master.kernel.org:/home/torvalds/BK/linux-2.6
torvalds@ppc970.osdl.org|ChangeSet|20050311175714|30898 torvalds
# This is a BitKeeper generated diff -Nru style patch.
#
# drivers/pci/hotplug/rpaphp_pci.c
#   2005/03/07 15:52:20-08:00 paulus@samba.org +11 -11
#   ppc64: error code cleanups rpa(php,dlpar)
# 
# drivers/pci/hotplug/rpaphp_vio.c
#   2005/03/07 15:52:20-08:00 paulus@samba.org +2 -2
#   ppc64: error code cleanups rpa(php,dlpar)
# 
# drivers/pci/hotplug/rpaphp_slot.c
#   2005/03/07 15:52:20-08:00 paulus@samba.org +2 -2
#   ppc64: error code cleanups rpa(php,dlpar)
# 
# ChangeSet
#   2005/03/11 09:09:44+01:00 perex@suse.cz 
#   Merge suse.cz:/home/perex/bk/linux-sound/linux-2.5
#   into suse.cz:/home/perex/bk/linux-sound/linux-sound
# 
# sound/pci/ymfpci/ymfpci_main.c
#   2005/03/11 09:09:31+01:00 perex@suse.cz +0 -0
#   Auto merged
# 
# sound/pci/via82xx.c
#   2005/03/11 09:09:31+01:00 perex@suse.cz +0 -0
#   Auto merged
# 
# sound/pci/trident/trident_main.c
#   2005/03/11 09:09:31+01:00 perex@suse.cz +0 -0
#   Auto merged
# 
# sound/pci/es1968.c
#   2005/03/11 09:09:31+01:00 perex@suse.cz +0 -0
#   Auto merged
# 
# sound/pci/cs46xx/cs46xx_lib.c
#   2005/03/11 09:09:31+01:00 perex@suse.cz +0 -0
#   Auto merged
# 
# sound/pci/es1938.c
#   2005/03/11 09:09:30+01:00 perex@suse.cz +0 -0
#   Auto merged
# 
# sound/pci/ens1370.c
#   2005/03/11 09:09:30+01:00 perex@suse.cz +0 -0
#   Auto merged
# 
# sound/pci/cs4281.c
#   2005/03/11 09:09:30+01:00 perex@suse.cz +0 -0
#   Auto merged
# 
# sound/pci/cmipci.c
#   2005/03/11 09:09:30+01:00 perex@suse.cz +0 -0
#   Auto merged
# 
# include/sound/ymfpci.h
#   2005/03/11 09:09:30+01:00 perex@suse.cz +0 -0
#   Auto merged
# 
# include/sound/trident.h
#   2005/03/11 09:09:30+01:00 perex@suse.cz +0 -0
#   Auto merged
# 
# ChangeSet
#   2005/03/11 00:03:05-08:00 torvalds@ppc970.osdl.org 
#   Cset exclude: bdschuym@pandora.be|ChangeSet|20050310042817|04711
# 
# net/core/netfilter.c
#   2005/03/11 00:02:48-08:00 torvalds@ppc970.osdl.org +0 -0
#   Exclude
# 
# net/bridge/br_netfilter.c
#   2005/03/11 00:02:48-08:00 torvalds@ppc970.osdl.org +0 -0
#   Exclude
# 
# include/linux/netfilter.h
#   2005/03/11 00:02:48-08:00 torvalds@ppc970.osdl.org +0 -0
#   Exclude
# 
# ChangeSet
#   2005/03/11 08:57:50+01:00 perex@suse.cz 
#   [ALSA] AC97 wm9713 support
#   
#   AC97 Codec
#   This patch series adds support for the WM9713/WM9714 family of AC97
#   codecs. This family is different from 'standard' AC97 codecs in that the
#   default codec power state is 'off'. i.e. performing a register reset
#   will power the device down.
#   
#   This patch also adds better support for larger single/double channel
#   enumerated mixer types.
#   
#   Signed-off-by: Liam Girdwood <liam.girdwood@wolfsonmicro.com>
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/ac97/ac97_patch.h
#   2005/03/10 07:35:48+01:00 perex@suse.cz +1 -0
#   [ALSA] AC97 wm9713 support
#   
#   D:2005/03/10 14:35:48
#   C:AC97 Codec
#   F:include/ac97_codec.h:1.63->1.64 
#   F:pci/ac97/ac97_codec.c:1.176->1.177 
#   F:pci/ac97/ac97_local.h:1.12->1.13 
#   F:pci/ac97/ac97_patch.c:1.75->1.76 
#   F:pci/ac97/ac97_patch.h:1.19->1.20 
#   L:This patch series adds support for the WM9713/WM9714 family of AC97
#   L:codecs. This family is different from 'standard' AC97 codecs in that the
#   L:default codec power state is 'off'. i.e. performing a register reset
#   L:will power the device down.
#   L:
#   L:This patch also adds better support for larger single/double channel
#   L:enumerated mixer types.
#   Signed-off-by: Liam Girdwood <liam.girdwood@wolfsonmicro.com>
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/ac97/ac97_patch.c
#   2005/03/10 07:35:48+01:00 perex@suse.cz +130 -0
#   [ALSA] AC97 wm9713 support
#   
#   D:2005/03/10 14:35:48
#   C:AC97 Codec
#   F:include/ac97_codec.h:1.63->1.64 
#   F:pci/ac97/ac97_codec.c:1.176->1.177 
#   F:pci/ac97/ac97_local.h:1.12->1.13 
#   F:pci/ac97/ac97_patch.c:1.75->1.76 
#   F:pci/ac97/ac97_patch.h:1.19->1.20 
#   L:This patch series adds support for the WM9713/WM9714 family of AC97
#   L:codecs. This family is different from 'standard' AC97 codecs in that the
#   L:default codec power state is 'off'. i.e. performing a register reset
#   L:will power the device down.
#   L:
#   L:This patch also adds better support for larger single/double channel
#   L:enumerated mixer types.
#   Signed-off-by: Liam Girdwood <liam.girdwood@wolfsonmicro.com>
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/ac97/ac97_local.h
#   2005/03/10 07:35:48+01:00 perex@suse.cz +16 -0
#   [ALSA] AC97 wm9713 support
#   
#   D:2005/03/10 14:35:48
#   C:AC97 Codec
#   F:include/ac97_codec.h:1.63->1.64 
#   F:pci/ac97/ac97_codec.c:1.176->1.177 
#   F:pci/ac97/ac97_local.h:1.12->1.13 
#   F:pci/ac97/ac97_patch.c:1.75->1.76 
#   F:pci/ac97/ac97_patch.h:1.19->1.20 
#   L:This patch series adds support for the WM9713/WM9714 family of AC97
#   L:codecs. This family is different from 'standard' AC97 codecs in that the
#   L:default codec power state is 'off'. i.e. performing a register reset
#   L:will power the device down.
#   L:
#   L:This patch also adds better support for larger single/double channel
#   L:enumerated mixer types.
#   Signed-off-by: Liam Girdwood <liam.girdwood@wolfsonmicro.com>
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/ac97/ac97_codec.c
#   2005/03/10 07:35:48+01:00 perex@suse.cz +129 -150
#   [ALSA] AC97 wm9713 support
#   
#   D:2005/03/10 14:35:48
#   C:AC97 Codec
#   F:include/ac97_codec.h:1.63->1.64 
#   F:pci/ac97/ac97_codec.c:1.176->1.177 
#   F:pci/ac97/ac97_local.h:1.12->1.13 
#   F:pci/ac97/ac97_patch.c:1.75->1.76 
#   F:pci/ac97/ac97_patch.h:1.19->1.20 
#   L:This patch series adds support for the WM9713/WM9714 family of AC97
#   L:codecs. This family is different from 'standard' AC97 codecs in that the
#   L:default codec power state is 'off'. i.e. performing a register reset
#   L:will power the device down.
#   L:
#   L:This patch also adds better support for larger single/double channel
#   L:enumerated mixer types.
#   Signed-off-by: Liam Girdwood <liam.girdwood@wolfsonmicro.com>
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# include/sound/ac97_codec.h
#   2005/03/10 07:35:48+01:00 perex@suse.cz +14 -0
#   [ALSA] AC97 wm9713 support
#   
#   D:2005/03/10 14:35:48
#   C:AC97 Codec
#   F:include/ac97_codec.h:1.63->1.64 
#   F:pci/ac97/ac97_codec.c:1.176->1.177 
#   F:pci/ac97/ac97_local.h:1.12->1.13 
#   F:pci/ac97/ac97_patch.c:1.75->1.76 
#   F:pci/ac97/ac97_patch.h:1.19->1.20 
#   L:This patch series adds support for the WM9713/WM9714 family of AC97
#   L:codecs. This family is different from 'standard' AC97 codecs in that the
#   L:default codec power state is 'off'. i.e. performing a register reset
#   L:will power the device down.
#   L:
#   L:This patch also adds better support for larger single/double channel
#   L:enumerated mixer types.
#   Signed-off-by: Liam Girdwood <liam.girdwood@wolfsonmicro.com>
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2005/03/10 20:20:45-08:00 mpm@selenic.com 
#   [PATCH] ia64 extable sorting fix
#   
#   Fix a goofup from the recent sort consolidation patches.
#   
#   - Subtractions in comparison functions could overflow the return type for
#     64-bit pointers.  Make it right again.
#   
#   - Add missing size arg to ia64 extable swap function.
#   
#   Signed-off-by: Matt Mackall <mpm@selenic.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# lib/extable.c
#   2005/03/10 08:19:53-08:00 mpm@selenic.com +7 -1
#   ia64 extable sorting fix
# 
# arch/ia64/mm/extable.c
#   2005/03/10 08:19:53-08:00 mpm@selenic.com +7 -2
#   ia64 extable sorting fix
# 
# ChangeSet
#   2005/03/10 20:20:30-08:00 tim.bird@am.sony.com 
#   [PATCH] printk-times bugfix for loglevel-only printks
#   
#   This patch fixes a bug with the recently added printk-times feature.
#   
#   In the case where a printk consists of only the log level (followed
#   subsequently by printks with more text for the same line), the printk-times
#   code doesn't correctly recognize the end of the string, and starts emitting
#   chars at the 0 byte at the end of the string.
#   
#   The patch below fixes this problem.  It also adjusts the handling of
#   printed_len in the routine, which was affected by the printk-times feature.
#   
#   Signed-off-by: Tim Bird <tim.bird@am.sony.com>
#   Acked-by: Tony Luck <tony.luck@intel.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# kernel/printk.c
#   2005/03/10 19:59:48-08:00 tim.bird@am.sony.com +7 -2
#   printk-times bugfix for loglevel-only printks
# 
# ChangeSet
#   2005/03/10 20:13:05-08:00 benh@kernel.crashing.org 
#   [SUNGEM]: Rework PM handling and fix MAC reset on stuck receiver.
#   
#   This patch updates the sungem driver. I reworked all of the PM stuff, making it
#   less prone to races, probably simpler to read as well, and I no longer shut the
#   PHY down when the interface is down so that things like laptop-net no longer
#   die (the gain in power consumption was minimal, not worth the pain). I also
#   implemented basic WOL support.
#   
#   There is still something I'm not totally happy with in the locking
#   (explained in the comment at the beginning), basically too much locking and a
#   couple of places with delays in locks. I will try to improve these later on.
#   
#   It also adds a fix for a MAC reset issue when the receiver gets stuck.
#   
#   Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# drivers/net/sungem_phy.h
#   2005/03/10 20:12:52-08:00 benh@kernel.crashing.org +2 -1
#   [SUNGEM]: Rework PM handling and fix MAC reset on stuck receiver.
#   
#   This patch updates the sungem driver. I reworked all of the PM stuff, making it
#   less prone to races, probably simpler to read as well, and I no longer shut the
#   PHY down when the interface is down so that things like laptop-net no longer
#   die (the gain in power consumption was minimal, not worth the pain). I also
#   implemented basic WOL support.
#   
#   There is still something I'm not totally happy with in the locking
#   (explained in the comment at the beginning), basically too much locking and a
#   couple of places with delays in locks. I will try to improve these later on.
#   
#   It also adds a fix for a MAC reset issue when the receiver gets stuck.
#   
#   Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# drivers/net/sungem_phy.c
#   2005/03/10 20:12:52-08:00 benh@kernel.crashing.org +24 -19
#   [SUNGEM]: Rework PM handling and fix MAC reset on stuck receiver.
#   
#   This patch updates the sungem driver. I reworked all of the PM stuff, making it
#   less prone to races, probably simpler to read as well, and I no longer shut the
#   PHY down when the interface is down so that things like laptop-net no longer
#   die (the gain in power consumption was minimal, not worth the pain). I also
#   implemented basic WOL support.
#   
#   There is still something I'm not totally happy with in the locking
#   (explained in the comment at the beginning), basically too much locking and a
#   couple of places with delays in locks. I will try to improve these later on.
#   
#   It also adds a fix for a MAC reset issue when the receiver gets stuck.
#   
#   Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# drivers/net/sungem.h
#   2005/03/10 20:12:52-08:00 benh@kernel.crashing.org +50 -32
#   [SUNGEM]: Rework PM handling and fix MAC reset on stuck receiver.
#   
#   This patch updates the sungem driver. I reworked all of the PM stuff, making it
#   less prone to races, probably simpler to read as well, and I no longer shut the
#   PHY down when the interface is down so that things like laptop-net no longer
#   die (the gain in power consumption was minimal, not worth the pain). I also
#   implemented basic WOL support.
#   
#   There is still something I'm not totally happy with in the locking
#   (explained in the comment at the beginning), basically too much locking and a
#   couple of places with delays in locks. I will try to improve these later on.
#   
#   It also adds a fix for a MAC reset issue when the receiver gets stuck.
#   
#   Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# drivers/net/sungem.c
#   2005/03/10 20:12:52-08:00 benh@kernel.crashing.org +572 -442
#   [SUNGEM]: Rework PM handling and fix MAC reset on stuck receiver.
#   
#   This patch updates the sungem driver. I reworked all of the PM stuff, making it
#   less prone to races, probably simpler to read as well, and I no longer shut the
#   PHY down when the interface is down so that things like laptop-net no longer
#   die (the gain in power consumption was minimal, not worth the pain). I also
#   implemented basic WOL support.
#   
#   There is still something I'm not totally happy with in the locking
#   (explained in the comment at the beginning), basically too much locking and a
#   couple of places with delays in locks. I will try to improve these later on.
#   
#   It also adds a fix for a MAC reset issue when the receiver gets stuck.
#   
#   Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# ChangeSet
#   2005/03/10 20:02:08-08:00 chas@cmf.nrl.navy.mil 
#   [ATM]: lanai: quiet sparse warnings
#   
#   Signed-off-by: Randy Dunlap <rddunlap@osdl.org>
#   Signed-off-by: Chas Williams <chas@cmf.nrl.navy.mil>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# drivers/atm/lanai.c
#   2005/03/10 20:01:56-08:00 chas@cmf.nrl.navy.mil +9 -9
#   [ATM]: lanai: quiet sparse warnings
#   
#   Signed-off-by: Randy Dunlap <rddunlap@osdl.org>
#   Signed-off-by: Chas Williams <chas@cmf.nrl.navy.mil>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# ChangeSet
#   2005/03/10 20:01:23-08:00 chas@cmf.nrl.navy.mil 
#   [ATM]: iphase: Use after free, found by Coverity tool
#   
#   Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
#   Signed-off-by: Chas Williams <chas@cmf.nrl.navy.mil>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# drivers/atm/iphase.c
#   2005/03/10 20:01:11-08:00 chas@cmf.nrl.navy.mil +1 -1
#   [ATM]: iphase: Use after free, found by Coverity tool
#   
#   Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
#   Signed-off-by: Chas Williams <chas@cmf.nrl.navy.mil>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# ChangeSet
#   2005/03/10 19:59:56-08:00 chas@cmf.nrl.navy.mil 
#   [ATM]: fore200e: Replace MSECS() with msecs_to_jiffies()
#   
#   Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
#   Signed-off-by: Chas Williams <chas@cmf.nrl.navy.mil>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# drivers/atm/fore200e.c
#   2005/03/10 19:59:44-08:00 chas@cmf.nrl.navy.mil +4 -8
#   [ATM]: fore200e: Replace MSECS() with msecs_to_jiffies()
#   
#   Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
#   Signed-off-by: Chas Williams <chas@cmf.nrl.navy.mil>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# ChangeSet
#   2005/03/10 19:53:46-08:00 chas@cmf.nrl.navy.mil 
#   [ATM]: Convert from pci_module_init to pci_register_driver
#   
#   Signed-off-by: Christophe Lucas <c.lucas@ifrance.com>
#   Signed-off-by: Domen Puncer <domen@coderock.org>
#   Signed-off-by: Chas Williams <chas@cmf.nrl.navy.mil>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# drivers/atm/zatm.c
#   2005/03/10 19:53:33-08:00 chas@cmf.nrl.navy.mil +1 -1
#   [ATM]: Convert from pci_module_init to pci_register_driver
#   
#   Signed-off-by: Christophe Lucas <c.lucas@ifrance.com>
#   Signed-off-by: Domen Puncer <domen@coderock.org>
#   Signed-off-by: Chas Williams <chas@cmf.nrl.navy.mil>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# drivers/atm/nicstar.c
#   2005/03/10 19:53:33-08:00 chas@cmf.nrl.navy.mil +1 -1
#   [ATM]: Convert from pci_module_init to pci_register_driver
#   
#   Signed-off-by: Christophe Lucas <c.lucas@ifrance.com>
#   Signed-off-by: Domen Puncer <domen@coderock.org>
#   Signed-off-by: Chas Williams <chas@cmf.nrl.navy.mil>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# drivers/atm/lanai.c
#   2005/03/10 19:53:33-08:00 chas@cmf.nrl.navy.mil +1 -1
#   [ATM]: Convert from pci_module_init to pci_register_driver
#   
#   Signed-off-by: Christophe Lucas <c.lucas@ifrance.com>
#   Signed-off-by: Domen Puncer <domen@coderock.org>
#   Signed-off-by: Chas Williams <chas@cmf.nrl.navy.mil>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# drivers/atm/iphase.c
#   2005/03/10 19:53:33-08:00 chas@cmf.nrl.navy.mil +1 -1
#   [ATM]: Convert from pci_module_init to pci_register_driver
#   
#   Signed-off-by: Christophe Lucas <c.lucas@ifrance.com>
#   Signed-off-by: Domen Puncer <domen@coderock.org>
#   Signed-off-by: Chas Williams <chas@cmf.nrl.navy.mil>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# drivers/atm/horizon.c
#   2005/03/10 19:53:33-08:00 chas@cmf.nrl.navy.mil +1 -1
#   [ATM]: Convert from pci_module_init to pci_register_driver
#   
#   Signed-off-by: Christophe Lucas <c.lucas@ifrance.com>
#   Signed-off-by: Domen Puncer <domen@coderock.org>
#   Signed-off-by: Chas Williams <chas@cmf.nrl.navy.mil>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# drivers/atm/he.c
#   2005/03/10 19:53:33-08:00 chas@cmf.nrl.navy.mil +1 -1
#   [ATM]: Convert from pci_module_init to pci_register_driver
#   
#   Signed-off-by: Christophe Lucas <c.lucas@ifrance.com>
#   Signed-off-by: Domen Puncer <domen@coderock.org>
#   Signed-off-by: Chas Williams <chas@cmf.nrl.navy.mil>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# drivers/atm/firestream.c
#   2005/03/10 19:53:32-08:00 chas@cmf.nrl.navy.mil +1 -1
#   [ATM]: Convert from pci_module_init to pci_register_driver
#   
#   Signed-off-by: Christophe Lucas <c.lucas@ifrance.com>
#   Signed-off-by: Domen Puncer <domen@coderock.org>
#   Signed-off-by: Chas Williams <chas@cmf.nrl.navy.mil>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# drivers/atm/ambassador.c
#   2005/03/10 19:53:32-08:00 chas@cmf.nrl.navy.mil +1 -1
#   [ATM]: Convert from pci_module_init to pci_register_driver
#   
#   Signed-off-by: Christophe Lucas <c.lucas@ifrance.com>
#   Signed-off-by: Domen Puncer <domen@coderock.org>
#   Signed-off-by: Chas Williams <chas@cmf.nrl.navy.mil>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# ChangeSet
#   2005/03/10 19:52:36-08:00 chas@cmf.nrl.navy.mil 
#   [ATM]: lanai: use the DMA_{64,32}BIT_MASK constants from dma-mapping.h
#   
#   Signed-off-by: Tobias Klauser <tklauser@nuerscht.ch>
#   Signed-off-by: Domen Puncer <domen@coderock.org>
#   Signed-off-by: Chas Williams <chas@cmf.nrl.navy.mil>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# drivers/atm/lanai.c
#   2005/03/10 19:52:23-08:00 chas@cmf.nrl.navy.mil +1 -1
#   [ATM]: lanai: use the DMA_{64,32}BIT_MASK constants from dma-mapping.h
#   
#   Signed-off-by: Tobias Klauser <tklauser@nuerscht.ch>
#   Signed-off-by: Domen Puncer <domen@coderock.org>
#   Signed-off-by: Chas Williams <chas@cmf.nrl.navy.mil>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# ChangeSet
#   2005/03/10 19:47:59-08:00 ralf@linux-mips.org 
#   [NETROM]: Sparse fixes.
#   
#   Moving nr_init_timers prototype to where all the other prototypes
#   already are.
#   
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/netrom/af_netrom.c
#   2005/03/10 19:47:44-08:00 ralf@linux-mips.org +0 -1
#   [NETROM]: Sparse fixes.
#   
#   Moving nr_init_timers prototype to where all the other prototypes
#   already are.
#   
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# include/net/netrom.h
#   2005/03/10 19:47:44-08:00 ralf@linux-mips.org +1 -0
#   [NETROM]: Sparse fixes.
#   
#   Moving nr_init_timers prototype to where all the other prototypes
#   already are.
#   
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# ChangeSet
#   2005/03/10 19:47:08-08:00 ralf@linux-mips.org 
#   [ROSE]: Fix minor security hole
#   
#   ROSE wasn't verifying the ndigis argument of a new route resulting in a
#   minor security hole.
#   
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/rose/rose_route.c
#   2005/03/10 19:46:52-08:00 ralf@linux-mips.org +2 -1
#   [ROSE]: Fix minor security hole
#   
#   ROSE wasn't verifying the ndigis argument of a new route resulting in a
#   minor security hole.
#   
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# ChangeSet
#   2005/03/10 19:46:23-08:00 ralf@linux-mips.org 
#   [NETROM]: Fix deadlock due to double locking.
#   
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/netrom/nr_in.c
#   2005/03/10 19:46:09-08:00 ralf@linux-mips.org +1 -10
#   [NETROM]: Fix deadlock due to double locking.
#   
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# ChangeSet
#   2005/03/10 19:40:52-08:00 chas@cmf.nrl.navy.mil 
#   [ATM]: fore200e: rewrite to eliminate pci_find_device() but preserve sbus support
#   
#   this patch correctly removes the pci_find_device() used by the fore200e
#   driver.  the __init/__exit remains a bit clunky since we need to preserve
#   sbus support.
#   
#   Signed-off-by: Chas Williams <chas@cmf.nrl.navy.mil>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# drivers/atm/fore200e.h
#   2005/03/10 19:40:37-08:00 chas@cmf.nrl.navy.mil +1 -1
#   [ATM]: fore200e: rewrite to eliminate pci_find_device() but preserve sbus support
#   
#   this patch correctly removes the pci_find_device() used by the fore200e
#   driver.  the __init/__exit remains a bit clunky since we need to preserve
#   sbus support.
#   
#   Signed-off-by: Chas Williams <chas@cmf.nrl.navy.mil>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# drivers/atm/fore200e.c
#   2005/03/10 19:40:37-08:00 chas@cmf.nrl.navy.mil +107 -47
#   [ATM]: fore200e: rewrite to eliminate pci_find_device() but preserve sbus support
#   
#   this patch correctly removes the pci_find_device() used by the fore200e
#   driver.  the __init/__exit remains a bit clunky since we need to preserve
#   sbus support.
#   
#   Signed-off-by: Chas Williams <chas@cmf.nrl.navy.mil>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# ChangeSet
#   2005/03/10 19:38:38-08:00 davem@sunset.davemloft.net 
#   [SIS900]: Driver needs to include asm/irq.h
#   
#   Otherwise declarations for disable_irq()/enable_irq() will
#   not be obtained on platforms not doing CONFIG_GENERIC_HARDIRQS.
#   
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# drivers/net/sis900.c
#   2005/03/10 19:38:10-08:00 davem@sunset.davemloft.net +1 -0
#   [SIS900]: Driver needs to include asm/irq.h
# 
# ChangeSet
#   2005/03/10 19:20:20-08:00 kaber@trash.net 
#   [TUN]: Fix check for underflow
#   
#   This check is wrong, gcc optimizes it away:
#   
#                   if ((len -= sizeof(pi)) > len)
#   			return -EINVAL;
#   
#   This could be responsible for the BUG. If len is 2 or 3 and TUN_NO_PI
#   isn't set it underflows. alloc_skb() allocates len + 2, which is 0 or
#   1 byte. skb_reserve tries to reserve 2 bytes and things explode in
#   skb_put.
#   
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# drivers/net/tun.c
#   2005/03/10 19:20:06-08:00 kaber@trash.net +1 -1
#   [TUN]: Fix check for underflow
#   
#   This check is wrong, gcc optimizes it away:
#   
#                   if ((len -= sizeof(pi)) > len)
#   			return -EINVAL;
#   
#   This could be responsible for the BUG. If len is 2 or 3 and TUN_NO_PI
#   isn't set it underflows. alloc_skb() allocates len + 2, which is 0 or
#   1 byte. skb_reserve tries to reserve 2 bytes and things explode in
#   skb_put.
#   
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# ChangeSet
#   2005/03/10 19:10:10-08:00 paulus@samba.org 
#   [PATCH] AGP support for powermac G5
#   
#   This patch adds AGP support for the U3 northbridge used in Apple G5
#   machines to drivers/char/agp/uninorth-agp.c.  This patch is based on
#   earlier work by Jerome Glisse.  With this patch, the driver works in
#   both ppc32 and ppc64 kernels.
#   
#   Signed-off-by: Paul Mackerras <paulus@samba.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/asm-ppc64/agp.h
#   2005/03/10 16:54:54-08:00 paulus@samba.org +13 -0
#   AGP support for powermac G5
# 
# include/linux/pci_ids.h
#   2005/03/10 16:54:54-08:00 paulus@samba.org +3 -0
#   AGP support for powermac G5
# 
# include/asm-ppc64/agp.h
#   2005/03/10 16:54:54-08:00 paulus@samba.org +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/include/asm-ppc64/agp.h
# 
# include/asm-ppc/uninorth.h
#   2005/03/10 16:54:54-08:00 paulus@samba.org +6 -1
#   AGP support for powermac G5
# 
# drivers/char/agp/uninorth-agp.c
#   2005/03/10 16:54:54-08:00 paulus@samba.org +233 -42
#   AGP support for powermac G5
# 
# drivers/char/agp/Kconfig
#   2005/03/10 18:53:47-08:00 paulus@samba.org +3 -3
#   AGP support for powermac G5
# 
# ChangeSet
#   2005/03/10 19:06:23-08:00 davem@sunset.davemloft.net 
#   [SK98LIN]: Driver needs to include asm/irq.h
#   
#   Otherwise declarations for disable_irq()/enable_irq() will
#   not be obtained on platforms not doing CONFIG_GENERIC_HARDIRQS.
#   
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# drivers/net/sk98lin/h/skdrv1st.h
#   2005/03/10 19:05:22-08:00 davem@sunset.davemloft.net +1 -0
#   [SK98LIN]: Driver needs to include asm/irq.h
# 
# ChangeSet
#   2005/03/10 18:58:21-08:00 Robert.Olsson@data.slu.se 
#   [PKTGEN]: Use __in_dev_put().
#   
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/core/pktgen.c
#   2005/03/10 18:58:06-08:00 Robert.Olsson@data.slu.se +2 -2
#   [PKTGEN]: Use __in_dev_put().
#   
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# ChangeSet
#   2005/03/10 18:56:25-08:00 kaber@trash.net 
#   [IPV4]: Speed up sequential reading of /proc/net/route
#   
#   Cacheing the current position reduces complexity from O(n^2)
#   to O(n).
#   
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/ipv4/fib_hash.c
#   2005/03/10 18:56:12-08:00 kaber@trash.net +22 -1
#   [IPV4]: Speed up sequential reading of /proc/net/route
#   
#   Cacheing the current position reduces complexity from O(n^2)
#   to O(n).
#   
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# ChangeSet
#   2005/03/10 18:52:51-08:00 shemminger@osdl.org 
#   [NET]: Optimize is_valid_ether_addr()
#   
#   Low level optimization of the comparison with zero address.
#   On most cpu's faster to use unrolled or rather than a loop
#   and memcmp. This is in the fastpath of bridge forwarding.
#   
#   Signed-off-by: Stephen Hemminger <shemminger@osdl.org>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# include/linux/etherdevice.h
#   2005/03/10 18:52:36-08:00 shemminger@osdl.org +11 -4
#   [NET]: Optimize is_valid_ether_addr()
#   
#   Low level optimization of the comparison with zero address.
#   On most cpu's faster to use unrolled or rather than a loop
#   and memcmp. This is in the fastpath of bridge forwarding.
#   
#   Signed-off-by: Stephen Hemminger <shemminger@osdl.org>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# ChangeSet
#   2005/03/10 18:51:52-08:00 shemminger@osdl.org 
#   [BRIDGE]: Forwarding table lockless update
#   
#   Optimize bridge forwarding table for the fastpath of updating
#   an existing entry. Use RCU to find the entry and change it's time.
#   Fallback to normal locking for insert. This gives about a 1/3
#   improvement in packets forwarding per second on SMP.
#   
#   Signed-off-by: Stephen Hemminger <shemminger@osdl.org>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/bridge/br_private.h
#   2005/03/10 18:51:37-08:00 shemminger@osdl.org +4 -2
#   [BRIDGE]: Forwarding table lockless update
#   
#   Optimize bridge forwarding table for the fastpath of updating
#   an existing entry. Use RCU to find the entry and change it's time.
#   Fallback to normal locking for insert. This gives about a 1/3
#   improvement in packets forwarding per second on SMP.
#   
#   Signed-off-by: Stephen Hemminger <shemminger@osdl.org>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/bridge/br_input.c
#   2005/03/10 18:51:37-08:00 shemminger@osdl.org +2 -2
#   [BRIDGE]: Forwarding table lockless update
#   
#   Optimize bridge forwarding table for the fastpath of updating
#   an existing entry. Use RCU to find the entry and change it's time.
#   Fallback to normal locking for insert. This gives about a 1/3
#   improvement in packets forwarding per second on SMP.
#   
#   Signed-off-by: Stephen Hemminger <shemminger@osdl.org>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/bridge/br_if.c
#   2005/03/10 18:51:37-08:00 shemminger@osdl.org +1 -1
#   [BRIDGE]: Forwarding table lockless update
#   
#   Optimize bridge forwarding table for the fastpath of updating
#   an existing entry. Use RCU to find the entry and change it's time.
#   Fallback to normal locking for insert. This gives about a 1/3
#   improvement in packets forwarding per second on SMP.
#   
#   Signed-off-by: Stephen Hemminger <shemminger@osdl.org>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/bridge/br_fdb.c
#   2005/03/10 18:51:37-08:00 shemminger@osdl.org +85 -49
#   [BRIDGE]: Forwarding table lockless update
#   
#   Optimize bridge forwarding table for the fastpath of updating
#   an existing entry. Use RCU to find the entry and change it's time.
#   Fallback to normal locking for insert. This gives about a 1/3
#   improvement in packets forwarding per second on SMP.
#   
#   Signed-off-by: Stephen Hemminger <shemminger@osdl.org>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# ChangeSet
#   2005/03/10 18:51:00-08:00 shemminger@osdl.org 
#   [BRIDGE]: Get rid of threaded link for forwarding timeout
#   
#   For 2.6, I changed the bridge forwarding table timeout code to keep
#   a threaded list of in order entries. Well, it turns out that this is
#   a performance hit because we end up constantly moving entries around
#   in the list.  Later patch changes this to be in place update with RCU.
#   
#   This version just uses a 100ms garbage collection timer.
#   
#   Signed-off-by: Stephen Hemminger <shemminger@osdl.org>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/bridge/br_stp_if.c
#   2005/03/10 18:50:45-08:00 shemminger@osdl.org +3 -0
#   [BRIDGE]: Get rid of threaded link for forwarding timeout
#   
#   For 2.6, I changed the bridge forwarding table timeout code to keep
#   a threaded list of in order entries. Well, it turns out that this is
#   a performance hit because we end up constantly moving entries around
#   in the list.  Later patch changes this to be in place update with RCU.
#   
#   This version just uses a 100ms garbage collection timer.
#   
#   Signed-off-by: Stephen Hemminger <shemminger@osdl.org>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/bridge/br_private.h
#   2005/03/10 18:50:45-08:00 shemminger@osdl.org +2 -4
#   [BRIDGE]: Get rid of threaded link for forwarding timeout
#   
#   For 2.6, I changed the bridge forwarding table timeout code to keep
#   a threaded list of in order entries. Well, it turns out that this is
#   a performance hit because we end up constantly moving entries around
#   in the list.  Later patch changes this to be in place update with RCU.
#   
#   This version just uses a 100ms garbage collection timer.
#   
#   Signed-off-by: Stephen Hemminger <shemminger@osdl.org>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/bridge/br_fdb.c
#   2005/03/10 18:50:45-08:00 shemminger@osdl.org +12 -31
#   [BRIDGE]: Get rid of threaded link for forwarding timeout
#   
#   For 2.6, I changed the bridge forwarding table timeout code to keep
#   a threaded list of in order entries. Well, it turns out that this is
#   a performance hit because we end up constantly moving entries around
#   in the list.  Later patch changes this to be in place update with RCU.
#   
#   This version just uses a 100ms garbage collection timer.
#   
#   Signed-off-by: Stephen Hemminger <shemminger@osdl.org>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# ChangeSet
#   2005/03/10 18:50:22-08:00 shemminger@osdl.org 
#   [BRIDGE]: Get rid of unneeded include
#   
#   Get rid of unneeded include.
#   
#   Signed-off-by: Stephen Hemminger <shemminger@osdl.org>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/bridge/br.c
#   2005/03/10 18:50:08-08:00 shemminger@osdl.org +0 -1
#   [BRIDGE]: Get rid of unneeded include
#   
#   Get rid of unneeded include.
#   
#   Signed-off-by: Stephen Hemminger <shemminger@osdl.org>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# ChangeSet
#   2005/03/10 18:49:36-08:00 shemminger@osdl.org 
#   [BRIDGE]: Use Jenkins hash
#   
#   Replace the existing mac hash in the bridge code with the nice
#   inline jenkins hash. This should provide better distribution across
#   hash buckets and compiles to code that is similar in complexity.
#   
#   Signed-off-by: Stephen Hemminger <shemminger@osdl.org>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/bridge/br_fdb.c
#   2005/03/10 18:49:22-08:00 shemminger@osdl.org +2 -12
#   [BRIDGE]: Use Jenkins hash
#   
#   Replace the existing mac hash in the bridge code with the nice
#   inline jenkins hash. This should provide better distribution across
#   hash buckets and compiles to code that is similar in complexity.
#   
#   Signed-off-by: Stephen Hemminger <shemminger@osdl.org>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# ChangeSet
#   2005/03/10 18:44:11-08:00 yoshfuji@linux-ipv6.org 
#   [IPV6]: Build modular by default.
#   
#   Signed-off-by: Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/Kconfig
#   2005/03/10 18:43:56-08:00 yoshfuji@linux-ipv6.org +1 -0
#   [IPV6]: Build modular by default.
#   
#   Signed-off-by: Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# ChangeSet
#   2005/03/10 18:42:50-08:00 shemminger@osdl.org 
#   [PKT_SCHED]: Move tc_u32_mark into pkt_cls.h
#   
#   The tc_u32_mark structure is used as part of the netlink message
#   from the user API to the kernel, so it needs to be moved to
#   include/linux/pkt_cls.h and have types changed from u32 to __u32.
#   
#   Also, the definition of u32 performance counters doesn't need to depend
#   on the config option.  The definition can exist even if the code isn't
#   enabled.
#   
#   Signed-off-by: Stephen Hemminger <shemminger@osdl.org>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/sched/cls_u32.c
#   2005/03/10 18:42:37-08:00 shemminger@osdl.org +0 -8
#   [PKT_SCHED]: Move tc_u32_mark into pkt_cls.h
#   
#   The tc_u32_mark structure is used as part of the netlink message
#   from the user API to the kernel, so it needs to be moved to
#   include/linux/pkt_cls.h and have types changed from u32 to __u32.
#   
#   Also, the definition of u32 performance counters doesn't need to depend
#   on the config option.  The definition can exist even if the code isn't
#   enabled.
#   
#   Signed-off-by: Stephen Hemminger <shemminger@osdl.org>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# include/linux/pkt_cls.h
#   2005/03/10 18:42:37-08:00 shemminger@osdl.org +8 -2
#   [PKT_SCHED]: Move tc_u32_mark into pkt_cls.h
#   
#   The tc_u32_mark structure is used as part of the netlink message
#   from the user API to the kernel, so it needs to be moved to
#   include/linux/pkt_cls.h and have types changed from u32 to __u32.
#   
#   Also, the definition of u32 performance counters doesn't need to depend
#   on the config option.  The definition can exist even if the code isn't
#   enabled.
#   
#   Signed-off-by: Stephen Hemminger <shemminger@osdl.org>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# ChangeSet
#   2005/03/10 18:41:35-08:00 torvalds@evo.osdl.org 
#   Fix double pci_dev_put()
#   
#   Paul Mackerras points out that the pci_get_class() call will
#   properly put away the old PCI device. Blush.
# 
# ChangeSet
#   2005/03/10 18:41:27-08:00 shemminger@osdl.org 
#   [NET]: Rearrange netdevice structure to save space.
#   
#   Trivial reordering of netdevice structure to save four bytes.
#   
#   Signed-off-by: Stephen Hemminger <shemminger@osdl.org>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# drivers/char/agp/generic.c
#   2005/03/10 18:41:24-08:00 torvalds@evo.osdl.org +0 -1
#   Fix double pci_dev_put()
#   
#   Paul Mackerras points out that the pci_get_class() call will
#   properly put away the old PCI device. Blush.
# 
# include/linux/netdevice.h
#   2005/03/10 18:41:13-08:00 shemminger@osdl.org +1 -5
#   [NET]: Rearrange netdevice structure to save space.
#   
#   Trivial reordering of netdevice structure to save four bytes.
#   
#   Signed-off-by: Stephen Hemminger <shemminger@osdl.org>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# ChangeSet
#   2005/03/10 18:40:08-08:00 kaber@trash.net 
#   [XFRM]: xfrm_find_acq_byseq should only return XFRM_STATE_ACQ states.
#   
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
# 
# net/xfrm/xfrm_state.c
#   2005/03/10 18:39:54-08:00 kaber@trash.net +1 -1
#   [XFRM]: xfrm_find_acq_byseq should only return XFRM_STATE_ACQ states.
#   
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
# 
# ChangeSet
#   2005/03/10 18:38:36-08:00 nhorman@redhat.com 
#   [SCTP]: Add receive buffer accounting.
#   
#   Signed-off-by: Neil Horman <nhorman@redhat.com>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/sctp/input.c
#   2005/03/10 18:38:23-08:00 nhorman@redhat.com +22 -0
#   [SCTP]: Add receive buffer accounting.
#   
#   Signed-off-by: Neil Horman <nhorman@redhat.com>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# ChangeSet
#   2005/03/10 18:23:13-08:00 domen@coderock.org 
#   [TIGON3]: Replace pci_find_device with pci_dev_present.
#   
#   Signed-off-by: Scott Feldman <sfeldma@pobox.com>
#   Signed-off-by: Maximilian Attems <janitor@sternwelten.at>
#   Signed-off-by: Domen Puncer <domen@coderock.org>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# drivers/net/tg3.c
#   2005/03/10 18:22:43-08:00 domen@coderock.org +14 -10
#   [TIGON3]: Replace pci_find_device with pci_dev_present.
# 
# ChangeSet
#   2005/03/10 18:20:44-08:00 kaber@trash.net 
#   [IPV4]: Fix crash while reading /proc/net/route caused by stale pointers
#   
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/ipv4/fib_hash.c
#   2005/03/10 18:20:30-08:00 kaber@trash.net +11 -1
#   [IPV4]: Fix crash while reading /proc/net/route caused by stale pointers
#   
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# ChangeSet
#   2005/03/10 18:19:49-08:00 jgarzik@pobox.com 
#   [NET]: Kill netdev->accept_fastpath hook.
#   
#   Never called AFAICS, and only assigned -- to a no-op stub -- in
#   one driver.
#   
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/bridge/br_device.c
#   2005/03/10 18:19:33-08:00 jgarzik@pobox.com +0 -6
#   [NET]: Kill netdev->accept_fastpath hook.
#   
#   Never called AFAICS, and only assigned -- to a no-op stub -- in
#   one driver.
#   
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# include/linux/netdevice.h
#   2005/03/10 18:19:33-08:00 jgarzik@pobox.com +0 -1
#   [NET]: Kill netdev->accept_fastpath hook.
#   
#   Never called AFAICS, and only assigned -- to a no-op stub -- in
#   one driver.
#   
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# ChangeSet
#   2005/03/10 18:17:45-08:00 herbert@gondor.apana.org.au 
#   [NET]: Move dst_release out of dst->ops->check
#   
#   As promised here is the patch that moves dst_release out of
#   dst->ops->check.  It bloats sk_dst_check/__sk_dst_check slightly
#   but they're only used in a handful of places so it isn't too bad.
#   I actually counted, it's about a few hundred bytes.
#   
#   Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/xfrm/xfrm_policy.c
#   2005/03/10 18:17:32-08:00 herbert@gondor.apana.org.au +0 -1
#   [NET]: Move dst_release out of dst->ops->check
#   
#   As promised here is the patch that moves dst_release out of
#   dst->ops->check.  It bloats sk_dst_check/__sk_dst_check slightly
#   but they're only used in a handful of places so it isn't too bad.
#   I actually counted, it's about a few hundred bytes.
#   
#   Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/ipv6/route.c
#   2005/03/10 18:17:32-08:00 herbert@gondor.apana.org.au +0 -1
#   [NET]: Move dst_release out of dst->ops->check
#   
#   As promised here is the patch that moves dst_release out of
#   dst->ops->check.  It bloats sk_dst_check/__sk_dst_check slightly
#   but they're only used in a handful of places so it isn't too bad.
#   I actually counted, it's about a few hundred bytes.
#   
#   Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/ipv6/ip6_tunnel.c
#   2005/03/10 18:17:32-08:00 herbert@gondor.apana.org.au +1 -0
#   [NET]: Move dst_release out of dst->ops->check
#   
#   As promised here is the patch that moves dst_release out of
#   dst->ops->check.  It bloats sk_dst_check/__sk_dst_check slightly
#   but they're only used in a handful of places so it isn't too bad.
#   I actually counted, it's about a few hundred bytes.
#   
#   Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/ipv4/route.c
#   2005/03/10 18:17:32-08:00 herbert@gondor.apana.org.au +0 -1
#   [NET]: Move dst_release out of dst->ops->check
#   
#   As promised here is the patch that moves dst_release out of
#   dst->ops->check.  It bloats sk_dst_check/__sk_dst_check slightly
#   but they're only used in a handful of places so it isn't too bad.
#   I actually counted, it's about a few hundred bytes.
#   
#   Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/ipv4/ipvs/ip_vs_xmit.c
#   2005/03/10 18:17:32-08:00 herbert@gondor.apana.org.au +1 -0
#   [NET]: Move dst_release out of dst->ops->check
#   
#   As promised here is the patch that moves dst_release out of
#   dst->ops->check.  It bloats sk_dst_check/__sk_dst_check slightly
#   but they're only used in a handful of places so it isn't too bad.
#   I actually counted, it's about a few hundred bytes.
#   
#   Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/decnet/dn_route.c
#   2005/03/10 18:17:32-08:00 herbert@gondor.apana.org.au +0 -1
#   [NET]: Move dst_release out of dst->ops->check
#   
#   As promised here is the patch that moves dst_release out of
#   dst->ops->check.  It bloats sk_dst_check/__sk_dst_check slightly
#   but they're only used in a handful of places so it isn't too bad.
#   I actually counted, it's about a few hundred bytes.
#   
#   Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# include/net/sock.h
#   2005/03/10 18:17:32-08:00 herbert@gondor.apana.org.au +2 -0
#   [NET]: Move dst_release out of dst->ops->check
#   
#   As promised here is the patch that moves dst_release out of
#   dst->ops->check.  It bloats sk_dst_check/__sk_dst_check slightly
#   but they're only used in a handful of places so it isn't too bad.
#   I actually counted, it's about a few hundred bytes.
#   
#   Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# include/net/dst.h
#   2005/03/10 18:17:32-08:00 herbert@gondor.apana.org.au +0 -2
#   [NET]: Move dst_release out of dst->ops->check
#   
#   As promised here is the patch that moves dst_release out of
#   dst->ops->check.  It bloats sk_dst_check/__sk_dst_check slightly
#   but they're only used in a handful of places so it isn't too bad.
#   I actually counted, it's about a few hundred bytes.
#   
#   Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# ChangeSet
#   2005/03/10 18:01:48-08:00 paulus@samba.org 
#   [PATCH] AGP 3.0 bogosities
#   
#   There are other bogosities in drivers/char/agp/generic.c.  I can't
#   believe Dave ever tested that code with an AGP 3.0 device.  If you pass
#   in a mode that has the AGP 3.0 bit set, agp_v3_parse_one() will first
#   clear that bit (and print a message), and then complain because you
#   haven't got that bit set in the mode, with a message that the caller is
#   broken.  Furthermore, if the mode passed in has both the 4x and 8x bits
#   set, the new code will give you 4x where the old code would give you 8x
#   (which is what the caller wanted).
#   
#   The patch below fixes this.  It will work in the 99.99% of cases where
#   we have one AGP bridge and one AGP video card.  We should eventually
#   cope with multiple AGP bridges, but doing the matching of bridges to
#   video cards is a hard problem because the video card is not necessarily
#   a child or sibling of the PCI device that we use for controlling the AGP
#   bridge.  I think we need to see an actual example of a system with
#   multiple AGP bridges first.
#   
#   Oh, and by the way, I have 3D working relatively well on my G5 with a
#   64-bit kernel (and 32-bit X server and clients), which is why I care
#   about AGP 3.0 support.  :)
#   
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/char/agp/generic.c
#   2005/03/10 17:08:29-08:00 paulus@samba.org +3 -7
#   AGP 3.0 bogosities
# 
# drivers/char/agp/agp.h
#   2005/03/10 16:54:54-08:00 paulus@samba.org +1 -1
#   AGP 3.0 bogosities
# 
# ChangeSet
#   2005/03/10 18:00:24-08:00 torvalds@ppc970.osdl.org 
#   Fix up AGP device discovery.
#   
#   The previous revert needed some more work to make it actually work.
# 
# drivers/char/agp/generic.c
#   2005/03/10 18:00:15-08:00 torvalds@ppc970.osdl.org +5 -7
#   Fix up AGP device discovery.
#   
#   The previous revert needed some more work to make it actually work.
# 
# ChangeSet
#   2005/03/10 16:19:18-08:00 kaber@trash.net 
#   [XFRM]: Always reroute in tunnel mode
#   
#   Tunnel mode packets are rerouted if the tunnel destination
#   address is different from the original destination address,
#   otherwise the old route is used. This is inconsistent, the
#   old route might have been selected for a given output device
#   or using routing by tos/fwmark. Always choose a new route
#   in tunnel mode.
#   
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/ipv6/xfrm6_policy.c
#   2005/03/10 16:18:39-08:00 kaber@trash.net +3 -1
#   [XFRM]: Always reroute in tunnel mode
# 
# net/ipv4/xfrm4_policy.c
#   2005/03/10 16:18:39-08:00 kaber@trash.net +3 -1
#   [XFRM]: Always reroute in tunnel mode
# 
# ChangeSet
#   2005/03/10 16:10:12-08:00 jt@hpl.hp.com 
#   [IRDA]: remove unneeded EXPORT_SYMBOL's from irport.c
#   
#   	<Patch from Adrian Bunk>
#   make needlessly global code static
#   remove unneeded EXPORT_SYMBOL's from irport.c
#   
#   Signed-off-by: Adrian Bunk <bunk@stusta.de>
#   Signed-off-by: Jean Tourrilhes <jt@hpl.hp.com>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# drivers/net/irda/smsc-ircc2.c
#   2005/03/10 16:09:58-08:00 jt@hpl.hp.com +1 -1
#   [IRDA]: remove unneeded EXPORT_SYMBOL's from irport.c
#   
#   	<Patch from Adrian Bunk>
#   make needlessly global code static
#   remove unneeded EXPORT_SYMBOL's from irport.c
#   
#   Signed-off-by: Adrian Bunk <bunk@stusta.de>
#   Signed-off-by: Jean Tourrilhes <jt@hpl.hp.com>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# drivers/net/irda/irtty-sir.c
#   2005/03/10 16:09:58-08:00 jt@hpl.hp.com +1 -1
#   [IRDA]: remove unneeded EXPORT_SYMBOL's from irport.c
#   
#   	<Patch from Adrian Bunk>
#   make needlessly global code static
#   remove unneeded EXPORT_SYMBOL's from irport.c
#   
#   Signed-off-by: Adrian Bunk <bunk@stusta.de>
#   Signed-off-by: Jean Tourrilhes <jt@hpl.hp.com>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# drivers/net/irda/irport.h
#   2005/03/10 16:09:58-08:00 jt@hpl.hp.com +0 -10
#   [IRDA]: remove unneeded EXPORT_SYMBOL's from irport.c
#   
#   	<Patch from Adrian Bunk>
#   make needlessly global code static
#   remove unneeded EXPORT_SYMBOL's from irport.c
#   
#   Signed-off-by: Adrian Bunk <bunk@stusta.de>
#   Signed-off-by: Jean Tourrilhes <jt@hpl.hp.com>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# drivers/net/irda/irport.c
#   2005/03/10 16:09:58-08:00 jt@hpl.hp.com +62 -65
#   [IRDA]: remove unneeded EXPORT_SYMBOL's from irport.c
#   
#   	<Patch from Adrian Bunk>
#   make needlessly global code static
#   remove unneeded EXPORT_SYMBOL's from irport.c
#   
#   Signed-off-by: Adrian Bunk <bunk@stusta.de>
#   Signed-off-by: Jean Tourrilhes <jt@hpl.hp.com>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# ChangeSet
#   2005/03/10 16:09:18-08:00 jt@hpl.hp.com 
#   [IRDA]: cleanup obsolete construct in IrCOMM
#   
#   cleanup some construct obsoleted by Linus's patch
#   
#   Signed-off-by: Jean Tourrilhes <jt@hpl.hp.com>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/irda/ircomm/ircomm_tty.c
#   2005/03/10 16:09:06-08:00 jt@hpl.hp.com +2 -6
#   [IRDA]: cleanup obsolete construct in IrCOMM
#   
#   cleanup some construct obsoleted by Linus's patch
#   
#   Signed-off-by: Jean Tourrilhes <jt@hpl.hp.com>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# ChangeSet
#   2005/03/10 16:08:32-08:00 jt@hpl.hp.com 
#   [IRDA]: support NSC PC8738x
#   
#   	<Original patch from Steffen Pingel>
#   support NSC PC8738x chipset (IBM x40 & ...)
#   
#   Signed-off-by: Jean Tourrilhes <jt@hpl.hp.com>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# drivers/net/irda/nsc-ircc.c
#   2005/03/10 16:08:19-08:00 jt@hpl.hp.com +3 -6
#   [IRDA]: support NSC PC8738x
#   
#   	<Original patch from Steffen Pingel>
#   support NSC PC8738x chipset (IBM x40 & ...)
#   
#   Signed-off-by: Jean Tourrilhes <jt@hpl.hp.com>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# ChangeSet
#   2005/03/10 16:07:54-08:00 jt@hpl.hp.com 
#   [IRDA]: arbitrary lsap connect
#   
#   	<Original patch from Iavor Fetvadjie>
#   allow IrDA socket to connect on arbitrary LSAPs
#   
#   Signed-off-by: Jean Tourrilhes <jt@hpl.hp.com>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/irda/af_irda.c
#   2005/03/10 16:07:41-08:00 jt@hpl.hp.com +17 -5
#   [IRDA]: arbitrary lsap connect
#   
#   	<Original patch from Iavor Fetvadjie>
#   allow IrDA socket to connect on arbitrary LSAPs
#   
#   Signed-off-by: Jean Tourrilhes <jt@hpl.hp.com>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# ChangeSet
#   2005/03/10 16:07:15-08:00 jt@hpl.hp.com 
#   [IRDA]: Mark exit code properly in VIA driver
#   
#   	<Patch from Randy Dunlap>
#   Mark exit code properly in VIA driver
#   
#   Signed-off-by: Randy Dunlap <rddunlap@osdl.org>
#   Signed-off-by: Jean Tourrilhes <jt@hpl.hp.com>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# drivers/net/irda/via-ircc.c
#   2005/03/10 16:07:02-08:00 jt@hpl.hp.com +6 -6
#   [IRDA]: Mark exit code properly in VIA driver
#   
#   	<Patch from Randy Dunlap>
#   Mark exit code properly in VIA driver
#   
#   Signed-off-by: Randy Dunlap <rddunlap@osdl.org>
#   Signed-off-by: Jean Tourrilhes <jt@hpl.hp.com>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# ChangeSet
#   2005/03/10 16:06:27-08:00 jt@hpl.hp.com 
#   [IRDA]: stir4200 turnaround calculation fix
#   
#   	<Patch from John K. Luebs>
#   Proper turnaround computations in the stir4200 driver
#   Take care of Tx packet without IrDA metadata (speed)
#   
#   Signed-off-by: John K. Luebs <jkluebs@lu...>
#   Signed-off-by: Jean Tourrilhes <jt@hpl.hp.com>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# drivers/net/irda/stir4200.c
#   2005/03/10 16:06:14-08:00 jt@hpl.hp.com +3 -2
#   [IRDA]: stir4200 turnaround calculation fix
#   
#   	<Patch from John K. Luebs>
#   Proper turnaround computations in the stir4200 driver
#   Take care of Tx packet without IrDA metadata (speed)
#   
#   Signed-off-by: John K. Luebs <jkluebs@lu...>
#   Signed-off-by: Jean Tourrilhes <jt@hpl.hp.com>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# ChangeSet
#   2005/03/10 16:05:02-08:00 jt@hpl.hp.com 
#   [IRDA]: irda-usb sysfs support
#   
#   Forgot to convert a few usb_unlink_urb() in usb_kill_urb()
#   	<Patch from John K. Luebs>
#   Proper sysfs support
#   
#   Signed-off-by: John K. Luebs <jkluebs@lu...>
#   Signed-off-by: Jean Tourrilhes <jt@hpl.hp.com>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# drivers/net/irda/irda-usb.c
#   2005/03/10 16:04:50-08:00 jt@hpl.hp.com +4 -4
#   [IRDA]: irda-usb sysfs support
#   
#   Forgot to convert a few usb_unlink_urb() in usb_kill_urb()
#   	<Patch from John K. Luebs>
#   Proper sysfs support
#   
#   Signed-off-by: John K. Luebs <jkluebs@lu...>
#   Signed-off-by: Jean Tourrilhes <jt@hpl.hp.com>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# ChangeSet
#   2005/03/10 16:04:14-08:00 jt@hpl.hp.com 
#   [IRDA]: fix IrNET poll with empty disco log
#   
#   poll would improperly exit when the discovery log
#   was empty
#   
#   Signed-off-by: Jean Tourrilhes <jt@hpl.hp.com>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/irda/irnet/irnet_ppp.c
#   2005/03/10 16:03:52-08:00 jt@hpl.hp.com +41 -19
#   [IRDA]: fix IrNET poll with empty disco log
#   
#   poll would improperly exit when the discovery log
#   was empty
#   
#   Signed-off-by: Jean Tourrilhes <jt@hpl.hp.com>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/irda/irnet/irnet_irda.c
#   2005/03/10 16:03:52-08:00 jt@hpl.hp.com +1 -1
#   [IRDA]: fix IrNET poll with empty disco log
#   
#   poll would improperly exit when the discovery log
#   was empty
#   
#   Signed-off-by: Jean Tourrilhes <jt@hpl.hp.com>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# ChangeSet
#   2005/03/10 15:36:27-08:00 torvalds@ppc970.osdl.org 
#   Revert AGP card->bridge mapping checks.
#   
#   They don't work, as per Ben Herrenschmidt:
#   
#    "device->bus may be a host bridge, which has no bus->self -> Ooops.
#   
#     Unfortunately, there is no sane way to match a host bridge with it's
#     eventual "self" device if it has any. The only way would be to scan for
#     devices of class host bridge, but that isn't even 100% reliable.
#   
#     The result is that the self device (AGP bridge device) is generally a
#     sibling of the actual AGP card, which is source of interesting problems,
#     especially with power management."
#   
#   Cset exclude: davej@delerium.kernelslacker.org|ChangeSet|20050223022533|52155
# 
# drivers/char/agp/generic.c
#   2005/03/10 15:36:25-08:00 torvalds@ppc970.osdl.org +0 -0
#   Revert AGP card->bridge mapping checks.
# 
# ChangeSet
#   2005/03/10 18:05:47-05:00 trond.myklebust@fys.uio.no 
#    NFS: Ensure "mount" is always interruptible and soft
#   
#    Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
# 
# fs/nfs/inode.c
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +7 -4
#    NFS: Ensure "mount" is always interruptible and soft
# 
# ChangeSet
#   2005/03/10 18:05:29-05:00 trond.myklebust@fys.uio.no 
#   NFS: cleanup create()
#   
#    Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
# 
# include/linux/nfs_xdr.h
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +1 -1
#   NFS: cleanup create()
# 
# fs/nfs/proc.c
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +4 -9
#   NFS: cleanup create()
# 
# fs/nfs/nfs4proc.c
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +10 -11
#   NFS: cleanup create()
# 
# fs/nfs/nfs3proc.c
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +8 -25
#   NFS: cleanup create()
# 
# fs/nfs/dir.c
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +9 -11
#   NFS: cleanup create()
# 
# ChangeSet
#   2005/03/10 18:05:12-05:00 trond.myklebust@fys.uio.no 
#   NFS: mkdir() cleanup
#   
#    Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
# 
# include/linux/nfs_xdr.h
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +1 -2
#   NFS: mkdir() cleanup
# 
# fs/nfs/proc.c
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +11 -8
#   NFS: mkdir() cleanup
# 
# fs/nfs/nfs4proc.c
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +14 -13
#   NFS: mkdir() cleanup
# 
# fs/nfs/nfs3proc.c
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +11 -9
#   NFS: mkdir() cleanup
# 
# fs/nfs/dir.c
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +1 -15
#   NFS: mkdir() cleanup
# 
# ChangeSet
#   2005/03/10 18:04:54-05:00 trond.myklebust@fys.uio.no 
#   NFS: mknod() cleanup
#   
#    Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
# 
# include/linux/nfs_xdr.h
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +2 -2
#   NFS: mknod() cleanup
# 
# include/linux/nfs_fs.h
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +2 -0
#   NFS: mknod() cleanup
# 
# fs/nfs/proc.c
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +14 -10
#   NFS: mknod() cleanup
# 
# fs/nfs/nfs4proc.c
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +14 -13
#   NFS: mknod() cleanup
# 
# fs/nfs/nfs3proc.c
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +13 -10
#   NFS: mknod() cleanup
# 
# fs/nfs/dir.c
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +25 -20
#   NFS: mknod() cleanup
# 
# ChangeSet
#   2005/03/10 18:04:40-05:00 trond.myklebust@fys.uio.no 
#   NFSv4: in readdir, use MOUNTED_ON_FILEID, rather than true fileid
#   
#    Some servers return an error if the READDIR call attempts to read the
#    fileid of a mountpoint.
#   
#    Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
# 
# include/linux/nfs_xdr.h
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +1 -0
#   NFSv4: in readdir, use MOUNTED_ON_FILEID, rather than true fileid
# 
# fs/nfs/nfs4xdr.c
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +17 -7
#   NFSv4: in readdir, use MOUNTED_ON_FILEID, rather than true fileid
# 
# fs/nfs/nfs4proc.c
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +1 -0
#   NFSv4: in readdir, use MOUNTED_ON_FILEID, rather than true fileid
# 
# ChangeSet
#   2005/03/10 18:04:20-05:00 trond.myklebust@fys.uio.no 
#   NFSv4: Allow recovery from network partitions
#   
#    Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
# 
# include/linux/nfs_fs.h
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +2 -0
#   NFSv4: Allow recovery from network partitions
# 
# fs/nfs/nfs4state.c
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +24 -10
#   NFSv4: Allow recovery from network partitions
# 
# fs/nfs/nfs4proc.c
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +104 -0
#   NFSv4: Allow recovery from network partitions
# 
# fs/nfs/inode.c
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +7 -1
#   NFSv4: Allow recovery from network partitions
# 
# ChangeSet
#   2005/03/10 18:04:01-05:00 trond.myklebust@fys.uio.no 
#   NFSv4: Add nfs4_state_recovery_ops
#   
#    We want to reuse the same code to recover the NFSv4 state after a server
#    reboot, a network partition, or a failover situation.
#   
#    Add a structure to contain those operations will that depend on the recovery
#    scenario under consideration.
#   
#    Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
# 
# include/linux/nfs_fs.h
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +7 -2
#   NFSv4: Add nfs4_state_recovery_ops
# 
# fs/nfs/nfs4state.c
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +8 -6
#   NFSv4: Add nfs4_state_recovery_ops
# 
# fs/nfs/nfs4proc.c
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +7 -2
#   NFSv4: Add nfs4_state_recovery_ops
# 
# ChangeSet
#   2005/03/10 18:03:44-05:00 trond.myklebust@fys.uio.no 
#   NFS: Cleanups for the network partition reclaim code
#   
#    Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
# 
# fs/nfs/nfs4state.c
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +17 -3
#   NFS: Cleanups for the network partition reclaim code
# 
# fs/nfs/nfs4proc.c
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +55 -42
#   NFS: Cleanups for the network partition reclaim code
# 
# ChangeSet
#   2005/03/10 18:03:27-05:00 trond.myklebust@fys.uio.no 
#   NFSv4: Fix access mode checking when opening a delegated file.
#   
#    Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
# 
# fs/nfs/nfs4proc.c
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +7 -3
#   NFSv4: Fix access mode checking when opening a delegated file.
# 
# ChangeSet
#   2005/03/10 18:03:10-05:00 trond.myklebust@fys.uio.no 
#   NFSv4: NFSv4 errors in nfs4_init_client() must not leak to userland
#   
#    Fixes a potential Oops at mount time.
#   
#    Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
# 
# include/linux/nfs_fs.h
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +1 -0
#   NFSv4: NFSv4 errors in nfs4_init_client() must not leak to userland
# 
# fs/nfs/nfs4state.c
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +7 -2
#   NFSv4: NFSv4 errors in nfs4_init_client() must not leak to userland
# 
# fs/nfs/nfs4proc.c
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +2 -2
#   NFSv4: NFSv4 errors in nfs4_init_client() must not leak to userland
# 
# ChangeSet
#   2005/03/10 18:02:53-05:00 trond.myklebust@fys.uio.no 
#    NFSv4: Exit without Oopsing from close when servers send us crazy errors.
#   
#    If retrying the request is not an option, we should just set state->state
#    and be done with it.
#   
#    Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
# 
# fs/nfs/nfs4proc.c
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +1 -1
#    NFSv4: Exit without Oopsing from close when servers send us crazy errors.
# 
# ChangeSet
#   2005/03/10 18:02:36-05:00 trond.myklebust@fys.uio.no 
#    NFSv4: Handle the NFS4ERR_CLID_INUSE error in SETCLIENTID
#   
#    Encode the AUTH flavour in the clientid, since AUTH_UNIX and AUTH_GSS
#    credentials will always conflict.
#   
#    Then, strategy is to first retry after sleeping for a lease period. If
#    the server then still refuses our clientid, assume we have a conflicting
#    client, out there, and try bumping a "uniquifier" variable.
#   
#    Give up if we're signalled, or if we've gone through the entire range
#    of uniquifiers...
#   
#    Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
# 
# include/linux/nfs_fs.h
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +4 -0
#    NFSv4: Handle the NFS4ERR_CLID_INUSE error in SETCLIENTID
# 
# fs/nfs/nfs4xdr.c
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +1 -1
#    NFSv4: Handle the NFS4ERR_CLID_INUSE error in SETCLIENTID
# 
# fs/nfs/nfs4state.c
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +1 -0
#    NFSv4: Handle the NFS4ERR_CLID_INUSE error in SETCLIENTID
# 
# fs/nfs/nfs4proc.c
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +32 -22
#    NFSv4: Handle the NFS4ERR_CLID_INUSE error in SETCLIENTID
# 
# ChangeSet
#   2005/03/10 18:02:19-05:00 trond.myklebust@fys.uio.no 
#   NFS: catch a few extra ESTALE errors that we are currently discarding.
#   
#    Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
# 
# fs/nfs/dir.c
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +17 -6
#   NFS: catch a few extra ESTALE errors that we are currently discarding.
# 
# ChangeSet
#   2005/03/10 18:02:01-05:00 trond.myklebust@fys.uio.no 
#   VFS: Retry pathname resolution after encountering ESTALE
#    
#    Add a mechanism for the VFS layer to retry pathname resolution if a file
#    system returns ESTALE at any point during the resolution process.  Pathname
#    resolution is retried once from the first component, using all real lookup
#    requests.
#   
#    This provides effective recovery for most cases where files or directories
#    have been replaced by other remote file system clients.  It also provides
#    a foundation to build a mechanism by which file system clients can fail
#    over transparently to a replicated server.
#   
#    Test-plan:
#    Combinations of rsync and "ls -l" on multiple clients.  No stale file handles
#    should be after directory trees are replaced.  Standard performance tests;
#    little or no loss of performance is expected.
#   
#    Created: Fri, 11 Feb 2005 16:46:19 -0500
#    
#    Signed-off-by: Chuck Lever <cel@netapp.com>
#    Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
# 
# include/linux/namei.h
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +2 -0
#   VFS: Retry pathname resolution after encountering ESTALE
# 
# fs/nfs/dir.c
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +15 -8
#   VFS: Retry pathname resolution after encountering ESTALE
# 
# fs/namei.c
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +32 -1
#   VFS: Retry pathname resolution after encountering ESTALE
# 
# ChangeSet
#   2005/03/10 18:01:43-05:00 trond.myklebust@fys.uio.no 
#   NFS,RPC: RPC client now advertises maximum payload size
#   
#    The RPC client now reports the maximum payload size supported by the chosen
#    transport method.  This is something a little less than 64KB for RPC over
#    UDP, and about 2GB - 1 for RPC over TCP.  The effective rsize and wsize
#    values are not allowed to exceed the reported maximum RPC payload size.
#   
#    Signed-off-by: Chuck Lever <cel@netapp.com>
#    Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
# 
# net/sunrpc/xprt.c
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +4 -1
#   NFS,RPC: RPC client now advertises maximum payload size
# 
# net/sunrpc/clnt.c
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +15 -0
#   NFS,RPC: RPC client now advertises maximum payload size
# 
# include/linux/sunrpc/xprt.h
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +3 -0
#   NFS,RPC: RPC client now advertises maximum payload size
# 
# include/linux/sunrpc/clnt.h
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +1 -0
#   NFS,RPC: RPC client now advertises maximum payload size
# 
# fs/nfs/inode.c
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +7 -0
#   NFS,RPC: RPC client now advertises maximum payload size
# 
# ChangeSet
#   2005/03/10 18:01:26-05:00 trond.myklebust@fys.uio.no 
#   RPC: remove broken_suid mount option
#   
#   Remove broken_suid mount option (retry RPC after dropping privileges
#   upon EACCES): no longer used and questionable w.r.t. security.
#   
#    Signed-off-by: Frank van Maarseveen <frankvm@frankvm.com>
#    Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
# 
# net/sunrpc/sched.c
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +0 -3
#   RPC: remove broken_suid mount option
# 
# net/sunrpc/clnt.c
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +0 -15
#   RPC: remove broken_suid mount option
# 
# net/sunrpc/auth_unix.c
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +8 -20
#   RPC: remove broken_suid mount option
# 
# net/sunrpc/auth_null.c
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +1 -1
#   RPC: remove broken_suid mount option
# 
# net/sunrpc/auth_gss/auth_gss.c
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +1 -1
#   RPC: remove broken_suid mount option
# 
# net/sunrpc/auth.c
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +1 -2
#   RPC: remove broken_suid mount option
# 
# include/linux/sunrpc/sched.h
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +2 -6
#   RPC: remove broken_suid mount option
# 
# include/linux/sunrpc/clnt.h
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +0 -1
#   RPC: remove broken_suid mount option
# 
# include/linux/sunrpc/auth.h
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +1 -1
#   RPC: remove broken_suid mount option
# 
# fs/nfs/nfsroot.c
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +0 -5
#   RPC: remove broken_suid mount option
# 
# fs/nfs/inode.c
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +0 -2
#   RPC: remove broken_suid mount option
# 
# ChangeSet
#   2005/03/10 18:01:08-05:00 trond.myklebust@fys.uio.no 
#   [NLM] fs/lockd/clntproc.c: make 2 functions static
#   
#    This patch makes two needlessly global functions static.
#   
#    Signed-off-by: Adrian Bunk <bunk@stusta.de>
#    Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
# 
# include/linux/lockd/lockd.h
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +0 -2
#   [NLM] fs/lockd/clntproc.c: make 2 functions static
# 
# fs/lockd/clntproc.c
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +2 -2
#   [NLM] fs/lockd/clntproc.c: make 2 functions static
# 
# ChangeSet
#   2005/03/10 18:00:50-05:00 trond.myklebust@fys.uio.no 
#   NFS: This patch makes some needlessly global code static.
#   
#    Signed-off-by: Adrian Bunk <bunk@stusta.de>
#    Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
# 
# include/linux/nfs_xdr.h
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +0 -2
#   NFS: This patch makes some needlessly global code static.
# 
# include/linux/nfs_fs.h
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +0 -24
#   NFS: This patch makes some needlessly global code static.
# 
# fs/nfs/write.c
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +23 -6
#   NFS: This patch makes some needlessly global code static.
# 
# fs/nfs/read.c
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +1 -1
#   NFS: This patch makes some needlessly global code static.
# 
# fs/nfs/nfsroot.c
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +2 -2
#   NFS: This patch makes some needlessly global code static.
# 
# fs/nfs/nfs4proc.c
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +5 -4
#   NFS: This patch makes some needlessly global code static.
# 
# fs/nfs/mount_clnt.c
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +2 -2
#   NFS: This patch makes some needlessly global code static.
# 
# fs/nfs/inode.c
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +5 -3
#   NFS: This patch makes some needlessly global code static.
# 
# ChangeSet
#   2005/03/10 18:00:33-05:00 trond.myklebust@fys.uio.no 
#   RPC: Clean up of rpcauth_lookupcred() and rpcauth_bindcred()
#   
#    Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
# 
# net/sunrpc/auth.c
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +14 -14
#   RPC: Clean up of rpcauth_lookupcred() and rpcauth_bindcred()
# 
# ChangeSet
#   2005/03/10 18:00:17-05:00 trond.myklebust@fys.uio.no 
#   RPC: make rpcauth_lookupcred() return error codes.
#   
#    So we can distinguish between ENOMEM and EACCES errors.
#   
#    Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
# 
# net/sunrpc/clnt.c
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +2 -2
#   RPC: make rpcauth_lookupcred() return error codes.
# 
# net/sunrpc/auth_unix.c
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +1 -1
#   RPC: make rpcauth_lookupcred() return error codes.
# 
# net/sunrpc/auth_gss/auth_gss.c
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +4 -3
#   RPC: make rpcauth_lookupcred() return error codes.
# 
# net/sunrpc/auth.c
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +8 -6
#   RPC: make rpcauth_lookupcred() return error codes.
# 
# fs/nfsd/nfs4callback.c
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +2 -2
#   RPC: make rpcauth_lookupcred() return error codes.
# 
# fs/nfs/unlink.c
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +8 -1
#   RPC: make rpcauth_lookupcred() return error codes.
# 
# fs/nfs/nfs4proc.c
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +10 -2
#   RPC: make rpcauth_lookupcred() return error codes.
# 
# fs/nfs/inode.c
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +9 -2
#   RPC: make rpcauth_lookupcred() return error codes.
# 
# fs/nfs/dir.c
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +5 -2
#   RPC: make rpcauth_lookupcred() return error codes.
# 
# ChangeSet
#   2005/03/10 18:00:00-05:00 trond.myklebust@fys.uio.no 
#   RPC: Initialize the GSS context upon RPC credential creation.
#   
#    Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
# 
# net/sunrpc/auth_gss/auth_gss.c
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +140 -71
#   RPC: Initialize the GSS context upon RPC credential creation.
# 
# net/sunrpc/auth.c
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +5 -2
#   RPC: Initialize the GSS context upon RPC credential creation.
# 
# ChangeSet
#   2005/03/10 17:59:44-05:00 trond.myklebust@fys.uio.no 
#   RPC: Remove dependency of RPCSEC_GSS upcalls on the credential cache
#   
#    Ensure that credentials that are referenced by an RPC task, but that
#    have been booted out of the credcache may still be refreshed.
#   
#    Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
# 
# net/sunrpc/auth_gss/auth_gss.c
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +42 -20
#   RPC: Remove dependency of RPCSEC_GSS upcalls on the credential cache
# 
# include/linux/sunrpc/auth_gss.h
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +2 -0
#   RPC: Remove dependency of RPCSEC_GSS upcalls on the credential cache
# 
# ChangeSet
#   2005/03/10 17:59:27-05:00 trond.myklebust@fys.uio.no 
#   RPCSEC_GSS: Enable expiring of credentials
#   
#    Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
# 
# net/sunrpc/auth_gss/auth_gss.c
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +9 -0
#   RPCSEC_GSS: Enable expiring of credentials
# 
# include/linux/sunrpc/auth_gss.h
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +1 -0
#   RPCSEC_GSS: Enable expiring of credentials
# 
# ChangeSet
#   2005/03/10 17:59:09-05:00 trond.myklebust@fys.uio.no 
#   RPCSEC_GSS: Misc little cleanups.
#   
#    Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
# 
# net/sunrpc/auth_gss/gss_mech_switch.c
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +1 -1
#   RPCSEC_GSS: Misc little cleanups.
# 
# net/sunrpc/auth_gss/auth_gss.c
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +1 -3
#   RPCSEC_GSS: Misc little cleanups.
# 
# include/linux/sunrpc/gss_api.h
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +1 -3
#   RPCSEC_GSS: Misc little cleanups.
# 
# ChangeSet
#   2005/03/10 17:58:52-05:00 trond.myklebust@fys.uio.no 
#   RPCSEC_GSS: cleanup gss_cred.
#   
#    gc_flavor is used only for looking up the security service, which is an
#    integer value that never changes. Store the latter instead of the former.
#   
#    Fix up a couple of dodgy casts between gss_cred and rpc_cred. Replace them
#    with the appropriate container_of().
#   
#    Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
# 
# net/sunrpc/auth_gss/auth_gss.c
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +22 -35
#   RPCSEC_GSS: cleanup gss_cred.
# 
# include/linux/sunrpc/auth_gss.h
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +1 -1
#   RPCSEC_GSS: cleanup gss_cred.
# 
# ChangeSet
#   2005/03/10 17:58:34-05:00 trond.myklebust@fys.uio.no 
#   RPC: Document the format of the gssd downcalls
#   
#    - Document the format of the gssd downcalls
#    - Separate out "uid" field from rest of GSS context data struct
#      since it will not be needed for the keyring-based contexts.
#   
#    Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
# 
# net/sunrpc/auth_gss/auth_gss.c
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +120 -120
#   RPC: Document the format of the gssd downcalls
# 
# include/linux/sunrpc/auth_gss.h
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +1 -1
#   RPC: Document the format of the gssd downcalls
# 
# ChangeSet
#   2005/03/10 17:58:17-05:00 trond.myklebust@fys.uio.no 
#   RPC: clean up the RPCSEC_GSS kerberos and spkm3 context import functions
#   
#    Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
# 
# net/sunrpc/auth_gss/svcauth_gss.c
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +1 -4
#   RPC: clean up the RPCSEC_GSS kerberos and spkm3 context import functions
# 
# net/sunrpc/auth_gss/gss_spkm3_mech.c
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +70 -63
#   RPC: clean up the RPCSEC_GSS kerberos and spkm3 context import functions
# 
# net/sunrpc/auth_gss/gss_mech_switch.c
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +3 -3
#   RPC: clean up the RPCSEC_GSS kerberos and spkm3 context import functions
# 
# net/sunrpc/auth_gss/gss_krb5_mech.c
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +60 -45
#   RPC: clean up the RPCSEC_GSS kerberos and spkm3 context import functions
# 
# net/sunrpc/auth_gss/auth_gss.c
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +1 -1
#   RPC: clean up the RPCSEC_GSS kerberos and spkm3 context import functions
# 
# include/linux/sunrpc/gss_api.h
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +6 -4
#   RPC: clean up the RPCSEC_GSS kerberos and spkm3 context import functions
# 
# ChangeSet
#   2005/03/10 17:58:00-05:00 trond.myklebust@fys.uio.no 
#   NLM: Always use AUTH_UNIX authentication for NLM locking.
#   
#    Most existing servers do not implement RPCSEC_GSS for either the lockd or
#    statd daemons.
#   
#    Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
# 
# include/linux/lockd/lockd.h
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +0 -1
#   NLM: Always use AUTH_UNIX authentication for NLM locking.
# 
# fs/lockd/host.c
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +2 -2
#   NLM: Always use AUTH_UNIX authentication for NLM locking.
# 
# fs/lockd/clntproc.c
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +1 -8
#   NLM: Always use AUTH_UNIX authentication for NLM locking.
# 
# ChangeSet
#   2005/03/10 17:57:38-05:00 trond.myklebust@fys.uio.no 
#   NFS: Add emulation of BSD flock() in terms of POSIX locks on the server
#   
#    This makes for an interesting situation in which programs compiled
#    to use flock() and running on the server will not see the locks that
#    are set by the clients. The clients will, however, see both POSIX and
#    flock() locks set by other clients.
#   
#    It is the best you can do, given the limitations of the protocol.
#   
#    Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
# 
# include/linux/nfs_fs.h
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +0 -5
#   NFS: Add emulation of BSD flock() in terms of POSIX locks on the server
# 
# fs/nfs/nfs4proc.c
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +21 -2
#   NFS: Add emulation of BSD flock() in terms of POSIX locks on the server
# 
# fs/nfs/file.c
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +53 -8
#   NFS: Add emulation of BSD flock() in terms of POSIX locks on the server
# 
# fs/lockd/clntproc.c
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +21 -5
#   NFS: Add emulation of BSD flock() in terms of POSIX locks on the server
# 
# ChangeSet
#   2005/03/10 17:57:20-05:00 trond.myklebust@fys.uio.no 
#   VFS: Fix structure initialization in locks_remove_flock()
#   
#    Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
# 
# fs/locks.c
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +7 -2
#   VFS: Fix structure initialization in locks_remove_flock()
# 
# ChangeSet
#   2005/03/10 17:57:03-05:00 trond.myklebust@fys.uio.no 
#   RPC: Shrink struct rpc_auth for those flavours that don't use the cache
#   
#    Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
# 
# net/sunrpc/auth_unix.c
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +8 -2
#   RPC: Shrink struct rpc_auth for those flavours that don't use the cache
# 
# net/sunrpc/auth_gss/auth_gss.c
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +2 -2
#   RPC: Shrink struct rpc_auth for those flavours that don't use the cache
# 
# net/sunrpc/auth.c
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +22 -11
#   RPC: Shrink struct rpc_auth for those flavours that don't use the cache
# 
# include/linux/sunrpc/auth.h
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +8 -4
#   RPC: Shrink struct rpc_auth for those flavours that don't use the cache
# 
# ChangeSet
#   2005/03/10 17:56:46-05:00 trond.myklebust@fys.uio.no 
#   RPC: Unify the AUTH_UNIX credential cache.
#   
#    AUTH_UNIX credentials really only depend on the process uid/gid/groups
#    information. In particular there is no dependency on any strict rpc_client
#    specific information. Might as well share them all between all RPC clients.
#   
#    Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
# 
# net/sunrpc/auth_unix.c
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +13 -14
#   RPC: Unify the AUTH_UNIX credential cache.
# 
# ChangeSet
#   2005/03/10 17:56:29-05:00 trond.myklebust@fys.uio.no 
#   RPC: Unify AUTH_NULL credentials
#   
#    There is only one AUTH_NULL "credential".
#   
#    Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
# 
# net/sunrpc/auth_null.c
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +24 -39
#   RPC: Unify AUTH_NULL credentials
# 
# ChangeSet
#   2005/03/10 17:56:13-05:00 trond.myklebust@fys.uio.no 
#   RPC: Convert RPC credcache to use hlists
#   
#    This will make initialization of statically allocated caches simpler.
#   
#    Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
# 
# net/sunrpc/auth.c
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +27 -24
#   RPC: Convert RPC credcache to use hlists
# 
# include/linux/sunrpc/auth.h
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +2 -2
#   RPC: Convert RPC credcache to use hlists
# 
# ChangeSet
#   2005/03/10 17:55:56-05:00 trond.myklebust@fys.uio.no 
#   RPC: kill cr_auth
#   
#    The cr_auth field is currently used only in order to figure out the name
#    of the credential's flavour in debugging printks. Replace with a dedicated
#    pointer in the statically allocated rpc_credops instead.
#   
#    Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
# 
# net/sunrpc/auth_unix.c
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +1 -0
#   RPC: kill cr_auth
# 
# net/sunrpc/auth_null.c
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +1 -0
#   RPC: kill cr_auth
# 
# net/sunrpc/auth_gss/auth_gss.c
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +1 -0
#   RPC: kill cr_auth
# 
# net/sunrpc/auth.c
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +7 -11
#   RPC: kill cr_auth
# 
# include/linux/sunrpc/auth.h
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +1 -1
#   RPC: kill cr_auth
# 
# ChangeSet
#   2005/03/10 17:55:39-05:00 trond.myklebust@fys.uio.no 
#   RPC: Make rpc_auth credential cache optional.
#   
#     Some RPC authentication flavours are not related to the uid (AUTH_NULL
#     springs to mind). This patch moves control over the caching mechanism
#     into the auth-specific code.
#   
#     Also ensure that expired creds are removed from the cache.
#   
#    Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
# 
# net/sunrpc/auth_unix.c
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +10 -0
#   RPC: Make rpc_auth credential cache optional.
# 
# net/sunrpc/auth_null.c
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +10 -0
#   RPC: Make rpc_auth credential cache optional.
# 
# net/sunrpc/auth_gss/auth_gss.c
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +10 -0
#   RPC: Make rpc_auth credential cache optional.
# 
# net/sunrpc/auth.c
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +11 -11
#   RPC: Make rpc_auth credential cache optional.
# 
# include/linux/sunrpc/auth.h
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +1 -0
#   RPC: Make rpc_auth credential cache optional.
# 
# ChangeSet
#   2005/03/10 17:55:21-05:00 trond.myklebust@fys.uio.no 
#   RPC: Move credcache-specific code out of put_rpccred()
#   
#    Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
# 
# net/sunrpc/auth_unix.c
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +1 -1
#   RPC: Move credcache-specific code out of put_rpccred()
# 
# net/sunrpc/auth_null.c
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +1 -1
#   RPC: Move credcache-specific code out of put_rpccred()
# 
# net/sunrpc/auth_gss/auth_gss.c
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +1 -1
#   RPC: Move credcache-specific code out of put_rpccred()
# 
# net/sunrpc/auth.c
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +8 -32
#   RPC: Move credcache-specific code out of put_rpccred()
# 
# ChangeSet
#   2005/03/10 17:55:05-05:00 trond.myklebust@fys.uio.no 
#   RPC: struct rpc_auth initialization and destruction code cleanup
#   
#    Move the initialization of auth->au_count into the flavour-specific code.
#    Move the kfree(auth) into the flavour-specific code.
#   
#    Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
# 
# net/sunrpc/auth_unix.c
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +2 -0
#   RPC: struct rpc_auth initialization and destruction code cleanup
# 
# net/sunrpc/auth_null.c
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +2 -0
#   RPC: struct rpc_auth initialization and destruction code cleanup
# 
# net/sunrpc/auth_gss/auth_gss.c
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +2 -0
#   RPC: struct rpc_auth initialization and destruction code cleanup
# 
# net/sunrpc/auth.c
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +0 -2
#   RPC: struct rpc_auth initialization and destruction code cleanup
# 
# ChangeSet
#   2005/03/10 17:54:47-05:00 trond.myklebust@fys.uio.no 
#   RPC: Remove unnecessary reference counting in gss downcall code.
#   
#    Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
# 
# net/sunrpc/auth_gss/auth_gss.c
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +0 -3
#   RPC: Remove unnecessary reference counting in gss downcall code.
# 
# ChangeSet
#   2005/03/10 17:54:29-05:00 trond.myklebust@fys.uio.no 
#   RPC: Remove unnecessary module refcounting
#   
#    The sunrpc module itself is referenced by other sources, so only the
#    auth_gss credcaches need to increment their module refcount.
#   
#    Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
# 
# net/sunrpc/auth_gss/auth_gss.c
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +4 -0
#   RPC: Remove unnecessary module refcounting
# 
# net/sunrpc/auth.c
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +0 -3
#   RPC: Remove unnecessary module refcounting
# 
# ChangeSet
#   2005/03/10 17:54:10-05:00 trond.myklebust@fys.uio.no 
#   RPC: Some portmappers expect AUTH_UNIX authentication
#   
#    Sun's RPC library portmap client therefore defaults to AUTH_UNIX. Change our
#    in-kernel client to follow that convention.
#   
#    Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
# 
# net/sunrpc/pmap_clnt.c
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +1 -4
#   RPC: Some portmappers expect AUTH_UNIX authentication
# 
# ChangeSet
#   2005/03/10 17:53:53-05:00 trond.myklebust@fys.uio.no 
#   RPC: Fix return value of rpc_call_async()
#   
#    RPC call async is supposed to return an error if and only if
#    it failed to run the rpc_task.
#   
#    Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
# 
# net/sunrpc/clnt.c
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +4 -5
#   RPC: Fix return value of rpc_call_async()
# 
# ChangeSet
#   2005/03/10 17:53:36-05:00 trond.myklebust@fys.uio.no 
#   NFS: Use sizeof() instead of strlen() on string constants.
#   
#    Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
# 
# fs/nfs/nfsroot.c
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +2 -2
#   NFS: Use sizeof() instead of strlen() on string constants.
# 
# fs/nfs/dir.c
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +1 -1
#   NFS: Use sizeof() instead of strlen() on string constants.
# 
# ChangeSet
#   2005/03/10 17:53:19-05:00 trond.myklebust@fys.uio.no 
#   RPC: Don't kill timers when calling rpc_restart_call() after rpc_delay()
#   
#    Currently, if we restart an RPC call after having set an RPC delay (for
#    instance in the case where an NFS EJUKEBOX error has occurred) the call
#    to rpc_delete_timer() at the top of the rpc_execute() loop will
#    kill off our timer.
#   
#    This patch causes rpc_delete_timer() to detect if the rpc_task is still
#    queued on a wait queue, and refuse to delete the timer if this is the case.
#   
#    Problem diagnosed by Jan Sanislo and Olaf Kirch.
#    Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
# 
# net/sunrpc/sched.c
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +3 -1
#   RPC: Don't kill timers when calling rpc_restart_call() after rpc_delay()
# 
# ChangeSet
#   2005/03/10 17:53:02-05:00 trond.myklebust@fys.uio.no 
#    NFS: Fix refcount leakage in nfs4_proc_create()
#   
#    Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
# 
# fs/nfs/nfs4proc.c
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +18 -15
#    NFS: Fix refcount leakage in nfs4_proc_create()
# 
# ChangeSet
#   2005/03/10 17:52:45-05:00 trond.myklebust@fys.uio.no 
#   NFS: Clean up nfs_permission().
#   
#    Fix a bug whereby we are failing to test for permissions on opendir().
#    Optimize away permissions checks that request MAY_WRITE on directories.
#    Ensure that VFS sets LOOKUP_CONTINUE before calling permission().
#   
#    Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
# 
# include/linux/nfs_fs_sb.h
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +1 -0
#   NFS: Clean up nfs_permission().
# 
# fs/nfs/inode.c
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +1 -0
#   NFS: Clean up nfs_permission().
# 
# fs/nfs/dir.c
#   2005/03/09 19:00:00-05:00 trond.myklebust@fys.uio.no +24 -10
#   NFS: Clean up nfs_permission().
# 
# ChangeSet
#   2005/03/10 12:55:24-08:00 willy@parisc-linux.org 
#   [PATCH] Remove CONFIG_PARISC64 symbol
#   
#   Use CONFIG_64BIT everywhere instead.
#   
#   Signed-off-by: Matthew Wilcox <willy@parisc-linux.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/asm-parisc/pdcpat.h
#   2005/03/10 09:18:20-08:00 willy@parisc-linux.org +3 -3
#   Remove CONFIG_PARISC64 symbol
# 
# include/asm-parisc/assembly.h
#   2005/03/10 09:18:18-08:00 willy@parisc-linux.org +1 -1
#   Remove CONFIG_PARISC64 symbol
# 
# ChangeSet
#   2005/03/10 12:55:09-08:00 willy@parisc-linux.org 
#   [PATCH] PA-RISC misc header cleanups
#   
#   Indentation and header file ordering
#   
#   Signed-off-by: Matthew Wilcox <willy@parisc-linux.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/asm-parisc/pdc_chassis.h
#   2005/03/10 09:18:20-08:00 willy@parisc-linux.org +3 -3
#   PA-RISC misc header cleanups
# 
# include/asm-parisc/dma-mapping.h
#   2005/03/10 09:18:18-08:00 willy@parisc-linux.org +1 -1
#   PA-RISC misc header cleanups
# 
# ChangeSet
#   2005/03/10 12:54:53-08:00 willy@parisc-linux.org 
#   [PATCH] Fix PA-RISC EISA EEPROM support
#   
#   The EISA EEPROM driver was being initialised too early, before miscdevs
#   can be registered.  But EISA needs to be registered early -- before PCI.
#   So stash the EEPROM address in a global variable at EISA init time,
#   then pick it up later in the EISA EEPROM driver.
#   
#   Also ioremap() it, use readb instead of gsc_readb and rename the
#   miscdev to not have a space in the name.
#   
#   Signed-off-by: Matthew Wilcox <willy@parisc-linux.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/asm-parisc/eisa_eeprom.h
#   2005/03/10 09:18:19-08:00 willy@parisc-linux.org +2 -0
#   Fix PA-RISC EISA EEPROM support
# 
# drivers/parisc/eisa_eeprom.c
#   2005/03/10 09:18:07-08:00 willy@parisc-linux.org +10 -14
#   Fix PA-RISC EISA EEPROM support
# 
# drivers/parisc/eisa.c
#   2005/03/10 09:18:07-08:00 willy@parisc-linux.org +7 -2
#   Fix PA-RISC EISA EEPROM support
# 
# ChangeSet
#   2005/03/10 12:54:38-08:00 willy@parisc-linux.org 
#   [PATCH] Minor changes to the PA-RISC Asp driver
#   
#   There can be only one Asp in the machine, so allocate its controller
#   structure statically.
#   
#   Signed-off-by: Matthew Wilcox <willy@parisc-linux.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/parisc/asp.c
#   2005/03/10 09:18:07-08:00 willy@parisc-linux.org +12 -18
#   Minor changes to the PA-RISC Asp driver
# 
# ChangeSet
#   2005/03/10 12:54:23-08:00 willy@parisc-linux.org 
#   [PATCH] Fix panic in PA-RISC CCIO driver
#   
#   Ditch ccio_mem_ratio. "Ported" from similar change to sba driver.
#   
#   From: Joel Soete <soete.joel@tiscali.be>
#   Signed-off-by: Grant Grundler <grundler@parisc-linux.org>
#   Signed-off-by: Matthew Wilcox <willy@parisc-linux.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/parisc/ccio-dma.c
#   2005/03/10 09:18:07-08:00 willy@parisc-linux.org +34 -32
#   Fix panic in PA-RISC CCIO driver
# 
# ChangeSet
#   2005/03/10 12:54:09-08:00 willy@parisc-linux.org 
#   [PATCH] PA-RISC IOMMU-related fixes
#   
#    - PCI_DMA_BUS_IS_PHYS is only true if we don't have an IOMMU.  Getting this
#      wrong results in system panics when we run out of bounce buffers.
#    - parisc_vmerge_boundary and parisc_vmerge_max_size need to be available on
#      all machines, not just ones with GSC.
#   
#   Signed-off-by: Grant Grundler <grundler@parisc-linux.org>
#   Signed-off-by: Matthew Wilcox <willy@parisc-linux.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/asm-parisc/pci.h
#   2005/03/08 11:16:18-08:00 willy@parisc-linux.org +20 -3
#   PA-RISC IOMMU-related fixes
# 
# arch/parisc/kernel/setup.c
#   2005/03/08 11:15:56-08:00 willy@parisc-linux.org +9 -0
#   PA-RISC IOMMU-related fixes
# 
# ChangeSet
#   2005/03/10 12:53:53-08:00 willy@parisc-linux.org 
#   [PATCH] Fix PA-RISC debuglocks
#   
#   _dbg_write_trylock() needs to return an int.
#   Also update Thibaut's email address
#   
#   Signed-off-by: Matthew Wilcox <willy@parisc-linux.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/asm-parisc/spinlock.h
#   2005/03/08 11:16:19-08:00 willy@parisc-linux.org +1 -1
#   Fix PA-RISC debuglocks
# 
# arch/parisc/lib/debuglocks.c
#   2005/03/08 11:15:56-08:00 willy@parisc-linux.org +2 -3
#   Fix PA-RISC debuglocks
# 
# ChangeSet
#   2005/03/10 12:53:38-08:00 willy@parisc-linux.org 
#   [PATCH] PA-RISC access_ok()
#   
#   Make access_ok an inline function to get rid of an unused variable warning
#   
#   Signed-off-by: Matthew Wilcox <willy@parisc-linux.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/asm-parisc/uaccess.h
#   2005/03/10 09:18:20-08:00 willy@parisc-linux.org +6 -1
#   PA-RISC access_ok()
# 
# ChangeSet
#   2005/03/10 12:53:23-08:00 willy@parisc-linux.org 
#   [PATCH] PA-RISC preempt accounting fixes
#   
#    - Match other architectures by initialising preempt_count to 1.
#    - PREEMPT_ACTIVE needs to not overlap with HARDIRQ_MASK
#   
#   Signed-off-by: Matthew Wilcox <willy@parisc-linux.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/asm-parisc/thread_info.h
#   2005/03/10 09:18:20-08:00 willy@parisc-linux.org +2 -2
#   PA-RISC preempt accounting fixes
# 
# ChangeSet
#   2005/03/10 12:53:08-08:00 willy@parisc-linux.org 
#   [PATCH] PA-RISC mb() definition
#   
#   The extraneous semicolon in mb() breaks the SMP build in the new skbuff.h
#   
#   From: Grant Grundler <grundler@parisc-linux.org>
#   Signed-off-by: Matthew Wilcox <willy@parisc-linux.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/asm-parisc/system.h
#   2005/03/10 09:18:20-08:00 willy@parisc-linux.org +1 -1
#   PA-RISC mb() definition
# 
# ChangeSet
#   2005/03/10 12:52:52-08:00 willy@parisc-linux.org 
#   [PATCH] PA-RISC readX() simplification
#   
#   The result from __raw_readX() can never be const so use __fswabXX() instead
#   of cpu_to_leXX()
#   
#   Signed-off-by: Matthew Wilcox <willy@parisc-linux.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/asm-parisc/io.h
#   2005/03/10 09:18:19-08:00 willy@parisc-linux.org +4 -3
#   PA-RISC readX() simplification
# 
# ChangeSet
#   2005/03/10 12:52:37-08:00 willy@parisc-linux.org 
#   [PATCH] PA-RISC can use the generic HARDIRQ_BITS
#   
#   We no longer need to define our own HARDIRQ_BITS
#   
#   Signed-off-by: Matthew Wilcox <willy@parisc-linux.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/asm-parisc/hardirq.h
#   2005/03/10 09:18:19-08:00 willy@parisc-linux.org +0 -12
#   PA-RISC can use the generic HARDIRQ_BITS
# 
# ChangeSet
#   2005/03/10 12:52:21-08:00 willy@parisc-linux.org 
#   [PATCH] PA-RISC DMA definitions
#   
#   Copy some DMA definitions from x86 to get crufty drivers to build
#   
#   Signed-off-by: Matthew Wilcox <willy@parisc-linux.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/asm-parisc/dma.h
#   2005/03/10 09:18:19-08:00 willy@parisc-linux.org +5 -3
#   PA-RISC DMA definitions
# 
# ChangeSet
#   2005/03/10 12:52:06-08:00 willy@parisc-linux.org 
#   [PATCH] PA-RISC nonatomic bitops for ext2/3
#   
#   Use nonatomic bitops for ext2/3 where possible.
#   
#   Signed-off-by: Matthew Wilcox <willy@parisc-linux.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/asm-parisc/bitops.h
#   2005/03/10 09:18:18-08:00 willy@parisc-linux.org +4 -4
#   PA-RISC nonatomic bitops for ext2/3
# 
# ChangeSet
#   2005/03/10 12:51:51-08:00 willy@parisc-linux.org 
#   [PATCH] PA-RISC: define SHRREG
#   
#   Add definition of SHRREG
#   
#   Signed-off-by: Randolph Chung <tausq@parisc-linux.org>
#   Signed-off-by: Matthew Wilcox <willy@parisc-linux.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/asm-parisc/assembly.h
#   2005/03/10 09:18:18-08:00 willy@parisc-linux.org +1 -0
#   PA-RISC: define SHRREG
# 
# ChangeSet
#   2005/03/10 12:51:35-08:00 willy@parisc-linux.org 
#   [PATCH] PA-RISC unwind updates
#   
#    - Update stale url to documentation
#   
#   From: Kyle McMartin <kyle@parisc-linux.org>
#   
#    - Make unwinding from modules work, mostly
#    - Fix unwinding from millicode
#   
#   Signed-off-by: Randolph Chung <tausq@debian.org>
#   
#   Signed-off-by: Matthew Wilcox <willy@parisc-linux.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/asm-parisc/unwind.h
#   2005/03/08 11:16:19-08:00 willy@parisc-linux.org +11 -6
#   PA-RISC unwind updates
# 
# include/asm-parisc/module.h
#   2005/03/08 11:16:18-08:00 willy@parisc-linux.org +4 -0
#   PA-RISC unwind updates
# 
# arch/parisc/kernel/unwind.c
#   2005/03/08 11:15:56-08:00 willy@parisc-linux.org +67 -28
#   PA-RISC unwind updates
# 
# arch/parisc/kernel/module.c
#   2005/03/08 11:15:55-08:00 willy@parisc-linux.org +59 -3
#   PA-RISC unwind updates
# 
# ChangeSet
#   2005/03/10 12:43:54-08:00 torvalds@ppc970.osdl.org 
#   Merge bk://kernel.bkbits.net/vojtech/for-linus
#   into ppc970.osdl.org:/home/torvalds/v2.6/linux
# 
# Documentation/kernel-parameters.txt
#   2005/03/10 12:43:48-08:00 torvalds@ppc970.osdl.org +0 -0
#   Auto merged
# 
# ChangeSet
#   2005/03/10 20:18:55+00:00 lucasvr@org.rmk.(none) 
#   [ARM PATCH] 2528/1: S3C2410 - modifies S3C2410_{VA,SZ} to S3C24XX_{VA,SZ}
#   
#   Patch from Lucas Correia Villa Real
#   
#   This patch modifies ocurrences of S3C2410_{VA,SZ} to S3C24XX_{VA,SZ},
#   as well as defining S3C2400 physical mappings on
#   include/asm-arm/arch-s3c2410/map.h.
#   
#   This cleans up the naming of the virtual address macros, which are
#   fixed for all S3C24XX systems. This should clean up any confusion
#   about whether the virtual addresses are specific to the CPU or to
#   the arch.
#   
#   Signed-off-by: Lucas Correia Villa Real
#   Signed-off-by: Ben Dooks
#   Signed-off-by: Russell King
# 
# include/asm-arm/arch-s3c2410/regs-watchdog.h
#   2005/03/10 05:19:43+00:00 lucasvr@org.rmk.(none) +2 -1
#   [PATCH] 2528/1: S3C2410 - modifies S3C2410_{VA,SZ} to S3C24XX_{VA,SZ}
# 
# include/asm-arm/arch-s3c2410/regs-udc.h
#   2005/03/10 05:20:05+00:00 lucasvr@org.rmk.(none) +2 -1
#   [PATCH] 2528/1: S3C2410 - modifies S3C2410_{VA,SZ} to S3C24XX_{VA,SZ}
# 
# include/asm-arm/arch-s3c2410/regs-timer.h
#   2005/03/10 05:18:23+00:00 lucasvr@org.rmk.(none) +2 -1
#   [PATCH] 2528/1: S3C2410 - modifies S3C2410_{VA,SZ} to S3C24XX_{VA,SZ}
# 
# include/asm-arm/arch-s3c2410/regs-serial.h
#   2005/03/10 05:18:00+00:00 lucasvr@org.rmk.(none) +6 -3
#   [PATCH] 2528/1: S3C2410 - modifies S3C2410_{VA,SZ} to S3C24XX_{VA,SZ}
# 
# include/asm-arm/arch-s3c2410/regs-rtc.h
#   2005/03/10 04:33:49+00:00 lucasvr@org.rmk.(none) +2 -1
#   [PATCH] 2528/1: S3C2410 - modifies S3C2410_{VA,SZ} to S3C24XX_{VA,SZ}
# 
# include/asm-arm/arch-s3c2410/regs-mem.h
#   2005/03/10 05:16:33+00:00 lucasvr@org.rmk.(none) +2 -1
#   [PATCH] 2528/1: S3C2410 - modifies S3C2410_{VA,SZ} to S3C24XX_{VA,SZ}
# 
# include/asm-arm/arch-s3c2410/regs-lcd.h
#   2005/03/10 05:15:50+00:00 lucasvr@org.rmk.(none) +2 -1
#   [PATCH] 2528/1: S3C2410 - modifies S3C2410_{VA,SZ} to S3C24XX_{VA,SZ}
# 
# include/asm-arm/arch-s3c2410/regs-irq.h
#   2005/03/10 05:15:58+00:00 lucasvr@org.rmk.(none) +3 -2
#   [PATCH] 2528/1: S3C2410 - modifies S3C2410_{VA,SZ} to S3C24XX_{VA,SZ}
# 
# include/asm-arm/arch-s3c2410/regs-gpio.h
#   2005/03/10 05:13:20+00:00 lucasvr@org.rmk.(none) +3 -2
#   [PATCH] 2528/1: S3C2410 - modifies S3C2410_{VA,SZ} to S3C24XX_{VA,SZ}
# 
# include/asm-arm/arch-s3c2410/regs-clock.h
#   2005/03/10 05:14:35+00:00 lucasvr@org.rmk.(none) +8 -7
#   [PATCH] 2528/1: S3C2410 - modifies S3C2410_{VA,SZ} to S3C24XX_{VA,SZ}
# 
# include/asm-arm/arch-s3c2410/map.h
#   2005/03/10 04:47:46+00:00 lucasvr@org.rmk.(none) +76 -42
#   [PATCH] 2528/1: S3C2410 - modifies S3C2410_{VA,SZ} to S3C24XX_{VA,SZ}
# 
# include/asm-arm/arch-s3c2410/io.h
#   2005/03/10 05:12:41+00:00 lucasvr@org.rmk.(none) +5 -4
#   [PATCH] 2528/1: S3C2410 - modifies S3C2410_{VA,SZ} to S3C24XX_{VA,SZ}
# 
# include/asm-arm/arch-s3c2410/entry-macro.S
#   2005/03/10 05:12:03+00:00 lucasvr@org.rmk.(none) +6 -3
#   [PATCH] 2528/1: S3C2410 - modifies S3C2410_{VA,SZ} to S3C24XX_{VA,SZ}
# 
# include/asm-arm/arch-s3c2410/debug-macro.S
#   2005/03/10 05:11:37+00:00 lucasvr@org.rmk.(none) +5 -3
#   [PATCH] 2528/1: S3C2410 - modifies S3C2410_{VA,SZ} to S3C24XX_{VA,SZ}
# 
# drivers/serial/s3c2410.c
#   2005/03/10 05:27:21+00:00 lucasvr@org.rmk.(none) +6 -4
#   [PATCH] 2528/1: S3C2410 - modifies S3C2410_{VA,SZ} to S3C24XX_{VA,SZ}
# 
# drivers/char/watchdog/s3c2410_wdt.c
#   2005/03/10 05:10:55+00:00 lucasvr@org.rmk.(none) +4 -2
#   [PATCH] 2528/1: S3C2410 - modifies S3C2410_{VA,SZ} to S3C24XX_{VA,SZ}
# 
# drivers/char/s3c2410-rtc.c
#   2005/03/10 05:09:35+00:00 lucasvr@org.rmk.(none) +3 -2
#   [PATCH] 2528/1: S3C2410 - modifies S3C2410_{VA,SZ} to S3C24XX_{VA,SZ}
# 
# arch/arm/mach-s3c2410/pm.c
#   2005/03/10 05:08:51+00:00 lucasvr@org.rmk.(none) +8 -3
#   [PATCH] 2528/1: S3C2410 - modifies S3C2410_{VA,SZ} to S3C24XX_{VA,SZ}
# 
# arch/arm/mach-s3c2410/mach-vr1000.c
#   2005/03/10 04:58:19+00:00 lucasvr@org.rmk.(none) +4 -3
#   [PATCH] 2528/1: S3C2410 - modifies S3C2410_{VA,SZ} to S3C24XX_{VA,SZ}
# 
# arch/arm/mach-s3c2410/mach-smdk2440.c
#   2005/03/10 05:23:36+00:00 lucasvr@org.rmk.(none) +8 -7
#   [PATCH] 2528/1: S3C2410 - modifies S3C2410_{VA,SZ} to S3C24XX_{VA,SZ}
# 
# arch/arm/mach-s3c2410/mach-smdk2410.c
#   2005/03/10 04:59:07+00:00 lucasvr@org.rmk.(none) +4 -1
#   [PATCH] 2528/1: S3C2410 - modifies S3C2410_{VA,SZ} to S3C24XX_{VA,SZ}
# 
# arch/arm/mach-s3c2410/mach-rx3715.c
#   2005/03/10 04:57:49+00:00 lucasvr@org.rmk.(none) +8 -7
#   [PATCH] 2528/1: S3C2410 - modifies S3C2410_{VA,SZ} to S3C24XX_{VA,SZ}
# 
# arch/arm/mach-s3c2410/mach-n30.c
#   2005/03/10 04:59:46+00:00 lucasvr@org.rmk.(none) +4 -1
#   [PATCH] 2528/1: S3C2410 - modifies S3C2410_{VA,SZ} to S3C24XX_{VA,SZ}
# 
# arch/arm/mach-s3c2410/mach-h1940.c
#   2005/03/10 04:57:19+00:00 lucasvr@org.rmk.(none) +2 -1
#   [PATCH] 2528/1: S3C2410 - modifies S3C2410_{VA,SZ} to S3C24XX_{VA,SZ}
# 
# arch/arm/mach-s3c2410/mach-bast.c
#   2005/03/10 04:56:40+00:00 lucasvr@org.rmk.(none) +4 -3
#   [PATCH] 2528/1: S3C2410 - modifies S3C2410_{VA,SZ} to S3C24XX_{VA,SZ}
# 
# arch/arm/mach-s3c2410/devs.c
#   2005/03/10 04:53:48+00:00 lucasvr@org.rmk.(none) +10 -9
#   [PATCH] 2528/1: S3C2410 - modifies S3C2410_{VA,SZ} to S3C24XX_{VA,SZ}
# 
# arch/arm/mach-s3c2410/cpu.h
#   2005/03/10 04:53:30+00:00 lucasvr@org.rmk.(none) +2 -1
#   [PATCH] 2528/1: S3C2410 - modifies S3C2410_{VA,SZ} to S3C24XX_{VA,SZ}
# 
# ChangeSet
#   2005/03/10 20:11:58+00:00 ben-linux@org.rmk.(none) 
#   [ARM PATCH] 2527/1: S3C2410 - update regs-iis.h with fifo and s3c2440
#   
#   Patch from Ben Dooks
#   
#   Add definitions for getting FIFO usage information
#   and the small difference for using the s3c2440.
#   
#   Signed-off-by: Ben Dooks
#   Signed-off-by: Russell King
# 
# include/asm-arm/arch-s3c2410/regs-iis.h
#   2005/03/10 11:20:09+00:00 ben-linux@org.rmk.(none) +8 -3
#   [PATCH] 2527/1: S3C2410 - update regs-iis.h with fifo and s3c2440
# 
# ChangeSet
#   2005/03/10 12:06:29-08:00 davem@sunset.davemloft.net 
#   Merge bk://212.42.230.204:994/nf-2.6
#   into sunset.davemloft.net:/home/davem/src/BK/net-2.6
# 
# net/ipv4/netfilter/ipt_hashlimit.c
#   2005/03/10 12:06:22-08:00 davem@sunset.davemloft.net +0 -0
#   Auto merged
# 
# ChangeSet
#   2005/03/10 20:32:04+01:00 vojtech@suse.cz 
#   Manual merge
# 
# drivers/usb/input/hid-core.c
#   2005/03/10 20:31:59+01:00 vojtech@suse.cz +1 -3
#   Manual merge
# 
# sound/oss/esssolo1.c
#   2005/03/10 20:27:01+01:00 vojtech@suse.cz +0 -0
#   Auto merged
# 
# sound/oss/es1370.c
#   2005/03/10 20:27:01+01:00 vojtech@suse.cz +0 -0
#   Auto merged
# 
# sound/oss/cmpci.c
#   2005/03/10 20:27:01+01:00 vojtech@suse.cz +0 -0
#   Auto merged
# 
# drivers/usb/input/wacom.c
#   2005/03/10 20:27:01+01:00 vojtech@suse.cz +0 -0
#   Auto merged
# 
# drivers/usb/input/powermate.c
#   2005/03/10 20:27:01+01:00 vojtech@suse.cz +0 -0
#   Auto merged
# 
# drivers/usb/input/mtouchusb.c
#   2005/03/10 20:27:00+01:00 vojtech@suse.cz +0 -0
#   Auto merged
# 
# drivers/usb/input/ati_remote.c
#   2005/03/10 20:27:00+01:00 vojtech@suse.cz +0 -0
#   Auto merged
# 
# drivers/char/keyboard.c
#   2005/03/10 20:27:00+01:00 vojtech@suse.cz +0 -0
#   Auto merged
# 
# drivers/Makefile
#   2005/03/10 20:27:00+01:00 vojtech@suse.cz +0 -0
#   Auto merged
# 
# Documentation/kernel-parameters.txt
#   2005/03/10 20:27:00+01:00 vojtech@suse.cz +0 -0
#   Auto merged
# 
# ChangeSet
#   2005/03/10 11:13:11-08:00 davem@sunset.davemloft.net 
#   Merge
# 
# include/net/dst.h
#   2005/03/10 11:13:09-08:00 davem@sunset.davemloft.net +0 -0
#   SCCS merged
# 
# ChangeSet
#   2005/03/10 10:33:12-08:00 torvalds@ppc970.osdl.org 
#   Merge bk://drm.bkbits.net/drm-linus
#   into ppc970.osdl.org:/home/torvalds/v2.6/linux
# 
# MAINTAINERS
#   2005/03/10 10:33:06-08:00 torvalds@ppc970.osdl.org +0 -0
#   Auto merged
# 
# ChangeSet
#   2005/03/10 10:22:15-08:00 benh@kernel.crashing.org 
#   [PATCH] ppc64: fix iounmap TLB flushes
#   
#   This patch fixes a bug in ppc64 local implementation of iounmap() that
#   would cause it to incorrectly flush the hash table since the changes to
#   set_pte have been applied.
#   
#   Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/ppc64/mm/init.c
#   2005/03/09 17:59:50-08:00 benh@kernel.crashing.org +6 -4
#   ppc64: fix iounmap TLB flushes
# 
# ChangeSet
#   2005/03/10 10:09:50-08:00 torvalds@ppc970.osdl.org 
#   Remove empty file left over from dead cpufreq /proc interface
# 
# BitKeeper/deleted/.del-proc_intf.c~7f5d623623b4f1db
#   2005/03/10 10:09:01-08:00 torvalds@ppc970.osdl.org +0 -0
#   Delete: drivers/cpufreq/proc_intf.c
# 
# ChangeSet
#   2005/03/10 10:05:36-08:00 torvalds@ppc970.osdl.org 
#   make Geode FB driver depend on X86
#   
#   There seems little point in doing otherwise.
# 
# drivers/video/geode/Kconfig
#   2005/03/10 10:05:27-08:00 torvalds@ppc970.osdl.org +1 -1
#   make Geode FB driver depend on X86
# 
# ChangeSet
#   2005/03/10 09:20:53-08:00 agk@redhat.com 
#   [PATCH] device-mapper: Some multipath fn renames
#   
#   Rename ctr to create etc.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/md/dm-round-robin.c
#   2005/03/10 00:39:17-08:00 agk@redhat.com +4 -4
#   device-mapper: Some multipath fn renames
# 
# drivers/md/dm-path-selector.h
#   2005/03/10 00:39:17-08:00 agk@redhat.com +2 -2
#   device-mapper: Some multipath fn renames
# 
# drivers/md/dm-mpath.c
#   2005/03/10 00:39:17-08:00 agk@redhat.com +6 -6
#   device-mapper: Some multipath fn renames
# 
# drivers/md/dm-hw-handler.h
#   2005/03/10 00:39:17-08:00 agk@redhat.com +4 -3
#   device-mapper: Some multipath fn renames
# 
# drivers/md/dm-emc.c
#   2005/03/10 00:39:17-08:00 agk@redhat.com +6 -6
#   device-mapper: Some multipath fn renames
# 
# ChangeSet
#   2005/03/10 09:20:37-08:00 agk@redhat.com 
#   [PATCH] device-mapper: Some code/formatting cleanups
#   
#   Some multipath code/formatting cleanups
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/md/dm-round-robin.c
#   2005/03/10 00:39:17-08:00 agk@redhat.com +1 -1
#   device-mapper: Some code/formatting cleanups
# 
# drivers/md/dm-path-selector.h
#   2005/03/10 00:39:17-08:00 agk@redhat.com +42 -55
#   device-mapper: Some code/formatting cleanups
# 
# drivers/md/dm-path-selector.c
#   2005/03/10 00:39:17-08:00 agk@redhat.com +1 -1
#   device-mapper: Some code/formatting cleanups
# 
# drivers/md/dm-mpath.h
#   2005/03/10 00:39:17-08:00 agk@redhat.com +1 -1
#   device-mapper: Some code/formatting cleanups
# 
# drivers/md/dm-mpath.c
#   2005/03/10 00:39:17-08:00 agk@redhat.com +4 -4
#   device-mapper: Some code/formatting cleanups
# 
# drivers/md/dm-hw-handler.h
#   2005/03/10 00:39:17-08:00 agk@redhat.com +9 -17
#   device-mapper: Some code/formatting cleanups
# 
# drivers/md/dm-emc.c
#   2005/03/10 00:39:17-08:00 agk@redhat.com +4 -8
#   device-mapper: Some code/formatting cleanups
# 
# ChangeSet
#   2005/03/10 09:20:21-08:00 agk@redhat.com 
#   [PATCH] device-mapper: tag multipath exports GPL
#   
#   Tag multipath exports GPL.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/md/dm-path-selector.c
#   2005/03/10 00:39:16-08:00 agk@redhat.com +2 -2
#   device-mapper: tag multipath exports GPL
# 
# drivers/md/dm-mpath.c
#   2005/03/10 00:39:16-08:00 agk@redhat.com +1 -1
#   device-mapper: tag multipath exports GPL
# 
# drivers/md/dm-hw-handler.c
#   2005/03/10 00:39:16-08:00 agk@redhat.com +3 -3
#   device-mapper: tag multipath exports GPL
# 
# ChangeSet
#   2005/03/10 09:20:05-08:00 agk@redhat.com 
#   [PATCH] device-mapper: multipath hardware handler for EMC
#   
#   Outline Hardware Handler for EMC CLARiiON AX/CX-series.
#   
#   Signed-Off-By: Alasdair G Kergon <agk@redhat.com>
#   From: Lars Marowsky-Bree <lmb@suse.de>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/md/dm-emc.c
#   2005/03/10 00:39:16-08:00 agk@redhat.com +363 -0
#   device-mapper: multipath hardware handler for EMC
# 
# drivers/md/dm-emc.c
#   2005/03/10 00:39:16-08:00 agk@redhat.com +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/drivers/md/dm-emc.c
# 
# drivers/md/Makefile
#   2005/03/10 00:39:16-08:00 agk@redhat.com +1 -0
#   device-mapper: multipath hardware handler for EMC
# 
# drivers/md/Kconfig
#   2005/03/10 00:39:16-08:00 agk@redhat.com +6 -0
#   device-mapper: multipath hardware handler for EMC
# 
# ChangeSet
#   2005/03/10 09:19:48-08:00 agk@redhat.com 
#   [PATCH] device-mapper: multipath hardware handler
#   
#   Each multipath instance can use a Hardware Handler with hooks for the
#   particular hardware you're using.
#   
#   This patch provides the hw_handler infrastructure.
#   
#   So far 3 hooks are available:
#   
#     A status function invoked by device-mapper table and status requests.
#   
#     An initialisation function called when a Priority Group is selected for
#     use but before any I/O is sent to it.  This function should return straight
#     away, and I/O is queued until dm_pg_init_complete() is called indicating
#     whether or not the initialisation was successful.  The are three error
#     flags, any or all of which may be set: MP_FAIL_PATH, MP_BYPASS_PG,
#     MP_ERROR_IO.
#   
#     An error handler which gets the opportunity to decode any error that a bio
#     generated.  Patches are pending to make scsi error details available for
#     dm_scsi_err_handler() to decode.
#   
#   Signed-Off-By: Alasdair G Kergon <agk@redhat.com>
#   Signed-off-by: Adrian Bunk <bunk@stusta.de>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/md/dm-hw-handler.h
#   2005/03/10 01:51:15-08:00 agk@redhat.com +68 -0
#   device-mapper: multipath hardware handler
# 
# drivers/md/dm-mpath.h
#   2005/03/10 01:51:15-08:00 agk@redhat.com +4 -0
#   device-mapper: multipath hardware handler
# 
# drivers/md/dm-mpath.c
#   2005/03/10 01:51:15-08:00 agk@redhat.com +119 -3
#   device-mapper: multipath hardware handler
# 
# drivers/md/dm-hw-handler.h
#   2005/03/10 01:51:15-08:00 agk@redhat.com +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/drivers/md/dm-hw-handler.h
# 
# drivers/md/dm-hw-handler.c
#   2005/03/10 01:51:18-08:00 agk@redhat.com +216 -0
#   device-mapper: multipath hardware handler
# 
# drivers/md/Makefile
#   2005/03/10 01:51:15-08:00 agk@redhat.com +1 -1
#   device-mapper: multipath hardware handler
# 
# drivers/md/dm-hw-handler.c
#   2005/03/10 01:51:18-08:00 agk@redhat.com +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/drivers/md/dm-hw-handler.c
# 
# ChangeSet
#   2005/03/10 09:19:31-08:00 agk@redhat.com 
#   [PATCH] device-mapper: multipath round-robin path selector.
#   
#   A very basic path selector: round-robin.
#   
#   It uses in turn each path that has not been disabled.
#   
#   By default, it instructs core multipath to use each path it supplies for 1000
#   bios, but a different repeat_count can be set against any path to provide
#   primitive load-balancing across unequal paths.
#   
#   Signed-Off-By: Alasdair G Kergon <agk@redhat.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/md/dm-round-robin.c
#   2005/03/10 00:39:15-08:00 agk@redhat.com +214 -0
#   device-mapper: multipath round-robin path selector.
# 
# drivers/md/Makefile
#   2005/03/10 00:39:15-08:00 agk@redhat.com +1 -1
#   device-mapper: multipath round-robin path selector.
# 
# drivers/md/dm-round-robin.c
#   2005/03/10 00:39:15-08:00 agk@redhat.com +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/drivers/md/dm-round-robin.c
# 
# ChangeSet
#   2005/03/10 09:19:15-08:00 agk@redhat.com 
#   [PATCH] device-mapper: multipath
#   
#   The core device-mapper multipath and path-selector code.
#   
#   Paths are grouped into an ordered list of Priority Groups.  Each Priority
#   Group has a Path Selector which chooses which of the Priority Group's paths is
#   to be used for each bio e.g.  according to some load-balancing algorithm.  If
#   a bio generates an error, the path that it used gets disabled and an
#   alternative path is tried.  If all the paths in a Priority Group fail, another
#   Priority Group is selected.
#   
#   There are management commands fail_path and reinstate_path.  A path tester
#   (currently implemented in userspace) is responsible for monitoring paths that
#   have failed and reinstating them should they come back.
#   
#   Other management commands can be use to switch immediately to a specified
#   Priority Group or to disable a particular Priority Group so it will only be
#   tried after there are no more left.
#   
#   As a last resort there is an option to 'queue_if_no_path' which queues I/O if
#   all paths have failed e.g.  temporarily during a firmware update or if the
#   userspace daemon is slow reinstating paths.
#   
#   The userspace multipath tools are available at:
#     http://christophe.varoqui.free.fr/
#   macroflux.png is a diagram of the current architecture.
#   
#   From: Alasdair G Kergon <agk@redhat.com>
#   
#     Don't requeue I/O repeatedly if there are no paths left and the device is
#     in the process of being suspended, or else the suspend can never complete.
#   
#   Reported-By: "goggin, edward" <egoggin@emc.com>
#   Signed-Off-By: Alasdair G Kergon <agk@redhat.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/md/dm-path-selector.h
#   2005/03/10 01:50:35-08:00 agk@redhat.com +106 -0
#   device-mapper: multipath
# 
# drivers/md/dm-path-selector.c
#   2005/03/10 01:50:35-08:00 agk@redhat.com +156 -0
#   device-mapper: multipath
# 
# drivers/md/dm-mpath.h
#   2005/03/10 01:50:35-08:00 agk@redhat.com +21 -0
#   device-mapper: multipath
# 
# drivers/md/dm-mpath.c
#   2005/03/10 01:50:39-08:00 agk@redhat.com +1186 -0
#   device-mapper: multipath
# 
# drivers/md/Makefile
#   2005/03/10 01:50:35-08:00 agk@redhat.com +2 -0
#   device-mapper: multipath
# 
# drivers/md/Kconfig
#   2005/03/10 01:50:35-08:00 agk@redhat.com +6 -0
#   device-mapper: multipath
# 
# drivers/md/dm-path-selector.h
#   2005/03/10 01:50:35-08:00 agk@redhat.com +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/drivers/md/dm-path-selector.h
# 
# drivers/md/dm-path-selector.c
#   2005/03/10 01:50:35-08:00 agk@redhat.com +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/drivers/md/dm-path-selector.c
# 
# drivers/md/dm-mpath.h
#   2005/03/10 01:50:35-08:00 agk@redhat.com +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/drivers/md/dm-mpath.h
# 
# drivers/md/dm-mpath.c
#   2005/03/10 01:50:39-08:00 agk@redhat.com +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/drivers/md/dm-mpath.c
# 
# ChangeSet
#   2005/03/10 09:18:57-08:00 agk@redhat.com 
#   [PATCH] device-mapper: Export map_info
#   
#   Export map_info (part of bio->bi_private) for targets like multipath to use
#   for storing context.
#   
#   Signed-Off-By: Alasdair G Kergon <agk@redhat.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/md/dm.h
#   2005/03/10 00:39:15-08:00 agk@redhat.com +1 -0
#   device-mapper: Export map_info
# 
# drivers/md/dm.c
#   2005/03/10 00:39:15-08:00 agk@redhat.com +9 -0
#   device-mapper: Export map_info
# 
# ChangeSet
#   2005/03/10 09:18:42-08:00 agk@redhat.com 
#   [PATCH] device-mapper: Record & restore bio state.
#   
#   Simple functions to record and restore bio state so we can resubmit a bio
#   that returned an error.
#   
#   DM multipath (following shortly) uses this.
#   
#   This patch has it private to device-mapper: is it any use elsewhere?
#   
#   Signed-Off-By: Alasdair G Kergon <agk@redhat.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/md/dm-bio-record.h
#   2005/03/10 00:39:14-08:00 agk@redhat.com +45 -0
#   device-mapper: Record & restore bio state.
# 
# drivers/md/dm-bio-record.h
#   2005/03/10 00:39:14-08:00 agk@redhat.com +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/drivers/md/dm-bio-record.h
# 
# ChangeSet
#   2005/03/10 09:18:24-08:00 lmb@suse.de 
#   [PATCH] device-mapper: Store name directly against device
#   
#   Add a name field to struct dm_dev so we don't have to use format_dev_t()
#   all over the place for informative error messages.
#   
#   Signed-Off-By: Alasdair G Kergon <agk@redhat.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/md/dm.h
#   2005/03/10 00:39:14-08:00 lmb@suse.de +1 -0
#   device-mapper: Store name directly against device
# 
# drivers/md/dm-table.c
#   2005/03/10 00:39:14-08:00 lmb@suse.de +2 -0
#   device-mapper: Store name directly against device
# 
# drivers/md/dm-stripe.c
#   2005/03/10 00:39:14-08:00 lmb@suse.de +2 -5
#   device-mapper: Store name directly against device
# 
# drivers/md/dm-snap.c
#   2005/03/10 00:39:14-08:00 lmb@suse.de +3 -8
#   device-mapper: Store name directly against device
# 
# drivers/md/dm-raid1.c
#   2005/03/10 00:39:14-08:00 lmb@suse.de +4 -9
#   device-mapper: Store name directly against device
# 
# drivers/md/dm-linear.c
#   2005/03/10 00:39:14-08:00 lmb@suse.de +2 -3
#   device-mapper: Store name directly against device
# 
# drivers/md/dm-crypt.c
#   2005/03/10 00:39:14-08:00 lmb@suse.de +1 -3
#   device-mapper: Store name directly against device
# 
# ChangeSet
#   2005/03/10 09:18:09-08:00 rddunlap@osdl.org 
#   [PATCH] tdfxfb: eliminate bad section references
#   
#   Fix tdfxfb section references:
#     convert __initdata to __devinitdata.
#   
#   Error: ./drivers/video/tdfxfb.o .text refers to 0000000000000e6f R_X86_64_PC32     .init.data+0xfffffffffffffffc
#   Error: ./drivers/video/tdfxfb.o .text refers to 0000000000000fea R_X86_64_32S      .init.data+0x00000000000000c0
#   Error: ./drivers/video/tdfxfb.o .text refers to 0000000000001006 R_X86_64_32S      .init.data+0x00000000000000c0
#   Error: ./drivers/video/tdfxfb.o .text refers to 0000000000001022 R_X86_64_32S      .init.data+0x00000000000000c0
#   Error: ./drivers/video/tdfxfb.o .text refers to 000000000000103c R_X86_64_PC32     .init.data+0x00000000000000f4
#   Error: ./drivers/video/tdfxfb.o .text refers to 0000000000001067 R_X86_64_PC32     .init.data+0x00000000000000f4
#   Error: ./drivers/video/tdfxfb.o .text refers to 000000000000106f R_X86_64_PC32     .init.data+0x00000000000000fc
#   Error: ./drivers/video/tdfxfb.o .text refers to 0000000000001084 R_X86_64_32S      .init.data+0x00000000000000c0
#   Error: ./drivers/video/tdfxfb.o .text refers to 00000000000010f1 R_X86_64_PC32     .init.data+0x00000000000000cc
#   Error: ./drivers/video/tdfxfb.o .text refers to 00000000000011b8 R_X86_64_PC32     .init.data+0x00000000000000d4
#   Error: ./drivers/video/tdfxfb.o .text refers to 00000000000011c1 R_X86_64_32S      .init.data+0x00000000000000c0
#   Error: ./drivers/video/tdfxfb.o .text refers to 000000000000122b R_X86_64_PC32     .init.data+0x00000000000000d4
#   Error: ./drivers/video/tdfxfb.o .text refers to 0000000000001232 R_X86_64_PC32     .init.data+0x00000000000000cc
#   Error: ./drivers/video/tdfxfb.o .text refers to 000000000000124a R_X86_64_32S      .init.data+0x00000000000000c0
#   Error: ./drivers/video/tdfxfb.o .text refers to 0000000000001320 R_X86_64_PC32     .init.data+0x00000000000000d4
#   Error: ./drivers/video/tdfxfb.o .text refers to 0000000000001327 R_X86_64_32S      .init.data+0x00000000000000c0
#   Error: ./drivers/video/tdfxfb.o .text refers to 000000000000134c R_X86_64_32S      .init.data+0x00000000000000c0
#   Error: ./drivers/video/tdfxfb.o .text refers to 000000000000136a R_X86_64_PC32     .init.data+0x00000000000000e6
#   Error: ./drivers/video/tdfxfb.o .text refers to 000000000000137d R_X86_64_PC32     .init.data+0x00000000000000e8
#   Error: ./drivers/video/tdfxfb.o .text refers to 00000000000013b1 R_X86_64_PC32     .init.data+0xfffffffffffffffc
#   Error: ./drivers/video/tdfxfb.o .text refers to 00000000000013c5 R_X86_64_PC32     .init.data+0xfffffffffffffffc
#   Error: ./drivers/video/tdfxfb.o .text refers to 00000000000013e4 R_X86_64_32S      .init.data+0x0000000000000020
#   
#   Signed-off-by: Randy Dunlap <rddunlap@osdl.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/video/tdfxfb.c
#   2005/03/10 00:39:14-08:00 rddunlap@osdl.org +3 -3
#   tdfxfb: eliminate bad section references
# 
# ChangeSet
#   2005/03/10 09:17:52-08:00 rddunlap@osdl.org 
#   [PATCH] sis: eliminate bad section references
#   
#   Fix sis section reference:
#     change 2 __init functions to be __devinit.
#   
#   Error: ./drivers/video/sis/sis_main.o .text refers to 0000000000000b5b R_X86_64_PC32     .init.text+0xfffffffffffffffc
#   
#   Signed-off-by: Randy Dunlap <rddunlap@osdl.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# ChangeSet
#   2005/03/10 18:17:49+01:00 bzolnier@trik.(none) 
#   [ide] kill setup_driver_defaults()
#   
#   * move default_do_request() to ide-default.c
#   * fix drivers to set ide_driver_t->{do_request,end_request,error,abort}
#   * kill setup_driver_defaults()
#   
#   Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
# 
# drivers/video/sis/sis_main.c
#   2005/03/10 00:39:14-08:00 rddunlap@osdl.org +2 -2
#   sis: eliminate bad section references
# 
# drivers/ide/ide.c
#   2005/03/10 18:10:12+01:00 bzolnier@trik.(none) +0 -37
#   [ide] kill setup_driver_defaults()
# 
# drivers/ide/ide-tape.c
#   2005/03/10 18:10:12+01:00 bzolnier@trik.(none) +2 -0
#   [ide] kill setup_driver_defaults()
# 
# drivers/ide/ide-io.c
#   2005/03/10 18:10:12+01:00 bzolnier@trik.(none) +4 -0
#   [ide] kill setup_driver_defaults()
# 
# drivers/ide/ide-floppy.c
#   2005/03/10 18:10:12+01:00 bzolnier@trik.(none) +2 -0
#   [ide] kill setup_driver_defaults()
# 
# drivers/ide/ide-disk.c
#   2005/03/10 18:10:12+01:00 bzolnier@trik.(none) +3 -0
#   [ide] kill setup_driver_defaults()
# 
# drivers/ide/ide-default.c
#   2005/03/10 18:10:12+01:00 bzolnier@trik.(none) +10 -0
#   [ide] kill setup_driver_defaults()
# 
# drivers/ide/ide-cd.c
#   2005/03/10 18:10:12+01:00 bzolnier@trik.(none) +3 -0
#   [ide] kill setup_driver_defaults()
# 
# ChangeSet
#   2005/03/10 09:17:37-08:00 rddunlap@osdl.org 
#   [PATCH] riva: eliminate bad section references
#   
#   Fix riva sections references:
#     change __initdata to __devinitdata.
#   
#   Error: ./drivers/video/riva/fbdev.o .text refers to 0000000000001e64 R_X86_64_32S      .init.data+0x0000000000000020
#   Error: ./drivers/video/riva/fbdev.o .text refers to 0000000000001e6f R_X86_64_PC32     .init.data+0x0000000000000004
#   Error: ./drivers/video/riva/fbdev.o .text refers to 0000000000001e7c R_X86_64_PC32     .init.data+0x0000000000000003
#   Error: ./drivers/video/riva/fbdev.o .text refers to 0000000000001e93 R_X86_64_PC32     .init.data
#   Error: ./drivers/video/riva/fbdev.o .text refers to 0000000000001ec6 R_X86_64_PC32     .init.data+0x000000000000005c
#   Error: ./drivers/video/riva/fbdev.o .text refers to 0000000000001ef2 R_X86_64_PC32     .init.data+0x0000000000000034
#   Error: ./drivers/video/riva/fbdev.o .text refers to 0000000000001f38 R_X86_64_PC32     .init.data+0x000000000000005c
#   Error: ./drivers/video/riva/fbdev.o .text refers to 0000000000001f41 R_X86_64_PC32     .init.data+0x0000000000000054
#   Error: ./drivers/video/riva/fbdev.o .text refers to 0000000000001f4f R_X86_64_PC32     .init.data+0x000000000000002c
#   Error: ./drivers/video/riva/fbdev.o .text refers to 0000000000001f94 R_X86_64_PC32     .init.data+0x000000000000002c
#   Error: ./drivers/video/riva/fbdev.o .text refers to 000000000000201a R_X86_64_PC32     .init.data+0x0000000000000034
#   Error: ./drivers/video/riva/fbdev.o .text refers to 0000000000002035 R_X86_64_PC32     .init.data+0x0000000000000034
#   Error: ./drivers/video/riva/fbdev.o .text refers to 000000000000203c R_X86_64_PC32     .init.data+0x000000000000002c
#   Error: ./drivers/video/riva/fbdev.o .text refers to 000000000000206b R_X86_64_PC32     .init.data+0xfffffffffffffffb
#   Error: ./drivers/video/riva/fbdev.o .text refers to 0000000000002074 R_X86_64_PC32     .init.data+0x0000000000000034
#   Error: ./drivers/video/riva/fbdev.o .text refers to 000000000000207b R_X86_64_PC32     .init.data+0x000000000000002c
#   Error: ./drivers/video/riva/fbdev.o .text refers to 00000000000020e7 R_X86_64_32S      .init.data+0x0000000000000020
#   Error: ./drivers/video/riva/fbdev.o .text refers to 00000000000021cb R_X86_64_32S      .init.data+0x0000000000000080
#   Error: ./drivers/video/riva/fbdev.o .text refers to 000000000000220f R_X86_64_PC32     .init.data+0x000000000000011c
#   Error: ./drivers/video/riva/fbdev.o .text refers to 000000000000228e R_X86_64_32S      .init.data+0x0000000000000080
#   Error: ./drivers/video/riva/fbdev.o .text refers to 00000000000022ea R_X86_64_PC32     .init.data+0x0000000000000007
#   
#   Signed-off-by: Randy Dunlap <rddunlap@osdl.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/video/riva/fbdev.c
#   2005/03/10 00:39:13-08:00 rddunlap@osdl.org +7 -7
#   riva: eliminate bad section references
# 
# ChangeSet
#   2005/03/10 09:17:20-08:00 akpm@osdl.org 
#   [PATCH] fbdev-cleanups-in-driver-video warning fixes
#   
#   drivers/video/cyber2000fb.c:95: warning: `default_font_storage' defined but not used
#   drivers/video/radeonfb.c:661: warning: `mode_option' defined but not used
#   
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/video/radeonfb.c
#   2005/03/10 00:39:13-08:00 akpm@osdl.org +4 -1
#   fbdev-cleanups-in-driver-video warning fixes
# 
# ChangeSet
#   2005/03/10 09:17:05-08:00 rddunlap@osdl.org 
#   [PATCH] radeonfb: eliminate bad section references
#   
#   Fix radeonfb section references by changing __initdata
#     to __devinitdata.
#   
#   Error: ./drivers/video/radeonfb.o .text refers to 0000000000002037 R_X86_64_PC32     .init.data+0x0000000000000003
#   Error: ./drivers/video/radeonfb.o .text refers to 0000000000002491 R_X86_64_PC32     .init.data
#   Error: ./drivers/video/radeonfb.o .text refers to 0000000000002870 R_X86_64_PC32     .init.data+0x000000000000000c
#   Error: ./drivers/video/radeonfb.o .text refers to 0000000000002a21 R_X86_64_PC32     .init.data+0xfffffffffffffffb
#   
#   Signed-off-by: Randy Dunlap <rddunlap@osdl.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/video/radeonfb.c
#   2005/03/10 00:39:13-08:00 rddunlap@osdl.org +4 -4
#   radeonfb: eliminate bad section references
# 
# ChangeSet
#   2005/03/10 09:16:49-08:00 rddunlap@osdl.org 
#   [PATCH] pm2fb: eliminate bad section references
#   
#   Fix pm2fb section references by changing referenced
#     __initdata to __devinitdata.
#   
#   Error: ./drivers/video/pm2fb.o .text refers to 0000000000000ad4 R_X86_64_PC32     .init.data+0x0000000000000007
#   Error: ./drivers/video/pm2fb.o .text refers to 0000000000000afc R_X86_64_PC32     .init.data+0x0000000000000003
#   Error: ./drivers/video/pm2fb.o .text refers to 000000000000147e R_X86_64_PC32     .init.data+0x00000000000000bc
#   Error: ./drivers/video/pm2fb.o .text refers to 0000000000001491 R_X86_64_PC32     .init.data+0x00000000000000c2
#   Error: ./drivers/video/pm2fb.o .text refers to 000000000000149a R_X86_64_PC32     .init.data+0x00000000000000bc
#   Error: ./drivers/video/pm2fb.o .text refers to 00000000000014aa R_X86_64_32S      .init.data+0x00000000000000c0
#   Error: ./drivers/video/pm2fb.o .text refers to 00000000000014e0 R_X86_64_PC32     .init.data+0x00000000000000f8
#   Error: ./drivers/video/pm2fb.o .text refers to 00000000000014eb R_X86_64_PC32     .init.data+0x00000000000000f4
#   Error: ./drivers/video/pm2fb.o .text refers to 000000000000150e R_X86_64_PC32     .init.data+0x00000000000000fc
#   Error: ./drivers/video/pm2fb.o .text refers to 0000000000001515 R_X86_64_PC32     .init.data+0x00000000000000f4
#   Error: ./drivers/video/pm2fb.o .text refers to 000000000000152d R_X86_64_32S      .init.data+0x00000000000000c0
#   Error: ./drivers/video/pm2fb.o .text refers to 00000000000015ce R_X86_64_PC32     .init.data+0x00000000000000cc
#   Error: ./drivers/video/pm2fb.o .text refers to 00000000000015d7 R_X86_64_PC32     .init.data+0x00000000000000d4
#   Error: ./drivers/video/pm2fb.o .text refers to 00000000000015fa R_X86_64_PC32     .init.data+0x00000000000000d4
#   Error: ./drivers/video/pm2fb.o .text refers to 0000000000001601 R_X86_64_PC32     .init.data+0x00000000000000cc
#   Error: ./drivers/video/pm2fb.o .text refers to 0000000000001644 R_X86_64_32S      .init.data+0x00000000000000c0
#   Error: ./drivers/video/pm2fb.o .text refers to 0000000000001674 R_X86_64_PC32     .init.data+0xfffffffffffffffc
#   Error: ./drivers/video/pm2fb.o .text refers to 000000000000168e R_X86_64_PC32     .init.data+0xfffffffffffffffc
#   Error: ./drivers/video/pm2fb.o .text refers to 00000000000016af R_X86_64_32S      .init.data+0x0000000000000020
#   Error: ./drivers/video/pm2fb.o .text refers to 0000000000001724 R_X86_64_PC32     .init.data+0x00000000000000d4
#   Error: ./drivers/video/pm2fb.o .text refers to 000000000000172b R_X86_64_PC32     .init.data+0x00000000000000cc
#   Error: ./drivers/video/pm2fb.o .text refers to 0000000000001746 R_X86_64_PC32     .init.data+0x00000000000000fc
#   Error: ./drivers/video/pm2fb.o .text refers to 000000000000174d R_X86_64_PC32     .init.data+0x00000000000000f4
#   
#   Signed-off-by: Randy Dunlap <rddunlap@osdl.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/video/pm2fb.c
#   2005/03/10 00:39:13-08:00 rddunlap@osdl.org +5 -5
#   pm2fb: eliminate bad section references
# 
# ChangeSet
#   2005/03/10 09:16:33-08:00 rddunlap@osdl.org 
#   [PATCH] neofb: eliminate bad section references
#   
#   Fix neofb section reference to __initdata: make it __devinitdata.
#   
#   Error: ./drivers/video/neofb.o .text refers to 0000000000001fb4 R_X86_64_PC32     .init.data+0xfffffffffffffffc
#   
#   Signed-off-by: Randy Dunlap <rddunlap@osdl.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/video/neofb.c
#   2005/03/10 00:39:12-08:00 rddunlap@osdl.org +1 -1
#   neofb: eliminate bad section references
# 
# ChangeSet
#   2005/03/10 09:16:18-08:00 rddunlap@osdl.org 
#   [PATCH] kyro: eliminate bad section references
#   
#   Fix kyro sections references by changing __initdata
#     to __devinitdata.
#   
#   Error: ./drivers/video/kyro/fbdev.o .text refers to 0000000000000692 R_X86_64_PC32     .init.data+0x000000000000090c
#   Error: ./drivers/video/kyro/fbdev.o .text refers to 00000000000006c2 R_X86_64_PC32     .init.data+0x0000000000000914
#   Error: ./drivers/video/kyro/fbdev.o .text refers to 00000000000006d1 R_X86_64_PC32     .init.data+0x0000000000000934
#   Error: ./drivers/video/kyro/fbdev.o .text refers to 0000000000000709 R_X86_64_PC32     .init.data+0x0000000000000934
#   Error: ./drivers/video/kyro/fbdev.o .text refers to 0000000000000711 R_X86_64_PC32     .init.data+0x000000000000093c
#   Error: ./drivers/video/kyro/fbdev.o .text refers to 0000000000000727 R_X86_64_PC32     .init.data+0x000000000000090c
#   Error: ./drivers/video/kyro/fbdev.o .text refers to 000000000000072d R_X86_64_PC32     .init.data+0x0000000000000914
#   Error: ./drivers/video/kyro/fbdev.o .text refers to 000000000000073f R_X86_64_PC32     .init.data+0x00000000000008eb
#   Error: ./drivers/video/kyro/fbdev.o .text refers to 0000000000000748 R_X86_64_PC32     .init.data+0x0000000000000914
#   Error: ./drivers/video/kyro/fbdev.o .text refers to 000000000000075b R_X86_64_PC32     .init.data+0x000000000000090c
#   Error: ./drivers/video/kyro/fbdev.o .text refers to 0000000000000778 R_X86_64_32S      .init.data+0x0000000000000900
#   Error: ./drivers/video/kyro/fbdev.o .text refers to 000000000000077e R_X86_64_PC32     .init.data+0x00000000000008e7
#   Error: ./drivers/video/kyro/fbdev.o .text refers to 0000000000000793 R_X86_64_PC32     .init.data+0x0000000000000926
#   Error: ./drivers/video/kyro/fbdev.o .text refers to 000000000000079b R_X86_64_PC32     .init.data+0x00000000000008e3
#   Error: ./drivers/video/kyro/fbdev.o .text refers to 00000000000007a6 R_X86_64_PC32     .init.data+0x0000000000000928
#   Error: ./drivers/video/kyro/fbdev.o .text refers to 00000000000007f1 R_X86_64_PC32     .init.data+0x00000000000008dc
#   Error: ./drivers/video/kyro/fbdev.o .text refers to 00000000000007f8 R_X86_64_32S      .init.data+0x0000000000000420
#   Error: ./drivers/video/kyro/fbdev.o .text refers to 0000000000000805 R_X86_64_32S      .init.data+0x00000000000000a0
#   Error: ./drivers/video/kyro/fbdev.o .text refers to 0000000000000834 R_X86_64_32S      .init.data
#   
#   Signed-off-by: Randy Dunlap <rddunlap@osdl.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/video/kyro/fbdev.c
#   2005/03/10 00:39:12-08:00 rddunlap@osdl.org +7 -7
#   kyro: eliminate bad section references
# 
# ChangeSet
#   2005/03/10 09:16:02-08:00 rddunlap@osdl.org 
#   [PATCH] imsttfb: eliminate bad section references
#   
#   Fix imsttfb section references:  change __initdata to __devinitdata
#     and __init to __devinit.
#   
#   Error: ./drivers/video/imsttfb.o .text refers to 000000000000103b R_X86_64_32S      .init.data+0x0000000000000040
#   Error: ./drivers/video/imsttfb.o .text refers to 0000000000001049 R_X86_64_32S      .init.data+0x0000000000000041
#   Error: ./drivers/video/imsttfb.o .text refers to 0000000000001064 R_X86_64_32S      .init.data
#   Error: ./drivers/video/imsttfb.o .text refers to 0000000000001071 R_X86_64_32S      .init.data+0x0000000000000001
#   
#   Signed-off-by: Randy Dunlap <rddunlap@osdl.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/video/imsttfb.c
#   2005/03/10 00:39:12-08:00 rddunlap@osdl.org +4 -4
#   imsttfb: eliminate bad section references
# 
# ChangeSet
#   2005/03/10 09:15:46-08:00 rddunlap@osdl.org 
#   [PATCH] atyfb: eliminate bad section references
#   
#   Fix atyfb references to __initdata from .text code sections
#     by changing __initdata to __devinitdata.
#   
#   Error: ./drivers/video/aty/atyfb_base.o .text refers to 0000000000002416 R_X86_64_32S      .init.data+0x00000000000004a0
#   Error: ./drivers/video/aty/atyfb_base.o .text refers to 0000000000002514 R_X86_64_32S      .init.data
#   Error: ./drivers/video/aty/atyfb_base.o .text refers to 000000000000253e R_X86_64_32S      .init.data+0x0000000000000060
#   Error: ./drivers/video/aty/atyfb_base.o .text refers to 00000000000026c4 R_X86_64_32S      .init.data+0x00000000000004a0
#   Error: ./drivers/video/aty/atyfb_base.o .text refers to 00000000000026e7 R_X86_64_32S      .init.data+0x0000000000000070
#   Error: ./drivers/video/aty/atyfb_base.o .text refers to 00000000000026ee R_X86_64_32S      .init.data+0x0000000000000068
#   Error: ./drivers/video/aty/atyfb_base.o .text refers to 00000000000026fa R_X86_64_32S      .init.data+0x0000000000000074
#   Error: ./drivers/video/aty/atyfb_base.o .text refers to 0000000000002706 R_X86_64_32S      .init.data+0x0000000000000078
#   Error: ./drivers/video/aty/atyfb_base.o .text refers to 0000000000002712 R_X86_64_32S      .init.data+0x000000000000007c
#   Error: ./drivers/video/aty/atyfb_base.o .text refers to 0000000000002afb R_X86_64_32S      .init.data+0x0000000000000560
#   Error: ./drivers/video/aty/atyfb_base.o .text refers to 0000000000002baa R_X86_64_32S      .init.data+0x00000000000004c0
#   
#   Signed-off-by: Randy Dunlap <rddunlap@osdl.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/video/aty/atyfb_base.c
#   2005/03/10 00:39:11-08:00 rddunlap@osdl.org +12 -12
#   atyfb: eliminate bad section references
# 
# ChangeSet
#   2005/03/10 09:15:30-08:00 rddunlap@osdl.org 
#   [PATCH] asiliantfb: eliminate bad section references
#   
#   asiliantfb refers to __initdata that should be __devinitdata
#     and calls __init functions that should be __devinit;
#   
#   Error: ./drivers/video/asiliantfb.o .text refers to 00000000000006ee R_X86_64_32S      .init.data+0x00000000000000a0
#   Error: ./drivers/video/asiliantfb.o .text refers to 0000000000000711 R_X86_64_32S      .init.data
#   
#   Signed-off-by: Randy Dunlap <rddunlap@osdl.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/video/asiliantfb.c
#   2005/03/10 00:39:11-08:00 rddunlap@osdl.org +4 -4
#   asiliantfb: eliminate bad section references
# 
# ChangeSet
#   2005/03/10 09:15:13-08:00 benh@kernel.crashing.org 
#   [PATCH] radeonfb: PLL access workaround
#   
#   So you remember all those weird lockups at boot that happened in late
#   2.6.11-rc with radeonfb.  I posted a "workaround" which just moved code
#   around a bit and it appeared to work.  I finally got some real infos about
#   the problem from ATI, and it seems my "workaround" is not very safe and
#   there are other potential issues realted to HW bugs when accessing the PLL
#   registers.
#   
#   This patch implements all of these workarounds (and puts back the code
#   where it was before my previous fix).  
#   
#   Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/video/aty/radeonfb.h
#   2005/03/10 00:39:11-08:00 benh@kernel.crashing.org +35 -51
#   radeonfb: PLL access workaround
# 
# drivers/video/aty/radeon_pm.c
#   2005/03/10 00:39:11-08:00 benh@kernel.crashing.org +20 -6
#   radeonfb: PLL access workaround
# 
# drivers/video/aty/radeon_monitor.c
#   2005/03/10 00:39:11-08:00 benh@kernel.crashing.org +8 -2
#   radeonfb: PLL access workaround
# 
# drivers/video/aty/radeon_base.c
#   2005/03/10 00:39:11-08:00 benh@kernel.crashing.org +25 -7
#   radeonfb: PLL access workaround
# 
# ChangeSet
#   2005/03/10 09:14:57-08:00 adaplas@hotpop.com 
#   [PATCH] fbdev: Cleanups in driver/video
#   
#   This patch contains cleanups including the following:
#   - make needlessly global code static
#   - remove the needlessly #ifdef MODULE from several module_exit
#   - remove or #if 0 the following unused global functions:
#     - fbmon.c: fb_create_modedb
#     - fbmon.c: fb_get_monitor_limits
#     - nvidia/nv_i2c.c: nvidia_delete_i2c_busses
#     - nvidia/nv_setup.c: NVEnablePalette
#     - nvidia/nv_setup.c: NVReadDacMask
#   - remove the following unneeded EXPORT_SYMBOL's:
#     - fbmon.c: fb_create_modedb
#     - fbmon.c: fb_get_monitor_limits
#     - hgafb.c: hgafb_setup
#   
#   Signed-off-by: Adrian Bunk <bunk@stusta.de>
#   Signed-off-by: Antonino Daplas <adaplas@pol.net>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/linux/fb.h
#   2005/03/10 00:39:10-08:00 adaplas@hotpop.com +0 -3
#   fbdev: Cleanups in driver/video
# 
# drivers/video/vfb.c
#   2005/03/10 00:39:10-08:00 adaplas@hotpop.com +4 -8
#   fbdev: Cleanups in driver/video
# 
# drivers/video/vesafb.c
#   2005/03/10 00:39:10-08:00 adaplas@hotpop.com +2 -10
#   fbdev: Cleanups in driver/video
# 
# drivers/video/tdfxfb.c
#   2005/03/10 00:39:10-08:00 adaplas@hotpop.com +23 -28
#   fbdev: Cleanups in driver/video
# 
# drivers/video/riva/fbdev.c
#   2005/03/10 00:39:10-08:00 adaplas@hotpop.com +4 -4
#   fbdev: Cleanups in driver/video
# 
# drivers/video/radeonfb.c
#   2005/03/10 00:39:10-08:00 adaplas@hotpop.com +20 -24
#   fbdev: Cleanups in driver/video
# 
# drivers/video/pm2fb.c
#   2005/03/10 00:39:10-08:00 adaplas@hotpop.com +22 -38
#   fbdev: Cleanups in driver/video
# 
# drivers/video/nvidia/nvidia.c
#   2005/03/10 00:39:10-08:00 adaplas@hotpop.com +2 -2
#   fbdev: Cleanups in driver/video
# 
# drivers/video/nvidia/nv_setup.c
#   2005/03/10 00:39:10-08:00 adaplas@hotpop.com +4 -0
#   fbdev: Cleanups in driver/video
# 
# drivers/video/nvidia/nv_proto.h
#   2005/03/10 00:39:10-08:00 adaplas@hotpop.com +0 -5
#   fbdev: Cleanups in driver/video
# 
# drivers/video/nvidia/nv_of.c
#   2005/03/10 00:39:10-08:00 adaplas@hotpop.com +0 -1
#   fbdev: Cleanups in driver/video
# 
# drivers/video/nvidia/nv_i2c.c
#   2005/03/10 00:39:10-08:00 adaplas@hotpop.com +2 -0
#   fbdev: Cleanups in driver/video
# 
# drivers/video/nvidia/nv_accel.c
#   2005/03/10 00:39:10-08:00 adaplas@hotpop.com +2 -2
#   fbdev: Cleanups in driver/video
# 
# drivers/video/neofb.c
#   2005/03/10 00:39:10-08:00 adaplas@hotpop.com +9 -7
#   fbdev: Cleanups in driver/video
# 
# drivers/video/intelfb/intelfbdrv.h
#   2005/03/10 00:39:10-08:00 adaplas@hotpop.com +1 -1
#   fbdev: Cleanups in driver/video
# 
# drivers/video/intelfb/intelfbdrv.c
#   2005/03/10 00:39:10-08:00 adaplas@hotpop.com +33 -40
#   fbdev: Cleanups in driver/video
# 
# drivers/video/imsttfb.c
#   2005/03/10 00:39:10-08:00 adaplas@hotpop.com +3 -4
#   fbdev: Cleanups in driver/video
# 
# drivers/video/i810/i810_main.c
#   2005/03/10 00:39:10-08:00 adaplas@hotpop.com +1 -1
#   fbdev: Cleanups in driver/video
# 
# drivers/video/hgafb.c
#   2005/03/10 00:39:10-08:00 adaplas@hotpop.com +3 -11
#   fbdev: Cleanups in driver/video
# 
# drivers/video/geode/gx1fb_core.c
#   2005/03/10 00:39:10-08:00 adaplas@hotpop.com +2 -2
#   fbdev: Cleanups in driver/video
# 
# drivers/video/fbmon.c
#   2005/03/10 00:39:10-08:00 adaplas@hotpop.com +2 -12
#   fbdev: Cleanups in driver/video
# 
# drivers/video/fbmem.c
#   2005/03/10 00:39:10-08:00 adaplas@hotpop.com +4 -5
#   fbdev: Cleanups in driver/video
# 
# drivers/video/cyber2000fb.c
#   2005/03/10 00:39:10-08:00 adaplas@hotpop.com +6 -3
#   fbdev: Cleanups in driver/video
# 
# drivers/video/backlight/lcd.c
#   2005/03/10 00:39:10-08:00 adaplas@hotpop.com +1 -1
#   fbdev: Cleanups in driver/video
# 
# drivers/video/backlight/backlight.c
#   2005/03/10 00:39:10-08:00 adaplas@hotpop.com +1 -1
#   fbdev: Cleanups in driver/video
# 
# drivers/video/aty/radeonfb.h
#   2005/03/10 00:39:10-08:00 adaplas@hotpop.com +0 -1
#   fbdev: Cleanups in driver/video
# 
# drivers/video/aty/radeon_pm.c
#   2005/03/10 00:39:10-08:00 adaplas@hotpop.com +2 -2
#   fbdev: Cleanups in driver/video
# 
# drivers/video/aty/radeon_base.c
#   2005/03/10 00:39:10-08:00 adaplas@hotpop.com +22 -24
#   fbdev: Cleanups in driver/video
# 
# drivers/video/aty/mach64_cursor.c
#   2005/03/10 00:39:10-08:00 adaplas@hotpop.com +1 -1
#   fbdev: Cleanups in driver/video
# 
# drivers/video/aty/mach64_ct.c
#   2005/03/10 00:39:10-08:00 adaplas@hotpop.com +5 -2
#   fbdev: Cleanups in driver/video
# 
# drivers/video/aty/atyfb_base.c
#   2005/03/10 00:39:10-08:00 adaplas@hotpop.com +7 -7
#   fbdev: Cleanups in driver/video
# 
# drivers/video/aty/atyfb.h
#   2005/03/10 00:39:10-08:00 adaplas@hotpop.com +0 -1
#   fbdev: Cleanups in driver/video
# 
# drivers/video/aty/aty128fb.c
#   2005/03/10 00:39:10-08:00 adaplas@hotpop.com +4 -9
#   fbdev: Cleanups in driver/video
# 
# ChangeSet
#   2005/03/10 09:14:39-08:00 adaplas@hotpop.com 
#   [PATCH] savagefb: Make savagefb one module
#   
#   #if defined(CONFIG_FB_SAVAGE_ACCEL)
#   
#     doesn't work with FB_SAVAGE_ACCEL=m, and
#   
#   #if defined(CONFIG_FB_SAVAGE_ACCEL) || defined(CONFIG_FB_SAVAGE_ACCEL_MODULE)
#   
#     would break with FB_SAVAGE=y and FB_SAVAGE_ACCEL=m.
#   
#   Rename savagefb.c to savagefb_driver.c.
#   
#   Signed-off-by: Adrian Bunk <bunk@stusta.de>
#   Signed-off-by: Antonino Daplas <adaplas@pol.net>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/video/savage/savagefb_driver.c
#   2005/03/10 00:39:10-08:00 adaplas@hotpop.com +9 -5
#   savagefb: Make savagefb one module
# 
# drivers/video/savage/savagefb_accel.c
#   2005/03/10 00:39:10-08:00 adaplas@hotpop.com +0 -4
#   savagefb: Make savagefb one module
# 
# drivers/video/savage/savagefb-i2c.c
#   2005/03/10 00:39:10-08:00 adaplas@hotpop.com +0 -3
#   savagefb: Make savagefb one module
# 
# drivers/video/savage/Makefile
#   2005/03/10 00:39:10-08:00 adaplas@hotpop.com +4 -3
#   savagefb: Make savagefb one module
# 
# drivers/video/Kconfig
#   2005/03/10 00:39:10-08:00 adaplas@hotpop.com +2 -2
#   savagefb: Make savagefb one module
# 
# ChangeSet
#   2005/03/10 09:14:07-08:00 jonsmirl@gmail.com 
#   [PATCH] fbdev: Allow core fb to be built as a module
#   
#   Allow the framebuffer core to be built as a module to ease debugging.
#   
#   Signed-off-by: Antonino Daplas <adaplas@pol.net>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/video/logo/logo.c
#   2005/03/10 00:39:10-08:00 jonsmirl@gmail.com +2 -1
#   fbdev: Allow core fb to be built as a module
# 
# drivers/video/fbmem.c
#   2005/03/10 00:39:10-08:00 jonsmirl@gmail.com +15 -0
#   fbdev: Allow core fb to be built as a module
# 
# drivers/video/console/Makefile
#   2005/03/10 00:39:10-08:00 jonsmirl@gmail.com +3 -1
#   fbdev: Allow core fb to be built as a module
# 
# drivers/video/Makefile
#   2005/03/10 00:39:10-08:00 jonsmirl@gmail.com +3 -5
#   fbdev: Allow core fb to be built as a module
# 
# drivers/video/Kconfig
#   2005/03/10 00:39:10-08:00 jonsmirl@gmail.com +38 -37
#   fbdev: Allow core fb to be built as a module
# 
# ChangeSet
#   2005/03/10 09:13:51-08:00 jsimmons@www.infradead.org 
#   [PATCH] fbdev: Generic drawing function cleanups 2
#   
#   Replaced LONG_MASK, SHIFT_PER_LONG, BYTES_PER_LONG with dynamic variables. 
#   This will allow drivers in the future to control how much data to read/write
#   from the framebuffer.
#   
#   Signed-off-by: Antonino Daplas <adaplas@pol.net>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# ChangeSet
#   2005/03/10 18:13:44+01:00 bzolnier@trik.(none) 
#   [ide] kill ide_driver_t->capacity
#   
#   * add private /proc/ide/hd?/capacity handlers to ide-{cd,disk,floppy}.c
#   * use generic proc_ide_read_capacity() for ide-{scsi,tape}.c
#   * kill ->capacity, default_capacity() and generic_subdriver_entries[]
#   
#   Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
# 
# drivers/video/cfbfillrect.c
#   2005/03/10 00:39:09-08:00 jsimmons@www.infradead.org +41 -49
#   fbdev: Generic drawing function cleanups 2
# 
# drivers/video/cfbcopyarea.c
#   2005/03/10 00:39:09-08:00 jsimmons@www.infradead.org +53 -132
#   fbdev: Generic drawing function cleanups 2
# 
# ChangeSet
#   2005/03/10 09:13:36-08:00 adaplas@hotpop.com 
#   [PATCH] nvidiafb:  Some chipsets need a buffer pitch divisible by 64
#   
#   The Geforce2 cards crashes at 800x600-8, but not at 640x480 or 1024x768.
#   Changing the xres_virtual to be divisible by 64 fixes the problem.
#   
#   Signed-off-by: Antonino Daplas <adaplas@pol.net>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/linux/ide.h
#   2005/03/10 18:10:00+01:00 bzolnier@trik.(none) +0 -1
#   [ide] kill ide_driver_t->capacity
# 
# drivers/scsi/ide-scsi.c
#   2005/03/10 18:10:00+01:00 bzolnier@trik.(none) +10 -0
#   [ide] kill ide_driver_t->capacity
# 
# drivers/ide/ide.c
#   2005/03/10 18:10:00+01:00 bzolnier@trik.(none) +1 -15
#   [ide] kill ide_driver_t->capacity
# 
# drivers/ide/ide-tape.c
#   2005/03/10 18:10:00+01:00 bzolnier@trik.(none) +1 -0
#   [ide] kill ide_driver_t->capacity
# 
# drivers/ide/ide-proc.c
#   2005/03/10 18:10:00+01:00 bzolnier@trik.(none) +3 -5
#   [ide] kill ide_driver_t->capacity
# 
# drivers/ide/ide-floppy.c
#   2005/03/10 18:10:00+01:00 bzolnier@trik.(none) +11 -1
#   [ide] kill ide_driver_t->capacity
# 
# drivers/ide/ide-disk.c
#   2005/03/10 18:10:00+01:00 bzolnier@trik.(none) +11 -1
#   [ide] kill ide_driver_t->capacity
# 
# drivers/ide/ide-cd.c
#   2005/03/10 18:10:00+01:00 bzolnier@trik.(none) +20 -1
#   [ide] kill ide_driver_t->capacity
# 
# drivers/video/nvidia/nvidia.c
#   2005/03/10 00:39:09-08:00 adaplas@hotpop.com +3 -2
#   nvidiafb:  Some chipsets need a buffer pitch divisible by 64
# 
# ChangeSet
#   2005/03/10 09:13:19-08:00 adaplas@hotpop.com 
#   [PATCH] nvidiafb: Fix i2c error handling
#   
#   Fixed error handling in rivafb-i2c.c if bus registration fails.
#   
#   Signed-off-by: Antonino Daplas <adaplas@pol.net>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/video/nvidia/nv_i2c.c
#   2005/03/10 00:39:09-08:00 adaplas@hotpop.com +7 -1
#   nvidiafb: Fix i2c error handling
# 
# ChangeSet
#   2005/03/10 09:13:03-08:00 adaplas@hotpop.com 
#   [PATCH] rivafb: Fix i2c error handling
#   
#   Fixed error handling in rivafb-i2c.c if bus registration fails.
#   
#   Signed-off-by: Antonino Daplas <adaplas@pol.net>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/video/riva/rivafb-i2c.c
#   2005/03/10 00:39:09-08:00 adaplas@hotpop.com +9 -2
#   rivafb: Fix i2c error handling
# 
# ChangeSet
#   2005/03/10 09:12:46-08:00 adaplas@hotpop.com 
#   [PATCH] fbcon: Cursor fixes
#   
#   From Jiri Benc:
#   
#   we found several bugs in framebuffer console code in recent kernels.
#   
#   1. The escape sequence '\033[?25l' does not work (should disable cursor).
#   
#   2. When scrolling console using Shift-PgUp with cursor in the upper half
#      part of the screen, cursor position is not updated.
#   
#   3. If cursor is placed at some character and console is scrolled using
#      Shift-PgUp, that character remains on the screen.
#   
#   Signed-off-by: Antonino Daplas <adaplas@pol.net>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/video/console/tileblit.c
#   2005/03/10 00:39:08-08:00 adaplas@hotpop.com +2 -1
#   fbcon: Cursor fixes
# 
# drivers/video/console/fbcon.h
#   2005/03/10 00:39:08-08:00 adaplas@hotpop.com +1 -1
#   fbcon: Cursor fixes
# 
# drivers/video/console/fbcon.c
#   2005/03/10 00:39:08-08:00 adaplas@hotpop.com +10 -14
#   fbcon: Cursor fixes
# 
# drivers/video/console/bitblit.c
#   2005/03/10 00:39:08-08:00 adaplas@hotpop.com +10 -1
#   fbcon: Cursor fixes
# 
# ChangeSet
#   2005/03/10 09:12:31-08:00 adaplas@hotpop.com 
#   [PATCH] fbdev: Capture modelist change event
#   
#   Add capability to change private modelist.  It checks if the entries in the
#   new modelist are acceptable, and if not, trimmed from the modelist.
#   
#   Also added a new event, FB_EVENT_NEW_MODELIST, sent by fbmem, and captured by
#   fbcon to resize all consoles, if need be.
#   
#   Requires minor changes to new functions, ie, fb_get_color_depth().
#   
#   Signed-off-by: Antonino Daplas <adaplas@pol.net>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/linux/fb.h
#   2005/03/10 00:39:08-08:00 adaplas@hotpop.com +6 -1
#   fbdev: Capture modelist change event
# 
# drivers/video/nvidia/nvidia.c
#   2005/03/10 00:39:08-08:00 adaplas@hotpop.com +1 -1
#   fbdev: Capture modelist change event
# 
# drivers/video/modedb.c
#   2005/03/10 00:39:08-08:00 adaplas@hotpop.com +42 -0
#   fbdev: Capture modelist change event
# 
# drivers/video/fbsysfs.c
#   2005/03/10 00:39:08-08:00 adaplas@hotpop.com +11 -1
#   fbdev: Capture modelist change event
# 
# drivers/video/fbmem.c
#   2005/03/10 00:39:08-08:00 adaplas@hotpop.com +38 -5
#   fbdev: Capture modelist change event
# 
# drivers/video/console/fbcon.c
#   2005/03/10 00:39:08-08:00 adaplas@hotpop.com +50 -18
#   fbdev: Capture modelist change event
# 
# drivers/video/console/bitblit.c
#   2005/03/10 00:39:08-08:00 adaplas@hotpop.com +1 -1
#   fbdev: Capture modelist change event
# 
# ChangeSet
#   2005/03/10 09:12:15-08:00 jonsmirl@gmail.com 
#   [PATCH] fbdev: Add mode changing via sysfs
#   
#   This is a first pass at adding two new sysfs attributes to
#   /sys/class/graphics/fb0 for setting modes.  There are two attributes: modes
#   which contains a list of valid modes, and mode which is the current mode.  To
#   switch modes echo one of the entries from the modes list to the mode
#   attribute.
#   
#   The D,V,S on the modes represents Detailed, Vesa, Standard from the DDC info.
#   
#   modes is root writable.  It can also be used to set the list of modes.  For
#   example a /etc file could add modes that are not in the monitor's DDC.
#   
#   mode is user writable.  PAM would set ownership of mode at user login time.
#   This provides a safe way for a user to set the mode without being root.  You
#   can only set the mode to one of the modes on the list.
#   
#   Signed-off-by: Antonino Daplas <adaplas@pol.net>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/linux/fb.h
#   2005/03/10 00:39:08-08:00 jonsmirl@gmail.com +4 -0
#   fbdev: Add mode changing via sysfs
# 
# drivers/video/fbsysfs.c
#   2005/03/10 00:39:08-08:00 jonsmirl@gmail.com +305 -2
#   fbdev: Add mode changing via sysfs
# 
# drivers/video/fbmem.c
#   2005/03/10 00:39:08-08:00 jonsmirl@gmail.com +8 -6
#   fbdev: Add mode changing via sysfs
# 
# ChangeSet
#   2005/03/10 09:12:01-08:00 benh@kernel.crashing.org 
#   [PATCH] ppc32: uninorth-agp suspend support
#   
#   This patch adds suspend/resume support to the Apple UniNorth AGP bridge to
#   make sure AGP is properly disabled when the machine goes to sleep.  Without
#   this, the r300 based laptops will fail to wakeup from sleep when using the
#   new experimental r300 DRI driver.  It should also improve reliablility in
#   general with other chips.
#   
#   Unfortunately, uninorth-agp is just a "sibling" of the video chip on the
#   PCI bus, and thus ends up beeing called either before the video chip
#   suspend routine, or after, depending on the HW layout or other random
#   things.
#   
#   To make sure the device side of AGP is always disabled first and that we
#   never touch the device after having put it into D2 state (which can be
#   deadly), I also need the separate patch to radeonfb and aty128fb which will
#   make them disabled their own side if not already done by the bridge driver.
#   
#   Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
#   Signed-off-by: Paul Mackerras <paulus@samba.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/char/agp/uninorth-agp.c
#   2005/03/10 00:39:08-08:00 benh@kernel.crashing.org +66 -0
#   ppc32: uninorth-agp suspend support
# 
# ChangeSet
#   2005/03/10 09:11:45-08:00 benh@kernel.crashing.org 
#   [PATCH] aty128fb: Disable AGP on suspend
#   
#   This patch improves reliability of suspend/resume by making sure AGP is
#   disabled on the Rage 128 chip before putting it into a suspend state.  It
#   works in conjunction with the uninorth-agp suspend patch, but should be
#   harmless on machines with a different AGP bridge.
#   
#   Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/video/aty/aty128fb.c
#   2005/03/10 00:39:07-08:00 benh@kernel.crashing.org +22 -0
#   aty128fb: Disable AGP on suspend
# 
# ChangeSet
#   2005/03/10 09:11:29-08:00 benh@kernel.crashing.org 
#   [PATCH] radeonfb: Disable AGP on suspend
#   
#   This patch improves reliability of suspend/resume by making sure AGP is
#   disabled on the radeon chip before putting it into a suspend state.  It
#   works in conjunction with the uninorth-agp suspend patch, but should be
#   harmless on machines with a different AGP bridge.
#   
#   Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/video/aty/radeon_pm.c
#   2005/03/10 00:39:07-08:00 benh@kernel.crashing.org +33 -8
#   radeonfb: Disable AGP on suspend
# 
# ChangeSet
#   2005/03/10 09:11:13-08:00 adaplas@hotpop.com 
#   [PATCH] fbdev: Generic drawing function cleanups
#   
#     From Ulrich Eckhardt:
#   
#      * removed trailing whitespace
#      * use helper function for common bitwise operations
#      * fixed several cases where either the wrong mask was used for bitops
#        or the mask was computed falsely, messing up <32 BPP support
#      * added self-tests for bitcpy_rev() algorithm in module-init function
#      * no need to use explicitly sized integers in some cases
#      * added a few comments where things weren't obvious to me
#   
#     I tested these changes on an Au1100 based board, using the patches to its
#     framebuffer code that were posted here by Christian Pellegrin[1]. I had this
#     code working both on a 16BPP color LCD and a 4BPP monochrome one.
#   
#   Signed-off-by: Antonino Daplas <adaplas@pol.net>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/video/cfbfillrect.c
#   2005/03/10 00:39:07-08:00 adaplas@hotpop.com +142 -141
#   fbdev: Generic drawing function cleanups
# 
# drivers/video/cfbcopyarea.c
#   2005/03/10 00:39:07-08:00 adaplas@hotpop.com +216 -132
#   fbdev: Generic drawing function cleanups
# 
# ChangeSet
#   2005/03/10 09:10:58-08:00 adaplas@hotpop.com 
#   [PATCH] nvidiafb: Add update framebuffer driver for nVidia chipsets
#   
#   Because nVidia keeps pumping out new graphics chipsets, it is becoming
#   harder to add support for these with the old rivafb code.  Currently, rivafb
#   can properly support NV_ARCH_20 chipsets and older.
#   
#   Instead of rewriting rivafb to support the latest chipsets, I've decided to
#   write a new driver, called nvidiafb.  The aim is to closely follow Xorg
#   development.
#   
#   Currently, this driver is based on the most recent CVS Xorg nv driver. Main
#   
#     - console acceleration for all chipsets
#     - uses DMA instead of PIO
#     - better LCD/digital output support
#     - better monitor detection
#     - support for Riva128 will be dropped as it cannot do DMA, rivafb
#       will remain as the driver for this chipset
#   
#   It should work with Xorg/XFree86 nv driver, but as with rivafb, is not
#   compatible with the proprietary nvidia driver.
#   
#   Once the code becomes stable, rivafb code will be trimmed to only support the
#   Riva128 and perhaps some of the older chipsets.  The code has been tested on
#   several nVidia graphics card on x86 and x86_64.  I'm still waiting for
#   feedback from Guido Guenther regarding ppc.
#   
#   This need not go to mainline immediately, as I would prefer the code to
#   receive rigorous testing in the mm tree.
#   
#   Signed-off-by: Antonino Daplas <adaplas@pol.net>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/video/nvidia/nvidia.c
#   2005/03/10 00:39:06-08:00 adaplas@hotpop.com +1725 -0
#   nvidiafb: Add update framebuffer driver for nVidia chipsets
# 
# drivers/video/nvidia/nv_type.h
#   2005/03/10 00:39:06-08:00 adaplas@hotpop.com +174 -0
#   nvidiafb: Add update framebuffer driver for nVidia chipsets
# 
# drivers/video/nvidia/nv_setup.c
#   2005/03/10 00:39:06-08:00 adaplas@hotpop.com +622 -0
#   nvidiafb: Add update framebuffer driver for nVidia chipsets
# 
# drivers/video/nvidia/nv_proto.h
#   2005/03/10 00:39:06-08:00 adaplas@hotpop.com +61 -0
#   nvidiafb: Add update framebuffer driver for nVidia chipsets
# 
# drivers/video/nvidia/nv_of.c
#   2005/03/10 00:39:06-08:00 adaplas@hotpop.com +59 -0
#   nvidiafb: Add update framebuffer driver for nVidia chipsets
# 
# drivers/video/nvidia/nv_local.h
#   2005/03/10 00:39:06-08:00 adaplas@hotpop.com +98 -0
#   nvidiafb: Add update framebuffer driver for nVidia chipsets
# 
# drivers/video/nvidia/nv_i2c.c
#   2005/03/10 00:39:06-08:00 adaplas@hotpop.com +209 -0
#   nvidiafb: Add update framebuffer driver for nVidia chipsets
# 
# drivers/video/nvidia/nv_hw.c
#   2005/03/10 00:39:06-08:00 adaplas@hotpop.com +1582 -0
#   nvidiafb: Add update framebuffer driver for nVidia chipsets
# 
# drivers/video/nvidia/nv_dma.h
#   2005/03/10 00:39:06-08:00 adaplas@hotpop.com +178 -0
#   nvidiafb: Add update framebuffer driver for nVidia chipsets
# 
# drivers/video/nvidia/nv_accel.c
#   2005/03/10 00:39:06-08:00 adaplas@hotpop.com +367 -0
#   nvidiafb: Add update framebuffer driver for nVidia chipsets
# 
# include/linux/pci_ids.h
#   2005/03/10 00:39:06-08:00 adaplas@hotpop.com +83 -1
#   nvidiafb: Add update framebuffer driver for nVidia chipsets
# 
# include/linux/fb.h
#   2005/03/10 00:39:06-08:00 adaplas@hotpop.com +4 -1
#   nvidiafb: Add update framebuffer driver for nVidia chipsets
# 
# drivers/video/nvidia/nvidia.c
#   2005/03/10 00:39:06-08:00 adaplas@hotpop.com +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/drivers/video/nvidia/nvidia.c
# 
# drivers/video/nvidia/nv_type.h
#   2005/03/10 00:39:06-08:00 adaplas@hotpop.com +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/drivers/video/nvidia/nv_type.h
# 
# drivers/video/nvidia/nv_setup.c
#   2005/03/10 00:39:06-08:00 adaplas@hotpop.com +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/drivers/video/nvidia/nv_setup.c
# 
# drivers/video/nvidia/nv_proto.h
#   2005/03/10 00:39:06-08:00 adaplas@hotpop.com +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/drivers/video/nvidia/nv_proto.h
# 
# drivers/video/nvidia/nv_of.c
#   2005/03/10 00:39:06-08:00 adaplas@hotpop.com +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/drivers/video/nvidia/nv_of.c
# 
# drivers/video/nvidia/nv_local.h
#   2005/03/10 00:39:06-08:00 adaplas@hotpop.com +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/drivers/video/nvidia/nv_local.h
# 
# drivers/video/nvidia/nv_i2c.c
#   2005/03/10 00:39:06-08:00 adaplas@hotpop.com +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/drivers/video/nvidia/nv_i2c.c
# 
# drivers/video/nvidia/nv_hw.c
#   2005/03/10 00:39:06-08:00 adaplas@hotpop.com +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/drivers/video/nvidia/nv_hw.c
# 
# drivers/video/nvidia/nv_dma.h
#   2005/03/10 00:39:06-08:00 adaplas@hotpop.com +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/drivers/video/nvidia/nv_dma.h
# 
# drivers/video/nvidia/nv_accel.c
#   2005/03/10 00:39:06-08:00 adaplas@hotpop.com +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/drivers/video/nvidia/nv_accel.c
# 
# drivers/video/nvidia/Makefile
#   2005/03/10 00:39:06-08:00 adaplas@hotpop.com +12 -0
#   nvidiafb: Add update framebuffer driver for nVidia chipsets
# 
# drivers/video/Makefile
#   2005/03/10 00:39:06-08:00 adaplas@hotpop.com +1 -0
#   nvidiafb: Add update framebuffer driver for nVidia chipsets
# 
# drivers/video/Kconfig
#   2005/03/10 00:39:06-08:00 adaplas@hotpop.com +32 -0
#   nvidiafb: Add update framebuffer driver for nVidia chipsets
# 
# drivers/video/nvidia/Makefile
#   2005/03/10 00:39:06-08:00 adaplas@hotpop.com +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/drivers/video/nvidia/Makefile
# 
# ChangeSet
#   2005/03/10 09:10:41-08:00 adaplas@hotpop.com 
#   [PATCH] geodefb: Add Geode framebuffer driver
#   
#     Attached is a patch (against 2.6.10) for a framebuffer driver for the
#     Geode family of processors.  It does not use AMD's horrible Durango API.
#      It is, however, rather feature incomplete at the moment.
#   
#             * Only Geode GX1 (with CS5530 companion chip) is supported.
#             * Tested resolutions: 640x480 to 1280x1024.
#             * Supported bit depths: 8 bit palette, 16 bit RGB 5-6-5.
#             * CRT output only.
#             * No accelerated features.
#             * Compression is not enabled.
#             * flat panel support (panel=<x>x<y> option). (Only one 640x480 panel
#               has been tested though.)
#             * blank function for display blanking/powersaving.
#             * crt=<n> option to enable/disable the CRT output.
#   
#   From: Alexey Dobriyan <adobriyan@mail.ru>
#   
#   Fix
#   
#   drivers/video/geode/display_gx1.c: error: `loops_per_jiffy' undeclared (first use in this function)
#   drivers/video/geode/video_cs5530.c: error: `loops_per_jiffy' undeclared (first use in this function)
#   
#   Signed-off-by: David Vrabel <dvrabel@arcom.com>
#   Signed-off-by: Antonino Daplas <adaplas@pol.net>
#   Signed-off-by: Alexey Dobriyan <adobriyan@mail.ru>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/video/geode/video_cs5530.h
#   2005/03/10 00:39:06-08:00 adaplas@hotpop.com +75 -0
#   geodefb: Add Geode framebuffer driver
# 
# drivers/video/geode/video_cs5530.c
#   2005/03/10 00:39:06-08:00 adaplas@hotpop.com +195 -0
#   geodefb: Add Geode framebuffer driver
# 
# drivers/video/geode/gx1fb_core.c
#   2005/03/10 00:39:06-08:00 adaplas@hotpop.com +359 -0
#   geodefb: Add Geode framebuffer driver
# 
# drivers/video/geode/geodefb.h
#   2005/03/10 00:39:06-08:00 adaplas@hotpop.com +39 -0
#   geodefb: Add Geode framebuffer driver
# 
# drivers/video/geode/display_gx1.h
#   2005/03/10 00:39:06-08:00 adaplas@hotpop.com +154 -0
#   geodefb: Add Geode framebuffer driver
# 
# drivers/video/geode/Makefile
#   2005/03/10 00:39:06-08:00 adaplas@hotpop.com +5 -0
#   geodefb: Add Geode framebuffer driver
# 
# drivers/video/geode/Kconfig
#   2005/03/10 00:39:06-08:00 adaplas@hotpop.com +29 -0
#   geodefb: Add Geode framebuffer driver
# 
# drivers/video/geode/video_cs5530.h
#   2005/03/10 00:39:06-08:00 adaplas@hotpop.com +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/drivers/video/geode/video_cs5530.h
# 
# drivers/video/geode/video_cs5530.c
#   2005/03/10 00:39:06-08:00 adaplas@hotpop.com +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/drivers/video/geode/video_cs5530.c
# 
# drivers/video/geode/gx1fb_core.c
#   2005/03/10 00:39:06-08:00 adaplas@hotpop.com +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/drivers/video/geode/gx1fb_core.c
# 
# drivers/video/geode/geodefb.h
#   2005/03/10 00:39:06-08:00 adaplas@hotpop.com +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/drivers/video/geode/geodefb.h
# 
# drivers/video/geode/display_gx1.h
#   2005/03/10 00:39:06-08:00 adaplas@hotpop.com +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/drivers/video/geode/display_gx1.h
# 
# drivers/video/geode/display_gx1.c
#   2005/03/10 00:39:06-08:00 adaplas@hotpop.com +214 -0
#   geodefb: Add Geode framebuffer driver
# 
# drivers/video/geode/Makefile
#   2005/03/10 00:39:06-08:00 adaplas@hotpop.com +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/drivers/video/geode/Makefile
# 
# drivers/video/geode/Kconfig
#   2005/03/10 00:39:06-08:00 adaplas@hotpop.com +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/drivers/video/geode/Kconfig
# 
# drivers/video/Makefile
#   2005/03/10 00:39:06-08:00 adaplas@hotpop.com +1 -0
#   geodefb: Add Geode framebuffer driver
# 
# drivers/video/Kconfig
#   2005/03/10 00:39:06-08:00 adaplas@hotpop.com +2 -0
#   geodefb: Add Geode framebuffer driver
# 
# drivers/video/geode/display_gx1.c
#   2005/03/10 00:39:06-08:00 adaplas@hotpop.com +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/drivers/video/geode/display_gx1.c
# 
# ChangeSet
#   2005/03/10 09:10:24-08:00 dvrabel@arcom.com 
#   [PATCH] fbdev: Kbuild cleanups
#   
#   This set of two patches add new options (FB_CFB_IMAGEBLIT, FB_CFB_FILLRECT,
#   FB_CFB_COPYAREA, FB_SOFT_CURSOR) to the framebuffer Kconfig to enable
#   building the generic software cfbfillrect, cfbcopyarea, cfbimageblt and
#   softcursor objects.  This cuts out a lot of stuff from the Makefile and
#   allows drivers in their own directory to be more self-contained.
#   
#   Signed-off-by: Antonino Daplas <adaplas@pol.net>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/video/Makefile
#   2005/03/10 00:39:05-08:00 dvrabel@arcom.com +68 -79
#   fbdev: Kbuild cleanups
# 
# drivers/video/Kconfig
#   2005/03/10 00:39:05-08:00 dvrabel@arcom.com +290 -0
#   fbdev: Kbuild cleanups
# 
# ChangeSet
#   2005/03/10 09:10:08-08:00 adaplas@hotpop.com 
#   [PATCH] fbdev: Logo code fixes
#   
#     This patch fixes a few bugs with the low level logo code.
#   
#     1. Allow DEC Alpha machines to draw the DEC logo
#     2. Cleanup the logo directory on a make clean
#     3. Some makefile cleanups.
#   
#     I have tested on my local machines. I like to be able to create the C
#     files from the logos for only the ones we want to compile but I haven't
#     figured out how to do that. That can wait. Please apply.
#   
#   Signed-off-by: James Simmons <jsimmons@www.infradead.org>
#   Signed-off-by: Antonino Daplas <adaplas@pol.net>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/video/logo/logo.c
#   2005/03/10 00:39:05-08:00 adaplas@hotpop.com +3 -1
#   fbdev: Logo code fixes
# 
# drivers/video/logo/Makefile
#   2005/03/10 00:39:05-08:00 adaplas@hotpop.com +19 -22
#   fbdev: Logo code fixes
# 
# drivers/video/logo/Kconfig
#   2005/03/10 00:39:05-08:00 adaplas@hotpop.com +1 -1
#   fbdev: Logo code fixes
# 
# ChangeSet
#   2005/03/10 09:09:51-08:00 adaplas@hotpop.com 
#   [PATCH] intelfb: vesa_modes require CONFIG_FB_MODEHELPERS
#   
#   The recent intelfb update made intelfb pass vesa_modes as the database to
#   fb_find_mode(). The array vesa_modes depends on CONFIG_FB_MODEHELPERS. Fix
#   
#   Signed-off-by: Antonino Daplas <adaplas@pol.net>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/video/Kconfig
#   2005/03/10 00:39:05-08:00 adaplas@hotpop.com +1 -0
#   intelfb: vesa_modes require CONFIG_FB_MODEHELPERS
# 
# ChangeSet
#   2005/03/10 09:09:35-08:00 akpm@osdl.org 
#   [PATCH] tridentfb warning fix
#   
#   drivers/video/tridentfb.c:1219: warning: `tridentfb_setup' declared `static' but never defined
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/video/tridentfb.c
#   2005/03/10 00:39:05-08:00 akpm@osdl.org +18 -21
#   tridentfb warning fix
# 
# ChangeSet
#   2005/03/10 09:09:19-08:00 bunk@stusta.de 
#   [PATCH] tridentfb.c: make some code static
#   
#   This patch makes some needlessly global code static.
#   
#   Signed-off-by: Adrian Bunk <bunk@stusta.de>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/video/tridentfb.c
#   2005/03/10 00:39:04-08:00 bunk@stusta.de +9 -7
#   tridentfb.c: make some code static
# 
# ChangeSet
#   2005/03/10 09:09:04-08:00 akpm@osdl.org 
#   [PATCH] sis warning fix
#   
#   drivers/video/sis/sis_main.c: In function `sisfb_compat_ioctl':
#   drivers/video/sis/sis_main.c:2204: warning: implicit declaration of function `lock_kernel'
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/video/sis/sis_main.c
#   2005/03/10 00:39:04-08:00 akpm@osdl.org +1 -0
#   sis warning fix
# 
# ChangeSet
#   2005/03/10 09:08:48-08:00 akpm@osdl.org 
#   [PATCH] fbdev compat_ioctl warning fix
#   
#   Fix some confusion over fbdev compat_ioctl return types - compat_ioctls return
#   `long'.
#   
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/linux/fb.h
#   2005/03/10 00:39:04-08:00 akpm@osdl.org +1 -1
#   fbdev compat_ioctl warning fix
# 
# drivers/video/fbmem.c
#   2005/03/10 00:39:04-08:00 akpm@osdl.org +2 -1
#   fbdev compat_ioctl warning fix
# 
# ChangeSet
#   2005/03/10 09:08:31-08:00 adaplas@gawab.com 
#   [PATCH] intelfb: Add partial support 915G chipset
#   
#   Add (partial) support for 915G
#     No HW cursor at the moment
#     Screen is blanked but signal/sync is not switched off
#   Mostly derived from XFree86/Xorg driver
#   Pass "vesa_modes" and VESA_MODEDB_SIZE in call to "fb_find_mode()"
#     to allow loading as module. Makes "vesa_modes" also the default
#     "modedb" when linking statically into the kernel.
#   Change PREFERRED_MODE to more reasonable value "1024x768-32@70"
#   
#   Signed-off-by: Axel Buttchereit <XL@XLsigned.net>
#   Signed-off-by: Antonino Daplas <adaplas@pol.net>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/video/intelfb/intelfbhw.h
#   2005/03/10 00:39:04-08:00 adaplas@gawab.com +3 -0
#   intelfb: Add partial support 915G chipset
# 
# drivers/video/intelfb/intelfbhw.c
#   2005/03/10 00:39:04-08:00 adaplas@gawab.com +11 -0
#   intelfb: Add partial support 915G chipset
# 
# drivers/video/intelfb/intelfbdrv.h
#   2005/03/10 00:39:04-08:00 adaplas@gawab.com +1 -1
#   intelfb: Add partial support 915G chipset
# 
# drivers/video/intelfb/intelfbdrv.c
#   2005/03/10 00:39:04-08:00 adaplas@gawab.com +22 -10
#   intelfb: Add partial support 915G chipset
# 
# drivers/video/intelfb/intelfb.h
#   2005/03/10 00:39:04-08:00 adaplas@gawab.com +5 -3
#   intelfb: Add partial support 915G chipset
# 
# ChangeSet
#   2005/03/10 09:08:15-08:00 lucasvr@gobolinux.org 
#   [PATCH] skeletonfb: Documentation fixes
#   
#   This patch just fixes some typos and adds retval documentation for some
#   functions that were missing it.
#   
#   I've also a question here: skeletonfb says that xxxfb_setcolreg() should
#   return a negative errno on error.  However, if the register number being
#   accessed is out of bounds, 1 is returned.  Shouldn't it be better to return
#   -EINVAL instead?  By looking at fbcmap.c, the retval isn't being checked
#   against positive/negative values, so it doesn't make sense to return 1.
#   
#   Signed-off-by: Antonino Daplas <adaplas@pol.net>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/video/skeletonfb.c
#   2005/03/10 00:39:03-08:00 lucasvr@gobolinux.org +13 -7
#   skeletonfb: Documentation fixes
# 
# ChangeSet
#   2005/03/10 09:08:00-08:00 adaplas@gawab.com 
#   [PATCH] kyrofb: copy_*_user return value checks added to kyro fb
#   
#   Here's a patch that makes sure the return value of copy_from/to_user gets
#   checked and handled in drivers/video/kyro/fbdev.c It also updates a comment at
#   the top of the file that lists the files name and location.
#   
#   Signed-off-by: Jesper Juhl <juhl-lkml@dif.dk>
#   Signed-off-by: Antonino Daplas <adaplas@pol.net>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/video/kyro/fbdev.c
#   2005/03/10 00:39:03-08:00 adaplas@gawab.com +12 -7
#   kyrofb: copy_*_user return value checks added to kyro fb
# 
# ChangeSet
#   2005/03/10 09:07:44-08:00 adaplas@gawab.com 
#   [PATCH] w100fb: Make blanking function interrupt safe
#   
#   w100fb bugfix: The blanking function used vmalloc/vfree which isn't interrupt
#   safe.  To avoid problems, switch to kmalloc/kfree and use several buffers to
#   avoid kmalloc size limitations.
#   
#   Signed-off-by: Richard Purdie <rpurdie@rpsys.net>
#   Signed-off-by: Antonino Daplas <adaplas@pol.net>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/video/w100fb.c
#   2005/03/10 00:39:03-08:00 adaplas@gawab.com +35 -24
#   w100fb: Make blanking function interrupt safe
# 
# ChangeSet
#   2005/03/10 09:07:28-08:00 adaplas@gawab.com 
#   [PATCH] radeonfb: Fix spurious error return in FBIO_RADEON_SET_MIRROR
#   
#   FBIO_RADEON_SET_MIRROR always returns with -EINVAL even if successful due to
#   an inappropriate fall-through.
#   
#   Signed-off-by: Andreas Schwab <schwab@suse.de>
#   Signed-off-by: Antonino Daplas <adaplas@pol.net>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/video/aty/radeon_base.c
#   2005/03/10 00:39:03-08:00 adaplas@gawab.com +1 -1
#   radeonfb: Fix spurious error return in FBIO_RADEON_SET_MIRROR
# 
# ChangeSet
#   2005/03/10 09:07:12-08:00 alan@lxorguk.ukuu.org.uk 
#   [PATCH] Ressurrect the esp serial driver
#   
#   Another first pass rescue run.  Fix up for modern locking, make it build
#   and check over.  It could still do with other fixes (sleep_on etc) but it's
#   a start
#   
#   Signed-off-by: Alan Cox <alan@redhat.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/char/esp.c
#   2005/03/10 00:39:03-08:00 alan@lxorguk.ukuu.org.uk +147 -121
#   Ressurrect the esp serial driver
# 
# ChangeSet
#   2005/03/10 09:06:56-08:00 pj@sgi.com 
#   [PATCH] cpusets: make CONFIG_CPUSETS the default in sn2_defconfig
#   
#   Make CONFIG_CPUSETS enabled by default in sn2_defconfig.
#   
#   Signed-off-by: Paul Jackson <pj@sgi.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/ia64/configs/sn2_defconfig
#   2005/03/10 00:39:02-08:00 pj@sgi.com +1 -0
#   cpusets: make CONFIG_CPUSETS the default in sn2_defconfig
# 
# ChangeSet
#   2005/03/10 09:06:39-08:00 pj@sgi.com 
#   [PATCH] cpusets - big numa cpu and memory placement
#   
#   This my cpuset patch, with the following changes in the last two weeks:
#   
#    1) Updated to 2.6.8.1-mm1
#    2) [Simon Derr <Simon.Derr@bull.net>] Fix new cpuset to begin empty,
#       not copied from parent.  Needed to avoid breaking exclusive property.
#    3) [Dinakar Guniguntala <dino@in.ibm.com>] Finish initializing top
#       cpuset from cpu_possible_map after smp_init() called.
#    4) [Paul Jackson <pj@sgi.com>] Check on each call to __alloc_pages()
#       if the current tasks cpuset mems_allowed has changed.  Use a cpuset
#       generation number, bumped on any cpuset memory placement change,
#       to make this check efficient.  Update the tasks mems_allowed from
#       its cpuset, if the cpuset has changed.
#    5) [Paul Jackson <pj@sgi.com>] If a task is moved to another cpuset,
#       then update its cpus_allowed, using set_cpus_allowed().
#    6) [Paul Jackson <pj@sgi.com>] Update Documentation/cpusets.txt to
#       reflect above changes (4) and (5).
#   
#   I continue to recommend the following patch for inclusion in your 2.6.9-*mm
#   series, when that opens.  It provides an important facility for high
#   performance computing on large systems.  Simon Derr of Bull (France) and
#   myself are the primary authors.  Erich Focht has indicated that NEC is also
#   a potential user of this patch on the TX-7 NUMA machines, and that he
#   "would very much welcome the inclusion of cpusets."
#   
#   I offer this update to lkml, in order to invite continued feedback.
#   
#   The one prerequiste patch for this cpuset patch was just posted before this
#   one.  That was a patch to provide a new bitmap list format, of which
#   cpusets is the first user.
#   
#   This patch has been built on top of 2.6.8.1-mm1, for the arch's:
#   
#     i386 x86_64 sparc ia64 powerpc-405 powerpc-750 sparc64
#   
#   with and without CONFIG_CPUSET.  It has been booted and tested on ia64
#   (sn2_defconfig, SN2 hardware).  The 'alpha' arch also built, except for
#   what seems to be an unrelated toolchain problem (crosstool ld sigsegv) in
#   the final link step.
#   
#   ===
#   
#   Cpusets provide a mechanism for assigning a set of CPUs and Memory Nodes to
#   a set of tasks.
#   
#   Cpusets constrain the CPU and Memory placement of tasks to only the
#   processor and memory resources within a tasks current cpuset.  They form a
#   nested hierarchy visible in a virtual file system.  These are the essential
#   hooks, beyond what is already present, required to manage dynamic job
#   placement on large systems.
#   
#   Cpusets require small kernel hooks in init, exit, fork, mempolicy,
#   sched_setaffinity, page_alloc and vmscan.  And they require a "struct
#   cpuset" pointer, a cpuset_mems_generation, and a "mems_allowed" nodemask_t
#   (to go along with the "cpus_allowed" cpumask_t that's already there) in
#   each task struct.
#   
#   These hooks:
#     1) establish and propagate cpusets,
#     2) enforce CPU placement in sched_setaffinity,
#     3) enforce Memory placement in mbind and sys_set_mempolicy,
#     4) restrict page allocation and scanning to mems_allowed, and
#     5) restrict migration and set_cpus_allowed to cpus_allowed.
#   
#   The other required hook, restricting task scheduling to CPUs in a tasks
#   cpus_allowed mask, is already present.
#   
#   Cpusets extend the usefulness of, the existing placement support that was
#   added to Linux 2.6 kernels: sched_setaffinity() for CPU placement, and
#   mbind() and set_mempolicy() for memory placement.  On smaller or dedicated
#   use systems, the existing calls are often sufficient.
#   
#   On larger NUMA systems, running more than one, performance critical, job,
#   it is necessary to be able to manage jobs in their entirety.  This includes
#   providing a job with exclusive CPU and memory that no other job can use,
#   and being able to list all tasks currently in a cpuset.
#   
#   A given job running within a cpuset, would likely use the existing
#   placement calls to manage its CPU and memory placement in more detail.
#   
#   Cpusets are named, nested sets of CPUs and Memory Nodes.  Each cpuset is
#   represented by a directory in the cpuset virtual file system, normally
#   mounted at /dev/cpuset.
#   
#   Each cpuset directory provides the following files, which can be
#   read and written:
#   
#     cpus:
#         List of CPUs allowed to tasks in that cpuset.
#   
#     mems:
#         List of Memory Nodes allowed to tasks in that cpuset.
#   
#     tasks:
#         List of pid's of tasks in that cpuset.
#   
#     cpu_exclusive:
#         Flag (0 or 1) - if set, cpuset has exclusive use of
#         its CPUs (no sibling or cousin cpuset may overlap CPUs).
#   
#     mem_exclusive:
#         Flag (0 or 1) - if set, cpuset has exclusive use of
#         its Memory Nodes (no sibling or cousin may overlap).
#   
#     notify_on_release:
#         Flag (0 or 1) - if set, then /sbin/cpuset_release_agent
#         will be invoked, with the name (/dev/cpuset relative path)
#         of that cpuset in argv[1], when the last user of it (task
#         or child cpuset) goes away.  This supports automatic
#         cleanup of abandoned cpusets.
#   
#   In addition one new filetype is added to the /proc file system:
#   
#     /proc/<pid>/cpuset:
#         For each task (pid), list its cpuset path, relative to the
#         root of the cpuset file system.  This file is read-only.
#   
#   New cpusets are created using 'mkdir' (at the shell or in C).  Old ones are
#   removed using 'rmdir'.  The above files are accessed using read(2) and
#   write(2) system calls, or shell commands such as 'cat' and 'echo'.
#   
#   The CPUs and Memory Nodes in a given cpuset are always a subset of its
#   parent.  The root cpuset has all possible CPUs and Memory Nodes in the
#   system.  A cpuset may be exclusive (cpu or memory) only if its parent is
#   similarly exclusive.
#   
#   See further Documentation/cpusets.txt, at the top of the following
#   patch.
#   
#   
#   /proc interface:
#   
#   It is useful, when learning and making new uses of cpusets and placement to be
#   able to see what are the current value of a tasks cpus_allowed and
#   mems_allowed, which are the actual placement used by the kernel scheduler and
#   memory allocator.
#   
#   The cpus_allowed and mems_allowed values are needed by user space apps that
#   are micromanaging placement, such as when moving an app to a obtained by
#   that app within its cpuset using sched_setaffinity, mbind and
#   set_mempolicy.
#   
#   The cpus_allowed value is also available via the sched_getaffinity system
#   call.  But since the entire rest of the cpuset API, including the display
#   of mems_allowed added here, is via an ascii style presentation in /proc and
#   /dev/cpuset, it is worth the extra couple lines of code to display
#   cpus_allowed in the same way.
#   
#   This patch adds the display of these two fields to the 'status' file in the
#   /proc/<pid> directory of each task.  The fields are only added if
#   CONFIG_CPUSETS is enabled (which is also needed to define the mems_allowed
#   field of each task).  The new output lines look like:
#   
#     $ tail -2 /proc/1/status
#     Cpus_allowed:   ffffffff,ffffffff,ffffffff,ffffffff
#     Mems_allowed:   ffffffff,ffffffff
#   
#   
#   Signed-off-by: Dinakar Guniguntala <dino@in.ibm.com>
#   Signed-off-by: Paul Jackson <pj@sgi.com>
#   Signed-off-by: Adrian Bunk <bunk@stusta.de>
#   Signed-off-by: Simon Derr <simon.derr@bull.net>
#   Signed-off-by: Matt Mackall <mpm@selenic.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# kernel/cpuset.c
#   2005/03/10 00:39:02-08:00 pj@sgi.com +1534 -0
#   cpusets - big numa cpu and memory placement
# 
# include/linux/cpuset.h
#   2005/03/10 00:39:02-08:00 pj@sgi.com +64 -0
#   cpusets - big numa cpu and memory placement
# 
# mm/vmscan.c
#   2005/03/10 00:39:02-08:00 pj@sgi.com +17 -2
#   cpusets - big numa cpu and memory placement
# 
# mm/page_alloc.c
#   2005/03/10 00:39:02-08:00 pj@sgi.com +16 -0
#   cpusets - big numa cpu and memory placement
# 
# mm/mempolicy.c
#   2005/03/10 00:39:02-08:00 pj@sgi.com +12 -1
#   cpusets - big numa cpu and memory placement
# 
# kernel/sched.c
#   2005/03/10 00:39:02-08:00 pj@sgi.com +5 -1
#   cpusets - big numa cpu and memory placement
# 
# kernel/fork.c
#   2005/03/10 00:39:02-08:00 pj@sgi.com +3 -0
#   cpusets - big numa cpu and memory placement
# 
# kernel/exit.c
#   2005/03/10 00:39:02-08:00 pj@sgi.com +2 -0
#   cpusets - big numa cpu and memory placement
# 
# kernel/cpuset.c
#   2005/03/10 00:39:02-08:00 pj@sgi.com +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/kernel/cpuset.c
# 
# kernel/Makefile
#   2005/03/10 00:39:02-08:00 pj@sgi.com +1 -0
#   cpusets - big numa cpu and memory placement
# 
# init/main.c
#   2005/03/10 00:39:02-08:00 pj@sgi.com +5 -0
#   cpusets - big numa cpu and memory placement
# 
# init/Kconfig
#   2005/03/10 00:39:02-08:00 pj@sgi.com +10 -0
#   cpusets - big numa cpu and memory placement
# 
# include/linux/sched.h
#   2005/03/10 00:39:02-08:00 pj@sgi.com +7 -0
#   cpusets - big numa cpu and memory placement
# 
# include/linux/cpuset.h
#   2005/03/10 00:39:02-08:00 pj@sgi.com +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/include/linux/cpuset.h
# 
# fs/proc/base.c
#   2005/03/10 00:39:02-08:00 pj@sgi.com +19 -0
#   cpusets - big numa cpu and memory placement
# 
# fs/proc/array.c
#   2005/03/10 00:39:02-08:00 pj@sgi.com +2 -0
#   cpusets - big numa cpu and memory placement
# 
# Documentation/cpusets.txt
#   2005/03/10 00:39:02-08:00 pj@sgi.com +407 -0
#   cpusets - big numa cpu and memory placement
# 
# Documentation/cpusets.txt
#   2005/03/10 00:39:02-08:00 pj@sgi.com +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/Documentation/cpusets.txt
# 
# ChangeSet
#   2005/03/10 18:06:22+01:00 bzolnier@trik.(none) 
#   [ide] kill ide_driver_t->pre_reset
#   
#   Add ide_drive_t->post_reset flag and use it to signal post reset
#   condition to the ide-tape driver (the only user of ->pre_reset).
#   
#   Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
# 
# ChangeSet
#   2005/03/10 09:06:21-08:00 pj@sgi.com 
#   [PATCH] new bitmap list format (for cpusets)
#   
#   [This is a copy of the bitmap list format patch that I submitted to lkml
#    on 9 Aug 2004, after removing the prefix character fluff^Wstuff.  I
#    include it here again just to get it associated with the current cpuset
#    patch, which will follow in a second email 10 seconds later.  -pj]
#   
#   A bitmap print and parse format that provides lists of ranges of numbers,
#   to be first used for by cpusets (next patch).
#   
#   Cpusets provide a way to manage subsets of CPUs and Memory Nodes for
#   scheduling and memory placement, via a new virtual file system, usually
#   mounted at /dev/cpuset.  Manipulation of cpusets can be done directly via
#   this file system, from the shell.
#   
#   However, manipulating 512 bit cpumasks or 256 bit nodemasks (which will get
#   bigger) via hex mask strings is painful for humans.
#   
#   The intention is to provide a format for the cpu and memory mask files in
#   /dev/cpusets that will stand the test of time.  This format is supported by
#   a couple of new lib/bitmap.c routines, for printing and parsing these
#   strings.  Wrappers for cpumask and nodemask are provided.
#   
#   Signed-off-by: Paul Jackson <pj@sgi.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# lib/bitmap.c
#   2005/03/10 00:39:01-08:00 pj@sgi.com +103 -0
#   new bitmap list format (for cpusets)
# 
# include/linux/nodemask.h
#   2005/03/10 00:39:01-08:00 pj@sgi.com +20 -2
#   new bitmap list format (for cpusets)
# 
# include/linux/cpumask.h
#   2005/03/10 00:39:01-08:00 pj@sgi.com +20 -2
#   new bitmap list format (for cpusets)
# 
# include/linux/bitmap.h
#   2005/03/10 00:39:01-08:00 pj@sgi.com +7 -1
#   new bitmap list format (for cpusets)
# 
# include/linux/ide.h
#   2005/03/10 18:06:00+01:00 bzolnier@trik.(none) +1 -1
#   [ide] kill ide_driver_t->pre_reset
# 
# drivers/ide/ide.c
#   2005/03/10 17:43:42+01:00 bzolnier@trik.(none) +0 -5
#   [ide] kill ide_driver_t->pre_reset
# 
# drivers/ide/ide-tape.c
#   2005/03/10 17:43:42+01:00 bzolnier@trik.(none) +5 -11
#   [ide] kill ide_driver_t->pre_reset
# 
# drivers/ide/ide-iops.c
#   2005/03/10 17:43:42+01:00 bzolnier@trik.(none) +1 -1
#   [ide] kill ide_driver_t->pre_reset
# 
# ChangeSet
#   2005/03/10 09:06:05-08:00 hirofumi@mail.parknet.co.jp 
#   [PATCH] FAT: Fix typo
#   
#   Add a `:'.
#   
#   Signed-off-by: OGAWA Hirofumi <hirofumi@mail.parknet.co.jp>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# fs/fat/misc.c
#   2005/03/10 00:39:01-08:00 hirofumi@mail.parknet.co.jp +1 -1
#   FAT: Fix typo
# 
# ChangeSet
#   2005/03/10 09:05:49-08:00 hirofumi@mail.parknet.co.jp 
#   [PATCH] FAT: Update ->rename() path
#   
#   a) If old_dir == new_dir, we don't need to update the ".." entry,
#      so this doesn't touch it if unneeded.
#   
#   b) old algorithm is using
#            1) add a new entry (doen't point the data cluster yet).
#   	 2) remove a old entry.
#   	 3) switch the data cluster to new entry.
#   	 4) update a ".." entry
#      this order lose the data cluster when between 2) and 3).
#   
#      Instead of above, this is using
#            1) add a new entry (doen't point the data cluster yet).
#   	 2) switch the data cluster to new entry.
#   	 3) update a ".." entry if needed.
#   	 4) remove a old entry.
#      this order would not lose the data cluster, but on disk metadata is
#      corrupted on some point (later, fsck would recover this corruption
#      without losing the data).
#   
#   c) use synchronous update.
#   
#   d) Fix the corrupted directory check created by 1 of new algorithm.
#      1) Fix fat_bmap(). If directory's ->i_start == 0, fat_bmap() is
#         handling it as root directory, this removes that strange behavior.
#      2) On mkdir() path if directory's ->i_start == 0, returns -EIO.
#   
#   Signed-off-by: OGAWA Hirofumi <hirofumi@mail.parknet.co.jp>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# fs/vfat/namei.c
#   2005/03/10 00:39:01-08:00 hirofumi@mail.parknet.co.jp +73 -28
#   FAT: Update ->rename() path
# 
# fs/msdos/namei.c
#   2005/03/10 00:39:01-08:00 hirofumi@mail.parknet.co.jp +86 -26
#   FAT: Update ->rename() path
# 
# fs/fat/misc.c
#   2005/03/10 00:39:01-08:00 hirofumi@mail.parknet.co.jp +2 -0
#   FAT: Update ->rename() path
# 
# fs/fat/dir.c
#   2005/03/10 00:39:01-08:00 hirofumi@mail.parknet.co.jp +8 -1
#   FAT: Update ->rename() path
# 
# fs/fat/cache.c
#   2005/03/10 00:39:01-08:00 hirofumi@mail.parknet.co.jp +1 -3
#   FAT: Update ->rename() path
# 
# ChangeSet
#   2005/03/10 09:05:34-08:00 hirofumi@mail.parknet.co.jp 
#   [PATCH] FAT: Use synchronous update for  {vfat,msdos}_add_entry()
#   
#   Use the synchronous updates, in order to guarantee that the writing to
#   a disk is completeing when a system call returns.
#   
#   Signed-off-by: OGAWA Hirofumi <hirofumi@mail.parknet.co.jp>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# fs/vfat/namei.c
#   2005/03/10 00:39:01-08:00 hirofumi@mail.parknet.co.jp +4 -1
#   FAT: Use synchronous update for  {vfat,msdos}_add_entry()
# 
# fs/msdos/namei.c
#   2005/03/10 00:39:01-08:00 hirofumi@mail.parknet.co.jp +4 -1
#   FAT: Use synchronous update for  {vfat,msdos}_add_entry()
# 
# ChangeSet
#   2005/03/10 09:05:18-08:00 hirofumi@mail.parknet.co.jp 
#   [PATCH] FAT: Fix fat_write_inode()
#   
#   Fix a missing error check for sync_buffer_dirty().
#   
#   Signed-off-by: OGAWA Hirofumi <hirofumi@mail.parknet.co.jp>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# fs/fat/inode.c
#   2005/03/10 00:39:00-08:00 hirofumi@mail.parknet.co.jp +10 -8
#   FAT: Fix fat_write_inode()
# 
# ChangeSet
#   2005/03/10 09:05:02-08:00 hirofumi@mail.parknet.co.jp 
#   [PATCH] FAT: Fix fat_truncate()
#   
#   Instead of
#   	mark_inode_dirty(inode);
#   	if (IS_SYNC(inode))
#   		fat_sync_inode(inode);
#   
#   use this
#   	if (IS_SYNC(inode))
#   		fat_sync_inode(inode);
#   	else
#   		mark_inode_dirty(inode);
#   
#   And if occurs a error, restore the ->i_start and ->i_logstart.
#   
#   Signed-off-by: OGAWA Hirofumi <hirofumi@mail.parknet.co.jp>-
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# fs/fat/file.c
#   2005/03/10 00:39:00-08:00 hirofumi@mail.parknet.co.jp +23 -17
#   FAT: Fix fat_truncate()
# 
# ChangeSet
#   2005/03/10 09:04:46-08:00 hirofumi@mail.parknet.co.jp 
#   [PATCH] FAT: Remove unneed mark_inode_dirty()
#   
#   Some mark_inode_dirty() is unneeded. Those are already detached (it's
#   not written) or change a ->i_nlink count only (fatfs don't have).
#   
#   Signed-off-by: OGAWA Hirofumi <hirofumi@mail.parknet.co.jp>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# fs/vfat/namei.c
#   2005/03/10 00:39:00-08:00 hirofumi@mail.parknet.co.jp +3 -7
#   FAT: Remove unneed mark_inode_dirty()
# 
# fs/msdos/namei.c
#   2005/03/10 00:39:00-08:00 hirofumi@mail.parknet.co.jp +3 -8
#   FAT: Remove unneed mark_inode_dirty()
# 
# ChangeSet
#   2005/03/10 09:04:30-08:00 hirofumi@mail.parknet.co.jp 
#   [PATCH] FAT: Remove the multiple MSDOS_SB() call
#   
#   Since MSDOS_SB() is inline function, it increases text size at each calls.
#   I don't know whether there is __attribute__ for avoiding this.
#   
#   This removes the multiple call.
#   
#   Signed-off-by: OGAWA Hirofumi <hirofumi@mail.parknet.co.jp>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# fs/vfat/namei.c
#   2005/03/10 00:39:00-08:00 hirofumi@mail.parknet.co.jp +4 -4
#   FAT: Remove the multiple MSDOS_SB() call
# 
# fs/fat/dir.c
#   2005/03/10 00:39:00-08:00 hirofumi@mail.parknet.co.jp +16 -14
#   FAT: Remove the multiple MSDOS_SB() call
# 
# ChangeSet
#   2005/03/10 09:04:13-08:00 hirofumi@mail.parknet.co.jp 
#   [PATCH] FAT: "i_pos" cleanup
#   
#   The "i_pos" can calculate later, so this makes the "i_pos" when it's needed.
#   
#   Signed-off-by: OGAWA Hirofumi <hirofumi@mail.parknet.co.jp>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# fs/fat/dir.c
#   2005/03/10 00:38:59-08:00 hirofumi@mail.parknet.co.jp +39 -31
#   FAT: "i_pos" cleanup
# 
# ChangeSet
#   2005/03/10 09:03:57-08:00 hirofumi@mail.parknet.co.jp 
#   [PATCH] FAT: make the fat_get_entry()/fat__get_entry() static
#   
#   Signed-off-by: OGAWA Hirofumi <hirofumi@mail.parknet.co.jp>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/linux/msdos_fs.h
#   2005/03/10 00:38:59-08:00 hirofumi@mail.parknet.co.jp +0 -17
#   FAT: make the fat_get_entry()/fat__get_entry() static
# 
# fs/fat/misc.c
#   2005/03/10 00:38:59-08:00 hirofumi@mail.parknet.co.jp +0 -50
#   FAT: make the fat_get_entry()/fat__get_entry() static
# 
# fs/fat/dir.c
#   2005/03/10 00:38:59-08:00 hirofumi@mail.parknet.co.jp +63 -0
#   FAT: make the fat_get_entry()/fat__get_entry() static
# 
# ChangeSet
#   2005/03/10 09:03:41-08:00 hirofumi@mail.parknet.co.jp 
#   [PATCH] FAT: Use fat_remove_entries() for msdos
#   
#   Signed-off-by: OGAWA Hirofumi <hirofumi@mail.parknet.co.jp>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# fs/msdos/namei.c
#   2005/03/10 00:38:59-08:00 hirofumi@mail.parknet.co.jp +17 -20
#   FAT: Use fat_remove_entries() for msdos
# 
# ChangeSet
#   2005/03/10 09:03:26-08:00 hirofumi@mail.parknet.co.jp 
#   [PATCH] FAT: Rewrite fat_add_entries()
#   
#   In order not to write out the same block repeatedly, rewrite the
#   fat_add_entries().
#   
#   Signed-off-by: OGAWA Hirofumi <hirofumi@mail.parknet.co.jp>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/linux/msdos_fs.h
#   2005/03/10 00:38:59-08:00 hirofumi@mail.parknet.co.jp +2 -3
#   FAT: Rewrite fat_add_entries()
# 
# fs/vfat/namei.c
#   2005/03/10 00:38:59-08:00 hirofumi@mail.parknet.co.jp +3 -32
#   FAT: Rewrite fat_add_entries()
# 
# fs/msdos/namei.c
#   2005/03/10 00:38:59-08:00 hirofumi@mail.parknet.co.jp +4 -9
#   FAT: Rewrite fat_add_entries()
# 
# fs/fat/dir.c
#   2005/03/10 00:38:59-08:00 hirofumi@mail.parknet.co.jp +189 -72
#   FAT: Rewrite fat_add_entries()
# 
# ChangeSet
#   2005/03/10 09:03:09-08:00 hirofumi@mail.parknet.co.jp 
#   [PATCH] FAT: Allocate the cluster before adding the directory  entry
#   
#   With this change, ->mkdir() uses the correct updating order.
#   
#   Signed-off-by: OGAWA Hirofumi <hirofumi@mail.parknet.co.jp>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/linux/msdos_fs.h
#   2005/03/10 00:38:58-08:00 hirofumi@mail.parknet.co.jp +1 -1
#   FAT: Allocate the cluster before adding the directory  entry
# 
# fs/vfat/namei.c
#   2005/03/10 00:38:58-08:00 hirofumi@mail.parknet.co.jp +29 -30
#   FAT: Allocate the cluster before adding the directory  entry
# 
# fs/msdos/namei.c
#   2005/03/10 00:38:58-08:00 hirofumi@mail.parknet.co.jp +24 -30
#   FAT: Allocate the cluster before adding the directory  entry
# 
# fs/fat/fatent.c
#   2005/03/10 00:38:58-08:00 hirofumi@mail.parknet.co.jp +3 -0
#   FAT: Allocate the cluster before adding the directory  entry
# 
# fs/fat/dir.c
#   2005/03/10 00:38:58-08:00 hirofumi@mail.parknet.co.jp +112 -43
#   FAT: Allocate the cluster before adding the directory  entry
# 
# ChangeSet
#   2005/03/10 09:02:54-08:00 hirofumi@mail.parknet.co.jp 
#   [PATCH] FAT: msdos_add_entry() cleanup
#   
#   The msdos_add_entry() use similar interface to vfat_add_entry().  And use a
#   same timestamp on some operations path.
#   
#   Signed-off-by: OGAWA Hirofumi <hirofumi@mail.parknet.co.jp>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# fs/msdos/namei.c
#   2005/03/10 00:38:58-08:00 hirofumi@mail.parknet.co.jp +84 -78
#   FAT: msdos_add_entry() cleanup
# 
# ChangeSet
#   2005/03/10 09:02:38-08:00 hirofumi@mail.parknet.co.jp 
#   [PATCH] FAT: msdos_rename() cleanup
#   
#   Cleans up the msdos_rename(). (use the logic similar to vfat_rename().)
#   
#   Signed-off-by: OGAWA Hirofumi <hirofumi@mail.parknet.co.jp>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# fs/msdos/namei.c
#   2005/03/10 00:38:58-08:00 hirofumi@mail.parknet.co.jp +88 -85
#   FAT: msdos_rename() cleanup
# 
# ChangeSet
#   2005/03/10 09:02:22-08:00 hirofumi@mail.parknet.co.jp 
#   [PATCH] FAT: Use a same timestamp on some operations path
#   
#   Signed-off-by: OGAWA Hirofumi <hirofumi@mail.parknet.co.jp>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# fs/vfat/namei.c
#   2005/03/10 00:38:58-08:00 hirofumi@mail.parknet.co.jp +35 -28
#   FAT: Use a same timestamp on some operations path
# 
# ChangeSet
#   2005/03/10 09:02:06-08:00 hirofumi@mail.parknet.co.jp 
#   [PATCH] FAT: vfat_build_slots() cleanup
#   
#   With this, the vfat_build_slots() builds the completely data including the
#   timestamp and cluster.  (But this is not using "cluster", it's not complete
#   yet)
#   
#   Signed-off-by: OGAWA Hirofumi <hirofumi@mail.parknet.co.jp>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# fs/vfat/namei.c
#   2005/03/10 00:38:58-08:00 hirofumi@mail.parknet.co.jp +52 -58
#   FAT: vfat_build_slots() cleanup
# 
# ChangeSet
#   2005/03/10 09:01:49-08:00 hirofumi@mail.parknet.co.jp 
#   [PATCH] FAT: Use "struct fat_slot_info" for msdos_find()
#   
#   The msdos_find() provide the "struct fat_slot_info". Then some cleanups.
#   
#   Signed-off-by: OGAWA Hirofumi <hirofumi@mail.parknet.co.jp>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# fs/msdos/namei.c
#   2005/03/10 00:38:57-08:00 hirofumi@mail.parknet.co.jp +36 -52
#   FAT: Use "struct fat_slot_info" for msdos_find()
# 
# ChangeSet
#   2005/03/10 09:01:33-08:00 hirofumi@mail.parknet.co.jp 
#   [PATCH] FAT: Use "struct fat_slot_info" for fat_scan()
#   
#   Use "struct fat_slot_info" for fat_scan().  But ".." entry can not provide
#   valid informations for inode, so add the fat_get_dotdot_entry() as special
#   case.
#   
#   Signed-off-by: OGAWA Hirofumi <hirofumi@mail.parknet.co.jp>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/linux/msdos_fs.h
#   2005/03/10 00:38:57-08:00 hirofumi@mail.parknet.co.jp +3 -2
#   FAT: Use "struct fat_slot_info" for fat_scan()
# 
# fs/vfat/namei.c
#   2005/03/10 00:38:57-08:00 hirofumi@mail.parknet.co.jp +6 -10
#   FAT: Use "struct fat_slot_info" for fat_scan()
# 
# fs/msdos/namei.c
#   2005/03/10 00:38:57-08:00 hirofumi@mail.parknet.co.jp +47 -37
#   FAT: Use "struct fat_slot_info" for fat_scan()
# 
# fs/fat/inode.c
#   2005/03/10 00:38:57-08:00 hirofumi@mail.parknet.co.jp +1 -1
#   FAT: Use "struct fat_slot_info" for fat_scan()
# 
# fs/fat/dir.c
#   2005/03/10 00:38:57-08:00 hirofumi@mail.parknet.co.jp +31 -10
#   FAT: Use "struct fat_slot_info" for fat_scan()
# 
# ChangeSet
#   2005/03/10 09:01:17-08:00 hirofumi@mail.parknet.co.jp 
#   [PATCH] FAT: fat_build_inode() cleanup
#   
#   Just use ERR_PTR() instead of getting the error code by additional
#   argument.
#   
#   Signed-off-by: OGAWA Hirofumi <hirofumi@mail.parknet.co.jp>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/linux/msdos_fs.h
#   2005/03/10 00:38:57-08:00 hirofumi@mail.parknet.co.jp +1 -1
#   FAT: fat_build_inode() cleanup
# 
# fs/vfat/namei.c
#   2005/03/10 00:38:57-08:00 hirofumi@mail.parknet.co.jp +11 -8
#   FAT: fat_build_inode() cleanup
# 
# fs/msdos/namei.c
#   2005/03/10 00:38:57-08:00 hirofumi@mail.parknet.co.jp +10 -7
#   FAT: fat_build_inode() cleanup
# 
# fs/fat/inode.c
#   2005/03/10 00:38:57-08:00 hirofumi@mail.parknet.co.jp +30 -32
#   FAT: fat_build_inode() cleanup
# 
# ChangeSet
#   2005/03/10 09:01:01-08:00 hirofumi@mail.parknet.co.jp 
#   [PATCH] FAT: Add fat_remove_entries()
#   
#   This changes the fat_slot_info->nr_slot, now it's total counts which
#   include a shortname entry.  And this adds a fat_remove_entries()
#   which use the ->nr_slots.
#   
#   In order not to write out the same block repeatedly,
#   fat_remove_entries() was rewritten from vfat_remove_entries().
#   
#   Signed-off-by: OGAWA Hirofumi <hirofumi@mail.parknet.co.jp>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/linux/msdos_fs.h
#   2005/03/10 00:38:56-08:00 hirofumi@mail.parknet.co.jp +1 -0
#   FAT: Add fat_remove_entries()
# 
# fs/vfat/namei.c
#   2005/03/10 00:38:56-08:00 hirofumi@mail.parknet.co.jp +27 -54
#   FAT: Add fat_remove_entries()
# 
# fs/fat/dir.c
#   2005/03/10 00:38:56-08:00 hirofumi@mail.parknet.co.jp +96 -7
#   FAT: Add fat_remove_entries()
# 
# ChangeSet
#   2005/03/10 09:00:46-08:00 hirofumi@mail.parknet.co.jp 
#   [PATCH] FAT: Use "struct fat_slot_info" for fat_search_long()
#   
#   The fat_search_long() provide the "struct fat_slot_info" by this
#   change.  So, vfat_find() became to be enough simple, and it just
#   returns 0 or error.
#   
#   And the error check of vfat_find() is also simplify.
#   
#   Signed-off-by: OGAWA Hirofumi <hirofumi@mail.parknet.co.jp>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/linux/msdos_fs.h
#   2005/03/10 00:38:56-08:00 hirofumi@mail.parknet.co.jp +1 -2
#   FAT: Use "struct fat_slot_info" for fat_search_long()
# 
# fs/vfat/namei.c
#   2005/03/10 00:38:56-08:00 hirofumi@mail.parknet.co.jp +38 -51
#   FAT: Use "struct fat_slot_info" for fat_search_long()
# 
# fs/fat/dir.c
#   2005/03/10 00:38:56-08:00 hirofumi@mail.parknet.co.jp +15 -11
#   FAT: Use "struct fat_slot_info" for fat_search_long()
# 
# ChangeSet
#   2005/03/10 09:00:30-08:00 hirofumi@mail.parknet.co.jp 
#   [PATCH] FAT: "struct vfat_slot_info" cleanup
#   
#   Add "struct fat_slot_info" for updating data of the directory entries.
#   
#    1) Rename "struct vfat_slot_info" to "struct fat_slot_info"
#    2) Add "de" and "bh" to fat_slot_info instead of using argument.
#    3) Replace the "vfat_slot_info + de + bh" by new fat_slot_info
#   
#   Signed-off-by: OGAWA Hirofumi <hirofumi@mail.parknet.co.jp>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/linux/msdos_fs.h
#   2005/03/10 00:38:56-08:00 hirofumi@mail.parknet.co.jp +5 -3
#   FAT: "struct vfat_slot_info" cleanup
# 
# fs/vfat/namei.c
#   2005/03/10 00:38:56-08:00 hirofumi@mail.parknet.co.jp +56 -70
#   FAT: "struct vfat_slot_info" cleanup
# 
# ChangeSet
#   2005/03/10 09:00:15-08:00 hirofumi@mail.parknet.co.jp 
#   [PATCH] FAT: Use "unsigned int" for ->free_clusters and  ->prev_free
#   
#   This changes ->free_clusters and ->prev_free from "int" to "unsigned int". 
#   These value should be never negative value (but it's using 0xffffffff(-1) as
#   undefined state).
#   
#   With this changes, fatfs would handle the corruption of free_clusters
#   more proper.
#   
#   Signed-off-by: OGAWA Hirofumi <hirofumi@mail.parknet.co.jp>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# ChangeSet
#   2005/03/10 18:00:07+01:00 bzolnier@trik.(none) 
#   [ide] fix some rare ide-default vs ide-disk races
#   
#   Some rare races between ide-default and ide-disk are possible, i.e.:
#   * ide-default is used, I/O request is triggered (ie. /proc/ide/hd?/identify),
#     drive->special is cleared silently (so CHS is not initialized properly),
#     ide-disk is loaded and fails if drive uses CHS
#   * ide-disk is used, drive is resetted, ide-disk is unloaded, ide-default
#     takes control over drive and on the first I/O request silently clears
#     drive->special without restoring settings
#   
#   Fix them by moving idedisk_{special,pre_reset}() and company to IDE core.
#   
#   Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
# 
# include/linux/msdos_fs.h
#   2005/03/10 00:38:55-08:00 hirofumi@mail.parknet.co.jp +2 -2
#   FAT: Use "unsigned int" for ->free_clusters and  ->prev_free
# 
# fs/fat/inode.c
#   2005/03/10 00:38:55-08:00 hirofumi@mail.parknet.co.jp +5 -1
#   FAT: Use "unsigned int" for ->free_clusters and  ->prev_free
# 
# fs/fat/fatent.c
#   2005/03/10 00:38:55-08:00 hirofumi@mail.parknet.co.jp +1 -2
#   FAT: Use "unsigned int" for ->free_clusters and  ->prev_free
# 
# ChangeSet
#   2005/03/10 08:59:58-08:00 hirofumi@mail.parknet.co.jp 
#   [PATCH] FAT: add debugging code to fatent.c
#   
#   Signed-off-by: OGAWA Hirofumi <hirofumi@mail.parknet.co.jp>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/linux/ide.h
#   2005/03/10 17:43:31+01:00 bzolnier@trik.(none) +0 -1
#   [ide] fix some rare ide-default vs ide-disk races
# 
# drivers/ide/ide.c
#   2005/03/10 17:43:31+01:00 bzolnier@trik.(none) +0 -10
#   [ide] fix some rare ide-default vs ide-disk races
# 
# drivers/ide/ide-taskfile.c
#   2005/03/10 17:43:31+01:00 bzolnier@trik.(none) +0 -6
#   [ide] fix some rare ide-default vs ide-disk races
# 
# drivers/ide/ide-probe.c
#   2005/03/10 17:43:31+01:00 bzolnier@trik.(none) +58 -2
#   [ide] fix some rare ide-default vs ide-disk races
# 
# drivers/ide/ide-iops.c
#   2005/03/10 17:59:37+01:00 bzolnier@trik.(none) +19 -1
#   [ide] fix some rare ide-default vs ide-disk races
# 
# drivers/ide/ide-io.c
#   2005/03/10 17:43:31+01:00 bzolnier@trik.(none) +66 -2
#   [ide] fix some rare ide-default vs ide-disk races
# 
# drivers/ide/ide-disk.c
#   2005/03/10 17:43:31+01:00 bzolnier@trik.(none) +0 -108
#   [ide] fix some rare ide-default vs ide-disk races
# 
# drivers/ide/Kconfig
#   2005/03/10 17:43:31+01:00 bzolnier@trik.(none) +0 -1
#   [ide] fix some rare ide-default vs ide-disk races
# 
# include/linux/msdos_fs.h
#   2005/03/10 00:38:55-08:00 hirofumi@mail.parknet.co.jp +6 -0
#   FAT: add debugging code to fatent.c
# 
# fs/fat/fatent.c
#   2005/03/10 00:38:55-08:00 hirofumi@mail.parknet.co.jp +20 -0
#   FAT: add debugging code to fatent.c
# 
# ChangeSet
#   2005/03/10 08:59:42-08:00 hirofumi@mail.parknet.co.jp 
#   [PATCH] FAT: Rewrite the FAT (File Allocation Table) access  stuff
#   
#   In order not to write the same block repeatedly, rewrite the FAT entry access
#   stuff.
#   
#   And this separates the "allocate the cluster" and "link to cluster chain"
#   operations for expanding the file/dir safely.  (fat_alloc_clusters() allocates
#   the cluster, and fat_chain_add() links allocated cluster to the chain which
#   inode has.)
#   
#   Signed-off-by: OGAWA Hirofumi <hirofumi@mail.parknet.co.jp>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/linux/msdos_fs.h
#   2005/03/10 00:38:55-08:00 hirofumi@mail.parknet.co.jp +47 -10
#   FAT: Rewrite the FAT (File Allocation Table) access  stuff
# 
# fs/fat/misc.c
#   2005/03/10 00:38:55-08:00 hirofumi@mail.parknet.co.jp +56 -66
#   FAT: Rewrite the FAT (File Allocation Table) access  stuff
# 
# fs/fat/inode.c
#   2005/03/10 00:38:55-08:00 hirofumi@mail.parknet.co.jp +29 -31
#   FAT: Rewrite the FAT (File Allocation Table) access  stuff
# 
# fs/fat/file.c
#   2005/03/10 00:38:55-08:00 hirofumi@mail.parknet.co.jp +35 -34
#   FAT: Rewrite the FAT (File Allocation Table) access  stuff
# 
# fs/fat/fatent.c
#   2005/03/10 00:38:55-08:00 hirofumi@mail.parknet.co.jp +590 -0
#   FAT: Rewrite the FAT (File Allocation Table) access  stuff
# 
# fs/fat/dir.c
#   2005/03/10 00:38:55-08:00 hirofumi@mail.parknet.co.jp +10 -5
#   FAT: Rewrite the FAT (File Allocation Table) access  stuff
# 
# fs/fat/cache.c
#   2005/03/10 00:38:55-08:00 hirofumi@mail.parknet.co.jp +13 -132
#   FAT: Rewrite the FAT (File Allocation Table) access  stuff
# 
# fs/fat/Makefile
#   2005/03/10 00:38:55-08:00 hirofumi@mail.parknet.co.jp +1 -1
#   FAT: Rewrite the FAT (File Allocation Table) access  stuff
# 
# fs/fat/fatent.c
#   2005/03/10 00:38:55-08:00 hirofumi@mail.parknet.co.jp +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/fs/fat/fatent.c
# 
# ChangeSet
#   2005/03/10 08:59:25-08:00 hirofumi@mail.parknet.co.jp 
#   [PATCH] let fat handle MS_SYNCHRONOUS flag
#   
#   Adds MS_SYNCHRONOUS flag support.
#   
#   Signed-off-by: Colin Leroy <colin@colino.net>
#   Signed-off-by: OGAWA Hirofumi <hirofumi@mail.parknet.co.jp>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/linux/msdos_fs.h
#   2005/03/10 00:38:55-08:00 hirofumi@mail.parknet.co.jp +1 -0
#   let fat handle MS_SYNCHRONOUS flag
# 
# fs/vfat/namei.c
#   2005/03/10 00:38:55-08:00 hirofumi@mail.parknet.co.jp +24 -7
#   let fat handle MS_SYNCHRONOUS flag
# 
# fs/fat/misc.c
#   2005/03/10 00:38:55-08:00 hirofumi@mail.parknet.co.jp +2 -0
#   let fat handle MS_SYNCHRONOUS flag
# 
# fs/fat/inode.c
#   2005/03/10 00:38:55-08:00 hirofumi@mail.parknet.co.jp +10 -0
#   let fat handle MS_SYNCHRONOUS flag
# 
# fs/fat/file.c
#   2005/03/10 00:38:55-08:00 hirofumi@mail.parknet.co.jp +5 -0
#   let fat handle MS_SYNCHRONOUS flag
# 
# fs/fat/dir.c
#   2005/03/10 00:38:55-08:00 hirofumi@mail.parknet.co.jp +17 -9
#   let fat handle MS_SYNCHRONOUS flag
# 
# fs/fat/cache.c
#   2005/03/10 00:38:55-08:00 hirofumi@mail.parknet.co.jp +8 -0
#   let fat handle MS_SYNCHRONOUS flag
# 
# ChangeSet
#   2005/03/10 08:59:09-08:00 hirofumi@mail.parknet.co.jp 
#   [PATCH] FAT: fat_readdirx() with dotOK=yes fix
#   
#   In the case of dotsOK, re-initialization of "ptname" pointer is needed,
#   otherwise, "ptname" is pointing the previous start position.
#   
#   This fixes it.
#   
#   Signed-off-by: OGAWA Hirofumi <hirofumi@mail.parknet.co.jp>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# fs/fat/dir.c
#   2005/03/10 00:38:54-08:00 hirofumi@mail.parknet.co.jp +7 -3
#   FAT: fat_readdirx() with dotOK=yes fix
# 
# ChangeSet
#   2005/03/10 08:58:53-08:00 hirofumi@mail.parknet.co.jp 
#   [PATCH] FAT: Updated FAT attributes patch
#   
#   This updates the FAT attributes as well as (hopefully) corrects the handling
#   of VFAT ctime.  The FAT attributes are implemented as a 32-bit ioctl, per the
#   previous discussions.
#   
#   Signed-Off-By: H. Peter Anvin <hpa@zytor.com>
#   Signed-off-by: OGAWA Hirofumi <hirofumi@mail.parknet.co.jp>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/linux/msdos_fs.h
#   2005/03/10 00:38:54-08:00 hirofumi@mail.parknet.co.jp +16 -6
#   FAT: Updated FAT attributes patch
# 
# fs/vfat/namei.c
#   2005/03/10 00:38:54-08:00 hirofumi@mail.parknet.co.jp +1 -1
#   FAT: Updated FAT attributes patch
# 
# fs/fat/inode.c
#   2005/03/10 00:38:54-08:00 hirofumi@mail.parknet.co.jp +18 -20
#   FAT: Updated FAT attributes patch
# 
# fs/fat/file.c
#   2005/03/10 00:38:54-08:00 hirofumi@mail.parknet.co.jp +99 -0
#   FAT: Updated FAT attributes patch
# 
# fs/fat/dir.c
#   2005/03/10 00:38:54-08:00 hirofumi@mail.parknet.co.jp +1 -1
#   FAT: Updated FAT attributes patch
# 
# ChangeSet
#   2005/03/10 08:58:38-08:00 hirofumi@mail.parknet.co.jp 
#   [PATCH] fat: fix writev(), add aio support
#   
#   With Christoph Hellwig <hch@lst.de>
#   
#   These patches adds the `-o sync' and `-o dirsync' supports to fatfs.  If user
#   specified that option, the fatfs does traditional ordered updates by using
#   synchronous writes.  If compared to before, these patches will show a
#   improvement of robustness I think.
#   
#   `-o sync'    - writes all buffers out before returning from syscall.
#   `-o dirsync' - writes the directory's metadata, and unreferencing
#                  operations of data block.
#   
#       remaining to be done
#            fat_generic_ioctl(), fat_notify_change(),
#   	 ATTR_ARCH of fat_xxx_write[v],
#   	 and probably, filling hole in cont_prepare_write(),
#   
#   NOTE: Since fatfs doesn't have link-count, unfortunately ->rename() is
#   not safe order at all.  It may make the shared blocks, but user
#   shouldn't lose the data by ->rename().
#   
#   If you test this, please use the dosfstools at
#   
#   	http://www.zip.com.au/~akpm/linux/patches/stuff/fatfsprogs.tar.bz2
#   
#   This is fixing several bugs of dosfstools.  And "2/29" patch from hpa adds new
#   ioctl, the attached archive is also including the commands for testing it.
#   
#   
#   This patch fixes vectored write support on fat to do the nessecary
#   non-standard action done in write() aswell.
#   
#   Also adds aio support and makes read/write wrappers around the aio
#   version.
#   
#   Signed-off-by: OGAWA Hirofumi <hirofumi@mail.parknet.co.jp>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# fs/fat/file.c
#   2005/03/10 00:38:54-08:00 hirofumi@mail.parknet.co.jp +24 -7
#   fat: fix writev(), add aio support
# 
# ChangeSet
#   2005/03/10 08:58:22-08:00 bfields@fieldses.org 
#   [PATCH] nfs4: Error checking on the results of nfsd4_lookupcred()
#   
#   Removing the spurious (!clnt) check, as in the following, will also simplify
#   that conflict resolution a bit.
#   
#   Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# fs/nfsd/nfs4callback.c
#   2005/03/10 00:38:54-08:00 bfields@fieldses.org +8 -9
#   nfs4: Error checking on the results of nfsd4_lookupcred()
# 
# ChangeSet
#   2005/03/10 08:58:06-08:00 gam3@gam3.net 
#   [PATCH] Fix error reported by nfsd which it gets ETXTBSY
#   
#   ETXTBSY doesn't have a direct anaolog in NFS, so just map it to nfserr_io.
#   
#   As this is the default error code this does not change the operation of nfsd. 
#   It only reduces logging.
#   
#   Signed-off-by: Neil Brown <neilb@cse.unsw.edu.au>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# fs/nfsd/nfsproc.c
#   2005/03/10 00:38:53-08:00 gam3@gam3.net +1 -0
#   Fix error reported by nfsd which it gets ETXTBSY
# 
# ChangeSet
#   2005/03/10 08:57:51-08:00 neilb@cse.unsw.edu.au 
#   [PATCH] nfsd: replace schedule_timeout() with msleep()
#   
#   Use msleep() instead of schedule_timeout() to guarantee the task
#   delays as expected.
#   
#   Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
#   Signed-off-by: Domen Puncer <domen@coderock.org>
#   Signed-off-by: Neil Brown <neilb@cse.unsw.edu.au>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# fs/nfsd/vfs.c
#   2005/03/10 00:38:53-08:00 neilb@cse.unsw.edu.au +2 -2
#   nfsd: replace schedule_timeout() with msleep()
# 
# ChangeSet
#   2005/03/10 08:57:36-08:00 neilb@cse.unsw.edu.au 
#   [PATCH] nfsd4: eliminate unnecessary remove_lease
#   
#   Get rid of remove_lease, use setlease() with F_UNLCK
#   
#   Signed-off-by: Andy Adamson <andros@citi.umich.edu>
#   Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
#   Signed-off-by: Neil Brown <neilb@cse.unsw.edu.au>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/linux/fs.h
#   2005/03/10 00:38:53-08:00 neilb@cse.unsw.edu.au +0 -1
#   nfsd4: eliminate unnecessary remove_lease
# 
# fs/nfsd/nfs4state.c
#   2005/03/10 00:38:53-08:00 neilb@cse.unsw.edu.au +1 -2
#   nfsd4: eliminate unnecessary remove_lease
# 
# fs/locks.c
#   2005/03/10 00:38:53-08:00 neilb@cse.unsw.edu.au +1 -19
#   nfsd4: eliminate unnecessary remove_lease
# 
# ChangeSet
#   2005/03/10 08:57:19-08:00 neilb@cse.unsw.edu.au 
#   [PATCH] nfsd4: move delegation decisions to lock_manager callbacks
#   
#   Remove nfs4_check_deleg_recall().  Move its checks into __setlease() via two
#   new lock_manager callbacks, fl_mylease and fl_change, so that all leases (not
#   just NFSv4 lease as with nfs4_check_deleg_recall) are checked.  Default
#   implementations of fl_mylease and fl_change are provided for the sake of the
#   fcntl_setlease interface.  Both callbacks must always be defined.
#   
#   fl_mylease: 
#   
#      for the NFSv4 server, this check is used to see if an existing lease
#      comes from the same client.  For the fcntl_setlease interface, the existing
#      logic is preserved.  the fl_mylease check sees if the existing lease is
#      from the input filp.
#   
#   fl_change: called if the fl_mylease returns true
#   
#      the NFSv4 server does not hand out a delegation to a client that already
#      has one.  -EAGAIN is returned.  Otherwise lease_modify is used.  For the
#      fcntl_setlease interface, the exisiting logic is preserved: The callback
#      used in lease_modify().
#   
#   Signed-off-by: Andy Adamson <andros@citi.umich.edu>
#   Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
#   Signed-off-by: Neil Brown <neilb@cse.unsw.edu.au>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/linux/fs.h
#   2005/03/10 00:38:53-08:00 neilb@cse.unsw.edu.au +3 -0
#   nfsd4: move delegation decisions to lock_manager callbacks
# 
# fs/nfsd/nfs4state.c
#   2005/03/10 00:38:53-08:00 neilb@cse.unsw.edu.au +51 -42
#   nfsd4: move delegation decisions to lock_manager callbacks
# 
# fs/locks.c
#   2005/03/10 00:38:53-08:00 neilb@cse.unsw.edu.au +12 -3
#   nfsd4: move delegation decisions to lock_manager callbacks
# 
# ChangeSet
#   2005/03/10 08:57:03-08:00 neilb@cse.unsw.edu.au 
#   [PATCH] locks: remove unnecessary BUG()
#   
#   We get a NULL dereference here anyway, no need to BUG() explicitly.
#   
#   Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
#   Signed-off-by: Neil Brown <neilb@cse.unsw.edu.au>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# fs/locks.c
#   2005/03/10 00:38:52-08:00 neilb@cse.unsw.edu.au +2 -4
#   locks: remove unnecessary BUG()
# 
# ChangeSet
#   2005/03/10 08:56:47-08:00 neilb@cse.unsw.edu.au 
#   [PATCH] nfsd4: fix_release_state_owner prototype
#   
#   Note that the second parameter is unused.
#   
#   Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
#   Signed-off-by: Neil Brown <neilb@cse.unsw.edu.au>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# fs/nfsd/nfs4state.c
#   2005/03/10 00:38:52-08:00 neilb@cse.unsw.edu.au +3 -4
#   nfsd4: fix_release_state_owner prototype
# 
# ChangeSet
#   2005/03/10 08:56:31-08:00 neilb@cse.unsw.edu.au 
#   [PATCH] nfsd4: fix delegation refcount leak
#   
#   It is the responsibility of the code that runs in the do_recall thread to drop
#   the reference to the delegation.  So if we fail to run that thread, then we
#   need to do it ourselves here.
#   
#   Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
#   Signed-off-by: Neil Brown <neilb@cse.unsw.edu.au>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# fs/nfsd/nfs4state.c
#   2005/03/10 00:38:52-08:00 neilb@cse.unsw.edu.au +1 -0
#   nfsd4: fix delegation refcount leak
# 
# ChangeSet
#   2005/03/10 08:56:15-08:00 neilb@cse.unsw.edu.au 
#   [PATCH] nfsd4: remove dl_state
#   
#   The dl_state flag isn't actually useful.
#   
#   Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
#   Signed-off-by: Neil Brown <neilb@cse.unsw.edu.au>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/linux/nfsd/state.h
#   2005/03/10 00:38:52-08:00 neilb@cse.unsw.edu.au +0 -7
#   nfsd4: remove dl_state
# 
# fs/nfsd/nfs4state.c
#   2005/03/10 00:38:52-08:00 neilb@cse.unsw.edu.au +5 -18
#   nfsd4: remove dl_state
# 
# fs/nfsd/nfs4callback.c
#   2005/03/10 00:38:52-08:00 neilb@cse.unsw.edu.au +0 -1
#   nfsd4: remove dl_state
# 
# ChangeSet
#   2005/03/10 08:55:59-08:00 neilb@cse.unsw.edu.au 
#   [PATCH] nfsd4: allow io to use deleg stateid file
#   
#   Allow io using a delegation stateid to proceed without the need to reopen the
#   file, as is done already with open stateid's.
#   
#   Signed-off-by: Andy Adamson <andros@citi.umich.edu>
#   Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
#   Signed-off-by: Neil Brown <neilb@cse.unsw.edu.au>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# fs/nfsd/nfs4state.c
#   2005/03/10 00:38:51-08:00 neilb@cse.unsw.edu.au +2 -0
#   nfsd4: allow io to use deleg stateid file
# 
# ChangeSet
#   2005/03/10 08:55:43-08:00 neilb@cse.unsw.edu.au 
#   [PATCH] nfsd4: fix sleep under spinlock
#   
#   We shouldn't be calling release_deleg under a spinlock.
#   
#   Signed-off-by: Andy Adamson <andros@citi.umich.edu>
#   Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
#   Signed-off-by: Neil Brown <neilb@cse.unsw.edu.au>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# ChangeSet
#   2005/03/10 17:55:36+01:00 bzolnier@trik.(none) 
#   [ide] generic Power Management for IDE devices
#   
#   Move PM code from ide-cd.c and ide-disk.c to IDE core so:
#   * PM is supported for other ATAPI devices (floppy, tape)
#   * PM is supported even if specific driver is not loaded
#   
#   Also s/HWIF(drive)/drive->hwif/ while at it.
#   
#   Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
# 
# fs/nfsd/nfs4state.c
#   2005/03/10 00:38:51-08:00 neilb@cse.unsw.edu.au +28 -7
#   nfsd4: fix sleep under spinlock
# 
# ChangeSet
#   2005/03/10 08:55:27-08:00 neilb@cse.unsw.edu.au 
#   [PATCH] nfsd4: fix delegation filp sharing
#   
#   The st_vfs_file pointer is set when the open that originally got the delegation
#   is closed, and then in release_deleg we attempt to distinguish between the case
#   when the original open has been closed and when it hasn't.  The resulting logic
#   is complicated and buggy.
#   
#   It's much simpler just to keep a reference count on the struct file.
#   
#   Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
#   Signed-off-by: Neil Brown <neilb@cse.unsw.edu.au>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/linux/ide.h
#   2005/03/10 17:55:25+01:00 bzolnier@trik.(none) +0 -2
#   [ide] generic Power Management for IDE devices
# 
# drivers/ide/ide.c
#   2005/03/10 17:55:25+01:00 bzolnier@trik.(none) +0 -9
#   [ide] generic Power Management for IDE devices
# 
# drivers/ide/ide-io.c
#   2005/03/10 17:55:25+01:00 bzolnier@trik.(none) +95 -2
#   [ide] generic Power Management for IDE devices
# 
# drivers/ide/ide-disk.c
#   2005/03/10 17:55:25+01:00 bzolnier@trik.(none) +0 -86
#   [ide] generic Power Management for IDE devices
# 
# drivers/ide/ide-cd.c
#   2005/03/10 17:55:25+01:00 bzolnier@trik.(none) +0 -41
#   [ide] generic Power Management for IDE devices
# 
# fs/nfsd/nfs4state.c
#   2005/03/10 00:38:51-08:00 neilb@cse.unsw.edu.au +14 -43
#   nfsd4: fix delegation filp sharing
# 
# ChangeSet
#   2005/03/10 08:55:11-08:00 neilb@cse.unsw.edu.au 
#   [PATCH] nfsd4: store-file-with-deleg
#   
#   The only reason we're keeping a pointer to the stateid in the delegation is so
#   we can get at st_vfs_file.  So we should just keep a pointer to the struct
#   file instead.
#   
#   Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
#   Signed-off-by: Neil Brown <neilb@cse.unsw.edu.au>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/linux/nfsd/state.h
#   2005/03/10 00:38:50-08:00 neilb@cse.unsw.edu.au +1 -1
#   nfsd4: store-file-with-deleg
# 
# fs/nfsd/nfs4state.c
#   2005/03/10 00:38:50-08:00 neilb@cse.unsw.edu.au +7 -8
#   nfsd4: store-file-with-deleg
# 
# ChangeSet
#   2005/03/10 08:54:55-08:00 neilb@cse.unsw.edu.au 
#   [PATCH] nfsd4: reorganize release_deleg
#   
#   Just separate part of release_deleg into a separate function.
#   
#   Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
#   Signed-off-by: Neil Brown <neilb@cse.unsw.edu.au>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# fs/nfsd/nfs4state.c
#   2005/03/10 00:38:50-08:00 neilb@cse.unsw.edu.au +17 -11
#   nfsd4: reorganize release_deleg
# 
# ChangeSet
#   2005/03/10 08:54:39-08:00 neilb@cse.unsw.edu.au 
#   [PATCH] nfsd4: fix delegation refcounting
#   
#   The delegation recall callback is setting the REAP_DELEGATION state when it
#   drops the reference count to zero instead of just freeing the thing itself,
#   which is needlessly complicated and bug-prone.  It's simpler just to define a
#   nfs4_put_delegation() which works in the usual way and have the delegation
#   recall code do call that itself.
#   
#   Eventually I'll convert all the nfsd4 state reference counts to struct krefs
#   which will be harder to abuse in this way....
#   
#   Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
#   Signed-off-by: Neil Brown <neilb@cse.unsw.edu.au>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/linux/nfsd/state.h
#   2005/03/10 00:38:50-08:00 neilb@cse.unsw.edu.au +1 -0
#   nfsd4: fix delegation refcounting
# 
# fs/nfsd/nfs4state.c
#   2005/03/10 00:38:50-08:00 neilb@cse.unsw.edu.au +10 -17
#   nfsd4: fix delegation refcounting
# 
# fs/nfsd/nfs4callback.c
#   2005/03/10 00:38:50-08:00 neilb@cse.unsw.edu.au +1 -5
#   nfsd4: fix delegation refcounting
# 
# ChangeSet
#   2005/03/10 08:54:23-08:00 neilb@cse.unsw.edu.au 
#   [PATCH] nfsd4: fix cb-race
#   
#   We weren't taking the reference count in the delegation recall thread until
#   we'd already started the new delegation thread (and possibly returned from the
#   break_lease callback).  That's too late.
#   
#   Also document some assumptions.
#   
#   Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
#   Signed-off-by: Neil Brown <neilb@cse.unsw.edu.au>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# fs/nfsd/nfs4state.c
#   2005/03/10 00:38:50-08:00 neilb@cse.unsw.edu.au +10 -4
#   nfsd4: fix cb-race
# 
# ChangeSet
#   2005/03/10 08:54:07-08:00 neilb@cse.unsw.edu.au 
#   [PATCH] nfsd4: remove st_vfs_file checks
#   
#   The st_vfs_file field *must* be non-NULL as long as the stateid is in use, so
#   there's no point testing for it, unless we want to just BUG().  But since we'd
#   immediately hit a NULL dereference in every case, there's no need even for
#   that.
#   
#   Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
#   Signed-off-by: Neil Brown <neilb@cse.unsw.edu.au>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# fs/nfsd/nfs4state.c
#   2005/03/10 00:38:50-08:00 neilb@cse.unsw.edu.au +5 -8
#   nfsd4: remove st_vfs_file checks
# 
# ChangeSet
#   2005/03/10 08:53:51-08:00 neilb@cse.unsw.edu.au 
#   [PATCH] nfsd4: remove st_vfs_set
#   
#   Note st_vfs_set is redundant; we can always just check whether st_vfs_file is
#   set.
#   
#   Fix one inconsistency along the way: we were setting st_vfs_file to 0 in one
#   case without fput()'ing st_vfs_file.  It doesn't appear there was a need to do
#   either one in that case.
#   
#   Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
#   Signed-off-by: Neil Brown <neilb@cse.unsw.edu.au>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/linux/nfsd/state.h
#   2005/03/10 00:38:49-08:00 neilb@cse.unsw.edu.au +0 -1
#   nfsd4: remove st_vfs_set
# 
# fs/nfsd/nfs4state.c
#   2005/03/10 00:38:49-08:00 neilb@cse.unsw.edu.au +4 -7
#   nfsd4: remove st_vfs_set
# 
# ChangeSet
#   2005/03/10 08:53:36-08:00 neilb@cse.unsw.edu.au 
#   [PATCH] nfsd4: fix laundromat delegation reaping
#   
#   The laundromat is freeing any delegation it finds in the RECALL_COMPLETE
#   state.  But note that RECALL_COMPLETE is the state that the delegation recall
#   callback leaves the state in.  We shouldn't actually be giving up on the
#   delegation till either the client has had a chance to call delegreturn, or the
#   lease time has run out.
#   
#   Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
#   Signed-off-by: Neil Brown <neilb@cse.unsw.edu.au>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# fs/nfsd/nfs4state.c
#   2005/03/10 00:38:49-08:00 neilb@cse.unsw.edu.au +0 -3
#   nfsd4: fix laundromat delegation reaping
# 
# ChangeSet
#   2005/03/10 08:53:20-08:00 neilb@cse.unsw.edu.au 
#   [PATCH] nfsd4: keep lockowners off perclient list
#   
#   There's no reason to have the lockowners hang off the same list on the client
#   struct as the openowners do; you can always get to the lockowners from their
#   original openowners instead.
#   
#   Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
#   Signed-off-by: Neil Brown <neilb@cse.unsw.edu.au>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# fs/nfsd/nfs4state.c
#   2005/03/10 00:38:49-08:00 neilb@cse.unsw.edu.au +4 -4
#   nfsd4: keep lockowners off perclient list
# 
# ChangeSet
#   2005/03/10 08:53:04-08:00 neilb@cse.unsw.edu.au 
#   [PATCH] nfsd4: rename release_stateid_lockowner
#   
#   The name makes it sounds like the job of this function is to release a single
#   lockowner; the plural seems clearer.
#   
#   Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
#   Signed-off-by: Neil Brown <neilb@cse.unsw.edu.au>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# fs/nfsd/nfs4state.c
#   2005/03/10 00:38:49-08:00 neilb@cse.unsw.edu.au +4 -4
#   nfsd4: rename release_stateid_lockowner
# 
# ChangeSet
#   2005/03/10 08:52:48-08:00 neilb@cse.unsw.edu.au 
#   [PATCH] nfsd4: remove dl_recall_cnt
#   
#   We don't need dl_recall_cnt any more, we're just using a local variable
#   in nfsd4_cb_recall.
#   
#   Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
#   Signed-off-by: Neil Brown <neilb@cse.unsw.edu.au>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/linux/nfsd/state.h
#   2005/03/10 00:38:48-08:00 neilb@cse.unsw.edu.au +0 -1
#   nfsd4: remove dl_recall_cnt
# 
# fs/nfsd/nfs4state.c
#   2005/03/10 00:38:48-08:00 neilb@cse.unsw.edu.au +0 -1
#   nfsd4: remove dl_recall_cnt
# 
# ChangeSet
#   2005/03/10 08:52:33-08:00 neilb@cse.unsw.edu.au 
#   [PATCH] nfsd4: nfs4_cb_recall cleanup
#   
#   Miscellaneous cleanup including:
#   	remove recursion
#   	use a local variable instead of dl_recall_cnt
#   
#   Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
#   Signed-off-by: Neil Brown <neilb@cse.unsw.edu.au>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# fs/nfsd/nfs4callback.c
#   2005/03/10 00:38:48-08:00 neilb@cse.unsw.edu.au +32 -54
#   nfsd4: nfs4_cb_recall cleanup
# 
# ChangeSet
#   2005/03/10 08:52:17-08:00 neilb@cse.unsw.edu.au 
#   [PATCH] nfsd4: trivial callback cleanup
#   
#   Whitespace, etc.
#   
#   Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
#   Signed-off-by: Neil Brown <neilb@cse.unsw.edu.au>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# fs/nfsd/nfs4callback.c
#   2005/03/10 00:38:48-08:00 neilb@cse.unsw.edu.au +7 -11
#   nfsd4: trivial callback cleanup
# 
# ChangeSet
#   2005/03/10 08:52:01-08:00 neilb@cse.unsw.edu.au 
#   [PATCH] nfsd4: use sync rpc for delegation recall
#   
#   Use a synchronous rpc for the delegation recall.  This is simpler and
#   avoids putting rpciod to sleep for 2 seconds on retries.
#   
#   Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
#   Signed-off-by: Neil Brown <neilb@cse.unsw.edu.au>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# fs/nfsd/nfs4callback.c
#   2005/03/10 00:38:48-08:00 neilb@cse.unsw.edu.au +7 -7
#   nfsd4: use sync rpc for delegation recall
# 
# ChangeSet
#   2005/03/10 08:51:46-08:00 neilb@cse.unsw.edu.au 
#   [PATCH] nfsd4: fix callback cred refcnt leak
#   
#   The rpc creds we look up in the callback code need puts.
#   
#   Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
#   Signed-off-by: Neil Brown <neilb@cse.unsw.edu.au>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# fs/nfsd/nfs4callback.c
#   2005/03/10 00:38:47-08:00 neilb@cse.unsw.edu.au +2 -0
#   nfsd4: fix callback cred refcnt leak
# 
# ChangeSet
#   2005/03/10 08:51:30-08:00 neilb@cse.unsw.edu.au 
#   [PATCH] nfsd4: make nfsd4_cb_recall return void
#   
#   The return value of nfsd4_cb_recall isn't really used (and the errors we were
#   returning were incorrect anyway).
#   
#   Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
#   Signed-off-by: Neil Brown <neilb@cse.unsw.edu.au>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/linux/nfsd/state.h
#   2005/03/10 00:38:47-08:00 neilb@cse.unsw.edu.au +1 -1
#   nfsd4: make nfsd4_cb_recall return void
# 
# fs/nfsd/nfs4callback.c
#   2005/03/10 00:38:47-08:00 neilb@cse.unsw.edu.au +7 -14
#   nfsd4: make nfsd4_cb_recall return void
# 
# ChangeSet
#   2005/03/10 08:51:15-08:00 neilb@cse.unsw.edu.au 
#   [PATCH] nfsd4: remove incorrect kfree from callback
#   
#   Remove incorrect kfree.
#   
#   Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
#   Signed-off-by: Neil Brown <neilb@cse.unsw.edu.au>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# fs/nfsd/nfs4callback.c
#   2005/03/10 00:38:47-08:00 neilb@cse.unsw.edu.au +1 -3
#   nfsd4: remove incorrect kfree from callback
# 
# ChangeSet
#   2005/03/10 08:50:59-08:00 neilb@cse.unsw.edu.au 
#   [PATCH] nfsd4: return callback_ident in callbacks
#   
#   Pass the callback_ident received in SETCLIENTID to the CB_RECALL rpc.
#   
#   Signed-off-by: Andy Adamson <andros@citi.umich.edu>
#   Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
#   Signed-off-by: Neil Brown <neilb@cse.unsw.edu.au>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# fs/nfsd/nfs4state.c
#   2005/03/10 00:38:47-08:00 neilb@cse.unsw.edu.au +5 -3
#   nfsd4: return callback_ident in callbacks
# 
# fs/nfsd/nfs4callback.c
#   2005/03/10 00:38:47-08:00 neilb@cse.unsw.edu.au +1 -0
#   nfsd4: return callback_ident in callbacks
# 
# ChangeSet
#   2005/03/10 08:50:43-08:00 neilb@cse.unsw.edu.au 
#   [PATCH] nfsd4: simplify find functions
#   
#   Fix "find" functions that use return value redundantly.  Calculate hashes on
#   demand.  Miscellaneous kernel style.
#   
#   Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
#   Signed-off-by: Neil Brown <neilb@cse.unsw.edu.au>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# fs/nfsd/nfs4state.c
#   2005/03/10 00:38:46-08:00 neilb@cse.unsw.edu.au +43 -40
#   nfsd4: simplify find functions
# 
# ChangeSet
#   2005/03/10 08:50:28-08:00 neilb@cse.unsw.edu.au 
#   [PATCH] nfsd4: simplify find_openstateowner_str
#   
#   There's no need to return duplicate information through the return value and an
#   argument.  Other minor cleanup.
#   
#   Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
#   Signed-off-by: Neil Brown <neilb@cse.unsw.edu.au>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# fs/nfsd/nfs4state.c
#   2005/03/10 00:38:46-08:00 neilb@cse.unsw.edu.au +12 -12
#   nfsd4: simplify find_openstateowner_str
# 
# ChangeSet
#   2005/03/10 08:50:12-08:00 neilb@cse.unsw.edu.au 
#   [PATCH] nfsd4: provide no_cb_path error on renew
#   
#   If the client was given a delegation, but our callback path to the client has
#   since failed for some reason, then our only chance to inform the client of this
#   is to return the cb_path_down error next time the client attempts to renew its
#   state.
#   
#   Signed-off-by: Andy Adamson <andros@citi.umich.edu>
#   Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
#   Signed-off-by: Neil Brown <neilb@cse.unsw.edu.au>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/linux/nfsd/nfsd.h
#   2005/03/10 00:38:46-08:00 neilb@cse.unsw.edu.au +1 -0
#   nfsd4: provide no_cb_path error on renew
# 
# fs/nfsd/nfs4state.c
#   2005/03/10 00:38:46-08:00 neilb@cse.unsw.edu.au +10 -10
#   nfsd4: provide no_cb_path error on renew
# 
# ChangeSet
#   2005/03/10 08:49:56-08:00 neilb@cse.unsw.edu.au 
#   [PATCH] nfsd4: don't allow unconfirmed renew
#   
#   Don't bother searching for unconfirmed clients when handling RENEW; a client is
#   pretty sick if it's trying to renew state it hasn't even finished acquiring
#   yet.
#   
#   Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
#   Signed-off-by: Neil Brown <neilb@cse.unsw.edu.au>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# fs/nfsd/nfs4state.c
#   2005/03/10 00:38:45-08:00 neilb@cse.unsw.edu.au +0 -5
#   nfsd4: don't allow unconfirmed renew
# 
# ChangeSet
#   2005/03/10 08:49:41-08:00 neilb@cse.unsw.edu.au 
#   [PATCH] nfsd4: simplify verify_clientid
#   
#   Simplify verify_clientid out of existance.
#   
#   Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
#   Signed-off-by: Neil Brown <neilb@cse.unsw.edu.au>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# fs/nfsd/nfs4state.c
#   2005/03/10 00:38:45-08:00 neilb@cse.unsw.edu.au +2 -16
#   nfsd4: simplify verify_clientid
# 
# ChangeSet
#   2005/03/10 08:49:25-08:00 neilb@cse.unsw.edu.au 
#   [PATCH] nfsd4: simplify clientid hash table searches
#   
#   We repeat the same hash table searches in a bunch of places, and keep making
#   the mistake of assuming the variable iterating over the list will be NULL when
#   the search fails.  Some helper functions here simplify things a bit.
#   
#   While we're at it, make move_to_confirmed take just a clp instead of making the
#   caller compute the hash.  This means we sometimes have to compute the hash
#   multiple times, but it's only an &, so no big deal.
#   
#   Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
#   Signed-off-by: Neil Brown <neilb@cse.unsw.edu.au>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# fs/nfsd/nfs4state.c
#   2005/03/10 00:38:45-08:00 neilb@cse.unsw.edu.au +45 -39
#   nfsd4: simplify clientid hash table searches
# 
# ChangeSet
#   2005/03/10 08:49:09-08:00 neilb@cse.unsw.edu.au 
#   [PATCH] nfsd4: fix nfs4_check_delegmode()
#   
#   Inline nfs4_check_delegmode, replace & by &&, remove incorrect check. (Note
#   that it's fine to read using the stateid for a write delegation.)
#   
#   While we're at it, the status return logic seems like overkill for one simple
#   check.
#   
#   Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
#   Signed-off-by: Neil Brown <neilb@cse.unsw.edu.au>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# ChangeSet
#   2005/03/10 17:49:07+01:00 bzolnier@trik.(none) 
#   [ide] fix drive->ready_stat for ATAPI
#   
#   ATAPI devices ignore DRDY bit so drive->ready_stat must be set to zero.
#   It is currently done by device drivers (including ide-default fake driver)
#   but for PMAC driver it is too late as wait_for_ready() may be called during
#   probe: probe_hwif()->pmac_ide_dma_check()->pmac_ide_{mdma,udma}_enable()->
#   ->pmac_ide_do_setfeature()->wait_for_ready().
#   
#   Fixup drive->ready_stat just after detecting ATAPI device.
#   
#   Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
# 
# fs/nfsd/nfs4state.c
#   2005/03/10 00:38:45-08:00 neilb@cse.unsw.edu.au +5 -10
#   nfsd4: fix nfs4_check_delegmode()
# 
# ChangeSet
#   2005/03/10 08:48:54-08:00 neilb@cse.unsw.edu.au 
#   [PATCH] nfsd4: remove unnecessary check in find_delegation_stateid
#   
#   We would have oopsed some time ago if either of these parameters were NULL.
#   
#   Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
#   Signed-off-by: Neil Brown <neilb@cse.unsw.edu.au>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/scsi/ide-scsi.c
#   2005/03/10 17:48:54+01:00 bzolnier@trik.(none) +0 -1
#   [ide] fix drive->ready_stat for ATAPI
# 
# drivers/ide/ide.c
#   2005/03/10 17:48:54+01:00 bzolnier@trik.(none) +3 -0
#   [ide] fix drive->ready_stat for ATAPI
# 
# drivers/ide/ide-tape.c
#   2005/03/10 17:48:54+01:00 bzolnier@trik.(none) +0 -2
#   [ide] fix drive->ready_stat for ATAPI
# 
# drivers/ide/ide-probe.c
#   2005/03/10 17:48:54+01:00 bzolnier@trik.(none) +2 -0
#   [ide] fix drive->ready_stat for ATAPI
# 
# drivers/ide/ide-floppy.c
#   2005/03/10 17:48:54+01:00 bzolnier@trik.(none) +0 -1
#   [ide] fix drive->ready_stat for ATAPI
# 
# drivers/ide/ide-default.c
#   2005/03/10 17:48:54+01:00 bzolnier@trik.(none) +0 -7
#   [ide] fix drive->ready_stat for ATAPI
# 
# drivers/ide/ide-cd.c
#   2005/03/10 17:48:54+01:00 bzolnier@trik.(none) +0 -1
#   [ide] fix drive->ready_stat for ATAPI
# 
# fs/nfsd/nfs4state.c
#   2005/03/10 00:38:44-08:00 neilb@cse.unsw.edu.au +0 -2
#   nfsd4: remove unnecessary check in find_delegation_stateid
# 
# ChangeSet
#   2005/03/10 08:48:38-08:00 neilb@cse.unsw.edu.au 
#   [PATCH] nfsd4: miscellaneous delegation fixes
#   
#   Don't hand out a delegation to a client that already has one.
#   
#   Minor simplification and reformatting.
#   
#   Signed-off-by: Andy Adamson <andros@citi.umich.edu>
#   Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
#   Signed-off-by: Neil Brown <neilb@cse.unsw.edu.au>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# fs/nfsd/nfs4state.c
#   2005/03/10 00:38:44-08:00 neilb@cse.unsw.edu.au +9 -22
#   nfsd4: miscellaneous delegation fixes
# 
# ChangeSet
#   2005/03/10 08:48:22-08:00 neilb@cse.unsw.edu.au 
#   [PATCH] nfsd4: simplify open_delegation 2
#   
#   Simplify logic in nfs4_open_delegation, fix a small bug on allocation failure.
#   
#   Signed-off-by: Andy Adamson <andros@citi.umich.edu>
#   Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
#   Signed-off-by: Neil Brown <neilb@cse.unsw.edu.au>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# fs/nfsd/nfs4state.c
#   2005/03/10 00:38:44-08:00 neilb@cse.unsw.edu.au +7 -6
#   nfsd4: simplify open_delegation 2
# 
# ChangeSet
#   2005/03/10 08:48:07-08:00 neilb@cse.unsw.edu.au 
#   [PATCH] nfsd4: simplify open_delegation
#   
#   The DONT_DELEGATE flag is superfluous.
#   
#   Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
#   Signed-off-by: Neil Brown <neilb@cse.unsw.edu.au>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# fs/nfsd/nfs4state.c
#   2005/03/10 00:38:44-08:00 neilb@cse.unsw.edu.au +2 -6
#   nfsd4: simplify open_delegation
# 
# ChangeSet
#   2005/03/10 08:47:51-08:00 neilb@cse.unsw.edu.au 
#   [PATCH] nfsd4: do callback replays by hand
#   
#   Turn off rpc layer timeout replay for the NFSv4 server callback client.
#   Rely on manual replay in nfs4_cb_recall_done instead.
#   
#   Signed-off-by: Andy Adamson <andros@citi.umich.edu>
#   Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
#   Signed-off-by: Neil Brown <neilb@cse.unsw.edu.au>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# fs/nfsd/nfs4callback.c
#   2005/03/10 00:38:44-08:00 neilb@cse.unsw.edu.au +3 -2
#   nfsd4: do callback replays by hand
# 
# ChangeSet
#   2005/03/10 08:47:35-08:00 neilb@cse.unsw.edu.au 
#   [PATCH] nfsd4: don't release nfs4_file with associated delegations
#   
#   Only release a struct nfs4_file if there are no associated delegations.
#   
#   Signed-off-by: Andy Adamson <andros@citi.umich.edu>
#   Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
#   Signed-off-by: Neil Brown <neilb@cse.unsw.edu.au>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# fs/nfsd/nfs4state.c
#   2005/03/10 00:38:43-08:00 neilb@cse.unsw.edu.au +1 -1
#   nfsd4: don't release nfs4_file with associated delegations
# 
# ChangeSet
#   2005/03/10 08:47:19-08:00 neilb@cse.unsw.edu.au 
#   [PATCH] nfsd4: miscellaneous open cleanup 3
#   
#   More minor logic cleanup.
#   
#   Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
#   Signed-off-by: Neil Brown <neilb@cse.unsw.edu.au>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# fs/nfsd/nfs4state.c
#   2005/03/10 00:38:43-08:00 neilb@cse.unsw.edu.au +3 -7
#   nfsd4: miscellaneous open cleanup 3
# 
# ChangeSet
#   2005/03/10 08:47:03-08:00 neilb@cse.unsw.edu.au 
#   [PATCH] nfsd4: miscellaneous open cleanup 2
#   
#   Replace sequence of if {...  goto} 's by if-elseif's, other minor
#   simplification of logic.
#   
#   Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
#   Signed-off-by: Neil Brown <neilb@cse.unsw.edu.au>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# fs/nfsd/nfs4state.c
#   2005/03/10 00:38:43-08:00 neilb@cse.unsw.edu.au +21 -24
#   nfsd4: miscellaneous open cleanup 2
# 
# ChangeSet
#   2005/03/10 08:46:48-08:00 neilb@cse.unsw.edu.au 
#   [PATCH] nfsd4: miscellaneous open cleanup
#   
#   Minor trivial cleanup, mostly whitespace.
#   
#   Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
#   Signed-off-by: Neil Brown <neilb@cse.unsw.edu.au>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# fs/nfsd/nfs4state.c
#   2005/03/10 00:38:43-08:00 neilb@cse.unsw.edu.au +9 -10
#   nfsd4: miscellaneous open cleanup
# 
# fs/nfsd/nfs4proc.c
#   2005/03/10 00:38:43-08:00 neilb@cse.unsw.edu.au +1 -2
#   nfsd4: miscellaneous open cleanup
# 
# ChangeSet
#   2005/03/10 08:46:32-08:00 neilb@cse.unsw.edu.au 
#   [PATCH] nfsd4: use existing open instead of reopening on read and write
#   
#   Use the struct file * obtained in nfsd4_open for nfsd_read and nfsd_write when
#   available.
#   
#   To do this we add a struct file * argument to nfsd_read and nfsd_write.  If a
#   struct file is passed in, nfsd_read and nfsd_write will use it, doing just an
#   access check instead of an open and close.  If the new argument is NULL, they
#   will fall back on the old behaviour.
#   
#   Signed-off-by: Andy Adamson <andros@citi.umich.edu>
#   Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
#   Signed-off-by: Neil Brown <neilb@cse.unsw.edu.au>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/linux/nfsd/xdr4.h
#   2005/03/10 00:38:42-08:00 neilb@cse.unsw.edu.au +1 -0
#   nfsd4: use existing open instead of reopening on read and write
# 
# include/linux/nfsd/state.h
#   2005/03/10 00:38:42-08:00 neilb@cse.unsw.edu.au +1 -1
#   nfsd4: use existing open instead of reopening on read and write
# 
# include/linux/nfsd/nfsd.h
#   2005/03/10 00:38:42-08:00 neilb@cse.unsw.edu.au +3 -3
#   nfsd4: use existing open instead of reopening on read and write
# 
# fs/nfsd/vfs.c
#   2005/03/10 00:38:42-08:00 neilb@cse.unsw.edu.au +70 -33
#   nfsd4: use existing open instead of reopening on read and write
# 
# fs/nfsd/nfsproc.c
#   2005/03/10 00:38:42-08:00 neilb@cse.unsw.edu.au +2 -2
#   nfsd4: use existing open instead of reopening on read and write
# 
# fs/nfsd/nfs4xdr.c
#   2005/03/10 00:38:42-08:00 neilb@cse.unsw.edu.au +4 -4
#   nfsd4: use existing open instead of reopening on read and write
# 
# fs/nfsd/nfs4state.c
#   2005/03/10 00:38:42-08:00 neilb@cse.unsw.edu.au +6 -2
#   nfsd4: use existing open instead of reopening on read and write
# 
# fs/nfsd/nfs4proc.c
#   2005/03/10 00:38:42-08:00 neilb@cse.unsw.edu.au +11 -7
#   nfsd4: use existing open instead of reopening on read and write
# 
# fs/nfsd/nfs3proc.c
#   2005/03/10 00:38:42-08:00 neilb@cse.unsw.edu.au +2 -2
#   nfsd4: use existing open instead of reopening on read and write
# 
# ChangeSet
#   2005/03/10 08:46:17-08:00 neilb@cse.unsw.edu.au 
#   [PATCH] nfsd4: allow some reads and writes during the grace period
#   
#   Allow READ and WRITE during the grace period on OPEN or LOCK state that has
#   been reclaimed, for files for which mandatory locking is not in force.  (Reads
#   and writes to files with mandatory locking must be delayed until we're sure
#   all the other clients have had a chance to recover locks.)
#   
#   Signed-off-by: Andy Adamson <andros@citi.umich.edu>
#   Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
#   Signed-off-by: Neil Brown <neilb@cse.unsw.edu.au>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# fs/nfsd/nfs4state.c
#   2005/03/10 00:38:42-08:00 neilb@cse.unsw.edu.au +24 -3
#   nfsd4: allow some reads and writes during the grace period
# 
# fs/nfsd/nfs4proc.c
#   2005/03/10 00:38:42-08:00 neilb@cse.unsw.edu.au +0 -8
#   nfsd4: allow some reads and writes during the grace period
# 
# ChangeSet
#   2005/03/10 08:46:01-08:00 neilb@cse.unsw.edu.au 
#   [PATCH] nfsd4: move special stateid processing
#   
#   Move special stateid processing to nfs4_preprocess_stateid_op().  Also make
#   stateid processing for setattr the same as that for write.
#   
#   Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
#   Signed-off-by: Neil Brown <neilb@cse.unsw.edu.au>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# fs/nfsd/nfs4state.c
#   2005/03/10 00:38:41-08:00 neilb@cse.unsw.edu.au +19 -0
#   nfsd4: move special stateid processing
# 
# fs/nfsd/nfs4proc.c
#   2005/03/10 00:38:41-08:00 neilb@cse.unsw.edu.au +1 -37
#   nfsd4: move special stateid processing
# 
# ChangeSet
#   2005/03/10 08:45:45-08:00 neilb@cse.unsw.edu.au 
#   [PATCH] nfsd4: reclaim cleanup
#   
#   Remove unnecessary fields in the nfs4_client_reclaim structure.  Initialize
#   reclaim_str_hashtbl_size and increment it inside of nfs4_client_to_reclaim.
#   Modify client_to_reclaim() in preparation for reboot recovery.
#   
#   Signed-off-by: Andy Adamson <andros@citi.umich.edu>
#   Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
#   Signed-off-by: Neil Brown <neilb@cse.unsw.edu.au>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/linux/nfsd/state.h
#   2005/03/10 00:38:41-08:00 neilb@cse.unsw.edu.au +0 -3
#   nfsd4: reclaim cleanup
# 
# fs/nfsd/nfs4state.c
#   2005/03/10 00:38:41-08:00 neilb@cse.unsw.edu.au +13 -25
#   nfsd4: reclaim cleanup
# 
# ChangeSet
#   2005/03/10 08:45:29-08:00 neilb@cse.unsw.edu.au 
#   [PATCH] nfsd4: cbnull refcount leak
#   
#   Properly decrement refcount on failure in nfsd4_probe_callback.
#   
#   Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
#   Signed-off-by: Neil Brown <neilb@cse.unsw.edu.au>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# fs/nfsd/nfs4callback.c
#   2005/03/10 00:38:41-08:00 neilb@cse.unsw.edu.au +2 -1
#   nfsd4: cbnull refcount leak
# 
# ChangeSet
#   2005/03/10 08:45:14-08:00 neilb@cse.unsw.edu.au 
#   [PATCH] nfsd4: Fix oops on nfsd4 shutdown
#   
#   Fix Oops at nfsd shutdown.  Reap any open nfs4_stateowners remaining on the
#   close_lru hash list prior to reaping nfs4_clients at shutdown.
#   
#   Signed-off-by: Andy Adamson <andros@citi.umich.edu>
#   Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
#   Signed-off-by: Neil Brown <neilb@cse.unsw.edu.au>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# fs/nfsd/nfs4state.c
#   2005/03/10 00:38:41-08:00 neilb@cse.unsw.edu.au +7 -0
#   nfsd4: Fix oops on nfsd4 shutdown
# 
# ChangeSet
#   2005/03/10 08:44:58-08:00 neilb@cse.unsw.edu.au 
#   [PATCH] nfsd4: remove stateowner debug counters
#   
#   Get rid of these debug counters.  Since they're no longer necessarily
#   incremented under state lock, we'd need to convert them to atomic_t to
#   guarantee them correct.  It doesn't seem worth it.
#   
#   Also, the debug checks in kmem_cache_destroy() should be sufficient for at
#   least one of the purposes the debugging counters existed for--we'll get a
#   dump_stack() if there are still stateowners left when we shut down.
#   
#   Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
#   Signed-off-by: Neil Brown <neilb@cse.unsw.edu.au>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# fs/nfsd/nfs4state.c
#   2005/03/10 00:38:40-08:00 neilb@cse.unsw.edu.au +0 -8
#   nfsd4: remove stateowner debug counters
# 
# ChangeSet
#   2005/03/10 08:44:42-08:00 neilb@cse.unsw.edu.au 
#   [PATCH] nfsd4: create a slab cache for stateowners
#   
#   Create a slab cache for nfsv4 stateowners.
#   
#   Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
#   Signed-off-by: Neil Brown <neilb@cse.unsw.edu.au>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/linux/nfsd/nfsd.h
#   2005/03/10 00:38:40-08:00 neilb@cse.unsw.edu.au +2 -2
#   nfsd4: create a slab cache for stateowners
# 
# fs/nfsd/nfssvc.c
#   2005/03/10 00:38:40-08:00 neilb@cse.unsw.edu.au +3 -1
#   nfsd4: create a slab cache for stateowners
# 
# fs/nfsd/nfs4state.c
#   2005/03/10 00:38:40-08:00 neilb@cse.unsw.edu.au +46 -9
#   nfsd4: create a slab cache for stateowners
# 
# ChangeSet
#   2005/03/10 08:44:26-08:00 neilb@cse.unsw.edu.au 
#   [PATCH] nfsd4: remove utf8 checking
#   
#   RFC3530 says NFSv4 filenames are in UTF-8, and that servers "should" reject
#   filenames that aren't valid UTF-8.  Currently we do some incomplete UTF-8
#   checking, but this turns out to be more of a hindrance than a help--if we
#   export a filesystem with non-UTF8 names, things break.  We might be able to
#   help things if we had some idea of the exported filesystem's charset and could
#   do some translation.  For now, though, the simplest solution by far seems to
#   be just to remove the UTF-8 checks, making NFSv4's behaviour just like
#   NFSv2/v3's.
#   
#   Similar problems exist with usernames.
#   
#   Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
#   Signed-off-by: Neil Brown <neilb@cse.unsw.edu.au>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# fs/nfsd/nfs4xdr.c
#   2005/03/10 00:38:40-08:00 neilb@cse.unsw.edu.au +1 -124
#   nfsd4: remove utf8 checking
# 
# ChangeSet
#   2005/03/10 08:44:10-08:00 cmm@us.ibm.com 
#   [PATCH] ext3: fix race between ext3 make block reservation and reservation window discard
#   
#   This patch fixed a race between ext3_discard_reservation() and
#   ext3_try_to_allocate_with_rsv().
#   
#   There is a window where ext3_discard_reservation will remove an already
#   unlinked reservation window node from the filesystem reservation tree:
#   It thinks the reservation is still linked in the filesystem reservation
#   tree, but it is actually temperately removed from the tree by
#   allocate_new_reservation() when it failed to make a new reservation from
#   the current group and try to make a new reservation from next block
#   group.
#   
#   Here is how it could happen:
#   
#   CPU 1
#   try to allocate a block in group1 with given reservation window my_rsv
#   ext3_try_to_allocate_with_rsv(group
#   	----copy reservation window my_rsv into local rsv_copy
#   	ext3_try_to_allocate(...rsv_copy) 
#   		----no free block in existing reservation window, 
#   		----need a new reservation window
#   	spin_lock(&rsv_lock);
#   
#   CPU 2
#   
#   ext3_discard_reservation
#   	if (!rsv_is_empty()
#   		----this is true
#   	spin_lock(&rsv_lock)
#   		----waiting for thread 1
#   
#   CPU 1:
#   
#   	allocate_new_reservation
#   		failed to reserve blocks in this group
#   		remove the window from the tree
#   		rsv_window_remove(my_rsv)
#   			----window node is unlinked from the tree here
#   		return -1
#   	spin_unlock(&rsv_lock)
#   ext3_try_to_allocate_with_rsv() failed in this group
#   group++
#   
#   CPU 2
#   	spin_lock(&rsv_lock) succeed
#   	rsv_remove_window ()
#   		---------------break, trying to remove a unlinked node from the tree
#   	....
#   	
#   
#   CPU 1:
#   ext3_try_to_allocate_with_rsv(group, my_rsv)
#   	rsv_is_empty is true, need a new reservation window
#   	spin_lock(&rsv_lock);
#   		^--------------- spinning forever
#   
#   We need to re-check whether the reservation window is still linked to
#   the tree after grab the rsv_lock spin lock in ext3_discard_reservation,
#   to prevent panic in rsv_remove_window->rb_erase.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# fs/ext3/balloc.c
#   2005/03/10 00:38:40-08:00 cmm@us.ibm.com +2 -1
#   ext3: fix race between ext3 make block reservation and reservation window discard
# 
# ChangeSet
#   2005/03/10 08:43:54-08:00 mike.miller@hp.com 
#   [PATCH] cciss: per disk queue support
#   
#   This patch adds per disk queue functionality.  It seems that the 2.6 kernel
#   expects a queue per disk.  If you have multiple logical drives on a controller
#   all of the queues actually point back to the same queue.  If a drive is
#   deleted it blows us out of the water.
#   
#   We hold the lock during any queue operations and have added what we call a
#   "fair-enough" algorithm to prevent starving out any drive.
#   
#   Signed-off-by: Mike Miller <mike.miller@hp.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/block/cciss.h
#   2005/03/10 00:38:39-08:00 mike.miller@hp.com +5 -0
#   cciss: per disk queue support
# 
# drivers/block/cciss.c
#   2005/03/10 00:38:39-08:00 mike.miller@hp.com +48 -4
#   cciss: per disk queue support
# 
# ChangeSet
#   2005/03/10 08:43:39-08:00 mike.miller@hp.com 
#   [PATCH] cciss: support for more than 8 controllers
#   
#   This patch adds support for more than 8 controllers.  If we run out of
#   preallocated major numbers we dynamically allocate more.
#   
#   Signed-off-by: Mike Miller <mike.miller@hp.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/block/cciss.h
#   2005/03/10 00:38:39-08:00 mike.miller@hp.com +3 -0
#   cciss: support for more than 8 controllers
# 
# drivers/block/cciss.c
#   2005/03/10 00:38:39-08:00 mike.miller@hp.com +27 -9
#   cciss: support for more than 8 controllers
# 
# ChangeSet
#   2005/03/10 08:43:23-08:00 mike.miller@hp.com 
#   [PATCH] cciss: new controller support
#   
#   This patch adds support for 2 new SAS controllers due out this summer.  It
#   also bumps the version to 2.6.6.
#   
#   Signed-off-by: Mike Miller <mike.miller@hp.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/linux/pci_ids.h
#   2005/03/10 00:38:39-08:00 mike.miller@hp.com +1 -0
#   cciss: new controller support
# 
# drivers/block/cciss.c
#   2005/03/10 00:38:39-08:00 mike.miller@hp.com +10 -4
#   cciss: new controller support
# 
# Documentation/cciss.txt
#   2005/03/10 00:38:39-08:00 mike.miller@hp.com +2 -0
#   cciss: new controller support
# 
# ChangeSet
#   2005/03/10 08:43:07-08:00 rmk+lkml@arm.linux.org.uk 
#   [PATCH] Hotplug parallel ports
#   
#   The Mobility docking station provides a PCI-based parallel port.  Since the
#   docking station connects via Cardbus, such devices are removable. 
#   Therefore, track which parallel ports are registered to each PCI device,
#   and remove them when the PCI device is removed.
#   
#   Signed-off-by: Russell King <rmk@arm.linux.org.uk>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/parport/parport_pc.c
#   2005/03/10 00:38:39-08:00 rmk+lkml@arm.linux.org.uk +41 -4
#   Hotplug parallel ports
# 
# ChangeSet
#   2005/03/10 08:42:51-08:00 dhowells@redhat.com 
#   [PATCH] Properly share process and session keyrings with CLONE_THREAD [try #2]
#   
#   The attached patch causes process and session keyrings to be shared
#   properly when CLONE_THREAD is in force.  It does this by moving the keyring
#   pointers into struct signal_struct[*].
#   
#   [*] I have a patch to rename this to struct thread_group that I'll revisit
#   after the advent of 2.6.11.
#   
#   Furthermore, once this patch is applied, process keyrings will no longer be
#   allocated at fork, but will instead only be allocated when needed.
#   Allocating them at fork was a way of half getting around the sharing across
#   threads problem, but that's no longer necessary.
#   
#   This revision of the patch has the documentation changes patch rolled into it
#   and no longer abstracts the locking for signal_struct into a pair of macros.
#   
#   Signed-Off-By: David Howells <dhowells@redhat.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# security/keys/request_key.c
#   2005/03/10 00:38:38-08:00 dhowells@redhat.com +34 -12
#   Properly share process and session keyrings with CLONE_THREAD [try #2]
# 
# security/keys/process_keys.c
#   2005/03/10 00:38:38-08:00 dhowells@redhat.com +100 -75
#   Properly share process and session keyrings with CLONE_THREAD [try #2]
# 
# kernel/signal.c
#   2005/03/10 00:38:38-08:00 dhowells@redhat.com +1 -0
#   Properly share process and session keyrings with CLONE_THREAD [try #2]
# 
# kernel/fork.c
#   2005/03/10 00:38:38-08:00 dhowells@redhat.com +8 -0
#   Properly share process and session keyrings with CLONE_THREAD [try #2]
# 
# init/main.c
#   2005/03/10 00:38:38-08:00 dhowells@redhat.com +1 -1
#   Properly share process and session keyrings with CLONE_THREAD [try #2]
# 
# include/linux/sched.h
#   2005/03/10 00:38:38-08:00 dhowells@redhat.com +7 -2
#   Properly share process and session keyrings with CLONE_THREAD [try #2]
# 
# include/linux/key.h
#   2005/03/10 00:38:38-08:00 dhowells@redhat.com +5 -0
#   Properly share process and session keyrings with CLONE_THREAD [try #2]
# 
# Documentation/keys.txt
#   2005/03/10 00:38:38-08:00 dhowells@redhat.com +2 -2
#   Properly share process and session keyrings with CLONE_THREAD [try #2]
# 
# ChangeSet
#   2005/03/10 08:42:34-08:00 alexn@dsv.su.se 
#   [PATCH] Race against parent deletion in key_user_lookup()
#   
#   I looked at some of the oops reports against keyrings, I think the problem
#   is that the search isn't restarted after dropping the key_user_lock, *p
#   will still be NULL when we get back to try_again and look through the tree.
#   
#   It looks like the intention was that the search start over from scratch.
#   
#   Signed-off-by: Alexander Nyberg <alexn@dsv.su.se>
#   Cc: David Howells <dhowells@redhat.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# security/keys/key.c
#   2005/03/10 00:38:38-08:00 alexn@dsv.su.se +2 -1
#   Race against parent deletion in key_user_lookup()
# 
# ChangeSet
#   2005/03/10 08:42:18-08:00 chrisw@osdl.org 
#   [PATCH] Security contact info
#   
#   Add security contact info and relevant documentation.
#   
#   Signed-off-by: Chris Wright <chrisw@osdl.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# Documentation/SecurityBugs
#   2005/03/10 00:38:38-08:00 chrisw@osdl.org +38 -0
#   Security contact info
# 
# REPORTING-BUGS
#   2005/03/10 00:38:38-08:00 chrisw@osdl.org +4 -0
#   Security contact info
# 
# MAINTAINERS
#   2005/03/10 00:38:38-08:00 chrisw@osdl.org +5 -0
#   Security contact info
# 
# Documentation/SecurityBugs
#   2005/03/10 00:38:38-08:00 chrisw@osdl.org +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/Documentation/SecurityBugs
# 
# ChangeSet
#   2005/03/10 08:42:01-08:00 coywolf@gmail.com 
#   [PATCH] mnt_init() cleanup
#   
#   At the very beginning in 2.4 days, in mnt_init(), mount_hashtable
#   allocation page order was determined at runtime.  Later the page order got
#   fixed to 0.  This patch cleanups it.
#   
#   Signed-off-by: Coywolf Qi Hunt <coywolf@gmail.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# fs/namespace.c
#   2005/03/10 00:38:38-08:00 coywolf@gmail.com +3 -6
#   mnt_init() cleanup
# 
# ChangeSet
#   2005/03/10 08:41:45-08:00 yuasa@hh.iij4u.or.jp 
#   [PATCH] mips: use c99 initialisers
#   
#   Signed-off-by: Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/mips/kernel/setup.c
#   2005/03/10 00:38:37-08:00 yuasa@hh.iij4u.or.jp +2 -2
#   mips: use c99 initialisers
# 
# ChangeSet
#   2005/03/10 08:41:31-08:00 mpm@selenic.com 
#   [PATCH] make cond_syscall look right
#   
#   The current cond_syscall #defines add a semicolon on the end, and then
#   folks leave the semicolons off in kernel/sys_ni.c, which confuses editors
#   that are language-aware and is just generally bad style.  This sweeps all
#   the users and makes sys_ni.c look like normal C code.
#   
#   Signed-off-by: Matt Mackall <mpm@selenic.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# kernel/sys_ni.c
#   2005/03/10 00:38:37-08:00 mpm@selenic.com +69 -69
#   make cond_syscall look right
# 
# include/asm-x86_64/unistd.h
#   2005/03/10 00:38:37-08:00 mpm@selenic.com +1 -1
#   make cond_syscall look right
# 
# include/asm-v850/unistd.h
#   2005/03/10 00:38:37-08:00 mpm@selenic.com +1 -1
#   make cond_syscall look right
# 
# include/asm-sparc64/unistd.h
#   2005/03/10 00:38:37-08:00 mpm@selenic.com +1 -1
#   make cond_syscall look right
# 
# include/asm-sparc/unistd.h
#   2005/03/10 00:38:37-08:00 mpm@selenic.com +1 -1
#   make cond_syscall look right
# 
# include/asm-sh64/unistd.h
#   2005/03/10 00:38:37-08:00 mpm@selenic.com +1 -1
#   make cond_syscall look right
# 
# include/asm-sh/unistd.h
#   2005/03/10 00:38:37-08:00 mpm@selenic.com +1 -1
#   make cond_syscall look right
# 
# include/asm-s390/unistd.h
#   2005/03/10 00:38:37-08:00 mpm@selenic.com +1 -1
#   make cond_syscall look right
# 
# include/asm-ppc64/unistd.h
#   2005/03/10 00:38:37-08:00 mpm@selenic.com +1 -1
#   make cond_syscall look right
# 
# include/asm-ppc/unistd.h
#   2005/03/10 00:38:37-08:00 mpm@selenic.com +1 -1
#   make cond_syscall look right
# 
# include/asm-parisc/unistd.h
#   2005/03/10 00:38:37-08:00 mpm@selenic.com +1 -1
#   make cond_syscall look right
# 
# include/asm-mips/unistd.h
#   2005/03/10 00:38:37-08:00 mpm@selenic.com +1 -1
#   make cond_syscall look right
# 
# include/asm-m68knommu/unistd.h
#   2005/03/10 00:38:37-08:00 mpm@selenic.com +1 -1
#   make cond_syscall look right
# 
# include/asm-m68k/unistd.h
#   2005/03/10 00:38:37-08:00 mpm@selenic.com +1 -1
#   make cond_syscall look right
# 
# include/asm-m32r/unistd.h
#   2005/03/10 00:38:37-08:00 mpm@selenic.com +1 -1
#   make cond_syscall look right
# 
# include/asm-ia64/unistd.h
#   2005/03/10 00:38:37-08:00 mpm@selenic.com +1 -1
#   make cond_syscall look right
# 
# include/asm-i386/unistd.h
#   2005/03/10 00:38:37-08:00 mpm@selenic.com +1 -1
#   make cond_syscall look right
# 
# include/asm-frv/unistd.h
#   2005/03/10 00:38:37-08:00 mpm@selenic.com +1 -1
#   make cond_syscall look right
# 
# include/asm-cris/unistd.h
#   2005/03/10 00:38:37-08:00 mpm@selenic.com +1 -1
#   make cond_syscall look right
# 
# include/asm-arm26/unistd.h
#   2005/03/10 00:38:37-08:00 mpm@selenic.com +1 -1
#   make cond_syscall look right
# 
# include/asm-arm/unistd.h
#   2005/03/10 00:38:37-08:00 mpm@selenic.com +1 -1
#   make cond_syscall look right
# 
# include/asm-alpha/unistd.h
#   2005/03/10 00:38:37-08:00 mpm@selenic.com +1 -1
#   make cond_syscall look right
# 
# ChangeSet
#   2005/03/10 08:41:13-08:00 pavel@suse.cz 
#   [PATCH] deprecate ACPI S4bios support
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# Documentation/feature-removal-schedule.txt
#   2005/03/10 00:38:37-08:00 pavel@suse.cz +5 -0
#   deprecate ACPI S4bios support
# 
# ChangeSet
#   2005/03/10 08:40:58-08:00 joern@wohnheim.fh-wedel.de 
#   [PATCH] checkstack false positive fix
#   
#   Randy Dunlap found one case where checkstack reported a false
#   positive.  From objdump of efi_stub.o:
#      5:   81 ea 00 00 00 c0       sub    $0xc0000000,%edx
#   
#   With the old code, this was interpreted as a negative number.  The
#   output line was:
#   0xc0116f5d efi_call_phys:                               1073741824
#   
#   Randy wanted a change to return the correct number, like this:
#   0xc0116f5d efi_call_phys:                               3221225472
#   
#   adding "or I can just ignore it, like I've been doing for awhile..."
#   
#   Let's help him with the most sophisticated electronic tools and have
#   the script actively ignore this case for him.
#   
#   Signed-off-by: Jörn Engel <joern@wohnheim.fh-wedel.de>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# scripts/checkstack.pl
#   2005/03/10 00:38:36-08:00 joern@wohnheim.fh-wedel.de +2 -1
#   checkstack false positive fix
# 
# ChangeSet
#   2005/03/10 08:40:42-08:00 sfr@canb.auug.org.au 
#   [PATCH] consolidate the last of the compat sigevent structs
#   
#   This patch pulls together the compat_sigevent structs.  It also
#   consolidates the copying of these structures into the kernel.
#   
#   The only part of the second union in sigevent that the kernel looks at
#   currently is the _tid, so that is the only bit we copy.
#   
#   This patch depends on my previous two patches "add and use
#   COMPAT_SIGEV_PAD_SIZE" and "Consolidate the last compat sigvals".
#   
#   Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# kernel/compat.c
#   2005/03/10 00:38:36-08:00 sfr@canb.auug.org.au +21 -0
#   consolidate the last of the compat sigevent structs
# 
# ipc/compat_mq.c
#   2005/03/10 00:38:36-08:00 sfr@canb.auug.org.au +0 -14
#   consolidate the last of the compat sigevent structs
# 
# include/linux/compat.h
#   2005/03/10 00:38:36-08:00 sfr@canb.auug.org.au +3 -0
#   consolidate the last of the compat sigevent structs
# 
# include/asm-sparc64/siginfo.h
#   2005/03/10 00:38:36-08:00 sfr@canb.auug.org.au +0 -22
#   consolidate the last of the compat sigevent structs
# 
# arch/x86_64/ia32/sys_ia32.c
#   2005/03/10 00:38:36-08:00 sfr@canb.auug.org.au +2 -14
#   consolidate the last of the compat sigevent structs
# 
# arch/sparc64/kernel/sys_sparc32.c
#   2005/03/10 00:38:36-08:00 sfr@canb.auug.org.au +2 -7
#   consolidate the last of the compat sigevent structs
# 
# arch/s390/kernel/compat_linux.h
#   2005/03/10 00:38:36-08:00 sfr@canb.auug.org.au +0 -17
#   consolidate the last of the compat sigevent structs
# 
# arch/s390/kernel/compat_linux.c
#   2005/03/10 00:38:36-08:00 sfr@canb.auug.org.au +2 -11
#   consolidate the last of the compat sigevent structs
# 
# arch/ppc64/kernel/sys_ppc32.c
#   2005/03/10 00:38:36-08:00 sfr@canb.auug.org.au +1 -8
#   consolidate the last of the compat sigevent structs
# 
# arch/ia64/ia32/sys_ia32.c
#   2005/03/10 00:38:36-08:00 sfr@canb.auug.org.au +2 -7
#   consolidate the last of the compat sigevent structs
# 
# arch/ia64/ia32/ia32priv.h
#   2005/03/10 00:38:36-08:00 sfr@canb.auug.org.au +0 -13
#   consolidate the last of the compat sigevent structs
# 
# ChangeSet
#   2005/03/10 08:40:27-08:00 sfr@canb.auug.org.au 
#   [PATCH] Consolidate the last compat sigvals
#   
#   This patch just consolidates the last of the (what should have been)
#   compat_sigval_ts.  It also fixes S390 that had a sigval_t in its struct
#   compat_siginfo.
#   
#   Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/asm-sparc64/siginfo.h
#   2005/03/10 00:38:35-08:00 sfr@canb.auug.org.au +1 -6
#   Consolidate the last compat sigvals
# 
# arch/sparc64/kernel/signal32.c
#   2005/03/10 00:38:35-08:00 sfr@canb.auug.org.au +2 -2
#   Consolidate the last compat sigvals
# 
# arch/s390/kernel/compat_linux.h
#   2005/03/10 00:38:35-08:00 sfr@canb.auug.org.au +2 -7
#   Consolidate the last compat sigvals
# 
# arch/mips/kernel/signal32.c
#   2005/03/10 00:38:35-08:00 sfr@canb.auug.org.au +1 -6
#   Consolidate the last compat sigvals
# 
# arch/ia64/ia32/ia32priv.h
#   2005/03/10 00:38:35-08:00 sfr@canb.auug.org.au +3 -8
#   Consolidate the last compat sigvals
# 
# ChangeSet
#   2005/03/10 08:40:11-08:00 sfr@canb.auug.org.au 
#   [PATCH] add and use COMPAT_SIGEV_PAD_SIZE
#   
#   All the 32 bit architectures (effectively) define SIGEV_PAD_SIZE to be
#   ((SIGEV_MAX_SIZE/sizeof(int)) - 3).  So define COMPAT_SIGEV_PAD_SIZE to be
#   this and replace SIGEV_PAD_SIZE32 where it is used.  It also needs to be
#   used in the definition of struct compat_sigevent as most of the
#   architectures would have had it 4 bytes too small in the kernel (since we
#   were using SIGEV_PAD_SIZE).
#   
#   Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/linux/compat.h
#   2005/03/10 00:38:35-08:00 sfr@canb.auug.org.au +3 -1
#   add and use COMPAT_SIGEV_PAD_SIZE
# 
# include/asm-sparc64/siginfo.h
#   2005/03/10 00:38:35-08:00 sfr@canb.auug.org.au +1 -2
#   add and use COMPAT_SIGEV_PAD_SIZE
# 
# arch/s390/kernel/compat_linux.h
#   2005/03/10 00:38:35-08:00 sfr@canb.auug.org.au +1 -2
#   add and use COMPAT_SIGEV_PAD_SIZE
# 
# arch/ia64/ia32/ia32priv.h
#   2005/03/10 00:38:35-08:00 sfr@canb.auug.org.au +1 -3
#   add and use COMPAT_SIGEV_PAD_SIZE
# 
# ChangeSet
#   2005/03/10 08:39:55-08:00 sct@redhat.com 
#   [PATCH] invalidate_inode_pages2_range livelock fix
#   
#   With Andrew Morton
#   
#   invalidate_inode_pages2_range() can livelock if all the pages in the pagevec
#   are outside the end of teh range which we're trying to invalidate.
#   
#   Fix that up in a similar manner to the truncate_inode_pages_range() handling.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# mm/truncate.c
#   2005/03/10 00:38:35-08:00 sct@redhat.com +12 -6
#   invalidate_inode_pages2_range livelock fix
# 
# ChangeSet
#   2005/03/10 08:39:39-08:00 kkeil@suse.de 
#   [PATCH] Removing Auvertech TurboPAM ISDN driver
#   
#   The Auvertech TurboPAM ISDN hardware was never produce and the company do
#   not longer exist, so it makes no sense to support this any longer.
#   
#   Signed-off-by: Karsten Keil <kkeil@suse.de>
#   Acked-by: Stelian Pop <stelian@popies.net>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/isdn/i4l/Kconfig
#   2005/03/10 00:38:34-08:00 kkeil@suse.de +0 -2
#   Removing Auvertech TurboPAM ISDN driver
# 
# drivers/isdn/Makefile
#   2005/03/10 00:38:34-08:00 kkeil@suse.de +0 -1
#   Removing Auvertech TurboPAM ISDN driver
# 
# BitKeeper/deleted/.del-tpam_queues.c~26705222c76ef1bc
#   2005/03/10 08:39:29-08:00 kkeil@suse.de +0 -0
#   Delete: drivers/isdn/tpam/tpam_queues.c
# 
# BitKeeper/deleted/.del-tpam_nco.c~9004ce7f9ff2177e
#   2005/03/10 08:39:29-08:00 kkeil@suse.de +0 -0
#   Delete: drivers/isdn/tpam/tpam_nco.c
# 
# BitKeeper/deleted/.del-tpam_memory.c~da230c38812855e7
#   2005/03/10 08:39:28-08:00 kkeil@suse.de +0 -0
#   Delete: drivers/isdn/tpam/tpam_memory.c
# 
# BitKeeper/deleted/.del-tpam_main.c~2b69af8a4889af23
#   2005/03/10 08:39:28-08:00 kkeil@suse.de +0 -0
#   Delete: drivers/isdn/tpam/tpam_main.c
# 
# BitKeeper/deleted/.del-tpam_hdlc.c~5a0f5b9a3c62b8cc
#   2005/03/10 08:39:28-08:00 kkeil@suse.de +0 -0
#   Delete: drivers/isdn/tpam/tpam_hdlc.c
# 
# BitKeeper/deleted/.del-tpam_crcpc.c~a5544270662e19
#   2005/03/10 08:39:28-08:00 kkeil@suse.de +0 -0
#   Delete: drivers/isdn/tpam/tpam_crcpc.c
# 
# BitKeeper/deleted/.del-tpam.h~a501b96f11b87ab0
#   2005/03/10 08:39:28-08:00 kkeil@suse.de +0 -0
#   Delete: drivers/isdn/tpam/tpam.h
# 
# BitKeeper/deleted/.del-tpam_commands.c~68cc08cffd226b45
#   2005/03/10 08:39:27-08:00 kkeil@suse.de +0 -0
#   Delete: drivers/isdn/tpam/tpam_commands.c
# 
# BitKeeper/deleted/.del-Makefile~34cbc298e0ef90ab
#   2005/03/10 08:39:27-08:00 kkeil@suse.de +0 -0
#   Delete: drivers/isdn/tpam/Makefile
# 
# BitKeeper/deleted/.del-Kconfig~8e56d2cceaf23b01
#   2005/03/10 08:39:27-08:00 kkeil@suse.de +0 -0
#   Delete: drivers/isdn/tpam/Kconfig
# 
# ChangeSet
#   2005/03/10 08:39:21-08:00 kkeil@suse.de 
#   [PATCH] Cleanup version of the hdriver for HFC 4S/8S based cards
#   
#   This should resolve all the issues from the review and is a big cleanup for
#   i4l-hfc-4s-and-hfc-8s-driver.patch.
#   
#   Signed-off-by: Karsten Keil <kkeil@suse.de>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/isdn/hisax/hfc4s8s_l1.h
#   2005/03/10 08:39:11-08:00 kkeil@suse.de +88 -0
# 
# drivers/isdn/hisax/hfc4s8s_l1.c
#   2005/03/10 00:38:34-08:00 kkeil@suse.de +1529 -1108
#   Cleanup version of the hdriver for HFC 4S/8S based cards
# 
# drivers/isdn/hisax/hfc4s8s_l1.h
#   2005/03/10 08:39:11-08:00 kkeil@suse.de +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/drivers/isdn/hisax/hfc4s8s_l1.h
# 
# BitKeeper/deleted/.del-hfc48scu.h~beaa42992e1b7843
#   2005/03/10 08:39:11-08:00 kkeil@suse.de +0 -0
#   Delete: drivers/isdn/hisax/hfc48scu.h
# 
# ChangeSet
#   2005/03/10 08:38:52-08:00 kkeil@suse.de 
#   [PATCH] i4l: HFC-4S and HFC-8S driver
#   
#   Add a new driver for new ISDN hardware.
#   
#   Signed-off-by: Karsten Keil <kkeil@suse.de>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/isdn/hisax/hfc4s8s_l1.c
#   2005/03/10 00:38:34-08:00 kkeil@suse.de +1293 -0
#   i4l: HFC-4S and HFC-8S driver
# 
# drivers/isdn/hisax/hfc4s8s_l1.c
#   2005/03/10 00:38:34-08:00 kkeil@suse.de +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/drivers/isdn/hisax/hfc4s8s_l1.c
# 
# drivers/isdn/hisax/hfc48scu.h
#   2005/03/10 00:38:34-08:00 kkeil@suse.de +4192 -0
#   i4l: HFC-4S and HFC-8S driver
# 
# drivers/isdn/hisax/Makefile
#   2005/03/10 00:38:34-08:00 kkeil@suse.de +1 -0
#   i4l: HFC-4S and HFC-8S driver
# 
# drivers/isdn/hisax/Kconfig
#   2005/03/10 00:38:34-08:00 kkeil@suse.de +6 -0
#   i4l: HFC-4S and HFC-8S driver
# 
# drivers/isdn/hisax/hfc48scu.h
#   2005/03/10 00:38:34-08:00 kkeil@suse.de +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/drivers/isdn/hisax/hfc48scu.h
# 
# ChangeSet
#   2005/03/10 08:38:35-08:00 kkeil@suse.de 
#   [PATCH] i4l: new hfc_usb driver version
#   
#   This is an update of the HFC USB ISDN driver, the current one has some bugs
#   and support not all HW.  It was already tested as standalone patch for some
#   time, so including it should be safe.
#   
#   Signed-off-by: Karsten Keil <kkeil@suse.de>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/isdn/hisax/hfc_usb.h
#   2005/03/10 00:38:33-08:00 kkeil@suse.de +228 -0
#   i4l: new hfc_usb driver version
# 
# drivers/isdn/hisax/hfc_usb.c
#   2005/03/10 00:38:33-08:00 kkeil@suse.de +1240 -1083
#   i4l: new hfc_usb driver version
# 
# drivers/isdn/hisax/hfc_usb.h
#   2005/03/10 00:38:33-08:00 kkeil@suse.de +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/drivers/isdn/hisax/hfc_usb.h
# 
# ChangeSet
#   2005/03/10 08:38:18-08:00 bstroesser@fujitsu-siemens.com 
#   [PATCH] uml: Fix rounding bug in tlb flushing
#   
#   fix_range_common and flush_tlb_kernel_range_common don't work correctly,
#   if a PGD (or PUD or PMD) is not present and start_addr (resp. start) is not
#   aligned to a PGD boundary (or PUD or PMD boundary).
#   
#   Signed-off-by: Bodo Stroesser <bstroesser@fujitsu-siemens.com>
#   Signed-off-by: Jeff Dike <jdike@addtoit.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/um/kernel/tlb.c
#   2005/03/10 00:38:33-08:00 bstroesser@fujitsu-siemens.com +26 -24
#   uml: Fix rounding bug in tlb flushing
# 
# ChangeSet
#   2005/03/10 08:38:02-08:00 jdike@addtoit.com 
#   [PATCH] uml: Consolidate tlb flushing code
#   
#   This patch merges now-identical page table walking and flushing code that had
#   been duplicated in skas and tt modes.  The differences had been the low-level
#   address space updating operations, which are now abstracted away in the
#   respective do_ops functions.
#   
#   Signed-off-by: Jeff Dike <jdike@addtoit.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/um/kernel/tt/trap_user.c
#   2005/03/10 00:38:33-08:00 jdike@addtoit.com +0 -3
#   uml: Consolidate tlb flushing code
# 
# arch/um/kernel/tt/tracer.c
#   2005/03/10 00:38:33-08:00 jdike@addtoit.com +0 -13
#   uml: Consolidate tlb flushing code
# 
# arch/um/kernel/tt/tlb.c
#   2005/03/10 00:38:33-08:00 jdike@addtoit.com +15 -205
#   uml: Consolidate tlb flushing code
# 
# arch/um/kernel/tt/process_kern.c
#   2005/03/10 00:38:33-08:00 jdike@addtoit.com +0 -96
#   uml: Consolidate tlb flushing code
# 
# arch/um/kernel/tt/mem.c
#   2005/03/10 00:38:33-08:00 jdike@addtoit.com +1 -1
#   uml: Consolidate tlb flushing code
# 
# arch/um/kernel/tlb.c
#   2005/03/10 00:38:33-08:00 jdike@addtoit.com +206 -35
#   uml: Consolidate tlb flushing code
# 
# arch/um/kernel/skas/tlb.c
#   2005/03/10 00:38:33-08:00 jdike@addtoit.com +13 -196
#   uml: Consolidate tlb flushing code
# 
# arch/um/include/um_mmu.h
#   2005/03/10 00:38:33-08:00 jdike@addtoit.com +6 -6
#   uml: Consolidate tlb flushing code
# 
# arch/um/include/tlb.h
#   2005/03/10 00:38:33-08:00 jdike@addtoit.com +5 -0
#   uml: Consolidate tlb flushing code
# 
# ChangeSet
#   2005/03/10 08:37:46-08:00 jdike@addtoit.com 
#   [PATCH] uml: Speed up tlb flushing
#   
#   This patch optimizes tlb flushing in a couple of ways to reduce the number
#   of system calls made to the host in order to update an address space.
#   
#   Operations are collected, and adjacent ones which can be merged, are.  This
#   includes consecutive munmaps, mprotects with the same permissions, and mmaps
#   with the same backing file and permissions and linear in the file.
#   
#   Second, the munmaps that always preceded mmaps are now done instead of mmap if
#   necessary.
#   
#   Signed-off-by: Jeff Dike <jdike@addtoit.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/um/kernel/tt/tlb.c
#   2005/03/10 00:38:33-08:00 jdike@addtoit.com +56 -22
#   uml: Speed up tlb flushing
# 
# arch/um/kernel/tlb.c
#   2005/03/10 00:38:33-08:00 jdike@addtoit.com +101 -0
#   uml: Speed up tlb flushing
# 
# arch/um/kernel/skas/tlb.c
#   2005/03/10 00:38:33-08:00 jdike@addtoit.com +61 -19
#   uml: Speed up tlb flushing
# 
# arch/um/kernel/skas/mem_user.c
#   2005/03/10 00:38:33-08:00 jdike@addtoit.com +4 -6
#   uml: Speed up tlb flushing
# 
# arch/um/kernel/skas/include/skas.h
#   2005/03/10 00:38:33-08:00 jdike@addtoit.com +4 -4
#   uml: Speed up tlb flushing
# 
# arch/um/include/tlb.h
#   2005/03/10 00:38:33-08:00 jdike@addtoit.com +39 -0
#   uml: Speed up tlb flushing
# 
# ChangeSet
#   2005/03/10 08:37:31-08:00 jdike@addtoit.com 
#   [PATCH] uml: Remove build dependency on perl
#   
#   To quote .config into config.c for building the result into the code, use sed
#   instead of perl, as requested by one "embedded" UML user (which notes that
#   perl is a big requirement, while busybox provides sed which is used in this
#   patch).
#   
#   I've tested that there are only cosmethical differences in the produced
#   config.c file, which don't change at all the result (i.e.  "a" is replaced by
#   "" "a" at the beginning, which is non-significant).
#   
#   Reported by, and initial patch provided by, Rob Landley.
#   Signed-off-by: Paolo 'Blaisorblade' Giarrusso <blaisorblade@yahoo.it>
#   Signed-off-by: Jeff Dike <jdike@addtoit.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/um/kernel/Makefile
#   2005/03/10 00:38:32-08:00 jdike@addtoit.com +21 -7
#   uml: Remove build dependency on perl
# 
# ChangeSet
#   2005/03/10 08:37:15-08:00 jdike@addtoit.com 
#   [PATCH] uml: change semaphores to completions
#   
#   From: Esben Nielsen <simlo at phys au dk>
#   
#   One of the problems was use of direct architecture specific semaphores (which
#   doesn't work under PREEMPT_REALTIME) and in places where a quick (maybe too
#   quick) look at the code told me that completions ought to be used.  Therefore
#   I changed two semaphores to completions which compiled fine.  I have tried the
#   change on 2.6.11-rc2, and it seemed to work, but I have not tested it heavily.
#   
#   Signed-off-by: Jeff Dike <jdike@addtoit.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/um/drivers/xterm_kern.c
#   2005/03/10 00:38:32-08:00 jdike@addtoit.com +5 -5
#   uml: change semaphores to completions
# 
# arch/um/drivers/port_kern.c
#   2005/03/10 00:38:32-08:00 jdike@addtoit.com +4 -16
#   uml: change semaphores to completions
# 
# ChangeSet
#   2005/03/10 08:36:59-08:00 jdike@addtoit.com 
#   [PATCH] uml: Export gcov symbol based on gcc version
#   
#   The init function called by gcc when gcov is enabled is __gcov_init or
#   __bb_init_func, depending on the gcc version.  Anton is using 3.3.4 and seeing
#   __gcov_init.  I'm using 3.3.2 and seeing __bb_init_func, so we need to close
#   that gap a bit.
#   
#   Signed-off-by: Jeff Dike <jdike@addtoit.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/um/kernel/gmon_syms.c
#   2005/03/10 00:38:32-08:00 jdike@addtoit.com +6 -0
#   uml: Export gcov symbol based on gcc version
# 
# ChangeSet
#   2005/03/10 08:36:44-08:00 jdike@addtoit.com 
#   [PATCH] uml: "Hardware" random number generator
#   
#   This implements a hardware random number generator for UML which attaches
#   itself to the host's /dev/random.
#   
#   Signed-off-by: Jeff Dike <jdike@addtoit.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/um/drivers/random.c
#   2005/03/10 00:38:32-08:00 jdike@addtoit.com +122 -0
#   uml: "Hardware" random number generator
# 
# arch/um/drivers/Makefile
#   2005/03/10 00:38:32-08:00 jdike@addtoit.com +1 -1
#   uml: "Hardware" random number generator
# 
# arch/um/defconfig
#   2005/03/10 00:38:32-08:00 jdike@addtoit.com +1 -0
#   uml: "Hardware" random number generator
# 
# arch/um/Kconfig_char
#   2005/03/10 00:38:32-08:00 jdike@addtoit.com +14 -0
#   uml: "Hardware" random number generator
# 
# arch/um/drivers/random.c
#   2005/03/10 00:38:32-08:00 jdike@addtoit.com +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/arch/um/drivers/random.c
# 
# ChangeSet
#   2005/03/10 08:36:26-08:00 jdike@addtoit.com 
#   [PATCH] uml: ptrace interface cleanup
#   
#   From: Bodo Stroesser, mostly:
#   
#   Gets rid of all inclusions of {sys,linux,asm}/ptrace.h since their effects and
#   contents are somewhat distro- and architecture-dependent.
#   arch/um/sysdep/ptrace_user is now responsible for providing the system's
#   ptrace interfaces to UML.
#   
#   As such, it is a purely userspace header, and this exposed a couple of places
#   where kernel files were including it.  One of them needed MAX_REG_OFFSET, so
#   this was provided by adding a new generated header, user-constants.h, which
#   includes this.
#   
#   Also, changed PTRACE_{PEEK,POKE}_USER to _USR since that seems to be more
#   standard.
#   
#   Signed-off-by: Jeff Dike <jdike@addtoit.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/um/sys-x86_64/ptrace_user.c
#   2005/03/10 00:38:31-08:00 jdike@addtoit.com +4 -6
#   uml: ptrace interface cleanup
# 
# arch/um/sys-ppc/ptrace_user.c
#   2005/03/10 00:38:31-08:00 jdike@addtoit.com +2 -3
#   uml: ptrace interface cleanup
# 
# arch/um/sys-i386/signal.c
#   2005/03/10 00:38:31-08:00 jdike@addtoit.com +3 -3
#   uml: ptrace interface cleanup
# 
# arch/um/sys-i386/ptrace_user.c
#   2005/03/10 00:38:31-08:00 jdike@addtoit.com +4 -4
#   uml: ptrace interface cleanup
# 
# arch/um/sys-i386/ptrace.c
#   2005/03/10 00:38:31-08:00 jdike@addtoit.com +1 -1
#   uml: ptrace interface cleanup
# 
# arch/um/os-Linux/util/mk_user_constants.c
#   2005/03/10 00:38:31-08:00 jdike@addtoit.com +29 -0
#   uml: ptrace interface cleanup
# 
# arch/um/os-Linux/sys-x86_64/registers.c
#   2005/03/10 00:38:31-08:00 jdike@addtoit.com +1 -2
#   uml: ptrace interface cleanup
# 
# arch/um/os-Linux/sys-i386/registers.c
#   2005/03/10 00:38:31-08:00 jdike@addtoit.com +18 -1
#   uml: ptrace interface cleanup
# 
# arch/um/os-Linux/process.c
#   2005/03/10 00:38:31-08:00 jdike@addtoit.com +1 -1
#   uml: ptrace interface cleanup
# 
# arch/um/kernel/user_util.c
#   2005/03/10 00:38:31-08:00 jdike@addtoit.com +1 -1
#   uml: ptrace interface cleanup
# 
# arch/um/os-Linux/util/mk_user_constants.c
#   2005/03/10 00:38:31-08:00 jdike@addtoit.com +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/arch/um/os-Linux/util/mk_user_constants.c
# 
# arch/um/os-Linux/util/Makefile
#   2005/03/10 00:38:31-08:00 jdike@addtoit.com +4 -0
#   uml: ptrace interface cleanup
# 
# arch/um/kernel/tt/tracer.c
#   2005/03/10 00:38:31-08:00 jdike@addtoit.com +1 -2
#   uml: ptrace interface cleanup
# 
# arch/um/kernel/tt/syscall_user.c
#   2005/03/10 00:38:31-08:00 jdike@addtoit.com +1 -2
#   uml: ptrace interface cleanup
# 
# arch/um/kernel/tt/ptproxy/wait.c
#   2005/03/10 00:38:31-08:00 jdike@addtoit.com +3 -4
#   uml: ptrace interface cleanup
# 
# arch/um/kernel/tt/ptproxy/sysdep.c
#   2005/03/10 00:38:31-08:00 jdike@addtoit.com +10 -11
#   uml: ptrace interface cleanup
# 
# arch/um/kernel/tt/ptproxy/ptrace.c
#   2005/03/10 00:38:31-08:00 jdike@addtoit.com +3 -5
#   uml: ptrace interface cleanup
# 
# arch/um/kernel/tt/ptproxy/proxy.c
#   2005/03/10 00:38:31-08:00 jdike@addtoit.com +1 -1
#   uml: ptrace interface cleanup
# 
# arch/um/kernel/tt/gdb.c
#   2005/03/10 00:38:31-08:00 jdike@addtoit.com +1 -1
#   uml: ptrace interface cleanup
# 
# arch/um/kernel/tt/exec_user.c
#   2005/03/10 00:38:31-08:00 jdike@addtoit.com +0 -2
#   uml: ptrace interface cleanup
# 
# arch/um/kernel/trap_user.c
#   2005/03/10 00:38:31-08:00 jdike@addtoit.com +0 -1
#   uml: ptrace interface cleanup
# 
# arch/um/kernel/skas/process.c
#   2005/03/10 00:38:31-08:00 jdike@addtoit.com +1 -3
#   uml: ptrace interface cleanup
# 
# arch/um/kernel/skas/mem_user.c
#   2005/03/10 00:38:31-08:00 jdike@addtoit.com +0 -1
#   uml: ptrace interface cleanup
# 
# arch/um/kernel/ptrace.c
#   2005/03/10 00:38:31-08:00 jdike@addtoit.com +1 -1
#   uml: ptrace interface cleanup
# 
# arch/um/kernel/process.c
#   2005/03/10 00:38:31-08:00 jdike@addtoit.com +6 -11
#   uml: ptrace interface cleanup
# 
# arch/um/include/sysdep-x86_64/ptrace_user.h
#   2005/03/10 00:38:31-08:00 jdike@addtoit.com +2 -3
#   uml: ptrace interface cleanup
# 
# arch/um/include/sysdep-x86_64/ptrace.h
#   2005/03/10 00:38:31-08:00 jdike@addtoit.com +4 -0
#   uml: ptrace interface cleanup
# 
# arch/um/include/sysdep-i386/ptrace_user.h
#   2005/03/10 00:38:31-08:00 jdike@addtoit.com +2 -5
#   uml: ptrace interface cleanup
# 
# arch/um/include/sysdep-i386/ptrace.h
#   2005/03/10 00:38:31-08:00 jdike@addtoit.com +5 -1
#   uml: ptrace interface cleanup
# 
# arch/um/include/registers.h
#   2005/03/10 00:38:31-08:00 jdike@addtoit.com +2 -0
#   uml: ptrace interface cleanup
# 
# arch/um/Makefile
#   2005/03/10 00:38:31-08:00 jdike@addtoit.com +9 -1
#   uml: ptrace interface cleanup
# 
# arch/um/os-Linux/util/Makefile
#   2005/03/10 00:38:31-08:00 jdike@addtoit.com +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/arch/um/os-Linux/util/Makefile
# 
# ChangeSet
#   2005/03/10 08:36:08-08:00 jdike@addtoit.com 
#   [PATCH] uml: gix hostfs typo
#   
#   Fix a typo in the hostfs setgid code.
#   
#   Signed-off-by: Jeff Dike <jdike@addtoit.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# fs/hostfs/hostfs_kern.c
#   2005/03/10 00:38:31-08:00 jdike@addtoit.com +1 -1
#   uml: gix hostfs typo
# 
# arch/um/include/kern.h
#   2005/03/10 00:38:31-08:00 jdike@addtoit.com +1 -0
#   uml: gix hostfs typo
# 
# ChangeSet
#   2005/03/10 08:35:53-08:00 domen@coderock.org 
#   [PATCH] unified spinlock initialization arch/um/drivers/port_kern.c
#   
#   Unify the spinlock initialization as far as possible.
#   
#   Signed-off-by: Amit Gud <gud@eth.net>
#   Signed-off-by: Domen Puncer <domen@coderock.org>
#   Signed-off-by: Paolo 'Blaisorblade' Giarrusso <blaisorblade@yahoo.it>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/um/drivers/port_kern.c
#   2005/03/10 00:38:30-08:00 domen@coderock.org +1 -1
#   unified spinlock initialization arch/um/drivers/port_kern.c
# 
# ChangeSet
#   2005/03/10 08:35:38-08:00 jdike@addtoit.com 
#   [PATCH] uml: Make a bunch of driver functions static
#   
#   Noticed by Frank Sorenson - the methods in arch/um/drivers/tty.c should be 
#   static.  It turns out that all the channels have the same problem, so these
#   are all fixed.  These files export only a structure of function pointers, so
#   that structure should be the only externally visible symbol.
#   
#   Signed-off-by: Jeff Dike <jdike@addtoit.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/um/drivers/xterm.c
#   2005/03/10 00:38:30-08:00 jdike@addtoit.com +9 -4
#   uml: Make a bunch of driver functions static
# 
# arch/um/drivers/tty.c
#   2005/03/10 00:38:30-08:00 jdike@addtoit.com +4 -3
#   uml: Make a bunch of driver functions static
# 
# arch/um/drivers/pty.c
#   2005/03/10 00:38:30-08:00 jdike@addtoit.com +7 -5
#   uml: Make a bunch of driver functions static
# 
# arch/um/drivers/port_user.c
#   2005/03/10 00:38:30-08:00 jdike@addtoit.com +6 -5
#   uml: Make a bunch of driver functions static
# 
# arch/um/drivers/null.c
#   2005/03/10 00:38:30-08:00 jdike@addtoit.com +5 -4
#   uml: Make a bunch of driver functions static
# 
# arch/um/drivers/fd.c
#   2005/03/10 00:38:30-08:00 jdike@addtoit.com +4 -4
#   uml: Make a bunch of driver functions static
# 
# ChangeSet
#   2005/03/10 08:35:22-08:00 jdike@addtoit.com 
#   [PATCH] uml: Improve error reporting
#   
#   This patch adds some errors and warnings where there were none before:
#       If someone typos "ubd" as "udb", that is caught and a warning is printed
#       If a ubd file can't be opened, that now results in an error message
#       If there are more telnet connections to port consoles than there are
#   consoles, then a message will appear in the telnet session explaining why
#   there is no login prompt.
#   
#   Signed-off-by: Jeff Dike <jdike@addtoit.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/um/drivers/ubd_kern.c
#   2005/03/10 00:38:30-08:00 jdike@addtoit.com +21 -1
#   uml: Improve error reporting
# 
# arch/um/drivers/port_kern.c
#   2005/03/10 00:38:30-08:00 jdike@addtoit.com +20 -3
#   uml: Improve error reporting
# 
# ChangeSet
#   2005/03/10 08:35:06-08:00 jdike@addtoit.com 
#   [PATCH] uml: Fix a compile failure
#   
#   Remove a UML/x86_64 warning (and build failure if CONFIG_MODE_TT is disabled).
#   
#   Signed-off-by: Jeff Dike <jdike@addtoit.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/um/sys-x86_64/ptrace_user.c
#   2005/03/10 00:38:30-08:00 jdike@addtoit.com +6 -17
#   uml: Fix a compile failure
# 
# ChangeSet
#   2005/03/10 08:34:51-08:00 jdike@addtoit.com 
#   [PATCH] uml: Remove mm_indirect reference in modify_ldt
#   
#   Spotted by Al Viro, there was some bogosity in the UML/x86_64 modify_ltd.
#   
#   Signed-off-by: Jeff Dike <jdike@addtoit.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/um/sys-x86_64/syscalls.c
#   2005/03/10 00:38:29-08:00 jdike@addtoit.com +7 -12
#   uml: Remove mm_indirect reference in modify_ldt
# 
# ChangeSet
#   2005/03/10 08:34:35-08:00 jdike@addtoit.com 
#   [PATCH] uml: Remove useless sys_mount wrapper
#   
#   um_mount did nothing but turn around and call sys_mount with the same
#   arguments.  This makes it useless code, and it has been duly removed.
#   
#   Signed-off-by: Jeff Dike <jdike@addtoit.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/um/kernel/syscall_kern.c
#   2005/03/10 00:38:29-08:00 jdike@addtoit.com +0 -6
#   uml: Remove useless sys_mount wrapper
# 
# arch/um/kernel/sys_call_table.c
#   2005/03/10 00:38:29-08:00 jdike@addtoit.com +1 -2
#   uml: Remove useless sys_mount wrapper
# 
# ChangeSet
#   2005/03/10 08:34:19-08:00 jdike@addtoit.com 
#   [PATCH] uml: add a comment explaining pread availability
#   
#   Prompted by Dave Mielke: This adds a comment explaining why we do not
#   define _XOPEN_SOURCE, even though the pread man page says you should.
#   
#   Signed-off-by: Jeff Dike <jdike@addtoit.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/um/drivers/cow_user.c
#   2005/03/10 00:38:29-08:00 jdike@addtoit.com +3 -0
#   uml: add a comment explaining pread availability
# 
# ChangeSet
#   2005/03/10 08:34:04-08:00 jdike@addtoit.com 
#   [PATCH] uml: Make syscall debugging code configurable
#   
#   This patch makes some debug code in the system call path configurable.
#   
#   Signed-off-by: Jeff Dike <jdike@addtoit.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/um/kernel/tt/tracer.c
#   2005/03/10 00:38:29-08:00 jdike@addtoit.com +21 -2
#   uml: Make syscall debugging code configurable
# 
# arch/um/kernel/tt/syscall_user.c
#   2005/03/10 00:38:29-08:00 jdike@addtoit.com +9 -0
#   uml: Make syscall debugging code configurable
# 
# arch/um/kernel/tt/syscall_kern.c
#   2005/03/10 00:38:29-08:00 jdike@addtoit.com +2 -0
#   uml: Make syscall debugging code configurable
# 
# arch/um/kernel/syscall_user.c
#   2005/03/10 00:38:29-08:00 jdike@addtoit.com +48 -0
#   uml: Make syscall debugging code configurable
# 
# arch/um/kernel/syscall_kern.c
#   2005/03/10 00:38:29-08:00 jdike@addtoit.com +16 -0
#   uml: Make syscall debugging code configurable
# 
# arch/um/kernel/skas/syscall_user.c
#   2005/03/10 00:38:29-08:00 jdike@addtoit.com +9 -0
#   uml: Make syscall debugging code configurable
# 
# arch/um/kernel/Makefile
#   2005/03/10 00:38:29-08:00 jdike@addtoit.com +1 -0
#   uml: Make syscall debugging code configurable
# 
# arch/um/defconfig
#   2005/03/10 00:38:29-08:00 jdike@addtoit.com +8 -2
#   uml: Make syscall debugging code configurable
# 
# arch/um/Kconfig.debug
#   2005/03/10 00:38:29-08:00 jdike@addtoit.com +10 -0
#   uml: Make syscall debugging code configurable
# 
# ChangeSet
#   2005/03/10 08:33:48-08:00 jdike@addtoit.com 
#   [PATCH] uml: Clean up the syscall path
#   
#   This patch removes some useless code from the system call path, and removes
#   some debug code, which will reappear in a configurable form in the
#   syscall-debug patch.
#   
#   Signed-off-by: Jeff Dike <jdike@addtoit.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/um/kernel/tt/tracer.c
#   2005/03/10 00:38:28-08:00 jdike@addtoit.com +1 -18
#   uml: Clean up the syscall path
# 
# arch/um/kernel/tt/syscall_user.c
#   2005/03/10 00:38:28-08:00 jdike@addtoit.com +2 -4
#   uml: Clean up the syscall path
# 
# arch/um/kernel/tt/include/tt.h
#   2005/03/10 00:38:28-08:00 jdike@addtoit.com +1 -0
#   uml: Clean up the syscall path
# 
# arch/um/kernel/syscall_kern.c
#   2005/03/10 00:38:28-08:00 jdike@addtoit.com +0 -21
#   uml: Clean up the syscall path
# 
# arch/um/kernel/skas/syscall_user.c
#   2005/03/10 00:38:28-08:00 jdike@addtoit.com +2 -6
#   uml: Clean up the syscall path
# 
# arch/um/kernel/skas/include/skas.h
#   2005/03/10 00:38:28-08:00 jdike@addtoit.com +1 -0
#   uml: Clean up the syscall path
# 
# arch/um/kernel/Makefile
#   2005/03/10 00:38:28-08:00 jdike@addtoit.com +3 -3
#   uml: Clean up the syscall path
# 
# ChangeSet
#   2005/03/10 08:33:33-08:00 bstroesser@fujitsu-siemens.com 
#   [PATCH] uml: Code cleanup
#   
#   Shifting register restore and userspace resume to the beginning of the
#   userspace loop, we can remove the identical code done before the loop.
#   
#   Signed-off-by: Bodo Stroesser <bstroesser@fujitsu-siemens.com>
#   Signed-off-by: Jeff Dike <jdike@addtoit.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/um/kernel/skas/process.c
#   2005/03/10 00:38:28-08:00 bstroesser@fujitsu-siemens.com +13 -23
#   uml: Code cleanup
# 
# ChangeSet
#   2005/03/10 08:33:18-08:00 jdike@addtoit.com 
#   [PATCH] uml: Fix a shutdown hang caused by a failed ifconfig
#   
#   The network driver wasn't checking that the host side of an interface had been
#   successfully opened before trying to close it at shuwtdown.
#   
#   Signed-off-by: Jeff Dike <jdike@addtoit.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/um/drivers/net_kern.c
#   2005/03/10 00:38:28-08:00 jdike@addtoit.com +2 -1
#   uml: Fix a shutdown hang caused by a failed ifconfig
# 
# ChangeSet
#   2005/03/10 08:33:03-08:00 jdike@addtoit.com 
#   [PATCH] uml: make the ubd driver recognize letters in device names
#   
#   ubd_get_config wasn't using the standard device number parser, which caused it
#   not to recognize letters.
#   
#   Signed-off-by: Jeff Dike <jdike@addtoit.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/um/drivers/ubd_kern.c
#   2005/03/10 00:38:28-08:00 jdike@addtoit.com +1 -7
#   uml: make the ubd driver recognize letters in device names
# 
# ChangeSet
#   2005/03/10 08:32:48-08:00 jdike@addtoit.com 
#   [PATCH] uml: Fix some usercopy confusion
#   
#   This fixes a couple of copy-user problems spotted by Al Viro.
#   
#   copy_sc_from_user_tt was doing a copy_from_user to do an in-kernel assignment.
#    I commented this, at the request of Chris Wedgewood.  sys_ipc had a void
#   *__user ptr which should have been void __user *ptr.  Finally, there were a
#   couple of bogus __user annotations on unsigned longs, which were never going
#   to be passed into copy_user.
#   
#   Signed-off-by: Jeff Dike <jdike@addtoit.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/um/sys-x86_64/signal.c
#   2005/03/10 00:38:27-08:00 jdike@addtoit.com +1 -1
#   uml: Fix some usercopy confusion
# 
# arch/um/sys-i386/syscalls.c
#   2005/03/10 00:38:27-08:00 jdike@addtoit.com +1 -1
#   uml: Fix some usercopy confusion
# 
# arch/um/sys-i386/signal.c
#   2005/03/10 00:38:27-08:00 jdike@addtoit.com +13 -7
#   uml: Fix some usercopy confusion
# 
# ChangeSet
#   2005/03/10 08:32:32-08:00 jdike@addtoit.com 
#   [PATCH] uml: Get rid of uneccessary hostfs build trick
#   
#   Get rid of the grepping for __st_ino in hostfs, since it doesn't work on
#   x86_64 (the grep finds it, but it is ifdefed out), and Al says it's
#   unnecessary anyway.
#   
#   Signed-off-by: Jeff Dike <jdike@addtoit.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# fs/hostfs/hostfs_user.c
#   2005/03/10 00:38:27-08:00 jdike@addtoit.com +1 -4
#   uml: Get rid of uneccessary hostfs build trick
# 
# fs/hostfs/Makefile
#   2005/03/10 00:38:27-08:00 jdike@addtoit.com +0 -9
#   uml: Get rid of uneccessary hostfs build trick
# 
# ChangeSet
#   2005/03/10 08:32:17-08:00 tzachar@cs.bgu.ac.il 
#   [PATCH] uml: slirp driver tells the network it's not ethernet
#   
#   Tell the netdevice code that a slirp device is not ethernet.
#   
#   Signed-off-by: Jeff Dike <jdike@addtoit.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/um/drivers/slirp_kern.c
#   2005/03/10 00:38:27-08:00 tzachar@cs.bgu.ac.il +5 -2
#   uml: slirp driver tells the network it's not ethernet
# 
# ChangeSet
#   2005/03/10 08:32:02-08:00 jdike@addtoit.com 
#   [PATCH] uml: Update defconfig
#   
#   Signed-off-by: Jeff Dike <jdike@addtoit.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/um/defconfig
#   2005/03/10 00:38:26-08:00 jdike@addtoit.com +30 -20
#   uml: Update defconfig
# 
# ChangeSet
#   2005/03/10 08:31:48-08:00 jdike@addtoit.com 
#   [PATCH] uml: 2.6.11 updates
#   
#   This patch makes some small changes that parallel changes in 2.6.11:
#   	The csum buffers are now unsigned char.
#   	Got rid of an unused define from pgtable-2level.h.
#   
#   Signed-off-by: Jeff Dike <jdike@addtoit.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/asm-um/pgtable-2level.h
#   2005/03/10 00:38:26-08:00 jdike@addtoit.com +0 -1
#   uml: 2.6.11 updates
# 
# arch/um/kernel/checksum.c
#   2005/03/10 00:38:26-08:00 jdike@addtoit.com +17 -26
#   uml: 2.6.11 updates
# 
# arch/um/include/sysdep-x86_64/checksum.h
#   2005/03/10 00:38:26-08:00 jdike@addtoit.com +3 -3
#   uml: 2.6.11 updates
# 
# ChangeSet
#   2005/03/10 08:31:32-08:00 coywolf@gmail.com 
#   [PATCH] remove barrier() in software_resume()
#   
#   This patch removes the redundant compiler barrier.  As Linus ever said "The
#   mb() should make sure that gcc cannot move things around...".
#   
#   Signed-off-by: Coywolf Qi Hunt <coywolf@gmail.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# kernel/power/disk.c
#   2005/03/10 00:38:26-08:00 coywolf@gmail.com +0 -1
#   remove barrier() in software_resume()
# 
# ChangeSet
#   2005/03/10 08:31:17-08:00 mst@mellanox.co.il 
#   [PATCH] x86: disable MSI for AMD-8131
#   
#   The AMD-8131 I/O APIC (device id 1022:7450/7451) does not support message
#   signalled interrupts.  Thus, if a device driver attempts to enable msi, it
#   will suceed, but interrupts are not actually delivered to the cpu.  The
#   Nforce chipsets do not seem to have this limitation.  AMD confirmed that
#   MSI mode is unsupported with this APIC.
#   
#   The following patch adds a flag to pci quirks to detect this and disable
#   msi.
#   
#   Signed-off-by: Michael S. Tsirkin <mst@mellano.co.il>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/pci/quirks.c
#   2005/03/10 00:38:25-08:00 mst@mellanox.co.il +5 -0
#   x86: disable MSI for AMD-8131
# 
# drivers/pci/pci.h
#   2005/03/10 00:38:25-08:00 mst@mellanox.co.il +1 -0
#   x86: disable MSI for AMD-8131
# 
# drivers/pci/msi.c
#   2005/03/10 00:38:25-08:00 mst@mellanox.co.il +8 -0
#   x86: disable MSI for AMD-8131
# 
# ChangeSet
#   2005/03/10 08:31:01-08:00 haveblue@us.ibm.com 
#   [PATCH] x86: SRAT cleanup: make calculations and indenting level more sane
#   
#   Using the assumption that all addresses in the SRAT are ascending, the
#   calculations can get a bit simpler, and remove the "been_here_before"
#   variable.
#   
#   This also breaks that calculation out into its own function, which further
#   simplifies the look of the code.
#   
#   Signed-off-by: Dave Hansen <haveblue@us.ibm.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/i386/kernel/srat.c
#   2005/03/10 00:38:25-08:00 haveblue@us.ibm.com +35 -32
#   x86: SRAT cleanup: make calculations and indenting level more sane
# 
# ChangeSet
#   2005/03/10 08:30:46-08:00 haveblue@us.ibm.com 
#   [PATCH] x86: allow SRAT to parse empty nodes
#   
#   This patch is to allow the booting of a numa srat base i386 system without
#   requiring memory to be in all of it's nodes.  It breaks the assumption that
#   all nodes have memory during bootup.
#   
#   Signed-off-by: Keith Mannthey <kmannth@us.ibm.com>
#   Signed-off-by: Dave Hansen <haveblue@us.ibm.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/linux/topology.h
#   2005/03/10 00:38:25-08:00 haveblue@us.ibm.com +4 -1
#   x86: allow SRAT to parse empty nodes
# 
# include/asm-i386/topology.h
#   2005/03/10 00:38:25-08:00 haveblue@us.ibm.com +6 -0
#   x86: allow SRAT to parse empty nodes
# 
# arch/i386/mm/discontig.c
#   2005/03/10 00:38:25-08:00 haveblue@us.ibm.com +19 -13
#   x86: allow SRAT to parse empty nodes
# 
# arch/i386/kernel/srat.c
#   2005/03/10 00:38:25-08:00 haveblue@us.ibm.com +12 -2
#   x86: allow SRAT to parse empty nodes
# 
# arch/i386/kernel/numaq.c
#   2005/03/10 00:38:25-08:00 haveblue@us.ibm.com +1 -3
#   x86: allow SRAT to parse empty nodes
# 
# ChangeSet
#   2005/03/10 08:30:30-08:00 haveblue@us.ibm.com 
#   [PATCH] x86: abstract discontigmem setup
#   
#   memory_present() is how each arch/subarch will tell sparsemem and discontigmem
#   where all of its memory is.  This is what triggers sparse to go out and create
#   its mappings for the memory, as well as allocate the mem_map[].
#   
#   By: Andy Whitcroft <apw@shadowen.org>
#   Signed-off-by: Dave Hansen <haveblue@us.ibm.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/linux/mmzone.h
#   2005/03/10 00:38:25-08:00 haveblue@us.ibm.com +11 -0
#   x86: abstract discontigmem setup
# 
# arch/i386/mm/discontig.c
#   2005/03/10 00:38:25-08:00 haveblue@us.ibm.com +31 -19
#   x86: abstract discontigmem setup
# 
# arch/i386/kernel/srat.c
#   2005/03/10 00:38:25-08:00 haveblue@us.ibm.com +8 -1
#   x86: abstract discontigmem setup
# 
# arch/i386/kernel/numaq.c
#   2005/03/10 00:38:25-08:00 haveblue@us.ibm.com +7 -1
#   x86: abstract discontigmem setup
# 
# arch/i386/Kconfig
#   2005/03/10 00:38:25-08:00 haveblue@us.ibm.com +10 -0
#   x86: abstract discontigmem setup
# 
# ChangeSet
#   2005/03/10 08:30:15-08:00 haveblue@us.ibm.com 
#   [PATCH] x86: do not unnecessarily memset the pgdats
#   
#   Both the pgdats and the struct zonelist are zeroed unnecessarily.  The
#   zonelist is a member of the pgdat, so any time the pgdat is cleared, so is the
#   zonelist.  All of the architectures present a zeroed pgdat to the generic
#   code, so it's not necessary to set it again.
#   
#   Not clearing it like this allows the functions to be reused by the memory
#   hotplug code.  The only architecture which has a dependence on these clears is
#   i386.  The previous patch in this series fixed that up.
#   
#   Signed-off-by: Dave Hansen <haveblue@us.ibm.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# mm/page_alloc.c
#   2005/03/10 00:38:24-08:00 haveblue@us.ibm.com +0 -2
#   x86: do not unnecessarily memset the pgdats
# 
# ChangeSet
#   2005/03/10 08:30:00-08:00 haveblue@us.ibm.com 
#   [PATCH] x86: memset the i386 numa pgdats in arch code
#   
#   The next patch in this series will remove the arch-independent clearing of the
#   pgdat's.  This first patch removes the i386 dependency on that behavior.
#   
#   The new i386 function, remapped_pgdat_init() takes care of initializing the
#   pgdats which are finally mapped after paging_init() is done.  The
#   zone_sizes_init() call has to occur after the pgdat clearing.
#   
#   zone_sizes_init() is currently called from the end of paging_init(), because
#   that's the first place where the pgdats could have been zeroed.  However,
#   zone_sizes_init() really doesn't have anything to do with paging, and probably
#   shouldn't be in paging_init().
#   
#   Moving this call into setup_memory() allows the declaration of
#   zone_sizes_init() to change files as well, which means a net removal of one
#   #ifdef.  It also provides a handy place to put the new function, far away from
#   the paging code that it really has nothing to do with.  Moving files required
#   only using highend_pfn inside of the HIGHMEM ifdef, but this saves a line of
#   code anyway.
#   
#   Fixes from: Yasunori Goto <ygoto@us.fujitsu.com>
#   Signed-off-by: Dave Hansen <haveblue@us.ibm.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/i386/mm/init.c
#   2005/03/10 00:38:24-08:00 haveblue@us.ibm.com +0 -26
#   x86: memset the i386 numa pgdats in arch code
# 
# arch/i386/mm/discontig.c
#   2005/03/10 00:38:24-08:00 haveblue@us.ibm.com +1 -3
#   x86: memset the i386 numa pgdats in arch code
# 
# arch/i386/kernel/setup.c
#   2005/03/10 00:38:24-08:00 haveblue@us.ibm.com +42 -0
#   x86: memset the i386 numa pgdats in arch code
# 
# ChangeSet
#   2005/03/10 08:29:45-08:00 david@gibson.dropbear.id.au 
#   [PATCH] ppc64: allow emulation of mfpvr on ppc64 kernel
#   
#   Allow userspace programs on ppc64 to use the (privileged) mfpvr instruction
#   to determine the processor type.  At the moment it emulates the instruction
#   to provide the real PVR value, though it could be made to lie in future if
#   for some reason we wish to restrict what CPU features userspace uses.
#   
#   If nothing else this means that some existing ppc32 applications will now
#   run on a 64-bit kernel (the 32-bit kernel has long supported this
#   emulation).  It will also be necessary for ppc64 perfctr support, where
#   userspace requires finer-grained cpu type information than the kernel in
#   order to correctly program the performance monitor control registers.
#   
#   Signed-off-by: David Gibson <dwg@au1.ibm.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/ppc64/kernel/traps.c
#   2005/03/10 00:38:24-08:00 david@gibson.dropbear.id.au +19 -7
#   ppc64: allow emulation of mfpvr on ppc64 kernel
# 
# ChangeSet
#   2005/03/10 08:29:29-08:00 ntl@pobox.com 
#   [PATCH] ppc64: fix xmon build break with non-SMP config
#   
#     CC      arch/ppc64/xmon/xmon.o
#   arch/ppc64/xmon/xmon.c: In function `set_controlled_dabr':
#   arch/ppc64/xmon/xmon.c:633: warning: implicit declaration of function `plpar_hcall_norets'
#   arch/ppc64/xmon/xmon.c:633: error: `H_SET_DABR' undeclared (first use in this function)
#   arch/ppc64/xmon/xmon.c:633: error: (Each undeclared identifier is reported only once
#   arch/ppc64/xmon/xmon.c:633: error: for each function it appears in.)
#   arch/ppc64/xmon/xmon.c:634: error: `H_Success' undeclared (first use in this function)
#   
#   Signed-off-by: Nathan Lynch <ntl@pobox.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/ppc64/xmon/xmon.c
#   2005/03/10 00:38:24-08:00 ntl@pobox.com +1 -0
#   ppc64: fix xmon build break with non-SMP config
# 
# ChangeSet
#   2005/03/10 08:29:14-08:00 galak@freescale.com 
#   [PATCH] ppc32: Consolidate Kconfig support for 83xx
#   
#   Consolidate Kconfig options between arch/ppc/platforms/83xx/Kconfig and
#   arch/ppc/Kconfig at Tom Rini's request.
#   
#   Signed-off-by: Kumar Gala <kumar.gala@freescale.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/ppc/Kconfig
#   2005/03/10 00:38:23-08:00 galak@freescale.com +17 -4
#   ppc32: Consolidate Kconfig support for 83xx
# 
# BitKeeper/deleted/.del-Kconfig~ded3e04631b0556c
#   2005/03/10 08:29:05-08:00 galak@freescale.com +0 -0
#   Delete: arch/ppc/platforms/83xx/Kconfig
# 
# ChangeSet
#   2005/03/10 08:28:59-08:00 sds@tycho.nsa.gov 
#   [PATCH] SELinux: fix selinux_setprocattr
#   
#   This patch changes the selinux_setprocattr hook function (which handles
#   writes to nodes in the /proc/pid/attr directory) to ignore an optional
#   terminating newline at the end of the value, and to handle a value
#   beginning with a newline or a null in the same manner as a zero length
#   value (clearing the attribute for the process and resetting it to using the
#   default policy behavior).  This change is to address the divergence from
#   POSIX in the existing API, as POSIX says that write(2) with a zero count
#   will return zero with no other effect, as well as to simplify use of the
#   API from scripts (although that isn't recommended).
#   
#   Signed-off-by:  Stephen Smalley <sds@tycho.nsa.gov>
#   Signed-off-by:  James Morris <jmorris@redhat.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# security/selinux/hooks.c
#   2005/03/10 00:38:23-08:00 sds@tycho.nsa.gov +6 -2
#   SELinux: fix selinux_setprocattr
# 
# ChangeSet
#   2005/03/10 08:28:44-08:00 sds@tycho.nsa.gov 
#   [PATCH] SELinux: document boot options
#   
#   Signed-off-by:  Stephen Smalley <sds@tycho.nsa.gov>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# Documentation/kernel-parameters.txt
#   2005/03/10 00:38:23-08:00 sds@tycho.nsa.gov +26 -0
#   SELinux: document boot options
# 
# ChangeSet
#   2005/03/10 08:28:29-08:00 sds@tycho.nsa.gov 
#   [PATCH] SELinux: pass requested protection to security_file_mmap/mprotect hooks
#   
#   This patch adds a reqprot parameter to the security_file_mmap and
#   security_file_mprotect hooks that is the original requested protection
#   value prior to any modification for read-implies-exec, and changes the
#   SELinux module to allow a mode of operation (controllable via a
#   checkreqprot setting) where it applies checks based on that protection
#   value rather than the protection that will be applied by the kernel,
#   effectively restoring SELinux's original behavior prior to the introduction
#   of the read-implies-exec logic in the mainline kernel.  The patch also
#   disables execmem and execmod checking entirely on PPC32, as the PPC32 ELF
#   ABI presently requires RWE segments per Ulrich Drepper.
#   
#   At present, the read-implies-exec logic causes SELinux to see every
#   mmap/mprotect read request by legacy binaries or binaries marked with
#   PT_GNU_STACK RWE as a read|execute request, which tends to distort policy
#   even if it reflects what is ultimately possible.  The checkreqprot setting
#   allows one to set the desired behavior for SELinux, so either the current
#   behavior or the original behavior is possible.  The checkreqprot value has
#   a compile-time configurable default value and can also be set via boot
#   parameter or at runtime via /selinux/checkreqprot if allowed by policy. 
#   Thanks to Chris Wright, James Morris, and Colin Walters for comments on an
#   earlier version of the patch.
#   
#   Signed-off-by: Stephen Smalley <sds@tycho.nsa.gov>
#   Signed-off-by: James Morris <jmorris@redhat.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# security/selinux/selinuxfs.c
#   2005/03/10 00:38:22-08:00 sds@tycho.nsa.gov +60 -0
#   SELinux: pass requested protection to security_file_mmap/mprotect hooks
# 
# security/selinux/include/objsec.h
#   2005/03/10 00:38:22-08:00 sds@tycho.nsa.gov +2 -0
#   SELinux: pass requested protection to security_file_mmap/mprotect hooks
# 
# security/selinux/include/av_permissions.h
#   2005/03/10 00:38:22-08:00 sds@tycho.nsa.gov +1 -0
#   SELinux: pass requested protection to security_file_mmap/mprotect hooks
# 
# security/selinux/include/av_perm_to_string.h
#   2005/03/10 00:38:22-08:00 sds@tycho.nsa.gov +1 -0
#   SELinux: pass requested protection to security_file_mmap/mprotect hooks
# 
# security/selinux/hooks.c
#   2005/03/10 00:38:22-08:00 sds@tycho.nsa.gov +15 -3
#   SELinux: pass requested protection to security_file_mmap/mprotect hooks
# 
# security/selinux/Kconfig
#   2005/03/10 00:38:22-08:00 sds@tycho.nsa.gov +19 -0
#   SELinux: pass requested protection to security_file_mmap/mprotect hooks
# 
# security/dummy.c
#   2005/03/10 00:38:22-08:00 sds@tycho.nsa.gov +5 -2
#   SELinux: pass requested protection to security_file_mmap/mprotect hooks
# 
# mm/mprotect.c
#   2005/03/10 00:38:22-08:00 sds@tycho.nsa.gov +4 -2
#   SELinux: pass requested protection to security_file_mmap/mprotect hooks
# 
# mm/mmap.c
#   2005/03/10 00:38:22-08:00 sds@tycho.nsa.gov +2 -2
#   SELinux: pass requested protection to security_file_mmap/mprotect hooks
# 
# include/linux/security.h
#   2005/03/10 00:38:22-08:00 sds@tycho.nsa.gov +16 -7
#   SELinux: pass requested protection to security_file_mmap/mprotect hooks
# 
# ChangeSet
#   2005/03/10 08:28:14-08:00 dgoeddel@trustedcs.com 
#   [PATCH] SELinux: enhanced MLS support
#   
#   This patch replaces the original experimental Multi-Level Security (MLS)
#   implementation in SELinux with an enhanced MLS implementation contributed
#   by Trusted Computer Solutions (TCS).
#   
#   The enhanced MLS implementation replaces the hardcoded MLS logic with a
#   flexible constraint-based system and replaces the compile-time option for
#   MLS support with a policy load-time enable based on whether MLS support was
#   enabled in the policy when it was built.
#   
#   The latter change allows a single kernel and policy toolchain to support
#   both MLS and non-MLS policies.  Compatibility is still provided as usual
#   for existing policies.
#   
#   Signed-off-by:  Stephen Smalley <sds@tycho.nsa.gov>
#   Signed-off-by:  James Morris <jmorris@redhat.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# security/selinux/ss/services.c
#   2005/03/10 00:38:22-08:00 dgoeddel@trustedcs.com +207 -59
#   SELinux: enhanced MLS support
# 
# security/selinux/ss/policydb.h
#   2005/03/10 00:38:22-08:00 dgoeddel@trustedcs.com +24 -34
#   SELinux: enhanced MLS support
# 
# security/selinux/ss/policydb.c
#   2005/03/10 00:38:22-08:00 dgoeddel@trustedcs.com +451 -124
#   SELinux: enhanced MLS support
# 
# security/selinux/ss/mls_types.h
#   2005/03/10 00:38:22-08:00 dgoeddel@trustedcs.com +37 -39
#   SELinux: enhanced MLS support
# 
# security/selinux/ss/mls.h
#   2005/03/10 00:38:22-08:00 dgoeddel@trustedcs.com +11 -68
#   SELinux: enhanced MLS support
# 
# security/selinux/ss/mls.c
#   2005/03/10 00:38:22-08:00 dgoeddel@trustedcs.com +251 -475
#   SELinux: enhanced MLS support
# 
# security/selinux/ss/context.h
#   2005/03/10 00:38:22-08:00 dgoeddel@trustedcs.com +10 -20
#   SELinux: enhanced MLS support
# 
# security/selinux/ss/constraint.h
#   2005/03/10 00:38:22-08:00 dgoeddel@trustedcs.com +7 -0
#   SELinux: enhanced MLS support
# 
# security/selinux/ss/Makefile
#   2005/03/10 00:38:22-08:00 dgoeddel@trustedcs.com +1 -3
#   SELinux: enhanced MLS support
# 
# security/selinux/include/security.h
#   2005/03/10 00:38:22-08:00 dgoeddel@trustedcs.com +7 -6
#   SELinux: enhanced MLS support
# 
# security/selinux/hooks.c
#   2005/03/10 00:38:22-08:00 dgoeddel@trustedcs.com +7 -0
#   SELinux: enhanced MLS support
# 
# security/selinux/Kconfig
#   2005/03/10 00:38:22-08:00 dgoeddel@trustedcs.com +0 -9
#   SELinux: enhanced MLS support
# 
# ChangeSet
#   2005/03/10 08:27:58-08:00 kenneth.w.chen@intel.com 
#   [PATCH] fix in slab.c:alloc_arraycache
#   
#   Kmem_cache_alloc_node is not capable of handling a null cachep pointer as
#   its input argument.
#   
#   If I try to increase a slab limit by echoing a very large number into
#   /proc/slabinfo, kernel will panic from alloc_arraycache() because
#   Kmem_find_general_cachep() can actually return a NULL pointer if the size
#   argument is sufficiently large.
#   
#   Signed-off-by: Ken Chen <kenneth.w.chen@intel.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# mm/slab.c
#   2005/03/10 00:38:21-08:00 kenneth.w.chen@intel.com +4 -2
#   fix in slab.c:alloc_arraycache
# 
# ChangeSet
#   2005/03/10 08:27:42-08:00 akpm@osdl.org 
#   [PATCH] setup_per_zone_lowmem_reserve() oops fix
#   
#   If you do 'echo 0 0 > /proc/sys/vm/lowmem_reserve_ratio' the kernel gets a
#   divide-by-zero.
#   
#   Prevent that, and fiddle with some whitespace too.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# mm/page_alloc.c
#   2005/03/10 00:38:21-08:00 akpm@osdl.org +15 -6
#   setup_per_zone_lowmem_reserve() oops fix
# 
# ChangeSet
#   2005/03/10 08:27:26-08:00 neilb@cse.unsw.edu.au 
#   [PATCH] md: fix typo in super_1_sync
#   
#   Instead of setting one value lots of times, let's set lots of values once
#   each, as we should..
#   
#   This fixes possible inconsistencies that might arise in a version-1 superblock
#   when devices fail and are removed.
#   
#   Usage of version-1 superblocks is not yet widespread and no actual problems
#   have been reported.
#   
#   From: Paul Clements <paul.clements@steeleye.com>
#   Signed-off-by: Neil Brown <neilb@cse.unsw.edu.au>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/md/md.c
#   2005/03/10 00:38:21-08:00 neilb@cse.unsw.edu.au +1 -1
#   md: fix typo in super_1_sync
# 
# ChangeSet
#   2005/03/10 08:27:11-08:00 akpm@osdl.org 
#   [PATCH] ptep_test_and_clear_dirty typo fix
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/asm-generic/pgtable.h
#   2005/03/10 02:42:25-08:00 akpm@osdl.org +1 -1
#   ptep_test_and_clear_dirty typo fix
# 
# ChangeSet
#   2005/03/10 16:15:57+01:00 bram.verweij@wanadoo.nl 
#   [ide] fix DMA support for LBA48 disks on ALi15x3 (revs < 0xC5)
#   
#   From: Bram Verweij <bram.verweij@wanadoo.nl>
#   
#   The problem seems to be that ide-disk.c tries to use PIO mode for
#   blocks > 137 GB (which is good), and LBA48 + DMA for blocks <= 137GB
#   (which is known to be a problem, i.e., this is why the no_lba48_dma 
#   field was introduced in the first place).  Attached is a small patch
#   that makes ide-disk.c use PIO mode for blocks > 137 GB, and LBA28 DMA
#   (instead of LBA48 DMA) for blocks <= 137 GB.
#   
#   bart: argh, I forgot about 'lba48' flag; patch slightly modified by me
#   
#   Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
# 
# drivers/ide/ide-disk.c
#   2005/03/10 16:07:50+01:00 bram.verweij@wanadoo.nl +3 -1
#   [ide] fix DMA support for LBA48 disks on ALi15x3 (revs < 0xC5)
# 
# ChangeSet
#   2005/03/10 22:49:02+11:00 airlied@starflyer.(none) 
#   drm: fix setversion ioctl zeroing
#   
#   Egbert Eich reported a bug 2673 on bugs.freedesktop.org and tracked it
#   down to a missing memset in the setversion ioctl, this causes X server
#   crashes so I would like to see the fix in a 2.6.11.x tree if possible..
#   
#   From: Egbert Eich <eich@pdx.freedesktop.org>
#   Signed-off-by: Dave Airlie <airlied@linux.ie>
# 
# drivers/char/drm/drm_ioctl.c
#   2005/03/10 22:48:54+11:00 airlied@starflyer.(none) +2 -0
#   drm: fix setversion ioctl zeroing
#   
#   Egbert Eich reported a bug 2673 on bugs.freedesktop.org and tracked it
#   down to a missing memset in the setversion ioctl, this causes X server
#   crashes so I would like to see the fix in a 2.6.11.x tree if possible..
#   
#   From: Egbert Eich <eich@pdx.freedesktop.org>
#   Signed-off-by: Dave Airlie <airlied@linux.ie>
# 
# ChangeSet
#   2005/03/10 22:11:56+11:00 airlied@starflyer.(none) 
#   Merge starflyer.(none):/foo/airlied/bitkeeper/drm-heads
#   into starflyer.(none):/foo/airlied/bitkeeper/drm-linus
# 
# drivers/char/drm/i830_drv.c
#   2005/03/10 22:11:52+11:00 airlied@starflyer.(none) +0 -0
#   Auto merged
# 
# drivers/char/drm/i830_dma.c
#   2005/03/10 22:11:52+11:00 airlied@starflyer.(none) +0 -0
#   Auto merged
# 
# drivers/char/drm/i810_drv.c
#   2005/03/10 22:11:52+11:00 airlied@starflyer.(none) +0 -0
#   Auto merged
# 
# drivers/char/drm/i810_dma.c
#   2005/03/10 22:11:52+11:00 airlied@starflyer.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2005/03/10 21:59:02+11:00 airlied@starflyer.(none) 
#   drm: upgrade radeon driver to 1.15
#   
#   add support for texture micro tiling on radeon/r200. 
#   Add support for r100 cube maps (since it also requires a version bump).
#   
#   From: Roland Scheidegger <rscheidegger_lists@hispeed.ch>
#   Signed-off-by: Dave Airlie <airlied@linux.ie>
# 
# drivers/char/drm/radeon_state.c
#   2005/03/10 21:58:53+11:00 airlied@starflyer.(none) +129 -22
#   drm: upgrade radeon driver to 1.15
#   
#   add support for texture micro tiling on radeon/r200. 
#   Add support for r100 cube maps (since it also requires a version bump).
#   
#   From: Roland Scheidegger <rscheidegger_lists@hispeed.ch>
#   Signed-off-by: Dave Airlie <airlied@linux.ie>
# 
# drivers/char/drm/radeon_drv.h
#   2005/03/10 21:58:53+11:00 airlied@starflyer.(none) +9 -1
#   drm: upgrade radeon driver to 1.15
#   
#   add support for texture micro tiling on radeon/r200. 
#   Add support for r100 cube maps (since it also requires a version bump).
#   
#   From: Roland Scheidegger <rscheidegger_lists@hispeed.ch>
#   Signed-off-by: Dave Airlie <airlied@linux.ie>
# 
# drivers/char/drm/radeon_drm.h
#   2005/03/10 21:58:53+11:00 airlied@starflyer.(none) +7 -2
#   drm: upgrade radeon driver to 1.15
#   
#   add support for texture micro tiling on radeon/r200. 
#   Add support for r100 cube maps (since it also requires a version bump).
#   
#   From: Roland Scheidegger <rscheidegger_lists@hispeed.ch>
#   Signed-off-by: Dave Airlie <airlied@linux.ie>
# 
# ChangeSet
#   2005/03/10 21:44:35+11:00 airlied@starflyer.(none) 
#   drm: cleanup i810/i830 drivers
#   
#   Cleanup patch for i810/i830 
#   
#   From: Adrian Bunk <bunk@stusta.de>
#   Signed-off-by: Dave Airlie <airlied@linux.ie>
# 
# drivers/char/drm/i830_drv.h
#   2005/03/10 21:44:27+11:00 airlied@starflyer.(none) +3 -37
#   drm: cleanup i810/i830 drivers
#   
#   Cleanup patch for i810/i830 
#   
#   From: Adrian Bunk <bunk@stusta.de>
#   Signed-off-by: Dave Airlie <airlied@linux.ie>
# 
# drivers/char/drm/i830_drv.c
#   2005/03/10 21:44:27+11:00 airlied@starflyer.(none) +1 -0
#   drm: cleanup i810/i830 drivers
#   
#   Cleanup patch for i810/i830 
#   
#   From: Adrian Bunk <bunk@stusta.de>
#   Signed-off-by: Dave Airlie <airlied@linux.ie>
# 
# drivers/char/drm/i830_dma.c
#   2005/03/10 21:44:27+11:00 airlied@starflyer.(none) +54 -64
#   drm: cleanup i810/i830 drivers
#   
#   Cleanup patch for i810/i830 
#   
#   From: Adrian Bunk <bunk@stusta.de>
#   Signed-off-by: Dave Airlie <airlied@linux.ie>
# 
# drivers/char/drm/i810_drv.h
#   2005/03/10 21:44:27+11:00 airlied@starflyer.(none) +1 -45
#   drm: cleanup i810/i830 drivers
#   
#   Cleanup patch for i810/i830 
#   
#   From: Adrian Bunk <bunk@stusta.de>
#   Signed-off-by: Dave Airlie <airlied@linux.ie>
# 
# drivers/char/drm/i810_drv.c
#   2005/03/10 21:44:27+11:00 airlied@starflyer.(none) +1 -0
#   drm: cleanup i810/i830 drivers
#   
#   Cleanup patch for i810/i830 
#   
#   From: Adrian Bunk <bunk@stusta.de>
#   Signed-off-by: Dave Airlie <airlied@linux.ie>
# 
# drivers/char/drm/i810_dma.c
#   2005/03/10 21:44:27+11:00 airlied@starflyer.(none) +53 -47
#   drm: cleanup i810/i830 drivers
#   
#   Cleanup patch for i810/i830 
#   
#   From: Adrian Bunk <bunk@stusta.de>
#   Signed-off-by: Dave Airlie <airlied@linux.ie>
# 
# ChangeSet
#   2005/03/10 21:20:36+11:00 airlied@starflyer.(none) 
#   drm: cleanup patch 
#   
#   This makes a lot of functions static and cleans up a few
#   other minor things.
#   
#   From: Adrian Bunk <bunk@stusta.de>
#   Signed-off-by: Dave Airlie <airlied@linux.ie>
# 
# drivers/char/drm/sis_mm.c
#   2005/03/10 21:20:28+11:00 airlied@starflyer.(none) +21 -20
#   drm: cleanup patch 
#   
#   This makes a lot of functions static and cleans up a few
#   other minor things.
#   
#   From: Adrian Bunk <bunk@stusta.de>
#   Signed-off-by: Dave Airlie <airlied@linux.ie>
# 
# drivers/char/drm/sis_ds.h
#   2005/03/10 21:20:28+11:00 airlied@starflyer.(none) +0 -19
#   drm: cleanup patch 
#   
#   This makes a lot of functions static and cleans up a few
#   other minor things.
#   
#   From: Adrian Bunk <bunk@stusta.de>
#   Signed-off-by: Dave Airlie <airlied@linux.ie>
# 
# drivers/char/drm/sis_ds.c
#   2005/03/10 21:20:28+11:00 airlied@starflyer.(none) +0 -84
#   drm: cleanup patch 
#   
#   This makes a lot of functions static and cleans up a few
#   other minor things.
#   
#   From: Adrian Bunk <bunk@stusta.de>
#   Signed-off-by: Dave Airlie <airlied@linux.ie>
# 
# drivers/char/drm/sis_drv.h
#   2005/03/10 21:20:28+11:00 airlied@starflyer.(none) +0 -7
#   drm: cleanup patch 
#   
#   This makes a lot of functions static and cleans up a few
#   other minor things.
#   
#   From: Adrian Bunk <bunk@stusta.de>
#   Signed-off-by: Dave Airlie <airlied@linux.ie>
# 
# drivers/char/drm/radeon_state.c
#   2005/03/10 21:20:28+11:00 airlied@starflyer.(none) +47 -47
#   drm: cleanup patch 
#   
#   This makes a lot of functions static and cleans up a few
#   other minor things.
#   
#   From: Adrian Bunk <bunk@stusta.de>
#   Signed-off-by: Dave Airlie <airlied@linux.ie>
# 
# drivers/char/drm/radeon_irq.c
#   2005/03/10 21:20:28+11:00 airlied@starflyer.(none) +2 -8
#   drm: cleanup patch 
#   
#   This makes a lot of functions static and cleans up a few
#   other minor things.
#   
#   From: Adrian Bunk <bunk@stusta.de>
#   Signed-off-by: Dave Airlie <airlied@linux.ie>
# 
# drivers/char/drm/radeon_drv.h
#   2005/03/10 21:20:28+11:00 airlied@starflyer.(none) +0 -25
#   drm: cleanup patch 
#   
#   This makes a lot of functions static and cleans up a few
#   other minor things.
#   
#   From: Adrian Bunk <bunk@stusta.de>
#   Signed-off-by: Dave Airlie <airlied@linux.ie>
# 
# drivers/char/drm/radeon_cp.c
#   2005/03/10 21:20:28+11:00 airlied@starflyer.(none) +3 -2
#   drm: cleanup patch 
#   
#   This makes a lot of functions static and cleans up a few
#   other minor things.
#   
#   From: Adrian Bunk <bunk@stusta.de>
#   Signed-off-by: Dave Airlie <airlied@linux.ie>
# 
# drivers/char/drm/r128_state.c
#   2005/03/10 21:20:28+11:00 airlied@starflyer.(none) +31 -31
#   drm: cleanup patch 
#   
#   This makes a lot of functions static and cleans up a few
#   other minor things.
#   
#   From: Adrian Bunk <bunk@stusta.de>
#   Signed-off-by: Dave Airlie <airlied@linux.ie>
# 
# drivers/char/drm/r128_drv.h
#   2005/03/10 21:20:28+11:00 airlied@starflyer.(none) +0 -16
#   drm: cleanup patch 
#   
#   This makes a lot of functions static and cleans up a few
#   other minor things.
#   
#   From: Adrian Bunk <bunk@stusta.de>
#   Signed-off-by: Dave Airlie <airlied@linux.ie>
# 
# drivers/char/drm/r128_cce.c
#   2005/03/10 21:20:28+11:00 airlied@starflyer.(none) +2 -2
#   drm: cleanup patch 
#   
#   This makes a lot of functions static and cleans up a few
#   other minor things.
#   
#   From: Adrian Bunk <bunk@stusta.de>
#   Signed-off-by: Dave Airlie <airlied@linux.ie>
# 
# drivers/char/drm/mga_state.c
#   2005/03/10 21:20:28+11:00 airlied@starflyer.(none) +22 -22
#   drm: cleanup patch 
#   
#   This makes a lot of functions static and cleans up a few
#   other minor things.
#   
#   From: Adrian Bunk <bunk@stusta.de>
#   Signed-off-by: Dave Airlie <airlied@linux.ie>
# 
# drivers/char/drm/mga_drv.h
#   2005/03/10 21:20:28+11:00 airlied@starflyer.(none) +0 -13
#   drm: cleanup patch 
#   
#   This makes a lot of functions static and cleans up a few
#   other minor things.
#   
#   From: Adrian Bunk <bunk@stusta.de>
#   Signed-off-by: Dave Airlie <airlied@linux.ie>
# 
# drivers/char/drm/mga_dma.c
#   2005/03/10 21:20:28+11:00 airlied@starflyer.(none) +3 -58
#   drm: cleanup patch 
#   
#   This makes a lot of functions static and cleans up a few
#   other minor things.
#   
#   From: Adrian Bunk <bunk@stusta.de>
#   Signed-off-by: Dave Airlie <airlied@linux.ie>
# 
# ChangeSet
#   2005/03/10 20:47:24+11:00 airlied@starflyer.(none) 
#   drm: fix radeon pci id
#   
#   fd.o bug #2576: Add support for ATI RN50/ES1000. (ATI Technologies Inc.)
#   
#   From: Michel Daenzer <michel@daenzer.net>
#   Signed-off-by: Dave Airlie <airlied@linux.ie>
# 
# drivers/char/drm/drm_pciids.h
#   2005/03/10 20:47:16+11:00 airlied@starflyer.(none) +1 -1
#   drm: fix radeon pci id
#   
#   fd.o bug #2576: Add support for ATI RN50/ES1000. (ATI Technologies Inc.)
#   
#   From: Michel Daenzer <michel@daenzer.net>
#   Signed-off-by: Dave Airlie <airlied@linux.ie>
# 
# ChangeSet
#   2005/03/10 20:19:51+11:00 airlied@starflyer.(none) 
#   drm: split out structure into heads
#   
#   This patch splits out the main drm structures for future multi-head support.
#   It just sets up the structures and the stub functions for putting/getting heads
#   
#   From: Jon Smirl <jonsmirl@gmail.com>
#   Signed-off-by: Dave Airlie <airlied@linux.ie>
# 
# drivers/char/drm/tdfx_drv.c
#   2005/03/10 20:19:43+11:00 airlied@starflyer.(none) +1 -1
#   drm: split out structure into heads
#   
#   This patch splits out the main drm structures for future multi-head support.
#   It just sets up the structures and the stub functions for putting/getting heads
#   
#   From: Jon Smirl <jonsmirl@gmail.com>
#   Signed-off-by: Dave Airlie <airlied@linux.ie>
# 
# drivers/char/drm/sis_drv.c
#   2005/03/10 20:19:43+11:00 airlied@starflyer.(none) +1 -1
#   drm: split out structure into heads
#   
#   This patch splits out the main drm structures for future multi-head support.
#   It just sets up the structures and the stub functions for putting/getting heads
#   
#   From: Jon Smirl <jonsmirl@gmail.com>
#   Signed-off-by: Dave Airlie <airlied@linux.ie>
# 
# drivers/char/drm/radeon_drv.c
#   2005/03/10 20:19:43+11:00 airlied@starflyer.(none) +1 -1
#   drm: split out structure into heads
#   
#   This patch splits out the main drm structures for future multi-head support.
#   It just sets up the structures and the stub functions for putting/getting heads
#   
#   From: Jon Smirl <jonsmirl@gmail.com>
#   Signed-off-by: Dave Airlie <airlied@linux.ie>
# 
# drivers/char/drm/r128_drv.c
#   2005/03/10 20:19:42+11:00 airlied@starflyer.(none) +1 -1
#   drm: split out structure into heads
#   
#   This patch splits out the main drm structures for future multi-head support.
#   It just sets up the structures and the stub functions for putting/getting heads
#   
#   From: Jon Smirl <jonsmirl@gmail.com>
#   Signed-off-by: Dave Airlie <airlied@linux.ie>
# 
# drivers/char/drm/mga_drv.c
#   2005/03/10 20:19:42+11:00 airlied@starflyer.(none) +1 -1
#   drm: split out structure into heads
#   
#   This patch splits out the main drm structures for future multi-head support.
#   It just sets up the structures and the stub functions for putting/getting heads
#   
#   From: Jon Smirl <jonsmirl@gmail.com>
#   Signed-off-by: Dave Airlie <airlied@linux.ie>
# 
# drivers/char/drm/i915_drv.c
#   2005/03/10 20:19:42+11:00 airlied@starflyer.(none) +1 -1
#   drm: split out structure into heads
#   
#   This patch splits out the main drm structures for future multi-head support.
#   It just sets up the structures and the stub functions for putting/getting heads
#   
#   From: Jon Smirl <jonsmirl@gmail.com>
#   Signed-off-by: Dave Airlie <airlied@linux.ie>
# 
# drivers/char/drm/i830_irq.c
#   2005/03/10 20:19:42+11:00 airlied@starflyer.(none) +2 -2
#   drm: split out structure into heads
#   
#   This patch splits out the main drm structures for future multi-head support.
#   It just sets up the structures and the stub functions for putting/getting heads
#   
#   From: Jon Smirl <jonsmirl@gmail.com>
#   Signed-off-by: Dave Airlie <airlied@linux.ie>
# 
# drivers/char/drm/i830_drv.c
#   2005/03/10 20:19:42+11:00 airlied@starflyer.(none) +1 -1
#   drm: split out structure into heads
#   
#   This patch splits out the main drm structures for future multi-head support.
#   It just sets up the structures and the stub functions for putting/getting heads
#   
#   From: Jon Smirl <jonsmirl@gmail.com>
#   Signed-off-by: Dave Airlie <airlied@linux.ie>
# 
# drivers/char/drm/i830_dma.c
#   2005/03/10 20:19:42+11:00 airlied@starflyer.(none) +12 -12
#   drm: split out structure into heads
#   
#   This patch splits out the main drm structures for future multi-head support.
#   It just sets up the structures and the stub functions for putting/getting heads
#   
#   From: Jon Smirl <jonsmirl@gmail.com>
#   Signed-off-by: Dave Airlie <airlied@linux.ie>
# 
# drivers/char/drm/i810_drv.c
#   2005/03/10 20:19:42+11:00 airlied@starflyer.(none) +1 -1
#   drm: split out structure into heads
#   
#   This patch splits out the main drm structures for future multi-head support.
#   It just sets up the structures and the stub functions for putting/getting heads
#   
#   From: Jon Smirl <jonsmirl@gmail.com>
#   Signed-off-by: Dave Airlie <airlied@linux.ie>
# 
# drivers/char/drm/i810_dma.c
#   2005/03/10 20:19:42+11:00 airlied@starflyer.(none) +15 -15
#   drm: split out structure into heads
#   
#   This patch splits out the main drm structures for future multi-head support.
#   It just sets up the structures and the stub functions for putting/getting heads
#   
#   From: Jon Smirl <jonsmirl@gmail.com>
#   Signed-off-by: Dave Airlie <airlied@linux.ie>
# 
# drivers/char/drm/drm_vm.c
#   2005/03/10 20:19:42+11:00 airlied@starflyer.(none) +8 -8
#   drm: split out structure into heads
#   
#   This patch splits out the main drm structures for future multi-head support.
#   It just sets up the structures and the stub functions for putting/getting heads
#   
#   From: Jon Smirl <jonsmirl@gmail.com>
#   Signed-off-by: Dave Airlie <airlied@linux.ie>
# 
# drivers/char/drm/drm_stub.c
#   2005/03/10 20:19:42+11:00 airlied@starflyer.(none) +113 -53
#   drm: split out structure into heads
#   
#   This patch splits out the main drm structures for future multi-head support.
#   It just sets up the structures and the stub functions for putting/getting heads
#   
#   From: Jon Smirl <jonsmirl@gmail.com>
#   Signed-off-by: Dave Airlie <airlied@linux.ie>
# 
# drivers/char/drm/drm_scatter.c
#   2005/03/10 20:19:42+11:00 airlied@starflyer.(none) +2 -2
#   drm: split out structure into heads
#   
#   This patch splits out the main drm structures for future multi-head support.
#   It just sets up the structures and the stub functions for putting/getting heads
#   
#   From: Jon Smirl <jonsmirl@gmail.com>
#   Signed-off-by: Dave Airlie <airlied@linux.ie>
# 
# drivers/char/drm/drm_proc.c
#   2005/03/10 20:19:42+11:00 airlied@starflyer.(none) +3 -3
#   drm: split out structure into heads
#   
#   This patch splits out the main drm structures for future multi-head support.
#   It just sets up the structures and the stub functions for putting/getting heads
#   
#   From: Jon Smirl <jonsmirl@gmail.com>
#   Signed-off-by: Dave Airlie <airlied@linux.ie>
# 
# drivers/char/drm/drm_os_linux.h
#   2005/03/10 20:19:42+11:00 airlied@starflyer.(none) +1 -1
#   drm: split out structure into heads
#   
#   This patch splits out the main drm structures for future multi-head support.
#   It just sets up the structures and the stub functions for putting/getting heads
#   
#   From: Jon Smirl <jonsmirl@gmail.com>
#   Signed-off-by: Dave Airlie <airlied@linux.ie>
# 
# drivers/char/drm/drm_lock.c
#   2005/03/10 20:19:42+11:00 airlied@starflyer.(none) +2 -2
#   drm: split out structure into heads
#   
#   This patch splits out the main drm structures for future multi-head support.
#   It just sets up the structures and the stub functions for putting/getting heads
#   
#   From: Jon Smirl <jonsmirl@gmail.com>
#   Signed-off-by: Dave Airlie <airlied@linux.ie>
# 
# drivers/char/drm/drm_irq.c
#   2005/03/10 20:19:42+11:00 airlied@starflyer.(none) +3 -3
#   drm: split out structure into heads
#   
#   This patch splits out the main drm structures for future multi-head support.
#   It just sets up the structures and the stub functions for putting/getting heads
#   
#   From: Jon Smirl <jonsmirl@gmail.com>
#   Signed-off-by: Dave Airlie <airlied@linux.ie>
# 
# drivers/char/drm/drm_ioctl.c
#   2005/03/10 20:19:42+11:00 airlied@starflyer.(none) +5 -5
#   drm: split out structure into heads
#   
#   This patch splits out the main drm structures for future multi-head support.
#   It just sets up the structures and the stub functions for putting/getting heads
#   
#   From: Jon Smirl <jonsmirl@gmail.com>
#   Signed-off-by: Dave Airlie <airlied@linux.ie>
# 
# drivers/char/drm/drm_fops.c
#   2005/03/10 20:19:42+11:00 airlied@starflyer.(none) +11 -9
#   drm: split out structure into heads
#   
#   This patch splits out the main drm structures for future multi-head support.
#   It just sets up the structures and the stub functions for putting/getting heads
#   
#   From: Jon Smirl <jonsmirl@gmail.com>
#   Signed-off-by: Dave Airlie <airlied@linux.ie>
# 
# drivers/char/drm/drm_drv.c
#   2005/03/10 20:19:42+11:00 airlied@starflyer.(none) +18 -30
#   drm: split out structure into heads
#   
#   This patch splits out the main drm structures for future multi-head support.
#   It just sets up the structures and the stub functions for putting/getting heads
#   
#   From: Jon Smirl <jonsmirl@gmail.com>
#   Signed-off-by: Dave Airlie <airlied@linux.ie>
# 
# drivers/char/drm/drm_context.c
#   2005/03/10 20:19:42+11:00 airlied@starflyer.(none) +6 -6
#   drm: split out structure into heads
#   
#   This patch splits out the main drm structures for future multi-head support.
#   It just sets up the structures and the stub functions for putting/getting heads
#   
#   From: Jon Smirl <jonsmirl@gmail.com>
#   Signed-off-by: Dave Airlie <airlied@linux.ie>
# 
# drivers/char/drm/drm_bufs.c
#   2005/03/10 20:19:42+11:00 airlied@starflyer.(none) +10 -10
#   drm: split out structure into heads
#   
#   This patch splits out the main drm structures for future multi-head support.
#   It just sets up the structures and the stub functions for putting/getting heads
#   
#   From: Jon Smirl <jonsmirl@gmail.com>
#   Signed-off-by: Dave Airlie <airlied@linux.ie>
# 
# drivers/char/drm/drm_auth.c
#   2005/03/10 20:19:42+11:00 airlied@starflyer.(none) +2 -2
#   drm: split out structure into heads
#   
#   This patch splits out the main drm structures for future multi-head support.
#   It just sets up the structures and the stub functions for putting/getting heads
#   
#   From: Jon Smirl <jonsmirl@gmail.com>
#   Signed-off-by: Dave Airlie <airlied@linux.ie>
# 
# drivers/char/drm/drm_agpsupport.c
#   2005/03/10 20:19:42+11:00 airlied@starflyer.(none) +8 -8
#   drm: split out structure into heads
#   
#   This patch splits out the main drm structures for future multi-head support.
#   It just sets up the structures and the stub functions for putting/getting heads
#   
#   From: Jon Smirl <jonsmirl@gmail.com>
#   Signed-off-by: Dave Airlie <airlied@linux.ie>
# 
# drivers/char/drm/drmP.h
#   2005/03/10 20:19:42+11:00 airlied@starflyer.(none) +24 -18
#   drm: split out structure into heads
#   
#   This patch splits out the main drm structures for future multi-head support.
#   It just sets up the structures and the stub functions for putting/getting heads
#   
#   From: Jon Smirl <jonsmirl@gmail.com>
#   Signed-off-by: Dave Airlie <airlied@linux.ie>
# 
# ChangeSet
#   2005/03/10 09:41:28+01:00 perex@suse.cz 
#   [ALSA] Fix ALC260 input
#   
#   HDA Codec driver
#   Fixed the ALC260 input on HP machines.  Added the front mic support.
#   
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/hda/patch_realtek.c
#   2005/03/09 04:13:19+01:00 perex@suse.cz +4 -1
#   [ALSA] Fix ALC260 input
#   
#   D:2005/03/09 11:13:19
#   C:HDA Codec driver
#   F:pci/hda/patch_realtek.c:1.5->1.6 
#   L:Fixed the ALC260 input on HP machines.  Added the front mic support.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2005/03/10 09:40:48+01:00 perex@suse.cz 
#   [ALSA] Fix pops and clicks at beginning/end of playback
#   
#   EMU10K1/EMU10K2 driver
#   The patch fixes pops and clicks at the beginning and the end of playback
#   on emu10k1 due to the cache size mismatch.
#   
#   Signed-off-by: Jindrich Makovicka <makovick@kmlinux.fjfi.cvut.cz>
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/emu10k1/emupcm.c
#   2005/03/09 04:12:10+01:00 perex@suse.cz +41 -22
#   [ALSA] Fix pops and clicks at beginning/end of playback
#   
#   D:2005/03/09 11:12:10
#   C:EMU10K1/EMU10K2 driver
#   F:pci/emu10k1/emupcm.c:1.41->1.42 
#   L:The patch fixes pops and clicks at the beginning and the end of playback
#   L:on emu10k1 due to the cache size mismatch.
#   Signed-off-by: Jindrich Makovicka <makovick@kmlinux.fjfi.cvut.cz>
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2005/03/10 09:40:07+01:00 perex@suse.cz 
#   [ALSA] fix forgotten release of semaphore in error path
#   
#   ALSA<-OSS emulation
#   In snd_mixer_oss_get_volume1_vol and snd_mixer_oss_put_volume1_vol,
#   card->controls_rwsem wouldn't be released if the boolean type
#   check fails.
#   
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# sound/core/oss/mixer_oss.c
#   2005/03/09 02:01:23+01:00 perex@suse.cz +2 -2
#   [ALSA] fix forgotten release of semaphore in error path
#   
#   D:2005/03/09 09:01:23
#   C:ALSA<-OSS emulation
#   F:core/oss/mixer_oss.c:1.38->1.39 
#   L:In snd_mixer_oss_get_volume1_vol and snd_mixer_oss_put_volume1_vol,
#   L:card->controls_rwsem wouldn't be released if the boolean type
#   L:check fails.
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# ChangeSet
#   2005/03/10 09:39:23+01:00 perex@suse.cz 
#   [ALSA] remove duplicate field initialization
#   
#   au88x0 driver
#   Remove duplicate (and inconsistent) initialization of the iface field.
#   
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# sound/pci/au88x0/au88x0_pcm.c
#   2005/03/09 01:54:56+01:00 perex@suse.cz +0 -1
#   [ALSA] remove duplicate field initialization
#   
#   D:2005/03/09 08:54:56
#   C:au88x0 driver
#   F:pci/au88x0/au88x0_pcm.c:1.7->1.8 
#   L:Remove duplicate (and inconsistent) initialization of the iface field.
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# ChangeSet
#   2005/03/10 09:38:43+01:00 perex@suse.cz 
#   [ALSA] replace wrong spin_trylock_irqsave with spin_lock_irqsave
#   
#   MPU401 UART
#   The last patch accidentally left a 'try' in where none was intended.
#   
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# sound/drivers/mpu401/mpu401_uart.c
#   2005/03/09 01:50:54+01:00 perex@suse.cz +1 -1
#   [ALSA] replace wrong spin_trylock_irqsave with spin_lock_irqsave
#   
#   D:2005/03/09 08:50:54
#   C:MPU401 UART
#   F:drivers/mpu401/mpu401_uart.c:1.33->1.34 
#   L:The last patch accidentally left a 'try' in where none was intended.
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# ChangeSet
#   2005/03/10 09:38:03+01:00 perex@suse.cz 
#   [ALSA] Add PCI ids for ICH6/7
#   
#   Intel8x0-modem driver
#   Added the PCI IDs for ICH6 and ICH7.
#   
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/intel8x0m.c
#   2005/03/08 09:35:32+01:00 perex@suse.cz +12 -0
#   [ALSA] Add PCI ids for ICH6/7
#   
#   D:2005/03/08 16:35:32
#   C:Intel8x0-modem driver
#   F:pci/intel8x0m.c:1.29->1.30 
#   L:Added the PCI IDs for ICH6 and ICH7.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2005/03/10 09:37:17+01:00 perex@suse.cz 
#   [ALSA] Add AD1986 support
#   
#   AC97 Codec
#   Added the support of AD1986.  Using the same patch as AD1985.
#   
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/ac97/ac97_codec.c
#   2005/03/08 09:23:38+01:00 perex@suse.cz +1 -0
#   [ALSA] Add AD1986 support
#   
#   D:2005/03/08 16:23:38
#   C:AC97 Codec
#   F:pci/ac97/ac97_codec.c:1.175->1.176 
#   L:Added the support of AD1986.  Using the same patch as AD1985.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2005/03/10 09:36:28+01:00 perex@suse.cz 
#   [ALSA] Disable DRA for ALI5455
#   
#   Intel8x0 driver
#   Disable DRA for ALI5455.  Apparently the device doesn't support it.
#   
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/intel8x0.c
#   2005/03/08 09:22:35+01:00 perex@suse.cz +2 -1
#   [ALSA] Disable DRA for ALI5455
#   
#   D:2005/03/08 16:22:35
#   C:Intel8x0 driver
#   F:pci/intel8x0.c:1.196->1.197 
#   L:Disable DRA for ALI5455.  Apparently the device doesn't support it.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2005/03/10 09:35:43+01:00 perex@suse.cz 
#   [ALSA] Restore the default value after rate detection
#   
#   AC97 Codec
#   Restore the default value of rate registers after detection of available
#   rates.  This might fix the problem of playback noises on some mobo drivers.
#   
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/ac97/ac97_codec.c
#   2005/03/08 09:19:13+01:00 perex@suse.cz +6 -0
#   [ALSA] Restore the default value after rate detection
#   
#   D:2005/03/08 16:19:13
#   C:AC97 Codec
#   F:pci/ac97/ac97_codec.c:1.174->1.175 
#   L:Restore the default value of rate registers after detection of available
#   L:rates.  This might fix the problem of playback noises on some mobo drivers.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2005/03/10 09:35:03+01:00 perex@suse.cz 
#   [ALSA] replace spdif frequency control with iec958 control
#   
#   au88x0 driver
#   The appended patch replaces the manual spdif frequency control in the
#   mixer with code that use the standard iec958 interface. The patch is
#   nearly the same as the one Raymond submitted, except it gets rid of the
#   identical *_default_* versions of the functions, and has a tiny bit of
#   cleanup.
#   I have only tested it a little bit because I don't currently
#   have the hardware to actually test it properly. However, it looks
#   harmless to me.
#   
#   Patch-by: Raymond
#   
#   Signed-off-by: Jeff Muizelaar <muizelaar@rogers.com>
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/au88x0/au88x0_pcm.c
#   2005/03/08 09:02:28+01:00 perex@suse.cz +62 -45
#   [ALSA] replace spdif frequency control with iec958 control
#   
#   D:2005/03/08 16:02:28
#   C:au88x0 driver
#   F:pci/au88x0/au88x0_pcm.c:1.6->1.7 
#   L:The appended patch replaces the manual spdif frequency control in the
#   L:mixer with code that use the standard iec958 interface. The patch is
#   L:nearly the same as the one Raymond submitted, except it gets rid of the
#   L:identical *_default_* versions of the functions, and has a tiny bit of
#   L:cleanup.
#   L:I have only tested it a little bit because I don't currently
#   L:have the hardware to actually test it properly. However, it looks
#   L:harmless to me.
#   L:
#   L:Patch-by: Raymond
#   Signed-off-by: Jeff Muizelaar <muizelaar@rogers.com>
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2005/03/10 09:34:20+01:00 perex@suse.cz 
#   [ALSA] Fix sample rates of Revo 7.1
#   
#   ICE1712 driver,ICE1724 driver
#   Fixed the available sample rates of Revo 7.1 board.
#   AK codecs don't support the rate below 32k Hz.
#   
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/ice1712/revo.c
#   2005/03/08 08:42:41+01:00 perex@suse.cz +13 -0
#   [ALSA] Fix sample rates of Revo 7.1
#   
#   D:2005/03/08 15:42:41
#   C:ICE1712 driver,ICE1724 driver
#   F:pci/ice1712/ice1712.h:1.29->1.30 
#   F:pci/ice1712/ice1724.c:1.51->1.52 
#   F:pci/ice1712/revo.c:1.9->1.10 
#   L:Fixed the available sample rates of Revo 7.1 board.
#   L:AK codecs don't support the rate below 32k Hz.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/ice1712/ice1724.c
#   2005/03/08 08:42:41+01:00 perex@suse.cz +7 -0
#   [ALSA] Fix sample rates of Revo 7.1
#   
#   D:2005/03/08 15:42:41
#   C:ICE1712 driver,ICE1724 driver
#   F:pci/ice1712/ice1712.h:1.29->1.30 
#   F:pci/ice1712/ice1724.c:1.51->1.52 
#   F:pci/ice1712/revo.c:1.9->1.10 
#   L:Fixed the available sample rates of Revo 7.1 board.
#   L:AK codecs don't support the rate below 32k Hz.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/ice1712/ice1712.h
#   2005/03/08 08:42:41+01:00 perex@suse.cz +1 -0
#   [ALSA] Fix sample rates of Revo 7.1
#   
#   D:2005/03/08 15:42:41
#   C:ICE1712 driver,ICE1724 driver
#   F:pci/ice1712/ice1712.h:1.29->1.30 
#   F:pci/ice1712/ice1724.c:1.51->1.52 
#   F:pci/ice1712/revo.c:1.9->1.10 
#   L:Fixed the available sample rates of Revo 7.1 board.
#   L:AK codecs don't support the rate below 32k Hz.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2005/03/10 09:33:35+01:00 perex@suse.cz 
#   [ALSA] Fix auto-probing of widget tree
#   
#   HDA generic driver
#   Fixed auto-probing of the widget tree, ignoring the widgets with
#   the digital attributes.
#   
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/hda/hda_generic.c
#   2005/03/08 08:41:35+01:00 perex@suse.cz +11 -0
#   [ALSA] Fix auto-probing of widget tree
#   
#   D:2005/03/08 15:41:35
#   C:HDA generic driver
#   F:pci/hda/hda_generic.c:1.1->1.2 
#   L:Fixed auto-probing of the widget tree, ignoring the widgets with
#   L:the digital attributes.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2005/03/10 09:32:53+01:00 perex@suse.cz 
#   [ALSA] Fix stereo mutes on Surround volume control
#   
#   AC97 Codec
#   Fix stereo mutes on Surround volume control.
#   
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/ac97/ac97_codec.c
#   2005/03/08 08:39:46+01:00 perex@suse.cz +8 -5
#   [ALSA] Fix stereo mutes on Surround volume control
#   
#   D:2005/03/08 15:39:46
#   C:AC97 Codec
#   F:pci/ac97/ac97_codec.c:1.173->1.174 
#   L:Fix stereo mutes on Surround volume control.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2005/03/10 09:32:09+01:00 perex@suse.cz 
#   [ALSA] Fix ALC260 support
#   
#   HDA Codec driver
#   Fix ALC260 support on HP machines.
#   
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/hda/patch_realtek.c
#   2005/03/08 08:30:35+01:00 perex@suse.cz +16 -4
#   [ALSA] Fix ALC260 support
#   
#   D:2005/03/08 15:30:35
#   C:HDA Codec driver
#   F:pci/hda/patch_realtek.c:1.4->1.5 
#   L:Fix ALC260 support on HP machines.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2005/03/10 09:31:26+01:00 perex@suse.cz 
#   [ALSA] Use DXS volumes as PCM
#   
#   VIA82xx driver
#   Use DXS volumes as PCM control in cases with no volume control on codec
#   (e.g. C-Media).  'DXS Playback Volume' controls are removed.
#   
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/via82xx.c
#   2005/03/08 08:28:50+01:00 perex@suse.cz +36 -23
#   [ALSA] Use DXS volumes as PCM
#   
#   D:2005/03/08 15:28:50
#   C:VIA82xx driver
#   F:pci/via82xx.c:1.136->1.137 
#   L:Use DXS volumes as PCM control in cases with no volume control on codec
#   L:(e.g. C-Media).  'DXS Playback Volume' controls are removed.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2005/03/10 09:30:39+01:00 perex@suse.cz 
#   [ALSA] GUS - Remove unused gus_lfo.c file
#   
#   GUS Library
#   
#   
#   Signed-off-by: Adrian Bunk <bunk@stusta.de>
#   Signed-off-by: Jaroslav Kysela <perex@suse.cz>
# 
# BitKeeper/deleted/.del-gus_lfo.c~fb23b2506a01fd6a
#   2005/03/10 09:30:17+01:00 perex@suse.cz +0 -0
#   Delete: sound/isa/gus/gus_lfo.c
# 
# ChangeSet
#   2005/03/10 09:29:52+01:00 perex@suse.cz 
#   [ALSA] fix locking for rawmidi trigger callbacks
#   
#   Generic drivers,MPU401 UART,SB8 driver,Wavefront drivers,CS4281 driver
#   ENS1370/1+ driver,CS46xx driver,EMU10K1/EMU10K2 driver,RME HDSP driver
#   Use spin_lock_irqsave() instead of spin_lock() in places where we
#   could be interrupted by another hardware interrupt that could call
#   the rawmidi trigger callback that could try to take the same lock.
#   
#   Additionally, remove locking code that is no longer needed now that
#   the trigger callback is no longer called recursively from the rawmidi
#   'event' handler.
#   
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# sound/pci/rme9652/hdsp.c
#   2005/03/07 02:42:51+01:00 perex@suse.cz +4 -3
#   [ALSA] fix locking for rawmidi trigger callbacks
#   
#   D:2005/03/07 09:42:48
#   C:Generic drivers,MPU401 UART,SB8 driver,Wavefront drivers,CS4281 driver
#   C:ENS1370/1+ driver,CS46xx driver,EMU10K1/EMU10K2 driver,RME HDSP driver
#   F:drivers/mtpav.c:1.29->1.30 
#   F:drivers/serial-u16550.c:1.32->1.33 
#   F:drivers/mpu401/mpu401_uart.c:1.32->1.33 
#   F:include/mpu401.h:1.13->1.14 
#   F:isa/sb/sb8_midi.c:1.11->1.12 
#   F:isa/wavefront/wavefront_midi.c:1.8->1.9 
#   F:pci/cs4281.c:1.70->1.71 
#   F:pci/ens1370.c:1.74->1.75 
#   F:pci/cs46xx/cs46xx_lib.c:1.94->1.95 
#   F:pci/emu10k1/emu10k1x.c:1.5->1.6 
#   F:pci/emu10k1/emumpu401.c:1.12->1.13 
#   F:pci/rme9652/hdsp.c:1.83->1.84 
#   L:Use spin_lock_irqsave() instead of spin_lock() in places where we
#   L:could be interrupted by another hardware interrupt that could call
#   L:the rawmidi trigger callback that could try to take the same lock.
#   L:
#   L:Additionally, remove locking code that is no longer needed now that
#   L:the trigger callback is no longer called recursively from the rawmidi
#   L:'event' handler.
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# sound/pci/ens1370.c
#   2005/03/07 02:42:50+01:00 perex@suse.cz +23 -18
#   [ALSA] fix locking for rawmidi trigger callbacks
#   
#   D:2005/03/07 09:42:48
#   C:Generic drivers,MPU401 UART,SB8 driver,Wavefront drivers,CS4281 driver
#   C:ENS1370/1+ driver,CS46xx driver,EMU10K1/EMU10K2 driver,RME HDSP driver
#   F:drivers/mtpav.c:1.29->1.30 
#   F:drivers/serial-u16550.c:1.32->1.33 
#   F:drivers/mpu401/mpu401_uart.c:1.32->1.33 
#   F:include/mpu401.h:1.13->1.14 
#   F:isa/sb/sb8_midi.c:1.11->1.12 
#   F:isa/wavefront/wavefront_midi.c:1.8->1.9 
#   F:pci/cs4281.c:1.70->1.71 
#   F:pci/ens1370.c:1.74->1.75 
#   F:pci/cs46xx/cs46xx_lib.c:1.94->1.95 
#   F:pci/emu10k1/emu10k1x.c:1.5->1.6 
#   F:pci/emu10k1/emumpu401.c:1.12->1.13 
#   F:pci/rme9652/hdsp.c:1.83->1.84 
#   L:Use spin_lock_irqsave() instead of spin_lock() in places where we
#   L:could be interrupted by another hardware interrupt that could call
#   L:the rawmidi trigger callback that could try to take the same lock.
#   L:
#   L:Additionally, remove locking code that is no longer needed now that
#   L:the trigger callback is no longer called recursively from the rawmidi
#   L:'event' handler.
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# sound/pci/emu10k1/emumpu401.c
#   2005/03/07 02:42:51+01:00 perex@suse.cz +3 -4
#   [ALSA] fix locking for rawmidi trigger callbacks
#   
#   D:2005/03/07 09:42:48
#   C:Generic drivers,MPU401 UART,SB8 driver,Wavefront drivers,CS4281 driver
#   C:ENS1370/1+ driver,CS46xx driver,EMU10K1/EMU10K2 driver,RME HDSP driver
#   F:drivers/mtpav.c:1.29->1.30 
#   F:drivers/serial-u16550.c:1.32->1.33 
#   F:drivers/mpu401/mpu401_uart.c:1.32->1.33 
#   F:include/mpu401.h:1.13->1.14 
#   F:isa/sb/sb8_midi.c:1.11->1.12 
#   F:isa/wavefront/wavefront_midi.c:1.8->1.9 
#   F:pci/cs4281.c:1.70->1.71 
#   F:pci/ens1370.c:1.74->1.75 
#   F:pci/cs46xx/cs46xx_lib.c:1.94->1.95 
#   F:pci/emu10k1/emu10k1x.c:1.5->1.6 
#   F:pci/emu10k1/emumpu401.c:1.12->1.13 
#   F:pci/rme9652/hdsp.c:1.83->1.84 
#   L:Use spin_lock_irqsave() instead of spin_lock() in places where we
#   L:could be interrupted by another hardware interrupt that could call
#   L:the rawmidi trigger callback that could try to take the same lock.
#   L:
#   L:Additionally, remove locking code that is no longer needed now that
#   L:the trigger callback is no longer called recursively from the rawmidi
#   L:'event' handler.
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# sound/pci/emu10k1/emu10k1x.c
#   2005/03/07 02:42:51+01:00 perex@suse.cz +3 -4
#   [ALSA] fix locking for rawmidi trigger callbacks
#   
#   D:2005/03/07 09:42:48
#   C:Generic drivers,MPU401 UART,SB8 driver,Wavefront drivers,CS4281 driver
#   C:ENS1370/1+ driver,CS46xx driver,EMU10K1/EMU10K2 driver,RME HDSP driver
#   F:drivers/mtpav.c:1.29->1.30 
#   F:drivers/serial-u16550.c:1.32->1.33 
#   F:drivers/mpu401/mpu401_uart.c:1.32->1.33 
#   F:include/mpu401.h:1.13->1.14 
#   F:isa/sb/sb8_midi.c:1.11->1.12 
#   F:isa/wavefront/wavefront_midi.c:1.8->1.9 
#   F:pci/cs4281.c:1.70->1.71 
#   F:pci/ens1370.c:1.74->1.75 
#   F:pci/cs46xx/cs46xx_lib.c:1.94->1.95 
#   F:pci/emu10k1/emu10k1x.c:1.5->1.6 
#   F:pci/emu10k1/emumpu401.c:1.12->1.13 
#   F:pci/rme9652/hdsp.c:1.83->1.84 
#   L:Use spin_lock_irqsave() instead of spin_lock() in places where we
#   L:could be interrupted by another hardware interrupt that could call
#   L:the rawmidi trigger callback that could try to take the same lock.
#   L:
#   L:Additionally, remove locking code that is no longer needed now that
#   L:the trigger callback is no longer called recursively from the rawmidi
#   L:'event' handler.
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# sound/pci/cs46xx/cs46xx_lib.c
#   2005/03/07 02:42:51+01:00 perex@suse.cz +13 -10
#   [ALSA] fix locking for rawmidi trigger callbacks
#   
#   D:2005/03/07 09:42:48
#   C:Generic drivers,MPU401 UART,SB8 driver,Wavefront drivers,CS4281 driver
#   C:ENS1370/1+ driver,CS46xx driver,EMU10K1/EMU10K2 driver,RME HDSP driver
#   F:drivers/mtpav.c:1.29->1.30 
#   F:drivers/serial-u16550.c:1.32->1.33 
#   F:drivers/mpu401/mpu401_uart.c:1.32->1.33 
#   F:include/mpu401.h:1.13->1.14 
#   F:isa/sb/sb8_midi.c:1.11->1.12 
#   F:isa/wavefront/wavefront_midi.c:1.8->1.9 
#   F:pci/cs4281.c:1.70->1.71 
#   F:pci/ens1370.c:1.74->1.75 
#   F:pci/cs46xx/cs46xx_lib.c:1.94->1.95 
#   F:pci/emu10k1/emu10k1x.c:1.5->1.6 
#   F:pci/emu10k1/emumpu401.c:1.12->1.13 
#   F:pci/rme9652/hdsp.c:1.83->1.84 
#   L:Use spin_lock_irqsave() instead of spin_lock() in places where we
#   L:could be interrupted by another hardware interrupt that could call
#   L:the rawmidi trigger callback that could try to take the same lock.
#   L:
#   L:Additionally, remove locking code that is no longer needed now that
#   L:the trigger callback is no longer called recursively from the rawmidi
#   L:'event' handler.
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# sound/pci/cs4281.c
#   2005/03/07 02:42:50+01:00 perex@suse.cz +11 -11
#   [ALSA] fix locking for rawmidi trigger callbacks
#   
#   D:2005/03/07 09:42:48
#   C:Generic drivers,MPU401 UART,SB8 driver,Wavefront drivers,CS4281 driver
#   C:ENS1370/1+ driver,CS46xx driver,EMU10K1/EMU10K2 driver,RME HDSP driver
#   F:drivers/mtpav.c:1.29->1.30 
#   F:drivers/serial-u16550.c:1.32->1.33 
#   F:drivers/mpu401/mpu401_uart.c:1.32->1.33 
#   F:include/mpu401.h:1.13->1.14 
#   F:isa/sb/sb8_midi.c:1.11->1.12 
#   F:isa/wavefront/wavefront_midi.c:1.8->1.9 
#   F:pci/cs4281.c:1.70->1.71 
#   F:pci/ens1370.c:1.74->1.75 
#   F:pci/cs46xx/cs46xx_lib.c:1.94->1.95 
#   F:pci/emu10k1/emu10k1x.c:1.5->1.6 
#   F:pci/emu10k1/emumpu401.c:1.12->1.13 
#   F:pci/rme9652/hdsp.c:1.83->1.84 
#   L:Use spin_lock_irqsave() instead of spin_lock() in places where we
#   L:could be interrupted by another hardware interrupt that could call
#   L:the rawmidi trigger callback that could try to take the same lock.
#   L:
#   L:Additionally, remove locking code that is no longer needed now that
#   L:the trigger callback is no longer called recursively from the rawmidi
#   L:'event' handler.
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# sound/isa/wavefront/wavefront_midi.c
#   2005/03/07 02:42:50+01:00 perex@suse.cz +2 -6
#   [ALSA] fix locking for rawmidi trigger callbacks
#   
#   D:2005/03/07 09:42:48
#   C:Generic drivers,MPU401 UART,SB8 driver,Wavefront drivers,CS4281 driver
#   C:ENS1370/1+ driver,CS46xx driver,EMU10K1/EMU10K2 driver,RME HDSP driver
#   F:drivers/mtpav.c:1.29->1.30 
#   F:drivers/serial-u16550.c:1.32->1.33 
#   F:drivers/mpu401/mpu401_uart.c:1.32->1.33 
#   F:include/mpu401.h:1.13->1.14 
#   F:isa/sb/sb8_midi.c:1.11->1.12 
#   F:isa/wavefront/wavefront_midi.c:1.8->1.9 
#   F:pci/cs4281.c:1.70->1.71 
#   F:pci/ens1370.c:1.74->1.75 
#   F:pci/cs46xx/cs46xx_lib.c:1.94->1.95 
#   F:pci/emu10k1/emu10k1x.c:1.5->1.6 
#   F:pci/emu10k1/emumpu401.c:1.12->1.13 
#   F:pci/rme9652/hdsp.c:1.83->1.84 
#   L:Use spin_lock_irqsave() instead of spin_lock() in places where we
#   L:could be interrupted by another hardware interrupt that could call
#   L:the rawmidi trigger callback that could try to take the same lock.
#   L:
#   L:Additionally, remove locking code that is no longer needed now that
#   L:the trigger callback is no longer called recursively from the rawmidi
#   L:'event' handler.
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# sound/isa/sb/sb8_midi.c
#   2005/03/07 02:42:49+01:00 perex@suse.cz +2 -6
#   [ALSA] fix locking for rawmidi trigger callbacks
#   
#   D:2005/03/07 09:42:48
#   C:Generic drivers,MPU401 UART,SB8 driver,Wavefront drivers,CS4281 driver
#   C:ENS1370/1+ driver,CS46xx driver,EMU10K1/EMU10K2 driver,RME HDSP driver
#   F:drivers/mtpav.c:1.29->1.30 
#   F:drivers/serial-u16550.c:1.32->1.33 
#   F:drivers/mpu401/mpu401_uart.c:1.32->1.33 
#   F:include/mpu401.h:1.13->1.14 
#   F:isa/sb/sb8_midi.c:1.11->1.12 
#   F:isa/wavefront/wavefront_midi.c:1.8->1.9 
#   F:pci/cs4281.c:1.70->1.71 
#   F:pci/ens1370.c:1.74->1.75 
#   F:pci/cs46xx/cs46xx_lib.c:1.94->1.95 
#   F:pci/emu10k1/emu10k1x.c:1.5->1.6 
#   F:pci/emu10k1/emumpu401.c:1.12->1.13 
#   F:pci/rme9652/hdsp.c:1.83->1.84 
#   L:Use spin_lock_irqsave() instead of spin_lock() in places where we
#   L:could be interrupted by another hardware interrupt that could call
#   L:the rawmidi trigger callback that could try to take the same lock.
#   L:
#   L:Additionally, remove locking code that is no longer needed now that
#   L:the trigger callback is no longer called recursively from the rawmidi
#   L:'event' handler.
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# sound/drivers/serial-u16550.c
#   2005/03/07 02:42:48+01:00 perex@suse.cz +7 -5
#   [ALSA] fix locking for rawmidi trigger callbacks
#   
#   D:2005/03/07 09:42:48
#   C:Generic drivers,MPU401 UART,SB8 driver,Wavefront drivers,CS4281 driver
#   C:ENS1370/1+ driver,CS46xx driver,EMU10K1/EMU10K2 driver,RME HDSP driver
#   F:drivers/mtpav.c:1.29->1.30 
#   F:drivers/serial-u16550.c:1.32->1.33 
#   F:drivers/mpu401/mpu401_uart.c:1.32->1.33 
#   F:include/mpu401.h:1.13->1.14 
#   F:isa/sb/sb8_midi.c:1.11->1.12 
#   F:isa/wavefront/wavefront_midi.c:1.8->1.9 
#   F:pci/cs4281.c:1.70->1.71 
#   F:pci/ens1370.c:1.74->1.75 
#   F:pci/cs46xx/cs46xx_lib.c:1.94->1.95 
#   F:pci/emu10k1/emu10k1x.c:1.5->1.6 
#   F:pci/emu10k1/emumpu401.c:1.12->1.13 
#   F:pci/rme9652/hdsp.c:1.83->1.84 
#   L:Use spin_lock_irqsave() instead of spin_lock() in places where we
#   L:could be interrupted by another hardware interrupt that could call
#   L:the rawmidi trigger callback that could try to take the same lock.
#   L:
#   L:Additionally, remove locking code that is no longer needed now that
#   L:the trigger callback is no longer called recursively from the rawmidi
#   L:'event' handler.
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# sound/drivers/mtpav.c
#   2005/03/07 02:42:48+01:00 perex@suse.cz +6 -6
#   [ALSA] fix locking for rawmidi trigger callbacks
#   
#   D:2005/03/07 09:42:48
#   C:Generic drivers,MPU401 UART,SB8 driver,Wavefront drivers,CS4281 driver
#   C:ENS1370/1+ driver,CS46xx driver,EMU10K1/EMU10K2 driver,RME HDSP driver
#   F:drivers/mtpav.c:1.29->1.30 
#   F:drivers/serial-u16550.c:1.32->1.33 
#   F:drivers/mpu401/mpu401_uart.c:1.32->1.33 
#   F:include/mpu401.h:1.13->1.14 
#   F:isa/sb/sb8_midi.c:1.11->1.12 
#   F:isa/wavefront/wavefront_midi.c:1.8->1.9 
#   F:pci/cs4281.c:1.70->1.71 
#   F:pci/ens1370.c:1.74->1.75 
#   F:pci/cs46xx/cs46xx_lib.c:1.94->1.95 
#   F:pci/emu10k1/emu10k1x.c:1.5->1.6 
#   F:pci/emu10k1/emumpu401.c:1.12->1.13 
#   F:pci/rme9652/hdsp.c:1.83->1.84 
#   L:Use spin_lock_irqsave() instead of spin_lock() in places where we
#   L:could be interrupted by another hardware interrupt that could call
#   L:the rawmidi trigger callback that could try to take the same lock.
#   L:
#   L:Additionally, remove locking code that is no longer needed now that
#   L:the trigger callback is no longer called recursively from the rawmidi
#   L:'event' handler.
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# sound/drivers/mpu401/mpu401_uart.c
#   2005/03/07 02:42:48+01:00 perex@suse.cz +16 -34
#   [ALSA] fix locking for rawmidi trigger callbacks
#   
#   D:2005/03/07 09:42:48
#   C:Generic drivers,MPU401 UART,SB8 driver,Wavefront drivers,CS4281 driver
#   C:ENS1370/1+ driver,CS46xx driver,EMU10K1/EMU10K2 driver,RME HDSP driver
#   F:drivers/mtpav.c:1.29->1.30 
#   F:drivers/serial-u16550.c:1.32->1.33 
#   F:drivers/mpu401/mpu401_uart.c:1.32->1.33 
#   F:include/mpu401.h:1.13->1.14 
#   F:isa/sb/sb8_midi.c:1.11->1.12 
#   F:isa/wavefront/wavefront_midi.c:1.8->1.9 
#   F:pci/cs4281.c:1.70->1.71 
#   F:pci/ens1370.c:1.74->1.75 
#   F:pci/cs46xx/cs46xx_lib.c:1.94->1.95 
#   F:pci/emu10k1/emu10k1x.c:1.5->1.6 
#   F:pci/emu10k1/emumpu401.c:1.12->1.13 
#   F:pci/rme9652/hdsp.c:1.83->1.84 
#   L:Use spin_lock_irqsave() instead of spin_lock() in places where we
#   L:could be interrupted by another hardware interrupt that could call
#   L:the rawmidi trigger callback that could try to take the same lock.
#   L:
#   L:Additionally, remove locking code that is no longer needed now that
#   L:the trigger callback is no longer called recursively from the rawmidi
#   L:'event' handler.
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# include/sound/mpu401.h
#   2005/03/07 02:42:49+01:00 perex@suse.cz +0 -3
#   [ALSA] fix locking for rawmidi trigger callbacks
#   
#   D:2005/03/07 09:42:48
#   C:Generic drivers,MPU401 UART,SB8 driver,Wavefront drivers,CS4281 driver
#   C:ENS1370/1+ driver,CS46xx driver,EMU10K1/EMU10K2 driver,RME HDSP driver
#   F:drivers/mtpav.c:1.29->1.30 
#   F:drivers/serial-u16550.c:1.32->1.33 
#   F:drivers/mpu401/mpu401_uart.c:1.32->1.33 
#   F:include/mpu401.h:1.13->1.14 
#   F:isa/sb/sb8_midi.c:1.11->1.12 
#   F:isa/wavefront/wavefront_midi.c:1.8->1.9 
#   F:pci/cs4281.c:1.70->1.71 
#   F:pci/ens1370.c:1.74->1.75 
#   F:pci/cs46xx/cs46xx_lib.c:1.94->1.95 
#   F:pci/emu10k1/emu10k1x.c:1.5->1.6 
#   F:pci/emu10k1/emumpu401.c:1.12->1.13 
#   F:pci/rme9652/hdsp.c:1.83->1.84 
#   L:Use spin_lock_irqsave() instead of spin_lock() in places where we
#   L:could be interrupted by another hardware interrupt that could call
#   L:the rawmidi trigger callback that could try to take the same lock.
#   L:
#   L:Additionally, remove locking code that is no longer needed now that
#   L:the trigger callback is no longer called recursively from the rawmidi
#   L:'event' handler.
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# ChangeSet
#   2005/03/10 09:29:07+01:00 perex@suse.cz 
#   [ALSA] remove duplicate module alias
#   
#   ALSA Core
#   Remove duplicate MODULE_ALIAS for the snd module.
#   
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# sound/core/sound.c
#   2005/03/07 02:36:40+01:00 perex@suse.cz +0 -1
#   [ALSA] remove duplicate module alias
#   
#   D:2005/03/07 09:36:40
#   C:ALSA Core
#   F:core/sound.c:1.73->1.74 
#   L:Remove duplicate MODULE_ALIAS for the snd module.
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# ChangeSet
#   2005/03/10 09:28:21+01:00 perex@suse.cz 
#   [ALSA] add module aliases for rtctimer and seq-dummy
#   
#   RTC timer driver,ALSA sequencer
#   Add snd-timer-1 and snd-seq-client-63 module aliases for the
#   snd-rtctimer and snd-seq-dummy modules.
#   
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# sound/core/seq/seq_dummy.c
#   2005/03/07 02:35:35+01:00 perex@suse.cz +1 -0
#   [ALSA] add module aliases for rtctimer and seq-dummy
#   
#   D:2005/03/07 09:35:35
#   C:RTC timer driver,ALSA sequencer
#   F:core/rtctimer.c:1.20->1.21 
#   F:core/seq/seq_dummy.c:1.15->1.16 
#   L:Add snd-timer-1 and snd-seq-client-63 module aliases for the
#   L:snd-rtctimer and snd-seq-dummy modules.
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# sound/core/rtctimer.c
#   2005/03/07 02:35:35+01:00 perex@suse.cz +2 -0
#   [ALSA] add module aliases for rtctimer and seq-dummy
#   
#   D:2005/03/07 09:35:35
#   C:RTC timer driver,ALSA sequencer
#   F:core/rtctimer.c:1.20->1.21 
#   F:core/seq/seq_dummy.c:1.15->1.16 
#   L:Add snd-timer-1 and snd-seq-client-63 module aliases for the
#   L:snd-rtctimer and snd-seq-dummy modules.
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# ChangeSet
#   2005/03/10 09:27:40+01:00 perex@suse.cz 
#   [ALSA] document rawmidi interface
#   
#   Documentation
#   Add information about the rawmidi interface to the driver-writing
#   documentation.
#   
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl
#   2005/03/07 02:33:34+01:00 perex@suse.cz +352 -14
#   [ALSA] document rawmidi interface
#   
#   D:2005/03/07 09:33:34
#   C:Documentation
#   F:Documentation/DocBook/writing-an-alsa-driver.tmpl:1.48->1.49 
#   L:Add information about the rawmidi interface to the driver-writing
#   L:documentation.
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# ChangeSet
#   2005/03/10 09:26:58+01:00 perex@suse.cz 
#   [ALSA] use simple_strtoul instead of simple_strtol
#   
#   AC97 Codec
#   Replace simple_strtol with simple_strtoul for compatibility with
#   2.2.x kernels.
#   
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# sound/pci/ac97/ac97_codec.c
#   2005/03/07 02:28:33+01:00 perex@suse.cz +1 -1
#   [ALSA] use simple_strtoul instead of simple_strtol
#   
#   D:2005/03/07 09:28:33
#   C:AC97 Codec
#   F:pci/ac97/ac97_codec.c:1.172->1.173 
#   L:Replace simple_strtol with simple_strtoul for compatibility with
#   L:2.2.x kernels.
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# ChangeSet
#   2005/03/10 09:26:12+01:00 perex@suse.cz 
#   [ALSA] move rawmidi event callback into tasklet
#   
#   RawMidi Midlevel
#   Move the event callback into a tasklet instead of calling it directly
#   from snd_rawmidi_transmit_ack/_receive to prevent recursive calls to
#   the trigger callback.  This means that drivers no longer have to
#   check that they're called inside their own spinlock.
#   
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# sound/core/rawmidi.c
#   2005/03/04 02:53:00+01:00 perex@suse.cz +34 -20
#   [ALSA] move rawmidi event callback into tasklet
#   
#   D:2005/03/04 09:53:00
#   C:RawMidi Midlevel
#   F:core/rawmidi.c:1.59->1.60 
#   F:include/rawmidi.h:1.13->1.14 
#   L:Move the event callback into a tasklet instead of calling it directly
#   L:from snd_rawmidi_transmit_ack/_receive to prevent recursive calls to
#   L:the trigger callback.  This means that drivers no longer have to
#   L:check that they're called inside their own spinlock.
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# include/sound/rawmidi.h
#   2005/03/04 02:53:00+01:00 perex@suse.cz +2 -0
#   [ALSA] move rawmidi event callback into tasklet
#   
#   D:2005/03/04 09:53:00
#   C:RawMidi Midlevel
#   F:core/rawmidi.c:1.59->1.60 
#   F:include/rawmidi.h:1.13->1.14 
#   L:Move the event callback into a tasklet instead of calling it directly
#   L:from snd_rawmidi_transmit_ack/_receive to prevent recursive calls to
#   L:the trigger callback.  This means that drivers no longer have to
#   L:check that they're called inside their own spinlock.
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# ChangeSet
#   2005/03/10 09:25:29+01:00 perex@suse.cz 
#   [ALSA] move common code into snd_rawmidi_runtime_create/_free functions
#   
#   RawMidi Midlevel
#   Move the duplicated memory handling code for the rawmidi runtime struct
#   into the snd_rawmidi_init/_done_buffer functions and rename them to
#   snd_rawmidi_runtime_create/_free.
#   
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# sound/core/rawmidi.c
#   2005/03/04 02:44:43+01:00 perex@suse.cz +29 -50
#   [ALSA] move common code into snd_rawmidi_runtime_create/_free functions
#   
#   D:2005/03/04 09:44:43
#   C:RawMidi Midlevel
#   F:core/rawmidi.c:1.58->1.59 
#   L:Move the duplicated memory handling code for the rawmidi runtime struct
#   L:into the snd_rawmidi_init/_done_buffer functions and rename them to
#   L:snd_rawmidi_runtime_create/_free.
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# ChangeSet
#   2005/03/10 09:24:49+01:00 perex@suse.cz 
#   [ALSA]  Fix bugs with incorrectly wrapped appl_ptr
#   
#   PCM Midlevel
#       This patch is against alsa-driver-1.0.8.
#       It covers:
#           alsa-kernel/core/pcm_lib.c
#       The main changes are in the first listed file.
#   
#       It corresponds to bug description:
#           <https://bugtrack.alsa-project.org/alsa-bug/view.php?id=951>
#   
#       The patch does cosmetic change:
#   
#        -- Better, more universal and smaller wrapping to within
#           0..runtime->boundary-1 in functions snd_pcm_lib_write1() and
#           snd_pcm_lib_read1() in pcm_lib.c
#   
#   Signed-off-by:  Charles Levert <charles_levert@gna.org>
#   Signed-off-by: Jaroslav Kysela <perex@suse.cz>
# 
# sound/core/pcm_lib.c
#   2005/03/03 07:09:25+01:00 perex@suse.cz +6 -10
#   [ALSA]  Fix bugs with incorrectly wrapped appl_ptr
#   
#   D:2005/03/03 14:09:25
#   C:PCM Midlevel
#   F:core/pcm_lib.c:1.61->1.62 
#   L:    This patch is against alsa-driver-1.0.8.
#   L:    It covers:
#   L:        alsa-kernel/core/pcm_lib.c
#   L:    The main changes are in the first listed file.
#   L:
#   L:    It corresponds to bug description:
#   L:        <https://bugtrack.alsa-project.org/alsa-bug/view.php?id=951>
#   L:
#   L:    The patch does cosmetic change:
#   L:
#   L:     -- Better, more universal and smaller wrapping to within
#   L:        0..runtime->boundary-1 in functions snd_pcm_lib_write1() and
#   L:        snd_pcm_lib_read1() in pcm_lib.c
#   Signed-off-by:  Charles Levert <charles_levert@gna.org>
#   Signed-off-by: Jaroslav Kysela <perex@suse.cz>
# 
# ChangeSet
#   2005/03/10 09:24:06+01:00 perex@suse.cz 
#   [ALSA]  Fix rounded-up integer division bug
#   
#   PCM Midlevel
#       This patch is against alsa-driver-1.0.8.
#       It covers:
#           alsa-kernel/core/pcm_lib.c
#   
#       It corresponds to bug description:
#           <https://bugtrack.alsa-project.org/alsa-bug/view.php?id=951>
#   
#       The patch fixes the following problem:
#   
#        -- Properly perform rounded-up integer division in
#           snd_pcm_system_tick_set() in pcm_lib.c.
#   
#           This only had a minor impact.
#   
#   Signed-off-by:  Charles Levert <charles_levert@gna.org>
#   Signed-off-by: Jaroslav Kysela <perex@suse.cz>
# 
# sound/core/pcm_lib.c
#   2005/03/03 07:02:16+01:00 perex@suse.cz +1 -2
#   [ALSA]  Fix rounded-up integer division bug
#   
#   D:2005/03/03 14:02:16
#   C:PCM Midlevel
#   F:core/pcm_lib.c:1.60->1.61 
#   L:    This patch is against alsa-driver-1.0.8.
#   L:    It covers:
#   L:        alsa-kernel/core/pcm_lib.c
#   L:
#   L:    It corresponds to bug description:
#   L:        <https://bugtrack.alsa-project.org/alsa-bug/view.php?id=951>
#   L:
#   L:    The patch fixes the following problem:
#   L:
#   L:     -- Properly perform rounded-up integer division in
#   L:        snd_pcm_system_tick_set() in pcm_lib.c.
#   L:
#   L:        This only had a minor impact.
#   Signed-off-by:  Charles Levert <charles_levert@gna.org>
#   Signed-off-by: Jaroslav Kysela <perex@suse.cz>
# 
# ChangeSet
#   2005/03/10 09:23:19+01:00 perex@suse.cz 
#   [ALSA] fix snd-serial-u16550 docs for setserial
#   
#   Documentation
#   Change the documentation about disabling the standard serial driver
#   to use 'uart none' instead of 'none' as setserial option.
#   
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# Documentation/sound/alsa/serial-u16550.txt
#   2005/03/03 00:58:40+01:00 perex@suse.cz +5 -5
#   [ALSA] fix snd-serial-u16550 docs for setserial
#   
#   D:2005/03/03 07:58:40
#   C:Documentation
#   F:Documentation/serial-u16550.txt:1.3->1.4 
#   L:Change the documentation about disabling the standard serial driver
#   L:to use 'uart none' instead of 'none' as setserial option.
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# ChangeSet
#   2005/03/10 08:03:11+01:00 perex@suse.cz 
#   Merge suse.cz:/home/perex/bk/linux-sound/linux-2.5
#   into suse.cz:/home/perex/bk/linux-sound/linux-sound
# 
# sound/usb/usbmixer.c
#   2005/03/10 08:02:57+01:00 perex@suse.cz +0 -0
#   Auto merged
# 
# net/ipv6/addrconf.c
#   2005/03/09 22:00:50-08:00 davem@sunset.davemloft.net +0 -0
#   Auto merged
# 
# net/ipv4/devinet.c
#   2005/03/09 22:00:50-08:00 davem@sunset.davemloft.net +0 -0
#   Auto merged
# 
# net/core/neighbour.c
#   2005/03/09 22:00:50-08:00 davem@sunset.davemloft.net +0 -0
#   Auto merged
# 
# include/net/addrconf.h
#   2005/03/09 22:00:50-08:00 davem@sunset.davemloft.net +0 -0
#   Auto merged
# 
# include/linux/sysctl.h
#   2005/03/09 22:00:50-08:00 davem@sunset.davemloft.net +0 -0
#   Auto merged
# 
# include/linux/rtnetlink.h
#   2005/03/09 22:00:50-08:00 davem@sunset.davemloft.net +0 -0
#   Auto merged
# 
# ChangeSet
#   2005/03/09 21:22:32-08:00 tgraf@suug.ch 
#   [NEIGH]: Provide number of probes to userspace
#   
#   Provides number of probes done so far to userspace,
#   quite useful for debugging.
#   
#   Signed-off-by: Thomas Graf <tgraf@suug.ch>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/core/neighbour.c
#   2005/03/09 21:22:17-08:00 tgraf@suug.ch +3 -0
#   [NEIGH]: Provide number of probes to userspace
#   
#   Provides number of probes done so far to userspace,
#   quite useful for debugging.
#   
#   Signed-off-by: Thomas Graf <tgraf@suug.ch>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# include/linux/rtnetlink.h
#   2005/03/09 21:22:17-08:00 tgraf@suug.ch +1 -0
#   [NEIGH]: Provide number of probes to userspace
#   
#   Provides number of probes done so far to userspace,
#   quite useful for debugging.
#   
#   Signed-off-by: Thomas Graf <tgraf@suug.ch>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# ChangeSet
#   2005/03/09 21:21:30-08:00 tgraf@suug.ch 
#   [NEIGH]: rtnetlink neighbour cleanups
#   
#   Signed-off-by: Thomas Graf <tgraf@suug.ch>
#   Acked-by: Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/core/neighbour.c
#   2005/03/09 21:21:16-08:00 tgraf@suug.ch +31 -29
#   [NEIGH]: rtnetlink neighbour cleanups
#   
#   Signed-off-by: Thomas Graf <tgraf@suug.ch>
#   Acked-by: Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# ChangeSet
#   2005/03/09 21:19:27-08:00 shemminger@osdl.org 
#   [NET]: Remove dead skb_iter code
#   
#   The code to iterate over skb_frags is defined but not used by any
#   existing kernel code.
#   
#   Signed-off-by: Stephen Hemminger <shemminger@osdl.org>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/core/skbuff.c
#   2005/03/09 21:19:14-08:00 shemminger@osdl.org +0 -67
#   [NET]: Remove dead skb_iter code
#   
#   The code to iterate over skb_frags is defined but not used by any
#   existing kernel code.
#   
#   Signed-off-by: Stephen Hemminger <shemminger@osdl.org>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# include/linux/skbuff.h
#   2005/03/09 21:19:14-08:00 shemminger@osdl.org +0 -16
#   [NET]: Remove dead skb_iter code
#   
#   The code to iterate over skb_frags is defined but not used by any
#   existing kernel code.
#   
#   Signed-off-by: Stephen Hemminger <shemminger@osdl.org>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# ChangeSet
#   2005/03/09 21:14:27-08:00 shemminger@osdl.org 
#   [NET]: Kill dead externs in netdevice.h
#   
#   The following definitions are historical relics.
#   
#   Signed-off-by: Stephen Hemminger <shemminger@osdl.org>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# include/linux/netdevice.h
#   2005/03/09 21:14:13-08:00 shemminger@osdl.org +0 -2
#   [NET]: Kill dead externs in netdevice.h
#   
#   The following definitions are historical relics.
#   
#   Signed-off-by: Stephen Hemminger <shemminger@osdl.org>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# ChangeSet
#   2005/03/09 21:12:23-08:00 herbert@gondor.apana.org.au 
#   [NET]: Fix CHECKSUM_HW wrt. packet trimming.
#   
#   When something, on receive, between a CHECKSUM_HW using
#   driver and the code validating skb->csum trims the head
#   of the packet we have to reset skb->ip_summed back to
#   CHECKSUM_NONE because this kind of change invalidates
#   the skb->csum value calculated by the driver.
#   
#   Various spots handle this properly, but not all.  So
#   abstract these actions into helper routines in order
#   to avoid code duplication.
#   
#   Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/ipv6/ip6_input.c
#   2005/03/09 21:12:11-08:00 herbert@gondor.apana.org.au +6 -14
#   [NET]: Fix CHECKSUM_HW wrt. packet trimming.
#   
#   When something, on receive, between a CHECKSUM_HW using
#   driver and the code validating skb->csum trims the head
#   of the packet we have to reset skb->ip_summed back to
#   CHECKSUM_NONE because this kind of change invalidates
#   the skb->csum value calculated by the driver.
#   
#   Various spots handle this properly, but not all.  So
#   abstract these actions into helper routines in order
#   to avoid code duplication.
#   
#   Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/ipv4/ip_input.c
#   2005/03/09 21:12:11-08:00 herbert@gondor.apana.org.au +3 -4
#   [NET]: Fix CHECKSUM_HW wrt. packet trimming.
#   
#   When something, on receive, between a CHECKSUM_HW using
#   driver and the code validating skb->csum trims the head
#   of the packet we have to reset skb->ip_summed back to
#   CHECKSUM_NONE because this kind of change invalidates
#   the skb->csum value calculated by the driver.
#   
#   Various spots handle this properly, but not all.  So
#   abstract these actions into helper routines in order
#   to avoid code duplication.
#   
#   Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/ipv4/ip_gre.c
#   2005/03/09 21:12:11-08:00 herbert@gondor.apana.org.au +1 -3
#   [NET]: Fix CHECKSUM_HW wrt. packet trimming.
#   
#   When something, on receive, between a CHECKSUM_HW using
#   driver and the code validating skb->csum trims the head
#   of the packet we have to reset skb->ip_summed back to
#   CHECKSUM_NONE because this kind of change invalidates
#   the skb->csum value calculated by the driver.
#   
#   Various spots handle this properly, but not all.  So
#   abstract these actions into helper routines in order
#   to avoid code duplication.
#   
#   Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# include/linux/skbuff.h
#   2005/03/09 21:12:11-08:00 herbert@gondor.apana.org.au +36 -0
#   [NET]: Fix CHECKSUM_HW wrt. packet trimming.
#   
#   When something, on receive, between a CHECKSUM_HW using
#   driver and the code validating skb->csum trims the head
#   of the packet we have to reset skb->ip_summed back to
#   CHECKSUM_NONE because this kind of change invalidates
#   the skb->csum value calculated by the driver.
#   
#   Various spots handle this properly, but not all.  So
#   abstract these actions into helper routines in order
#   to avoid code duplication.
#   
#   Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# drivers/net/pppoe.c
#   2005/03/09 21:12:11-08:00 herbert@gondor.apana.org.au +3 -1
#   [NET]: Fix CHECKSUM_HW wrt. packet trimming.
#   
#   When something, on receive, between a CHECKSUM_HW using
#   driver and the code validating skb->csum trims the head
#   of the packet we have to reset skb->ip_summed back to
#   CHECKSUM_NONE because this kind of change invalidates
#   the skb->csum value calculated by the driver.
#   
#   Various spots handle this properly, but not all.  So
#   abstract these actions into helper routines in order
#   to avoid code duplication.
#   
#   Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# ChangeSet
#   2005/03/09 20:49:05-08:00 kaber@trash.net 
#   [XFRM]: Fix ICMP tempsel
#   
#   The selector ports are initialized to fl_ip_sport/fl_ip_dport instead
#   of xfrm_flowi_sport(fl)/xfrm_flowi_dport(fl). This is wrong for ICMP,
#   type and code should be stored in sport and dport, in struct flowi both
#   are contained in fl_ip_sport.
#   
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/ipv6/xfrm6_state.c
#   2005/03/09 20:48:50-08:00 kaber@trash.net +2 -2
#   [XFRM]: Fix ICMP tempsel
#   
#   The selector ports are initialized to fl_ip_sport/fl_ip_dport instead
#   of xfrm_flowi_sport(fl)/xfrm_flowi_dport(fl). This is wrong for ICMP,
#   type and code should be stored in sport and dport, in struct flowi both
#   are contained in fl_ip_sport.
#   
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/ipv4/xfrm4_state.c
#   2005/03/09 20:48:50-08:00 kaber@trash.net +2 -2
#   [XFRM]: Fix ICMP tempsel
#   
#   The selector ports are initialized to fl_ip_sport/fl_ip_dport instead
#   of xfrm_flowi_sport(fl)/xfrm_flowi_dport(fl). This is wrong for ICMP,
#   type and code should be stored in sport and dport, in struct flowi both
#   are contained in fl_ip_sport.
#   
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# ChangeSet
#   2005/03/09 20:44:37-08:00 bunk@stusta.de 
#   [SUNHME]: make a struct static
#   
#   This patch makes a needlessly global struct static.
#   
#   Signed-off-by: Adrian Bunk <bunk@stusta.de>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# drivers/net/sunhme.c
#   2005/03/09 20:44:23-08:00 bunk@stusta.de +2 -2
#   [SUNHME]: make a struct static
#   
#   This patch makes a needlessly global struct static.
#   
#   Signed-off-by: Adrian Bunk <bunk@stusta.de>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# ChangeSet
#   2005/03/09 20:43:08-08:00 herbert@13thfloor.at 
#   [NET]: Passcred cleanup in struct sock
#   
#   struct socket uses a 'bool' (unsigned char) to
#   'flag' the pass-credential option for sockets
#   (which can be easily replaced by a flag)
#   
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/unix/af_unix.c
#   2005/03/09 20:42:53-08:00 herbert@13thfloor.at +6 -4
#   [NET]: Passcred cleanup in struct sock
#   
#   struct socket uses a 'bool' (unsigned char) to
#   'flag' the pass-credential option for sockets
#   (which can be easily replaced by a flag)
#   
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/socket.c
#   2005/03/09 20:42:53-08:00 herbert@13thfloor.at +1 -1
#   [NET]: Passcred cleanup in struct sock
#   
#   struct socket uses a 'bool' (unsigned char) to
#   'flag' the pass-credential option for sockets
#   (which can be easily replaced by a flag)
#   
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/core/sock.c
#   2005/03/09 20:42:53-08:00 herbert@13thfloor.at +5 -2
#   [NET]: Passcred cleanup in struct sock
#   
#   struct socket uses a 'bool' (unsigned char) to
#   'flag' the pass-credential option for sockets
#   (which can be easily replaced by a flag)
#   
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# include/net/scm.h
#   2005/03/09 20:42:52-08:00 herbert@13thfloor.at +2 -2
#   [NET]: Passcred cleanup in struct sock
#   
#   struct socket uses a 'bool' (unsigned char) to
#   'flag' the pass-credential option for sockets
#   (which can be easily replaced by a flag)
#   
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# include/linux/net.h
#   2005/03/09 20:42:52-08:00 herbert@13thfloor.at +1 -1
#   [NET]: Passcred cleanup in struct sock
#   
#   struct socket uses a 'bool' (unsigned char) to
#   'flag' the pass-credential option for sockets
#   (which can be easily replaced by a flag)
#   
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# ChangeSet
#   2005/03/09 20:39:57-08:00 herbert@gondor.apana.org.au 
#   [IPV6]: Handle loopback restration errors in addrconf_init()
#   
#   Let's also clean up loopback's ipv6 structure in addrconf_cleanup
#   even though it never happens currently :)
#   
#   Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/ipv6/af_inet6.c
#   2005/03/09 20:39:44-08:00 herbert@gondor.apana.org.au +9 -2
#   [IPV6]: Handle loopback restration errors in addrconf_init()
#   
#   Let's also clean up loopback's ipv6 structure in addrconf_cleanup
#   even though it never happens currently :)
#   
#   Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/ipv6/addrconf.c
#   2005/03/09 20:39:44-08:00 herbert@gondor.apana.org.au +13 -9
#   [IPV6]: Handle loopback restration errors in addrconf_init()
#   
#   Let's also clean up loopback's ipv6 structure in addrconf_cleanup
#   even though it never happens currently :)
#   
#   Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# include/net/addrconf.h
#   2005/03/09 20:39:44-08:00 herbert@gondor.apana.org.au +1 -1
#   [IPV6]: Handle loopback restration errors in addrconf_init()
#   
#   Let's also clean up loopback's ipv6 structure in addrconf_cleanup
#   even though it never happens currently :)
#   
#   Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# ChangeSet
#   2005/03/09 20:34:01-08:00 wensong@linux-vs.org 
#   [IPVS]: Fix that the WRR scheduler works correctly when server is updated or overloaded
#   
#   Here is the patch to make the WRR scheduler work correctly when server is 
#   updated with new weight or marked overloaded. Please check and apply it to 
#   kernel 2.6.
#   
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/ipv4/ipvs/ip_vs_wrr.c
#   2005/03/09 20:33:48-08:00 wensong@linux-vs.org +3 -1
#   [IPVS]: Fix that the WRR scheduler works correctly when server is updated or overloaded
#   
#   Here is the patch to make the WRR scheduler work correctly when server is 
#   updated with new weight or marked overloaded. Please check and apply it to 
#   kernel 2.6.
#   
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# ChangeSet
#   2005/03/09 20:29:20-08:00 horms@verge.net.au 
#   [IPVS]: Fix comment typos.
#   
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/ipv4/ipvs/ip_vs_wrr.c
#   2005/03/09 20:29:08-08:00 horms@verge.net.au +1 -1
#   [IPVS]: Fix comment typos.
#   
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/ipv4/ipvs/ip_vs_core.c
#   2005/03/09 20:29:08-08:00 horms@verge.net.au +1 -1
#   [IPVS]: Fix comment typos.
#   
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# ChangeSet
#   2005/03/09 15:41:29-08:00 gregkh@suse.de 
#   [PATCH] class: add a semaphore to struct class, and use that instead of the subsystem rwsem.
#   
#   This moves us away from using the rwsem, although recursive adds and removes of class devices
#   is not yet possible (nor is it really known if it even is needed.)  So this simple change is
#   done instead.
#   
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# include/linux/device.h
#   2005/03/09 09:03:56-08:00 gregkh@suse.de +1 -1
#   class: add a semaphore to struct class, and use that instead of the subsystem rwsem.
# 
# drivers/base/class.c
#   2005/03/09 09:03:56-08:00 gregkh@suse.de +11 -12
#   class: add a semaphore to struct class, and use that instead of the subsystem rwsem.
# 
# ChangeSet
#   2005/03/09 15:39:09-08:00 gregkh@suse.de 
#   [PATCH] sysdev: remove the rwsem usage from this subsystem.
#   
#   If further finer grained locking is needed, we can add a lock to the sysdev_class to
#   lock the class drivers list.  But if you do that, remember the global list also is still
#   there and needs to be protected.  That's why I went with a simple lock for everything.
#   
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/base/sys.c
#   2005/03/09 09:03:37-08:00 gregkh@suse.de +11 -10
#   sysdev: remove the rwsem usage from this subsystem.
# 
# ChangeSet
#   2005/03/09 15:35:31-08:00 gregkh@suse.de 
#   [PATCH] sysdev: fix the name of the list of drivers to be a sane name
#   
#   Heh, "global_drivers" as a static...
#   
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/base/sys.c
#   2005/03/09 09:03:41-08:00 gregkh@suse.de +8 -8
#   sysdev: fix the name of the list of drivers to be a sane name
# 
# ChangeSet
#   2005/03/09 15:24:27-08:00 gregkh@suse.de 
#   [PATCH] debugfs: fix bool built-in type.
#   
#   Thanks to Alessandro Rubini <rubini@gnudd.com> for pointing this out.
#   
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# fs/debugfs/file.c
#   2005/03/09 09:03:16-08:00 gregkh@suse.de +1 -1
#   debugfs: fix bool built-in type.
# 
# ChangeSet
#   2005/03/09 15:24:07-08:00 gregkh@suse.de 
#   [PATCH] debufs: make built in types add a \n to their output
#   
#   Thanks to Alessandro Rubini <rubini@gnudd.com> for pointing this out.
#   
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# fs/debugfs/file.c
#   2005/03/09 09:03:20-08:00 gregkh@suse.de +1 -1
#   debufs: make built in types add a \n to their output
# 
# ChangeSet
#   2005/03/09 15:06:02-08:00 gregkh@suse.de 
#   [PATCH] kmap: remove usage of rwsem from kobj_map.
#   
#   This forces the caller to provide the lock, but as they all already had one, it's not a big change.
#   It also removes the now-unneeded cdev_subsys.  Thanks to Jon Corbet for reminding me about that.
#   
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# include/linux/kobj_map.h
#   2005/03/09 09:03:28-08:00 gregkh@suse.de +1 -1
#   kmap: remove usage of rwsem from kobj_map.
# 
# fs/char_dev.c
#   2005/03/09 09:03:28-08:00 gregkh@suse.de +9 -17
#   kmap: remove usage of rwsem from kobj_map.
# 
# drivers/block/genhd.c
#   2005/03/09 09:03:28-08:00 gregkh@suse.de +1 -1
#   kmap: remove usage of rwsem from kobj_map.
# 
# drivers/base/map.c
#   2005/03/09 09:03:28-08:00 gregkh@suse.de +10 -11
#   kmap: remove usage of rwsem from kobj_map.
# 
# ChangeSet
#   2005/03/09 22:57:45+00:00 ben-linux@org.rmk.(none) 
#   [ARM PATCH] 2526/1: S3C2410 - s3c2400 uart support
#   
#   Patch from Ben Dooks
#   
#   Support for s3c2400 uarts in the s3c2410.c driver,
#   to go with the s3c2410 and s3c2440 support already
#   in there.
#   Add PORT_S3C2400 to include/linux/serial_core.h
#   
#   Signed-off-by: Ben Dooks
#   Signed-off-by: Russell King
# 
# include/linux/serial_core.h
#   2005/03/09 21:53:04+00:00 ben-linux@org.rmk.(none) +3 -0
#   [PATCH] 2526/1: S3C2410 - s3c2400 uart support
# 
# drivers/serial/s3c2410.c
#   2005/03/09 22:09:10+00:00 ben-linux@org.rmk.(none) +98 -1
#   [PATCH] 2526/1: S3C2410 - s3c2400 uart support
# 
# ChangeSet
#   2005/03/09 22:33:29+00:00 ben-linux@org.rmk.(none) 
#   [ARM PATCH] 2521/2: S3C2410 - update documentation
#   
#   Patch from Ben Dooks
#   
#   Update info on supported CPUs, add Lucas to
#   the list of contributors.
#   Add section on adding new machines
#   
#   Signed-off-by: Ben Dooks
#   Signed-off-by: Russell King
# 
# Documentation/arm/Samsung-S3C24XX/Overview.txt
#   2005/03/09 20:48:01+00:00 ben-linux@org.rmk.(none) +32 -2
#   [PATCH] 2521/2: S3C2410 - update documentation
# 
# ChangeSet
#   2005/03/09 12:17:18-08:00 gregkh@suse.de 
#   [PATCH] USB: move usb core to use class_simple instead of it's own class functions.
#   
#   This is needed if the class code is going to be made easier to use, and it makes the code
#   smaller and easier to understand.
#   
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/core/file.c
#   2005/03/09 09:03:08-08:00 gregkh@suse.de +19 -36
#   USB: move usb core to use class_simple instead of it's own class functions.
# 
# ChangeSet
#   2005/03/09 12:14:18-08:00 paul.mundt@nokia.com 
#   [PATCH] Add SuperHyway bus subsystem
#   
#   Signed-off-by: Paul Mundt <paul.mundt@nokia.com>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# ChangeSet
#   2005/03/09 15:14:14-05:00 olof@austin.ibm.com 
#   [PATCH] [VIA RHINE] older chips oops on shutdown
#   
#   I'm oopsing on shutdown on a machine that has a Via Rhine adapter in it:
#   
#   Unable to handle kernel paging request at virtual address e0803003
#   [...]
#   EIP is at ioread8+0x2c/0x40
#   Call Trace:
#    [<c0103d5f>] show_stack+0x7f/0xa0
#    [<c0103efa>] show_registers+0x15a/0x1c0
#    [<c01040ce>] die+0xce/0x150
#    [<c0113406>] do_page_fault+0x356/0x692
#    [<c01039ff>] error_code+0x2b/0x30
#    [<c026b490>] rhine_shutdown+0x60/0x140
#    [<c0253ad9>] device_shutdown+0x89/0x8b
#    [<c012461c>] sys_reboot+0xac/0x200
#    [<c0102f71>] sysenter_past_esp+0x52/0x75
#   
#   
#   Seems like it is the ioread8 in:
#   
#           /* Hit power state D3 (sleep) */
#           iowrite8(ioread8(ioaddr + StickyHW) | 0x03, ioaddr + StickyHW);
#   
#   that fails. StickyHW is 0x83. lspci says:
#   
#   0000:00:07.0 Ethernet controller: VIA Technologies, Inc. VT86C100A [Rhine] (rev 06)
#           Flags: bus master, medium devsel, latency 32, IRQ 18
#           I/O ports at ec00 [size=128]
#           Memory at dfffff80 (32-bit, non-prefetchable) [size=128]
#   
#   In other words, it's trying to read outside of the I/O range (0x80),
#   which matches the fauling address.
#   
#   I'm guessing my chip revision doesn't support WOL, it's a crappy noname
#   card.
#   
#   It does seem as if rhine_power_init checks quirks for rqWOL before
#   touching any registers. Should rhine_shutdown do the same? Proposed
#   patch below, which resolves the problem on my system.
#   
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/via-rhine.c
#   2005/03/05 13:25:34-05:00 olof@austin.ibm.com +3 -0
#   [VIA RHINE] older chips oops on shutdown
# 
# include/linux/superhyway.h
#   2005/03/09 09:04:50-08:00 paul.mundt@nokia.com +79 -0
#   Add SuperHyway bus subsystem
# 
# drivers/sh/superhyway/superhyway.c
#   2005/03/09 09:04:50-08:00 paul.mundt@nokia.com +201 -0
#   Add SuperHyway bus subsystem
# 
# drivers/sh/superhyway/superhyway-sysfs.c
#   2005/03/09 09:04:50-08:00 paul.mundt@nokia.com +45 -0
#   Add SuperHyway bus subsystem
# 
# drivers/sh/superhyway/Makefile
#   2005/03/09 09:04:50-08:00 paul.mundt@nokia.com +7 -0
#   Add SuperHyway bus subsystem
# 
# include/linux/superhyway.h
#   2005/03/09 09:04:50-08:00 paul.mundt@nokia.com +0 -0
#   BitKeeper file /home/greg/linux/BK/do/sh-2.6/include/linux/superhyway.h
# 
# drivers/sh/superhyway/superhyway.c
#   2005/03/09 09:04:50-08:00 paul.mundt@nokia.com +0 -0
#   BitKeeper file /home/greg/linux/BK/do/sh-2.6/drivers/sh/superhyway/superhyway.c
# 
# drivers/sh/superhyway/superhyway-sysfs.c
#   2005/03/09 09:04:50-08:00 paul.mundt@nokia.com +0 -0
#   BitKeeper file /home/greg/linux/BK/do/sh-2.6/drivers/sh/superhyway/superhyway-sysfs.c
# 
# drivers/sh/superhyway/Makefile
#   2005/03/09 09:04:50-08:00 paul.mundt@nokia.com +0 -0
#   BitKeeper file /home/greg/linux/BK/do/sh-2.6/drivers/sh/superhyway/Makefile
# 
# drivers/sh/Makefile
#   2005/03/09 09:04:50-08:00 paul.mundt@nokia.com +6 -0
#   Add SuperHyway bus subsystem
# 
# drivers/sh/Makefile
#   2005/03/09 09:04:50-08:00 paul.mundt@nokia.com +0 -0
#   BitKeeper file /home/greg/linux/BK/do/sh-2.6/drivers/sh/Makefile
# 
# ChangeSet
#   2005/03/09 15:12:50-05:00 akpm@osdl.org 
#   [PATCH] sis900 kernel oops fix
#   
#   From: Herbert Xu <herbert@gondor.apana.org.au>
#   
#   Fix bug #4223.
#   
#   OK, this happened because we got preempted before sis900_mii_probe
#   finished setting the sis_priv->mii.  Theoretically this can happen
#   with SMP as well but I suppose the number of SMP machines with sis900
#   is fairly small.
#   
#   Anyway, the fix is to make sure that sis900_mii_probe is done before
#   the device can be opened.  This patch does it by moving the setup
#   before register_netdevice.
#   
#   Since the netdev name is not available before register_netdev, I've
#   changed the relevant printk's to use pci_name instead.  Note that
#   one of those printk's may be called after register_netdev as well.
#   
#   Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/sis900.c
#   2005/03/09 04:01:21-05:00 akpm@osdl.org +21 -20
#   sis900 kernel oops fix
# 
# ChangeSet
#   2005/03/09 10:25:02-08:00 dhowells@redhat.com 
#   [PATCH] rwsem: Make rwsems use interrupt disabling spinlocks
#   
#   The attached patch makes read/write semaphores use interrupt disabling
#   spinlocks in the slow path, thus rendering the up functions and trylock
#   functions available for use in interrupt context.  This matches the
#   regular semaphore behaviour.
#   
#   I've assumed that the normal down functions must be called with interrupts
#   enabled (since they might schedule), and used the irq-disabling spinlock
#   variants that don't save the flags.
#   
#   Signed-Off-By: David Howells <dhowells@redhat.com>
#   Tested-by: Badari Pulavarty <pbadari@us.ibm.com>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# lib/rwsem.c
#   2005/03/09 02:45:16-08:00 dhowells@redhat.com +10 -6
#   rwsem: Make rwsems use interrupt disabling spinlocks
# 
# lib/rwsem-spinlock.c
#   2005/03/09 02:43:47-08:00 dhowells@redhat.com +26 -16
#   rwsem: Make rwsems use interrupt disabling spinlocks
# 
# ChangeSet
#   2005/03/09 10:22:12-08:00 ecashin@coraid.com 
#   [PATCH] aoe: drivers/block/aoe/aoechr.c cleanups
#   
#   Adrian Bunk <bunk@stusta.de> writes:
#   
#   > This patch contains the following cleanups:
#   > - make the needlessly global struct aoe_fops static
#   > - #if 0 the unused global function aoechr_hdump
#   
#   Thanks for the patch.  The original patch leaves the prototype for
#   aoechr_hdump in aoe.h, but since this function is just for debugging,
#   it seems better to just take both prototype and definition out.
#   
#   
#   remove aoechr_hdump
#   make aoe_fops static
#   
#   Signed-off-by: Adrian Bunk <bunk@stusta.de>
#   Signed-off-by: Ed L. Cashin <ecashin@coraid.com>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/block/aoe/aoechr.c
#   2005/03/09 09:05:11-08:00 ecashin@coraid.com +1 -36
#   aoe: drivers/block/aoe/aoechr.c cleanups
# 
# drivers/block/aoe/aoe.h
#   2005/03/09 09:05:11-08:00 ecashin@coraid.com +0 -1
#   aoe: drivers/block/aoe/aoechr.c cleanups
# 
# ChangeSet
#   2005/03/09 10:21:52-08:00 ecashin@coraid.com 
#   [PATCH] aoe status.sh: handle sysfs not in /etc/mtab
#   
#   Suse 9.1 Pro doesn't put /sys in /etc/mtab.  This patch makes the
#   example aoe status.sh script work when sysfs is mounted but `mount`
#   doesn't mention sysfs.
#   
#   
#   aoe status.sh: handle sysfs not in /etc/mtab
#   
#   Signed-off-by: Ed L. Cashin <ecashin@coraid.com>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# Documentation/aoe/status.sh
#   2005/03/09 09:05:15-08:00 ecashin@coraid.com +5 -2
#   aoe status.sh: handle sysfs not in /etc/mtab
# 
# ChangeSet
#   2005/03/09 10:21:33-08:00 ecashin@coraid.com 
#   [PATCH] aoe: fail IO on disk errors
#   
#   This patch makes disk errors fail the IO instead of getting logged and
#   ignored.
#   
#   
#   Fail IO on disk errors
#   
#   Signed-off-by: Ed L. Cashin <ecashin@coraid.com>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/block/aoe/aoecmd.c
#   2005/03/09 09:05:19-08:00 ecashin@coraid.com +5 -3
#   aoe: fail IO on disk errors
# 
# ChangeSet
#   2005/03/09 10:21:15-08:00 ecashin@coraid.com 
#   [PATCH] aoe: update documentation for udev users
#   
#   Bodo Eggert <7eggert@gmx.de> writes:
#   
#   > Ed L Cashin <ecashin@coraid.com> wrote:
#   >
#   >> +if=A0test=A0-z=A0"$conf";=A0then
#   >> +=A0=A0=A0=A0=A0=A0=A0=A0conf=3D"`find=A0/etc=A0-type=A0f=A0-name=A0udev=
#   .conf=A02>=A0/dev/null`"
#   >> +fi
#   >> +if=A0test=A0-z=A0"$conf"=A0||=A0test=A0!=A0-r=A0$conf;=A0then
#   >> +=A0=A0=A0=A0=A0=A0=A0=A0echo=A0"$me=A0Error:=A0could=A0not=A0find=A0rea=
#   dable=A0udev.conf=A0in=A0/etc"=A01>&2
#   >> +=A0=A0=A0=A0=A0=A0=A0=A0exit=A01
#   >> +fi
#   >
#   > This will fail and print
#   > ---
#   > bash: test: etc/udev.conf: binary operator expected
#   > ---
#   > if there is more than one udev.conf.
#   >
#   > Fix: Always put quotes around variables.
#   
#   Thanks.  With the changes below, it still will complain if it finds
#   more than one udev.conf, but only if /etc/udev/udev.conf doesn't
#   exist.
#   
#   Quote all shell variables, and use /etc/udev/udev.conf if available.
#   
#   Signed-off-by: Ed L. Cashin <ecashin@coraid.com>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# Documentation/aoe/udev-install.sh
#   2005/03/09 09:05:23-08:00 ecashin@coraid.com +9 -5
#   aoe: update documentation for udev users
# 
# ChangeSet
#   2005/03/09 10:20:56-08:00 ecashin@coraid.com 
#   [PATCH] aoe: add documentation for udev users
#   
#   add documentation for udev users
#   
#   Signed-off-by: Ed L. Cashin <ecashin@coraid.com>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# Documentation/aoe/udev.txt
#   2005/03/09 09:05:27-08:00 ecashin@coraid.com +23 -0
#   aoe: add documentation for udev users
# 
# Documentation/aoe/udev-install.sh
#   2005/03/09 09:05:27-08:00 ecashin@coraid.com +22 -0
#   aoe: add documentation for udev users
# 
# Documentation/aoe/udev.txt
#   2005/03/09 09:05:27-08:00 ecashin@coraid.com +0 -0
#   BitKeeper file /home/greg/linux/BK/do/aoe-2.6/Documentation/aoe/udev.txt
# 
# Documentation/aoe/udev-install.sh
#   2005/03/09 09:05:27-08:00 ecashin@coraid.com +0 -0
#   BitKeeper file /home/greg/linux/BK/do/aoe-2.6/Documentation/aoe/udev-install.sh
# 
# Documentation/aoe/aoe.txt
#   2005/03/09 09:05:27-08:00 ecashin@coraid.com +10 -3
#   aoe: add documentation for udev users
# 
# ChangeSet
#   2005/03/09 10:20:37-08:00 alexn@dsv.su.se 
#   [PATCH] AoE warning on 64-bit archs
#   
#   I just accidently built AoE on x86-64 and it emits a warning
#   due to conversion of types of different size, trivial fix:
#   
#   
#   Signed-off-by: Alexander Nyberg <alexn@dsv.su.se>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/block/aoe/aoechr.c
#   2005/03/09 09:05:31-08:00 alexn@dsv.su.se +2 -2
#   AoE warning on 64-bit archs
# 
# ChangeSet
#   2005/03/09 10:13:34-08:00 akpm@osdl.org 
#   [PATCH] tpm-build-fix
#   
#   drivers/char/tpm/tpm.c: In function `show_pcrs':
#   drivers/char/tpm/tpm.c:228: warning: passing arg 1 of `tpm_transmit' from incompatible pointer type
#   drivers/char/tpm/tpm.c:238: warning: passing arg 1 of `tpm_transmit' from incompatible pointer type
#   
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/char/tpm/tpm.c
#   2005/03/09 09:03:12-08:00 akpm@osdl.org +1 -1
#   tpm-build-fix
# 
# ChangeSet
#   2005/03/09 10:13:15-08:00 akpm@osdl.org 
#   [PATCH] tpm_atmel build fix
#   
#   drivers/char/tpm/tpm_atmel.c:131: unknown field `fops' specified in initializer
#   drivers/char/tpm/tpm_atmel.c:131: warning: missing braces around initializer
#   
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/char/tpm/tpm_atmel.c
#   2005/03/09 09:04:58-08:00 akpm@osdl.org +1 -1
#   tpm_atmel build fix
# 
# ChangeSet
#   2005/03/09 10:12:56-08:00 akpm@osdl.org 
#   [PATCH] tpm_msc-build-fix
#   
#   With older gcc's:
#   
#   drivers/char/tpm/tpm_nsc.c:238: unknown field `fops' specified in initializer
#   drivers/char/tpm/tpm_nsc.c:238: warning: missing braces around initializer
#   
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/char/tpm/tpm_nsc.c
#   2005/03/09 09:05:02-08:00 akpm@osdl.org +2 -1
#   tpm_msc-build-fix
# 
# ChangeSet
#   2005/03/09 10:12:38-08:00 kjhall@us.ibm.com 
#   [PATCH] tpm: fix cause of SMP stack traces
#   
#   There were misplaced spinlock acquires and releases in the probe, close and release
#   paths which were causing might_sleep and schedule while atomic error messages accompanied
#   by stack traces when the kernel was compiled with SMP support. Bug reported by Reben Jenster
#   <ruben@hotheads.de>
#   
#   Signed-off-by: Kylene Hall <kjhall@us.ibm.com>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/char/tpm/tpm.c
#   2005/03/09 09:05:06-08:00 kjhall@us.ibm.com +8 -8
#   tpm: fix cause of SMP stack traces
# 
# ChangeSet
#   2005/03/09 10:12:19-08:00 kjhall@us.ibm.com 
#   [PATCH] Add TPM hardware enablement driver
#   
#   This patch is a device driver to enable new hardware.  The new hardware is
#   the TPM chip as described by specifications at
#   <http://www.trustedcomputinggroup.org>.  The TPM chip will enable you to
#   use hardware to securely store and protect your keys and personal data.
#   To use the chip according to the specification, you will need the Trusted
#   Software Stack (TSS) of which an implementation for Linux is available at:
#   <http://sourceforge.net/projects/trousers>.
#   
#   
#   Signed-off-by: Leendert van Doorn <leendert@watson.ibm.com>
#   Signed-off-by: Reiner Sailer <sailer@watson.ibm.com>
#   Signed-off-by: Dave Safford <safford@watson.ibm.com>
#   Signed-off-by: Kylene Hall <kjhall@us.ibm.com>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/char/tpm/tpm_nsc.c
#   2005/03/09 09:05:40-08:00 kjhall@us.ibm.com +372 -0
#   Add TPM hardware enablement driver
# 
# drivers/char/tpm/tpm_atmel.c
#   2005/03/09 09:05:40-08:00 kjhall@us.ibm.com +216 -0
#   Add TPM hardware enablement driver
# 
# drivers/char/tpm/tpm.h
#   2005/03/09 09:05:40-08:00 kjhall@us.ibm.com +92 -0
#   Add TPM hardware enablement driver
# 
# drivers/char/tpm/tpm.c
#   2005/03/09 09:05:40-08:00 kjhall@us.ibm.com +697 -0
#   Add TPM hardware enablement driver
# 
# drivers/char/tpm/Makefile
#   2005/03/09 09:05:40-08:00 kjhall@us.ibm.com +7 -0
#   Add TPM hardware enablement driver
# 
# include/linux/pci_ids.h
#   2005/03/09 09:05:40-08:00 kjhall@us.ibm.com +1 -0
#   Add TPM hardware enablement driver
# 
# drivers/char/tpm/tpm_nsc.c
#   2005/03/09 09:05:40-08:00 kjhall@us.ibm.com +0 -0
#   BitKeeper file /home/greg/linux/BK/do/tpm-2.6/drivers/char/tpm/tpm_nsc.c
# 
# drivers/char/tpm/tpm_atmel.c
#   2005/03/09 09:05:40-08:00 kjhall@us.ibm.com +0 -0
#   BitKeeper file /home/greg/linux/BK/do/tpm-2.6/drivers/char/tpm/tpm_atmel.c
# 
# drivers/char/tpm/tpm.h
#   2005/03/09 09:05:40-08:00 kjhall@us.ibm.com +0 -0
#   BitKeeper file /home/greg/linux/BK/do/tpm-2.6/drivers/char/tpm/tpm.h
# 
# drivers/char/tpm/tpm.c
#   2005/03/09 09:05:40-08:00 kjhall@us.ibm.com +0 -0
#   BitKeeper file /home/greg/linux/BK/do/tpm-2.6/drivers/char/tpm/tpm.c
# 
# drivers/char/tpm/Makefile
#   2005/03/09 09:05:40-08:00 kjhall@us.ibm.com +0 -0
#   BitKeeper file /home/greg/linux/BK/do/tpm-2.6/drivers/char/tpm/Makefile
# 
# drivers/char/tpm/Kconfig
#   2005/03/09 09:05:40-08:00 kjhall@us.ibm.com +39 -0
#   Add TPM hardware enablement driver
# 
# drivers/char/Makefile
#   2005/03/09 09:05:39-08:00 kjhall@us.ibm.com +1 -1
#   Add TPM hardware enablement driver
# 
# drivers/char/Kconfig
#   2005/03/09 09:05:39-08:00 kjhall@us.ibm.com +2 -0
#   Add TPM hardware enablement driver
# 
# drivers/char/tpm/Kconfig
#   2005/03/09 09:05:40-08:00 kjhall@us.ibm.com +0 -0
#   BitKeeper file /home/greg/linux/BK/do/tpm-2.6/drivers/char/tpm/Kconfig
# 
# ChangeSet
#   2005/03/09 10:00:20-08:00 gregkh@suse.de 
#   [PATCH] kref: make kref_put return if this was the last put call.
#   
#   This is needed for the upcoming klist code from Pat.
#   
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# lib/kref.c
#   2005/03/09 09:03:24-08:00 gregkh@suse.de +9 -2
#   kref: make kref_put return if this was the last put call.
# 
# include/linux/kref.h
#   2005/03/09 09:03:24-08:00 gregkh@suse.de +1 -1
#   kref: make kref_put return if this was the last put call.
# 
# ChangeSet
#   2005/03/09 09:59:49-08:00 gregkh@suse.de 
#   [PATCH] sysdev: make system_subsys static as no one else needs access to it.
#   
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/base/sys.c
#   2005/03/09 09:03:51-08:00 gregkh@suse.de +1 -1
#   sysdev: make system_subsys static as no one else needs access to it.
# 
# ChangeSet
#   2005/03/09 09:53:28-08:00 gregkh@suse.de 
#   [PATCH] kset: make ksets have a spinlock, and use that to lock their lists
#   
#   Do this instead of using the rwsem of a subsys.
#   Smaller, faster, and I'm trying to get rid of the rwsem in the subsys.
#   
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# lib/kobject.c
#   2005/03/09 09:04:09-08:00 gregkh@suse.de +7 -6
#   kset: make ksets have a spinlock, and use that to lock their lists
# 
# include/linux/kobject.h
#   2005/03/09 09:04:09-08:00 gregkh@suse.de +2 -0
#   kset: make ksets have a spinlock, and use that to lock their lists
# 
# ChangeSet
#   2005/03/09 09:53:08-08:00 kay.sievers@vrfy.org 
#   [PATCH] floppy.c: pass physical device to device registration
#   
#   With this patch the floppy driver creates the usual symlink in sysfs to
#   the physical device backing the block device:
#   
#     $tree /sys/block/
#     /sys/block/
#     |-- fd0
#     |   |-- dev
#     |   |-- device -> ../../devices/platform/floppy0
#     ...
#   
#   Signed-off-by: Kay Sievers <kay.sievers@vrfy.org>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/block/floppy.c
#   2005/03/09 09:04:13-08:00 kay.sievers@vrfy.org +6 -13
#   floppy.c: pass physical device to device registration
# 
# ChangeSet
#   2005/03/09 09:52:48-08:00 kay.sievers@vrfy.org 
#   [PATCH] Driver core: add "bus" symlink to class/block devices
#   
#   On Tue, Feb 15, 2005 at 09:53:44PM +0100, Kay Sievers wrote:
#   > Add a "bus" symlink to the class and block devices, just like the "driver"
#   > and "device" links. This may be a huge speed gain for e.g. udev to determine
#   > the bus value of a device, as we currently need to do a brute-force scan in
#   > /sys/bus/* to find this value.
#   
#   Hmm, while playing around with it, I think we should create the "bus"
#   link on the physical device on not on the class device.
#   
#   Also the current "driver" link at the class device should be removed,
#   cause class devices don't have a driver. Block devices never had this
#   misleading symlink.
#   
#    From the class device we point with the "device" link to the physical
#    device, and only the physical device should have the "driver" and the
#    "bus" link, as it represents the real relationship.
#   
#   Signed-off-by: Kay Sievers <kay.sievers@vrfy.org>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/base/class.c
#   2005/03/09 09:04:17-08:00 kay.sievers@vrfy.org +5 -31
#   Driver core: add "bus" symlink to class/block devices
# 
# drivers/base/bus.c
#   2005/03/09 09:04:17-08:00 kay.sievers@vrfy.org +2 -0
#   Driver core: add "bus" symlink to class/block devices
# 
# ChangeSet
#   2005/03/09 09:52:29-08:00 Michael.Waychison@Sun.COM 
#   [PATCH] driver core: clean driver unload
#   
#   Get rid of semaphore abuse by converting device_driver->unload_sem
#   semaphore to device_driver->unloaded completion.
#   
#   This should get rid of any confusion as well as save a few bytes in the
#   process.
#   
#   Signed-off-by: Mike Waychison <michael.waychison@sun.com>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# include/linux/device.h
#   2005/03/09 09:04:21-08:00 Michael.Waychison@Sun.COM +1 -1
#   driver core: clean driver unload
# 
# drivers/base/driver.c
#   2005/03/09 09:04:21-08:00 Michael.Waychison@Sun.COM +6 -7
#   driver core: clean driver unload
# 
# drivers/base/bus.c
#   2005/03/09 09:04:21-08:00 Michael.Waychison@Sun.COM +1 -1
#   driver core: clean driver unload
# 
# ChangeSet
#   2005/03/09 09:52:10-08:00 kay.sievers@vrfy.org 
#   [PATCH] videodev: pass dev_t to the class core
#   
#   Signed-off-by: Kay Sievers <kay.sievers@vrfy.org>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/media/video/videodev.c
#   2005/03/09 09:04:25-08:00 kay.sievers@vrfy.org +1 -10
#   videodev: pass dev_t to the class core
# 
# ChangeSet
#   2005/03/09 09:51:50-08:00 kay.sievers@vrfy.org 
#   [PATCH] i2c: class driver pass dev_t to the class core
#   
#   Signed-off-by: Kay Sievers <kay.sievers@vrfy.org>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/i2c/i2c-dev.c
#   2005/03/09 09:04:29-08:00 kay.sievers@vrfy.org +1 -8
#   i2c: class driver pass dev_t to the class core
# 
# ChangeSet
#   2005/03/09 09:51:30-08:00 kay.sievers@vrfy.org 
#   [PATCH] usb: class driver pass dev_t to the class core
#   
#   Signed-off-by: Kay Sievers <kay.sievers@vrfy.org>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/core/file.c
#   2005/03/09 09:04:33-08:00 kay.sievers@vrfy.org +1 -8
#   usb: class driver pass dev_t to the class core
# 
# ChangeSet
#   2005/03/09 09:33:17-08:00 kay.sievers@vrfy.org 
#   [PATCH] class_simple: pass dev_t to the class core
#   
#   Signed-off-by: Kay Sievers <kay.sievers@vrfy.org>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/base/class_simple.c
#   2005/03/09 09:04:38-08:00 kay.sievers@vrfy.org +2 -19
#   class_simple: pass dev_t to the class core
# 
# ChangeSet
#   2005/03/09 09:32:58-08:00 kay.sievers@vrfy.org 
#   [PATCH] block core: export MAJOR/MINOR to the hotplug env
#   
#   Signed-off-by: Kay Sievers <kay.sievers@vrfy.org>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/block/genhd.c
#   2005/03/09 09:04:42-08:00 kay.sievers@vrfy.org +34 -19
#   block core: export MAJOR/MINOR to the hotplug env
# 
# ChangeSet
#   2005/03/09 09:32:38-08:00 kay.sievers@vrfy.org 
#   [PATCH] class core: export MAJOR/MINOR to the hotplug env
#   
#   Move the creation of the sysfs "dev" file of a class device into the
#   driver core. The struct class_device contains a dev_t value now.  If set,
#   the driver core will create the "dev" file containing the major/minor
#   numbers automatically.
#   
#   Signed-off-by: Kay Sievers <kay.sievers@vrfy.org>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# include/linux/device.h
#   2005/03/09 09:04:46-08:00 kay.sievers@vrfy.org +1 -0
#   class core: export MAJOR/MINOR to the hotplug env
# 
# drivers/base/class.c
#   2005/03/09 09:04:46-08:00 kay.sievers@vrfy.org +29 -10
#   class core: export MAJOR/MINOR to the hotplug env
# 
# ChangeSet
#   2005/03/09 09:32:19-08:00 rmk+lkml@arm.linux.org.uk 
#   [PATCH] driver core: Separate platform device name from platform device number
#   
#   Separate platform device name from platform device number such that
#   names ending with numbers aren't confusing.
#   
#   Signed-off-by: Russell King <rmk@arm.linux.org.uk>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/base/platform.c
#   2005/03/09 09:04:54-08:00 rmk+lkml@arm.linux.org.uk +1 -1
#   driver core: Separate platform device name from platform device number
# 
# ChangeSet
#   2005/03/09 09:32:00-08:00 linux@dominikbrodowski.de 
#   [PATCH] cpufreq 2.4 interface removal schedule
#   
#   Even though these 2.4. interfaces are already gone in Dave Jones' cpufreq
#   bitkeeper tree, here's a patch which properly announces it in
#   Documentation/feature-removal-schedule.txt:
#   
#   
#   Add meaningful content concerning the removal of deprecated interfaces to
#   the cpufreq core.
#   
#   Signed-off-by: Dominik Brodowski <linux@brodo.de>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# Documentation/feature-removal-schedule.txt
#   2005/03/09 09:05:48-08:00 linux@dominikbrodowski.de +11 -3
#   cpufreq 2.4 interface removal schedule
# 
# ChangeSet
#   2005/03/09 09:31:40-08:00 rddunlap@osdl.org 
#   [PATCH] Add 2.4.x cpufreq /proc and sysctl interface removal feature-removal-schedule
#   
#   Add 2.4.x cpufreq /proc and sysctl interface removal
#   to the feature-removal-schedule.
#   
#   Signed-off-by: Randy Dunlap <rddunlap@osdl.org>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# Documentation/feature-removal-schedule.txt
#   2005/03/09 09:05:52-08:00 rddunlap@osdl.org +9 -0
#   Add 2.4.x cpufreq /proc and sysctl interface removal feature-removal-schedule
# 
# ChangeSet
#   2005/03/09 09:31:21-08:00 arjan@infradead.org 
#   [PATCH] Kobject: remove some unneeded exports
#   
#   kobject_get_path and kobject_rename are only used by the sysfs core code
#   and not aren't really driver-ish code. Remove the unused exports
#   
#   Signed-off-by: Arjan van de Ven <arjan@infradead.org>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# lib/kobject.c
#   2005/03/09 09:05:56-08:00 arjan@infradead.org +0 -2
#   Kobject: remove some unneeded exports
# 
# ChangeSet
#   2005/03/09 08:30:33-08:00 axboe@suse.de 
#   [PATCH] barrier rework updates
#   
#   As promised to Andrew, here are the latest bits that fixup the block io
#   barrier handling.
#   
#   - Add io scheduler ->deactivate hook to tell the io scheduler is a
#     request is suspended from the block layer. cfq and as needs this hook.
#   
#   - Locking updates
#   
#   - Make sure a driver doesn't reuse the flush rq before a previous one
#     has completed
#   
#   - Typo in the scsi_io_completion() function, the bit shift was wrong
#   
#   - sd needs proper timeout on the flush
#   
#   - remove silly debug leftover in ide-disk wrt "hdc"
#   
#   Signed-off-by: Jens Axboe <axboe@suse.de>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/linux/elevator.h
#   2005/03/09 00:03:46-08:00 axboe@suse.de +3 -0
#   barrier rework updates
# 
# include/linux/blkdev.h
#   2005/03/09 00:03:24-08:00 axboe@suse.de +2 -0
#   barrier rework updates
# 
# drivers/scsi/sd.c
#   2005/03/09 00:12:06-08:00 axboe@suse.de +15 -3
#   barrier rework updates
# 
# drivers/scsi/scsi_lib.c
#   2005/03/09 00:12:06-08:00 axboe@suse.de +1 -1
#   barrier rework updates
# 
# drivers/ide/ide-disk.c
#   2005/03/09 03:27:42-08:00 axboe@suse.de +7 -13
#   barrier rework updates
# 
# drivers/block/ll_rw_blk.c
#   2005/03/09 00:01:38-08:00 axboe@suse.de +10 -11
#   barrier rework updates
# 
# drivers/block/elevator.c
#   2005/03/09 00:08:14-08:00 axboe@suse.de +27 -1
#   barrier rework updates
# 
# drivers/block/cfq-iosched.c
#   2005/03/09 00:05:54-08:00 axboe@suse.de +10 -4
#   barrier rework updates
# 
# drivers/block/as-iosched.c
#   2005/03/09 00:07:15-08:00 axboe@suse.de +16 -14
#   barrier rework updates
# 
# ChangeSet
#   2005/03/09 08:13:13-08:00 willy@parisc-linux.org 
#   [PATCH] PA-RISC irq handling improvements
#   
#    - Move the bits_wide parameter from txn_alloc_data to txn_alloc_irq.
#      It's too late by the time it hits txn_alloc_data(), we can only panic.
#      In txn_alloc_irq, we can fail the allocation and continue.
#    - Also fix a bug where we'd only allow up to half the interrupts to be
#      allocated.  Not a problem for iosapic machines, but might have sucked
#      on a really big GSC-based machine.
#    - Add missing irq_enter() / irq_exit()
#    - Allow interrupt processing to be interrupted by the timer tick so we
#      actually account hard interrupts.  Also speed up the handling of CPU
#      interrupts by not masking with cpu_eiem again.
#    - Remove sufficiently obsolete DEBUG_IRQ code
#    - Remove limit on times around the loop.  If we exit the loop while
#      interrupts are still pending, we'll only be re-interrupted as soon
#      as we exit the function.
#    - Remove unnecessary includes
#   
#   Signed-off-by: Matthew Wilcox <willy@parisc-linux.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/asm-parisc/irq.h
#   2005/03/08 11:16:16-08:00 willy@parisc-linux.org +5 -3
#   PA-RISC irq handling improvements
# 
# drivers/parisc/gsc.c
#   2005/03/08 11:16:05-08:00 willy@parisc-linux.org +3 -3
#   PA-RISC irq handling improvements
# 
# arch/parisc/kernel/irq.c
#   2005/03/08 11:15:55-08:00 willy@parisc-linux.org +36 -68
#   PA-RISC irq handling improvements
# 
# ChangeSet
#   2005/03/09 08:12:57-08:00 willy@parisc-linux.org 
#   [PATCH] Improve PA-RISC make configcheck
#   
#   Fix "make configcheck | fgrep 'not needed' | fgrep parisc"
#   
#   Signed-off-by: Grant Grundler <grundler@parisc-linux.org>
#   Signed-off-by: Matthew Wilcox <willy@parisc-linux.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/asm-parisc/serial.h
#   2005/03/08 11:16:19-08:00 willy@parisc-linux.org +0 -2
#   Improve PA-RISC make configcheck
# 
# include/asm-parisc/numnodes.h
#   2005/03/08 11:16:18-08:00 willy@parisc-linux.org +0 -2
#   Improve PA-RISC make configcheck
# 
# include/asm-parisc/ide.h
#   2005/03/08 11:16:16-08:00 willy@parisc-linux.org +0 -2
#   Improve PA-RISC make configcheck
# 
# drivers/parisc/hppb.c
#   2005/03/08 11:16:06-08:00 willy@parisc-linux.org +0 -1
#   Improve PA-RISC make configcheck
# 
# drivers/parisc/eisa_eeprom.c
#   2005/03/08 11:16:05-08:00 willy@parisc-linux.org +0 -1
#   Improve PA-RISC make configcheck
# 
# arch/parisc/math-emu/driver.c
#   2005/03/08 11:15:57-08:00 willy@parisc-linux.org +0 -1
#   Improve PA-RISC make configcheck
# 
# arch/parisc/kernel/signal32.c
#   2005/03/08 11:15:56-08:00 willy@parisc-linux.org +0 -1
#   Improve PA-RISC make configcheck
# 
# arch/parisc/kernel/perf.c
#   2005/03/08 11:15:56-08:00 willy@parisc-linux.org +0 -1
#   Improve PA-RISC make configcheck
# 
# arch/parisc/kernel/binfmt_elf32.c
#   2005/03/08 11:15:54-08:00 willy@parisc-linux.org +0 -1
#   Improve PA-RISC make configcheck
# 
# ChangeSet
#   2005/03/09 08:12:42-08:00 willy@parisc-linux.org 
#   [PATCH] ALSA Harmony fixes
#   
#    - The entire silence buffer is now being filled, instead of just 1/8th of it.
#    - The silence buffer is now prepared during initialisation of the driver.
#    - snd_pcm_format_size() is missing from the ALSA headers:
#      using snd_pcm_format_physical_width() instead.
#   
#   Signed-off-by: Stuart Brady <sdbrady@ntlworld.com>
#   Signed-off-by: Matthew Wilcox <willy@parisc-linux.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# sound/parisc/harmony.c
#   2005/03/08 11:37:40-08:00 willy@parisc-linux.org +8 -5
#   ALSA Harmony fixes
# 
# sound/oss/harmony.c
#   2005/03/08 11:16:26-08:00 willy@parisc-linux.org +1 -1
#   ALSA Harmony fixes
# 
# ChangeSet
#   2005/03/09 08:12:28-08:00 willy@parisc-linux.org 
#   [PATCH] Sparse annotations and cleanup warnings for PA-RISC
#   
#    - Missing UL on large integers
#    - 0/NULL confusion
#    - __user annotations
#    - C99-style array elements
#   
#   Signed-off-by: Randolph Chung <tausq@parisc-linux.org>
#   Signed-off-by: Matthew Wilcox <willy@parisc-linux.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/asm-parisc/signal.h
#   2005/03/08 11:16:19-08:00 willy@parisc-linux.org +4 -3
#   Sparse annotations and cleanup warnings for PA-RISC
# 
# include/asm-parisc/compat.h
#   2005/03/08 11:16:16-08:00 willy@parisc-linux.org +4 -4
#   Sparse annotations and cleanup warnings for PA-RISC
# 
# include/asm-parisc/checksum.h
#   2005/03/08 11:16:16-08:00 willy@parisc-linux.org +2 -2
#   Sparse annotations and cleanup warnings for PA-RISC
# 
# arch/parisc/mm/fault.c
#   2005/03/08 11:15:57-08:00 willy@parisc-linux.org +1 -1
#   Sparse annotations and cleanup warnings for PA-RISC
# 
# arch/parisc/math-emu/driver.c
#   2005/03/08 11:15:57-08:00 willy@parisc-linux.org +1 -1
#   Sparse annotations and cleanup warnings for PA-RISC
# 
# arch/parisc/lib/checksum.c
#   2005/03/08 11:15:56-08:00 willy@parisc-linux.org +3 -3
#   Sparse annotations and cleanup warnings for PA-RISC
# 
# arch/parisc/kernel/unaligned.c
#   2005/03/08 11:15:56-08:00 willy@parisc-linux.org +2 -2
#   Sparse annotations and cleanup warnings for PA-RISC
# 
# arch/parisc/kernel/traps.c
#   2005/03/08 11:15:56-08:00 willy@parisc-linux.org +9 -9
#   Sparse annotations and cleanup warnings for PA-RISC
# 
# arch/parisc/kernel/sys_parisc32.c
#   2005/03/08 11:15:56-08:00 willy@parisc-linux.org +34 -36
#   Sparse annotations and cleanup warnings for PA-RISC
# 
# arch/parisc/kernel/sys_parisc.c
#   2005/03/08 11:15:56-08:00 willy@parisc-linux.org +8 -8
#   Sparse annotations and cleanup warnings for PA-RISC
# 
# arch/parisc/kernel/signal32.h
#   2005/03/08 11:15:56-08:00 willy@parisc-linux.org +6 -6
#   Sparse annotations and cleanup warnings for PA-RISC
# 
# arch/parisc/kernel/signal32.c
#   2005/03/08 11:15:56-08:00 willy@parisc-linux.org +13 -13
#   Sparse annotations and cleanup warnings for PA-RISC
# 
# arch/parisc/kernel/signal.c
#   2005/03/08 11:15:56-08:00 willy@parisc-linux.org +15 -15
#   Sparse annotations and cleanup warnings for PA-RISC
# 
# arch/parisc/kernel/setup.c
#   2005/03/08 11:15:56-08:00 willy@parisc-linux.org +3 -3
#   Sparse annotations and cleanup warnings for PA-RISC
# 
# arch/parisc/kernel/process.c
#   2005/03/08 11:15:56-08:00 willy@parisc-linux.org +4 -4
#   Sparse annotations and cleanup warnings for PA-RISC
# 
# arch/parisc/kernel/perf.c
#   2005/03/08 11:15:56-08:00 willy@parisc-linux.org +28 -28
#   Sparse annotations and cleanup warnings for PA-RISC
# 
# arch/parisc/kernel/ioctl32.c
#   2005/03/08 11:15:55-08:00 willy@parisc-linux.org +1 -1
#   Sparse annotations and cleanup warnings for PA-RISC
# 
# arch/parisc/kernel/hardware.c
#   2005/03/08 11:15:54-08:00 willy@parisc-linux.org +12 -12
#   Sparse annotations and cleanup warnings for PA-RISC
# 
# arch/parisc/kernel/firmware.c
#   2005/03/08 11:15:54-08:00 willy@parisc-linux.org +3 -3
#   Sparse annotations and cleanup warnings for PA-RISC
# 
# ChangeSet
#   2005/03/09 08:12:13-08:00 willy@parisc-linux.org 
#   [PATCH] PA-RISC assembler cleanups and fixes
#   
#    - Convert ldil/ldo to using the load32 macro.
#   
#   Signed-Off-By: Kyle McMartin <kyle@parisc-linux.org>
#   
#    - loop on signal delivery like other archs
#    - unify VM initialization code for 32/64-bit
#   
#   Signed-off-by: Randolph Chung <tausq@parisc-linux.org>
#   
#   Signed-off-by: Matthew Wilcox <willy@parisc-linux.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/parisc/kernel/real2.S
#   2005/03/08 11:15:56-08:00 willy@parisc-linux.org +1 -2
#   PA-RISC assembler cleanups and fixes
# 
# arch/parisc/kernel/hpmc.S
#   2005/03/08 11:15:55-08:00 willy@parisc-linux.org +12 -24
#   PA-RISC assembler cleanups and fixes
# 
# arch/parisc/kernel/head.S
#   2005/03/08 11:15:55-08:00 willy@parisc-linux.org +19 -24
#   PA-RISC assembler cleanups and fixes
# 
# arch/parisc/kernel/entry.S
#   2005/03/08 11:15:54-08:00 willy@parisc-linux.org +14 -26
#   PA-RISC assembler cleanups and fixes
# 
# ChangeSet
#   2005/03/09 18:55:51+11:00 airlied@starflyer.(none) 
#   drm: fixup CREDITS and MAINTAINERS
#   
#   Add myself to MAINTAINERS for drm, and fixup my CREDITS.
#   
#   Signed-off-by: Dave Airlie <airlied@linux.ie>
# 
# MAINTAINERS
#   2005/03/09 18:55:42+11:00 airlied@starflyer.(none) +3 -1
#   drm: fixup CREDITS and MAINTAINERS
#   
#   Add myself to MAINTAINERS for drm, and fixup my CREDITS.
#   
#   Signed-off-by: Dave Airlie <airlied@linux.ie>
# 
# CREDITS
#   2005/03/09 18:55:42+11:00 airlied@starflyer.(none) +3 -2
#   drm: fixup CREDITS and MAINTAINERS
#   
#   Add myself to MAINTAINERS for drm, and fixup my CREDITS.
#   
#   Signed-off-by: Dave Airlie <airlied@linux.ie>
# 
# ChangeSet
#   2005/03/08 19:40:52-08:00 davem@northbeach.davemloft.net 
#   Merge northbeach.davemloft.net:/home/davem/src/BK/sparcwork-2.6
#   into northbeach.davemloft.net:/home/davem/src/BK/sparc-2.6
# 
# drivers/media/video/bttvp.h
#   2005/03/08 19:40:45-08:00 davem@northbeach.davemloft.net +0 -0
#   Auto merged
# 
# ChangeSet
#   2005/03/08 19:17:53-08:00 davem@northbeach.davemloft.net 
#   [SPARC64]: Fix inline assembler in init_irqwork_curcpu().
#   
#   'tmp' cannot be a global register, because we are going
#   into the interrupt globals by writing to pstate.
#   Since we did not specify any particular register, gcc
#   could use anything, and in fact because of this I am
#   surprised we did not hit this bug earlier.
#   
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# arch/sparc64/kernel/irq.c
#   2005/03/08 19:16:31-08:00 davem@northbeach.davemloft.net +1 -1
#   [SPARC64]: Fix inline assembler in init_irqwork_curcpu().
# 
# ChangeSet
#   2005/03/08 17:02:18-08:00 davem@northbeach.davemloft.net 
#   [SCSI_ACARD]: Eliminate bogus virt_to_bus() call in atp870u.c
#   
#   prdaddr is set by the pci_alloc_consistent() call to portably
#   specify the DMA address.  There is no need to recompute it
#   again using the deprecated virt_to_bus() on the pointer returned
#   from pci_alloc_consistent().
#   
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# drivers/scsi/atp870u.c
#   2005/03/08 17:01:14-08:00 davem@northbeach.davemloft.net +0 -4
#   [SCSI_ACARD]: Eliminate bogus virt_to_bus() call in atp870u.c
# 
# ChangeSet
#   2005/03/08 16:56:36-08:00 davem@northbeach.davemloft.net 
#   [AFS]: Push module_{init,exit}() after function definitions.
#   
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# fs/afs/main.c
#   2005/03/08 16:56:12-08:00 davem@northbeach.davemloft.net +7 -10
#   [AFS]: Push module_{init,exit}() after function definitions.
# 
# ChangeSet
#   2005/03/08 16:54:08-08:00 davem@northbeach.davemloft.net 
#   [RXRPC]: Push module_{init,exit}() after function definitions.
#   
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/rxrpc/main.c
#   2005/03/08 16:53:44-08:00 davem@northbeach.davemloft.net +5 -7
#   [RXRPC]: Push module_{init,exit}() after function definitions.
# 
# ChangeSet
#   2005/03/08 16:50:31-08:00 davem@northbeach.davemloft.net 
#   [BTTV]: Declare bttvs[] array after struct layout.
#   
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# drivers/media/video/bttvp.h
#   2005/03/08 16:50:03-08:00 davem@northbeach.davemloft.net +1 -1
#   [BTTV]: Declare bttvs[] array after struct layout.
# 
# ChangeSet
#   2005/03/08 16:26:54-08:00 gregkh@suse.de 
#   Merge suse.de:/home/greg/linux/BK/bleed-2.6
#   into suse.de:/home/greg/linux/BK/usb-2.6
# 
# include/linux/pci_ids.h
#   2005/03/08 16:26:50-08:00 gregkh@suse.de +0 -0
#   Auto merged
# 
# include/linux/compat_ioctl.h
#   2005/03/08 16:26:50-08:00 gregkh@suse.de +0 -0
#   Auto merged
# 
# fs/compat_ioctl.c
#   2005/03/08 16:26:50-08:00 gregkh@suse.de +0 -0
#   Auto merged
# 
# MAINTAINERS
#   2005/03/08 16:26:50-08:00 gregkh@suse.de +0 -0
#   Auto merged
# 
# CREDITS
#   2005/03/08 16:26:50-08:00 gregkh@suse.de +0 -0
#   Auto merged
# 
# ChangeSet
#   2005/03/08 23:44:06+00:00 tony@com.rmk.(none) 
#   [ARM PATCH] 2451/1: OMAP 32KHz timer and 64-bit sched_clock, take 3
#   
#   Patch from Tony Lindgren
#   
#   This patch adds support for 32k timer on OMAP 16xx, and 64-bit
#   sched clock to the MPU timer.
#   This is an update version of ARM patch 2337/1. The 32k timer
#   modulo code has been left out, and the dynamic tick (VST) timer
#   will be submitted in a separate patch.
#   
#   Signed-off-by: Tony Lindgren
#   Signed-off-by: Russell King
# 
# arch/arm/mach-omap/time.c
#   2005/02/03 02:17:13+00:00 tony@com.rmk.(none) +204 -2
#   [PATCH] 2451/1: OMAP 32KHz timer and 64-bit sched_clock, take 3
# 
# arch/arm/mach-omap/Kconfig
#   2005/02/03 02:17:13+00:00 tony@com.rmk.(none) +32 -0
#   [PATCH] 2451/1: OMAP 32KHz timer and 64-bit sched_clock, take 3
# 
# ChangeSet
#   2005/03/08 23:25:46+00:00 rmk@flint.arm.linux.org.uk 
#   [ARM] Fix build error in rtctime.c
#   
#   Oops, it broke.  Glue the bits back together, replacing yrs with
#   tm->tm_year + 1900.
#   
#   I will not merge untested changes into Linus' tree.
#   I will not merge untested changes into Linus' tree.
#   I will not merge untested changes into Linus' tree.
#   I will not ...
#   
#   Signed-off-by: Russell King <rmk@arm.linux.org.uk>
# 
# arch/arm/common/rtctime.c
#   2005/03/08 23:19:23+00:00 rmk@flint.arm.linux.org.uk +1 -1
#   Replace yrs with tm->tm_year + 1900
# 
# ChangeSet
#   2005/03/08 22:47:59+00:00 rpurdie@net.rmk.(none) 
#   [ARM PATCH] 2522/1: Sharp SCOOP - Add mutliple device support
#   
#   Patch from Richard Purdie
#   
#   Sharp SCOOP: Devices with multiple scoop interfaces are now
#   available so:
#   * add support for mutliple device support to the driver
#   * Update corgi, collie and poodle to share the scoop
#     device structure so a device can be selected in drivers
#   * Update drivers to use the device structures
#   
#   Signed-off-by: Richard Purdie
#   Signed-off-by: Russell King
# 
# include/asm-arm/hardware/scoop.h
#   2005/03/06 16:52:27+00:00 rpurdie@net.rmk.(none) +5 -5
#   [PATCH] 2522/1: Sharp SCOOP - Add mutliple device support
# 
# include/asm-arm/arch-pxa/corgi.h
#   2005/03/06 20:23:51+00:00 rpurdie@net.rmk.(none) +4 -0
#   [PATCH] 2522/1: Sharp SCOOP - Add mutliple device support
# 
# drivers/video/backlight/corgi_bl.c
#   2005/03/06 20:23:52+00:00 rpurdie@net.rmk.(none) +2 -2
#   [PATCH] 2522/1: Sharp SCOOP - Add mutliple device support
# 
# drivers/pcmcia/pxa2xx_sharpsl.c
#   2005/03/06 16:52:27+00:00 rpurdie@net.rmk.(none) +20 -20
#   [PATCH] 2522/1: Sharp SCOOP - Add mutliple device support
# 
# arch/arm/mach-sa1100/collie.c
#   2005/03/06 20:25:11+00:00 rpurdie@net.rmk.(none) +1 -1
#   [PATCH] 2522/1: Sharp SCOOP - Add mutliple device support
# 
# arch/arm/mach-pxa/poodle.c
#   2005/03/06 20:25:13+00:00 rpurdie@net.rmk.(none) +1 -1
#   [PATCH] 2522/1: Sharp SCOOP - Add mutliple device support
# 
# arch/arm/mach-pxa/corgi.c
#   2005/03/06 20:23:56+00:00 rpurdie@net.rmk.(none) +1 -1
#   [PATCH] 2522/1: Sharp SCOOP - Add mutliple device support
# 
# arch/arm/common/scoop.c
#   2005/03/05 23:21:53+00:00 rpurdie@net.rmk.(none) +79 -37
#   [PATCH] 2522/1: Sharp SCOOP - Add mutliple device support
# 
# ChangeSet
#   2005/03/08 22:37:20+00:00 buytenh@org.rmk.(none) 
#   [ARM PATCH] 2517/1: more ixp2000 typo fixes
#   
#   Patch from Lennert Buytenhek
#   
#   Another round of ixp2000 typo fixes.
#   
#   Signed-off-by: Lennert Buytenhek
#   Signed-off-by: Russell King
# 
# include/asm-arm/arch-ixp2000/platform.h
#   2005/03/04 20:34:53+00:00 buytenh@org.rmk.(none) +2 -2
#   [PATCH] 2517/1: more ixp2000 typo fixes
# 
# include/asm-arm/arch-ixp2000/ixdp2x01.h
#   2005/03/04 20:34:53+00:00 buytenh@org.rmk.(none) +1 -1
#   [PATCH] 2517/1: more ixp2000 typo fixes
# 
# include/asm-arm/arch-ixp2000/io.h
#   2005/03/04 20:34:53+00:00 buytenh@org.rmk.(none) +1 -1
#   [PATCH] 2517/1: more ixp2000 typo fixes
# 
# arch/arm/mach-ixp2000/ixdp2x01.c
#   2005/03/02 12:41:08+00:00 buytenh@org.rmk.(none) +1 -1
#   [PATCH] 2517/1: more ixp2000 typo fixes
# 
# arch/arm/mach-ixp2000/enp2611.c
#   2005/03/02 12:41:38+00:00 buytenh@org.rmk.(none) +1 -1
#   [PATCH] 2517/1: more ixp2000 typo fixes
# 
# Documentation/arm/IXP2000
#   2005/03/02 12:41:08+00:00 buytenh@org.rmk.(none) +1 -1
#   [PATCH] 2517/1: more ixp2000 typo fixes
# 
# ChangeSet
#   2005/03/08 22:13:51+00:00 rmk@flint.arm.linux.org.uk 
#   [SERIAL] Add PCI state save/restore and PCI power state management
#   
#   Resolve a problem where a Sony Ericsson GC79 Cardbus device was not
#   being correctly resumed across a S3 suspend, as reported by Hendrik
#   Hoeth.
#   
#   Signed-off-by: Russell King <rmk@arm.linux.org.uk>
# 
# drivers/serial/8250_pci.c
#   2005/03/08 22:08:47+00:00 rmk@flint.arm.linux.org.uk +11 -1
#   Add PCI state save/restore and PCI power state management.
# 
# ChangeSet
#   2005/03/08 15:49:23-05:00 jgarzik@pobox.com 
#   Merge pobox.com:/garz/repo/netdev-2.6/viro-isa-ectomy
#   into pobox.com:/garz/repo/net-drivers-2.6
# 
# drivers/net/ewrk3.c
#   2005/03/08 15:49:18-05:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# ChangeSet
#   2005/03/08 15:46:55-05:00 jgarzik@pobox.com 
#   Merge pobox.com:/garz/repo/linux-2.6
#   into pobox.com:/garz/repo/netdev-2.6/janitor
# 
# drivers/net/via-velocity.c
#   2005/03/08 15:46:51-05:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# drivers/net/via-rhine.c
#   2005/03/08 15:46:51-05:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# drivers/net/s2io.c
#   2005/03/08 15:46:51-05:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# drivers/net/pppoe.c
#   2005/03/08 15:46:51-05:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# drivers/net/ioc3-eth.c
#   2005/03/08 15:46:51-05:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# drivers/net/eepro100.c
#   2005/03/08 15:46:51-05:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# drivers/net/bonding/bond_alb.c
#   2005/03/08 15:46:51-05:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# drivers/net/amd8111e.c
#   2005/03/08 15:46:51-05:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# ChangeSet
#   2005/03/08 11:27:48-08:00 paulus@samba.org 
#   [PATCH] ppc64: fix eeh.h compile warnings
#   
#   This patch is from Nathan Lynch <ntl@pobox.com>.
#   
#   Use static inlines instead of #defines for stub functions when
#   CONFIG_EEH=n, to eliminate "statement with no effect" warnings with
#   some toolchains.
#   
#   Signed-off-by: Nathan Lynch <ntl@pobox.com>
#   Signed-off-by: Paul Mackerras <paulus@samba.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/asm-ppc64/eeh.h
#   2005/03/02 17:39:25-08:00 paulus@samba.org +22 -9
#   ppc64: fix eeh.h compile warnings
# 
# ChangeSet
#   2005/03/08 11:27:33-08:00 paulus@samba.org 
#   [PATCH] ppc64: update irq affinity mask when migrating irqs
#   
#   This patch is from Nathan Lynch <ntl@pobox.com>.
#   
#   When offlining a cpu, any device interrupts which are bound to the cpu
#   have their affinity forcibly reset to all cpus (the default).
#   However, the value in /proc/irq/XXX/smp_affinity remains unchanged.
#   Since we're doing this while all the other cpus are stopped, it should
#   be safe to just call desc->handler->set_affinity and manually update
#   the irq_affinity array.
#   
#   
#   Signed-off-by: Nathan Lynch <ntl@pobox.com>
#   Signed-off-by: Paul Mackerras <paulus@samba.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/ppc64/kernel/xics.c
#   2005/03/06 19:52:08-08:00 paulus@samba.org +2 -9
#   ppc64: update irq affinity mask when migrating irqs
# 
# ChangeSet
#   2005/03/08 11:27:18-08:00 paulus@samba.org 
#   [PATCH] ppc64: call idle_task_exit with irqs disabled
#   
#   This patch is from Nathan Lynch <ntl@pobox.com>.
#   
#   Seeing this very occasionally during cpu hotplug testing:
#   
#    Badness in slb_flush_and_rebolt at arch/ppc64/mm/slb.c:52
#    Call Trace:
#    [c0000000ef0efbe0] [c0000000000127a0] .__switch_to+0xa4/0xf0 (unreliable)
#    [c0000000ef0efc80] [c000000000050178] .idle_task_exit+0xbc/0x15c
#    [c0000000ef0efd10] [c00000000000d108] .cpu_die+0x18/0x68
#    [c0000000ef0efd90] [c00000000001023c] .dedicated_idle+0x1fc/0x254
#    [c0000000ef0efe80] [c00000000000fc80] .cpu_idle+0x3c/0x54
#    [c0000000ef0eff00] [c00000000003aa90] .start_secondary+0x108/0x148
#    [c0000000ef0eff90] [c00000000000bd28] .enable_64b_mode+0x0/0x28
#   
#   idle_task_exit can result in a call to slb_flush_and_rebolt, which
#   must not be called with interrupts enabled.  Make the call with
#   interrupts disabled.
#   
#   
#   Signed-off-by: Nathan Lynch <ntl@pobox.com>
#   Signed-off-by: Paul Mackerras <paulus@samba.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/ppc64/kernel/pSeries_setup.c
#   2005/03/06 20:15:22-08:00 paulus@samba.org +1 -1
#   ppc64: call idle_task_exit with irqs disabled
# 
# ChangeSet
#   2005/03/08 11:27:02-08:00 paulus@samba.org 
#   [PATCH] ppc64: error code cleanups rpa(php,dlpar)
#   
#   This patch is from John Rose <johnrose@austin.ibm.com>
#   
#   This patch changes the RPA PCI Hotplug and DLPAR modules to use more
#   conventional error values for return codes.  The goal is to make failure
#   conditions obvious in the wrapper functions and in the caller code.
#   
#   Signed-off-by: John Rose <johnrose@austin.ibm.com>
#   Signed-off-by: Paul Mackerras <paulus@samba.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/pci/hotplug/rpaphp_core.c
#   2005/03/07 15:52:20-08:00 paulus@samba.org +3 -3
#   ppc64: error code cleanups rpa(php,dlpar)
# 
# drivers/pci/hotplug/rpaphp.h
#   2005/03/07 15:52:20-08:00 paulus@samba.org +0 -5
#   ppc64: error code cleanups rpa(php,dlpar)
# 
# drivers/pci/hotplug/rpadlpar_core.c
#   2005/03/07 15:53:02-08:00 paulus@samba.org +5 -5
#   ppc64: error code cleanups rpa(php,dlpar)
# 
# ChangeSet
#   2005/03/08 11:26:46-08:00 paulus@samba.org 
#   [PATCH] ppc64: error code cleanups for rtas wrappers
#   
#   This patch is from John Rose <johnrose@austin.ibm.com>
#   
#   This patch changes the rtas wrapper functions in rtas.c to map RTAS
#   failure codes to conventional error values.  The goal is to make
#   failure conditions obvious in the wrapper functions and in the caller
#   code.
#   
#   Signed-off-by: John Rose <johnrose@austin.ibm.com>
#   Signed-off-by: Paul Mackerras <paulus@samba.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/asm-ppc64/rtas.h
#   2005/03/02 12:50:33-08:00 paulus@samba.org +0 -3
#   ppc64: error code cleanups for rtas wrappers
# 
# arch/ppc64/kernel/xics.c
#   2005/03/02 12:50:33-08:00 paulus@samba.org +1 -1
#   ppc64: error code cleanups for rtas wrappers
# 
# arch/ppc64/kernel/rtasd.c
#   2005/03/02 12:50:33-08:00 paulus@samba.org +1 -1
#   ppc64: error code cleanups for rtas wrappers
# 
# arch/ppc64/kernel/rtas.c
#   2005/03/02 12:50:33-08:00 paulus@samba.org +48 -12
#   ppc64: error code cleanups for rtas wrappers
# 
# arch/ppc64/kernel/pSeries_smp.c
#   2005/03/02 12:50:33-08:00 paulus@samba.org +1 -1
#   ppc64: error code cleanups for rtas wrappers
# 
# ChangeSet
#   2005/03/08 11:23:57-08:00 sfr@canb.auug.org.au 
#   [PATCH] ppc64: "invert" dma mapping routines
#   
#   This patch "inverts" the PPC64 dma mapping routines so that the pci_ and
#   vio_ ... routines are implemented in terms of the dma_ ... routines (the
#   vio_ routines disappear anyway as noone uses them directly any more).
#   
#   The most noticable change after this patch is applied will be that the
#   flags passed to dma_alloc_coherent will now be honoured (whereas they were
#   previously silently ignored since we used to just call
#   pci_alloc_consistent).
#   
#   Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/asm-ppc64/vio.h
#   2005/02/06 20:42:37-08:00 sfr@canb.auug.org.au +1 -26
#   ppc64: "invert" dma mapping routines
# 
# include/asm-ppc64/pci.h
#   2005/03/06 15:24:32-08:00 sfr@canb.auug.org.au +6 -120
#   ppc64: "invert" dma mapping routines
# 
# include/asm-ppc64/iommu.h
#   2005/02/06 20:02:01-08:00 sfr@canb.auug.org.au +3 -3
#   ppc64: "invert" dma mapping routines
# 
# include/asm-ppc64/dma-mapping.h
#   2005/02/06 19:38:01-08:00 sfr@canb.auug.org.au +20 -0
#   ppc64: "invert" dma mapping routines
# 
# arch/ppc64/kernel/vio.c
#   2005/02/06 20:45:00-08:00 sfr@canb.auug.org.au +34 -21
#   ppc64: "invert" dma mapping routines
# 
# arch/ppc64/kernel/pci_iommu.c
#   2005/02/06 20:10:05-08:00 sfr@canb.auug.org.au +30 -25
#   ppc64: "invert" dma mapping routines
# 
# arch/ppc64/kernel/pci_direct_iommu.c
#   2005/02/06 21:00:47-08:00 sfr@canb.auug.org.au +20 -14
#   ppc64: "invert" dma mapping routines
# 
# arch/ppc64/kernel/pci.c
#   2005/03/06 15:23:14-08:00 sfr@canb.auug.org.au +1 -1
#   ppc64: "invert" dma mapping routines
# 
# arch/ppc64/kernel/iommu.c
#   2005/02/06 20:00:06-08:00 sfr@canb.auug.org.au +4 -4
#   ppc64: "invert" dma mapping routines
# 
# arch/ppc64/kernel/dma.c
#   2005/02/06 22:47:41-08:00 sfr@canb.auug.org.au +47 -53
#   ppc64: "invert" dma mapping routines
# 
# ChangeSet
#   2005/03/08 10:49:39-08:00 andrea@suse.de 
#   [PATCH] remove vmalloc guard page knowledge from arch code
#   
#   Now that we cleaned up the guard page handling in vmalloc, we have to
#   remove the p-PAGE_SIZE hack that was put in there for the original guard
#   page handling.  This also removes some spurious tab.
#   
#   Signed-off-by: Andrea Arcangeli <andrea@suse.de>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/x86_64/mm/ioremap.c
#   2005/03/08 09:28:18-08:00 andrea@suse.de +2 -2
#   remove vmalloc guard page knowledge from arch code
# 
# arch/i386/mm/ioremap.c
#   2005/03/08 09:27:41-08:00 andrea@suse.de +2 -2
#   remove vmalloc guard page knowledge from arch code
# 
# ChangeSet
#   2005/03/08 10:18:29-08:00 roland@redhat.com 
#   [PATCH] set RLIMIT_SIGPENDING limit based on RLIMIT_NPROC
#   
#   While looking into the issues Jeremy had with the RLIMIT_SIGPENDING limit,
#   it occurred to me that the normal setting of this limit is bizarrely low.
#   The initial hard limit setting (MAX_SIGPENDING) was taken from the old
#   max_queued_signals parameter, which was for the entire system in aggregate.
#   
#   But even as a per-user limit, the 1024 value is incongruously low for this.
#    On my machine, RLIMIT_NPROC allows me 8192 processes, but only 1024 queued
#   signals, i.e.  fewer even than one pending signal in each process.  (To me,
#   this really puts in doubt the sensibility of using a per-user limit for
#   this rather than a per-process one, i.e.  counted in sighand_struct or
#   signal_struct, which could have a much smaller reasonable value.  I don't
#   recall the rationale for making this new limit per-user in the first
#   place.)
#   
#   This patch sets the default RLIMIT_SIGPENDING limit at boot time, using the
#   calculation that decides the default RLIMIT_NPROC limit.  This uses the
#   same value for those two limits, which I think is still pretty conservative
#   on the RLIMIT_SIGPENDING value.
#   
#   Signed-off-by: Roland McGrath <roland@redhat.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# kernel/fork.c
#   2005/03/07 20:41:54-08:00 roland@redhat.com +2 -0
#   set RLIMIT_SIGPENDING limit based on RLIMIT_NPROC
# 
# include/linux/signal.h
#   2005/03/07 20:41:53-08:00 roland@redhat.com +0 -2
#   set RLIMIT_SIGPENDING limit based on RLIMIT_NPROC
# 
# include/asm-generic/resource.h
#   2005/03/07 20:41:53-08:00 roland@redhat.com +1 -1
#   set RLIMIT_SIGPENDING limit based on RLIMIT_NPROC
# 
# ChangeSet
#   2005/03/08 10:18:14-08:00 roland@redhat.com 
#   [PATCH] show RLIMIT_SIGPENDING usage in /proc/PID/status
#   
#   Jeremy mentioned the aggravation of not being able to tell when your
#   processes are using up signal queue entries and hitting the
#   RLIMIT_SIGPENDING limit.  This patch adds a line to /proc/PID/status
#   showing how many queue items are in use, and allowed, for your uid.
#   
#   I can certainly see the appeal of having a display of the number of queued
#   items specific to each process, and even the items within the process
#   broken down per signal number.  However, those are not things that are
#   directly counted, and ascertaining them requires iterating through the
#   queue.  This patch instead gives what can be readily determined in constant
#   time using the accounting already done.  I'm not sure something more
#   complex is warranted just to facilitate one particular debugging need.
#   With this, you can see quickly that this particular problem has come up.
#   Then examination of each process's SigPnd/ShdPnd lines ought to give you an
#   indication of which processes have any queued RT signals sitting around for
#   a long time, and you can then attack those programs directly, though there
#   is no way after the fact to determine how many queued signals with the same
#   number a given process has (short of killing it and seeing the usage drop).
#   
#   Note you may still have a mystery if the leaking programs are not leaving
#   pending RT signals queued, but rather preallocating queue items via
#   timer_create.  That usage is not readily apparent in any /proc information.
#   
#   Signed-off-by: Roland McGrath <roland@redhat.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# fs/proc/array.c
#   2005/03/07 20:41:53-08:00 roland@redhat.com +5 -0
#   show RLIMIT_SIGPENDING usage in /proc/PID/status
# 
# ChangeSet
#   2005/03/08 10:18:00-08:00 roland@redhat.com 
#   [PATCH] override RLIMIT_SIGPENDING for non-RT signals
#   
#   I can read POSIX to say that the siginfo_t data must be available when
#   `kill' was used, as well.  This patch makes it allocate the siginfo_t, even
#   when that exceeds {RLIMIT_SIGPENDING}, for any non-RT signal (< SIGRTMIN)
#   not sent by sigqueue (actually, any signal that couldn't have been faked by
#   a sigqueue call).  Of course, in an extreme memory shortage situation, you
#   are SOL and violate POSIX a little before you die horribly from being out
#   of memory anyway.
#   
#   The LEGACY_QUEUE logic already ensures that, for non-RT signals, at most
#   one is ever on the queue.  So there really is no risk at all of unbounded
#   resource consumption; the usage can reach {RLIMIT_SIGPENDING} + 31, is all.
#   
#   It's already the case that the limit can be exceeded by (in theory) up to
#   {RLIMIT_NPROC}-1 in race conditions because the bump and the limit check
#   are not atomic.  (Obviously you can only get anywhere near that many with
#   assloads of preemption, but exceeding it by a few is not too unlikely.)
#   This patch also fixes that accounting so that it should not be possible to
#   exceed {RLIMIT_SIGPENDING} + SIGRTMIN-1 queue items per user in races.
#   
#   Signed-off-by: Roland McGrath <roland@redhat.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# kernel/signal.c
#   2005/03/07 20:41:53-08:00 roland@redhat.com +12 -6
#   override RLIMIT_SIGPENDING for non-RT signals
# 
# ChangeSet
#   2005/03/08 10:17:44-08:00 roland@redhat.com 
#   [PATCH] make RLIMIT_CPU/SIGXCPU per-process
#   
#   POSIX requires that the RLIMIT_CPU resource limit that generates SIGXCPU be
#   counted on a per-process basis.  Currently, Linux implements this for
#   individual threads.  This patch fixes the semantics to conform with POSIX.
#   
#   The essential machinery for the process CPU limit is is tied into the new
#   posix-timers code for process CPU clocks and timers.
#   
#   Signed-off-by: Roland McGrath <roland@redhat.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# security/selinux/hooks.c
#   2005/03/07 20:41:53-08:00 roland@redhat.com +7 -0
#   make RLIMIT_CPU/SIGXCPU per-process
# 
# kernel/sys.c
#   2005/03/07 20:41:53-08:00 roland@redhat.com +15 -0
#   make RLIMIT_CPU/SIGXCPU per-process
# 
# kernel/sched.c
#   2005/03/07 20:41:53-08:00 roland@redhat.com +0 -32
#   make RLIMIT_CPU/SIGXCPU per-process
# 
# kernel/posix-cpu-timers.c
#   2005/03/07 20:41:53-08:00 roland@redhat.com +56 -9
#   make RLIMIT_CPU/SIGXCPU per-process
# 
# kernel/fork.c
#   2005/03/07 21:14:14-08:00 roland@redhat.com +10 -0
#   make RLIMIT_CPU/SIGXCPU per-process
# 
# ChangeSet
#   2005/03/08 10:17:29-08:00 roland@redhat.com 
#   [PATCH] make ITIMER_PROF, ITIMER_VIRTUAL per-process
#   
#   POSIX requires that setitimer, getitimer, and alarm work on a per-process
#   basis.  Currently, Linux implements these for individual threads.  This patch
#   fixes these semantics for the ITIMER_PROF timer (which generates SIGPROF) and
#   the ITIMER_VIRTUAL timer (which generates SIGVTALRM), making them shared by
#   all threads in a process (thread group).  This patch should be applied after
#   the one that fixes ITIMER_REAL.
#   
#   The essential machinery for these timers is tied into the new posix-timers
#   code for process CPU clocks and timers.  This patch requires the cputimers
#   patch and its dependencies.
#   
#   Signed-off-by: Roland McGrath <roland@redhat.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# kernel/signal.c
#   2005/03/07 21:14:14-08:00 roland@redhat.com +1 -1
#   make ITIMER_PROF, ITIMER_VIRTUAL per-process
# 
# kernel/sched.c
#   2005/03/07 21:14:14-08:00 roland@redhat.com +2 -45
#   make ITIMER_PROF, ITIMER_VIRTUAL per-process
# 
# kernel/posix-cpu-timers.c
#   2005/03/07 21:14:14-08:00 roland@redhat.com +138 -19
#   make ITIMER_PROF, ITIMER_VIRTUAL per-process
# 
# kernel/itimer.c
#   2005/03/07 20:41:53-08:00 roland@redhat.com +119 -57
#   make ITIMER_PROF, ITIMER_VIRTUAL per-process
# 
# kernel/fork.c
#   2005/03/07 21:14:14-08:00 roland@redhat.com +10 -6
#   make ITIMER_PROF, ITIMER_VIRTUAL per-process
# 
# kernel/exit.c
#   2005/03/07 20:41:53-08:00 roland@redhat.com +0 -3
#   make ITIMER_PROF, ITIMER_VIRTUAL per-process
# 
# include/linux/signal.h
#   2005/03/07 21:14:14-08:00 roland@redhat.com +1 -0
#   make ITIMER_PROF, ITIMER_VIRTUAL per-process
# 
# include/linux/sched.h
#   2005/03/07 20:41:53-08:00 roland@redhat.com +4 -2
#   make ITIMER_PROF, ITIMER_VIRTUAL per-process
# 
# include/linux/posix-timers.h
#   2005/03/07 20:41:53-08:00 roland@redhat.com +2 -0
#   make ITIMER_PROF, ITIMER_VIRTUAL per-process
# 
# ChangeSet
#   2005/03/08 10:17:13-08:00 roland@redhat.com 
#   [PATCH] make ITIMER_REAL per-process
#   
#   POSIX requires that setitimer, getitimer, and alarm work on a per-process
#   basis.  Currently, Linux implements these for individual threads.  This patch
#   fixes these semantics for the ITIMER_REAL timer (which generates SIGALRM),
#   making it shared by all threads in a process (thread group).
#   
#   Signed-off-by: Roland McGrath <roland@redhat.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# kernel/itimer.c
#   2005/03/07 21:14:15-08:00 roland@redhat.com +72 -43
#   make ITIMER_REAL per-process
# 
# kernel/fork.c
#   2005/03/07 21:14:15-08:00 roland@redhat.com +5 -4
#   make ITIMER_REAL per-process
# 
# kernel/exit.c
#   2005/03/07 21:14:15-08:00 roland@redhat.com +3 -2
#   make ITIMER_REAL per-process
# 
# include/linux/sched.h
#   2005/03/07 21:14:15-08:00 roland@redhat.com +4 -2
#   make ITIMER_REAL per-process
# 
# include/linux/init_task.h
#   2005/03/07 20:41:53-08:00 roland@redhat.com +0 -3
#   make ITIMER_REAL per-process
# 
# fs/proc/array.c
#   2005/03/07 21:14:14-08:00 roland@redhat.com +3 -1
#   make ITIMER_REAL per-process
# 
# ChangeSet
#   2005/03/08 10:16:57-08:00 roland@redhat.com 
#   [PATCH] PANIC in check_process_timers()
#   
#   It was intended that such things would not be possible because getting into
#   that code in the first place should be ruled out while exiting.  That
#   removes the requirement for any special case check in the common path.
#   But, it was done too late since it hadn't occurred to me that ->live going
#   zero itself created a problem.
#   
#   Signed-off-by: Roland McGrath <roland@redhat.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# kernel/exit.c
#   2005/03/07 21:14:15-08:00 roland@redhat.com +8 -7
#   PANIC in check_process_timers()
# 
# ChangeSet
#   2005/03/08 10:16:42-08:00 roland@redhat.com 
#   [PATCH] posix-timers: CPU clock support for POSIX timers
#   
#   POSIX requires that when you claim _POSIX_CPUTIME and _POSIX_THREAD_CPUTIME,
#   not only the clock_* calls but also timer_* calls must support the thread and
#   process CPU time clocks.  This patch provides that support, building on my
#   recent additions to support these clocks in the POSIX clock_* interfaces.
#   This patch will not work without those changes, as well as the patch fixing
#   the timer lock-siglock deadlock problem.
#   
#   The apparent pervasive changes to posix-timers.c are simply that some fields
#   of struct k_itimer have changed name and moved into a union.  This was
#   appropriate since the data structures required for the existing real-time
#   timer support and for the new thread/process CPU-time timers are quite
#   different.
#   
#   The glibc patches to support CPU time clocks using the new kernel support is
#   in http://people.redhat.com/roland/glibc/kernel-cpuclocks.patch, and that
#   includes tests for the timer support (if you build glibc with NPTL).
#   From: Christoph Lameter <clameter@sgi.com>
#   
#     Your patch breaks the mmtimer driver because it used k_itimer values for
#     its own purposes.  Here is a fix by defining an additional structure in
#     k_itimer (same approach for mmtimer as the cpu timers):
#   From: Roland McGrath <roland@redhat.com>
#   
#   Fix bug identified by Alexander Nyberg <alexn@dsv.su.se>
#   
#   > The problem arises from code touching the union in alloc_posix_timer()
#   > which makes firing go non-zero. When firing is checked in
#   > posix_cpu_timer_set() it will be positive causing an infinite loop.
#   >
#   > So either the below fix or preferably move the INIT_LIST_HEAD(x) from
#   > alloc_posix_timer() to somewhere later where it doesn't disturb the other
#   > union members.
#   
#   Thanks for finding this problem.  The latter is what I think is the right
#   solution.  This patch does that, and also removes some superfluous rezeroing.
#   
#   Signed-off-by: Roland McGrath <roland@redhat.com>
#   Signed-off-by: Christoph Lameter <clameter@sgi.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# kernel/timer.c
#   2005/03/07 20:41:52-08:00 roland@redhat.com +2 -0
#   posix-timers: CPU clock support for POSIX timers
# 
# kernel/signal.c
#   2005/03/07 21:14:15-08:00 roland@redhat.com +3 -0
#   posix-timers: CPU clock support for POSIX timers
# 
# kernel/posix-timers.c
#   2005/03/07 20:41:52-08:00 roland@redhat.com +55 -56
#   posix-timers: CPU clock support for POSIX timers
# 
# kernel/posix-cpu-timers.c
#   2005/03/07 21:14:15-08:00 roland@redhat.com +1096 -19
#   posix-timers: CPU clock support for POSIX timers
# 
# kernel/fork.c
#   2005/03/07 21:14:15-08:00 roland@redhat.com +20 -0
#   posix-timers: CPU clock support for POSIX timers
# 
# kernel/exit.c
#   2005/03/07 21:14:15-08:00 roland@redhat.com +3 -0
#   posix-timers: CPU clock support for POSIX timers
# 
# include/linux/sched.h
#   2005/03/07 21:14:15-08:00 roland@redhat.com +7 -0
#   posix-timers: CPU clock support for POSIX timers
# 
# include/linux/posix-timers.h
#   2005/03/07 21:14:15-08:00 roland@redhat.com +41 -10
#   posix-timers: CPU clock support for POSIX timers
# 
# include/linux/init_task.h
#   2005/03/07 21:14:15-08:00 roland@redhat.com +9 -0
#   posix-timers: CPU clock support for POSIX timers
# 
# drivers/char/mmtimer.c
#   2005/03/07 20:41:52-08:00 roland@redhat.com +20 -20
#   posix-timers: CPU clock support for POSIX timers
# 
# ChangeSet
#   2005/03/08 10:16:26-08:00 roland@redhat.com 
#   [PATCH] posix-timers: fix posix-timers signals lock order
#   
#   The posix-timers code establishes the locking order that k_itimer locks are
#   outside siglocks.  However, when the signal code calls back into the
#   posix-timers code to reload a timer after its signal is dequeued, it holds a
#   siglock while calling do_schedule_next_timer, which gets a timer lock.
#   
#   I'm not sure there is any deadlock scenario possible using the real-time POSIX
#   timers, because of the intricate arrangement of timer firing and resetting
#   synchronization.  But with the new CPU timers code, this deadlock pops up
#   right away.  Dropping the siglock here certainly doesn't hurt in the real-time
#   timer cases, and it really seems like the right thing here to keep the locking
#   details in the interface between signals and posix-timers code comprehensible.
#   
#   Signed-off-by: Roland McGrath <roland@redhat.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# kernel/signal.c
#   2005/03/07 21:14:15-08:00 roland@redhat.com +8 -0
#   posix-timers: fix posix-timers signals lock order
# 
# ChangeSet
#   2005/03/08 10:16:12-08:00 roland@redhat.com 
#   [PATCH] posix-timers: tidy up clock interfaces and  consolidate dispatch logic cleanup
#   
#   > We do need to do one or the other.  I assume the current indecision is
#   > pending some benchmarking work?
#   
#   That was more or less the idea.  But I kind of figured someone would just
#   tell me which one to do without actually doing any timings.  This patch
#   (applies after the cpuclocks patch) makes the one decision, to use
#   conditional branches rather than indirect calls in the common case.
#   That is consistent with what the old code did.  
#   
#   Signed-off-by: Roland McGrath <roland@redhat.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# kernel/posix-timers.c
#   2005/03/07 21:14:15-08:00 roland@redhat.com +11 -46
#   posix-timers: tidy up clock interfaces and  consolidate dispatch logic cleanup
# 
# ChangeSet
#   2005/03/08 10:15:56-08:00 roland@redhat.com 
#   [PATCH] posix-timers: high-resolution CPU clocks for POSIX clock_* syscalls
#   
#   This patch provides support for thread and process CPU time clocks in the
#   POSIX clock interface.  Both the existing utime and utime+stime information
#   (already available via getrusage et al) can be used, as well as a new
#   (potentially) more precise and accurate clock (which cannot distinguish user
#   from system time).  The clock used is that provided by the `sched_clock'
#   function already used internally by the scheduler.  This gives a way for
#   platforms to provide the highest-resolution CPU time tracking that is
#   available cheaply, and some already do so (such as x86 using TSC).  Because
#   this clock is already sampled internally by the scheduler, this new tracking
#   adds only the tiniest new overhead to accomplish the bookkeeping.
#   
#   Some notes:
#   
#   This allows per-thread clocks to be accessed only by other threads in the same
#   process.  The only POSIX calls that access these are defined only for
#   in-process use, and having this check is necessary for the userland
#   implementations of the POSIX clock functions to robustly refuse stale
#   clockid_t's in the face of potential PID reuse.
#   
#   This makes no constraint on who can see whose per-process clocks.  This
#   information is already available for the VIRT and PROF (i.e.  utime and stime)
#   information via /proc.  I am open to suggestions on if/how security
#   constraints on who can see whose clocks should be imposed.
#   
#   The SCHED clock information is now available only via clock_* syscalls.  This
#   means that per-thread information is not available outside the process. 
#   Perhaps /proc should show sched_time as well?  This would let ps et al show
#   this more-accurate information.
#   
#   When this code is merged, it will be supported in glibc.  I have written the
#   support and added some test programs for glibc, which are what I mainly used
#   to test the new kernel code.  You can get those here:
#   
#   	http://people.redhat.com/roland/glibc/kernel-cpuclocks.patch
#   
#   Signed-off-by: Roland McGrath <roland@redhat.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# kernel/signal.c
#   2005/03/07 21:14:16-08:00 roland@redhat.com +1 -0
#   posix-timers: high-resolution CPU clocks for POSIX clock_* syscalls
# 
# kernel/sched.c
#   2005/03/07 21:14:15-08:00 roland@redhat.com +32 -1
#   posix-timers: high-resolution CPU clocks for POSIX clock_* syscalls
# 
# kernel/posix-timers.c
#   2005/03/07 21:14:16-08:00 roland@redhat.com +7 -3
#   posix-timers: high-resolution CPU clocks for POSIX clock_* syscalls
# 
# kernel/posix-cpu-timers.c
#   2005/03/07 21:14:15-08:00 roland@redhat.com +288 -0
#   posix-timers: high-resolution CPU clocks for POSIX clock_* syscalls
# 
# kernel/fork.c
#   2005/03/07 21:14:15-08:00 roland@redhat.com +2 -0
#   posix-timers: high-resolution CPU clocks for POSIX clock_* syscalls
# 
# kernel/Makefile
#   2005/03/07 20:41:52-08:00 roland@redhat.com +1 -1
#   posix-timers: high-resolution CPU clocks for POSIX clock_* syscalls
# 
# include/linux/sched.h
#   2005/03/07 21:14:15-08:00 roland@redhat.com +10 -0
#   posix-timers: high-resolution CPU clocks for POSIX clock_* syscalls
# 
# include/linux/posix-timers.h
#   2005/03/07 21:14:15-08:00 roland@redhat.com +31 -1
#   posix-timers: high-resolution CPU clocks for POSIX clock_* syscalls
# 
# kernel/posix-cpu-timers.c
#   2005/03/07 21:14:15-08:00 roland@redhat.com +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/kernel/posix-cpu-timers.c
# 
# ChangeSet
#   2005/03/08 10:15:40-08:00 roland@redhat.com 
#   [PATCH] posix-timers: tidy up clock interfaces and consolidate dispatch logic
#   
#   This patch cleans up the posix-timers interfaces for defining clocks, and the
#   calls to them.  It fixes some sloppy types, adds a clockid_t parameter to the
#   calls that lacked it, and adds a function pointer that can be used for
#   clock_getres.  It further cleans up the posix-timers.c code using the k_clock
#   function pointers or default functions when no hooks are supplied,
#   consolidating repeated code into shared inline functions or macros.  This
#   paves the way for adding the CPU clock hooks.
#   
#   The mmtimer.c changes are untested, but obviously can't be wrong.  There
#   aren't any other struct k_clock definitions in the tree, but any others would
#   need to be updated for the function signature changes.
#   
#   Signed-off-by: Roland McGrath <roland@redhat.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# kernel/posix-timers.c
#   2005/03/07 21:14:16-08:00 roland@redhat.com +164 -91
#   posix-timers: tidy up clock interfaces and consolidate dispatch logic
# 
# include/linux/posix-timers.h
#   2005/03/07 21:14:16-08:00 roland@redhat.com +7 -7
#   posix-timers: tidy up clock interfaces and consolidate dispatch logic
# 
# drivers/char/mmtimer.c
#   2005/03/07 21:14:15-08:00 roland@redhat.com +2 -2
#   posix-timers: tidy up clock interfaces and consolidate dispatch logic
# 
# ChangeSet
#   2005/03/08 10:15:24-08:00 pmeda@akamai.com 
#   [PATCH] Speed up /proc/pid/maps
#   
#   This patch uses find_vma() to improve the read response of /proc/pid/maps. 
#   It attempts to make the liner scan instead of quadratic walk and utilise rb
#   tree.  Reading the file was doing sequential scan from the begining to file
#   position all the time, and taking a quite long time.
#   
#   The improvements came from f_version/m_version and resulting in mmap_cache
#   match.  Even if mmap_cache does not match, rb tree walk should be faster
#   than sequential walk.  First attempt was to put the state across read
#   system calls into private data.  Later got inspiration from wli's pid patch
#   using f_version in readdir of /proc.  Other advantage is, f_version will be
#   cleared automatically by lseek.
#   
#   The test program creates 32K maps and splits them into two(limited by
#   max_map_count sysctl) using mprotect(0).  After the patch, the read time
#   improves from many seconds to milliseconds, and does not grow superlinearly
#   with number of read calls.
#   
#   Help taken from Peter Swain in idea and testing.
#   
#   After the patch:
#   Reading /proc/self/maps:65528 time: 0 secs and   780728 usecs buf:4096 bytes:3811362
#   Reading /proc/self/maps:65528 time: 1 secs and   117573 usecs buf:1024 bytes:3866627
#   Reading /proc/self/maps:65528 time: 0 secs and   473459 usecs buf: 256 bytes:3866627
#   Reading /proc/self/maps:65528 time: 0 secs and   901288 usecs buf:  64 bytes:3866627
#   Reading /proc/self/maps:65528 time: 1 secs and   480185 usecs buf:  16 bytes:3866627
#   Reading /proc/self/maps:65528 time: 1 secs and   636268 usecs buf:   4 bytes:3866627
#   Reading /proc/self/maps:65528 time: 4 secs and   118327 usecs buf:   1 bytes:3866627
#   
#   Before the patch:
#   Reading /proc/self/maps:65528 time: 4 secs and   359556 usecs buf:4096 bytes:3866647
#   Reading /proc/self/maps:65528 time:16 secs and   218584 usecs buf:1024 bytes:3866688
#   Reading /proc/self/maps:65528 time:67 secs and   870200 usecs buf: 256 bytes:3866688
#   Reading /proc/self/maps:65528 time:255 secs and   186934 usecs buf:  64 bytes:3866688
#   Small reads never completed.
#   
#   Signed-off-by: Prasanna Meda <pmeda@akamai.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/linux/seq_file.h
#   2005/03/07 20:41:51-08:00 pmeda@akamai.com +1 -0
#   Speed up /proc/pid/maps
# 
# fs/seq_file.c
#   2005/03/07 20:41:51-08:00 pmeda@akamai.com +25 -0
#   Speed up /proc/pid/maps
# 
# fs/proc/task_mmu.c
#   2005/03/07 20:41:51-08:00 pmeda@akamai.com +51 -14
#   Speed up /proc/pid/maps
# 
# ChangeSet
#   2005/03/08 10:15:09-08:00 akpm@osdl.org 
#   [PATCH] lib/parser.o linkage fix
#   
#   It's possible to define .configs in which there are no references in vmlinux
#   to lib/parser.o.  So you cannot load any filesystem modules.
#   
#   Arrange for parser.o to be statically linked.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# lib/Makefile
#   2005/03/07 20:41:51-08:00 akpm@osdl.org +2 -2
#   lib/parser.o linkage fix
# 
# ChangeSet
#   2005/03/08 10:14:53-08:00 mpm@selenic.com 
#   [PATCH] random: Move syncookies to net/
#   
#   Move syncookie code off to networking land.
#   
#   Signed-off-by: Matt Mackall <mpm@selenic.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# net/ipv4/syncookies.c
#   2005/03/07 20:41:51-08:00 mpm@selenic.com +77 -0
#   random: Move syncookies to net/
# 
# include/linux/random.h
#   2005/03/07 20:41:51-08:00 mpm@selenic.com +0 -8
#   random: Move syncookies to net/
# 
# drivers/char/random.c
#   2005/03/07 20:41:51-08:00 mpm@selenic.com +0 -81
#   random: Move syncookies to net/
# 
# ChangeSet
#   2005/03/08 10:14:38-08:00 mpm@selenic.com 
#   [PATCH] random: Simplify and shrink syncookie code
#   
#   Simplify syncookie initialization
#   Refactor syncookie code with separate hash function
#   
#   Signed-off-by: Matt Mackall <mpm@selenic.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/char/random.c
#   2005/03/07 21:14:17-08:00 mpm@selenic.com +30 -48
#   random: Simplify and shrink syncookie code
# 
# ChangeSet
#   2005/03/08 10:14:22-08:00 mpm@selenic.com 
#   [PATCH] random: Kill duplicate halfmd4 in ext3 htree
#   
#   Replace duplicate halfMD4 code with call to lib/
#   
#   Signed-off-by: Matt Mackall <mpm@selenic.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# lib/halfmd4.c
#   2005/03/07 20:41:51-08:00 mpm@selenic.com +7 -3
#   random: Kill duplicate halfmd4 in ext3 htree
# 
# include/linux/cryptohash.h
#   2005/03/07 20:41:51-08:00 mpm@selenic.com +1 -1
#   random: Kill duplicate halfmd4 in ext3 htree
# 
# fs/ext3/hash.c
#   2005/03/07 20:41:51-08:00 mpm@selenic.com +2 -68
#   random: Kill duplicate halfmd4 in ext3 htree
# 
# ChangeSet
#   2005/03/08 10:14:07-08:00 mpm@selenic.com 
#   [PATCH] random: Move halfmd4 to lib
#   
#   Move half-MD4 hash to /lib where we can share it with htree.
#   
#   Signed-off-by: Matt Mackall <mpm@selenic.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# lib/halfmd4.c
#   2005/03/07 21:14:17-08:00 mpm@selenic.com +62 -0
#   random: Move halfmd4 to lib
# 
# lib/Makefile
#   2005/03/07 21:14:17-08:00 mpm@selenic.com +2 -1
#   random: Move halfmd4 to lib
# 
# include/linux/cryptohash.h
#   2005/03/07 21:14:17-08:00 mpm@selenic.com +2 -0
#   random: Move halfmd4 to lib
# 
# drivers/char/random.c
#   2005/03/07 21:14:17-08:00 mpm@selenic.com +3 -44
#   random: Move halfmd4 to lib
# 
# lib/halfmd4.c
#   2005/03/07 21:14:17-08:00 mpm@selenic.com +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/lib/halfmd4.c
# 
# ChangeSet
#   2005/03/08 10:13:51-08:00 mpm@selenic.com 
#   [PATCH] random: Update cryptolib to use SHA fro lib
#   
#   Drop the cryptolib SHA implementation and use the faster and much smaller SHA
#   implementation from lib/.  Saves about 5K.  This also saves time by doing one
#   memset per update call rather than one per SHA block.
#   
#   Signed-off-by: Matt Mackall <mpm@selenic.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# crypto/sha1.c
#   2005/03/07 20:41:51-08:00 mpm@selenic.com +7 -71
#   random: Update cryptolib to use SHA fro lib
# 
# ChangeSet
#   2005/03/08 10:13:35-08:00 mpm@selenic.com 
#   [PATCH] random: Replace SHA with faster version
#   
#   A replacement SHA routine that's slightly larger, but over twice as
#   fast. It's also faster and much smaller than the cryptolib version.
#   
#                size      speed    buffer size
#   original:    350B      2.3us     320B
#   cryptolib:  5776B      1.2us      80B
#   this code:   466B      1.0us     320B
#   alternate:  2112B      1.0us      80B
#   
#   Signed-off-by: Matt Mackall <mpm@selenic.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# lib/sha1.c
#   2005/03/07 20:41:50-08:00 mpm@selenic.com +49 -55
#   random: Replace SHA with faster version
# 
# ChangeSet
#   2005/03/08 10:13:20-08:00 mpm@selenic.com 
#   [PATCH] random: Move SHA code to lib/
#   
#   Move random SHA code to lib/.
#   
#   Signed-off-by: Matt Mackall <mpm@selenic.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# lib/sha1.c
#   2005/03/07 21:14:18-08:00 mpm@selenic.com +102 -0
#   random: Move SHA code to lib/
# 
# lib/sha1.c
#   2005/03/07 21:14:18-08:00 mpm@selenic.com +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/lib/sha1.c
# 
# lib/Makefile
#   2005/03/07 21:14:17-08:00 mpm@selenic.com +1 -1
#   random: Move SHA code to lib/
# 
# include/linux/cryptohash.h
#   2005/03/07 21:14:17-08:00 mpm@selenic.com +10 -0
#   random: Move SHA code to lib/
# 
# drivers/char/random.c
#   2005/03/07 21:14:17-08:00 mpm@selenic.com +5 -116
#   random: Move SHA code to lib/
# 
# include/linux/cryptohash.h
#   2005/03/07 21:14:17-08:00 mpm@selenic.com +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/include/linux/cryptohash.h
# 
# ChangeSet
#   2005/03/08 10:13:04-08:00 mpm@selenic.com 
#   [PATCH] random: Cleanup SHA interface
#   
#   Clean up SHA hash function for moving to lib/
#   Do proper endian conversion
#   Provide sha_init function
#   Add kerneldoc
#   
#   Signed-off-by: Matt Mackall <mpm@selenic.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/char/random.c
#   2005/03/07 21:14:18-08:00 mpm@selenic.com +36 -40
#   random: Cleanup SHA interface
# 
# ChangeSet
#   2005/03/08 10:12:49-08:00 mpm@selenic.com 
#   [PATCH] random: Kill the SHA variants
#   
#   Kill the unrolled SHA variants, they're unused and duplicate code in
#   cryptoapi.
#   
#   Signed-off-by: Matt Mackall <mpm@selenic.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/char/random.c
#   2005/03/07 21:14:18-08:00 mpm@selenic.com +0 -145
#   random: Kill the SHA variants
# 
# ChangeSet
#   2005/03/08 10:12:34-08:00 mpm@selenic.com 
#   [PATCH] random: Use them throughout the tree
#   
#   Move users of private rotl/rotr functions to rol32/ror32.  Crypto bits
#   verified with tcrypt.
#   
#   Signed-off-by: Matt Mackall <mpm@selenic.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# fs/xfs/xfs_da_btree.c
#   2005/03/07 20:41:50-08:00 mpm@selenic.com +9 -11
#   random: Use them throughout the tree
# 
# fs/ncpfs/ncpsign_kernel.c
#   2005/03/07 20:41:50-08:00 mpm@selenic.com +1 -2
#   random: Use them throughout the tree
# 
# crypto/sha256.c
#   2005/03/07 20:41:50-08:00 mpm@selenic.com +4 -9
#   random: Use them throughout the tree
# 
# crypto/sha1.c
#   2005/03/07 21:14:17-08:00 mpm@selenic.com +9 -14
#   random: Use them throughout the tree
# 
# crypto/serpent.c
#   2005/03/07 20:41:50-08:00 mpm@selenic.com +11 -13
#   random: Use them throughout the tree
# 
# crypto/michael_mic.c
#   2005/03/07 20:41:50-08:00 mpm@selenic.com +3 -15
#   random: Use them throughout the tree
# 
# crypto/cast6.c
#   2005/03/07 20:41:50-08:00 mpm@selenic.com +3 -5
#   random: Use them throughout the tree
# 
# crypto/cast5.c
#   2005/03/07 20:41:50-08:00 mpm@selenic.com +3 -6
#   random: Use them throughout the tree
# 
# crypto/aes.c
#   2005/03/07 20:41:50-08:00 mpm@selenic.com +18 -35
#   random: Use them throughout the tree
# 
# ChangeSet
#   2005/03/08 10:12:18-08:00 mpm@selenic.com 
#   [PATCH] random: Create new rol32/ror32 bitops
#   
#   Add rol32 and ror32 bitops to bitops.h
#   
#   Signed-off-by: Matt Mackall <mpm@selenic.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/linux/bitops.h
#   2005/03/07 20:41:50-08:00 mpm@selenic.com +22 -0
#   random: Create new rol32/ror32 bitops
# 
# drivers/char/random.c
#   2005/03/07 21:14:18-08:00 mpm@selenic.com +0 -5
#   random: Create new rol32/ror32 bitops
# 
# ChangeSet
#   2005/03/08 10:12:03-08:00 mpm@selenic.com 
#   [PATCH] random: Remove entropy batching
#   
#   Rather than batching up entropy samples, resulting in longer lock hold times
#   when we actually process the samples, mix in samples immediately.  The trickle
#   code should eliminate almost all the additional interrupt-time overhead this
#   would otherwise incur, with or without locking.
#   
#   Signed-off-by: Matt Mackall <mpm@selenic.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/char/random.c
#   2005/03/07 21:14:19-08:00 mpm@selenic.com +17 -134
#   random: Remove entropy batching
# 
# ChangeSet
#   2005/03/08 10:11:49-08:00 mpm@selenic.com 
#   [PATCH] random: Clean up hash buffering
#   
#   Clean up buffer usage for SHA and reseed.  This makes the code more readable
#   and reduces worst-case stack usage.
#   
#   Signed-off-by: Matt Mackall <mpm@selenic.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/char/random.c
#   2005/03/07 21:14:19-08:00 mpm@selenic.com +19 -17
#   random: Clean up hash buffering
# 
# ChangeSet
#   2005/03/08 10:11:32-08:00 mpm@selenic.com 
#   [PATCH] random: Simplify hash folding
#   
#   Simplify output hash folding
#   
#   Signed-off-by: Matt Mackall <mpm@selenic.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/char/random.c
#   2005/03/07 21:14:19-08:00 mpm@selenic.com +3 -8
#   random: Simplify hash folding
# 
# ChangeSet
#   2005/03/08 10:11:15-08:00 mpm@selenic.com 
#   [PATCH] random: Remove dead MD5 copy
#   
#   Remove long-dead md5 code.
#   
#   Signed-off-by: Matt Mackall <mpm@selenic.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/char/random.c
#   2005/03/07 21:14:19-08:00 mpm@selenic.com +8 -145
#   random: Remove dead MD5 copy
# 
# ChangeSet
#   2005/03/08 10:11:00-08:00 mpm@selenic.com 
#   [PATCH] random: Break up extract_user
#   
#   Break apart extract_entropy into kernel and user versions, remove last extract
#   flag and some unnecessary variables.  This makes the code more readable and
#   amenable to sparse.
#   
#   Signed-off-by: Matt Mackall <mpm@selenic.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/char/random.c
#   2005/03/07 21:14:19-08:00 mpm@selenic.com +107 -83
#   random: Break up extract_user
# 
# ChangeSet
#   2005/03/08 10:10:45-08:00 mpm@selenic.com 
#   [PATCH] random: Reseed pointer in pool struct
#   
#   Put pointer to reseed pool in pool struct and automatically pull entropy from
#   it if it is set.  This lets us remove the EXTRACT_SECONDARY flag.
#   
#   Signed-off-by: Matt Mackall <mpm@selenic.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/char/random.c
#   2005/03/07 21:14:20-08:00 mpm@selenic.com +9 -13
#   random: Reseed pointer in pool struct
# 
# ChangeSet
#   2005/03/08 10:10:29-08:00 mpm@selenic.com 
#   [PATCH] random: Reservation flag in pool struct
#   
#   Move the limit flag to the pool struct, begin process of eliminating extract
#   flags.
#   
#   Signed-off-by: Matt Mackall <mpm@selenic.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/char/random.c
#   2005/03/07 21:14:20-08:00 mpm@selenic.com +9 -17
#   random: Reservation flag in pool struct
# 
# ChangeSet
#   2005/03/08 10:10:15-08:00 mpm@selenic.com 
#   [PATCH] random: Entropy reservation accounting
#   
#   Additional parameter to allow keeping an entropy reserve in the input pool.
#   Groundwork for proper /dev/urandom vs /dev/random starvation prevention.
#   
#   Signed-off-by: Matt Mackall <mpm@selenic.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/char/random.c
#   2005/03/07 21:14:20-08:00 mpm@selenic.com +17 -13
#   random: Entropy reservation accounting
# 
# ChangeSet
#   2005/03/08 10:10:00-08:00 mpm@selenic.com 
#   [PATCH] random: Catastrophic reseed checks
#   
#   When reseeding, we must always do a "catastrophic reseed" where we pull enough
#   new bits to make the new state unguessable from outputs even if we knew the
#   old state.  So we must do the checks against the minimum reseed amount under
#   the pool lock in extract_entropy.
#   
#   Signed-off-by: Matt Mackall <mpm@selenic.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/char/random.c
#   2005/03/07 21:14:20-08:00 mpm@selenic.com +23 -14
#   random: Catastrophic reseed checks
# 
# ChangeSet
#   2005/03/08 10:09:45-08:00 mpm@selenic.com 
#   [PATCH] random: Static sysctl bits
#   
#   Static initialization for sysctl support
#   
#   Signed-off-by: Matt Mackall <mpm@selenic.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/char/random.c
#   2005/03/07 21:14:20-08:00 mpm@selenic.com +6 -24
#   random: Static sysctl bits
# 
# ChangeSet
#   2005/03/08 10:09:30-08:00 mpm@selenic.com 
#   [PATCH] random: Static allocation of pools
#   
#   As we no longer allow resizing of pools, it makes sense to allocate and
#   initialize them statically.  Remove create_entropy_store and simplify
#   rand_initialize.
#   
#   Signed-off-by: Matt Mackall <mpm@selenic.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/char/random.c
#   2005/03/07 21:14:20-08:00 mpm@selenic.com +79 -124
#   random: Static allocation of pools
# 
# ChangeSet
#   2005/03/08 10:09:14-08:00 mpm@selenic.com 
#   [PATCH] random: More meaningful pool names
#   
#   Give pools more meaningful names.
#   
#   Signed-off-by: Matt Mackall <mpm@selenic.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/char/random.c
#   2005/03/07 21:14:21-08:00 mpm@selenic.com +49 -50
#   random: More meaningful pool names
# 
# ChangeSet
#   2005/03/08 10:08:59-08:00 mpm@selenic.com 
#   [PATCH] random: kill misnamed log2
#   
#   Remove incorrectly named ln (it's log2!) and x86 asm function and replace with
#   fls bitop.
#   
#   Signed-off-by: Matt Mackall <mpm@selenic.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/char/random.c
#   2005/03/07 21:14:21-08:00 mpm@selenic.com +1 -47
#   random: kill misnamed log2
# 
# ChangeSet
#   2005/03/08 10:08:44-08:00 mpm@selenic.com 
#   [PATCH] rol32 thinko
#   
#   This thinko..  makes things a bit more arbitrary than we'd like.  I've
#   re-audited the other rotate conversions.
#   
#   Signed-off-by: Matt Mackall <mpm@selenic.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/char/random.c
#   2005/03/07 21:14:21-08:00 mpm@selenic.com +1 -1
#   rol32 thinko
# 
# ChangeSet
#   2005/03/08 10:08:28-08:00 mpm@selenic.com 
#   [PATCH] random: kill redundant rotate_left definitions
#   
#   We've got three definitions of rotate_left.  Remove x86 and duplicate rotate
#   definitions.  Remaining definition is fixed up such that recent gcc will
#   generate rol instructions on x86 at least.
#   
#   A later patch will move this to bitops and clean up the other tree users.
#   
#   Signed-off-by: Matt Mackall <mpm@selenic.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/char/random.c
#   2005/03/07 21:14:21-08:00 mpm@selenic.com +15 -34
#   random: kill redundant rotate_left definitions
# 
# ChangeSet
#   2005/03/08 10:08:13-08:00 mpm@selenic.com 
#   [PATCH] random: kill 2.2 compat waitqueue defs
#   
#   Remove Linux 2.2 compatibility cruft.
#   
#   Signed-off-by: Matt Mackall <mpm@selenic.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/char/random.c
#   2005/03/07 21:14:21-08:00 mpm@selenic.com +0 -10
#   random: kill 2.2 compat waitqueue defs
# 
# ChangeSet
#   2005/03/08 10:07:57-08:00 mpm@selenic.com 
#   [PATCH] random: kill dead extract_state struct
#   
#   Remove unused extract_timer_state struct.  It was formerly used to feedback
#   zero-entropy timing samples while extracting entropy, but that had a tendency
#   to overwhelm the batch processing queue and prevent storing real samples.
#   
#   Signed-off-by: Matt Mackall <mpm@selenic.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/char/random.c
#   2005/03/07 21:14:21-08:00 mpm@selenic.com +0 -2
#   random: kill dead extract_state struct
# 
# ChangeSet
#   2005/03/08 10:07:42-08:00 mpm@selenic.com 
#   [PATCH] random: kill memsets of static data
#   
#   Remove redundant memsets of BSS data
#   
#   Signed-off-by: Matt Mackall <mpm@selenic.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/char/random.c
#   2005/03/07 21:14:21-08:00 mpm@selenic.com +0 -6
#   random: kill memsets of static data
# 
# ChangeSet
#   2005/03/08 10:07:27-08:00 mpm@selenic.com 
#   [PATCH] random: simplify initialization
#   
#   Simplify the init code
#   
#   Signed-off-by: Matt Mackall <mpm@selenic.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/char/random.c
#   2005/03/07 21:14:22-08:00 mpm@selenic.com +3 -17
#   random: simplify initialization
# 
# ChangeSet
#   2005/03/08 10:07:12-08:00 mpm@selenic.com 
#   [PATCH] random: re-init all pools on zero
#   
#   - Re-init all three pools in ioctls
#   
#   - Clear entropy count in init_std_data under a lock
#   
#   - Add kerneldoc comment
#   
#   Signed-off-by: Matt Mackall <mpm@selenic.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/char/random.c
#   2005/03/07 21:14:22-08:00 mpm@selenic.com +13 -9
#   random: re-init all pools on zero
# 
# ChangeSet
#   2005/03/08 10:06:57-08:00 mpm@selenic.com 
#   [PATCH] random: combine legacy ioctls
#   
#   ZAPENTCNT is now effectively identical to RNDCLEARPOOL, fall through
#   
#   Signed-off-by: Matt Mackall <mpm@selenic.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/char/random.c
#   2005/03/07 21:14:22-08:00 mpm@selenic.com +0 -4
#   random: combine legacy ioctls
# 
# ChangeSet
#   2005/03/08 10:06:41-08:00 mpm@selenic.com 
#   [PATCH] random: kill pool clearing
#   
#   Remove pool clearing.  We've only ever cleared one of three pools and there's
#   no good reason to do it.  Instead just reset the entropy count.
#   
#   Signed-off-by: Matt Mackall <mpm@selenic.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/char/random.c
#   2005/03/07 21:14:22-08:00 mpm@selenic.com +2 -14
#   random: kill pool clearing
# 
# ChangeSet
#   2005/03/08 10:06:26-08:00 mpm@selenic.com 
#   [PATCH] random: cleanup waitqueue logic, fix missed wakeup
#   
#   Original code checked in output pool for missed wakeup avoidance, while waker
#   (batch_entropy_process) checked input pool which could result in a missed
#   wakeup.
#   
#   - Move to wait_event_interruptible style
#   
#   - Delete superfluous waitqueue
#   
#   Signed-off-by: Matt Mackall <mpm@selenic.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/char/random.c
#   2005/03/07 21:14:22-08:00 mpm@selenic.com +9 -10
#   random: cleanup waitqueue logic, fix missed wakeup
# 
# ChangeSet
#   2005/03/08 10:06:11-08:00 mpm@selenic.com 
#   [PATCH] lib/sort: Use generic sort on x86_64
#   
#   x86_64 wasn't doing anything special in its sort_extable.  Use the generic
#   lib/extable sort.
#   
#   Signed-off-by: Matt Mackall <mpm@selenic.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/asm-x86_64/uaccess.h
#   2005/03/07 20:41:46-08:00 mpm@selenic.com +1 -0
#   lib/sort: Use generic sort on x86_64
# 
# arch/x86_64/mm/extable.c
#   2005/03/07 20:41:46-08:00 mpm@selenic.com +0 -23
#   lib/sort: Use generic sort on x86_64
# 
# ChangeSet
#   2005/03/08 10:05:55-08:00 mpm@selenic.com 
#   [PATCH] lib/sort: Replace insertion sort in IA64 exception tables
#   
#   Switch IA64 exception tables to lib/sort.
#   
#   Signed-off-by: Matt Mackall <mpm@selenic.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/ia64/mm/extable.c
#   2005/03/07 20:41:46-08:00 mpm@selenic.com +18 -26
#   lib/sort: Replace insertion sort in IA64 exception tables
# 
# ChangeSet
#   2005/03/08 10:05:40-08:00 mpm@selenic.com 
#   [PATCH] lib/sort: Replace insertion sort in exception tables
#   
#   Replace exception table insertion sort with lib/sort
#   
#   Signed-off-by: Matt Mackall <mpm@selenic.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# lib/extable.c
#   2005/03/07 20:41:46-08:00 mpm@selenic.com +9 -17
#   lib/sort: Replace insertion sort in exception tables
# 
# ChangeSet
#   2005/03/08 10:05:24-08:00 mpm@selenic.com 
#   [PATCH] lib/sort: Replace qsort in XFS
#   
#   Point XFS qsort at lib/sort in a way that makes it happy.
#   
#   Signed-off-by: Matt Mackall <mpm@selenic.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# fs/xfs/linux-2.6/xfs_linux.h
#   2005/03/07 20:41:46-08:00 mpm@selenic.com +3 -0
#   lib/sort: Replace qsort in XFS
# 
# ChangeSet
#   2005/03/08 10:05:10-08:00 akpm@osdl.org 
#   [PATCH] sort: link it in
#   
#   We cannot tell at build time whether some module may want it.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# lib/Makefile
#   2005/03/07 21:14:18-08:00 akpm@osdl.org +3 -1
#   sort: link it in
# 
# ChangeSet
#   2005/03/08 10:04:55-08:00 mpm@selenic.com 
#   [PATCH] lib/sort: Heapsort implementation of sort()
#   
#   This patch adds a generic array sorting library routine. This is meant
#   to replace qsort, which has two problem areas for kernel use.
#   
#   The first issue is quadratic worst-case performance. While quicksort
#   worst-case datasets are rarely encountered in normal scenarios, it is
#   in fact quite easy to construct worst cases for almost all quicksort
#   algorithms given source or access to an element comparison callback.
#   This could allow attackers to cause sorts that would otherwise take
#   less than a millisecond to take seconds and sorts that should take
#   less than a second to take weeks or months. Fixing this problem
#   requires randomizing pivot selection with a secure random number
#   generator, which is rather expensive.
#   
#   The second is that quicksort's recursion tracking requires either
#   nontrivial amounts of stack space or dynamic memory allocation and out
#   of memory error handling.
#   
#   By comparison, heapsort has both O(n log n) average and worst-case
#   performance and practically no extra storage requirements. This
#   version runs within 70-90% of the average performance of optimized
#   quicksort so it should be an acceptable replacement wherever quicksort
#   would be used in the kernel.
#   
#   Note that this function has an extra parameter for passing in an
#   optimized swapping function. This is worth 10% or more over the
#   typical byte-by-byte exchange functions.
#   
#   Benchmarks:
#   
#   qsort:     glibc variant            1189 bytes (+ 256/1024 stack)
#   qsort_3f:  my simplified variant     459 bytes (+ 256/1024 stack)
#   heapsort:  the version below         346 bytes
#   shellsort: an optimized shellsort    196 bytes
#   
#                            P4 1.8GHz        Opteron 1.4GHz (32-bit)
#   size   algorithm      cycles relative        cycles relative
#   100:
#              qsort:      38682 100.00%	      27631 100.00%
#           qsort_3f:      36277 106.63%	      22406 123.32%
#           heapsort:      43574  88.77%	      30301  91.19%
#          shellsort:      39087  98.97%	      25139 109.91%
#   200:									  
#              qsort:      86468 100.00%	      61148 100.00%
#           qsort_3f:      78918 109.57%	      48959 124.90%
#           heapsort:      98040  88.20%	      68235  89.61%
#          shellsort:      95688  90.36%	      62279  98.18%
#   400:									  
#              qsort:     187720 100.00%	     131313 100.00%
#           qsort_3f:     174905 107.33%	     107954 121.64%
#           heapsort:     223896  83.84%	     154241  85.13%
#          shellsort:     223037  84.17%	     148990  88.14%
#   800:									  
#              qsort:     407060 100.00%	     287460 100.00%
#           qsort_3f:     385106 105.70%	     239131 120.21%
#           heapsort:     484662  83.99%	     340099  84.52%
#          shellsort:     537110  75.79%	     354755  81.03%
#   1600:									    
#              qsort:     879596 100.00%	     621331 100.00%
#           qsort_3f:     861568 102.09%	     522013 119.03%
#           heapsort:    1079750  81.46%	     746677  83.21%
#          shellsort:    1234243  71.27%	     820782  75.70%
#   3200:									    
#              qsort:    1903902 100.00%	    1342126 100.00%
#           qsort_3f:    1908816  99.74%	    1131496 118.62%
#           heapsort:    2515493  75.69%	    1630333  82.32%
#          shellsort:    2985339  63.78%	    1964794  68.31%
#   6400:									    
#              qsort:    4046370 100.00%	    2909215 100.00%
#           qsort_3f:    4164468  97.16%	    2468393 117.86%
#           heapsort:    5150659  78.56%	    3533585  82.33%
#          shellsort:    6650225  60.85%	    4429849  65.67%
#   12800:									   
#              qsort:    8729730 100.00%	    6185097 100.00%
#           qsort_3f:    8776885  99.46%	    5288826 116.95%
#           heapsort:   11064224  78.90%	    7603061  81.35%
#          shellsort:   15487905  56.36%	   10305163  60.02%
#   25600:									   
#              qsort:   18357770 100.00%	   13172205 100.00%
#           qsort_3f:   18687842  98.23%	   11337115 116.19%
#           heapsort:   24121241  76.11%	   16612122  79.29%
#          shellsort:   35552814  51.64%	   24106987  54.64%
#   51200:									   
#              qsort:   38658883 100.00%	   28008505 100.00%
#           qsort_3f:   39498463  97.87%	   24339675 115.07%
#           heapsort:   50553552  76.47%	   37013828  75.67%
#          shellsort:   82602416  46.80%	   56201889  49.84%
#   102400:									  
#              qsort:   81197794 100.00%	   58918933 100.00%
#           qsort_3f:   84257930  96.37%	   51986219 113.34%
#           heapsort:  110540577  73.46%	   81419675  72.36%
#          shellsort:  191303132  42.44%	  129786472  45.40%
#   From: Zou Nan hai <nanhai.zou@intel.com>
#   
#   The new sort routine only works if there are an even number of entries in
#   the ia64 exception fix-up tables.  If the number of entries is odd the sort
#   fails, and then random get_user/put_user calls can fail.
#   
#   Signed-off-by: Matt Mackall <mpm@selenic.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# lib/sort.c
#   2005/03/07 20:41:45-08:00 mpm@selenic.com +119 -0
#   lib/sort: Heapsort implementation of sort()
# 
# lib/sort.c
#   2005/03/07 20:41:45-08:00 mpm@selenic.com +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/lib/sort.c
# 
# lib/Makefile
#   2005/03/07 21:14:23-08:00 mpm@selenic.com +1 -1
#   lib/sort: Heapsort implementation of sort()
# 
# init/Kconfig
#   2005/03/07 20:41:45-08:00 mpm@selenic.com +5 -5
#   lib/sort: Heapsort implementation of sort()
# 
# include/linux/sort.h
#   2005/03/07 20:41:45-08:00 mpm@selenic.com +10 -0
#   lib/sort: Heapsort implementation of sort()
# 
# include/linux/sort.h
#   2005/03/07 20:41:45-08:00 mpm@selenic.com +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/include/linux/sort.h
# 
# ChangeSet
#   2005/03/08 10:04:39-08:00 mpm@selenic.com 
#   [PATCH] base-small: shrink console buffer
#   
#   CONFIG_BASE_SMALL reduce console transfer buffer
#   
#   Signed-off-by: Matt Mackall <mpm@selenic.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/linux/vt_kern.h
#   2005/03/07 20:41:45-08:00 mpm@selenic.com +2 -1
#   base-small: shrink console buffer
# 
# ChangeSet
#   2005/03/08 10:04:24-08:00 mpm@selenic.com 
#   [PATCH] base-small: shrink timer hashes
#   
#   CONFIG_BASE_SMALL reduce timer list hashes
#   
#   Signed-off-by: Matt Mackall <mpm@selenic.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# kernel/timer.c
#   2005/03/07 21:14:15-08:00 mpm@selenic.com +3 -2
#   base-small: shrink timer hashes
# 
# ChangeSet
#   2005/03/08 10:04:09-08:00 mpm@selenic.com 
#   [PATCH] base-small: shrink futex queues
#   
#   CONFIG_BASE_SMALL reduce futex hash table
#   
#   Signed-off-by: Matt Mackall <mpm@selenic.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# kernel/futex.c
#   2005/03/07 20:41:45-08:00 mpm@selenic.com +1 -1
#   base-small: shrink futex queues
# 
# ChangeSet
#   2005/03/08 10:03:54-08:00 mpm@selenic.com 
#   [PATCH] base-small: shrink UID hash
#   
#   CONFIG_BASE_SMALL reduce UID lookup hash
#   
#   Signed-off-by: Matt Mackall <mpm@selenic.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# kernel/user.c
#   2005/03/07 20:41:45-08:00 mpm@selenic.com +2 -1
#   base-small: shrink UID hash
# 
# ChangeSet
#   2005/03/08 10:03:40-08:00 mpm@selenic.com 
#   [PATCH] base-small: shrink PID tables
#   
#   CONFIG_BASE_SMALL reduce size of pidmap table for small machines
#   
#   Signed-off-by: Matt Mackall <mpm@selenic.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/linux/threads.h
#   2005/03/07 20:41:45-08:00 mpm@selenic.com +4 -3
#   base-small: shrink PID tables
# 
# ChangeSet
#   2005/03/08 10:03:24-08:00 mpm@selenic.com 
#   [PATCH] base-small: shrink chrdevs hash
#   
#   CONFIG_BASE_SMALL degrade char dev hash table to linked list
#   
#   Signed-off-by: Matt Mackall <mpm@selenic.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# fs/char_dev.c
#   2005/03/07 20:41:45-08:00 mpm@selenic.com +2 -1
#   base-small: shrink chrdevs hash
# 
# ChangeSet
#   2005/03/08 10:03:10-08:00 mpm@selenic.com 
#   [PATCH] base-small: introduce the CONFIG_BASE_SMALL flag
#   
#   This patch series introduced a new pair of CONFIG_EMBEDDED options call
#   CONFIG_BASE_FULL/CONFIG_BASE_SMALL.  Disabling CONFIG_BASE_FULL sets the
#   boolean CONFIG_BASE_SMALL to 1 and it is used to shrink a number of core data
#   structures.  The space savings for the current batch is around 14k.
#   
#   This patch:
#   
#   Add CONFIG_BASE_SMALL for miscellaneous core size that don't warrant
#   their own options. Example users to follow.
#   
#   Signed-off-by: Matt Mackall <mpm@selenic.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# init/Kconfig
#   2005/03/07 21:14:23-08:00 mpm@selenic.com +12 -0
#   base-small: introduce the CONFIG_BASE_SMALL flag
# 
# ChangeSet
#   2005/03/08 10:02:55-08:00 rddunlap@osdl.org 
#   [PATCH] oss/sscape: fix section references
#   
#   oss/sscape: fix initdata reference used in exit:
#   
#   Error: ./sound/oss/sscape.o .exit.text refers to 000000000000007d R_X86_64_PC32     .init.data+0x0000000000000003
#   
#   Signed-off-by: Randy Dunlap <rddunlap@osdl.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# sound/oss/sscape.c
#   2005/03/07 20:41:44-08:00 rddunlap@osdl.org +1 -1
#   oss/sscape: fix section references
# 
# ChangeSet
#   2005/03/08 10:02:40-08:00 rddunlap@osdl.org 
#   [PATCH] oss/pss: fix section references
#   
#   oss/pss: fix initdata reference used in exit:
#   
#   Error: ./sound/oss/pss.o .exit.text refers to 000000000000003f R_X86_64_PC32     .init.data+0x0000000000000003
#   
#   Signed-off-by: Randy Dunlap <rddunlap@osdl.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# sound/oss/pss.c
#   2005/03/07 20:41:44-08:00 rddunlap@osdl.org +1 -1
#   oss/pss: fix section references
# 
# ChangeSet
#   2005/03/08 10:02:25-08:00 rddunlap@osdl.org 
#   [PATCH] oss/nm256: fix section references
#   
#   oss/nm256_audio: fix init text section reference:
#   
#   Error: ./sound/oss/nm256_audio.o .text refers to 0000000000001847 R_X86_64_PC32     .init.text+0x0000000000000018
#   
#   Signed-off-by: Randy Dunlap <rddunlap@osdl.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# sound/oss/nm256_audio.c
#   2005/03/07 20:41:44-08:00 rddunlap@osdl.org +1 -1
#   oss/nm256: fix section references
# 
# ChangeSet
#   2005/03/08 10:02:09-08:00 rddunlap@osdl.org 
#   [PATCH] oss/esssolo1: fix initdata section references
#   
#   oss/esssolo1: fix initdata section reference:
#   
#   Error: ./sound/oss/esssolo1.o .text refers to 0000000000000bab R_X86_64_32S      .init.data+0x0000000000000004
#   Error: ./sound/oss/esssolo1.o .text refers to 0000000000000bb2 R_X86_64_32S      .init.data
#   
#   Signed-off-by: Randy Dunlap <rddunlap@osdl.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# sound/oss/esssolo1.c
#   2005/03/07 20:41:44-08:00 rddunlap@osdl.org +1 -1
#   oss/esssolo1: fix initdata section references
# 
# ChangeSet
#   2005/03/08 10:01:54-08:00 rddunlap@osdl.org 
#   [PATCH] oss/es1370: fix initdata section references
#   
#   oss/es1370: fix initdata section reference:
#   
#   Error: ./sound/oss/es1370.o .text refers to 00000000000042bd R_X86_64_32S      .init.data+0x0000000000000024
#   Error: ./sound/oss/es1370.o .text refers to 00000000000042c5 R_X86_64_32S      .init.data+0x0000000000000020
#   
#   Signed-off-by: Randy Dunlap <rddunlap@osdl.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# sound/oss/es1370.c
#   2005/03/07 20:41:44-08:00 rddunlap@osdl.org +1 -1
#   oss/es1370: fix initdata section references
# 
# ChangeSet
#   2005/03/08 10:01:39-08:00 rddunlap@osdl.org 
#   [PATCH] oss/cmpci: fix initdata section references
#   
#   oss/cmpci: fix initdata section reference:
#   
#   Error: ./sound/oss/cmpci.o .text refers to 000000000000418e R_X86_64_32S      .init.data+0x0000000000000004
#   Error: ./sound/oss/cmpci.o .text refers to 0000000000004196 R_X86_64_32S      .init.data
#   
#   Signed-off-by: Randy Dunlap <rddunlap@osdl.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# sound/oss/cmpci.c
#   2005/03/07 20:41:44-08:00 rddunlap@osdl.org +1 -1
#   oss/cmpci: fix initdata section references
# 
# ChangeSet
#   2005/03/08 10:01:24-08:00 rddunlap@osdl.org 
#   [PATCH] oss/cs4281: fix initdata section references
#   
#   oss/cs4281: fix initdata section references:
#   
#   Error: ./sound/oss/cs4281/cs4281.o .text refers to 0000000000006dae R_X86_64_32S      .init.data+0x0000000000000004
#   Error: ./sound/oss/cs4281/cs4281.o .text refers to 0000000000006db6 R_X86_64_32S      .init.data
#   Error: ./sound/oss/cs4281/cs4281m.o .text refers to 0000000000006dae R_X86_64_32S      .init.data+0x0000000000000004
#   Error: ./sound/oss/cs4281/cs4281m.o .text refers to 0000000000006db6 R_X86_64_32S      .init.data
#   
#   Signed-off-by: Randy Dunlap <rddunlap@osdl.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# sound/oss/cs4281/cs4281m.c
#   2005/03/07 20:41:44-08:00 rddunlap@osdl.org +1 -1
#   oss/cs4281: fix initdata section references
# 
# ChangeSet
#   2005/03/08 10:01:09-08:00 rddunlap@osdl.org 
#   [PATCH] atm/zatm: fix section references
#   
#   atm/zatm: fix text section references to __init text and __initdata;
#     they should be __devinit instead of __init;
#   
#   Error: ./drivers/atm/zatm.o .text refers to 0000000000001abb R_X86_64_PC32     .init.text+0x0000000000000154
#   Error: ./drivers/atm/zatm.o .text refers to 0000000000001ad3 R_X86_64_PC32     .init.text+0x0000000000000154
#   
#   Signed-off-by: Randy Dunlap <rddunlap@osdl.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/atm/zatm.c
#   2005/03/07 20:41:43-08:00 rddunlap@osdl.org +6 -6
#   atm/zatm: fix section references
# 
# ChangeSet
#   2005/03/08 10:00:54-08:00 rddunlap@osdl.org 
#   [PATCH] atm/ambassador: fix init section references
#   
#   atm/ambassador: fix text section references to __init text and __initdata;
#   
#   The biggest negative about this AFAIK is that it makes ucode_data
#   non-initdata, and that moves about 8 KB of data from .init.data
#   to .data.  Similarly, .text increases by approx. 1300 bytes (on x86-32).
#   
#   Error: ./drivers/atm/ambassador.o .text refers to 0000000000002a07 R_X86_64_PC32     .init.text+0x0000000000000149
#   Error: ./drivers/atm/ambassador.o .text refers to 0000000000002a45 R_X86_64_32S      .init.data+0x0000000000000040
#   Error: ./drivers/atm/ambassador.o .text refers to 0000000000002a7c R_X86_64_PC32     .init.data+0x0000000000000020
#   Error: ./drivers/atm/ambassador.o .text refers to 0000000000002a83 R_X86_64_PC32     .init.data+0x000000000000001c
#   Error: ./drivers/atm/ambassador.o .text refers to 0000000000002b40 R_X86_64_PC32     .init.text+0x0000000000000149
#   Error: ./drivers/atm/ambassador.o .text refers to 0000000000002bbc R_X86_64_PC32     .init.text+0x0000000000000149
#   Error: ./drivers/atm/ambassador.o .text refers to 0000000000002c0f R_X86_64_32S      .init.data+0x0000000000000024
#   Error: ./drivers/atm/ambassador.o .text refers to 0000000000002c17 R_X86_64_32S      .init.data+0x0000000000000020
#   Error: ./drivers/atm/ambassador.o .text refers to 0000000000002c3c R_X86_64_PC32     .init.data+0xfffffffffffffffc
#   Error: ./drivers/atm/ambassador.o .text refers to 0000000000002c6a R_X86_64_PC32     .init.text+0x0000000000000149
#   Error: ./drivers/atm/ambassador.o .text refers to 0000000000002c77 R_X86_64_32S      .init.data+0x0000000000000040
#   
#   Signed-off-by: Randy Dunlap <rddunlap@osdl.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/atm/ambassador.c
#   2005/03/07 20:41:43-08:00 rddunlap@osdl.org +14 -14
#   atm/ambassador: fix init section references
# 
# ChangeSet
#   2005/03/08 10:00:39-08:00 rddunlap@osdl.org 
#   [PATCH] atm/lanai: fix section references
#   
#   atm/lanai: fix text section references to __init text;
#     they should be __devinit instead of __init;
#   
#   Error: ./drivers/atm/lanai.o .text refers to 0000000000002105 R_X86_64_PC32     .init.text+0x0000000000000021
#   Error: ./drivers/atm/lanai.o .text refers to 0000000000002116 R_X86_64_PC32     .init.text+0x0000000000000021
#   Error: ./drivers/atm/lanai.o .text refers to 0000000000002132 R_X86_64_PC32     .init.text+0x0000000000000021
#   
#   Signed-off-by: Randy Dunlap <rddunlap@osdl.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/atm/lanai.c
#   2005/03/07 20:41:43-08:00 rddunlap@osdl.org +10 -10
#   atm/lanai: fix section references
# 
# ChangeSet
#   2005/03/08 10:00:24-08:00 paulkf@microgate.com 
#   [PATCH] fix register access typo in synclinkmp
#   
#   Fix register access typo in synclinkmp.c that caused value to be written to
#   wrong register.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/char/synclinkmp.c
#   2005/03/07 20:41:43-08:00 paulkf@microgate.com +3 -3
#   fix register access typo in synclinkmp
# 
# ChangeSet
#   2005/03/08 10:00:09-08:00 panagiotis.issaris@mech.kuleuven.ac.be 
#   [PATCH] efi: fix failure handling
#   
#   The EFI driver allocates memory and writes into it without checking the
#   success of the allocation.  Furthermore, on failure of the
#   firmware_register() it doesn't free the allocated memory and on failure of
#   the subsys_create_file() calls it returns zero instead of the errorcode.
#   
#   Signed-off-by: Panagiotis Issaris <panagiotis.issaris@mech.kuleuven.ac.be>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/firmware/efivars.c
#   2005/03/07 20:41:43-08:00 panagiotis.issaris@mech.kuleuven.ac.be +35 -9
#   efi: fix failure handling
# 
# ChangeSet
#   2005/03/08 09:59:54-08:00 jmoyer@redhat.com 
#   [PATCH] autofs4 patch: autofs4_wait can leak memory
#   
#   There is a memory in the autofs4_wait function, if multiple processes are
#   waiting on the same queue:
#   
#   	name = kmalloc(NAME_MAX + 1, GFP_KERNEL);
#   	if (!name)
#   		return -ENOMEM;
#   	...
#   
#   	if ( !wq ) {
#   		/* Create a new wait queue */
#   		wq = kmalloc(sizeof(struct autofs_wait_queue), GFP_KERNEL);
#   		if ( !wq ) {
#   			kfree(name);
#   			up(&sbi->wq_sem);
#   			return -ENOMEM;
#   		}
#   		...
#   		wq->name = name;
#   
#   		...
#   	} else {
#   		atomic_inc(&wq->wait_ctr);
#   		up(&sbi->wq_sem);
#   		...
#          }
#   
#   In the else clause, we forget to free the name we kmalloc'd above.  This is
#   pretty easy to trigger with the following reproducer:
#   
#   setup an automount map as follows:
#   for n in `seq 1 48`; do echo "$n server:/export/$n" >> /etc/auto.test; done
#   setup a master map entry to point at this:
#   echo "/test /etc/auto.test --timeout=1" >> /etc/auto.master
#   
#   Now, assuming the nfs server was setup to export said directories, run the
#   following shell script in two xterms:
#   
#   #!/bin/sh
#   while true; do
#           for n in `seq 1 48`; do
#                   ls /test/$n
#           done
#           sleep 2
#   done
#   
#   and watch the size-256 slab cache grow
#   
#   Within 4 minutes, I had the size-256 cache grow to 384k.  On a kernel with
#   the below patch applied, the size-256 remained constant during an over-night
#   run.
#   
#   Signed-off-by: Jeff Moyer <jmoyer@redhat.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# fs/autofs4/waitq.c
#   2005/03/07 20:41:43-08:00 jmoyer@redhat.com +1 -0
#   autofs4 patch: autofs4_wait can leak memory
# 
# ChangeSet
#   2005/03/08 09:59:39-08:00 jack@suse.cz 
#   [PATCH] Quotactl changes for XFS
#   
#   Attached patch from Nathan splits the checks done in quotactl() in XFS and
#   VFS parts (it's mostly just moving of code back and forth).  It's done
#   mainly because XFS guys would like to implement more types of quotas and I
#   don't want them to slow down the general VFS case.
#   
#   Signed-off-by: Nathan Scott <nathans@sgi.com>
#   Signed-off-by: Jan Kara <jack@suse.cz>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/linux/dqblk_xfs.h
#   2005/03/07 20:41:43-08:00 jack@suse.cz +6 -0
#   Quotactl changes for XFS
# 
# fs/quota.c
#   2005/03/07 20:41:43-08:00 jack@suse.cz +64 -21
#   Quotactl changes for XFS
# 
# ChangeSet
#   2005/03/08 09:59:24-08:00 minyard@acm.org 
#   [PATCH] Minor cleanups to the IPMI driver
#   
#   This patch cleans up the DMI handling so that multiple interfaces can be
#   reported from the DMI tables and so that the DMI slave address can be
#   transferred up to the upper layer.  It also adds an option to specify the
#   slave address as an init parm and removes some unnecessary initializers.
#   
#   This patch also adds inc/dec usecount functions for the SMIs so they can
#   modify the usecounts of modules they use (added because the SMB driver uses
#   the I2C code).
#   
#   Signed-off-by: Corey Minyard <minyard@acm.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/linux/ipmi_smi.h
#   2005/03/07 20:41:43-08:00 minyard@acm.org +10 -1
#   Minor cleanups to the IPMI driver
# 
# drivers/char/ipmi/ipmi_si_intf.c
#   2005/03/07 20:41:43-08:00 minyard@acm.org +62 -38
#   Minor cleanups to the IPMI driver
# 
# drivers/char/ipmi/ipmi_msghandler.c
#   2005/03/07 20:41:43-08:00 minyard@acm.org +25 -7
#   Minor cleanups to the IPMI driver
# 
# Documentation/IPMI.txt
#   2005/03/07 20:41:43-08:00 minyard@acm.org +6 -0
#   Minor cleanups to the IPMI driver
# 
# ChangeSet
#   2005/03/08 09:59:09-08:00 ntl@pobox.com 
#   [PATCH] explicitly bind idle tasks
#   
#   With hotplug cpu and preempt, we tend to see smp_processor_id warnings from
#   idle loop code because it's always checking whether its cpu has gone
#   offline.  Replacing every use of smp_processor_id with _smp_processor_id in
#   all idle loop code is one solution; another way is explicitly binding idle
#   threads to their cpus (the smp_processor_id warning does not fire if the
#   caller is bound only to the calling cpu).  This has the (admittedly slight)
#   advantage of letting us know if an idle thread ever runs on the wrong cpu.
#   
#   Signed-off-by: Nathan Lynch <ntl@pobox.com>
#   Acked-by: Joel Schopp <jschopp@austin.ibm.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# kernel/sched.c
#   2005/03/07 21:14:16-08:00 ntl@pobox.com +1 -0
#   explicitly bind idle tasks
# 
# init/main.c
#   2005/03/07 20:41:42-08:00 ntl@pobox.com +4 -0
#   explicitly bind idle tasks
# 
# ChangeSet
#   2005/03/08 09:58:54-08:00 Andries.Brouwer@cwi.nl 
#   [PATCH] partitions/msdos.c fix
#   
#   A well-known kernel bug is that it guesses at the partition type and the
#   partitions on any disk it encounters.  This is bad because needless I/O is
#   done, slowing down the boot, sometimes quite a lot, especially when I/O
#   errors occur.  And it is bad because sometimes we guess wrong.
#   
#   In other words, we need the user space command `partition', where
#   "partition -t dos /dev/sda" reads a DOS-type partition table.  (And
#   "partition /dev/sda" tries all known heuristics to decide what type of
#   partitioning might be present.) The two variants are: (i) partition tells
#   the kernel to do the partition table reading, and (ii) partition uses partx
#   to read the partition table and tells the kernel one-by-one about the
#   partitions found this way.
#   
#   Since this is a fundamental change, a long transition period is needed, and
#   that period could start with a kernel boot parameter telling the kernel not
#   to do partition table parsing on a particular disk, or a particular type of
#   disks, or all disks.
#   
#   This could have been the intro to a patch doing that, but is not.  (It is
#   just an RFC.)
#   
#   The tiny patch below prompted the above - it was suggested by Uwe Bonnes
#   who encountered USB devices without partition table where our present
#   heuristics did not suffice to stop partition table parsing.  It causes the
#   kernel to ignore partitions of type 0.  A band-aid.
#   
#   I think nobody uses such partitions seriously, but nevertheless this should
#   probably live in -mm for a while to see if anybody complains.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# fs/partitions/msdos.c
#   2005/03/07 20:41:42-08:00 Andries.Brouwer@cwi.nl +5 -0
#   partitions/msdos.c fix
# 
# ChangeSet
#   2005/03/08 09:58:39-08:00 adobriyan@mail.ru 
#   [PATCH] sparc: use initalisers for struct resource
#   
#   For when the layout of `struct resource' changes.
#   
#   Signed-off-by: Alexey Dobriyan <adobriyan@mail.ru>
#   Acked-by: William Irwin <wli@holomorphy.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/sparc/kernel/ioport.c
#   2005/03/07 20:41:42-08:00 adobriyan@mail.ru +2 -2
#   sparc: use initalisers for struct resource
# 
# ChangeSet
#   2005/03/08 09:58:25-08:00 peter@p12n.org 
#   [PATCH] cross-compile scripts/lxdialog/ on AIX
#   
#   AIX curses.h defines macros 'clear_screen' and 'color_names' but does not
#   define 'scroll()'.
#   
#   Signed-Off-By: Peter Samuelson <peter@p12n.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# scripts/lxdialog/menubox.c
#   2005/03/07 20:41:42-08:00 peter@p12n.org +2 -2
#   cross-compile scripts/lxdialog/ on AIX
# 
# scripts/lxdialog/lxdialog.c
#   2005/03/07 20:41:42-08:00 peter@p12n.org +4 -4
#   cross-compile scripts/lxdialog/ on AIX
# 
# scripts/lxdialog/colors.h
#   2005/03/07 20:41:42-08:00 peter@p12n.org +0 -6
#   cross-compile scripts/lxdialog/ on AIX
# 
# scripts/lxdialog/checklist.c
#   2005/03/07 20:41:42-08:00 peter@p12n.org +1 -1
#   cross-compile scripts/lxdialog/ on AIX
# 
# ChangeSet
#   2005/03/08 09:58:10-08:00 Matthias.Kunze@gmx-topmail.de 
#   [PATCH] loglevel boot option
#   
#   Add a boot-time option to set the loglevel.  We already have `quiet' and
#   `debug', which set it to specific levels.  This is better.  
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# init/main.c
#   2005/03/07 21:14:28-08:00 Matthias.Kunze@gmx-topmail.de +8 -0
#   loglevel boot option
# 
# Documentation/kernel-parameters.txt
#   2005/03/07 20:41:42-08:00 Matthias.Kunze@gmx-topmail.de +14 -0
#   loglevel boot option
# 
# ChangeSet
#   2005/03/08 09:57:54-08:00 alexn@dsv.su.se 
#   [PATCH] ext3_new_inode() failure handling missing check
#   
#   There's a missing failure handling check here that would possibly lead to a
#   null dereference later on, I'm not sure about the correct return value
#   however.  I haven't tried it as I'm not sure how to trigger the case ;)
#   
#   Found by the Coverity tool.
#   
#   Signed-off-by: Alexander Nyberg <alexn@dsv.su.se>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# fs/ext3/ialloc.c
#   2005/03/07 20:41:42-08:00 alexn@dsv.su.se +4 -1
#   ext3_new_inode() failure handling missing check
# 
# ChangeSet
#   2005/03/08 09:57:39-08:00 dhowells@redhat.com 
#   [PATCH] Keys: Doc update on locking
#   
#   The attached patch updates the documentation on the kernel keys to describe
#   the locking associated with keys and key type operations.
#   
#   Signed-Off-By: David Howells <dhowells@redhat.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# Documentation/keys.txt
#   2005/03/07 20:41:42-08:00 dhowells@redhat.com +44 -11
#   Keys: Doc update on locking
# 
# ChangeSet
#   2005/03/08 09:57:23-08:00 vs@namesys.com 
#   [PATCH] reiserfs: return -EIO instead of calling BUG() when rename goes wrong
#   
#   This patch makes reiserfs to return -EIO when rename-ing went wrong instead
#   of calling BUG().
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# fs/reiserfs/namei.c
#   2005/03/07 20:41:41-08:00 vs@namesys.com +23 -7
#   reiserfs: return -EIO instead of calling BUG() when rename goes wrong
# 
# ChangeSet
#   2005/03/08 09:57:09-08:00 a.llano@usyscom.com 
#   [PATCH] Fix 1-Wire Dallas in bigendian machines
#   
#   I've been testing the 1-Wire Dallas in a bigendian machine (through a GPIO)
#   and I've found some problems that can easily addressed with the provided
#   patch.  (inline at the end of the message).
#   
#   I have a question about the implementation of w1_smem.
#   In the line 90 of drivers/w1/w1_smem.c.
#     for (i = 0; i < 9; ++i)
#        count += sprintf(buf + count, "%02x ", ((u8 *)&sl->reg_num)[i]);
#   I don't see why this loop is execute 9 times when the provided reg_num
#   is 8 bytes long. I don't understand the purpose of the last byte.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/w1/w1.h
#   2005/03/07 20:41:41-08:00 a.llano@usyscom.com +8 -0
#   Fix 1-Wire Dallas in bigendian machines
# 
# drivers/w1/w1.c
#   2005/03/07 20:41:41-08:00 a.llano@usyscom.com +4 -3
#   Fix 1-Wire Dallas in bigendian machines
# 
# ChangeSet
#   2005/03/08 09:56:54-08:00 pbadari@us.ibm.com 
#   [PATCH] Add nobh_writepage() support
#   
#   Add nobh_wripage() support for the filesystems which uses
#   nobh_prepare_write/nobh_commit_write().
#   
#   Idea here is to reduce unnecessary bufferhead creation/attachment to the
#   page through pageout()->block_write_full_page().  nobh_wripage() tries to
#   operate by directly creating bios, but it falls back to
#   __block_write_full_page() if it can't make progress.
#   
#   Note that this is not really generic routine and can't be used for
#   filesystems which uses page->Private for anything other than buffer heads.
#   
#   Signed-off-by: Badari Pulavarty <pbadari@us.ibm.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/linux/mpage.h
#   2005/03/07 20:41:41-08:00 pbadari@us.ibm.com +3 -0
#   Add nobh_writepage() support
# 
# include/linux/buffer_head.h
#   2005/03/07 20:41:41-08:00 pbadari@us.ibm.com +3 -0
#   Add nobh_writepage() support
# 
# fs/mpage.c
#   2005/03/07 20:41:41-08:00 pbadari@us.ibm.com +29 -5
#   Add nobh_writepage() support
# 
# fs/jfs/inode.c
#   2005/03/07 20:41:41-08:00 pbadari@us.ibm.com +1 -1
#   Add nobh_writepage() support
# 
# fs/ext2/inode.c
#   2005/03/07 20:41:41-08:00 pbadari@us.ibm.com +7 -1
#   Add nobh_writepage() support
# 
# fs/buffer.c
#   2005/03/07 20:41:41-08:00 pbadari@us.ibm.com +56 -0
#   Add nobh_writepage() support
# 
# ChangeSet
#   2005/03/08 09:56:38-08:00 pbadari@us.ibm.com 
#   [PATCH] export kallsyms_lookup_name()
#   
#   Export kallsyms_lookup_name() for kprobe/jprobe module use.
#   
#   (akpm: modules which use kprobes/jrobes are usually problem-specific and
#   will not be merged into the mainline kernel, so we we're actually to see
#   actual users of this patch merged)
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# kernel/kallsyms.c
#   2005/03/07 20:41:41-08:00 pbadari@us.ibm.com +1 -0
#   export kallsyms_lookup_name()
# 
# ChangeSet
#   2005/03/08 09:56:23-08:00 smurf@smurf.noris.de 
#   [PATCH] bksend example script fix
#   
#   The "bksend" example script doesn't work if PAGER (used by "bk changes")
#   is set to something which doesn't fallback to plain stdout if its output
#   isn't a tty.
#   
#   Fixed by forcing PAGER to be /bin/cat.
#   
#   Signed-Off-By: Matthias Urlichs <smurf@debian.org>
#   Acked-by: Jeff Garzik <jgarzik@pobox.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# Documentation/BK-usage/bksend
#   2005/03/07 20:41:41-08:00 smurf@smurf.noris.de +1 -1
#   bksend example script fix
# 
# ChangeSet
#   2005/03/08 09:56:07-08:00 smurf@smurf.noris.de 
#   [PATCH] CREDITS Update
#   
#   CREDITS update for Mattihas Urlichs.
#   
#   Signed-Off-By: Matthias Urlichs <smurf@debian.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# CREDITS
#   2005/03/07 20:41:41-08:00 smurf@smurf.noris.de +4 -3
#   CREDITS Update
# 
# ChangeSet
#   2005/03/08 09:55:52-08:00 rene.scharfe@lsrfire.ath.cx 
#   [PATCH] remove mount option parsing from procfs
#   
#   This patch removes the mount options of the proc filesystem.  They don't
#   have any effect since 2.4.something.
#   
#   Only proc_fill_super() calls parse_options, notably proc_remount() does
#   not.  And proc_fill_super() is only called at the very first mount which in
#   turn is the one caused by kern_mount() in fs/proc/root.c and that passes a
#   NULL pointer as mount options string.  It is called only once because proc
#   is a filesystem with a single super_block (i.e.  it uses get_sb_single()).
#   
#   Since noone seems to miss the uid and gid options so far I suggest to
#   simply remove them.  Their function can be easily performed in userspace.
#   E.g.  this (if it worked like intended):
#   
#       # mount -t proc -o uid=procuser,gid=procgrp proc /proc
#   
#   can be done like so, probably in some init script:
#   
#       # mount -t proc proc /proc && chown procuser:procgrp /proc
#   
#   But I don't see why anyone would want to do that in the first place.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# fs/proc/inode.c
#   2005/03/07 20:41:41-08:00 rene.scharfe@lsrfire.ath.cx +2 -47
#   remove mount option parsing from procfs
# 
# ChangeSet
#   2005/03/08 09:55:38-08:00 kraxel@bytesex.org 
#   [PATCH] tv tuner module update.
#   
#   Did some code reorganization: split up the source into four files:
#    - tuner-core.c for all the interfacing stuff (register driver,
#      handle insmod options, react on v4l ioctls, ...),
#    - tuner-simple.c for all those trivial 4-byte-command-sequence tuner
#      chips.
#    - mt20xx.c for the mt2032 and mt2050 tuners.
#    - tda8290.c for the tda8290/8272 combo (this code is new).
#   
#   I also did a number of cleanups like using dev_printk() for the
#   messages everythere.  There should be no functional changes beside
#   the new support for the tda8290 tuner.
#   
#   Signed-off-by: Gerd Knorr <kraxel@bytesex.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/media/video/tuner-simple.c
#   2005/03/08 09:55:29-08:00 kraxel@bytesex.org +467 -0
# 
# drivers/media/video/tuner-core.c
#   2005/03/08 09:55:29-08:00 kraxel@bytesex.org +443 -0
# 
# drivers/media/video/tda8290.c
#   2005/03/08 09:55:29-08:00 kraxel@bytesex.org +224 -0
# 
# include/media/tuner.h
#   2005/03/07 20:41:40-08:00 kraxel@bytesex.org +73 -4
#   tv tuner module update.
# 
# drivers/media/video/tveeprom.c
#   2005/03/07 20:41:40-08:00 kraxel@bytesex.org +1 -0
#   tv tuner module update.
# 
# drivers/media/video/tuner-simple.c
#   2005/03/08 09:55:29-08:00 kraxel@bytesex.org +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/drivers/media/video/tuner-simple.c
# 
# drivers/media/video/tuner-core.c
#   2005/03/08 09:55:29-08:00 kraxel@bytesex.org +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/drivers/media/video/tuner-core.c
# 
# drivers/media/video/tda9887.c
#   2005/03/07 20:41:40-08:00 kraxel@bytesex.org +1 -1
#   tv tuner module update.
# 
# drivers/media/video/tda8290.c
#   2005/03/08 09:55:29-08:00 kraxel@bytesex.org +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/drivers/media/video/tda8290.c
# 
# drivers/media/video/mt20xx.c
#   2005/03/08 09:55:28-08:00 kraxel@bytesex.org +557 -0
# 
# drivers/media/video/Makefile
#   2005/03/07 20:41:40-08:00 kraxel@bytesex.org +1 -0
#   tv tuner module update.
# 
# drivers/media/video/mt20xx.c
#   2005/03/08 09:55:28-08:00 kraxel@bytesex.org +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/drivers/media/video/mt20xx.c
# 
# BitKeeper/deleted/.del-tuner.c~f6eebc25b85fe165
#   2005/03/08 09:55:28-08:00 kraxel@bytesex.org +0 -0
#   Delete: drivers/media/video/tuner.c
# 
# ChangeSet
#   2005/03/08 09:54:59-08:00 kraxel@bytesex.org 
#   [PATCH] minor bttv driver update
#   
#   Just a new PCI Subsystem ID and a PM fix from Pavel.
#   
#   Signed-off-by: Gerd Knorr <kraxel@bytesex.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/media/video/bttvp.h
#   2005/03/07 20:41:40-08:00 kraxel@bytesex.org +1 -1
#   minor bttv driver update
# 
# drivers/media/video/bttv.h
#   2005/03/07 20:41:40-08:00 kraxel@bytesex.org +1 -1
#   minor bttv driver update
# 
# drivers/media/video/bttv-driver.c
#   2005/03/07 20:41:40-08:00 kraxel@bytesex.org +2 -2
#   minor bttv driver update
# 
# drivers/media/video/bttv-cards.c
#   2005/03/07 20:41:40-08:00 kraxel@bytesex.org +3 -1
#   minor bttv driver update
# 
# ChangeSet
#   2005/03/08 09:54:43-08:00 andrea@cpushare.com 
#   [PATCH] seccomp: secure computing support
#   
#   I'd need it merged into mainline at some point, unless anybody has strong
#   arguments against it.  All I can guarantee here, is that I'll back it out
#   myself in the future, iff Cpushare will fail and nobody else started using
#   it in the meantime for similar security purposes.
#   
#   (akpm: project details are at http://www.cpushare.com/technical.  It seems
#   like a good idea to me, and one which is worth supporting.  I agree that for
#   this to be successful, the added robustness of Andrea's simple and specific
#   jail is worthwhile).
#   
#   Signed-off-by: Andrea Arcangeli <andrea@cpushare.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# kernel/seccomp.c
#   2005/03/07 20:41:40-08:00 andrea@cpushare.com +74 -0
#   seccomp: secure computing support
# 
# kernel/seccomp.c
#   2005/03/07 20:41:40-08:00 andrea@cpushare.com +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/kernel/seccomp.c
# 
# kernel/Makefile
#   2005/03/07 21:14:16-08:00 andrea@cpushare.com +1 -0
#   seccomp: secure computing support
# 
# include/linux/seccomp.h
#   2005/03/07 20:41:40-08:00 andrea@cpushare.com +33 -0
#   seccomp: secure computing support
# 
# include/linux/sched.h
#   2005/03/07 21:14:16-08:00 andrea@cpushare.com +2 -0
#   seccomp: secure computing support
# 
# include/asm-x86_64/thread_info.h
#   2005/03/07 20:41:40-08:00 andrea@cpushare.com +4 -2
#   seccomp: secure computing support
# 
# include/asm-i386/thread_info.h
#   2005/03/07 20:41:40-08:00 andrea@cpushare.com +5 -2
#   seccomp: secure computing support
# 
# fs/proc/base.c
#   2005/03/07 20:41:40-08:00 andrea@cpushare.com +74 -0
#   seccomp: secure computing support
# 
# arch/x86_64/kernel/ptrace.c
#   2005/03/07 20:41:40-08:00 andrea@cpushare.com +4 -0
#   seccomp: secure computing support
# 
# arch/x86_64/kernel/entry.S
#   2005/03/07 20:41:40-08:00 andrea@cpushare.com +1 -1
#   seccomp: secure computing support
# 
# arch/x86_64/ia32/ia32entry.S
#   2005/03/07 20:41:40-08:00 andrea@cpushare.com +3 -3
#   seccomp: secure computing support
# 
# arch/x86_64/Kconfig
#   2005/03/07 20:41:40-08:00 andrea@cpushare.com +18 -0
#   seccomp: secure computing support
# 
# arch/i386/kernel/ptrace.c
#   2005/03/07 20:41:40-08:00 andrea@cpushare.com +4 -0
#   seccomp: secure computing support
# 
# arch/i386/kernel/entry.S
#   2005/03/07 20:41:40-08:00 andrea@cpushare.com +4 -2
#   seccomp: secure computing support
# 
# arch/i386/Kconfig
#   2005/03/07 20:41:40-08:00 andrea@cpushare.com +17 -0
#   seccomp: secure computing support
# 
# include/linux/seccomp.h
#   2005/03/07 20:41:40-08:00 andrea@cpushare.com +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/include/linux/seccomp.h
# 
# ChangeSet
#   2005/03/08 09:54:26-08:00 tim.bird@am.sony.com 
#   [PATCH] add timing information to printk messages
#   
#   Here's a little patch which is useful for showing timing information for
#   kernel bootup activities.
#   
#   This patch adds a new Kconfig option under "Kernel Hacking" and a new
#   option for the kernel command line.  It also provides a script for showing
#   delta information.
#   
#   Note that the timing data may not be correct on some platforms until after
#   time_init() is called.
#   
#   Recently (as of about 2.6.10) I found that the message log produced by
#   dmesg is truncated when I use this feature.  That is, the first few printk
#   messages of the boot sequence are not in the dmesg output, although they
#   are printed to console during startup.  This is a new behavior - dmesg
#   output was fine as of 2.6.9.  Increasing CONFIG_LOG_BUF_SHIFT had no effect
#   on the truncation.
#   
#   Has something changed with printk recently?
#   
#   For more information on this patch, see:
#   http://tree.celinuxforum.org/CelfPubWiki/InstrumentedPrintk
#   
#   Here's some sample output:
#   ...
#   [4294667.296000] Kernel command line: ro root=/dev/nfs ip=dhcp hdc=ide-scsi console=vga console=ttyS0,115200
#   [4294667.296000] ide_setup: hdc=ide-scsi
#   [4294667.296000] Initializing CPU#0
#   [4294667.296000] PID hash table entries: 512 (order: 9, 8192 bytes)
#   [    0.000000] Detected 1995.620 MHz processor.
#   [   21.397369] Using tsc for high-res timesource
#   [   21.399820] Console: colour VGA+ 80x25
#   [   21.537244] Dentry cache hash table entries: 32768 (order: 5, 131072 bytes)
#   [   21.544547] Inode-cache hash table entries: 16384 (order: 4, 65536 bytes)
#   [   21.555066] Memory: 125076k/130240k available (2002k kernel code, 4556k reserved, 1006k data, 140k init, 0k highmem)
#   [   21.565775] Checking if this processor honours the WP bit even in supervisor mode... Ok.
#   [   21.574089] Calibrating delay loop... 3940.35 BogoMIPS (lpj=1970176)
#   [   21.596511] Mount-cache hash table entries: 512 (order: 0, 4096 bytes)
#   [   21.603263] CPU: After generic identify, caps: bfebfbff 00000000 00000000 00000000 00004400 00000000 00000000
#   [   21.603276] CPU: After vendor identify, caps: bfebfbff 00000000 00000000 00000000 00004400 00000000 00000000
#   [   21.603287] CPU: Trace cache: 12K uops, L1 D cache: 8K
#   [   21.608884] CPU: L2 cache: 128K
#   ...
#   
#   And now the patch...
#   
#   Signed-off-by: Tim Bird <tim.bird@am.sony.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# scripts/show_delta
#   2005/03/07 20:41:40-08:00 tim.bird@am.sony.com +129 -0
#   add timing information to printk messages
# 
# lib/Kconfig.debug
#   2005/03/07 20:41:40-08:00 tim.bird@am.sony.com +9 -0
#   add timing information to printk messages
# 
# kernel/printk.c
#   2005/03/07 20:41:40-08:00 tim.bird@am.sony.com +54 -4
#   add timing information to printk messages
# 
# Documentation/kernel-parameters.txt
#   2005/03/07 21:14:29-08:00 tim.bird@am.sony.com +2 -0
#   add timing information to printk messages
# 
# scripts/show_delta
#   2005/03/07 20:41:40-08:00 tim.bird@am.sony.com +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/scripts/show_delta
# 
# ChangeSet
#   2005/03/08 09:54:10-08:00 aia21@cam.ac.uk 
#   [PATCH] a_ops-based loop I/O
#   
#   Implements fallback to file_operations->write in the case that
#   aops->{prepare,commit}_write are not present on the backing filesystem.
#   
#   The fallback happens in two different ways:
#   
#   - For normal loop devices, i.e.  ones which do not do transformation on
#     the data but simply pass it along, we simply call fops->write.  This
#     should be pretty much just as fast as using aops->{prepare,commit}_write
#     directly.
#   
#   - For all other loop devices (e.g.  xor and cryptoloop), i.e.  all the
#     ones which may be doing transformations on the data, we allocate and map
#     a page (once for each bio), then for each bio vec we copy the bio vec
#     page data to our mapped page, apply the loop transformation, and use
#     fops->write to write out the transformed data from our page.  Once all
#     bio vecs from the bio are done, we unmap and free the page.
#   
#   This approach is the absolute minimum of overhead I could come up with and
#   for performance hungry people, as you can see I left the address space
#   operations method in place for filesystems which implement
#   aops->{prepare,commit}_write.
#   
#   I have tested this patch with normal loop devices using
#   aops->{prepare,commit}_write on the backing filesystem, with normal loop
#   devices using the fops->write code path and with cryptoloop devices using
#   the double buffering + fops->write code path.
#   
#   Signed-off-by: Anton Altaparmakov <aia21@cantab.net>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/linux/loop.h
#   2005/03/07 20:41:40-08:00 aia21@cam.ac.uk +4 -1
#   a_ops-based loop I/O
# 
# drivers/block/loop.c
#   2005/03/07 20:41:40-08:00 aia21@cam.ac.uk +132 -27
#   a_ops-based loop I/O
# 
# ChangeSet
#   2005/03/08 09:53:55-08:00 zwane@arm.linux.org.uk 
#   [PATCH] Run softirqs on proper processor on offline
#   
#   We take down ksoftirqds at CPU_DEAD time, so there is a brief period whereupon
#   there is a ksoftirqd thread for an offline processor, it is at this point that
#   ->cpus_allowed won't have it pinned anymore.  An online processor would then
#   take down that ksoftirqd and exit it.
#   
#   Ensure that we only offline the processor when it's safe and never run
#   softirqs in another processor's ksoftirqd context.  This also gets rid of the
#   warnings in ksoftirqd on cpu offline.
#   
#   Signed-off-by: Zwane Mwaikambo <zwane@arm.linux.org.uk>
#   Acked-by: Ingo Molnar <mingo@elte.hu>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# kernel/softirq.c
#   2005/03/07 20:41:40-08:00 zwane@arm.linux.org.uk +8 -4
#   Run softirqs on proper processor on offline
# 
# ChangeSet
#   2005/03/08 09:53:40-08:00 jack@suse.cz 
#   [PATCH] Implement quota reading and writing functions for UFS.
#   
#   Attached patch adds functions ufs_quota_read() and ufs_quota_write() to the
#   UFS code.  So quotas for UFS should work again (they were broken by the
#   quota io redesign).  I don't actually think the patch is too much important
#   as I'm not sure anybody uses quotas on UFS but we're in the "stable" branch
#   so just dropping a support did not seem right to me.
#   
#   Signed-off-by: Jan Kara <jack@suse.cz>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# fs/ufs/super.c
#   2005/03/07 20:41:39-08:00 jack@suse.cz +99 -0
#   Implement quota reading and writing functions for UFS.
# 
# ChangeSet
#   2005/03/08 09:53:24-08:00 dmo@osdl.org 
#   [PATCH] add local bio pool support and modify dm
#   
#   I've had this patch reviewed by Jens, and incorporated his recommended
#   fixes.
#   
#   The patch adds new interfaces to bio.c that support the creation of local
#   bio and bvec pools.  This is important for layered drivers that need to
#   allocate new bio and bvec structures in response to bio's submitted to it
#   from higher up.  The layered drivers can allocate local pools of bio
#   structures to preclude deadlock under global bio pool exhaustion.
#   
#   The device mapper source files have been modified to remove duplicate bio
#   code, and to use the new interfaces to create local bio pools.
#   
#   From: Dave Olien <dmo@osdl.org>
#   
#   Change bio_clone() to use the global bio_set pool instead of the bio_set pool
#   associated with the bio argument.  This is because raid5 and raid6 bio's are
#   not allocated from a bio_set and have no bio_set associated with them.  This
#   patch along with the patch Linux just accepted allows raid5 and raid6 to
#   function.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/linux/bio.h
#   2005/03/07 20:41:39-08:00 dmo@osdl.org +7 -0
#   add local bio pool support and modify dm
# 
# fs/bio.c
#   2005/03/07 20:41:39-08:00 dmo@osdl.org +160 -54
#   add local bio pool support and modify dm
# 
# drivers/md/dm.c
#   2005/03/07 20:41:39-08:00 dmo@osdl.org +9 -1
#   add local bio pool support and modify dm
# 
# drivers/md/dm-zero.c
#   2005/03/07 20:41:39-08:00 dmo@osdl.org +0 -17
#   add local bio pool support and modify dm
# 
# drivers/md/dm-io.c
#   2005/03/07 20:41:39-08:00 dmo@osdl.org +7 -212
#   add local bio pool support and modify dm
# 
# ChangeSet
#   2005/03/08 09:53:09-08:00 mingo@elte.hu 
#   [PATCH] clean up and unify asm-*/resource.h files
#   
#   This patch does the final consolidation of asm-*/resource.h file, without
#   changing any of the rlimit definitions on any architecture.  Primarily it
#   removes the __ARCH_RLIMIT_ORDER method and replaces it with a more compact
#   and isolated one that allows architectures to define only the offending
#   rlimits.
#   
#   This method has the positive effect that adding a new rlimit can now be
#   purely done via changing asm-generic/resource.h alone.  Previously one
#   would have to patch 4 other (sparc, sparc64, alpha and mips) resource.h
#   files.
#   
#   The patch also does style unification, whitespace cleanups and
#   simplification of resource.h files and cleans up the asm-generic/resource.h
#   file as well.  I've added more comments too.
#   
#   This patch should have no effect on any code on any architecture.  (i.e.
#   it's a pure identity patch.)
#   
#   Tested on x86 and carefully reviewed to make sure that Sparc, Sparc64,
#   MIPS and Alpha rlimits are still the same as required by the ABI.
#   
#   Signed-off-by: Ingo Molnar <mingo@elte.hu>
#   Acked-by: Chris Wright <chrisw@osdl.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/asm-sparc64/resource.h
#   2005/03/07 20:41:39-08:00 mingo@elte.hu +4 -18
#   clean up and unify asm-*/resource.h files
# 
# include/asm-sparc/resource.h
#   2005/03/07 20:41:39-08:00 mingo@elte.hu +6 -20
#   clean up and unify asm-*/resource.h files
# 
# include/asm-mips/resource.h
#   2005/03/07 20:41:39-08:00 mingo@elte.hu +13 -23
#   clean up and unify asm-*/resource.h files
# 
# include/asm-generic/resource.h
#   2005/03/07 21:14:14-08:00 mingo@elte.hu +51 -23
#   clean up and unify asm-*/resource.h files
# 
# include/asm-alpha/resource.h
#   2005/03/07 20:41:39-08:00 mingo@elte.hu +7 -19
#   clean up and unify asm-*/resource.h files
# 
# ChangeSet
#   2005/03/08 09:52:53-08:00 ken@mvista.com 
#   [PATCH] drivers/char/lp.c race fix
#   
#   In lp_write(), copy_from_user() is called to copy data into a statically
#   allocated kernel buffer before down_interruptible() is called.  If a second
#   thread of execution comes in between the copy_from_user() and the
#   down_interruptible() calls, silent data corruption could result.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/char/lp.c
#   2005/03/07 20:41:39-08:00 ken@mvista.com +6 -4
#   drivers/char/lp.c race fix
# 
# ChangeSet
#   2005/03/08 09:52:39-08:00 shemminger@osdl.org 
#   [PATCH] convert /proc/driver/rtc to seq_file.
#   
#   The /proc/driver/rtc interface didn't have any module owner hook.  The
#   simplest fix is to just convert this to the single version of seq_file. 
#   Also, fix initialization of rtc_dev to use C99 form.
#   
#   Signed-off-by: Stephen Hemminger <shemminger@osdl.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/char/rtc.c
#   2005/03/07 20:41:39-08:00 shemminger@osdl.org +55 -53
#   convert /proc/driver/rtc to seq_file.
# 
# ChangeSet
#   2005/03/08 09:52:24-08:00 bunk@stusta.de 
#   [PATCH] add compiler-gcc4.h
#   
#   With the release of gcc 4.0 being only a few months away and people
#   already tring compiling with it, it's time for adding a compiler-gcc4.h .
#   
#   This patch contains the following changes:
#   - remove compiler-gcc+.h
#   - compiler-gcc4.h: new file based on a corrected compiler-gcc+.h
#   - compiler.h: include compiler-gcc4.h for gcc 4
#   - compiler.h: #error for gcc > 4
#   - compiler-gcc3.h: remove __compiler_offsetof (there will never be a
#                                                  gcc 3.5)
#                      small indention corrections
#   
#   I've tested the compilation with both gcc 3.4.4 and a recent gcc 4.0 
#   snapshot from Debian experimental.
#   
#   Signed-off-by: Adrian Bunk <bunk@stusta.de>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/linux/compiler.h
#   2005/03/07 20:41:38-08:00 bunk@stusta.de +4 -2
#   add compiler-gcc4.h
# 
# include/linux/compiler-gcc4.h
#   2005/03/07 20:41:38-08:00 bunk@stusta.de +4 -4
#   add compiler-gcc4.h
# 
# include/linux/compiler-gcc3.h
#   2005/03/07 20:41:38-08:00 bunk@stusta.de +4 -6
#   add compiler-gcc4.h
# 
# ChangeSet
#   2005/03/08 09:51:51-08:00 petrides@redhat.com 
#   [PATCH] minor conceptual fix for /proc/kcore header size
#   
#   While investigating the 2.4 memory corruption problem fixed by the patch
#   previously posted, it was noticed that the 2.6 version of get_kcore_size()
#   inappropriately uses sizeof(struct memelfnote) in its calculation of the
#   /proc/kcore ELF header size.  What is actually stored in the header is an
#   "elf_note" structure plus the 4 ASCII chars "CORE".
#   
#   It just so happens that on 32-bit arches, both calculations result in the
#   same value (16).  But on 64-bit arches, the allocated size (24) is larger
#   than necessary (16).  This does not result in any possible data corruption,
#   but it might be nice to correct this "conceptual" error.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# fs/proc/kcore.c
#   2005/03/07 20:41:38-08:00 petrides@redhat.com +1 -1
#   minor conceptual fix for /proc/kcore header size
# 
# ChangeSet
#   2005/03/08 09:51:35-08:00 yuasa@hh.iij4u.or.jp 
#   [PATCH] serial: update vr41xx_siu
#   
#   This patch updates serial driver for VR41xx serial unit.  Some check are
#   added to verify_port.
#   
#   Signed-off-by: Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
#   Cc: Russell King <rmk@arm.linux.org.uk>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/serial/vr41xx_siu.c
#   2005/03/07 20:41:38-08:00 yuasa@hh.iij4u.or.jp +10 -2
#   serial: update vr41xx_siu
# 
# ChangeSet
#   2005/03/08 09:51:21-08:00 arun.sharma@intel.com 
#   [PATCH] add TCSBRKP to compat_ioctl.h
#   
#   Move ioctl TCSBRKP support to compat layer. Same rationale as TCSBRK.
#   
#   - Remove corresponding code under ppc64, sparc64 and s390.
#   - Use ULONG_IOCTL() instead of COMPATIBLE_IOCTL(), since the argument is int, 
#     not pointer.
#   
#   Signed-off-by: Gordon Jin <gordon.jin@intel.com>
#   Signed-off-by: Arun Sharma <arun.sharma@intel.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/linux/compat_ioctl.h
#   2005/03/07 20:41:38-08:00 arun.sharma@intel.com +1 -0
#   add TCSBRKP to compat_ioctl.h
# 
# arch/sparc64/kernel/ioctl32.c
#   2005/03/07 20:41:38-08:00 arun.sharma@intel.com +0 -1
#   add TCSBRKP to compat_ioctl.h
# 
# arch/s390/kernel/compat_ioctl.c
#   2005/03/07 20:41:38-08:00 arun.sharma@intel.com +0 -3
#   add TCSBRKP to compat_ioctl.h
# 
# arch/ppc64/kernel/ioctl32.c
#   2005/03/07 20:41:38-08:00 arun.sharma@intel.com +0 -1
#   add TCSBRKP to compat_ioctl.h
# 
# ChangeSet
#   2005/03/08 09:51:06-08:00 mingo@elte.hu 
#   [PATCH] sys_setpriority() euid semantics fix
#   
#   What _is_ inconsistent is kernel/sys.c's setpriority()/set_one_prio().
#   
#   It checks current->euid|uid against p->uid, which makes little sense, but
#   is how we've been doing it ever since.  It's a Linux quirk documented in
#   the manpage.  To make things funnier, SuS requires current->euid|uid match
#   against p->euid.
#   
#   The patch below fixes it (and brings the logic in line with what
#   setscheduler()/setaffinity() does), but if we do it then it should be done
#   only in 2.6.12 or later, after good exposure in -mm.
#   
#   (Worst-case this could break an application but i highly doubt it: it at
#   most could deny renicing another task to positive (or in very rare cases,
#   to negative) nice values, which no application should crash on something
#   like that, normally.)
#   
#   Signed-off-by: Ingo Molnar <mingo@elte.hu>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# kernel/sys.c
#   2005/03/07 21:14:14-08:00 mingo@elte.hu +2 -1
#   sys_setpriority() euid semantics fix
# 
# ChangeSet
#   2005/03/08 09:50:52-08:00 yuasa@hh.iij4u.or.jp 
#   [PATCH] serial: add the output interface control to VR41xx SIU driver
#   
#   This patch adds the output interface control to VR41xx SIU driver.
#   And obsolete function for VR41xx SIU is removed.
#   
#   And add __init for the function used only for initialization.
#   
#   Signed-off-by: Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
#   Cc: Russell King <rmk@arm.linux.org.uk>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/asm-mips/vr41xx/vr41xx.h
#   2005/03/07 20:41:37-08:00 yuasa@hh.iij4u.or.jp +0 -26
#   serial: add the output interface control to VR41xx SIU driver
# 
# include/asm-mips/vr41xx/siu.h
#   2005/03/08 09:50:41-08:00 yuasa@hh.iij4u.or.jp +50 -0
# 
# drivers/serial/vr41xx_siu.c
#   2005/03/07 21:14:34-08:00 yuasa@hh.iij4u.or.jp +94 -11
#   serial: add the output interface control to VR41xx SIU driver
# 
# arch/mips/vr41xx/zao-capcella/setup.c
#   2005/03/07 20:41:37-08:00 yuasa@hh.iij4u.or.jp +1 -17
#   serial: add the output interface control to VR41xx SIU driver
# 
# arch/mips/vr41xx/victor-mpc30x/setup.c
#   2005/03/07 20:41:37-08:00 yuasa@hh.iij4u.or.jp +1 -16
#   serial: add the output interface control to VR41xx SIU driver
# 
# arch/mips/vr41xx/tanbac-tb0229/setup.c
#   2005/03/07 20:41:37-08:00 yuasa@hh.iij4u.or.jp +1 -17
#   serial: add the output interface control to VR41xx SIU driver
# 
# arch/mips/vr41xx/tanbac-tb0226/setup.c
#   2005/03/07 20:41:37-08:00 yuasa@hh.iij4u.or.jp +1 -16
#   serial: add the output interface control to VR41xx SIU driver
# 
# arch/mips/vr41xx/nec-cmbvr4133/setup.c
#   2005/03/07 20:41:37-08:00 yuasa@hh.iij4u.or.jp +0 -12
#   serial: add the output interface control to VR41xx SIU driver
# 
# arch/mips/vr41xx/ibm-workpad/setup.c
#   2005/03/07 20:41:37-08:00 yuasa@hh.iij4u.or.jp +4 -9
#   serial: add the output interface control to VR41xx SIU driver
# 
# arch/mips/vr41xx/common/Makefile
#   2005/03/07 20:41:37-08:00 yuasa@hh.iij4u.or.jp +0 -1
#   serial: add the output interface control to VR41xx SIU driver
# 
# arch/mips/vr41xx/casio-e55/setup.c
#   2005/03/07 20:41:37-08:00 yuasa@hh.iij4u.or.jp +4 -9
#   serial: add the output interface control to VR41xx SIU driver
# 
# include/asm-mips/vr41xx/siu.h
#   2005/03/08 09:50:41-08:00 yuasa@hh.iij4u.or.jp +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/include/asm-mips/vr41xx/siu.h
# 
# BitKeeper/deleted/.del-serial.c~259829ce2d6d46fa
#   2005/03/08 09:50:41-08:00 yuasa@hh.iij4u.or.jp +0 -0
#   Delete: arch/mips/vr41xx/common/serial.c
# 
# ChangeSet
#   2005/03/08 09:50:18-08:00 yuasa@hh.iij4u.or.jp 
#   [PATCH] serial: add NEC VR4100 series serial support
#   
#   This patch adds serial driver for NEC VR4100 series serial interface unit.
#   
#   The new device numbers have been recorded by LANANA.
#   
#   Signed-off-by: Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
#   Cc: Russell King <rmk@arm.linux.org.uk>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/linux/serial_core.h
#   2005/03/07 20:41:37-08:00 yuasa@hh.iij4u.or.jp +4 -0
#   serial: add NEC VR4100 series serial support
# 
# include/asm-mips/vr41xx/vr41xx.h
#   2005/03/07 21:14:35-08:00 yuasa@hh.iij4u.or.jp +0 -2
#   serial: add NEC VR4100 series serial support
# 
# drivers/serial/vr41xx_siu.c
#   2005/03/07 21:14:35-08:00 yuasa@hh.iij4u.or.jp +1009 -0
#   serial: add NEC VR4100 series serial support
# 
# drivers/serial/Makefile
#   2005/03/07 20:41:37-08:00 yuasa@hh.iij4u.or.jp +1 -0
#   serial: add NEC VR4100 series serial support
# 
# drivers/serial/Kconfig
#   2005/03/07 20:41:37-08:00 yuasa@hh.iij4u.or.jp +17 -0
#   serial: add NEC VR4100 series serial support
# 
# arch/mips/vr41xx/common/cmu.c
#   2005/03/07 20:41:37-08:00 yuasa@hh.iij4u.or.jp +1 -1
#   serial: add NEC VR4100 series serial support
# 
# Documentation/devices.txt
#   2005/03/07 20:41:37-08:00 yuasa@hh.iij4u.or.jp +4 -0
#   serial: add NEC VR4100 series serial support
# 
# drivers/serial/vr41xx_siu.c
#   2005/03/07 21:14:35-08:00 yuasa@hh.iij4u.or.jp +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/drivers/serial/vr41xx_siu.c
# 
# ChangeSet
#   2005/03/08 09:50:03-08:00 mingo@elte.hu 
#   [PATCH] annotate /proc/<PID>/maps with [heap]/[stack]/[vdso] markers
#   
#   This patch makes the /proc/<PID>/maps file easier to parse (both for humans
#   and for applications), by annotating the heap, stack and vdso mappings with
#   [heap], [stack] and [vdso] markers.
#   
#   It makes it easier/faster to determine at a quick glance whether an
#   application has a secure VM layout, and it also makes it easier for tools
#   to determine whether e.g.  the heap or stack is executable or not.
#   
#   new maps file, on a patched kernel:
#   
#    001c4000-001d9000 r-xp 00000000 03:01 19954      /lib/ld-2.3.3.so
#    001d9000-001db000 rw-p 00014000 03:01 19954      /lib/ld-2.3.3.so
#    001dd000-002fb000 r-xp 00000000 03:01 19960      /lib/tls/libc-2.3.3.so
#    002fb000-002fd000 r--p 0011d000 03:01 19960      /lib/tls/libc-2.3.3.so
#    002fd000-002ff000 rw-p 0011f000 03:01 19960      /lib/tls/libc-2.3.3.so
#    002ff000-00301000 rw-p 002ff000 00:00 0
#    08048000-0804c000 r-xp 00000000 03:01 31968      /bin/cat
#    0804c000-0804d000 rw-p 00003000 03:01 31968      /bin/cat
#    0804d000-0806e000 rw-p 0804d000 00:00 0          [heap]
#    b7dbc000-b7dbd000 r--p 009d1000 03:01 83628      /usr/lib/locale/locale-archive
#    b7dbd000-b7dc4000 r--p 0097d000 03:01 83628      /usr/lib/locale/locale-archive
#    b7dc4000-b7df1000 r--p 0094a000 03:01 83628      /usr/lib/locale/locale-archive
#    b7df1000-b7ff1000 r--p 00000000 03:01 83628      /usr/lib/locale/locale-archive
#    b7ff1000-b7ff2000 rw-p b7ff1000 00:00 0
#    bffeb000-c0000000 rw-p bffeb000 00:00 0          [stack]
#    ffffe000-fffff000 ---p 00000000 00:00 0          [vdso]
#   
#   Tested on x86, but should work on all architectures.
#   
#   Signed-off-by: Ingo Molnar <mingo@elte.hu>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# fs/proc/task_mmu.c
#   2005/03/07 21:14:16-08:00 mingo@elte.hu +32 -4
#   annotate /proc/<PID>/maps with [heap]/[stack]/[vdso] markers
# 
# ChangeSet
#   2005/03/08 09:49:48-08:00 axboe@suse.de 
#   [PATCH] blk_execute_rq() oops on fast completion
#   
#   blk_execute_rq() can oops in wait_for_completion(), if the request has
#   completed before we call wait_for_completion() because blk_end_sync_rq()
#   clears ->waiting when it is entered.  Fix this by always using the on-stack
#   completion variable instead.
#   
#   Signed-off-by: Jens Axboe <axboe@suse.de>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/block/ll_rw_blk.c
#   2005/03/07 20:41:37-08:00 axboe@suse.de +1 -1
#   blk_execute_rq() oops on fast completion
# 
# ChangeSet
#   2005/03/08 09:49:33-08:00 axboe@suse.de 
#   [PATCH] scsi_io_completion sense copy
#   
#   For the flush generated requests, we don't have room for sense info right
#   now.  This might change in the future so that the sd end_io function can
#   make a better judgement on what to do about an error.  So check this in
#   scsi_io_completion(), only copy sense data to request if it has space
#   assigned to it.
#   
#   Signed-off-by: Jens Axboe <axboe@suse.de>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/scsi/scsi_lib.c
#   2005/03/07 20:41:37-08:00 axboe@suse.de +1 -1
#   scsi_io_completion sense copy
# 
# ChangeSet
#   2005/03/08 09:49:17-08:00 axboe@suse.de 
#   [PATCH] rework core barrier support
#   
#   This reworks the core barrier support to be a lot nicer, so that all the
#   nasty code resides outside of drivers/ide.  It requires minimal changes to
#   support in a driver, I've added SCSI support as an example.  The ide code
#   is adapted to the new code.
#   
#   With this patch, we support full barriers on sata now.  Bart has acked the
#   addition to -mm, I would like for this to be submitted as soon as 2.6.12
#   opens.
#   
#   Signed-off-by: Jens Axboe <axboe@suse.de>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/scsi/scsi_host.h
#   2005/03/07 20:41:36-08:00 axboe@suse.de +12 -0
#   rework core barrier support
# 
# include/scsi/scsi_driver.h
#   2005/03/07 20:41:36-08:00 axboe@suse.de +2 -0
#   rework core barrier support
# 
# include/linux/ide.h
#   2005/03/07 20:41:36-08:00 axboe@suse.de +1 -1
#   rework core barrier support
# 
# include/linux/blkdev.h
#   2005/03/07 20:41:36-08:00 axboe@suse.de +22 -2
#   rework core barrier support
# 
# drivers/scsi/sd.c
#   2005/03/07 20:41:36-08:00 axboe@suse.de +31 -0
#   rework core barrier support
# 
# drivers/scsi/scsi_lib.c
#   2005/03/07 21:14:36-08:00 axboe@suse.de +46 -0
#   rework core barrier support
# 
# drivers/scsi/sata_vsc.c
#   2005/03/07 20:41:36-08:00 axboe@suse.de +1 -0
#   rework core barrier support
# 
# drivers/scsi/sata_via.c
#   2005/03/07 20:41:36-08:00 axboe@suse.de +1 -0
#   rework core barrier support
# 
# drivers/scsi/sata_uli.c
#   2005/03/07 20:41:36-08:00 axboe@suse.de +1 -0
#   rework core barrier support
# 
# drivers/scsi/sata_sx4.c
#   2005/03/07 20:41:36-08:00 axboe@suse.de +1 -0
#   rework core barrier support
# 
# drivers/scsi/sata_svw.c
#   2005/03/07 20:41:36-08:00 axboe@suse.de +1 -0
#   rework core barrier support
# 
# drivers/scsi/sata_sis.c
#   2005/03/07 20:41:36-08:00 axboe@suse.de +1 -0
#   rework core barrier support
# 
# drivers/scsi/sata_sil.c
#   2005/03/07 20:41:36-08:00 axboe@suse.de +1 -0
#   rework core barrier support
# 
# drivers/scsi/sata_promise.c
#   2005/03/07 20:41:36-08:00 axboe@suse.de +1 -0
#   rework core barrier support
# 
# drivers/scsi/sata_nv.c
#   2005/03/07 20:41:36-08:00 axboe@suse.de +1 -0
#   rework core barrier support
# 
# drivers/scsi/hosts.c
#   2005/03/07 20:41:36-08:00 axboe@suse.de +10 -0
#   rework core barrier support
# 
# drivers/scsi/ata_piix.c
#   2005/03/07 20:41:36-08:00 axboe@suse.de +1 -0
#   rework core barrier support
# 
# drivers/scsi/ahci.c
#   2005/03/07 20:41:36-08:00 axboe@suse.de +1 -0
#   rework core barrier support
# 
# drivers/ide/ide-io.c
#   2005/03/07 20:41:36-08:00 axboe@suse.de +8 -151
#   rework core barrier support
# 
# drivers/ide/ide-disk.c
#   2005/03/07 20:41:36-08:00 axboe@suse.de +65 -8
#   rework core barrier support
# 
# drivers/block/ll_rw_blk.c
#   2005/03/07 21:14:36-08:00 axboe@suse.de +207 -21
#   rework core barrier support
# 
# drivers/block/elevator.c
#   2005/03/07 20:41:36-08:00 axboe@suse.de +15 -1
#   rework core barrier support
# 
# ChangeSet
#   2005/03/08 09:49:01-08:00 axboe@suse.de 
#   [PATCH] Add struct request end_io callback
#   
#   This is needed for several things, one in-tree user which I will introduce
#   after this patch.
#   
#   This adds a ->end_io callback to struct request, so it can be used with
#   async io of any sort.  Right now users have to wait for completion in a
#   blocking manner.  In the next iteration, ->waiting can be folded into
#   ->end_io_data since it is just a special case of that use.
#   
#   From: Peter Osterlund <petero2@telia.com>
#   
#   The problem is that the add-struct-request-end_io-callback patch forgot to
#   update pktcdvd.c.  This patch fixes it.
#   
#   Signed-off-by: Jens Axboe <axboe@suse.de>
#   Signed-off-by: Peter Osterlund <petero2@telia.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/linux/blkdev.h
#   2005/03/07 21:14:36-08:00 axboe@suse.de +10 -1
#   Add struct request end_io callback
# 
# drivers/ide/ide-tape.c
#   2005/03/07 20:41:36-08:00 axboe@suse.de +1 -0
#   Add struct request end_io callback
# 
# drivers/ide/ide-io.c
#   2005/03/07 21:14:36-08:00 axboe@suse.de +1 -0
#   Add struct request end_io callback
# 
# drivers/block/pktcdvd.c
#   2005/03/07 20:41:36-08:00 axboe@suse.de +1 -0
#   Add struct request end_io callback
# 
# drivers/block/paride/pd.c
#   2005/03/07 20:41:36-08:00 axboe@suse.de +1 -0
#   Add struct request end_io callback
# 
# drivers/block/ll_rw_blk.c
#   2005/03/07 21:14:36-08:00 axboe@suse.de +28 -8
#   Add struct request end_io callback
# 
# ChangeSet
#   2005/03/08 09:48:44-08:00 j.blunck@tu-harburg.de 
#   [PATCH] d_drop should use per dentry lock
#   
#   d_drop() must use the dentry->d_lock spinlock.  In some cases __d_drop()
#   was used without holding the dentry->d_lock spinlock, too.  This could end
#   in a race with __d_lookup().
#   
#   Signed-off-by: Jan Blunck <j.blunck@tu-harburg.de>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/linux/dcache.h
#   2005/03/07 20:41:36-08:00 j.blunck@tu-harburg.de +10 -9
#   d_drop should use per dentry lock
# 
# fs/sysfs/inode.c
#   2005/03/07 20:41:36-08:00 j.blunck@tu-harburg.de +5 -1
#   d_drop should use per dentry lock
# 
# fs/proc/base.c
#   2005/03/07 21:14:32-08:00 j.blunck@tu-harburg.de +5 -1
#   d_drop should use per dentry lock
# 
# fs/namei.c
#   2005/03/07 20:41:36-08:00 j.blunck@tu-harburg.de +5 -9
#   d_drop should use per dentry lock
# 
# fs/dcache.c
#   2005/03/07 20:41:36-08:00 j.blunck@tu-harburg.de +3 -0
#   d_drop should use per dentry lock
# 
# fs/autofs4/root.c
#   2005/03/07 20:41:36-08:00 j.blunck@tu-harburg.de +2 -0
#   d_drop should use per dentry lock
# 
# ChangeSet
#   2005/03/08 09:48:29-08:00 dhowells@redhat.com 
#   [PATCH] Fix kallsyms/insmod/rmmod race
#   
#   The attached patch fixes a race between kallsyms and insmod/rmmod.
#   
#   The problem is this:
#   
#    (1) The various kallsyms functions poke around in the module list without any
#        locking so that they can be called from the oops handler.
#   
#    (2) Although insmod and rmmod use locks to exclude each other, these have no
#        effect on the kallsyms function.
#   
#    (3) Although rmmod modifies the module state with the machine "stopped", it
#        hasn't removed the metadata from the module metadata list, meaning that
#        as soon as the machine is "restarted", the metadata can be observed by
#        kallsyms.
#   
#        It's not possible to say that an item in that list should be ignored if
#        it's state is marked as inactive - you can't get at the state information
#        because you can't trust the metadata in which it is embedded.
#   
#        Furthermore, list linkage information is embedded in the metadata too, so
#        you can't trust that either...
#   
#    (4) kallsyms may be walking the module list without a lock whilst either
#        insmod or rmmod are busy changing it. insmod probably isn't a problem
#        since nothing is going a way, but rmmod is as it's deleting an entry.
#   
#    (5) Therefore nothing that uses these functions can in any way trust any
#        pointers to "static" data (such as module symbol names or module names)
#        that are returned.
#   
#    (6) On ppc64 the problems are exacerbated since the hypervisor may reschedule
#        bits of the kernel, making operations that appear adjacent occur a long
#        time apart.
#   
#   This patch fixes the race by only linking/unlinking modules into/from the
#   master module list with the machine in the "stopped" state. This means that
#   any "static" information can be trusted as far as the next kernel reschedule
#   on any given CPU without the need to hold any locks.
#   
#   However, I'm not sure how this is affected by preemption. I suspect more work
#   may need to be done in that case, but I'm not entirely sure.
#   
#   This also means that rmmod has to bump the machine into the stopped state
#   twice... but since that shouldn't be a common operation, I don't think that's
#   a problem.
#   
#   I've amended this patch to not get spinlocks whilst in the machine locked
#   state - there's no point as nothing else can be holding spinlocks.
#   
#   Signed-Off-By: David Howells <dhowells@redhat.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# kernel/module.c
#   2005/03/07 20:41:36-08:00 dhowells@redhat.com +25 -8
#   Fix kallsyms/insmod/rmmod race
# 
# kernel/kallsyms.c
#   2005/03/07 21:14:30-08:00 dhowells@redhat.com +14 -2
#   Fix kallsyms/insmod/rmmod race
# 
# include/linux/stop_machine.h
#   2005/03/07 20:41:36-08:00 dhowells@redhat.com +1 -1
#   Fix kallsyms/insmod/rmmod race
# 
# ChangeSet
#   2005/03/08 09:48:14-08:00 Liam.Girdwood@wolfsonmicro.com 
#   [PATCH] OSS Support for AC97 low power codecs
#   
#   This is a resend of a patch that has been applied to 2.4.  The low power
#   codec functionality has also now been included in ALSA.
#   
#   It checks the codec ID before doing an AC97 register reset.  This allows
#   the kernel to support low power codecs that are powered down by a reset
#   command.  This patch also fixes some other minor issues.
#   
#   Changes:-
#   
#   - Added AC97_DEFAULT_POWER_OFF to ac97_codec_ids[]
#   
#   - ac97_probe now checks hardwired codec ID's before sending a reset
#   
#   - Added support for WM9713
#   
#   - Moved the codec specific inits after the mixer setup as some init
#   
#   - tings were being clobbered.
#   
#   - Added extra check so that default_digital_ops doesn't overwrite a valid
#     codec_ops.  (SPDIF)
#   
#   Signed-off-by: Liam Girdwood <liam.girdwood@wolfsonmicro.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# sound/oss/ac97_codec.c
#   2005/03/07 20:41:36-08:00 Liam.Girdwood@wolfsonmicro.com +54 -27
#   OSS Support for AC97 low power codecs
# 
# include/linux/ac97_codec.h
#   2005/03/07 20:41:36-08:00 Liam.Girdwood@wolfsonmicro.com +1 -0
#   OSS Support for AC97 low power codecs
# 
# ChangeSet
#   2005/03/08 09:47:58-08:00 minyard@acm.org 
#   [PATCH] Fix race between the NMI code and the CMOS clock
#   
#   This patch fixes a race between the CMOS clock setting and the NMI code.
#   The NMI code indiscriminatly sets index registers and values in the same
#   place the CMOS clock is set.  If you are setting the CMOS clock and an NMI
#   occurs, Bad values could be written to or read from the CMOS RAM, or the
#   NMI operation might not occur correctly.
#   
#   Fixing this requires creating a special lock so the NMI code can know its
#   CPU owns the lock an "do the right thing" in that case.
#   
#   This was discovered and the fix has been tested by a very demanding
#   customer who tests the heck of out the software we deliver.
#   
#   Signed-off-by: Corey Minyard <minyard@acm.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/asm-i386/mc146818rtc.h
#   2005/03/07 20:41:35-08:00 minyard@acm.org +73 -8
#   Fix race between the NMI code and the CMOS clock
# 
# include/asm-i386/mach-default/mach_traps.h
#   2005/03/07 20:41:35-08:00 minyard@acm.org +12 -0
#   Fix race between the NMI code and the CMOS clock
# 
# arch/i386/kernel/time.c
#   2005/03/07 20:41:35-08:00 minyard@acm.org +29 -0
#   Fix race between the NMI code and the CMOS clock
# 
# ChangeSet
#   2005/03/08 09:47:43-08:00 pmeda@akamai.com 
#   [PATCH] ext3_test_root() speedup
#   
#   Reorder test_root testing from 3,5,7 to 7,5,3 so that average case becomes
#   good.  Even number check is added.  
#   
#   Signed-off-by: Prasanna Meda <pmeda@akamai.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# fs/ext3/balloc.c
#   2005/03/07 20:41:35-08:00 pmeda@akamai.com +4 -2
#   ext3_test_root() speedup
# 
# ChangeSet
#   2005/03/08 09:47:28-08:00 matthew@wil.cx 
#   [PATCH] ext3: free block accounting fix
#   
#   If we chose to "do_more", we would double-count the amount freed in the
#   second and subsequent block groups.  Fix it the same way as was done in
#   ext2 a couple of years ago.
#   
#   Signed-off-by: Matthew Wilcox <matthew@wil.cx>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# fs/ext3/balloc.c
#   2005/03/07 21:14:38-08:00 matthew@wil.cx +7 -5
#   ext3: free block accounting fix
# 
# ChangeSet
#   2005/03/08 09:47:13-08:00 matthew@wil.cx 
#   [PATCH] ext3 cleanup 1
#   
#   Rename variables in ext3/balloc.c as was done in ext2 a couple of years
#   ago.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# fs/ext3/balloc.c
#   2005/03/07 21:14:38-08:00 matthew@wil.cx +24 -25
#   ext3 cleanup 1
# 
# ChangeSet
#   2005/03/08 09:46:59-08:00 matthew@wil.cx 
#   [PATCH] Factor out phase 6 of journal_commit_transaction
#   
#   journal_commit_transaction() is 720 lines long.  This patch pulls about 55
#   of them out into their own function, removes a goto and cleans up the
#   control flow a little.
#   
#   Signed-off-by: Matthew Wilcox <matthew@wil.cx>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# fs/jbd/commit.c
#   2005/03/07 20:41:35-08:00 matthew@wil.cx +70 -65
#   Factor out phase 6 of journal_commit_transaction
# 
# ChangeSet
#   2005/03/08 09:46:43-08:00 alex@clusterfs.com 
#   [PATCH] JBD: log space management optimization
#   
#   during truncate ext3 calls journal_forget() for freed blocks, but before
#   these blocks go to the transaction and jbd reserves space in log for them
#   (->t_outstanding_credits).  also, journal_forget() removes these blocks
#   from the transaction, but doesn't correct log space reservation.  for
#   example, removal of 500MB file reserves 136 blocks, but only 10 blocks go
#   to the log.  a commit is expensive and correct reservation allows us to
#   avoid needless commits.  here is the patch.  tested on UP.
#   
#   Signed-off-by: Alex Tomas <alex@clusterfs.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# fs/jbd/transaction.c
#   2005/03/07 20:41:35-08:00 alex@clusterfs.com +9 -1
#   JBD: log space management optimization
# 
# ChangeSet
#   2005/03/08 09:46:28-08:00 alex@clusterfs.com 
#   [PATCH] JBD: reduce stack and number of journal descriptors
#   
#   Dynamically allocate the holding array for kjournald write patching rather
#   than allocating it on the stack.
#   
#   Signed-off-by: Alex Tomas <alex@clusterfs.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/linux/jbd.h
#   2005/03/07 20:41:35-08:00 alex@clusterfs.com +6 -0
#   JBD: reduce stack and number of journal descriptors
# 
# fs/jbd/journal.c
#   2005/03/07 20:41:35-08:00 alex@clusterfs.com +25 -0
#   JBD: reduce stack and number of journal descriptors
# 
# fs/jbd/commit.c
#   2005/03/07 21:14:38-08:00 alex@clusterfs.com +3 -3
#   JBD: reduce stack and number of journal descriptors
# 
# ChangeSet
#   2005/03/08 09:46:14-08:00 alex@clusterfs.com 
#   [PATCH] jbd: journal overflow fix #2
#   
#   fix against credits leak in journal_release_buffer()
#   
#   The idea is to charge a buffer in journal_dirty_metadata(), not in
#   journal_get_*_access()).  Each buffer has flag call
#   journal_dirty_metadata() sets on the buffer.
#   
#   Signed-off-by: Alex Tomas <alex@clusterfs.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/linux/journal-head.h
#   2005/03/07 20:41:34-08:00 alex@clusterfs.com +7 -0
#   jbd: journal overflow fix #2
# 
# include/linux/jbd.h
#   2005/03/07 21:14:38-08:00 alex@clusterfs.com +3 -6
#   jbd: journal overflow fix #2
# 
# include/linux/ext3_jbd.h
#   2005/03/07 20:41:34-08:00 alex@clusterfs.com +9 -12
#   jbd: journal overflow fix #2
# 
# fs/jbd/transaction.c
#   2005/03/07 21:14:38-08:00 alex@clusterfs.com +23 -33
#   jbd: journal overflow fix #2
# 
# fs/jbd/commit.c
#   2005/03/07 21:14:38-08:00 alex@clusterfs.com +16 -0
#   jbd: journal overflow fix #2
# 
# fs/ext3/ialloc.c
#   2005/03/07 21:14:29-08:00 alex@clusterfs.com +2 -4
#   jbd: journal overflow fix #2
# 
# fs/ext3/balloc.c
#   2005/03/07 21:14:38-08:00 alex@clusterfs.com +3 -4
#   jbd: journal overflow fix #2
# 
# ChangeSet
#   2005/03/08 09:45:57-08:00 zippel@linux-m68k.org 
#   [PATCH] merge vt_struct into vc_data
#   
#   The vt_struct and vc_data are always allocated together, so there is no need
#   for a separate vt_struct structure.
#   
#   Signed-off-by: Roman Zippel <zippel@linux-m68k.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/linux/vt_kern.h
#   2005/03/07 21:14:24-08:00 zippel@linux-m68k.org +0 -9
#   merge vt_struct into vc_data
# 
# include/linux/console_struct.h
#   2005/03/07 20:41:34-08:00 zippel@linux-m68k.org +6 -1
#   merge vt_struct into vc_data
# 
# fs/compat_ioctl.c
#   2005/03/07 20:41:34-08:00 zippel@linux-m68k.org +5 -4
#   merge vt_struct into vc_data
# 
# drivers/video/sun3fb.c
#   2005/03/07 20:41:34-08:00 zippel@linux-m68k.org +1 -1
#   merge vt_struct into vc_data
# 
# drivers/video/console/sticon.c
#   2005/03/07 20:41:34-08:00 zippel@linux-m68k.org +4 -6
#   merge vt_struct into vc_data
# 
# drivers/video/console/fbcon.c
#   2005/03/07 20:41:34-08:00 zippel@linux-m68k.org +20 -23
#   merge vt_struct into vc_data
# 
# drivers/char/vt_ioctl.c
#   2005/03/07 20:41:34-08:00 zippel@linux-m68k.org +39 -54
#   merge vt_struct into vc_data
# 
# drivers/char/vt.c
#   2005/03/07 20:41:34-08:00 zippel@linux-m68k.org +37 -51
#   merge vt_struct into vc_data
# 
# drivers/char/selection.c
#   2005/03/07 20:41:34-08:00 zippel@linux-m68k.org +3 -3
#   merge vt_struct into vc_data
# 
# ChangeSet
#   2005/03/08 09:45:43-08:00 zippel@linux-m68k.org 
#   [PATCH] remove console_macros.h
#   
#   Remove the macros in console_macros.h and so make the structure references
#   explicit.
#   
#   Signed-off-by: Roman Zippel <zippel@linux-m68k.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/char/vt.c
#   2005/03/07 21:14:40-08:00 zippel@linux-m68k.org +523 -512
#   remove console_macros.h
# 
# BitKeeper/deleted/.del-console_macros.h~3a224345e8a60e29
#   2005/03/08 09:45:34-08:00 zippel@linux-m68k.org +0 -0
#   Delete: drivers/char/console_macros.h
# 
# ChangeSet
#   2005/03/08 09:45:28-08:00 zippel@linux-m68k.org 
#   [PATCH] cleanup vc array access
#   
#   This removes as far as possible unneccessary vc_cons lookups by using a
#   pointer to the vc_data structure instead of the index.  The hidden currcons
#   argument in console_macros.h is temporarily replaced with a hidden vc pointer.
#   
#   Signed-off-by: Roman Zippel <zippel@linux-m68k.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/linux/vt_kern.h
#   2005/03/07 21:14:40-08:00 zippel@linux-m68k.org +22 -22
#   cleanup vc array access
# 
# include/linux/consolemap.h
#   2005/03/07 20:41:34-08:00 zippel@linux-m68k.org +1 -1
#   cleanup vc array access
# 
# fs/compat_ioctl.c
#   2005/03/07 21:14:40-08:00 zippel@linux-m68k.org +5 -5
#   cleanup vc array access
# 
# drivers/video/console/vgacon.c
#   2005/03/07 20:41:34-08:00 zippel@linux-m68k.org +5 -5
#   cleanup vc array access
# 
# drivers/video/console/sticon.c
#   2005/03/07 21:14:40-08:00 zippel@linux-m68k.org +1 -1
#   cleanup vc array access
# 
# drivers/video/console/promcon.c
#   2005/03/07 20:41:34-08:00 zippel@linux-m68k.org +7 -7
#   cleanup vc array access
# 
# drivers/video/console/mdacon.c
#   2005/03/07 20:41:34-08:00 zippel@linux-m68k.org +3 -4
#   cleanup vc array access
# 
# drivers/video/console/fbcon.c
#   2005/03/07 21:14:40-08:00 zippel@linux-m68k.org +22 -24
#   cleanup vc array access
# 
# drivers/video/console/dummycon.c
#   2005/03/07 20:41:34-08:00 zippel@linux-m68k.org +1 -1
#   cleanup vc array access
# 
# drivers/char/vt_ioctl.c
#   2005/03/07 21:14:40-08:00 zippel@linux-m68k.org +40 -38
#   cleanup vc array access
# 
# drivers/char/vt.c
#   2005/03/07 21:14:40-08:00 zippel@linux-m68k.org +417 -431
#   cleanup vc array access
# 
# drivers/char/vc_screen.c
#   2005/03/07 20:41:34-08:00 zippel@linux-m68k.org +5 -2
#   cleanup vc array access
# 
# drivers/char/tty_io.c
#   2005/03/07 20:41:34-08:00 zippel@linux-m68k.org +1 -3
#   cleanup vc array access
# 
# drivers/char/sysrq.c
#   2005/03/07 20:41:34-08:00 zippel@linux-m68k.org +2 -3
#   cleanup vc array access
# 
# drivers/char/selection.c
#   2005/03/07 21:14:40-08:00 zippel@linux-m68k.org +2 -4
#   cleanup vc array access
# 
# drivers/char/keyboard.c
#   2005/03/07 20:41:34-08:00 zippel@linux-m68k.org +3 -3
#   cleanup vc array access
# 
# drivers/char/consolemap.c
#   2005/03/07 20:41:34-08:00 zippel@linux-m68k.org +44 -53
#   cleanup vc array access
# 
# drivers/char/console_macros.h
#   2005/03/07 21:14:40-08:00 zippel@linux-m68k.org +66 -66
#   cleanup vc array access
# 
# ChangeSet
#   2005/03/08 09:45:12-08:00 ptiedem@de.ibm.com 
#   [PATCH] s390: ctc online/offline bug fix.
#   
#   ctc network driver changes:
#    - Properly initialize ccw array. This fixes the stray oopses after
#      an online/offline cycle.
#    - Correct check for already existing channel.
#    - Add missing kfrees.
#   
#   Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/s390/net/ctcmain.c
#   2005/03/07 20:41:34-08:00 ptiedem@de.ibm.com +11 -10
#   s390: ctc online/offline bug fix.
# 
# ChangeSet
#   2005/03/08 09:44:57-08:00 braunu@de.ibm.com 
#   [PATCH] s390: qeth layer 2, fake_ll and vlan bugs.
#   
#   With Frank Pavlic <pavlic@de.ibm.com>
#   
#   qeth network driver changes:
#    - Using layer 2 mode IPv6 multicast addresses has not been
#      registered at the OSA card (??? FIXME)
#    - We have to allow QETH_IP_THREAD in qeth_set_online too when
#      running in layer 2 mode otherwise multicast addresses won't
#      be registered at the OSA card.
#    - fake_ll improvements for dhcpcd.
#    - Strip ethernet header of VLAN packets before calling skb_pull.
#      This fixes multicast VLAN traffic stalls.
#    - Fix unused variable warning.
#   
#   Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
#   Acked-by: Jeff Garzik <jgarzik@pobox.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/s390/net/qeth_main.c
#   2005/03/07 20:41:33-08:00 braunu@de.ibm.com +25 -25
#   s390: qeth layer 2, fake_ll and vlan bugs.
# 
# ChangeSet
#   2005/03/08 09:44:42-08:00 braunu@de.ibm.com 
#   [PATCH] s390: iucv driver init call.
#   
#   iucv changes:
#    - Initialize iucv with subsys_initcall to make sure that it is
#      there before either vmlogrdr or netiucv start using it.
#   
#   Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/s390/net/iucv.c
#   2005/03/07 20:41:33-08:00 braunu@de.ibm.com +4 -4
#   s390: iucv driver init call.
# 
# ChangeSet
#   2005/03/08 09:44:28-08:00 edrossma@us.ibm.com 
#   [PATCH] s390: z90crypt reader task rescheduling.
#   
#   z90crypt device driver changes:
#    - Correct the condition for which the reader task is scheduled to run.
#   
#   Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/s390/crypto/z90main.c
#   2005/03/07 20:41:33-08:00 edrossma@us.ibm.com +3 -3
#   s390: z90crypt reader task rescheduling.
# 
# ChangeSet
#   2005/03/08 09:44:13-08:00 cohuck@de.ibm.com 
#   [PATCH] s390: irb faking.
#   
#   Common i/o layer changes:
#    - If a device driver tries to start I/O while the common I/O layer wants
#      to start path verification, don't reject the I/O with -EBUSY (which
#      might prompt the driver to retry the next tick) but seemingly accept
#      the I/O and deliver a fake irb with deferred cc 1 after path
#      verification has finished (prompting the driver to retry the I/O).
#      This prevents the device driver from doing useless retries while cio
#      is still busy with path verification.
#   
#   Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/s390/cio/device_ops.c
#   2005/03/07 20:41:33-08:00 cohuck@de.ibm.com +10 -0
#   s390: irb faking.
# 
# drivers/s390/cio/device_fsm.c
#   2005/03/07 20:41:33-08:00 cohuck@de.ibm.com +29 -0
#   s390: irb faking.
# 
# drivers/s390/cio/css.h
#   2005/03/07 20:41:33-08:00 cohuck@de.ibm.com +2 -0
#   s390: irb faking.
# 
# drivers/s390/cio/chsc.c
#   2005/03/07 20:41:33-08:00 cohuck@de.ibm.com +3 -0
#   s390: irb faking.
# 
# ChangeSet
#   2005/03/08 09:43:59-08:00 cohuck@de.ibm.com 
#   [PATCH] s390: common i/o layer.
#   
#   Common i/o layer changes:
#    - Update scsw information before checking activity control bits in
#      the offline processing.
#    - Clear irb structure after cio initiated I/O completed.
#    - Modify cdev private structure only while holding the lock.
#    - Update scsw information before checking whether we can start path
#      verification.
#    - Only generate a notoper event if the device is not already in the
#      not operation state, otherwise we end up with two unregister calls.
#   
#   Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/s390/cio/device_pgid.c
#   2005/03/07 20:41:33-08:00 cohuck@de.ibm.com +8 -2
#   s390: common i/o layer.
# 
# drivers/s390/cio/device_ops.c
#   2005/03/07 21:14:41-08:00 cohuck@de.ibm.com +1 -1
#   s390: common i/o layer.
# 
# drivers/s390/cio/device_id.c
#   2005/03/07 20:41:33-08:00 cohuck@de.ibm.com +1 -0
#   s390: common i/o layer.
# 
# drivers/s390/cio/device_fsm.c
#   2005/03/07 21:14:41-08:00 cohuck@de.ibm.com +12 -9
#   s390: common i/o layer.
# 
# drivers/s390/cio/device.c
#   2005/03/07 20:41:33-08:00 cohuck@de.ibm.com +9 -1
#   s390: common i/o layer.
# 
# drivers/s390/cio/css.c
#   2005/03/07 20:41:33-08:00 cohuck@de.ibm.com +10 -2
#   s390: common i/o layer.
# 
# drivers/s390/cio/chsc.c
#   2005/03/07 21:14:41-08:00 cohuck@de.ibm.com +5 -2
#   s390: common i/o layer.
# 
# ChangeSet
#   2005/03/08 09:43:42-08:00 schwidefsky@de.ibm.com 
#   [PATCH] s390: key management.
#   
#   Add key management system calls.
#   
#   Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/asm-s390/unistd.h
#   2005/03/07 20:41:33-08:00 schwidefsky@de.ibm.com +4 -1
#   s390: key management.
# 
# arch/s390/kernel/syscalls.S
#   2005/03/07 20:41:33-08:00 schwidefsky@de.ibm.com +3 -0
#   s390: key management.
# 
# arch/s390/kernel/compat_wrapper.S
#   2005/03/07 20:41:33-08:00 schwidefsky@de.ibm.com +17 -0
#   s390: key management.
# 
# ChangeSet
#   2005/03/08 09:43:28-08:00 schwidefsky@de.ibm.com 
#   [PATCH] s390: gcc4 compile fixes.
#   
#   Make s390 compile and work with gcc4.
#   
#   Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/asm-s390/uaccess.h
#   2005/03/07 20:41:32-08:00 schwidefsky@de.ibm.com +4 -5
#   s390: gcc4 compile fixes.
# 
# include/asm-s390/system.h
#   2005/03/07 20:41:32-08:00 schwidefsky@de.ibm.com +12 -4
#   s390: gcc4 compile fixes.
# 
# drivers/s390/cio/chsc.h
#   2005/03/07 20:41:32-08:00 schwidefsky@de.ibm.com +0 -2
#   s390: gcc4 compile fixes.
# 
# drivers/s390/char/keyboard.c
#   2005/03/07 20:41:32-08:00 schwidefsky@de.ibm.com +5 -5
#   s390: gcc4 compile fixes.
# 
# ChangeSet
#   2005/03/08 09:43:13-08:00 schwidefsky@de.ibm.com 
#   [PATCH] s390: soft-float, 4GB swap bug, smp clean & cpu hotplug.
#   
#   s390 core changes:
#    - Add -msoft-float to CFLAGS.
#    - Remove experimantal tag from cpu hotplug.
#    - Allow more than 4GB swap on a single device for 64 bit.
#    - Fix race in machine_restart to make sure all cpus entered
#      stopped state before reipl.
#    - Cleanup: use for_each_online_cpu macro where possible.
#    - Add argument brackets to __FD_SET/__FD_CLEAR/__FD_ZERO.
#    - Reset cpu_present in smp startup to avoid long delays if only
#      one cpu is defined.
#    - Regenerate default configuration.
#   
#   Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/asm-s390/smp.h
#   2005/03/07 20:41:32-08:00 schwidefsky@de.ibm.com +25 -0
#   s390: soft-float, 4GB swap bug, smp clean & cpu hotplug.
# 
# include/asm-s390/posix_types.h
#   2005/03/07 20:41:32-08:00 schwidefsky@de.ibm.com +4 -4
#   s390: soft-float, 4GB swap bug, smp clean & cpu hotplug.
# 
# include/asm-s390/pgtable.h
#   2005/03/07 20:41:32-08:00 schwidefsky@de.ibm.com +7 -1
#   s390: soft-float, 4GB swap bug, smp clean & cpu hotplug.
# 
# drivers/s390/char/sclp_quiesce.c
#   2005/03/07 20:41:32-08:00 schwidefsky@de.ibm.com +5 -20
#   s390: soft-float, 4GB swap bug, smp clean & cpu hotplug.
# 
# arch/s390/kernel/smp.c
#   2005/03/07 20:41:32-08:00 schwidefsky@de.ibm.com +39 -35
#   s390: soft-float, 4GB swap bug, smp clean & cpu hotplug.
# 
# arch/s390/kernel/irq.c
#   2005/03/07 20:41:32-08:00 schwidefsky@de.ibm.com +4 -6
#   s390: soft-float, 4GB swap bug, smp clean & cpu hotplug.
# 
# arch/s390/defconfig
#   2005/03/07 20:41:32-08:00 schwidefsky@de.ibm.com +8 -3
#   s390: soft-float, 4GB swap bug, smp clean & cpu hotplug.
# 
# arch/s390/Makefile
#   2005/03/07 20:41:32-08:00 schwidefsky@de.ibm.com +1 -1
#   s390: soft-float, 4GB swap bug, smp clean & cpu hotplug.
# 
# arch/s390/Kconfig
#   2005/03/07 20:41:32-08:00 schwidefsky@de.ibm.com +3 -3
#   s390: soft-float, 4GB swap bug, smp clean & cpu hotplug.
# 
# ChangeSet
#   2005/03/08 09:42:58-08:00 blaisorblade@yahoo.it 
#   [PATCH] uml: trivial removal of Makefile var
#   
#   That var is used only once, use its value directly.
#   
#   Signed-off-by: Paolo 'Blaisorblade' Giarrusso <blaisorblade@yahoo.it>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/um/drivers/Makefile
#   2005/03/07 20:41:32-08:00 blaisorblade@yahoo.it +1 -3
#   uml: trivial removal of Makefile var
# 
# ChangeSet
#   2005/03/08 09:42:42-08:00 didickman@yahoo.com 
#   [PATCH] m32r: use generic bug.h
#   
#   Signed-off-by: Daniel Dickman <didickman@yahoo.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/asm-m32r/bug.h
#   2005/03/07 20:41:32-08:00 didickman@yahoo.com +2 -20
#   m32r: use generic bug.h
# 
# ChangeSet
#   2005/03/08 09:42:28-08:00 barryn@pobox.com 
#   [PATCH] kconfig: DEBUG_PAGEALLOC and SOFTWARE_SUSPEND are incompatible on i386
#   
#   On i386, SOFTWARE_SUSPEND requires the CPU to have PSE support, but
#   DEBUG_PAGEALLOC disables PSE.  Thus, allowing both options to be enabled
#   simultaneously makes no sense.  This patch disables DEBUG_PAGEALLOC if
#   SOFTWARE_SUSPEND is enabled; it also displays a comment to briefly explain
#   why DEBUG_PAGEALLOC is missing in that case.
#   
#   I have tested this patch against oldconfig and menuconfig on 2.6.11-bk2.
#   
#   Signed-off-by: Barry K. Nathan <barryn@pobox.com>
#   Acked-by: Pavel Machek <pavel@ucw.cz>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/i386/Kconfig.debug
#   2005/03/07 20:41:32-08:00 barryn@pobox.com +4 -1
#   kconfig: DEBUG_PAGEALLOC and SOFTWARE_SUSPEND are incompatible on i386
# 
# ChangeSet
#   2005/03/08 09:42:13-08:00 pavel@ucw.cz 
#   [PATCH] swsusp fails to suspend if CONFIG_DEBUG_PAGEALLOC is also enabled
#   
#   swsusp low-level assembly requires PSE (4mb pages for kernel) and
#   DEBUG_PAGEALLOC disables that capability.
#   
#   Tell people what went wrong, some people seen same problem on VIA cpus...
#   
#   Signed-off-by: Pavel Machek <pavel@suse.cz>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/asm-i386/suspend.h
#   2005/03/07 20:41:32-08:00 pavel@ucw.cz +4 -2
#   swsusp fails to suspend if CONFIG_DEBUG_PAGEALLOC is also enabled
# 
# ChangeSet
#   2005/03/08 09:41:59-08:00 pavel@ucw.cz 
#   [PATCH] Update suspend-to-RAM vs. video documentation
#   
#   We got quite long list of machines and tricks needed to get them working.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# Documentation/power/video.txt
#   2005/03/07 20:41:32-08:00 pavel@ucw.cz +144 -17
#   Update suspend-to-RAM vs. video documentation
# 
# ChangeSet
#   2005/03/08 09:41:44-08:00 pavel@ucw.cz 
#   [PATCH] swsusp: do not use higher order memory allocations on suspend
#   
#   This is patch from Rafael, it eliminates order-5 (or worse) allocations
#   during suspend.  I did few style/whitespace modifications.  It was tested
#   by me, Rafael, and Stefan from SuSE.
#   
#   Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
#   Signed-off-by: Pavel Machek <pavel@suse.cz>
#   Signed-off-by: Adrian Bunk <bunk@stusta.de>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# kernel/power/swsusp.c
#   2005/03/07 20:41:31-08:00 pavel@ucw.cz +95 -86
#   swsusp: do not use higher order memory allocations on suspend
# 
# include/linux/suspend.h
#   2005/03/07 20:41:31-08:00 pavel@ucw.cz +14 -3
#   swsusp: do not use higher order memory allocations on suspend
# 
# ChangeSet
#   2005/03/08 09:41:29-08:00 pfg@sgi.com 
#   [PATCH] Altix: ioc4 serial driver support
#   
#   Signed-off-by: Patrick Gefre <pfg@sgi.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/linux/ioc4_common.h
#   2005/03/07 20:41:31-08:00 pfg@sgi.com +21 -0
#   Altix: ioc4 serial driver support
# 
# drivers/sn/ioc4.c
#   2005/03/07 20:41:31-08:00 pfg@sgi.com +65 -0
#   Altix: ioc4 serial driver support
# 
# drivers/sn/Makefile
#   2005/03/07 20:41:31-08:00 pfg@sgi.com +6 -0
#   Altix: ioc4 serial driver support
# 
# include/linux/ioc4_common.h
#   2005/03/07 20:41:31-08:00 pfg@sgi.com +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/include/linux/ioc4_common.h
# 
# drivers/sn/ioc4.c
#   2005/03/07 20:41:31-08:00 pfg@sgi.com +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/drivers/sn/ioc4.c
# 
# drivers/sn/Makefile
#   2005/03/07 20:41:31-08:00 pfg@sgi.com +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/drivers/sn/Makefile
# 
# drivers/serial/ioc4_serial.c
#   2005/03/07 20:41:31-08:00 pfg@sgi.com +2909 -0
#   Altix: ioc4 serial driver support
# 
# drivers/serial/Makefile
#   2005/03/07 21:14:35-08:00 pfg@sgi.com +1 -0
#   Altix: ioc4 serial driver support
# 
# drivers/ide/pci/sgiioc4.c
#   2005/03/07 20:41:31-08:00 pfg@sgi.com +7 -34
#   Altix: ioc4 serial driver support
# 
# drivers/Makefile
#   2005/03/07 20:41:31-08:00 pfg@sgi.com +1 -0
#   Altix: ioc4 serial driver support
# 
# drivers/serial/ioc4_serial.c
#   2005/03/07 20:41:31-08:00 pfg@sgi.com +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/drivers/serial/ioc4_serial.c
# 
# ChangeSet
#   2005/03/08 09:41:13-08:00 pfg@sgi.com 
#   [PATCH] Altix: Ignore input during early boot
#   
#   2.6 Altix console patch to ignore input during early booting
#   
#   Signed-off-by: Patrick Gefre <pfg@sgi.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/serial/sn_console.c
#   2005/03/07 20:41:31-08:00 pfg@sgi.com +5 -2
#   Altix: Ignore input during early boot
# 
# ChangeSet
#   2005/03/08 09:40:59-08:00 Andries.Brouwer@cwi.nl 
#   [PATCH] remove dead cyrix/centaur mtrr init code
#   
#   There are several cases where __init function pointers are stored in a
#   general purpose struct.  For example, a SCSI template may contain a __init
#   detect function.  Have not yet thought of an elegant way to avoid this.
#   
#   One such case is the mtrr code, where struct mtrr_ops has an init field
#   pointing at __init functions.  Unless I overlook something, this case may
#   be easy to settle, since the .init field is never used.
#   
#   The patch below comments out the declaration and initialisation of the
#   .init field of struct mtrr_ops, and puts #if 0 ...  #endif around the
#   centaur_mcr_init() and cyrix_arr_init() code.
#   
#   Simultaneously a number of variables are made static.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/i386/kernel/cpu/mtrr/mtrr.h
#   2005/03/07 20:41:31-08:00 Andries.Brouwer@cwi.nl +1 -3
#   remove dead cyrix/centaur mtrr init code
# 
# arch/i386/kernel/cpu/mtrr/main.c
#   2005/03/07 20:41:31-08:00 Andries.Brouwer@cwi.nl +1 -5
#   remove dead cyrix/centaur mtrr init code
# 
# arch/i386/kernel/cpu/mtrr/generic.c
#   2005/03/07 20:41:31-08:00 Andries.Brouwer@cwi.nl +2 -3
#   remove dead cyrix/centaur mtrr init code
# 
# arch/i386/kernel/cpu/mtrr/cyrix.c
#   2005/03/07 20:41:31-08:00 Andries.Brouwer@cwi.nl +5 -3
#   remove dead cyrix/centaur mtrr init code
# 
# arch/i386/kernel/cpu/mtrr/centaur.c
#   2005/03/07 20:41:31-08:00 Andries.Brouwer@cwi.nl +4 -1
#   remove dead cyrix/centaur mtrr init code
# 
# ChangeSet
#   2005/03/08 09:40:43-08:00 christoph@graphe.net 
#   [PATCH] Support HPET with a single timer for system time
#   
#   This patch removes the check for the existence of multiple HPET timers.  It
#   allows the use of HPET with only a single timer for system time if
#   HPET_EMULATE_RTC is not set.
#   
#   Signed-off-by: Christoph Lameter <christoph@lameter.com>
#   Signed-off-by: Shai Fultheim <Shai@Scalex86.org>
#   Acked-by: "Pallipadi, Venkatesh" <venkatesh.pallipadi@intel.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/i386/kernel/time_hpet.c
#   2005/03/07 20:41:31-08:00 christoph@graphe.net +9 -4
#   Support HPET with a single timer for system time
# 
# ChangeSet
#   2005/03/08 09:40:29-08:00 rlrevell@joe-job.com 
#   [PATCH] x86: clean up FIXME in do_timer_interrupt
#   
#   Clean up the logic in do_timer_interrupt()
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/i386/kernel/time.c
#   2005/03/07 21:14:37-08:00 rlrevell@joe-job.com +5 -9
#   x86: clean up FIXME in do_timer_interrupt
# 
# ChangeSet
#   2005/03/08 09:40:13-08:00 riel@redhat.com 
#   [PATCH] cpuid takes unsigned arguments
#   
#   Because Xen is compiled with -Wall -Werror, has inherited processor.h from
#   Linux and Fedora is now built with gcc4, I discovered this bug.
#   
#   The few callers I verified all call cpuid with unsigned ints, but the
#   function is defined with signed ints.  This trivial patch fixes that.
#   
#   Signed-off-by: Rik van Riel <riel@redhat.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/asm-i386/processor.h
#   2005/03/07 20:41:31-08:00 riel@redhat.com +1 -1
#   cpuid takes unsigned arguments
# 
# ChangeSet
#   2005/03/08 09:39:59-08:00 tglx@linutronix.de 
#   [PATCH] i386: C99 initializers for hw_interrupt_type structures
#   
#   Convert the initializers of hw_interrupt_type structures to C99 initializers.
#   
#   Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/i386/mach-voyager/voyager_smp.c
#   2005/03/07 20:41:30-08:00 tglx@linutronix.de +8 -8
#   i386: C99 initializers for hw_interrupt_type structures
# 
# arch/i386/kernel/i8259.c
#   2005/03/07 20:41:30-08:00 tglx@linutronix.de +7 -8
#   i386: C99 initializers for hw_interrupt_type structures
# 
# ChangeSet
#   2005/03/08 09:39:45-08:00 haveblue@us.ibm.com 
#   [PATCH] make highmem_start access only valid addresses (i386)
#   
#   When CONFIG_HIGHMEM=y, but ZONE_NORMAL isn't quite full, there is, of
#   course, no actual memory at *high_memory.  This isn't a problem with normal
#   virt<->phys translations because it's never dereferenced, but
#   CONFIG_NONLINEAR is a bit more finicky.  So, don't do __va() in
#   non-existent addresses.
#   
#   Signed-off-by: Dave Hansen <haveblue@us.ibm.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/i386/mm/init.c
#   2005/03/07 20:41:30-08:00 haveblue@us.ibm.com +2 -2
#   make highmem_start access only valid addresses (i386)
# 
# ChangeSet
#   2005/03/08 09:39:30-08:00 kianusch@sk-tech.net 
#   [PATCH] Support for GEODE CPUs
#   
#   Those CPU's are found mostly in embedded systems ...  one of the most
#   prominent Hardware using GEODE CPU is probably soekris net4801
#   (http://www.soekris.com).
#   
#   This patch has been on my homepage
#   (http://www.sk-tech.net/support/soekris.html) for quite a time - but I've
#   been asked several time to have it included in the main kernel.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/asm-i386/module.h
#   2005/03/07 20:41:30-08:00 kianusch@sk-tech.net +2 -0
#   Support for GEODE CPUs
# 
# arch/i386/Makefile
#   2005/03/07 20:41:30-08:00 kianusch@sk-tech.net +5 -0
#   Support for GEODE CPUs
# 
# arch/i386/Kconfig
#   2005/03/07 21:14:32-08:00 kianusch@sk-tech.net +13 -5
#   Support for GEODE CPUs
# 
# ChangeSet
#   2005/03/08 09:39:16-08:00 akpm@osdl.org 
#   [PATCH] x86: iounmap() isa special case
#   
#   ioremap() has special-case handling for the IS region, but inunmap() does not.
#    So iounmap() generates a warning when a caller correctly performs an
#   ioremap()/iounmap() sequence.
#   
#   Fix that by teaching iounmap() about the IS address range.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/i386/mm/ioremap.c
#   2005/03/07 20:41:30-08:00 akpm@osdl.org +16 -3
#   x86: iounmap() isa special case
# 
# ChangeSet
#   2005/03/08 09:39:00-08:00 brix@gentoo.org 
#   [PATCH] Determine SCx200 CB address at run-time
#   
#   The current SCx200 drivers use a fixed base address of 0x9000 for the
#   Configuration Block, but some systems (at least the Soekris net4801) uses a
#   base address of 0x6000.  This patch first tries the fixed address then - if
#   no configuration block could be found - tries the address written to the
#   Configuration Block Address Scratchpad register by the BIOS.
#   
#   Signed-off-by: Henrik Brix Andersen <brix@gentoo.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/linux/scx200.h
#   2005/03/07 20:41:30-08:00 brix@gentoo.org +6 -4
#   Determine SCx200 CB address at run-time
# 
# include/linux/pci_ids.h
#   2005/03/07 20:41:30-08:00 brix@gentoo.org +2 -0
#   Determine SCx200 CB address at run-time
# 
# drivers/mtd/maps/scx200_docflash.c
#   2005/03/07 20:41:30-08:00 brix@gentoo.org +6 -7
#   Determine SCx200 CB address at run-time
# 
# drivers/mtd/maps/Kconfig
#   2005/03/07 20:41:30-08:00 brix@gentoo.org +1 -1
#   Determine SCx200 CB address at run-time
# 
# drivers/char/watchdog/scx200_wdt.c
#   2005/03/07 20:41:30-08:00 brix@gentoo.org +14 -28
#   Determine SCx200 CB address at run-time
# 
# drivers/char/watchdog/Kconfig
#   2005/03/07 20:41:30-08:00 brix@gentoo.org +2 -2
#   Determine SCx200 CB address at run-time
# 
# arch/i386/kernel/scx200.c
#   2005/03/07 20:41:30-08:00 brix@gentoo.org +38 -13
#   Determine SCx200 CB address at run-time
# 
# ChangeSet
#   2005/03/08 09:38:45-08:00 andrea@novell.com 
#   [PATCH] fix iounmap and a pageattr memleak (x86 and x86-64)
#   
#   Reject zero page vm-area request, align size properly and hide the guard page
#   from the callers like ioremap - this avoids a kernel crash due one more page
#   being passed to change_page_attr
#   
#   Signed-off-by: Andrea Arcangeli <andrea@novell.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# mm/vmalloc.c
#   2005/03/07 20:41:30-08:00 andrea@novell.com +11 -4
#   fix iounmap and a pageattr memleak (x86 and x86-64)
# 
# ChangeSet
#   2005/03/08 09:38:30-08:00 haveblue@us.ibm.com 
#   [PATCH] x86: remove-free_all_bootmem() #define
#   
#   in arch/i386/mm/init.c, there's a #define for __free_all_bootmem():
#   
#   #ifndef CONFIG_DISCONTIGMEM
#   #define __free_all_bootmem() free_all_bootmem()
#   #else
#   #define __free_all_bootmem() free_all_bootmem_node(NODE_DATA(0))
#   #endif /* !CONFIG_DISCONTIGMEM */
#   
#   However, both of those functions end up eventually calling the same
#   thing:
#   
#   	free_all_bootmem_core(NODE_DATA(0))
#   
#   This might have once been a placeholder for a more complex bootmem
#   init call, but that never happened.  So, kill off the DISCONTIG
#   version, and just call free_all_bootmem() directly in both cases.
#   
#   Signed-off-by: Dave Hansen <haveblue@us.ibm.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/i386/mm/init.c
#   2005/03/07 21:14:45-08:00 haveblue@us.ibm.com +1 -7
#   x86: remove-free_all_bootmem() #define
# 
# ChangeSet
#   2005/03/08 09:38:15-08:00 haveblue@us.ibm.com 
#   [PATCH] x86: consolidate set_max_mapnr_init() implementations
#   
#   discontig.c has its own version of set_max_mapnr_init().  However, all that it
#   really does differently from the mm/init.c version is skip setting max_mapnr
#   (which doesn't exist because there's no mem_map[]).
#   
#   Signed-off-by: Dave Hansen <haveblue@us.ibm.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/i386/mm/init.c
#   2005/03/07 21:14:46-08:00 haveblue@us.ibm.com +7 -4
#   x86: consolidate set_max_mapnr_init() implementations
# 
# arch/i386/mm/discontig.c
#   2005/03/07 20:41:29-08:00 haveblue@us.ibm.com +0 -9
#   x86: consolidate set_max_mapnr_init() implementations
# 
# ChangeSet
#   2005/03/08 09:37:59-08:00 haveblue@us.ibm.com 
#   [PATCH] x86: refactor memory setup
#   
#   Refactor the i386 default and CONFIG_DISCONTIG_MEM setup_memory() functions to
#   share the common bootmem initialisation code.  This code is intended to be
#   identical, but there are currently some fixes applied to one and not the
#   other.  This patch extracts this common initialisation code.
#   
#   Signed-off-by: Andy Whitcroft <apw@shadowen.org>
#   Signed-off-by: Dave Hansen <haveblue@us.ibm.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/i386/mm/discontig.c
#   2005/03/07 21:14:46-08:00 haveblue@us.ibm.com +4 -115
#   x86: refactor memory setup
# 
# arch/i386/kernel/setup.c
#   2005/03/07 20:41:29-08:00 haveblue@us.ibm.com +17 -11
#   x86: refactor memory setup
# 
# ChangeSet
#   2005/03/08 09:37:44-08:00 kmannth@us.ibm.com 
#   [PATCH] Allow hot-add enabled i386 NUMA box to boot
#   
#   Dave Hanson mentioned I should send this patch to you.  I posted it to
#   linux-mm a while ago without complaint.  This patch solves a simple
#   problem related to the interpretation on the SRAT table and the info
#   found in the e820.
#   
#   When a possible hot-add area is exposed on my box (IBM x445 with hot
#   add enabled in the bios) my SRAT table correctly exposed a new node from
#   the end of my physical memory to 64gb.  In the present kernels the numa
#   KVA areas (based on the SRAT) are calculated before find_max_pfn.  The
#   remap area is created for this large non-populated zone and the system
#   dies a while later during bootup.
#   
#   I believe the correct things to do (as did the hot-plug community) the
#   correct thing to do is the keep the node_start_end_pfn data structures
#   focuses on memory that is in the system.  That is all this patch does.
#   It ignores any node data (correctly reported by the SRAT) that is above
#   the e820 end of memory.    
#   
#   Signed-off-by: <kmannth@us.ibm.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/i386/mm/discontig.c
#   2005/03/07 21:14:47-08:00 kmannth@us.ibm.com +10 -1
#   Allow hot-add enabled i386 NUMA box to boot
# 
# ChangeSet
#   2005/03/08 09:37:29-08:00 lethal@Linux-SH.ORG 
#   [PATCH] sh: merge updates
#   
#   More random cleanup and build fixes.
#   
#   Signed-off-by: Paul Mundt <lethal@linux-sh.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/asm-sh/sh03/ide.h
#   2005/03/07 20:41:29-08:00 lethal@Linux-SH.ORG +7 -0
#   sh: merge updates
# 
# include/asm-sh/cpu-sh4/timer.h
#   2005/03/07 20:41:29-08:00 lethal@Linux-SH.ORG +51 -0
#   sh: merge updates
# 
# include/asm-sh/sh03/ide.h
#   2005/03/07 20:41:29-08:00 lethal@Linux-SH.ORG +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/include/asm-sh/sh03/ide.h
# 
# include/asm-sh/mc146818rtc.h
#   2005/03/07 20:41:29-08:00 lethal@Linux-SH.ORG +1 -0
#   sh: merge updates
# 
# include/asm-sh/irq.h
#   2005/03/07 20:41:29-08:00 lethal@Linux-SH.ORG +2 -1
#   sh: merge updates
# 
# include/asm-sh/dma-mapping.h
#   2005/03/07 20:41:29-08:00 lethal@Linux-SH.ORG +0 -1
#   sh: merge updates
# 
# include/asm-sh/cpu-sh4/timer.h
#   2005/03/07 20:41:29-08:00 lethal@Linux-SH.ORG +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/include/asm-sh/cpu-sh4/timer.h
# 
# include/asm-sh/cpu-sh3/timer.h
#   2005/03/07 20:41:29-08:00 lethal@Linux-SH.ORG +64 -0
#   sh: merge updates
# 
# include/asm-sh/cpu-sh3/freq.h
#   2005/03/07 20:41:29-08:00 lethal@Linux-SH.ORG +4 -0
#   sh: merge updates
# 
# include/asm-sh/cacheflush.h
#   2005/03/07 20:41:29-08:00 lethal@Linux-SH.ORG +2 -0
#   sh: merge updates
# 
# include/asm-sh/bug.h
#   2005/03/07 20:41:29-08:00 lethal@Linux-SH.ORG +1 -1
#   sh: merge updates
# 
# include/asm-sh/bitops.h
#   2005/03/07 20:41:29-08:00 lethal@Linux-SH.ORG +3 -3
#   sh: merge updates
# 
# arch/sh/kernel/time.c
#   2005/03/07 20:41:29-08:00 lethal@Linux-SH.ORG +2 -31
#   sh: merge updates
# 
# arch/sh/kernel/signal.c
#   2005/03/07 20:41:29-08:00 lethal@Linux-SH.ORG +5 -4
#   sh: merge updates
# 
# arch/sh/kernel/sh_ksyms.c
#   2005/03/07 20:41:29-08:00 lethal@Linux-SH.ORG +0 -7
#   sh: merge updates
# 
# arch/sh/kernel/ptrace.c
#   2005/03/07 20:41:29-08:00 lethal@Linux-SH.ORG +1 -2
#   sh: merge updates
# 
# arch/sh/drivers/pci/pci-sh7751.c
#   2005/03/07 20:41:29-08:00 lethal@Linux-SH.ORG +1 -1
#   sh: merge updates
# 
# arch/sh/boards/snapgear/setup.c
#   2005/03/07 20:41:29-08:00 lethal@Linux-SH.ORG +1 -5
#   sh: merge updates
# 
# arch/sh/boards/sh03/rtc.c
#   2005/03/07 20:41:29-08:00 lethal@Linux-SH.ORG +0 -2
#   sh: merge updates
# 
# arch/sh/boards/se/7300/io.c
#   2005/03/07 20:41:29-08:00 lethal@Linux-SH.ORG +6 -2
#   sh: merge updates
# 
# include/asm-sh/cpu-sh3/timer.h
#   2005/03/07 20:41:29-08:00 lethal@Linux-SH.ORG +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/include/asm-sh/cpu-sh3/timer.h
# 
# ChangeSet
#   2005/03/08 09:37:13-08:00 lethal@Linux-SH.ORG 
#   [PATCH] sh: Update cpufreq driver for cpumask
#   
#   This updates the sh cpufreq driver for the cpumask changes.
#   
#   Signed-off-by: Paul Mundt <lethal@linux-sh.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/sh/kernel/cpufreq.c
#   2005/03/07 20:41:29-08:00 lethal@Linux-SH.ORG +8 -10
#   sh: Update cpufreq driver for cpumask
# 
# ChangeSet
#   2005/03/08 09:36:58-08:00 lethal@Linux-SH.ORG 
#   [PATCH] sh: framebuffer updates
#   
#   hitfb and pvr2fb were both recently broken by mainline changes, this gets them
#   working properly again.
#   
#   Signed-off-by: Paul Mundt <lethal@linux-sh.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/video/pvr2fb.c
#   2005/03/07 20:41:29-08:00 lethal@Linux-SH.ORG +4 -4
#   sh: framebuffer updates
# 
# drivers/video/hitfb.c
#   2005/03/07 20:41:29-08:00 lethal@Linux-SH.ORG +15 -18
#   sh: framebuffer updates
# 
# ChangeSet
#   2005/03/08 09:36:44-08:00 lethal@Linux-SH.ORG 
#   [PATCH] sh: hp620 updates
#   
#   This gets hp620 working again..
#   
#   Signed-off-by: Kristoffer Ericson <kristoffer@jlime.com>
#   Signed-off-by: Paul Mundt <lethal@linux-sh.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/sh/boards/hp6xx/hp620/setup.c
#   2005/03/07 20:41:28-08:00 lethal@Linux-SH.ORG +45 -0
#   sh: hp620 updates
# 
# arch/sh/boards/hp6xx/hp620/Makefile
#   2005/03/07 20:41:28-08:00 lethal@Linux-SH.ORG +1 -1
#   sh: hp620 updates
# 
# arch/sh/boards/hp6xx/hp620/setup.c
#   2005/03/07 20:41:28-08:00 lethal@Linux-SH.ORG +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/arch/sh/boards/hp6xx/hp620/setup.c
# 
# ChangeSet
#   2005/03/08 09:36:28-08:00 lethal@Linux-SH.ORG 
#   [PATCH] sh: generic hardirqs
#   
#   Convert sh to use generic hardirqs.
#   
#   Signed-off-by: Christoph Hellwig <hch@lst.de>
#   Signed-off-by: Paul Mundt <lethal@linux-sh.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/asm-sh/hardirq.h
#   2005/03/07 20:41:28-08:00 lethal@Linux-SH.ORG +1 -10
#   sh: generic hardirqs
# 
# arch/sh/kernel/irq.c
#   2005/03/07 20:41:28-08:00 lethal@Linux-SH.ORG +3 -628
#   sh: generic hardirqs
# 
# arch/sh/Kconfig
#   2005/03/07 20:41:28-08:00 lethal@Linux-SH.ORG +8 -1
#   sh: generic hardirqs
# 
# ChangeSet
#   2005/03/08 09:36:13-08:00 lethal@Linux-SH.ORG 
#   [PATCH] sh: defconfig updates
#   
#   Nothing to see here, move along.
#   
#   Signed-off-by: Paul Mundt <lethal@linux-sh.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/sh/configs/systemh_defconfig
#   2005/03/07 20:41:28-08:00 lethal@Linux-SH.ORG +191 -54
#   sh: defconfig updates
# 
# arch/sh/configs/snapgear_defconfig
#   2005/03/07 20:41:28-08:00 lethal@Linux-SH.ORG +252 -92
#   sh: defconfig updates
# 
# arch/sh/configs/sh03_defconfig
#   2005/03/07 20:41:28-08:00 lethal@Linux-SH.ORG +75 -87
#   sh: defconfig updates
# 
# arch/sh/configs/se7751_defconfig
#   2005/03/07 20:41:28-08:00 lethal@Linux-SH.ORG +254 -94
#   sh: defconfig updates
# 
# arch/sh/configs/se7705_defconfig
#   2005/03/07 20:41:28-08:00 lethal@Linux-SH.ORG +81 -12
#   sh: defconfig updates
# 
# arch/sh/configs/se73180_defconfig
#   2005/03/07 20:41:28-08:00 lethal@Linux-SH.ORG +82 -16
#   sh: defconfig updates
# 
# arch/sh/configs/se7300_defconfig
#   2005/03/07 20:41:28-08:00 lethal@Linux-SH.ORG +86 -16
#   sh: defconfig updates
# 
# arch/sh/configs/rts7751r2d_defconfig
#   2005/03/07 20:41:28-08:00 lethal@Linux-SH.ORG +92 -118
#   sh: defconfig updates
# 
# arch/sh/configs/microdev_defconfig
#   2005/03/07 20:41:28-08:00 lethal@Linux-SH.ORG +69 -15
#   sh: defconfig updates
# 
# arch/sh/configs/se7750_defconfig
#   2005/03/08 09:36:02-08:00 lethal@Linux-SH.ORG +713 -0
# 
# arch/sh/configs/hp680_defconfig
#   2005/03/07 20:41:28-08:00 lethal@Linux-SH.ORG +217 -81
#   sh: defconfig updates
# 
# arch/sh/configs/dreamcast_defconfig
#   2005/03/07 20:41:28-08:00 lethal@Linux-SH.ORG +149 -69
#   sh: defconfig updates
# 
# arch/sh/configs/cqreek_defconfig
#   2005/03/07 20:41:28-08:00 lethal@Linux-SH.ORG +386 -127
#   sh: defconfig updates
# 
# arch/sh/configs/adx_defconfig
#   2005/03/07 20:41:28-08:00 lethal@Linux-SH.ORG +390 -127
#   sh: defconfig updates
# 
# arch/sh/Makefile
#   2005/03/07 20:41:28-08:00 lethal@Linux-SH.ORG +7 -0
#   sh: defconfig updates
# 
# arch/sh/configs/se7750_defconfig
#   2005/03/08 09:36:02-08:00 lethal@Linux-SH.ORG +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/arch/sh/configs/se7750_defconfig
# 
# BitKeeper/deleted/.del-defconfig~95f712e414495a57
#   2005/03/08 09:36:02-08:00 lethal@Linux-SH.ORG +0 -0
#   Delete: arch/sh/defconfig
# 
# ChangeSet
#   2005/03/08 09:35:43-08:00 lethal@Linux-SH.ORG 
#   [PATCH] sh64: merge updates
#   
#   Mostly random bugfixes and some build fixes, as well as killing off some
#   leftover cruft.
#   
#   Signed-off-by: Paul Mundt <lethal@linux-sh.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/asm-sh64/unistd.h
#   2005/03/07 20:41:28-08:00 lethal@Linux-SH.ORG +6 -1
#   sh64: merge updates
# 
# include/asm-sh64/thread_info.h
#   2005/03/07 20:41:28-08:00 lethal@Linux-SH.ORG +6 -2
#   sh64: merge updates
# 
# include/asm-sh64/system.h
#   2005/03/07 20:41:28-08:00 lethal@Linux-SH.ORG +0 -1
#   sh64: merge updates
# 
# include/asm-sh64/pgtable.h
#   2005/03/07 20:41:28-08:00 lethal@Linux-SH.ORG +0 -2
#   sh64: merge updates
# 
# include/asm-sh64/ioctls.h
#   2005/03/07 20:41:28-08:00 lethal@Linux-SH.ORG +88 -83
#   sh64: merge updates
# 
# include/asm-sh64/hardware.h
#   2005/03/07 20:41:28-08:00 lethal@Linux-SH.ORG +1 -24
#   sh64: merge updates
# 
# include/asm-sh64/bug.h
#   2005/03/07 20:41:28-08:00 lethal@Linux-SH.ORG +26 -1
#   sh64: merge updates
# 
# arch/sh64/oprofile/op_model_null.c
#   2005/03/07 20:41:28-08:00 lethal@Linux-SH.ORG +1 -1
#   sh64: merge updates
# 
# arch/sh64/mm/tlbmiss.c
#   2005/03/07 20:41:28-08:00 lethal@Linux-SH.ORG +0 -1
#   sh64: merge updates
# 
# arch/sh64/mm/ioremap.c
#   2005/03/07 20:41:28-08:00 lethal@Linux-SH.ORG +2 -2
#   sh64: merge updates
# 
# arch/sh64/mm/fault.c
#   2005/03/07 20:41:28-08:00 lethal@Linux-SH.ORG +25 -14
#   sh64: merge updates
# 
# arch/sh64/mm/extable.c
#   2005/03/07 20:41:28-08:00 lethal@Linux-SH.ORG +2 -1
#   sh64: merge updates
# 
# arch/sh64/lib/page_copy.S
#   2005/03/07 20:41:28-08:00 lethal@Linux-SH.ORG +9 -0
#   sh64: merge updates
# 
# arch/sh64/lib/page_clear.S
#   2005/03/07 20:41:28-08:00 lethal@Linux-SH.ORG +3 -0
#   sh64: merge updates
# 
# arch/sh64/lib/dbg.c
#   2005/03/07 20:41:28-08:00 lethal@Linux-SH.ORG +40 -4
#   sh64: merge updates
# 
# arch/sh64/lib/copy_user_memcpy.S
#   2005/03/07 20:41:28-08:00 lethal@Linux-SH.ORG +9 -5
#   sh64: merge updates
# 
# arch/sh64/kernel/traps.c
#   2005/03/07 20:41:28-08:00 lethal@Linux-SH.ORG +3 -0
#   sh64: merge updates
# 
# arch/sh64/kernel/syscalls.S
#   2005/03/07 20:41:28-08:00 lethal@Linux-SH.ORG +6 -1
#   sh64: merge updates
# 
# arch/sh64/kernel/sys_sh64.c
#   2005/03/07 20:41:28-08:00 lethal@Linux-SH.ORG +14 -0
#   sh64: merge updates
# 
# arch/sh64/kernel/switchto.S
#   2005/03/07 20:41:28-08:00 lethal@Linux-SH.ORG +1 -2
#   sh64: merge updates
# 
# arch/sh64/kernel/signal.c
#   2005/03/07 20:41:28-08:00 lethal@Linux-SH.ORG +6 -10
#   sh64: merge updates
# 
# arch/sh64/kernel/sh_ksyms.c
#   2005/03/07 20:41:28-08:00 lethal@Linux-SH.ORG +7 -1
#   sh64: merge updates
# 
# arch/sh64/kernel/ptrace.c
#   2005/03/07 20:41:28-08:00 lethal@Linux-SH.ORG +17 -0
#   sh64: merge updates
# 
# arch/sh64/kernel/process.c
#   2005/03/07 20:41:28-08:00 lethal@Linux-SH.ORG +6 -7
#   sh64: merge updates
# 
# arch/sh64/kernel/head.S
#   2005/03/07 20:41:28-08:00 lethal@Linux-SH.ORG +3 -3
#   sh64: merge updates
# 
# arch/sh64/kernel/entry.S
#   2005/03/07 20:41:28-08:00 lethal@Linux-SH.ORG +14 -12
#   sh64: merge updates
# 
# arch/sh64/kernel/early_printk.c
#   2005/03/07 20:41:28-08:00 lethal@Linux-SH.ORG +0 -2
#   sh64: merge updates
# 
# arch/sh64/kernel/dma.c
#   2005/03/07 20:41:28-08:00 lethal@Linux-SH.ORG +1 -1
#   sh64: merge updates
# 
# arch/sh64/kernel/Makefile
#   2005/03/07 20:41:28-08:00 lethal@Linux-SH.ORG +3 -5
#   sh64: merge updates
# 
# arch/sh64/Makefile
#   2005/03/07 20:41:28-08:00 lethal@Linux-SH.ORG +14 -10
#   sh64: merge updates
# 
# arch/sh64/Kconfig
#   2005/03/07 20:41:28-08:00 lethal@Linux-SH.ORG +5 -0
#   sh64: merge updates
# 
# arch/sh64/Kconfig.debug
#   2005/03/07 20:41:28-08:00 lethal@Linux-SH.ORG +7 -0
#   sh64: merge updates
# 
# BitKeeper/deleted/.del-old-checksum.c~22154efeaad79af0
#   2005/03/08 09:35:34-08:00 lethal@Linux-SH.ORG +0 -0
#   Delete: arch/sh64/lib/old-checksum.c
# 
# ChangeSet
#   2005/03/08 09:35:28-08:00 lethal@Linux-SH.ORG 
#   [PATCH] sh64: Beat dcache disabling back into submission
#   
#   Somewhere along the line dcache disabling decided it wanted to stop itself
#   from compiling.  So we fix it.
#   
#   Signed-off-by: Paul Mundt <lethal@linux-sh.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/sh64/mm/cache.c
#   2005/03/07 20:41:27-08:00 lethal@Linux-SH.ORG +13 -2
#   sh64: Beat dcache disabling back into submission
# 
# ChangeSet
#   2005/03/08 09:35:14-08:00 lethal@Linux-SH.ORG 
#   [PATCH] sh64: Send cli()/sti() back from whence it came
#   
#   There were a couple of cli()/sti() users left, so we get rid of them..
#   Hopefully this is the last of this mess.
#   
#   Signed-off-by: James Nelson <james4765@cwazy.co.uk>
#   Signed-off-by: Paul Mundt <lethal@linux-sh.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/sh64/mm/fault.c
#   2005/03/07 21:14:49-08:00 lethal@Linux-SH.ORG +1 -1
#   sh64: Send cli()/sti() back from whence it came
# 
# arch/sh64/mach-cayman/irq.c
#   2005/03/07 20:41:27-08:00 lethal@Linux-SH.ORG +4 -4
#   sh64: Send cli()/sti() back from whence it came
# 
# arch/sh64/kernel/time.c
#   2005/03/07 20:41:27-08:00 lethal@Linux-SH.ORG +2 -2
#   sh64: Send cli()/sti() back from whence it came
# 
# ChangeSet
#   2005/03/08 09:34:59-08:00 lethal@Linux-SH.ORG 
#   [PATCH] sh64: TMU init bugfix
#   
#   TMU0 initialization was broken when the timer was already started by someone
#   else (for instance, a boot loader).  This fixes it.
#   
#   Signed-off-by: Andy Sturges <andy.sturges@st.com>
#   Signed-off-by: Richard Curnow <rc@rc0.org.uk>
#   Signed-off-by: Paul Mundt <lethal@linux-sh.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/sh64/kernel/time.c
#   2005/03/07 21:14:50-08:00 lethal@Linux-SH.ORG +2 -0
#   sh64: TMU init bugfix
# 
# ChangeSet
#   2005/03/08 09:34:45-08:00 lethal@Linux-SH.ORG 
#   [PATCH] sh64: IDE updates
#   
#   This fixes up a few minor IDE issues on sh64.  We also enable cayman on-board
#   IDE in the SuperIO.
#   
#   Signed-off-by: Richard Curnow <rc@rc0.org.uk>
#   Signed-off-by: Paul Mundt <lethal@linux-sh.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/asm-sh64/irq.h
#   2005/03/07 20:41:27-08:00 lethal@Linux-SH.ORG +3 -2
#   sh64: IDE updates
# 
# include/asm-sh64/ide.h
#   2005/03/07 20:41:27-08:00 lethal@Linux-SH.ORG +5 -0
#   sh64: IDE updates
# 
# arch/sh64/mach-cayman/setup.c
#   2005/03/07 20:41:27-08:00 lethal@Linux-SH.ORG +44 -7
#   sh64: IDE updates
# 
# ChangeSet
#   2005/03/08 09:34:30-08:00 lethal@Linux-SH.ORG 
#   [PATCH] sh64: generic hardirqs
#   
#   Convert sh64 to use generic hardirqs.
#   
#   Signed-off-by: Paul Mundt <lethal@linux-sh.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/asm-sh64/hardirq.h
#   2005/03/07 20:41:27-08:00 lethal@Linux-SH.ORG +13 -1
#   sh64: generic hardirqs
# 
# arch/sh64/kernel/irq.c
#   2005/03/07 20:41:27-08:00 lethal@Linux-SH.ORG +4 -610
#   sh64: generic hardirqs
# 
# arch/sh64/Kconfig
#   2005/03/07 21:14:49-08:00 lethal@Linux-SH.ORG +12 -0
#   sh64: generic hardirqs
# 
# ChangeSet
#   2005/03/08 09:34:16-08:00 lethal@Linux-SH.ORG 
#   [PATCH] sh64: module support
#   
#   This adds support for modules.
#   
#   Signed-off-by: Richard Curnow <rc@rc0.org.uk>
#   Signed-off-by: Paul Mundt <lethal@linux-sh.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/sh64/kernel/module.c
#   2005/03/07 20:41:27-08:00 lethal@Linux-SH.ORG +161 -0
#   sh64: module support
# 
# include/asm-sh64/module.h
#   2005/03/07 20:41:27-08:00 lethal@Linux-SH.ORG +8 -0
#   sh64: module support
# 
# include/asm-sh64/elf.h
#   2005/03/07 20:41:27-08:00 lethal@Linux-SH.ORG +6 -0
#   sh64: module support
# 
# arch/sh64/kernel/module.c
#   2005/03/07 20:41:27-08:00 lethal@Linux-SH.ORG +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/arch/sh64/kernel/module.c
# 
# ChangeSet
#   2005/03/08 09:34:00-08:00 lethal@Linux-SH.ORG 
#   [PATCH] sh64: iomap interface.
#   
#   This adds support for the iomap interface to sh64.  As a result of this, we
#   can also clean up a lot of the sh64 common I/O routines.
#   
#   We also add a board-specific ioport_map() for the cayman
#   so we can use iomap generically.
#   
#   Signed-off-by: Paul Mundt <lethal@linux-sh.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/sh64/mach-cayman/iomap.c
#   2005/03/07 20:41:27-08:00 lethal@Linux-SH.ORG +24 -0
#   sh64: iomap interface.
# 
# include/asm-sh64/io.h
#   2005/03/07 20:41:27-08:00 lethal@Linux-SH.ORG +51 -34
#   sh64: iomap interface.
# 
# arch/sh64/mach-cayman/iomap.c
#   2005/03/07 20:41:27-08:00 lethal@Linux-SH.ORG +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/arch/sh64/mach-cayman/iomap.c
# 
# arch/sh64/mach-cayman/Makefile
#   2005/03/07 20:41:27-08:00 lethal@Linux-SH.ORG +1 -1
#   sh64: iomap interface.
# 
# arch/sh64/lib/iomap.c
#   2005/03/07 20:41:27-08:00 lethal@Linux-SH.ORG +55 -0
#   sh64: iomap interface.
# 
# arch/sh64/lib/io.c
#   2005/03/07 20:41:27-08:00 lethal@Linux-SH.ORG +3 -70
#   sh64: iomap interface.
# 
# arch/sh64/lib/Makefile
#   2005/03/07 20:41:27-08:00 lethal@Linux-SH.ORG +1 -1
#   sh64: iomap interface.
# 
# arch/sh64/lib/iomap.c
#   2005/03/07 20:41:27-08:00 lethal@Linux-SH.ORG +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/arch/sh64/lib/iomap.c
# 
# ChangeSet
#   2005/03/08 09:33:45-08:00 lethal@Linux-SH.ORG 
#   [PATCH] sh64: defconfig updates
#   
#   Update for the cayman defconfig.  We also drop the generic arch/sh64/defconfig
#   as it has very little hope of being kept up to date, so we use the cayman one
#   instead.
#   
#   Signed-off-by: Paul Mundt <lethal@linux-sh.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/sh64/configs/cayman_defconfig
#   2005/03/07 20:41:26-08:00 lethal@Linux-SH.ORG +204 -26
#   sh64: defconfig updates
# 
# BitKeeper/deleted/.del-defconfig~ba3d6dc8a0aaa03e
#   2005/03/08 09:33:36-08:00 lethal@Linux-SH.ORG +0 -0
#   Delete: arch/sh64/defconfig
# 
# ChangeSet
#   2005/03/08 09:33:31-08:00 lethal@Linux-SH.ORG 
#   [PATCH] sh64: Align slab caches on an 8-byte boundary
#   
#   The BYTES_PER_WORD assumption doesn't work out on sh64 when we are using a
#   32-bit ABI.  We want slab caches to be forced to a minimum alignment of
#   8-bytes, as it was before Anton's change.
#   
#   This was also already discussed at length with Manfred in this thread:
#   
#   	http://marc.theaimsgroup.com/?l=linux-kernel&m=110227138116749&w=2
#   
#   Signed-off-by: Paul Mundt <lethal@linux-sh.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/asm-sh64/uaccess.h
#   2005/03/07 20:41:26-08:00 lethal@Linux-SH.ORG +6 -0
#   sh64: Align slab caches on an 8-byte boundary
# 
# ChangeSet
#   2005/03/08 09:33:17-08:00 lethal@Linux-SH.ORG 
#   [PATCH] sh64: Update Richard Curnow's MAINTAINERS info
#   
#   Fairly self explanatory..
#   
#   Signed-off-by: Richard Curnow <rc@rc0.org.uk>
#   Signed-off-by: Paul Mundt <lethal@linux-sh.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# MAINTAINERS
#   2005/03/07 20:41:26-08:00 lethal@Linux-SH.ORG +2 -1
#   sh64: Update Richard Curnow's MAINTAINERS info
# 
# ChangeSet
#   2005/03/08 09:33:02-08:00 lethal@Linux-SH.ORG 
#   [PATCH] sh64: Initial checkstack port
#   
#   This provides a port of checkstack for sh64 for the simple frames
#   allocated as an immediate with a single instruction.
#   
#   Stack frame creation on sh64 happens in a couple of different ways,
#   when the frame size is less than 511 bytes an addi or addi.l is
#   typically used, generally along the lines of something like:
#   
#   	addi{,.l}	r15, -IMM_FRAME_SIZE, r15
#   
#   For larger frames, this ends up getting split up into a
#   movi/sub pair:
#   
#   	movi	IMM_FRAME_SIZE, rX
#   	sub	r15, rX, r15
#   
#   We currently don't handle the split pair case, as basically
#   any register can be used, and there is no easy way to determine
#   what happens without scanning the prologue multiple times and
#   using some sort of register cache (we already do something
#   similar for the sh64 stack unwinder, but it would be preferable
#   not to do this in perl..).
#   
#   This does have limited usefulness in that we are not easily able
#   to check for huge frames without manual inspection, but this is
#   still useful enough in the general case to be worth doing for
#   the addi/addi.l case as long as people are aware of this caveat.
#   
#   It may be worth revisiting at a later point to try and catch the
#   larger users though.
#   
#   Signed-off-by: Paul Mundt <lethal@linux-sh.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# scripts/checkstack.pl
#   2005/03/07 20:41:26-08:00 lethal@Linux-SH.ORG +7 -0
#   sh64: Initial checkstack port
# 
# ChangeSet
#   2005/03/08 09:32:48-08:00 yuasa@hh.iij4u.or.jp 
#   [PATCH] mips: add spare timer init
#   
#   This patch adds spare timer initialization for NEC VR41xx.
#   
#   Signed-off-by: Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/asm-mips/vr41xx/vr41xx.h
#   2005/03/07 21:14:35-08:00 yuasa@hh.iij4u.or.jp +1 -1
#   mips: add spare timer init
# 
# arch/mips/vr41xx/common/init.c
#   2005/03/07 20:41:26-08:00 yuasa@hh.iij4u.or.jp +27 -0
#   mips: add spare timer init
# 
# ChangeSet
#   2005/03/08 09:32:34-08:00 paulus@samba.org 
#   [PATCH] ppc64: allow dynamic enablement of EEH
#   
#   This patch is from John Rose <johnrose@austin.ibm.com>.
#   
#   EEH scans the system I/O adapters at boot for EEH-capabilities.  If no
#   EEH-capable adapters are found, the subsystem is marked disabled for the life
#   of the system.  EEH should allow dynamic enabling of the EEH subsystem when
#   hotplug-adding an adapter.
#   
#   Signed-off-by: John Rose <johnrose@austin.ibm.com>
#   Signed-off-by: Paul Mackerras <paulus@samba.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/ppc64/kernel/eeh.c
#   2005/03/07 20:41:26-08:00 paulus@samba.org +1 -1
#   ppc64: allow dynamic enablement of EEH
# 
# ChangeSet
#   2005/03/08 09:32:20-08:00 paulus@samba.org 
#   [PATCH] ppc64: set pci_io_base dynamically if necessary
#   
#   This patch is from John Rose <johnrose@austin.ibm.com>.
#   
#   Upon DLPAR addition of a PCI Host Brige to a system with purely virtual I/O,
#   set pci_io_base as necessary.
#   
#   Signed-off-by: John Rose <johnrose@austin.ibm.com>
#   Signed-off-by: Paul Mackerras <paulus@samba.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/ppc64/kernel/pci.h
#   2005/03/07 20:41:26-08:00 paulus@samba.org +1 -2
#   ppc64: set pci_io_base dynamically if necessary
# 
# arch/ppc64/kernel/pci.c
#   2005/03/07 20:41:26-08:00 paulus@samba.org +5 -1
#   ppc64: set pci_io_base dynamically if necessary
# 
# arch/ppc64/kernel/pSeries_pci.c
#   2005/03/07 20:41:26-08:00 paulus@samba.org +3 -1
#   ppc64: set pci_io_base dynamically if necessary
# 
# ChangeSet
#   2005/03/08 09:32:05-08:00 paulus@samba.org 
#   [PATCH] ppc64: kprobes: handle trap variants while processing probes
#   
#   This patch is from Ananth N Mavinakayanahalli <ananth@in.ibm.com>.
#   
#   While processing a kprobe, we were currently not handling all available trap
#   variants available on PowerPC.  This lead to the breakage of BUG() handling in
#   ppc64.
#   
#   Signed-off-by: Paul Mackerras <paulus@samba.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/asm-ppc64/kprobes.h
#   2005/03/07 20:41:25-08:00 paulus@samba.org +5 -0
#   ppc64: kprobes: handle trap variants while processing probes
# 
# arch/ppc64/kernel/kprobes.c
#   2005/03/07 20:41:25-08:00 paulus@samba.org +9 -2
#   ppc64: kprobes: handle trap variants while processing probes
# 
# ChangeSet
#   2005/03/08 09:31:51-08:00 paulus@samba.org 
#   [PATCH] ppc64: C99 initializers for hw_interrupt_type
#   
#   This patch is from Thomas Gleixner <tglx@linutronix.de>.
#   
#   Convert the initializers of hw_interrupt_type structures to C99 initializers.
#   
#   Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
#   Signed-off-by: Paul Mackerras <paulus@samba.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/ppc64/kernel/i8259.c
#   2005/03/07 20:41:25-08:00 paulus@samba.org +5 -8
#   ppc64: C99 initializers for hw_interrupt_type
# 
# ChangeSet
#   2005/03/08 09:31:37-08:00 paulus@samba.org 
#   [PATCH] ppc64: fix init_boot_display link error
#   
#   This patch is from Amos Waterland <apw@us.ibm.com>.
#   
#   In pmac_setup.c, the function init_boot_display as currently written only
#   makes sense with CONFIG_BOOTX_TEXT enabled, and causes a link error if it is
#   not enabled.
#   
#   Signed-off-by: Amos Waterland <apw@us.ibm.com>
#   Signed-off-by: Paul Mackerras <paulus@samba.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/ppc64/kernel/pmac_setup.c
#   2005/03/07 20:41:25-08:00 paulus@samba.org +1 -1
#   ppc64: fix init_boot_display link error
# 
# ChangeSet
#   2005/03/08 09:31:23-08:00 paulus@samba.org 
#   [PATCH] ppc64: addresses from OF getting truncated to 32-bits
#   
#   This patch is from Jake Moilanen <moilanen@austin.ibm.com>,
#   reformatted by me.
#   
#   The `assigned-addresses' property in the Open Firmware device tree
#   nodes for PCI devices has 64 bits of PCI bus address, but we were only
#   using 32.  This patch fixes it so we use all 64.
#   
#   Signed-off-by: Jake Moilanen <moilanen@austin.ibm.com>
#   Signed-off-by: Paul Mackerras <paulus@samba.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/ppc64/kernel/prom.c
#   2005/03/07 20:41:25-08:00 paulus@samba.org +4 -2
#   ppc64: addresses from OF getting truncated to 32-bits
# 
# ChangeSet
#   2005/03/08 09:31:09-08:00 paulus@samba.org 
#   [PATCH] ppc64: Mode 2 PCI-X config space size fix
#   
#   This patch is from Brian King <brking@us.ibm.com>.
#   
#   When working with a PCI-X Mode 2 adapter on a PCI-X Mode 1 PPC64 system, the
#   current code used to determine the config space size of a device results in a
#   PCI Master abort and an EEH error, resulting in the device being taken
#   offline.  This patch checks OF to see if the PCI bridge supports PCI-X Mode 2
#   and fails config accesses beyond 256 bytes if it does not.
#   
#   Signed-off-by: Brian King <brking@us.ibm.com>
#   Signed-off-by: Paul Mackerras <paulus@samba.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/asm-ppc64/prom.h
#   2005/03/07 20:41:25-08:00 paulus@samba.org +1 -0
#   ppc64: Mode 2 PCI-X config space size fix
# 
# arch/ppc64/kernel/pci_dn.c
#   2005/03/07 20:41:25-08:00 paulus@samba.org +3 -0
#   ppc64: Mode 2 PCI-X config space size fix
# 
# arch/ppc64/kernel/pSeries_pci.c
#   2005/03/07 21:14:53-08:00 paulus@samba.org +16 -4
#   ppc64: Mode 2 PCI-X config space size fix
# 
# arch/ppc64/kernel/iSeries_pci.c
#   2005/03/07 20:41:25-08:00 paulus@samba.org +6 -0
#   ppc64: Mode 2 PCI-X config space size fix
# 
# ChangeSet
#   2005/03/08 09:30:54-08:00 colin@colino.net 
#   [PATCH] Make therm_adt746x handle latest powerbooks
#   
#   This patch lets therm_adt746x handle the latest powerbooks.  In these ones,
#   Apple doesn't put the i2c bus number in the "reg" property of the fan node.
#    Instead, we can get the bus number from the fan node path, which looks
#   like "/proc/device-tree/.../i2c-bus@1/.../fan".  Here's a patch that
#   handles both old and new form.
#   
#   Signed-off-by: Colin Leroy <colin@colino.net>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/macintosh/therm_adt746x.c
#   2005/03/07 20:41:25-08:00 colin@colino.net +9 -1
#   Make therm_adt746x handle latest powerbooks
# 
# ChangeSet
#   2005/03/08 09:30:40-08:00 mgreer@mvista.com 
#   [PATCH] ppc32: add Radstone PPC7D platform support
#   
#   Radstone PPC7D are ppc7447A VME boards with Marvell Discovery-II, dual
#   GigE, dual PMC, 6 serial ports, keyboard/mouse, USB and optional SCSI/VGA. 
#   This patch adds support for the PPC7D platform.
#   
#   Signed-off-by: James Chapman <jchapman@katalix.com>
#   Signed-off-by: Mark A. Greer <mgreer@mvista.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/ppc/platforms/radstone_ppc7d.h
#   2005/03/07 20:41:25-08:00 mgreer@mvista.com +434 -0
#   ppc32: add Radstone PPC7D platform support
# 
# arch/ppc/platforms/radstone_ppc7d.c
#   2005/03/07 20:41:25-08:00 mgreer@mvista.com +1408 -0
#   ppc32: add Radstone PPC7D platform support
# 
# arch/ppc/configs/radstone_ppc7d_defconfig
#   2005/03/07 20:41:25-08:00 mgreer@mvista.com +870 -0
#   ppc32: add Radstone PPC7D platform support
# 
# include/asm-ppc/serial.h
#   2005/03/07 20:41:25-08:00 mgreer@mvista.com +2 -0
#   ppc32: add Radstone PPC7D platform support
# 
# arch/ppc/syslib/Makefile
#   2005/03/07 20:41:25-08:00 mgreer@mvista.com +1 -0
#   ppc32: add Radstone PPC7D platform support
# 
# arch/ppc/platforms/radstone_ppc7d.h
#   2005/03/07 20:41:25-08:00 mgreer@mvista.com +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/arch/ppc/platforms/radstone_ppc7d.h
# 
# arch/ppc/platforms/radstone_ppc7d.c
#   2005/03/07 20:41:25-08:00 mgreer@mvista.com +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/arch/ppc/platforms/radstone_ppc7d.c
# 
# arch/ppc/platforms/Makefile
#   2005/03/07 20:41:25-08:00 mgreer@mvista.com +1 -0
#   ppc32: add Radstone PPC7D platform support
# 
# arch/ppc/configs/radstone_ppc7d_defconfig
#   2005/03/07 20:41:25-08:00 mgreer@mvista.com +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/arch/ppc/configs/radstone_ppc7d_defconfig
# 
# arch/ppc/boot/simple/misc-radstone_ppc7d.c
#   2005/03/07 20:41:25-08:00 mgreer@mvista.com +19 -0
#   ppc32: add Radstone PPC7D platform support
# 
# arch/ppc/boot/simple/Makefile
#   2005/03/07 20:41:25-08:00 mgreer@mvista.com +4 -0
#   ppc32: add Radstone PPC7D platform support
# 
# arch/ppc/Kconfig
#   2005/03/07 20:41:25-08:00 mgreer@mvista.com +6 -2
#   ppc32: add Radstone PPC7D platform support
# 
# arch/ppc/boot/simple/misc-radstone_ppc7d.c
#   2005/03/07 20:41:25-08:00 mgreer@mvista.com +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/arch/ppc/boot/simple/misc-radstone_ppc7d.c
# 
# ChangeSet
#   2005/03/08 09:30:25-08:00 jeffm@suse.com 
#   [PATCH] reiserfs: change reiserfs to use S_PRIVATE
#   
#   This patch changes reiserfs to use the VFS level private inode flags, and
#   eliminates the old reiserfs private inode flag.
#   
#   Signed-off-by: Jeff Mahoney <jeffm@suse.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/linux/reiserfs_xattr.h
#   2005/03/07 20:41:24-08:00 jeffm@suse.com +2 -2
#   reiserfs: change reiserfs to use S_PRIVATE
# 
# include/linux/reiserfs_fs_i.h
#   2005/03/07 20:41:24-08:00 jeffm@suse.com +2 -3
#   reiserfs: change reiserfs to use S_PRIVATE
# 
# ChangeSet
#   2005/03/08 09:30:08-08:00 jeffm@suse.com 
#   [PATCH] reiserfs: private inode abstracted to static inline
#   
#   This patch moves the assignment of i_priv_object to a static inline.  This
#   is in preparation for selinux support in reiserfs.
#   
#   Signed-off-by: Jeff Mahoney <jeffm@suse.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/linux/reiserfs_xattr.h
#   2005/03/07 21:14:55-08:00 jeffm@suse.com +7 -0
#   reiserfs: private inode abstracted to static inline
# 
# fs/reiserfs/xattr_acl.c
#   2005/03/07 20:41:24-08:00 jeffm@suse.com +1 -1
#   reiserfs: private inode abstracted to static inline
# 
# fs/reiserfs/xattr.c
#   2005/03/07 20:41:24-08:00 jeffm@suse.com +1 -5
#   reiserfs: private inode abstracted to static inline
# 
# fs/reiserfs/namei.c
#   2005/03/07 21:14:29-08:00 jeffm@suse.com +1 -1
#   reiserfs: private inode abstracted to static inline
# 
# fs/reiserfs/inode.c
#   2005/03/07 20:41:24-08:00 jeffm@suse.com +2 -0
#   reiserfs: private inode abstracted to static inline
# 
# ChangeSet
#   2005/03/08 09:29:53-08:00 jeffm@suse.com 
#   [PATCH] selinux: internal inode loop needs IS_PRIVATE test
#   
#   This patch applies the IS_PRIVATE test to the selinux internal inode loop.
#   
#   Signed-off-by: Jeff Mahoney <jeffm@suse.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# security/selinux/hooks.c
#   2005/03/07 21:14:14-08:00 jeffm@suse.com +2 -1
#   selinux: internal inode loop needs IS_PRIVATE test
# 
# ChangeSet
#   2005/03/08 09:29:39-08:00 jeffm@suse.com 
#   [PATCH] vfs: adds the S_PRIVATE flag and adds use to security
#   
#   This patch series adds SELinux support to reiserfs.
#   
#   This patch adds an S_PRIVATE flag to inode->i_flags to mark an inode as
#   filesystem-internal. As such, it should be excepted from the security
#   infrastructure to allow the filesystem to perform its own access control.
#   
#   Signed-off-by: Jeff Mahoney <jeffm@suse.com>
#   Acked-by:  Stephen Smalley <sds@tycho.nsa.gov>
#   Acked-by: Chris Wright <chrisw@osdl.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/linux/security.h
#   2005/03/07 20:41:24-08:00 jeffm@suse.com +64 -0
#   vfs: adds the S_PRIVATE flag and adds use to security
# 
# include/linux/fs.h
#   2005/03/07 20:41:24-08:00 jeffm@suse.com +2 -0
#   vfs: adds the S_PRIVATE flag and adds use to security
# 
# ChangeSet
#   2005/03/08 09:29:24-08:00 ncunningham@cyclades.com 
#   [PATCH] Speed freeing memory for suspend.
#   
#   Here's a patch I've prepared which improves the speed at which memory is freed
#   prior to suspend.  It should be a big gain for swsusp.  For suspend2, it isn't
#   used much, but has shown big improvements when I set a very low image size
#   limit and had memory quite full.
#   
#   1GB P4, 2.6.11+Suspend2 2.1.8.
#   Soft image size limit set to 2MB to emulate Pavel's implementation (eat
#   as much memory as we can).
#   
#   Without patch:
#   Freed  16545 pages in  4000 jiffies = 16.16 MB/s
#   Freed  83281 pages in 14060 jiffies = 23.14 MB/s
#   Freed 237754 pages in 41482 jiffies = 22.39 MB/s
#   
#   With patch:
#   Freed  52257 pages in  6700 jiffies = 30.46 MB/s
#   Freed 105693 pages in 11035 jiffies = 37.41 MB/s
#   Freed 239007 pages in 18284 jiffies = 51.06 MB/s
#   
#   With a less aggressive image size limit (200MB):
#   
#   Without the patch:
#   Freed  14600 pages in  1749 jiffies = 32.61 MB/s (Anomolous!)
#   Freed  88563 pages in 14719 jiffies = 23.50 MB/s
#   Freed 205734 pages in 32389 jiffies = 24.81 MB/s
#   
#   With the patch:
#   Freed  68252 pages in   496 jiffies = 537.52 MB/s
#   Freed 116464 pages in   569 jiffies = 798.54 MB/s
#   Freed 209699 pages in   705 jiffies = 1161.89 MB/s
#   
#   The later pages take more work to get, which accounts for the slower MB/s with
#   smaller numbers of pages to free.  Without the patch, though, getting the
#   easier pages also takes longer because we do a far greater number of
#   invocations of shrink_all_memory in order to get the same number of pages.
#   
#   Signed-Off-By: Nigel Cunningham <ncunningham@cyclades.com>
#   Acked-By: Pavel Machek <pavel@ucw.cz>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# mm/vmscan.c
#   2005/03/07 20:41:24-08:00 ncunningham@cyclades.com +17 -9
#   Speed freeing memory for suspend.
# 
# ChangeSet
#   2005/03/08 09:29:09-08:00 hch@lst.de 
#   [PATCH] put newly registered shrinkers at the tail of the list
#   
#   This way we actually shake dentries before inodes and thus mark more
#   inodes reclaimable once we shake them.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# mm/vmscan.c
#   2005/03/07 21:14:56-08:00 hch@lst.de +1 -1
#   put newly registered shrinkers at the tail of the list
# 
# ChangeSet
#   2005/03/08 09:28:54-08:00 hugh@veritas.com 
#   [PATCH] Bad page state mapcount
#   
#   A small change to the tests for "Bad page state", to avoid one class of the
#   page_remove_rmap BUG reports, giving more information while letting the
#   system continue: check page_mapcount (_mapcount != -1) rather than
#   page_mapped (_mapcount >= 0).
#   
#   And how does _mapcount go bad?  In the case under study, it looks sure now
#   that an overheating(?) Pentium III sometimes gets confused by a pair of
#   instructions in the no-buddy-bitmap __free_pages_bulk, and clears the
#   PG_private bit from the _mapcount field while buddying around - changing
#   PG_private value changes the bit cleared from _mapcount.  Bad page state
#   mapcount:-4096 would have tracked this down much sooner, and will be
#   recognizable if other cpus show the same aberrant reaction to 2.6.11.
#   
#   The page_remove_rmap BUG does need to be replaced by more permissive and
#   informative handling, but I'm not yet ready to to finalize such a patch.
#   
#   Please admit Colin Harrison to the Order of the Iridescent Penguin, for his
#   tireless testing.
#   
#   Signed-off-by: Hugh Dickins <hugh@veritas.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# mm/page_alloc.c
#   2005/03/07 20:41:24-08:00 hugh@veritas.com +2 -2
#   Bad page state mapcount
# 
# ChangeSet
#   2005/03/08 09:28:40-08:00 marcelo.tosatti@cyclades.com 
#   [PATCH] use find_trylock_page in free_swap_and_cache instead of hand coding
#   
#   Use find_*_page helpers in swap code instead handcoding it.
#   
#   Signed-off-by: Marcelo Tosatti <marcelo.tosatti@cyclades.com>
#   Acked-by: Hugh Dickins <hugh@veritas.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# mm/swapfile.c
#   2005/03/07 20:41:23-08:00 marcelo.tosatti@cyclades.com +2 -8
#   use find_trylock_page in free_swap_and_cache instead of hand coding
# 
# mm/swap_state.c
#   2005/03/07 20:41:23-08:00 marcelo.tosatti@cyclades.com +5 -12
#   use find_trylock_page in free_swap_and_cache instead of hand coding
# 
# ChangeSet
#   2005/03/08 09:28:25-08:00 oleg@tv-sign.ru 
#   [PATCH] readahead: trivial, small comments update
#   
#   On top of "[PATCH 2/2] readahead: improve sequential read detection".
#   
#   Signed-off-by: Oleg Nesterov <oleg@tv-sign.ru>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# mm/readahead.c
#   2005/03/07 20:41:23-08:00 oleg@tv-sign.ru +13 -18
#   readahead: trivial, small comments update
# 
# ChangeSet
#   2005/03/08 09:28:11-08:00 oleg@tv-sign.ru 
#   [PATCH] readahead: improve sequential read detection
#   
#   1. Current code can't always detect sequential reading, in case
#      when read size is not PAGE_CACHE_SIZE aligned.
#   
#      If application reads the file by 4096+512 chunks, we have:
#      1st read: first read detected, prev_page = 2.
#      2nd read: offset == 2, the read is considered random.
#   
#      page_cache_readahead() should treat prev_page == offset as
#      sequential access. In this case it is better to ++offset,
#      because of blockable_page_cache_readahead(offset, size).
#   
#   2. If application reads 4096 bytes with *ppos == 512, we have to
#      read 2 pages, but req_size == 1 in do_generic_mapping_read().
#   
#      Usually it's not a problem. But in random read case it results
#      in unnecessary page cache misses.
#   
#   ~$ time dd conv=notrunc if=/tmp/GIG of=/tmp/dummy bs=$((4096+512))
#   
#   2.6.11-clean:	real=370.35 user=0.16 sys=14.66
#   2.6.11-patched:	real=234.49 user=0.19 sys=12.41
#   
#   Signed-off-by: Oleg Nesterov <oleg@tv-sign.ru>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# mm/readahead.c
#   2005/03/07 21:14:56-08:00 oleg@tv-sign.ru +10 -10
#   readahead: improve sequential read detection
# 
# mm/filemap.c
#   2005/03/07 20:41:23-08:00 oleg@tv-sign.ru +6 -9
#   readahead: improve sequential read detection
# 
# ChangeSet
#   2005/03/08 09:27:57-08:00 oleg@tv-sign.ru 
#   [PATCH] readahead: simplify ra->size testing
#   
#   Currently page_cache_readahead() treats ra->size == 0 (first read)
#   and ra->size == -1 (ra_off was called) separately, but does exactly
#   the same in both cases.
#   
#   With this patch we may assume that the reading starts in 'ra_off()'
#   state, so we don't need to consider the first read as a special case.
#   
#   
#   file_ra_state_init() sets
#   	ra->prev_page = -1;
#   	ra->size      =  0;
#   
#   When the page_cache_readahead() is called for the first time it sets
#   ra->size to nonzero value either via get_init_ra_size() or ra_off().
#   So ra->size == 0 implies that ra->prev_page == -1. I am ignoring the
#   case when readahead is disabled via ra->ra_pages == 0.
#   
#   
#   page_cache_readahead detects sub-page sized reads:
#   	if (offset == ra->prev_page && req_size == 1 && ra->size != 0)
#   
#   But if offset == ra->prev_page, then ra->size == 0 can happen only if
#   offset == -1, so there is no need to check ra->size here. If application
#   starts reading 16Tb file from the last page then readahead can't help.
#   
#   
#   First offset==0 read or first sequential detection:
#   	if ((ra->size == 0 && offset == 0) || (ra->size == -1 && sequential)
#   could be changed to:
#   	if ((ra->size == 0 && sequential) || (ra->size == -1 && sequential)
#   which means:
#   	if (sequential && (ra->size == 0 || ra->size == -1))
#   
#   
#   Random case detection:
#   	if (!sequential || (ra->size == 0))
#   But if sequential == 1, then ra->size can't be 0, this case is already handled
#   before.
#   
#   
#   Now we have:
#   
#   	if (offset == ra->prev_page && req_size == 1)
#   		/* sub-page reads */
#   
#   	if (sequential && (ra->size == 0 || ra->size == -1))
#   		/* first offset==0 read or first sequential */
#   
#   	if (!sequential)
#   		/* random case */
#   
#   Now ->size is checked only in one place, so ra_off() can set ra->size = 0,
#   and we can just test ->size against 0.
#   
#   Signed-off-by: Oleg Nesterov <oleg@tv-sign.ru>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# mm/readahead.c
#   2005/03/07 21:14:56-08:00 oleg@tv-sign.ru +4 -6
#   readahead: simplify ra->size testing
# 
# ChangeSet
#   2005/03/08 09:27:43-08:00 oleg@tv-sign.ru 
#   [PATCH] readahead: cleanup blockable_page_cache_readahead()
#   
#   I think that do_page_cache_readahead() can be inlined in
#   blockable_page_cache_readahead(), this makes the code a bit more readable in
#   my opinion.
#   
#   Also makes check_ra_success() static inline.
#   
#   Signed-off-by: Oleg Nesterov <oleg@tv-sign.ru>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# mm/readahead.c
#   2005/03/07 21:14:57-08:00 oleg@tv-sign.ru +7 -11
#   readahead: cleanup blockable_page_cache_readahead()
# 
# ChangeSet
#   2005/03/08 09:27:29-08:00 oleg@tv-sign.ru 
#   [PATCH] readahead: factor out duplicated code
#   
#   This patch introduces make_ahead_window() function for simplification of
#   page_cache_readahead.
#   
#   Signed-off-by: Oleg Nesterov <oleg@tv-sign.ru>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# mm/readahead.c
#   2005/03/07 21:14:57-08:00 oleg@tv-sign.ru +47 -54
#   readahead: factor out duplicated code
# 
# ChangeSet
#   2005/03/08 09:27:15-08:00 oleg@tv-sign.ru 
#   [PATCH] readahead: cleanup get_next_ra_size()
#   
#   get_next_ra_size() can get all info from file_ra_state.
#   
#   Signed-off-by: Oleg Nesterov <oleg@tv-sign.ru>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# mm/readahead.c
#   2005/03/07 21:14:57-08:00 oleg@tv-sign.ru +11 -13
#   readahead: cleanup get_next_ra_size()
# 
# ChangeSet
#   2005/03/08 09:27:01-08:00 oleg@tv-sign.ru 
#   [PATCH] readahead: unneeded prev_page assignments
#   
#   There is no point in setting ra->prev_page before 'goto out', it will be
#   overwritten anyway.
#   
#   Signed-off-by: Oleg Nesterov <oleg@tv-sign.ru>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# mm/readahead.c
#   2005/03/07 21:14:57-08:00 oleg@tv-sign.ru +1 -4
#   readahead: unneeded prev_page assignments
# 
# ChangeSet
#   2005/03/08 09:26:46-08:00 hugh@veritas.com 
#   [PATCH] copy_pte_range latency fix
#   
#   Ingo's patch to reduce scheduling latencies, by checking for lockbreak in
#   copy_page_range, was in the -VP and -mm patchsets some months ago; but got
#   preempted by the 4level rework, and not reinstated since.  Restore it now
#   in copy_pte_range - which mercifully makes it easier.
#   
#   Signed-off-by: Hugh Dickins <hugh@veritas.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# mm/memory.c
#   2005/03/07 20:41:22-08:00 hugh@veritas.com +16 -4
#   copy_pte_range latency fix
# 
# ChangeSet
#   2005/03/08 09:26:32-08:00 gordon.jin@intel.com 
#   [PATCH] Fix mincore cornercases: overflow caused by large "len"
#   
#   This patch fixes 2 cornercases of overflow caused by argument len in
#   sys_mincore():
#   
#   Case 1: len is so large that will overflow to 0 after page alignment.
#   E.g. len=(size_t)(-1), i.e. 0xff...ff.
#   Expected result: it's overflow and return ENOMEM.
#   Current result: len is aligned to 0, then treated the same as len=0 and
#   return succeed.
#   This cornercase has been fixed in do_mmap_pgoff(), and here
#   sys_mincore() also needs this fix.
#   
#   Case 2: len is a large number but will not overflow after alignment. But
#   start+len will overflow.
#   E.g. len=(size_t)(-PAGE_SIZE), and start>0.
#   Expected result: it's overflow and return ENOMEM.
#   Current result: return EINVAL. Looks like considering len as a
#   non-positive value, probably influenced by manpage. But since the type
#   of len is size_t, i.e. unsigned, it shouldn't be considered as
#   non-positive value.
#   I've also reported this inconsistency to manpage mincore.
#   
#   Signed-off-by: Gordon Jin <gordon.jin@intel.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# mm/mincore.c
#   2005/03/07 20:41:22-08:00 gordon.jin@intel.com +6 -4
#   Fix mincore cornercases: overflow caused by large "len"
# 
# ChangeSet
#   2005/03/08 09:26:18-08:00 pmeda@akamai.com 
#   [PATCH] mempool: protect buffer overflow in mempool_resize
#   
#   - Race in mempool_resize: memcpy can copy at the end of the kmalloced
#     elements.
#   
#   - When new_min_nr is same as min_nr, instead of reallocate and copy, just
#     return, changed '<' to '<='.
#   
#   - Changed while condition to the same sense of if condition from '>' to
#     '<'; it is easy to think with only one of the left and right brains at a
#     time.
#   
#   Signed-off-by: Prasanna Meda <pmeda@akamai.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# mm/mempool.c
#   2005/03/07 20:41:22-08:00 pmeda@akamai.com +9 -3
#   mempool: protect buffer overflow in mempool_resize
# 
# ChangeSet
#   2005/03/08 09:26:04-08:00 haveblue@us.ibm.com 
#   [PATCH] stop using "base" argument in __free_pages_bulk()
#   
#   Appended is a patch which stops using the zone->zone_mem_map to calculate
#   the buddy and combined page pointers.  It uses the fact that the mem_map
#   array is guaranteed to be contigious for the surrounding (1 << MAX_ORDER)
#   pages.  The relative positions of the pages in the physical address space
#   to provide the alignement; which conicidentally fixes the issue where zones
#   are not aligned at MAX_ORDER.  There is a very comprehensive comment in the
#   new code explaining the mathematical relationship between a page and its
#   buddy so I won't reproduce it here.
#   
#   This kind of approach is required for CONFIG_NONLINEAR systems where the
#   mem_map is not contiguous within a zone, and the zone->zone_mem_map is not
#   used at all.
#   
#   This patch has been boot-tested on a large variety of systems and
#   architectures: my P4 laptop, 16-way NUMAQ, 16-way Summit, 4-way x86 SMP,
#   ppc64 LPAR, x86_64, and several ia64 configurations.
#   
#   It has been performance-tested on a 16-way NUMAQ.  SDET shows a very slight
#   (within margin of error) performance gain.  Kernbench shows an
#   approximately ~1% decrease in system time with this patch applied.  So, it
#   has a likely positive performance impact.
#   
#   However, the patch has the potential to have a negative performance impact
#   on systems with an expensive page_to_pfn() implementation.  But, I think
#   the NUMAQ has one of the more expensive ones around, and it doesn't seem
#   mind too much.
#   
#   Signed-off-by: Andy Whitcroft <apw@shadowen.org>
#   Signed-off-by: Dave Hansen <haveblue@us.ibm.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# mm/page_alloc.c
#   2005/03/07 21:14:56-08:00 haveblue@us.ibm.com +44 -15
#   stop using "base" argument in __free_pages_bulk()
# 
# ChangeSet
#   2005/03/08 09:25:50-08:00 nickpiggin@yahoo.com.au 
#   [PATCH] vmscan: reclaim SWAP_CLUSTER_MAX pages in a single pass
#   
#   Here is another small OOM killer improvement.  Previously we needed to
#   reclaim SWAP_CLUSTER_MAX pages in a single pass.  That should be changed so
#   that we need only reclaim that many pages during the entire
#   try_to_free_pages run, without going OOM.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# mm/vmscan.c
#   2005/03/07 21:14:56-08:00 nickpiggin@yahoo.com.au +3 -3
#   vmscan: reclaim SWAP_CLUSTER_MAX pages in a single pass
# 
# ChangeSet
#   2005/03/08 09:25:35-08:00 mingo@elte.hu 
#   [PATCH] simpler topdown mmap layout allocator
#   
#   1. typos/spelling ;-)
#   
#   2. removed prev_vma and find_vma_prev because the condition checked
#      later was always true
#   
#   3. moved the free_area_cache/mmap_base check into arch_unmap_area_topdown
#      where i think it belongs.
#   
#   4. removed the extra free_area_cache setting code in the while loop
#      as it only has to be set when we actually (and successfully) return
#      from this function.
#   
#   The only visible change to the layout should be the following:
#   
#      
# 
# mm/mmap.c
#   2005/03/07 20:41:22-08:00 mingo@elte.hu +22 -37
#   simpler topdown mmap layout allocator
# 
# ChangeSet
#   2005/03/08 09:25:19-08:00 marcelo.tosatti@cyclades.com 
#   [PATCH] vm: pageout throttling
#   
#   With silly pageout testcases it is possible to place huge amounts of memory
#   under I/O.  With a large request queue (CFQ uses 8192 requests) it is
#   possible to place _all_ memory under I/O at the same time.
#   
#   This means that all memory is pinned and unreclaimable and the VM gets
#   upset and goes oom.
#   
#   The patch limits the amount of memory which is under pageout writeout to be
#   a little more than the amount of memory at which balance_dirty_pages()
#   callers will synchronously throttle.
#   
#   This means that heavy pageout activity can starve heavy writeback activity
#   completely, but heavy writeback activity will not cause starvation of
#   pageout.  Because we don't want a simple `dd' to be causing excessive
#   latencies in page reclaim.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# mm/vmscan.c
#   2005/03/07 21:14:58-08:00 marcelo.tosatti@cyclades.com +2 -0
#   vm: pageout throttling
# 
# mm/page-writeback.c
#   2005/03/07 20:41:21-08:00 marcelo.tosatti@cyclades.com +22 -0
#   vm: pageout throttling
# 
# include/linux/writeback.h
#   2005/03/07 20:41:21-08:00 marcelo.tosatti@cyclades.com +1 -0
#   vm: pageout throttling
# 
# ChangeSet
#   2005/03/08 09:25:05-08:00 kai.makisara@kolumbus.fi 
#   [PATCH] make st seekable again
#   
#   Apparently `tar' errors out if it cannot perform lseek() against a tape.  Work
#   around that in-kernel.
#   
#   Signed-off-by: Kai Makisara <kai.makisara@kolumbus.fi>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/scsi/st.c
#   2005/03/07 20:41:21-08:00 kai.makisara@kolumbus.fi +7 -1
#   make st seekable again
# 
# drivers/scsi/osst.c
#   2005/03/07 20:41:21-08:00 kai.makisara@kolumbus.fi +7 -1
#   make st seekable again
# 
# drivers/ide/ide-tape.c
#   2005/03/07 21:14:37-08:00 kai.makisara@kolumbus.fi +7 -1
#   make st seekable again
# 
# ChangeSet
#   2005/03/08 09:24:50-08:00 mporter@kernel.crashing.org 
#   [PATCH] ppc32: Compilation fixes for Ebony, Luan and Ocotea
#   
#   this patch fixes the problem, that the current kernel (linux-2.6.11-rc5)
#   could not be compiled, when "support for early boot texts over serial port"
#   (CONFIG_SERIAL_TEXT_DEBUG=y) is active.
#   
#   Signed-off-by: Gerhard Jaeger <gjaeger@sysgo.com>
#   Signed-off-by: Matt Porter <mporter@kernel.crashing.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/ppc/platforms/4xx/ocotea.h
#   2005/03/07 20:41:21-08:00 mporter@kernel.crashing.org +2 -2
#   ppc32: Compilation fixes for Ebony, Luan and Ocotea
# 
# arch/ppc/platforms/4xx/luan.h
#   2005/03/07 20:41:21-08:00 mporter@kernel.crashing.org +3 -3
#   ppc32: Compilation fixes for Ebony, Luan and Ocotea
# 
# arch/ppc/platforms/4xx/ebony.h
#   2005/03/07 20:41:21-08:00 mporter@kernel.crashing.org +2 -2
#   ppc32: Compilation fixes for Ebony, Luan and Ocotea
# 
# ChangeSet
#   2005/03/08 09:24:37-08:00 akpm@osdl.org 
#   [PATCH] macserial build fix
#   
#   `current' is a lousy choice for a variable name.  This driver explodes on
#   ppc64 because `current' expands to (local_paca->__current).
#   
#   OK, the driver doesn't compile on power4 anyway, but...
#   
#   Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/macintosh/macserial.c
#   2005/03/07 20:41:20-08:00 akpm@osdl.org +3 -3
#   macserial build fix
# 
# ChangeSet
#   2005/03/08 09:24:22-08:00 eric@lammerts.org 
#   [PATCH] cramfs: small stat(2) fix
#   
#   When I stat(2) a device node on a cramfs, the st_blocks field is bogus
#   (it's derived from the size field which in this case holds the major/minor
#   numbers).  This makes du(1) output completely wrong.
#   
#   Signed-off-by: Eric Lammerts <eric@lammerts.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# fs/cramfs/inode.c
#   2005/03/07 20:41:20-08:00 eric@lammerts.org +1 -0
#   cramfs: small stat(2) fix
# 
# ChangeSet
#   2005/03/08 09:24:08-08:00 akpm@osdl.org 
#   [PATCH] ppc64: revert implement-a-vdso-and-use-it-for-signal-trampoline-gas-workaround
#   
#   We don't actually need this.
#   
#   The reason why the ppc64 build exploded was that I had CC="gcc -m64", and even
#   though the build system turns that into "gcc -m64 -m32", that is,
#   surprisingly, equivalent to "gcc -m64".
#   
#   Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/ppc64/kernel/vdso32/gettimeofday.S
#   2005/03/07 20:41:20-08:00 akpm@osdl.org +2 -2
#   ppc64: revert implement-a-vdso-and-use-it-for-signal-trampoline-gas-workaround
# 
# arch/ppc64/kernel/vdso32/datapage.S
#   2005/03/07 20:41:20-08:00 akpm@osdl.org +1 -1
#   ppc64: revert implement-a-vdso-and-use-it-for-signal-trampoline-gas-workaround
# 
# ChangeSet
#   2005/03/08 09:23:53-08:00 bunk@stusta.de 
#   [PATCH] remove drivers/char/tpqic02.c
#   
#   Since at about half a year, this driver was no longer selectable via
#   Kconfig.
#   
#   Since it seems noone missed this driver, therefore this patch removes
#   it.
#   
#   Signed-off-by: Adrian Bunk <bunk@stusta.de>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/linux/mtio.h
#   2005/03/07 20:41:20-08:00 bunk@stusta.de +0 -28
#   remove drivers/char/tpqic02.c
# 
# include/linux/major.h
#   2005/03/07 20:41:20-08:00 bunk@stusta.de +0 -1
#   remove drivers/char/tpqic02.c
# 
# fs/compat_ioctl.c
#   2005/03/07 21:14:40-08:00 bunk@stusta.de +0 -63
#   remove drivers/char/tpqic02.c
# 
# drivers/char/Makefile
#   2005/03/07 20:41:20-08:00 bunk@stusta.de +0 -1
#   remove drivers/char/tpqic02.c
# 
# BitKeeper/deleted/.del-tpqic02.h~4f31c833bb939563
#   2005/03/08 09:23:44-08:00 bunk@stusta.de +0 -0
#   Delete: include/linux/tpqic02.h
# 
# BitKeeper/deleted/.del-tpqic02.c~650ff07523472d13
#   2005/03/08 09:23:44-08:00 bunk@stusta.de +0 -0
#   Delete: drivers/char/tpqic02.c
# 
# ChangeSet
#   2005/03/08 09:23:39-08:00 akpm@osdl.org 
#   [PATCH] x86_64 pte warning fix
#   
#   include/asm/pgtable.h:267: warning: `struct vm_area_struct' declared inside parameter list
#   include/asm/pgtable.h:267: warning: its scope is only this definition or declaration, which is probably not what you want
#   
#   Cc: Andi Kleen <ak@muc.de>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/asm-x86_64/pgtable.h
#   2005/03/07 20:41:20-08:00 akpm@osdl.org +2 -0
#   x86_64 pte warning fix
# 
# ChangeSet
#   2005/03/08 09:23:25-08:00 akpm@osdl.org 
#   [PATCH] ppc: raid6 build fix
#   
#   Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
#   Cc: Paul Mackerras <paulus@samba.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/md/raid6altivec.uc
#   2005/03/07 20:41:20-08:00 akpm@osdl.org +1 -1
#   ppc: raid6 build fix
# 
# ChangeSet
#   2005/03/08 09:23:11-08:00 galak@freescale.com 
#   [PATCH] ppc32: fix for e500 oprofile build
#   
#   Fix for trivial fix for 2.6.11 oprofile compilation on e500 based ppc.
#   
#   Signed-off-by: Andy Fleming <afleming@freescale.com>
#   Signed-off-by: Kumar Gala <kumar.gala@freescale.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/ppc/oprofile/op_model_fsl_booke.c
#   2005/03/07 20:41:19-08:00 galak@freescale.com +1 -2
#   ppc32: fix for e500 oprofile build
# 
# ChangeSet
#   2005/03/08 08:18:50-08:00 torvalds@ppc970.osdl.org 
#   epoll: return proper error on overflow condition
#   
#   Noted by Georgi Guninski.
# 
# fs/eventpoll.c
#   2005/03/08 08:18:40-08:00 torvalds@ppc970.osdl.org +2 -1
#   epoll: return proper error on overflow condition
#   
#   Noted by Georgi Guninski.
# 
# ChangeSet
#   2005/03/08 16:14:02+00:00 ben-linux@org.rmk.(none) 
#   [ARM PATCH] 2516/1: S3C2410 - add Acer n30
#   
#   Patch from Ben Dooks
#   
#   Add the Acer N30 machine, from Christer Weinigel
#   
#   Signed-off-by: Christer Weinigel
#   
#   Signed-off-by: Ben Dooks
#   Signed-off-by: Russell King
# 
# arch/arm/mach-s3c2410/Makefile
#   2005/03/06 15:03:11+00:00 ben-linux@org.rmk.(none) +1 -0
#   [PATCH] 2516/1: S3C2410 - add Acer n30
# 
# arch/arm/mach-s3c2410/Kconfig
#   2005/03/06 15:03:11+00:00 ben-linux@org.rmk.(none) +8 -0
#   [PATCH] 2516/1: S3C2410 - add Acer n30
# 
# arch/arm/configs/s3c2410_defconfig
#   2005/03/06 15:10:38+00:00 ben-linux@org.rmk.(none) +1 -0
#   [PATCH] 2516/1: S3C2410 - add Acer n30
# 
# Documentation/arm/Samsung-S3C24XX/Overview.txt
#   2005/03/06 15:07:31+00:00 ben-linux@org.rmk.(none) +6 -2
#   [PATCH] 2516/1: S3C2410 - add Acer n30
# 
# arch/arm/mach-s3c2410/mach-n30.c
#   2005/03/06 15:16:42+00:00 ben-linux@org.rmk.(none) +155 -0
#   [PATCH] 2516/1: S3C2410 - add Acer n30
# 
# arch/arm/mach-s3c2410/mach-n30.c
#   2005/03/06 15:16:42+00:00 ben-linux@org.rmk.(none) +0 -0
#   BitKeeper file /usr/src/bk/linux-2.6-rmk/arch/arm/mach-s3c2410/mach-n30.c
# 
# ChangeSet
#   2005/03/08 14:24:12+00:00 vandrove@cz.rmk.(none) 
#   [SERIAL] Fix 16550A misdetection
#   
#   Patch from Petr Vandrovec
#   
#   XScale detection needs access to Interrupt Enable Register on UART.
#   But this register shares position with high byte clock divisor, and
#   previous detection steps were leaving clock divisor and not IER
#   selected, causing misdetection of all 16550A chips as XScale.
#    
#   Fix this by disabling access to clock divisor at the end of previous
#   detection step, so chip is in same mode after each detection step.
#    
#   Signed-off-by: Petr Vandrovec
# 
# drivers/serial/8250.c
#   2005/03/08 10:04:55+00:00 vandrove@cz.rmk.(none) +1 -0
#   [PATCH] Fix 16550A misdetection
# 
# ChangeSet
#   2005/03/08 01:10:37-08:00 akpm@osdl.org 
#   [PATCH] USB: compat ioctl for submiting URB
#   
#   From: Christopher Li <chrisl@vmware.com>
#   
#   - Let usbdevfs directly handle 32 bit URB ioctl. More specifically:
#     USBDEVFS_SUBMITURB32, USBDEVFS_REAPURB32 and USBDEVFS_REAPURBNDELAY32.
#     Those asynchronous ioctls are too complicate to handle by the
#     compatible layer.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# include/linux/usbdevice_fs.h
#   2005/03/07 20:41:38-08:00 akpm@osdl.org +22 -1
#   USB: compat ioctl for submiting URB
# 
# include/linux/compat_ioctl.h
#   2005/03/07 20:41:38-08:00 akpm@osdl.org +3 -0
#   USB: compat ioctl for submiting URB
# 
# fs/compat_ioctl.c
#   2005/03/07 20:41:38-08:00 akpm@osdl.org +4 -225
#   USB: compat ioctl for submiting URB
# 
# drivers/usb/core/devio.c
#   2005/03/07 20:41:38-08:00 akpm@osdl.org +185 -66
#   USB: compat ioctl for submiting URB
# 
# ChangeSet
#   2005/03/08 01:05:49-08:00 gregkh@suse.de 
#   [PATCH] USB: fix up HZ change in zd1201 driver.
#   
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/net/zd1201.h
#   2005/03/07 20:41:29-08:00 gregkh@suse.de +2 -2
#   USB: fix up HZ change in zd1201 driver.
# 
# ChangeSet
#   2005/03/08 01:05:26-08:00 pe1rxq@amsat.org 
#   [PATCH] USB: add zd1201 wireless lan driver
#   
#   Signed-off-by: Jeroen Vreeken <pe1rxq@amsat.org>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/net/zd1201.h
#   2005/03/07 20:41:34-08:00 pe1rxq@amsat.org +147 -0
#   USB: add zd1201 wireless lan driver
# 
# drivers/usb/net/zd1201.c
#   2005/03/07 20:41:34-08:00 pe1rxq@amsat.org +1905 -0
#   USB: add zd1201 wireless lan driver
# 
# drivers/usb/net/zd1201.h
#   2005/03/07 20:41:34-08:00 pe1rxq@amsat.org +0 -0
#   BitKeeper file /home/greg/linux/BK/do/usb-2.6/drivers/usb/net/zd1201.h
# 
# drivers/usb/net/zd1201.c
#   2005/03/07 20:41:34-08:00 pe1rxq@amsat.org +0 -0
#   BitKeeper file /home/greg/linux/BK/do/usb-2.6/drivers/usb/net/zd1201.c
# 
# drivers/usb/net/Makefile
#   2005/03/07 20:41:34-08:00 pe1rxq@amsat.org +3 -0
#   USB: add zd1201 wireless lan driver
# 
# drivers/usb/net/Kconfig
#   2005/03/07 20:41:34-08:00 pe1rxq@amsat.org +17 -0
#   USB: add zd1201 wireless lan driver
# 
# MAINTAINERS
#   2005/03/07 20:41:34-08:00 pe1rxq@amsat.org +8 -0
#   USB: add zd1201 wireless lan driver
# 
# CREDITS
#   2005/03/07 20:41:34-08:00 pe1rxq@amsat.org +1 -0
#   USB: add zd1201 wireless lan driver
# 
# ChangeSet
#   2005/03/08 01:05:04-08:00 sean@mess.org 
#   [PATCH] USB: PhidgetKit driver update
#   
#   A small patch for drivers/usb/misc/phidgetkit.c:
#   
#   Fixes for PhidgetInterfaceKit 0/0/4, by Chris Strandt <chris@firetrim.com>
#   
#   Signed-off-by: Sean Young <sean@mess.org>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/misc/phidgetkit.c
#   2005/03/07 20:41:42-08:00 sean@mess.org +14 -9
#   USB: PhidgetKit driver update
# 
# ChangeSet
#   2005/03/08 01:04:42-08:00 alexn@dsv.su.se 
#   [PATCH] USB: Fix use after free in usb/core/devices.c
#   
#   There's a low probability use-after-free here caused by some switched
#   pointers, st needs to go back to file->private_data
#   
#   Found by Coverity tool
#   
#   Signed-off-by: Alexander Nyberg <alexn@dsv.su.se>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/core/devices.c
#   2005/03/07 20:41:46-08:00 alexn@dsv.su.se +1 -0
#   USB: Fix use after free in usb/core/devices.c
# 
# ChangeSet
#   2005/03/08 01:04:22-08:00 stern@rowland.harvard.edu 
#   [PATCH] USB Storage: Unusual_devs entry for Nikon DSC D70
#   
#   Here's a new unusual_devs.h entry for the Nikon DSC D70 camera, which
#   suffers the common problem of reporting one more sector than it actually
#   has.
#   
#   Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/storage/unusual_devs.h
#   2005/03/07 20:41:50-08:00 stern@rowland.harvard.edu +7 -0
#   USB Storage: Unusual_devs entry for Nikon DSC D70
# 
# ChangeSet
#   2005/03/08 01:04:01-08:00 nacc@us.ibm.com 
#   [PATCH] usb/ftdi_sio: convert WDR_TIMEOUT to milliseconds
#   
#   WDR_TIMEOUT was not updated with the the other constants related to
#   converting the final parameter of usb_{control,bulk}_msg() to
#   milliseconds.
#   
#   Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/serial/ftdi_sio.c
#   2005/03/07 20:41:54-08:00 nacc@us.ibm.com +1 -1
#   usb/ftdi_sio: convert WDR_TIMEOUT to milliseconds
# 
# ChangeSet
#   2005/03/08 01:03:39-08:00 nacc@us.ibm.com 
#   [PATCH] usb/usblp: convert USBLP_WRITE_TIMEOUT to milliseconds
#   
#   USBLP_WRITE_TIMEOUT was not updated with the the other constants related
#   to converting the final parameter of usb_{control,bulk}_msg() to
#   milliseconds.
#   
#   Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/class/usblp.c
#   2005/03/07 20:41:59-08:00 nacc@us.ibm.com +1 -1
#   usb/usblp: convert USBLP_WRITE_TIMEOUT to milliseconds
# 
# ChangeSet
#   2005/03/08 01:03:15-08:00 phil@ipom.com 
#   [PATCH] [PATCH] Add US_FL_GO_SLOW flag,
#   
#   This adds the US_FL_GO_SLOW flag. This flag is for devices that need a
#   110 usec delay during high-speed transfers. This seems to be limited to
#   USB-to-IDE chips. Unusual_dev entries for affected devices are included.
#   
#   This has been thrown around in the usb-storage list for a while now, and
#   I believe everyone is happy with it.
#   
#   Signed-off-by: Phil Dibowitz <phil@ipom.com>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/storage/usb.h
#   2005/03/07 20:42:03-08:00 phil@ipom.com +1 -0
#   [PATCH] Add US_FL_GO_SLOW flag,
# 
# drivers/usb/storage/usb.c
#   2005/03/07 20:42:03-08:00 phil@ipom.com +7 -0
#   [PATCH] Add US_FL_GO_SLOW flag,
# 
# drivers/usb/storage/unusual_devs.h
#   2005/03/07 20:42:03-08:00 phil@ipom.com +31 -5
#   [PATCH] Add US_FL_GO_SLOW flag,
# 
# drivers/usb/storage/transport.c
#   2005/03/07 20:42:03-08:00 phil@ipom.com +2 -2
#   [PATCH] Add US_FL_GO_SLOW flag,
# 
# ChangeSet
#   2005/03/08 01:02:53-08:00 david-b@pacbell.net 
#   [PATCH] USB: pxa2xx_udc tweak
#   
#   Add a missing local_irq_restore() on the SET_CONFIGURATION completion path.
#   
#   From: Eugeny S. Mints <emints@ru.mvista.com>
#   Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/gadget/pxa2xx_udc.c
#   2005/03/07 20:42:28-08:00 david-b@pacbell.net +1 -0
#   USB: pxa2xx_udc tweak
# 
# ChangeSet
#   2005/03/08 01:02:31-08:00 petkan@nucleusys.com 
#   [PATCH] USB: pegasus and rtl8150 cset for proper link detection
#   
#   changes mainly include adding work queue to both drivers
#   and a bunch of other small fixes.
#   
#   Signed-off-by: Petko Manolov <petkan@nucleusys.com>
# 
# drivers/usb/net/pegasus.h
#   2005/03/07 20:42:32-08:00 petkan@nucleusys.com +1 -0
#   USB: pegasus and rtl8150 cset for proper link detection
# 
# drivers/usb/net/pegasus.c
#   2005/03/07 20:42:32-08:00 petkan@nucleusys.com +45 -16
#   USB: pegasus and rtl8150 cset for proper link detection
# 
# ChangeSet
#   2005/03/08 01:02:09-08:00 stern@rowland.harvard.edu 
#   [PATCH] USB Documentation update: USB error codes
#   
#   This patch fixes a documentation error I made earlier and clears up the
#   meaning of the -ETIMEDOUT error code in urb->status.  Some host controller
#   drivers _do_ use that code to indicate no response was received from the
#   device, which can be confusing since the same code is also used when a
#   request's timer expires.  In the future it would be a good idea to change
#   the second usage (as returned by usb_bulk_msg and usb_control_msg) to
#   -ETIME.
#   
#   
#   Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# Documentation/usb/error-codes.txt
#   2005/03/07 20:42:36-08:00 stern@rowland.harvard.edu +17 -8
#   USB Documentation update: USB error codes
# 
# ChangeSet
#   2005/03/08 00:55:59-08:00 gregkh@suse.de 
#   [PATCH] USB: fix up compiler warnings when CONFIG_USB_DEBUG is not set.
#   
#   As pointed out by Kay Sievers <kay.sievers@vrfy.org>
#   
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/core/hub.c
#   2005/03/07 20:41:19-08:00 gregkh@suse.de +1 -1
#   USB: fix up compiler warnings when CONFIG_USB_DEBUG is not set.
# 
# ChangeSet
#   2005/03/08 00:55:39-08:00 gregkh@suse.de 
#   [PATCH] USB: fix memory leak in get_string if usb_string() call failed.
#   
#   Pointed out by Alan Stern <stern@rowland.harvard.edu>
#   
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/core/hub.c
#   2005/03/07 20:41:25-08:00 gregkh@suse.de +2 -0
#   USB: fix memory leak in get_string if usb_string() call failed.
# 
# ChangeSet
#   2005/03/08 00:55:16-08:00 gregkh@suse.de 
#   [PATCH] USB: cache the iConfiguration string, if present.
#   
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# include/linux/usb.h
#   2005/03/07 20:42:07-08:00 gregkh@suse.de +3 -0
#   USB: cache the iConfiguration string, if present.
# 
# drivers/usb/core/sysfs.c
#   2005/03/07 20:42:07-08:00 gregkh@suse.de +17 -20
#   USB: cache the iConfiguration string, if present.
# 
# drivers/usb/core/message.c
#   2005/03/07 20:42:07-08:00 gregkh@suse.de +7 -0
#   USB: cache the iConfiguration string, if present.
# 
# drivers/usb/core/config.c
#   2005/03/07 20:42:07-08:00 gregkh@suse.de +3 -0
#   USB: cache the iConfiguration string, if present.
# 
# ChangeSet
#   2005/03/08 00:54:56-08:00 gregkh@suse.de 
#   [PATCH] USB: make iInterface string cached
#   
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# include/linux/usb.h
#   2005/03/07 20:42:11-08:00 gregkh@suse.de +1 -0
#   USB: make iInterface string cached
# 
# drivers/usb/core/sysfs.c
#   2005/03/07 20:42:11-08:00 gregkh@suse.de +18 -21
#   USB: make iInterface string cached
# 
# drivers/usb/core/message.c
#   2005/03/07 20:42:11-08:00 gregkh@suse.de +9 -0
#   USB: make iInterface string cached
# 
# ChangeSet
#   2005/03/08 00:54:31-08:00 gregkh@suse.de 
#   [PATCH] USB: remove string fetches from the usb-storage core, have them used the cached versions instead.
#   
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/storage/usb.h
#   2005/03/07 20:42:15-08:00 gregkh@suse.de +0 -3
#   USB: remove string fetches from the usb-storage core, have them used the cached versions instead.
# 
# drivers/usb/storage/usb.c
#   2005/03/07 20:42:15-08:00 gregkh@suse.de +0 -31
#   USB: remove string fetches from the usb-storage core, have them used the cached versions instead.
# 
# drivers/usb/storage/scsiglue.c
#   2005/03/07 20:42:15-08:00 gregkh@suse.de +16 -3
#   USB: remove string fetches from the usb-storage core, have them used the cached versions instead.
# 
# ChangeSet
#   2005/03/08 00:54:10-08:00 gregkh@suse.de 
#   [PATCH] USB: fix up the input drivers to use the built in strings, instead of re-reading them from the device.
#   
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/input/usbmouse.c
#   2005/03/07 20:42:19-08:00 gregkh@suse.de +4 -15
#   USB: fix up the input drivers to use the built in strings, instead of re-reading them from the device.
# 
# drivers/usb/input/usbkbd.c
#   2005/03/07 20:42:19-08:00 gregkh@suse.de +4 -16
#   USB: fix up the input drivers to use the built in strings, instead of re-reading them from the device.
# 
# drivers/usb/input/touchkitusb.c
#   2005/03/07 20:42:19-08:00 gregkh@suse.de +4 -15
#   USB: fix up the input drivers to use the built in strings, instead of re-reading them from the device.
# 
# drivers/usb/input/mtouchusb.c
#   2005/03/07 20:42:19-08:00 gregkh@suse.de +4 -14
#   USB: fix up the input drivers to use the built in strings, instead of re-reading them from the device.
# 
# drivers/usb/input/hid-core.c
#   2005/03/07 20:42:19-08:00 gregkh@suse.de +6 -6
#   USB: fix up the input drivers to use the built in strings, instead of re-reading them from the device.
# 
# drivers/usb/input/ati_remote.c
#   2005/03/07 20:42:19-08:00 gregkh@suse.de +5 -14
#   USB: fix up the input drivers to use the built in strings, instead of re-reading them from the device.
# 
# drivers/usb/input/aiptek.c
#   2005/03/07 20:42:19-08:00 gregkh@suse.de +2 -17
#   USB: fix up the input drivers to use the built in strings, instead of re-reading them from the device.
# 
# ChangeSet
#   2005/03/08 00:53:47-08:00 gregkh@suse.de 
#   [PATCH] USB: cache the product, manufacturer, and serial number strings at device insertion.
#   
#   This should fix a lot of issues with broken devices that can't handle retrieving strings
#   while they are doing something else (strings would be fetched from usbfs and sysfs entries.)
#   
#   Based on a patch that has been in the SuSE kernel tree for a long time from Olaf Hering <olh@suse.de>
#   
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# include/linux/usb.h
#   2005/03/07 20:42:24-08:00 gregkh@suse.de +3 -0
#   USB: cache the product, manufacturer, and serial number strings at device insertion.
# 
# drivers/usb/core/usb.c
#   2005/03/07 20:42:24-08:00 gregkh@suse.de +4 -1
#   USB: cache the product, manufacturer, and serial number strings at device insertion.
# 
# drivers/usb/core/sysfs.c
#   2005/03/07 20:42:24-08:00 gregkh@suse.de +8 -8
#   USB: cache the product, manufacturer, and serial number strings at device insertion.
# 
# drivers/usb/core/hub.c
#   2005/03/07 20:42:24-08:00 gregkh@suse.de +24 -18
#   USB: cache the product, manufacturer, and serial number strings at device insertion.
# 
# drivers/usb/core/devices.c
#   2005/03/07 20:42:24-08:00 gregkh@suse.de +6 -18
#   USB: cache the product, manufacturer, and serial number strings at device insertion.
# 
# ChangeSet
#   2005/03/08 00:45:11-08:00 david-b@pacbell.net 
#   [PATCH] USB: fix ohci Kconfig entry
#   
#   The recently merged AMD/Alchemy Au1xxx OHCI driver won't configure
#   on boards which also have PCI support; this resolves that.
#   
#   Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/host/Kconfig
#   2005/03/07 20:42:45-08:00 david-b@pacbell.net +2 -0
#   USB: fix ohci Kconfig entry
# 
# ChangeSet
#   2005/03/08 00:44:49-08:00 stern@rowland.harvard.edu 
#   [PATCH] USB: Don't return IRQ_NONE for edge-triggered interrupts
#   
#   On Tue, 15 Feb 2005, Greg KH wrote:
#   > Thanks, I've applied all of them except as460 as there seemed to be
#   > confusion about that one.  Care to respin that one based on all of the
#   > comments given to it?
#   
#   It turns out that patch as460 is all right as it stands, and the addition
#   of the patch below will resolve the problem.  It prevents the OHCI drivers
#   from returning IRQ_NONE on architectures that use edge-triggered
#   interrupts.  The patch has been OK'ed by Christopher and David.  Just be
#   sure to apply this one and as460 at the same time!
#   
#   Properly speaking this problem ought to be fixed in the interrupt core
#   since it affects every driver, not just USB.  Until that happens, this
#   will suffice.
#   
#   
#   Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/host/ohci-hcd.c
#   2005/03/07 20:42:49-08:00 stern@rowland.harvard.edu +12 -1
#   USB: Don't return IRQ_NONE for edge-triggered interrupts
# 
# ChangeSet
#   2005/03/08 00:44:22-08:00 stern@rowland.harvard.edu 
#   [PATCH] USBcore: implement usb_add_hcd and usb_remove_hcd
#   
#   This patch contains the changes to the ohci-sa1111 driver to accomodate
#   the new usb_add_hcd, usb_remove_hcd routines.
#   
#   Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/host/ohci-sa1111.c
#   2005/03/07 20:42:53-08:00 stern@rowland.harvard.edu +21 -109
#   USBcore: implement usb_add_hcd and usb_remove_hcd
# 
# ChangeSet
#   2005/03/08 00:43:55-08:00 stern@rowland.harvard.edu 
#   [PATCH] USB: Fix race in URB submission vs. endpoint-disable
#   
#   This patch fixes a race between URB submission and endpoint-disable.  (I
#   don't know that it's actually possible to trigger the race, but it won't
#   hurt to move the appropriate test inside the region protected by the
#   spinlock.)  In addition, an out-of-date comment referring to timeouts is
#   removed.
#   
#   The patch also changes the error code returned when an URB is submitted
#   for a nonexistent or disabled endpoint to -ENOENT and documents the error
#   code (which was already in use by usbfs) in
#   Documentation/usb/error-codes.txt.
#   
#   Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/core/hcd.c
#   2005/03/07 20:42:57-08:00 stern@rowland.harvard.edu +6 -9
#   USB: Fix race in URB submission vs. endpoint-disable
# 
# Documentation/usb/error-codes.txt
#   2005/03/07 20:42:57-08:00 stern@rowland.harvard.edu +3 -0
#   USB: Fix race in URB submission vs. endpoint-disable
# 
# ChangeSet
#   2005/03/08 00:43:29-08:00 stern@rowland.harvard.edu 
#   [PATCH] USB: Clear endpoint toggles in usb_set_interface
#   
#   Pete Zaitcev has found some USB devices that don't reset their endpoint
#   data toggles when they get a SET-INTERFACE request.  Apparently they
#   interpret the USB specification too literally when it says that the
#   toggles must be reset whenever the alternate setting is "changed".
#   
#   Anyway, this patch calls usb_clear_halt for all endpoints in the
#   altsetting whenever usb_set_interface is called and the new altsetting is
#   the same as the old one.  It adds some extra overhead for the majority of
#   devices that don't need it, but fortunately usb_set_interface isn't called
#   very often.
#   
#   Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/core/message.c
#   2005/03/07 20:43:01-08:00 stern@rowland.harvard.edu +20 -1
#   USB: Clear endpoint toggles in usb_set_interface
# 
# ChangeSet
#   2005/03/08 00:43:04-08:00 stern@rowland.harvard.edu 
#   [PATCH] USBcore: implement usb_add_hcd and usb_remove_hcd
#   
#   This patch contains the changes to the ohci-au1xxx driver.
#   
#   Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/host/ohci-au1xxx.c
#   2005/03/07 20:43:05-08:00 stern@rowland.harvard.edu +29 -107
#   USBcore: implement usb_add_hcd and usb_remove_hcd
# 
# ChangeSet
#   2005/03/08 00:42:37-08:00 stern@rowland.harvard.edu 
#   [PATCH] USBcore: implement usb_add_hcd and usb_remove_hcd
#   
#   This patch contains the changes to the sl811-hcd driver.
#   
#   Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/host/sl811-hcd.c
#   2005/03/07 20:43:10-08:00 stern@rowland.harvard.edu +24 -49
#   USBcore: implement usb_add_hcd and usb_remove_hcd
# 
# ChangeSet
#   2005/03/08 00:42:13-08:00 stern@rowland.harvard.edu 
#   [PATCH] USBcore: implement usb_add_hcd and usb_remove_hcd
#   
#   This patch contains the changes to the ohci-pxa27x driver.
#   
#   Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/host/ohci-pxa27x.c
#   2005/03/07 20:43:14-08:00 stern@rowland.harvard.edu +33 -94
#   USBcore: implement usb_add_hcd and usb_remove_hcd
# 
# ChangeSet
#   2005/03/08 00:41:46-08:00 stern@rowland.harvard.edu 
#   [PATCH] USBcore: implement usb_add_hcd and usb_remove_hcd
#   
#   This patch contains the changes to the ohci-ppc-soc driver.
#   
#   Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/host/ohci-ppc-soc.c
#   2005/03/07 20:43:18-08:00 stern@rowland.harvard.edu +29 -94
#   USBcore: implement usb_add_hcd and usb_remove_hcd
# 
# ChangeSet
#   2005/03/08 00:41:20-08:00 stern@rowland.harvard.edu 
#   [PATCH] USBcore: implement usb_add_hcd and usb_remove_hcd
#   
#   This patch contains the changes to the ohci-omap driver.
#   
#   Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/host/ohci-omap.c
#   2005/03/07 20:43:22-08:00 stern@rowland.harvard.edu +23 -76
#   USBcore: implement usb_add_hcd and usb_remove_hcd
# 
# ChangeSet
#   2005/03/08 00:40:59-08:00 stern@rowland.harvard.edu 
#   [PATCH] USBcore: implement usb_add_hcd and usb_remove_hcd
#   
#   This patch contains the changes for the ohci-lh7a404 driver.
#   
#   Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/host/ohci-lh7a404.c
#   2005/03/07 20:43:26-08:00 stern@rowland.harvard.edu +30 -108
#   USBcore: implement usb_add_hcd and usb_remove_hcd
# 
# ChangeSet
#   2005/03/08 00:40:34-08:00 stern@rowland.harvard.edu 
#   [PATCH] USBcore: implement usb_add_hcd and usb_remove_hcd
#   
#   This patch contains the changes for the dummy-hcd driver.
#   
#   Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/gadget/dummy_hcd.c
#   2005/03/07 20:43:30-08:00 stern@rowland.harvard.edu +19 -62
#   USBcore: implement usb_add_hcd and usb_remove_hcd
# 
# ChangeSet
#   2005/03/08 00:40:13-08:00 stern@rowland.harvard.edu 
#   [PATCH] USBcore: implement usb_add_hcd and usb_remove_hcd
#   
#   This patch contains the changes for the core hcd-pci file and the uhci-hcd
#   driver.
#   
#   Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/host/uhci-hcd.c
#   2005/03/07 20:43:34-08:00 stern@rowland.harvard.edu +2 -2
#   USBcore: implement usb_add_hcd and usb_remove_hcd
# 
# drivers/usb/core/hcd-pci.c
#   2005/03/07 20:43:34-08:00 stern@rowland.harvard.edu +45 -114
#   USBcore: implement usb_add_hcd and usb_remove_hcd
# 
# ChangeSet
#   2005/03/08 00:39:47-08:00 stern@rowland.harvard.edu 
#   [PATCH] USBcore: implement usb_add_hcd and usb_remove_hcd
#   
#   This patch contains the changes to the hcd glue layer in usbcore.  It is a
#   prerequisite for all the other patches (which are all otherwise
#   independent).
#   
#   Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/core/hcd.h
#   2005/03/07 20:43:39-08:00 stern@rowland.harvard.edu +8 -6
#   USBcore: implement usb_add_hcd and usb_remove_hcd
# 
# drivers/usb/core/hcd.c
#   2005/03/07 20:43:39-08:00 stern@rowland.harvard.edu +121 -8
#   USBcore: implement usb_add_hcd and usb_remove_hcd
# 
# ChangeSet
#   2005/03/08 00:39:20-08:00 brian@murphy.dk 
#   [PATCH] USB: usbfs: remove debug message
#   
#   	this removes a warning message which only contains
#   data which is in any case returned to user space. This message
#   is especially annoying when polling with short timeouts, filling
#   up the log files and polluting the console. As agreed with
#   David Brownell.
#   
#   
#   Signed-off-by: Brian Murphy <brian@murphy.dk>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/core/devio.c
#   2005/03/07 20:43:43-08:00 brian@murphy.dk +1 -4
#   USB: usbfs: remove debug message
# 
# ChangeSet
#   2005/03/08 00:38:55-08:00 brian@murphy.dk 
#   [PATCH] USB: set timeout message to debug level: message.c
#   
#   	this makes a the debug message on timeout be at debug level
#   so it only exists when compiling with explicit debugging support.
#   I have added information about the request length and data length
#   as now if the data length is non-zero a 0 status is returned.
#   
#   Signed-off-by: Brian Murphy <brian@murphy.dk>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/core/message.c
#   2005/03/07 20:43:47-08:00 brian@murphy.dk +6 -3
#   USB: set timeout message to debug level: message.c
# 
# ChangeSet
#   2005/03/08 00:38:29-08:00 brian@murphy.dk 
#   [PATCH] USB: usbfs fix for data loss in message.c
#   
#   	This is my fix for usbfs losing data when the urb
#   is timed out but already contains data.
#   
#   Signed-off-by: Brian Murphy <brian@murphy.dk>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/core/message.c
#   2005/03/07 20:43:51-08:00 brian@murphy.dk +4 -1
#   USB: usbfs fix for data loss in message.c
# 
# ChangeSet
#   2005/03/08 00:38:00-08:00 hwelte@hmw-consulting.de 
#   [PATCH] [PATCH 2.6] maintainers / documentation update cyberjack
#   
#   Here's a pure documentation update for the cyberjack driver.
#   
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/serial/cyberjack.c
#   2005/03/07 20:43:55-08:00 hwelte@hmw-consulting.de +6 -1
#   [PATCH 2.6] maintainers / documentation update cyberjack
# 
# MAINTAINERS
#   2005/03/07 20:43:55-08:00 hwelte@hmw-consulting.de +6 -0
#   [PATCH 2.6] maintainers / documentation update cyberjack
# 
# ChangeSet
#   2005/03/08 00:37:33-08:00 stern@rowland.harvard.edu 
#   [PATCH] usb-storage: Don't log expected signatures
#   
#   This fairly trivial patch makes three small changes:
#   
#   	Correct a typo in a comment.
#   
#   	Don't print a debugging message when a USB mass-storage device
#   	uses the standard signature (the one we would expect normally).
#   
#   	Shorten a debugging message and add a newline.
#   
#   
#   Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/storage/transport.h
#   2005/03/07 20:44:00-08:00 stern@rowland.harvard.edu +1 -0
#   usb-storage: Don't log expected signatures
# 
# drivers/usb/storage/transport.c
#   2005/03/07 20:44:00-08:00 stern@rowland.harvard.edu +4 -3
#   usb-storage: Don't log expected signatures
# 
# drivers/usb/storage/scsiglue.c
#   2005/03/07 20:44:00-08:00 stern@rowland.harvard.edu +1 -1
#   usb-storage: Don't log expected signatures
# 
# ChangeSet
#   2005/03/08 00:37:10-08:00 050035w@acadiau.ca 
#   [PATCH] USB: fix error in usb_skel.c
#   
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/usb-skeleton.c
#   2005/03/07 20:44:04-08:00 050035w@acadiau.ca +1 -1
#   USB: fix error in usb_skel.c
# 
# ChangeSet
#   2005/03/08 00:36:42-08:00 david-b@pacbell.net 
#   [PATCH] USB: usbnet uses NET_IP_ALIGN
#   
#   Go back to aligning RX packets to make the IP layer happy, now that
#   there's an appropriately platform-specific way to do this.  This should
#   be only a performance tweak.  However, the alignment handlers on some
#   platforms don't seem to behave; so it may have correctness impacts too.
#   
#   Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/net/usbnet.c
#   2005/03/07 20:44:08-08:00 david-b@pacbell.net +2 -1
#   USB: usbnet uses NET_IP_ALIGN
# 
# ChangeSet
#   2005/03/08 00:36:16-08:00 david-b@pacbell.net 
#   [PATCH] USB: teach gadget drivers about s3c2410_udc
#   
#   This patch makes gadget drivers recognize the UDC controller in
#   the Samsung s3c2310 (ARMv4T).  This is used in the iPaq H1940,
#   partially supported by Linux, as well as various other devices.
#   A controller driver is available, though it's not yet submitted.
#   
#   Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/gadget/zero.c
#   2005/03/07 20:44:12-08:00 david-b@pacbell.net +2 -0
#   USB: teach gadget drivers about s3c2410_udc
# 
# drivers/usb/gadget/serial.c
#   2005/03/07 20:44:12-08:00 david-b@pacbell.net +3 -0
#   USB: teach gadget drivers about s3c2410_udc
# 
# drivers/usb/gadget/gadget_chips.h
#   2005/03/07 20:44:12-08:00 david-b@pacbell.net +6 -0
#   USB: teach gadget drivers about s3c2410_udc
# 
# drivers/usb/gadget/ether.c
#   2005/03/07 20:44:12-08:00 david-b@pacbell.net +5 -0
#   USB: teach gadget drivers about s3c2410_udc
# 
# ChangeSet
#   2005/03/08 00:35:50-08:00 david-b@pacbell.net 
#   [PATCH] USB: ehci updates for TDI/ATG silicon
#   
#   This patch updates support for the TDI EHCI controller, which is mostly
#   used on non-PCI systems:
#   
#       - Correctly initialize the latest chip, which has both host (EHCI)
#         and peripheral modes.
#   
#       - Initialize split isochronous transfers to use the integrated TT.
#   
#   Most of the patch, by volume, just changes the company name from ARC to TDI in
#   the source code; TransDimension bought ARC's peripheral connectivity business.
#   
#   From: Craig Nadler <cnadler@transdimension.com>
#   Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# include/linux/pci_ids.h
#   2005/03/07 20:44:17-08:00 david-b@pacbell.net +2 -2
#   USB: ehci updates for TDI/ATG silicon
# 
# drivers/usb/host/ehci.h
#   2005/03/07 20:44:17-08:00 david-b@pacbell.net +4 -4
#   USB: ehci updates for TDI/ATG silicon
# 
# drivers/usb/host/ehci-sched.c
#   2005/03/07 20:44:16-08:00 david-b@pacbell.net +6 -2
#   USB: ehci updates for TDI/ATG silicon
# 
# drivers/usb/host/ehci-q.c
#   2005/03/07 20:44:16-08:00 david-b@pacbell.net +3 -3
#   USB: ehci updates for TDI/ATG silicon
# 
# drivers/usb/host/ehci-hub.c
#   2005/03/07 20:44:17-08:00 david-b@pacbell.net +2 -2
#   USB: ehci updates for TDI/ATG silicon
# 
# drivers/usb/host/ehci-hcd.c
#   2005/03/07 20:44:17-08:00 david-b@pacbell.net +38 -15
#   USB: ehci updates for TDI/ATG silicon
# 
# drivers/usb/host/Kconfig
#   2005/03/07 20:44:17-08:00 david-b@pacbell.net +1 -1
#   USB: ehci updates for TDI/ATG silicon
# 
# ChangeSet
#   2005/03/08 00:35:22-08:00 david-b@pacbell.net 
#   [PATCH] USB: ethernet gadget driver aligns IP headers
#   
#   Align incoming Ethernet packets so the header after Ethernet starts on
#   something closer to a cacheline boundary.  This normally just tweaks
#   performance for the IP layer.  But on one board (a no-MMU ARM9TDMI with
#   no hardware support for alignment fixups) it's needed to prevent the
#   IP checksumming code from failing.
#   
#   From: Thomas Brinker <thomas.brinker@gmx.de>
#   Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/gadget/ether.c
#   2005/03/07 20:44:21-08:00 david-b@pacbell.net +7 -1
#   USB: ethernet gadget driver aligns IP headers
# 
# ChangeSet
#   2005/03/08 00:28:41-08:00 nacc@us.ibm.com 
#   [PATCH] dvb/ttusb_dec: change parameters of usb_{control,bulk}_msg() to msecs
#   
#   Change units of parameters being passed to usb_{control,bulk}_msg() to
#   milliseconds. Patch is compile-tested.
#   
#   Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/media/dvb/ttusb-dec/ttusb_dec.c
#   2005/03/07 20:44:25-08:00 nacc@us.ibm.com +4 -4
#   dvb/ttusb_dec: change parameters of usb_{control,bulk}_msg() to msecs
# 
# ChangeSet
#   2005/03/08 00:28:14-08:00 nacc@us.ibm.com 
#   [PATCH] dvb/dvb-ttusb-budget: change parameters of usb_{control,bulk}_msg() to msecs
#   
#   Change units of parameters being passed to usb_{control,bulk}_msg() to
#   milliseconds. Patch is compile-tested.
#   
#   Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c
#   2005/03/07 20:44:29-08:00 nacc@us.ibm.com +2 -2
#   dvb/dvb-ttusb-budget: change parameters of usb_{control,bulk}_msg() to msecs
# 
# ChangeSet
#   2005/03/08 00:27:47-08:00 nacc@us.ibm.com 
#   [PATCH] dvb/dvb-dibusb: change parameters of usb_{control,bulk}_msg() to msecs
#   
#   Change units of parameters being passed to usb_{control,bulk}_msg() to
#   milliseconds. This constant is only used for these functions. Patch is
#   compile-tested.
#   
#   Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/media/dvb/dibusb/dvb-dibusb.h
#   2005/03/07 20:44:33-08:00 nacc@us.ibm.com +1 -1
#   dvb/dvb-dibusb: change parameters of usb_{control,bulk}_msg() to msecs
# 
# ChangeSet
#   2005/03/08 00:27:22-08:00 nacc@us.ibm.com 
#   [PATCH] dvb/cinergyT2: change parameters of usb_{control,bulk}_msg() to msecs
#   
#   Change units of parameters being passed to usb_{control,bulk}_msg() to
#   milliseconds. Patch is compile-tested.
#   
#   Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/media/dvb/cinergyT2/cinergyT2.c
#   2005/03/07 20:44:38-08:00 nacc@us.ibm.com +2 -2
#   dvb/cinergyT2: change parameters of usb_{control,bulk}_msg() to msecs
# 
# ChangeSet
#   2005/03/08 00:26:55-08:00 nacc@us.ibm.com 
#   [PATCH] video/cpia_usb: change parameters of usb_{control,bulk}_msg() to msecs
#   
#   Change units of parameters being passed to usb_{control,bulk}_msg() to
#   milliseconds. Patch is compile-tested.
#   
#   Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/media/video/cpia_usb.c
#   2005/03/07 20:44:42-08:00 nacc@us.ibm.com +2 -2
#   video/cpia_usb: change parameters of usb_{control,bulk}_msg() to msecs
# 
# ChangeSet
#   2005/03/08 00:26:29-08:00 nacc@us.ibm.com 
#   [PATCH] dvb/dvb-dibusb-firmware: change parameters of usb_{control,bulk}_msg() to msecs
#   
#   Change units of parameters being passed to usb_{control,bulk}_msg() to
#   milliseconds. Patch is compile-tested.
#   
#   Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/media/dvb/dibusb/dvb-dibusb-firmware.c
#   2005/03/07 20:44:46-08:00 nacc@us.ibm.com +1 -1
#   dvb/dvb-dibusb-firmware: change parameters of usb_{control,bulk}_msg() to msecs
# 
# ChangeSet
#   2005/03/08 00:26:02-08:00 nacc@us.ibm.com 
#   [PATCH] dvb/b2c2-usb-core: change parameters of usb_{control,bulk}_msg() to msecs
#   
#   Change units of parameters being passed to usb_{control,bulk}_msg() to
#   milliseconds. Patch is compile-tested.
#   
#   Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/media/dvb/b2c2/b2c2-usb-core.c
#   2005/03/07 20:44:50-08:00 nacc@us.ibm.com +5 -5
#   dvb/b2c2-usb-core: change parameters of usb_{control,bulk}_msg() to msecs
# 
# ChangeSet
#   2005/03/08 00:25:38-08:00 nacc@us.ibm.com 
#   [PATCH] sound/usX2Yhwdep: change parameters of usb_{control,bulk}_msg() to msecs
#   
#   Change units of parameters being passed to usb_{control,bulk}_msg() to
#   milliseconds. Patch is compile-tested.
#   
#   Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# sound/usb/usx2y/usX2Yhwdep.c
#   2005/03/07 20:44:55-08:00 nacc@us.ibm.com +1 -1
#   sound/usX2Yhwdep: change parameters of usb_{control,bulk}_msg() to msecs
# 
# ChangeSet
#   2005/03/08 00:25:11-08:00 nacc@us.ibm.com 
#   [PATCH] sound/usbmixer: change parameters of usb_{control,bulk}_msg() to msecs
#   
#   Change units of parameters being passed to usb_{control,bulk}_msg() to
#   milliseconds. Patch is compile-tested.
#   
#   Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# sound/usb/usbmixer.c
#   2005/03/07 20:44:59-08:00 nacc@us.ibm.com +2 -2
#   sound/usbmixer: change parameters of usb_{control,bulk}_msg() to msecs
# 
# ChangeSet
#   2005/03/08 00:24:43-08:00 nacc@us.ibm.com 
#   [PATCH] w1/dscore: change parameters of usb_{control,bulk}_msg() to msecs
#   
#   Change units of parameters being passed to usb_{control,bulk}_msg() to
#   milliseconds. Patch is compile-tested.
#   
#   Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/w1/dscore.c
#   2005/03/07 20:45:03-08:00 nacc@us.ibm.com +5 -5
#   w1/dscore: change parameters of usb_{control,bulk}_msg() to msecs
# 
# ChangeSet
#   2005/03/08 00:24:17-08:00 nacc@us.ibm.com 
#   [PATCH] net/stir4200: change parameters of usb_{control,bulk}_msg() to msecs
#   
#   Change units of parameters being passed to usb_{control,bulk}_msg() to
#   milliseconds. Patch is compile-tested.
#   
#   Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/net/irda/stir4200.c
#   2005/03/07 20:45:07-08:00 nacc@us.ibm.com +3 -3
#   net/stir4200: change parameters of usb_{control,bulk}_msg() to msecs
# 
# ChangeSet
#   2005/03/08 00:23:52-08:00 nacc@us.ibm.com 
#   [PATCH] net/irda-usb: change parameters of usb_{control,bulk}_msg() to msecs
#   
#   Change units of parameters being passed to usb_{control,bulk}_msg() to
#   milliseconds. Patch is compile-tested.
#   
#   Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/net/irda/irda-usb.c
#   2005/03/07 20:45:11-08:00 nacc@us.ibm.com +1 -1
#   net/irda-usb: change parameters of usb_{control,bulk}_msg() to msecs
# 
# ChangeSet
#   2005/03/08 00:23:26-08:00 nacc@us.ibm.com 
#   [PATCH] char/pcwd_usb: change parameters of usb_{control,bulk}_msg() to msecs
#   
#   Change units of parameters being passed to usb_{control,bulk}_msg() to
#   milliseconds. Patch is compile-tested.
#   
#   Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/char/watchdog/pcwd_usb.c
#   2005/03/07 20:45:15-08:00 nacc@us.ibm.com +1 -1
#   char/pcwd_usb: change parameters of usb_{control,bulk}_msg() to msecs
# 
# ChangeSet
#   2005/03/08 00:23:00-08:00 nacc@us.ibm.com 
#   [PATCH] bluetooth/bfusb: change parameters of usb_{control,bulk}_msg() to msecs
#   
#   Change units of parameters being passed to usb_{control,bulk}_msg() to
#   milliseconds. Patch is compile-tested.
#   
#   Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
#   Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/bluetooth/bfusb.c
#   2005/03/07 20:45:20-08:00 nacc@us.ibm.com +4 -4
#   bluetooth/bfusb: change parameters of usb_{control,bulk}_msg() to msecs
# 
# ChangeSet
#   2005/03/08 00:22:34-08:00 nacc@us.ibm.com 
#   [PATCH] usb/usb-skeleton: change parameters of usb_{control,bulk}_msg() to msecs
#   
#   Change units of parameters being passed to usb_{control,bulk}_msg() to
#   milliseconds. Patch is compile-tested.
#   
#   Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/usb-skeleton.c
#   2005/03/07 20:45:24-08:00 nacc@us.ibm.com +1 -1
#   usb/usb-skeleton: change parameters of usb_{control,bulk}_msg() to msecs
# 
# ChangeSet
#   2005/03/08 00:22:07-08:00 nacc@us.ibm.com 
#   [PATCH] usb/whiteheat: change parameters of usb_{control,bulk}_msg() to msecs
#   
#   Change units of parameters being passed to usb_{control,bulk}_msg() to
#   milliseconds. Patch is compile-tested.
#   
#   Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/serial/whiteheat.c
#   2005/03/07 20:45:28-08:00 nacc@us.ibm.com +3 -2
#   usb/whiteheat: change parameters of usb_{control,bulk}_msg() to msecs
# 
# ChangeSet
#   2005/03/08 00:21:41-08:00 nacc@us.ibm.com 
#   [PATCH] usb/rio500: change parameters of usb_{control,bulk}_msg() to msecs
#   
#   Change units of parameters being passed to usb_{control,bulk}_msg() to
#   milliseconds. Patch is compile-tested.
#   
#   Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/misc/rio500.c
#   2005/03/07 20:45:32-08:00 nacc@us.ibm.com +4 -4
#   usb/rio500: change parameters of usb_{control,bulk}_msg() to msecs
# 
# ChangeSet
#   2005/03/08 00:21:14-08:00 nacc@us.ibm.com 
#   [PATCH] usb/visor: change parameters of usb_{control,bulk}_msg() to msecs
#   
#   Change units of parameters being passed to usb_{control,bulk}_msg() to
#   milliseconds. Patch is compile-tested.
#   
#   Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/serial/visor.c
#   2005/03/07 20:45:36-08:00 nacc@us.ibm.com +2 -2
#   usb/visor: change parameters of usb_{control,bulk}_msg() to msecs
# 
# ChangeSet
#   2005/03/08 00:20:48-08:00 nacc@us.ibm.com 
#   [PATCH] usb/ti_usb_3410_5052: change parameters of usb_{control,bulk}_msg() to msecs
#   
#   Change units of parameters being passed to usb_{control,bulk}_msg() to
#   milliseconds. Patch is compile-tested.
#   
#   Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/serial/ti_usb_3410_5052.c
#   2005/03/07 20:45:40-08:00 nacc@us.ibm.com +3 -3
#   usb/ti_usb_3410_5052: change parameters of usb_{control,bulk}_msg() to msecs
# 
# ChangeSet
#   2005/03/08 00:20:21-08:00 nacc@us.ibm.com 
#   [PATCH] usb/mct_u232: change parameters of usb_{control,bulk}_msg() to msecs
#   
#   Change units of parameters being passed to usb_{control,bulk}_msg() to
#   milliseconds. Patch is compile-tested.
#   
#   Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/serial/mct_u232.c
#   2005/03/07 20:45:44-08:00 nacc@us.ibm.com +1 -1
#   usb/mct_u232: change parameters of usb_{control,bulk}_msg() to msecs
# 
# ChangeSet
#   2005/03/08 00:19:54-08:00 nacc@us.ibm.com 
#   [PATCH] usb/kl5kusb105: change parameters of usb_{control,bulk}_msg() to msecs
#   
#   Change units of parameters being passed to usb_{control,bulk}_msg() to
#   milliseconds. Patch is compile-tested.
#   
#   Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/serial/kl5kusb105.c
#   2005/03/07 20:45:49-08:00 nacc@us.ibm.com +1 -1
#   usb/kl5kusb105: change parameters of usb_{control,bulk}_msg() to msecs
# 
# ChangeSet
#   2005/03/08 00:19:28-08:00 nacc@us.ibm.com 
#   [PATCH] usb/keyspan_pda: change parameters of usb_{control,bulk}_msg() to msecs
#   
#   Change units of parameters being passed to usb_{control,bulk}_msg() to
#   milliseconds. Patch is compile-tested.
#   
#   Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/serial/keyspan_pda.c
#   2005/03/07 20:45:53-08:00 nacc@us.ibm.com +7 -7
#   usb/keyspan_pda: change parameters of usb_{control,bulk}_msg() to msecs
# 
# ChangeSet
#   2005/03/08 00:19:01-08:00 nacc@us.ibm.com 
#   [PATCH] usb/ir-usb: change parameters of usb_{control,bulk}_msg() to msecs
#   
#   Change units of parameters being passed to usb_{control,bulk}_msg() to
#   milliseconds. Patch is compile-tested.
#   
#   Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/serial/ir-usb.c
#   2005/03/07 20:45:57-08:00 nacc@us.ibm.com +1 -1
#   usb/ir-usb: change parameters of usb_{control,bulk}_msg() to msecs
# 
# ChangeSet
#   2005/03/08 00:18:33-08:00 nacc@us.ibm.com 
#   [PATCH] usb/ipw: change parameters of usb_{control,bulk}_msg() to msecs
#   
#   Change units of parameters being passed to usb_{control,bulk}_msg() to
#   milliseconds. Patch is compile-tested.
#   
#   Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/serial/ipw.c
#   2005/03/07 20:46:01-08:00 nacc@us.ibm.com +9 -9
#   usb/ipw: change parameters of usb_{control,bulk}_msg() to msecs
# 
# ChangeSet
#   2005/03/08 00:18:07-08:00 nacc@us.ibm.com 
#   [PATCH] usb/ipaq: change parameters of usb_{control,bulk}_msg() to msecs
#   
#   Change units of parameters being passed to usb_{control,bulk}_msg() to
#   milliseconds. Patch is compile-tested.
#   
#   Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/serial/ipaq.c
#   2005/03/07 20:46:05-08:00 nacc@us.ibm.com +1 -1
#   usb/ipaq: change parameters of usb_{control,bulk}_msg() to msecs
# 
# ChangeSet
#   2005/03/08 00:17:40-08:00 nacc@us.ibm.com 
#   [PATCH] usb/io_ti: change parameters of usb_{control,bulk}_msg() to msecs
#   
#   Change units of parameters being passed to usb_{control,bulk}_msg() to
#   milliseconds. Patch is compile-tested.
#   
#   Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/serial/io_ti.c
#   2005/03/07 20:46:09-08:00 nacc@us.ibm.com +3 -4
#   usb/io_ti: change parameters of usb_{control,bulk}_msg() to msecs
# 
# ChangeSet
#   2005/03/08 00:17:13-08:00 nacc@us.ibm.com 
#   [PATCH] usb/ezusb: change parameters of usb_{control,bulk}_msg() to msecs
#   
#   Change units of parameters being passed to usb_{control,bulk}_msg() to
#   milliseconds. Patch is compile-tested.
#   
#   Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/serial/ezusb.c
#   2005/03/07 20:46:13-08:00 nacc@us.ibm.com +1 -1
#   usb/ezusb: change parameters of usb_{control,bulk}_msg() to msecs
# 
# ChangeSet
#   2005/03/08 00:16:49-08:00 nacc@us.ibm.com 
#   [PATCH] usb/belkin_sa: change parameters of usb_{control,bulk}_msg() to msecs
#   
#   Change units of parameters being passed to usb_{control,bulk}_msg() to
#   milliseconds. Patch is compile-tested.
#   
#   Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/serial/belkin_sa.c
#   2005/03/07 20:46:18-08:00 nacc@us.ibm.com +1 -1
#   usb/belkin_sa: change parameters of usb_{control,bulk}_msg() to msecs
# 
# ChangeSet
#   2005/03/08 00:16:23-08:00 nacc@us.ibm.com 
#   [PATCH] usb/usbnet: change parameters of usb_{control,bulk}_msg() to msecs
#   
#   Change units of parameters being passed to usb_{control,bulk}_msg() to
#   milliseconds. Remove unused jiffy-unit constant. Patch is
#   compile-tested.
#   
#   Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/net/usbnet.c
#   2005/03/07 20:46:22-08:00 nacc@us.ibm.com +7 -8
#   usb/usbnet: change parameters of usb_{control,bulk}_msg() to msecs
# 
# ChangeSet
#   2005/03/08 00:15:59-08:00 nacc@us.ibm.com 
#   [PATCH] usb/rtl8150: change parameters of usb_{control,bulk}_msg() to msecs
#   
#   Change units of parameters being passed to usb_{control,bulk}_msg() to
#   milliseconds. Patch is compile-tested.
#   
#   Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/net/rtl8150.c
#   2005/03/07 20:46:26-08:00 nacc@us.ibm.com +2 -2
#   usb/rtl8150: change parameters of usb_{control,bulk}_msg() to msecs
# 
# ChangeSet
#   2005/03/08 00:15:32-08:00 nacc@us.ibm.com 
#   [PATCH] usb/catc: change parameters of usb_{control,bulk}_msg() to msecs
#   
#   Change units of parameters being passed to usb_{control,bulk}_msg() to
#   milliseconds. Patch is compile-tested.
#   
#   Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/net/catc.c
#   2005/03/07 20:46:30-08:00 nacc@us.ibm.com +1 -1
#   usb/catc: change parameters of usb_{control,bulk}_msg() to msecs
# 
# ChangeSet
#   2005/03/08 00:15:09-08:00 nacc@us.ibm.com 
#   [PATCH] usb/uss720: change parameters of usb_{control,bulk}_msg() to msecs
#   
#   Change units of parameters being passed to usb_{control,bulk}_msg() to
#   milliseconds. Patch is compile-tested.
#   
#   Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/misc/uss720.c
#   2005/03/07 20:46:35-08:00 nacc@us.ibm.com +6 -6
#   usb/uss720: change parameters of usb_{control,bulk}_msg() to msecs
# 
# ChangeSet
#   2005/03/08 00:14:43-08:00 nacc@us.ibm.com 
#   [PATCH] usb/usbled: change parameters of usb_{control,bulk}_msg() to msecs
#   
#   Change units of parameters being passed to usb_{control,bulk}_msg() to
#   milliseconds. Patch is compile-tested.
#   
#   Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/misc/usbled.c
#   2005/03/07 20:46:39-08:00 nacc@us.ibm.com +1 -1
#   usb/usbled: change parameters of usb_{control,bulk}_msg() to msecs
# 
# ChangeSet
#   2005/03/08 00:14:16-08:00 nacc@us.ibm.com 
#   [PATCH] usb/phidgetservo: change parameters of usb_{control,bulk}_msg() to msecs
#   
#   Change units of parameters being passed to usb_{control,bulk}_msg() to
#   milliseconds. Patch is compile-tested.
#   
#   Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/misc/phidgetservo.c
#   2005/03/07 20:46:43-08:00 nacc@us.ibm.com +2 -2
#   usb/phidgetservo: change parameters of usb_{control,bulk}_msg() to msecs
# 
# ChangeSet
#   2005/03/08 00:13:49-08:00 nacc@us.ibm.com 
#   [PATCH] usb/phidgetkit: change parameters of usb_{control,bulk}_msg() to msecs
#   
#   Change units of parameters being passed to usb_{control,bulk}_msg() to
#   milliseconds. Patch is compile-tested.
#   
#   Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/misc/phidgetkit.c
#   2005/03/07 20:46:47-08:00 nacc@us.ibm.com +3 -3
#   usb/phidgetkit: change parameters of usb_{control,bulk}_msg() to msecs
# 
# ChangeSet
#   2005/03/08 00:13:24-08:00 nacc@us.ibm.com 
#   [PATCH] usb/legousbtower: change parameters of usb_{control,bulk}_msg() to msecs
#   
#   Change units of parameters being passed to usb_{control,bulk}_msg() to
#   milliseconds. Patch is compile-tested.
#   
#   Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/misc/legousbtower.c
#   2005/03/07 20:46:51-08:00 nacc@us.ibm.com +2 -2
#   usb/legousbtower: change parameters of usb_{control,bulk}_msg() to msecs
# 
# ChangeSet
#   2005/03/08 00:12:56-08:00 nacc@us.ibm.com 
#   [PATCH] usb/idmouse: change parameters of usb_{control,bulk}_msg() to msecs
#   
#   Change units of parameters being passed to usb_{control,bulk}_msg() to
#   milliseconds. Patch is compile-tested.
#   
#   Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/misc/idmouse.c
#   2005/03/07 20:46:55-08:00 nacc@us.ibm.com +8 -8
#   usb/idmouse: change parameters of usb_{control,bulk}_msg() to msecs
# 
# ChangeSet
#   2005/03/08 00:12:32-08:00 nacc@us.ibm.com 
#   [PATCH] usb/w9968cf: change parameters of usb_{control,bulk}_msg() to msecs
#   
#   Change units of parameters being passed to usb_{control,bulk}_msg() to
#   milliseconds. Patch is compile-tested.
#   
#   Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/media/w9968cf.h
#   2005/03/07 20:46:59-08:00 nacc@us.ibm.com +1 -1
#   usb/w9968cf: change parameters of usb_{control,bulk}_msg() to msecs
# 
# ChangeSet
#   2005/03/08 00:12:05-08:00 nacc@us.ibm.com 
#   [PATCH] usb/auerswald: change parameters of usb_{control,bulk}_msg() to msecs
#   
#   Change units of parameters being passed to usb_{control,bulk}_msg() to
#   milliseconds. Patch is compile-tested.
#   
#   Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/misc/auerswald.c
#   2005/03/07 20:47:04-08:00 nacc@us.ibm.com +1 -1
#   usb/auerswald: change parameters of usb_{control,bulk}_msg() to msecs
# 
# ChangeSet
#   2005/03/08 00:11:43-08:00 nacc@us.ibm.com 
#   [PATCH] usb/vicam: change parameters of usb_{control,bulk}_msg() to msecs
#   
#   Change units of parameters being passed to usb_{control,bulk}_msg() to
#   milliseconds. Patch is compile-tested.
#   
#   Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/media/vicam.c
#   2005/03/07 20:47:08-08:00 nacc@us.ibm.com +2 -2
#   usb/vicam: change parameters of usb_{control,bulk}_msg() to msecs
# 
# ChangeSet
#   2005/03/08 00:11:16-08:00 nacc@us.ibm.com 
#   [PATCH] usb/ultracam: change parameters of usb_{control,bulk}_msg() to msecs
#   
#   Change units of parameters being passed to usb_{control,bulk}_msg() to
#   milliseconds. Patch is compile-tested.
#   
#   Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/media/ultracam.c
#   2005/03/07 20:47:12-08:00 nacc@us.ibm.com +2 -2
#   usb/ultracam: change parameters of usb_{control,bulk}_msg() to msecs
# 
# ChangeSet
#   2005/03/08 00:10:49-08:00 nacc@us.ibm.com 
#   [PATCH] usb/sn9c102: change parameters of usb_{control,bulk}_msg() to msecs
#   
#   Change units of parameters being passed to usb_{control,bulk}_msg() to
#   milliseconds. Patch is compile-tested.
#   
#   Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/media/sn9c102.h
#   2005/03/07 20:47:16-08:00 nacc@us.ibm.com +1 -1
#   usb/sn9c102: change parameters of usb_{control,bulk}_msg() to msecs
# 
# ChangeSet
#   2005/03/08 00:10:23-08:00 nacc@us.ibm.com 
#   [PATCH] usb/se401: change parameters of usb_{control,bulk}_msg() to msecs
#   
#   Change units of parameters being passed to usb_{control,bulk}_msg() to
#   milliseconds. USB_CTRL_{GET,SET}_TIMEOUT were converted to milliseconds
#   in a separate patch. Patch is compile-tested.
#   
#   Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/media/se401.c
#   2005/03/07 20:47:20-08:00 nacc@us.ibm.com +3 -3
#   usb/se401: change parameters of usb_{control,bulk}_msg() to msecs
# 
# ChangeSet
#   2005/03/08 00:09:57-08:00 nacc@us.ibm.com 
#   [PATCH] usb/ov511: change parameters of usb_{control,bulk}_msg() to msecs
#   
#   Change units of parameters being passed to usb_{control,bulk}_msg() to
#   milliseconds. USB_CTRL_{GET,SET}_TIMEOUT were converted to milliseconds
#   in a separate patch. Patch is compile-tested.
#   
#   Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/media/ov511.c
#   2005/03/07 20:47:25-08:00 nacc@us.ibm.com +3 -3
#   usb/ov511: change parameters of usb_{control,bulk}_msg() to msecs
# 
# ChangeSet
#   2005/03/08 00:09:31-08:00 nacc@us.ibm.com 
#   [PATCH] usb/konicawc: change parameters of usb_{control,bulk}_msg() to msecs
#   
#   Change units of parameters being passed to usb_{control,bulk}_msg() to
#   milliseconds. USB_CTRL_{GET,SET}_TIMEOUT were converted to milliseconds
#   in a separate patch. Patch is compile-tested.
#   
#   Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/media/konicawc.c
#   2005/03/07 20:47:29-08:00 nacc@us.ibm.com +1 -1
#   usb/konicawc: change parameters of usb_{control,bulk}_msg() to msecs
# 
# ChangeSet
#   2005/03/08 00:09:04-08:00 nacc@us.ibm.com 
#   [PATCH] usb/ibmcam: change parameters of usb_{control,bulk}_msg() to msecs
#   
#   Change units of parameters being passed to usb_{control,bulk}_msg() to
#   milliseconds. USB_CTRL_{GET,SET}_TIMEOUT were converted to milliseconds
#   in a separate patch. Patch is compile-tested.
#   
#   Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/media/ibmcam.c
#   2005/03/07 20:47:33-08:00 nacc@us.ibm.com +2 -2
#   usb/ibmcam: change parameters of usb_{control,bulk}_msg() to msecs
# 
# ChangeSet
#   2005/03/08 00:08:37-08:00 nacc@us.ibm.com 
#   [PATCH] usb/wacom: change parameters of usb_{control,bulk}_msg() to msecs
#   
#   Change units of parameters being passed to usb_{control,bulk}_msg() to
#   milliseconds. USB_CTRL_{GET,SET}_TIMEOUT were converted to milliseconds
#   in a separate patch. Patch is compile-tested.
#   
#   Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/input/wacom.c
#   2005/03/07 20:47:37-08:00 nacc@us.ibm.com +1 -1
#   usb/wacom: change parameters of usb_{control,bulk}_msg() to msecs
# 
# ChangeSet
#   2005/03/08 00:08:11-08:00 nacc@us.ibm.com 
#   [PATCH] usb/mtouchusb: change parameters of usb_{control,bulk}_msg() to msecs
#   
#   Change units of parameters being passed to usb_{control,bulk}_msg() to
#   milliseconds. USB_CTRL_{GET,SET}_TIMEOUT were converted to milliseconds
#   in a separate patch. Patch is compile-tested.
#   
#   Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/input/mtouchusb.c
#   2005/03/07 20:47:41-08:00 nacc@us.ibm.com +2 -2
#   usb/mtouchusb: change parameters of usb_{control,bulk}_msg() to msecs
# 
# ChangeSet
#   2005/03/08 00:07:45-08:00 nacc@us.ibm.com 
#   [PATCH] usb/aipteke: change parameters of usb_{control,bulk}_msg() to msecs
#   
#   Change units of parameters being passed to usb_{control,bulk}_msg() to
#   milliseconds. USB_CTRL_{GET,SET}_TIMEOUT were converted to milliseconds
#   in a separate patch. Patch is compile-tested.
#   
#   Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/input/aiptek.c
#   2005/03/07 20:47:45-08:00 nacc@us.ibm.com +2 -2
#   usb/aipteke: change parameters of usb_{control,bulk}_msg() to msecs
# 
# ChangeSet
#   2005/03/08 00:07:18-08:00 nacc@us.ibm.com 
#   [PATCH] usb/powermate: change parameters of usb_{control,bulk}_msg() to msecs
#   
#   Change units of parameters being passed to usb_{control,bulk}_msg() to
#   milliseconds. USB_CTRL_{GET,SET}_TIMEOUT were converted to milliseconds
#   in a separate patch. Patch is compile-tested.
#   
#   Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/input/powermate.c
#   2005/03/07 20:47:49-08:00 nacc@us.ibm.com +1 -1
#   usb/powermate: change parameters of usb_{control,bulk}_msg() to msecs
# 
# ChangeSet
#   2005/03/08 00:06:51-08:00 nacc@us.ibm.com 
#   [PATCH] usb/usbtest: change parameters of usb_{control,bulk}_msg() to msecs
#   
#   Change units of parameters being passed to usb_{control,bulk}_msg() to
#   milliseconds. USB_CTRL_{GET,SET}_TIMEOUT were converted to milliseconds
#   in a separate patch. Patch is compile-tested.
#   
#   Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/misc/usbtest.c
#   2005/03/07 20:47:54-08:00 nacc@us.ibm.com +5 -5
#   usb/usbtest: change parameters of usb_{control,bulk}_msg() to msecs
# 
# ChangeSet
#   2005/03/08 00:06:27-08:00 nacc@us.ibm.com 
#   [PATCH] usb/cytherm: change parameters of usb_{control,bulk}_msg() to msecs
#   
#   Change units of parameters being passed to usb_{control,bulk}_msg() to
#   milliseconds. USB_CTRL_{GET,SET}_TIMEOUT were converted to milliseconds
#   in a separate patch. Patch is compile-tested.
#   
#   Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/misc/cytherm.c
#   2005/03/07 20:47:58-08:00 nacc@us.ibm.com +1 -1
#   usb/cytherm: change parameters of usb_{control,bulk}_msg() to msecs
# 
# ChangeSet
#   2005/03/08 00:06:00-08:00 nacc@us.ibm.com 
#   [PATCH] usb/hid-core: change parameters of usb_{control,bulk}_msg() to msecs
#   
#   Change units of parameters being passed to usb_{control,bulk}_msg() to
#   milliseconds. USB_CTRL_{GET,SET}_TIMEOUT were converted to milliseconds
#   in a separate patch. Patch is compile-tested.
#   
#   Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/input/hid-core.c
#   2005/03/07 20:48:02-08:00 nacc@us.ibm.com +3 -3
#   usb/hid-core: change parameters of usb_{control,bulk}_msg() to msecs
# 
# ChangeSet
#   2005/03/08 00:05:35-08:00 nacc@us.ibm.com 
#   [PATCH] usb/hub: change parameters of usb_{control,bulk}_msg() to msecs
#   
#   Change units of parameters being passed to usb_{control,bulk}_msg() to
#   milliseconds. USB_CTRL_{GET,SET}_TIMEOUT was converted to milliseconds
#   in a separate patch. Patch is compile-tested.
#   
#   Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/core/hub.c
#   2005/03/07 20:48:06-08:00 nacc@us.ibm.com +12 -12
#   usb/hub: change parameters of usb_{control,bulk}_msg() to msecs
# 
# ChangeSet
#   2005/03/08 00:05:09-08:00 nacc@us.ibm.com 
#   [PATCH] usb/devio: change parameters of usb_{control,bulk}_msg() to msecs
#   
#   Change units of parameters being passed to usb_{control,bulk}_msg() to
#   milliseconds. Patch is compile-tested.
#   
#   Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/core/devio.c
#   2005/03/07 20:48:10-08:00 nacc@us.ibm.com +2 -2
#   usb/devio: change parameters of usb_{control,bulk}_msg() to msecs
# 
# ChangeSet
#   2005/03/08 00:04:43-08:00 nacc@us.ibm.com 
#   [PATCH] usb/usblp: change parameters of usb_{control,bulk}_msg() to msecs
#   
#   Change units of parameters being passed to usb_{control,bulk}_msg() to
#   milliseconds. Patch is compile-tested.
#   
#   Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/misc/usblcd.c
#   2005/03/07 20:48:14-08:00 nacc@us.ibm.com +2 -2
#   usb/usblp: change parameters of usb_{control,bulk}_msg() to msecs
# 
# ChangeSet
#   2005/03/08 00:04:16-08:00 nacc@us.ibm.com 
#   [PATCH] usb/cdc-acm: change parameters of usb_{control,bulk}_msg() to msecs
#   
#   Change units of parameters being passed to usb_{control,bulk}_msg() to
#   milliseconds. Patch is compile-tested.
#   
#   Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/class/cdc-acm.c
#   2005/03/07 20:48:18-08:00 nacc@us.ibm.com +1 -1
#   usb/cdc-acm: change parameters of usb_{control,bulk}_msg() to msecs
# 
# ChangeSet
#   2005/03/08 00:03:49-08:00 nacc@us.ibm.com 
#   [PATCH] usb/audio: change parameters of usb_{control,bulk}_msg() to msecs
#   
#   Change units of parameters being passed to usb_{control,bulk}_msg() to
#   milliseconds. Patch is compile-tested.
#   
#   Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/class/audio.c
#   2005/03/07 20:48:23-08:00 nacc@us.ibm.com +28 -28
#   usb/audio: change parameters of usb_{control,bulk}_msg() to msecs
# 
# ChangeSet
#   2005/03/08 00:03:23-08:00 nacc@us.ibm.com 
#   [PATCH] usb/speedtch: change parameters of usb_{control,bulk}_msg() to msecs
#   
#   Change units of parameters being passed to
#   usb_{control,bulk}_msg() to milliseconds. Patch is compile-tested.
#   
#   Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/atm/speedtch.c
#   2005/03/07 20:48:27-08:00 nacc@us.ibm.com +4 -4
#   usb/speedtch: change parameters of usb_{control,bulk}_msg() to msecs
# 
# ChangeSet
#   2005/03/08 00:02:54-08:00 nacc@us.ibm.com 
#   [PATCH] usb/message: move msecs change into usb_start_wait_urb()
#   
#   After discussion with gregkh on IRC, I realized that the conversion can
#   be pushed one layer further down into usb_start_wait_urb(), as only
#   usb_{control,bulk}_msg() call this function (kaweth.c has its own
#   version, which remains unchanged by this set of patches).
#   
#   The following incremental patch pushes the conversion into
#   usb_start_wait_urb(). It should be applied after the previous ones to
#   message.c [1/63 and 3/63].
#   
#   Description: Pushes conversion from milliseconds to jiffies one function
#   further down the usb stack into usb_start_wait_urb(). The only callers
#   of this function are usb_{control,bulk}_msg(); this patch makes the
#   units conversion happen in one place instead of two.
#   
#   Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/core/message.c
#   2005/03/07 20:48:31-08:00 nacc@us.ibm.com +3 -3
#   usb/message: move msecs change into usb_start_wait_urb()
# 
# ChangeSet
#   2005/03/07 23:19:27-08:00 nacc@us.ibm.com 
#   [PATCH] usb/message: change parameters of usb_control_msg() to msecs
#   
#   Change units of parameters being passed to usb_control_msg() to
#   milliseconds. USB_CTRL_{GET,SET}_TIMEOUT's units are changed in a separate patch
#   such that the the HZ multiplication is no longer necessary.
#   
#   Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/core/message.c
#   2005/03/07 20:48:35-08:00 nacc@us.ibm.com +7 -7
#   usb/message: change parameters of usb_control_msg() to msecs
# 
# ChangeSet
#   2005/03/07 23:19:01-08:00 nacc@us.ibm.com 
#   [PATCH] include/usb: change USB_CTRL_{SET,GET}_TIMEOUT to msecs
#   
#   Change the units of the timeout constants in usb.h to correspond to
#   the new parameter units for usb_{control,bulk}_msg(), in this case from seconds
#   to milliseconds.
#   
#   Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# include/linux/usb.h
#   2005/03/07 20:48:39-08:00 nacc@us.ibm.com +3 -3
#   include/usb: change USB_CTRL_{SET,GET}_TIMEOUT to msecs
# 
# ChangeSet
#   2005/03/07 23:18:40-08:00 nacc@us.ibm.com 
#   [PATCH] usb/message: make usb_{control,bulk}_msg() use msecs
#   
#   Change the units of the timeout parameter in both usb_control_msg()
#   and usb_bulk_msg() from jiffies to milliseconds. This is the core patch upon
#   which the remaining ones will be built. Patch is compile-tested.
#   
#   Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/core/message.c
#   2005/03/07 20:48:43-08:00 nacc@us.ibm.com +4 -4
#   usb/message: make usb_{control,bulk}_msg() use msecs
# 
# ChangeSet
#   2005/03/07 23:18:12-08:00 stern@rowland.harvard.edu 
#   [PATCH] USB: UHCI: Fix build errors when CONFIG_DEBUG_FS isn't set
#   
#   > I've dropped this now.  It caused the usb-bk tree to be dropped from the
#   > -mm releases due to it causing build errors if CONFIG_DEBUG_FS not being
#   > enabled.  Andrew sent me a horrible hack to try to fix it up, but I'm
#   > going to trust you to fix it up properly :)
#   
#   Here's a proper fix (well, it's a little hackish, but better than Andrew's
#   I hope).  No more build problems if CONFIG_DEBUG_FS isn't set.
#   
#   
#   Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/host/uhci-debug.c
#   2005/03/07 20:48:52-08:00 stern@rowland.harvard.edu +7 -2
#   USB: UHCI: Fix build errors when CONFIG_DEBUG_FS isn't set
# 
# ChangeSet
#   2005/03/07 23:17:43-08:00 david-b@pacbell.net 
#   [PATCH] USB: ohci ppc driver (2/2):  ohci-ppc-soc.c
#   
#   This adds drivers/usb/host/ohci-ppc-soc.c, the USB OHCI glue file
#   for two PPC SOC implementations.
#   
#   Signed-off-by: Dale Farnsworth <dale@farnsworth.org>
#   Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/host/ohci-ppc-soc.c
#   2005/03/07 20:48:56-08:00 david-b@pacbell.net +299 -0
#   USB: ohci ppc driver (2/2):  ohci-ppc-soc.c
# 
# drivers/usb/host/ohci-hcd.c
#   2005/03/07 20:48:56-08:00 david-b@pacbell.net +5 -0
#   USB: ohci ppc driver (2/2):  ohci-ppc-soc.c
# 
# drivers/usb/host/ohci-ppc-soc.c
#   2005/03/07 20:48:56-08:00 david-b@pacbell.net +0 -0
#   BitKeeper file /home/greg/linux/BK/do/usb-2.6/drivers/usb/host/ohci-ppc-soc.c
# 
# ChangeSet
#   2005/03/07 23:17:15-08:00 david-b@pacbell.net 
#   [PATCH] USB: ohci ppc driver (1/2):  big-endian tweaks
#   
#   These are the remaining OHCI core (and Kconfig) updates for big-endian
#   support on STB03xxx and MPC52xx PPC chips.  These are the first known
#   implementations with big-endian register and memory layouts.
#   
#       - Two more in-memory fields, related to isochronous transfers
#         have different behavior:  HCCA frame number, and ISO TD status.
#   
#       - Kconfig gets new OHCI options, for big-endian and little-endian.
#         The default is little-endian; those PPC platforms can support
#         both the on-chip big-endian version, and little-endian PCI chips.
#   
#   Most of the related ohci core fixes have already been merged.
#   
#   Signed-off-by: Dale Farnsworth <dale@farnsworth.org>
#   Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/host/ohci.h
#   2005/03/07 20:49:00-08:00 david-b@pacbell.net +43 -5
#   USB: ohci ppc driver (1/2):  big-endian tweaks
# 
# drivers/usb/host/ohci-q.c
#   2005/03/07 20:49:00-08:00 david-b@pacbell.net +6 -3
#   USB: ohci ppc driver (1/2):  big-endian tweaks
# 
# drivers/usb/host/ohci-dbg.c
#   2005/03/07 20:49:00-08:00 david-b@pacbell.net +1 -1
#   USB: ohci ppc driver (1/2):  big-endian tweaks
# 
# drivers/usb/host/Kconfig
#   2005/03/07 20:49:00-08:00 david-b@pacbell.net +35 -1
#   USB: ohci ppc driver (1/2):  big-endian tweaks
# 
# ChangeSet
#   2005/03/07 23:16:45-08:00 david-b@pacbell.net 
#   [PATCH] USB: cdc-acm uses <linux/usb_cdc.h>
#   
#   This makes cdc-acm use the <linux/usb_cdc.h> file.  It (still) passes
#   "sparse -Wbitwise" on those fields.
#   
#   Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/class/cdc-acm.h
#   2005/03/07 20:49:04-08:00 david-b@pacbell.net +1 -48
#   USB: cdc-acm uses <linux/usb_cdc.h>
# 
# drivers/usb/class/cdc-acm.c
#   2005/03/07 20:49:04-08:00 david-b@pacbell.net +49 -35
#   USB: cdc-acm uses <linux/usb_cdc.h>
# 
# ChangeSet
#   2005/03/07 23:16:18-08:00 david-b@pacbell.net 
#   [PATCH] USB: serial/acm gadget uses <linux/usb_cdc.h>
#   
#   This converts the serial/ACM gadget driver to use <linux/usb_cdc.h>, again
#   a net code shrink.
#   
#   It also gets rid of several "sparse -Wcontext -Wbitwise" warnings; again,
#   excepting the cases where the gadget driver setup() callback hasn't yet
#   changed in all the controller drivers.  Two of these warnings were bugs:
#   one affecting CDC ACM support on big-endian hardware (reporting of DTE
#   data rate), one keeping IRQs blocked too long.
#   
#   Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/gadget/serial.c
#   2005/03/07 20:49:08-08:00 david-b@pacbell.net +46 -108
#   USB: serial/acm gadget uses <linux/usb_cdc.h>
# 
# ChangeSet
#   2005/03/07 23:15:46-08:00 david-b@pacbell.net 
#   [PATCH] USB: Ethernet/RNDIS gadget driver uses <linux/usb_cdc.h>
#   
#   This converts the Ethernet/RNDIS gadget driver to use <linux/usb_cdc.h>.
#   It now passes "sparse -Wbitwise", except for the spot in the gadget API
#   where the SETUP packet is still byteswapped.
#   
#   Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/gadget/rndis.c
#   2005/03/07 20:49:12-08:00 david-b@pacbell.net +1 -1
#   USB: Ethernet/RNDIS gadget driver uses <linux/usb_cdc.h>
# 
# drivers/usb/gadget/ether.c
#   2005/03/07 20:49:12-08:00 david-b@pacbell.net +74 -160
#   USB: Ethernet/RNDIS gadget driver uses <linux/usb_cdc.h>
# 
# ChangeSet
#   2005/03/07 23:13:13-08:00 gregkh@suse.de 
#   USB: revert wacom driver patch.
#   
#   Cset exclude: akpm@osdl.org[gregkh]|ChangeSet|20050308064955|00321
#   
#   Will be coming in through the bk-input tree instead.
#   
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/input/wacom.c
#   2005/03/07 23:13:10-08:00 gregkh@suse.de +0 -0
#   Exclude
#   
#   Revert wacom driver patch, will be coming in through the bk-input
#   tree instead.
#   
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# ChangeSet
#   2005/03/07 22:57:40-08:00 david-b@pacbell.net 
#   [PATCH] USB: usbnet uses <linux/usb_cdc.h>
#   
#   This makes the "usbnet" driver user the new <linux/usb_cdc.h> header,
#   and the stuctures and constants found therein.  It also cleans up
#   the Zaurus device table entries a smidgeon.
#   
#   Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/net/usbnet.c
#   2005/03/07 20:49:17-08:00 david-b@pacbell.net +28 -67
#   USB: usbnet uses <linux/usb_cdc.h>
# 
# ChangeSet
#   2005/03/07 22:57:11-08:00 david-b@pacbell.net 
#   [PATCH] USB: usbnet, cleanups and suspend/resume calls
#   
#   This has some small updates to the "usbnet" driver:
#   
#    - Remove an unused debug-only symbol
#    - Make the net1080 minidriver pass "sparse -Wbitwise"
#    - Add suspend/resume methods
#   
#   No functionality changes other than the suspend/resume support.
#   
#   Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/net/usbnet.c
#   2005/03/07 20:49:21-08:00 david-b@pacbell.net +48 -22
#   USB: usbnet, cleanups and suspend/resume calls
# 
# ChangeSet
#   2005/03/07 22:56:40-08:00 david-b@pacbell.net 
#   [PATCH] USB: pxa2xx_udc isn't for pxa27x
#   
#   This prevents selection of the pxa2xx_udc driver on pxa27x chips;
#   the newer chip has incompatible changes in the register API.
#   
#   Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/gadget/Kconfig
#   2005/03/07 20:49:25-08:00 david-b@pacbell.net +3 -3
#   USB: pxa2xx_udc isn't for pxa27x
# 
# ChangeSet
#   2005/03/07 22:56:17-08:00 david-b@pacbell.net 
#   [PATCH] USB: omap_udc handles two more devel boards
#   
#   This teaches omap_udc how to work on two more OMAP development boards:
#   
#     - OMAP 5912 OSK, a starter kit;
#     - OMAP 1710 H3, more or less an H2 with a newer OMAP chip (0.90 nm etc).
#   
#   It also adds slightly more informative debug dumps for transceiver
#   configuration.
#   
#   Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/gadget/omap_udc.c
#   2005/03/07 20:49:29-08:00 david-b@pacbell.net +18 -12
#   USB: omap_udc handles two more devel boards
# 
# drivers/usb/gadget/Kconfig
#   2005/03/07 20:49:29-08:00 david-b@pacbell.net +1 -1
#   USB: omap_udc handles two more devel boards
# 
# ChangeSet
#   2005/03/07 22:55:48-08:00 david-b@pacbell.net 
#   [PATCH] USB: Ethernet/RNDIS build fix on PXA25x
#   
#   This fixes a build problem with the RNDIS support on PXA25x processors.
#   It's useful to help OpenZaurus win even bigger ... current OpenEmbedded
#   builds already bundle this patch.
#   
#   Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/gadget/ether.c
#   2005/03/07 20:49:33-08:00 david-b@pacbell.net +3 -0
#   USB: Ethernet/RNDIS build fix on PXA25x
# 
# ChangeSet
#   2005/03/07 22:55:19-08:00 david-b@pacbell.net 
#   [PATCH] USB: add <linux/usb_cdc.h>
#   
#   This adds a new <linux/usb_cdc.h> header file, with definitions for the
#   CDC class constants and structures used by various drivers.  For now
#   this only has the ones Linux actually uses.  Each one is used in at least
#   two or three different drivers, so sharing the definitions helps reduce
#   errors.  It's also a good excuse to make sure there "sparse -Wbitwise"
#   doesn't report errors in how these are used!
#   
#   Patches to those drivers will follow as I have time to verify the updates:
#   
#     - CDC ACM (for serial lines and modems)
#   	* Host side support in "cdc-acm"
#   	* Peripheral side support in "g_serial"
#     - CDC Ethernet (cable modems, PDAs, etc)
#   	* Host side support in "usbnet"
#   	* Peripheral side support in "g_ether"
#   
#   Also, Microsoft's RNDIS is a variant of CDC ACM, providing an Ethernet model
#   and implemented by g_ether; it uses these definitions too.
#   
#   Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# include/linux/usb_cdc.h
#   2005/03/07 20:49:37-08:00 david-b@pacbell.net +162 -0
#   USB: add <linux/usb_cdc.h>
# 
# include/linux/usb_cdc.h
#   2005/03/07 20:49:37-08:00 david-b@pacbell.net +0 -0
#   BitKeeper file /home/greg/linux/BK/do/usb-2.6/include/linux/usb_cdc.h
# 
# ChangeSet
#   2005/03/07 22:54:50-08:00 david-b@pacbell.net 
#   [PATCH] USB: don't power down net2280 on suspend
#   
#   This creates a module parameter "enable_suspend", and changes the default
#   behavior to avoid the need to power cycle machines with net2280 cards to
#   recover from some common developer actions (like rmmod/modprobe).
#   
#   When set to 1, the net2280, for better or worse, will enter low-power
#   mode when the USB host requests it.  This is fine except in situations
#   involving a power-cycling host or rmmoding the gadget driver while
#   connected to a suspended (or disconnected!) port.
#   
#   When set to 0 (now the default), the driver will report suspend requests
#   to the gadget driver, but will not place the NET2280 into low-power mode.
#   This works fine in all situations except bus-powered devices (for which
#   a PCI+Linux-based NET2280 generally doesn't make much sense anyway)
#   
#   It also (finally...) updates NetChip references to refer to PLX; and
#   updates the dates on the driver.
#   
#   From: Alex Sanks <ASanks@plxtech.com>
#   Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/gadget/net2280.c
#   2005/03/07 20:49:41-08:00 david-b@pacbell.net +19 -6
#   USB: don't power down net2280 on suspend
# 
# ChangeSet
#   2005/03/07 22:54:20-08:00 bernard@blackham.com.au 
#   [PATCH] USB: fix types in usb suspend
#   
#   This fixes types in USB w.r.t. driver model. It should not actually
#   change any code. Please apply,
#   
#   
#   From: Bernard Blackham <bernard@blackham.com.au>
#   Signed-off-by: Pavel Machek <pavel@suse.cz>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/core/hub.c
#   2005/03/07 20:49:46-08:00 bernard@blackham.com.au +7 -7
#   USB: fix types in usb suspend
# 
# ChangeSet
#   2005/03/07 22:53:53-08:00 nacc@us.ibm.com 
#   [PATCH] usb/mdc800: replace wake_up() with wake_up_interruptible()
#   
#   On Tue, Feb 01, 2005 at 11:51:36AM -0800, Nishanth Aravamudan wrote:
#   > This should fix the behavior of the previous patch (probably not noticed yet).
#   > The wake_up*() was not matched properly in the first patch (fixed below).
#   
#   Modify the wake_up*() calls to match the wait_event*() ones from a
#   previous patch.
#   
#   Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/image/mdc800.c
#   2005/03/07 20:49:50-08:00 nacc@us.ibm.com +3 -3
#   usb/mdc800: replace wake_up() with wake_up_interruptible()
# 
# ChangeSet
#   2005/03/07 22:53:26-08:00 nacc@us.ibm.com 
#   [PATCH] usb/io_edgeport: remove interruptible_sleep_on_timeout() usage
#   
#   On Tue, Feb 01, 2005 at 11:43:08AM -0800, Nishanth Aravamudan wrote:
#   > This should fix the behavior of the previous patch (probably not noticed yet).
#   > The wake_up*() was not matched properly in the first patch (fixed below). Please
#   > consider reverting the previous patch and applying this one instead.
#   
#   Directly use wait-queues to remove remaining callers of
#   interruptible_sleep_on_timeout(). Signals are not checked (except in one
#   case) in the current code, so interruptible should not be necessary.
#   Modify the wake_up*() calls to match the wait-queue usage. There were
#   some naming conflicts, which I tried to resolve appropriately. The final
#   replacement is within a #if 0 / #endif section of code, but in case that
#   code is ever used again, I would prefer it had the correct interface :)
#   
#   Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/serial/io_edgeport.c
#   2005/03/07 20:49:54-08:00 nacc@us.ibm.com +24 -18
#   usb/io_edgeport: remove interruptible_sleep_on_timeout() usage
# 
# ChangeSet
#   2005/03/07 22:52:55-08:00 zaitcev@redhat.com 
#   [PATCH] USB: add usbmon, a USB monitoring framework
#   
#   This patch adds so-called "usbmon", or USB monitoring framework, similar
#   to what tcpdump provides for Ethernet. This is an initial version, but
#   it should be safe and useful. It adds an overhead of an if () statement
#   into submission and giveback paths even when not monitoring, but this
#   was deemed a lesser evil than stealth manipulation of function pointers.
#   
#   The patch makes two changes to hcd.c which make usbmon more useful:
#    - Change the way we determine that DMA should not be mapped for root
#      hubs, so that usbmon knows easily when it's safe to capture data.
#    - Return exports of usb_bus_list and usb_bus_list_lock for those who
#      wish to build usbmon as a module.
#   
#   This version of the patch changes #define to inlines for hooks and
#   drops extra mod_ops.
#   
#   Signed-off-by: Pete Zaitcev <zaitcev@redhat.com>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/mon/usb_mon.h
#   2005/03/07 20:49:58-08:00 zaitcev@redhat.com +51 -0
#   USB: add usbmon, a USB monitoring framework
# 
# drivers/usb/mon/mon_text.c
#   2005/03/07 20:49:58-08:00 zaitcev@redhat.com +395 -0
#   USB: add usbmon, a USB monitoring framework
# 
# drivers/usb/mon/mon_stat.c
#   2005/03/07 20:49:58-08:00 zaitcev@redhat.com +74 -0
#   USB: add usbmon, a USB monitoring framework
# 
# drivers/usb/mon/mon_main.c
#   2005/03/07 20:49:58-08:00 zaitcev@redhat.com +377 -0
#   USB: add usbmon, a USB monitoring framework
# 
# drivers/usb/mon/Makefile
#   2005/03/07 20:49:58-08:00 zaitcev@redhat.com +7 -0
#   USB: add usbmon, a USB monitoring framework
# 
# include/linux/usb.h
#   2005/03/07 20:49:58-08:00 zaitcev@redhat.com +4 -0
#   USB: add usbmon, a USB monitoring framework
# 
# drivers/usb/mon/usb_mon.h
#   2005/03/07 20:49:58-08:00 zaitcev@redhat.com +0 -0
#   BitKeeper file /home/greg/linux/BK/do/usb-2.6/drivers/usb/mon/usb_mon.h
# 
# drivers/usb/mon/mon_text.c
#   2005/03/07 20:49:58-08:00 zaitcev@redhat.com +0 -0
#   BitKeeper file /home/greg/linux/BK/do/usb-2.6/drivers/usb/mon/mon_text.c
# 
# drivers/usb/mon/mon_stat.c
#   2005/03/07 20:49:58-08:00 zaitcev@redhat.com +0 -0
#   BitKeeper file /home/greg/linux/BK/do/usb-2.6/drivers/usb/mon/mon_stat.c
# 
# drivers/usb/mon/mon_main.c
#   2005/03/07 20:49:58-08:00 zaitcev@redhat.com +0 -0
#   BitKeeper file /home/greg/linux/BK/do/usb-2.6/drivers/usb/mon/mon_main.c
# 
# drivers/usb/mon/Makefile
#   2005/03/07 20:49:58-08:00 zaitcev@redhat.com +0 -0
#   BitKeeper file /home/greg/linux/BK/do/usb-2.6/drivers/usb/mon/Makefile
# 
# drivers/usb/mon/Kconfig
#   2005/03/07 20:49:58-08:00 zaitcev@redhat.com +22 -0
#   USB: add usbmon, a USB monitoring framework
# 
# drivers/usb/core/hcd.h
#   2005/03/07 20:49:58-08:00 zaitcev@redhat.com +60 -0
#   USB: add usbmon, a USB monitoring framework
# 
# drivers/usb/core/hcd.c
#   2005/03/07 20:49:58-08:00 zaitcev@redhat.com +52 -10
#   USB: add usbmon, a USB monitoring framework
# 
# drivers/usb/Makefile
#   2005/03/07 20:49:58-08:00 zaitcev@redhat.com +2 -0
#   USB: add usbmon, a USB monitoring framework
# 
# drivers/usb/Kconfig
#   2005/03/07 20:49:58-08:00 zaitcev@redhat.com +2 -0
#   USB: add usbmon, a USB monitoring framework
# 
# drivers/usb/mon/Kconfig
#   2005/03/07 20:49:58-08:00 zaitcev@redhat.com +0 -0
#   BitKeeper file /home/greg/linux/BK/do/usb-2.6/drivers/usb/mon/Kconfig
# 
# ChangeSet
#   2005/03/07 22:52:25-08:00 dsd@gentoo.org 
#   [PATCH] usb-storage: More flexible signature checking mechanism
#   
#   This patch alters the CSW signature checking code to work with devices that
#   report non-standard signatures, such as some Olympus and Aldi cameras.
#   
#   We now learn the first signature we see, and use it to check signatures of all
#   subsequent transfers. This allows us to continue to benefit from the
#   error-checking capabilities of the signature transfer, while becoming
#   compatible with (yet more) non-standard devices.
#   
#   Suggestion from Alan Stern.
#   
#   Signed-off-by: Daniel Drake <dsd@gentoo.org>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/storage/usb.h
#   2005/03/07 20:50:02-08:00 dsd@gentoo.org +1 -0
#   usb-storage: More flexible signature checking mechanism
# 
# drivers/usb/storage/transport.h
#   2005/03/07 20:50:02-08:00 dsd@gentoo.org +0 -3
#   usb-storage: More flexible signature checking mechanism
# 
# drivers/usb/storage/transport.c
#   2005/03/07 20:50:02-08:00 dsd@gentoo.org +16 -4
#   usb-storage: More flexible signature checking mechanism
# 
# ChangeSet
#   2005/03/07 22:51:55-08:00 dhollis@davehollis.com 
#   [PATCH] USB: Add ASIX AX88772 10/100 Ethernet support to usbnet
#   
#   * Add support for the ASIX AX88772 10/100 Ethernet chip
#   * Fix ax8817x_bind to use allocated buffer to avoid DMA on the stack
#   * Fix ax8817x_bind error handling to ensure all resources are freed on failure
#   * Fix ax8817x_get_eeprom routines to return valid eeprom data
#   
#   
#   Signed-off-by: David Hollis <dhollis@davehollis.com>
#   Acked-by: David Brownell <david-b@pacbell.net>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/net/usbnet.c
#   2005/03/07 20:50:06-08:00 dhollis@davehollis.com +378 -28
#   USB: Add ASIX AX88772 10/100 Ethernet support to usbnet
# 
# drivers/usb/net/Kconfig
#   2005/03/07 20:50:06-08:00 dhollis@davehollis.com +2 -2
#   USB: Add ASIX AX88772 10/100 Ethernet support to usbnet
# 
# ChangeSet
#   2005/03/07 22:51:25-08:00 stern@rowland.harvard.edu 
#   [PATCH] USB: Revised fixups for root-hub message handler
#   
#   This patch fixes a number of small errors in the routines that handle
#   messages for root hubs:
#   
#   	Fill in the extra byte if a string descriptor transfer
#   	asks for an odd number of bytes.
#   
#   	Don't copy more than urb->transfer_buffer_length bytes.
#   	Use an extra internal buffer to avoid the need for lots
#   	of bounds checking.
#   
#   	Replace strcpy by strlcpy and sprintf by snprintf to avoid
#   	overflowing an internal buffer.
#   
#   	Don't set urb->status without first acquiring urb->lock.
#   
#   Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/core/hcd.c
#   2005/03/07 20:50:15-08:00 stern@rowland.harvard.edu +71 -33
#   USB: Revised fixups for root-hub message handler
# 
# ChangeSet
#   2005/03/07 22:50:54-08:00 nacc@us.ibm.com 
#   [PATCH] usb/kaweth: use wait_event_timeout()
#   
#   Use wait_event_timeout() instead of custom wait-queue code. Remove now
#   unused variables. I changed the code to only add to the wait-queue if
#   necessary, but I'm not sure if this is correct.
#   
#   Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/net/kaweth.c
#   2005/03/07 20:50:24-08:00 nacc@us.ibm.com +2 -11
#   usb/kaweth: use wait_event_timeout()
# 
# ChangeSet
#   2005/03/07 22:50:25-08:00 nacc@us.ibm.com 
#   [PATCH] usb/hid-core: use wait_event_timeout()
#   
#   Use wait_event_timeout() instead of custom wait-queue code. Remove now
#   unused variables.
#   
#   Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/input/hid-core.c
#   2005/03/07 20:50:28-08:00 nacc@us.ibm.com +4 -16
#   usb/hid-core: use wait_event_timeout()
# 
# ChangeSet
#   2005/03/07 22:49:23-08:00 stern@rowland.harvard.edu 
#   [PATCH] USB UHCI: split code from uhci-hcd.c to new file uhci-q.c
#   
#   The uhci-hcd.c source file has become uncomfortably large.  In
#   anticipation of separate upcoming changes to the HC management (for
#   suspend/resume) and the URB handling (single QH per endpoint), and for the
#   sake of compatibility with the structure of the OHCI and EHCI drivers,
#   this patch splits out almost all the code for scheduling URBs and sticks
#   it in a new source file, uhci-q.c.  This is code rearrangement only, with
#   no functional changes.
#   
#   In case your patch scripts aren't smart enough to realize it, the new
#   uhci-q.c file will have to added to the list of BK-managed files.
#   
#   Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/host/uhci-q.c
#   2005/03/07 20:50:36-08:00 stern@rowland.harvard.edu +1488 -0
#   USB UHCI: split code from uhci-hcd.c to new file uhci-q.c
# 
# drivers/usb/host/uhci-q.c
#   2005/03/07 20:50:36-08:00 stern@rowland.harvard.edu +0 -0
#   BitKeeper file /home/greg/linux/BK/do/usb-2.6/drivers/usb/host/uhci-q.c
# 
# drivers/usb/host/uhci-hcd.c
#   2005/03/07 20:50:36-08:00 stern@rowland.harvard.edu +12 -1485
#   USB UHCI: split code from uhci-hcd.c to new file uhci-q.c
# 
# ChangeSet
#   2005/03/07 22:35:24-08:00 stern@rowland.harvard.edu 
#   [PATCH] USB: Initialize connected ports on newly-activated hubs
#   
#   This patch changes the mechanism used for detecting devices that were
#   already connected to a hub at the time the hub was activated.  This can
#   occur in several different circumstances:
#   
#   	when the hub is configured for the first time,
#   
#   	when the hub is reset following a malfunction,
#   
#   	when the hub is resumed.
#   
#   The patch mainly addresses the third possibility, although it also handles
#   the other two.  The scenario I have in mind is waking up from a system
#   suspend, where the user has plugged in a new USB device while the system
#   was asleep, and for some reason the hub no longer has a record of the
#   connect change on that port.  (Maybe the BIOS or the boot kernel has
#   interfered.)  At any rate, the patch causes the hub driver to scan all
#   ports in the reactivated hub, and if it finds a connected port with no
#   child device already allocated then it pretends there was a connect-change
#   event on that port.
#   
#   This will serve to take care of ports with new devices attached that the
#   driver doesn't know about.  The existing resume code already handles the
#   case of ports that used to have a device but don't any longer.  The
#   remaining case, where different devices are attached to the port before
#   suspending and after resuming, still needs to be handled.  The resume code
#   should call the same "descriptors changed" check used by usb_reset_device.
#   That's a patch for another day.
#   
#   
#   Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/core/hub.h
#   2005/03/07 20:50:41-08:00 stern@rowland.harvard.edu +1 -0
#   USB: Initialize connected ports on newly-activated hubs
# 
# drivers/usb/core/hub.c
#   2005/03/07 20:50:41-08:00 stern@rowland.harvard.edu +9 -3
#   USB: Initialize connected ports on newly-activated hubs
# 
# ChangeSet
#   2005/03/07 22:35:05-08:00 david-b@pacbell.net 
#   [PATCH] USB: ohci-omap updates
#   
#   This resolves a FIXME by making the OHCI driver handle power switching
#   on the OSK board, rather than expecting tps65010 init logic to do that.
#   The tps65010 support is #ifdeffed, since that driver hasn't yet been
#   merged into the mainline kernel tree.
#   
#   It also makes OSK (and Innovator) report that they can do ganged power
#   switching; the rest of usb ignores that for now, but that'll change.
#   (Eventually OHCI needs to support board-specific root hub operations,
#   especially for power switching and overcurrent detection, but that needs
#   a few more tweaks.)
#   
#   Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/host/ohci-omap.c
#   2005/03/07 20:50:45-08:00 david-b@pacbell.net +70 -28
#   USB: ohci-omap updates
# 
# ChangeSet
#   2005/03/07 22:34:40-08:00 david-b@pacbell.net 
#   [PATCH] USB: add 'distrust_firmware' option to ohci
#   
#   This replaces an undocumented/experimental "power_switching" flag with a
#   more useful one that lets the driver rely on the boot firmware to report
#   such capabilities.
#   
#   The driver still defaults to munging those informational flags (as it has
#   since 2.2!), so usbcore usually won't try to power-switch with OHCI, but
#   now we have a simple way to default to the behavior specified by the board
#   manufacturer.
#   
#   Also corrects a misprint in the debug 'registers' dump:  a bit was shifted
#   right by one nibble, so every controller was reported as supporting the
#   legacy i8042 emulation registers.
#   
#   Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/host/ohci-hcd.c
#   2005/03/07 20:50:49-08:00 david-b@pacbell.net +13 -16
#   USB: add 'distrust_firmware' option to ohci
# 
# drivers/usb/host/ohci-dbg.c
#   2005/03/07 20:50:49-08:00 david-b@pacbell.net +1 -1
#   USB: add 'distrust_firmware' option to ohci
# 
# ChangeSet
#   2005/03/07 22:34:19-08:00 nacc@us.ibm.com 
#   [PATCH] usb/ati_remote: use wait_event_timeout()
#   
#   Description: Use wait_event_timeout() instead of custom wait-queue code. The
#   current code uses TASK_INTERRUPTIBLE but doesn't seem to care about signals
#   so TASK_UNINTERRUPTIBLE should be ok.
#   
#   Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/input/ati_remote.c
#   2005/03/07 20:50:54-08:00 nacc@us.ibm.com +5 -14
#   usb/ati_remote: use wait_event_timeout()
# 
# ChangeSet
#   2005/03/07 22:33:54-08:00 nacc@us.ibm.com 
#   [PATCH] usb/auerswald: use wait_event_timeout()
#   
#   Use wait_event_timeout() instead of custom wait-queue code. There
#   might be a problem with returning without adding/removing to the waitqueue
#   before wait_event_timeout() is called. I am not sure if this is a problem or
#   not.
#   
#   Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/misc/auerswald.c
#   2005/03/07 20:50:58-08:00 nacc@us.ibm.com +3 -16
#   usb/auerswald: use wait_event_timeout()
# 
# ChangeSet
#   2005/03/07 22:33:35-08:00 nacc@us.ibm.com 
#   [PATCH] usb/mdc800: use wait_event_timeout()
#   
#   Use wait_event_timeout() instead of custom wait-queue code. Remove
#   now unused variables.
#   
#   Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/image/mdc800.c
#   2005/03/07 20:51:02-08:00 nacc@us.ibm.com +5 -31
#   usb/mdc800: use wait_event_timeout()
# 
# ChangeSet
#   2005/03/07 22:33:09-08:00 nacc@us.ibm.com 
#   [PATCH] usb/io_edgeport: replace interruptible_sleep_on_timeout() with wait_event_timeout()
#   
#   Use wait_event_timeout() instead of deprecated
#   interruptible_sleep_on_timeout(). Signals are not checked in the current
#   code, so interruptible should not be necessary. Patch is compile-tested.
#   
#   Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/serial/io_edgeport.c
#   2005/03/07 20:51:06-08:00 nacc@us.ibm.com +2 -5
#   usb/io_edgeport: replace interruptible_sleep_on_timeout() with wait_event_timeout()
# 
# ChangeSet
#   2005/03/07 22:32:50-08:00 stern@rowland.harvard.edu 
#   [PATCH] USB: Make use_both_schemes=y the default
#   
#   Enough people are experiencing problems with the new device initialization
#   scheme that it seems like a good idea to make the default behavior be to
#   try the old scheme when the new one fails.  That's what this patch does,
#   simply by changing the initial value of the use_both_schemes module
#   parameter.
#   
#   Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/core/hub.c
#   2005/03/07 20:51:10-08:00 stern@rowland.harvard.edu +1 -1
#   USB: Make use_both_schemes=y the default
# 
# ChangeSet
#   2005/03/07 22:32:28-08:00 stern@rowland.harvard.edu 
#   [PATCH] USB: Retry more aggressively during device initialization
#   
#   This patch make the hub driver's device initialization routine more
#   aggressive about detecting errors and retrying.  It checks the result of
#   the 64-byte GET-DESCRIPTOR request to verify that the descriptor tag is
#   set correctly and the ep0-maxpacket value is legal; if either is not true
#   it will retry the request immediately.  David Brownell has said that this
#   kind of approach is necessary to make certain buggy devices work.
#   
#   
#   Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/core/hub.c
#   2005/03/07 20:51:14-08:00 stern@rowland.harvard.edu +18 -10
#   USB: Retry more aggressively during device initialization
# 
# ChangeSet
#   2005/03/07 22:32:07-08:00 radford@golemgroup.com 
#   [PATCH] USB ftdi_sio: an rs485 adaptor from 4n-galaxy.de
#   
#   This patch adds support for an rs485 adaptor from 4n-galaxy.de.
#   
#   
#   Signed-off-by: Jim Radford <radford@golemgroup.com>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/serial/ftdi_sio.h
#   2005/03/07 20:51:19-08:00 radford@golemgroup.com +1 -0
#   USB ftdi_sio: an rs485 adaptor from 4n-galaxy.de
# 
# drivers/usb/serial/ftdi_sio.c
#   2005/03/07 20:51:19-08:00 radford@golemgroup.com +3 -0
#   USB ftdi_sio: an rs485 adaptor from 4n-galaxy.de
# 
# ChangeSet
#   2005/03/07 22:21:24-08:00 nacc@us.ibm.com 
#   [PATCH] usb/cypress_m8: replace schedule_timeout() with msleep()
#   
#   Description: Use msleep() instead of schedule_timeout() to guarantee the task
#   delays as expected. The current code is not incorrect. Using msleep(), though,
#   encourages specifying time delays in human time-units and consistency across the
#   kernel.
#   
#   Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/serial/cypress_m8.c
#   2005/03/07 20:51:23-08:00 nacc@us.ibm.com +3 -3
#   usb/cypress_m8: replace schedule_timeout() with msleep()
# 
# ChangeSet
#   2005/03/07 22:21:00-08:00 mdharm-usb@one-eyed-alien.net 
#   [PATCH] USB Storage: devices which don't process PREVENT-ALLOW MEDIUM REMOVAL
#   
#   This patch started life as as423, and has been re-generated against the
#   current tip.
#   
#   Some storage devices don't like PREVENT-ALLOW MEDIUM REMOVAL commands;
#   rather than returning an Invalid Command ASC they just die or imagine that
#   the medium has actually been removed.  Until now people have been relying
#   on the SCSI blacklist table, which can be updated at runtime, to mark
#   devices which shouldn't receive these commands.  However it will be more
#   efficient and easier to do it from within usb-storage, particularly since
#   many of these devices share the same USB Vendor and Product IDs (while
#   having different INQUIRY product strings).
#   
#   *sigh* We really should be trying to push as much of this as possible onto
#   hotplug.  It's easier to update userspace tools than the kernel to support
#   a new device.
#   
#   The relevant devices already have unusual_devs entries; this patch just
#   adds the new flag to those entries and uses it to set a corresponding flag
#   in the scsi_device structure.
#   
#   Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
#   Signed-off-by: Matthew Dharm <mdharm-usb@one-eyed-alien.net>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/storage/usb.h
#   2005/03/07 20:51:28-08:00 mdharm-usb@one-eyed-alien.net +1 -0
#   USB Storage: devices which don't process PREVENT-ALLOW MEDIUM REMOVAL
# 
# drivers/usb/storage/unusual_devs.h
#   2005/03/07 20:51:28-08:00 mdharm-usb@one-eyed-alien.net +3 -7
#   USB Storage: devices which don't process PREVENT-ALLOW MEDIUM REMOVAL
# 
# drivers/usb/storage/scsiglue.c
#   2005/03/07 20:51:28-08:00 mdharm-usb@one-eyed-alien.net +5 -0
#   USB Storage: devices which don't process PREVENT-ALLOW MEDIUM REMOVAL
# 
# ChangeSet
#   2005/03/07 22:20:36-08:00 phil@ipom.com 
#   [PATCH] USB: unusual_devs.h update
#   
#   Alan and Matt recently submitted a patch to change IGNORE_RESIDE to
#   ignore residues on WRITE as well as READ. As a follow up to that, this
#   device needs that functionality. This adds the unusual_devs entry for
#   that device.
#   
#   
#   Signed-off-by: Phil Dibowitz <phil@ipom.com>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/storage/unusual_devs.h
#   2005/03/07 20:51:32-08:00 phil@ipom.com +7 -0
#   USB: unusual_devs.h update
# 
# ChangeSet
#   2005/03/07 22:20:14-08:00 dsd@gentoo.org 
#   [PATCH] USB: Add USBAT-based CompactFlash storage support
#   
#   Adds long overdue support for 12 CompactFlash card reader/writers based on the
#   USBAT02 chip!
#   
#   See http://usbat2.sourceforge.net
#   
#   Signed-off-by: Daniel Drake <dsd@gentoo.org>
#   Signed-off-by: Matthew Dharm <mdharm-usb@one-eyed-alien.net>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/storage/usb.c
#   2005/03/07 20:51:36-08:00 dsd@gentoo.org +1 -1
#   USB: Add USBAT-based CompactFlash storage support
# 
# drivers/usb/storage/unusual_devs.h
#   2005/03/07 20:51:36-08:00 dsd@gentoo.org +11 -3
#   USB: Add USBAT-based CompactFlash storage support
# 
# drivers/usb/storage/shuttle_usbat.h
#   2005/03/07 20:51:36-08:00 dsd@gentoo.org +32 -4
#   USB: Add USBAT-based CompactFlash storage support
# 
# drivers/usb/storage/shuttle_usbat.c
#   2005/03/07 20:51:36-08:00 dsd@gentoo.org +784 -72
#   USB: Add USBAT-based CompactFlash storage support
# 
# drivers/usb/storage/Kconfig
#   2005/03/07 20:51:36-08:00 dsd@gentoo.org +11 -0
#   USB: Add USBAT-based CompactFlash storage support
# 
# CREDITS
#   2005/03/07 20:51:36-08:00 dsd@gentoo.org +5 -0
#   USB: Add USBAT-based CompactFlash storage support
# 
# ChangeSet
#   2005/03/07 22:19:51-08:00 dsd@gentoo.org 
#   [PATCH] USB: Add USBAT02 storage support
#   
#   Adds support for USBAT02-based devices. A few HP cd writers came out
#   with this chip.  A lot of flash-readers also share these ID numbers:
#   this will be addressed in the next patch.
#   
#   Signed-off-by: Daniel Drake <dsd@gentoo.org>
#   Signed-off-by: Matthew Dharm <mdharm-usb@one-eyed-alien.net>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/storage/unusual_devs.h
#   2005/03/07 20:51:41-08:00 dsd@gentoo.org +8 -0
#   USB: Add USBAT02 storage support
# 
# drivers/usb/storage/Kconfig
#   2005/03/07 20:51:41-08:00 dsd@gentoo.org +1 -1
#   USB: Add USBAT02 storage support
# 
# ChangeSet
#   2005/03/07 22:19:29-08:00 dsd@gentoo.org 
#   [PATCH] USB: shuttle_usbat cleanups and generalisations
#   
#   Misc cleanups, a few more annotations, some function name/usage
#   generalisation, and preparation for addition of support for flash-reader devices.
#   
#   Signed-off-by: Daniel Drake <dsd@gentoo.org>
#   Signed-off-by: Matthew Dharm <mdharm-usb@one-eyed-alien.net>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/storage/usb.c
#   2005/03/07 20:51:45-08:00 dsd@gentoo.org +3 -3
#   USB: shuttle_usbat cleanups and generalisations
# 
# drivers/usb/storage/unusual_devs.h
#   2005/03/07 20:51:45-08:00 dsd@gentoo.org +3 -3
#   USB: shuttle_usbat cleanups and generalisations
# 
# drivers/usb/storage/transport.h
#   2005/03/07 20:51:45-08:00 dsd@gentoo.org +1 -1
#   USB: shuttle_usbat cleanups and generalisations
# 
# drivers/usb/storage/shuttle_usbat.h
#   2005/03/07 20:51:45-08:00 dsd@gentoo.org +45 -5
#   USB: shuttle_usbat cleanups and generalisations
# 
# drivers/usb/storage/shuttle_usbat.c
#   2005/03/07 20:51:45-08:00 dsd@gentoo.org +231 -185
#   USB: shuttle_usbat cleanups and generalisations
# 
# drivers/usb/storage/Makefile
#   2005/03/07 20:51:45-08:00 dsd@gentoo.org +1 -1
#   USB: shuttle_usbat cleanups and generalisations
# 
# drivers/usb/storage/Kconfig
#   2005/03/07 20:51:45-08:00 dsd@gentoo.org +7 -4
#   USB: shuttle_usbat cleanups and generalisations
# 
# ChangeSet
#   2005/03/07 22:19:06-08:00 greg@kroah.com 
#   [PATCH] USB: remove UB checks in the usb-storage driver.
#   
#   This allows either the ub or usb-storage driver to bind to the same device,
#   allowing people to use both without rebuilding their kernels.  It can be
#   a bit messy at times...
#   
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
#   Acked-by: Matthew Dharm <mdharm-kernel@one-eyed-alien.net>
#   Acked-by: Pete Zaitcev <zaitcev@redhat.com>
# 
# drivers/usb/storage/usb.c
#   2005/03/07 20:51:49-08:00 greg@kroah.com +0 -4
#   USB: remove UB checks in the usb-storage driver.
# 
# drivers/usb/storage/unusual_devs.h
#   2005/03/07 20:51:49-08:00 greg@kroah.com +0 -2
#   USB: remove UB checks in the usb-storage driver.
# 
# ChangeSet
#   2005/03/07 22:18:46-08:00 mdharm-usb@one-eyed-alien.net 
#   [PATCH] USB storage: make IGNORE_RESIDUE apply for reads (in addition to writes)
#   
#   This patch was originally as406.  I've rediffed it against a current tree.
#   
#   This patch makes the iGNORE_RESIDUE flag apply to reads (as well as writes,
#   which it already does).  This is done because we've found devices which
#   improperly report residue in the 'read' case.
#   
#   Phil will send in a follow-up patch with the appropriate unusual_devs
#   entry for Ian's device soon.
#   
#   
#   Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
#   Signed-off-by: Matthew Dharm <mdharm-usb@one-eyed-alien.net>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/storage/transport.c
#   2005/03/07 20:51:53-08:00 mdharm-usb@one-eyed-alien.net +1 -2
#   USB storage: make IGNORE_RESIDUE apply for reads (in addition to writes)
# 
# ChangeSet
#   2005/03/07 22:18:22-08:00 mdharm-usb@one-eyed-alien.net 
#   [PATCH] USB Storage: Remove fix_capacity routine
#   
#   This is patch as422 from Alan Stern.
#   
#   This is the second half of the two-part patch to move the fix_capacity
#   functionality up into the sd driver.  James Bottomley has applied the SCSI
#   half, so now the usb-storage part is ready to go.
#   
#   In short, the patch removes the fix_capacity routine and in its place,
#   sets a device flag to tell sd that the reported capacity is one sector too
#   high.  It's a simple change and shouldn't cause any problems.
#   
#   
#   Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
#   Signed-off-by: Matthew Dharm <mdharm-usb@one-eyed-alien.net>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/storage/scsiglue.c
#   2005/03/07 20:51:57-08:00 mdharm-usb@one-eyed-alien.net +5 -0
#   USB Storage: Remove fix_capacity routine
# 
# drivers/usb/storage/protocol.c
#   2005/03/07 20:51:57-08:00 mdharm-usb@one-eyed-alien.net +0 -39
#   USB Storage: Remove fix_capacity routine
# 
# ChangeSet
#   2005/03/07 22:18:03-08:00 luca.risolia@studio.unibo.it 
#   [PATCH] USB: SN9C10x driver bugfix
#   
#   SN9C10x driver bugfix.
#   
#   Changes:
#   @ Calculate correct image size in urb_complete()
#   
#   Signed-off-by: Luca Risolia <luca.risolia@studio.unibo.it>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/media/sn9c102_core.c
#   2005/03/07 20:52:01-08:00 luca.risolia@studio.unibo.it +9 -5
#   USB: SN9C10x driver bugfix
# 
# drivers/usb/media/sn9c102.h
#   2005/03/07 20:52:01-08:00 luca.risolia@studio.unibo.it +2 -2
#   USB: SN9C10x driver bugfix
# 
# ChangeSet
#   2005/03/07 22:17:36-08:00 luca.risolia@studio.unibo.it 
#   [PATCH] USB: SN9C10x driver bugfix
#   
#   SN9C10x bugfix and small updates.
#   
#   Changes:
#   @ Allocate the correct number of buffer memory bytes for read()
#   * Wakeup interruptible events on DEV_MISCONFIGURED status
#   * Allocate the exact number of buffers (nreadbuffers) in poll()
#   * Documentation updates
#   
#   Signed-off-by: Luca Risolia <luca.risolia@studio.unibo.it>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/media/sn9c102_core.c
#   2005/03/07 20:52:05-08:00 luca.risolia@studio.unibo.it +26 -12
#   USB: SN9C10x driver bugfix
# 
# drivers/usb/media/sn9c102.h
#   2005/03/07 20:52:05-08:00 luca.risolia@studio.unibo.it +3 -3
#   USB: SN9C10x driver bugfix
# 
# Documentation/usb/sn9c102.txt
#   2005/03/07 20:52:05-08:00 luca.risolia@studio.unibo.it +3 -10
#   USB: SN9C10x driver bugfix
# 
# ChangeSet
#   2005/03/07 22:17:17-08:00 gregkh@suse.de 
#   [PATCH] USB: give sisusb a valid minor number (133 - 140)
#   
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/misc/sisusbvga/sisusb.h
#   2005/03/07 20:52:10-08:00 gregkh@suse.de +1 -1
#   USB: give sisusb a valid minor number (133 - 140)
# 
# ChangeSet
#   2005/03/07 22:16:51-08:00 thomas@winischhofer.net 
#   [PATCH] USB: SiS USB2VGA minor fix.
#   
#   here is a tiny, small update for the sisusb driver. It fixes one spacing
#   issue, one (internal) API issue and one endian issue (stupid copy/paste
#   error)
#   
#   Signed-off by: Thomas Winischhofer <thomas@winischhofer.net>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/misc/sisusbvga/sisusb.h
#   2005/03/07 20:52:14-08:00 thomas@winischhofer.net +2 -2
#   USB: SiS USB2VGA minor fix.
# 
# drivers/usb/misc/sisusbvga/sisusb.c
#   2005/03/07 20:52:14-08:00 thomas@winischhofer.net +2 -1
#   USB: SiS USB2VGA minor fix.
# 
# ChangeSet
#   2005/03/07 22:16:31-08:00 greg@kroah.com 
#   [PATCH] USB: fix sparse bitwise warnings in the sisusb.c driver
#   
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/misc/sisusbvga/sisusb.c
#   2005/03/07 20:52:18-08:00 greg@kroah.com +2 -2
#   USB: fix sparse bitwise warnings in the sisusb.c driver
# 
# ChangeSet
#   2005/03/07 22:16:09-08:00 thomas@winischhofer.net 
#   [PATCH] USB: add SiS USB2VGA kernel driver
#   
#   Signed-off-by: Thomas Winischhofer <thomas@winischhofer.net>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/usb/misc/sisusbvga/sisusb.h
#   2005/03/07 20:52:22-08:00 thomas@winischhofer.net +278 -0
#   USB: add SiS USB2VGA kernel driver
# 
# drivers/usb/misc/sisusbvga/sisusb.c
#   2005/03/07 20:52:22-08:00 thomas@winischhofer.net +3143 -0
#   USB: add SiS USB2VGA kernel driver
# 
# drivers/usb/misc/sisusbvga/Makefile
#   2005/03/07 20:52:22-08:00 thomas@winischhofer.net +6 -0
#   USB: add SiS USB2VGA kernel driver
# 
# drivers/usb/misc/sisusbvga/sisusb.h
#   2005/03/07 20:52:22-08:00 thomas@winischhofer.net +0 -0
#   BitKeeper file /home/greg/linux/BK/do/usb-2.6/drivers/usb/misc/sisusbvga/sisusb.h
# 
# drivers/usb/misc/sisusbvga/sisusb.c
#   2005/03/07 20:52:22-08:00 thomas@winischhofer.net +0 -0
#   BitKeeper file /home/greg/linux/BK/do/usb-2.6/drivers/usb/misc/sisusbvga/sisusb.c
# 
# drivers/usb/misc/sisusbvga/Makefile
#   2005/03/07 20:52:22-08:00 thomas@winischhofer.net +0 -0
#   BitKeeper file /home/greg/linux/BK/do/usb-2.6/drivers/usb/misc/sisusbvga/Makefile
# 
# drivers/usb/misc/sisusbvga/Kconfig
#   2005/03/07 20:52:22-08:00 thomas@winischhofer.net +14 -0
#   USB: add SiS USB2VGA kernel driver
# 
# drivers/usb/misc/Makefile
#   2005/03/07 20:52:22-08:00 thomas@winischhofer.net +2 -0
#   USB: add SiS USB2VGA kernel driver
# 
# drivers/usb/misc/Kconfig
#   2005/03/07 20:52:22-08:00 thomas@winischhofer.net +2 -0
#   USB: add SiS USB2VGA kernel driver
# 
# MAINTAINERS
#   2005/03/07 20:52:22-08:00 thomas@winischhofer.net +6 -0
#   USB: add SiS USB2VGA kernel driver
# 
# drivers/usb/misc/sisusbvga/Kconfig
#   2005/03/07 20:52:22-08:00 thomas@winischhofer.net +0 -0
#   BitKeeper file /home/greg/linux/BK/do/usb-2.6/drivers/usb/misc/sisusbvga/Kconfig
# 
# ChangeSet
#   2005/03/07 21:22:43-08:00 davem@northbeach.davemloft.net 
#   [BT8XX]: Declare bt878[] array after struct layout definition.
#   
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# drivers/media/dvb/bt8xx/bt878.h
#   2005/03/07 21:22:19-08:00 davem@northbeach.davemloft.net +2 -1
#   [BT8XX]: Declare bt878[] array after struct layout definition.
# 
# ChangeSet
#   2005/03/07 21:21:18-08:00 davem@northbeach.davemloft.net 
#   [SPARC64]: Make access_ok() more palatable to gcc-4.x
#   
#   Also, kill __{user,kernel}_ok() as they are unused
#   macros on sparc64.
#   
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# include/asm-sparc64/uaccess.h
#   2005/03/07 21:20:28-08:00 davem@northbeach.davemloft.net +9 -4
#   [SPARC64]: Make access_ok() more palatable to gcc-4.x
# 
# arch/sparc64/kernel/signal32.c
#   2005/03/07 21:20:28-08:00 davem@northbeach.davemloft.net +1 -1
#   [SPARC64]: Make access_ok() more palatable to gcc-4.x
# 
# arch/sparc64/kernel/signal.c
#   2005/03/07 21:20:28-08:00 davem@northbeach.davemloft.net +1 -1
#   [SPARC64]: Make access_ok() more palatable to gcc-4.x
# 
# ChangeSet
#   2005/03/07 20:35:08-08:00 davem@northbeach.davemloft.net 
#   [SPARC64]: boot_cpu_id is static.
#   
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# include/asm-sparc64/smp.h
#   2005/03/07 20:34:44-08:00 davem@northbeach.davemloft.net +0 -2
#   [SPARC64]: boot_cpu_id is static.
# 
# ChangeSet
#   2005/03/07 23:31:52-05:00 jgarzik@pobox.com 
#   Merge pobox.com:/garz/repo/netdev-2.6/via-rhine
#   into pobox.com:/garz/repo/net-drivers-2.6
# 
# drivers/net/via-rhine.c
#   2005/03/07 23:31:49-05:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# ChangeSet
#   2005/03/07 23:30:48-05:00 jgarzik@pobox.com 
#   Merge pobox.com:/garz/repo/netdev-2.6/sis900
#   into pobox.com:/garz/repo/net-drivers-2.6
# 
# drivers/net/sis900.c
#   2005/03/07 23:30:45-05:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# ChangeSet
#   2005/03/07 23:28:06-05:00 jgarzik@pobox.com 
#   Hand-merge MV643xx ethernet Kconfig dependencies.
# 
# drivers/net/Kconfig
#   2005/03/07 23:28:00-05:00 jgarzik@pobox.com +1 -2
#   Hand-merge MV643xx ethernet Kconfig dependencies.
# 
# include/linux/mv643xx.h
#   2005/03/07 23:26:32-05:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# drivers/net/mv643xx_eth.c
#   2005/03/07 23:26:32-05:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# ChangeSet
#   2005/03/07 20:22:40-08:00 davem@northbeach.davemloft.net 
#   [SPARC]: mstk48t{08,59}_regs is static.
#   
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# include/asm-sparc64/mostek.h
#   2005/03/07 20:22:16-08:00 davem@northbeach.davemloft.net +0 -2
#   [SPARC]: mstk48t{08,59}_regs is static.
# 
# include/asm-sparc/mostek.h
#   2005/03/07 20:22:16-08:00 davem@northbeach.davemloft.net +0 -1
#   [SPARC]: mstk48t{08,59}_regs is static.
# 
# ChangeSet
#   2005/03/07 14:07:42-08:00 torvalds@ppc970.osdl.org 
#   Merge bk://linux-1394.bkbits.net/1394-2.6
#   into ppc970.osdl.org:/home/torvalds/v2.6/linux
# 
# MAINTAINERS
#   2005/03/07 14:07:36-08:00 torvalds@ppc970.osdl.org +0 -0
#   Auto merged
# 
# ChangeSet
#   2005/03/07 13:54:45-08:00 torvalds@ppc970.osdl.org 
#   Merge pcnet32 conflicting updates manually
# 
# drivers/net/pcnet32.c
#   2005/03/07 13:54:36-08:00 torvalds@ppc970.osdl.org +25 -25
#   Merge pcnet32 conflicting updates manually
# 
# include/linux/pci_ids.h
#   2005/03/07 13:51:42-08:00 torvalds@ppc970.osdl.org +0 -0
#   Auto merged
# 
# ChangeSet
#   2005/03/07 13:50:19-08:00 alan@lxorguk.ukuu.org.uk 
#   [PATCH] resync ATI PCI idents into base kernel
# 
# include/linux/pci_ids.h
#   2005/03/05 08:19:27-08:00 alan@lxorguk.ukuu.org.uk +11 -0
#   resync ATI PCI idents into base kernel
# 
# ChangeSet
#   2005/03/07 13:50:06-08:00 alan@lxorguk.ukuu.org.uk 
#   [PATCH] stallion ressurection, phase 1
#   
#   This gets the stallion driver working again non-SMP. Patch by Wayne
#   Meissner
#   
#   Signed-off-by: Alan Cox <alan@redhat.com>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/linux/stallion.h
#   2005/03/05 07:41:16-08:00 alan@lxorguk.ukuu.org.uk +1 -1
#   stallion ressurection, phase 1
# 
# drivers/char/stallion.c
#   2005/03/05 07:32:33-08:00 alan@lxorguk.ukuu.org.uk +51 -71
#   stallion ressurection, phase 1
# 
# ChangeSet
#   2005/03/07 13:49:53-08:00 alan@lxorguk.ukuu.org.uk 
#   [PATCH] PCI idents for PCnet32 fix
#   
#   Sorry forgot I made these constants
# 
# include/linux/pci_ids.h
#   2005/03/05 08:19:27-08:00 alan@lxorguk.ukuu.org.uk +4 -0
#   PCI idents for PCnet32 fix
# 
# ChangeSet
#   2005/03/07 13:49:40-08:00 alan@lxorguk.ukuu.org.uk 
#   [PATCH] Restore PWC driver
#   
#   PWC has a new maintainer (Luc Saillard) and also the various contentious
#   binary hooks removed and replaced with reverse engineering work.
#   
#   Please restore it to the kernel
#   
#   Alan
#   
#   Signed-off-by: Luc Saillard <luc@saillard.org>
#   Signed-off-by: Alan Cox <alan@redhat.com>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/usb/media/pwc/pwc.h
#   2005/03/05 07:26:35-08:00 alan@lxorguk.ukuu.org.uk +278 -0
#   Restore PWC driver
# 
# drivers/usb/media/pwc/pwc-uncompress.h
#   2005/03/05 07:26:35-08:00 alan@lxorguk.ukuu.org.uk +41 -0
#   Restore PWC driver
# 
# drivers/usb/media/pwc/pwc-uncompress.c
#   2005/03/05 07:26:35-08:00 alan@lxorguk.ukuu.org.uk +147 -0
#   Restore PWC driver
# 
# drivers/usb/media/pwc/pwc-timon.h
#   2005/03/05 07:26:35-08:00 alan@lxorguk.ukuu.org.uk +61 -0
#   Restore PWC driver
# 
# drivers/usb/media/pwc/pwc-timon.c
#   2005/03/05 07:26:35-08:00 alan@lxorguk.ukuu.org.uk +1446 -0
#   Restore PWC driver
# 
# drivers/usb/media/pwc/pwc-nala.h
#   2005/03/05 07:26:35-08:00 alan@lxorguk.ukuu.org.uk +66 -0
#   Restore PWC driver
# 
# drivers/usb/media/pwc/pwc-misc.c
#   2005/03/05 07:26:35-08:00 alan@lxorguk.ukuu.org.uk +140 -0
#   Restore PWC driver
# 
# drivers/usb/media/pwc/pwc-kiara.h
#   2005/03/05 07:26:35-08:00 alan@lxorguk.ukuu.org.uk +45 -0
#   Restore PWC driver
# 
# drivers/usb/media/pwc/pwc-kiara.c
#   2005/03/05 07:26:35-08:00 alan@lxorguk.ukuu.org.uk +891 -0
#   Restore PWC driver
# 
# drivers/usb/media/pwc/pwc-ioctl.h
#   2005/03/05 07:26:35-08:00 alan@lxorguk.ukuu.org.uk +292 -0
#   Restore PWC driver
# 
# drivers/usb/media/pwc/pwc-if.c
#   2005/03/05 07:26:35-08:00 alan@lxorguk.ukuu.org.uk +2211 -0
#   Restore PWC driver
# 
# drivers/usb/media/pwc/pwc-dec23.h
#   2005/03/05 07:26:35-08:00 alan@lxorguk.ukuu.org.uk +58 -0
#   Restore PWC driver
# 
# drivers/usb/media/pwc/pwc-dec23.c
#   2005/03/05 07:26:35-08:00 alan@lxorguk.ukuu.org.uk +623 -0
#   Restore PWC driver
# 
# drivers/usb/media/pwc/pwc-dec1.h
#   2005/03/05 07:26:35-08:00 alan@lxorguk.ukuu.org.uk +36 -0
#   Restore PWC driver
# 
# drivers/usb/media/pwc/pwc-dec1.c
#   2005/03/05 07:26:35-08:00 alan@lxorguk.ukuu.org.uk +42 -0
#   Restore PWC driver
# 
# drivers/usb/media/pwc/pwc-ctrl.c
#   2005/03/05 07:26:35-08:00 alan@lxorguk.ukuu.org.uk +1630 -0
#   Restore PWC driver
# 
# drivers/usb/media/pwc/philips.txt
#   2005/03/05 07:26:35-08:00 alan@lxorguk.ukuu.org.uk +236 -0
#   Restore PWC driver
# 
# drivers/usb/media/pwc/Makefile
#   2005/03/05 07:26:35-08:00 alan@lxorguk.ukuu.org.uk +20 -0
#   Restore PWC driver
# 
# drivers/usb/media/pwc/pwc.h
#   2005/03/05 07:26:35-08:00 alan@lxorguk.ukuu.org.uk +0 -0
#   BitKeeper file /home/torvalds/v2.6/alan/drivers/usb/media/pwc/pwc.h
# 
# drivers/usb/media/pwc/pwc-uncompress.h
#   2005/03/05 07:26:35-08:00 alan@lxorguk.ukuu.org.uk +0 -0
#   BitKeeper file /home/torvalds/v2.6/alan/drivers/usb/media/pwc/pwc-uncompress.h
# 
# drivers/usb/media/pwc/pwc-uncompress.c
#   2005/03/05 07:26:35-08:00 alan@lxorguk.ukuu.org.uk +0 -0
#   BitKeeper file /home/torvalds/v2.6/alan/drivers/usb/media/pwc/pwc-uncompress.c
# 
# drivers/usb/media/pwc/pwc-timon.h
#   2005/03/05 07:26:35-08:00 alan@lxorguk.ukuu.org.uk +0 -0
#   BitKeeper file /home/torvalds/v2.6/alan/drivers/usb/media/pwc/pwc-timon.h
# 
# drivers/usb/media/pwc/pwc-timon.c
#   2005/03/05 07:26:35-08:00 alan@lxorguk.ukuu.org.uk +0 -0
#   BitKeeper file /home/torvalds/v2.6/alan/drivers/usb/media/pwc/pwc-timon.c
# 
# drivers/usb/media/pwc/pwc-nala.h
#   2005/03/05 07:26:35-08:00 alan@lxorguk.ukuu.org.uk +0 -0
#   BitKeeper file /home/torvalds/v2.6/alan/drivers/usb/media/pwc/pwc-nala.h
# 
# drivers/usb/media/pwc/pwc-misc.c
#   2005/03/05 07:26:35-08:00 alan@lxorguk.ukuu.org.uk +0 -0
#   BitKeeper file /home/torvalds/v2.6/alan/drivers/usb/media/pwc/pwc-misc.c
# 
# drivers/usb/media/pwc/pwc-kiara.h
#   2005/03/05 07:26:35-08:00 alan@lxorguk.ukuu.org.uk +0 -0
#   BitKeeper file /home/torvalds/v2.6/alan/drivers/usb/media/pwc/pwc-kiara.h
# 
# drivers/usb/media/pwc/pwc-kiara.c
#   2005/03/05 07:26:35-08:00 alan@lxorguk.ukuu.org.uk +0 -0
#   BitKeeper file /home/torvalds/v2.6/alan/drivers/usb/media/pwc/pwc-kiara.c
# 
# drivers/usb/media/pwc/pwc-ioctl.h
#   2005/03/05 07:26:35-08:00 alan@lxorguk.ukuu.org.uk +0 -0
#   BitKeeper file /home/torvalds/v2.6/alan/drivers/usb/media/pwc/pwc-ioctl.h
# 
# drivers/usb/media/pwc/pwc-if.c
#   2005/03/05 07:26:35-08:00 alan@lxorguk.ukuu.org.uk +0 -0
#   BitKeeper file /home/torvalds/v2.6/alan/drivers/usb/media/pwc/pwc-if.c
# 
# drivers/usb/media/pwc/pwc-dec23.h
#   2005/03/05 07:26:35-08:00 alan@lxorguk.ukuu.org.uk +0 -0
#   BitKeeper file /home/torvalds/v2.6/alan/drivers/usb/media/pwc/pwc-dec23.h
# 
# drivers/usb/media/pwc/pwc-dec23.c
#   2005/03/05 07:26:35-08:00 alan@lxorguk.ukuu.org.uk +0 -0
#   BitKeeper file /home/torvalds/v2.6/alan/drivers/usb/media/pwc/pwc-dec23.c
# 
# drivers/usb/media/pwc/pwc-dec1.h
#   2005/03/05 07:26:35-08:00 alan@lxorguk.ukuu.org.uk +0 -0
#   BitKeeper file /home/torvalds/v2.6/alan/drivers/usb/media/pwc/pwc-dec1.h
# 
# drivers/usb/media/pwc/pwc-dec1.c
#   2005/03/05 07:26:35-08:00 alan@lxorguk.ukuu.org.uk +0 -0
#   BitKeeper file /home/torvalds/v2.6/alan/drivers/usb/media/pwc/pwc-dec1.c
# 
# drivers/usb/media/pwc/pwc-ctrl.c
#   2005/03/05 07:26:35-08:00 alan@lxorguk.ukuu.org.uk +0 -0
#   BitKeeper file /home/torvalds/v2.6/alan/drivers/usb/media/pwc/pwc-ctrl.c
# 
# drivers/usb/media/pwc/philips.txt
#   2005/03/05 07:26:35-08:00 alan@lxorguk.ukuu.org.uk +0 -0
#   BitKeeper file /home/torvalds/v2.6/alan/drivers/usb/media/pwc/philips.txt
# 
# drivers/usb/media/pwc/Makefile
#   2005/03/05 07:26:35-08:00 alan@lxorguk.ukuu.org.uk +0 -0
#   BitKeeper file /home/torvalds/v2.6/alan/drivers/usb/media/pwc/Makefile
# 
# drivers/usb/media/pwc/ChangeLog
#   2005/03/05 07:26:35-08:00 alan@lxorguk.ukuu.org.uk +143 -0
#   Restore PWC driver
# 
# drivers/usb/media/Makefile
#   2005/03/05 07:26:35-08:00 alan@lxorguk.ukuu.org.uk +1 -0
#   Restore PWC driver
# 
# drivers/usb/media/Kconfig
#   2005/03/05 07:26:35-08:00 alan@lxorguk.ukuu.org.uk +36 -0
#   Restore PWC driver
# 
# drivers/usb/media/pwc/ChangeLog
#   2005/03/05 07:26:35-08:00 alan@lxorguk.ukuu.org.uk +0 -0
#   BitKeeper file /home/torvalds/v2.6/alan/drivers/usb/media/pwc/ChangeLog
# 
# ChangeSet
#   2005/03/07 13:49:26-08:00 alan@lxorguk.ukuu.org.uk 
#   [PATCH] Add ATP88x support to the ATP870U driver (Vendor patch)
#   
#   Patch-by: ARTOP Corp.
#   
#   Basically this adds the small bits for the new card and makes one set of items
#   an array because the new card is multi-channel.
#   
#   Signed-off-by: Alan Cox <alan@redhat.com>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/linux/pci_ids.h
#   2005/03/05 08:19:27-08:00 alan@lxorguk.ukuu.org.uk +3 -0
#   Add ATP88x support to the ATP870U driver (Vendor patch)
# 
# drivers/scsi/atp870u.h
#   2005/03/05 08:14:06-08:00 alan@lxorguk.ukuu.org.uk +53 -39
#   Add ATP88x support to the ATP870U driver (Vendor patch)
# 
# drivers/scsi/atp870u.c
#   2005/03/05 08:14:06-08:00 alan@lxorguk.ukuu.org.uk +1845 -714
#   Add ATP88x support to the ATP870U driver (Vendor patch)
# 
# drivers/scsi/Kconfig
#   2005/03/05 08:14:25-08:00 alan@lxorguk.ukuu.org.uk +2 -2
#   Add ATP88x support to the ATP870U driver (Vendor patch)
# 
# ChangeSet
#   2005/03/07 13:49:13-08:00 alan@lxorguk.ukuu.org.uk 
#   [PATCH] Fibre attached pcnet/32
#   
#   The current driver does workarounds for errata that do not work with
#   fibre attached devices. This patch avoids doing the workaround on the
#   only known fibre attach pcnet/32 hardware. All handling is automated on
#   pci sub-ids
#   
#   Patch by: Guido Guenther
#   Signed-off-by: Alan Cox <alan@redhat.com>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/net/pcnet32.c
#   2005/03/05 08:12:01-08:00 alan@lxorguk.ukuu.org.uk +25 -19
#   Fibre attached pcnet/32
# 
# ChangeSet
#   2005/03/07 13:49:00-08:00 alan@lxorguk.ukuu.org.uk 
#   [PATCH] Document a "don't do that" case for the tty layer
# 
# Documentation/tty.txt
#   2005/03/05 07:30:59-08:00 alan@lxorguk.ukuu.org.uk +5 -0
#   Document a "don't do that" case for the tty layer
# 
# ChangeSet
#   2005/03/07 13:34:58-08:00 willy@parisc-linux.org 
#   [PATCH] PA-RISC Makefile updates
#   
#    - Support sparse
#    - Use CONFIG_64BIT instead of CONFIG_PARISC64
#    - Find palo in /sbin even if it's not in our $PATH
#   
#   Signed-off-by: Randolph Chung <tausq@parisc-linux.org>
#   Signed-off-by: Matthew Wilcox <willy@parisc-linux.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/parisc/Makefile
#   2005/03/02 03:25:23-08:00 willy@parisc-linux.org +10 -3
#   PA-RISC Makefile updates
# 
# ChangeSet
#   2005/03/07 13:34:43-08:00 willy@parisc-linux.org 
#   [PATCH] PA-RISC Kconfig updates
#   
#    - Use def_bool where possible
#    - Eliminate PARISC64
#   
#   Signed-off-by: Matthew Wilcox <willy@parisc-linux.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/parisc/Kconfig
#   2005/03/02 03:25:23-08:00 willy@parisc-linux.org +8 -16
#   PA-RISC Kconfig updates
# 
# ChangeSet
#   2005/03/07 13:34:29-08:00 willy@parisc-linux.org 
#   [PATCH] Update PA-RISC IOSAPIC driver
#   
#    - Fix all ioremap abuse noticed by CONFIG_DEBUG_IOREMAP on an N4000.
#    - F_EXTEND doesn't do what I thought it did on a 32-bit box.
#    - New calling convention for txn_alloc_irq()
#    - Replace CONFIG_PARISC64 with CONFIG_64BIT
#    - Ensure alignment of the irt buffer to 8 bytes even when slab debugging
#      is enabled
#   
#   Signed-off-by: Matthew Wilcox <willy@parisc-linux.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/parisc/iosapic.c
#   2005/03/02 03:25:37-08:00 willy@parisc-linux.org +95 -137
#   Update PA-RISC IOSAPIC driver
# 
# ChangeSet
#   2005/03/07 13:34:15-08:00 willy@parisc-linux.org 
#   [PATCH] Update PA-RISC IOMMU code
#   
#    - The pdc_io_reset_devices() call necessary for USB keyboard kills the
#      serial console.  Use a test that seems to work for both.
#    - Don't bounce >4G buffers on machines with IOMMU
#    - Remove ASSERT code and cleanup iomem * related warnings
#    - Fix comment that was pointing to the old file location
#    - Expand comment about PDC reset to describe broken GFX+USB console at
#      powerup by direct linux to serial console
#    - Fix all ioremap abuse noticed by CONFIG_DEBUG_IOREMAP on an N4000
#    - Remove casts from "READ_REG" and "WRITE_REG" macro
#    - Set D4 and DD bits in IOC_CTRL
#    - Allow all memory in machine to be in-flight DMA at once, up to 4GB
#   
#   Signed-off-by: Grant Grundler <grundler@parisc-linux.org>
#   Signed-off-by: Matthew Wilcox <willy@parisc-linux.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/parisc/sba_iommu.c
#   2005/03/02 03:25:38-08:00 willy@parisc-linux.org +141 -189
#   Update PA-RISC IOMMU code
# 
# ChangeSet
#   2005/03/07 13:34:01-08:00 willy@parisc-linux.org 
#   [PATCH] Update PA-RISC PCI host adapter
#   
#    - Use CONFIG_64BIT instead of CONFIG_PARISC64
#    - Rename lba_cfg_ops to elroy_cfg_ops
#    - Don't check for a non-1,2 or 4 size in the cfg_ops
#    - Call LBA_CFG_ADDR_SETUP instead of LBA_CFG_TR4_ADDR_SETUP in elroy_cfg_ops
#    - Don't read back from LBA_PCI_CFG_ADDR in LBA_CFG_TR4_ADDR_SETUP
#    - Remove LBA_FLAG_NO_DMA_DURING_CFG since it's always set for elroy_cfg_ops
#    - Remove LBA_TR4PLUS since we no longer need to test for it.
#    - Inline lba_common_init() into lba_driver_probe()
#    - Move TR2.1 check into an elroy-only path
#    - Check for LBAs that aren't Elroy, Mercury or Quicksilver.
#    - Remove all casts to 'int' in the driver, got rid of some unnecessary parens
#      and deleted the obsolete part of a comment.
#    - Return -EINVAL for config space >255
#    - Always return 0 on config read success
#    - Remove definitions of TRUE and FALSE
#    - ioremap fix for port-io on non-PAT machines
#    - Remove the bad casts from the register accessors
#    - With those gone, I could see the piop_base needed to be remapped.
#    - Fix all ioremap abuse noticed by CONFIG_DEBUG_IOREMAP on an N4000.
#   
#   Signed-off-by: Grant Grundler <grundler@parisc-linux.org>
#   Signed-off-by: Matthew Wilcox <willy@parisc-linux.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/parisc/lba_pci.c
#   2005/03/02 03:25:37-08:00 willy@parisc-linux.org +211 -325
#   Update PA-RISC PCI host adapter
# 
# ChangeSet
#   2005/03/07 13:33:46-08:00 willy@parisc-linux.org 
#   [PATCH] PA-RISC defconfig update
#   
#   Update a500_defconfig
#   Remove n4000_defconfig as a500_defconfig is now suitable for both boxes
#   
#   Signed-off-by: Matthew Wilcox <willy@parisc-linux.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/parisc/configs/a500_defconfig
#   2005/03/02 03:25:23-08:00 willy@parisc-linux.org +46 -18
#   PA-RISC defconfig update
# 
# BitKeeper/deleted/.del-n4000_defconfig~f54e9fd42d2c0c9c
#   2005/03/07 13:33:37-08:00 willy@parisc-linux.org +0 -0
#   Delete: arch/parisc/configs/n4000_defconfig
# 
# ChangeSet
#   2005/03/07 13:33:32-08:00 willy@parisc-linux.org 
#   [PATCH] ALSA Harmony sound driver for PA-RISC
#   
#   ALSA Harmony rewrite
#   
#   Signed-Off-By: Kyle McMartin <kyle@parisc-linux.org>
#   Signed-off-by: Stuart Brady <sdbrady@ntlworld.com>
#   Signed-off-by: Matthew Wilcox <willy@parisc-linux.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# sound/parisc/harmony.h
#   2005/03/02 03:25:14-08:00 willy@parisc-linux.org +151 -0
#   ALSA Harmony sound driver for PA-RISC
# 
# sound/parisc/harmony.c
#   2005/03/02 03:26:02-08:00 willy@parisc-linux.org +730 -885
#   ALSA Harmony sound driver for PA-RISC
# 
# sound/parisc/Kconfig
#   2005/03/02 03:26:01-08:00 willy@parisc-linux.org +1 -1
#   ALSA Harmony sound driver for PA-RISC
# 
# MAINTAINERS
#   2005/03/02 03:25:15-08:00 willy@parisc-linux.org +7 -0
#   ALSA Harmony sound driver for PA-RISC
# 
# sound/parisc/harmony.h
#   2005/03/02 03:25:14-08:00 willy@parisc-linux.org +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/sound/parisc/harmony.h
# 
# ChangeSet
#   2005/03/07 13:33:16-08:00 willy@parisc-linux.org 
#   [PATCH] PA-RISC PDC stable storage driver
#   
#   Add PDC stable storage driver.  Also reorganise PA-RISC Kconfig a little.
#   
#   Signed-off-by: Thibaut VARENE <varenet@parisc-linux.org>
#   Signed-off-by: Matthew Wilcox <willy@parisc-linux.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/parisc/pdc_stable.c
#   2005/03/02 03:24:55-08:00 willy@parisc-linux.org +735 -0
#   PA-RISC PDC stable storage driver
# 
# drivers/parisc/Makefile
#   2005/03/02 03:25:37-08:00 willy@parisc-linux.org +1 -0
#   PA-RISC PDC stable storage driver
# 
# drivers/parisc/Kconfig
#   2005/03/02 03:25:37-08:00 willy@parisc-linux.org +21 -4
#   PA-RISC PDC stable storage driver
# 
# drivers/parisc/pdc_stable.c
#   2005/03/02 03:24:55-08:00 willy@parisc-linux.org +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/drivers/parisc/pdc_stable.c
# 
# ChangeSet
#   2005/03/07 13:33:01-08:00 willy@parisc-linux.org 
#   [PATCH] Convert from a struct dev to a firmware hwpath
#   
#   PA-RISC firmware needs a hwpath which can be constructed from a pci_dev
#   or a parisc_device.  Previously we've known what type of device we had,
#   but when using sysfs we have to figure it out.
#   
#   Signed-off-by: Thibaut VARENE <varenet@parisc-linux.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/asm-parisc/hardware.h
#   2005/03/02 03:25:51-08:00 willy@parisc-linux.org +1 -0
#   Convert from a struct dev to a firmware hwpath
# 
# arch/parisc/kernel/drivers.c
#   2005/03/02 03:25:23-08:00 willy@parisc-linux.org +19 -1
#   Convert from a struct dev to a firmware hwpath
# 
# ChangeSet
#   2005/03/07 13:32:46-08:00 willy@parisc-linux.org 
#   [PATCH] Convert PARISC64 to 64BIT
#   
#   More CONFIG_PARISC64 to CONFIG_64BIT conversion
#   
#   Signed-off-by: Matthew Wilcox <willy@parisc-linux.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/parisc/kernel/vmlinux.lds.S
#   2005/03/02 03:25:26-08:00 willy@parisc-linux.org +4 -4
#   Convert PARISC64 to 64BIT
# 
# arch/parisc/kernel/perf_asm.S
#   2005/03/02 03:25:25-08:00 willy@parisc-linux.org +2 -2
#   Convert PARISC64 to 64BIT
# 
# arch/parisc/kernel/pdc_chassis.c
#   2005/03/02 03:25:25-08:00 willy@parisc-linux.org +2 -2
#   Convert PARISC64 to 64BIT
# 
# arch/parisc/kernel/Makefile
#   2005/03/02 03:25:23-08:00 willy@parisc-linux.org +2 -2
#   Convert PARISC64 to 64BIT
# 
# ChangeSet
#   2005/03/07 13:32:32-08:00 willy@parisc-linux.org 
#   [PATCH] GCC 3.4 fixes for PA-RISC parport support
#   
#    - Move include/asm/parport_gsc.h to drivers/parport/
#    - Fix gcc 3.4 compilation (redefined extern inline functions are not
#      considered for inlining)
#   
#   From: Joel Soete <joel.soete@tiscali.be>
#   Signed-off-by: Grant Grundler <grundler@parisc-linux.org>
#   Signed-off-by: Matthew Wilcox <willy@parisc-linux.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/parport/parport_gsc.h
#   2005/01/19 12:49:36-08:00 willy@parisc-linux.org +52 -23
#   GCC 3.4 fixes for PA-RISC parport support
# 
# drivers/parport/parport_gsc.c
#   2005/01/19 12:55:28-08:00 willy@parisc-linux.org +1 -90
#   GCC 3.4 fixes for PA-RISC parport support
# 
# ChangeSet
#   2005/03/07 13:31:48-08:00 willy@parisc-linux.org 
#   [PATCH] PA-RISC copy/clear_user_page improvements
#   
#    - Performance improvement to __clear_user_page_asm
#    - White space cleanup
#    - 64-bit version of copy_user_page_asm
#    - Add prefetching to copy_user_page_asm
#    - remove NOP and "bundle" comments
#   
#   Contributions from Joel Soete
#   Signed-off-by: Grant Grundler <grundler@parisc-linux.org>
#   Signed-off-by: Matthew Wilcox <willy@parisc-linux.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/parisc/kernel/pacache.S
#   2005/03/02 03:25:24-08:00 willy@parisc-linux.org +610 -524
#   PA-RISC copy/clear_user_page improvements
# 
# ChangeSet
#   2005/03/07 09:34:59-08:00 herbert@gondor.apana.org.au 
#   [IPSEC]: Kill redundant dst_release check in xfrm_dst_destroy
#   
#   Here's a trivial patch to get rid of a redundant check that I added
#   in patch 3/4.  dst_release already checks for dst == NULL.
#   
#   Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/xfrm/xfrm_policy.c
#   2005/03/07 09:34:47-08:00 herbert@gondor.apana.org.au +1 -2
#   [IPSEC]: Kill redundant dst_release check in xfrm_dst_destroy
#   
#   Here's a trivial patch to get rid of a redundant check that I added
#   in patch 3/4.  dst_release already checks for dst == NULL.
#   
#   Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# ChangeSet
#   2005/03/07 09:33:29-08:00 akpm@osdl.org 
#   [ATALK]: linux/atalk.h needs net/sock.h
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# include/linux/atalk.h
#   2005/03/07 09:33:17-08:00 akpm@osdl.org +3 -0
#   [ATALK]: linux/atalk.h needs net/sock.h
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# ChangeSet
#   2005/03/07 09:32:25-08:00 herbert@gondor.apana.org.au 
#   [IPSEC]: Get rid of dst_pmtu/ext2_header_len
#   
#   Here is a patch that replaces all occurrences of dst_pmtu in the TCP
#   stack.  As a result we no longer need ext2_header_len.
#   
#   This has a nice synergetic effect with Arnaldo's latest change to
#   linux/tcp.h :)
#   
#   I'll be removing other users of dst->path/dst_pmtu next.
#   
#   Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/ipv6/tcp_ipv6.c
#   2005/03/07 09:32:09-08:00 herbert@gondor.apana.org.au +3 -7
#   [IPSEC]: Get rid of dst_pmtu/ext2_header_len
#   
#   Here is a patch that replaces all occurrences of dst_pmtu in the TCP
#   stack.  As a result we no longer need ext2_header_len.
#   
#   This has a nice synergetic effect with Arnaldo's latest change to
#   linux/tcp.h :)
#   
#   I'll be removing other users of dst->path/dst_pmtu next.
#   
#   Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/ipv4/tcp_output.c
#   2005/03/07 09:32:09-08:00 herbert@gondor.apana.org.au +5 -11
#   [IPSEC]: Get rid of dst_pmtu/ext2_header_len
#   
#   Here is a patch that replaces all occurrences of dst_pmtu in the TCP
#   stack.  As a result we no longer need ext2_header_len.
#   
#   This has a nice synergetic effect with Arnaldo's latest change to
#   linux/tcp.h :)
#   
#   I'll be removing other users of dst->path/dst_pmtu next.
#   
#   Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/ipv4/tcp_ipv4.c
#   2005/03/07 09:32:09-08:00 herbert@gondor.apana.org.au +3 -7
#   [IPSEC]: Get rid of dst_pmtu/ext2_header_len
#   
#   Here is a patch that replaces all occurrences of dst_pmtu in the TCP
#   stack.  As a result we no longer need ext2_header_len.
#   
#   This has a nice synergetic effect with Arnaldo's latest change to
#   linux/tcp.h :)
#   
#   I'll be removing other users of dst->path/dst_pmtu next.
#   
#   Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# include/linux/tcp.h
#   2005/03/07 09:32:09-08:00 herbert@gondor.apana.org.au +4 -6
#   [IPSEC]: Get rid of dst_pmtu/ext2_header_len
#   
#   Here is a patch that replaces all occurrences of dst_pmtu in the TCP
#   stack.  As a result we no longer need ext2_header_len.
#   
#   This has a nice synergetic effect with Arnaldo's latest change to
#   linux/tcp.h :)
#   
#   I'll be removing other users of dst->path/dst_pmtu next.
#   
#   Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# ChangeSet
#   2005/03/07 09:31:04-08:00 herbert@gondor.apana.org.au 
#   [IPSEC]: Check dst validity harder in xfrm_bundle_ok
#   
#   There is another bug in xfrm_bundle_ok where I forgot to
#   check the validity of xdst->route.  In fact, the check
#   on dst->path isn't strong enough either.  For IPv6 entries,
#   dst->path->obsolete is always negative until you call
#   ipv6_dst_check.  So we really need to do that here.
#   
#   Here's the patch to fix those two problems.  Yes I know
#   my dst_check implementation is lame.  I'll come back and
#   fix up all the dst_check functions by moving their dst_release
#   calls out.  It proves that you were right in that IPv6 dst
#   leak thread :)
#   
#   Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/xfrm/xfrm_policy.c
#   2005/03/07 09:30:52-08:00 herbert@gondor.apana.org.au +3 -1
#   [IPSEC]: Check dst validity harder in xfrm_bundle_ok
#   
#   There is another bug in xfrm_bundle_ok where I forgot to
#   check the validity of xdst->route.  In fact, the check
#   on dst->path isn't strong enough either.  For IPv6 entries,
#   dst->path->obsolete is always negative until you call
#   ipv6_dst_check.  So we really need to do that here.
#   
#   Here's the patch to fix those two problems.  Yes I know
#   my dst_check implementation is lame.  I'll come back and
#   fix up all the dst_check functions by moving their dst_release
#   calls out.  It proves that you were right in that IPv6 dst
#   leak thread :)
#   
#   Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# include/net/dst.h
#   2005/03/07 09:30:52-08:00 herbert@gondor.apana.org.au +9 -0
#   [IPSEC]: Check dst validity harder in xfrm_bundle_ok
#   
#   There is another bug in xfrm_bundle_ok where I forgot to
#   check the validity of xdst->route.  In fact, the check
#   on dst->path isn't strong enough either.  For IPv6 entries,
#   dst->path->obsolete is always negative until you call
#   ipv6_dst_check.  So we really need to do that here.
#   
#   Here's the patch to fix those two problems.  Yes I know
#   my dst_check implementation is lame.  I'll come back and
#   fix up all the dst_check functions by moving their dst_release
#   calls out.  It proves that you were right in that IPv6 dst
#   leak thread :)
#   
#   Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# ChangeSet
#   2005/03/07 15:30:12+01:00 akropel1@rochester.rr.com 
#   input: hid-debug.h includes resolv_event, which is not used if DEBUG is only
#          enabled in hid-core, but _is_ used when DEBUG is also enabled in hid-input.
#          Mark the function with __attribute__((unused)) to silence the warning
#          when only hid-core is being DEBUGged.
#   
#   Signed-off-by: Adam Kropelin <akropel1@rochester.rr.com>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/usb/input/hid-debug.h
#   2005/03/07 15:30:06+01:00 akropel1@rochester.rr.com +1 -1
#   input: hid-debug.h includes resolv_event, which is not used if DEBUG is only
#          enabled in hid-core, but _is_ used when DEBUG is also enabled in hid-input.
#          Mark the function with __attribute__((unused)) to silence the warning
#          when only hid-core is being DEBUGged.
#   
#   Signed-off-by: Adam Kropelin <akropel1@rochester.rr.com>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# ChangeSet
#   2005/03/07 15:29:15+01:00 dtor_core@ameritech.net 
#   Input: export psmouse module parameters via sysfs:
#             /sys/module/psmouse/parameters/proto
#             /sys/module/psmouse/parameters/rate
#             /sys/module/psmouse/parameters/resetafter
#             /sys/module/psmouse/parameters/resolution
#             /sys/module/psmouse/parameters/smartscroll
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/mouse/psmouse-base.c
#   2005/03/07 15:29:08+01:00 dtor_core@ameritech.net +40 -18
#   Input: export psmouse module parameters via sysfs:
#             /sys/module/psmouse/parameters/proto
#             /sys/module/psmouse/parameters/rate
#             /sys/module/psmouse/parameters/resetafter
#             /sys/module/psmouse/parameters/resolution
#             /sys/module/psmouse/parameters/smartscroll
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# ChangeSet
#   2005/03/07 15:28:44+01:00 dtor_core@ameritech.net 
#   Input: i8042 - disable MUX mode on some Fujitsu notebooks as it
#          does not seem to be working properly and requires psmouse
#          module to be reloaded several times for touchpad to be  
#          identified correctly.  
#          Since none of these notebooks have external PS/2 ports
#          disabling MUX should have no drawbacks.  
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/serio/i8042-x86ia64io.h
#   2005/03/07 15:28:38+01:00 dtor_core@ameritech.net +47 -4
#   Input: i8042 - disable MUX mode on some Fujitsu notebooks as it
#          does not seem to be working properly and requires psmouse
#          module to be reloaded several times for touchpad to be  
#          identified correctly.  
#          Since none of these notebooks have external PS/2 ports
#          disabling MUX should have no drawbacks.  
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# ChangeSet
#   2005/03/07 15:27:41+01:00 dtor_core@ameritech.net 
#   input: some whitespace and formatting cleanup in Corgi drivers.
#          Also change del_timer to del_timer_sync in corgikbd and
#          add missing del_timer_sync to corgi_ts.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/touchscreen/corgi_ts.c
#   2005/03/07 15:27:35+01:00 dtor_core@ameritech.net +43 -43
#   input: some whitespace and formatting cleanup in Corgi drivers.
#          Also change del_timer to del_timer_sync in corgikbd and
#          add missing del_timer_sync to corgi_ts.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/keyboard/corgikbd.c
#   2005/03/07 15:27:35+01:00 dtor_core@ameritech.net +43 -45
#   input: some whitespace and formatting cleanup in Corgi drivers.
#          Also change del_timer to del_timer_sync in corgikbd and
#          add missing del_timer_sync to corgi_ts.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# ChangeSet
#   2005/03/07 15:24:32+01:00 dtor_core@ameritech.net 
#   input: Fix compiler warning in trident gameport code with enabled debugging
#          and compiler error in ymfpci when compiled without gameport support.
#   
#   From: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# sound/pci/ymfpci/ymfpci.c
#   2005/03/07 15:24:26+01:00 dtor_core@ameritech.net +1 -1
#   input: Fix compiler warning in trident gameport code with enabled debugging
#          and compiler error in ymfpci when compiled without gameport support.
#   
#   From: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# sound/pci/trident/trident_main.c
#   2005/03/07 15:24:26+01:00 dtor_core@ameritech.net +1 -1
#   input: Fix compiler warning in trident gameport code with enabled debugging
#          and compiler error in ymfpci when compiled without gameport support.
#   
#   From: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# ChangeSet
#   2005/03/07 15:15:42+01:00 c.lucas@ifrance.com 
#   input: convert from pci_module_init to pci_register_driver
#   
#   Signed-off-by: Christophe Lucas <c.lucas@ifrance.com>
#   Signed-off-by: Domen Puncer <domen@coderock.org>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/serio/pcips2.c
#   2005/03/07 15:15:36+01:00 c.lucas@ifrance.com +1 -1
#   input: convert from pci_module_init to pci_register_driver
#   
#   Signed-off-by: Christophe Lucas <c.lucas@ifrance.com>
#   Signed-off-by: Domen Puncer <domen@coderock.org>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/gameport/vortex.c
#   2005/03/07 15:15:36+01:00 c.lucas@ifrance.com +1 -1
#   input: convert from pci_module_init to pci_register_driver
#   
#   Signed-off-by: Christophe Lucas <c.lucas@ifrance.com>
#   Signed-off-by: Domen Puncer <domen@coderock.org>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/gameport/fm801-gp.c
#   2005/03/07 15:15:36+01:00 c.lucas@ifrance.com +1 -1
#   input: convert from pci_module_init to pci_register_driver
#   
#   Signed-off-by: Christophe Lucas <c.lucas@ifrance.com>
#   Signed-off-by: Domen Puncer <domen@coderock.org>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/gameport/emu10k1-gp.c
#   2005/03/07 15:15:36+01:00 c.lucas@ifrance.com +1 -1
#   input: convert from pci_module_init to pci_register_driver
#   
#   Signed-off-by: Christophe Lucas <c.lucas@ifrance.com>
#   Signed-off-by: Domen Puncer <domen@coderock.org>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/gameport/cs461x.c
#   2005/03/07 15:15:36+01:00 c.lucas@ifrance.com +1 -1
#   input: convert from pci_module_init to pci_register_driver
#   
#   Signed-off-by: Christophe Lucas <c.lucas@ifrance.com>
#   Signed-off-by: Domen Puncer <domen@coderock.org>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# ChangeSet
#   2005/03/07 15:14:28+01:00 akropel@rochester.rr.com 
#   input: hid-debug.h uses a C99 feature (range designators) not available in
#          gcc-2.95. Since gcc-2.95 is still a supported compiler for 2.6 and the 
#          initializers as used here add no functional value, this patch removes
#          them. gcc-2.95 is then able to compile hid-core with DEBUG enabled.
#   
#   Signed-off-by: Adam Kropelin <akropel1@rochester.rr.com>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/usb/input/hid-debug.h
#   2005/03/07 15:14:22+01:00 akropel@rochester.rr.com +0 -10
#   input: hid-debug.h uses a C99 feature (range designators) not available in
#          gcc-2.95. Since gcc-2.95 is still a supported compiler for 2.6 and the 
#          initializers as used here add no functional value, this patch removes
#          them. gcc-2.95 is then able to compile hid-core with DEBUG enabled.
#   
#   Signed-off-by: Adam Kropelin <akropel1@rochester.rr.com>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# ChangeSet
#   2005/03/07 15:13:27+01:00 lenz@cs.wisc.edu 
#   input: This patch is for the keyboard on Sharp Zaurus collie and poodle
#          models (SL5000, SL5500, and SL5600).  It uses the devices exported
#          in arch/arm/common/locomo.c.  The pressed state of the keys is now
#          handled by the input layer rather than directly in this driver.
#   
#   More information about the status of Zaurus (and some extra patches
#   if you need to test this out) can be found on my web page at
#   http://www.cs.wisc.edu/~lenz/zaurus
#   
#   Signed-off-by: John Lenz <lenz@cs.wisc.edu>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/keyboard/locomokbd.c
#   2005/03/07 15:13:21+01:00 lenz@cs.wisc.edu +309 -0
# 
# drivers/input/keyboard/locomokbd.c
#   2005/03/07 15:13:21+01:00 lenz@cs.wisc.edu +0 -0
#   BitKeeper file /home/vojtech/bk/input-new/drivers/input/keyboard/locomokbd.c
# 
# drivers/input/keyboard/Makefile
#   2005/03/07 15:13:21+01:00 lenz@cs.wisc.edu +1 -0
#   input: This patch is for the keyboard on Sharp Zaurus collie and poodle
#          models (SL5000, SL5500, and SL5600).  It uses the devices exported
#          in arch/arm/common/locomo.c.  The pressed state of the keys is now
#          handled by the input layer rather than directly in this driver.
#   
#   More information about the status of Zaurus (and some extra patches
#   if you need to test this out) can be found on my web page at
#   http://www.cs.wisc.edu/~lenz/zaurus
#   
#   Signed-off-by: John Lenz <lenz@cs.wisc.edu>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/keyboard/Kconfig
#   2005/03/07 15:13:21+01:00 lenz@cs.wisc.edu +9 -0
#   input: This patch is for the keyboard on Sharp Zaurus collie and poodle
#          models (SL5000, SL5500, and SL5600).  It uses the devices exported
#          in arch/arm/common/locomo.c.  The pressed state of the keys is now
#          handled by the input layer rather than directly in this driver.
#   
#   More information about the status of Zaurus (and some extra patches
#   if you need to test this out) can be found on my web page at
#   http://www.cs.wisc.edu/~lenz/zaurus
#   
#   Signed-off-by: John Lenz <lenz@cs.wisc.edu>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# ChangeSet
#   2005/03/07 15:12:03+01:00 lethal@linux-sh.org 
#   New BitKeeper file ``drivers/input/touchscreen/hp680_ts_input.c''
# 
# drivers/input/touchscreen/hp680_ts_input.c
#   2005/03/07 15:11:57+01:00 lethal@linux-sh.org +135 -0
# 
# drivers/input/touchscreen/hp680_ts_input.c
#   2005/03/07 15:11:57+01:00 lethal@linux-sh.org +0 -0
#   BitKeeper file /home/vojtech/bk/input-new/drivers/input/touchscreen/hp680_ts_input.c
# 
# drivers/input/touchscreen/Makefile
#   2005/03/07 15:11:57+01:00 lethal@linux-sh.org +2 -1
#   New BitKeeper file ``drivers/input/touchscreen/hp680_ts_input.c''
# 
# drivers/input/touchscreen/Kconfig
#   2005/03/07 15:11:57+01:00 lethal@linux-sh.org +12 -0
#   input: Add support for the touchscreen found in the hp680 and
#          hp690 jornada devices.
#   
#   Signed-off-by: Andriy Skulysh <askulysh@image.kiev.ua>
#   Signed-off-by: Paul Mundt <lethal@linux-sh.org>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# ChangeSet
#   2005/03/07 15:10:51+01:00 vojtech@suse.cz 
#   input: Fix a connector name in a comment in lkkbd.c
#   
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/keyboard/lkkbd.c
#   2005/03/07 15:10:46+01:00 vojtech@suse.cz +2 -2
#   input: Fix a connector name in a comment in lkkbd.c
#   
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# ChangeSet
#   2005/03/07 15:09:59+01:00 vojtech@suse.cz 
#   input: Fix ALPS breakage caused by previous refactoring.
#   
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/mouse/alps.c
#   2005/03/07 15:09:53+01:00 vojtech@suse.cz +25 -32
#   input: Fix ALPS breakage caused by previous refactoring.
#   
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# ChangeSet
#   2005/03/07 15:07:54+01:00 vojtech@suse.cz 
#   input: Fix two typos in i8042 PnP code.
#   
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/serio/i8042-x86ia64io.h
#   2005/03/07 15:07:11+01:00 vojtech@suse.cz +2 -2
#   input: Fix two typos in i8042 PnP code.
#   
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# ChangeSet
#   2005/03/07 14:50:57+01:00 vojtech@suse.cz 
#   Manual merge
# 
# drivers/input/serio/i8042-x86ia64io.h
#   2005/03/07 14:50:52+01:00 vojtech@suse.cz +0 -1
#   Manual merge
# 
# sound/oss/sonicvibes.c
#   2005/03/07 14:48:09+01:00 vojtech@suse.cz +0 -0
#   Auto merged
# 
# ChangeSet
#   2005/03/07 01:52:19-05:00 jgarzik@pobox.com 
#   Merge pobox.com:/garz/repo/linux-2.6
#   into pobox.com:/garz/repo/libata-dev/remove-one-fix
# 
# drivers/scsi/libata-core.c
#   2005/03/07 01:52:11-05:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# ChangeSet
#   2005/03/07 01:48:21-05:00 jgarzik@pobox.com 
#   Merge pobox.com:/garz/repo/libata-dev/janitor
#   into pobox.com:/garz/repo/libata-2.6
# 
# drivers/scsi/sata_vsc.c
#   2005/03/07 01:48:15-05:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# ChangeSet
#   2005/03/07 01:37:25-05:00 jgarzik@pobox.com 
#   Merge pobox.com:/garz/repo/netdev-2.6/smc91x
#   into pobox.com:/garz/repo/net-drivers-2.6
# 
# drivers/net/Kconfig
#   2005/03/07 01:37:22-05:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# ChangeSet
#   2005/03/07 01:35:21-05:00 jgarzik@pobox.com 
#   Merge pobox.com:/garz/repo/netdev-2.6/s2io
#   into pobox.com:/garz/repo/net-drivers-2.6
# 
# drivers/net/s2io.c
#   2005/03/07 01:35:18-05:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# ChangeSet
#   2005/03/07 01:33:21-05:00 jgarzik@pobox.com 
#   Merge pobox.com:/garz/repo/netdev-2.6/pm_message_t
#   into pobox.com:/garz/repo/net-drivers-2.6
# 
# drivers/net/via-velocity.c
#   2005/03/07 01:33:18-05:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# drivers/net/typhoon.c
#   2005/03/07 01:33:18-05:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# drivers/net/tg3.c
#   2005/03/07 01:33:18-05:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# drivers/net/eepro100.c
#   2005/03/07 01:33:18-05:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# drivers/net/amd8111e.c
#   2005/03/07 01:33:18-05:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# drivers/net/8139too.c
#   2005/03/07 01:33:18-05:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# ChangeSet
#   2005/03/07 01:30:13-05:00 jgarzik@pobox.com 
#   Merge pobox.com:/garz/repo/netdev-2.6/bonding
#   into pobox.com:/garz/repo/net-drivers-2.6
# 
# drivers/net/Kconfig
#   2005/03/07 01:30:10-05:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# ChangeSet
#   2005/03/06 21:36:51-08:00 herbert@gondor.apana.org.au 
#   [IPSEC]: Get metrics for xfrm_dst from top dst
#   
#   For the metrics other than MTU, we should also be getting it from
#   the top dst as opposed to the bottom dst.  With this change, the
#   user is able to manipulate values such as advmss for individual
#   hosts behind a remote IPsec gateway.
#    
#   Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/ipv6/xfrm6_policy.c
#   2005/03/06 21:36:27-08:00 herbert@gondor.apana.org.au +1 -1
#   [IPSEC]: Get metrics for xfrm_dst from top dst
#   
#   For the metrics other than MTU, we should also be getting it from
#   the top dst as opposed to the bottom dst.  With this change, the
#   user is able to manipulate values such as advmss for individual
#   hosts behind a remote IPsec gateway.
#    
#   Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/ipv4/xfrm4_policy.c
#   2005/03/06 21:36:27-08:00 herbert@gondor.apana.org.au +1 -1
#   [IPSEC]: Get metrics for xfrm_dst from top dst
#   
#   For the metrics other than MTU, we should also be getting it from
#   the top dst as opposed to the bottom dst.  With this change, the
#   user is able to manipulate values such as advmss for individual
#   hosts behind a remote IPsec gateway.
#    
#   Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# ChangeSet
#   2005/03/06 21:35:27-08:00 herbert@gondor.apana.org.au 
#   [IPSEC]: Fix xfrm[46]_update_pmtu to update top dst
#   
#   Let's also fix IPsec PMTU storage.  When we get an MTU update for an
#   xfrm_dst, it should be done to the top dst, not the bottom dst.
#   
#   For example, when we get a need-to-frag message for host C behind
#   a our IPsec peer B, we should be updating the dst entry for C and
#   not B as we do now.
#   
#   I've removed the boundary checks since the same checks are done
#   in ipv[46]/route.c already.
#   
#   Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/ipv6/xfrm6_policy.c
#   2005/03/06 21:35:03-08:00 herbert@gondor.apana.org.au +3 -5
#   [IPSEC]: Fix xfrm[46]_update_pmtu to update top dst
#   
#   Let's also fix IPsec PMTU storage.  When we get an MTU update for an
#   xfrm_dst, it should be done to the top dst, not the bottom dst.
#   
#   For example, when we get a need-to-frag message for host C behind
#   a our IPsec peer B, we should be updating the dst entry for C and
#   not B as we do now.
#   
#   I've removed the boundary checks since the same checks are done
#   in ipv[46]/route.c already.
#   
#   Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/ipv4/xfrm4_policy.c
#   2005/03/06 21:35:03-08:00 herbert@gondor.apana.org.au +2 -4
#   [IPSEC]: Fix xfrm[46]_update_pmtu to update top dst
#   
#   Let's also fix IPsec PMTU storage.  When we get an MTU update for an
#   xfrm_dst, it should be done to the top dst, not the bottom dst.
#   
#   For example, when we get a need-to-frag message for host C behind
#   a our IPsec peer B, we should be updating the dst entry for C and
#   not B as we do now.
#   
#   I've removed the boundary checks since the same checks are done
#   in ipv[46]/route.c already.
#   
#   Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# ChangeSet
#   2005/03/06 21:34:23-08:00 herbert@gondor.apana.org.au 
#   [IPSEC]: Use dst_mtu i n xfrm[46]_output
#   
#   There was a lot of fun in laying the foundations.  Now it's time
#   to start using it.
#   
#   This patch fixes the calculations in xfrm[46]_output so that we don't
#   reject properly sized packets from the TCP stack.  The previous
#   calculation is wrong because the xfrm overhead is not constant.
#   
#   After this I'll start cleaning stuff up.  For example, tcp's
#   ext2_header_len and dst's path can both be removed.
#   
#   Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/ipv6/xfrm6_output.c
#   2005/03/06 21:33:59-08:00 herbert@gondor.apana.org.au +1 -1
#   [IPSEC]: Use dst_mtu i n xfrm[46]_output
#   
#   There was a lot of fun in laying the foundations.  Now it's time
#   to start using it.
#   
#   This patch fixes the calculations in xfrm[46]_output so that we don't
#   reject properly sized packets from the TCP stack.  The previous
#   calculation is wrong because the xfrm overhead is not constant.
#   
#   After this I'll start cleaning stuff up.  For example, tcp's
#   ext2_header_len and dst's path can both be removed.
#   
#   Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/ipv4/xfrm4_output.c
#   2005/03/06 21:33:59-08:00 herbert@gondor.apana.org.au +1 -1
#   [IPSEC]: Use dst_mtu i n xfrm[46]_output
#   
#   There was a lot of fun in laying the foundations.  Now it's time
#   to start using it.
#   
#   This patch fixes the calculations in xfrm[46]_output so that we don't
#   reject properly sized packets from the TCP stack.  The previous
#   calculation is wrong because the xfrm overhead is not constant.
#   
#   After this I'll start cleaning stuff up.  For example, tcp's
#   ext2_header_len and dst's path can both be removed.
#   
#   Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# include/net/dst.h
#   2005/03/06 21:33:59-08:00 herbert@gondor.apana.org.au +10 -0
#   [IPSEC]: Use dst_mtu i n xfrm[46]_output
#   
#   There was a lot of fun in laying the foundations.  Now it's time
#   to start using it.
#   
#   This patch fixes the calculations in xfrm[46]_output so that we don't
#   reject properly sized packets from the TCP stack.  The previous
#   calculation is wrong because the xfrm overhead is not constant.
#   
#   After this I'll start cleaning stuff up.  For example, tcp's
#   ext2_header_len and dst's path can both be removed.
#   
#   Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# ChangeSet
#   2005/03/06 21:31:52-08:00 herbert@gondor.apana.org.au 
#   [IPSEC]: Store MTU at each xfrm_dst
#   
#   Finally this is the patch that sets the MTU values of each xfrm_dst
#   and keeps it up-to-date.
#   
#   To recap, at this point we've obtained accurate MTU values at each
#   xfrm_dst.  The next step would be to start using it as
#   dst_pmtu(xfrm_dst).
#   
#   Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/xfrm/xfrm_policy.c
#   2005/03/06 21:31:30-08:00 herbert@gondor.apana.org.au +63 -2
#   [IPSEC]: Store MTU at each xfrm_dst
#   
#   Finally this is the patch that sets the MTU values of each xfrm_dst
#   and keeps it up-to-date.
#   
#   To recap, at this point we've obtained accurate MTU values at each
#   xfrm_dst.  The next step would be to start using it as
#   dst_pmtu(xfrm_dst).
#   
#   Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/ipv6/xfrm6_policy.c
#   2005/03/06 21:31:30-08:00 herbert@gondor.apana.org.au +2 -0
#   [IPSEC]: Store MTU at each xfrm_dst
#   
#   Finally this is the patch that sets the MTU values of each xfrm_dst
#   and keeps it up-to-date.
#   
#   To recap, at this point we've obtained accurate MTU values at each
#   xfrm_dst.  The next step would be to start using it as
#   dst_pmtu(xfrm_dst).
#   
#   Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/ipv4/xfrm4_policy.c
#   2005/03/06 21:31:30-08:00 herbert@gondor.apana.org.au +2 -0
#   [IPSEC]: Store MTU at each xfrm_dst
#   
#   Finally this is the patch that sets the MTU values of each xfrm_dst
#   and keeps it up-to-date.
#   
#   To recap, at this point we've obtained accurate MTU values at each
#   xfrm_dst.  The next step would be to start using it as
#   dst_pmtu(xfrm_dst).
#   
#   Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# include/net/xfrm.h
#   2005/03/06 21:31:30-08:00 herbert@gondor.apana.org.au +3 -0
#   [IPSEC]: Store MTU at each xfrm_dst
#   
#   Finally this is the patch that sets the MTU values of each xfrm_dst
#   and keeps it up-to-date.
#   
#   To recap, at this point we've obtained accurate MTU values at each
#   xfrm_dst.  The next step would be to start using it as
#   dst_pmtu(xfrm_dst).
#   
#   Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# ChangeSet
#   2005/03/06 21:27:44-08:00 herbert@gondor.apana.org.au 
#   [IPSEC]: Add route element to xfrm_dst
#   
#   This patch adds a pointer to the route corresponding to the specific
#   flow over the SA of an xfrm_dst that's being used.
#   
#   It also sets the next pointer of each xfrm_dst to the one above it.
#   This allows to traverse the list upwards from the bottom.
#    
#   Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/xfrm/xfrm_policy.c
#   2005/03/06 21:27:20-08:00 herbert@gondor.apana.org.au +5 -0
#   [IPSEC]: Add route element to xfrm_dst
#   
#   This patch adds a pointer to the route corresponding to the specific
#   flow over the SA of an xfrm_dst that's being used.
#   
#   It also sets the next pointer of each xfrm_dst to the one above it.
#   This allows to traverse the list upwards from the bottom.
#    
#   Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/ipv6/xfrm6_policy.c
#   2005/03/06 21:27:20-08:00 herbert@gondor.apana.org.au +33 -17
#   [IPSEC]: Add route element to xfrm_dst
#   
#   This patch adds a pointer to the route corresponding to the specific
#   flow over the SA of an xfrm_dst that's being used.
#   
#   It also sets the next pointer of each xfrm_dst to the one above it.
#   This allows to traverse the list upwards from the bottom.
#    
#   Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/ipv4/xfrm4_policy.c
#   2005/03/06 21:27:20-08:00 herbert@gondor.apana.org.au +33 -15
#   [IPSEC]: Add route element to xfrm_dst
#   
#   This patch adds a pointer to the route corresponding to the specific
#   flow over the SA of an xfrm_dst that's being used.
#   
#   It also sets the next pointer of each xfrm_dst to the one above it.
#   This allows to traverse the list upwards from the bottom.
#    
#   Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# include/net/xfrm.h
#   2005/03/06 21:27:20-08:00 herbert@gondor.apana.org.au +1 -0
#   [IPSEC]: Add route element to xfrm_dst
#   
#   This patch adds a pointer to the route corresponding to the specific
#   flow over the SA of an xfrm_dst that's being used.
#   
#   It also sets the next pointer of each xfrm_dst to the one above it.
#   This allows to traverse the list upwards from the bottom.
#    
#   Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# ChangeSet
#   2005/03/06 21:24:19-08:00 herbert@gondor.apana.org.au 
#   [IPSEC]: Add xfrm_state_mtu()
#   
#   This patch introduces the function xfrm_state_mtu which calculates
#   the MTU under a specific SA.  This function can be simplified once
#   we get rid all other uses of get_max_size as we can move the calculation
#   into the invidual SA type.
#   
#   Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/xfrm/xfrm_state.c
#   2005/03/06 21:23:53-08:00 herbert@gondor.apana.org.au +30 -0
#   [IPSEC]: Add xfrm_state_mtu()
#   
#   This patch introduces the function xfrm_state_mtu which calculates
#   the MTU under a specific SA.  This function can be simplified once
#   we get rid all other uses of get_max_size as we can move the calculation
#   into the invidual SA type.
#   
#   Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# include/net/xfrm.h
#   2005/03/06 21:23:53-08:00 herbert@gondor.apana.org.au +1 -0
#   [IPSEC]: Add xfrm_state_mtu()
#   
#   This patch introduces the function xfrm_state_mtu which calculates
#   the MTU under a specific SA.  This function can be simplified once
#   we get rid all other uses of get_max_size as we can move the calculation
#   into the invidual SA type.
#   
#   Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# ChangeSet
#   2005/03/06 21:03:21-08:00 herbert@gondor.apana.org.au 
#   [CRYPTO]: Mark myself as co-maintainer.
#   
#   James is stepping down for a while.
#   
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# MAINTAINERS
#   2005/03/06 21:02:57-08:00 herbert@gondor.apana.org.au +2 -3
#   [CRYPTO]: Mark myself as co-maintainer.
#   
#   James is stepping down for a while.
#   
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# ChangeSet
#   2005/03/06 20:50:43-08:00 davem@northbeach.davemloft.net.davemloft.net 
#   [SPARC64]: Fix semtimedop compat ipc code.
#   
#   The timeout pointer really does get passed in
#   as the fifth argument, not the third.
#   
#   Thanks to Willy Tarreau for noticing.
#   
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# arch/sparc64/kernel/sys_sparc32.c
#   2005/03/06 20:49:59-08:00 davem@northbeach.davemloft.net.davemloft.net +1 -1
#   [SPARC64]: Fix semtimedop compat ipc code.
# 
# ChangeSet
#   2005/03/06 20:48:08-08:00 davem@northbeach.davemloft.net.davemloft.net 
#   [SPARC64]: Update defconfig.
#   
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# arch/sparc64/defconfig
#   2005/03/06 20:47:44-08:00 davem@northbeach.davemloft.net.davemloft.net +15 -3
#   [SPARC64]: Update defconfig.
# 
# ChangeSet
#   2005/03/06 17:25:39-08:00 sfr@canb.auug.org.au 
#   [PATCH] Consolidate compat_sys_waitid
#   
#   This patch does:
#   	- consolidate the three implementations of compat_sys_waitid
#   	  (some were called sys32_waitid).
#   	- adds sys_waitid syscall to ppc
#   	- adds sys_waitid and compat_sys_waitid syscalls to ppc64
#   
#   I have left PARISC and MIPS to their own devices (by request).
#   
#   Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# kernel/compat.c
#   2005/03/06 15:58:58-08:00 sfr@canb.auug.org.au +31 -0
#   Consolidate compat_sys_waitid
# 
# include/linux/compat.h
#   2005/03/06 15:58:58-08:00 sfr@canb.auug.org.au +6 -1
#   Consolidate compat_sys_waitid
# 
# include/asm-ppc64/unistd.h
#   2005/03/06 15:58:58-08:00 sfr@canb.auug.org.au +2 -1
#   Consolidate compat_sys_waitid
# 
# include/asm-ppc/unistd.h
#   2005/03/06 15:58:58-08:00 sfr@canb.auug.org.au +2 -1
#   Consolidate compat_sys_waitid
# 
# arch/x86_64/ia32/sys_ia32.c
#   2005/03/06 15:58:58-08:00 sfr@canb.auug.org.au +0 -26
#   Consolidate compat_sys_waitid
# 
# arch/x86_64/ia32/ia32entry.S
#   2005/03/06 15:58:58-08:00 sfr@canb.auug.org.au +1 -1
#   Consolidate compat_sys_waitid
# 
# arch/sparc64/kernel/sys_sparc32.c
#   2005/03/06 15:58:58-08:00 sfr@canb.auug.org.au +0 -31
#   Consolidate compat_sys_waitid
# 
# arch/ppc64/kernel/misc.S
#   2005/03/06 15:58:58-08:00 sfr@canb.auug.org.au +2 -0
#   Consolidate compat_sys_waitid
# 
# arch/ppc/kernel/misc.S
#   2005/03/06 15:58:58-08:00 sfr@canb.auug.org.au +1 -0
#   Consolidate compat_sys_waitid
# 
# arch/ia64/ia32/sys_ia32.c
#   2005/03/06 15:58:57-08:00 sfr@canb.auug.org.au +0 -26
#   Consolidate compat_sys_waitid
# 
# arch/ia64/ia32/ia32_entry.S
#   2005/03/06 15:58:57-08:00 sfr@canb.auug.org.au +1 -1
#   Consolidate compat_sys_waitid
# 
# ChangeSet
#   2005/03/06 17:04:35-08:00 torvalds@ppc970.osdl.org 
#   Merge bk://gkernel.bkbits.net/net-drivers-2.6
#   into ppc970.osdl.org:/home/torvalds/v2.6/linux
# 
# MAINTAINERS
#   2005/03/06 17:04:30-08:00 torvalds@ppc970.osdl.org +0 -0
#   Auto merged
# 
# ChangeSet
#   2005/03/06 17:03:25-08:00 torvalds@ppc970.osdl.org 
#   Merge bk://bk.arm.linux.org.uk/linux-2.6-rmk
#   into ppc970.osdl.org:/home/torvalds/v2.6/linux
# 
# include/asm-arm/pgtable.h
#   2005/03/06 17:03:21-08:00 torvalds@ppc970.osdl.org +0 -0
#   Auto merged
# 
# ChangeSet
#   2005/03/06 16:59:24-08:00 torvalds@ppc970.osdl.org 
#   Merge bk://linux-dj.bkbits.net/agpgart
#   into ppc970.osdl.org:/home/torvalds/v2.6/linux
# 
# include/linux/agp_backend.h
#   2005/03/06 16:59:19-08:00 torvalds@ppc970.osdl.org +0 -1
#   Auto merged
# 
# drivers/char/agp/sis-agp.c
#   2005/03/06 16:59:19-08:00 torvalds@ppc970.osdl.org +0 -0
#   Auto merged
# 
# drivers/char/agp/generic.c
#   2005/03/06 16:59:19-08:00 torvalds@ppc970.osdl.org +0 -0
#   Auto merged
# 
# ChangeSet
#   2005/03/06 16:58:12-08:00 torvalds@ppc970.osdl.org 
#   Merge http://jfs.bkbits.net/linux-2.5
#   into ppc970.osdl.org:/home/torvalds/v2.6/linux
# 
# MAINTAINERS
#   2005/03/06 16:58:07-08:00 torvalds@ppc970.osdl.org +0 -0
#   Auto merged
# 
# ChangeSet
#   2005/03/06 16:56:53-08:00 torvalds@ppc970.osdl.org 
#   Merge bk://kernel.bkbits.net/davem/net-2.6
#   into ppc970.osdl.org:/home/torvalds/v2.6/linux
# 
# drivers/net/tg3.c
#   2005/03/06 16:56:48-08:00 torvalds@ppc970.osdl.org +0 -0
#   Auto merged
# 
# ChangeSet
#   2005/03/06 16:55:28-08:00 torvalds@ppc970.osdl.org 
#   Merge bk://kernel.bkbits.net/davem/flush_cache_page-2.6
#   into ppc970.osdl.org:/home/torvalds/v2.6/linux
# 
# mm/rmap.c
#   2005/03/06 16:55:23-08:00 torvalds@ppc970.osdl.org +0 -0
#   Auto merged
# 
# mm/memory.c
#   2005/03/06 16:55:23-08:00 torvalds@ppc970.osdl.org +0 -0
#   Auto merged
# 
# mm/fremap.c
#   2005/03/06 16:55:23-08:00 torvalds@ppc970.osdl.org +0 -0
#   Auto merged
# 
# ChangeSet
#   2005/03/06 16:52:04-08:00 dan@debian.org 
#   [PATCH] x86: fix TF bit corner case with ptrace and signals
#   
#   If a debugger set the TF bit, make sure to clear it when creating a
#   signal context.  Otherwise, TF will be incorrectly restored by
#   sigreturn.
#   
#   Signed-off-by: Daniel Jacobowitz <dan@debian.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/i386/kernel/signal.c
#   2005/03/06 12:36:41-08:00 dan@debian.org +12 -0
#   x86: fix TF bit corner case with ptrace and signals
# 
# ChangeSet
#   2005/03/06 18:11:09-05:00 davej@redhat.com 
#   [AGPGART] vfree() checking cleanups
#   
#   generic.c vfree() checking cleanups.
#   
#   Signed-off by: James Lamanna <jlamanna@gmail.com>
#   Signed-off-by: Domen Puncer <domen@coderock.org>
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# drivers/char/agp/generic.c
#   2005/03/06 18:11:00-05:00 davej@redhat.com +1 -3
#   [AGPGART] vfree() checking cleanups
#   
#   generic.c vfree() checking cleanups.
#   
#   Signed-off by: James Lamanna <jlamanna@gmail.com>
#   Signed-off-by: Domen Puncer <domen@coderock.org>
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# ChangeSet
#   2005/03/06 23:07:50+00:00 ben-linux@org.rmk.(none) 
#   [ARM PATCH] 2515/1: S3C2410 - allow serial to use fclk on s3c2440
#   
#   Patch from Ben Dooks
#   
#   This patch extends the s3c2410 serial driver to allow it
#   to use fclk and correctly determine the uart dividers. The
#   necessary defines are added to the serial headers as well.
#   Also modified is the header to point at the current
#   Simtec linux pages, as well as extend the copyright.
#   
#   Signed-off-by: Ben Dooks
#   Signed-off-by: Russell King
# 
# include/asm-arm/arch-s3c2410/regs-serial.h
#   2005/03/06 12:59:10+00:00 ben-linux@org.rmk.(none) +5 -0
#   [PATCH] 2515/1: S3C2410 - allow serial to use fclk on s3c2440
# 
# drivers/serial/s3c2410.c
#   2005/03/06 14:36:49+00:00 ben-linux@org.rmk.(none) +116 -25
#   [PATCH] 2515/1: S3C2410 - allow serial to use fclk on s3c2440
# 
# ChangeSet
#   2005/03/06 22:33:13+00:00 rmk@flint.arm.linux.org.uk 
#   [ARM] Update mach-types from website.
#   
#   Signed-off-by: Russell King <rmk@arm.linux.org.uk>
# 
# arch/arm/tools/mach-types
#   2005/03/06 22:28:32+00:00 rmk@flint.arm.linux.org.uk +44 -3
#   Update from web site.
# 
# ChangeSet
#   2005/03/06 19:53:37+00:00 rmk@flint.arm.linux.org.uk 
#   [ARM] Simplify /proc/driver/rtc procfs interface.
#   
#   The read method doesn't need to calculate eof/start offsets.
#   
#   Signed-off-by: Russell King <rmk@arm.linux.org.uk>
# 
# arch/arm/common/rtctime.c
#   2005/03/06 19:49:31+00:00 rmk@flint.arm.linux.org.uk +1 -8
#   Simplify /proc/driver/rtc procfs interface.
#   
#   The read method doesn't need to calculate eof/start offsets.
# 
# ChangeSet
#   2005/03/06 19:05:01+00:00 rmk@flint.arm.linux.org.uk 
#   [ARM] Add validation function for struct rtc_time
#   
#   Signed-off-by: Russell King <rmk@arm.linux.org.uk>
# 
# include/asm-arm/rtc.h
#   2005/03/06 19:00:53+00:00 rmk@flint.arm.linux.org.uk +1 -0
#   Add new function prototype for rtc_valid_tm()
# 
# arch/arm/common/rtctime.c
#   2005/03/06 19:00:52+00:00 rmk@flint.arm.linux.org.uk +20 -9
#   Add rtc_valid_tm() to check validity of a struct rtc_time.
#   Move check for valid rtc_time into rtc_set_time.
# 
# ChangeSet
#   2005/03/05 21:23:33-08:00 lethal@linux-sh.org 
#   [SH]: Cache flush simplifications after flush_cache_page() arg change.
#   
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# arch/sh64/mm/cache.c
#   2005/03/05 21:23:02-08:00 lethal@linux-sh.org +1 -6
#   [SH]: Cache flush simplifications after flush_cache_page() arg change.
# 
# arch/sh/mm/cache-sh4.c
#   2005/03/05 21:23:02-08:00 lethal@linux-sh.org +1 -2
#   [SH]: Cache flush simplifications after flush_cache_page() arg change.
# 
# ChangeSet
#   2005/03/05 21:15:21-08:00 davem@picasso.davemloft.net 
#   Merge davem@nuts:/disk1/BK/flush_cache_page-2.6
#   into picasso.davemloft.net:/home/davem/src/BK/flush_cache_page-2.6
# 
# mm/rmap.c
#   2005/03/05 21:15:17-08:00 davem@picasso.davemloft.net +0 -0
#   Auto merged
# 
# mm/memory.c
#   2005/03/05 21:15:17-08:00 davem@picasso.davemloft.net +0 -0
#   Auto merged
# 
# include/asm-ppc64/cacheflush.h
#   2005/03/05 21:15:17-08:00 davem@picasso.davemloft.net +0 -0
#   Auto merged
# 
# include/asm-parisc/cacheflush.h
#   2005/03/05 21:15:17-08:00 davem@picasso.davemloft.net +0 -0
#   Auto merged
# 
# include/asm-arm/cacheflush.h
#   2005/03/05 21:15:17-08:00 davem@picasso.davemloft.net +0 -0
#   Auto merged
# 
# fs/binfmt_elf.c
#   2005/03/05 21:15:17-08:00 davem@picasso.davemloft.net +0 -0
#   Auto merged
# 
# ChangeSet
#   2005/03/05 20:52:11-08:00 davem@nuts.davemloft.net 
#   Merge http://linux-mh.bkbits.net/bluetooth-2.6
#   into nuts.davemloft.net:/disk1/BK/net-2.6
# 
# MAINTAINERS
#   2005/03/05 20:51:58-08:00 davem@nuts.davemloft.net +0 -0
#   Auto merged
# 
# ChangeSet
#   2005/03/05 20:48:01-08:00 davem@picasso.davemloft.net 
#   Merge davem@nuts:/disk1/BK/set_pte-2.6
#   into picasso.davemloft.net:/home/davem/src/BK/set_pte-2.6
# 
# mm/swapfile.c
#   2005/03/05 20:47:57-08:00 davem@picasso.davemloft.net +0 -0
#   Auto merged
# 
# mm/rmap.c
#   2005/03/05 20:47:57-08:00 davem@picasso.davemloft.net +0 -0
#   Auto merged
# 
# mm/mremap.c
#   2005/03/05 20:47:57-08:00 davem@picasso.davemloft.net +0 -0
#   Auto merged
# 
# mm/memory.c
#   2005/03/05 20:47:57-08:00 davem@picasso.davemloft.net +0 -0
#   Auto merged
# 
# include/asm-arm/pgtable.h
#   2005/03/05 20:47:56-08:00 davem@picasso.davemloft.net +0 -0
#   Auto merged
# 
# fs/exec.c
#   2005/03/05 20:47:56-08:00 davem@picasso.davemloft.net +0 -0
#   Auto merged
# 
# arch/ppc64/mm/init.c
#   2005/03/05 20:47:56-08:00 davem@picasso.davemloft.net +0 -0
#   Auto merged
# 
# arch/ppc64/mm/hugetlbpage.c
#   2005/03/05 20:47:56-08:00 davem@picasso.davemloft.net +0 -0
#   Auto merged
# 
# ChangeSet
#   2005/03/05 20:43:56-08:00 davem@nuts.davemloft.net 
#   Merge nuts.davemloft.net:/disk1/BK/net-2.6.12
#   into nuts.davemloft.net:/disk1/BK/net-2.6
# 
# net/ipv4/route.c
#   2005/03/05 20:43:44-08:00 davem@nuts.davemloft.net +0 -0
#   Auto merged
# 
# include/linux/random.h
#   2005/03/05 20:43:43-08:00 davem@nuts.davemloft.net +0 -0
#   Auto merged
# 
# drivers/net/ixgb/ixgb_main.c
#   2005/03/05 20:43:43-08:00 davem@nuts.davemloft.net +0 -0
#   Auto merged
# 
# drivers/net/e1000/e1000_main.c
#   2005/03/05 20:43:43-08:00 davem@nuts.davemloft.net +0 -0
#   Auto merged
# 
# drivers/char/random.c
#   2005/03/05 20:43:43-08:00 davem@nuts.davemloft.net +0 -0
#   Auto merged
# 
# ChangeSet
#   2005/03/05 16:26:40-08:00 torvalds@evo.osdl.org 
#   x86: make put_user() out-of-line
#   
#   This makes the resulting assembly not only easier to read,
#   it results in roughly a 0.5% savings in code size.
#   
#   Fixes from Richard Henderson for the original broken asm
#   constraints.
# 
# arch/i386/lib/putuser.S
#   2005/03/05 16:26:28-08:00 torvalds@evo.osdl.org +87 -0
# 
# include/asm-i386/uaccess.h
#   2005/03/05 16:26:28-08:00 torvalds@evo.osdl.org +27 -13
#   x86: make put_user() out-of-line
# 
# arch/i386/lib/putuser.S
#   2005/03/05 16:26:28-08:00 torvalds@evo.osdl.org +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/arch/i386/lib/putuser.S
# 
# arch/i386/lib/Makefile
#   2005/03/05 16:26:28-08:00 torvalds@evo.osdl.org +1 -1
#   x86: make put_user() out-of-line
# 
# arch/i386/kernel/i386_ksyms.c
#   2005/03/05 16:26:28-08:00 torvalds@evo.osdl.org +5 -0
#   x86: make put_user() out-of-line
# 
# ChangeSet
#   2005/03/05 18:11:05-05:00 jgarzik@pobox.com 
#   Merge pobox.com:/garz/repo/netdev-2.6/mips
#   into pobox.com:/garz/repo/net-drivers-2.6
# 
# drivers/net/s2io.c
#   2005/03/05 18:11:02-05:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# drivers/net/Kconfig
#   2005/03/05 18:11:02-05:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# ChangeSet
#   2005/03/05 18:10:00-05:00 jgarzik@pobox.com 
#   Merge pobox.com:/garz/repo/netdev-2.6/sk98lin
#   into pobox.com:/garz/repo/net-drivers-2.6
# 
# drivers/net/sk98lin/skge.c
#   2005/03/05 18:09:57-05:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# ChangeSet
#   2005/03/05 18:08:48-05:00 jgarzik@pobox.com 
#   Merge pobox.com:/garz/repo/netdev-2.6/wan-fixes
#   into pobox.com:/garz/repo/net-drivers-2.6
# 
# MAINTAINERS
#   2005/03/05 18:08:45-05:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# ChangeSet
#   2005/03/05 18:07:32-05:00 jgarzik@pobox.com 
#   Merge pobox.com:/garz/repo/netdev-2.6/pcnet32
#   into pobox.com:/garz/repo/net-drivers-2.6
# 
# include/linux/pci_ids.h
#   2005/03/05 18:07:29-05:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# ChangeSet
#   2005/03/05 17:55:29-05:00 galak@freescale.com 
#   [PATCH] initialize a spin lock in gianfar driver
#   
#   Initialize the mdio_lock spin lock in mii_info struct, which is otherwise
#   accessed prior to initialization.
#   
#   Signed-off-by: Jaka Mocnik <jaka@activetools.si>
#   Signed-off-by: Kumar Gala <kumar.gala@freescale.com>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/gianfar.c
#   2005/03/05 00:03:27-05:00 galak@freescale.com +2 -0
#   initialize a spin lock in gianfar driver
# 
# ChangeSet
#   2005/03/05 17:50:51-05:00 lethal@linux-sh.org 
#   [PATCH] net: port smc91x to SH4-202 Microdev.
#   
#   Here is a patch that gets the smc91x driver working on the
#   SH4-202 Microdev board.
#   
#   Signed-off-by: Paul Mundt <lethal@linux-sh.org>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/smc91x.h
#   2005/03/04 13:40:57-05:00 lethal@linux-sh.org +19 -0
#   net: port smc91x to SH4-202 Microdev.
# 
# drivers/net/Kconfig
#   2005/03/04 13:40:57-05:00 lethal@linux-sh.org +1 -1
#   net: port smc91x to SH4-202 Microdev.
# 
# ChangeSet
#   2005/03/05 13:26:50-08:00 torvalds@ppc970.osdl.org 
#   Merge bk://gkernel.bkbits.net/net-drivers-2.6
#   into ppc970.osdl.org:/home/torvalds/v2.6/linux
# 
# drivers/net/typhoon.c
#   2005/03/05 13:26:45-08:00 torvalds@ppc970.osdl.org +0 -0
#   Auto merged
# 
# drivers/net/Kconfig
#   2005/03/05 13:26:45-08:00 torvalds@ppc970.osdl.org +0 -0
#   Auto merged
# 
# ChangeSet
#   2005/03/05 09:37:01-08:00 yuasa@hh.iij4u.or.jp 
#   [PATCH] mips: update CMU
#   
#   This patch updates cmu.c to get the resource by standard method.
#   
#   Signed-off-by: Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/mips/vr41xx/common/cmu.c
#   2005/03/04 22:41:56-08:00 yuasa@hh.iij4u.or.jp +47 -20
#   mips: update CMU
# 
# arch/mips/pci/pci-vr41xx.c
#   2005/03/04 22:41:56-08:00 yuasa@hh.iij4u.or.jp +1 -1
#   mips: update CMU
# 
# ChangeSet
#   2005/03/05 09:36:48-08:00 yuasa@hh.iij4u.or.jp 
#   [PATCH] mips: calculate clock at any time
#   
#   This patch changes bcu.c to calculate clock at any time.  Because clock can
#   be changed.  Moreover, EXPORT_SYMBOL_GPLs are added to it.
#   
#   Signed-off-by: Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/asm-mips/vr41xx/vr41xx.h
#   2005/03/04 22:41:55-08:00 yuasa@hh.iij4u.or.jp +1 -0
#   mips: calculate clock at any time
# 
# arch/mips/vr41xx/common/ksyms.c
#   2005/03/04 22:41:55-08:00 yuasa@hh.iij4u.or.jp +0 -3
#   mips: calculate clock at any time
# 
# arch/mips/vr41xx/common/init.c
#   2005/03/04 22:41:55-08:00 yuasa@hh.iij4u.or.jp +16 -1
#   mips: calculate clock at any time
# 
# arch/mips/vr41xx/common/bcu.c
#   2005/03/04 22:41:55-08:00 yuasa@hh.iij4u.or.jp +10 -15
#   mips: calculate clock at any time
# 
# ChangeSet
#   2005/03/05 09:36:33-08:00 yuasa@hh.iij4u.or.jp 
#   [PATCH] mips: add TANBAC TB0219 base board driver
#   
#   This patch adds GPIO/LED/DIPSW driver for TANBAC TB0219.
#   
#   Signed-off-by: Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/char/tb0219.c
#   2005/03/05 09:36:24-08:00 yuasa@hh.iij4u.or.jp +347 -0
# 
# drivers/char/Makefile
#   2005/03/04 22:41:55-08:00 yuasa@hh.iij4u.or.jp +1 -0
#   mips: add TANBAC TB0219 base board driver
# 
# drivers/char/Kconfig
#   2005/03/04 22:41:55-08:00 yuasa@hh.iij4u.or.jp +4 -0
#   mips: add TANBAC TB0219 base board driver
# 
# arch/mips/vr41xx/tanbac-tb0229/Makefile
#   2005/03/04 22:41:55-08:00 yuasa@hh.iij4u.or.jp +0 -2
#   mips: add TANBAC TB0219 base board driver
# 
# arch/mips/Kconfig
#   2005/03/04 22:41:55-08:00 yuasa@hh.iij4u.or.jp +0 -4
#   mips: add TANBAC TB0219 base board driver
# 
# drivers/char/tb0219.c
#   2005/03/05 09:36:24-08:00 yuasa@hh.iij4u.or.jp +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/drivers/char/tb0219.c
# 
# BitKeeper/deleted/.del-tb0219.c~8b2edbef490c5193
#   2005/03/05 09:36:24-08:00 yuasa@hh.iij4u.or.jp +0 -0
#   Delete: arch/mips/vr41xx/tanbac-tb0229/tb0219.c
# 
# ChangeSet
#   2005/03/05 09:35:39-08:00 moilanen@austin.ibm.com 
#   [PATCH] ppc64: offb remapped address
#   
#   The offb code did not take into account a remapped pci address.  Adding in
#   the pci_mem_offset fixed a DSI in offb.
#   
#   Signed-off-by: Jake Moilanen <moilanen@austin.ibm.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/video/offb.c
#   2005/03/04 22:41:55-08:00 moilanen@austin.ibm.com +10 -1
#   ppc64: offb remapped address
# 
# ChangeSet
#   2005/03/05 09:35:25-08:00 benh@kernel.crashing.org 
#   [PATCH] ppc64: Fix zImage wrapper incorrect size to flush_cache()
#   
#   This patch fixes a bug in the ppc64 zImage wrapper causing it to pass an
#   incorrect size to flush_cache() when flushing the data and instruction
#   caches prior to jumping to the kernel entry.  This causes crashes on
#   firmare environment that do strict MMU mapping only of actually allocated
#   areas
#   
#   Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/ppc64/boot/main.c
#   2005/03/04 22:41:55-08:00 benh@kernel.crashing.org +1 -1
#   ppc64: Fix zImage wrapper incorrect size to flush_cache()
# 
# ChangeSet
#   2005/03/05 09:35:12-08:00 benh@kernel.crashing.org 
#   [PATCH] ppc64: Fix thinko in prom_init.c
#   
#   (It's a real bug, but I suspect it doesn't trigger normally as we tend
#   to allocate the initrd low, but it should be fixed anyway).
#   
#   This patch fixes an error in prom_init.c in the check for the initrd
#   location vs. the memory allocation mecanism. 
#   
#   Signed-off-by: Arnd Bergmann <arndb@de.ibm.com>
#   Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/ppc64/kernel/prom_init.c
#   2005/03/04 22:41:55-08:00 benh@kernel.crashing.org +1 -2
#   ppc64: Fix thinko in prom_init.c
# 
# ChangeSet
#   2005/03/05 09:34:58-08:00 david@gibson.dropbear.id.au 
#   [PATCH] ppc64: functions to reserve performance monitor hardware
#   
#   The PPC64 interrupt code includes a hook to call when an exception
#   from the performance monitor unit occurs.  However, there's no way of
#   reserving the hook properly, so if more than one bit of code tries to
#   use it things will get ugly.  Currently oprofile is the only user, but
#   there are likely to be more in future e.g. perfctr, if and when it
#   reaches a fit state for merging.
#   
#   This patch creates functions to reserve and release the performance
#   monitor hardware (including its interrupt), and makes oprofile use
#   them.  It also creates a new arch/ppc64/kernel/pmc.c, in which we can
#   put any future helper functions for handling the performance monitor
#   counters.
#   
#   Signed-off-by: David Gibson <dwg@au1.ibm.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/asm-ppc64/pmc.h
#   2005/03/04 22:41:55-08:00 david@gibson.dropbear.id.au +29 -0
#   ppc64: functions to reserve performance monitor hardware
# 
# include/asm-ppc64/pmc.h
#   2005/03/04 22:41:55-08:00 david@gibson.dropbear.id.au +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/include/asm-ppc64/pmc.h
# 
# arch/ppc64/oprofile/common.c
#   2005/03/04 22:41:55-08:00 david@gibson.dropbear.id.au +7 -11
#   ppc64: functions to reserve performance monitor hardware
# 
# arch/ppc64/kernel/traps.c
#   2005/03/04 22:41:55-08:00 david@gibson.dropbear.id.au +2 -12
#   ppc64: functions to reserve performance monitor hardware
# 
# arch/ppc64/kernel/pmc.c
#   2005/03/04 22:41:55-08:00 david@gibson.dropbear.id.au +64 -0
#   ppc64: functions to reserve performance monitor hardware
# 
# arch/ppc64/kernel/Makefile
#   2005/03/04 22:41:55-08:00 david@gibson.dropbear.id.au +1 -1
#   ppc64: functions to reserve performance monitor hardware
# 
# arch/ppc64/kernel/pmc.c
#   2005/03/04 22:41:55-08:00 david@gibson.dropbear.id.au +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/arch/ppc64/kernel/pmc.c
# 
# ChangeSet
#   2005/03/05 09:34:42-08:00 olh@suse.de 
#   [PATCH] ppc64: use vmlinux during make install on ppc64
#   
#   make install passes the zImage to the installkernel script.  When an initrd is
#   used, this script has to pull out the vmlinux from the zImage because yaboot
#   can not boot a zImage+initrd combo.  It can only handle vmlinux+initrd or
#   zImage.initrd.  Its simple to just pass the plain vmlinux instead.
#   
#   Signed-off-by: Olaf Hering <olh@suse.de>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/ppc64/boot/install.sh
#   2005/03/04 22:41:55-08:00 olh@suse.de +2 -1
#   ppc64: use vmlinux during make install on ppc64
# 
# arch/ppc64/boot/Makefile
#   2005/03/04 22:41:55-08:00 olh@suse.de +2 -2
#   ppc64: use vmlinux during make install on ppc64
# 
# arch/ppc64/Makefile
#   2005/03/04 22:41:55-08:00 olh@suse.de +9 -3
#   ppc64: use vmlinux during make install on ppc64
# 
# ChangeSet
#   2005/03/05 09:34:28-08:00 olh@suse.de 
#   [PATCH] ppc64: disable HMT for RS64 cpus
#   
#   Hardware multithreading for RS64 cpus is currently broken.  Anton sent me a
#   patch a few weeks ago, but it did not work.  So just hide the config option
#   for the time being.
#   
#   Signed-off-by: Olaf Hering <olh@suse.de>
#   Acked-by: Paul Mackerras <paulus@samba.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/ppc64/Kconfig
#   2005/03/04 22:41:54-08:00 olh@suse.de +4 -1
#   ppc64: disable HMT for RS64 cpus
# 
# ChangeSet
#   2005/03/05 09:34:14-08:00 akpm@osdl.org 
#   [PATCH] ppc64: generic hotplug cpu support fix
#   
#   Fix a false-positive from the smp_processor_id() debugging code.  Idle threads
#   are per-cpu anwyay.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/ppc64/kernel/idle.c
#   2005/03/04 22:41:54-08:00 akpm@osdl.org +1 -1
#   ppc64: generic hotplug cpu support fix
# 
# ChangeSet
#   2005/03/05 09:34:00-08:00 zwane@arm.linux.org.uk 
#   [PATCH] ppc64: generic hotplug cpu support
#   
#   Patch provides a generic hotplug cpu implementation, with the only current
#   user being pmac.  This doesn't replace real hotplug code as is currently
#   used by LPAR systems.  Ben i can add the additional pmac specific code to
#   put the processor into a sleeping state seperately.  Thanks to Nathan for
#   testing.
#   
#   Signed-off-by: Zwane Mwaikambo <zwane@arm.linux.org.uk>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/asm-ppc64/smp.h
#   2005/03/04 22:41:54-08:00 zwane@arm.linux.org.uk +8 -1
#   ppc64: generic hotplug cpu support
# 
# include/asm-ppc64/machdep.h
#   2005/03/04 22:41:54-08:00 zwane@arm.linux.org.uk +1 -0
#   ppc64: generic hotplug cpu support
# 
# arch/ppc64/kernel/sysfs.c
#   2005/03/04 22:41:54-08:00 zwane@arm.linux.org.uk +2 -4
#   ppc64: generic hotplug cpu support
# 
# arch/ppc64/kernel/smp.c
#   2005/03/04 22:41:54-08:00 zwane@arm.linux.org.uk +80 -0
#   ppc64: generic hotplug cpu support
# 
# arch/ppc64/kernel/setup.c
#   2005/03/04 22:41:54-08:00 zwane@arm.linux.org.uk +0 -3
#   ppc64: generic hotplug cpu support
# 
# arch/ppc64/kernel/pmac_smp.c
#   2005/03/04 22:41:54-08:00 zwane@arm.linux.org.uk +5 -0
#   ppc64: generic hotplug cpu support
# 
# arch/ppc64/kernel/pmac_setup.c
#   2005/03/04 22:41:54-08:00 zwane@arm.linux.org.uk +3 -0
#   ppc64: generic hotplug cpu support
# 
# arch/ppc64/kernel/pSeries_setup.c
#   2005/03/04 22:41:54-08:00 zwane@arm.linux.org.uk +3 -2
#   ppc64: generic hotplug cpu support
# 
# arch/ppc64/kernel/irq.c
#   2005/03/04 22:41:54-08:00 zwane@arm.linux.org.uk +29 -0
#   ppc64: generic hotplug cpu support
# 
# arch/ppc64/kernel/idle.c
#   2005/03/04 23:17:15-08:00 zwane@arm.linux.org.uk +4 -0
#   ppc64: generic hotplug cpu support
# 
# arch/ppc64/Kconfig
#   2005/03/04 23:17:15-08:00 zwane@arm.linux.org.uk +1 -1
#   ppc64: generic hotplug cpu support
# 
# ChangeSet
#   2005/03/05 09:33:46-08:00 akpm@osdl.org 
#   [PATCH] ppc64-implement-a-vdso-and-use-it-for-signal-trampoline gas workaround
#   
#   I cannot find a version of binutils which doesn't either do
#   
#   arch/ppc64/kernel/vdso32/gettimeofday.S: Assembler messages:
#   arch/ppc64/kernel/vdso32/gettimeofday.S:33: Error: syntax error; found `@' but expected `,'
#   
#   or
#   
#   arch/ppc64/kernel/vdso32/gettimeofday.S: Assembler messages:
#   arch/ppc64/kernel/vdso32/gettimeofday.S:33: Internal error, aborting at ../../gas/config/tc-ppc.c line 2658 in md_assemble
#   
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/ppc64/kernel/vdso32/gettimeofday.S
#   2005/03/04 22:41:54-08:00 akpm@osdl.org +2 -2
#   ppc64-implement-a-vdso-and-use-it-for-signal-trampoline gas workaround
# 
# arch/ppc64/kernel/vdso32/datapage.S
#   2005/03/04 22:41:54-08:00 akpm@osdl.org +1 -1
#   ppc64-implement-a-vdso-and-use-it-for-signal-trampoline gas workaround
# 
# ChangeSet
#   2005/03/05 09:33:32-08:00 benh@kernel.crashing.org 
#   [PATCH] ppc64: Implement a vDSO and use it for signal trampoline
#   
#   This patch adds to the ppc64 kernel a virtual .so (vDSO) that is mapped
#   into every process space, similar to the x86 vsyscall page.  However, the
#   implementation is very different (and doesn't use the gate area mecanism). 
#   Actually, it contains two implementations, a 32 bits and a 64 bits one.
#   
#   These vDSO's are currently mapped at 0x100000 (+1Mb) when possible (when a
#   process load section isn't already there).  In the future, we can randomize
#   that address, or even imagine having a special phdr entry letting apps that
#   wnat finer control over their address space to put it elsewhere (or not at
#   all).
#   
#   The implementation adds a hook to binfmt_elf to let the architecture add a
#   real VMA to the process space instead of using the gate area mecanism.
#   This mecanism wasn't very suitable for ppc, we couldn't just "shove" PTE
#   entries mapping kernel addresses into userland without expensive changes to
#   our hash table management.  Instead, I made the vDSO be a normal VMA which,
#   additionally, means it supports copy-on-write semantics if made writable
#   via ptrace/mprotect, thus allowing breakpoints in the vDSO code.
#   
#   The current implementation of the vDSOs contain the signal trampolines with
#   appropriate DWARF informations, which enable us to use non-executable
#   stacks (patches to come later) along with a few more functions that we hope
#   glibc will soon make good use of (this is the "hard" part now :) Note that
#   the symbols exposed by the vDSO aren't "normal" function symbols, apps
#   can't be expected to link against them directly, the vDSO's are both seen
#   as if they were linked at 0 and the symbols just contain offsets to the
#   various functions.  This is done on purpose to avoid a relocation step
#   (ppc64 functions normally have descriptors with abs addresses in them). 
#   When glibc uses those functions, it's expected to use it's own trampolines
#   that know how to reach them.
#   
#   In some cases, the vDSO contains several versions of a given function (for
#   various CPUs), the kernel will "patch" the symbol table at boot to make it
#   point to the appropriate one transparently.  What is currently implemented
#   is:
#   
#    -  int __kernel_gettimeofday(struct timeval *tv, struct timezone *tz);
#   
#    This is a fully userland implementation of gettimeofday, with no barriers
#    and no locks, and providing 100% equivalent results to the syscall version
#   
#    - void __kernel_sync_dicache(unsigned long start, unsigned long end)
#   
#    This function sync's the data and instruction caches (for making data
#    executable), it is expected that userland loaders use this instead of
#    doing it themselves, as the kernel will provide optimized versions for the
#    current CPU.  Currently, the vDSO procides a full one for all CPUs prior
#    to POWER5 and a nop one for POWER5 which implements hardware snooping at
#    the L1 level.  In the future, an intermediate implementation may be done
#    for the POWER4 and 970 which don't need the "dcbst" loop (the L1D cache is
#    write-through on those).
#   
#    - void *__kernel_get_syscall_map(unsigned int *syscall_count);
#   
#    Returns a pointer to a map of implemented syscalls on the currently
#    running kernel.  The map is agnostic to the size of "long", unlike kernel
#    bitops, it stores bits from top to bottom so that memory actually contains
#    a linear bitmap check for syscall N by testing bit (0x80000000 >> (N &
#    0x1f)) of * 32 bits int at N >> 5.
#   
#   Note about backward compatibility issues: A bug in the ppc64 libgcc
#   unwinder makes it unable to unwind stacks properly accross signals if the
#   signal trampoline isn't on the stack.  This has been fixed in CVS for gcc
#   4.0 and will be soon on the stable branch, but the problem exist will all
#   currently used versions.
#   
#   That means that until glibc gets the patch to enable it's use of the vDSO
#   symbols for the DWARF unwinder (rather trivial patch that will be pushed to
#   glibc CVS soon hopefully), unwinding from a signal handler will not work
#   for 64 bits applications.
#   
#   I consider this as a non-issue though as a patch is about to be produced,
#   which can easily get pushed to "live" distros like debian, gentoo, fedora,
#   etc...  soon enough (it breaks compatilbity with kernels below 2.4.20
#   unfortunately as our signal stack layout changed, crap crap crap), as there
#   are few 64 bits applications out there (expect gentoo), as it's only really
#   an issue with C++ code relying on throwing exceptions out of signal
#   handlers (extremely rare it seems), and as "release" distros like SLES or
#   RHEL will probably have the vDSO enabled glibc _and_ the unwinder fix by
#   the time they release a version with a 2.6.11 or 2.6.12 kernel anyway :)
#   
#   So far, I yet have to see an app failing because of that...
#   
#   Finally, many many many thanks to Alan Modra for writing the DWARF
#   information of the signal handlers and debugging the libgcc issues !
#   
#   Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/asm-ppc64/vdso.h
#   2005/03/04 22:41:54-08:00 benh@kernel.crashing.org +83 -0
#   ppc64: Implement a vDSO and use it for signal trampoline
# 
# arch/ppc64/kernel/vdso64/vdso64_wrapper.S
#   2005/03/04 22:41:54-08:00 benh@kernel.crashing.org +13 -0
#   ppc64: Implement a vDSO and use it for signal trampoline
# 
# arch/ppc64/kernel/vdso64/vdso64.lds.S
#   2005/03/04 22:41:54-08:00 benh@kernel.crashing.org +110 -0
#   ppc64: Implement a vDSO and use it for signal trampoline
# 
# arch/ppc64/kernel/vdso64/sigtramp.S
#   2005/03/04 22:41:54-08:00 benh@kernel.crashing.org +294 -0
#   ppc64: Implement a vDSO and use it for signal trampoline
# 
# arch/ppc64/kernel/vdso64/gettimeofday.S
#   2005/03/04 22:41:54-08:00 benh@kernel.crashing.org +91 -0
#   ppc64: Implement a vDSO and use it for signal trampoline
# 
# arch/ppc64/kernel/vdso64/datapage.S
#   2005/03/04 22:41:54-08:00 benh@kernel.crashing.org +68 -0
#   ppc64: Implement a vDSO and use it for signal trampoline
# 
# arch/ppc64/kernel/vdso64/cacheflush.S
#   2005/03/04 22:41:54-08:00 benh@kernel.crashing.org +64 -0
#   ppc64: Implement a vDSO and use it for signal trampoline
# 
# arch/ppc64/kernel/vdso64/Makefile
#   2005/03/04 22:41:54-08:00 benh@kernel.crashing.org +35 -0
#   ppc64: Implement a vDSO and use it for signal trampoline
# 
# arch/ppc64/kernel/vdso32/vdso32_wrapper.S
#   2005/03/04 22:41:54-08:00 benh@kernel.crashing.org +13 -0
#   ppc64: Implement a vDSO and use it for signal trampoline
# 
# arch/ppc64/kernel/vdso32/vdso32.lds.S
#   2005/03/04 22:41:54-08:00 benh@kernel.crashing.org +111 -0
#   ppc64: Implement a vDSO and use it for signal trampoline
# 
# arch/ppc64/kernel/vdso32/sigtramp.S
#   2005/03/04 22:41:54-08:00 benh@kernel.crashing.org +300 -0
#   ppc64: Implement a vDSO and use it for signal trampoline
# 
# arch/ppc64/kernel/vdso32/gettimeofday.S
#   2005/03/04 23:17:16-08:00 benh@kernel.crashing.org +139 -0
#   ppc64: Implement a vDSO and use it for signal trampoline
# 
# arch/ppc64/kernel/vdso32/datapage.S
#   2005/03/04 23:17:16-08:00 benh@kernel.crashing.org +68 -0
#   ppc64: Implement a vDSO and use it for signal trampoline
# 
# arch/ppc64/kernel/vdso32/Makefile
#   2005/03/04 22:41:54-08:00 benh@kernel.crashing.org +36 -0
#   ppc64: Implement a vDSO and use it for signal trampoline
# 
# arch/ppc64/kernel/vdso.c
#   2005/03/04 22:41:54-08:00 benh@kernel.crashing.org +614 -0
#   ppc64: Implement a vDSO and use it for signal trampoline
# 
# include/asm-ppc64/vdso.h
#   2005/03/04 22:41:54-08:00 benh@kernel.crashing.org +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/include/asm-ppc64/vdso.h
# 
# include/asm-ppc64/time.h
#   2005/03/04 22:41:54-08:00 benh@kernel.crashing.org +1 -1
#   ppc64: Implement a vDSO and use it for signal trampoline
# 
# include/asm-ppc64/systemcfg.h
#   2005/03/04 22:41:54-08:00 benh@kernel.crashing.org +7 -1
#   ppc64: Implement a vDSO and use it for signal trampoline
# 
# include/asm-ppc64/processor.h
#   2005/03/04 22:41:54-08:00 benh@kernel.crashing.org +3 -3
#   ppc64: Implement a vDSO and use it for signal trampoline
# 
# include/asm-ppc64/page.h
#   2005/03/04 22:41:54-08:00 benh@kernel.crashing.org +3 -0
#   ppc64: Implement a vDSO and use it for signal trampoline
# 
# include/asm-ppc64/elf.h
#   2005/03/04 22:41:54-08:00 benh@kernel.crashing.org +12 -0
#   ppc64: Implement a vDSO and use it for signal trampoline
# 
# include/asm-ppc64/a.out.h
#   2005/03/04 22:41:54-08:00 benh@kernel.crashing.org +4 -7
#   ppc64: Implement a vDSO and use it for signal trampoline
# 
# fs/binfmt_elf.c
#   2005/03/04 22:41:54-08:00 benh@kernel.crashing.org +8 -0
#   ppc64: Implement a vDSO and use it for signal trampoline
# 
# arch/ppc64/mm/init.c
#   2005/03/04 22:41:54-08:00 benh@kernel.crashing.org +3 -0
#   ppc64: Implement a vDSO and use it for signal trampoline
# 
# arch/ppc64/kernel/vdso64/vdso64_wrapper.S
#   2005/03/04 22:41:54-08:00 benh@kernel.crashing.org +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/arch/ppc64/kernel/vdso64/vdso64_wrapper.S
# 
# arch/ppc64/kernel/vdso64/vdso64.lds.S
#   2005/03/04 22:41:54-08:00 benh@kernel.crashing.org +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/arch/ppc64/kernel/vdso64/vdso64.lds.S
# 
# arch/ppc64/kernel/vdso64/sigtramp.S
#   2005/03/04 22:41:54-08:00 benh@kernel.crashing.org +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/arch/ppc64/kernel/vdso64/sigtramp.S
# 
# arch/ppc64/kernel/vdso64/gettimeofday.S
#   2005/03/04 22:41:54-08:00 benh@kernel.crashing.org +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/arch/ppc64/kernel/vdso64/gettimeofday.S
# 
# arch/ppc64/kernel/vdso64/datapage.S
#   2005/03/04 22:41:54-08:00 benh@kernel.crashing.org +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/arch/ppc64/kernel/vdso64/datapage.S
# 
# arch/ppc64/kernel/vdso64/cacheflush.S
#   2005/03/04 22:41:54-08:00 benh@kernel.crashing.org +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/arch/ppc64/kernel/vdso64/cacheflush.S
# 
# arch/ppc64/kernel/vdso64/Makefile
#   2005/03/04 22:41:54-08:00 benh@kernel.crashing.org +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/arch/ppc64/kernel/vdso64/Makefile
# 
# arch/ppc64/kernel/vdso32/vdso32_wrapper.S
#   2005/03/04 22:41:54-08:00 benh@kernel.crashing.org +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/arch/ppc64/kernel/vdso32/vdso32_wrapper.S
# 
# arch/ppc64/kernel/vdso32/vdso32.lds.S
#   2005/03/04 22:41:54-08:00 benh@kernel.crashing.org +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/arch/ppc64/kernel/vdso32/vdso32.lds.S
# 
# arch/ppc64/kernel/vdso32/sigtramp.S
#   2005/03/04 22:41:54-08:00 benh@kernel.crashing.org +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/arch/ppc64/kernel/vdso32/sigtramp.S
# 
# arch/ppc64/kernel/vdso32/gettimeofday.S
#   2005/03/04 23:17:16-08:00 benh@kernel.crashing.org +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/arch/ppc64/kernel/vdso32/gettimeofday.S
# 
# arch/ppc64/kernel/vdso32/datapage.S
#   2005/03/04 23:17:16-08:00 benh@kernel.crashing.org +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/arch/ppc64/kernel/vdso32/datapage.S
# 
# arch/ppc64/kernel/vdso32/cacheflush.S
#   2005/03/04 22:41:54-08:00 benh@kernel.crashing.org +65 -0
#   ppc64: Implement a vDSO and use it for signal trampoline
# 
# arch/ppc64/kernel/vdso32/Makefile
#   2005/03/04 22:41:54-08:00 benh@kernel.crashing.org +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/arch/ppc64/kernel/vdso32/Makefile
# 
# arch/ppc64/kernel/vdso.c
#   2005/03/04 22:41:54-08:00 benh@kernel.crashing.org +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/arch/ppc64/kernel/vdso.c
# 
# arch/ppc64/kernel/time.c
#   2005/03/04 22:41:54-08:00 benh@kernel.crashing.org +59 -27
#   ppc64: Implement a vDSO and use it for signal trampoline
# 
# arch/ppc64/kernel/smp.c
#   2005/03/04 23:17:15-08:00 benh@kernel.crashing.org +1 -1
#   ppc64: Implement a vDSO and use it for signal trampoline
# 
# arch/ppc64/kernel/signal32.c
#   2005/03/04 22:41:54-08:00 benh@kernel.crashing.org +20 -7
#   ppc64: Implement a vDSO and use it for signal trampoline
# 
# arch/ppc64/kernel/signal.c
#   2005/03/04 22:41:54-08:00 benh@kernel.crashing.org +9 -5
#   ppc64: Implement a vDSO and use it for signal trampoline
# 
# arch/ppc64/kernel/setup.c
#   2005/03/04 23:17:15-08:00 benh@kernel.crashing.org +31 -0
#   ppc64: Implement a vDSO and use it for signal trampoline
# 
# arch/ppc64/kernel/head.S
#   2005/03/04 22:41:54-08:00 benh@kernel.crashing.org +0 -1
#   ppc64: Implement a vDSO and use it for signal trampoline
# 
# arch/ppc64/kernel/asm-offsets.c
#   2005/03/04 22:41:54-08:00 benh@kernel.crashing.org +22 -0
#   ppc64: Implement a vDSO and use it for signal trampoline
# 
# arch/ppc64/kernel/Makefile
#   2005/03/04 23:17:14-08:00 benh@kernel.crashing.org +2 -1
#   ppc64: Implement a vDSO and use it for signal trampoline
# 
# arch/ppc64/boot/Makefile
#   2005/03/04 23:17:15-08:00 benh@kernel.crashing.org +5 -11
#   ppc64: Implement a vDSO and use it for signal trampoline
# 
# arch/ppc64/Makefile
#   2005/03/04 23:17:15-08:00 benh@kernel.crashing.org +21 -0
#   ppc64: Implement a vDSO and use it for signal trampoline
# 
# arch/ppc64/kernel/vdso32/cacheflush.S
#   2005/03/04 22:41:54-08:00 benh@kernel.crashing.org +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/arch/ppc64/kernel/vdso32/cacheflush.S
# 
# ChangeSet
#   2005/03/05 09:33:16-08:00 sfr@canb.auug.org.au 
#   [PATCH] ppc64: distribute EXPORT_SYMBOLs
#   
#   This patch just moves as many as possible EXPORT_SYMBOL()s from
#   arch/ppc64/kernel/ppc_ksyms.c to where the symbols are defined.  This has
#   been compiled on pSeries, iSeries and pmac.
#   
#   Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/asm-ppc64/lmb.h
#   2005/03/04 22:41:53-08:00 sfr@canb.auug.org.au +0 -2
#   ppc64: distribute EXPORT_SYMBOLs
# 
# arch/ppc64/mm/init.c
#   2005/03/04 23:17:16-08:00 sfr@canb.auug.org.au +8 -0
#   ppc64: distribute EXPORT_SYMBOLs
# 
# arch/ppc64/kernel/time.c
#   2005/03/04 23:17:16-08:00 sfr@canb.auug.org.au +1 -0
#   ppc64: distribute EXPORT_SYMBOLs
# 
# arch/ppc64/kernel/signal.c
#   2005/03/04 23:17:16-08:00 sfr@canb.auug.org.au +3 -3
#   ppc64: distribute EXPORT_SYMBOLs
# 
# arch/ppc64/kernel/setup.c
#   2005/03/04 23:17:16-08:00 sfr@canb.auug.org.au +1 -0
#   ppc64: distribute EXPORT_SYMBOLs
# 
# arch/ppc64/kernel/semaphore.c
#   2005/03/04 22:41:53-08:00 sfr@canb.auug.org.au +5 -0
#   ppc64: distribute EXPORT_SYMBOLs
# 
# arch/ppc64/kernel/prom_init.c
#   2005/03/04 23:17:14-08:00 sfr@canb.auug.org.au +0 -1
#   ppc64: distribute EXPORT_SYMBOLs
# 
# arch/ppc64/kernel/prom.c
#   2005/03/04 22:41:53-08:00 sfr@canb.auug.org.au +10 -0
#   ppc64: distribute EXPORT_SYMBOLs
# 
# arch/ppc64/kernel/process.c
#   2005/03/04 22:41:53-08:00 sfr@canb.auug.org.au +2 -0
#   ppc64: distribute EXPORT_SYMBOLs
# 
# arch/ppc64/kernel/ppc_ksyms.c
#   2005/03/04 22:41:53-08:00 sfr@canb.auug.org.au +2 -66
#   ppc64: distribute EXPORT_SYMBOLs
# 
# arch/ppc64/kernel/pci.c
#   2005/03/04 22:41:53-08:00 sfr@canb.auug.org.au +2 -0
#   ppc64: distribute EXPORT_SYMBOLs
# 
# arch/ppc64/kernel/pacaData.c
#   2005/03/04 22:41:53-08:00 sfr@canb.auug.org.au +1 -0
#   ppc64: distribute EXPORT_SYMBOLs
# 
# arch/ppc64/kernel/irq.c
#   2005/03/04 23:17:15-08:00 sfr@canb.auug.org.au +1 -0
#   ppc64: distribute EXPORT_SYMBOLs
# 
# arch/ppc64/kernel/cputable.c
#   2005/03/04 22:41:53-08:00 sfr@canb.auug.org.au +3 -0
#   ppc64: distribute EXPORT_SYMBOLs
# 
# arch/ppc64/kernel/LparData.c
#   2005/03/04 22:41:53-08:00 sfr@canb.auug.org.au +1 -0
#   ppc64: distribute EXPORT_SYMBOLs
# 
# ChangeSet
#   2005/03/05 09:33:01-08:00 olh@suse.de 
#   [PATCH] ppc64: defconfig updates
#   
#   Update several ppc64 defconfigs.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/ppc64/defconfig
#   2005/03/04 22:41:53-08:00 olh@suse.de +421 -173
#   ppc64: defconfig updates
# 
# arch/ppc64/configs/pSeries_defconfig
#   2005/03/04 22:41:53-08:00 olh@suse.de +149 -46
#   ppc64: defconfig updates
# 
# arch/ppc64/configs/maple_defconfig
#   2005/03/04 22:41:53-08:00 olh@suse.de +102 -23
#   ppc64: defconfig updates
# 
# arch/ppc64/configs/iSeries_defconfig
#   2005/03/04 22:41:53-08:00 olh@suse.de +110 -46
#   ppc64: defconfig updates
# 
# arch/ppc64/configs/g5_defconfig
#   2005/03/04 22:41:53-08:00 olh@suse.de +220 -125
#   ppc64: defconfig updates
# 
# ChangeSet
#   2005/03/05 09:32:46-08:00 benh@kernel.crashing.org 
#   [PATCH] ppc64: Move systemcfg out of head.S
#   
#   The "systemcfg" data structure in the ppc64 kernel is something that used
#   to be defined to be at a hard-coded page number in the kernel image.  This
#   is not necessary (at least not any more) and is a possible problem with
#   future developements.  This patch removes that constraint, which also
#   simplifies various bits of assembly in head.S that were dealing with it.
#   
#   This is the first step of a deeper cleanup of systemcfg definition of usage
#   (and ultimately removal in it's current incarnation).
#   
#   Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/asm-ppc64/systemcfg.h
#   2005/03/04 23:17:16-08:00 benh@kernel.crashing.org +0 -5
#   ppc64: Move systemcfg out of head.S
# 
# arch/ppc64/kernel/proc_ppc64.c
#   2005/03/04 22:41:53-08:00 benh@kernel.crashing.org +1 -1
#   ppc64: Move systemcfg out of head.S
# 
# arch/ppc64/kernel/pacaData.c
#   2005/03/04 23:17:17-08:00 benh@kernel.crashing.org +6 -1
#   ppc64: Move systemcfg out of head.S
# 
# arch/ppc64/kernel/head.S
#   2005/03/04 23:17:16-08:00 benh@kernel.crashing.org +5 -27
#   ppc64: Move systemcfg out of head.S
# 
# arch/ppc64/kernel/LparData.c
#   2005/03/04 23:17:17-08:00 benh@kernel.crashing.org +1 -1
#   ppc64: Move systemcfg out of head.S
# 
# ChangeSet
#   2005/03/05 09:32:31-08:00 paulus@samba.org 
#   [PATCH] ppc64: collect and export low-level cpu usage statistics
#   
#   POWER5 machines have a per-hardware-thread register which counts at a rate
#   which is proportional to the percentage of cycles on which the cpu
#   dispatches an instruction for this thread (if the thread gets all the
#   dispatch cycles it counts at the same rate as the timebase register).  This
#   register is also context-switched by the hypervisor.  Thus it gives a
#   fine-grained measure of the actual cpu usage by the thread over time.
#   
#   This patch adds code to read this register every timer interrupt and on
#   every context switch.  The total over all virtual processors is available
#   through the existing /proc/ppc64/lparcfg file, giving a way to measure the
#   total cpu usage over the whole partition.
#   
#   Signed-off-by: Manish Ahuja <ahuja@austin.ibm.com>
#   Signed-off-by: Paul Mackerras <paulus@samba.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/asm-ppc64/time.h
#   2005/03/04 23:17:16-08:00 paulus@samba.org +9 -0
#   ppc64: collect and export low-level cpu usage statistics
# 
# include/asm-ppc64/processor.h
#   2005/03/04 23:17:16-08:00 paulus@samba.org +3 -1
#   ppc64: collect and export low-level cpu usage statistics
# 
# arch/ppc64/kernel/time.c
#   2005/03/04 23:17:17-08:00 paulus@samba.org +8 -0
#   ppc64: collect and export low-level cpu usage statistics
# 
# arch/ppc64/kernel/process.c
#   2005/03/04 23:17:17-08:00 paulus@samba.org +18 -0
#   ppc64: collect and export low-level cpu usage statistics
# 
# arch/ppc64/kernel/lparcfg.c
#   2005/03/04 22:41:53-08:00 paulus@samba.org +13 -5
#   ppc64: collect and export low-level cpu usage statistics
# 
# ChangeSet
#   2005/03/05 09:32:17-08:00 olh@suse.de 
#   [PATCH] remove unneeded includes from pSeries_nvram.c
#   
#   The pseries nvram driver started probably as a copy of nvram.c.  These
#   includes are not needed to build it.
#   
#   Signed-off-by: Olaf Hering <olh@suse.de>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/ppc64/kernel/pSeries_nvram.c
#   2005/03/04 22:41:53-08:00 olh@suse.de +0 -5
#   remove unneeded includes from pSeries_nvram.c
# 
# ChangeSet
#   2005/03/05 09:32:03-08:00 galak@freescale.com 
#   [PATCH] ppc32: PowerQUICC II Pro subarch support
#   
#   Patch adds support for the initial PowerQUICC II Pro processors
#   (MPC8343/E, MPC8347/E, and MPC8349/E) and the first reference platform
#   (MPC834x SYS) from Freescale.
#   
#   The initial support is limited to existing drivers that overlap with the
#   MPC85xx subarch (ethernet, I2C, uart).
#   
#   Signed-off-by: Kumar Gala <kumar.gala@freescale.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/asm-ppc/mpc83xx.h
#   2005/03/04 22:41:52-08:00 galak@freescale.com +114 -0
#   ppc32: PowerQUICC II Pro subarch support
# 
# include/asm-ppc/ipic.h
#   2005/03/04 22:41:52-08:00 galak@freescale.com +85 -0
#   ppc32: PowerQUICC II Pro subarch support
# 
# arch/ppc/syslib/ppc83xx_setup.h
#   2005/03/04 22:41:52-08:00 galak@freescale.com +53 -0
#   ppc32: PowerQUICC II Pro subarch support
# 
# arch/ppc/syslib/ppc83xx_setup.c
#   2005/03/04 22:41:52-08:00 galak@freescale.com +138 -0
#   ppc32: PowerQUICC II Pro subarch support
# 
# arch/ppc/syslib/ipic.h
#   2005/03/04 22:41:52-08:00 galak@freescale.com +49 -0
#   ppc32: PowerQUICC II Pro subarch support
# 
# arch/ppc/syslib/ipic.c
#   2005/03/04 22:41:52-08:00 galak@freescale.com +646 -0
#   ppc32: PowerQUICC II Pro subarch support
# 
# arch/ppc/platforms/83xx/mpc83xx_sys.c
#   2005/03/04 22:41:52-08:00 galak@freescale.com +100 -0
#   ppc32: PowerQUICC II Pro subarch support
# 
# arch/ppc/platforms/83xx/mpc83xx_devices.c
#   2005/03/04 22:41:52-08:00 galak@freescale.com +237 -0
#   ppc32: PowerQUICC II Pro subarch support
# 
# arch/ppc/platforms/83xx/mpc834x_sys.h
#   2005/03/04 22:41:52-08:00 galak@freescale.com +51 -0
#   ppc32: PowerQUICC II Pro subarch support
# 
# arch/ppc/platforms/83xx/mpc834x_sys.c
#   2005/03/04 22:41:52-08:00 galak@freescale.com +290 -0
#   ppc32: PowerQUICC II Pro subarch support
# 
# arch/ppc/platforms/83xx/Makefile
#   2005/03/04 22:41:52-08:00 galak@freescale.com +6 -0
#   ppc32: PowerQUICC II Pro subarch support
# 
# arch/ppc/platforms/83xx/Kconfig
#   2005/03/04 22:41:52-08:00 galak@freescale.com +30 -0
#   ppc32: PowerQUICC II Pro subarch support
# 
# include/asm-ppc/serial.h
#   2005/03/04 22:41:52-08:00 galak@freescale.com +2 -0
#   ppc32: PowerQUICC II Pro subarch support
# 
# include/asm-ppc/ppcboot.h
#   2005/03/04 22:41:52-08:00 galak@freescale.com +4 -2
#   ppc32: PowerQUICC II Pro subarch support
# 
# include/asm-ppc/ppc_sys.h
#   2005/03/04 22:41:52-08:00 galak@freescale.com +3 -1
#   ppc32: PowerQUICC II Pro subarch support
# 
# include/asm-ppc/mpc83xx.h
#   2005/03/04 22:41:52-08:00 galak@freescale.com +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/include/asm-ppc/mpc83xx.h
# 
# include/asm-ppc/irq.h
#   2005/03/04 22:41:52-08:00 galak@freescale.com +10 -0
#   ppc32: PowerQUICC II Pro subarch support
# 
# include/asm-ppc/ipic.h
#   2005/03/04 22:41:52-08:00 galak@freescale.com +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/include/asm-ppc/ipic.h
# 
# include/asm-ppc/io.h
#   2005/03/04 22:41:52-08:00 galak@freescale.com +2 -0
#   ppc32: PowerQUICC II Pro subarch support
# 
# drivers/net/Kconfig
#   2005/03/04 22:41:52-08:00 galak@freescale.com +1 -1
#   ppc32: PowerQUICC II Pro subarch support
# 
# arch/ppc/syslib/ppc83xx_setup.h
#   2005/03/04 22:41:52-08:00 galak@freescale.com +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/arch/ppc/syslib/ppc83xx_setup.h
# 
# arch/ppc/syslib/ppc83xx_setup.c
#   2005/03/04 22:41:52-08:00 galak@freescale.com +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/arch/ppc/syslib/ppc83xx_setup.c
# 
# arch/ppc/syslib/ipic.h
#   2005/03/04 22:41:52-08:00 galak@freescale.com +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/arch/ppc/syslib/ipic.h
# 
# arch/ppc/syslib/ipic.c
#   2005/03/04 22:41:52-08:00 galak@freescale.com +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/arch/ppc/syslib/ipic.c
# 
# arch/ppc/syslib/Makefile
#   2005/03/04 22:41:52-08:00 galak@freescale.com +4 -0
#   ppc32: PowerQUICC II Pro subarch support
# 
# arch/ppc/platforms/83xx/mpc83xx_sys.c
#   2005/03/04 22:41:52-08:00 galak@freescale.com +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/arch/ppc/platforms/83xx/mpc83xx_sys.c
# 
# arch/ppc/platforms/83xx/mpc83xx_devices.c
#   2005/03/04 22:41:52-08:00 galak@freescale.com +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/arch/ppc/platforms/83xx/mpc83xx_devices.c
# 
# arch/ppc/platforms/83xx/mpc834x_sys.h
#   2005/03/04 22:41:52-08:00 galak@freescale.com +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/arch/ppc/platforms/83xx/mpc834x_sys.h
# 
# arch/ppc/platforms/83xx/mpc834x_sys.c
#   2005/03/04 22:41:52-08:00 galak@freescale.com +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/arch/ppc/platforms/83xx/mpc834x_sys.c
# 
# arch/ppc/platforms/83xx/Makefile
#   2005/03/04 22:41:52-08:00 galak@freescale.com +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/arch/ppc/platforms/83xx/Makefile
# 
# arch/ppc/platforms/83xx/Kconfig
#   2005/03/04 22:41:52-08:00 galak@freescale.com +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/arch/ppc/platforms/83xx/Kconfig
# 
# arch/ppc/kernel/setup.c
#   2005/03/04 22:41:52-08:00 galak@freescale.com +4 -0
#   ppc32: PowerQUICC II Pro subarch support
# 
# arch/ppc/kernel/ppc_ksyms.c
#   2005/03/04 22:41:52-08:00 galak@freescale.com +2 -1
#   ppc32: PowerQUICC II Pro subarch support
# 
# arch/ppc/kernel/cputable.c
#   2005/03/04 22:41:52-08:00 galak@freescale.com +12 -0
#   ppc32: PowerQUICC II Pro subarch support
# 
# arch/ppc/configs/mpc834x_sys_defconfig
#   2005/03/04 22:41:52-08:00 galak@freescale.com +644 -0
#   ppc32: PowerQUICC II Pro subarch support
# 
# arch/ppc/Makefile
#   2005/03/04 22:41:52-08:00 galak@freescale.com +1 -0
#   ppc32: PowerQUICC II Pro subarch support
# 
# arch/ppc/Kconfig
#   2005/03/04 22:41:52-08:00 galak@freescale.com +10 -9
#   ppc32: PowerQUICC II Pro subarch support
# 
# MAINTAINERS
#   2005/03/04 22:41:52-08:00 galak@freescale.com +1 -1
#   ppc32: PowerQUICC II Pro subarch support
# 
# CREDITS
#   2005/03/04 22:41:52-08:00 galak@freescale.com +1 -1
#   ppc32: PowerQUICC II Pro subarch support
# 
# arch/ppc/configs/mpc834x_sys_defconfig
#   2005/03/04 22:41:52-08:00 galak@freescale.com +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/arch/ppc/configs/mpc834x_sys_defconfig
# 
# ChangeSet
#   2005/03/05 09:31:47-08:00 galak@freescale.com 
#   [PATCH] ppc32: Trivial bug fix in CRITICAL_EXCEPTION macro
#   
#   This patch fixes a trival bug in the CRITICAL_EXCEPTION macro
#   
#   Signed-off-by: Takeharu KATO <kato.takeharu@jp.fujitsu.com>
#   Signed-off-by: Kumar Gala <kumar.gala@freescale.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/ppc/kernel/head_booke.h
#   2005/03/04 22:41:52-08:00 galak@freescale.com +2 -2
#   ppc32: Trivial bug fix in CRITICAL_EXCEPTION macro
# 
# ChangeSet
#   2005/03/05 09:31:34-08:00 galak@freescale.com 
#   [PATCH] ppc32: Add support to use the DS1553 RTC/NVRAM on MPC8555 CDS system
#   
#   This patch makes the MPC8555 CDS system utilize the DS1553 RTC/NVRAM.
#                  
#   Signed-off-by: Kumar Gala <kumar.gala@freescale.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/ppc/syslib/Makefile
#   2005/03/04 23:17:19-08:00 galak@freescale.com +1 -0
#   ppc32: Add support to use the DS1553 RTC/NVRAM on MPC8555 CDS system
# 
# arch/ppc/platforms/85xx/mpc85xx_cds_common.h
#   2005/03/04 22:41:52-08:00 galak@freescale.com +4 -0
#   ppc32: Add support to use the DS1553 RTC/NVRAM on MPC8555 CDS system
# 
# arch/ppc/platforms/85xx/mpc85xx_cds_common.c
#   2005/03/04 22:41:52-08:00 galak@freescale.com +17 -3
#   ppc32: Add support to use the DS1553 RTC/NVRAM on MPC8555 CDS system
# 
# ChangeSet
#   2005/03/05 09:31:20-08:00 galak@freescale.com 
#   [PATCH] ppc32: Add support for the Dallas 1553 RTC/NVRAM
#   
#   This patch adds support for the Dallas 1553 RTC/NVRAM.
#   
#   Signed-off-by: Kumar Gala <kumar.gala@freescale.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/asm-ppc/todc.h
#   2005/03/04 22:41:52-08:00 galak@freescale.com +23 -0
#   ppc32: Add support for the Dallas 1553 RTC/NVRAM
# 
# arch/ppc/syslib/todc_time.c
#   2005/03/04 22:41:52-08:00 galak@freescale.com +4 -0
#   ppc32: Add support for the Dallas 1553 RTC/NVRAM
# 
# ChangeSet
#   2005/03/05 09:31:06-08:00 mporter@kernel.crashing.org 
#   [PATCH] ppc32: support OpenBIOS/U-Boot for Ebony
#   
#   This patch adds support for OpenBios on Ebony, as Matt Porter has
#   suggested.  It will provide same functionality as the pibs extension for
#   Luan and Ocotea.
#   
#   Signed-off-by: Gerhard Jaeger <gjaeger@sysgo.com>
#   Signed-off-by: Matt Porter <mporter@kernel.crashing.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/ppc/platforms/4xx/ebony.h
#   2005/03/04 22:41:48-08:00 mporter@kernel.crashing.org +3 -7
#   ppc32: support OpenBIOS/U-Boot for Ebony
# 
# arch/ppc/platforms/4xx/ebony.c
#   2005/03/04 22:41:48-08:00 mporter@kernel.crashing.org +26 -6
#   ppc32: support OpenBIOS/U-Boot for Ebony
# 
# arch/ppc/boot/simple/openbios.c
#   2005/03/04 22:41:48-08:00 mporter@kernel.crashing.org +37 -0
#   ppc32: support OpenBIOS/U-Boot for Ebony
# 
# arch/ppc/boot/simple/Makefile
#   2005/03/04 22:41:48-08:00 mporter@kernel.crashing.org +1 -0
#   ppc32: support OpenBIOS/U-Boot for Ebony
# 
# arch/ppc/boot/simple/openbios.c
#   2005/03/04 22:41:48-08:00 mporter@kernel.crashing.org +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/arch/ppc/boot/simple/openbios.c
# 
# ChangeSet
#   2005/03/05 09:30:51-08:00 mgreer@mvista.com 
#   [PATCH] ppc32: Add GPIO/IRQ definitions for mv64x60 parts
#   
#   Add mv64x60 GPP IO pin/IRQ register definitions
#   
#   Signed-off-by: James Chapman <jchapman@katalix.com>
#   Signed-off-by: Mark A. Greer <mgreer@mvista.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/asm-ppc/mv64x60_defs.h
#   2005/03/04 22:41:17-08:00 mgreer@mvista.com +41 -0
#   ppc32: Add GPIO/IRQ definitions for mv64x60 parts
# 
# ChangeSet
#   2005/03/05 09:30:37-08:00 mgreer@mvista.com 
#   [PATCH] ppc32: mv64360_pic non-zero irq base
#   
#   Add support for non-zero irq base to mv64360_pic code.
#   
#   - Fix mv64360 pic code to handle non-zero mv64x60_irq_base
#   - Cleanup mv64360 entries in /proc/interrupts
#   
#   Signed-off-by: James Chapman <jchapman@katalix.com>
#   Signed-off-by: Mark A. Greer <mgreer@mvista.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/asm-ppc/mv64x60_defs.h
#   2005/03/04 23:17:20-08:00 mgreer@mvista.com +1 -0
#   ppc32: mv64360_pic non-zero irq base
# 
# arch/ppc/syslib/mv64360_pic.c
#   2005/03/04 22:41:17-08:00 mgreer@mvista.com +17 -12
#   ppc32: mv64360_pic non-zero irq base
# 
# ChangeSet
#   2005/03/05 09:30:23-08:00 galak@freescale.com 
#   [PATCH] ppc32: Move from using #define SVR_ to cur_ppc_sys_spec name for 85xx platform
#   
#   Removes explicit defines for SVR_85xx and use the information in the
#   ppc_sys_specs table in platform code.  Changed the ppc_sys_name strings to
#   be a bit more generic so we have a bit more flexilibity when we display
#   them.
#   
#   Signed-off-by: Kumar Gala <kumar.gala@freescale.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/asm-ppc/reg.h
#   2005/03/04 22:41:17-08:00 galak@freescale.com +0 -6
#   ppc32: Move from using #define SVR_ to cur_ppc_sys_spec name for 85xx platform
# 
# arch/ppc/platforms/85xx/stx_gp3.c
#   2005/03/04 22:41:17-08:00 galak@freescale.com +4 -12
#   ppc32: Move from using #define SVR_ to cur_ppc_sys_spec name for 85xx platform
# 
# arch/ppc/platforms/85xx/sbc85xx.c
#   2005/03/04 22:41:17-08:00 galak@freescale.com +3 -12
#   ppc32: Move from using #define SVR_ to cur_ppc_sys_spec name for 85xx platform
# 
# arch/ppc/platforms/85xx/mpc85xx_sys.c
#   2005/03/04 22:41:17-08:00 galak@freescale.com +6 -6
#   ppc32: Move from using #define SVR_ to cur_ppc_sys_spec name for 85xx platform
# 
# arch/ppc/platforms/85xx/mpc85xx_cds_common.c
#   2005/03/04 23:17:19-08:00 galak@freescale.com +2 -1
#   ppc32: Move from using #define SVR_ to cur_ppc_sys_spec name for 85xx platform
# 
# arch/ppc/platforms/85xx/mpc85xx_ads_common.c
#   2005/03/04 22:41:17-08:00 galak@freescale.com +3 -12
#   ppc32: Move from using #define SVR_ to cur_ppc_sys_spec name for 85xx platform
# 
# ChangeSet
#   2005/03/05 09:30:10-08:00 galak@freescale.com 
#   [PATCH] ppc32: fix whitespace for 85xx CDS common platform
#   
#   Fix whitespace in arch/ppc/platforms/85xx/mpc85xx_cds_common.c
#   
#   Signed-off-by: Kumar Gala <kumar.gala@freescale.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/ppc/platforms/85xx/mpc85xx_cds_common.c
#   2005/03/04 23:17:20-08:00 galak@freescale.com +150 -150
#   ppc32: fix whitespace for 85xx CDS common platform
# 
# ChangeSet
#   2005/03/05 09:29:56-08:00 benh@kernel.crashing.org 
#   [PATCH] ppc32: Bogus definition of __cmpxchg_u32()
#   
#   This patch fix bogus types in the definition of __cmpxchg_u32() on ppc32.
#   
#   Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/asm-ppc/system.h
#   2005/03/04 22:41:17-08:00 benh@kernel.crashing.org +2 -2
#   ppc32: Bogus definition of __cmpxchg_u32()
# 
# ChangeSet
#   2005/03/05 09:29:42-08:00 mgreer@mvista.com 
#   [PATCH] ppc32: incorrect #define in include/asm-ppc/cpm2.h
#   
#   This patch fixes the incorrect definition of a macro that sets the transmit
#   parity to even on a cpm uart device.
#   
#   Signed-off-by: Mark A. Greer <mgreer@mista.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/asm-ppc/cpm2.h
#   2005/03/04 22:41:17-08:00 mgreer@mvista.com +1 -1
#   ppc32: incorrect #define in include/asm-ppc/cpm2.h
# 
# ChangeSet
#   2005/03/05 09:29:28-08:00 ebs@ebshome.net 
#   [PATCH] ppc32: PPC4xx PIC: ack parent UIC in disable_irq
#   
#   This patch fixes bug in PPC4xx disable_irq implementation.  We need to ACK
#   parent UIC to prevent false triggering in case IRQ we just disabled was
#   already pending.
#   
#   Signed-off-by: Eugene Surovegin <ebs@ebshome.net>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/ppc/syslib/ppc4xx_pic.c
#   2005/03/04 22:41:17-08:00 ebs@ebshome.net +2 -1
#   ppc32: PPC4xx PIC: ack parent UIC in disable_irq
# 
# ChangeSet
#   2005/03/05 09:29:14-08:00 ebs@ebshome.net 
#   [PATCH] ppc32: Lindentify PPC4xx PIC driver
#   
#   This patch fixes whitespace in PPC4xx PIC driver.
#   
#   Signed-off-by: Eugene Surovegin <ebs@ebshome.net>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/asm-ppc/ppc4xx_pic.h
#   2005/03/04 22:41:16-08:00 ebs@ebshome.net +4 -4
#   ppc32: Lindentify PPC4xx PIC driver
# 
# arch/ppc/syslib/ppc4xx_pic.c
#   2005/03/04 23:17:21-08:00 ebs@ebshome.net +26 -20
#   ppc32: Lindentify PPC4xx PIC driver
# 
# ChangeSet
#   2005/03/05 09:28:59-08:00 mporter@kernel.crashing.org 
#   [PATCH] ppc32: move irq_desc[].status, IRQ_LEVEL bit setup to xilinx_pic.c
#   
#   Move the code that informs the kernel if the particular interrupt is edge
#   triggered or level sensitive from the board specific file to a
#   "CONFIG_VIRTEX_II_PRO-specific" file.  Using old IRQ numbering in that code
#   is also fixed.
#   
#   Signed-off-by: Andrei Konovalov <akonovalov@ru.mvista.com>
#   Signed-off-by: Matt Porter <mporter@kernel.crashing.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/ppc/syslib/xilinx_pic.c
#   2005/03/04 22:41:16-08:00 mporter@kernel.crashing.org +15 -1
#   ppc32: move irq_desc[].status, IRQ_LEVEL bit setup to xilinx_pic.c
# 
# arch/ppc/platforms/4xx/xilinx_ml300.c
#   2005/03/04 22:41:16-08:00 mporter@kernel.crashing.org +0 -18
#   ppc32: move irq_desc[].status, IRQ_LEVEL bit setup to xilinx_pic.c
# 
# ChangeSet
#   2005/03/05 09:28:45-08:00 mgreer@mvista.com 
#   [PATCH] ppc32: Artesyn Katana enet update
#   
#   - Adapt Katana to the new names used by the ethernet driver.
#   - Remove SRAM allocation code for mv643xx_enet until it's had more review.
#   
#   Signed-off-by: Dale Farnsworth <dale@farnsworth.org>
#   Signed-off-by: Mark A. Greer <mgreer@mvista.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/ppc/syslib/mv64x60.c
#   2005/03/04 22:41:16-08:00 mgreer@mvista.com +10 -10
#   ppc32: Artesyn Katana enet update
# 
# arch/ppc/platforms/katana.c
#   2005/03/04 22:41:16-08:00 mgreer@mvista.com +4 -18
#   ppc32: Artesyn Katana enet update
# 
# ChangeSet
#   2005/03/05 09:28:32-08:00 mgreer@mvista.com 
#   [PATCH] ppc32: Artesyn Katana platform update
#   
#   - Adds MTD support for the soldered FLASH
#   - Adds cmdline parsing
#   - Turns on the Blue LED when the system is halted
#   - Moves some of the device window left by the firmware to proper alignments
#   - Handles possibility of different frequencies for TCLK & SysCLK in 64460
#   - Misc. code clean up
#   
#   Signed-off-by: Mark A. Greer <mgreer@mvista.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/asm-ppc/mv64x60_defs.h
#   2005/03/04 23:17:20-08:00 mgreer@mvista.com +3 -1
#   ppc32: Artesyn Katana platform update
# 
# arch/ppc/platforms/katana.h
#   2005/03/04 22:41:16-08:00 mgreer@mvista.com +18 -27
#   ppc32: Artesyn Katana platform update
# 
# arch/ppc/platforms/katana.c
#   2005/03/04 23:17:22-08:00 mgreer@mvista.com +144 -49
#   ppc32: Artesyn Katana platform update
# 
# arch/ppc/configs/katana_defconfig
#   2005/03/04 22:41:16-08:00 mgreer@mvista.com +86 -7
#   ppc32: Artesyn Katana platform update
# 
# ChangeSet
#   2005/03/05 09:28:17-08:00 olh@suse.de 
#   [PATCH] ppc32: update arch/ppc/configs/pmac_defconfig
#   
#   enable drm/agp, cpufreq, pppoe and new pccard option
#   
#   Signed-off-by: Olaf Hering <olh@suse.de>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/ppc/configs/pmac_defconfig
#   2005/03/04 22:41:16-08:00 olh@suse.de +262 -101
#   ppc32: update arch/ppc/configs/pmac_defconfig
# 
# ChangeSet
#   2005/03/05 09:28:04-08:00 mgreer@mvista.com 
#   [PATCH] ppc32: fix mv64x60 register relocation bug in bootwrapper
#   
#   The gt64260 looks at the highest 20 bits while the mv64[34]60 looks at only
#   the highest 16 bits when determining the base address for the bridge's
#   registers.  This patch adds support for both.
#   
#   Signed-off-by: Nate Case <ncase@xes-inc.com>
#   Signed-off-by: Mark A. Greer <mgreer@mvista.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/ppc/boot/simple/misc-mv64x60.S
#   2005/03/04 22:41:16-08:00 mgreer@mvista.com +4 -0
#   ppc32: fix mv64x60 register relocation bug in bootwrapper
# 
# ChangeSet
#   2005/03/05 09:27:51-08:00 trini@kernel.crashing.org 
#   [PATCH] ppc32: Don't create .tmp_gas_check
#   
#   This changes how the ppc32 'checkbin' target works.  Previously we did all
#   of the tests using variables which would be evaluated for any and every
#   make target.  This meant that 'make tags' for example would leave behind a
#   '.tmp_gas_check' file even though we didn't actually compile up anything,
#   and would get in the way of diffs.  By moving all of this logic directly
#   into the 'checkbin' target, we only test gcc/gas versions when we're going
#   to compile.
#   
#   Signed-off-by: Olaf Hering <olh@suse.de>
#   Signed-off-by: Tom Rini <trini@kernel.crashing.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/ppc/Makefile
#   2005/03/04 23:17:19-08:00 trini@kernel.crashing.org +14 -16
#   ppc32: Don't create .tmp_gas_check
# 
# ChangeSet
#   2005/03/05 09:27:37-08:00 olof@austin.ibm.com 
#   [PATCH] PPC/PPC64: Abstract cpu_feature checks.
#   
#   Abstract most manual mask checks of cpu_features with cpu_has_feature()
#   
#   Signed-off-by: Olof Johansson <olof@austin.ibm.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/asm-ppc64/page.h
#   2005/03/04 23:17:16-08:00 olof@austin.ibm.com +1 -1
#   PPC/PPC64: Abstract cpu_feature checks.
# 
# include/asm-ppc64/mmu_context.h
#   2005/03/04 22:41:15-08:00 olof@austin.ibm.com +2 -2
#   PPC/PPC64: Abstract cpu_feature checks.
# 
# include/asm-ppc64/cputable.h
#   2005/03/04 22:41:15-08:00 olof@austin.ibm.com +5 -0
#   PPC/PPC64: Abstract cpu_feature checks.
# 
# include/asm-ppc64/cacheflush.h
#   2005/03/04 22:41:15-08:00 olof@austin.ibm.com +1 -1
#   PPC/PPC64: Abstract cpu_feature checks.
# 
# include/asm-ppc/cputable.h
#   2005/03/04 22:41:15-08:00 olof@austin.ibm.com +5 -0
#   PPC/PPC64: Abstract cpu_feature checks.
# 
# drivers/md/raid6altivec.uc
#   2005/03/04 22:41:15-08:00 olof@austin.ibm.com +1 -1
#   PPC/PPC64: Abstract cpu_feature checks.
# 
# drivers/macintosh/via-pmu.c
#   2005/03/04 22:41:15-08:00 olof@austin.ibm.com +1 -1
#   PPC/PPC64: Abstract cpu_feature checks.
# 
# arch/ppc64/xmon/xmon.c
#   2005/03/04 22:41:15-08:00 olof@austin.ibm.com +4 -4
#   PPC/PPC64: Abstract cpu_feature checks.
# 
# arch/ppc64/oprofile/op_model_rs64.c
#   2005/03/04 22:41:15-08:00 olof@austin.ibm.com +1 -1
#   PPC/PPC64: Abstract cpu_feature checks.
# 
# arch/ppc64/oprofile/op_model_power4.c
#   2005/03/04 22:41:15-08:00 olof@austin.ibm.com +1 -1
#   PPC/PPC64: Abstract cpu_feature checks.
# 
# arch/ppc64/mm/stab.c
#   2005/03/04 22:41:15-08:00 olof@austin.ibm.com +1 -1
#   PPC/PPC64: Abstract cpu_feature checks.
# 
# arch/ppc64/mm/slb.c
#   2005/03/04 22:41:15-08:00 olof@austin.ibm.com +2 -2
#   PPC/PPC64: Abstract cpu_feature checks.
# 
# arch/ppc64/mm/init.c
#   2005/03/04 23:17:17-08:00 olof@austin.ibm.com +5 -5
#   PPC/PPC64: Abstract cpu_feature checks.
# 
# arch/ppc64/mm/hugetlbpage.c
#   2005/03/04 22:41:15-08:00 olof@austin.ibm.com +1 -1
#   PPC/PPC64: Abstract cpu_feature checks.
# 
# arch/ppc64/mm/hash_utils.c
#   2005/03/04 22:41:15-08:00 olof@austin.ibm.com +1 -1
#   PPC/PPC64: Abstract cpu_feature checks.
# 
# arch/ppc64/mm/hash_native.c
#   2005/03/04 22:41:15-08:00 olof@austin.ibm.com +7 -7
#   PPC/PPC64: Abstract cpu_feature checks.
# 
# arch/ppc64/kernel/sysfs.c
#   2005/03/04 23:17:15-08:00 olof@austin.ibm.com +11 -11
#   PPC/PPC64: Abstract cpu_feature checks.
# 
# arch/ppc64/kernel/smp.c
#   2005/03/04 23:17:16-08:00 olof@austin.ibm.com +1 -1
#   PPC/PPC64: Abstract cpu_feature checks.
# 
# arch/ppc64/kernel/setup.c
#   2005/03/04 23:17:17-08:00 olof@austin.ibm.com +3 -3
#   PPC/PPC64: Abstract cpu_feature checks.
# 
# arch/ppc64/kernel/process.c
#   2005/03/04 23:17:18-08:00 olof@austin.ibm.com +2 -2
#   PPC/PPC64: Abstract cpu_feature checks.
# 
# arch/ppc64/kernel/pSeries_lpar.c
#   2005/03/04 22:41:15-08:00 olof@austin.ibm.com +1 -1
#   PPC/PPC64: Abstract cpu_feature checks.
# 
# arch/ppc64/kernel/iSeries_setup.c
#   2005/03/04 22:41:15-08:00 olof@austin.ibm.com +1 -1
#   PPC/PPC64: Abstract cpu_feature checks.
# 
# arch/ppc64/kernel/align.c
#   2005/03/04 22:41:15-08:00 olof@austin.ibm.com +1 -1
#   PPC/PPC64: Abstract cpu_feature checks.
# 
# arch/ppc/platforms/sandpoint.c
#   2005/03/04 22:41:15-08:00 olof@austin.ibm.com +3 -3
#   PPC/PPC64: Abstract cpu_feature checks.
# 
# arch/ppc/platforms/pmac_smp.c
#   2005/03/04 22:41:15-08:00 olof@austin.ibm.com +2 -2
#   PPC/PPC64: Abstract cpu_feature checks.
# 
# arch/ppc/platforms/pmac_setup.c
#   2005/03/04 22:41:15-08:00 olof@austin.ibm.com +1 -1
#   PPC/PPC64: Abstract cpu_feature checks.
# 
# arch/ppc/platforms/pmac_cpufreq.c
#   2005/03/04 22:41:15-08:00 olof@austin.ibm.com +1 -1
#   PPC/PPC64: Abstract cpu_feature checks.
# 
# arch/ppc/mm/ppc_mmu.c
#   2005/03/04 22:41:15-08:00 olof@austin.ibm.com +2 -2
#   PPC/PPC64: Abstract cpu_feature checks.
# 
# arch/ppc/mm/mmu_decl.h
#   2005/03/04 22:41:15-08:00 olof@austin.ibm.com +1 -1
#   PPC/PPC64: Abstract cpu_feature checks.
# 
# arch/ppc/kernel/temp.c
#   2005/03/04 22:41:15-08:00 olof@austin.ibm.com +1 -1
#   PPC/PPC64: Abstract cpu_feature checks.
# 
# arch/ppc/kernel/setup.c
#   2005/03/04 23:17:19-08:00 olof@austin.ibm.com +2 -2
#   PPC/PPC64: Abstract cpu_feature checks.
# 
# arch/ppc/kernel/ppc_htab.c
#   2005/03/04 22:41:15-08:00 olof@austin.ibm.com +4 -4
#   PPC/PPC64: Abstract cpu_feature checks.
# 
# ChangeSet
#   2005/03/05 09:27:21-08:00 bill.irwin@oracle.com 
#   [PATCH] make mapping->tree_lock an rwlock
#   
#   Convert mapping->tree_lock to an rwlock.
#   
#   with:
#   
#   dd if=/dev/zero of=foo bs=1 count=2M  0.80s user 4.15s system 99% cpu 4.961 total
#   dd if=/dev/zero of=foo bs=1 count=2M  0.73s user 4.26s system 100% cpu 4.987 total
#   dd if=/dev/zero of=foo bs=1 count=2M  0.79s user 4.25s system 100% cpu 5.034 total
#   
#   dd if=foo of=/dev/null bs=1  0.80s user 3.12s system 99% cpu 3.928 total
#   dd if=foo of=/dev/null bs=1  0.77s user 3.15s system 100% cpu 3.914 total
#   dd if=foo of=/dev/null bs=1  0.92s user 3.02s system 100% cpu 3.935 total
#   
#   (3.926: 1.87 usecs)
#   
#   without:
#   
#   dd if=/dev/zero of=foo bs=1 count=2M  0.85s user 3.92s system 99% cpu 4.780 total
#   dd if=/dev/zero of=foo bs=1 count=2M  0.78s user 4.02s system 100% cpu 4.789 total
#   dd if=/dev/zero of=foo bs=1 count=2M  0.82s user 3.94s system 99% cpu 4.763 total
#   dd if=/dev/zero of=foo bs=1 count=2M  0.71s user 4.10s system 99% cpu 4.810 tota
#   
#   dd if=foo of=/dev/null bs=1  0.76s user 2.68s system 100% cpu 3.438 total
#   dd if=foo of=/dev/null bs=1  0.74s user 2.72s system 99% cpu 3.465 total
#   dd if=foo of=/dev/null bs=1  0.67s user 2.82s system 100% cpu 3.489 total
#   dd if=foo of=/dev/null bs=1  0.70s user 2.62s system 99% cpu 3.326 total
#   
#   (3.430: 1.635 usecs)
#   
#   
#   So on a P4, the additional cost of the rwlock is ~240 nsecs for a
#   one-byte-write().  On the other hand:
#   
#   From: Peter Chubb <peterc@gelato.unsw.edu.au>
#   
#     As part of the Gelato scalability focus group, we've been running OSDL's
#     Re-AIM7 benchmark with an I/O intensive load with varying numbers of
#     processors.  The current kernel shows severe contention on the tree_lock in
#     the address space structure when running on tmpfs or ext2 on a RAM disk.
#   
#   
#     Lockstat output for a 12-way:
#   
#     SPINLOCKS         HOLD            WAIT
#       UTIL  CON    MEAN(  MAX )   MEAN(  MAX )(% CPU)     TOTAL NOWAIT SPIN RJECT  NAME
#   
#             5.5%  0.4us(3177us)   28us(  20ms)(44.2%) 131821954 94.5%  5.5% 0.00%  *TOTAL*
#   
#      72.3% 13.1%  0.5us( 9.5us)   29us(  20ms)(42.5%)  50542055 86.9% 13.1%    0%  find_lock_page+0x30
#      23.8%    0%  385us(3177us)    0us                    23235  100%    0%    0%  exit_mmap+0x50
#      11.5% 0.82%  0.1us( 101us)   17us(5670us)( 1.6%)  50665658 99.2% 0.82%    0%  dnotify_parent+0x70
#   
#   
#     Replacing the spinlock with a multi-reader lock fixes this problem,
#     without unduly affecting anything else.
#   
#     Here are the benchmark results (jobs per minute at a 50-client level, average
#     of 5 runs, standard deviation in parens) on an HP Olympia with 3 cells, 12
#     processors, and dnotify turned off (after this spinlock, the spinlock in
#     dnotify_parent is the worst contended for this workload).
#   
#     	 tmpfs...............               ext2...............
#     #CPUs	 spinlock      rwlock               spinlock     rwlock
#         1     7556(15)      7588(17)  +0.42%      3744(20)     3791(16) +1.25%
#         2	 13743(31)     13791(33)  +0.35%      6405(30)     6413(24) +0.12%
#         4	 23334(111)    22881(154) -2%        9648(51)     9595(50)  -0.55%
#         8	 33580(240)    36163(190) +7.7%     13183(63)    13070(68)  -0.85%
#        12	 28748(170)    44064(238)+53%      12681(49)	 14504(105)+14% 
#   
#     And on a pentium3 single processsor:
#         1    4177(4)        4169(2)  -0.2%        3811(4)     3820(3) +0.23%
#   
#     I'm not sure what's happening in the 4-processor case.  The important thing to
#     note is that with a spinlock, the benchmark shows worse performance for a 12
#     than for an 8-way box; with the patch, the 12 way performs better, as
#     expected.  We've done some runs with 16-way as well; without the patch below,
#     the 16-way performs worse than the 12-way.
#   
#   
#   It's a tricky tradeoff, but large-smp is hurt a lot more by the spinlocks than
#   small-smp is by the rwlocks.  And I don't think we really want to implement
#   compile-time either-or-locks.
#   
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# mm/vmscan.c
#   2005/03/04 22:41:15-08:00 bill.irwin@oracle.com +4 -4
#   make mapping->tree_lock an rwlock
# 
# mm/truncate.c
#   2005/03/04 22:41:15-08:00 bill.irwin@oracle.com +3 -3
#   make mapping->tree_lock an rwlock
# 
# mm/swapfile.c
#   2005/03/04 22:41:15-08:00 bill.irwin@oracle.com +6 -6
#   make mapping->tree_lock an rwlock
# 
# mm/swap_state.c
#   2005/03/04 22:41:15-08:00 bill.irwin@oracle.com +9 -9
#   make mapping->tree_lock an rwlock
# 
# mm/readahead.c
#   2005/03/04 22:41:15-08:00 bill.irwin@oracle.com +4 -4
#   make mapping->tree_lock an rwlock
# 
# mm/page-writeback.c
#   2005/03/04 22:41:15-08:00 bill.irwin@oracle.com +14 -14
#   make mapping->tree_lock an rwlock
# 
# mm/filemap.c
#   2005/03/04 22:41:15-08:00 bill.irwin@oracle.com +16 -16
#   make mapping->tree_lock an rwlock
# 
# include/linux/fs.h
#   2005/03/04 22:41:15-08:00 bill.irwin@oracle.com +1 -1
#   make mapping->tree_lock an rwlock
# 
# include/asm-parisc/cacheflush.h
#   2005/03/04 22:41:15-08:00 bill.irwin@oracle.com +2 -2
#   make mapping->tree_lock an rwlock
# 
# include/asm-arm/cacheflush.h
#   2005/03/04 22:41:15-08:00 bill.irwin@oracle.com +2 -2
#   make mapping->tree_lock an rwlock
# 
# fs/inode.c
#   2005/03/04 22:41:15-08:00 bill.irwin@oracle.com +1 -1
#   make mapping->tree_lock an rwlock
# 
# fs/buffer.c
#   2005/03/04 22:41:15-08:00 bill.irwin@oracle.com +2 -2
#   make mapping->tree_lock an rwlock
# 
# drivers/mtd/devices/block2mtd.c
#   2005/03/04 22:41:15-08:00 bill.irwin@oracle.com +4 -4
#   make mapping->tree_lock an rwlock
# 
# ChangeSet
#   2005/03/05 09:27:06-08:00 zach.brown@oracle.com 
#   [PATCH] only unmap what intersects a direct_IO op
#   
#   Now that we're only invalidating the pages that intersected a direct IO
#   write we might as well only unmap the intersecting bytes as well.  This
#   passed a light fsx load with page cache, direct, and mmap IO.
#   
#   Signed-off-by: Zach Brown <zach.brown@oracle.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# mm/filemap.c
#   2005/03/04 23:17:24-08:00 zach.brown@oracle.com +8 -4
#   only unmap what intersects a direct_IO op
# 
# ChangeSet
#   2005/03/05 09:26:52-08:00 zach.brown@oracle.com 
#   [PATCH] write and wait on range before direct io read
#   
#   This adds filemap_write_and_wait_range(mapping, lstart, lend) which starts
#   writeback and waits on a range of pages.  We call this from
#   __blkdev_direct_IO with just the range that is going to be read by the
#   direct_IO read.  It was lightly tested with fsx and ext3 and passed.
#   
#   Signed-off-by: Zach Brown <zach.brown@oracle.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# mm/filemap.c
#   2005/03/04 23:17:24-08:00 zach.brown@oracle.com +16 -0
#   write and wait on range before direct io read
# 
# include/linux/fs.h
#   2005/03/04 23:17:24-08:00 zach.brown@oracle.com +2 -0
#   write and wait on range before direct io read
# 
# fs/direct-io.c
#   2005/03/04 22:41:15-08:00 zach.brown@oracle.com +5 -2
#   write and wait on range before direct io read
# 
# ChangeSet
#   2005/03/05 09:26:38-08:00 zach.brown@oracle.com 
#   [PATCH] invalidate range of pages after direct IO write
#   
#   Presently we invalidate all of a file's pages when writing to any part of
#   that file with direct-IO.
#   
#   After a direct IO write only invalidate the pages that the write intersected.
#   invalidate_inode_pages2_range(mapping, pgoff start, pgoff end) is added and
#   called from generic_file_direct_IO().
#   
#   While we're in there, invalidate_inode_pages2() was calling
#   unmap_mapping_range() with the wrong convention in the single page case.
#   It was providing the byte offset of the final page rather than the length
#   of the hole being unmapped.  This is also fixed.
#   
#   This was lightly tested with a 10k op fsx run with O_DIRECT on a 16MB file
#   in ext3 on a junky old IDE drive.  Totaling vmstat columns of blocks read
#   and written during the runs shows that read traffic drops significantly.
#   The run time seems to have gone down a little.
#   
#   Two runs before the patch gave the following user/real/sys times and total
#   blocks in and out:
#   
#   0m28.029s 0m20.093s 0m3.166s 16673 125107 
#   0m27.949s 0m20.068s 0m3.227s 18426 126094
#   
#   and after the patch:
#   
#   0m26.775s 0m19.996s 0m3.060s 3505 124982
#   0m26.856s 0m19.935s 0m3.052s 3505 125279
#   
#   akpm:
#   
#   - Don't look up more pages than we're going to use
#   
#   - Don't test page->index until we've locked the page
#   
#   - Check for the cursor wrapping at the end of the mapping.
#   
#   Signed-off-by: Zach Brown <zach.brown@oracle.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# mm/truncate.c
#   2005/03/04 23:17:24-08:00 zach.brown@oracle.com +37 -14
#   invalidate range of pages after direct IO write
# 
# mm/filemap.c
#   2005/03/04 23:17:25-08:00 zach.brown@oracle.com +4 -1
#   invalidate range of pages after direct IO write
# 
# include/linux/fs.h
#   2005/03/04 23:17:25-08:00 zach.brown@oracle.com +2 -0
#   invalidate range of pages after direct IO write
# 
# ChangeSet
#   2005/03/05 09:26:24-08:00 clameter@sgi.com 
#   [PATCH] Move accounting function calls out of critical vm code paths
#   
#   In the 2.6.11 development cycle function calls have been added to lots
#   of hot vm paths to do accounting. I think these should not go into the
#   final 2.6.1 release because these statistics can be collected in a different
#   way that does not require the updating of counters from frequently used
#   vm code paths and is consistent with the methods use elsewhere in the kernel
#   to obtain statistics.
#   
#   These function calls are
#   
#   acct_update_integrals	-> Account for processes based on stime changes
#   update_mem_hiwater	-> takes rss and total_vm hiwater marks.
#   
#   acct_update_integrals is only useful to call if stime changes otherwise
#   it will simply return. It is therefore best to relocate the function call
#   to acct_update_integral into the function that updates stime which is
#   account_system_time and remove it from the vm code paths.
#   
#   update_mem_hiwater finds the rss hiwater mark.  We call that from timer
#   context as well.  This means that processes' high-water marks are now
#   sampled statistically, at timer-interrupt time rather than
#   deterministically.  This may or may not be a problem..
#   
#   This means that the rss limit is not always updated if rss is increased
#   and thus not as accurate. But the benefit is that the rss checks do no
#   pollute the vm paths and that it is consistent with the rss limit check.
#   
#   The following patch removes acct_update_integrals and update_mem_hiwater
#   from the hot vm paths.
#   
#   Signed-off-by: Christoph Lameter <clameter@sgi.com>
#   
#   From: Jay Lan <jlan@sgi.com>
#   
#   The new "move-accounting-function-calls-out-of-critical-vm-code-paths"
#   patch in 2.6.11-rc3-mm2 was different from the code i tested.
#   
#   In particular, it mistakenly dropped the accounting routine calls
#   in fs/exec.c. The calls in do_execve() are needed to properly
#   initialize accounting fields. Specifically, the tsk->acct_stimexpd
#   needs to be initialized to tsk->stime.
#   
#   I have discussed this with Christoph Lameter and he gave me full
#   blessings to bring the calls back.
#   
#   Signed-off-by: Jay Lan <jlan@sgi.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# mm/swapfile.c
#   2005/03/04 23:17:24-08:00 clameter@sgi.com +0 -3
#   Move accounting function calls out of critical vm code paths
# 
# mm/rmap.c
#   2005/03/04 22:41:14-08:00 clameter@sgi.com +0 -3
#   Move accounting function calls out of critical vm code paths
# 
# mm/nommu.c
#   2005/03/04 22:41:14-08:00 clameter@sgi.com +1 -3
#   Move accounting function calls out of critical vm code paths
# 
# mm/mremap.c
#   2005/03/04 22:41:14-08:00 clameter@sgi.com +0 -6
#   Move accounting function calls out of critical vm code paths
# 
# mm/mmap.c
#   2005/03/04 22:41:14-08:00 clameter@sgi.com +0 -7
#   Move accounting function calls out of critical vm code paths
# 
# mm/memory.c
#   2005/03/04 22:41:14-08:00 clameter@sgi.com +3 -16
#   Move accounting function calls out of critical vm code paths
# 
# kernel/sched.c
#   2005/03/04 22:41:14-08:00 clameter@sgi.com +5 -0
#   Move accounting function calls out of critical vm code paths
# 
# kernel/exit.c
#   2005/03/04 22:41:14-08:00 clameter@sgi.com +2 -2
#   Move accounting function calls out of critical vm code paths
# 
# kernel/acct.c
#   2005/03/04 22:41:14-08:00 clameter@sgi.com +1 -3
#   Move accounting function calls out of critical vm code paths
# 
# include/linux/mm.h
#   2005/03/04 22:41:14-08:00 clameter@sgi.com +1 -1
#   Move accounting function calls out of critical vm code paths
# 
# include/linux/acct.h
#   2005/03/04 22:41:14-08:00 clameter@sgi.com +2 -2
#   Move accounting function calls out of critical vm code paths
# 
# fs/exec.c
#   2005/03/04 22:41:14-08:00 clameter@sgi.com +2 -2
#   Move accounting function calls out of critical vm code paths
# 
# ChangeSet
#   2005/03/05 09:26:09-08:00 arjan@infradead.org 
#   [PATCH] Randomisation: top-of-stack randomization
#   
#   In addition to randomisation of the stack pointer within the stack, the stack
#   itself should be randomized too.  We need both approaches, we can only
#   randomize the stack itself in pagesize increments.  However randomizing large
#   ranges with the stackpointer runs into the situation where a huge chunk of the
#   stack rlimit is used by the randomisation; this is undesirable so we need to
#   do both.
#   
#   Signed-off-by: Arjan van de Ven <arjan@infradead.org>
#   Signed-off-by: Ingo Molnar <mingo@elte.hu>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# fs/exec.c
#   2005/03/04 23:17:25-08:00 arjan@infradead.org +1 -1
#   Randomisation: top-of-stack randomization
# 
# fs/binfmt_elf.c
#   2005/03/04 23:17:16-08:00 arjan@infradead.org +16 -1
#   Randomisation: top-of-stack randomization
# 
# ChangeSet
#   2005/03/05 09:25:55-08:00 arjan@infradead.org 
#   [PATCH] Randomisation: add ADDR_NO_RANDOMIZE personality
#   
#   Introduce a personality that disables randomisation, so that users can use
#   setarch and related commands to run specific applications without
#   randomisation.
#   
#   Signed-off-by: Arjan van de Ven <arjan@infradead.org>
#   Signed-off-by: Ingo Molnar <mingo@elte.hu>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/linux/personality.h
#   2005/03/04 22:41:14-08:00 arjan@infradead.org +2 -1
#   Randomisation: add ADDR_NO_RANDOMIZE personality
# 
# fs/binfmt_elf.c
#   2005/03/04 23:17:25-08:00 arjan@infradead.org +1 -1
#   Randomisation: add ADDR_NO_RANDOMIZE personality
# 
# ChangeSet
#   2005/03/05 09:25:41-08:00 arjan@infradead.org 
#   [PATCH] Randomisation: enable by default
#   
#   Signed-off-by: Arjan van de Ven <arjan@infradead.org>
#   Signed-off-by: Ingo Molnar <mingo@elte.hu>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# kernel/sysctl.c
#   2005/03/04 22:41:14-08:00 arjan@infradead.org +1 -1
#   Randomisation: enable by default
# 
# include/linux/kernel.h
#   2005/03/04 22:41:14-08:00 arjan@infradead.org +1 -1
#   Randomisation: enable by default
# 
# ChangeSet
#   2005/03/05 09:25:27-08:00 arjan@infradead.org 
#   [PATCH] Randomisation: mmap randomisation
#   
#   The patch below randomizes the starting point of the mmap area.
#   
#   This has the effect that all non-prelinked shared libaries and all bigger
#   malloc()s will be randomized between various invocations of the binary. 
#   Prelinked binaries get a address-hint from ld.so in their mmap and are thus
#   exempt from this randomisation, in order to not break the prelink advantage.
#   The randomisation range is 1 megabyte (this is bigger than the stack
#   randomisation since the stack randomisation only needs 16 bytes alignment
#   while the mmap needs page alignment, a 64kb range would not have given enough
#   entropy to be effective)
#   
#   Signed-off-by: Arjan van de Ven <arjan@infradead.org>
#   Signed-off-by: Ingo Molnar <mingo@elte.hu>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/i386/mm/mmap.c
#   2005/03/04 22:41:14-08:00 arjan@infradead.org +6 -1
#   Randomisation: mmap randomisation
# 
# ChangeSet
#   2005/03/05 09:25:13-08:00 arjan@infradead.org 
#   [PATCH] Randomisation: stack randomisation
#   
#   The patch below replaces the existing 8Kb randomisation of the userspace stack
#   pointer (which is currently only done for Hyperthreaded P-IVs) with a more
#   general randomisation over a 64Kb range.  64Kb is not a lot, but it's a start
#   and once the dust settles we can increase this value to a more agressive
#   value.
#   
#   Signed-off-by: Arjan van de Ven <arjan@infradead.org>
#   Signed-off-by: Ingo Molnar <mingo@elte.hu>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/asm-x86_64/system.h
#   2005/03/04 22:41:13-08:00 arjan@infradead.org +2 -0
#   Randomisation: stack randomisation
# 
# include/asm-v850/system.h
#   2005/03/04 22:41:13-08:00 arjan@infradead.org +2 -0
#   Randomisation: stack randomisation
# 
# include/asm-sparc64/system.h
#   2005/03/04 22:41:13-08:00 arjan@infradead.org +2 -0
#   Randomisation: stack randomisation
# 
# include/asm-sparc/system.h
#   2005/03/04 22:41:13-08:00 arjan@infradead.org +2 -0
#   Randomisation: stack randomisation
# 
# include/asm-sh64/system.h
#   2005/03/04 22:41:13-08:00 arjan@infradead.org +2 -0
#   Randomisation: stack randomisation
# 
# include/asm-sh/system.h
#   2005/03/04 22:41:13-08:00 arjan@infradead.org +2 -0
#   Randomisation: stack randomisation
# 
# include/asm-s390/system.h
#   2005/03/04 22:41:13-08:00 arjan@infradead.org +2 -0
#   Randomisation: stack randomisation
# 
# include/asm-ppc64/system.h
#   2005/03/04 22:41:13-08:00 arjan@infradead.org +2 -0
#   Randomisation: stack randomisation
# 
# include/asm-ppc/system.h
#   2005/03/04 23:17:21-08:00 arjan@infradead.org +2 -0
#   Randomisation: stack randomisation
# 
# include/asm-parisc/system.h
#   2005/03/04 22:41:13-08:00 arjan@infradead.org +2 -0
#   Randomisation: stack randomisation
# 
# include/asm-mips/system.h
#   2005/03/04 22:41:13-08:00 arjan@infradead.org +2 -0
#   Randomisation: stack randomisation
# 
# include/asm-m68knommu/system.h
#   2005/03/04 22:41:13-08:00 arjan@infradead.org +1 -0
#   Randomisation: stack randomisation
# 
# include/asm-m68k/system.h
#   2005/03/04 22:41:13-08:00 arjan@infradead.org +2 -0
#   Randomisation: stack randomisation
# 
# include/asm-m32r/system.h
#   2005/03/04 22:41:13-08:00 arjan@infradead.org +2 -0
#   Randomisation: stack randomisation
# 
# include/asm-ia64/system.h
#   2005/03/04 22:41:13-08:00 arjan@infradead.org +3 -0
#   Randomisation: stack randomisation
# 
# include/asm-i386/system.h
#   2005/03/04 22:41:13-08:00 arjan@infradead.org +2 -0
#   Randomisation: stack randomisation
# 
# include/asm-h8300/system.h
#   2005/03/04 22:41:13-08:00 arjan@infradead.org +2 -0
#   Randomisation: stack randomisation
# 
# include/asm-frv/system.h
#   2005/03/04 22:41:13-08:00 arjan@infradead.org +2 -0
#   Randomisation: stack randomisation
# 
# include/asm-cris/system.h
#   2005/03/04 22:41:13-08:00 arjan@infradead.org +2 -0
#   Randomisation: stack randomisation
# 
# include/asm-arm26/system.h
#   2005/03/04 22:41:13-08:00 arjan@infradead.org +2 -0
#   Randomisation: stack randomisation
# 
# include/asm-arm/system.h
#   2005/03/04 22:41:13-08:00 arjan@infradead.org +2 -0
#   Randomisation: stack randomisation
# 
# include/asm-alpha/system.h
#   2005/03/04 22:41:13-08:00 arjan@infradead.org +2 -0
#   Randomisation: stack randomisation
# 
# fs/exec.c
#   2005/03/04 23:17:25-08:00 arjan@infradead.org +2 -1
#   Randomisation: stack randomisation
# 
# fs/binfmt_elf.c
#   2005/03/04 23:17:26-08:00 arjan@infradead.org +2 -9
#   Randomisation: stack randomisation
# 
# arch/x86_64/kernel/process.c
#   2005/03/04 22:41:13-08:00 arjan@infradead.org +8 -0
#   Randomisation: stack randomisation
# 
# arch/i386/kernel/process.c
#   2005/03/04 22:41:13-08:00 arjan@infradead.org +7 -0
#   Randomisation: stack randomisation
# 
# ChangeSet
#   2005/03/05 09:24:57-08:00 arjan@infradead.org 
#   [PATCH] Randomisation: add PF_RANDOMIZE
#   
#   Even though there is a global flag to disable randomisation, it's useful to
#   have a per process flag too; the patch below introduces this per process flag
#   and automatically sets it for "new" binaries.
#   
#   Eventually we will want to tie this to the legacy-va-space personality
#   
#   Signed-off-by: Arjan van de Ven <arjan@infradead.org>
#   Signed-off-by: Ingo Molnar <mingo@elte.hu>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/linux/sched.h
#   2005/03/04 22:41:13-08:00 arjan@infradead.org +1 -0
#   Randomisation: add PF_RANDOMIZE
# 
# fs/exec.c
#   2005/03/04 23:17:27-08:00 arjan@infradead.org +1 -0
#   Randomisation: add PF_RANDOMIZE
# 
# fs/binfmt_elf.c
#   2005/03/04 23:17:27-08:00 arjan@infradead.org +2 -0
#   Randomisation: add PF_RANDOMIZE
# 
# ChangeSet
#   2005/03/05 09:24:44-08:00 arjan@infradead.org 
#   [PATCH] Randomisation: infrastructure
#   
#   The patch below introduces get_random_int() and randomize_range(), two helpers
#   used in later patches in the series.  get_random_int() shares the tcp/ip
#   random number stuff so the CONFIG_INET ifdef needs to move slightly, and to
#   reduce the damange due to that, secure_ip_id() needs to move inside random.c
#   From: Frank Sorenson <frank@tuxrocks.com>
#   Acked-By: Jeff Dike <jdike@addtoit.com>
#   
#   The stack randomization patches that went into 2.6.11-rc3-mm1 broke
#   compilation of ARCH=um.  This patch fixes compiling by adding arch_align_stack
#   back in.
#   
#   Signed-off-by: Arjan van de Ven <arjan@infradead.org>
#   Signed-off-by: Ingo Molnar <mingo@elte.hu>
#   Signed-off-by: Frank Sorenson <frank@tuxrocks.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/linux/random.h
#   2005/03/04 22:38:34-08:00 arjan@infradead.org +3 -0
#   Randomisation: infrastructure
# 
# drivers/char/random.c
#   2005/03/04 22:38:34-08:00 arjan@infradead.org +62 -22
#   Randomisation: infrastructure
# 
# arch/um/kernel/process_kern.c
#   2005/03/04 22:38:38-08:00 arjan@infradead.org +9 -0
#   Randomisation: infrastructure
# 
# ChangeSet
#   2005/03/05 09:24:30-08:00 arjan@infradead.org 
#   [PATCH] Randomisation: global sysctl
#   
#   This first patch of the series introduces a sysctl (default off) that
#   enables/disables the randomisation feature globally.  Since randomisation may
#   make it harder to debug really tricky situations (reproducability goes down),
#   the sysadmin needs a way to disable it globally.
#   
#   Signed-off-by: Arjan van de Ven <arjan@infradead.org>
#   Signed-off-by: Ingo Molnar <mingo@elte.hu>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# kernel/sysctl.c
#   2005/03/04 23:17:26-08:00 arjan@infradead.org +11 -0
#   Randomisation: global sysctl
# 
# include/linux/sysctl.h
#   2005/03/04 22:32:56-08:00 arjan@infradead.org +1 -0
#   Randomisation: global sysctl
# 
# include/linux/kernel.h
#   2005/03/04 23:17:26-08:00 arjan@infradead.org +6 -0
#   Randomisation: global sysctl
# 
# ChangeSet
#   2005/03/05 09:24:16-08:00 galak@freescale.com 
#   [PATCH] initialize a spin lock in CPM2 uart driver
#   
#   Static initialization of spin locks that are otherwise accessed prior to
#   initialization.
#   
#   Signed-off-by: Jaka Mocnik <jaka@activetools.si>
#   Signed-off-by: Kumar Gala <kumar.gala@freescale.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/serial/cpm_uart/cpm_uart_core.c
#   2005/03/04 22:32:56-08:00 galak@freescale.com +6 -0
#   initialize a spin lock in CPM2 uart driver
# 
# ChangeSet
#   2005/03/05 09:24:03-08:00 sean.hefty@intel.com 
#   [PATCH] IB: MAD cancel callbacks from thread
#   
#   Modify ib_cancel_mad() to invoke a user's send completion callback from
#   a different thread context than that used by the caller.  This allows a
#   caller to hold a lock while calling cancel that is also acquired from
#   their send handler.
#   
#   Signed-off-by: Sean Hefty <sean.hefty@intel.com>
#   Signed-off-by: Roland Dreier <roland@topspin.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/infiniband/core/mad_priv.h
#   2005/03/04 22:32:56-08:00 sean.hefty@intel.com +2 -0
#   IB: MAD cancel callbacks from thread
# 
# drivers/infiniband/core/mad.c
#   2005/03/04 22:32:56-08:00 sean.hefty@intel.com +39 -11
#   IB: MAD cancel callbacks from thread
# 
# ChangeSet
#   2005/03/05 09:23:48-08:00 mst@mellanox.co.il 
#   [PATCH] IB/mthca: implement query of device caps
#   
#   Set device_cap_flags field in mthca's query_device method.
#   
#   Signed-off-by: Michael S. Tsirkin <mst@mellanox.co.il>
#   Signed-off-by: Roland Dreier <roland@topspin.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/infiniband/hw/mthca/mthca_provider.c
#   2005/03/04 22:32:56-08:00 mst@mellanox.co.il +8 -5
#   IB/mthca: implement query of device caps
# 
# drivers/infiniband/hw/mthca/mthca_main.c
#   2005/03/04 22:32:56-08:00 mst@mellanox.co.il +27 -0
#   IB/mthca: implement query of device caps
# 
# drivers/infiniband/hw/mthca/mthca_dev.h
#   2005/03/04 22:32:56-08:00 mst@mellanox.co.il +1 -0
#   IB/mthca: implement query of device caps
# 
# drivers/infiniband/hw/mthca/mthca_cmd.h
#   2005/03/04 22:32:56-08:00 mst@mellanox.co.il +15 -1
#   IB/mthca: implement query of device caps
# 
# ChangeSet
#   2005/03/05 09:23:36-08:00 mst@mellanox.co.il 
#   [PATCH] IB/mthca: QP locking optimization
#   
#   1. Split the QP spinlock into separate send and receive locks.
#   
#      The only place where we have to lock both is upon modify_qp, and
#      that is not on data path.
#   
#   2. Avoid taking any QP locks when polling CQ.
#   
#      This last part is achieved by getting rid of the cur field in
#      mthca_wq, and calculating the number of outstanding WQEs by
#      comparing the head and tail fields.  head is only updated by
#      post, tail is only updated by poll.
#   
#      In a rare case where an overrun is detected, a CQ is locked and the
#      overrun condition is re-tested, to avoid any potential for stale
#      tail values.
#   
#   Signed-off-by: Michael S. Tsirkin <mst@mellanox.co.il>
#   Signed-off-by: Roland Dreier <roland@topspin.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/infiniband/hw/mthca/mthca_qp.c
#   2005/03/04 22:32:56-08:00 mst@mellanox.co.il +77 -46
#   IB/mthca: QP locking optimization
# 
# drivers/infiniband/hw/mthca/mthca_provider.h
#   2005/03/04 22:32:56-08:00 mst@mellanox.co.il +11 -10
#   IB/mthca: QP locking optimization
# 
# drivers/infiniband/hw/mthca/mthca_cq.c
#   2005/03/04 22:32:56-08:00 mst@mellanox.co.il +2 -16
#   IB/mthca: QP locking optimization
# 
# ChangeSet
#   2005/03/05 09:23:21-08:00 roland@topspin.com 
#   [PATCH] IB/mthca: mem-free multicast table
#   
#   Tie up one last loose end by mapping enough context memory to cover
#   the whole multicast table during initialization, and then enable
#   mem-free mode.  mthca now supports enough of mem-free mode so that
#   IPoIB works with a mem-free HCA.
#   
#   Signed-off-by: Roland Dreier <roland@topspin.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/infiniband/hw/mthca/mthca_main.c
#   2005/03/04 23:17:29-08:00 roland@topspin.com +28 -9
#   IB/mthca: mem-free multicast table
# 
# drivers/infiniband/hw/mthca/mthca_dev.h
#   2005/03/04 23:17:29-08:00 roland@topspin.com +3 -2
#   IB/mthca: mem-free multicast table
# 
# ChangeSet
#   2005/03/05 09:23:08-08:00 roland@topspin.com 
#   [PATCH] IB/mthca: mem-free work request posting
#   
#   Implement posting send and receive work requests for mem-free mode.
#   Also tidy up a few things in send/receive posting for Tavor mode (fix
#   smp_wmb()s that should really be just wmb()s, annotate tests in the
#   fast path with likely()/unlikely()).
#   
#   Signed-off-by: Roland Dreier <roland@topspin.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/infiniband/hw/mthca/mthca_qp.c
#   2005/03/04 23:17:29-08:00 roland@topspin.com +266 -26
#   IB/mthca: mem-free work request posting
# 
# drivers/infiniband/hw/mthca/mthca_provider.c
#   2005/03/04 23:17:29-08:00 roland@topspin.com +7 -4
#   IB/mthca: mem-free work request posting
# 
# drivers/infiniband/hw/mthca/mthca_dev.h
#   2005/03/04 23:17:29-08:00 roland@topspin.com +8 -4
#   IB/mthca: mem-free work request posting
# 
# ChangeSet
#   2005/03/05 09:22:54-08:00 roland@topspin.com 
#   [PATCH] IB/mthca: mem-free address vectors
#   
#   Update address vector handling to support mem-free mode.  In mem-free
#   mode, the address vector (in hardware format) is copied by the driver
#   into each send work queue entry, so our address handle creation can
#   become pretty trivial: we just kmalloc() a buffer to hold the
#   formatted address vector.
#   
#   Signed-off-by: Roland Dreier <roland@topspin.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/infiniband/hw/mthca/mthca_provider.h
#   2005/03/04 23:17:29-08:00 roland@topspin.com +11 -5
#   IB/mthca: mem-free address vectors
# 
# drivers/infiniband/hw/mthca/mthca_av.c
#   2005/03/04 22:32:55-08:00 roland@topspin.com +34 -12
#   IB/mthca: mem-free address vectors
# 
# ChangeSet
#   2005/03/05 09:22:41-08:00 roland@topspin.com 
#   [PATCH] IB/mthca: mem-free QP initialization
#   
#   Update QP initialization and cleanup to handle mem-free mode.  In
#   mem-free mode, work queue sizes have to be rounded up to a power of 2,
#   we need to allocate doorbells, there must be memory mapped for the
#   entries in the QP and extended QP context table that we use, and the
#   entries of the receive queue must be initialized.
#   
#   Signed-off-by: Roland Dreier <roland@topspin.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/infiniband/hw/mthca/mthca_qp.c
#   2005/03/04 23:17:29-08:00 roland@topspin.com +175 -30
#   IB/mthca: mem-free QP initialization
# 
# drivers/infiniband/hw/mthca/mthca_provider.h
#   2005/03/04 23:17:29-08:00 roland@topspin.com +3 -0
#   IB/mthca: mem-free QP initialization
# 
# ChangeSet
#   2005/03/05 09:22:27-08:00 roland@topspin.com 
#   [PATCH] IB/mthca: mem-free CQ operations
#   
#   Add support for CQ data path operations (request notification, update
#   consumer index) in mem-free mode.
#   
#   Signed-off-by: Roland Dreier <roland@topspin.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/infiniband/hw/mthca/mthca_qp.c
#   2005/03/04 23:17:30-08:00 roland@topspin.com +5 -2
#   IB/mthca: mem-free CQ operations
# 
# drivers/infiniband/hw/mthca/mthca_provider.h
#   2005/03/04 23:17:30-08:00 roland@topspin.com +1 -1
#   IB/mthca: mem-free CQ operations
# 
# drivers/infiniband/hw/mthca/mthca_provider.c
#   2005/03/04 23:17:29-08:00 roland@topspin.com +5 -8
#   IB/mthca: mem-free CQ operations
# 
# drivers/infiniband/hw/mthca/mthca_dev.h
#   2005/03/04 23:17:29-08:00 roland@topspin.com +3 -3
#   IB/mthca: mem-free CQ operations
# 
# drivers/infiniband/hw/mthca/mthca_cq.c
#   2005/03/04 23:17:29-08:00 roland@topspin.com +79 -27
#   IB/mthca: mem-free CQ operations
# 
# ChangeSet
#   2005/03/05 09:22:12-08:00 roland@topspin.com 
#   [PATCH] IB/mthca: mem-free CQ initialization
#   
#   Update CQ initialization and cleanup to handle mem-free mode: we need
#   to make sure the HCA has memory mapped for the entry in the CQ context
#   table we will use and also allocate doorbell records.
#   
#   Signed-off-by: Roland Dreier <roland@topspin.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/infiniband/hw/mthca/mthca_provider.h
#   2005/03/04 23:17:30-08:00 roland@topspin.com +8 -0
#   IB/mthca: mem-free CQ initialization
# 
# drivers/infiniband/hw/mthca/mthca_cq.c
#   2005/03/04 23:17:30-08:00 roland@topspin.com +45 -3
#   IB/mthca: mem-free CQ initialization
# 
# ChangeSet
#   2005/03/05 09:21:58-08:00 roland@topspin.com 
#   [PATCH] IB/mthca: refactor CQ buffer allocate/free
#   
#   Factor the allocation and freeing of completion queue buffers into
#   mthca_alloc_cq_buf() and mthca_free_cq_buf().  This makes the code
#   more readable and will eventually make handling userspace CQs simpler
#   (the kernel doesn't have to allocate a buffer at all).
#   
#   Signed-off-by: Roland Dreier <roland@topspin.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/infiniband/hw/mthca/mthca_provider.c
#   2005/03/04 23:17:30-08:00 roland@topspin.com +1 -2
#   IB/mthca: refactor CQ buffer allocate/free
# 
# drivers/infiniband/hw/mthca/mthca_cq.c
#   2005/03/04 23:17:30-08:00 roland@topspin.com +84 -78
#   IB/mthca: refactor CQ buffer allocate/free
# 
# ChangeSet
#   2005/03/05 09:21:44-08:00 roland@topspin.com 
#   [PATCH] IB/mthca: mem-free doorbell record writing
#   
#   Add a mthca_write_db_rec() to wrap writing doorbell records.  On
#   64-bit archs, this is just a 64-bit write, while on 32-bit archs it
#   splits the write into two 32-bit writes with a memory barrier to make
#   sure the two halves of the record are written in the correct order.
#   
#   Signed-off-by: Roland Dreier <roland@topspin.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/infiniband/hw/mthca/mthca_doorbell.h
#   2005/03/04 22:32:55-08:00 roland@topspin.com +12 -0
#   IB/mthca: mem-free doorbell record writing
# 
# ChangeSet
#   2005/03/05 09:21:30-08:00 roland@topspin.com 
#   [PATCH] IB/mthca: mem-free doorbell record allocation
#   
#   Mem-free mode requires the driver to allocate additional doorbell pages
#   for each user access region.  Add support for this in mthca_memfree.c,
#   and have the driver allocate a table in db_tab for kernel use.
#   
#   Signed-off-by: Roland Dreier <roland@topspin.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/infiniband/hw/mthca/mthca_uar.c
#   2005/03/04 22:32:54-08:00 roland@topspin.com +9 -0
#   IB/mthca: mem-free doorbell record allocation
# 
# drivers/infiniband/hw/mthca/mthca_profile.c
#   2005/03/04 22:32:54-08:00 roland@topspin.com +5 -3
#   IB/mthca: mem-free doorbell record allocation
# 
# drivers/infiniband/hw/mthca/mthca_memfree.h
#   2005/03/04 22:32:54-08:00 roland@topspin.com +33 -0
#   IB/mthca: mem-free doorbell record allocation
# 
# drivers/infiniband/hw/mthca/mthca_memfree.c
#   2005/03/04 22:32:54-08:00 roland@topspin.com +196 -0
#   IB/mthca: mem-free doorbell record allocation
# 
# drivers/infiniband/hw/mthca/mthca_dev.h
#   2005/03/04 23:17:30-08:00 roland@topspin.com +4 -3
#   IB/mthca: mem-free doorbell record allocation
# 
# ChangeSet
#   2005/03/05 09:21:17-08:00 roland@topspin.com 
#   [PATCH] IB/mthca: tweak MAP_ICM_page firmware command
#   
#   Have MAP_ICM_page() firmware command map assume pages are always the
#   HCA-native 4K size rather than using the kernel's page size.  This
#   will make handling doorbell pages for mem-free mode simpler.
#   
#   Signed-off-by: Roland Dreier <roland@topspin.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/infiniband/hw/mthca/mthca_cmd.c
#   2005/03/04 22:32:54-08:00 roland@topspin.com +1 -1
#   IB/mthca: tweak MAP_ICM_page firmware command
# 
# ChangeSet
#   2005/03/05 09:21:04-08:00 roland@topspin.com 
#   [PATCH] IB/mthca: tweak firmware command debug messages
#   
#   Slightly improve debugging output for UNMAP_ICM and MODIFY_QP firmware commands.
#   
#   Signed-off-by: Roland Dreier <roland@topspin.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/infiniband/hw/mthca/mthca_cmd.c
#   2005/03/04 23:17:31-08:00 roland@topspin.com +5 -2
#   IB/mthca: tweak firmware command debug messages
# 
# ChangeSet
#   2005/03/05 09:20:51-08:00 roland@topspin.com 
#   [PATCH] IB/mthca: mem-free interrupt handling
#   
#   Update interrupt handling code to handle mem-free mode.  While we're
#   at it, improve the Tavor interrupt handling to avoid an extra MMIO
#   read of the event cause register.
#   
#   Signed-off-by: Roland Dreier <roland@topspin.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/infiniband/hw/mthca/mthca_provider.h
#   2005/03/04 23:17:30-08:00 roland@topspin.com +1 -1
#   IB/mthca: mem-free interrupt handling
# 
# drivers/infiniband/hw/mthca/mthca_main.c
#   2005/03/04 23:17:29-08:00 roland@topspin.com +10 -9
#   IB/mthca: mem-free interrupt handling
# 
# drivers/infiniband/hw/mthca/mthca_eq.c
#   2005/03/04 22:32:54-08:00 roland@topspin.com +120 -39
#   IB/mthca: mem-free interrupt handling
# 
# drivers/infiniband/hw/mthca/mthca_dev.h
#   2005/03/04 23:17:30-08:00 roland@topspin.com +1 -0
#   IB/mthca: mem-free interrupt handling
# 
# ChangeSet
#   2005/03/05 09:20:37-08:00 roland@topspin.com 
#   [PATCH] IB/mthca: mem-free EQ initialization
#   
#   Add code to initialize EQ context properly in both Tavor and mem-free mode.
#   
#   Signed-off-by: Roland Dreier <roland@topspin.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/infiniband/hw/mthca/mthca_eq.c
#   2005/03/04 23:17:31-08:00 roland@topspin.com +13 -6
#   IB/mthca: mem-free EQ initialization
# 
# ChangeSet
#   2005/03/05 09:20:23-08:00 roland@topspin.com 
#   [PATCH] IB/mthca: mem-free memory region support
#   
#   Add support for mem-free mode to memory region code.  This mostly
#   amounts to properly munging between keys and indices.
#   
#   Signed-off-by: Roland Dreier <roland@topspin.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/infiniband/hw/mthca/mthca_mr.c
#   2005/03/04 22:32:54-08:00 roland@topspin.com +33 -13
#   IB/mthca: mem-free memory region support
# 
# ChangeSet
#   2005/03/05 09:20:10-08:00 roland@topspin.com 
#   [PATCH] IB/mthca: dynamic context memory mapping for mem-free mode
#   
#   Add support for mapping more memory into HCA's context to cover
#   context tables when new objects are allocated.  Pass the object
#   size into mthca_alloc_icm_table(), reference count the ICM chunks,
#   and add new mthca_table_get() and mthca_table_put() functions to
#   handle mapping memory when allocating or destroying objects.
#   
#   Signed-off-by: Roland Dreier <roland@topspin.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/infiniband/hw/mthca/mthca_memfree.h
#   2005/03/04 23:17:30-08:00 roland@topspin.com +9 -3
#   IB/mthca: dynamic context memory mapping for mem-free mode
# 
# drivers/infiniband/hw/mthca/mthca_memfree.c
#   2005/03/04 23:17:30-08:00 roland@topspin.com +70 -7
#   IB/mthca: dynamic context memory mapping for mem-free mode
# 
# drivers/infiniband/hw/mthca/mthca_main.c
#   2005/03/04 23:17:31-08:00 roland@topspin.com +10 -15
#   IB/mthca: dynamic context memory mapping for mem-free mode
# 
# ChangeSet
#   2005/03/05 09:19:57-08:00 roland@topspin.com 
#   [PATCH] IB/mthca: add UAR allocation
#   
#   Add support for allocating user access regions (UARs).  Use this to
#   allocate a region for kernel at driver init instead using hard-coded
#   MTHCA_KAR_PAGE index.
#   
#   Signed-off-by: Roland Dreier <roland@topspin.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/infiniband/hw/mthca/mthca_uar.c
#   2005/03/04 23:17:30-08:00 roland@topspin.com +69 -0
#   IB/mthca: add UAR allocation
# 
# drivers/infiniband/hw/mthca/mthca_uar.c
#   2005/03/04 23:17:30-08:00 roland@topspin.com +0 -0
#   BitKeeper file /home/torvalds/v2.6/linux/drivers/infiniband/hw/mthca/mthca_uar.c
# 
# drivers/infiniband/hw/mthca/mthca_qp.c
#   2005/03/04 23:17:30-08:00 roland@topspin.com +1 -1
#   IB/mthca: add UAR allocation
# 
# drivers/infiniband/hw/mthca/mthca_provider.h
#   2005/03/04 23:17:31-08:00 roland@topspin.com +5 -0
#   IB/mthca: add UAR allocation
# 
# drivers/infiniband/hw/mthca/mthca_profile.c
#   2005/03/04 23:17:30-08:00 roland@topspin.com +1 -0
#   IB/mthca: add UAR allocation
# 
# drivers/infiniband/hw/mthca/mthca_main.c
#   2005/03/04 23:17:31-08:00 roland@topspin.com +42 -21
#   IB/mthca: add UAR allocation
# 
# drivers/infiniband/hw/mthca/mthca_eq.c
#   2005/03/04 23:17:31-08:00 roland@topspin.com +1 -1
#   IB/mthca: add UAR allocation
# 
# drivers/infiniband/hw/mthca/mthca_dev.h
#   2005/03/04 23:17:31-08:00 roland@topspin.com +14 -1
#   IB/mthca: add UAR allocation
# 
# drivers/infiniband/hw/mthca/mthca_cq.c
#   2005/03/04 23:17:30-08:00 roland@topspin.com +1 -1
#   IB/mthca: add UAR allocation
# 
# drivers/infiniband/hw/mthca/Makefile
#   2005/03/04 22:32:53-08:00 roland@topspin.com +1 -1
#   IB/mthca: add UAR allocation
# 
# ChangeSet
#   2005/03/05 09:19:43-08:00 roland@topspin.com 
#   [PATCH] IB/mthca: map registers for mem-free mode
#   
#   Move the request/ioremap of regions related to event handling into
#   mthca_eq.c.  Map the correct regions depending on whether we're in
#   Tavor or native mem-free mode.
#   
#   Signed-off-by: Roland Dreier <roland@topspin.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/infiniband/hw/mthca/mthca_main.c
#   2005/03/04 23:17:32-08:00 roland@topspin.com +15 -81
#   IB/mthca: map registers for mem-free mode
# 
# drivers/infiniband/hw/mthca/mthca_eq.c
#   2005/03/04 23:17:32-08:00 roland@topspin.com +135 -3
#   IB/mthca: map registers for mem-free mode
# 
# drivers/infiniband/hw/mthca/mthca_dev.h
#   2005/03/04 23:17:32-08:00 roland@topspin.com +10 -2
#   IB/mthca: map registers for mem-free mode
# 
# drivers/infiniband/hw/mthca/mthca_config_reg.h
#   2005/03/04 22:32:53-08:00 roland@topspin.com +1 -0
#   IB/mthca: map registers for mem-free mode
# 
# ChangeSet
#   2005/03/05 09:19:29-08:00 mst@mellanox.co.il 
#   [PATCH] IB: remove unsignaled receives
#   
#   Remove support for unsignaled receive requests.  This is a
#   non-standard extension to the IB spec that is not used by any known
#   applications or protocols, and is not supported by newer hardware.
#   
#   Signed-off-by: Michael S. Tsirkin <mst@mellanox.co.il>
#   Signed-off-by: Roland Dreier <roland@topspin.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/infiniband/ulp/ipoib/ipoib_verbs.c
#   2005/03/04 22:32:53-08:00 mst@mellanox.co.il +0 -1
#   IB: remove unsignaled receives
# 
# drivers/infiniband/ulp/ipoib/ipoib_ib.c
#   2005/03/04 22:32:53-08:00 mst@mellanox.co.il +0 -1
#   IB: remove unsignaled receives
# 
# drivers/infiniband/include/ib_verbs.h
#   2005/03/04 22:32:53-08:00 mst@mellanox.co.il +0 -7
#   IB: remove unsignaled receives
# 
# drivers/infiniband/hw/mthca/mthca_qp.c
#   2005/03/04 23:17:32-08:00 mst@mellanox.co.il +7 -14
#   IB: remove unsignaled receives
# 
# drivers/infiniband/hw/mthca/mthca_provider.h
#   2005/03/04 23:17:32-08:00 mst@mellanox.co.il +1 -1
#   IB: remove unsignaled receives
# 
# drivers/infiniband/hw/mthca/mthca_provider.c
#   2005/03/04 23:17:30-08:00 mst@mellanox.co.il +2 -2
#   IB: remove unsignaled receives
# 
# drivers/infiniband/hw/mthca/mthca_dev.h
#   2005/03/04 23:17:32-08:00 mst@mellanox.co.il +0 -2
#   IB: remove unsignaled receives
# 
# drivers/infiniband/core/mad.c
#   2005/03/04 23:17:28-08:00 mst@mellanox.co.il +0 -2
#   IB: remove unsignaled receives
# 
# ChangeSet
#   2005/03/05 09:19:15-08:00 roland@topspin.com 
#   [PATCH] IB/mthca: CQ cleanups
#   
#   Simplify some of the code for CQ handling slightly.
#   
#   Signed-off-by: Roland Dreier <roland@topspin.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/infiniband/hw/mthca/mthca_cq.c
#   2005/03/04 23:17:32-08:00 roland@topspin.com +6 -10
#   IB/mthca: CQ cleanups
# 
# ChangeSet
#   2005/03/05 09:19:00-08:00 mst@mellanox.co.il 
#   [PATCH] IB/mthca: improve CQ locking part 2
#   
#   Locking during the poll cq operation can be reduced by locking the cq
#   while qp is being removed from the qp array.  This also avoids an
#   extra atomic operation for reference counting.
#   
#   Signed-off-by: Michael S. Tsirkin <mst@mellanox.co.il>
#   Signed-off-by: Roland Dreier <roland@topspin.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/infiniband/hw/mthca/mthca_qp.c
#   2005/03/04 23:17:32-08:00 mst@mellanox.co.il +33 -4
#   IB/mthca: improve CQ locking part 2
# 
# drivers/infiniband/hw/mthca/mthca_cq.c
#   2005/03/04 23:17:32-08:00 mst@mellanox.co.il +6 -10
#   IB/mthca: improve CQ locking part 2
# 
# ChangeSet
#   2005/03/05 09:18:47-08:00 mst@mellanox.co.il 
#   [PATCH] IB/mthca: improve CQ locking part 1
#   
#   Avoid taking the CQ table lock in the fast path path by using
#   synchronize_irq() after removing a CQ from the table to make sure that
#   no completion events are still in progress.  This gets a nice speedup
#   (about 4%) in IP over IB on my hardware.
#   
#   Signed-off-by: Michael S. Tsirkin <mst@mellanox.co.il>
#   Signed-off-by: Roland Dreier <roland@topspin.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/infiniband/hw/mthca/mthca_cq.c
#   2005/03/04 23:17:33-08:00 mst@mellanox.co.il +6 -7
#   IB/mthca: improve CQ locking part 1
# 
# ChangeSet
#   2005/03/05 09:18:33-08:00 mst@mellanox.co.il 
#   [PATCH] IB/mthca: CQ minor tweaks
#   
#   Clean up CQ code so that we only calculate the address of a CQ entry
#   once when using it.
#   
#   Signed-off-by: Michael S. Tsirkin <mst@mellanox.co.il>
#   Signed-off-by: Roland Dreier <roland@topspin.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/infiniband/hw/mthca/mthca_cq.c
#   2005/03/04 23:17:33-08:00 mst@mellanox.co.il +13 -13
#   IB/mthca: CQ minor tweaks
# 
# ChangeSet
#   2005/03/05 09:18:19-08:00 sean.hefty@intel.com 
#   [PATCH] IB: fix ib_find_cached_gid() port numbering
#   
#   Fix ib_find_cached_gid() to return the correct port number relative to
#   the port numbering used by the device.
#   
#   Signed-off-by: Sean Hefty <sean.hefty@intel.com>
#   Signed-off-by: Roland Dreier <roland@topspin.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/infiniband/core/cache.c
#   2005/03/04 22:32:52-08:00 sean.hefty@intel.com +1 -1
#   IB: fix ib_find_cached_gid() port numbering
# 
# ChangeSet
#   2005/03/05 09:18:04-08:00 roland@topspin.com 
#   [PATCH] IB/ipoib: fix locking on path deletion
#   
#   Fix up locking for IPoIB path table.  Make sure that destruction of address
#   handles, neighbour info and path structs is locked properly to avoid races and
#   deadlocks.  (Problem originally diagnosed by Shirley Ma)
#   
#   Signed-off-by: Roland Dreier <roland@topspin.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/infiniband/ulp/ipoib/ipoib_main.c
#   2005/03/04 22:32:52-08:00 roland@topspin.com +28 -9
#   IB/ipoib: fix locking on path deletion
# 
# ChangeSet
#   2005/03/05 09:17:51-08:00 xma@us.ibm.com 
#   [PATCH] IB/ipoib: don't call ipoib_put_ah with lock held
#   
#   ipoib_put_ah() may call ipoib_free_ah(), which might take the device's lock.
#   Therefore we need to make sure we don't call ipoib_put_ah() when holding the
#   lock already.
#   
#   Signed-off-by: Shirley Ma <xma@us.ibm.com>
#   Signed-off-by: Roland Dreier <roland@topspin.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/infiniband/ulp/ipoib/ipoib_multicast.c
#   2005/03/04 22:32:52-08:00 xma@us.ibm.com +7 -1
#   IB/ipoib: don't call ipoib_put_ah with lock held
# 
# drivers/infiniband/ulp/ipoib/ipoib_main.c
#   2005/03/04 23:17:33-08:00 xma@us.ibm.com +5 -1
#   IB/ipoib: don't call ipoib_put_ah with lock held
# 
# ChangeSet
#   2005/03/05 09:17:36-08:00 xma@us.ibm.com 
#   [PATCH] IB/ipoib: small fixes
#   
#   IPoIB small fixes: Initialize path->ah to NULL, and fix dereference after free
#   of neigh in error path of neigh_add_path().
#   
#   Signed-off-by: Shirley Ma <xma@us.ibm.com>
#   Signed-off-by: Roland Dreier <roland@topspin.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/infiniband/ulp/ipoib/ipoib_main.c
#   2005/03/04 23:17:34-08:00 xma@us.ibm.com +3 -2
#   IB/ipoib: small fixes
# 
# ChangeSet
#   2005/03/05 09:17:23-08:00 roland@topspin.com 
#   [PATCH] IB/ipoib: rename global symbols
#   
#   Make IPoIB data_debug_level module parameter static to the single file
#   where it is used.  Also Rename IPoIB module parameter variable from
#   "debug_level" to "ipoib_debug_level".  This avoids possible name
#   clashes if IPoIB is built into the kernel.  We use module_param_named
#   so that the user-visible parameter names remain the same.
#   
#   Signed-off-by: Tom Duffy <tduffy@sun.com>
#   Signed-off-by: Roland Dreier <roland@topspin.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/infiniband/ulp/ipoib/ipoib_main.c
#   2005/03/04 23:17:34-08:00 roland@topspin.com +2 -2
#   IB/ipoib: rename global symbols
# 
# drivers/infiniband/ulp/ipoib/ipoib_ib.c
#   2005/03/04 23:17:32-08:00 roland@topspin.com +1 -1
#   IB/ipoib: rename global symbols
# 
# drivers/infiniband/ulp/ipoib/ipoib.h
#   2005/03/04 22:32:52-08:00 roland@topspin.com +2 -2
#   IB/ipoib: rename global symbols
# 
# ChangeSet
#   2005/03/05 09:17:09-08:00 xma@us.ibm.com 
#   [PATCH] IB/ipoib: use list_for_each_entry_safe when required
#   
#   Change uses of list_for_each_entry() where the loop variable is freed
#   inside the loop to list_for_each_entry_safe().
#   
#   Signed-off-by: Shirley Ma <xma@us.ibm.com>
#   Signed-off-by: Roland Dreier <roland@topspin.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/infiniband/ulp/ipoib/ipoib_multicast.c
#   2005/03/04 23:17:34-08:00 xma@us.ibm.com +2 -2
#   IB/ipoib: use list_for_each_entry_safe when required
# 
# ChangeSet
#   2005/03/05 09:16:56-08:00 roland@topspin.com 
#   [PATCH] IB/ipoib: fix rx memory leak
#   
#   Fix memory leak when posting a receive buffer (pointed out by Shirley Ma).
#   
#   Signed-off-by: Roland Dreier <roland@topspin.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/infiniband/ulp/ipoib/ipoib_ib.c
#   2005/03/04 23:17:34-08:00 roland@topspin.com +3 -0
#   IB/ipoib: fix rx memory leak
# 
# ChangeSet
#   2005/03/05 09:16:43-08:00 roland@topspin.com 
#   [PATCH] IB/mthca: fix reset value endianness
#   
#   MTHCA_RESET_VALUE must always be swapped, since the HCA expects to see
#   it in big-endian order and we write it with writel.  This means on
#   little-endian systems we have to swap it to big-endian order before
#   writing, and on big-endian systems we need to swap it to make up for
#   the additional swap that writel will do.  This fixes resetting the HCA
#   on big-endian machines.
#   
#   Signed-off-by: Roland Dreier <roland@topspin.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/infiniband/hw/mthca/mthca_reset.c
#   2005/03/04 22:32:51-08:00 roland@topspin.com +1 -1
#   IB/mthca: fix reset value endianness
# 
# ChangeSet
#   2005/03/05 09:16:29-08:00 roland@topspin.com 
#   [PATCH] IB/mthca: add missing break
#   
#   Add missing break statements in switch in mthca_profile.c (pointed out
#   by Michael Tsirkin).
#   
#   Signed-off-by: Roland Dreier <roland@topspin.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/infiniband/hw/mthca/mthca_profile.c
#   2005/03/04 23:17:32-08:00 roland@topspin.com +2 -0
#   IB/mthca: add missing break
# 
# ChangeSet
#   2005/03/05 09:16:17-08:00 tduffy@sun.com 
#   [PATCH] IB: sparse fixes
#   
#   Fix some sparse warnings by making sure we have appropriate "extern"
#   declarations visible.
#   
#   Signed-off-by: Tom Duffy <tduffy@sun.com>
#   Signed-off-by: Hal Rosenstock (<halr@voltaire.com>
#   Signed-off-by: Roland Dreier <roland@topspin.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/infiniband/core/smi.c
#   2005/03/04 22:32:51-08:00 tduffy@sun.com +1 -1
#   IB: sparse fixes
# 
# drivers/infiniband/core/mad_priv.h
#   2005/03/04 23:17:28-08:00 tduffy@sun.com +2 -0
#   IB: sparse fixes
# 
# drivers/infiniband/core/cache.c
#   2005/03/04 23:17:33-08:00 tduffy@sun.com +2 -0
#   IB: sparse fixes
# 
# drivers/infiniband/core/agent.c
#   2005/03/04 22:32:51-08:00 tduffy@sun.com +1 -4
#   IB: sparse fixes
# 
# ChangeSet
#   2005/03/05 09:16:03-08:00 shaharf@voltaire.com 
#   [PATCH] IB: fix vendor MAD deregistration
#   
#   Fix bug when deregistering a vendor class MAD agent.
#   
#   Signed-off-by: Roland Dreier <roland@topspin.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/infiniband/core/mad_priv.h
#   2005/03/04 23:17:35-08:00 shaharf@voltaire.com +2 -2
#   IB: fix vendor MAD deregistration
# 
# drivers/infiniband/core/mad.c
#   2005/03/04 23:17:32-08:00 shaharf@voltaire.com +9 -4
#   IB: fix vendor MAD deregistration
# 
# ChangeSet
#   2005/03/05 09:15:49-08:00 halr@voltaire.com 
#   [PATCH] IB: simplify MAD code
#   
#   Remove unneeded MAD agent registration by using a single agent for
#   both directed-route and LID-routed MADs.
#   
#   Signed-off-by: Hal Rosenstock <halr@voltaire.com>
#   Signed-off-by: Roland Dreier <roland@topspin.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/infiniband/core/agent_priv.h
#   2005/03/04 22:32:50-08:00 halr@voltaire.com +1 -2
#   IB: simplify MAD code
# 
# drivers/infiniband/core/agent.c
#   2005/03/04 23:17:35-08:00 halr@voltaire.com +19 -42
#   IB: simplify MAD code
# 
# ChangeSet
#   2005/03/05 09:15:36-08:00 yuasa@hh.iij4u.or.jp 
#   [PATCH] audit mips fix
#   
#     CC      arch/mips/kernel/ptrace.o
#   arch/mips/kernel/ptrace.c: In function 'do_syscall_trace':
#   arch/mips/kernel/ptrace.c:310: warning: implicit declaration of function 'audit_syscall_entry'
#   arch/mips/kernel/ptrace.c:310: error: 'struct pt_regs' has no member named 'orig_eax'
#   arch/mips/kernel/ptrace.c:314: warning: implicit declaration of function 'audit_syscall_exit'
#   
#   Signed-off-by: Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# arch/mips/kernel/ptrace.c
#   2005/03/04 22:32:50-08:00 yuasa@hh.iij4u.or.jp +2 -1
#   audit mips fix
# 
# ChangeSet
#   2005/03/05 09:15:23-08:00 rddunlap@osdl.org 
#   [PATCH] aoe: fix printk warning
#   
#   u64's are not longlongs on sparc64 and ppc64.
#   
#   Signed-off-by: Randy Dunlap <rddunlap@osdl.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# drivers/block/aoe/aoeblk.c
#   2005/03/04 22:32:50-08:00 rddunlap@osdl.org +4 -2
#   aoe: fix printk warning
# 
# ChangeSet
#   2005/03/05 09:15:09-08:00 neilb@cse.unsw.edu.au 
#   [PATCH] nfsd: discard CACHE_HASHED flag, keeping information in refcount instead.
#   
#   This patch should fix a problem that has been experienced on at-least one
#   busy NFS server, but it has not had lots of testing yet.  If -mm could provide
#   that .....
#   
#   The rpc auth cache currently differentiates between a reference due to
#   being in a hash chain (signalled by CACHE_HASHED flag) and any other
#   reference (counted in refcnt).
#   
#   This is an artificial difference due to an historical accident, and it
#   makes cache_put unsafe.
#   
#   This patch removes the distinction so now existance in a hash chain is
#   counted just like any other reference.  Thus a race window in cache_put is
#   closed.
#   
#   Signed-off-by: Neil Brown <neilb@cse.unsw.edu.au>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# net/sunrpc/svcauth.c
#   2005/03/04 22:32:50-08:00 neilb@cse.unsw.edu.au +4 -4
#   nfsd: discard CACHE_HASHED flag, keeping information in refcount instead.
# 
# net/sunrpc/cache.c
#   2005/03/04 22:32:50-08:00 neilb@cse.unsw.edu.au +1 -3
#   nfsd: discard CACHE_HASHED flag, keeping information in refcount instead.
# 
# include/linux/sunrpc/cache.h
#   2005/03/04 22:32:50-08:00 neilb@cse.unsw.edu.au +5 -14
#   nfsd: discard CACHE_HASHED flag, keeping information in refcount instead.
# 
# ChangeSet
#   2005/03/05 09:14:56-08:00 neilb@cse.unsw.edu.au 
#   [PATCH] nfsd: change nfsd reply cache to use list.h lists
#   
#   also kmalloc the cache one entry at a time, instead of in one big slab.
#   
#   Signed-off-by: Neil Brown <neilb@cse.unsw.edu.au>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# include/linux/nfsd/cache.h
#   2005/03/04 22:32:50-08:00 neilb@cse.unsw.edu.au +3 -4
#   nfsd: change nfsd reply cache to use list.h lists
# 
# fs/nfsd/nfscache.c
#   2005/03/04 22:32:50-08:00 neilb@cse.unsw.edu.au +43 -88
#   nfsd: change nfsd reply cache to use list.h lists
# 
# ChangeSet
#   2005/03/05 09:14:42-08:00 neilb@cse.unsw.edu.au 
#   [PATCH] nfsd: global/static cleanups for nfsd
#   
#   The patch below contains the following cleanups:
#   - make some needlessly global code static
#   
#   Signed-off-by: Adrian Bunk <bunk@stusta.de>
#   Signed-off-by: Neil Brown <neilb@cse.unsw.edu.au>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# fs/nfsd/vfs.c
#   2005/03/04 22:32:50-08:00 neilb@cse.unsw.edu.au +4 -4
#   nfsd: global/static cleanups for nfsd
# 
# fs/nfsd/nfssvc.c
#   2005/03/04 22:32:50-08:00 neilb@cse.unsw.edu.au +1 -1
#   nfsd: global/static cleanups for nfsd
# 
# fs/nfsd/nfsfh.c
#   2005/03/04 22:32:50-08:00 neilb@cse.unsw.edu.au +6 -5
#   nfsd: global/static cleanups for nfsd
# 
# fs/nfsd/lockd.c
#   2005/03/04 22:32:50-08:00 neilb@cse.unsw.edu.au +1 -1
#   nfsd: global/static cleanups for nfsd
# 
# fs/nfsd/export.c
#   2005/03/04 22:32:50-08:00 neilb@cse.unsw.edu.au +11 -11
#   nfsd: global/static cleanups for nfsd
# 
# ChangeSet
#   2005/03/05 09:14:29-08:00 neilb@cse.unsw.edu.au 
#   [PATCH] nfsd: nfsd: remove pg_authenticate field
#   
#   The pg_authenticate (now pg_authenticate_obsolete) callback was only being
#   used by the nfs4 client callback code to circumvent the svcauth_unix code's
#   insistence on checking all requests against the export table.  With that
#   problem solved, we no longer need it.
#   
#   Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
#   Signed-off-by: Neil Brown <neilb@cse.unsw.edu.au>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# net/sunrpc/svc.c
#   2005/03/04 22:32:49-08:00 neilb@cse.unsw.edu.au +1 -4
#   nfsd: nfsd: remove pg_authenticate field
# 
# include/linux/sunrpc/svc.h
#   2005/03/04 22:32:49-08:00 neilb@cse.unsw.edu.au +0 -2
#   nfsd: nfsd: remove pg_authenticate field
# 
# ChangeSet
#   2005/03/05 09:14:15-08:00 neilb@cse.unsw.edu.au 
#   [PATCH] nfsd: lockd: don't try to match callback requests against export table
#   
#   On lockd callbacks, we're a client, and the source address is that of a
#   server, so we shouldn't be trying to match the source address of the callback
#   request against our export table.
#   
#   Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
#   Signed-off-by: Neil Brown <neilb@cse.unsw.edu.au>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# fs/lockd/svc.c
#   2005/03/04 22:32:49-08:00 neilb@cse.unsw.edu.au +18 -0
#   nfsd: lockd: don't try to match callback requests against export table
# 
# ChangeSet
#   2005/03/05 09:14:01-08:00 neilb@cse.unsw.edu.au 
#   [PATCH] nfsd: nfs4: use new pg_set_client method to simplify nfs4 callback authentication
#   
#   Use new pg_authenticate method to simplify nfs4 callback authentication.
#   
#   This also has the effect of changing the error return from rejectedcred to
#   badcred.  I believe the change is correct.
#   
#   Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
#   Signed-off-by: Neil Brown <neilb@cse.unsw.edu.au>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# fs/nfs/callback.c
#   2005/03/04 22:32:49-08:00 neilb@cse.unsw.edu.au +9 -147
#   nfsd: nfs4: use new pg_set_client method to simplify nfs4 callback authentication
# 
# ChangeSet
#   2005/03/05 09:13:48-08:00 neilb@cse.unsw.edu.au 
#   [PATCH] nfsd: svcrpc: move export table checks to a per-program pg_add_client method
#   
#   svcauth_null_accept() and svcauth_unix_accept() are currently hard-wired to
#   check the source ip address on an incoming request against the export table,
#   which make sense for nfsd but not necessarily for other rpc-based services.
#   
#   So instead we have the accept() method call a program-specific
#   pg_authenticate() method.  We also move the call to this method into
#   svc_process instead of calling it from the flavor-specific accept() routines.
#   
#   Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
#   Signed-off-by: Neil Brown <neilb@cse.unsw.edu.au>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# net/sunrpc/svcauth_unix.c
#   2005/03/04 22:32:49-08:00 neilb@cse.unsw.edu.au +2 -16
#   nfsd: svcrpc: move export table checks to a per-program pg_add_client method
# 
# net/sunrpc/svc.c
#   2005/03/04 23:17:36-08:00 neilb@cse.unsw.edu.au +11 -1
#   nfsd: svcrpc: move export table checks to a per-program pg_add_client method
# 
# net/sunrpc/auth_gss/svcauth_gss.c
#   2005/03/04 22:32:49-08:00 neilb@cse.unsw.edu.au +2 -7
#   nfsd: svcrpc: move export table checks to a per-program pg_add_client method
# 
# include/linux/sunrpc/svc.h
#   2005/03/04 23:17:36-08:00 neilb@cse.unsw.edu.au +1 -0
#   nfsd: svcrpc: move export table checks to a per-program pg_add_client method
# 
# fs/nfsd/nfssvc.c
#   2005/03/04 23:17:36-08:00 neilb@cse.unsw.edu.au +2 -0
#   nfsd: svcrpc: move export table checks to a per-program pg_add_client method
# 
# fs/lockd/svc.c
#   2005/03/04 23:17:36-08:00 neilb@cse.unsw.edu.au +15 -0
#   nfsd: svcrpc: move export table checks to a per-program pg_add_client method
# 
# ChangeSet
#   2005/03/05 09:13:35-08:00 neilb@cse.unsw.edu.au 
#   [PATCH] nfsd: svcrpc: rename pg_authenticate
#   
#   Later patches remove pg_authenticate and use the name for a different purpose;
#   so rename it to pg_authenticate_obsolete for now.
#   
#   Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
#   Signed-off-by: Neil Brown <neilb@cse.unsw.edu.au>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# net/sunrpc/svc.c
#   2005/03/04 23:17:37-08:00 neilb@cse.unsw.edu.au +2 -2
#   nfsd: svcrpc: rename pg_authenticate
# 
# include/linux/sunrpc/svc.h
#   2005/03/04 23:17:37-08:00 neilb@cse.unsw.edu.au +1 -1
#   nfsd: svcrpc: rename pg_authenticate
# 
# fs/nfs/callback.c
#   2005/03/04 23:17:37-08:00 neilb@cse.unsw.edu.au +1 -1
#   nfsd: svcrpc: rename pg_authenticate
# 
# ChangeSet
#   2005/03/05 09:13:22-08:00 neilb@cse.unsw.edu.au 
#   [PATCH] nfsd: svcrpc: add a per-flavor set_client method
#   
#   Add a set_client method to the server rpc auth_ops struct, used to set the
#   client (for the purposes of nfsd export authorization) using flavor-specific
#   information.
#   
#   Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
#   Signed-off-by: Neil Brown <neilb@cse.unsw.edu.au>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# net/sunrpc/svcauth_unix.c
#   2005/03/04 23:17:37-08:00 neilb@cse.unsw.edu.au +2 -0
#   nfsd: svcrpc: add a per-flavor set_client method
# 
# net/sunrpc/svcauth.c
#   2005/03/04 23:17:36-08:00 neilb@cse.unsw.edu.au +5 -0
#   nfsd: svcrpc: add a per-flavor set_client method
# 
# net/sunrpc/sunrpc_syms.c
#   2005/03/04 22:32:49-08:00 neilb@cse.unsw.edu.au +1 -0
#   nfsd: svcrpc: add a per-flavor set_client method
# 
# net/sunrpc/auth_gss/svcauth_gss.c
#   2005/03/04 23:17:37-08:00 neilb@cse.unsw.edu.au +14 -0
#   nfsd: svcrpc: add a per-flavor set_client method
# 
# include/linux/sunrpc/svcauth.h
#   2005/03/04 22:32:49-08:00 neilb@cse.unsw.edu.au +2 -0
#   nfsd: svcrpc: add a per-flavor set_client method
# 
# ChangeSet
#   2005/03/05 09:13:08-08:00 neilb@cse.unsw.edu.au 
#   [PATCH] nfsd: exportfs: reduce stack usage
#   
#   find_exported_dentry() declares
#   	char nbuf[NAME_MAX+1];
#   in 2 separate places, and gcc allocates space on the stack for both
#   of them.  Having just one of them will suffice, if we can put put
#   with its scope.
#   
#   Reduces function stack usage on x86-32 from 0x230 to 0x130.
#   
#   Signed-off-by: Randy Dunlap <rddunlap@osdl.org>
#   Signed-off-by: Neil Brown <neilb@cse.unsw.edu.au>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# fs/exportfs/expfs.c
#   2005/03/04 22:32:49-08:00 neilb@cse.unsw.edu.au +1 -3
#   nfsd: exportfs: reduce stack usage
# 
# ChangeSet
#   2005/03/05 09:12:54-08:00 neilb@cse.unsw.edu.au 
#   [PATCH] SGI 921857: find broken with nohide on NFSv3
#   
#   This patch makes "find" work when traversing nohide exports on NFSv3.  The
#   READDIRPLUS reply needs to not return a file handle for the ".." entry when
#   the directory is a server side mountpoint, which would be the directory
#   itself, otherwise the client remembers the wrong file handle and gets
#   confused.
#   
#   Signed-off-by: Greg Banks <gnb@melbourne.sgi.com>
#   Signed-off-by: Neil Brown <neilb@cse.unsw.edu.au>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Linus Torvalds <torvalds@osdl.org>
# 
# fs/nfsd/nfs3xdr.c
#   2005/03/04 22:32:48-08:00 neilb@cse.unsw.edu.au +5 -0
#   SGI 921857: find broken with nohide on NFSv3
# 
# ChangeSet
#   2005/03/05 15:55:50+00:00 rmk@flint.arm.linux.org.uk 
#   [ARM] Remove ARM specific set_pmd()
#   
#   set_pmd has specific behaviour on ARM which may be unexpected.  Since
#   it is rather too close to macros used by other architectures, open
#   code this functionality.
#   
#   Signed-off-by: Russell King <rmk@arm.linux.org.uk>
# 
# include/asm-arm/pgtable.h
#   2005/03/05 15:51:55+00:00 rmk@flint.arm.linux.org.uk +0 -6
#   set_pmd has specific behaviour on ARM which may be unexpected.  Since
#   it is rather too close to macros used by other architectures, open
#   code this functionality.
# 
# arch/arm/mm/mm-armv.c
#   2005/03/05 15:51:55+00:00 rmk@flint.arm.linux.org.uk +5 -3
#   set_pmd has specific behaviour on ARM which may be unexpected.  Since
#   it is rather too close to macros used by other architectures, open
#   code this functionality.
# 
# arch/arm/mach-sa1100/assabet.c
#   2005/03/05 15:51:54+00:00 rmk@flint.arm.linux.org.uk +5 -3
#   set_pmd has specific behaviour on ARM which may be unexpected.  Since
#   it is rather too close to macros used by other architectures, open
#   code this functionality.
# 
# ChangeSet
#   2005/03/05 14:29:38+00:00 rmk@flint.arm.linux.org.uk 
#   [ARM] Fix sparse warnings for ebsa110 IO implementation
#   
#   Signed-off-by: Russell King <rmk@arm.linux.org.uk>
# 
# arch/arm/mach-ebsa110/io.c
#   2005/03/05 14:25:03+00:00 rmk@flint.arm.linux.org.uk +32 -55
#   Fix sparse warnings for ebsa110 IO implementation
# 
# ChangeSet
#   2005/03/05 14:20:51+00:00 rmk@flint.arm.linux.org.uk 
#   [ARM] Add __iomem checking for __raw_{read,write}[bwl]
#   
#   Signed-off-by: Russell King <rmk@arm.linux.org.uk>
# 
# include/asm-arm/io.h
#   2005/03/05 14:16:24+00:00 rmk@flint.arm.linux.org.uk +6 -6
#   Add __iomem checking for __raw_{read,write}[bwl]
# 
# ChangeSet
#   2005/03/05 14:22:13+01:00 marcel@holtmann.org 
#   [Bluetooth] Update entry for the BPA 100/105 driver
#   
#   This patch adds the missing entry for the BPA 100/105 driver
#   into the MAINTAINERS file.
#   
#   Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
# 
# MAINTAINERS
#   2005/03/05 14:20:42+01:00 marcel@holtmann.org +5 -0
#   Update entry for the BPA 100/105 driver
# 
# ChangeSet
#   2005/03/05 14:10:28+01:00 marcel@holtmann.org 
#   [Bluetooth] Enhance HCI callback interface
#   
#   This patch adds callback functions for changing the link key and
#   switching the role to the Bluetooth core interface.
#   
#   Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
# 
# net/bluetooth/hci_conn.c
#   2005/03/05 14:08:48+01:00 marcel@holtmann.org +18 -0
#   Enhance HCI callback interface
# 
# net/bluetooth/hci_event.c
#   2005/03/05 14:08:45+01:00 marcel@holtmann.org +31 -7
#   Enhance HCI callback interface
# 
# include/net/bluetooth/hci_core.h
#   2005/03/05 14:05:56+01:00 marcel@holtmann.org +31 -1
#   Enhance HCI callback interface
# 
# ChangeSet
#   2005/03/05 13:45:00+01:00 marcel@holtmann.org 
#   [Bluetooth] Convert clock offset value from little endian
#   
#   The clock offset value is stored in little endian and so convert
#   it before showing it in the inquiry cache list.
#   
#   Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
# 
# net/bluetooth/hci_sysfs.c
#   2005/03/05 13:43:03+01:00 marcel@holtmann.org +1 -1
#   Convert clock offset value from little endian
# 
# ChangeSet
#   2005/03/05 13:31:32+01:00 marcel@holtmann.org 
#   [Bluetooth] Remove interruptible_sleep_on_timeout() usage
#   
#   Remove deprecated interruptible_sleep_on_timeout() function calls
#   and replace them with direct wait-queue usage.
#   
#   Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
#   Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
# 
# drivers/bluetooth/bluecard_cs.c
#   2005/03/05 13:30:19+01:00 marcel@holtmann.org +9 -5
#   Remove interruptible_sleep_on_timeout() usage
# 
# ChangeSet
#   2005/03/05 13:29:30+01:00 marcel@holtmann.org 
#   [Bluetooth] Don't use ISOC transfers for sniffer devices
#   
#   The sniffer devices present themself as a full H:2 device, but
#   actually they don't need any ISOC transfers and so don't start
#   them.
#   
#   Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
# 
# drivers/bluetooth/hci_usb.c
#   2005/03/05 13:27:09+01:00 marcel@holtmann.org +1 -1
#   Don't use ISOC transfers for sniffer devices
# 
# ChangeSet
#   2005/03/04 20:21:20-08:00 davem@northbeach.davemloft.net.davemloft.net 
#   [TIGON3]: Update driver version and reldate.
#   
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# drivers/net/tg3.c
#   2005/03/04 20:21:03-08:00 davem@northbeach.davemloft.net.davemloft.net +2 -2
#   [TIGON3]: Update driver version and reldate.
# 
# ChangeSet
#   2005/03/04 20:20:02-08:00 davem@northbeach.davemloft.net.davemloft.net 
#   [TIGON3]: Do not touch NIC_SRAM_FIRMWARE_MBOX when TG3_FLG2_SUN_570X.
#   
#   There is no firmware on these chips, so accessing this
#   value is pointless.  But, more importantly, touching
#   this area on such chips results in PCI PIO timeouts.
#   
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# drivers/net/tg3.c
#   2005/03/04 20:19:37-08:00 davem@northbeach.davemloft.net.davemloft.net +17 -15
#   [TIGON3]: Do not touch NIC_SRAM_FIRMWARE_MBOX when TG3_FLG2_SUN_570X.
# 
# ChangeSet
#   2005/03/04 16:47:05-08:00 davem@northbeach.davemloft.net.davemloft.net 
#   [SPARC64]: Tomatillo PCI controller bug fixes.
#   
#   - Error handlers were mis-calculating ICLR register to
#     ACK on Tomatillo.
#   - PCI error handlers should not ACK other IRQ.
#   - Fix Tomatillo version comparison for PCI Timeout
#     Interval setting
#   - Tomatillo PCI control register prefetch enable bits
#     were off.
#   - Tomatillo revs <= 1 need bit 61 set, all others should
#     have it clear.  This is in the PCI control register.
#   
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# arch/sparc64/kernel/pci_schizo.c
#   2005/03/04 16:46:31-08:00 davem@northbeach.davemloft.net.davemloft.net +69 -43
#   [SPARC64]: Tomatillo PCI controller bug fixes.
# 
# ChangeSet
#   2005/03/04 16:12:52-08:00 torvalds@ppc970.osdl.org 
#   Merge bk://kernel.bkbits.net/gregkh/linux/pci-2.6
#   into ppc970.osdl.org:/home/torvalds/v2.6/linux
# 
# include/linux/pci_ids.h
#   2005/03/04 16:12:48-08:00 torvalds@ppc970.osdl.org +0 -0
#   Auto merged
# 
# ChangeSet
#   2005/03/04 23:55:22+00:00 rmk@flint.arm.linux.org.uk 
#   [ARM] Fix two missed ether1_outw() function calls.
#   
#   Signed-off-by: Russell King <rmk@arm.linux.org.uk>
# 
# drivers/net/arm/ether1.c
#   2005/03/04 23:51:18+00:00 rmk@flint.arm.linux.org.uk +2 -2
#   Fix two missed ether1_outw() function calls.
# 
# ChangeSet
#   2005/03/04 23:13:29+00:00 nico@org.rmk.(none) 
#   [ARM PATCH] 2514/1: save iWMMXt context to ram before entering sleep mode
#   
#   Patch from Nicolas Pitre
#   
#   Signed-off-by: Nicolas Pitre
#   Signed-off-by: Russell King
# 
# arch/arm/mach-pxa/pm.c
#   2005/03/04 00:00:00+00:00 nico@org.rmk.(none) +5 -0
#   [PATCH] 2514/1: save iWMMXt context to ram before entering sleep mode
# 
# ChangeSet
#   2005/03/04 22:07:11+00:00 rmk@flint.arm.linux.org.uk 
#   [MMC] Use bus dev_attrs instead of handling device attrs manually
#   
#   Convert MMC to use bus dev_attrs instead of handling the registration
#   of these attributes itself.
#   
#   Signed-off-by: Russell King <rmk@arm.linux.org.uk>
# 
# drivers/mmc/mmc_sysfs.c
#   2005/03/04 22:01:12+00:00 rmk@flint.arm.linux.org.uk +37 -40
#   Convert MMC to use bus dev_attrs instead of handling the registration
#   of these attributes itself.
# 
# ChangeSet
#   2005/03/04 21:19:20+00:00 gtj.member@com.rmk.(none) 
#   [ARM PATCH] 2472/1: Updates 8250.c to correctly detect XScale UARTs
#   
#   Patch from George Joseph
#   
#   Modifications to autoconfig_16550a to add a testcase
#   to detect XScale UARTS.
#   
#   Signed-off-by: George Joseph
#   Signed-off-by: Russell King
# 
# drivers/serial/8250.c
#   2005/01/24 16:00:57+00:00 gtj.member@com.rmk.(none) +35 -0
#   [PATCH] 2472/1: Updates 8250.c to correctly detect XScale UARTs
# 
# ChangeSet
#   2005/03/04 18:43:44+00:00 nico@org.rmk.(none) 
#   [ARM PATCH] 2513/1: more PXA27x regs to save for sleep mode
#   
#   Patch from Nicolas Pitre
#   
#   ... plus Mainstone bits.
#   
#   Signed-off-by: Nicolas Pitre
#   Signed-off-by: Russell King
# 
# arch/arm/mach-pxa/pm.c
#   2005/03/04 00:00:00+00:00 nico@org.rmk.(none) +34 -7
#   [PATCH] 2513/1: more PXA27x regs to save for sleep mode
# 
# arch/arm/mach-pxa/mainstone.c
#   2005/03/04 00:00:00+00:00 nico@org.rmk.(none) +9 -0
#   [PATCH] 2513/1: more PXA27x regs to save for sleep mode
# 
# ChangeSet
#   2005/03/04 18:19:21+00:00 davis_g@com.rmk.(none) 
#   [ARM PATCH] 2459/1: ARMv6 supersections for static kernel direct mapped memory regions [updated]
#   
#   Patch from George G. Davis
#   
#   Use ARMv6 supersections for 16MiB static kernel direct mapped memory
#   regions when possible.
#   Based on comments received for the first version of this patch, this
#   version has added a comment to clarify that ARMv6 supersections are
#   only valid for the domain == 0 case and moved the supersection address
#   mask and size macros before the hardware page table definitions.
#   
#   Signed-off-by: George G. Davis
#   Signed-off-by: Russell King
# 
# include/asm-arm/pgtable.h
#   2005/03/04 00:00:00+00:00 davis_g@com.rmk.(none) +8 -0
#   [PATCH] 2459/1: ARMv6 supersections for static kernel direct mapped memory regions [updated]
# 
# arch/arm/mm/mm-armv.c
#   2005/03/04 00:00:00+00:00 davis_g@com.rmk.(none) +43 -1
#   [PATCH] 2459/1: ARMv6 supersections for static kernel direct mapped memory regions [updated]
# 
# ChangeSet
#   2005/03/04 17:01:00+00:00 andrew@com.rmk.(none) 
#   [ARM PATCH] 1941/2: End-of-interrupt (irq_finish) macro on ARM
#   
#   Patch from SAN People
#   
#   On some ARM-based processor's (eg, Atmel's AT91RM9200) it is necessary
#   to signal the end-of-interrupt to the interrupt controller. This is
#   necessary so it can restore its internal priority levels, etc.
#   This patch is equivalent to the version in the current 2.4 kernels.
#   Patch now updated to 2.6.11
#   
#   Signed-off-by: Andrew Victor
#   Signed-off-by: Russell King
# 
# arch/arm/kernel/irq.c
#   2005/03/04 10:08:06+00:00 andrew@com.rmk.(none) +9 -0
#   [PATCH] 1941/2: End-of-interrupt (irq_finish) macro on ARM
# 
# ChangeSet
#   2005/03/04 16:47:29+00:00 rpurdie@net.rmk.(none) 
#   [ARM PATCH] 2510/1: PXA: Disable pxa_gpio_irq_type printks
#   
#   Patch from Richard Purdie
#   
#   The printks inside pxa_gpio_irq_type damage performance and are of little value in a production kernel. They should be disabled.
#   
#   Signed-off-by: Richard PurdieSigned-off-by: Nicolas Pitre
#   Signed-off-by: Russell King
# 
# arch/arm/mach-pxa/irq.c
#   2005/03/02 21:35:46+00:00 rpurdie@net.rmk.(none) +4 -4
#   [PATCH] 2510/1: PXA: Disable pxa_gpio_irq_type printks
# 
# ChangeSet
#   2005/03/04 16:24:42+00:00 tglx@de.rmk.(none) 
#   [ARM PATCH] 2477/1: Move double defined macro to header file
#   
#   Patch from Thomas Gleixner
#   
#   IRQ_DISPATCH is defined in two c files. Move it to the common header file.
#   
#   Signed-off-by: Thomas Gleixner
#   Signed-off-by: Russell King
# 
# arch/arm/mach-lh7a40x/irq-lpd7a40x.c
#   2005/03/04 00:00:00+00:00 tglx@de.rmk.(none) +0 -2
#   [PATCH] 2477/1: Move double defined macro to header file
# 
# arch/arm/mach-lh7a40x/common.h
#   2005/03/04 00:00:00+00:00 tglx@de.rmk.(none) +2 -0
#   [PATCH] 2477/1: Move double defined macro to header file
# 
# arch/arm/mach-lh7a40x/arch-lpd7a40x.c
#   2005/03/04 00:00:00+00:00 tglx@de.rmk.(none) +0 -2
#   [PATCH] 2477/1: Move double defined macro to header file
# 
# ChangeSet
#   2005/03/03 23:15:05+00:00 nico@org.rmk.(none) 
#   [ARM PATCH] 2509/1: fix watchdog timer frequency for PXA27x
#   
#   Patch from Nicolas Pitre
#   
#   Signed-off-by: Nicolas Pitre
#   Signed-off-by: Russell King
# 
# drivers/char/watchdog/sa1100_wdt.c
#   2005/02/25 18:53:29+00:00 nico@org.rmk.(none) +1 -1
#   [PATCH] 2509/1: fix watchdog timer frequency for PXA27x
# 
# ChangeSet
#   2005/03/03 22:57:33+00:00 ben-linux@org.rmk.(none) 
#   [ARM PATCH] 2512/1: S3C2410 - remove bast-cpld.h from include/asm-arm/arch-s3c2410/hardware.h
#   
#   Patch from Ben Dooks
#   
#   Remove the include of bast-cpld.h, as it shouldn't be here as
#   it only defines some extra bast-specific registers, and does
#   not affect the configuration of the hardware dependenat items.
#   Ensure that the file is included in the one place it is needed
#   and not included.
#   This should discourage anyone else putting include files in
#   which do not affect the over-all hardware definitions.
#   
#   Signed-off-by: Ben Dooks
#   Signed-off-by: Russell King
# 
# include/asm-arm/arch-s3c2410/hardware.h
#   2005/03/03 14:10:27+00:00 ben-linux@org.rmk.(none) +1 -5
#   [PATCH] 2512/1: S3C2410 - remove bast-cpld.h from include/asm-arm/arch-s3c2410/hardware.h
# 
# arch/arm/mach-s3c2410/mach-bast.c
#   2005/03/03 14:11:23+00:00 ben-linux@org.rmk.(none) +2 -0
#   [PATCH] 2512/1: S3C2410 - remove bast-cpld.h from include/asm-arm/arch-s3c2410/hardware.h
# 
# ChangeSet
#   2005/03/03 22:35:54+00:00 ben-linux@org.rmk.(none) 
#   [ARM PATCH] 2511/1: SMDK2440 - base machine support
#   
#   Patch from Ben Dooks
#   
#   SMDK2440 core board support
#   
#   Signed-off-by: Ben Dooks
#   
#   Signed-off-by: Dimitry Andric
#   Signed-off-by: Russell King
# 
# ChangeSet
#   2005/03/03 23:20:42+01:00 kaber@coreworks.de 
#   [NETFILTER]: Don't insist on ICMP errors carrying 8 byte of protocol header
#   
#   An ICMP error only needs to carry 8 bytes of protocol header if they were
#   present in the original packet. Makes netfilter's handling of ICMP errors
#   consistent with IP.
#   
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
# 
# net/ipv4/netfilter/ipt_REJECT.c
#   2005/03/03 23:20:32+01:00 kaber@coreworks.de +0 -4
#   [NETFILTER]: Don't insist on ICMP errors carrying 8 byte of protocol header
#   
#   An ICMP error only needs to carry 8 bytes of protocol header if they were
#   present in the original packet. Makes netfilter's handling of ICMP errors
#   consistent with IP.
#   
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
# 
# net/ipv4/netfilter/ipt_LOG.c
#   2005/03/03 23:20:32+01:00 kaber@coreworks.de +5 -5
#   [NETFILTER]: Don't insist on ICMP errors carrying 8 byte of protocol header
#   
#   An ICMP error only needs to carry 8 bytes of protocol header if they were
#   present in the original packet. Makes netfilter's handling of ICMP errors
#   consistent with IP.
#   
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
# 
# ChangeSet
#   2005/03/03 23:19:00+01:00 kadlec@blackhole.kfki.hu 
#   [NETFILTER]: Fix multiple problems with TCP window tracking
#   
#   The first attached patch addresses several problems in the current TCP
#   connection tracking in the 2.6 tree. Some of the problems was reported,
#   others was discovered by nfsim tests:
#   
#   - tcp_sack function was not safe against nonlinear skbs
#   - practically arbitrary RST segments (addresses, ports assumed to be
#     known) could cause connection teardown in conntrack (thanks to Tim
#     Burress for the bugreport and patch)
#   - article on which the code was based falsely assumed that packets
#     must fit completely into the window: packets must at least overlap
#     (thanks to Phil Oester for the bugreport and patch)
#   - state table slightly changed to handle ACK packets sent by server to
#     late resent SYNs
#   - tracking reopening connections reworked
#   - cosmetic change: when window tracking is ignored by setting
#     ip_conntrack_tcp_be_liberal to nonzero, it's ignored completely from
#     now on
#   
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
# 
# net/ipv4/netfilter/ip_conntrack_proto_tcp.c
#   2005/03/03 23:18:52+01:00 kadlec@blackhole.kfki.hu +89 -66
#   [NETFILTER]: Fix multiple problems with TCP window tracking
#   
#   The first attached patch addresses several problems in the current TCP
#   connection tracking in the 2.6 tree. Some of the problems was reported,
#   others was discovered by nfsim tests:
#   
#   - tcp_sack function was not safe against nonlinear skbs
#   - practically arbitrary RST segments (addresses, ports assumed to be
#     known) could cause connection teardown in conntrack (thanks to Tim
#     Burress for the bugreport and patch)
#   - article on which the code was based falsely assumed that packets
#     must fit completely into the window: packets must at least overlap
#     (thanks to Phil Oester for the bugreport and patch)
#   - state table slightly changed to handle ACK packets sent by server to
#     late resent SYNs
#   - tracking reopening connections reworked
#   - cosmetic change: when window tracking is ignored by setting
#     ip_conntrack_tcp_be_liberal to nonzero, it's ignored completely from
#     now on
#   
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
# 
# include/linux/netfilter_ipv4/ip_conntrack_tcp.h
#   2005/03/03 23:18:52+01:00 kadlec@blackhole.kfki.hu +4 -1
#   [NETFILTER]: Fix multiple problems with TCP window tracking
#   
#   The first attached patch addresses several problems in the current TCP
#   connection tracking in the 2.6 tree. Some of the problems was reported,
#   others was discovered by nfsim tests:
#   
#   - tcp_sack function was not safe against nonlinear skbs
#   - practically arbitrary RST segments (addresses, ports assumed to be
#     known) could cause connection teardown in conntrack (thanks to Tim
#     Burress for the bugreport and patch)
#   - article on which the code was based falsely assumed that packets
#     must fit completely into the window: packets must at least overlap
#     (thanks to Phil Oester for the bugreport and patch)
#   - state table slightly changed to handle ACK packets sent by server to
#     late resent SYNs
#   - tracking reopening connections reworked
#   - cosmetic change: when window tracking is ignored by setting
#     ip_conntrack_tcp_be_liberal to nonzero, it's ignored completely from
#     now on
#   
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
# 
# ChangeSet
#   2005/03/03 23:18:41+01:00 ariel@blueslice.com 
#   [NETFILTER]: SCTP conntrack: fix association restart
#   
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
# 
# net/ipv4/netfilter/ip_conntrack_proto_sctp.c
#   2005/03/03 23:18:33+01:00 ariel@blueslice.com +2 -2
#   [NETFILTER]: SCTP conntrack: fix association restart
#   
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
# 
# ChangeSet
#   2005/03/03 23:17:17+01:00 kaber@coreworks.de 
#   [NETFILTER]: Fix /proc/net/ip_conntrack seq_file operations
#   
#   ip_conntrack dumps an entire hash chain at a time. If dumping
#   the first hash chain exceeds the available room nothing has
#   been copied and seq_read() stops and returns the error. Change
#   it to dump just a single entry at a time.
#   
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
# 
# net/ipv4/netfilter/ip_conntrack_standalone.c
#   2005/03/03 23:17:07+01:00 kaber@coreworks.de +77 -39
#   [NETFILTER]: Fix /proc/net/ip_conntrack seq_file operations
#   
#   ip_conntrack dumps an entire hash chain at a time. If dumping
#   the first hash chain exceeds the available room nothing has
#   been copied and seq_read() stops and returns the error. Change
#   it to dump just a single entry at a time.
#   
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
# 
# ChangeSet
#   2005/03/03 23:16:38+01:00 kaber@coreworks.de 
#   [NETFILTER]: Use num_possible_cpus instead of NR_CPUS in {ip6_,arp_,eb}tables
#   
#   Similar to Andi Kleen's patch "Reduce netfilter memory use on MP systems".
#   
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
# 
# arch/arm/mach-s3c2410/Makefile
#   2005/03/03 10:30:16+00:00 ben-linux@org.rmk.(none) +1 -0
#   [PATCH] 2511/1: SMDK2440 - base machine support
# 
# arch/arm/mach-s3c2410/Kconfig
#   2005/03/03 10:30:16+00:00 ben-linux@org.rmk.(none) +6 -0
#   [PATCH] 2511/1: SMDK2440 - base machine support
# 
# arch/arm/configs/s3c2410_defconfig
#   2005/03/03 10:43:43+00:00 ben-linux@org.rmk.(none) +1 -0
#   [PATCH] 2511/1: SMDK2440 - base machine support
# 
# Documentation/arm/Samsung-S3C24XX/Overview.txt
#   2005/03/03 10:31:25+00:00 ben-linux@org.rmk.(none) +5 -0
#   [PATCH] 2511/1: SMDK2440 - base machine support
# 
# arch/arm/mach-s3c2410/mach-smdk2440.c
#   2005/03/03 10:30:16+00:00 ben-linux@org.rmk.(none) +133 -0
#   [PATCH] 2511/1: SMDK2440 - base machine support
# 
# arch/arm/mach-s3c2410/mach-smdk2440.c
#   2005/03/03 10:30:16+00:00 ben-linux@org.rmk.(none) +0 -0
#   BitKeeper file /usr/src/bk/linux-2.6-rmk/arch/arm/mach-s3c2410/mach-smdk2440.c
# 
# net/ipv6/netfilter/ip6_tables.c
#   2005/03/03 23:16:30+01:00 kaber@coreworks.de +5 -5
#   [NETFILTER]: Use num_possible_cpus instead of NR_CPUS in {ip6_,arp_,eb}tables
#   
#   Similar to Andi Kleen's patch "Reduce netfilter memory use on MP systems".
#   
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
# 
# net/ipv4/netfilter/arp_tables.c
#   2005/03/03 23:16:30+01:00 kaber@coreworks.de +4 -4
#   [NETFILTER]: Use num_possible_cpus instead of NR_CPUS in {ip6_,arp_,eb}tables
#   
#   Similar to Andi Kleen's patch "Reduce netfilter memory use on MP systems".
#   
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
# 
# net/bridge/netfilter/ebtables.c
#   2005/03/03 23:16:30+01:00 kaber@coreworks.de +9 -9
#   [NETFILTER]: Use num_possible_cpus instead of NR_CPUS in {ip6_,arp_,eb}tables
#   
#   Similar to Andi Kleen's patch "Reduce netfilter memory use on MP systems".
#   
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
# 
# ChangeSet
#   2005/03/03 23:15:48+01:00 ak@suse.de 
#   [NETFILTER]: Reduce netfilter memory use on MP systems
#   
#   On kernels compiled with a big NR_CPUS netfilter rules would 
#   eat a lot of memory because all counters would be duplicated
#   for all NR_CPUs CPUs.  With NR_CPUS=256 this would add up
#   to many MBs of memory.
#   
#   This patch only allocates enough memory for the possible CPUs,
#   which is usually a much smaller number than NR_CPUS.
#   
#   This allows loading of bigger rule sets on 64bit systems.
#   There is still a limit because someone else broke vmalloc to have a 64MB 
#   limit on 64bit systems for single allocations, 129MB on 32bit.
#   It allocates an array of pages with kmalloc and kmalloc has a 128K limit. 
#   To be fixed with a separate patch.
#   
#   64bit systems were hurt worst because they tend to have big NR_CPUS
#   and the counters need more memory there, and the vmalloc limit is lower.
#   But it will raise the limits even on 32bit. 
#   
#   And in general it saves a lot of memory.
#   
#   Tested only on a small dual CPU box. 
#   
#   Signed-off-by: Andi Kleen <ak@suse.de>
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
# 
# net/ipv4/netfilter/ip_tables.c
#   2005/03/03 23:15:40+01:00 ak@suse.de +5 -5
#   [NETFILTER]: Reduce netfilter memory use on MP systems
#   
#   On kernels compiled with a big NR_CPUS netfilter rules would 
#   eat a lot of memory because all counters would be duplicated
#   for all NR_CPUs CPUs.  With NR_CPUS=256 this would add up
#   to many MBs of memory.
#   
#   This patch only allocates enough memory for the possible CPUs,
#   which is usually a much smaller number than NR_CPUS.
#   
#   This allows loading of bigger rule sets on 64bit systems.
#   There is still a limit because someone else broke vmalloc to have a 64MB 
#   limit on 64bit systems for single allocations, 129MB on 32bit.
#   It allocates an array of pages with kmalloc and kmalloc has a 128K limit. 
#   To be fixed with a separate patch.
#   
#   64bit systems were hurt worst because they tend to have big NR_CPUS
#   and the counters need more memory there, and the vmalloc limit is lower.
#   But it will raise the limits even on 32bit. 
#   
#   And in general it saves a lot of memory.
#   
#   Tested only on a small dual CPU box. 
#   
#   Signed-off-by: Andi Kleen <ak@suse.de>
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
# 
# ChangeSet
#   2005/03/03 23:15:03+01:00 kaber@coreworks.de 
#   [NETFILTER]: Use correct types in seq_printf calls
#   
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
# 
# net/ipv4/netfilter/ipt_hashlimit.c
#   2005/03/03 23:14:53+01:00 kaber@coreworks.de +1 -1
#   [NETFILTER]: Use correct types in seq_printf calls
#   
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
# 
# net/ipv4/netfilter/ip_conntrack_standalone.c
#   2005/03/03 23:14:53+01:00 kaber@coreworks.de +6 -5
#   [NETFILTER]: Use correct types in seq_printf calls
#   
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
# 
# Documentation/arm/Samsung-S3C24XX/SMDK2440.txt
#   2005/03/03 10:30:16+00:00 ben-linux@org.rmk.(none) +56 -0
#   [PATCH] 2511/1: SMDK2440 - base machine support
# 
# Documentation/arm/Samsung-S3C24XX/SMDK2440.txt
#   2005/03/03 10:30:16+00:00 ben-linux@org.rmk.(none) +0 -0
#   BitKeeper file /usr/src/bk/linux-2.6-rmk/Documentation/arm/Samsung-S3C24XX/SMDK2440.txt
# 
# ChangeSet
#   2005/03/03 23:12:29+01:00 mstjohns@mindspring.com 
#   [NETFILTER]: fix ip6_queue inefficiencies
#   
#   Check if packet exceeds max queue length before netlink_unicast(),
#   add drop statistics.
#   
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
# 
# net/ipv6/netfilter/ip6_queue.c
#   2005/03/03 23:12:20+01:00 mstjohns@mindspring.com +26 -14
#   [NETFILTER]: fix ip6_queue inefficiencies
#   
#   Check if packet exceeds max queue length before netlink_unicast(),
#   add drop statistics.
#   
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
# 
# net/ipv4/netfilter/ip_queue.c
#   2005/03/03 23:12:20+01:00 mstjohns@mindspring.com +27 -15
#   [NETFILTER]: fix ip6_queue inefficiencies
#   
#   Check if packet exceeds max queue length before netlink_unicast(),
#   add drop statistics.
#   
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
# 
# ChangeSet
#   2005/03/03 22:09:57+00:00 ben-linux@org.rmk.(none) 
#   [ARM PATCH] 2508/1: S3C2440 - timer and irq device updates
#   
#   Patch from Ben Dooks
#   
#   The patch does a number of updates, which are inter-dependant
#   on each other, for the s3c2440 support and some clean-ups for
#   all s3c24xx architecture in general.
#   1) Remove the s3c24xx_{fclk,hclk,pclk} variables, and pass
#      these values to the clock core on initialisation. This
#      removes the needless double copy, as only the timer code
#      uses these directly (see point 4).
#      Add an over-all xtal clock to the clock core
#   2) Add a sysdev driver to the clock code to ensure all the
#      s3c2440 clocks are added if an s3c2440 is present.
#   3) Add the new IRQs to irq.c, and initialise them if the
#      sysdev for the s3c2440 is present.
#   4) Change the timer code to request the timer clk and
#      use it to get the frequency.
#   Depends on patch 2467/1
#   Thanks to Guillaume Gourat for the original patches that
#   prompted this re-write.
#   
#   Signed-off-by: Ben Dooks
#   Signed-off-by: Russell King
# 
# include/asm-arm/arch-s3c2410/irqs.h
#   2005/03/01 00:54:26+00:00 ben-linux@org.rmk.(none) +13 -4
#   [PATCH] 2508/1: S3C2440 - timer and irq device updates
# 
# arch/arm/mach-s3c2410/time.c
#   2005/03/01 00:29:07+00:00 ben-linux@org.rmk.(none) +20 -3
#   [PATCH] 2508/1: S3C2440 - timer and irq device updates
# 
# arch/arm/mach-s3c2410/s3c2440.c
#   2005/03/01 00:41:52+00:00 ben-linux@org.rmk.(none) +30 -42
#   [PATCH] 2508/1: S3C2440 - timer and irq device updates
# 
# arch/arm/mach-s3c2410/s3c2410.c
#   2005/03/01 00:29:07+00:00 ben-linux@org.rmk.(none) +9 -8
#   [PATCH] 2508/1: S3C2440 - timer and irq device updates
# 
# arch/arm/mach-s3c2410/irq.c
#   2005/03/01 01:02:28+00:00 ben-linux@org.rmk.(none) +173 -0
#   [PATCH] 2508/1: S3C2440 - timer and irq device updates
# 
# arch/arm/mach-s3c2410/cpu.h
#   2005/03/01 00:29:07+00:00 ben-linux@org.rmk.(none) +5 -0
#   [PATCH] 2508/1: S3C2440 - timer and irq device updates
# 
# arch/arm/mach-s3c2410/cpu.c
#   2005/03/01 00:29:07+00:00 ben-linux@org.rmk.(none) +5 -4
#   [PATCH] 2508/1: S3C2440 - timer and irq device updates
# 
# arch/arm/mach-s3c2410/clock.h
#   2005/03/01 00:29:07+00:00 ben-linux@org.rmk.(none) +6 -9
#   [PATCH] 2508/1: S3C2440 - timer and irq device updates
# 
# arch/arm/mach-s3c2410/clock.c
#   2005/03/01 00:29:07+00:00 ben-linux@org.rmk.(none) +83 -13
#   [PATCH] 2508/1: S3C2440 - timer and irq device updates
# 
# ChangeSet
#   2005/03/03 21:58:16+00:00 buytenh@org.rmk.(none) 
#   [ARM PATCH] 2491/1: make ixp2000 use section mappings for on-chip registers
#   
#   Patch from Lennert Buytenhek
#   
#   This patch makes the ixp2000 port use section mappings for on-chip
#   registers.  This has two advantages:
#   1. It saves some TLB entries.
#   2. It enables us to work around ixp2400 erratum #66, for which the
#      suggested (and only) fix involves mapping all on-chip registers
#      using XCB=101 instead of XCB=000.
#   This patch was derived from an older patch for the same erratum
#   (ARM patch ID 2265/1), made by Deepak Saxena.
#   Note that this patch does not actually constitute a workaround for
#   erratum #66, it merely lays the foundation for such a workaround.
#   
#   Signed-off-by: Lennert BuytenhekSigned-off-by: Deepak Saxena
#   Signed-off-by: Russell King
# 
# include/asm-arm/arch-ixp2000/vmalloc.h
#   2005/02/16 23:49:43+00:00 buytenh@org.rmk.(none) +1 -1
#   [PATCH] 2491/1: make ixp2000 use section mappings for on-chip registers
# 
# include/asm-arm/arch-ixp2000/ixp2000-regs.h
#   2005/02/16 23:51:04+00:00 buytenh@org.rmk.(none) +33 -26
#   [PATCH] 2491/1: make ixp2000 use section mappings for on-chip registers
# 
# include/asm-arm/arch-ixp2000/ixdp2x01.h
#   2005/02/16 23:49:43+00:00 buytenh@org.rmk.(none) +2 -2
#   [PATCH] 2491/1: make ixp2000 use section mappings for on-chip registers
# 
# include/asm-arm/arch-ixp2000/ixdp2x00.h
#   2005/02/16 23:49:43+00:00 buytenh@org.rmk.(none) +1 -1
#   [PATCH] 2491/1: make ixp2000 use section mappings for on-chip registers
# 
# include/asm-arm/arch-ixp2000/entry-macro.S
#   2005/02/16 23:49:43+00:00 buytenh@org.rmk.(none) +3 -4
#   [PATCH] 2491/1: make ixp2000 use section mappings for on-chip registers
# 
# arch/arm/mach-ixp2000/core.c
#   2005/02/16 23:50:16+00:00 buytenh@org.rmk.(none) +6 -31
#   [PATCH] 2491/1: make ixp2000 use section mappings for on-chip registers
# 
# ChangeSet
#   2005/03/03 21:35:52+00:00 jelenz@edu.rmk.(none) 
#   [ARM PATCH] 2461/1: base support for poodle machine
#   
#   Patch from John Lenz
#   
#   Adds support for the Sharp Zaurus SL-5600
#   Add the ability to compile any collection of poodle and
#   corgi support under the PXA_SHARPSL option.
#   arch/arm/boot/compressed/head-sharpsl.S already has code
#   to detect the poodle machine.
#   
#   Signed-off-by: John Lenz
#   Signed-off-by: Russell King
# 
# include/asm-arm/arch-pxa/poodle.h
#   2005/03/03 00:00:00+00:00 jelenz@edu.rmk.(none) +111 -0
#   [PATCH] 2461/1: base support for poodle machine
# 
# include/asm-arm/arch-pxa/irqs.h
#   2005/03/03 00:00:00+00:00 jelenz@edu.rmk.(none) +32 -0
#   [PATCH] 2461/1: base support for poodle machine
# 
# arch/arm/mach-pxa/Makefile
#   2005/03/03 00:00:00+00:00 jelenz@edu.rmk.(none) +2 -1
#   [PATCH] 2461/1: base support for poodle machine
# 
# arch/arm/mach-pxa/Kconfig
#   2005/03/03 00:00:00+00:00 jelenz@edu.rmk.(none) +16 -3
#   [PATCH] 2461/1: base support for poodle machine
# 
# arch/arm/Kconfig
#   2005/03/03 00:00:00+00:00 jelenz@edu.rmk.(none) +1 -1
#   [PATCH] 2461/1: base support for poodle machine
# 
# include/asm-arm/arch-pxa/poodle.h
#   2005/03/03 00:00:00+00:00 jelenz@edu.rmk.(none) +0 -0
#   BitKeeper file /usr/src/bk/linux-2.6-rmk/include/asm-arm/arch-pxa/poodle.h
# 
# arch/arm/mach-pxa/poodle.c
#   2005/03/03 00:00:00+00:00 jelenz@edu.rmk.(none) +181 -0
#   [PATCH] 2461/1: base support for poodle machine
# 
# arch/arm/mach-pxa/poodle.c
#   2005/03/03 00:00:00+00:00 jelenz@edu.rmk.(none) +0 -0
#   BitKeeper file /usr/src/bk/linux-2.6-rmk/arch/arm/mach-pxa/poodle.c
# 
# ChangeSet
#   2005/03/03 08:29:59+00:00 ben-linux@org.rmk.(none) 
#   [ARM PATCH] 2506/1: S3C2410 - dma descriptor slab
#   
#   Patch from Ben Dooks
#   
#   Use slab allocator instead of kmalloc() to allocate the
#   dma buffer descriptors. This should allow the tracking
#   of dma descriptors, and to check if they are being freed
#   correctly.
#   
#   Signed-off-by: Ben Dooks
#   Signed-off-by: Russell King
# 
# arch/arm/mach-s3c2410/dma.c
#   2005/02/28 12:57:12+00:00 ben-linux@org.rmk.(none) +24 -3
#   [PATCH] 2506/1: S3C2410 - dma descriptor slab
# 
# ChangeSet
#   2005/03/03 08:13:07+00:00 ben-linux@org.rmk.(none) 
#   [ARM PATCH] 2503/1: S3C2410 - add brief documentation for HP IPAQ H1940
#   
#   Patch from Ben Dooks
#   
#   Brief documentation for Documents/arm/Samsung-S3C24XX for the
#   HP IPAQ H1940
#   
#   Signed-off-by: Ben Dooks
#   Signed-off-by: Russell King
# 
# Documentation/arm/Samsung-S3C24XX/H1940.txt
#   2005/02/25 12:45:38+00:00 ben-linux@org.rmk.(none) +40 -0
#   [PATCH] 2503/1: S3C2410 - add brief documentation for HP IPAQ H1940
# 
# Documentation/arm/Samsung-S3C24XX/H1940.txt
#   2005/02/25 12:45:38+00:00 ben-linux@org.rmk.(none) +0 -0
#   BitKeeper file /usr/src/bk/linux-2.6-rmk/Documentation/arm/Samsung-S3C24XX/H1940.txt
# 
# ChangeSet
#   2005/03/03 07:53:43+00:00 ben-linux@org.rmk.(none) 
#   [ARM PATCH] 2502/1: S3C2410 - watchdog during kernel uncompression
#   
#   Patch from Ben Dooks
#   
#   Enable the watchdog at the start of the kernel uncompression
#   stage, so that if any errors occur before the kernel reaches
#   the stage where it can start running processes then the system
#   will be reset.
#   
#   Signed-off-by: Ben Dooks
#   Signed-off-by: Russell King
# 
# include/asm-arm/arch-s3c2410/uncompress.h
#   2005/02/25 12:16:22+00:00 ben-linux@org.rmk.(none) +48 -15
#   [PATCH] 2502/1: S3C2410 - watchdog during kernel uncompression
# 
# arch/arm/mach-s3c2410/Kconfig
#   2005/02/25 12:30:13+00:00 ben-linux@org.rmk.(none) +20 -0
#   [PATCH] 2502/1: S3C2410 - watchdog during kernel uncompression
# 
# ChangeSet
#   2005/03/03 02:31:57-05:00 akpm@osdl.org 
#   [PATCH] VIA-Rhine: undork whitespace
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/via-rhine.c
#   2005/03/03 02:25:33-05:00 akpm@osdl.org +1 -2
#   VIA-Rhine: undork whitespace
# 
# ChangeSet
#   2005/03/02 23:18:01-08:00 gregkh@suse.de 
#   Merge suse.de:/home/greg/linux/BK/bleed-2.6
#   into suse.de:/home/greg/linux/BK/pci-2.6
# 
# include/linux/pci_ids.h
#   2005/03/02 23:17:58-08:00 gregkh@suse.de +0 -0
#   Auto merged
# 
# drivers/scsi/qla2xxx/qla_os.c
#   2005/03/02 23:17:58-08:00 gregkh@suse.de +0 -0
#   Auto merged
# 
# drivers/pci/pci.c
#   2005/03/02 23:17:57-08:00 gregkh@suse.de +0 -0
#   Auto merged
# 
# drivers/net/s2io.c
#   2005/03/02 23:17:57-08:00 gregkh@suse.de +0 -0
#   Auto merged
# 
# drivers/net/r8169.c
#   2005/03/02 23:17:57-08:00 gregkh@suse.de +0 -0
#   Auto merged
# 
# ChangeSet
#   2005/03/03 00:56:29-05:00 jchapman@katalix.com 
#   [PATCH] mii: add GigE support
#   
#   Add support for GigE PHYs in MII support library.
#   
#   This patch allows GigE drivers to use the MII library the same way
#   10/100 drivers do.
#   
#   Since the MII library is already used by lots of network drivers and the
#   GigE MII register bit definitions were reserved when many 10/100 PHYs
#   were designed, the new GigE registers are accessed only if a driver
#   specifically enables it. Existing 10/100 drivers should see no behavior
#   differences with this change.
#   
#   Signed-off-by: James Chapman <jchapman@katalix.com>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# include/linux/mii.h
#   2005/02/25 16:12:07-05:00 jchapman@katalix.com +18 -6
#   mii: add GigE support
# 
# drivers/net/mii.c
#   2005/02/25 16:12:07-05:00 jchapman@katalix.com +54 -9
#   mii: add GigE support
# 
# ChangeSet
#   2005/03/03 14:39:35+09:00 yoshfuji@linux-ipv6.org 
#   [NET] Don't use magic number for sysctl table definition.
#   
#   Signed-off-by: Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
# 
# net/ipv6/addrconf.c
#   2005/03/03 14:13:01+09:00 yoshfuji@linux-ipv6.org +1 -1
#   [NET] Don't use magic number for sysctl table definition.
#   
#   Signed-off-by: Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
# 
# net/ipv4/devinet.c
#   2005/03/03 14:13:01+09:00 yoshfuji@linux-ipv6.org +1 -1
#   [NET] Don't use magic number for sysctl table definition.
#   
#   Signed-off-by: Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
# 
# include/linux/sysctl.h
#   2005/03/03 14:13:01+09:00 yoshfuji@linux-ipv6.org +3 -1
#   [NET] Don't use magic number for sysctl table definition.
#   
#   Signed-off-by: Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
# 
# ChangeSet
#   2005/03/03 14:39:22+09:00 yoshfuji@linux-ipv6.org 
#   [IPV6] Mature enough, no longer EXPERIMENTAL.
#   
#   Now we can pass IPv6 Ready Logo <http://www.ipv6ready.org>
#   Phase 1 and Phase 2 Self Tests.
#   
#   Signed-off-by: Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
# 
# net/ipv6/netfilter/Kconfig
#   2005/03/03 14:12:56+09:00 yoshfuji@linux-ipv6.org +2 -2
#   [IPV6] Mature enough, no longer EXPERIMENTAL.
#   
#   Now we can pass IPv6 Ready Logo <http://www.ipv6ready.org>
#   Phase 1 and Phase 2 Self Tests.
#   
#   Signed-off-by: Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
# 
# net/Kconfig
#   2005/03/03 14:12:56+09:00 yoshfuji@linux-ipv6.org +9 -14
#   [IPV6] Mature enough, no longer EXPERIMENTAL.
#   
#   Now we can pass IPv6 Ready Logo <http://www.ipv6ready.org>
#   Phase 1 and Phase 2 Self Tests.
#   
#   Signed-off-by: Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
# 
# BitKeeper/deleted/.del-README~d53c7e98391bb0d8
#   2005/03/03 14:39:15+09:00 yoshfuji@linux-ipv6.org +0 -0
#   Delete: net/ipv6/README
# 
# ChangeSet
#   2005/03/03 14:39:10+09:00 yoshfuji@linux-ipv6.org 
#   [IPV6] ADDRCONF: Update prefix route on address deletion.
#   
#   We did not delete prefix route on deletion of corresponding
#   permanent address while we add prefix route on addition of
#   permanent address. This was confusing.
#   With this changeset, we purge prefix route or convert it to
#   dynamic one, if appropriate.
#   
#   Signed-off-by: Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
# 
# net/ipv6/addrconf.c
#   2005/03/03 14:12:50+09:00 yoshfuji@linux-ipv6.org +61 -1
#   [IPV6] ADDRCONF: Update prefix route on address deletion.
#   
#   We did not delete prefix route on deletion of corresponding
#   permanent address while we add prefix route on addition of
#   permanent address. This was confusing.
#   With this changeset, we purge prefix route or convert it to
#   dynamic one, if appropriate.
#   
#   Signed-off-by: Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
# 
# ChangeSet
#   2005/03/03 14:38:57+09:00 yoshfuji@linux-ipv6.org 
#   [IPV6] Unify common functions to compare ipv6 prefixes.
#   
#   Signed-off-by: Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
# 
# net/ipv6/ip6_fib.c
#   2005/03/03 14:12:44+09:00 yoshfuji@linux-ipv6.org +3 -33
#   [IPV6] Unify common functions to compare ipv6 prefixes.
#   
#   Signed-off-by: Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
# 
# net/ipv6/anycast.c
#   2005/03/03 14:12:44+09:00 yoshfuji@linux-ipv6.org +2 -28
#   [IPV6] Unify common functions to compare ipv6 prefixes.
#   
#   Signed-off-by: Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
# 
# include/net/ipv6.h
#   2005/03/03 14:12:44+09:00 yoshfuji@linux-ipv6.org +26 -0
#   [IPV6] Unify common functions to compare ipv6 prefixes.
#   
#   Signed-off-by: Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
# 
# ChangeSet
#   2005/03/03 14:38:44+09:00 yoshfuji@linux-ipv6.org 
#   [IPV6] Ensure to use interface hoplimit by default.
#   
#   Signed-off-by: Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
# 
# net/ipv6/udp.c
#   2005/03/03 14:12:38+09:00 yoshfuji@linux-ipv6.org +2 -0
#   [IPV6] Ensure to use interface hoplimit by default.
#   
#   Signed-off-by: Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
# 
# net/ipv6/route.c
#   2005/03/03 14:12:38+09:00 yoshfuji@linux-ipv6.org +4 -11
#   [IPV6] Ensure to use interface hoplimit by default.
#   
#   Signed-off-by: Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
# 
# net/ipv6/raw.c
#   2005/03/03 14:12:38+09:00 yoshfuji@linux-ipv6.org +2 -0
#   [IPV6] Ensure to use interface hoplimit by default.
#   
#   Signed-off-by: Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
# 
# net/ipv6/ndisc.c
#   2005/03/03 14:12:38+09:00 yoshfuji@linux-ipv6.org +4 -1
#   [IPV6] Ensure to use interface hoplimit by default.
#   
#   Signed-off-by: Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
# 
# net/ipv6/ip6_output.c
#   2005/03/03 14:12:38+09:00 yoshfuji@linux-ipv6.org +2 -0
#   [IPV6] Ensure to use interface hoplimit by default.
#   
#   Signed-off-by: Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
# 
# net/ipv6/icmp.c
#   2005/03/03 14:12:38+09:00 yoshfuji@linux-ipv6.org +4 -0
#   [IPV6] Ensure to use interface hoplimit by default.
#   
#   Signed-off-by: Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
# 
# include/net/addrconf.h
#   2005/03/03 14:12:38+09:00 yoshfuji@linux-ipv6.org +2 -0
#   [IPV6] Ensure to use interface hoplimit by default.
#   
#   Signed-off-by: Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
# 
# ChangeSet
#   2005/03/03 14:38:31+09:00 yoshfuji@linux-ipv6.org 
#   [IPV6] Always add a fragment header after receiving TOO BIG w/ pmtu < 1280.
#   
#   According to RFC2460, PMTU is set to the IPv6 Minimum Link
#   MTU (1280) and a fragment header should always be included
#   after a node receiving Too Big message reporting PMTU is
#   less than the IPv6 Minimum Link MTU (1280).
#   
#   Signed-off-by: Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
# 
# net/ipv6/route.c
#   2005/03/03 14:12:32+09:00 yoshfuji@linux-ipv6.org +21 -13
#   [IPV6] Always add a fragment header after receiving TOO BIG w/ pmtu < 1280.
#   
#   According to RFC2460, PMTU is set to the IPv6 Minimum Link
#   MTU (1280) and a fragment header should always be included
#   after a node receiving Too Big message reporting PMTU is
#   less than the IPv6 Minimum Link MTU (1280).
#   
#   Signed-off-by: Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
# 
# net/ipv6/ip6_output.c
#   2005/03/03 14:12:32+09:00 yoshfuji@linux-ipv6.org +7 -3
#   [IPV6] Always add a fragment header after receiving TOO BIG w/ pmtu < 1280.
#   
#   According to RFC2460, PMTU is set to the IPv6 Minimum Link
#   MTU (1280) and a fragment header should always be included
#   after a node receiving Too Big message reporting PMTU is
#   less than the IPv6 Minimum Link MTU (1280).
#   
#   Signed-off-by: Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
# 
# include/net/dst.h
#   2005/03/03 14:12:32+09:00 yoshfuji@linux-ipv6.org +9 -0
#   [IPV6] Always add a fragment header after receiving TOO BIG w/ pmtu < 1280.
#   
#   According to RFC2460, PMTU is set to the IPv6 Minimum Link
#   MTU (1280) and a fragment header should always be included
#   after a node receiving Too Big message reporting PMTU is
#   less than the IPv6 Minimum Link MTU (1280).
#   
#   Signed-off-by: Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
# 
# include/linux/rtnetlink.h
#   2005/03/03 14:12:32+09:00 yoshfuji@linux-ipv6.org +1 -0
#   [IPV6] Always add a fragment header after receiving TOO BIG w/ pmtu < 1280.
#   
#   According to RFC2460, PMTU is set to the IPv6 Minimum Link
#   MTU (1280) and a fragment header should always be included
#   after a node receiving Too Big message reporting PMTU is
#   less than the IPv6 Minimum Link MTU (1280).
#   
#   Signed-off-by: Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
# 
# include/linux/ip.h
#   2005/03/03 14:12:32+09:00 yoshfuji@linux-ipv6.org +1 -0
#   [IPV6] Always add a fragment header after receiving TOO BIG w/ pmtu < 1280.
#   
#   According to RFC2460, PMTU is set to the IPv6 Minimum Link
#   MTU (1280) and a fragment header should always be included
#   after a node receiving Too Big message reporting PMTU is
#   less than the IPv6 Minimum Link MTU (1280).
#   
#   Signed-off-by: Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
# 
# ChangeSet
#   2005/03/03 14:38:18+09:00 yoshfuji@linux-ipv6.org 
#   [IPV6] NDISC: Ensure to send redirects even if we don't know target's lladdr.
# 
# net/ipv6/ndisc.c
#   2005/03/03 14:12:27+09:00 yoshfuji@linux-ipv6.org +11 -12
#   [IPV6] NDISC: Ensure to send redirects even if we don't know target's lladdr.
# 
# ChangeSet
#   2005/03/03 14:38:06+09:00 yoshfuji@linux-ipv6.org 
#   [IPV6] NDISC: Ensure to send redirects.
#   
#   rt6_lookup() is inappropriate because it cannot lookup
#   route to the source node of the original packet if
#   we don't have specific route to it.
#   
#   Signed-off-by: Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
# 
# net/ipv6/ndisc.c
#   2005/03/03 14:12:21+09:00 yoshfuji@linux-ipv6.org +2 -3
#   [IPV6] NDISC: Ensure to send redirects.
#   
#   rt6_lookup() is inappropriate because it cannot lookup
#   route to the source node of the original packet if
#   we don't have specific route to it.
#   
#   Signed-off-by: Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
# 
# ChangeSet
#   2005/03/03 14:37:53+09:00 yoshfuji@linux-ipv6.org 
#   [IPV6] ROUTE: Keep cache entries for a while.
#   
#   GC always removed most cache entries and
#   a fresh redirect entry might be removed immideately.
#   
#   Signed-off-by: Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
# 
# net/ipv6/route.c
#   2005/03/03 12:33:24+09:00 yoshfuji@linux-ipv6.org +1 -3
#   [IPV6] ROUTE: Keep cache entrries for a while.
#   
#   GC always removed most cache entries and
#   a fresh redirect entry might be removed immideately.
#   
#   Signed-off-by: Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
# 
# net/ipv6/ndisc.c
#   2005/03/03 12:33:24+09:00 yoshfuji@linux-ipv6.org +2 -2
#   [IPV6] ROUTE: Keep cache routes for a while.
#   
#   GC always removed most cache entries and
#   a fresh redirect entry might be removed immideately.
#   
#   Signed-off-by: Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
# 
# net/ipv6/ip6_fib.c
#   2005/03/03 12:33:24+09:00 yoshfuji@linux-ipv6.org +1 -1
#   [IPV6] ROUTE: Keep cache entrries for a while.
#   
#   GC always removed most cache entries and
#   a fresh redirect entry might be removed immideately.
#   
#   Signed-off-by: Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
# 
# ChangeSet
#   2005/03/03 14:37:40+09:00 yoshfuji@linux-ipv6.org 
#   [IPV6] NDISC: Deprecate base_reachable_time and retrans_timer.
#   
#   Signed-off-by: Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
# 
# net/ipv6/ndisc.c
#   2005/03/03 14:12:16+09:00 yoshfuji@linux-ipv6.org +28 -1
#   [IPV6] NDISC: Deprecate base_reachable_time and retrans_timer.
#   
#   Signed-off-by: Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
# 
# Documentation/filesystems/proc.txt
#   2005/03/03 14:12:16+09:00 yoshfuji@linux-ipv6.org +3 -3
#   [IPV6] NDISC: Deprecate base_reachable_time and retrans_timer.
#   
#   Signed-off-by: Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
# 
# ChangeSet
#   2005/03/03 14:37:28+09:00 yoshfuji@linux-ipv6.org 
#   [NET] NEIGHBOUR: Add retrans_time_ms and reachable_time_ms sysctls.
#   
#   Signed-off-by: Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
# 
# net/ipv6/ndisc.c
#   2005/03/03 14:12:11+09:00 yoshfuji@linux-ipv6.org +15 -2
#   [NET] NEIGHBOUR: Add retrans_time_ms and reachable_time_ms sysctls.
#   
#   Signed-off-by: Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
# 
# net/core/neighbour.c
#   2005/03/03 14:12:11+09:00 yoshfuji@linux-ipv6.org +44 -13
#   [NET] NEIGHBOUR: Add retrans_time_ms and reachable_time_ms sysctls.
#   
#   Signed-off-by: Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
# 
# include/linux/sysctl.h
#   2005/03/03 14:12:11+09:00 yoshfuji@linux-ipv6.org +4 -1
#   [NET] NEIGHBOUR: Add retrans_time_ms and reachable_time_ms sysctls.
#   
#   Signed-off-by: Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
# 
# Documentation/filesystems/proc.txt
#   2005/03/03 14:12:11+09:00 yoshfuji@linux-ipv6.org +14 -7
#   [NET] NEIGHBOUR: Add retrans_time_ms and reachable_time_ms sysctls.
#   
#   Signed-off-by: Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
# 
# ChangeSet
#   2005/03/03 14:37:14+09:00 yoshfuji@linux-ipv6.org 
#   [IPV6] NDISC: Recompute Reachable Time on change of Base Reachable Time.
#   
#   Signed-off-by: Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
# 
# net/ipv6/ndisc.c
#   2005/03/03 14:12:06+09:00 yoshfuji@linux-ipv6.org +4 -0
#   [IPV6] NDISC: Recompute Reachable Time on change of Base Reachable Time.
#   
#   Signed-off-by: Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
# 
# ChangeSet
#   2005/03/03 14:37:02+09:00 yoshfuji@linux-ipv6.org 
#   [IPV6] NDISC: NEWLINK notification on change of Reachable Time
#   
#   Signed-off-by: Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
# 
# net/ipv6/ndisc.c
#   2005/03/03 14:12:00+09:00 yoshfuji@linux-ipv6.org +44 -2
#   [IPV6] NDISC: NEWLINK notification on change of Reachable Time
#   
#   Signed-off-by: Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
# 
# net/core/neighbour.c
#   2005/03/03 14:12:00+09:00 yoshfuji@linux-ipv6.org +5 -0
#   [IPV6] NDISC: NEWLINK notification on change of Reachable Time
#   
#   Signed-off-by: Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
# 
# ChangeSet
#   2005/03/03 14:36:49+09:00 yoshfuji@linux-ipv6.org 
#   [NET] NEIGHBOUR: Add hook for sysctl strategy.
#   
#   Signed-off-by: Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
# 
# ChangeSet
#   2005/03/02 21:36:48-08:00 yoshfuji@linux-ipv6.org 
#   [TCP]: Put back tcp_timer_bug_msg[] symbol export.
#   
#   It is needed for tcp_reset_xmit_timer(), which is invoked by
#   tcp_prequeue() which is invoked from tcp_ipv6.c
#   
#   Signed-off-by: Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/ipv6/ndisc.c
#   2005/03/03 14:11:55+09:00 yoshfuji@linux-ipv6.org +1 -1
#   [NET] NEIGHBOUR: Add hook for sysctl strategy.
#   
#   Signed-off-by: Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
# 
# net/ipv6/addrconf.c
#   2005/03/03 14:11:55+09:00 yoshfuji@linux-ipv6.org +7 -2
#   [NET] NEIGHBOUR: Add hook for sysctl strategy.
#   
#   Signed-off-by: Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
# 
# net/ipv4/devinet.c
#   2005/03/03 14:11:55+09:00 yoshfuji@linux-ipv6.org +2 -2
#   [NET] NEIGHBOUR: Add hook for sysctl strategy.
#   
#   Signed-off-by: Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
# 
# net/ipv4/arp.c
#   2005/03/03 14:11:55+09:00 yoshfuji@linux-ipv6.org +1 -1
#   [NET] NEIGHBOUR: Add hook for sysctl strategy.
#   
#   Signed-off-by: Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
# 
# net/core/neighbour.c
#   2005/03/03 14:11:55+09:00 yoshfuji@linux-ipv6.org +3 -2
#   [NET] NEIGHBOUR: Add hook for sysctl strategy.
#   
#   Signed-off-by: Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
# 
# include/net/neighbour.h
#   2005/03/03 14:11:55+09:00 yoshfuji@linux-ipv6.org +2 -1
#   [NET] NEIGHBOUR: Add hook for sysctl strategy.
#   
#   Signed-off-by: Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
# 
# net/ipv4/tcp_timer.c
#   2005/03/02 21:36:38-08:00 yoshfuji@linux-ipv6.org +1 -0
#   [TCP]: Put back tcp_timer_bug_msg[] symbol export.
#   
#   It is needed for tcp_reset_xmit_timer(), which is invoked by
#   tcp_prequeue() which is invoked from tcp_ipv6.c
#   
#   Signed-off-by: Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# ChangeSet
#   2005/03/03 14:36:36+09:00 yoshfuji@linux-ipv6.org 
#   [IPV6] NDISC: Ensure to notify up-to-date link information.
#   
#   Signed-off-by: Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
# 
# net/ipv6/ndisc.c
#   2005/03/03 14:11:50+09:00 yoshfuji@linux-ipv6.org +5 -2
#   [IPV6] NDISC: Ensure to notify up-to-date link information.
#   
#   Signed-off-by: Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
# 
# ChangeSet
#   2005/03/03 14:36:24+09:00 yoshfuji@linux-ipv6.org 
#   [IPV6] ROUTE: Add gc_min_interval_ms sysctl.
#   
#   Signed-off-by: Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
# 
# net/ipv6/route.c
#   2005/03/03 14:11:44+09:00 yoshfuji@linux-ipv6.org +9 -0
#   [IPV6] ROUTE: Add gc_min_interval_ms sysctl.
#   
#   Signed-off-by: Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
# 
# include/linux/sysctl.h
#   2005/03/03 14:11:44+09:00 yoshfuji@linux-ipv6.org +2 -1
#   [IPV6] ROUTE: Add gc_min_interval_ms sysctl.
#   
#   Signed-off-by: Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
# 
# ChangeSet
#   2005/03/03 14:36:11+09:00 yoshfuji@linux-ipv6.org 
#   [IPV6] NDISC: Make ndisc_opt_lladdr_data() and check length inside.
#   
#   What we should do is to check lladdrlen and get pointer
#   for link-layer address option.
#   Since we know lladdrlen == dev->addr_len, we can check inside.
#   
#   Singned-off-by: Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
# 
# net/ipv6/ndisc.c
#   2005/03/03 14:11:39+09:00 yoshfuji@linux-ipv6.org +24 -25
#   [IPV6] NDISC: Make ndisc_opt_lladdr_data() and check length inside.
#   
#   What we should do is to check lladdrlen and get pointer
#   for link-layer address option.
#   Since we know lladdrlen == dev->addr_len, we can check inside.
#   
#   Singned-off-by: Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
# 
# ChangeSet
#   2005/03/03 14:35:57+09:00 yoshfuji@linux-ipv6.org 
#   [IPV6] NDISC: Save space for ndisc_options{}.
#   
#   Pointed out by Krishna Kumar <kumarkr@us.ibm.com>.
#   
#   Also, size of structure is now adjusted automatically.
#   
#   Signed-off-by: Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
# 
# net/ipv6/ndisc.c
#   2005/03/03 14:11:34+09:00 yoshfuji@linux-ipv6.org +2 -3
#   [IPV6] NDISC: Save space for ndisc_options{}.
#   
#   Pointed out by Krishna Kumar <kumarkr@us.ibm.com>.
#   
#   Also, size of structure is now adjusted automatically.
#   
#   Signed-off-by: Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
# 
# include/net/ndisc.h
#   2005/03/03 14:11:34+09:00 yoshfuji@linux-ipv6.org +9 -5
#   [IPV6] NDISC: Save space for ndisc_options{}.
#   
#   Pointed out by Krishna Kumar <kumarkr@us.ibm.com>.
#   
#   Also, size of structure is now adjusted automatically.
#   
#   Signed-off-by: Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
# 
# ChangeSet
#   2005/03/03 14:35:45+09:00 yoshfuji@linux-ipv6.org 
#   [IPV6] NDISC: Fix space calculation for link-layer address options.
#   
#   Signed-off-by: Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
# 
# net/ipv6/ndisc.c
#   2005/03/03 14:11:28+09:00 yoshfuji@linux-ipv6.org +14 -9
#   [IPV6] NDISC: Fix space calculation for link-layer address options.
#   
#   Signed-off-by: Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
# 
# ChangeSet
#   2005/03/03 00:23:55-05:00 xose@wanadoo.es 
#   [PATCH] 2.6 eepro100: replace and delete duplicate ids
#   
#   - replace PCI_DEVICE_ID_INTEL_82557 and PCI_DEVICE_ID_INTEL_82559ER
#     with theirs hex numbers
#   - PCI_DEVICE_ID_INTEL_82801BA_7 is a duplicate of 0x2449.
#   
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/eepro100.c
#   2005/02/01 15:10:15-05:00 xose@wanadoo.es +2 -6
#   2.6 eepro100: replace and delete duplicate ids
# 
# ChangeSet
#   2005/03/03 00:22:23-05:00 akpm@osdl.org 
#   [PATCH] drivers/net/wan/z85230.c interrupt handling fix
#   
#   From: tom watson <lkml@tommywatson.com>
#   
#   While working on a driver for z85230 based board I noticed what looks like
#   it could be a problem.  If the interrupt handler is handling an interrupt
#   on port b and an interrupt comes in for port a, it seems to me that the
#   port b handler would be called instead of the port a handler, and possibly
#   hang the board until reset.
#   
#   Attached is a patch to set the irq methods back to port a before attempting
#   to call them.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/wan/z85230.c
#   2005/02/24 12:39:03-05:00 akpm@osdl.org +3 -1
#   drivers/net/wan/z85230.c interrupt handling fix
# 
# ChangeSet
#   2005/03/03 00:21:30-05:00 bunk@stusta.de 
#   [PATCH] drivers/scsi/sata_*: make code static
#   
#   This patch makes needlessly global code static.
#   
#   Signed-off-by: Adrian Bunk <bunk@stusta.de>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/scsi/sata_vsc.c
#   2005/02/28 13:55:40-05:00 bunk@stusta.de +2 -1
#   drivers/scsi/sata_*: make code static
# 
# drivers/scsi/sata_svw.c
#   2005/02/28 13:55:06-05:00 bunk@stusta.de +2 -2
#   drivers/scsi/sata_*: make code static
# 
# drivers/scsi/sata_sil.c
#   2005/02/28 13:54:34-05:00 bunk@stusta.de +1 -1
#   drivers/scsi/sata_*: make code static
# 
# drivers/scsi/sata_nv.c
#   2005/02/28 13:54:00-05:00 bunk@stusta.de +4 -2
#   drivers/scsi/sata_*: make code static
# 
# ChangeSet
#   2005/03/03 00:19:59-05:00 khc@pm.waw.pl 
#   [PATCH] WAN drivers fix: N2, C101, PCI200SYN - quite fatal
#   
#   The last change to drivers/wan/hd6457x.c was a bit fatal to drivers
#   using it - the attached patch fixes NULL pointer dereference on RX.
#   
#   I've updated URLs in MAINTAINERS and wan/Kconfig as well.
#   
#   Signed-off-by: Krzysztof Halasa <khc@pm.waw.pl>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/wan/hd6457x.c
#   2005/02/28 19:58:08-05:00 khc@pm.waw.pl +1 -1
#   WAN drivers fix: N2, C101, PCI200SYN - quite fatal
# 
# drivers/net/wan/Kconfig
#   2005/02/28 19:58:08-05:00 khc@pm.waw.pl +6 -5
#   WAN drivers fix: N2, C101, PCI200SYN - quite fatal
# 
# MAINTAINERS
#   2005/02/28 19:58:08-05:00 khc@pm.waw.pl +2 -2
#   WAN drivers fix: N2, C101, PCI200SYN - quite fatal
# 
# ChangeSet
#   2005/03/03 00:18:38-05:00 mporter@kernel.crashing.org 
#   [PATCH] emac: fix skb allocation for full-size jumbo frames
#   
#   Sets jumbo frame handling based on MTU and allocates rx buffers
#   large to handle full-size jumbo frames.
#   
#   Signed-off-by: Matt Porter <mporter@kernel.crashing.org>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/ibm_emac/ibm_emac_core.h
#   2005/02/18 11:30:07-05:00 mporter@kernel.crashing.org +2 -0
#   emac: fix skb allocation for full-size jumbo frames
# 
# drivers/net/ibm_emac/ibm_emac_core.c
#   2005/02/18 11:23:08-05:00 mporter@kernel.crashing.org +12 -4
#   emac: fix skb allocation for full-size jumbo frames
# 
# ChangeSet
#   2005/03/03 00:17:59-05:00 rddunlap@osdl.org 
#   [PATCH] tulip/de2104x: don't mix __init & __devinit sections
#   
#   tulip/de2104x: fix section usage, don't mix __init & __devinit:
#   
#   Error: ./drivers/net/tulip/de2104x.o .text refers to 000000000000176d R_X86_64_PC32     .init.text+0xfffffffffffffffc
#   Error: ./drivers/net/tulip/de2104x.o .text refers to 0000000000001798 R_X86_64_PC32     .init.text+0xfffffffffffffffc
#   
#   Signed-off-by: Randy Dunlap <rddunlap@osdl.org>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/tulip/de2104x.c
#   2005/03/02 12:49:14-05:00 rddunlap@osdl.org +1 -1
#   tulip/de2104x: don't mix __init & __devinit sections
# 
# ChangeSet
#   2005/03/03 00:17:18-05:00 rddunlap@osdl.org 
#   [PATCH] net/wan/sbni: fix section usage
#   
#   net/wan/sbni data reference can be initdata:
#   
#   Error: ./drivers/net/wan/sbni.o .data refers to 0000000000000000 R_X86_64_64       .init.data+0x0000000000000060
#   Error: ./drivers/net/wan/sbni.o .data refers to 0000000000000008 R_X86_64_64       .init.data+0x0000000000000140
#   Error: ./drivers/net/wan/sbni.o .data refers to 0000000000000010 R_X86_64_64       .init.data+0x0000000000000180
#   Error: ./drivers/net/wan/sbni.o .data refers to 0000000000000018 R_X86_64_64       .init.data+0x0000000000000020
#   Error: ./drivers/net/wan/sbni.o .data refers to 0000000000000020 R_X86_64_64       .init.data+0x00000000000001c0
#   
#   Signed-off-by: Randy Dunlap <rddunlap@osdl.org>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/wan/sbni.c
#   2005/03/02 12:45:09-05:00 rddunlap@osdl.org +1 -1
#   net/wan/sbni: fix section usage
# 
# ChangeSet
#   2005/03/03 00:15:00-05:00 liml@rtr.ca 
#   [PATCH] sata_qstor: eh_timeout fix
#   
#   Here is an update to sata_qstor.c to enable full/proper
#   register access during eh_timeout handling.
#   
#   Signed-off-by: Mark Lord <mlord@pobox.com>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/scsi/sata_qstor.c
#   2005/02/28 11:19:31-05:00 liml@rtr.ca +24 -6
#   sata_qstor:  eh_timeout fix
# 
# ChangeSet
#   2005/03/03 00:09:53-05:00 ralf@linux-mips.org 
#   [PATCH] Remove unused MAXBPQDEV definition
#   
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/hamradio/bpqether.c
#   2005/02/26 10:33:50-05:00 ralf@linux-mips.org +0 -2
#   Remove unused MAXBPQDEV definition
# 
# ChangeSet
#   2005/03/03 00:09:04-05:00 rddunlap@osdl.org 
#   [PATCH] prism54: fix printk format warnings
#   
#   prism54 build shows some printk format complaints:
#   (sparc64 build warning)
#   
#   drivers/net/wireless/prism54/isl_38xx.c:131: warning: long int format, different type arg (arg 3)
#   drivers/net/wireless/prism54/isl_38xx.c:151: warning: long int format, different type arg (arg 3)
#   
#   cross-compile results:
#   https://www.osdl.org/plm-cgi/plm?module=patch_info&patch_id=4240
#   
#   Signed-off-by: Randy Dunlap <rddunlap@osdl.org>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/wireless/prism54/isl_38xx.c
#   2005/03/01 23:15:00-05:00 rddunlap@osdl.org +6 -6
#   prism54: fix printk format warnings
# 
# ChangeSet
#   2005/03/03 00:07:46-05:00 takis@lumumba.luc.ac.be 
#   [PATCH] Possible AMD8111e free irq issue
#   
#   It seems to me that if in the amd8111e_open() fuction dev->irq isn't
#   zero and the irq request succeeds it might not get released anymore.
#   
#   Specifically, on failure of the amd8111e_restart() call the function
#   returns -ENOMEM without releasing the irq. The amd8111e_restart()
#   function can fail because of various pci_alloc_consistent() and
#   dev_alloc_skb() calls in amd8111e_init_ring() which is being
#   called by amd8111e_restart.
#   
#   1374     if(dev->irq ==0 || request_irq(dev->irq, amd8111e_interrupt, SA_SHIRQ,
#   1375                      dev->name, dev))
#   1376         return -EAGAIN;
#   
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/amd8111e.c
#   2005/02/28 07:45:09-05:00 takis@lumumba.luc.ac.be +2 -0
#   Possible AMD8111e free irq issue
# 
# ChangeSet
#   2005/03/03 00:06:39-05:00 takis@lumumba.luc.ac.be 
#   [PATCH] Possible VIA-Rhine free irq issue
#   
#   It seems to me that in the VIA Rhine device driver the requested irq might
#   not be freed in case the alloc_ring() function fails. alloc_ring()
#   can fail with a ENOMEM return value because of possible
#   pci_alloc_consistent() failures.
#   
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/via-rhine.c
#   2005/02/28 07:44:31-05:00 takis@lumumba.luc.ac.be +3 -0
#   Possible VIA-Rhine free irq issue
# 
# ChangeSet
#   2005/03/03 00:04:43-05:00 tvignaud@mandrakesoft.com 
#   [PATCH] fix driver name in dl2k as returned by ETHTOOL_GDRVINFO
#   
#   The GDRVINFO command of the ETHTOOL ioctl returns a bogus driver name.
#   
#   this bug confusees various network config tools...
#   
#   see mdk bug #12609 (http://qa.mandrakesoft.com/show_bug.cgi?id=12609)
#   for reference
#   
#   Signed-off-by: Thierry Vignaud <tvignaud@mandrakesoft.com>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/dl2k.c
#   2005/02/25 13:26:52-05:00 tvignaud@mandrakesoft.com +1 -1
#   fix driver name in dl2k as returned by ETHTOOL_GDRVINFO
# 
# ChangeSet
#   2005/03/03 00:02:38-05:00 sfeldma@pobox.com 
#   [PATCH] eepro100: remove ID for 82556
#   
#   82556 support doesn't work with eepro100, so this removes the ID
#   (0x1228) for 82556.  See this thread for more info:
#   
#   http://marc.theaimsgroup.com/?l=linux-kernel&m=110726223221165&w=2
#   
#   Signed-off-by: Scott Feldman <sfeldma@pobox.com>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/eepro100.c
#   2005/03/03 00:02:31-05:00 sfeldma@pobox.com +0 -1
#   [PATCH] eepro100: remove ID for 82556
#   
#   82556 support doesn't work with eepro100, so this removes the ID
#   (0x1228) for 82556.  See this thread for more info:
#   
#   http://marc.theaimsgroup.com/?l=linux-kernel&m=110726223221165&w=2
#   
#   Signed-off-by: Scott Feldman <sfeldma@pobox.com>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# ChangeSet
#   2005/03/03 00:01:46-05:00 linville@redhat.com 
#   [PATCH] sk98lin: add MODULE_DEVICE_TABLE entry
#   
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/sk98lin/skge.c
#   2005/03/03 00:01:39-05:00 linville@redhat.com +2 -0
#   [PATCH] sk98lin: add MODULE_DEVICE_TABLE entry
#   
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# ChangeSet
#   2005/03/03 00:00:49-05:00 pavel@suse.cz 
#   [PATCH] Fix u32 vs. pm_message_t in network device drivers
#   
#   This should fix confusion in network device drivers. No code
#   changes.
#   
#   Signed-off-by: Pavel Machek <pavel@suse.cz>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/via-velocity.c
#   2005/03/03 00:00:42-05:00 pavel@suse.cz +2 -2
#   [PATCH] Fix u32 vs. pm_message_t in network device drivers
#   
#   This should fix confusion in network device drivers. No code
#   changes.
#   
#   Signed-off-by: Pavel Machek <pavel@suse.cz>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/via-rhine.c
#   2005/03/03 00:00:42-05:00 pavel@suse.cz +1 -1
#   [PATCH] Fix u32 vs. pm_message_t in network device drivers
#   
#   This should fix confusion in network device drivers. No code
#   changes.
#   
#   Signed-off-by: Pavel Machek <pavel@suse.cz>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/typhoon.c
#   2005/03/03 00:00:42-05:00 pavel@suse.cz +5 -5
#   [PATCH] Fix u32 vs. pm_message_t in network device drivers
#   
#   This should fix confusion in network device drivers. No code
#   changes.
#   
#   Signed-off-by: Pavel Machek <pavel@suse.cz>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/tulip/tulip_core.c
#   2005/03/03 00:00:42-05:00 pavel@suse.cz +1 -1
#   [PATCH] Fix u32 vs. pm_message_t in network device drivers
#   
#   This should fix confusion in network device drivers. No code
#   changes.
#   
#   Signed-off-by: Pavel Machek <pavel@suse.cz>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/tg3.c
#   2005/03/03 00:00:42-05:00 pavel@suse.cz +2 -2
#   [PATCH] Fix u32 vs. pm_message_t in network device drivers
#   
#   This should fix confusion in network device drivers. No code
#   changes.
#   
#   Signed-off-by: Pavel Machek <pavel@suse.cz>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/sungem.c
#   2005/03/03 00:00:42-05:00 pavel@suse.cz +1 -1
#   [PATCH] Fix u32 vs. pm_message_t in network device drivers
#   
#   This should fix confusion in network device drivers. No code
#   changes.
#   
#   Signed-off-by: Pavel Machek <pavel@suse.cz>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/sis900.c
#   2005/03/03 00:00:42-05:00 pavel@suse.cz +1 -1
#   [PATCH] Fix u32 vs. pm_message_t in network device drivers
#   
#   This should fix confusion in network device drivers. No code
#   changes.
#   
#   Signed-off-by: Pavel Machek <pavel@suse.cz>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/ne2k-pci.c
#   2005/03/03 00:00:42-05:00 pavel@suse.cz +2 -2
#   [PATCH] Fix u32 vs. pm_message_t in network device drivers
#   
#   This should fix confusion in network device drivers. No code
#   changes.
#   
#   Signed-off-by: Pavel Machek <pavel@suse.cz>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/natsemi.c
#   2005/03/03 00:00:42-05:00 pavel@suse.cz +1 -1
#   [PATCH] Fix u32 vs. pm_message_t in network device drivers
#   
#   This should fix confusion in network device drivers. No code
#   changes.
#   
#   Signed-off-by: Pavel Machek <pavel@suse.cz>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/irda/donauboe.c
#   2005/03/03 00:00:42-05:00 pavel@suse.cz +1 -1
#   [PATCH] Fix u32 vs. pm_message_t in network device drivers
#   
#   This should fix confusion in network device drivers. No code
#   changes.
#   
#   Signed-off-by: Pavel Machek <pavel@suse.cz>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/epic100.c
#   2005/03/03 00:00:42-05:00 pavel@suse.cz +1 -1
#   [PATCH] Fix u32 vs. pm_message_t in network device drivers
#   
#   This should fix confusion in network device drivers. No code
#   changes.
#   
#   Signed-off-by: Pavel Machek <pavel@suse.cz>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/eepro100.c
#   2005/03/03 00:00:42-05:00 pavel@suse.cz +3 -3
#   [PATCH] Fix u32 vs. pm_message_t in network device drivers
#   
#   This should fix confusion in network device drivers. No code
#   changes.
#   
#   Signed-off-by: Pavel Machek <pavel@suse.cz>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/e100.c
#   2005/03/03 00:00:42-05:00 pavel@suse.cz +2 -2
#   [PATCH] Fix u32 vs. pm_message_t in network device drivers
#   
#   This should fix confusion in network device drivers. No code
#   changes.
#   
#   Signed-off-by: Pavel Machek <pavel@suse.cz>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/b44.c
#   2005/03/03 00:00:42-05:00 pavel@suse.cz +1 -1
#   [PATCH] Fix u32 vs. pm_message_t in network device drivers
#   
#   This should fix confusion in network device drivers. No code
#   changes.
#   
#   Signed-off-by: Pavel Machek <pavel@suse.cz>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/amd8111e.c
#   2005/03/03 00:00:42-05:00 pavel@suse.cz +1 -1
#   [PATCH] Fix u32 vs. pm_message_t in network device drivers
#   
#   This should fix confusion in network device drivers. No code
#   changes.
#   
#   Signed-off-by: Pavel Machek <pavel@suse.cz>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/8139too.c
#   2005/03/03 00:00:42-05:00 pavel@suse.cz +1 -1
#   [PATCH] Fix u32 vs. pm_message_t in network device drivers
#   
#   This should fix confusion in network device drivers. No code
#   changes.
#   
#   Signed-off-by: Pavel Machek <pavel@suse.cz>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/3c59x.c
#   2005/03/03 00:00:42-05:00 pavel@suse.cz +1 -1
#   [PATCH] Fix u32 vs. pm_message_t in network device drivers
#   
#   This should fix confusion in network device drivers. No code
#   changes.
#   
#   Signed-off-by: Pavel Machek <pavel@suse.cz>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# ChangeSet
#   2005/03/02 23:58:29-05:00 mporter@kernel.crashing.org 
#   [PATCH] Add PPC440SP support to IBM EMAC driver
#   
#   Configures EMAC thresholds appropriately for the EMAC on the PPC440SP.
#   
#   Signed-off-by: Matt Porter <mporter@kernel.crashing.org>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/ibm_emac/ibm_emac.h
#   2005/03/02 23:58:23-05:00 mporter@kernel.crashing.org +4 -0
#   [PATCH] Add PPC440SP support to IBM EMAC driver
#   
#   Configures EMAC thresholds appropriately for the EMAC on the PPC440SP.
#   
#   Signed-off-by: Matt Porter <mporter@kernel.crashing.org>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# ChangeSet
#   2005/03/02 23:57:27-05:00 sfeldma@pobox.com 
#   [PATCH] e100: remove reference to NAPI config option
#   
#   e100 is NAPI all the time, so the Kconfig option is wasting space.
#   
#   Signed-off-by: Scott Feldman <sfeldma@pobox.com>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/Kconfig
#   2005/03/02 23:57:20-05:00 sfeldma@pobox.com +0 -17
#   [PATCH] e100: remove reference to NAPI config option
#   
#   e100 is NAPI all the time, so the Kconfig option is wasting space.
#   
#   Signed-off-by: Scott Feldman <sfeldma@pobox.com>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# Documentation/networking/e100.txt
#   2005/03/02 23:57:20-05:00 sfeldma@pobox.com +1 -2
#   [PATCH] e100: remove reference to NAPI config option
#   
#   e100 is NAPI all the time, so the Kconfig option is wasting space.
#   
#   Signed-off-by: Scott Feldman <sfeldma@pobox.com>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# ChangeSet
#   2005/03/02 23:55:36-05:00 akpm@osdl.org 
#   [PATCH] smc91x: power down PHY on suspend
#   
#   From: Ian Campbell <icampbell@arcom.com>
#   
#   Powering down the PHY saves something like 100mA at 5V on my platform.
#   Currently it is only done when the interface is brought down but it makes
#   sense to do it on suspend as well.
#   
#   Signed-off-by: Ian Campbell <icampbell@arcom.com>
#   Signed-off-by: Nicolas Pitre <nico@cam.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/smc91x.c
#   2005/03/02 23:55:29-05:00 akpm@osdl.org +20 -17
#   [PATCH] smc91x: power down PHY on suspend
#   
#   From: Ian Campbell <icampbell@arcom.com>
#   
#   Powering down the PHY saves something like 100mA at 5V on my platform.
#   Currently it is only done when the interface is brought down but it makes
#   sense to do it on suspend as well.
#   
#   Signed-off-by: Ian Campbell <icampbell@arcom.com>
#   Signed-off-by: Nicolas Pitre <nico@cam.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# ChangeSet
#   2005/03/02 23:54:56-05:00 jgarzik@pobox.com 
#   [wireless atmel] Add support LG LW2100N WLAN PCMCIA card
#   
#   Originally from Serge A. Suchkov <justman@e1.bmstu.ru>.
# 
# drivers/net/wireless/atmel_cs.c
#   2005/03/02 23:54:50-05:00 jgarzik@pobox.com +2 -1
#   [wireless atmel] Add support LG LW2100N WLAN PCMCIA card
#   
#   Originally from Serge A. Suchkov <justman@e1.bmstu.ru>.
# 
# ChangeSet
#   2005/03/02 23:50:42-05:00 akpm@osdl.org 
#   [PATCH] Add OMAP support to smc91x Ethernet driver
#   
#   From: Tony Lindgren <tony@atomide.com>
#   
#   Following patch adds support for various OMAP boards to smc91x.
#   
#   Signed-off-by: Tony Lindgren <tony@atomide.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/smc91x.h
#   2005/03/02 23:50:34-05:00 akpm@osdl.org +20 -0
#   [PATCH] Add OMAP support to smc91x Ethernet driver
#   
#   From: Tony Lindgren <tony@atomide.com>
#   
#   Following patch adds support for various OMAP boards to smc91x.
#   
#   Signed-off-by: Tony Lindgren <tony@atomide.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# ChangeSet
#   2005/03/02 23:49:14-05:00 rddunlap@osdl.org 
#   [PATCH] (v2) arlan: remove gcc warning with CONFIG_PROC_FS=n
#   
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/wireless/arlan.h
#   2005/03/02 23:49:07-05:00 rddunlap@osdl.org +2 -2
#   [PATCH] (v2) arlan: remove gcc warning with CONFIG_PROC_FS=n
#   
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# ChangeSet
#   2005/03/02 23:48:04-05:00 ganesh.venkatesan@intel.com 
#   [PATCH] ixgb: Documentation/networking/ixgb.txt
#   
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# Documentation/networking/ixgb.txt
#   2005/03/02 23:47:54-05:00 ganesh.venkatesan@intel.com +4 -5
#   [PATCH] ixgb: Documentation/networking/ixgb.txt
#   
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# ChangeSet
#   2005/03/02 23:37:44-05:00 ralf@linux-mips.org 
#   [PATCH] Sparse fixes for drivers/net/hamradio
#   
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/hamradio/6pack.c
#   2005/02/28 19:31:55-05:00 ralf@linux-mips.org +2 -2
#   Sparse fixes for drivers/net/hamradio
# 
# ChangeSet
#   2005/03/02 23:30:53-05:00 jgarzik@pobox.com 
#   Hand-merge sis900 conflicts.
# 
# drivers/net/sis900.c
#   2005/03/02 23:30:47-05:00 jgarzik@pobox.com +2 -1
#   Hand-merge sis900 conflicts.
# 
# ChangeSet
#   2005/03/02 23:28:51-05:00 mbrancaleoni@tiscali.it 
#   [PATCH] sis900.c net poll support
#   
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/sis900.c
#   2005/01/05 04:09:04-05:00 mbrancaleoni@tiscali.it +18 -0
#   sis900.c net poll support
# 
# ChangeSet
#   2005/03/03 02:32:18+00:00 ben-linux@org.rmk.(none) 
#   [ARM PATCH] 2500/1: S3C2410 - include/asm-arm/arch-s3c2410/regs-adc.h
#   
#   Patch from Ben Dooks
#   
#   S3C2410 ADC register definitions
#   Patch from Shannon Holland
#   
#   Signed-off-by: Shannon Holland
#   
#   Signed-off-by: Ben Dooks
#   Signed-off-by: Russell King
# 
# include/asm-arm/arch-s3c2410/regs-adc.h
#   2005/02/22 18:03:36+00:00 ben-linux@org.rmk.(none) +63 -0
#   [PATCH] 2500/1: S3C2410 - include/asm-arm/arch-s3c2410/regs-adc.h
# 
# include/asm-arm/arch-s3c2410/regs-adc.h
#   2005/02/22 18:03:36+00:00 ben-linux@org.rmk.(none) +0 -0
#   BitKeeper file /usr/src/bk/linux-2.6-rmk/include/asm-arm/arch-s3c2410/regs-adc.h
# 
# ChangeSet
#   2005/03/03 02:11:30+00:00 ben-linux@org.rmk.(none) 
#   [ARM PATCH] 2495/1: 21285 - fix build warnings
#   
#   Patch from Ben Dooks
#   
#   21285 serial driver has a couple of sparse errors from zero
#   initialiser, as well as an unused label.
#   
#   Signed-off-by: Ben Dooks
#   Signed-off-by: Russell King
# 
# drivers/serial/21285.c
#   2005/02/21 12:34:22+00:00 ben-linux@org.rmk.(none) +0 -3
#   [PATCH] 2495/1: 21285 - fix build warnings
# 
# ChangeSet
#   2005/03/03 01:52:00+00:00 cbrake@com.rmk.(none) 
#   [ARM PATCH] 2488/1: Update Vibren PXA255 IDP support
#   
#   Patch from Cliff Brake
#   
#   Changes to machine specific files and add defconfig so the CONFIG_ARCH_PXA_IDP machine will build and run.  Changes are mostly related to the 2.6 driver model.  Also removed code that is no longer required -- support for older versions of hardware, etc.
#   
#   Signed-off-by: Cliff Brake
#   Signed-off-by: Russell King
# 
# include/asm-arm/arch-pxa/idp.h
#   2005/02/16 16:52:21+00:00 cbrake@com.rmk.(none) +13 -277
#   [PATCH] 2488/1: Update Vibren PXA255 IDP support
# 
# arch/arm/mach-pxa/leds-idp.c
#   2005/02/16 16:52:21+00:00 cbrake@com.rmk.(none) +1 -0
#   [PATCH] 2488/1: Update Vibren PXA255 IDP support
# 
# arch/arm/mach-pxa/idp.c
#   2005/02/16 16:52:21+00:00 cbrake@com.rmk.(none) +113 -47
#   [PATCH] 2488/1: Update Vibren PXA255 IDP support
# 
# arch/arm/configs/pxa255-idp_defconfig
#   2005/02/16 16:52:21+00:00 cbrake@com.rmk.(none) +765 -0
#   [PATCH] 2488/1: Update Vibren PXA255 IDP support
# 
# arch/arm/configs/pxa255-idp_defconfig
#   2005/02/16 16:52:21+00:00 cbrake@com.rmk.(none) +0 -0
#   BitKeeper file /usr/src/bk/linux-2.6-rmk/arch/arm/configs/pxa255-idp_defconfig
# 
# ChangeSet
#   2005/03/03 01:37:23+00:00 ben-linux@org.rmk.(none) 
#   [ARM PATCH] 2483/1: S3C2410 - serial sparse error
#   
#   Patch from Ben Dooks
#   
#   Eliminate NULL initiated fields in the port structures
#   which where causing errors from sparse.
#   
#   Signed-off-by: Ben Dooks
#   Signed-off-by: Russell King
# 
# drivers/serial/s3c2410.c
#   2005/02/14 16:58:39+00:00 ben-linux@org.rmk.(none) +0 -6
#   [PATCH] 2483/1: S3C2410 - serial sparse error
# 
# ChangeSet
#   2005/03/03 01:16:06+00:00 ben-linux@org.rmk.(none) 
#   [ARM PATCH] 2482/1: IXP2000 - header cleanup
#   
#   Patch from Ben Dooks
#   
#   fix the following problems:
#   lib/iomap.c:140: warning: passing arg 1 of `__raw_readsb' makes pointer from integer without a cast
#   lib/iomap.c:156: warning: passing arg 1 of `__raw_writesb' makes pointer from integer without a cast
#   include/asm-arm/arch-ixp2000/io.h modified to have (void __iomem *) in front of the alignment code
#   include/asm/arch/system.h:22: warning: `cli' is deprecated (declared at include/linux/interrupt.h:65)
#   cli() replace by local_irq_disable
#   arch/arm/mach-ixp2000/ixdp2x01.c:116: warning: passing arg 1 of `ixp2000_reg_write' from incompatible pointer type
#   arch/arm/mach-ixp2000/ixdp2x01.c:117: warning: passing arg 1 of `ixp2000_reg_write' from incompatible pointer type
#   fixed definition of the cpld registers IXDP2X01_CPLD_VIRT_REG()
#   
#   Signed-off-by: Ben DooksLooks okay.  Test-booted on ENP-2611, no problem.
#   
#   
#   Signed-off-by: Lennert Buytenhek <buytenh@wantstofly.org>
#   Signed-off-by: Russell King
# 
# ChangeSet
#   2005/03/02 16:59:57-08:00 c.lucas@ifrance.com 
#   [PATCH] drivers/w1/*: convert to pci_register_driver
#   
#   convert from pci_module_init to pci_register_driver
#   (from:http://kerneljanitors.org/TODO).
#   
#   Signed-off-by: Christophe Lucas <c.lucas@ifrance.com>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/w1/matrox_w1.c
#   2005/03/02 09:56:32-08:00 c.lucas@ifrance.com +1 -1
#   drivers/w1/*: convert to pci_register_driver
# 
# ChangeSet
#   2005/03/02 16:59:41-08:00 johnpol@2ka.mipt.ru 
#   [PATCH] w1: get rid of the potential problems with atomic operations.
#   
#   Get rid of the potential problems with atomic operations.
#   
#   According to upcoming atomic_ops.txt by David Miller and Anton Blanchard
#   some archs may reoder atomic operations with nonatomic, since
#   the former are always visible but the latter are not, this can lead
#   to unpredicted behaviour.
#   
#   Signed-off-by: Evgeniy Polyakov <johnpol@2ka.mipt.ru>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/w1/w1_therm.c
#   2005/03/02 09:56:44-08:00 johnpol@2ka.mipt.ru +2 -0
#   w1: get rid of the potential problems with atomic operations.
# 
# drivers/w1/w1_family.c
#   2005/03/02 09:56:44-08:00 johnpol@2ka.mipt.ru +2 -0
#   w1: get rid of the potential problems with atomic operations.
# 
# ChangeSet
#   2005/03/02 16:59:25-08:00 johnpol@2ka.mipt.ru 
#   [PATCH] w1: replace obsoleted *sleep_on*
#   
#   Remove obsoleded *sleep_on*.
#   
#   Since they are used only to wait for a given flags and awakening
#   only happens on signals, we can just replace them with
#   msleep_interruptible.
#   
#   Signed-off-by: Evgeniy Polyakov <johnpol@2ka.mipt.ru>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/w1/w1_int.c
#   2005/03/02 09:56:50-08:00 johnpol@2ka.mipt.ru +0 -1
#   w1: replace obsoleted *sleep_on*
# 
# drivers/w1/w1.h
#   2005/03/02 09:56:50-08:00 johnpol@2ka.mipt.ru +0 -1
#   w1: replace obsoleted *sleep_on*
# 
# drivers/w1/w1.c
#   2005/03/02 09:56:50-08:00 johnpol@2ka.mipt.ru +5 -13
#   w1: replace obsoleted *sleep_on*
# 
# ChangeSet
#   2005/03/02 16:59:08-08:00 greg@kroah.com 
#   [PATCH] w1: fix some compiler warnings generated by the last "static" patch.
#   
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/w1/dscore.h
#   2005/03/02 09:57:48-08:00 greg@kroah.com +0 -3
#   w1: fix some compiler warnings generated by the last "static" patch.
# 
# drivers/w1/dscore.c
#   2005/03/02 09:57:48-08:00 greg@kroah.com +0 -3
#   w1: fix some compiler warnings generated by the last "static" patch.
# 
# ChangeSet
#   2005/03/02 16:58:52-08:00 johnpol@2ka.mipt.ru 
#   [PATCH] w1: Core cleanup 1/2
#   
#   Trivial cleanups, mostly static/non static, removed unneded exports.
#   It fuzzes a bit, sorry, patch is quite old.
#   
#   Signed-off-by: Evgeniy Polyakov <johnpol@2ka.mipt.ru>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/w1/w1_int.c
#   2005/03/02 09:57:55-08:00 johnpol@2ka.mipt.ru +0 -3
#   w1: Core cleanup 1/2
# 
# drivers/w1/w1_family.c
#   2005/03/02 09:57:55-08:00 johnpol@2ka.mipt.ru +0 -2
#   w1: Core cleanup 1/2
# 
# drivers/w1/w1.c
#   2005/03/02 09:57:55-08:00 johnpol@2ka.mipt.ru +10 -13
#   w1: Core cleanup 1/2
# 
# ChangeSet
#   2005/03/02 16:58:36-08:00 johnpol@2ka.mipt.ru 
#   [PATCH] w1: dscore cleanups. 2/2
#   
#   Trivial cleanups, mostly static/non static, removed unneded exports.
#   
#   Signed-off-by: Evgeniy Polyakov <johnpol@2ka.mipt.ru>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/w1/dscore.c
#   2005/03/02 09:58:02-08:00 johnpol@2ka.mipt.ru +14 -10
#   w1: dscore cleanups. 2/2
# 
# ChangeSet
#   2005/03/02 16:58:20-08:00 nacc@us.ibm.com 
#   [PATCH] w1/w1_therm: replace schedule_timeout() with msleep_interruptible()
#   
#   Description: Use msleep_interruptible() instead of schedule_timeout() to
#   guarantee the task delays as expected. Changed tm to an int, as it now is in
#   terms of msecs, not jiffies.
#   
#   Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
#   Signed-off-by: Evgeniy Polyakov <johnpol@2ka.mipt.ru>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/w1/w1_therm.c
#   2005/03/02 09:59:29-08:00 nacc@us.ibm.com +4 -6
#   w1/w1_therm: replace schedule_timeout() with msleep_interruptible()
# 
# include/asm-arm/arch-ixp2000/system.h
#   2005/02/14 00:35:09+00:00 ben-linux@org.rmk.(none) +1 -1
#   [PATCH] 2482/1: IXP2000 - header cleanup
# 
# include/asm-arm/arch-ixp2000/ixdp2x01.h
#   2005/02/14 00:34:41+00:00 ben-linux@org.rmk.(none) +1 -1
#   [PATCH] 2482/1: IXP2000 - header cleanup
# 
# include/asm-arm/arch-ixp2000/io.h
#   2005/02/14 00:39:16+00:00 ben-linux@org.rmk.(none) +2 -2
#   [PATCH] 2482/1: IXP2000 - header cleanup
# 
# ChangeSet
#   2005/03/03 00:55:12+00:00 ben-linux@org.rmk.(none) 
#   [ARM PATCH] 2470/1: S3C2410 Documentation - add Guillaume Gourat
#   
#   Patch from Ben Dooks
#   
#   Add Guillaume Gourat to list of port contributors
#   
#   Signed-off-by: Ben Dooks
#   Signed-off-by: Russell King
# 
# Documentation/arm/Samsung-S3C24XX/Overview.txt
#   2005/02/11 00:02:19+00:00 ben-linux@org.rmk.(none) +2 -0
#   [PATCH] 2470/1: S3C2410 Documentation - add Guillaume Gourat
# 
# ChangeSet
#   2005/03/03 00:37:40+00:00 ben-linux@org.rmk.(none) 
#   [ARM PATCH] 2469/1: S3C2410 - add S3C2410_TCFG1_MUX4_SHIFT definition
#   
#   Patch from Ben Dooks
#   
#   Add missing S3C2410_TCFG1_MUX4_SHIFT
#   Patch from Guillaume Gourat
#   
#   Signed-off-by: Guillaume GOURAT
#   
#   Signed-off-by: Ben Dooks
#   Signed-off-by: Russell King
# 
# include/asm-arm/arch-s3c2410/regs-timer.h
#   2005/02/11 00:04:43+00:00 ben-linux@org.rmk.(none) +2 -0
#   [PATCH] 2469/1: S3C2410 - add S3C2410_TCFG1_MUX4_SHIFT definition
# 
# ChangeSet
#   2005/03/03 00:18:41+00:00 ben-linux@org.rmk.(none) 
#   [ARM PATCH] 2467/1: S3C2440 - camera interface device
#   
#   Patch from Ben Dooks
#   
#   Add s3c2440 camera interface device definition
#   Patch from Guillaume GOURAT
#   
#   Signed-off-by: Guillaume GOURAT
#   
#   Signed-off-by: Ben Dooks
#   Signed-off-by: Russell King
# 
# ChangeSet
#   2005/03/02 16:13:45-08:00 khali@linux-fr.org 
#   [PATCH] I2C: Trivial indentation fix in i2c/chips/Kconfig
#   
#   Hi Greg,
#   
#   Quoting myself:
#   
#   > (...) I also think I see an indentation issue on the "tristate" line,
#   > seemingly copied from the SENSORS_DS1621 section which would need to
#   > be fixed as well.
#   
#   Here is the trivial patch fixing that, if you want to apply it.
#   
#   Signed-off-by: Jean Delvare <khali@linux-fr.org>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/i2c/chips/Kconfig
#   2005/03/02 07:15:12-08:00 khali@linux-fr.org +1 -1
#   I2C: Trivial indentation fix in i2c/chips/Kconfig
# 
# ChangeSet
#   2005/03/02 16:13:14-08:00 khali@linux-fr.org 
#   [PATCH] I2C: Change of i2c co-maintainer
#   
#   Since I am working more actively than Philip (or anyone else, for that
#   matter) on the i2c subsystem these days, it would probably make sense
#   that I am listed as the co-maintainer instead of him.
#   
#   Signed-off-by: Jean Delvare <khali@linux-fr.org>
#   Acked-by: Philip Edelbrock <phil@netroedge.com>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# MAINTAINERS
#   2005/03/02 10:50:04-08:00 khali@linux-fr.org +2 -2
#   I2C: Change of i2c co-maintainer
# 
# include/asm-arm/arch-s3c2410/map.h
#   2005/02/10 17:35:15+00:00 ben-linux@org.rmk.(none) +5 -0
#   [PATCH] 2467/1: S3C2440 - camera interface device
# 
# include/asm-arm/arch-s3c2410/irqs.h
#   2005/02/10 17:41:08+00:00 ben-linux@org.rmk.(none) +3 -1
#   [PATCH] 2467/1: S3C2440 - camera interface device
# 
# arch/arm/mach-s3c2410/devs.h
#   2005/02/10 17:40:27+00:00 ben-linux@org.rmk.(none) +12 -0
#   [PATCH] 2467/1: S3C2440 - camera interface device
# 
# arch/arm/mach-s3c2410/devs.c
#   2005/02/10 17:39:56+00:00 ben-linux@org.rmk.(none) +36 -0
#   [PATCH] 2467/1: S3C2440 - camera interface device
# 
# ChangeSet
#   2005/03/03 00:00:59+00:00 ben-linux@org.rmk.(none) 
#   [ARM PATCH] 2465/1: VR1000 - add power-off hook
#   
#   Patch from Ben Dooks
#   
#   Add PM hook to power board down when requested
#   
#   Signed-off-by: Ben Dooks
#   Signed-off-by: Russell King
# 
# ChangeSet
#   2005/03/02 15:50:42-08:00 gregkh@suse.de 
#   [PATCH] I2C: fixed up the i2c-id.h algo ids.
#   
#   Thanks to Jean Delvare <khali@linux-fr.org> for the help with this.
#   
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# include/linux/i2c-id.h
#   2005/03/02 15:48:37-08:00 gregkh@suse.de +9 -6
#   I2C: fixed up the i2c-id.h algo ids.
# 
# arch/arm/mach-s3c2410/mach-vr1000.c
#   2005/02/10 15:03:12+00:00 ben-linux@org.rmk.(none) +9 -1
#   [PATCH] 2465/1: VR1000 - add power-off hook
# 
# ChangeSet
#   2005/03/02 23:39:59+00:00 jelenz@edu.rmk.(none) 
#   [ARM PATCH] 2460/1: fix up resource usage on locomo
#   
#   Patch from John Lenz
#   
#   Add the list of devices on the locomo chip, and change around
#   how resources and struct resource are used.  There is only one
#   struct resource for the entire locomo, but each driver will
#   call request_mem_region on the pieces it is using.
#   Secondly, add a few helper functions to locomo.c to control
#   GPIOs and DAC.
#   
#   Signed-off-by: John Lenz
#   Signed-off-by: Russell King
# 
# include/asm-arm/hardware/locomo.h
#   2005/03/02 00:00:00+00:00 jelenz@edu.rmk.(none) +113 -111
#   [PATCH] 2460/1: fix up resource usage on locomo
# 
# arch/arm/common/locomo.c
#   2005/03/02 00:00:00+00:00 jelenz@edu.rmk.(none) +330 -29
#   [PATCH] 2460/1: fix up resource usage on locomo
# 
# ChangeSet
#   2005/03/02 23:20:52+00:00 dsaxena@net.rmk.(none) 
#   [ARM PATCH] 2450/1: Add missing REG_OFFSET to ixp4xx platform.h header
#   
#   Patch from Deepak Saxena
#   
#   Patch 2449/1 depends on this since it removes REG_OFFSET from the
#   individual board implementations.
#   
#   Signed-off-by: Deepak Saxena
#   Signed-off-by: Russell King
# 
# ChangeSet
#   2005/03/02 15:03:48-08:00 khali@linux-fr.org 
#   [PATCH] I2C: w83627hf needs i2c-isa
#   
#   The w83627hf driver is useless unless i2c-isa is present. All other
#   drivers in this case do select I2C_ISA through Kconfig, so this one
#   should as well do.
#   
#   Signed-off-by: Jean Delvare <khali@linux-fr.org>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/i2c/chips/Kconfig
#   2005/03/02 09:54:07-08:00 khali@linux-fr.org +1 -0
#   I2C: w83627hf needs i2c-isa
# 
# ChangeSet
#   2005/03/02 15:03:32-08:00 akpm@osdl.org 
#   [PATCH] I2C: saa7146 build fix
#   
#   include/media/saa7146.h:160: parse error before `*'
#   include/media/saa7146.h:160: warning: function declaration isn't a prototype
#   
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# include/media/saa7146.h
#   2005/03/02 09:54:20-08:00 akpm@osdl.org +1 -1
#   I2C: saa7146 build fix
# 
# ChangeSet
#   2005/03/02 15:03:15-08:00 khali@linux-fr.org 
#   [PATCH] Add class definition to the elektor bus driver
#   
#   Hi Frank, all,
#   
#   > > Which bus driver are you using? It obviously lacks class declaration,
#   > > so the correct fix is to add the class there.
#   >
#   > The modules that are loading are (in reverse order):
#   >      adm1031
#   >      ad5321
#   >      mic184
#   >      pca9540
#   >      i2c_sensor
#   >      i2c_elektor
#   >      i2c_algo_pcf
#   >      i2c_core
#   >
#   > So I believe what you are asking for is the i2c_elektor driver for the
#   > PCF8584 ISA to I2C chip.
#   
#   Correct, I just checked and this one actually lacks its class. Patch
#   follows.
#   
#   This patch adds a class definition to the elektor i2c bus driver.
#   Without this definition, hardware monitoring chips located on such
#   busses cannot possibly be driven.
#   
#   Signed-off-by: Jean Delvare <khali@linux-fr.org>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/i2c/busses/i2c-elektor.c
#   2005/03/02 09:54:29-08:00 khali@linux-fr.org +1 -0
#   Add class definition to the elektor bus driver
# 
# ChangeSet
#   2005/03/02 15:03:00-08:00 minyard@acm.org 
#   [PATCH] I2C: minor I2C cleanups
#   
#   This is one in a series of patches for adding a non-blocking interface
#   to the I2C driver for supporting the IPMI SMBus driver.  This patch is a
#   simply some minor cleanups and is in addition to the patch by Mickey
#   Stein (http://marc.theaimsgroup.com/?l=linux-kernel&m=110919738708916&w=2).
#   
#   Clean up some general I2C things.  Fix some grammar and put ()
#   around all the #defines that are compound to avoid nasty
#   side-effects.
#   
#   Signed-off-by: Corey Minyard <minyard@acm.org>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# include/linux/i2c.h
#   2005/03/02 09:54:36-08:00 minyard@acm.org +25 -25
#   I2C: minor I2C cleanups
# 
# ChangeSet
#   2005/03/02 15:02:43-08:00 ben-linux@fluff.org 
#   [PATCH] I2C: S3C2410 missing I2C_CLASS_HWMON
#   
#   None of the standard sensor drivers currently recognise the s3c24xx
#   I2C controller as it does not have I2C_CLASS_HWMON set in the
#   adapter class field.
#   
#   The attached patch initialises the adapter class to I2C_CLASS_HWMON
#   
#   Signed-off-by: Ben Dooks <ben-linux@fluff.org>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/i2c/busses/i2c-s3c2410.c
#   2005/03/02 09:54:46-08:00 ben-linux@fluff.org +1 -0
#   I2C: S3C2410 missing I2C_CLASS_HWMON
# 
# ChangeSet
#   2005/03/02 15:02:27-08:00 yekkim@pacbell.net 
#   [PATCH] I2C: Fix some gcc 4.0 compile failures and warnings
#   
#   gcc 4.0.x cvs seems to dislike "include/linux/i2c.h file" and others due
#   to a current gcc 4.0.x change having to do with array declarations.
#   
#   Example error msg:   include/linux/i2c.h:{55,194} error: array type has
#   incomplete element type
#   
#   A. Daplas has recently done a workaround for this on another header
#   file. A thread discussing this can be found by following the link below:
#   
#   http://gcc.gnu.org/ml/gcc/2005-02/msg00053.html
#   
#   The patch changes the array(struct i2c_msg) declaration used by
#   *i2c_transfer and *master_xfer from "struct i2c_msg msg[]" format to
#   "struct i2c_msg *msg".
#   
#   After some grepping, I came up with about a dozen files that used the
#   format disliked by gcc4 that're addressed by the attached patch.
#   Tested on gcc 3.x & gcc 4.x by configuring kernel with all i2c switches
#   enabled as module, and saw no errors or warnings in i2c.
#   
#   Signed-off-by: Mickey Stein <yekkim@pacbell.net>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# include/media/saa7146.h
#   2005/03/02 09:55:02-08:00 yekkim@pacbell.net +1 -1
#   I2C: Fix some gcc 4.0 compile failures and warnings
# 
# include/linux/i2c.h
#   2005/03/02 09:55:02-08:00 yekkim@pacbell.net +2 -2
#   I2C: Fix some gcc 4.0 compile failures and warnings
# 
# drivers/media/video/saa7134/saa7134-i2c.c
#   2005/03/02 09:55:02-08:00 yekkim@pacbell.net +1 -1
#   I2C: Fix some gcc 4.0 compile failures and warnings
# 
# drivers/media/video/bttv-i2c.c
#   2005/03/02 09:55:02-08:00 yekkim@pacbell.net +1 -1
#   I2C: Fix some gcc 4.0 compile failures and warnings
# 
# drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c
#   2005/03/02 09:55:03-08:00 yekkim@pacbell.net +1 -1
#   I2C: Fix some gcc 4.0 compile failures and warnings
# 
# drivers/media/dvb/dibusb/dvb-dibusb-fe-i2c.c
#   2005/03/02 09:55:03-08:00 yekkim@pacbell.net +1 -1
#   I2C: Fix some gcc 4.0 compile failures and warnings
# 
# drivers/media/dvb/b2c2/skystar2.c
#   2005/03/02 09:55:03-08:00 yekkim@pacbell.net +1 -1
#   I2C: Fix some gcc 4.0 compile failures and warnings
# 
# drivers/media/common/saa7146_i2c.c
#   2005/03/02 09:55:03-08:00 yekkim@pacbell.net +4 -4
#   I2C: Fix some gcc 4.0 compile failures and warnings
# 
# drivers/i2c/i2c-core.c
#   2005/03/02 09:55:02-08:00 yekkim@pacbell.net +1 -1
#   I2C: Fix some gcc 4.0 compile failures and warnings
# 
# drivers/i2c/busses/i2c-s3c2410.c
#   2005/03/02 09:55:02-08:00 yekkim@pacbell.net +2 -2
#   I2C: Fix some gcc 4.0 compile failures and warnings
# 
# drivers/i2c/busses/i2c-mpc.c
#   2005/03/02 09:55:02-08:00 yekkim@pacbell.net +1 -1
#   I2C: Fix some gcc 4.0 compile failures and warnings
# 
# drivers/i2c/busses/i2c-keywest.c
#   2005/03/02 09:55:02-08:00 yekkim@pacbell.net +1 -1
#   I2C: Fix some gcc 4.0 compile failures and warnings
# 
# drivers/i2c/busses/i2c-iop3xx.c
#   2005/03/02 09:55:02-08:00 yekkim@pacbell.net +1 -1
#   I2C: Fix some gcc 4.0 compile failures and warnings
# 
# drivers/i2c/busses/i2c-ibm_iic.c
#   2005/03/02 09:55:03-08:00 yekkim@pacbell.net +1 -1
#   I2C: Fix some gcc 4.0 compile failures and warnings
# 
# drivers/i2c/busses/i2c-au1550.c
#   2005/03/02 09:55:03-08:00 yekkim@pacbell.net +1 -1
#   I2C: Fix some gcc 4.0 compile failures and warnings
# 
# drivers/i2c/algos/i2c-algo-sgi.c
#   2005/03/02 09:55:02-08:00 yekkim@pacbell.net +1 -1
#   I2C: Fix some gcc 4.0 compile failures and warnings
# 
# drivers/i2c/algos/i2c-algo-pcf.c
#   2005/03/02 09:55:03-08:00 yekkim@pacbell.net +1 -1
#   I2C: Fix some gcc 4.0 compile failures and warnings
# 
# drivers/i2c/algos/i2c-algo-pca.c
#   2005/03/02 09:55:02-08:00 yekkim@pacbell.net +1 -1
#   I2C: Fix some gcc 4.0 compile failures and warnings
# 
# drivers/i2c/algos/i2c-algo-ite.c
#   2005/03/02 09:55:03-08:00 yekkim@pacbell.net +2 -2
#   I2C: Fix some gcc 4.0 compile failures and warnings
# 
# Documentation/i2c/writing-clients
#   2005/03/02 09:55:02-08:00 yekkim@pacbell.net +1 -1
#   I2C: Fix some gcc 4.0 compile failures and warnings
# 
# ChangeSet
#   2005/03/02 15:02:10-08:00 khali@linux-fr.org 
#   [PATCH] I2C: Make i2c list terminators explicitely unsigned
#   
#   Shouldn't the i2c list terminators be explicitely declared as unsigned?
#   I'd hope it to help code analysis tools and possibly avoid false
#   positives. Coverity's SWAT pointed my attention to these constants.
#   
#   Signed-off-by: Jean Delvare <khali@linux-fr.org>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# include/linux/i2c.h
#   2005/03/02 09:55:12-08:00 khali@linux-fr.org +2 -2
#   I2C: Make i2c list terminators explicitely unsigned
# 
# ChangeSet
#   2005/03/02 15:01:52-08:00 khali@linux-fr.org 
#   [PATCH] I2C: Remove NULL client checks in rtc8564 driver
#   
#   Several functions in your rtc8564 driver verify the non-NULLity of the
#   i2c client that is passed to them. It doesn't seem to be necessary, as I
#   can't think of any case where these functions could possibly be called
#   with a NULL i2c client. As a matter of fact, I couldn't find any similar
#   driver doing such checks.
#   
#   My attention was brought on this by Coverity's SWAT which correctly
#   noticed that three of these functions contain explicit or hidden
#   dereferences of the i2c client pointer *before* the NULL check. I guess
#   it wasn't a problem because the NULL case cannot happen (unless I miss
#   something), but this still is confusing code.
#   
#   Thus I propose the following changes:
#   
#   Signed-off-by: Jean Delvare <khali@linux-fr.org>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/i2c/chips/rtc8564.c
#   2005/03/02 09:55:20-08:00 khali@linux-fr.org +8 -8
#   I2C: Remove NULL client checks in rtc8564 driver
# 
# include/asm-arm/arch-ixp4xx/platform.h
#   2005/02/02 18:09:04+00:00 dsaxena@net.rmk.(none) +6 -0
#   [PATCH] 2450/1: Add missing REG_OFFSET to ixp4xx platform.h header
# 
# ChangeSet
#   2005/03/02 22:57:50+00:00 dsaxena@net.rmk.(none) 
#   [ARM PATCH] 2449/1: Make IXP4xx use platform devices for serial ports
#   
#   Patch from Deepak Saxena
#   
#   Signed-off-by: Deepak Saxena
#   Signed-off-by: Russell King
# 
# arch/arm/mach-ixp4xx/ixdp425-setup.c
#   2005/02/02 18:10:24+00:00 dsaxena@net.rmk.(none) +47 -41
#   [PATCH] 2449/1: Make IXP4xx use platform devices for serial ports
# 
# arch/arm/mach-ixp4xx/coyote-setup.c
#   2005/02/02 18:10:13+00:00 dsaxena@net.rmk.(none) +38 -34
#   [PATCH] 2449/1: Make IXP4xx use platform devices for serial ports
# 
# ChangeSet
#   2005/03/02 22:33:50+00:00 dsaxena@net.rmk.(none) 
#   [ARM PATCH] 2448/1: Remove PrPMC1100 platform
#   
#   Patch from Deepak Saxena
#   
#   No longer maintained, not sure one can even buy one of these.
#   
#   Signed-off-by: Deepak Saxena
#   Signed-off-by: Russell King
# 
# arch/arm/mach-ixp4xx/Makefile
#   2005/02/02 17:59:45+00:00 dsaxena@net.rmk.(none) +0 -1
#   [PATCH] 2448/1: Remove PrPMC1100 platform
# 
# BitKeeper/deleted/.del-prpmc1100-setup.c~d52922ff42d9b621
#   2005/03/02 22:29:26+00:00 dsaxena@net.rmk.(none) +0 -0
#   Delete: arch/arm/mach-ixp4xx/prpmc1100-setup.c
# 
# BitKeeper/deleted/.del-prpmc1100-pci.c~da88e9014dd6125b
#   2005/03/02 22:29:24+00:00 dsaxena@net.rmk.(none) +0 -0
#   Delete: arch/arm/mach-ixp4xx/prpmc1100-pci.c
# 
# ChangeSet
#   2005/03/02 22:21:51+00:00 rmk@flint.arm.linux.org.uk 
#   [ARM] Acorn expansion card core update.
#   
#   Add __iomem annotations and use iomem functions where appropriate.
#   Separate out expansion card allocation/initialisation and freeing.
#   Convert device attributes to be handled by driver core.
#   Clean up deprecated function warnings for internal ecard_address
#   usage.
#   
#   Signed-off-by: Russell King <rmk@arm.linux.org.uk>
# 
# include/asm-arm/ecard.h
#   2005/03/02 22:16:28+00:00 rmk@flint.arm.linux.org.uk +11 -4
#   Add __iomem annotations to irqaddr and fiqaddr.
#   Stop deprecated warnings for ecard_address usage within ecard.c
# 
# arch/arm/kernel/ecard.c
#   2005/03/02 22:16:28+00:00 rmk@flint.arm.linux.org.uk +122 -94
#   Stop deprecated warnings for ecard_address usage within ecard.c
#   Provide function to free an expansion_card.
#   Move expansion card structure allocation/initialisation to separate
#   function.
#   Convert device attributes to be registered/unregistered by driver
#   core.
#   Move test for calling expansion card loaders at reset up to top level.
# 
# ChangeSet
#   2005/03/02 14:03:27-08:00 davem@nuts.davemloft.net 
#   [SPARC64]: Accept 'm5823' clock chip as seen on SB1500.
#   
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# arch/sparc64/kernel/time.c
#   2005/03/02 14:02:54-08:00 davem@nuts.davemloft.net +5 -2
#   [SPARC64]: Accept 'm5823' clock chip as seen on SB1500.
# 
# ChangeSet
#   2005/03/02 21:28:32+00:00 rmk@flint.arm.linux.org.uk 
#   [ARM] Add card type specific data structure.
#   
#   Signed-off-by: Russell King <rmk@arm.linux.org.uk>
# 
# drivers/net/arm/ether3.h
#   2005/03/02 21:23:30+00:00 rmk@flint.arm.linux.org.uk +5 -0
#   Add card type specific data structure.
# 
# drivers/net/arm/ether3.c
#   2005/03/02 21:23:30+00:00 rmk@flint.arm.linux.org.uk +27 -35
#   Add barrier()'s to loops.
#   Add card type specific data.
# 
# ChangeSet
#   2005/03/02 21:09:16+00:00 rmk@flint.arm.linux.org.uk 
#   [ARM] Net: Convert ether1 and ether3 to use iomem accesses.
#   
#   Signed-off-by: Russell King <rmk@arm.linux.org.uk>
# 
# drivers/net/arm/ether3.h
#   2005/03/02 21:04:45+00:00 rmk@flint.arm.linux.org.uk +11 -9
#   Convert ether3 to use iomem accesses.
# 
# drivers/net/arm/ether3.c
#   2005/03/02 21:04:45+00:00 rmk@flint.arm.linux.org.uk +32 -21
#   Convert ether3 to use iomem accesses.
# 
# drivers/net/arm/ether1.h
#   2005/03/02 21:04:45+00:00 rmk@flint.arm.linux.org.uk +5 -4
#   Convert ether1 to use iomem accesses.
# 
# drivers/net/arm/ether1.c
#   2005/03/02 21:04:44+00:00 rmk@flint.arm.linux.org.uk +78 -67
#   Convert ether1 to use iomem accesses.
# 
# ChangeSet
#   2005/03/02 20:35:25+00:00 rmk@flint.arm.linux.org.uk 
#   [ARM] Use ecard_{request,release}_resources() for resource management
#   
#   Signed-off-by: Russell King <rmk@arm.linux.org.uk>
# 
# drivers/net/arm/ether3.c
#   2005/03/02 20:30:38+00:00 rmk@flint.arm.linux.org.uk +14 -18
#   Claim/release expansion card resources with ecard_request_resources()
#   and ecard_release_resources()
# 
# drivers/net/arm/ether1.c
#   2005/03/02 20:30:38+00:00 rmk@flint.arm.linux.org.uk +13 -18
#   Claim/release expansion card resources with ecard_request_resources()
#   and ecard_release_resources()
# 
# ChangeSet
#   2005/03/02 12:18:53-08:00 hfvogt@gmx.net 
#   [PATCH] I2C i2c-nforce2: add support for nForce4 (patch against 2.6.11-rc4)
#   
#   can you please apply the attached patch (against 2.6.11-rc4, but works
#   as well for 2.6.11-rc3-mm2),  that adds support for the two SMBusses of
#   the nForce4 to the i2c-nforce2 i2c bus driver.  The patch is reported to
#   work on the standard nForce4 (i.e. non-Ultra, non-SLI), but I expect
#   that it works as well for the other nForce4 chipsets, that seem to have
#   the same PCI-id for the SMBus-device.
#   
#   This patch was proposed by Chuck <chunkeey@web.de>, thanks to him for the
#   information, testing and his patch.
#   
#   Signed-off-by: Hans-Frieder Vogt <hfvogt@arcor.de>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# include/linux/pci_ids.h
#   2005/03/02 09:55:27-08:00 hfvogt@gmx.net +1 -0
#   I2C i2c-nforce2: add support for nForce4 (patch against 2.6.11-rc4)
# 
# drivers/i2c/busses/i2c-nforce2.c
#   2005/03/02 09:55:27-08:00 hfvogt@gmx.net +4 -2
#   I2C i2c-nforce2: add support for nForce4 (patch against 2.6.11-rc4)
# 
# ChangeSet
#   2005/03/02 12:18:36-08:00 icampbell@arcom.com 
#   [PATCH] I2C: fix typo in drivers/i2c/busses/i2c-ixp4xx.c
#   
#   I was looking at your ixp4xx gpio i2c driver for inspiration (for a
#   similar pxa2xx one) and I just happened to notice a tiny typo.
#   
#   Signed-off-by: Ian Campbell <icampbell@arcom.com>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/i2c/busses/i2c-ixp4xx.c
#   2005/03/02 09:55:39-08:00 icampbell@arcom.com +2 -2
#   I2C: fix typo in drivers/i2c/busses/i2c-ixp4xx.c
# 
# ChangeSet
#   2005/03/02 12:18:19-08:00 macro@linux-mips.org 
#   [PATCH] I2C: Enable I2C_PIIX4 for 64-bit platforms
#   
#    Is there any specific reason for the PIIX4 SMBus driver to be disabled on
#   64-bit platforms?  If not, then please apply the following change.  The
#   MIPS Technologies Malta development board has the 82371EB chip and
#   supports 64-bit configurations.  I've verified the driver to work
#   correctly using 64-bit kernels for both endiannesses.
#   
#   Signed-off-by: Maciej W. Rozycki <macro@mips.com>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/i2c/busses/Kconfig
#   2005/03/02 09:55:46-08:00 macro@linux-mips.org +1 -1
#   I2C: Enable I2C_PIIX4 for 64-bit platforms
# 
# ChangeSet
#   2005/03/02 12:18:03-08:00 icampbell@arcom.com 
#   [PATCH] I2C: improve debugging output
#   
#   Rework the pca_xfer() function to always print the number of
#   successfully completed transfers in a series when debugging, even when
#   exiting with an error.
#   
#   Signed-off-by: Ian Campbell <icampbell@arcom.com>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/i2c/algos/i2c-algo-pca.c
#   2005/03/02 09:55:52-08:00 icampbell@arcom.com +16 -12
#   I2C: improve debugging output
# 
# ChangeSet
#   2005/03/02 20:17:47+00:00 rmk@flint.arm.linux.org.uk 
#   [ARM] Net: add macro to access driver specific netdev data.
#   
#   Signed-off-by: Russell King <rmk@arm.linux.org.uk>
# 
# ChangeSet
#   2005/03/02 12:17:46-08:00 maartendeprez@scarlet.be 
#   [PATCH] I2C: add GL520SM Sensor Chip driver
#   
#   Port of the Genesys Logic 520SM sensor chip driver from linux 2.4
#   
#   Signed-off-by: Maarten Deprez <maartendeprez@users.sourceforge.net>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/i2c/chips/gl520sm.c
#   2005/03/02 09:55:58-08:00 maartendeprez@scarlet.be +754 -0
#   I2C: add GL520SM Sensor Chip driver
# 
# drivers/i2c/chips/Makefile
#   2005/03/02 09:55:58-08:00 maartendeprez@scarlet.be +1 -0
#   I2C: add GL520SM Sensor Chip driver
# 
# drivers/i2c/chips/Kconfig
#   2005/03/02 09:55:58-08:00 maartendeprez@scarlet.be +11 -0
#   I2C: add GL520SM Sensor Chip driver
# 
# drivers/i2c/chips/gl520sm.c
#   2005/03/02 09:55:58-08:00 maartendeprez@scarlet.be +0 -0
#   BitKeeper file /home/greg/linux/BK/do/i2c-2.6/drivers/i2c/chips/gl520sm.c
# 
# ChangeSet
#   2005/03/02 12:17:29-08:00 mgreer@mvista.com 
#   [PATCH] I2C: add Marvell mv64xxx i2c driver
#   
#   Marvell makes a line of host bridge for PPC and MIPS systems.  On those
#   bridges is an i2c controller.  This patch adds the driver for that i2c
#   controller.
#   
#   Please apply.
#   
#   Depends on patch submitted by Jean Delvare:
#   http://archives.andrew.net.au/lm-sensors/msg29405.html
#   
#   Signed-off-by: Mark A. Greer <mgreer@mvista.com>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# include/linux/mv643xx.h
#   2005/03/02 09:56:05-08:00 mgreer@mvista.com +11 -6
#   I2C: add Marvell mv64xxx i2c driver
# 
# include/linux/i2c-id.h
#   2005/03/02 09:56:05-08:00 mgreer@mvista.com +3 -0
#   I2C: add Marvell mv64xxx i2c driver
# 
# drivers/i2c/busses/i2c-mv64xxx.c
#   2005/03/02 09:56:05-08:00 mgreer@mvista.com +596 -0
#   I2C: add Marvell mv64xxx i2c driver
# 
# drivers/i2c/busses/Makefile
#   2005/03/02 09:56:05-08:00 mgreer@mvista.com +1 -0
#   I2C: add Marvell mv64xxx i2c driver
# 
# drivers/i2c/busses/Kconfig
#   2005/03/02 09:56:05-08:00 mgreer@mvista.com +10 -0
#   I2C: add Marvell mv64xxx i2c driver
# 
# drivers/i2c/busses/i2c-mv64xxx.c
#   2005/03/02 09:56:05-08:00 mgreer@mvista.com +0 -0
#   BitKeeper file /home/greg/linux/BK/do/i2c-2.6/drivers/i2c/busses/i2c-mv64xxx.c
# 
# ChangeSet
#   2005/03/02 12:17:12-08:00 aurelien@aurel32.net 
#   [PATCH] I2C: New chip driver: sis5595
#   
#   Please find below the new version of the patch against kernel
#   2.6.11-rc3-mm1 to add the sis5595 driver (sensor part).
#   
#   As you suggested, I have changed the PCI part of the driver, taking the
#   via686a driver as an example. I have also changed the comparison of
#   jiffies by using time_after.
#   
#   
#   Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/i2c/chips/sis5595.c
#   2005/03/02 09:56:12-08:00 aurelien@aurel32.net +794 -0
#   I2C: New chip driver: sis5595
# 
# drivers/i2c/chips/Makefile
#   2005/03/02 09:56:12-08:00 aurelien@aurel32.net +1 -0
#   I2C: New chip driver: sis5595
# 
# drivers/i2c/chips/Kconfig
#   2005/03/02 09:56:12-08:00 aurelien@aurel32.net +12 -0
#   I2C: New chip driver: sis5595
# 
# drivers/i2c/chips/sis5595.c
#   2005/03/02 09:56:12-08:00 aurelien@aurel32.net +0 -0
#   BitKeeper file /home/greg/linux/BK/do/i2c-2.6/drivers/i2c/chips/sis5595.c
# 
# ChangeSet
#   2005/03/02 12:16:55-08:00 mgreer@mvista.com 
#   [PATCH] I2C: add ST M41T00 I2C RTC chip driver
#   
#   This patch adds support for the ST M41T00 I2C RTC chip.
#   
#   This rtc chip has no mechanism to freeze it's registers while being
#   read; however, it will delay updating the external values of the
#   registers for 250ms after a register is read.  To ensure that a sane
#   time value is read, the driver verifies that the same registers values
#   were read twice before returning.
#   
#   Also, when setting the rtc from an interrupt handler, a tasklet is used
#   to provide the context required by the i2c core code.
#   
#   
#   Signed-off-by: Mark A. Greer <mgreer@mvista.com>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/i2c/chips/m41t00.c
#   2005/03/02 09:56:19-08:00 mgreer@mvista.com +247 -0
#   I2C: add ST M41T00 I2C RTC chip driver
# 
# drivers/i2c/chips/Makefile
#   2005/03/02 09:56:19-08:00 mgreer@mvista.com +1 -0
#   I2C: add ST M41T00 I2C RTC chip driver
# 
# drivers/i2c/chips/Kconfig
#   2005/03/02 09:56:19-08:00 mgreer@mvista.com +9 -0
#   I2C: add ST M41T00 I2C RTC chip driver
# 
# drivers/i2c/chips/m41t00.c
#   2005/03/02 09:56:19-08:00 mgreer@mvista.com +0 -0
#   BitKeeper file /home/greg/linux/BK/do/i2c-2.6/drivers/i2c/chips/m41t00.c
# 
# ChangeSet
#   2005/03/02 12:16:37-08:00 adobriyan@mail.ru 
#   [PATCH] I2C: use time_after instead of comparing jiffies
#   
#   Signed-off-by: Alexey Dobriyan <adobriyan@mail.ru>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/i2c/chips/w83l785ts.c
#   2005/03/02 09:56:26-08:00 adobriyan@mail.ru +2 -3
#   I2C: use time_after instead of comparing jiffies
# 
# drivers/i2c/chips/w83781d.c
#   2005/03/02 09:56:26-08:00 adobriyan@mail.ru +3 -3
#   I2C: use time_after instead of comparing jiffies
# 
# drivers/i2c/chips/w83627hf.c
#   2005/03/02 09:56:26-08:00 adobriyan@mail.ru +3 -2
#   I2C: use time_after instead of comparing jiffies
# 
# drivers/i2c/chips/via686a.c
#   2005/03/02 09:56:26-08:00 adobriyan@mail.ru +3 -3
#   I2C: use time_after instead of comparing jiffies
# 
# drivers/i2c/chips/smsc47m1.c
#   2005/03/02 09:56:26-08:00 adobriyan@mail.ru +2 -2
#   I2C: use time_after instead of comparing jiffies
# 
# drivers/i2c/chips/smsc47b397.c
#   2005/03/02 09:56:26-08:00 adobriyan@mail.ru +2 -3
#   I2C: use time_after instead of comparing jiffies
# 
# drivers/i2c/chips/pc87360.c
#   2005/03/02 09:56:26-08:00 adobriyan@mail.ru +2 -2
#   I2C: use time_after instead of comparing jiffies
# 
# drivers/i2c/chips/max1619.c
#   2005/03/02 09:56:26-08:00 adobriyan@mail.ru +2 -4
#   I2C: use time_after instead of comparing jiffies
# 
# drivers/i2c/chips/lm90.c
#   2005/03/02 09:56:26-08:00 adobriyan@mail.ru +2 -3
#   I2C: use time_after instead of comparing jiffies
# 
# drivers/i2c/chips/lm87.c
#   2005/03/02 09:56:26-08:00 adobriyan@mail.ru +2 -3
#   I2C: use time_after instead of comparing jiffies
# 
# drivers/i2c/chips/lm85.c
#   2005/03/02 09:56:26-08:00 adobriyan@mail.ru +3 -2
#   I2C: use time_after instead of comparing jiffies
# 
# drivers/i2c/chips/lm83.c
#   2005/03/02 09:56:26-08:00 adobriyan@mail.ru +2 -3
#   I2C: use time_after instead of comparing jiffies
# 
# drivers/i2c/chips/lm80.c
#   2005/03/02 09:56:26-08:00 adobriyan@mail.ru +2 -3
#   I2C: use time_after instead of comparing jiffies
# 
# drivers/i2c/chips/lm78.c
#   2005/03/02 09:56:26-08:00 adobriyan@mail.ru +3 -2
#   I2C: use time_after instead of comparing jiffies
# 
# drivers/i2c/chips/lm77.c
#   2005/03/02 09:56:26-08:00 adobriyan@mail.ru +3 -2
#   I2C: use time_after instead of comparing jiffies
# 
# drivers/i2c/chips/lm75.c
#   2005/03/02 09:56:26-08:00 adobriyan@mail.ru +3 -2
#   I2C: use time_after instead of comparing jiffies
# 
# drivers/i2c/chips/lm63.c
#   2005/03/02 09:56:26-08:00 adobriyan@mail.ru +2 -3
#   I2C: use time_after instead of comparing jiffies
# 
# drivers/i2c/chips/it87.c
#   2005/03/02 09:56:26-08:00 adobriyan@mail.ru +3 -2
#   I2C: use time_after instead of comparing jiffies
# 
# drivers/i2c/chips/gl518sm.c
#   2005/03/02 09:56:26-08:00 adobriyan@mail.ru +3 -2
#   I2C: use time_after instead of comparing jiffies
# 
# drivers/i2c/chips/fscher.c
#   2005/03/02 09:56:26-08:00 adobriyan@mail.ru +2 -2
#   I2C: use time_after instead of comparing jiffies
# 
# drivers/i2c/chips/eeprom.c
#   2005/03/02 09:56:26-08:00 adobriyan@mail.ru +2 -2
#   I2C: use time_after instead of comparing jiffies
# 
# drivers/i2c/chips/ds1621.c
#   2005/03/02 09:56:26-08:00 adobriyan@mail.ru +3 -2
#   I2C: use time_after instead of comparing jiffies
# 
# drivers/i2c/chips/asb100.c
#   2005/03/02 09:56:26-08:00 adobriyan@mail.ru +2 -2
#   I2C: use time_after instead of comparing jiffies
# 
# drivers/i2c/chips/adm1031.c
#   2005/03/02 09:56:26-08:00 adobriyan@mail.ru +3 -2
#   I2C: use time_after instead of comparing jiffies
# 
# drivers/i2c/chips/adm1026.c
#   2005/03/02 09:56:26-08:00 adobriyan@mail.ru +4 -3
#   I2C: use time_after instead of comparing jiffies
# 
# drivers/i2c/chips/adm1025.c
#   2005/03/02 09:56:26-08:00 adobriyan@mail.ru +2 -3
#   I2C: use time_after instead of comparing jiffies
# 
# drivers/i2c/chips/adm1021.c
#   2005/03/02 09:56:26-08:00 adobriyan@mail.ru +3 -2
#   I2C: use time_after instead of comparing jiffies
# 
# ChangeSet
#   2005/03/02 12:12:54-08:00 bunk@stusta.de 
#   [PATCH] i2c-core.c: make some code static
#   
#   This patch makes some needlessly global code static.
#   
#   Signed-off-by: Adrian Bunk <bunk@stusta.de>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# include/linux/i2c.h
#   2005/03/02 09:57:42-08:00 bunk@stusta.de +0 -2
#   i2c-core.c: make some code static
# 
# drivers/i2c/i2c-core.c
#   2005/03/02 09:57:42-08:00 bunk@stusta.de +39 -40
#   i2c-core.c: make some code static
# 
# drivers/net/arm/ether3.h
#   2005/03/02 20:12:26+00:00 rmk@flint.arm.linux.org.uk +2 -0
#   Add macro to access driver private netdev data.
# 
# drivers/net/arm/ether3.c
#   2005/03/02 20:12:26+00:00 rmk@flint.arm.linux.org.uk +97 -116
#   Use a macro to access driver-specific netdev data.
# 
# drivers/net/arm/ether1.h
#   2005/03/02 20:12:26+00:00 rmk@flint.arm.linux.org.uk +2 -0
#   Add macro to access driver private netdev data.
# 
# drivers/net/arm/ether1.c
#   2005/03/02 20:12:25+00:00 rmk@flint.arm.linux.org.uk +58 -70
#   Use a macro to access driver-specific netdev data.
# 
# ChangeSet
#   2005/03/02 12:10:18-08:00 shawn.starr@rogers.com 
#   [PATCH] I2C: lm80 driver improvement
#   
#   Description: Cleanup some cluttered macros, add error checking for fan divisor value set.
#   
#   Signed-off-by: Sytse Wielinga <s.b.wielinga@student.utwente.nl>
#   Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
#   Signed-off-by: Shawn Starr <shawn.starr@rogers.com>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/i2c/chips/lm80.c
#   2005/03/02 09:58:09-08:00 shawn.starr@rogers.com +12 -5
#   I2C: lm80 driver improvement
# 
# ChangeSet
#   2005/03/02 12:10:01-08:00 mhoffman@lightlink.com 
#   [PATCH] I2C: unnecessary #includes in asb100.c
#   
#   * Jean Delvare <khali@linux-fr.org> [2005-01-25 10:14:49 +0100]:
#   > Any reson why asb100.c (in linux 2.6.11-rc2) includes linux/ioport.h and
#   > asm/io.h? As an i2c-only chip driver, I don't think it needs these.
#   >
#   > As a side note, I also wonder what the inclusions of linux/config.h,
#   > linux/types.h and asm/errno.h are there for.
#   
#   Because they look pretty?  Here's a patch Greg, please apply...
#   
#   Signed-off-by: Mark M. Hoffman <mhoffman@lightlink.com>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/i2c/chips/asb100.c
#   2005/03/02 09:58:27-08:00 mhoffman@lightlink.com +0 -5
#   I2C: unnecessary #includes in asb100.c
# 
# ChangeSet
#   2005/03/02 12:09:45-08:00 khali@linux-fr.org 
#   [PATCH] I2C: Kill unused includes in i2c-sensor-detect.c
#   
#   Looks to me like i2c-sensor-detect.c includes a handful of headers it
#   doesn't need at all. This patch removes them.
#   
#   Signed-off-by: Jean Delvare <khali@linux-fr.org>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/i2c/i2c-sensor-detect.c
#   2005/03/02 09:58:33-08:00 khali@linux-fr.org +0 -7
#   I2C: Kill unused includes in i2c-sensor-detect.c
# 
# ChangeSet
#   2005/03/02 12:09:28-08:00 khali@linux-fr.org 
#   [PATCH] I2C: Enable w83781d and w83627hf temperature channels
#   
#   The chips supported by the w83781d and w83627hf drivers might come up
#   with their temperature channels disabled. Currently, the w83781d driver
#   does so for temp3 but omits temp2, while the w83627hf driver omits both.
#   The following patch fixes that, and prints warning messages when the
#   driver has to enable the channels (normally the BIOS should do it for
#   us). We also skip this initialization step for the AS99127F chips, for
#   which we have no documentation.
#   
#   This should hopefully solve the problem reported here:
#   http://archives.andrew.net.au/lm-sensors/msg29150.html
#   
#   Signed-off-by: Jean Delvare <khali@linux-fr.org>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/i2c/chips/w83781d.c
#   2005/03/02 09:58:47-08:00 khali@linux-fr.org +20 -3
#   I2C: Enable w83781d and w83627hf temperature channels
# 
# drivers/i2c/chips/w83627hf.c
#   2005/03/02 09:58:47-08:00 khali@linux-fr.org +21 -0
#   I2C: Enable w83781d and w83627hf temperature channels
# 
# ChangeSet
#   2005/03/02 12:04:28-08:00 aurelien@aurel32.net 
#   [PATCH] I2C: lm78 driver improvement
#   
#   The following patch against kernel 2.6.11-rc2-mm1 improves the lm78
#   driver. I used it as a model to port the sis5595 driver to the 2.6
#   kernel, and I then applied the changes suggested by Jean Delvare on
#   the sis5595 driver to this one.
#   
#   
#   Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/i2c/chips/lm78.c
#   2005/03/02 09:58:53-08:00 aurelien@aurel32.net +24 -29
#   I2C: lm78 driver improvement
# 
# ChangeSet
#   2005/03/02 12:04:12-08:00 mhoffman@lightlink.com 
#   [PATCH] I2C: i2c-dev namespace cleanup
#   
#   This patch is namespace cleanup for the i2c-dev module.  Please apply.
#   
#   Signed-off-by Mark M. Hoffman <mhoffman@lightlink.com>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/i2c/i2c-dev.c
#   2005/03/02 09:59:08-08:00 mhoffman@lightlink.com +4 -4
#   I2C: i2c-dev namespace cleanup
# 
# ChangeSet
#   2005/03/02 15:03:29-05:00 davej@redhat.com 
#   [AGPGART] Fix typo.
#   
#   From: Joern Heissler
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# include/linux/agp_backend.h
#   2005/03/02 15:03:19-05:00 davej@redhat.com +1 -1
#   [AGPGART] Fix typo.
#   
#   From: Joern Heissler
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# ChangeSet
#   2005/03/02 11:59:41-08:00 stefan@desire.ch 
#   [PATCH] I2C: fix for fscpos voltage values
#   
#   Multiplied the voltage multipliers by 10 in order to comply with the sysfs
#   guidelines.
#   
#   Signed-off-by: Stefan Ott <stefan@desire.ch>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/i2c/chips/fscpos.c
#   2005/03/02 10:00:05-08:00 stefan@desire.ch +3 -3
#   I2C: fix for fscpos voltage values
# 
# ChangeSet
#   2005/03/02 11:58:47-08:00 greg@kroah.com 
#   [PATCH] I2C: just delete the id field, let's not delay it any longer
#   
#   Becides, sparse keeps complaining when it sees this attribute within a structure...
#   
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# include/linux/i2c.h
#   2005/03/02 10:00:35-08:00 greg@kroah.com +0 -1
#   I2C: just delete the id field, let's not delay it any longer
# 
# ChangeSet
#   2005/03/02 11:58:29-08:00 khali@linux-fr.org 
#   [PATCH] I2C: Kill i2c_client.id (5/5)
#   
#   > (5/5) Documentation update.
#   
#   Finally, updates are required to the i2c/writing-client and
#   i2c/porting-client documents. Remove any reference to i2c_client id and
#   invite porters to discard that struct member.
#   
#   Signed-off-by: Jean Delvare <khali@linux-fr.org>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# Documentation/i2c/writing-clients
#   2005/03/02 10:00:42-08:00 khali@linux-fr.org +0 -4
#   I2C: Kill i2c_client.id (5/5)
# 
# Documentation/i2c/porting-clients
#   2005/03/02 10:00:42-08:00 khali@linux-fr.org +3 -3
#   I2C: Kill i2c_client.id (5/5)
# 
# ChangeSet
#   2005/03/02 11:52:48-08:00 khali@linux-fr.org 
#   [PATCH] I2C: Kill i2c_client.id (4/5)
#   
#   > (4/5) Deprecate i2c_client.id.
#   
#   Now that i2c_client.id has no more users in the kernel (none that I
#   could find at least) we could remove that struct member. I however think
#   that it's better to only deprecate it at the moment, in case I missed
#   users or any of the other patches are delayed for some reason. We could
#   then delete the id member definitely in a month or so.
#   
#   Signed-off-by: Jean Delvare <khali@linux-fr.org>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# include/linux/i2c.h
#   2005/03/02 10:00:49-08:00 khali@linux-fr.org +1 -1
#   I2C: Kill i2c_client.id (4/5)
# 
# ChangeSet
#   2005/03/02 11:52:31-08:00 khali@linux-fr.org 
#   [PATCH] I2C: Kill i2c_client.id (3/5)
#   
#   (3/5) Stop using i2c_client.id in misc drivers.
#   
#   Affected drivers:
#   * acorn/char/pcf8583
#   * acorn/char/i2c
#   * i2c/i2c-dev
#   * macintosh/therm_windtunnel
#   * sound/oss/dmasound/dac3550a
#   * sound/ppc/keywest
#   
#   The Acorn pcf8583 driver would give the i2c_client id the same value as
#   the i2c_driver id, and later test that client id (in i2c). I changed it
#   to test the client's driver id instead. The result is the same and the
#   client id is then useless and can be removed.
#   
#   All other drivers here would allocate the client id to some value and
#   then never use it. They are unaffected by the change.
#   
#   Signed-off-by: Jean Delvare <khali@linux-fr.org>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# sound/ppc/keywest.c
#   2005/03/02 10:00:56-08:00 khali@linux-fr.org +0 -2
#   I2C: Kill i2c_client.id (3/5)
# 
# sound/oss/dmasound/dac3550a.c
#   2005/03/02 10:00:56-08:00 khali@linux-fr.org +0 -4
#   I2C: Kill i2c_client.id (3/5)
# 
# drivers/macintosh/therm_windtunnel.c
#   2005/03/02 10:00:56-08:00 khali@linux-fr.org +0 -4
#   I2C: Kill i2c_client.id (3/5)
# 
# drivers/i2c/i2c-dev.c
#   2005/03/02 10:00:56-08:00 khali@linux-fr.org +0 -1
#   I2C: Kill i2c_client.id (3/5)
# 
# drivers/acorn/char/pcf8583.c
#   2005/03/02 10:00:56-08:00 khali@linux-fr.org +0 -1
#   I2C: Kill i2c_client.id (3/5)
# 
# drivers/acorn/char/i2c.c
#   2005/03/02 10:00:56-08:00 khali@linux-fr.org +1 -1
#   I2C: Kill i2c_client.id (3/5)
# 
# ChangeSet
#   2005/03/02 11:52:15-08:00 khali@linux-fr.org 
#   [PATCH] I2C: Kill i2c_client.id (2/5)
#   
#   (2/5) Stop using i2c_client.id in media/video drivers.
#   
#   Affected drivers:
#   * adv7170
#   * adv7175
#   * bt819
#   * bt856
#   * bttv
#   * cx88
#   * ovcamchip
#   * saa5246a
#   * saa5249
#   * saa7110
#   * saa7111
#   * saa7114
#   * saa7134
#   * saa7185
#   * tda7432
#   * tda9840
#   * tda9875
#   * tea6415c
#   * tea6420
#   * tuner-3036
#   * vpx3220
#   
#   Most drivers here would include the id as part of their i2c client name
#   (e.g. adv7170[0]). This looks more like an habit than something really
#   needed, so I replaced the various printf by strlcpy, which should be
#   slightly faster. As said earlier, clients can be differenciated thanks
#   to their bus id and address if needed, so I don't think that including
#   this information in the client name is wise anyway.
#   
#   Other drivers would either set the id to -1 or to a unique value but
#   then never use it. These drivers are unaffected by the changes.
#   
#   Signed-off-by: Jean Delvare <khali@linux-fr.org>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/media/video/vpx3220.c
#   2005/03/02 10:01:03-08:00 khali@linux-fr.org +8 -11
#   I2C: Kill i2c_client.id (2/5)
# 
# drivers/media/video/tuner-3036.c
#   2005/03/02 10:01:03-08:00 khali@linux-fr.org +0 -1
#   I2C: Kill i2c_client.id (2/5)
# 
# drivers/media/video/tea6420.c
#   2005/03/02 10:01:03-08:00 khali@linux-fr.org +0 -4
#   I2C: Kill i2c_client.id (2/5)
# 
# drivers/media/video/tea6415c.c
#   2005/03/02 10:01:03-08:00 khali@linux-fr.org +0 -4
#   I2C: Kill i2c_client.id (2/5)
# 
# drivers/media/video/tda9875.c
#   2005/03/02 10:01:03-08:00 khali@linux-fr.org +0 -1
#   I2C: Kill i2c_client.id (2/5)
# 
# drivers/media/video/tda9840.c
#   2005/03/02 10:01:03-08:00 khali@linux-fr.org +0 -4
#   I2C: Kill i2c_client.id (2/5)
# 
# drivers/media/video/tda7432.c
#   2005/03/02 10:01:03-08:00 khali@linux-fr.org +0 -1
#   I2C: Kill i2c_client.id (2/5)
# 
# drivers/media/video/saa7185.c
#   2005/03/02 10:01:03-08:00 khali@linux-fr.org +1 -4
#   I2C: Kill i2c_client.id (2/5)
# 
# drivers/media/video/saa7134/saa7134-i2c.c
#   2005/03/02 10:01:03-08:00 khali@linux-fr.org +0 -1
#   I2C: Kill i2c_client.id (2/5)
# 
# drivers/media/video/saa7114.c
#   2005/03/02 10:01:03-08:00 khali@linux-fr.org +1 -4
#   I2C: Kill i2c_client.id (2/5)
# 
# drivers/media/video/saa7111.c
#   2005/03/02 10:01:03-08:00 khali@linux-fr.org +1 -4
#   I2C: Kill i2c_client.id (2/5)
# 
# drivers/media/video/saa7110.c
#   2005/03/02 10:01:03-08:00 khali@linux-fr.org +1 -4
#   I2C: Kill i2c_client.id (2/5)
# 
# drivers/media/video/saa5249.c
#   2005/03/02 10:01:03-08:00 khali@linux-fr.org +0 -1
#   I2C: Kill i2c_client.id (2/5)
# 
# drivers/media/video/saa5246a.c
#   2005/03/02 10:01:03-08:00 khali@linux-fr.org +0 -1
#   I2C: Kill i2c_client.id (2/5)
# 
# drivers/media/video/ovcamchip/ovcamchip_core.c
#   2005/03/02 10:01:03-08:00 khali@linux-fr.org +0 -1
#   I2C: Kill i2c_client.id (2/5)
# 
# drivers/media/video/cx88/cx88-i2c.c
#   2005/03/02 10:01:03-08:00 khali@linux-fr.org +0 -1
#   I2C: Kill i2c_client.id (2/5)
# 
# drivers/media/video/bttv-i2c.c
#   2005/03/02 10:01:03-08:00 khali@linux-fr.org +0 -1
#   I2C: Kill i2c_client.id (2/5)
# 
# drivers/media/video/bt856.c
#   2005/03/02 10:01:03-08:00 khali@linux-fr.org +1 -4
#   I2C: Kill i2c_client.id (2/5)
# 
# drivers/media/video/bt819.c
#   2005/03/02 10:01:03-08:00 khali@linux-fr.org +3 -8
#   I2C: Kill i2c_client.id (2/5)
# 
# drivers/media/video/adv7175.c
#   2005/03/02 10:01:03-08:00 khali@linux-fr.org +1 -4
#   I2C: Kill i2c_client.id (2/5)
# 
# drivers/media/video/adv7170.c
#   2005/03/02 10:01:03-08:00 khali@linux-fr.org +1 -4
#   I2C: Kill i2c_client.id (2/5)
# 
# ChangeSet
#   2005/03/02 11:51:51-08:00 khali@linux-fr.org 
#   [PATCH] I2C: Kill i2c_client.id (1/5)
#   
#   (1/5) Stop using i2c_client.id in i2c/chips drivers (mostly hardware
#         monitoring drivers).
#   
#   Drivers affected:
#   * adm1021
#   * adm1025
#   * adm1026
#   * adm1031
#   * ds1621
#   * fscher
#   * gl518sm
#   * isp1301_omap
#   * lm75
#   * lm77
#   * lm80
#   * lm83
#   * lm85
#   * lm87
#   * lm90
#   * max1619
#   * pcf8574
#   * pcf8591
#   * rtc8564
#   * smsc47m1
#   * w83l785ts
#   
#   The vast majority of these drivers simply defined the i2c_client id
#   struct member but never used it, so they are not affected at all by the
#   change. Exceptions are:
#   
#   * lm85 and rtc8564, which would at least display the id in a debug
#   message when assigning it. Not really useful though, as the id was then
#   never used.
#   
#   * adm1026, which used the assigned id in all driver messages. However,
#   since dev_* calls will append the bus number and client address to these
#   messages, the id information is redundant and can go away. Also, the
#   driver would allow some GPIO reprogramming on the first client only
#   (id=0) and removing the id doesn't allow that anymore. I would restore a
#   similar functionality if needed, but the ADM1026 chip is found on very
#   few motherboards and none of these has more than one ADM1026 chip AFAIK,
#   so it doesn't seem to be worth the effort.
#   
#   Signed-off-by: Jean Delvare <khali@linux-fr.org>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/i2c/chips/w83l785ts.c
#   2005/03/02 10:01:11-08:00 khali@linux-fr.org +0 -7
#   I2C: Kill i2c_client.id (1/5)
# 
# drivers/i2c/chips/smsc47m1.c
#   2005/03/02 10:01:11-08:00 khali@linux-fr.org +0 -5
#   I2C: Kill i2c_client.id (1/5)
# 
# drivers/i2c/chips/rtc8564.c
#   2005/03/02 10:01:11-08:00 khali@linux-fr.org +0 -2
#   I2C: Kill i2c_client.id (1/5)
# 
# drivers/i2c/chips/pcf8591.c
#   2005/03/02 10:01:11-08:00 khali@linux-fr.org +0 -4
#   I2C: Kill i2c_client.id (1/5)
# 
# drivers/i2c/chips/pcf8574.c
#   2005/03/02 10:01:11-08:00 khali@linux-fr.org +0 -4
#   I2C: Kill i2c_client.id (1/5)
# 
# drivers/i2c/chips/max1619.c
#   2005/03/02 10:01:11-08:00 khali@linux-fr.org +0 -7
#   I2C: Kill i2c_client.id (1/5)
# 
# drivers/i2c/chips/lm90.c
#   2005/03/02 10:01:11-08:00 khali@linux-fr.org +0 -7
#   I2C: Kill i2c_client.id (1/5)
# 
# drivers/i2c/chips/lm87.c
#   2005/03/02 10:01:11-08:00 khali@linux-fr.org +0 -7
#   I2C: Kill i2c_client.id (1/5)
# 
# drivers/i2c/chips/lm85.c
#   2005/03/02 10:01:11-08:00 khali@linux-fr.org +0 -9
#   I2C: Kill i2c_client.id (1/5)
# 
# drivers/i2c/chips/lm83.c
#   2005/03/02 10:01:11-08:00 khali@linux-fr.org +0 -7
#   I2C: Kill i2c_client.id (1/5)
# 
# drivers/i2c/chips/lm80.c
#   2005/03/02 10:01:11-08:00 khali@linux-fr.org +0 -8
#   I2C: Kill i2c_client.id (1/5)
# 
# drivers/i2c/chips/lm77.c
#   2005/03/02 10:01:11-08:00 khali@linux-fr.org +0 -4
#   I2C: Kill i2c_client.id (1/5)
# 
# drivers/i2c/chips/lm75.c
#   2005/03/02 10:01:11-08:00 khali@linux-fr.org +0 -4
#   I2C: Kill i2c_client.id (1/5)
# 
# drivers/i2c/chips/isp1301_omap.c
#   2005/03/02 10:01:11-08:00 khali@linux-fr.org +0 -1
#   I2C: Kill i2c_client.id (1/5)
# 
# drivers/i2c/chips/gl518sm.c
#   2005/03/02 10:01:11-08:00 khali@linux-fr.org +0 -7
#   I2C: Kill i2c_client.id (1/5)
# 
# drivers/i2c/chips/fscher.c
#   2005/03/02 10:01:11-08:00 khali@linux-fr.org +0 -7
#   I2C: Kill i2c_client.id (1/5)
# 
# drivers/i2c/chips/ds1621.c
#   2005/03/02 10:01:11-08:00 khali@linux-fr.org +0 -4
#   I2C: Kill i2c_client.id (1/5)
# 
# drivers/i2c/chips/adm1031.c
#   2005/03/02 10:01:11-08:00 khali@linux-fr.org +0 -4
#   I2C: Kill i2c_client.id (1/5)
# 
# drivers/i2c/chips/adm1026.c
#   2005/03/02 10:01:11-08:00 khali@linux-fr.org +32 -48
#   I2C: Kill i2c_client.id (1/5)
# 
# drivers/i2c/chips/adm1025.c
#   2005/03/02 10:01:11-08:00 khali@linux-fr.org +0 -7
#   I2C: Kill i2c_client.id (1/5)
# 
# drivers/i2c/chips/adm1021.c
#   2005/03/02 10:01:11-08:00 khali@linux-fr.org +0 -4
#   I2C: Kill i2c_client.id (1/5)
# 
# ChangeSet
#   2005/03/02 11:51:21-08:00 greg@kroah.com 
#   [PATCH] I2C: Fix up some build warnings in the fscpos driver.
#   
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/i2c/chips/fscpos.c
#   2005/03/02 10:01:19-08:00 greg@kroah.com +1 -3
#   I2C: Fix up some build warnings in the fscpos driver.
# 
# ChangeSet
#   2005/03/02 11:50:10-08:00 khali@linux-fr.org 
#   [PATCH] I2C: Allow it87 pwm reconfiguration
#   
#   Quoting myself:
#   
#   > As soon as you will have confirmed that everything worked as expected,
#   > Jonas and I will provide a patch adding a pwm polarity reconfiguration
#   > module parameter for you to test. This should give you access to the
#   > PWM features of your it87 chip again, but in a safe way for a change
#   > ;)
#   
#   Here comes this patch. The new "fix_pwm_polarity" module parameter
#   allows one to force the it87 chip reconfiguration. This is only
#   supported in the case the original PWM configuration is suspected to be
#   bogus, and only if we think that reconfiguring the chip is safe.
#   
#   I wish to thank Rudolf Marek and Jonas Munsin again for their testing
#   and review of my code.
#   
#   Signed-off-by: Jean Delvare <khali@linux-fr.org>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/i2c/chips/it87.c
#   2005/03/02 10:01:25-08:00 khali@linux-fr.org +59 -12
#   I2C: Allow it87 pwm reconfiguration
# 
# ChangeSet
#   2005/03/02 19:16:04+00:00 rmk@flint.arm.linux.org.uk 
#   [ARM] Unuse scsi host->base
#   
#   This eliminates the final usage of deprecated elements in scsi_host by
#   Acorn SCSI drivers.
#   
#   Signed-off-by: Russell King <rmk@arm.linux.org.uk>
# 
# drivers/scsi/arm/powertec.c
#   2005/03/02 19:11:57+00:00 rmk@flint.arm.linux.org.uk +0 -2
#   Remove host->base.
# 
# drivers/scsi/arm/fas216.h
#   2005/03/02 19:11:57+00:00 rmk@flint.arm.linux.org.uk +1 -2
#   Mark info->scsi.io_base with __iomem.
#   Remove info->scsi.io_port.
# 
# drivers/scsi/arm/fas216.c
#   2005/03/02 19:11:57+00:00 rmk@flint.arm.linux.org.uk +6 -12
#   Remove inb / outb.
#   Use info->scsi.io_base instead of info->host->io_port.
# 
# drivers/scsi/arm/eesox.c
#   2005/03/02 19:11:56+00:00 rmk@flint.arm.linux.org.uk +0 -2
#   Remove host->base.
# 
# drivers/scsi/arm/cumana_2.c
#   2005/03/02 19:11:56+00:00 rmk@flint.arm.linux.org.uk +0 -2
#   Remove host->base.
# 
# drivers/scsi/arm/arxescsi.c
#   2005/03/02 19:11:56+00:00 rmk@flint.arm.linux.org.uk +0 -2
#   Remove host->base.
# 
# ChangeSet
#   2005/03/02 11:04:17-08:00 stefan@desire.ch 
#   [PATCH] I2C: add fscpos chip driver
#   
#   This patch against 2.6.11-rc1 contains a driver for fscpos sensors.
#   
#   Signed-off-by: Stefan Ott <stefan@desire.ch>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/i2c/chips/Makefile
#   2005/03/02 10:01:31-08:00 stefan@desire.ch +1 -0
#   I2C: add fscpos chip driver
# 
# drivers/i2c/chips/Kconfig
#   2005/03/02 10:01:31-08:00 stefan@desire.ch +11 -0
#   I2C: add fscpos chip driver
# 
# drivers/i2c/chips/fscpos.c
#   2005/03/02 10:01:31-08:00 stefan@desire.ch +633 -0
#   I2C: add fscpos chip driver
# 
# drivers/i2c/chips/fscpos.c
#   2005/03/02 10:01:31-08:00 stefan@desire.ch +0 -0
#   BitKeeper file /home/greg/linux/BK/do/i2c-2.6/drivers/i2c/chips/fscpos.c
# 
# ChangeSet
#   2005/03/02 18:50:36+00:00 rmk@flint.arm.linux.org.uk 
#   [ARM] SCSI: Move host->dma_channel to info->scsi.dma
#   
#   Signed-off-by: Russell King <rmk@arm.linux.org.uk>
# 
# drivers/scsi/arm/powertec.c
#   2005/03/02 18:45:41+00:00 rmk@flint.arm.linux.org.uk +14 -13
#   Move host->dma_channel to info->scsi.dma
# 
# drivers/scsi/arm/fas216.h
#   2005/03/02 18:45:41+00:00 rmk@flint.arm.linux.org.uk +1 -0
#   Add scsi dma channel
# 
# drivers/scsi/arm/fas216.c
#   2005/03/02 18:45:40+00:00 rmk@flint.arm.linux.org.uk +1 -1
#   Move host->dma_channel to info->scsi.dma
# 
# drivers/scsi/arm/eesox.c
#   2005/03/02 18:45:39+00:00 rmk@flint.arm.linux.org.uk +14 -13
#   Move host->dma_channel to info->scsi.dma
# 
# drivers/scsi/arm/cumana_2.c
#   2005/03/02 18:45:39+00:00 rmk@flint.arm.linux.org.uk +13 -13
#   Move host->dma_channel to info->scsi.dma
# 
# drivers/scsi/arm/arxescsi.c
#   2005/03/02 18:45:39+00:00 rmk@flint.arm.linux.org.uk +1 -1
#   Move host->dma_channel to info->scsi.dma
# 
# ChangeSet
#   2005/03/02 17:28:15+00:00 rmk@flint.arm.linux.org.uk 
#   [ARM] Don't use host->irq
#   
#   Signed-off-by: Russell King <rmk@arm.linux.org.uk>
# 
# drivers/scsi/arm/powertec.c
#   2005/03/02 17:22:48+00:00 rmk@flint.arm.linux.org.uk +5 -6
#   Don't use host->irq.
# 
# drivers/scsi/arm/fas216.c
#   2005/03/02 17:22:48+00:00 rmk@flint.arm.linux.org.uk +1 -1
#   Don't use host->irq.
# 
# drivers/scsi/arm/eesox.c
#   2005/03/02 17:22:48+00:00 rmk@flint.arm.linux.org.uk +5 -6
#   Don't use host->irq.
# 
# drivers/scsi/arm/cumana_2.c
#   2005/03/02 17:22:47+00:00 rmk@flint.arm.linux.org.uk +5 -6
#   Don't use host->irq.
# 
# drivers/scsi/arm/arxescsi.c
#   2005/03/02 17:22:47+00:00 rmk@flint.arm.linux.org.uk +1 -2
#   Don't use host->irq.
# 
# ChangeSet
#   2005/03/02 16:56:54+00:00 rmk@flint.arm.linux.org.uk 
#   [ARM] Acorn SCSI: Ensure iomem pointers are marked as such.
#   
#   Signed-off-by: Russell King <rmk@arm.linux.org.uk>
# 
# drivers/scsi/arm/powertec.c
#   2005/03/02 16:50:55+00:00 rmk@flint.arm.linux.org.uk +18 -16
#   Ensure iomem pointers are marked as such.
# 
# drivers/scsi/arm/eesox.c
#   2005/03/02 16:50:54+00:00 rmk@flint.arm.linux.org.uk +22 -22
#   Ensure iomem pointers are marked as such.
# 
# drivers/scsi/arm/cumana_2.c
#   2005/03/02 16:50:54+00:00 rmk@flint.arm.linux.org.uk +28 -30
#   Ensure iomem pointers are marked as such.
# 
# drivers/scsi/arm/arxescsi.c
#   2005/03/02 16:50:54+00:00 rmk@flint.arm.linux.org.uk +7 -4
#   Ensure iomem pointers are marked as such.
# 
# ChangeSet
#   2005/03/02 16:07:18+00:00 rmk@flint.arm.linux.org.uk 
#   [ARM] Fix sparse warnings in ARM IDE drivers.
#   
#   Signed-off-by: Russell King <rmk@arm.linux.org.uk>
# 
# drivers/ide/arm/rapide.c
#   2005/03/02 16:02:29+00:00 rmk@flint.arm.linux.org.uk +1 -1
#   "ctrl" is an iomem pointer.  Mark it as such.
# 
# drivers/ide/arm/icside.c
#   2005/03/02 16:02:28+00:00 rmk@flint.arm.linux.org.uk +1 -1
#   "idmem" is an iomem pointer.  Mark it as such.
# 
# ChangeSet
#   2005/03/02 15:32:02+00:00 rmk@flint.arm.linux.org.uk 
#   [ARM] Fix set_fiq_regs()/get_fiq_regs()
#   
#   Make these "naked" functions.  This allows us to eliminate the
#   clobbers which later gcc versions complain about.
#   
#   Signed-off-by: Russell King <rmk@arm.linux.org.uk>
# 
# arch/arm/kernel/fiq.c
#   2005/03/02 15:26:19+00:00 rmk@flint.arm.linux.org.uk +20 -27
#   Convert [sg]et_fiq_regs() to be "naked" functions.
# 
# ChangeSet
#   2005/03/02 15:09:38+00:00 rmk@flint.arm.linux.org.uk 
#   [ARM] Update syscall table
#   
#   Add demultiplexed socket and ipc syscalls.  Add key syscalls.
#   
#   Leave the new numbers for the demultiplexed socket and ipc syscalls
#   commented out in asm-arm/unistd.h for the time being.
#   
#   Signed-off-by: Russell King <rmk@arm.linux.org.uk>
# 
# include/asm-arm/unistd.h
#   2005/03/02 15:05:14+00:00 rmk@flint.arm.linux.org.uk +40 -2
#   Add syscall numbers.  Comment out unmuxed socket and ipc calls for
#   the time being.
# 
# arch/arm/kernel/sys_arm.c
#   2005/03/02 15:05:14+00:00 rmk@flint.arm.linux.org.uk +12 -0
#   Add sys_shmat, required for demultiplexed IPC.
# 
# arch/arm/kernel/calls.S
#   2005/03/02 15:05:14+00:00 rmk@flint.arm.linux.org.uk +33 -2
#   Update syscall table - demultiplexed socket calls, IPC calls and
#   key syscalls.
# 
# ChangeSet
#   2005/03/02 15:03:02+01:00 perex@suse.cz 
#   [ALSA] emu10k1 - fix the initial value for Captured FX8010 Outputs
#   
#   EMU10K1/EMU10K2 driver
#   - rename 'EFX voices mask' to 'Captured FX8010 Outputs'
#   - fix the initial value
#   
#   Signed-off-by: Lee Revell <rlrevell@joe-job.com>
#   Signed-off-by: Jaroslav Kysela <perex@suse.cz>
# 
# sound/pci/emu10k1/emupcm.c
#   2005/03/02 01:40:37+01:00 perex@suse.cz +2 -2
#   [ALSA] emu10k1 - fix the initial value for Captured FX8010 Outputs
#   
#   D:2005/03/02 08:40:37
#   C:EMU10K1/EMU10K2 driver
#   F:pci/emu10k1/emupcm.c:1.40->1.41 
#   L:- rename 'EFX voices mask' to 'Captured FX8010 Outputs'
#   L:- fix the initial value
#   Signed-off-by: Lee Revell <rlrevell@joe-job.com>
#   Signed-off-by: Jaroslav Kysela <perex@suse.cz>
# 
# ChangeSet
#   2005/03/02 15:02:09+01:00 perex@suse.cz 
#   [ALSA] Control API - fix the wrong allocation for userspace controls
#   
#   Control Midlevel
#   
#   
#   Signed-off-by: Jaroslav Kysela <perex@suse.cz>
# 
# sound/core/control.c
#   2005/03/01 02:12:03+01:00 perex@suse.cz +1 -1
#   [ALSA] Control API - fix the wrong allocation for userspace controls
#   
#   D:2005/03/01 09:12:03
#   C:Control Midlevel
#   F:core/control.c:1.58->1.59 
#   L:
#   Signed-off-by: Jaroslav Kysela <perex@suse.cz>
# 
# ChangeSet
#   2005/03/02 15:01:23+01:00 perex@suse.cz 
#   [ALSA] Fix the Audigy SPDIF sample rate register definitions
#   
#   EMU10K1/EMU10K2 driver
#   
#   
#   Signed-off-by: Lee Revell <rlrevell@joe-job.com>
#   Signed-off-by: Jaroslav Kysela <perex@suse.cz>
# 
# include/sound/emu10k1.h
#   2005/03/01 01:17:25+01:00 perex@suse.cz +2 -2
#   [ALSA] Fix the Audigy SPDIF sample rate register definitions
#   
#   D:2005/03/01 08:17:25
#   C:EMU10K1/EMU10K2 driver
#   F:include/emu10k1.h:1.57->1.58 
#   L:
#   Signed-off-by: Lee Revell <rlrevell@joe-job.com>
#   Signed-off-by: Jaroslav Kysela <perex@suse.cz>
# 
# ChangeSet
#   2005/03/02 15:00:33+01:00 perex@suse.cz 
#   [ALSA] remove _snd_rawmidi_runtime.trigger
#   
#   RawMidi Midlevel
#   Remove the trigger field from _snd_rawmidi_runtime because
#   it is never ever read.  (This may be why nobody noticed that
#   snd_rawmidi_transmit_empty sets it to the wrong value.)
#   
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# sound/core/rawmidi.c
#   2005/02/28 01:54:40+01:00 perex@suse.cz +0 -11
#   [ALSA] remove _snd_rawmidi_runtime.trigger
#   
#   D:2005/02/28 08:54:40
#   C:RawMidi Midlevel
#   F:core/rawmidi.c:1.57->1.58 
#   F:include/rawmidi.h:1.12->1.13 
#   L:Remove the trigger field from _snd_rawmidi_runtime because
#   L:it is never ever read.  (This may be why nobody noticed that
#   L:snd_rawmidi_transmit_empty sets it to the wrong value.)
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# include/sound/rawmidi.h
#   2005/02/28 01:54:40+01:00 perex@suse.cz +1 -2
#   [ALSA] remove _snd_rawmidi_runtime.trigger
#   
#   D:2005/02/28 08:54:40
#   C:RawMidi Midlevel
#   F:core/rawmidi.c:1.57->1.58 
#   F:include/rawmidi.h:1.12->1.13 
#   L:Remove the trigger field from _snd_rawmidi_runtime because
#   L:it is never ever read.  (This may be why nobody noticed that
#   L:snd_rawmidi_transmit_empty sets it to the wrong value.)
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# ChangeSet
#   2005/03/02 14:59:45+01:00 perex@suse.cz 
#   [ALSA] remove unsafe usage of urb->status
#   
#   USB generic driver
#   Remove unprotected accesses to urb->status and
#   substream->runtimer->trigger.
#   
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# sound/usb/usbmidi.c
#   2005/02/28 01:50:18+01:00 perex@suse.cz +15 -4
#   [ALSA] remove unsafe usage of urb->status
#   
#   D:2005/02/28 08:50:18
#   C:USB generic driver
#   F:usb/usbmidi.c:1.43->1.44 
#   L:Remove unprotected accesses to urb->status and
#   L:substream->runtimer->trigger.
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# ChangeSet
#   2005/03/02 14:58:55+01:00 perex@suse.cz 
#   [ALSA] add port names for serial MIDI ports
#   
#   Generic drivers
#   Give each of the MIDI ports created by snd-serial-u16550
#   a unique name.
#   
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# sound/drivers/serial-u16550.c
#   2005/02/28 01:46:30+01:00 perex@suse.cz +14 -2
#   [ALSA] add port names for serial MIDI ports
#   
#   D:2005/02/28 08:46:30
#   C:Generic drivers
#   F:drivers/serial-u16550.c:1.31->1.32 
#   L:Give each of the MIDI ports created by snd-serial-u16550
#   L:a unique name.
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# ChangeSet
#   2005/03/02 14:58:06+01:00 perex@suse.cz 
#   [ALSA] fix counting of MIDI input overruns
#   
#   RawMidi Midlevel
#   Do not throw away the old value of the overrun counter when
#   more than one byte is received.
#   
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# sound/core/rawmidi.c
#   2005/02/28 01:44:40+01:00 perex@suse.cz +1 -1
#   [ALSA] fix counting of MIDI input overruns
#   
#   D:2005/02/28 08:44:40
#   C:RawMidi Midlevel
#   F:core/rawmidi.c:1.56->1.57 
#   L:Do not throw away the old value of the overrun counter when
#   L:more than one byte is received.
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# ChangeSet
#   2005/03/02 14:57:19+01:00 perex@suse.cz 
#   [ALSA] fix buffer wrap in snd_rawmidi_transmit_peek
#   
#   RawMidi Midlevel
#   Fix the behaviour and return value of snd_rawmidi_transmit_peek
#   when the buffer wraps around.
#   
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# sound/core/rawmidi.c
#   2005/02/28 01:42:25+01:00 perex@suse.cz +5 -1
#   [ALSA] fix buffer wrap in snd_rawmidi_transmit_peek
#   
#   D:2005/02/28 08:42:25
#   C:RawMidi Midlevel
#   F:core/rawmidi.c:1.55->1.56 
#   L:Fix the behaviour and return value of snd_rawmidi_transmit_peek
#   L:when the buffer wraps around.
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# ChangeSet
#   2005/03/02 14:56:32+01:00 perex@suse.cz 
#   [ALSA] add more USB MIDI quirks
#   
#   USB generic driver
#   Add support for Roland RS-70, SP-606, BOSS DR-880
#   
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# sound/usb/usbquirks.h
#   2005/02/25 00:56:05+01:00 perex@suse.cz +39 -0
#   [ALSA] add more USB MIDI quirks
#   
#   D:2005/02/25 07:56:05
#   C:USB generic driver
#   F:usb/usbquirks.h:1.43->1.44 
#   L:Add support for Roland RS-70, SP-606, BOSS DR-880
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# ChangeSet
#   2005/03/02 14:55:41+01:00 perex@suse.cz 
#   [ALSA] AC97 quirk for Dell Precision 650
#   
#   Intel8x0 driver
#   Added the ac97 quirk entry for Dell Precision 650.
#   
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/intel8x0.c
#   2005/02/24 04:55:36+01:00 perex@suse.cz +6 -0
#   [ALSA] AC97 quirk for Dell Precision 650
#   
#   D:2005/02/24 11:55:36
#   C:Intel8x0 driver
#   F:pci/intel8x0.c:1.195->1.196 
#   L:Added the ac97 quirk entry for Dell Precision 650.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2005/03/02 14:54:56+01:00 perex@suse.cz 
#   [ALSA] Add mixer controls to intel8x0m
#   
#   Intel8x0-modem driver
#   This patch adds a mixer switch to the intel8x0m driver, so that the
#   hook state can be controlled from userspace, instead of bringing the
#   line off hook on capture start. Please someone test, and merge into
#   cvs. Comments are welcome.
#   
#   Signed-off-by: Jaime A. Lopez Sollano <jsollano@gmail.com>
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/intel8x0m.c
#   2005/02/24 03:12:31+01:00 perex@suse.cz +59 -7
#   [ALSA] Add mixer controls to intel8x0m
#   
#   D:2005/02/24 10:12:31
#   C:Intel8x0-modem driver
#   F:pci/intel8x0m.c:1.28->1.29 
#   L:This patch adds a mixer switch to the intel8x0m driver, so that the
#   L:hook state can be controlled from userspace, instead of bringing the
#   L:line off hook on capture start. Please someone test, and merge into
#   L:cvs. Comments are welcome.
#   Signed-off-by: Jaime A. Lopez Sollano <jsollano@gmail.com>
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2005/03/02 14:54:11+01:00 perex@suse.cz 
#   [ALSA] Fix CM9761 again
#   
#   AC97 Codec
#   Fixed the silent output playback problem on CM9761.
#   The SPDIF_CTRL register (0x6c) bit 17 was the culprit.
#   
#   The master volume is back again since it seems to have some
#   influence on the looped input sounds.
#   
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/ac97/ac97_patch.c
#   2005/02/23 07:04:02+01:00 perex@suse.cz +10 -6
#   [ALSA] Fix CM9761 again
#   
#   D:2005/02/23 14:04:02
#   C:AC97 Codec
#   F:pci/ac97/ac97_patch.c:1.74->1.75 
#   L:Fixed the silent output playback problem on CM9761.
#   L:The SPDIF_CTRL register (0x6c) bit 17 was the culprit.
#   L:
#   L:The master volume is back again since it seems to have some
#   L:influence on the looped input sounds.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2005/03/02 14:53:21+01:00 perex@suse.cz 
#   [ALSA] do codec init more like windows does
#   
#   au88x0 driver
#   The following patch makes the codec init code act more like the windows
#   code.
#   
#   Signed-off-by: Jeff Muizelaar <jeff@infidigm.net>
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/au88x0/au88x0_core.c
#   2005/02/23 04:00:31+01:00 perex@suse.cz +3 -2
#   [ALSA] do codec init more like windows does
#   
#   D:2005/02/23 11:00:31
#   C:au88x0 driver
#   F:pci/au88x0/au88x0_core.c:1.10->1.11 
#   L:The following patch makes the codec init code act more like the windows
#   L:code.
#   Signed-off-by: Jeff Muizelaar <jeff@infidigm.net>
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2005/03/02 14:52:35+01:00 perex@suse.cz 
#   [ALSA] add Roland FANTOM-X support
#   
#   USB generic driver
#   This adds a USB MIDI quirk for the Roland FANTOM-X.
#   
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# sound/usb/usbquirks.h
#   2005/02/23 01:04:57+01:00 perex@suse.cz +26 -13
#   [ALSA] add Roland FANTOM-X support
#   
#   D:2005/02/23 08:04:57
#   C:USB generic driver
#   F:usb/usbquirks.h:1.42->1.43 
#   L:This adds a USB MIDI quirk for the Roland FANTOM-X.
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# ChangeSet
#   2005/03/02 14:51:49+01:00 perex@suse.cz 
#   [ALSA] Add module_init and module_exit entries
#   
#   ALSA sequencer
#   From Mikael Magnusson <mikaelmagnusson@glocalnet.net>:
#   Added the missing module_init and module_exit entries.
#   
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/core/seq/seq_midi_event.c
#   2005/02/22 14:02:02+01:00 perex@suse.cz +12 -0
#   [ALSA] Add module_init and module_exit entries
#   
#   D:2005/02/22 21:02:02
#   C:ALSA sequencer
#   F:core/seq/seq_midi_event.c:1.14->1.15 
#   L:From Mikael Magnusson <mikaelmagnusson@glocalnet.net>:
#   L:Added the missing module_init and module_exit entries.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2005/03/02 14:50:58+01:00 perex@suse.cz 
#   [ALSA] Don't query chip models on CMI8338
#   
#   CMIPCI driver
#   Don't call query_chip() for CMI8338.  It's for CMI8738/8768 only.
#   
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/cmipci.c
#   2005/02/22 13:18:21+01:00 perex@suse.cz +9 -8
#   [ALSA] Don't query chip models on CMI8338
#   
#   D:2005/02/22 20:18:21
#   C:CMIPCI driver
#   F:pci/cmipci.c:1.79->1.80 
#   L:Don't call query_chip() for CMI8338.  It's for CMI8738/8768 only.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2005/03/02 14:50:13+01:00 perex@suse.cz 
#   [ALSA] Fix digital input
#   
#   HDA Codec driver
#   Fixed SPDIF digital input.
#   
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/hda/patch_cmedia.c
#   2005/02/22 10:53:32+01:00 perex@suse.cz +8 -2
#   [ALSA] Fix digital input
#   
#   D:2005/02/22 17:53:32
#   C:HDA Codec driver
#   F:pci/hda/patch_cmedia.c:1.2->1.3 
#   L:Fixed SPDIF digital input.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2005/03/02 14:49:25+01:00 perex@suse.cz 
#   [ALSA] ALC882 support, fix ALC880 5-stack mode
#   
#   HDA Codec driver
#   - Added the ALC882 support.
#     Currently no model selections; full-mode with digital I/O only.
#   - Fixed the widget assignment in ALC880 5-stack mode.
#   
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/hda/patch_realtek.c
#   2005/02/22 10:50:53+01:00 perex@suse.cz +317 -14
#   [ALSA] ALC882 support, fix ALC880 5-stack mode
#   
#   D:2005/02/22 17:50:53
#   C:HDA Codec driver
#   F:pci/hda/patch_realtek.c:1.3->1.4 
#   L:- Added the ALC882 support.
#   L:  Currently no model selections; full-mode with digital I/O only.
#   L:- Fixed the widget assignment in ALC880 5-stack mode.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2005/03/02 14:48:40+01:00 perex@suse.cz 
#   [ALSA] CMI8768 patch
#   
#   CMIPCI driver
#   Hi,
#   
#   I made a patch for CM8768, which has the same PCI ID but there are
#   several HW diffecece, aas listed:
#   
#   1. 8768 has no PCM volume control.
#   2. The ADC of 8768 can only record in 44.1kHz or 48kHz.
#   3. 8768 can support up to 8 channels.
#   
#   I made change for item 2 and 3, I want to use the softvol plugin but
#   don't know how to. The driver just don't generate the PCM volume slider
#    for now.
#   
#   Signed-off-by: ChenLi Tien <cltien@cmedia.com.tw>
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/cmipci.c
#   2005/02/22 10:29:37+01:00 perex@suse.cz +52 -11
#   [ALSA] CMI8768 patch
#   
#   D:2005/02/22 17:29:37
#   C:CMIPCI driver
#   F:pci/cmipci.c:1.78->1.79 
#   L:Hi,
#   L:
#   L:I made a patch for CM8768, which has the same PCI ID but there are
#   L:several HW diffecece, aas listed:
#   L:
#   L:1. 8768 has no PCM volume control.
#   L:2. The ADC of 8768 can only record in 44.1kHz or 48kHz.
#   L:3. 8768 can support up to 8 channels.
#   L:
#   L:I made change for item 2 and 3, I want to use the softvol plugin but
#   L:don't know how to. The driver just don't generate the PCM volume slider
#   L: for now.
#   Signed-off-by: ChenLi Tien <cltien@cmedia.com.tw>
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2005/03/02 14:47:54+01:00 perex@suse.cz 
#   [ALSA] Fix Digital Input
#   
#   HDA Codec driver,HDA generic driver
#   Fixed the SPDIF digital input support for HDA codecs.
#   New controls 'IEC958 Capture Switch' and 'IEC958 Capture Default'
#   are added.
#   
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/hda/hda_local.h
#   2005/02/22 10:18:08+01:00 perex@suse.cz +2 -0
#   [ALSA] Fix Digital Input
#   
#   D:2005/02/22 17:17:57
#   C:HDA Codec driver,HDA generic driver
#   F:pci/hda/hda_codec.c:1.5->1.6 
#   F:pci/hda/hda_codec.h:1.3->1.4 
#   F:pci/hda/hda_local.h:1.2->1.3 
#   L:Fixed the SPDIF digital input support for HDA codecs.
#   L:New controls 'IEC958 Capture Switch' and 'IEC958 Capture Default'
#   L:are added.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/hda/hda_codec.h
#   2005/02/22 10:17:58+01:00 perex@suse.cz +1 -0
#   [ALSA] Fix Digital Input
#   
#   D:2005/02/22 17:17:57
#   C:HDA Codec driver,HDA generic driver
#   F:pci/hda/hda_codec.c:1.5->1.6 
#   F:pci/hda/hda_codec.h:1.3->1.4 
#   F:pci/hda/hda_local.h:1.2->1.3 
#   L:Fixed the SPDIF digital input support for HDA codecs.
#   L:New controls 'IEC958 Capture Switch' and 'IEC958 Capture Default'
#   L:are added.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/hda/hda_codec.c
#   2005/02/22 10:17:57+01:00 perex@suse.cz +103 -2
#   [ALSA] Fix Digital Input
#   
#   D:2005/02/22 17:17:57
#   C:HDA Codec driver,HDA generic driver
#   F:pci/hda/hda_codec.c:1.5->1.6 
#   F:pci/hda/hda_codec.h:1.3->1.4 
#   F:pci/hda/hda_local.h:1.2->1.3 
#   L:Fixed the SPDIF digital input support for HDA codecs.
#   L:New controls 'IEC958 Capture Switch' and 'IEC958 Capture Default'
#   L:are added.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2005/03/02 14:47:08+01:00 perex@suse.cz 
#   [ALSA] fix Emagic broadcast port names
#   
#   USB generic driver
#   Name the broadcast port 'Broadcast' instead of 'Broadcast/Control'
#   because control messages are returned through the first MIDI port.
#   
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# sound/usb/usbmidi.c
#   2005/02/22 00:36:12+01:00 perex@suse.cz +3 -3
#   [ALSA] fix Emagic broadcast port names
#   
#   D:2005/02/22 07:36:12
#   C:USB generic driver
#   F:usb/usbmidi.c:1.42->1.43 
#   L:Name the broadcast port 'Broadcast' instead of 'Broadcast/Control'
#   L:because control messages are returned through the first MIDI port.
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# ChangeSet
#   2005/03/02 14:46:23+01:00 perex@suse.cz 
#   [ALSA] ignore Emagic padding bytes
#   
#   USB generic driver
#   Ignore the 0xff padding bytes added by Emagic devices at the end
#   of input packets.
#   
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# sound/usb/usbmidi.c
#   2005/02/22 00:34:39+01:00 perex@suse.cz +4 -0
#   [ALSA] ignore Emagic padding bytes
#   
#   D:2005/02/22 07:34:39
#   C:USB generic driver
#   F:usb/usbmidi.c:1.41->1.42 
#   L:Ignore the 0xff padding bytes added by Emagic devices at the end
#   L:of input packets.
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# ChangeSet
#   2005/03/02 14:45:33+01:00 perex@suse.cz 
#   [ALSA] add logging to send_bulk_static_data
#   
#   USB generic driver
#   Add the optional dump_urb call to send_bulk_static_data, too.
#   
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# sound/usb/usbmidi.c
#   2005/02/22 00:33:22+01:00 perex@suse.cz +1 -0
#   [ALSA] add logging to send_bulk_static_data
#   
#   D:2005/02/22 07:33:22
#   C:USB generic driver
#   F:usb/usbmidi.c:1.40->1.41 
#   L:Add the optional dump_urb call to send_bulk_static_data, too.
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# ChangeSet
#   2005/03/02 14:44:45+01:00 perex@suse.cz 
#   [ALSA] add support for Emagic USB MIDI interfaces
#   
#   USB generic driver
#   Add support for the Emagic USB MIDI protocol (raw MIDI with 'F5 xx'
#   port switching) and for Unitor8/AMT8/MT4 devices.
#   
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# sound/usb/usbquirks.h
#   2005/02/21 01:41:06+01:00 perex@suse.cz +41 -0
#   [ALSA] add support for Emagic USB MIDI interfaces
#   
#   D:2005/02/21 08:41:06
#   C:USB generic driver
#   F:usb/usbaudio.c:1.116->1.117 
#   F:usb/usbaudio.h:1.37->1.38 
#   F:usb/usbmidi.c:1.39->1.40 
#   F:usb/usbquirks.h:1.41->1.42 
#   L:Add support for the Emagic USB MIDI protocol (raw MIDI with 'F5 xx'
#   L:port switching) and for Unitor8/AMT8/MT4 devices.
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# sound/usb/usbmidi.c
#   2005/02/21 01:41:06+01:00 perex@suse.cz +161 -1
#   [ALSA] add support for Emagic USB MIDI interfaces
#   
#   D:2005/02/21 08:41:06
#   C:USB generic driver
#   F:usb/usbaudio.c:1.116->1.117 
#   F:usb/usbaudio.h:1.37->1.38 
#   F:usb/usbmidi.c:1.39->1.40 
#   F:usb/usbquirks.h:1.41->1.42 
#   L:Add support for the Emagic USB MIDI protocol (raw MIDI with 'F5 xx'
#   L:port switching) and for Unitor8/AMT8/MT4 devices.
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# sound/usb/usbaudio.h
#   2005/02/21 01:41:06+01:00 perex@suse.cz +4 -0
#   [ALSA] add support for Emagic USB MIDI interfaces
#   
#   D:2005/02/21 08:41:06
#   C:USB generic driver
#   F:usb/usbaudio.c:1.116->1.117 
#   F:usb/usbaudio.h:1.37->1.38 
#   F:usb/usbmidi.c:1.39->1.40 
#   F:usb/usbquirks.h:1.41->1.42 
#   L:Add support for the Emagic USB MIDI protocol (raw MIDI with 'F5 xx'
#   L:port switching) and for Unitor8/AMT8/MT4 devices.
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# sound/usb/usbaudio.c
#   2005/02/21 01:41:06+01:00 perex@suse.cz +1 -0
#   [ALSA] add support for Emagic USB MIDI interfaces
#   
#   D:2005/02/21 08:41:06
#   C:USB generic driver
#   F:usb/usbaudio.c:1.116->1.117 
#   F:usb/usbaudio.h:1.37->1.38 
#   F:usb/usbmidi.c:1.39->1.40 
#   F:usb/usbquirks.h:1.41->1.42 
#   L:Add support for the Emagic USB MIDI protocol (raw MIDI with 'F5 xx'
#   L:port switching) and for Unitor8/AMT8/MT4 devices.
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# ChangeSet
#   2005/03/02 14:43:50+01:00 perex@suse.cz 
#   [ALSA] fix indentation
#   
#   Generic drivers
#   
#   
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# sound/drivers/serial-u16550.c
#   2005/02/21 01:17:50+01:00 perex@suse.cz +1 -1
#   [ALSA] fix indentation
#   
#   D:2005/02/21 08:17:50
#   C:Generic drivers
#   F:drivers/serial-u16550.c:1.30->1.31 
#   L:
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# ChangeSet
#   2005/03/02 14:43:04+01:00 perex@suse.cz 
#   [ALSA] remove superfluous from_timer_port parameter
#   
#   ALSA sequencer
#   Removed superfluous from_timer_port parameter from
#   snd_seq_queue_process_event and queue_broadcast_event
#   functions.
#   
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# sound/core/seq/seq_queue.h
#   2005/02/21 01:17:11+01:00 perex@suse.cz +1 -1
#   [ALSA] remove superfluous from_timer_port parameter
#   
#   D:2005/02/21 08:17:11
#   C:ALSA sequencer
#   F:core/seq/seq_queue.c:1.16->1.17 
#   F:core/seq/seq_queue.h:1.9->1.10 
#   L:Removed superfluous from_timer_port parameter from
#   L:snd_seq_queue_process_event and queue_broadcast_event
#   L:functions.
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# sound/core/seq/seq_queue.c
#   2005/02/21 01:17:11+01:00 perex@suse.cz +15 -17
#   [ALSA] remove superfluous from_timer_port parameter
#   
#   D:2005/02/21 08:17:11
#   C:ALSA sequencer
#   F:core/seq/seq_queue.c:1.16->1.17 
#   F:core/seq/seq_queue.h:1.9->1.10 
#   L:Removed superfluous from_timer_port parameter from
#   L:snd_seq_queue_process_event and queue_broadcast_event
#   L:functions.
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# ChangeSet
#   2005/03/02 14:42:11+01:00 perex@suse.cz 
#   [ALSA] Fix SPDIF output
#   
#   HDA Codec driver
#   Fixed SPDIF output (over multi-out).
#   
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/hda/hda_codec.h
#   2005/02/18 10:51:16+01:00 perex@suse.cz +2 -1
#   [ALSA] Fix SPDIF output
#   
#   D:2005/02/18 17:51:16
#   C:HDA Codec driver
#   F:pci/hda/hda_codec.c:1.4->1.5 
#   F:pci/hda/hda_codec.h:1.2->1.3 
#   L:Fixed SPDIF output (over multi-out).
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/hda/hda_codec.c
#   2005/02/18 10:51:16+01:00 perex@suse.cz +70 -53
#   [ALSA] Fix SPDIF output
#   
#   D:2005/02/18 17:51:16
#   C:HDA Codec driver
#   F:pci/hda/hda_codec.c:1.4->1.5 
#   F:pci/hda/hda_codec.h:1.2->1.3 
#   L:Fixed SPDIF output (over multi-out).
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2005/03/02 14:41:26+01:00 perex@suse.cz 
#   [ALSA] Fix mono volume/mute controls
#   
#   HDA generic driver
#   Fixed mono volume/mute controls.  They were handled as stereo mistakenly.
#   
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/hda/hda_local.h
#   2005/02/18 07:27:06+01:00 perex@suse.cz +2 -2
#   [ALSA] Fix mono volume/mute controls
#   
#   D:2005/02/18 14:27:06
#   C:HDA generic driver
#   F:pci/hda/hda_local.h:1.1->1.2 
#   L:Fixed mono volume/mute controls.  They were handled as stereo mistakenly.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2005/03/02 14:40:37+01:00 perex@suse.cz 
#   [ALSA] Don't set up the front stream twice
#   
#   HDA Codec driver
#   Don't set up the front stream twice in the loop.
#   
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/hda/hda_codec.c
#   2005/02/18 07:25:55+01:00 perex@suse.cz +1 -1
#   [ALSA] Don't set up the front stream twice
#   
#   D:2005/02/18 14:25:55
#   C:HDA Codec driver
#   F:pci/hda/hda_codec.c:1.3->1.4 
#   L:Don't set up the front stream twice in the loop.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2005/03/02 14:39:47+01:00 perex@suse.cz 
#   [ALSA] Fix compilation with compat support
#   
#   ALSA sequencer
#   Fix the compilation with 32bit compat support.
#   
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/core/seq/seq_clientmgr.c
#   2005/02/18 07:24:34+01:00 perex@suse.cz +2 -2
#   [ALSA] Fix compilation with compat support
#   
#   D:2005/02/18 14:24:34
#   C:ALSA sequencer
#   F:core/seq/seq_clientmgr.c:1.43->1.44 
#   L:Fix the compilation with 32bit compat support.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2005/03/02 14:38:56+01:00 perex@suse.cz 
#   [ALSA] remove an unnecessary printk
#   
#   EMU10K1/EMU10K2 driver
#   This patch removes an unnecessary printk accidentally left in the
#   multichannel patch.
#   
#   Signed-off-by: Lee Revell <rlrevell@joe-job.com>
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/emu10k1/voice.c
#   2005/02/18 03:21:10+01:00 perex@suse.cz +1 -3
#   [ALSA] remove an unnecessary printk
#   
#   D:2005/02/18 10:21:10
#   C:EMU10K1/EMU10K2 driver
#   F:pci/emu10k1/voice.c:1.6->1.7 
#   L:This patch removes an unnecessary printk accidentally left in the
#   L:multichannel patch.
#   Signed-off-by: Lee Revell <rlrevell@joe-job.com>
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2005/03/02 14:38:10+01:00 perex@suse.cz 
#   [ALSA] Fix invalid use of readl/writel
#   
#   KORG1212 driver
#   Fixed the invalid use of readl/writel to normal pointers.
#   
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/korg1212/korg1212.c
#   2005/02/17 07:55:59+01:00 perex@suse.cz +6 -6
#   [ALSA] Fix invalid use of readl/writel
#   
#   D:2005/02/17 14:55:59
#   C:KORG1212 driver
#   F:pci/korg1212/korg1212.c:1.54->1.55 
#   L:Fixed the invalid use of readl/writel to normal pointers.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2005/03/02 14:37:23+01:00 perex@suse.cz 
#   [ALSA] [SPARSE] Use NULL instead of 0
#   
#   HDA Codec driver
#   Use NULL for pointers instead of 0.
#   
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/hda/patch_realtek.c
#   2005/02/17 07:55:26+01:00 perex@suse.cz +1 -1
#   [ALSA] [SPARSE] Use NULL instead of 0
#   
#   D:2005/02/17 14:55:26
#   C:HDA Codec driver
#   F:pci/hda/patch_realtek.c:1.2->1.3 
#   L:Use NULL for pointers instead of 0.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2005/03/02 14:36:33+01:00 perex@suse.cz 
#   [ALSA] [SPARSE] Add __user pointer casts
#   
#   Wavefront drivers
#   Added __user pointer casts to sys_*() arguments
#   
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/isa/wavefront/wavefront_synth.c
#   2005/02/17 07:54:12+01:00 perex@suse.cz +3 -3
#   [ALSA] [SPARSE] Add __user pointer casts
#   
#   D:2005/02/17 14:54:12
#   C:Wavefront drivers
#   F:isa/wavefront/wavefront_synth.c:1.24->1.25 
#   L:Added __user pointer casts to sys_*() arguments
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2005/03/02 14:34:50+01:00 perex@suse.cz 
#   [ALSA] [SPARSE] Fix __user pointers
#   
#   EMU10K1/EMU10K2 driver
#   Fix the access to __user pointers in some places.
#   Added proper casts.
#   
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/emu10k1/emufx.c
#   2005/02/17 07:51:52+01:00 perex@suse.cz +38 -33
#   [ALSA] [SPARSE] Fix __user pointers
#   
#   D:2005/02/17 14:51:52
#   C:EMU10K1/EMU10K2 driver
#   F:pci/emu10k1/emufx.c:1.68->1.69 
#   L:Fix the access to __user pointers in some places.
#   L:Added proper casts.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2005/03/02 14:34:07+01:00 perex@suse.cz 
#   [ALSA] Fix comiple with old gcc
#   
#   EMU10K1/EMU10K2 driver
#   Fix compile with old gcc.
#   
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/emu10k1/emupcm.c
#   2005/02/17 07:49:50+01:00 perex@suse.cz +4 -3
#   [ALSA] Fix comiple with old gcc
#   
#   D:2005/02/17 14:49:50
#   C:EMU10K1/EMU10K2 driver
#   F:pci/emu10k1/emupcm.c:1.39->1.40 
#   L:Fix compile with old gcc.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2005/03/02 14:33:19+01:00 perex@suse.cz 
#   [ALSA] [SPARSE] Use unsigned int :1 bitfields
#   
#   EMU10K1/EMU10K2 driver,GUS Library,ALSA<-OSS emulation,Trident driver
#   YMFPCI driver,CMIPCI driver,Intel8x0-modem driver,Maestro3 driver
#   ALI5451 driver,ICE1712 driver
#   Use unsigned int :1 bitfields.
#   
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/maestro3.c
#   2005/02/17 07:48:07+01:00 perex@suse.cz +1 -1
#   [ALSA] [SPARSE] Use unsigned int :1 bitfields
#   
#   D:2005/02/17 14:48:07
#   C:EMU10K1/EMU10K2 driver,GUS Library,ALSA<-OSS emulation,Trident driver
#   C:YMFPCI driver,CMIPCI driver,Intel8x0-modem driver,Maestro3 driver
#   C:ALI5451 driver,ICE1712 driver
#   F:include/emu10k1.h:1.56->1.57 
#   F:include/gus.h:1.11->1.12 
#   F:include/mixer_oss.h:1.8->1.9 
#   F:include/trident.h:1.21->1.22 
#   F:include/ymfpci.h:1.18->1.19 
#   F:pci/cmipci.c:1.77->1.78 
#   F:pci/intel8x0m.c:1.27->1.28 
#   F:pci/maestro3.c:1.70->1.71 
#   F:pci/ali5451/ali5451.c:1.61->1.62 
#   F:pci/ice1712/ice1712.h:1.28->1.29 
#   L:Use unsigned int :1 bitfields.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/intel8x0m.c
#   2005/02/17 07:48:07+01:00 perex@suse.cz +1 -1
#   [ALSA] [SPARSE] Use unsigned int :1 bitfields
#   
#   D:2005/02/17 14:48:07
#   C:EMU10K1/EMU10K2 driver,GUS Library,ALSA<-OSS emulation,Trident driver
#   C:YMFPCI driver,CMIPCI driver,Intel8x0-modem driver,Maestro3 driver
#   C:ALI5451 driver,ICE1712 driver
#   F:include/emu10k1.h:1.56->1.57 
#   F:include/gus.h:1.11->1.12 
#   F:include/mixer_oss.h:1.8->1.9 
#   F:include/trident.h:1.21->1.22 
#   F:include/ymfpci.h:1.18->1.19 
#   F:pci/cmipci.c:1.77->1.78 
#   F:pci/intel8x0m.c:1.27->1.28 
#   F:pci/maestro3.c:1.70->1.71 
#   F:pci/ali5451/ali5451.c:1.61->1.62 
#   F:pci/ice1712/ice1712.h:1.28->1.29 
#   L:Use unsigned int :1 bitfields.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/ice1712/ice1712.h
#   2005/02/17 07:48:07+01:00 perex@suse.cz +1 -1
#   [ALSA] [SPARSE] Use unsigned int :1 bitfields
#   
#   D:2005/02/17 14:48:07
#   C:EMU10K1/EMU10K2 driver,GUS Library,ALSA<-OSS emulation,Trident driver
#   C:YMFPCI driver,CMIPCI driver,Intel8x0-modem driver,Maestro3 driver
#   C:ALI5451 driver,ICE1712 driver
#   F:include/emu10k1.h:1.56->1.57 
#   F:include/gus.h:1.11->1.12 
#   F:include/mixer_oss.h:1.8->1.9 
#   F:include/trident.h:1.21->1.22 
#   F:include/ymfpci.h:1.18->1.19 
#   F:pci/cmipci.c:1.77->1.78 
#   F:pci/intel8x0m.c:1.27->1.28 
#   F:pci/maestro3.c:1.70->1.71 
#   F:pci/ali5451/ali5451.c:1.61->1.62 
#   F:pci/ice1712/ice1712.h:1.28->1.29 
#   L:Use unsigned int :1 bitfields.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/cmipci.c
#   2005/02/17 07:48:07+01:00 perex@suse.cz +3 -3
#   [ALSA] [SPARSE] Use unsigned int :1 bitfields
#   
#   D:2005/02/17 14:48:07
#   C:EMU10K1/EMU10K2 driver,GUS Library,ALSA<-OSS emulation,Trident driver
#   C:YMFPCI driver,CMIPCI driver,Intel8x0-modem driver,Maestro3 driver
#   C:ALI5451 driver,ICE1712 driver
#   F:include/emu10k1.h:1.56->1.57 
#   F:include/gus.h:1.11->1.12 
#   F:include/mixer_oss.h:1.8->1.9 
#   F:include/trident.h:1.21->1.22 
#   F:include/ymfpci.h:1.18->1.19 
#   F:pci/cmipci.c:1.77->1.78 
#   F:pci/intel8x0m.c:1.27->1.28 
#   F:pci/maestro3.c:1.70->1.71 
#   F:pci/ali5451/ali5451.c:1.61->1.62 
#   F:pci/ice1712/ice1712.h:1.28->1.29 
#   L:Use unsigned int :1 bitfields.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/ali5451/ali5451.c
#   2005/02/17 07:48:07+01:00 perex@suse.cz +2 -2
#   [ALSA] [SPARSE] Use unsigned int :1 bitfields
#   
#   D:2005/02/17 14:48:07
#   C:EMU10K1/EMU10K2 driver,GUS Library,ALSA<-OSS emulation,Trident driver
#   C:YMFPCI driver,CMIPCI driver,Intel8x0-modem driver,Maestro3 driver
#   C:ALI5451 driver,ICE1712 driver
#   F:include/emu10k1.h:1.56->1.57 
#   F:include/gus.h:1.11->1.12 
#   F:include/mixer_oss.h:1.8->1.9 
#   F:include/trident.h:1.21->1.22 
#   F:include/ymfpci.h:1.18->1.19 
#   F:pci/cmipci.c:1.77->1.78 
#   F:pci/intel8x0m.c:1.27->1.28 
#   F:pci/maestro3.c:1.70->1.71 
#   F:pci/ali5451/ali5451.c:1.61->1.62 
#   F:pci/ice1712/ice1712.h:1.28->1.29 
#   L:Use unsigned int :1 bitfields.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# include/sound/ymfpci.h
#   2005/02/17 07:48:07+01:00 perex@suse.cz +4 -4
#   [ALSA] [SPARSE] Use unsigned int :1 bitfields
#   
#   D:2005/02/17 14:48:07
#   C:EMU10K1/EMU10K2 driver,GUS Library,ALSA<-OSS emulation,Trident driver
#   C:YMFPCI driver,CMIPCI driver,Intel8x0-modem driver,Maestro3 driver
#   C:ALI5451 driver,ICE1712 driver
#   F:include/emu10k1.h:1.56->1.57 
#   F:include/gus.h:1.11->1.12 
#   F:include/mixer_oss.h:1.8->1.9 
#   F:include/trident.h:1.21->1.22 
#   F:include/ymfpci.h:1.18->1.19 
#   F:pci/cmipci.c:1.77->1.78 
#   F:pci/intel8x0m.c:1.27->1.28 
#   F:pci/maestro3.c:1.70->1.71 
#   F:pci/ali5451/ali5451.c:1.61->1.62 
#   F:pci/ice1712/ice1712.h:1.28->1.29 
#   L:Use unsigned int :1 bitfields.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# include/sound/trident.h
#   2005/02/17 07:48:07+01:00 perex@suse.cz +3 -3
#   [ALSA] [SPARSE] Use unsigned int :1 bitfields
#   
#   D:2005/02/17 14:48:07
#   C:EMU10K1/EMU10K2 driver,GUS Library,ALSA<-OSS emulation,Trident driver
#   C:YMFPCI driver,CMIPCI driver,Intel8x0-modem driver,Maestro3 driver
#   C:ALI5451 driver,ICE1712 driver
#   F:include/emu10k1.h:1.56->1.57 
#   F:include/gus.h:1.11->1.12 
#   F:include/mixer_oss.h:1.8->1.9 
#   F:include/trident.h:1.21->1.22 
#   F:include/ymfpci.h:1.18->1.19 
#   F:pci/cmipci.c:1.77->1.78 
#   F:pci/intel8x0m.c:1.27->1.28 
#   F:pci/maestro3.c:1.70->1.71 
#   F:pci/ali5451/ali5451.c:1.61->1.62 
#   F:pci/ice1712/ice1712.h:1.28->1.29 
#   L:Use unsigned int :1 bitfields.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# include/sound/mixer_oss.h
#   2005/02/17 07:48:07+01:00 perex@suse.cz +1 -1
#   [ALSA] [SPARSE] Use unsigned int :1 bitfields
#   
#   D:2005/02/17 14:48:07
#   C:EMU10K1/EMU10K2 driver,GUS Library,ALSA<-OSS emulation,Trident driver
#   C:YMFPCI driver,CMIPCI driver,Intel8x0-modem driver,Maestro3 driver
#   C:ALI5451 driver,ICE1712 driver
#   F:include/emu10k1.h:1.56->1.57 
#   F:include/gus.h:1.11->1.12 
#   F:include/mixer_oss.h:1.8->1.9 
#   F:include/trident.h:1.21->1.22 
#   F:include/ymfpci.h:1.18->1.19 
#   F:pci/cmipci.c:1.77->1.78 
#   F:pci/intel8x0m.c:1.27->1.28 
#   F:pci/maestro3.c:1.70->1.71 
#   F:pci/ali5451/ali5451.c:1.61->1.62 
#   F:pci/ice1712/ice1712.h:1.28->1.29 
#   L:Use unsigned int :1 bitfields.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# include/sound/gus.h
#   2005/02/17 07:48:07+01:00 perex@suse.cz +2 -2
#   [ALSA] [SPARSE] Use unsigned int :1 bitfields
#   
#   D:2005/02/17 14:48:07
#   C:EMU10K1/EMU10K2 driver,GUS Library,ALSA<-OSS emulation,Trident driver
#   C:YMFPCI driver,CMIPCI driver,Intel8x0-modem driver,Maestro3 driver
#   C:ALI5451 driver,ICE1712 driver
#   F:include/emu10k1.h:1.56->1.57 
#   F:include/gus.h:1.11->1.12 
#   F:include/mixer_oss.h:1.8->1.9 
#   F:include/trident.h:1.21->1.22 
#   F:include/ymfpci.h:1.18->1.19 
#   F:pci/cmipci.c:1.77->1.78 
#   F:pci/intel8x0m.c:1.27->1.28 
#   F:pci/maestro3.c:1.70->1.71 
#   F:pci/ali5451/ali5451.c:1.61->1.62 
#   F:pci/ice1712/ice1712.h:1.28->1.29 
#   L:Use unsigned int :1 bitfields.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# include/sound/emu10k1.h
#   2005/02/17 07:48:07+01:00 perex@suse.cz +2 -2
#   [ALSA] [SPARSE] Use unsigned int :1 bitfields
#   
#   D:2005/02/17 14:48:07
#   C:EMU10K1/EMU10K2 driver,GUS Library,ALSA<-OSS emulation,Trident driver
#   C:YMFPCI driver,CMIPCI driver,Intel8x0-modem driver,Maestro3 driver
#   C:ALI5451 driver,ICE1712 driver
#   F:include/emu10k1.h:1.56->1.57 
#   F:include/gus.h:1.11->1.12 
#   F:include/mixer_oss.h:1.8->1.9 
#   F:include/trident.h:1.21->1.22 
#   F:include/ymfpci.h:1.18->1.19 
#   F:pci/cmipci.c:1.77->1.78 
#   F:pci/intel8x0m.c:1.27->1.28 
#   F:pci/maestro3.c:1.70->1.71 
#   F:pci/ali5451/ali5451.c:1.61->1.62 
#   F:pci/ice1712/ice1712.h:1.28->1.29 
#   L:Use unsigned int :1 bitfields.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2005/03/02 14:32:38+01:00 perex@suse.cz 
#   [ALSA] [SPARSE] Fix __user pointers
#   
#   PCM Midlevel,RawMidi Midlevel,ALSA<-OSS emulation,ALSA sequencer
#   Fixed __user pointers including other misc fixes:
#    - replaced the obsolete CONFIG_SND_IOCTL32_EMUL.
#    - added the proper segment change before passing the kernel pointer
#      as the user pointer in PCM code.
#   
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/core/seq/seq_memory.c
#   2005/02/17 07:45:48+01:00 perex@suse.cz +4 -4
#   [ALSA] [SPARSE] Fix __user pointers
#   
#   D:2005/02/17 14:45:47
#   C:PCM Midlevel,RawMidi Midlevel,ALSA<-OSS emulation,ALSA sequencer
#   F:core/pcm_native.c:1.114->1.115 
#   F:core/rawmidi.c:1.54->1.55 
#   F:core/oss/pcm_oss.c:1.84->1.85 
#   F:core/seq/seq_clientmgr.c:1.42->1.43 
#   F:core/seq/seq_instr.c:1.12->1.13 
#   F:core/seq/seq_memory.c:1.19->1.20 
#   L:Fixed __user pointers including other misc fixes:
#   L: - replaced the obsolete CONFIG_SND_IOCTL32_EMUL.
#   L: - added the proper segment change before passing the kernel pointer
#   L:   as the user pointer in PCM code.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/core/seq/seq_instr.c
#   2005/02/17 07:45:48+01:00 perex@suse.cz +3 -3
#   [ALSA] [SPARSE] Fix __user pointers
#   
#   D:2005/02/17 14:45:47
#   C:PCM Midlevel,RawMidi Midlevel,ALSA<-OSS emulation,ALSA sequencer
#   F:core/pcm_native.c:1.114->1.115 
#   F:core/rawmidi.c:1.54->1.55 
#   F:core/oss/pcm_oss.c:1.84->1.85 
#   F:core/seq/seq_clientmgr.c:1.42->1.43 
#   F:core/seq/seq_instr.c:1.12->1.13 
#   F:core/seq/seq_memory.c:1.19->1.20 
#   L:Fixed __user pointers including other misc fixes:
#   L: - replaced the obsolete CONFIG_SND_IOCTL32_EMUL.
#   L: - added the proper segment change before passing the kernel pointer
#   L:   as the user pointer in PCM code.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/core/seq/seq_clientmgr.c
#   2005/02/17 07:45:47+01:00 perex@suse.cz +3 -3
#   [ALSA] [SPARSE] Fix __user pointers
#   
#   D:2005/02/17 14:45:47
#   C:PCM Midlevel,RawMidi Midlevel,ALSA<-OSS emulation,ALSA sequencer
#   F:core/pcm_native.c:1.114->1.115 
#   F:core/rawmidi.c:1.54->1.55 
#   F:core/oss/pcm_oss.c:1.84->1.85 
#   F:core/seq/seq_clientmgr.c:1.42->1.43 
#   F:core/seq/seq_instr.c:1.12->1.13 
#   F:core/seq/seq_memory.c:1.19->1.20 
#   L:Fixed __user pointers including other misc fixes:
#   L: - replaced the obsolete CONFIG_SND_IOCTL32_EMUL.
#   L: - added the proper segment change before passing the kernel pointer
#   L:   as the user pointer in PCM code.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/core/rawmidi.c
#   2005/02/17 07:45:47+01:00 perex@suse.cz +6 -4
#   [ALSA] [SPARSE] Fix __user pointers
#   
#   D:2005/02/17 14:45:47
#   C:PCM Midlevel,RawMidi Midlevel,ALSA<-OSS emulation,ALSA sequencer
#   F:core/pcm_native.c:1.114->1.115 
#   F:core/rawmidi.c:1.54->1.55 
#   F:core/oss/pcm_oss.c:1.84->1.85 
#   F:core/seq/seq_clientmgr.c:1.42->1.43 
#   F:core/seq/seq_instr.c:1.12->1.13 
#   F:core/seq/seq_memory.c:1.19->1.20 
#   L:Fixed __user pointers including other misc fixes:
#   L: - replaced the obsolete CONFIG_SND_IOCTL32_EMUL.
#   L: - added the proper segment change before passing the kernel pointer
#   L:   as the user pointer in PCM code.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/core/pcm_native.c
#   2005/02/17 07:45:47+01:00 perex@suse.cz +2 -2
#   [ALSA] [SPARSE] Fix __user pointers
#   
#   D:2005/02/17 14:45:47
#   C:PCM Midlevel,RawMidi Midlevel,ALSA<-OSS emulation,ALSA sequencer
#   F:core/pcm_native.c:1.114->1.115 
#   F:core/rawmidi.c:1.54->1.55 
#   F:core/oss/pcm_oss.c:1.84->1.85 
#   F:core/seq/seq_clientmgr.c:1.42->1.43 
#   F:core/seq/seq_instr.c:1.12->1.13 
#   F:core/seq/seq_memory.c:1.19->1.20 
#   L:Fixed __user pointers including other misc fixes:
#   L: - replaced the obsolete CONFIG_SND_IOCTL32_EMUL.
#   L: - added the proper segment change before passing the kernel pointer
#   L:   as the user pointer in PCM code.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/core/oss/pcm_oss.c
#   2005/02/17 07:45:47+01:00 perex@suse.cz +15 -12
#   [ALSA] [SPARSE] Fix __user pointers
#   
#   D:2005/02/17 14:45:47
#   C:PCM Midlevel,RawMidi Midlevel,ALSA<-OSS emulation,ALSA sequencer
#   F:core/pcm_native.c:1.114->1.115 
#   F:core/rawmidi.c:1.54->1.55 
#   F:core/oss/pcm_oss.c:1.84->1.85 
#   F:core/seq/seq_clientmgr.c:1.42->1.43 
#   F:core/seq/seq_instr.c:1.12->1.13 
#   F:core/seq/seq_memory.c:1.19->1.20 
#   L:Fixed __user pointers including other misc fixes:
#   L: - replaced the obsolete CONFIG_SND_IOCTL32_EMUL.
#   L: - added the proper segment change before passing the kernel pointer
#   L:   as the user pointer in PCM code.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2005/03/02 14:31:51+01:00 perex@suse.cz 
#   [ALSA] Fix the wrong function call from ioctl
#   
#   Control Midlevel
#   Fixed the call of a wrong function from ioctl.
#   
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/core/control.c
#   2005/02/17 07:40:34+01:00 perex@suse.cz +1 -1
#   [ALSA] Fix the wrong function call from ioctl
#   
#   D:2005/02/17 14:40:34
#   C:Control Midlevel
#   F:core/control.c:1.57->1.58 
#   L:Fixed the call of a wrong function from ioctl.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2005/03/02 14:31:07+01:00 perex@suse.cz 
#   [ALSA] use unsigned 1-bit fields
#   
#   Virtual Midi
#   Can't have a boolean and a sign bit in 1 bit.
#   
#   Fix (14) boolean/bitfield sparse warning:
#   include/sound/seq_virmidi.h:41:16: warning: dubious one-bit signed bitfield
#   
#   Signed-off-by: Randy Dunlap <rddunlap@osdl.org>
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# include/sound/seq_virmidi.h
#   2005/02/17 04:55:52+01:00 perex@suse.cz +1 -1
#   [ALSA] use unsigned 1-bit fields
#   
#   D:2005/02/17 11:55:52
#   C:Virtual Midi
#   F:include/seq_virmidi.h:1.4->1.5 
#   L:Can't have a boolean and a sign bit in 1 bit.
#   L:
#   L:Fix (14) boolean/bitfield sparse warning:
#   L:include/sound/seq_virmidi.h:41:16: warning: dubious one-bit signed bitfield
#   Signed-off-by: Randy Dunlap <rddunlap@osdl.org>
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2005/03/02 14:30:15+01:00 perex@suse.cz 
#   [ALSA] Fix CM9761 again
#   
#   AC97 Codec
#   Revert the last addition for CM9761A support.  The codec doesn't
#   support the real control of Master/PCM volumes, too.
#   Instead, fixed the default multi-channel register setting now.
#   
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/ac97/ac97_patch.h
#   2005/02/16 11:27:19+01:00 perex@suse.cz +0 -1
#   [ALSA] Fix CM9761 again
#   
#   D:2005/02/16 18:27:12
#   C:AC97 Codec
#   F:pci/ac97/ac97_codec.c:1.171->1.172 
#   F:pci/ac97/ac97_patch.c:1.73->1.74 
#   F:pci/ac97/ac97_patch.h:1.18->1.19 
#   L:Revert the last addition for CM9761A support.  The codec doesn't
#   L:support the real control of Master/PCM volumes, too.
#   L:Instead, fixed the default multi-channel register setting now.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/ac97/ac97_patch.c
#   2005/02/16 11:27:17+01:00 perex@suse.cz +0 -26
#   [ALSA] Fix CM9761 again
#   
#   D:2005/02/16 18:27:12
#   C:AC97 Codec
#   F:pci/ac97/ac97_codec.c:1.171->1.172 
#   F:pci/ac97/ac97_patch.c:1.73->1.74 
#   F:pci/ac97/ac97_patch.h:1.18->1.19 
#   L:Revert the last addition for CM9761A support.  The codec doesn't
#   L:support the real control of Master/PCM volumes, too.
#   L:Instead, fixed the default multi-channel register setting now.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/ac97/ac97_codec.c
#   2005/02/16 11:27:12+01:00 perex@suse.cz +1 -2
#   [ALSA] Fix CM9761 again
#   
#   D:2005/02/16 18:27:12
#   C:AC97 Codec
#   F:pci/ac97/ac97_codec.c:1.171->1.172 
#   F:pci/ac97/ac97_patch.c:1.73->1.74 
#   F:pci/ac97/ac97_patch.h:1.18->1.19 
#   L:Revert the last addition for CM9761A support.  The codec doesn't
#   L:support the real control of Master/PCM volumes, too.
#   L:Instead, fixed the default multi-channel register setting now.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2005/03/02 14:29:36+01:00 perex@suse.cz 
#   [ALSA] Fix CM9761A codec support
#   
#   AC97 Codec
#   Fixed the codec patch for (probably) CM9761A.  It looks incompatible
#   with other CM9761 models.
#   
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/ac97/ac97_patch.h
#   2005/02/16 09:21:04+01:00 perex@suse.cz +1 -0
#   [ALSA] Fix CM9761A codec support
#   
#   D:2005/02/16 16:21:03
#   C:AC97 Codec
#   F:pci/ac97/ac97_codec.c:1.170->1.171 
#   F:pci/ac97/ac97_patch.c:1.72->1.73 
#   F:pci/ac97/ac97_patch.h:1.17->1.18 
#   L:Fixed the codec patch for (probably) CM9761A.  It looks incompatible
#   L:with other CM9761 models.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/ac97/ac97_patch.c
#   2005/02/16 09:21:04+01:00 perex@suse.cz +28 -0
#   [ALSA] Fix CM9761A codec support
#   
#   D:2005/02/16 16:21:03
#   C:AC97 Codec
#   F:pci/ac97/ac97_codec.c:1.170->1.171 
#   F:pci/ac97/ac97_patch.c:1.72->1.73 
#   F:pci/ac97/ac97_patch.h:1.17->1.18 
#   L:Fixed the codec patch for (probably) CM9761A.  It looks incompatible
#   L:with other CM9761 models.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/ac97/ac97_codec.c
#   2005/02/16 09:21:03+01:00 perex@suse.cz +2 -1
#   [ALSA] Fix CM9761A codec support
#   
#   D:2005/02/16 16:21:03
#   C:AC97 Codec
#   F:pci/ac97/ac97_codec.c:1.170->1.171 
#   F:pci/ac97/ac97_patch.c:1.72->1.73 
#   F:pci/ac97/ac97_patch.h:1.17->1.18 
#   L:Fixed the codec patch for (probably) CM9761A.  It looks incompatible
#   L:with other CM9761 models.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2005/03/02 14:28:44+01:00 perex@suse.cz 
#   [ALSA] add code to dump packets
#   
#   USB generic driver
#   add a compile-time option to log the contents of USB packets
#   
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# sound/usb/usbmidi.c
#   2005/02/16 08:55:54+01:00 perex@suse.cz +22 -0
#   [ALSA] add code to dump packets
#   
#   D:2005/02/16 15:55:54
#   C:USB generic driver
#   F:usb/usbmidi.c:1.38->1.39 
#   L:add a compile-time option to log the contents of USB packets
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# ChangeSet
#   2005/03/02 14:28:03+01:00 perex@suse.cz 
#   [ALSA] Fix detection of AFG node
#   
#   HDA Codec driver
#   Fix the detection of AFG node with unsolicited events.
#   
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/hda/hda_codec.c
#   2005/02/16 03:48:15+01:00 perex@suse.cz +2 -1
#   [ALSA] Fix detection of AFG node
#   
#   D:2005/02/16 10:48:15
#   C:HDA Codec driver
#   F:pci/hda/hda_codec.c:1.2->1.3 
#   L:Fix the detection of AFG node with unsolicited events.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2005/03/02 14:27:11+01:00 perex@suse.cz 
#   [ALSA] emu10k1 - add 'voices' /proc entry for debugging the voice allocator
#   
#   EMU10K1/EMU10K2 driver
#   This patch adds a 'voices' /proc entry for debugging the voice
#   allocator.  It also increases the size of the ptr_regs files to display
#   the values for all channels.  Finally it updates the names of the EFX
#   recording inputs from '???' to 'FXBUS2_*'.
#   
#   Signed-Off-By: Lee Revell <rlrevell@joe-job.com>
#   Signed-off-by: Jaroslav Kysela <perex@suse.cz>
# 
# sound/pci/emu10k1/emuproc.c
#   2005/02/16 03:27:03+01:00 perex@suse.cz +61 -38
#   [ALSA] emu10k1 - add 'voices' /proc entry for debugging the voice allocator
#   
#   D:2005/02/16 10:27:03
#   C:EMU10K1/EMU10K2 driver
#   F:pci/emu10k1/emuproc.c:1.23->1.24 
#   L:This patch adds a 'voices' /proc entry for debugging the voice
#   L:allocator.  It also increases the size of the ptr_regs files to display
#   L:the values for all channels.  Finally it updates the names of the EFX
#   L:recording inputs from '???' to 'FXBUS2_*'.
#   Signed-Off-By: Lee Revell <rlrevell@joe-job.com>
#   Signed-off-by: Jaroslav Kysela <perex@suse.cz>
# 
# ChangeSet
#   2005/03/02 14:26:25+01:00 perex@suse.cz 
#   [ALSA] emu10k1 driver - add multichannel device hw:x,3 [2-8/8]
#   
#   EMU10K1/EMU10K2 driver
#   This series of patches adds a 16 channel non interleaved PCM playback
#   device, hw:x,3, to the emu10k1 driver.  It also adds support for the
#   newly discovered per channel half loop interrupt.
#   
#   Signed-Off-By: Lee Revell <rlrevell@joe-job.com>
#   Signed-off-by: Jaroslav Kysela <perex@suse.cz>
# 
# sound/pci/emu10k1/voice.c
#   2005/02/16 03:25:36+01:00 perex@suse.cz +70 -21
#   [ALSA] emu10k1 driver - add multichannel device hw:x,3 [2-8/8]
#   
#   D:2005/02/16 10:25:36
#   C:EMU10K1/EMU10K2 driver
#   F:pci/emu10k1/emu10k1.c:1.30->1.31 
#   F:pci/emu10k1/emu10k1_callback.c:1.12->1.13 
#   F:pci/emu10k1/emumixer.c:1.29->1.30 
#   F:pci/emu10k1/emupcm.c:1.38->1.39 
#   F:pci/emu10k1/io.c:1.8->1.9 
#   F:pci/emu10k1/irq.c:1.11->1.12 
#   F:pci/emu10k1/voice.c:1.5->1.6 
#   L:This series of patches adds a 16 channel non interleaved PCM playback
#   L:device, hw:x,3, to the emu10k1 driver.  It also adds support for the
#   L:newly discovered per channel half loop interrupt.
#   Signed-Off-By: Lee Revell <rlrevell@joe-job.com>
#   Signed-off-by: Jaroslav Kysela <perex@suse.cz>
# 
# sound/pci/emu10k1/irq.c
#   2005/02/16 03:25:36+01:00 perex@suse.cz +15 -0
#   [ALSA] emu10k1 driver - add multichannel device hw:x,3 [2-8/8]
#   
#   D:2005/02/16 10:25:36
#   C:EMU10K1/EMU10K2 driver
#   F:pci/emu10k1/emu10k1.c:1.30->1.31 
#   F:pci/emu10k1/emu10k1_callback.c:1.12->1.13 
#   F:pci/emu10k1/emumixer.c:1.29->1.30 
#   F:pci/emu10k1/emupcm.c:1.38->1.39 
#   F:pci/emu10k1/io.c:1.8->1.9 
#   F:pci/emu10k1/irq.c:1.11->1.12 
#   F:pci/emu10k1/voice.c:1.5->1.6 
#   L:This series of patches adds a 16 channel non interleaved PCM playback
#   L:device, hw:x,3, to the emu10k1 driver.  It also adds support for the
#   L:newly discovered per channel half loop interrupt.
#   Signed-Off-By: Lee Revell <rlrevell@joe-job.com>
#   Signed-off-by: Jaroslav Kysela <perex@suse.cz>
# 
# sound/pci/emu10k1/io.c
#   2005/02/16 03:25:36+01:00 perex@suse.cz +57 -0
#   [ALSA] emu10k1 driver - add multichannel device hw:x,3 [2-8/8]
#   
#   D:2005/02/16 10:25:36
#   C:EMU10K1/EMU10K2 driver
#   F:pci/emu10k1/emu10k1.c:1.30->1.31 
#   F:pci/emu10k1/emu10k1_callback.c:1.12->1.13 
#   F:pci/emu10k1/emumixer.c:1.29->1.30 
#   F:pci/emu10k1/emupcm.c:1.38->1.39 
#   F:pci/emu10k1/io.c:1.8->1.9 
#   F:pci/emu10k1/irq.c:1.11->1.12 
#   F:pci/emu10k1/voice.c:1.5->1.6 
#   L:This series of patches adds a 16 channel non interleaved PCM playback
#   L:device, hw:x,3, to the emu10k1 driver.  It also adds support for the
#   L:newly discovered per channel half loop interrupt.
#   Signed-Off-By: Lee Revell <rlrevell@joe-job.com>
#   Signed-off-by: Jaroslav Kysela <perex@suse.cz>
# 
# sound/pci/emu10k1/emupcm.c
#   2005/02/16 03:25:36+01:00 perex@suse.cz +293 -21
#   [ALSA] emu10k1 driver - add multichannel device hw:x,3 [2-8/8]
#   
#   D:2005/02/16 10:25:36
#   C:EMU10K1/EMU10K2 driver
#   F:pci/emu10k1/emu10k1.c:1.30->1.31 
#   F:pci/emu10k1/emu10k1_callback.c:1.12->1.13 
#   F:pci/emu10k1/emumixer.c:1.29->1.30 
#   F:pci/emu10k1/emupcm.c:1.38->1.39 
#   F:pci/emu10k1/io.c:1.8->1.9 
#   F:pci/emu10k1/irq.c:1.11->1.12 
#   F:pci/emu10k1/voice.c:1.5->1.6 
#   L:This series of patches adds a 16 channel non interleaved PCM playback
#   L:device, hw:x,3, to the emu10k1 driver.  It also adds support for the
#   L:newly discovered per channel half loop interrupt.
#   Signed-Off-By: Lee Revell <rlrevell@joe-job.com>
#   Signed-off-by: Jaroslav Kysela <perex@suse.cz>
# 
# sound/pci/emu10k1/emumixer.c
#   2005/02/16 03:25:36+01:00 perex@suse.cz +224 -1
#   [ALSA] emu10k1 driver - add multichannel device hw:x,3 [2-8/8]
#   
#   D:2005/02/16 10:25:36
#   C:EMU10K1/EMU10K2 driver
#   F:pci/emu10k1/emu10k1.c:1.30->1.31 
#   F:pci/emu10k1/emu10k1_callback.c:1.12->1.13 
#   F:pci/emu10k1/emumixer.c:1.29->1.30 
#   F:pci/emu10k1/emupcm.c:1.38->1.39 
#   F:pci/emu10k1/io.c:1.8->1.9 
#   F:pci/emu10k1/irq.c:1.11->1.12 
#   F:pci/emu10k1/voice.c:1.5->1.6 
#   L:This series of patches adds a 16 channel non interleaved PCM playback
#   L:device, hw:x,3, to the emu10k1 driver.  It also adds support for the
#   L:newly discovered per channel half loop interrupt.
#   Signed-Off-By: Lee Revell <rlrevell@joe-job.com>
#   Signed-off-by: Jaroslav Kysela <perex@suse.cz>
# 
# sound/pci/emu10k1/emu10k1_callback.c
#   2005/02/16 03:25:36+01:00 perex@suse.cz +1 -1
#   [ALSA] emu10k1 driver - add multichannel device hw:x,3 [2-8/8]
#   
#   D:2005/02/16 10:25:36
#   C:EMU10K1/EMU10K2 driver
#   F:pci/emu10k1/emu10k1.c:1.30->1.31 
#   F:pci/emu10k1/emu10k1_callback.c:1.12->1.13 
#   F:pci/emu10k1/emumixer.c:1.29->1.30 
#   F:pci/emu10k1/emupcm.c:1.38->1.39 
#   F:pci/emu10k1/io.c:1.8->1.9 
#   F:pci/emu10k1/irq.c:1.11->1.12 
#   F:pci/emu10k1/voice.c:1.5->1.6 
#   L:This series of patches adds a 16 channel non interleaved PCM playback
#   L:device, hw:x,3, to the emu10k1 driver.  It also adds support for the
#   L:newly discovered per channel half loop interrupt.
#   Signed-Off-By: Lee Revell <rlrevell@joe-job.com>
#   Signed-off-by: Jaroslav Kysela <perex@suse.cz>
# 
# sound/pci/emu10k1/emu10k1.c
#   2005/02/16 03:25:36+01:00 perex@suse.cz +5 -0
#   [ALSA] emu10k1 driver - add multichannel device hw:x,3 [2-8/8]
#   
#   D:2005/02/16 10:25:36
#   C:EMU10K1/EMU10K2 driver
#   F:pci/emu10k1/emu10k1.c:1.30->1.31 
#   F:pci/emu10k1/emu10k1_callback.c:1.12->1.13 
#   F:pci/emu10k1/emumixer.c:1.29->1.30 
#   F:pci/emu10k1/emupcm.c:1.38->1.39 
#   F:pci/emu10k1/io.c:1.8->1.9 
#   F:pci/emu10k1/irq.c:1.11->1.12 
#   F:pci/emu10k1/voice.c:1.5->1.6 
#   L:This series of patches adds a 16 channel non interleaved PCM playback
#   L:device, hw:x,3, to the emu10k1 driver.  It also adds support for the
#   L:newly discovered per channel half loop interrupt.
#   Signed-Off-By: Lee Revell <rlrevell@joe-job.com>
#   Signed-off-by: Jaroslav Kysela <perex@suse.cz>
# 
# ChangeSet
#   2005/03/02 14:25:34+01:00 perex@suse.cz 
#   [ALSA] emu10k1 driver - add multichannel device hw:x,3 [1/8]
#   
#   EMU10K1/EMU10K2 driver
#   Update header file for multichannel support.
#   Add some new register info.
#   
#   Signed-Off-By: Lee Revell <rlrevell@joe-job.com>
#   Signed-off-by: Jaroslav Kysela <perex@suse.cz>
# 
# include/sound/emu10k1.h
#   2005/02/16 03:19:02+01:00 perex@suse.cz +81 -12
#   [ALSA] emu10k1 driver - add multichannel device hw:x,3 [1/8]
#   
#   D:2005/02/16 10:19:02
#   C:EMU10K1/EMU10K2 driver
#   F:include/emu10k1.h:1.55->1.56 
#   L:Update header file for multichannel support.
#   L:Add some new register info.
#   Signed-Off-By: Lee Revell <rlrevell@joe-job.com>
#   Signed-off-by: Jaroslav Kysela <perex@suse.cz>
# 
# ChangeSet
#   2005/03/02 14:24:49+01:00 perex@suse.cz 
#   [ALSA] FM801 - radio: Fixed thinko for tea575x_tuner module parameter (int type not bool)
#   
#   FM801 driver
#   
#   
#   Signed-off-by: Jaroslav Kysela <perex@suse.cz>
# 
# sound/pci/fm801.c
#   2005/02/15 10:27:47+01:00 perex@suse.cz +1 -1
#   [ALSA] FM801 - radio: Fixed thinko for tea575x_tuner module parameter (int type not bool)
#   
#   D:2005/02/15 17:27:47
#   C:FM801 driver
#   F:pci/fm801.c:1.55->1.56 
#   L:
#   Signed-off-by: Jaroslav Kysela <perex@suse.cz>
# 
# ChangeSet
#   2005/03/02 14:23:58+01:00 perex@suse.cz 
#   [ALSA] TEA575x - add video release callback to avoid warning
#   
#   TEA575x tuner
#   
#   
#   Signed-off-by: Jaroslav Kysela <perex@suse.cz>
# 
# sound/i2c/other/tea575x-tuner.c
#   2005/02/15 03:23:46+01:00 perex@suse.cz +5 -0
#   [ALSA] TEA575x - add video release callback to avoid warning
#   
#   D:2005/02/15 10:23:46
#   C:TEA575x tuner
#   F:i2c/other/tea575x-tuner.c:1.3->1.4 
#   L:
#   Signed-off-by: Jaroslav Kysela <perex@suse.cz>
# 
# ChangeSet
#   2005/03/02 11:17:39+01:00 perex@suse.cz 
#   Alsa sync
# 
# sound/pci/rme9652/hdsp.c
#   2005/03/02 11:17:14+01:00 perex@suse.cz +0 -1
#   ALSA sync
# 
# sound/pci/intel8x0.c
#   2005/03/02 11:17:13+01:00 perex@suse.cz +0 -16
#   ALSA sync
# 
# sound/pci/ac97/ac97_patch.c
#   2005/03/02 09:51:31+01:00 perex@suse.cz +0 -24
#   Auto merged
# 
# BitKeeper/deleted/.del-pcm32.c~79101ddd8c8dbba8
#   2005/03/02 09:51:30+01:00 perex@suse.cz +0 -3
#   Auto merged
# 
# BitKeeper/deleted/.del-ioctl32.c~e6621ca58003986f
#   2005/03/02 09:51:30+01:00 perex@suse.cz +0 -3
#   Auto merged
# 
# sound/pci/bt87x.c
#   2005/03/02 09:51:30+01:00 perex@suse.cz +0 -1
#   Auto merged
# 
# sound/pci/atiixp.c
#   2005/03/02 09:51:30+01:00 perex@suse.cz +0 -6
#   Auto merged
# 
# BitKeeper/deleted/.del-pcm32.c~79101ddd8c8dbba8
#   2005/03/02 09:51:30+01:00 perex@suse.cz +0 -0
#   Merge rename: sound/core/ioctl32/pcm32.c -> BitKeeper/deleted/.del-pcm32.c~79101ddd8c8dbba8
# 
# BitKeeper/deleted/.del-ioctl32.c~e6621ca58003986f
#   2005/03/02 09:51:30+01:00 perex@suse.cz +0 -0
#   Merge rename: sound/core/ioctl32/ioctl32.c -> BitKeeper/deleted/.del-ioctl32.c~e6621ca58003986f
# 
# ChangeSet
#   2005/03/01 15:38:13-08:00 davem@nuts.davemloft.net 
#   Resolve conflicts.
# 
# arch/ppc64/mm/tlb.c
#   2005/03/01 15:37:54-08:00 davem@nuts.davemloft.net +0 -6
#   Resolve conflicts with bug fix.
# 
# ChangeSet
#   2005/03/01 15:33:45-08:00 davem@nuts.davemloft.net 
#   Resolve conflicts.
# 
# mm/highmem.c
#   2005/03/01 15:04:37-08:00 davem@nuts.davemloft.net +0 -0
#   Auto merged
# 
# arch/arm/mm/consistent.c
#   2005/03/01 15:04:36-08:00 davem@nuts.davemloft.net +0 -0
#   Auto merged
# 
# ChangeSet
#   2005/03/01 15:00:34-08:00 davem@nuts.davemloft.net 
#   [S390]: Fix build after set_pte_at() changes.
#   
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# include/asm-s390/pgtable.h
#   2005/03/01 15:00:00-08:00 davem@nuts.davemloft.net +1 -1
#   [S390]: Fix build after set_pte_at() changes.
# 
# ChangeSet
#   2005/03/01 14:13:43+01:00 ddstreet@ieee.org 
#   input: Add the option to use cooked coordinates in MicroTouch
#          USB touchscreen driver.
#   
#   From: Dan Streetman <ddstreet@ieee.org>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/usb/input/mtouchusb.c
#   2005/03/01 14:13:37+01:00 ddstreet@ieee.org +29 -8
#   input: Add the option to use cooked coordinates in MicroTouch
#          USB touchscreen driver.
#   
#   From: Dan Streetman <ddstreet@ieee.org>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# Documentation/kernel-parameters.txt
#   2005/03/01 14:13:37+01:00 ddstreet@ieee.org +4 -0
#   input: Add the option to use cooked coordinates in MicroTouch
#          USB touchscreen driver.
#   
#   From: Dan Streetman <ddstreet@ieee.org>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# ChangeSet
#   2005/03/01 14:02:56+01:00 ddstreet@ieee.org 
#   input: Add MicroTouch (3M) serial touchscreen driver
#   
#   From: Dan Streetman <ddstreet@ieee.org>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/touchscreen/mtouch.c
#   2005/03/01 14:02:50+01:00 ddstreet@ieee.org +219 -0
# 
# include/linux/serio.h
#   2005/03/01 14:02:50+01:00 ddstreet@ieee.org +1 -0
#   input: Add MicroTouch (3M) serial touchscreen driver
#   
#   From: Dan Streetman <ddstreet@ieee.org>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/touchscreen/mtouch.c
#   2005/03/01 14:02:50+01:00 ddstreet@ieee.org +0 -0
#   BitKeeper file /home/vojtech/bk/input/drivers/input/touchscreen/mtouch.c
# 
# drivers/input/touchscreen/Makefile
#   2005/03/01 14:02:50+01:00 ddstreet@ieee.org +1 -0
#   input: Add MicroTouch (3M) serial touchscreen driver
#   
#   From: Dan Streetman <ddstreet@ieee.org>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/touchscreen/Kconfig
#   2005/03/01 14:02:50+01:00 ddstreet@ieee.org +11 -0
#   input: Add MicroTouch (3M) serial touchscreen driver
#   
#   From: Dan Streetman <ddstreet@ieee.org>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# ChangeSet
#   2005/02/28 16:45:42-07:00 dale@farnsworth.org 
#   mv643xx: remove superfluous function, mv643xx_set_ethtool_ops
#   
#   Signed-off-by: Dale Farnsworth <dale@farnsworth.org>
# 
# drivers/net/mv643xx_eth.c
#   2005/02/28 16:45:27-07:00 dale@farnsworth.org +3 -8
#   mv643xx: remove superfluous function, mv643xx_set_ethtool_ops
#   
#   Signed-off-by: Dale Farnsworth <dale@farnsworth.org>
# 
# ChangeSet
#   2005/02/28 15:50:37-07:00 dale@farnsworth.org 
#   mv643xx: raise size of receive skbs to allow for an optional VLAN tag
#   
#   VLAN tag needs an extra 4 bytes in receive skb
#   
#   Signed-off-by: Dale Farnsworth <dale@farnsworth.org>
# 
# drivers/net/mv643xx_eth.c
#   2005/02/28 15:50:21-07:00 dale@farnsworth.org +6 -2
#   mv643xx: raise size of receive skbs to allow for an optional VLAN tag
#   
#   VLAN tag needs an extra 4 bytes in receive skb
#   
#   Signed-off-by: Dale Farnsworth <dale@farnsworth.org>
# 
# ChangeSet
#   2005/02/28 12:08:34+01:00 vojtech@suse.cz 
#   Merge suse.cz:/home/vojtech/bk/linus into suse.cz:/home/vojtech/bk/input
# 
# drivers/char/keyboard.c
#   2005/02/28 12:08:31+01:00 vojtech@suse.cz +0 -0
#   Auto merged
# 
# ChangeSet
#   2005/02/28 11:58:50+01:00 vojtech@suse.cz 
#   input: Make gameport digital joysticks work on 2.6 and x86_64 again.
#   
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/joystick/tmdc.c
#   2005/02/28 11:58:45+01:00 vojtech@suse.cz +2 -2
#   input: Make gameport digital joysticks work on 2.6 and x86_64 again.
#   
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/joystick/sidewinder.c
#   2005/02/28 11:58:45+01:00 vojtech@suse.cz +21 -21
#   input: Make gameport digital joysticks work on 2.6 and x86_64 again.
#   
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/joystick/interact.c
#   2005/02/28 11:58:45+01:00 vojtech@suse.cz +2 -2
#   input: Make gameport digital joysticks work on 2.6 and x86_64 again.
#   
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/joystick/analog.c
#   2005/02/28 11:58:45+01:00 vojtech@suse.cz +1 -1
#   input: Make gameport digital joysticks work on 2.6 and x86_64 again.
#   
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/joystick/adi.c
#   2005/02/28 11:58:45+01:00 vojtech@suse.cz +10 -9
#   input: Make gameport digital joysticks work on 2.6 and x86_64 again.
#   
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/joystick/a3d.c
#   2005/02/28 11:58:45+01:00 vojtech@suse.cz +2 -3
#   input: Make gameport digital joysticks work on 2.6 and x86_64 again.
#   
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/gameport/gameport.c
#   2005/02/28 11:58:45+01:00 vojtech@suse.cz +31 -3
#   input: Make gameport digital joysticks work on 2.6 and x86_64 again.
#   
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# ChangeSet
#   2005/02/28 08:48:22+01:00 vojtech@suse.cz 
#   input: Add more PnP IDs to i8042 PnP probe table. BIOS manufacturers
#          are very creative.
#   
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/serio/i8042-x86ia64io.h
#   2005/02/28 08:48:11+01:00 vojtech@suse.cz +6 -0
#   input: Add more PnP IDs to i8042 PnP probe table. BIOS manufacturers
#          are very creative.
#   
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# ChangeSet
#   2005/02/27 11:34:35-08:00 davem@nuts.davemloft.net 
#   [SPARC64]: Do the init_mm check inline in set_pte_at().
#   
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# include/asm-sparc64/pgtable.h
#   2005/02/27 11:33:59-08:00 davem@nuts.davemloft.net +8 -5
#   [SPARC64]: Do the init_mm check inline in set_pte_at().
# 
# arch/sparc64/mm/tlb.c
#   2005/02/27 11:33:59-08:00 davem@nuts.davemloft.net +2 -11
#   [SPARC64]: Do the init_mm check inline in set_pte_at().
# 
# ChangeSet
#   2005/02/26 20:51:23-08:00 davem@nuts.davemloft.net 
#   [MM]: Pass correct address down to bottom of page table iterators.
#   
#   Some routines, namely zeromap_pte_range, remap_pte_range,
#   change_pte_range, unmap_area_pte, and map_area_pte, were
#   using a chopped off address.  This causes bogus addresses
#   to be passed into set_pte_at() and friends, resulting
#   in missed TLB flushes and other nasties.
#   
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# mm/vmalloc.c
#   2005/02/26 20:50:16-08:00 davem@nuts.davemloft.net +13 -9
#   [MM]: Pass correct address down to bottom of page table iterators.
# 
# mm/mprotect.c
#   2005/02/26 20:50:16-08:00 davem@nuts.davemloft.net +10 -7
#   [MM]: Pass correct address down to bottom of page table iterators.
# 
# mm/memory.c
#   2005/02/26 20:50:16-08:00 davem@nuts.davemloft.net +7 -5
#   [MM]: Pass correct address down to bottom of page table iterators.
# 
# ChangeSet
#   2005/02/26 04:10:55-05:00 dcbw@redhat.com 
#   [PATCH] wireless: Make Atmel driver use SET_NETDEV_DEV
#   
#   Make the Atmel wireless driver use SET_NETDEV_DEV to get the correct
#   entries in sysfs.  Seems like somebody meant to do this but it got lost.
#   atmel_cs.c was previously fixed to pass in the correct struct device *
#   via handle_to_dev() but the driver never actually used it.
#   
#   Signed-off-by: Dan Williams <dcbw@redhat.com>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/wireless/atmel.c
#   2005/02/01 16:15:55-05:00 dcbw@redhat.com +2 -0
#   wireless: Make Atmel driver use SET_NETDEV_DEV
# 
# ChangeSet
#   2005/02/26 04:10:42-05:00 dcbw@redhat.com 
#   [PATCH] wireless: WEXT quality cleanups + max rssi
#   
#   (resend)
#   
#   Use correct maximum rssi level for at76c502e-type cards, and correct
#   values in the qual.updated field to more closely match the current
#   Wireless Extensions API.
#   
#   Signed-off-by: Dan Williams <dcbw@redhat.com>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/wireless/atmel.c
#   2005/02/01 16:25:53-05:00 dcbw@redhat.com +28 -11
#   wireless: WEXT quality cleanups + max rssi
# 
# ChangeSet
#   2005/02/26 04:10:29-05:00 dcbw@redhat.com 
#   [PATCH] wireless: Clean up firmware loading in
#   
#   (resend)
#   
#   Identify different firmware by enums, not strings, as we need to have
#   some integral firmware identifier for choosing maximum rssi values for
#   each different firmware type.  Consolidate the information about
#   firmware filenames and capabilities in the atmel module, not in atmel_cs
#   or atmel_pci.  Move common prototypes and firmware enum into new atmel.h
#   file.  The atmel_cs driver also thought that init_atmel_card() took "int
#   irq" as the first parameter, this is now fixed to be "unsigned short
#   irq".
#   
#   Signed-off-by: Dan Williams <dcbw@redhat.com>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/wireless/atmel.h
#   2005/01/30 18:33:31-05:00 dcbw@redhat.com +43 -0
#   wireless: Clean up firmware loading in
# 
# drivers/net/wireless/atmel_pci.c
#   2005/01/30 14:05:30-05:00 dcbw@redhat.com +2 -4
#   wireless: Clean up firmware loading in
# 
# drivers/net/wireless/atmel_cs.c
#   2005/01/30 14:05:08-05:00 dcbw@redhat.com +22 -26
#   wireless: Clean up firmware loading in
# 
# drivers/net/wireless/atmel.h
#   2005/01/30 18:33:31-05:00 dcbw@redhat.com +0 -0
#   BitKeeper file /garz/repo/netdev-2.6/atmel/drivers/net/wireless/atmel.h
# 
# drivers/net/wireless/atmel.c
#   2005/02/01 16:22:26-05:00 dcbw@redhat.com +45 -17
#   wireless: Clean up firmware loading in
# 
# ChangeSet
#   2005/02/26 04:04:17-05:00 rddunlap@osdl.org 
#   [PATCH] sb1000: reduce ioctl stack usage
#   
#   sb1000_dev_ioctl() (on i386) uses 824 bytes of stack space,
#   all due to overuse of inline functions.
#   By changing a few infrequently used functions to non-inline,
#   the stack usage is reduced to only 60 bytes.
#   Nothing in a fast path is changed.
#   
#   Signed-off-by: Randy Dunlap <rddunlap@osdl.org>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/sb1000.c
#   2005/01/30 20:49:27-05:00 rddunlap@osdl.org +10 -10
#   sb1000: reduce ioctl stack usage
# 
# ChangeSet
#   2005/02/26 04:00:31-05:00 hermes@gibson.dropbear.id.au 
#   [PATCH] Orinoco driver updates - cleanup PCI initialization
#   
#   As someone pointed out, pci_set_drvdata() belongs right at the
#   end of PCI initialization.  Correct this in the various PCI based
#   orinoco drivers.
#   
#   Signed-off-by: David Gibson <hermes@gibson.dropbear.id.au>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/wireless/orinoco_tmd.c
#   2005/02/24 23:45:33-05:00 hermes@gibson.dropbear.id.au +2 -1
#   Re: [6/14] Orinoco driver updates - cleanup PCI initialization
# 
# drivers/net/wireless/orinoco_plx.c
#   2005/02/24 23:45:13-05:00 hermes@gibson.dropbear.id.au +2 -1
#   Re: [6/14] Orinoco driver updates - cleanup PCI initialization
# 
# drivers/net/wireless/orinoco_pci.c
#   2005/02/24 23:44:50-05:00 hermes@gibson.dropbear.id.au +2 -1
#   Re: [6/14] Orinoco driver updates - cleanup PCI initialization
# 
# ChangeSet
#   2005/02/26 04:00:17-05:00 hermes@gibson.dropbear.id.au 
#   [PATCH] Orinoco driver updates - PCMCIA initialization cleanups
#   
#   The client_reg.Attributes field is no longer used.  Don't bother
#   setting it.
#   
#   Signed-off-by: David Gibson <hermes@gibson.dropbear.id.au>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/wireless/orinoco_cs.c
#   2005/02/24 23:52:56-05:00 hermes@gibson.dropbear.id.au +0 -1
#   Re: [8/14] Orinoco driver updates - PCMCIA initialization cleanups
# 
# ChangeSet
#   2005/02/26 09:01:13+01:00 vojtech@suse.cz 
#   input: Fix string formatting in joydump.
#   
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/joystick/joydump.c
#   2005/02/26 09:01:02+01:00 vojtech@suse.cz +12 -12
#   input: Fix string formatting in joydump.
#   
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# ChangeSet
#   2005/02/26 08:13:30+01:00 dtor_core@ameritech.net 
#   input: set gameport devices' bus so they can be bound to drivers.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/gameport/gameport.c
#   2005/02/26 08:13:19+01:00 dtor_core@ameritech.net +1 -0
#   input: set gameport devices' bus so they can be bound to drivers.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# ChangeSet
#   2005/02/25 16:36:06-08:00 davem@nuts.davemloft.net 
#   [MM]: Add 'pfn' arg to flush_cache_page().
#   
#   Based almost entirely upon a patch by Russell King.
#   
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# mm/rmap.c
#   2005/02/25 16:35:20-08:00 davem@nuts.davemloft.net +2 -2
#   [MM]: Add 'pfn' arg to flush_cache_page().
# 
# mm/memory.c
#   2005/02/25 16:35:20-08:00 davem@nuts.davemloft.net +2 -2
#   [MM]: Add 'pfn' arg to flush_cache_page().
# 
# mm/fremap.c
#   2005/02/25 16:35:20-08:00 davem@nuts.davemloft.net +1 -1
#   [MM]: Add 'pfn' arg to flush_cache_page().
# 
# include/asm-x86_64/cacheflush.h
#   2005/02/25 16:35:20-08:00 davem@nuts.davemloft.net +1 -1
#   [MM]: Add 'pfn' arg to flush_cache_page().
# 
# include/asm-v850/cacheflush.h
#   2005/02/25 16:35:20-08:00 davem@nuts.davemloft.net +1 -1
#   [MM]: Add 'pfn' arg to flush_cache_page().
# 
# include/asm-sparc64/cacheflush.h
#   2005/02/25 16:35:20-08:00 davem@nuts.davemloft.net +7 -7
#   [MM]: Add 'pfn' arg to flush_cache_page().
# 
# include/asm-sparc/cacheflush.h
#   2005/02/25 16:35:20-08:00 davem@nuts.davemloft.net +7 -7
#   [MM]: Add 'pfn' arg to flush_cache_page().
# 
# include/asm-sh64/cacheflush.h
#   2005/02/25 16:35:20-08:00 davem@nuts.davemloft.net +3 -3
#   [MM]: Add 'pfn' arg to flush_cache_page().
# 
# include/asm-sh/cpu-sh4/cacheflush.h
#   2005/02/25 16:35:20-08:00 davem@nuts.davemloft.net +1 -1
#   [MM]: Add 'pfn' arg to flush_cache_page().
# 
# include/asm-sh/cpu-sh3/cacheflush.h
#   2005/02/25 16:35:20-08:00 davem@nuts.davemloft.net +3 -3
#   [MM]: Add 'pfn' arg to flush_cache_page().
# 
# include/asm-sh/cpu-sh2/cacheflush.h
#   2005/02/25 16:35:20-08:00 davem@nuts.davemloft.net +2 -2
#   [MM]: Add 'pfn' arg to flush_cache_page().
# 
# include/asm-sh/cacheflush.h
#   2005/02/25 16:35:20-08:00 davem@nuts.davemloft.net +2 -2
#   [MM]: Add 'pfn' arg to flush_cache_page().
# 
# include/asm-s390/cacheflush.h
#   2005/02/25 16:35:20-08:00 davem@nuts.davemloft.net +1 -1
#   [MM]: Add 'pfn' arg to flush_cache_page().
# 
# include/asm-ppc64/cacheflush.h
#   2005/02/25 16:35:20-08:00 davem@nuts.davemloft.net +1 -1
#   [MM]: Add 'pfn' arg to flush_cache_page().
# 
# include/asm-ppc/cacheflush.h
#   2005/02/25 16:35:20-08:00 davem@nuts.davemloft.net +1 -1
#   [MM]: Add 'pfn' arg to flush_cache_page().
# 
# include/asm-parisc/cacheflush.h
#   2005/02/25 16:35:20-08:00 davem@nuts.davemloft.net +3 -3
#   [MM]: Add 'pfn' arg to flush_cache_page().
# 
# include/asm-mips/cacheflush.h
#   2005/02/25 16:35:20-08:00 davem@nuts.davemloft.net +2 -3
#   [MM]: Add 'pfn' arg to flush_cache_page().
# 
# include/asm-m68knommu/cacheflush.h
#   2005/02/25 16:35:20-08:00 davem@nuts.davemloft.net +1 -1
#   [MM]: Add 'pfn' arg to flush_cache_page().
# 
# include/asm-m68k/cacheflush.h
#   2005/02/25 16:35:20-08:00 davem@nuts.davemloft.net +7 -8
#   [MM]: Add 'pfn' arg to flush_cache_page().
# 
# include/asm-m32r/cacheflush.h
#   2005/02/25 16:35:20-08:00 davem@nuts.davemloft.net +3 -3
#   [MM]: Add 'pfn' arg to flush_cache_page().
# 
# include/asm-ia64/cacheflush.h
#   2005/02/25 16:35:20-08:00 davem@nuts.davemloft.net +1 -1
#   [MM]: Add 'pfn' arg to flush_cache_page().
# 
# include/asm-i386/cacheflush.h
#   2005/02/25 16:35:20-08:00 davem@nuts.davemloft.net +1 -1
#   [MM]: Add 'pfn' arg to flush_cache_page().
# 
# include/asm-h8300/cacheflush.h
#   2005/02/25 16:35:20-08:00 davem@nuts.davemloft.net +1 -1
#   [MM]: Add 'pfn' arg to flush_cache_page().
# 
# include/asm-frv/cacheflush.h
#   2005/02/25 16:35:20-08:00 davem@nuts.davemloft.net +1 -1
#   [MM]: Add 'pfn' arg to flush_cache_page().
# 
# include/asm-cris/cacheflush.h
#   2005/02/25 16:35:20-08:00 davem@nuts.davemloft.net +1 -1
#   [MM]: Add 'pfn' arg to flush_cache_page().
# 
# include/asm-arm26/cacheflush.h
#   2005/02/25 16:35:20-08:00 davem@nuts.davemloft.net +1 -1
#   [MM]: Add 'pfn' arg to flush_cache_page().
# 
# include/asm-arm/cacheflush.h
#   2005/02/25 16:35:20-08:00 davem@nuts.davemloft.net +8 -8
#   [MM]: Add 'pfn' arg to flush_cache_page().
# 
# include/asm-alpha/cacheflush.h
#   2005/02/25 16:35:20-08:00 davem@nuts.davemloft.net +1 -1
#   [MM]: Add 'pfn' arg to flush_cache_page().
# 
# fs/binfmt_elf.c
#   2005/02/25 16:35:19-08:00 davem@nuts.davemloft.net +1 -1
#   [MM]: Add 'pfn' arg to flush_cache_page().
# 
# arch/sparc/mm/srmmu.c
#   2005/02/25 16:35:19-08:00 davem@nuts.davemloft.net +1 -2
#   [MM]: Add 'pfn' arg to flush_cache_page().
# 
# arch/sh64/mm/cache.c
#   2005/02/25 16:35:19-08:00 davem@nuts.davemloft.net +4 -24
#   [MM]: Add 'pfn' arg to flush_cache_page().
# 
# arch/sh/mm/cache-sh7705.c
#   2005/02/25 16:35:19-08:00 davem@nuts.davemloft.net +2 -18
#   [MM]: Add 'pfn' arg to flush_cache_page().
# 
# arch/sh/mm/cache-sh4.c
#   2005/02/25 16:35:19-08:00 davem@nuts.davemloft.net +11 -30
#   [MM]: Add 'pfn' arg to flush_cache_page().
# 
# arch/mips/mm/cache.c
#   2005/02/25 16:35:19-08:00 davem@nuts.davemloft.net +1 -1
#   [MM]: Add 'pfn' arg to flush_cache_page().
# 
# arch/mips/mm/c-tx39.c
#   2005/02/25 16:35:19-08:00 davem@nuts.davemloft.net +1 -2
#   [MM]: Add 'pfn' arg to flush_cache_page().
# 
# arch/mips/mm/c-sb1.c
#   2005/02/25 16:35:19-08:00 davem@nuts.davemloft.net +6 -5
#   [MM]: Add 'pfn' arg to flush_cache_page().
# 
# arch/mips/mm/c-r4k.c
#   2005/02/25 16:35:19-08:00 davem@nuts.davemloft.net +1 -2
#   [MM]: Add 'pfn' arg to flush_cache_page().
# 
# arch/mips/mm/c-r3k.c
#   2005/02/25 16:35:19-08:00 davem@nuts.davemloft.net +1 -2
#   [MM]: Add 'pfn' arg to flush_cache_page().
# 
# arch/arm/mm/flush.c
#   2005/02/25 16:35:19-08:00 davem@nuts.davemloft.net +1 -1
#   [MM]: Add 'pfn' arg to flush_cache_page().
# 
# arch/arm/mm/fault-armv.c
#   2005/02/25 16:35:19-08:00 davem@nuts.davemloft.net +2 -2
#   [MM]: Add 'pfn' arg to flush_cache_page().
# 
# Documentation/cachetlb.txt
#   2005/02/25 16:35:19-08:00 davem@nuts.davemloft.net +9 -3
#   [MM]: Add 'pfn' arg to flush_cache_page().
# 
# ChangeSet
#   2005/02/25 15:48:28-08:00 khali@linux-fr.org 
#   [PATCH] PCI: One more Asus SMBus quirk
#   
#   One more Asus laptop requiring the SMBus quirk (W1N model).
#   
#   Signed-off-by: Jean Delvare <khali@linux-fr.org>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/pci/quirks.c
#   2005/02/14 11:10:24-08:00 khali@linux-fr.org +1 -0
#   PCI: One more Asus SMBus quirk
# 
# ChangeSet
#   2005/02/25 15:48:12-08:00 alexn@dsv.su.se 
#   [PATCH] PCI: fix hotplug double free
#   
#   With the brackets missed out func could be freed twice.
#   
#   Found by Coverity tool
#   
#   Signed-off-by: Alexander Nyberg <alexn@dsv.su.se>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/pci/hotplug/pciehp_ctrl.c
#   2005/02/23 01:26:22-08:00 alexn@dsv.su.se +2 -1
#   PCI: fix hotplug double free
# 
# ChangeSet
#   2005/02/25 15:47:53-08:00 akpm@osdl.org 
#   [PATCH] PCI: tone down pci=routeirq message
#   
#   From: Bjorn Helgaas <bjorn.helgaas@hp.com>
#   
#   Tone down the message about using "pci=routeirq".  I do still get a few
#   reports, but most are now prompted just by the fact that my email address
#   appears in dmesg in an "error-type" message.
#   
#   Signed-off-by: Bjorn Helgaas <bjorn.helgaas@hp.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# arch/ia64/pci/pci.c
#   2005/02/22 18:53:24-08:00 akpm@osdl.org +3 -13
#   PCI: tone down pci=routeirq message
# 
# arch/i386/pci/acpi.c
#   2005/02/22 18:53:24-08:00 akpm@osdl.org +4 -13
#   PCI: tone down pci=routeirq message
# 
# ChangeSet
#   2005/02/25 14:36:10-08:00 benh@kernel.crashing.org 
#   [PATCH] PCI: Apple PCI IDs update
#   
#   please sent that to Andrew/Linus in your next batch for after 2.6.11,
#   those new IDs will be needed for support of the new iMac G5.
#   
#   The changes to pci.ids match the changes already submitted to the web
#   database.
#   
#   From: Benjamin Herrenschmidt <benh@kernel.crashing.org>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# include/linux/pci_ids.h
#   2005/02/17 19:26:36-08:00 benh@kernel.crashing.org +3 -0
#   PCI: Apple PCI IDs update
# 
# ChangeSet
#   2005/02/25 21:21:03+01:00 vojtech@suse.cz 
#   input: After testing on real world hardware, it's obvious we can't trust
#          ACPIPnP nor PnPBIOS to properly report the existence of a keyboard
#          and mouse port in all cases. Some BIOSes hide the ports if no mouse
#          or keyboard is connected, causing trouble with eg. KVM switches.
#   
#          The i8042 driver now does read-only probing first, which should
#          not cause any problems even if an i8042 controller really is not
#          present.
#   
#          However, on IA64 we still need to trust ACPI, since legacy-free hardware
#          is common there and invalid port accesses cause exceptions.
#   
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/serio/i8042-x86ia64io.h
#   2005/02/25 21:20:51+01:00 vojtech@suse.cz +6 -7
#   input: After testing on real world hardware, it's obvious we can't trust
#          ACPIPnP nor PnPBIOS to properly report the existence of a keyboard
#          and mouse port in all cases. Some BIOSes hide the ports if no mouse
#          or keyboard is connected, causing trouble with eg. KVM switches.
#   
#          The i8042 driver now does read-only probing first, which should
#          not cause any problems even if an i8042 controller really is not
#          present.
#   
#          However, on IA64 we still need to trust ACPI, since legacy-free hardware
#          is common there and invalid port accesses cause exceptions.
#   
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# ChangeSet
#   2005/02/25 08:26:11-08:00 gregkh@suse.de 
#   PCI: remove pci_find_device usage from pci sysfs code.
#   
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/pci/pci-sysfs.c
#   2005/02/25 08:25:55-08:00 gregkh@suse.de +1 -1
#   PCI: remove pci_find_device usage from pci sysfs code.
#   
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# ChangeSet
#   2005/02/25 15:27:54+01:00 vojtech@suse.cz 
#   input: Add a missing brace in hid-core.c
#   
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/usb/input/hid-core.c
#   2005/02/25 15:27:48+01:00 vojtech@suse.cz +1 -1
#   input: Add a missing brace in hid-core.c
#   
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# ChangeSet
#   2005/02/25 08:17:35+01:00 vojtech@suse.cz 
#   input: Remove filtering of duplicate events in hid-core. HIDDEV wants them,
#          and hid-input doesn't care, since input does the filtering anyway.
#   
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/usb/input/hid-core.c
#   2005/02/25 08:17:23+01:00 vojtech@suse.cz +1 -10
#   input: Remove filtering of duplicate events in hid-core. HIDDEV wants them,
#          and hid-input doesn't care, since input does the filtering anyway.
#   
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# ChangeSet
#   2005/02/25 08:06:21+01:00 dtor_core@ameritech.net 
#   input: atkbd - "scroll" is a per-device attribute, don't use global
#          flag in interrupt handler.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/keyboard/atkbd.c
#   2005/02/25 08:06:09+01:00 dtor_core@ameritech.net +1 -1
#   input: atkbd - "scroll" is a per-device attribute, don't use global
#          flag in interrupt handler.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# ChangeSet
#   2005/02/24 22:02:25+01:00 vojtech@suse.cz 
#   input: Disable scancode event generation in hid-core.c, as it can
#          cause floods of events when devices don't honor the set_idle()
#          call or report noise on absolute values, until a solution for
#          this is found.
#   
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/usb/input/hid-input.c
#   2005/02/24 22:02:13+01:00 vojtech@suse.cz +0 -4
#   input: Disable scancode event generation in hid-core.c, as it can
#          cause floods of events when devices don't honor the set_idle()
#          call or report noise on absolute values, until a solution for
#          this is found.
#   
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# ChangeSet
#   2005/02/24 21:54:53+01:00 vojtech@suse.cz 
#   input: Print a warning message when PnP fails to find an i8042
#          controller.
#   
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/serio/i8042-x86ia64io.h
#   2005/02/24 21:54:40+01:00 vojtech@suse.cz +43 -42
#   input: Print a warning message when PnP fails to find an i8042
#          controller.
#   
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# ChangeSet
#   2005/02/24 21:38:18+01:00 vojtech@suse.cz 
#   input: Make the i8042 PnP detection even more BIOS and CONFIG-proof.
#          This now should work with almost any BIOS and kernel config
#          combination.
#   
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/serio/i8042-x86ia64io.h
#   2005/02/24 21:38:07+01:00 vojtech@suse.cz +75 -66
#   input: Make the i8042 PnP detection even more BIOS and CONFIG-proof.
#          This now should work with almost any BIOS and kernel config
#          combination.
#   
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# ChangeSet
#   2005/02/24 14:52:48-05:00 jgarzik@pobox.com 
#   [libata ahci] Print out port id on error messages
#   
#   Pointed out by Justin Cormack, Brett Russ, and others.
# 
# drivers/scsi/ahci.c
#   2005/02/24 14:52:41-05:00 jgarzik@pobox.com +1 -1
#   [libata ahci] Print out port id on error messages
#   
#   Pointed out by Justin Cormack, Brett Russ, and others.
# 
# ChangeSet
#   2005/02/24 20:37:21+01:00 vojtech@suse.cz 
#   input: Separate dualpoint and passthrough flags in ALPS driver.
#          Some non-dualpoint devices need passthrough enabled.
#   
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/mouse/alps.c
#   2005/02/24 20:37:08+01:00 vojtech@suse.cz +9 -8
#   input: Separate dualpoint and passthrough flags in ALPS driver.
#          Some non-dualpoint devices need passthrough enabled.
#   
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# ChangeSet
#   2005/02/24 11:25:26-08:00 ajgrothe@yahoo.com 
#   [CRYPTO]: Add Tiger digest algorithms.
#   
#   Signed-off-by: James Morris <jmorris@redhat.com>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# crypto/tcrypt.h
#   2005/02/24 11:24:22-08:00 ajgrothe@yahoo.com +131 -0
#   [CRYPTO]: Add Tiger digest algorithms.
# 
# crypto/tcrypt.c
#   2005/02/24 11:24:22-08:00 ajgrothe@yahoo.com +16 -0
#   [CRYPTO]: Add Tiger digest algorithms.
# 
# crypto/Makefile
#   2005/02/24 11:24:22-08:00 ajgrothe@yahoo.com +1 -0
#   [CRYPTO]: Add Tiger digest algorithms.
# 
# crypto/Kconfig
#   2005/02/24 11:24:22-08:00 ajgrothe@yahoo.com +13 -0
#   [CRYPTO]: Add Tiger digest algorithms.
# 
# Documentation/crypto/api-intro.txt
#   2005/02/24 11:24:22-08:00 ajgrothe@yahoo.com +3 -0
#   [CRYPTO]: Add Tiger digest algorithms.
# 
# crypto/tgr192.c
#   2005/02/24 11:24:18-08:00 ajgrothe@yahoo.com +735 -0
#   [CRYPTO]: Add Tiger digest algorithms.
# 
# crypto/tgr192.c
#   2005/02/24 11:24:18-08:00 ajgrothe@yahoo.com +0 -0
#   BitKeeper file /disk1/BK/net-2.6.12/crypto/tgr192.c
# 
# ChangeSet
#   2005/02/24 20:12:05+01:00 vojtech@suse.cz 
#   input: Fix usage of *_MAX macros. Check keycode in KDIOSKEYCODE and
#          EVIOCSKEYCODE macros to be <= KEY_MAX. Check off-by one mistakes
#          in keycodemax usage. There was a lot of potential for overwriting
#          memory. Also enlarge NR_KEYS to 256 while we're at it.
#   
#   Found-by: Georgi Guninski <guninski@guninski.com>
#   Initial-patch-by: Linus Torvalds <torvalds@osdl.org>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# include/linux/keyboard.h
#   2005/02/24 20:11:54+01:00 vojtech@suse.cz +1 -1
#   input: Fix usage of *_MAX macros. Check keycode in KDIOSKEYCODE and
#          EVIOCSKEYCODE macros to be <= KEY_MAX. Check off-by one mistakes
#          in keycodemax usage. There was a lot of potential for overwriting
#          memory. Also enlarge NR_KEYS to 256 while we're at it.
#   
#   Found-by: Georgi Guninski <guninski@guninski.com>
#   Initial-patch-by: Linus Torvalds <torvalds@osdl.org>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# include/linux/joystick.h
#   2005/02/24 20:11:54+01:00 vojtech@suse.cz +4 -4
#   input: Fix usage of *_MAX macros. Check keycode in KDIOSKEYCODE and
#          EVIOCSKEYCODE macros to be <= KEY_MAX. Check off-by one mistakes
#          in keycodemax usage. There was a lot of potential for overwriting
#          memory. Also enlarge NR_KEYS to 256 while we're at it.
#   
#   Found-by: Georgi Guninski <guninski@guninski.com>
#   Initial-patch-by: Linus Torvalds <torvalds@osdl.org>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# include/linux/input.h
#   2005/02/24 20:11:54+01:00 vojtech@suse.cz +1 -1
#   input: Fix usage of *_MAX macros. Check keycode in KDIOSKEYCODE and
#          EVIOCSKEYCODE macros to be <= KEY_MAX. Check off-by one mistakes
#          in keycodemax usage. There was a lot of potential for overwriting
#          memory. Also enlarge NR_KEYS to 256 while we're at it.
#   
#   Found-by: Georgi Guninski <guninski@guninski.com>
#   Initial-patch-by: Linus Torvalds <torvalds@osdl.org>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/misc/uinput.c
#   2005/02/24 20:11:54+01:00 vojtech@suse.cz +3 -5
#   input: Fix usage of *_MAX macros. Check keycode in KDIOSKEYCODE and
#          EVIOCSKEYCODE macros to be <= KEY_MAX. Check off-by one mistakes
#          in keycodemax usage. There was a lot of potential for overwriting
#          memory. Also enlarge NR_KEYS to 256 while we're at it.
#   
#   Found-by: Georgi Guninski <guninski@guninski.com>
#   Initial-patch-by: Linus Torvalds <torvalds@osdl.org>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/joydev.c
#   2005/02/24 20:11:54+01:00 vojtech@suse.cz +13 -13
#   input: Fix usage of *_MAX macros. Check keycode in KDIOSKEYCODE and
#          EVIOCSKEYCODE macros to be <= KEY_MAX. Check off-by one mistakes
#          in keycodemax usage. There was a lot of potential for overwriting
#          memory. Also enlarge NR_KEYS to 256 while we're at it.
#   
#   Found-by: Georgi Guninski <guninski@guninski.com>
#   Initial-patch-by: Linus Torvalds <torvalds@osdl.org>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/evdev.c
#   2005/02/24 20:11:54+01:00 vojtech@suse.cz +3 -2
#   input: Fix usage of *_MAX macros. Check keycode in KDIOSKEYCODE and
#          EVIOCSKEYCODE macros to be <= KEY_MAX. Check off-by one mistakes
#          in keycodemax usage. There was a lot of potential for overwriting
#          memory. Also enlarge NR_KEYS to 256 while we're at it.
#   
#   Found-by: Georgi Guninski <guninski@guninski.com>
#   Initial-patch-by: Linus Torvalds <torvalds@osdl.org>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/char/keyboard.c
#   2005/02/24 20:11:54+01:00 vojtech@suse.cz +3 -1
#   input: Fix usage of *_MAX macros. Check keycode in KDIOSKEYCODE and
#          EVIOCSKEYCODE macros to be <= KEY_MAX. Check off-by one mistakes
#          in keycodemax usage. There was a lot of potential for overwriting
#          memory. Also enlarge NR_KEYS to 256 while we're at it.
#   
#   Found-by: Georgi Guninski <guninski@guninski.com>
#   Initial-patch-by: Linus Torvalds <torvalds@osdl.org>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# ChangeSet
#   2005/02/24 10:59:51-08:00 herbert@gondor.apana.org.au 
#   [IXGB]: Check skb_header_cloned for TSO packets.
#   
#   Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# drivers/net/ixgb/ixgb_main.c
#   2005/02/24 10:59:26-08:00 herbert@gondor.apana.org.au +18 -4
#   [IXGB]: Check skb_header_cloned for TSO packets.
#   
#   Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# ChangeSet
#   2005/02/24 15:36:55+01:00 vojtech@suse.cz 
#   input: Make ALPS protocol synchronization dependent on
#          protocol variant to enhance robustness.
#   
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/mouse/alps.h
#   2005/02/24 15:36:49+01:00 vojtech@suse.cz +11 -5
#   input: Make ALPS protocol synchronization dependent on
#          protocol variant to enhance robustness.
#   
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/mouse/alps.c
#   2005/02/24 15:36:49+01:00 vojtech@suse.cz +45 -48
#   input: Make ALPS protocol synchronization dependent on
#          protocol variant to enhance robustness.
#   
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# ChangeSet
#   2005/02/24 15:06:24+01:00 vojtech@suse.cz 
#   input: Fix i8042's interactions with ACPI. Only believe what ACPI
#          tells us if it is enabled, if is PnP enabled, and if is
#          ACPIPnP enabled. It will still lie to us, but it won't be
#          too bad.
#   
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/serio/i8042-x86ia64io.h
#   2005/02/24 15:06:17+01:00 vojtech@suse.cz +57 -28
#   input: Fix i8042's interactions with ACPI. Only believe what ACPI
#          tells us if it is enabled, if is PnP enabled, and if is
#          ACPIPnP enabled. It will still lie to us, but it won't be
#          too bad.
#   
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# ChangeSet
#   2005/02/24 13:20:20+01:00 vojtech@suse.cz 
#   Merge
# 
# drivers/input/mouse/alps.c
#   2005/02/24 13:20:19+01:00 vojtech@suse.cz +0 -0
#   SCCS merged
# 
# ChangeSet
#   2005/02/24 12:44:37+01:00 vojtech@suse.cz 
#   input: Update kernel documentation to reflect the
#          i8042.noacpi -> i8042.nopnp change.
#   
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# Documentation/kernel-parameters.txt
#   2005/02/24 12:44:31+01:00 vojtech@suse.cz +2 -2
#   input: Update kernel documentation to reflect the
#          i8042.noacpi -> i8042.nopnp change.
#   
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# ChangeSet
#   2005/02/24 11:31:55+01:00 vojtech@suse.cz 
#   input: Workaround in i8042 for PnP BIOS reporting incorrect command
#          register address. If the address is in the standard range,
#          and a non-standard number is reported, we ignore it and use
#          the default.
#   
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/serio/i8042-x86ia64io.h
#   2005/02/24 11:31:49+01:00 vojtech@suse.cz +14 -6
#   input: Workaround in i8042 for PnP BIOS reporting incorrect command
#          register address. If the address is in the standard range,
#          and a non-standard number is reported, we ignore it and use
#          the default.
#   
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# ChangeSet
#   2005/02/24 10:40:24+01:00 dtor_core@ameritech.net 
#   Input: fix identation in PID driver.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/usb/input/pid.h
#   2005/02/24 10:40:18+01:00 dtor_core@ameritech.net +14 -14
#   Input: fix identation in PID driver.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/usb/input/pid.c
#   2005/02/24 10:40:18+01:00 dtor_core@ameritech.net +112 -114
#   Input: fix identation in PID driver.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# ChangeSet
#   2005/02/24 10:39:32+01:00 vojtech@suse.cz 
#   input: Rename hid_find_field to hidinput_find_field to
#          match the naming convention in hid-input
#   
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz> 
# 
# drivers/usb/input/hid-input.c
#   2005/02/24 10:39:25+01:00 vojtech@suse.cz +2 -2
#   input: Rename hid_find_field to hidinput_find_field to
#          match the naming convention in hid-input
#   
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz> 
# 
# ChangeSet
#   2005/02/24 10:31:36+01:00 dtor_core@ameritech.net 
#   input: Fix compilation warning in PID driver and generally
#          repair force feedback effect erase routine that could
#          never have worked.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/usb/input/pid.c
#   2005/02/24 10:31:29+01:00 dtor_core@ameritech.net +7 -15
#   input: Fix compilation warning in PID driver and generally
#          repair force feedback effect erase routine that could
#          never have worked.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/usb/input/hid.h
#   2005/02/24 10:31:29+01:00 dtor_core@ameritech.net +1 -1
#   input: Fix compilation warning in PID driver and generally
#          repair force feedback effect erase routine that could
#          never have worked.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/usb/input/hid-core.c
#   2005/02/24 10:31:29+01:00 dtor_core@ameritech.net +3 -3
#   input: Fix compilation warning in PID driver and generally
#          repair force feedback effect erase routine that could
#          never have worked.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# ChangeSet
#   2005/02/24 10:20:01+01:00 dtor_core@ameritech.net 
#   input: Fix sermouse not to call serio_open() twice.
#          Bug introduced in last serio update.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/mouse/sermouse.c
#   2005/02/24 10:19:54+01:00 dtor_core@ameritech.net +1 -1
#   input: Fix sermouse not to call serio_open() twice.
#          Bug introduced in last serio update.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# ChangeSet
#   2005/02/24 10:18:37+01:00 dtor_core@ameritech.net 
#   input: adjust file2alias utility to export aliases for
#          serio drivers (serio:tyNprNidNexN).
#          Move serio_device_id from serio.h to mod_devicetable.h
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# scripts/mod/file2alias.c
#   2005/02/24 10:18:30+01:00 dtor_core@ameritech.net +22 -1
#   input: adjust file2alias utility to export aliases for
#          serio drivers (serio:tyNprNidNexN).
#          Move serio_device_id from serio.h to mod_devicetable.h
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# include/linux/serio.h
#   2005/02/24 10:18:30+01:00 dtor_core@ameritech.net +1 -9
#   input: adjust file2alias utility to export aliases for
#          serio drivers (serio:tyNprNidNexN).
#          Move serio_device_id from serio.h to mod_devicetable.h
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# include/linux/mod_devicetable.h
#   2005/02/24 10:18:30+01:00 dtor_core@ameritech.net +10 -0
#   input: adjust file2alias utility to export aliases for
#          serio drivers (serio:tyNprNidNexN).
#          Move serio_device_id from serio.h to mod_devicetable.h
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# ChangeSet
#   2005/02/24 10:04:38+01:00 vojtech@suse.cz 
#   input: Add support for less usual ALPS touchpads, rearrange code,
#          separate touchpoint/passthrough into its own input device.
#   
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/mouse/alps.h
#   2005/02/24 10:04:32+01:00 vojtech@suse.cz +6 -2
#   input: Add support for less usual ALPS touchpads, rearrange code,
#          separate touchpoint/passthrough into its own input device.
#   
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/mouse/alps.c
#   2005/02/24 10:04:32+01:00 vojtech@suse.cz +141 -121
#   input: Add support for less usual ALPS touchpads, rearrange code,
#          separate touchpoint/passthrough into its own input device.
#   
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# ChangeSet
#   2005/02/24 01:00:31-05:00 romieu@fr.zoreil.com 
#   [PATCH] strip: use of netdev_priv
#   
#   Signed-off-by: Francois Romieu <romieu@fr.zoreil.com>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/wireless/strip.c
#   2005/02/13 18:11:09-05:00 romieu@fr.zoreil.com +8 -8
#   strip: use of netdev_priv
# 
# ChangeSet
#   2005/02/24 00:33:29-05:00 tklauser@nuerscht.ch 
#   [PATCH] drivers/scsi/ahci: Use the DMA_{64,32}BIT_MASK constants
#   
#   Use the DMA_{64,32}BIT_MASK constants from dma-mapping.h
#   when calling pci_set_dma_mask() or pci_set_consistent_dma_mask()
#   See http://marc.theaimsgroup.com/?t=108001993000001&r=1&w=2 for details
#   
#   Signed-off-by: Tobias Klauser <tklauser@nuerscht.ch>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/scsi/ahci.c
#   2005/02/16 15:19:53-05:00 tklauser@nuerscht.ch +5 -5
#   drivers/scsi/ahci: Use the DMA_{64,32}BIT_MASK constants
# 
# ChangeSet
#   2005/02/24 00:33:15-05:00 tklauser@nuerscht.ch 
#   [PATCH] drivers/scsi/sata_vsc: Use the DMA_{64,32}BIT_MASK constants
#   
#   Use the DMA_{64,32}BIT_MASK constants from dma-mapping.h
#   when calling pci_set_dma_mask() or pci_set_consistent_dma_mask()
#   See http://marc.theaimsgroup.com/?t=108001993000001&r=1&w=2 for details
#   
#   Signed-off-by: Tobias Klauser <tklauser@nuerscht.ch>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/scsi/sata_vsc.c
#   2005/02/16 15:25:01-05:00 tklauser@nuerscht.ch +2 -2
#   drivers/scsi/sata_vsc: Use the DMA_{64,32}BIT_MASK constants
# 
# ChangeSet
#   2005/02/24 00:25:36-05:00 mlord@pobox.com 
#   [libata qstor] minor update per LKML comments
#   
#   * use __le{32,64}
#   * use DMA_{32,64}BIT_MASK
# 
# drivers/scsi/sata_qstor.c
#   2005/02/24 00:25:30-05:00 mlord@pobox.com +10 -10
#   [libata qstor] minor update per LKML comments
#   
#   * use __le{32,64}
#   * use DMA_{32,64}BIT_MASK
# 
# ChangeSet
#   2005/02/24 00:17:17-05:00 viro@parcelfarce.linux.theplanet.co.uk 
#   [PATCH] smc91x iomem annotations
#   
#   	usual iomem annotations;
#   Signed-off-by: Al Viro <viro@parcelfarce.linux.theplanet.co.uk>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/smc91x.c
#   2005/02/15 13:38:10-05:00 viro@parcelfarce.linux.theplanet.co.uk +41 -33
#   smc91x iomem annotations
# 
# ChangeSet
#   2005/02/24 00:12:34-05:00 jgarzik@pobox.com 
#   Merge pobox.com:/garz/repo/linux-2.6
#   into pobox.com:/garz/repo/netdev-2.6/smc91x
# 
# arch/arm/mach-pxa/lubbock.c
#   2005/02/24 00:12:31-05:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# ChangeSet
#   2005/02/23 23:56:56-05:00 jgarzik@pobox.com 
#   Merge bk://dfarnsworth.bkbits.net/linux-2.5-mv643xx-enet
#   into pobox.com:/garz/repo/netdev-2.6/mv643xx
# 
# include/linux/mv643xx.h
#   2005/02/23 23:56:53-05:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# ChangeSet
#   2005/02/23 23:46:03-05:00 jgarzik@pobox.com 
#   Merge pobox.com:/garz/repo/linux-2.6
#   into pobox.com:/garz/repo/netdev-2.6/mv643xx
# 
# include/linux/mv643xx.h
#   2005/02/23 23:46:00-05:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# ChangeSet
#   2005/02/23 23:39:39-05:00 hermes@gibson.dropbear.id.au 
#   [PATCH] Orinoco driver updates - update version and changelog
#   
#   Previous patches have brought the in-kernel orinoco driver roughly to
#   parity with version 0.14alpha2 from out-of-tree.  Update the version
#   number and changelog accordingly.
#   
#   Signed-off-by: David Gibson <hermes@gibson.dropbear.id.au>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/wireless/orinoco.h
#   2005/02/23 22:51:02-05:00 hermes@gibson.dropbear.id.au +1 -1
#   Orinoco driver updates - update version and changelog
# 
# drivers/net/wireless/orinoco.c
#   2005/02/23 22:51:02-05:00 hermes@gibson.dropbear.id.au +23 -0
#   Orinoco driver updates - update version and changelog
# 
# ChangeSet
#   2005/02/23 23:39:26-05:00 hermes@gibson.dropbear.id.au 
#   [PATCH] Orinoco driver updates - update firmware detection
#   
#   Update firmware detection code.  This will now reliably detect
#   Intersil firmwares past verison 1.x, a serious flaw in the previous
#   code.  It cleans up the code, and reduces the size of the private
#   structure by using single bits for the various firmware feature flags.
#   
#   Signed-off-by: David Gibson <hermes@gibson.dropbear.id.au>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/wireless/orinoco_pci.c
#   2005/02/23 23:39:20-05:00 hermes@gibson.dropbear.id.au +0 -4
#   Orinoco driver updates - update firmware detection
# 
# drivers/net/wireless/orinoco.h
#   2005/02/23 23:39:20-05:00 hermes@gibson.dropbear.id.au +20 -11
#   Orinoco driver updates - update firmware detection
# 
# drivers/net/wireless/orinoco.c
#   2005/02/23 23:39:20-05:00 hermes@gibson.dropbear.id.au +64 -27
#   Orinoco driver updates - update firmware detection
# 
# ChangeSet
#   2005/02/23 23:39:14-05:00 hermes@gibson.dropbear.id.au 
#   [PATCH] Orinoco driver updates - WEP updates
#   
#   Updates to the WEP configuration code.  This adds support for shared
#   key authentication on Agere firmwares.  It also adds support (in some
#   cases) for changing the WEP keys without disabling the MAC port (thus
#   triggering a reassociation by the firmware).  This is needed by 802.1x
#   implementations, although it's not clear if the code so far is
#   sufficient to allow working 802.1x.
#   
#   Signed-off-by: David Gibson <hermes@gibson.dropbear.id.au>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/wireless/orinoco.c
#   2005/02/23 22:50:57-05:00 hermes@gibson.dropbear.id.au +106 -95
#   Orinoco driver updates - WEP updates
# 
# ChangeSet
#   2005/02/23 23:39:03-05:00 hermes@gibson.dropbear.id.au 
#   [PATCH] Orinoco driver updates - delay Tx wake
#   
#   Delay netif_wake_queue() until the packet has actually been
#   transmitted, rather than just when the firmware has copied it into its
#   internal buffers.  This seems to prevent problems on some Intersil
#   firmware versions (I suspect the problems were caused by the
#   firmware's buffers filling up).
#   
#   Signed-off-by: David Gibson <hermes@gibson.dropbear.id.au>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/wireless/orinoco.c
#   2005/02/17 20:58:09-05:00 hermes@gibson.dropbear.id.au +3 -2
#   Orinoco driver updates - delay Tx wake
# 
# ChangeSet
#   2005/02/23 23:38:50-05:00 hermes@gibson.dropbear.id.au 
#   [PATCH] Orinoco driver updates - prohibit IBSS with no ESSID
#   
#   Remove has_ibss_any flag and never set the CREATEIBSS RID when the
#   ESSID is empty.  Too many firmware break if we do.
#   
#   Signed-off-by: David Gibson <hermes@gibson.dropbear.id.au>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/wireless/orinoco.h
#   2005/02/23 22:50:53-05:00 hermes@gibson.dropbear.id.au +1 -1
#   Orinoco driver updates - prohibit IBSS with no ESSID
# 
# drivers/net/wireless/orinoco.c
#   2005/02/23 22:50:53-05:00 hermes@gibson.dropbear.id.au +14 -11
#   Orinoco driver updates - prohibit IBSS with no ESSID
# 
# ChangeSet
#   2005/02/23 23:37:56-05:00 hermes@gibson.dropbear.id.au 
#   [PATCH] Orinoco driver updates - update is_ethersnap()
#   
#   Make the is_ethersnap() function take a void * rather than a pointer
#   to the internal header structure.  This makes more logical sense and
#   reduces dependencies between different parts of the code.
#   
#   Signed-off-by: David Gibson <hermes@gibson.dropbear.id.au>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/wireless/orinoco.c
#   2005/02/23 22:50:50-05:00 hermes@gibson.dropbear.id.au +5 -3
#   Orinoco driver updates - update is_ethersnap()
# 
# ChangeSet
#   2005/02/23 23:37:45-05:00 hermes@gibson.dropbear.id.au 
#   [PATCH] Orinoco driver updates - PCMCIA initialization cleanups
#   
#   Cleanup the various bits of initialization code for PCMCIA / PC-Card
#   orinoco devices.  This includes one important bugfix where we could
#   fail to take the lock in some circumstances.
#   
#   Signed-off-by: David Gibson <hermes@gibson.dropbear.id.au>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/wireless/orinoco_cs.c
#   2005/02/17 20:11:49-05:00 hermes@gibson.dropbear.id.au +14 -22
#   Orinoco driver updates - PCMCIA initialization cleanups
# 
# ChangeSet
#   2005/02/23 23:37:33-05:00 hermes@gibson.dropbear.id.au 
#   [PATCH] Orinoco driver updates - use modern module_parm()
#   
#   Add descrptions to module parameters in the orinoco driver, and also
#   add permissions to allow them to be exported in sysfs.
#   
#   Signed-off-by: David Gibson <hermes@gibson.dropbear.id.au>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/wireless/orinoco.c
#   2005/02/09 21:24:03-05:00 hermes@gibson.dropbear.id.au +4 -2
#   Orinoco driver updates - use modern module_parm()
# 
# ChangeSet
#   2005/02/23 23:37:21-05:00 hermes@gibson.dropbear.id.au 
#   [PATCH] Orinoco driver updates - cleanup PCI initialization
#   
#   Update the initialization code in the various PCI incarnations of the
#   orinoco driver.  This applies similar initialization and shutdown
#   cleanups to the orinoco_pci, orinoco_plx and orinoco_tmd drivers.  It
#   also adds COR reset support to the orinoco_plx and orinoco_tmd
#   drivers, improves PCI power management support in the orinoco_pci
#   driver and adds a couple of extra supported cards to the ID tables.
#   
#   Signed-off-by: David Gibson <hermes@gibson.dropbear.id.au>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/wireless/orinoco_tmd.c
#   2004/11/04 22:37:35-05:00 hermes@gibson.dropbear.id.au +87 -52
#   Orinoco driver updates - cleanup PCI initialization
# 
# drivers/net/wireless/orinoco_plx.c
#   2004/11/04 22:20:30-05:00 hermes@gibson.dropbear.id.au +120 -73
#   Orinoco driver updates - cleanup PCI initialization
# 
# drivers/net/wireless/orinoco_pci.c
#   2005/01/12 00:10:57-05:00 hermes@gibson.dropbear.id.au +46 -25
#   Orinoco driver updates - cleanup PCI initialization
# 
# ChangeSet
#   2005/02/23 23:32:46-05:00 hermes@gibson.dropbear.id.au 
#   [PATCH] Orinoco driver updates - cleanup low-level code
#   
#   Apply some cleanups to the low-level orinoco handling code in
#   hermes.[ch].  This cleans up some error handling code, corrects an
#   error code to something more accurate, and also increases a timeout
#   value.  This last can (when the hardware plays up) cause long delays
#   with spinlocks held, which is bad, but is rather less prone to
#   prematurely giving up, which has the unfortunate habit of fatally
#   confusing the hardware in other ways :-/.
#   
#   Signed-off-by: David Gibson <hermes@gibson.dropbear.id.au>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/wireless/hermes.h
#   2004/11/04 21:53:55-05:00 hermes@gibson.dropbear.id.au +1 -1
#   Orinoco driver updates - cleanup low-level code
# 
# drivers/net/wireless/hermes.c
#   2004/11/04 21:59:07-05:00 hermes@gibson.dropbear.id.au +11 -6
#   Orinoco driver updates - cleanup low-level code
# 
# ChangeSet
#   2005/02/23 23:32:35-05:00 hermes@gibson.dropbear.id.au 
#   [PATCH] Orinoco driver updates - add free_orinocodev()
#   
#   Introduce a free_orinocodev() function into the orinoco driver, used
#   by the hardware type/initialization modules to free the device
#   structure in preference to directly calling free_netdev().  At the
#   moment free_orinocodev() just calls free_netdev().  Future merges will
#   make it clean up internal scanning state, so merging this now will
#   reduce the diff noise.
#   
#   Signed-off-by: David Gibson <hermes@gibson.dropbear.id.au>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/wireless/orinoco_tmd.c
#   2005/02/17 20:04:03-05:00 hermes@gibson.dropbear.id.au +2 -2
#   Orinoco driver updates - add free_orinocodev()
# 
# drivers/net/wireless/orinoco_plx.c
#   2005/02/17 20:04:03-05:00 hermes@gibson.dropbear.id.au +2 -2
#   Orinoco driver updates - add free_orinocodev()
# 
# drivers/net/wireless/orinoco_pci.c
#   2005/02/17 20:04:03-05:00 hermes@gibson.dropbear.id.au +2 -2
#   Orinoco driver updates - add free_orinocodev()
# 
# drivers/net/wireless/orinoco_cs.c
#   2005/02/17 20:04:03-05:00 hermes@gibson.dropbear.id.au +1 -1
#   Orinoco driver updates - add free_orinocodev()
# 
# drivers/net/wireless/orinoco.h
#   2005/02/17 20:04:03-05:00 hermes@gibson.dropbear.id.au +1 -0
#   Orinoco driver updates - add free_orinocodev()
# 
# drivers/net/wireless/orinoco.c
#   2005/02/17 21:03:52-05:00 hermes@gibson.dropbear.id.au +6 -0
#   Orinoco driver updates - add free_orinocodev()
# 
# drivers/net/wireless/airport.c
#   2005/02/17 20:04:03-05:00 hermes@gibson.dropbear.id.au +2 -2
#   Orinoco driver updates - add free_orinocodev()
# 
# ChangeSet
#   2005/02/23 23:32:22-05:00 hermes@gibson.dropbear.id.au 
#   [PATCH] Orinoco driver updates - use mdelay()/ssleep() more
#   
#   Use mdelay() or ssleep() instead of various silly more complicated
#   ways of delaying in the orinoco driver.
#   
#   Signed-off-by: David Gibson <hermes@gibson.dropbear.id.au>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/wireless/orinoco_tmd.c
#   2005/01/11 23:16:06-05:00 hermes@gibson.dropbear.id.au +1 -2
#   Orinoco driver updates - use mdelay()/ssleep() more
# 
# drivers/net/wireless/orinoco_plx.c
#   2005/01/11 23:15:33-05:00 hermes@gibson.dropbear.id.au +1 -2
#   Orinoco driver updates - use mdelay()/ssleep() more
# 
# drivers/net/wireless/orinoco_pci.c
#   2005/01/11 23:15:33-05:00 hermes@gibson.dropbear.id.au +2 -10
#   Orinoco driver updates - use mdelay()/ssleep() more
# 
# ChangeSet
#   2005/02/23 23:32:10-05:00 hermes@gibson.dropbear.id.au 
#   [PATCH] Orinoco driver updates - update printk()s
#   
#   Reformats printk()s, comments, labels and other cosmetic strings in
#   the orinoco driver.  Also moves, removes, and adds ratelimiting in
#   some places.  Behavioural changes are trivial/cosmetic only.  This
#   reduces the cosmetic/trivial differences between the current kernel
#   version, and the CVS version of the driver; one small step towards
#   full merge.
#   
#   Signed-off-by: David Gibson <hermes@gibson.dropbear.id.au>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/wireless/orinoco_tmd.c
#   2005/02/09 22:47:41-05:00 hermes@gibson.dropbear.id.au +11 -7
#   Orinoco driver updates - update printk()s
# 
# drivers/net/wireless/orinoco_plx.c
#   2005/02/09 22:47:41-05:00 hermes@gibson.dropbear.id.au +34 -30
#   Orinoco driver updates - update printk()s
# 
# drivers/net/wireless/orinoco_pci.c
#   2005/02/09 22:47:41-05:00 hermes@gibson.dropbear.id.au +13 -18
#   Orinoco driver updates - update printk()s
# 
# drivers/net/wireless/orinoco_cs.c
#   2005/02/09 22:47:41-05:00 hermes@gibson.dropbear.id.au +1 -1
#   Orinoco driver updates - update printk()s
# 
# drivers/net/wireless/orinoco.h
#   2005/02/09 22:47:41-05:00 hermes@gibson.dropbear.id.au +1 -1
#   Orinoco driver updates - update printk()s
# 
# drivers/net/wireless/orinoco.c
#   2005/02/09 22:47:41-05:00 hermes@gibson.dropbear.id.au +16 -12
#   Orinoco driver updates - update printk()s
# 
# drivers/net/wireless/hermes.c
#   2005/02/09 22:47:41-05:00 hermes@gibson.dropbear.id.au +18 -16
#   Orinoco driver updates - update printk()s
# 
# drivers/net/wireless/airport.c
#   2005/02/09 22:47:41-05:00 hermes@gibson.dropbear.id.au +6 -7
#   Orinoco driver updates - update printk()s
# 
# ChangeSet
#   2005/02/23 23:31:18-05:00 hermes@gibson.dropbear.id.au 
#   [PATCH] Orinoco driver updates - use netif_carrier_*()
#   
#   Removes the orinoco driver's custom and dodgy "connected" variable
#   used to track whether or not we're associated with an AP.  Replaces it
#   instead with netif_carrier_ok() settings.
#   
#   Signed-off-by: David Gibson <hermes@gibson.dropbear.id.au>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/wireless/orinoco.h
#   2005/02/09 22:22:32-05:00 hermes@gibson.dropbear.id.au +0 -1
#   Orinoco driver updates - use netif_carrier_*()
# 
# drivers/net/wireless/orinoco.c
#   2005/02/09 22:22:32-05:00 hermes@gibson.dropbear.id.au +13 -13
#   Orinoco driver updates - use netif_carrier_*()
# 
# ChangeSet
#   2005/02/23 19:57:33-08:00 laforge@netfilter.org 
#   [NETFILTER]: ipt_hashlimit: use hlist instead of list head
#   
#   Use hlist instead of list_head to save lots of memory for the hash buckets.
#   
#   Signed-off-by: Samuel Jean <sjean@cookinglinux.org>
#   Signed-off-by: Harald Welte <laforge@netfilter.org>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/ipv4/netfilter/ipt_hashlimit.c
#   2005/02/23 19:57:13-08:00 laforge@netfilter.org +35 -24
#   [NETFILTER]: ipt_hashlimit: use hlist instead of list head
#   
#   Use hlist instead of list_head to save lots of memory for the hash buckets.
#   
#   Signed-off-by: Samuel Jean <sjean@cookinglinux.org>
#   Signed-off-by: Harald Welte <laforge@netfilter.org>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# ChangeSet
#   2005/02/23 19:56:46-08:00 laforge@netfilter.org 
#   [NETFILTER]: ipt_hashlimit: replace rwlock with spinlock
#   
#   As Samuel points out, the rwlock doesn't really make much sense.
#   
#   Signed-off-by: Samuel Jean <sjean@cookinglinux.org>
#   Signed-off-by: Harald Welte <laforge@netfilter.org>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/ipv4/netfilter/ipt_hashlimit.c
#   2005/02/23 19:56:26-08:00 laforge@netfilter.org +8 -8
#   [NETFILTER]: ipt_hashlimit: replace rwlock with spinlock
#   
#   As Samuel points out, the rwlock doesn't really make much sense.
#   
#   Signed-off-by: Samuel Jean <sjean@cookinglinux.org>
#   Signed-off-by: Harald Welte <laforge@netfilter.org>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# ChangeSet
#   2005/02/23 19:51:56-08:00 davem@nuts.davemloft.net 
#   Merge nuts.davemloft.net:/disk1/BK/net-2.6
#   into nuts.davemloft.net:/disk1/BK/net-2.6.12
# 
# net/ipv6/addrconf.c
#   2005/02/23 19:51:43-08:00 davem@nuts.davemloft.net +0 -0
#   Auto merged
# 
# ChangeSet
#   2005/02/23 19:27:50-08:00 davem@nuts.davemloft.net 
#   [PPC]: Use new set_pte_at() w/mm+address args.
#   
#   Based almost entirely upon an earlier patch by
#   Benjamin Herrenschmidt.
#   
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# include/asm-ppc64/pgtable.h
#   2005/02/23 19:26:53-08:00 davem@nuts.davemloft.net +32 -20
#   [PPC]: Use new set_pte_at() w/mm+address args.
# 
# include/asm-ppc64/pgalloc.h
#   2005/02/23 19:26:53-08:00 davem@nuts.davemloft.net +6 -22
#   [PPC]: Use new set_pte_at() w/mm+address args.
# 
# include/asm-ppc/pgtable.h
#   2005/02/23 19:26:53-08:00 davem@nuts.davemloft.net +33 -28
#   [PPC]: Use new set_pte_at() w/mm+address args.
# 
# include/asm-ppc/highmem.h
#   2005/02/23 19:26:53-08:00 davem@nuts.davemloft.net +1 -1
#   [PPC]: Use new set_pte_at() w/mm+address args.
# 
# arch/ppc64/mm/tlb.c
#   2005/02/23 19:26:53-08:00 davem@nuts.davemloft.net +2 -9
#   [PPC]: Use new set_pte_at() w/mm+address args.
# 
# arch/ppc/mm/tlb.c
#   2005/02/23 19:26:53-08:00 davem@nuts.davemloft.net +0 -20
#   [PPC]: Use new set_pte_at() w/mm+address args.
# 
# arch/ppc/mm/pgtable.c
#   2005/02/23 19:26:53-08:00 davem@nuts.davemloft.net +2 -12
#   [PPC]: Use new set_pte_at() w/mm+address args.
# 
# arch/ppc/mm/init.c
#   2005/02/23 19:26:53-08:00 davem@nuts.davemloft.net +0 -12
#   [PPC]: Use new set_pte_at() w/mm+address args.
# 
# arch/ppc/kernel/dma-mapping.c
#   2005/02/23 19:26:53-08:00 davem@nuts.davemloft.net +5 -2
#   [PPC]: Use new set_pte_at() w/mm+address args.
# 
# ChangeSet
#   2005/02/23 19:18:34-08:00 herbert@gondor.apana.org.au 
#   [NET]: Add skb_header_cloned and use it in e1000/tg3
#   
#   This patch adds skb_header_cloned which tells us whether we need to
#   copy the data before we can modify the header part of the skb.  Again,
#   what constitutes the header is left up to the users of the skb to define.
#   
#   This patch then uses this function in e1000/tg3 to copy the data before
#   the TCP/IP header is modified.
#   
#   Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# include/linux/skbuff.h
#   2005/02/23 19:18:14-08:00 herbert@gondor.apana.org.au +19 -0
#   [NET]: Add skb_header_cloned and use it in e1000/tg3
#   
#   This patch adds skb_header_cloned which tells us whether we need to
#   copy the data before we can modify the header part of the skb.  Again,
#   what constitutes the header is left up to the users of the skb to define.
#   
#   This patch then uses this function in e1000/tg3 to copy the data before
#   the TCP/IP header is modified.
#   
#   Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# drivers/net/tg3.c
#   2005/02/23 19:18:14-08:00 herbert@gondor.apana.org.au +6 -0
#   [NET]: Add skb_header_cloned and use it in e1000/tg3
#   
#   This patch adds skb_header_cloned which tells us whether we need to
#   copy the data before we can modify the header part of the skb.  Again,
#   what constitutes the header is left up to the users of the skb to define.
#   
#   This patch then uses this function in e1000/tg3 to copy the data before
#   the TCP/IP header is modified.
#   
#   Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# drivers/net/e1000/e1000_main.c
#   2005/02/23 19:18:14-08:00 herbert@gondor.apana.org.au +18 -4
#   [NET]: Add skb_header_cloned and use it in e1000/tg3
#   
#   This patch adds skb_header_cloned which tells us whether we need to
#   copy the data before we can modify the header part of the skb.  Again,
#   what constitutes the header is left up to the users of the skb to define.
#   
#   This patch then uses this function in e1000/tg3 to copy the data before
#   the TCP/IP header is modified.
#   
#   Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# ChangeSet
#   2005/02/23 19:17:24-08:00 herbert@gondor.apana.org.au 
#   [NET]: Add skb_header_release and use it in net/ipv4/tcp
#   
#   This patch adds skb_header_release which can be called when the owner
#   of an skb no longer needs to access the header at all.  What constitutes
#   the header is left up to the users of the skb to define.
#   
#   For instance, for outbound TCP packets we define the header to be
#   anything in front of the TCP payload.  Therefore we add skb_header_release
#   calls to all the paths where outound TCP packets are produced.
#   
#   Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/ipv4/tcp_output.c
#   2005/02/23 19:16:59-08:00 herbert@gondor.apana.org.au +3 -0
#   [NET]: Add skb_header_release and use it in net/ipv4/tcp
#   
#   This patch adds skb_header_release which can be called when the owner
#   of an skb no longer needs to access the header at all.  What constitutes
#   the header is left up to the users of the skb to define.
#   
#   For instance, for outbound TCP packets we define the header to be
#   anything in front of the TCP payload.  Therefore we add skb_header_release
#   calls to all the paths where outound TCP packets are produced.
#   
#   Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/ipv4/tcp.c
#   2005/02/23 19:16:58-08:00 herbert@gondor.apana.org.au +1 -0
#   [NET]: Add skb_header_release and use it in net/ipv4/tcp
#   
#   This patch adds skb_header_release which can be called when the owner
#   of an skb no longer needs to access the header at all.  What constitutes
#   the header is left up to the users of the skb to define.
#   
#   For instance, for outbound TCP packets we define the header to be
#   anything in front of the TCP payload.  Therefore we add skb_header_release
#   calls to all the paths where outound TCP packets are produced.
#   
#   Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/core/skbuff.c
#   2005/02/23 19:16:58-08:00 herbert@gondor.apana.org.au +4 -1
#   [NET]: Add skb_header_release and use it in net/ipv4/tcp
#   
#   This patch adds skb_header_release which can be called when the owner
#   of an skb no longer needs to access the header at all.  What constitutes
#   the header is left up to the users of the skb to define.
#   
#   For instance, for outbound TCP packets we define the header to be
#   anything in front of the TCP payload.  Therefore we add skb_header_release
#   calls to all the paths where outound TCP packets are produced.
#   
#   Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# include/linux/skbuff.h
#   2005/02/23 19:16:58-08:00 herbert@gondor.apana.org.au +34 -2
#   [NET]: Add skb_header_release and use it in net/ipv4/tcp
#   
#   This patch adds skb_header_release which can be called when the owner
#   of an skb no longer needs to access the header at all.  What constitutes
#   the header is left up to the users of the skb to define.
#   
#   For instance, for outbound TCP packets we define the header to be
#   anything in front of the TCP payload.  Therefore we add skb_header_release
#   calls to all the paths where outound TCP packets are produced.
#   
#   Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# ChangeSet
#   2005/02/23 17:46:43-08:00 davem@nuts.davemloft.net 
#   [SPARC64]: Pass mm/addr directly to tlb_batch_add()
#   
#   No longer need to store this information in the pte table
#   page struct.
#   
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# include/asm-sparc64/pgtable.h
#   2005/02/23 17:45:37-08:00 davem@nuts.davemloft.net +6 -5
#   [SPARC64]: Pass mm/addr directly to tlb_batch_add()
# 
# include/asm-sparc64/pgalloc.h
#   2005/02/23 17:45:37-08:00 davem@nuts.davemloft.net +5 -15
#   [SPARC64]: Pass mm/addr directly to tlb_batch_add()
# 
# arch/sparc64/mm/tlb.c
#   2005/02/23 17:45:37-08:00 davem@nuts.davemloft.net +7 -10
#   [SPARC64]: Pass mm/addr directly to tlb_batch_add()
# 
# arch/sparc64/mm/init.c
#   2005/02/23 17:45:36-08:00 davem@nuts.davemloft.net +2 -1
#   [SPARC64]: Pass mm/addr directly to tlb_batch_add()
# 
# arch/sparc64/mm/hugetlbpage.c
#   2005/02/23 17:45:36-08:00 davem@nuts.davemloft.net +6 -4
#   [SPARC64]: Pass mm/addr directly to tlb_batch_add()
# 
# arch/sparc64/mm/generic.c
#   2005/02/23 17:45:36-08:00 davem@nuts.davemloft.net +14 -11
#   [SPARC64]: Pass mm/addr directly to tlb_batch_add()
# 
# ChangeSet
#   2005/02/23 19:36:15-05:00 davej@redhat.com 
#   [AGPGART] add bridge parameter to driver functions
#   
#   From: Michael Werner <werner@mrcoffee.engr.sgi.com>
#   
#   Add bridge parameter to create_gatt_table, free_gatt_table and mask_memory
#   
#   Signed-off-by: Mike Werner <werner@sgi.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
# 
# drivers/char/agp/uninorth-agp.c
#   2005/02/23 19:36:05-05:00 davej@redhat.com +10 -10
#   [AGPGART] add bridge parameter to driver functions
#   
#   From: Michael Werner <werner@mrcoffee.engr.sgi.com>
#   
#   Add bridge parameter to create_gatt_table, free_gatt_table and mask_memory
#   
#   Signed-off-by: Mike Werner <werner@sgi.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
# 
# drivers/char/agp/sworks-agp.c
#   2005/02/23 19:36:05-05:00 davej@redhat.com +7 -7
#   [AGPGART] add bridge parameter to driver functions
#   
#   From: Michael Werner <werner@mrcoffee.engr.sgi.com>
#   
#   Add bridge parameter to create_gatt_table, free_gatt_table and mask_memory
#   
#   Signed-off-by: Mike Werner <werner@sgi.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
# 
# drivers/char/agp/sis-agp.c
#   2005/02/23 19:36:05-05:00 davej@redhat.com +3 -3
#   [AGPGART] add bridge parameter to driver functions
#   
#   From: Michael Werner <werner@mrcoffee.engr.sgi.com>
#   
#   Add bridge parameter to create_gatt_table, free_gatt_table and mask_memory
#   
#   Signed-off-by: Mike Werner <werner@sgi.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
# 
# drivers/char/agp/nvidia-agp.c
#   2005/02/23 19:36:05-05:00 davej@redhat.com +2 -1
#   [AGPGART] add bridge parameter to driver functions
#   
#   From: Michael Werner <werner@mrcoffee.engr.sgi.com>
#   
#   Add bridge parameter to create_gatt_table, free_gatt_table and mask_memory
#   
#   Signed-off-by: Mike Werner <werner@sgi.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
# 
# drivers/char/agp/intel-agp.c
#   2005/02/23 19:36:05-05:00 davej@redhat.com +15 -11
#   [AGPGART] add bridge parameter to driver functions
#   
#   From: Michael Werner <werner@mrcoffee.engr.sgi.com>
#   
#   Add bridge parameter to create_gatt_table, free_gatt_table and mask_memory
#   
#   Signed-off-by: Mike Werner <werner@sgi.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
# 
# drivers/char/agp/i460-agp.c
#   2005/02/23 19:36:05-05:00 davej@redhat.com +9 -6
#   [AGPGART] add bridge parameter to driver functions
#   
#   From: Michael Werner <werner@mrcoffee.engr.sgi.com>
#   
#   Add bridge parameter to create_gatt_table, free_gatt_table and mask_memory
#   
#   Signed-off-by: Mike Werner <werner@sgi.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
# 
# drivers/char/agp/hp-agp.c
#   2005/02/23 19:36:05-05:00 davej@redhat.com +9 -6
#   [AGPGART] add bridge parameter to driver functions
#   
#   From: Michael Werner <werner@mrcoffee.engr.sgi.com>
#   
#   Add bridge parameter to create_gatt_table, free_gatt_table and mask_memory
#   
#   Signed-off-by: Mike Werner <werner@sgi.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
# 
# drivers/char/agp/generic.c
#   2005/02/23 19:36:05-05:00 davej@redhat.com +47 -44
#   [AGPGART] add bridge parameter to driver functions
#   
#   From: Michael Werner <werner@mrcoffee.engr.sgi.com>
#   
#   Add bridge parameter to create_gatt_table, free_gatt_table and mask_memory
#   
#   Signed-off-by: Mike Werner <werner@sgi.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
# 
# drivers/char/agp/efficeon-agp.c
#   2005/02/23 19:36:05-05:00 davej@redhat.com +3 -3
#   [AGPGART] add bridge parameter to driver functions
#   
#   From: Michael Werner <werner@mrcoffee.engr.sgi.com>
#   
#   Add bridge parameter to create_gatt_table, free_gatt_table and mask_memory
#   
#   Signed-off-by: Mike Werner <werner@sgi.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
# 
# drivers/char/agp/backend.c
#   2005/02/23 19:36:05-05:00 davej@redhat.com +4 -4
#   [AGPGART] add bridge parameter to driver functions
#   
#   From: Michael Werner <werner@mrcoffee.engr.sgi.com>
#   
#   Add bridge parameter to create_gatt_table, free_gatt_table and mask_memory
#   
#   Signed-off-by: Mike Werner <werner@sgi.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
# 
# drivers/char/agp/ati-agp.c
#   2005/02/23 19:36:05-05:00 davej@redhat.com +4 -3
#   [AGPGART] add bridge parameter to driver functions
#   
#   From: Michael Werner <werner@mrcoffee.engr.sgi.com>
#   
#   Add bridge parameter to create_gatt_table, free_gatt_table and mask_memory
#   
#   Signed-off-by: Mike Werner <werner@sgi.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
# 
# drivers/char/agp/amd64-agp.c
#   2005/02/23 19:36:05-05:00 davej@redhat.com +2 -1
#   [AGPGART] add bridge parameter to driver functions
#   
#   From: Michael Werner <werner@mrcoffee.engr.sgi.com>
#   
#   Add bridge parameter to create_gatt_table, free_gatt_table and mask_memory
#   
#   Signed-off-by: Mike Werner <werner@sgi.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
# 
# drivers/char/agp/amd-k7-agp.c
#   2005/02/23 19:36:05-05:00 davej@redhat.com +4 -3
#   [AGPGART] add bridge parameter to driver functions
#   
#   From: Michael Werner <werner@mrcoffee.engr.sgi.com>
#   
#   Add bridge parameter to create_gatt_table, free_gatt_table and mask_memory
#   
#   Signed-off-by: Mike Werner <werner@sgi.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
# 
# drivers/char/agp/alpha-agp.c
#   2005/02/23 19:36:05-05:00 davej@redhat.com +4 -3
#   [AGPGART] add bridge parameter to driver functions
#   
#   From: Michael Werner <werner@mrcoffee.engr.sgi.com>
#   
#   Add bridge parameter to create_gatt_table, free_gatt_table and mask_memory
#   
#   Signed-off-by: Mike Werner <werner@sgi.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
# 
# drivers/char/agp/agp.h
#   2005/02/23 19:36:05-05:00 davej@redhat.com +10 -8
#   [AGPGART] add bridge parameter to driver functions
#   
#   From: Michael Werner <werner@mrcoffee.engr.sgi.com>
#   
#   Add bridge parameter to create_gatt_table, free_gatt_table and mask_memory
#   
#   Signed-off-by: Mike Werner <werner@sgi.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
# 
# ChangeSet
#   2005/02/23 15:42:56-08:00 davem@nuts.davemloft.net 
#   [MM]: Add set_pte_at() which takes 'mm' and 'addr' args.
#   
#   I'm taking a slightly different approach this time around so things
#   are easier to integrate.  Here is the first patch which builds the
#   infrastructure.  Basically:
#   
#   1) Add set_pte_at() which is set_pte() with 'mm' and 'addr' arguments
#      added.  All generic code uses set_pte_at().
#   
#      Most platforms simply get this define:
#   	#define set_pte_at(mm,addr,ptep,pteval) set_pte(ptep,pteval)
#   
#      I chose this method over simply changing all set_pte() call sites
#      because many platforms implement this in assembler and it would
#      take forever to preserve the build and stabilize things if modifying
#      that was necessary.
#   
#      Soon, with platform maintainer's help, we can kill of set_pte() entirely.
#      To be honest, there are only a handful of set_pte() call sites in the
#      arch specific code.
#   
#      Actually, in this patch ppc64 is completely set_pte() free and does not
#      define it.
#   
#   2) pte_clear() gets 'mm' and 'addr' arguments now.
#      This had a cascading effect on many ptep_test_and_*() routines.  Specifically:
#      a) ptep_test_and_clear_{young,dirty}() now take 'vma' and 'address' args.
#      b) ptep_get_and_clear now take 'mm' and 'address' args.
#      c) ptep_mkdirty was deleted, unused by any code.
#      d) ptep_set_wrprotect now takes 'mm' and 'address' args.
#   
#   I've tested this patch as follows:
#   
#   1) compile and run tested on sparc64/SMP
#   2) compile tested on:
#      a) ppc64/SMP
#      b) i386 both with and without PAE enabled
#   
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# mm/vmalloc.c
#   2005/02/23 15:40:53-08:00 davem@nuts.davemloft.net +2 -2
#   [MM]: Add set_pte_at() which takes 'mm' and 'addr' args.
# 
# mm/swapfile.c
#   2005/02/23 15:40:53-08:00 davem@nuts.davemloft.net +2 -1
#   [MM]: Add set_pte_at() which takes 'mm' and 'addr' args.
# 
# mm/rmap.c
#   2005/02/23 15:40:53-08:00 davem@nuts.davemloft.net +2 -2
#   [MM]: Add set_pte_at() which takes 'mm' and 'addr' args.
# 
# mm/mremap.c
#   2005/02/23 15:40:53-08:00 davem@nuts.davemloft.net +1 -1
#   [MM]: Add set_pte_at() which takes 'mm' and 'addr' args.
# 
# mm/mprotect.c
#   2005/02/23 15:40:53-08:00 davem@nuts.davemloft.net +10 -10
#   [MM]: Add set_pte_at() which takes 'mm' and 'addr' args.
# 
# mm/memory.c
#   2005/02/23 15:40:53-08:00 davem@nuts.davemloft.net +21 -18
#   [MM]: Add set_pte_at() which takes 'mm' and 'addr' args.
# 
# mm/highmem.c
#   2005/02/23 15:40:53-08:00 davem@nuts.davemloft.net +4 -2
#   [MM]: Add set_pte_at() which takes 'mm' and 'addr' args.
# 
# mm/fremap.c
#   2005/02/23 15:40:53-08:00 davem@nuts.davemloft.net +3 -3
#   [MM]: Add set_pte_at() which takes 'mm' and 'addr' args.
# 
# include/asm-x86_64/pgtable.h
#   2005/02/23 15:40:53-08:00 davem@nuts.davemloft.net +9 -7
#   [MM]: Add set_pte_at() which takes 'mm' and 'addr' args.
# 
# include/asm-um/pgtable.h
#   2005/02/23 15:40:53-08:00 davem@nuts.davemloft.net +1 -1
#   [MM]: Add set_pte_at() which takes 'mm' and 'addr' args.
# 
# include/asm-um/pgtable-3level.h
#   2005/02/23 15:40:53-08:00 davem@nuts.davemloft.net +1 -0
#   [MM]: Add set_pte_at() which takes 'mm' and 'addr' args.
# 
# include/asm-um/pgtable-2level.h
#   2005/02/23 15:40:53-08:00 davem@nuts.davemloft.net +1 -0
#   [MM]: Add set_pte_at() which takes 'mm' and 'addr' args.
# 
# include/asm-sparc64/pgtable.h
#   2005/02/23 15:40:53-08:00 davem@nuts.davemloft.net +3 -1
#   [MM]: Add set_pte_at() which takes 'mm' and 'addr' args.
# 
# include/asm-sparc/pgtable.h
#   2005/02/23 15:40:53-08:00 davem@nuts.davemloft.net +2 -1
#   [MM]: Add set_pte_at() which takes 'mm' and 'addr' args.
# 
# include/asm-sh64/pgtable.h
#   2005/02/23 15:40:53-08:00 davem@nuts.davemloft.net +2 -1
#   [MM]: Add set_pte_at() which takes 'mm' and 'addr' args.
# 
# include/asm-sh/pgtable.h
#   2005/02/23 15:40:53-08:00 davem@nuts.davemloft.net +2 -2
#   [MM]: Add set_pte_at() which takes 'mm' and 'addr' args.
# 
# include/asm-sh/pgtable-2level.h
#   2005/02/23 15:40:53-08:00 davem@nuts.davemloft.net +2 -0
#   [MM]: Add set_pte_at() which takes 'mm' and 'addr' args.
# 
# include/asm-s390/pgtable.h
#   2005/02/23 15:40:53-08:00 davem@nuts.davemloft.net +11 -16
#   [MM]: Add set_pte_at() which takes 'mm' and 'addr' args.
# 
# include/asm-s390/pgalloc.h
#   2005/02/23 15:40:53-08:00 davem@nuts.davemloft.net +4 -2
#   [MM]: Add set_pte_at() which takes 'mm' and 'addr' args.
# 
# include/asm-ppc64/pgtable.h
#   2005/02/23 15:40:53-08:00 davem@nuts.davemloft.net +12 -9
#   [MM]: Add set_pte_at() which takes 'mm' and 'addr' args.
# 
# include/asm-ppc/pgtable.h
#   2005/02/23 15:40:53-08:00 davem@nuts.davemloft.net +6 -11
#   [MM]: Add set_pte_at() which takes 'mm' and 'addr' args.
# 
# include/asm-ppc/highmem.h
#   2005/02/23 15:40:53-08:00 davem@nuts.davemloft.net +1 -1
#   [MM]: Add set_pte_at() which takes 'mm' and 'addr' args.
# 
# include/asm-parisc/pgtable.h
#   2005/02/23 15:40:53-08:00 davem@nuts.davemloft.net +10 -20
#   [MM]: Add set_pte_at() which takes 'mm' and 'addr' args.
# 
# include/asm-mips/pgtable.h
#   2005/02/23 15:40:53-08:00 davem@nuts.davemloft.net +8 -6
#   [MM]: Add set_pte_at() which takes 'mm' and 'addr' args.
# 
# include/asm-m68k/sun3_pgtable.h
#   2005/02/23 15:40:53-08:00 davem@nuts.davemloft.net +4 -1
#   [MM]: Add set_pte_at() which takes 'mm' and 'addr' args.
# 
# include/asm-m68k/pgtable.h
#   2005/02/23 15:40:53-08:00 davem@nuts.davemloft.net +1 -0
#   [MM]: Add set_pte_at() which takes 'mm' and 'addr' args.
# 
# include/asm-m68k/motorola_pgtable.h
#   2005/02/23 15:40:53-08:00 davem@nuts.davemloft.net +1 -1
#   [MM]: Add set_pte_at() which takes 'mm' and 'addr' args.
# 
# include/asm-m32r/pgtable.h
#   2005/02/23 15:40:53-08:00 davem@nuts.davemloft.net +4 -10
#   [MM]: Add set_pte_at() which takes 'mm' and 'addr' args.
# 
# include/asm-m32r/pgtable-2level.h
#   2005/02/23 15:40:53-08:00 davem@nuts.davemloft.net +2 -1
#   [MM]: Add set_pte_at() which takes 'mm' and 'addr' args.
# 
# include/asm-ia64/pgtable.h
#   2005/02/23 15:40:53-08:00 davem@nuts.davemloft.net +10 -21
#   [MM]: Add set_pte_at() which takes 'mm' and 'addr' args.
# 
# include/asm-i386/pgtable.h
#   2005/02/23 15:40:53-08:00 davem@nuts.davemloft.net +7 -6
#   [MM]: Add set_pte_at() which takes 'mm' and 'addr' args.
# 
# include/asm-i386/pgtable-3level.h
#   2005/02/23 15:40:53-08:00 davem@nuts.davemloft.net +3 -1
#   [MM]: Add set_pte_at() which takes 'mm' and 'addr' args.
# 
# include/asm-i386/pgtable-2level.h
#   2005/02/23 15:40:53-08:00 davem@nuts.davemloft.net +2 -1
#   [MM]: Add set_pte_at() which takes 'mm' and 'addr' args.
# 
# include/asm-generic/pgtable.h
#   2005/02/23 15:40:53-08:00 davem@nuts.davemloft.net +38 -37
#   [MM]: Add set_pte_at() which takes 'mm' and 'addr' args.
# 
# include/asm-frv/pgtable.h
#   2005/02/23 15:40:52-08:00 davem@nuts.davemloft.net +6 -12
#   [MM]: Add set_pte_at() which takes 'mm' and 'addr' args.
# 
# include/asm-cris/pgtable.h
#   2005/02/23 15:40:52-08:00 davem@nuts.davemloft.net +3 -1
#   [MM]: Add set_pte_at() which takes 'mm' and 'addr' args.
# 
# include/asm-arm26/pgtable.h
#   2005/02/23 15:40:52-08:00 davem@nuts.davemloft.net +2 -1
#   [MM]: Add set_pte_at() which takes 'mm' and 'addr' args.
# 
# include/asm-arm/pgtable.h
#   2005/02/23 15:40:52-08:00 davem@nuts.davemloft.net +2 -1
#   [MM]: Add set_pte_at() which takes 'mm' and 'addr' args.
# 
# include/asm-alpha/pgtable.h
#   2005/02/23 15:40:52-08:00 davem@nuts.davemloft.net +5 -1
#   [MM]: Add set_pte_at() which takes 'mm' and 'addr' args.
# 
# fs/exec.c
#   2005/02/23 15:40:52-08:00 davem@nuts.davemloft.net +1 -1
#   [MM]: Add set_pte_at() which takes 'mm' and 'addr' args.
# 
# arch/sparc64/mm/hugetlbpage.c
#   2005/02/23 15:40:52-08:00 davem@nuts.davemloft.net +1 -1
#   [MM]: Add set_pte_at() which takes 'mm' and 'addr' args.
# 
# arch/sparc/mm/highmem.c
#   2005/02/23 15:40:52-08:00 davem@nuts.davemloft.net +1 -1
#   [MM]: Add set_pte_at() which takes 'mm' and 'addr' args.
# 
# arch/sparc/mm/generic.c
#   2005/02/23 15:40:52-08:00 davem@nuts.davemloft.net +6 -6
#   [MM]: Add set_pte_at() which takes 'mm' and 'addr' args.
# 
# arch/sh64/mm/ioremap.c
#   2005/02/23 15:40:52-08:00 davem@nuts.davemloft.net +1 -1
#   [MM]: Add set_pte_at() which takes 'mm' and 'addr' args.
# 
# arch/sh64/mm/hugetlbpage.c
#   2005/02/23 15:40:52-08:00 davem@nuts.davemloft.net +1 -1
#   [MM]: Add set_pte_at() which takes 'mm' and 'addr' args.
# 
# arch/sh/mm/pg-sh7705.c
#   2005/02/23 15:40:52-08:00 davem@nuts.davemloft.net +2 -2
#   [MM]: Add set_pte_at() which takes 'mm' and 'addr' args.
# 
# arch/sh/mm/pg-sh4.c
#   2005/02/23 15:40:52-08:00 davem@nuts.davemloft.net +4 -4
#   [MM]: Add set_pte_at() which takes 'mm' and 'addr' args.
# 
# arch/sh/mm/hugetlbpage.c
#   2005/02/23 15:40:52-08:00 davem@nuts.davemloft.net +1 -1
#   [MM]: Add set_pte_at() which takes 'mm' and 'addr' args.
# 
# arch/s390/mm/init.c
#   2005/02/23 15:40:52-08:00 davem@nuts.davemloft.net +2 -2
#   [MM]: Add set_pte_at() which takes 'mm' and 'addr' args.
# 
# arch/ppc64/mm/init.c
#   2005/02/23 15:40:52-08:00 davem@nuts.davemloft.net +2 -2
#   [MM]: Add set_pte_at() which takes 'mm' and 'addr' args.
# 
# arch/ppc64/mm/hugetlbpage.c
#   2005/02/23 15:40:52-08:00 davem@nuts.davemloft.net +6 -5
#   [MM]: Add set_pte_at() which takes 'mm' and 'addr' args.
# 
# arch/ppc/kernel/dma-mapping.c
#   2005/02/23 15:40:52-08:00 davem@nuts.davemloft.net +4 -2
#   [MM]: Add set_pte_at() which takes 'mm' and 'addr' args.
# 
# arch/parisc/mm/kmap.c
#   2005/02/23 15:40:52-08:00 davem@nuts.davemloft.net +2 -2
#   [MM]: Add set_pte_at() which takes 'mm' and 'addr' args.
# 
# arch/parisc/kernel/pci-dma.c
#   2005/02/23 15:40:52-08:00 davem@nuts.davemloft.net +1 -1
#   [MM]: Add set_pte_at() which takes 'mm' and 'addr' args.
# 
# arch/mips/mm/highmem.c
#   2005/02/23 15:40:52-08:00 davem@nuts.davemloft.net +1 -1
#   [MM]: Add set_pte_at() which takes 'mm' and 'addr' args.
# 
# arch/ia64/mm/hugetlbpage.c
#   2005/02/23 15:40:52-08:00 davem@nuts.davemloft.net +1 -1
#   [MM]: Add set_pte_at() which takes 'mm' and 'addr' args.
# 
# arch/i386/mm/hugetlbpage.c
#   2005/02/23 15:40:52-08:00 davem@nuts.davemloft.net +1 -1
#   [MM]: Add set_pte_at() which takes 'mm' and 'addr' args.
# 
# arch/i386/mm/highmem.c
#   2005/02/23 15:40:52-08:00 davem@nuts.davemloft.net +1 -1
#   [MM]: Add set_pte_at() which takes 'mm' and 'addr' args.
# 
# arch/arm/mm/consistent.c
#   2005/02/23 15:40:52-08:00 davem@nuts.davemloft.net +4 -2
#   [MM]: Add set_pte_at() which takes 'mm' and 'addr' args.
# 
# ChangeSet
#   2005/02/23 18:19:13-05:00 davej@redhat.com 
#   [FB] add support for new multiple agp bridge agpgart api
#   
#   From: Michael Werner <werner@mrcoffee.engr.sgi.com>
#   
#   This patch adds fb support for new multiple agp bridge agpgart api.
#   
#   Signed-off-by: Mike Werner <werner@sgi.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# drivers/video/intelfb/intelfbdrv.c
#   2005/02/23 18:19:04-05:00 davej@redhat.com +12 -11
#   [FB] add support for new multiple agp bridge agpgart api
#   
#   From: Michael Werner <werner@mrcoffee.engr.sgi.com>
#   
#   This patch adds fb support for new multiple agp bridge agpgart api.
#   
#   Signed-off-by: Mike Werner <werner@sgi.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# drivers/video/i810/i810_main.c
#   2005/02/23 18:19:04-05:00 davej@redhat.com +9 -8
#   [FB] add support for new multiple agp bridge agpgart api
#   
#   From: Michael Werner <werner@mrcoffee.engr.sgi.com>
#   
#   This patch adds fb support for new multiple agp bridge agpgart api.
#   
#   Signed-off-by: Mike Werner <werner@sgi.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# ChangeSet
#   2005/02/23 18:18:13-05:00 davej@redhat.com 
#   [DRM] add support for new multiple agp bridge agpgart api
#   
#   From: Michael Werner <werner@mrcoffee.engr.sgi.com>
#   
#   This patch adds drm support for new multiple agp bridge agpgart api.
#   
#   Signed-off-by: Mike Werner <werner@sgi.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# drivers/char/drm/drm_stub.c
#   2005/02/23 18:18:04-05:00 davej@redhat.com +1 -1
#   [DRM] add support for new multiple agp bridge agpgart api
#   
#   From: Michael Werner <werner@mrcoffee.engr.sgi.com>
#   
#   This patch adds drm support for new multiple agp bridge agpgart api.
#   
#   Signed-off-by: Mike Werner <werner@sgi.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# drivers/char/drm/drm_memory.c
#   2005/02/23 18:18:04-05:00 davej@redhat.com +2 -2
#   [DRM] add support for new multiple agp bridge agpgart api
#   
#   From: Michael Werner <werner@mrcoffee.engr.sgi.com>
#   
#   This patch adds drm support for new multiple agp bridge agpgart api.
#   
#   Signed-off-by: Mike Werner <werner@sgi.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# drivers/char/drm/drm_drv.c
#   2005/02/23 18:18:04-05:00 davej@redhat.com +1 -1
#   [DRM] add support for new multiple agp bridge agpgart api
#   
#   From: Michael Werner <werner@mrcoffee.engr.sgi.com>
#   
#   This patch adds drm support for new multiple agp bridge agpgart api.
#   
#   Signed-off-by: Mike Werner <werner@sgi.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# drivers/char/drm/drm_agpsupport.c
#   2005/02/23 18:18:04-05:00 davej@redhat.com +16 -12
#   [DRM] add support for new multiple agp bridge agpgart api
#   
#   From: Michael Werner <werner@mrcoffee.engr.sgi.com>
#   
#   This patch adds drm support for new multiple agp bridge agpgart api.
#   
#   Signed-off-by: Mike Werner <werner@sgi.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# drivers/char/drm/drmP.h
#   2005/02/23 18:18:04-05:00 davej@redhat.com +5 -4
#   [DRM] add support for new multiple agp bridge agpgart api
#   
#   From: Michael Werner <werner@mrcoffee.engr.sgi.com>
#   
#   This patch adds drm support for new multiple agp bridge agpgart api.
#   
#   Signed-off-by: Mike Werner <werner@sgi.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# ChangeSet
#   2005/02/23 18:17:02-05:00 davej@redhat.com 
#   [AGPGART] allow drivers to allocate memory local to the bridge
#   
#   From: Michael Werner <werner@mrcoffee.engr.sgi.com>
#   
#   This patch allows drivers to allocate memory local to the bridge using
#   platform specific alloc_page routines.
#   
#   Signed-off-by: Mike Werner <werner@sgi.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# drivers/char/agp/intel-agp.c
#   2005/02/23 18:16:53-05:00 davej@redhat.com +1 -1
#   [AGPGART] allow drivers to allocate memory local to the bridge
#   
#   From: Michael Werner <werner@mrcoffee.engr.sgi.com>
#   
#   This patch allows drivers to allocate memory local to the bridge using
#   platform specific alloc_page routines.
#   
#   Signed-off-by: Mike Werner <werner@sgi.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# drivers/char/agp/i460-agp.c
#   2005/02/23 18:16:53-05:00 davej@redhat.com +2 -2
#   [AGPGART] allow drivers to allocate memory local to the bridge
#   
#   From: Michael Werner <werner@mrcoffee.engr.sgi.com>
#   
#   This patch allows drivers to allocate memory local to the bridge using
#   platform specific alloc_page routines.
#   
#   Signed-off-by: Mike Werner <werner@sgi.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# drivers/char/agp/generic.c
#   2005/02/23 18:16:53-05:00 davej@redhat.com +2 -2
#   [AGPGART] allow drivers to allocate memory local to the bridge
#   
#   From: Michael Werner <werner@mrcoffee.engr.sgi.com>
#   
#   This patch allows drivers to allocate memory local to the bridge using
#   platform specific alloc_page routines.
#   
#   Signed-off-by: Mike Werner <werner@sgi.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# drivers/char/agp/backend.c
#   2005/02/23 18:16:53-05:00 davej@redhat.com +1 -1
#   [AGPGART] allow drivers to allocate memory local to the bridge
#   
#   From: Michael Werner <werner@mrcoffee.engr.sgi.com>
#   
#   This patch allows drivers to allocate memory local to the bridge using
#   platform specific alloc_page routines.
#   
#   Signed-off-by: Mike Werner <werner@sgi.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# drivers/char/agp/ali-agp.c
#   2005/02/23 18:16:53-05:00 davej@redhat.com +2 -2
#   [AGPGART] allow drivers to allocate memory local to the bridge
#   
#   From: Michael Werner <werner@mrcoffee.engr.sgi.com>
#   
#   This patch allows drivers to allocate memory local to the bridge using
#   platform specific alloc_page routines.
#   
#   Signed-off-by: Mike Werner <werner@sgi.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# drivers/char/agp/agp.h
#   2005/02/23 18:16:53-05:00 davej@redhat.com +2 -2
#   [AGPGART] allow drivers to allocate memory local to the bridge
#   
#   From: Michael Werner <werner@mrcoffee.engr.sgi.com>
#   
#   This patch allows drivers to allocate memory local to the bridge using
#   platform specific alloc_page routines.
#   
#   Signed-off-by: Mike Werner <werner@sgi.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# ChangeSet
#   2005/02/23 18:15:47-05:00 davej@redhat.com 
#   [AGPGART] add agp_find_bridge function
#   
#   From: Michael Werner <werner@mrcoffee.engr.sgi.com>
#   
#   This patch gives non-generic platforms a method for using platform specific
#   agp_find_bridge functions.
#   
#   Signed-off-by: Mike Werner <werner@sgi.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# include/linux/agp_backend.h
#   2005/02/23 18:15:38-05:00 davej@redhat.com +2 -0
#   [AGPGART] add agp_find_bridge function
#   
#   From: Michael Werner <werner@mrcoffee.engr.sgi.com>
#   
#   This patch gives non-generic platforms a method for using platform specific
#   agp_find_bridge functions.
#   
#   Signed-off-by: Mike Werner <werner@sgi.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# drivers/char/agp/backend.c
#   2005/02/23 18:15:38-05:00 davej@redhat.com +4 -1
#   [AGPGART] add agp_find_bridge function
#   
#   From: Michael Werner <werner@mrcoffee.engr.sgi.com>
#   
#   This patch gives non-generic platforms a method for using platform specific
#   agp_find_bridge functions.
#   
#   Signed-off-by: Mike Werner <werner@sgi.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# ChangeSet
#   2005/02/23 18:12:13-05:00 davej@redhat.com 
#   [AGPGART] allow multiple backends to be initialized.
#   
#   From: Michael Werner <werner@mrcoffee.engr.sgi.com>
#   
#   This patch adds support for initializing and addressing multiple AGP
#   bridges using the agpgart driver.  In particular, it extends agp_acquire
#   and agp_allocate_memory so that different bridges can be acquired and
#   memory allocated within a specific AGP aperature.
#   
#   From: Brice Goglin <Brice.Goglin@ens-lyon.fr>
#   
#   It seems that memsetting the whole bridge structure to 0 (instead of juste
#   the agp_in_use field) fixes Benoit's problem too.  No idea which field was
#   responsible for this.  New patch attached.
#   
#   From: Mike Werner <werner@sgi.com>
#   
#   add bridge assignment missed in agp_allocate_memory
#   
#   From: Andi Kleen <ak@suse.de>
#   
#   Here's the correct fix. agp_bridge is defined in drivers/char/agp/agp.h.
#   It's a bit ugly though.
#   
#   Signed-off-by: Mike Werner <werner@sgi.com>
#   Signed-off-by: Andi Kleen <ak@suse.de>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# include/linux/agp_backend.h
#   2005/02/23 18:12:04-05:00 davej@redhat.com +14 -7
#   [AGPGART] allow multiple backends to be initialized.
#   
#   From: Michael Werner <werner@mrcoffee.engr.sgi.com>
#   
#   This patch adds support for initializing and addressing multiple AGP
#   bridges using the agpgart driver.  In particular, it extends agp_acquire
#   and agp_allocate_memory so that different bridges can be acquired and
#   memory allocated within a specific AGP aperature.
#   
#   From: Brice Goglin <Brice.Goglin@ens-lyon.fr>
#   
#   It seems that memsetting the whole bridge structure to 0 (instead of juste
#   the agp_in_use field) fixes Benoit's problem too.  No idea which field was
#   responsible for this.  New patch attached.
#   
#   From: Mike Werner <werner@sgi.com>
#   
#   add bridge assignment missed in agp_allocate_memory
#   
#   From: Andi Kleen <ak@suse.de>
#   
#   Here's the correct fix. agp_bridge is defined in drivers/char/agp/agp.h.
#   It's a bit ugly though.
#   
#   Signed-off-by: Mike Werner <werner@sgi.com>
#   Signed-off-by: Andi Kleen <ak@suse.de>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# drivers/char/agp/generic.c
#   2005/02/23 18:12:04-05:00 davej@redhat.com +71 -47
#   [AGPGART] allow multiple backends to be initialized.
#   
#   From: Michael Werner <werner@mrcoffee.engr.sgi.com>
#   
#   This patch adds support for initializing and addressing multiple AGP
#   bridges using the agpgart driver.  In particular, it extends agp_acquire
#   and agp_allocate_memory so that different bridges can be acquired and
#   memory allocated within a specific AGP aperature.
#   
#   From: Brice Goglin <Brice.Goglin@ens-lyon.fr>
#   
#   It seems that memsetting the whole bridge structure to 0 (instead of juste
#   the agp_in_use field) fixes Benoit's problem too.  No idea which field was
#   responsible for this.  New patch attached.
#   
#   From: Mike Werner <werner@sgi.com>
#   
#   add bridge assignment missed in agp_allocate_memory
#   
#   From: Andi Kleen <ak@suse.de>
#   
#   Here's the correct fix. agp_bridge is defined in drivers/char/agp/agp.h.
#   It's a bit ugly though.
#   
#   Signed-off-by: Mike Werner <werner@sgi.com>
#   Signed-off-by: Andi Kleen <ak@suse.de>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# drivers/char/agp/frontend.c
#   2005/02/23 18:12:04-05:00 davej@redhat.com +17 -13
#   [AGPGART] allow multiple backends to be initialized.
#   
#   From: Michael Werner <werner@mrcoffee.engr.sgi.com>
#   
#   This patch adds support for initializing and addressing multiple AGP
#   bridges using the agpgart driver.  In particular, it extends agp_acquire
#   and agp_allocate_memory so that different bridges can be acquired and
#   memory allocated within a specific AGP aperature.
#   
#   From: Brice Goglin <Brice.Goglin@ens-lyon.fr>
#   
#   It seems that memsetting the whole bridge structure to 0 (instead of juste
#   the agp_in_use field) fixes Benoit's problem too.  No idea which field was
#   responsible for this.  New patch attached.
#   
#   From: Mike Werner <werner@sgi.com>
#   
#   add bridge assignment missed in agp_allocate_memory
#   
#   From: Andi Kleen <ak@suse.de>
#   
#   Here's the correct fix. agp_bridge is defined in drivers/char/agp/agp.h.
#   It's a bit ugly though.
#   
#   Signed-off-by: Mike Werner <werner@sgi.com>
#   Signed-off-by: Andi Kleen <ak@suse.de>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# drivers/char/agp/backend.c
#   2005/02/23 18:12:04-05:00 davej@redhat.com +60 -44
#   [AGPGART] allow multiple backends to be initialized.
#   
#   From: Michael Werner <werner@mrcoffee.engr.sgi.com>
#   
#   This patch adds support for initializing and addressing multiple AGP
#   bridges using the agpgart driver.  In particular, it extends agp_acquire
#   and agp_allocate_memory so that different bridges can be acquired and
#   memory allocated within a specific AGP aperature.
#   
#   From: Brice Goglin <Brice.Goglin@ens-lyon.fr>
#   
#   It seems that memsetting the whole bridge structure to 0 (instead of juste
#   the agp_in_use field) fixes Benoit's problem too.  No idea which field was
#   responsible for this.  New patch attached.
#   
#   From: Mike Werner <werner@sgi.com>
#   
#   add bridge assignment missed in agp_allocate_memory
#   
#   From: Andi Kleen <ak@suse.de>
#   
#   Here's the correct fix. agp_bridge is defined in drivers/char/agp/agp.h.
#   It's a bit ugly though.
#   
#   Signed-off-by: Mike Werner <werner@sgi.com>
#   Signed-off-by: Andi Kleen <ak@suse.de>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# drivers/char/agp/agp.h
#   2005/02/23 18:12:04-05:00 davej@redhat.com +3 -0
#   [AGPGART] allow multiple backends to be initialized.
#   
#   From: Michael Werner <werner@mrcoffee.engr.sgi.com>
#   
#   This patch adds support for initializing and addressing multiple AGP
#   bridges using the agpgart driver.  In particular, it extends agp_acquire
#   and agp_allocate_memory so that different bridges can be acquired and
#   memory allocated within a specific AGP aperature.
#   
#   From: Brice Goglin <Brice.Goglin@ens-lyon.fr>
#   
#   It seems that memsetting the whole bridge structure to 0 (instead of juste
#   the agp_in_use field) fixes Benoit's problem too.  No idea which field was
#   responsible for this.  New patch attached.
#   
#   From: Mike Werner <werner@sgi.com>
#   
#   add bridge assignment missed in agp_allocate_memory
#   
#   From: Andi Kleen <ak@suse.de>
#   
#   Here's the correct fix. agp_bridge is defined in drivers/char/agp/agp.h.
#   It's a bit ugly though.
#   
#   Signed-off-by: Mike Werner <werner@sgi.com>
#   Signed-off-by: Andi Kleen <ak@suse.de>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# arch/x86_64/kernel/pci-gart.c
#   2005/02/23 18:12:04-05:00 davej@redhat.com +1 -1
#   [AGPGART] allow multiple backends to be initialized.
#   
#   From: Michael Werner <werner@mrcoffee.engr.sgi.com>
#   
#   This patch adds support for initializing and addressing multiple AGP
#   bridges using the agpgart driver.  In particular, it extends agp_acquire
#   and agp_allocate_memory so that different bridges can be acquired and
#   memory allocated within a specific AGP aperature.
#   
#   From: Brice Goglin <Brice.Goglin@ens-lyon.fr>
#   
#   It seems that memsetting the whole bridge structure to 0 (instead of juste
#   the agp_in_use field) fixes Benoit's problem too.  No idea which field was
#   responsible for this.  New patch attached.
#   
#   From: Mike Werner <werner@sgi.com>
#   
#   add bridge assignment missed in agp_allocate_memory
#   
#   From: Andi Kleen <ak@suse.de>
#   
#   Here's the correct fix. agp_bridge is defined in drivers/char/agp/agp.h.
#   It's a bit ugly though.
#   
#   Signed-off-by: Mike Werner <werner@sgi.com>
#   Signed-off-by: Andi Kleen <ak@suse.de>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# ChangeSet
#   2005/02/23 18:02:50-05:00 davej@redhat.com 
#   [AGPGART] Rework AGPv2 rate verification.
#   
#   The spec says its valid for multiple bits to be set when we read rate,
#   however we must take care to ensure that we only write 1 bit back.
#   
#   This removes some bogus warnings that appeared on some boxes.
#   
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# drivers/char/agp/generic.c
#   2005/02/23 18:02:41-05:00 davej@redhat.com +18 -11
#   [AGPGART] Rework AGPv2 rate verification.
#   
#   The spec says its valid for multiple bits to be set when we read rate,
#   however we must take care to ensure that we only write 1 bit back.
#   
#   This removes some bogus warnings that appeared on some boxes.
#   
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# ChangeSet
#   2005/02/23 20:43:04+01:00 vojtech@suse.cz 
#   input: Add a missing ';' to hid-core.c
#   
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/usb/input/hid-core.c
#   2005/02/23 20:42:52+01:00 vojtech@suse.cz +1 -1
#   input: Add a missing ';' to hid-core.c
#   
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# ChangeSet
#   2005/02/23 19:37:57+01:00 vojtech@suse.cz 
#   Manual merge
# 
# drivers/input/mouse/alps.c
#   2005/02/23 19:37:51+01:00 vojtech@suse.cz +0 -2
#   Manual merge
# 
# ChangeSet
#   2005/02/23 12:37:52-05:00 davej@redhat.com 
#   [AGPGART] aper_base can't be signed.
#   
#   We pass this to remap_pfn_range after shifting it right.
#   Nasty things happen as a result.
#   
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# include/linux/agp_backend.h
#   2005/02/23 12:37:43-05:00 davej@redhat.com +3 -3
#   [AGPGART] aper_base can't be signed.
#   
#   We pass this to remap_pfn_range after shifting it right.
#   Nasty things happen as a result.
#   
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# ChangeSet
#   2005/02/23 12:36:42-05:00 davej@redhat.com 
#   [AGPGART] Compile fixes.
#   
#   Somehow the conversion to the extra arg for agp_collect_device_status() got dropped.
#   
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# drivers/char/agp/sworks-agp.c
#   2005/02/23 12:36:32-05:00 davej@redhat.com +1 -1
#   [AGPGART] Compile fixes.
#   
#   Somehow the conversion to the extra arg for agp_collect_device_status() got dropped.
#   
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# drivers/char/agp/sis-agp.c
#   2005/02/23 12:36:32-05:00 davej@redhat.com +3 -3
#   [AGPGART] Compile fixes.
#   
#   Somehow the conversion to the extra arg for agp_collect_device_status() got dropped.
#   
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# drivers/input/serio/sa1111ps2.c
#   2005/02/23 17:49:58+01:00 vojtech@suse.cz +0 -0
#   Auto merged
# 
# drivers/input/serio/ambakmi.c
#   2005/02/23 17:49:58+01:00 vojtech@suse.cz +0 -0
#   Auto merged
# 
# ChangeSet
#   2005/02/23 17:40:00+01:00 vojtech@suse.cz 
#   input: Fix keyboard scrollwheel support, add horizontal
#          wheel support, and enable both by default.
#   
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/keyboard/atkbd.c
#   2005/02/23 17:39:54+01:00 vojtech@suse.cz +32 -22
#   input: Fix keyboard scrollwheel support, add horizontal
#          wheel support, and enable both by default.
#   
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# ChangeSet
#   2005/02/23 03:46:53-05:00 davej@redhat.com 
#   [AGPGART] yet more whitespace removal.
#   
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# drivers/char/agp/frontend.c
#   2005/02/23 03:46:44-05:00 davej@redhat.com +20 -20
#   [AGPGART] yet more whitespace removal.
#   
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# ChangeSet
#   2005/02/22 19:23:21-08:00 davem@nuts.davemloft.net 
#   Merge nuts.davemloft.net:/disk1/BK/network-2.6.12
#   into nuts.davemloft.net:/disk1/BK/net-2.6.12
# 
# net/xfrm/xfrm_policy.c
#   2005/02/22 19:23:09-08:00 davem@nuts.davemloft.net +0 -0
#   Auto merged
# 
# net/ipv6/tcp_ipv6.c
#   2005/02/22 19:23:09-08:00 davem@nuts.davemloft.net +0 -0
#   Auto merged
# 
# net/ipv4/tcp_ipv4.c
#   2005/02/22 19:23:09-08:00 davem@nuts.davemloft.net +0 -0
#   Auto merged
# 
# net/ipv4/route.c
#   2005/02/22 19:23:09-08:00 davem@nuts.davemloft.net +0 -0
#   Auto merged
# 
# kernel/workqueue.c
#   2005/02/22 19:23:08-08:00 davem@nuts.davemloft.net +0 -0
#   Auto merged
# 
# ChangeSet
#   2005/02/22 22:00:10-05:00 davej@redhat.com 
#   [AGPGART] i810 suspend/resume support.
#   
#   From Nigel Cunningham/Karol Kozimor
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# drivers/char/agp/intel-agp.c
#   2005/02/22 22:00:00-05:00 davej@redhat.com +2 -0
#   [AGPGART] i810 suspend/resume support.
#   
#   From Nigel Cunningham/Karol Kozimor
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# ChangeSet
#   2005/02/22 21:53:10-05:00 davej@delerium.kernelslacker.org 
#   [AGPGART] Convert from pci_module_init to pci_register_driver
#   
#   Signed-off-by: Christophe Lucas <c.lucas@ifrance.com>
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# drivers/char/agp/via-agp.c
#   2005/02/22 19:56:06-05:00 davej@delerium.kernelslacker.org +1 -1
#   [AGPGART] Convert from pci_module_init to pci_register_driver
#   
#   Signed-off-by: Christophe Lucas <c.lucas@ifrance.com>
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# drivers/char/agp/uninorth-agp.c
#   2005/02/22 19:56:06-05:00 davej@delerium.kernelslacker.org +1 -1
#   [AGPGART] Convert from pci_module_init to pci_register_driver
#   
#   Signed-off-by: Christophe Lucas <c.lucas@ifrance.com>
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# drivers/char/agp/sworks-agp.c
#   2005/02/22 19:56:06-05:00 davej@delerium.kernelslacker.org +1 -1
#   [AGPGART] Convert from pci_module_init to pci_register_driver
#   
#   Signed-off-by: Christophe Lucas <c.lucas@ifrance.com>
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# drivers/char/agp/sis-agp.c
#   2005/02/22 19:56:06-05:00 davej@delerium.kernelslacker.org +1 -1
#   [AGPGART] Convert from pci_module_init to pci_register_driver
#   
#   Signed-off-by: Christophe Lucas <c.lucas@ifrance.com>
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# drivers/char/agp/nvidia-agp.c
#   2005/02/22 19:56:06-05:00 davej@delerium.kernelslacker.org +1 -1
#   [AGPGART] Convert from pci_module_init to pci_register_driver
#   
#   Signed-off-by: Christophe Lucas <c.lucas@ifrance.com>
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# drivers/char/agp/intel-agp.c
#   2005/02/22 19:56:06-05:00 davej@delerium.kernelslacker.org +1 -1
#   [AGPGART] Convert from pci_module_init to pci_register_driver
#   
#   Signed-off-by: Christophe Lucas <c.lucas@ifrance.com>
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# drivers/char/agp/i460-agp.c
#   2005/02/22 19:56:06-05:00 davej@delerium.kernelslacker.org +1 -1
#   [AGPGART] Convert from pci_module_init to pci_register_driver
#   
#   Signed-off-by: Christophe Lucas <c.lucas@ifrance.com>
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# drivers/char/agp/efficeon-agp.c
#   2005/02/22 19:56:06-05:00 davej@delerium.kernelslacker.org +1 -1
#   [AGPGART] Convert from pci_module_init to pci_register_driver
#   
#   Signed-off-by: Christophe Lucas <c.lucas@ifrance.com>
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# drivers/char/agp/ati-agp.c
#   2005/02/22 19:56:06-05:00 davej@delerium.kernelslacker.org +1 -1
#   [AGPGART] Convert from pci_module_init to pci_register_driver
#   
#   Signed-off-by: Christophe Lucas <c.lucas@ifrance.com>
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# drivers/char/agp/amd64-agp.c
#   2005/02/22 19:56:06-05:00 davej@delerium.kernelslacker.org +1 -1
#   [AGPGART] Convert from pci_module_init to pci_register_driver
#   
#   Signed-off-by: Christophe Lucas <c.lucas@ifrance.com>
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# drivers/char/agp/amd-k7-agp.c
#   2005/02/22 19:56:06-05:00 davej@delerium.kernelslacker.org +1 -1
#   [AGPGART] Convert from pci_module_init to pci_register_driver
#   
#   Signed-off-by: Christophe Lucas <c.lucas@ifrance.com>
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# drivers/char/agp/ali-agp.c
#   2005/02/22 19:56:06-05:00 davej@delerium.kernelslacker.org +1 -1
#   [AGPGART] Convert from pci_module_init to pci_register_driver
#   
#   Signed-off-by: Christophe Lucas <c.lucas@ifrance.com>
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# ChangeSet
#   2005/02/22 21:35:30-05:00 davej@delerium.kernelslacker.org 
#   [AGPGART] Drop the Intel-mch AGP driver.
#   
#   Andi Kleen points out that the intel-agp driver actually works on i865's, where
#   the -mch driver doesn't.  The -mch driver was something of a failed experiment.
#   Hoping that the code would be much cleaner, I forked the intel-agp driver into
#   this variant, and removed some legacy bits. The result was a third the size,
#   but it still was no work of art, worse yet -- it didn't even do what it said on the can.
#   
#   intel-agp still supports everything that the -mch driver did, so we can just
#   remove this from the tree and fall back to the old driver.
#   
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# BitKeeper/deleted/.del-intel-mch-agp.c~ada34657bfa6d42b
#   2005/02/22 21:35:14-05:00 davej@delerium.kernelslacker.org +0 -0
#   Delete: drivers/char/agp/intel-mch-agp.c
# 
# drivers/char/agp/Makefile
#   2005/02/22 19:55:59-05:00 davej@delerium.kernelslacker.org +0 -1
#   [AGPGART] Drop the Intel-mch AGP driver.
#   
#   Andi Kleen points out that the intel-agp driver actually works on i865's, where
#   the -mch driver doesn't.  The -mch driver was something of a failed experiment.
#   Hoping that the code would be much cleaner, I forked the intel-agp driver into
#   this variant, and removed some legacy bits. The result was a third the size,
#   but it still was no work of art, worse yet -- it didn't even do what it said on the can.
#   
#   intel-agp still supports everything that the -mch driver did, so we can just
#   remove this from the tree and fall back to the old driver.
#   
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# drivers/char/agp/Kconfig
#   2005/02/22 19:55:59-05:00 davej@delerium.kernelslacker.org +0 -10
#   [AGPGART] Drop the Intel-mch AGP driver.
#   
#   Andi Kleen points out that the intel-agp driver actually works on i865's, where
#   the -mch driver doesn't.  The -mch driver was something of a failed experiment.
#   Hoping that the code would be much cleaner, I forked the intel-agp driver into
#   this variant, and removed some legacy bits. The result was a third the size,
#   but it still was no work of art, worse yet -- it didn't even do what it said on the can.
#   
#   intel-agp still supports everything that the -mch driver did, so we can just
#   remove this from the tree and fall back to the old driver.
#   
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# arch/x86_64/defconfig
#   2005/02/22 19:55:59-05:00 davej@delerium.kernelslacker.org +0 -1
#   [AGPGART] Drop the Intel-mch AGP driver.
#   
#   Andi Kleen points out that the intel-agp driver actually works on i865's, where
#   the -mch driver doesn't.  The -mch driver was something of a failed experiment.
#   Hoping that the code would be much cleaner, I forked the intel-agp driver into
#   this variant, and removed some legacy bits. The result was a third the size,
#   but it still was no work of art, worse yet -- it didn't even do what it said on the can.
#   
#   intel-agp still supports everything that the -mch driver did, so we can just
#   remove this from the tree and fall back to the old driver.
#   
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# arch/i386/defconfig
#   2005/02/22 19:55:59-05:00 davej@delerium.kernelslacker.org +0 -1
#   [AGPGART] Drop the Intel-mch AGP driver.
#   
#   Andi Kleen points out that the intel-agp driver actually works on i865's, where
#   the -mch driver doesn't.  The -mch driver was something of a failed experiment.
#   Hoping that the code would be much cleaner, I forked the intel-agp driver into
#   this variant, and removed some legacy bits. The result was a third the size,
#   but it still was no work of art, worse yet -- it didn't even do what it said on the can.
#   
#   intel-agp still supports everything that the -mch driver did, so we can just
#   remove this from the tree and fall back to the old driver.
#   
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# ChangeSet
#   2005/02/22 21:27:52-05:00 davej@delerium.kernelslacker.org 
#   [AGPGART] Lower 7 bits of TLB flush register must be zero.
#   
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# drivers/char/agp/via-agp.c
#   2005/02/22 19:55:02-05:00 davej@delerium.kernelslacker.org +2 -0
#   [AGPGART] Lower 7 bits of TLB flush register must be zero.
#   
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# ChangeSet
#   2005/02/22 21:27:37-05:00 davej@delerium.kernelslacker.org 
#   [AGPGART] Various "I'm a dumbass" compile fixes.
#   
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# drivers/char/agp/via-agp.c
#   2005/02/22 19:55:09-05:00 davej@delerium.kernelslacker.org +4 -4
#   [AGPGART] Various "I'm a dumbass" compile fixes.
#   
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# ChangeSet
#   2005/02/22 21:27:22-05:00 davej@delerium.kernelslacker.org 
#   [AGPGART] Don't clobber other bits in control register when flushing TLB on VIA.
#   
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# drivers/char/agp/via-agp.c
#   2005/02/22 19:55:17-05:00 davej@delerium.kernelslacker.org +7 -2
#   [AGPGART] Don't clobber other bits in control register when flushing TLB on VIA.
#   
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# ChangeSet
#   2005/02/22 21:27:07-05:00 davej@delerium.kernelslacker.org 
#   [AGPGART] VIA AGPGARTs can support really small aperture sizes.
#   
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# drivers/char/agp/via-agp.c
#   2005/02/22 19:55:24-05:00 davej@delerium.kernelslacker.org +2 -0
#   [AGPGART] VIA AGPGARTs can support really small aperture sizes.
#   
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# ChangeSet
#   2005/02/22 21:26:52-05:00 davej@delerium.kernelslacker.org 
#   [AGPGART] Trailing whitespace removal de jour.
#   
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# drivers/char/agp/via-agp.c
#   2005/02/22 19:55:31-05:00 davej@delerium.kernelslacker.org +4 -4
#   [AGPGART] Trailing whitespace removal de jour.
#   
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# ChangeSet
#   2005/02/22 21:26:36-05:00 davej@delerium.kernelslacker.org 
#   [AGPGART] Print diagnostic info when failing to determine aperture size on VIA systems.
#   
#   I've seen this happen a few times, and never got to the bottom of it, so hopefully
#   this will make things a little easier to diagnose what's going on.
#   
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# drivers/char/agp/via-agp.c
#   2005/02/22 19:55:38-05:00 davej@delerium.kernelslacker.org +1 -0
#   [AGPGART] Print diagnostic info when failing to determine aperture size on VIA systems.
#   
#   I've seen this happen a few times, and never got to the bottom of it, so hopefully
#   this will make things a little easier to diagnose what's going on.
#   
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# ChangeSet
#   2005/02/22 21:26:21-05:00 davej@delerium.kernelslacker.org 
#   [AGPGART] Trailing whitespace removal.
#   
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# drivers/char/agp/backend.c
#   2005/02/22 19:55:45-05:00 davej@delerium.kernelslacker.org +6 -6
#   [AGPGART] Trailing whitespace removal.
#   
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# ChangeSet
#   2005/02/22 21:26:04-05:00 davej@delerium.kernelslacker.org 
#   [AGPGART] Make agp=off boot param work for Intel AGP drivers.
#   
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# drivers/char/agp/intel-mch-agp.c
#   2005/02/22 19:56:13-05:00 davej@delerium.kernelslacker.org +2 -0
#   [AGPGART] Make agp=off boot param work for Intel AGP drivers.
#   
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# drivers/char/agp/intel-agp.c
#   2005/02/22 19:56:13-05:00 davej@delerium.kernelslacker.org +2 -0
#   [AGPGART] Make agp=off boot param work for Intel AGP drivers.
#   
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# ChangeSet
#   2005/02/22 21:25:49-05:00 davej@delerium.kernelslacker.org 
#   [AGPGART] Make sure we don't give up searching for gfx cards.
#   
#   We need to clear the previously found cap_ptr, or we exit after
#   finding the first one, even if its not the one plugged into the
#   bridge we're looking at.
#   
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# drivers/char/agp/generic.c
#   2005/02/22 19:56:20-05:00 davej@delerium.kernelslacker.org +1 -0
#   [AGPGART] Make sure we don't give up searching for gfx cards.
#   
#   We need to clear the previously found cap_ptr, or we exit after
#   finding the first one, even if its not the one plugged into the
#   bridge we're looking at.
#   
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# ChangeSet
#   2005/02/22 21:25:18-05:00 davej@delerium.kernelslacker.org 
#   [AGPGART] Silly thinko in reserve bit masking.
#   
#   Stupid inversion meant we passed '0' to userspace, and madness
#   ensued resulting in very funky visuals.
#   
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# drivers/char/agp/generic.c
#   2005/02/22 19:56:34-05:00 davej@delerium.kernelslacker.org +2 -2
#   [AGPGART] Silly thinko in reserve bit masking.
#   
#   Stupid inversion meant we passed '0' to userspace, and madness
#   ensued resulting in very funky visuals.
#   
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# ChangeSet
#   2005/02/22 21:25:03-05:00 davej@delerium.kernelslacker.org 
#   [AGPGART] Fix the same pci_get_class bug in the amd-k7 driver.
#   
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# drivers/char/agp/amd-k7-agp.c
#   2005/02/22 19:56:41-05:00 davej@delerium.kernelslacker.org +1 -1
#   [AGPGART] Fix the same pci_get_class bug in the amd-k7 driver.
#   
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# ChangeSet
#   2005/02/22 21:24:48-05:00 davej@delerium.kernelslacker.org 
#   [AGPGART] Fix stupid thinko in device discovery.
#   
#   Should fix the 'cant find AGP VGA controller' warnings.
#   
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# drivers/char/agp/generic.c
#   2005/02/22 19:56:48-05:00 davej@delerium.kernelslacker.org +1 -1
#   [AGPGART] Fix stupid thinko in device discovery.
#   
#   Should fix the 'cant find AGP VGA controller' warnings.
#   
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# ChangeSet
#   2005/02/22 21:24:32-05:00 davej@delerium.kernelslacker.org 
#   [AGPGART] In AGP2.0 mode, if we're in 1X mode, disable fast writes.
#   
#   In this mode, fast writes are just ignored, and treated as regular PCI
#   writes, but disabling them explicitly doesn't hurt.
#   
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# drivers/char/agp/generic.c
#   2005/02/22 19:56:55-05:00 davej@delerium.kernelslacker.org +4 -0
#   [AGPGART] In AGP2.0 mode, if we're in 1X mode, disable fast writes.
#   
#   In this mode, fast writes are just ignored, and treated as regular PCI
#   writes, but disabling them explicitly doesn't hurt.
#   
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# ChangeSet
#   2005/02/22 21:24:12-05:00 davej@delerium.kernelslacker.org 
#   [AGPGART] Mask out the reserved bits of the agp mode register before handing them to userspace.
#   
#   X munges what we hand to it, so with luck, this will lower the possibility
#   of it handing us something with reserved bits set.
#   
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# drivers/char/agp/generic.c
#   2005/02/22 19:57:02-05:00 davej@delerium.kernelslacker.org +17 -14
#   [AGPGART] Mask out the reserved bits of the agp mode register before handing them to userspace.
#   
#   X munges what we hand to it, so with luck, this will lower the possibility
#   of it handing us something with reserved bits set.
#   
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# ChangeSet
#   2005/02/22 21:23:57-05:00 davej@delerium.kernelslacker.org 
#   [AGPGART] Introduce routine to check current operating mode of agp bridge.
#   
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# drivers/char/agp/generic.c
#   2005/02/22 19:57:08-05:00 davej@delerium.kernelslacker.org +17 -11
#   [AGPGART] Introduce routine to check current operating mode of agp bridge.
#   
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# ChangeSet
#   2005/02/22 21:23:42-05:00 davej@delerium.kernelslacker.org 
#   [AGPGART] Remove pointless tests for bridge vendor from amd-k7-agp driver.
#   
#   If we got far enough to run this code, we *must* have an AMD bridge.
#   
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# drivers/char/agp/amd-k7-agp.c
#   2005/02/22 19:57:15-05:00 davej@delerium.kernelslacker.org +2 -4
#   [AGPGART] Remove pointless tests for bridge vendor from amd-k7-agp driver.
#   
#   If we got far enough to run this code, we *must* have an AMD bridge.
#   
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# ChangeSet
#   2005/02/22 21:23:27-05:00 davej@delerium.kernelslacker.org 
#   [AGPGART] AMD 751 errata workaround.
#   Some combinations of NVidia GeForce cards and this AGP chipset cause lockups
#   when operated in AGP x2 mode. Force them to x1 mode for safety.
#   
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# drivers/char/agp/amd-k7-agp.c
#   2005/02/22 19:57:22-05:00 davej@delerium.kernelslacker.org +31 -0
#   [AGPGART] AMD 751 errata workaround.
#   Some combinations of NVidia GeForce cards and this AGP chipset cause lockups
#   when operated in AGP x2 mode. Force them to x1 mode for safety.
#   
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# ChangeSet
#   2005/02/22 21:23:12-05:00 davej@delerium.kernelslacker.org 
#   [AGPGART] AMD 761 errata workaround.
#   B0/B1 steppings of this chipset were horribly broken,
#   and couldn't do fast writes, or side band addressing.
#   Looking through the errata on this one reads like a horror story, it's
#   a miracle it could get AGP x1 working.
#   
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# drivers/char/agp/amd-k7-agp.c
#   2005/02/22 19:57:29-05:00 davej@delerium.kernelslacker.org +18 -0
#   [AGPGART] AMD 761 errata workaround.
#   B0/B1 steppings of this chipset were horribly broken,
#   and couldn't do fast writes, or side band addressing.
#   Looking through the errata on this one reads like a horror story, it's
#   a miracle it could get AGP x1 working.
#   
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# ChangeSet
#   2005/02/22 21:22:57-05:00 davej@delerium.kernelslacker.org 
#   [AGPGART] Add mechanism for chipset specific errata.
#   
#   Allow chipset drivers to tell the generic routines not to enable
#   certain features if they have errata when those features are used. 
#   
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# drivers/char/agp/generic.c
#   2005/02/22 19:57:36-05:00 davej@delerium.kernelslacker.org +29 -3
#   [AGPGART] Add mechanism for chipset specific errata.
#   
#   Allow chipset drivers to tell the generic routines not to enable
#   certain features if they have errata when those features are used. 
#   
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# drivers/char/agp/agp.h
#   2005/02/22 19:57:36-05:00 davej@delerium.kernelslacker.org +5 -0
#   [AGPGART] Add mechanism for chipset specific errata.
#   
#   Allow chipset drivers to tell the generic routines not to enable
#   certain features if they have errata when those features are used. 
#   
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# ChangeSet
#   2005/02/22 21:22:42-05:00 davej@delerium.kernelslacker.org 
#   [AGPGART] Name & Shame the apps passing bad flags.
#   (Basically a distinction between XFree and Xorg)
#   
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# drivers/char/agp/generic.c
#   2005/02/22 19:57:43-05:00 davej@delerium.kernelslacker.org +6 -6
#   [AGPGART] Name & Shame the apps passing bad flags.
#   (Basically a distinction between XFree and Xorg)
#   
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# ChangeSet
#   2005/02/22 21:22:27-05:00 davej@delerium.kernelslacker.org 
#   [AGPGART] Do some sanity checks on the rates that userspace passes.
#   
#   The AGP specifications define the following...
#   
#         agp2 agp3
#   000   BAD  BAD
#   001   x1   x4
#   010   x2   x8
#   011   BAD  x8
#   100   x4   BAD
#   101   BAD  BAD
#   110   BAD  BAD
#   111   BAD  BAD
#   
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# drivers/char/agp/generic.c
#   2005/02/22 19:57:50-05:00 davej@delerium.kernelslacker.org +33 -0
#   [AGPGART] Do some sanity checks on the rates that userspace passes.
#   
#   The AGP specifications define the following...
#   
#         agp2 agp3
#   000   BAD  BAD
#   001   x1   x4
#   010   x2   x8
#   011   BAD  x8
#   100   x4   BAD
#   101   BAD  BAD
#   110   BAD  BAD
#   111   BAD  BAD
#   
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# ChangeSet
#   2005/02/22 21:22:11-05:00 davej@delerium.kernelslacker.org 
#   [AGPGART] Fix up the reserved bits.
#   The previous checks were against AGP_STAT values, but userspace passes us
#   an agp command register.
# 
# drivers/char/agp/agp.h
#   2005/02/22 19:57:57-05:00 davej@delerium.kernelslacker.org +2 -2
#   [AGPGART] Fix up the reserved bits.
#   The previous checks were against AGP_STAT values, but userspace passes us
#   an agp command register.
# 
# ChangeSet
#   2005/02/22 21:21:55-05:00 davej@delerium.kernelslacker.org 
#   [AGPGART] Warn and fix up mode if userspace passes nonsense.
#   Check the reserved bits in the agp mode register.
#   
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# drivers/char/agp/generic.c
#   2005/02/22 19:58:04-05:00 davej@delerium.kernelslacker.org +11 -1
#   [AGPGART] Warn and fix up mode if userspace passes nonsense.
#   Check the reserved bits in the agp mode register.
#   
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# drivers/char/agp/agp.h
#   2005/02/22 19:58:04-05:00 davej@delerium.kernelslacker.org +3 -0
#   [AGPGART] Warn and fix up mode if userspace passes nonsense.
#   Check the reserved bits in the agp mode register.
#   
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# ChangeSet
#   2005/02/22 21:21:40-05:00 davej@delerium.kernelslacker.org 
#   [AGPGART] Check the bridge is in 3.0 mode, not the graphic card.
#   
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# drivers/char/agp/generic.c
#   2005/02/22 19:58:11-05:00 davej@delerium.kernelslacker.org +4 -3
#   [AGPGART] Check the bridge is in 3.0 mode, not the graphic card.
#   
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# drivers/char/agp/agp.h
#   2005/02/22 19:58:11-05:00 davej@delerium.kernelslacker.org +1 -1
#   [AGPGART] Check the bridge is in 3.0 mode, not the graphic card.
#   
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# ChangeSet
#   2005/02/22 21:21:25-05:00 davej@delerium.kernelslacker.org 
#   [AGPGART] Fix refcount bug in mode parsing code.
#   
#   The pci_get_class conversion leaked this refcount.
#   
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# drivers/char/agp/generic.c
#   2005/02/22 19:58:17-05:00 davej@delerium.kernelslacker.org +4 -3
#   [AGPGART] Fix refcount bug in mode parsing code.
#   
#   The pci_get_class conversion leaked this refcount.
#   
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# ChangeSet
#   2005/02/22 21:21:09-05:00 davej@delerium.kernelslacker.org 
#   [AGPGART] Rename a bunch of ambiguous variables.
#   mode = What X wants us to set the mode to (As set by AGPMode in X config)
#   cmd = PCI_AGP_STATUS from the AGP bridge.
#   tmp = PCI_AGP_STATUS from the graphic card.
#   
#   mode -> requested_mode
#   cmd -> bridge_agpstat
#   tmp -> vga_agpstat
#   
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# drivers/char/agp/generic.c
#   2005/02/22 19:58:24-05:00 davej@delerium.kernelslacker.org +74 -72
#   [AGPGART] Rename a bunch of ambiguous variables.
#   mode = What X wants us to set the mode to (As set by AGPMode in X config)
#   cmd = PCI_AGP_STATUS from the AGP bridge.
#   tmp = PCI_AGP_STATUS from the graphic card.
#   
#   mode -> requested_mode
#   cmd -> bridge_agpstat
#   tmp -> vga_agpstat
#   
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# ChangeSet
#   2005/02/22 21:20:54-05:00 davej@delerium.kernelslacker.org 
#   [AGPGART] Don't scan whole bus for a VGA card.
#   Use the handy pci_get_class() function instead of implementing our own
#   pci bus walking loop.  Also makes it skip non-VGA devices fixing up a
#   long-standing FIXME. Previously, it may have been tripping up on AGP
#   bridges, which could have caused all sorts of sillyness.
#   
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# drivers/char/agp/generic.c
#   2005/02/22 19:58:31-05:00 davej@delerium.kernelslacker.org +45 -29
#   [AGPGART] Don't scan whole bus for a VGA card.
#   Use the handy pci_get_class() function instead of implementing our own
#   pci bus walking loop.  Also makes it skip non-VGA devices fixing up a
#   long-standing FIXME. Previously, it may have been tripping up on AGP
#   bridges, which could have caused all sorts of sillyness.
#   
#   Signed-off-by: Dave Jones <davej@redhat.com>
# 
# ChangeSet
#   2005/02/22 21:09:45-05:00 jgarzik@pobox.com 
#   Merge pobox.com:/garz/repo/linux-2.6
#   into pobox.com:/garz/repo/netdev-2.6/mii
# 
# drivers/net/tg3.h
#   2005/02/22 21:09:42-05:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# ChangeSet
#   2005/02/22 20:56:28-05:00 bunk@stusta.de 
#   [PATCH] drivers/net/via-rhine.c: make a variable static const
#   
#   This patch makes a needlessly global variable static const.
#   
#   Signed-off-by: Adrian Bunk <bunk@stusta.de>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/via-rhine.c
#   2005/02/16 12:57:05-05:00 bunk@stusta.de +1 -1
#   drivers/net/via-rhine.c: make a variable static const
# 
# ChangeSet
#   2005/02/22 20:56:12-05:00 bunk@stusta.de 
#   [PATCH] drivers/net/sb1000.c: make some variables static
#   
#   This patch makes some needlessly global variables static.
#   
#   Signed-off-by: Adrian Bunk <bunk@stusta.de>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/sb1000.c
#   2005/02/21 09:16:35-05:00 bunk@stusta.de +4 -4
#   drivers/net/sb1000.c: make some variables static
# 
# ChangeSet
#   2005/02/22 20:55:59-05:00 bunk@stusta.de 
#   [PATCH] drivers/net/lp486e.c: make some code static
#   
#   This patch makes some needlessly global code static and makes
#   CUcmdnames const.
#   
#   Signed-off-by: Adrian Bunk <bunk@stusta.de>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/lp486e.c
#   2005/02/16 10:15:33-05:00 bunk@stusta.de +5 -3
#   drivers/net/lp486e.c: make some code static
# 
# ChangeSet
#   2005/02/22 20:50:18-05:00 jgarzik@pobox.com 
#   Merge pobox.com:/garz/repo/linux-2.6
#   into pobox.com:/garz/repo/netdev-2.6/janitor
# 
# drivers/net/s2io.c
#   2005/02/22 20:50:15-05:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# ChangeSet
#   2005/02/22 16:44:56-07:00 dale@farnsworth.org 
#   [netdrvr mv643xx] Remove call to msleep() while locks are held.  We don't really need to
#   wait for the link to come up.  It was a workaround to avoid a transient
#   error message, "Virtual device %s asks to queue packet!\n", in
#   dev_queue_xmit() when called by ic_bootp_send_if().  This happens because
#   right after opening the network device, there is a pending PHY status
#   change interrupt causing the driver to call netif_stop_queue().  A half
#   second later, the link comes up and all is well.  We could have moved
#   the call to msleep() to mv643xx_eth_open() to perpetuate the workaround,
#   but I think it's best to remove it entirely.
#   
#   Signed-off-by: Dale Farnsworth <dale@farnsworth.org>
# 
# drivers/net/mv643xx_eth.c
#   2005/02/22 16:44:39-07:00 dale@farnsworth.org +0 -5
#   Remove call to msleep() while locks are held.  We don't really need to
#   wait for the link to come up.  It was a workaround to avoid a transient
#   error message, "Virtual device %s asks to queue packet!\n", in
#   dev_queue_xmit() when called by ic_bootp_send_if().  This happens because
#   right after opening the network device, there is a pending PHY status
#   change interrupt causing the driver to call netif_stop_queue().  A half
#   second later, the link comes up and all is well.  We could have moved
#   the call to msleep() to mv643xx_eth_open() to perpetuate the workaround,
#   but I think it's best to remove it entirely.
#   
#   Signed-off-by: Dale Farnsworth <dale@farnsworth.org>
# 
# ChangeSet
#   2005/02/22 16:34:46-07:00 dale@farnsworth.org 
#   [netdrvr mv643xx] Ensure that we only change the Port Serial Control Reg while the port is
#   disabled.
#   
#   Signed-off-by: Dale Farnsworth <dale@farnsworth.org>
# 
# drivers/net/mv643xx_eth.c
#   2005/02/22 16:34:28-07:00 dale@farnsworth.org +17 -19
#   Ensure that we only change the Port Serial Control Reg while the port is
#   disabled.
#   
#   Signed-off-by: Dale Farnsworth <dale@farnsworth.org>
# 
# ChangeSet
#   2005/02/21 11:07:58+01:00 vojtech@suse.cz 
#   input: Fix a few conditions in power.c, which kept it from doint
#          anything at all.
#   
#   Found-by: BJ Douma <bjdouma@xs4all.nl>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/power.c
#   2005/02/21 11:07:46+01:00 vojtech@suse.cz +3 -9
#   input: Fix a few conditions in power.c, which kept it from doint
#          anything at all:
#   
#   Found-by: BJ Douma <bjdouma@xs4all.nl>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# ChangeSet
#   2005/02/20 21:11:56-05:00 mallikarjuna.chilakala@intel.com 
#   [PATCH] e1000: Driver version white space,
#   
#   10 Driver version number, white space, comments, device id & other changes
#   Signed-off-by: Mallikarjuna R Chilakala <mallikarjuna.chilakala@intel.com>
#   Signed-off-by: Ganesh Venkatesan <ganesh.venkatesan@intel.com>
#   Signed-off-by: John Ronciak <john.ronciak@intel.com>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/e1000/e1000_main.c
#   2005/02/02 02:10:27-05:00 mallikarjuna.chilakala@intel.com +13 -7
#   e1000: Driver version white space,
# 
# drivers/net/e1000/e1000_hw.h
#   2005/02/02 02:10:27-05:00 mallikarjuna.chilakala@intel.com +9 -2
#   e1000: Driver version white space,
# 
# drivers/net/e1000/e1000_hw.c
#   2005/02/02 02:10:27-05:00 mallikarjuna.chilakala@intel.com +4 -5
#   e1000: Driver version white space,
# 
# ChangeSet
#   2005/02/20 21:11:41-05:00 mallikarjuna.chilakala@intel.com 
#   [PATCH] e1000: Fixes related to Cable length
#   
#   9 Fixes related to Cable length estimation
#   Signed-off-by: Mallikarjuna R Chilakala <mallikarjuna.chilakala@intel.com>
#   Signed-off-by: Ganesh Venkatesan <ganesh.venkatesan@intel.com>
#   Signed-off-by: John Ronciak <john.ronciak@intel.com>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/e1000/e1000_hw.c
#   2005/02/02 02:10:27-05:00 mallikarjuna.chilakala@intel.com +42 -37
#   e1000: Fixes related to Cable length
# 
# ChangeSet
#   2005/02/20 21:11:30-05:00 mallikarjuna.chilakala@intel.com 
#   [PATCH] e1000: Report failure code when loopback
#   
#   8 Report failure code when loopback test fails
#   Signed-off-by: Mallikarjuna R Chilakala <mallikarjuna.chilakala@intel.com>
#   Signed-off-by: Ganesh Venkatesan <ganesh.venkatesan@intel.com>
#   Signed-off-by: John Ronciak <john.ronciak@intel.com>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/e1000/e1000_ethtool.c
#   2005/02/02 02:10:26-05:00 mallikarjuna.chilakala@intel.com +6 -5
#   e1000: Report failure code when loopback
# 
# ChangeSet
#   2005/02/20 21:11:15-05:00 mallikarjuna.chilakala@intel.com 
#   [PATCH] e1000: Checks for desc ring/rx data
#   
#   7 Add checks for desc ring/rx data bufs spanning 64k address boundary
#   Signed-off-by: Mallikarjuna R Chilakala <mallikarjuna.chilakala@intel.com>
#   Signed-off-by: Ganesh Venkatesan <ganesh.venkatesan@intel.com>
#   Signed-off-by: John Ronciak <john.ronciak@intel.com>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/e1000/e1000_main.c
#   2005/02/02 02:10:27-05:00 mallikarjuna.chilakala@intel.com +133 -2
#   e1000: Checks for desc ring/rx data
# 
# ChangeSet
#   2005/02/20 21:11:01-05:00 mallikarjuna.chilakala@intel.com 
#   [PATCH] e1000: Patch from Peter Kjellstroem --
#   
#   6 Patch from Peter Kjellstroem -- fix lockup with 82547
#   Signed-off-by: Mallikarjuna R Chilakala <mallikarjuna.chilakala@intel.com>
#   Signed-off-by: Ganesh Venkatesan <ganesh.venkatesan@intel.com>
#   Signed-off-by: John Ronciak <john.ronciak@intel.com>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/e1000/e1000_main.c
#   2005/02/02 02:10:27-05:00 mallikarjuna.chilakala@intel.com +18 -0
#   e1000: Patch from Peter Kjellstroem --
# 
# ChangeSet
#   2005/02/20 21:10:46-05:00 mallikarjuna.chilakala@intel.com 
#   [PATCH] e1000: Fix WOL settings in 82544 based
#   
#   5 Fix WOL settings in 82544 based adapters
#   Signed-off-by: Mallikarjuna R Chilakala <mallikarjuna.chilakala@intel.com>
#   Signed-off-by: Ganesh Venkatesan <ganesh.venkatesan@intel.com>
#   Signed-off-by: John Ronciak <john.ronciak@intel.com>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/e1000/e1000_main.c
#   2005/02/02 02:10:27-05:00 mallikarjuna.chilakala@intel.com +7 -1
#   e1000: Fix WOL settings in 82544 based
# 
# drivers/net/e1000/e1000.h
#   2005/02/02 02:10:26-05:00 mallikarjuna.chilakala@intel.com +1 -0
#   e1000: Fix WOL settings in 82544 based
# 
# ChangeSet
#   2005/02/20 21:10:31-05:00 mallikarjuna.chilakala@intel.com 
#   [PATCH] e1000: Delay clean-up of last Tx buffer
#   
#   4 Delay clean-up of last Tx buffer to fix pre-mature writeback of Tx descriptors.
#   Signed-off-by: Mallikarjuna R Chilakala <mallikarjuna.chilakala@intel.com>
#   Signed-off-by: Ganesh Venkatesan <ganesh.venkatesan@intel.com>
#   Signed-off-by: John Ronciak <john.ronciak@intel.com>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/e1000/e1000_main.c
#   2005/02/02 02:10:27-05:00 mallikarjuna.chilakala@intel.com +30 -1
#   e1000: Delay clean-up of last Tx buffer
# 
# drivers/net/e1000/e1000.h
#   2005/02/02 02:10:26-05:00 mallikarjuna.chilakala@intel.com +1 -0
#   e1000: Delay clean-up of last Tx buffer
# 
# ChangeSet
#   2005/02/20 21:10:20-05:00 mallikarjuna.chilakala@intel.com 
#   [PATCH] e1000: Avoid race between e1000_watchdog
#   
#   3 Avoid race condition between e1000_watchdog and e1000_clean_tx_irq
#   Signed-off-by: Mallikarjuna R Chilakala <mallikarjuna.chilakala@intel.com>
#   Signed-off-by: Ganesh Venkatesan <ganesh.venkatesan@intel.com>
#   Signed-off-by: John Ronciak <john.ronciak@intel.com>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/e1000/e1000_main.c
#   2005/02/02 02:10:27-05:00 mallikarjuna.chilakala@intel.com +12 -7
#   e1000: Avoid race between e1000_watchdog
# 
# drivers/net/e1000/e1000.h
#   2005/02/02 02:10:26-05:00 mallikarjuna.chilakala@intel.com +1 -0
#   e1000: Avoid race between e1000_watchdog
# 
# ChangeSet
#   2005/02/20 21:10:06-05:00 mallikarjuna.chilakala@intel.com 
#   [PATCH] e1000: use netif_poll_{enable|disable}
#   
#   2 use netif_poll_{enable|disable} to synchronize between poll and i/f down/up
#   Signed-off-by: Mallikarjuna R Chilakala <mallikarjuna.chilakala@intel.com>
#   Signed-off-by: Ganesh Venkatesan <ganesh.venkatesan@intel.com>
#   Signed-off-by: John Ronciak <john.ronciak@intel.com>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/e1000/e1000_main.c
#   2005/02/02 02:10:27-05:00 mallikarjuna.chilakala@intel.com +7 -0
#   e1000: use netif_poll_{enable|disable}
# 
# ChangeSet
#   2005/02/20 21:09:54-05:00 mallikarjuna.chilakala@intel.com 
#   [PATCH] e1000: Robert Olsson's fix and refinement
#   
#   1 Robert Olsson's fix and refinement to the poll routine
#   Signed-off-by: Mallikarjuna R Chilakala <mallikarjuna.chilakala@intel.com>
#   Signed-off-by: Ganesh Venkatesan <ganesh.venkatesan@intel.com>
#   Signed-off-by: John Ronciak <john.ronciak@intel.com>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/e1000/e1000_main.c
#   2005/02/02 02:10:27-05:00 mallikarjuna.chilakala@intel.com +4 -7
#   e1000: Robert Olsson's fix and refinement
# 
# ChangeSet
#   2005/02/20 20:59:40-05:00 mallikarjuna.chilakala@intel.com 
#   [PATCH] ixgb: Driver version, white space, other stuff
#   
#   Driver version number, white space, comments, device id & other changes
#   Signed-off-by: Mallikarjuna R Chilakala <mallikarjuna.chilakala@intel.com>
#   Signed-off-by: Ganesh Venkatesan <ganesh.venkatesan@intel.com>
#   Signed-off-by: John Ronciak <john.ronciak@intel.com>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/ixgb/ixgb_param.c
#   2005/02/07 02:33:02-05:00 mallikarjuna.chilakala@intel.com +1 -1
#   ixgb: Driver version, white space,
# 
# drivers/net/ixgb/ixgb_osdep.h
#   2005/02/07 02:33:02-05:00 mallikarjuna.chilakala@intel.com +1 -1
#   ixgb: Driver version, white space,
# 
# drivers/net/ixgb/ixgb_main.c
#   2005/02/07 02:33:02-05:00 mallikarjuna.chilakala@intel.com +20 -15
#   ixgb: Driver version, white space,
# 
# drivers/net/ixgb/ixgb_ids.h
#   2005/02/07 02:33:02-05:00 mallikarjuna.chilakala@intel.com +1 -1
#   ixgb: Driver version, white space,
# 
# drivers/net/ixgb/ixgb_hw.h
#   2005/02/07 02:33:02-05:00 mallikarjuna.chilakala@intel.com +1 -1
#   ixgb: Driver version, white space,
# 
# drivers/net/ixgb/ixgb_hw.c
#   2005/02/07 02:33:02-05:00 mallikarjuna.chilakala@intel.com +1 -1
#   ixgb: Driver version, white space,
# 
# drivers/net/ixgb/ixgb_ethtool.c
#   2005/02/07 02:33:02-05:00 mallikarjuna.chilakala@intel.com +4 -1
#   ixgb: Driver version, white space,
# 
# drivers/net/ixgb/ixgb_ee.h
#   2005/02/07 02:33:01-05:00 mallikarjuna.chilakala@intel.com +1 -1
#   ixgb: Driver version, white space,
# 
# drivers/net/ixgb/ixgb_ee.c
#   2005/02/07 02:33:01-05:00 mallikarjuna.chilakala@intel.com +1 -1
#   ixgb: Driver version, white space,
# 
# drivers/net/ixgb/ixgb.h
#   2005/02/07 02:33:02-05:00 mallikarjuna.chilakala@intel.com +1 -1
#   ixgb: Driver version, white space,
# 
# ChangeSet
#   2005/02/20 20:59:28-05:00 mallikarjuna.chilakala@intel.com 
#   [PATCH] ixgb: Invalidate software cache, when EEPROM write occurs
#   
#   Added code to invalidate software cache, when a write is made to the EEPROM.
#   Signed-off-by: Mallikarjuna R Chilakala <mallikarjuna.chilakala@intel.com>
#   Signed-off-by: Ganesh Venkatesan <ganesh.venkatesan@intel.com>
#   Signed-off-by: John Ronciak <john.ronciak@intel.com>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/ixgb/ixgb_ee.h
#   2005/02/07 02:33:01-05:00 mallikarjuna.chilakala@intel.com +1 -0
#   ixgb: Invalidate software cache, when
# 
# drivers/net/ixgb/ixgb_ee.c
#   2005/02/07 02:33:01-05:00 mallikarjuna.chilakala@intel.com +10 -4
#   ixgb: Invalidate software cache, when
# 
# ChangeSet
#   2005/02/20 20:59:16-05:00 mallikarjuna.chilakala@intel.com 
#   [PATCH] ixgb: Robert Olsson's fix and refinement to poll
#   
#   obert Olsson's fix and refinement to the poll routine
#   Signed-off-by: Mallikarjuna R Chilakala <mallikarjuna.chilakala@intel.com>
#   Signed-off-by: Ganesh Venkatesan <ganesh.venkatesan@intel.com>
#   Signed-off-by: John Ronciak <john.ronciak@intel.com>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/ixgb/ixgb_main.c
#   2005/02/07 02:33:02-05:00 mallikarjuna.chilakala@intel.com +4 -8
#   ixgb: Robert Olsson's fix and refinement
# 
# ChangeSet
#   2005/02/20 20:59:04-05:00 mallikarjuna.chilakala@intel.com 
#   [PATCH] ixgb: Avoid race e1000_watchdog and ixgb_clean_tx_irq
#   
#   Avoid race between e1000_watchdog and ixgb_clean_tx_irq
#   Signed-off-by: Mallikarjuna R Chilakala <mallikarjuna.chilakala@intel.com>
#   Signed-off-by: Ganesh Venkatesan <ganesh.venkatesan@intel.com>
#   Signed-off-by: John Ronciak <john.ronciak@intel.com>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/ixgb/ixgb_main.c
#   2005/02/07 02:33:02-05:00 mallikarjuna.chilakala@intel.com +13 -7
#   ixgb: Avoid race e1000_watchdog and
# 
# drivers/net/ixgb/ixgb.h
#   2005/02/07 02:33:02-05:00 mallikarjuna.chilakala@intel.com +1 -0
#   ixgb: Avoid race e1000_watchdog and
# 
# ChangeSet
#   2005/02/20 20:58:53-05:00 mallikarjuna.chilakala@intel.com 
#   [PATCH] ixgb: use netif_poll_{enable|disable}
#   
#   1 use netif_poll_{enable|disable} to synchronize between poll and i/f down/up
#   Signed-off-by: Mallikarjuna R Chilakala <mallikarjuna.chilakala@intel.com>
#   Signed-off-by: Ganesh Venkatesan <ganesh.venkatesan@intel.com>
#   Signed-off-by: John Ronciak <john.ronciak@intel.com>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/ixgb/ixgb_main.c
#   2005/02/07 02:33:02-05:00 mallikarjuna.chilakala@intel.com +6 -0
#   ixgb: use netif_poll_{enable|disable}
# 
# ChangeSet
#   2005/02/20 20:52:00-05:00 bunk@stusta.de 
#   [PATCH] drivers/net/3c509.c: make 2 structs static
#   
#   This patch makes two needlessly global structs static.
#   
#   Signed-off-by: Adrian Bunk <bunk@stusta.de>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/3c509.c
#   2005/02/16 09:12:44-05:00 bunk@stusta.de +2 -2
#   drivers/net/3c509.c: make 2 structs static
# 
# ChangeSet
#   2005/02/20 20:51:47-05:00 bunk@stusta.de 
#   [PATCH] drivers/net/3c527.c: make a struct static
#   
#   This patch makes a needlessly global struct static.
#   
#   Signed-off-by: Adrian Bunk <bunk@stusta.de>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/3c527.c
#   2005/02/16 09:13:29-05:00 bunk@stusta.de +1 -1
#   drivers/net/3c527.c: make a struct static
# 
# ChangeSet
#   2005/02/20 20:51:34-05:00 bunk@stusta.de 
#   [PATCH] drivers/net/amd8111e.c: make 2 functions static
#   
#   This patch makes two needlessly global functions static.
#   
#   Signed-off-by: Adrian Bunk <bunk@stusta.de>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/amd8111e.c
#   2005/02/16 09:14:29-05:00 bunk@stusta.de +2 -2
#   drivers/net/amd8111e.c: make 2 functions static
# 
# ChangeSet
#   2005/02/20 20:48:56-05:00 bunk@stusta.de 
#   [PATCH] drivers/net/loopback.c: make a function static
#   
#   This patch makes a needlessly global function static.
#   
#   Signed-off-by: Adrian Bunk <bunk@stusta.de>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/loopback.c
#   2005/02/16 10:08:14-05:00 bunk@stusta.de +1 -1
#   drivers/net/loopback.c: make a function static
# 
# ChangeSet
#   2005/02/20 20:48:42-05:00 bunk@stusta.de 
#   [PATCH] drivers/net/ethertap.c: make 2 functions static
#   
#   This patch makes two needlessly global functions static.
#   
#   Signed-off-by: Adrian Bunk <bunk@stusta.de>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/ethertap.c
#   2005/02/16 09:40:17-05:00 bunk@stusta.de +2 -2
#   drivers/net/ethertap.c: make 2 functions static
# 
# ChangeSet
#   2005/02/20 20:48:28-05:00 bunk@stusta.de 
#   [PATCH] drivers/net/dgrs.c: make 3 functions static
#   
#   This patch makes three needlessly global functions static.
#   
#   Signed-off-by: Adrian Bunk <bunk@stusta.de>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/dgrs.c
#   2005/02/16 09:26:27-05:00 bunk@stusta.de +3 -3
#   drivers/net/dgrs.c: make 3 functions static
# 
# ChangeSet
#   2005/02/20 20:48:15-05:00 bunk@stusta.de 
#   [PATCH] drivers/net/depca.c: make 2 structs static
#   
#   This patch makes two needlessly global structs static.
#   
#   Signed-off-by: Adrian Bunk <bunk@stusta.de>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/depca.c
#   2005/02/16 09:25:08-05:00 bunk@stusta.de +2 -2
#   drivers/net/depca.c: make 2 structs static
# 
# ChangeSet
#   2005/02/20 20:48:02-05:00 bunk@stusta.de 
#   [PATCH] drivers/net/bonding/: make 3 functions static
#   
#   This patch makes three needlessly global functions static.
#   
#   Signed-off-by: Adrian Bunk <bunk@stusta.de>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/bonding/bond_alb.c
#   2005/02/16 09:24:21-05:00 bunk@stusta.de +2 -2
#   drivers/net/bonding/: make 3 functions static
# 
# drivers/net/bonding/bond_3ad.h
#   2005/02/16 09:23:29-05:00 bunk@stusta.de +0 -1
#   drivers/net/bonding/: make 3 functions static
# 
# drivers/net/bonding/bond_3ad.c
#   2005/02/16 09:23:45-05:00 bunk@stusta.de +1 -1
#   drivers/net/bonding/: make 3 functions static
# 
# ChangeSet
#   2005/02/20 20:41:20-05:00 bunk@stusta.de 
#   [PATCH] drivers/net/s2io.c: cleanups
#   
#   This patch contains the following cleanups:
#   - make needlessly global code static
#   - remove the unused blobal function get_xena_rev_id
#   
#   Signed-off-by: Adrian Bunk <bunk@stusta.de>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/s2io.h
#   2005/02/16 12:15:42-05:00 bunk@stusta.de +4 -4
#   drivers/net/s2io.c: cleanups
# 
# drivers/net/s2io.c
#   2005/02/16 13:05:11-05:00 bunk@stusta.de +31 -44
#   drivers/net/s2io.c: cleanups
# 
# ChangeSet
#   2005/02/20 20:41:06-05:00 bunk@stusta.de 
#   [PATCH] drivers/net/pppoe.c: make a struct static
#   
#   This patch makes a needlessly global struct static.
#   
#   Signed-off-by: Adrian Bunk <bunk@stusta.de>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/pppoe.c
#   2005/02/16 12:07:23-05:00 bunk@stusta.de +1 -1
#   drivers/net/pppoe.c: make a struct static
# 
# ChangeSet
#   2005/02/20 20:40:52-05:00 bunk@stusta.de 
#   [PATCH] drivers/net/ppp_deflate.c: make 2 structs static
#   
#   This patch makes two needlessly global structs static.
#   
#   Signed-off-by: Adrian Bunk <bunk@stusta.de>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/ppp_deflate.c
#   2005/02/16 12:06:45-05:00 bunk@stusta.de +2 -2
#   drivers/net/ppp_deflate.c: make 2 structs static
# 
# ChangeSet
#   2005/02/20 20:34:26-05:00 bunk@stusta.de 
#   [PATCH] drivers/net/via-velocity.c: make a function static
#   
#   This patch makes a needlessly global function static.
#   
#   Signed-off-by: Adrian Bunk <bunk@stusta.de>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/via-velocity.c
#   2005/02/16 12:57:49-05:00 bunk@stusta.de +1 -1
#   drivers/net/via-velocity.c: make a function static
# 
# ChangeSet
#   2005/02/20 20:34:11-05:00 bunk@stusta.de 
#   [PATCH] drivers/net/tun.c: make 2 functions static
#   
#   This patch makes two needlessly global functions static.
#   
#   Signed-off-by: Adrian Bunk <bunk@stusta.de>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/tun.c
#   2005/02/16 12:55:57-05:00 bunk@stusta.de +2 -2
#   drivers/net/tun.c: make 2 functions static
# 
# ChangeSet
#   2005/02/20 20:33:57-05:00 bunk@stusta.de 
#   [PATCH] drivers/net/tulip/interrupt.c: make a variable static
#   
#   This patch makes a needlessly global variable static.
#   
#   Signed-off-by: Adrian Bunk <bunk@stusta.de>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/tulip/interrupt.c
#   2005/02/16 12:55:02-05:00 bunk@stusta.de +1 -1
#   drivers/net/tulip/interrupt.c: make a variable static
# 
# ChangeSet
#   2005/02/20 20:33:44-05:00 bunk@stusta.de 
#   [PATCH] drivers/net/shaper.c: make a variable static
#   
#   On Fri, Feb 18, 2005 at 07:18:19PM -0500, Jeff Garzik wrote:
#   > Adrian Bunk wrote:
#   > >This patch contains the following cleanups:
#   > >- remove an unused #define SHAPER_BANNER
#   > >- remove the sh_debug flag
#   > >
#   > >Signed-off-by: Adrian Bunk <bunk@stusta.de>
#   >
#   > you are removing presumably-useful debug code; NAK.
#   
#   OK, less invasive patch below.
#   
#   
#   <--  snip  -->
#   
#   
#   This patch makes a needlessly global variable static.
#   
#   Signed-off-by: Adrian Bunk <bunk@stusta.de>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/shaper.c
#   2005/02/19 03:27:53-05:00 bunk@stusta.de +1 -1
#   drivers/net/shaper.c: make a variable static
# 
# ChangeSet
#   2005/02/20 20:33:30-05:00 bunk@stusta.de 
#   [PATCH] drivers/net/slhc.c: remove 2 functions
#   
#   This patch removes two unused global functions.
#   
#   Signed-off-by: Adrian Bunk <bunk@stusta.de>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# include/net/slhc_vj.h
#   2005/02/16 12:43:49-05:00 bunk@stusta.de +0 -3
#   drivers/net/slhc.c: remove 2 functions
# 
# drivers/net/slhc.c
#   2005/02/16 12:43:40-05:00 bunk@stusta.de +0 -27
#   drivers/net/slhc.c: remove 2 functions
# 
# ChangeSet
#   2005/02/18 16:45:25-06:00 shaggy@austin.ibm.com 
#   JFS: change project url to http://jfs.sourceforge.net/
#   
#   Signed-off-by: Dave Kleikamp <shaggy@austin.ibm.com>
# 
# MAINTAINERS
#   2005/02/18 16:45:14-06:00 shaggy@austin.ibm.com +2 -2
#   move to sourceforge.net
# 
# Documentation/Changes
#   2005/02/18 16:45:14-06:00 shaggy@austin.ibm.com +1 -1
#   move to sourceforge.net
# 
# ChangeSet
#   2005/02/18 16:41:17-06:00 shaggy@austin.ibm.com 
#   JFS: allow iocharset=none mount option
#   
#   iocharset=none is an explicit option to specify the default
#   character translation be used (no translation).  This allows
#   remounting a partition which was mounted with a different setting,
#   and allows the same mount options to be used between 2.6 and 2.4
#   kernels, where there is a different default.
#   
#   Signed-off-by: Dave Kleikamp <shaggy@austin.ibm.com>
# 
# fs/jfs/super.c
#   2005/02/18 16:41:05-06:00 shaggy@austin.ibm.com +13 -8
#   Allow iocharset=none mount option
# 
# Documentation/filesystems/jfs.txt
#   2005/02/18 16:41:05-06:00 shaggy@austin.ibm.com +3 -9
#   Allow iocharset=none mount option
# 
# ChangeSet
#   2005/02/17 15:07:21-08:00 c-d.hailfinger.devel.2005@gmx.net 
#   [PATCH] PCI: pci.ids update
#   
#   this patch partially updates drivers/pci/pci.ids to the current
#   version from http://pciids.sf.net. I have gone over the diff to
#   ensure nothing gets deleted/changed erroneously. There are some
#   differences where I couldn't verify whether the in-kernel or
#   the upstream version are correct, so I left them alone.
#   
#   Patch checked for build warnings and I'm running a kernel with
#   it on my machine right now.
#   
#   Signed-off-by: Carl-Daniel Hailfinger <c-d.hailfinger.devel.2005@gmx.net>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/pci/pci.ids
#   2005/02/16 19:05:44-08:00 c-d.hailfinger.devel.2005@gmx.net +1011 -126
#   PCI: pci.ids update
# 
# ChangeSet
#   2005/02/17 15:07:01-08:00 roland@topspin.com 
#   [PATCH] PCI: clean up the msi api
#   
#   Remove the call to request_mem_region() in msix_capability_init() to
#   grab the MSI-X vector table.  Drivers should be using
#   pci_request_regions() so that they own all of the PCI BARs, and the
#   MSI-X core should trust it's being called by a correct driver.
#   
#   Signed-off-by: Roland Dreier <roland@topspin.com>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/pci/msi.c
#   2005/02/16 16:00:00-08:00 roland@topspin.com +2 -11
#   PCI: clean up the msi api
# 
# ChangeSet
#   2005/02/17 15:06:37-08:00 c-d.hailfinger.devel.2005@gmx.net 
#   [PATCH] pci/quirks.c: unhide SMBus device on Samsung P35 laptop
#   
#   this patch is needed to make the SMBus device on my Samsung P35
#   laptop visible. By default, it doesn't appear as a pci device.
#   
#   Patch tested, works perfectly for me. Please apply.
#   
#   Signed-off-by: Carl-Daniel Hailfinger <c-d.hailfinger.devel.2005@gmx.net>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# include/linux/pci_ids.h
#   2005/02/16 14:48:09-08:00 c-d.hailfinger.devel.2005@gmx.net +2 -0
#   pci/quirks.c: unhide SMBus device on Samsung P35 laptop
# 
# drivers/pci/quirks.c
#   2005/02/16 14:50:49-08:00 c-d.hailfinger.devel.2005@gmx.net +6 -0
#   pci/quirks.c: unhide SMBus device on Samsung P35 laptop
# 
# ChangeSet
#   2005/02/17 15:06:16-08:00 ak@muc.de 
#   [PATCH] PCI: allow x86_64 to do pci express
#   
#   On Mon, Feb 14, 2005 at 10:47:01AM +0100, Piotr Kaczuba wrote:
#   > On Mon, Feb 14, 2005 at 10:18:43AM +0100, Andi Kleen wrote:
#   > > Piotr Kaczuba <pepe@attika.ath.cx> writes:
#   > > > Is there a reason why "PCI access mode" config option isn't available for
#   > > > x86_64? Due to this, PCIE config options aren't available either.
#   > >
#   > > There is no 64bit PCI BIOS, so access is always direct.
#   > >
#   > > I assume you mean mmconfig access with "PCIE config options", that is
#   > > a separate config option and available.
#   >
#   > I mean the PCIEPORTBUS option which depends on PCI_GOMMCONFIG or
#   > PCI_GOANY. I assume that due to PCI_MMCONFIG / PCI_GOMMCONFIG mismatch
#   > it's not available on x86_64.
#   
#   Ok, that's a bug in PCIEPORTBUS.  Best is probably to
#   completely remove the dependency, it doesn't make much sense
#   (the code has to handle the case of mmconfig not being available at
#   runtime anyways)
#   
#   Remove bogus dependency in PCI Express root driver.
#   
#   Signed-off-by: Andi Kleen <ak@suse.de>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/pci/pcie/Kconfig
#   2005/02/14 03:59:46-08:00 ak@muc.de +0 -1
#   PCI: allow x86_64 to do pci express
# 
# ChangeSet
#   2005/02/17 15:05:53-08:00 khali@linux-fr.org 
#   [PATCH] PCI: Add PCI quirk for SMBus on the Toshiba Satellite A40
#   
#   The Toshiba Satellite A40 laptop hides its SMBus device, much like a
#   number of Asus boards reputedly do. This prevents access to the LM90
#   hardware monitoring chip. This simple patch extends the PCI quirk used
#   for the Asus and HP systems to this Toshiba laptop.
#   
#   Signed-off-by: Frans Pop <aragorn@tiscali.nl>
#   Signed-off-by: Jean Delvare <khali@linux-fr.org>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/pci/quirks.c
#   2005/02/13 03:35:28-08:00 khali@linux-fr.org +6 -0
#   PCI: Add PCI quirk for SMBus on the Toshiba Satellite A40
# 
# ChangeSet
#   2005/02/17 15:05:32-08:00 dlsy@snoqualmie.dp.intel.com 
#   [PATCH] PCI Hotplug: Fix OSHP calls in shpchp and pciehp drivers
#   
#   Here is a patch to fix a problem in OSHP calls in shpchp and pciehp
#   drivers that was detected in 2.6.11-rc3. In this kernel, calls to
#   acpi_evaluate_object() to evaluate OSHP returned AE_BUFFER_OVERFLOW
#   with the existing code.  Earlier kernels didn't return this error
#   code.  The correct fix should be making return_buffer pointer NULL
#   for no value is returned from this method.
#   
#   Signed-off-by: Dely Sy <dely.l.sy@intel.com>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/pci/hotplug/shpchprm_acpi.c
#   2005/02/08 14:04:19-08:00 dlsy@snoqualmie.dp.intel.com +1 -2
#   PCI Hotplug: Fix OSHP calls in shpchp and pciehp drivers
# 
# drivers/pci/hotplug/pciehprm_acpi.c
#   2005/02/08 14:03:48-08:00 dlsy@snoqualmie.dp.intel.com +1 -2
#   PCI Hotplug: Fix OSHP calls in shpchp and pciehp drivers
# 
# ChangeSet
#   2005/02/17 15:05:08-08:00 c.lucas@ifrance.com 
#   [PATCH] drivers/pci/*: convert to pci_register_driver
#   
#   convert from pci_module_init to pci_register_driver
#   (from:http://kerneljanitors.org/TODO).
#   
#   Signed-off-by: Christophe Lucas <c.lucas@ifrance.com>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/pci/pcie/portdrv_pci.c
#   2005/02/07 00:41:08-08:00 c.lucas@ifrance.com +1 -1
#   drivers/pci/*: convert to pci_register_driver
# 
# ChangeSet
#   2005/02/17 14:28:01-07:00 dale@farnsworth.org 
#   [netdrvr mv643xx] Add ethtool support to the mv643xx ethernet driver.
#   Initially, we add statistics and link status reporting.
#   
#   Signed-off-by: Dale Farnsworth <dale@farnsworth.org>
# 
# include/linux/mv643xx.h
#   2005/02/17 14:27:41-07:00 dale@farnsworth.org +14 -0
#   Add ethtool support to the mv643xx ethernet driver.
#   Initially, we add statistics and link status reporting.
#   
#   Signed-off-by: Dale Farnsworth <dale@farnsworth.org>
# 
# drivers/net/mv643xx_eth.h
#   2005/02/17 14:27:41-07:00 dale@farnsworth.org +34 -0
#   Add ethtool support to the mv643xx ethernet driver.
#   Initially, we add statistics and link status reporting.
#   
#   Signed-off-by: Dale Farnsworth <dale@farnsworth.org>
# 
# drivers/net/mv643xx_eth.c
#   2005/02/17 14:27:41-07:00 dale@farnsworth.org +275 -4
#   Add ethtool support to the mv643xx ethernet driver.
#   Initially, we add statistics and link status reporting.
#   
#   Signed-off-by: Dale Farnsworth <dale@farnsworth.org>
# 
# ChangeSet
#   2005/02/17 14:26:54-07:00 dale@farnsworth.org 
#   [netdrvr mv643xx] Enable the mv643xx ethernet support on platforms using the MV64360 chip.
#   
#   Signed-off-by: Dale Farnsworth <dale@farnsworth.org>
# 
# drivers/net/Kconfig
#   2005/02/17 14:26:45-07:00 dale@farnsworth.org +3 -2
#   Enable the mv643xx ethernet support on platforms using the MV64360 chip.
#   
#   Signed-off-by: Dale Farnsworth <dale@farnsworth.org>
# 
# ChangeSet
#   2005/02/17 14:26:04-07:00 dale@farnsworth.org 
#   [netdrvr mv643xx] Disable tcp/udp checksum offload to hardware.  It generally works,
#   but the hardware appears to generate the wrong checksum if the
#   hw checksum generation wasn't used in the previous packet sent.
#   
#   I'm increasingly confident this is a hardware error.
#   We'll disable hw tcp/udp checksum generation until we have a fix
#   or workaround.
#   
#   Signed-off-by: Dale Farnsworth <dale@farnsworth.org>
# 
# drivers/net/mv643xx_eth.h
#   2005/02/17 14:25:47-07:00 dale@farnsworth.org +4 -2
#   Disable tcp/udp checksum offload to hardware.  It generally works,
#   but the hardware appears to generate the wrong checksum if the
#   hw checksum generation wasn't used in the previous packet sent.
#   
#   I'm increasingly confident this is a hardware error.
#   We'll disable hw tcp/udp checksum generation until we have a fix
#   or workaround.
#   
#   Signed-off-by: Dale Farnsworth <dale@farnsworth.org>
# 
# ChangeSet
#   2005/02/17 14:25:19-07:00 dale@farnsworth.org 
#   [netdrvr mv643xx] We already set ETH_TX_ENABLE_INTERRUPT whenever we set ETH_TX_LAST_DESC.
#   
#   Signed-off-by: Dale Farnsworth <dale@farnsworth.org>
# 
# drivers/net/mv643xx_eth.c
#   2005/02/17 14:25:00-07:00 dale@farnsworth.org +0 -3
#   We already set ETH_TX_ENABLE_INTERRUPT whenever we set ETH_TX_LAST_DESC.
#   
#   Signed-off-by: Dale Farnsworth <dale@farnsworth.org>
# 
# ChangeSet
#   2005/02/17 14:24:24-07:00 dale@farnsworth.org 
#   [netdrvr mv643xx] Update tx_bytes statistic when using hw tcp/udp checksum generation.
#   
#   Signed-off-by: Dale Farnsworth <dale@farnsworth.org>
# 
# drivers/net/mv643xx_eth.c
#   2005/02/17 14:24:07-07:00 dale@farnsworth.org +4 -1
#   Update tx_bytes statistic when using hw tcp/udp checksum generation.
#   
#   Signed-off-by: Dale Farnsworth <dale@farnsworth.org>
# 
# ChangeSet
#   2005/02/17 14:23:18-07:00 dale@farnsworth.org 
#   [netdrvr mv643xx] Call netif_carrier_off when closing the driver.
#   
#   Signed-off-by: Dale Farnsworth <dale@farnsworth.org>
# 
# drivers/net/mv643xx_eth.c
#   2005/02/17 14:23:02-07:00 dale@farnsworth.org +1 -0
#   Call netif_carrier_off when closing the driver.
#   
#   Signed-off-by: Dale Farnsworth <dale@farnsworth.org>
# 
# ChangeSet
#   2005/02/17 14:22:23-07:00 dale@farnsworth.org 
#   [netdrvr mv643xx] Trivial.  Remove repeated comment.
#   
#   Signed-off-by: Dale Farnsworth <dale@farnsworth.org>
# 
# drivers/net/mv643xx_eth.c
#   2005/02/17 14:22:06-07:00 dale@farnsworth.org +0 -1
#   Trivial.  Remove repeated comment.
#   
#   Signed-off-by: Dale Farnsworth <dale@farnsworth.org>
# 
# ChangeSet
#   2005/02/17 14:21:31-07:00 dale@farnsworth.org 
#   [netdrvr mv643xx] Clear transmit l4i_chk even when the hardware ignores it.
#   Not absolutely necessary, but makes debugging easier.
#   
#   Signed-off-by: Dale Farnsworth <dale@farnsworth.org>
# 
# drivers/net/mv643xx_eth.c
#   2005/02/17 14:21:17-07:00 dale@farnsworth.org +6 -2
#   Clear transmit l4i_chk even when the hardware ignores it.
#   Not absolutely necessary, but makes debugging easier.
#   
#   Signed-off-by: Dale Farnsworth <dale@farnsworth.org>
# 
# ChangeSet
#   2005/02/17 14:19:54-07:00 dale@farnsworth.org 
#   [netdrvr mv643xx] Increment tx_ring_skbs before calling eth_port_send, since
#   otherwise the irq handler may check and decrement it before
#   we increment it.
#   
#   Signed-off-by: Dale Farnsworth <dale@farnsworth.org>
# 
# drivers/net/mv643xx_eth.c
#   2005/02/17 14:19:34-07:00 dale@farnsworth.org +2 -2
#   Increment tx_ring_skbs before calling eth_port_send, since
#   otherwise the irq handler may check and decrement it before
#   we increment it.
#   
#   Signed-off-by: Dale Farnsworth <dale@farnsworth.org>
# 
# ChangeSet
#   2005/02/17 14:18:46-07:00 dale@farnsworth.org 
#   [netdrvr mv643xx] Fix handling of unaligned tiny fragments not handled by hardware
#   Check all fragments instead of just the last.
#   
#   Signed-off-by: Dale Farnsworth <dale@farnsworth.org>
# 
# drivers/net/mv643xx_eth.c
#   2005/02/17 14:18:37-07:00 dale@farnsworth.org +18 -6
#   Fix handling of unaligned tiny fragments not handled by hardware
#   Check all fragments instead of just the last.
#   
#   Signed-off-by: Dale Farnsworth <dale@farnsworth.org>
# 
# ChangeSet
#   2005/02/17 14:17:16-07:00 dale@farnsworth.org 
#   [netdrvr mv643xx] Fix a few places I missed in the previous rename patch.
#   Rename: mv64x60 => mv643xx
#   
#   Signed-off-by: Dale Farnsworth <dale@farnsworth.org>
# 
# drivers/net/mv643xx_eth.c
#   2005/02/17 14:17:07-07:00 dale@farnsworth.org +7 -7
#   Fix a few places I missed in the previous rename patch.
#   Rename: mv64x60 => mv643xx
#   
#   Signed-off-by: Dale Farnsworth <dale@farnsworth.org>
# 
# ChangeSet
#   2005/02/17 10:23:56-07:00 dale@farnsworth.org 
#   Merge bk://dfarnsworth@bkbits.net/linux-2.5-mv643xx-enet
#   into farnsworth.org:/x/bk/linux-2.5-mv643xx-enet
# 
# include/linux/mv643xx.h
#   2005/02/17 10:23:50-07:00 dale@farnsworth.org +0 -0
#   Auto merged
# 
# ChangeSet
#   2005/02/17 10:15:17-07:00 dale@farnsworth.org 
#   Merge farnsworth.org:/x/bk/linux-2.5
#   into farnsworth.org:/x/bk/linux-2.5-mv643xx-enet
# 
# include/linux/mv643xx.h
#   2005/02/17 10:15:11-07:00 dale@farnsworth.org +0 -0
#   Auto merged
# 
# ChangeSet
#   2005/02/17 09:11:28-08:00 dfarnsworth.adm@bkbits.net 
#   Merge bk://linux.bkbits.net/linux-2.5
#   into bkbits.net:/repos/d/dfarnsworth/linux-2.5-mv643xx-enet
# 
# include/linux/mv643xx.h
#   2005/02/17 09:11:21-08:00 dfarnsworth.adm@bkbits.net +0 -0
#   Auto merged
# 
# ChangeSet
#   2005/02/16 09:35:42+01:00 dtor_core@ameritech.net 
#   Input: fix timer handling race in sidewinder joystick driver by
#          switching to gameport's polling facilities.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/joystick/sidewinder.c
#   2005/02/16 09:35:30+01:00 dtor_core@ameritech.net +7 -13
#   Input: fix timer handling race in sidewinder joystick driver by
#          switching to gameport's polling facilities.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# ChangeSet
#   2005/02/16 08:51:47+01:00 vojtech@suse.cz 
#   input: Fix Microtouch USB touchscreen Y axis direction.
#          [0,0] should be upper left corner.
#   
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/usb/input/mtouchusb.c
#   2005/02/16 08:51:35+01:00 vojtech@suse.cz +1 -1
#   input: Fix Microtouch USB touchscreen Y axis direction.
#          [0,0] should be upper left corner.
#   
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# ChangeSet
#   2005/02/15 15:16:58-08:00 herbert@gondor.apana.org.au 
#   [XFRM]: stale_bundle()'s test was reversed
#   
#   Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/xfrm/xfrm_policy.c
#   2005/02/15 15:16:04-08:00 herbert@gondor.apana.org.au +1 -1
#   [XFRM]: stale_bundle()'s test was reversed
# 
# ChangeSet
#   2005/02/15 14:10:35-08:00 herbert@gondor.apana.org.au 
#   [IPV6]: Make loopback idev stick around.
#   
#   Mirror the ipv4 change.
#   
#   Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/ipv6/addrconf.c
#   2005/02/15 14:10:14-08:00 herbert@gondor.apana.org.au +8 -2
#   [IPV6]: Make loopback idev stick around.
#   
#   Mirror the ipv4 change.
#   
#   Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# ChangeSet
#   2005/02/15 14:09:38-08:00 herbert@gondor.apana.org.au 
#   [IPV4]: Make loopback idev stick around.
#   
#   As it is when loopback_dev loses all of its IPv4 addresses its
#   corresponding idev will be destroyed.  Unfortunately as of last
#   August route.c relies on the loopback idev to kill references
#   to other idev objects.
#   
#   The end result is that when you do ip a f dev lo, unregistering
#   other devices will hang until those dst objects referring to
#   their idev objects die of natural causes.  Of course this may
#   never happen if the processes holding those references get
#   dead-locked by invoking an operation that takes the RTNL.
#   
#   A simple solution is to make sure that loopback's idev sticks
#   around all the time.
#   
#   Incidentally this also fixes the setting of some flags on the
#   loopback idev object as currently the code that does it won't
#   be called if you add the addresses to lo after bring it up.
#   
#   Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/ipv4/devinet.c
#   2005/02/15 14:09:16-08:00 herbert@gondor.apana.org.au +13 -4
#   [IPV4]: Make loopback idev stick around.
#   
#   As it is when loopback_dev loses all of its IPv4 addresses its
#   corresponding idev will be destroyed.  Unfortunately as of last
#   August route.c relies on the loopback idev to kill references
#   to other idev objects.
#   
#   The end result is that when you do ip a f dev lo, unregistering
#   other devices will hang until those dst objects referring to
#   their idev objects die of natural causes.  Of course this may
#   never happen if the processes holding those references get
#   dead-locked by invoking an operation that takes the RTNL.
#   
#   A simple solution is to make sure that loopback's idev sticks
#   around all the time.
#   
#   Incidentally this also fixes the setting of some flags on the
#   loopback idev object as currently the code that does it won't
#   be called if you add the addresses to lo after bring it up.
#   
#   Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# ChangeSet
#   2005/02/15 13:58:56-08:00 akpm@osdl.org 
#   [IPVS]: Fix deadlock in update_defense_level()
#   
#   This function invokes si_meminfo() from timer context,
#   which doesn't work due to bdev_lock not being an IRQ
#   safe lock.
#   
#   So move it to keventd context.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/ipv4/ipvs/ip_vs_ctl.c
#   2005/02/15 13:58:35-08:00 akpm@osdl.org +8 -11
#   [IPVS]: Fix deadlock in update_defense_level()
#   
#   This function invokes si_meminfo() from timer context,
#   which doesn't work due to bdev_lock not being an IRQ
#   safe lock.
#   
#   So move it to keventd context.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# ChangeSet
#   2005/02/15 13:57:16-08:00 akpm@osdl.org 
#   [WORKQUEUE]: Add cancel_rearming_delayed_work()
#   
#   From: Arjan van de Ven <arjan@infradead.org>
#   
#   cancel_rearming_delayed_workqueue() is only used inside workqueue.c; make
#   this function static (the more useful wrapper around it later in that
#   function remains non-static and exported)
#   
#   Signed-off-by: Arjan van de Ven <arjan@infradead.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# kernel/workqueue.c
#   2005/02/15 13:56:55-08:00 akpm@osdl.org +24 -0
#   [WORKQUEUE]: Add cancel_rearming_delayed_work()
#   
#   From: Arjan van de Ven <arjan@infradead.org>
#   
#   cancel_rearming_delayed_workqueue() is only used inside workqueue.c; make
#   this function static (the more useful wrapper around it later in that
#   function remains non-static and exported)
#   
#   Signed-off-by: Arjan van de Ven <arjan@infradead.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# include/linux/workqueue.h
#   2005/02/15 13:56:55-08:00 akpm@osdl.org +1 -0
#   [WORKQUEUE]: Add cancel_rearming_delayed_work()
#   
#   From: Arjan van de Ven <arjan@infradead.org>
#   
#   cancel_rearming_delayed_workqueue() is only used inside workqueue.c; make
#   this function static (the more useful wrapper around it later in that
#   function remains non-static and exported)
#   
#   Signed-off-by: Arjan van de Ven <arjan@infradead.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# ChangeSet
#   2005/02/15 15:47:08-06:00 shaggy@austin.ibm.com 
#   JFS: Fix array overflow
#   
#   On a system with more than 64 processors, commit_threads was too
#   big and caused an array overflow.  Always limit it to MAX_COMMIT_THREADS.
#   
#   Also, avoid waking up more than one commit thread at a time.
#   
#   Signed-off-by: Dave Kleikamp <shaggy@austin.ibm.com>
# 
# fs/jfs/super.c
#   2005/02/15 15:46:55-06:00 shaggy@austin.ibm.com +1 -1
#   Prevent array overflow by limiting commit_threads to MAX_COMMIT_THREADS
# 
# fs/jfs/jfs_txnmgr.c
#   2005/02/15 15:46:55-06:00 shaggy@austin.ibm.com +7 -2
#   Only wake up one commit thread at a time
# 
# ChangeSet
#   2005/02/15 13:46:51-08:00 herbert@gondor.apana.org.au 
#   [IPSEC]: Merge xfrm{4,6}_bundle_ok/stale_bundle
#   
#   This patch merges __xfrm4_bundle_ok/__xfrm6_bundle_ok/stale_bundle
#   so that when I add MTU verification code I don't have to put it in
#   three places.
#   
#   It also moves the tests on dst->dev and dst->obsolete outside the
#   loop since the former is identical throughout the bundle and the
#   latter can only be positive on the final element which also happens
#   to be dst->path.
#   
#   Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/xfrm/xfrm_policy.c
#   2005/02/15 13:46:16-08:00 herbert@gondor.apana.org.au +26 -12
#   [IPSEC]: Merge xfrm{4,6}_bundle_ok/stale_bundle
# 
# net/ipv6/xfrm6_policy.c
#   2005/02/15 13:46:16-08:00 herbert@gondor.apana.org.au +1 -21
#   [IPSEC]: Merge xfrm{4,6}_bundle_ok/stale_bundle
# 
# net/ipv4/xfrm4_policy.c
#   2005/02/15 13:46:16-08:00 herbert@gondor.apana.org.au +1 -21
#   [IPSEC]: Merge xfrm{4,6}_bundle_ok/stale_bundle
# 
# include/net/xfrm.h
#   2005/02/15 13:46:16-08:00 herbert@gondor.apana.org.au +1 -0
#   [IPSEC]: Merge xfrm{4,6}_bundle_ok/stale_bundle
# 
# ChangeSet
#   2005/02/15 13:36:18-08:00 davem@nuts.davemloft.net 
#   [TIMER]: Export avenrun for packet scheduler meta ematch.
#   
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# kernel/timer.c
#   2005/02/15 13:35:45-08:00 davem@nuts.davemloft.net +2 -0
#   [TIMER]: Export avenrun for packet scheduler meta ematch.
# 
# ChangeSet
#   2005/02/15 13:04:52-08:00 davem@nuts.davemloft.net 
#   [ATM]: fore200e needs to be converted over to sk_atm().
#   
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# drivers/atm/fore200e.c
#   2005/02/15 13:04:20-08:00 davem@nuts.davemloft.net +6 -6
#   [ATM]: fore200e needs to be converted over to sk_atm().
# 
# ChangeSet
#   2005/02/15 12:21:22-08:00 davem@nuts.davemloft.net 
#   [PKT_SCHED]: Basic classifier
#   
#   The basic classifier is the most simple classifier one can think of,
#   it doesn't do anything on its own but to support extended matches and
#   actions. A basic classifier returns true if no ematches or actions
#   are configured and thus can also be used as a catch-all classifier.
#   
#   Signed-off-by: Thomas Graf <tgraf@suug.ch>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/sched/Makefile
#   2005/02/15 12:20:47-08:00 davem@nuts.davemloft.net +1 -0
#   [PKT_SCHED]: Basic classifier
# 
# net/sched/Kconfig
#   2005/02/15 12:20:47-08:00 davem@nuts.davemloft.net +10 -0
#   [PKT_SCHED]: Basic classifier
# 
# include/linux/pkt_cls.h
#   2005/02/15 12:20:47-08:00 davem@nuts.davemloft.net +14 -0
#   [PKT_SCHED]: Basic classifier
# 
# net/sched/cls_basic.c
#   2005/02/15 12:20:45-08:00 davem@nuts.davemloft.net +303 -0
#   [PKT_SCHED]: Basic classifier
# 
# net/sched/cls_basic.c
#   2005/02/15 12:20:45-08:00 davem@nuts.davemloft.net +0 -0
#   BitKeeper file /disk1/BK/net-2.6.12/net/sched/cls_basic.c
# 
# ChangeSet
#   2005/02/15 12:20:03-08:00 davem@nuts.davemloft.net 
#   [PKT_SCHED]: Metadata ematch (meta)
#   
#   The meta ematch allows comparing various metadata values against
#   static values from usersapce or other metadata values. It currently
#   supports various numeric meta values such as netfilter mark, packet
#   length, security level, interface indices, tc classid, load average,
#   a random value but also variable length values such as interface
#   names. Adding support for additional meta values is as easy as
#   writing a data collector (usually 1-5 lines of code) and assign it
#   to a id and type by putting it into the meta operations table.
#   
#   Signed-off-by: Thomas Graf <tgraf@suug.ch>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/sched/Makefile
#   2005/02/15 12:19:29-08:00 davem@nuts.davemloft.net +1 -0
#   [PKT_SCHED]: Metadata ematch (meta)
# 
# net/sched/Kconfig
#   2005/02/15 12:19:29-08:00 davem@nuts.davemloft.net +11 -0
#   [PKT_SCHED]: Metadata ematch (meta)
# 
# include/linux/pkt_cls.h
#   2005/02/15 12:19:29-08:00 davem@nuts.davemloft.net +1 -0
#   [PKT_SCHED]: Metadata ematch (meta)
# 
# net/sched/em_meta.c
#   2005/02/15 12:19:25-08:00 davem@nuts.davemloft.net +661 -0
#   [PKT_SCHED]: Metadata ematch (meta)
# 
# net/sched/em_meta.c
#   2005/02/15 12:19:25-08:00 davem@nuts.davemloft.net +0 -0
#   BitKeeper file /disk1/BK/net-2.6.12/net/sched/em_meta.c
# 
# include/linux/tc_ematch/tc_em_meta.h
#   2005/02/15 12:19:24-08:00 davem@nuts.davemloft.net +69 -0
#   [PKT_SCHED]: Metadata ematch (meta)
# 
# include/linux/tc_ematch/tc_em_meta.h
#   2005/02/15 12:19:24-08:00 davem@nuts.davemloft.net +0 -0
#   BitKeeper file /disk1/BK/net-2.6.12/include/linux/tc_ematch/tc_em_meta.h
# 
# ChangeSet
#   2005/02/15 12:18:11-08:00 davem@nuts.davemloft.net 
#   [PKT_SCHED]: u32 ematch
#   
#   The u32 ematch behaves exactly the same as a u32 match and will replace
#   it in the long term. It allows the underlying classifiers to give hints
#   about the position of the next protocol header (i.e. nexthdr+).
#   
#   Signed-off-by: Thomas Graf <tgraf@suug.ch>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/sched/Makefile
#   2005/02/15 12:17:28-08:00 davem@nuts.davemloft.net +1 -0
#   [PKT_SCHED]: u32 ematch
# 
# net/sched/Kconfig
#   2005/02/15 12:17:28-08:00 davem@nuts.davemloft.net +10 -0
#   [PKT_SCHED]: u32 ematch
# 
# include/net/pkt_cls.h
#   2005/02/15 12:17:28-08:00 davem@nuts.davemloft.net +2 -0
#   [PKT_SCHED]: u32 ematch
# 
# include/linux/pkt_cls.h
#   2005/02/15 12:17:28-08:00 davem@nuts.davemloft.net +1 -0
#   [PKT_SCHED]: u32 ematch
# 
# net/sched/em_u32.c
#   2005/02/15 12:17:19-08:00 davem@nuts.davemloft.net +63 -0
#   [PKT_SCHED]: u32 ematch
# 
# net/sched/em_u32.c
#   2005/02/15 12:17:19-08:00 davem@nuts.davemloft.net +0 -0
#   BitKeeper file /disk1/BK/net-2.6.12/net/sched/em_u32.c
# 
# ChangeSet
#   2005/02/15 12:16:10-08:00 davem@nuts.davemloft.net 
#   [PKT_SCHED]: Multi byte comparison ematch (nbyte)
#   
#   The nbyte ematch allows comparing any number of bytes at an arbitary
#   offset based on one of the skb layers. Its main usage is intended
#   for IPv6 addresses but may be used for any kind of pattern.
#   
#   Signed-off-by: Thomas Graf <tgraf@suug.ch>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/sched/em_nbyte.c
#   2005/02/15 12:15:35-08:00 davem@nuts.davemloft.net +82 -0
#   [PKT_SCHED]: Multi byte comparison ematch (nbyte)
# 
# net/sched/Makefile
#   2005/02/15 12:15:36-08:00 davem@nuts.davemloft.net +1 -0
#   [PKT_SCHED]: Multi byte comparison ematch (nbyte)
# 
# net/sched/Kconfig
#   2005/02/15 12:15:36-08:00 davem@nuts.davemloft.net +10 -0
#   [PKT_SCHED]: Multi byte comparison ematch (nbyte)
# 
# include/linux/pkt_cls.h
#   2005/02/15 12:15:36-08:00 davem@nuts.davemloft.net +1 -0
#   [PKT_SCHED]: Multi byte comparison ematch (nbyte)
# 
# net/sched/em_nbyte.c
#   2005/02/15 12:15:35-08:00 davem@nuts.davemloft.net +0 -0
#   BitKeeper file /disk1/BK/net-2.6.12/net/sched/em_nbyte.c
# 
# include/linux/tc_ematch/tc_em_nbyte.h
#   2005/02/15 12:15:33-08:00 davem@nuts.davemloft.net +13 -0
#   [PKT_SCHED]: Multi byte comparison ematch (nbyte)
# 
# include/linux/tc_ematch/tc_em_nbyte.h
#   2005/02/15 12:15:33-08:00 davem@nuts.davemloft.net +0 -0
#   BitKeeper file /disk1/BK/net-2.6.12/include/linux/tc_ematch/tc_em_nbyte.h
# 
# ChangeSet
#   2005/02/15 12:14:44-08:00 davem@nuts.davemloft.net 
#   [PKT_SCHED]: Simple comparison ematch (cmp)
#   
#   The cmp ematch compares a static value provided by userspace against
#   a 8, 16, or 32bit chunk read from the packet. The reading offset is
#   provided by userspace and based on one of the skb layers (mac|nh|h).
#   The ematch provides functionality to transform the byte order of
#   the chunk and/or apply a mask and understands the operands eq, lt,
#   and gt. Basically, it is very similiar to the u32 (e)match but tries
#   filling the gaps left behind.
#   
#   Signed-off-by: Thomas Graf <tgraf@suug.ch>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/sched/Makefile
#   2005/02/15 12:13:58-08:00 davem@nuts.davemloft.net +1 -0
#   [PKT_SCHED]: Simple comparison ematch (cmp)
# 
# net/sched/Kconfig
#   2005/02/15 12:13:58-08:00 davem@nuts.davemloft.net +10 -0
#   [PKT_SCHED]: Simple comparison ematch (cmp)
# 
# include/net/pkt_cls.h
#   2005/02/15 12:13:58-08:00 davem@nuts.davemloft.net +20 -0
#   [PKT_SCHED]: Simple comparison ematch (cmp)
# 
# include/linux/pkt_cls.h
#   2005/02/15 12:13:58-08:00 davem@nuts.davemloft.net +8 -0
#   [PKT_SCHED]: Simple comparison ematch (cmp)
# 
# net/sched/em_cmp.c
#   2005/02/15 12:13:56-08:00 davem@nuts.davemloft.net +101 -0
#   [PKT_SCHED]: Simple comparison ematch (cmp)
# 
# net/sched/em_cmp.c
#   2005/02/15 12:13:56-08:00 davem@nuts.davemloft.net +0 -0
#   BitKeeper file /disk1/BK/net-2.6.12/net/sched/em_cmp.c
# 
# include/linux/tc_ematch/tc_em_cmp.h
#   2005/02/15 12:13:55-08:00 davem@nuts.davemloft.net +26 -0
#   [PKT_SCHED]: Simple comparison ematch (cmp)
# 
# include/linux/tc_ematch/tc_em_cmp.h
#   2005/02/15 12:13:55-08:00 davem@nuts.davemloft.net +0 -0
#   BitKeeper file /disk1/BK/net-2.6.12/include/linux/tc_ematch/tc_em_cmp.h
# 
# ChangeSet
#   2005/02/15 12:13:15-08:00 davem@nuts.davemloft.net 
#   [PKT_SCHED]: Extended Matches API
#   
#   An extended match (ematch) is a small classifiction tool not worth
#   writing a full classifier for. Ematches can be interconnected to form
#   a logic expression and get attached to classifiers to extend their
#   functionatlity.
#   
#   The userspace part transforms the logic expressions into an array
#   consisting of multiple sequences of interconnected ematches separated
#   by markers. Precedence is implemented by a special ematch kind
#   referencing a sequence beyond the marker of the current sequence
#   causing the current position in the sequence to be pushed onto a stack
#   to allow the current position to be overwritten by the position
#   referenced in the special ematch. Matching continues in the new sequence
#   until a marker is reached causing the position to be restored from the
#   stack.
#   
#   Signed-off-by: Thomas Graf <tgraf@suug.ch>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/sched/Makefile
#   2005/02/15 12:12:37-08:00 davem@nuts.davemloft.net +1 -0
#   [PKT_SCHED]: Extended Matches API
# 
# net/sched/Kconfig
#   2005/02/15 12:12:37-08:00 davem@nuts.davemloft.net +23 -0
#   [PKT_SCHED]: Extended Matches API
# 
# include/net/pkt_cls.h
#   2005/02/15 12:12:37-08:00 davem@nuts.davemloft.net +170 -0
#   [PKT_SCHED]: Extended Matches API
# 
# include/linux/rtnetlink.h
#   2005/02/15 12:12:37-08:00 davem@nuts.davemloft.net +5 -0
#   [PKT_SCHED]: Extended Matches API
# 
# include/linux/pkt_cls.h
#   2005/02/15 12:12:37-08:00 davem@nuts.davemloft.net +72 -0
#   [PKT_SCHED]: Extended Matches API
# 
# net/sched/ematch.c
#   2005/02/15 12:12:33-08:00 davem@nuts.davemloft.net +524 -0
#   [PKT_SCHED]: Extended Matches API
# 
# net/sched/ematch.c
#   2005/02/15 12:12:33-08:00 davem@nuts.davemloft.net +0 -0
#   BitKeeper file /disk1/BK/net-2.6.12/net/sched/ematch.c
# 
# ChangeSet
#   2005/02/15 21:05:48+01:00 vojtech@suse.cz 
#   input: Properly ignore padding fields in HID reports.
#   
#   Bug-found-by: Ted <6x0124@yahoo.com.tw>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/usb/input/hid-core.c
#   2005/02/15 21:05:37+01:00 vojtech@suse.cz +5 -3
#   input: Properly ignore padding fields in HID reports.
#   
#   Bug-found-by: Ted <6x0124@yahoo.com.tw>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# ChangeSet
#   2005/02/15 11:54:41-08:00 davem@nuts.davemloft.net 
#   Merge nuts.davemloft.net:/disk1/BK/network-2.6.12
#   into nuts.davemloft.net:/disk1/BK/net-2.6.12
# 
# net/ipv4/route.c
#   2005/02/15 11:54:29-08:00 davem@nuts.davemloft.net +0 -0
#   Auto merged
# 
# net/core/sock.c
#   2005/02/15 11:54:29-08:00 davem@nuts.davemloft.net +0 -0
#   Auto merged
# 
# drivers/char/random.c
#   2005/02/15 11:54:29-08:00 davem@nuts.davemloft.net +0 -0
#   Auto merged
# 
# drivers/atm/iphase.c
#   2005/02/15 11:54:29-08:00 davem@nuts.davemloft.net +0 -0
#   Auto merged
# 
# ChangeSet
#   2005/02/15 16:05:47+01:00 dtor_core@ameritech.net 
#   Input: fix race timer handling races in gameport-based joystick drivers
#          by moving pollig timer down into gameport and using spinlock to
#          protect it.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# include/linux/gameport.h
#   2005/02/15 16:05:41+01:00 dtor_core@ameritech.net +19 -0
#   Input: fix race timer handling races in gameport-based joystick drivers
#          by moving pollig timer down into gameport and using spinlock to
#          protect it.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/joystick/tmdc.c
#   2005/02/15 16:05:41+01:00 dtor_core@ameritech.net +10 -15
#   Input: fix race timer handling races in gameport-based joystick drivers
#          by moving pollig timer down into gameport and using spinlock to
#          protect it.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/joystick/interact.c
#   2005/02/15 16:05:41+01:00 dtor_core@ameritech.net +8 -16
#   Input: fix race timer handling races in gameport-based joystick drivers
#          by moving pollig timer down into gameport and using spinlock to
#          protect it.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/joystick/guillemot.c
#   2005/02/15 16:05:41+01:00 dtor_core@ameritech.net +8 -15
#   Input: fix race timer handling races in gameport-based joystick drivers
#          by moving pollig timer down into gameport and using spinlock to
#          protect it.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/joystick/grip_mp.c
#   2005/02/15 16:05:41+01:00 dtor_core@ameritech.net +7 -23
#   Input: fix race timer handling races in gameport-based joystick drivers
#          by moving pollig timer down into gameport and using spinlock to
#          protect it.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/joystick/grip.c
#   2005/02/15 16:05:40+01:00 dtor_core@ameritech.net +9 -15
#   Input: fix race timer handling races in gameport-based joystick drivers
#          by moving pollig timer down into gameport and using spinlock to
#          protect it.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/joystick/gf2k.c
#   2005/02/15 16:05:40+01:00 dtor_core@ameritech.net +13 -17
#   Input: fix race timer handling races in gameport-based joystick drivers
#          by moving pollig timer down into gameport and using spinlock to
#          protect it.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/joystick/cobra.c
#   2005/02/15 16:05:40+01:00 dtor_core@ameritech.net +12 -16
#   Input: fix race timer handling races in gameport-based joystick drivers
#          by moving pollig timer down into gameport and using spinlock to
#          protect it.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/joystick/analog.c
#   2005/02/15 16:05:40+01:00 dtor_core@ameritech.net +10 -15
#   Input: fix race timer handling races in gameport-based joystick drivers
#          by moving pollig timer down into gameport and using spinlock to
#          protect it.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/joystick/adi.c
#   2005/02/15 16:05:40+01:00 dtor_core@ameritech.net +11 -14
#   Input: fix race timer handling races in gameport-based joystick drivers
#          by moving pollig timer down into gameport and using spinlock to
#          protect it.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/joystick/a3d.c
#   2005/02/15 16:05:40+01:00 dtor_core@ameritech.net +17 -21
#   Input: fix race timer handling races in gameport-based joystick drivers
#          by moving pollig timer down into gameport and using spinlock to
#          protect it.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/gameport/gameport.c
#   2005/02/15 16:05:40+01:00 dtor_core@ameritech.net +41 -1
#   Input: fix race timer handling races in gameport-based joystick drivers
#          by moving pollig timer down into gameport and using spinlock to
#          protect it.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# ChangeSet
#   2005/02/15 15:14:38+01:00 syrjala@sci.fi 
#   input: Some changes to ati_remote key assignments:
#   - Channel up/down keys are reversed on my ATI Remote Wonder.
#   - Use KEY_TV, KEY_DVD and KEY_OK where appropriate.
#   - Replace KEY_PLAYCD with KEY_PLAY.
#   
#   Signed-off-by: Ville Syrjala <syrjala@sci.fi>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/usb/input/ati_remote.c
#   2005/02/15 15:14:32+01:00 syrjala@sci.fi +6 -6
#   input: Some changes to ati_remote key assignments:
#   - Channel up/down keys are reversed on my ATI Remote Wonder.
#   - Use KEY_TV, KEY_DVD and KEY_OK where appropriate.
#   - Replace KEY_PLAYCD with KEY_PLAY.
#   
#   Signed-off-by: Ville Syrjala <syrjala@sci.fi>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# ChangeSet
#   2005/02/15 15:13:33+01:00 syrjala@sci.fi 
#   input: Make ati_remote clean up properly when removing either the device or the
#   module.
#   
#   Signed-off-by: Ville Syrjala <syrjala@sci.fi>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/usb/input/ati_remote.c
#   2005/02/15 15:13:26+01:00 syrjala@sci.fi +3 -21
#   input: Make ati_remote clean up properly when removing either the device or the
#   module.
#   
#   Signed-off-by: Ville Syrjala <syrjala@sci.fi>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# ChangeSet
#   2005/02/14 16:24:30+01:00 perex@suse.cz 
#   [ALSA] Add ac97_quirk for Dell machine
#   
#   Intel8x0 driver
#   Added ac97_quirk option for Dell machine.
#   
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/intel8x0.c
#   2005/02/14 08:19:39+01:00 perex@suse.cz +6 -0
#   [ALSA] Add ac97_quirk for Dell machine
#   
#   D:2005/02/14 15:19:39
#   C:Intel8x0 driver
#   F:pci/intel8x0.c:1.194->1.195 
#   L:Added ac97_quirk option for Dell machine.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2005/02/14 16:23:16+01:00 perex@suse.cz 
#   [ALSA] Enables SPDIF output on the Audigy2 Value
#   
#   EMU10K1/EMU10K2 driver
#   Enables SPDIF output on the Audigy2 Value.
#   It seems to work for PCM, but not AC3 yet.
#   
#   Signed-off-by: James Courtier-Dutton <James@superbug.co.uk>
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/emu10k1/emu10k1_main.c
#   2005/02/14 06:53:40+01:00 perex@suse.cz +9 -0
#   [ALSA] Enables SPDIF output on the Audigy2 Value
#   
#   D:2005/02/14 13:53:40
#   C:EMU10K1/EMU10K2 driver
#   F:pci/emu10k1/emu10k1_main.c:1.42->1.43 
#   L:Enables SPDIF output on the Audigy2 Value.
#   L:It seems to work for PCM, but not AC3 yet.
#   Signed-off-by: James Courtier-Dutton <James@superbug.co.uk>
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2005/02/14 16:22:05+01:00 perex@suse.cz 
#   [ALSA] Add support for Audigy2LS on MSI motherboard
#   
#   CA0106 driver
#   Add support for Audigy2LS on MSI motherboard.
#   Fixes Bug #0901
#   
#   Signed-off-by: James Courtier-Dutton <James@superbug.demon.co.uk>
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/ca0106/ca0106_main.c
#   2005/02/14 06:46:49+01:00 perex@suse.cz +10 -3
#   [ALSA] Add support for Audigy2LS on MSI motherboard
#   
#   D:2005/02/14 13:46:49
#   C:CA0106 driver
#   F:pci/ca0106/ca0106_main.c:1.3->1.4 
#   L:Add support for Audigy2LS on MSI motherboard.
#   L:Fixes Bug #0901
#   Signed-off-by: James Courtier-Dutton <James@superbug.demon.co.uk>
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2005/02/14 16:20:52+01:00 perex@suse.cz 
#   [ALSA] fix typo in midi code
#   
#   RME HDSP driver
#   fix typo in midi code
#   
#   Signed-off-by: Thomas Charbonnel <thomas@undata.org>
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/rme9652/hdsp.c
#   2005/02/14 06:44:50+01:00 perex@suse.cz +1 -1
#   [ALSA] fix typo in midi code
#   
#   D:2005/02/14 13:44:50
#   C:RME HDSP driver
#   F:pci/rme9652/hdsp.c:1.82->1.83 
#   L:fix typo in midi code
#   Signed-off-by: Thomas Charbonnel <thomas@undata.org>
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2005/02/14 16:19:39+01:00 perex@suse.cz 
#   [ALSA] Fix rate setting on multiple codecs
#   
#   AC97 Codec
#   From Ron Cococcia <ron.cococcia@request.com>:
#   
#   Fixed the PCM rate setting on multiple AC97 codecs.
#   
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/ac97/ac97_pcm.c
#   2005/02/14 06:43:03+01:00 perex@suse.cz +3 -3
#   [ALSA] Fix rate setting on multiple codecs
#   
#   D:2005/02/14 13:43:03
#   C:AC97 Codec
#   F:pci/ac97/ac97_pcm.c:1.19->1.20 
#   L:From Ron Cococcia <ron.cococcia@request.com>:
#   L:
#   L:Fixed the PCM rate setting on multiple AC97 codecs.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2005/02/14 16:18:30+01:00 perex@suse.cz 
#   [ALSA] split snd_emu10k1_trigger_voice into trigger and prepare functions
#   
#   EMU10K1/EMU10K2 driver
#   This patch provides better sync between multiple voices by separating
#   the trigger_voice function into prepare_voice which sets up the volume
#   and filter parameters and trigger_voice which sets pitch target, current
#   and initial pitch and enables the voice interrupt.  For standard PCM
#   this should not make much of a difference but will be important for
#   minimizing phase error between voices for multichannel PCM.
#   
#   This behavior was derived from the opensource.creative.com driver.
#   
#   Signed-off-by: Lee Revell <rlrevell@joe-job.com>
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/emu10k1/emupcm.c
#   2005/02/14 06:37:23+01:00 perex@suse.cz +26 -8
#   [ALSA] split snd_emu10k1_trigger_voice into trigger and prepare functions
#   
#   D:2005/02/14 13:37:23
#   C:EMU10K1/EMU10K2 driver
#   F:pci/emu10k1/emupcm.c:1.37->1.38 
#   L:This patch provides better sync between multiple voices by separating
#   L:the trigger_voice function into prepare_voice which sets up the volume
#   L:and filter parameters and trigger_voice which sets pitch target, current
#   L:and initial pitch and enables the voice interrupt.  For standard PCM
#   L:this should not make much of a difference but will be important for
#   L:minimizing phase error between voices for multichannel PCM.
#   L:
#   L:This behavior was derived from the opensource.creative.com driver.
#   Signed-off-by: Lee Revell <rlrevell@joe-job.com>
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2005/02/14 16:03:46+01:00 perex@suse.cz 
#   [ALSA] Remove unused yss225.h
#   
#   Wavefront drivers
#   yss225.h is just obsolete, not used/read by any codes.
#   Let's remove it.
#   
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# BitKeeper/deleted/.del-yss225.h~c73ea10a3054ca69
#   2005/02/14 16:03:14+01:00 perex@suse.cz +0 -0
#   Delete: include/sound/yss225.h
# 
# ChangeSet
#   2005/02/14 15:31:18+01:00 perex@suse.cz 
#   [ALSA] Added support for Terratec PHASE 22
#   
#   ICE1712 driver,ICE1724 driver
#   I've struggled for a couple of days with Terratec Phase 22 card.
#   Chips used on it are well known but the combination is somehow unique.
#   Phase 88 should have been similar...  but it actually uses 1712
#   instead of 1721 (Envy24HT-S). So here is the patch against release
#   1.0.8 that adds Phase 22 to ice1724. I've tested only analog part
#   (balances 1/4 TRS in and outs).
#   
#   Signed-off-by: Misha Zhilin <misha@epiphan.com>
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/ice1712/phase.h
#   2005/02/14 14:19:10+01:00 perex@suse.cz +34 -0
#   [ALSA] Added support for Terratec PHASE 22
#   
#   D:2005/02/09 10:47:51
#   C:ICE1712 driver,ICE1724 driver
#   F:pci/ice1712/Makefile:1.15->1.16 
#   F:pci/ice1712/ice1724.c:1.50->1.51 
#   F:pci/ice1712/phase.c:INITIAL->1.1 
#   F:pci/ice1712/phase.h:INITIAL->1.1 
#   L:I've struggled for a couple of days with Terratec Phase 22 card.
#   L:Chips used on it are well known but the combination is somehow unique.
#   L:Phase 88 should have been similar...  but it actually uses 1712
#   L:instead of 1721 (Envy24HT-S). So here is the patch against release
#   L:1.0.8 that adds Phase 22 to ice1724. I've tested only analog part
#   L:(balances 1/4 TRS in and outs).
#   Signed-off-by: Misha Zhilin <misha@epiphan.com>
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/ice1712/phase.h
#   2005/02/14 14:19:10+01:00 perex@suse.cz +0 -0
#   BitKeeper file /home/perex/bk/linux-sound/work/sound/pci/ice1712/phase.h
# 
# sound/pci/ice1712/ice1724.c
#   2005/02/09 03:47:51+01:00 perex@suse.cz +3 -0
#   [ALSA] Added support for Terratec PHASE 22
#   
#   D:2005/02/09 10:47:51
#   C:ICE1712 driver,ICE1724 driver
#   F:pci/ice1712/Makefile:1.15->1.16 
#   F:pci/ice1712/ice1724.c:1.50->1.51 
#   F:pci/ice1712/phase.c:INITIAL->1.1 
#   F:pci/ice1712/phase.h:INITIAL->1.1 
#   L:I've struggled for a couple of days with Terratec Phase 22 card.
#   L:Chips used on it are well known but the combination is somehow unique.
#   L:Phase 88 should have been similar...  but it actually uses 1712
#   L:instead of 1721 (Envy24HT-S). So here is the patch against release
#   L:1.0.8 that adds Phase 22 to ice1724. I've tested only analog part
#   L:(balances 1/4 TRS in and outs).
#   Signed-off-by: Misha Zhilin <misha@epiphan.com>
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/ice1712/Makefile
#   2005/02/09 03:47:51+01:00 perex@suse.cz +1 -1
#   [ALSA] Added support for Terratec PHASE 22
#   
#   D:2005/02/09 10:47:51
#   C:ICE1712 driver,ICE1724 driver
#   F:pci/ice1712/Makefile:1.15->1.16 
#   F:pci/ice1712/ice1724.c:1.50->1.51 
#   F:pci/ice1712/phase.c:INITIAL->1.1 
#   F:pci/ice1712/phase.h:INITIAL->1.1 
#   L:I've struggled for a couple of days with Terratec Phase 22 card.
#   L:Chips used on it are well known but the combination is somehow unique.
#   L:Phase 88 should have been similar...  but it actually uses 1712
#   L:instead of 1721 (Envy24HT-S). So here is the patch against release
#   L:1.0.8 that adds Phase 22 to ice1724. I've tested only analog part
#   L:(balances 1/4 TRS in and outs).
#   Signed-off-by: Misha Zhilin <misha@epiphan.com>
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/ice1712/phase.c
#   2005/02/14 14:19:06+01:00 perex@suse.cz +138 -0
#   [ALSA] Added support for Terratec PHASE 22
#   
#   D:2005/02/09 10:47:51
#   C:ICE1712 driver,ICE1724 driver
#   F:pci/ice1712/Makefile:1.15->1.16 
#   F:pci/ice1712/ice1724.c:1.50->1.51 
#   F:pci/ice1712/phase.c:INITIAL->1.1 
#   F:pci/ice1712/phase.h:INITIAL->1.1 
#   L:I've struggled for a couple of days with Terratec Phase 22 card.
#   L:Chips used on it are well known but the combination is somehow unique.
#   L:Phase 88 should have been similar...  but it actually uses 1712
#   L:instead of 1721 (Envy24HT-S). So here is the patch against release
#   L:1.0.8 that adds Phase 22 to ice1724. I've tested only analog part
#   L:(balances 1/4 TRS in and outs).
#   Signed-off-by: Misha Zhilin <misha@epiphan.com>
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/ice1712/phase.c
#   2005/02/14 14:19:06+01:00 perex@suse.cz +0 -0
#   BitKeeper file /home/perex/bk/linux-sound/work/sound/pci/ice1712/phase.c
# 
# ChangeSet
#   2005/02/14 15:27:44+01:00 perex@suse.cz 
#   [ALSA] AK4114 - fixed workqueue initialization & removed debug code
#   
#   AK4114 receiver
#   
#   
#   Signed-off-by: Jaroslav Kysela <perex@suse.cz>
# 
# sound/i2c/other/ak4114.c
#   2005/01/28 07:25:23+01:00 perex@suse.cz +7 -8
#   [ALSA] AK4114 - fixed workqueue initialization & removed debug code
#   
#   D:2005/01/28 14:25:23
#   C:AK4114 receiver
#   F:i2c/other/ak4114.c:1.2->1.3 
#   L:
#   Signed-off-by: Jaroslav Kysela <perex@suse.cz>
# 
# ChangeSet
#   2005/02/14 15:26:34+01:00 perex@suse.cz 
#   [ALSA] fix typo in assignment of snd_ak4114_spdif_playback_put
#   
#   AK4114 receiver
#   snd_ak4114_spdif_playback_put was assigned to the .get callback
#   which resulted in a duplicate initialization of that member
#   
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# sound/i2c/other/ak4114.c
#   2005/01/21 10:43:47+01:00 perex@suse.cz +1 -1
#   [ALSA] fix typo in assignment of snd_ak4114_spdif_playback_put
#   
#   D:2005/01/21 17:43:47
#   C:AK4114 receiver
#   F:i2c/other/ak4114.c:1.1->1.2 
#   L:snd_ak4114_spdif_playback_put was assigned to the .get callback
#   L:which resulted in a duplicate initialization of that member
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# ChangeSet
#   2005/02/14 15:25:22+01:00 perex@suse.cz 
#   [ALSA] Added ICE1724 - ESI Juli@ code (not complete) + AK4114 code + AK4358
#   
#   Serial BUS drivers,AK4114 receiver,AK4XXX AD/DA converters
#   ICE1712 driver,ICE1724 driver
#   Initial incomplete driver for ESI Juli@ cardcards based on ICE1724, AK4114,
#   AK4358 and AK5385. The ICE1724 and ICE1712 main files plus some drivers are
#   also updated (cleanups and new callbacks).
#   
#   Signed-off-by: Jaroslav Kysela <perex@suse.cz>
# 
# sound/pci/ice1712/revo.c
#   2005/01/18 08:48:02+01:00 perex@suse.cz +11 -0
#   [ALSA] Added ICE1724 - ESI Juli@ code (not complete) + AK4114 code + AK4358
#   
#   D:2005/01/18 15:47:47
#   C:Serial BUS drivers,AK4114 receiver,AK4XXX AD/DA converters
#   C:ICE1712 driver,ICE1724 driver
#   F:i2c/other/Makefile:1.3->1.4 
#   F:i2c/other/ak4114.c:INITIAL->1.1 
#   F:i2c/other/ak4xxx-adda.c:1.8->1.9 
#   F:include/ak4114.h:INITIAL->1.1 
#   F:include/ak4xxx-adda.h:1.3->1.4 
#   F:pci/ice1712/Makefile:1.14->1.15 
#   F:pci/ice1712/ak4xxx.c:1.10->1.11 
#   F:pci/ice1712/envy24ht.h:1.4->1.5 
#   F:pci/ice1712/ice1712.c:1.64->1.65 
#   F:pci/ice1712/ice1712.h:1.27->1.28 
#   F:pci/ice1712/ice1724.c:1.49->1.50 
#   F:pci/ice1712/juli.c:INITIAL->1.1 
#   F:pci/ice1712/juli.h:INITIAL->1.1 
#   F:pci/ice1712/prodigy192.c:1.1->1.2 
#   F:pci/ice1712/revo.c:1.8->1.9 
#   L:Initial incomplete driver for ESI Juli@ cardcards based on ICE1724, AK4114,
#   L:AK4358 and AK5385. The ICE1724 and ICE1712 main files plus some drivers are
#   L:also updated (cleanups and new callbacks).
#   Signed-off-by: Jaroslav Kysela <perex@suse.cz>
# 
# sound/pci/ice1712/prodigy192.c
#   2005/01/18 08:48:01+01:00 perex@suse.cz +2 -2
#   [ALSA] Added ICE1724 - ESI Juli@ code (not complete) + AK4114 code + AK4358
#   
#   D:2005/01/18 15:47:47
#   C:Serial BUS drivers,AK4114 receiver,AK4XXX AD/DA converters
#   C:ICE1712 driver,ICE1724 driver
#   F:i2c/other/Makefile:1.3->1.4 
#   F:i2c/other/ak4114.c:INITIAL->1.1 
#   F:i2c/other/ak4xxx-adda.c:1.8->1.9 
#   F:include/ak4114.h:INITIAL->1.1 
#   F:include/ak4xxx-adda.h:1.3->1.4 
#   F:pci/ice1712/Makefile:1.14->1.15 
#   F:pci/ice1712/ak4xxx.c:1.10->1.11 
#   F:pci/ice1712/envy24ht.h:1.4->1.5 
#   F:pci/ice1712/ice1712.c:1.64->1.65 
#   F:pci/ice1712/ice1712.h:1.27->1.28 
#   F:pci/ice1712/ice1724.c:1.49->1.50 
#   F:pci/ice1712/juli.c:INITIAL->1.1 
#   F:pci/ice1712/juli.h:INITIAL->1.1 
#   F:pci/ice1712/prodigy192.c:1.1->1.2 
#   F:pci/ice1712/revo.c:1.8->1.9 
#   L:Initial incomplete driver for ESI Juli@ cardcards based on ICE1724, AK4114,
#   L:AK4358 and AK5385. The ICE1724 and ICE1712 main files plus some drivers are
#   L:also updated (cleanups and new callbacks).
#   Signed-off-by: Jaroslav Kysela <perex@suse.cz>
# 
# sound/pci/ice1712/juli.h
#   2005/01/20 19:12:22+01:00 perex@suse.cz +10 -0
#   [ALSA] Added ICE1724 - ESI Juli@ code (not complete) + AK4114 code + AK4358
#   
#   D:2005/01/18 15:47:47
#   C:Serial BUS drivers,AK4114 receiver,AK4XXX AD/DA converters
#   C:ICE1712 driver,ICE1724 driver
#   F:i2c/other/Makefile:1.3->1.4 
#   F:i2c/other/ak4114.c:INITIAL->1.1 
#   F:i2c/other/ak4xxx-adda.c:1.8->1.9 
#   F:include/ak4114.h:INITIAL->1.1 
#   F:include/ak4xxx-adda.h:1.3->1.4 
#   F:pci/ice1712/Makefile:1.14->1.15 
#   F:pci/ice1712/ak4xxx.c:1.10->1.11 
#   F:pci/ice1712/envy24ht.h:1.4->1.5 
#   F:pci/ice1712/ice1712.c:1.64->1.65 
#   F:pci/ice1712/ice1712.h:1.27->1.28 
#   F:pci/ice1712/ice1724.c:1.49->1.50 
#   F:pci/ice1712/juli.c:INITIAL->1.1 
#   F:pci/ice1712/juli.h:INITIAL->1.1 
#   F:pci/ice1712/prodigy192.c:1.1->1.2 
#   F:pci/ice1712/revo.c:1.8->1.9 
#   L:Initial incomplete driver for ESI Juli@ cardcards based on ICE1724, AK4114,
#   L:AK4358 and AK5385. The ICE1724 and ICE1712 main files plus some drivers are
#   L:also updated (cleanups and new callbacks).
#   Signed-off-by: Jaroslav Kysela <perex@suse.cz>
# 
# sound/pci/ice1712/juli.c
#   2005/01/20 19:12:18+01:00 perex@suse.cz +230 -0
#   [ALSA] Added ICE1724 - ESI Juli@ code (not complete) + AK4114 code + AK4358
#   
#   D:2005/01/18 15:47:47
#   C:Serial BUS drivers,AK4114 receiver,AK4XXX AD/DA converters
#   C:ICE1712 driver,ICE1724 driver
#   F:i2c/other/Makefile:1.3->1.4 
#   F:i2c/other/ak4114.c:INITIAL->1.1 
#   F:i2c/other/ak4xxx-adda.c:1.8->1.9 
#   F:include/ak4114.h:INITIAL->1.1 
#   F:include/ak4xxx-adda.h:1.3->1.4 
#   F:pci/ice1712/Makefile:1.14->1.15 
#   F:pci/ice1712/ak4xxx.c:1.10->1.11 
#   F:pci/ice1712/envy24ht.h:1.4->1.5 
#   F:pci/ice1712/ice1712.c:1.64->1.65 
#   F:pci/ice1712/ice1712.h:1.27->1.28 
#   F:pci/ice1712/ice1724.c:1.49->1.50 
#   F:pci/ice1712/juli.c:INITIAL->1.1 
#   F:pci/ice1712/juli.h:INITIAL->1.1 
#   F:pci/ice1712/prodigy192.c:1.1->1.2 
#   F:pci/ice1712/revo.c:1.8->1.9 
#   L:Initial incomplete driver for ESI Juli@ cardcards based on ICE1724, AK4114,
#   L:AK4358 and AK5385. The ICE1724 and ICE1712 main files plus some drivers are
#   L:also updated (cleanups and new callbacks).
#   Signed-off-by: Jaroslav Kysela <perex@suse.cz>
# 
# sound/pci/ice1712/ice1724.c
#   2005/01/18 08:48:00+01:00 perex@suse.cz +42 -26
#   [ALSA] Added ICE1724 - ESI Juli@ code (not complete) + AK4114 code + AK4358
#   
#   D:2005/01/18 15:47:47
#   C:Serial BUS drivers,AK4114 receiver,AK4XXX AD/DA converters
#   C:ICE1712 driver,ICE1724 driver
#   F:i2c/other/Makefile:1.3->1.4 
#   F:i2c/other/ak4114.c:INITIAL->1.1 
#   F:i2c/other/ak4xxx-adda.c:1.8->1.9 
#   F:include/ak4114.h:INITIAL->1.1 
#   F:include/ak4xxx-adda.h:1.3->1.4 
#   F:pci/ice1712/Makefile:1.14->1.15 
#   F:pci/ice1712/ak4xxx.c:1.10->1.11 
#   F:pci/ice1712/envy24ht.h:1.4->1.5 
#   F:pci/ice1712/ice1712.c:1.64->1.65 
#   F:pci/ice1712/ice1712.h:1.27->1.28 
#   F:pci/ice1712/ice1724.c:1.49->1.50 
#   F:pci/ice1712/juli.c:INITIAL->1.1 
#   F:pci/ice1712/juli.h:INITIAL->1.1 
#   F:pci/ice1712/prodigy192.c:1.1->1.2 
#   F:pci/ice1712/revo.c:1.8->1.9 
#   L:Initial incomplete driver for ESI Juli@ cardcards based on ICE1724, AK4114,
#   L:AK4358 and AK5385. The ICE1724 and ICE1712 main files plus some drivers are
#   L:also updated (cleanups and new callbacks).
#   Signed-off-by: Jaroslav Kysela <perex@suse.cz>
# 
# sound/pci/ice1712/ice1712.h
#   2005/01/18 08:48:00+01:00 perex@suse.cz +8 -1
#   [ALSA] Added ICE1724 - ESI Juli@ code (not complete) + AK4114 code + AK4358
#   
#   D:2005/01/18 15:47:47
#   C:Serial BUS drivers,AK4114 receiver,AK4XXX AD/DA converters
#   C:ICE1712 driver,ICE1724 driver
#   F:i2c/other/Makefile:1.3->1.4 
#   F:i2c/other/ak4114.c:INITIAL->1.1 
#   F:i2c/other/ak4xxx-adda.c:1.8->1.9 
#   F:include/ak4114.h:INITIAL->1.1 
#   F:include/ak4xxx-adda.h:1.3->1.4 
#   F:pci/ice1712/Makefile:1.14->1.15 
#   F:pci/ice1712/ak4xxx.c:1.10->1.11 
#   F:pci/ice1712/envy24ht.h:1.4->1.5 
#   F:pci/ice1712/ice1712.c:1.64->1.65 
#   F:pci/ice1712/ice1712.h:1.27->1.28 
#   F:pci/ice1712/ice1724.c:1.49->1.50 
#   F:pci/ice1712/juli.c:INITIAL->1.1 
#   F:pci/ice1712/juli.h:INITIAL->1.1 
#   F:pci/ice1712/prodigy192.c:1.1->1.2 
#   F:pci/ice1712/revo.c:1.8->1.9 
#   L:Initial incomplete driver for ESI Juli@ cardcards based on ICE1724, AK4114,
#   L:AK4358 and AK5385. The ICE1724 and ICE1712 main files plus some drivers are
#   L:also updated (cleanups and new callbacks).
#   Signed-off-by: Jaroslav Kysela <perex@suse.cz>
# 
# sound/pci/ice1712/ice1712.c
#   2005/01/18 08:48:00+01:00 perex@suse.cz +18 -14
#   [ALSA] Added ICE1724 - ESI Juli@ code (not complete) + AK4114 code + AK4358
#   
#   D:2005/01/18 15:47:47
#   C:Serial BUS drivers,AK4114 receiver,AK4XXX AD/DA converters
#   C:ICE1712 driver,ICE1724 driver
#   F:i2c/other/Makefile:1.3->1.4 
#   F:i2c/other/ak4114.c:INITIAL->1.1 
#   F:i2c/other/ak4xxx-adda.c:1.8->1.9 
#   F:include/ak4114.h:INITIAL->1.1 
#   F:include/ak4xxx-adda.h:1.3->1.4 
#   F:pci/ice1712/Makefile:1.14->1.15 
#   F:pci/ice1712/ak4xxx.c:1.10->1.11 
#   F:pci/ice1712/envy24ht.h:1.4->1.5 
#   F:pci/ice1712/ice1712.c:1.64->1.65 
#   F:pci/ice1712/ice1712.h:1.27->1.28 
#   F:pci/ice1712/ice1724.c:1.49->1.50 
#   F:pci/ice1712/juli.c:INITIAL->1.1 
#   F:pci/ice1712/juli.h:INITIAL->1.1 
#   F:pci/ice1712/prodigy192.c:1.1->1.2 
#   F:pci/ice1712/revo.c:1.8->1.9 
#   L:Initial incomplete driver for ESI Juli@ cardcards based on ICE1724, AK4114,
#   L:AK4358 and AK5385. The ICE1724 and ICE1712 main files plus some drivers are
#   L:also updated (cleanups and new callbacks).
#   Signed-off-by: Jaroslav Kysela <perex@suse.cz>
# 
# sound/pci/ice1712/envy24ht.h
#   2005/01/18 08:48:00+01:00 perex@suse.cz +1 -1
#   [ALSA] Added ICE1724 - ESI Juli@ code (not complete) + AK4114 code + AK4358
#   
#   D:2005/01/18 15:47:47
#   C:Serial BUS drivers,AK4114 receiver,AK4XXX AD/DA converters
#   C:ICE1712 driver,ICE1724 driver
#   F:i2c/other/Makefile:1.3->1.4 
#   F:i2c/other/ak4114.c:INITIAL->1.1 
#   F:i2c/other/ak4xxx-adda.c:1.8->1.9 
#   F:include/ak4114.h:INITIAL->1.1 
#   F:include/ak4xxx-adda.h:1.3->1.4 
#   F:pci/ice1712/Makefile:1.14->1.15 
#   F:pci/ice1712/ak4xxx.c:1.10->1.11 
#   F:pci/ice1712/envy24ht.h:1.4->1.5 
#   F:pci/ice1712/ice1712.c:1.64->1.65 
#   F:pci/ice1712/ice1712.h:1.27->1.28 
#   F:pci/ice1712/ice1724.c:1.49->1.50 
#   F:pci/ice1712/juli.c:INITIAL->1.1 
#   F:pci/ice1712/juli.h:INITIAL->1.1 
#   F:pci/ice1712/prodigy192.c:1.1->1.2 
#   F:pci/ice1712/revo.c:1.8->1.9 
#   L:Initial incomplete driver for ESI Juli@ cardcards based on ICE1724, AK4114,
#   L:AK4358 and AK5385. The ICE1724 and ICE1712 main files plus some drivers are
#   L:also updated (cleanups and new callbacks).
#   Signed-off-by: Jaroslav Kysela <perex@suse.cz>
# 
# sound/pci/ice1712/ak4xxx.c
#   2005/01/18 08:48:00+01:00 perex@suse.cz +8 -4
#   [ALSA] Added ICE1724 - ESI Juli@ code (not complete) + AK4114 code + AK4358
#   
#   D:2005/01/18 15:47:47
#   C:Serial BUS drivers,AK4114 receiver,AK4XXX AD/DA converters
#   C:ICE1712 driver,ICE1724 driver
#   F:i2c/other/Makefile:1.3->1.4 
#   F:i2c/other/ak4114.c:INITIAL->1.1 
#   F:i2c/other/ak4xxx-adda.c:1.8->1.9 
#   F:include/ak4114.h:INITIAL->1.1 
#   F:include/ak4xxx-adda.h:1.3->1.4 
#   F:pci/ice1712/Makefile:1.14->1.15 
#   F:pci/ice1712/ak4xxx.c:1.10->1.11 
#   F:pci/ice1712/envy24ht.h:1.4->1.5 
#   F:pci/ice1712/ice1712.c:1.64->1.65 
#   F:pci/ice1712/ice1712.h:1.27->1.28 
#   F:pci/ice1712/ice1724.c:1.49->1.50 
#   F:pci/ice1712/juli.c:INITIAL->1.1 
#   F:pci/ice1712/juli.h:INITIAL->1.1 
#   F:pci/ice1712/prodigy192.c:1.1->1.2 
#   F:pci/ice1712/revo.c:1.8->1.9 
#   L:Initial incomplete driver for ESI Juli@ cardcards based on ICE1724, AK4114,
#   L:AK4358 and AK5385. The ICE1724 and ICE1712 main files plus some drivers are
#   L:also updated (cleanups and new callbacks).
#   Signed-off-by: Jaroslav Kysela <perex@suse.cz>
# 
# sound/pci/ice1712/Makefile
#   2005/01/18 08:48:00+01:00 perex@suse.cz +1 -1
#   [ALSA] Added ICE1724 - ESI Juli@ code (not complete) + AK4114 code + AK4358
#   
#   D:2005/01/18 15:47:47
#   C:Serial BUS drivers,AK4114 receiver,AK4XXX AD/DA converters
#   C:ICE1712 driver,ICE1724 driver
#   F:i2c/other/Makefile:1.3->1.4 
#   F:i2c/other/ak4114.c:INITIAL->1.1 
#   F:i2c/other/ak4xxx-adda.c:1.8->1.9 
#   F:include/ak4114.h:INITIAL->1.1 
#   F:include/ak4xxx-adda.h:1.3->1.4 
#   F:pci/ice1712/Makefile:1.14->1.15 
#   F:pci/ice1712/ak4xxx.c:1.10->1.11 
#   F:pci/ice1712/envy24ht.h:1.4->1.5 
#   F:pci/ice1712/ice1712.c:1.64->1.65 
#   F:pci/ice1712/ice1712.h:1.27->1.28 
#   F:pci/ice1712/ice1724.c:1.49->1.50 
#   F:pci/ice1712/juli.c:INITIAL->1.1 
#   F:pci/ice1712/juli.h:INITIAL->1.1 
#   F:pci/ice1712/prodigy192.c:1.1->1.2 
#   F:pci/ice1712/revo.c:1.8->1.9 
#   L:Initial incomplete driver for ESI Juli@ cardcards based on ICE1724, AK4114,
#   L:AK4358 and AK5385. The ICE1724 and ICE1712 main files plus some drivers are
#   L:also updated (cleanups and new callbacks).
#   Signed-off-by: Jaroslav Kysela <perex@suse.cz>
# 
# sound/i2c/other/ak4xxx-adda.c
#   2005/01/18 08:47:47+01:00 perex@suse.cz +33 -3
#   [ALSA] Added ICE1724 - ESI Juli@ code (not complete) + AK4114 code + AK4358
#   
#   D:2005/01/18 15:47:47
#   C:Serial BUS drivers,AK4114 receiver,AK4XXX AD/DA converters
#   C:ICE1712 driver,ICE1724 driver
#   F:i2c/other/Makefile:1.3->1.4 
#   F:i2c/other/ak4114.c:INITIAL->1.1 
#   F:i2c/other/ak4xxx-adda.c:1.8->1.9 
#   F:include/ak4114.h:INITIAL->1.1 
#   F:include/ak4xxx-adda.h:1.3->1.4 
#   F:pci/ice1712/Makefile:1.14->1.15 
#   F:pci/ice1712/ak4xxx.c:1.10->1.11 
#   F:pci/ice1712/envy24ht.h:1.4->1.5 
#   F:pci/ice1712/ice1712.c:1.64->1.65 
#   F:pci/ice1712/ice1712.h:1.27->1.28 
#   F:pci/ice1712/ice1724.c:1.49->1.50 
#   F:pci/ice1712/juli.c:INITIAL->1.1 
#   F:pci/ice1712/juli.h:INITIAL->1.1 
#   F:pci/ice1712/prodigy192.c:1.1->1.2 
#   F:pci/ice1712/revo.c:1.8->1.9 
#   L:Initial incomplete driver for ESI Juli@ cardcards based on ICE1724, AK4114,
#   L:AK4358 and AK5385. The ICE1724 and ICE1712 main files plus some drivers are
#   L:also updated (cleanups and new callbacks).
#   Signed-off-by: Jaroslav Kysela <perex@suse.cz>
# 
# sound/i2c/other/Makefile
#   2005/01/18 08:47:47+01:00 perex@suse.cz +2 -0
#   [ALSA] Added ICE1724 - ESI Juli@ code (not complete) + AK4114 code + AK4358
#   
#   D:2005/01/18 15:47:47
#   C:Serial BUS drivers,AK4114 receiver,AK4XXX AD/DA converters
#   C:ICE1712 driver,ICE1724 driver
#   F:i2c/other/Makefile:1.3->1.4 
#   F:i2c/other/ak4114.c:INITIAL->1.1 
#   F:i2c/other/ak4xxx-adda.c:1.8->1.9 
#   F:include/ak4114.h:INITIAL->1.1 
#   F:include/ak4xxx-adda.h:1.3->1.4 
#   F:pci/ice1712/Makefile:1.14->1.15 
#   F:pci/ice1712/ak4xxx.c:1.10->1.11 
#   F:pci/ice1712/envy24ht.h:1.4->1.5 
#   F:pci/ice1712/ice1712.c:1.64->1.65 
#   F:pci/ice1712/ice1712.h:1.27->1.28 
#   F:pci/ice1712/ice1724.c:1.49->1.50 
#   F:pci/ice1712/juli.c:INITIAL->1.1 
#   F:pci/ice1712/juli.h:INITIAL->1.1 
#   F:pci/ice1712/prodigy192.c:1.1->1.2 
#   F:pci/ice1712/revo.c:1.8->1.9 
#   L:Initial incomplete driver for ESI Juli@ cardcards based on ICE1724, AK4114,
#   L:AK4358 and AK5385. The ICE1724 and ICE1712 main files plus some drivers are
#   L:also updated (cleanups and new callbacks).
#   Signed-off-by: Jaroslav Kysela <perex@suse.cz>
# 
# include/sound/ak4xxx-adda.h
#   2005/01/18 08:47:59+01:00 perex@suse.cz +2 -1
#   [ALSA] Added ICE1724 - ESI Juli@ code (not complete) + AK4114 code + AK4358
#   
#   D:2005/01/18 15:47:47
#   C:Serial BUS drivers,AK4114 receiver,AK4XXX AD/DA converters
#   C:ICE1712 driver,ICE1724 driver
#   F:i2c/other/Makefile:1.3->1.4 
#   F:i2c/other/ak4114.c:INITIAL->1.1 
#   F:i2c/other/ak4xxx-adda.c:1.8->1.9 
#   F:include/ak4114.h:INITIAL->1.1 
#   F:include/ak4xxx-adda.h:1.3->1.4 
#   F:pci/ice1712/Makefile:1.14->1.15 
#   F:pci/ice1712/ak4xxx.c:1.10->1.11 
#   F:pci/ice1712/envy24ht.h:1.4->1.5 
#   F:pci/ice1712/ice1712.c:1.64->1.65 
#   F:pci/ice1712/ice1712.h:1.27->1.28 
#   F:pci/ice1712/ice1724.c:1.49->1.50 
#   F:pci/ice1712/juli.c:INITIAL->1.1 
#   F:pci/ice1712/juli.h:INITIAL->1.1 
#   F:pci/ice1712/prodigy192.c:1.1->1.2 
#   F:pci/ice1712/revo.c:1.8->1.9 
#   L:Initial incomplete driver for ESI Juli@ cardcards based on ICE1724, AK4114,
#   L:AK4358 and AK5385. The ICE1724 and ICE1712 main files plus some drivers are
#   L:also updated (cleanups and new callbacks).
#   Signed-off-by: Jaroslav Kysela <perex@suse.cz>
# 
# include/sound/ak4114.h
#   2005/01/20 19:11:13+01:00 perex@suse.cz +205 -0
#   [ALSA] Added ICE1724 - ESI Juli@ code (not complete) + AK4114 code + AK4358
#   
#   D:2005/01/18 15:47:47
#   C:Serial BUS drivers,AK4114 receiver,AK4XXX AD/DA converters
#   C:ICE1712 driver,ICE1724 driver
#   F:i2c/other/Makefile:1.3->1.4 
#   F:i2c/other/ak4114.c:INITIAL->1.1 
#   F:i2c/other/ak4xxx-adda.c:1.8->1.9 
#   F:include/ak4114.h:INITIAL->1.1 
#   F:include/ak4xxx-adda.h:1.3->1.4 
#   F:pci/ice1712/Makefile:1.14->1.15 
#   F:pci/ice1712/ak4xxx.c:1.10->1.11 
#   F:pci/ice1712/envy24ht.h:1.4->1.5 
#   F:pci/ice1712/ice1712.c:1.64->1.65 
#   F:pci/ice1712/ice1712.h:1.27->1.28 
#   F:pci/ice1712/ice1724.c:1.49->1.50 
#   F:pci/ice1712/juli.c:INITIAL->1.1 
#   F:pci/ice1712/juli.h:INITIAL->1.1 
#   F:pci/ice1712/prodigy192.c:1.1->1.2 
#   F:pci/ice1712/revo.c:1.8->1.9 
#   L:Initial incomplete driver for ESI Juli@ cardcards based on ICE1724, AK4114,
#   L:AK4358 and AK5385. The ICE1724 and ICE1712 main files plus some drivers are
#   L:also updated (cleanups and new callbacks).
#   Signed-off-by: Jaroslav Kysela <perex@suse.cz>
# 
# sound/pci/ice1712/juli.h
#   2005/01/20 19:12:22+01:00 perex@suse.cz +0 -0
#   BitKeeper file /home/perex/bk/linux-sound/work/sound/pci/ice1712/juli.h
# 
# sound/pci/ice1712/juli.c
#   2005/01/20 19:12:18+01:00 perex@suse.cz +0 -0
#   BitKeeper file /home/perex/bk/linux-sound/work/sound/pci/ice1712/juli.c
# 
# sound/i2c/other/ak4114.c
#   2005/01/20 19:11:04+01:00 perex@suse.cz +581 -0
#   [ALSA] Added ICE1724 - ESI Juli@ code (not complete) + AK4114 code + AK4358
#   
#   D:2005/01/18 15:47:47
#   C:Serial BUS drivers,AK4114 receiver,AK4XXX AD/DA converters
#   C:ICE1712 driver,ICE1724 driver
#   F:i2c/other/Makefile:1.3->1.4 
#   F:i2c/other/ak4114.c:INITIAL->1.1 
#   F:i2c/other/ak4xxx-adda.c:1.8->1.9 
#   F:include/ak4114.h:INITIAL->1.1 
#   F:include/ak4xxx-adda.h:1.3->1.4 
#   F:pci/ice1712/Makefile:1.14->1.15 
#   F:pci/ice1712/ak4xxx.c:1.10->1.11 
#   F:pci/ice1712/envy24ht.h:1.4->1.5 
#   F:pci/ice1712/ice1712.c:1.64->1.65 
#   F:pci/ice1712/ice1712.h:1.27->1.28 
#   F:pci/ice1712/ice1724.c:1.49->1.50 
#   F:pci/ice1712/juli.c:INITIAL->1.1 
#   F:pci/ice1712/juli.h:INITIAL->1.1 
#   F:pci/ice1712/prodigy192.c:1.1->1.2 
#   F:pci/ice1712/revo.c:1.8->1.9 
#   L:Initial incomplete driver for ESI Juli@ cardcards based on ICE1724, AK4114,
#   L:AK4358 and AK5385. The ICE1724 and ICE1712 main files plus some drivers are
#   L:also updated (cleanups and new callbacks).
#   Signed-off-by: Jaroslav Kysela <perex@suse.cz>
# 
# include/sound/ak4114.h
#   2005/01/20 19:11:13+01:00 perex@suse.cz +0 -0
#   BitKeeper file /home/perex/bk/linux-sound/work/include/sound/ak4114.h
# 
# sound/i2c/other/ak4114.c
#   2005/01/20 19:11:04+01:00 perex@suse.cz +0 -0
#   BitKeeper file /home/perex/bk/linux-sound/work/sound/i2c/other/ak4114.c
# 
# ChangeSet
#   2005/02/14 15:21:35+01:00 perex@suse.cz 
#   [ALSA] add STAC9708 output bias mixer control
#   
#   AC97 Codec
#   This adds a mixer control for an undocumented bit of the STAC9708
#   that somehow affects the analog output.  This should help reducing
#   the distortion at high output levels on ymfpci and SBLive cards.
#   
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# sound/pci/ac97/ac97_patch.c
#   2005/02/11 02:56:09+01:00 perex@suse.cz +27 -0
#   [ALSA] add STAC9708 output bias mixer control
#   
#   D:2005/02/11 09:56:09
#   C:AC97 Codec
#   F:pci/ac97/ac97_patch.c:1.71->1.72 
#   L:This adds a mixer control for an undocumented bit of the STAC9708
#   L:that somehow affects the analog output.  This should help reducing
#   L:the distortion at high output levels on ymfpci and SBLive cards.
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# ChangeSet
#   2005/02/14 15:20:21+01:00 perex@suse.cz 
#   [ALSA] MPU-401 driver cleanup
#   
#   MPU401 UART
#   Correctly check for error codes returned by pnp_register_driver,
#   use a common function for registering the sound card, and remove
#   many #ifdef's.
#   
#   Signed-off-by: Matthieu Castet <castet.matthieu@free.fr>
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# sound/drivers/mpu401/mpu401.c
#   2005/02/11 02:51:56+01:00 perex@suse.cz +68 -74
#   [ALSA] MPU-401 driver cleanup
#   
#   D:2005/02/11 09:51:56
#   C:MPU401 UART
#   F:drivers/mpu401/mpu401.c:1.22->1.23 
#   L:Correctly check for error codes returned by pnp_register_driver,
#   L:use a common function for registering the sound card, and remove
#   L:many #ifdef's.
#   Signed-off-by: Matthieu Castet <castet.matthieu@free.fr>
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# ChangeSet
#   2005/02/14 15:19:12+01:00 perex@suse.cz 
#   [ALSA] add 96Khz support and setting sample rate for	direct SPDIF output
#   
#   EMU10K1/EMU10K2 driver
#   This patch should add support for 96Khz 'direct SPDIF' aka 'SPDIF
#   Bypass' (not P16V) playback mode available on the Audigy1 and 2 and
#   newer SBLives (?).  It lets you bypass the 48khz DSP resampling when
#   using the card in digital mode.  It also adds 96khz analog playback
#   support, good for testing but less interesting because it's downsampled
#   to 48khz.  A new mixer control 'Audigy SPDIF Output Sample Rate' is
#   created, you can choose 44100, 48000, or 96000.  Standard SPDIF
#   playback, AC3 passthrough (real 96khz playback), and analog playback
#   (96khz is resampled to 48khz in the DSP) all work with a 16 bit,96khz
#   wav file.  Only the last was tested due to lack of any SPDIF hardware.
#   
#   This was derived mostly from the opensource.creative.com driver.  All
#   that was needed for 96khz playback to work in analog mode was changing
#   the format to 8000_96000 (looks like the creative driver supports 192khz
#   too).  And, of course this sample rate has always been supported (albeit
#   downsampled) because if you have 48khz samples in a soundfont the
#   envelope engine has to be able to pitch shift them in both directions.
#   
#   I still have not been able to figure out how to get 24 bit playback to
#   work.  This is possible, independent of the P16V, for spdif and analog
#   24/48 playback via the DSP.  I do know how to access the full 24 bits
#   from the ADC from within the DSP, just not how to get it in there.  For
#   one thing I have no idea which 24 bit format it supports.  Some of them
#   seemed to work with JACK but produced noise.
#   
#   This was generated with my multichannel patch but it applies against
#   ALSA CVS as well.
#   
#   Signed-off-by: Lee Revell <rlrevell@joe-job.com>
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/emu10k1/emupcm.c
#   2005/02/10 04:52:51+01:00 perex@suse.cz +2 -2
#   [ALSA] add 96Khz support and setting sample rate for	direct SPDIF output
#   
#   D:2005/02/10 11:52:50
#   C:EMU10K1/EMU10K2 driver
#   F:include/emu10k1.h:1.54->1.55 
#   F:pci/emu10k1/emumixer.c:1.28->1.29 
#   F:pci/emu10k1/emupcm.c:1.36->1.37 
#   L:This patch should add support for 96Khz 'direct SPDIF' aka 'SPDIF
#   L:Bypass' (not P16V) playback mode available on the Audigy1 and 2 and
#   L:newer SBLives (?).  It lets you bypass the 48khz DSP resampling when
#   L:using the card in digital mode.  It also adds 96khz analog playback
#   L:support, good for testing but less interesting because it's downsampled
#   L:to 48khz.  A new mixer control 'Audigy SPDIF Output Sample Rate' is
#   L:created, you can choose 44100, 48000, or 96000.  Standard SPDIF
#   L:playback, AC3 passthrough (real 96khz playback), and analog playback
#   L:(96khz is resampled to 48khz in the DSP) all work with a 16 bit,96khz
#   L:wav file.  Only the last was tested due to lack of any SPDIF hardware.
#   L:
#   L:This was derived mostly from the opensource.creative.com driver.  All
#   L:that was needed for 96khz playback to work in analog mode was changing
#   L:the format to 8000_96000 (looks like the creative driver supports 192khz
#   L:too).  And, of course this sample rate has always been supported (albeit
#   L:downsampled) because if you have 48khz samples in a soundfont the
#   L:envelope engine has to be able to pitch shift them in both directions.
#   L:
#   L:I still have not been able to figure out how to get 24 bit playback to
#   L:work.  This is possible, independent of the P16V, for spdif and analog
#   L:24/48 playback via the DSP.  I do know how to access the full 24 bits
#   L:from the ADC from within the DSP, just not how to get it in there.  For
#   L:one thing I have no idea which 24 bit format it supports.  Some of them
#   L:seemed to work with JACK but produced noise.
#   L:
#   L:This was generated with my multichannel patch but it applies against
#   L:ALSA CVS as well.
#   Signed-off-by: Lee Revell <rlrevell@joe-job.com>
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/emu10k1/emumixer.c
#   2005/02/10 04:52:51+01:00 perex@suse.cz +89 -0
#   [ALSA] add 96Khz support and setting sample rate for	direct SPDIF output
#   
#   D:2005/02/10 11:52:50
#   C:EMU10K1/EMU10K2 driver
#   F:include/emu10k1.h:1.54->1.55 
#   F:pci/emu10k1/emumixer.c:1.28->1.29 
#   F:pci/emu10k1/emupcm.c:1.36->1.37 
#   L:This patch should add support for 96Khz 'direct SPDIF' aka 'SPDIF
#   L:Bypass' (not P16V) playback mode available on the Audigy1 and 2 and
#   L:newer SBLives (?).  It lets you bypass the 48khz DSP resampling when
#   L:using the card in digital mode.  It also adds 96khz analog playback
#   L:support, good for testing but less interesting because it's downsampled
#   L:to 48khz.  A new mixer control 'Audigy SPDIF Output Sample Rate' is
#   L:created, you can choose 44100, 48000, or 96000.  Standard SPDIF
#   L:playback, AC3 passthrough (real 96khz playback), and analog playback
#   L:(96khz is resampled to 48khz in the DSP) all work with a 16 bit,96khz
#   L:wav file.  Only the last was tested due to lack of any SPDIF hardware.
#   L:
#   L:This was derived mostly from the opensource.creative.com driver.  All
#   L:that was needed for 96khz playback to work in analog mode was changing
#   L:the format to 8000_96000 (looks like the creative driver supports 192khz
#   L:too).  And, of course this sample rate has always been supported (albeit
#   L:downsampled) because if you have 48khz samples in a soundfont the
#   L:envelope engine has to be able to pitch shift them in both directions.
#   L:
#   L:I still have not been able to figure out how to get 24 bit playback to
#   L:work.  This is possible, independent of the P16V, for spdif and analog
#   L:24/48 playback via the DSP.  I do know how to access the full 24 bits
#   L:from the ADC from within the DSP, just not how to get it in there.  For
#   L:one thing I have no idea which 24 bit format it supports.  Some of them
#   L:seemed to work with JACK but produced noise.
#   L:
#   L:This was generated with my multichannel patch but it applies against
#   L:ALSA CVS as well.
#   Signed-off-by: Lee Revell <rlrevell@joe-job.com>
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# include/sound/emu10k1.h
#   2005/02/10 04:52:50+01:00 perex@suse.cz +4 -3
#   [ALSA] add 96Khz support and setting sample rate for	direct SPDIF output
#   
#   D:2005/02/10 11:52:50
#   C:EMU10K1/EMU10K2 driver
#   F:include/emu10k1.h:1.54->1.55 
#   F:pci/emu10k1/emumixer.c:1.28->1.29 
#   F:pci/emu10k1/emupcm.c:1.36->1.37 
#   L:This patch should add support for 96Khz 'direct SPDIF' aka 'SPDIF
#   L:Bypass' (not P16V) playback mode available on the Audigy1 and 2 and
#   L:newer SBLives (?).  It lets you bypass the 48khz DSP resampling when
#   L:using the card in digital mode.  It also adds 96khz analog playback
#   L:support, good for testing but less interesting because it's downsampled
#   L:to 48khz.  A new mixer control 'Audigy SPDIF Output Sample Rate' is
#   L:created, you can choose 44100, 48000, or 96000.  Standard SPDIF
#   L:playback, AC3 passthrough (real 96khz playback), and analog playback
#   L:(96khz is resampled to 48khz in the DSP) all work with a 16 bit,96khz
#   L:wav file.  Only the last was tested due to lack of any SPDIF hardware.
#   L:
#   L:This was derived mostly from the opensource.creative.com driver.  All
#   L:that was needed for 96khz playback to work in analog mode was changing
#   L:the format to 8000_96000 (looks like the creative driver supports 192khz
#   L:too).  And, of course this sample rate has always been supported (albeit
#   L:downsampled) because if you have 48khz samples in a soundfont the
#   L:envelope engine has to be able to pitch shift them in both directions.
#   L:
#   L:I still have not been able to figure out how to get 24 bit playback to
#   L:work.  This is possible, independent of the P16V, for spdif and analog
#   L:24/48 playback via the DSP.  I do know how to access the full 24 bits
#   L:from the ADC from within the DSP, just not how to get it in there.  For
#   L:one thing I have no idea which 24 bit format it supports.  Some of them
#   L:seemed to work with JACK but produced noise.
#   L:
#   L:This was generated with my multichannel patch but it applies against
#   L:ALSA CVS as well.
#   Signed-off-by: Lee Revell <rlrevell@joe-job.com>
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2005/02/14 15:18:00+01:00 perex@suse.cz 
#   [ALSA] fix sound/isa/gus/interwave.c compile with PNP=n
#   
#   AMD InterWave driver
#   Emmanuel Colbus sent this patch one month ago with the following
#   description:
#   
#   There is a trivial bug in the file sound/isa/gus/interwave.c .
#   The variable isapnp is defined only if CONFIG_PNP is enabled, but it is
#   always used few lines after.
#   
#   Signed-off-by: Adrian Bunk <bunk@stusta.de>
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/isa/gus/interwave.c
#   2005/02/10 04:35:42+01:00 perex@suse.cz +2 -0
#   [ALSA] fix sound/isa/gus/interwave.c compile with PNP=n
#   
#   D:2005/02/10 11:35:42
#   C:AMD InterWave driver
#   F:isa/gus/interwave.c:1.37->1.38 
#   L:Emmanuel Colbus sent this patch one month ago with the following
#   L:description:
#   L:
#   L:There is a trivial bug in the file sound/isa/gus/interwave.c .
#   L:The variable isapnp is defined only if CONFIG_PNP is enabled, but it is
#   L:always used few lines after.
#   Signed-off-by: Adrian Bunk <bunk@stusta.de>
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2005/02/14 15:11:49+01:00 perex@suse.cz 
#   [ALSA] Bind master and HP controls with hp_only quirk
#   
#   AC97 Codec
#   Bind master and HP controls when hp_only quirk is given, instead
#   of removing master control.  This fixes the problem of some laptops
#   which require sync'ed volume for PC-speaker and headphone output.
#   
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/ac97/ac97_codec.c
#   2005/02/09 03:27:15+01:00 perex@suse.cz +30 -0
#   [ALSA] Bind master and HP controls with hp_only quirk
#   
#   D:2005/02/09 10:27:15
#   C:AC97 Codec
#   F:pci/ac97/ac97_codec.c:1.169->1.170 
#   L:Bind master and HP controls when hp_only quirk is given, instead
#   L:of removing master control.  This fixes the problem of some laptops
#   L:which require sync'ed volume for PC-speaker and headphone output.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2005/02/14 15:10:40+01:00 perex@suse.cz 
#   [ALSA] fixes als100 not detecting opl3
#   
#   ALS100 driver
#   This patch fixes issue when opl3 device couldn't be found
#   due to numbering of devices in pnp card, because search of
#   opl3 device started from mpu device, which could have number
#   greater than opl3 could.
#   
#   Example:
#   MPU is 00:01.03
#   and
#   OPL is 00:01.01
#   
#   Signed-off-by: Anton Romanov <theli@ukr.net>
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# sound/isa/als100.c
#   2005/02/07 08:20:21+01:00 perex@suse.cz +1 -1
#   [ALSA] fixes als100 not detecting opl3
#   
#   D:2005/02/07 15:20:21
#   C:ALS100 driver
#   F:isa/als100.c:1.29->1.30 
#   L:This patch fixes issue when opl3 device couldn't be found
#   L:due to numbering of devices in pnp card, because search of
#   L:opl3 device started from mpu device, which could have number
#   L:greater than opl3 could.
#   L:
#   L:Example:
#   L:MPU is 00:01.03
#   L:and
#   L:OPL is 00:01.01
#   Signed-off-by: Anton Romanov <theli@ukr.net>
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# ChangeSet
#   2005/02/14 15:09:33+01:00 perex@suse.cz 
#   [ALSA] enable disabling of isapnp
#   
#   OPL3SA2 driver
#   Fixed a logic error that prevented the 'isapnp=0' module
#   parameter from taking effect.
#   
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# sound/isa/opl3sa2.c
#   2005/02/07 02:05:26+01:00 perex@suse.cz +1 -1
#   [ALSA] enable disabling of isapnp
#   
#   D:2005/02/07 09:05:26
#   C:OPL3SA2 driver
#   F:isa/opl3sa2.c:1.43->1.44 
#   L:Fixed a logic error that prevented the 'isapnp=0' module
#   L:parameter from taking effect.
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# ChangeSet
#   2005/02/14 15:08:24+01:00 perex@suse.cz 
#   [ALSA] MPU-401 PnP support
#   
#   Documentation,MPU401 UART
#   Replace the ACPI PnP code with generic PnP calls.
#   
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# sound/drivers/mpu401/mpu401.c
#   2005/02/07 01:40:37+01:00 perex@suse.cz +73 -121
#   [ALSA] MPU-401 PnP support
#   
#   D:2005/02/07 08:40:37
#   C:Documentation,MPU401 UART
#   F:Documentation/ALSA-Configuration.txt:1.68->1.69 
#   F:drivers/mpu401/mpu401.c:1.21->1.22 
#   L:Replace the ACPI PnP code with generic PnP calls.
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# Documentation/sound/alsa/ALSA-Configuration.txt
#   2005/02/07 01:40:37+01:00 perex@suse.cz +2 -3
#   [ALSA] MPU-401 PnP support
#   
#   D:2005/02/07 08:40:37
#   C:Documentation,MPU401 UART
#   F:Documentation/ALSA-Configuration.txt:1.68->1.69 
#   F:drivers/mpu401/mpu401.c:1.21->1.22 
#   L:Replace the ACPI PnP code with generic PnP calls.
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# ChangeSet
#   2005/02/14 15:07:15+01:00 perex@suse.cz 
#   [ALSA] Add quirk for Fujitsu S6210
#   
#   Intel8x0 driver
#   Added ac97_quirk for Fujitsu S6210.
#   
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/intel8x0.c
#   2005/02/04 10:00:49+01:00 perex@suse.cz +6 -0
#   [ALSA] Add quirk for Fujitsu S6210
#   
#   D:2005/02/04 17:00:49
#   C:Intel8x0 driver
#   F:pci/intel8x0.c:1.193->1.194 
#   L:Added ac97_quirk for Fujitsu S6210.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2005/02/14 15:06:09+01:00 perex@suse.cz 
#   [ALSA] Add __iomem prefix
#   
#   BT87x driver
#   Added __iomem prefix to the mmio pointer.
#   
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/bt87x.c
#   2005/02/04 09:08:58+01:00 perex@suse.cz +1 -1
#   [ALSA] Add __iomem prefix
#   
#   D:2005/02/04 16:08:58
#   C:BT87x driver
#   F:pci/bt87x.c:1.19->1.20 
#   L:Added __iomem prefix to the mmio pointer.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2005/02/14 15:04:59+01:00 perex@suse.cz 
#   [ALSA] Remove interruptible_sleep_on_timeout().
#   
#   ALSA<-OSS sequencer
#   Use wait_event_interruptible_timeout() instead of deprecated
#   interruptible_sleep_on_timeout().
#   
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/core/seq/oss/seq_oss_writeq.c
#   2005/02/04 08:31:49+01:00 perex@suse.cz +5 -19
#   [ALSA] Remove interruptible_sleep_on_timeout().
#   
#   D:2005/02/04 15:31:49
#   C:ALSA<-OSS sequencer
#   F:core/seq/oss/seq_oss_readq.c:1.11->1.12 
#   F:core/seq/oss/seq_oss_writeq.c:1.6->1.7 
#   L:Use wait_event_interruptible_timeout() instead of deprecated
#   L:interruptible_sleep_on_timeout().
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/core/seq/oss/seq_oss_readq.c
#   2005/02/04 08:31:49+01:00 perex@suse.cz +4 -1
#   [ALSA] Remove interruptible_sleep_on_timeout().
#   
#   D:2005/02/04 15:31:49
#   C:ALSA<-OSS sequencer
#   F:core/seq/oss/seq_oss_readq.c:1.11->1.12 
#   F:core/seq/oss/seq_oss_writeq.c:1.6->1.7 
#   L:Use wait_event_interruptible_timeout() instead of deprecated
#   L:interruptible_sleep_on_timeout().
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2005/02/14 15:03:52+01:00 perex@suse.cz 
#   [ALSA] remove interruptible_sleep_on_timeout() usage
#   
#   GUS Library
#   Replace deprecated interruptible_sleep_on_timeout() with
#   wait_event_timeout(). Code is not identical, as the current sleeping
#   system is 1 jiffy at a time checking atomic_read()'s return every
#   iteration. Patch is compile-tested.
#   
#   Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/isa/gus/gus_pcm.c
#   2005/02/04 08:30:35+01:00 perex@suse.cz +3 -9
#   [ALSA] remove interruptible_sleep_on_timeout() usage
#   
#   D:2005/02/04 15:30:35
#   C:GUS Library
#   F:isa/gus/gus_pcm.c:1.24->1.25 
#   L:Replace deprecated interruptible_sleep_on_timeout() with
#   L:wait_event_timeout(). Code is not identical, as the current sleeping
#   L:system is 1 jiffy at a time checking atomic_read()'s return every
#   L:iteration. Patch is compile-tested.
#   Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2005/02/14 15:02:40+01:00 perex@suse.cz 
#   [ALSA] Korg1212 updates
#   
#   KORG1212 driver
#   This patches covers the following issues:
#   
#       - solves double 'spin_lock_irqsave' problems;
#       - eliminate the use of deprecated function 'sleep_on_timeout';
#       - clarify some 'printk' messages; and
#       - logs korg DMA Errors due to PCI congestion.
#   
#   Signed-off-by: Haroldo Gamal <gamal@alternex.com.br>
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/korg1212/korg1212.c
#   2005/02/03 10:30:57+01:00 perex@suse.cz +43 -32
#   [ALSA] Korg1212 updates
#   
#   D:2005/02/03 17:30:57
#   C:KORG1212 driver
#   F:pci/korg1212/korg1212.c:1.53->1.54 
#   L:This patches covers the following issues:
#   L:
#   L:    - solves double 'spin_lock_irqsave' problems;
#   L:    - eliminate the use of deprecated function 'sleep_on_timeout';
#   L:    - clarify some 'printk' messages; and
#   L:    - logs korg DMA Errors due to PCI congestion.
#   Signed-off-by: Haroldo Gamal <gamal@alternex.com.br>
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2005/02/14 15:01:33+01:00 perex@suse.cz 
#   [ALSA] Novation and MOTU USB MIDI support
#   
#   USB generic driver
#   Rewrote USB MIDI protocol handling code to use callbacks
#   for each protocol;
#   added support for Novation and MOTU protocols;
#   changed detection code to allow interrupt endpoints.
#   
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# sound/usb/usbquirks.h
#   2005/02/02 05:54:08+01:00 perex@suse.cz +44 -6
#   [ALSA] Novation and MOTU USB MIDI support
#   
#   D:2005/02/02 12:54:07
#   C:USB generic driver
#   F:usb/usbaudio.c:1.115->1.116 
#   F:usb/usbaudio.h:1.36->1.37 
#   F:usb/usbmidi.c:1.37->1.38 
#   F:usb/usbquirks.h:1.40->1.41 
#   L:Rewrote USB MIDI protocol handling code to use callbacks
#   L:for each protocol;
#   L:added support for Novation and MOTU protocols;
#   L:changed detection code to allow interrupt endpoints.
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# sound/usb/usbmidi.c
#   2005/02/02 05:54:08+01:00 perex@suse.cz +270 -174
#   [ALSA] Novation and MOTU USB MIDI support
#   
#   D:2005/02/02 12:54:07
#   C:USB generic driver
#   F:usb/usbaudio.c:1.115->1.116 
#   F:usb/usbaudio.h:1.36->1.37 
#   F:usb/usbmidi.c:1.37->1.38 
#   F:usb/usbquirks.h:1.40->1.41 
#   L:Rewrote USB MIDI protocol handling code to use callbacks
#   L:for each protocol;
#   L:added support for Novation and MOTU protocols;
#   L:changed detection code to allow interrupt endpoints.
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# sound/usb/usbaudio.h
#   2005/02/02 05:54:08+01:00 perex@suse.cz +9 -2
#   [ALSA] Novation and MOTU USB MIDI support
#   
#   D:2005/02/02 12:54:07
#   C:USB generic driver
#   F:usb/usbaudio.c:1.115->1.116 
#   F:usb/usbaudio.h:1.36->1.37 
#   F:usb/usbmidi.c:1.37->1.38 
#   F:usb/usbquirks.h:1.40->1.41 
#   L:Rewrote USB MIDI protocol handling code to use callbacks
#   L:for each protocol;
#   L:added support for Novation and MOTU protocols;
#   L:changed detection code to allow interrupt endpoints.
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# sound/usb/usbaudio.c
#   2005/02/02 05:54:07+01:00 perex@suse.cz +2 -0
#   [ALSA] Novation and MOTU USB MIDI support
#   
#   D:2005/02/02 12:54:07
#   C:USB generic driver
#   F:usb/usbaudio.c:1.115->1.116 
#   F:usb/usbaudio.h:1.36->1.37 
#   F:usb/usbmidi.c:1.37->1.38 
#   F:usb/usbquirks.h:1.40->1.41 
#   L:Rewrote USB MIDI protocol handling code to use callbacks
#   L:for each protocol;
#   L:added support for Novation and MOTU protocols;
#   L:changed detection code to allow interrupt endpoints.
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# ChangeSet
#   2005/02/14 15:00:22+01:00 perex@suse.cz 
#   [ALSA] simplify snd_usbmidi_count_bits()
#   
#   USB generic driver
#   This makes the bit counting code smaller and simpler.
#   
#   Signed-off-by: Charles C. Bennett <ccb@acm.org>
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# sound/usb/usbmidi.c
#   2005/02/02 05:45:33+01:00 perex@suse.cz +4 -4
#   [ALSA] simplify snd_usbmidi_count_bits()
#   
#   D:2005/02/02 12:45:33
#   C:USB generic driver
#   F:usb/usbmidi.c:1.36->1.37 
#   L:This makes the bit counting code smaller and simpler.
#   Signed-off-by: Charles C. Bennett <ccb@acm.org>
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# ChangeSet
#   2005/02/14 14:59:12+01:00 perex@suse.cz 
#   [ALSA] capture EXTINs with multichannel device
#   
#   EMU10K1/EMU10K2 driver
#   This patch changes the emu10k1 multichannel capture device (hw:x,2) to
#   capture the 16 external inputs by default.  This involves adding DSP
#   code to route the EXTINs to the FXBUS2 (EFX capture) channels and
#   setting the corresponding FXWC bits by default.
#   
#   This allows capturing multiple inputs simultaneously.  It completely
#   bypasses the capture controls of the mixer.  With my Audigy2 ZS I can
#   capture LineIn, Line2, and Aux2 at the same time (6 channels).
#   
#   Signed-off-by: Lee Revell <rlrevell@joe-job.com>
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/emu10k1/emupcm.c
#   2005/02/02 04:52:46+01:00 perex@suse.cz +12 -2
#   [ALSA] capture EXTINs with multichannel device
#   
#   D:2005/02/02 11:52:45
#   C:EMU10K1/EMU10K2 driver
#   F:include/emu10k1.h:1.53->1.54 
#   F:pci/emu10k1/emufx.c:1.67->1.68 
#   F:pci/emu10k1/emupcm.c:1.35->1.36 
#   L:This patch changes the emu10k1 multichannel capture device (hw:x,2) to
#   L:capture the 16 external inputs by default.  This involves adding DSP
#   L:code to route the EXTINs to the FXBUS2 (EFX capture) channels and
#   L:setting the corresponding FXWC bits by default.
#   L:
#   L:This allows capturing multiple inputs simultaneously.  It completely
#   L:bypasses the capture controls of the mixer.  With my Audigy2 ZS I can
#   L:capture LineIn, Line2, and Aux2 at the same time (6 channels).
#   Signed-off-by: Lee Revell <rlrevell@joe-job.com>
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/emu10k1/emufx.c
#   2005/02/02 04:52:46+01:00 perex@suse.cz +23 -0
#   [ALSA] capture EXTINs with multichannel device
#   
#   D:2005/02/02 11:52:45
#   C:EMU10K1/EMU10K2 driver
#   F:include/emu10k1.h:1.53->1.54 
#   F:pci/emu10k1/emufx.c:1.67->1.68 
#   F:pci/emu10k1/emupcm.c:1.35->1.36 
#   L:This patch changes the emu10k1 multichannel capture device (hw:x,2) to
#   L:capture the 16 external inputs by default.  This involves adding DSP
#   L:code to route the EXTINs to the FXBUS2 (EFX capture) channels and
#   L:setting the corresponding FXWC bits by default.
#   L:
#   L:This allows capturing multiple inputs simultaneously.  It completely
#   L:bypasses the capture controls of the mixer.  With my Audigy2 ZS I can
#   L:capture LineIn, Line2, and Aux2 at the same time (6 channels).
#   Signed-off-by: Lee Revell <rlrevell@joe-job.com>
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# include/sound/emu10k1.h
#   2005/02/02 04:52:45+01:00 perex@suse.cz +11 -4
#   [ALSA] capture EXTINs with multichannel device
#   
#   D:2005/02/02 11:52:45
#   C:EMU10K1/EMU10K2 driver
#   F:include/emu10k1.h:1.53->1.54 
#   F:pci/emu10k1/emufx.c:1.67->1.68 
#   F:pci/emu10k1/emupcm.c:1.35->1.36 
#   L:This patch changes the emu10k1 multichannel capture device (hw:x,2) to
#   L:capture the 16 external inputs by default.  This involves adding DSP
#   L:code to route the EXTINs to the FXBUS2 (EFX capture) channels and
#   L:setting the corresponding FXWC bits by default.
#   L:
#   L:This allows capturing multiple inputs simultaneously.  It completely
#   L:bypasses the capture controls of the mixer.  With my Audigy2 ZS I can
#   L:capture LineIn, Line2, and Aux2 at the same time (6 channels).
#   Signed-off-by: Lee Revell <rlrevell@joe-job.com>
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2005/02/14 14:57:56+01:00 perex@suse.cz 
#   [ALSA] Add quirk for LEGEND ZhaoYang 3100CF
#   
#   Maestro3 driver
#   Added a quirk entry for LEGEND ZhaoYang 3100CF.
#   
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/maestro3.c
#   2005/02/01 11:27:39+01:00 perex@suse.cz +7 -0
#   [ALSA] Add quirk for LEGEND ZhaoYang 3100CF
#   
#   D:2005/02/01 18:27:39
#   C:Maestro3 driver
#   F:pci/maestro3.c:1.69->1.70 
#   L:Added a quirk entry for LEGEND ZhaoYang 3100CF.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2005/02/14 14:56:43+01:00 perex@suse.cz 
#   [ALSA] replace interruptible_sleep_on_timeout() with wait_event_interruptible_timeout()
#   
#   RawMidi Midlevel
#   Use wai_event_interruptible_timeout() instead of deprecated
#   interruptible_sleep_on_timeout(). Patch is compile-tested.
#   
#   Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/core/rawmidi.c
#   2005/01/31 07:58:05+01:00 perex@suse.cz +9 -11
#   [ALSA] replace interruptible_sleep_on_timeout() with wait_event_interruptible_timeout()
#   
#   D:2005/01/31 14:58:05
#   C:RawMidi Midlevel
#   F:core/rawmidi.c:1.53->1.54 
#   L:Use wai_event_interruptible_timeout() instead of deprecated
#   L:interruptible_sleep_on_timeout(). Patch is compile-tested.
#   Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2005/02/14 14:55:33+01:00 perex@suse.cz 
#   [ALSA] Kconfig: cleanup sound menu
#   
#   ALSA Core
#   This properly indents the sound menu.
#   
#   Signed-off-by: Roman Zippel <zippel@linux-m68k.org>
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/core/Kconfig
#   2005/01/31 07:48:50+01:00 perex@suse.cz +7 -1
#   [ALSA] Kconfig: cleanup sound menu
#   
#   D:2005/01/31 14:48:50
#   C:ALSA Core
#   F:core/Kconfig:1.9->1.10 
#   L:This properly indents the sound menu.
#   Signed-off-by: Roman Zippel <zippel@linux-m68k.org>
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2005/02/14 14:54:24+01:00 perex@suse.cz 
#   [ALSA] hdsp ghost midi device fix
#   
#   RME HDSP driver
#   * Prevents the creation of a second midi device for cards with only
#     one midi I/O
#   
#   Signed-off-by: Thomas Charbonnel <thomas@undata.org>
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/rme9652/hdsp.c
#   2005/01/31 06:41:30+01:00 perex@suse.cz +8 -5
#   [ALSA] hdsp ghost midi device fix
#   
#   D:2005/01/31 13:41:30
#   C:RME HDSP driver
#   F:pci/rme9652/hdsp.c:1.81->1.82 
#   L:* Prevents the creation of a second midi device for cards with only
#   L:  one midi I/O
#   Signed-off-by: Thomas Charbonnel <thomas@undata.org>
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2005/02/14 14:53:15+01:00 perex@suse.cz 
#   [ALSA] Fix 32bit calls to snd_pcm_channel_info()
#   
#   PCM Midlevel
#   Fix 32-bit calls to snd_pcm_channel_info().
#   
#   Signed-off-by: Brian Gerst <bgerst@didntduck.org>
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/core/pcm_native.c
#   2005/01/31 06:38:39+01:00 perex@suse.cz +16 -10
#   [ALSA] Fix 32bit calls to snd_pcm_channel_info()
#   
#   D:2005/01/31 13:38:39
#   C:PCM Midlevel
#   F:core/pcm_native.c:1.113->1.114 
#   L:Fix 32-bit calls to snd_pcm_channel_info().
#   Signed-off-by: Brian Gerst <bgerst@didntduck.org>
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2005/02/14 14:52:11+01:00 perex@suse.cz 
#   [ALSA] Fix compile error (due to last suspend/resume fix)
#   
#   PPC PMAC driver
#   Fixed the forgotten caller of suspend/resume callbacks to follow
#   the recent PM fixes.
#   
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/ppc/pmac.c
#   2005/01/31 03:41:30+01:00 perex@suse.cz +2 -2
#   [ALSA] Fix compile error (due to last suspend/resume fix)
#   
#   D:2005/01/31 10:41:30
#   C:PPC PMAC driver
#   F:ppc/pmac.c:1.44->1.45 
#   L:Fixed the forgotten caller of suspend/resume callbacks to follow
#   L:the recent PM fixes.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2005/02/14 14:51:01+01:00 perex@suse.cz 
#   [ALSA] intel8x0 - fix for broken PCI ID define for ICH6
#   
#   Intel8x0 driver
#   Patch-level: High
#   
#   Signed-off-by: Jean Delvare <khali@linux-fr.org>
#   Signed-off-by: Jaroslav Kysela <perex@suse.cz>
# 
# sound/pci/intel8x0.c
#   2005/01/31 03:04:10+01:00 perex@suse.cz +3 -3
#   [ALSA] intel8x0 - fix for broken PCI ID define for ICH6
#   
#   D:2005/01/31 10:04:10
#   C:Intel8x0 driver
#   F:pci/intel8x0.c:1.192->1.193 
#   L:Patch-level: High
#   Signed-off-by: Jean Delvare <khali@linux-fr.org>
#   Signed-off-by: Jaroslav Kysela <perex@suse.cz>
# 
# ChangeSet
#   2005/02/14 14:49:48+01:00 perex@suse.cz 
#   [ALSA] intel8x0 - fixed timeout in the 'get current DMA pointer' routine
#   
#   Intel8x0 driver
#   Patch-level: High
#   
#   Signed-off-by: Wei Ni <Wei.Ni@uli.com.tw>
#   Signed-off-by: Jaroslav Kysela <perex@suse.cz>
# 
# sound/pci/intel8x0.c
#   2005/01/31 02:50:36+01:00 perex@suse.cz +5 -3
#   [ALSA] intel8x0 - fixed timeout in the 'get current DMA pointer' routine
#   
#   D:2005/01/31 09:50:36
#   C:Intel8x0 driver
#   F:pci/intel8x0.c:1.191->1.192 
#   L:Patch-level: High
#   Signed-off-by: Wei Ni <Wei.Ni@uli.com.tw>
#   Signed-off-by: Jaroslav Kysela <perex@suse.cz>
# 
# ChangeSet
#   2005/02/14 14:48:36+01:00 perex@suse.cz 
#   [ALSA] Fix suspend/resume functions
#   
#   ALSA Core
#   Fix the suspend/resume callback functions to follow the last change.
#   (This fix was missing in the last patch.)
#   
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/core/init.c
#   2005/01/28 13:18:39+01:00 perex@suse.cz +2 -2
#   [ALSA] Fix suspend/resume functions
#   
#   D:2005/01/28 20:18:39
#   C:ALSA Core
#   F:core/init.c:1.59->1.60 
#   L:Fix the suspend/resume callback functions to follow the last change.
#   L:(This fix was missing in the last patch.)
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2005/02/14 14:47:25+01:00 perex@suse.cz 
#   [ALSA] Fix inclusion of pm.h
#   
#   ALSA Core
#   Added the missing inclusion of linux/pm.h.
#   
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# include/sound/core.h
#   2005/01/28 13:13:27+01:00 perex@suse.cz +1 -0
#   [ALSA] Fix inclusion of pm.h
#   
#   D:2005/01/28 20:13:27
#   C:ALSA Core
#   F:include/core.h:1.66->1.67 
#   L:Added the missing inclusion of linux/pm.h.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2005/02/14 14:46:09+01:00 perex@suse.cz 
#   [ALSA] Fix resume callback
#   
#   HDA Codec driver
#   Fixed resume callback to follow the recent change of PM callbacks.
#   
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/hda/patch_realtek.c
#   2005/01/28 12:48:54+01:00 perex@suse.cz +1 -1
#   [ALSA] Fix resume callback
#   
#   D:2005/01/28 19:48:54
#   C:HDA Codec driver
#   F:pci/hda/patch_cmedia.c:1.1->1.2 
#   F:pci/hda/patch_realtek.c:1.1->1.2 
#   L:Fixed resume callback to follow the recent change of PM callbacks.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/hda/patch_cmedia.c
#   2005/01/28 12:48:54+01:00 perex@suse.cz +1 -1
#   [ALSA] Fix resume callback
#   
#   D:2005/01/28 19:48:54
#   C:HDA Codec driver
#   F:pci/hda/patch_cmedia.c:1.1->1.2 
#   F:pci/hda/patch_realtek.c:1.1->1.2 
#   L:Fixed resume callback to follow the recent change of PM callbacks.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2005/02/14 14:44:45+01:00 perex@suse.cz 
#   [ALSA] Remove unused variable
#   
#   USB USX2Y
#   Removed an unused variable to fix a compile warning.
#   
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/usb/usx2y/usbusx2yaudio.c
#   2005/01/28 12:39:48+01:00 perex@suse.cz +0 -1
#   [ALSA] Remove unused variable
#   
#   D:2005/01/28 19:39:48
#   C:USB USX2Y
#   F:usb/usx2y/usbusx2yaudio.c:1.10->1.11 
#   L:Removed an unused variable to fix a compile warning.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2005/02/14 14:43:33+01:00 perex@suse.cz 
#   [ALSA] Fix descriptions about suspend/resume callbacks
#   
#   Documentation
#   Fixed the descriptions about suspend/resume callbacks.
#   The suspend callback takes pm_message_t argument, and resume takes no
#   extra argument now.
#   
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# Documentation/sound/alsa/hda_codec.txt
#   2005/01/28 12:36:32+01:00 perex@suse.cz +2 -2
#   [ALSA] Fix descriptions about suspend/resume callbacks
#   
#   D:2005/01/28 19:36:32
#   C:Documentation
#   F:Documentation/hda_codec.txt:1.1->1.2 
#   F:Documentation/DocBook/writing-an-alsa-driver.tmpl:1.47->1.48 
#   L:Fixed the descriptions about suspend/resume callbacks.
#   L:The suspend callback takes pm_message_t argument, and resume takes no
#   L:extra argument now.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl
#   2005/01/28 12:36:33+01:00 perex@suse.cz +3 -3
#   [ALSA] Fix descriptions about suspend/resume callbacks
#   
#   D:2005/01/28 19:36:32
#   C:Documentation
#   F:Documentation/hda_codec.txt:1.1->1.2 
#   F:Documentation/DocBook/writing-an-alsa-driver.tmpl:1.47->1.48 
#   L:Fixed the descriptions about suspend/resume callbacks.
#   L:The suspend callback takes pm_message_t argument, and resume takes no
#   L:extra argument now.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2005/02/14 14:42:16+01:00 perex@suse.cz 
#   [ALSA] driver model type fixes for ALSA
#   
#   SA11xx UDA1341 driver,Control Midlevel,ALSA Core,Digigram VX core
#   ES18xx driver,OPL3SA2 driver,AD1848 driver,CS4231 driver,ATIIXP driver
#   ATIIXP-modem driver,CS4281 driver,ES1938 driver,ES1968 driver
#   Intel8x0 driver,Intel8x0-modem driver,Maestro3 driver,VIA82xx driver
#   VIA82xx-modem driver,ALI5451 driver,CS46xx driver,HDA Codec driver
#   HDA Intel driver,NM256 driver,Trident driver,YMFPCI driver
#   PDAudioCF driver,Digigram VX Pocket driver,PPC PMAC driver
#   Fixes by Pavel Machek <pavel@suse.cz>:
#   suspend() routines no longer get u32 as their parameter (they get
#   pm_message_t, which is u32 for now, but will change in 2.6.12 or
#   so). This fixes ALSA to notice this, and uses constants with right
#   types where appropriate. It results in no code changes. [Best results
#   will be when patching against latest -mm, you may get some warnings if
#   you patch it into older kernel, but it should still do the right
#   thing.] Please apply,
#   							Pavel
#   
#   [In addition, suspend callback type is changed to follow to the standard
#    style taking no state argument -- Takashi]
#   
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/ppc/pmac.c
#   2005/01/28 12:34:08+01:00 perex@suse.cz +4 -4
#   [ALSA] driver model type fixes for ALSA
#   
#   D:2005/01/28 19:34:04
#   C:SA11xx UDA1341 driver,Control Midlevel,ALSA Core,Digigram VX core
#   C:ES18xx driver,OPL3SA2 driver,AD1848 driver,CS4231 driver,ATIIXP driver
#   C:ATIIXP-modem driver,CS4281 driver,ES1938 driver,ES1968 driver
#   C:Intel8x0 driver,Intel8x0-modem driver,Maestro3 driver,VIA82xx driver
#   C:VIA82xx-modem driver,ALI5451 driver,CS46xx driver,HDA Codec driver
#   C:HDA Intel driver,NM256 driver,Trident driver,YMFPCI driver
#   C:PDAudioCF driver,Digigram VX Pocket driver,PPC PMAC driver
#   F:arm/sa11xx-uda1341.c:1.20->1.21 
#   F:core/control.c:1.56->1.57 
#   F:core/init.c:1.58->1.59 
#   F:drivers/vx/vx_core.c:1.14->1.15 
#   F:include/core.h:1.65->1.66 
#   F:isa/es18xx.c:1.53->1.54 
#   F:isa/opl3sa2.c:1.42->1.43 
#   F:isa/ad1848/ad1848_lib.c:1.39->1.40 
#   F:isa/cs423x/cs4231_lib.c:1.47->1.48 
#   F:pci/atiixp.c:1.31->1.32 
#   F:pci/atiixp_modem.c:1.14->1.15 
#   F:pci/cs4281.c:1.69->1.70 
#   F:pci/es1938.c:1.45->1.46 
#   F:pci/es1968.c:1.82->1.83 
#   F:pci/intel8x0.c:1.190->1.191 
#   F:pci/intel8x0m.c:1.26->1.27 
#   F:pci/maestro3.c:1.68->1.69 
#   F:pci/via82xx.c:1.135->1.136 
#   F:pci/via82xx_modem.c:1.4->1.5 
#   F:pci/ali5451/ali5451.c:1.60->1.61 
#   F:pci/cs46xx/cs46xx_lib.c:1.93->1.94 
#   F:pci/hda/hda_codec.c:1.1->1.2 
#   F:pci/hda/hda_codec.h:1.1->1.2 
#   F:pci/hda/hda_intel.c:1.2->1.3 
#   F:pci/nm256/nm256.c:1.58->1.59 
#   F:pci/trident/trident_main.c:1.69->1.70 
#   F:pci/ymfpci/ymfpci_main.c:1.64->1.65 
#   F:pcmcia/pdaudiocf/pdaudiocf.c:1.11->1.12 
#   F:pcmcia/pdaudiocf/pdaudiocf.h:1.7->1.8 
#   F:pcmcia/pdaudiocf/pdaudiocf_core.c:1.6->1.7 
#   F:pcmcia/vx/vx_entry.c:1.8->1.9 
#   F:ppc/pmac.c:1.43->1.44 
#   L:Fixes by Pavel Machek <pavel@suse.cz>:
#   L:suspend() routines no longer get u32 as their parameter (they get
#   L:pm_message_t, which is u32 for now, but will change in 2.6.12 or
#   L:so). This fixes ALSA to notice this, and uses constants with right
#   L:types where appropriate. It results in no code changes. [Best results
#   L:will be when patching against latest -mm, you may get some warnings if
#   L:you patch it into older kernel, but it should still do the right
#   L:thing.] Please apply,
#   L:							Pavel
#   L:
#   L:[In addition, suspend callback type is changed to follow to the standard
#   L: style taking no state argument -- Takashi]
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pcmcia/vx/vx_entry.c
#   2005/01/28 12:34:08+01:00 perex@suse.cz +2 -2
#   [ALSA] driver model type fixes for ALSA
#   
#   D:2005/01/28 19:34:04
#   C:SA11xx UDA1341 driver,Control Midlevel,ALSA Core,Digigram VX core
#   C:ES18xx driver,OPL3SA2 driver,AD1848 driver,CS4231 driver,ATIIXP driver
#   C:ATIIXP-modem driver,CS4281 driver,ES1938 driver,ES1968 driver
#   C:Intel8x0 driver,Intel8x0-modem driver,Maestro3 driver,VIA82xx driver
#   C:VIA82xx-modem driver,ALI5451 driver,CS46xx driver,HDA Codec driver
#   C:HDA Intel driver,NM256 driver,Trident driver,YMFPCI driver
#   C:PDAudioCF driver,Digigram VX Pocket driver,PPC PMAC driver
#   F:arm/sa11xx-uda1341.c:1.20->1.21 
#   F:core/control.c:1.56->1.57 
#   F:core/init.c:1.58->1.59 
#   F:drivers/vx/vx_core.c:1.14->1.15 
#   F:include/core.h:1.65->1.66 
#   F:isa/es18xx.c:1.53->1.54 
#   F:isa/opl3sa2.c:1.42->1.43 
#   F:isa/ad1848/ad1848_lib.c:1.39->1.40 
#   F:isa/cs423x/cs4231_lib.c:1.47->1.48 
#   F:pci/atiixp.c:1.31->1.32 
#   F:pci/atiixp_modem.c:1.14->1.15 
#   F:pci/cs4281.c:1.69->1.70 
#   F:pci/es1938.c:1.45->1.46 
#   F:pci/es1968.c:1.82->1.83 
#   F:pci/intel8x0.c:1.190->1.191 
#   F:pci/intel8x0m.c:1.26->1.27 
#   F:pci/maestro3.c:1.68->1.69 
#   F:pci/via82xx.c:1.135->1.136 
#   F:pci/via82xx_modem.c:1.4->1.5 
#   F:pci/ali5451/ali5451.c:1.60->1.61 
#   F:pci/cs46xx/cs46xx_lib.c:1.93->1.94 
#   F:pci/hda/hda_codec.c:1.1->1.2 
#   F:pci/hda/hda_codec.h:1.1->1.2 
#   F:pci/hda/hda_intel.c:1.2->1.3 
#   F:pci/nm256/nm256.c:1.58->1.59 
#   F:pci/trident/trident_main.c:1.69->1.70 
#   F:pci/ymfpci/ymfpci_main.c:1.64->1.65 
#   F:pcmcia/pdaudiocf/pdaudiocf.c:1.11->1.12 
#   F:pcmcia/pdaudiocf/pdaudiocf.h:1.7->1.8 
#   F:pcmcia/pdaudiocf/pdaudiocf_core.c:1.6->1.7 
#   F:pcmcia/vx/vx_entry.c:1.8->1.9 
#   F:ppc/pmac.c:1.43->1.44 
#   L:Fixes by Pavel Machek <pavel@suse.cz>:
#   L:suspend() routines no longer get u32 as their parameter (they get
#   L:pm_message_t, which is u32 for now, but will change in 2.6.12 or
#   L:so). This fixes ALSA to notice this, and uses constants with right
#   L:types where appropriate. It results in no code changes. [Best results
#   L:will be when patching against latest -mm, you may get some warnings if
#   L:you patch it into older kernel, but it should still do the right
#   L:thing.] Please apply,
#   L:							Pavel
#   L:
#   L:[In addition, suspend callback type is changed to follow to the standard
#   L: style taking no state argument -- Takashi]
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pcmcia/pdaudiocf/pdaudiocf_core.c
#   2005/01/28 12:34:08+01:00 perex@suse.cz +2 -2
#   [ALSA] driver model type fixes for ALSA
#   
#   D:2005/01/28 19:34:04
#   C:SA11xx UDA1341 driver,Control Midlevel,ALSA Core,Digigram VX core
#   C:ES18xx driver,OPL3SA2 driver,AD1848 driver,CS4231 driver,ATIIXP driver
#   C:ATIIXP-modem driver,CS4281 driver,ES1938 driver,ES1968 driver
#   C:Intel8x0 driver,Intel8x0-modem driver,Maestro3 driver,VIA82xx driver
#   C:VIA82xx-modem driver,ALI5451 driver,CS46xx driver,HDA Codec driver
#   C:HDA Intel driver,NM256 driver,Trident driver,YMFPCI driver
#   C:PDAudioCF driver,Digigram VX Pocket driver,PPC PMAC driver
#   F:arm/sa11xx-uda1341.c:1.20->1.21 
#   F:core/control.c:1.56->1.57 
#   F:core/init.c:1.58->1.59 
#   F:drivers/vx/vx_core.c:1.14->1.15 
#   F:include/core.h:1.65->1.66 
#   F:isa/es18xx.c:1.53->1.54 
#   F:isa/opl3sa2.c:1.42->1.43 
#   F:isa/ad1848/ad1848_lib.c:1.39->1.40 
#   F:isa/cs423x/cs4231_lib.c:1.47->1.48 
#   F:pci/atiixp.c:1.31->1.32 
#   F:pci/atiixp_modem.c:1.14->1.15 
#   F:pci/cs4281.c:1.69->1.70 
#   F:pci/es1938.c:1.45->1.46 
#   F:pci/es1968.c:1.82->1.83 
#   F:pci/intel8x0.c:1.190->1.191 
#   F:pci/intel8x0m.c:1.26->1.27 
#   F:pci/maestro3.c:1.68->1.69 
#   F:pci/via82xx.c:1.135->1.136 
#   F:pci/via82xx_modem.c:1.4->1.5 
#   F:pci/ali5451/ali5451.c:1.60->1.61 
#   F:pci/cs46xx/cs46xx_lib.c:1.93->1.94 
#   F:pci/hda/hda_codec.c:1.1->1.2 
#   F:pci/hda/hda_codec.h:1.1->1.2 
#   F:pci/hda/hda_intel.c:1.2->1.3 
#   F:pci/nm256/nm256.c:1.58->1.59 
#   F:pci/trident/trident_main.c:1.69->1.70 
#   F:pci/ymfpci/ymfpci_main.c:1.64->1.65 
#   F:pcmcia/pdaudiocf/pdaudiocf.c:1.11->1.12 
#   F:pcmcia/pdaudiocf/pdaudiocf.h:1.7->1.8 
#   F:pcmcia/pdaudiocf/pdaudiocf_core.c:1.6->1.7 
#   F:pcmcia/vx/vx_entry.c:1.8->1.9 
#   F:ppc/pmac.c:1.43->1.44 
#   L:Fixes by Pavel Machek <pavel@suse.cz>:
#   L:suspend() routines no longer get u32 as their parameter (they get
#   L:pm_message_t, which is u32 for now, but will change in 2.6.12 or
#   L:so). This fixes ALSA to notice this, and uses constants with right
#   L:types where appropriate. It results in no code changes. [Best results
#   L:will be when patching against latest -mm, you may get some warnings if
#   L:you patch it into older kernel, but it should still do the right
#   L:thing.] Please apply,
#   L:							Pavel
#   L:
#   L:[In addition, suspend callback type is changed to follow to the standard
#   L: style taking no state argument -- Takashi]
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pcmcia/pdaudiocf/pdaudiocf.h
#   2005/01/28 12:34:08+01:00 perex@suse.cz +2 -2
#   [ALSA] driver model type fixes for ALSA
#   
#   D:2005/01/28 19:34:04
#   C:SA11xx UDA1341 driver,Control Midlevel,ALSA Core,Digigram VX core
#   C:ES18xx driver,OPL3SA2 driver,AD1848 driver,CS4231 driver,ATIIXP driver
#   C:ATIIXP-modem driver,CS4281 driver,ES1938 driver,ES1968 driver
#   C:Intel8x0 driver,Intel8x0-modem driver,Maestro3 driver,VIA82xx driver
#   C:VIA82xx-modem driver,ALI5451 driver,CS46xx driver,HDA Codec driver
#   C:HDA Intel driver,NM256 driver,Trident driver,YMFPCI driver
#   C:PDAudioCF driver,Digigram VX Pocket driver,PPC PMAC driver
#   F:arm/sa11xx-uda1341.c:1.20->1.21 
#   F:core/control.c:1.56->1.57 
#   F:core/init.c:1.58->1.59 
#   F:drivers/vx/vx_core.c:1.14->1.15 
#   F:include/core.h:1.65->1.66 
#   F:isa/es18xx.c:1.53->1.54 
#   F:isa/opl3sa2.c:1.42->1.43 
#   F:isa/ad1848/ad1848_lib.c:1.39->1.40 
#   F:isa/cs423x/cs4231_lib.c:1.47->1.48 
#   F:pci/atiixp.c:1.31->1.32 
#   F:pci/atiixp_modem.c:1.14->1.15 
#   F:pci/cs4281.c:1.69->1.70 
#   F:pci/es1938.c:1.45->1.46 
#   F:pci/es1968.c:1.82->1.83 
#   F:pci/intel8x0.c:1.190->1.191 
#   F:pci/intel8x0m.c:1.26->1.27 
#   F:pci/maestro3.c:1.68->1.69 
#   F:pci/via82xx.c:1.135->1.136 
#   F:pci/via82xx_modem.c:1.4->1.5 
#   F:pci/ali5451/ali5451.c:1.60->1.61 
#   F:pci/cs46xx/cs46xx_lib.c:1.93->1.94 
#   F:pci/hda/hda_codec.c:1.1->1.2 
#   F:pci/hda/hda_codec.h:1.1->1.2 
#   F:pci/hda/hda_intel.c:1.2->1.3 
#   F:pci/nm256/nm256.c:1.58->1.59 
#   F:pci/trident/trident_main.c:1.69->1.70 
#   F:pci/ymfpci/ymfpci_main.c:1.64->1.65 
#   F:pcmcia/pdaudiocf/pdaudiocf.c:1.11->1.12 
#   F:pcmcia/pdaudiocf/pdaudiocf.h:1.7->1.8 
#   F:pcmcia/pdaudiocf/pdaudiocf_core.c:1.6->1.7 
#   F:pcmcia/vx/vx_entry.c:1.8->1.9 
#   F:ppc/pmac.c:1.43->1.44 
#   L:Fixes by Pavel Machek <pavel@suse.cz>:
#   L:suspend() routines no longer get u32 as their parameter (they get
#   L:pm_message_t, which is u32 for now, but will change in 2.6.12 or
#   L:so). This fixes ALSA to notice this, and uses constants with right
#   L:types where appropriate. It results in no code changes. [Best results
#   L:will be when patching against latest -mm, you may get some warnings if
#   L:you patch it into older kernel, but it should still do the right
#   L:thing.] Please apply,
#   L:							Pavel
#   L:
#   L:[In addition, suspend callback type is changed to follow to the standard
#   L: style taking no state argument -- Takashi]
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pcmcia/pdaudiocf/pdaudiocf.c
#   2005/01/28 12:34:08+01:00 perex@suse.cz +2 -2
#   [ALSA] driver model type fixes for ALSA
#   
#   D:2005/01/28 19:34:04
#   C:SA11xx UDA1341 driver,Control Midlevel,ALSA Core,Digigram VX core
#   C:ES18xx driver,OPL3SA2 driver,AD1848 driver,CS4231 driver,ATIIXP driver
#   C:ATIIXP-modem driver,CS4281 driver,ES1938 driver,ES1968 driver
#   C:Intel8x0 driver,Intel8x0-modem driver,Maestro3 driver,VIA82xx driver
#   C:VIA82xx-modem driver,ALI5451 driver,CS46xx driver,HDA Codec driver
#   C:HDA Intel driver,NM256 driver,Trident driver,YMFPCI driver
#   C:PDAudioCF driver,Digigram VX Pocket driver,PPC PMAC driver
#   F:arm/sa11xx-uda1341.c:1.20->1.21 
#   F:core/control.c:1.56->1.57 
#   F:core/init.c:1.58->1.59 
#   F:drivers/vx/vx_core.c:1.14->1.15 
#   F:include/core.h:1.65->1.66 
#   F:isa/es18xx.c:1.53->1.54 
#   F:isa/opl3sa2.c:1.42->1.43 
#   F:isa/ad1848/ad1848_lib.c:1.39->1.40 
#   F:isa/cs423x/cs4231_lib.c:1.47->1.48 
#   F:pci/atiixp.c:1.31->1.32 
#   F:pci/atiixp_modem.c:1.14->1.15 
#   F:pci/cs4281.c:1.69->1.70 
#   F:pci/es1938.c:1.45->1.46 
#   F:pci/es1968.c:1.82->1.83 
#   F:pci/intel8x0.c:1.190->1.191 
#   F:pci/intel8x0m.c:1.26->1.27 
#   F:pci/maestro3.c:1.68->1.69 
#   F:pci/via82xx.c:1.135->1.136 
#   F:pci/via82xx_modem.c:1.4->1.5 
#   F:pci/ali5451/ali5451.c:1.60->1.61 
#   F:pci/cs46xx/cs46xx_lib.c:1.93->1.94 
#   F:pci/hda/hda_codec.c:1.1->1.2 
#   F:pci/hda/hda_codec.h:1.1->1.2 
#   F:pci/hda/hda_intel.c:1.2->1.3 
#   F:pci/nm256/nm256.c:1.58->1.59 
#   F:pci/trident/trident_main.c:1.69->1.70 
#   F:pci/ymfpci/ymfpci_main.c:1.64->1.65 
#   F:pcmcia/pdaudiocf/pdaudiocf.c:1.11->1.12 
#   F:pcmcia/pdaudiocf/pdaudiocf.h:1.7->1.8 
#   F:pcmcia/pdaudiocf/pdaudiocf_core.c:1.6->1.7 
#   F:pcmcia/vx/vx_entry.c:1.8->1.9 
#   F:ppc/pmac.c:1.43->1.44 
#   L:Fixes by Pavel Machek <pavel@suse.cz>:
#   L:suspend() routines no longer get u32 as their parameter (they get
#   L:pm_message_t, which is u32 for now, but will change in 2.6.12 or
#   L:so). This fixes ALSA to notice this, and uses constants with right
#   L:types where appropriate. It results in no code changes. [Best results
#   L:will be when patching against latest -mm, you may get some warnings if
#   L:you patch it into older kernel, but it should still do the right
#   L:thing.] Please apply,
#   L:							Pavel
#   L:
#   L:[In addition, suspend callback type is changed to follow to the standard
#   L: style taking no state argument -- Takashi]
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/ymfpci/ymfpci_main.c
#   2005/01/28 12:34:08+01:00 perex@suse.cz +2 -2
#   [ALSA] driver model type fixes for ALSA
#   
#   D:2005/01/28 19:34:04
#   C:SA11xx UDA1341 driver,Control Midlevel,ALSA Core,Digigram VX core
#   C:ES18xx driver,OPL3SA2 driver,AD1848 driver,CS4231 driver,ATIIXP driver
#   C:ATIIXP-modem driver,CS4281 driver,ES1938 driver,ES1968 driver
#   C:Intel8x0 driver,Intel8x0-modem driver,Maestro3 driver,VIA82xx driver
#   C:VIA82xx-modem driver,ALI5451 driver,CS46xx driver,HDA Codec driver
#   C:HDA Intel driver,NM256 driver,Trident driver,YMFPCI driver
#   C:PDAudioCF driver,Digigram VX Pocket driver,PPC PMAC driver
#   F:arm/sa11xx-uda1341.c:1.20->1.21 
#   F:core/control.c:1.56->1.57 
#   F:core/init.c:1.58->1.59 
#   F:drivers/vx/vx_core.c:1.14->1.15 
#   F:include/core.h:1.65->1.66 
#   F:isa/es18xx.c:1.53->1.54 
#   F:isa/opl3sa2.c:1.42->1.43 
#   F:isa/ad1848/ad1848_lib.c:1.39->1.40 
#   F:isa/cs423x/cs4231_lib.c:1.47->1.48 
#   F:pci/atiixp.c:1.31->1.32 
#   F:pci/atiixp_modem.c:1.14->1.15 
#   F:pci/cs4281.c:1.69->1.70 
#   F:pci/es1938.c:1.45->1.46 
#   F:pci/es1968.c:1.82->1.83 
#   F:pci/intel8x0.c:1.190->1.191 
#   F:pci/intel8x0m.c:1.26->1.27 
#   F:pci/maestro3.c:1.68->1.69 
#   F:pci/via82xx.c:1.135->1.136 
#   F:pci/via82xx_modem.c:1.4->1.5 
#   F:pci/ali5451/ali5451.c:1.60->1.61 
#   F:pci/cs46xx/cs46xx_lib.c:1.93->1.94 
#   F:pci/hda/hda_codec.c:1.1->1.2 
#   F:pci/hda/hda_codec.h:1.1->1.2 
#   F:pci/hda/hda_intel.c:1.2->1.3 
#   F:pci/nm256/nm256.c:1.58->1.59 
#   F:pci/trident/trident_main.c:1.69->1.70 
#   F:pci/ymfpci/ymfpci_main.c:1.64->1.65 
#   F:pcmcia/pdaudiocf/pdaudiocf.c:1.11->1.12 
#   F:pcmcia/pdaudiocf/pdaudiocf.h:1.7->1.8 
#   F:pcmcia/pdaudiocf/pdaudiocf_core.c:1.6->1.7 
#   F:pcmcia/vx/vx_entry.c:1.8->1.9 
#   F:ppc/pmac.c:1.43->1.44 
#   L:Fixes by Pavel Machek <pavel@suse.cz>:
#   L:suspend() routines no longer get u32 as their parameter (they get
#   L:pm_message_t, which is u32 for now, but will change in 2.6.12 or
#   L:so). This fixes ALSA to notice this, and uses constants with right
#   L:types where appropriate. It results in no code changes. [Best results
#   L:will be when patching against latest -mm, you may get some warnings if
#   L:you patch it into older kernel, but it should still do the right
#   L:thing.] Please apply,
#   L:							Pavel
#   L:
#   L:[In addition, suspend callback type is changed to follow to the standard
#   L: style taking no state argument -- Takashi]
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/via82xx_modem.c
#   2005/01/28 12:34:07+01:00 perex@suse.cz +2 -2
#   [ALSA] driver model type fixes for ALSA
#   
#   D:2005/01/28 19:34:04
#   C:SA11xx UDA1341 driver,Control Midlevel,ALSA Core,Digigram VX core
#   C:ES18xx driver,OPL3SA2 driver,AD1848 driver,CS4231 driver,ATIIXP driver
#   C:ATIIXP-modem driver,CS4281 driver,ES1938 driver,ES1968 driver
#   C:Intel8x0 driver,Intel8x0-modem driver,Maestro3 driver,VIA82xx driver
#   C:VIA82xx-modem driver,ALI5451 driver,CS46xx driver,HDA Codec driver
#   C:HDA Intel driver,NM256 driver,Trident driver,YMFPCI driver
#   C:PDAudioCF driver,Digigram VX Pocket driver,PPC PMAC driver
#   F:arm/sa11xx-uda1341.c:1.20->1.21 
#   F:core/control.c:1.56->1.57 
#   F:core/init.c:1.58->1.59 
#   F:drivers/vx/vx_core.c:1.14->1.15 
#   F:include/core.h:1.65->1.66 
#   F:isa/es18xx.c:1.53->1.54 
#   F:isa/opl3sa2.c:1.42->1.43 
#   F:isa/ad1848/ad1848_lib.c:1.39->1.40 
#   F:isa/cs423x/cs4231_lib.c:1.47->1.48 
#   F:pci/atiixp.c:1.31->1.32 
#   F:pci/atiixp_modem.c:1.14->1.15 
#   F:pci/cs4281.c:1.69->1.70 
#   F:pci/es1938.c:1.45->1.46 
#   F:pci/es1968.c:1.82->1.83 
#   F:pci/intel8x0.c:1.190->1.191 
#   F:pci/intel8x0m.c:1.26->1.27 
#   F:pci/maestro3.c:1.68->1.69 
#   F:pci/via82xx.c:1.135->1.136 
#   F:pci/via82xx_modem.c:1.4->1.5 
#   F:pci/ali5451/ali5451.c:1.60->1.61 
#   F:pci/cs46xx/cs46xx_lib.c:1.93->1.94 
#   F:pci/hda/hda_codec.c:1.1->1.2 
#   F:pci/hda/hda_codec.h:1.1->1.2 
#   F:pci/hda/hda_intel.c:1.2->1.3 
#   F:pci/nm256/nm256.c:1.58->1.59 
#   F:pci/trident/trident_main.c:1.69->1.70 
#   F:pci/ymfpci/ymfpci_main.c:1.64->1.65 
#   F:pcmcia/pdaudiocf/pdaudiocf.c:1.11->1.12 
#   F:pcmcia/pdaudiocf/pdaudiocf.h:1.7->1.8 
#   F:pcmcia/pdaudiocf/pdaudiocf_core.c:1.6->1.7 
#   F:pcmcia/vx/vx_entry.c:1.8->1.9 
#   F:ppc/pmac.c:1.43->1.44 
#   L:Fixes by Pavel Machek <pavel@suse.cz>:
#   L:suspend() routines no longer get u32 as their parameter (they get
#   L:pm_message_t, which is u32 for now, but will change in 2.6.12 or
#   L:so). This fixes ALSA to notice this, and uses constants with right
#   L:types where appropriate. It results in no code changes. [Best results
#   L:will be when patching against latest -mm, you may get some warnings if
#   L:you patch it into older kernel, but it should still do the right
#   L:thing.] Please apply,
#   L:							Pavel
#   L:
#   L:[In addition, suspend callback type is changed to follow to the standard
#   L: style taking no state argument -- Takashi]
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/via82xx.c
#   2005/01/28 12:34:06+01:00 perex@suse.cz +2 -2
#   [ALSA] driver model type fixes for ALSA
#   
#   D:2005/01/28 19:34:04
#   C:SA11xx UDA1341 driver,Control Midlevel,ALSA Core,Digigram VX core
#   C:ES18xx driver,OPL3SA2 driver,AD1848 driver,CS4231 driver,ATIIXP driver
#   C:ATIIXP-modem driver,CS4281 driver,ES1938 driver,ES1968 driver
#   C:Intel8x0 driver,Intel8x0-modem driver,Maestro3 driver,VIA82xx driver
#   C:VIA82xx-modem driver,ALI5451 driver,CS46xx driver,HDA Codec driver
#   C:HDA Intel driver,NM256 driver,Trident driver,YMFPCI driver
#   C:PDAudioCF driver,Digigram VX Pocket driver,PPC PMAC driver
#   F:arm/sa11xx-uda1341.c:1.20->1.21 
#   F:core/control.c:1.56->1.57 
#   F:core/init.c:1.58->1.59 
#   F:drivers/vx/vx_core.c:1.14->1.15 
#   F:include/core.h:1.65->1.66 
#   F:isa/es18xx.c:1.53->1.54 
#   F:isa/opl3sa2.c:1.42->1.43 
#   F:isa/ad1848/ad1848_lib.c:1.39->1.40 
#   F:isa/cs423x/cs4231_lib.c:1.47->1.48 
#   F:pci/atiixp.c:1.31->1.32 
#   F:pci/atiixp_modem.c:1.14->1.15 
#   F:pci/cs4281.c:1.69->1.70 
#   F:pci/es1938.c:1.45->1.46 
#   F:pci/es1968.c:1.82->1.83 
#   F:pci/intel8x0.c:1.190->1.191 
#   F:pci/intel8x0m.c:1.26->1.27 
#   F:pci/maestro3.c:1.68->1.69 
#   F:pci/via82xx.c:1.135->1.136 
#   F:pci/via82xx_modem.c:1.4->1.5 
#   F:pci/ali5451/ali5451.c:1.60->1.61 
#   F:pci/cs46xx/cs46xx_lib.c:1.93->1.94 
#   F:pci/hda/hda_codec.c:1.1->1.2 
#   F:pci/hda/hda_codec.h:1.1->1.2 
#   F:pci/hda/hda_intel.c:1.2->1.3 
#   F:pci/nm256/nm256.c:1.58->1.59 
#   F:pci/trident/trident_main.c:1.69->1.70 
#   F:pci/ymfpci/ymfpci_main.c:1.64->1.65 
#   F:pcmcia/pdaudiocf/pdaudiocf.c:1.11->1.12 
#   F:pcmcia/pdaudiocf/pdaudiocf.h:1.7->1.8 
#   F:pcmcia/pdaudiocf/pdaudiocf_core.c:1.6->1.7 
#   F:pcmcia/vx/vx_entry.c:1.8->1.9 
#   F:ppc/pmac.c:1.43->1.44 
#   L:Fixes by Pavel Machek <pavel@suse.cz>:
#   L:suspend() routines no longer get u32 as their parameter (they get
#   L:pm_message_t, which is u32 for now, but will change in 2.6.12 or
#   L:so). This fixes ALSA to notice this, and uses constants with right
#   L:types where appropriate. It results in no code changes. [Best results
#   L:will be when patching against latest -mm, you may get some warnings if
#   L:you patch it into older kernel, but it should still do the right
#   L:thing.] Please apply,
#   L:							Pavel
#   L:
#   L:[In addition, suspend callback type is changed to follow to the standard
#   L: style taking no state argument -- Takashi]
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/trident/trident_main.c
#   2005/01/28 12:34:08+01:00 perex@suse.cz +4 -4
#   [ALSA] driver model type fixes for ALSA
#   
#   D:2005/01/28 19:34:04
#   C:SA11xx UDA1341 driver,Control Midlevel,ALSA Core,Digigram VX core
#   C:ES18xx driver,OPL3SA2 driver,AD1848 driver,CS4231 driver,ATIIXP driver
#   C:ATIIXP-modem driver,CS4281 driver,ES1938 driver,ES1968 driver
#   C:Intel8x0 driver,Intel8x0-modem driver,Maestro3 driver,VIA82xx driver
#   C:VIA82xx-modem driver,ALI5451 driver,CS46xx driver,HDA Codec driver
#   C:HDA Intel driver,NM256 driver,Trident driver,YMFPCI driver
#   C:PDAudioCF driver,Digigram VX Pocket driver,PPC PMAC driver
#   F:arm/sa11xx-uda1341.c:1.20->1.21 
#   F:core/control.c:1.56->1.57 
#   F:core/init.c:1.58->1.59 
#   F:drivers/vx/vx_core.c:1.14->1.15 
#   F:include/core.h:1.65->1.66 
#   F:isa/es18xx.c:1.53->1.54 
#   F:isa/opl3sa2.c:1.42->1.43 
#   F:isa/ad1848/ad1848_lib.c:1.39->1.40 
#   F:isa/cs423x/cs4231_lib.c:1.47->1.48 
#   F:pci/atiixp.c:1.31->1.32 
#   F:pci/atiixp_modem.c:1.14->1.15 
#   F:pci/cs4281.c:1.69->1.70 
#   F:pci/es1938.c:1.45->1.46 
#   F:pci/es1968.c:1.82->1.83 
#   F:pci/intel8x0.c:1.190->1.191 
#   F:pci/intel8x0m.c:1.26->1.27 
#   F:pci/maestro3.c:1.68->1.69 
#   F:pci/via82xx.c:1.135->1.136 
#   F:pci/via82xx_modem.c:1.4->1.5 
#   F:pci/ali5451/ali5451.c:1.60->1.61 
#   F:pci/cs46xx/cs46xx_lib.c:1.93->1.94 
#   F:pci/hda/hda_codec.c:1.1->1.2 
#   F:pci/hda/hda_codec.h:1.1->1.2 
#   F:pci/hda/hda_intel.c:1.2->1.3 
#   F:pci/nm256/nm256.c:1.58->1.59 
#   F:pci/trident/trident_main.c:1.69->1.70 
#   F:pci/ymfpci/ymfpci_main.c:1.64->1.65 
#   F:pcmcia/pdaudiocf/pdaudiocf.c:1.11->1.12 
#   F:pcmcia/pdaudiocf/pdaudiocf.h:1.7->1.8 
#   F:pcmcia/pdaudiocf/pdaudiocf_core.c:1.6->1.7 
#   F:pcmcia/vx/vx_entry.c:1.8->1.9 
#   F:ppc/pmac.c:1.43->1.44 
#   L:Fixes by Pavel Machek <pavel@suse.cz>:
#   L:suspend() routines no longer get u32 as their parameter (they get
#   L:pm_message_t, which is u32 for now, but will change in 2.6.12 or
#   L:so). This fixes ALSA to notice this, and uses constants with right
#   L:types where appropriate. It results in no code changes. [Best results
#   L:will be when patching against latest -mm, you may get some warnings if
#   L:you patch it into older kernel, but it should still do the right
#   L:thing.] Please apply,
#   L:							Pavel
#   L:
#   L:[In addition, suspend callback type is changed to follow to the standard
#   L: style taking no state argument -- Takashi]
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/nm256/nm256.c
#   2005/01/28 12:34:07+01:00 perex@suse.cz +2 -2
#   [ALSA] driver model type fixes for ALSA
#   
#   D:2005/01/28 19:34:04
#   C:SA11xx UDA1341 driver,Control Midlevel,ALSA Core,Digigram VX core
#   C:ES18xx driver,OPL3SA2 driver,AD1848 driver,CS4231 driver,ATIIXP driver
#   C:ATIIXP-modem driver,CS4281 driver,ES1938 driver,ES1968 driver
#   C:Intel8x0 driver,Intel8x0-modem driver,Maestro3 driver,VIA82xx driver
#   C:VIA82xx-modem driver,ALI5451 driver,CS46xx driver,HDA Codec driver
#   C:HDA Intel driver,NM256 driver,Trident driver,YMFPCI driver
#   C:PDAudioCF driver,Digigram VX Pocket driver,PPC PMAC driver
#   F:arm/sa11xx-uda1341.c:1.20->1.21 
#   F:core/control.c:1.56->1.57 
#   F:core/init.c:1.58->1.59 
#   F:drivers/vx/vx_core.c:1.14->1.15 
#   F:include/core.h:1.65->1.66 
#   F:isa/es18xx.c:1.53->1.54 
#   F:isa/opl3sa2.c:1.42->1.43 
#   F:isa/ad1848/ad1848_lib.c:1.39->1.40 
#   F:isa/cs423x/cs4231_lib.c:1.47->1.48 
#   F:pci/atiixp.c:1.31->1.32 
#   F:pci/atiixp_modem.c:1.14->1.15 
#   F:pci/cs4281.c:1.69->1.70 
#   F:pci/es1938.c:1.45->1.46 
#   F:pci/es1968.c:1.82->1.83 
#   F:pci/intel8x0.c:1.190->1.191 
#   F:pci/intel8x0m.c:1.26->1.27 
#   F:pci/maestro3.c:1.68->1.69 
#   F:pci/via82xx.c:1.135->1.136 
#   F:pci/via82xx_modem.c:1.4->1.5 
#   F:pci/ali5451/ali5451.c:1.60->1.61 
#   F:pci/cs46xx/cs46xx_lib.c:1.93->1.94 
#   F:pci/hda/hda_codec.c:1.1->1.2 
#   F:pci/hda/hda_codec.h:1.1->1.2 
#   F:pci/hda/hda_intel.c:1.2->1.3 
#   F:pci/nm256/nm256.c:1.58->1.59 
#   F:pci/trident/trident_main.c:1.69->1.70 
#   F:pci/ymfpci/ymfpci_main.c:1.64->1.65 
#   F:pcmcia/pdaudiocf/pdaudiocf.c:1.11->1.12 
#   F:pcmcia/pdaudiocf/pdaudiocf.h:1.7->1.8 
#   F:pcmcia/pdaudiocf/pdaudiocf_core.c:1.6->1.7 
#   F:pcmcia/vx/vx_entry.c:1.8->1.9 
#   F:ppc/pmac.c:1.43->1.44 
#   L:Fixes by Pavel Machek <pavel@suse.cz>:
#   L:suspend() routines no longer get u32 as their parameter (they get
#   L:pm_message_t, which is u32 for now, but will change in 2.6.12 or
#   L:so). This fixes ALSA to notice this, and uses constants with right
#   L:types where appropriate. It results in no code changes. [Best results
#   L:will be when patching against latest -mm, you may get some warnings if
#   L:you patch it into older kernel, but it should still do the right
#   L:thing.] Please apply,
#   L:							Pavel
#   L:
#   L:[In addition, suspend callback type is changed to follow to the standard
#   L: style taking no state argument -- Takashi]
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/maestro3.c
#   2005/01/28 12:34:06+01:00 perex@suse.cz +2 -2
#   [ALSA] driver model type fixes for ALSA
#   
#   D:2005/01/28 19:34:04
#   C:SA11xx UDA1341 driver,Control Midlevel,ALSA Core,Digigram VX core
#   C:ES18xx driver,OPL3SA2 driver,AD1848 driver,CS4231 driver,ATIIXP driver
#   C:ATIIXP-modem driver,CS4281 driver,ES1938 driver,ES1968 driver
#   C:Intel8x0 driver,Intel8x0-modem driver,Maestro3 driver,VIA82xx driver
#   C:VIA82xx-modem driver,ALI5451 driver,CS46xx driver,HDA Codec driver
#   C:HDA Intel driver,NM256 driver,Trident driver,YMFPCI driver
#   C:PDAudioCF driver,Digigram VX Pocket driver,PPC PMAC driver
#   F:arm/sa11xx-uda1341.c:1.20->1.21 
#   F:core/control.c:1.56->1.57 
#   F:core/init.c:1.58->1.59 
#   F:drivers/vx/vx_core.c:1.14->1.15 
#   F:include/core.h:1.65->1.66 
#   F:isa/es18xx.c:1.53->1.54 
#   F:isa/opl3sa2.c:1.42->1.43 
#   F:isa/ad1848/ad1848_lib.c:1.39->1.40 
#   F:isa/cs423x/cs4231_lib.c:1.47->1.48 
#   F:pci/atiixp.c:1.31->1.32 
#   F:pci/atiixp_modem.c:1.14->1.15 
#   F:pci/cs4281.c:1.69->1.70 
#   F:pci/es1938.c:1.45->1.46 
#   F:pci/es1968.c:1.82->1.83 
#   F:pci/intel8x0.c:1.190->1.191 
#   F:pci/intel8x0m.c:1.26->1.27 
#   F:pci/maestro3.c:1.68->1.69 
#   F:pci/via82xx.c:1.135->1.136 
#   F:pci/via82xx_modem.c:1.4->1.5 
#   F:pci/ali5451/ali5451.c:1.60->1.61 
#   F:pci/cs46xx/cs46xx_lib.c:1.93->1.94 
#   F:pci/hda/hda_codec.c:1.1->1.2 
#   F:pci/hda/hda_codec.h:1.1->1.2 
#   F:pci/hda/hda_intel.c:1.2->1.3 
#   F:pci/nm256/nm256.c:1.58->1.59 
#   F:pci/trident/trident_main.c:1.69->1.70 
#   F:pci/ymfpci/ymfpci_main.c:1.64->1.65 
#   F:pcmcia/pdaudiocf/pdaudiocf.c:1.11->1.12 
#   F:pcmcia/pdaudiocf/pdaudiocf.h:1.7->1.8 
#   F:pcmcia/pdaudiocf/pdaudiocf_core.c:1.6->1.7 
#   F:pcmcia/vx/vx_entry.c:1.8->1.9 
#   F:ppc/pmac.c:1.43->1.44 
#   L:Fixes by Pavel Machek <pavel@suse.cz>:
#   L:suspend() routines no longer get u32 as their parameter (they get
#   L:pm_message_t, which is u32 for now, but will change in 2.6.12 or
#   L:so). This fixes ALSA to notice this, and uses constants with right
#   L:types where appropriate. It results in no code changes. [Best results
#   L:will be when patching against latest -mm, you may get some warnings if
#   L:you patch it into older kernel, but it should still do the right
#   L:thing.] Please apply,
#   L:							Pavel
#   L:
#   L:[In addition, suspend callback type is changed to follow to the standard
#   L: style taking no state argument -- Takashi]
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/intel8x0m.c
#   2005/01/28 12:34:06+01:00 perex@suse.cz +2 -2
#   [ALSA] driver model type fixes for ALSA
#   
#   D:2005/01/28 19:34:04
#   C:SA11xx UDA1341 driver,Control Midlevel,ALSA Core,Digigram VX core
#   C:ES18xx driver,OPL3SA2 driver,AD1848 driver,CS4231 driver,ATIIXP driver
#   C:ATIIXP-modem driver,CS4281 driver,ES1938 driver,ES1968 driver
#   C:Intel8x0 driver,Intel8x0-modem driver,Maestro3 driver,VIA82xx driver
#   C:VIA82xx-modem driver,ALI5451 driver,CS46xx driver,HDA Codec driver
#   C:HDA Intel driver,NM256 driver,Trident driver,YMFPCI driver
#   C:PDAudioCF driver,Digigram VX Pocket driver,PPC PMAC driver
#   F:arm/sa11xx-uda1341.c:1.20->1.21 
#   F:core/control.c:1.56->1.57 
#   F:core/init.c:1.58->1.59 
#   F:drivers/vx/vx_core.c:1.14->1.15 
#   F:include/core.h:1.65->1.66 
#   F:isa/es18xx.c:1.53->1.54 
#   F:isa/opl3sa2.c:1.42->1.43 
#   F:isa/ad1848/ad1848_lib.c:1.39->1.40 
#   F:isa/cs423x/cs4231_lib.c:1.47->1.48 
#   F:pci/atiixp.c:1.31->1.32 
#   F:pci/atiixp_modem.c:1.14->1.15 
#   F:pci/cs4281.c:1.69->1.70 
#   F:pci/es1938.c:1.45->1.46 
#   F:pci/es1968.c:1.82->1.83 
#   F:pci/intel8x0.c:1.190->1.191 
#   F:pci/intel8x0m.c:1.26->1.27 
#   F:pci/maestro3.c:1.68->1.69 
#   F:pci/via82xx.c:1.135->1.136 
#   F:pci/via82xx_modem.c:1.4->1.5 
#   F:pci/ali5451/ali5451.c:1.60->1.61 
#   F:pci/cs46xx/cs46xx_lib.c:1.93->1.94 
#   F:pci/hda/hda_codec.c:1.1->1.2 
#   F:pci/hda/hda_codec.h:1.1->1.2 
#   F:pci/hda/hda_intel.c:1.2->1.3 
#   F:pci/nm256/nm256.c:1.58->1.59 
#   F:pci/trident/trident_main.c:1.69->1.70 
#   F:pci/ymfpci/ymfpci_main.c:1.64->1.65 
#   F:pcmcia/pdaudiocf/pdaudiocf.c:1.11->1.12 
#   F:pcmcia/pdaudiocf/pdaudiocf.h:1.7->1.8 
#   F:pcmcia/pdaudiocf/pdaudiocf_core.c:1.6->1.7 
#   F:pcmcia/vx/vx_entry.c:1.8->1.9 
#   F:ppc/pmac.c:1.43->1.44 
#   L:Fixes by Pavel Machek <pavel@suse.cz>:
#   L:suspend() routines no longer get u32 as their parameter (they get
#   L:pm_message_t, which is u32 for now, but will change in 2.6.12 or
#   L:so). This fixes ALSA to notice this, and uses constants with right
#   L:types where appropriate. It results in no code changes. [Best results
#   L:will be when patching against latest -mm, you may get some warnings if
#   L:you patch it into older kernel, but it should still do the right
#   L:thing.] Please apply,
#   L:							Pavel
#   L:
#   L:[In addition, suspend callback type is changed to follow to the standard
#   L: style taking no state argument -- Takashi]
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/intel8x0.c
#   2005/01/28 12:34:06+01:00 perex@suse.cz +2 -2
#   [ALSA] driver model type fixes for ALSA
#   
#   D:2005/01/28 19:34:04
#   C:SA11xx UDA1341 driver,Control Midlevel,ALSA Core,Digigram VX core
#   C:ES18xx driver,OPL3SA2 driver,AD1848 driver,CS4231 driver,ATIIXP driver
#   C:ATIIXP-modem driver,CS4281 driver,ES1938 driver,ES1968 driver
#   C:Intel8x0 driver,Intel8x0-modem driver,Maestro3 driver,VIA82xx driver
#   C:VIA82xx-modem driver,ALI5451 driver,CS46xx driver,HDA Codec driver
#   C:HDA Intel driver,NM256 driver,Trident driver,YMFPCI driver
#   C:PDAudioCF driver,Digigram VX Pocket driver,PPC PMAC driver
#   F:arm/sa11xx-uda1341.c:1.20->1.21 
#   F:core/control.c:1.56->1.57 
#   F:core/init.c:1.58->1.59 
#   F:drivers/vx/vx_core.c:1.14->1.15 
#   F:include/core.h:1.65->1.66 
#   F:isa/es18xx.c:1.53->1.54 
#   F:isa/opl3sa2.c:1.42->1.43 
#   F:isa/ad1848/ad1848_lib.c:1.39->1.40 
#   F:isa/cs423x/cs4231_lib.c:1.47->1.48 
#   F:pci/atiixp.c:1.31->1.32 
#   F:pci/atiixp_modem.c:1.14->1.15 
#   F:pci/cs4281.c:1.69->1.70 
#   F:pci/es1938.c:1.45->1.46 
#   F:pci/es1968.c:1.82->1.83 
#   F:pci/intel8x0.c:1.190->1.191 
#   F:pci/intel8x0m.c:1.26->1.27 
#   F:pci/maestro3.c:1.68->1.69 
#   F:pci/via82xx.c:1.135->1.136 
#   F:pci/via82xx_modem.c:1.4->1.5 
#   F:pci/ali5451/ali5451.c:1.60->1.61 
#   F:pci/cs46xx/cs46xx_lib.c:1.93->1.94 
#   F:pci/hda/hda_codec.c:1.1->1.2 
#   F:pci/hda/hda_codec.h:1.1->1.2 
#   F:pci/hda/hda_intel.c:1.2->1.3 
#   F:pci/nm256/nm256.c:1.58->1.59 
#   F:pci/trident/trident_main.c:1.69->1.70 
#   F:pci/ymfpci/ymfpci_main.c:1.64->1.65 
#   F:pcmcia/pdaudiocf/pdaudiocf.c:1.11->1.12 
#   F:pcmcia/pdaudiocf/pdaudiocf.h:1.7->1.8 
#   F:pcmcia/pdaudiocf/pdaudiocf_core.c:1.6->1.7 
#   F:pcmcia/vx/vx_entry.c:1.8->1.9 
#   F:ppc/pmac.c:1.43->1.44 
#   L:Fixes by Pavel Machek <pavel@suse.cz>:
#   L:suspend() routines no longer get u32 as their parameter (they get
#   L:pm_message_t, which is u32 for now, but will change in 2.6.12 or
#   L:so). This fixes ALSA to notice this, and uses constants with right
#   L:types where appropriate. It results in no code changes. [Best results
#   L:will be when patching against latest -mm, you may get some warnings if
#   L:you patch it into older kernel, but it should still do the right
#   L:thing.] Please apply,
#   L:							Pavel
#   L:
#   L:[In addition, suspend callback type is changed to follow to the standard
#   L: style taking no state argument -- Takashi]
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/hda/hda_intel.c
#   2005/01/28 12:34:07+01:00 perex@suse.cz +3 -3
#   [ALSA] driver model type fixes for ALSA
#   
#   D:2005/01/28 19:34:04
#   C:SA11xx UDA1341 driver,Control Midlevel,ALSA Core,Digigram VX core
#   C:ES18xx driver,OPL3SA2 driver,AD1848 driver,CS4231 driver,ATIIXP driver
#   C:ATIIXP-modem driver,CS4281 driver,ES1938 driver,ES1968 driver
#   C:Intel8x0 driver,Intel8x0-modem driver,Maestro3 driver,VIA82xx driver
#   C:VIA82xx-modem driver,ALI5451 driver,CS46xx driver,HDA Codec driver
#   C:HDA Intel driver,NM256 driver,Trident driver,YMFPCI driver
#   C:PDAudioCF driver,Digigram VX Pocket driver,PPC PMAC driver
#   F:arm/sa11xx-uda1341.c:1.20->1.21 
#   F:core/control.c:1.56->1.57 
#   F:core/init.c:1.58->1.59 
#   F:drivers/vx/vx_core.c:1.14->1.15 
#   F:include/core.h:1.65->1.66 
#   F:isa/es18xx.c:1.53->1.54 
#   F:isa/opl3sa2.c:1.42->1.43 
#   F:isa/ad1848/ad1848_lib.c:1.39->1.40 
#   F:isa/cs423x/cs4231_lib.c:1.47->1.48 
#   F:pci/atiixp.c:1.31->1.32 
#   F:pci/atiixp_modem.c:1.14->1.15 
#   F:pci/cs4281.c:1.69->1.70 
#   F:pci/es1938.c:1.45->1.46 
#   F:pci/es1968.c:1.82->1.83 
#   F:pci/intel8x0.c:1.190->1.191 
#   F:pci/intel8x0m.c:1.26->1.27 
#   F:pci/maestro3.c:1.68->1.69 
#   F:pci/via82xx.c:1.135->1.136 
#   F:pci/via82xx_modem.c:1.4->1.5 
#   F:pci/ali5451/ali5451.c:1.60->1.61 
#   F:pci/cs46xx/cs46xx_lib.c:1.93->1.94 
#   F:pci/hda/hda_codec.c:1.1->1.2 
#   F:pci/hda/hda_codec.h:1.1->1.2 
#   F:pci/hda/hda_intel.c:1.2->1.3 
#   F:pci/nm256/nm256.c:1.58->1.59 
#   F:pci/trident/trident_main.c:1.69->1.70 
#   F:pci/ymfpci/ymfpci_main.c:1.64->1.65 
#   F:pcmcia/pdaudiocf/pdaudiocf.c:1.11->1.12 
#   F:pcmcia/pdaudiocf/pdaudiocf.h:1.7->1.8 
#   F:pcmcia/pdaudiocf/pdaudiocf_core.c:1.6->1.7 
#   F:pcmcia/vx/vx_entry.c:1.8->1.9 
#   F:ppc/pmac.c:1.43->1.44 
#   L:Fixes by Pavel Machek <pavel@suse.cz>:
#   L:suspend() routines no longer get u32 as their parameter (they get
#   L:pm_message_t, which is u32 for now, but will change in 2.6.12 or
#   L:so). This fixes ALSA to notice this, and uses constants with right
#   L:types where appropriate. It results in no code changes. [Best results
#   L:will be when patching against latest -mm, you may get some warnings if
#   L:you patch it into older kernel, but it should still do the right
#   L:thing.] Please apply,
#   L:							Pavel
#   L:
#   L:[In addition, suspend callback type is changed to follow to the standard
#   L: style taking no state argument -- Takashi]
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/hda/hda_codec.h
#   2005/01/28 12:34:07+01:00 perex@suse.cz +4 -4
#   [ALSA] driver model type fixes for ALSA
#   
#   D:2005/01/28 19:34:04
#   C:SA11xx UDA1341 driver,Control Midlevel,ALSA Core,Digigram VX core
#   C:ES18xx driver,OPL3SA2 driver,AD1848 driver,CS4231 driver,ATIIXP driver
#   C:ATIIXP-modem driver,CS4281 driver,ES1938 driver,ES1968 driver
#   C:Intel8x0 driver,Intel8x0-modem driver,Maestro3 driver,VIA82xx driver
#   C:VIA82xx-modem driver,ALI5451 driver,CS46xx driver,HDA Codec driver
#   C:HDA Intel driver,NM256 driver,Trident driver,YMFPCI driver
#   C:PDAudioCF driver,Digigram VX Pocket driver,PPC PMAC driver
#   F:arm/sa11xx-uda1341.c:1.20->1.21 
#   F:core/control.c:1.56->1.57 
#   F:core/init.c:1.58->1.59 
#   F:drivers/vx/vx_core.c:1.14->1.15 
#   F:include/core.h:1.65->1.66 
#   F:isa/es18xx.c:1.53->1.54 
#   F:isa/opl3sa2.c:1.42->1.43 
#   F:isa/ad1848/ad1848_lib.c:1.39->1.40 
#   F:isa/cs423x/cs4231_lib.c:1.47->1.48 
#   F:pci/atiixp.c:1.31->1.32 
#   F:pci/atiixp_modem.c:1.14->1.15 
#   F:pci/cs4281.c:1.69->1.70 
#   F:pci/es1938.c:1.45->1.46 
#   F:pci/es1968.c:1.82->1.83 
#   F:pci/intel8x0.c:1.190->1.191 
#   F:pci/intel8x0m.c:1.26->1.27 
#   F:pci/maestro3.c:1.68->1.69 
#   F:pci/via82xx.c:1.135->1.136 
#   F:pci/via82xx_modem.c:1.4->1.5 
#   F:pci/ali5451/ali5451.c:1.60->1.61 
#   F:pci/cs46xx/cs46xx_lib.c:1.93->1.94 
#   F:pci/hda/hda_codec.c:1.1->1.2 
#   F:pci/hda/hda_codec.h:1.1->1.2 
#   F:pci/hda/hda_intel.c:1.2->1.3 
#   F:pci/nm256/nm256.c:1.58->1.59 
#   F:pci/trident/trident_main.c:1.69->1.70 
#   F:pci/ymfpci/ymfpci_main.c:1.64->1.65 
#   F:pcmcia/pdaudiocf/pdaudiocf.c:1.11->1.12 
#   F:pcmcia/pdaudiocf/pdaudiocf.h:1.7->1.8 
#   F:pcmcia/pdaudiocf/pdaudiocf_core.c:1.6->1.7 
#   F:pcmcia/vx/vx_entry.c:1.8->1.9 
#   F:ppc/pmac.c:1.43->1.44 
#   L:Fixes by Pavel Machek <pavel@suse.cz>:
#   L:suspend() routines no longer get u32 as their parameter (they get
#   L:pm_message_t, which is u32 for now, but will change in 2.6.12 or
#   L:so). This fixes ALSA to notice this, and uses constants with right
#   L:types where appropriate. It results in no code changes. [Best results
#   L:will be when patching against latest -mm, you may get some warnings if
#   L:you patch it into older kernel, but it should still do the right
#   L:thing.] Please apply,
#   L:							Pavel
#   L:
#   L:[In addition, suspend callback type is changed to follow to the standard
#   L: style taking no state argument -- Takashi]
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/hda/hda_codec.c
#   2005/01/28 12:34:07+01:00 perex@suse.cz +3 -3
#   [ALSA] driver model type fixes for ALSA
#   
#   D:2005/01/28 19:34:04
#   C:SA11xx UDA1341 driver,Control Midlevel,ALSA Core,Digigram VX core
#   C:ES18xx driver,OPL3SA2 driver,AD1848 driver,CS4231 driver,ATIIXP driver
#   C:ATIIXP-modem driver,CS4281 driver,ES1938 driver,ES1968 driver
#   C:Intel8x0 driver,Intel8x0-modem driver,Maestro3 driver,VIA82xx driver
#   C:VIA82xx-modem driver,ALI5451 driver,CS46xx driver,HDA Codec driver
#   C:HDA Intel driver,NM256 driver,Trident driver,YMFPCI driver
#   C:PDAudioCF driver,Digigram VX Pocket driver,PPC PMAC driver
#   F:arm/sa11xx-uda1341.c:1.20->1.21 
#   F:core/control.c:1.56->1.57 
#   F:core/init.c:1.58->1.59 
#   F:drivers/vx/vx_core.c:1.14->1.15 
#   F:include/core.h:1.65->1.66 
#   F:isa/es18xx.c:1.53->1.54 
#   F:isa/opl3sa2.c:1.42->1.43 
#   F:isa/ad1848/ad1848_lib.c:1.39->1.40 
#   F:isa/cs423x/cs4231_lib.c:1.47->1.48 
#   F:pci/atiixp.c:1.31->1.32 
#   F:pci/atiixp_modem.c:1.14->1.15 
#   F:pci/cs4281.c:1.69->1.70 
#   F:pci/es1938.c:1.45->1.46 
#   F:pci/es1968.c:1.82->1.83 
#   F:pci/intel8x0.c:1.190->1.191 
#   F:pci/intel8x0m.c:1.26->1.27 
#   F:pci/maestro3.c:1.68->1.69 
#   F:pci/via82xx.c:1.135->1.136 
#   F:pci/via82xx_modem.c:1.4->1.5 
#   F:pci/ali5451/ali5451.c:1.60->1.61 
#   F:pci/cs46xx/cs46xx_lib.c:1.93->1.94 
#   F:pci/hda/hda_codec.c:1.1->1.2 
#   F:pci/hda/hda_codec.h:1.1->1.2 
#   F:pci/hda/hda_intel.c:1.2->1.3 
#   F:pci/nm256/nm256.c:1.58->1.59 
#   F:pci/trident/trident_main.c:1.69->1.70 
#   F:pci/ymfpci/ymfpci_main.c:1.64->1.65 
#   F:pcmcia/pdaudiocf/pdaudiocf.c:1.11->1.12 
#   F:pcmcia/pdaudiocf/pdaudiocf.h:1.7->1.8 
#   F:pcmcia/pdaudiocf/pdaudiocf_core.c:1.6->1.7 
#   F:pcmcia/vx/vx_entry.c:1.8->1.9 
#   F:ppc/pmac.c:1.43->1.44 
#   L:Fixes by Pavel Machek <pavel@suse.cz>:
#   L:suspend() routines no longer get u32 as their parameter (they get
#   L:pm_message_t, which is u32 for now, but will change in 2.6.12 or
#   L:so). This fixes ALSA to notice this, and uses constants with right
#   L:types where appropriate. It results in no code changes. [Best results
#   L:will be when patching against latest -mm, you may get some warnings if
#   L:you patch it into older kernel, but it should still do the right
#   L:thing.] Please apply,
#   L:							Pavel
#   L:
#   L:[In addition, suspend callback type is changed to follow to the standard
#   L: style taking no state argument -- Takashi]
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/es1968.c
#   2005/01/28 12:34:06+01:00 perex@suse.cz +2 -2
#   [ALSA] driver model type fixes for ALSA
#   
#   D:2005/01/28 19:34:04
#   C:SA11xx UDA1341 driver,Control Midlevel,ALSA Core,Digigram VX core
#   C:ES18xx driver,OPL3SA2 driver,AD1848 driver,CS4231 driver,ATIIXP driver
#   C:ATIIXP-modem driver,CS4281 driver,ES1938 driver,ES1968 driver
#   C:Intel8x0 driver,Intel8x0-modem driver,Maestro3 driver,VIA82xx driver
#   C:VIA82xx-modem driver,ALI5451 driver,CS46xx driver,HDA Codec driver
#   C:HDA Intel driver,NM256 driver,Trident driver,YMFPCI driver
#   C:PDAudioCF driver,Digigram VX Pocket driver,PPC PMAC driver
#   F:arm/sa11xx-uda1341.c:1.20->1.21 
#   F:core/control.c:1.56->1.57 
#   F:core/init.c:1.58->1.59 
#   F:drivers/vx/vx_core.c:1.14->1.15 
#   F:include/core.h:1.65->1.66 
#   F:isa/es18xx.c:1.53->1.54 
#   F:isa/opl3sa2.c:1.42->1.43 
#   F:isa/ad1848/ad1848_lib.c:1.39->1.40 
#   F:isa/cs423x/cs4231_lib.c:1.47->1.48 
#   F:pci/atiixp.c:1.31->1.32 
#   F:pci/atiixp_modem.c:1.14->1.15 
#   F:pci/cs4281.c:1.69->1.70 
#   F:pci/es1938.c:1.45->1.46 
#   F:pci/es1968.c:1.82->1.83 
#   F:pci/intel8x0.c:1.190->1.191 
#   F:pci/intel8x0m.c:1.26->1.27 
#   F:pci/maestro3.c:1.68->1.69 
#   F:pci/via82xx.c:1.135->1.136 
#   F:pci/via82xx_modem.c:1.4->1.5 
#   F:pci/ali5451/ali5451.c:1.60->1.61 
#   F:pci/cs46xx/cs46xx_lib.c:1.93->1.94 
#   F:pci/hda/hda_codec.c:1.1->1.2 
#   F:pci/hda/hda_codec.h:1.1->1.2 
#   F:pci/hda/hda_intel.c:1.2->1.3 
#   F:pci/nm256/nm256.c:1.58->1.59 
#   F:pci/trident/trident_main.c:1.69->1.70 
#   F:pci/ymfpci/ymfpci_main.c:1.64->1.65 
#   F:pcmcia/pdaudiocf/pdaudiocf.c:1.11->1.12 
#   F:pcmcia/pdaudiocf/pdaudiocf.h:1.7->1.8 
#   F:pcmcia/pdaudiocf/pdaudiocf_core.c:1.6->1.7 
#   F:pcmcia/vx/vx_entry.c:1.8->1.9 
#   F:ppc/pmac.c:1.43->1.44 
#   L:Fixes by Pavel Machek <pavel@suse.cz>:
#   L:suspend() routines no longer get u32 as their parameter (they get
#   L:pm_message_t, which is u32 for now, but will change in 2.6.12 or
#   L:so). This fixes ALSA to notice this, and uses constants with right
#   L:types where appropriate. It results in no code changes. [Best results
#   L:will be when patching against latest -mm, you may get some warnings if
#   L:you patch it into older kernel, but it should still do the right
#   L:thing.] Please apply,
#   L:							Pavel
#   L:
#   L:[In addition, suspend callback type is changed to follow to the standard
#   L: style taking no state argument -- Takashi]
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/es1938.c
#   2005/01/28 12:34:06+01:00 perex@suse.cz +2 -2
#   [ALSA] driver model type fixes for ALSA
#   
#   D:2005/01/28 19:34:04
#   C:SA11xx UDA1341 driver,Control Midlevel,ALSA Core,Digigram VX core
#   C:ES18xx driver,OPL3SA2 driver,AD1848 driver,CS4231 driver,ATIIXP driver
#   C:ATIIXP-modem driver,CS4281 driver,ES1938 driver,ES1968 driver
#   C:Intel8x0 driver,Intel8x0-modem driver,Maestro3 driver,VIA82xx driver
#   C:VIA82xx-modem driver,ALI5451 driver,CS46xx driver,HDA Codec driver
#   C:HDA Intel driver,NM256 driver,Trident driver,YMFPCI driver
#   C:PDAudioCF driver,Digigram VX Pocket driver,PPC PMAC driver
#   F:arm/sa11xx-uda1341.c:1.20->1.21 
#   F:core/control.c:1.56->1.57 
#   F:core/init.c:1.58->1.59 
#   F:drivers/vx/vx_core.c:1.14->1.15 
#   F:include/core.h:1.65->1.66 
#   F:isa/es18xx.c:1.53->1.54 
#   F:isa/opl3sa2.c:1.42->1.43 
#   F:isa/ad1848/ad1848_lib.c:1.39->1.40 
#   F:isa/cs423x/cs4231_lib.c:1.47->1.48 
#   F:pci/atiixp.c:1.31->1.32 
#   F:pci/atiixp_modem.c:1.14->1.15 
#   F:pci/cs4281.c:1.69->1.70 
#   F:pci/es1938.c:1.45->1.46 
#   F:pci/es1968.c:1.82->1.83 
#   F:pci/intel8x0.c:1.190->1.191 
#   F:pci/intel8x0m.c:1.26->1.27 
#   F:pci/maestro3.c:1.68->1.69 
#   F:pci/via82xx.c:1.135->1.136 
#   F:pci/via82xx_modem.c:1.4->1.5 
#   F:pci/ali5451/ali5451.c:1.60->1.61 
#   F:pci/cs46xx/cs46xx_lib.c:1.93->1.94 
#   F:pci/hda/hda_codec.c:1.1->1.2 
#   F:pci/hda/hda_codec.h:1.1->1.2 
#   F:pci/hda/hda_intel.c:1.2->1.3 
#   F:pci/nm256/nm256.c:1.58->1.59 
#   F:pci/trident/trident_main.c:1.69->1.70 
#   F:pci/ymfpci/ymfpci_main.c:1.64->1.65 
#   F:pcmcia/pdaudiocf/pdaudiocf.c:1.11->1.12 
#   F:pcmcia/pdaudiocf/pdaudiocf.h:1.7->1.8 
#   F:pcmcia/pdaudiocf/pdaudiocf_core.c:1.6->1.7 
#   F:pcmcia/vx/vx_entry.c:1.8->1.9 
#   F:ppc/pmac.c:1.43->1.44 
#   L:Fixes by Pavel Machek <pavel@suse.cz>:
#   L:suspend() routines no longer get u32 as their parameter (they get
#   L:pm_message_t, which is u32 for now, but will change in 2.6.12 or
#   L:so). This fixes ALSA to notice this, and uses constants with right
#   L:types where appropriate. It results in no code changes. [Best results
#   L:will be when patching against latest -mm, you may get some warnings if
#   L:you patch it into older kernel, but it should still do the right
#   L:thing.] Please apply,
#   L:							Pavel
#   L:
#   L:[In addition, suspend callback type is changed to follow to the standard
#   L: style taking no state argument -- Takashi]
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/cs46xx/cs46xx_lib.c
#   2005/01/28 12:34:07+01:00 perex@suse.cz +2 -2
#   [ALSA] driver model type fixes for ALSA
#   
#   D:2005/01/28 19:34:04
#   C:SA11xx UDA1341 driver,Control Midlevel,ALSA Core,Digigram VX core
#   C:ES18xx driver,OPL3SA2 driver,AD1848 driver,CS4231 driver,ATIIXP driver
#   C:ATIIXP-modem driver,CS4281 driver,ES1938 driver,ES1968 driver
#   C:Intel8x0 driver,Intel8x0-modem driver,Maestro3 driver,VIA82xx driver
#   C:VIA82xx-modem driver,ALI5451 driver,CS46xx driver,HDA Codec driver
#   C:HDA Intel driver,NM256 driver,Trident driver,YMFPCI driver
#   C:PDAudioCF driver,Digigram VX Pocket driver,PPC PMAC driver
#   F:arm/sa11xx-uda1341.c:1.20->1.21 
#   F:core/control.c:1.56->1.57 
#   F:core/init.c:1.58->1.59 
#   F:drivers/vx/vx_core.c:1.14->1.15 
#   F:include/core.h:1.65->1.66 
#   F:isa/es18xx.c:1.53->1.54 
#   F:isa/opl3sa2.c:1.42->1.43 
#   F:isa/ad1848/ad1848_lib.c:1.39->1.40 
#   F:isa/cs423x/cs4231_lib.c:1.47->1.48 
#   F:pci/atiixp.c:1.31->1.32 
#   F:pci/atiixp_modem.c:1.14->1.15 
#   F:pci/cs4281.c:1.69->1.70 
#   F:pci/es1938.c:1.45->1.46 
#   F:pci/es1968.c:1.82->1.83 
#   F:pci/intel8x0.c:1.190->1.191 
#   F:pci/intel8x0m.c:1.26->1.27 
#   F:pci/maestro3.c:1.68->1.69 
#   F:pci/via82xx.c:1.135->1.136 
#   F:pci/via82xx_modem.c:1.4->1.5 
#   F:pci/ali5451/ali5451.c:1.60->1.61 
#   F:pci/cs46xx/cs46xx_lib.c:1.93->1.94 
#   F:pci/hda/hda_codec.c:1.1->1.2 
#   F:pci/hda/hda_codec.h:1.1->1.2 
#   F:pci/hda/hda_intel.c:1.2->1.3 
#   F:pci/nm256/nm256.c:1.58->1.59 
#   F:pci/trident/trident_main.c:1.69->1.70 
#   F:pci/ymfpci/ymfpci_main.c:1.64->1.65 
#   F:pcmcia/pdaudiocf/pdaudiocf.c:1.11->1.12 
#   F:pcmcia/pdaudiocf/pdaudiocf.h:1.7->1.8 
#   F:pcmcia/pdaudiocf/pdaudiocf_core.c:1.6->1.7 
#   F:pcmcia/vx/vx_entry.c:1.8->1.9 
#   F:ppc/pmac.c:1.43->1.44 
#   L:Fixes by Pavel Machek <pavel@suse.cz>:
#   L:suspend() routines no longer get u32 as their parameter (they get
#   L:pm_message_t, which is u32 for now, but will change in 2.6.12 or
#   L:so). This fixes ALSA to notice this, and uses constants with right
#   L:types where appropriate. It results in no code changes. [Best results
#   L:will be when patching against latest -mm, you may get some warnings if
#   L:you patch it into older kernel, but it should still do the right
#   L:thing.] Please apply,
#   L:							Pavel
#   L:
#   L:[In addition, suspend callback type is changed to follow to the standard
#   L: style taking no state argument -- Takashi]
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/cs4281.c
#   2005/01/28 12:34:06+01:00 perex@suse.cz +4 -4
#   [ALSA] driver model type fixes for ALSA
#   
#   D:2005/01/28 19:34:04
#   C:SA11xx UDA1341 driver,Control Midlevel,ALSA Core,Digigram VX core
#   C:ES18xx driver,OPL3SA2 driver,AD1848 driver,CS4231 driver,ATIIXP driver
#   C:ATIIXP-modem driver,CS4281 driver,ES1938 driver,ES1968 driver
#   C:Intel8x0 driver,Intel8x0-modem driver,Maestro3 driver,VIA82xx driver
#   C:VIA82xx-modem driver,ALI5451 driver,CS46xx driver,HDA Codec driver
#   C:HDA Intel driver,NM256 driver,Trident driver,YMFPCI driver
#   C:PDAudioCF driver,Digigram VX Pocket driver,PPC PMAC driver
#   F:arm/sa11xx-uda1341.c:1.20->1.21 
#   F:core/control.c:1.56->1.57 
#   F:core/init.c:1.58->1.59 
#   F:drivers/vx/vx_core.c:1.14->1.15 
#   F:include/core.h:1.65->1.66 
#   F:isa/es18xx.c:1.53->1.54 
#   F:isa/opl3sa2.c:1.42->1.43 
#   F:isa/ad1848/ad1848_lib.c:1.39->1.40 
#   F:isa/cs423x/cs4231_lib.c:1.47->1.48 
#   F:pci/atiixp.c:1.31->1.32 
#   F:pci/atiixp_modem.c:1.14->1.15 
#   F:pci/cs4281.c:1.69->1.70 
#   F:pci/es1938.c:1.45->1.46 
#   F:pci/es1968.c:1.82->1.83 
#   F:pci/intel8x0.c:1.190->1.191 
#   F:pci/intel8x0m.c:1.26->1.27 
#   F:pci/maestro3.c:1.68->1.69 
#   F:pci/via82xx.c:1.135->1.136 
#   F:pci/via82xx_modem.c:1.4->1.5 
#   F:pci/ali5451/ali5451.c:1.60->1.61 
#   F:pci/cs46xx/cs46xx_lib.c:1.93->1.94 
#   F:pci/hda/hda_codec.c:1.1->1.2 
#   F:pci/hda/hda_codec.h:1.1->1.2 
#   F:pci/hda/hda_intel.c:1.2->1.3 
#   F:pci/nm256/nm256.c:1.58->1.59 
#   F:pci/trident/trident_main.c:1.69->1.70 
#   F:pci/ymfpci/ymfpci_main.c:1.64->1.65 
#   F:pcmcia/pdaudiocf/pdaudiocf.c:1.11->1.12 
#   F:pcmcia/pdaudiocf/pdaudiocf.h:1.7->1.8 
#   F:pcmcia/pdaudiocf/pdaudiocf_core.c:1.6->1.7 
#   F:pcmcia/vx/vx_entry.c:1.8->1.9 
#   F:ppc/pmac.c:1.43->1.44 
#   L:Fixes by Pavel Machek <pavel@suse.cz>:
#   L:suspend() routines no longer get u32 as their parameter (they get
#   L:pm_message_t, which is u32 for now, but will change in 2.6.12 or
#   L:so). This fixes ALSA to notice this, and uses constants with right
#   L:types where appropriate. It results in no code changes. [Best results
#   L:will be when patching against latest -mm, you may get some warnings if
#   L:you patch it into older kernel, but it should still do the right
#   L:thing.] Please apply,
#   L:							Pavel
#   L:
#   L:[In addition, suspend callback type is changed to follow to the standard
#   L: style taking no state argument -- Takashi]
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/atiixp_modem.c
#   2005/01/28 12:34:06+01:00 perex@suse.cz +2 -2
#   [ALSA] driver model type fixes for ALSA
#   
#   D:2005/01/28 19:34:04
#   C:SA11xx UDA1341 driver,Control Midlevel,ALSA Core,Digigram VX core
#   C:ES18xx driver,OPL3SA2 driver,AD1848 driver,CS4231 driver,ATIIXP driver
#   C:ATIIXP-modem driver,CS4281 driver,ES1938 driver,ES1968 driver
#   C:Intel8x0 driver,Intel8x0-modem driver,Maestro3 driver,VIA82xx driver
#   C:VIA82xx-modem driver,ALI5451 driver,CS46xx driver,HDA Codec driver
#   C:HDA Intel driver,NM256 driver,Trident driver,YMFPCI driver
#   C:PDAudioCF driver,Digigram VX Pocket driver,PPC PMAC driver
#   F:arm/sa11xx-uda1341.c:1.20->1.21 
#   F:core/control.c:1.56->1.57 
#   F:core/init.c:1.58->1.59 
#   F:drivers/vx/vx_core.c:1.14->1.15 
#   F:include/core.h:1.65->1.66 
#   F:isa/es18xx.c:1.53->1.54 
#   F:isa/opl3sa2.c:1.42->1.43 
#   F:isa/ad1848/ad1848_lib.c:1.39->1.40 
#   F:isa/cs423x/cs4231_lib.c:1.47->1.48 
#   F:pci/atiixp.c:1.31->1.32 
#   F:pci/atiixp_modem.c:1.14->1.15 
#   F:pci/cs4281.c:1.69->1.70 
#   F:pci/es1938.c:1.45->1.46 
#   F:pci/es1968.c:1.82->1.83 
#   F:pci/intel8x0.c:1.190->1.191 
#   F:pci/intel8x0m.c:1.26->1.27 
#   F:pci/maestro3.c:1.68->1.69 
#   F:pci/via82xx.c:1.135->1.136 
#   F:pci/via82xx_modem.c:1.4->1.5 
#   F:pci/ali5451/ali5451.c:1.60->1.61 
#   F:pci/cs46xx/cs46xx_lib.c:1.93->1.94 
#   F:pci/hda/hda_codec.c:1.1->1.2 
#   F:pci/hda/hda_codec.h:1.1->1.2 
#   F:pci/hda/hda_intel.c:1.2->1.3 
#   F:pci/nm256/nm256.c:1.58->1.59 
#   F:pci/trident/trident_main.c:1.69->1.70 
#   F:pci/ymfpci/ymfpci_main.c:1.64->1.65 
#   F:pcmcia/pdaudiocf/pdaudiocf.c:1.11->1.12 
#   F:pcmcia/pdaudiocf/pdaudiocf.h:1.7->1.8 
#   F:pcmcia/pdaudiocf/pdaudiocf_core.c:1.6->1.7 
#   F:pcmcia/vx/vx_entry.c:1.8->1.9 
#   F:ppc/pmac.c:1.43->1.44 
#   L:Fixes by Pavel Machek <pavel@suse.cz>:
#   L:suspend() routines no longer get u32 as their parameter (they get
#   L:pm_message_t, which is u32 for now, but will change in 2.6.12 or
#   L:so). This fixes ALSA to notice this, and uses constants with right
#   L:types where appropriate. It results in no code changes. [Best results
#   L:will be when patching against latest -mm, you may get some warnings if
#   L:you patch it into older kernel, but it should still do the right
#   L:thing.] Please apply,
#   L:							Pavel
#   L:
#   L:[In addition, suspend callback type is changed to follow to the standard
#   L: style taking no state argument -- Takashi]
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/atiixp.c
#   2005/01/28 12:34:06+01:00 perex@suse.cz +2 -2
#   [ALSA] driver model type fixes for ALSA
#   
#   D:2005/01/28 19:34:04
#   C:SA11xx UDA1341 driver,Control Midlevel,ALSA Core,Digigram VX core
#   C:ES18xx driver,OPL3SA2 driver,AD1848 driver,CS4231 driver,ATIIXP driver
#   C:ATIIXP-modem driver,CS4281 driver,ES1938 driver,ES1968 driver
#   C:Intel8x0 driver,Intel8x0-modem driver,Maestro3 driver,VIA82xx driver
#   C:VIA82xx-modem driver,ALI5451 driver,CS46xx driver,HDA Codec driver
#   C:HDA Intel driver,NM256 driver,Trident driver,YMFPCI driver
#   C:PDAudioCF driver,Digigram VX Pocket driver,PPC PMAC driver
#   F:arm/sa11xx-uda1341.c:1.20->1.21 
#   F:core/control.c:1.56->1.57 
#   F:core/init.c:1.58->1.59 
#   F:drivers/vx/vx_core.c:1.14->1.15 
#   F:include/core.h:1.65->1.66 
#   F:isa/es18xx.c:1.53->1.54 
#   F:isa/opl3sa2.c:1.42->1.43 
#   F:isa/ad1848/ad1848_lib.c:1.39->1.40 
#   F:isa/cs423x/cs4231_lib.c:1.47->1.48 
#   F:pci/atiixp.c:1.31->1.32 
#   F:pci/atiixp_modem.c:1.14->1.15 
#   F:pci/cs4281.c:1.69->1.70 
#   F:pci/es1938.c:1.45->1.46 
#   F:pci/es1968.c:1.82->1.83 
#   F:pci/intel8x0.c:1.190->1.191 
#   F:pci/intel8x0m.c:1.26->1.27 
#   F:pci/maestro3.c:1.68->1.69 
#   F:pci/via82xx.c:1.135->1.136 
#   F:pci/via82xx_modem.c:1.4->1.5 
#   F:pci/ali5451/ali5451.c:1.60->1.61 
#   F:pci/cs46xx/cs46xx_lib.c:1.93->1.94 
#   F:pci/hda/hda_codec.c:1.1->1.2 
#   F:pci/hda/hda_codec.h:1.1->1.2 
#   F:pci/hda/hda_intel.c:1.2->1.3 
#   F:pci/nm256/nm256.c:1.58->1.59 
#   F:pci/trident/trident_main.c:1.69->1.70 
#   F:pci/ymfpci/ymfpci_main.c:1.64->1.65 
#   F:pcmcia/pdaudiocf/pdaudiocf.c:1.11->1.12 
#   F:pcmcia/pdaudiocf/pdaudiocf.h:1.7->1.8 
#   F:pcmcia/pdaudiocf/pdaudiocf_core.c:1.6->1.7 
#   F:pcmcia/vx/vx_entry.c:1.8->1.9 
#   F:ppc/pmac.c:1.43->1.44 
#   L:Fixes by Pavel Machek <pavel@suse.cz>:
#   L:suspend() routines no longer get u32 as their parameter (they get
#   L:pm_message_t, which is u32 for now, but will change in 2.6.12 or
#   L:so). This fixes ALSA to notice this, and uses constants with right
#   L:types where appropriate. It results in no code changes. [Best results
#   L:will be when patching against latest -mm, you may get some warnings if
#   L:you patch it into older kernel, but it should still do the right
#   L:thing.] Please apply,
#   L:							Pavel
#   L:
#   L:[In addition, suspend callback type is changed to follow to the standard
#   L: style taking no state argument -- Takashi]
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/ali5451/ali5451.c
#   2005/01/28 12:34:07+01:00 perex@suse.cz +2 -2
#   [ALSA] driver model type fixes for ALSA
#   
#   D:2005/01/28 19:34:04
#   C:SA11xx UDA1341 driver,Control Midlevel,ALSA Core,Digigram VX core
#   C:ES18xx driver,OPL3SA2 driver,AD1848 driver,CS4231 driver,ATIIXP driver
#   C:ATIIXP-modem driver,CS4281 driver,ES1938 driver,ES1968 driver
#   C:Intel8x0 driver,Intel8x0-modem driver,Maestro3 driver,VIA82xx driver
#   C:VIA82xx-modem driver,ALI5451 driver,CS46xx driver,HDA Codec driver
#   C:HDA Intel driver,NM256 driver,Trident driver,YMFPCI driver
#   C:PDAudioCF driver,Digigram VX Pocket driver,PPC PMAC driver
#   F:arm/sa11xx-uda1341.c:1.20->1.21 
#   F:core/control.c:1.56->1.57 
#   F:core/init.c:1.58->1.59 
#   F:drivers/vx/vx_core.c:1.14->1.15 
#   F:include/core.h:1.65->1.66 
#   F:isa/es18xx.c:1.53->1.54 
#   F:isa/opl3sa2.c:1.42->1.43 
#   F:isa/ad1848/ad1848_lib.c:1.39->1.40 
#   F:isa/cs423x/cs4231_lib.c:1.47->1.48 
#   F:pci/atiixp.c:1.31->1.32 
#   F:pci/atiixp_modem.c:1.14->1.15 
#   F:pci/cs4281.c:1.69->1.70 
#   F:pci/es1938.c:1.45->1.46 
#   F:pci/es1968.c:1.82->1.83 
#   F:pci/intel8x0.c:1.190->1.191 
#   F:pci/intel8x0m.c:1.26->1.27 
#   F:pci/maestro3.c:1.68->1.69 
#   F:pci/via82xx.c:1.135->1.136 
#   F:pci/via82xx_modem.c:1.4->1.5 
#   F:pci/ali5451/ali5451.c:1.60->1.61 
#   F:pci/cs46xx/cs46xx_lib.c:1.93->1.94 
#   F:pci/hda/hda_codec.c:1.1->1.2 
#   F:pci/hda/hda_codec.h:1.1->1.2 
#   F:pci/hda/hda_intel.c:1.2->1.3 
#   F:pci/nm256/nm256.c:1.58->1.59 
#   F:pci/trident/trident_main.c:1.69->1.70 
#   F:pci/ymfpci/ymfpci_main.c:1.64->1.65 
#   F:pcmcia/pdaudiocf/pdaudiocf.c:1.11->1.12 
#   F:pcmcia/pdaudiocf/pdaudiocf.h:1.7->1.8 
#   F:pcmcia/pdaudiocf/pdaudiocf_core.c:1.6->1.7 
#   F:pcmcia/vx/vx_entry.c:1.8->1.9 
#   F:ppc/pmac.c:1.43->1.44 
#   L:Fixes by Pavel Machek <pavel@suse.cz>:
#   L:suspend() routines no longer get u32 as their parameter (they get
#   L:pm_message_t, which is u32 for now, but will change in 2.6.12 or
#   L:so). This fixes ALSA to notice this, and uses constants with right
#   L:types where appropriate. It results in no code changes. [Best results
#   L:will be when patching against latest -mm, you may get some warnings if
#   L:you patch it into older kernel, but it should still do the right
#   L:thing.] Please apply,
#   L:							Pavel
#   L:
#   L:[In addition, suspend callback type is changed to follow to the standard
#   L: style taking no state argument -- Takashi]
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/isa/opl3sa2.c
#   2005/01/28 12:34:05+01:00 perex@suse.cz +2 -2
#   [ALSA] driver model type fixes for ALSA
#   
#   D:2005/01/28 19:34:04
#   C:SA11xx UDA1341 driver,Control Midlevel,ALSA Core,Digigram VX core
#   C:ES18xx driver,OPL3SA2 driver,AD1848 driver,CS4231 driver,ATIIXP driver
#   C:ATIIXP-modem driver,CS4281 driver,ES1938 driver,ES1968 driver
#   C:Intel8x0 driver,Intel8x0-modem driver,Maestro3 driver,VIA82xx driver
#   C:VIA82xx-modem driver,ALI5451 driver,CS46xx driver,HDA Codec driver
#   C:HDA Intel driver,NM256 driver,Trident driver,YMFPCI driver
#   C:PDAudioCF driver,Digigram VX Pocket driver,PPC PMAC driver
#   F:arm/sa11xx-uda1341.c:1.20->1.21 
#   F:core/control.c:1.56->1.57 
#   F:core/init.c:1.58->1.59 
#   F:drivers/vx/vx_core.c:1.14->1.15 
#   F:include/core.h:1.65->1.66 
#   F:isa/es18xx.c:1.53->1.54 
#   F:isa/opl3sa2.c:1.42->1.43 
#   F:isa/ad1848/ad1848_lib.c:1.39->1.40 
#   F:isa/cs423x/cs4231_lib.c:1.47->1.48 
#   F:pci/atiixp.c:1.31->1.32 
#   F:pci/atiixp_modem.c:1.14->1.15 
#   F:pci/cs4281.c:1.69->1.70 
#   F:pci/es1938.c:1.45->1.46 
#   F:pci/es1968.c:1.82->1.83 
#   F:pci/intel8x0.c:1.190->1.191 
#   F:pci/intel8x0m.c:1.26->1.27 
#   F:pci/maestro3.c:1.68->1.69 
#   F:pci/via82xx.c:1.135->1.136 
#   F:pci/via82xx_modem.c:1.4->1.5 
#   F:pci/ali5451/ali5451.c:1.60->1.61 
#   F:pci/cs46xx/cs46xx_lib.c:1.93->1.94 
#   F:pci/hda/hda_codec.c:1.1->1.2 
#   F:pci/hda/hda_codec.h:1.1->1.2 
#   F:pci/hda/hda_intel.c:1.2->1.3 
#   F:pci/nm256/nm256.c:1.58->1.59 
#   F:pci/trident/trident_main.c:1.69->1.70 
#   F:pci/ymfpci/ymfpci_main.c:1.64->1.65 
#   F:pcmcia/pdaudiocf/pdaudiocf.c:1.11->1.12 
#   F:pcmcia/pdaudiocf/pdaudiocf.h:1.7->1.8 
#   F:pcmcia/pdaudiocf/pdaudiocf_core.c:1.6->1.7 
#   F:pcmcia/vx/vx_entry.c:1.8->1.9 
#   F:ppc/pmac.c:1.43->1.44 
#   L:Fixes by Pavel Machek <pavel@suse.cz>:
#   L:suspend() routines no longer get u32 as their parameter (they get
#   L:pm_message_t, which is u32 for now, but will change in 2.6.12 or
#   L:so). This fixes ALSA to notice this, and uses constants with right
#   L:types where appropriate. It results in no code changes. [Best results
#   L:will be when patching against latest -mm, you may get some warnings if
#   L:you patch it into older kernel, but it should still do the right
#   L:thing.] Please apply,
#   L:							Pavel
#   L:
#   L:[In addition, suspend callback type is changed to follow to the standard
#   L: style taking no state argument -- Takashi]
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/isa/es18xx.c
#   2005/01/28 12:34:05+01:00 perex@suse.cz +2 -2
#   [ALSA] driver model type fixes for ALSA
#   
#   D:2005/01/28 19:34:04
#   C:SA11xx UDA1341 driver,Control Midlevel,ALSA Core,Digigram VX core
#   C:ES18xx driver,OPL3SA2 driver,AD1848 driver,CS4231 driver,ATIIXP driver
#   C:ATIIXP-modem driver,CS4281 driver,ES1938 driver,ES1968 driver
#   C:Intel8x0 driver,Intel8x0-modem driver,Maestro3 driver,VIA82xx driver
#   C:VIA82xx-modem driver,ALI5451 driver,CS46xx driver,HDA Codec driver
#   C:HDA Intel driver,NM256 driver,Trident driver,YMFPCI driver
#   C:PDAudioCF driver,Digigram VX Pocket driver,PPC PMAC driver
#   F:arm/sa11xx-uda1341.c:1.20->1.21 
#   F:core/control.c:1.56->1.57 
#   F:core/init.c:1.58->1.59 
#   F:drivers/vx/vx_core.c:1.14->1.15 
#   F:include/core.h:1.65->1.66 
#   F:isa/es18xx.c:1.53->1.54 
#   F:isa/opl3sa2.c:1.42->1.43 
#   F:isa/ad1848/ad1848_lib.c:1.39->1.40 
#   F:isa/cs423x/cs4231_lib.c:1.47->1.48 
#   F:pci/atiixp.c:1.31->1.32 
#   F:pci/atiixp_modem.c:1.14->1.15 
#   F:pci/cs4281.c:1.69->1.70 
#   F:pci/es1938.c:1.45->1.46 
#   F:pci/es1968.c:1.82->1.83 
#   F:pci/intel8x0.c:1.190->1.191 
#   F:pci/intel8x0m.c:1.26->1.27 
#   F:pci/maestro3.c:1.68->1.69 
#   F:pci/via82xx.c:1.135->1.136 
#   F:pci/via82xx_modem.c:1.4->1.5 
#   F:pci/ali5451/ali5451.c:1.60->1.61 
#   F:pci/cs46xx/cs46xx_lib.c:1.93->1.94 
#   F:pci/hda/hda_codec.c:1.1->1.2 
#   F:pci/hda/hda_codec.h:1.1->1.2 
#   F:pci/hda/hda_intel.c:1.2->1.3 
#   F:pci/nm256/nm256.c:1.58->1.59 
#   F:pci/trident/trident_main.c:1.69->1.70 
#   F:pci/ymfpci/ymfpci_main.c:1.64->1.65 
#   F:pcmcia/pdaudiocf/pdaudiocf.c:1.11->1.12 
#   F:pcmcia/pdaudiocf/pdaudiocf.h:1.7->1.8 
#   F:pcmcia/pdaudiocf/pdaudiocf_core.c:1.6->1.7 
#   F:pcmcia/vx/vx_entry.c:1.8->1.9 
#   F:ppc/pmac.c:1.43->1.44 
#   L:Fixes by Pavel Machek <pavel@suse.cz>:
#   L:suspend() routines no longer get u32 as their parameter (they get
#   L:pm_message_t, which is u32 for now, but will change in 2.6.12 or
#   L:so). This fixes ALSA to notice this, and uses constants with right
#   L:types where appropriate. It results in no code changes. [Best results
#   L:will be when patching against latest -mm, you may get some warnings if
#   L:you patch it into older kernel, but it should still do the right
#   L:thing.] Please apply,
#   L:							Pavel
#   L:
#   L:[In addition, suspend callback type is changed to follow to the standard
#   L: style taking no state argument -- Takashi]
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/isa/cs423x/cs4231_lib.c
#   2005/01/28 12:34:05+01:00 perex@suse.cz +2 -2
#   [ALSA] driver model type fixes for ALSA
#   
#   D:2005/01/28 19:34:04
#   C:SA11xx UDA1341 driver,Control Midlevel,ALSA Core,Digigram VX core
#   C:ES18xx driver,OPL3SA2 driver,AD1848 driver,CS4231 driver,ATIIXP driver
#   C:ATIIXP-modem driver,CS4281 driver,ES1938 driver,ES1968 driver
#   C:Intel8x0 driver,Intel8x0-modem driver,Maestro3 driver,VIA82xx driver
#   C:VIA82xx-modem driver,ALI5451 driver,CS46xx driver,HDA Codec driver
#   C:HDA Intel driver,NM256 driver,Trident driver,YMFPCI driver
#   C:PDAudioCF driver,Digigram VX Pocket driver,PPC PMAC driver
#   F:arm/sa11xx-uda1341.c:1.20->1.21 
#   F:core/control.c:1.56->1.57 
#   F:core/init.c:1.58->1.59 
#   F:drivers/vx/vx_core.c:1.14->1.15 
#   F:include/core.h:1.65->1.66 
#   F:isa/es18xx.c:1.53->1.54 
#   F:isa/opl3sa2.c:1.42->1.43 
#   F:isa/ad1848/ad1848_lib.c:1.39->1.40 
#   F:isa/cs423x/cs4231_lib.c:1.47->1.48 
#   F:pci/atiixp.c:1.31->1.32 
#   F:pci/atiixp_modem.c:1.14->1.15 
#   F:pci/cs4281.c:1.69->1.70 
#   F:pci/es1938.c:1.45->1.46 
#   F:pci/es1968.c:1.82->1.83 
#   F:pci/intel8x0.c:1.190->1.191 
#   F:pci/intel8x0m.c:1.26->1.27 
#   F:pci/maestro3.c:1.68->1.69 
#   F:pci/via82xx.c:1.135->1.136 
#   F:pci/via82xx_modem.c:1.4->1.5 
#   F:pci/ali5451/ali5451.c:1.60->1.61 
#   F:pci/cs46xx/cs46xx_lib.c:1.93->1.94 
#   F:pci/hda/hda_codec.c:1.1->1.2 
#   F:pci/hda/hda_codec.h:1.1->1.2 
#   F:pci/hda/hda_intel.c:1.2->1.3 
#   F:pci/nm256/nm256.c:1.58->1.59 
#   F:pci/trident/trident_main.c:1.69->1.70 
#   F:pci/ymfpci/ymfpci_main.c:1.64->1.65 
#   F:pcmcia/pdaudiocf/pdaudiocf.c:1.11->1.12 
#   F:pcmcia/pdaudiocf/pdaudiocf.h:1.7->1.8 
#   F:pcmcia/pdaudiocf/pdaudiocf_core.c:1.6->1.7 
#   F:pcmcia/vx/vx_entry.c:1.8->1.9 
#   F:ppc/pmac.c:1.43->1.44 
#   L:Fixes by Pavel Machek <pavel@suse.cz>:
#   L:suspend() routines no longer get u32 as their parameter (they get
#   L:pm_message_t, which is u32 for now, but will change in 2.6.12 or
#   L:so). This fixes ALSA to notice this, and uses constants with right
#   L:types where appropriate. It results in no code changes. [Best results
#   L:will be when patching against latest -mm, you may get some warnings if
#   L:you patch it into older kernel, but it should still do the right
#   L:thing.] Please apply,
#   L:							Pavel
#   L:
#   L:[In addition, suspend callback type is changed to follow to the standard
#   L: style taking no state argument -- Takashi]
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/isa/ad1848/ad1848_lib.c
#   2005/01/28 12:34:05+01:00 perex@suse.cz +2 -2
#   [ALSA] driver model type fixes for ALSA
#   
#   D:2005/01/28 19:34:04
#   C:SA11xx UDA1341 driver,Control Midlevel,ALSA Core,Digigram VX core
#   C:ES18xx driver,OPL3SA2 driver,AD1848 driver,CS4231 driver,ATIIXP driver
#   C:ATIIXP-modem driver,CS4281 driver,ES1938 driver,ES1968 driver
#   C:Intel8x0 driver,Intel8x0-modem driver,Maestro3 driver,VIA82xx driver
#   C:VIA82xx-modem driver,ALI5451 driver,CS46xx driver,HDA Codec driver
#   C:HDA Intel driver,NM256 driver,Trident driver,YMFPCI driver
#   C:PDAudioCF driver,Digigram VX Pocket driver,PPC PMAC driver
#   F:arm/sa11xx-uda1341.c:1.20->1.21 
#   F:core/control.c:1.56->1.57 
#   F:core/init.c:1.58->1.59 
#   F:drivers/vx/vx_core.c:1.14->1.15 
#   F:include/core.h:1.65->1.66 
#   F:isa/es18xx.c:1.53->1.54 
#   F:isa/opl3sa2.c:1.42->1.43 
#   F:isa/ad1848/ad1848_lib.c:1.39->1.40 
#   F:isa/cs423x/cs4231_lib.c:1.47->1.48 
#   F:pci/atiixp.c:1.31->1.32 
#   F:pci/atiixp_modem.c:1.14->1.15 
#   F:pci/cs4281.c:1.69->1.70 
#   F:pci/es1938.c:1.45->1.46 
#   F:pci/es1968.c:1.82->1.83 
#   F:pci/intel8x0.c:1.190->1.191 
#   F:pci/intel8x0m.c:1.26->1.27 
#   F:pci/maestro3.c:1.68->1.69 
#   F:pci/via82xx.c:1.135->1.136 
#   F:pci/via82xx_modem.c:1.4->1.5 
#   F:pci/ali5451/ali5451.c:1.60->1.61 
#   F:pci/cs46xx/cs46xx_lib.c:1.93->1.94 
#   F:pci/hda/hda_codec.c:1.1->1.2 
#   F:pci/hda/hda_codec.h:1.1->1.2 
#   F:pci/hda/hda_intel.c:1.2->1.3 
#   F:pci/nm256/nm256.c:1.58->1.59 
#   F:pci/trident/trident_main.c:1.69->1.70 
#   F:pci/ymfpci/ymfpci_main.c:1.64->1.65 
#   F:pcmcia/pdaudiocf/pdaudiocf.c:1.11->1.12 
#   F:pcmcia/pdaudiocf/pdaudiocf.h:1.7->1.8 
#   F:pcmcia/pdaudiocf/pdaudiocf_core.c:1.6->1.7 
#   F:pcmcia/vx/vx_entry.c:1.8->1.9 
#   F:ppc/pmac.c:1.43->1.44 
#   L:Fixes by Pavel Machek <pavel@suse.cz>:
#   L:suspend() routines no longer get u32 as their parameter (they get
#   L:pm_message_t, which is u32 for now, but will change in 2.6.12 or
#   L:so). This fixes ALSA to notice this, and uses constants with right
#   L:types where appropriate. It results in no code changes. [Best results
#   L:will be when patching against latest -mm, you may get some warnings if
#   L:you patch it into older kernel, but it should still do the right
#   L:thing.] Please apply,
#   L:							Pavel
#   L:
#   L:[In addition, suspend callback type is changed to follow to the standard
#   L: style taking no state argument -- Takashi]
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/drivers/vx/vx_core.c
#   2005/01/28 12:34:05+01:00 perex@suse.cz +2 -2
#   [ALSA] driver model type fixes for ALSA
#   
#   D:2005/01/28 19:34:04
#   C:SA11xx UDA1341 driver,Control Midlevel,ALSA Core,Digigram VX core
#   C:ES18xx driver,OPL3SA2 driver,AD1848 driver,CS4231 driver,ATIIXP driver
#   C:ATIIXP-modem driver,CS4281 driver,ES1938 driver,ES1968 driver
#   C:Intel8x0 driver,Intel8x0-modem driver,Maestro3 driver,VIA82xx driver
#   C:VIA82xx-modem driver,ALI5451 driver,CS46xx driver,HDA Codec driver
#   C:HDA Intel driver,NM256 driver,Trident driver,YMFPCI driver
#   C:PDAudioCF driver,Digigram VX Pocket driver,PPC PMAC driver
#   F:arm/sa11xx-uda1341.c:1.20->1.21 
#   F:core/control.c:1.56->1.57 
#   F:core/init.c:1.58->1.59 
#   F:drivers/vx/vx_core.c:1.14->1.15 
#   F:include/core.h:1.65->1.66 
#   F:isa/es18xx.c:1.53->1.54 
#   F:isa/opl3sa2.c:1.42->1.43 
#   F:isa/ad1848/ad1848_lib.c:1.39->1.40 
#   F:isa/cs423x/cs4231_lib.c:1.47->1.48 
#   F:pci/atiixp.c:1.31->1.32 
#   F:pci/atiixp_modem.c:1.14->1.15 
#   F:pci/cs4281.c:1.69->1.70 
#   F:pci/es1938.c:1.45->1.46 
#   F:pci/es1968.c:1.82->1.83 
#   F:pci/intel8x0.c:1.190->1.191 
#   F:pci/intel8x0m.c:1.26->1.27 
#   F:pci/maestro3.c:1.68->1.69 
#   F:pci/via82xx.c:1.135->1.136 
#   F:pci/via82xx_modem.c:1.4->1.5 
#   F:pci/ali5451/ali5451.c:1.60->1.61 
#   F:pci/cs46xx/cs46xx_lib.c:1.93->1.94 
#   F:pci/hda/hda_codec.c:1.1->1.2 
#   F:pci/hda/hda_codec.h:1.1->1.2 
#   F:pci/hda/hda_intel.c:1.2->1.3 
#   F:pci/nm256/nm256.c:1.58->1.59 
#   F:pci/trident/trident_main.c:1.69->1.70 
#   F:pci/ymfpci/ymfpci_main.c:1.64->1.65 
#   F:pcmcia/pdaudiocf/pdaudiocf.c:1.11->1.12 
#   F:pcmcia/pdaudiocf/pdaudiocf.h:1.7->1.8 
#   F:pcmcia/pdaudiocf/pdaudiocf_core.c:1.6->1.7 
#   F:pcmcia/vx/vx_entry.c:1.8->1.9 
#   F:ppc/pmac.c:1.43->1.44 
#   L:Fixes by Pavel Machek <pavel@suse.cz>:
#   L:suspend() routines no longer get u32 as their parameter (they get
#   L:pm_message_t, which is u32 for now, but will change in 2.6.12 or
#   L:so). This fixes ALSA to notice this, and uses constants with right
#   L:types where appropriate. It results in no code changes. [Best results
#   L:will be when patching against latest -mm, you may get some warnings if
#   L:you patch it into older kernel, but it should still do the right
#   L:thing.] Please apply,
#   L:							Pavel
#   L:
#   L:[In addition, suspend callback type is changed to follow to the standard
#   L: style taking no state argument -- Takashi]
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/core/init.c
#   2005/01/28 12:34:04+01:00 perex@suse.cz +7 -11
#   [ALSA] driver model type fixes for ALSA
#   
#   D:2005/01/28 19:34:04
#   C:SA11xx UDA1341 driver,Control Midlevel,ALSA Core,Digigram VX core
#   C:ES18xx driver,OPL3SA2 driver,AD1848 driver,CS4231 driver,ATIIXP driver
#   C:ATIIXP-modem driver,CS4281 driver,ES1938 driver,ES1968 driver
#   C:Intel8x0 driver,Intel8x0-modem driver,Maestro3 driver,VIA82xx driver
#   C:VIA82xx-modem driver,ALI5451 driver,CS46xx driver,HDA Codec driver
#   C:HDA Intel driver,NM256 driver,Trident driver,YMFPCI driver
#   C:PDAudioCF driver,Digigram VX Pocket driver,PPC PMAC driver
#   F:arm/sa11xx-uda1341.c:1.20->1.21 
#   F:core/control.c:1.56->1.57 
#   F:core/init.c:1.58->1.59 
#   F:drivers/vx/vx_core.c:1.14->1.15 
#   F:include/core.h:1.65->1.66 
#   F:isa/es18xx.c:1.53->1.54 
#   F:isa/opl3sa2.c:1.42->1.43 
#   F:isa/ad1848/ad1848_lib.c:1.39->1.40 
#   F:isa/cs423x/cs4231_lib.c:1.47->1.48 
#   F:pci/atiixp.c:1.31->1.32 
#   F:pci/atiixp_modem.c:1.14->1.15 
#   F:pci/cs4281.c:1.69->1.70 
#   F:pci/es1938.c:1.45->1.46 
#   F:pci/es1968.c:1.82->1.83 
#   F:pci/intel8x0.c:1.190->1.191 
#   F:pci/intel8x0m.c:1.26->1.27 
#   F:pci/maestro3.c:1.68->1.69 
#   F:pci/via82xx.c:1.135->1.136 
#   F:pci/via82xx_modem.c:1.4->1.5 
#   F:pci/ali5451/ali5451.c:1.60->1.61 
#   F:pci/cs46xx/cs46xx_lib.c:1.93->1.94 
#   F:pci/hda/hda_codec.c:1.1->1.2 
#   F:pci/hda/hda_codec.h:1.1->1.2 
#   F:pci/hda/hda_intel.c:1.2->1.3 
#   F:pci/nm256/nm256.c:1.58->1.59 
#   F:pci/trident/trident_main.c:1.69->1.70 
#   F:pci/ymfpci/ymfpci_main.c:1.64->1.65 
#   F:pcmcia/pdaudiocf/pdaudiocf.c:1.11->1.12 
#   F:pcmcia/pdaudiocf/pdaudiocf.h:1.7->1.8 
#   F:pcmcia/pdaudiocf/pdaudiocf_core.c:1.6->1.7 
#   F:pcmcia/vx/vx_entry.c:1.8->1.9 
#   F:ppc/pmac.c:1.43->1.44 
#   L:Fixes by Pavel Machek <pavel@suse.cz>:
#   L:suspend() routines no longer get u32 as their parameter (they get
#   L:pm_message_t, which is u32 for now, but will change in 2.6.12 or
#   L:so). This fixes ALSA to notice this, and uses constants with right
#   L:types where appropriate. It results in no code changes. [Best results
#   L:will be when patching against latest -mm, you may get some warnings if
#   L:you patch it into older kernel, but it should still do the right
#   L:thing.] Please apply,
#   L:							Pavel
#   L:
#   L:[In addition, suspend callback type is changed to follow to the standard
#   L: style taking no state argument -- Takashi]
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/core/control.c
#   2005/01/28 12:34:04+01:00 perex@suse.cz +2 -4
#   [ALSA] driver model type fixes for ALSA
#   
#   D:2005/01/28 19:34:04
#   C:SA11xx UDA1341 driver,Control Midlevel,ALSA Core,Digigram VX core
#   C:ES18xx driver,OPL3SA2 driver,AD1848 driver,CS4231 driver,ATIIXP driver
#   C:ATIIXP-modem driver,CS4281 driver,ES1938 driver,ES1968 driver
#   C:Intel8x0 driver,Intel8x0-modem driver,Maestro3 driver,VIA82xx driver
#   C:VIA82xx-modem driver,ALI5451 driver,CS46xx driver,HDA Codec driver
#   C:HDA Intel driver,NM256 driver,Trident driver,YMFPCI driver
#   C:PDAudioCF driver,Digigram VX Pocket driver,PPC PMAC driver
#   F:arm/sa11xx-uda1341.c:1.20->1.21 
#   F:core/control.c:1.56->1.57 
#   F:core/init.c:1.58->1.59 
#   F:drivers/vx/vx_core.c:1.14->1.15 
#   F:include/core.h:1.65->1.66 
#   F:isa/es18xx.c:1.53->1.54 
#   F:isa/opl3sa2.c:1.42->1.43 
#   F:isa/ad1848/ad1848_lib.c:1.39->1.40 
#   F:isa/cs423x/cs4231_lib.c:1.47->1.48 
#   F:pci/atiixp.c:1.31->1.32 
#   F:pci/atiixp_modem.c:1.14->1.15 
#   F:pci/cs4281.c:1.69->1.70 
#   F:pci/es1938.c:1.45->1.46 
#   F:pci/es1968.c:1.82->1.83 
#   F:pci/intel8x0.c:1.190->1.191 
#   F:pci/intel8x0m.c:1.26->1.27 
#   F:pci/maestro3.c:1.68->1.69 
#   F:pci/via82xx.c:1.135->1.136 
#   F:pci/via82xx_modem.c:1.4->1.5 
#   F:pci/ali5451/ali5451.c:1.60->1.61 
#   F:pci/cs46xx/cs46xx_lib.c:1.93->1.94 
#   F:pci/hda/hda_codec.c:1.1->1.2 
#   F:pci/hda/hda_codec.h:1.1->1.2 
#   F:pci/hda/hda_intel.c:1.2->1.3 
#   F:pci/nm256/nm256.c:1.58->1.59 
#   F:pci/trident/trident_main.c:1.69->1.70 
#   F:pci/ymfpci/ymfpci_main.c:1.64->1.65 
#   F:pcmcia/pdaudiocf/pdaudiocf.c:1.11->1.12 
#   F:pcmcia/pdaudiocf/pdaudiocf.h:1.7->1.8 
#   F:pcmcia/pdaudiocf/pdaudiocf_core.c:1.6->1.7 
#   F:pcmcia/vx/vx_entry.c:1.8->1.9 
#   F:ppc/pmac.c:1.43->1.44 
#   L:Fixes by Pavel Machek <pavel@suse.cz>:
#   L:suspend() routines no longer get u32 as their parameter (they get
#   L:pm_message_t, which is u32 for now, but will change in 2.6.12 or
#   L:so). This fixes ALSA to notice this, and uses constants with right
#   L:types where appropriate. It results in no code changes. [Best results
#   L:will be when patching against latest -mm, you may get some warnings if
#   L:you patch it into older kernel, but it should still do the right
#   L:thing.] Please apply,
#   L:							Pavel
#   L:
#   L:[In addition, suspend callback type is changed to follow to the standard
#   L: style taking no state argument -- Takashi]
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/arm/sa11xx-uda1341.c
#   2005/01/28 12:34:04+01:00 perex@suse.cz +3 -3
#   [ALSA] driver model type fixes for ALSA
#   
#   D:2005/01/28 19:34:04
#   C:SA11xx UDA1341 driver,Control Midlevel,ALSA Core,Digigram VX core
#   C:ES18xx driver,OPL3SA2 driver,AD1848 driver,CS4231 driver,ATIIXP driver
#   C:ATIIXP-modem driver,CS4281 driver,ES1938 driver,ES1968 driver
#   C:Intel8x0 driver,Intel8x0-modem driver,Maestro3 driver,VIA82xx driver
#   C:VIA82xx-modem driver,ALI5451 driver,CS46xx driver,HDA Codec driver
#   C:HDA Intel driver,NM256 driver,Trident driver,YMFPCI driver
#   C:PDAudioCF driver,Digigram VX Pocket driver,PPC PMAC driver
#   F:arm/sa11xx-uda1341.c:1.20->1.21 
#   F:core/control.c:1.56->1.57 
#   F:core/init.c:1.58->1.59 
#   F:drivers/vx/vx_core.c:1.14->1.15 
#   F:include/core.h:1.65->1.66 
#   F:isa/es18xx.c:1.53->1.54 
#   F:isa/opl3sa2.c:1.42->1.43 
#   F:isa/ad1848/ad1848_lib.c:1.39->1.40 
#   F:isa/cs423x/cs4231_lib.c:1.47->1.48 
#   F:pci/atiixp.c:1.31->1.32 
#   F:pci/atiixp_modem.c:1.14->1.15 
#   F:pci/cs4281.c:1.69->1.70 
#   F:pci/es1938.c:1.45->1.46 
#   F:pci/es1968.c:1.82->1.83 
#   F:pci/intel8x0.c:1.190->1.191 
#   F:pci/intel8x0m.c:1.26->1.27 
#   F:pci/maestro3.c:1.68->1.69 
#   F:pci/via82xx.c:1.135->1.136 
#   F:pci/via82xx_modem.c:1.4->1.5 
#   F:pci/ali5451/ali5451.c:1.60->1.61 
#   F:pci/cs46xx/cs46xx_lib.c:1.93->1.94 
#   F:pci/hda/hda_codec.c:1.1->1.2 
#   F:pci/hda/hda_codec.h:1.1->1.2 
#   F:pci/hda/hda_intel.c:1.2->1.3 
#   F:pci/nm256/nm256.c:1.58->1.59 
#   F:pci/trident/trident_main.c:1.69->1.70 
#   F:pci/ymfpci/ymfpci_main.c:1.64->1.65 
#   F:pcmcia/pdaudiocf/pdaudiocf.c:1.11->1.12 
#   F:pcmcia/pdaudiocf/pdaudiocf.h:1.7->1.8 
#   F:pcmcia/pdaudiocf/pdaudiocf_core.c:1.6->1.7 
#   F:pcmcia/vx/vx_entry.c:1.8->1.9 
#   F:ppc/pmac.c:1.43->1.44 
#   L:Fixes by Pavel Machek <pavel@suse.cz>:
#   L:suspend() routines no longer get u32 as their parameter (they get
#   L:pm_message_t, which is u32 for now, but will change in 2.6.12 or
#   L:so). This fixes ALSA to notice this, and uses constants with right
#   L:types where appropriate. It results in no code changes. [Best results
#   L:will be when patching against latest -mm, you may get some warnings if
#   L:you patch it into older kernel, but it should still do the right
#   L:thing.] Please apply,
#   L:							Pavel
#   L:
#   L:[In addition, suspend callback type is changed to follow to the standard
#   L: style taking no state argument -- Takashi]
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# include/sound/core.h
#   2005/01/28 12:34:05+01:00 perex@suse.cz +7 -7
#   [ALSA] driver model type fixes for ALSA
#   
#   D:2005/01/28 19:34:04
#   C:SA11xx UDA1341 driver,Control Midlevel,ALSA Core,Digigram VX core
#   C:ES18xx driver,OPL3SA2 driver,AD1848 driver,CS4231 driver,ATIIXP driver
#   C:ATIIXP-modem driver,CS4281 driver,ES1938 driver,ES1968 driver
#   C:Intel8x0 driver,Intel8x0-modem driver,Maestro3 driver,VIA82xx driver
#   C:VIA82xx-modem driver,ALI5451 driver,CS46xx driver,HDA Codec driver
#   C:HDA Intel driver,NM256 driver,Trident driver,YMFPCI driver
#   C:PDAudioCF driver,Digigram VX Pocket driver,PPC PMAC driver
#   F:arm/sa11xx-uda1341.c:1.20->1.21 
#   F:core/control.c:1.56->1.57 
#   F:core/init.c:1.58->1.59 
#   F:drivers/vx/vx_core.c:1.14->1.15 
#   F:include/core.h:1.65->1.66 
#   F:isa/es18xx.c:1.53->1.54 
#   F:isa/opl3sa2.c:1.42->1.43 
#   F:isa/ad1848/ad1848_lib.c:1.39->1.40 
#   F:isa/cs423x/cs4231_lib.c:1.47->1.48 
#   F:pci/atiixp.c:1.31->1.32 
#   F:pci/atiixp_modem.c:1.14->1.15 
#   F:pci/cs4281.c:1.69->1.70 
#   F:pci/es1938.c:1.45->1.46 
#   F:pci/es1968.c:1.82->1.83 
#   F:pci/intel8x0.c:1.190->1.191 
#   F:pci/intel8x0m.c:1.26->1.27 
#   F:pci/maestro3.c:1.68->1.69 
#   F:pci/via82xx.c:1.135->1.136 
#   F:pci/via82xx_modem.c:1.4->1.5 
#   F:pci/ali5451/ali5451.c:1.60->1.61 
#   F:pci/cs46xx/cs46xx_lib.c:1.93->1.94 
#   F:pci/hda/hda_codec.c:1.1->1.2 
#   F:pci/hda/hda_codec.h:1.1->1.2 
#   F:pci/hda/hda_intel.c:1.2->1.3 
#   F:pci/nm256/nm256.c:1.58->1.59 
#   F:pci/trident/trident_main.c:1.69->1.70 
#   F:pci/ymfpci/ymfpci_main.c:1.64->1.65 
#   F:pcmcia/pdaudiocf/pdaudiocf.c:1.11->1.12 
#   F:pcmcia/pdaudiocf/pdaudiocf.h:1.7->1.8 
#   F:pcmcia/pdaudiocf/pdaudiocf_core.c:1.6->1.7 
#   F:pcmcia/vx/vx_entry.c:1.8->1.9 
#   F:ppc/pmac.c:1.43->1.44 
#   L:Fixes by Pavel Machek <pavel@suse.cz>:
#   L:suspend() routines no longer get u32 as their parameter (they get
#   L:pm_message_t, which is u32 for now, but will change in 2.6.12 or
#   L:so). This fixes ALSA to notice this, and uses constants with right
#   L:types where appropriate. It results in no code changes. [Best results
#   L:will be when patching against latest -mm, you may get some warnings if
#   L:you patch it into older kernel, but it should still do the right
#   L:thing.] Please apply,
#   L:							Pavel
#   L:
#   L:[In addition, suspend callback type is changed to follow to the standard
#   L: style taking no state argument -- Takashi]
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2005/02/14 14:40:49+01:00 perex@suse.cz 
#   [ALSA] use cached idVendor/idProduct values
#   
#   USB generic driver
#   use the vendor/product IDs in the state structure instead of
#   reading them again from the device
#   
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# sound/usb/usbmixer.c
#   2005/01/28 10:48:14+01:00 perex@suse.cz +1 -1
#   [ALSA] use cached idVendor/idProduct values
#   
#   D:2005/01/28 17:48:14
#   C:USB generic driver
#   F:usb/usbmixer.c:1.35->1.36 
#   L:use the vendor/product IDs in the state structure instead of
#   L:reading them again from the device
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# ChangeSet
#   2005/02/14 14:39:40+01:00 perex@suse.cz 
#   [ALSA] Set default index of modem and bt87x drivers to -2
#   
#   Documentation,ATIIXP-modem driver,BT87x driver,Intel8x0-modem driver
#   VIA82xx-modem driver
#   Set the default index value of modem and bt87x drivers to -2 so that
#   the first slot is excluded when no index option is given.
#   This gives other uadio drivers a chance to put them as the primary
#   driver.
#   
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/via82xx_modem.c
#   2005/01/28 10:02:15+01:00 perex@suse.cz +1 -1
#   [ALSA] Set default index of modem and bt87x drivers to -2
#   
#   D:2005/01/28 17:02:13
#   C:Documentation,ATIIXP-modem driver,BT87x driver,Intel8x0-modem driver
#   C:VIA82xx-modem driver
#   F:Documentation/ALSA-Configuration.txt:1.67->1.68 
#   F:pci/atiixp_modem.c:1.13->1.14 
#   F:pci/bt87x.c:1.18->1.19 
#   F:pci/intel8x0m.c:1.25->1.26 
#   F:pci/via82xx_modem.c:1.3->1.4 
#   L:Set the default index value of modem and bt87x drivers to -2 so that
#   L:the first slot is excluded when no index option is given.
#   L:This gives other uadio drivers a chance to put them as the primary
#   L:driver.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/intel8x0m.c
#   2005/01/28 10:02:15+01:00 perex@suse.cz +1 -1
#   [ALSA] Set default index of modem and bt87x drivers to -2
#   
#   D:2005/01/28 17:02:13
#   C:Documentation,ATIIXP-modem driver,BT87x driver,Intel8x0-modem driver
#   C:VIA82xx-modem driver
#   F:Documentation/ALSA-Configuration.txt:1.67->1.68 
#   F:pci/atiixp_modem.c:1.13->1.14 
#   F:pci/bt87x.c:1.18->1.19 
#   F:pci/intel8x0m.c:1.25->1.26 
#   F:pci/via82xx_modem.c:1.3->1.4 
#   L:Set the default index value of modem and bt87x drivers to -2 so that
#   L:the first slot is excluded when no index option is given.
#   L:This gives other uadio drivers a chance to put them as the primary
#   L:driver.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/bt87x.c
#   2005/01/28 10:02:15+01:00 perex@suse.cz +1 -1
#   [ALSA] Set default index of modem and bt87x drivers to -2
#   
#   D:2005/01/28 17:02:13
#   C:Documentation,ATIIXP-modem driver,BT87x driver,Intel8x0-modem driver
#   C:VIA82xx-modem driver
#   F:Documentation/ALSA-Configuration.txt:1.67->1.68 
#   F:pci/atiixp_modem.c:1.13->1.14 
#   F:pci/bt87x.c:1.18->1.19 
#   F:pci/intel8x0m.c:1.25->1.26 
#   F:pci/via82xx_modem.c:1.3->1.4 
#   L:Set the default index value of modem and bt87x drivers to -2 so that
#   L:the first slot is excluded when no index option is given.
#   L:This gives other uadio drivers a chance to put them as the primary
#   L:driver.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/atiixp_modem.c
#   2005/01/28 10:02:14+01:00 perex@suse.cz +1 -1
#   [ALSA] Set default index of modem and bt87x drivers to -2
#   
#   D:2005/01/28 17:02:13
#   C:Documentation,ATIIXP-modem driver,BT87x driver,Intel8x0-modem driver
#   C:VIA82xx-modem driver
#   F:Documentation/ALSA-Configuration.txt:1.67->1.68 
#   F:pci/atiixp_modem.c:1.13->1.14 
#   F:pci/bt87x.c:1.18->1.19 
#   F:pci/intel8x0m.c:1.25->1.26 
#   F:pci/via82xx_modem.c:1.3->1.4 
#   L:Set the default index value of modem and bt87x drivers to -2 so that
#   L:the first slot is excluded when no index option is given.
#   L:This gives other uadio drivers a chance to put them as the primary
#   L:driver.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# Documentation/sound/alsa/ALSA-Configuration.txt
#   2005/01/28 10:02:13+01:00 perex@suse.cz +12 -0
#   [ALSA] Set default index of modem and bt87x drivers to -2
#   
#   D:2005/01/28 17:02:13
#   C:Documentation,ATIIXP-modem driver,BT87x driver,Intel8x0-modem driver
#   C:VIA82xx-modem driver
#   F:Documentation/ALSA-Configuration.txt:1.67->1.68 
#   F:pci/atiixp_modem.c:1.13->1.14 
#   F:pci/bt87x.c:1.18->1.19 
#   F:pci/intel8x0m.c:1.25->1.26 
#   F:pci/via82xx_modem.c:1.3->1.4 
#   L:Set the default index value of modem and bt87x drivers to -2 so that
#   L:the first slot is excluded when no index option is given.
#   L:This gives other uadio drivers a chance to put them as the primary
#   L:driver.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2005/02/14 14:38:31+01:00 perex@suse.cz 
#   [ALSA] Interpret negative index as bitmask of permissible indexes
#   
#   Documentation,ALSA Core
#   Currently arguments of the 'index' option from 0 through SNDRV_CARDS-1
#   force a module to take the specified index. Index -1 makes the module
#   take the first available index. This patch extends this convention so
#   that a negative index value is interpreted as a bitmask of the
#   permitted indexes. Special cases:
#   
#       -1 0xffffffff 0 and up
#       -2 0xfffffffe 1 and up
#       -4 0xfffffffc 2 and up
#       ...
#   
#   The patch includes also corrections of ALSA-Configuration.txt document.
#   
#   Signed-off-by: Thomas Hood <jdthood@yahoo.co.uk>
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/core/init.c
#   2005/01/28 09:55:34+01:00 perex@suse.cz +4 -7
#   [ALSA] Interpret negative index as bitmask of permissible indexes
#   
#   D:2005/01/28 16:55:33
#   C:Documentation,ALSA Core
#   F:Documentation/ALSA-Configuration.txt:1.66->1.67 
#   F:core/init.c:1.57->1.58 
#   L:Currently arguments of the 'index' option from 0 through SNDRV_CARDS-1
#   L:force a module to take the specified index. Index -1 makes the module
#   L:take the first available index. This patch extends this convention so
#   L:that a negative index value is interpreted as a bitmask of the
#   L:permitted indexes. Special cases:
#   L:
#   L:    -1 0xffffffff 0 and up
#   L:    -2 0xfffffffe 1 and up
#   L:    -4 0xfffffffc 2 and up
#   L:    ...
#   L:
#   L:The patch includes also corrections of ALSA-Configuration.txt document.
#   Signed-off-by: Thomas Hood <jdthood@yahoo.co.uk>
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# Documentation/sound/alsa/ALSA-Configuration.txt
#   2005/01/28 09:55:33+01:00 perex@suse.cz +114 -107
#   [ALSA] Interpret negative index as bitmask of permissible indexes
#   
#   D:2005/01/28 16:55:33
#   C:Documentation,ALSA Core
#   F:Documentation/ALSA-Configuration.txt:1.66->1.67 
#   F:core/init.c:1.57->1.58 
#   L:Currently arguments of the 'index' option from 0 through SNDRV_CARDS-1
#   L:force a module to take the specified index. Index -1 makes the module
#   L:take the first available index. This patch extends this convention so
#   L:that a negative index value is interpreted as a bitmask of the
#   L:permitted indexes. Special cases:
#   L:
#   L:    -1 0xffffffff 0 and up
#   L:    -2 0xfffffffe 1 and up
#   L:    -4 0xfffffffc 2 and up
#   L:    ...
#   L:
#   L:The patch includes also corrections of ALSA-Configuration.txt document.
#   Signed-off-by: Thomas Hood <jdthood@yahoo.co.uk>
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2005/02/14 14:37:21+01:00 perex@suse.cz 
#   [ALSA] Changes 'Music' to 'Synth' in mixer control names
#   
#   EMU10K1/EMU10K2 driver
#   Changes 'Music' to 'Synth' in mixer control names
#   
#   Signed-off-by: Lee Revell <rlrevell@joe-job.com>
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/emu10k1/emufx.c
#   2005/01/28 08:33:10+01:00 perex@suse.cz +9 -9
#   [ALSA] Changes 'Music' to 'Synth' in mixer control names
#   
#   D:2005/01/28 15:33:10
#   C:EMU10K1/EMU10K2 driver
#   F:pci/emu10k1/emufx.c:1.66->1.67 
#   L:Changes 'Music' to 'Synth' in mixer control names
#   Signed-off-by: Lee Revell <rlrevell@joe-job.com>
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2005/02/14 14:36:10+01:00 perex@suse.cz 
#   [ALSA] HDSP fixes
#   
#   Documentation,RME HDSP driver
#   * init sequence cleanup and firmware upload related bugfixes
#   * more robust revision detection scheme
#     (should transparently handle new revisions)
#   * allow hdsploader and the kernel fw loader to coexist
#     this is useful for cardbus user who compiled the driver in-kernel
#     (userspace may not be ready to upload the firmware when the card
#      is probed)
#   * removed confusing and obsolete passthru option (was interfering
#     with the mixer when opening the device for capture or playback)
#     this change requires a recompile of the userspace tools against
#     the patched hdsp.h
#   * removed confusing and obsolete line_outs_monitor module param
#   * made precise_ptr the default behaviour, and runtime tweakable
#     (removed corresponding module param)
#   * add an alsa ctl to disable the use of the midi tasklet, and
#     process midi data in the interrupt handler
#     (using the tasklet is still the default)
#     this is mainly intended for users of Ingo Molnar's RT patch
#   * metering fix for Multiface/Digiface users (closes ALSA BUG #0000801)
#   * small endianness fix
#   * ALSA-Configuration.txt HDSP entry update
#   * error messages cleanup
#   
#   Signed-off-by: Thomas Charbonnel <thomas@undata.org>
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/rme9652/hdsp.c
#   2005/01/28 08:12:41+01:00 perex@suse.cz +235 -271
#   [ALSA] HDSP fixes
#   
#   D:2005/01/28 15:12:41
#   C:Documentation,RME HDSP driver
#   F:Documentation/ALSA-Configuration.txt:1.65->1.66 
#   F:pci/rme9652/hdsp.c:1.80->1.81 
#   L:* init sequence cleanup and firmware upload related bugfixes
#   L:* more robust revision detection scheme
#   L:  (should transparently handle new revisions)
#   L:* allow hdsploader and the kernel fw loader to coexist
#   L:  this is useful for cardbus user who compiled the driver in-kernel
#   L:  (userspace may not be ready to upload the firmware when the card
#   L:   is probed)
#   L:* removed confusing and obsolete passthru option (was interfering
#   L:  with the mixer when opening the device for capture or playback)
#   L:  this change requires a recompile of the userspace tools against
#   L:  the patched hdsp.h
#   L:* removed confusing and obsolete line_outs_monitor module param
#   L:* made precise_ptr the default behaviour, and runtime tweakable
#   L:  (removed corresponding module param)
#   L:* add an alsa ctl to disable the use of the midi tasklet, and
#   L:  process midi data in the interrupt handler
#   L:  (using the tasklet is still the default)
#   L:  this is mainly intended for users of Ingo Molnar's RT patch
#   L:* metering fix for Multiface/Digiface users (closes ALSA BUG #0000801)
#   L:* small endianness fix
#   L:* ALSA-Configuration.txt HDSP entry update
#   L:* error messages cleanup
#   Signed-off-by: Thomas Charbonnel <thomas@undata.org>
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# Documentation/sound/alsa/ALSA-Configuration.txt
#   2005/01/28 08:12:41+01:00 perex@suse.cz +0 -7
#   [ALSA] HDSP fixes
#   
#   D:2005/01/28 15:12:41
#   C:Documentation,RME HDSP driver
#   F:Documentation/ALSA-Configuration.txt:1.65->1.66 
#   F:pci/rme9652/hdsp.c:1.80->1.81 
#   L:* init sequence cleanup and firmware upload related bugfixes
#   L:* more robust revision detection scheme
#   L:  (should transparently handle new revisions)
#   L:* allow hdsploader and the kernel fw loader to coexist
#   L:  this is useful for cardbus user who compiled the driver in-kernel
#   L:  (userspace may not be ready to upload the firmware when the card
#   L:   is probed)
#   L:* removed confusing and obsolete passthru option (was interfering
#   L:  with the mixer when opening the device for capture or playback)
#   L:  this change requires a recompile of the userspace tools against
#   L:  the patched hdsp.h
#   L:* removed confusing and obsolete line_outs_monitor module param
#   L:* made precise_ptr the default behaviour, and runtime tweakable
#   L:  (removed corresponding module param)
#   L:* add an alsa ctl to disable the use of the midi tasklet, and
#   L:  process midi data in the interrupt handler
#   L:  (using the tasklet is still the default)
#   L:  this is mainly intended for users of Ingo Molnar's RT patch
#   L:* metering fix for Multiface/Digiface users (closes ALSA BUG #0000801)
#   L:* small endianness fix
#   L:* ALSA-Configuration.txt HDSP entry update
#   L:* error messages cleanup
#   Signed-off-by: Thomas Charbonnel <thomas@undata.org>
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2005/02/14 14:34:58+01:00 perex@suse.cz 
#   [ALSA] Remove pm_register/pm_unregister
#   
#   SA11xx UDA1341 driver,ALSA Core,ISA
#   Removed pm_register() and pm_unregister().
#   Use platform_device for suspend/resume, instead.
#   
#   The current implemention is still a hack.  The whole ISA drivers should
#   be rewritten with a proper bus definition.
#   
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/isa/Kconfig
#   2005/01/28 07:49:59+01:00 perex@suse.cz +6 -0
#   [ALSA] Remove pm_register/pm_unregister
#   
#   D:2005/01/28 14:49:59
#   C:SA11xx UDA1341 driver,ALSA Core,ISA
#   F:arm/sa11xx-uda1341.c:1.19->1.20 
#   F:core/Kconfig:1.8->1.9 
#   F:core/init.c:1.56->1.57 
#   F:core/sound.c:1.72->1.73 
#   F:include/core.h:1.64->1.65 
#   F:isa/Kconfig:1.14->1.15 
#   L:Removed pm_register() and pm_unregister().
#   L:Use platform_device for suspend/resume, instead.
#   L:
#   L:The current implemention is still a hack.  The whole ISA drivers should
#   L:be rewritten with a proper bus definition.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/core/sound.c
#   2005/01/28 07:49:59+01:00 perex@suse.cz +3 -1
#   [ALSA] Remove pm_register/pm_unregister
#   
#   D:2005/01/28 14:49:59
#   C:SA11xx UDA1341 driver,ALSA Core,ISA
#   F:arm/sa11xx-uda1341.c:1.19->1.20 
#   F:core/Kconfig:1.8->1.9 
#   F:core/init.c:1.56->1.57 
#   F:core/sound.c:1.72->1.73 
#   F:include/core.h:1.64->1.65 
#   F:isa/Kconfig:1.14->1.15 
#   L:Removed pm_register() and pm_unregister().
#   L:Use platform_device for suspend/resume, instead.
#   L:
#   L:The current implemention is still a hack.  The whole ISA drivers should
#   L:be rewritten with a proper bus definition.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/core/init.c
#   2005/01/28 07:49:59+01:00 perex@suse.cz +108 -26
#   [ALSA] Remove pm_register/pm_unregister
#   
#   D:2005/01/28 14:49:59
#   C:SA11xx UDA1341 driver,ALSA Core,ISA
#   F:arm/sa11xx-uda1341.c:1.19->1.20 
#   F:core/Kconfig:1.8->1.9 
#   F:core/init.c:1.56->1.57 
#   F:core/sound.c:1.72->1.73 
#   F:include/core.h:1.64->1.65 
#   F:isa/Kconfig:1.14->1.15 
#   L:Removed pm_register() and pm_unregister().
#   L:Use platform_device for suspend/resume, instead.
#   L:
#   L:The current implemention is still a hack.  The whole ISA drivers should
#   L:be rewritten with a proper bus definition.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/core/Kconfig
#   2005/01/28 07:49:59+01:00 perex@suse.cz +2 -0
#   [ALSA] Remove pm_register/pm_unregister
#   
#   D:2005/01/28 14:49:59
#   C:SA11xx UDA1341 driver,ALSA Core,ISA
#   F:arm/sa11xx-uda1341.c:1.19->1.20 
#   F:core/Kconfig:1.8->1.9 
#   F:core/init.c:1.56->1.57 
#   F:core/sound.c:1.72->1.73 
#   F:include/core.h:1.64->1.65 
#   F:isa/Kconfig:1.14->1.15 
#   L:Removed pm_register() and pm_unregister().
#   L:Use platform_device for suspend/resume, instead.
#   L:
#   L:The current implemention is still a hack.  The whole ISA drivers should
#   L:be rewritten with a proper bus definition.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/arm/sa11xx-uda1341.c
#   2005/01/28 07:49:59+01:00 perex@suse.cz +2 -2
#   [ALSA] Remove pm_register/pm_unregister
#   
#   D:2005/01/28 14:49:59
#   C:SA11xx UDA1341 driver,ALSA Core,ISA
#   F:arm/sa11xx-uda1341.c:1.19->1.20 
#   F:core/Kconfig:1.8->1.9 
#   F:core/init.c:1.56->1.57 
#   F:core/sound.c:1.72->1.73 
#   F:include/core.h:1.64->1.65 
#   F:isa/Kconfig:1.14->1.15 
#   L:Removed pm_register() and pm_unregister().
#   L:Use platform_device for suspend/resume, instead.
#   L:
#   L:The current implemention is still a hack.  The whole ISA drivers should
#   L:be rewritten with a proper bus definition.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# include/sound/core.h
#   2005/01/28 07:49:59+01:00 perex@suse.cz +15 -15
#   [ALSA] Remove pm_register/pm_unregister
#   
#   D:2005/01/28 14:49:59
#   C:SA11xx UDA1341 driver,ALSA Core,ISA
#   F:arm/sa11xx-uda1341.c:1.19->1.20 
#   F:core/Kconfig:1.8->1.9 
#   F:core/init.c:1.56->1.57 
#   F:core/sound.c:1.72->1.73 
#   F:include/core.h:1.64->1.65 
#   F:isa/Kconfig:1.14->1.15 
#   L:Removed pm_register() and pm_unregister().
#   L:Use platform_device for suspend/resume, instead.
#   L:
#   L:The current implemention is still a hack.  The whole ISA drivers should
#   L:be rewritten with a proper bus definition.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2005/02/14 14:33:45+01:00 perex@suse.cz 
#   [ALSA] Remove descriptions of obsolete options
#   
#   Documentation
#   Removed descriptions of obsolete irq_mask and irq_list options for
#   vxpocket, vxp440 and pdaudiocf drivers.
#   
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# Documentation/sound/alsa/ALSA-Configuration.txt
#   2005/01/28 07:42:55+01:00 perex@suse.cz +0 -16
#   [ALSA] Remove descriptions of obsolete options
#   
#   D:2005/01/28 14:42:55
#   C:Documentation
#   F:Documentation/ALSA-Configuration.txt:1.64->1.65 
#   L:Removed descriptions of obsolete irq_mask and irq_list options for
#   L:vxpocket, vxp440 and pdaudiocf drivers.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2005/02/14 14:32:27+01:00 perex@suse.cz 
#   [ALSA] Ascii chars only
#   
#   RME HDSP driver
#   
#   
#   Signed-off-by: Jaroslav Kysela <perex@suse.cz>
# 
# sound/pci/rme9652/hdsp.c
#   2005/02/14 14:31:38+01:00 perex@suse.cz +1 -1
#   [ALSA] Ascii chars only
#   
#   D:2005/01/28 10:13:37
#   C:RME HDSP driver
#   F:pci/rme9652/hdsp.c:1.79->1.80 
#   L:
#   Signed-off-by: Jaroslav Kysela <perex@suse.cz>
# 
# ChangeSet
#   2005/02/14 14:28:53+01:00 perex@suse.cz 
#   [ALSA] Add newline to printk
#       
#   ALSA Core
#   Added the newline to printk error output.
#       
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/core/init.c
#   2005/01/25 07:27:34+01:00 perex@suse.cz +1 -1
#   [ALSA] Add newline to printk
#   
#   ALSA Core
#   Added the newline to printk error output.
#   
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2005/02/14 07:59:28+01:00 dtor_core@ameritech.net 
#   Input: psmouse should probe for "special" protocols only if max
#          protocol is greater than IMEX so that proto=imps and    
#          proto=exps options work. Fix Kensington case.       
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/mouse/psmouse-base.c
#   2005/02/14 07:59:16+01:00 dtor_core@ameritech.net +1 -1
#   Input: psmouse should probe for "special" protocols only if max
#          protocol is greater than IMEX so that proto=imps and    
#          proto=exps options work. Fix Kensington case.       
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# ChangeSet
#   2005/02/13 18:58:47+01:00 petero2@telia.com 
#   input: Store alps hardware version info in the input_dev structure, so that
#          it shows up in /proc/bus/input/devices.
#    
#   Signed-off-by: Peter Osterlund <petero2@telia.com>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/mouse/psmouse.h
#   2005/02/13 18:58:36+01:00 petero2@telia.com +1 -1
#   input: Store alps hardware version info in the input_dev structure, so that
#          it shows up in /proc/bus/input/devices.
#    
#   Signed-off-by: Peter Osterlund <petero2@telia.com>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/mouse/alps.c
#   2005/02/13 18:58:36+01:00 petero2@telia.com +13 -4
#   input: Store alps hardware version info in the input_dev structure, so that
#          it shows up in /proc/bus/input/devices.
#    
#   Signed-off-by: Peter Osterlund <petero2@telia.com>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# ChangeSet
#   2005/02/13 12:50:34-05:00 nacc@us.ibm.com 
#   [PATCH] net/s2io: replace schedule_timeout() with msleep()
#   
#   Use msleep() instead of schedule_timeout() to guarantee the task delays
#   as expected. This makes the code independent of HZ values (particularly
#   important when HZ changes or is dynamic). Compile- and boot-tested.
#   
#   Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
#   Acked-by: Ravinandan Arakali <ravinandan.arakali@neterion.com>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/s2io.c
#   2005/02/09 14:08:48-05:00 nacc@us.ibm.com +18 -35
#   net/s2io: replace schedule_timeout() with msleep()
# 
# ChangeSet
#   2005/02/12 20:10:55+01:00 vojtech@suse.cz 
#   input: HID list handling cleanup, fix two bugs in pid.c and one in hid-core.c
#          that the cleanup uncovered. Remove a workaround for BTC keyboard 
#          46e:5303, because it's breaking other devices. Instead enable
#          QUIRK_NOGET for this keyboard.
#          Change set_idle handling to use a '0' report ID, meaning all reports
#          instead of iterating over each individual report ID. This shouldn't
#          change much, since most normal devices have only one report with
#          id '0'.
#   
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/usb/input/pid.c
#   2005/02/12 20:10:38+01:00 vojtech@suse.cz +5 -5
#   input: HID list handling cleanup, fix two bugs in pid.c and one in hid-core.c
#          that the cleanup uncovered. Remove a workaround for BTC keyboard 
#          46e:5303, because it's breaking other devices. Instead enable
#          QUIRK_NOGET for this keyboard.
#          Change set_idle handling to use a '0' report ID, meaning all reports
#          instead of iterating over each individual report ID. This shouldn't
#          change much, since most normal devices have only one report with
#          id '0'.
#   
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/usb/input/hiddev.c
#   2005/02/12 20:10:38+01:00 vojtech@suse.cz +2 -6
#   input: HID list handling cleanup, fix two bugs in pid.c and one in hid-core.c
#          that the cleanup uncovered. Remove a workaround for BTC keyboard 
#          46e:5303, because it's breaking other devices. Instead enable
#          QUIRK_NOGET for this keyboard.
#          Change set_idle handling to use a '0' report ID, meaning all reports
#          instead of iterating over each individual report ID. This shouldn't
#          change much, since most normal devices have only one report with
#          id '0'.
#   
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/usb/input/hid.h
#   2005/02/12 20:10:38+01:00 vojtech@suse.cz +1 -2
#   input: HID list handling cleanup, fix two bugs in pid.c and one in hid-core.c
#          that the cleanup uncovered. Remove a workaround for BTC keyboard 
#          46e:5303, because it's breaking other devices. Instead enable
#          QUIRK_NOGET for this keyboard.
#          Change set_idle handling to use a '0' report ID, meaning all reports
#          instead of iterating over each individual report ID. This shouldn't
#          change much, since most normal devices have only one report with
#          id '0'.
#   
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/usb/input/hid-input.c
#   2005/02/12 20:10:38+01:00 vojtech@suse.cz +21 -15
#   input: HID list handling cleanup, fix two bugs in pid.c and one in hid-core.c
#          that the cleanup uncovered. Remove a workaround for BTC keyboard 
#          46e:5303, because it's breaking other devices. Instead enable
#          QUIRK_NOGET for this keyboard.
#          Change set_idle handling to use a '0' report ID, meaning all reports
#          instead of iterating over each individual report ID. This shouldn't
#          change much, since most normal devices have only one report with
#          id '0'.
#   
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/usb/input/hid-core.c
#   2005/02/12 20:10:38+01:00 vojtech@suse.cz +20 -92
#   input: HID list handling cleanup, fix two bugs in pid.c and one in hid-core.c
#          that the cleanup uncovered. Remove a workaround for BTC keyboard 
#          46e:5303, because it's breaking other devices. Instead enable
#          QUIRK_NOGET for this keyboard.
#          Change set_idle handling to use a '0' report ID, meaning all reports
#          instead of iterating over each individual report ID. This shouldn't
#          change much, since most normal devices have only one report with
#          id '0'.
#   
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# ChangeSet
#   2005/02/12 20:05:32+01:00 vojtech@suse.cz 
#   input: Add pin numbers to parkbd.c documentation.
#   
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/serio/parkbd.c
#   2005/02/12 20:05:21+01:00 vojtech@suse.cz +8 -8
#   input: Add pin numbers to parkbd.c documentation.
#   
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# ChangeSet
#   2005/02/12 08:18:35+01:00 davej@redhat.com 
#   input: Looks like someone forgot the ARCH_
#   
#   Signed-off-by: Dave Jones <davej@redhat.com>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/char/keyboard.c
#   2005/02/12 08:18:24+01:00 davej@redhat.com +1 -1
#   input: Looks like someone forgot the ARCH_
#   
#   Signed-off-by: Dave Jones <davej@redhat.com>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# ChangeSet
#   2005/02/11 16:59:53-05:00 andi@cosy.sbg.ac.at 
#   [PATCH] sundance: attempt to address high irqs due to TX overflow
#   
#   In at least some versions of Kernel 2.6 (2.6.8.1, 2.6.11-rc2)
#   the driver drivers/net/sundance.c creates high interrupt load
#   (~ 100 interrupts per second) even in case of no network traffic
#   at all.
#   
#   It seems that some sort of TX overflow handling is misplaced
#   and triggers interrupts very often even in case of no data to
#   send. The TX overflow handling has been moved to a more
#   appropriate place.
#   
#   While there, an off by one error of reading the TX status has
#   also been corrected by moving the read after the break.
#   
#   Thanks to Jeroen who tested the patch (also with high workload).
#   Interrupts are down to normal and there are no obvious side
#   effects.
# 
# drivers/net/sundance.c
#   2005/02/11 16:59:47-05:00 andi@cosy.sbg.ac.at +4 -3
#   [PATCH] sundance: attempt to address high irqs due to TX overflow
#   
#   In at least some versions of Kernel 2.6 (2.6.8.1, 2.6.11-rc2)
#   the driver drivers/net/sundance.c creates high interrupt load
#   (~ 100 interrupts per second) even in case of no network traffic
#   at all.
#   
#   It seems that some sort of TX overflow handling is misplaced
#   and triggers interrupts very often even in case of no data to
#   send. The TX overflow handling has been moved to a more
#   appropriate place.
#   
#   While there, an off by one error of reading the TX status has
#   also been corrected by moving the read after the break.
#   
#   Thanks to Jeroen who tested the patch (also with high workload).
#   Interrupts are down to normal and there are no obvious side
#   effects.
# 
# ChangeSet
#   2005/02/11 16:55:06-05:00 fubar@us.ibm.com 
#   [PATCH] bonding: Update/rewrite bonding.txt
#   
#   	This is a complete overhaul of the bonding.txt documentation.
#   
#   Signed-off-by: Jay Vosburgh <fubar@us.ibm.com>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# Documentation/networking/bonding.txt
#   2005/02/11 04:44:37-05:00 fubar@us.ibm.com +1367 -741
#   bonding: Update/rewrite bonding.txt
# 
# ChangeSet
#   2005/02/11 16:54:54-05:00 fubar@us.ibm.com 
#   [PATCH] bonding: Update kconfig description
#   
#   This patch updates the very-outdated Kconfig description for bonding.
#   Users reading the help text in menuconfig or xconfig would see text that
#   implied that bonding only supports static link aggregation, and required a
#   specific switch to make it work.  The new description mentions multiple
#   bonding modes and points the user to the bonding.txt documentation.
#   
#   Signed-off-by:  Mitch Williams <mitch.a.williams@intel.com>
#   Signed-off-by: Jay Vosburgh <fubar@us.ibm.com>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/Kconfig
#   2005/02/08 17:05:06-05:00 fubar@us.ibm.com +5 -8
#   bonding: Update kconfig description
# 
# ChangeSet
#   2005/02/11 16:54:40-05:00 fubar@us.ibm.com 
#   [PATCH] bonding: change misleading warning
#   
#   	This updates a warning message that the bonding driver issues
#   when some modes are unable to determine the link speed of a slave
#   device.  The old message led users to believe that bonding was slowing
#   their gigabit devices to 100 Mb/sec.
#   
#   Signed-off-by: Jay Vosburgh <fubar@us.ibm.com>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/bonding/bond_main.c
#   2005/02/11 02:00:02-05:00 fubar@us.ibm.com +2 -2
#   bonding: change misleading warning
# 
# ChangeSet
#   2005/02/11 16:54:28-05:00 fubar@us.ibm.com 
#   [PATCH] : bonding: use wrappers to change mtu and MAC
#   
#   	This updates the bonding driver to use the dev_set_mtu() and
#   dev_set_mac_address() wrapper functions.
#   
#   Signed-off-by: Jay Vosburgh <fubar@us.ibm.com>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/bonding/bond_main.c
#   2005/02/11 01:20:08-05:00 fubar@us.ibm.com +11 -20
#   : bonding: use wrappers to change mtu and MAC
# 
# drivers/net/bonding/bond_alb.c
#   2005/02/11 01:16:32-05:00 fubar@us.ibm.com +4 -4
#   : bonding: use wrappers to change mtu and MAC
# 
# ChangeSet
#   2005/02/11 16:54:16-05:00 fubar@us.ibm.com 
#   [PATCH] : net/core: move set MAC into separate function
#   
#   	This moves the SIOCSIFHWADDR code from dev_ifsioc() into a
#   separate new function, dev_set_mac_address().  This provides a single
#   entry point for all callers performing MAC address changes.
#   
#   Signed-off-by: Jay Vosburgh <fubar@us.ibm.com>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# net/core/dev.c
#   2005/02/11 00:54:32-05:00 fubar@us.ibm.com +17 -11
#   : net/core: move set MAC into separate function
# 
# include/linux/netdevice.h
#   2005/02/11 00:54:25-05:00 fubar@us.ibm.com +2 -0
#   : net/core: move set MAC into separate function
# 
# ChangeSet
#   2005/02/11 17:08:14+01:00 n1gp@hotmail.com 
#   input: Fix keybit initialization in MK712 touchscreen driver.
#          With this, the driver is tested to work properly.
#   
#   From: Richard Koch <n1gp@hotmail.com>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/touchscreen/mk712.c
#   2005/02/11 17:08:07+01:00 n1gp@hotmail.com +1 -1
#   input: Fix keybit initialization in MK712 touchscreen driver.
#          With this, the driver is tested to work properly.
#   
#   From: Richard Koch <n1gp@hotmail.com>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# ChangeSet
#   2005/02/11 01:23:40-05:00 dtor_core@ameritech.net 
#   Input: remove gameport->private in favor of using driver-specific data
#          in device structure, add gameport_get/set_drvdata to access it.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
# 
# include/linux/gameport.h
#   2005/02/10 19:00:00-05:00 dtor_core@ameritech.net +14 -1
#   Add gameport_get/set_drvdata to access driver-specific data in gameport.
# 
# drivers/input/joystick/tmdc.c
#   2005/02/10 19:00:00-05:00 dtor_core@ameritech.net +6 -4
#   Use gameport_get/set_drvdata to access driver-specific data in gameport.
# 
# drivers/input/joystick/sidewinder.c
#   2005/02/10 19:00:00-05:00 dtor_core@ameritech.net +6 -4
#   Use gameport_get/set_drvdata to access driver-specific data in gameport.
# 
# drivers/input/joystick/interact.c
#   2005/02/10 19:00:00-05:00 dtor_core@ameritech.net +6 -4
#   Use gameport_get/set_drvdata to access driver-specific data in gameport.
# 
# drivers/input/joystick/guillemot.c
#   2005/02/10 19:00:00-05:00 dtor_core@ameritech.net +5 -4
#   Use gameport_get/set_drvdata to access driver-specific data in gameport.
# 
# drivers/input/joystick/grip_mp.c
#   2005/02/10 19:00:00-05:00 dtor_core@ameritech.net +6 -3
#   Use gameport_get/set_drvdata to access driver-specific data in gameport.
# 
# drivers/input/joystick/grip.c
#   2005/02/10 19:00:00-05:00 dtor_core@ameritech.net +6 -4
#   Use gameport_get/set_drvdata to access driver-specific data in gameport.
# 
# drivers/input/joystick/gf2k.c
#   2005/02/10 19:00:00-05:00 dtor_core@ameritech.net +6 -4
#   Use gameport_get/set_drvdata to access driver-specific data in gameport.
# 
# drivers/input/joystick/cobra.c
#   2005/02/10 19:00:00-05:00 dtor_core@ameritech.net +6 -4
#   Use gameport_get/set_drvdata to access driver-specific data in gameport.
# 
# drivers/input/joystick/analog.c
#   2005/02/10 19:00:00-05:00 dtor_core@ameritech.net +5 -2
#   Use gameport_get/set_drvdata to access driver-specific data in gameport.
# 
# drivers/input/joystick/adi.c
#   2005/02/10 19:00:00-05:00 dtor_core@ameritech.net +4 -3
#   Use gameport_get/set_drvdata to access driver-specific data in gameport.
# 
# drivers/input/joystick/a3d.c
#   2005/02/10 19:00:00-05:00 dtor_core@ameritech.net +6 -4
#   Use gameport_get/set_drvdata to access driver-specific data in gameport.
# 
# ChangeSet
#   2005/02/11 01:21:32-05:00 dtor_core@ameritech.net 
#   Input: complete gameport sysfs integration, ports are now
#          devices in driver model. Implemented similarly to serio.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
# 
# include/linux/gameport.h
#   2005/02/10 19:00:00-05:00 dtor_core@ameritech.net +43 -21
#   Complete sysfs integration.
# 
# drivers/input/gameport/gameport.c
#   2005/02/10 19:00:00-05:00 dtor_core@ameritech.net +536 -50
#   Complete sysfs integration.
# 
# ChangeSet
#   2005/02/11 01:21:02-05:00 dtor_core@ameritech.net 
#   Input: integrate gameport drivers info dribver model/sysfs,
#          create "gameport" bus. drivers' connect() routines
#          now return error code instead of void.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
# 
# include/linux/gameport.h
#   2005/02/10 19:00:00-05:00 dtor_core@ameritech.net +4 -2
#   Add device_driver structure to gameport_driver; make connect()
#   return error code instead of void.
# 
# drivers/input/joystick/tmdc.c
#   2005/02/10 19:00:00-05:00 dtor_core@ameritech.net +29 -24
#   Sysfs integration; make connect() return error code instead of void.
# 
# drivers/input/joystick/sidewinder.c
#   2005/02/10 19:00:00-05:00 dtor_core@ameritech.net +53 -22
#   Sysfs integration; make connect() return error code instead of void.
# 
# drivers/input/joystick/joydump.c
#   2005/02/10 19:00:00-05:00 dtor_core@ameritech.net +14 -6
#   Sysfs integration; make connect() return error code instead of void.
# 
# drivers/input/joystick/interact.c
#   2005/02/10 19:00:00-05:00 dtor_core@ameritech.net +23 -9
#   Sysfs integration; make connect() return error code instead of void.
# 
# drivers/input/joystick/guillemot.c
#   2005/02/10 19:00:00-05:00 dtor_core@ameritech.net +31 -22
#   Sysfs integration; make connect() return error code instead of void.
# 
# drivers/input/joystick/grip_mp.c
#   2005/02/10 19:00:00-05:00 dtor_core@ameritech.net +36 -20
#   Sysfs integration; make connect() return error code instead of void.
# 
# drivers/input/joystick/grip.c
#   2005/02/10 19:00:00-05:00 dtor_core@ameritech.net +29 -32
#   Sysfs integration; make connect() return error code instead of void.
# 
# drivers/input/joystick/gf2k.c
#   2005/02/10 19:00:00-05:00 dtor_core@ameritech.net +29 -13
#   Sysfs integration; make connect() return error code instead of void.
# 
# drivers/input/joystick/cobra.c
#   2005/02/10 19:00:00-05:00 dtor_core@ameritech.net +26 -16
#   Sysfs integration; make connect() return error code instead of void.
# 
# drivers/input/joystick/analog.c
#   2005/02/10 19:00:00-05:00 dtor_core@ameritech.net +32 -20
#   Sysfs integration; make connect() return error code instead of void.
# 
# drivers/input/joystick/adi.c
#   2005/02/10 19:00:00-05:00 dtor_core@ameritech.net +30 -33
#   Sysfs integration; make connect() return error code instead of void.
# 
# drivers/input/joystick/a3d.c
#   2005/02/10 19:00:00-05:00 dtor_core@ameritech.net +31 -13
#   Sysfs integration; make connect() return error code instead of void.
# 
# drivers/input/gameport/gameport.c
#   2005/02/10 19:00:00-05:00 dtor_core@ameritech.net +39 -0
#   Start of sysfs integration - make gameport drivers part of
#   driver model.
# 
# drivers/Makefile
#   2005/02/10 19:00:00-05:00 dtor_core@ameritech.net +1 -1
#   Move input/gameport ahead of input/ since we need gameport
#   bus registered before we start adding joystick drivers.
# 
# ChangeSet
#   2005/02/11 01:20:30-05:00 dtor_core@ameritech.net 
#   Input: convert sound/pci to dynamic gameport allocation.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
# 
# sound/pci/ymfpci/ymfpci_main.c
#   2005/02/09 22:16:24-05:00 dtor_core@ameritech.net +1 -8
#   Convert to dynamic gameport allocation.
# 
# sound/pci/ymfpci/ymfpci.c
#   2005/02/09 22:16:23-05:00 dtor_core@ameritech.net +92 -57
#   Convert to dynamic gameport allocation.
# 
# sound/pci/via82xx.c
#   2005/02/09 22:16:24-05:00 dtor_core@ameritech.net +65 -24
#   Convert to dynamic gameport allocation.
# 
# sound/pci/trident/trident_main.c
#   2005/02/09 22:16:23-05:00 dtor_core@ameritech.net +42 -45
#   Convert to dynamic gameport allocation.
# 
# sound/pci/trident/trident.c
#   2005/02/09 22:16:23-05:00 dtor_core@ameritech.net +1 -1
#   Convert to dynamic gameport allocation.
# 
# sound/pci/sonicvibes.c
#   2005/02/09 22:16:23-05:00 dtor_core@ameritech.net +44 -11
#   Convert to dynamic gameport allocation.
# 
# sound/pci/es1968.c
#   2005/02/09 22:16:24-05:00 dtor_core@ameritech.net +56 -20
#   Convert to dynamic gameport allocation.
# 
# sound/pci/es1938.c
#   2005/02/09 22:16:23-05:00 dtor_core@ameritech.net +42 -10
#   Convert to dynamic gameport allocation.
# 
# sound/pci/ens1370.c
#   2005/02/09 22:16:24-05:00 dtor_core@ameritech.net +81 -41
#   Convert to dynamic gameport allocation.
# 
# sound/pci/cs46xx/cs46xx_lib.c
#   2005/02/09 22:16:23-05:00 dtor_core@ameritech.net +39 -42
#   Convert to dynamic gameport allocation.
# 
# sound/pci/cs4281.c
#   2005/02/09 22:16:24-05:00 dtor_core@ameritech.net +46 -45
#   Convert to dynamic gameport allocation.
# 
# sound/pci/cmipci.c
#   2005/02/09 22:16:23-05:00 dtor_core@ameritech.net +70 -34
#   Convert to dynamic gameport allocation.
# 
# sound/pci/azt3328.c
#   2005/02/09 22:16:23-05:00 dtor_core@ameritech.net +68 -43
#   Convert to dynamic gameport allocation.
# 
# sound/pci/au88x0/au88x0_game.c
#   2005/02/09 22:16:23-05:00 dtor_core@ameritech.net +26 -23
#   Convert to dynamic gameport allocation.
# 
# sound/pci/au88x0/au88x0.h
#   2005/02/09 22:16:23-05:00 dtor_core@ameritech.net +1 -1
#   Convert to dynamic gameport allocation.
# 
# sound/pci/au88x0/au88x0.c
#   2005/02/09 22:16:23-05:00 dtor_core@ameritech.net +3 -4
#   Convert to dynamic gameport allocation.
# 
# sound/pci/als4000.c
#   2005/02/09 22:16:24-05:00 dtor_core@ameritech.net +73 -38
#   Convert to dynamic gameport allocation.
# 
# include/sound/ymfpci.h
#   2005/02/09 22:16:23-05:00 dtor_core@ameritech.net +7 -7
#   Convert to dynamic gameport allocation.
# 
# include/sound/trident.h
#   2005/02/09 22:16:23-05:00 dtor_core@ameritech.net +2 -2
#   Convert to dynamic gameport allocation.
# 
# include/sound/cs46xx.h
#   2005/02/09 22:16:23-05:00 dtor_core@ameritech.net +2 -2
#   Convert to dynamic gameport allocation.
# 
# ChangeSet
#   2005/02/11 01:20:08-05:00 dtor_core@ameritech.net 
#   Input: convert sound/oss to dynamic gameport allocation.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
# 
# sound/oss/trident.c
#   2005/02/10 19:00:00-05:00 dtor_core@ameritech.net +29 -10
#   Convert to dynamic gameport allocation.
# 
# sound/oss/sonicvibes.c
#   2005/02/10 19:00:00-05:00 dtor_core@ameritech.net +36 -13
#   Convert to dynamic gameport allocation.
# 
# sound/oss/mad16.c
#   2005/02/10 19:00:00-05:00 dtor_core@ameritech.net +31 -16
#   Convert to dynamic gameport allocation.
# 
# sound/oss/esssolo1.c
#   2005/02/10 19:00:00-05:00 dtor_core@ameritech.net +34 -13
#   Convert to dynamic gameport allocation.
# 
# sound/oss/es1371.c
#   2005/02/10 19:00:00-05:00 dtor_core@ameritech.net +32 -20
#   Convert to dynamic gameport allocation.
# 
# sound/oss/es1370.c
#   2005/02/10 19:00:00-05:00 dtor_core@ameritech.net +22 -12
#   Convert to dynamic gameport allocation.
# 
# sound/oss/cmpci.c
#   2005/02/10 19:00:00-05:00 dtor_core@ameritech.net +65 -35
#   Convert to dynamic gameport allocation.
# 
# ChangeSet
#   2005/02/11 01:19:36-05:00 dtor_core@ameritech.net 
#   Input: convert input/gameport to dynamic gameport allocation.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
# 
# include/linux/gameport.h
#   2005/02/10 19:00:00-05:00 dtor_core@ameritech.net +0 -3
#   drop input_id as nobody really uses it.
# 
# drivers/input/joystick/a3d.c
#   2005/02/10 19:00:00-05:00 dtor_core@ameritech.net +28 -31
#   Switch to dynamic gameport allocation.
# 
# drivers/input/gameport/vortex.c
#   2005/02/10 19:00:00-05:00 dtor_core@ameritech.net +34 -34
#   Switch to dynamic gameport allocation.
# 
# drivers/input/gameport/ns558.c
#   2005/02/10 19:00:00-05:00 dtor_core@ameritech.net +58 -62
#   Switch to dynamic gameport allocation.
# 
# drivers/input/gameport/lightning.c
#   2005/02/10 19:00:00-05:00 dtor_core@ameritech.net +108 -68
#   Switch to dynamic gameport allocation.
# 
# drivers/input/gameport/fm801-gp.c
#   2005/02/10 19:00:00-05:00 dtor_core@ameritech.net +29 -28
#   Switch to dynamic gameport allocation.
# 
# drivers/input/gameport/emu10k1-gp.c
#   2005/02/10 19:00:00-05:00 dtor_core@ameritech.net +20 -20
#   Switch to dynamic gameport allocation.
# 
# drivers/input/gameport/cs461x.c
#   2005/02/10 19:00:00-05:00 dtor_core@ameritech.net +9 -20
#   Switch to dynamic gameport allocation.
# 
# ChangeSet
#   2005/02/11 01:18:48-05:00 dtor_core@ameritech.net 
#   Input: prepare for dynamic gameport allocation:
#          - provide functions to allocate and free gameports;
#          - provide functions to properly set name and phys;
#          - dynamically allocated gameports are automatically
#            announced in kernel logs and freed when unregistered.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
# 
# include/linux/gameport.h
#   2005/02/10 19:00:00-05:00 dtor_core@ameritech.net +31 -7
#   Provide functions to dynamically allocate and free gameports.
# 
# drivers/input/gameport/gameport.c
#   2005/02/10 19:00:00-05:00 dtor_core@ameritech.net +24 -0
#   Support dynamic gameport allocation.
# 
# ChangeSet
#   2005/02/11 01:18:29-05:00 dtor_core@ameritech.net 
#   Input: make connect and disconnect methods mandatory for gameport
#          drivers since that's where gameport_{open|close} are called
#          from to actually bind driver to a port.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
# 
# drivers/input/gameport/gameport.c
#   2005/02/09 01:35:11-05:00 dtor_core@ameritech.net +4 -5
#   Connect and disconnect handlers are now mandatory.
# 
# ChangeSet
#   2005/02/11 01:09:59-05:00 dtor_core@ameritech.net 
#   Input: more renames in gameport in preparations to sysfs integration
#          - gameport_dev -> gameport_driver
#          - gameport_[un]register_device -> gameport_[un]register_driver
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
# 
# include/linux/gameport.h
#   2005/02/09 01:09:41-05:00 dtor_core@ameritech.net +6 -6
#   Rename gameport_dev to gameport_driver
# 
# drivers/input/joystick/tmdc.c
#   2005/02/09 01:09:41-05:00 dtor_core@ameritech.net +5 -5
#   Rename gameport_dev to gameport_driver
# 
# drivers/input/joystick/sidewinder.c
#   2005/02/09 01:09:41-05:00 dtor_core@ameritech.net +5 -5
#   Rename gameport_dev to gameport_driver
# 
# drivers/input/joystick/joydump.c
#   2005/02/09 01:09:41-05:00 dtor_core@ameritech.net +6 -6
#   Rename gameport_dev to gameport_driver
# 
# drivers/input/joystick/interact.c
#   2005/02/09 01:09:41-05:00 dtor_core@ameritech.net +5 -5
#   Rename gameport_dev to gameport_driver
# 
# drivers/input/joystick/guillemot.c
#   2005/02/09 01:09:41-05:00 dtor_core@ameritech.net +5 -5
#   Rename gameport_dev to gameport_driver
# 
# drivers/input/joystick/grip_mp.c
#   2005/02/09 01:09:41-05:00 dtor_core@ameritech.net +5 -5
#   Rename gameport_dev to gameport_driver
# 
# drivers/input/joystick/grip.c
#   2005/02/09 01:09:41-05:00 dtor_core@ameritech.net +5 -5
#   Rename gameport_dev to gameport_driver
# 
# drivers/input/joystick/gf2k.c
#   2005/02/09 01:09:41-05:00 dtor_core@ameritech.net +5 -5
#   Rename gameport_dev to gameport_driver
# 
# drivers/input/joystick/cobra.c
#   2005/02/09 01:09:41-05:00 dtor_core@ameritech.net +5 -5
#   Rename gameport_dev to gameport_driver
# 
# drivers/input/joystick/analog.c
#   2005/02/09 01:09:41-05:00 dtor_core@ameritech.net +9 -9
#   Rename gameport_dev to gameport_driver
# 
# drivers/input/joystick/adi.c
#   2005/02/09 01:09:41-05:00 dtor_core@ameritech.net +5 -5
#   Rename gameport_dev to gameport_driver
# 
# drivers/input/joystick/a3d.c
#   2005/02/09 01:09:41-05:00 dtor_core@ameritech.net +5 -5
#   Rename gameport_dev to gameport_driver
# 
# drivers/input/gameport/gameport.c
#   2005/02/09 01:09:41-05:00 dtor_core@ameritech.net +26 -26
#   Rename gameport_dev to gameport_driver
# 
# ChangeSet
#   2005/02/11 01:09:43-05:00 dtor_core@ameritech.net 
#   Input: rename gameport->driver to gameport->port_data in preparation
#          to sysfs integration.
#     
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
# 
# sound/pci/au88x0/au88x0_game.c
#   2005/02/09 01:09:23-05:00 dtor_core@ameritech.net +7 -8
#   Rename gameport->driver to gameport->port_data
# 
# sound/oss/trident.c
#   2005/02/09 01:09:23-05:00 dtor_core@ameritech.net +5 -5
#   Rename gameport->driver to gameport->port_data
# 
# include/linux/gameport.h
#   2005/02/09 01:09:23-05:00 dtor_core@ameritech.net +2 -2
#   Rename gameport->driver to gameport->port_data
# 
# drivers/input/joystick/a3d.c
#   2005/02/09 01:09:23-05:00 dtor_core@ameritech.net +4 -4
#   Rename gameport->driver to gameport->port_data
# 
# drivers/input/gameport/vortex.c
#   2005/02/09 01:09:23-05:00 dtor_core@ameritech.net +5 -5
#   Rename gameport->driver to gameport->port_data
# 
# drivers/input/gameport/lightning.c
#   2005/02/09 01:09:23-05:00 dtor_core@ameritech.net +4 -4
#   Rename gameport->driver to gameport->port_data
# 
# ChangeSet
#   2005/02/09 20:48:10+01:00 vojtech@suse.cz 
#   input: Fix Elo touchscreen touch detection.
#   
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/touchscreen/elo.c
#   2005/02/09 20:47:58+01:00 vojtech@suse.cz +2 -2
#   input: Fix Elo touchscreen touch detection.
#   
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# ChangeSet
#   2005/02/09 10:17:53+01:00 jbj1@ultraemail.net 
#   input: Fix a code example in a comment in hiddev.c
#   
#   From: Jens B. Jorgensen <jbj1@ultraemail.net>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# include/linux/hiddev.h
#   2005/02/09 10:17:47+01:00 jbj1@ultraemail.net +2 -2
#   input: Fix a code example in a comment in hiddev.c
#   
#   From: Jens B. Jorgensen <jbj1@ultraemail.net>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# ChangeSet
#   2005/02/09 10:09:47+01:00 vojtech@suse.cz 
#   input: Add support for serial ELO touchscreens, including
#          Elo IntelliTouch, AccuTouch and SecureTouch.
#   
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/touchscreen/elo.c
#   2005/02/09 10:09:40+01:00 vojtech@suse.cz +315 -0
# 
# include/linux/serio.h
#   2005/02/09 10:09:40+01:00 vojtech@suse.cz +1 -0
#   input: Add support for serial ELO touchscreens, including
#          Elo IntelliTouch, AccuTouch and SecureTouch.
#   
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/touchscreen/elo.c
#   2005/02/09 10:09:40+01:00 vojtech@suse.cz +0 -0
#   BitKeeper file /home/vojtech/bk/input/drivers/input/touchscreen/elo.c
# 
# drivers/input/touchscreen/Makefile
#   2005/02/09 10:09:40+01:00 vojtech@suse.cz +1 -0
#   input: Add support for serial ELO touchscreens, including
#          Elo IntelliTouch, AccuTouch and SecureTouch.
#   
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/touchscreen/Kconfig
#   2005/02/09 10:09:40+01:00 vojtech@suse.cz +13 -0
#   input: Add support for serial ELO touchscreens, including
#          Elo IntelliTouch, AccuTouch and SecureTouch.
#   
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# ChangeSet
#   2005/02/09 08:24:55+01:00 dtor_core@ameritech.net 
#   Input: alps - fix protocol validation rules causing touchpad
#          to lose sync if an absolute packet is received after
#          a relative packet with negative Y displacement.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/mouse/alps.c
#   2005/02/09 08:24:43+01:00 dtor_core@ameritech.net +2 -2
#   Input: alps - fix protocol validation rules causing touchpad
#          to lose sync if an absolute packet is received after
#          a relative packet with negative Y displacement.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# ChangeSet
#   2005/02/08 20:26:38-08:00 herbert@gondor.apana.org.au 
#   [IPSEC]: Stop using dst->xfrm
#   
#   Here is a precursor to the xfrm dst consolidation that I talked about.
#   In order to be able to store multiple SAs in one dst, we need to stop
#   using dst->xfrm directly.
#   
#   The following patch does that for the ->output() functions.
#   
#   Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/ipv6/xfrm6_tunnel.c
#   2005/02/08 20:26:16-08:00 herbert@gondor.apana.org.au +1 -1
#   [IPSEC]: Stop using dst->xfrm
#   
#   Here is a precursor to the xfrm dst consolidation that I talked about.
#   In order to be able to store multiple SAs in one dst, we need to stop
#   using dst->xfrm directly.
#   
#   The following patch does that for the ->output() functions.
#   
#   Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/ipv6/xfrm6_output.c
#   2005/02/08 20:26:16-08:00 herbert@gondor.apana.org.au +1 -1
#   [IPSEC]: Stop using dst->xfrm
#   
#   Here is a precursor to the xfrm dst consolidation that I talked about.
#   In order to be able to store multiple SAs in one dst, we need to stop
#   using dst->xfrm directly.
#   
#   The following patch does that for the ->output() functions.
#   
#   Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/ipv6/ipcomp6.c
#   2005/02/08 20:26:16-08:00 herbert@gondor.apana.org.au +1 -3
#   [IPSEC]: Stop using dst->xfrm
#   
#   Here is a precursor to the xfrm dst consolidation that I talked about.
#   In order to be able to store multiple SAs in one dst, we need to stop
#   using dst->xfrm directly.
#   
#   The following patch does that for the ->output() functions.
#   
#   Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/ipv6/esp6.c
#   2005/02/08 20:26:16-08:00 herbert@gondor.apana.org.au +1 -3
#   [IPSEC]: Stop using dst->xfrm
#   
#   Here is a precursor to the xfrm dst consolidation that I talked about.
#   In order to be able to store multiple SAs in one dst, we need to stop
#   using dst->xfrm directly.
#   
#   The following patch does that for the ->output() functions.
#   
#   Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/ipv6/ah6.c
#   2005/02/08 20:26:16-08:00 herbert@gondor.apana.org.au +1 -3
#   [IPSEC]: Stop using dst->xfrm
#   
#   Here is a precursor to the xfrm dst consolidation that I talked about.
#   In order to be able to store multiple SAs in one dst, we need to stop
#   using dst->xfrm directly.
#   
#   The following patch does that for the ->output() functions.
#   
#   Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/ipv4/xfrm4_tunnel.c
#   2005/02/08 20:26:16-08:00 herbert@gondor.apana.org.au +1 -1
#   [IPSEC]: Stop using dst->xfrm
#   
#   Here is a precursor to the xfrm dst consolidation that I talked about.
#   In order to be able to store multiple SAs in one dst, we need to stop
#   using dst->xfrm directly.
#   
#   The following patch does that for the ->output() functions.
#   
#   Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/ipv4/xfrm4_output.c
#   2005/02/08 20:26:16-08:00 herbert@gondor.apana.org.au +1 -1
#   [IPSEC]: Stop using dst->xfrm
#   
#   Here is a precursor to the xfrm dst consolidation that I talked about.
#   In order to be able to store multiple SAs in one dst, we need to stop
#   using dst->xfrm directly.
#   
#   The following patch does that for the ->output() functions.
#   
#   Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/ipv4/ipcomp.c
#   2005/02/08 20:26:16-08:00 herbert@gondor.apana.org.au +1 -3
#   [IPSEC]: Stop using dst->xfrm
#   
#   Here is a precursor to the xfrm dst consolidation that I talked about.
#   In order to be able to store multiple SAs in one dst, we need to stop
#   using dst->xfrm directly.
#   
#   The following patch does that for the ->output() functions.
#   
#   Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/ipv4/esp4.c
#   2005/02/08 20:26:16-08:00 herbert@gondor.apana.org.au +1 -3
#   [IPSEC]: Stop using dst->xfrm
#   
#   Here is a precursor to the xfrm dst consolidation that I talked about.
#   In order to be able to store multiple SAs in one dst, we need to stop
#   using dst->xfrm directly.
#   
#   The following patch does that for the ->output() functions.
#   
#   Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/ipv4/ah4.c
#   2005/02/08 20:26:16-08:00 herbert@gondor.apana.org.au +1 -3
#   [IPSEC]: Stop using dst->xfrm
#   
#   Here is a precursor to the xfrm dst consolidation that I talked about.
#   In order to be able to store multiple SAs in one dst, we need to stop
#   using dst->xfrm directly.
#   
#   The following patch does that for the ->output() functions.
#   
#   Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# include/net/xfrm.h
#   2005/02/08 20:26:16-08:00 herbert@gondor.apana.org.au +1 -1
#   [IPSEC]: Stop using dst->xfrm
#   
#   Here is a precursor to the xfrm dst consolidation that I talked about.
#   In order to be able to store multiple SAs in one dst, we need to stop
#   using dst->xfrm directly.
#   
#   The following patch does that for the ->output() functions.
#   
#   Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# ChangeSet
#   2005/02/08 20:17:48-08:00 davem@nuts.davemloft.net 
#   Resolve ATM conflicts.
# 
# net/atm/svc.c
#   2005/02/08 20:17:29-08:00 davem@nuts.davemloft.net +1 -1
#   Resolve ATM conflicts.
# 
# ChangeSet
#   2005/02/08 20:13:46-08:00 davem@nuts.davemloft.net 
#   Resolve ATM conflicts.
# 
# net/netlink/af_netlink.c
#   2005/02/08 20:09:15-08:00 davem@nuts.davemloft.net +0 -0
#   Auto merged
# 
# net/key/af_key.c
#   2005/02/08 20:09:15-08:00 davem@nuts.davemloft.net +0 -0
#   Auto merged
# 
# net/atm/lec.c
#   2005/02/08 20:09:15-08:00 davem@nuts.davemloft.net +0 -0
#   Auto merged
# 
# net/atm/clip.c
#   2005/02/08 20:09:15-08:00 davem@nuts.davemloft.net +0 -0
#   Auto merged
# 
# include/linux/atalk.h
#   2005/02/08 20:09:15-08:00 davem@nuts.davemloft.net +0 -0
#   Auto merged
# 
# drivers/net/pppoe.c
#   2005/02/08 20:09:15-08:00 davem@nuts.davemloft.net +0 -0
#   Auto merged
# 
# drivers/atm/he.c
#   2005/02/08 20:09:14-08:00 davem@nuts.davemloft.net +0 -0
#   Auto merged
# 
# ChangeSet
#   2005/02/08 20:06:58-08:00 shemminger@osdl.org 
#   [IPV6]: match TCP port selection behavior with ipv4
#   
#   This patch makes TCP over IPV6 select ports the same way the current
#   TCPv4 code does. It uses a hash function to provide a starting offset
#   and a free running counter to provide seed.
#   
#   This changes the port selection semantics to match TCPv4 as well.
#   If the port is in use but to a different remote address, it will get
#   reused. It looks like the TCPv6 code was not updated when the TCPv4
#   code changed. Now the code in ipv4/tcp_ipv4.c and ipv6/tcp_ipv6.c are
#   almost identical for tcp_hash_connect.
#   
#   Signed-off-by: Stephen Hemminger <shemminger@osdl.org>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/ipv6/tcp_ipv6.c
#   2005/02/08 20:06:36-08:00 shemminger@osdl.org +104 -23
#   [IPV6]: match TCP port selection behavior with ipv4
#   
#   This patch makes TCP over IPV6 select ports the same way the current
#   TCPv4 code does. It uses a hash function to provide a starting offset
#   and a free running counter to provide seed.
#   
#   This changes the port selection semantics to match TCPv4 as well.
#   If the port is in use but to a different remote address, it will get
#   reused. It looks like the TCPv6 code was not updated when the TCPv4
#   code changed. Now the code in ipv4/tcp_ipv4.c and ipv6/tcp_ipv6.c are
#   almost identical for tcp_hash_connect.
#   
#   Signed-off-by: Stephen Hemminger <shemminger@osdl.org>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/ipv4/tcp_ipv4.c
#   2005/02/08 20:06:36-08:00 shemminger@osdl.org +1 -0
#   [IPV6]: match TCP port selection behavior with ipv4
#   
#   This patch makes TCP over IPV6 select ports the same way the current
#   TCPv4 code does. It uses a hash function to provide a starting offset
#   and a free running counter to provide seed.
#   
#   This changes the port selection semantics to match TCPv4 as well.
#   If the port is in use but to a different remote address, it will get
#   reused. It looks like the TCPv6 code was not updated when the TCPv4
#   code changed. Now the code in ipv4/tcp_ipv4.c and ipv6/tcp_ipv6.c are
#   almost identical for tcp_hash_connect.
#   
#   Signed-off-by: Stephen Hemminger <shemminger@osdl.org>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# include/linux/random.h
#   2005/02/08 20:06:36-08:00 shemminger@osdl.org +2 -0
#   [IPV6]: match TCP port selection behavior with ipv4
#   
#   This patch makes TCP over IPV6 select ports the same way the current
#   TCPv4 code does. It uses a hash function to provide a starting offset
#   and a free running counter to provide seed.
#   
#   This changes the port selection semantics to match TCPv4 as well.
#   If the port is in use but to a different remote address, it will get
#   reused. It looks like the TCPv6 code was not updated when the TCPv4
#   code changed. Now the code in ipv4/tcp_ipv4.c and ipv6/tcp_ipv6.c are
#   almost identical for tcp_hash_connect.
#   
#   Signed-off-by: Stephen Hemminger <shemminger@osdl.org>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# drivers/char/random.c
#   2005/02/08 20:06:36-08:00 shemminger@osdl.org +15 -0
#   [IPV6]: match TCP port selection behavior with ipv4
#   
#   This patch makes TCP over IPV6 select ports the same way the current
#   TCPv4 code does. It uses a hash function to provide a starting offset
#   and a free running counter to provide seed.
#   
#   This changes the port selection semantics to match TCPv4 as well.
#   If the port is in use but to a different remote address, it will get
#   reused. It looks like the TCPv6 code was not updated when the TCPv4
#   code changed. Now the code in ipv4/tcp_ipv4.c and ipv6/tcp_ipv6.c are
#   almost identical for tcp_hash_connect.
#   
#   Signed-off-by: Stephen Hemminger <shemminger@osdl.org>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# ChangeSet
#   2005/02/08 20:02:47-08:00 kaber@trash.net 
#   [NET]: Remove protocol specific hacks in skb_ip_make_writable()
#   
#   These cause more trouble than anything else.  In fact these
#   silly checks keep the ipt action from working with targets
#   that mangle the data area.
#   
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/core/netfilter.c
#   2005/02/08 20:02:09-08:00 kaber@trash.net +1 -33
#   [NET]: Remove protocol specific hacks in skb_ip_make_writable()
#   
#   These cause more trouble than anything else.  In fact these
#   silly checks keep the ipt action from working with targets
#   that mangle the data area.
#   
#   Signed-off-by: Patrick McHardy <kaber@trash.net>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# ChangeSet
#   2005/02/08 12:23:18-08:00 brking@us.ibm.com 
#   [PATCH] PCI: Dynids - passing driver data
#   
#   Currently, code exists in the pci layer to allow userspace to specify
#   driver data when adding a pci dynamic id from sysfs. However, this data
#   is never used and there exists no way in the existing code to use it.
#   This patch allows device drivers to indicate that they want driver data
#   passed to them on dynamic id adds by initializing use_driver_data in their
#   pci_driver->pci_dynids struct. The documentation has also been updated
#   to reflect this.
#   
#   Signed-off-by: Brian King <brking@us.ibm.com>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/pci/pci-driver.c
#   2005/02/07 13:58:21-08:00 brking@us.ibm.com +0 -1
#   PCI: Dynids - passing driver data
# 
# Documentation/pci.txt
#   2005/02/07 13:58:21-08:00 brking@us.ibm.com +4 -4
#   PCI: Dynids - passing driver data
# 
# ChangeSet
#   2005/02/08 12:22:53-08:00 Mark.Haigh@spirentcom.com 
#   [PATCH] arch/i386/kernel/pci/irq.c:  Wrong message output
#   
#   The following has been reported in the wild for kernel 2.6.8-24:
#   
#   PCI: Enabling device 0000:00:05.0 (0000 -> 0002)
#   PCI: No IRQ known for interrupt pin @ of device 0000:00:05.0. Probably
#   buggy MP table.
#   
#   It should read "No IRQ known for interrupt pin A", but the 'pin'
#   variable has already been decremented (from 1 to 0), so the line:
#   
#   printk(KERN_WARNING "PCI: No IRQ known for interrupt pin %c of device
#   %s.%s\n", 'A' + pin - 1, dev->slot_name, msg);
#   
#   causes "pin @" to be output, because 'A' + 0 - 1 == '@'.
#   
#   The supplied patch should fix it.  It also removes a redundant check for
#   a nonzero pin.
#   
#   Signed-off-by: Mark F. Haigh  <Mark.Haigh@spirentcom.com>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# arch/i386/pci/irq.c
#   2005/02/07 21:39:15-08:00 Mark.Haigh@spirentcom.com +36 -37
#   arch/i386/kernel/pci/irq.c:  Wrong message output
# 
# ChangeSet
#   2005/02/08 19:04:58+01:00 castet.matthieu@free.fr 
#   input: this patch turns off the pc speaker when pcspkr.ko is unloaded,
#          else it would never stop
#   
#   Signed-off-by: Matthieu Castet <castet.matthieu@free.fr>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/misc/pcspkr.c
#   2005/02/08 19:04:45+01:00 castet.matthieu@free.fr +2 -0
#   input: this patch turns off the pc speaker when pcspkr.ko is unloaded,
#          else it would never stop
#   
#   Signed-off-by: Matthieu Castet <castet.matthieu@free.fr>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# ChangeSet
#   2005/02/08 18:00:02+01:00 svrmgrl@gmx.net 
#   input: Add a new ID to the Logitech ForceFeedback joystick driver.
#   
#   From: Rainer Kümmerle <svrmgrl@gmx.net>
#   Acked-by: Johann Deneux <johann.deneux@it.uu.se>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/usb/input/hid-lgff.c
#   2005/02/08 17:59:55+01:00 svrmgrl@gmx.net +1 -0
#   input: Add a new ID to the Logitech ForceFeedback joystick driver.
#   
#   From: Rainer Kümmerle <svrmgrl@gmx.net>
#   Acked-by: Johann Deneux <johann.deneux@it.uu.se>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/usb/input/hid-ff.c
#   2005/02/08 17:59:55+01:00 svrmgrl@gmx.net +1 -0
#   input: Add a new ID to the Logitech ForceFeedback joystick driver.
#   
#   From: Rainer Kümmerle <svrmgrl@gmx.net>
#   Acked-by: Johann Deneux <johann.deneux@it.uu.se>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# ChangeSet
#   2005/02/08 17:53:43+01:00 hal@realmsys.com 
#   input: Fix range checks for the HIDIOC[GS]USAGES ioctl() to allow
#          reading full number of bytes.
#   
#   From: Hal Tolley <hal@realmsys.com>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/usb/input/hiddev.c
#   2005/02/08 17:53:37+01:00 hal@realmsys.com +2 -3
#   input: Fix range checks for the HIDIOC[GS]USAGES ioctl() to allow
#          reading full number of bytes.
#   
#   From: Hal Tolley <hal@realmsys.com>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# ChangeSet
#   2005/02/08 17:37:12+01:00 vojtech@suse.cz 
#   input: Move #include <linux/interrupt.h> inside #ifdef __KERNEL__
#          in serio.h, to make it userspace-compilable.
#   
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# include/linux/serio.h
#   2005/02/08 17:37:05+01:00 vojtech@suse.cz +1 -1
#   input: Move #include <linux/interrupt.h> inside #ifdef __KERNEL__
#          in serio.h, to make it userspace-compilable.
#   
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# ChangeSet
#   2005/02/08 17:35:59+01:00 vojtech@suse.cz 
#   input: Change touchscreen drivers NOT to rescale their values
#          to a 4:3 shape.
#   
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/touchscreen/mk712.c
#   2005/02/08 17:35:52+01:00 vojtech@suse.cz +3 -3
#   input: Change touchscreen drivers NOT to rescale their values
#          to a 4:3 shape.
#   
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/touchscreen/gunze.c
#   2005/02/08 17:35:52+01:00 vojtech@suse.cz +4 -4
#   input: Change touchscreen drivers NOT to rescale their values
#          to a 4:3 shape.
#   
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# ChangeSet
#   2005/02/08 16:05:23+01:00 vojtech@suse.cz 
#   Merge suse.cz:/home/vojtech/bk/linus into suse.cz:/home/vojtech/bk/input
# 
# drivers/input/mousedev.c
#   2005/02/08 16:05:20+01:00 vojtech@suse.cz +0 -2
#   Auto merged
# 
# ChangeSet
#   2005/02/08 10:27:30+01:00 stuart_hayes@dell.com 
#   input: A Chicony keyboard doesn't like get_report on its non-exisiting
#          PS/2 mouse interface. Add to HID blacklist.
#   
#   From: Stuart Hayes <stuart_hayes@dell.com>
#   Seen-by: Pete Zaitcev <zaitcev@redhat.com>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/usb/input/hid-core.c
#   2005/02/08 10:27:15+01:00 stuart_hayes@dell.com +6 -1
#   input: A Chicony keyboard doesn't like get_report on its non-exisiting
#          PS/2 mouse interface. Add to HID blacklist.
#   
#   From: Stuart Hayes <stuart_hayes@dell.com>
#   Seen-by: Pete Zaitcev <zaitcev@redhat.com>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# ChangeSet
#   2005/02/08 10:20:19+01:00 akpm@osdl.org 
#   input: On some architectures the atomic ops return `long'. Fix
#          a printk() in serio.c to take that into account.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/serio/serio.c
#   2005/02/08 10:20:08+01:00 akpm@osdl.org +1 -1
#   input: On some architectures the atomic ops return `long'. Fix
#          a printk() in serio.c to take that into account.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# ChangeSet
#   2005/02/08 10:18:37+01:00 dtor_core@ameritech.net 
#   Input: make sure that all instances of ns558 are released
#          upon module unload.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/gameport/ns558.c
#   2005/02/08 10:18:25+01:00 dtor_core@ameritech.net +2 -3
#   Input: make sure that all instances of ns558 are released
#          upon module unload.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# ChangeSet
#   2005/02/08 08:53:09+01:00 rufus-kernel@hackish.org 
#   input: For now, a bug in the PSX controllers support in gamecon prevents
#   hot-swapping of such controllers. If a controllers is removed then all
#   the controllers stop working and cpu usage gets high. The attached patch
#   (against 2.6.11-rc3) corrects this bug by checking the information read
#   from the controller. If the message length is bigger than the maximum
#   possible, then it means the controller is not there and therefore this
#   value should be discarded.
#   
#   Note that this is a re-send of a previous patch now that the patch of
#   Peter (which had to be applied before this one) has been intregrated in
#   the vanilla kernel. It's Peter's version modified to apply cleanly
#   against 2.6.11-rc3 plus a fix in the comment.
#   
#   Signed-off-by: Peter Nelson <rufus-kernel@hackish.org>
#   Signed-off-by: Eric Piel <eric.piel@tremplin-utc.net>
# 
# drivers/input/joystick/gamecon.c
#   2005/02/08 08:52:57+01:00 rufus-kernel@hackish.org +11 -8
#   input: For now, a bug in the PSX controllers support in gamecon prevents
#   hot-swapping of such controllers. If a controllers is removed then all
#   the controllers stop working and cpu usage gets high. The attached patch
#   (against 2.6.11-rc3) corrects this bug by checking the information read
#   from the controller. If the message length is bigger than the maximum
#   possible, then it means the controller is not there and therefore this
#   value should be discarded.
#   
#   Note that this is a re-send of a previous patch now that the patch of
#   Peter (which had to be applied before this one) has been intregrated in
#   the vanilla kernel. It's Peter's version modified to apply cleanly
#   against 2.6.11-rc3 plus a fix in the comment.
#   
#   Signed-off-by: Peter Nelson <rufus-kernel@hackish.org>
#   Signed-off-by: Eric Piel <eric.piel@tremplin-utc.net>
# 
# ChangeSet
#   2005/02/07 16:21:16-08:00 bjorn.helgaas@hp.com 
#   [PATCH] PCI: pci_raw_ops should use unsigned args
#   
#   Convert pci_raw_ops to use unsigned segment (aka domain),
#   bus, and devfn.  With the previous code, various ia64 config
#   accesses fail due to segment sign-extension problems.
#   
#   ia64:
#       - With a signed seg >= 0x8, unwanted sign-extension occurs when
#         "seg << 28" is cast to u64 in PCI_SAL_EXT_ADDRESS()
#       - PCI_SAL_EXT_ADDRESS(): cast to u64 *before* shifting; otherwise
#         "seg << 28" is evaluated as unsigned int (32 bits) and gets
#         truncated when seg > 0xf
#       - pci_sal_read(): validate "value" ptr as other arches do
#       - pci_sal_{read,write}(): return -EINVAL rather than SAL error status
#   
#    arch/i386/pci/direct.c     |   12 ++++++----
#    arch/i386/pci/mmconfig.c   |    6 +++--
#    arch/i386/pci/numa.c       |    6 +++--
#    arch/i386/pci/pcbios.c     |    6 +++--
#    arch/ia64/pci/pci.c        |   53 ++++++++++++++++++---------------------------
#    arch/x86_64/pci/mmconfig.c |    8 ++++--
#    include/linux/pci.h        |    6 +++--
#    7 files changed, 51 insertions(+), 46 deletions(-)
#   
#   Signed-off-by: Bjorn Helgaas <bjorn.helgaas@hp.com>
#   Acked-by: Matthew Wilcox <matthew@wil.cx>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# include/linux/pci.h
#   2005/02/03 10:08:22-08:00 bjorn.helgaas@hp.com +4 -2
#   PCI: pci_raw_ops should use unsigned args
# 
# arch/x86_64/pci/mmconfig.c
#   2005/02/03 10:08:22-08:00 bjorn.helgaas@hp.com +5 -3
#   PCI: pci_raw_ops should use unsigned args
# 
# arch/ia64/pci/pci.c
#   2005/02/03 10:08:22-08:00 bjorn.helgaas@hp.com +22 -31
#   PCI: pci_raw_ops should use unsigned args
# 
# arch/i386/pci/pcbios.c
#   2005/02/03 10:08:21-08:00 bjorn.helgaas@hp.com +4 -2
#   PCI: pci_raw_ops should use unsigned args
# 
# arch/i386/pci/numa.c
#   2005/02/03 10:55:05-08:00 bjorn.helgaas@hp.com +4 -2
#   PCI: pci_raw_ops should use unsigned args
# 
# arch/i386/pci/mmconfig.c
#   2005/02/03 10:08:21-08:00 bjorn.helgaas@hp.com +4 -2
#   PCI: pci_raw_ops should use unsigned args
# 
# arch/i386/pci/direct.c
#   2005/02/03 10:08:21-08:00 bjorn.helgaas@hp.com +8 -4
#   PCI: pci_raw_ops should use unsigned args
# 
# ChangeSet
#   2005/02/07 16:20:50-08:00 bjorn.helgaas@hp.com 
#   [PATCH] PCI: NUMA-Q PCI config access arg validation
#   
#   Fix NUMA-Q PCI config access bus validation.  "bus" indexes
#   into BUS2QUAD, which is mp_bus_id_to_node[MAX_MP_BUSSES].
#   
#   This depends on the "pci_raw_ops should use unsigned args"
#   patch I posted earlier today (no functional dependency; it
#   just happens to be very close textually).
#   
#   Signed-off-by: Bjorn Helgaas <bjorn.helgaas@hp.com>
#   Signed-off-by: Martin J. Bligh <mbligh@aracnet.com>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# arch/i386/pci/numa.c
#   2005/02/03 15:24:27-08:00 bjorn.helgaas@hp.com +2 -2
#   PCI: NUMA-Q PCI config access arg validation
# 
# ChangeSet
#   2005/02/07 16:20:26-08:00 muneda.takahiro@jp.fujitsu.com 
#   [PATCH] PCI: fix pci_remove_legacy_files() crash
#   
#   The legacy_io which is the member of pci_bus struct might be
#   NULL. It should be checked.
#   
#   This patch checks 'b->legacy_io', NULL or not.
#   
#   Signed-off-by: MUNEDA Takahiro <muneda.takahiro@jp.fujitsu.com>
#   Acked-by: Jesse Barnes <jbarnes@sgi.com>
#   Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
# 
# drivers/pci/probe.c
#   2005/02/02 18:21:51-08:00 muneda.takahiro@jp.fujitsu.com +5 -3
#   PCI: fix pci_remove_legacy_files() crash
# 
# ChangeSet
#   2005/02/07 14:38:32-08:00 matthew@wil.cx 
#   [PATCH] PCI: Make pci_claim_resource __devinit
#   
#   ia64 calls pci_claim_resource() from pcibios_fixup_bus(), which is
#   __devinit, so pci_claim_resource() needs to be __devinit too.
#   
#   Signed-off-by: Matthew Wilcox <matthew@wil.cx>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/pci/setup-res.c
#   2005/02/07 12:51:58-08:00 matthew@wil.cx +1 -1
#   PCI: Make pci_claim_resource __devinit
# 
# ChangeSet
#   2005/02/07 14:38:06-08:00 matthew@wil.cx 
#   [PATCH] PCI: pci_proc_domain
#   
#   There's no need for the architectures to know how to name busses,
#   so replace pci_name_bus with pci_proc_domain -- a predicate to allow
#   architectures to choose whether domains are included in /proc/bus/pci
#   or not.  I've converted all architectures but only tested ia64 and a
#   CONFIG_PCI_DOMAINS=n build.
#   
#   Signed-off-by: Matthew Wilcox <matthew@wil.cx>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# include/linux/pci.h
#   2005/02/07 12:52:02-08:00 matthew@wil.cx +1 -2
#   PCI: pci_proc_domain
# 
# include/asm-sparc64/pci.h
#   2005/02/07 12:52:02-08:00 matthew@wil.cx +4 -1
#   PCI: pci_proc_domain
# 
# include/asm-ppc64/pci.h
#   2005/02/07 12:52:02-08:00 matthew@wil.cx +2 -2
#   PCI: pci_proc_domain
# 
# include/asm-ppc/pci.h
#   2005/02/07 12:52:02-08:00 matthew@wil.cx +1 -2
#   PCI: pci_proc_domain
# 
# include/asm-mips/pci.h
#   2005/02/07 12:52:02-08:00 matthew@wil.cx +2 -9
#   PCI: pci_proc_domain
# 
# include/asm-ia64/pci.h
#   2005/02/07 12:52:02-08:00 matthew@wil.cx +2 -7
#   PCI: pci_proc_domain
# 
# include/asm-alpha/pci.h
#   2005/02/07 12:52:02-08:00 matthew@wil.cx +2 -9
#   PCI: pci_proc_domain
# 
# drivers/pci/proc.c
#   2005/02/07 12:52:02-08:00 matthew@wil.cx +13 -7
#   PCI: pci_proc_domain
# 
# arch/sparc64/kernel/pci.c
#   2005/02/07 12:52:02-08:00 matthew@wil.cx +0 -6
#   PCI: pci_proc_domain
# 
# arch/ppc64/kernel/pci.c
#   2005/02/07 12:52:02-08:00 matthew@wil.cx +6 -10
#   PCI: pci_proc_domain
# 
# ChangeSet
#   2005/02/07 14:37:42-08:00 eike-hotplug@sf-tec.de 
#   [PATCH] PCI Hotplug: Remove unneeded instructions from ibmphp_pci.c
#   
#   this patch removes some unneeded code from ibmphp_pci.c. First I thought it
#   is a bug and the second line should have been "sec_no = (int) sec_number".
#   But than I found exactly the same read only 9 lines higher and after it the
#   line I expected the second one to be. Between the 2 pci_bus_read_config_byte's
#   are only some checks so I don't expect them to return different results. And
#   sec_no is and int so removing this wont change anything at all.
#   
#   
#   Signed-off-by: Rolf Eike Beer <eike-hotplug@sf-tec.de>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/pci/hotplug/ibmphp_pci.c
#   2005/02/07 12:52:07-08:00 eike-hotplug@sf-tec.de +0 -3
#   PCI Hotplug: Remove unneeded instructions from ibmphp_pci.c
# 
# ChangeSet
#   2005/02/07 14:37:01-08:00 davej@redhat.com 
#   [PATCH] Remove pci_dev->slot_name
#   
#   This is a pointer to dev.bus_id, which is properly accessed through the
#   pci_name() function.
#   
#   Signed-off-by: Dave Jones <davej@redhat.com>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# include/linux/pci.h
#   2005/02/07 12:52:49-08:00 davej@redhat.com +0 -2
#   Remove pci_dev->slot_name
# 
# ChangeSet
#   2005/02/07 14:36:14-08:00 davej@redhat.com 
#   [PATCH] convert pci_dev->slot_name usage to pci_name()
#   
#   Prepare for removal of pci_dev->slot_name
#   
#   Signed-off-by: Dave Jones <davej@redhat.com>
#   Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
# 
# drivers/scsi/qla2xxx/qla_os.c
#   2005/02/07 12:52:54-08:00 davej@redhat.com +7 -7
#   convert pci_dev->slot_name usage to pci_name()
# 
# drivers/pcmcia/yenta_socket.c
#   2005/02/07 12:52:54-08:00 davej@redhat.com +1 -1
#   convert pci_dev->slot_name usage to pci_name()
# 
# drivers/pci/setup-res.c
#   2005/02/07 12:52:54-08:00 davej@redhat.com +1 -1
#   convert pci_dev->slot_name usage to pci_name()
# 
# drivers/pci/probe.c
#   2005/02/07 12:52:54-08:00 davej@redhat.com +0 -1
#   convert pci_dev->slot_name usage to pci_name()
# 
# drivers/pci/pci.c
#   2005/02/07 12:52:54-08:00 davej@redhat.com +1 -1
#   convert pci_dev->slot_name usage to pci_name()
# 
# drivers/parisc/dino.c
#   2005/02/07 12:52:54-08:00 davej@redhat.com +2 -3
#   convert pci_dev->slot_name usage to pci_name()
# 
# drivers/net/wan/wanxl.c
#   2005/02/07 12:52:54-08:00 davej@redhat.com +16 -22
#   convert pci_dev->slot_name usage to pci_name()
# 
# drivers/net/via-velocity.c
#   2005/02/07 12:52:54-08:00 davej@redhat.com +1 -1
#   convert pci_dev->slot_name usage to pci_name()
# 
# drivers/net/typhoon.c
#   2005/02/07 12:52:54-08:00 davej@redhat.com +1 -1
#   convert pci_dev->slot_name usage to pci_name()
# 
# drivers/net/tulip/tulip.h
#   2005/02/07 12:52:54-08:00 davej@redhat.com +1 -1
#   convert pci_dev->slot_name usage to pci_name()
# 
# drivers/net/sk98lin/skge.c
#   2005/02/07 12:52:54-08:00 davej@redhat.com +1 -1
#   convert pci_dev->slot_name usage to pci_name()
# 
# drivers/net/sk98lin/skethtool.c
#   2005/02/07 12:52:54-08:00 davej@redhat.com +1 -1
#   convert pci_dev->slot_name usage to pci_name()
# 
# drivers/net/s2io.c
#   2005/02/07 12:52:54-08:00 davej@redhat.com +1 -1
#   convert pci_dev->slot_name usage to pci_name()
# 
# drivers/net/r8169.c
#   2005/02/07 12:52:54-08:00 davej@redhat.com +2 -2
#   convert pci_dev->slot_name usage to pci_name()
# 
# drivers/net/defxx.c
#   2005/02/07 12:52:54-08:00 davej@redhat.com +1 -1
#   convert pci_dev->slot_name usage to pci_name()
# 
# drivers/media/video/zoran_driver.c
#   2005/02/07 12:52:54-08:00 davej@redhat.com +1 -1
#   convert pci_dev->slot_name usage to pci_name()
# 
# drivers/media/video/meye.c
#   2005/02/07 12:52:54-08:00 davej@redhat.com +1 -1
#   convert pci_dev->slot_name usage to pci_name()
# 
# drivers/media/common/saa7146_video.c
#   2005/02/07 12:52:54-08:00 davej@redhat.com +1 -1
#   convert pci_dev->slot_name usage to pci_name()
# 
# drivers/isdn/hisax/hisax_fcpcipnp.c
#   2005/02/07 12:52:54-08:00 davej@redhat.com +1 -1
#   convert pci_dev->slot_name usage to pci_name()
# 
# drivers/ide/pci/sgiioc4.c
#   2005/02/07 12:52:54-08:00 davej@redhat.com +3 -3
#   convert pci_dev->slot_name usage to pci_name()
# 
# drivers/char/agp/sis-agp.c
#   2005/02/07 12:52:54-08:00 davej@redhat.com +1 -1
#   convert pci_dev->slot_name usage to pci_name()
# 
# drivers/char/agp/generic.c
#   2005/02/07 12:52:54-08:00 davej@redhat.com +1 -1
#   convert pci_dev->slot_name usage to pci_name()
# 
# arch/sh64/kernel/pcibios.c
#   2005/02/07 12:52:54-08:00 davej@redhat.com +2 -2
#   convert pci_dev->slot_name usage to pci_name()
# 
# arch/sh64/kernel/pci_sh5.c
#   2005/02/07 12:52:54-08:00 davej@redhat.com +1 -1
#   convert pci_dev->slot_name usage to pci_name()
# 
# arch/sh/drivers/pci/pci-st40.c
#   2005/02/07 12:52:54-08:00 davej@redhat.com +1 -1
#   convert pci_dev->slot_name usage to pci_name()
# 
# arch/sh/drivers/pci/pci-sh7751.c
#   2005/02/07 12:52:54-08:00 davej@redhat.com +4 -4
#   convert pci_dev->slot_name usage to pci_name()
# 
# arch/sh/drivers/pci/fixups-sh03.c
#   2005/02/07 12:52:54-08:00 davej@redhat.com +2 -2
#   convert pci_dev->slot_name usage to pci_name()
# 
# arch/ppc/kernel/pci.c
#   2005/02/07 12:52:54-08:00 davej@redhat.com +1 -1
#   convert pci_dev->slot_name usage to pci_name()
# 
# arch/mips/pmc-sierra/yosemite/ht.c
#   2005/02/07 12:52:54-08:00 davej@redhat.com +3 -3
#   convert pci_dev->slot_name usage to pci_name()
# 
# arch/frv/mb93090-mb00/pci-vdk.c
#   2005/02/07 12:52:54-08:00 davej@redhat.com +3 -3
#   convert pci_dev->slot_name usage to pci_name()
# 
# arch/frv/mb93090-mb00/pci-frv.c
#   2005/02/07 12:52:54-08:00 davej@redhat.com +2 -2
#   convert pci_dev->slot_name usage to pci_name()
# 
# ChangeSet
#   2005/02/07 21:13:22+01:00 krautz@gmail.com 
#   input: Make the polling interval for mice a configurable parameter
#          of the HID driver. This is useful when a faster response
#          from a mouse is beneficial, ie games.
#   
#   Signed-off-by: Mikkel Krautz <krautz@gmail.com>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/usb/input/hid-core.c
#   2005/02/07 21:13:10+01:00 krautz@gmail.com +12 -1
#   input: Make the polling interval for mice a configurable parameter
#          of the HID driver. This is useful when a faster response
#          from a mouse is beneficial, ie games.
#   
#   Signed-off-by: Mikkel Krautz <krautz@gmail.com>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# Documentation/kernel-parameters.txt
#   2005/02/07 21:13:10+01:00 krautz@gmail.com +4 -0
#   input: Make the polling interval for mice a configurable parameter
#          of the HID driver. This is useful when a faster response
#          from a mouse is beneficial, ie games.
#   
#   Signed-off-by: Mikkel Krautz <krautz@gmail.com>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# ChangeSet
#   2005/02/07 20:46:26+01:00 vojtech@silver.ucw.cz 
#   input: Fix i8042 PnP printk()'s and pnp_driver name.
#   
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/serio/i8042-x86ia64io.h
#   2005/02/07 20:46:13+01:00 vojtech@silver.ucw.cz +5 -5
#   input: Fix i8042 PnP printk()'s and pnp_driver name.
#   
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# ChangeSet
#   2005/02/07 19:00:24+01:00 castet.matthieu@free.fr 
#   input: Now that ACPIPnP is available, replace ACPI probing in i8042
#          with PnP probing.
#   
#   From: Matthieu Castet <castet.matthieu@free.fr>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/serio/i8042.c
#   2005/02/07 19:00:12+01:00 castet.matthieu@free.fr +4 -4
#   input: Now that ACPIPnP is available, replace ACPI probing in i8042
#          with PnP probing.
#   
#   From: Matthieu Castet <castet.matthieu@free.fr>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/serio/i8042-x86ia64io.h
#   2005/02/07 19:00:12+01:00 castet.matthieu@free.fr +63 -133
#   input: Now that ACPIPnP is available, replace ACPI probing in i8042
#          with PnP probing.
#   
#   From: Matthieu Castet <castet.matthieu@free.fr>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# ChangeSet
#   2005/02/07 18:32:36+01:00 duraid@octopus.com.au 
#   input: Properly set input.phys in Griffin Powermate driver.
#   
#   From: Duraid Madina <duraid@octopus.com.au>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/usb/input/powermate.c
#   2005/02/07 18:32:16+01:00 duraid@octopus.com.au +1 -0
#   
#     Click [Discard] again if you really want to unedit this file,
#     or type Control-l to go back and work on the comments.
#   
#     Warning!  The changes to this file shown below will be lost.
# 
# ChangeSet
#   2005/02/07 18:30:35+01:00 vojtech@silver.ucw.cz 
#   input: Do a kill_fasync() in input handlers on device disconnect
#          to notify a client using poll() that the device is gone.
#   
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/tsdev.c
#   2005/02/07 18:30:18+01:00 vojtech@silver.ucw.cz +3 -0
#   input: Do a kill_fasync() in input handlers on device disconnect
#          to notify a client using poll() that the device is gone.
#   
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/mousedev.c
#   2005/02/07 18:30:18+01:00 vojtech@silver.ucw.cz +3 -0
#   input: Do a kill_fasync() in input handlers on device disconnect
#          to notify a client using poll() that the device is gone.
#   
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/joydev.c
#   2005/02/07 18:30:18+01:00 vojtech@silver.ucw.cz +3 -0
#   input: Do a kill_fasync() in input handlers on device disconnect
#          to notify a client using poll() that the device is gone.
#   
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/evdev.c
#   2005/02/07 18:30:17+01:00 vojtech@silver.ucw.cz +3 -0
#   input: Do a kill_fasync() in input handlers on device disconnect
#          to notify a client using poll() that the device is gone.
#   
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# ChangeSet
#   2005/02/07 12:20:33-05:00 scjody@modernduck.com 
#   Merge modernduck.com:/usr/src/bk/linux-2.5
#   into modernduck.com:/usr/src/bk/1394-2.6
# 
# MAINTAINERS
#   2005/02/07 12:20:26-05:00 scjody@modernduck.com +0 -0
#   Auto merged
# 
# BitKeeper/etc/ignore
#   2005/02/07 12:19:58-05:00 scjody@modernduck.com +10 -10
#   auto-union
# 
# ChangeSet
#   2005/02/07 13:09:39+01:00 dtor_core@ameritech.net 
#   Input: fix compie error in twidjoy.c
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/joystick/twidjoy.c
#   2005/02/07 13:09:33+01:00 dtor_core@ameritech.net +3 -1
#   Input: fix compie error in twidjoy.c
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# ChangeSet
#   2005/02/07 10:53:26+01:00 vojtech@suse.cz 
#   input: This patch fixes an oops in ns558 when no ports are found and
#   at the same time the driver gets registered with the PnP subsystem.
#   Since there is no need for port->type struct member, it removes it.
#   Patch based on a patch from Matthieu Castet <castet.matthieu@free.fr>
#   and Adam Belay <ambx1@neo.rr.com>
#     
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/gameport/ns558.c
#   2005/02/07 10:53:19+01:00 vojtech@suse.cz +19 -27
#   input: This patch fixes an oops in ns558 when no ports are found and
#   at the same time the driver gets registered with the PnP subsystem.
#   Since there is no need for port->type struct member, it removes it.
#   Patch based on a patch from Matthieu Castet <castet.matthieu@free.fr>
#   and Adam Belay <ambx1@neo.rr.com>
#     
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# ChangeSet
#   2005/02/06 20:56:49+01:00 bunk@stusta.de 
#   input: This patch removes the bouncing email address of Victor Krapivin from
#   MODULE_AUTHOR.
#   
#   Signed-off-by: Adrian Bunk <bunk@stusta.de>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/gameport/cs461x.c
#   2005/02/06 20:56:36+01:00 bunk@stusta.de +1 -1
#   input: This patch removes the bouncing email address of Victor Krapivin from
#   MODULE_AUTHOR.
#   
#   Signed-off-by: Adrian Bunk <bunk@stusta.de>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# ChangeSet
#   2005/02/06 20:47:57+01:00 juhl-lkml@dif.dk 
#   input: ere's a patch that removes a few pointless comparisons; "scancode" is
#   unsigned so it can never be <0 which makes the test pointless.
#   Also, there are a few instances where signed and unsigned variables are
#   comared, and as far as I can tell they really should just all be unsigned.
#   
#   Signed-off-by: Jesper Juhl <juhl-lkml@dif.dk>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/char/keyboard.c
#   2005/02/06 20:47:40+01:00 juhl-lkml@dif.dk +5 -5
#   input: ere's a patch that removes a few pointless comparisons; "scancode" is
#   unsigned so it can never be <0 which makes the test pointless.
#   Also, there are a few instances where signed and unsigned variables are
#   comared, and as far as I can tell they really should just all be unsigned.
#   
#   Signed-off-by: Jesper Juhl <juhl-lkml@dif.dk>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# ChangeSet
#   2005/02/06 20:19:36+01:00 pingc@wacom.com 
#   input: This patch adds support for a Wacom new tablet, Intuos3, and its associated
#   tools.
#   
#   From: Ping Cheng <pingc@wacom.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/usb/input/wacom.c
#   2005/02/06 20:19:22+01:00 pingc@wacom.com +262 -73
#   input: This patch adds support for a Wacom new tablet, Intuos3, and its associated
#   tools.
#   
#   From: Ping Cheng <pingc@wacom.com>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# ChangeSet
#   2005/02/06 19:56:01+01:00 vojtech@silver.ucw.cz 
#   input: Fix ExplorerPS/2 wheel emulation for wheel events > 8 ticks.
#   
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/mousedev.c
#   2005/02/06 19:55:46+01:00 vojtech@silver.ucw.cz +1 -1
#   input: Fix ExplorerPS/2 wheel emulation for wheel events > 8 ticks.
#   
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# ChangeSet
#   2005/02/06 19:49:20+01:00 vojtech@silver.ucw.cz 
#   input: Typo fix in parkbd.c comment
#   
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/serio/parkbd.c
#   2005/02/06 19:49:08+01:00 vojtech@silver.ucw.cz +1 -1
#   input: Typo fix in parkbd.c comment
#   
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# ChangeSet
#   2005/02/06 18:04:33+01:00 vojtech@silver.ucw.cz 
#   input: Document the adapter schematic needed for parkbd.c, right
#          in the source.
#   
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/serio/parkbd.c
#   2005/02/06 18:04:17+01:00 vojtech@silver.ucw.cz +33 -17
#   input: Document the adapter schematic needed for parkbd.c, right
#          in the source.
#   
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# ChangeSet
#   2005/02/06 15:55:16+01:00 akropel1@rochester.rr.com 
#   I have a buggy USB HID device (APC SmartUPS) in which the designers
#   forgot that ReportCount is a global item. Consequently, according to the
#   report descriptor, several reports have multiple copies of the same
#   usage in each field. When you actually query the device, however, only a
#   single copy of the usage is returned. hid-core catches the expected vs.
#   actual length mismatch and fails the transfer. This effectively makes
#   the buggy reports inaccessible even though enough data is present to
#   populate one usage (which is all userspace wants anyway).
#   
#   This patch changes hid-core to only warn (if debug is enabled) on such
#   reports rather than failing the transfer.
#   
#   Signed-off-by: Adam Kropelin <akropel1@rochester.rr.com>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/usb/input/hid-core.c
#   2005/02/06 15:55:02+01:00 akropel1@rochester.rr.com +1 -3
#   I have a buggy USB HID device (APC SmartUPS) in which the designers
#   forgot that ReportCount is a global item. Consequently, according to the
#   report descriptor, several reports have multiple copies of the same
#   usage in each field. When you actually query the device, however, only a
#   single copy of the usage is returned. hid-core catches the expected vs.
#   actual length mismatch and fails the transfer. This effectively makes
#   the buggy reports inaccessible even though enough data is present to
#   populate one usage (which is all userspace wants anyway).
#   
#   This patch changes hid-core to only warn (if debug is enabled) on such
#   reports rather than failing the transfer.
#   
#   Signed-off-by: Adam Kropelin <akropel1@rochester.rr.com>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# ChangeSet
#   2005/02/06 15:46:02+01:00 cl81@gmx.net 
#   input: Typo fix in atkbd.c comment
#   
#   From: Christian Ludwig <cl81@gmx.net>
#   Signed-off-by: Adrian Bunk <bunk@stusta.de>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/keyboard/atkbd.c
#   2005/02/06 15:45:37+01:00 cl81@gmx.net +1 -1
#   input: Typo fix in atkbd.c comment
#   
#   From: Christian Ludwig <cl81@gmx.net>
#   Signed-off-by: Adrian Bunk <bunk@stusta.de>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# ChangeSet
#   2005/02/06 14:34:19+01:00 deller@gmx.de 
#   input: HP HIL support (from PARISC Linux tree).
#   
#   From: Helge Deller <deller@gmx.de>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/serio/hp_sdc_mlc.c
#   2005/02/06 14:34:07+01:00 deller@gmx.de +358 -0
# 
# drivers/input/serio/hp_sdc_mlc.c
#   2005/02/06 14:34:07+01:00 deller@gmx.de +0 -0
#   BitKeeper file /home/vojtech/bk/input/drivers/input/serio/hp_sdc_mlc.c
# 
# drivers/input/serio/hp_sdc.c
#   2005/02/06 14:34:06+01:00 deller@gmx.de +1055 -0
# 
# drivers/input/serio/hil_mlc.c
#   2005/02/06 14:34:06+01:00 deller@gmx.de +949 -0
# 
# drivers/input/serio/hp_sdc.c
#   2005/02/06 14:34:06+01:00 deller@gmx.de +0 -0
#   BitKeeper file /home/vojtech/bk/input/drivers/input/serio/hp_sdc.c
# 
# drivers/input/serio/hil_mlc.c
#   2005/02/06 14:34:06+01:00 deller@gmx.de +0 -0
#   BitKeeper file /home/vojtech/bk/input/drivers/input/serio/hil_mlc.c
# 
# drivers/input/mouse/hil_ptr.c
#   2005/02/06 14:34:05+01:00 deller@gmx.de +414 -0
# 
# drivers/input/mouse/hil_ptr.c
#   2005/02/06 14:34:05+01:00 deller@gmx.de +0 -0
#   BitKeeper file /home/vojtech/bk/input/drivers/input/mouse/hil_ptr.c
# 
# drivers/input/misc/hp_sdc_rtc.c
#   2005/02/06 14:34:04+01:00 deller@gmx.de +724 -0
# 
# drivers/input/misc/hp_sdc_rtc.c
#   2005/02/06 14:34:04+01:00 deller@gmx.de +0 -0
#   BitKeeper file /home/vojtech/bk/input/drivers/input/misc/hp_sdc_rtc.c
# 
# drivers/input/keyboard/hilkbd.c
#   2005/02/06 14:34:03+01:00 deller@gmx.de +343 -0
# 
# drivers/input/keyboard/hilkbd.c
#   2005/02/06 14:34:03+01:00 deller@gmx.de +0 -0
#   BitKeeper file /home/vojtech/bk/input/drivers/input/keyboard/hilkbd.c
# 
# drivers/input/keyboard/hil_kbd.c
#   2005/02/06 14:34:01+01:00 deller@gmx.de +375 -0
# 
# drivers/input/serio/gscps2.c
#   2005/02/06 14:34:01+01:00 deller@gmx.de +2 -2
#   input: HP HIL support (from PARISC Linux tree).
#   
#   From: Helge Deller <deller@gmx.de>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/serio/Makefile
#   2005/02/06 14:34:01+01:00 deller@gmx.de +2 -0
#   input: HP HIL support (from PARISC Linux tree).
#   
#   From: Helge Deller <deller@gmx.de>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/serio/Kconfig
#   2005/02/06 14:34:01+01:00 deller@gmx.de +27 -1
#   input: HP HIL support (from PARISC Linux tree).
#   
#   From: Helge Deller <deller@gmx.de>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/mouse/Makefile
#   2005/02/06 14:34:01+01:00 deller@gmx.de +1 -0
#   input: HP HIL support (from PARISC Linux tree).
#   
#   From: Helge Deller <deller@gmx.de>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/mouse/Kconfig
#   2005/02/06 14:34:01+01:00 deller@gmx.de +8 -0
#   input: HP HIL support (from PARISC Linux tree).
#   
#   From: Helge Deller <deller@gmx.de>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/misc/Makefile
#   2005/02/06 14:34:01+01:00 deller@gmx.de +1 -0
#   input: HP HIL support (from PARISC Linux tree).
#   
#   From: Helge Deller <deller@gmx.de>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/misc/Kconfig
#   2005/02/06 14:34:01+01:00 deller@gmx.de +8 -0
#   input: HP HIL support (from PARISC Linux tree).
#   
#   From: Helge Deller <deller@gmx.de>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/keyboard/hpps2atkbd.h
#   2005/02/06 14:34:01+01:00 deller@gmx.de +4 -7
#   input: HP HIL support (from PARISC Linux tree).
#   
#   From: Helge Deller <deller@gmx.de>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/keyboard/hil_kbd.c
#   2005/02/06 14:34:01+01:00 deller@gmx.de +0 -0
#   BitKeeper file /home/vojtech/bk/input/drivers/input/keyboard/hil_kbd.c
# 
# drivers/input/keyboard/atkbd.c
#   2005/02/06 14:34:01+01:00 deller@gmx.de +8 -6
#   input: HP HIL support (from PARISC Linux tree).
#   
#   From: Helge Deller <deller@gmx.de>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/keyboard/Makefile
#   2005/02/06 14:34:01+01:00 deller@gmx.de +3 -0
#   input: HP HIL support (from PARISC Linux tree).
#   
#   From: Helge Deller <deller@gmx.de>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/keyboard/Kconfig
#   2005/02/06 14:34:01+01:00 deller@gmx.de +68 -0
#   input: HP HIL support (from PARISC Linux tree).
#   
#   From: Helge Deller <deller@gmx.de>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# ChangeSet
#   2005/02/06 13:58:37+01:00 vojtech@silver.ucw.cz 
#   input: Fix poll() behavior of input handlers on disconnect.
#   
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/tsdev.c
#   2005/02/06 13:58:22+01:00 vojtech@silver.ucw.cz +2 -4
#   input: Fix poll() behavior of input handlers on disconnect.
#   
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/mousedev.c
#   2005/02/06 13:58:22+01:00 vojtech@silver.ucw.cz +3 -3
#   input: Fix poll() behavior of input handlers on disconnect.
#   
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/joydev.c
#   2005/02/06 13:58:22+01:00 vojtech@silver.ucw.cz +5 -5
#   input: Fix poll() behavior of input handlers on disconnect.
#   
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/evdev.c
#   2005/02/06 13:58:22+01:00 vojtech@silver.ucw.cz +2 -3
#   input: Fix poll() behavior of input handlers on disconnect.
#   
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# ChangeSet
#   2005/02/06 11:18:28+01:00 vojtech@silver.ucw.cz 
#   input: Add MCC devices to HID blacklist, cleanup whitespace along
#          the way.
#   
#   From: Mark Glines <mark-pmd@glines.org>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/usb/input/hid-core.c
#   2005/02/06 11:18:17+01:00 vojtech@silver.ucw.cz +63 -62
#   input: Add MCC devices to HID blacklist, cleanup whitespace along
#          the way.
#   
#   From: Mark Glines <mark-pmd@glines.org>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# ChangeSet
#   2005/02/06 10:15:36+01:00 dtor_core@ameritech.net 
#   Input: add resume method to serio bus so ports are properly
#          set up at resume time. Remove calls to serio_reconnect
#          from i8042 as they should now be reconnected in course
#          of regular resume process.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/serio/serio.c
#   2005/02/06 10:15:22+01:00 dtor_core@ameritech.net +17 -0
#   Input: add resume method to serio bus so ports are properly
#          set up at resume time. Remove calls to serio_reconnect
#          from i8042 as they should now be reconnected in course
#          of regular resume process.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/serio/i8042.c
#   2005/02/06 10:15:22+01:00 dtor_core@ameritech.net +4 -4
#   Input: add resume method to serio bus so ports are properly
#          set up at resume time. Remove calls to serio_reconnect
#          from i8042 as they should now be reconnected in course
#          of regular resume process.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# ChangeSet
#   2005/02/06 10:13:52+01:00 vojtech@silver.ucw.cz 
#   input: New driver for ICS MicroClock MK712 TouchScreens.
#   
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/touchscreen/mk712.c
#   2005/02/06 10:13:39+01:00 vojtech@silver.ucw.cz +222 -0
# 
# drivers/input/touchscreen/mk712.c
#   2005/02/06 10:13:39+01:00 vojtech@silver.ucw.cz +0 -0
#   BitKeeper file /home/vojtech/bk/input/drivers/input/touchscreen/mk712.c
# 
# drivers/input/touchscreen/Makefile
#   2005/02/06 10:13:39+01:00 vojtech@silver.ucw.cz +2 -1
#   input: New driver for ICS MicroClock MK712 TouchScreens.
#   
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/touchscreen/Kconfig
#   2005/02/06 10:13:39+01:00 vojtech@silver.ucw.cz +11 -0
#   input: New driver for ICS MicroClock MK712 TouchScreens.
#   
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# ChangeSet
#   2005/02/05 23:12:30-05:00 jgarzik@pobox.com 
#   Merge pobox.com:/garz/repo/linux-2.6
#   into pobox.com:/garz/repo/libata-dev/remove-one-fix
# 
# drivers/scsi/libata-core.c
#   2005/02/05 23:12:26-05:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# ChangeSet
#   2005/02/05 23:08:09-05:00 adam@yggdrasil.com 
#   [PATCH] ata_pci_remove_one used freed memory
#   
#   	Attempting to unload a serial ATA driver module gave me a kernel
#   memory fault.  I think this problem occurs in all configurations, but
#   I should mention that my configuration may be slightly unusual in that
#   I configured my BIOS not to do IDE emulation with SATA disks, and I don't
#   actually have any disks plugged in.
#   
#   	The problem was that ata_pci_remove_one would call
#   scsi_host_put(ap->host), which would free the memory used to hold
#   host_set->ports, but host_set->ports was used later in ata_pci_remove_one.
#   
#   	So, the following patch reorders some of the steps in
#   ata_pci_remove_one and seems to eliminate the problem, at least to
#   the extent that I can unload and reload the module, although I do not
#   have a SATA disk handy for testing (I'm expecting one to arrive later
#   today).
#   
#   	The patch actually makes the code four lines shorter, although
#   two of those lines come from putting an assignement and variable
#   declaration in the same line.  Since the patch is a little hard to
#   read, here is a description of the edit steps.
#   
#   	1. Moved pci_release_regions() to toward the end of the routine
#   to facilitate merging the loops before and after it.  Also, I think that
#   calls that are good candidates for consolidating into the bus-level code
#   in the future (instead of individual drivers) are best put at the beginning
#   or end of the driver routines so that it is clearer if there would be
#   problems doing such consolidation.
#   
#   	2. Moved the cacluation of ioaddr into the only if-branch that
#   uses it.
#   
#   	3. Moved the call to scsi_host_put to after the code that
#   checks ATA_FLAG_NO_LEGACY.
#   
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/scsi/libata-core.c
#   2004/12/24 21:15:45-05:00 adam@yggdrasil.com +6 -10
#   ata_pci_remove_one used freed memory
# 
# ChangeSet
#   2005/02/05 20:08:22+01:00 rpurdie@rpsys.net 
#   input: Add support for Sharp SL-C7xx touchscreen (Corgi).
#   
#   From: Richard Purdie <rpurdie@rpsys.net>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/touchscreen/corgi_ts.c
#   2005/02/05 20:08:10+01:00 rpurdie@rpsys.net +380 -0
# 
# drivers/input/touchscreen/corgi_ts.c
#   2005/02/05 20:08:10+01:00 rpurdie@rpsys.net +0 -0
#   BitKeeper file /home/vojtech/bk/input/drivers/input/touchscreen/corgi_ts.c
# 
# drivers/input/touchscreen/Makefile
#   2005/02/05 20:08:10+01:00 rpurdie@rpsys.net +1 -0
#   input: Add support for Sharp SL-C7xx touchscreen (Corgi).
#   
#   From: Richard Purdie <rpurdie@rpsys.net>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/touchscreen/Kconfig
#   2005/02/05 20:08:10+01:00 rpurdie@rpsys.net +14 -1
#   input: Add support for Sharp SL-C7xx touchscreen (Corgi).
#   
#   From: Richard Purdie <rpurdie@rpsys.net>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# ChangeSet
#   2005/02/05 20:06:12+01:00 rpurdie@rpsys.net 
#   input: Add support for Sharp Zaurus SL-C7cc Corgi keyboards.
#   
#   From: Richard Purdie <rpurdie@rpsys.net>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/keyboard/corgikbd.c
#   2005/02/05 20:05:57+01:00 rpurdie@rpsys.net +363 -0
# 
# drivers/input/keyboard/corgikbd.c
#   2005/02/05 20:05:57+01:00 rpurdie@rpsys.net +0 -0
#   BitKeeper file /home/vojtech/bk/input/drivers/input/keyboard/corgikbd.c
# 
# drivers/input/keyboard/Makefile
#   2005/02/05 20:05:57+01:00 rpurdie@rpsys.net +1 -0
#   input: Add support for Sharp Zaurus SL-C7cc Corgi keyboards.
#   
#   From: Richard Purdie <rpurdie@rpsys.net>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/keyboard/Kconfig
#   2005/02/05 20:05:57+01:00 rpurdie@rpsys.net +16 -5
#   input: Add support for Sharp Zaurus SL-C7cc Corgi keyboards.
#   
#   From: Richard Purdie <rpurdie@rpsys.net>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# ChangeSet
#   2005/02/05 13:25:50+01:00 dtor_core@ameritech.net 
#   Input: make serio drivers register asynchronously. This should
#          speed up boot process as some drivers take a long time
#          probing for supported devices.
#   
#          Also change __inline__ to inline in serio.h
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# include/linux/serio.h
#   2005/02/05 13:25:37+01:00 dtor_core@ameritech.net +15 -10
#   Input: make serio drivers register asynchronously. This should
#          speed up boot process as some drivers take a long time
#          probing for supported devices.
#   
#          Also change __inline__ to inline in serio.h
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/serio/serio.c
#   2005/02/05 13:25:37+01:00 dtor_core@ameritech.net +36 -29
#   Input: make serio drivers register asynchronously. This should
#          speed up boot process as some drivers take a long time
#          probing for supported devices.
#   
#          Also change __inline__ to inline in serio.h
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# ChangeSet
#   2005/02/05 07:23:23+01:00 bunk@stusta.de 
#   input: This patch makes two needlessly global functions static.
#   
#   Signed-off-by: Adrian Bunk <bunk@stusta.de>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/gameport/cs461x.c
#   2005/02/05 07:23:10+01:00 bunk@stusta.de +2 -2
#   input: This patch makes two needlessly global functions static.
#   
#   Signed-off-by: Adrian Bunk <bunk@stusta.de>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# ChangeSet
#   2005/02/04 14:49:20-05:00 scjody@modernduck.com 
#   Merge modernduck.com:/usr/src/bk/linux-2.5
#   into modernduck.com:/usr/src/bk/1394-2.6
# 
# MAINTAINERS
#   2005/02/04 14:49:13-05:00 scjody@modernduck.com +0 -0
#   Auto merged
# 
# ChangeSet
#   2005/02/04 20:06:07+01:00 petero2@telia.com 
#   input: Only parse a "z == 127" packet as a relative Dualpoint stick
#   packet if the touchpad actually is a Dualpoint device.  The Glidepoint
#   modelsdon't have a stick, and can report z == 127 for a very wide finger.
#   If such a packet is parsed as a stick packet, the mouse pointer will
#   typically jump to one corner of the screen.
#   
#   Signed-off-by: Peter Osterlund <petero2@telia.com>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/mouse/alps.h
#   2005/02/04 20:05:52+01:00 petero2@telia.com +1 -0
#   input: Only parse a "z == 127" packet as a relative Dualpoint stick
#   packet if the touchpad actually is a Dualpoint device.  The Glidepoint
#   modelsdon't have a stick, and can report z == 127 for a very wide finger.
#   If such a packet is parsed as a stick packet, the mouse pointer will
#   typically jump to one corner of the screen.
#   
#   Signed-off-by: Peter Osterlund <petero2@telia.com>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/mouse/alps.c
#   2005/02/04 20:05:52+01:00 petero2@telia.com +10 -10
#   input: Only parse a "z == 127" packet as a relative Dualpoint stick
#   packet if the touchpad actually is a Dualpoint device.  The Glidepoint
#   modelsdon't have a stick, and can report z == 127 for a very wide finger.
#   If such a packet is parsed as a stick packet, the mouse pointer will
#   typically jump to one corner of the screen.
#   
#   Signed-off-by: Peter Osterlund <petero2@telia.com>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# ChangeSet
#   2005/02/04 20:04:21+01:00 petero2@telia.com 
#   input: When hardware tapping is disabled on an ALPS touchpad, the touchpad
#   generates exactly the same data for a single tap and a fast double
#   tap.  The effect is that the second tap in the double tap sequence is
#   lost.
#   
#   To fix this problem, this patch enables hardware tapping and converts
#   the resulting tap and gesture bits to standard finger pressure values
#   (z), which is what mousedev.c and the userspace X driver expects.
#   
#   Signed-off-by: Peter Osterlund <petero2@telia.com>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/mouse/alps.h
#   2005/02/04 20:04:09+01:00 petero2@telia.com +4 -0
#   input: When hardware tapping is disabled on an ALPS touchpad, the touchpad
#   generates exactly the same data for a single tap and a fast double
#   tap.  The effect is that the second tap in the double tap sequence is
#   lost.
#   
#   To fix this problem, this patch enables hardware tapping and converts
#   the resulting tap and gesture bits to standard finger pressure values
#   (z), which is what mousedev.c and the userspace X driver expects.
#   
#   Signed-off-by: Peter Osterlund <petero2@telia.com>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/mouse/alps.c
#   2005/02/04 20:04:09+01:00 petero2@telia.com +43 -10
#   input: When hardware tapping is disabled on an ALPS touchpad, the touchpad
#   generates exactly the same data for a single tap and a fast double
#   tap.  The effect is that the second tap in the double tap sequence is
#   lost.
#   
#   To fix this problem, this patch enables hardware tapping and converts
#   the resulting tap and gesture bits to standard finger pressure values
#   (z), which is what mousedev.c and the userspace X driver expects.
#   
#   Signed-off-by: Peter Osterlund <petero2@telia.com>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# ChangeSet
#   2005/02/04 15:41:37+01:00 zippel@linux-m68k.org 
#   input: Cleanup the Kconfig menus for the input subsystem.
#   
#   From: Roman Zippel <zippel@linux-m68k.org>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/touchscreen/Kconfig
#   2005/02/04 15:41:31+01:00 zippel@linux-m68k.org +5 -4
#   input: Cleanup the Kconfig menus for the input subsystem.
#   
#   From: Roman Zippel <zippel@linux-m68k.org>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/serio/Kconfig
#   2005/02/04 15:41:31+01:00 zippel@linux-m68k.org +14 -15
#   input: Cleanup the Kconfig menus for the input subsystem.
#   
#   From: Roman Zippel <zippel@linux-m68k.org>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/mouse/Kconfig
#   2005/02/04 15:41:31+01:00 zippel@linux-m68k.org +11 -12
#   input: Cleanup the Kconfig menus for the input subsystem.
#   
#   From: Roman Zippel <zippel@linux-m68k.org>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/misc/Kconfig
#   2005/02/04 15:41:31+01:00 zippel@linux-m68k.org +8 -7
#   input: Cleanup the Kconfig menus for the input subsystem.
#   
#   From: Roman Zippel <zippel@linux-m68k.org>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/keyboard/Kconfig
#   2005/02/04 15:41:31+01:00 zippel@linux-m68k.org +7 -9
#   input: Cleanup the Kconfig menus for the input subsystem.
#   
#   From: Roman Zippel <zippel@linux-m68k.org>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/joystick/Kconfig
#   2005/02/04 15:41:31+01:00 zippel@linux-m68k.org +20 -24
#   input: Cleanup the Kconfig menus for the input subsystem.
#   
#   From: Roman Zippel <zippel@linux-m68k.org>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/gameport/Kconfig
#   2005/02/04 15:41:31+01:00 zippel@linux-m68k.org +22 -26
#   input: Cleanup the Kconfig menus for the input subsystem.
#   
#   From: Roman Zippel <zippel@linux-m68k.org>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/Kconfig
#   2005/02/04 15:41:31+01:00 zippel@linux-m68k.org +13 -12
#   input: Cleanup the Kconfig menus for the input subsystem.
#   
#   From: Roman Zippel <zippel@linux-m68k.org>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# ChangeSet
#   2005/02/04 15:35:12+01:00 vojtech@suse.cz 
#   input: Add support for the Logitech MX1000 mouse in PS/2 mode.
# 
# drivers/input/mouse/logips2pp.c
#   2005/02/04 15:35:06+01:00 vojtech@suse.cz +5 -0
#   input: Add support for the Logitech MX1000 mouse in PS/2 mode.
# 
# ChangeSet
#   2005/02/04 14:35:55+01:00 gijoe@poczta.onet.pl 
#   input: Add support for Logitech MX300 mouse in PS/2 mode.
#   
#   From: Daniel Johnson <gijoe@poczta.onet.pl>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/mouse/logips2pp.c
#   2005/02/04 14:35:49+01:00 gijoe@poczta.onet.pl +10 -8
#   input: Add support for Logitech MX300 mouse in PS/2 mode.
#   
#   From: Daniel Johnson <gijoe@poczta.onet.pl>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# ChangeSet
#   2005/02/04 14:25:26+01:00 petero2@telia.com 
#   input: Correct Y axis range for ALPS touchpads.
#   
#   From: Peter Osterlund <petero2@telia.com>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/mouse/alps.c
#   2005/02/04 14:25:19+01:00 petero2@telia.com +1 -1
#   input: Correct Y axis range for ALPS touchpads.
#   
#   From: Peter Osterlund <petero2@telia.com>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# ChangeSet
#   2005/02/04 14:23:40+01:00 petero2@telia.com 
#   input: Here it is, with the suggestions from Pete and Dmitry included. The
#   patch does the following:
#   
#   * Compensates for the lack of floating point arithmetic by keeping
#     track of remainders from the integer divisions.
#   * Removes the xres/yres scaling so that you get the same speed in the
#     X and Y directions even if your screen does not the same aspect ratio
#     as your touchpad.
#   * Sets scale factors to make the speed for synaptics and alps equal to
#     each other and equal to the synaptics speed from 2.6.10.
#   
#   Signed-off-by: Peter Osterlund <petero2@telia.com>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/mousedev.c
#   2005/02/04 14:23:34+01:00 petero2@telia.com +19 -9
#   input: Here it is, with the suggestions from Pete and Dmitry included. The
#   patch does the following:
#   
#   * Compensates for the lack of floating point arithmetic by keeping
#     track of remainders from the integer divisions.
#   * Removes the xres/yres scaling so that you get the same speed in the
#     X and Y directions even if your screen does not the same aspect ratio
#     as your touchpad.
#   * Sets scale factors to make the speed for synaptics and alps equal to
#     each other and equal to the synaptics speed from 2.6.10.
#   
#   Signed-off-by: Peter Osterlund <petero2@telia.com>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# ChangeSet
#   2005/02/04 14:20:48+01:00 petero2@telia.com 
#   input: Some Synaptics touchpads have a middle mouse button that also works
#   as a scroll wheel.  Scroll data is reported as packets with w == 2 and
#   the scroll amount in byte 1, treated as a signed character.  For some
#   reason, the smallest possible wheel movement is reported as a scroll
#   amount of 4 units.  This amount is typically spread out over more than
#   one packet, so the driver has to accumulate scroll delta values to
#   correctly deal with this.
#   
#   Signed-off-by: Peter Osterlund <petero2@telia.com>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/mouse/synaptics.h
#   2005/02/04 14:20:41+01:00 petero2@telia.com +2 -0
#   input: Some Synaptics touchpads have a middle mouse button that also works
#   as a scroll wheel.  Scroll data is reported as packets with w == 2 and
#   the scroll amount in byte 1, treated as a signed character.  For some
#   reason, the smallest possible wheel movement is reported as a scroll
#   amount of 4 units.  This amount is typically spread out over more than
#   one packet, so the driver has to accumulate scroll delta values to
#   correctly deal with this.
#   
#   Signed-off-by: Peter Osterlund <petero2@telia.com>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/mouse/synaptics.c
#   2005/02/04 14:20:41+01:00 petero2@telia.com +26 -2
#   input: Some Synaptics touchpads have a middle mouse button that also works
#   as a scroll wheel.  Scroll data is reported as packets with w == 2 and
#   the scroll amount in byte 1, treated as a signed character.  For some
#   reason, the smallest possible wheel movement is reported as a scroll
#   amount of 4 units.  This amount is typically spread out over more than
#   one packet, so the driver has to accumulate scroll delta values to
#   correctly deal with this.
#   
#   Signed-off-by: Peter Osterlund <petero2@telia.com>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# ChangeSet
#   2005/02/04 14:16:34+01:00 petero2@telia.com 
#   input: mousedev_packet() incorrectly clears list->ready when called with
#   "tail == head - 1".  The effect is that the last mouse event from the
#   hardware isn't reported to user space until another hardware mouse
#   event arrives.  This can make the left mouse button get stuck when
#   tapping on a touchpad.  When this happens, the button doesn't unstick
#   until the next time you interact with the touchpad.
#   
#   Signed-off-by: Peter Osterlund <petero2@telia.com>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/mousedev.c
#   2005/02/04 14:16:28+01:00 petero2@telia.com +2 -2
#   input: mousedev_packet() incorrectly clears list->ready when called with
#   "tail == head - 1".  The effect is that the last mouse event from the
#   hardware isn't reported to user space until another hardware mouse
#   event arrives.  This can make the left mouse button get stuck when
#   tapping on a touchpad.  When this happens, the button doesn't unstick
#   until the next time you interact with the touchpad.
#   
#   Signed-off-by: Peter Osterlund <petero2@telia.com>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# ChangeSet
#   2005/02/04 14:13:08+01:00 rddunlap@osdl.org 
#   input: joydump_connect: reduce stack usage from 2048 to 44 bytes (on i386)
#   by allocating 'buf' dynamically;
#           struct joydump buf[BUF_SIZE]; // 2048 bytes
#   
#   Signed-off-by: Randy Dunlap <rddunlap@osdl.org>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/joystick/joydump.c
#   2005/02/04 14:13:02+01:00 rddunlap@osdl.org +27 -11
#   input: joydump_connect: reduce stack usage from 2048 to 44 bytes (on i386)
#   by allocating 'buf' dynamically;
#           struct joydump buf[BUF_SIZE]; // 2048 bytes
#   
#   Signed-off-by: Randy Dunlap <rddunlap@osdl.org>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# ChangeSet
#   2005/02/04 14:09:42+01:00 micah@navi.cx 
#   input: This patch adds support to uinput for Linux's force feedback interface.
#          With these changes, it's possible to write drivers for force feedback
#          joysticks and similar devices in userspace.  It also adds a way to set the
#          physical path of devices created via uinput, and it has a couple trivial
#          bugfixes.
#   
#   Signed-off-by: Micah Dowty <micah@navi.cx>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# include/linux/uinput.h
#   2005/02/04 14:09:36+01:00 micah@navi.cx +92 -0
#   input: This patch adds support to uinput for Linux's force feedback interface.
#          With these changes, it's possible to write drivers for force feedback
#          joysticks and similar devices in userspace.  It also adds a way to set the
#          physical path of devices created via uinput, and it has a couple trivial
#          bugfixes.
#   
#   Signed-off-by: Micah Dowty <micah@navi.cx>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/misc/uinput.c
#   2005/02/04 14:09:36+01:00 micah@navi.cx +204 -13
#   input: This patch adds support to uinput for Linux's force feedback interface.
#          With these changes, it's possible to write drivers for force feedback
#          joysticks and similar devices in userspace.  It also adds a way to set the
#          physical path of devices created via uinput, and it has a couple trivial
#          bugfixes.
#   
#   Signed-off-by: Micah Dowty <micah@navi.cx>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# ChangeSet
#   2005/02/04 14:06:43+01:00 vojtech@suse.cz 
#   input: Don't even try to reset the i8042 controller when it's not
#          willing to talk to us at all - it's probably not there.
#   
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/serio/i8042.h
#   2005/02/04 14:06:37+01:00 vojtech@suse.cz +2 -2
#   input: Don't even try to reset the i8042 controller when it's not
#          willing to talk to us at all - it's probably not there.
#   
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/serio/i8042.c
#   2005/02/04 14:06:37+01:00 vojtech@suse.cz +8 -4
#   input: Don't even try to reset the i8042 controller when it's not
#          willing to talk to us at all - it's probably not there.
#   
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# ChangeSet
#   2005/02/04 13:49:36+01:00 prarit@sgi.com 
#   Input: i8042 - call i8042_platform_exit to release resources
#          acquired by i8042_platform_init when controller
#          initialization fails.
#   
#   Signed-off-by: Prarit Bhargava <prarit@sgi.com>
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/serio/i8042.c
#   2005/02/04 13:49:30+01:00 prarit@sgi.com +7 -2
#   Input: i8042 - call i8042_platform_exit to release resources
#          acquired by i8042_platform_init when controller
#          initialization fails.
#   
#   Signed-off-by: Prarit Bhargava <prarit@sgi.com>
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# ChangeSet
#   2005/02/04 13:47:18+01:00 bunk@stusta.de 
#   Input: Make some needlessly global code static.
#   
#   Signed-off-by: Adrian Bunk <bunk@stusta.de>
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/tsdev.c
#   2005/02/04 13:47:12+01:00 bunk@stusta.de +1 -1
#   Input: Make some needlessly global code static.
#   
#   Signed-off-by: Adrian Bunk <bunk@stusta.de>
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/touchscreen/gunze.c
#   2005/02/04 13:47:12+01:00 bunk@stusta.de +2 -2
#   Input: Make some needlessly global code static.
#   
#   Signed-off-by: Adrian Bunk <bunk@stusta.de>
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/serio/serio_raw.c
#   2005/02/04 13:47:12+01:00 bunk@stusta.de +3 -3
#   Input: Make some needlessly global code static.
#   
#   Signed-off-by: Adrian Bunk <bunk@stusta.de>
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/serio/serio.c
#   2005/02/04 13:47:12+01:00 bunk@stusta.de +1 -1
#   Input: Make some needlessly global code static.
#   
#   Signed-off-by: Adrian Bunk <bunk@stusta.de>
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/serio/parkbd.c
#   2005/02/04 13:47:12+01:00 bunk@stusta.de +2 -2
#   Input: Make some needlessly global code static.
#   
#   Signed-off-by: Adrian Bunk <bunk@stusta.de>
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/serio/i8042.c
#   2005/02/04 13:47:12+01:00 bunk@stusta.de +5 -5
#   Input: Make some needlessly global code static.
#   
#   Signed-off-by: Adrian Bunk <bunk@stusta.de>
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/serio/ct82c710.c
#   2005/02/04 13:47:12+01:00 bunk@stusta.de +2 -2
#   Input: Make some needlessly global code static.
#   
#   Signed-off-by: Adrian Bunk <bunk@stusta.de>
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/mousedev.c
#   2005/02/04 13:47:12+01:00 bunk@stusta.de +1 -1
#   Input: Make some needlessly global code static.
#   
#   Signed-off-by: Adrian Bunk <bunk@stusta.de>
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/mouse/vsxxxaa.c
#   2005/02/04 13:47:12+01:00 bunk@stusta.de +2 -2
#   Input: Make some needlessly global code static.
#   
#   Signed-off-by: Adrian Bunk <bunk@stusta.de>
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/mouse/sermouse.c
#   2005/02/04 13:47:12+01:00 bunk@stusta.de +2 -2
#   Input: Make some needlessly global code static.
#   
#   Signed-off-by: Adrian Bunk <bunk@stusta.de>
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/mouse/psmouse-base.c
#   2005/02/04 13:47:12+01:00 bunk@stusta.de +2 -2
#   Input: Make some needlessly global code static.
#   
#   Signed-off-by: Adrian Bunk <bunk@stusta.de>
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/mouse/alps.c
#   2005/02/04 13:47:12+01:00 bunk@stusta.de +2 -2
#   Input: Make some needlessly global code static.
#   
#   Signed-off-by: Adrian Bunk <bunk@stusta.de>
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/misc/uinput.c
#   2005/02/04 13:47:12+01:00 bunk@stusta.de +1 -1
#   Input: Make some needlessly global code static.
#   
#   Signed-off-by: Adrian Bunk <bunk@stusta.de>
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/misc/pcspkr.c
#   2005/02/04 13:47:12+01:00 bunk@stusta.de +1 -1
#   Input: Make some needlessly global code static.
#   
#   Signed-off-by: Adrian Bunk <bunk@stusta.de>
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/keyboard/xtkbd.c
#   2005/02/04 13:47:12+01:00 bunk@stusta.de +6 -6
#   Input: Make some needlessly global code static.
#   
#   Signed-off-by: Adrian Bunk <bunk@stusta.de>
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/keyboard/sunkbd.c
#   2005/02/04 13:47:12+01:00 bunk@stusta.de +2 -2
#   Input: Make some needlessly global code static.
#   
#   Signed-off-by: Adrian Bunk <bunk@stusta.de>
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/keyboard/newtonkbd.c
#   2005/02/04 13:47:12+01:00 bunk@stusta.de +6 -6
#   Input: Make some needlessly global code static.
#   
#   Signed-off-by: Adrian Bunk <bunk@stusta.de>
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/keyboard/lkkbd.c
#   2005/02/04 13:47:12+01:00 bunk@stusta.de +2 -2
#   Input: Make some needlessly global code static.
#   
#   Signed-off-by: Adrian Bunk <bunk@stusta.de>
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/keyboard/atkbd.c
#   2005/02/04 13:47:12+01:00 bunk@stusta.de +2 -2
#   Input: Make some needlessly global code static.
#   
#   Signed-off-by: Adrian Bunk <bunk@stusta.de>
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/joystick/warrior.c
#   2005/02/04 13:47:12+01:00 bunk@stusta.de +2 -2
#   Input: Make some needlessly global code static.
#   
#   Signed-off-by: Adrian Bunk <bunk@stusta.de>
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/joystick/turbografx.c
#   2005/02/04 13:47:11+01:00 bunk@stusta.de +3 -3
#   Input: Make some needlessly global code static.
#   
#   Signed-off-by: Adrian Bunk <bunk@stusta.de>
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/joystick/tmdc.c
#   2005/02/04 13:47:11+01:00 bunk@stusta.de +2 -2
#   Input: Make some needlessly global code static.
#   
#   Signed-off-by: Adrian Bunk <bunk@stusta.de>
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/joystick/stinger.c
#   2005/02/04 13:47:11+01:00 bunk@stusta.de +2 -2
#   Input: Make some needlessly global code static.
#   
#   Signed-off-by: Adrian Bunk <bunk@stusta.de>
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/joystick/spaceorb.c
#   2005/02/04 13:47:11+01:00 bunk@stusta.de +2 -2
#   Input: Make some needlessly global code static.
#   
#   Signed-off-by: Adrian Bunk <bunk@stusta.de>
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/joystick/spaceball.c
#   2005/02/04 13:47:11+01:00 bunk@stusta.de +2 -2
#   Input: Make some needlessly global code static.
#   
#   Signed-off-by: Adrian Bunk <bunk@stusta.de>
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/joystick/sidewinder.c
#   2005/02/04 13:47:11+01:00 bunk@stusta.de +2 -2
#   Input: Make some needlessly global code static.
#   
#   Signed-off-by: Adrian Bunk <bunk@stusta.de>
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/joystick/magellan.c
#   2005/02/04 13:47:11+01:00 bunk@stusta.de +2 -2
#   Input: Make some needlessly global code static.
#   
#   Signed-off-by: Adrian Bunk <bunk@stusta.de>
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/joystick/interact.c
#   2005/02/04 13:47:11+01:00 bunk@stusta.de +2 -2
#   Input: Make some needlessly global code static.
#   
#   Signed-off-by: Adrian Bunk <bunk@stusta.de>
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/joystick/guillemot.c
#   2005/02/04 13:47:11+01:00 bunk@stusta.de +2 -2
#   Input: Make some needlessly global code static.
#   
#   Signed-off-by: Adrian Bunk <bunk@stusta.de>
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/joystick/grip.c
#   2005/02/04 13:47:11+01:00 bunk@stusta.de +2 -2
#   Input: Make some needlessly global code static.
#   
#   Signed-off-by: Adrian Bunk <bunk@stusta.de>
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/joystick/gf2k.c
#   2005/02/04 13:47:11+01:00 bunk@stusta.de +2 -2
#   Input: Make some needlessly global code static.
#   
#   Signed-off-by: Adrian Bunk <bunk@stusta.de>
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/joystick/gamecon.c
#   2005/02/04 13:47:11+01:00 bunk@stusta.de +2 -2
#   Input: Make some needlessly global code static.
#   
#   Signed-off-by: Adrian Bunk <bunk@stusta.de>
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/joystick/db9.c
#   2005/02/04 13:47:11+01:00 bunk@stusta.de +2 -2
#   Input: Make some needlessly global code static.
#   
#   Signed-off-by: Adrian Bunk <bunk@stusta.de>
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/joystick/cobra.c
#   2005/02/04 13:47:11+01:00 bunk@stusta.de +2 -2
#   Input: Make some needlessly global code static.
#   
#   Signed-off-by: Adrian Bunk <bunk@stusta.de>
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/joystick/analog.c
#   2005/02/04 13:47:11+01:00 bunk@stusta.de +3 -3
#   Input: Make some needlessly global code static.
#   
#   Signed-off-by: Adrian Bunk <bunk@stusta.de>
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/joystick/adi.c
#   2005/02/04 13:47:11+01:00 bunk@stusta.de +2 -2
#   Input: Make some needlessly global code static.
#   
#   Signed-off-by: Adrian Bunk <bunk@stusta.de>
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/joystick/a3d.c
#   2005/02/04 13:47:11+01:00 bunk@stusta.de +5 -5
#   Input: Make some needlessly global code static.
#   
#   Signed-off-by: Adrian Bunk <bunk@stusta.de>
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/input.c
#   2005/02/04 13:47:11+01:00 bunk@stusta.de +1 -1
#   Input: Make some needlessly global code static.
#   
#   Signed-off-by: Adrian Bunk <bunk@stusta.de>
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/gameport/vortex.c
#   2005/02/04 13:47:11+01:00 bunk@stusta.de +2 -2
#   Input: Make some needlessly global code static.
#   
#   Signed-off-by: Adrian Bunk <bunk@stusta.de>
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/gameport/ns558.c
#   2005/02/04 13:47:11+01:00 bunk@stusta.de +2 -2
#   Input: Make some needlessly global code static.
#   
#   Signed-off-by: Adrian Bunk <bunk@stusta.de>
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/gameport/lightning.c
#   2005/02/04 13:47:11+01:00 bunk@stusta.de +2 -2
#   Input: Make some needlessly global code static.
#   
#   Signed-off-by: Adrian Bunk <bunk@stusta.de>
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/gameport/fm801-gp.c
#   2005/02/04 13:47:11+01:00 bunk@stusta.de +2 -2
#   Input: Make some needlessly global code static.
#   
#   Signed-off-by: Adrian Bunk <bunk@stusta.de>
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/gameport/emu10k1-gp.c
#   2005/02/04 13:47:11+01:00 bunk@stusta.de +2 -2
#   Input: Make some needlessly global code static.
#   
#   Signed-off-by: Adrian Bunk <bunk@stusta.de>
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/evbug.c
#   2005/02/04 13:47:11+01:00 bunk@stusta.de +2 -2
#   Input: Make some needlessly global code static.
#   
#   Signed-off-by: Adrian Bunk <bunk@stusta.de>
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# ChangeSet
#   2005/02/04 13:44:14+01:00 dtor@mail.ru 
#   Input: serio - export id.type, id.proto, id.id and id.extra as
#          sysfs attributes to assist hotplug scripts in recovering
#          lost boot-time serio hotplug events.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/serio/serio.c
#   2005/02/04 13:44:08+01:00 dtor@mail.ru +28 -0
#   Input: serio - export id.type, id.proto, id.id and id.extra as
#          sysfs attributes to assist hotplug scripts in recovering
#          lost boot-time serio hotplug events.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# ChangeSet
#   2005/02/04 13:43:30+01:00 dtor@mail.ru 
#   Input: i8042 - fix 'noloop' module parameter description
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/serio/i8042.c
#   2005/02/04 13:43:24+01:00 dtor@mail.ru +1 -1
#   Input: i8042 - fix 'noloop' module parameter description
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# ChangeSet
#   2005/02/04 13:42:32+01:00 dtor@mail.ru 
#   Input: make serio's connect routines return error code
#          instead of void.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# include/linux/serio.h
#   2005/02/04 13:42:25+01:00 dtor@mail.ru +1 -1
#   Input: make serio's connect routines return error code
#          instead of void.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/touchscreen/h3600_ts_input.c
#   2005/02/04 13:42:25+01:00 dtor@mail.ru +10 -6
#   Input: make serio's connect routines return error code
#          instead of void.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/touchscreen/gunze.c
#   2005/02/04 13:42:25+01:00 dtor@mail.ru +8 -4
#   Input: make serio's connect routines return error code
#          instead of void.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/serio/serio_raw.c
#   2005/02/04 13:42:25+01:00 dtor@mail.ru +6 -3
#   Input: make serio's connect routines return error code
#          instead of void.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/serio/serio.c
#   2005/02/04 13:42:25+01:00 dtor@mail.ru +2 -4
#   Input: make serio's connect routines return error code
#          instead of void.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/mouse/vsxxxaa.c
#   2005/02/04 13:42:25+01:00 dtor@mail.ru +8 -4
#   Input: make serio's connect routines return error code
#          instead of void.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/mouse/sermouse.c
#   2005/02/04 13:42:25+01:00 dtor@mail.ru +8 -4
#   Input: make serio's connect routines return error code
#          instead of void.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/mouse/psmouse-base.c
#   2005/02/04 13:42:25+01:00 dtor@mail.ru +12 -3
#   Input: make serio's connect routines return error code
#          instead of void.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/keyboard/xtkbd.c
#   2005/02/04 13:42:25+01:00 dtor@mail.ru +8 -4
#   Input: make serio's connect routines return error code
#          instead of void.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/keyboard/sunkbd.c
#   2005/02/04 13:42:25+01:00 dtor@mail.ru +9 -5
#   Input: make serio's connect routines return error code
#          instead of void.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/keyboard/newtonkbd.c
#   2005/02/04 13:42:25+01:00 dtor@mail.ru +8 -4
#   Input: make serio's connect routines return error code
#          instead of void.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/keyboard/lkkbd.c
#   2005/02/04 13:42:25+01:00 dtor@mail.ru +9 -4
#   Input: make serio's connect routines return error code
#          instead of void.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/keyboard/atkbd.c
#   2005/02/04 13:42:25+01:00 dtor@mail.ru +10 -5
#   Input: make serio's connect routines return error code
#          instead of void.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/joystick/warrior.c
#   2005/02/04 13:42:25+01:00 dtor@mail.ru +8 -4
#   Input: make serio's connect routines return error code
#          instead of void.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/joystick/twidjoy.c
#   2005/02/04 13:42:25+01:00 dtor@mail.ru +8 -4
#   Input: make serio's connect routines return error code
#          instead of void.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/joystick/stinger.c
#   2005/02/04 13:42:25+01:00 dtor@mail.ru +7 -4
#   Input: make serio's connect routines return error code
#          instead of void.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/joystick/spaceorb.c
#   2005/02/04 13:42:25+01:00 dtor@mail.ru +9 -4
#   Input: make serio's connect routines return error code
#          instead of void.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/joystick/spaceball.c
#   2005/02/04 13:42:25+01:00 dtor@mail.ru +10 -5
#   Input: make serio's connect routines return error code
#          instead of void.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/joystick/magellan.c
#   2005/02/04 13:42:25+01:00 dtor@mail.ru +7 -4
#   Input: make serio's connect routines return error code
#          instead of void.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/joystick/iforce/iforce-serio.c
#   2005/02/04 13:42:25+01:00 dtor@mail.ru +10 -5
#   Input: make serio's connect routines return error code
#          instead of void.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# ChangeSet
#   2005/02/04 13:40:52+01:00 dtor@mail.ru 
#   Input: make serio implementation more in line with standard
#          driver model implementations. serio_register_port is
#          always asynchronous to allow freely registering child
#          ports. When deregistering serio core still takes care
#          of destroying children ports first.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# include/linux/serio.h
#   2005/02/04 13:40:45+01:00 dtor@mail.ru +12 -5
#   Input: make serio implementation more in line with standard
#          driver model implementations. serio_register_port is
#          always asynchronous to allow freely registering child
#          ports. When deregistering serio core still takes care
#          of destroying children ports first.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/serio/serio.c
#   2005/02/04 13:40:45+01:00 dtor@mail.ru +199 -163
#   Input: make serio implementation more in line with standard
#          driver model implementations. serio_register_port is
#          always asynchronous to allow freely registering child
#          ports. When deregistering serio core still takes care
#          of destroying children ports first.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/mouse/synaptics.c
#   2005/02/04 13:40:45+01:00 dtor@mail.ru +6 -4
#   Input: make serio implementation more in line with standard
#          driver model implementations. serio_register_port is
#          always asynchronous to allow freely registering child
#          ports. When deregistering serio core still takes care
#          of destroying children ports first.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/mouse/psmouse-base.c
#   2005/02/04 13:40:45+01:00 dtor@mail.ru +1 -10
#   Input: make serio implementation more in line with standard
#          driver model implementations. serio_register_port is
#          always asynchronous to allow freely registering child
#          ports. When deregistering serio core still takes care
#          of destroying children ports first.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# ChangeSet
#   2005/02/04 13:39:25+01:00 dtor@mail.ru 
#   Input: replace serio's type field with serio_id structure and
#          add id_table to serio drivers to split initial matching
#          and probing routines for better sysfs integration and
#          to assist hotplug scripts in loading proper drivers.
#          Add serio_hotplug to notify userspace about new ports.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# include/linux/serio.h
#   2005/02/04 13:39:19+01:00 dtor@mail.ru +24 -18
#   Input: replace serio's type field with serio_id structure and
#          add id_table to serio drivers to split initial matching
#          and probing routines for better sysfs integration and
#          to assist hotplug scripts in loading proper drivers.
#          Add serio_hotplug to notify userspace about new ports.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/serial/sunzilog.c
#   2005/02/04 13:39:19+01:00 dtor@mail.ru +4 -3
#   Input: replace serio's type field with serio_id structure and
#          add id_table to serio drivers to split initial matching
#          and probing routines for better sysfs integration and
#          to assist hotplug scripts in loading proper drivers.
#          Add serio_hotplug to notify userspace about new ports.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/serial/sunsu.c
#   2005/02/04 13:39:18+01:00 dtor@mail.ru +4 -3
#   Input: replace serio's type field with serio_id structure and
#          add id_table to serio drivers to split initial matching
#          and probing routines for better sysfs integration and
#          to assist hotplug scripts in loading proper drivers.
#          Add serio_hotplug to notify userspace about new ports.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/touchscreen/h3600_ts_input.c
#   2005/02/04 13:39:18+01:00 dtor@mail.ru +17 -6
#   Input: replace serio's type field with serio_id structure and
#          add id_table to serio drivers to split initial matching
#          and probing routines for better sysfs integration and
#          to assist hotplug scripts in loading proper drivers.
#          Add serio_hotplug to notify userspace about new ports.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/touchscreen/gunze.c
#   2005/02/04 13:39:18+01:00 dtor@mail.ru +16 -6
#   Input: replace serio's type field with serio_id structure and
#          add id_table to serio drivers to split initial matching
#          and probing routines for better sysfs integration and
#          to assist hotplug scripts in loading proper drivers.
#          Add serio_hotplug to notify userspace about new ports.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/serio/serport.c
#   2005/02/04 13:39:18+01:00 dtor@mail.ru +15 -5
#   Input: replace serio's type field with serio_id structure and
#          add id_table to serio drivers to split initial matching
#          and probing routines for better sysfs integration and
#          to assist hotplug scripts in loading proper drivers.
#          Add serio_hotplug to notify userspace about new ports.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/serio/serio_raw.c
#   2005/02/04 13:39:18+01:00 dtor@mail.ru +13 -3
#   Input: replace serio's type field with serio_id structure and
#          add id_table to serio drivers to split initial matching
#          and probing routines for better sysfs integration and
#          to assist hotplug scripts in loading proper drivers.
#          Add serio_hotplug to notify userspace about new ports.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/serio/serio.c
#   2005/02/04 13:39:18+01:00 dtor@mail.ru +66 -7
#   Input: replace serio's type field with serio_id structure and
#          add id_table to serio drivers to split initial matching
#          and probing routines for better sysfs integration and
#          to assist hotplug scripts in loading proper drivers.
#          Add serio_hotplug to notify userspace about new ports.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/serio/sa1111ps2.c
#   2005/02/04 13:39:18+01:00 dtor@mail.ru +1 -1
#   Input: replace serio's type field with serio_id structure and
#          add id_table to serio drivers to split initial matching
#          and probing routines for better sysfs integration and
#          to assist hotplug scripts in loading proper drivers.
#          Add serio_hotplug to notify userspace about new ports.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/serio/rpckbd.c
#   2005/02/04 13:39:18+01:00 dtor@mail.ru +1 -1
#   Input: replace serio's type field with serio_id structure and
#          add id_table to serio drivers to split initial matching
#          and probing routines for better sysfs integration and
#          to assist hotplug scripts in loading proper drivers.
#          Add serio_hotplug to notify userspace about new ports.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/serio/q40kbd.c
#   2005/02/04 13:39:18+01:00 dtor@mail.ru +1 -1
#   Input: replace serio's type field with serio_id structure and
#          add id_table to serio drivers to split initial matching
#          and probing routines for better sysfs integration and
#          to assist hotplug scripts in loading proper drivers.
#          Add serio_hotplug to notify userspace about new ports.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/serio/pcips2.c
#   2005/02/04 13:39:18+01:00 dtor@mail.ru +1 -1
#   Input: replace serio's type field with serio_id structure and
#          add id_table to serio drivers to split initial matching
#          and probing routines for better sysfs integration and
#          to assist hotplug scripts in loading proper drivers.
#          Add serio_hotplug to notify userspace about new ports.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/serio/parkbd.c
#   2005/02/04 13:39:18+01:00 dtor@mail.ru +1 -1
#   Input: replace serio's type field with serio_id structure and
#          add id_table to serio drivers to split initial matching
#          and probing routines for better sysfs integration and
#          to assist hotplug scripts in loading proper drivers.
#          Add serio_hotplug to notify userspace about new ports.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/serio/maceps2.c
#   2005/02/04 13:39:18+01:00 dtor@mail.ru +1 -1
#   Input: replace serio's type field with serio_id structure and
#          add id_table to serio drivers to split initial matching
#          and probing routines for better sysfs integration and
#          to assist hotplug scripts in loading proper drivers.
#          Add serio_hotplug to notify userspace about new ports.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/serio/i8042.c
#   2005/02/04 13:39:18+01:00 dtor@mail.ru +3 -3
#   Input: replace serio's type field with serio_id structure and
#          add id_table to serio drivers to split initial matching
#          and probing routines for better sysfs integration and
#          to assist hotplug scripts in loading proper drivers.
#          Add serio_hotplug to notify userspace about new ports.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/serio/gscps2.c
#   2005/02/04 13:39:18+01:00 dtor@mail.ru +1 -5
#   Input: replace serio's type field with serio_id structure and
#          add id_table to serio drivers to split initial matching
#          and probing routines for better sysfs integration and
#          to assist hotplug scripts in loading proper drivers.
#          Add serio_hotplug to notify userspace about new ports.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/serio/ct82c710.c
#   2005/02/04 13:39:18+01:00 dtor@mail.ru +1 -1
#   Input: replace serio's type field with serio_id structure and
#          add id_table to serio drivers to split initial matching
#          and probing routines for better sysfs integration and
#          to assist hotplug scripts in loading proper drivers.
#          Add serio_hotplug to notify userspace about new ports.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/serio/ambakmi.c
#   2005/02/04 13:39:18+01:00 dtor@mail.ru +1 -1
#   Input: replace serio's type field with serio_id structure and
#          add id_table to serio drivers to split initial matching
#          and probing routines for better sysfs integration and
#          to assist hotplug scripts in loading proper drivers.
#          Add serio_hotplug to notify userspace about new ports.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/mouse/vsxxxaa.c
#   2005/02/04 13:39:18+01:00 dtor@mail.ru +13 -5
#   Input: replace serio's type field with serio_id structure and
#          add id_table to serio drivers to split initial matching
#          and probing routines for better sysfs integration and
#          to assist hotplug scripts in loading proper drivers.
#          Add serio_hotplug to notify userspace about new ports.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/mouse/synaptics.c
#   2005/02/04 13:39:18+01:00 dtor@mail.ru +1 -1
#   Input: replace serio's type field with serio_id structure and
#          add id_table to serio drivers to split initial matching
#          and probing routines for better sysfs integration and
#          to assist hotplug scripts in loading proper drivers.
#          Add serio_hotplug to notify userspace about new ports.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/mouse/sermouse.c
#   2005/02/04 13:39:18+01:00 dtor@mail.ru +52 -6
#   Input: replace serio's type field with serio_id structure and
#          add id_table to serio drivers to split initial matching
#          and probing routines for better sysfs integration and
#          to assist hotplug scripts in loading proper drivers.
#          Add serio_hotplug to notify userspace about new ports.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/mouse/psmouse-base.c
#   2005/02/04 13:39:18+01:00 dtor@mail.ru +22 -8
#   Input: replace serio's type field with serio_id structure and
#          add id_table to serio drivers to split initial matching
#          and probing routines for better sysfs integration and
#          to assist hotplug scripts in loading proper drivers.
#          Add serio_hotplug to notify userspace about new ports.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/keyboard/xtkbd.c
#   2005/02/04 13:39:18+01:00 dtor@mail.ru +13 -3
#   Input: replace serio's type field with serio_id structure and
#          add id_table to serio drivers to split initial matching
#          and probing routines for better sysfs integration and
#          to assist hotplug scripts in loading proper drivers.
#          Add serio_hotplug to notify userspace about new ports.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/keyboard/sunkbd.c
#   2005/02/04 13:39:18+01:00 dtor@mail.ru +19 -6
#   Input: replace serio's type field with serio_id structure and
#          add id_table to serio drivers to split initial matching
#          and probing routines for better sysfs integration and
#          to assist hotplug scripts in loading proper drivers.
#          Add serio_hotplug to notify userspace about new ports.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/keyboard/newtonkbd.c
#   2005/02/04 13:39:18+01:00 dtor@mail.ru +13 -3
#   Input: replace serio's type field with serio_id structure and
#          add id_table to serio drivers to split initial matching
#          and probing routines for better sysfs integration and
#          to assist hotplug scripts in loading proper drivers.
#          Add serio_hotplug to notify userspace about new ports.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/keyboard/lkkbd.c
#   2005/02/04 13:39:18+01:00 dtor@mail.ru +13 -5
#   Input: replace serio's type field with serio_id structure and
#          add id_table to serio drivers to split initial matching
#          and probing routines for better sysfs integration and
#          to assist hotplug scripts in loading proper drivers.
#          Add serio_hotplug to notify userspace about new ports.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/keyboard/atkbd.c
#   2005/02/04 13:39:18+01:00 dtor@mail.ru +26 -7
#   Input: replace serio's type field with serio_id structure and
#          add id_table to serio drivers to split initial matching
#          and probing routines for better sysfs integration and
#          to assist hotplug scripts in loading proper drivers.
#          Add serio_hotplug to notify userspace about new ports.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/joystick/warrior.c
#   2005/02/04 13:39:18+01:00 dtor@mail.ru +14 -4
#   Input: replace serio's type field with serio_id structure and
#          add id_table to serio drivers to split initial matching
#          and probing routines for better sysfs integration and
#          to assist hotplug scripts in loading proper drivers.
#          Add serio_hotplug to notify userspace about new ports.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/joystick/twidjoy.c
#   2005/02/04 13:39:18+01:00 dtor@mail.ru +14 -4
#   Input: replace serio's type field with serio_id structure and
#          add id_table to serio drivers to split initial matching
#          and probing routines for better sysfs integration and
#          to assist hotplug scripts in loading proper drivers.
#          Add serio_hotplug to notify userspace about new ports.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/joystick/stinger.c
#   2005/02/04 13:39:18+01:00 dtor@mail.ru +16 -6
#   Input: replace serio's type field with serio_id structure and
#          add id_table to serio drivers to split initial matching
#          and probing routines for better sysfs integration and
#          to assist hotplug scripts in loading proper drivers.
#          Add serio_hotplug to notify userspace about new ports.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/joystick/spaceorb.c
#   2005/02/04 13:39:18+01:00 dtor@mail.ru +15 -5
#   Input: replace serio's type field with serio_id structure and
#          add id_table to serio drivers to split initial matching
#          and probing routines for better sysfs integration and
#          to assist hotplug scripts in loading proper drivers.
#          Add serio_hotplug to notify userspace about new ports.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/joystick/spaceball.c
#   2005/02/04 13:39:18+01:00 dtor@mail.ru +17 -7
#   Input: replace serio's type field with serio_id structure and
#          add id_table to serio drivers to split initial matching
#          and probing routines for better sysfs integration and
#          to assist hotplug scripts in loading proper drivers.
#          Add serio_hotplug to notify userspace about new ports.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/joystick/magellan.c
#   2005/02/04 13:39:18+01:00 dtor@mail.ru +16 -6
#   Input: replace serio's type field with serio_id structure and
#          add id_table to serio drivers to split initial matching
#          and probing routines for better sysfs integration and
#          to assist hotplug scripts in loading proper drivers.
#          Add serio_hotplug to notify userspace about new ports.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/joystick/iforce/iforce-serio.c
#   2005/02/04 13:39:18+01:00 dtor@mail.ru +15 -3
#   Input: replace serio's type field with serio_id structure and
#          add id_table to serio drivers to split initial matching
#          and probing routines for better sysfs integration and
#          to assist hotplug scripts in loading proper drivers.
#          Add serio_hotplug to notify userspace about new ports.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# ChangeSet
#   2005/02/04 13:36:53+01:00 dtor@mail.ru 
#   Input: remove serio->private in favor of using driver-specific data
#          in device structure, add serio_get_drvdata/serio_put_drvdata
#          to access it.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# include/linux/serio.h
#   2005/02/04 13:36:46+01:00 dtor@mail.ru +13 -1
#   Input: remove serio->private in favor of using driver-specific data
#          in device structure, add serio_get_drvdata/serio_put_drvdata
#          to access it.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/touchscreen/h3600_ts_input.c
#   2005/02/04 13:36:46+01:00 dtor@mail.ru +8 -5
#   Input: remove serio->private in favor of using driver-specific data
#          in device structure, add serio_get_drvdata/serio_put_drvdata
#          to access it.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/touchscreen/gunze.c
#   2005/02/04 13:36:46+01:00 dtor@mail.ru +7 -3
#   Input: remove serio->private in favor of using driver-specific data
#          in device structure, add serio_get_drvdata/serio_put_drvdata
#          to access it.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/serio/serio_raw.c
#   2005/02/04 13:36:46+01:00 dtor@mail.ru +6 -6
#   Input: remove serio->private in favor of using driver-specific data
#          in device structure, add serio_get_drvdata/serio_put_drvdata
#          to access it.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/mouse/vsxxxaa.c
#   2005/02/04 13:36:46+01:00 dtor@mail.ru +6 -3
#   Input: remove serio->private in favor of using driver-specific data
#          in device structure, add serio_get_drvdata/serio_put_drvdata
#          to access it.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/mouse/synaptics.c
#   2005/02/04 13:36:46+01:00 dtor@mail.ru +4 -3
#   Input: remove serio->private in favor of using driver-specific data
#          in device structure, add serio_get_drvdata/serio_put_drvdata
#          to access it.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/mouse/sermouse.c
#   2005/02/04 13:36:46+01:00 dtor@mail.ru +7 -4
#   Input: remove serio->private in favor of using driver-specific data
#          in device structure, add serio_get_drvdata/serio_put_drvdata
#          to access it.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/mouse/psmouse-base.c
#   2005/02/04 13:36:46+01:00 dtor@mail.ru +16 -13
#   Input: remove serio->private in favor of using driver-specific data
#          in device structure, add serio_get_drvdata/serio_put_drvdata
#          to access it.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/keyboard/xtkbd.c
#   2005/02/04 13:36:46+01:00 dtor@mail.ru +6 -3
#   Input: remove serio->private in favor of using driver-specific data
#          in device structure, add serio_get_drvdata/serio_put_drvdata
#          to access it.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/keyboard/sunkbd.c
#   2005/02/04 13:36:46+01:00 dtor@mail.ru +6 -3
#   Input: remove serio->private in favor of using driver-specific data
#          in device structure, add serio_get_drvdata/serio_put_drvdata
#          to access it.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/keyboard/newtonkbd.c
#   2005/02/04 13:36:46+01:00 dtor@mail.ru +7 -3
#   Input: remove serio->private in favor of using driver-specific data
#          in device structure, add serio_get_drvdata/serio_put_drvdata
#          to access it.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/keyboard/lkkbd.c
#   2005/02/04 13:36:46+01:00 dtor@mail.ru +5 -3
#   Input: remove serio->private in favor of using driver-specific data
#          in device structure, add serio_get_drvdata/serio_put_drvdata
#          to access it.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/keyboard/atkbd.c
#   2005/02/04 13:36:46+01:00 dtor@mail.ru +10 -8
#   Input: remove serio->private in favor of using driver-specific data
#          in device structure, add serio_get_drvdata/serio_put_drvdata
#          to access it.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/joystick/warrior.c
#   2005/02/04 13:36:46+01:00 dtor@mail.ru +6 -3
#   Input: remove serio->private in favor of using driver-specific data
#          in device structure, add serio_get_drvdata/serio_put_drvdata
#          to access it.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/joystick/twidjoy.c
#   2005/02/04 13:36:46+01:00 dtor@mail.ru +7 -3
#   Input: remove serio->private in favor of using driver-specific data
#          in device structure, add serio_get_drvdata/serio_put_drvdata
#          to access it.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/joystick/stinger.c
#   2005/02/04 13:36:46+01:00 dtor@mail.ru +7 -3
#   Input: remove serio->private in favor of using driver-specific data
#          in device structure, add serio_get_drvdata/serio_put_drvdata
#          to access it.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/joystick/spaceorb.c
#   2005/02/04 13:36:46+01:00 dtor@mail.ru +6 -3
#   Input: remove serio->private in favor of using driver-specific data
#          in device structure, add serio_get_drvdata/serio_put_drvdata
#          to access it.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/joystick/spaceball.c
#   2005/02/04 13:36:46+01:00 dtor@mail.ru +6 -3
#   Input: remove serio->private in favor of using driver-specific data
#          in device structure, add serio_get_drvdata/serio_put_drvdata
#          to access it.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/joystick/magellan.c
#   2005/02/04 13:36:46+01:00 dtor@mail.ru +6 -3
#   Input: remove serio->private in favor of using driver-specific data
#          in device structure, add serio_get_drvdata/serio_put_drvdata
#          to access it.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/joystick/iforce/iforce-serio.c
#   2005/02/04 13:36:46+01:00 dtor@mail.ru +10 -4
#   Input: remove serio->private in favor of using driver-specific data
#          in device structure, add serio_get_drvdata/serio_put_drvdata
#          to access it.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# ChangeSet
#   2005/02/04 13:33:07+01:00 dtor@mail.ru 
#   Input: use msecs_to_jiffies instead of manually calculating
#          delay for Toshiba bouncing keys workaround to the code
#          works with HZ != 1000.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/keyboard/atkbd.c
#   2005/02/04 13:33:01+01:00 dtor@mail.ru +1 -1
#   Input: use msecs_to_jiffies instead of manually calculating
#          delay for Toshiba bouncing keys workaround to the code
#          works with HZ != 1000.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# ChangeSet
#   2005/02/04 13:24:54+01:00 dtor@mail.ru 
#   Input: use msecs_to_jiffies instead of homegrown ms_to_jiffies
#          when setting timer for autorepeat handling. This will
#          make sure that autorepeat is scheduled correctly when
#          HZ != 1000.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/input.c
#   2005/02/04 13:24:47+01:00 dtor@mail.ru +4 -11
#   Input: use msecs_to_jiffies instead of homegrown ms_to_jiffies
#          when setting timer for autorepeat handling. This will
#          make sure that autorepeat is scheduled correctly when
#          HZ != 1000.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# ChangeSet
#   2005/02/04 13:22:01+01:00 dtor@mail.ru 
#   Input: twidjoy - apparently Kconfig and Makefile disagreed on the
#          name for config option so the module was never built.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/joystick/Kconfig
#   2005/02/04 13:21:54+01:00 dtor@mail.ru +1 -1
#   Input: twidjoy - apparently Kconfig and Makefile disagreed on the
#          name for config option so the module was never built.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# ChangeSet
#   2005/02/04 13:18:43+01:00 dtor@mail.ru 
#   Input: synaptics - use DMI to detect Toshiba Satellite notebooks
#          and automatically reduce touchpad reporting rate to 40 pps
#          as they have trouble handling high rate (80 pps).
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/mouse/synaptics.c
#   2005/02/04 13:18:37+01:00 dtor@mail.ru +26 -0
#   Input: synaptics - use DMI to detect Toshiba Satellite notebooks
#          and automatically reduce touchpad reporting rate to 40 pps
#          as they have trouble handling high rate (80 pps).
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# ChangeSet
#   2005/02/04 13:17:07+01:00 dtor@mail.ru 
#   Input: evdev - return -EINVAL from evdev_read if read buffer
#          is too small.
#   
#          Based on a patch by James Lamanna.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/evdev.c
#   2005/02/04 13:17:01+01:00 dtor@mail.ru +3 -0
#   Input: evdev - return -EINVAL from evdev_read if read buffer
#          is too small.
#   
#          Based on a patch by James Lamanna.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# ChangeSet
#   2005/02/04 13:14:06+01:00 dtor@mail.ru 
#   Input: rearrange serio event processing to get rid of duplicate
#          events - do not sumbit event into the event queue if similar
#          event has not been processed yet; also once event has been
#          processed check the queue and delete events of the same type
#          that have been accumulated in the mean time.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/serio/serio.c
#   2005/02/04 13:13:59+01:00 dtor@mail.ru +48 -9
#   Input: rearrange serio event processing to get rid of duplicate
#          events - do not sumbit event into the event queue if similar
#          event has not been processed yet; also once event has been
#          processed check the queue and delete events of the same type
#          that have been accumulated in the mean time.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# ChangeSet
#   2005/02/04 13:08:36+01:00 dtor@mail.ru 
#   Input: i8042 - make use of new serio start() and stop() callbacks
#          to ensure that i8042 interrupt handler that is shared among
#          several ports does not reference deleted ports. Also rename
#          i8042_valies structure to i8042_port, consolidate handling
#          of KBD, AUX and MUX ports, rearrange interrupt handler code.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/serio/i8042.h
#   2005/02/04 13:08:30+01:00 dtor@mail.ru +3 -3
#   Input: i8042 - make use of new serio start() and stop() callbacks
#          to ensure that i8042 interrupt handler that is shared among
#          several ports does not reference deleted ports. Also rename
#          i8042_valies structure to i8042_port, consolidate handling
#          of KBD, AUX and MUX ports, rearrange interrupt handler code.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/serio/i8042.c
#   2005/02/04 13:08:30+01:00 dtor@mail.ru +164 -160
#   Input: i8042 - make use of new serio start() and stop() callbacks
#          to ensure that i8042 interrupt handler that is shared among
#          several ports does not reference deleted ports. Also rename
#          i8042_valies structure to i8042_port, consolidate handling
#          of KBD, AUX and MUX ports, rearrange interrupt handler code.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# ChangeSet
#   2005/02/04 12:57:11+01:00 dtor@mail.ru 
#   Input: add serio->start() and serio->stop() callback methods that
#          are called whenever serio port is finishes being registered
#          or unregistered. The callbacks are useful for drivers that
#          share interrupt between several ports and there is a danger
#          that interrupt handler will reference port that was just
#          unregistered.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# include/linux/serio.h
#   2005/02/04 12:57:04+01:00 dtor@mail.ru +2 -0
#   Input: add serio->start() and serio->stop() callback methods that
#          are called whenever serio port is finishes being registered
#          or unregistered. The callbacks are useful for drivers that
#          share interrupt between several ports and there is a danger
#          that interrupt handler will reference port that was just
#          unregistered.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/serio/serio.c
#   2005/02/04 12:57:04+01:00 dtor@mail.ru +7 -1
#   Input: add serio->start() and serio->stop() callback methods that
#          are called whenever serio port is finishes being registered
#          or unregistered. The callbacks are useful for drivers that
#          share interrupt between several ports and there is a danger
#          that interrupt handler will reference port that was just
#          unregistered.
#   
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# ChangeSet
#   2005/02/04 12:55:58+01:00 dtor@mail.ru 
#   Input: i8042 - move panicblink with the rest of module parameters,
#          add proper entry to kernel-parameters.txt
#           
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# drivers/input/serio/i8042.c
#   2005/02/04 12:55:51+01:00 dtor@mail.ru +21 -9
#   Input: i8042 - move panicblink with the rest of module parameters,
#          add proper entry to kernel-parameters.txt
#           
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# Documentation/kernel-parameters.txt
#   2005/02/04 12:55:51+01:00 dtor@mail.ru +3 -0
#   Input: i8042 - move panicblink with the rest of module parameters,
#          add proper entry to kernel-parameters.txt
#           
#   Signed-off-by: Dmitry Torokhov <dtor@mail.ru>
#   Signed-off-by: Vojtech Pavlik <vojtech@suse.cz>
# 
# ChangeSet
#   2005/02/03 14:17:57-05:00 scjody@modernduck.com 
#   Re-added Ben Collins to 1394.
#   
#   Signed-off-by: Jody McIntyre <scjody@modernduck.com>
# 
# MAINTAINERS
#   2005/02/03 14:17:34-05:00 scjody@modernduck.com +6 -0
#   Re-added Ben Collins to 1394.
# 
# ChangeSet
#   2005/02/03 13:32:52-05:00 scjody@modernduck.com 
#   Merge modernduck.com:/usr/src/bk/linux-2.5
#   into modernduck.com:/usr/src/bk/1394-2.6
# 
# MAINTAINERS
#   2005/02/03 13:32:44-05:00 scjody@modernduck.com +0 -0
#   Auto merged
# 
# ChangeSet
#   2005/02/02 16:50:23-08:00 lkml@einar-lueck.de 
#   [IPV4]: Splitting of ip_route_{in,out}put_slow().
#   
#   From: Einar Lueck <lkml@einar-lueck.de>
#   
#   This patch splits up ip_route_[in|out]put_slow in inlined functions.
#   Basic idea:
#   * improve overall comprehensibility
#   * allow for an easier application of patch for improved multipath 
#     support
#   
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/ipv4/route.c
#   2005/02/02 16:49:29-08:00 lkml@einar-lueck.de +332 -207
#   [IPV4]: Splitting of ip_route_{in,out}put_slow().
# 
# BitKeeper/etc/ignore
#   2005/02/02 14:11:07-05:00 scjody@modernduck.com +3 -0
#   added patches/pcilynx-stack-reduction.patch patches/select-net.patch patches/series
# 
# ChangeSet
#   2005/02/02 13:33:22-05:00 scjody@modernduck.com 
#   1394 uses skbs, so select NET.
# 
# drivers/ieee1394/Kconfig
#   2005/02/02 13:32:57-05:00 scjody@modernduck.com +1 -0
#   1394 uses skbs, so select NET.
# 
# ChangeSet
#   2005/02/02 00:37:41-05:00 akpm@osdl.org 
#   [PATCH] use datacs in smc91x driver
#   
#   From: Ian Campbell <icampbell@arcom.com>
#   
#   Below is a patch to support the second 32-bit DATACS chipselect in the
#   smc91x driver to transfer data.  Support is enabled by adding a resource to
#   the platform device named 'smc91x-data32'.
#   
#   My platform has a 16-bit chip select for the primary IO region and no DMA.
#   I found that throughput went from roughly 50mbit/s to 80mbit/s.  I tested
#   by throwing UDP packets at it using mgen (9000 packets/second with UDP
#   payload of 1472 bytes is roughly 100mbit/s, I think) and counting the
#   packets received in 60s, I then did the same for transmitting.  The
#   measurements are very rough but the improvement seems fairly significant to
#   me.
#   
#   Patch was compiled for lubbock and neponset and compiled and tested on my
#   PXA platform.
#   
#   Signed-off-by: Ian Campbell <icampbell@arcom.com>
#   Signed-off-by: Nicolas Pitre <nico@cam.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/smc91x.h
#   2005/01/28 22:36:52-05:00 akpm@osdl.org +52 -7
#   use datacs in smc91x driver
# 
# drivers/net/smc91x.c
#   2005/01/28 22:36:52-05:00 akpm@osdl.org +108 -42
#   use datacs in smc91x driver
# 
# arch/arm/mach-sa1100/neponset.c
#   2005/01/28 22:36:52-05:00 akpm@osdl.org +2 -0
#   use datacs in smc91x driver
# 
# arch/arm/mach-pxa/lubbock.c
#   2005/01/28 22:36:52-05:00 akpm@osdl.org +2 -0
#   use datacs in smc91x driver
# 
# ChangeSet
#   2005/02/02 00:37:29-05:00 nico@cam.org 
#   [PATCH] smc91x: allow RX of VLAN packets
#   
#   This patch allows for VLAN packets to be received.  The initial patch
#   was from Andrew de Quincey.
#   
#   While there, it also adds a test against an impossible hardware state
#   in theory but that happened in practice where the chip returns a
#   packet length of 0 which, once the status words have been substracted,
#   causes the transfer of data with a negative length.  Flaky hardware is
#   probably to blame here but better guard ourselves against that than
#   crashing the kernel.  David Brownell was the happy victim of such hw.
#   
#   Signed-off-by: Nicolas Pitre <nico@cam.org>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/smc91x.c
#   2005/01/27 22:16:44-05:00 nico@cam.org +14 -2
#   smc91x: allow RX of VLAN packets
# 
# ChangeSet
#   2005/02/02 00:33:52-05:00 pavel@ucw.cz 
#   [PATCH] eepro100 kill obsolete ifdefs
#   
#   pci layer should provide enough dummy functions for such ugly hacks to
#   be unneccessary these days. Please apply,
#   
#   Signed-off-by: Pavel Machek <pavel@ucw.cz>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/eepro100.c
#   2005/01/12 05:22:37-05:00 pavel@ucw.cz +0 -10
#   eepro100 kill obsolete ifdefs
# 
# ChangeSet
#   2005/02/02 00:33:39-05:00 rddunlap@osdl.org 
#   [PATCH] ray_cs: reduce stack usage (sockaddr)
#   
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/wireless/ray_cs.c
#   2005/01/28 17:00:02-05:00 rddunlap@osdl.org +3 -2
#   ray_cs: reduce stack usage (sockaddr)
# 
# ChangeSet
#   2005/02/02 00:33:27-05:00 akpm@osdl.org 
#   [PATCH] remove bogus exports in ppp
#   
#   From: Paul Mackerras <paulus@samba.org>
#   
#   Remove unnecessary exports from ppp_generic.c.
#   
#   Signed-off-by: Christoph Hellwig <hch@lst.de>
#   Signed-off-by: Paul Mackerras <paulus@samba.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/ppp_generic.c
#   2005/01/27 10:58:35-05:00 akpm@osdl.org +0 -2
#   remove bogus exports in ppp
# 
# ChangeSet
#   2005/02/02 00:33:15-05:00 bunk@stusta.de 
#   [PATCH] remove dp83840.h
#   
#   dp83840.h is included once but none of the definitions it contains is
#   actually used.
#   
#   Signed-off-by: Adrian Bunk <bunk@stusta.de>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/ioc3-eth.c
#   2004/11/29 06:14:34-05:00 bunk@stusta.de +0 -1
#   remove dp83840.h
# 
# BitKeeper/deleted/.del-dp83840.h~b63222a569f252d9
#   2005/02/02 00:33:09-05:00 bunk@stusta.de +0 -0
#   Delete: include/linux/dp83840.h
# 
# ChangeSet
#   2005/02/02 00:26:35-05:00 ralf@linux-mips.org 
#   [PATCH] Reformat DMASCC driver
#   
#   Feed dmascc through indent, remove the RCS $Id string.
#   
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/hamradio/dmascc.c
#   2005/02/01 19:00:00-05:00 ralf@linux-mips.org +1082 -991
#   Reformat DMASCC driver
# 
# ChangeSet
#   2005/02/02 00:23:03-05:00 ralf@linux-mips.org 
#   [PATCH] Use netdev_priv in baycom_epp driver
#   
#   Eleminate the last remaining instance of a direct reference to the priv
#   member of struct net_device.  The paranoia check code of the same
#   type that has been eleminated from many other drivers, so do this here
#   also.
#   
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/hamradio/baycom_epp.c
#   2005/02/01 19:00:00-05:00 ralf@linux-mips.org +10 -43
#   Use netdev_priv in baycom_epp driver
# 
# ChangeSet
#   2005/02/02 00:22:51-05:00 ralf@linux-mips.org 
#   [PATCH] Use netdev_priv in baycom_ser_fdx driver
#   
#   Eleminate the last remaining instance of a direct reference to the priv
#   member of struct net_device.  This was debug code only, so use BUG_ON()
#   instead of printk.
#   
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/hamradio/baycom_ser_fdx.c
#   2005/02/01 19:00:00-05:00 ralf@linux-mips.org +3 -4
#   Use netdev_priv in baycom_ser_fdx driver
# 
# ChangeSet
#   2005/02/02 00:22:39-05:00 ralf@linux-mips.org 
#   [PATCH] Use netdev_priv in hdlcdrv driver
#   
#   Eleminate the last remaining instance of a direct reference to the priv
#   member of struct net_device.  The paranoia check code of the same
#   type that has been eleminated from many other drivers, so do this here
#   also.
#   
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/hamradio/hdlcdrv.c
#   2005/02/01 19:00:00-05:00 ralf@linux-mips.org +8 -40
#   Use netdev_priv in hdlcdrv driver
# 
# ChangeSet
#   2005/02/02 00:22:27-05:00 ralf@linux-mips.org 
#   [PATCH] Use netdev_priv in baycom_ser_hdx driver
#   
#   Eleminate the last remaining instance of a direct reference to the priv
#   member of struct net_device.  This was debug code only, so use BUG_ON()
#   instead of printk.
#   
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/hamradio/baycom_ser_hdx.c
#   2005/02/01 19:00:00-05:00 ralf@linux-mips.org +3 -4
#   Use netdev_priv in baycom_ser_hdx driver
# 
# ChangeSet
#   2005/02/02 00:22:15-05:00 ralf@linux-mips.org 
#   [PATCH] Use netdev_priv in baycom_par driver
#   
#   Eleminate the last remaining instance of a direct reference to the priv
#   member of struct net_device.  This was debug code only, so use BUG_ON()
#   instead of printk.
#   
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/hamradio/baycom_par.c
#   2005/02/01 19:00:00-05:00 ralf@linux-mips.org +4 -4
#   Use netdev_priv in baycom_par driver
# 
# ChangeSet
#   2005/02/02 00:22:03-05:00 ralf@linux-mips.org 
#   [PATCH] Use netdev_priv in bpqether driver
#   
#   Convert the bpqether driver to use netdev_priv().
#   
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/hamradio/bpqether.c
#   2005/02/01 19:00:00-05:00 ralf@linux-mips.org +7 -10
#   Use netdev_priv in bpqether driver
# 
# ChangeSet
#   2005/02/02 00:21:51-05:00 ralf@linux-mips.org 
#   [PATCH] Use netdev_priv in mkiss driver
#   
#   Convert the mkiss driver to use netdev_priv().
#   
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/hamradio/mkiss.c
#   2005/02/01 19:00:00-05:00 ralf@linux-mips.org +6 -6
#   Use netdev_priv in mkiss driver
# 
# ChangeSet
#   2005/02/02 00:21:39-05:00 ralf@linux-mips.org 
#   [PATCH] Use netdev_priv in YAM driver
#   
#    o Convert the YAM driver to use netdev_priv().
#    o If dev is valid there is no point in checking netdev_priv()'s return
#      value for being NULL.
#    o Fix build warning.
#   
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/hamradio/yam.c
#   2005/02/01 19:00:00-05:00 ralf@linux-mips.org +19 -19
#   Use netdev_priv in YAM driver
# 
# ChangeSet
#   2005/02/01 17:05:14-05:00 scjody@modernduck.com 
#   pcilynx.c:
#     pcilynx: reduce stack usage in add_card(),
#     from 800 to 308 bytes (on i386), by dynamically allocating
#             struct i2c_adapter i2c_adapter;  /* 492 bytes */
#   
#   Signed-off-by: Randy Dunlap <rddunlap@osdl.org>
#   Signed-off-by: Jody McIntyre <scjody@modernduck.com>
# 
# drivers/ieee1394/pcilynx.c
#   2005/02/01 17:03:20-05:00 scjody@modernduck.com +18 -11
#   pcilynx: reduce stack usage in add_card(),
#   from 800 to 308 bytes (on i386), by dynamically allocating
#           struct i2c_adapter i2c_adapter;  /* 492 bytes */
# 
# ChangeSet
#   2005/01/31 16:19:48-05:00 scjody@modernduck.com 
#   Update ieee1394 maintainers.
#   
#   Signed-off-by: Jody McIntyre <scjody@modernduck.com>
# 
# MAINTAINERS
#   2005/01/31 16:19:25-05:00 scjody@modernduck.com +18 -8
#   Update ieee1394 maintainers.
# 
# ChangeSet
#   2005/01/31 16:02:58-05:00 scjody@modernduck.com 
#   Fix PCILynx bus resets.
#   
#   Signed-off-by: Ben Collins <bcollins@debian.org>
#   Signed-off-by: Jody McIntyre <scjody@modernduck.com>
# 
# drivers/ieee1394/pcilynx.c
#   2005/01/31 16:02:35-05:00 scjody@modernduck.com +2 -2
#   Fix PCILynx bus resets.
# 
# ChangeSet
#   2005/01/31 15:51:07-05:00 scjody@modernduck.com 
#   Dan Dennedy: change allocation to GPF_ATOMIC to fix timing issue when this
#   is called from raw1394.c:arm_register().
#   
#   Signed-off-by: Jody McIntyre <scjody@modernduck.com>
# 
# drivers/ieee1394/highlevel.c
#   2005/01/31 15:50:32-05:00 scjody@modernduck.com +1 -1
#   Dan Dennedy: change allocation to GPF_ATOMIC to fix timing issue when this
#   is called from raw1394.c:arm_register().
#   
#   Signed-off-by: Jody McIntyre <scjody@modernduck.com>
# 
# ChangeSet
#   2005/01/31 15:50:09-05:00 scjody@modernduck.com 
#   Fix whitespace/indenting to match SVN.
#   
#   Signed-off-by: Jody McIntyre <scjody@modernduck.com>
# 
# drivers/ieee1394/eth1394.c
#   2005/01/31 15:49:38-05:00 scjody@modernduck.com +2 -2
#   Fix whitespace/indenting to match SVN.
#   
#   Signed-off-by: Jody McIntyre <scjody@modernduck.com>
# 
# ChangeSet
#   2005/01/31 15:47:36-05:00 scjody@modernduck.com 
#   Fix revisions to match svn
#   Signed-off-by: Jody McIntyre <scjody@modernduck.com>
# 
# drivers/ieee1394/ohci1394.c
#   2005/01/31 15:46:02-05:00 scjody@modernduck.com +1 -1
#   Fix revisions to match svn
#   Signed-off-by: Jody McIntyre <scjody@modernduck.com>
# 
# drivers/ieee1394/eth1394.c
#   2005/01/31 15:46:02-05:00 scjody@modernduck.com +2 -2
#   Fix revisions to match svn
#   Signed-off-by: Jody McIntyre <scjody@modernduck.com>
# 
# ChangeSet
#   2005/01/31 01:16:24-05:00 scjody@modernduck.com 
#   Dan Dennedy:
#   
#   reorganise LUN handling to resolve oops
#   
#   Signed-off-by: Jody McIntyre <scjody@modernduck.com>
# 
# drivers/ieee1394/nodemgr.c
#   2005/01/31 01:15:47-05:00 scjody@modernduck.com +2 -5
# 
# ChangeSet
#   2005/01/31 01:15:11-05:00 scjody@modernduck.com 
#   
#   Adds a disable_irm option to ieee1394.ko which disables all Isochronous
#   Resource Manager functionality, useful to work around certain problems,
#   e.g. iPod detection.
#   
#   Signed-off-by: Jody McIntyre <scjody@modernduck.com>
# 
# drivers/ieee1394/pcilynx.c
#   2005/01/31 01:14:29-05:00 scjody@modernduck.com +23 -16
# 
# drivers/ieee1394/ohci1394.c
#   2005/01/31 01:14:29-05:00 scjody@modernduck.com +8 -4
# 
# drivers/ieee1394/nodemgr.c
#   2005/01/31 01:14:29-05:00 scjody@modernduck.com +2 -1
# 
# drivers/ieee1394/ieee1394_core.h
#   2005/01/31 01:14:29-05:00 scjody@modernduck.com +1 -0
# 
# drivers/ieee1394/ieee1394_core.c
#   2005/01/31 01:14:29-05:00 scjody@modernduck.com +17 -1
# 
# drivers/ieee1394/ieee1394.h
#   2005/01/31 01:14:29-05:00 scjody@modernduck.com +24 -0
# 
# ChangeSet
#   2005/01/31 01:13:34-05:00 scjody@modernduck.com 
#   Dan Dennedy:
#   
#   bugfix for logical unit directory lun number
#   
#   Signed-off-by: Jody McIntyre <scjody@modernduck.com>
# 
# drivers/ieee1394/sbp2.c
#   2005/01/31 01:12:53-05:00 scjody@modernduck.com +4 -1
# 
# ChangeSet
#   2005/01/31 01:10:23-05:00 scjody@modernduck.com 
#   
#   Bugfix for Logical Unit Number in unit directory -- popular with multi-bay
#   enclosures -- while not breaking Logical Unit Directory.
#   
#   Signed-off-by: Dan Dennedy <dan@dennedy.org>
#   Signed-off-by: Jody McIntyre <scjody@modernduck.com>
# 
# drivers/ieee1394/sbp2.c
#   2005/01/31 01:09:18-05:00 scjody@modernduck.com +2 -2
# 
# drivers/ieee1394/nodemgr.h
#   2005/01/31 01:09:18-05:00 scjody@modernduck.com +2 -0
# 
# drivers/ieee1394/nodemgr.c
#   2005/01/31 01:09:17-05:00 scjody@modernduck.com +20 -5
# 
# ChangeSet
#   2005/01/31 01:08:05-05:00 scjody@modernduck.com 
#   
#   Fixed removal of old partial datagrams.  Since max_partial_datagrams can
#   be changed at runtime, there may be _more_ than max_partial_datagrams
#   in the list.  Also removed obsolote comment.
#   
#   Signed-off-by: Jody McIntyre <scjody@modernduck.com>
# 
# drivers/ieee1394/eth1394.c
#   2005/01/31 01:07:26-05:00 scjody@modernduck.com +2 -3
# 
# ChangeSet
#   2005/01/31 01:06:59-05:00 scjody@modernduck.com 
#   
#   dma.c vfree() checking cleanups.
#   
#   Signed-off by: James Lamanna <jlamanna@gmail.com>
#   Signed-off-by: Domen Puncer <domen@coderock.org>
#   Signed-off-by: Jody McIntyre <scjody@modernduck.com>
# 
# drivers/ieee1394/dma.c
#   2005/01/31 01:06:22-05:00 scjody@modernduck.com +5 -9
# 
# ChangeSet
#   2005/01/31 01:05:55-05:00 scjody@modernduck.com 
#   
#   Sets the sendtime of a packet _before_ adding it to pending_packet_queue,
#   to prevent premature expiry (which leads to "unsolicited response packet"
#   errors, among other things).
#   
#   Signed-off-by: Jody McIntyre <scjody@modernduck.com>
# 
# drivers/ieee1394/ieee1394_core.c
#   2005/01/31 01:05:18-05:00 scjody@modernduck.com +1 -0
# 
# ChangeSet
#   2005/01/31 01:04:34-05:00 scjody@modernduck.com 
#   
#   We need to update the old csr1212 cache's bus generation after a bus
#   reset once we decide it is still valid.
#   Closes a vmalloc leak on *every* bus reset.
#   
#   Signed-off-by: Jim Radford <radford@indigita.com>
#   Signed-off-by: Jody McIntyre <scjody@modernduck.com>
# 
# drivers/ieee1394/nodemgr.c
#   2005/01/31 01:03:52-05:00 scjody@modernduck.com +7 -0
# 
# ChangeSet
#   2005/01/31 01:03:20-05:00 scjody@modernduck.com 
#   
#   This closes a small vmalloc leak on insmod/rmmod.
#   
#   Signed-off-by: Jim Radford <radford@indigita.com>
#   Signed-off-by: Jody McIntyre <scjody@modernduck.com>
# 
# drivers/ieee1394/config_roms.c
#   2005/01/31 01:02:41-05:00 scjody@modernduck.com +1 -1
# 
# ChangeSet
#   2005/01/31 01:00:27-05:00 scjody@modernduck.com 
#   
#   Dan Dennedy:
#   
#   Ignore any return value from devfs since it is non-critical, and a
#   EEXIST return prevents the module from loading!
#   
#   Signed-off-by: Jody McIntyre <scjody@modernduck.com>
# 
# drivers/ieee1394/raw1394.c
#   2005/01/31 00:59:32-05:00 scjody@modernduck.com +1 -4
# 
# ChangeSet
#   2005/01/31 00:58:01-05:00 scjody@modernduck.com 
#   
#   Move simple class to ieee1394 core and register as
#   /sys/class/ieee1394_protocol.
#   Add sysfs/udev support to video1394 and dv1394 using simple class
#   ieee1394_protocol.
#   
#   Signed-off-by: Dan Dennedy <dan@dennedy.org>
#   Signed-off-by: Jody McIntyre <scjody@modernduck.com>
# 
# drivers/ieee1394/video1394.c
#   2005/01/31 00:57:19-05:00 scjody@modernduck.com +8 -2
# 
# drivers/ieee1394/raw1394.c
#   2005/01/31 00:57:18-05:00 scjody@modernduck.com +16 -25
# 
# drivers/ieee1394/ieee1394_core.h
#   2005/01/31 00:57:18-05:00 scjody@modernduck.com +1 -0
# 
# drivers/ieee1394/ieee1394_core.c
#   2005/01/31 00:57:18-05:00 scjody@modernduck.com +13 -3
# 
# drivers/ieee1394/dv1394.c
#   2005/01/31 00:57:18-05:00 scjody@modernduck.com +5 -0
# 
# ChangeSet
#   2005/01/31 00:56:15-05:00 scjody@modernduck.com 
#   Cleanup with Lindent.
#   
#   Signed-off-by: Jody McIntyre <scjody@modernduck.com>
# 
# drivers/ieee1394/raw1394.c
#   2005/01/31 00:51:42-05:00 scjody@modernduck.com +1525 -1538
# 
# ChangeSet
#   2005/01/31 00:49:36-05:00 scjody@modernduck.com 
#   Some Lindent cleanup (most removed to its own patch by scjody)
#   Adds basic sysfs support for udev etc.
#   
#   Signed-off-by: Daniel Drake <dsd@gentoo.org>
#   Signed-off-by: Jody McIntyre <scjody@modernduck.com>
# 
# drivers/ieee1394/raw1394.c
#   2005/01/31 00:47:36-05:00 scjody@modernduck.com +531 -335
# 
# ChangeSet
#   2005/01/31 00:34:02-05:00 scjody@modernduck.com 
#   
#   Change some variables and functions that were needlessly global static.
#   Removes several functions that weren't used anywhere in the kernel.
#   Removes many unnecessary EXPORT_SYMBOL's.
#   
#   Signed-off-by: Adrian Bunk <bunk@stusta.de>
#   Signed-off-by: Jody McIntyre <scjody@modernduck.com>
# 
# drivers/ieee1394/video1394.c
#   2005/01/31 00:33:22-05:00 scjody@modernduck.com +5 -5
# 
# drivers/ieee1394/sbp2.c
#   2005/01/31 00:33:22-05:00 scjody@modernduck.com +2 -2
# 
# drivers/ieee1394/nodemgr.c
#   2005/01/31 00:33:22-05:00 scjody@modernduck.com +2 -45
# 
# drivers/ieee1394/ieee1394_transactions.c
#   2005/01/31 00:33:22-05:00 scjody@modernduck.com +0 -28
# 
# drivers/ieee1394/ieee1394_core.h
#   2005/01/31 00:33:22-05:00 scjody@modernduck.com +0 -1
# 
# drivers/ieee1394/ieee1394_core.c
#   2005/01/31 00:33:22-05:00 scjody@modernduck.com +3 -27
# 
# drivers/ieee1394/highlevel.c
#   2005/01/31 00:33:22-05:00 scjody@modernduck.com +0 -32
# 
# drivers/ieee1394/dv1394.c
#   2005/01/31 00:33:22-05:00 scjody@modernduck.com +1 -1
# 
# drivers/ieee1394/amdtp.c
#   2005/01/31 00:33:22-05:00 scjody@modernduck.com +8 -8
# 
# ChangeSet
#   2005/01/31 00:32:16-05:00 scjody@modernduck.com 
#   
#   Fixes a bug in the channel reservation :
#   If dma resources allocation fails, the channel was not freed.  I fixed
#   that by marking the channel allocated after the dma resources allocation
#   succeeded.  Also changed the error return value from ioctl.
#   
#   Signed-off-by: Philippe De Muyter <phdm at macqel dot be>
#   Signed-off-by: Dan Dennedy <dan@dennedy.org>
#   Signed-off-by: Jody McIntyre <scjody@modernduck.com>
# 
# drivers/ieee1394/video1394.c
#   2005/01/31 00:31:38-05:00 scjody@modernduck.com +55 -37
# 
# ChangeSet
#   2005/01/30 23:28:23-05:00 scjody@modernduck.com 
#   Damien Douxchamps:
#   
#   I have tested and updated a patch from Randy Dunlap that fixes missing
#   entries in the modules.ieee1394map file. The patch is against latest SVN
#   (1234).
#   
#   The patch adds the following entries for IIDC cameras that would not be
#   detected otherwise:
#   
#   video1394            0x0000000c  0x000000  0x000000 0x00a02d     0x000101
#   video1394            0x0000000c  0x000000  0x000000 0x00a02d     0x000102
#   raw1394              0x0000000c  0x000000  0x000000 0x00a02d     0x000101
#   raw1394              0x0000000c  0x000000  0x000000 0x00a02d     0x000102
#   
#   This is necessary because the IIDC consortium interpreted the 1394
#   specifications differently. They have been summoned by the 1394TA to
#   change their numbering policy so that these entries are final and will
#   not grow forever in number.
#   
#   Signed-off-by: Jody McIntyre <scjody@modernduck.com>
# 
# drivers/ieee1394/video1394.c
#   2005/01/30 23:27:16-05:00 scjody@modernduck.com +10 -0
# 
# drivers/ieee1394/raw1394.c
#   2005/01/30 23:27:07-05:00 scjody@modernduck.com +10 -0
# 
# ChangeSet
#   2005/01/30 23:24:06-05:00 scjody@modernduck.com 
#   From Stefan Richter:
#   
#   In trunk/ohci1394.c, duplicate code has slipped in which sets 
#   max_packet_size to 512 and prints a log notice. See "Serial EEPROM 
#   Sanity check" further down in ohci_initialize(). Since the latter code 
#   is more appropriate, the former is deleted by the attached patch.
#   
#   Signed-off-by: Jody McIntyre <scjody@modernduck.com>
# 
# drivers/ieee1394/ohci1394.c
#   2005/01/30 23:20:38-05:00 scjody@modernduck.com +0 -6
# 
# ChangeSet
#   2005/01/30 23:00:14-05:00 scjody@modernduck.com 
#   This patch makes sure we check the return value of copy_to_user() in
#   drivers/ieee1394/raw1394.c::raw1394_read() with the added bonus of
#   silencing this warning:
#   include/asm/uaccess.h: In function `raw1394_read':
#   drivers/ieee1394/raw1394.c:446: warning: ignoring return value of `__copy_to_user', declared with attribute warn_unused_result
#   
#   I've submitted this before, but never got an ACK or NACK, and the patch is
#   still relevant against latest Linus bk (2.6.10-rc2-bk11 atm).
#   
#   
#   Signed-off-by: Jesper Juhl <juhl-lkml@dif.dk>
#   Signed-off-by: Jody McIntyre <scjody@modernduck.com>
# 
# drivers/ieee1394/raw1394.c
#   2005/01/30 22:58:41-05:00 scjody@modernduck.com +8 -2
# 
# ChangeSet
#   2005/01/30 22:30:46-05:00 scjody@modernduck.com 
#   Olaf Hering: Fix sw-suspend issue
#   
#   sw-suspend does not work with our kernel.
#   khpsbpkt will die because down_interruptible returns -EINTR on suspend.
#   As a result, hpsb packet delivery will not work anymore after resume.
#   
#   Signed-off-by: Jody McIntyre <scjody@modernduck.com>
# 
# drivers/ieee1394/ieee1394_core.c
#   2005/01/30 22:28:36-05:00 scjody@modernduck.com +10 -6
# 
# ChangeSet
#   2005/01/30 22:11:26-05:00 scjody@modernduck.com 
#   Christoph Hellwig: avoid obsolete scsi APIs in sbp2
#   
#   Signed-off-by: Jody McIntyre <scjody@modernduck.com>
# 
# drivers/ieee1394/sbp2.h
#   2005/01/30 22:10:07-05:00 scjody@modernduck.com +9 -7
# 
# drivers/ieee1394/sbp2.c
#   2005/01/30 22:10:07-05:00 scjody@modernduck.com +36 -33
# 
# ChangeSet
#   2005/01/29 15:28:42-05:00 scjody@modernduck.com 
#   fix nodemgr parsing subdirectories in unit directory and tiny bugfix in
#   sbp2 unit directory parsing (for PowerFile)
#   
#   Signed-off-by: Jody McIntyre <scjody@modernduck.com>
# 
# drivers/ieee1394/sbp2.c
#   2005/01/29 15:28:18-05:00 scjody@modernduck.com +1 -1
# 
# drivers/ieee1394/nodemgr.c
#   2005/01/29 15:28:18-05:00 scjody@modernduck.com +59 -48
# 
# ChangeSet
#   2005/01/29 15:27:50-05:00 scjody@modernduck.com 
#   
#   Fix GCC 3.4 compile error with inline keyword in function prototype.
#   
#   Signed-off-by: Adrian Bunk <bunk@fs.tum.de>
#   Signed-off-by: Steve Kinneberg <kberg@linux1394.org>
#   Signed-off-by: Jody McIntyre <scjody@modernduck.com>
# 
# drivers/ieee1394/eth1394.c
#   2005/01/29 15:27:27-05:00 scjody@modernduck.com +2 -2
# 
# ChangeSet
#   2005/01/29 15:25:53-05:00 scjody@modernduck.com 
#   
#   Use wmb() to make sure things get flushed before setting the wakup bit.
#   
#   Signed-off-by: Ben Collins <bcollins@debian.org>
#   Submitted-by: Keith Bengston <Keith.Bengston@csiro.au>
#   Signed-off-by: Jody McIntyre <scjody@modernduck.com>
# 
# drivers/ieee1394/ohci1394.c
#   2005/01/29 15:25:30-05:00 scjody@modernduck.com +4 -0
# 
# ChangeSet
#   2005/01/29 15:24:28-05:00 scjody@modernduck.com 
#   
#   Fix buffer overflow in csr1212.c.
#   
#   Signed-off-by: Steve Kinneberg <kberg@linux13294.org>
#   Signed-off-by: Jody McIntyre <scjody@modernduck.com>
# 
# drivers/ieee1394/csr1212.c
#   2005/01/29 15:24:05-05:00 scjody@modernduck.com +5 -2
# 
# ChangeSet
#   2005/01/29 15:21:50-05:00 scjody@modernduck.com 
#   
#   Fix bug where 4 times Extended ROM Leaf size would be read when parsing in csr1212.  Added NULL check for csr1212_rom_cache_malloc return value.
#   
#   Signed-off-by: Steve Kinneberg <kberg@linux1394.org>
#   Signed-off-by: Jody McIntyre <scjody@modernduck.com>
# 
# drivers/ieee1394/csr1212.c
#   2005/01/29 15:21:26-05:00 scjody@modernduck.com +7 -5
# 
# ChangeSet
#   2005/01/29 15:16:50-05:00 scjody@modernduck.com 
#   
#   Fix bugs generating and parsing ConfigROMs with Extended ROM entries.
#   
#   Signed-off-by: Steve Kinneberg <kberg@linux1394.org>
#   Signed-off-by: Jody McIntyre <scjody@modernduck.com>
# 
# drivers/ieee1394/csr1212.c
#   2005/01/29 15:16:02-05:00 scjody@modernduck.com +75 -44
# 
# ChangeSet
#   2005/01/28 00:16:10-05:00 ralf@linux-mips.org 
#   [PATCH] SGI Seeq updates
#   
#    o Support for setting the MAC address
#    o Make some sort of attempt at dealing with multicast in order to support
#      IPv6 etc.  The Seeq 8003 was built in the assumption nobody was ever going
#      to need multicast, it seems.
#   
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/sgiseeq.c
#   2005/01/27 21:11:40-05:00 ralf@linux-mips.org +52 -18
#   SGI Seeq updates
# 
# ChangeSet
#   2005/01/28 00:15:58-05:00 ralf@linux-mips.org 
#   [PATCH] SB1250 driver updates
#   
#    o Fix initialization of internal sbmac eth1
#    o Clean up comments
#    o Add in new module parameter handling
#    o Fix printing of device name before register_netdevice
#   
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/sb1250-mac.c
#   2005/01/27 21:08:04-05:00 ralf@linux-mips.org +58 -51
#   SB1250 driver updates
# 
# ChangeSet
#   2005/01/28 00:15:46-05:00 ralf@linux-mips.org 
#   [PATCH] S2IO syntax fixes
#   
#   Syntactic nitpicking - C wants a space between the "include" and "<" just
#   gcc happens to be tollerant.
#   
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/s2io.c
#   2005/01/27 21:05:03-05:00 ralf@linux-mips.org +23 -22
#   S2IO syntax fixes
# 
# ChangeSet
#   2005/01/28 00:15:32-05:00 ralf@linux-mips.org 
#   [PATCH] Meth driver updates
#   
#   General driver updates, now approaching reliability of some definition.
#   
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/meth.h
#   2005/01/27 21:03:34-05:00 ralf@linux-mips.org +1 -1
#   Meth driver updates
# 
# drivers/net/meth.c
#   2005/01/27 21:03:34-05:00 ralf@linux-mips.org +143 -132
#   Meth driver updates
# 
# ChangeSet
#   2005/01/28 00:12:42-05:00 ralf@linux-mips.org 
#   [PATCH] Marvell MV-64340 driver upda
#   
#    o Momentum Ocelot 3 also features a MV-64340
#    o Momentum Jaguar ATX does not need the special casing in the driver.
#   
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/mv643xx_eth.c
#   2005/01/27 21:01:51-05:00 ralf@linux-mips.org +0 -2
#   Marvell MV-64340 driver upda
# 
# drivers/net/Kconfig
#   2005/01/27 21:01:51-05:00 ralf@linux-mips.org +1 -1
#   Marvell MV-64340 driver upda
# 
# ChangeSet
#   2005/01/28 00:12:28-05:00 ralf@linux-mips.org 
#   [PATCH] Jazzsonic driver updates
#   
#    o Resurrect the Jazz SONIC driver after years of it not having been tested
#    o Convert from Space.c initialization to module_init / platform device.
#   
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/sonic.c
#   2005/01/27 20:59:23-05:00 ralf@linux-mips.org +2 -2
#   Jazzsonic driver updates
# 
# drivers/net/jazzsonic.c
#   2005/01/27 20:59:23-05:00 ralf@linux-mips.org +146 -71
#   Jazzsonic driver updates
# 
# drivers/net/Space.c
#   2005/01/27 20:59:23-05:00 ralf@linux-mips.org +0 -8
#   Jazzsonic driver updates
# 
# drivers/net/Kconfig
#   2005/01/27 20:59:23-05:00 ralf@linux-mips.org +1 -1
#   Jazzsonic driver updates
# 
# ChangeSet
#   2005/01/28 00:12:15-05:00 ralf@linux-mips.org 
#   [PATCH] IOC3 driver updates
#   
#    o Fix build if CONFIG_SERIAL_8250 is disabled.
#    o Add support for setting the MAC address via ifconfig
#    o Generally try to pretend we're a better PCI citizen than the broken piece
#      of silicon that the IOC3 is actually is.
#   
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/ioc3-eth.c
#   2005/01/27 20:55:14-05:00 ralf@linux-mips.org +71 -11
#   IOC3 driver updates
# 
# drivers/net/Kconfig
#   2005/01/27 20:55:14-05:00 ralf@linux-mips.org +1 -1
#   IOC3 driver updates
# 
# ChangeSet
#   2005/01/28 00:09:27-05:00 ralf@linux-mips.org 
#   [PATCH] Remove Baget network driver
#   
#   Remove the support for Baget, a Russian embedded system suffering from
#   bitrot for way too long.
#   
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/Space.c
#   2005/01/27 20:47:03-05:00 ralf@linux-mips.org +0 -3
#   Remove Baget network driver
# 
# drivers/net/Makefile
#   2005/01/27 20:47:03-05:00 ralf@linux-mips.org +0 -1
#   Remove Baget network driver
# 
# drivers/net/Kconfig
#   2005/01/27 20:47:03-05:00 ralf@linux-mips.org +0 -8
#   Remove Baget network driver
# 
# BitKeeper/deleted/.del-bagetlance.c~e863fc0ebec8bb67
#   2005/01/28 00:09:20-05:00 ralf@linux-mips.org +0 -0
#   Delete: drivers/net/bagetlance.c
# 
# ChangeSet
#   2005/01/28 00:09:14-05:00 ralf@linux-mips.org 
#   [PATCH] Au1000 driver updates
#   
#    o mii-tool support
#    o MAC address memcpy fix
#    o VLAN support
#   
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/au1000_eth.h
#   2005/01/27 20:46:47-05:00 ralf@linux-mips.org +32 -23
#   Au1000 driver updates
# 
# drivers/net/au1000_eth.c
#   2005/01/27 20:46:47-05:00 ralf@linux-mips.org +1114 -247
#   Au1000 driver updates
# 
# ChangeSet
#   2005/01/27 17:18:18-05:00 dhollis@davehollis.com 
#   Move MII-related constants from b44/tg3 drivers to linux/mii.h.
# 
# include/linux/mii.h
#   2005/01/27 17:18:11-05:00 dhollis@davehollis.com +4 -0
#   Move MII-related constants from b44/tg3 drivers to linux/mii.h.
# 
# drivers/net/tg3.h
#   2005/01/27 17:18:11-05:00 dhollis@davehollis.com +0 -14
#   Move MII-related constants from b44/tg3 drivers to linux/mii.h.
# 
# drivers/net/b44.h
#   2005/01/27 17:18:11-05:00 dhollis@davehollis.com +0 -14
#   Move MII-related constants from b44/tg3 drivers to linux/mii.h.
# 
# ChangeSet
#   2005/01/27 17:12:02-05:00 rddunlap@osdl.org 
#   [PATCH] prism54: use NULL for pointer
#   
#   Use NULL instead of 0 for pointer:
#   
#   drivers/net/wireless/prism54/isl_ioctl.c:1753:16: warning: Using plain integer as NULL pointer
#   drivers/net/wireless/prism54/isl_ioctl.c:1753:26: warning: Using plain integer as NULL pointer
#   
#   Signed-off-by: Randy Dunlap <rddunlap@osdl.org>
#   
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/wireless/prism54/isl_ioctl.c
#   2005/01/23 00:53:58-05:00 rddunlap@osdl.org +1 -1
#   prism54: use NULL for pointer
# 
# ChangeSet
#   2005/01/27 17:07:24-05:00 viro@parcelfarce.linux.theplanet.co.uk 
#   [PATCH] 3c503 (iomem + isa-ectomy)
#   
#   	switch to ioremap() and normal iomem access primitives
#   Signed-off-by: Al Viro <viro@parcelfarce.linux.theplanet.co.uk>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/3c503.c
#   2004/12/27 21:29:49-05:00 viro@parcelfarce.linux.theplanet.co.uk +40 -27
#   3c503 (iomem + isa-ectomy)
# 
# ChangeSet
#   2005/01/27 16:58:32-05:00 viro@parcelfarce.linux.theplanet.co.uk 
#   [PATCH] ibmlana part 2 (iomem annotations and isa-ectomy)
#   
#   	the usual switch to ioremap and normal iomem access primitives
#   Signed-off-by: Al Viro <viro@parcelfarce.linux.theplanet.co.uk>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/ibmlana.h
#   2004/12/27 21:29:49-05:00 viro@parcelfarce.linux.theplanet.co.uk +1 -0
#   ibmlana part 2 (iomem annotations and isa-ectomy)
# 
# drivers/net/ibmlana.c
#   2004/12/27 21:29:49-05:00 viro@parcelfarce.linux.theplanet.co.uk +38 -30
#   ibmlana part 2 (iomem annotations and isa-ectomy)
# 
# ChangeSet
#   2005/01/27 16:58:20-05:00 viro@parcelfarce.linux.theplanet.co.uk 
#   [PATCH] ibmlana part 1 (netdev_priv())
#   
#   	switched to netdev_priv()
#   Signed-off-by: Al Viro <viro@parcelfarce.linux.theplanet.co.uk>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/ibmlana.c
#   2004/12/27 01:04:19-05:00 viro@parcelfarce.linux.theplanet.co.uk +14 -17
#   ibmlana part 1 (netdev_priv())
# 
# ChangeSet
#   2005/01/27 16:55:13-05:00 viro@parcelfarce.linux.theplanet.co.uk 
#   [PATCH] sk_mca - iomem and isa-ectomy
#   
#   usual isa-ectomy and iomem annotations
#   
#   Signed-off-by: Al Viro <viro@parcelfarce.linux.theplanet.co.uk>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/sk_mca.h
#   2005/01/19 18:58:13-05:00 viro@parcelfarce.linux.theplanet.co.uk +5 -14
#   sk_mca - iomem and isa-ectomy
# 
# drivers/net/sk_mca.c
#   2005/01/19 18:58:13-05:00 viro@parcelfarce.linux.theplanet.co.uk +50 -46
#   sk_mca - iomem and isa-ectomy
# 
# ChangeSet
#   2005/01/27 16:54:59-05:00 viro@parcelfarce.linux.theplanet.co.uk 
#   [PATCH] sk_mca - netdev_priv()
#   
#   Signed-off-by: Al Viro <viro@parcelfarce.linux.theplanet.co.uk>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/sk_mca.c
#   2005/01/19 18:58:13-05:00 viro@parcelfarce.linux.theplanet.co.uk +14 -16
#   sk_mca - netdev_priv()
# 
# ChangeSet
#   2005/01/27 16:49:13-05:00 klassert@mathematik.tu-chemnitz.de 
#   [PATCH] Add MODULE_VERSION to the 3c515 driver
#   
#   Add MODULE_VERSION to the 3c515 driver.
#   
#   Signed-off-by: Steffen Klassert <klassert@mathematik.tu-chemnitz.de>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/3c515.c
#   2005/01/22 06:25:21-05:00 klassert@mathematik.tu-chemnitz.de +1 -0
#   Add MODULE_VERSION to the 3c515 driver
# 
# ChangeSet
#   2005/01/27 16:49:01-05:00 klassert@mathematik.tu-chemnitz.de 
#   [PATCH] Use netdev_priv in the 3c515 driver
#   
#   Use netdev_priv in the 3c515 driver.
#   
#   Signed-off-by: Steffen Klassert <klassert@mathematik.tu-chemnitz.de>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/3c515.c
#   2005/01/19 16:08:20-05:00 klassert@mathematik.tu-chemnitz.de +12 -19
#   Use netdev_priv in the 3c515 driver
# 
# ChangeSet
#   2005/01/27 16:20:35-05:00 webvenza@libero.it 
#   [PATCH] sis900: chiprev i/o cleanups
#   
#   Chip revision is now a member of sis_priv structure
#   Kill all calls to pci_read_config_byte but one
#   Change the code to use sis_priv->chipset_rev
#   
#   Signed-off-by: Daniele Venzano <webvenza@libero.it>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/sis900.c
#   2005/01/26 19:00:00-05:00 webvenza@libero.it +16 -28
#   sis900 printk audit
# 
# ChangeSet
#   2005/01/27 16:20:23-05:00 webvenza@libero.it 
#   [PATCH] sis900: debugging output update
#   
#   Add some init debugging printk
#   Use netif_msg macros before printing debug messages
#   
#   Signed-off-by: Daniele Venzano <webvenza@libero.it>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/sis900.c
#   2005/01/26 19:00:00-05:00 webvenza@libero.it +56 -33
#   sis900 printk audit
# 
# ChangeSet
#   2005/01/27 16:20:11-05:00 webvenza@libero.it 
#   [PATCH] sis900 printk audit
#   
#   Change priority of printk where appropriate
#   Remove two cryptic and useless printk
#   
#   Signed-off-by: Daniele Venzano <webvenza@libero.it>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/sis900.c
#   2005/01/26 19:00:00-05:00 webvenza@libero.it +11 -13
#   sis900 printk audit
# 
# ChangeSet
#   2005/01/27 16:20:00-05:00 webvenza@libero.it 
#   [PATCH] sis900: version bump; remove broken URL
#   
#   Version bump
#   Remove broken link to documentation
#   
#   Signed-off-by: Daniele Venzano <webvenza@libero.it>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/sis900.c
#   2005/01/26 19:00:00-05:00 webvenza@libero.it +3 -3
#   sis900 printk audit
# 
# ChangeSet
#   2005/01/27 16:19:48-05:00 webvenza@libero.it 
#   [PATCH] sis900: add infrastructure needed for standard netif messages
#   
#   Infrastructure needed for standard netif messages
#    - add msg_level to sis900_private
#    - define default msg level
#    - set default value for sis900_debug
#   Update module parameter description
#   Ethtool support for debugging output level
#   
#   Signed-off-by: Daniele Venzano <webvenza@libero.it>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/sis900.c
#   2005/01/26 19:00:00-05:00 webvenza@libero.it +31 -5
#   sis900 printk audit
# 
# ChangeSet
#   2005/01/27 16:15:07-05:00 viro@parcelfarce.linux.theplanet.co.uk 
#   [PATCH] ibmtr 2/2: ibmtr annotations - the rest
#   
#   The rest of annotations and cleanup: ->sram_virt abuse removed, we have
#   separate ->sram_phys now (not remapped) and keep ->sram_virt an iomem pointer.
#   
#   Signed-off-by: Al Viro <viro@parcelfarce.linux.theplanet.co.uk>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# include/linux/ibmtr.h
#   2005/01/24 19:01:53-05:00 viro@parcelfarce.linux.theplanet.co.uk +2 -1
#   ibmtr - part 2
# 
# drivers/net/tokenring/ibmtr.c
#   2005/01/24 19:01:53-05:00 viro@parcelfarce.linux.theplanet.co.uk +45 -59
#   ibmtr - part 2
# 
# drivers/net/pcmcia/ibmtr_cs.c
#   2005/01/24 19:01:53-05:00 viro@parcelfarce.linux.theplanet.co.uk +3 -2
#   ibmtr - part 2
# 
# ChangeSet
#   2005/01/27 16:14:55-05:00 viro@parcelfarce.linux.theplanet.co.uk 
#   [PATCH] ibmtr 1/2: iomem annotations - trivial part
#   
#   Signed-off-by: Al Viro <viro@parcelfarce.linux.theplanet.co.uk>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# include/linux/ibmtr.h
#   2005/01/24 19:01:23-05:00 viro@parcelfarce.linux.theplanet.co.uk +7 -7
#   ibmtr - part 1
# 
# drivers/net/tokenring/ibmtr.c
#   2005/01/24 19:01:23-05:00 viro@parcelfarce.linux.theplanet.co.uk +52 -50
#   ibmtr - part 1
# 
# drivers/net/pcmcia/ibmtr_cs.c
#   2005/01/24 19:01:23-05:00 viro@parcelfarce.linux.theplanet.co.uk +1 -1
#   ibmtr - part 1
# 
# ChangeSet
#   2005/01/27 15:55:00-05:00 brazilnut@us.ibm.com 
#   [PATCH] pcnet32: 79c976 with fiber optic fix
#   
#   After testing this patch I agree that it should be applied.  The one
#   change I made was to print the device name (ethN) instead of 'pcnet32'.
#   Tested ia32.
#   
#   From: Guido Guenther <agx@sigxcpu.org>,
#         Lars Munch <lars@segv.dk>
#   
#   Skip PHY selection on Allied Telesyn 2701FX, it looses the link otherwise.
#   Fix up the AT 2700FX as well.
#   
#   Signed-Off-By: Guido Guenther <agx@sigxcpu.org>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   signed-off-by: Don Fry <brazilnut@us.ibm.com>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# include/linux/pci_ids.h
#   2005/01/05 00:57:36-05:00 brazilnut@us.ibm.com +5 -0
#   pcnet32: 79c976 with fiber optic fix
# 
# drivers/net/pcnet32.c
#   2005/01/05 00:57:36-05:00 brazilnut@us.ibm.com +29 -18
#   pcnet32: 79c976 with fiber optic fix
# 
# ChangeSet
#   2005/01/27 15:53:46-05:00 nacc@us.ibm.com 
#   [PATCH] net/cosa: replace schedule_timeout() with msleep()
#   
#   Hi,
#   
#   Description: Use msleep() instead of schedule_timeout() to guarantee the task
#   delays as expected. Also uses the set_current_state() macro instead of direct
#   assignment in a pair of spots. I am still concerned about those sleeps, as
#   TASK_INTERRUPTIBLE() is used without any checking for signals. Hence I used
#   msleep() for the longer delay. Perhaps the 30 jiffy delay has not been
#   updated for the larger HZ values and thus could be changed to msleep(300).
#   
#   Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/wan/cosa.c
#   2005/01/04 17:57:49-05:00 nacc@us.ibm.com +3 -4
#   net/cosa: replace schedule_timeout() with msleep()
# 
# ChangeSet
#   2005/01/27 15:53:33-05:00 nacc@us.ibm.com 
#   [PATCH] net/airo: replace schedule_timeout() with msleep()/ssleep()
#   
#   Hi,
#   
#   Description: Use msleep()/ssleep() instead of schedule_timeout() to guarantee the task delays as expected.
#   
#   Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/wireless/airo.c
#   2005/01/04 17:57:49-05:00 nacc@us.ibm.com +9 -16
#   net/airo: replace schedule_timeout() with msleep()/ssleep()
# 
# ChangeSet
#   2005/01/27 15:53:21-05:00 nacc@us.ibm.com 
#   [PATCH] net/cs89x0: replace schedule_timeout() with msleep()
#   
#   Hi,
#   
#   Description: The existing wait is in TASK_INTERRUPTIBLE, but does not check for
#   signals (especially problemtic for a 30 msec wait!) as being a cause for
#   schedule_timeout()s return. Use msleep() instead, to guarantee the task delays
#   as expected.
#   
#   Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/cs89x0.c
#   2005/01/04 17:57:49-05:00 nacc@us.ibm.com +2 -2
#   net/cs89x0: replace schedule_timeout() with msleep()
# 
# ChangeSet
#   2005/01/27 15:47:48-05:00 jgarzik@pobox.com 
#   Merge pobox.com:/garz/repo/linux-2.6
#   into pobox.com:/garz/repo/netdev-2.6/janitor
# 
# drivers/net/pcmcia/xirc2ps_cs.c
#   2005/01/27 15:47:44-05:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# drivers/net/arcnet/arcnet.c
#   2005/01/27 15:47:44-05:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# ChangeSet
#   2005/01/27 12:39:09-07:00 dfarnsworth@mvista.com 
#   [netdrvr mv643xx] Big rename.
#   
#   Change MV64340 => MV643XX and mv64340 => mv643xx
#   
#   Signed-off-by: Dale Farnsworth <dale@farnsworth.org>
# 
# include/linux/mv643xx.h
#   2005/01/27 12:38:57-07:00 dfarnsworth@mvista.com +283 -283
#   Big rename.
#   
#   Change MV64340 => MV643XX and mv64340 => mv643xx
#   
#   Signed-off-by: Dale Farnsworth <dale@farnsworth.org>
# 
# drivers/net/mv643xx_eth.h
#   2005/01/27 12:38:57-07:00 dfarnsworth@mvista.com +23 -23
#   Big rename.
#   
#   Change MV64340 => MV643XX and mv64340 => mv643xx
#   
#   Signed-off-by: Dale Farnsworth <dale@farnsworth.org>
# 
# drivers/net/mv643xx_eth.c
#   2005/01/27 12:38:57-07:00 dfarnsworth@mvista.com +259 -259
#   Big rename.
#   
#   Change MV64340 => MV643XX and mv64340 => mv643xx
#   
#   Signed-off-by: Dale Farnsworth <dale@farnsworth.org>
# 
# ChangeSet
#   2005/01/27 12:37:15-07:00 dfarnsworth@mvista.com 
#   [netdrvr mv643xx] Rename MV_READ => mv_read and MV_WRITE => mv_write
#   
#   Signed-off-by: Dale Farnsworth <dale@farnsworth.org>
# 
# drivers/net/mv643xx_eth.c
#   2005/01/27 12:37:02-07:00 dfarnsworth@mvista.com +90 -82
#   Rename MV_READ => mv_read and MV_WRITE => mv_write
#   
#   Signed-off-by: Dale Farnsworth <dale@farnsworth.org>
# 
# ChangeSet
#   2005/01/27 12:36:03-07:00 dfarnsworth@mvista.com 
#   [netdrvr mv643xx] Additional whitespace cleanups, mostly changing spaces to tabs in comments
# 
# drivers/net/mv643xx_eth.h
#   2005/01/27 12:35:50-07:00 dfarnsworth@mvista.com +153 -153
#   Additional whitespace cleanups, mostly changing spaces to tabs in comments
# 
# drivers/net/mv643xx_eth.c
#   2005/01/27 12:35:50-07:00 dfarnsworth@mvista.com +425 -424
#   Additional whitespace cleanups, mostly changing spaces to tabs in comments
# 
# ChangeSet
#   2005/01/27 12:31:54-07:00 dfarnsworth@mvista.com 
#   [netdrvr mv643xx] Run mv643xx_eth.[ch] through scripts/Lindent
#   
#   Signed-off-by: Dale Farnsworth <dale@farnsworth.org>
# 
# drivers/net/mv643xx_eth.h
#   2005/01/27 12:31:42-07:00 dfarnsworth@mvista.com +60 -66
#   Run mv643xx_eth.[ch] through scripts/Lindent
#   
#   Signed-off-by: Dale Farnsworth <dale@farnsworth.org>
# 
# drivers/net/mv643xx_eth.c
#   2005/01/27 12:31:42-07:00 dfarnsworth@mvista.com +266 -275
#   Run mv643xx_eth.[ch] through scripts/Lindent
#   
#   Signed-off-by: Dale Farnsworth <dale@farnsworth.org>
# 
# ChangeSet
#   2005/01/27 12:26:38-07:00 dfarnsworth@mvista.com 
#   [netdrvr mv643xx] Add a function to detect at runtime whether a PHY is attached to
#   the specified port, and use it to cause the probe routine to fail
#   when there is no PHY.
#   
#   Signed-off-by: Dale Farnsworth <dale@farnsworth.org>
# 
# drivers/net/mv643xx_eth.c
#   2005/01/27 12:26:27-07:00 dfarnsworth@mvista.com +47 -0
#   Add a function to detect at runtime whether a PHY is attached to
#   the specified port, and use it to cause the probe routine to fail
#   when there is no PHY.
#   
#   Signed-off-by: Dale Farnsworth <dale@farnsworth.org>
# 
# ChangeSet
#   2005/01/27 12:16:27-07:00 dfarnsworth@mvista.com 
#   [netdrvr mv643xx] This one liner removes a spurious left paren fixing an obvious syntax error
#   in the #ifndef MV64340_NAPI case
# 
# drivers/net/mv643xx_eth.c
#   2005/01/27 12:16:18-07:00 dfarnsworth@mvista.com +0 -1
#   This one liner removes a spurious left paren fixing an obvious syntax error
#   in the #ifndef MV64340_NAPI case
# 
# ChangeSet
#   2005/01/27 12:13:34-07:00 dfarnsworth@mvista.com 
#   [netdrvr mv643xx] Add support for PHYs/boards that don't support autonegotiation.
#     
#   Signed-off-by: Brian Waite <brian@waitefamily.us>
#   Signed-off-by: Dale Farnsworth <dale@farnsworth.org>
# 
# drivers/net/mv643xx_eth.h
#   2005/01/27 12:13:21-07:00 dfarnsworth@mvista.com +1 -1
#   Add support for PHYs/boards that don't support autonegotiation.
#     
#   Signed-off-by: Brian Waite <brian@waitefamily.us>
#   Signed-off-by: Dale Farnsworth <dale@farnsworth.org>
# 
# drivers/net/mv643xx_eth.c
#   2005/01/27 12:13:21-07:00 dfarnsworth@mvista.com +35 -41
#   Add support for PHYs/boards that don't support autonegotiation.
#     
#   Signed-off-by: Brian Waite <brian@waitefamily.us>
#   Signed-off-by: Dale Farnsworth <dale@farnsworth.org>
# 
# ChangeSet
#   2005/01/27 12:12:17-07:00 dfarnsworth@mvista.com 
#   [netdrvr mv643xx] With this patch, the driver now calls netif_carrier_off/netif_carrier_on
#   on a link down/up condition.
#     
#   Signed-off-by: Dale Farnsworth <dale@farnsworth.org>
# 
# drivers/net/mv643xx_eth.c
#   2005/01/27 12:12:08-07:00 dfarnsworth@mvista.com +2 -0
#   With this patch, the driver now calls netif_carrier_off/netif_carrier_on
#   on a link down/up condition.
#     
#   Signed-off-by: Dale Farnsworth <dale@farnsworth.org>
# 
# ChangeSet
#   2005/01/27 12:10:48-07:00 dfarnsworth@mvista.com 
#   [netdrvr mv643xx] This patch cleans up the handling of receive skb sizing.
#     
#   Signed-off-by: Dale Farnsworth <dale@farnsworth.org>
# 
# drivers/net/mv643xx_eth.c
#   2005/01/27 12:10:39-07:00 dfarnsworth@mvista.com +6 -17
#   This patch cleans up the handling of receive skb sizing.
#     
#   Signed-off-by: Dale Farnsworth <dale@farnsworth.org>
# 
# ChangeSet
#   2005/01/27 08:20:45+01:00 perex@suse.cz 
#   [ALSA] Removed file added by mistake
#   
#   Removed include/sound/version.h~
# 
# BitKeeper/deleted/.del-version.h~~37c78b8aa77b0731
#   2005/01/27 08:15:16+01:00 perex@suse.cz +0 -0
#   Delete: include/sound/version.h~
# 
# ChangeSet
#   2005/01/25 20:52:17+01:00 perex@suse.cz 
#   [ALSA] replace schedule_timeout() with msleep()
#   
#   EMU8000 driver
#   Use msleep() instead of schedule_timeout() to guarantee the task
#   delays as expected.
#   
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/isa/sb/emu8000.c
#   2005/01/24 08:00:18+01:00 perex@suse.cz +2 -2
#   [ALSA] replace schedule_timeout() with msleep()
#   
#   D:2005/01/24 15:00:18
#   C:EMU8000 driver
#   F:isa/sb/emu8000.c:1.24->1.25 
#   L:Use msleep() instead of schedule_timeout() to guarantee the task
#   L:delays as expected.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2005/01/25 20:50:28+01:00 perex@suse.cz 
#   [ALSA] insert set_current_state() before schedule_timeout()
#   
#   Wavefront drivers
#   Insert set_current_state() before schedule_timeout(). Without the
#   insertion, schedule_timeout() returns immediately, resulting in an
#   effective busy-wait.
#   
#   Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/isa/wavefront/wavefront_synth.c
#   2005/01/24 07:59:27+01:00 perex@suse.cz +1 -0
#   [ALSA] insert set_current_state() before schedule_timeout()
#   
#   D:2005/01/24 14:59:27
#   C:Wavefront drivers
#   F:isa/wavefront/wavefront_synth.c:1.23->1.24 
#   L:Insert set_current_state() before schedule_timeout(). Without the
#   L:insertion, schedule_timeout() returns immediately, resulting in an
#   L:effective busy-wait.
#   Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2005/01/25 20:48:58+01:00 perex@suse.cz 
#   [ALSA] replace schedule_timeout() with msleep_interruptible()
#   
#   GUS Library
#   Use msleep_interruptible() instead of custom wait code involving
#   schedule_timeout() to guarantee the task delays as expected. This also
#   removes a dependence on the value of HZ.
#   
#   Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/isa/gus/gus_reset.c
#   2005/01/24 07:58:37+01:00 perex@suse.cz +1 -6
#   [ALSA] replace schedule_timeout() with msleep_interruptible()
#   
#   D:2005/01/24 14:58:37
#   C:GUS Library
#   F:isa/gus/gus_reset.c:1.7->1.8 
#   L:Use msleep_interruptible() instead of custom wait code involving
#   L:schedule_timeout() to guarantee the task delays as expected. This also
#   L:removes a dependence on the value of HZ.
#   Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2005/01/25 20:47:19+01:00 perex@suse.cz 
#   [ALSA] insert set_current_state() before schedule_timeout()
#   
#   GUS Library
#   Insert set_current_state() before schedule_timeout(). Without the
#   insertion, schedule_timeout() returns immediately.
#   
#   Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/isa/gus/gus_pcm.c
#   2005/01/24 07:57:51+01:00 perex@suse.cz +1 -0
#   [ALSA] insert set_current_state() before schedule_timeout()
#   
#   D:2005/01/24 14:57:51
#   C:GUS Library
#   F:isa/gus/gus_pcm.c:1.23->1.24 
#   L:Insert set_current_state() before schedule_timeout(). Without the
#   L:insertion, schedule_timeout() returns immediately.
#   Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2005/01/25 20:41:00+01:00 perex@suse.cz 
#   [ALSA] replace schedule_timeout() with msleep()
#   
#   Digigram VX core
#   Use msleep() instead of schedule_timeout() to guarantee the task
#   delays as expected.
#   
#   Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/drivers/vx/vx_core.c
#   2005/01/24 07:56:51+01:00 perex@suse.cz +3 -5
#   [ALSA] replace schedule_timeout() with msleep()
#   
#   D:2005/01/24 14:56:51
#   C:Digigram VX core
#   F:drivers/vx/vx_core.c:1.13->1.14 
#   L:Use msleep() instead of schedule_timeout() to guarantee the task
#   L:delays as expected.
#   Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2005/01/25 20:39:04+01:00 perex@suse.cz 
#   [ALSA] replace schedule_timeout() with msleep()
#   
#   RawMidi Midlevel
#   Use msleep instead of schedule_timeout() to guarantee the task delays
#   as expected. This also removes a dependence on the value of HZ.
#   
#   Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/core/rawmidi.c
#   2005/01/24 07:55:43+01:00 perex@suse.cz +3 -4
#   [ALSA] replace schedule_timeout() with msleep()
#   
#   D:2005/01/24 14:55:43
#   C:RawMidi Midlevel
#   F:core/rawmidi.c:1.52->1.53 
#   L:Use msleep instead of schedule_timeout() to guarantee the task delays
#   L:as expected. This also removes a dependence on the value of HZ.
#   Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2005/01/25 20:37:18+01:00 perex@suse.cz 
#   [ALSA] Special AC97 patch for ASUS W1000/CMI9739 laptop
#   
#   AC97 Codec
#   This patch fixes sound output on the ASUS W1000 laptop with the CMI9739
#   chip. It wrongly reports that it has a SPDIF in, when in fact we wish to
#   use the EAPD pin.
#   
#   Signed-off-by: James Courtier-Dutton <James@superbug.co.uk>
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/ac97/ac97_patch.c
#   2005/01/24 05:11:00+01:00 perex@suse.cz +9 -0
#   [ALSA] Special AC97 patch for ASUS W1000/CMI9739 laptop
#   
#   D:2005/01/24 12:11:00
#   C:AC97 Codec
#   F:pci/ac97/ac97_patch.c:1.70->1.71 
#   L:This patch fixes sound output on the ASUS W1000 laptop with the CMI9739
#   L:chip. It wrongly reports that it has a SPDIF in, when in fact we wish to
#   L:use the EAPD pin.
#   Signed-off-by: James Courtier-Dutton <James@superbug.co.uk>
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2005/01/25 20:35:33+01:00 perex@suse.cz 
#   [ALSA] Warning doc about VIA82xx recording
#   
#   Documentation
#   Add warning about the consequences of adjusting the 'Input Source Select'
#   of VIA82xx.
#   
#   Signed-off-by: Ross Kendall Axe <ross.axe@blueyonder.co.uk>
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# Documentation/sound/alsa/VIA82xx-mixer.txt
#   2005/01/25 14:32:28+01:00 perex@suse.cz +8 -0
#   [ALSA] Warning doc about VIA82xx recording
#   
#   D:2005/01/21 19:33:11
#   C:Documentation
#   F:Documentation/VIA82xx-mixer.txt:INITIAL->1.1 
#   L:Add warning about the consequences of adjusting the 'Input Source Select'
#   L:of VIA82xx.
#   Signed-off-by: Ross Kendall Axe <ross.axe@blueyonder.co.uk>
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# Documentation/sound/alsa/VIA82xx-mixer.txt
#   2005/01/25 14:32:28+01:00 perex@suse.cz +0 -0
#   BitKeeper file /home/perex/bk/linux-sound/work/Documentation/sound/alsa/VIA82xx-mixer.txt
# 
# ChangeSet
#   2005/01/25 20:33:42+01:00 perex@suse.cz 
#   [ALSA] fix usage of preprocessor directive inside macro
#   
#   HDA Intel driver
#   gcc-2 complains about preprocessor directives inside a macro argument list
#   
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# sound/pci/hda/hda_intel.c
#   2005/01/21 10:46:00+01:00 perex@suse.cz +3 -3
#   [ALSA] fix usage of preprocessor directive inside macro
#   
#   D:2005/01/21 17:46:00
#   C:HDA Intel driver
#   F:pci/hda/hda_intel.c:1.1->1.2 
#   L:gcc-2 complains about preprocessor directives inside a macro argument list
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# ChangeSet
#   2005/01/25 20:32:04+01:00 perex@suse.cz 
#   [ALSA] add more Yamaha USB MIDI quirks
#   
#   USB generic driver
#   add support for Yamaha UC-MX, UC-KX, CLP-175, SPX2000
#   
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# sound/usb/usbquirks.h
#   2005/01/21 01:32:12+01:00 perex@suse.cz +6 -0
#   [ALSA] add more Yamaha USB MIDI quirks
#   
#   D:2005/01/21 08:32:12
#   C:USB generic driver
#   F:usb/usbquirks.h:1.39->1.40 
#   L:add support for Yamaha UC-MX, UC-KX, CLP-175, SPX2000
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# ChangeSet
#   2005/01/24 09:09:37-06:00 shaggy@austin.ibm.com 
#   Merge jfs@jfs.bkbits.net:linux-2.5
#   into austin.ibm.com:/home/shaggy/bk/jfs-2.5
# 
# fs/jfs/jfs_txnmgr.c
#   2005/01/24 09:09:26-06:00 shaggy@austin.ibm.com +0 -0
#   Auto merged
# 
# fs/jfs/jfs_metapage.c
#   2005/01/24 09:09:26-06:00 shaggy@austin.ibm.com +0 -0
#   Auto merged
# 
# fs/jfs/jfs_logmgr.c
#   2005/01/24 09:09:26-06:00 shaggy@austin.ibm.com +0 -0
#   Auto merged
# 
# ChangeSet
#   2005/01/21 00:17:51-02:00 acme@toy.ghostprotocols.net 
#   [ATM] stop using sk_protinfo
#   
#   Required to introduce struct connection_sock.
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/sched/sch_atm.c
#   2005/01/21 00:17:39-02:00 acme@toy.ghostprotocols.net +1 -1
#   [ATM] stop using sk_protinfo
#   
#   Required to introduce struct connection_sock.
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/atm/svc.c
#   2005/01/21 00:17:39-02:00 acme@toy.ghostprotocols.net +37 -34
#   [ATM] stop using sk_protinfo
#   
#   Required to introduce struct connection_sock.
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/atm/signaling.c
#   2005/01/21 00:17:39-02:00 acme@toy.ghostprotocols.net +22 -19
#   [ATM] stop using sk_protinfo
#   
#   Required to introduce struct connection_sock.
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/atm/raw.c
#   2005/01/21 00:17:39-02:00 acme@toy.ghostprotocols.net +9 -5
#   [ATM] stop using sk_protinfo
#   
#   Required to introduce struct connection_sock.
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/atm/proc.c
#   2005/01/21 00:17:39-02:00 acme@toy.ghostprotocols.net +9 -9
#   [ATM] stop using sk_protinfo
#   
#   Required to introduce struct connection_sock.
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/atm/pppoatm.c
#   2005/01/21 00:17:39-02:00 acme@toy.ghostprotocols.net +2 -1
#   [ATM] stop using sk_protinfo
#   
#   Required to introduce struct connection_sock.
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/atm/mpc.c
#   2005/01/21 00:17:39-02:00 acme@toy.ghostprotocols.net +18 -10
#   [ATM] stop using sk_protinfo
#   
#   Required to introduce struct connection_sock.
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/atm/lec.c
#   2005/01/21 00:17:39-02:00 acme@toy.ghostprotocols.net +23 -15
#   [ATM] stop using sk_protinfo
#   
#   Required to introduce struct connection_sock.
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/atm/ioctl.c
#   2005/01/21 00:17:39-02:00 acme@toy.ghostprotocols.net +5 -4
#   [ATM] stop using sk_protinfo
#   
#   Required to introduce struct connection_sock.
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/atm/common.c
#   2005/01/21 00:17:39-02:00 acme@toy.ghostprotocols.net +24 -31
#   [ATM] stop using sk_protinfo
#   
#   Required to introduce struct connection_sock.
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/atm/clip.c
#   2005/01/21 00:17:39-02:00 acme@toy.ghostprotocols.net +11 -8
#   [ATM] stop using sk_protinfo
#   
#   Required to introduce struct connection_sock.
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/atm/br2684.c
#   2005/01/21 00:17:39-02:00 acme@toy.ghostprotocols.net +2 -2
#   [ATM] stop using sk_protinfo
#   
#   Required to introduce struct connection_sock.
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/atm/atm_misc.c
#   2005/01/21 00:17:39-02:00 acme@toy.ghostprotocols.net +4 -3
#   [ATM] stop using sk_protinfo
#   
#   Required to introduce struct connection_sock.
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# include/linux/atmdev.h
#   2005/01/21 00:17:39-02:00 acme@toy.ghostprotocols.net +20 -8
#   [ATM] stop using sk_protinfo
#   
#   Required to introduce struct connection_sock.
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# drivers/atm/iphase.c
#   2005/01/21 00:17:39-02:00 acme@toy.ghostprotocols.net +7 -5
#   [ATM] stop using sk_protinfo
#   
#   Required to introduce struct connection_sock.
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# drivers/atm/idt77252.c
#   2005/01/21 00:17:39-02:00 acme@toy.ghostprotocols.net +5 -4
#   [ATM] stop using sk_protinfo
#   
#   Required to introduce struct connection_sock.
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# drivers/atm/he.c
#   2005/01/21 00:17:39-02:00 acme@toy.ghostprotocols.net +1 -1
#   [ATM] stop using sk_protinfo
#   
#   Required to introduce struct connection_sock.
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# drivers/atm/atmtcp.c
#   2005/01/21 00:17:39-02:00 acme@toy.ghostprotocols.net +7 -7
#   [ATM] stop using sk_protinfo
#   
#   Required to introduce struct connection_sock.
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# ChangeSet
#   2005/01/21 00:16:19-02:00 acme@toy.ghostprotocols.net 
#   [PPPOX] stop using sk_protinfo
#   
#   Required to introduce struct connection_sock.
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# include/linux/if_pppox.h
#   2005/01/21 00:16:04-02:00 acme@toy.ghostprotocols.net +15 -4
#   [PPPOX] stop using sk_protinfo
#   
#   Required to introduce struct connection_sock.
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# drivers/net/pppox.c
#   2005/01/21 00:16:04-02:00 acme@toy.ghostprotocols.net +1 -1
#   [PPPOX] stop using sk_protinfo
#   
#   Required to introduce struct connection_sock.
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# drivers/net/pppoe.c
#   2005/01/21 00:16:04-02:00 acme@toy.ghostprotocols.net +39 -62
#   [PPPOX] stop using sk_protinfo
#   
#   Required to introduce struct connection_sock.
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# ChangeSet
#   2005/01/20 21:21:48-02:00 acme@toy.ghostprotocols.net 
#   [IRDA] stop using sk_protinfo
#   
#   Required to introduce struct connection_sock.
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/irda/af_irda.c
#   2005/01/20 21:21:35-02:00 acme@toy.ghostprotocols.net +14 -24
#   [IRDA] stop using sk_protinfo
#   
#   Required to introduce struct connection_sock.
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# include/net/irda/af_irda.h
#   2005/01/20 21:21:35-02:00 acme@toy.ghostprotocols.net +7 -2
#   [IRDA] stop using sk_protinfo
#   
#   Required to introduce struct connection_sock.
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# ChangeSet
#   2005/01/20 21:17:52-02:00 acme@toy.ghostprotocols.net 
#   [LLC] stop using sk_protinfo
#   
#   Required to introduce struct connection_sock.
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/llc/llc_sap.c
#   2005/01/20 21:17:39-02:00 acme@toy.ghostprotocols.net +1 -1
#   [LLC] stop using sk_protinfo
#   
#   Required to introduce struct connection_sock.
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/llc/llc_proc.c
#   2005/01/20 21:17:39-02:00 acme@toy.ghostprotocols.net +4 -4
#   [LLC] stop using sk_protinfo
#   
#   Required to introduce struct connection_sock.
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/llc/llc_if.c
#   2005/01/20 21:17:39-02:00 acme@toy.ghostprotocols.net +2 -2
#   [LLC] stop using sk_protinfo
#   
#   Required to introduce struct connection_sock.
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/llc/llc_conn.c
#   2005/01/20 21:17:39-02:00 acme@toy.ghostprotocols.net +18 -32
#   [LLC] stop using sk_protinfo
#   
#   Required to introduce struct connection_sock.
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/llc/llc_c_ev.c
#   2005/01/20 21:17:39-02:00 acme@toy.ghostprotocols.net +1 -1
#   [LLC] stop using sk_protinfo
#   
#   Required to introduce struct connection_sock.
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/llc/llc_c_ac.c
#   2005/01/20 21:17:39-02:00 acme@toy.ghostprotocols.net +46 -46
#   [LLC] stop using sk_protinfo
#   
#   Required to introduce struct connection_sock.
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/llc/af_llc.c
#   2005/01/20 21:17:39-02:00 acme@toy.ghostprotocols.net +11 -11
#   [LLC] stop using sk_protinfo
#   
#   Required to introduce struct connection_sock.
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# include/net/llc_conn.h
#   2005/01/20 21:17:39-02:00 acme@toy.ghostprotocols.net +8 -3
#   [LLC] stop using sk_protinfo
#   
#   Required to introduce struct connection_sock.
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# ChangeSet
#   2005/01/20 21:09:34-02:00 acme@toy.ghostprotocols.net 
#   [PF_KEY] stop using sk_protinfo
#   
#   Required to introduce struct connection_sock.
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/key/af_key.c
#   2005/01/20 21:09:22-02:00 acme@toy.ghostprotocols.net +14 -19
#   [PF_KEY] stop using sk_protinfo
#   
#   Required to introduce struct connection_sock.
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# ChangeSet
#   2005/01/20 20:59:08-02:00 acme@toy.ghostprotocols.net 
#   [X25] stop using sk_protinfo
#   
#   Required to introduce struct connection_sock.
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/x25/x25_timer.c
#   2005/01/20 20:58:55-02:00 acme@toy.ghostprotocols.net +7 -7
#   [X25] stop using sk_protinfo
#   
#   Required to introduce struct connection_sock.
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/x25/x25_subr.c
#   2005/01/20 20:58:55-02:00 acme@toy.ghostprotocols.net +7 -7
#   [X25] stop using sk_protinfo
#   
#   Required to introduce struct connection_sock.
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/x25/x25_proc.c
#   2005/01/20 20:58:55-02:00 acme@toy.ghostprotocols.net +1 -1
#   [X25] stop using sk_protinfo
#   
#   Required to introduce struct connection_sock.
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/x25/x25_out.c
#   2005/01/20 20:58:55-02:00 acme@toy.ghostprotocols.net +4 -4
#   [X25] stop using sk_protinfo
#   
#   Required to introduce struct connection_sock.
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/x25/x25_in.c
#   2005/01/20 20:58:55-02:00 acme@toy.ghostprotocols.net +5 -5
#   [X25] stop using sk_protinfo
#   
#   Required to introduce struct connection_sock.
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/x25/x25_facilities.c
#   2005/01/20 20:58:55-02:00 acme@toy.ghostprotocols.net +1 -1
#   [X25] stop using sk_protinfo
#   
#   Required to introduce struct connection_sock.
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/x25/af_x25.c
#   2005/01/20 20:58:55-02:00 acme@toy.ghostprotocols.net +13 -23
#   [X25] stop using sk_protinfo
#   
#   Required to introduce struct connection_sock.
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# include/net/x25.h
#   2005/01/20 20:58:55-02:00 acme@toy.ghostprotocols.net +7 -3
#   [X25] stop using sk_protinfo
#   
#   Required to introduce struct connection_sock.
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# ChangeSet
#   2005/01/20 20:54:11-02:00 acme@toy.ghostprotocols.net 
#   [NETLINK] stop using sk_protinfo
#   
#   Required to introduce struct connection_sock.
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/netlink/af_netlink.c
#   2005/01/20 20:53:58-02:00 acme@toy.ghostprotocols.net +28 -30
#   [NETLINK] stop using sk_protinfo
#   
#   Required to introduce struct connection_sock.
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# ChangeSet
#   2005/01/20 20:44:56-02:00 acme@toy.ghostprotocols.net 
#   [ECONET] stop using sk_protinfo
#   
#   Required to introduce struct connection_sock.
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/econet/af_econet.c
#   2005/01/20 20:44:43-02:00 acme@toy.ghostprotocols.net +8 -13
#   [ECONET] stop using sk_protinfo
#   
#   Required to introduce struct connection_sock.
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# include/linux/if_ec.h
#   2005/01/20 20:44:43-02:00 acme@toy.ghostprotocols.net +7 -3
#   [ECONET] stop using sk_protinfo
#   
#   Required to introduce struct connection_sock.
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# ChangeSet
#   2005/01/20 20:41:35-02:00 acme@toy.ghostprotocols.net 
#   [AF_PACKET] stop using sk_protinfo
#   
#   Required to introduce struct connection_sock.
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/packet/af_packet.c
#   2005/01/20 20:41:21-02:00 acme@toy.ghostprotocols.net +26 -29
#   [AF_PACKET] stop using sk_protinfo
#   
#   Required to introduce struct connection_sock.
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# ChangeSet
#   2005/01/20 20:36:07-02:00 acme@toy.ghostprotocols.net 
#   [DECNET] Don't use sk_protinfo + private sock slab cache
#   
#   DecNET already uses a private sock slab cache, but initializes sk->sk_protinfo,
#   pointing to (sk + 1), this is wrong because at sk_free time we call
#   sk->sk_destruct, that by default points to sock_def_destruct, that does a kfree
#   on sk->sk_protinfo, since it was initialized at net_proto_family->create() time
#   (dn_create), but in decnet sk_protinfo was not kmalloced, it was allocated
#   piggybacked to struct sock.
#   
#   This doesn't causes problems because decnet sets sk->sk_destruct to a custom
#   function that doesn't calls kfree(sk->sk_protinfo), but to reach a long time
#   goal of killing sk_protinfo lets just make DN_SK return sk + 1.
#   
#   I left merging dn_scp with dn_sock for later, as the current state suits my
#   needs to introduce connection_sock.
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/decnet/af_decnet.c
#   2005/01/20 20:35:54-02:00 acme@toy.ghostprotocols.net +1 -2
#   [DECNET] Don't use sk_protinfo + private sock slab cache
#   
#   DecNET already uses a private sock slab cache, but initializes sk->sk_protinfo,
#   pointing to (sk + 1), this is wrong because at sk_free time we call
#   sk->sk_destruct, that by default points to sock_def_destruct, that does a kfree
#   on sk->sk_protinfo, since it was initialized at net_proto_family->create() time
#   (dn_create), but in decnet sk_protinfo was not kmalloced, it was allocated
#   piggybacked to struct sock.
#   
#   This doesn't causes problems because decnet sets sk->sk_destruct to a custom
#   function that doesn't calls kfree(sk->sk_protinfo), but to reach a long time
#   goal of killing sk_protinfo lets just make DN_SK return sk + 1.
#   
#   I left merging dn_scp with dn_sock for later, as the current state suits my
#   needs to introduce connection_sock.
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# include/net/dn.h
#   2005/01/20 20:35:54-02:00 acme@toy.ghostprotocols.net +5 -1
#   [DECNET] Don't use sk_protinfo + private sock slab cache
#   
#   DecNET already uses a private sock slab cache, but initializes sk->sk_protinfo,
#   pointing to (sk + 1), this is wrong because at sk_free time we call
#   sk->sk_destruct, that by default points to sock_def_destruct, that does a kfree
#   on sk->sk_protinfo, since it was initialized at net_proto_family->create() time
#   (dn_create), but in decnet sk_protinfo was not kmalloced, it was allocated
#   piggybacked to struct sock.
#   
#   This doesn't causes problems because decnet sets sk->sk_destruct to a custom
#   function that doesn't calls kfree(sk->sk_protinfo), but to reach a long time
#   goal of killing sk_protinfo lets just make DN_SK return sk + 1.
#   
#   I left merging dn_scp with dn_sock for later, as the current state suits my
#   needs to introduce connection_sock.
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# ChangeSet
#   2005/01/20 20:32:38-02:00 acme@toy.ghostprotocols.net 
#   [APPLETALK] stop using sk_protinfo
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/appletalk/ddp.c
#   2005/01/20 20:32:26-02:00 acme@toy.ghostprotocols.net +2 -9
#   [APPLETALK] stop using sk_protinfo
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# include/linux/atalk.h
#   2005/01/20 20:32:26-02:00 acme@toy.ghostprotocols.net +7 -2
#   [APPLETALK] stop using sk_protinfo
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# ChangeSet
#   2005/01/20 20:25:41-02:00 acme@toy.ghostprotocols.net 
#   [SOCK] make sk_alloc use kmalloc for non performance critical families
#   
#   With this we can have aggregate protocol specific struct proto_sock
#   allocated for non performance critical protocols.
#   
#   We still check for slab == NULL && zero_it == 1 to allocate from the
#   generic "sock" slab cache, but this will be removed when all the
#   network families stop using sk_protinfo, when the generic "sock"
#   slab cache will be removed.
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# net/core/sock.c
#   2005/01/20 20:25:26-02:00 acme@toy.ghostprotocols.net +14 -3
#   [SOCK] make sk_alloc use kmalloc for non performance critical families
#   
#   With this we can have aggregate protocol specific struct proto_sock
#   allocated for non performance critical protocols.
#   
#   We still check for slab == NULL && zero_it == 1 to allocate from the
#   generic "sock" slab cache, but this will be removed when all the
#   network families stop using sk_protinfo, when the generic "sock"
#   slab cache will be removed.
#   
#   Signed-off-by: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
#   Signed-off-by: David S. Miller <davem@davemloft.net>
# 
# ChangeSet
#   2005/01/20 22:29:20+01:00 perex@suse.cz 
#   [ALSA] remove obsolete sound/core/ioctl32 directory
#   
#   The compatibility layer is integrated to ALSA midlevel code now.
# 
# include/sound/version.h~
#   2005/01/20 22:26:24+01:00 perex@suse.cz +3 -0
# 
# include/sound/version.h~
#   2005/01/20 22:26:24+01:00 perex@suse.cz +0 -0
#   BitKeeper file /home/perex/bk/linux-sound/work/include/sound/version.h~
# 
# BitKeeper/deleted/.del-hwdep32.c~2628af71433fb282
#   2005/01/20 22:14:14+01:00 perex@suse.cz +0 -0
#   Delete: sound/core/ioctl32/hwdep32.c
# 
# BitKeeper/deleted/.del-ioctl32.h~6fa31b659e702cbd
#   2005/01/20 22:14:12+01:00 perex@suse.cz +0 -0
#   Delete: sound/core/ioctl32/ioctl32.h
# 
# BitKeeper/deleted/.del-ioctl32.c~e6621ca58003986f
#   2005/01/20 22:14:11+01:00 perex@suse.cz +0 -0
#   Delete: sound/core/ioctl32/ioctl32.c
# 
# BitKeeper/deleted/.del-Makefile~767d5bad6308fa6d
#   2005/01/20 22:14:08+01:00 perex@suse.cz +0 -0
#   Delete: sound/core/ioctl32/Makefile
# 
# BitKeeper/deleted/.del-pcm32.c~79101ddd8c8dbba8
#   2005/01/20 22:14:05+01:00 perex@suse.cz +0 -0
#   Delete: sound/core/ioctl32/pcm32.c
# 
# BitKeeper/deleted/.del-rawmidi32.c~b24d28b2a36477f1
#   2005/01/20 22:14:03+01:00 perex@suse.cz +0 -0
#   Delete: sound/core/ioctl32/rawmidi32.c
# 
# BitKeeper/deleted/.del-seq32.c~c96c6dffe1307ca0
#   2005/01/20 22:14:00+01:00 perex@suse.cz +0 -0
#   Delete: sound/core/ioctl32/seq32.c
# 
# BitKeeper/deleted/.del-timer32.c~e0c2522dbc4e6d68
#   2005/01/20 22:13:55+01:00 perex@suse.cz +0 -0
#   Delete: sound/core/ioctl32/timer32.c
# 
# ChangeSet
#   2005/01/20 21:47:16+01:00 perex@suse.cz 
#   Merge suse.cz:/home/perex/bk/linux-sound/linux-sound
#   into suse.cz:/home/perex/bk/linux-sound/work
# 
# sound/pci/Kconfig
#   2005/01/20 21:46:53+01:00 perex@suse.cz +0 -0
#   Auto merged
# 
# ChangeSet
#   2005/01/20 14:46:30-06:00 shaggy@austin.ibm.com 
#   JFS: replace schedule_timeout() with msleep()
#   
#   Use msleep() instead of schedule_timeout() to guarantee the task
#   delays as expected. The current code uses TASK_INTERRUPTIBLE;
#   however, it does not check for signals, so I do not think the
#   change to msleep() is necessarily bad.
#   
#   Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
#   Signed-off-by: Dave Kleikamp <shaggy@austin.ibm.com>
# 
# fs/jfs/jfs_logmgr.c
#   2005/01/20 14:46:19-06:00 shaggy@austin.ibm.com +2 -2
#   replace schedule_timeout() with msleep()
# 
# ChangeSet
#   2005/01/20 14:22:50-06:00 shaggy@austin.ibm.com 
#   JFS: add missing include
#   
#   This is why it's a good idea to compile & test before checking in
#   the code.
#   
#   Signed-off-by: Dave Kleikamp <shaggy@austin.ibm.com>
# 
# fs/jfs/jfs_metapage.c
#   2005/01/20 14:22:33-06:00 shaggy@austin.ibm.com +1 -0
#   add missing include
# 
# ChangeSet
#   2005/01/20 14:14:19-06:00 shaggy@austin.ibm.com 
#   JFS: fix livelock waiting for stale metapage
#   
#   Several waitors were keeping mp->count from going to zero, so we
#   would never release the page.  Simplify the logic by doing a busy
#   wait without locking the metapage.
#   
#   Signed-off-by: Dave Kleikamp <shaggy@austin.ibm.com>
# 
# fs/jfs/jfs_metapage.c
#   2005/01/20 14:13:55-06:00 shaggy@austin.ibm.com +6 -17
#   many waitors for stale metapage resulted in livelock
# 
# ChangeSet
#   2005/01/20 20:33:37+01:00 perex@suse.cz 
#   [ALSA] Use DEFINE_SPINLOCK(), DEFINE_RWLOCK() macros
#   
#   ALSA Core,PCM Midlevel,Timer Midlevel,ALSA sequencer
#   ALSA<-OSS sequencer
#   Replace spin/rwlock definitions with DEFINE_SPINLOCK() and DEFINE_RWLOCK()
#   macros.
#   
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/core/timer.c
#   2005/01/20 10:42:36+01:00 perex@suse.cz +1 -1
#   [ALSA] Use DEFINE_SPINLOCK(), DEFINE_RWLOCK() macros
#   
#   D:2005/01/20 17:42:36
#   C:ALSA Core,PCM Midlevel,Timer Midlevel,ALSA sequencer
#   C:ALSA<-OSS sequencer
#   F:core/init.c:1.54->1.55 
#   F:core/memory.c:1.36->1.37 
#   F:core/pcm_native.c:1.112->1.113 
#   F:core/timer.c:1.64->1.65 
#   F:core/seq/seq_clientmgr.c:1.41->1.42 
#   F:core/seq/seq_queue.c:1.15->1.16 
#   F:core/seq/oss/seq_oss_midi.c:1.16->1.17 
#   F:core/seq/oss/seq_oss_synth.c:1.16->1.17 
#   L:Replace spin/rwlock definitions with DEFINE_SPINLOCK() and DEFINE_RWLOCK()
#   L:macros.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/core/seq/seq_queue.c
#   2005/01/20 10:42:37+01:00 perex@suse.cz +1 -1
#   [ALSA] Use DEFINE_SPINLOCK(), DEFINE_RWLOCK() macros
#   
#   D:2005/01/20 17:42:36
#   C:ALSA Core,PCM Midlevel,Timer Midlevel,ALSA sequencer
#   C:ALSA<-OSS sequencer
#   F:core/init.c:1.54->1.55 
#   F:core/memory.c:1.36->1.37 
#   F:core/pcm_native.c:1.112->1.113 
#   F:core/timer.c:1.64->1.65 
#   F:core/seq/seq_clientmgr.c:1.41->1.42 
#   F:core/seq/seq_queue.c:1.15->1.16 
#   F:core/seq/oss/seq_oss_midi.c:1.16->1.17 
#   F:core/seq/oss/seq_oss_synth.c:1.16->1.17 
#   L:Replace spin/rwlock definitions with DEFINE_SPINLOCK() and DEFINE_RWLOCK()
#   L:macros.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/core/seq/seq_clientmgr.c
#   2005/01/20 10:42:37+01:00 perex@suse.cz +1 -1
#   [ALSA] Use DEFINE_SPINLOCK(), DEFINE_RWLOCK() macros
#   
#   D:2005/01/20 17:42:36
#   C:ALSA Core,PCM Midlevel,Timer Midlevel,ALSA sequencer
#   C:ALSA<-OSS sequencer
#   F:core/init.c:1.54->1.55 
#   F:core/memory.c:1.36->1.37 
#   F:core/pcm_native.c:1.112->1.113 
#   F:core/timer.c:1.64->1.65 
#   F:core/seq/seq_clientmgr.c:1.41->1.42 
#   F:core/seq/seq_queue.c:1.15->1.16 
#   F:core/seq/oss/seq_oss_midi.c:1.16->1.17 
#   F:core/seq/oss/seq_oss_synth.c:1.16->1.17 
#   L:Replace spin/rwlock definitions with DEFINE_SPINLOCK() and DEFINE_RWLOCK()
#   L:macros.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/core/seq/oss/seq_oss_synth.c
#   2005/01/20 10:42:37+01:00 perex@suse.cz +1 -1
#   [ALSA] Use DEFINE_SPINLOCK(), DEFINE_RWLOCK() macros
#   
#   D:2005/01/20 17:42:36
#   C:ALSA Core,PCM Midlevel,Timer Midlevel,ALSA sequencer
#   C:ALSA<-OSS sequencer
#   F:core/init.c:1.54->1.55 
#   F:core/memory.c:1.36->1.37 
#   F:core/pcm_native.c:1.112->1.113 
#   F:core/timer.c:1.64->1.65 
#   F:core/seq/seq_clientmgr.c:1.41->1.42 
#   F:core/seq/seq_queue.c:1.15->1.16 
#   F:core/seq/oss/seq_oss_midi.c:1.16->1.17 
#   F:core/seq/oss/seq_oss_synth.c:1.16->1.17 
#   L:Replace spin/rwlock definitions with DEFINE_SPINLOCK() and DEFINE_RWLOCK()
#   L:macros.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/core/seq/oss/seq_oss_midi.c
#   2005/01/20 10:42:37+01:00 perex@suse.cz +1 -1
#   [ALSA] Use DEFINE_SPINLOCK(), DEFINE_RWLOCK() macros
#   
#   D:2005/01/20 17:42:36
#   C:ALSA Core,PCM Midlevel,Timer Midlevel,ALSA sequencer
#   C:ALSA<-OSS sequencer
#   F:core/init.c:1.54->1.55 
#   F:core/memory.c:1.36->1.37 
#   F:core/pcm_native.c:1.112->1.113 
#   F:core/timer.c:1.64->1.65 
#   F:core/seq/seq_clientmgr.c:1.41->1.42 
#   F:core/seq/seq_queue.c:1.15->1.16 
#   F:core/seq/oss/seq_oss_midi.c:1.16->1.17 
#   F:core/seq/oss/seq_oss_synth.c:1.16->1.17 
#   L:Replace spin/rwlock definitions with DEFINE_SPINLOCK() and DEFINE_RWLOCK()
#   L:macros.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/core/pcm_native.c
#   2005/01/20 10:42:36+01:00 perex@suse.cz +1 -1
#   [ALSA] Use DEFINE_SPINLOCK(), DEFINE_RWLOCK() macros
#   
#   D:2005/01/20 17:42:36
#   C:ALSA Core,PCM Midlevel,Timer Midlevel,ALSA sequencer
#   C:ALSA<-OSS sequencer
#   F:core/init.c:1.54->1.55 
#   F:core/memory.c:1.36->1.37 
#   F:core/pcm_native.c:1.112->1.113 
#   F:core/timer.c:1.64->1.65 
#   F:core/seq/seq_clientmgr.c:1.41->1.42 
#   F:core/seq/seq_queue.c:1.15->1.16 
#   F:core/seq/oss/seq_oss_midi.c:1.16->1.17 
#   F:core/seq/oss/seq_oss_synth.c:1.16->1.17 
#   L:Replace spin/rwlock definitions with DEFINE_SPINLOCK() and DEFINE_RWLOCK()
#   L:macros.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/core/memory.c
#   2005/01/20 10:42:36+01:00 perex@suse.cz +2 -2
#   [ALSA] Use DEFINE_SPINLOCK(), DEFINE_RWLOCK() macros
#   
#   D:2005/01/20 17:42:36
#   C:ALSA Core,PCM Midlevel,Timer Midlevel,ALSA sequencer
#   C:ALSA<-OSS sequencer
#   F:core/init.c:1.54->1.55 
#   F:core/memory.c:1.36->1.37 
#   F:core/pcm_native.c:1.112->1.113 
#   F:core/timer.c:1.64->1.65 
#   F:core/seq/seq_clientmgr.c:1.41->1.42 
#   F:core/seq/seq_queue.c:1.15->1.16 
#   F:core/seq/oss/seq_oss_midi.c:1.16->1.17 
#   F:core/seq/oss/seq_oss_synth.c:1.16->1.17 
#   L:Replace spin/rwlock definitions with DEFINE_SPINLOCK() and DEFINE_RWLOCK()
#   L:macros.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/core/init.c
#   2005/01/20 10:42:36+01:00 perex@suse.cz +1 -1
#   [ALSA] Use DEFINE_SPINLOCK(), DEFINE_RWLOCK() macros
#   
#   D:2005/01/20 17:42:36
#   C:ALSA Core,PCM Midlevel,Timer Midlevel,ALSA sequencer
#   C:ALSA<-OSS sequencer
#   F:core/init.c:1.54->1.55 
#   F:core/memory.c:1.36->1.37 
#   F:core/pcm_native.c:1.112->1.113 
#   F:core/timer.c:1.64->1.65 
#   F:core/seq/seq_clientmgr.c:1.41->1.42 
#   F:core/seq/seq_queue.c:1.15->1.16 
#   F:core/seq/oss/seq_oss_midi.c:1.16->1.17 
#   F:core/seq/oss/seq_oss_synth.c:1.16->1.17 
#   L:Replace spin/rwlock definitions with DEFINE_SPINLOCK() and DEFINE_RWLOCK()
#   L:macros.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2005/01/20 20:32:02+01:00 perex@suse.cz 
#   [ALSA] Remove snd-ioctl32 entry
#   
#   ALSA Core
#   Remove the entry for snd-ioctl32.  The 32bit wrapper is built in the core
#   module.
#   
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/core/Makefile
#   2005/01/20 10:16:39+01:00 perex@suse.cz +0 -1
#   [ALSA] Remove snd-ioctl32 entry
#   
#   D:2005/01/20 17:16:35
#   C:ALSA Core
#   F:core/Kconfig:1.7->1.8 
#   F:core/Makefile:1.54->1.55 
#   L:Remove the entry for snd-ioctl32.  The 32bit wrapper is built in the core
#   L:module.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/core/Kconfig
#   2005/01/20 10:16:35+01:00 perex@suse.cz +0 -14
#   [ALSA] Remove snd-ioctl32 entry
#   
#   D:2005/01/20 17:16:35
#   C:ALSA Core
#   F:core/Kconfig:1.7->1.8 
#   F:core/Makefile:1.54->1.55 
#   L:Remove the entry for snd-ioctl32.  The 32bit wrapper is built in the core
#   L:module.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2005/01/20 20:30:46+01:00 perex@suse.cz 
#   [ALSA] Export new register/unregister functions
#   
#   ALSA Core
#   Export new register/unregister functions for compat control-ioctls.
#   
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/core/sound.c
#   2005/01/20 10:15:37+01:00 perex@suse.cz +4 -0
#   [ALSA] Export new register/unregister functions
#   
#   D:2005/01/20 17:15:37
#   C:ALSA Core
#   F:core/sound.c:1.71->1.72 
#   L:Export new register/unregister functions for compat control-ioctls.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2005/01/20 20:29:26+01:00 perex@suse.cz 
#   [ALSA] unlocked/compat_ioctl rewrite for OSS compatible drivers
#   
#   ALSA<-OSS emulation,ALSA<-OSS sequencer
#   The ioctl handlers for OSS compatible drivers are rewritten using
#   unlocked/compat_ioctl.
#   
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/core/seq/oss/seq_oss.c
#   2005/01/20 10:14:45+01:00 perex@suse.cz +11 -10
#   [ALSA] unlocked/compat_ioctl rewrite for OSS compatible drivers
#   
#   D:2005/01/20 17:14:44
#   C:ALSA<-OSS emulation,ALSA<-OSS sequencer
#   F:core/oss/mixer_oss.c:1.37->1.38 
#   F:core/oss/pcm_oss.c:1.83->1.84 
#   F:core/seq/oss/seq_oss.c:1.17->1.18 
#   L:The ioctl handlers for OSS compatible drivers are rewritten using
#   L:unlocked/compat_ioctl.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/core/oss/pcm_oss.c
#   2005/01/20 10:14:45+01:00 perex@suse.cz +9 -13
#   [ALSA] unlocked/compat_ioctl rewrite for OSS compatible drivers
#   
#   D:2005/01/20 17:14:44
#   C:ALSA<-OSS emulation,ALSA<-OSS sequencer
#   F:core/oss/mixer_oss.c:1.37->1.38 
#   F:core/oss/pcm_oss.c:1.83->1.84 
#   F:core/seq/oss/seq_oss.c:1.17->1.18 
#   L:The ioctl handlers for OSS compatible drivers are rewritten using
#   L:unlocked/compat_ioctl.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/core/oss/mixer_oss.c
#   2005/01/20 10:14:44+01:00 perex@suse.cz +11 -10
#   [ALSA] unlocked/compat_ioctl rewrite for OSS compatible drivers
#   
#   D:2005/01/20 17:14:44
#   C:ALSA<-OSS emulation,ALSA<-OSS sequencer
#   F:core/oss/mixer_oss.c:1.37->1.38 
#   F:core/oss/pcm_oss.c:1.83->1.84 
#   F:core/seq/oss/seq_oss.c:1.17->1.18 
#   L:The ioctl handlers for OSS compatible drivers are rewritten using
#   L:unlocked/compat_ioctl.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2005/01/20 20:28:06+01:00 perex@suse.cz 
#   [ALSA] unlocked/compat_ioctl rewrite for hwdep, rawmidi, timer and sequencer API
#   
#   HWDEP Midlevel,RawMidi Midlevel,Timer Midlevel,ALSA sequencer
#   The ioctl handler for hwdep, rawmidi, timer and sequencer API are rewritten
#   using unlocked/compat_ioctl.
#   The 32bit wrapper is merged to the core module.
#   
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/core/timer_compat.c
#   2005/01/20 19:16:31+01:00 perex@suse.cz +119 -0
#   [ALSA] unlocked/compat_ioctl rewrite for hwdep, rawmidi, timer and sequencer API
#   
#   D:2005/01/20 17:13:40
#   C:HWDEP Midlevel,RawMidi Midlevel,Timer Midlevel,ALSA sequencer
#   F:core/hwdep.c:1.28->1.29 
#   F:core/hwdep_compat.c:INITIAL->1.1 
#   F:core/rawmidi.c:1.51->1.52 
#   F:core/rawmidi_compat.c:INITIAL->1.1 
#   F:core/timer.c:1.63->1.64 
#   F:core/timer_compat.c:INITIAL->1.1 
#   F:core/seq/seq_clientmgr.c:1.40->1.41 
#   F:core/seq/seq_compat.c:INITIAL->1.1 
#   F:include/hwdep.h:1.6->1.7 
#   L:The ioctl handler for hwdep, rawmidi, timer and sequencer API are rewritten
#   L:using unlocked/compat_ioctl.
#   L:The 32bit wrapper is merged to the core module.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/core/seq/seq_compat.c
#   2005/01/20 19:17:01+01:00 perex@suse.cz +137 -0
#   [ALSA] unlocked/compat_ioctl rewrite for hwdep, rawmidi, timer and sequencer API
#   
#   D:2005/01/20 17:13:40
#   C:HWDEP Midlevel,RawMidi Midlevel,Timer Midlevel,ALSA sequencer
#   F:core/hwdep.c:1.28->1.29 
#   F:core/hwdep_compat.c:INITIAL->1.1 
#   F:core/rawmidi.c:1.51->1.52 
#   F:core/rawmidi_compat.c:INITIAL->1.1 
#   F:core/timer.c:1.63->1.64 
#   F:core/timer_compat.c:INITIAL->1.1 
#   F:core/seq/seq_clientmgr.c:1.40->1.41 
#   F:core/seq/seq_compat.c:INITIAL->1.1 
#   F:include/hwdep.h:1.6->1.7 
#   L:The ioctl handler for hwdep, rawmidi, timer and sequencer API are rewritten
#   L:using unlocked/compat_ioctl.
#   L:The 32bit wrapper is merged to the core module.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/core/rawmidi_compat.c
#   2005/01/20 19:16:21+01:00 perex@suse.cz +120 -0
#   [ALSA] unlocked/compat_ioctl rewrite for hwdep, rawmidi, timer and sequencer API
#   
#   D:2005/01/20 17:13:40
#   C:HWDEP Midlevel,RawMidi Midlevel,Timer Midlevel,ALSA sequencer
#   F:core/hwdep.c:1.28->1.29 
#   F:core/hwdep_compat.c:INITIAL->1.1 
#   F:core/rawmidi.c:1.51->1.52 
#   F:core/rawmidi_compat.c:INITIAL->1.1 
#   F:core/timer.c:1.63->1.64 
#   F:core/timer_compat.c:INITIAL->1.1 
#   F:core/seq/seq_clientmgr.c:1.40->1.41 
#   F:core/seq/seq_compat.c:INITIAL->1.1 
#   F:include/hwdep.h:1.6->1.7 
#   L:The ioctl handler for hwdep, rawmidi, timer and sequencer API are rewritten
#   L:using unlocked/compat_ioctl.
#   L:The 32bit wrapper is merged to the core module.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/core/timer_compat.c
#   2005/01/20 19:16:31+01:00 perex@suse.cz +0 -0
#   BitKeeper file /home/perex/bk/linux-sound/work/sound/core/timer_compat.c
# 
# sound/core/timer.c
#   2005/01/20 10:13:40+01:00 perex@suse.cz +9 -14
#   [ALSA] unlocked/compat_ioctl rewrite for hwdep, rawmidi, timer and sequencer API
#   
#   D:2005/01/20 17:13:40
#   C:HWDEP Midlevel,RawMidi Midlevel,Timer Midlevel,ALSA sequencer
#   F:core/hwdep.c:1.28->1.29 
#   F:core/hwdep_compat.c:INITIAL->1.1 
#   F:core/rawmidi.c:1.51->1.52 
#   F:core/rawmidi_compat.c:INITIAL->1.1 
#   F:core/timer.c:1.63->1.64 
#   F:core/timer_compat.c:INITIAL->1.1 
#   F:core/seq/seq_clientmgr.c:1.40->1.41 
#   F:core/seq/seq_compat.c:INITIAL->1.1 
#   F:include/hwdep.h:1.6->1.7 
#   L:The ioctl handler for hwdep, rawmidi, timer and sequencer API are rewritten
#   L:using unlocked/compat_ioctl.
#   L:The 32bit wrapper is merged to the core module.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/core/seq/seq_compat.c
#   2005/01/20 19:17:01+01:00 perex@suse.cz +0 -0
#   BitKeeper file /home/perex/bk/linux-sound/work/sound/core/seq/seq_compat.c
# 
# sound/core/seq/seq_clientmgr.c
#   2005/01/20 10:13:41+01:00 perex@suse.cz +9 -9
#   [ALSA] unlocked/compat_ioctl rewrite for hwdep, rawmidi, timer and sequencer API
#   
#   D:2005/01/20 17:13:40
#   C:HWDEP Midlevel,RawMidi Midlevel,Timer Midlevel,ALSA sequencer
#   F:core/hwdep.c:1.28->1.29 
#   F:core/hwdep_compat.c:INITIAL->1.1 
#   F:core/rawmidi.c:1.51->1.52 
#   F:core/rawmidi_compat.c:INITIAL->1.1 
#   F:core/timer.c:1.63->1.64 
#   F:core/timer_compat.c:INITIAL->1.1 
#   F:core/seq/seq_clientmgr.c:1.40->1.41 
#   F:core/seq/seq_compat.c:INITIAL->1.1 
#   F:include/hwdep.h:1.6->1.7 
#   L:The ioctl handler for hwdep, rawmidi, timer and sequencer API are rewritten
#   L:using unlocked/compat_ioctl.
#   L:The 32bit wrapper is merged to the core module.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/core/rawmidi_compat.c
#   2005/01/20 19:16:21+01:00 perex@suse.cz +0 -0
#   BitKeeper file /home/perex/bk/linux-sound/work/sound/core/rawmidi_compat.c
# 
# sound/core/rawmidi.c
#   2005/01/20 10:13:40+01:00 perex@suse.cz +13 -14
#   [ALSA] unlocked/compat_ioctl rewrite for hwdep, rawmidi, timer and sequencer API
#   
#   D:2005/01/20 17:13:40
#   C:HWDEP Midlevel,RawMidi Midlevel,Timer Midlevel,ALSA sequencer
#   F:core/hwdep.c:1.28->1.29 
#   F:core/hwdep_compat.c:INITIAL->1.1 
#   F:core/rawmidi.c:1.51->1.52 
#   F:core/rawmidi_compat.c:INITIAL->1.1 
#   F:core/timer.c:1.63->1.64 
#   F:core/timer_compat.c:INITIAL->1.1 
#   F:core/seq/seq_clientmgr.c:1.40->1.41 
#   F:core/seq/seq_compat.c:INITIAL->1.1 
#   F:include/hwdep.h:1.6->1.7 
#   L:The ioctl handler for hwdep, rawmidi, timer and sequencer API are rewritten
#   L:using unlocked/compat_ioctl.
#   L:The 32bit wrapper is merged to the core module.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/core/hwdep.c
#   2005/01/20 10:13:40+01:00 perex@suse.cz +11 -14
#   [ALSA] unlocked/compat_ioctl rewrite for hwdep, rawmidi, timer and sequencer API
#   
#   D:2005/01/20 17:13:40
#   C:HWDEP Midlevel,RawMidi Midlevel,Timer Midlevel,ALSA sequencer
#   F:core/hwdep.c:1.28->1.29 
#   F:core/hwdep_compat.c:INITIAL->1.1 
#   F:core/rawmidi.c:1.51->1.52 
#   F:core/rawmidi_compat.c:INITIAL->1.1 
#   F:core/timer.c:1.63->1.64 
#   F:core/timer_compat.c:INITIAL->1.1 
#   F:core/seq/seq_clientmgr.c:1.40->1.41 
#   F:core/seq/seq_compat.c:INITIAL->1.1 
#   F:include/hwdep.h:1.6->1.7 
#   L:The ioctl handler for hwdep, rawmidi, timer and sequencer API are rewritten
#   L:using unlocked/compat_ioctl.
#   L:The 32bit wrapper is merged to the core module.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# include/sound/hwdep.h
#   2005/01/20 10:13:41+01:00 perex@suse.cz +1 -0
#   [ALSA] unlocked/compat_ioctl rewrite for hwdep, rawmidi, timer and sequencer API
#   
#   D:2005/01/20 17:13:40
#   C:HWDEP Midlevel,RawMidi Midlevel,Timer Midlevel,ALSA sequencer
#   F:core/hwdep.c:1.28->1.29 
#   F:core/hwdep_compat.c:INITIAL->1.1 
#   F:core/rawmidi.c:1.51->1.52 
#   F:core/rawmidi_compat.c:INITIAL->1.1 
#   F:core/timer.c:1.63->1.64 
#   F:core/timer_compat.c:INITIAL->1.1 
#   F:core/seq/seq_clientmgr.c:1.40->1.41 
#   F:core/seq/seq_compat.c:INITIAL->1.1 
#   F:include/hwdep.h:1.6->1.7 
#   L:The ioctl handler for hwdep, rawmidi, timer and sequencer API are rewritten
#   L:using unlocked/compat_ioctl.
#   L:The 32bit wrapper is merged to the core module.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/core/hwdep_compat.c
#   2005/01/20 19:16:12+01:00 perex@suse.cz +77 -0
#   [ALSA] unlocked/compat_ioctl rewrite for hwdep, rawmidi, timer and sequencer API
#   
#   D:2005/01/20 17:13:40
#   C:HWDEP Midlevel,RawMidi Midlevel,Timer Midlevel,ALSA sequencer
#   F:core/hwdep.c:1.28->1.29 
#   F:core/hwdep_compat.c:INITIAL->1.1 
#   F:core/rawmidi.c:1.51->1.52 
#   F:core/rawmidi_compat.c:INITIAL->1.1 
#   F:core/timer.c:1.63->1.64 
#   F:core/timer_compat.c:INITIAL->1.1 
#   F:core/seq/seq_clientmgr.c:1.40->1.41 
#   F:core/seq/seq_compat.c:INITIAL->1.1 
#   F:include/hwdep.h:1.6->1.7 
#   L:The ioctl handler for hwdep, rawmidi, timer and sequencer API are rewritten
#   L:using unlocked/compat_ioctl.
#   L:The 32bit wrapper is merged to the core module.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/core/hwdep_compat.c
#   2005/01/20 19:16:12+01:00 perex@suse.cz +0 -0
#   BitKeeper file /home/perex/bk/linux-sound/work/sound/core/hwdep_compat.c
# 
# ChangeSet
#   2005/01/20 20:26:43+01:00 perex@suse.cz 
#   [ALSA] unlocked/compat_ioctl rewrite for PCM API
#   
#   PCM Midlevel
#   The ioctl handler for PCM API is rewritten using unlocked/compat_ioctl.
#   The 32bit wrapper is merged to the core module.
#   
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/core/pcm_native.c
#   2005/01/20 10:11:46+01:00 perex@suse.cz +17 -18
#   [ALSA] unlocked/compat_ioctl rewrite for PCM API
#   
#   D:2005/01/20 17:11:46
#   C:PCM Midlevel
#   F:core/pcm.c:1.49->1.50 
#   F:core/pcm_compat.c:INITIAL->1.1 
#   F:core/pcm_native.c:1.111->1.112 
#   L:The ioctl handler for PCM API is rewritten using unlocked/compat_ioctl.
#   L:The 32bit wrapper is merged to the core module.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/core/pcm.c
#   2005/01/20 10:11:46+01:00 perex@suse.cz +2 -0
#   [ALSA] unlocked/compat_ioctl rewrite for PCM API
#   
#   D:2005/01/20 17:11:46
#   C:PCM Midlevel
#   F:core/pcm.c:1.49->1.50 
#   F:core/pcm_compat.c:INITIAL->1.1 
#   F:core/pcm_native.c:1.111->1.112 
#   L:The ioctl handler for PCM API is rewritten using unlocked/compat_ioctl.
#   L:The 32bit wrapper is merged to the core module.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/core/pcm_compat.c
#   2005/01/20 19:15:57+01:00 perex@suse.cz +513 -0
#   [ALSA] unlocked/compat_ioctl rewrite for PCM API
#   
#   D:2005/01/20 17:11:46
#   C:PCM Midlevel
#   F:core/pcm.c:1.49->1.50 
#   F:core/pcm_compat.c:INITIAL->1.1 
#   F:core/pcm_native.c:1.111->1.112 
#   L:The ioctl handler for PCM API is rewritten using unlocked/compat_ioctl.
#   L:The 32bit wrapper is merged to the core module.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/core/pcm_compat.c
#   2005/01/20 19:15:57+01:00 perex@suse.cz +0 -0
#   BitKeeper file /home/perex/bk/linux-sound/work/sound/core/pcm_compat.c
# 
# ChangeSet
#   2005/01/20 20:25:19+01:00 perex@suse.cz 
#   [ALSA] unlocked/compat_ioctl rewrite for control API
#   
#   Control Midlevel
#   ioctl handler for control API is rewritten using unlocked/compat_ioctl.
#   The 32bit wrapper is merged to the core module.
#   
#   Added a new register/unregister function for compat control ioctls.
#   
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/core/control.c
#   2005/01/20 10:10:23+01:00 perex@suse.cz +95 -81
#   [ALSA] unlocked/compat_ioctl rewrite for control API
#   
#   D:2005/01/20 17:10:23
#   C:Control Midlevel
#   F:core/control.c:1.55->1.56 
#   F:core/control_compat.c:INITIAL->1.1 
#   F:include/control.h:1.11->1.12 
#   L:ioctl handler for control API is rewritten using unlocked/compat_ioctl.
#   L:The 32bit wrapper is merged to the core module.
#   L:
#   L:Added a new register/unregister function for compat control ioctls.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# include/sound/control.h
#   2005/01/20 10:10:24+01:00 perex@suse.cz +7 -0
#   [ALSA] unlocked/compat_ioctl rewrite for control API
#   
#   D:2005/01/20 17:10:23
#   C:Control Midlevel
#   F:core/control.c:1.55->1.56 
#   F:core/control_compat.c:INITIAL->1.1 
#   F:include/control.h:1.11->1.12 
#   L:ioctl handler for control API is rewritten using unlocked/compat_ioctl.
#   L:The 32bit wrapper is merged to the core module.
#   L:
#   L:Added a new register/unregister function for compat control ioctls.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/core/control_compat.c
#   2005/01/20 19:15:43+01:00 perex@suse.cz +412 -0
#   [ALSA] unlocked/compat_ioctl rewrite for control API
#   
#   D:2005/01/20 17:10:23
#   C:Control Midlevel
#   F:core/control.c:1.55->1.56 
#   F:core/control_compat.c:INITIAL->1.1 
#   F:include/control.h:1.11->1.12 
#   L:ioctl handler for control API is rewritten using unlocked/compat_ioctl.
#   L:The 32bit wrapper is merged to the core module.
#   L:
#   L:Added a new register/unregister function for compat control ioctls.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/core/control_compat.c
#   2005/01/20 19:15:43+01:00 perex@suse.cz +0 -0
#   BitKeeper file /home/perex/bk/linux-sound/work/sound/core/control_compat.c
# 
# ChangeSet
#   2005/01/20 20:23:54+01:00 perex@suse.cz 
#   [ALSA] Add Intel HDA driver
#   
#   Documentation,PCI drivers,HDA generic driver,HDA Codec driver
#   HDA Intel driver
#   Added a new Intel High-Definition audio driver.
#   The driver consists of two separate modules: the generic support
#   module for HD codecs (snd-hda-codec), and the driver for Intel ICH6/7
#   chipset (snd-hda-intel).  The snd-hda-intel was called formerly
#   snd-azx in the ALSA 1.0.8 rlease.
#   
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/hda/patch_realtek.c
#   2005/01/20 19:15:31+01:00 perex@suse.cz +1174 -0
#   [ALSA] Add Intel HDA driver
#   
#   D:2005/01/20 15:02:27
#   C:Documentation,PCI drivers,HDA generic driver,HDA Codec driver
#   C:HDA Intel driver
#   F:Documentation/ALSA-Configuration.txt:1.63->1.64 
#   F:Documentation/hda_codec.txt:INITIAL->1.1 
#   F:pci/Kconfig:1.39->1.40 
#   F:pci/Makefile:1.19->1.20 
#   F:pci/hda/Makefile:INITIAL->1.1 
#   F:pci/hda/hda_codec.c:INITIAL->1.1 
#   F:pci/hda/hda_codec.h:INITIAL->1.1 
#   F:pci/hda/hda_generic.c:INITIAL->1.1 
#   F:pci/hda/hda_intel.c:INITIAL->1.1 
#   F:pci/hda/hda_local.h:INITIAL->1.1 
#   F:pci/hda/hda_patch.h:INITIAL->1.1 
#   F:pci/hda/hda_proc.c:INITIAL->1.1 
#   F:pci/hda/patch_cmedia.c:INITIAL->1.1 
#   F:pci/hda/patch_realtek.c:INITIAL->1.1 
#   L:Added a new Intel High-Definition audio driver.
#   L:The driver consists of two separate modules: the generic support
#   L:module for HD codecs (snd-hda-codec), and the driver for Intel ICH6/7
#   L:chipset (snd-hda-intel).  The snd-hda-intel was called formerly
#   L:snd-azx in the ALSA 1.0.8 rlease.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/hda/patch_cmedia.c
#   2005/01/20 19:15:26+01:00 perex@suse.cz +614 -0
#   [ALSA] Add Intel HDA driver
#   
#   D:2005/01/20 15:02:27
#   C:Documentation,PCI drivers,HDA generic driver,HDA Codec driver
#   C:HDA Intel driver
#   F:Documentation/ALSA-Configuration.txt:1.63->1.64 
#   F:Documentation/hda_codec.txt:INITIAL->1.1 
#   F:pci/Kconfig:1.39->1.40 
#   F:pci/Makefile:1.19->1.20 
#   F:pci/hda/Makefile:INITIAL->1.1 
#   F:pci/hda/hda_codec.c:INITIAL->1.1 
#   F:pci/hda/hda_codec.h:INITIAL->1.1 
#   F:pci/hda/hda_generic.c:INITIAL->1.1 
#   F:pci/hda/hda_intel.c:INITIAL->1.1 
#   F:pci/hda/hda_local.h:INITIAL->1.1 
#   F:pci/hda/hda_patch.h:INITIAL->1.1 
#   F:pci/hda/hda_proc.c:INITIAL->1.1 
#   F:pci/hda/patch_cmedia.c:INITIAL->1.1 
#   F:pci/hda/patch_realtek.c:INITIAL->1.1 
#   L:Added a new Intel High-Definition audio driver.
#   L:The driver consists of two separate modules: the generic support
#   L:module for HD codecs (snd-hda-codec), and the driver for Intel ICH6/7
#   L:chipset (snd-hda-intel).  The snd-hda-intel was called formerly
#   L:snd-azx in the ALSA 1.0.8 rlease.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/hda/hda_proc.c
#   2005/01/20 19:15:21+01:00 perex@suse.cz +298 -0
#   [ALSA] Add Intel HDA driver
#   
#   D:2005/01/20 15:02:27
#   C:Documentation,PCI drivers,HDA generic driver,HDA Codec driver
#   C:HDA Intel driver
#   F:Documentation/ALSA-Configuration.txt:1.63->1.64 
#   F:Documentation/hda_codec.txt:INITIAL->1.1 
#   F:pci/Kconfig:1.39->1.40 
#   F:pci/Makefile:1.19->1.20 
#   F:pci/hda/Makefile:INITIAL->1.1 
#   F:pci/hda/hda_codec.c:INITIAL->1.1 
#   F:pci/hda/hda_codec.h:INITIAL->1.1 
#   F:pci/hda/hda_generic.c:INITIAL->1.1 
#   F:pci/hda/hda_intel.c:INITIAL->1.1 
#   F:pci/hda/hda_local.h:INITIAL->1.1 
#   F:pci/hda/hda_patch.h:INITIAL->1.1 
#   F:pci/hda/hda_proc.c:INITIAL->1.1 
#   F:pci/hda/patch_cmedia.c:INITIAL->1.1 
#   F:pci/hda/patch_realtek.c:INITIAL->1.1 
#   L:Added a new Intel High-Definition audio driver.
#   L:The driver consists of two separate modules: the generic support
#   L:module for HD codecs (snd-hda-codec), and the driver for Intel ICH6/7
#   L:chipset (snd-hda-intel).  The snd-hda-intel was called formerly
#   L:snd-azx in the ALSA 1.0.8 rlease.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/hda/hda_patch.h
#   2005/01/20 19:15:17+01:00 perex@suse.cz +14 -0
#   [ALSA] Add Intel HDA driver
#   
#   D:2005/01/20 15:02:27
#   C:Documentation,PCI drivers,HDA generic driver,HDA Codec driver
#   C:HDA Intel driver
#   F:Documentation/ALSA-Configuration.txt:1.63->1.64 
#   F:Documentation/hda_codec.txt:INITIAL->1.1 
#   F:pci/Kconfig:1.39->1.40 
#   F:pci/Makefile:1.19->1.20 
#   F:pci/hda/Makefile:INITIAL->1.1 
#   F:pci/hda/hda_codec.c:INITIAL->1.1 
#   F:pci/hda/hda_codec.h:INITIAL->1.1 
#   F:pci/hda/hda_generic.c:INITIAL->1.1 
#   F:pci/hda/hda_intel.c:INITIAL->1.1 
#   F:pci/hda/hda_local.h:INITIAL->1.1 
#   F:pci/hda/hda_patch.h:INITIAL->1.1 
#   F:pci/hda/hda_proc.c:INITIAL->1.1 
#   F:pci/hda/patch_cmedia.c:INITIAL->1.1 
#   F:pci/hda/patch_realtek.c:INITIAL->1.1 
#   L:Added a new Intel High-Definition audio driver.
#   L:The driver consists of two separate modules: the generic support
#   L:module for HD codecs (snd-hda-codec), and the driver for Intel ICH6/7
#   L:chipset (snd-hda-intel).  The snd-hda-intel was called formerly
#   L:snd-azx in the ALSA 1.0.8 rlease.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/hda/hda_local.h
#   2005/01/20 19:15:12+01:00 perex@suse.cz +159 -0
#   [ALSA] Add Intel HDA driver
#   
#   D:2005/01/20 15:02:27
#   C:Documentation,PCI drivers,HDA generic driver,HDA Codec driver
#   C:HDA Intel driver
#   F:Documentation/ALSA-Configuration.txt:1.63->1.64 
#   F:Documentation/hda_codec.txt:INITIAL->1.1 
#   F:pci/Kconfig:1.39->1.40 
#   F:pci/Makefile:1.19->1.20 
#   F:pci/hda/Makefile:INITIAL->1.1 
#   F:pci/hda/hda_codec.c:INITIAL->1.1 
#   F:pci/hda/hda_codec.h:INITIAL->1.1 
#   F:pci/hda/hda_generic.c:INITIAL->1.1 
#   F:pci/hda/hda_intel.c:INITIAL->1.1 
#   F:pci/hda/hda_local.h:INITIAL->1.1 
#   F:pci/hda/hda_patch.h:INITIAL->1.1 
#   F:pci/hda/hda_proc.c:INITIAL->1.1 
#   F:pci/hda/patch_cmedia.c:INITIAL->1.1 
#   F:pci/hda/patch_realtek.c:INITIAL->1.1 
#   L:Added a new Intel High-Definition audio driver.
#   L:The driver consists of two separate modules: the generic support
#   L:module for HD codecs (snd-hda-codec), and the driver for Intel ICH6/7
#   L:chipset (snd-hda-intel).  The snd-hda-intel was called formerly
#   L:snd-azx in the ALSA 1.0.8 rlease.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/hda/hda_intel.c
#   2005/01/20 19:15:07+01:00 perex@suse.cz +1449 -0
#   [ALSA] Add Intel HDA driver
#   
#   D:2005/01/20 15:02:27
#   C:Documentation,PCI drivers,HDA generic driver,HDA Codec driver
#   C:HDA Intel driver
#   F:Documentation/ALSA-Configuration.txt:1.63->1.64 
#   F:Documentation/hda_codec.txt:INITIAL->1.1 
#   F:pci/Kconfig:1.39->1.40 
#   F:pci/Makefile:1.19->1.20 
#   F:pci/hda/Makefile:INITIAL->1.1 
#   F:pci/hda/hda_codec.c:INITIAL->1.1 
#   F:pci/hda/hda_codec.h:INITIAL->1.1 
#   F:pci/hda/hda_generic.c:INITIAL->1.1 
#   F:pci/hda/hda_intel.c:INITIAL->1.1 
#   F:pci/hda/hda_local.h:INITIAL->1.1 
#   F:pci/hda/hda_patch.h:INITIAL->1.1 
#   F:pci/hda/hda_proc.c:INITIAL->1.1 
#   F:pci/hda/patch_cmedia.c:INITIAL->1.1 
#   F:pci/hda/patch_realtek.c:INITIAL->1.1 
#   L:Added a new Intel High-Definition audio driver.
#   L:The driver consists of two separate modules: the generic support
#   L:module for HD codecs (snd-hda-codec), and the driver for Intel ICH6/7
#   L:chipset (snd-hda-intel).  The snd-hda-intel was called formerly
#   L:snd-azx in the ALSA 1.0.8 rlease.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/hda/hda_generic.c
#   2005/01/20 19:15:01+01:00 perex@suse.cz +898 -0
#   [ALSA] Add Intel HDA driver
#   
#   D:2005/01/20 15:02:27
#   C:Documentation,PCI drivers,HDA generic driver,HDA Codec driver
#   C:HDA Intel driver
#   F:Documentation/ALSA-Configuration.txt:1.63->1.64 
#   F:Documentation/hda_codec.txt:INITIAL->1.1 
#   F:pci/Kconfig:1.39->1.40 
#   F:pci/Makefile:1.19->1.20 
#   F:pci/hda/Makefile:INITIAL->1.1 
#   F:pci/hda/hda_codec.c:INITIAL->1.1 
#   F:pci/hda/hda_codec.h:INITIAL->1.1 
#   F:pci/hda/hda_generic.c:INITIAL->1.1 
#   F:pci/hda/hda_intel.c:INITIAL->1.1 
#   F:pci/hda/hda_local.h:INITIAL->1.1 
#   F:pci/hda/hda_patch.h:INITIAL->1.1 
#   F:pci/hda/hda_proc.c:INITIAL->1.1 
#   F:pci/hda/patch_cmedia.c:INITIAL->1.1 
#   F:pci/hda/patch_realtek.c:INITIAL->1.1 
#   L:Added a new Intel High-Definition audio driver.
#   L:The driver consists of two separate modules: the generic support
#   L:module for HD codecs (snd-hda-codec), and the driver for Intel ICH6/7
#   L:chipset (snd-hda-intel).  The snd-hda-intel was called formerly
#   L:snd-azx in the ALSA 1.0.8 rlease.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/hda/hda_codec.h
#   2005/01/20 19:14:56+01:00 perex@suse.cz +602 -0
#   [ALSA] Add Intel HDA driver
#   
#   D:2005/01/20 15:02:27
#   C:Documentation,PCI drivers,HDA generic driver,HDA Codec driver
#   C:HDA Intel driver
#   F:Documentation/ALSA-Configuration.txt:1.63->1.64 
#   F:Documentation/hda_codec.txt:INITIAL->1.1 
#   F:pci/Kconfig:1.39->1.40 
#   F:pci/Makefile:1.19->1.20 
#   F:pci/hda/Makefile:INITIAL->1.1 
#   F:pci/hda/hda_codec.c:INITIAL->1.1 
#   F:pci/hda/hda_codec.h:INITIAL->1.1 
#   F:pci/hda/hda_generic.c:INITIAL->1.1 
#   F:pci/hda/hda_intel.c:INITIAL->1.1 
#   F:pci/hda/hda_local.h:INITIAL->1.1 
#   F:pci/hda/hda_patch.h:INITIAL->1.1 
#   F:pci/hda/hda_proc.c:INITIAL->1.1 
#   F:pci/hda/patch_cmedia.c:INITIAL->1.1 
#   F:pci/hda/patch_realtek.c:INITIAL->1.1 
#   L:Added a new Intel High-Definition audio driver.
#   L:The driver consists of two separate modules: the generic support
#   L:module for HD codecs (snd-hda-codec), and the driver for Intel ICH6/7
#   L:chipset (snd-hda-intel).  The snd-hda-intel was called formerly
#   L:snd-azx in the ALSA 1.0.8 rlease.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/hda/hda_codec.c
#   2005/01/20 19:14:51+01:00 perex@suse.cz +1731 -0
#   [ALSA] Add Intel HDA driver
#   
#   D:2005/01/20 15:02:27
#   C:Documentation,PCI drivers,HDA generic driver,HDA Codec driver
#   C:HDA Intel driver
#   F:Documentation/ALSA-Configuration.txt:1.63->1.64 
#   F:Documentation/hda_codec.txt:INITIAL->1.1 
#   F:pci/Kconfig:1.39->1.40 
#   F:pci/Makefile:1.19->1.20 
#   F:pci/hda/Makefile:INITIAL->1.1 
#   F:pci/hda/hda_codec.c:INITIAL->1.1 
#   F:pci/hda/hda_codec.h:INITIAL->1.1 
#   F:pci/hda/hda_generic.c:INITIAL->1.1 
#   F:pci/hda/hda_intel.c:INITIAL->1.1 
#   F:pci/hda/hda_local.h:INITIAL->1.1 
#   F:pci/hda/hda_patch.h:INITIAL->1.1 
#   F:pci/hda/hda_proc.c:INITIAL->1.1 
#   F:pci/hda/patch_cmedia.c:INITIAL->1.1 
#   F:pci/hda/patch_realtek.c:INITIAL->1.1 
#   L:Added a new Intel High-Definition audio driver.
#   L:The driver consists of two separate modules: the generic support
#   L:module for HD codecs (snd-hda-codec), and the driver for Intel ICH6/7
#   L:chipset (snd-hda-intel).  The snd-hda-intel was called formerly
#   L:snd-azx in the ALSA 1.0.8 rlease.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/hda/Makefile
#   2005/01/20 19:14:46+01:00 perex@suse.cz +7 -0
#   [ALSA] Add Intel HDA driver
#   
#   D:2005/01/20 15:02:27
#   C:Documentation,PCI drivers,HDA generic driver,HDA Codec driver
#   C:HDA Intel driver
#   F:Documentation/ALSA-Configuration.txt:1.63->1.64 
#   F:Documentation/hda_codec.txt:INITIAL->1.1 
#   F:pci/Kconfig:1.39->1.40 
#   F:pci/Makefile:1.19->1.20 
#   F:pci/hda/Makefile:INITIAL->1.1 
#   F:pci/hda/hda_codec.c:INITIAL->1.1 
#   F:pci/hda/hda_codec.h:INITIAL->1.1 
#   F:pci/hda/hda_generic.c:INITIAL->1.1 
#   F:pci/hda/hda_intel.c:INITIAL->1.1 
#   F:pci/hda/hda_local.h:INITIAL->1.1 
#   F:pci/hda/hda_patch.h:INITIAL->1.1 
#   F:pci/hda/hda_proc.c:INITIAL->1.1 
#   F:pci/hda/patch_cmedia.c:INITIAL->1.1 
#   F:pci/hda/patch_realtek.c:INITIAL->1.1 
#   L:Added a new Intel High-Definition audio driver.
#   L:The driver consists of two separate modules: the generic support
#   L:module for HD codecs (snd-hda-codec), and the driver for Intel ICH6/7
#   L:chipset (snd-hda-intel).  The snd-hda-intel was called formerly
#   L:snd-azx in the ALSA 1.0.8 rlease.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/hda/patch_realtek.c
#   2005/01/20 19:15:31+01:00 perex@suse.cz +0 -0
#   BitKeeper file /home/perex/bk/linux-sound/work/sound/pci/hda/patch_realtek.c
# 
# sound/pci/hda/patch_cmedia.c
#   2005/01/20 19:15:26+01:00 perex@suse.cz +0 -0
#   BitKeeper file /home/perex/bk/linux-sound/work/sound/pci/hda/patch_cmedia.c
# 
# sound/pci/hda/hda_proc.c
#   2005/01/20 19:15:21+01:00 perex@suse.cz +0 -0
#   BitKeeper file /home/perex/bk/linux-sound/work/sound/pci/hda/hda_proc.c
# 
# sound/pci/hda/hda_patch.h
#   2005/01/20 19:15:17+01:00 perex@suse.cz +0 -0
#   BitKeeper file /home/perex/bk/linux-sound/work/sound/pci/hda/hda_patch.h
# 
# sound/pci/hda/hda_local.h
#   2005/01/20 19:15:12+01:00 perex@suse.cz +0 -0
#   BitKeeper file /home/perex/bk/linux-sound/work/sound/pci/hda/hda_local.h
# 
# sound/pci/hda/hda_intel.c
#   2005/01/20 19:15:07+01:00 perex@suse.cz +0 -0
#   BitKeeper file /home/perex/bk/linux-sound/work/sound/pci/hda/hda_intel.c
# 
# sound/pci/hda/hda_generic.c
#   2005/01/20 19:15:01+01:00 perex@suse.cz +0 -0
#   BitKeeper file /home/perex/bk/linux-sound/work/sound/pci/hda/hda_generic.c
# 
# sound/pci/hda/hda_codec.h
#   2005/01/20 19:14:56+01:00 perex@suse.cz +0 -0
#   BitKeeper file /home/perex/bk/linux-sound/work/sound/pci/hda/hda_codec.h
# 
# sound/pci/hda/hda_codec.c
#   2005/01/20 19:14:51+01:00 perex@suse.cz +0 -0
#   BitKeeper file /home/perex/bk/linux-sound/work/sound/pci/hda/hda_codec.c
# 
# sound/pci/hda/Makefile
#   2005/01/20 19:14:46+01:00 perex@suse.cz +0 -0
#   BitKeeper file /home/perex/bk/linux-sound/work/sound/pci/hda/Makefile
# 
# sound/pci/Makefile
#   2005/01/20 08:02:28+01:00 perex@suse.cz +1 -0
#   [ALSA] Add Intel HDA driver
#   
#   D:2005/01/20 15:02:27
#   C:Documentation,PCI drivers,HDA generic driver,HDA Codec driver
#   C:HDA Intel driver
#   F:Documentation/ALSA-Configuration.txt:1.63->1.64 
#   F:Documentation/hda_codec.txt:INITIAL->1.1 
#   F:pci/Kconfig:1.39->1.40 
#   F:pci/Makefile:1.19->1.20 
#   F:pci/hda/Makefile:INITIAL->1.1 
#   F:pci/hda/hda_codec.c:INITIAL->1.1 
#   F:pci/hda/hda_codec.h:INITIAL->1.1 
#   F:pci/hda/hda_generic.c:INITIAL->1.1 
#   F:pci/hda/hda_intel.c:INITIAL->1.1 
#   F:pci/hda/hda_local.h:INITIAL->1.1 
#   F:pci/hda/hda_patch.h:INITIAL->1.1 
#   F:pci/hda/hda_proc.c:INITIAL->1.1 
#   F:pci/hda/patch_cmedia.c:INITIAL->1.1 
#   F:pci/hda/patch_realtek.c:INITIAL->1.1 
#   L:Added a new Intel High-Definition audio driver.
#   L:The driver consists of two separate modules: the generic support
#   L:module for HD codecs (snd-hda-codec), and the driver for Intel ICH6/7
#   L:chipset (snd-hda-intel).  The snd-hda-intel was called formerly
#   L:snd-azx in the ALSA 1.0.8 rlease.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/Kconfig
#   2005/01/20 08:02:28+01:00 perex@suse.cz +11 -1
#   [ALSA] Add Intel HDA driver
#   
#   D:2005/01/20 15:02:27
#   C:Documentation,PCI drivers,HDA generic driver,HDA Codec driver
#   C:HDA Intel driver
#   F:Documentation/ALSA-Configuration.txt:1.63->1.64 
#   F:Documentation/hda_codec.txt:INITIAL->1.1 
#   F:pci/Kconfig:1.39->1.40 
#   F:pci/Makefile:1.19->1.20 
#   F:pci/hda/Makefile:INITIAL->1.1 
#   F:pci/hda/hda_codec.c:INITIAL->1.1 
#   F:pci/hda/hda_codec.h:INITIAL->1.1 
#   F:pci/hda/hda_generic.c:INITIAL->1.1 
#   F:pci/hda/hda_intel.c:INITIAL->1.1 
#   F:pci/hda/hda_local.h:INITIAL->1.1 
#   F:pci/hda/hda_patch.h:INITIAL->1.1 
#   F:pci/hda/hda_proc.c:INITIAL->1.1 
#   F:pci/hda/patch_cmedia.c:INITIAL->1.1 
#   F:pci/hda/patch_realtek.c:INITIAL->1.1 
#   L:Added a new Intel High-Definition audio driver.
#   L:The driver consists of two separate modules: the generic support
#   L:module for HD codecs (snd-hda-codec), and the driver for Intel ICH6/7
#   L:chipset (snd-hda-intel).  The snd-hda-intel was called formerly
#   L:snd-azx in the ALSA 1.0.8 rlease.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# Documentation/sound/alsa/ALSA-Configuration.txt
#   2005/01/20 08:02:27+01:00 perex@suse.cz +31 -0
#   [ALSA] Add Intel HDA driver
#   
#   D:2005/01/20 15:02:27
#   C:Documentation,PCI drivers,HDA generic driver,HDA Codec driver
#   C:HDA Intel driver
#   F:Documentation/ALSA-Configuration.txt:1.63->1.64 
#   F:Documentation/hda_codec.txt:INITIAL->1.1 
#   F:pci/Kconfig:1.39->1.40 
#   F:pci/Makefile:1.19->1.20 
#   F:pci/hda/Makefile:INITIAL->1.1 
#   F:pci/hda/hda_codec.c:INITIAL->1.1 
#   F:pci/hda/hda_codec.h:INITIAL->1.1 
#   F:pci/hda/hda_generic.c:INITIAL->1.1 
#   F:pci/hda/hda_intel.c:INITIAL->1.1 
#   F:pci/hda/hda_local.h:INITIAL->1.1 
#   F:pci/hda/hda_patch.h:INITIAL->1.1 
#   F:pci/hda/hda_proc.c:INITIAL->1.1 
#   F:pci/hda/patch_cmedia.c:INITIAL->1.1 
#   F:pci/hda/patch_realtek.c:INITIAL->1.1 
#   L:Added a new Intel High-Definition audio driver.
#   L:The driver consists of two separate modules: the generic support
#   L:module for HD codecs (snd-hda-codec), and the driver for Intel ICH6/7
#   L:chipset (snd-hda-intel).  The snd-hda-intel was called formerly
#   L:snd-azx in the ALSA 1.0.8 rlease.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# Documentation/sound/alsa/hda_codec.txt
#   2005/01/20 19:14:31+01:00 perex@suse.cz +299 -0
#   [ALSA] Add Intel HDA driver
#   
#   D:2005/01/20 15:02:27
#   C:Documentation,PCI drivers,HDA generic driver,HDA Codec driver
#   C:HDA Intel driver
#   F:Documentation/ALSA-Configuration.txt:1.63->1.64 
#   F:Documentation/hda_codec.txt:INITIAL->1.1 
#   F:pci/Kconfig:1.39->1.40 
#   F:pci/Makefile:1.19->1.20 
#   F:pci/hda/Makefile:INITIAL->1.1 
#   F:pci/hda/hda_codec.c:INITIAL->1.1 
#   F:pci/hda/hda_codec.h:INITIAL->1.1 
#   F:pci/hda/hda_generic.c:INITIAL->1.1 
#   F:pci/hda/hda_intel.c:INITIAL->1.1 
#   F:pci/hda/hda_local.h:INITIAL->1.1 
#   F:pci/hda/hda_patch.h:INITIAL->1.1 
#   F:pci/hda/hda_proc.c:INITIAL->1.1 
#   F:pci/hda/patch_cmedia.c:INITIAL->1.1 
#   F:pci/hda/patch_realtek.c:INITIAL->1.1 
#   L:Added a new Intel High-Definition audio driver.
#   L:The driver consists of two separate modules: the generic support
#   L:module for HD codecs (snd-hda-codec), and the driver for Intel ICH6/7
#   L:chipset (snd-hda-intel).  The snd-hda-intel was called formerly
#   L:snd-azx in the ALSA 1.0.8 rlease.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# Documentation/sound/alsa/hda_codec.txt
#   2005/01/20 19:14:31+01:00 perex@suse.cz +0 -0
#   BitKeeper file /home/perex/bk/linux-sound/work/Documentation/sound/alsa/hda_codec.txt
# 
# ChangeSet
#   2005/01/20 20:22:29+01:00 perex@suse.cz 
#   [ALSA] Enable HP jack sense for FSC Scenic-W
#   
#   AC97 Codec
#   Enable 'Headphone Jack Sense' control on FSC Scenic-W as default, too.
#   
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/ac97/ac97_patch.c
#   2005/01/20 04:43:19+01:00 perex@suse.cz +1 -0
#   [ALSA] Enable HP jack sense for FSC Scenic-W
#   
#   D:2005/01/20 11:43:19
#   C:AC97 Codec
#   F:pci/ac97/ac97_patch.c:1.69->1.70 
#   L:Enable 'Headphone Jack Sense' control on FSC Scenic-W as default, too.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2005/01/20 20:21:09+01:00 perex@suse.cz 
#   [ALSA] Add quirk for HP nc8000
#   
#   Intel8x0 driver
#   Added ac97 quirk for HP nc8000.
#   The list is sorted again.
#   
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/intel8x0.c
#   2005/01/20 04:41:50+01:00 perex@suse.cz +10 -4
#   [ALSA] Add quirk for HP nc8000
#   
#   D:2005/01/20 11:41:50
#   C:Intel8x0 driver
#   F:pci/intel8x0.c:1.189->1.190 
#   L:Added ac97 quirk for HP nc8000.
#   L:The list is sorted again.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2005/01/20 20:19:48+01:00 perex@suse.cz 
#   [ALSA] Add quirk for HP pavilion ZV5030US
#   
#   ATIIXP driver
#   Added ac97 quirk for HP Pavilion ZV5030US to bind the control with
#   mute-LED.
#   
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/atiixp.c
#   2005/01/19 09:43:06+01:00 perex@suse.cz +6 -0
#   [ALSA] Add quirk for HP pavilion ZV5030US
#   
#   D:2005/01/19 16:43:06
#   C:ATIIXP driver
#   F:pci/atiixp.c:1.30->1.31 
#   L:Added ac97 quirk for HP Pavilion ZV5030US to bind the control with
#   L:mute-LED.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2005/01/20 20:18:30+01:00 perex@suse.cz 
#   [ALSA] Simplify the general ac97 volume/switch callback
#   
#   AC97 Codec
#   Simplified the control callbacks of general AC97 volumes/switches.
#   
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/ac97/ac97_local.h
#   2005/01/19 05:03:51+01:00 perex@suse.cz +2 -4
#   [ALSA] Simplify the general ac97 volume/switch callback
#   
#   D:2005/01/19 12:03:49
#   C:AC97 Codec
#   F:pci/ac97/ac97_codec.c:1.168->1.169 
#   F:pci/ac97/ac97_local.h:1.11->1.12 
#   L:Simplified the control callbacks of general AC97 volumes/switches.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/ac97/ac97_codec.c
#   2005/01/19 05:03:49+01:00 perex@suse.cz +36 -37
#   [ALSA] Simplify the general ac97 volume/switch callback
#   
#   D:2005/01/19 12:03:49
#   C:AC97 Codec
#   F:pci/ac97/ac97_codec.c:1.168->1.169 
#   F:pci/ac97/ac97_local.h:1.11->1.12 
#   L:Simplified the control callbacks of general AC97 volumes/switches.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2005/01/20 20:17:15+01:00 perex@suse.cz 
#   [ALSA] Add missing inclusion of linux/device.h
#   
#   Digigram VX core,Digigram VX222 driver,Digigram VX Pocket driver
#   Added the missing inclusion of <linux/device.h>
#   
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pcmcia/vx/vxp_ops.c
#   2005/01/19 04:36:30+01:00 perex@suse.cz +1 -0
#   [ALSA] Add missing inclusion of linux/device.h
#   
#   D:2005/01/19 11:36:29
#   C:Digigram VX core,Digigram VX222 driver,Digigram VX Pocket driver
#   F:drivers/vx/vx_core.c:1.12->1.13 
#   F:drivers/vx/vx_hwdep.c:1.4->1.5 
#   F:pci/vx222/vx222_ops.c:1.8->1.9 
#   F:pcmcia/vx/vxp_ops.c:1.5->1.6 
#   L:Added the missing inclusion of <linux/device.h>
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/vx222/vx222_ops.c
#   2005/01/19 04:36:30+01:00 perex@suse.cz +1 -0
#   [ALSA] Add missing inclusion of linux/device.h
#   
#   D:2005/01/19 11:36:29
#   C:Digigram VX core,Digigram VX222 driver,Digigram VX Pocket driver
#   F:drivers/vx/vx_core.c:1.12->1.13 
#   F:drivers/vx/vx_hwdep.c:1.4->1.5 
#   F:pci/vx222/vx222_ops.c:1.8->1.9 
#   F:pcmcia/vx/vxp_ops.c:1.5->1.6 
#   L:Added the missing inclusion of <linux/device.h>
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/drivers/vx/vx_hwdep.c
#   2005/01/19 04:36:29+01:00 perex@suse.cz +1 -0
#   [ALSA] Add missing inclusion of linux/device.h
#   
#   D:2005/01/19 11:36:29
#   C:Digigram VX core,Digigram VX222 driver,Digigram VX Pocket driver
#   F:drivers/vx/vx_core.c:1.12->1.13 
#   F:drivers/vx/vx_hwdep.c:1.4->1.5 
#   F:pci/vx222/vx222_ops.c:1.8->1.9 
#   F:pcmcia/vx/vxp_ops.c:1.5->1.6 
#   L:Added the missing inclusion of <linux/device.h>
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/drivers/vx/vx_core.c
#   2005/01/19 04:36:29+01:00 perex@suse.cz +1 -0
#   [ALSA] Add missing inclusion of linux/device.h
#   
#   D:2005/01/19 11:36:29
#   C:Digigram VX core,Digigram VX222 driver,Digigram VX Pocket driver
#   F:drivers/vx/vx_core.c:1.12->1.13 
#   F:drivers/vx/vx_hwdep.c:1.4->1.5 
#   F:pci/vx222/vx222_ops.c:1.8->1.9 
#   F:pcmcia/vx/vxp_ops.c:1.5->1.6 
#   L:Added the missing inclusion of <linux/device.h>
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2005/01/20 20:15:52+01:00 perex@suse.cz 
#   [ALSA] Add workaround for buggy ATI IXP hardwares
#   
#   ATIIXP-modem driver
#   Added a workaround for buggy ATI IXP hardwares which returns
#   bogus DMA pointer register value.
#   
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/atiixp_modem.c
#   2005/01/19 04:35:04+01:00 perex@suse.cz +11 -12
#   [ALSA] Add workaround for buggy ATI IXP hardwares
#   
#   D:2005/01/19 11:35:04
#   C:ATIIXP-modem driver
#   F:pci/atiixp_modem.c:1.12->1.13 
#   L:Added a workaround for buggy ATI IXP hardwares which returns
#   L:bogus DMA pointer register value.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2005/01/20 20:14:34+01:00 perex@suse.cz 
#   [ALSA] Add support for Chaintech 9CJS
#   
#   ICE1712 driver
#   Added the support for Chaintech 9CJS by Delmaire Maxime.
#   
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/ice1712/vt1720_mobo.h
#   2005/01/19 04:32:46+01:00 perex@suse.cz +3 -1
#   [ALSA] Add support for Chaintech 9CJS
#   
#   D:2005/01/19 11:32:46
#   C:ICE1712 driver
#   F:pci/ice1712/vt1720_mobo.c:1.2->1.3 
#   F:pci/ice1712/vt1720_mobo.h:1.2->1.3 
#   L:Added the support for Chaintech 9CJS by Delmaire Maxime.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/ice1712/vt1720_mobo.c
#   2005/01/19 04:32:46+01:00 perex@suse.cz +9 -0
#   [ALSA] Add support for Chaintech 9CJS
#   
#   D:2005/01/19 11:32:46
#   C:ICE1712 driver
#   F:pci/ice1712/vt1720_mobo.c:1.2->1.3 
#   F:pci/ice1712/vt1720_mobo.h:1.2->1.3 
#   L:Added the support for Chaintech 9CJS by Delmaire Maxime.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2005/01/20 20:13:15+01:00 perex@suse.cz 
#   [ALSA] AK4117 code - fixed cosmetic typos
#   
#   AK4117 receiver
#   
#   
#   Signed-off-by: Jaroslav Kysela <perex@suse.cz>
# 
# include/sound/ak4117.h
#   2005/01/18 08:41:15+01:00 perex@suse.cz +3 -3
#   [ALSA] AK4117 code - fixed cosmetic typos
#   
#   D:2005/01/18 15:41:15
#   C:AK4117 receiver
#   F:include/ak4117.h:1.1->1.2 
#   L:
#   Signed-off-by: Jaroslav Kysela <perex@suse.cz>
# 
# ChangeSet
#   2005/01/20 20:11:59+01:00 perex@suse.cz 
#   [ALSA] don't use broken legacy interfaces on M-Audio Quattro/Omnistudio
#   
#   USB generic driver
#   Interfaces 0-2 of M-Audio Quattro/Omnistudio devices duplicate functionality
#   of interfaces 3-5 and cause errors when used with those.  Add a quirk to
#   tell the driver not to use them.
#   
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# sound/usb/usbquirks.h
#   2005/01/17 10:41:38+01:00 perex@suse.cz +70 -5
#   [ALSA] don't use broken legacy interfaces on M-Audio Quattro/Omnistudio
#   
#   D:2005/01/17 17:41:34
#   C:USB generic driver
#   F:usb/usbaudio.c:1.113->1.114 
#   F:usb/usbaudio.h:1.35->1.36 
#   F:usb/usbquirks.h:1.38->1.39 
#   L:Interfaces 0-2 of M-Audio Quattro/Omnistudio devices duplicate functionality
#   L:of interfaces 3-5 and cause errors when used with those.  Add a quirk to
#   L:tell the driver not to use them.
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# sound/usb/usbaudio.h
#   2005/01/17 10:41:38+01:00 perex@suse.cz +3 -0
#   [ALSA] don't use broken legacy interfaces on M-Audio Quattro/Omnistudio
#   
#   D:2005/01/17 17:41:34
#   C:USB generic driver
#   F:usb/usbaudio.c:1.113->1.114 
#   F:usb/usbaudio.h:1.35->1.36 
#   F:usb/usbquirks.h:1.38->1.39 
#   L:Interfaces 0-2 of M-Audio Quattro/Omnistudio devices duplicate functionality
#   L:of interfaces 3-5 and cause errors when used with those.  Add a quirk to
#   L:tell the driver not to use them.
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# sound/usb/usbaudio.c
#   2005/01/17 10:41:34+01:00 perex@suse.cz +2 -0
#   [ALSA] don't use broken legacy interfaces on M-Audio Quattro/Omnistudio
#   
#   D:2005/01/17 17:41:34
#   C:USB generic driver
#   F:usb/usbaudio.c:1.113->1.114 
#   F:usb/usbaudio.h:1.35->1.36 
#   F:usb/usbquirks.h:1.38->1.39 
#   L:Interfaces 0-2 of M-Audio Quattro/Omnistudio devices duplicate functionality
#   L:of interfaces 3-5 and cause errors when used with those.  Add a quirk to
#   L:tell the driver not to use them.
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# ChangeSet
#   2005/01/20 20:10:41+01:00 perex@suse.cz 
#   [ALSA] Fix silent output on some machines with AD1981x codecs
#   
#   AC97 Codec
#   Fixed the default state of 'Headphone Jack Sense' switch on AD1981x
#   codecs.  Setting this on affects the output of some machines (e.g.
#   Thindpads).
#   
#   The default value is set on only hardwares which are known to work.
#   
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/ac97/ac97_patch.c
#   2005/01/17 06:47:20+01:00 perex@suse.cz +14 -2
#   [ALSA] Fix silent output on some machines with AD1981x codecs
#   
#   D:2005/01/17 13:47:20
#   C:AC97 Codec
#   F:pci/ac97/ac97_patch.c:1.68->1.69 
#   L:Fixed the default state of 'Headphone Jack Sense' switch on AD1981x
#   L:codecs.  Setting this on affects the output of some machines (e.g.
#   L:Thindpads).
#   L:
#   L:The default value is set on only hardwares which are known to work.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2005/01/20 20:09:28+01:00 perex@suse.cz 
#   [ALSA] AC'97 Audio support for Intel ICH7
#   
#   Intel8x0 driver
#   This patch adds the ICH7 AC'97 DID the the intel8x0.c AC'97 audio
#   driver. This patch was build against 2.6.11-rc1.
#   
#   Signed-off-by: Jason Gaston <Jason.d.gaston@intel.com>
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/intel8x0.c
#   2005/01/17 04:29:18+01:00 perex@suse.cz +6 -0
#   [ALSA] AC'97 Audio support for Intel ICH7
#   
#   D:2005/01/17 11:29:18
#   C:Intel8x0 driver
#   F:pci/intel8x0.c:1.188->1.189 
#   L:This patch adds the ICH7 AC'97 DID the the intel8x0.c AC'97 audio
#   L:driver. This patch was build against 2.6.11-rc1.
#   Signed-off-by: Jason Gaston <Jason.d.gaston@intel.com>
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2005/01/20 20:08:09+01:00 perex@suse.cz 
#   [ALSA] Fix compilation on big-endian arch
#   
#   RME HDSP driver
#   Fixed typo in the code for big-endian architectures.
#   
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/pci/rme9652/hdsp.c
#   2005/01/14 12:52:06+01:00 perex@suse.cz +1 -1
#   [ALSA] Fix compilation on big-endian arch
#   
#   D:2005/01/14 19:52:06
#   C:RME HDSP driver
#   F:pci/rme9652/hdsp.c:1.78->1.79 
#   L:Fixed typo in the code for big-endian architectures.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2005/01/20 20:07:01+01:00 perex@suse.cz 
#   [ALSA] Show firmware loading state in proc file
#   
#   Digigram VX core
#   Show the firmware loading state in proc file.
#   
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/drivers/vx/vx_core.c
#   2005/01/14 10:41:36+01:00 perex@suse.cz +4 -0
#   [ALSA] Show firmware loading state in proc file
#   
#   D:2005/01/14 17:41:36
#   C:Digigram VX core
#   F:drivers/vx/vx_core.c:1.11->1.12 
#   L:Show the firmware loading state in proc file.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2005/01/20 20:05:33+01:00 perex@suse.cz 
#   [ALSA] Fix struct size mismatch
#   
#   IOCTL32 emulation
#   Fixed the struct size mismatch - should work on SPARC64 now, too.
#   
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/core/ioctl32/ioctl32.c
#   2005/01/14 04:15:16+01:00 perex@suse.cz +1 -1
#   [ALSA] Fix struct size mismatch
#   
#   D:2005/01/14 11:15:16
#   C:IOCTL32 emulation
#   F:core/ioctl32/ioctl32.c:1.28->1.29 
#   L:Fixed the struct size mismatch - should work on SPARC64 now, too.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2005/01/20 20:04:23+01:00 perex@suse.cz 
#   [ALSA] Add missing FORWARD ioctl
#   
#   IOCTL32 emulation
#   Added the missing FORWARD ioctl.
#   
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/core/ioctl32/pcm32.c
#   2005/01/14 03:51:12+01:00 perex@suse.cz +3 -0
#   [ALSA] Add missing FORWARD ioctl
#   
#   D:2005/01/14 10:51:12
#   C:IOCTL32 emulation
#   F:core/ioctl32/pcm32.c:1.23->1.24 
#   L:Added the missing FORWARD ioctl.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2005/01/20 20:03:02+01:00 perex@suse.cz 
#   [ALSA] Fix struct alignment on PPC64
#   
#   IOCTL32 emulation
#   Fixed the struct size mismatch (due to alignment) of
#   snd_ctl_elem_value_t for PPC64.
#   
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/core/ioctl32/ioctl32.c
#   2005/01/14 03:50:29+01:00 perex@suse.cz +3 -0
#   [ALSA] Fix struct alignment on PPC64
#   
#   D:2005/01/14 10:50:29
#   C:IOCTL32 emulation
#   F:core/ioctl32/ioctl32.c:1.27->1.28 
#   L:Fixed the struct size mismatch (due to alignment) of
#   L:snd_ctl_elem_value_t for PPC64.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2005/01/20 20:01:42+01:00 perex@suse.cz 
#   [ALSA] fix typo
#   
#   Documentation
#   
#   
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# Documentation/sound/alsa/ALSA-Configuration.txt
#   2005/01/14 03:15:32+01:00 perex@suse.cz +1 -1
#   [ALSA] fix typo
#   
#   D:2005/01/14 10:15:32
#   C:Documentation
#   F:Documentation/ALSA-Configuration.txt:1.62->1.63 
#   L:
#   Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
# 
# ChangeSet
#   2005/01/20 20:00:22+01:00 perex@suse.cz 
#   [ALSA] Fix typos in doc
#   
#   Documentation
#   Fixed typos in the document by Kirill Smelkov <kirr@mns.spb.ru>
#   
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl
#   2005/01/13 10:29:03+01:00 perex@suse.cz +16 -13
#   [ALSA] Fix typos in doc
#   
#   D:2005/01/13 17:29:03
#   C:Documentation
#   F:Documentation/DocBook/writing-an-alsa-driver.tmpl:1.46->1.47 
#   L:Fixed typos in the document by Kirill Smelkov <kirr@mns.spb.ru>
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2005/01/20 19:58:45+01:00 perex@suse.cz 
#   ALSA CVS update
#   PCM Midlevel
#   Sumary: Fix comment of snd_pcm_lib_malloc_pages()
#   
#   Fixed comment of snd_pcm_lib_malloc_pages() by
#   Kirill Smelkov <kirr@mns.spb.ru>.
#   
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# sound/core/pcm_memory.c
#   2005/01/13 10:27:29+01:00 perex@suse.cz +1 -1
#   ALSA CVS update
#   D:2005/01/13 17:27:29
#   C:PCM Midlevel
#   F:core/pcm_memory.c:1.33->1.34 
#   L:Sumary: Fix comment of snd_pcm_lib_malloc_pages()
#   L:
#   L:Fixed comment of snd_pcm_lib_malloc_pages() by
#   L:Kirill Smelkov <kirr@mns.spb.ru>.
#   Signed-off-by: Takashi Iwai <tiwai@suse.de>
# 
# ChangeSet
#   2005/01/18 01:43:40-05:00 jgarzik@pobox.com 
#   Merge pobox.com:/garz/repo/linux-2.6
#   into pobox.com:/garz/repo/netdev-2.6/8139too
# 
# drivers/net/8139too.c
#   2005/01/18 01:43:27-05:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# ChangeSet
#   2005/01/18 00:56:24-05:00 jgarzik@pobox.com 
#   Merge http://typhoon.bkbits.net/typhoon-2.6
#   into pobox.com:/garz/repo/netdev-2.6/typhoon
# 
# drivers/net/typhoon.c
#   2005/01/18 00:56:21-05:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# ChangeSet
#   2005/01/18 00:54:29-05:00 jgarzik@pobox.com 
#   Merge pobox.com:/garz/repo/linux-2.6
#   into pobox.com:/garz/repo/netdev-2.6/viro-isa-ectomy
# 
# drivers/net/wd.c
#   2005/01/18 00:54:25-05:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# drivers/net/smc-ultra.c
#   2005/01/18 00:54:25-05:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# drivers/net/smc-mca.c
#   2005/01/18 00:54:25-05:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# drivers/net/ewrk3.c
#   2005/01/18 00:54:25-05:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# drivers/net/es3210.c
#   2005/01/18 00:54:25-05:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# ChangeSet
#   2005/01/18 00:51:31-05:00 jgarzik@pobox.com 
#   Merge pobox.com:/garz/repo/linux-2.6
#   into pobox.com:/garz/repo/netdev-2.6/viro-iomap
# 
# drivers/net/wireless/orinoco_cs.c
#   2005/01/18 00:51:26-05:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# drivers/net/fealnx.c
#   2005/01/18 00:51:26-05:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# ChangeSet
#   2005/01/14 15:26:21-07:00 dale@farnsworth.org 
#   [netdrvr mv643xx] This patch simplifies the mv64340_eth_set_rx_mode function without
#   changing its behavior.
#   
#   Signed-off-by: Dale Farnsworth <dale@farnsworth.org>
# 
# drivers/net/mv643xx_eth.c
#   2005/01/14 15:26:09-07:00 dale@farnsworth.org +7 -11
#   This patch simplifies the mv64340_eth_set_rx_mode function without
#   changing its behavior.
#   
#   Signed-off-by: Dale Farnsworth <dale@farnsworth.org>
# 
# ChangeSet
#   2005/01/14 15:25:50-07:00 dale@farnsworth.org 
#   [netdrvr mv643xx] This patch makes the use of the MV64340_RX_QUEUE_FILL_ON_TASK config macro
#   more consistent, though the macro remains undefined, since the feature still
#   does not work properly.
#           
#   Signed-off-by: Steven J. Hill <sjhill1@rockwellcollins.com>
#   Signed-off-by: Dale Farnsworth <dale@farnsworth.org>
# 
# drivers/net/mv643xx_eth.h
#   2005/01/14 15:25:42-07:00 dale@farnsworth.org +5 -4
#   This patch makes the use of the MV64340_RX_QUEUE_FILL_ON_TASK config macro
#   more consistent, though the macro remains undefined, since the feature still
#   does not work properly.
#           
#   Signed-off-by: Steven J. Hill <sjhill1@rockwellcollins.com>
#   Signed-off-by: Dale Farnsworth <dale@farnsworth.org>
# 
# drivers/net/mv643xx_eth.c
#   2005/01/14 15:25:42-07:00 dale@farnsworth.org +6 -6
#   This patch makes the use of the MV64340_RX_QUEUE_FILL_ON_TASK config macro
#   more consistent, though the macro remains undefined, since the feature still
#   does not work properly.
#           
#   Signed-off-by: Steven J. Hill <sjhill1@rockwellcollins.com>
#   Signed-off-by: Dale Farnsworth <dale@farnsworth.org>
# 
# ChangeSet
#   2005/01/14 15:25:14-07:00 dale@farnsworth.org 
#   [netdrvr mv643xx] This patch adds support for passing additional parameters via the
#   platform_device interface.  These additional parameters are:
#           size of RX and TX descriptor rings
#           port_config value 
#           port_config_extend value
#           port_sdma_config value
#           port_serial_control value
#           PHY address                                                                                                                                             Signed-off-by: Dale Farnsworth <dale@farnsworth.org>
# 
# include/linux/mv643xx.h
#   2005/01/14 15:25:05-07:00 dale@farnsworth.org +195 -1
#   This patch adds support for passing additional parameters via the
#   platform_device interface.  These additional parameters are:
#           size of RX and TX descriptor rings
#           port_config value 
#           port_config_extend value
#           port_sdma_config value
#           port_serial_control value
#           PHY address                                                                                                                                             Signed-off-by: Dale Farnsworth <dale@farnsworth.org>
# 
# drivers/net/mv643xx_eth.h
#   2005/01/14 15:25:05-07:00 dale@farnsworth.org +9 -200
#   This patch adds support for passing additional parameters via the
#   platform_device interface.  These additional parameters are:
#           size of RX and TX descriptor rings
#           port_config value 
#           port_config_extend value
#           port_sdma_config value
#           port_serial_control value
#           PHY address                                                                                                                                             Signed-off-by: Dale Farnsworth <dale@farnsworth.org>
# 
# drivers/net/mv643xx_eth.c
#   2005/01/14 15:25:05-07:00 dale@farnsworth.org +142 -66
#   This patch adds support for passing additional parameters via the
#   platform_device interface.  These additional parameters are:
#           size of RX and TX descriptor rings
#           port_config value 
#           port_config_extend value
#           port_sdma_config value
#           port_serial_control value
#           PHY address                                                                                                                                             Signed-off-by: Dale Farnsworth <dale@farnsworth.org>
# 
# ChangeSet
#   2005/01/14 15:24:38-07:00 dale@farnsworth.org 
#   [netdrvr mv643xx] This patch adds device driver model support to the mv643xx_eth driver.
#   
#   This is a change to the driver's programming interface.  Platform
#   code must now pass in the address of the MV643xx ethernet registers
#   and IRQ.  If firmware doesn't set the MAC address, platform code
#   must also pass in the MAC address.
#   
#   Also, note that local MV_READ/MV_WRITE macros are used rather than              using global macros.  Keeping the macro names minimizes the patch size.         The names will be changed to mv_read/mv_write in a later cosmetic               cleanup patch.                                                                                                                                                  Signed-off-by: Dale Farnsworth <dale@farnsworth.org>
# 
# include/linux/mv643xx.h
#   2005/01/14 15:24:30-07:00 dale@farnsworth.org +12 -0
#   This patch adds device driver model support to the mv643xx_eth driver.
#   
#   This is a change to the driver's programming interface.  Platform
#   code must now pass in the address of the MV643xx ethernet registers
#   and IRQ.  If firmware doesn't set the MAC address, platform code
#   must also pass in the MAC address.
#   
#   Also, note that local MV_READ/MV_WRITE macros are used rather than              using global macros.  Keeping the macro names minimizes the patch size.         The names will be changed to mv_read/mv_write in a later cosmetic               cleanup patch.                                                                                                                                                  Signed-off-by: Dale Farnsworth <dale@farnsworth.org>
# 
# drivers/net/mv643xx_eth.h
#   2005/01/14 15:24:30-07:00 dale@farnsworth.org +0 -4
#   This patch adds device driver model support to the mv643xx_eth driver.
#   
#   This is a change to the driver's programming interface.  Platform
#   code must now pass in the address of the MV643xx ethernet registers
#   and IRQ.  If firmware doesn't set the MAC address, platform code
#   must also pass in the MAC address.
#   
#   Also, note that local MV_READ/MV_WRITE macros are used rather than              using global macros.  Keeping the macro names minimizes the patch size.         The names will be changed to mv_read/mv_write in a later cosmetic               cleanup patch.                                                                                                                                                  Signed-off-by: Dale Farnsworth <dale@farnsworth.org>
# 
# drivers/net/mv643xx_eth.c
#   2005/01/14 15:24:30-07:00 dale@farnsworth.org +158 -63
#   This patch adds device driver model support to the mv643xx_eth driver.
#   
#   This is a change to the driver's programming interface.  Platform
#   code must now pass in the address of the MV643xx ethernet registers
#   and IRQ.  If firmware doesn't set the MAC address, platform code
#   must also pass in the MAC address.
#   
#   Also, note that local MV_READ/MV_WRITE macros are used rather than              using global macros.  Keeping the macro names minimizes the patch size.         The names will be changed to mv_read/mv_write in a later cosmetic               cleanup patch.                                                                                                                                                  Signed-off-by: Dale Farnsworth <dale@farnsworth.org>
# 
# ChangeSet
#   2005/01/14 15:24:06-07:00 dale@farnsworth.org 
#   [netdrvr mv643xx] This patch replaces the use of the pci_map_* functions with the
#   corresponding dma_map_* functions.
#   
#   Signed-off-by: Dale Farnsworth <dale@farnsworth.org>
# 
# drivers/net/mv643xx_eth.c
#   2005/01/14 15:23:52-07:00 dale@farnsworth.org +34 -35
#   This patch replaces the use of the pci_map_* functions with the
#   corresponding dma_map_* functions.
#   
#   Signed-off-by: Dale Farnsworth <dale@farnsworth.org>
# 
# ChangeSet
#   2005/01/14 15:23:29-07:00 dale@farnsworth.org 
#   [netdrvr mv643xx] This patch fixes the code that enables hardware checksum generation.
#   The previous code has so many problems that it appears to never have 
#   worked 2.6.
#   
#   Signed-off-by: Dale Farnsworth <dale@farnsworth.org>
# 
# drivers/net/mv643xx_eth.h
#   2005/01/14 15:23:20-07:00 dale@farnsworth.org +3 -2
#   This patch fixes the code that enables hardware checksum generation.
#   The previous code has so many problems that it appears to never have 
#   worked 2.6.
#   
#   Signed-off-by: Dale Farnsworth <dale@farnsworth.org>
# 
# drivers/net/mv643xx_eth.c
#   2005/01/14 15:23:20-07:00 dale@farnsworth.org +154 -139
#   This patch fixes the code that enables hardware checksum generation.
#   The previous code has so many problems that it appears to never have 
#   worked 2.6.
#   
#   Signed-off-by: Dale Farnsworth <dale@farnsworth.org>
# 
# ChangeSet
#   2005/01/14 15:22:36-07:00 dale@farnsworth.org 
#   [netdrvr mv643xx] This patch removes spin delays (count to 1000000, ugh) and instead waits
#   with udelay or msleep for hardware flags to change.
#   
#   It also adds a spinlock to protect access to the MV64340_ETH_SMI_REG,
#   which is shared across ports.
#   
#   Signed-off-by: Dale Farnsworth <dale@farnsworth.org>
# 
# drivers/net/mv643xx_eth.h
#   2005/01/14 15:22:22-07:00 dale@farnsworth.org +3 -3
#   This patch removes spin delays (count to 1000000, ugh) and instead waits
#   with udelay or msleep for hardware flags to change.
#   
#   It also adds a spinlock to protect access to the MV64340_ETH_SMI_REG,
#   which is shared across ports.
#   
#   Signed-off-by: Dale Farnsworth <dale@farnsworth.org>
# 
# drivers/net/mv643xx_eth.c
#   2005/01/14 15:22:22-07:00 dale@farnsworth.org +86 -98
#   This patch removes spin delays (count to 1000000, ugh) and instead waits
#   with udelay or msleep for hardware flags to change.
#   
#   It also adds a spinlock to protect access to the MV64340_ETH_SMI_REG,
#   which is shared across ports.
#   
#   Signed-off-by: Dale Farnsworth <dale@farnsworth.org>
# 
# ChangeSet
#   2005/01/14 15:21:59-07:00 dale@farnsworth.org 
#   [netdrvr mv643xx] This patch removes code that is redundant or useless.
#   The biggest area is in pre-initializing the RX and TX descriptor
#   rings, which only obfuscates the driver since the ring data is
#   overwritten without being used.
#   
#   Signed-off-by: Dale Farnsworth <dale@farnsworth.org>
# 
# drivers/net/mv643xx_eth.c
#   2005/01/14 15:21:50-07:00 dale@farnsworth.org +21 -111
#   This patch removes code that is redundant or useless.
#   The biggest area is in pre-initializing the RX and TX descriptor
#   rings, which only obfuscates the driver since the ring data is
#   overwritten without being used.
#   
#   Signed-off-by: Dale Farnsworth <dale@farnsworth.org>
# 
# ChangeSet
#   2005/01/14 13:10:38-06:00 shaggy@austin.ibm.com 
#   JFS: base static allocations on physical memory size
#   
#   On larger systems, performance is improved with a larger
#   allocation of tlocks & tblocks.  Base the default size of these
#   allocations on the physical memory size.
#   
#   Signed-off-by: Dave Kleikamp <shaggy@austin.ibm.com>
# 
# fs/jfs/jfs_txnmgr.c
#   2005/01/14 13:10:22-06:00 shaggy@austin.ibm.com +28 -6
#   base default number of tlocks & tblocks on size of phyiscal memory
# 
# ChangeSet
#   2005/01/12 00:10:49-05:00 domen@coderock.org 
#   [PATCH] net/ewrk3: replace schedule_timeout() with msleep_interruptible()
#   
#   Any comments would be, as always, appreciated.
#   
#   -Nish
#   
#   Description: Uses msleep() instead of schedule_timeout() to guarantee
#   the task delays as expected.
#   
#   Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
#   Signed-off-by: Domen Puncer <domen@coderock.org>
# 
# drivers/net/ewrk3.c
#   2005/01/10 12:00:24-05:00 domen@coderock.org +1 -2
#   net/ewrk3: replace schedule_timeout() with msleep_interruptible()
# 
# ChangeSet
#   2005/01/12 00:10:32-05:00 domen@coderock.org 
#   [PATCH] net/tekram-sir: replace schedule_timeout() with msleep()
#   
#   Any comments would be appreciated.
#   
#   Description: Use msleep() instead of schedule_timeout() to guarantee the
#   task delays as expected.
#   
#   Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
#   Signed-off-by: Maximilian Attems <janitor@sternwelten.at>
#   Signed-off-by: Domen Puncer <domen@coderock.org>
# 
# drivers/net/irda/tekram-sir.c
#   2005/01/10 12:00:06-05:00 domen@coderock.org +1 -2
#   net/tekram-sir: replace schedule_timeout() with msleep()
# 
# ChangeSet
#   2005/01/12 00:10:17-05:00 domen@coderock.org 
#   [PATCH] net/ns83820: replace schedule_timeout() with msleep()
#   
#   Any comments would be appreciated.
#   
#   Description: Use msleep() instead of schedule_timeout()
#   to guarantee the task delays as expected.
#   
#   Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
#   Signed-off-by: Maximilian Attems <janitor@sternwelten.at>
#   Signed-off-by: Domen Puncer <domen@coderock.org>
# 
# drivers/net/ns83820.c
#   2005/01/10 12:00:02-05:00 domen@coderock.org +1 -2
#   net/ns83820: replace schedule_timeout() with msleep()
# 
# ChangeSet
#   2005/01/12 00:10:05-05:00 domen@coderock.org 
#   [PATCH] net/ni65: replace schedule_timeout() with msleep()
#   
#   Any comments would be appreciated.
#   
#   Description: Use msleep() instead of schedule_timeout()
#   to guarantee the task delays as expected.
#   
#   Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
#   Signed-off-by: Maximilian Attems <janitor@sternwelten.at>
#   Signed-off-by: Domen Puncer <domen@coderock.org>
# 
# drivers/net/ni65.c
#   2005/01/10 12:00:02-05:00 domen@coderock.org +1 -2
#   net/ni65: replace schedule_timeout() with msleep()
# 
# ChangeSet
#   2005/01/12 00:09:55-05:00 domen@coderock.org 
#   [PATCH] net/sir_dev: replace schedule_timeout() with msleep()
#   
#   Any comments would be appreciated.
#   
#   Description: Use msleep() instead of schedule_timeout()
#   to guarantee the task delays as expected.
#   
#   Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
#   Signed-off-by: Maximilian Attems <janitor@sternwelten.at>
#   Signed-off-by: Domen Puncer <domen@coderock.org>
# 
# drivers/net/irda/sir_dev.c
#   2005/01/10 12:00:01-05:00 domen@coderock.org +2 -2
#   net/sir_dev: replace schedule_timeout() with msleep()
# 
# ChangeSet
#   2005/01/12 00:09:44-05:00 domen@coderock.org 
#   [PATCH] net/xirc2ps_cs: replace Wait() with msleep()
#   
#   Any comments would be appreciated.
#   
#   Description: Use msleep() instead of Wait() to guarantee the task delays
#   as expected. Remove definition of Wait().
#   
#   Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
#   Signed-off-by: Maximilian Attems <janitor@sternwelten.at>
#   Signed-off-by: Domen Puncer <domen@coderock.org>
# 
# drivers/net/pcmcia/xirc2ps_cs.c
#   2005/01/10 12:00:00-05:00 domen@coderock.org +9 -14
#   net/xirc2ps_cs: replace Wait() with msleep()
# 
# ChangeSet
#   2005/01/12 00:09:33-05:00 domen@coderock.org 
#   [PATCH] net/ma600-sir: replace schedule_timeout() with msleep()
#   
#   Any comments would be appreciated.
#   
#   Description: Use msleep() instead of schedule_timeout()
#   to guarantee the task delays as expected.
#   
#   Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
#   Signed-off-by: Maximilian Attems <janitor@sternwelten.at>
#   Signed-off-by: Domen Puncer <domen@coderock.org>
# 
# drivers/net/irda/ma600-sir.c
#   2005/01/10 12:00:00-05:00 domen@coderock.org +4 -8
#   net/ma600-sir: replace schedule_timeout() with msleep()
# 
# ChangeSet
#   2005/01/12 00:09:22-05:00 domen@coderock.org 
#   [PATCH] net/irtty-sir: replace schedule_timeout() with msleep()
#   
#   Any comments would be appreciated.
#   
#   Description: Use msleep() instead of schedule_timeout()
#   to guarantee the task delays as expected.
#   
#   Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
#   Signed-off-by: Maximilian Attems <janitor@sternwelten.at>
#   Signed-off-by: Domen Puncer <domen@coderock.org>
# 
# drivers/net/irda/irtty-sir.c
#   2005/01/10 11:59:59-05:00 domen@coderock.org +2 -2
#   net/irtty-sir: replace schedule_timeout() with msleep()
# 
# ChangeSet
#   2005/01/12 00:09:11-05:00 domen@coderock.org 
#   [PATCH] net/act2001-sir: replace schedule_timeout() with msleep()
#   
#   Any comments would be appreciated.
#   
#   Description: Use msleep() instead of schedule_timeout()
#   to guarantee the task delays as expected.
#   
#   Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
#   Signed-off-by: Maximilian Attems <janitor@sternwelten.at>
#   Signed-off-by: Domen Puncer <domen@coderock.org>
# 
# drivers/net/irda/act200l-sir.c
#   2005/01/10 11:59:59-05:00 domen@coderock.org +1 -2
#   net/act2001-sir: replace schedule_timeout() with msleep()
# 
# ChangeSet
#   2005/01/12 00:06:24-05:00 jgarzik@pobox.com 
#   Merge pobox.com:/garz/repo/linux-2.6
#   into pobox.com:/garz/repo/netdev-2.6/janitor
# 
# drivers/net/arcnet/arcnet.c
#   2005/01/12 00:06:20-05:00 jgarzik@pobox.com +0 -0
#   Auto merged
# 
# ChangeSet
#   2005/01/07 01:25:03-05:00 dave@thedillows.org 
#   Bump version and release date.
#   
#   Signed-off-by: David Dillow <dave@thedillows.org>
# 
# drivers/net/typhoon.c
#   2005/01/07 01:24:46-05:00 dave@thedillows.org +2 -2
#   Bump version and release date.
#   
#   Signed-off-by: David Dillow <dave@thedillows.org>
# 
# ChangeSet
#   2005/01/07 01:23:22-05:00 dave@thedillows.org 
#   Version 03.001.008 of the Typhoon firmware, courtesy of 3Com.
#   Fixes various crypto bugs on the 3CR990B family, among other
#   issues.
#   
#   Signed-off-by: David Dillow <dave@thedillows.org>
# 
# drivers/net/typhoon-firmware.h
#   2005/01/07 01:23:05-05:00 dave@thedillows.org +2525 -3043
#   Version 03.001.008 of the Typhoon firmware, courtesy of 3Com.
#   Fixes various crypto bugs on the 3CR990B family, among other
#   issues.
#   
#   Signed-off-by: David Dillow <dave@thedillows.org>
# 
# ChangeSet
#   2005/01/07 01:22:08-05:00 dave@thedillows.org 
#   Fixup the version reporting to match 3Com.
#   
#   Signed-off-by: David Dillow <dave@thedillows.org>
# 
# drivers/net/typhoon.c
#   2005/01/07 01:21:50-05:00 dave@thedillows.org +6 -3
#   Fixup the version reporting to match 3Com.
#   
#   Signed-off-by: David Dillow <dave@thedillows.org>
# 
# ChangeSet
#   2005/01/07 01:18:58-05:00 dave@thedillows.org 
#   Use module_param() and add descriptions.
#   
#   Signed-off-by: David Dillow <dave@thedillows.org>
# 
# drivers/net/typhoon.c
#   2005/01/07 01:18:41-05:00 dave@thedillows.org +8 -2
#   Use module_param() and add descriptions.
#   
#   Signed-off-by: David Dillow <dave@thedillows.org>
# 
# ChangeSet
#   2005/01/07 00:55:41-05:00 dave@thedillows.org 
#   Teach typhoon to use port IO on machines that need it. It will attempt
#   to use MMIO, but if that fails (or the user asks), it will fallback
#   to port IO.
#   
#   Signed-off-by: David Dillow <dave@thedillows.org>
# 
# drivers/net/typhoon.c
#   2005/01/07 00:55:21-05:00 dave@thedillows.org +144 -72
#   Teach typhoon to use port IO on machines that need it. It will attempt
#   to use MMIO, but if that fails (or the user asks), it will fallback
#   to port IO.
#   
#   Signed-off-by: David Dillow <dave@thedillows.org>
# 
# ChangeSet
#   2005/01/07 00:53:27-05:00 dave@thedillows.org 
#   Enable bus mastering before saving our state, or we'll only be able
#   to load the modules one time.
#   
#   Signed-off-by: David Dillow <dave@thedillows.org>
# 
# drivers/net/typhoon.c
#   2005/01/07 00:53:08-05:00 dave@thedillows.org +3 -4
#   Enable bus mastering before saving our state, or we'll only be able
#   to load the modules one time.
#   
#   Signed-off-by: David Dillow <dave@thedillows.org>
# 
# ChangeSet
#   2005/01/06 22:00:35-05:00 domen@coderock.org 
#   [PATCH] arcnet: remove casts
#   
#   Remove casts of (void *) pointers.
#   
#    drivers/net/arcnet/arc-rawmode.c |    4 ++--
#    drivers/net/arcnet/arc-rimi.c    |   14 +++++++-------
#    drivers/net/arcnet/arcnet.c      |   30 +++++++++++++++---------------
#    drivers/net/arcnet/com20020.c    |    6 +++---
#    drivers/net/arcnet/com90io.c     |    4 ++--
#    drivers/net/arcnet/com90xx.c     |    8 ++++----
#    drivers/net/arcnet/rfc1051.c     |    8 ++++----
#    drivers/net/arcnet/rfc1201.c     |   12 ++++++------
#    8 files changed, 43 insertions(+), 43 deletions(-)
#   
#   Signed-off-by: Domen Puncer <domen@coderock.org>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/arcnet/rfc1201.c
#   2004/12/29 17:09:19-05:00 domen@coderock.org +6 -6
#   arcnet: remove casts
# 
# drivers/net/arcnet/rfc1051.c
#   2004/12/29 17:09:19-05:00 domen@coderock.org +4 -4
#   arcnet: remove casts
# 
# drivers/net/arcnet/com90xx.c
#   2004/12/29 17:09:19-05:00 domen@coderock.org +4 -4
#   arcnet: remove casts
# 
# drivers/net/arcnet/com90io.c
#   2004/12/29 17:09:19-05:00 domen@coderock.org +2 -2
#   arcnet: remove casts
# 
# drivers/net/arcnet/com20020.c
#   2004/12/29 17:11:53-05:00 domen@coderock.org +3 -3
#   arcnet: remove casts
# 
# drivers/net/arcnet/arcnet.c
#   2004/12/29 17:09:19-05:00 domen@coderock.org +15 -15
#   arcnet: remove casts
# 
# drivers/net/arcnet/arc-rimi.c
#   2004/12/29 17:09:19-05:00 domen@coderock.org +7 -7
#   arcnet: remove casts
# 
# drivers/net/arcnet/arc-rawmode.c
#   2004/12/29 17:09:19-05:00 domen@coderock.org +2 -2
#   arcnet: remove casts
# 
# ChangeSet
#   2005/01/06 21:18:17-05:00 viro@parcelfarce.linux.theplanet.co.uk 
#   [PATCH] es3210 iomem annotions and isa-ectomy
#   
#   	switched to ioremap + normal iomem access primitives
#   Signed-off-by: Al Viro <viro@parcelfarce.linux.theplanet.co.uk>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/es3210.c
#   2004/12/27 21:29:50-05:00 viro@parcelfarce.linux.theplanet.co.uk +19 -13
#   es3210 iomem annotions and isa-ectomy
# 
# ChangeSet
#   2005/01/06 21:18:06-05:00 viro@parcelfarce.linux.theplanet.co.uk 
#   [PATCH] ewrk3 iomem annotations + isa-ectomy
#   
#   	switched to ioremap + normal iomem access primitives
#   Signed-off-by: Al Viro <viro@parcelfarce.linux.theplanet.co.uk>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/ewrk3.c
#   2004/12/27 22:51:43-05:00 viro@parcelfarce.linux.theplanet.co.uk +45 -39
#   ewrk3 iomem annotations + isa-ectomy
# 
# ChangeSet
#   2005/01/06 21:17:55-05:00 viro@parcelfarce.linux.theplanet.co.uk 
#   [PATCH] wd iomem annotations + isa-ectomy
#   
#   	switched to ioremap + normal iomem access primitives
#   Signed-off-by: Al Viro <viro@parcelfarce.linux.theplanet.co.uk>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/wd.c
#   2004/12/27 21:29:51-05:00 viro@parcelfarce.linux.theplanet.co.uk +22 -14
#   wd iomem annotations + isa-ectomy
# 
# ChangeSet
#   2005/01/06 21:17:44-05:00 viro@parcelfarce.linux.theplanet.co.uk 
#   [PATCH] smc-ultra32 iomem annotations + isa-ectomy
#   
#   	switched to ioremap + normal iomem access primitives
#   Signed-off-by: Al Viro <viro@parcelfarce.linux.theplanet.co.uk>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/smc-ultra32.c
#   2004/12/27 21:29:51-05:00 viro@parcelfarce.linux.theplanet.co.uk +18 -12
#   smc-ultra32 iomem annotations + isa-ectomy
# 
# ChangeSet
#   2005/01/06 21:17:32-05:00 viro@parcelfarce.linux.theplanet.co.uk 
#   [PATCH] smc-ultra iomem annotations + isa-ectomy
#   
#   	switched to ioremap + normal iomem access primitives
#   Signed-off-by: Al Viro <viro@parcelfarce.linux.theplanet.co.uk>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/smc-ultra.c
#   2004/12/27 21:29:50-05:00 viro@parcelfarce.linux.theplanet.co.uk +20 -14
#   smc-ultra iomem annotations + isa-ectomy
# 
# ChangeSet
#   2005/01/06 21:17:20-05:00 viro@parcelfarce.linux.theplanet.co.uk 
#   [PATCH] smc-mca iomem annotations and isa-ectomy
#   
#   	switched to ioremap + normal iomem access primitives
#   Signed-off-by: Al Viro <viro@parcelfarce.linux.theplanet.co.uk>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/smc-mca.c
#   2004/12/27 21:29:50-05:00 viro@parcelfarce.linux.theplanet.co.uk +22 -15
#   smc-mca iomem annotations and isa-ectomy
# 
# ChangeSet
#   2004/10/30 09:06:31-04:00 jgarzik@pobox.com 
#   Merge pobox.com:/garz/repo/netdev-2.6/tmp
#   into pobox.com:/garz/repo/netdev-2.6/8139too
# 
# drivers/net/8139too.c
#   2004/10/30 09:06:28-04:00 jgarzik@pobox.com +0 -1
#   Auto merged
# 
# ChangeSet
#   2004/10/30 09:05:22-04:00 tglx@linutronix.de 
#   [PATCH] rtl8139too.c: Fix missing pci_disable_dev
#   
#   Simple fix to make pci_enable/disable symetric and avoid the warning on
#   module unload.
#   
#   Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/8139too.c
#   2004/10/21 20:00:00-04:00 tglx@linutronix.de +1 -1
#   rtl8139too.c: Fix missing pci_disable_dev
# 
# ChangeSet
#   2004/10/26 17:10:11-04:00 akpm@osdl.org 
#   [PATCH] rtl8139too.c: Fix missing pci_disable_dev
#   
#   From: Thomas Gleixner <tglx@linutronix.de>
#   
#   Simple fix to make pci_enable/disable symetric and avoid the warning on
#   module unload.
#   
#   Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
# 
# drivers/net/8139too.c
#   2004/10/24 06:32:54-04:00 akpm@osdl.org +1 -1
#   rtl8139too.c: Fix missing pci_disable_dev
# 
# ChangeSet
#   2004/10/26 17:00:44-04:00 jgarzik@pobox.com 
#   Hand-merge upstream pci_{save,restore}_state() stuff.
# 
# drivers/net/8139too.c
#   2004/10/26 17:00:39-04:00 jgarzik@pobox.com +0 -1
#   Hand-merge upstream pci_{save,restore}_state() stuff.
# 
# ChangeSet
#   2004/10/21 18:36:08-04:00 viro@www.linux.org.uk 
#   [PATCH] fealnx iomem annotations, switch to io{read,write}
#   
#   Signed-off-by: Al Viro <viro@parcelfarce.linux.theplanet.co.uk>
# 
# drivers/net/fealnx.c
#   2004/10/21 10:48:46-04:00 viro@www.linux.org.uk +129 -146
#   (10/18) fealnx iomem annotations, switch to io{read,write}
# 
# ChangeSet
#   2004/10/21 18:33:39-04:00 viro@www.linux.org.uk 
#   [PATCH] wireless iomem annotations and fixes, switch to io{read,write}
#   
#   hermes.c switched to ioread/iowrite from homegrown analogs, its users
#   updated.  Fixed direct dereferencing of ioremapped memory in orinoco_plx.
#   
#   Signed-off-by: Al Viro <viro@parcelfarce.linux.theplanet.co.uk>
# 
# drivers/net/wireless/orinoco_tmd.c
#   2004/10/21 10:48:45-04:00 viro@www.linux.org.uk +27 -24
#   (9/18) wireless iomem annotations and fixes, switch to io{read,write}
# 
# drivers/net/wireless/orinoco_plx.c
#   2004/10/21 10:48:45-04:00 viro@www.linux.org.uk +41 -41
#   (9/18) wireless iomem annotations and fixes, switch to io{read,write}
# 
# drivers/net/wireless/orinoco_pci.c
#   2004/10/21 10:48:45-04:00 viro@www.linux.org.uk +3 -4
#   (9/18) wireless iomem annotations and fixes, switch to io{read,write}
# 
# drivers/net/wireless/orinoco_cs.c
#   2004/10/21 10:48:45-04:00 viro@www.linux.org.uk +8 -2
#   (9/18) wireless iomem annotations and fixes, switch to io{read,write}
# 
# drivers/net/wireless/hermes.h
#   2004/10/21 10:48:45-04:00 viro@www.linux.org.uk +10 -52
#   (9/18) wireless iomem annotations and fixes, switch to io{read,write}
# 
# drivers/net/wireless/hermes.c
#   2004/10/21 10:48:45-04:00 viro@www.linux.org.uk +20 -23
#   (9/18) wireless iomem annotations and fixes, switch to io{read,write}
# 
# drivers/net/wireless/airport.c
#   2004/10/21 10:48:45-04:00 viro@www.linux.org.uk +2 -3
#   (9/18) wireless iomem annotations and fixes, switch to io{read,write}
# 
# ChangeSet
#   2004/10/15 19:25:35-04:00 shemminger@osdl.org 
#   [PATCH] 8139too: use netdev_priv
#   
#   Use netdev_priv where appropriate, and get rid of "can't happen anymore" assert's.
#   
#   Signed-off-by: Stephen Hemminger <shemminger@osdl.org>
# 
# drivers/net/8139too.c
#   2004/10/15 18:25:02-04:00 shemminger@osdl.org +38 -45
#   8139too: use netdev_priv
# 
# ChangeSet
#   2004/08/28 19:06:15-04:00 rene.herman@keyaccess.nl 
#   [PATCH] 8139too Interframe Gap Time
# 
# drivers/net/8139too.c
#   2004/04/30 10:29:08-04:00 rene.herman@keyaccess.nl +9 -5
#   8139too Interframe Gap Time
# 
diff -Nru a/CREDITS b/CREDITS
--- a/CREDITS	2005-03-11 12:51:47 -08:00
+++ b/CREDITS	2005-03-11 12:51:47 -08:00
@@ -34,8 +34,9 @@
 E: airlied@linux.ie
 W: http://www.csn.ul.ie/~airlied
 D: NFS over TCP patches
-S: University of Limerick
-S: Ireland
+D: in-kernel DRM Maintainer
+S: Longford, Ireland
+S: Sydney, Australia
 
 N: Tigran A. Aivazian
 E: tigran@veritas.com
@@ -841,6 +842,11 @@
 W: http://www.fsmlabs.com/linuxppcbk.html
 D: PowerPC
 
+N: Daniel Drake
+E: dsd@gentoo.org
+D: USBAT02 CompactFlash support in usb-storage
+S: UK
+
 N: Oleg Drokin
 E: green@ccssu.crimea.ua
 W: http://www.ccssu.crimea.ua/~green
@@ -1095,7 +1101,7 @@
 
 N: Kumar Gala
 E: kumar.gala@freescale.com
-D: Embedded PowerPC 6xx/7xx/74xx/82xx/85xx support
+D: Embedded PowerPC 6xx/7xx/74xx/82xx/83xx/85xx support
 S: Austin, Texas 78729
 S: USA
 
@@ -3351,10 +3357,11 @@
 S: USA
 
 N: Matthias Urlichs
-E: urlichs@noris.de
-E: urlichs@smurf.sub.org
+E: smurf@smurf.noris.de
+E: smurf@debian.org
+E: matthias@urlichs.de
 D: Consultant, developer, kernel hacker
-D: Playing with Streams, ISDN, and BSD networking code for Linux
+D: In a previous life, worked on Streams/ISDN/BSD networking code for Linux
 S: Schleiermacherstrasse 12
 S: 90491 Nuernberg
 S: Germany
@@ -3426,6 +3433,7 @@
 E: pe1rxq@amsat.org
 W: http://www.chello.nl/~j.vreeken/
 D: SE401 usb webcam driver
+D: ZD1201 usb wireless lan driver
 S: Maastrichterweg 63
 S: 5554 GG Valkenswaard
 S: The Netherlands
diff -Nru a/Documentation/BK-usage/bksend b/Documentation/BK-usage/bksend
--- a/Documentation/BK-usage/bksend	2005-03-11 12:51:50 -08:00
+++ b/Documentation/BK-usage/bksend	2005-03-11 12:51:50 -08:00
@@ -27,7 +27,7 @@
 
 SEP="\n===================================================================\n\n"
 echo -e $SEP
-bk changes -r$REV
+env PAGER=/bin/cat bk changes -r$REV
 echo
 bk export -tpatch -du -h -r$REV | diffstat
 echo; echo
diff -Nru a/Documentation/Changes b/Documentation/Changes
--- a/Documentation/Changes	2005-03-11 12:51:51 -08:00
+++ b/Documentation/Changes	2005-03-11 12:51:51 -08:00
@@ -339,7 +339,7 @@
 
 JFSutils
 --------
-o  <http://oss.software.ibm.com/jfs>
+o  <http://jfs.sourceforge.net/>
 
 Reiserfsprogs
 -------------
diff -Nru a/Documentation/IPMI.txt b/Documentation/IPMI.txt
--- a/Documentation/IPMI.txt	2005-03-11 12:51:41 -08:00
+++ b/Documentation/IPMI.txt	2005-03-11 12:51:41 -08:00
@@ -342,6 +342,7 @@
        irqs=<irq1>,<irq2>... trydefaults=[0|1]
        regspacings=<sp1>,<sp2>,... regsizes=<size1>,<size2>,...
        regshifts=<shift1>,<shift2>,...
+       slave_addrs=<addr1>,<addr2>,...
 
 Each of these except si_trydefaults is a list, the first item for the
 first interface, second item for the second interface, etc.
@@ -383,6 +384,10 @@
 be in the lower 8 bits.  The regshifts parameter give the amount to shift
 the data to get to the actual IPMI data.
 
+The slave_addrs specifies the IPMI address of the local BMC.  This is
+usually 0x20 and the driver defaults to that, but in case it's not, it
+can be specified when the driver starts up.
+
 When compiled into the kernel, the addresses can be specified on the
 kernel command line as:
 
@@ -392,6 +397,7 @@
        ipmi_si.regspacings=<sp1>,<sp2>,...
        ipmi_si.regsizes=<size1>,<size2>,...
        ipmi_si.regshifts=<shift1>,<shift2>,...
+       ipmi_si.slave_addrs=<addr1>,<addr2>,...
 
 It works the same as the module parameters of the same names.
 
diff -Nru a/Documentation/SecurityBugs b/Documentation/SecurityBugs
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/Documentation/SecurityBugs	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,38 @@
+Linux kernel developers take security very seriously.  As such, we'd
+like to know when a security bug is found so that it can be fixed and
+disclosed as quickly as possible.  Please report security bugs to the
+Linux kernel security team.
+
+1) Contact
+
+The Linux kernel security team can be contacted by email at
+<security@kernel.org>.  This is a private list of security officers
+who will help verify the bug report and develop and release a fix.
+It is possible that the security team will bring in extra help from
+area maintainers to understand and fix the security vulnerability.
+
+As it is with any bug, the more information provided the easier it
+will be to diagnose and fix.  Please review the procedure outlined in
+REPORTING-BUGS if you are unclear about what information is helpful.
+Any exploit code is very helpful and will not be released without
+consent from the reporter unless it has already been made public.
+
+2) Disclosure
+
+The goal of the Linux kernel security team is to work with the
+bug submitter to bug resolution as well as disclosure.  We prefer
+to fully disclose the bug as soon as possible.  It is reasonable to
+delay disclosure when the bug or the fix is not yet fully understood,
+the solution is not well-tested or for vendor coordination.  However, we
+expect these delays to be short, measurable in days, not weeks or months.
+A disclosure date is negotiated by the security team working with the
+bug submitter as well as vendors.  However, the kernel security team
+holds the final say when setting a disclosure date.  The timeframe for
+disclosure is from immediate (esp. if it's already publically known)
+to a few weeks.  As a basic default policy, we expect report date to
+disclosure date to be on the order of 7 days.
+
+3) Non-disclosure agreements
+
+The Linux kernel security team is not a formal body and therefore unable
+to enter any non-disclosure agreements.
diff -Nru a/Documentation/aoe/aoe.txt b/Documentation/aoe/aoe.txt
--- a/Documentation/aoe/aoe.txt	2005-03-11 12:51:42 -08:00
+++ b/Documentation/aoe/aoe.txt	2005-03-11 12:51:42 -08:00
@@ -6,9 +6,16 @@
 
 CREATING DEVICE NODES
 
-  Users of udev should find device nodes created automatically.  Two
-  scripts are provided in Documentation/aoe as examples of static
-  device node creation for using the aoe driver.
+  Users of udev should find the block device nodes created
+  automatically, but to create all the necessary device nodes, use the
+  udev configuration rules provided in udev.txt (in this directory).
+
+  There is a udev-install.sh script that shows how to install these
+  rules on your system.
+
+  If you are not using udev, two scripts are provided in
+  Documentation/aoe as examples of static device node creation for
+  using the aoe driver.
 
     rm -rf /dev/etherd
     sh Documentation/aoe/mkdevs.sh /dev/etherd
diff -Nru a/Documentation/aoe/status.sh b/Documentation/aoe/status.sh
--- a/Documentation/aoe/status.sh	2005-03-11 12:51:41 -08:00
+++ b/Documentation/aoe/status.sh	2005-03-11 12:51:41 -08:00
@@ -4,10 +4,13 @@
 set -e
 format="%8s\t%8s\t%8s\n"
 me=`basename $0`
+sysd=${sysfs_dir:-/sys}
 
 # printf "$format" device mac netif state
 
-test -z "`mount | grep sysfs`" && {
+# Suse 9.1 Pro doesn't put /sys in /etc/mtab
+#test -z "`mount | grep sysfs`" && {
+test ! -d "$sysd/block" && {
 	echo "$me Error: sysfs is not mounted" 1>&2
 	exit 1
 }
@@ -16,7 +19,7 @@
 	exit 1
 }
 
-for d in `ls -d /sys/block/etherd* 2>/dev/null | grep -v p` end; do
+for d in `ls -d $sysd/block/etherd* 2>/dev/null | grep -v p` end; do
 	# maybe ls comes up empty, so we use "end"
 	test $d = end && continue
 
diff -Nru a/Documentation/aoe/udev-install.sh b/Documentation/aoe/udev-install.sh
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/Documentation/aoe/udev-install.sh	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,26 @@
+# install the aoe-specific udev rules from udev.txt into 
+# the system's udev configuration
+# 
+
+me="`basename $0`"
+
+# find udev.conf, often /etc/udev/udev.conf
+# (or environment can specify where to find udev.conf)
+#
+if test -z "$conf"; then
+	if test -r /etc/udev/udev.conf; then
+		conf=/etc/udev/udev.conf
+	else
+		conf="`find /etc -type f -name udev.conf 2> /dev/null`"
+		if test -z "$conf" || test ! -r "$conf"; then
+			echo "$me Error: no udev.conf found" 1>&2
+			exit 1
+		fi
+	fi
+fi
+
+# find the directory where udev rules are stored, often
+# /etc/udev/rules.d
+#
+rules_d="`sed -n '/^udev_rules=/{ s!udev_rules=!!; s!\"!!g; p; }' $conf`"
+test "$rules_d" && sh -xc "cp `dirname $0`/udev.txt $rules_d/60-aoe.rules"
diff -Nru a/Documentation/aoe/udev.txt b/Documentation/aoe/udev.txt
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/Documentation/aoe/udev.txt	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,23 @@
+# These rules tell udev what device nodes to create for aoe support.
+# They may be installed along the following lines (adjusted to what
+# you see on your system).
+# 
+#   ecashin@makki ~$ su
+#   Password:
+#   bash# find /etc -type f -name udev.conf
+#   /etc/udev/udev.conf
+#   bash# grep udev_rules= /etc/udev/udev.conf
+#   udev_rules="/etc/udev/rules.d/"
+#   bash# ls /etc/udev/rules.d/
+#   10-wacom.rules  50-udev.rules
+#   bash# cp /path/to/linux-2.6.xx/Documentation/aoe/udev.txt \
+#           /etc/udev/rules.d/60-aoe.rules
+#  
+
+# aoe char devices
+SUBSYSTEM="aoe", KERNEL="discover",	NAME="etherd/%k", GROUP="disk", MODE="0220"
+SUBSYSTEM="aoe", KERNEL="err",		NAME="etherd/%k", GROUP="disk", MODE="0440"
+SUBSYSTEM="aoe", KERNEL="interfaces",	NAME="etherd/%k", GROUP="disk", MODE="0220"
+
+# aoe block devices     
+KERNEL="etherd*",       NAME="%k", GROUP="disk"
diff -Nru a/Documentation/arm/IXP2000 b/Documentation/arm/IXP2000
--- a/Documentation/arm/IXP2000	2005-03-11 12:51:50 -08:00
+++ b/Documentation/arm/IXP2000	2005-03-11 12:51:50 -08:00
@@ -45,7 +45,7 @@
 
 4. Usage Notes
 
-- The IXP2000 platforms ususally have rather complex PCI bus topologies
+- The IXP2000 platforms usually have rather complex PCI bus topologies
   with large memory space requirements. In addition, b/c of the way the
   Intel SDK is designed, devices are enumerated in a very specific
   way. B/c of this this, we use "pci=firmware" option in the kernel
diff -Nru a/Documentation/arm/Samsung-S3C24XX/H1940.txt b/Documentation/arm/Samsung-S3C24XX/H1940.txt
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/Documentation/arm/Samsung-S3C24XX/H1940.txt	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,40 @@
+		HP IPAQ H1940
+		=============
+
+http://www.handhelds.org/projects/h1940.html
+
+Introduction
+------------
+
+  The HP H1940 is a S3C2410 based handheld device, with
+  bluetooth connectivity.
+
+
+Support
+-------
+
+  A variety of information is available
+
+  handhelds.org project page:
+
+    http://www.handhelds.org/projects/h1940.html
+
+  handhelds.org wiki page:
+
+    http://handhelds.org/moin/moin.cgi/HpIpaqH1940
+
+  Herbert Pötzl pages:
+
+    http://vserver.13thfloor.at/H1940/
+
+
+Maintainers
+-----------
+
+  This project is being maintained and developed by a variety
+  of people, including Ben Dooks, Arnaud Patard, and Herbert Pötzl.
+
+  Thanks to the many others who have also provided support.
+
+
+(c) 2005 Ben Dooks
\ No newline at end of file
diff -Nru a/Documentation/arm/Samsung-S3C24XX/Overview.txt b/Documentation/arm/Samsung-S3C24XX/Overview.txt
--- a/Documentation/arm/Samsung-S3C24XX/Overview.txt	2005-03-11 12:51:52 -08:00
+++ b/Documentation/arm/Samsung-S3C24XX/Overview.txt	2005-03-11 12:51:52 -08:00
@@ -7,8 +7,8 @@
 ------------
 
   The Samsung S3C24XX range of ARM9 System-on-Chip CPUs are supported
-  by the 's3c2410' architecture of ARM Linux. Currently the S3C2410 is
-  the only supported CPU in this range.
+  by the 's3c2410' architecture of ARM Linux. Currently the S3C2410 and
+  the S3C2440 are supported CPUs.
 
 
 Configuration
@@ -36,6 +36,10 @@
 
     Samsung's own development board, geared for PDA work.
 
+  Samsung/Meritech SMDK2440
+
+    The S3C2440 compatible version of the SMDK2440
+
   Thorcom VR1000
 
     Custom embedded board
@@ -44,12 +48,41 @@
 
     Handheld (IPAQ), available in several varieties
 
-
   HP iPAQ rx3715
 
     S3C2440 based IPAQ, with a number of variations depending on
     features shipped.
 
+  Acer N30
+
+    A S3C2410 based PDA from Acer.  There is a Wiki page at
+    http://handhelds.org/moin/moin.cgi/AcerN30Documentation .
+
+
+Adding New Machines
+-------------------
+
+  The archicture has been designed to support as many machines as can
+  be configured for it in one kernel build, and any future additions
+  should keep this in mind before altering items outside of their own
+  machine files.
+
+  Machine definitions should be kept in linux/arch/arm/mach-s3c2410,
+  and there are a number of examples that can be looked at.
+
+  Read the kernel patch submission policies as well as the
+  Documentation/arm directory before submitting patches. The
+  ARM kernel series is managed by Russell King, and has a patch system
+  located at http://www.arm.linux.org.uk/developer/patches/
+  as well as mailing lists that can be found from the same site.
+
+  As a courtesy, please notify <ben-linux@fluff.org> of any new
+  machines or other modifications.
+
+  Any large scale modifications, or new drivers should be discussed
+  on the ARM kernel mailing list (linux-arm-kernel) before being
+  attempted.
+
 
 NAND
 ----
@@ -98,6 +131,9 @@
   Klaus Fetscher
   Dimitry Andric
   Shannon Holland
+  Guillaume Gourat (NexVision)
+  Christer Weinigel (wingel) (Acer N30)
+  Lucas Correia Villa Real (S3C2400 port)
 
 
 Document Changes
@@ -108,6 +144,11 @@
   25 Oct 2004 - BJD - Added Dimitry Andric to list of contributors
   25 Oct 2004 - BJD - Updated the MTD from the 2.6.9 merge
   21 Jan 2005 - BJD - Added rx3715, added Shannon to contributors
+  10 Feb 2005 - BJD - Added Guillaume Gourat to contributors
+  02 Mar 2005 - BJD - Added SMDK2440 to list of machines
+  06 Mar 2005 - BJD - Added Christer Weinigel
+  08 Mar 2005 - BJD - Added LCVR to list of people, updated introduction
+  08 Mar 2005 - BJD - Added section on adding machines
 
 Document Author
 ---------------
diff -Nru a/Documentation/arm/Samsung-S3C24XX/SMDK2440.txt b/Documentation/arm/Samsung-S3C24XX/SMDK2440.txt
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/Documentation/arm/Samsung-S3C24XX/SMDK2440.txt	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,56 @@
+		Samsung/Meritech SMDK2440
+		=========================
+
+Introduction
+------------
+
+  The SMDK2440 is a two part evaluation board for the Samsung S3C2440
+  processor. It includes support for LCD, SmartMedia, Audio, SD and
+  10MBit Ethernet, and expansion headers for various signals, including
+  the camera and unused GPIO.
+
+
+Configuration
+-------------
+
+  To set the default configuration, use `make smdk2440_defconfig` which
+  will configure the common features of this board, or use
+  `make s3c2410_config` to include support for all s3c2410/s3c2440 machines
+
+
+Support
+-------
+
+  Ben Dooks' SMDK2440 site at http://www.fluff.org/ben/smdk2440/ which
+  includes linux based USB download tools.
+
+  Some of the h1940 patches that can be found from the H1940 project
+  site at http://www.handhelds.org/projects/h1940.html can also be
+  applied to this board.
+
+
+Peripherals
+-----------
+
+  There is no current support for any of the extra peripherals on the
+  base-board itself.
+
+
+MTD
+---
+
+  The NAND flash should be supported by the in kernel MTD NAND support,
+  NOR flash will be added later.
+
+
+Maintainers
+-----------
+
+  This board is being maintained by Ben Dooks, for more info, see
+  http://www.fluff.org/ben/smdk2440/
+
+  Many thanks to Dimitry Andric of TomTom for the loan of the SMDK2440,
+  and to Simtec Electronics for allowing me time to work on this.
+
+
+(c) 2004 Ben Dooks
\ No newline at end of file
diff -Nru a/Documentation/cachetlb.txt b/Documentation/cachetlb.txt
--- a/Documentation/cachetlb.txt	2005-03-11 12:51:42 -08:00
+++ b/Documentation/cachetlb.txt	2005-03-11 12:51:42 -08:00
@@ -155,7 +155,7 @@
 	   change_range_of_page_tables(mm, start, end);
 	   flush_tlb_range(vma, start, end);
 
-	3) flush_cache_page(vma, addr);
+	3) flush_cache_page(vma, addr, pfn);
 	   set_pte(pte_pointer, new_pte_val);
 	   flush_tlb_page(vma, addr);
 
@@ -203,7 +203,7 @@
 	call flush_cache_page (see below) for each entry which may be
 	modified.
 
-3) void flush_cache_page(struct vm_area_struct *vma, unsigned long addr)
+3) void flush_cache_page(struct vm_area_struct *vma, unsigned long addr, unsigned long pfn)
 
 	This time we need to remove a PAGE_SIZE sized range
 	from the cache.  The 'vma' is the backing structure used by
@@ -213,8 +213,14 @@
 	executable (and thus could be in the 'instruction cache' in
 	"Harvard" type cache layouts).
 
+	The 'pfn' indicates the physical page frame (shift this value
+	left by PAGE_SHIFT to get the physical address) that 'addr'
+	translates to.  It is this mapping which should be removed from
+	the cache.
+
 	After running, there will be no entries in the cache for
-	'vma->vm_mm' for virtual address 'addr'.
+	'vma->vm_mm' for virtual address 'addr' which translates
+	to 'pfn'.
 
 	This is used primarily during fault processing.
 
diff -Nru a/Documentation/cciss.txt b/Documentation/cciss.txt
--- a/Documentation/cciss.txt	2005-03-11 12:51:41 -08:00
+++ b/Documentation/cciss.txt	2005-03-11 12:51:41 -08:00
@@ -15,6 +15,8 @@
 	* SA 6400 U320 Expansion Module
 	* SA 6i
 	* SA P600
+	* SA P800
+	* SA E400
 
 If nodes are not already created in the /dev/cciss directory, run as root:
 
diff -Nru a/Documentation/cpusets.txt b/Documentation/cpusets.txt
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/Documentation/cpusets.txt	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,407 @@
+				CPUSETS
+				-------
+
+Copyright (C) 2004 BULL SA.
+Written by Simon.Derr@bull.net
+
+Portions Copyright (c) 2004 Silicon Graphics, Inc.
+Modified by Paul Jackson <pj@sgi.com>
+
+CONTENTS:
+=========
+
+1. Cpusets
+  1.1 What are cpusets ?
+  1.2 Why are cpusets needed ?
+  1.3 How are cpusets implemented ?
+  1.4 How do I use cpusets ?
+2. Usage Examples and Syntax
+  2.1 Basic Usage
+  2.2 Adding/removing cpus
+  2.3 Setting flags
+  2.4 Attaching processes
+3. Questions
+4. Contact
+
+1. Cpusets
+==========
+
+1.1 What are cpusets ?
+----------------------
+
+Cpusets provide a mechanism for assigning a set of CPUs and Memory
+Nodes to a set of tasks.
+
+Cpusets constrain the CPU and Memory placement of tasks to only
+the resources within a tasks current cpuset.  They form a nested
+hierarchy visible in a virtual file system.  These are the essential
+hooks, beyond what is already present, required to manage dynamic
+job placement on large systems.
+
+Each task has a pointer to a cpuset.  Multiple tasks may reference
+the same cpuset.  Requests by a task, using the sched_setaffinity(2)
+system call to include CPUs in its CPU affinity mask, and using the
+mbind(2) and set_mempolicy(2) system calls to include Memory Nodes
+in its memory policy, are both filtered through that tasks cpuset,
+filtering out any CPUs or Memory Nodes not in that cpuset.  The
+scheduler will not schedule a task on a CPU that is not allowed in
+its cpus_allowed vector, and the kernel page allocator will not
+allocate a page on a node that is not allowed in the requesting tasks
+mems_allowed vector.
+
+If a cpuset is cpu or mem exclusive, no other cpuset, other than a direct
+ancestor or descendent, may share any of the same CPUs or Memory Nodes.
+
+User level code may create and destroy cpusets by name in the cpuset
+virtual file system, manage the attributes and permissions of these
+cpusets and which CPUs and Memory Nodes are assigned to each cpuset,
+specify and query to which cpuset a task is assigned, and list the
+task pids assigned to a cpuset.
+
+
+1.2 Why are cpusets needed ?
+----------------------------
+
+The management of large computer systems, with many processors (CPUs),
+complex memory cache hierarchies and multiple Memory Nodes having
+non-uniform access times (NUMA) presents additional challenges for
+the efficient scheduling and memory placement of processes.
+
+Frequently more modest sized systems can be operated with adequate
+efficiency just by letting the operating system automatically share
+the available CPU and Memory resources amongst the requesting tasks.
+
+But larger systems, which benefit more from careful processor and
+memory placement to reduce memory access times and contention,
+and which typically represent a larger investment for the customer,
+can benefit from explictly placing jobs on properly sized subsets of
+the system.
+
+This can be especially valuable on:
+
+    * Web Servers running multiple instances of the same web application,
+    * Servers running different applications (for instance, a web server
+      and a database), or
+    * NUMA systems running large HPC applications with demanding
+      performance characteristics.
+
+These subsets, or "soft partitions" must be able to be dynamically
+adjusted, as the job mix changes, without impacting other concurrently
+executing jobs.
+
+The kernel cpuset patch provides the minimum essential kernel
+mechanisms required to efficiently implement such subsets.  It
+leverages existing CPU and Memory Placement facilities in the Linux
+kernel to avoid any additional impact on the critical scheduler or
+memory allocator code.
+
+
+1.3 How are cpusets implemented ?
+---------------------------------
+
+Cpusets provide a Linux kernel (2.6.7 and above) mechanism to constrain
+which CPUs and Memory Nodes are used by a process or set of processes.
+
+The Linux kernel already has a pair of mechanisms to specify on which
+CPUs a task may be scheduled (sched_setaffinity) and on which Memory
+Nodes it may obtain memory (mbind, set_mempolicy).
+
+Cpusets extends these two mechanisms as follows:
+
+ - Cpusets are sets of allowed CPUs and Memory Nodes, known to the
+   kernel.
+ - Each task in the system is attached to a cpuset, via a pointer
+   in the task structure to a reference counted cpuset structure.
+ - Calls to sched_setaffinity are filtered to just those CPUs
+   allowed in that tasks cpuset.
+ - Calls to mbind and set_mempolicy are filtered to just
+   those Memory Nodes allowed in that tasks cpuset.
+ - The root cpuset contains all the systems CPUs and Memory
+   Nodes.
+ - For any cpuset, one can define child cpusets containing a subset
+   of the parents CPU and Memory Node resources.
+ - The hierarchy of cpusets can be mounted at /dev/cpuset, for
+   browsing and manipulation from user space.
+ - A cpuset may be marked exclusive, which ensures that no other
+   cpuset (except direct ancestors and descendents) may contain
+   any overlapping CPUs or Memory Nodes.
+ - You can list all the tasks (by pid) attached to any cpuset.
+
+The implementation of cpusets requires a few, simple hooks
+into the rest of the kernel, none in performance critical paths:
+
+ - in main/init.c, to initialize the root cpuset at system boot.
+ - in fork and exit, to attach and detach a task from its cpuset.
+ - in sched_setaffinity, to mask the requested CPUs by what's
+   allowed in that tasks cpuset.
+ - in sched.c migrate_all_tasks(), to keep migrating tasks within
+   the CPUs allowed by their cpuset, if possible.
+ - in the mbind and set_mempolicy system calls, to mask the requested
+   Memory Nodes by what's allowed in that tasks cpuset.
+ - in page_alloc, to restrict memory to allowed nodes.
+ - in vmscan.c, to restrict page recovery to the current cpuset.
+
+In addition a new file system, of type "cpuset" may be mounted,
+typically at /dev/cpuset, to enable browsing and modifying the cpusets
+presently known to the kernel.  No new system calls are added for
+cpusets - all support for querying and modifying cpusets is via
+this cpuset file system.
+
+Each task under /proc has an added file named 'cpuset', displaying
+the cpuset name, as the path relative to the root of the cpuset file
+system.
+
+The /proc/<pid>/status file for each task has two added lines,
+displaying the tasks cpus_allowed (on which CPUs it may be scheduled)
+and mems_allowed (on which Memory Nodes it may obtain memory),
+in the format seen in the following example:
+
+  Cpus_allowed:   ffffffff,ffffffff,ffffffff,ffffffff
+  Mems_allowed:   ffffffff,ffffffff
+
+Each cpuset is represented by a directory in the cpuset file system
+containing the following files describing that cpuset:
+
+ - cpus: list of CPUs in that cpuset
+ - mems: list of Memory Nodes in that cpuset
+ - cpu_exclusive flag: is cpu placement exclusive?
+ - mem_exclusive flag: is memory placement exclusive?
+ - tasks: list of tasks (by pid) attached to that cpuset
+
+New cpusets are created using the mkdir system call or shell
+command.  The properties of a cpuset, such as its flags, allowed
+CPUs and Memory Nodes, and attached tasks, are modified by writing
+to the appropriate file in that cpusets directory, as listed above.
+
+The named hierarchical structure of nested cpusets allows partitioning
+a large system into nested, dynamically changeable, "soft-partitions".
+
+The attachment of each task, automatically inherited at fork by any
+children of that task, to a cpuset allows organizing the work load
+on a system into related sets of tasks such that each set is constrained
+to using the CPUs and Memory Nodes of a particular cpuset.  A task
+may be re-attached to any other cpuset, if allowed by the permissions
+on the necessary cpuset file system directories.
+
+Such management of a system "in the large" integrates smoothly with
+the detailed placement done on individual tasks and memory regions
+using the sched_setaffinity, mbind and set_mempolicy system calls.
+
+The following rules apply to each cpuset:
+
+ - Its CPUs and Memory Nodes must be a subset of its parents.
+ - It can only be marked exclusive if its parent is.
+ - If its cpu or memory is exclusive, they may not overlap any sibling.
+
+These rules, and the natural hierarchy of cpusets, enable efficient
+enforcement of the exclusive guarantee, without having to scan all
+cpusets every time any of them change to ensure nothing overlaps a
+exclusive cpuset.  Also, the use of a Linux virtual file system (vfs)
+to represent the cpuset hierarchy provides for a familiar permission
+and name space for cpusets, with a minimum of additional kernel code.
+
+1.4 How do I use cpusets ?
+--------------------------
+
+In order to minimize the impact of cpusets on critical kernel
+code, such as the scheduler, and due to the fact that the kernel
+does not support one task updating the memory placement of another
+task directly, the impact on a task of changing its cpuset CPU
+or Memory Node placement, or of changing to which cpuset a task
+is attached, is subtle.
+
+If a cpuset has its Memory Nodes modified, then for each task attached
+to that cpuset, the next time that the kernel attempts to allocate
+a page of memory for that task, the kernel will notice the change
+in the tasks cpuset, and update its per-task memory placement to
+remain within the new cpusets memory placement.  If the task was using
+mempolicy MPOL_BIND, and the nodes to which it was bound overlap with
+its new cpuset, then the task will continue to use whatever subset
+of MPOL_BIND nodes are still allowed in the new cpuset.  If the task
+was using MPOL_BIND and now none of its MPOL_BIND nodes are allowed
+in the new cpuset, then the task will be essentially treated as if it
+was MPOL_BIND bound to the new cpuset (even though its numa placement,
+as queried by get_mempolicy(), doesn't change).  If a task is moved
+from one cpuset to another, then the kernel will adjust the tasks
+memory placement, as above, the next time that the kernel attempts
+to allocate a page of memory for that task.
+
+If a cpuset has its CPUs modified, then each task using that
+cpuset does _not_ change its behavior automatically.  In order to
+minimize the impact on the critical scheduling code in the kernel,
+tasks will continue to use their prior CPU placement until they
+are rebound to their cpuset, by rewriting their pid to the 'tasks'
+file of their cpuset.  If a task had been bound to some subset of its
+cpuset using the sched_setaffinity() call, and if any of that subset
+is still allowed in its new cpuset settings, then the task will be
+restricted to the intersection of the CPUs it was allowed on before,
+and its new cpuset CPU placement.  If, on the other hand, there is
+no overlap between a tasks prior placement and its new cpuset CPU
+placement, then the task will be allowed to run on any CPU allowed
+in its new cpuset.  If a task is moved from one cpuset to another,
+its CPU placement is updated in the same way as if the tasks pid is
+rewritten to the 'tasks' file of its current cpuset.
+
+In summary, the memory placement of a task whose cpuset is changed is
+updated by the kernel, on the next allocation of a page for that task,
+but the processor placement is not updated, until that tasks pid is
+rewritten to the 'tasks' file of its cpuset.  This is done to avoid
+impacting the scheduler code in the kernel with a check for changes
+in a tasks processor placement.
+
+There is an exception to the above.  If hotplug funtionality is used
+to remove all the CPUs that are currently assigned to a cpuset,
+then the kernel will automatically update the cpus_allowed of all
+tasks attached to CPUs in that cpuset with the online CPUs of the
+nearest parent cpuset that still has some CPUs online.  When memory
+hotplug functionality for removing Memory Nodes is available, a
+similar exception is expected to apply there as well.  In general,
+the kernel prefers to violate cpuset placement, over starving a task
+that has had all its allowed CPUs or Memory Nodes taken offline.  User
+code should reconfigure cpusets to only refer to online CPUs and Memory
+Nodes when using hotplug to add or remove such resources.
+
+To start a new job that is to be contained within a cpuset, the steps are:
+
+ 1) mkdir /dev/cpuset
+ 2) mount -t cpuset none /dev/cpuset
+ 3) Create the new cpuset by doing mkdir's and write's (or echo's) in
+    the /dev/cpuset virtual file system.
+ 4) Start a task that will be the "founding father" of the new job.
+ 5) Attach that task to the new cpuset by writing its pid to the
+    /dev/cpuset tasks file for that cpuset.
+ 6) fork, exec or clone the job tasks from this founding father task.
+
+For example, the following sequence of commands will setup a cpuset
+named "Charlie", containing just CPUs 2 and 3, and Memory Node 1,
+and then start a subshell 'sh' in that cpuset:
+
+  mount -t cpuset none /dev/cpuset
+  cd /dev/cpuset
+  mkdir Charlie
+  cd Charlie
+  /bin/echo 2-3 > cpus
+  /bin/echo 1 > mems
+  /bin/echo $$ > tasks
+  sh
+  # The subshell 'sh' is now running in cpuset Charlie
+  # The next line should display '/Charlie'
+  cat /proc/self/cpuset
+
+In the case that a change of cpuset includes wanting to move already
+allocated memory pages, consider further the work of IWAMOTO
+Toshihiro <iwamoto@valinux.co.jp> for page remapping and memory
+hotremoval, which can be found at:
+
+  http://people.valinux.co.jp/~iwamoto/mh.html
+
+The integration of cpusets with such memory migration is not yet
+available.
+
+In the future, a C library interface to cpusets will likely be
+available.  For now, the only way to query or modify cpusets is
+via the cpuset file system, using the various cd, mkdir, echo, cat,
+rmdir commands from the shell, or their equivalent from C.
+
+The sched_setaffinity calls can also be done at the shell prompt using
+SGI's runon or Robert Love's taskset.  The mbind and set_mempolicy
+calls can be done at the shell prompt using the numactl command
+(part of Andi Kleen's numa package).
+
+2. Usage Examples and Syntax
+============================
+
+2.1 Basic Usage
+---------------
+
+Creating, modifying, using the cpusets can be done through the cpuset
+virtual filesystem.
+
+To mount it, type:
+# mount -t cpuset none /dev/cpuset
+
+Then under /dev/cpuset you can find a tree that corresponds to the
+tree of the cpusets in the system. For instance, /dev/cpuset
+is the cpuset that holds the whole system.
+
+If you want to create a new cpuset under /dev/cpuset:
+# cd /dev/cpuset
+# mkdir my_cpuset
+
+Now you want to do something with this cpuset.
+# cd my_cpuset
+
+In this directory you can find several files:
+# ls
+cpus  cpu_exclusive  mems  mem_exclusive  tasks
+
+Reading them will give you information about the state of this cpuset:
+the CPUs and Memory Nodes it can use, the processes that are using
+it, its properties.  By writing to these files you can manipulate
+the cpuset.
+
+Set some flags:
+# /bin/echo 1 > cpu_exclusive
+
+Add some cpus:
+# /bin/echo 0-7 > cpus
+
+Now attach your shell to this cpuset:
+# /bin/echo $$ > tasks
+
+You can also create cpusets inside your cpuset by using mkdir in this
+directory.
+# mkdir my_sub_cs
+
+To remove a cpuset, just use rmdir:
+# rmdir my_sub_cs
+This will fail if the cpuset is in use (has cpusets inside, or has
+processes attached).
+
+2.2 Adding/removing cpus
+------------------------
+
+This is the syntax to use when writing in the cpus or mems files
+in cpuset directories:
+
+# /bin/echo 1-4 > cpus		-> set cpus list to cpus 1,2,3,4
+# /bin/echo 1,2,3,4 > cpus	-> set cpus list to cpus 1,2,3,4
+
+2.3 Setting flags
+-----------------
+
+The syntax is very simple:
+
+# /bin/echo 1 > cpu_exclusive 	-> set flag 'cpu_exclusive'
+# /bin/echo 0 > cpu_exclusive 	-> unset flag 'cpu_exclusive'
+
+2.4 Attaching processes
+-----------------------
+
+# /bin/echo PID > tasks
+
+Note that it is PID, not PIDs. You can only attach ONE task at a time.
+If you have several tasks to attach, you have to do it one after another:
+
+# /bin/echo PID1 > tasks
+# /bin/echo PID2 > tasks
+	...
+# /bin/echo PIDn > tasks
+
+
+3. Questions
+============
+
+Q: what's up with this '/bin/echo' ?
+A: bash's builtin 'echo' command does not check calls to write() against
+   errors. If you use it in the cpuset file system, you won't be
+   able to tell whether a command succeeded or failed.
+
+Q: When I attach processes, only the first of the line gets really attached !
+A: We can only return one error code per call to write(). So you should also
+   put only ONE pid.
+
+4. Contact
+==========
+
+Web: http://www.bullopensource.org/cpuset
diff -Nru a/Documentation/crypto/api-intro.txt b/Documentation/crypto/api-intro.txt
--- a/Documentation/crypto/api-intro.txt	2005-03-11 12:51:47 -08:00
+++ b/Documentation/crypto/api-intro.txt	2005-03-11 12:51:47 -08:00
@@ -234,6 +234,9 @@
 Anubis algorithm contributors:
   Aaron Grothe
 
+Tiger algorithm contributors:
+  Aaron Grothe
+
 Generic scatterwalk code by Adam J. Richter <adam@yggdrasil.com>
 
 Please send any credits updates or corrections to:
diff -Nru a/Documentation/devices.txt b/Documentation/devices.txt
--- a/Documentation/devices.txt	2005-03-11 12:51:52 -08:00
+++ b/Documentation/devices.txt	2005-03-11 12:51:52 -08:00
@@ -2754,6 +2754,8 @@
 		 50 = /dev/ttyIOC40		Altix serial card
 		    ...
 		 81 = /dev/ttyIOC431		Altix serial card
+		 82 = /dev/ttyVR0               NEC VR4100 series SIU
+		 83 = /dev/ttyVR1               NEC VR4100 series DSIU
 
 205 char	Low-density serial ports (alternate device)
 		  0 = /dev/culu0		Callout device for ttyLU0
@@ -2788,6 +2790,8 @@
 		 50 = /dev/cuioc40		Callout device for ttyIOC40
 		    ...
 		 81 = /dev/cuioc431		Callout device for ttyIOC431
+		 82 = /dev/cuvr0                Callout device for ttyVR0
+		 83 = /dev/cuvr1                Callout device for ttyVR1
 
 
 206 char	OnStream SC-x0 tape devices
diff -Nru a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt
--- a/Documentation/feature-removal-schedule.txt	2005-03-11 12:51:47 -08:00
+++ b/Documentation/feature-removal-schedule.txt	2005-03-11 12:51:47 -08:00
@@ -15,3 +15,25 @@
 	against the LSB, and can be replaced by using udev.
 Who:	Greg Kroah-Hartman <greg@kroah.com>
 
+---------------------------
+
+What:	/proc/sys/cpu/*, sysctl and /proc/cpufreq interfaces to cpufreq (2.4.x interfaces)
+When:	January 2005
+Files:	drivers/cpufreq/: cpufreq_userspace.c, proc_intf.c
+Why:	/proc/sys/cpu/* has been deprecated since inclusion of cpufreq into
+	the main kernel tree. It bloats /proc/ unnecessarily and doesn't work
+	well with the "governor"-based design of cpufreq.
+	/proc/cpufreq/* has also been deprecated for a long time and was only
+	meant for usage during 2.5. until the new sysfs-based interface became
+	ready. It has an inconsistent interface which doesn't work well with
+	userspace setting the frequency. The output from /proc/cpufreq/* can
+	be emulated using "cpufreq-info --proc" (cpufrequtils).
+	Both interfaces are superseded by the cpufreq interface in
+	/sys/devices/system/cpu/cpu%n/cpufreq/.
+Who:	Dominik Brodowski <linux@brodo.de>
+
+What:	ACPI S4bios support
+When:	May 2005
+Why:	Noone uses it, and it probably does not work, anyway. swsusp is
+	faster, more reliable, and people are actually using it.
+Who:	Pavel Machek <pavel@suse.cz>
diff -Nru a/Documentation/filesystems/jfs.txt b/Documentation/filesystems/jfs.txt
--- a/Documentation/filesystems/jfs.txt	2005-03-11 12:51:47 -08:00
+++ b/Documentation/filesystems/jfs.txt	2005-03-11 12:51:47 -08:00
@@ -1,13 +1,6 @@
 IBM's Journaled File System (JFS) for Linux
 
-JFS Homepage:  http://oss.software.ibm.com/jfs/
-
-Team members
-------------
-Dave Kleikamp      shaggy@austin.ibm.com  
-Dave Blaschke      blaschke@us.ibm.com
-Steve Best         sbest@us.ibm.com
-Barry Arndt        barndt@us.ibm.com
+JFS Homepage:  http://jfs.sourceforge.net/
 
 The following mount options are supported:
 
@@ -15,6 +8,7 @@
 		ASCII.  The default is to do no conversion.  Use
 		iocharset=utf8 for UTF8 translations.  This requires
 		CONFIG_NLS_UTF8 to be set in the kernel .config file.
+		iocharset=none specifies the default behavior explicitly.
 
 resize=value	Resize the volume to <value> blocks.  JFS only supports
 		growing a volume, not shrinking it.  This option is only
@@ -38,4 +32,4 @@
 Please send bugs, comments, cards and letters to shaggy@austin.ibm.com.
 
 The JFS mailing list can be subscribed to by using the link labeled
-"Mail list Subscribe" at our web page http://oss.software.ibm.com/jfs/.
+"Mail list Subscribe" at our web page http://jfs.sourceforge.net/
diff -Nru a/Documentation/filesystems/proc.txt b/Documentation/filesystems/proc.txt
--- a/Documentation/filesystems/proc.txt	2005-03-11 12:51:42 -08:00
+++ b/Documentation/filesystems/proc.txt	2005-03-11 12:51:42 -08:00
@@ -1754,18 +1754,25 @@
 
 In the interface directories you'll find the following entries:
 
-base_reachable_time
--------------------
+base_reachable_time, base_reachable_time_ms
+-------------------------------------------
 
 A base  value  used for computing the random reachable time value as specified
 in RFC2461.
 
-retrans_time
-------------
+Expression of base_reachable_time, which is deprecated, is in seconds.
+Expression of base_reachable_time_ms is in milliseconds.
 
-The time,  expressed  in  jiffies  (1/100 sec), between retransmitted Neighbor
-Solicitation messages.  Used  for  address  resolution  and  to determine if a
-neighbor is unreachable.
+retrans_time, retrans_time_ms
+-----------------------------
+
+The time between retransmitted Neighbor Solicitation messages.
+Used for address resolution and to determine if a neighbor is
+unreachable.
+
+Expression of retrans_time, which is deprecated, is in 1/100 seconds (for
+IPv4) or in jiffies (for IPv6).
+Expression of retrans_time_ms is in milliseconds.
 
 unres_qlen
 ----------
diff -Nru a/Documentation/i2c/porting-clients b/Documentation/i2c/porting-clients
--- a/Documentation/i2c/porting-clients	2005-03-11 12:51:42 -08:00
+++ b/Documentation/i2c/porting-clients	2005-03-11 12:51:42 -08:00
@@ -49,9 +49,8 @@
   static void lm75_update_client(struct i2c_client *client);
 
 * [Sysctl] All sysctl stuff is of course gone (defines, ctl_table
-  and functions). Instead, right after the static id definition
-  line, you have to define show and set functions for each sysfs
-  file. Only define set for writable values. Take a look at an
+  and functions). Instead, you have to define show and set functions for
+  each sysfs file. Only define set for writable values. Take a look at an
   existing 2.6 driver for details (lm78 for example). Don't forget
   to define the attributes for each file (this is that step that
   links callback functions). Use the file names specified in
@@ -86,6 +85,7 @@
   Replace the sysctl directory registration by calls to
   device_create_file. Move the driver initialization before any
   sysfs file creation.
+  Drop client->id.
 
 * [Init] Limits must not be set by the driver (can be done later in
   user-space). Chip should not be reset default (although a module
diff -Nru a/Documentation/i2c/writing-clients b/Documentation/i2c/writing-clients
--- a/Documentation/i2c/writing-clients	2005-03-11 12:51:41 -08:00
+++ b/Documentation/i2c/writing-clients	2005-03-11 12:51:41 -08:00
@@ -344,9 +344,6 @@
 
 For now, you can ignore the `flags' parameter. It is there for future use.
 
-  /* Unique ID allocation */
-  static int foo_id = 0;
-
   int foo_detect_client(struct i2c_adapter *adapter, int address, 
                         unsigned short flags, int kind)
   {
@@ -482,7 +479,6 @@
     data->type = kind;
     /* SENSORS ONLY END */
 
-    new_client->id = foo_id++; /* Automatically unique */
     data->valid = 0; /* Only if you use this field */
     init_MUTEX(&data->update_lock); /* Only if you use this field */
 
@@ -642,7 +638,7 @@
 parameter contains the bytes the read/write, the third the length of the
 buffer. Returned is the actual number of bytes read/written.
   
-  extern int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[],
+  extern int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msg,
                           int num);
 
 This sends a series of messages. Each message can be a read or write,
diff -Nru a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
--- a/Documentation/kernel-parameters.txt	2005-03-11 12:51:52 -08:00
+++ b/Documentation/kernel-parameters.txt	2005-03-11 12:51:52 -08:00
@@ -67,12 +67,14 @@
 	SCSI	Appropriate SCSI support is enabled.
 			A lot of drivers has their options described inside of
 			Documentation/scsi/.
+	SELINUX SELinux support is enabled.
 	SERIAL	Serial support is enabled.
 	SMP	The kernel is an SMP kernel.
 	SPARC	Sparc architecture is enabled.
 	SWSUSP	Software suspension is enabled.
 	TS	Appropriate touchscreen support is enabled.
 	USB	USB support is enabled.
+	USBHID	USB Human Interface Device support is enabled.
 	V4L	Video For Linux support is enabled.
 	VGA	The VGA console has been enabled.
 	VT	Virtual terminal support is enabled.
@@ -295,6 +297,14 @@
 			See header of drivers/cdrom/cdu31a.c.
 
 	chandev=	[HW,NET] Generic channel device initialisation
+
+	checkreqprot	[SELINUX] Set initial checkreqprot flag value.
+			Format: { "0" | "1" }
+			See security/selinux/Kconfig help text.
+			0 -- check protection applied by kernel (includes any implied execute protection).
+			1 -- check protection requested by application.
+			Default value is set via a kernel config option.
+			Value can be changed at runtime via /selinux/checkreqprot.
  
  	clock=		[BUGS=IA-32, HW] gettimeofday timesource override. 
 			Forces specified timesource (if avaliable) to be used
@@ -435,6 +445,14 @@
 			See Documentation/block/as-iosched.txt
 			and Documentation/block/deadline-iosched.txt for details.
 
+	enforcing	[SELINUX] Set initial enforcing status.
+			Format: {"0" | "1"}
+			See security/selinux/Kconfig help text.
+			0 -- permissive (log only, no denials).
+			1 -- enforcing (deny and log).
+			Default value is 0.
+			Value can be changed at runtime via /selinux/enforce.
+
 	es1370=		[HW,OSS]
 			Format: <lineout>[,<micbias>]
 			See also header of sound/oss/es1370.c.
@@ -514,11 +532,14 @@
 	i8042.dumbkbd	[HW] Pretend that controlled can only read data from
 			     keyboard and can not control its state
 			     (Don't attempt to blink the leds)
-	i8042.noacpi	[HW] Don't use ACPI to discover KBD/AUX controller
-			     settings
 	i8042.noaux	[HW] Don't check for auxiliary (== mouse) port
 	i8042.nomux	[HW] Don't check presence of an active multiplexing
 			     controller
+	i8042.nopnp	[HW] Don't use ACPIPnP / PnPBIOS to discover KBD/AUX
+			     controllers
+	i8042.panicblink=
+			[HW] Frequency with which keyboard LEDs should blink
+			     when kernel panics (default is 0.5 sec)
 	i8042.reset	[HW] Reset the controller during init and cleanup
 	i8042.unlock	[HW] Unlock (ignore) the keylock
 
@@ -634,6 +655,20 @@
 	logibm.irq=	[HW,MOUSE] Logitech Bus Mouse Driver
 			Format: <irq>
 
+	loglevel=	All Kernel Messages with a loglevel smaller than the
+			console loglevel will be printed to the console. It can
+			also be changed with klogd or other programs. The
+			loglevels are defined as follows:
+
+			0 (KERN_EMERG)		system is unusable
+			1 (KERN_ALERT)		action must be taken immediately
+			2 (KERN_CRIT)		critical conditions
+			3 (KERN_ERR)		error conditions
+			4 (KERN_WARNING)	warning conditions
+			5 (KERN_NOTICE)		normal but significant condition
+			6 (KERN_INFO)		informational
+			7 (KERN_DEBUG)		debug-level messages
+
 	log_buf_len=n	Sets the size of the printk ring buffer, in bytes.
 			Format is n, nk, nM.  n must be a power of two.  The
 			default is set in kernel config.
@@ -776,6 +811,10 @@
 	mtdparts=	[MTD]
 			See drivers/mtd/cmdline.c.
 
+	mtouchusb.raw_coordinates=
+			[HW] Make the MicroTouch USB driver use raw coordinates ('y', default)
+			or cooked coordinates ('n')
+
 	n2=		[NET] SDL Inc. RISCom/N2 synchronous serial card
 
 	NCR_D700=	[HW,SCSI]
@@ -1146,6 +1185,15 @@
 
 	scsi_logging=	[SCSI]
 
+	selinux		[SELINUX] Disable or enable SELinux at boot time.
+			Format: { "0" | "1" }
+			See security/selinux/Kconfig help text.
+			0 -- disable.
+			1 -- enable.
+			Default value is set via kernel config option.
+			If enabled at boot time, /selinux/disable can be used
+			later to disable prior to initial policy load.
+
 	serialnumber	[BUGS=IA-32]
 
 	sf16fm=		[HW] SF16FMI radio driver for Linux
@@ -1356,6 +1404,8 @@
 	thash_entries=	[KNL,NET]
 			Set number of hash buckets for TCP connection
 
+	time		Show timing data prefixed to each printk message line
+
 	tipar.timeout=	[HW,PPT]
 			Set communications timeout in tenths of a second
 			(default 15).
@@ -1393,6 +1443,9 @@
 			Format: <io>,<irq>
 
 	usb-handoff	[HW] Enable early USB BIOS -> OS handoff
+
+	usbhid.mousepoll=
+			[USBHID] The interval which mice are to be polled at.
  
 	video=		[FB] Frame buffer configuration
 			See Documentation/fb/modedb.txt.
diff -Nru a/Documentation/keys.txt b/Documentation/keys.txt
--- a/Documentation/keys.txt	2005-03-11 12:51:47 -08:00
+++ b/Documentation/keys.txt	2005-03-11 12:51:47 -08:00
@@ -151,8 +151,8 @@
      by using PR_JOIN_SESSION_KEYRING. It is permitted to request an anonymous
      new one, or to attempt to create or join one of a specific name.
 
-     The ownership of the thread and process-specific keyrings changes when
-     the real UID and GID of the thread changes.
+     The ownership of the thread keyring changes when the real UID and GID of
+     the thread changes.
 
  (*) Each user ID resident in the system holds two special keyrings: a user
      specific keyring and a default user session keyring. The default session
@@ -606,8 +606,12 @@
 due to two different users opening the same file is left to the filesystem
 author to solve.
 
-When accessing a key's payload data, the key->lock should be at least read
-locked, or else the data may be changed by update during the access.
+When accessing a key's payload data, key->lock should be at least read locked,
+or else the data may be changed by an update being performed from userspace
+whilst the driver or filesystem is trying to access it. If no update method is
+supplied, then the key's payload may be accessed without holding a lock as
+there is no way to change it, provided it can be guaranteed that the key's
+type definition won't go away.
 
 (*) To search for a key, call:
 
@@ -719,13 +723,19 @@
 
  (*) int (*instantiate)(struct key *key, const void *data, size_t datalen);
 
-     This method is called to attach a payload to a key during
-     construction. The payload attached need not bear any relation to the data
-     passed to this function.
+     This method is called to attach a payload to a key during construction.
+     The payload attached need not bear any relation to the data passed to
+     this function.
 
      If the amount of data attached to the key differs from the size in
      keytype->def_datalen, then key_payload_reserve() should be called.
 
+     This method does not have to lock the key in order to attach a payload.
+     The fact that KEY_FLAG_INSTANTIATED is not set in key->flags prevents
+     anything else from gaining access to the key.
+
+     This method may sleep if it wishes.
+
 
  (*) int (*duplicate)(struct key *key, const struct key *source);
 
@@ -734,8 +744,8 @@
      the new key. The data length on the new key will have been updated and
      the quota adjusted already.
 
-     The source key will be locked against change on the source->sem, so it is
-     safe to sleep here.
+     This method will be called with the source key's semaphore read-locked to
+     prevent its payload from being changed. It is safe to sleep here.
 
 
  (*) int (*update)(struct key *key, const void *data, size_t datalen);
@@ -749,30 +759,47 @@
      type is committed to changing the key because it's already been altered,
      so all memory allocation must be done first.
 
-     The key will be locked against other changers on key->sem, so it is safe
-     to sleep here.
-
      key_payload_reserve() should be called with the key->lock write locked,
      and the changes to the key's attached payload should be made before the
      key is locked.
 
+     The key will have its semaphore write-locked before this method is
+     called. Any changes to the key should be made with the key's rwlock
+     write-locked also. It is safe to sleep here.
+
 
  (*) int (*match)(const struct key *key, const void *desc);
 
      This method is called to match a key against a description. It should
      return non-zero if the two match, zero if they don't.
 
+     This method should not need to lock the key in any way. The type and
+     description can be considered invariant, and the payload should not be
+     accessed (the key may not yet be instantiated).
+
+     It is not safe to sleep in this method; the caller may hold spinlocks.
+
 
  (*) void (*destroy)(struct key *key);
 
      This method is optional. It is called to discard the payload data on a
      key when it is being destroyed.
 
+     This method does not need to lock the key; it can consider the key as
+     being inaccessible. Note that the key's type may have changed before this
+     function is called.
+
+     It is not safe to sleep in this method; the caller may hold spinlocks.
+
 
  (*) void (*describe)(const struct key *key, struct seq_file *p);
 
      This method is optional. It is called during /proc/keys reading to
-     summarise a key in text form.
+     summarise a key's description and payload in text form.
+
+     This method will be called with the key's rwlock read-locked. This will
+     prevent the key's payload and state changing; also the description should
+     not change. This also means it is not safe to sleep in this method.
 
 
  (*) long (*read)(const struct key *key, char __user *buffer, size_t buflen);
@@ -784,6 +811,12 @@
 
      If successful, the blob size that could be produced should be returned
      rather than the size copied.
+
+     This method will be called with the key's semaphore read-locked. This
+     will prevent the key's payload changing. It is not necessary to also
+     read-lock key->lock when accessing the key's payload. It is safe to sleep
+     in this method, such as might happen when the userspace buffer is
+     accessed.
 
 
 ============================
diff -Nru a/Documentation/networking/bonding.txt b/Documentation/networking/bonding.txt
--- a/Documentation/networking/bonding.txt	2005-03-11 12:51:42 -08:00
+++ b/Documentation/networking/bonding.txt	2005-03-11 12:51:42 -08:00
@@ -1,5 +1,5 @@
 
-                   Linux Ethernet Bonding Driver mini-howto
+                   Linux Ethernet Bonding Driver HOWTO
 
 Initial release : Thomas Davis <tadavis at lbl.gov>
 Corrections, HA extensions : 2000/10/03-15 :
@@ -9,8 +9,11 @@
   - Janice Girouard <girouard at us dot ibm dot com>
   - Jay Vosburgh <fubar at us dot ibm dot com>
 
+Reorganized and updated Feb 2005 by Jay Vosburgh
+
 Note :
 ------
+	
 The bonding driver originally came from Donald Becker's beowulf patches for
 kernel 2.0. It has changed quite a bit since, and the original tools from
 extreme-linux and beowulf sites will not work with this version of the driver.
@@ -18,218 +21,190 @@
 For new versions of the driver, patches for older kernels and the updated
 userspace tools, please follow the links at the end of this file.
 
-
 Table of Contents
 =================
 
-Installation
-Bond Configuration
-Module Parameters
-Configuring Multiple Bonds
-Switch Configuration
-Verifying Bond Configuration
-Frequently Asked Questions
-High Availability
-Promiscuous Sniffing notes
-8021q VLAN support
-Limitations
-Resources and Links
-
-
-Installation
-============
-
-1) Build kernel with the bonding driver
----------------------------------------
-For the latest version of the bonding driver, use kernel 2.4.12 or above
-(otherwise you will need to apply a patch).
-
-Configure kernel with `make menuconfig/xconfig/config', and select "Bonding
-driver support" in the "Network device support" section. It is recommended
-to configure the driver as module since it is currently the only way to
-pass parameters to the driver and configure more than one bonding device.
-
-Build and install the new kernel and modules.
-
-2) Get and install the userspace tools
---------------------------------------
-This version of the bonding driver requires updated ifenslave program. The
-original one from extreme-linux and beowulf will not work. Kernels 2.4.12
-and above include the updated version of ifenslave.c in
-Documentation/networking directory. For older kernels, please follow the
-links at the end of this file.
-
-IMPORTANT!!!  If you are running on Redhat 7.1 or greater, you need
-to be careful because /usr/include/linux is no longer a symbolic link
-to /usr/src/linux/include/linux.  If you build ifenslave while this is
-true, ifenslave will appear to succeed but your bond won't work.  The purpose
-of the -I option on the ifenslave compile line is to make sure it uses
-/usr/src/linux/include/linux/if_bonding.h instead of the version from
-/usr/include/linux.
-
-To install ifenslave.c, do:
-    # gcc -Wall -Wstrict-prototypes -O -I/usr/src/linux/include ifenslave.c -o ifenslave
-    # cp ifenslave /sbin/ifenslave
+1. Bonding Driver Installation
 
+2. Bonding Driver Options
 
-Bond Configuration
-==================
+3. Configuring Bonding Devices
+3.1	Configuration with sysconfig support
+3.2	Configuration with initscripts support
+3.3	Configuring Bonding Manually
+3.4	Configuring Multiple Bonds
 
-You will need to add at least the following line to /etc/modprobe.conf
-so the bonding driver will automatically load when the bond0 interface is
-configured. Refer to the modprobe.conf manual page for specific modprobe.conf
-syntax details. The Module Parameters section of this document describes each
-bonding driver parameter.
-
-	alias bond0 bonding
-
-Use standard distribution techniques to define the bond0 network interface. For
-example, on modern Red Hat distributions, create an ifcfg-bond0 file in
-the /etc/sysconfig/network-scripts directory that resembles the following:
+5. Querying Bonding Configuration
+5.1	Bonding Configuration
+5.2	Network Configuration
 
-DEVICE=bond0
-IPADDR=192.168.1.1
-NETMASK=255.255.255.0
-NETWORK=192.168.1.0
-BROADCAST=192.168.1.255
-ONBOOT=yes
-BOOTPROTO=none
-USERCTL=no
+6. Switch Configuration
 
-(use appropriate values for your network above)
+7. 802.1q VLAN Support
 
-All interfaces that are part of a bond should have SLAVE and MASTER
-definitions. For example, in the case of Red Hat, if you wish to make eth0 and
-eth1 a part of the bonding interface bond0, their config files (ifcfg-eth0 and
-ifcfg-eth1) should resemble the following:
+8. Link Monitoring
+8.1	ARP Monitor Operation
+8.2	Configuring Multiple ARP Targets
+8.3	MII Monitor Operation
 
-DEVICE=eth0
-USERCTL=no
-ONBOOT=yes
-MASTER=bond0
-SLAVE=yes
-BOOTPROTO=none
+9. Potential Trouble Sources
+9.1	Adventures in Routing
+9.2	Ethernet Device Renaming
+9.3	Painfully Slow Or No Failed Link Detection By Miimon
 
-Use DEVICE=eth1 in the ifcfg-eth1 config file. If you configure a second
-bonding interface (bond1), use MASTER=bond1 in the config file to make the
-network interface be a slave of bond1.
-
-Restart the networking subsystem or just bring up the bonding device if your
-administration tools allow it. Otherwise, reboot. On Red Hat distros you can
-issue `ifup bond0' or `/etc/rc.d/init.d/network restart'.
-
-If the administration tools of your distribution do not support
-master/slave notation in configuring network interfaces, you will need to
-manually configure the bonding device with the following commands:
-
-    # /sbin/ifconfig bond0 192.168.1.1 netmask 255.255.255.0 \
-      broadcast 192.168.1.255 up
-
-    # /sbin/ifenslave bond0 eth0
-    # /sbin/ifenslave bond0 eth1
-
-(use appropriate values for your network above)
-
-You can then create a script containing these commands and place it in the
-appropriate rc directory.
-
-If you specifically need all network drivers loaded before the bonding driver,
-adding the following line to modprobe.conf will cause the network driver for
-eth0 and eth1 to be loaded before the bonding driver.
-
-install bond0 /sbin/modprobe -a eth0 eth1 && /sbin/modprobe bonding
-
-Be careful not to reference bond0 itself at the end of the line, or modprobe
-will die in an endless recursive loop.
-
-If running SNMP agents, the bonding driver should be loaded before any network
-drivers participating in a bond. This requirement is due to the the interface
-index (ipAdEntIfIndex) being associated to the first interface found with a
-given IP address. That is, there is only one ipAdEntIfIndex for each IP
-address. For example, if eth0 and eth1 are slaves of bond0 and the driver for
-eth0 is loaded before the bonding driver, the interface for the IP address
-will be associated with the eth0 interface. This configuration is shown below,
-the IP address 192.168.1.1 has an interface index of 2 which indexes to eth0
-in the ifDescr table (ifDescr.2).
+10. SNMP agents
 
-     interfaces.ifTable.ifEntry.ifDescr.1 = lo
-     interfaces.ifTable.ifEntry.ifDescr.2 = eth0
-     interfaces.ifTable.ifEntry.ifDescr.3 = eth1
-     interfaces.ifTable.ifEntry.ifDescr.4 = eth2
-     interfaces.ifTable.ifEntry.ifDescr.5 = eth3
-     interfaces.ifTable.ifEntry.ifDescr.6 = bond0
-     ip.ipAddrTable.ipAddrEntry.ipAdEntIfIndex.10.10.10.10 = 5
-     ip.ipAddrTable.ipAddrEntry.ipAdEntIfIndex.192.168.1.1 = 2
-     ip.ipAddrTable.ipAddrEntry.ipAdEntIfIndex.10.74.20.94 = 4
-     ip.ipAddrTable.ipAddrEntry.ipAdEntIfIndex.127.0.0.1 = 1
+11. Promiscuous mode
 
-This problem is avoided by loading the bonding driver before any network
-drivers participating in a bond. Below is an example of loading the bonding
-driver first, the IP address 192.168.1.1 is correctly associated with
-ifDescr.2.
+12. High Availability Information
+12.1	High Availability in a Single Switch Topology
+12.1.1		Bonding Mode Selection for Single Switch Topology
+12.1.2		Link Monitoring for Single Switch Topology
+12.2	High Availability in a Multiple Switch Topology
+12.2.1		Bonding Mode Selection for Multiple Switch Topology
+12.2.2		Link Monitoring for Multiple Switch Topology
+12.3	Switch Behavior Issues for High Availability
 
-     interfaces.ifTable.ifEntry.ifDescr.1 = lo
-     interfaces.ifTable.ifEntry.ifDescr.2 = bond0
-     interfaces.ifTable.ifEntry.ifDescr.3 = eth0
-     interfaces.ifTable.ifEntry.ifDescr.4 = eth1
-     interfaces.ifTable.ifEntry.ifDescr.5 = eth2
-     interfaces.ifTable.ifEntry.ifDescr.6 = eth3
-     ip.ipAddrTable.ipAddrEntry.ipAdEntIfIndex.10.10.10.10 = 6
-     ip.ipAddrTable.ipAddrEntry.ipAdEntIfIndex.192.168.1.1 = 2
-     ip.ipAddrTable.ipAddrEntry.ipAdEntIfIndex.10.74.20.94 = 5
-     ip.ipAddrTable.ipAddrEntry.ipAdEntIfIndex.127.0.0.1 = 1
+13. Hardware Specific Considerations
+13.1	IBM BladeCenter
 
-While some distributions may not report the interface name in ifDescr,
-the association between the IP address and IfIndex remains and SNMP
-functions such as Interface_Scan_Next will report that association.
+14. Frequently Asked Questions
 
+15. Resources and Links
 
-Module Parameters
-=================
 
-Optional parameters for the bonding driver can be supplied as command line
-arguments to the insmod command. Typically, these parameters are specified in
-the file /etc/modprobe.conf (see the manual page for modprobe.conf). The
-available bonding driver parameters are listed below. If a parameter is not
-specified the default value is used. When initially configuring a bond, it
-is recommended "tail -f /var/log/messages" be run in a separate window to
-watch for bonding driver error messages.
-
-It is critical that either the miimon or arp_interval and arp_ip_target
-parameters be specified, otherwise serious network degradation will occur
-during link failures.
+1. Bonding Driver Installation
+==============================
+
+	Most popular distro kernels ship with the bonding driver
+already available as a module and the ifenslave user level control
+program installed and ready for use. If your distro does not, or you
+have need to compile bonding from source (e.g., configuring and
+installing a mainline kernel from kernel.org), you'll need to perform
+the following steps:
+
+1.1 Configure and build the kernel with bonding
+-----------------------------------------------
+
+	The latest version of the bonding driver is available in the
+drivers/net/bonding subdirectory of the most recent kernel source
+(which is available on http://kernel.org).
+
+	Prior to the 2.4.11 kernel, the bonding driver was maintained
+largely outside the kernel tree; patches for some earlier kernels are
+available on the bonding sourceforge site, although those patches are
+still several years out of date.  Most users will want to use either
+the most recent kernel from kernel.org or whatever kernel came with
+their distro.
+
+	Configure kernel with "make menuconfig" (or "make xconfig" or
+"make config"), then select "Bonding driver support" in the "Network
+device support" section.  It is recommended that you configure the
+driver as module since it is currently the only way to pass parameters
+to the driver or configure more than one bonding device.
+
+	Build and install the new kernel and modules, then proceed to
+step 2.
+
+1.2 Install ifenslave Control Utility
+-------------------------------------
+
+	The ifenslave user level control program is included in the
+kernel source tree, in the file Documentation/networking/ifenslave.c.
+It is generally recommended that you use the ifenslave that
+corresponds to the kernel that you are using (either from the same
+source tree or supplied with the distro), however, ifenslave
+executables from older kernels should function (but features newer
+than the ifenslave release are not supported).  Running an ifenslave
+that is newer than the kernel is not supported, and may or may not
+work.
+
+	To install ifenslave, do the following:
+
+# gcc -Wall -O -I/usr/src/linux/include ifenslave.c -o ifenslave
+# cp ifenslave /sbin/ifenslave
+
+	If your kernel source is not in "/usr/src/linux," then replace
+"/usr/src/linux/include" in the above with the location of your kernel
+source include directory.
+
+	You may wish to back up any existing /sbin/ifenslave, or, for
+testing or informal use, tag the ifenslave to the kernel version
+(e.g., name the ifenslave executable /sbin/ifenslave-2.6.10).
+
+IMPORTANT NOTE:
+
+	If you omit the "-I" or specify an incorrect directory, you
+may end up with an ifenslave that is incompatible with the kernel
+you're trying to build it for.  Some distros (e.g., Red Hat from 7.1
+onwards) do not have /usr/include/linux symbolically linked to the
+default kernel source include directory.
+
+
+2. Bonding Driver Options
+=========================
+
+	Options for the bonding driver are supplied as parameters to
+the bonding module at load time.  They may be given as command line
+arguments to the insmod or modprobe command, but are usually specified
+in either the /etc/modprobe.conf configuration file, or in a
+distro-specific configuration file (some of which are detailed in the
+next section).
+
+	The available bonding driver parameters are listed below. If a
+parameter is not specified the default value is used.  When initially
+configuring a bond, it is recommended "tail -f /var/log/messages" be
+run in a separate window to watch for bonding driver error messages.
+
+	It is critical that either the miimon or arp_interval and
+arp_ip_target parameters be specified, otherwise serious network
+degradation will occur during link failures.  Very few devices do not
+support at least miimon, so there is really no reason not to use it.
+
+	Options with textual values will accept either the text name
+	or, for backwards compatibility, the option value.  E.g.,
+	"mode=802.3ad" and "mode=4" set the same mode.
+
+	The parameters are as follows:
 
 arp_interval
 
-        Specifies the ARP monitoring frequency in milli-seconds.
-        If ARP monitoring is used in a load-balancing mode (mode 0 or 2), the
-        switch should be configured in a mode that evenly distributes packets
-        across all links - such as round-robin. If the switch is configured to
-        distribute the packets in an XOR fashion, all replies from the ARP
-        targets will be received on the same link which could cause the other
-        team members to fail. ARP monitoring should not be used in conjunction
-        with miimon. A value of 0 disables ARP monitoring. The default value
-        is 0.
+	Specifies the ARP monitoring frequency in milli-seconds. If
+	ARP monitoring is used in a load-balancing mode (mode 0 or 2),
+	the switch should be configured in a mode that evenly
+	distributes packets across all links - such as round-robin. If
+	the switch is configured to distribute the packets in an XOR
+	fashion, all replies from the ARP targets will be received on
+	the same link which could cause the other team members to
+	fail. ARP monitoring should not be used in conjunction with
+	miimon. A value of 0 disables ARP monitoring. The default
+	value is 0.
 
 arp_ip_target
 
-	Specifies the ip addresses to use when arp_interval is > 0. These
-	are the targets of the ARP request sent to determine the health of
-	the link to the targets. Specify these values in ddd.ddd.ddd.ddd
-	format. Multiple ip adresses must be seperated by a comma. At least
-	one ip address needs to be given for ARP monitoring to work. The
-	maximum number of targets that can be specified is set at 16.
+	Specifies the ip addresses to use when arp_interval is > 0.
+	These are the targets of the ARP request sent to determine the
+	health of the link to the targets.  Specify these values in
+	ddd.ddd.ddd.ddd format.  Multiple ip adresses must be
+	seperated by a comma.  At least one IP address must be given
+	for ARP monitoring to function.  The maximum number of targets
+	that can be specified is 16.  The default value is no IP
+	addresses.
 
 downdelay
 
-        Specifies the delay time in milli-seconds to disable a link after a
-        link failure has been detected. This should be a multiple of miimon
-        value, otherwise the value will be rounded. The default value is 0.
+	Specifies the time, in milliseconds, to wait before disabling
+	a slave after a link failure has been detected.  This option
+	is only valid for the miimon link monitor.  The downdelay
+	value should be a multiple of the miimon value; if not, it
+	will be rounded down to the nearest multiple.  The default
+	value is 0.
 
 lacp_rate
 
-        Option specifying the rate in which we'll ask our link partner to
-	transmit LACPDU packets in 802.3ad mode.  Possible values are:
+	Option specifying the rate in which we'll ask our link partner
+	to transmit LACPDU packets in 802.3ad mode.  Possible values
+	are:
 
 	slow or 0
 		Request partner to transmit LACPDUs every 30 seconds (default)
@@ -246,69 +221,76 @@
 
 miimon
 
-        Specifies the frequency in milli-seconds that MII link monitoring
-        will occur. A value of zero disables MII link monitoring. A value
-        of 100 is a good starting point. See High Availability section for
-        additional information. The default value is 0.
+	Specifies the frequency in milli-seconds that MII link
+	monitoring will occur.  A value of zero disables MII link
+	monitoring.  A value of 100 is a good starting point.  The
+	use_carrier option, below, affects how the link state is
+	determined.  See the High Availability section for additional
+	information.  The default value is 0.
 
 mode
 
 	Specifies one of the bonding policies. The default is
-	round-robin (balance-rr).  Possible values are (you can use
-	either the text or numeric option):
+	balance-rr (round robin).  Possible values are:
 
 	balance-rr or 0
 
-		Round-robin policy: Transmit in a sequential order
-		from the first available slave through the last. This
-		mode provides load balancing and fault tolerance.
+		Round-robin policy: Transmit packets in sequential
+		order from the first available slave through the
+		last.  This mode provides load balancing and fault
+		tolerance.
 
 	active-backup or 1
 
 		Active-backup policy: Only one slave in the bond is
-		active. A different slave becomes active if, and only
-		if, the active slave fails. The bond's MAC address is
+		active.  A different slave becomes active if, and only
+		if, the active slave fails.  The bond's MAC address is
 		externally visible on only one port (network adapter)
 		to avoid confusing the switch.  This mode provides
-		fault tolerance.
+		fault tolerance.  The primary option affects the
+		behavior of this mode.
 
 	balance-xor or 2
 
 		XOR policy: Transmit based on [(source MAC address
-		XOR'd with destination MAC address) modula slave
-		count]. This selects the same slave for each
-		destination MAC address. This mode provides load
+		XOR'd with destination MAC address) modulo slave
+		count].  This selects the same slave for each
+		destination MAC address.  This mode provides load
 		balancing and fault tolerance.
 
 	broadcast or 3
 
 		Broadcast policy: transmits everything on all slave
-		interfaces. This mode provides fault tolerance.
+		interfaces.  This mode provides fault tolerance.
 
 	802.3ad or 4
 
-		IEEE 802.3ad Dynamic link aggregation. Creates aggregation
-		groups that share the same speed and duplex settings.
-		Transmits and receives on all slaves in the active
-		aggregator.
+		IEEE 802.3ad Dynamic link aggregation.  Creates
+		aggregation groups that share the same speed and
+		duplex settings.  Utilizes all slaves in the active
+		aggregator according to the 802.3ad specification.
 
 		Pre-requisites:
 
-		1. Ethtool support in the base drivers for retrieving the
-		speed and duplex of each slave.
+		1. Ethtool support in the base drivers for retrieving
+		the speed and duplex of each slave.
 
 		2. A switch that supports IEEE 802.3ad Dynamic link
 		aggregation.
 
+		Most switches will require some type of configuration
+		to enable 802.3ad mode.
+
 	balance-tlb or 5
 
-		Adaptive transmit load balancing: channel bonding that does
-		not require any special switch support. The outgoing
-		traffic is distributed according to the current load
-		(computed relative to the speed) on each slave. Incoming
-		traffic is received by the current slave. If the receiving
-		slave fails, another slave takes over the MAC address of
-		the failed receiving slave.
+		Adaptive transmit load balancing: channel bonding that
+		does not require any special switch support.  The
+		outgoing traffic is distributed according to the
+		current load (computed relative to the speed) on each
+		slave.  Incoming traffic is received by the current
+		slave.  If the receiving slave fails, another slave
+		takes over the MAC address of the failed receiving
+		slave.
 
 		Prerequisite:
 
@@ -317,205 +299,452 @@
 
 	balance-alb or 6
 
-		Adaptive load balancing: includes balance-tlb + receive
-		load balancing (rlb) for IPV4 traffic and does not require
-		any special switch support. The receive load balancing is
-		achieved by ARP negotiation. The bonding driver intercepts
-		the ARP Replies sent by the server on their way out and
-		overwrites the src hw address with the unique hw address of
-		one of the slaves in the bond such that different clients
-		use different hw addresses for the server.
-
-		Receive traffic from connections created by the server is
-		also balanced. When the server sends an ARP Request the
-		bonding driver copies and saves the client's IP information
-		from the ARP. When the ARP Reply arrives from the client,
-		its hw address is retrieved and the bonding driver
-		initiates an ARP reply to this client assigning it to one
-		of the slaves in the bond. A problematic outcome of using
-		ARP negotiation for balancing is that each time that an ARP
-		request is broadcasted it uses the hw address of the
-		bond. Hence, clients learn the hw address of the bond and
-		the balancing of receive traffic collapses to the current
-		salve. This is handled by sending updates (ARP Replies) to
-		all the clients with their assigned hw address such that
-		the traffic is redistributed. Receive traffic is also
-		redistributed when a new slave is added to the bond and
-		when an inactive slave is re-activated. The receive load is
-		distributed sequentially (round robin) among the group of
-		highest speed slaves in the bond.
-
-		When a link is reconnected or a new slave joins the bond
-		the receive traffic is redistributed among all active
-		slaves in the bond by intiating ARP Replies with the
-		selected mac address to each of the clients. The updelay
-		modeprobe parameter must be set to a value equal or greater
-		than the switch's forwarding delay so that the ARP Replies
-		sent to the clients will not be blocked by the switch.
+		Adaptive load balancing: includes balance-tlb plus
+		receive load balancing (rlb) for IPV4 traffic, and
+		does not require any special switch support.  The
+		receive load balancing is achieved by ARP negotiation.
+		The bonding driver intercepts the ARP Replies sent by
+		the local system on their way out and overwrites the
+		source hardware address with the unique hardware
+		address of one of the slaves in the bond such that
+		different peers use different hardware addresses for
+		the server.
+
+		Receive traffic from connections created by the server
+		is also balanced.  When the local system sends an ARP
+		Request the bonding driver copies and saves the peer's
+		IP information from the ARP packet.  When the ARP
+		Reply arrives from the peer, its hardware address is
+		retrieved and the bonding driver initiates an ARP
+		reply to this peer assigning it to one of the slaves
+		in the bond.  A problematic outcome of using ARP
+		negotiation for balancing is that each time that an
+		ARP request is broadcast it uses the hardware address
+		of the bond.  Hence, peers learn the hardware address
+		of the bond and the balancing of receive traffic
+		collapses to the current slave.  This is handled by
+		sending updates (ARP Replies) to all the peers with
+		their individually assigned hardware address such that
+		the traffic is redistributed.  Receive traffic is also
+		redistributed when a new slave is added to the bond
+		and when an inactive slave is re-activated.  The
+		receive load is distributed sequentially (round robin)
+		among the group of highest speed slaves in the bond.
+
+		When a link is reconnected or a new slave joins the
+		bond the receive traffic is redistributed among all
+		active slaves in the bond by intiating ARP Replies
+		with the selected mac address to each of the
+		clients. The updelay parameter (detailed below) must
+		be set to a value equal or greater than the switch's
+		forwarding delay so that the ARP Replies sent to the
+		peers will not be blocked by the switch.
 
 		Prerequisites:
 
-		1. Ethtool support in the base drivers for retrieving the
-		speed of each slave.
+		1. Ethtool support in the base drivers for retrieving
+		the speed of each slave.
 
-		2. Base driver support for setting the hw address of a
-		device also when it is open. This is required so that there
-		will always be one slave in the team using the bond hw
-		address (the curr_active_slave) while having a unique hw
-		address for each slave in the bond. If the curr_active_slave
-		fails it's hw address is swapped with the new curr_active_slave
-		that was chosen.
+		2. Base driver support for setting the hardware
+		address of a device while it is open.  This is
+		required so that there will always be one slave in the
+		team using the bond hardware address (the
+		curr_active_slave) while having a unique hardware
+		address for each slave in the bond.  If the
+		curr_active_slave fails its hardware address is
+		swapped with the new curr_active_slave that was
+		chosen.
 
 primary
 
-        A string (eth0, eth2, etc) to equate to a primary device. If this
-        value is entered, and the device is on-line, it will be used first
-        as the output media. Only when this device is off-line, will
-        alternate devices be used. Otherwise, once a failover is detected
-        and a new default output is chosen, it will remain the output media
-        until it too fails. This is useful when one slave was preferred
-        over another, i.e. when one slave is 1000Mbps and another is
-        100Mbps. If the 1000Mbps slave fails and is later restored, it may
-        be preferred the faster slave gracefully become the active slave -
-        without deliberately failing the 100Mbps slave. Specifying a
-        primary is only valid in active-backup mode.
+	A string (eth0, eth2, etc) specifying which slave is the
+	primary device.  The specified device will always be the
+	active slave while it is available.  Only when the primary is
+	off-line will alternate devices be used.  This is useful when
+	one slave is preferred over another, e.g., when one slave has
+	higher throughput than another.
+
+	The primary option is only valid for active-backup mode.
 
 updelay
 
-        Specifies the delay time in milli-seconds to enable a link after a
-        link up status has been detected. This should be a multiple of miimon
-        value, otherwise the value will be rounded. The default value is 0.
+	Specifies the time, in milliseconds, to wait before enabling a
+	slave after a link recovery has been detected.  This option is
+	only valid for the miimon link monitor.  The updelay value
+	should be a multiple of the miimon value; if not, it will be
+	rounded down to the nearest multiple.  The default value is 0.
 
 use_carrier
 
-        Specifies whether or not miimon should use MII or ETHTOOL
-        ioctls vs. netif_carrier_ok() to determine the link status.
-        The MII or ETHTOOL ioctls are less efficient and utilize a
-        deprecated calling sequence within the kernel.  The
-        netif_carrier_ok() relies on the device driver to maintain its
-        state with netif_carrier_on/off; at this writing, most, but
-        not all, device drivers support this facility.
-
-        If bonding insists that the link is up when it should not be,
-        it may be that your network device driver does not support
-        netif_carrier_on/off.  This is because the default state for
-        netif_carrier is "carrier on." In this case, disabling
-        use_carrier will cause bonding to revert to the MII / ETHTOOL
-        ioctl method to determine the link state.
-
-        A value of 1 enables the use of netif_carrier_ok(), a value of
-        0 will use the deprecated MII / ETHTOOL ioctls.  The default
-        value is 1.
-
-
-Configuring Multiple Bonds
-==========================
-
-If several bonding interfaces are required, either specify the max_bonds
-parameter (described above), or load the driver multiple times.  Using
-the max_bonds parameter is less complicated, but has the limitation that
-all bonding instances created will have the same options.  Loading the
-driver multiple times allows each instance of the driver to have differing
-options.
-
-For example, to configure two bonding interfaces, one with mii link
-monitoring performed every 100 milliseconds, and one with ARP link
-monitoring performed every 200 milliseconds, the /etc/conf.modules should
-resemble the following:
+	Specifies whether or not miimon should use MII or ETHTOOL
+	ioctls vs. netif_carrier_ok() to determine the link
+	status. The MII or ETHTOOL ioctls are less efficient and
+	utilize a deprecated calling sequence within the kernel.  The
+	netif_carrier_ok() relies on the device driver to maintain its
+	state with netif_carrier_on/off; at this writing, most, but
+	not all, device drivers support this facility.
+
+	If bonding insists that the link is up when it should not be,
+	it may be that your network device driver does not support
+	netif_carrier_on/off.  The default state for netif_carrier is
+	"carrier on," so if a driver does not support netif_carrier,
+	it will appear as if the link is always up.  In this case,
+	setting use_carrier to 0 will cause bonding to revert to the
+	MII / ETHTOOL ioctl method to determine the link state.
+
+	A value of 1 enables the use of netif_carrier_ok(), a value of
+	0 will use the deprecated MII / ETHTOOL ioctls.  The default
+	value is 1.
+
+
+
+3. Configuring Bonding Devices
+==============================
+
+	There are, essentially, two methods for configuring bonding:
+with support from the distro's network initialization scripts, and
+without.  Distros generally use one of two packages for the network
+initialization scripts: initscripts or sysconfig.  Recent versions of
+these packages have support for bonding, while older versions do not.
+
+	We will first describe the options for configuring bonding for
+distros using versions of initscripts and sysconfig with full or
+partial support for bonding, then provide information on enabling
+bonding without support from the network initialization scripts (i.e.,
+older versions of initscripts or sysconfig).
+
+	If you're unsure whether your distro uses sysconfig or
+initscripts, or don't know if it's new enough, have no fear.
+Determining this is fairly straightforward.
+
+	First, issue the command:
+
+$ rpm -qf /sbin/ifup
+
+	It will respond with a line of text starting with either
+"initscripts" or "sysconfig," followed by some numbers.  This is the
+package that provides your network initialization scripts.
+
+	Next, to determine if your installation supports bonding,
+issue the command:
+
+$ grep ifenslave /sbin/ifup
+
+	If this returns any matches, then your initscripts or
+sysconfig has support for bonding.
+
+3.1 Configuration with sysconfig support
+----------------------------------------
+
+	This section applies to distros using a version of sysconfig
+with bonding support, for example, SuSE Linux Enterprise Server 9.
+
+	SuSE SLES 9's networking configuration system does support
+bonding, however, at this writing, the YaST system configuration
+frontend does not provide any means to work with bonding devices.
+Bonding devices can be managed by hand, however, as follows.
+
+	First, if they have not already been configured, configure the
+slave devices.  On SLES 9, this is most easily done by running the
+yast2 sysconfig configuration utility.  The goal is for to create an
+ifcfg-id file for each slave device.  The simplest way to accomplish
+this is to configure the devices for DHCP.  The name of the
+configuration file for each device will be of the form:
+
+ifcfg-id-xx:xx:xx:xx:xx:xx
+
+	Where the "xx" portion will be replaced with the digits from
+the device's permanent MAC address.
+
+	Once the set of ifcfg-id-xx:xx:xx:xx:xx:xx files has been
+created, it is necessary to edit the configuration files for the slave
+devices (the MAC addresses correspond to those of the slave devices).
+Before editing, the file will contain muliple lines, and will look
+something like this:
+
+BOOTPROTO='dhcp'
+STARTMODE='on'
+USERCTL='no'
+UNIQUE='XNzu.WeZGOGF+4wE'
+_nm_name='bus-pci-0001:61:01.0'
+
+	Change the BOOTPROTO and STARTMODE lines to the following:
+
+BOOTPROTO='none'
+STARTMODE='off'
+
+	Do not alter the UNIQUE or _nm_name lines.  Remove any other
+lines (USERCTL, etc).
+
+	Once the ifcfg-id-xx:xx:xx:xx:xx:xx files have been modified,
+it's time to create the configuration file for the bonding device
+itself.  This file is named ifcfg-bondX, where X is the number of the
+bonding device to create, starting at 0.  The first such file is
+ifcfg-bond0, the second is ifcfg-bond1, and so on.  The sysconfig
+network configuration system will correctly start multiple instances
+of bonding.
+
+	The contents of the ifcfg-bondX file is as follows:
+
+BOOTPROTO="static"
+BROADCAST="10.0.2.255"
+IPADDR="10.0.2.10"
+NETMASK="255.255.0.0"
+NETWORK="10.0.2.0"
+REMOTE_IPADDR=""
+STARTMODE="onboot"
+BONDING_MASTER="yes"
+BONDING_MODULE_OPTS="mode=active-backup miimon=100"
+BONDING_SLAVE0="eth0"
+BONDING_SLAVE1="eth1"
+
+	Replace the sample BROADCAST, IPADDR, NETMASK and NETWORK
+values with the appropriate values for your network.
+
+	Note that configuring the bonding device with BOOTPROTO='dhcp'
+does not work; the scripts attempt to obtain the device address from
+DHCP prior to adding any of the slave devices.  Without active slaves,
+the DHCP requests are not sent to the network.
+
+	The STARTMODE specifies when the device is brought online.
+The possible values are:
+
+	onboot:	 The device is started at boot time.  If you're not
+		 sure, this is probably what you want.
+
+	manual:	 The device is started only when ifup is called
+		 manually.  Bonding devices may be configured this
+		 way if you do not wish them to start automatically
+		 at boot for some reason.
+
+	hotplug: The device is started by a hotplug event.  This is not
+		 a valid choice for a bonding device.
+
+	off or ignore: The device configuration is ignored.
+
+	The line BONDING_MASTER='yes' indicates that the device is a
+bonding master device.  The only useful value is "yes."
+
+	The contents of BONDING_MODULE_OPTS are supplied to the
+instance of the bonding module for this device.  Specify the options
+for the bonding mode, link monitoring, and so on here.  Do not include
+the max_bonds bonding parameter; this will confuse the configuration
+system if you have multiple bonding devices.
+
+	Finally, supply one BONDING_SLAVEn="ethX" for each slave,
+where "n" is an increasing value, one for each slave, and "ethX" is
+the name of the slave device (eth0, eth1, etc).
+
+	When all configuration files have been modified or created,
+networking must be restarted for the configuration changes to take
+effect.  This can be accomplished via the following:
+
+# /etc/init.d/network restart
+
+	Note that the network control script (/sbin/ifdown) will
+remove the bonding module as part of the network shutdown processing,
+so it is not necessary to remove the module by hand if, e.g., the
+module paramters have changed.
+
+	Also, at this writing, YaST/YaST2 will not manage bonding
+devices (they do not show bonding interfaces on its list of network
+devices).  It is necessary to edit the configuration file by hand to
+change the bonding configuration.
+
+	Additional general options and details of the ifcfg file
+format can be found in an example ifcfg template file:
+
+/etc/sysconfig/network/ifcfg.template
+
+	Note that the template does not document the various BONDING_
+settings described above, but does describe many of the other options.
+
+3.2 Configuration with initscripts support
+------------------------------------------
+
+	This section applies to distros using a version of initscripts
+with bonding support, for example, Red Hat Linux 9 or Red Hat
+Enterprise Linux version 3.  On these systems, the network
+initialization scripts have some knowledge of bonding, and can be
+configured to control bonding devices.
+
+	These distros will not automatically load the network adapter
+driver unless the ethX device is configured with an IP address.
+Because of this constraint, users must manually configure a
+network-script file for all physical adapters that will be members of
+a bondX link.  Network script files are located in the directory:
+
+/etc/sysconfig/network-scripts
+
+	The file name must be prefixed with "ifcfg-eth" and suffixed
+with the adapter's physical adapter number.  For example, the script
+for eth0 would be named /etc/sysconfig/network-scripts/ifcfg-eth0.
+Place the following text in the file:
 
-alias bond0 bonding
-alias bond1 bonding
+DEVICE=eth0
+USERCTL=no
+ONBOOT=yes
+MASTER=bond0
+SLAVE=yes
+BOOTPROTO=none
 
-options bond0 miimon=100
-options bond1 -o bonding1 arp_interval=200 arp_ip_target=10.0.0.1
+	The DEVICE= line will be different for every ethX device and
+must correspond with the name of the file, i.e., ifcfg-eth1 must have
+a device line of DEVICE=eth1.  The setting of the MASTER= line will
+also depend on the final bonding interface name chosen for your bond.
+As with other network devices, these typically start at 0, and go up
+one for each device, i.e., the first bonding instance is bond0, the
+second is bond1, and so on.
+
+	Next, create a bond network script.  The file name for this
+script will be /etc/sysconfig/network-scripts/ifcfg-bondX where X is
+the number of the bond.  For bond0 the file is named "ifcfg-bond0",
+for bond1 it is named "ifcfg-bond1", and so on.  Within that file,
+place the following text:
 
-Configuring Multiple ARP Targets
-================================
+DEVICE=bond0
+IPADDR=192.168.1.1
+NETMASK=255.255.255.0
+NETWORK=192.168.1.0
+BROADCAST=192.168.1.255
+ONBOOT=yes
+BOOTPROTO=none
+USERCTL=no
 
-While ARP monitoring can be done with just one target, it can be useful
-in a High Availability setup to have several targets to monitor. In the
-case of just one target,  the target itself may go down or have a problem
-making it unresponsive to ARP requests. Having an additional target (or
-several) increases the reliability of the ARP monitoring.
+	Be sure to change the networking specific lines (IPADDR,
+NETMASK, NETWORK and BROADCAST) to match your network configuration.
 
-Multiple ARP targets must be seperated by commas as follows:
+	Finally, it is necessary to edit /etc/modules.conf to load the
+bonding module when the bond0 interface is brought up.  The following
+sample lines in /etc/modules.conf will load the bonding module, and
+select its options:
 
-# example options for ARP monitoring with three targets
 alias bond0 bonding
-options bond0 arp_interval=60 arp_ip_target=192.168.0.1,192.168.0.3,192.168.0.9
+options bond0 mode=balance-alb miimon=100
 
-For just a single target the options would resemble:
+	Replace the sample parameters with the appropriate set of
+options for your configuration.
 
-# example options for ARP monitoring with one target
+	Finally run "/etc/rc.d/init.d/network restart" as root.  This
+will restart the networking subsystem and your bond link should be now
+up and running.
+
+
+3.3 Configuring Bonding Manually
+--------------------------------
+
+	This section applies to distros whose network initialization
+scripts (the sysconfig or initscripts package) do not have specific
+knowledge of bonding.  One such distro is SuSE Linux Enterprise Server
+version 8.
+
+	The general methodology for these systems is to place the
+bonding module parameters into /etc/modprobe.conf, then add modprobe
+and/or ifenslave commands to the system's global init script.  The
+name of the global init script differs; for sysconfig, it is
+/etc/init.d/boot.local and for initscripts it is /etc/rc.d/rc.local.
+
+	For example, if you wanted to make a simple bond of two e100
+devices (presumed to be eth0 and eth1), and have it persist across
+reboots, edit the appropriate file (/etc/init.d/boot.local or
+/etc/rc.d/rc.local), and add the following:
+
+modprobe bonding -obond0 mode=balance-alb miimon=100
+modprobe e100
+ifconfig bond0 192.168.1.1 netmask 255.255.255.0 up
+ifenslave bond0 eth0
+ifenslave bond0 eth1
+
+	Replace the example bonding module parameters and bond0
+network configuration (IP address, netmask, etc) with the appropriate
+values for your configuration.  The above example loads the bonding
+module with the name "bond0," this simplifies the naming if multiple
+bonding modules are loaded (each successive instance of the module is
+given a different name, and the module instance names match the
+bonding interface names).
+
+	Unfortunately, this method will not provide support for the
+ifup and ifdown scripts on the bond devices.  To reload the bonding
+configuration, it is necessary to run the initialization script, e.g.,
+
+# /etc/init.d/boot.local
+
+	or
+
+# /etc/rc.d/rc.local
+
+	It may be desirable in such a case to create a separate script
+which only initializes the bonding configuration, then call that
+separate script from within boot.local.  This allows for bonding to be
+enabled without re-running the entire global init script.
+
+	To shut down the bonding devices, it is necessary to first
+mark the bonding device itself as being down, then remove the
+appropriate device driver modules.  For our example above, you can do
+the following:
+
+# ifconfig bond0 down
+# rmmod bond0
+# rmmod e100
+
+	Again, for convenience, it may be desirable to create a script
+with these commands.
+
+
+3.4 Configuring Multiple Bonds
+------------------------------
+
+	This section contains information on configuring multiple
+bonding devices with differing options.  If you require multiple
+bonding devices, but all with the same options, see the "max_bonds"
+module paramter, documented above.
+
+	To create multiple bonding devices with differing options, it
+is necessary to load the bonding driver multiple times.  Note that
+current versions of the sysconfig network initialization scripts
+handle this automatically; if your distro uses these scripts, no
+special action is needed.  See the section Configuring Bonding
+Devices, above, if you're not sure about your network initialization
+scripts.
+
+	To load multiple instances of the module, it is necessary to
+specify a different name for each instance (the module loading system
+requires that every loaded module, even multiple instances of the same
+module, have a unique name).  This is accomplished by supplying
+multiple sets of bonding options in /etc/modprobe.conf, for example:
+	
 alias bond0 bonding
-options bond0 arp_interval=60 arp_ip_target=192.168.0.100
-
-Potential Problems When Using ARP Monitor
-=========================================
+options bond0 -o bond0 mode=balance-rr miimon=100
 
-1. Driver support
-
-The ARP monitor relies on the network device driver to maintain two
-statistics: the last receive time (dev->last_rx), and the last
-transmit time (dev->trans_start).  If the network device driver does
-not update one or both of these, then the typical result will be that,
-upon startup, all links in the bond will immediately be declared down,
-and remain that way.  A network monitoring tool (tcpdump, e.g.) will
-show ARP requests and replies being sent and received on the bonding
-device.
-
-The possible resolutions for this are to (a) fix the device driver, or
-(b) discontinue the ARP monitor (using miimon as an alternative, for
-example).
-
-2. Adventures in Routing
-
-When bonding is set up with the ARP monitor, it is important that the
-slave devices not have routes that supercede routes of the master (or,
-generally, not have routes at all).  For example, suppose the bonding
-device bond0 has two slaves, eth0 and eth1, and the routing table is
-as follows:
-
-Kernel IP routing table
-Destination     Gateway         Genmask         Flags   MSS Window  irtt Iface
-10.0.0.0        0.0.0.0         255.255.0.0     U        40 0          0 eth0
-10.0.0.0        0.0.0.0         255.255.0.0     U        40 0          0 eth1
-10.0.0.0        0.0.0.0         255.255.0.0     U        40 0          0 bond0
-127.0.0.0       0.0.0.0         255.0.0.0       U        40 0          0 lo
+alias bond1 bonding
+options bond1 -o bond1 mode=balance-alb miimon=50
 
-In this case, the ARP monitor (and ARP itself) may become confused,
-because ARP requests will be sent on one interface (bond0), but the
-corresponding reply will arrive on a different interface (eth0).  This
-reply looks to ARP as an unsolicited ARP reply (because ARP matches
-replies on an interface basis), and is discarded.  This will likely
-still update the receive/transmit times in the driver, but will lose
-packets.
-
-The resolution here is simply to insure that slaves do not have routes
-of their own, and if for some reason they must, those routes do not
-supercede routes of their master.  This should generally be the case,
-but unusual configurations or errant manual or automatic static route
-additions may cause trouble.
+	will load the bonding module two times.  The first instance is
+named "bond0" and creates the bond0 device in balance-rr mode with an
+miimon of 100.  The second instance is named "bond1" and creates the
+bond1 device in balance-alb mode with an miimon of 50.
 
-Switch Configuration
-====================
+	This may be repeated any number of times, specifying a new and
+unique name in place of bond0 or bond1 for each instance.
 
-While the switch does not need to be configured when the active-backup,
-balance-tlb or balance-alb policies (mode=1,5,6) are used, it does need to
-be configured for the round-robin, XOR, broadcast, or 802.3ad policies
-(mode=0,2,3,4).
+	When the appropriate module paramters are in place, then
+configure bonding according to the instructions for your distro.
 
+5. Querying Bonding Configuration 
+=================================
 
-Verifying Bond Configuration
-============================
+5.1 Bonding Configuration
+-------------------------
 
-1) Bonding information files
-----------------------------
-The bonding driver information files reside in the /proc/net/bonding directory.
+	Each bonding device has a read-only file residing in the
+/proc/net/bonding directory.  The file contents include information
+about the bonding configuration, options and state of each slave.
 
-Sample contents of /proc/net/bonding/bond0 after the driver is loaded with
-parameters of mode=0 and miimon=1000 is shown below.
+	For example, the contents of /proc/net/bonding/bond0 after the
+driver is loaded with parameters of mode=0 and miimon=1000 is
+generally as follows:
 
+	Ethernet Channel Bonding Driver: 2.6.1 (October 29, 2004)
         Bonding Mode: load balancing (round-robin)
         Currently Active Slave: eth0
         MII Status: up
@@ -531,15 +760,23 @@
         MII Status: up
         Link Failure Count: 1
 
-2) Network verification
------------------------
-The network configuration can be verified using the ifconfig command. In
-the example below, the bond0 interface is the master (MASTER) while eth0 and
-eth1 are slaves (SLAVE). Notice all slaves of bond0 have the same MAC address
-(HWaddr) as bond0 for all modes except TLB and ALB that require a unique MAC
-address for each slave.
+	The precise format and contents will change depending upon the
+bonding configuration, state, and version of the bonding driver.
+
+5.2 Network configuration
+-------------------------
+
+	The network configuration can be inspected using the ifconfig
+command.  Bonding devices will have the MASTER flag set; Bonding slave
+devices will have the SLAVE flag set.  The ifconfig output does not
+contain information on which slaves are associated with which masters.
+
+	In the example below, the bond0 interface is the master
+(MASTER) while eth0 and eth1 are slaves (SLAVE). Notice all slaves of
+bond0 have the same MAC address (HWaddr) as bond0 for all modes except
+TLB and ALB that require a unique MAC address for each slave.
 
-[root]# /sbin/ifconfig
+# /sbin/ifconfig
 bond0     Link encap:Ethernet  HWaddr 00:C0:F0:1F:37:B4
           inet addr:XXX.XXX.XXX.YYY  Bcast:XXX.XXX.XXX.255  Mask:255.255.252.0
           UP BROADCAST RUNNING MASTER MULTICAST  MTU:1500  Metric:1
@@ -563,430 +800,819 @@
           collisions:0 txqueuelen:100
           Interrupt:9 Base address:0x1400
 
+6. Switch Configuration
+=======================
 
-Frequently Asked Questions
-==========================
+	For this section, "switch" refers to whatever system the
+bonded devices are directly connected to (i.e., where the other end of
+the cable plugs into).  This may be an actual dedicated switch device,
+or it may be another regular system (e.g., another computer running
+Linux),
+
+	The active-backup, balance-tlb and balance-alb modes do not
+require any specific configuration of the switch.
+
+	The 802.3ad mode requires that the switch have the appropriate
+ports configured as an 802.3ad aggregation.  The precise method used
+to configure this varies from switch to switch, but, for example, a
+Cisco 3550 series switch requires that the appropriate ports first be
+grouped together in a single etherchannel instance, then that
+etherchannel is set to mode "lacp" to enable 802.3ad (instead of
+standard EtherChannel).
+
+	The balance-rr, balance-xor and broadcast modes generally
+require that the switch have the appropriate ports grouped together.
+The nomenclature for such a group differs between switches, it may be
+called an "etherchannel" (as in the Cisco example, above), a "trunk
+group" or some other similar variation.  For these modes, each switch
+will also have its own configuration options for the switch's transmit
+policy to the bond.  Typical choices include XOR of either the MAC or
+IP addresses.  The transmit policy of the two peers does not need to
+match.  For these three modes, the bonding mode really selects a
+transmit policy for an EtherChannel group; all three will interoperate
+with another EtherChannel group.
+
+
+7. 802.1q VLAN Support
+======================
+
+	It is possible to configure VLAN devices over a bond interface
+using the 8021q driver.  However, only packets coming from the 8021q
+driver and passing through bonding will be tagged by default.  Self
+generated packets, for example, bonding's learning packets or ARP
+packets generated by either ALB mode or the ARP monitor mechanism, are
+tagged internally by bonding itself.  As a result, bonding must
+"learn" the VLAN IDs configured above it, and use those IDs to tag
+self generated packets.
+
+	For reasons of simplicity, and to support the use of adapters
+that can do VLAN hardware acceleration offloding, the bonding
+interface declares itself as fully hardware offloaing capable, it gets
+the add_vid/kill_vid notifications to gather the necessary
+information, and it propagates those actions to the slaves.  In case
+of mixed adapter types, hardware accelerated tagged packets that
+should go through an adapter that is not offloading capable are
+"un-accelerated" by the bonding driver so the VLAN tag sits in the
+regular location.
+
+	VLAN interfaces *must* be added on top of a bonding interface
+only after enslaving at least one slave.  The bonding interface has a
+hardware address of 00:00:00:00:00:00 until the first slave is added.
+If the VLAN interface is created prior to the first enslavement, it
+would pick up the all-zeroes hardware address.  Once the first slave
+is attached to the bond, the bond device itself will pick up the
+slave's hardware address, which is then available for the VLAN device.
+
+	Also, be aware that a similar problem can occur if all slaves
+are released from a bond that still has one or more VLAN interfaces on
+top of it.  When a new slave is added, the bonding interface will
+obtain its hardware address from the first slave, which might not
+match the hardware address of the VLAN interfaces (which was
+ultimately copied from an earlier slave).
+
+	There are two methods to insure that the VLAN device operates
+with the correct hardware address if all slaves are removed from a
+bond interface:
+
+	1. Remove all VLAN interfaces then recreate them
+
+	2. Set the bonding interface's hardware address so that it
+matches the hardware address of the VLAN interfaces.
+
+	Note that changing a VLAN interface's HW address would set the
+underlying device -- i.e. the bonding interface -- to promiscouos
+mode, which might not be what you want.
 
-1.  Is it SMP safe?
-
-	Yes. The old 2.0.xx channel bonding patch was not SMP safe.
-	The new driver was designed to be SMP safe from the start.
 
-2.  What type of cards will work with it?
-
-	Any Ethernet type cards (you can even mix cards - a Intel
-	EtherExpress PRO/100 and a 3com 3c905b, for example).
-	You can even bond together Gigabit Ethernet cards!
+8. Link Monitoring
+==================
 
-3.  How many bonding devices can I have?
+	The bonding driver at present supports two schemes for
+monitoring a slave device's link state: the ARP monitor and the MII
+monitor.
+
+	At the present time, due to implementation restrictions in the
+bonding driver itself, it is not possible to enable both ARP and MII
+monitoring simultaneously.
+
+8.1 ARP Monitor Operation
+-------------------------
+
+	The ARP monitor operates as its name suggests: it sends ARP
+queries to one or more designated peer systems on the network, and
+uses the response as an indication that the link is operating.  This
+gives some assurance that traffic is actually flowing to and from one
+or more peers on the local network.
+
+	The ARP monitor relies on the device driver itself to verify
+that traffic is flowing.  In particular, the driver must keep up to
+date the last receive time, dev->last_rx, and transmit start time,
+dev->trans_start.  If these are not updated by the driver, then the
+ARP monitor will immediately fail any slaves using that driver, and
+those slaves will stay down.  If networking monitoring (tcpdump, etc)
+shows the ARP requests and replies on the network, then it may be that
+your device driver is not updating last_rx and trans_start.
 
-	There is no limit.
+8.2 Configuring Multiple ARP Targets
+------------------------------------
 
-4.  How many slaves can a bonding device have?
+	While ARP monitoring can be done with just one target, it can
+be useful in a High Availability setup to have several targets to
+monitor.  In the case of just one target, the target itself may go
+down or have a problem making it unresponsive to ARP requests.  Having
+an additional target (or several) increases the reliability of the ARP
+monitoring.
 
-	Limited by the number of network interfaces Linux supports and/or the
-	number of network cards you can place in your system.
+	Multiple ARP targets must be seperated by commas as follows:
 
-5.  What happens when a slave link dies?
+# example options for ARP monitoring with three targets
+alias bond0 bonding
+options bond0 arp_interval=60 arp_ip_target=192.168.0.1,192.168.0.3,192.168.0.9
 
-	If your ethernet cards support MII or ETHTOOL link status monitoring
-        and the MII monitoring has been enabled in the driver (see description
-        of module parameters), there will be no adverse consequences. This
-        release of the bonding driver knows how to get the MII information and
-	enables or disables its slaves according to their link status.
-	See section on High Availability for additional information.
-
-	For ethernet cards not supporting MII status, the arp_interval and
-        arp_ip_target parameters must be specified for bonding to work
-        correctly. If packets have not been sent or received during the
-        specified arp_interval duration, an ARP request is sent to the
-        targets to generate send and receive traffic. If after this
-        interval, either the successful send and/or receive count has not
-        incremented, the next slave in the sequence will become the active
-        slave.
-
-	If neither mii_monitor and arp_interval is configured, the bonding
-	driver will not handle this situation very well. The driver will
-	continue to send packets but some packets will be lost. Retransmits
-	will cause serious degradation of performance (in the case when one
-	of two slave links fails, 50% packets will be lost, which is a serious
-	problem for both TCP and UDP).
+	For just a single target the options would resemble:
 
-6.  Can bonding be used for High Availability?
+# example options for ARP monitoring with one target
+alias bond0 bonding
+options bond0 arp_interval=60 arp_ip_target=192.168.0.100
 
-        Yes, if you use MII monitoring and ALL your cards support MII link
-        status reporting. See section on High Availability for more
-        information.
 
-7.  Which switches/systems does it work with?
+8.3 MII Monitor Operation
+-------------------------
 
-	In round-robin and XOR mode, it works with systems that support
-	trunking:
+	The MII monitor monitors only the carrier state of the local
+network interface.  It accomplishes this in one of three ways: by
+depending upon the device driver to maintain its carrier state, by
+querying the device's MII registers, or by making an ethtool query to
+the device.
+
+	If the use_carrier module parameter is 1 (the default value),
+then the MII monitor will rely on the driver for carrier state
+information (via the netif_carrier subsystem).  As explained in the
+use_carrier parameter information, above, if the MII monitor fails to
+detect carrier loss on the device (e.g., when the cable is physically
+disconnected), it may be that the driver does not support
+netif_carrier.
+
+	If use_carrier is 0, then the MII monitor will first query the
+device's (via ioctl) MII registers and check the link state.  If that
+request fails (not just that it returns carrier down), then the MII
+monitor will make an ethtool ETHOOL_GLINK request to attempt to obtain
+the same information.  If both methods fail (i.e., the driver either
+does not support or had some error in processing both the MII register
+and ethtool requests), then the MII monitor will assume the link is
+up.
 
-	* Many Cisco switches and routers (look for EtherChannel support).
-	* SunTrunking software.
-	* Alteon AceDirector switches / WebOS (use Trunks).
-	* BayStack Switches (trunks must be explicitly configured). Stackable
-	  models (450) can define trunks between ports on different physical
-	  units.
-	* Linux bonding, of course !
-
-	In 802.3ad mode, it works with with systems that support IEEE 802.3ad
-	Dynamic Link Aggregation:
-
-	* Extreme networks Summit 7i (look for link-aggregation).
-	* Many Cisco switches and routers (look for LACP support; this may
-	  require an upgrade to your IOS software; LACP support was added
-	  by Cisco in late 2002).
-	* Foundry Big Iron 4000
+9. Potential Sources of Trouble
+===============================
 
-        In active-backup, balance-tlb and balance-alb modes, it should work
-        with any Layer-II switch.
+9.1 Adventures in Routing
+-------------------------
 
+	When bonding is configured, it is important that the slave
+devices not have routes that supercede routes of the master (or,
+generally, not have routes at all).  For example, suppose the bonding
+device bond0 has two slaves, eth0 and eth1, and the routing table is
+as follows:
 
-8.  Where does a bonding device get its MAC address from?
+Kernel IP routing table
+Destination     Gateway         Genmask         Flags   MSS Window  irtt Iface
+10.0.0.0        0.0.0.0         255.255.0.0     U        40 0          0 eth0
+10.0.0.0        0.0.0.0         255.255.0.0     U        40 0          0 eth1
+10.0.0.0        0.0.0.0         255.255.0.0     U        40 0          0 bond0
+127.0.0.0       0.0.0.0         255.0.0.0       U        40 0          0 lo
 
-	If not explicitly configured with ifconfig, the MAC address of the
-	bonding device is taken from its first slave device. This MAC address
-	is then passed to all following slaves and remains persistent (even if
-	the the first slave is removed) until the bonding device is brought
-	down or reconfigured.
+	This routing configuration will likely still update the
+receive/transmit times in the driver (needed by the ARP monitor), but
+may bypass the bonding driver (because outgoing traffic to, in this
+case, another host on network 10 would use eth0 or eth1 before bond0).
+
+	The ARP monitor (and ARP itself) may become confused by this
+configuration, because ARP requests (generated by the ARP monitor)
+will be sent on one interface (bond0), but the corresponding reply
+will arrive on a different interface (eth0).  This reply looks to ARP
+as an unsolicited ARP reply (because ARP matches replies on an
+interface basis), and is discarded.  The MII monitor is not affected
+by the state of the routing table.
+
+	The solution here is simply to insure that slaves do not have
+routes of their own, and if for some reason they must, those routes do
+not supercede routes of their master.  This should generally be the
+case, but unusual configurations or errant manual or automatic static
+route additions may cause trouble.
 
-	If you wish to change the MAC address, you can set it with ifconfig:
+9.2 Ethernet Device Renaming
+----------------------------
 
-	  # ifconfig bond0 hw ether 00:11:22:33:44:55
+	On systems with network configuration scripts that do not
+associate physical devices directly with network interface names (so
+that the same physical device always has the same "ethX" name), it may
+be necessary to add some special logic to either /etc/modules.conf or
+/etc/modprobe.conf (depending upon which is installed on the system).
 
-	The MAC address can be also changed by bringing down/up the device
-	and then changing its slaves (or their order):
+	For example, given a modules.conf containing the following:
 
-	  # ifconfig bond0 down ; modprobe -r bonding
-	  # ifconfig bond0 .... up
-	  # ifenslave bond0 eth...
+alias bond0 bonding
+options bond0 mode=some-mode miimon=50
+alias eth0 tg3
+alias eth1 tg3
+alias eth2 e1000
+alias eth3 e1000
+
+	If neither eth0 and eth1 are slaves to bond0, then when the
+bond0 interface comes up, the devices may end up reordered.  This
+happens because bonding is loaded first, then its slave device's
+drivers are loaded next.  Since no other drivers have been loaded,
+when the e1000 driver loads, it will receive eth0 and eth1 for its
+devices, but the bonding configuration tries to enslave eth2 and eth3
+(which may later be assigned to the tg3 devices).
+
+	Adding the following:
+
+add above bonding e1000 tg3
+
+	causes modprobe to load e1000 then tg3, in that order, when
+bonding is loaded.  This command is fully documented in the
+modules.conf manual page.
+
+	On systems utilizing modprobe.conf (or modprobe.conf.local),
+an equivalent problem can occur.  In this case, the following can be
+added to modprobe.conf (or modprobe.conf.local, as appropriate), as
+follows (all on one line; it has been split here for clarity):
+
+install bonding /sbin/modprobe tg3; /sbin/modprobe e1000;
+	/sbin/modprobe --ignore-install bonding
+
+	This will, when loading the bonding module, rather than
+performing the normal action, instead execute the provided command.
+This command loads the device drivers in the order needed, then calls
+modprobe with --ingore-install to cause the normal action to then take
+place.  Full documentation on this can be found in the modprobe.conf
+and modprobe manual pages.
+
+9.3. Painfully Slow Or No Failed Link Detection By Miimon
+---------------------------------------------------------
+
+	By default, bonding enables the use_carrier option, which
+instructs bonding to trust the driver to maintain carrier state.
+
+	As discussed in the options section, above, some drivers do
+not support the netif_carrier_on/_off link state tracking system.
+With use_carrier enabled, bonding will always see these links as up,
+regardless of their actual state.
+
+	Additionally, other drivers do support netif_carrier, but do
+not maintain it in real time, e.g., only polling the link state at
+some fixed interval.  In this case, miimon will detect failures, but
+only after some long period of time has expired.  If it appears that
+miimon is very slow in detecting link failures, try specifying
+use_carrier=0 to see if that improves the failure detection time.  If
+it does, then it may be that the driver checks the carrier state at a
+fixed interval, but does not cache the MII register values (so the
+use_carrier=0 method of querying the registers directly works).  If
+use_carrier=0 does not improve the failover, then the driver may cache
+the registers, or the problem may be elsewhere.
+
+	Also, remember that miimon only checks for the device's
+carrier state.  It has no way to determine the state of devices on or
+beyond other ports of a switch, or if a switch is refusing to pass
+traffic while still maintaining carrier on.
+
+10. SNMP agents
+===============
+
+	If running SNMP agents, the bonding driver should be loaded
+before any network drivers participating in a bond.  This requirement
+is due to the the interface index (ipAdEntIfIndex) being associated to
+the first interface found with a given IP address.  That is, there is
+only one ipAdEntIfIndex for each IP address.  For example, if eth0 and
+eth1 are slaves of bond0 and the driver for eth0 is loaded before the
+bonding driver, the interface for the IP address will be associated
+with the eth0 interface.  This configuration is shown below, the IP
+address 192.168.1.1 has an interface index of 2 which indexes to eth0
+in the ifDescr table (ifDescr.2).
 
-	This method will automatically take the address from the next slave
-	that will be added.
+     interfaces.ifTable.ifEntry.ifDescr.1 = lo
+     interfaces.ifTable.ifEntry.ifDescr.2 = eth0
+     interfaces.ifTable.ifEntry.ifDescr.3 = eth1
+     interfaces.ifTable.ifEntry.ifDescr.4 = eth2
+     interfaces.ifTable.ifEntry.ifDescr.5 = eth3
+     interfaces.ifTable.ifEntry.ifDescr.6 = bond0
+     ip.ipAddrTable.ipAddrEntry.ipAdEntIfIndex.10.10.10.10 = 5
+     ip.ipAddrTable.ipAddrEntry.ipAdEntIfIndex.192.168.1.1 = 2
+     ip.ipAddrTable.ipAddrEntry.ipAdEntIfIndex.10.74.20.94 = 4
+     ip.ipAddrTable.ipAddrEntry.ipAdEntIfIndex.127.0.0.1 = 1
 
-	To restore your slaves' MAC addresses, you need to detach them
-	from the bond (`ifenslave -d bond0 eth0'). The bonding driver will then
-	restore the MAC addresses that the slaves had before they were enslaved.
+	This problem is avoided by loading the bonding driver before
+any network drivers participating in a bond.  Below is an example of
+loading the bonding driver first, the IP address 192.168.1.1 is
+correctly associated with ifDescr.2.
 
-9.  Which transmit polices can be used?
+     interfaces.ifTable.ifEntry.ifDescr.1 = lo
+     interfaces.ifTable.ifEntry.ifDescr.2 = bond0
+     interfaces.ifTable.ifEntry.ifDescr.3 = eth0
+     interfaces.ifTable.ifEntry.ifDescr.4 = eth1
+     interfaces.ifTable.ifEntry.ifDescr.5 = eth2
+     interfaces.ifTable.ifEntry.ifDescr.6 = eth3
+     ip.ipAddrTable.ipAddrEntry.ipAdEntIfIndex.10.10.10.10 = 6
+     ip.ipAddrTable.ipAddrEntry.ipAdEntIfIndex.192.168.1.1 = 2
+     ip.ipAddrTable.ipAddrEntry.ipAdEntIfIndex.10.74.20.94 = 5
+     ip.ipAddrTable.ipAddrEntry.ipAdEntIfIndex.127.0.0.1 = 1
 
-	Round-robin, based on the order of enslaving, the output device
-	is selected base on the next available slave. Regardless of
-	the source and/or destination of the packet.
+	While some distributions may not report the interface name in
+ifDescr, the association between the IP address and IfIndex remains
+and SNMP functions such as Interface_Scan_Next will report that
+association.
 
-	Active-backup policy that ensures that one and only one device will
-	transmit at any given moment. Active-backup policy is useful for
-	implementing high availability solutions using two hubs (see
-	section on High Availability).
+11. Promiscuous mode
+====================
 
-	XOR, based on (src hw addr XOR dst hw addr) % slave count. This
-	policy selects the same slave for each destination hw address.
+	When running network monitoring tools, e.g., tcpdump, it is
+common to enable promiscuous mode on the device, so that all traffic
+is seen (instead of seeing only traffic destined for the local host).
+The bonding driver handles promiscuous mode changes to the bonding
+master device (e.g., bond0), and propogates the setting to the slave
+devices.
+
+	For the balance-rr, balance-xor, broadcast, and 802.3ad modes,
+the promiscuous mode setting is propogated to all slaves.
+
+	For the active-backup, balance-tlb and balance-alb modes, the
+promiscuous mode setting is propogated only to the active slave.
+
+	For balance-tlb mode, the active slave is the slave currently
+receiving inbound traffic.
+
+	For balance-alb mode, the active slave is the slave used as a
+"primary."  This slave is used for mode-specific control traffic, for
+sending to peers that are unassigned or if the load is unbalanced.
+
+	For the active-backup, balance-tlb and balance-alb modes, when
+the active slave changes (e.g., due to a link failure), the
+promiscuous setting will be propogated to the new active slave.
+
+12. High Availability Information
+=================================
+
+	High Availability refers to configurations that provide
+maximum network availability by having redundant or backup devices,
+links and switches between the host and the rest of the world.
+
+	There are currently two basic methods for configuring to
+maximize availability. They are dependent on the network topology and
+the primary goal of the configuration, but in general, a configuration
+can be optimized for maximum available bandwidth, or for maximum
+network availability.
+
+12.1 High Availability in a Single Switch Topology
+--------------------------------------------------
+
+	If two hosts (or a host and a switch) are directly connected
+via multiple physical links, then there is no network availability
+penalty for optimizing for maximum bandwidth: there is only one switch
+(or peer), so if it fails, you have no alternative access to fail over
+to.
 
-	Broadcast policy transmits everything on all slave interfaces.
+Example 1 : host to switch (or other host)
 
-	802.3ad, based on XOR but distributes traffic among all interfaces
-	in the active aggregator.
+          +----------+                          +----------+
+          |          |eth0                  eth0|  switch  |
+          | Host A   +--------------------------+    or    |
+          |          +--------------------------+  other   |
+          |          |eth1                  eth1|  host    |
+          +----------+                          +----------+
 
-	Transmit load balancing (balance-tlb) balances the traffic
-	according to the current load on each slave. The balancing is
-	clients based and the least loaded slave is selected for each new
-	client. The load of each slave is calculated relative to its speed
-	and enables load balancing in mixed speed teams.
 
-	Adaptive load balancing (balance-alb) uses the Transmit load
-	balancing for the transmit load. The receive load is balanced only
-	among the group of highest speed active slaves in the bond. The
-	load is distributed with round-robin i.e. next available slave in
-	the high speed group of active slaves.
+12.1.1 Bonding Mode Selection for single switch topology
+--------------------------------------------------------
 
-High Availability
-=================
+	This configuration is the easiest to set up and to understand,
+although you will have to decide which bonding mode best suits your
+needs.  The tradeoffs for each mode are detailed below:
+
+balance-rr: This mode is the only mode that will permit a single
+	TCP/IP connection to stripe traffic across multiple
+	interfaces. It is therefore the only mode that will allow a
+	single TCP/IP stream to utilize more than one interface's
+	worth of throughput.  This comes at a cost, however: the
+	striping often results in peer systems receiving packets out
+	of order, causing TCP/IP's congestion control system to kick
+	in, often by retransmitting segments.
+
+	It is possible to adjust TCP/IP's congestion limits by
+	altering the net.ipv4.tcp_reordering sysctl parameter.  The
+	usual default value is 3, and the maximum useful value is 127.
+	For a four interface balance-rr bond, expect that a single
+	TCP/IP stream will utilize no more than approximately 2.3
+	interface's worth of throughput, even after adjusting
+	tcp_reordering.
+
+	If you are utilizing protocols other than TCP/IP, UDP for
+	example, and your application can tolerate out of order
+	delivery, then this mode can allow for single stream datagram
+	performance that scales near linearly as interfaces are added
+	to the bond.
+
+	This mode requires the switch to have the appropriate ports
+	configured for "etherchannel" or "trunking."
+
+active-backup: There is not much advantage in this network topology to
+	the active-backup mode, as the inactive backup devices are all
+	connected to the same peer as the primary.  In this case, a
+	load balancing mode (with link monitoring) will provide the
+	same level of network availability, but with increased
+	available bandwidth.  On the plus side, it does not require
+	any configuration of the switch.
+
+balance-xor: This mode will limit traffic such that packets destined
+	for specific peers will always be sent over the same
+	interface.  Since the destination is determined by the MAC
+	addresses involved, this may be desirable if you have a large
+	network with many hosts.  It is likely to be suboptimal if all
+	your traffic is passed through a single router, however.  As
+	with balance-rr, the switch ports need to be configured for
+	"etherchannel" or "trunking."
+
+broadcast: Like active-backup, there is not much advantage to this
+	mode in this type of network topology.
+
+802.3ad: This mode can be a good choice for this type of network
+	topology.  The 802.3ad mode is an IEEE standard, so all peers
+	that implement 802.3ad should interoperate well.  The 802.3ad
+	protocol includes automatic configuration of the aggregates,
+	so minimal manual configuration of the switch is needed
+	(typically only to designate that some set of devices is
+	usable for 802.3ad).  The 802.3ad standard also mandates that
+	frames be delivered in order (within certain limits), so in
+	general single connections will not see misordering of
+	packets.  The 802.3ad mode does have some drawbacks: the
+	standard mandates that all devices in the aggregate operate at
+	the same speed and duplex.  Also, as with all bonding load
+	balance modes other than balance-rr, no single connection will
+	be able to utilize more than a single interface's worth of
+	bandwidth.  Additionally, the linux bonding 802.3ad
+	implementation distributes traffic by peer (using an XOR of
+	MAC addresses), so in general all traffic to a particular
+	destination will use the same interface.  Finally, the 802.3ad
+	mode mandates the use of the MII monitor, therefore, the ARP
+	monitor is not available in this mode.
+
+balance-tlb: This mode is also a good choice for this type of
+	topology.  It has no special switch configuration
+	requirements, and balances outgoing traffic by peer, in a
+	vaguely intelligent manner (not a simple XOR as in balance-xor
+	or 802.3ad mode), so that unlucky MAC addresses will not all
+	"bunch up" on a single interface.  Interfaces may be of
+	differing speeds.  On the down side, in this mode all incoming
+	traffic arrives over a single interface, this mode requires
+	certain ethtool support in the network device driver of the
+	slave interfaces, and the ARP monitor is not available.
+
+balance-alb: This mode is everything that balance-tlb is, and more. It
+	has all of the features (and restrictions) of balance-tlb, and
+	will also balance incoming traffic from peers (as described in
+	the Bonding Module Options section, above).  The only extra
+	down side to this mode is that the network device driver must
+	support changing the hardware address while the device is
+	open.
+
+12.1.2 Link Monitoring for Single Switch Topology
+-------------------------------------------------
+
+	The choice of link monitoring may largely depend upon which
+mode you choose to use.  The more advanced load balancing modes do not
+support the use of the ARP monitor, and are thus restricted to using
+the MII monitor (which does not provide as high a level of assurance
+as the ARP monitor).
+
+
+12.2 High Availability in a Multiple Switch Topology
+----------------------------------------------------
+
+	With multiple switches, the configuration of bonding and the
+network changes dramatically.  In multiple switch topologies, there is
+a tradeoff between network availability and usable bandwidth.
 
-To implement high availability using the bonding driver, the driver needs to be
-compiled as a module, because currently it is the only way to pass parameters
-to the driver. This may change in the future.
-
-High availability is achieved by using MII or ETHTOOL status reporting. You
-need to verify that all your interfaces support MII or ETHTOOL link status
-reporting.  On Linux kernel 2.2.17, all the 100 Mbps capable drivers and
-yellowfin gigabit driver support MII. To determine if ETHTOOL link reporting
-is available for interface eth0, type "ethtool eth0" and the "Link detected:"
-line should contain the correct link status. If your system has an interface
-that does not support MII or ETHTOOL status reporting, a failure of its link
-will not be detected! A message indicating MII and ETHTOOL is not supported by
-a network driver is logged when the bonding driver is loaded with a non-zero
-miimon value.
-
-The bonding driver can regularly check all its slaves links using the ETHTOOL
-IOCTL (ETHTOOL_GLINK command) or by checking the MII status registers. The
-check interval is specified by the module argument "miimon" (MII monitoring).
-It takes an integer that represents the checking time in milliseconds. It
-should not come to close to (1000/HZ) (10 milli-seconds on i386) because it
-may then reduce the system interactivity. A value of 100 seems to be a good
-starting point. It means that a dead link will be detected at most 100
-milli-seconds after it goes down.
-
-Example:
-
-   # modprobe bonding miimon=100
-
-Or, put the following line in /etc/modprobe.conf:
-
-   options bond0 miimon=100
-
-There are currently two policies for high availability. They are dependent on
-whether:
-
-   a) hosts are connected to a single host or switch that support trunking
-
-   b) hosts are connected to several different switches or a single switch that
-      does not support trunking
-
-
-1) High Availability on a single switch or host - load balancing
-----------------------------------------------------------------
-It is the easiest to set up and to understand. Simply configure the
-remote equipment (host or switch) to aggregate traffic over several
-ports (Trunk, EtherChannel, etc.) and configure the bonding interfaces.
-If the module has been loaded with the proper MII option, it will work
-automatically. You can then try to remove and restore different links
-and see in your logs what the driver detects. When testing, you may
-encounter problems on some buggy switches that disable the trunk for a
-long time if all ports in a trunk go down. This is not Linux, but really
-the switch (reboot it to ensure).
+	Below is a sample network, configured to maximize the
+availability of the network:
 
-Example 1 : host to host at twice the speed
+                |                                     |
+                |port3                           port3|
+          +-----+----+                          +-----+----+
+          |          |port2       ISL      port2|          |
+          | switch A +--------------------------+ switch B |
+          |          |                          |          |
+          +-----+----+                          +-----++---+
+                |port1                           port1|
+                |             +-------+               |
+                +-------------+ host1 +---------------+
+                         eth0 +-------+ eth1
 
-          +----------+                          +----------+
-          |          |eth0                  eth0|          |
-          | Host A   +--------------------------+  Host B  |
-          |          +--------------------------+          |
-          |          |eth1                  eth1|          |
-          +----------+                          +----------+
+	In this configuration, there is a link between the two
+switches (ISL, or inter switch link), and multiple ports connecting to
+the outside world ("port3" on each switch).  There is no technical
+reason that this could not be extended to a third switch.
+
+12.2.1 Bonding Mode Selection for Multiple Switch Topology
+----------------------------------------------------------
+
+	In a topology such as this, the active-backup and broadcast
+modes are the only useful bonding modes; the other modes require all
+links to terminate on the same peer for them to behave rationally.
+
+active-backup: This is generally the preferred mode, particularly if
+	the switches have an ISL and play together well.  If the
+	network configuration is such that one switch is specifically
+	a backup switch (e.g., has lower capacity, higher cost, etc),
+	then the primary option can be used to insure that the
+	preferred link is always used when it is available.
+
+broadcast: This mode is really a special purpose mode, and is suitable
+	only for very specific needs.  For example, if the two
+	switches are not connected (no ISL), and the networks beyond
+	them are totally independant.  In this case, if it is
+	necessary for some specific one-way traffic to reach both
+	independent networks, then the broadcast mode may be suitable.
+
+12.2.2 Link Monitoring Selection for Multiple Switch Topology
+-------------------------------------------------------------
+
+	The choice of link monitoring ultimately depends upon your
+switch.  If the switch can reliably fail ports in response to other
+failures, then either the MII or ARP monitors should work.  For
+example, in the above example, if the "port3" link fails at the remote
+end, the MII monitor has no direct means to detect this.  The ARP
+monitor could be configured with a target at the remote end of port3,
+thus detecting that failure without switch support.
+
+	In general, however, in a multiple switch topology, the ARP
+monitor can provide a higher level of reliability in detecting link
+failures.  Additionally, it should be configured with multiple targets
+(at least one for each switch in the network).  This will insure that,
+regardless of which switch is active, the ARP monitor has a suitable
+target to query.
+
+
+12.3 Switch Behavior Issues for High Availability
+-------------------------------------------------
+
+	You may encounter issues with the timing of link up and down
+reporting by the switch.
+
+	First, when a link comes up, some switches may indicate that
+the link is up (carrier available), but not pass traffic over the
+interface for some period of time.  This delay is typically due to
+some type of autonegotiation or routing protocol, but may also occur
+during switch initialization (e.g., during recovery after a switch
+failure).  If you find this to be a problem, specify an appropriate
+value to the updelay bonding module option to delay the use of the
+relevant interface(s).
+
+	Second, some switches may "bounce" the link state one or more
+times while a link is changing state.  This occurs most commonly while
+the switch is initializing.  Again, an appropriate updelay value may
+help, but note that if all links are down, then updelay is ignored
+when any link becomes active (the slave closest to completing its
+updelay is chosen).
+
+	Note that when a bonding interface has no active links, the
+driver will immediately reuse the first link that goes up, even if
+updelay parameter was specified.  If there are slave interfaces
+waiting for the updelay timeout to expire, the interface that first
+went into that state will be immediately reused.  This reduces down
+time of the network if the value of updelay has been overestimated.
+
+	In addition to the concerns about switch timings, if your
+switches take a long time to go into backup mode, it may be desirable
+to not activate a backup interface immediately after a link goes down.
+Failover may be delayed via the downdelay bonding module option.
+
+13. Hardware Specific Considerations
+====================================
+
+	This section contains additional information for configuring
+bonding on specific hardware platforms, or for interfacing bonding
+with particular switches or other devices.
+
+13.1 IBM BladeCenter
+--------------------
+
+	This applies to the JS20 and similar systems.
+
+	On the JS20 blades, the bonding driver supports only
+balance-rr, active-backup, balance-tlb and balance-alb modes.  This is
+largely due to the network topology inside the BladeCenter, detailed
+below.
+
+JS20 network adapter information
+--------------------------------
+
+	All JS20s come with two Broadcom Gigabit Ethernet ports
+integrated on the planar.  In the BladeCenter chassis, the eth0 port
+of all JS20 blades is hard wired to I/O Module #1; similarly, all eth1
+ports are wired to I/O Module #2.  An add-on Broadcom daughter card
+can be installed on a JS20 to provide two more Gigabit Ethernet ports.
+These ports, eth2 and eth3, are wired to I/O Modules 3 and 4,
+respectively.
+
+	Each I/O Module may contain either a switch or a passthrough
+module (which allows ports to be directly connected to an external
+switch).  Some bonding modes require a specific BladeCenter internal
+network topology in order to function; these are detailed below.
 
-  On each host :
-     # modprobe bonding miimon=100
-     # ifconfig bond0 addr
-     # ifenslave bond0 eth0 eth1
+	Additional BladeCenter-specific networking information can be
+found in two IBM Redbooks (www.ibm.com/redbooks):
 
-Example 2 : host to switch at twice the speed
+"IBM eServer BladeCenter Networking Options"
+"IBM eServer BladeCenter Layer 2-7 Network Switching"
 
-          +----------+                          +----------+
-          |          |eth0                 port1|          |
-          | Host A   +--------------------------+  switch  |
-          |          +--------------------------+          |
-          |          |eth1                 port2|          |
-          +----------+                          +----------+
+BladeCenter networking configuration
+------------------------------------
 
-  On host A :                             On the switch :
-     # modprobe bonding miimon=100           # set up a trunk on port1
-     # ifconfig bond0 addr                     and port2
-     # ifenslave bond0 eth0 eth1
+	Because a BladeCenter can be configured in a very large number
+of ways, this discussion will be confined to describing basic
+configurations.
+
+	Normally, Ethernet Switch Modules (ESM) are used in I/O
+modules 1 and 2.  In this configuration, the eth0 and eth1 ports of a
+JS20 will be connected to different internal switches (in the
+respective I/O modules).
+
+	An optical passthru module (OPM) connects the I/O module
+directly to an external switch.  By using OPMs in I/O module #1 and
+#2, the eth0 and eth1 interfaces of a JS20 can be redirected to the
+outside world and connected to a common external switch.
+
+	Depending upon the mix of ESM and OPM modules, the network
+will appear to bonding as either a single switch topology (all OPM
+modules) or as a multiple switch topology (one or more ESM modules,
+zero or more OPM modules).  It is also possible to connect ESM modules
+together, resulting in a configuration much like the example in "High
+Availability in a multiple switch topology."
+
+Requirements for specifc modes
+------------------------------
+
+	The balance-rr mode requires the use of OPM modules for
+devices in the bond, all connected to an common external switch.  That
+switch must be configured for "etherchannel" or "trunking" on the
+appropriate ports, as is usual for balance-rr.
+
+	The balance-alb and balance-tlb modes will function with
+either switch modules or passthrough modules (or a mix).  The only
+specific requirement for these modes is that all network interfaces
+must be able to reach all destinations for traffic sent over the
+bonding device (i.e., the network must converge at some point outside
+the BladeCenter).
+
+	The active-backup mode has no additional requirements.
+
+Link monitoring issues
+----------------------
+
+	When an Ethernet Switch Module is in place, only the ARP
+monitor will reliably detect link loss to an external switch.  This is
+nothing unusual, but examination of the BladeCenter cabinet would
+suggest that the "external" network ports are the ethernet ports for
+the system, when it fact there is a switch between these "external"
+ports and the devices on the JS20 system itself.  The MII monitor is
+only able to detect link failures between the ESM and the JS20 system.
+
+	When a passthrough module is in place, the MII monitor does
+detect failures to the "external" port, which is then directly
+connected to the JS20 system.
+
+Other concerns
+--------------
+
+	The Serial Over LAN link is established over the primary
+ethernet (eth0) only, therefore, any loss of link to eth0 will result
+in losing your SoL connection.  It will not fail over with other
+network traffic.
+
+	It may be desirable to disable spanning tree on the switch
+(either the internal Ethernet Switch Module, or an external switch) to
+avoid fail-over delays issues when using bonding.
+
+	
+14. Frequently Asked Questions
+==============================
 
+1.  Is it SMP safe?
 
-2) High Availability on two or more switches (or a single switch without
-   trunking support)
----------------------------------------------------------------------------
-This mode is more problematic because it relies on the fact that there
-are multiple ports and the host's MAC address should be visible on one
-port only to avoid confusing the switches.
+	Yes. The old 2.0.xx channel bonding patch was not SMP safe.
+The new driver was designed to be SMP safe from the start.
 
-If you need to know which interface is the active one, and which ones are
-backup, use ifconfig. All backup interfaces have the NOARP flag set.
+2.  What type of cards will work with it?
 
-To use this mode, pass "mode=1" to the module at load time :
+	Any Ethernet type cards (you can even mix cards - a Intel
+EtherExpress PRO/100 and a 3com 3c905b, for example).  They need not
+be of the same speed.
 
-    # modprobe bonding miimon=100 mode=active-backup
+3.  How many bonding devices can I have?
 
-	or:
+	There is no limit.
 
-    # modprobe bonding miimon=100 mode=1
+4.  How many slaves can a bonding device have?
 
-Or, put in your /etc/modprobe.conf :
+	This is limited only by the number of network interfaces Linux
+supports and/or the number of network cards you can place in your
+system.
 
-    options bond0 miimon=100 mode=active-backup
+5.  What happens when a slave link dies?
 
-Example 1: Using multiple host and multiple switches to build a "no single
-point of failure" solution.
+	If link monitoring is enabled, then the failing device will be
+disabled.  The active-backup mode will fail over to a backup link, and
+other modes will ignore the failed link.  The link will continue to be
+monitored, and should it recover, it will rejoin the bond (in whatever
+manner is appropriate for the mode). See the section on High
+Availability for additional information.
+	
+	Link monitoring can be enabled via either the miimon or
+arp_interval paramters (described in the module paramters section,
+above).  In general, miimon monitors the carrier state as sensed by
+the underlying network device, and the arp monitor (arp_interval)
+monitors connectivity to another host on the local network.
+
+	If no link monitoring is configured, the bonding driver will
+be unable to detect link failures, and will assume that all links are
+always available.  This will likely result in lost packets, and a
+resulting degredation of performance.  The precise performance loss
+depends upon the bonding mode and network configuration.
 
+6.  Can bonding be used for High Availability?
 
-                |                                     |
-                |port3                           port3|
-          +-----+----+                          +-----+----+
-          |          |port7       ISL      port7|          |
-          | switch A +--------------------------+ switch B |
-          |          +--------------------------+          |
-          |          |port8                port8|          |
-          +----++----+                          +-----++---+
-          port2||port1                           port1||port2
-               ||             +-------+               ||
-               |+-------------+ host1 +---------------+|
-               |         eth0 +-------+ eth1           |
-               |                                       |
-               |              +-------+                |
-               +--------------+ host2 +----------------+
-                         eth0 +-------+ eth1
+	Yes.  See the section on High Availability for details.
 
-In this configuration, there is an ISL - Inter Switch Link (could be a trunk),
-several servers (host1, host2 ...) attached to both switches each, and one or
-more ports to the outside world (port3...). One and only one slave on each host
-is active at a time, while all links are still monitored (the system can
-detect a failure of active and backup links).
-
-Each time a host changes its active interface, it sticks to the new one until
-it goes down. In this example, the hosts are negligibly affected by the
-expiration time of the switches' forwarding tables.
-
-If host1 and host2 have the same functionality and are used in load balancing
-by another external mechanism, it is good to have host1's active interface
-connected to one switch and host2's to the other. Such system will survive
-a failure of a single host, cable, or switch. The worst thing that may happen
-in the case of a switch failure is that half of the hosts will be temporarily
-unreachable until the other switch expires its tables.
+7.  Which switches/systems does it work with?
 
-Example 2: Using multiple ethernet cards connected to a switch to configure
-           NIC failover (switch is not required to support trunking).
+	The full answer to this depends upon the desired mode.
 
+	In the basic balance modes (balance-rr and balance-xor), it
+works with any system that supports etherchannel (also called
+trunking).  Most managed switches currently available have such
+support, and many unmananged switches as well.
+
+	The advanced balance modes (balance-tlb and balance-alb) do
+not have special switch requirements, but do need device drivers that
+support specific features (described in the appropriate section under
+module paramters, above).
+
+	In 802.3ad mode, it works with with systems that support IEEE
+802.3ad Dynamic Link Aggregation.  Most managed and many unmanaged
+switches currently available support 802.3ad.
 
-          +----------+                          +----------+
-          |          |eth0                 port1|          |
-          | Host A   +--------------------------+  switch  |
-          |          +--------------------------+          |
-          |          |eth1                 port2|          |
-          +----------+                          +----------+
+        The active-backup mode should work with any Layer-II switch.
 
-  On host A :                                 On the switch :
-     # modprobe bonding miimon=100 mode=1     # (optional) minimize the time
-     # ifconfig bond0 addr                    # for table expiration
-     # ifenslave bond0 eth0 eth1
+8.  Where does a bonding device get its MAC address from?
 
-Each time the host changes its active interface, it sticks to the new one until
-it goes down. In this example, the host is strongly affected by the expiration
-time of the switch forwarding table.
+	If not explicitly configured with ifconfig, the MAC address of
+the bonding device is taken from its first slave device. This MAC
+address is then passed to all following slaves and remains persistent
+(even if the the first slave is removed) until the bonding device is
+brought down or reconfigured.
+
+	If you wish to change the MAC address, you can set it with
+ifconfig:
+
+# ifconfig bond0 hw ether 00:11:22:33:44:55
+
+	The MAC address can be also changed by bringing down/up the
+device and then changing its slaves (or their order):
+
+# ifconfig bond0 down ; modprobe -r bonding
+# ifconfig bond0 .... up
+# ifenslave bond0 eth...
 
+	This method will automatically take the address from the next
+slave that is added.
 
-3) Adapting to your switches' timing
-------------------------------------
-If your switches take a long time to go into backup mode, it may be
-desirable not to activate a backup interface immediately after a link goes
-down. It is possible to delay the moment at which a link will be
-completely disabled by passing the module parameter "downdelay" (in
-milliseconds, must be a multiple of miimon).
-
-When a switch reboots, it is possible that its ports report "link up" status
-before they become usable. This could fool a bond device by causing it to
-use some ports that are not ready yet. It is possible to delay the moment at
-which an active link will be reused by passing the module parameter "updelay"
-(in milliseconds, must be a multiple of miimon).
-
-A similar situation can occur when a host re-negotiates a lost link with the
-switch (a case of cable replacement).
-
-A special case is when a bonding interface has lost all slave links. Then the
-driver will immediately reuse the first link that goes up, even if updelay
-parameter was specified. (If there are slave interfaces in the "updelay" state,
-the interface that first went into that state will be immediately reused.) This
-allows to reduce down-time if the value of updelay has been overestimated.
-
-Examples :
-
-    # modprobe bonding miimon=100 mode=1 downdelay=2000 updelay=5000
-    # modprobe bonding miimon=100 mode=balance-rr downdelay=0 updelay=5000
-
-
-Promiscuous Sniffing notes
-==========================
-
-If you wish to bond channels together for a network sniffing
-application --- you wish to run tcpdump, or ethereal, or an IDS like
-snort, with its input aggregated from multiple interfaces using the
-bonding driver --- then you need to handle the Promiscuous interface
-setting by hand. Specifically, when you "ifconfing bond0 up" you
-must add the promisc flag there; it will be propagated down to the
-slave interfaces at ifenslave time; a full example might look like:
-
-   ifconfig bond0 promisc up
-   for if in eth1 eth2 ...;do
-       ifconfig $if up
-       ifenslave bond0 $if
-   done
-   snort ... -i bond0 ...
-
-Ifenslave also wants to propagate addresses from interface to
-interface, appropriately for its design functions in HA and channel
-capacity aggregating; but it works fine for unnumbered interfaces;
-just ignore all the warnings it emits.
+	To restore your slaves' MAC addresses, you need to detach them
+from the bond (`ifenslave -d bond0 eth0'). The bonding driver will
+then restore the MAC addresses that the slaves had before they were
+enslaved.
 
+15. Resources and Links
+=======================
 
-8021q VLAN support
-==================
+The latest version of the bonding driver can be found in the latest
+version of the linux kernel, found on http://kernel.org
 
-It is possible to configure VLAN devices over a bond interface using the 8021q
-driver. However, only packets coming from the 8021q driver and passing through
-bonding will be tagged by default. Self generated packets, like bonding's
-learning packets or ARP packets generated by either ALB mode or the ARP
-monitor mechanism, are tagged internally by bonding itself. As a result,
-bonding has to "learn" what VLAN IDs are configured on top of it, and it uses
-those IDs to tag self generated packets.
-
-For simplicity reasons, and to support the use of adapters that can do VLAN
-hardware acceleration offloding, the bonding interface declares itself as
-fully hardware offloaing capable, it gets the add_vid/kill_vid notifications
-to gather the necessary information, and it propagates those actions to the
-slaves.
-In case of mixed adapter types, hardware accelerated tagged packets that should
-go through an adapter that is not offloading capable are "un-accelerated" by the
-bonding driver so the VLAN tag sits in the regular location.
-
-VLAN interfaces *must* be added on top of a bonding interface only after
-enslaving at least one slave. This is because until the first slave is added the
-bonding interface has a HW address of 00:00:00:00:00:00, which will be copied by
-the VLAN interface when it is created.
-
-Notice that a problem would occur if all slaves are released from a bond that
-still has VLAN interfaces on top of it. When later coming to add new slaves, the
-bonding interface would get a HW address from the first slave, which might not
-match that of the VLAN interfaces. It is recommended that either all VLANs are
-removed and then re-added, or to manually set the bonding interface's HW
-address so it matches the VLAN's. (Note: changing a VLAN interface's HW address
-would set the underlying device -- i.e. the bonding interface -- to promiscouos
-mode, which might not be what you want).
-
-
-Limitations
-===========
-The main limitations are :
-  - only the link status is monitored. If the switch on the other side is
-    partially down (e.g. doesn't forward anymore, but the link is OK), the link
-    won't be disabled. Another way to check for a dead link could be to count
-    incoming frames on a heavily loaded host. This is not applicable to small
-    servers, but may be useful when the front switches send multicast
-    information on their links (e.g. VRRP), or even health-check the servers.
-    Use the arp_interval/arp_ip_target parameters to count incoming/outgoing
-    frames.
+Discussions regarding the bonding driver take place primarily on the
+bonding-devel mailing list, hosted at sourceforge.net.  If you have
+questions or problems, post them to the list.
 
+bonding-devel@lists.sourceforge.net
 
+https://lists.sourceforge.net/lists/listinfo/bonding-devel
 
-Resources and Links
-===================
+There is also a project site on sourceforge.
 
-Current development on this driver is posted to:
- - http://www.sourceforge.net/projects/bonding/
+http://www.sourceforge.net/projects/bonding
 
 Donald Becker's Ethernet Drivers and diag programs may be found at :
  - http://www.scyld.com/network/
 
-You will also find a lot of information regarding Ethernet, NWay, MII, etc. at
-www.scyld.com.
-
-Patches for 2.2 kernels are at Willy Tarreau's site :
- - http://wtarreau.free.fr/pub/bonding/
- - http://www-miaif.lip6.fr/~tarreau/pub/bonding/
-
-To get latest informations about Linux Kernel development, please consult
-the Linux Kernel Mailing List Archives at :
-   http://www.ussg.iu.edu/hypermail/linux/kernel/
+You will also find a lot of information regarding Ethernet, NWay, MII,
+etc. at www.scyld.com.
 
 -- END --
diff -Nru a/Documentation/networking/e100.txt b/Documentation/networking/e100.txt
--- a/Documentation/networking/e100.txt	2005-03-11 12:51:51 -08:00
+++ b/Documentation/networking/e100.txt	2005-03-11 12:51:51 -08:00
@@ -140,8 +140,7 @@
   NAPI
   ----
 
-  NAPI (Rx polling mode) is supported in the e100 driver. NAPI is enabled
-  or disabled based on the configuration of the kernel. 
+  NAPI (Rx polling mode) is supported in the e100 driver.
 
   See www.cyberus.ca/~hadi/usenix-paper.tgz for more information on NAPI.
 
diff -Nru a/Documentation/networking/ixgb.txt b/Documentation/networking/ixgb.txt
--- a/Documentation/networking/ixgb.txt	2005-03-11 12:51:47 -08:00
+++ b/Documentation/networking/ixgb.txt	2005-03-11 12:51:47 -08:00
@@ -1,7 +1,7 @@
 Linux* Base Driver for the Intel(R) PRO/10GbE Family of Adapters
 ================================================================
 
-September 13, 2004
+November 17, 2004
 
 
 Contents
@@ -18,8 +18,7 @@
 ===============
 
 This file describes the Linux* Base Driver for the Intel(R) PRO/10GbE Family 
-of Adapters, version 1.0.x.  This driver includes support for Itanium(TM)2 and
-EM64T systems.
+of Adapters, version 1.0.x.  
 
 For questions related to hardware requirements, refer to the documentation 
 supplied with your Intel PRO/10GbE adapter. All hardware requirements listed 
@@ -71,8 +70,8 @@
     Ethernet PAUSE frames.
 
 RxDescriptors
-Valid Range: 64-4096
-Default Value: 1024
+Valid Range: 64-512
+Default Value: 512
     This value is the number of receive descriptors allocated by the driver. 
     Increasing this value allows the driver to buffer more incoming packets. 
     Each descriptor is 16 bytes.  A receive buffer is also allocated for 
diff -Nru a/Documentation/pci.txt b/Documentation/pci.txt
--- a/Documentation/pci.txt	2005-03-11 12:51:46 -08:00
+++ b/Documentation/pci.txt	2005-03-11 12:51:46 -08:00
@@ -99,10 +99,10 @@
 Users need pass only as many fields as necessary; vendor, device,
 subvendor, and subdevice fields default to PCI_ANY_ID (FFFFFFFF),
 class and classmask fields default to 0, and driver_data defaults to
-0UL.  Device drivers must call
-   pci_dynids_set_use_driver_data(pci_driver *, 1)
-in order for the driver_data field to get passed to the driver.
-Otherwise, only a 0 is passed in that field.
+0UL.  Device drivers must initialize use_driver_data in the dynids struct
+in their pci_driver struct prior to calling pci_register_driver in order
+for the driver_data field to get passed to the driver. Otherwise, only a
+0 is passed in that field.
 
 When the driver exits, it just calls pci_unregister_driver() and the PCI layer
 automatically calls the remove hook for all devices handled by the driver.
diff -Nru a/Documentation/power/video.txt b/Documentation/power/video.txt
--- a/Documentation/power/video.txt	2005-03-11 12:51:46 -08:00
+++ b/Documentation/power/video.txt	2005-03-11 12:51:46 -08:00
@@ -1,7 +1,7 @@
 
 		Video issues with S3 resume
 		~~~~~~~~~~~~~~~~~~~~~~~~~~~
-		  2003-2004, Pavel Machek
+		  2003-2005, Pavel Machek
 
 During S3 resume, hardware needs to be reinitialized. For most
 devices, this is easy, and kernel driver knows how to do
@@ -11,33 +11,160 @@
 driver -- vesafb and vgacon are widely used).
 
 This is not problem for swsusp, because during swsusp resume, BIOS is
-run normally so video card is normally initialized.
+run normally so video card is normally initialized. S3 has absolutely
+no chance of working with SMP/HT. Be sure it to turn it off before
+testing (swsusp should work ok, OTOH).
 
-There are three types of systems where video works after S3 resume:
+There are a few types of systems where video works after S3 resume:
 
-* systems where video state is preserved over S3. (Athlon HP Omnibook xe3s)
+(1) systems where video state is preserved over S3.
 
-* systems where it is possible to call video bios during S3
-  resume. Unfortunately, it is not correct to call video BIOS at that
-  point, but it happens to work on some machines. Use
-  acpi_sleep=s3_bios (Athlon64 desktop system)
+(2) systems where it is possible to call the video BIOS during S3
+  resume. Unfortunately, it is not correct to call the video BIOS at
+  that point, but it happens to work on some machines. Use
+  acpi_sleep=s3_bios.
 
-* systems that initialize video card into vga text mode and where BIOS
-  works well enough to be able to set video mode. Use
-  acpi_sleep=s3_mode on these. (Toshiba 4030cdt)
+(3) systems that initialize video card into vga text mode and where
+  the BIOS works well enough to be able to set video mode. Use
+  acpi_sleep=s3_mode on these.
 
-* on some systems s3_bios kicks video into text mode, and
-  acpi_sleep=s3_bios,s3_mode is needed (Toshiba Satellite P10-554)
+(4) on some systems s3_bios kicks video into text mode, and
+  acpi_sleep=s3_bios,s3_mode is needed.
 
-* radeon systems, where X can soft-boot your video card. You'll need
+(5) radeon systems, where X can soft-boot your video card. You'll need
   patched X, and plain text console (no vesafb or radeonfb), see
-  http://www.doesi.gmxhome.de/linux/tm800s3/s3.html. (Acer TM 800)
+  http://www.doesi.gmxhome.de/linux/tm800s3/s3.html. Actually you
+  should probably use vbetool (6) instead.
+
+(6) other radeon systems, where vbetool is enough to bring system back
+  to life. It needs text console to be working. Do vbetool vbestate
+  save > /tmp/delme; echo 3 > /proc/acpi/sleep; vbetool post; vbetool
+  vbestate restore < /tmp/delme; setfont <whatever>, and your video
+  should work.
+
+(7) on some systems, it is possible to boot most of kernel, and then
+  POSTing bios works. Ole Rohne has patch to do just that at
+  http://dev.gentoo.org/~marineam/patch-radeonfb-2.6.11-rc2-mm2.
 
 Now, if you pass acpi_sleep=something, and it does not work with your
-bios, you'll get hard crash during resume. Be carefull.
+bios, you'll get a hard crash during resume. Be careful. Also it is
+safest to do your experiments with plain old VGA console. The vesafb
+and radeonfb (etc) drivers have a tendency to crash the machine during
+resume.
 
-You may have system where none of above works. At that point you
+You may have a system where none of above works. At that point you
 either invent another ugly hack that works, or write proper driver for
 your video card (good luck getting docs :-(). Maybe suspending from X
 (proper X, knowing your hardware, not XF68_FBcon) might have better
 chance of working.
+
+Table of known working systems:
+
+Model                           hack (or "how to do it")
+------------------------------------------------------------------------------
+Acer Aspire 1406LC		ole's late BIOS init (7), turn off DRI
+Acer TM 242FX			vbetool (6)
+Acer TM 4052LCi		        s3_bios (2)
+Acer TM 636Lci			s3_bios vga=normal (2)
+Acer TM 650 (Radeon M7)		vga=normal plus boot-radeon (5) gets text console back
+Acer TM 660			??? (*)
+Acer TM 800			vga=normal, X patches, see webpage (5)
+Arima W730a			vbetool needed (6)
+Asus L2400D                     s3_mode (3)(***) (S1 also works OK)
+Asus L3800C (Radeon M7)		s3_bios (2) (S1 also works OK)
+Asus M6NE			??? (*)
+Athlon64 desktop prototype	s3_bios (2)
+Compal CL-50			??? (*)
+Compaq Armada E500 - P3-700     none (1) (S1 also works OK)
+Dell 600m, ATI R250 Lf		none (1), but needs xorg-x11-6.8.1.902-1
+Dell D600, ATI RV250            vga=normal (**), or try vbestate (6)
+Dell Inspiron 4000		??? (*)
+Dell Inspiron 500m		??? (*)
+Dell Inspiron 600m		??? (*)
+Dell Inspiron 8200		??? (*)
+Dell Inspiron 8500		??? (*)
+Dell Inspiron 8600		??? (*)
+eMachines athlon64 machines	vbetool needed (6) (someone please get me model #s)
+HP NC6000			s3_bios, may not use radeonfb (2)
+HP NX7000			??? (*)
+HP Pavilion ZD7000		vbetool post needed, need open-source nv driver for X
+HP Omnibook XE3	athlon version	none (1)
+HP Omnibook XE3GC w/S3 Savage/IX-MV  none (1)
+IBM TP A31 / Type 2652-M5G      s3_mode (3) [works ok with BIOS 1.04 2002-08-23, but not at all with BIOS 1.11 2004-11-05 :-(]
+IBM TP R32 / Type 2658-MMG      none (1)
+IBM TP R40 2722B3G		??? (*)
+IBM TP R50p / Type 1832-22U     s3_bios (2)
+IBM TP R51			??? (*)
+IBM TP T30	236681A		??? (*)
+IBM TP T40 / Type 2373-MU4      none (1)
+IBM TP T40p			??? (*)
+IBM TP T41p			none (1)
+IBM TP T42			??? (*)
+IBM ThinkPad T42p (2373-GTG)	s3_bios (2)
+IBM TP X20			??? (*)
+IBM TP X30			??? (*)
+IBM TP X31 / Type 2672-XXH      none (1), use radeontool (http://fdd.com/software/radeon/) to turn off backlight.
+IBM TP X40			??? (*)
+Medion MD4220			??? (*)
+Samsung P35			vbetool needed (6)
+Sharp PC-AR10 (ATI rage)	none (1)
+Sony Vaio PCG-F403		??? (*)
+Sony Vaio PCG-N505SN		??? (*)
+Sony Vaio vgn-s260		X or boot-radeon can init it (5)
+Toshiba Satellite 4030CDT	s3_mode (3)
+Toshiba Satellite 4080XCDT      s3_mode (3)
+Toshiba Satellite 4090XCDT      ??? (*)
+Toshiba Satellite P10-554       s3_bios,s3_mode (4)(****)
+Uniwill 244IIO			??? (*)
+
+
+(*) from http://www.ubuntulinux.org/wiki/HoaryPMResults, not sure
+    which options to use. If you know, please tell me.
+
+(**) Text console is "strange" after resume. Backlight is switched on again
+     by the X server. X server is:
+     | X Window System Version 6.8.1.904 (6.8.2 RC 4)
+     | Release Date: 2 February 2005
+     | X Protocol Version 11, Revision 0, Release 6.8.1.904
+     | Build Operating System: SuSE Linux [ELF] SuSE
+     as present in SUSE 9.3preview3.
+
+(***) To be tested with a newer kernel.
+
+(****) Not with SMP kernel, UP only.
+
+VBEtool details
+~~~~~~~~~~~~~~~
+(with thanks to Carl-Daniel Hailfinger)
+
+First, boot into X and run the following script ONCE:
+#!/bin/bash
+statedir=/root/s3/state
+mkdir -p $statedir
+chvt 2
+sleep 1
+vbetool vbestate save >$statedir/vbe
+
+
+To suspend and resume properly, call the following script as root:
+#!/bin/bash
+statedir=/root/s3/state
+curcons=`fgconsole`
+fuser /dev/tty$curcons 2>/dev/null|xargs ps -o comm= -p|grep -q X && chvt 2
+cat /dev/vcsa >$statedir/vcsa
+sync
+echo 3 >/proc/acpi/sleep
+sync
+vbetool post
+vbetool vbestate restore <$statedir/vbe
+cat $statedir/vcsa >/dev/vcsa
+rckbd restart
+chvt $[curcons%6+1]
+chvt $curcons
+
+
+Unless you change your graphics card or other hardware configuration,
+the state once saved will be OK for every resume afterwards.
+NOTE: The "rckbd restart" command may be different for your
+distribution. Simply replace it with the command you would use to
+set the fonts on screen.
diff -Nru a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt
--- a/Documentation/sound/alsa/ALSA-Configuration.txt	2005-03-11 12:51:41 -08:00
+++ b/Documentation/sound/alsa/ALSA-Configuration.txt	2005-03-11 12:51:41 -08:00
@@ -7,75 +7,75 @@
 Kernel Configuration
 ====================
 
-To enable the ALSA support, at least you need to build the kernel with
-the primary sound card support (CONFIG_SOUND).  Since ALSA can emulate
-the OSS, you don't have to choose any of the OSS/Free modules.  Please
-enable "OSS API emulation" (CONFIG_SND_OSSEMUL) and both OSS mixer and
-PCM supports if you want to run the OSS application with the ALSA.
+To enable ALSA support you need at least to build the kernel with
+primary sound card support (CONFIG_SOUND).  Since ALSA can emulate OSS,
+you don't have to choose any of the OSS modules.
 
-When you want to support the WaveTable functionality on some cards
-such like SB Live!, you need to enable "Sequencer support"
+Enable "OSS API emulation" (CONFIG_SND_OSSEMUL) and both OSS mixer and
+PCM supports if you want to run OSS applications with ALSA.
+
+If you want to support the WaveTable functionality on cards such as
+SB Live! then you need to enable "Sequencer support"
 (CONFIG_SND_SEQUENCER).
 
-For getting more verbose debug messages, turn on "Verbose printk" and
-"Debug" options.  For checking the memory leaks, you can turn on
-"Debug memory" option, too.  "Debug detection" will put more
-additional checks for the detection of cards.
-
-Please note that all the ALSA ISA drivers support Linux isapnp API (if
-the card supports).  You don't need to configure the PnP via
-isapnptools.
+To make ALSA debug messages more verbose, enable the "Verbose printk"
+and "Debug" options.  To check for memory leaks, turn on "Debug memory"
+too.  "Debug detection" will add checks for the detection of cards.
+
+Please note that all the ALSA ISA drivers support the Linux isapnp API
+(if the card supports ISA PnP).  You don't need to configure the cards
+using isapnptools.
 
 
 Creating ALSA devices
 =====================
 
-Use the /dev/MAKEDEV script to create the nessecary device nodes.
+This depends on your distribution, but normally you use the /dev/MAKEDEV
+script to create the necessary device nodes.  On some systems you use a
+script named 'snddevices'.
 
 
 Module parameters
 =================
 
-  A user can modify or set parameters at the load time of the module. If
-  the module supports more cards and you have got more than one card
-  of the same type, you may simply specify more values for the parameter,
-  delimited by commas.
-  
-  Note that module option names were changed in 0.9.0rc4. The 'snd_'
-  prefix was removed.
+The user can load modules with options. If the module supports more than
+one card and you have more than one card of the same type then you can
+specify multiple values for the option separated by commas.
+
+Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
 
   Module snd
   ----------
 
-    The module snd is the ALSA core module, which is used by all ALSA
-    card drivers.  This takes the global options for creating devices,
-    etc.
+    The core ALSA module.  It is used by all ALSA card drivers.
+    It takes the following options which have global effects.
 
-    major	- major # for sound driver
-		- default is 116
+    major	- major number for sound driver
+		- Default: 116
     cards_limit
-		- specifies card limit # for auto-loading (1-8)
-		- default is 1
-		- for auto-loading more than 1 card, specify this option
-		  together with snd-card-X aliases.
+		- limiting card index for auto-loading (1-8)
+		- Default: 1
+		- For auto-loading more than one card, specify this
+		  option together with snd-card-X aliases.
     device_mode
-		- specifies permission mask for dynamic sound device filesystem
-		  (available only when DEVFS is enabled)
-		- default value = 0666
-		- for example 'device_mode=0660'
+		- permission mask for dynamic sound device filesystem
+		- This is available only when DEVFS is enabled
+		- Default: 0666
+		- E.g.: device_mode=0660
 
   
   Module snd-pcm-oss
   ------------------
 
     The PCM OSS emulation module.
-    This module takes the options to change the mapping of devices.
+    This module takes options which change the mapping of devices.
 
     dsp_map	- PCM device number maps assigned to the 1st OSS device.
-		  (default: 0)
+		- Default: 0
     adsp_map	- PCM device number maps assigned to the 2st OSS device.
-		  (default: 1)
-    nonblock_open - Don't block opening busy PCM devices.
+		- Default: 1
+    nonblock_open
+		- Don't block opening busy PCM devices.
 
     For example, when dsp_map=2, /dev/dsp will be mapped to PCM #2 of
     the card #0.  Similarly, when adsp_map=0, /dev/adsp will be mapped
@@ -91,33 +91,39 @@
   Module snd-rawmidi
   ------------------
 
-    This module takes the options to change the mapping of OSS
-    devices like snd-pcm-oss module.
+    This module takes options which change the mapping of devices.
+    similar to those of the snd-pcm-oss module.
 
     midi_map	- MIDI device number maps assigned to the 1st OSS device.
-		  (default: 0)
+		- Default: 0
     amidi_map	- MIDI device number maps assigned to the 2st OSS device.
-		  (default: 1)
+		- Default: 1
 
-  Common parameters for top soundcard modules
-  -------------------------------------------
+  Common parameters for top sound card modules
+  --------------------------------------------
 
-    Each of top-level soundcard module takes some general options,
+    Each of top level sound card module takes the following options.
 
-    index	- 0-7 - index (slot #) for soundcard
-                - if not set or -1, first free index (slot #) is assigned
-    id		- user identification for card (up to 15 chars)
-		- default expression is 'card<index>' (for example card1)
-		- value is used for /proc/asound filesystem
-		- this value can be used by applications for identification
-		  of card if user does not want identify card with index number
-    enable  	- enable card.  (all cards enabled for PCI and ISA PnP cards
-		  as default.)
+    index	- index (slot #) of sound card
+		- Values: 0 through 7 or negative
+		- If nonnegative, assign that index number
+                - if negative, interpret as a bitmask of permissible
+		  indices; the first free permitted index is assigned
+		- Default: -1
+    id		- card ID (identifier or name)
+		- Can be up to 15 characters long
+		- Default: the card type
+		- A directory by this name is created under /proc/asound/
+		  containing information about the card
+		- This ID can be used instead of the index number in
+		  identifying the card
+    enable  	- enable card
+		- Default: enabled, for PCI and ISA PnP cards
 
   Module snd-ad1816a
   ------------------
 
-    Module for soundcards based on Analog Devices AD1816A/AD1815 ISA chips.
+    Module for sound cards based on Analog Devices AD1816A/AD1815 ISA chips.
 
     port	- port # for AD1816A chip (PnP setup)
     mpu_port	- port # for MPU-401 UART (PnP setup)
@@ -132,7 +138,7 @@
   Module snd-ad1848
   -----------------
 
-    Module for soundcards based on AD1848/AD1847/CS4248 ISA chips.
+    Module for sound cards based on AD1848/AD1847/CS4248 ISA chips.
 
     port	- port # for AD1848 chip
     irq		- IRQ # for AD1848  chip
@@ -147,7 +153,8 @@
     Module for ALi M5451 PCI chip.
 
     pcm_channels    - Number of hardware channels assigned for PCM
-    spdif           - Support SPDIF I/O (disabled by default)
+    spdif           - Support SPDIF I/O
+    		    - Default: disabled
 
     Module supports autoprobe and multiple chips (max 8).
 
@@ -156,7 +163,7 @@
   Module snd-als100
   -----------------
 
-    Module for soundcards based on Avance Logic ALS100/ALS120 ISA chips.
+    Module for sound cards based on Avance Logic ALS100/ALS120 ISA chips.
 
     port	- port # for ALS100 (SB16) chip (PnP setup)
     irq		- IRQ # for ALS100 (SB16) chip (PnP setup)
@@ -171,7 +178,7 @@
   Module snd-als4000
   ------------------
 
-    Module for soundcards based on Avance Logic ALS4000 PCI chip.
+    Module for sound cards based on Avance Logic ALS4000 PCI chip.
 
     joystick_port - port # for legacy joystick support.
                     0 = disabled (default), 1 = auto-detect
@@ -197,6 +204,9 @@
 
     Module supports up to 8 cards.
 
+    Note: The default index value of this module is -2, i.e. the first
+          slot is excluded.
+
   Module snd-au8810, snd-au8820, snd-au8830
   -----------------------------------------
 
@@ -226,7 +236,7 @@
   Module snd-azt2320
   ------------------
 
-    Module for soundcards based on Aztech System AZT2320 ISA chip (PnP only).
+    Module for sound cards based on Aztech System AZT2320 ISA chip (PnP only).
 
     port	- port # for AZT2320 chip (PnP setup)
     wss_port	- port # for WSS (PnP setup)
@@ -242,7 +252,7 @@
   Module snd-azt3328
   ------------------
 
-    Module for soundcards based on Aztech AZF3328 PCI chip.
+    Module for sound cards based on Aztech AZF3328 PCI chip.
 
     joystick	- Enable joystick (default off)
 
@@ -258,6 +268,9 @@
 
     Module supports up to 8 cards.
 
+    Note: The default index value of this module is -2, i.e. the first
+          slot is excluded.
+
   Module snd-ca0106
   -----------------
 
@@ -269,7 +282,7 @@
   Module snd-cmi8330
   ------------------
 
-    Module for soundcards based on C-Media CMI8330 ISA chips.
+    Module for sound cards based on C-Media CMI8330 ISA chips.
 
     wssport	- port # for CMI8330 chip (WSS)
     wssirq	- IRQ # for CMI8330 chip (WSS)
@@ -284,7 +297,7 @@
   Module snd-cmipci
   -----------------
 
-    Module for C-Media CMI8338 and 8738 PCI soundcards.
+    Module for C-Media CMI8338 and 8738 PCI sound cards.
 
     mpu_port	- 0x300,0x310,0x320,0x330, 0 = disable (default)
     fm_port     - 0x388 (default), 0 = disable (default)
@@ -297,7 +310,7 @@
   Module snd-cs4231
   -----------------
 
-    Module for soundcards based on CS4231 ISA chips.
+    Module for sound cards based on CS4231 ISA chips.
 
     port	- port # for CS4231 chip
     mpu_port	- port # for MPU-401 UART (optional), -1 = disable
@@ -314,7 +327,7 @@
   Module snd-cs4232
   -----------------
 
-    Module for soundcards based on CS4232/CS4232A ISA chips.
+    Module for sound cards based on CS4232/CS4232A ISA chips.
 
     port	- port # for CS4232 chip (PnP setup - 0x534)
     cport	- control port # for CS4232 chip (PnP setup - 0x120,0x210,0xf00)
@@ -334,7 +347,7 @@
   Module snd-cs4236
   -----------------
 
-    Module for soundcards based on CS4235/CS4236/CS4236B/CS4237B/
+    Module for sound cards based on CS4235/CS4236/CS4236B/CS4237B/
                                    CS4238B/CS4239 ISA chips.
 
     port	- port # for CS4236 chip (PnP setup - 0x534)
@@ -367,7 +380,7 @@
   Module snd-cs46xx
   -----------------
 
-    Module for PCI soundcards based on CS4610/CS4612/CS4614/CS4615/CS4622/
+    Module for PCI sound cards based on CS4610/CS4612/CS4614/CS4615/CS4622/
 				       CS4624/CS4630/CS4280 PCI chips.
 
     external_amp     - Force to enable external amplifer.
@@ -400,14 +413,14 @@
   Module snd-dummy
   ----------------
 
-    Module for the dummy soundcard. This soundcard doesn't do any output
+    Module for the dummy sound card. This "card" doesn't do any output
     or input, but you may use this module for any application which
-    requires a soundcard (like RealPlayer).
+    requires a sound card (like RealPlayer).
 
   Module snd-emu10k1
   ------------------
 
-    Module for EMU10K1/EMU10k2 based PCI soundcards.
+    Module for EMU10K1/EMU10k2 based PCI sound cards.
 			* Sound Blaster Live!
 			* Sound Blaster PCI 512
 			* Emu APS (partially supported)
@@ -447,7 +460,7 @@
   Module snd-ens1370
   ------------------
 
-    Module for Ensoniq AudioPCI ES1370 PCI soundcards.
+    Module for Ensoniq AudioPCI ES1370 PCI sound cards.
 			* SoundBlaster PCI 64
 			* SoundBlaster PCI 128
 
@@ -458,7 +471,7 @@
   Module snd-ens1371
   ------------------
 
-    Module for Ensoniq AudioPCI ES1371 PCI soundcards.
+    Module for Ensoniq AudioPCI ES1371 PCI sound cards.
 			* SoundBlaster PCI 64
 			* SoundBlaster PCI 128
 			* SoundBlaster Vibra PCI
@@ -471,7 +484,7 @@
   Module snd-es968
   ----------------
 
-    Module for soundcards based on ESS ES968 chip (PnP only).
+    Module for sound cards based on ESS ES968 chip (PnP only).
 
     port	- port # for ES968 (SB8) chip (PnP setup)
     irq		- IRQ # for ES968 (SB8) chip (PnP setup)
@@ -482,7 +495,7 @@
   Module snd-es1688
   -----------------
 
-    Module for ESS AudioDrive ES-1688 and ES-688 soundcards.
+    Module for ESS AudioDrive ES-1688 and ES-688 sound cards.
 
     port	- port # for ES-1688 chip (0x220,0x240,0x260)
     mpu_port	- port # for MPU-401 port (0x300,0x310,0x320,0x330), -1 = disable (default)
@@ -495,7 +508,7 @@
   Module snd-es18xx
   -----------------
 
-    Module for ESS AudioDrive ES-18xx soundcards.
+    Module for ESS AudioDrive ES-18xx sound cards.
 
     port	- port # for ES-18xx chip (0x220,0x240,0x260)
     mpu_port	- port # for MPU-401 port (0x300,0x310,0x320,0x330), -1 = disable (default)
@@ -514,14 +527,14 @@
   Module snd-es1938
   -----------------
 
-    Module for soundcards based on ESS Solo-1 (ES1938,ES1946) chips.
+    Module for sound cards based on ESS Solo-1 (ES1938,ES1946) chips.
 
     Module supports up to 8 cards and autoprobe.
 
   Module snd-es1968
   -----------------
 
-    Module for soundcards based on ESS Maestro-1/2/2E (ES1968/ES1978) chips.
+    Module for sound cards based on ESS Maestro-1/2/2E (ES1968/ES1978) chips.
 
     total_bufsize	- total buffer size in kB (1-4096kB)
     pcm_substreams_p	- playback channels (1-8, default=2)
@@ -539,7 +552,7 @@
   Module snd-fm801
   ----------------
 
-    Module for ForteMedia FM801 based PCI soundcards.
+    Module for ForteMedia FM801 based PCI sound cards.
 
     tea575x_tuner       - Enable TEA575x tuner
                           - 1 = MediaForte 256-PCS
@@ -553,7 +566,7 @@
   Module snd-gusclassic
   ---------------------
 
-    Module for Gravis UltraSound Classic soundcard.
+    Module for Gravis UltraSound Classic sound card.
 
     port	- port # for GF1 chip (0x220,0x230,0x240,0x250,0x260)
     irq		- IRQ # for GF1 chip (3,5,9,11,12,15)
@@ -568,7 +581,7 @@
   Module snd-gusextreme
   ---------------------
 
-    Module for Gravis UltraSound Extreme (Synergy ViperMax) soundcard.
+    Module for Gravis UltraSound Extreme (Synergy ViperMax) sound card.
 
     port	- port # for ES-1688 chip (0x220,0x230,0x240,0x250,0x260)
     gf1_port	- port # for GF1 chip (0x210,0x220,0x230,0x240,0x250,0x260,0x270)
@@ -587,7 +600,7 @@
   Module snd-gusmax
   -----------------
 
-    Module for Gravis UltraSound MAX soundcard.
+    Module for Gravis UltraSound MAX sound card.
 
     port	- port # for GF1 chip (0x220,0x230,0x240,0x250,0x260)
     irq		- IRQ # for GF1 chip (3,5,9,11,12,15)
@@ -599,18 +612,42 @@
 
     Module supports up to 8 cards and autoprobe.
     
+  Module snd-hda-intel
+  --------------------
+
+    Module for Intel HD Audio (ICH6, ICH6M, ICH7)
+
+    model	- force the model name
+
+    Module supports up to 8 cards.
+
+    Each codec may have a model table for different configurations.
+    If your machine isn't listed there, the default (usually minimal)
+    configuration is set up.  You can pass "model=<name>" option to
+    specify a certain model in such a case.  There are different
+    models depending on the codec chip.
+
+	  Model name	Description
+	  ----------    -----------
+	ALC880
+	  3stack	3-jack in back and a headphone out
+	  3stack-digout	3-jack in back, a HP out and a SPDIF out
+	  5stack	5-jack in back, 2-jack in front
+	  5stack-digout	5-jack in back, 2-jack in front, a SPDIF out
+	  w810		3-jack
+
+	CMI9880
+	  minimal	3-jack in back
+	  min_fp	3-jack in back, 2-jack in front
+	  full		6-jack in back, 2-jack in front
+	  full_dig	6-jack in back, 2-jack in front, SPDIF I/O
+	  allout	5-jack in back, 2-jack in front, SPDIF out
+
   Module snd-hdsp
   ---------------
 
     Module for RME Hammerfall DSP audio interface(s)
 
-    precise_ptr	      - Enable precise pointer (doesn't work reliably).
-			(default = 0)
-    line_outs_monitor - Send all input and playback streams to line outs
-			by default. (default = 0)
-    force_firmware    - Force a reload of the I/O box firmware
-			(default = 0)
-
     Module supports up to 8 cards.
 
     Note: The firmware data can be automatically loaded via hotplug
@@ -628,7 +665,7 @@
   Module snd-ice1712
   ------------------
 
-    Module for Envy24 (ICE1712) based PCI soundcards.
+    Module for Envy24 (ICE1712) based PCI sound cards.
 			* MidiMan M Audio Delta 1010
 			* MidiMan M Audio Delta 1010LT
 			* MidiMan M Audio Delta DiO 2496
@@ -660,7 +697,7 @@
   Module snd-ice1724
   ------------------
 
-    Module for Envy24HT (VT/ICE1724) based PCI soundcards.
+    Module for Envy24HT (VT/ICE1724) based PCI sound cards.
 			* MidiMan M Audio Revolution 7.1
 			* AMP Ltd AUDIO2000
 			* TerraTec Aureon Sky-5.1, Space-7.1
@@ -689,7 +726,7 @@
                       hp_only = use headphone control as master
                       swap_hp = swap headphone and master controls
                       swap_surround = swap master and surround controls
-                      ad_shring = for AD1985, turn on OMS bit and use headphone
+                      ad_sharing = for AD1985, turn on OMS bit and use headphone
                       alc_jack = for ALC65x, turn on the jack sense mode
                       inv_eapd = inverted EAPD implementation
                       mute_led = bind EAPD bit for turning on/off mute LED
@@ -726,11 +763,14 @@
 
     This module supports up to 8 cards and autoprobe.
 
+    Note: The default index value of this module is -2, i.e. the first
+          slot is excluded.
+
   Module snd-interwave
   --------------------
 
     Module for Gravis UltraSound PnP, Dynasonic 3-D/Pro, STB Sound Rage 32
-    and other soundcards based on AMD InterWave (tm) chip.
+    and other sound cards based on AMD InterWave (tm) chip.
   
     port	- port # for InterWave chip (0x210,0x220,0x230,0x240,0x250,0x260)
     irq		- IRQ # for InterWave chip (3,5,9,11,12,15)
@@ -747,8 +787,8 @@
   Module snd-interwave-stb
   ------------------------
 
-    Module for UltraSound 32-Pro (soundcard from STB used by Compaq)
-    and other soundcards based on AMD InterWave (tm) chip with TEA6330T
+    Module for UltraSound 32-Pro (sound card from STB used by Compaq)
+    and other sound cards based on AMD InterWave (tm) chip with TEA6330T
     circuit for extended control of bass, treble and master volume.
   
     port	- port # for InterWave chip (0x210,0x220,0x230,0x240,0x250,0x260)
@@ -794,7 +834,7 @@
   Module snd-mixart
   -----------------
 
-    Module for Digigram miXart8 soundcards.
+    Module for Digigram miXart8 sound cards.
 
     Module supports multiple cards.
     Note: One miXart8 board will be represented as 4 alsa cards.
@@ -813,10 +853,9 @@
 
     port	- port number or -1 (disable)
     irq		- IRQ number or -1 (disable)
-    acpipnp	- ACPI PnP detection - 0 = disable, 1 = enable (default)
+    pnp		- PnP detection - 0 = disable, 1 = enable (default)
 
-    Module supports multiple devices (max 8) and ACPI PnP.  If PnP is not
-    used (or ACPI not enabled), port and irq must be specified.
+    Module supports multiple devices (max 8) and PnP.
     
   Module snd-mtpav
   ----------------
@@ -883,7 +922,7 @@
   Module snd-opl3sa2
   ------------------
 
-    Module for Yamaha OPL3-SA2/SA3 soundcards.
+    Module for Yamaha OPL3-SA2/SA3 sound cards.
 
     port	- control port # for OPL3-SA chip (0x370)
     sb_port	- SB port # for OPL3-SA chip (0x220,0x240)
@@ -903,7 +942,7 @@
   Module snd-opti92x-ad1848
   -------------------------
 
-    Module for soundcards based on OPTi 82c92x and Analog Devices AD1848 chips.
+    Module for sound cards based on OPTi 82c92x and Analog Devices AD1848 chips.
     Module works with OAK Mozart cards as well.
     
     port      - port # for WSS chip (0x530,0xe80,0xf40,0x604)
@@ -918,7 +957,7 @@
   Module snd-opti92x-cs4231
   -------------------------
 
-    Module for soundcards based on OPTi 82c92x and Crystal CS4231 chips.
+    Module for sound cards based on OPTi 82c92x and Crystal CS4231 chips.
     
     port      - port # for WSS chip (0x530,0xe80,0xf40,0x604)
     mpu_port  - port # for MPU-401 UART (0x300,0x310,0x320,0x330)
@@ -933,7 +972,7 @@
   Module snd-opti93x
   ------------------
 
-    Module for soundcards based on OPTi 82c93x chips.
+    Module for sound cards based on OPTi 82c93x chips.
     
     port      - port # for WSS chip (0x530,0xe80,0xf40,0x604)
     mpu_port  - port # for MPU-401 UART (0x300,0x310,0x320,0x330)
@@ -962,21 +1001,21 @@
   ----------------
 
     Module for RME Digi32, Digi32 Pro and Digi32/8 (Sek'd Prodif32, 
-    Prodif96 and Prodif Gold) soundcards.
+    Prodif96 and Prodif Gold) sound cards.
 
     Module supports up to 8 cards.
 
   Module snd-rme96
   ----------------
 
-    Module for RME Digi96, Digi96/8 and Digi96/8 PRO/PAD/PST soundcards.
+    Module for RME Digi96, Digi96/8 and Digi96/8 PRO/PAD/PST sound cards.
 
     Module supports up to 8 cards.
 
   Module snd-rme9652
   ------------------
 
-    Module for RME Digi9652 (Hammerfall, Hammerfall-Light) soundcards.
+    Module for RME Digi9652 (Hammerfall, Hammerfall-Light) sound cards.
 
     precise_ptr	- Enable precise pointer (doesn't work reliably).
 		  (default = 0)
@@ -992,7 +1031,7 @@
   Module snd-sa11xx-uda1341 (on arm only)
   ---------------------------------------
 
-    Module for Philips UDA1341TS on Compaq iPAQ H3600 soundcard.
+    Module for Philips UDA1341TS on Compaq iPAQ H3600 sound card.
 
     Module supports only one card.
     Module has no enable and index options.
@@ -1039,7 +1078,7 @@
   Module snd-sgalaxy
   ------------------
 
-    Module for Aztech Sound Galaxy soundcard.
+    Module for Aztech Sound Galaxy sound card.
 
     sbport	- Port # for SB16 interface (0x220,0x240)
     wssport	- Port # for WSS interface (0x530,0xe80,0xf40,0x604)
@@ -1079,7 +1118,7 @@
   Module snd-wavefront
   --------------------
 
-    Module for Turtle Beach Maui, Tropez and Tropez+ soundcards.
+    Module for Turtle Beach Maui, Tropez and Tropez+ sound cards.
 
     cs4232_pcm_port - Port # for CS4232 PCM interface.
     cs4232_pcm_irq  - IRQ # for CS4232 PCM interface (5,7,9,11,12,15).
@@ -1099,7 +1138,7 @@
   Module snd-sonicvibes
   ---------------------
 
-    Module for S3 SonicVibes PCI soundcards.
+    Module for S3 SonicVibes PCI sound cards.
 			* PINE Schubert 32 PCI
 
     reverb    - Reverb Enable - 1 = enable, 0 = disable (default)
@@ -1131,7 +1170,7 @@
   Module snd-trident
   ------------------
 
-    Module for Trident 4DWave DX/NX soundcards.
+    Module for Trident 4DWave DX/NX sound cards.
 			* Best Union  Miss Melody 4DWave PCI
 			* HIS  4DWave PCI
 			* Warpspeed  ONSpeed 4DWave PCI
@@ -1223,6 +1262,9 @@
 
     Module supports up to 8 cards.
 
+    Note: The default index value of this module is -2, i.e. the first
+          slot is excluded.
+
   Module snd-virmidi
   ------------------
 
@@ -1266,10 +1308,6 @@
 
     Module for Digigram VX-Pocket VX2 PCMCIA card.
 
-    irq_mask - IRQ bitmask, specifies the available IRQs as bits
-               (default = 0xffff, all available)
-    irq_list - List of available interrupts (default = -1, not specified)
-               4 numbers must be given (if specified).
     ibl      - Capture IBL size. (default = 0, minimum size)
 
     Module supports up to 8 cards.  The module is compiled only when
@@ -1284,9 +1322,6 @@
     When no hotplug fw loader is available, you need to load the
     firmware via vxloader utility in alsa-tools package.
 
-    The irq_mask and irq_list are provided to avoid allocation of
-    specific IRQs.  Usually you don't need to specify them.
-
     About capture IBL, see the description of snd-vx222 module.
 
     Note: the driver is build only when CONFIG_ISA is set.
@@ -1296,9 +1331,6 @@
 
     Module for Digigram VX-Pocket 440 PCMCIA card.
 
-    irq_mask - IRQ bitmask, specifies the available IRQs as bits
-    irq_list - List of available interrupts (default = -1, not specified)
-               4 numbers must be given (if specified).
     ibl      - Capture IBL size. (default = 0, minimum size)
 
     Module supports up to 8 cards.  The module is compiled only when
@@ -1313,9 +1345,6 @@
     When no hotplug fw loader is available, you need to load the
     firmware via vxloader utility in alsa-tools package.
 
-    The irq_mask and irq_list are provided to avoid allocation of
-    specific IRQs.  Usually you don't need to specify them.
-
     About capture IBL, see the description of snd-vx222 module.
 
     Note: the driver is build only when CONFIG_ISA is set.
@@ -1340,10 +1369,7 @@
   Module snd-pdaudiocf
   --------------------
 
-    Module for Sound Core PDAudioCF soundcard.
-
-    irq_mask	  - IRQ mask (PCMCIA type)
-    irq_list	  - List of available interrupts for this soundcard
+    Module for Sound Core PDAudioCF sound card.
 
     Note: the driver is build only when CONFIG_ISA is set.
 
@@ -1366,7 +1392,7 @@
 
 The ALSA drivers can be loaded automatically on demand by defining
 module aliases.  The string 'snd-card-%1' is requested for ALSA native
-devices where %i is soundcard number from zero to seven.
+devices where %i is sound card number from zero to seven.
 
 To auto-load an ALSA driver for OSS services, define the string
 'sound-slot-%i' where %i means the slot number for OSS, which
@@ -1379,16 +1405,16 @@
 alias sound-slot-0 snd-emu10k1
 ----- /etc/modprobe.conf
 
-The available number of auto-loaded soundcards depends on the module
+The available number of auto-loaded sound cards depends on the module
 option "cards_limit" of snd module.  As default it's set to 1.
 To enable the auto-loading of multiple cards, specify the number of
-soundcards in that option.
+sound cards in that option.
 
 When multiple cards are available, it'd better to specify the index
 number for each card via module option, too, so that the order of
 cards is kept consistent.
 
-An example configuration for two soundcards is like below:
+An example configuration for two sound cards is like below:
 
 ----- /etc/modprobe.conf
 # ALSA portion
@@ -1420,7 +1446,7 @@
 /dev/snd/pcmC2D1[c|p]  -> /dev/adsp2               -> minor 12+32 = 44
 
 The first number from /dev/snd/pcmC{X}D{Y}[c|p] expression means
-soundcard number and second means device number.  The ALSA devices
+sound card number and second means device number.  The ALSA devices
 have either 'c' or 'p' suffix indicating the direction, capture and
 playback, respectively.
 
diff -Nru a/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl b/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl
--- a/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl	2005-03-11 12:51:42 -08:00
+++ b/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl	2005-03-11 12:51:42 -08:00
@@ -18,8 +18,8 @@
       </affiliation>
      </author>
 
-     <date>July 11, 2004</date>
-     <edition>0.3.3</edition>
+     <date>March 6, 2005</date>
+     <edition>0.3.4</edition>
 
     <abstract>
       <para>
@@ -110,9 +110,9 @@
       </para>
 
       <para>
-        One is the the trees provided as a tarball or via cvs from the
+        One is the trees provided as a tarball or via cvs from the
       ALSA's ftp site, and another is the 2.6 (or later) Linux kernel
-      tree. To synchronize both, the ALSA driver tree is split to
+      tree. To synchronize both, the ALSA driver tree is split into
       two different trees: alsa-kernel and alsa-driver. The former
       contains purely the source codes for the Linux 2.6 (or later)
       tree. This tree is designed only for compilation on 2.6 or
@@ -766,7 +766,7 @@
       </para>
 
       <para>
-      The ALSA interfaces like PCM or control API are define in other
+      The ALSA interfaces like PCM or control API are defined in other
       header files as <filename>&lt;sound/xxx.h&gt;</filename>.
       They have to be included after
       <filename>&lt;sound/core.h&gt;</filename>.
@@ -1103,7 +1103,7 @@
           /* release the irq */
           if (chip->irq >= 0)
                   free_irq(chip->irq, (void *)chip);
-          /* release the i/o ports */
+          /* release the i/o ports & memory */
           pci_release_regions(chip->pci);
           /* disable the PCI entry */
           pci_disable_device(chip->pci);
@@ -1314,6 +1314,7 @@
       </para>
 
       <para>
+        <!-- obsolete -->
         It will reserve the i/o port region of 8 bytes of the given
       PCI device. The returned value, chip-&gt;res_port, is allocated
       via <function>kmalloc()</function> by
@@ -1936,6 +1937,7 @@
           snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
                           &snd_mychip_capture_ops);
           /* pre-allocation of buffers */
+          /* NOTE: this may fail */
           snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
                                                 snd_dma_pci_data(chip->pci),
                                                 64*1024, 64*1024);
@@ -1950,7 +1952,7 @@
     <section id="pcm-interface-constructor">
       <title>Constructor</title>
       <para>
-        A pcm instance is allocated <function>snd_pcm_new()</function>
+        A pcm instance is allocated by <function>snd_pcm_new()</function>
       function. It would be better to create a constructor for pcm,
       namely, 
 
@@ -2235,7 +2237,8 @@
 	unsigned char *dma_area;	/* DMA area */
 	dma_addr_t dma_addr;		/* physical bus address (not accessible from main CPU) */
 	size_t dma_bytes;		/* size of DMA area */
-	void *dma_private;		/* private DMA data for the memory allocator */
+
+	struct snd_dma_buffer *dma_buffer_p;	/* allocated buffer */
 
 #if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE)
 	/* -- OSS things -- */
@@ -2250,7 +2253,7 @@
 	<para>
 	  For the operators (callbacks) of each sound driver, most of
 	these records are supposed to be read-only.  Only the PCM
-	middle-layer changes / updates these info.  The excpetions are
+	middle-layer changes / updates these info.  The exceptions are
 	the hardware description (hw), interrupt callbacks
 	(transfer_ack_xxx), DMA buffer information, and the private
 	data.  Besides, if you use the standard buffer allocation
@@ -3250,7 +3253,7 @@
 
       <para>
         There are many different constraints.
-        Look in <filename>sound/asound.h</filename> for a complete list.
+        Look in <filename>sound/pcm.h</filename> for a complete list.
         You can even define your own constraint rules.
         For example, let's suppose my_chip can manage a substream of 1 channel
         if and only if the format is S16_LE, otherwise it supports any format
@@ -4066,7 +4069,7 @@
         Both <function>snd_ac97_write()</function> and
         <function>snd_ac97_update()</function> functions are used to
         set a value to the given register
-        (<constant>AC97_XXX</constant>). The different between them is
+        (<constant>AC97_XXX</constant>). The difference between them is
         that <function>snd_ac97_update()</function> doesn't write a
         value if the given value has been already set, while
         <function>snd_ac97_write()</function> always rewrites the
@@ -4152,8 +4155,8 @@
       <title>Proc Files</title>
       <para>
         The ALSA AC97 interface will create a proc file such as
-      <filename>/proc/asound/card0/ac97#0</filename> and
-      <filename>ac97#0regs</filename>. You can refer to these files to
+      <filename>/proc/asound/card0/codec97#0/ac97#0-0</filename> and
+      <filename>ac97#0-0+regs</filename>. You can refer to these files to
       see the current status and registers of the codec. 
       </para>
     </section>
@@ -4200,18 +4203,6 @@
       implementation of mpu401 stuff. For example, emu10k1 has its own
       mpu401 routines. 
       </para>
-
-      <para>
-        In this document, I won't explain the rawmidi interface API,
-      which is the basis of MPU401-UART implementation. 
-      </para>
-
-      <para>
-        For details, please check the source,
-      <filename>core/rawmidi.c</filename>, and examples such as
-      <filename>drivers/mpu401/mpu401_uart.c</filename> or
-      <filename>usb/usbmidi.c</filename>. 
-      </para>
     </section>
 
     <section id="midi-interface-constructor">
@@ -4335,6 +4326,356 @@
 
 
 <!-- ****************************************************** -->
+<!-- RawMIDI Interface  -->
+<!-- ****************************************************** -->
+  <chapter id="rawmidi-interface">
+    <title>RawMIDI Interface</title>
+
+    <section id="rawmidi-interface-overview">
+      <title>Overview</title>
+
+      <para>
+      The raw MIDI interface is used for hardware MIDI ports that can
+      be accessed as a byte stream.  It is not used for synthesizer
+      chips that do not directly understand MIDI.
+      </para>
+
+      <para>
+      ALSA handles file and buffer management.  All you have to do is
+      to write some code to move data between the buffer and the
+      hardware.
+      </para>
+
+      <para>
+      The rawmidi API is defined in
+      <filename>&lt;sound/rawmidi.h&gt;</filename>.
+      </para>
+    </section>
+
+    <section id="rawmidi-interface-constructor">
+      <title>Constructor</title>
+
+      <para>
+      To create a rawmidi device, call the
+      <function>snd_rawmidi_new</function> function:
+        <informalexample>
+          <programlisting>
+<![CDATA[
+  snd_rawmidi_t *rmidi;
+  err = snd_rawmidi_new(chip->card, "MyMIDI", 0, outs, ins, &rmidi);
+  if (err < 0)
+          return err;
+  rmidi->private_data = chip;
+  strcpy(rmidi->name, "My MIDI");
+  rmidi->info_flags = SNDRV_RAWMIDI_INFO_OUTPUT |
+                      SNDRV_RAWMIDI_INFO_INPUT |
+                      SNDRV_RAWMIDI_INFO_DUPLEX;
+]]>
+          </programlisting>
+        </informalexample>
+      </para>
+
+      <para>
+      The first argument is the card pointer, the second argument is
+      the ID string.
+      </para>
+
+      <para>
+      The third argument is the index of this component.  You can
+      create up to 8 rawmidi devices.
+      </para>
+
+      <para>
+      The fourth and fifth arguments are the number of output and
+      input substreams, respectively, of this device.  (A substream is
+      the equivalent of a MIDI port.)
+      </para>
+
+      <para>
+      Set the <structfield>info_flags</structfield> field to specify
+      the capabilities of the device.
+      Set <constant>SNDRV_RAWMIDI_INFO_OUTPUT</constant> if there is
+      at least one output port,
+      <constant>SNDRV_RAWMIDI_INFO_INPUT</constant> if there is at
+      least one input port,
+      and <constant>SNDRV_RAWMIDI_INFO_DUPLEX</constant> if the device
+      can handle output and input at the same time.
+      </para>
+
+      <para>
+      After the rawmidi device is created, you need to set the
+      operators (callbacks) for each substream.  There are helper
+      functions to set the operators for all substream of a device:
+        <informalexample>
+          <programlisting>
+<![CDATA[
+  snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &snd_mymidi_output_ops);
+  snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, &snd_mymidi_input_ops);
+]]>
+          </programlisting>
+        </informalexample>
+      </para>
+
+      <para>
+      The operators are usually defined like this:
+        <informalexample>
+          <programlisting>
+<![CDATA[
+  static snd_rawmidi_ops_t snd_mymidi_output_ops = {
+          .open =    snd_mymidi_output_open,
+          .close =   snd_mymidi_output_close,
+          .trigger = snd_mymidi_output_trigger,
+  };
+]]>
+          </programlisting>
+        </informalexample>
+      These callbacks are explained in the <link
+      linkend="rawmidi-interface-callbacks"><citetitle>Callbacks</citetitle></link>
+      section.
+      </para>
+
+      <para>
+      If there is more than one substream, you should give each one a
+      unique name:
+        <informalexample>
+          <programlisting>
+<![CDATA[
+  struct list_head *list;
+  snd_rawmidi_substream_t *substream;
+  list_for_each(list, &rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT].substreams) {
+          substream = list_entry(list, snd_rawmidi_substream_t, list);
+          sprintf(substream->name, "My MIDI Port %d", substream->number + 1);
+  }
+  /* same for SNDRV_RAWMIDI_STREAM_INPUT */
+]]>
+          </programlisting>
+        </informalexample>
+      </para>
+    </section>
+
+    <section id="rawmidi-interface-callbacks">
+      <title>Callbacks</title>
+
+      <para>
+      In all callbacks, the private data that you've set for the
+      rawmidi device can be accessed as
+      substream-&gt;rmidi-&gt;private_data.
+      <!-- <code> isn't available before DocBook 4.3 -->
+      </para>
+
+      <para>
+      If there is more than one port, your callbacks can determine the
+      port index from the snd_rawmidi_substream_t data passed to each
+      callback:
+        <informalexample>
+          <programlisting>
+<![CDATA[
+  snd_rawmidi_substream_t *substream;
+  int index = substream->number;
+]]>
+          </programlisting>
+        </informalexample>
+      </para>
+
+      <section id="rawmidi-interface-op-open">
+      <title><function>open</function> callback</title>
+
+        <informalexample>
+          <programlisting>
+<![CDATA[
+  static int snd_xxx_open(snd_rawmidi_substream_t *substream);
+]]>
+          </programlisting>
+        </informalexample>
+
+        <para>
+        This is called when a substream is opened.
+        You can initialize the hardware here, but you should not yet
+        start transmitting/receiving data.
+        </para>
+      </section>
+
+      <section id="rawmidi-interface-op-close">
+      <title><function>close</function> callback</title>
+
+        <informalexample>
+          <programlisting>
+<![CDATA[
+  static int snd_xxx_close(snd_rawmidi_substream_t *substream);
+]]>
+          </programlisting>
+        </informalexample>
+
+        <para>
+        Guess what.
+        </para>
+
+        <para>
+        The <function>open</function> and <function>close</function>
+        callbacks of a rawmidi device are serialized with a mutex,
+        and can sleep.
+        </para>
+      </section>
+
+      <section id="rawmidi-interface-op-trigger-out">
+      <title><function>trigger</function> callback for output
+      substreams</title>
+
+        <informalexample>
+          <programlisting>
+<![CDATA[
+  static void snd_xxx_output_trigger(snd_rawmidi_substream_t *substream, int up);
+]]>
+          </programlisting>
+        </informalexample>
+
+        <para>
+        This is called with a nonzero <parameter>up</parameter>
+        parameter when there is some data in the substream buffer that
+        must be transmitted.
+        </para>
+
+        <para>
+        To read data from the buffer, call
+        <function>snd_rawmidi_transmit_peek</function>.  It will
+        return the number of bytes that have been read; this will be
+        less than the number of bytes requested when there is no more
+        data in the buffer.
+        After the data has been transmitted successfully, call
+        <function>snd_rawmidi_transmit_ack</function> to remove the
+        data from the substream buffer:
+          <informalexample>
+            <programlisting>
+<![CDATA[
+  unsigned char data;
+  while (snd_rawmidi_transmit_peek(substream, &data, 1) == 1) {
+          if (mychip_try_to_transmit(data))
+                  snd_rawmidi_transmit_ack(substream, 1);
+          else
+                  break; /* hardware FIFO full */
+  }
+]]>
+            </programlisting>
+          </informalexample>
+        </para>
+
+        <para>
+        If you know beforehand that the hardware will accept data, you
+        can use the <function>snd_rawmidi_transmit</function> function
+        which reads some data and removes it from the buffer at once:
+          <informalexample>
+            <programlisting>
+<![CDATA[
+  while (mychip_transmit_possible()) {
+          unsigned char data;
+          if (snd_rawmidi_transmit(substream, &data, 1) != 1)
+                  break; /* no more data */
+          mychip_transmit(data);
+  }
+]]>
+            </programlisting>
+          </informalexample>
+        </para>
+
+        <para>
+        If you know beforehand how many bytes you can accept, you can
+        use a buffer size greater than one with the
+        <function>snd_rawmidi_transmit*</function> functions.
+        </para>
+
+        <para>
+        The <function>trigger</function> callback must not sleep.  If
+        the hardware FIFO is full before the substream buffer has been
+        emptied, you have to continue transmitting data later, either
+        in an interrupt handler, or with a timer if the hardware
+        doesn't have a MIDI transmit interrupt.
+        </para>
+
+        <para>
+        The <function>trigger</function> callback is called with a
+        zero <parameter>up</parameter> parameter when the transmission
+        of data should be aborted.
+        </para>
+
+        <para>
+        The <function>trigger</function> callback may be called from
+        another hardware interrupt handler.  This means that all
+        spinlocks taken in the <function>trigger</function> callback
+        must be taken with <function>spin_lock_irqsave</function>
+        everywhere.
+        </para>
+      </section>
+
+      <section id="rawmidi-interface-op-trigger-in">
+      <title><function>trigger</function> callback for input
+      substreams</title>
+
+        <informalexample>
+          <programlisting>
+<![CDATA[
+  static void snd_xxx_input_trigger(snd_rawmidi_substream_t *substream, int up);
+]]>
+          </programlisting>
+        </informalexample>
+
+        <para>
+        This is called with a nonzero <parameter>up</parameter>
+        parameter to enable receiving data, or with a zero
+        <parameter>up</parameter> parameter do disable receiving data.
+        </para>
+
+        <para>
+        When data reception is enabled, your interrupt handler should
+        call <function>snd_rawmidi_receive</function> for all received
+        data:
+          <informalexample>
+            <programlisting>
+<![CDATA[
+  void snd_mychip_midi_interrupt(...)
+  {
+          while (mychip_midi_available()) {
+                  unsigned char data;
+                  data = mychip_midi_read();
+                  snd_rawmidi_receive(substream, &data, 1);
+          }
+  }
+]]>
+            </programlisting>
+          </informalexample>
+        </para>
+      </section>
+
+      <section id="rawmidi-interface-op-drain">
+      <title><function>drain</function> callback</title>
+
+        <informalexample>
+          <programlisting>
+<![CDATA[
+  static void snd_xxx_drain(snd_rawmidi_substream_t *substream);
+]]>
+          </programlisting>
+        </informalexample>
+
+        <para>
+        This is only used with output substreams.  This function should wait
+        until all data read from the substream buffer has been transmitted.
+        This ensures that the device can be closed and the driver unloaded
+        without losing data.
+        </para>
+
+        <para>
+        This callback is optional.  If you do not set
+        <structfield>drain</structfield> in the snd_rawmidi_ops_t
+        structure, ALSA will simply wait for 50&nbsp;milliseconds
+        instead.
+        </para>
+      </section>
+    </section>
+
+  </chapter>
+
+
+<!-- ****************************************************** -->
 <!-- Miscellaneous Devices  -->
 <!-- ****************************************************** -->
   <chapter id="misc-devices">
@@ -4633,7 +4974,7 @@
         where <parameter>size</parameter> is the byte size to be
       pre-allocated and the <parameter>max</parameter> is the maximal
       size to be changed via <filename>prealloc</filename> proc file.
-      The allocator will try to get as the large area as possible
+      The allocator will try to get as large area as possible
       within the given size. 
       </para>
 
@@ -4855,7 +5196,7 @@
         If your hardware supports the page table like emu10k1 or the
       buffer descriptors like via82xx, you can use the scatter-gather
       (SG) DMA. ALSA provides an interface for handling SG-buffers.
-      The API is provided in <filename>&lt;sound/pcm_sgbuf.h&gt;</filename>. 
+      The API is provided in <filename>&lt;sound/pcm.h&gt;</filename>. 
       </para>
 
       <para>
@@ -5159,12 +5500,12 @@
         <programlisting>
 <![CDATA[
   #ifdef CONFIG_PM
-  static int snd_my_suspend(snd_card_t *card, unsigned int state)
+  static int snd_my_suspend(snd_card_t *card, pm_message_t state)
   {
           .... // do things for suspsend
           return 0;
   }
-  static int snd_my_resume(snd_card_t *card, unsigned int state)
+  static int snd_my_resume(snd_card_t *card)
   {
           .... // do things for suspsend
           return 0;
@@ -5193,7 +5534,7 @@
       <informalexample>
         <programlisting>
 <![CDATA[
-  static int mychip_suspend(snd_card_t *card, unsigned int state)
+  static int mychip_suspend(snd_card_t *card, pm_message_t state)
   {
           /* (1) */
           mychip_t *chip = card->pm_private_data;
diff -Nru a/Documentation/sound/alsa/VIA82xx-mixer.txt b/Documentation/sound/alsa/VIA82xx-mixer.txt
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/Documentation/sound/alsa/VIA82xx-mixer.txt	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,8 @@
+
+				VIA82xx mixer
+				=============
+
+On many VIA82xx boards, the 'Input Source Select' mixer control does not work.
+Setting it to 'Input2' on such boards will cause recording to hang, or fail
+with EIO (input/output error) via OSS emulation.  This control should be left
+at 'Input1' for such cards.
diff -Nru a/Documentation/sound/alsa/hda_codec.txt b/Documentation/sound/alsa/hda_codec.txt
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/Documentation/sound/alsa/hda_codec.txt	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,299 @@
+Notes on Universal Interface for Intel High Definition Audio Codec
+------------------------------------------------------------------
+
+Takashi Iwai <tiwai@suse.de>
+
+
+[Still a draft version]
+
+
+General
+=======
+
+The snd-hda-codec module supports the generic access function for the
+High Definition (HD) audio codecs.  It's designed to be independent
+from the controller code like ac97 codec module.  The real accessors
+from/to the controller must be implemented in the lowlevel driver.
+
+The structure of this module is similar with ac97_codec module.
+Each codec chip belongs to a bus class which communicates with the
+controller.
+
+
+Initialization of Bus Instance
+==============================
+
+The card driver has to create struct hda_bus at first.  The template
+struct should be filled and passed to the constructor:
+
+struct hda_bus_template {
+	void *private_data;
+	struct pci_dev *pci;
+	const char *modelname;
+	struct hda_bus_ops ops;
+};
+
+The card driver can set and use the private_data field to retrieve its
+own data in callback functions.  The pci field is used when the patch
+needs to check the PCI subsystem IDs, so on.  For non-PCI system, it
+doesn't have to be set, of course.
+The modelname field specifies the board's specific configuration.  The
+string is passed to the codec parser, and it depends on the parser how
+the string is used.
+These fields, private_data, pci and modelname are all optional.
+
+The ops field contains the callback functions as the following:
+
+struct hda_bus_ops {
+	int (*command)(struct hda_codec *codec, hda_nid_t nid, int direct,
+		       unsigned int verb, unsigned int parm);
+	unsigned int (*get_response)(struct hda_codec *codec);
+	void (*private_free)(struct hda_bus *);
+};
+
+The command callback is called when the codec module needs to send a
+VERB to the controller.  It's always a single command.
+The get_response callback is called when the codec requires the answer
+for the last command.  These two callbacks are mandatory and have to
+be given.
+The last, private_free callback, is optional.  It's called in the
+destructor to release any necessary data in the lowlevel driver.
+
+The bus instance is created via snd_hda_bus_new().  You need to pass
+the card instance, the template, and the pointer to store the
+resultant bus instance.
+
+int snd_hda_bus_new(snd_card_t *card, const struct hda_bus_template *temp,
+		    struct hda_bus **busp);
+
+It returns zero if successful.  A negative return value means any
+error during creation.
+
+
+Creation of Codec Instance
+==========================
+
+Each codec chip on the board is then created on the BUS instance.
+To create a codec instance, call snd_hda_codec_new().
+
+int snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr,
+		      struct hda_codec **codecp);
+
+The first argument is the BUS instance, the second argument is the
+address of the codec, and the last one is the pointer to store the
+resultant codec instance (can be NULL if not needed).
+
+The codec is stored in a linked list of bus instance.  You can follow
+the codec list like:
+
+	struct list_head *p;
+	struct hda_codec *codec;
+	list_for_each(p, &bus->codec_list) {
+		codec = list_entry(p, struct hda_codec, list);
+		...
+	}
+
+The codec isn't initialized at this stage properly.  The
+initialization sequence is called when the controls are built later.
+
+
+Codec Access
+============
+
+To access codec, use snd_codec_read() and snd_codec_write().
+snd_hda_param_read() is for reading parameters.
+For writing a sequence of verbs, use snd_hda_sequence_write().
+
+To retrieve the number of sub nodes connected to the given node, use
+snd_hda_get_sub_nodes().  The connection list can be obtained via
+snd_hda_get_connections() call.
+
+When an unsolicited event happens, pass the event via
+snd_hda_queue_unsol_event() so that the codec routines will process it
+later.
+
+
+(Mixer) Controls
+================
+
+To create mixer controls of all codecs, call
+snd_hda_build_controls().  It then builds the mixers and does
+initialization stuff on each codec.
+
+
+PCM Stuff
+=========
+
+snd_hda_build_pcms() gives the necessary information to create PCM
+streams.  When it's called, each codec belonging to the bus stores 
+codec->num_pcms and codec->pcm_info fields.  The num_pcms indicates
+the number of elements in pcm_info array.  The card driver is supposed
+to traverse the codec linked list, read the pcm information in
+pcm_info array, and build pcm instances according to them. 
+
+The pcm_info array contains the following record:
+
+/* PCM information for each substream */
+struct hda_pcm_stream {
+	unsigned int substreams;	/* number of substreams, 0 = not exist */
+	unsigned int channels_min;	/* min. number of channels */
+	unsigned int channels_max;	/* max. number of channels */
+	hda_nid_t nid;	/* default NID to query rates/formats/bps, or set up */
+	u32 rates;	/* supported rates */
+	u64 formats;	/* supported formats (SNDRV_PCM_FMTBIT_) */
+	unsigned int maxbps;	/* supported max. bit per sample */
+	struct hda_pcm_ops ops;
+};
+
+/* for PCM creation */
+struct hda_pcm {
+	char *name;
+	struct hda_pcm_stream stream[2];
+};
+
+The name can be passed to snd_pcm_new().  The stream field contains
+the information  for playback (SNDRV_PCM_STREAM_PLAYBACK = 0) and
+capture (SNDRV_PCM_STREAM_CAPTURE = 1) directions.  The card driver
+should pass substreams to snd_pcm_new() for the number of substreams
+to create.
+
+The channels_min, channels_max, rates and formats should be copied to
+runtime->hw record.  They and maxbps fields are used also to compute
+the format value for the HDA codec and controller.  Call
+snd_hda_calc_stream_format() to get the format value.
+
+The ops field contains the following callback functions:
+
+struct hda_pcm_ops {
+	int (*open)(struct hda_pcm_stream *info, struct hda_codec *codec,
+		    snd_pcm_substream_t *substream);
+	int (*close)(struct hda_pcm_stream *info, struct hda_codec *codec,
+		     snd_pcm_substream_t *substream);
+	int (*prepare)(struct hda_pcm_stream *info, struct hda_codec *codec,
+		       unsigned int stream_tag, unsigned int format,
+		       snd_pcm_substream_t *substream);
+	int (*cleanup)(struct hda_pcm_stream *info, struct hda_codec *codec,
+		       snd_pcm_substream_t *substream);
+};
+
+All are non-NULL, so you can call them safely without NULL check.
+
+The open callback should be called in PCM open after runtime->hw is
+set up.  It may override some setting and constraints additionally.
+Similarly, the close callback should be called in the PCM close.
+
+The prepare callback should be called in PCM prepare.  This will set
+up the codec chip properly for the operation.  The cleanup should be
+called in hw_free to clean up the configuration.
+
+The caller should check the return value, at least for open and
+prepare callbacks.  When a negative value is returned, some error
+occurred.
+
+
+Proc Files
+==========
+
+Each codec dumps the widget node information in
+/proc/asound/card*/codec#* file.  This information would be really
+helpful for debugging.  Please provide its contents together with the
+bug report.
+
+
+Power Management
+================
+
+It's simple:
+Call snd_hda_suspend() in the PM suspend callback.
+Call snd_hda_resume() in the PM resume callback.
+
+
+Codec Preset (Patch)
+====================
+
+To set up and handle the codec functionality fully, each codec may
+have a codec preset (patch).  It's defined in struct hda_codec_preset:
+
+	struct hda_codec_preset {
+		unsigned int id;
+		unsigned int mask;
+		unsigned int subs;
+		unsigned int subs_mask;
+		unsigned int rev;
+		const char *name;
+		int (*patch)(struct hda_codec *codec);
+	};
+
+When the codec id and codec subsystem id match with the given id and
+subs fields bitwise (with bitmask mask and subs_mask), the callback
+patch is called.  The patch callback should initialize the codec and
+set the codec->patch_ops field.  This is defined as below:
+
+	struct hda_codec_ops {
+		int (*build_controls)(struct hda_codec *codec);
+		int (*build_pcms)(struct hda_codec *codec);
+		int (*init)(struct hda_codec *codec);
+		void (*free)(struct hda_codec *codec);
+		void (*unsol_event)(struct hda_codec *codec, unsigned int res);
+	#ifdef CONFIG_PM
+		int (*suspend)(struct hda_codec *codec, pm_message_t state);
+		int (*resume)(struct hda_codec *codec);
+	#endif
+	};
+
+The build_controls callback is called from snd_hda_build_controls().
+Similarly, the build_pcms callback is called from
+snd_hda_build_pcms().  The init callback is called after
+build_controls to initialize the hardware.
+The free callback is called as a destructor.
+
+The unsol_event callback is called when an unsolicited event is
+received.
+
+The suspend and resume callbacks are for power management.
+
+Each entry can be NULL if not necessary to be called.
+
+
+Generic Parser
+==============
+
+When the device doesn't match with any given presets, the widgets are
+parsed via th generic parser (hda_generic.c).  Its support is
+limited: no multi-channel support, for example.
+
+
+Digital I/O
+===========
+
+Call snd_hda_create_spdif_out_ctls() from the patch to create controls
+related with SPDIF out.  In the patch resume callback, call
+snd_hda_resume_spdif().
+
+
+Helper Functions
+================
+
+snd_hda_get_codec_name() stores the codec name on the given string.
+
+snd_hda_check_board_config() can be used to obtain the configuration
+information matching with the device.  Define the table with struct
+hda_board_config entries (zero-terminated), and pass it to the
+function.  The function checks the modelname given as a module
+parameter, and PCI subsystem IDs.  If the matching entry is found, it
+returns the config field value.
+
+snd_hda_add_new_ctls() can be used to create and add control entries.
+Pass the zero-terminated array of snd_kcontrol_new_t.  The same array
+can be passed to snd_hda_resume_ctls() for resume.
+Note that this will call control->put callback of these entries.  So,
+put callback should check codec->in_resume and force to restore the
+given value if it's non-zero even if the value is identical with the
+cached value.
+
+Macros HDA_CODEC_VOLUME(), HDA_CODEC_MUTE() and their variables can be
+used for the entry of snd_kcontrol_new_t.
+
+The input MUX helper callbacks for such a control are provided, too:
+snd_hda_input_mux_info() and snd_hda_input_mux_put().  See
+patch_realtek.c for example.
diff -Nru a/Documentation/sound/alsa/serial-u16550.txt b/Documentation/sound/alsa/serial-u16550.txt
--- a/Documentation/sound/alsa/serial-u16550.txt	2005-03-11 12:51:47 -08:00
+++ b/Documentation/sound/alsa/serial-u16550.txt	2005-03-11 12:51:47 -08:00
@@ -23,12 +23,12 @@
 
 Usage example for simple serial converter:
 
-	/sbin/setserial /dev/ttyS0 none
+	/sbin/setserial /dev/ttyS0 uart none
 	/sbin/modprobe snd-serial-u16550 port=0x3f8 irq=4 speed=115200
 
 Usage example for Roland SoundCanvas with 4 MIDI ports:
 
-	/sbin/setserial /dev/ttyS0 none
+	/sbin/setserial /dev/ttyS0 uart none
 	/sbin/modprobe snd-serial-u16550 port=0x3f8 irq=4 outs=4
 
 In MS-124T mode, one raw MIDI substream is supported (midiCnD0); the outs
@@ -38,7 +38,7 @@
 
 Usage example for MS-124T, with A-B switch in A position:
 
-	/sbin/setserial /dev/ttyS0 none
+	/sbin/setserial /dev/ttyS0 uart none
 	/sbin/modprobe snd-serial-u16550 port=0x3f8 irq=4 adaptor=1 \
 			speed=19200
 
@@ -48,7 +48,7 @@
 
 Usage example for S/A mode:
 
-	/sbin/setserial /dev/ttyS0 none
+	/sbin/setserial /dev/ttyS0 uart none
 	/sbin/modprobe snd-serial-u16550 port=0x3f8 irq=4 adaptor=2
 
 In MS-124W M/B mode, the driver supports 16 ALSA raw MIDI substreams;
@@ -64,7 +64,7 @@
 
 Usage example for M/B mode:
 
-	/sbin/setserial /dev/ttyS0 none
+	/sbin/setserial /dev/ttyS0 uart none
 	/sbin/modprobe snd-serial-u16550 port=0x3f8 irq=4 adaptor=3
 
 The MS-124W hardware's M/A mode is currently not supported. This mode allows
diff -Nru a/Documentation/tty.txt b/Documentation/tty.txt
--- a/Documentation/tty.txt	2005-03-11 12:51:52 -08:00
+++ b/Documentation/tty.txt	2005-03-11 12:51:52 -08:00
@@ -93,6 +93,11 @@
 			ldisc must be careful about setting order and to
 			handle unexpected calls. Must not sleep.
 
+			The driver is forbidden from calling this directly
+			from the ->write call from the ldisc as the ldisc
+			is permitted to call the driver write method from
+			this function. In such a situation defer it.
+
 
 Locking
 
diff -Nru a/Documentation/usb/error-codes.txt b/Documentation/usb/error-codes.txt
--- a/Documentation/usb/error-codes.txt	2005-03-11 12:51:40 -08:00
+++ b/Documentation/usb/error-codes.txt	2005-03-11 12:51:40 -08:00
@@ -23,6 +23,9 @@
 
 -ENODEV		specified USB-device or bus doesn't exist
 
+-ENOENT		specified interface or endpoint does not exist or
+		is not enabled
+
 -ENXIO		host controller driver does not support queuing of this type
 		of urb.  (treat as a host controller bug.)
 
@@ -88,13 +91,19 @@
 			   prescribed bus turn-around time
 			c) unknown USB error 
 
-			In cases b) and c) either -EPROTO or -EILSEQ
-			may be returned.  Note that often the controller
-			hardware does not distinguish among cases a),
-			b), and c), so a driver cannot tell whether
-			there was a protocol error, a failure to respond
-			(often caused by device disconnect), or some
-			other fault.
+			Note that often the controller hardware does not
+			distinguish among cases a), b), and c), so a
+			driver cannot tell whether there was a protocol
+			error, a failure to respond (often caused by
+			device disconnect), or some other fault.
+
+-ETIMEDOUT (**)		No response packet received within the prescribed
+			bus turn-around time.  This error may instead be
+			reported as -EPROTO or -EILSEQ.
+
+			Note that the synchronous USB message functions
+			also use this code to indicate timeout expired
+			before the transfer completed.
 
 -EPIPE (**)		Endpoint stalled.  For non-control endpoints,
 			reset this status with usb_clear_halt().
@@ -152,4 +161,7 @@
 usb_get_*/usb_set_*():
 usb_control_msg():
 usb_bulk_msg():
--ETIMEDOUT		timeout expired before the transfer completed
+-ETIMEDOUT		Timeout expired before the transfer completed.
+			In the future this code may change to -ETIME,
+			whose definition is a closer match to this sort
+			of error.
diff -Nru a/Documentation/usb/sn9c102.txt b/Documentation/usb/sn9c102.txt
--- a/Documentation/usb/sn9c102.txt	2005-03-11 12:51:51 -08:00
+++ b/Documentation/usb/sn9c102.txt	2005-03-11 12:51:51 -08:00
@@ -210,8 +210,8 @@
 SN9C10x bridge, while the other two control the sensor chip. "reg" and
 "i2c_reg" hold the values of the current register index where the following
 reading/writing operations are addressed at through "val" and "i2c_val". Their
-use is not intended for end-users. Note that "i2c_reg" and "i2c_val" won't be
-created if the sensor does not actually support the standard I2C protocol or
+use is not intended for end-users. Note that "i2c_reg" and "i2c_val" will not
+be created if the sensor does not actually support the standard I2C protocol or
 its registers are not 8-bit long. Also, remember that you must be logged in as
 root before writing to them.
 
@@ -341,15 +341,8 @@
 All the available control settings of each image sensor are supported through
 the V4L2 interface.
 
-If you think your camera is based on the above hardware and is not actually
-listed in the above table, you may try to add the specific USB VendorID and
-ProductID identifiers to the sn9c102_id_table[] in the file "sn9c102_sensor.h";
-then compile, load the module again and look at the kernel output.
-If this works, please send an email to the author reporting the kernel
-messages, so that a new entry in the list of supported devices can be added.
-
 Donations of new models for further testing and support would be much
-appreciated. Non-available hardware won't be supported by the author of this
+appreciated. Non-available hardware will not be supported by the author of this
 driver.
 
 
diff -Nru a/MAINTAINERS b/MAINTAINERS
--- a/MAINTAINERS	2005-03-11 12:51:47 -08:00
+++ b/MAINTAINERS	2005-03-11 12:51:47 -08:00
@@ -457,6 +457,11 @@
 M:	marcel@holtmann.org
 S:	Maintained
 
+BLUETOOTH HCI BPA10X DRIVER
+P:	Marcel Holtmann
+M:	marcel@holtmann.org
+S:	Maintained
+
 BLUETOOTH HCI BFUSB DRIVER
 P:	Marcel Holtmann
 M:	marcel@holtmann.org
@@ -596,11 +601,10 @@
 S:	Maintained
 
 CRYPTO API
-P:	James Morris
-M:	jmorris@redhat.com
+P:	Herbert Xu
+M:	herbert@gondor.apana.org.au
 P:	David S. Miller
 M:	davem@davemloft.net
-W	http://samba.org/~jamesm/crypto/
 L:	linux-kernel@vger.kernel.org
 S:	Maintained
 
@@ -754,8 +758,10 @@
 S:	Supported
 
 DRM DRIVERS
+P:	David Airlie
+M:	airlied@linux.ie
 L:	dri-devel@lists.sourceforge.net
-S:	Supported
+S:	Maintained
 
 DSCC4 DRIVER
 P:	François Romieu
@@ -910,10 +916,17 @@
 W:	http://www.icp-vortex.com/
 S:	Supported
 
-GENERIC HDLC DRIVER, N2 AND C101 DRIVERS
+GENERIC HDLC DRIVER, N2, C101, PCI200SYN and WANXL DRIVERS
 P:	Krzysztof Halasa
 M:	khc@pm.waw.pl
-W:	http://hq.pm.waw.pl/hdlc/
+W:	http://www.kernel.org/pub/linux/utils/net/hdlc/
+S:	Maintained
+
+HARMONY SOUND DRIVER
+P:	Kyle McMartin
+M:	kyle@parisc-linux.org
+W:	http://www.parisc-linux.org/~kyle/harmony/
+L:	parisc-linux@lists.parisc-linux.org
 S:	Maintained
 
 HAYES ESP SERIAL DRIVER
@@ -991,8 +1004,8 @@
 I2C AND SENSORS DRIVERS
 P:	Greg Kroah-Hartman
 M:	greg@kroah.com
-P:	Philip Edelbrock
-M:	phil@netroedge.com
+P:	Jean Delvare
+M:	khali@linux-fr.org
 L:	sensors@stimpy.netroedge.com
 W:	http://www.lm-sensors.nu/
 S:	Maintained
@@ -1082,9 +1095,21 @@
 L:	linux-kernel@vger.kernel.org
 S:	Maintained
 
+IEEE 1394 ETHERNET (eth1394)
+L:	linux1394-devel@lists.sourceforge.net
+W:	http://www.linux1394.org/
+S:	Orphan
+
+IEEE 1394 SBP2
+L:	linux1394-devel@lists.sourceforge.net
+W:	http://www.linux1394.org/
+S:	Orphan
+
 IEEE 1394 SUBSYSTEM
 P:	Ben Collins
 M:	bcollins@debian.org
+P:	Jody McIntyre
+M:	scjody@steamballoon.com
 L:	linux1394-devel@lists.sourceforge.net
 W:	http://www.linux1394.org/
 S:	Maintained
@@ -1092,13 +1117,15 @@
 IEEE 1394 OHCI DRIVER
 P:	Ben Collins
 M:	bcollins@debian.org
+P:	Jody McIntyre
+M:	scjody@steamballoon.com
 L:	linux1394-devel@lists.sourceforge.net
 W:	http://www.linux1394.org/
 S:	Maintained
 
 IEEE 1394 PCILYNX DRIVER
-P:	Andreas Bombe
-M:	andreas.bombe@munich.netsurf.de
+P:	Jody McIntyre
+M:	scjody@steamballoon.com
 L:	linux1394-devel@lists.sourceforge.net
 W:	http://www.linux1394.org/
 S:	Maintained
@@ -1106,6 +1133,8 @@
 IEEE 1394 RAW I/O DRIVER
 P:	Ben Collins
 M:	bcollins@debian.org
+P:	Dan Dennedy
+M:	dan@dennedy.org
 L:	linux1394-devel@lists.sourceforge.net
 W:	http://www.linux1394.org/
 S:	Maintained
@@ -1247,8 +1276,8 @@
 JFS FILESYSTEM
 P:	Dave Kleikamp
 M:	shaggy@austin.ibm.com
-L:	jfs-discussion@oss.software.ibm.com
-W:	http://oss.software.ibm.com/jfs/
+L:	jfs-discussion@lists.sourceforge.net
+W:	http://jfs.sourceforge.net/
 S:	Supported
 
 KCONFIG
@@ -1372,7 +1401,7 @@
 L:	linuxppc-embedded@ozlabs.org
 S:	Maintained
 
-LINUX FOR POWERPC EMBEDDED PPC85XX
+LINUX FOR POWERPC EMBEDDED PPC83XX AND PPC85XX
 P:     Kumar Gala
 M:     kumar.gala@freescale.com
 W:     http://www.penguinppc.org/
@@ -1966,6 +1995,11 @@
 W:	http://www.weinigel.se
 S:	Supported
 
+SECURITY CONTACT
+P:	Security Officers
+M:	security@kernel.org
+S:	Supported
+
 SELINUX SECURITY MODULE
 P:	Stephen Smalley
 M:	sds@epoch.ncsc.mil
@@ -2028,6 +2062,12 @@
 W:	http://www.winischhofer.net/linuxsisvga.shtml
 S:	Maintained	
 
+SIS USB2VGA DRIVER
+P:	Thomas Winischhofer
+M:	thomas@winischhofer.net
+W:	http://www.winischhofer.at/linuxsisusbvga.shtml
+S:	Maintained
+
 SMSC47M1 HARDWARE MONITOR DRIVER
 P:	Jean Delvare
 M:	khali@linux-fr.org
@@ -2162,9 +2202,10 @@
 P:	Paul Mundt
 M:	lethal@linux-sh.org
 P:	Richard Curnow
-M:	richard.curnow@superh.com
+M:	rc@rc0.org.uk
 L:	linuxsh-shmedia-dev@lists.sourceforge.net
 W:	http://www.linux-sh.org
+W:	http://www.rc0.org.uk/sh64
 S:	Maintained
 
 SUN3/3X
@@ -2376,6 +2417,12 @@
 W:	http://www.chello.nl/~j.vreeken/se401/
 S:	Maintained
 
+USB SERIAL CYBERJACK DRIVER
+P:	Matthias Bruestle and Harald Welte
+M:	support@reiner-sct.com
+W:	http://www.reiner-sct.de/support/treiber_cyberjack.php
+S:	Maintained
+
 USB SERIAL DIGI ACCELEPORT DRIVER
 P:	Peter Berger and Al Borchers
 M:	pberger@brimson.com
@@ -2475,6 +2522,14 @@
 M:	luca.risolia@studio.unibo.it
 L:	linux-usb-devel@lists.sourceforge.net
 W:	http://www.linux-projects.org
+S:	Maintained
+
+USB ZD1201 DRIVER
+P:	Jeroen Vreeken
+M:	pe1rxq@amsat.org
+L:	linux-usb-users@lists.sourceforge.net
+L:	linux-usb-devel@lists.sourceforge.net
+W:	http://linux-lc100020.sourceforge.net
 S:	Maintained
 
 USER-MODE LINUX
diff -Nru a/REPORTING-BUGS b/REPORTING-BUGS
--- a/REPORTING-BUGS	2005-03-11 12:51:46 -08:00
+++ b/REPORTING-BUGS	2005-03-11 12:51:46 -08:00
@@ -16,6 +16,10 @@
 describe how to recreate it. That is worth even more than the oops itself.
 The list of maintainers is in the MAINTAINERS file in this directory.
 
+      If it is a security bug, please copy the Security Contact listed
+in the MAINTAINERS file.  They can help coordinate bugfix and disclosure.
+See Documentation/SecurityBugs for more infomation.
+
       If you are totally stumped as to whom to send the report, send it to
 linux-kernel@vger.kernel.org. (For more information on the linux-kernel
 mailing list see http://www.tux.org/lkml/).
diff -Nru a/arch/arm/Kconfig b/arch/arm/Kconfig
--- a/arch/arm/Kconfig	2005-03-11 12:51:46 -08:00
+++ b/arch/arm/Kconfig	2005-03-11 12:51:46 -08:00
@@ -231,7 +231,7 @@
 
 config SHARP_LOCOMO
 	bool
-	depends on SA1100_COLLIE
+	depends on SA1100_COLLIE || MACH_POODLE
 	default y
 
 config SHARP_SCOOP
diff -Nru a/arch/arm/common/locomo.c b/arch/arm/common/locomo.c
--- a/arch/arm/common/locomo.c	2005-03-11 12:51:40 -08:00
+++ b/arch/arm/common/locomo.c	2005-03-11 12:51:40 -08:00
@@ -34,11 +34,33 @@
 
 #include <asm/hardware/locomo.h>
 
+/* M62332 output channel selection */
+#define M62332_EVR_CH	1	/* M62332 volume channel number  */
+				/*   0 : CH.1 , 1 : CH. 2        */
+/* DAC send data */
+#define	M62332_SLAVE_ADDR	0x4e	/* Slave address  */
+#define	M62332_W_BIT		0x00	/* W bit (0 only) */
+#define	M62332_SUB_ADDR		0x00	/* Sub address    */
+#define	M62332_A_BIT		0x00	/* A bit (0 only) */
+
+/* DAC setup and hold times (expressed in us) */
+#define DAC_BUS_FREE_TIME	5	/*   4.7 us */
+#define DAC_START_SETUP_TIME	5	/*   4.7 us */
+#define DAC_STOP_SETUP_TIME	4	/*   4.0 us */
+#define DAC_START_HOLD_TIME	5	/*   4.7 us */
+#define DAC_SCL_LOW_HOLD_TIME	5	/*   4.7 us */
+#define DAC_SCL_HIGH_HOLD_TIME	4	/*   4.0 us */
+#define DAC_DATA_SETUP_TIME	1	/*   250 ns */
+#define DAC_DATA_HOLD_TIME	1	/*   300 ns */
+#define DAC_LOW_SETUP_TIME	1	/*   300 ns */
+#define DAC_HIGH_SETUP_TIME	1	/*  1000 ns */
+
 /* the following is the overall data for the locomo chip */
 struct locomo {
 	struct device *dev;
 	unsigned long phys;
 	unsigned int irq;
+	spinlock_t lock;
 	void *base;
 };
 
@@ -50,7 +72,57 @@
 	const char *	name;
 };
 
+/* All the locomo devices.  If offset is non-zero, the mapbase for the
+ * locomo_dev will be set to the chip base plus offset.  If offset is
+ * zero, then the mapbase for the locomo_dev will be set to zero.  An
+ * offset of zero means the device only uses GPIOs or other helper
+ * functions inside this file */
 static struct locomo_dev_info locomo_devices[] = {
+	{
+		.devid 		= LOCOMO_DEVID_KEYBOARD,
+		.irq = {
+			IRQ_LOCOMO_KEY,
+		},
+		.name		= "locomo-keyboard",
+		.offset		= LOCOMO_KEYBOARD,
+		.length		= 16,
+	},
+	{
+		.devid		= LOCOMO_DEVID_FRONTLIGHT,
+		.irq		= {},
+		.name		= "locomo-frontlight",
+		.offset		= LOCOMO_FRONTLIGHT,
+		.length		= 8,
+
+	},
+	{
+		.devid		= LOCOMO_DEVID_BACKLIGHT,
+		.irq		= {},
+		.name		= "locomo-backlight",
+		.offset		= LOCOMO_BACKLIGHT,
+		.length		= 8,
+	},
+	{
+		.devid		= LOCOMO_DEVID_AUDIO,
+		.irq		= {},
+		.name		= "locomo-audio",
+		.offset		= LOCOMO_AUDIO,
+		.length		= 4,
+	},
+	{
+		.devid		= LOCOMO_DEVID_LED,
+		.irq 		= {},
+		.name		= "locomo-led",
+		.offset		= LOCOMO_LED,
+		.length		= 8,
+	},
+	{
+		.devid		= LOCOMO_DEVID_UART,
+		.irq		= {},
+		.name		= "locomo-uart",
+		.offset		= 0,
+		.length		= 0,
+	},
 };
 
 
@@ -146,7 +218,7 @@
 	struct irqdesc *d;
 	void *mapbase = get_irq_chipdata(irq);
 
-	if (locomo_readl(mapbase + LOCOMO_KIC) & 0x0001) {
+	if (locomo_readl(mapbase + LOCOMO_KEYBOARD + LOCOMO_KIC) & 0x0001) {
 		d = irq_desc + LOCOMO_IRQ_KEY_START;
 		d->handle(LOCOMO_IRQ_KEY_START, d, regs);
 	}
@@ -156,27 +228,27 @@
 {
 	void *mapbase = get_irq_chipdata(irq);
 	unsigned int r;
-	r = locomo_readl(mapbase + LOCOMO_KIC);
+	r = locomo_readl(mapbase + LOCOMO_KEYBOARD + LOCOMO_KIC);
 	r &= ~(0x0100 << (irq - LOCOMO_IRQ_KEY_START));
-	locomo_writel(r, mapbase + LOCOMO_KIC);
+	locomo_writel(r, mapbase + LOCOMO_KEYBOARD + LOCOMO_KIC);
 }
 
 static void locomo_key_mask_irq(unsigned int irq)
 {
 	void *mapbase = get_irq_chipdata(irq);
 	unsigned int r;
-	r = locomo_readl(mapbase + LOCOMO_KIC);
+	r = locomo_readl(mapbase + LOCOMO_KEYBOARD + LOCOMO_KIC);
 	r &= ~(0x0010 << (irq - LOCOMO_IRQ_KEY_START));
-	locomo_writel(r, mapbase + LOCOMO_KIC);
+	locomo_writel(r, mapbase + LOCOMO_KEYBOARD + LOCOMO_KIC);
 }
 
 static void locomo_key_unmask_irq(unsigned int irq)
 {
 	void *mapbase = get_irq_chipdata(irq);
 	unsigned int r;
-	r = locomo_readl(mapbase + LOCOMO_KIC);
+	r = locomo_readl(mapbase + LOCOMO_KEYBOARD + LOCOMO_KIC);
 	r |= (0x0010 << (irq - LOCOMO_IRQ_KEY_START));
-	locomo_writel(r, mapbase + LOCOMO_KIC);
+	locomo_writel(r, mapbase + LOCOMO_KEYBOARD + LOCOMO_KIC);
 }
 
 static struct irqchip locomo_key_chip = {
@@ -421,13 +493,11 @@
 {
 	struct locomo_dev *dev = LOCOMO_DEV(_dev);
 
-	release_resource(&dev->res);
 	kfree(dev);
 }
 
 static int
-locomo_init_one_child(struct locomo *lchip, struct resource *parent,
-		      struct locomo_dev_info *info)
+locomo_init_one_child(struct locomo *lchip, struct locomo_dev_info *info)
 {
 	struct locomo_dev *dev;
 	int ret;
@@ -454,25 +524,17 @@
 	dev->dev.bus     = &locomo_bus_type;
 	dev->dev.release = locomo_dev_release;
 	dev->dev.coherent_dma_mask = lchip->dev->coherent_dma_mask;
-	dev->res.start   = lchip->phys + info->offset;
-	dev->res.end     = dev->res.start + info->length;
-	dev->res.name    = dev->dev.bus_id;
-	dev->res.flags   = IORESOURCE_MEM;
-	dev->mapbase     = lchip->base + info->offset;
-	memmove(dev->irq, info->irq, sizeof(dev->irq));
 
-	if (info->length) {
-		ret = request_resource(parent, &dev->res);
-		if (ret) {
-			printk("LoCoMo: failed to allocate resource for %s\n",
-				dev->res.name);
-			goto out;
-		}
-	}
+	if (info->offset)
+		dev->mapbase = lchip->base + info->offset;
+	else
+		dev->mapbase = 0;
+	dev->length = info->length;
+
+	memmove(dev->irq, info->irq, sizeof(dev->irq));
 
 	ret = device_register(&dev->dev);
 	if (ret) {
-		release_resource(&dev->res);
  out:
 		kfree(dev);
 	}
@@ -504,6 +566,8 @@
 
 	memset(lchip, 0, sizeof(struct locomo));
 
+	spin_lock_init(&lchip->lock);
+
 	lchip->dev = me;
 	dev_set_drvdata(lchip->dev, lchip);
 
@@ -523,7 +587,7 @@
 	/* locomo initialize */
 	locomo_writel(0, lchip->base + LOCOMO_ICR);
 	/* KEYBOARD */
-	locomo_writel(0, lchip->base + LOCOMO_KIC);
+	locomo_writel(0, lchip->base + LOCOMO_KEYBOARD + LOCOMO_KIC);
 
 	/* GPIO */
 	locomo_writel(0, lchip->base + LOCOMO_GPO);
@@ -534,8 +598,8 @@
 	locomo_writel(0, lchip->base + LOCOMO_GIE);
 
 	/* FrontLight */
-	locomo_writel(0, lchip->base + LOCOMO_ALS);
-	locomo_writel(0, lchip->base + LOCOMO_ALD);
+	locomo_writel(0, lchip->base + LOCOMO_FRONTLIGHT + LOCOMO_ALS);
+	locomo_writel(0, lchip->base + LOCOMO_FRONTLIGHT + LOCOMO_ALD);
 	/* Longtime timer */
 	locomo_writel(0, lchip->base + LOCOMO_LTINT);
 	/* SPI */
@@ -578,7 +642,7 @@
 		locomo_setup_irq(lchip);
 
 	for (i = 0; i < ARRAY_SIZE(locomo_devices); i++)
-		locomo_init_one_child(lchip, mem, &locomo_devices[i]);
+		locomo_init_one_child(lchip, &locomo_devices[i]);
 
 	return 0;
 
@@ -654,6 +718,238 @@
 	return (struct locomo *)dev_get_drvdata(ldev->dev.parent);
 }
 
+void locomo_gpio_set_dir(struct locomo_dev *ldev, unsigned int bits, unsigned int dir)
+{
+	struct locomo *lchip = locomo_chip_driver(ldev);
+	unsigned long flags;
+	unsigned int r;
+
+	spin_lock_irqsave(&lchip->lock, flags);
+
+	r = locomo_readl(lchip->base + LOCOMO_GPD);
+	r &= ~bits;
+	locomo_writel(r, lchip->base + LOCOMO_GPD);
+
+	r = locomo_readl(lchip->base + LOCOMO_GPE);
+	if (dir)
+		r |= bits;
+	else
+		r &= ~bits;
+	locomo_writel(r, lchip->base + LOCOMO_GPE);
+
+	spin_unlock_irqrestore(&lchip->lock, flags);
+}
+
+unsigned int locomo_gpio_read_level(struct locomo_dev *ldev, unsigned int bits)
+{
+	struct locomo *lchip = locomo_chip_driver(ldev);
+	unsigned long flags;
+	unsigned int ret;
+
+	spin_lock_irqsave(&lchip->lock, flags);
+	ret = locomo_readl(lchip->base + LOCOMO_GPL);
+	spin_unlock_irqrestore(&lchip->lock, flags);
+
+	ret &= bits;
+	return ret;
+}
+
+unsigned int locomo_gpio_read_output(struct locomo_dev *ldev, unsigned int bits)
+{
+	struct locomo *lchip = locomo_chip_driver(ldev);
+	unsigned long flags;
+	unsigned int ret;
+
+	spin_lock_irqsave(&lchip->lock, flags);
+	ret = locomo_readl(lchip->base + LOCOMO_GPO);
+	spin_unlock_irqrestore(&lchip->lock, flags);
+
+	ret &= bits;
+	return ret;
+}
+
+void locomo_gpio_write(struct locomo_dev *ldev, unsigned int bits, unsigned int set)
+{
+	struct locomo *lchip = locomo_chip_driver(ldev);
+	unsigned long flags;
+	unsigned int r;
+
+	spin_lock_irqsave(&lchip->lock, flags);
+
+	r = locomo_readl(lchip->base + LOCOMO_GPO);
+	if (set)
+		r |= bits;
+	else
+		r &= ~bits;
+	locomo_writel(r, lchip->base + LOCOMO_GPO);
+
+	spin_unlock_irqrestore(&lchip->lock, flags);
+}
+
+static void locomo_m62332_sendbit(void *mapbase, int bit)
+{
+	unsigned int r;
+
+	r = locomo_readl(mapbase + LOCOMO_DAC);
+	r &=  ~(LOCOMO_DAC_SCLOEB);
+	locomo_writel(r, mapbase + LOCOMO_DAC);
+	udelay(DAC_LOW_SETUP_TIME);	/* 300 nsec */
+	udelay(DAC_DATA_HOLD_TIME);	/* 300 nsec */
+	r = locomo_readl(mapbase + LOCOMO_DAC);
+	r &=  ~(LOCOMO_DAC_SCLOEB);
+	locomo_writel(r, mapbase + LOCOMO_DAC);
+	udelay(DAC_LOW_SETUP_TIME);	/* 300 nsec */
+	udelay(DAC_SCL_LOW_HOLD_TIME);	/* 4.7 usec */
+
+	if (bit & 1) {
+		r = locomo_readl(mapbase + LOCOMO_DAC);
+		r |=  LOCOMO_DAC_SDAOEB;
+		locomo_writel(r, mapbase + LOCOMO_DAC);
+		udelay(DAC_HIGH_SETUP_TIME);	/* 1000 nsec */
+	} else {
+		r = locomo_readl(mapbase + LOCOMO_DAC);
+		r &=  ~(LOCOMO_DAC_SDAOEB);
+		locomo_writel(r, mapbase + LOCOMO_DAC);
+		udelay(DAC_LOW_SETUP_TIME);	/* 300 nsec */
+	}
+
+	udelay(DAC_DATA_SETUP_TIME);	/* 250 nsec */
+	r = locomo_readl(mapbase + LOCOMO_DAC);
+	r |=  LOCOMO_DAC_SCLOEB;
+	locomo_writel(r, mapbase + LOCOMO_DAC);
+	udelay(DAC_HIGH_SETUP_TIME);	/* 1000 nsec */
+	udelay(DAC_SCL_HIGH_HOLD_TIME);	/*  4.0 usec */
+}
+
+void locomo_m62332_senddata(struct locomo_dev *ldev, unsigned int dac_data, int channel)
+{
+	struct locomo *lchip = locomo_chip_driver(ldev);
+	int i;
+	unsigned char data;
+	unsigned int r;
+	void *mapbase = lchip->base;
+	unsigned long flags;
+
+	spin_lock_irqsave(&lchip->lock, flags);
+
+	/* Start */
+	udelay(DAC_BUS_FREE_TIME);	/* 5.0 usec */
+	r = locomo_readl(mapbase + LOCOMO_DAC);
+	r |=  LOCOMO_DAC_SCLOEB | LOCOMO_DAC_SDAOEB;
+	locomo_writel(r, mapbase + LOCOMO_DAC);
+	udelay(DAC_HIGH_SETUP_TIME);	/* 1000 nsec */
+	udelay(DAC_SCL_HIGH_HOLD_TIME);	/* 4.0 usec */
+	r = locomo_readl(mapbase + LOCOMO_DAC);
+	r &=  ~(LOCOMO_DAC_SDAOEB);
+	locomo_writel(r, mapbase + LOCOMO_DAC);
+	udelay(DAC_START_HOLD_TIME);	/* 5.0 usec */
+	udelay(DAC_DATA_HOLD_TIME);	/* 300 nsec */
+
+	/* Send slave address and W bit (LSB is W bit) */
+	data = (M62332_SLAVE_ADDR << 1) | M62332_W_BIT;
+	for (i = 1; i <= 8; i++) {
+		locomo_m62332_sendbit(mapbase, data >> (8 - i));
+	}
+
+	/* Check A bit */
+	r = locomo_readl(mapbase + LOCOMO_DAC);
+	r &=  ~(LOCOMO_DAC_SCLOEB);
+	locomo_writel(r, mapbase + LOCOMO_DAC);
+	udelay(DAC_LOW_SETUP_TIME);	/* 300 nsec */
+	udelay(DAC_SCL_LOW_HOLD_TIME);	/* 4.7 usec */
+	r = locomo_readl(mapbase + LOCOMO_DAC);
+	r &=  ~(LOCOMO_DAC_SDAOEB);
+	locomo_writel(r, mapbase + LOCOMO_DAC);
+	udelay(DAC_LOW_SETUP_TIME);	/* 300 nsec */
+	r = locomo_readl(mapbase + LOCOMO_DAC);
+	r |=  LOCOMO_DAC_SCLOEB;
+	locomo_writel(r, mapbase + LOCOMO_DAC);
+	udelay(DAC_HIGH_SETUP_TIME);	/* 1000 nsec */
+	udelay(DAC_SCL_HIGH_HOLD_TIME);	/* 4.7 usec */
+	if (locomo_readl(mapbase + LOCOMO_DAC) & LOCOMO_DAC_SDAOEB) {	/* High is error */
+		printk(KERN_WARNING "locomo: m62332_senddata Error 1\n");
+		return;
+	}
+
+	/* Send Sub address (LSB is channel select) */
+	/*    channel = 0 : ch1 select              */
+	/*            = 1 : ch2 select              */
+	data = M62332_SUB_ADDR + channel;
+	for (i = 1; i <= 8; i++) {
+		locomo_m62332_sendbit(mapbase, data >> (8 - i));
+	}
+
+	/* Check A bit */
+	r = locomo_readl(mapbase + LOCOMO_DAC);
+	r &=  ~(LOCOMO_DAC_SCLOEB);
+	locomo_writel(r, mapbase + LOCOMO_DAC);
+	udelay(DAC_LOW_SETUP_TIME);	/* 300 nsec */
+	udelay(DAC_SCL_LOW_HOLD_TIME);	/* 4.7 usec */
+	r = locomo_readl(mapbase + LOCOMO_DAC);
+	r &=  ~(LOCOMO_DAC_SDAOEB);
+	locomo_writel(r, mapbase + LOCOMO_DAC);
+	udelay(DAC_LOW_SETUP_TIME);	/* 300 nsec */
+	r = locomo_readl(mapbase + LOCOMO_DAC);
+	r |=  LOCOMO_DAC_SCLOEB;
+	locomo_writel(r, mapbase + LOCOMO_DAC);
+	udelay(DAC_HIGH_SETUP_TIME);	/* 1000 nsec */
+	udelay(DAC_SCL_HIGH_HOLD_TIME);	/* 4.7 usec */
+	if (locomo_readl(mapbase + LOCOMO_DAC) & LOCOMO_DAC_SDAOEB) {	/* High is error */
+		printk(KERN_WARNING "locomo: m62332_senddata Error 2\n");
+		return;
+	}
+
+	/* Send DAC data */
+	for (i = 1; i <= 8; i++) {
+		locomo_m62332_sendbit(mapbase, dac_data >> (8 - i));
+	}
+
+	/* Check A bit */
+	r = locomo_readl(mapbase + LOCOMO_DAC);
+	r &=  ~(LOCOMO_DAC_SCLOEB);
+	locomo_writel(r, mapbase + LOCOMO_DAC);
+	udelay(DAC_LOW_SETUP_TIME);	/* 300 nsec */
+	udelay(DAC_SCL_LOW_HOLD_TIME);	/* 4.7 usec */
+	r = locomo_readl(mapbase + LOCOMO_DAC);
+	r &=  ~(LOCOMO_DAC_SDAOEB);
+	locomo_writel(r, mapbase + LOCOMO_DAC);
+	udelay(DAC_LOW_SETUP_TIME);	/* 300 nsec */
+	r = locomo_readl(mapbase + LOCOMO_DAC);
+	r |=  LOCOMO_DAC_SCLOEB;
+	locomo_writel(r, mapbase + LOCOMO_DAC);
+	udelay(DAC_HIGH_SETUP_TIME);	/* 1000 nsec */
+	udelay(DAC_SCL_HIGH_HOLD_TIME);	/* 4.7 usec */
+	if (locomo_readl(mapbase + LOCOMO_DAC) & LOCOMO_DAC_SDAOEB) {	/* High is error */
+		printk(KERN_WARNING "locomo: m62332_senddata Error 3\n");
+		return;
+	}
+
+	/* stop */
+	r = locomo_readl(mapbase + LOCOMO_DAC);
+	r &=  ~(LOCOMO_DAC_SCLOEB);
+	locomo_writel(r, mapbase + LOCOMO_DAC);
+	udelay(DAC_LOW_SETUP_TIME);	/* 300 nsec */
+	udelay(DAC_SCL_LOW_HOLD_TIME);	/* 4.7 usec */
+	r = locomo_readl(mapbase + LOCOMO_DAC);
+	r |=  LOCOMO_DAC_SCLOEB;
+	locomo_writel(r, mapbase + LOCOMO_DAC);
+	udelay(DAC_HIGH_SETUP_TIME);	/* 1000 nsec */
+	udelay(DAC_SCL_HIGH_HOLD_TIME);	/* 4 usec */
+	r = locomo_readl(mapbase + LOCOMO_DAC);
+	r |=  LOCOMO_DAC_SDAOEB;
+	locomo_writel(r, mapbase + LOCOMO_DAC);
+	udelay(DAC_HIGH_SETUP_TIME);	/* 1000 nsec */
+	udelay(DAC_SCL_HIGH_HOLD_TIME);	/* 4 usec */
+
+	r = locomo_readl(mapbase + LOCOMO_DAC);
+	r |=  LOCOMO_DAC_SCLOEB | LOCOMO_DAC_SDAOEB;
+	locomo_writel(r, mapbase + LOCOMO_DAC);
+	udelay(DAC_LOW_SETUP_TIME);	/* 1000 nsec */
+	udelay(DAC_SCL_LOW_HOLD_TIME);	/* 4.7 usec */
+
+	spin_unlock_irqrestore(&lchip->lock, flags);
+}
+
 /*
  *	LoCoMo "Register Access Bus."
  *
@@ -755,3 +1051,8 @@
 
 EXPORT_SYMBOL(locomo_driver_register);
 EXPORT_SYMBOL(locomo_driver_unregister);
+EXPORT_SYMBOL(locomo_gpio_set_dir);
+EXPORT_SYMBOL(locomo_gpio_read_level);
+EXPORT_SYMBOL(locomo_gpio_read_output);
+EXPORT_SYMBOL(locomo_gpio_write);
+EXPORT_SYMBOL(locomo_m62332_senddata);
diff -Nru a/arch/arm/common/rtctime.c b/arch/arm/common/rtctime.c
--- a/arch/arm/common/rtctime.c	2005-03-11 12:51:41 -08:00
+++ b/arch/arm/common/rtctime.c	2005-03-11 12:51:41 -08:00
@@ -94,24 +94,29 @@
 EXPORT_SYMBOL(rtc_time_to_tm);
 
 /*
- * Convert Gregorian date to seconds since 01-01-1970 00:00:00.
+ * Does the rtc_time represent a valid date/time?
  */
-int rtc_tm_to_time(struct rtc_time *tm, unsigned long *time)
+int rtc_valid_tm(struct rtc_time *tm)
 {
-	unsigned int yrs = tm->tm_year + 1900;
-
-	*time = 0;
-
-	if (yrs < 1970 ||
+	if (tm->tm_year < 70 ||
 	    tm->tm_mon >= 12 ||
 	    tm->tm_mday < 1 ||
-	    tm->tm_mday > month_days(tm->tm_mon, yrs) ||
+	    tm->tm_mday > month_days(tm->tm_mon, tm->tm_year + 1900) ||
 	    tm->tm_hour >= 24 ||
 	    tm->tm_min >= 60 ||
 	    tm->tm_sec >= 60)
 		return -EINVAL;
 
-	*time = mktime(yrs, tm->tm_mon + 1, tm->tm_mday,
+	return 0;
+}
+EXPORT_SYMBOL(rtc_valid_tm);
+
+/*
+ * Convert Gregorian date to seconds since 01-01-1970 00:00:00.
+ */
+int rtc_tm_to_time(struct rtc_time *tm, unsigned long *time)
+{
+	*time = mktime(tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
 		       tm->tm_hour, tm->tm_min, tm->tm_sec);
 
 	return 0;
@@ -144,7 +149,13 @@
 
 static inline int rtc_set_time(struct rtc_ops *ops, struct rtc_time *tm)
 {
-	return ops->set_time(tm);
+	int ret;
+
+	ret = rtc_valid_tm(tm);
+	if (ret == 0)
+		ret = ops->set_time(tm);
+
+	return ret;
 }
 
 static inline int rtc_read_alarm(struct rtc_ops *ops, struct rtc_wkalrm *alrm)
@@ -412,7 +423,6 @@
 	struct rtc_wkalrm alrm;
 	struct rtc_time tm;
 	char *p = page;
-	int len;
 
 	rtc_read_time(ops, &tm);
 
@@ -461,13 +471,7 @@
 	if (ops->proc)
 		p += ops->proc(p);
 
-	len = (p - page) - off;
-	if (len < 0)
-		len = 0;
-	*eof = len <= count;
-	*start = page + off;
-
-	return len;
+	return p - page;
 }
 
 int register_rtc(struct rtc_ops *ops)
diff -Nru a/arch/arm/common/scoop.c b/arch/arm/common/scoop.c
--- a/arch/arm/common/scoop.c	2005-03-11 12:51:41 -08:00
+++ b/arch/arm/common/scoop.c	2005-03-11 12:51:41 -08:00
@@ -15,47 +15,52 @@
 #include <asm/io.h>
 #include <asm/hardware/scoop.h>
 
-static void __iomem *scoop_io_base;
+#define SCOOP_REG(d,adr) (*(volatile unsigned short*)(d +(adr)))
 
-#define SCOOP_REG(adr) (*(volatile unsigned short*)(scoop_io_base+(adr)))
+struct  scoop_dev {
+	void  *base;
+	spinlock_t scoop_lock;
+	u32 scoop_gpwr;
+};
 
-void reset_scoop(void)
+void reset_scoop(struct device *dev)
 {
-	SCOOP_REG(SCOOP_MCR) = 0x0100;	// 00
-	SCOOP_REG(SCOOP_CDR) = 0x0000;  // 04
-	SCOOP_REG(SCOOP_CPR) = 0x0000;  // 0C
-	SCOOP_REG(SCOOP_CCR) = 0x0000;  // 10
-	SCOOP_REG(SCOOP_IMR) = 0x0000;  // 18
-	SCOOP_REG(SCOOP_IRM) = 0x00FF;  // 14
-	SCOOP_REG(SCOOP_ISR) = 0x0000;  // 1C
-	SCOOP_REG(SCOOP_IRM) = 0x0000;
-}
+	struct scoop_dev *sdev = dev_get_drvdata(dev);
 
-static DEFINE_SPINLOCK(scoop_lock);
-static u32 scoop_gpwr;
+	SCOOP_REG(sdev->base,SCOOP_MCR) = 0x0100;  // 00
+	SCOOP_REG(sdev->base,SCOOP_CDR) = 0x0000;  // 04
+	SCOOP_REG(sdev->base,SCOOP_CPR) = 0x0000;  // 0C
+	SCOOP_REG(sdev->base,SCOOP_CCR) = 0x0000;  // 10
+	SCOOP_REG(sdev->base,SCOOP_IMR) = 0x0000;  // 18
+	SCOOP_REG(sdev->base,SCOOP_IRM) = 0x00FF;  // 14
+	SCOOP_REG(sdev->base,SCOOP_ISR) = 0x0000;  // 1C
+	SCOOP_REG(sdev->base,SCOOP_IRM) = 0x0000;
+}
 
-unsigned short set_scoop_gpio(unsigned short bit)
+unsigned short set_scoop_gpio(struct device *dev, unsigned short bit)
 {
 	unsigned short gpio_bit;
 	unsigned long flag;
+	struct scoop_dev *sdev = dev_get_drvdata(dev);
 
-	spin_lock_irqsave(&scoop_lock, flag);
-	gpio_bit = SCOOP_REG(SCOOP_GPWR) | bit;
-	SCOOP_REG(SCOOP_GPWR) = gpio_bit;
-	spin_unlock_irqrestore(&scoop_lock, flag);
+	spin_lock_irqsave(&sdev->scoop_lock, flag);
+	gpio_bit = SCOOP_REG(sdev->base, SCOOP_GPWR) | bit;
+	SCOOP_REG(sdev->base, SCOOP_GPWR) = gpio_bit;
+	spin_unlock_irqrestore(&sdev->scoop_lock, flag);
 
 	return gpio_bit;
 }
 
-unsigned short reset_scoop_gpio(unsigned short bit)
+unsigned short reset_scoop_gpio(struct device *dev, unsigned short bit)
 {
 	unsigned short gpio_bit;
 	unsigned long flag;
+	struct scoop_dev *sdev = dev_get_drvdata(dev);
 
-	spin_lock_irqsave(&scoop_lock, flag);
-	gpio_bit = SCOOP_REG(SCOOP_GPWR) & ~bit;
-	SCOOP_REG(SCOOP_GPWR) = gpio_bit;
-	spin_unlock_irqrestore(&scoop_lock, flag);
+	spin_lock_irqsave(&sdev->scoop_lock, flag);
+	gpio_bit = SCOOP_REG(sdev->base, SCOOP_GPWR) & ~bit;
+	SCOOP_REG(sdev->base,SCOOP_GPWR) = gpio_bit;
+	spin_unlock_irqrestore(&sdev->scoop_lock, flag);
 
 	return gpio_bit;
 }
@@ -63,25 +68,30 @@
 EXPORT_SYMBOL(set_scoop_gpio);
 EXPORT_SYMBOL(reset_scoop_gpio);
 
-unsigned short read_scoop_reg(unsigned short reg)
+unsigned short read_scoop_reg(struct device *dev, unsigned short reg)
 {
-	return SCOOP_REG(reg);
+	struct scoop_dev *sdev = dev_get_drvdata(dev);
+	return SCOOP_REG(sdev->base,reg);
 }
 
-void write_scoop_reg(unsigned short reg, unsigned short data)
+void write_scoop_reg(struct device *dev, unsigned short reg, unsigned short data)
 {
-	SCOOP_REG(reg)=data;
+	struct scoop_dev *sdev = dev_get_drvdata(dev);
+	SCOOP_REG(sdev->base,reg)=data;
 }
 
 EXPORT_SYMBOL(reset_scoop);
 EXPORT_SYMBOL(read_scoop_reg);
 EXPORT_SYMBOL(write_scoop_reg);
 
+#ifdef CONFIG_PM
 static int scoop_suspend(struct device *dev, uint32_t state, uint32_t level)
 {
 	if (level == SUSPEND_POWER_DOWN) {
-		scoop_gpwr = SCOOP_REG(SCOOP_GPWR);
-		SCOOP_REG(SCOOP_GPWR) = 0;
+		struct scoop_dev *sdev = dev_get_drvdata(dev);
+
+		sdev->scoop_gpwr = SCOOP_REG(sdev->base,SCOOP_GPWR);
+		SCOOP_REG(sdev->base,SCOOP_GPWR) = 0;
 	}
 	return 0;
 }
@@ -89,13 +99,20 @@
 static int scoop_resume(struct device *dev, uint32_t level)
 {
 	if (level == RESUME_POWER_ON) {
-		SCOOP_REG(SCOOP_GPWR) = scoop_gpwr;
+		struct scoop_dev *sdev = dev_get_drvdata(dev);
+
+		SCOOP_REG(sdev->base,SCOOP_GPWR) = sdev->scoop_gpwr;
 	}
 	return 0;
 }
+#else
+#define scoop_suspend	NULL
+#define scoop_resume	NULL
+#endif
 
 int __init scoop_probe(struct device *dev)
 {
+	struct scoop_dev *devptr;
 	struct scoop_config *inf;
 	struct platform_device *pdev = to_platform_device(dev);
 	struct resource *mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -103,25 +120,50 @@
 	if (!mem)
 		return -EINVAL;
 
+	devptr = kmalloc(sizeof(struct scoop_dev), GFP_KERNEL);
+
+	if (!devptr)
+		return  -ENOMEM;
+
+	memset(devptr, 0, sizeof(struct scoop_dev));
+	spin_lock_init(&devptr->scoop_lock);
+
 	inf = dev->platform_data;
-	scoop_io_base = ioremap(mem->start, 0x1000);
-	if (!scoop_io_base)
+	devptr->base = ioremap(mem->start, mem->end - mem->start + 1);
+
+	if (!devptr->base) {
+		kfree(devptr);
 		return -ENOMEM;
+	}
 
-	SCOOP_REG(SCOOP_MCR) = 0x0140;
+	dev_set_drvdata(dev, devptr);
 
-	reset_scoop();
+	printk("Sharp Scoop Device found at 0x%08x -> 0x%08x\n",(unsigned int)mem->start,(unsigned int)devptr->base);
 
-	SCOOP_REG(SCOOP_GPCR) = inf->io_dir & 0xffff;
-	SCOOP_REG(SCOOP_GPWR) = inf->io_out & 0xffff;
+	SCOOP_REG(devptr->base, SCOOP_MCR) = 0x0140;
+	reset_scoop(dev);
+	SCOOP_REG(devptr->base, SCOOP_GPCR) = inf->io_dir & 0xffff;
+	SCOOP_REG(devptr->base, SCOOP_GPWR) = inf->io_out & 0xffff;
 
 	return 0;
 }
 
+static int scoop_remove(struct device *dev)
+{
+	struct scoop_dev *sdev = dev_get_drvdata(dev);
+	if (sdev) {
+		iounmap(sdev->base);
+		kfree(sdev);
+		dev_set_drvdata(dev, NULL);
+	}
+	return 0;
+}
+
 static struct device_driver scoop_driver = {
 	.name		= "sharp-scoop",
 	.bus		= &platform_bus_type,
 	.probe		= scoop_probe,
+	.remove 	= scoop_remove,
 	.suspend	= scoop_suspend,
 	.resume		= scoop_resume,
 };
diff -Nru a/arch/arm/configs/pxa255-idp_defconfig b/arch/arm/configs/pxa255-idp_defconfig
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/arm/configs/pxa255-idp_defconfig	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,765 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.11-rc3
+# Fri Feb 11 16:53:43 2005
+#
+CONFIG_ARM=y
+CONFIG_MMU=y
+CONFIG_UID16=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_IOMAP=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_HOTPLUG=y
+CONFIG_KOBJECT_UEVENT=y
+# CONFIG_IKCONFIG is not set
+# CONFIG_EMBEDDED is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+# CONFIG_MODULE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+# CONFIG_KMOD is not set
+
+#
+# System Type
+#
+# CONFIG_ARCH_CLPS7500 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_CO285 is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_CAMELOT is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_IOP3XX is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_L7200 is not set
+CONFIG_ARCH_PXA=y
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_OMAP is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_IMX is not set
+# CONFIG_ARCH_H720X is not set
+
+#
+# Intel PXA2xx Implementations
+#
+# CONFIG_ARCH_LUBBOCK is not set
+# CONFIG_MACH_MAINSTONE is not set
+CONFIG_ARCH_PXA_IDP=y
+# CONFIG_PXA_SHARPSL is not set
+CONFIG_PXA25x=y
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_XSCALE=y
+CONFIG_CPU_32v5=y
+CONFIG_CPU_ABRT_EV5T=y
+CONFIG_CPU_CACHE_VIVT=y
+CONFIG_CPU_TLB_V4WBI=y
+CONFIG_CPU_MINICACHE=y
+
+#
+# Processor Features
+#
+# CONFIG_ARM_THUMB is not set
+CONFIG_XSCALE_PMU=y
+
+#
+# General setup
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+# CONFIG_XIP_KERNEL is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PC-card bridges
+#
+
+#
+# At least one math emulation must be selected
+#
+CONFIG_FPE_NWFPE=y
+# CONFIG_FPE_NWFPE_XP is not set
+# CONFIG_FPE_FASTFPE is not set
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_PM is not set
+# CONFIG_PREEMPT is not set
+# CONFIG_ARTHUR is not set
+CONFIG_CMDLINE="root=/dev/nfs ip=dhcp console=ttyS0,115200 mem=64M"
+CONFIG_LEDS=y
+CONFIG_LEDS_TIMER=y
+CONFIG_LEDS_CPU=y
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_CONCAT is not set
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+# CONFIG_MTD_AFS_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+CONFIG_MTD_CFI_ADV_OPTIONS=y
+CONFIG_MTD_CFI_NOSWAP=y
+# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set
+# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set
+CONFIG_MTD_CFI_GEOMETRY=y
+# CONFIG_MTD_MAP_BANK_WIDTH_1 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_2 is not set
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+# CONFIG_MTD_CFI_I1 is not set
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+CONFIG_MTD_CFI_INTELEXT=y
+# CONFIG_MTD_CFI_AMDSTD is not set
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+# CONFIG_MTD_XIP is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PHYSMAP is not set
+# CONFIG_MTD_ARM_INTEGRATOR is not set
+# CONFIG_MTD_EDB7312 is not set
+# CONFIG_MTD_SHARP_SL is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLKMTD is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+
+#
+# NAND Flash Device Drivers
+#
+# CONFIG_MTD_NAND is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_RAM is not set
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+# CONFIG_PACKET is not set
+# CONFIG_NETLINK_DEV is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_IP_TCPDIAG=y
+# CONFIG_IP_TCPDIAG_IPV6 is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+CONFIG_SMC91X=y
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+
+#
+# Token Ring devices
+#
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_BLK_DEV_IDEDISK=y
+# CONFIG_IDEDISK_MULTI_MODE is not set
+# CONFIG_BLK_DEV_IDECD is not set
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_IDE_TASK_IOCTL is not set
+
+#
+# IDE chipset support/bugfixes
+#
+# CONFIG_IDE_GENERIC is not set
+# CONFIG_IDE_ARM is not set
+# CONFIG_BLK_DEV_IDEDMA is not set
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+CONFIG_SERIO=y
+# CONFIG_SERIO_SERPORT is not set
+# CONFIG_SERIO_CT82C710 is not set
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_PXA=y
+CONFIG_SERIAL_PXA_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+# CONFIG_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+
+#
+# XFS support
+#
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+# CONFIG_VFAT_FS is not set
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_SYSFS=y
+# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVPTS_FS_XATTR is not set
+# CONFIG_TMPFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+# CONFIG_JFFS2_FS_NAND is not set
+# CONFIG_JFFS2_FS_NOR_ECC is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+# CONFIG_NLS_CODEPAGE_437 is not set
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+CONFIG_NLS_ISO8859_1=y
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Graphics support
+#
+CONFIG_FB=y
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+CONFIG_FB_PXA=y
+# CONFIG_FB_PXA_PARAMETERS is not set
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+
+#
+# Logo configuration
+#
+CONFIG_LOGO=y
+CONFIG_LOGO_LINUX_MONO=y
+CONFIG_LOGO_LINUX_VGA16=y
+CONFIG_LOGO_LINUX_CLUT224=y
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# Misc devices
+#
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+CONFIG_USB_ARCH_HAS_HCD=y
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# Kernel hacking
+#
+CONFIG_DEBUG_KERNEL=y
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_FS is not set
+CONFIG_FRAME_POINTER=y
+CONFIG_DEBUG_USER=y
+# CONFIG_DEBUG_WAITQ is not set
+CONFIG_DEBUG_ERRORS=y
+CONFIG_DEBUG_LL=y
+# CONFIG_DEBUG_ICEDCC is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
diff -Nru a/arch/arm/configs/s3c2410_defconfig b/arch/arm/configs/s3c2410_defconfig
--- a/arch/arm/configs/s3c2410_defconfig	2005-03-11 12:51:42 -08:00
+++ b/arch/arm/configs/s3c2410_defconfig	2005-03-11 12:51:42 -08:00
@@ -86,7 +86,9 @@
 #
 CONFIG_ARCH_BAST=y
 CONFIG_ARCH_H1940=y
+CONFIG_MACH_N30=y
 CONFIG_ARCH_SMDK2410=y
+CONFIG_ARCH_S3C2440=y
 CONFIG_MACH_VR1000=y
 CONFIG_MACH_RX3715=y
 CONFIG_CPU_S3C2410=y
diff -Nru a/arch/arm/kernel/calls.S b/arch/arm/kernel/calls.S
--- a/arch/arm/kernel/calls.S	2005-03-11 12:51:52 -08:00
+++ b/arch/arm/kernel/calls.S	2005-03-11 12:51:52 -08:00
@@ -1,7 +1,7 @@
 /*
  *  linux/arch/arm/kernel/calls.S
  *
- *  Copyright (C) 1995-2004 Russell King
+ *  Copyright (C) 1995-2005 Russell King
  *
  * 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
@@ -10,7 +10,7 @@
  *  This file is included twice in entry-common.S
  */
 #ifndef NR_syscalls
-#define NR_syscalls 288
+#define NR_syscalls 320
 #else
 
 __syscall_start:
@@ -295,6 +295,37 @@
 		.long	sys_mq_notify
 		.long	sys_mq_getsetattr
 /* 280 */	.long	sys_waitid
+		.long	sys_socket
+		.long	sys_bind
+		.long	sys_connect
+		.long	sys_listen
+/* 285 */	.long	sys_accept
+		.long	sys_getsockname
+		.long	sys_getpeername
+		.long	sys_socketpair
+		.long	sys_send
+/* 290 */	.long	sys_sendto
+		.long	sys_recv
+		.long	sys_recvfrom
+		.long	sys_shutdown
+		.long	sys_setsockopt
+/* 295 */	.long	sys_getsockopt
+		.long	sys_sendmsg
+		.long	sys_recvmsg
+		.long	sys_semop
+		.long	sys_semget
+/* 300 */	.long	sys_semctl
+		.long	sys_msgsnd
+		.long	sys_msgrcv
+		.long	sys_msgget
+		.long	sys_msgctl
+/* 305 */	.long	sys_shmat
+		.long	sys_shmdt
+		.long	sys_shmget
+		.long	sys_shmctl
+		.long	sys_add_key
+/* 310 */	.long	sys_request_key
+		.long	sys_keyctl
 __syscall_end:
 
 		.rept	NR_syscalls - (__syscall_end - __syscall_start) / 4
diff -Nru a/arch/arm/kernel/ecard.c b/arch/arm/kernel/ecard.c
--- a/arch/arm/kernel/ecard.c	2005-03-11 12:51:52 -08:00
+++ b/arch/arm/kernel/ecard.c	2005-03-11 12:51:52 -08:00
@@ -85,27 +85,21 @@
 };
 
 asmlinkage extern int
-ecard_loader_reset(volatile unsigned char *pa, loader_t loader);
+ecard_loader_reset(unsigned long base, loader_t loader);
 asmlinkage extern int
-ecard_loader_read(int off, volatile unsigned char *pa, loader_t loader);
+ecard_loader_read(int off, unsigned long base, loader_t loader);
 
-static const struct ecard_id *
-ecard_match_device(const struct ecard_id *ids, struct expansion_card *ec);
-
-static inline unsigned short
-ecard_getu16(unsigned char *v)
+static inline unsigned short ecard_getu16(unsigned char *v)
 {
 	return v[0] | v[1] << 8;
 }
 
-static inline signed long
-ecard_gets24(unsigned char *v)
+static inline signed long ecard_gets24(unsigned char *v)
 {
 	return v[0] | v[1] << 8 | v[2] << 16 | ((v[2] & 0x80) ? 0xff000000 : 0);
 }
 
-static inline ecard_t *
-slot_to_ecard(unsigned int slot)
+static inline ecard_t *slot_to_ecard(unsigned int slot)
 {
 	return slot < MAX_ECARDS ? slot_to_expcard[slot] : NULL;
 }
@@ -122,26 +116,31 @@
  * From a security standpoint, we trust the card vendors.  This
  * may be a misplaced trust.
  */
-#define BUS_ADDR(x) ((((unsigned long)(x)) << 2) + IO_BASE)
-#define POD_INT_ADDR(x)	((volatile unsigned char *)\
-			 ((BUS_ADDR((x)) - IO_BASE) + IO_START))
-
 static void ecard_task_reset(struct ecard_request *req)
 {
 	struct expansion_card *ec = req->ec;
-	if (ec->loader)
-		ecard_loader_reset(POD_INT_ADDR(ec->podaddr), ec->loader);
+	struct resource *res;
+
+	res = ec->slot_no == 8
+		? &ec->resource[ECARD_RES_MEMC]
+		: ec->type == ECARD_EASI
+		  ? &ec->resource[ECARD_RES_EASI]
+		  : &ec->resource[ECARD_RES_IOCSYNC];
+
+	ecard_loader_reset(res->start, ec->loader);
 }
 
 static void ecard_task_readbytes(struct ecard_request *req)
 {
-	unsigned char *buf = (unsigned char *)req->buffer;
-	volatile unsigned char *base_addr =
-		(volatile unsigned char *)POD_INT_ADDR(req->ec->podaddr);
+	struct expansion_card *ec = req->ec;
+	unsigned char *buf = req->buffer;
 	unsigned int len = req->length;
 	unsigned int off = req->address;
 
-	if (req->ec->slot_no == 8) {
+	if (ec->slot_no == 8) {
+		void __iomem *base = (void __iomem *)
+				ec->resource[ECARD_RES_MEMC].start;
+
 		/*
 		 * The card maintains an index which increments the address
 		 * into a 4096-byte page on each access.  We need to keep
@@ -161,7 +160,7 @@
 		 * greater than the offset, reset the hardware index counter.
 		 */
 		if (off == 0 || index > off) {
-			*base_addr = 0;
+			writeb(0, base);
 			index = 0;
 		}
 
@@ -170,21 +169,24 @@
 		 * required offset.  The read bytes are discarded.
 		 */
 		while (index < off) {
-			unsigned char byte;
-			byte = base_addr[page];
+			readb(base + page);
 			index += 1;
 		}
 
 		while (len--) {
-			*buf++ = base_addr[page];
+			*buf++ = readb(base + page);
 			index += 1;
 		}
 	} else {
+		unsigned long base = (ec->type == ECARD_EASI
+			 ? &ec->resource[ECARD_RES_EASI]
+			 : &ec->resource[ECARD_RES_IOCSYNC])->start;
+		void __iomem *pbase = (void __iomem *)base;
 
-		if (!req->use_loader || !req->ec->loader) {
+		if (!req->use_loader || !ec->loader) {
 			off *= 4;
 			while (len--) {
-				*buf++ = base_addr[off];
+				*buf++ = readb(pbase + off);
 				off += 4;
 			}
 		} else {
@@ -194,8 +196,8 @@
 				 * expansion card loader programs.
 				 */
 				*(unsigned long *)0x108 = 0;
-				*buf++ = ecard_loader_read(off++, base_addr,
-							   req->ec->loader);
+				*buf++ = ecard_loader_read(off++, base,
+							   ec->loader);
 			}
 		}
 	}
@@ -406,7 +408,7 @@
 
 static int ecard_def_irq_pending(ecard_t *ec)
 {
-	return !ec->irqmask || ec->irqaddr[0] & ec->irqmask;
+	return !ec->irqmask || readb(ec->irqaddr) & ec->irqmask;
 }
 
 static void ecard_def_fiq_enable(ecard_t *ec, int fiqnr)
@@ -421,7 +423,7 @@
 
 static int ecard_def_fiq_pending(ecard_t *ec)
 {
-	return !ec->fiqmask || ec->fiqaddr[0] & ec->fiqmask;
+	return !ec->fiqmask || readb(ec->fiqaddr) & ec->fiqmask;
 }
 
 static expansioncard_ops_t ecard_default_ops = {
@@ -522,7 +524,7 @@
 			       ec->ops->irqpending(ec) ? "" : "not ");
 		else
 			printk("irqaddr %p, mask = %02X, status = %02X\n",
-			       ec->irqaddr, ec->irqmask, *ec->irqaddr);
+			       ec->irqaddr, ec->irqmask, readb(ec->irqaddr));
 	}
 }
 
@@ -675,7 +677,7 @@
 #define IO_EC_MEMC8_BASE 0
 #endif
 
-unsigned int ecard_address(ecard_t *ec, card_type_t type, card_speed_t speed)
+unsigned int __ecard_address(ecard_t *ec, card_type_t type, card_speed_t speed)
 {
 	unsigned long address = 0;
 	int slot = ec->slot_no;
@@ -779,55 +781,89 @@
 		get_ecard_dev_info);
 }
 
-#define ec_set_resource(ec,nr,st,sz,flg)			\
+#define ec_set_resource(ec,nr,st,sz)				\
 	do {							\
 		(ec)->resource[nr].name = ec->dev.bus_id;	\
 		(ec)->resource[nr].start = st;			\
 		(ec)->resource[nr].end = (st) + (sz) - 1;	\
-		(ec)->resource[nr].flags = flg;			\
+		(ec)->resource[nr].flags = IORESOURCE_MEM;	\
 	} while (0)
 
-static void __init ecard_init_resources(struct expansion_card *ec)
+static void __init ecard_free_card(struct expansion_card *ec)
+{
+	int i;
+
+	for (i = 0; i < ECARD_NUM_RESOURCES; i++)
+		if (ec->resource[i].flags)
+			release_resource(&ec->resource[i]);
+
+	kfree(ec);
+}
+
+static struct expansion_card *__init ecard_alloc_card(int type, int slot)
 {
-	unsigned long base = PODSLOT_IOC4_BASE;
-	unsigned int slot = ec->slot_no;
+	struct expansion_card *ec;
+	unsigned long base;
 	int i;
 
+	ec = kmalloc(sizeof(ecard_t), GFP_KERNEL);
+	if (!ec) {
+		ec = ERR_PTR(-ENOMEM);
+		goto nomem;
+	}
+
+	memset(ec, 0, sizeof(ecard_t));
+
+	ec->slot_no = slot;
+	ec->type = type;
+	ec->irq = NO_IRQ;
+	ec->fiq = NO_IRQ;
+	ec->dma = NO_DMA;
+	ec->ops = &ecard_default_ops;
+
+	snprintf(ec->dev.bus_id, sizeof(ec->dev.bus_id), "ecard%d", slot);
+	ec->dev.parent = NULL;
+	ec->dev.bus = &ecard_bus_type;
+	ec->dev.dma_mask = &ec->dma_mask;
+	ec->dma_mask = (u64)0xffffffff;
+
 	if (slot < 4) {
 		ec_set_resource(ec, ECARD_RES_MEMC,
 				PODSLOT_MEMC_BASE + (slot << 14),
-				PODSLOT_MEMC_SIZE, IORESOURCE_MEM);
-		base = PODSLOT_IOC0_BASE;
-	}
+				PODSLOT_MEMC_SIZE);
+		base = PODSLOT_IOC0_BASE + (slot << 14);
+	} else
+		base = PODSLOT_IOC4_BASE + ((slot - 4) << 14);
 
 #ifdef CONFIG_ARCH_RPC
 	if (slot < 8) {
 		ec_set_resource(ec, ECARD_RES_EASI,
 				PODSLOT_EASI_BASE + (slot << 24),
-				PODSLOT_EASI_SIZE, IORESOURCE_MEM);
+				PODSLOT_EASI_SIZE);
 	}
 
 	if (slot == 8) {
-		ec_set_resource(ec, ECARD_RES_MEMC, NETSLOT_BASE,
-				NETSLOT_SIZE, IORESOURCE_MEM);
+		ec_set_resource(ec, ECARD_RES_MEMC, NETSLOT_BASE, NETSLOT_SIZE);
 	} else
 #endif
 
-	for (i = 0; i <= ECARD_RES_IOCSYNC - ECARD_RES_IOCSLOW; i++) {
+	for (i = 0; i <= ECARD_RES_IOCSYNC - ECARD_RES_IOCSLOW; i++)
 		ec_set_resource(ec, i + ECARD_RES_IOCSLOW,
-				base + (slot << 14) + (i << 19),
-				PODSLOT_IOC_SIZE, IORESOURCE_MEM);
-	}
+				base + (i << 19), PODSLOT_IOC_SIZE);
 
 	for (i = 0; i < ECARD_NUM_RESOURCES; i++) {
-		if (ec->resource[i].start &&
+		if (ec->resource[i].flags &&
 		    request_resource(&iomem_resource, &ec->resource[i])) {
 			printk(KERN_ERR "%s: resource(s) not available\n",
 				ec->dev.bus_id);
 			ec->resource[i].end -= ec->resource[i].start;
 			ec->resource[i].start = 0;
+			ec->resource[i].flags = 0;
 		}
 	}
+
+ nomem:
+	return ec;
 }
 
 static ssize_t ecard_show_irq(struct device *dev, char *buf)
@@ -836,16 +872,12 @@
 	return sprintf(buf, "%u\n", ec->irq);
 }
 
-static DEVICE_ATTR(irq, S_IRUGO, ecard_show_irq, NULL);
-
 static ssize_t ecard_show_dma(struct device *dev, char *buf)
 {
 	struct expansion_card *ec = ECARD_DEV(dev);
 	return sprintf(buf, "%u\n", ec->dma);
 }
 
-static DEVICE_ATTR(dma, S_IRUGO, ecard_show_dma, NULL);
-
 static ssize_t ecard_show_resources(struct device *dev, char *buf)
 {
 	struct expansion_card *ec = ECARD_DEV(dev);
@@ -861,23 +893,33 @@
 	return str - buf;
 }
 
-static DEVICE_ATTR(resource, S_IRUGO, ecard_show_resources, NULL);
-
 static ssize_t ecard_show_vendor(struct device *dev, char *buf)
 {
 	struct expansion_card *ec = ECARD_DEV(dev);
 	return sprintf(buf, "%u\n", ec->cid.manufacturer);
 }
 
-static DEVICE_ATTR(vendor, S_IRUGO, ecard_show_vendor, NULL);
-
 static ssize_t ecard_show_device(struct device *dev, char *buf)
 {
 	struct expansion_card *ec = ECARD_DEV(dev);
 	return sprintf(buf, "%u\n", ec->cid.product);
 }
 
-static DEVICE_ATTR(device, S_IRUGO, ecard_show_device, NULL);
+static ssize_t ecard_show_type(struct device *dev, char *buf)
+{
+	struct expansion_card *ec = ECARD_DEV(dev);
+	return sprintf(buf, "%s\n", ec->type == ECARD_EASI ? "EASI" : "IOC");
+}
+
+static struct device_attribute ecard_dev_attrs[] = {
+	__ATTR(device,   S_IRUGO, ecard_show_device,    NULL),
+	__ATTR(dma,      S_IRUGO, ecard_show_dma,       NULL),
+	__ATTR(irq,      S_IRUGO, ecard_show_irq,       NULL),
+	__ATTR(resource, S_IRUGO, ecard_show_resources, NULL),
+	__ATTR(type,     S_IRUGO, ecard_show_type,      NULL),
+	__ATTR(vendor,   S_IRUGO, ecard_show_vendor,    NULL),
+	__ATTR_NULL,
+};
 
 
 int ecard_request_resources(struct expansion_card *ec)
@@ -927,21 +969,13 @@
 	ecard_t **ecp;
 	ecard_t *ec;
 	struct ex_ecid cid;
-	int i, rc = -ENOMEM;
+	int i, rc;
 
-	ec = kmalloc(sizeof(ecard_t), GFP_KERNEL);
-	if (!ec)
+	ec = ecard_alloc_card(type, slot);
+	if (IS_ERR(ec)) {
+		rc = PTR_ERR(ec);
 		goto nomem;
-
-	memset(ec, 0, sizeof(ecard_t));
-
-	ec->slot_no	= slot;
-	ec->type	= type;
-	ec->irq		= NO_IRQ;
-	ec->fiq		= NO_IRQ;
-	ec->dma		= NO_DMA;
-	ec->card_desc	= NULL;
-	ec->ops		= &ecard_default_ops;
+	}
 
 	rc = -ENODEV;
 	if ((ec->podaddr = ecard_address(ec, type, ECARD_SYNC)) == 0)
@@ -964,7 +998,7 @@
 	ec->cid.fiqmask = cid.r_fiqmask;
 	ec->cid.fiqoff  = ecard_gets24(cid.r_fiqoff);
 	ec->fiqaddr	=
-	ec->irqaddr	= (unsigned char *)ioaddr(ec->podaddr);
+	ec->irqaddr	= (void __iomem *)ioaddr(ec->podaddr);
 
 	if (ec->cid.is) {
 		ec->irqmask = ec->cid.irqmask;
@@ -983,14 +1017,6 @@
 			break;
 		}
 
-	snprintf(ec->dev.bus_id, sizeof(ec->dev.bus_id), "ecard%d", slot);
-	ec->dev.parent = NULL;
-	ec->dev.bus    = &ecard_bus_type;
-	ec->dev.dma_mask = &ec->dma_mask;
-	ec->dma_mask = (u64)0xffffffff;
-
-	ecard_init_resources(ec);
-
 	/*
 	 * hook the interrupt handlers
 	 */
@@ -1017,17 +1043,12 @@
 	slot_to_expcard[slot] = ec;
 
 	device_register(&ec->dev);
-	device_create_file(&ec->dev, &dev_attr_dma);
-	device_create_file(&ec->dev, &dev_attr_irq);
-	device_create_file(&ec->dev, &dev_attr_resource);
-	device_create_file(&ec->dev, &dev_attr_vendor);
-	device_create_file(&ec->dev, &dev_attr_device);
 
 	return 0;
 
-nodev:
-	kfree(ec);
-nomem:
+ nodev:
+	ecard_free_card(ec);
+ nomem:
 	return rc;
 }
 
@@ -1128,9 +1149,15 @@
 	if (drv->shutdown)
 		drv->shutdown(ec);
 	ecard_release(ec);
-	req.fn = ecard_task_reset;
-	req.ec = ec;
-	ecard_call(&req);
+
+	/*
+	 * If this card has a loader, call the reset handler.
+	 */
+	if (ec->loader) {
+		req.fn = ecard_task_reset;
+		req.ec = ec;
+		ecard_call(&req);
+	}
 }
 
 int ecard_register_driver(struct ecard_driver *drv)
@@ -1164,8 +1191,9 @@
 }
 
 struct bus_type ecard_bus_type = {
-	.name	= "ecard",
-	.match	= ecard_match,
+	.name		= "ecard",
+	.dev_attrs	= ecard_dev_attrs,
+	.match		= ecard_match,
 };
 
 static int ecard_bus_init(void)
@@ -1176,7 +1204,7 @@
 postcore_initcall(ecard_bus_init);
 
 EXPORT_SYMBOL(ecard_readchunk);
-EXPORT_SYMBOL(ecard_address);
+EXPORT_SYMBOL(__ecard_address);
 EXPORT_SYMBOL(ecard_register_driver);
 EXPORT_SYMBOL(ecard_remove_driver);
 EXPORT_SYMBOL(ecard_bus_type);
diff -Nru a/arch/arm/kernel/fiq.c b/arch/arm/kernel/fiq.c
--- a/arch/arm/kernel/fiq.c	2005-03-11 12:51:51 -08:00
+++ b/arch/arm/kernel/fiq.c	2005-03-11 12:51:51 -08:00
@@ -46,12 +46,6 @@
 #include <asm/system.h>
 #include <asm/uaccess.h>
 
-#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
-#warning This file requires GCC 3.3.x or older to build.  Alternatively,
-#warning please talk to GCC people to resolve the issues with the
-#warning assembly clobber list.
-#endif
-
 static unsigned long no_fiq_insn;
 
 /* Default reacquire function
@@ -91,44 +85,43 @@
 
 /*
  * Taking an interrupt in FIQ mode is death, so both these functions
- * disable irqs for the duration. 
+ * disable irqs for the duration.  Note - these functions are almost
+ * entirely coded in assembly.
  */
-void set_fiq_regs(struct pt_regs *regs)
+void __attribute__((naked)) set_fiq_regs(struct pt_regs *regs)
 {
 	register unsigned long tmp;
-	__asm__ volatile (
-	"mrs	%0, cpsr\n\
+	asm volatile (
+	"mov	ip, sp\n\
+	stmfd	sp!, {fp, ip, lr, pc}\n\
+	sub	fp, ip, #4\n\
+	mrs	%0, cpsr\n\
 	msr	cpsr_c, %2	@ select FIQ mode\n\
 	mov	r0, r0\n\
 	ldmia	%1, {r8 - r14}\n\
 	msr	cpsr_c, %0	@ return to SVC mode\n\
-	mov	r0, r0"
+	mov	r0, r0\n\
+	ldmea	fp, {fp, sp, pc}"
 	: "=&r" (tmp)
-	: "r" (&regs->ARM_r8), "I" (PSR_I_BIT | PSR_F_BIT | FIQ_MODE)
-	/* These registers aren't modified by the above code in a way
-	   visible to the compiler, but we mark them as clobbers anyway
-	   so that GCC won't put any of the input or output operands in
-	   them.  */
-	: "r8", "r9", "r10", "r11", "r12", "r13", "r14");
+	: "r" (&regs->ARM_r8), "I" (PSR_I_BIT | PSR_F_BIT | FIQ_MODE));
 }
 
-void get_fiq_regs(struct pt_regs *regs)
+void __attribute__((naked)) get_fiq_regs(struct pt_regs *regs)
 {
 	register unsigned long tmp;
-	__asm__ volatile (
-	"mrs	%0, cpsr\n\
+	asm volatile (
+	"mov	ip, sp\n\
+	stmfd	sp!, {fp, ip, lr, pc}\n\
+	sub	fp, ip, #4\n\
+	mrs	%0, cpsr\n\
 	msr	cpsr_c, %2	@ select FIQ mode\n\
 	mov	r0, r0\n\
 	stmia	%1, {r8 - r14}\n\
 	msr	cpsr_c, %0	@ return to SVC mode\n\
-	mov	r0, r0"
+	mov	r0, r0\n\
+	ldmea	fp, {fp, sp, pc}"
 	: "=&r" (tmp)
-	: "r" (&regs->ARM_r8), "I" (PSR_I_BIT | PSR_F_BIT | FIQ_MODE)
-	/* These registers aren't modified by the above code in a way
-	   visible to the compiler, but we mark them as clobbers anyway
-	   so that GCC won't put any of the input or output operands in
-	   them.  */
-	: "r8", "r9", "r10", "r11", "r12", "r13", "r14");
+	: "r" (&regs->ARM_r8), "I" (PSR_I_BIT | PSR_F_BIT | FIQ_MODE));
 }
 
 int claim_fiq(struct fiq_handler *f)
diff -Nru a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c
--- a/arch/arm/kernel/irq.c	2005-03-11 12:51:40 -08:00
+++ b/arch/arm/kernel/irq.c	2005-03-11 12:51:40 -08:00
@@ -56,6 +56,13 @@
 void (*init_arch_irq)(void) __initdata = NULL;
 
 /*
+ * No architecture-specific irq_finish function defined in arm/arch/irqs.h.
+ */
+#ifndef irq_finish
+#define irq_finish(irq) do { } while (0)
+#endif
+
+/*
  * Dummy mask/unmask handler
  */
 void dummy_mask_unmask_irq(unsigned int irq)
@@ -531,6 +538,8 @@
 	 */
 	if (!list_empty(&irq_pending))
 		do_pending_irqs(regs);
+
+	irq_finish(irq);
 
 	spin_unlock(&irq_controller_lock);
 	irq_exit();
diff -Nru a/arch/arm/kernel/sys_arm.c b/arch/arm/kernel/sys_arm.c
--- a/arch/arm/kernel/sys_arm.c	2005-03-11 12:51:41 -08:00
+++ b/arch/arm/kernel/sys_arm.c	2005-03-11 12:51:41 -08:00
@@ -230,6 +230,18 @@
 	}
 }
 
+asmlinkage long sys_shmat(int shmid, char __user *shmaddr, int shmflg,
+			  unsigned long __user *addr)
+{
+	unsigned long ret;
+	long err;
+
+	err = do_shmat(shmid, shmaddr, shmflg, &ret);
+	if (err == 0)
+		err = put_user(ret, addr);
+	return err;
+}
+
 /* Fork a new task - this creates a new program thread.
  * This is called indirectly via a small wrapper
  */
diff -Nru a/arch/arm/mach-ebsa110/io.c b/arch/arm/mach-ebsa110/io.c
--- a/arch/arm/mach-ebsa110/io.c	2005-03-11 12:51:52 -08:00
+++ b/arch/arm/mach-ebsa110/io.c	2005-03-11 12:51:52 -08:00
@@ -153,9 +153,9 @@
 	 * The SuperIO registers use sane addressing techniques...
 	 */
 	if (SUPERIO_PORT(port))
-		ret = __raw_readb(ISAIO_BASE + (port << 2));
+		ret = __raw_readb((void __iomem *)ISAIO_BASE + (port << 2));
 	else {
-		void __iomem *a = ISAIO_BASE + ((port & ~1) << 1);
+		void __iomem *a = (void __iomem *)ISAIO_BASE + ((port & ~1) << 1);
 
 		/*
 		 * Shame nothing else does
@@ -174,45 +174,33 @@
  */
 u8 __inb16(unsigned int port)
 {
-	u32 ret;
+	unsigned int offset;
 
 	/*
 	 * The SuperIO registers use sane addressing techniques...
 	 */
 	if (SUPERIO_PORT(port))
-		ret = __raw_readb(ISAIO_BASE + (port << 2));
-	else {
-		void __iomem *a = ISAIO_BASE + ((port & ~1) << 1);
+		offset = port << 2;
+	else
+		offset = (port & ~1) << 1 | (port & 1);
 
-		/*
-		 * Shame nothing else does
-		 */
-		ret = __raw_readb(a + (port & 1));
-	}
-	return ret;
+	return __raw_readb((void __iomem *)ISAIO_BASE + offset);
 }
 
 u16 __inw(unsigned int port)
 {
-	u32 ret;
+	unsigned int offset;
 
 	/*
 	 * The SuperIO registers use sane addressing techniques...
 	 */
 	if (SUPERIO_PORT(port))
-		ret = __raw_readw(ISAIO_BASE + (port << 2));
+		offset = port << 2;
 	else {
-		void __iomem *a = ISAIO_BASE + ((port & ~1) << 1);
-
-		/*
-		 * Shame nothing else does
-		 */
-		if (port & 1)
-			BUG();
-
-		ret = __raw_readw(a);
+		offset = port << 1;
+		BUG_ON(port & 1);
 	}
-	return ret;
+	return __raw_readw((void __iomem *)ISAIO_BASE + offset);
 }
 
 /*
@@ -225,7 +213,7 @@
 	if (SUPERIO_PORT(port) || port & 3)
 		BUG();
 
-	a = ISAIO_BASE + (port << 1);
+	a = (void __iomem *)ISAIO_BASE + ((port & ~1) << 1);
 
 	return __raw_readw(a) | __raw_readw(a + 4) << 16;
 }
@@ -241,9 +229,9 @@
 	 * The SuperIO registers use sane addressing techniques...
 	 */
 	if (SUPERIO_PORT(port))
-		__raw_writeb(val, ISAIO_BASE + (port << 2));
+		__raw_writeb(val, (void __iomem *)ISAIO_BASE + (port << 2));
 	else {
-		void __iomem *a = ISAIO_BASE + ((port & ~1) << 1);
+		void __iomem *a = (void __iomem *)ISAIO_BASE + ((port & ~1) << 1);
 
 		/*
 		 * Shame nothing else does
@@ -257,37 +245,33 @@
 
 void __outb16(u8 val, unsigned int port)
 {
+	unsigned int offset;
+
 	/*
 	 * The SuperIO registers use sane addressing techniques...
 	 */
 	if (SUPERIO_PORT(port))
-		__raw_writeb(val, ISAIO_BASE + (port << 2));
-	else {
-		void __iomem *a = ISAIO_BASE + ((port & ~1) << 1);
+		offset = port << 2;
+	else
+		offset = (port & ~1) << 1 | (port & 1);
 
-		/*
-		 * Shame nothing else does
-		 */
-		__raw_writeb(val, a + (port & 1));
-	}
+	__raw_writeb(val, (void __iomem *)ISAIO_BASE + offset);
 }
 
 void __outw(u16 val, unsigned int port)
 {
-	u32 off;
+	unsigned int offset;
 
 	/*
 	 * The SuperIO registers use sane addressing techniques...
 	 */
 	if (SUPERIO_PORT(port))
-		off = port << 2;
+		offset = port << 2;
 	else {
-		off = port << 1;
-		if (port & 1)
-			BUG();
-
+		offset = port << 1;
+		BUG_ON(port & 1);
 	}
-	__raw_writew(val, ISAIO_BASE + off);
+	__raw_writew(val, (void __iomem *)ISAIO_BASE + offset);
 }
 
 void __outl(u32 val, unsigned int port)
@@ -300,13 +284,6 @@
 EXPORT_SYMBOL(__outw);
 EXPORT_SYMBOL(__outl);
 
-extern void __arch_writesb(unsigned long virt, const void *from, int len);
-extern void __arch_writesw(unsigned long virt, const void *from, int len);
-extern void __arch_writesl(unsigned long virt, const void *from, int len);
-extern void __arch_readsb(unsigned long virt, void *from, int len);
-extern void __arch_readsw(unsigned long virt, void *from, int len);
-extern void __arch_readsl(unsigned long virt, void *from, int len);
-
 void outsb(unsigned int port, const void *from, int len)
 {
 	u32 off;
@@ -319,7 +296,7 @@
 			BUG();
 	}
 
-	__raw_writesb(ISAIO_BASE + off, from, len);
+	__raw_writesb((void __iomem *)ISAIO_BASE + off, from, len);
 }
 
 void insb(unsigned int port, void *from, int len)
@@ -334,7 +311,7 @@
 			BUG();
 	}
 
-	__raw_readsb(ISAIO_BASE + off, from, len);
+	__raw_readsb((void __iomem *)ISAIO_BASE + off, from, len);
 }
 
 EXPORT_SYMBOL(outsb);
@@ -352,7 +329,7 @@
 			BUG();
 	}
 
-	__raw_writesw(ISAIO_BASE + off, from, len);
+	__raw_writesw((void __iomem *)ISAIO_BASE + off, from, len);
 }
 
 void insw(unsigned int port, void *from, int len)
@@ -367,7 +344,7 @@
 			BUG();
 	}
 
-	__raw_readsw(ISAIO_BASE + off, from, len);
+	__raw_readsw((void __iomem *)ISAIO_BASE + off, from, len);
 }
 
 EXPORT_SYMBOL(outsw);
@@ -384,7 +361,7 @@
 	if (SUPERIO_PORT(port) || port & 3)
 		BUG();
 
-	__raw_writesw(ISAIO_BASE + off, from, len << 1);
+	__raw_writesw((void __iomem *)ISAIO_BASE + off, from, len << 1);
 }
 
 void insl(unsigned int port, void *from, int len)
@@ -394,7 +371,7 @@
 	if (SUPERIO_PORT(port) || port & 3)
 		BUG();
 
-	__raw_readsw(ISAIO_BASE + off, from, len << 1);
+	__raw_readsw((void __iomem *)ISAIO_BASE + off, from, len << 1);
 }
 
 EXPORT_SYMBOL(outsl);
diff -Nru a/arch/arm/mach-ixp2000/core.c b/arch/arm/mach-ixp2000/core.c
--- a/arch/arm/mach-ixp2000/core.c	2005-03-11 12:51:51 -08:00
+++ b/arch/arm/mach-ixp2000/core.c	2005-03-11 12:51:51 -08:00
@@ -79,31 +79,11 @@
 /*************************************************************************
  * Chip specific mappings shared by all IXP2000 systems
  *************************************************************************/
-static struct map_desc ixp2000_small_io_desc[] __initdata = {
+static struct map_desc ixp2000_io_desc[] __initdata = {
 	{
-		.virtual	= IXP2000_GLOBAL_REG_VIRT_BASE,
-		.physical	= IXP2000_GLOBAL_REG_PHYS_BASE,
-		.length		= IXP2000_GLOBAL_REG_SIZE,
-		.type		= MT_DEVICE
-	}, {
-		.virtual	= IXP2000_GPIO_VIRT_BASE,
-		.physical	= IXP2000_GPIO_PHYS_BASE,
-		.length		= IXP2000_GPIO_SIZE,
-		.type		= MT_DEVICE
-	}, {
-		.virtual	= IXP2000_TIMER_VIRT_BASE,
-		.physical	= IXP2000_TIMER_PHYS_BASE,
-		.length		= IXP2000_TIMER_SIZE,
-		.type		= MT_DEVICE
-	}, {
-		.virtual	= IXP2000_UART_VIRT_BASE,
-		.physical	= IXP2000_UART_PHYS_BASE,
-		.length		= IXP2000_UART_SIZE,
-		.type		= MT_DEVICE
-	}, {
-		.virtual	= IXP2000_SLOWPORT_CSR_VIRT_BASE,
-		.physical	= IXP2000_SLOWPORT_CSR_PHYS_BASE,
-		.length		= IXP2000_SLOWPORT_CSR_SIZE,
+		.virtual	= IXP2000_CAP_VIRT_BASE,
+		.physical	= IXP2000_CAP_PHYS_BASE,
+		.length		= IXP2000_CAP_SIZE,
 		.type		= MT_DEVICE
 	}, {
 		.virtual	= IXP2000_INTCTL_VIRT_BASE,
@@ -115,11 +95,7 @@
 		.physical	= IXP2000_PCI_CREG_PHYS_BASE,
 		.length		= IXP2000_PCI_CREG_SIZE,
 		.type		= MT_DEVICE
-	}
-};
-
-static struct map_desc ixp2000_large_io_desc[] __initdata = {
-	{
+	}, {
 		.virtual	= IXP2000_PCI_CSR_VIRT_BASE,
 		.physical	= IXP2000_PCI_CSR_PHYS_BASE,
 		.length		= IXP2000_PCI_CSR_SIZE,
@@ -157,8 +133,7 @@
 
 void __init ixp2000_map_io(void)
 {
-	iotable_init(ixp2000_small_io_desc, ARRAY_SIZE(ixp2000_small_io_desc));
-	iotable_init(ixp2000_large_io_desc, ARRAY_SIZE(ixp2000_large_io_desc));
+	iotable_init(ixp2000_io_desc, ARRAY_SIZE(ixp2000_io_desc));
 	early_serial_setup(&ixp2000_serial_port);
 
 	/* Set slowport to 8-bit mode.  */
diff -Nru a/arch/arm/mach-ixp2000/enp2611.c b/arch/arm/mach-ixp2000/enp2611.c
--- a/arch/arm/mach-ixp2000/enp2611.c	2005-03-11 12:51:42 -08:00
+++ b/arch/arm/mach-ixp2000/enp2611.c	2005-03-11 12:51:42 -08:00
@@ -6,7 +6,7 @@
  * Created 2004 by Lennert Buytenhek from the ixdp2x01 code.  The
  * original version carries the following notices:
  *
- * Original Author: Andrzej Mialwoski <andrzej.mialwoski@intel.com>
+ * Original Author: Andrzej Mialkowski <andrzej.mialkowski@intel.com>
  * Maintainer: Deepak Saxena <dsaxena@plexity.net>
  *
  * Copyright (C) 2002-2003 Intel Corp.
diff -Nru a/arch/arm/mach-ixp2000/ixdp2x01.c b/arch/arm/mach-ixp2000/ixdp2x01.c
--- a/arch/arm/mach-ixp2000/ixdp2x01.c	2005-03-11 12:51:41 -08:00
+++ b/arch/arm/mach-ixp2000/ixdp2x01.c	2005-03-11 12:51:41 -08:00
@@ -3,7 +3,7 @@
  *
  * Code common to Intel IXDP2401 and IXDP2801 platforms
  *
- * Original Author: Andrzej Mialwoski <andrzej.mialwoski@intel.com>
+ * Original Author: Andrzej Mialkowski <andrzej.mialkowski@intel.com>
  * Maintainer: Deepak Saxena <dsaxena@plexity.net>
  *
  * Copyright (C) 2002-2003 Intel Corp.
diff -Nru a/arch/arm/mach-ixp4xx/Makefile b/arch/arm/mach-ixp4xx/Makefile
--- a/arch/arm/mach-ixp4xx/Makefile	2005-03-11 12:51:41 -08:00
+++ b/arch/arm/mach-ixp4xx/Makefile	2005-03-11 12:51:41 -08:00
@@ -7,6 +7,5 @@
 obj-$(CONFIG_ARCH_IXDP4XX)	+= ixdp425-pci.o ixdp425-setup.o
 obj-$(CONFIG_MACH_IXDPG425)	+= ixdpg425-pci.o coyote-setup.o
 obj-$(CONFIG_ARCH_ADI_COYOTE)	+= coyote-pci.o coyote-setup.o
-obj-$(CONFIG_ARCH_PRPMC1100)	+= prpmc1100-pci.o prpmc1100-setup.o
 obj-$(CONFIG_MACH_GTWX5715)	+= gtwx5715-pci.o gtwx5715-setup.o
 
diff -Nru a/arch/arm/mach-ixp4xx/coyote-setup.c b/arch/arm/mach-ixp4xx/coyote-setup.c
--- a/arch/arm/mach-ixp4xx/coyote-setup.c	2005-03-11 12:51:42 -08:00
+++ b/arch/arm/mach-ixp4xx/coyote-setup.c	2005-03-11 12:51:42 -08:00
@@ -3,7 +3,7 @@
  *
  * Board setup for ADI Engineering and IXDGP425 boards
  *
- * Copyright (C) 2003-2004 MontaVista Software, Inc.
+ * Copyright (C) 2003-2005 MontaVista Software, Inc.
  *
  * Author: Deepak Saxena <dsaxena@plexity.net>
  */
@@ -13,7 +13,7 @@
 #include <linux/device.h>
 #include <linux/serial.h>
 #include <linux/tty.h>
-#include <linux/serial_core.h>
+#include <linux/serial_8250.h>
 
 #include <asm/types.h>
 #include <asm/setup.h>
@@ -24,39 +24,8 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/flash.h>
 
-#ifdef	__ARMEB__
-#define	REG_OFFSET	3
-#else
-#define	REG_OFFSET	0
-#endif
-
-/*
- * Only one serial port is connected on the Coyote & IXDPG425
- */
-static struct uart_port coyote_serial_port = {
-	.membase	= (char*)(IXP4XX_UART2_BASE_VIRT + REG_OFFSET),
-	.mapbase	= (IXP4XX_UART2_BASE_PHYS),
-	.irq		= IRQ_IXP4XX_UART2,
-	.flags		= UPF_SKIP_TEST,
-	.iotype		= UPIO_MEM,	
-	.regshift	= 2,
-	.uartclk	= IXP4XX_UART_XTAL,
-	.line		= 0,
-	.type		= PORT_XSCALE,
-	.fifosize	= 32
-};
-
 void __init coyote_map_io(void)
 {
-	if (machine_is_ixdpg425()) {
-		coyote_serial_port.membase =
-			(char*)(IXP4XX_UART1_BASE_VIRT + REG_OFFSET);
-		coyote_serial_port.mapbase = IXP4XX_UART1_BASE_PHYS;
-		coyote_serial_port.irq = IRQ_IXP4XX_UART1;
-	}
-
-	early_serial_setup(&coyote_serial_port);
-
 	ixp4xx_map_io();
 }
 
@@ -81,14 +50,49 @@
 	.resource	= &coyote_flash_resource,
 };
 
+static struct resource coyote_uart_resource = {
+	.start	= IXP4XX_UART2_BASE_PHYS,
+	.end	= IXP4XX_UART2_BASE_PHYS + 0x0fff,
+	.flags	= IORESOURCE_MEM,
+};
+
+static struct plat_serial8250_port coyote_uart_data = {
+	.mapbase	= IXP4XX_UART2_BASE_PHYS,
+	.membase	= (char *)IXP4XX_UART2_BASE_VIRT + REG_OFFSET,
+	.irq		= IRQ_IXP4XX_UART2,
+	.flags		= UPF_BOOT_AUTOCONF,
+	.iotype		= UPIO_MEM,
+	.regshift	= 2,
+	.uartclk	= IXP4XX_UART_XTAL,
+};
+
+static struct platform_device coyote_uart = {
+	.name		= "serial8250",
+	.id		= 0,
+	.dev			= {
+		.platform_data	= &coyote_uart_data,
+	},
+	.num_resources	= 1,
+	.resource	= &coyote_uart_resource,
+};
+
 static struct platform_device *coyote_devices[] __initdata = {
-	&coyote_flash
+	&coyote_flash,
+	&coyote_uart
 };
 
 static void __init coyote_init(void)
 {
 	*IXP4XX_EXP_CS0 |= IXP4XX_FLASH_WRITABLE;
 	*IXP4XX_EXP_CS1 = *IXP4XX_EXP_CS0;
+
+	if (machine_is_ixdpg425()) {
+		coyote_uart_data.membase =
+			(char*)(IXP4XX_UART1_BASE_VIRT + REG_OFFSET);
+		coyote_uart_data.mapbase = IXP4XX_UART1_BASE_PHYS;
+		coyote_uart_data.irq = IRQ_IXP4XX_UART1;
+	}
+
 
 	ixp4xx_sys_init();
 	platform_add_devices(coyote_devices, ARRAY_SIZE(coyote_devices));
diff -Nru a/arch/arm/mach-ixp4xx/ixdp425-setup.c b/arch/arm/mach-ixp4xx/ixdp425-setup.c
--- a/arch/arm/mach-ixp4xx/ixdp425-setup.c	2005-03-11 12:51:46 -08:00
+++ b/arch/arm/mach-ixp4xx/ixdp425-setup.c	2005-03-11 12:51:46 -08:00
@@ -3,7 +3,7 @@
  *
  * IXDP425/IXCDP1100 board-setup 
  *
- * Copyright (C) 2003-2004 MontaVista Software, Inc.
+ * Copyright (C) 2003-2005 MontaVista Software, Inc.
  *
  * Author: Deepak Saxena <dsaxena@plexity.net>
  */
@@ -13,7 +13,7 @@
 #include <linux/device.h>
 #include <linux/serial.h>
 #include <linux/tty.h>
-#include <linux/serial_core.h>
+#include <linux/serial_8250.h>
 
 #include <asm/types.h>
 #include <asm/setup.h>
@@ -24,46 +24,8 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/flash.h>
 
-#ifdef	__ARMEB__
-#define	REG_OFFSET	3
-#else
-#define	REG_OFFSET	0
-#endif
-
-/*
- * IXDP425 uses both chipset serial ports
- */
-static struct uart_port ixdp425_serial_ports[] = {
-	{
-		.membase	= (char*)(IXP4XX_UART1_BASE_VIRT + REG_OFFSET),
-		.mapbase	= (IXP4XX_UART1_BASE_PHYS),
-		.irq		= IRQ_IXP4XX_UART1,
-		.flags		= UPF_SKIP_TEST,
-		.iotype		= UPIO_MEM,	
-		.regshift	= 2,
-		.uartclk	= IXP4XX_UART_XTAL,
-		.line		= 0,
-		.type		= PORT_XSCALE,
-		.fifosize	= 32
-	} , {
-		.membase	= (char*)(IXP4XX_UART2_BASE_VIRT + REG_OFFSET),
-		.mapbase	= (IXP4XX_UART2_BASE_PHYS),
-		.irq		= IRQ_IXP4XX_UART2,
-		.flags		= UPF_SKIP_TEST,
-		.iotype		= UPIO_MEM,	
-		.regshift	= 2,
-		.uartclk	= IXP4XX_UART_XTAL,
-		.line		= 1,
-		.type		= PORT_XSCALE,
-		.fifosize	= 32
-	}
-};
-
 void __init ixdp425_map_io(void) 
 {
-	early_serial_setup(&ixdp425_serial_ports[0]);
-	early_serial_setup(&ixdp425_serial_ports[1]);
-
 	ixp4xx_map_io();
 }
 
@@ -102,10 +64,54 @@
 	.num_resources	= 0
 };
 
+static struct resource ixdp425_uart_resources[] = {
+	{
+		.start		= IXP4XX_UART1_BASE_PHYS,
+		.end		= IXP4XX_UART1_BASE_PHYS + 0x0fff,
+		.flags		= IORESOURCE_MEM
+	},
+	{
+		.start		= IXP4XX_UART2_BASE_PHYS,
+		.end		= IXP4XX_UART2_BASE_PHYS + 0x0fff,
+		.flags		= IORESOURCE_MEM
+	}
+};
+
+static struct plat_serial8250_port ixdp425_uart_data[] = {
+	{
+		.mapbase	= IXP4XX_UART1_BASE_PHYS,
+		.membase	= (char *)IXP4XX_UART1_BASE_VIRT + REG_OFFSET,
+		.irq		= IRQ_IXP4XX_UART1,
+		.flags		= UPF_BOOT_AUTOCONF,
+		.iotype		= UPIO_MEM,
+		.regshift	= 2,
+		.uartclk	= IXP4XX_UART_XTAL,
+	},
+	{
+		.mapbase	= IXP4XX_UART2_BASE_PHYS,
+		.membase	= (char *)IXP4XX_UART2_BASE_VIRT + REG_OFFSET,
+		.irq		= IRQ_IXP4XX_UART1,
+		.flags		= UPF_BOOT_AUTOCONF,
+		.iotype		= UPIO_MEM,
+		.regshift	= 2,
+		.uartclk	= IXP4XX_UART_XTAL,
+	}
+};
+
+static struct platform_device ixdp425_uart = {
+	.name			= "serial8250",
+	.id			= 0,
+	.dev.platform_data	= ixdp425_uart_data,
+	.num_resources		= 2,
+	.resource		= ixdp425_uart_resources
+};
+
 static struct platform_device *ixdp425_devices[] __initdata = {
 	&ixdp425_i2c_controller,
-	&ixdp425_flash
+	&ixdp425_flash,
+	&ixdp425_uart
 };
+
 
 static void __init ixdp425_init(void)
 {
diff -Nru a/arch/arm/mach-ixp4xx/prpmc1100-pci.c b/arch/arm/mach-ixp4xx/prpmc1100-pci.c
--- a/arch/arm/mach-ixp4xx/prpmc1100-pci.c	2005-03-11 12:51:40 -08:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,120 +0,0 @@
-/*
- * arch/arm/mach-ixp4xx/prpmc1100-pci.c 
- *
- * PrPMC1100 PCI initialization
- *
- * Copyright (C) 2003-2004 MontaVista Sofwtare, Inc. 
- * Based on IXDP425 code originally (C) Intel Corporation
- *
- * Author: Deepak Saxena <dsaxena@plexity.net>
- *
- * PrPMC1100 PCI init code.  GPIO usage is similar to that on 
- * IXDP425, but the IRQ routing is completely different and
- * depends on what carrier you are using. This code is written
- * to work on the Motorola PrPMC800 ATX carrier board.
- *
- * 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/kernel.h>
-#include <linux/config.h>
-#include <linux/pci.h>
-#include <linux/init.h>
-
-#include <asm/mach-types.h>
-#include <asm/irq.h>
-#include <asm/hardware.h>
-
-#include <asm/mach/pci.h>
-
-
-void __init prpmc1100_pci_preinit(void)
-{
-	gpio_line_config(PRPMC1100_PCI_INTA_PIN, 
-				IXP4XX_GPIO_IN | IXP4XX_GPIO_ACTIVE_LOW);
-	gpio_line_config(PRPMC1100_PCI_INTB_PIN, 
-				IXP4XX_GPIO_IN | IXP4XX_GPIO_ACTIVE_LOW);
-	gpio_line_config(PRPMC1100_PCI_INTC_PIN, 
-				IXP4XX_GPIO_IN | IXP4XX_GPIO_ACTIVE_LOW);
-	gpio_line_config(PRPMC1100_PCI_INTD_PIN, 
-				IXP4XX_GPIO_IN | IXP4XX_GPIO_ACTIVE_LOW);
-
-	gpio_line_isr_clear(PRPMC1100_PCI_INTA_PIN);
-	gpio_line_isr_clear(PRPMC1100_PCI_INTB_PIN);
-	gpio_line_isr_clear(PRPMC1100_PCI_INTC_PIN);
-	gpio_line_isr_clear(PRPMC1100_PCI_INTD_PIN);
-
-	ixp4xx_pci_preinit();
-}
-
-
-static int __init prpmc1100_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
-{
-	int irq = -1;
-
-	static int pci_irq_table[][4] = { 
-		{	/* IDSEL 16 - PMC A1 */
-			IRQ_PRPMC1100_PCI_INTD, 
-			IRQ_PRPMC1100_PCI_INTA, 
-			IRQ_PRPMC1100_PCI_INTB, 
-			IRQ_PRPMC1100_PCI_INTC
-		}, {	/* IDSEL 17 - PRPMC-A-B */
-			IRQ_PRPMC1100_PCI_INTD, 
-			IRQ_PRPMC1100_PCI_INTA, 
-			IRQ_PRPMC1100_PCI_INTB, 
-			IRQ_PRPMC1100_PCI_INTC
-		}, { 	/* IDSEL 18 - PMC A1-B */
-			IRQ_PRPMC1100_PCI_INTA, 
-			IRQ_PRPMC1100_PCI_INTB, 
-			IRQ_PRPMC1100_PCI_INTC, 
-			IRQ_PRPMC1100_PCI_INTD
-		}, {	/* IDSEL 19 - Unused */
-			0, 0, 0, 0 
-		}, {	/* IDSEL 20 - P2P Bridge */
-			IRQ_PRPMC1100_PCI_INTA, 
-			IRQ_PRPMC1100_PCI_INTB, 
-			IRQ_PRPMC1100_PCI_INTC, 
-			IRQ_PRPMC1100_PCI_INTD
-		}, {	/* IDSEL 21 - PMC A2 */
-			IRQ_PRPMC1100_PCI_INTC, 
-			IRQ_PRPMC1100_PCI_INTD, 
-			IRQ_PRPMC1100_PCI_INTA, 
-			IRQ_PRPMC1100_PCI_INTB
-		}, {	/* IDSEL 22 - PMC A2-B */
-			IRQ_PRPMC1100_PCI_INTD, 
-			IRQ_PRPMC1100_PCI_INTA, 
-			IRQ_PRPMC1100_PCI_INTB, 
-			IRQ_PRPMC1100_PCI_INTC
-		},
-	};
-
-	if (slot >= PRPMC1100_PCI_MIN_DEVID && slot <= PRPMC1100_PCI_MAX_DEVID 
-		&& pin >= 1 && pin <= PRPMC1100_PCI_IRQ_LINES) {
-		irq = pci_irq_table[slot - PRPMC1100_PCI_MIN_DEVID][pin - 1];
-	}
-
-	return irq;
-}
-
-
-struct hw_pci prpmc1100_pci __initdata = {
-	.nr_controllers = 1,
-	.preinit =	  prpmc1100_pci_preinit,
-	.swizzle =	  pci_std_swizzle,
-	.setup =	  ixp4xx_setup,
-	.scan =		  ixp4xx_scan_bus,
-	.map_irq =	  prpmc1100_map_irq,
-};
-
-int __init prpmc1100_pci_init(void)
-{
-	if (machine_is_prpmc1100())
-		pci_common_init(&prpmc1100_pci);
-	return 0;
-}
-
-subsys_initcall(prpmc1100_pci_init);
-
diff -Nru a/arch/arm/mach-ixp4xx/prpmc1100-setup.c b/arch/arm/mach-ixp4xx/prpmc1100-setup.c
--- a/arch/arm/mach-ixp4xx/prpmc1100-setup.c	2005-03-11 12:51:41 -08:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,98 +0,0 @@
-/*
- * arch/arm/mach-ixp4xx/prpmc1100-setup.c
- *
- * Motorola PrPMC1100 board setup
- *
- * Copyright (C) 2003-2004 MontaVista Software, Inc.
- *
- * Author: Deepak Saxena <dsaxena@plexity.net>
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/device.h>
-#include <linux/serial.h>
-#include <linux/tty.h>
-#include <linux/serial_core.h>
-
-#include <asm/types.h>
-#include <asm/setup.h>
-#include <asm/memory.h>
-#include <asm/hardware.h>
-#include <asm/irq.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/flash.h>
-
-#ifdef	__ARMEB__
-#define	REG_OFFSET	3
-#else
-#define	REG_OFFSET	0
-#endif
-
-/*
- * Only one serial port is connected on the PrPMC1100
- */
-static struct uart_port prpmc1100_serial_port = {
-	.membase	= (char*)(IXP4XX_UART1_BASE_VIRT + REG_OFFSET),
-	.mapbase	= (IXP4XX_UART1_BASE_PHYS),
-	.irq		= IRQ_IXP4XX_UART1,
-	.flags		= UPF_SKIP_TEST,
-	.iotype		= UPIO_MEM,	
-	.regshift	= 2,
-	.uartclk	= IXP4XX_UART_XTAL,
-	.line		= 0,
-	.type		= PORT_XSCALE,
-	.fifosize	= 32
-};
-
-void __init prpmc1100_map_io(void)
-{
-	early_serial_setup(&prpmc1100_serial_port);
-
-	ixp4xx_map_io();
-}
-
-static struct flash_platform_data prpmc1100_flash_data = {
-	.map_name	= "cfi_probe",
-	.width		= 2,
-};
-
-static struct resource prpmc1100_flash_resource = {
-	.start		= PRPMC1100_FLASH_BASE,
-	.end		= PRPMC1100_FLASH_BASE + PRPMC1100_FLASH_SIZE,
-	.flags		= IORESOURCE_MEM,
-};
-
-static struct platform_device prpmc1100_flash = {
-	.name		= "IXP4XX-Flash",
-	.id		= 0,
-	.dev		= {
-		.platform_data = &prpmc1100_flash_data,
-	},
-	.num_resources	= 1,
-	.resource	= &prpmc1100_flash_resource,
-};
-
-static struct platform_device *prpmc1100_devices[] __initdata = {
-	&prpmc1100_flash
-};
-
-static void __init prpmc1100_init(void)
-{
-	ixp4xx_sys_init();
-
-	platform_add_devices(prpmc1100_devices, ARRAY_SIZE(prpmc1100_devices));
-}
-
-MACHINE_START(PRPMC1100, "Motorola PrPMC1100")
-        MAINTAINER("MontaVista Software, Inc.")
-        BOOT_MEM(PHYS_OFFSET, IXP4XX_PERIPHERAL_BASE_PHYS,
-                IXP4XX_PERIPHERAL_BASE_VIRT)
-        MAPIO(prpmc1100_map_io)
-        INITIRQ(ixp4xx_init_irq)
-	.timer		= &ixp4xx_timer,
-        BOOT_PARAMS(0x0100)
-	INIT_MACHINE(prpmc1100_init)
-MACHINE_END
-
diff -Nru a/arch/arm/mach-lh7a40x/arch-lpd7a40x.c b/arch/arm/mach-lh7a40x/arch-lpd7a40x.c
--- a/arch/arm/mach-lh7a40x/arch-lpd7a40x.c	2005-03-11 12:51:41 -08:00
+++ b/arch/arm/mach-lh7a40x/arch-lpd7a40x.c	2005-03-11 12:51:41 -08:00
@@ -157,8 +157,6 @@
 	.unmask	= lh7a40x_unmask_cpld_irq,
 };
 
-#define IRQ_DISPATCH(irq) irq_desc[irq].handle ((irq), &irq_desc[irq], regs)
-
 static void lpd7a40x_cpld_handler (unsigned int irq, struct irqdesc *desc,
 				  struct pt_regs *regs)
 {
diff -Nru a/arch/arm/mach-lh7a40x/common.h b/arch/arm/mach-lh7a40x/common.h
--- a/arch/arm/mach-lh7a40x/common.h	2005-03-11 12:51:43 -08:00
+++ b/arch/arm/mach-lh7a40x/common.h	2005-03-11 12:51:43 -08:00
@@ -12,3 +12,5 @@
 
 extern void lh7a400_init_irq (void);
 extern void lh7a404_init_irq (void);
+
+#define IRQ_DISPATCH(irq) irq_desc[irq].handle ((irq), &irq_desc[irq], regs)
diff -Nru a/arch/arm/mach-lh7a40x/irq-lpd7a40x.c b/arch/arm/mach-lh7a40x/irq-lpd7a40x.c
--- a/arch/arm/mach-lh7a40x/irq-lpd7a40x.c	2005-03-11 12:51:41 -08:00
+++ b/arch/arm/mach-lh7a40x/irq-lpd7a40x.c	2005-03-11 12:51:41 -08:00
@@ -55,8 +55,6 @@
 	.unmask	= lh7a40x_unmask_cpld_irq,
 };
 
-#define IRQ_DISPATCH(irq) irq_desc[irq].handle ((irq), &irq_desc[irq], regs)
-
 static void lh7a40x_cpld_handler (unsigned int irq, struct irqdesc *desc,
 				  struct pt_regs *regs)
 {
diff -Nru a/arch/arm/mach-omap/Kconfig b/arch/arm/mach-omap/Kconfig
--- a/arch/arm/mach-omap/Kconfig	2005-03-11 12:51:41 -08:00
+++ b/arch/arm/mach-omap/Kconfig	2005-03-11 12:51:41 -08:00
@@ -113,6 +113,38 @@
 	  printed, it's safe to deselect OMAP_MUX for your product.
 
 choice
+        prompt "System timer"
+	default OMAP_MPU_TIMER
+
+config OMAP_MPU_TIMER
+	bool "Use mpu timer"
+	help
+	  Select this option if you want to use the OMAP mpu timer. This
+	  timer provides more intra-tick resolution than the 32KHz timer,
+	  but consumes more power.
+
+config OMAP_32K_TIMER
+	bool "Use 32KHz timer"
+	depends on ARCH_OMAP16XX
+	help
+	  Select this option if you want to enable the OMAP 32KHz timer.
+	  This timer saves power compared to the OMAP_MPU_TIMER, and has
+	  support for no tick during idle. The 32KHz timer provides less
+	  intra-tick resolution than OMAP_MPU_TIMER. The 32KHz timer is
+	  currently only available for OMAP-16xx.
+
+endchoice
+
+config OMAP_32K_TIMER_HZ
+       int "Kernel internal timer frequency for 32KHz timer"
+       range 32 1024
+       depends on OMAP_32K_TIMER
+       default "128"
+       help
+	  Kernel internal timer frequency should be a divisor of 32768,
+	  such as 64 or 128.
+
+choice
 	prompt "Low-level debug console UART"
 	depends on ARCH_OMAP
 	default OMAP_LL_DEBUG_UART1
diff -Nru a/arch/arm/mach-omap/time.c b/arch/arm/mach-omap/time.c
--- a/arch/arm/mach-omap/time.c	2005-03-11 12:51:46 -08:00
+++ b/arch/arm/mach-omap/time.c	2005-03-11 12:51:46 -08:00
@@ -51,6 +51,8 @@
 
 struct sys_timer omap_timer;
 
+#ifdef CONFIG_OMAP_MPU_TIMER
+
 /*
  * ---------------------------------------------------------------------------
  * MPU timer
@@ -67,6 +69,36 @@
 #define MPU_TIMER_AR			(1 << 1)
 #define MPU_TIMER_ST			(1 << 0)
 
+/* cycles to nsec conversions taken from arch/i386/kernel/timers/timer_tsc.c,
+ * converted to use kHz by Kevin Hilman */
+/* convert from cycles(64bits) => nanoseconds (64bits)
+ *  basic equation:
+ *		ns = cycles / (freq / ns_per_sec)
+ *		ns = cycles * (ns_per_sec / freq)
+ *		ns = cycles * (10^9 / (cpu_khz * 10^3))
+ *		ns = cycles * (10^6 / cpu_khz)
+ *
+ *	Then we use scaling math (suggested by george at mvista.com) to get:
+ *		ns = cycles * (10^6 * SC / cpu_khz / SC
+ *		ns = cycles * cyc2ns_scale / SC
+ *
+ *	And since SC is a constant power of two, we can convert the div
+ *  into a shift.
+ *			-johnstul at us.ibm.com "math is hard, lets go shopping!"
+ */
+static unsigned long cyc2ns_scale;
+#define CYC2NS_SCALE_FACTOR 10 /* 2^10, carefully chosen */
+
+static inline void set_cyc2ns_scale(unsigned long cpu_khz)
+{
+	cyc2ns_scale = (1000000 << CYC2NS_SCALE_FACTOR)/cpu_khz;
+}
+
+static inline unsigned long long cycles_2_ns(unsigned long long cyc)
+{
+	return (cyc * cyc2ns_scale) >> CYC2NS_SCALE_FACTOR;
+}
+
 /*
  * MPU_TICKS_PER_SEC must be an even number, otherwise machinecycles_to_usecs
  * will break. On P2, the timer count rate is 6.5 MHz after programming PTV
@@ -112,8 +144,10 @@
 
 unsigned long omap_mpu_timer_ticks_to_usecs(unsigned long nr_ticks)
 {
-	/* Round up to nearest usec */
-	return ((nr_ticks * 1000) / (MPU_TICKS_PER_SEC / 2 / 1000) + 1) >> 1;
+	unsigned long long nsec;
+
+	nsec = cycles_2_ns((unsigned long long)nr_ticks);
+	return (unsigned long)nsec / 1000;
 }
 
 /*
@@ -158,22 +192,190 @@
 	.handler	= omap_mpu_timer_interrupt
 };
 
+static unsigned long omap_mpu_timer1_overflows;
+static irqreturn_t omap_mpu_timer1_interrupt(int irq, void *dev_id,
+					     struct pt_regs *regs)
+{
+	omap_mpu_timer1_overflows++;
+	return IRQ_HANDLED;
+}
+
+static struct irqaction omap_mpu_timer1_irq = {
+	.name		= "mpu timer1 overflow",
+	.flags		= SA_INTERRUPT,
+	.handler	= omap_mpu_timer1_interrupt
+};
+
 static __init void omap_init_mpu_timer(void)
 {
+	set_cyc2ns_scale(MPU_TICKS_PER_SEC / 1000);
 	omap_timer.offset = omap_mpu_timer_gettimeoffset;
+	setup_irq(INT_TIMER1, &omap_mpu_timer1_irq);
 	setup_irq(INT_TIMER2, &omap_mpu_timer_irq);
 	omap_mpu_timer_start(0, 0xffffffff);
 	omap_mpu_timer_start(1, MPU_TIMER_TICK_PERIOD);
 }
 
 /*
+ * Scheduler clock - returns current time in nanosec units.
+ */
+unsigned long long sched_clock(void)
+{
+	unsigned long ticks = 0 - omap_mpu_timer_read(0);
+	unsigned long long ticks64;
+
+	ticks64 = omap_mpu_timer1_overflows;
+	ticks64 <<= 32;
+	ticks64 |= ticks;
+
+	return cycles_2_ns(ticks64);
+}
+#endif	/* CONFIG_OMAP_MPU_TIMER */
+
+#ifdef CONFIG_OMAP_32K_TIMER
+
+#ifdef CONFIG_ARCH_OMAP1510
+#error OMAP 32KHz timer does not currently work on 1510!
+#endif
+
+/*
+ * ---------------------------------------------------------------------------
+ * 32KHz OS timer
+ *
+ * This currently works only on 16xx, as 1510 does not have the continuous
+ * 32KHz synchronous timer. The 32KHz synchronous timer is used to keep track
+ * of time in addition to the 32KHz OS timer. Using only the 32KHz OS timer
+ * on 1510 would be possible, but the timer would not be as accurate as
+ * with the 32KHz synchronized timer.
+ * ---------------------------------------------------------------------------
+ */
+#define OMAP_32K_TIMER_BASE		0xfffb9000
+#define OMAP_32K_TIMER_CR		0x08
+#define OMAP_32K_TIMER_TVR		0x00
+#define OMAP_32K_TIMER_TCR		0x04
+
+#define OMAP_32K_TICKS_PER_HZ		(32768 / HZ)
+
+/*
+ * TRM says 1 / HZ = ( TVR + 1) / 32768, so TRV = (32768 / HZ) - 1
+ * so with HZ = 100, TVR = 327.68.
+ */
+#define OMAP_32K_TIMER_TICK_PERIOD	((32768 / HZ) - 1)
+#define MAX_SKIP_JIFFIES		25
+#define TIMER_32K_SYNCHRONIZED		0xfffbc410
+
+#define JIFFIES_TO_HW_TICKS(nr_jiffies, clock_rate)			\
+				(((nr_jiffies) * (clock_rate)) / HZ)
+
+static inline void omap_32k_timer_write(int val, int reg)
+{
+	omap_writew(val, reg + OMAP_32K_TIMER_BASE);
+}
+
+static inline unsigned long omap_32k_timer_read(int reg)
+{
+	return omap_readl(reg + OMAP_32K_TIMER_BASE) & 0xffffff;
+}
+
+/*
+ * The 32KHz synchronized timer is an additional timer on 16xx.
+ * It is always running.
+ */
+static inline unsigned long omap_32k_sync_timer_read(void)
+{
+	return omap_readl(TIMER_32K_SYNCHRONIZED);
+}
+
+static inline void omap_32k_timer_start(unsigned long load_val)
+{
+	omap_32k_timer_write(load_val, OMAP_32K_TIMER_TVR);
+	omap_32k_timer_write(0x0f, OMAP_32K_TIMER_CR);
+}
+
+static inline void omap_32k_timer_stop(void)
+{
+	omap_32k_timer_write(0x0, OMAP_32K_TIMER_CR);
+}
+
+/*
+ * Rounds down to nearest usec
+ */
+static inline unsigned long omap_32k_ticks_to_usecs(unsigned long ticks_32k)
+{
+	return (ticks_32k * 5*5*5*5*5*5) >> 9;
+}
+
+static unsigned long omap_32k_last_tick = 0;
+
+/*
+ * Returns elapsed usecs since last 32k timer interrupt
+ */
+static unsigned long omap_32k_timer_gettimeoffset(void)
+{
+	unsigned long now = omap_32k_sync_timer_read();
+	return omap_32k_ticks_to_usecs(now - omap_32k_last_tick);
+}
+
+/*
+ * Timer interrupt for 32KHz timer. When dynamic tick is enabled, this
+ * function is also called from other interrupts to remove latency
+ * issues with dynamic tick. In the dynamic tick case, we need to lock
+ * with irqsave.
+ */
+static irqreturn_t omap_32k_timer_interrupt(int irq, void *dev_id,
+					    struct pt_regs *regs)
+{
+	unsigned long flags;
+	unsigned long now;
+
+	write_seqlock_irqsave(&xtime_lock, flags);
+	now = omap_32k_sync_timer_read();
+
+	while (now - omap_32k_last_tick >= OMAP_32K_TICKS_PER_HZ) {
+		omap_32k_last_tick += OMAP_32K_TICKS_PER_HZ;
+		timer_tick(regs);
+	}
+
+	/* Restart timer so we don't drift off due to modulo or dynamic tick.
+	 * By default we program the next timer to be continuous to avoid
+	 * latencies during high system load. During dynamic tick operation the
+	 * continuous timer can be overridden from pm_idle to be longer.
+	 */
+	omap_32k_timer_start(omap_32k_last_tick + OMAP_32K_TICKS_PER_HZ - now);
+	write_sequnlock_irqrestore(&xtime_lock, flags);
+
+	return IRQ_HANDLED;
+}
+
+static struct irqaction omap_32k_timer_irq = {
+	.name		= "32KHz timer",
+	.flags		= SA_INTERRUPT,
+	.handler	= omap_32k_timer_interrupt
+};
+
+static __init void omap_init_32k_timer(void)
+{
+	setup_irq(INT_OS_TIMER, &omap_32k_timer_irq);
+	omap_timer.offset  = omap_32k_timer_gettimeoffset;
+	omap_32k_last_tick = omap_32k_sync_timer_read();
+	omap_32k_timer_start(OMAP_32K_TIMER_TICK_PERIOD);
+}
+#endif	/* CONFIG_OMAP_32K_TIMER */
+
+/*
  * ---------------------------------------------------------------------------
  * Timer initialization
  * ---------------------------------------------------------------------------
  */
 void __init omap_timer_init(void)
 {
+#if defined(CONFIG_OMAP_MPU_TIMER)
 	omap_init_mpu_timer();
+#elif defined(CONFIG_OMAP_32K_TIMER)
+	omap_init_32k_timer();
+#else
+#error No system timer selected in Kconfig!
+#endif
 }
 
 struct sys_timer omap_timer = {
diff -Nru a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig
--- a/arch/arm/mach-pxa/Kconfig	2005-03-11 12:51:42 -08:00
+++ b/arch/arm/mach-pxa/Kconfig	2005-03-11 12:51:42 -08:00
@@ -19,28 +19,36 @@
 	select PXA25x
 
 config PXA_SHARPSL
-	bool "SHARP SL-C7xx Models (Corgi, Shepherd and Husky)"
+	bool "SHARP SL-5600 and SL-C7xx Models"
 	select PXA25x
 	help
 	  Say Y here if you intend to run this kernel on a
-	  Sharp SL-C700 (Corgi), SL-C750 (Shepherd) or a
-	  Sharp SL-C760 (Husky) handheld computer.
+	  Sharp SL-5600 (Poodle), Sharp SL-C700 (Corgi),
+	  SL-C750 (Shepherd) or a Sharp SL-C760 (Husky)
+	  handheld computer.
 
 endchoice
 
 endmenu
 
+config MACH_POODLE
+	bool "Enable Sharp SL-5600 (Poodle) Support"
+	depends PXA_SHARPSL
+
 config MACH_CORGI
 	bool "Enable Sharp SL-C700 (Corgi) Support"
 	depends PXA_SHARPSL
+	select PXA_SHARP_C7xx
 
 config MACH_SHEPHERD
 	bool "Enable Sharp SL-C750 (Shepherd) Support"
 	depends PXA_SHARPSL
+	select PXA_SHARP_C7xx
 
 config MACH_HUSKY
 	bool "Enable Sharp SL-C760 (Husky) Support"
 	depends PXA_SHARPSL
+	select PXA_SHARP_C7xx
 
 config PXA25x
 	bool
@@ -56,5 +64,10 @@
 	bool
 	help
 	  Enable support for iWMMXt
+
+config PXA_SHARP_C7xx
+	bool
+	help
+	  Enable support for all Sharp C7xx models
 
 endif
diff -Nru a/arch/arm/mach-pxa/Makefile b/arch/arm/mach-pxa/Makefile
--- a/arch/arm/mach-pxa/Makefile	2005-03-11 12:51:46 -08:00
+++ b/arch/arm/mach-pxa/Makefile	2005-03-11 12:51:46 -08:00
@@ -11,7 +11,8 @@
 obj-$(CONFIG_ARCH_LUBBOCK) += lubbock.o
 obj-$(CONFIG_MACH_MAINSTONE) += mainstone.o
 obj-$(CONFIG_ARCH_PXA_IDP) += idp.o
-obj-$(CONFIG_PXA_SHARPSL)	+= corgi.o corgi_ssp.o ssp.o
+obj-$(CONFIG_PXA_SHARP_C7xx)	+= corgi.o corgi_ssp.o ssp.o
+obj-$(CONFIG_MACH_POODLE)	+= poodle.o
 
 # Support for blinky lights
 led-y := leds.o
diff -Nru a/arch/arm/mach-pxa/corgi.c b/arch/arm/mach-pxa/corgi.c
--- a/arch/arm/mach-pxa/corgi.c	2005-03-11 12:51:40 -08:00
+++ b/arch/arm/mach-pxa/corgi.c	2005-03-11 12:51:40 -08:00
@@ -59,7 +59,7 @@
 	.io_out		= CORGI_SCOOP_IO_OUT,
 };
 
-static struct platform_device corgiscoop_device = {
+struct platform_device corgiscoop_device = {
 	.name		= "sharp-scoop",
 	.id		= -1,
 	.dev		= {
diff -Nru a/arch/arm/mach-pxa/idp.c b/arch/arm/mach-pxa/idp.c
--- a/arch/arm/mach-pxa/idp.c	2005-03-11 12:51:40 -08:00
+++ b/arch/arm/mach-pxa/idp.c	2005-03-11 12:51:40 -08:00
@@ -10,13 +10,16 @@
  *  2001-09-13: Cliff Brake <cbrake@accelent.com>
  *              Initial code
  *
- * Expected command line: mem=32M initrd=0xa1000000,4M root=/dev/ram ramdisk=8192
+ *  2005-02-15: Cliff Brake <cliff.brake@gmail.com>
+ *  		<http://www.vibren.com> <http://bec-systems.com>
+ *              Updated for 2.6 kernel
+ *
  */
-#include <linux/kernel.h>
+
 #include <linux/init.h>
-#include <linux/major.h>
-#include <linux/fs.h>
 #include <linux/interrupt.h>
+#include <linux/device.h>
+#include <linux/fb.h>
 
 #include <asm/setup.h>
 #include <asm/memory.h>
@@ -29,68 +32,133 @@
 
 #include <asm/arch/pxa-regs.h>
 #include <asm/arch/idp.h>
+#include <asm/arch/pxafb.h>
+#include <asm/arch/bitfield.h>
+#include <asm/arch/mmc.h>
 
 #include "generic.h"
 
-#ifndef PXA_IDP_REV02
-/* shadow registers for write only registers */
-unsigned int idp_cpld_led_control_shadow = 0x1;
-unsigned int idp_cpld_periph_pwr_shadow = 0xd;
-unsigned int ipd_cpld_cir_shadow = 0;
-unsigned int idp_cpld_kb_col_high_shadow = 0;
-unsigned int idp_cpld_kb_col_low_shadow = 0;
-unsigned int idp_cpld_pccard_en_shadow = 0xC3;
-unsigned int idp_cpld_gpioh_dir_shadow = 0;
-unsigned int idp_cpld_gpioh_value_shadow = 0;
-unsigned int idp_cpld_gpiol_dir_shadow = 0;
-unsigned int idp_cpld_gpiol_value_shadow = 0;
-
-/*
- * enable all LCD signals -- they should still be on
- * write protect flash
- * enable all serial port transceivers
+/* TODO:
+ * - add pxa2xx_audio_ops_t device structure
+ * - Ethernet interrupt
  */
 
-unsigned int idp_control_port_shadow = ((0x7 << 21) | 		/* LCD power */
-					(0x1 << 19) |		/* disable flash write enable */
-					(0x7 << 9));		/* enable serial port transeivers */
+static struct resource smc91x_resources[] = {
+	[0] = {
+		.start	= (IDP_ETH_PHYS + 0x300),
+		.end	= (IDP_ETH_PHYS + 0xfffff),
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= IRQ_GPIO(4),
+		.end	= IRQ_GPIO(4),
+		.flags	= IORESOURCE_IRQ,
+	}
+};
+
+static struct platform_device smc91x_device = {
+	.name		= "smc91x",
+	.id		= 0,
+	.num_resources	= ARRAY_SIZE(smc91x_resources),
+	.resource	= smc91x_resources,
+};
+
+static void idp_backlight_power(int on)
+{
+	if (on) {
+		IDP_CPLD_LCD |= (1<<1);
+	} else {
+		IDP_CPLD_LCD &= ~(1<<1);
+	}
+}
+
+static void idp_vlcd(int on)
+{
+	if (on) {
+		IDP_CPLD_LCD |= (1<<2);
+	} else {
+		IDP_CPLD_LCD &= ~(1<<2);
+	}
+}
+
+static void idp_lcd_power(int on)
+{
+	if (on) {
+		IDP_CPLD_LCD |= (1<<0);
+	} else {
+		IDP_CPLD_LCD &= ~(1<<0);
+	}
+
+	/* call idp_vlcd for now as core driver does not support
+	 * both power and vlcd hooks.  Note, this is not technically
+	 * the correct sequence, but seems to work.  Disclaimer:
+	 * this may eventually damage the display.
+	 */
+
+	idp_vlcd(on);
+}
+
+static struct pxafb_mach_info sharp_lm8v31 __initdata = {
+	.pixclock	= 270000,
+	.xres		= 640,
+	.yres		= 480,
+	.bpp		= 16,
+	.hsync_len	= 1,
+	.left_margin	= 3,
+	.right_margin	= 3,
+	.vsync_len	= 1,
+	.upper_margin	= 0,
+	.lower_margin	= 0,
+	.sync		= FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+	.cmap_greyscale	= 0,
+	.cmap_inverse	= 0,
+	.cmap_static	= 0,
+	.lccr0		= LCCR0_SDS,
+	.lccr3		= LCCR3_PCP | LCCR3_Acb(255),
+	.pxafb_backlight_power = &idp_backlight_power,
+	.pxafb_lcd_power = &idp_lcd_power
+};
+
+static int idp_mci_init(struct device *dev, irqreturn_t (*idp_detect_int)(int, void *, struct pt_regs *), void *data)
+{
+	/* setup GPIO for PXA25x MMC controller	*/
+	pxa_gpio_mode(GPIO6_MMCCLK_MD);
+	pxa_gpio_mode(GPIO8_MMCCS0_MD);
+
+	return 0;
+}
 
-#endif
+static struct pxamci_platform_data idp_mci_platform_data = {
+	.ocr_mask	= MMC_VDD_32_33|MMC_VDD_33_34,
+	.init 		= idp_mci_init,
+};
 
 static void __init idp_init(void)
 {
 	printk("idp_init()\n");
+
+	platform_device_register(&smc91x_device);
+	//platform_device_register(&mst_audio_device);
+	set_pxa_fb_info(&sharp_lm8v31);
+	pxa_set_mci_info(&idp_mci_platform_data);
 }
 
 static void __init idp_init_irq(void)
 {
+
 	pxa_init_irq();
+
+	set_irq_type(TOUCH_PANEL_IRQ, TOUCH_PANEL_IRQ_EDGE);
 }
 
 static struct map_desc idp_io_desc[] __initdata = {
  /* virtual     physical    length      type */
 
-
-#ifndef PXA_IDP_REV02
-  { IDP_CTRL_PORT_BASE,
-    IDP_CTRL_PORT_PHYS,
-    IDP_CTRL_PORT_SIZE,
-    MT_DEVICE },
-#endif
-
-  { IDP_IDE_BASE,
-    IDP_IDE_PHYS,
-    IDP_IDE_SIZE,
-    MT_DEVICE },
-  { IDP_ETH_BASE,
-    IDP_ETH_PHYS,
-    IDP_ETH_SIZE,
-    MT_DEVICE },
-  { IDP_COREVOLT_BASE,
+  { IDP_COREVOLT_VIRT,
     IDP_COREVOLT_PHYS,
     IDP_COREVOLT_SIZE,
     MT_DEVICE },
-  { IDP_CPLD_BASE,
+  { IDP_CPLD_VIRT,
     IDP_CPLD_PHYS,
     IDP_CPLD_SIZE,
     MT_DEVICE }
@@ -101,8 +169,6 @@
 	pxa_map_io();
 	iotable_init(idp_io_desc, ARRAY_SIZE(idp_io_desc));
 
-	set_irq_type(TOUCH_PANEL_IRQ, TOUCH_PANEL_IRQ_EDGE);
-
 	// serial ports 2 & 3
 	pxa_gpio_mode(GPIO42_BTRXD_MD);
 	pxa_gpio_mode(GPIO43_BTTXD_MD);
@@ -114,8 +180,8 @@
 }
 
 
-MACHINE_START(PXA_IDP, "Accelent Xscale IDP")
-	MAINTAINER("Accelent Systems Inc.")
+MACHINE_START(PXA_IDP, "Vibren PXA255 IDP")
+	MAINTAINER("Vibren Technologies")
 	BOOT_MEM(0xa0000000, 0x40000000, io_p2v(0x40000000))
 	MAPIO(idp_map_io)
 	INITIRQ(idp_init_irq)
diff -Nru a/arch/arm/mach-pxa/irq.c b/arch/arm/mach-pxa/irq.c
--- a/arch/arm/mach-pxa/irq.c	2005-03-11 12:51:51 -08:00
+++ b/arch/arm/mach-pxa/irq.c	2005-03-11 12:51:51 -08:00
@@ -97,23 +97,23 @@
 		type = __IRQT_RISEDGE | __IRQT_FALEDGE;
 	}
 
-	printk(KERN_DEBUG "IRQ%d (GPIO%d): ", irq, gpio);
+	/* printk(KERN_DEBUG "IRQ%d (GPIO%d): ", irq, gpio); */
 
 	pxa_gpio_mode(gpio | GPIO_IN);
 
 	if (type & __IRQT_RISEDGE) {
-		printk("rising ");
+		/* printk("rising "); */
 		__set_bit (gpio, GPIO_IRQ_rising_edge);
 	} else
 		__clear_bit (gpio, GPIO_IRQ_rising_edge);
 
 	if (type & __IRQT_FALEDGE) {
-		printk("falling ");
+		/* printk("falling "); */
 		__set_bit (gpio, GPIO_IRQ_falling_edge);
 	} else
 		__clear_bit (gpio, GPIO_IRQ_falling_edge);
 
-	printk("edges\n");
+	/* printk("edges\n"); */
 
 	GRER(gpio) = GPIO_IRQ_rising_edge[idx] & GPIO_IRQ_mask[idx];
 	GFER(gpio) = GPIO_IRQ_falling_edge[idx] & GPIO_IRQ_mask[idx];
diff -Nru a/arch/arm/mach-pxa/leds-idp.c b/arch/arm/mach-pxa/leds-idp.c
--- a/arch/arm/mach-pxa/leds-idp.c	2005-03-11 12:51:50 -08:00
+++ b/arch/arm/mach-pxa/leds-idp.c	2005-03-11 12:51:50 -08:00
@@ -19,6 +19,7 @@
 #include <asm/leds.h>
 #include <asm/system.h>
 
+#include <asm/arch/pxa-regs.h>
 #include <asm/arch/idp.h>
 
 #include "leds.h"
diff -Nru a/arch/arm/mach-pxa/lubbock.c b/arch/arm/mach-pxa/lubbock.c
--- a/arch/arm/mach-pxa/lubbock.c	2005-03-11 12:51:52 -08:00
+++ b/arch/arm/mach-pxa/lubbock.c	2005-03-11 12:51:52 -08:00
@@ -138,6 +138,7 @@
 
 static struct resource smc91x_resources[] = {
 	[0] = {
+		.name	= "smc91x-regs",
 		.start	= 0x0c000000,
 		.end	= 0x0c0fffff,
 		.flags	= IORESOURCE_MEM,
@@ -148,6 +149,7 @@
 		.flags	= IORESOURCE_IRQ,
 	},
 	[2] = {
+		.name	= "smc91x-attrib",
 		.start	= 0x0e000000,
 		.end	= 0x0e0fffff,
 		.flags	= IORESOURCE_MEM,
diff -Nru a/arch/arm/mach-pxa/mainstone.c b/arch/arm/mach-pxa/mainstone.c
--- a/arch/arm/mach-pxa/mainstone.c	2005-03-11 12:51:52 -08:00
+++ b/arch/arm/mach-pxa/mainstone.c	2005-03-11 12:51:52 -08:00
@@ -295,6 +295,15 @@
 {
 	pxa_map_io();
 	iotable_init(mainstone_io_desc, ARRAY_SIZE(mainstone_io_desc));
+
+	/* initialize sleep mode regs (wake-up sources, etc) */
+	PGSR0 = 0x00008800;
+	PGSR1 = 0x00000002;
+	PGSR2 = 0x0001FC00;
+	PGSR3 = 0x00001F81;
+	PWER  = 0xC0000002;
+	PRER  = 0x00000002;
+	PFER  = 0x00000002;
 }
 
 MACHINE_START(MAINSTONE, "Intel HCDDBBVA0 Development Platform (aka Mainstone)")
diff -Nru a/arch/arm/mach-pxa/pm.c b/arch/arm/mach-pxa/pm.c
--- a/arch/arm/mach-pxa/pm.c	2005-03-11 12:51:47 -08:00
+++ b/arch/arm/mach-pxa/pm.c	2005-03-11 12:51:47 -08:00
@@ -47,12 +47,18 @@
  */
 enum {	SLEEP_SAVE_START = 0,
 
-	SLEEP_SAVE_GPLR0, SLEEP_SAVE_GPLR1, SLEEP_SAVE_GPLR2,
-	SLEEP_SAVE_GPDR0, SLEEP_SAVE_GPDR1, SLEEP_SAVE_GPDR2,
-	SLEEP_SAVE_GRER0, SLEEP_SAVE_GRER1, SLEEP_SAVE_GRER2,
-	SLEEP_SAVE_GFER0, SLEEP_SAVE_GFER1, SLEEP_SAVE_GFER2,
-	SLEEP_SAVE_GAFR0_L, SLEEP_SAVE_GAFR1_L, SLEEP_SAVE_GAFR2_L,
-	SLEEP_SAVE_GAFR0_U, SLEEP_SAVE_GAFR1_U, SLEEP_SAVE_GAFR2_U,
+	SLEEP_SAVE_GPLR0, SLEEP_SAVE_GPLR1, SLEEP_SAVE_GPLR2, SLEEP_SAVE_GPLR3,
+	SLEEP_SAVE_GPDR0, SLEEP_SAVE_GPDR1, SLEEP_SAVE_GPDR2, SLEEP_SAVE_GPDR3,
+	SLEEP_SAVE_GRER0, SLEEP_SAVE_GRER1, SLEEP_SAVE_GRER2, SLEEP_SAVE_GRER3,
+	SLEEP_SAVE_GFER0, SLEEP_SAVE_GFER1, SLEEP_SAVE_GFER2, SLEEP_SAVE_GFER3,
+	SLEEP_SAVE_PGSR0, SLEEP_SAVE_PGSR1, SLEEP_SAVE_PGSR2, SLEEP_SAVE_PGSR3,
+
+	SLEEP_SAVE_GAFR0_L, SLEEP_SAVE_GAFR0_U,
+	SLEEP_SAVE_GAFR1_L, SLEEP_SAVE_GAFR1_U,
+	SLEEP_SAVE_GAFR2_L, SLEEP_SAVE_GAFR2_U,
+	SLEEP_SAVE_GAFR3_L, SLEEP_SAVE_GAFR3_U,
+
+	SLEEP_SAVE_PSTR,
 
 	SLEEP_SAVE_ICMR,
 	SLEEP_SAVE_CKEN,
@@ -73,6 +79,11 @@
 	if (state != PM_SUSPEND_MEM)
 		return -EINVAL;
 
+#ifdef CONFIG_IWMMXT
+	/* force any iWMMXt context to ram **/
+	iwmmxt_task_disable(NULL);
+#endif
+
 	/* preserve current time */
 	rtc.tv_sec = RCNR;
 	rtc.tv_nsec = 0;
@@ -82,20 +93,32 @@
 	SAVE(GPDR0); SAVE(GPDR1); SAVE(GPDR2);
 	SAVE(GRER0); SAVE(GRER1); SAVE(GRER2);
 	SAVE(GFER0); SAVE(GFER1); SAVE(GFER2);
+	SAVE(PGSR0); SAVE(PGSR1); SAVE(PGSR2);
+
 	SAVE(GAFR0_L); SAVE(GAFR0_U);
 	SAVE(GAFR1_L); SAVE(GAFR1_U);
 	SAVE(GAFR2_L); SAVE(GAFR2_U);
 
+#ifdef CONFIG_PXA27x
+	SAVE(GPLR3); SAVE(GPDR3); SAVE(GRER3); SAVE(GFER3); SAVE(PGSR3);
+	SAVE(GAFR3_L); SAVE(GAFR3_U);
+#endif
+
 	SAVE(ICMR);
 	ICMR = 0;
 
 	SAVE(CKEN);
 	CKEN = 0;
 
+	SAVE(PSTR);
+
 	/* Note: wake up source are set up in each machine specific files */
 
 	/* clear GPIO transition detect  bits */
 	GEDR0 = GEDR0; GEDR1 = GEDR1; GEDR2 = GEDR2;
+#ifdef CONFIG_PXA27x
+	GEDR3 = GEDR3;
+#endif
 
 	/* Clear sleep reset status */
 	RCSR = RCSR_SMR;
@@ -121,7 +144,8 @@
 #ifdef CONFIG_ARCH_LUBBOCK
 		LUB_HEXLED = 0xbadbadc5;
 #endif
-		while (1);
+		while (1)
+			pxa_cpu_suspend();
 	}
 
 	/* ensure not to come back here if it wasn't intended */
@@ -135,6 +159,12 @@
 	RESTORE(GPDR0); RESTORE(GPDR1); RESTORE(GPDR2);
 	RESTORE(GRER0); RESTORE(GRER1); RESTORE(GRER2);
 	RESTORE(GFER0); RESTORE(GFER1); RESTORE(GFER2);
+	RESTORE(PGSR0); RESTORE(PGSR1); RESTORE(PGSR2);
+
+#ifdef CONFIG_PXA27x
+	RESTORE(GAFR3_L); RESTORE(GAFR3_U); RESTORE_GPLEVEL(3);
+	RESTORE(GPDR3); RESTORE(GRER3); RESTORE(GFER3); RESTORE(PGSR3);
+#endif
 
 	PSSR = PSSR_RDH | PSSR_PH;
 
@@ -143,6 +173,8 @@
 	ICLR = 0;
 	ICCR = 1;
 	RESTORE(ICMR);
+
+	RESTORE(PSTR);
 
 	/* restore current time */
 	rtc.tv_sec = RCNR;
diff -Nru a/arch/arm/mach-pxa/poodle.c b/arch/arm/mach-pxa/poodle.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/arm/mach-pxa/poodle.c	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,181 @@
+/*
+ * linux/arch/arm/mach-pxa/poodle.c
+ *
+ *  Support for the SHARP Poodle Board.
+ *
+ * Based on:
+ *  linux/arch/arm/mach-pxa/lubbock.c Author:	Nicolas Pitre
+ *
+ *  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.
+ *
+ * Change Log
+ *  12-Dec-2002 Sharp Corporation for Poodle
+ *  John Lenz <lenz@cs.wisc.edu> updates to 2.6
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/fb.h>
+
+#include <asm/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/irq.h>
+#include <asm/setup.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <asm/arch/pxa-regs.h>
+#include <asm/arch/irq.h>
+#include <asm/arch/poodle.h>
+#include <asm/arch/pxafb.h>
+
+#include <asm/hardware/scoop.h>
+#include <asm/hardware/locomo.h>
+
+#include "generic.h"
+
+static struct resource poodle_scoop_resources[] = {
+	[0] = {
+		.start		= 0x10800000,
+		.end		= 0x10800fff,
+		.flags		= IORESOURCE_MEM,
+	},
+};
+
+static struct scoop_config poodle_scoop_setup = {
+	.io_dir		= POODLE_SCOOP_IO_DIR,
+	.io_out		= POODLE_SCOOP_IO_OUT,
+};
+
+struct platform_device poodle_scoop_device = {
+	.name		= "sharp-scoop",
+	.id		= -1,
+	.dev		= {
+		.platform_data	= &poodle_scoop_setup,
+	},
+	.num_resources	= ARRAY_SIZE(poodle_scoop_resources),
+	.resource	= poodle_scoop_resources,
+};
+
+
+/* LoCoMo device */
+static struct resource locomo_resources[] = {
+	[0] = {
+		.start		= 0x10000000,
+		.end		= 0x10001fff,
+		.flags		= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start		= IRQ_GPIO(10),
+		.end		= IRQ_GPIO(10),
+		.flags		= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device locomo_device = {
+	.name		= "locomo",
+	.id		= 0,
+	.num_resources	= ARRAY_SIZE(locomo_resources),
+	.resource	= locomo_resources,
+};
+
+/* PXAFB device */
+static struct pxafb_mach_info poodle_fb_info __initdata = {
+	.pixclock	= 144700,
+
+	.xres		= 320,
+	.yres		= 240,
+	.bpp		= 16,
+
+	.hsync_len	= 7,
+	.left_margin	= 11,
+	.right_margin	= 30,
+
+	.vsync_len	= 2,
+	.upper_margin	= 2,
+	.lower_margin	= 0,
+	.sync		= FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+
+	.lccr0		= LCCR0_Act | LCCR0_Sngl | LCCR0_Color,
+	.lccr3		= 0,
+
+	.pxafb_backlight_power	= NULL,
+	.pxafb_lcd_power	= NULL,
+};
+
+static struct platform_device *devices[] __initdata = {
+	&locomo_device,
+	&poodle_scoop_device,
+};
+
+static void __init poodle_init(void)
+{
+	int ret = 0;
+
+	/* cpu initialize */
+	/* Pgsr Register */
+  	PGSR0 = 0x0146dd80;
+  	PGSR1 = 0x03bf0890;
+  	PGSR2 = 0x0001c000;
+
+	/* Alternate Register */
+  	GAFR0_L = 0x01001000;
+  	GAFR0_U = 0x591a8010;
+  	GAFR1_L = 0x900a8451;
+  	GAFR1_U = 0xaaa5aaaa;
+  	GAFR2_L = 0x8aaaaaaa;
+  	GAFR2_U = 0x00000002;
+
+	/* Direction Register */
+  	GPDR0 = 0xd3f0904c;
+  	GPDR1 = 0xfcffb7d3;
+  	GPDR2 = 0x0001ffff;
+
+	/* Output Register */
+  	GPCR0 = 0x00000000;
+  	GPCR1 = 0x00000000;
+  	GPCR2 = 0x00000000;
+
+  	GPSR0 = 0x00400000;
+  	GPSR1 = 0x00000000;
+        GPSR2 = 0x00000000;
+
+	set_pxa_fb_info(&poodle_fb_info);
+
+	ret = platform_add_devices(devices, ARRAY_SIZE(devices));
+	if (ret) {
+		printk(KERN_WARNING "poodle: Unable to register LoCoMo device\n");
+	}
+}
+
+static struct map_desc poodle_io_desc[] __initdata = {
+ /* virtual     physical    length                   */
+  { 0xef800000, 0x00000000, 0x00800000, MT_DEVICE }, /* Boot Flash */
+};
+
+static void __init poodle_map_io(void)
+{
+	pxa_map_io();
+	iotable_init(poodle_io_desc, ARRAY_SIZE(poodle_io_desc));
+
+	/* setup sleep mode values */
+	PWER  = 0x00000002;
+	PFER  = 0x00000000;
+	PRER  = 0x00000002;
+	PGSR0 = 0x00008000;
+	PGSR1 = 0x003F0202;
+	PGSR2 = 0x0001C000;
+	PCFR |= PCFR_OPDE;
+}
+
+MACHINE_START(POODLE, "SHARP Poodle")
+	BOOT_MEM(0xa0000000, 0x40000000, io_p2v(0x40000000))
+	MAPIO(poodle_map_io)
+	INITIRQ(pxa_init_irq)
+	.timer = &pxa_timer,
+	.init_machine = poodle_init,
+MACHINE_END
diff -Nru a/arch/arm/mach-s3c2410/Kconfig b/arch/arm/mach-s3c2410/Kconfig
--- a/arch/arm/mach-s3c2410/Kconfig	2005-03-11 12:51:42 -08:00
+++ b/arch/arm/mach-s3c2410/Kconfig	2005-03-11 12:51:42 -08:00
@@ -19,6 +19,14 @@
 
 	  <http://www.handhelds.org/projects/h1940.html>.
 
+config MACH_N30
+	bool "Acer N30"
+	select CPU_S3C2410
+	help
+	  Say Y here if you are using the Acer N30
+
+	  <http://zoo.weinigel.se/n30>.
+
 config ARCH_SMDK2410
 	bool "SMDK2410/A9M2410"
 	select CPU_S3C2410
@@ -26,6 +34,12 @@
 	   Say Y here if you are using the SMDK2410 or the derived module A9M2410
            <http://www.fsforth.de>
 
+config ARCH_S3C2440
+	bool "SMDK2440"
+	select CPU_S3C2440
+	help
+	  Say Y here if you are using the SMDK2440.
+
 config MACH_VR1000
 	bool "Thorcom VR1000"
 	select CPU_S3C2410
@@ -58,6 +72,26 @@
 	depends on ARCH_S3C2410
 	help
 	  Support for S3C2440 Samsung Mobile CPU based systems.
+
+comment "S3C2410 Boot"
+
+config S3C2410_BOOT_WATCHDOG
+	bool "S3C2410 Initialisation watchdog"
+	depends on ARCH_S3C2410 && S3C2410_WATCHDOG
+	help
+	  Say y to enable the watchdog during the kernel decompression
+	  stage. If the kernel fails to uncompress, then the watchdog
+	  will trigger a reset and the system should restart.
+
+	  Although this uses the same hardware unit as the kernel watchdog
+	  driver, it is not a replacement for it. If you use this option,
+	  you will have to use the watchdg driver to either stop the timeout
+	  or restart it. If you do not, then your kernel will reboot after
+	  startup.
+
+	  The driver uses a fixed timeout value, so the exact time till the
+	  system resets depends on the value of PCLK. The timeout on an
+	  200MHz s3c2410 should be about 30 seconds.
 
 comment "S3C2410 Setup"
 
diff -Nru a/arch/arm/mach-s3c2410/Makefile b/arch/arm/mach-s3c2410/Makefile
--- a/arch/arm/mach-s3c2410/Makefile	2005-03-11 12:51:41 -08:00
+++ b/arch/arm/mach-s3c2410/Makefile	2005-03-11 12:51:41 -08:00
@@ -27,6 +27,8 @@
 
 obj-$(CONFIG_ARCH_BAST)		+= mach-bast.o usb-simtec.o
 obj-$(CONFIG_ARCH_H1940)	+= mach-h1940.o
+obj-$(CONFIG_MACH_N30)		+= mach-n30.o
 obj-$(CONFIG_ARCH_SMDK2410)	+= mach-smdk2410.o
+obj-$(CONFIG_ARCH_S3C2440)	+= mach-smdk2440.o
 obj-$(CONFIG_MACH_VR1000)	+= mach-vr1000.o usb-simtec.o
 obj-$(CONFIG_MACH_RX3715)	+= mach-rx3715.o
diff -Nru a/arch/arm/mach-s3c2410/clock.c b/arch/arm/mach-s3c2410/clock.c
--- a/arch/arm/mach-s3c2410/clock.c	2005-03-11 12:51:41 -08:00
+++ b/arch/arm/mach-s3c2410/clock.c	2005-03-11 12:51:41 -08:00
@@ -1,7 +1,7 @@
 /* linux/arch/arm/mach-s3c2410/clock.c
  *
- * Copyright (c) 2004 Simtec Electronics
- * Ben Dooks <ben@simtec.co.uk>
+ * Copyright (c) 2004-2005 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
  *
  * S3C2410 Clock control support
  *
@@ -33,6 +33,7 @@
 #include <linux/errno.h>
 #include <linux/err.h>
 #include <linux/device.h>
+#include <linux/sysdev.h>
 
 #include <linux/interrupt.h>
 #include <linux/ioport.h>
@@ -46,18 +47,13 @@
 #include <asm/arch/regs-clock.h>
 
 #include "clock.h"
+#include "cpu.h"
 
 /* clock information */
 
-unsigned long s3c24xx_xtal = 12*1000*1000;	/* default 12MHz */
-unsigned long s3c24xx_fclk;
-unsigned long s3c24xx_hclk;
-unsigned long s3c24xx_pclk;
-
 static LIST_HEAD(clocks);
 static DECLARE_MUTEX(clocks_sem);
 
-
 /* old functions */
 
 void inline s3c24xx_clk_enable(unsigned int clocks, unsigned int enable)
@@ -206,6 +202,14 @@
 
 /* base clocks */
 
+static struct clk clk_xtal = {
+	.name		= "xtal",
+	.id		= -1,
+	.rate		= 0,
+	.parent		= NULL,
+	.ctrlbit	= 0,
+};
+
 static struct clk clk_f = {
 	.name		= "fclk",
 	.id		= -1,
@@ -286,6 +290,7 @@
 	  .ctrlbit = S3C2410_CLKCON_USBD
 	},
 	{ .name    = "timers",
+	  .id	   = -1,
 	  .parent  = &clk_p,
 	  .enable  = s3c24xx_clkcon_enable,
 	  .ctrlbit = S3C2410_CLKCON_PWMT
@@ -378,19 +383,24 @@
 
 /* initalise all the clocks */
 
-int __init s3c24xx_setup_clocks(void)
+int __init s3c24xx_setup_clocks(unsigned long xtal,
+				unsigned long fclk,
+				unsigned long hclk,
+				unsigned long pclk)
 {
 	struct clk *clkp = init_clocks;
 	int ptr;
 	int ret;
 
-	printk(KERN_INFO "S3C2410 Clock control, (c) 2004 Simtec Electronics\n");
+	printk(KERN_INFO "S3C2410 Clocks, (c) 2004 Simtec Electronics\n");
 
 	/* initialise the main system clocks */
 
-	clk_h.rate = s3c24xx_hclk;
-	clk_p.rate = s3c24xx_pclk;
-	clk_f.rate = s3c24xx_fclk;
+	clk_xtal.rate = xtal;
+
+	clk_h.rate = hclk;
+	clk_p.rate = pclk;
+	clk_f.rate = fclk;
 
 	/* it looks like just setting the register here is not good
 	 * enough, and causes the odd hang at initial boot time, so
@@ -414,6 +424,9 @@
 
 	/* register our clocks */
 
+	if (s3c24xx_register_clock(&clk_xtal) < 0)
+		printk(KERN_ERR "failed to register master xtal\n");
+
 	if (s3c24xx_register_clock(&clk_f) < 0)
 		printk(KERN_ERR "failed to register cpu fclk\n");
 
@@ -423,6 +436,8 @@
 	if (s3c24xx_register_clock(&clk_p) < 0)
 		printk(KERN_ERR "failed to register cpu pclk\n");
 
+	/* register clocks from clock array */
+
 	for (ptr = 0; ptr < ARRAY_SIZE(init_clocks); ptr++, clkp++) {
 		ret = s3c24xx_register_clock(clkp);
 		if (ret < 0) {
@@ -434,4 +449,59 @@
 	return 0;
 }
 
+/* S3C2440 extended clock support */
+
+#ifdef CONFIG_CPU_S3C2440
+
+static struct clk s3c2440_clk_upll = {
+	.name		= "upll",
+	.id		= -1,
+};
+
+static struct clk s3c2440_clk_cam = {
+	.name		= "camif",
+	.parent		= &clk_h,
+	.id		= -1,
+	.enable		= s3c24xx_clkcon_enable,
+	.ctrlbit	= S3C2440_CLKCON_CAMERA,
+};
+
+static struct clk s3c2440_clk_ac97 = {
+	.name		= "ac97",
+	.parent		= &clk_p,
+	.id		= -1,
+	.enable		= s3c24xx_clkcon_enable,
+	.ctrlbit	= S3C2440_CLKCON_CAMERA,
+};
+
+static int s3c2440_clk_add(struct sys_device *sysdev)
+{
+	unsigned long upllcon = __raw_readl(S3C2410_UPLLCON);
+
+	s3c2440_clk_upll.rate = s3c2410_get_pll(upllcon, clk_xtal.rate) * 2;
+
+	printk("S3C2440: Clock Support, UPLL %ld.%03ld MHz\n",
+	       print_mhz(s3c2440_clk_upll.rate));
+
+	s3c24xx_register_clock(&s3c2440_clk_ac97);
+	s3c24xx_register_clock(&s3c2440_clk_cam);
+	s3c24xx_register_clock(&s3c2440_clk_upll);
+
+	clk_disable(&s3c2440_clk_ac97);
+	clk_disable(&s3c2440_clk_cam);
+
+	return 0;
+}
+
+static struct sysdev_driver s3c2440_clk_driver = {
+	.add	= s3c2440_clk_add,
+};
+
+static int s3c24xx_clk_driver(void)
+{
+	return sysdev_driver_register(&s3c2440_sysclass, &s3c2440_clk_driver);
+}
+
+arch_initcall(s3c24xx_clk_driver);
 
+#endif /* CONFIG_CPU_S3C2440 */
diff -Nru a/arch/arm/mach-s3c2410/clock.h b/arch/arm/mach-s3c2410/clock.h
--- a/arch/arm/mach-s3c2410/clock.h	2005-03-11 12:51:46 -08:00
+++ b/arch/arm/mach-s3c2410/clock.h	2005-03-11 12:51:46 -08:00
@@ -1,7 +1,8 @@
 /*
  * linux/arch/arm/mach-s3c2410/clock.h
  *
- * Copyright (c) 2004 Simtec Electronics
+ * Copyright (c) 2004-2005 Simtec Electronics
+ *	http://www.simtec.co.uk/products/SWLINUX/
  *	Written by Ben Dooks, <ben@simtec.co.uk>
  *
  * This program is free software; you can redistribute it and/or modify
@@ -29,13 +30,6 @@
 extern struct clk s3c24xx_clkout1;
 extern struct clk s3c24xx_uclk;
 
-/* processor clock settings, in Hz */
-
-extern unsigned long s3c24xx_xtal;
-extern unsigned long s3c24xx_pclk;
-extern unsigned long s3c24xx_hclk;
-extern unsigned long s3c24xx_fclk;
-
 /* exports for arch/arm/mach-s3c2410
  *
  * Please DO NOT use these outside of arch/arm/mach-s3c2410
@@ -44,4 +38,7 @@
 extern int s3c24xx_clkcon_enable(struct clk *clk, int enable);
 extern int s3c24xx_register_clock(struct clk *clk);
 
-extern int s3c24xx_setup_clocks(void);
+extern int s3c24xx_setup_clocks(unsigned long xtal,
+				unsigned long fclk,
+				unsigned long hclk,
+				unsigned long pclk);
diff -Nru a/arch/arm/mach-s3c2410/cpu.c b/arch/arm/mach-s3c2410/cpu.c
--- a/arch/arm/mach-s3c2410/cpu.c	2005-03-11 12:51:46 -08:00
+++ b/arch/arm/mach-s3c2410/cpu.c	2005-03-11 12:51:46 -08:00
@@ -1,7 +1,8 @@
 /* linux/arch/arm/mach-s3c2410/cpu.c
  *
- * Copyright (c) 2004 Simtec Electronics
- * Ben Dooks <ben@simtec.co.uk>
+ * Copyright (c) 2004-2005 Simtec Electronics
+ *	http://www.simtec.co.uk/products/SWLINUX/
+ *	Ben Dooks <ben@simtec.co.uk>
  *
  * S3C24XX CPU Support
  *
@@ -181,8 +182,8 @@
 
 void __init s3c24xx_init_clocks(int xtal)
 {
-	if (xtal != 0)
-		s3c24xx_xtal = xtal;
+	if (xtal == 0)
+		xtal = 12*1000*1000;
 
 	if (cpu == NULL)
 		panic("s3c24xx_init_clocks: no cpu setup?\n");
diff -Nru a/arch/arm/mach-s3c2410/cpu.h b/arch/arm/mach-s3c2410/cpu.h
--- a/arch/arm/mach-s3c2410/cpu.h	2005-03-11 12:51:41 -08:00
+++ b/arch/arm/mach-s3c2410/cpu.h	2005-03-11 12:51:41 -08:00
@@ -15,9 +15,10 @@
  *     04-Jan-2005 BJD  New uart initialisation
  *     10-Jan-2005 BJD  Moved generic init here, specific to cpu headers
  *     14-Jan-2005 BJD  Added s3c24xx_init_clocks() call
+ *     10-Mar-2005 LCVR Changed S3C2410_{VA,SZ} to S3C24XX_{VA,SZ} on IODESC_ENT
 */
 
-#define IODESC_ENT(x) { S3C2410_VA_##x, S3C2410_PA_##x, S3C2410_SZ_##x, MT_DEVICE }
+#define IODESC_ENT(x) { S3C24XX_VA_##x, S3C2410_PA_##x, S3C24XX_SZ_##x, MT_DEVICE }
 
 #ifndef MHZ
 #define MHZ (1000*1000)
@@ -27,6 +28,7 @@
 
 /* forward declaration */
 struct s3c2410_uartcfg;
+struct map_desc;
 
 /* core initialisation functions */
 
@@ -58,3 +60,7 @@
 
 struct sys_timer;
 extern struct sys_timer s3c24xx_timer;
+
+/* system device classes */
+
+extern struct sysdev_class s3c2440_sysclass;
diff -Nru a/arch/arm/mach-s3c2410/devs.c b/arch/arm/mach-s3c2410/devs.c
--- a/arch/arm/mach-s3c2410/devs.c	2005-03-11 12:51:42 -08:00
+++ b/arch/arm/mach-s3c2410/devs.c	2005-03-11 12:51:42 -08:00
@@ -10,6 +10,8 @@
  * published by the Free Software Foundation.
  *
  * Modifications:
+ *     10-Mar-2005 LCVR Changed S3C2410_{VA,SZ} to S3C24XX_{VA,SZ}
+ *     10-Feb-2005 BJD  Added camera from guillaume.gourat@nexvision.tv
  *     29-Aug-2004 BJD  Added timers 0 through 3
  *     29-Aug-2004 BJD  Changed index of devices we only have one of to -1
  *     21-Aug-2004 BJD  Added IRQ_TICK to RTC resources
@@ -45,7 +47,7 @@
 static struct resource s3c_usb_resource[] = {
 	[0] = {
 		.start = S3C2410_PA_USBHOST,
-		.end   = S3C2410_PA_USBHOST + S3C2410_SZ_USBHOST,
+		.end   = S3C2410_PA_USBHOST + S3C24XX_SZ_USBHOST,
 		.flags = IORESOURCE_MEM,
 	},
 	[1] = {
@@ -75,7 +77,7 @@
 static struct resource s3c_lcd_resource[] = {
 	[0] = {
 		.start = S3C2410_PA_LCD,
-		.end   = S3C2410_PA_LCD + S3C2410_SZ_LCD,
+		.end   = S3C2410_PA_LCD + S3C24XX_SZ_LCD,
 		.flags = IORESOURCE_MEM,
 	},
 	[1] = {
@@ -106,7 +108,7 @@
 static struct resource s3c_nand_resource[] = {
 	[0] = {
 		.start = S3C2410_PA_NAND,
-		.end   = S3C2410_PA_NAND + S3C2410_SZ_NAND,
+		.end   = S3C2410_PA_NAND + S3C24XX_SZ_NAND,
 		.flags = IORESOURCE_MEM,
 	}
 };
@@ -125,7 +127,7 @@
 static struct resource s3c_usbgadget_resource[] = {
 	[0] = {
 		.start = S3C2410_PA_USBDEV,
-		.end   = S3C2410_PA_USBDEV + S3C2410_SZ_USBDEV,
+		.end   = S3C2410_PA_USBDEV + S3C24XX_SZ_USBDEV,
 		.flags = IORESOURCE_MEM,
 	},
 	[1] = {
@@ -150,7 +152,7 @@
 static struct resource s3c_wdt_resource[] = {
 	[0] = {
 		.start = S3C2410_PA_WATCHDOG,
-		.end   = S3C2410_PA_WATCHDOG + S3C2410_SZ_WATCHDOG,
+		.end   = S3C2410_PA_WATCHDOG + S3C24XX_SZ_WATCHDOG,
 		.flags = IORESOURCE_MEM,
 	},
 	[1] = {
@@ -175,7 +177,7 @@
 static struct resource s3c_i2c_resource[] = {
 	[0] = {
 		.start = S3C2410_PA_IIC,
-		.end   = S3C2410_PA_IIC + S3C2410_SZ_IIC,
+		.end   = S3C2410_PA_IIC + S3C24XX_SZ_IIC,
 		.flags = IORESOURCE_MEM,
 	},
 	[1] = {
@@ -200,7 +202,7 @@
 static struct resource s3c_iis_resource[] = {
 	[0] = {
 		.start = S3C2410_PA_IIS,
-		.end   = S3C2410_PA_IIS + S3C2410_SZ_IIS,
+		.end   = S3C2410_PA_IIS + S3C24XX_SZ_IIS,
 		.flags = IORESOURCE_MEM,
 	}
 };
@@ -254,7 +256,7 @@
 static struct resource s3c_adc_resource[] = {
 	[0] = {
 		.start = S3C2410_PA_ADC,
-		.end   = S3C2410_PA_ADC + S3C2410_SZ_ADC,
+		.end   = S3C2410_PA_ADC + S3C24XX_SZ_ADC,
 		.flags = IORESOURCE_MEM,
 	},
 	[1] = {
@@ -277,7 +279,7 @@
 static struct resource s3c_sdi_resource[] = {
 	[0] = {
 		.start = S3C2410_PA_SDI,
-		.end   = S3C2410_PA_SDI + S3C2410_SZ_SDI,
+		.end   = S3C2410_PA_SDI + S3C24XX_SZ_SDI,
 		.flags = IORESOURCE_MEM,
 	},
 	[1] = {
@@ -446,3 +448,38 @@
 };
 
 EXPORT_SYMBOL(s3c_device_timer3);
+
+#ifdef CONFIG_CPU_S3C2440
+
+/* Camif Controller */
+
+static struct resource s3c_camif_resource[] = {
+	[0] = {
+		.start = S3C2440_PA_CAMIF,
+		.end   = S3C2440_PA_CAMIF + S3C2440_SZ_CAMIF,
+		.flags = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start = IRQ_CAM,
+		.end   = IRQ_CAM,
+		.flags = IORESOURCE_IRQ,
+	}
+
+};
+
+static u64 s3c_device_camif_dmamask = 0xffffffffUL;
+
+struct platform_device s3c_device_camif = {
+	.name		  = "s3c2440-camif",
+	.id		  = -1,
+	.num_resources	  = ARRAY_SIZE(s3c_camif_resource),
+	.resource	  = s3c_camif_resource,
+	.dev              = {
+		.dma_mask = &s3c_device_camif_dmamask,
+		.coherent_dma_mask = 0xffffffffUL
+	}
+};
+
+EXPORT_SYMBOL(s3c_device_camif);
+
+#endif // CONFIG_CPU_S32440
diff -Nru a/arch/arm/mach-s3c2410/devs.h b/arch/arm/mach-s3c2410/devs.h
--- a/arch/arm/mach-s3c2410/devs.h	2005-03-11 12:51:41 -08:00
+++ b/arch/arm/mach-s3c2410/devs.h	2005-03-11 12:51:41 -08:00
@@ -12,7 +12,11 @@
  * Modifications:
  *      18-Aug-2004 BJD  Created initial version
  *	27-Aug-2004 BJD  Added timers 0 through 3
+ *	10-Feb-2005 BJD	 Added camera from guillaume.gourat@nexvision.tv
 */
+#include <linux/config.h>
+
+extern struct platform_device *s3c24xx_uart_devs[];
 
 extern struct platform_device s3c_device_usb;
 extern struct platform_device s3c_device_lcd;
@@ -34,3 +38,11 @@
 extern struct platform_device s3c_device_timer3;
 
 extern struct platform_device s3c_device_usbgadget;
+
+/* s3c2440 specific devices */
+
+#ifdef CONFIG_CPU_S3C2440
+
+extern struct platform_device s3c_device_camif;
+
+#endif
diff -Nru a/arch/arm/mach-s3c2410/dma.c b/arch/arm/mach-s3c2410/dma.c
--- a/arch/arm/mach-s3c2410/dma.c	2005-03-11 12:51:52 -08:00
+++ b/arch/arm/mach-s3c2410/dma.c	2005-03-11 12:51:52 -08:00
@@ -1,6 +1,6 @@
 /* linux/arch/arm/mach-bast/dma.c
  *
- * (c) 2003,2004 Simtec Electronics
+ * (c) 2003-2005 Simtec Electronics
  *	Ben Dooks <ben@simtec.co.uk>
  *
  * S3C2410 DMA core
@@ -12,6 +12,7 @@
  * published by the Free Software Foundation.
  *
  * Changelog:
+ *  27-Feb-2005 BJD  Added kmem cache for dma descriptors
  *  18-Nov-2004 BJD  Removed error for loading onto stopped channel
  *  10-Nov-2004 BJD  Ensure all external symbols exported for modules
  *  10-Nov-2004 BJD  Use sys_device and sysdev_class for power management
@@ -57,6 +58,7 @@
 
 /* io map for dma */
 static void __iomem *dma_base;
+static kmem_cache_t *dma_kmem;
 
 /* dma channel state information */
 s3c2410_dma_chan_t s3c2410_chans[S3C2410_DMA_CHANNELS];
@@ -432,7 +434,7 @@
 	pr_debug("%s: id=%p, data=%08x, size=%d\n",
 		 __FUNCTION__, id, (unsigned int)data, size);
 
-	buf = (s3c2410_dma_buf_t *)kmalloc(sizeof(*buf), GFP_ATOMIC);
+	buf = kmem_cache_alloc(dma_kmem, GFP_ATOMIC);
 	if (buf == NULL) {
 		pr_debug("%s: out of memory (%d alloc)\n",
 			 __FUNCTION__, sizeof(*buf));
@@ -511,7 +513,7 @@
 	buf->magic = -1;
 
 	if (magicok) {
-		kfree(buf);
+		kmem_cache_free(dma_kmem, buf);
 	} else {
 		printk("s3c2410_dma_freebuf: buff %p with bad magic\n", buf);
 	}
@@ -1128,6 +1130,14 @@
 	.resume		= s3c2410_dma_resume,
 };
 
+/* kmem cache implementation */
+
+static void s3c2410_dma_cache_ctor(void *p, kmem_cache_t *c, unsigned long f)
+{
+	memset(p, 0, sizeof(s3c2410_dma_buf_t));
+}
+
+
 /* initialisation code */
 
 static int __init s3c2410_init_dma(void)
@@ -1150,6 +1160,16 @@
 		goto err;
 	}
 
+	dma_kmem = kmem_cache_create("dma_desc", sizeof(s3c2410_dma_buf_t), 0,
+				     SLAB_HWCACHE_ALIGN,
+				     s3c2410_dma_cache_ctor, NULL);
+
+	if (dma_kmem == NULL) {
+		printk(KERN_ERR "dma failed to make kmem cache\n");
+		ret = -ENOMEM;
+		goto err;
+	}
+
 	for (channel = 0; channel < S3C2410_DMA_CHANNELS; channel++) {
 		cp = &s3c2410_chans[channel];
 
@@ -1181,6 +1201,7 @@
 	return 0;
 
  err:
+	kmem_cache_destroy(dma_kmem);
 	iounmap(dma_base);
 	dma_base = NULL;
 	return ret;
diff -Nru a/arch/arm/mach-s3c2410/irq.c b/arch/arm/mach-s3c2410/irq.c
--- a/arch/arm/mach-s3c2410/irq.c	2005-03-11 12:51:42 -08:00
+++ b/arch/arm/mach-s3c2410/irq.c	2005-03-11 12:51:42 -08:00
@@ -57,6 +57,7 @@
 #include <asm/arch/regs-irq.h>
 #include <asm/arch/regs-gpio.h>
 
+#include "cpu.h"
 #include "pm.h"
 
 #define irqdbf(x...)
@@ -628,6 +629,7 @@
 	s3c_irq_demux_uart(IRQ_S3CUART_RX2, regs);
 }
 
+
 /* s3c24xx_init_irq
  *
  * Initialise S3C2410 IRQ system
@@ -771,3 +773,174 @@
 
 	irqdbf("s3c2410: registered interrupt handlers\n");
 }
+
+/* s3c2440 irq code
+*/
+
+#ifdef CONFIG_CPU_S3C2440
+
+/* WDT/AC97 */
+
+static void s3c_irq_demux_wdtac97(unsigned int irq,
+				  struct irqdesc *desc,
+				  struct pt_regs *regs)
+{
+	unsigned int subsrc, submsk;
+	struct irqdesc *mydesc;
+
+	/* read the current pending interrupts, and the mask
+	 * for what it is available */
+
+	subsrc = __raw_readl(S3C2410_SUBSRCPND);
+	submsk = __raw_readl(S3C2410_INTSUBMSK);
+
+	subsrc &= ~submsk;
+	subsrc >>= 13;
+	subsrc &= 3;
+
+	if (subsrc != 0) {
+		if (subsrc & 1) {
+			mydesc = irq_desc + IRQ_S3C2440_WDT;
+			mydesc->handle( IRQ_S3C2440_WDT, mydesc, regs);
+		}
+		if (subsrc & 2) {
+			mydesc = irq_desc + IRQ_S3C2440_AC97;
+			mydesc->handle(IRQ_S3C2440_AC97, mydesc, regs);
+		}
+	}
+}
+
+
+#define INTMSK_WDT	 (1UL << (IRQ_WDT - IRQ_EINT0))
+
+static void
+s3c_irq_wdtac97_mask(unsigned int irqno)
+{
+	s3c_irqsub_mask(irqno, INTMSK_WDT, 3<<13);
+}
+
+static void
+s3c_irq_wdtac97_unmask(unsigned int irqno)
+{
+	s3c_irqsub_unmask(irqno, INTMSK_WDT);
+}
+
+static void
+s3c_irq_wdtac97_ack(unsigned int irqno)
+{
+	s3c_irqsub_maskack(irqno, INTMSK_WDT, 3<<13);
+}
+
+static struct irqchip s3c_irq_wdtac97 = {
+	.mask	    = s3c_irq_wdtac97_mask,
+	.unmask	    = s3c_irq_wdtac97_unmask,
+	.ack	    = s3c_irq_wdtac97_ack,
+};
+
+/* camera irq */
+
+static void s3c_irq_demux_cam(unsigned int irq,
+			      struct irqdesc *desc,
+			      struct pt_regs *regs)
+{
+	unsigned int subsrc, submsk;
+	struct irqdesc *mydesc;
+
+	/* read the current pending interrupts, and the mask
+	 * for what it is available */
+
+	subsrc = __raw_readl(S3C2410_SUBSRCPND);
+	submsk = __raw_readl(S3C2410_INTSUBMSK);
+
+	subsrc &= ~submsk;
+	subsrc >>= 11;
+	subsrc &= 3;
+
+	if (subsrc != 0) {
+		if (subsrc & 1) {
+			mydesc = irq_desc + IRQ_S3C2440_CAM_C;
+			mydesc->handle( IRQ_S3C2440_WDT, mydesc, regs);
+		}
+		if (subsrc & 2) {
+			mydesc = irq_desc + IRQ_S3C2440_CAM_P;
+			mydesc->handle(IRQ_S3C2440_AC97, mydesc, regs);
+		}
+	}
+}
+
+#define INTMSK_CAM (1UL << (IRQ_CAM - IRQ_EINT0))
+
+static void
+s3c_irq_cam_mask(unsigned int irqno)
+{
+	s3c_irqsub_mask(irqno, INTMSK_CAM, 3<<11);
+}
+
+static void
+s3c_irq_cam_unmask(unsigned int irqno)
+{
+	s3c_irqsub_unmask(irqno, INTMSK_CAM);
+}
+
+static void
+s3c_irq_cam_ack(unsigned int irqno)
+{
+	s3c_irqsub_maskack(irqno, INTMSK_CAM, 3<<11);
+}
+
+static struct irqchip s3c_irq_cam = {
+	.mask	    = s3c_irq_cam_mask,
+	.unmask	    = s3c_irq_cam_unmask,
+	.ack	    = s3c_irq_cam_ack,
+};
+
+static int s3c2440_irq_add(struct sys_device *sysdev)
+{
+	unsigned int irqno;
+
+	printk("S3C2440: IRQ Support\n");
+
+	set_irq_chip(IRQ_NFCON, &s3c_irq_level_chip);
+	set_irq_handler(IRQ_NFCON, do_level_IRQ);
+	set_irq_flags(IRQ_NFCON, IRQF_VALID);
+
+	/* add new chained handler for wdt, ac7 */
+
+	set_irq_chip(IRQ_WDT, &s3c_irq_level_chip);
+	set_irq_handler(IRQ_WDT, do_level_IRQ);
+	set_irq_chained_handler(IRQ_WDT, s3c_irq_demux_wdtac97);
+
+	for (irqno = IRQ_S3C2440_WDT; irqno <= IRQ_S3C2440_AC97; irqno++) {
+		set_irq_chip(irqno, &s3c_irq_wdtac97);
+		set_irq_handler(irqno, do_level_IRQ);
+		set_irq_flags(irqno, IRQF_VALID);
+	}
+
+	/* add chained handler for camera */
+
+	set_irq_chip(IRQ_CAM, &s3c_irq_level_chip);
+	set_irq_handler(IRQ_CAM, do_level_IRQ);
+	set_irq_chained_handler(IRQ_CAM, s3c_irq_demux_cam);
+
+	for (irqno = IRQ_S3C2440_CAM_C; irqno <= IRQ_S3C2440_CAM_P; irqno++) {
+		set_irq_chip(irqno, &s3c_irq_cam);
+		set_irq_handler(irqno, do_level_IRQ);
+		set_irq_flags(irqno, IRQF_VALID);
+	}
+
+	return 0;
+}
+
+static struct sysdev_driver s3c2440_irq_driver = {
+	.add	= s3c2440_irq_add,
+};
+
+static int s3c24xx_irq_driver(void)
+{
+	return sysdev_driver_register(&s3c2440_sysclass, &s3c2440_irq_driver);
+}
+
+arch_initcall(s3c24xx_irq_driver);
+
+#endif /* CONFIG_CPU_S3C2440 */
+
diff -Nru a/arch/arm/mach-s3c2410/mach-bast.c b/arch/arm/mach-s3c2410/mach-bast.c
--- a/arch/arm/mach-s3c2410/mach-bast.c	2005-03-11 12:51:46 -08:00
+++ b/arch/arm/mach-s3c2410/mach-bast.c	2005-03-11 12:51:46 -08:00
@@ -23,6 +23,8 @@
  *     04-Jan-2005 BJD  New uart init call
  *     10-Jan-2005 BJD  Removed include of s3c2410.h
  *     14-Jan-2005 BJD  Add support for muitlple NAND devices
+ *     03-Mar-2005 BJD  Ensured that bast-cpld.h is included
+ *     10-Mar-2005 LCVR Changed S3C2410_VA to S3C24XX_VA
 */
 
 #include <linux/kernel.h>
@@ -39,6 +41,7 @@
 
 #include <asm/arch/bast-map.h>
 #include <asm/arch/bast-irq.h>
+#include <asm/arch/bast-cpld.h>
 
 #include <asm/hardware.h>
 #include <asm/io.h>
@@ -80,8 +83,8 @@
 static struct map_desc bast_iodesc[] __initdata = {
   /* ISA IO areas */
 
-  { S3C2410_VA_ISA_BYTE, PA_CS2(BAST_PA_ISAIO),	   SZ_16M, MT_DEVICE },
-  { S3C2410_VA_ISA_WORD, PA_CS3(BAST_PA_ISAIO),	   SZ_16M, MT_DEVICE },
+  { S3C24XX_VA_ISA_BYTE, PA_CS2(BAST_PA_ISAIO),	   SZ_16M, MT_DEVICE },
+  { S3C24XX_VA_ISA_WORD, PA_CS3(BAST_PA_ISAIO),	   SZ_16M, MT_DEVICE },
 
   /* we could possibly compress the next set down into a set of smaller tables
    * pagetables, but that would mean using an L2 section, and it still means
@@ -407,7 +410,7 @@
 
 MACHINE_START(BAST, "Simtec-BAST")
      MAINTAINER("Ben Dooks <ben@simtec.co.uk>")
-     BOOT_MEM(S3C2410_SDRAM_PA, S3C2410_PA_UART, S3C2410_VA_UART)
+     BOOT_MEM(S3C2410_SDRAM_PA, S3C2410_PA_UART, S3C24XX_VA_UART)
      BOOT_PARAMS(S3C2410_SDRAM_PA + 0x100)
      MAPIO(bast_map_io)
      INITIRQ(bast_init_irq)
diff -Nru a/arch/arm/mach-s3c2410/mach-h1940.c b/arch/arm/mach-s3c2410/mach-h1940.c
--- a/arch/arm/mach-s3c2410/mach-h1940.c	2005-03-11 12:51:50 -08:00
+++ b/arch/arm/mach-s3c2410/mach-h1940.c	2005-03-11 12:51:50 -08:00
@@ -23,6 +23,7 @@
  *     04-Jan-2005 BJD  Updated uart init call
  *     10-Jan-2005 BJD  Removed include of s3c2410.h
  *     14-Jan-2005 BJD  Added clock init
+ *     10-Mar-2005 LCVR Changed S3C2410_VA to S3C24XX_VA
 */
 
 #include <linux/kernel.h>
@@ -117,7 +118,7 @@
 
 MACHINE_START(H1940, "IPAQ-H1940")
      MAINTAINER("Ben Dooks <ben@fluff.org>")
-     BOOT_MEM(S3C2410_SDRAM_PA, S3C2410_PA_UART, S3C2410_VA_UART)
+     BOOT_MEM(S3C2410_SDRAM_PA, S3C2410_PA_UART, S3C24XX_VA_UART)
      BOOT_PARAMS(S3C2410_SDRAM_PA + 0x100)
      MAPIO(h1940_map_io)
      INITIRQ(h1940_init_irq)
diff -Nru a/arch/arm/mach-s3c2410/mach-n30.c b/arch/arm/mach-s3c2410/mach-n30.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/arm/mach-s3c2410/mach-n30.c	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,158 @@
+/* linux/arch/arm/mach-s3c2410/mach-n30.c
+ *
+ * Copyright (c) 2003-2005 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * Copyright (c) 2005 Christer Weinigel <christer@weinigel.se>
+ *
+ * There is a wiki with more information about the n30 port at
+ * http://handhelds.org/moin/moin.cgi/AcerN30Documentation .
+ *
+ * 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.
+ *
+ * Modifications:
+ *     10-Mar-2005 LCVR Changed S3C2410_VA to S3C24XX_VA
+*/
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/timer.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/kthread.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <asm/hardware.h>
+#include <asm/hardware/iomd.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/mach-types.h>
+
+#include <asm/arch/regs-serial.h>
+#include <asm/arch/regs-gpio.h>
+#include <asm/arch/iic.h>
+
+#include <linux/serial_core.h>
+
+#include "s3c2410.h"
+#include "clock.h"
+#include "devs.h"
+#include "cpu.h"
+
+static struct map_desc n30_iodesc[] __initdata = {
+	/* nothing here yet */
+};
+
+static struct s3c2410_uartcfg n30_uartcfgs[] = {
+	/* Normal serial port */
+	[0] = {
+		.hwport	     = 0,
+		.flags	     = 0,
+		.ucon	     = 0x2c5,
+		.ulcon	     = 0x03,
+		.ufcon	     = 0x51,
+	},
+	/* IR port */
+	[1] = {
+		.hwport	     = 1,
+		.flags	     = 0,
+		.uart_flags  = UPF_CONS_FLOW,
+		.ucon	     = 0x2c5,
+		.ulcon	     = 0x43,
+		.ufcon	     = 0x51,
+	},
+	/* The BlueTooth controller is connected to port 2 */
+	[2] = {
+		.hwport	     = 2,
+		.flags	     = 0,
+		.ucon	     = 0x2c5,
+		.ulcon	     = 0x03,
+		.ufcon	     = 0x51,
+	},
+};
+
+static struct platform_device *n30_devices[] __initdata = {
+	&s3c_device_usb,
+	&s3c_device_lcd,
+	&s3c_device_wdt,
+	&s3c_device_i2c,
+	&s3c_device_iis,
+	&s3c_device_usbgadget,
+};
+
+static struct s3c2410_platform_i2c n30_i2ccfg = {
+	.flags		= 0,
+	.slave_addr	= 0x10,
+	.bus_freq	= 10*1000,
+	.max_freq	= 10*1000,
+};
+
+static struct s3c24xx_board n30_board __initdata = {
+	.devices       = n30_devices,
+	.devices_count = ARRAY_SIZE(n30_devices)
+};
+
+void __init n30_map_io(void)
+{
+	s3c24xx_init_io(n30_iodesc, ARRAY_SIZE(n30_iodesc));
+	s3c24xx_init_clocks(0);
+	s3c24xx_init_uarts(n30_uartcfgs, ARRAY_SIZE(n30_uartcfgs));
+	s3c24xx_set_board(&n30_board);
+}
+
+void __init n30_init_irq(void)
+{
+	s3c24xx_init_irq();
+}
+
+
+static int n30_usbstart_thread(void *unused)
+{
+	/* Turn off suspend on both USB ports, and switch the
+	 * selectable USB port to USB device mode. */
+	writel(readl(S3C2410_MISCCR) & ~0x00003008, S3C2410_MISCCR);
+
+	/* Turn off the D+ pull up for 3 seconds so that the USB host
+	 * at the other end will do a rescan of the USB bus.  */
+	s3c2410_gpio_setpin(S3C2410_GPB3, 0);
+
+	msleep_interruptible(3*HZ);
+
+	s3c2410_gpio_setpin(S3C2410_GPB3, 1);
+
+	return 0;
+}
+
+
+void __init n30_init(void)
+{
+	s3c_device_i2c.dev.platform_data = &n30_i2ccfg;
+
+	kthread_run(n30_usbstart_thread, NULL, "n30_usbstart");
+}
+
+MACHINE_START(N30, "Acer-N30")
+     MAINTAINER("Christer Weinigel <christer@weinigel.se>, Ben Dooks <ben-linux@fluff.org>")
+     BOOT_MEM(S3C2410_SDRAM_PA, S3C2410_PA_UART, S3C24XX_VA_UART)
+     BOOT_PARAMS(S3C2410_SDRAM_PA + 0x100)
+
+	.timer		= &s3c24xx_timer,
+	.init_machine	= n30_init,
+	.init_irq	= n30_init_irq,
+	.map_io		= n30_map_io,
+MACHINE_END
+
+/*
+    Local variables:
+        compile-command: "make ARCH=arm CROSS_COMPILE=/usr/local/arm/3.3.2/bin/arm-linux- -k -C ../../.."
+        c-basic-offset: 8
+    End:
+*/
diff -Nru a/arch/arm/mach-s3c2410/mach-rx3715.c b/arch/arm/mach-s3c2410/mach-rx3715.c
--- a/arch/arm/mach-s3c2410/mach-rx3715.c	2005-03-11 12:51:47 -08:00
+++ b/arch/arm/mach-s3c2410/mach-rx3715.c	2005-03-11 12:51:47 -08:00
@@ -10,10 +10,11 @@
  * published by the Free Software Foundation.
  *
  * Modifications:
- *	16-Sep-2004 BJD Copied from mach-h1940.c
- *	25-Oct-2004 BJD Updates for 2.6.10-rc1
- *	10-Jan-2005 BJD Removed include of s3c2410.h s3c2440.h
- *	14-Jan-2005 BJD Added new clock init
+ *	16-Sep-2004 BJD  Copied from mach-h1940.c
+ *	25-Oct-2004 BJD  Updates for 2.6.10-rc1
+ *	10-Jan-2005 BJD  Removed include of s3c2410.h s3c2440.h
+ *	14-Jan-2005 BJD  Added new clock init
+ *	10-Mar-2005 LCVR Changed S3C2410_VA to S3C24XX_VA
 */
 
 #include <linux/kernel.h>
@@ -48,8 +49,8 @@
 static struct map_desc rx3715_iodesc[] __initdata = {
 	/* dump ISA space somewhere unused */
 
-	{ S3C2410_VA_ISA_WORD, S3C2410_CS3, SZ_16M, MT_DEVICE },
-	{ S3C2410_VA_ISA_BYTE, S3C2410_CS3, SZ_16M, MT_DEVICE },
+	{ S3C24XX_VA_ISA_WORD, S3C2410_CS3, SZ_16M, MT_DEVICE },
+	{ S3C24XX_VA_ISA_BYTE, S3C2410_CS3, SZ_16M, MT_DEVICE },
 };
 
 static struct s3c2410_uartcfg rx3715_uartcfgs[] = {
@@ -114,7 +115,7 @@
 
 MACHINE_START(RX3715, "IPAQ-RX3715")
      MAINTAINER("Ben Dooks <ben@fluff.org>")
-     BOOT_MEM(S3C2410_SDRAM_PA, S3C2410_PA_UART, S3C2410_VA_UART)
+     BOOT_MEM(S3C2410_SDRAM_PA, S3C2410_PA_UART, S3C24XX_VA_UART)
      BOOT_PARAMS(S3C2410_SDRAM_PA + 0x100)
      MAPIO(rx3715_map_io)
      INITIRQ(rx3715_init_irq)
diff -Nru a/arch/arm/mach-s3c2410/mach-smdk2410.c b/arch/arm/mach-s3c2410/mach-smdk2410.c
--- a/arch/arm/mach-s3c2410/mach-smdk2410.c	2005-03-11 12:51:52 -08:00
+++ b/arch/arm/mach-s3c2410/mach-smdk2410.c	2005-03-11 12:51:52 -08:00
@@ -26,6 +26,9 @@
  * @History:
  * derived from linux/arch/arm/mach-s3c2410/mach-bast.c, written by
  * Ben Dooks <ben@simtec.co.uk>
+ *
+ * 10-Mar-2005 LCVR  Changed S3C2410_VA to S3C24XX_VA
+ *
  ***********************************************************************/
 
 #include <linux/kernel.h>
@@ -110,7 +113,7 @@
 MACHINE_START(SMDK2410, "SMDK2410") /* @TODO: request a new identifier and switch
 				    * to SMDK2410 */
      MAINTAINER("Jonas Dietsche")
-     BOOT_MEM(S3C2410_SDRAM_PA, S3C2410_PA_UART, S3C2410_VA_UART)
+     BOOT_MEM(S3C2410_SDRAM_PA, S3C2410_PA_UART, S3C24XX_VA_UART)
      BOOT_PARAMS(S3C2410_SDRAM_PA + 0x100)
      MAPIO(smdk2410_map_io)
      INITIRQ(smdk2410_init_irq)
diff -Nru a/arch/arm/mach-s3c2410/mach-smdk2440.c b/arch/arm/mach-s3c2410/mach-smdk2440.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/arm/mach-s3c2410/mach-smdk2440.c	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,134 @@
+/* linux/arch/arm/mach-s3c2410/mach-smdk2440.c
+ *
+ * Copyright (c) 2004,2005 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * http://www.fluff.org/ben/smdk2440/
+ *
+ * Thanks to Dimity Andric and TomTom for the loan of an SMDK2440.
+ *
+ * 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.
+ *
+ * Modifications:
+ *	01-Nov-2004 BJD   Initial version
+ *	12-Nov-2004 BJD   Updated for release
+ *	04-Jan-2005 BJD   Fixes for pre-release
+ *	22-Feb-2005 BJD   Updated for 2.6.11-rc5 relesa
+ *	10-Mar-2005 LCVR  Replaced S3C2410_VA by S3C24XX_VA
+*/
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/timer.h>
+#include <linux/init.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <asm/hardware.h>
+#include <asm/hardware/iomd.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/mach-types.h>
+
+//#include <asm/debug-ll.h>
+#include <asm/arch/regs-serial.h>
+#include <asm/arch/regs-gpio.h>
+#include <asm/arch/idle.h>
+
+#include "s3c2410.h"
+#include "s3c2440.h"
+#include "clock.h"
+#include "devs.h"
+#include "cpu.h"
+#include "pm.h"
+
+static struct map_desc smdk2440_iodesc[] __initdata = {
+	/* ISA IO Space map (memory space selected by A24) */
+
+	{ S3C24XX_VA_ISA_WORD, S3C2410_CS2, SZ_16M, MT_DEVICE },
+	{ S3C24XX_VA_ISA_BYTE, S3C2410_CS2, SZ_16M, MT_DEVICE },
+};
+
+#define UCON S3C2410_UCON_DEFAULT | S3C2410_UCON_UCLK
+#define ULCON S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB
+#define UFCON S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE
+
+static struct s3c2410_uartcfg smdk2440_uartcfgs[] = {
+	[0] = {
+		.hwport	     = 0,
+		.flags	     = 0,
+		.ucon	     = 0x3c5,
+		.ulcon	     = 0x03,
+		.ufcon	     = 0x51,
+	},
+	[1] = {
+		.hwport	     = 1,
+		.flags	     = 0,
+		.ucon	     = 0x3c5,
+		.ulcon	     = 0x03,
+		.ufcon	     = 0x51,
+	},
+	/* IR port */
+	[2] = {
+		.hwport	     = 2,
+		.flags	     = 0,
+		.ucon	     = 0x3c5,
+		.ulcon	     = 0x43,
+		.ufcon	     = 0x51,
+	}
+};
+
+static struct platform_device *smdk2440_devices[] __initdata = {
+	&s3c_device_usb,
+	&s3c_device_lcd,
+	&s3c_device_wdt,
+	&s3c_device_i2c,
+	&s3c_device_iis,
+};
+
+static struct s3c24xx_board smdk2440_board __initdata = {
+	.devices       = smdk2440_devices,
+	.devices_count = ARRAY_SIZE(smdk2440_devices)
+};
+
+void __init smdk2440_map_io(void)
+{
+	s3c24xx_init_io(smdk2440_iodesc, ARRAY_SIZE(smdk2440_iodesc));
+	s3c24xx_init_clocks(16934400);
+	s3c24xx_init_uarts(smdk2440_uartcfgs, ARRAY_SIZE(smdk2440_uartcfgs));
+	s3c24xx_set_board(&smdk2440_board);
+}
+
+void __init smdk2440_machine_init(void)
+{
+	/* Configure the LEDs (even if we have no LED support)*/
+
+	s3c2410_gpio_cfgpin(S3C2410_GPF4, S3C2410_GPF4_OUTP);
+	s3c2410_gpio_cfgpin(S3C2410_GPF5, S3C2410_GPF5_OUTP);
+	s3c2410_gpio_cfgpin(S3C2410_GPF6, S3C2410_GPF6_OUTP);
+	s3c2410_gpio_cfgpin(S3C2410_GPF7, S3C2410_GPF7_OUTP);
+
+	s3c2410_gpio_setpin(S3C2410_GPF4, 0);
+	s3c2410_gpio_setpin(S3C2410_GPF5, 0);
+	s3c2410_gpio_setpin(S3C2410_GPF6, 0);
+	s3c2410_gpio_setpin(S3C2410_GPF7, 0);
+
+	s3c2410_pm_init();
+}
+
+MACHINE_START(S3C2440, "SMDK2440")
+	MAINTAINER("Ben Dooks <ben@fluff.org>")
+	BOOT_MEM(S3C2410_SDRAM_PA, S3C2410_PA_UART, S3C24XX_VA_UART)
+	BOOT_PARAMS(S3C2410_SDRAM_PA + 0x100)
+
+	.init_irq	= s3c24xx_init_irq,
+	.map_io		= smdk2440_map_io,
+	.init_machine	= smdk2440_machine_init,
+	.timer		= &s3c24xx_timer,
+MACHINE_END
diff -Nru a/arch/arm/mach-s3c2410/mach-vr1000.c b/arch/arm/mach-s3c2410/mach-vr1000.c
--- a/arch/arm/mach-s3c2410/mach-vr1000.c	2005-03-11 12:51:51 -08:00
+++ b/arch/arm/mach-s3c2410/mach-vr1000.c	2005-03-11 12:51:51 -08:00
@@ -24,6 +24,8 @@
  *     14-Jan-2005 BJD  Added clock init
  *     15-Jan-2005 BJD  Add serial port device definition
  *     20-Jan-2005 BJD  Use UPF_IOREMAP for ports
+ *     10-Feb-2005 BJD  Added power-off capability
+ *     10-Mar-2005 LCVR Changed S3C2410_VA to S3C24XX_VA
 */
 
 #include <linux/kernel.h>
@@ -52,8 +54,8 @@
 #include <asm/irq.h>
 #include <asm/mach-types.h>
 
-//#include <asm/debug-ll.h>
 #include <asm/arch/regs-serial.h>
+#include <asm/arch/regs-gpio.h>
 
 #include "clock.h"
 #include "devs.h"
@@ -76,8 +78,8 @@
 static struct map_desc vr1000_iodesc[] __initdata = {
   /* ISA IO areas */
 
-  { S3C2410_VA_ISA_BYTE, PA_CS2(BAST_PA_ISAIO),	   SZ_16M, MT_DEVICE },
-  { S3C2410_VA_ISA_WORD, PA_CS3(BAST_PA_ISAIO),	   SZ_16M, MT_DEVICE },
+  { S3C24XX_VA_ISA_BYTE, PA_CS2(BAST_PA_ISAIO),	   SZ_16M, MT_DEVICE },
+  { S3C24XX_VA_ISA_WORD, PA_CS3(BAST_PA_ISAIO),	   SZ_16M, MT_DEVICE },
 
   /* we could possibly compress the next set down into a set of smaller tables
    * pagetables, but that would mean using an L2 section, and it still means
@@ -269,6 +271,11 @@
 	.clocks_count  = ARRAY_SIZE(vr1000_clocks),
 };
 
+static void vr1000_power_off(void)
+{
+	s3c2410_gpio_cfgpin(S3C2410_GPB9, S3C2410_GPB9_OUTP);
+	s3c2410_gpio_setpin(S3C2410_GPB9, 1);
+}
 
 void __init vr1000_map_io(void)
 {
@@ -285,6 +292,8 @@
 
 	s3c24xx_uclk.parent  = &s3c24xx_clkout1;
 
+	pm_power_off = vr1000_power_off;
+
 	s3c24xx_init_io(vr1000_iodesc, ARRAY_SIZE(vr1000_iodesc));
 	s3c24xx_init_clocks(0);
 	s3c24xx_init_uarts(vr1000_uartcfgs, ARRAY_SIZE(vr1000_uartcfgs));
@@ -299,7 +308,7 @@
 
 MACHINE_START(VR1000, "Thorcom-VR1000")
      MAINTAINER("Ben Dooks <ben@simtec.co.uk>")
-     BOOT_MEM(S3C2410_SDRAM_PA, S3C2410_PA_UART, S3C2410_VA_UART)
+     BOOT_MEM(S3C2410_SDRAM_PA, S3C2410_PA_UART, S3C24XX_VA_UART)
      BOOT_PARAMS(S3C2410_SDRAM_PA + 0x100)
      MAPIO(vr1000_map_io)
      INITIRQ(vr1000_init_irq)
diff -Nru a/arch/arm/mach-s3c2410/pm.c b/arch/arm/mach-s3c2410/pm.c
--- a/arch/arm/mach-s3c2410/pm.c	2005-03-11 12:51:41 -08:00
+++ b/arch/arm/mach-s3c2410/pm.c	2005-03-11 12:51:41 -08:00
@@ -24,6 +24,9 @@
  * Parts based on arch/arm/mach-pxa/pm.c
  *
  * Thanks to Dimitry Andric for debugging
+ *
+ * Modifications:
+ *     10-Mar-2005 LCVR  Changed S3C2410_VA_UART to S3C24XX_VA_UART
 */
 
 #include <linux/config.h>
@@ -144,9 +147,11 @@
 	SAVE_ITEM((va) + S3C2410_UBRDIV)
 
 static struct sleep_save uart_save[] = {
-	SAVE_UART(S3C2410_VA_UART0),
-	SAVE_UART(S3C2410_VA_UART1),
-	SAVE_UART(S3C2410_VA_UART2),
+	SAVE_UART(S3C24XX_VA_UART0),
+	SAVE_UART(S3C24XX_VA_UART1),
+#ifndef CONFIG_CPU_S3C2400
+	SAVE_UART(S3C24XX_VA_UART2),
+#endif
 };
 
 /* debug
diff -Nru a/arch/arm/mach-s3c2410/s3c2410.c b/arch/arm/mach-s3c2410/s3c2410.c
--- a/arch/arm/mach-s3c2410/s3c2410.c	2005-03-11 12:51:46 -08:00
+++ b/arch/arm/mach-s3c2410/s3c2410.c	2005-03-11 12:51:46 -08:00
@@ -17,7 +17,7 @@
  *     21-Aug-2004 BJD  Added new struct s3c2410_board handler
  *     28-Sep-2004 BJD  Updates for new serial port bits
  *     04-Nov-2004 BJD  Updated UART configuration process
- *     10-Jan-2004 BJD  Removed s3c2410_clock_tick_rate
+ *     10-Jan-2005 BJD  Removed s3c2410_clock_tick_rate
 */
 
 #include <linux/kernel.h>
@@ -164,31 +164,32 @@
 void __init s3c2410_init_clocks(int xtal)
 {
 	unsigned long tmp;
+	unsigned long fclk;
+	unsigned long hclk;
+	unsigned long pclk;
 
 	/* now we've got our machine bits initialised, work out what
 	 * clocks we've got */
 
-	s3c24xx_fclk = s3c2410_get_pll(__raw_readl(S3C2410_MPLLCON),
-				       s3c24xx_xtal);
+	fclk = s3c2410_get_pll(__raw_readl(S3C2410_MPLLCON), xtal);
 
 	tmp = __raw_readl(S3C2410_CLKDIVN);
 
 	/* work out clock scalings */
 
-	s3c24xx_hclk = s3c24xx_fclk / ((tmp & S3C2410_CLKDIVN_HDIVN) ? 2 : 1);
-	s3c24xx_pclk = s3c24xx_hclk / ((tmp & S3C2410_CLKDIVN_PDIVN) ? 2 : 1);
+	hclk = fclk / ((tmp & S3C2410_CLKDIVN_HDIVN) ? 2 : 1);
+	pclk = hclk / ((tmp & S3C2410_CLKDIVN_PDIVN) ? 2 : 1);
 
 	/* print brieft summary of clocks, etc */
 
 	printk("S3C2410: core %ld.%03ld MHz, memory %ld.%03ld MHz, peripheral %ld.%03ld MHz\n",
-	       print_mhz(s3c24xx_fclk), print_mhz(s3c24xx_hclk),
-	       print_mhz(s3c24xx_pclk));
+	       print_mhz(fclk), print_mhz(hclk), print_mhz(pclk));
 
 	/* initialise the clocks here, to allow other things like the
 	 * console to use them
 	 */
 
-	s3c24xx_setup_clocks();
+	s3c24xx_setup_clocks(xtal, fclk, hclk, pclk);
 }
 
 int __init s3c2410_init(void)
diff -Nru a/arch/arm/mach-s3c2410/s3c2440.c b/arch/arm/mach-s3c2410/s3c2440.c
--- a/arch/arm/mach-s3c2410/s3c2440.c	2005-03-11 12:51:40 -08:00
+++ b/arch/arm/mach-s3c2410/s3c2440.c	2005-03-11 12:51:40 -08:00
@@ -109,7 +109,6 @@
 	.resource	  = s3c_uart0_resource,
 };
 
-
 static struct platform_device s3c_uart1 = {
 	.name		  = "s3c2440-uart",
 	.id		  = 1,
@@ -149,19 +148,6 @@
 	s3c2440_uart_count = uart;
 }
 
-/* s3c2440 specific clock sources */
-
-static struct clk s3c2440_clk_cam = {
-	.name		= "camera",
-	.enable		= s3c24xx_clkcon_enable,
-	.ctrlbit	= S3C2440_CLKCON_CAMERA
-};
-
-static struct clk s3c2440_clk_ac97 = {
-	.name		= "ac97",
-	.enable		= s3c24xx_clkcon_enable,
-	.ctrlbit	= S3C2440_CLKCON_CAMERA
-};
 
 #ifdef CONFIG_PM
 
@@ -190,7 +176,7 @@
 #define s3c2440_resume  NULL
 #endif
 
-static struct sysdev_class s3c2440_sysclass = {
+struct sysdev_class s3c2440_sysclass = {
 	set_kset_name("s3c2440-core"),
 	.suspend	= s3c2440_suspend,
 	.resume		= s3c2440_resume
@@ -209,19 +195,24 @@
 	/* rename any peripherals used differing from the s3c2410 */
 
 	s3c_device_i2c.name = "s3c2440-i2c";
+
+	/* change irq for watchdog */
+
+	s3c_device_wdt.resource[1].start = IRQ_S3C2440_WDT;
+	s3c_device_wdt.resource[1].end   = IRQ_S3C2440_WDT;
 }
 
 void __init s3c2440_init_clocks(int xtal)
 {
 	unsigned long clkdiv;
 	unsigned long camdiv;
-	int s3c2440_hdiv = 1;
+	unsigned long hclk, fclk, pclk;
+	int hdiv = 1;
 
 	/* now we've got our machine bits initialised, work out what
 	 * clocks we've got */
 
-	s3c24xx_fclk = s3c2410_get_pll(__raw_readl(S3C2410_MPLLCON),
-				       s3c24xx_xtal) * 2;
+	fclk = s3c2410_get_pll(__raw_readl(S3C2410_MPLLCON), xtal) * 2;
 
 	clkdiv = __raw_readl(S3C2410_CLKDIVN);
 	camdiv = __raw_readl(S3C2440_CAMDIVN);
@@ -230,63 +221,60 @@
 
 	switch (clkdiv & S3C2440_CLKDIVN_HDIVN_MASK) {
 	case S3C2440_CLKDIVN_HDIVN_1:
-		s3c2440_hdiv = 1;
+		hdiv = 1;
 		break;
 
 	case S3C2440_CLKDIVN_HDIVN_2:
-		s3c2440_hdiv = 1;
+		hdiv = 1;
 		break;
 
 	case S3C2440_CLKDIVN_HDIVN_4_8:
-		s3c2440_hdiv = (camdiv & S3C2440_CAMDIVN_HCLK4_HALF) ? 8 : 4;
+		hdiv = (camdiv & S3C2440_CAMDIVN_HCLK4_HALF) ? 8 : 4;
 		break;
 
 	case S3C2440_CLKDIVN_HDIVN_3_6:
-		s3c2440_hdiv = (camdiv & S3C2440_CAMDIVN_HCLK3_HALF) ? 6 : 3;
+		hdiv = (camdiv & S3C2440_CAMDIVN_HCLK3_HALF) ? 6 : 3;
 		break;
 	}
 
-	s3c24xx_hclk = s3c24xx_fclk / s3c2440_hdiv;
-	s3c24xx_pclk = s3c24xx_hclk / ((clkdiv & S3C2440_CLKDIVN_PDIVN)? 2:1);
+	hclk = fclk / hdiv;
+	pclk = hclk / ((clkdiv & S3C2440_CLKDIVN_PDIVN)? 2:1);
 
 	/* print brief summary of clocks, etc */
 
 	printk("S3C2440: core %ld.%03ld MHz, memory %ld.%03ld MHz, peripheral %ld.%03ld MHz\n",
-	       print_mhz(s3c24xx_fclk), print_mhz(s3c24xx_hclk),
-	       print_mhz(s3c24xx_pclk));
+	       print_mhz(fclk), print_mhz(hclk), print_mhz(pclk));
 
 	/* initialise the clocks here, to allow other things like the
 	 * console to use them, and to add new ones after the initialisation
 	 */
 
-	s3c24xx_setup_clocks();
-
-	/* add s3c2440 specific clocks */
-
-	s3c2440_clk_cam.parent = clk_get(NULL, "hclk");
-	s3c2440_clk_ac97.parent = clk_get(NULL, "pclk");
+	s3c24xx_setup_clocks(xtal, fclk, hclk, pclk);
+}
 
-	s3c24xx_register_clock(&s3c2440_clk_ac97);
-	s3c24xx_register_clock(&s3c2440_clk_cam);
+/* need to register class before we actually register the device, and
+ * we also need to ensure that it has been initialised before any of the
+ * drivers even try to use it (even if not on an s3c2440 based system)
+ * as a driver which may support both 2410 and 2440 may try and use it.
+*/
 
-	clk_disable(&s3c2440_clk_ac97);
-	clk_disable(&s3c2440_clk_cam);
+int __init s3c2440_core_init(void)
+{
+	return sysdev_class_register(&s3c2440_sysclass);
 }
 
+core_initcall(s3c2440_core_init);
+
 int __init s3c2440_init(void)
 {
 	int ret;
 
 	printk("S3C2440: Initialising architecture\n");
 
-	ret = sysdev_class_register(&s3c2440_sysclass);
-	if (ret == 0)
-		ret = sysdev_register(&s3c2440_sysdev);
-
+	ret = sysdev_register(&s3c2440_sysdev);
 	if (ret != 0)
 		printk(KERN_ERR "failed to register sysdev for s3c2440\n");
-
-	if (ret == 0)
+	else
 		ret = platform_add_devices(s3c24xx_uart_devs, s3c2440_uart_count);
 
 	return ret;
diff -Nru a/arch/arm/mach-s3c2410/time.c b/arch/arm/mach-s3c2410/time.c
--- a/arch/arm/mach-s3c2410/time.c	2005-03-11 12:51:42 -08:00
+++ b/arch/arm/mach-s3c2410/time.c	2005-03-11 12:51:42 -08:00
@@ -1,6 +1,6 @@
 /* linux/arch/arm/mach-s3c2410/time.c
  *
- * Copyright (C) 2003,2004 Simtec Electronics
+ * Copyright (C) 2003-2005 Simtec Electronics
  *	Ben Dooks, <ben@simtec.co.uk>
  *
  * This program is free software; you can redistribute it and/or modify
@@ -23,6 +23,8 @@
 #include <linux/sched.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
+#include <linux/err.h>
+
 #include <asm/system.h>
 #include <asm/leds.h>
 #include <asm/mach-types.h>
@@ -33,6 +35,7 @@
 #include <asm/arch/regs-timer.h>
 #include <asm/arch/regs-irq.h>
 #include <asm/mach/time.h>
+#include <asm/hardware/clock.h>
 
 #include "clock.h"
 
@@ -169,6 +172,9 @@
 		tcfg1 &= ~S3C2410_TCFG1_MUX4_MASK;
 		tcfg1 |= S3C2410_TCFG1_MUX4_TCLK1;
 	} else {
+		unsigned long pclk;
+		struct clk *clk;
+
 		/* for the h1940 (and others), we use the pclk from the core
 		 * to generate the timer values. since values around 50 to
 		 * 70MHz are not values we can directly generate the timer
@@ -180,7 +186,18 @@
 
 		/* this is used as default if no other timer can be found */
 
-		timer_usec_ticks = timer_mask_usec_ticks(6, s3c24xx_pclk);
+		clk = clk_get(NULL, "timers");
+		if (IS_ERR(clk))
+			panic("failed to get clock for system timer");
+
+		clk_use(clk);
+		clk_enable(clk);
+
+		pclk = clk_get_rate(clk);
+
+		/* configure clock tick */
+
+		timer_usec_ticks = timer_mask_usec_ticks(6, pclk);
 
 		tcfg1 &= ~S3C2410_TCFG1_MUX4_MASK;
 		tcfg1 |= S3C2410_TCFG1_MUX4_DIV2;
@@ -188,7 +205,7 @@
 		tcfg0 &= ~S3C2410_TCFG_PRESCALER1_MASK;
 		tcfg0 |= ((6 - 1) / 2) << S3C2410_TCFG_PRESCALER1_SHIFT;
 
-		tcnt = (s3c24xx_pclk / 6) / HZ;
+		tcnt = (pclk / 6) / HZ;
 	}
 
 	/* timers reload after counting zero, so reduce the count by 1 */
diff -Nru a/arch/arm/mach-sa1100/assabet.c b/arch/arm/mach-sa1100/assabet.c
--- a/arch/arm/mach-sa1100/assabet.c	2005-03-11 12:51:40 -08:00
+++ b/arch/arm/mach-sa1100/assabet.c	2005-03-11 12:51:40 -08:00
@@ -259,9 +259,11 @@
 	unsigned long phys = __PREG(GPLR) & PMD_MASK;
 	unsigned long virt = io_p2v(phys);
 	int prot = PMD_TYPE_SECT | PMD_SECT_AP_WRITE | PMD_DOMAIN(DOMAIN_IO);
-	pmd_t pmd;
-	pmd_val(pmd) = phys | prot;
-	set_pmd(pmd_offset(pgd_offset_k(virt), virt), pmd);
+	pmd_t *pmd;
+
+	pmd = pmd_offset(pgd_offset_k(virt), virt);
+	*pmd = __pmd(phys | prot);
+	flush_pmd_entry(pmd);
 }
 
 /*
diff -Nru a/arch/arm/mach-sa1100/collie.c b/arch/arm/mach-sa1100/collie.c
--- a/arch/arm/mach-sa1100/collie.c	2005-03-11 12:51:42 -08:00
+++ b/arch/arm/mach-sa1100/collie.c	2005-03-11 12:51:42 -08:00
@@ -55,7 +55,7 @@
 	.io_out		= COLLIE_SCOOP_IO_OUT,
 };
 
-static struct platform_device colliescoop_device = {
+struct platform_device colliescoop_device = {
 	.name		= "sharp-scoop",
 	.id		= -1,
 	.dev		= {
diff -Nru a/arch/arm/mach-sa1100/neponset.c b/arch/arm/mach-sa1100/neponset.c
--- a/arch/arm/mach-sa1100/neponset.c	2005-03-11 12:51:46 -08:00
+++ b/arch/arm/mach-sa1100/neponset.c	2005-03-11 12:51:46 -08:00
@@ -266,6 +266,7 @@
 
 static struct resource smc91x_resources[] = {
 	[0] = {
+		.name	= "smc91x-regs",
 		.start	= SA1100_CS3_PHYS,
 		.end	= SA1100_CS3_PHYS + 0x01ffffff,
 		.flags	= IORESOURCE_MEM,
@@ -276,6 +277,7 @@
 		.flags	= IORESOURCE_IRQ,
 	},
 	[2] = {
+		.name	= "smc91x-attrib",
 		.start	= SA1100_CS3_PHYS + 0x02000000,
 		.end	= SA1100_CS3_PHYS + 0x03ffffff,
 		.flags	= IORESOURCE_MEM,
diff -Nru a/arch/arm/mm/consistent.c b/arch/arm/mm/consistent.c
--- a/arch/arm/mm/consistent.c	2005-03-11 12:51:50 -08:00
+++ b/arch/arm/mm/consistent.c	2005-03-11 12:51:50 -08:00
@@ -323,7 +323,7 @@
 void dma_free_coherent(struct device *dev, size_t size, void *cpu_addr, dma_addr_t handle)
 {
 	struct vm_region *c;
-	unsigned long flags;
+	unsigned long flags, addr;
 	pte_t *ptep;
 
 	size = PAGE_ALIGN(size);
@@ -342,11 +342,13 @@
 	}
 
 	ptep = consistent_pte + CONSISTENT_OFFSET(c->vm_start);
+	addr = c->vm_start;
 	do {
-		pte_t pte = ptep_get_and_clear(ptep);
+		pte_t pte = ptep_get_and_clear(&init_mm, addr, ptep);
 		unsigned long pfn;
 
 		ptep++;
+		addr += PAGE_SIZE;
 
 		if (!pte_none(pte) && pte_present(pte)) {
 			pfn = pte_pfn(pte);
diff -Nru a/arch/arm/mm/fault-armv.c b/arch/arm/mm/fault-armv.c
--- a/arch/arm/mm/fault-armv.c	2005-03-11 12:51:41 -08:00
+++ b/arch/arm/mm/fault-armv.c	2005-03-11 12:51:41 -08:00
@@ -54,7 +54,7 @@
 	 * fault (ie, is old), we can safely ignore any issues.
 	 */
 	if (pte_present(entry) && pte_val(entry) & shared_pte_mask) {
-		flush_cache_page(vma, address);
+		flush_cache_page(vma, address, pte_pfn(entry));
 		pte_val(entry) &= ~shared_pte_mask;
 		set_pte(pte, entry);
 		flush_tlb_page(vma, address);
@@ -115,7 +115,7 @@
 	if (aliases)
 		adjust_pte(vma, addr);
 	else
-		flush_cache_page(vma, addr);
+		flush_cache_page(vma, addr, page_to_pfn(page));
 }
 
 /*
diff -Nru a/arch/arm/mm/flush.c b/arch/arm/mm/flush.c
--- a/arch/arm/mm/flush.c	2005-03-11 12:51:46 -08:00
+++ b/arch/arm/mm/flush.c	2005-03-11 12:51:46 -08:00
@@ -56,7 +56,7 @@
 		if (!(mpnt->vm_flags & VM_MAYSHARE))
 			continue;
 		offset = (pgoff - mpnt->vm_pgoff) << PAGE_SHIFT;
-		flush_cache_page(mpnt, mpnt->vm_start + offset);
+		flush_cache_page(mpnt, mpnt->vm_start + offset, page_to_pfn(page));
 		if (cache_is_vipt())
 			break;
 	}
diff -Nru a/arch/arm/mm/mm-armv.c b/arch/arm/mm/mm-armv.c
--- a/arch/arm/mm/mm-armv.c	2005-03-11 12:51:47 -08:00
+++ b/arch/arm/mm/mm-armv.c	2005-03-11 12:51:47 -08:00
@@ -252,7 +252,25 @@
 	if (virt & (1 << 20))
 		pmdp++;
 
-	set_pmd(pmdp, __pmd(phys | prot));
+	*pmdp = __pmd(phys | prot);
+	flush_pmd_entry(pmdp);
+}
+
+/*
+ * Create a SUPER SECTION PGD between VIRT and PHYS with protection PROT
+ */
+static inline void
+alloc_init_supersection(unsigned long virt, unsigned long phys, int prot)
+{
+	int i;
+
+	for (i = 0; i < 16; i += 1) {
+		alloc_init_section(virt, phys & SUPERSECTION_MASK,
+				   prot | PMD_SECT_SUPER);
+
+		virt += (PGDIR_SIZE / 2);
+		phys += (PGDIR_SIZE / 2);
+	}
 }
 
 /*
@@ -436,7 +454,8 @@
  * Create the page directory entries and any necessary
  * page tables for the mapping specified by `md'.  We
  * are able to cope here with varying sizes and address
- * offsets, and we take full advantage of sections.
+ * offsets, and we take full advantage of sections and
+ * supersections.
  */
 static void __init create_mapping(struct map_desc *md)
 {
@@ -483,6 +502,30 @@
 		length -= PAGE_SIZE;
 	}
 
+	/* N.B.	ARMv6 supersections are only defined to work with domain 0.
+	 *	Since domain assignments can in fact be arbitrary, the
+	 *	'domain == 0' check below is required to insure that ARMv6
+	 *	supersections are only allocated for domain 0 regardless
+	 *	of the actual domain assignments in use.
+	 */
+	if (cpu_architecture() >= CPU_ARCH_ARMv6 && domain == 0) {
+		/* Align to supersection boundary */
+		while ((virt & ~SUPERSECTION_MASK || (virt + off) &
+			~SUPERSECTION_MASK) && length >= (PGDIR_SIZE / 2)) {
+			alloc_init_section(virt, virt + off, prot_sect);
+
+			virt   += (PGDIR_SIZE / 2);
+			length -= (PGDIR_SIZE / 2);
+		}
+
+		while (length >= SUPERSECTION_SIZE) {
+			alloc_init_supersection(virt, virt + off, prot_sect);
+
+			virt   += SUPERSECTION_SIZE;
+			length -= SUPERSECTION_SIZE;
+		}
+	}
+
 	/*
 	 * A section mapping covers half a "pgdir" entry.
 	 */
@@ -526,8 +569,9 @@
 		if (cpu_arch <= CPU_ARCH_ARMv5)
 			pmdval |= PMD_BIT4;
 		pmd = pmd_offset(pgd + i, i << PGDIR_SHIFT);
-		set_pmd(pmd, __pmd(pmdval));
-		set_pmd(pmd + 1, __pmd(pmdval + (1 << (PGDIR_SHIFT - 1))));
+		pmd[0] = __pmd(pmdval);
+		pmd[1] = __pmd(pmdval + (1 << (PGDIR_SHIFT - 1)));
+		flush_pmd_entry(pmd);
 	}
 }
 
diff -Nru a/arch/arm/tools/mach-types b/arch/arm/tools/mach-types
--- a/arch/arm/tools/mach-types	2005-03-11 12:51:46 -08:00
+++ b/arch/arm/tools/mach-types	2005-03-11 12:51:46 -08:00
@@ -6,7 +6,7 @@
 # To add an entry into this database, please see Documentation/arm/README,
 # or contact rmk@arm.linux.org.uk
 #
-# Last update: Thu Jan 6 00:10:23 2005
+# Last update: Wed Mar 2 11:32:53 2005
 #
 # machine_is_xxx	CONFIG_xxxx		MACH_TYPE_xxx		number
 #
@@ -226,7 +226,7 @@
 pnp1110			SA1100_PNP1110		PNP1110			215
 csb226			ARCH_CSB226		CSB226			216
 arnold			SA1100_ARNOLD		ARNOLD			217
-voiceblue		SA1100_PSIBOARD		PSIBOARD		218
+voiceblue		MACH_VOICEBLUE		VOICEBLUE		218
 jz8028			ARCH_JZ8028		JZ8028			219
 h5400			ARCH_H5400		H5400			220
 forte			SA1100_FORTE		FORTE			221
@@ -381,7 +381,7 @@
 spearhead		ARCH_SPEARHEAD		SPEARHEAD		370
 pantera			ARCH_PANTERA		PANTERA			371
 prayoglite		ARCH_PRAYOGLITE		PRAYOGLITE		372
-gumstik			ARCH_GUMSTIK		GUMSTIK			373
+gumstix			ARCH_GUMSTIK		GUMSTIK			373
 rcube			ARCH_RCUBE		RCUBE			374
 rea_olv			ARCH_REA_OLV		REA_OLV			375
 pxa_iphone		ARCH_PXA_IPHONE		PXA_IPHONE		376
@@ -667,3 +667,44 @@
 manga_ks8695		MACH_MANGA_KS8695	MANGA_KS8695		657
 ajax			MACH_AJAX		AJAX			658
 nec_mp900		MACH_NEC_MP900		NEC_MP900		659
+vvtk1000		MACH_VVTK1000		VVTK1000		661
+kafa			MACH_KAFA		KAFA			662
+vvtk3000		MACH_VVTK3000		VVTK3000		663
+pimx1			MACH_PIMX1		PIMX1			664
+ollie			MACH_OLLIE		OLLIE			665
+skymax			MACH_SKYMAX		SKYMAX			666
+jazz			MACH_JAZZ		JAZZ			667
+tel_t3			MACH_TEL_T3		TEL_T3			668
+aisino_fcr255		MACH_AISINO_FCR255	AISINO_FCR255		669
+btweb			MACH_BTWEB		BTWEB			670
+dbg_lh79520		MACH_DBG_LH79520	DBG_LH79520		671
+cm41xx			MACH_CM41XX		CM41XX			672
+ts72xx			MACH_TS72XX		TS72XX			673
+nggpxa			MACH_NGGPXA		NGGPXA			674
+csb535			MACH_CSB535		CSB535			675
+csb536			MACH_CSB536		CSB536			676
+pxa_trakpod		MACH_PXA_TRAKPOD	PXA_TRAKPOD		677
+praxis			MACH_PRAXIS		PRAXIS			678
+lh75411			MACH_LH75411		LH75411			679
+otom			MACH_OTOM		OTOM			680
+nexcoder_2440		MACH_NEXCODER_2440	NEXCODER_2440		681
+loox410			MACH_LOOX410		LOOX410			682
+westlake		MACH_WESTLAKE		WESTLAKE		683
+nsb			MACH_NSB		NSB			684
+esl_sarva_stn		MACH_ESL_SARVA_STN	ESL_SARVA_STN		685
+esl_sarva_tft		MACH_ESL_SARVA_TFT	ESL_SARVA_TFT		686
+esl_sarva_iad		MACH_ESL_SARVA_IAD	ESL_SARVA_IAD		687
+esl_sarva_acc		MACH_ESL_SARVA_ACC	ESL_SARVA_ACC		688
+typhoon			MACH_TYPHOON		TYPHOON			689
+cnav			MACH_CNAV		CNAV			690
+a730			MACH_A730		A730			691
+netstar			MACH_NETSTAR		NETSTAR			692
+supercon		MACH_PHASEFALE_SUPERCON	PHASEFALE_SUPERCON	693
+shiva1100		MACH_SHIVA1100		SHIVA1100		694
+etexsc			MACH_ETEXSC		ETEXSC			695
+ixdpg465		MACH_IXDPG465		IXDPG465		696
+a9m2410			MACH_A9M2410		A9M2410			697
+a9m2440			MACH_A9M2440		A9M2440			698
+a9m9750			MACH_A9M9750		A9M9750			699
+a9m9360			MACH_A9M9360		A9M9360			700
+unc90			MACH_UNC90		UNC90			701
diff -Nru a/arch/frv/mb93090-mb00/pci-frv.c b/arch/frv/mb93090-mb00/pci-frv.c
--- a/arch/frv/mb93090-mb00/pci-frv.c	2005-03-11 12:51:41 -08:00
+++ b/arch/frv/mb93090-mb00/pci-frv.c	2005-03-11 12:51:41 -08:00
@@ -43,7 +43,7 @@
 	pci_read_config_dword(dev, reg, &check);
 	if ((new ^ check) & ((new & PCI_BASE_ADDRESS_SPACE_IO) ? PCI_BASE_ADDRESS_IO_MASK : PCI_BASE_ADDRESS_MEM_MASK)) {
 		printk(KERN_ERR "PCI: Error while updating region "
-		       "%s/%d (%08x != %08x)\n", dev->slot_name, resource,
+		       "%s/%d (%08x != %08x)\n", pci_name(dev), resource,
 		       new, check);
 	}
 }
@@ -128,7 +128,7 @@
 					continue;
 				pr = pci_find_parent_resource(dev, r);
 				if (!pr || request_resource(pr, r) < 0)
-					printk(KERN_ERR "PCI: Cannot allocate resource region %d of bridge %s\n", idx, dev->slot_name);
+					printk(KERN_ERR "PCI: Cannot allocate resource region %d of bridge %s\n", idx, pci_name(dev));
 			}
 		}
 		pcibios_allocate_bus_resources(&bus->children);
diff -Nru a/arch/frv/mb93090-mb00/pci-vdk.c b/arch/frv/mb93090-mb00/pci-vdk.c
--- a/arch/frv/mb93090-mb00/pci-vdk.c	2005-03-11 12:51:51 -08:00
+++ b/arch/frv/mb93090-mb00/pci-vdk.c	2005-03-11 12:51:51 -08:00
@@ -294,7 +294,7 @@
 	 */
 	int i;
 
-	printk("PCI: Fixing base address flags for device %s\n", d->slot_name);
+	printk("PCI: Fixing base address flags for device %s\n", pci_name(d));
 	for(i=0; i<4; i++)
 		d->resource[i].flags |= PCI_BASE_ADDRESS_SPACE_IO;
 }
@@ -308,7 +308,7 @@
 	 */
 	if ((d->class >> 8) != PCI_CLASS_STORAGE_IDE)
 		return;
-	printk("PCI: IDE base address fixup for %s\n", d->slot_name);
+	printk("PCI: IDE base address fixup for %s\n", pci_name(d));
 	for(i=0; i<4; i++) {
 		struct resource *r = &d->resource[i];
 		if ((r->start & ~0x80) == 0x374) {
@@ -326,7 +326,7 @@
 	 * There exist PCI IDE controllers which have utter garbage
 	 * in first four base registers. Ignore that.
 	 */
-	printk("PCI: IDE base address trash cleared for %s\n", d->slot_name);
+	printk("PCI: IDE base address trash cleared for %s\n", pci_name(d));
 	for(i=0; i<4; i++)
 		d->resource[i].start = d->resource[i].end = d->resource[i].flags = 0;
 }
diff -Nru a/arch/i386/Kconfig b/arch/i386/Kconfig
--- a/arch/i386/Kconfig	2005-03-11 12:51:41 -08:00
+++ b/arch/i386/Kconfig	2005-03-11 12:51:41 -08:00
@@ -183,6 +183,7 @@
 	  - "Winchip-C6" for original IDT Winchip.
 	  - "Winchip-2" for IDT Winchip 2.
 	  - "Winchip-2A" for IDT Winchips with 3dNow! capabilities.
+	  - "MediaGX/Geode" for Cyrix MediaGX aka Geode.
 	  - "CyrixIII/VIA C3" for VIA Cyrix III or VIA C3.
 	  - "VIA C3-2 for VIA C3-2 "Nehemiah" (model 9 and above).
 
@@ -310,6 +311,13 @@
 	  stores for this CPU, which can increase performance of some
 	  operations.
 
+config MGEODE
+	bool "MediaGX/Geode"
+	help
+	  Select this for a Cyrix MediaGX aka Geode chip. Linux and GCC
+          treat this chip as a 586TSC with some extended instructions
+          and alignment reqirements.
+
 config MCYRIXIII
 	bool "CyrixIII/VIA-C3"
 	help
@@ -360,7 +368,7 @@
 	int
 	default "7" if MPENTIUM4 || X86_GENERIC
 	default "4" if X86_ELAN || M486 || M386
-	default "5" if MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCRUSOE || MEFFICEON || MCYRIXIII || MK6 || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || M586 || MVIAC3_2
+	default "5" if MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCRUSOE || MEFFICEON || MCYRIXIII || MK6 || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || M586 || MVIAC3_2 || MGEODE
 	default "6" if MK7 || MK8 || MPENTIUMM
 
 config RWSEM_GENERIC_SPINLOCK
@@ -379,7 +387,7 @@
 
 config X86_PPRO_FENCE
 	bool
-	depends on M686 || M586MMX || M586TSC || M586 || M486 || M386
+	depends on M686 || M586MMX || M586TSC || M586 || M486 || M386 || MGEODE
 	default y
 
 config X86_F00F_BUG
@@ -409,7 +417,7 @@
 
 config X86_ALIGNMENT_16
 	bool
-	depends on MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCYRIXIII || X86_ELAN || MK6 || M586MMX || M586TSC || M586 || M486 || MVIAC3_2
+	depends on MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCYRIXIII || X86_ELAN || MK6 || M586MMX || M586TSC || M586 || M486 || MVIAC3_2 || MGEODE
 	default y
 
 config X86_GOOD_APIC
@@ -434,7 +442,7 @@
 
 config X86_OOSTORE
 	bool
-	depends on (MWINCHIP3D || MWINCHIP2 || MWINCHIPC6) && MTRR
+	depends on (MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MGEODE) && MTRR
 	default y
 
 config HPET_TIMER
@@ -570,7 +578,7 @@
 
 config X86_TSC
 	bool
-	depends on (MWINCHIP3D || MWINCHIP2 || MCRUSOE || MEFFICEON || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || MK8 || MVIAC3_2) && !X86_NUMAQ
+	depends on (MWINCHIP3D || MWINCHIP2 || MCRUSOE || MEFFICEON || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || MK8 || MVIAC3_2 || MGEODE) && !X86_NUMAQ
 	default y
 
 config X86_MCE
@@ -769,6 +777,16 @@
 	depends on NUMA
 	default y
 
+config HAVE_MEMORY_PRESENT
+	bool
+	depends on DISCONTIGMEM
+	default y
+
+config NEED_NODE_MEMMAP_SIZE
+	bool
+	depends on DISCONTIGMEM
+	default y
+
 config HIGHPTE
 	bool "Allocate 3rd-level pagetables from highmem"
 	depends on HIGHMEM4G || HIGHMEM64G
@@ -887,6 +905,23 @@
 	This feature is only enabled for gcc-3.0 and later - earlier compilers
 	generate incorrect output with certain kernel constructs when
 	-mregparm=3 is used.
+
+config SECCOMP
+	bool "Enable seccomp to safely compute untrusted bytecode"
+	depends on PROC_FS
+	default y
+	help
+	  This kernel feature is useful for number crunching applications
+	  that may need to compute untrusted bytecode during their
+	  execution. By using pipes or other transports made available to
+	  the process as file descriptors supporting the read/write
+	  syscalls, it's possible to isolate those applications in
+	  their own address space using seccomp. Once seccomp is
+	  enabled via /proc/<pid>/seccomp, it cannot be disabled
+	  and the task is only allowed to execute a few safe syscalls
+	  defined by each seccomp mode.
+
+	  If unsure, say Y. Only embedded should say N here.
 
 endmenu
 
diff -Nru a/arch/i386/Kconfig.debug b/arch/i386/Kconfig.debug
--- a/arch/i386/Kconfig.debug	2005-03-11 12:51:46 -08:00
+++ b/arch/i386/Kconfig.debug	2005-03-11 12:51:46 -08:00
@@ -38,9 +38,12 @@
 
 	  This option will slow down process creation somewhat.
 
+comment "Page alloc debug is incompatible with Software Suspend on i386"
+	depends on DEBUG_KERNEL && SOFTWARE_SUSPEND
+
 config DEBUG_PAGEALLOC
 	bool "Page alloc debugging"
-	depends on DEBUG_KERNEL
+	depends on DEBUG_KERNEL && !SOFTWARE_SUSPEND
 	help
 	  Unmap pages from the kernel linear mapping after free_pages().
 	  This results in a large slowdown, but helps to find certain types
diff -Nru a/arch/i386/Makefile b/arch/i386/Makefile
--- a/arch/i386/Makefile	2005-03-11 12:51:42 -08:00
+++ b/arch/i386/Makefile	2005-03-11 12:51:42 -08:00
@@ -14,6 +14,8 @@
 # 19990713  Artur Skawina <skawina@geocities.com>
 #           Added '-march' and '-mpreferred-stack-boundary' support
 #
+#           Kianusch Sayah Karadji <kianusch@sk-tech.net>
+#           Added support for GEODE CPU
 
 LDFLAGS		:= -m elf_i386
 OBJCOPYFLAGS	:= -O binary -R .note -R .comment -S
@@ -51,6 +53,9 @@
 
 # AMD Elan support
 cflags-$(CONFIG_X86_ELAN)	+= -march=i486
+
+# MediaGX aka Geode support
+cflags-$(CONFIG_MGEODE)		+= $(call cc-option,-march=pentium-mmx,-march=i586)
 
 # -mregparm=3 works ok on gcc-3.0 and later
 #
diff -Nru a/arch/i386/defconfig b/arch/i386/defconfig
--- a/arch/i386/defconfig	2005-03-11 12:51:47 -08:00
+++ b/arch/i386/defconfig	2005-03-11 12:51:47 -08:00
@@ -802,7 +802,6 @@
 # CONFIG_AGP_AMD is not set
 # CONFIG_AGP_AMD64 is not set
 CONFIG_AGP_INTEL=y
-CONFIG_AGP_INTEL_MCH=m
 # CONFIG_AGP_NVIDIA is not set
 # CONFIG_AGP_SIS is not set
 # CONFIG_AGP_SWORKS is not set
diff -Nru a/arch/i386/kernel/cpu/mtrr/centaur.c b/arch/i386/kernel/cpu/mtrr/centaur.c
--- a/arch/i386/kernel/cpu/mtrr/centaur.c	2005-03-11 12:51:42 -08:00
+++ b/arch/i386/kernel/cpu/mtrr/centaur.c	2005-03-11 12:51:42 -08:00
@@ -86,6 +86,8 @@
 	centaur_mcr[reg].low = low;
 	wrmsr(MSR_IDT_MCR0 + reg, low, high);
 }
+
+#if 0
 /*
  *	Initialise the later (saner) Winchip MCR variant. In this version
  *	the BIOS can pass us the registers it has used (but not their values)
@@ -183,6 +185,7 @@
 
 	set_mtrr_done(&ctxt);
 }
+#endif
 
 static int centaur_validate_add_page(unsigned long base, 
 				     unsigned long size, unsigned int type)
@@ -203,7 +206,7 @@
 
 static struct mtrr_ops centaur_mtrr_ops = {
 	.vendor            = X86_VENDOR_CENTAUR,
-	.init              = centaur_mcr_init,
+//	.init              = centaur_mcr_init,
 	.set               = centaur_set_mcr,
 	.get               = centaur_get_mcr,
 	.get_free_region   = centaur_get_free_region,
diff -Nru a/arch/i386/kernel/cpu/mtrr/cyrix.c b/arch/i386/kernel/cpu/mtrr/cyrix.c
--- a/arch/i386/kernel/cpu/mtrr/cyrix.c	2005-03-11 12:51:46 -08:00
+++ b/arch/i386/kernel/cpu/mtrr/cyrix.c	2005-03-11 12:51:46 -08:00
@@ -218,12 +218,12 @@
 	mtrr_type type;
 } arr_state_t;
 
-arr_state_t arr_state[8] __initdata = {
+static arr_state_t arr_state[8] __initdata = {
 	{0UL, 0UL, 0UL}, {0UL, 0UL, 0UL}, {0UL, 0UL, 0UL}, {0UL, 0UL, 0UL},
 	{0UL, 0UL, 0UL}, {0UL, 0UL, 0UL}, {0UL, 0UL, 0UL}, {0UL, 0UL, 0UL}
 };
 
-unsigned char ccr_state[7] __initdata = { 0, 0, 0, 0, 0, 0, 0 };
+static unsigned char ccr_state[7] __initdata = { 0, 0, 0, 0, 0, 0, 0 };
 
 static void cyrix_set_all(void)
 {
@@ -243,6 +243,7 @@
 	post_set();
 }
 
+#if 0
 /*
  * On Cyrix 6x86(MX) and M II the ARR3 is special: it has connection
  * with the SMM (System Management Mode) mode. So we need the following:
@@ -341,10 +342,11 @@
 	if (ccrc[6])
 		printk(KERN_INFO "mtrr: ARR3 was write protected, unprotected\n");
 }
+#endif
 
 static struct mtrr_ops cyrix_mtrr_ops = {
 	.vendor            = X86_VENDOR_CYRIX,
-	.init              = cyrix_arr_init,
+//	.init              = cyrix_arr_init,
 	.set_all	   = cyrix_set_all,
 	.set               = cyrix_set_arr,
 	.get               = cyrix_get_arr,
diff -Nru a/arch/i386/kernel/cpu/mtrr/generic.c b/arch/i386/kernel/cpu/mtrr/generic.c
--- a/arch/i386/kernel/cpu/mtrr/generic.c	2005-03-11 12:51:47 -08:00
+++ b/arch/i386/kernel/cpu/mtrr/generic.c	2005-03-11 12:51:47 -08:00
@@ -19,8 +19,7 @@
 };
 
 static unsigned long smp_changes_mask;
-struct mtrr_state mtrr_state = {};
-
+static struct mtrr_state mtrr_state = {};
 
 /*  Get the MSR pair relating to a var range  */
 static void __init
@@ -383,7 +382,7 @@
 }
 
 
-int generic_have_wrcomb(void)
+static int generic_have_wrcomb(void)
 {
 	unsigned long config, dummy;
 	rdmsr(MTRRcap_MSR, config, dummy);
diff -Nru a/arch/i386/kernel/cpu/mtrr/main.c b/arch/i386/kernel/cpu/mtrr/main.c
--- a/arch/i386/kernel/cpu/mtrr/main.c	2005-03-11 12:51:41 -08:00
+++ b/arch/i386/kernel/cpu/mtrr/main.c	2005-03-11 12:51:41 -08:00
@@ -57,10 +57,6 @@
 
 struct mtrr_ops * mtrr_if = NULL;
 
-__initdata char *mtrr_if_name[] = {
-    "none", "Intel", "AMD K6", "Cyrix ARR", "Centaur MCR"
-};
-
 static void set_mtrr(unsigned int reg, unsigned long base,
 		     unsigned long size, mtrr_type type);
 
@@ -100,7 +96,7 @@
 }
 
 /*  This function returns the number of variable MTRRs  */
-void __init set_num_var_ranges(void)
+static void __init set_num_var_ranges(void)
 {
 	unsigned long config = 0, dummy;
 
diff -Nru a/arch/i386/kernel/cpu/mtrr/mtrr.h b/arch/i386/kernel/cpu/mtrr/mtrr.h
--- a/arch/i386/kernel/cpu/mtrr/mtrr.h	2005-03-11 12:51:52 -08:00
+++ b/arch/i386/kernel/cpu/mtrr/mtrr.h	2005-03-11 12:51:52 -08:00
@@ -37,7 +37,7 @@
 struct mtrr_ops {
 	u32	vendor;
 	u32	use_intel_if;
-	void	(*init)(void);
+//	void	(*init)(void);
 	void	(*set)(unsigned int reg, unsigned long base,
 		       unsigned long size, mtrr_type type);
 	void	(*set_all)(void);
@@ -57,7 +57,6 @@
 
 extern struct mtrr_ops generic_mtrr_ops;
 
-extern int generic_have_wrcomb(void);
 extern int positive_have_wrcomb(void);
 
 /* library functions for processor-specific routines */
@@ -96,4 +95,3 @@
 void mtrr_state_warn(void);
 char *mtrr_attrib_to_str(int x);
 
-extern char * mtrr_if_name[];
diff -Nru a/arch/i386/kernel/entry.S b/arch/i386/kernel/entry.S
--- a/arch/i386/kernel/entry.S	2005-03-11 12:51:42 -08:00
+++ b/arch/i386/kernel/entry.S	2005-03-11 12:51:42 -08:00
@@ -219,7 +219,8 @@
 	SAVE_ALL
 	GET_THREAD_INFO(%ebp)
 
-	testb $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT),TI_flags(%ebp)
+	/* Note, _TIF_SECCOMP is bit number 8, and so it needs testw and not testb */
+	testw $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SECCOMP),TI_flags(%ebp)
 	jnz syscall_trace_entry
 	cmpl $(nr_syscalls), %eax
 	jae syscall_badsys
@@ -243,7 +244,8 @@
 	SAVE_ALL
 	GET_THREAD_INFO(%ebp)
 					# system call tracing in operation
-	testb $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT),TI_flags(%ebp)
+	/* Note, _TIF_SECCOMP is bit number 8, and so it needs testw and not testb */
+	testw $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SECCOMP),TI_flags(%ebp)
 	jnz syscall_trace_entry
 	cmpl $(nr_syscalls), %eax
 	jae syscall_badsys
diff -Nru a/arch/i386/kernel/i386_ksyms.c b/arch/i386/kernel/i386_ksyms.c
--- a/arch/i386/kernel/i386_ksyms.c	2005-03-11 12:51:52 -08:00
+++ b/arch/i386/kernel/i386_ksyms.c	2005-03-11 12:51:52 -08:00
@@ -97,6 +97,11 @@
 EXPORT_SYMBOL(__get_user_2);
 EXPORT_SYMBOL(__get_user_4);
 
+EXPORT_SYMBOL(__put_user_1);
+EXPORT_SYMBOL(__put_user_2);
+EXPORT_SYMBOL(__put_user_4);
+EXPORT_SYMBOL(__put_user_8);
+
 EXPORT_SYMBOL(strpbrk);
 EXPORT_SYMBOL(strstr);
 
diff -Nru a/arch/i386/kernel/i8259.c b/arch/i386/kernel/i8259.c
--- a/arch/i386/kernel/i8259.c	2005-03-11 12:51:52 -08:00
+++ b/arch/i386/kernel/i8259.c	2005-03-11 12:51:52 -08:00
@@ -58,14 +58,13 @@
 }
 
 static struct hw_interrupt_type i8259A_irq_type = {
-	"XT-PIC",
-	startup_8259A_irq,
-	shutdown_8259A_irq,
-	enable_8259A_irq,
-	disable_8259A_irq,
-	mask_and_ack_8259A,
-	end_8259A_irq,
-	NULL
+	.typename = "XT-PIC",
+	.startup = startup_8259A_irq,
+	.shutdown = shutdown_8259A_irq,
+	.enable = enable_8259A_irq,
+	.disable = disable_8259A_irq,
+	.ack = mask_and_ack_8259A,
+	.end = end_8259A_irq,
 };
 
 /*
diff -Nru a/arch/i386/kernel/numaq.c b/arch/i386/kernel/numaq.c
--- a/arch/i386/kernel/numaq.c	2005-03-11 12:51:47 -08:00
+++ b/arch/i386/kernel/numaq.c	2005-03-11 12:51:47 -08:00
@@ -30,9 +30,7 @@
 #include <linux/module.h>
 #include <linux/nodemask.h>
 #include <asm/numaq.h>
-
-/* These are needed before the pgdat's are created */
-extern long node_start_pfn[], node_end_pfn[];
+#include <asm/topology.h>
 
 #define	MB_TO_PAGES(addr) ((addr) << (20 - PAGE_SHIFT))
 
@@ -59,6 +57,12 @@
 				eq->hi_shrd_mem_start - eq->priv_mem_size);
 			node_end_pfn[node] = MB_TO_PAGES(
 				eq->hi_shrd_mem_start + eq->hi_shrd_mem_size);
+
+			memory_present(node,
+				node_start_pfn[node], node_end_pfn[node]);
+			node_remap_size[node] = node_memmap_size_bytes(node,
+							node_start_pfn[node],
+							node_end_pfn[node]);
 		}
 	}
 }
diff -Nru a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c
--- a/arch/i386/kernel/process.c	2005-03-11 12:51:40 -08:00
+++ b/arch/i386/kernel/process.c	2005-03-11 12:51:40 -08:00
@@ -36,6 +36,7 @@
 #include <linux/module.h>
 #include <linux/kallsyms.h>
 #include <linux/ptrace.h>
+#include <linux/random.h>
 
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
@@ -828,3 +829,9 @@
 	return 0;
 }
 
+unsigned long arch_align_stack(unsigned long sp)
+{
+	if (randomize_va_space)
+		sp -= get_random_int() % 8192;
+	return sp & ~0xf;
+}
diff -Nru a/arch/i386/kernel/ptrace.c b/arch/i386/kernel/ptrace.c
--- a/arch/i386/kernel/ptrace.c	2005-03-11 12:51:42 -08:00
+++ b/arch/i386/kernel/ptrace.c	2005-03-11 12:51:42 -08:00
@@ -15,6 +15,7 @@
 #include <linux/user.h>
 #include <linux/security.h>
 #include <linux/audit.h>
+#include <linux/seccomp.h>
 
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
@@ -678,6 +679,9 @@
 __attribute__((regparm(3)))
 void do_syscall_trace(struct pt_regs *regs, int entryexit)
 {
+	/* do the secure computing check first */
+	secure_computing(regs->orig_eax);
+
 	if (unlikely(current->audit_context)) {
 		if (!entryexit)
 			audit_syscall_entry(current, regs->orig_eax,
diff -Nru a/arch/i386/kernel/scx200.c b/arch/i386/kernel/scx200.c
--- a/arch/i386/kernel/scx200.c	2005-03-11 12:51:51 -08:00
+++ b/arch/i386/kernel/scx200.c	2005-03-11 12:51:51 -08:00
@@ -13,6 +13,9 @@
 
 #include <linux/scx200.h>
 
+/* Verify that the configuration block really is there */
+#define scx200_cb_probe(base) (inw((base) + SCx200_CBA) == (base))
+
 #define NAME "scx200"
 
 MODULE_AUTHOR("Christer Weinigel <wingel@nano-system.com>");
@@ -22,9 +25,13 @@
 unsigned scx200_gpio_base = 0;
 long scx200_gpio_shadow[2];
 
+unsigned scx200_cb_base = 0;
+
 static struct pci_device_id scx200_tbl[] = {
 	{ PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_SCx200_BRIDGE) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_SC1100_BRIDGE) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_SCx200_XBUS)   },
+	{ PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_SC1100_XBUS)   },
 	{ },
 };
 MODULE_DEVICE_TABLE(pci,scx200_tbl);
@@ -45,22 +52,39 @@
 	int bank;
 	unsigned base;
 
-	base = pci_resource_start(pdev, 0);
-	printk(KERN_INFO NAME ": GPIO base 0x%x\n", base);
-
-	if (request_region(base, SCx200_GPIO_SIZE, "NatSemi SCx200 GPIO") == 0) {
-		printk(KERN_ERR NAME ": can't allocate I/O for GPIOs\n");
-		return -EBUSY;
+	if (pdev->device == PCI_DEVICE_ID_NS_SCx200_BRIDGE ||
+	    pdev->device == PCI_DEVICE_ID_NS_SC1100_BRIDGE) {
+		base = pci_resource_start(pdev, 0);
+		printk(KERN_INFO NAME ": GPIO base 0x%x\n", base);
+
+		if (request_region(base, SCx200_GPIO_SIZE, "NatSemi SCx200 GPIO") == 0) {
+			printk(KERN_ERR NAME ": can't allocate I/O for GPIOs\n");
+			return -EBUSY;
+		}
+
+		scx200_gpio_base = base;
+
+		/* read the current values driven on the GPIO signals */
+		for (bank = 0; bank < 2; ++bank)
+			scx200_gpio_shadow[bank] = inl(scx200_gpio_base + 0x10 * bank);
+
+	} else {
+		/* find the base of the Configuration Block */
+		if (scx200_cb_probe(SCx200_CB_BASE_FIXED)) {
+			scx200_cb_base = SCx200_CB_BASE_FIXED;
+		} else {
+			pci_read_config_dword(pdev, SCx200_CBA_SCRATCH, &base);
+			if (scx200_cb_probe(base)) {
+				scx200_cb_base = base;
+			} else {
+				printk(KERN_WARNING NAME ": Configuration Block not found\n");
+				return -ENODEV;
+			}
+		}
+		printk(KERN_INFO NAME ": Configuration Block base 0x%x\n", scx200_cb_base);
 	}
 
-	scx200_gpio_base = base;
-
-	/* read the current values driven on the GPIO signals */
-	for (bank = 0; bank < 2; ++bank)
-		scx200_gpio_shadow[bank] = inl(scx200_gpio_base + 0x10 * bank);
-
 	return 0;
-
 }
 
 u32 scx200_gpio_configure(int index, u32 mask, u32 bits)
@@ -134,6 +158,7 @@
 EXPORT_SYMBOL(scx200_gpio_lock);
 EXPORT_SYMBOL(scx200_gpio_configure);
 EXPORT_SYMBOL(scx200_gpio_dump);
+EXPORT_SYMBOL(scx200_cb_base);
 
 /*
     Local variables:
diff -Nru a/arch/i386/kernel/setup.c b/arch/i386/kernel/setup.c
--- a/arch/i386/kernel/setup.c	2005-03-11 12:51:46 -08:00
+++ b/arch/i386/kernel/setup.c	2005-03-11 12:51:46 -08:00
@@ -40,6 +40,7 @@
 #include <linux/efi.h>
 #include <linux/init.h>
 #include <linux/edd.h>
+#include <linux/nodemask.h>
 #include <video/edid.h>
 #include <asm/e820.h>
 #include <asm/mpspec.h>
@@ -951,8 +952,6 @@
 	return max_low_pfn;
 }
 
-#ifndef CONFIG_DISCONTIGMEM
-
 /*
  * Free all available memory for boot time allocation.  Used
  * as a callback function by efi_memory_walk()
@@ -1026,15 +1025,15 @@
 		reserve_bootmem(addr, PAGE_SIZE);	
 }
 
+#ifndef CONFIG_DISCONTIGMEM
+void __init setup_bootmem_allocator(void);
 static unsigned long __init setup_memory(void)
 {
-	unsigned long bootmap_size, start_pfn, max_low_pfn;
-
 	/*
 	 * partially used pages are not usable - thus
 	 * we are rounding upwards:
 	 */
-	start_pfn = PFN_UP(init_pg_tables_end);
+	min_low_pfn = PFN_UP(init_pg_tables_end);
 
 	find_max_pfn();
 
@@ -1050,10 +1049,43 @@
 #endif
 	printk(KERN_NOTICE "%ldMB LOWMEM available.\n",
 			pages_to_mb(max_low_pfn));
+
+	setup_bootmem_allocator();
+
+	return max_low_pfn;
+}
+
+void __init zone_sizes_init(void)
+{
+	unsigned long zones_size[MAX_NR_ZONES] = {0, 0, 0};
+	unsigned int max_dma, low;
+
+	max_dma = virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT;
+	low = max_low_pfn;
+
+	if (low < max_dma)
+		zones_size[ZONE_DMA] = low;
+	else {
+		zones_size[ZONE_DMA] = max_dma;
+		zones_size[ZONE_NORMAL] = low - max_dma;
+#ifdef CONFIG_HIGHMEM
+		zones_size[ZONE_HIGHMEM] = highend_pfn - low;
+#endif
+	}
+	free_area_init(zones_size);
+}
+#else
+extern unsigned long setup_memory(void);
+extern void zone_sizes_init(void);
+#endif /* !CONFIG_DISCONTIGMEM */
+
+void __init setup_bootmem_allocator(void)
+{
+	unsigned long bootmap_size;
 	/*
 	 * Initialize the boot-time allocator (with low memory only):
 	 */
-	bootmap_size = init_bootmem(start_pfn, max_low_pfn);
+	bootmap_size = init_bootmem(min_low_pfn, max_low_pfn);
 
 	register_bootmem_low_pages(max_low_pfn);
 
@@ -1063,7 +1095,7 @@
 	 * the (very unlikely) case of us accidentally initializing the
 	 * bootmem allocator with an invalid RAM area.
 	 */
-	reserve_bootmem(HIGH_MEMORY, (PFN_PHYS(start_pfn) +
+	reserve_bootmem(HIGH_MEMORY, (PFN_PHYS(min_low_pfn) +
 			 bootmap_size + PAGE_SIZE-1) - (HIGH_MEMORY));
 
 	/*
@@ -1120,11 +1152,25 @@
 		}
 	}
 #endif
-	return max_low_pfn;
 }
-#else
-extern unsigned long setup_memory(void);
-#endif /* !CONFIG_DISCONTIGMEM */
+
+/*
+ * The node 0 pgdat is initialized before all of these because
+ * it's needed for bootmem.  node>0 pgdats have their virtual
+ * space allocated before the pagetables are in place to access
+ * them, so they can't be cleared then.
+ *
+ * This should all compile down to nothing when NUMA is off.
+ */
+void __init remapped_pgdat_init(void)
+{
+	int nid;
+
+	for_each_online_node(nid) {
+		if (nid != 0)
+			memset(NODE_DATA(nid), 0, sizeof(struct pglist_data));
+	}
+}
 
 /*
  * Request address space for all standard RAM and ROM resources
@@ -1432,6 +1478,8 @@
 	smp_alloc_memory(); /* AP processor realmode stacks in low memory*/
 #endif
 	paging_init();
+	remapped_pgdat_init();
+	zone_sizes_init();
 
 	/*
 	 * NOTE: at this point the bootmem allocator is fully available.
diff -Nru a/arch/i386/kernel/signal.c b/arch/i386/kernel/signal.c
--- a/arch/i386/kernel/signal.c	2005-03-11 12:51:43 -08:00
+++ b/arch/i386/kernel/signal.c	2005-03-11 12:51:43 -08:00
@@ -277,6 +277,18 @@
 {
 	int tmp, err = 0;
 
+	/*
+	 * If TF is set due to a debugger (PT_DTRACE), clear the TF
+	 * flag so that register information in the sigcontext is
+	 * correct.
+	 */
+	if (unlikely(regs->eflags & TF_MASK)) {
+		if (likely(current->ptrace & PT_DTRACE)) {
+			current->ptrace &= ~PT_DTRACE;
+			regs->eflags &= ~TF_MASK;
+		}
+	}
+
 	tmp = 0;
 	__asm__("movl %%gs,%0" : "=r"(tmp): "0"(tmp));
 	err |= __put_user(tmp, (unsigned int __user *)&sc->gs);
diff -Nru a/arch/i386/kernel/srat.c b/arch/i386/kernel/srat.c
--- a/arch/i386/kernel/srat.c	2005-03-11 12:51:52 -08:00
+++ b/arch/i386/kernel/srat.c	2005-03-11 12:51:52 -08:00
@@ -30,6 +30,7 @@
 #include <linux/acpi.h>
 #include <linux/nodemask.h>
 #include <asm/srat.h>
+#include <asm/topology.h>
 
 /*
  * proximity macros and definitions
@@ -58,8 +59,6 @@
 static int zholes_size_init;
 static unsigned long zholes_size[MAX_NUMNODES * MAX_NR_ZONES];
 
-extern unsigned long node_start_pfn[], node_end_pfn[];
-
 extern void * boot_ioremap(unsigned long, unsigned long);
 
 /* Identify CPU proximity domains */
@@ -182,6 +181,38 @@
 	}
 }
 
+/*
+ * The SRAT table always lists ascending addresses, so can always
+ * assume that the first "start" address that you see is the real
+ * start of the node, and that the current "end" address is after
+ * the previous one.
+ */
+static __init void node_read_chunk(int nid, struct node_memory_chunk_s *memory_chunk)
+{
+	/*
+	 * Only add present memory as told by the e820.
+	 * There is no guarantee from the SRAT that the memory it
+	 * enumerates is present at boot time because it represents
+	 * *possible* memory hotplug areas the same as normal RAM.
+	 */
+	if (memory_chunk->start_pfn >= max_pfn) {
+		printk (KERN_INFO "Ignoring SRAT pfns: 0x%08lx -> %08lx\n",
+			memory_chunk->start_pfn, memory_chunk->end_pfn);
+		return;
+	}
+	if (memory_chunk->nid != nid)
+		return;
+
+	if (!node_has_online_mem(nid))
+		node_start_pfn[nid] = memory_chunk->start_pfn;
+
+	if (node_start_pfn[nid] > memory_chunk->start_pfn)
+		node_start_pfn[nid] = memory_chunk->start_pfn;
+
+	if (node_end_pfn[nid] < memory_chunk->end_pfn)
+		node_end_pfn[nid] = memory_chunk->end_pfn;
+}
+
 /* Parse the ACPI Static Resource Affinity Table */
 static int __init acpi20_parse_srat(struct acpi_table_srat *sratp)
 {
@@ -262,29 +293,18 @@
 	printk("Number of memory chunks in system = %d\n", num_memory_chunks);
 
 	for (j = 0; j < num_memory_chunks; j++){
+		struct node_memory_chunk_s * chunk = &node_memory_chunk[j];
 		printk("chunk %d nid %d start_pfn %08lx end_pfn %08lx\n",
-		       j, node_memory_chunk[j].nid,
-		       node_memory_chunk[j].start_pfn,
-		       node_memory_chunk[j].end_pfn);
+		       j, chunk->nid, chunk->start_pfn, chunk->end_pfn);
+		node_read_chunk(chunk->nid, chunk);
 	}
  
-	/*calculate node_start_pfn/node_end_pfn arrays*/
 	for_each_online_node(nid) {
-		int been_here_before = 0;
+		unsigned long start = node_start_pfn[nid];
+		unsigned long end = node_end_pfn[nid];
 
-		for (j = 0; j < num_memory_chunks; j++){
-			if (node_memory_chunk[j].nid == nid) {
-				if (been_here_before == 0) {
-					node_start_pfn[nid] = node_memory_chunk[j].start_pfn;
-					node_end_pfn[nid] = node_memory_chunk[j].end_pfn;
-					been_here_before = 1;
-				} else { /* We've found another chunk of memory for the node */
-					if (node_start_pfn[nid] < node_memory_chunk[j].start_pfn) {
-						node_end_pfn[nid] = node_memory_chunk[j].end_pfn;
-					}
-				}
-			}
-		}
+		memory_present(nid, start, end);
+		node_remap_size[nid] = node_memmap_size_bytes(nid, start, end);
 	}
 	return 1;
 out_fail:
diff -Nru a/arch/i386/kernel/time.c b/arch/i386/kernel/time.c
--- a/arch/i386/kernel/time.c	2005-03-11 12:51:46 -08:00
+++ b/arch/i386/kernel/time.c	2005-03-11 12:51:46 -08:00
@@ -89,6 +89,35 @@
 struct timer_opts *cur_timer = &timer_none;
 
 /*
+ * This is a special lock that is owned by the CPU and holds the index
+ * register we are working with.  It is required for NMI access to the
+ * CMOS/RTC registers.  See include/asm-i386/mc146818rtc.h for details.
+ */
+volatile unsigned long cmos_lock = 0;
+EXPORT_SYMBOL(cmos_lock);
+
+/* Routines for accessing the CMOS RAM/RTC. */
+unsigned char rtc_cmos_read(unsigned char addr)
+{
+	unsigned char val;
+	lock_cmos_prefix(addr);
+	outb_p(addr, RTC_PORT(0));
+	val = inb_p(RTC_PORT(1));
+	lock_cmos_suffix(addr);
+	return val;
+}
+EXPORT_SYMBOL(rtc_cmos_read);
+
+void rtc_cmos_write(unsigned char val, unsigned char addr)
+{
+	lock_cmos_prefix(addr);
+	outb_p(addr, RTC_PORT(0));
+	outb_p(val, RTC_PORT(1));
+	lock_cmos_suffix(addr);
+}
+EXPORT_SYMBOL(rtc_cmos_write);
+
+/*
  * This version of gettimeofday has microsecond resolution
  * and better than microsecond precision on fast x86 machines with TSC.
  */
@@ -250,16 +279,12 @@
 			>= USEC_AFTER - ((unsigned) TICK_SIZE) / 2 &&
 	    (xtime.tv_nsec / 1000)
 			<= USEC_BEFORE + ((unsigned) TICK_SIZE) / 2) {
-		/* horrible...FIXME */
+	        last_rtc_update = xtime.tv_sec;
 		if (efi_enabled) {
-	 		if (efi_set_rtc_mmss(xtime.tv_sec) == 0)
-				last_rtc_update = xtime.tv_sec;
-			else
-				last_rtc_update = xtime.tv_sec - 600;
-		} else if (set_rtc_mmss(xtime.tv_sec) == 0)
-			last_rtc_update = xtime.tv_sec;
-		else
-			last_rtc_update = xtime.tv_sec - 600; /* do it again in 60 s */
+		    if (efi_set_rtc_mmss(xtime.tv_sec))
+			last_rtc_update -= 600;
+		} else if (set_rtc_mmss(xtime.tv_sec))
+			last_rtc_update -= 600;
 	}
 
 	if (MCA_bus) {
diff -Nru a/arch/i386/kernel/time_hpet.c b/arch/i386/kernel/time_hpet.c
--- a/arch/i386/kernel/time_hpet.c	2005-03-11 12:51:41 -08:00
+++ b/arch/i386/kernel/time_hpet.c	2005-03-11 12:51:41 -08:00
@@ -121,11 +121,16 @@
 	id = hpet_readl(HPET_ID);
 
 	/*
-	 * We are checking for value '1' or more in number field.
-	 * So, we are OK with HPET_EMULATE_RTC part too, where we need
-	 * to have atleast 2 timers.
+	 * We are checking for value '1' or more in number field if
+	 * CONFIG_HPET_EMULATE_RTC is set because we will need an
+	 * additional timer for RTC emulation.
+	 * However, we can do with one timer otherwise using the
+	 * the single HPET timer for system time.
 	 */
-	if (!(id & HPET_ID_NUMBER) ||
+	if (
+#ifdef CONFIG_HPET_EMULATE_RTC
+		!(id & HPET_ID_NUMBER) ||
+#endif
 	    !(id & HPET_ID_LEGSUP))
 		return -1;
 
diff -Nru a/arch/i386/lib/Makefile b/arch/i386/lib/Makefile
--- a/arch/i386/lib/Makefile	2005-03-11 12:51:52 -08:00
+++ b/arch/i386/lib/Makefile	2005-03-11 12:51:52 -08:00
@@ -3,7 +3,7 @@
 #
 
 
-lib-y = checksum.o delay.o usercopy.o getuser.o memcpy.o strstr.o \
+lib-y = checksum.o delay.o usercopy.o getuser.o putuser.o memcpy.o strstr.o \
 	bitops.o
 
 lib-$(CONFIG_X86_USE_3DNOW) += mmx.o
diff -Nru a/arch/i386/lib/putuser.S b/arch/i386/lib/putuser.S
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/i386/lib/putuser.S	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,87 @@
+/*
+ * __put_user functions.
+ *
+ * (C) Copyright 2005 Linus Torvalds
+ *
+ * These functions have a non-standard call interface
+ * to make them more efficient, especially as they
+ * return an error value in addition to the "real"
+ * return value.
+ */
+#include <asm/thread_info.h>
+
+
+/*
+ * __put_user_X
+ *
+ * Inputs:	%eax[:%edx] contains the data
+ *		%ecx contains the address
+ *
+ * Outputs:	%eax is error code (0 or -EFAULT)
+ *
+ * These functions should not modify any other registers,
+ * as they get called from within inline assembly.
+ */
+
+#define ENTER	pushl %ebx ; GET_THREAD_INFO(%ebx)
+#define EXIT	popl %ebx ; ret
+
+.text
+.align 4
+.globl __put_user_1
+__put_user_1:
+	ENTER
+	cmpl TI_addr_limit(%ebx),%ecx
+	jae bad_put_user
+1:	movb %al,(%ecx)
+	xorl %eax,%eax
+	EXIT
+
+.align 4
+.globl __put_user_2
+__put_user_2:
+	ENTER
+	movl TI_addr_limit(%ebx),%ebx
+	subl $1,%ebx
+	cmpl %ebx,%ecx
+	jae bad_put_user
+2:	movw %ax,(%ecx)
+	xorl %eax,%eax
+	EXIT
+
+.align 4
+.globl __put_user_4
+__put_user_4:
+	ENTER
+	movl TI_addr_limit(%ebx),%ebx
+	subl $3,%ebx
+	cmpl %ebx,%ecx
+	jae bad_put_user
+3:	movl %eax,(%ecx)
+	xorl %eax,%eax
+	EXIT
+
+.align 4
+.globl __put_user_8
+__put_user_8:
+	ENTER
+	movl TI_addr_limit(%ebx),%ebx
+	subl $7,%ebx
+	cmpl %ebx,%ecx
+	jae bad_put_user
+4:	movl %eax,(%ecx)
+5:	movl %edx,4(%ecx)
+	xorl %eax,%eax
+	EXIT
+
+bad_put_user:
+	movl $-14,%eax
+	EXIT
+
+.section __ex_table,"a"
+	.long 1b,bad_put_user
+	.long 2b,bad_put_user
+	.long 3b,bad_put_user
+	.long 4b,bad_put_user
+	.long 5b,bad_put_user
+.previous
diff -Nru a/arch/i386/mach-voyager/voyager_smp.c b/arch/i386/mach-voyager/voyager_smp.c
--- a/arch/i386/mach-voyager/voyager_smp.c	2005-03-11 12:51:42 -08:00
+++ b/arch/i386/mach-voyager/voyager_smp.c	2005-03-11 12:51:42 -08:00
@@ -210,14 +210,14 @@
  * 8259 IRQs except that masks and things must be kept per processor
  */
 static struct hw_interrupt_type vic_irq_type = {
-	"VIC-level",
-	startup_vic_irq,	/* startup */
-	disable_vic_irq,	/* shutdown */
-	enable_vic_irq,		/* enable */
-	disable_vic_irq,	/* disable */
-	before_handle_vic_irq,	/* ack */
-	after_handle_vic_irq,	/* end */
-	set_vic_irq_affinity,	/* affinity */
+	.typename = "VIC-level",
+	.startup = startup_vic_irq,
+	.shutdown = disable_vic_irq,
+	.enable = enable_vic_irq,
+	.disable = disable_vic_irq,
+	.ack = before_handle_vic_irq,
+	.end = after_handle_vic_irq,
+	.set_affinity = set_vic_irq_affinity,
 };
 
 /* used to count up as CPUs are brought on line (starts at 0) */
diff -Nru a/arch/i386/mm/discontig.c b/arch/i386/mm/discontig.c
--- a/arch/i386/mm/discontig.c	2005-03-11 12:51:46 -08:00
+++ b/arch/i386/mm/discontig.c	2005-03-11 12:51:46 -08:00
@@ -60,6 +60,32 @@
  */
 s8 physnode_map[MAX_ELEMENTS] = { [0 ... (MAX_ELEMENTS - 1)] = -1};
 
+void memory_present(int nid, unsigned long start, unsigned long end)
+{
+	unsigned long pfn;
+
+	printk(KERN_INFO "Node: %d, start_pfn: %ld, end_pfn: %ld\n",
+			nid, start, end);
+	printk(KERN_DEBUG "  Setting physnode_map array to node %d for pfns:\n", nid);
+	printk(KERN_DEBUG "  ");
+	for (pfn = start; pfn < end; pfn += PAGES_PER_ELEMENT) {
+		physnode_map[pfn / PAGES_PER_ELEMENT] = nid;
+		printk("%ld ", pfn);
+	}
+	printk("\n");
+}
+
+unsigned long node_memmap_size_bytes(int nid, unsigned long start_pfn,
+					      unsigned long end_pfn)
+{
+	unsigned long nr_pages = end_pfn - start_pfn;
+
+	if (!nr_pages)
+		return 0;
+
+	return (nr_pages + 1) * sizeof(struct page);
+}
+
 unsigned long node_start_pfn[MAX_NUMNODES];
 unsigned long node_end_pfn[MAX_NUMNODES];
 
@@ -128,52 +154,11 @@
  */
 static void __init allocate_pgdat(int nid)
 {
-	if (nid)
+	if (nid && node_has_online_mem(nid))
 		NODE_DATA(nid) = (pg_data_t *)node_remap_start_vaddr[nid];
 	else {
 		NODE_DATA(nid) = (pg_data_t *)(__va(min_low_pfn << PAGE_SHIFT));
 		min_low_pfn += PFN_UP(sizeof(pg_data_t));
-		memset(NODE_DATA(nid), 0, sizeof(pg_data_t));
-	}
-}
-
-/*
- * Register fully available low RAM pages with the bootmem allocator.
- */
-static void __init register_bootmem_low_pages(unsigned long system_max_low_pfn)
-{
-	int i;
-
-	for (i = 0; i < e820.nr_map; i++) {
-		unsigned long curr_pfn, last_pfn, size;
-		/*
-		 * Reserve usable low memory
-		 */
-		if (e820.map[i].type != E820_RAM)
-			continue;
-		/*
-		 * We are rounding up the start address of usable memory:
-		 */
-		curr_pfn = PFN_UP(e820.map[i].addr);
-		if (curr_pfn >= system_max_low_pfn)
-			continue;
-		/*
-		 * ... and at the end of the usable range downwards:
-		 */
-		last_pfn = PFN_DOWN(e820.map[i].addr + e820.map[i].size);
-
-		if (last_pfn > system_max_low_pfn)
-			last_pfn = system_max_low_pfn;
-
-		/*
-		 * .. finally, did all the rounding and playing
-		 * around just make the area go away?
-		 */
-		if (last_pfn <= curr_pfn)
-			continue;
-
-		size = last_pfn - curr_pfn;
-		free_bootmem_node(NODE_DATA(0), PFN_PHYS(curr_pfn), PFN_PHYS(size));
 	}
 }
 
@@ -203,9 +188,21 @@
 	for_each_online_node(nid) {
 		if (nid == 0)
 			continue;
-		/* calculate the size of the mem_map needed in bytes */
-		size = (node_end_pfn[nid] - node_start_pfn[nid] + 1) 
-			* sizeof(struct page) + sizeof(pg_data_t);
+		if (!node_remap_size[nid])
+			continue;
+
+		/*
+		 * The acpi/srat node info can show hot-add memroy zones
+		 * where memory could be added but not currently present.
+		 */
+		if (node_start_pfn[nid] > max_pfn)
+			continue;
+		if (node_end_pfn[nid] > max_pfn)
+			node_end_pfn[nid] = max_pfn;
+
+		/* ensure the remap includes space for the pgdat. */
+		size = node_remap_size[nid] + sizeof(pg_data_t);
+
 		/* convert size to large (pmd size) pages, rounding up */
 		size = (size + LARGE_PAGE_BYTES - 1) / LARGE_PAGE_BYTES;
 		/* now the roundup is correct, convert to PAGE_SIZE pages */
@@ -225,22 +222,12 @@
 	return reserve_pages;
 }
 
-/*
- * workaround for Dell systems that neglect to reserve EBDA
- */
-static void __init reserve_ebda_region_node(void)
-{
-	unsigned int addr;
-	addr = get_bios_ebda();
-	if (addr)
-		reserve_bootmem_node(NODE_DATA(0), addr, PAGE_SIZE);
-}
-
+extern void setup_bootmem_allocator(void);
 unsigned long __init setup_memory(void)
 {
 	int nid;
-	unsigned long bootmap_size, system_start_pfn, system_max_low_pfn;
-	unsigned long reserve_pages, pfn;
+	unsigned long system_start_pfn, system_max_low_pfn;
+	unsigned long reserve_pages;
 
 	/*
 	 * When mapping a NUMA machine we allocate the node_mem_map arrays
@@ -249,28 +236,14 @@
 	 * this space and use it to adjust the boundry between ZONE_NORMAL
 	 * and ZONE_HIGHMEM.
 	 */
+	find_max_pfn();
 	get_memcfg_numa();
 
-	/* Fill in the physnode_map */
-	for_each_online_node(nid) {
-		printk("Node: %d, start_pfn: %ld, end_pfn: %ld\n",
-				nid, node_start_pfn[nid], node_end_pfn[nid]);
-		printk("  Setting physnode_map array to node %d for pfns:\n  ",
-				nid);
-		for (pfn = node_start_pfn[nid]; pfn < node_end_pfn[nid];
-	       				pfn += PAGES_PER_ELEMENT) {
-			physnode_map[pfn / PAGES_PER_ELEMENT] = nid;
-			printk("%ld ", pfn);
-		}
-		printk("\n");
-	}
-
 	reserve_pages = calculate_numa_remap_pages();
 
 	/* partially used pages are not usable - thus round upwards */
 	system_start_pfn = min_low_pfn = PFN_UP(init_pg_tables_end);
 
-	find_max_pfn();
 	system_max_low_pfn = max_low_pfn = find_max_low_pfn() - reserve_pages;
 	printk("reserve_pages = %ld find_max_low_pfn() ~ %ld\n",
 			reserve_pages, max_low_pfn + reserve_pages);
@@ -304,70 +277,10 @@
 	for_each_online_node(nid)
 		find_max_pfn_node(nid);
 
+	memset(NODE_DATA(0), 0, sizeof(struct pglist_data));
 	NODE_DATA(0)->bdata = &node0_bdata;
-
-	/*
-	 * Initialize the boot-time allocator (with low memory only):
-	 */
-	bootmap_size = init_bootmem_node(NODE_DATA(0), min_low_pfn, 0, system_max_low_pfn);
-
-	register_bootmem_low_pages(system_max_low_pfn);
-
-	/*
-	 * Reserve the bootmem bitmap itself as well. We do this in two
-	 * steps (first step was init_bootmem()) because this catches
-	 * the (very unlikely) case of us accidentally initializing the
-	 * bootmem allocator with an invalid RAM area.
-	 */
-	reserve_bootmem_node(NODE_DATA(0), HIGH_MEMORY, (PFN_PHYS(min_low_pfn) +
-		 bootmap_size + PAGE_SIZE-1) - (HIGH_MEMORY));
-
-	/*
-	 * reserve physical page 0 - it's a special BIOS page on many boxes,
-	 * enabling clean reboots, SMP operation, laptop functions.
-	 */
-	reserve_bootmem_node(NODE_DATA(0), 0, PAGE_SIZE);
-
-	/*
-	 * But first pinch a few for the stack/trampoline stuff
-	 * FIXME: Don't need the extra page at 4K, but need to fix
-	 * trampoline before removing it. (see the GDT stuff)
-	 */
-	reserve_bootmem_node(NODE_DATA(0), PAGE_SIZE, PAGE_SIZE);
-
-	/* reserve EBDA region, it's a 4K region */
-	reserve_ebda_region_node();
-
-#ifdef CONFIG_ACPI_SLEEP
-	/*
-	 * Reserve low memory region for sleep support.
-	 */
-	acpi_reserve_bootmem();
-#endif
-
-	/*
-	 * Find and reserve possible boot-time SMP configuration:
-	 */
-	find_smp_config();
-
-#ifdef CONFIG_BLK_DEV_INITRD
-	if (LOADER_TYPE && INITRD_START) {
-		if (INITRD_START + INITRD_SIZE <= (system_max_low_pfn << PAGE_SHIFT)) {
-			reserve_bootmem_node(NODE_DATA(0), INITRD_START, INITRD_SIZE);
-			initrd_start =
-				INITRD_START ? INITRD_START + PAGE_OFFSET : 0;
-			initrd_end = initrd_start+INITRD_SIZE;
-		}
-		else {
-			printk(KERN_ERR "initrd extends beyond end of memory "
-			    "(0x%08lx > 0x%08lx)\ndisabling initrd\n",
-			    INITRD_START + INITRD_SIZE,
-			    system_max_low_pfn << PAGE_SHIFT);
-			initrd_start = 0;
-		}
-	}
-#endif
-	return system_max_low_pfn;
+	setup_bootmem_allocator();
+	return max_low_pfn;
 }
 
 void __init zone_sizes_init(void)
@@ -382,8 +295,6 @@
 	for (nid = MAX_NUMNODES - 1; nid >= 0; nid--) {
 		if (!node_online(nid))
 			continue;
-		if (nid)
-			memset(NODE_DATA(nid), 0, sizeof(pg_data_t));
 		NODE_DATA(nid)->pgdat_next = pgdat_list;
 		pgdat_list = NODE_DATA(nid);
 	}
@@ -399,24 +310,27 @@
 
 		max_dma = virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT;
 
-		if (start > low) {
+		if (node_has_online_mem(nid)){
+			if (start > low) {
 #ifdef CONFIG_HIGHMEM
-			BUG_ON(start > high);
-			zones_size[ZONE_HIGHMEM] = high - start;
+				BUG_ON(start > high);
+				zones_size[ZONE_HIGHMEM] = high - start;
 #endif
-		} else {
-			if (low < max_dma)
-				zones_size[ZONE_DMA] = low;
-			else {
-				BUG_ON(max_dma > low);
-				BUG_ON(low > high);
-				zones_size[ZONE_DMA] = max_dma;
-				zones_size[ZONE_NORMAL] = low - max_dma;
+			} else {
+				if (low < max_dma)
+					zones_size[ZONE_DMA] = low;
+				else {
+					BUG_ON(max_dma > low);
+					BUG_ON(low > high);
+					zones_size[ZONE_DMA] = max_dma;
+					zones_size[ZONE_NORMAL] = low - max_dma;
 #ifdef CONFIG_HIGHMEM
-				zones_size[ZONE_HIGHMEM] = high - low;
+					zones_size[ZONE_HIGHMEM] = high - low;
 #endif
+				}
 			}
 		}
+
 		zholes_size = get_zholes_size(nid);
 		/*
 		 * We let the lmem_map for node 0 be allocated from the
@@ -464,14 +378,5 @@
 		}
 	}
 	totalram_pages += totalhigh_pages;
-#endif
-}
-
-void __init set_max_mapnr_init(void)
-{
-#ifdef CONFIG_HIGHMEM
-	num_physpages = highend_pfn;
-#else
-	num_physpages = max_low_pfn;
 #endif
 }
diff -Nru a/arch/i386/mm/highmem.c b/arch/i386/mm/highmem.c
--- a/arch/i386/mm/highmem.c	2005-03-11 12:51:46 -08:00
+++ b/arch/i386/mm/highmem.c	2005-03-11 12:51:46 -08:00
@@ -66,7 +66,7 @@
 	 * force other mappings to Oops if they'll try to access
 	 * this pte without first remap it
 	 */
-	pte_clear(kmap_pte-idx);
+	pte_clear(&init_mm, vaddr, kmap_pte-idx);
 	__flush_tlb_one(vaddr);
 #endif
 
diff -Nru a/arch/i386/mm/hugetlbpage.c b/arch/i386/mm/hugetlbpage.c
--- a/arch/i386/mm/hugetlbpage.c	2005-03-11 12:51:51 -08:00
+++ b/arch/i386/mm/hugetlbpage.c	2005-03-11 12:51:51 -08:00
@@ -216,7 +216,7 @@
 	BUG_ON(end & (HPAGE_SIZE - 1));
 
 	for (address = start; address < end; address += HPAGE_SIZE) {
-		pte = ptep_get_and_clear(huge_pte_offset(mm, address));
+		pte = ptep_get_and_clear(mm, address, huge_pte_offset(mm, address));
 		if (pte_none(pte))
 			continue;
 		page = pte_page(pte);
diff -Nru a/arch/i386/mm/init.c b/arch/i386/mm/init.c
--- a/arch/i386/mm/init.c	2005-03-11 12:51:48 -08:00
+++ b/arch/i386/mm/init.c	2005-03-11 12:51:48 -08:00
@@ -394,31 +394,6 @@
 	flush_tlb_all();
 }
 
-#ifndef CONFIG_DISCONTIGMEM
-void __init zone_sizes_init(void)
-{
-	unsigned long zones_size[MAX_NR_ZONES] = {0, 0, 0};
-	unsigned int max_dma, high, low;
-	
-	max_dma = virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT;
-	low = max_low_pfn;
-	high = highend_pfn;
-	
-	if (low < max_dma)
-		zones_size[ZONE_DMA] = low;
-	else {
-		zones_size[ZONE_DMA] = max_dma;
-		zones_size[ZONE_NORMAL] = low - max_dma;
-#ifdef CONFIG_HIGHMEM
-		zones_size[ZONE_HIGHMEM] = high - low;
-#endif
-	}
-	free_area_init(zones_size);	
-}
-#else
-extern void zone_sizes_init(void);
-#endif /* !CONFIG_DISCONTIGMEM */
-
 static int disable_nx __initdata = 0;
 u64 __supported_pte_mask = ~_PAGE_NX;
 
@@ -519,7 +494,6 @@
 	__flush_tlb_all();
 
 	kmap_init();
-	zone_sizes_init();
 }
 
 /*
@@ -548,20 +522,17 @@
 	}
 }
 
-#ifndef CONFIG_DISCONTIGMEM
 static void __init set_max_mapnr_init(void)
 {
 #ifdef CONFIG_HIGHMEM
-	max_mapnr = num_physpages = highend_pfn;
+	num_physpages = highend_pfn;
 #else
-	max_mapnr = num_physpages = max_low_pfn;
+	num_physpages = max_low_pfn;
+#endif
+#ifndef CONFIG_DISCONTIGMEM
+	max_mapnr = num_physpages;
 #endif
 }
-#define __free_all_bootmem() free_all_bootmem()
-#else
-#define __free_all_bootmem() free_all_bootmem_node(NODE_DATA(0))
-extern void set_max_mapnr_init(void);
-#endif /* !CONFIG_DISCONTIGMEM */
 
 static struct kcore_list kcore_mem, kcore_vmalloc; 
 
@@ -592,13 +563,13 @@
 	set_max_mapnr_init();
 
 #ifdef CONFIG_HIGHMEM
-	high_memory = (void *) __va(highstart_pfn * PAGE_SIZE);
+	high_memory = (void *) __va(highstart_pfn * PAGE_SIZE - 1) + 1;
 #else
-	high_memory = (void *) __va(max_low_pfn * PAGE_SIZE);
+	high_memory = (void *) __va(max_low_pfn * PAGE_SIZE - 1) + 1;
 #endif
 
 	/* this will put all low memory onto the freelists */
-	totalram_pages += __free_all_bootmem();
+	totalram_pages += free_all_bootmem();
 
 	reservedpages = 0;
 	for (tmp = 0; tmp < max_low_pfn; tmp++)
diff -Nru a/arch/i386/mm/ioremap.c b/arch/i386/mm/ioremap.c
--- a/arch/i386/mm/ioremap.c	2005-03-11 12:51:42 -08:00
+++ b/arch/i386/mm/ioremap.c	2005-03-11 12:51:42 -08:00
@@ -17,6 +17,9 @@
 #include <asm/tlbflush.h>
 #include <asm/pgtable.h>
 
+#define ISA_START_ADDRESS	0xa0000
+#define ISA_END_ADDRESS		0x100000
+
 static inline void remap_area_pte(pte_t * pte, unsigned long address, unsigned long size,
 	unsigned long phys_addr, unsigned long flags)
 {
@@ -129,7 +132,7 @@
 	/*
 	 * Don't remap the low PCI/ISA area, it's always mapped..
 	 */
-	if (phys_addr >= 0xA0000 && last_addr < 0x100000)
+	if (phys_addr >= ISA_START_ADDRESS && last_addr < ISA_END_ADDRESS)
 		return (void __iomem *) phys_to_virt(phys_addr);
 
 	/*
@@ -230,7 +233,17 @@
 {
 	struct vm_struct *p;
 	if ((void __force *) addr <= high_memory) 
-		return; 
+		return;
+
+	/*
+	 * __ioremap special-cases the PCI/ISA range by not instantiating a
+	 * vm_area and by simply returning an address into the kernel mapping
+	 * of ISA space.   So handle that here.
+	 */
+	if (addr >= phys_to_virt(ISA_START_ADDRESS) &&
+			addr < phys_to_virt(ISA_END_ADDRESS))
+		return;
+
 	p = remove_vm_area((void *) (PAGE_MASK & (unsigned long __force) addr));
 	if (!p) { 
 		printk("__iounmap: bad address %p\n", addr);
@@ -240,8 +253,8 @@
 	if ((p->flags >> 20) && p->phys_addr < virt_to_phys(high_memory) - 1) {
 		/* p->size includes the guard page, but cpa doesn't like that */
 		change_page_attr(virt_to_page(__va(p->phys_addr)),
-				 (p->size - PAGE_SIZE) >> PAGE_SHIFT,
-				 PAGE_KERNEL); 				 
+				 p->size >> PAGE_SHIFT,
+				 PAGE_KERNEL);
 		global_flush_tlb();
 	} 
 	kfree(p); 
@@ -261,7 +274,7 @@
 	/*
 	 * Don't remap the low PCI/ISA area, it's always mapped..
 	 */
-	if (phys_addr >= 0xA0000 && last_addr < 0x100000)
+	if (phys_addr >= ISA_START_ADDRESS && last_addr < ISA_END_ADDRESS)
 		return phys_to_virt(phys_addr);
 
 	/*
diff -Nru a/arch/i386/mm/mmap.c b/arch/i386/mm/mmap.c
--- a/arch/i386/mm/mmap.c	2005-03-11 12:51:43 -08:00
+++ b/arch/i386/mm/mmap.c	2005-03-11 12:51:43 -08:00
@@ -26,6 +26,7 @@
 
 #include <linux/personality.h>
 #include <linux/mm.h>
+#include <linux/random.h>
 
 /*
  * Top of mmap area (just below the process stack).
@@ -38,13 +39,17 @@
 static inline unsigned long mmap_base(struct mm_struct *mm)
 {
 	unsigned long gap = current->signal->rlim[RLIMIT_STACK].rlim_cur;
+	unsigned long random_factor = 0;
+
+	if (current->flags & PF_RANDOMIZE)
+		random_factor = get_random_int() % (1024*1024);
 
 	if (gap < MIN_GAP)
 		gap = MIN_GAP;
 	else if (gap > MAX_GAP)
 		gap = MAX_GAP;
 
-	return TASK_SIZE - (gap & PAGE_MASK);
+	return PAGE_ALIGN(TASK_SIZE - gap - random_factor);
 }
 
 /*
diff -Nru a/arch/i386/pci/acpi.c b/arch/i386/pci/acpi.c
--- a/arch/i386/pci/acpi.c	2005-03-11 12:51:47 -08:00
+++ b/arch/i386/pci/acpi.c	2005-03-11 12:51:47 -08:00
@@ -37,21 +37,12 @@
 		 * also do it here in case there are still broken drivers that
 		 * don't use pci_enable_device().
 		 */
-		printk(KERN_INFO "** Routing PCI interrupts for all devices because \"pci=routeirq\"\n");
-		printk(KERN_INFO "** was specified.  If this was required to make a driver work,\n");
-		printk(KERN_INFO "** please email the output of \"lspci\" to bjorn.helgaas@hp.com\n");
-		printk(KERN_INFO "** so I can fix the driver.\n");
+		printk(KERN_INFO "PCI: Routing PCI interrupts for all devices because \"pci=routeirq\" specified\n");
 		while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL)
 			acpi_pci_irq_enable(dev);
-	} else {
-		printk(KERN_INFO "** PCI interrupts are no longer routed automatically.  If this\n");
-		printk(KERN_INFO "** causes a device to stop working, it is probably because the\n");
-		printk(KERN_INFO "** driver failed to call pci_enable_device().  As a temporary\n");
-		printk(KERN_INFO "** workaround, the \"pci=routeirq\" argument restores the old\n");
-		printk(KERN_INFO "** behavior.  If this argument makes the device work again,\n");
-		printk(KERN_INFO "** please email the output of \"lspci\" to bjorn.helgaas@hp.com\n");
-		printk(KERN_INFO "** so I can fix the driver.\n");
-	}
+	} else
+		printk(KERN_INFO "PCI: If a device doesn't work, try \"pci=routeirq\".  If it helps, post a report\n");
+
 #ifdef CONFIG_X86_IO_APIC
 	if (acpi_ioapic)
 		print_IO_APIC();
diff -Nru a/arch/i386/pci/direct.c b/arch/i386/pci/direct.c
--- a/arch/i386/pci/direct.c	2005-03-11 12:51:41 -08:00
+++ b/arch/i386/pci/direct.c	2005-03-11 12:51:41 -08:00
@@ -13,7 +13,8 @@
 #define PCI_CONF1_ADDRESS(bus, devfn, reg) \
 	(0x80000000 | (bus << 16) | (devfn << 8) | (reg & ~3))
 
-static int pci_conf1_read (int seg, int bus, int devfn, int reg, int len, u32 *value)
+static int pci_conf1_read(unsigned int seg, unsigned int bus,
+			  unsigned int devfn, int reg, int len, u32 *value)
 {
 	unsigned long flags;
 
@@ -41,7 +42,8 @@
 	return 0;
 }
 
-static int pci_conf1_write (int seg, int bus, int devfn, int reg, int len, u32 value)
+static int pci_conf1_write(unsigned int seg, unsigned int bus,
+			   unsigned int devfn, int reg, int len, u32 value)
 {
 	unsigned long flags;
 
@@ -83,7 +85,8 @@
 
 #define PCI_CONF2_ADDRESS(dev, reg)	(u16)(0xC000 | (dev << 8) | reg)
 
-static int pci_conf2_read(int seg, int bus, int devfn, int reg, int len, u32 *value)
+static int pci_conf2_read(unsigned int seg, unsigned int bus,
+			  unsigned int devfn, int reg, int len, u32 *value)
 {
 	unsigned long flags;
 	int dev, fn;
@@ -121,7 +124,8 @@
 	return 0;
 }
 
-static int pci_conf2_write (int seg, int bus, int devfn, int reg, int len, u32 value)
+static int pci_conf2_write(unsigned int seg, unsigned int bus,
+			   unsigned int devfn, int reg, int len, u32 value)
 {
 	unsigned long flags;
 	int dev, fn;
diff -Nru a/arch/i386/pci/irq.c b/arch/i386/pci/irq.c
--- a/arch/i386/pci/irq.c	2005-03-11 12:51:52 -08:00
+++ b/arch/i386/pci/irq.c	2005-03-11 12:51:52 -08:00
@@ -1031,56 +1031,55 @@
 
 	pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
 	if (pin && !pcibios_lookup_irq(dev, 1) && !dev->irq) {
-		char *msg;
-		msg = "";
+		char *msg = "";
+
+		pin--;		/* interrupt pins are numbered starting from 1 */
+
 		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 %s[%c] to get irq %d\n",
-							pci_name(bridge), 'A' + pin, irq);
-					dev = bridge;
-				}
-				dev = temp_dev;
-				if (irq >= 0) {
+			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 %s[%c] to get irq %d\n",
+						pci_name(bridge), 'A' + pin, irq);
+				dev = bridge;
+			}
+			dev = temp_dev;
+			if (irq >= 0) {
 #ifdef CONFIG_PCI_MSI
-					if (!platform_legacy_irq(irq))
-						irq = IO_APIC_VECTOR(irq);
+				if (!platform_legacy_irq(irq))
+					irq = IO_APIC_VECTOR(irq);
 #endif
-					printk(KERN_INFO "PCI->APIC IRQ transform: %s[%c] -> IRQ %d\n",
-						pci_name(dev), 'A' + pin, irq);
-					dev->irq = irq;
-					return 0;
-				} else
-					msg = " Probably buggy MP table.";
-			}
+				printk(KERN_INFO "PCI->APIC IRQ transform: %s[%c] -> IRQ %d\n",
+					pci_name(dev), 'A' + pin, irq);
+				dev->irq = irq;
+				return 0;
+			} else
+				msg = " Probably buggy MP table.";
 		} else if (pci_probe & PCI_BIOS_IRQ_SCAN)
 			msg = "";
 		else
 			msg = " Please try using pci=biosirq.";
-			
+
 		/* With IDE legacy devices the IRQ lookup failure is not a problem.. */
 		if (dev->class >> 8 == PCI_CLASS_STORAGE_IDE && !(dev->class & 0x5))
 			return 0;
-			
+
 		printk(KERN_WARNING "PCI: No IRQ known for interrupt pin %c of device %s.%s\n",
-		       'A' + pin - 1, pci_name(dev), msg);
+		       'A' + pin, pci_name(dev), msg);
 	}
 	/* VIA bridges use interrupt line for apic/pci steering across
 	   the V-Link */
diff -Nru a/arch/i386/pci/mmconfig.c b/arch/i386/pci/mmconfig.c
--- a/arch/i386/pci/mmconfig.c	2005-03-11 12:51:47 -08:00
+++ b/arch/i386/pci/mmconfig.c	2005-03-11 12:51:47 -08:00
@@ -34,7 +34,8 @@
 	}
 }
 
-static int pci_mmcfg_read(int seg, int bus, int devfn, int reg, int len, u32 *value)
+static int pci_mmcfg_read(unsigned int seg, unsigned int bus,
+			  unsigned int devfn, int reg, int len, u32 *value)
 {
 	unsigned long flags;
 
@@ -62,7 +63,8 @@
 	return 0;
 }
 
-static int pci_mmcfg_write(int seg, int bus, int devfn, int reg, int len, u32 value)
+static int pci_mmcfg_write(unsigned int seg, unsigned int bus,
+			   unsigned int devfn, int reg, int len, u32 value)
 {
 	unsigned long flags;
 
diff -Nru a/arch/i386/pci/numa.c b/arch/i386/pci/numa.c
--- a/arch/i386/pci/numa.c	2005-03-11 12:51:41 -08:00
+++ b/arch/i386/pci/numa.c	2005-03-11 12:51:41 -08:00
@@ -14,11 +14,12 @@
 #define PCI_CONF1_MQ_ADDRESS(bus, devfn, reg) \
 	(0x80000000 | (BUS2LOCAL(bus) << 16) | (devfn << 8) | (reg & ~3))
 
-static int pci_conf1_mq_read (int seg, int bus, int devfn, int reg, int len, u32 *value)
+static int pci_conf1_mq_read(unsigned int seg, unsigned int bus,
+			     unsigned int devfn, int reg, int len, u32 *value)
 {
 	unsigned long flags;
 
-	if (!value || (bus > MAX_MP_BUSSES) || (devfn > 255) || (reg > 255))
+	if (!value || (bus >= MAX_MP_BUSSES) || (devfn > 255) || (reg > 255))
 		return -EINVAL;
 
 	spin_lock_irqsave(&pci_config_lock, flags);
@@ -42,11 +43,12 @@
 	return 0;
 }
 
-static int pci_conf1_mq_write (int seg, int bus, int devfn, int reg, int len, u32 value)
+static int pci_conf1_mq_write(unsigned int seg, unsigned int bus,
+			      unsigned int devfn, int reg, int len, u32 value)
 {
 	unsigned long flags;
 
-	if ((bus > MAX_MP_BUSSES) || (devfn > 255) || (reg > 255)) 
+	if ((bus >= MAX_MP_BUSSES) || (devfn > 255) || (reg > 255)) 
 		return -EINVAL;
 
 	spin_lock_irqsave(&pci_config_lock, flags);
diff -Nru a/arch/i386/pci/pcbios.c b/arch/i386/pci/pcbios.c
--- a/arch/i386/pci/pcbios.c	2005-03-11 12:51:52 -08:00
+++ b/arch/i386/pci/pcbios.c	2005-03-11 12:51:52 -08:00
@@ -172,7 +172,8 @@
 	return (int) (ret & 0xff00) >> 8;
 }
 
-static int pci_bios_read (int seg, int bus, int devfn, int reg, int len, u32 *value)
+static int pci_bios_read(unsigned int seg, unsigned int bus,
+			 unsigned int devfn, int reg, int len, u32 *value)
 {
 	unsigned long result = 0;
 	unsigned long flags;
@@ -227,7 +228,8 @@
 	return (int)((result & 0xff00) >> 8);
 }
 
-static int pci_bios_write (int seg, int bus, int devfn, int reg, int len, u32 value)
+static int pci_bios_write(unsigned int seg, unsigned int bus,
+			  unsigned int devfn, int reg, int len, u32 value)
 {
 	unsigned long result = 0;
 	unsigned long flags;
diff -Nru a/arch/ia64/configs/sn2_defconfig b/arch/ia64/configs/sn2_defconfig
--- a/arch/ia64/configs/sn2_defconfig	2005-03-11 12:51:40 -08:00
+++ b/arch/ia64/configs/sn2_defconfig	2005-03-11 12:51:40 -08:00
@@ -31,6 +31,7 @@
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
+CONFIG_CPUSETS=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_SHMEM=y
 CONFIG_CC_ALIGN_FUNCTIONS=0
diff -Nru a/arch/ia64/ia32/ia32_entry.S b/arch/ia64/ia32/ia32_entry.S
--- a/arch/ia64/ia32/ia32_entry.S	2005-03-11 12:51:46 -08:00
+++ b/arch/ia64/ia32/ia32_entry.S	2005-03-11 12:51:46 -08:00
@@ -494,7 +494,7 @@
   	data8 compat_sys_mq_notify
   	data8 compat_sys_mq_getsetattr
 	data8 sys_ni_syscall		/* reserved for kexec */
-	data8 sys32_waitid
+	data8 compat_sys_waitid
 
 	// guard against failures to increase IA32_NR_syscalls
 	.org ia32_syscall_table + 8*IA32_NR_syscalls
diff -Nru a/arch/ia64/ia32/ia32priv.h b/arch/ia64/ia32/ia32priv.h
--- a/arch/ia64/ia32/ia32priv.h	2005-03-11 12:51:51 -08:00
+++ b/arch/ia64/ia32/ia32priv.h	2005-03-11 12:51:51 -08:00
@@ -225,13 +225,6 @@
 	unsigned int	st_ino_hi;
 };
 
-typedef union sigval32 {
-	int sival_int;
-	unsigned int sival_ptr;
-} sigval_t32;
-
-#define SIGEV_PAD_SIZE32 ((SIGEV_MAX_SIZE/sizeof(int)) - 3)
-
 typedef struct compat_siginfo {
 	int si_signo;
 	int si_errno;
@@ -251,7 +244,7 @@
 			timer_t _tid;		/* timer id */
 			int _overrun;		/* overrun count */
 			char _pad[sizeof(unsigned int) - sizeof(int)];
-			sigval_t32 _sigval;	/* same as below */
+			compat_sigval_t _sigval;	/* same as below */
 			int _sys_private;       /* not to be passed to user */
 		} _timer;
 
@@ -259,7 +252,7 @@
 		struct {
 			unsigned int _pid;	/* sender's pid */
 			unsigned int _uid;	/* sender's uid */
-			sigval_t32 _sigval;
+			compat_sigval_t _sigval;
 		} _rt;
 
 		/* SIGCHLD */
@@ -283,19 +276,6 @@
 		} _sigpoll;
 	} _sifields;
 } compat_siginfo_t;
-
-typedef struct sigevent32 {
-	sigval_t32 sigev_value;
-	int sigev_signo;
-	int sigev_notify;
-	union {
-		int _pad[SIGEV_PAD_SIZE32];
-		struct {
-			u32 _function;
-			u32 _attribute; /* really pthread_attr_t */
-		} _sigev_thread;
-	} _sigev_un;
-} sigevent_t32;
 
 struct old_linux32_dirent {
 	u32	d_ino;
diff -Nru a/arch/ia64/ia32/sys_ia32.c b/arch/ia64/ia32/sys_ia32.c
--- a/arch/ia64/ia32/sys_ia32.c	2005-03-11 12:51:47 -08:00
+++ b/arch/ia64/ia32/sys_ia32.c	2005-03-11 12:51:47 -08:00
@@ -2592,7 +2592,7 @@
 }
 
 asmlinkage long
-sys32_timer_create(u32 clock, struct sigevent32 __user *se32, timer_t __user *timer_id)
+sys32_timer_create(u32 clock, struct compat_sigevent __user *se32, timer_t __user *timer_id)
 {
 	struct sigevent se;
 	mm_segment_t oldfs;
@@ -2602,12 +2602,7 @@
 	if (se32 == NULL)
 		return sys_timer_create(clock, NULL, timer_id);
 
-	memset(&se, 0, sizeof(struct sigevent));
-	if (get_user(se.sigev_value.sival_int,	&se32->sigev_value.sival_int) ||
-	    __get_user(se.sigev_signo, &se32->sigev_signo) ||
-	    __get_user(se.sigev_notify, &se32->sigev_notify) ||
-	    __copy_from_user(&se._sigev_un._pad, &se32->_sigev_un._pad,
-	    sizeof(se._sigev_un._pad)))
+	if (get_compat_sigevent(&se, se32))
 		return -EFAULT;
 
 	if (!access_ok(VERIFY_WRITE,timer_id,sizeof(timer_t)))
@@ -2632,32 +2627,6 @@
 			       (((u64)len_high)<<32) | len_low,
 			       advice); 
 } 
-
-asmlinkage long sys32_waitid(int which, compat_pid_t pid,
-			     compat_siginfo_t __user *uinfo, int options,
-			     struct compat_rusage __user *uru)
-{
-	siginfo_t info;
-	struct rusage ru;
-	long ret;
-	mm_segment_t old_fs = get_fs();
-
-	info.si_signo = 0;
-	set_fs (KERNEL_DS);
-	ret = sys_waitid(which, pid, (siginfo_t __user *) &info, options,
-			 uru ? (struct rusage __user *) &ru : NULL);
-	set_fs (old_fs);
-
-	if (ret < 0 || info.si_signo == 0)
-		return ret;
-
-	if (uru && (ret = put_compat_rusage(&ru, uru)))
-		return ret;
-
-	BUG_ON(info.si_code & __SI_MASK);
-	info.si_code |= __SI_CHLD;
-	return copy_siginfo_to_user32(uinfo, &info);
-}
 
 #ifdef	NOTYET  /* UNTESTED FOR IA64 FROM HERE DOWN */
 
diff -Nru a/arch/ia64/mm/extable.c b/arch/ia64/mm/extable.c
--- a/arch/ia64/mm/extable.c	2005-03-11 12:51:42 -08:00
+++ b/arch/ia64/mm/extable.c	2005-03-11 12:51:42 -08:00
@@ -6,29 +6,29 @@
  */
 
 #include <linux/config.h>
+#include <linux/sort.h>
 
 #include <asm/uaccess.h>
 #include <asm/module.h>
 
-static inline int
-compare_entries (struct exception_table_entry *l, struct exception_table_entry *r)
+static int cmp_ex(const void *a, const void *b)
 {
+	const struct exception_table_entry *l = a, *r = b;
 	u64 lip = (u64) &l->addr + l->addr;
 	u64 rip = (u64) &r->addr + r->addr;
 
+	/* avoid overflow */
+	if (lip > rip)
+		return 1;
 	if (lip < rip)
 		return -1;
-	if (lip == rip)
-		return 0;
-	else
-		return 1;
+	return 0;
 }
 
-static inline void
-swap_entries (struct exception_table_entry *l, struct exception_table_entry *r)
+static void swap_ex(void *a, void *b, int size)
 {
+	struct exception_table_entry *l = a, *r = b, tmp;
 	u64 delta = (u64) r - (u64) l;
-	struct exception_table_entry tmp;
 
 	tmp = *l;
 	l->addr = r->addr + delta;
@@ -38,23 +38,20 @@
 }
 
 /*
- * Sort the exception table.  It's usually already sorted, but there may be unordered
- * entries due to multiple text sections (such as the .init text section).  Note that the
- * exception-table-entries contain location-relative addresses, which requires a bit of
- * care during sorting to avoid overflows in the offset members (e.g., it would not be
- * safe to make a temporary copy of an exception-table entry on the stack, because the
- * stack may be more than 2GB away from the exception-table).
+ * Sort the exception table. It's usually already sorted, but there
+ * may be unordered entries due to multiple text sections (such as the
+ * .init text section). Note that the exception-table-entries contain
+ * location-relative addresses, which requires a bit of care during
+ * sorting to avoid overflows in the offset members (e.g., it would
+ * not be safe to make a temporary copy of an exception-table entry on
+ * the stack, because the stack may be more than 2GB away from the
+ * exception-table).
  */
-void
-sort_extable (struct exception_table_entry *start, struct exception_table_entry *finish)
+void sort_extable (struct exception_table_entry *start,
+		   struct exception_table_entry *finish)
 {
-	struct exception_table_entry *p, *q;
-
- 	/* insertion sort */
-	for (p = start + 1; p < finish; ++p)
-		/* start .. p-1 is sorted; push p down to it's proper place */
-		for (q = p; q > start && compare_entries(&q[0], &q[-1]) < 0; --q)
-			swap_entries(&q[0], &q[-1]);
+	sort(start, finish - start, sizeof(struct exception_table_entry),
+	     cmp_ex, swap_ex);
 }
 
 const struct exception_table_entry *
diff -Nru a/arch/ia64/mm/hugetlbpage.c b/arch/ia64/mm/hugetlbpage.c
--- a/arch/ia64/mm/hugetlbpage.c	2005-03-11 12:51:46 -08:00
+++ b/arch/ia64/mm/hugetlbpage.c	2005-03-11 12:51:46 -08:00
@@ -244,7 +244,7 @@
 			continue;
 		page = pte_page(*pte);
 		put_page(page);
-		pte_clear(pte);
+		pte_clear(mm, address, pte);
 	}
 	mm->rss -= (end - start) >> PAGE_SHIFT;
 	flush_tlb_range(vma, start, end);
diff -Nru a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c
--- a/arch/ia64/pci/pci.c	2005-03-11 12:51:43 -08:00
+++ b/arch/ia64/pci/pci.c	2005-03-11 12:51:43 -08:00
@@ -3,9 +3,9 @@
  *
  * Derived from bios32.c of i386 tree.
  *
- * Copyright (C) 2002 Hewlett-Packard Co
+ * (c) Copyright 2002, 2005 Hewlett-Packard Development Company, L.P.
  *	David Mosberger-Tang <davidm@hpl.hp.com>
- *	Bjorn Helgaas <bjorn_helgaas@hp.com>
+ *	Bjorn Helgaas <bjorn.helgaas@hp.com>
  * Copyright (C) 2004 Silicon Graphics, Inc.
  *
  * Note: Above list of copyright holders is incomplete...
@@ -27,26 +27,12 @@
 #include <asm/segment.h>
 #include <asm/system.h>
 #include <asm/io.h>
-
 #include <asm/sal.h>
-
-
-#ifdef CONFIG_SMP
-# include <asm/smp.h>
-#endif
+#include <asm/smp.h>
 #include <asm/irq.h>
 #include <asm/hw_irq.h>
 
 
-#undef DEBUG
-#define DEBUG
-
-#ifdef DEBUG
-#define DBG(x...) printk(x)
-#else
-#define DBG(x...)
-#endif
-
 static int pci_routeirq;
 
 /*
@@ -55,23 +41,22 @@
  * synchronization mechanism here.
  */
 
-#define PCI_SAL_ADDRESS(seg, bus, devfn, reg)	\
-	((u64)(seg << 24) | (u64)(bus << 16) |	\
-	 (u64)(devfn << 8) | (u64)(reg))
+#define PCI_SAL_ADDRESS(seg, bus, devfn, reg)		\
+	(((u64) seg << 24) | (bus << 16) | (devfn << 8) | (reg))
 
 /* SAL 3.2 adds support for extended config space. */
 
 #define PCI_SAL_EXT_ADDRESS(seg, bus, devfn, reg)	\
-	((u64)(seg << 28) | (u64)(bus << 20) |		\
-	 (u64)(devfn << 12) | (u64)(reg))
+	(((u64) seg << 28) | (bus << 20) | (devfn << 12) | (reg))
 
 static int
-pci_sal_read (int seg, int bus, int devfn, int reg, int len, u32 *value)
+pci_sal_read (unsigned int seg, unsigned int bus, unsigned int devfn,
+	      int reg, int len, u32 *value)
 {
-	u64 addr, mode, data = 0;
-	int result = 0;
+	u64 addr, data = 0;
+	int mode, result;
 
-	if ((seg > 65535) || (bus > 255) || (devfn > 255) || (reg > 4095))
+	if (!value || (seg > 65535) || (bus > 255) || (devfn > 255) || (reg > 4095))
 		return -EINVAL;
 
 	if ((seg | reg) <= 255) {
@@ -82,16 +67,19 @@
 		mode = 1;
 	}
 	result = ia64_sal_pci_config_read(addr, mode, len, &data);
+	if (result != 0)
+		return -EINVAL;
 
 	*value = (u32) data;
-
-	return result;
+	return 0;
 }
 
 static int
-pci_sal_write (int seg, int bus, int devfn, int reg, int len, u32 value)
+pci_sal_write (unsigned int seg, unsigned int bus, unsigned int devfn,
+	       int reg, int len, u32 value)
 {
-	u64 addr, mode;
+	u64 addr;
+	int mode, result;
 
 	if ((seg > 65535) || (bus > 255) || (devfn > 255) || (reg > 4095))
 		return -EINVAL;
@@ -103,7 +91,10 @@
 		addr = PCI_SAL_EXT_ADDRESS(seg, bus, devfn, reg);
 		mode = 1;
 	}
-	return ia64_sal_pci_config_write(addr, mode, len, value);
+	result = ia64_sal_pci_config_write(addr, mode, len, value);
+	if (result != 0)
+		return -EINVAL;
+	return 0;
 }
 
 static struct pci_raw_ops pci_sal_ops = {
@@ -160,21 +151,11 @@
 		 * also do it here in case there are still broken drivers that
 		 * don't use pci_enable_device().
 		 */
-		printk(KERN_INFO "** Routing PCI interrupts for all devices because \"pci=routeirq\"\n");
-		printk(KERN_INFO "** was specified.  If this was required to make a driver work,\n");
-		printk(KERN_INFO "** please email the output of \"lspci\" to bjorn.helgaas@hp.com\n");
-		printk(KERN_INFO "** so I can fix the driver.\n");
+		printk(KERN_INFO "PCI: Routing interrupts for all devices because \"pci=routeirq\" specified\n");
 		for_each_pci_dev(dev)
 			acpi_pci_irq_enable(dev);
-	} else {
-		printk(KERN_INFO "** PCI interrupts are no longer routed automatically.  If this\n");
-		printk(KERN_INFO "** causes a device to stop working, it is probably because the\n");
-		printk(KERN_INFO "** driver failed to call pci_enable_device().  As a temporary\n");
-		printk(KERN_INFO "** workaround, the \"pci=routeirq\" argument restores the old\n");
-		printk(KERN_INFO "** behavior.  If this argument makes the device work again,\n");
-		printk(KERN_INFO "** please email the output of \"lspci\" to bjorn.helgaas@hp.com\n");
-		printk(KERN_INFO "** so I can fix the driver.\n");
-	}
+	} else
+		printk(KERN_INFO "PCI: If a device doesn't work, try \"pci=routeirq\".  If it helps, post a report\n");
 
 	return 0;
 }
diff -Nru a/arch/mips/Kconfig b/arch/mips/Kconfig
--- a/arch/mips/Kconfig	2005-03-11 12:51:46 -08:00
+++ b/arch/mips/Kconfig	2005-03-11 12:51:46 -08:00
@@ -122,10 +122,6 @@
 	  The TANBAC TB0229 (VR4131DIMM) is a MIPS-based platform manufactured by TANBAC.
 	  Please refer to <http://www.tanbac.co.jp/> about VR4131DIMM.
 
-config TANBAC_TB0219
-	bool "Added TANBAC TB0219 Base board support"
-	depends on TANBAC_TB0229
-
 config VICTOR_MPC30X
 	bool "Support for Victor MP-C303/304"
 	select DMA_NONCOHERENT
diff -Nru a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c
--- a/arch/mips/kernel/ptrace.c	2005-03-11 12:51:52 -08:00
+++ b/arch/mips/kernel/ptrace.c	2005-03-11 12:51:52 -08:00
@@ -21,6 +21,7 @@
 #include <linux/mm.h>
 #include <linux/errno.h>
 #include <linux/ptrace.h>
+#include <linux/audit.h>
 #include <linux/smp.h>
 #include <linux/smp_lock.h>
 #include <linux/user.h>
@@ -307,7 +308,7 @@
 {
 	if (unlikely(current->audit_context)) {
 		if (!entryexit)
-			audit_syscall_entry(current, regs->orig_eax,
+			audit_syscall_entry(current, regs->regs[2],
 			                    regs->regs[4], regs->regs[5],
 			                    regs->regs[6], regs->regs[7]);
 		else
diff -Nru a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c
--- a/arch/mips/kernel/setup.c	2005-03-11 12:51:41 -08:00
+++ b/arch/mips/kernel/setup.c	2005-03-11 12:51:41 -08:00
@@ -86,8 +86,8 @@
 unsigned long isa_slot_offset;
 EXPORT_SYMBOL(isa_slot_offset);
 
-static struct resource code_resource = { "Kernel code" };
-static struct resource data_resource = { "Kernel data" };
+static struct resource code_resource = { .name = "Kernel code", };
+static struct resource data_resource = { .name = "Kernel data", };
 
 void __init add_memory_region(phys_t start, phys_t size, long type)
 {
diff -Nru a/arch/mips/kernel/signal32.c b/arch/mips/kernel/signal32.c
--- a/arch/mips/kernel/signal32.c	2005-03-11 12:51:46 -08:00
+++ b/arch/mips/kernel/signal32.c	2005-03-11 12:51:46 -08:00
@@ -32,11 +32,6 @@
 
 #define SI_PAD_SIZE32   ((SI_MAX_SIZE/sizeof(int)) - 3)
 
-typedef union sigval32 {
-	int sival_int;
-	s32 sival_ptr;
-} sigval_t32;
-
 typedef struct compat_siginfo {
 	int si_signo;
 	int si_code;
@@ -89,7 +84,7 @@
 		struct {
 			compat_pid_t _pid;	/* sender's pid */
 			compat_uid_t _uid;	/* sender's uid */
-			sigval_t32 _sigval;
+			compat_sigval_t _sigval;
 		} _rt;
 
 	} _sifields;
diff -Nru a/arch/mips/mm/c-r3k.c b/arch/mips/mm/c-r3k.c
--- a/arch/mips/mm/c-r3k.c	2005-03-11 12:51:50 -08:00
+++ b/arch/mips/mm/c-r3k.c	2005-03-11 12:51:50 -08:00
@@ -254,8 +254,7 @@
 {
 }
 
-static void r3k_flush_cache_page(struct vm_area_struct *vma,
-	unsigned long page)
+static void r3k_flush_cache_page(struct vm_area_struct *vma, unsigned long page, unsigned long pfn)
 {
 }
 
diff -Nru a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c
--- a/arch/mips/mm/c-r4k.c	2005-03-11 12:51:51 -08:00
+++ b/arch/mips/mm/c-r4k.c	2005-03-11 12:51:51 -08:00
@@ -426,8 +426,7 @@
 	}
 }
 
-static void r4k_flush_cache_page(struct vm_area_struct *vma,
-	unsigned long page)
+static void r4k_flush_cache_page(struct vm_area_struct *vma, unsigned long page, unsigned long pfn)
 {
 	struct flush_cache_page_args args;
 
diff -Nru a/arch/mips/mm/c-sb1.c b/arch/mips/mm/c-sb1.c
--- a/arch/mips/mm/c-sb1.c	2005-03-11 12:51:46 -08:00
+++ b/arch/mips/mm/c-sb1.c	2005-03-11 12:51:46 -08:00
@@ -160,8 +160,7 @@
  * dcache first, then invalidate the icache.  If the page isn't
  * executable, nothing is required.
  */
-static void local_sb1_flush_cache_page(struct vm_area_struct *vma,
-	unsigned long addr)
+static void local_sb1_flush_cache_page(struct vm_area_struct *vma, unsigned long addr, unsigned long pfn)
 {
 	int cpu = smp_processor_id();
 
@@ -183,17 +182,18 @@
 struct flush_cache_page_args {
 	struct vm_area_struct *vma;
 	unsigned long addr;
+	unsigned long pfn;
 };
 
 static void sb1_flush_cache_page_ipi(void *info)
 {
 	struct flush_cache_page_args *args = info;
 
-	local_sb1_flush_cache_page(args->vma, args->addr);
+	local_sb1_flush_cache_page(args->vma, args->addr, args->pfn);
 }
 
 /* Dirty dcache could be on another CPU, so do the IPIs */
-static void sb1_flush_cache_page(struct vm_area_struct *vma, unsigned long addr)
+static void sb1_flush_cache_page(struct vm_area_struct *vma, unsigned long addr, unsigned long pfn)
 {
 	struct flush_cache_page_args args;
 
@@ -203,10 +203,11 @@
 	addr &= PAGE_MASK;
 	args.vma = vma;
 	args.addr = addr;
+	args.pfn = pfn;
 	on_each_cpu(sb1_flush_cache_page_ipi, (void *) &args, 1, 1);
 }
 #else
-void sb1_flush_cache_page(struct vm_area_struct *vma, unsigned long addr)
+void sb1_flush_cache_page(struct vm_area_struct *vma, unsigned long addr, unsigned long pfn)
 	__attribute__((alias("local_sb1_flush_cache_page")));
 #endif
 
diff -Nru a/arch/mips/mm/c-tx39.c b/arch/mips/mm/c-tx39.c
--- a/arch/mips/mm/c-tx39.c	2005-03-11 12:51:52 -08:00
+++ b/arch/mips/mm/c-tx39.c	2005-03-11 12:51:52 -08:00
@@ -178,8 +178,7 @@
 	}
 }
 
-static void tx39_flush_cache_page(struct vm_area_struct *vma,
-				   unsigned long page)
+static void tx39_flush_cache_page(struct vm_area_struct *vma, unsigned long page, unsigned long pfn)
 {
 	int exec = vma->vm_flags & VM_EXEC;
 	struct mm_struct *mm = vma->vm_mm;
diff -Nru a/arch/mips/mm/cache.c b/arch/mips/mm/cache.c
--- a/arch/mips/mm/cache.c	2005-03-11 12:51:42 -08:00
+++ b/arch/mips/mm/cache.c	2005-03-11 12:51:42 -08:00
@@ -23,7 +23,7 @@
 void (*flush_cache_mm)(struct mm_struct *mm);
 void (*flush_cache_range)(struct vm_area_struct *vma, unsigned long start,
 	unsigned long end);
-void (*flush_cache_page)(struct vm_area_struct *vma, unsigned long page);
+void (*flush_cache_page)(struct vm_area_struct *vma, unsigned long page, unsigned long pfn);
 void (*flush_icache_range)(unsigned long start, unsigned long end);
 void (*flush_icache_page)(struct vm_area_struct *vma, struct page *page);
 
diff -Nru a/arch/mips/mm/highmem.c b/arch/mips/mm/highmem.c
--- a/arch/mips/mm/highmem.c	2005-03-11 12:51:42 -08:00
+++ b/arch/mips/mm/highmem.c	2005-03-11 12:51:42 -08:00
@@ -75,7 +75,7 @@
 	 * force other mappings to Oops if they'll try to access
 	 * this pte without first remap it
 	 */
-	pte_clear(kmap_pte-idx);
+	pte_clear(&init_mm, vaddr, kmap_pte-idx);
 	local_flush_tlb_one(vaddr);
 #endif
 
diff -Nru a/arch/mips/pci/pci-vr41xx.c b/arch/mips/pci/pci-vr41xx.c
--- a/arch/mips/pci/pci-vr41xx.c	2005-03-11 12:51:52 -08:00
+++ b/arch/mips/pci/pci-vr41xx.c	2005-03-11 12:51:52 -08:00
@@ -288,4 +288,4 @@
 	return 0;
 }
 
-early_initcall(vr41xx_pciu_init);
+arch_initcall(vr41xx_pciu_init);
diff -Nru a/arch/mips/pmc-sierra/yosemite/ht.c b/arch/mips/pmc-sierra/yosemite/ht.c
--- a/arch/mips/pmc-sierra/yosemite/ht.c	2005-03-11 12:51:52 -08:00
+++ b/arch/mips/pmc-sierra/yosemite/ht.c	2005-03-11 12:51:52 -08:00
@@ -303,7 +303,7 @@
                 if (!r->start && r->end) {
                         printk(KERN_ERR
                                "PCI: Device %s not available because of "
-                               "resource collisions\n", dev->slot_name);
+                               "resource collisions\n", pci_name(dev));
                         return -EINVAL;
                 }
                 if (r->flags & IORESOURCE_IO)
@@ -377,7 +377,7 @@
             ((new & PCI_BASE_ADDRESS_SPACE_IO) ? PCI_BASE_ADDRESS_IO_MASK :
              PCI_BASE_ADDRESS_MEM_MASK)) {
                 printk(KERN_ERR "PCI: Error while updating region "
-                       "%s/%d (%08x != %08x)\n", dev->slot_name, resource,
+                       "%s/%d (%08x != %08x)\n", pci_name(dev), resource,
                        new, check);
         }
 }
@@ -396,7 +396,7 @@
                    addresses kilobyte aligned.  */
                 if (size > 0x100) {
                         printk(KERN_ERR "PCI: I/O Region %s/%d too large"
-                               " (%ld bytes)\n", dev->slot_name,
+                               " (%ld bytes)\n", pci_name(dev),
                                 dev->resource - res, size);
                 }
 
diff -Nru a/arch/mips/vr41xx/casio-e55/setup.c b/arch/mips/vr41xx/casio-e55/setup.c
--- a/arch/mips/vr41xx/casio-e55/setup.c	2005-03-11 12:51:42 -08:00
+++ b/arch/mips/vr41xx/casio-e55/setup.c	2005-03-11 12:51:42 -08:00
@@ -1,7 +1,7 @@
 /*
  *  setup.c, Setup for the CASIO CASSIOPEIA E-11/15/55/65.
  *
- *  Copyright (C) 2002-2004  Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
+ *  Copyright (C) 2002-2005  Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -17,7 +17,7 @@
  *  along with this program; if not, write to the Free Software
  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
-#include <linux/config.h>
+#include <linux/init.h>
 #include <linux/ioport.h>
 
 #include <asm/io.h>
@@ -28,18 +28,13 @@
 	return "CASIO CASSIOPEIA E-11/15/55/65";
 }
 
-static int casio_e55_setup(void)
+static int __init casio_e55_setup(void)
 {
 	set_io_port_base(IO_PORT_BASE);
 	ioport_resource.start = IO_PORT_RESOURCE_START;
 	ioport_resource.end = IO_PORT_RESOURCE_END;
 
-#ifdef CONFIG_SERIAL_8250
-	vr41xx_select_siu_interface(SIU_RS232C, IRDA_NONE);
-	vr41xx_siu_init();
-#endif
-
 	return 0;
 }
 
-early_initcall(casio_e55_setup);
+arch_initcall(casio_e55_setup);
diff -Nru a/arch/mips/vr41xx/common/Makefile b/arch/mips/vr41xx/common/Makefile
--- a/arch/mips/vr41xx/common/Makefile	2005-03-11 12:51:46 -08:00
+++ b/arch/mips/vr41xx/common/Makefile	2005-03-11 12:51:46 -08:00
@@ -3,7 +3,6 @@
 #
 
 obj-y				+= bcu.o cmu.o giu.o icu.o init.o int-handler.o ksyms.o pmu.o rtc.o
-obj-$(CONFIG_SERIAL_8250)	+= serial.o
 obj-$(CONFIG_VRC4171)		+= vrc4171.o
 obj-$(CONFIG_VRC4173)		+= vrc4173.o
 
diff -Nru a/arch/mips/vr41xx/common/bcu.c b/arch/mips/vr41xx/common/bcu.c
--- a/arch/mips/vr41xx/common/bcu.c	2005-03-11 12:51:51 -08:00
+++ b/arch/mips/vr41xx/common/bcu.c	2005-03-11 12:51:51 -08:00
@@ -3,7 +3,7 @@
  *
  *  Copyright (C) 2002  MontaVista Software Inc.
  *    Author: Yoichi Yuasa <yyuasa@mvista.com, or source@mvista.com>
- *  Copyright (C) 2003-2004  Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
+ *  Copyright (C) 2003-2005  Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -28,20 +28,16 @@
  *  Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
  *  - Added support for NEC VR4133.
  */
-#include <linux/init.h>
-#include <linux/ioport.h>
 #include <linux/kernel.h>
+#include <linux/module.h>
 #include <linux/smp.h>
 #include <linux/types.h>
 
 #include <asm/cpu.h>
 #include <asm/io.h>
 
-#define IO_MEM_RESOURCE_START	0UL
-#define IO_MEM_RESOURCE_END	0x1fffffffUL
-
-#define CLKSPEEDREG_TYPE1	KSEG1ADDR(0x0b000014)
-#define CLKSPEEDREG_TYPE2	KSEG1ADDR(0x0f000014)
+#define CLKSPEEDREG_TYPE1	(void __iomem *)KSEG1ADDR(0x0b000014)
+#define CLKSPEEDREG_TYPE2	(void __iomem *)KSEG1ADDR(0x0f000014)
  #define CLKSP(x)		((x) & 0x001f)
  #define CLKSP_VR4133(x)	((x) & 0x0007)
 
@@ -63,11 +59,15 @@
 	return vr41xx_vtclock;
 }
 
+EXPORT_SYMBOL_GPL(vr41xx_get_vtclock_frequency);
+
 unsigned long vr41xx_get_tclock_frequency(void)
 {
 	return vr41xx_tclock;
 }
 
+EXPORT_SYMBOL_GPL(vr41xx_get_tclock_frequency);
+
 static inline uint16_t read_clkspeed(void)
 {
 	switch (current_cpu_data.cputype) {
@@ -207,7 +207,7 @@
 	return tclock;
 }
 
-static int __init vr41xx_bcu_init(void)
+void vr41xx_calculate_clock_frequency(void)
 {
 	unsigned long pclock;
 	uint16_t clkspeed;
@@ -217,11 +217,6 @@
 	pclock = calculate_pclock(clkspeed);
 	vr41xx_vtclock = calculate_vtclock(clkspeed, pclock);
 	vr41xx_tclock = calculate_tclock(clkspeed, pclock, vr41xx_vtclock);
-
-	iomem_resource.start = IO_MEM_RESOURCE_START;
-	iomem_resource.end = IO_MEM_RESOURCE_END;
-
-	return 0;
 }
 
-early_initcall(vr41xx_bcu_init);
+EXPORT_SYMBOL_GPL(vr41xx_calculate_clock_frequency);
diff -Nru a/arch/mips/vr41xx/common/cmu.c b/arch/mips/vr41xx/common/cmu.c
--- a/arch/mips/vr41xx/common/cmu.c	2005-03-11 12:51:42 -08:00
+++ b/arch/mips/vr41xx/common/cmu.c	2005-03-11 12:51:42 -08:00
@@ -3,7 +3,7 @@
  *
  *  Copyright (C) 2001-2002  MontaVista Software Inc.
  *    Author: Yoichi Yuasa <yyuasa@mvista.com or source@mvista.com>
- *  Copuright (C) 2003-2004  Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
+ *  Copuright (C) 2003-2005  Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -29,6 +29,8 @@
  *  - Added support for NEC VR4133.
  */
 #include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/module.h>
 #include <linux/smp.h>
 #include <linux/spinlock.h>
 #include <linux/types.h>
@@ -37,8 +39,16 @@
 #include <asm/io.h>
 #include <asm/vr41xx/vr41xx.h>
 
-#define CMUCLKMSK_TYPE1	KSEG1ADDR(0x0b000060)
-#define CMUCLKMSK_TYPE2	KSEG1ADDR(0x0f000060)
+#define CMU_TYPE1_BASE	0x0b000060UL
+#define CMU_TYPE1_SIZE	0x4
+
+#define CMU_TYPE2_BASE	0x0f000060UL
+#define CMU_TYPE2_SIZE	0x4
+
+#define CMU_TYPE3_BASE	0x0f000060UL
+#define CMU_TYPE3_SIZE	0x8
+
+#define CMUCLKMSK	0x0
  #define MSKPIU		0x0001
  #define MSKSIU		0x0002
  #define MSKAIU		0x0004
@@ -52,19 +62,17 @@
  #define MSKFFIR	0x0400
  #define MSKSCSI	0x1000
  #define MSKPPCIU	0x2000
-#define CMUCLKMSK2	KSEG1ADDR(0x0f000064)
+#define CMUCLKMSK2	0x4
  #define MSKCEU		0x0001
  #define MSKMAC0	0x0002
  #define MSKMAC1	0x0004
 
-static uint32_t cmu_base;
+static void __iomem *cmu_base;
 static uint16_t cmuclkmsk, cmuclkmsk2;
 static spinlock_t cmu_lock;
 
-#define read_cmuclkmsk()	readw(cmu_base)
-#define read_cmuclkmsk2()	readw(CMUCLKMSK2)
-#define write_cmuclkmsk()	writew(cmuclkmsk, cmu_base)
-#define write_cmuclkmsk2()	writew(cmuclkmsk2, CMUCLKMSK2)
+#define cmu_read(offset)		readw(cmu_base + (offset))
+#define cmu_write(offset, value)	writew((value), cmu_base + (offset))
 
 void vr41xx_supply_clock(vr41xx_clock_t clock)
 {
@@ -120,13 +128,15 @@
 
 	if (clock == CEU_CLOCK || clock == ETHER0_CLOCK ||
 	    clock == ETHER1_CLOCK)
-		write_cmuclkmsk2();
+		cmu_write(CMUCLKMSK2, cmuclkmsk2);
 	else
-		write_cmuclkmsk();
+		cmu_write(CMUCLKMSK, cmuclkmsk);
 
 	spin_unlock_irq(&cmu_lock);
 }
 
+EXPORT_SYMBOL_GPL(vr41xx_supply_clock);
+
 void vr41xx_mask_clock(vr41xx_clock_t clock)
 {
 	spin_lock_irq(&cmu_lock);
@@ -160,7 +170,7 @@
 		    current_cpu_data.cputype == CPU_VR4121) {
 			cmuclkmsk &= ~MSKDSIU;
 		} else {
-			if (cmuclkmsk & MSKSIU)
+			if (cmuclkmsk & MSKSSIU)
 				cmuclkmsk &= ~MSKDSIU;
 			else
 				cmuclkmsk &= ~(MSKSIU | MSKDSIU);
@@ -193,38 +203,55 @@
 
 	if (clock == CEU_CLOCK || clock == ETHER0_CLOCK ||
 	    clock == ETHER1_CLOCK)
-		write_cmuclkmsk2();
+		cmu_write(CMUCLKMSK2, cmuclkmsk2);
 	else
-		write_cmuclkmsk();
+		cmu_write(CMUCLKMSK, cmuclkmsk);
 
 	spin_unlock_irq(&cmu_lock);
 }
 
+EXPORT_SYMBOL_GPL(vr41xx_mask_clock);
+
 static int __init vr41xx_cmu_init(void)
 {
+	unsigned long start, size;
+
 	switch (current_cpu_data.cputype) {
         case CPU_VR4111:
         case CPU_VR4121:
-                cmu_base = CMUCLKMSK_TYPE1;
+		start = CMU_TYPE1_BASE;
+		size = CMU_TYPE1_SIZE;
                 break;
         case CPU_VR4122:
         case CPU_VR4131:
-                cmu_base = CMUCLKMSK_TYPE2;
-                break;
+		start = CMU_TYPE2_BASE;
+		size = CMU_TYPE2_SIZE;
+		break;
         case CPU_VR4133:
-                cmu_base = CMUCLKMSK_TYPE2;
-		cmuclkmsk2 = read_cmuclkmsk2();
+		start = CMU_TYPE3_BASE;
+		size = CMU_TYPE3_SIZE;
                 break;
 	default:
 		panic("Unexpected CPU of NEC VR4100 series");
 		break;
         }
 
-	cmuclkmsk = read_cmuclkmsk();
+	if (request_mem_region(start, size, "CMU") == NULL)
+		return -EBUSY;
+
+	cmu_base = ioremap(start, size);
+	if (cmu_base == NULL) {
+		release_mem_region(start, size);
+		return -EBUSY;
+	}
+
+	cmuclkmsk = cmu_read(CMUCLKMSK);
+	if (current_cpu_data.cputype == CPU_VR4133)
+		cmuclkmsk2 = cmu_read(CMUCLKMSK2);
 
 	spin_lock_init(&cmu_lock);
 
 	return 0;
 }
 
-early_initcall(vr41xx_cmu_init);
+core_initcall(vr41xx_cmu_init);
diff -Nru a/arch/mips/vr41xx/common/init.c b/arch/mips/vr41xx/common/init.c
--- a/arch/mips/vr41xx/common/init.c	2005-03-11 12:51:47 -08:00
+++ b/arch/mips/vr41xx/common/init.c	2005-03-11 12:51:47 -08:00
@@ -1,7 +1,7 @@
 /*
  *  init.c, Common initialization routines for NEC VR4100 series.
  *
- *  Copyright (C) 2003-2004  Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
+ *  Copyright (C) 2003-2005  Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -18,9 +18,45 @@
  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 #include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/irq.h>
 #include <linux/string.h>
 
 #include <asm/bootinfo.h>
+#include <asm/time.h>
+#include <asm/vr41xx/vr41xx.h>
+
+#define IO_MEM_RESOURCE_START	0UL
+#define IO_MEM_RESOURCE_END	0x1fffffffUL
+
+static void __init iomem_resource_init(void)
+{
+	iomem_resource.start = IO_MEM_RESOURCE_START;
+	iomem_resource.end = IO_MEM_RESOURCE_END;
+}
+
+static void __init setup_timer_frequency(void)
+{
+	unsigned long tclock;
+
+	tclock = vr41xx_get_tclock_frequency();
+	if (current_cpu_data.processor_id == PRID_VR4131_REV2_0 ||
+	    current_cpu_data.processor_id == PRID_VR4131_REV2_1)
+		mips_hpt_frequency = tclock / 2;
+	else
+		mips_hpt_frequency = tclock / 4;
+}
+
+static void __init setup_timer_irq(struct irqaction *irq)
+{
+	setup_irq(TIMER_IRQ, irq);
+}
+
+static void __init timer_init(void)
+{
+	board_time_init = setup_timer_frequency;
+	board_timer_setup = setup_timer_irq;
+}
 
 void __init prom_init(void)
 {
@@ -35,6 +71,12 @@
 		if (i < (argc - 1))
 			strcat(arcs_cmdline, " ");
 	}
+
+	vr41xx_calculate_clock_frequency();
+
+	timer_init();
+
+	iomem_resource_init();
 }
 
 unsigned long __init prom_free_prom_memory (void)
diff -Nru a/arch/mips/vr41xx/common/ksyms.c b/arch/mips/vr41xx/common/ksyms.c
--- a/arch/mips/vr41xx/common/ksyms.c	2005-03-11 12:51:41 -08:00
+++ b/arch/mips/vr41xx/common/ksyms.c	2005-03-11 12:51:41 -08:00
@@ -22,9 +22,6 @@
 
 #include <asm/vr41xx/vr41xx.h>
 
-EXPORT_SYMBOL(vr41xx_get_vtclock_frequency);
-EXPORT_SYMBOL(vr41xx_get_tclock_frequency);
-
 EXPORT_SYMBOL(vr41xx_set_rtclong1_cycle);
 EXPORT_SYMBOL(vr41xx_read_rtclong1_counter);
 EXPORT_SYMBOL(vr41xx_set_rtclong2_cycle);
diff -Nru a/arch/mips/vr41xx/common/serial.c b/arch/mips/vr41xx/common/serial.c
--- a/arch/mips/vr41xx/common/serial.c	2005-03-11 12:51:42 -08:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,178 +0,0 @@
-/*
- *  serial.c, Serial Interface Unit routines for NEC VR4100 series.
- *
- *  Copyright (C) 2002  MontaVista Software Inc.
- *    Author: Yoichi Yuasa <yyuasa@mvista.com or source@mvista.com>
- *  Copyright (C) 2003-2004  Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-/*
- * Changes:
- *  MontaVista Software Inc. <yyuasa@mvista.com> or <source@mvista.com>
- *  - New creation, NEC VR4122 and VR4131 are supported.
- *  - Added support for NEC VR4111 and VR4121.
- *
- *  Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
- *  - Added support for NEC VR4133.
- */
-#include <linux/init.h>
-#include <linux/types.h>
-#include <linux/tty.h>
-#include <linux/serial.h>
-#include <linux/serial_core.h>
-#include <linux/smp.h>
-
-#include <asm/addrspace.h>
-#include <asm/cpu.h>
-#include <asm/io.h>
-#include <asm/vr41xx/vr41xx.h>
-
-#define SIUIRSEL_TYPE1		KSEG1ADDR(0x0c000008)
-#define SIUIRSEL_TYPE2		KSEG1ADDR(0x0f000808)
- #define USE_RS232C		0x00
- #define USE_IRDA		0x01
- #define SIU_USES_IRDA		0x00
- #define FIR_USES_IRDA		0x02
- #define IRDA_MODULE_SHARP	0x00
- #define IRDA_MODULE_TEMIC	0x04
- #define IRDA_MODULE_HP		0x08
- #define TMICTX			0x10
- #define TMICMODE		0x20
-
-#define SIU_BASE_TYPE1		0x0c000000UL	/* VR4111 and VR4121 */
-#define SIU_BASE_TYPE2		0x0f000800UL	/* VR4122, VR4131 and VR4133 */
-#define SIU_SIZE		0x8UL
-
-#define SIU_BASE_BAUD		1152000
-
-/* VR4122, VR4131 and VR4133 DSIU Registers */
-#define DSIU_BASE		0x0f000820UL
-#define DSIU_SIZE		0x8UL
-
-#define DSIU_BASE_BAUD		1152000
-
-int vr41xx_serial_ports = 0;
-
-void vr41xx_select_siu_interface(siu_interface_t interface,
-                                 irda_module_t module)
-{
-	uint16_t val = USE_RS232C;	/* Select RS-232C */
-
-	/* Select IrDA */
-	if (interface == SIU_IRDA) {
-		switch (module) {
-		case IRDA_SHARP:
-			val = IRDA_MODULE_SHARP;
-			break;
-		case IRDA_TEMIC:
-			val = IRDA_MODULE_TEMIC;
-			break;
-		case IRDA_HP:
-			val = IRDA_MODULE_HP;
-			break;
-		default:
-			printk(KERN_ERR "SIU: unknown IrDA module\n");
-			return;
-		}
-		val |= USE_IRDA | SIU_USES_IRDA;
-	}
-
-	switch (current_cpu_data.cputype) {
-	case CPU_VR4111:
-	case CPU_VR4121:
-		writew(val, SIUIRSEL_TYPE1);
-		break;
-	case CPU_VR4122:
-	case CPU_VR4131:
-	case CPU_VR4133:
-		writew(val, SIUIRSEL_TYPE2);
-		break;
-	default:
-		printk(KERN_ERR "SIU: unsupported CPU of NEC VR4100 series\n");
-		break;
-	}
-}
-
-void __init vr41xx_siu_init(void)
-{
-	struct uart_port port;
-
-	memset(&port, 0, sizeof(port));
-
-	port.line = vr41xx_serial_ports;
-	port.uartclk = SIU_BASE_BAUD * 16;
-	port.irq = SIU_IRQ;
-	port.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST;
-	switch (current_cpu_data.cputype) {
-	case CPU_VR4111:
-	case CPU_VR4121:
-		port.mapbase = SIU_BASE_TYPE1;
-		break;
-	case CPU_VR4122:
-	case CPU_VR4131:
-	case CPU_VR4133:
-		port.mapbase = SIU_BASE_TYPE2;
-		break;
-	default:
-		printk(KERN_ERR "SIU: unsupported CPU of NEC VR4100 series\n");
-		return;
-	}
-	port.regshift = 0;
-	port.iotype = UPIO_MEM;
-	port.membase = ioremap(port.mapbase, SIU_SIZE);
-	if (port.membase != NULL) {
-		if (early_serial_setup(&port) == 0) {
-			vr41xx_supply_clock(SIU_CLOCK);
-			vr41xx_serial_ports++;
-			return;
-		}
-	}
-
-	printk(KERN_ERR "SIU: setup failed!\n");
-}
-
-void __init vr41xx_dsiu_init(void)
-{
-	struct uart_port port;
-
-	if (current_cpu_data.cputype != CPU_VR4122 &&
-	    current_cpu_data.cputype != CPU_VR4131 &&
-	    current_cpu_data.cputype != CPU_VR4133) {
-		printk(KERN_ERR "DSIU: unsupported CPU of NEC VR4100 series\n");
-		return;
-	}
-
-	memset(&port, 0, sizeof(port));
-
-	port.line = vr41xx_serial_ports;
-	port.uartclk = DSIU_BASE_BAUD * 16;
-	port.irq = DSIU_IRQ;
-	port.flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST;
-	port.mapbase = DSIU_BASE;
-	port.regshift = 0;
-	port.iotype = UPIO_MEM;
-	port.membase = ioremap(port.mapbase, DSIU_SIZE);
-	if (port.membase != NULL) {
-		if (early_serial_setup(&port) == 0) {
-			vr41xx_supply_clock(DSIU_CLOCK);
-			vr41xx_enable_dsiuint(DSIUINT_ALL);
-			vr41xx_serial_ports++;
-			return;
-		}
-	}
-
-	printk(KERN_ERR "DSIU: setup failed!\n");
-}
diff -Nru a/arch/mips/vr41xx/ibm-workpad/setup.c b/arch/mips/vr41xx/ibm-workpad/setup.c
--- a/arch/mips/vr41xx/ibm-workpad/setup.c	2005-03-11 12:51:52 -08:00
+++ b/arch/mips/vr41xx/ibm-workpad/setup.c	2005-03-11 12:51:52 -08:00
@@ -1,7 +1,7 @@
 /*
  *  setup.c, Setup for the IBM WorkPad z50.
  *
- *  Copyright (C) 2002-2004  Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
+ *  Copyright (C) 2002-2005  Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -17,7 +17,7 @@
  *  along with this program; if not, write to the Free Software
  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
-#include <linux/config.h>
+#include <linux/init.h>
 #include <linux/ioport.h>
 
 #include <asm/io.h>
@@ -28,18 +28,13 @@
 	return "IBM WorkPad z50";
 }
 
-static int ibm_workpad_setup(void)
+static int __init ibm_workpad_setup(void)
 {
 	set_io_port_base(IO_PORT_BASE);
 	ioport_resource.start = IO_PORT_RESOURCE_START;
 	ioport_resource.end = IO_PORT_RESOURCE_END;
 
-#ifdef CONFIG_SERIAL_8250
-	vr41xx_select_siu_interface(SIU_RS232C, IRDA_NONE);
-	vr41xx_siu_init();
-#endif
-
 	return 0;
 }
 
-early_initcall(ibm_workpad_setup);
+arch_initcall(ibm_workpad_setup);
diff -Nru a/arch/mips/vr41xx/nec-cmbvr4133/setup.c b/arch/mips/vr41xx/nec-cmbvr4133/setup.c
--- a/arch/mips/vr41xx/nec-cmbvr4133/setup.c	2005-03-11 12:51:52 -08:00
+++ b/arch/mips/vr41xx/nec-cmbvr4133/setup.c	2005-03-11 12:51:52 -08:00
@@ -16,7 +16,6 @@
  */
 #include <linux/config.h>
 #include <linux/init.h>
-#include <linux/console.h>
 #include <linux/ide.h>
 #include <linux/ioport.h>
 
@@ -55,15 +54,6 @@
 #define number_partitions (sizeof(cmbvr4133_mtd_parts)/sizeof(struct mtd_partition))
 #endif
 
-extern void (*late_time_init)(void);
-
-static void __init vr4133_serial_init(void)
-{
-	vr41xx_select_siu_interface(SIU_RS232C, IRDA_NONE);
-	vr41xx_siu_init();
-	vr41xx_dsiu_init();
-}
-
 extern void i8259_init(void);
 
 static int __init nec_cmbvr4133_setup(void)
@@ -77,8 +67,6 @@
 
 	mips_machgroup = MACH_GROUP_NEC_VR41XX;
 	mips_machtype = MACH_NEC_CMBVR4133;
-
-	late_time_init = vr4133_serial_init;
 
 #ifdef CONFIG_PCI
 #ifdef CONFIG_ROCKHOPPER
diff -Nru a/arch/mips/vr41xx/tanbac-tb0226/setup.c b/arch/mips/vr41xx/tanbac-tb0226/setup.c
--- a/arch/mips/vr41xx/tanbac-tb0226/setup.c	2005-03-11 12:51:42 -08:00
+++ b/arch/mips/vr41xx/tanbac-tb0226/setup.c	2005-03-11 12:51:42 -08:00
@@ -1,7 +1,7 @@
 /*
  *  setup.c, Setup for the TANBAC TB0226.
  *
- *  Copyright (C) 2002-2004  Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
+ *  Copyright (C) 2002-2005  Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -17,23 +17,8 @@
  *  along with this program; if not, write to the Free Software
  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
-#include <linux/config.h>
-
-#include <asm/vr41xx/vr41xx.h>
 
 const char *get_system_type(void)
 {
 	return "TANBAC TB0226";
 }
-
-static int tanbac_tb0226_setup(void)
-{
-#ifdef CONFIG_SERIAL_8250
-	vr41xx_select_siu_interface(SIU_RS232C, IRDA_NONE);
-	vr41xx_siu_init();
-#endif
-
-	return 0;
-}
-
-early_initcall(tanbac_tb0226_setup);
diff -Nru a/arch/mips/vr41xx/tanbac-tb0229/Makefile b/arch/mips/vr41xx/tanbac-tb0229/Makefile
--- a/arch/mips/vr41xx/tanbac-tb0229/Makefile	2005-03-11 12:51:47 -08:00
+++ b/arch/mips/vr41xx/tanbac-tb0229/Makefile	2005-03-11 12:51:47 -08:00
@@ -3,5 +3,3 @@
 #
 
 obj-y				:= setup.o
-
-obj-$(CONFIG_TANBAC_TB0219)	+= tb0219.o
diff -Nru a/arch/mips/vr41xx/tanbac-tb0229/setup.c b/arch/mips/vr41xx/tanbac-tb0229/setup.c
--- a/arch/mips/vr41xx/tanbac-tb0229/setup.c	2005-03-11 12:51:52 -08:00
+++ b/arch/mips/vr41xx/tanbac-tb0229/setup.c	2005-03-11 12:51:52 -08:00
@@ -1,7 +1,7 @@
 /*
  *  setup.c, Setup for the TANBAC TB0229 (VR4131DIMM)
  *
- *  Copyright (C) 2002-2004  Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
+ *  Copyright (C) 2002-2005  Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
  *
  *  Modified for TANBAC TB0229:
  *  Copyright (C) 2003  Megasolution Inc.  <matsu@megasolution.jp>
@@ -20,24 +20,8 @@
  *  along with this program; if not, write to the Free Software
  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
-#include <linux/config.h>
-
-#include <asm/vr41xx/vr41xx.h>
 
 const char *get_system_type(void)
 {
 	return "TANBAC TB0229";
 }
-
-static int tanbac_tb0229_setup(void)
-{
-#ifdef CONFIG_SERIAL_8250
-	vr41xx_select_siu_interface(SIU_RS232C, IRDA_NONE);
-	vr41xx_siu_init();
-	vr41xx_dsiu_init();
-#endif
-
-	return 0;
-}
-
-early_initcall(tanbac_tb0229_setup);
diff -Nru a/arch/mips/vr41xx/tanbac-tb0229/tb0219.c b/arch/mips/vr41xx/tanbac-tb0229/tb0219.c
--- a/arch/mips/vr41xx/tanbac-tb0229/tb0219.c	2005-03-11 12:51:42 -08:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,44 +0,0 @@
-/*
- *  tb0219.c, Setup for the TANBAC TB0219
- *
- *  Copyright (C) 2003  Megasolution Inc. <matsu@megasolution.jp>
- *  Copyright (C) 2004  Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-#include <linux/init.h>
-
-#include <asm/io.h>
-#include <asm/reboot.h>
-
-#define TB0219_RESET_REGS	KSEG1ADDR(0x0a00000e)
-
-#define tb0219_hard_reset()	writew(0, TB0219_RESET_REGS)
-
-static void tanbac_tb0219_restart(char *command)
-{
-	local_irq_disable();
-	tb0219_hard_reset();
-	while (1);
-}
-
-static int __init tanbac_tb0219_setup(void)
-{
-	_machine_restart = tanbac_tb0219_restart;
-
-	return 0;
-}
-
-early_initcall(tanbac_tb0219_setup);
diff -Nru a/arch/mips/vr41xx/victor-mpc30x/setup.c b/arch/mips/vr41xx/victor-mpc30x/setup.c
--- a/arch/mips/vr41xx/victor-mpc30x/setup.c	2005-03-11 12:51:47 -08:00
+++ b/arch/mips/vr41xx/victor-mpc30x/setup.c	2005-03-11 12:51:47 -08:00
@@ -1,7 +1,7 @@
 /*
  *  setup.c, Setup for the Victor MP-C303/304.
  *
- *  Copyright (C) 2002-2004  Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
+ *  Copyright (C) 2002-2005  Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -17,23 +17,8 @@
  *  along with this program; if not, write to the Free Software
  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
-#include <linux/config.h>
-
-#include <asm/vr41xx/vr41xx.h>
 
 const char *get_system_type(void)
 {
 	return "Victor MP-C303/304";
 }
-
-static int victor_mpc30x_setup(void)
-{
-#ifdef CONFIG_SERIAL_8250
-	vr41xx_select_siu_interface(SIU_RS232C, IRDA_NONE);
-	vr41xx_siu_init();
-#endif
-
-	return 0;
-}
-
-early_initcall(victor_mpc30x_setup);
diff -Nru a/arch/mips/vr41xx/zao-capcella/setup.c b/arch/mips/vr41xx/zao-capcella/setup.c
--- a/arch/mips/vr41xx/zao-capcella/setup.c	2005-03-11 12:51:42 -08:00
+++ b/arch/mips/vr41xx/zao-capcella/setup.c	2005-03-11 12:51:42 -08:00
@@ -1,7 +1,7 @@
 /*
  *  setup.c, Setup for the ZAO Networks Capcella.
  *
- *  Copyright (C) 2002-2004  Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
+ *  Copyright (C) 2002-2005  Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -17,24 +17,8 @@
  *  along with this program; if not, write to the Free Software
  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
-#include <linux/config.h>
-
-#include <asm/vr41xx/vr41xx.h>
 
 const char *get_system_type(void)
 {
 	return "ZAO Networks Capcella";
 }
-
-static int zao_capcella_setup(void)
-{
-#ifdef CONFIG_SERIAL_8250
-	vr41xx_select_siu_interface(SIU_RS232C, IRDA_NONE);
-	vr41xx_siu_init();
-	vr41xx_dsiu_init();
-#endif
-
-	return 0;
-}
-
-early_initcall(zao_capcella_setup);
diff -Nru a/arch/parisc/Kconfig b/arch/parisc/Kconfig
--- a/arch/parisc/Kconfig	2005-03-11 12:51:47 -08:00
+++ b/arch/parisc/Kconfig	2005-03-11 12:51:47 -08:00
@@ -6,8 +6,7 @@
 mainmenu "Linux/PA-RISC Kernel Configuration"
 
 config PARISC
-	bool
-	default y
+	def_bool y
 	help
 	  The PA-RISC microprocessor is designed by Hewlett-Packard and used
 	  in many of their workstations & servers (HP9000 700 and 800 series,
@@ -15,19 +14,16 @@
 	  at <http://www.parisc-linux.org/>.
 
 config MMU
-	bool
-	default y
+	def_bool y
 
 config STACK_GROWSUP
-	bool
-	default y
+	def_bool y
 
 config UID16
 	bool
 
 config RWSEM_GENERIC_SPINLOCK
-	bool
-	default y
+	def_bool y
 
 config RWSEM_XCHGADD_ALGORITHM
 	bool
@@ -111,7 +107,7 @@
 	def_bool y
 	depends on PA8X00
 
-config PARISC64
+config 64BIT
 	bool "64-bit kernel"
 	depends on PA8X00
 	help
@@ -124,9 +120,6 @@
 	  enable this option otherwise. The 64bit kernel is significantly bigger
 	  and slower than the 32bit one.
 
-config 64BIT
-	def_bool PARISC64
-
 config SMP
 	bool "Symmetric multi-processing support"
 	---help---
@@ -166,13 +159,12 @@
 	default n
 
 config COMPAT
-	bool
-	depends on PARISC64
-	default y
+	def_bool y
+	depends on 64BIT
 
 config HPUX
 	bool "Support for HP-UX binaries"
-	depends on !PARISC64
+	depends on !64BIT
 
 config NR_CPUS
 	int "Maximum number of CPUs (2-32)"
diff -Nru a/arch/parisc/Makefile b/arch/parisc/Makefile
--- a/arch/parisc/Makefile	2005-03-11 12:51:51 -08:00
+++ b/arch/parisc/Makefile	2005-03-11 12:51:51 -08:00
@@ -17,9 +17,12 @@
 # Mike Shaver, Helge Deller and Martin K. Petersen
 #
 NM		= sh $(srctree)/arch/parisc/nm
-ifdef CONFIG_PARISC64
+CHECKFLAGS	+= -D__hppa__=1
+
+ifdef CONFIG_64BIT
 CROSS_COMPILE	:= hppa64-linux-
 UTS_MACHINE	:= parisc64
+CHECKFLAGS	+= -D__LP64__=1 -m64
 else
 MACHINE := $(subst 64,,$(shell uname -m))
 ifneq ($(MACHINE),parisc)
@@ -65,8 +68,12 @@
 
 drivers-$(CONFIG_OPROFILE)		+= arch/parisc/oprofile/
 
+PALO := $(shell if which palo; then : ; \
+	elif [ -x /sbin/palo ]; then echo /sbin/palo; \
+	fi)
+
 palo: vmlinux
-	@if [ $$(palo -f /dev/null >/dev/null 2>&1 ; echo $$?) != 2 ]; then \
+	@if [ -x $PALO ]; then \
 		echo 'ERROR: Please install palo first (apt-get install palo)';\
 		echo 'or build it from source and install it somewhere in your $$PATH';\
 		false; \
@@ -78,7 +85,7 @@
 		echo 'WARNING: the "lifimage" file is now placed in this directory by default!'; \
 		false; \
 	fi
-	palo -f ./palo.conf
+	$(PALO) -f ./palo.conf
 
 oldpalo: vmlinux
 	export TOPDIR=`pwd`; \
diff -Nru a/arch/parisc/configs/a500_defconfig b/arch/parisc/configs/a500_defconfig
--- a/arch/parisc/configs/a500_defconfig	2005-03-11 12:51:41 -08:00
+++ b/arch/parisc/configs/a500_defconfig	2005-03-11 12:51:41 -08:00
@@ -1,12 +1,15 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.10-pa5
-# Wed Jan  5 13:22:34 2005
+# Linux kernel version: 2.6.11-rc4-pa1
+# Wed Feb 16 11:32:49 2005
 #
 CONFIG_PARISC=y
 CONFIG_MMU=y
 CONFIG_STACK_GROWSUP=y
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
 
 #
 # Code maturity level options
@@ -68,7 +71,6 @@
 CONFIG_PA8X00=y
 CONFIG_PA20=y
 CONFIG_PREFETCH=y
-CONFIG_PARISC64=y
 CONFIG_64BIT=y
 CONFIG_SMP=y
 CONFIG_HOTPLUG_CPU=y
@@ -87,16 +89,12 @@
 CONFIG_PCI_LBA=y
 CONFIG_IOSAPIC=y
 CONFIG_IOMMU_SBA=y
-# CONFIG_SUPERIO is not set
-# CONFIG_CHASSIS_LCD_LED is not set
-CONFIG_PDC_CHASSIS=y
 
 #
 # PCCARD (PCMCIA/CardBus) support
 #
 CONFIG_PCCARD=m
 # CONFIG_PCMCIA_DEBUG is not set
-# CONFIG_PCMCIA_OBSOLETE is not set
 CONFIG_PCMCIA=m
 CONFIG_CARDBUS=y
 
@@ -107,6 +105,7 @@
 CONFIG_PD6729=m
 CONFIG_I82092=m
 CONFIG_TCIC=m
+CONFIG_PCCARD_NONSTATIC=m
 
 #
 # PCI Hotplug Support
@@ -114,6 +113,14 @@
 # CONFIG_HOTPLUG_PCI is not set
 
 #
+# PA-RISC specific drivers
+#
+# CONFIG_SUPERIO is not set
+# CONFIG_CHASSIS_LCD_LED is not set
+CONFIG_PDC_CHASSIS=y
+CONFIG_PDC_STABLE=y
+
+#
 # Executable file formats
 #
 CONFIG_BINFMT_ELF=y
@@ -153,6 +160,7 @@
 # CONFIG_BLK_CPQ_CISS_DA is not set
 # CONFIG_BLK_DEV_DAC960 is not set
 CONFIG_BLK_DEV_UMEM=m
+# CONFIG_BLK_DEV_COW_COMMON is not set
 CONFIG_BLK_DEV_LOOP=y
 # CONFIG_BLK_DEV_CRYPTOLOOP is not set
 # CONFIG_BLK_DEV_NBD is not set
@@ -171,6 +179,7 @@
 CONFIG_IOSCHED_AS=y
 CONFIG_IOSCHED_DEADLINE=y
 CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
 
 #
 # ATA/ATAPI/MFM/RLL support
@@ -205,6 +214,7 @@
 #
 CONFIG_SCSI_SPI_ATTRS=y
 CONFIG_SCSI_FC_ATTRS=m
+CONFIG_SCSI_ISCSI_ATTRS=m
 
 #
 # SCSI low-level drivers
@@ -231,10 +241,10 @@
 # CONFIG_SCSI_INITIO is not set
 # CONFIG_SCSI_INIA100 is not set
 CONFIG_SCSI_SYM53C8XX_2=y
-CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=0
+CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1
 CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
 CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
-CONFIG_SCSI_SYM53C8XX_IOMAPPED=y
+# CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set
 # CONFIG_SCSI_IPR is not set
 # CONFIG_SCSI_PCI2000 is not set
 # CONFIG_SCSI_PCI2220I is not set
@@ -249,7 +259,6 @@
 CONFIG_SCSI_QLA2300=m
 CONFIG_SCSI_QLA2322=m
 CONFIG_SCSI_QLA6312=m
-CONFIG_SCSI_QLA6322=m
 # CONFIG_SCSI_DC395x is not set
 # CONFIG_SCSI_DC390T is not set
 CONFIG_SCSI_DEBUG=m
@@ -399,8 +408,6 @@
 CONFIG_IP_NF_ARPTABLES=m
 CONFIG_IP_NF_ARPFILTER=m
 CONFIG_IP_NF_ARP_MANGLE=m
-# CONFIG_IP_NF_COMPAT_IPCHAINS is not set
-# CONFIG_IP_NF_COMPAT_IPFWADM is not set
 CONFIG_XFRM=y
 CONFIG_XFRM_USER=m
 
@@ -465,7 +472,7 @@
 #
 CONFIG_NET_TULIP=y
 CONFIG_DE2104X=m
-CONFIG_TULIP=m
+CONFIG_TULIP=y
 # CONFIG_TULIP_MWI is not set
 CONFIG_TULIP_MMIO=y
 # CONFIG_TULIP_NAPI is not set
@@ -483,7 +490,6 @@
 # CONFIG_FORCEDETH is not set
 # CONFIG_DGRS is not set
 CONFIG_EEPRO100=m
-# CONFIG_EEPRO100_PIO is not set
 CONFIG_E100=m
 CONFIG_E100_NAPI=y
 # CONFIG_FEALNX is not set
@@ -524,6 +530,7 @@
 CONFIG_IXGB_NAPI=y
 CONFIG_S2IO=m
 CONFIG_S2IO_NAPI=y
+# CONFIG_2BUFF_MODE is not set
 
 #
 # Token Ring devices
@@ -691,7 +698,6 @@
 #
 # Ftape, the floppy tape device driver
 #
-# CONFIG_AGP is not set
 # CONFIG_DRM is not set
 
 #
@@ -733,9 +739,9 @@
 #
 # Console display driver support
 #
+CONFIG_DUMMY_CONSOLE=y
 CONFIG_DUMMY_CONSOLE_COLUMNS=160
 CONFIG_DUMMY_CONSOLE_ROWS=64
-CONFIG_DUMMY_CONSOLE=y
 
 #
 # Sound
@@ -764,6 +770,15 @@
 # CONFIG_MMC is not set
 
 #
+# InfiniBand support
+#
+CONFIG_INFINIBAND=m
+CONFIG_INFINIBAND_MTHCA=m
+# CONFIG_INFINIBAND_MTHCA_DEBUG is not set
+CONFIG_INFINIBAND_IPOIB=m
+# CONFIG_INFINIBAND_IPOIB_DEBUG is not set
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -775,10 +790,16 @@
 # CONFIG_REISERFS_FS is not set
 CONFIG_JFS_FS=m
 # CONFIG_JFS_POSIX_ACL is not set
+# CONFIG_JFS_SECURITY is not set
 # CONFIG_JFS_DEBUG is not set
 # CONFIG_JFS_STATISTICS is not set
 CONFIG_FS_POSIX_ACL=y
+
+#
+# XFS support
+#
 CONFIG_XFS_FS=m
+CONFIG_XFS_EXPORT=y
 # CONFIG_XFS_RT is not set
 # CONFIG_XFS_QUOTA is not set
 # CONFIG_XFS_SECURITY is not set
@@ -786,7 +807,7 @@
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
 # CONFIG_QUOTA is not set
-# CONFIG_DNOTIFY is not set
+CONFIG_DNOTIFY=y
 # CONFIG_AUTOFS_FS is not set
 CONFIG_AUTOFS4_FS=y
 
@@ -817,7 +838,8 @@
 CONFIG_SYSFS=y
 # CONFIG_DEVFS_FS is not set
 # CONFIG_DEVPTS_FS_XATTR is not set
-# CONFIG_TMPFS is not set
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_XATTR is not set
 # CONFIG_HUGETLBFS is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
@@ -935,6 +957,8 @@
 # CONFIG_DEBUG_SPINLOCK is not set
 # CONFIG_DEBUG_KOBJECT is not set
 # CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_IOREMAP is not set
+# CONFIG_DEBUG_FS is not set
 # CONFIG_DEBUG_RWLOCK is not set
 
 #
@@ -971,6 +995,10 @@
 CONFIG_CRYPTO_MICHAEL_MIC=m
 CONFIG_CRYPTO_CRC32C=m
 CONFIG_CRYPTO_TEST=m
+
+#
+# Hardware crypto devices
+#
 
 #
 # Library routines
diff -Nru a/arch/parisc/configs/n4000_defconfig b/arch/parisc/configs/n4000_defconfig
--- a/arch/parisc/configs/n4000_defconfig	2005-03-11 12:51:52 -08:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,927 +0,0 @@
-#
-# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.10-pa5
-# Wed Jan  5 13:40:36 2005
-#
-CONFIG_PARISC=y
-CONFIG_MMU=y
-CONFIG_STACK_GROWSUP=y
-CONFIG_RWSEM_GENERIC_SPINLOCK=y
-
-#
-# Code maturity level options
-#
-CONFIG_EXPERIMENTAL=y
-# CONFIG_CLEAN_COMPILE is not set
-CONFIG_BROKEN=y
-CONFIG_BROKEN_ON_SMP=y
-
-#
-# General setup
-#
-CONFIG_LOCALVERSION=""
-CONFIG_SWAP=y
-CONFIG_SYSVIPC=y
-CONFIG_POSIX_MQUEUE=y
-# CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_SYSCTL=y
-# CONFIG_AUDIT is not set
-CONFIG_LOG_BUF_SHIFT=16
-CONFIG_HOTPLUG=y
-CONFIG_KOBJECT_UEVENT=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_EMBEDDED=y
-CONFIG_KALLSYMS=y
-CONFIG_KALLSYMS_ALL=y
-# CONFIG_KALLSYMS_EXTRA_PASS is not set
-CONFIG_FUTEX=y
-CONFIG_EPOLL=y
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_SHMEM=y
-CONFIG_CC_ALIGN_FUNCTIONS=0
-CONFIG_CC_ALIGN_LABELS=0
-CONFIG_CC_ALIGN_LOOPS=0
-CONFIG_CC_ALIGN_JUMPS=0
-# CONFIG_TINY_SHMEM is not set
-
-#
-# Loadable module support
-#
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-CONFIG_MODULE_FORCE_UNLOAD=y
-CONFIG_OBSOLETE_MODPARM=y
-# CONFIG_MODVERSIONS is not set
-# CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_KMOD=y
-
-#
-# Processor type and features
-#
-# CONFIG_PA7000 is not set
-# CONFIG_PA7100LC is not set
-# CONFIG_PA7200 is not set
-# CONFIG_PA7300LC is not set
-CONFIG_PA8X00=y
-CONFIG_PA20=y
-CONFIG_PREFETCH=y
-CONFIG_PARISC64=y
-CONFIG_64BIT=y
-# CONFIG_SMP is not set
-CONFIG_DISCONTIGMEM=y
-# CONFIG_PREEMPT is not set
-CONFIG_COMPAT=y
-
-#
-# Bus options (PCI, PCMCIA, EISA, GSC, ISA)
-#
-# CONFIG_GSC is not set
-CONFIG_PCI=y
-CONFIG_PCI_LEGACY_PROC=y
-CONFIG_PCI_NAMES=y
-CONFIG_PCI_LBA=y
-CONFIG_IOSAPIC=y
-CONFIG_IOMMU_SBA=y
-# CONFIG_SUPERIO is not set
-CONFIG_CHASSIS_LCD_LED=y
-# CONFIG_PDC_CHASSIS is not set
-
-#
-# PCCARD (PCMCIA/CardBus) support
-#
-# CONFIG_PCCARD is not set
-
-#
-# PC-card bridges
-#
-
-#
-# PCI Hotplug Support
-#
-# CONFIG_HOTPLUG_PCI is not set
-
-#
-# Executable file formats
-#
-CONFIG_BINFMT_ELF=y
-# CONFIG_BINFMT_MISC is not set
-
-#
-# Device Drivers
-#
-
-#
-# Generic Driver Options
-#
-# CONFIG_STANDALONE is not set
-# CONFIG_PREVENT_FIRMWARE_BUILD is not set
-CONFIG_FW_LOADER=y
-# CONFIG_DEBUG_DRIVER is not set
-
-#
-# Memory Technology Devices (MTD)
-#
-# CONFIG_MTD is not set
-
-#
-# Parallel port support
-#
-# CONFIG_PARPORT is not set
-
-#
-# Plug and Play support
-#
-
-#
-# Block devices
-#
-# CONFIG_BLK_DEV_FD is not set
-# CONFIG_BLK_CPQ_DA is not set
-# CONFIG_BLK_CPQ_CISS_DA is not set
-# CONFIG_BLK_DEV_DAC960 is not set
-CONFIG_BLK_DEV_UMEM=m
-CONFIG_BLK_DEV_LOOP=y
-# CONFIG_BLK_DEV_CRYPTOLOOP is not set
-# CONFIG_BLK_DEV_NBD is not set
-# CONFIG_BLK_DEV_SX8 is not set
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_COUNT=16
-CONFIG_BLK_DEV_RAM_SIZE=6144
-CONFIG_BLK_DEV_INITRD=y
-CONFIG_INITRAMFS_SOURCE=""
-CONFIG_CDROM_PKTCDVD=m
-CONFIG_CDROM_PKTCDVD_BUFFERS=8
-# CONFIG_CDROM_PKTCDVD_WCACHE is not set
-
-#
-# IO Schedulers
-#
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
-# CONFIG_IDE is not set
-
-#
-# SCSI device support
-#
-CONFIG_SCSI=y
-CONFIG_SCSI_PROC_FS=y
-
-#
-# SCSI support type (disk, tape, CD-ROM)
-#
-CONFIG_BLK_DEV_SD=y
-CONFIG_CHR_DEV_ST=y
-# CONFIG_CHR_DEV_OSST is not set
-CONFIG_BLK_DEV_SR=y
-# CONFIG_BLK_DEV_SR_VENDOR is not set
-CONFIG_CHR_DEV_SG=y
-
-#
-# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
-#
-CONFIG_SCSI_MULTI_LUN=y
-# CONFIG_SCSI_CONSTANTS is not set
-# CONFIG_SCSI_LOGGING is not set
-
-#
-# SCSI Transport Attributes
-#
-CONFIG_SCSI_SPI_ATTRS=y
-CONFIG_SCSI_FC_ATTRS=m
-
-#
-# SCSI low-level drivers
-#
-# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
-# CONFIG_SCSI_3W_9XXX is not set
-# CONFIG_SCSI_ACARD is not set
-# CONFIG_SCSI_AACRAID is not set
-# CONFIG_SCSI_AIC7XXX is not set
-# CONFIG_SCSI_AIC7XXX_OLD is not set
-# CONFIG_SCSI_AIC79XX is not set
-# CONFIG_SCSI_ADVANSYS is not set
-# CONFIG_MEGARAID_NEWGEN is not set
-# CONFIG_MEGARAID_LEGACY is not set
-# CONFIG_SCSI_SATA is not set
-# CONFIG_SCSI_BUSLOGIC is not set
-# CONFIG_SCSI_CPQFCTS is not set
-# CONFIG_SCSI_DMX3191D is not set
-# CONFIG_SCSI_EATA is not set
-# CONFIG_SCSI_EATA_PIO is not set
-# CONFIG_SCSI_FUTURE_DOMAIN is not set
-# CONFIG_SCSI_GDTH is not set
-# CONFIG_SCSI_IPS is not set
-# CONFIG_SCSI_INITIO is not set
-# CONFIG_SCSI_INIA100 is not set
-CONFIG_SCSI_SYM53C8XX_2=y
-CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=0
-CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
-CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
-CONFIG_SCSI_SYM53C8XX_IOMAPPED=y
-# CONFIG_SCSI_IPR is not set
-# CONFIG_SCSI_PCI2000 is not set
-# CONFIG_SCSI_PCI2220I is not set
-# CONFIG_SCSI_QLOGIC_ISP is not set
-CONFIG_SCSI_QLOGIC_FC=m
-# CONFIG_SCSI_QLOGIC_FC_FIRMWARE is not set
-CONFIG_SCSI_QLOGIC_1280=m
-# CONFIG_SCSI_QLOGIC_1280_1040 is not set
-CONFIG_SCSI_QLA2XXX=y
-# CONFIG_SCSI_QLA21XX is not set
-# CONFIG_SCSI_QLA22XX is not set
-CONFIG_SCSI_QLA2300=m
-CONFIG_SCSI_QLA2322=m
-CONFIG_SCSI_QLA6312=m
-CONFIG_SCSI_QLA6322=m
-# CONFIG_SCSI_DC395x is not set
-# CONFIG_SCSI_DC390T is not set
-CONFIG_SCSI_DEBUG=m
-
-#
-# Multi-device support (RAID and LVM)
-#
-CONFIG_MD=y
-CONFIG_BLK_DEV_MD=y
-CONFIG_MD_LINEAR=y
-CONFIG_MD_RAID0=y
-CONFIG_MD_RAID1=y
-# CONFIG_MD_RAID10 is not set
-# CONFIG_MD_RAID5 is not set
-# CONFIG_MD_RAID6 is not set
-# CONFIG_MD_MULTIPATH is not set
-# CONFIG_MD_FAULTY is not set
-# CONFIG_BLK_DEV_DM is not set
-
-#
-# Fusion MPT device support
-#
-CONFIG_FUSION=m
-CONFIG_FUSION_MAX_SGE=40
-CONFIG_FUSION_CTL=m
-
-#
-# IEEE 1394 (FireWire) support
-#
-# CONFIG_IEEE1394 is not set
-
-#
-# I2O device support
-#
-# CONFIG_I2O is not set
-
-#
-# Networking support
-#
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-CONFIG_PACKET_MMAP=y
-CONFIG_NETLINK_DEV=y
-CONFIG_UNIX=y
-CONFIG_NET_KEY=m
-CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-CONFIG_IP_PNP_BOOTP=y
-# CONFIG_IP_PNP_RARP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_IP_MROUTE is not set
-# CONFIG_ARPD is not set
-# CONFIG_SYN_COOKIES is not set
-CONFIG_INET_AH=m
-CONFIG_INET_ESP=m
-# CONFIG_INET_IPCOMP is not set
-# CONFIG_INET_TUNNEL is not set
-CONFIG_IP_TCPDIAG=y
-# CONFIG_IP_TCPDIAG_IPV6 is not set
-
-#
-# IP: Virtual Server Configuration
-#
-# CONFIG_IP_VS is not set
-# CONFIG_IPV6 is not set
-CONFIG_NETFILTER=y
-# CONFIG_NETFILTER_DEBUG is not set
-
-#
-# IP: Netfilter Configuration
-#
-CONFIG_IP_NF_CONNTRACK=m
-# CONFIG_IP_NF_CT_ACCT is not set
-# CONFIG_IP_NF_CONNTRACK_MARK is not set
-# CONFIG_IP_NF_CT_PROTO_SCTP is not set
-CONFIG_IP_NF_FTP=m
-CONFIG_IP_NF_IRC=m
-CONFIG_IP_NF_TFTP=m
-CONFIG_IP_NF_AMANDA=m
-CONFIG_IP_NF_QUEUE=m
-CONFIG_IP_NF_IPTABLES=m
-CONFIG_IP_NF_MATCH_LIMIT=m
-CONFIG_IP_NF_MATCH_IPRANGE=m
-CONFIG_IP_NF_MATCH_MAC=m
-CONFIG_IP_NF_MATCH_PKTTYPE=m
-CONFIG_IP_NF_MATCH_MARK=m
-CONFIG_IP_NF_MATCH_MULTIPORT=m
-CONFIG_IP_NF_MATCH_TOS=m
-CONFIG_IP_NF_MATCH_RECENT=m
-CONFIG_IP_NF_MATCH_ECN=m
-CONFIG_IP_NF_MATCH_DSCP=m
-CONFIG_IP_NF_MATCH_AH_ESP=m
-CONFIG_IP_NF_MATCH_LENGTH=m
-CONFIG_IP_NF_MATCH_TTL=m
-CONFIG_IP_NF_MATCH_TCPMSS=m
-CONFIG_IP_NF_MATCH_HELPER=m
-CONFIG_IP_NF_MATCH_STATE=m
-CONFIG_IP_NF_MATCH_CONNTRACK=m
-CONFIG_IP_NF_MATCH_OWNER=m
-CONFIG_IP_NF_MATCH_ADDRTYPE=m
-CONFIG_IP_NF_MATCH_REALM=m
-CONFIG_IP_NF_MATCH_SCTP=m
-CONFIG_IP_NF_MATCH_COMMENT=m
-CONFIG_IP_NF_MATCH_HASHLIMIT=m
-CONFIG_IP_NF_FILTER=m
-CONFIG_IP_NF_TARGET_REJECT=m
-CONFIG_IP_NF_TARGET_LOG=m
-CONFIG_IP_NF_TARGET_ULOG=m
-CONFIG_IP_NF_TARGET_TCPMSS=m
-CONFIG_IP_NF_NAT=m
-CONFIG_IP_NF_NAT_NEEDED=y
-CONFIG_IP_NF_TARGET_MASQUERADE=m
-CONFIG_IP_NF_TARGET_REDIRECT=m
-CONFIG_IP_NF_TARGET_NETMAP=m
-CONFIG_IP_NF_TARGET_SAME=m
-CONFIG_IP_NF_NAT_SNMP_BASIC=m
-CONFIG_IP_NF_NAT_IRC=m
-CONFIG_IP_NF_NAT_FTP=m
-CONFIG_IP_NF_NAT_TFTP=m
-CONFIG_IP_NF_NAT_AMANDA=m
-CONFIG_IP_NF_MANGLE=m
-CONFIG_IP_NF_TARGET_TOS=m
-CONFIG_IP_NF_TARGET_ECN=m
-CONFIG_IP_NF_TARGET_DSCP=m
-CONFIG_IP_NF_TARGET_MARK=m
-CONFIG_IP_NF_TARGET_CLASSIFY=m
-CONFIG_IP_NF_RAW=m
-CONFIG_IP_NF_TARGET_NOTRACK=m
-CONFIG_IP_NF_ARPTABLES=m
-CONFIG_IP_NF_ARPFILTER=m
-CONFIG_IP_NF_ARP_MANGLE=m
-# CONFIG_IP_NF_COMPAT_IPCHAINS is not set
-# CONFIG_IP_NF_COMPAT_IPFWADM is not set
-CONFIG_XFRM=y
-CONFIG_XFRM_USER=m
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_SCTP is not set
-# CONFIG_ATM is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_DECNET is not set
-CONFIG_LLC=m
-CONFIG_LLC2=m
-# CONFIG_IPX is not set
-# CONFIG_ATALK is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-CONFIG_NET_CLS_ROUTE=y
-
-#
-# Network testing
-#
-CONFIG_NET_PKTGEN=m
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-# CONFIG_HAMRADIO is not set
-# CONFIG_IRDA is not set
-# CONFIG_BT is not set
-CONFIG_NETDEVICES=y
-CONFIG_DUMMY=m
-CONFIG_BONDING=m
-# CONFIG_EQUALIZER is not set
-CONFIG_TUN=m
-# CONFIG_ETHERTAP is not set
-
-#
-# ARCnet devices
-#
-# CONFIG_ARCNET is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
-CONFIG_NET_ETHERNET=y
-CONFIG_MII=m
-# CONFIG_HAPPYMEAL is not set
-# CONFIG_SUNGEM is not set
-CONFIG_NET_VENDOR_3COM=y
-CONFIG_VORTEX=m
-CONFIG_TYPHOON=m
-
-#
-# Tulip family network device support
-#
-CONFIG_NET_TULIP=y
-CONFIG_DE2104X=y
-CONFIG_TULIP=y
-# CONFIG_TULIP_MWI is not set
-CONFIG_TULIP_MMIO=y
-# CONFIG_TULIP_NAPI is not set
-# CONFIG_DE4X5 is not set
-# CONFIG_WINBOND_840 is not set
-# CONFIG_DM9102 is not set
-CONFIG_HP100=m
-CONFIG_NET_PCI=y
-CONFIG_PCNET32=m
-# CONFIG_AMD8111_ETH is not set
-# CONFIG_ADAPTEC_STARFIRE is not set
-# CONFIG_B44 is not set
-# CONFIG_FORCEDETH is not set
-# CONFIG_DGRS is not set
-CONFIG_EEPRO100=m
-# CONFIG_EEPRO100_PIO is not set
-CONFIG_E100=m
-CONFIG_E100_NAPI=y
-# CONFIG_FEALNX is not set
-CONFIG_NATSEMI=m
-# CONFIG_NE2K_PCI is not set
-# CONFIG_8139CP is not set
-CONFIG_8139TOO=m
-# CONFIG_8139TOO_PIO is not set
-# CONFIG_8139TOO_TUNE_TWISTER is not set
-# CONFIG_8139TOO_8129 is not set
-# CONFIG_8139_OLD_RX_RESET is not set
-# CONFIG_SIS900 is not set
-CONFIG_EPIC100=m
-# CONFIG_SUNDANCE is not set
-CONFIG_VIA_RHINE=m
-CONFIG_VIA_RHINE_MMIO=y
-
-#
-# Ethernet (1000 Mbit)
-#
-CONFIG_ACENIC=m
-CONFIG_ACENIC_OMIT_TIGON_I=y
-CONFIG_DL2K=m
-CONFIG_E1000=m
-CONFIG_E1000_NAPI=y
-# CONFIG_NS83820 is not set
-# CONFIG_HAMACHI is not set
-# CONFIG_YELLOWFIN is not set
-# CONFIG_R8169 is not set
-# CONFIG_SK98LIN is not set
-# CONFIG_VIA_VELOCITY is not set
-CONFIG_TIGON3=m
-
-#
-# Ethernet (10000 Mbit)
-#
-CONFIG_IXGB=m
-CONFIG_IXGB_NAPI=y
-CONFIG_S2IO=m
-CONFIG_S2IO_NAPI=y
-
-#
-# Token Ring devices
-#
-# CONFIG_TR is not set
-
-#
-# Wireless LAN (non-hamradio)
-#
-CONFIG_NET_RADIO=y
-
-#
-# Obsolete Wireless cards support (pre-802.11)
-#
-# CONFIG_STRIP is not set
-
-#
-# Wireless 802.11b ISA/PCI cards support
-#
-CONFIG_HERMES=m
-CONFIG_PLX_HERMES=m
-CONFIG_TMD_HERMES=m
-CONFIG_PCI_HERMES=m
-# CONFIG_ATMEL is not set
-
-#
-# Prism GT/Duette 802.11(a/b/g) PCI/Cardbus support
-#
-# CONFIG_PRISM54 is not set
-CONFIG_NET_WIRELESS=y
-
-#
-# Wan interfaces
-#
-# CONFIG_WAN is not set
-# CONFIG_FDDI is not set
-# CONFIG_HIPPI is not set
-CONFIG_PPP=m
-# CONFIG_PPP_MULTILINK is not set
-# CONFIG_PPP_FILTER is not set
-CONFIG_PPP_ASYNC=m
-CONFIG_PPP_SYNC_TTY=m
-CONFIG_PPP_DEFLATE=m
-CONFIG_PPP_BSDCOMP=m
-# CONFIG_PPPOE is not set
-# CONFIG_SLIP is not set
-# CONFIG_NET_FC is not set
-# CONFIG_SHAPER is not set
-# CONFIG_NETCONSOLE is not set
-
-#
-# ISDN subsystem
-#
-# CONFIG_ISDN is not set
-
-#
-# Telephony Support
-#
-# CONFIG_PHONE is not set
-
-#
-# Input device support
-#
-CONFIG_INPUT=y
-
-#
-# Userland interfaces
-#
-# CONFIG_INPUT_MOUSEDEV is not set
-# CONFIG_INPUT_JOYDEV is not set
-# CONFIG_INPUT_TSDEV is not set
-# CONFIG_INPUT_EVDEV is not set
-# CONFIG_INPUT_EVBUG is not set
-
-#
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-# CONFIG_SERIO is not set
-
-#
-# Input Device Drivers
-#
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_INPUT_JOYSTICK is not set
-# CONFIG_INPUT_TOUCHSCREEN is not set
-# CONFIG_INPUT_MISC is not set
-
-#
-# Character devices
-#
-CONFIG_VT=y
-CONFIG_VT_CONSOLE=y
-CONFIG_HW_CONSOLE=y
-# CONFIG_SERIAL_NONSTANDARD is not set
-
-#
-# Serial drivers
-#
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_SERIAL_8250_NR_UARTS=8
-CONFIG_SERIAL_8250_EXTENDED=y
-CONFIG_SERIAL_8250_MANY_PORTS=y
-CONFIG_SERIAL_8250_SHARE_IRQ=y
-# CONFIG_SERIAL_8250_DETECT_IRQ is not set
-# CONFIG_SERIAL_8250_MULTIPORT is not set
-# CONFIG_SERIAL_8250_RSA is not set
-
-#
-# Non-8250 serial port support
-#
-# CONFIG_SERIAL_MUX is not set
-CONFIG_PDC_CONSOLE=y
-CONFIG_SERIAL_CORE=y
-CONFIG_SERIAL_CORE_CONSOLE=y
-CONFIG_UNIX98_PTYS=y
-# CONFIG_LEGACY_PTYS is not set
-
-#
-# IPMI
-#
-# CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
-# CONFIG_WATCHDOG is not set
-CONFIG_GEN_RTC=y
-CONFIG_GEN_RTC_X=y
-# CONFIG_DTLK is not set
-# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
-# CONFIG_AGP is not set
-# CONFIG_DRM is not set
-CONFIG_RAW_DRIVER=y
-CONFIG_MAX_RAW_DEVS=256
-
-#
-# I2C support
-#
-# CONFIG_I2C is not set
-
-#
-# Dallas's 1-wire bus
-#
-# CONFIG_W1 is not set
-
-#
-# Misc devices
-#
-
-#
-# Multimedia devices
-#
-# CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
-
-#
-# Graphics support
-#
-# CONFIG_FB is not set
-
-#
-# Console display driver support
-#
-CONFIG_DUMMY_CONSOLE_COLUMNS=160
-CONFIG_DUMMY_CONSOLE_ROWS=64
-CONFIG_DUMMY_CONSOLE=y
-
-#
-# Sound
-#
-# CONFIG_SOUND is not set
-
-#
-# USB support
-#
-# CONFIG_USB is not set
-CONFIG_USB_ARCH_HAS_HCD=y
-CONFIG_USB_ARCH_HAS_OHCI=y
-
-#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
-#
-
-#
-# USB Gadget Support
-#
-# CONFIG_USB_GADGET is not set
-
-#
-# MMC/SD Card support
-#
-# CONFIG_MMC is not set
-
-#
-# File systems
-#
-CONFIG_EXT2_FS=y
-# CONFIG_EXT2_FS_XATTR is not set
-CONFIG_EXT3_FS=y
-# CONFIG_EXT3_FS_XATTR is not set
-CONFIG_JBD=y
-# CONFIG_JBD_DEBUG is not set
-# CONFIG_REISERFS_FS is not set
-CONFIG_JFS_FS=m
-# CONFIG_JFS_POSIX_ACL is not set
-# CONFIG_JFS_DEBUG is not set
-# CONFIG_JFS_STATISTICS is not set
-CONFIG_FS_POSIX_ACL=y
-CONFIG_XFS_FS=m
-# CONFIG_XFS_RT is not set
-# CONFIG_XFS_QUOTA is not set
-# CONFIG_XFS_SECURITY is not set
-# CONFIG_XFS_POSIX_ACL is not set
-# CONFIG_MINIX_FS is not set
-# CONFIG_ROMFS_FS is not set
-# CONFIG_QUOTA is not set
-# CONFIG_DNOTIFY is not set
-# CONFIG_AUTOFS_FS is not set
-CONFIG_AUTOFS4_FS=y
-
-#
-# CD-ROM/DVD Filesystems
-#
-CONFIG_ISO9660_FS=y
-CONFIG_JOLIET=y
-# CONFIG_ZISOFS is not set
-CONFIG_UDF_FS=m
-CONFIG_UDF_NLS=y
-
-#
-# DOS/FAT/NT Filesystems
-#
-CONFIG_FAT_FS=m
-CONFIG_MSDOS_FS=m
-CONFIG_VFAT_FS=m
-CONFIG_FAT_DEFAULT_CODEPAGE=437
-CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
-# CONFIG_NTFS_FS is not set
-
-#
-# Pseudo filesystems
-#
-CONFIG_PROC_FS=y
-CONFIG_PROC_KCORE=y
-CONFIG_SYSFS=y
-# CONFIG_DEVFS_FS is not set
-# CONFIG_DEVPTS_FS_XATTR is not set
-CONFIG_TMPFS=y
-# CONFIG_TMPFS_XATTR is not set
-# CONFIG_HUGETLBFS is not set
-# CONFIG_HUGETLB_PAGE is not set
-CONFIG_RAMFS=y
-
-#
-# Miscellaneous filesystems
-#
-# CONFIG_ADFS_FS is not set
-# CONFIG_AFFS_FS is not set
-# CONFIG_HFS_FS is not set
-# CONFIG_HFSPLUS_FS is not set
-# CONFIG_BEFS_FS is not set
-# CONFIG_BFS_FS is not set
-# CONFIG_EFS_FS is not set
-# CONFIG_CRAMFS is not set
-# CONFIG_VXFS_FS is not set
-# CONFIG_HPFS_FS is not set
-# CONFIG_QNX4FS_FS is not set
-# CONFIG_SYSV_FS is not set
-CONFIG_UFS_FS=m
-# CONFIG_UFS_FS_WRITE is not set
-
-#
-# Network File Systems
-#
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
-CONFIG_NFS_V4=y
-CONFIG_NFS_DIRECTIO=y
-CONFIG_NFSD=m
-CONFIG_NFSD_V3=y
-CONFIG_NFSD_V4=y
-CONFIG_NFSD_TCP=y
-CONFIG_ROOT_NFS=y
-CONFIG_LOCKD=y
-CONFIG_LOCKD_V4=y
-CONFIG_EXPORTFS=m
-CONFIG_SUNRPC=y
-CONFIG_SUNRPC_GSS=y
-CONFIG_RPCSEC_GSS_KRB5=y
-# CONFIG_RPCSEC_GSS_SPKM3 is not set
-CONFIG_SMB_FS=m
-CONFIG_SMB_NLS_DEFAULT=y
-CONFIG_SMB_NLS_REMOTE="cp437"
-CONFIG_CIFS=m
-# CONFIG_CIFS_STATS is not set
-# CONFIG_CIFS_XATTR is not set
-# CONFIG_CIFS_EXPERIMENTAL is not set
-# CONFIG_NCP_FS is not set
-# CONFIG_CODA_FS is not set
-# CONFIG_AFS_FS is not set
-
-#
-# Partition Types
-#
-# CONFIG_PARTITION_ADVANCED is not set
-CONFIG_MSDOS_PARTITION=y
-
-#
-# Native Language Support
-#
-CONFIG_NLS=y
-CONFIG_NLS_DEFAULT="iso8859-1"
-CONFIG_NLS_CODEPAGE_437=m
-# CONFIG_NLS_CODEPAGE_737 is not set
-# CONFIG_NLS_CODEPAGE_775 is not set
-CONFIG_NLS_CODEPAGE_850=m
-CONFIG_NLS_CODEPAGE_852=m
-# CONFIG_NLS_CODEPAGE_855 is not set
-# CONFIG_NLS_CODEPAGE_857 is not set
-# CONFIG_NLS_CODEPAGE_860 is not set
-# CONFIG_NLS_CODEPAGE_861 is not set
-# CONFIG_NLS_CODEPAGE_862 is not set
-CONFIG_NLS_CODEPAGE_863=m
-# CONFIG_NLS_CODEPAGE_864 is not set
-CONFIG_NLS_CODEPAGE_865=m
-# CONFIG_NLS_CODEPAGE_866 is not set
-# CONFIG_NLS_CODEPAGE_869 is not set
-# CONFIG_NLS_CODEPAGE_936 is not set
-# CONFIG_NLS_CODEPAGE_950 is not set
-# CONFIG_NLS_CODEPAGE_932 is not set
-# CONFIG_NLS_CODEPAGE_949 is not set
-# CONFIG_NLS_CODEPAGE_874 is not set
-# CONFIG_NLS_ISO8859_8 is not set
-# CONFIG_NLS_CODEPAGE_1250 is not set
-# CONFIG_NLS_CODEPAGE_1251 is not set
-# CONFIG_NLS_ASCII is not set
-CONFIG_NLS_ISO8859_1=m
-CONFIG_NLS_ISO8859_2=m
-CONFIG_NLS_ISO8859_3=m
-CONFIG_NLS_ISO8859_4=m
-# CONFIG_NLS_ISO8859_5 is not set
-# CONFIG_NLS_ISO8859_6 is not set
-# CONFIG_NLS_ISO8859_7 is not set
-# CONFIG_NLS_ISO8859_9 is not set
-# CONFIG_NLS_ISO8859_13 is not set
-# CONFIG_NLS_ISO8859_14 is not set
-CONFIG_NLS_ISO8859_15=m
-# CONFIG_NLS_KOI8_R is not set
-# CONFIG_NLS_KOI8_U is not set
-CONFIG_NLS_UTF8=m
-
-#
-# Profiling support
-#
-CONFIG_PROFILING=y
-CONFIG_OPROFILE=m
-
-#
-# Kernel hacking
-#
-CONFIG_DEBUG_KERNEL=y
-CONFIG_MAGIC_SYSRQ=y
-# CONFIG_SCHEDSTATS is not set
-# CONFIG_DEBUG_SLAB is not set
-# CONFIG_DEBUG_SPINLOCK is not set
-# CONFIG_DEBUG_KOBJECT is not set
-# CONFIG_DEBUG_INFO is not set
-
-#
-# Security options
-#
-# CONFIG_KEYS is not set
-# CONFIG_SECURITY is not set
-
-#
-# Cryptographic options
-#
-CONFIG_CRYPTO=y
-CONFIG_CRYPTO_HMAC=y
-CONFIG_CRYPTO_NULL=m
-CONFIG_CRYPTO_MD4=m
-CONFIG_CRYPTO_MD5=y
-CONFIG_CRYPTO_SHA1=m
-CONFIG_CRYPTO_SHA256=m
-CONFIG_CRYPTO_SHA512=m
-CONFIG_CRYPTO_WP512=m
-CONFIG_CRYPTO_DES=y
-CONFIG_CRYPTO_BLOWFISH=m
-CONFIG_CRYPTO_TWOFISH=m
-CONFIG_CRYPTO_SERPENT=m
-CONFIG_CRYPTO_AES=m
-CONFIG_CRYPTO_CAST5=m
-CONFIG_CRYPTO_CAST6=m
-CONFIG_CRYPTO_TEA=m
-# CONFIG_CRYPTO_ARC4 is not set
-CONFIG_CRYPTO_KHAZAD=m
-CONFIG_CRYPTO_ANUBIS=m
-CONFIG_CRYPTO_DEFLATE=m
-# CONFIG_CRYPTO_MICHAEL_MIC is not set
-CONFIG_CRYPTO_CRC32C=m
-CONFIG_CRYPTO_TEST=m
-
-#
-# Library routines
-#
-CONFIG_CRC_CCITT=m
-CONFIG_CRC32=y
-CONFIG_LIBCRC32C=m
-CONFIG_ZLIB_INFLATE=m
-CONFIG_ZLIB_DEFLATE=m
diff -Nru a/arch/parisc/kernel/Makefile b/arch/parisc/kernel/Makefile
--- a/arch/parisc/kernel/Makefile	2005-03-11 12:51:42 -08:00
+++ b/arch/parisc/kernel/Makefile	2005-03-11 12:51:42 -08:00
@@ -19,6 +19,6 @@
 obj-$(CONFIG_PA11)	+= pci-dma.o
 obj-$(CONFIG_PCI)	+= pci.o
 obj-$(CONFIG_MODULES)	+= module.o
-obj-$(CONFIG_PARISC64)	+= binfmt_elf32.o sys_parisc32.o ioctl32.o signal32.o
+obj-$(CONFIG_64BIT)	+= binfmt_elf32.o sys_parisc32.o ioctl32.o signal32.o
 # only supported for PCX-W/U in 64-bit mode at the moment
-obj-$(CONFIG_PARISC64)	+= perf.o perf_asm.o
+obj-$(CONFIG_64BIT)	+= perf.o perf_asm.o
diff -Nru a/arch/parisc/kernel/binfmt_elf32.c b/arch/parisc/kernel/binfmt_elf32.c
--- a/arch/parisc/kernel/binfmt_elf32.c	2005-03-11 12:51:42 -08:00
+++ b/arch/parisc/kernel/binfmt_elf32.c	2005-03-11 12:51:42 -08:00
@@ -37,7 +37,6 @@
 #include <linux/spinlock.h>
 #include <asm/processor.h>
 #include <linux/module.h>
-#include <linux/config.h>
 #include <linux/elfcore.h>
 #include <linux/compat.h>		/* struct compat_timeval */
 
diff -Nru a/arch/parisc/kernel/drivers.c b/arch/parisc/kernel/drivers.c
--- a/arch/parisc/kernel/drivers.c	2005-03-11 12:51:51 -08:00
+++ b/arch/parisc/kernel/drivers.c	2005-03-11 12:51:51 -08:00
@@ -10,7 +10,7 @@
  * Copyright (c) 2001 Matthew Wilcox for Hewlett Packard
  * Copyright (c) 2001 Helge Deller <deller@gmx.de>
  * Copyright (c) 2001,2002 Ryan Bradetich 
- * Copyright (c) 2004 Thibaut VARENE <varenet@parisc-linux.org>
+ * Copyright (c) 2004-2005 Thibaut VARENE <varenet@parisc-linux.org>
  * 
  * The file handles registering devices and drivers, then matching them.
  * It's the closest we get to a dating agency.
@@ -610,6 +610,24 @@
 		return parse_tree_node(parent, 6, modpath);
 }
 EXPORT_SYMBOL(hwpath_to_device);
+
+/**
+ * device_to_hwpath - Populates the hwpath corresponding to the given device.
+ * @param dev the target device
+ * @param path pointer to a previously allocated hwpath struct to be filled in
+ */
+void device_to_hwpath(struct device *dev, struct hardware_path *path)
+{
+	struct parisc_device *padev;
+	if (dev->bus == &parisc_bus_type) {
+		padev = to_parisc_device(dev);
+		get_node_path(dev->parent, path);
+		path->mod = padev->hw_path;
+	} else if (is_pci_dev(dev)) {
+		get_node_path(dev, path);
+	}
+}
+EXPORT_SYMBOL(device_to_hwpath);
 
 #define BC_PORT_MASK 0x8
 #define BC_LOWER_PORT 0x8
diff -Nru a/arch/parisc/kernel/entry.S b/arch/parisc/kernel/entry.S
--- a/arch/parisc/kernel/entry.S	2005-03-11 12:51:41 -08:00
+++ b/arch/parisc/kernel/entry.S	2005-03-11 12:51:41 -08:00
@@ -76,13 +76,11 @@
 	mtsp	%r0, %sr5
 	mtsp	%r0, %sr6
 	mtsp	%r0, %sr7
-	ldil	L%KERNEL_PSW, %r1
-	ldo	R%KERNEL_PSW(%r1), %r1
+	load32	KERNEL_PSW, %r1
 	mtctl	%r1, %cr22
 	mtctl	%r0, %cr17	/* Clear IIASQ tail */
 	mtctl	%r0, %cr17	/* Clear IIASQ head */
-	ldil	L%4f, %r1
-	ldo	R%4f(%r1), %r1
+	load32	4f, %r1
 	mtctl	%r1, %cr18	/* Set IIAOQ tail */
 	ldo	4(%r1), %r1
 	mtctl	%r1, %cr18	/* Set IIAOQ head */
@@ -197,8 +195,7 @@
 	/* HPMC handler */
 	.macro	hpmc code
 	nop			/* must be a NOP, will be patched later */
-	ldil	L%PA(os_hpmc), %r3
-	ldo	R%PA(os_hpmc)(%r3), %r3
+	load32	PA(os_hpmc), %r3
 	bv,n	0(%r3)
 	nop
 	.word	0		/* checksum (will be patched) */
@@ -860,8 +857,7 @@
 
 	callee_save
 
-	ldil	L%_switch_to_ret, %r2
-	ldo	R%_switch_to_ret(%r2), %r2
+	load32	_switch_to_ret, %r2
 
 	STREG	%r2, TASK_PT_KPC(%r26)
 	LDREG	TASK_PT_KPC(%r25), %r2
@@ -914,16 +910,13 @@
 	depi	3,31,2,%r19
 	STREG	%r19,PT_IAOQ1(%r16)
 	LDREG   PT_PSW(%r16),%r19
-	ldil    L%USER_PSW_MASK,%r1
-	ldo     R%USER_PSW_MASK(%r1),%r1
+	load32	USER_PSW_MASK,%r1
 #ifdef __LP64__
-	ldil    L%USER_PSW_HI_MASK,%r20
-	ldo     R%USER_PSW_HI_MASK(%r20),%r20
+	load32	USER_PSW_HI_MASK,%r20
 	depd    %r20,31,32,%r1
 #endif
 	and     %r19,%r1,%r19 /* Mask out bits that user shouldn't play with */
-	ldil    L%USER_PSW,%r1
-	ldo     R%USER_PSW(%r1),%r1
+	load32	USER_PSW,%r1
 	or      %r19,%r1,%r19 /* Make sure default USER_PSW bits are set */
 	STREG   %r19,PT_PSW(%r16)
 
@@ -955,8 +948,7 @@
 
 	.import irq_stat,data
 
-	ldil	L%irq_stat,%r19
-	ldo	R%irq_stat(%r19),%r19
+	load32	irq_stat,%r19
 #ifdef CONFIG_SMP
 	mfctl   %cr30,%r1
 	ldw	TI_CPU(%r1),%r1 /* get cpu # - int */
@@ -1079,7 +1071,7 @@
 	BL	do_signal,%r2
 	copy	%r0, %r26			/* sigset_t *oldset = NULL */
 
-	b	intr_restore
+	b	intr_check_sig
 	nop
 
 	/*
@@ -1607,8 +1599,7 @@
 
 #ifdef CONFIG_SMP
 	CMPIB=,n        0,spc,dbit_nolock_20w
-	ldil            L%PA(pa_dbit_lock),t0
-	ldo             R%PA(pa_dbit_lock)(t0),t0
+	load32		PA(pa_dbit_lock),t0
 
 dbit_spin_20w:
 	ldcw            0(t0),t1
@@ -1644,8 +1635,7 @@
 
 #ifdef CONFIG_SMP
 	CMPIB=,n        0,spc,dbit_nolock_11
-	ldil            L%PA(pa_dbit_lock),t0
-	ldo             R%PA(pa_dbit_lock)(t0),t0
+	load32		PA(pa_dbit_lock),t0
 
 dbit_spin_11:
 	ldcw            0(t0),t1
@@ -1685,8 +1675,7 @@
 
 #ifdef CONFIG_SMP
 	CMPIB=,n        0,spc,dbit_nolock_20
-	ldil            L%PA(pa_dbit_lock),t0
-	ldo             R%PA(pa_dbit_lock)(t0),t0
+	load32		PA(pa_dbit_lock),t0
 
 dbit_spin_20:
 	ldcw            0(t0),t1
@@ -2082,8 +2071,7 @@
 
 	.import irq_stat,data
 
-	ldil    L%irq_stat,%r19
-	ldo     R%irq_stat(%r19),%r19
+	load32	irq_stat,%r19
 
 #ifdef CONFIG_SMP
 	/* sched.h: int processor */
@@ -2282,7 +2270,7 @@
 	ldo	TASK_REGS(%r1), %r20		/* reload pt_regs */
 	reg_restore %r20
 
-	b,n     syscall_restore
+	b,n     syscall_check_sig
 
 	/*
 	 * get_register is used by the non access tlb miss handlers to
diff -Nru a/arch/parisc/kernel/firmware.c b/arch/parisc/kernel/firmware.c
--- a/arch/parisc/kernel/firmware.c	2005-03-11 12:51:41 -08:00
+++ b/arch/parisc/kernel/firmware.c	2005-03-11 12:51:41 -08:00
@@ -120,10 +120,10 @@
 #ifdef __LP64__
 	if(unlikely(parisc_narrow_firmware)) {
 		if((address & 0xff000000) == 0xf0000000)
-			return 0xf0f0f0f000000000 | (u32)address;
+			return 0xf0f0f0f000000000UL | (u32)address;
 
 		if((address & 0xf0000000) == 0xf0000000)
-			return 0xffffffff00000000 | (u32)address;
+			return 0xffffffff00000000UL | (u32)address;
 	}
 #endif
 	return address;
@@ -912,7 +912,7 @@
  *
  * Reset the system.
  */
-int pdc_do_reset()
+int pdc_do_reset(void)
 {
         int retval;
 
diff -Nru a/arch/parisc/kernel/hardware.c b/arch/parisc/kernel/hardware.c
--- a/arch/parisc/kernel/hardware.c	2005-03-11 12:51:42 -08:00
+++ b/arch/parisc/kernel/hardware.c	2005-03-11 12:51:42 -08:00
@@ -1296,18 +1296,18 @@
 };
 
 char *cpu_name_version[][2] = {
-	[pcx]	{ "PA7000 (PCX)",	"1.0" },
-	[pcxs]	{ "PA7000 (PCX-S)",	"1.1a" },
-	[pcxt]	{ "PA7100 (PCX-T)",	"1.1b" },
-	[pcxt_]	{ "PA7200 (PCX-T')",	"1.1c" },
-	[pcxl]	{ "PA7100LC (PCX-L)",	"1.1d" },
-	[pcxl2]	{ "PA7300LC (PCX-L2)",	"1.1e" },
-	[pcxu]	{ "PA8000 (PCX-U)",	"2.0" },
-	[pcxu_]	{ "PA8200 (PCX-U+)",	"2.0" },
-	[pcxw]	{ "PA8500 (PCX-W)",	"2.0" },
-	[pcxw_]	{ "PA8600 (PCX-W+)",	"2.0" },
-	[pcxw2]	{ "PA8700 (PCX-W2)",	"2.0" },
-	[mako]	{ "PA8800 (Mako)",	"2.0" }
+	[pcx]	= { "PA7000 (PCX)",	"1.0" },
+	[pcxs]	= { "PA7000 (PCX-S)",	"1.1a" },
+	[pcxt]	= { "PA7100 (PCX-T)",	"1.1b" },
+	[pcxt_]	= { "PA7200 (PCX-T')",	"1.1c" },
+	[pcxl]	= { "PA7100LC (PCX-L)",	"1.1d" },
+	[pcxl2]	= { "PA7300LC (PCX-L2)",	"1.1e" },
+	[pcxu]	= { "PA8000 (PCX-U)",	"2.0" },
+	[pcxu_]	= { "PA8200 (PCX-U+)",	"2.0" },
+	[pcxw]	= { "PA8500 (PCX-W)",	"2.0" },
+	[pcxw_]	= { "PA8600 (PCX-W+)",	"2.0" },
+	[pcxw2]	= { "PA8700 (PCX-W2)",	"2.0" },
+	[mako]	= { "PA8800 (Mako)",	"2.0" }
 };
 
 const char * __init
diff -Nru a/arch/parisc/kernel/head.S b/arch/parisc/kernel/head.S
--- a/arch/parisc/kernel/head.S	2005-03-11 12:51:52 -08:00
+++ b/arch/parisc/kernel/head.S	2005-03-11 12:51:52 -08:00
@@ -71,47 +71,42 @@
 	stw,ma          %arg2,4(%r1)
 	stw,ma          %arg3,4(%r1)
 
-	/* Initialize startup VM. Just map first 8 MB of memory */
-	load32		PA(pg0),%r1
-
-#ifdef __LP64__
-	load32		PA(pmd0),%r5
-	shrd            %r5,PxD_VALUE_SHIFT,%r3	
-#else
-	shr		%r1,PxD_VALUE_SHIFT,%r3
-#endif
-        ldo             (PxD_FLAG_PRESENT+PxD_FLAG_VALID)(%r3),%r3	
-	
+	/* Initialize startup VM. Just map first 8/16 MB of memory */
 	load32		PA(swapper_pg_dir),%r4
 	mtctl		%r4,%cr24	/* Initialize kernel root pointer */
 	mtctl		%r4,%cr25	/* Initialize user root pointer */
 
 #ifdef __LP64__
+	/* Set pmd in pgd */
+	load32		PA(pmd0),%r5
+	shrd            %r5,PxD_VALUE_SHIFT,%r3	
+        ldo             (PxD_FLAG_PRESENT+PxD_FLAG_VALID)(%r3),%r3	
 	stw		%r3,ASM_PGD_ENTRY*ASM_PGD_ENTRY_SIZE(%r4)
-	shrd		%r1,PxD_VALUE_SHIFT,%r3
-	ldo		(PxD_FLAG_PRESENT+PxD_FLAG_VALID)(%r3),%r3
-	ldo		ASM_PMD_ENTRY*ASM_PMD_ENTRY_SIZE(%r5),%r5
+	ldo		ASM_PMD_ENTRY*ASM_PMD_ENTRY_SIZE(%r5),%r4
 #else
+	/* 2-level page table, so pmd == pgd */
         ldo             ASM_PGD_ENTRY*ASM_PGD_ENTRY_SIZE(%r4),%r4
 #endif
+
+	/* Fill in pmd with enough pte directories */
+	load32		PA(pg0),%r1
+	SHRREG		%r1,PxD_VALUE_SHIFT,%r3
+	ldo		(PxD_FLAG_PRESENT+PxD_FLAG_VALID)(%r3),%r3
+
 	ldi		ASM_PT_INITIAL,%r1
 
 1:
-#ifdef __LP64__
-	stw             %r3,0(%r5)
-#else
-	stw             %r3,0(%r4)
-#endif
-	
+	stw		%r3,0(%r4)
 	ldo		(ASM_PAGE_SIZE >> PxD_VALUE_SHIFT)(%r3),%r3
 	addib,>		-1,%r1,1b
-
 #ifdef __LP64__
-	ldo		ASM_PMD_ENTRY_SIZE(%r5),%r5
+	ldo             ASM_PMD_ENTRY_SIZE(%r4),%r4
 #else
-	ldo		ASM_PGD_ENTRY_SIZE(%r4),%r4
+	ldo             ASM_PGD_ENTRY_SIZE(%r4),%r4
 #endif
 
+
+	/* Now initialize the PTEs themselves */
 	ldo		_PAGE_KERNEL(%r0),%r3 /* Hardwired 0 phys addr start */
 	load32		PA(pg0),%r1
 
@@ -306,7 +301,7 @@
 	mtctl		%r11,%cr18	/* IIAOQ head */
 	ldo		4(%r11),%r11
 	mtctl		%r11,%cr18	/* IIAOQ tail */
-
+	
 	/* Jump to hyperspace */
 	rfi
 	nop
diff -Nru a/arch/parisc/kernel/hpmc.S b/arch/parisc/kernel/hpmc.S
--- a/arch/parisc/kernel/hpmc.S	2005-03-11 12:51:51 -08:00
+++ b/arch/parisc/kernel/hpmc.S	2005-03-11 12:51:51 -08:00
@@ -121,8 +121,7 @@
 
 	/* Setup stack pointer. */
 
-	ldil    L%PA(hpmc_stack),sp
-	ldo     R%PA(hpmc_stack)(sp),sp
+	load32	PA(hpmc_stack),sp
 	
 	ldo     128(sp),sp /* leave room for arguments */
 
@@ -135,8 +134,7 @@
 	mtctl   %r4,ipsw
 	mtctl   %r0,pcsq
 	mtctl   %r0,pcsq
-	ldil    L%PA(os_hpmc_1),%r4
-	ldo     R%PA(os_hpmc_1)(%r4),%r4
+	load32	PA(os_hpmc_1),%r4
 	mtctl   %r4,pcoq
 	ldo     4(%r4),%r4
 	mtctl   %r4,pcoq
@@ -155,12 +153,9 @@
 
 	ldo     PDC_PIM(%r0), arg0
 	ldo     PDC_PIM_HPMC(%r0),arg1          /* Transfer HPMC data */
-	ldil    L%PA(hpmc_raddr),arg2
-	ldo     R%PA(hpmc_raddr)(arg2),arg2
-	ldil    L%PA(hpmc_pim_data),arg3
-	ldo     R%PA(hpmc_pim_data)(arg3),arg3
-	ldil    L%HPMC_PIM_DATA_SIZE,%r4
-	ldo     R%HPMC_PIM_DATA_SIZE(%r4),%r4
+	load32	PA(hpmc_raddr),arg2
+	load32	PA(hpmc_pim_data),arg3
+	load32	HPMC_PIM_DATA_SIZE,%r4
 	stw     %r4,-52(sp)
 
 	ldil    L%PA(os_hpmc_2), rp
@@ -199,16 +194,13 @@
 
 	ldo     PDC_IODC(%r0),arg0
 	ldo     PDC_IODC_READ(%r0),arg1
-	ldil    L%PA(hpmc_raddr),arg2
-	ldo     R%PA(hpmc_raddr)(arg2),arg2
+	load32	PA(hpmc_raddr),arg2
 	ldw     BOOT_CONSOLE_HPA_OFFSET(%r0),arg3 /* console hpa */
 	ldo     PDC_IODC_RI_INIT(%r0),%r4
 	stw     %r4,-52(sp)
-	ldil    L%PA(hpmc_iodc_buf),%r4
-	ldo     R%PA(hpmc_iodc_buf)(%r4),%r4
+	load32	PA(hpmc_iodc_buf),%r4
 	stw     %r4,-56(sp)
-	ldil    L%HPMC_IODC_BUF_SIZE,%r4
-	ldo     R%HPMC_IODC_BUF_SIZE(%r4),%r4
+	load32	HPMC_IODC_BUF_SIZE,%r4
 	stw     %r4,-60(sp)
 
 	ldil    L%PA(os_hpmc_4),rp
@@ -225,16 +217,14 @@
 	ldw     BOOT_CONSOLE_SPA_OFFSET(%r0),arg2  /* console spa */
 	depi    0,31,11,arg2                       /* clear bits 21-31    */
 	ldo     BOOT_CONSOLE_PATH_OFFSET(%r0),arg3 /* console path */
-	ldil    L%PA(hpmc_raddr),%r4
-	ldo     R%PA(hpmc_raddr)(%r4),%r4
+	load32	PA(hpmc_raddr),%r4
 	stw     %r4, -52(sp)
 	stw     %r0, -56(sp)                    /* HV                  */
 	stw     %r0, -60(sp)                    /* HV                  */
 	stw     %r0, -64(sp)                    /* HV                  */
 	stw     %r0, -68(sp)                    /* lang, must be zero  */
 
-	ldil    L%PA(hpmc_iodc_buf),%r5
-	ldo     R%PA(hpmc_iodc_buf)(%r5),%r5
+	load32	PA(hpmc_iodc_buf),%r5
 	ldil    L%PA(os_hpmc_5),rp
 	bv      (%r5)
 	ldo     R%PA(os_hpmc_5)(rp),rp
@@ -249,8 +239,7 @@
 	 * we don't intend to ever return to user land anyway)
 	 */
 
-	ldil		L%PA(swapper_pg_dir),%r4
-	ldo		R%PA(swapper_pg_dir)(%r4),%r4
+	load32		PA(swapper_pg_dir),%r4
 	mtctl		%r4,%cr24	/* Initialize kernel root pointer */
 	mtctl		%r4,%cr25	/* Initialize user root pointer */
 
@@ -265,8 +254,7 @@
 
 	rsm 8,%r0           /* Clear Q bit */
 	ldi     1,%r8       /* Set trap code to "1" for HPMC */
-	ldil    L%PA(intr_save), %r1
-	ldo     R%PA(intr_save)(%r1), %r1
+	load32	PA(intr_save),%r1
 	be      0(%sr7,%r1)
 	nop
 
diff -Nru a/arch/parisc/kernel/ioctl32.c b/arch/parisc/kernel/ioctl32.c
--- a/arch/parisc/kernel/ioctl32.c	2005-03-11 12:51:41 -08:00
+++ b/arch/parisc/kernel/ioctl32.c	2005-03-11 12:51:41 -08:00
@@ -563,7 +563,7 @@
 
 #endif
 
-#define HANDLE_IOCTL(cmd, handler) { cmd, (ioctl_trans_handler_t)handler, 0 },
+#define HANDLE_IOCTL(cmd, handler) { cmd, (ioctl_trans_handler_t)handler, NULL },
 #define COMPATIBLE_IOCTL(cmd) HANDLE_IOCTL(cmd, sys_ioctl) 
 
 #define IOCTL_TABLE_START  struct ioctl_trans ioctl_start[] = {
diff -Nru a/arch/parisc/kernel/irq.c b/arch/parisc/kernel/irq.c
--- a/arch/parisc/kernel/irq.c	2005-03-11 12:51:42 -08:00
+++ b/arch/parisc/kernel/irq.c	2005-03-11 12:51:42 -08:00
@@ -5,6 +5,7 @@
  * Copyright (C) 1994, 1995, 1996, 1997, 1998 Ralf Baechle
  * Copyright (C) 1999 SuSE GmbH (Philipp Rumpf, prumpf@tux.org)
  * Copyright (C) 1999-2000 Grant Grundler
+ * Copyright (c) 2005 Matthew Wilcox
  *
  *    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
@@ -22,38 +23,19 @@
  */
 #include <linux/bitops.h>
 #include <linux/config.h>
-#include <linux/eisa.h>
 #include <linux/errno.h>
 #include <linux/init.h>
-#include <linux/module.h>
-#include <linux/signal.h>
-#include <linux/types.h>
-#include <linux/ioport.h>
-#include <linux/timex.h>
-#include <linux/slab.h>
-#include <linux/random.h>
-#include <linux/sched.h>
 #include <linux/interrupt.h>
 #include <linux/kernel_stat.h>
-#include <linux/irq.h>
 #include <linux/seq_file.h>
 #include <linux/spinlock.h>
+#include <linux/types.h>
 
-#include <asm/cache.h>
-#include <asm/pdc.h>
-
-#undef DEBUG_IRQ
 #undef PARISC_IRQ_CR16_COUNTS
 
 extern irqreturn_t timer_interrupt(int, void *, struct pt_regs *);
 extern irqreturn_t ipi_interrupt(int, void *, struct pt_regs *);
 
-#ifdef DEBUG_IRQ
-#define DBG_IRQ(irq, x)	if ((irq) != TIMER_IRQ) printk x
-#else /* DEBUG_IRQ */
-#define DBG_IRQ(irq, x)	do { } while (0)
-#endif /* DEBUG_IRQ */
-
 #define EIEM_MASK(irq)       (1UL<<(CPU_IRQ_MAX - irq))
 
 /* Bits in EIEM correlate with cpu_irq_action[].
@@ -200,7 +182,25 @@
 	return cpu_claim_irq(irq, NULL, NULL) ? -1 : irq;
 }
 
-int txn_alloc_irq(void)
+/*
+ * The bits_wide parameter accommodates the limitations of the HW/SW which
+ * use these bits:
+ * Legacy PA I/O (GSC/NIO): 5 bits (architected EIM register)
+ * V-class (EPIC):          6 bits
+ * N/L/A-class (iosapic):   8 bits
+ * PCI 2.2 MSI:            16 bits
+ * Some PCI devices:       32 bits (Symbios SCSI/ATM/HyperFabric)
+ *
+ * On the service provider side:
+ * o PA 1.1 (and PA2.0 narrow mode)     5-bits (width of EIR register)
+ * o PA 2.0 wide mode                   6-bits (per processor)
+ * o IA64                               8-bits (0-256 total)
+ *
+ * So a Legacy PA I/O device on a PA 2.0 box can't use all the bits supported
+ * by the processor...and the N/L-class I/O subsystem supports more bits than
+ * PA2.0 has. The first case is the problem.
+ */
+int txn_alloc_irq(unsigned int bits_wide)
 {
 	int irq;
 
@@ -208,6 +208,8 @@
 	for (irq = CPU_IRQ_BASE + 1; irq <= CPU_IRQ_MAX; irq++) {
 		if (cpu_claim_irq(irq, NULL, NULL) < 0)
 			continue;
+		if ((irq - CPU_IRQ_BASE) >= (1 << bits_wide))
+			continue;
 		return irq;
 	}
 
@@ -215,7 +217,7 @@
 	return -1;
 }
 
-unsigned long txn_alloc_addr(int virt_irq)
+unsigned long txn_alloc_addr(unsigned int virt_irq)
 {
 	static int next_cpu = -1;
 
@@ -233,36 +235,8 @@
 }
 
 
-/*
-** The alloc process needs to accept a parameter to accommodate limitations
-** of the HW/SW which use these bits:
-** Legacy PA I/O (GSC/NIO): 5 bits (architected EIM register)
-** V-class (EPIC):          6 bits
-** N/L-class/A500:          8 bits (iosapic)
-** PCI 2.2 MSI:             16 bits (I think)
-** Existing PCI devices:    32-bits (all Symbios SCSI/ATM/HyperFabric)
-**
-** On the service provider side:
-** o PA 1.1 (and PA2.0 narrow mode)     5-bits (width of EIR register)
-** o PA 2.0 wide mode                   6-bits (per processor)
-** o IA64                               8-bits (0-256 total)
-**
-** So a Legacy PA I/O device on a PA 2.0 box can't use all
-** the bits supported by the processor...and the N/L-class
-** I/O subsystem supports more bits than PA2.0 has. The first
-** case is the problem.
-*/
-unsigned int txn_alloc_data(int virt_irq, unsigned int bits_wide)
+unsigned int txn_alloc_data(unsigned int virt_irq)
 {
-	/* XXX FIXME : bits_wide indicates how wide the transaction
-	** data is allowed to be...we may need a different virt_irq
-	** if this one won't work. Another reason to index virtual
-	** irq's into a table which can manage CPU/IRQ bit separately.
-	*/
-	if ((virt_irq - CPU_IRQ_BASE) > (1 << (bits_wide - 1))) {
-		panic("Sorry -- didn't allocate valid IRQ for this device\n");
-	}
-
 	return virt_irq - CPU_IRQ_BASE;
 }
 
@@ -270,42 +244,35 @@
 void do_cpu_irq_mask(struct pt_regs *regs)
 {
 	unsigned long eirr_val;
-	unsigned int i=3;	/* limit time in interrupt context */
+
+	irq_enter();
 
 	/*
-	 * PSW_I or EIEM bits cannot be enabled until after the
-	 * interrupts are processed.
-	 * timer_interrupt() assumes it won't get interrupted when it
-	 * holds the xtime_lock...an unmasked interrupt source could
-	 * interrupt and deadlock by trying to grab xtime_lock too.
-	 * Keeping PSW_I and EIEM disabled avoids this.
+	 * Only allow interrupt processing to be interrupted by the
+	 * timer tick
 	 */
-	set_eiem(0UL);	/* disable all extr interrupt for now */
+	set_eiem(EIEM_MASK(TIMER_IRQ));
 
 	/* 1) only process IRQs that are enabled/unmasked (cpu_eiem)
 	 * 2) We loop here on EIRR contents in order to avoid
 	 *    nested interrupts or having to take another interrupt
 	 *    when we could have just handled it right away.
-	 * 3) Limit the number of times we loop to make sure other
-	 *    processing can occur.
 	 */
 	for (;;) {
 		unsigned long bit = (1UL << (BITS_PER_LONG - 1));
 		unsigned int irq;
 		eirr_val = mfctl(23) & cpu_eiem;
-		if (!eirr_val || !i--)
+		if (!eirr_val)
 			break;
 
-		mtctl(eirr_val, 23); /* reset bits we are going to process */
+		if (eirr_val & EIEM_MASK(TIMER_IRQ))
+			set_eiem(0);
 
-#ifdef DEBUG_IRQ
-		if (eirr_val != (1UL << MAX_CPU_IRQ))
-			printk(KERN_DEBUG "do_cpu_irq_mask  0x%x & 0x%x\n", eirr_val, cpu_eiem);
-#endif
+		mtctl(eirr_val, 23); /* reset bits we are going to process */
 
 		/* Work our way from MSb to LSb...same order we alloc EIRs */
 		for (irq = TIMER_IRQ; eirr_val && bit; bit>>=1, irq++) {
-			if (!(bit & eirr_val & cpu_eiem))
+			if (!(bit & eirr_val))
 				continue;
 
 			/* clear bit in mask - can exit loop sooner */
@@ -315,6 +282,7 @@
 		}
 	}
 	set_eiem(cpu_eiem);
+	irq_exit();
 }
 
 
diff -Nru a/arch/parisc/kernel/module.c b/arch/parisc/kernel/module.c
--- a/arch/parisc/kernel/module.c	2005-03-11 12:51:52 -08:00
+++ b/arch/parisc/kernel/module.c	2005-03-11 12:51:52 -08:00
@@ -2,7 +2,7 @@
  *
  *    The best reference for this stuff is probably the Processor-
  *    Specific ELF Supplement for PA-RISC:
- *        http://ftp.parisc-linux.org/docs/elf-pa-hp.pdf
+ *        http://ftp.parisc-linux.org/docs/arch/elf-pa-hp.pdf
  *
  *    Linux/PA-RISC Project (http://www.parisc-linux.org/)
  *    Copyright (C) 2003 Randolph Chung <tausq at debian . org>
@@ -21,6 +21,23 @@
  *    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
+ *
+ *
+ *    Notes:
+ *    - SEGREL32 handling
+ *      We are not doing SEGREL32 handling correctly. According to the ABI, we
+ *      should do a value offset, like this:
+ *			if (is_init(me, (void *)val))
+ *				val -= (uint32_t)me->module_init;
+ *			else
+ *				val -= (uint32_t)me->module_core;
+ *	However, SEGREL32 is used only for PARISC unwind entries, and we want
+ *	those entries to have an absolute address, and not just an offset.
+ *
+ *	The unwind table mechanism has the ability to specify an offset for 
+ *	the unwind table; however, because we split off the init functions into
+ *	a different piece of memory, it is not possible to do this using a 
+ *	single offset. Instead, we use the above hack for now.
  */
 
 #include <linux/moduleloader.h>
@@ -30,6 +47,8 @@
 #include <linux/string.h>
 #include <linux/kernel.h>
 
+#include <asm/unwind.h>
+
 #if 0
 #define DEBUGP printk
 #else
@@ -248,6 +267,10 @@
 		const Elf_Rela *rels = (void *)hdr + sechdrs[i].sh_offset;
 		unsigned long nrels = sechdrs[i].sh_size / sizeof(*rels);
 
+		if (strncmp(secstrings + sechdrs[i].sh_name,
+			    ".PARISC.unwind", 14) == 0)
+			me->arch.unwind_section = i;
+
 		if (sechdrs[i].sh_type != SHT_RELA)
 			continue;
 
@@ -499,7 +522,9 @@
 			break;
 		case R_PARISC_SEGREL32:
 			/* 32-bit segment relative address */
-			val -= (uint32_t)me->module_core;
+			/* See note about special handling of SEGREL32 at
+			 * the beginning of this file.
+			 */
 			*loc = fsel(val, addend); 
 			break;
 		case R_PARISC_DPREL21L:
@@ -651,7 +676,9 @@
 			break;
 		case R_PARISC_SEGREL32:
 			/* 32-bit segment relative address */
-			val -= (uint64_t)me->module_core;
+			/* See note about special handling of SEGREL32 at
+			 * the beginning of this file.
+			 */
 			*loc = fsel(val, addend); 
 			break;
 		case R_PARISC_FPTR64:
@@ -682,6 +709,32 @@
 }
 #endif
 
+static void
+register_unwind_table(struct module *me,
+		      const Elf_Shdr *sechdrs)
+{
+	unsigned char *table, *end;
+	unsigned long gp;
+
+	if (!me->arch.unwind_section)
+		return;
+
+	table = (unsigned char *)sechdrs[me->arch.unwind_section].sh_addr;
+	end = table + sechdrs[me->arch.unwind_section].sh_size;
+	gp = (Elf_Addr)me->module_core + me->arch.got_offset;
+
+	DEBUGP("register_unwind_table(), sect = %d at 0x%p - 0x%p (gp=0x%lx)\n",
+	       me->arch.unwind_section, table, end, gp);
+	me->arch.unwind = unwind_table_add(me->name, 0, gp, table, end);
+}
+
+static void
+deregister_unwind_table(struct module *me)
+{
+	if (me->arch.unwind)
+		unwind_table_remove(me->arch.unwind);
+}
+
 int module_finalize(const Elf_Ehdr *hdr,
 		    const Elf_Shdr *sechdrs,
 		    struct module *me)
@@ -711,6 +764,8 @@
 	       me->arch.fdesc_count, me->arch.fdesc_max);
 #endif
 
+	register_unwind_table(me, sechdrs);
+
 	/* haven't filled in me->symtab yet, so have to find it
 	 * ourselves */
 	for (i = 1; i < hdr->e_shnum; i++) {
@@ -763,4 +818,5 @@
 
 void module_arch_cleanup(struct module *mod)
 {
+	deregister_unwind_table(mod);
 }
diff -Nru a/arch/parisc/kernel/pacache.S b/arch/parisc/kernel/pacache.S
--- a/arch/parisc/kernel/pacache.S	2005-03-11 12:51:41 -08:00
+++ b/arch/parisc/kernel/pacache.S	2005-03-11 12:51:41 -08:00
@@ -27,17 +27,17 @@
  */
 
 #ifdef __LP64__
-#define ADDIB   addib,*
-#define CMPB    cmpb,*
-#define ANDCM   andcm,*
+#define ADDIB	addib,*
+#define CMPB	cmpb,*
+#define ANDCM	andcm,*
 
-	.level 2.0w
+	.level	2.0w
 #else
-#define ADDIB   addib,
-#define CMPB    cmpb,
-#define ANDCM   andcm
+#define ADDIB	addib,
+#define CMPB	cmpb,
+#define ANDCM	andcm
 
-	.level 2.0
+	.level	2.0
 #endif
 
 #include <asm/assembly.h>
@@ -46,7 +46,7 @@
 #include <asm/cache.h>
 
 	.text
-	.align 128
+	.align	128
 
 	.export flush_tlb_all_local,code
 
@@ -68,7 +68,7 @@
 	 * consolidated.
 	 */
 
-	rsm     PSW_SM_I,%r19	/* relied upon translation! PA 2.0 Arch. F-5 */
+	rsm		PSW_SM_I, %r19		/* relied upon translation! PA 2.0 Arch. F-5 */
 	nop
 	nop
 	nop
@@ -77,127 +77,127 @@
 	nop
 	nop
 	
-	rsm     PSW_SM_Q,%r0       /* Turn off Q bit to load iia queue */
-	ldil    L%REAL_MODE_PSW, %r1
-	ldo     R%REAL_MODE_PSW(%r1), %r1
-	mtctl	%r1, %cr22
-	mtctl	%r0, %cr17	/* Clear IIASQ tail */
-	mtctl	%r0, %cr17	/* Clear IIASQ head */
-	ldil    L%PA(1f),%r1
-	ldo     R%PA(1f)(%r1),%r1
-	mtctl	%r1, %cr18	/* IIAOQ head */
-	ldo	4(%r1), %r1
-	mtctl	%r1, %cr18	/* IIAOQ tail */
+	rsm		PSW_SM_Q, %r0		/* Turn off Q bit to load iia queue */
+	ldil		L%REAL_MODE_PSW, %r1
+	ldo		R%REAL_MODE_PSW(%r1), %r1
+	mtctl		%r1, %cr22
+	mtctl		%r0, %cr17		/* Clear IIASQ tail */
+	mtctl		%r0, %cr17		/* Clear IIASQ head */
+	ldil		L%PA(1f), %r1
+	ldo		R%PA(1f)(%r1), %r1
+	mtctl		%r1, %cr18		/* IIAOQ head */
+	ldo		4(%r1), %r1
+	mtctl		%r1, %cr18		/* IIAOQ tail */
 	rfi
 	nop
 
-1:      ldil            L%PA(cache_info),%r1
-	ldo             R%PA(cache_info)(%r1),%r1
+1:      ldil		L%PA(cache_info), %r1
+	ldo		R%PA(cache_info)(%r1), %r1
 
 	/* Flush Instruction Tlb */
 
-	LDREG           ITLB_SID_BASE(%r1),%r20
-	LDREG           ITLB_SID_STRIDE(%r1),%r21
-	LDREG           ITLB_SID_COUNT(%r1),%r22
-	LDREG           ITLB_OFF_BASE(%r1),%arg0
-	LDREG           ITLB_OFF_STRIDE(%r1),%arg1
-	LDREG           ITLB_OFF_COUNT(%r1),%arg2
-	LDREG           ITLB_LOOP(%r1),%arg3
-
-	ADDIB=          -1,%arg3,fitoneloop     /* Preadjust and test */
-	movb,<,n        %arg3,%r31,fitdone      /* If loop < 0, skip */
-	copy            %arg0,%r28              /* Init base addr */
-
-fitmanyloop:                                    /* Loop if LOOP >= 2 */
-	mtsp            %r20,%sr1
-	add             %r21,%r20,%r20          /* increment space */
-	copy            %arg2,%r29              /* Init middle loop count */
-
-fitmanymiddle:                                  /* Loop if LOOP >= 2 */
-	ADDIB>          -1,%r31,fitmanymiddle   /* Adjusted inner loop decr */
-	pitlbe          0(%sr1,%r28)
-	pitlbe,m        %arg1(%sr1,%r28)        /* Last pitlbe and addr adjust */
-	ADDIB>          -1,%r29,fitmanymiddle   /* Middle loop decr */
-	copy            %arg3,%r31              /* Re-init inner loop count */
-
-	movb,tr         %arg0,%r28,fitmanyloop  /* Re-init base addr */
-	ADDIB<=,n       -1,%r22,fitdone         /* Outer loop count decr */
-
-fitoneloop:                                     /* Loop if LOOP = 1 */
-	mtsp            %r20,%sr1
-	copy            %arg0,%r28              /* init base addr */
-	copy            %arg2,%r29              /* init middle loop count */
-
-fitonemiddle:                                   /* Loop if LOOP = 1 */
-	ADDIB>          -1,%r29,fitonemiddle    /* Middle loop count decr */
-	pitlbe,m        %arg1(%sr1,%r28)        /* pitlbe for one loop */
+	LDREG		ITLB_SID_BASE(%r1), %r20
+	LDREG		ITLB_SID_STRIDE(%r1), %r21
+	LDREG		ITLB_SID_COUNT(%r1), %r22
+	LDREG		ITLB_OFF_BASE(%r1), %arg0
+	LDREG		ITLB_OFF_STRIDE(%r1), %arg1
+	LDREG		ITLB_OFF_COUNT(%r1), %arg2
+	LDREG		ITLB_LOOP(%r1), %arg3
+
+	ADDIB=		-1, %arg3, fitoneloop	/* Preadjust and test */
+	movb,<,n	%arg3, %r31, fitdone	/* If loop < 0, skip */
+	copy		%arg0, %r28		/* Init base addr */
+
+fitmanyloop:					/* Loop if LOOP >= 2 */
+	mtsp		%r20, %sr1
+	add		%r21, %r20, %r20	/* increment space */
+	copy		%arg2, %r29		/* Init middle loop count */
+
+fitmanymiddle:					/* Loop if LOOP >= 2 */
+	ADDIB>		-1, %r31, fitmanymiddle	/* Adjusted inner loop decr */
+	pitlbe		0(%sr1, %r28)
+	pitlbe,m	%arg1(%sr1, %r28)	/* Last pitlbe and addr adjust */
+	ADDIB>		-1, %r29, fitmanymiddle	/* Middle loop decr */
+	copy		%arg3, %r31		/* Re-init inner loop count */
+
+	movb,tr		%arg0, %r28, fitmanyloop /* Re-init base addr */
+	ADDIB<=,n	-1, %r22, fitdone	/* Outer loop count decr */
+
+fitoneloop:					/* Loop if LOOP = 1 */
+	mtsp		%r20, %sr1
+	copy		%arg0, %r28		/* init base addr */
+	copy		%arg2, %r29		/* init middle loop count */
+
+fitonemiddle:					/* Loop if LOOP = 1 */
+	ADDIB>		-1, %r29, fitonemiddle	/* Middle loop count decr */
+	pitlbe,m	%arg1(%sr1, %r28)	/* pitlbe for one loop */
 
-	ADDIB>          -1,%r22,fitoneloop      /* Outer loop count decr */
-	add             %r21,%r20,%r20          /* increment space */
+	ADDIB>		-1, %r22, fitoneloop	/* Outer loop count decr */
+	add		%r21, %r20, %r20		/* increment space */
 
 fitdone:
 
 	/* Flush Data Tlb */
 
-	LDREG           DTLB_SID_BASE(%r1),%r20
-	LDREG           DTLB_SID_STRIDE(%r1),%r21
-	LDREG           DTLB_SID_COUNT(%r1),%r22
-	LDREG           DTLB_OFF_BASE(%r1),%arg0
-	LDREG           DTLB_OFF_STRIDE(%r1),%arg1
-	LDREG           DTLB_OFF_COUNT(%r1),%arg2
-	LDREG           DTLB_LOOP(%r1),%arg3
-
-	ADDIB=          -1,%arg3,fdtoneloop     /* Preadjust and test */
-	movb,<,n        %arg3,%r31,fdtdone      /* If loop < 0, skip */
-	copy            %arg0,%r28              /* Init base addr */
-
-fdtmanyloop:                                    /* Loop if LOOP >= 2 */
-	mtsp            %r20,%sr1
-	add             %r21,%r20,%r20          /* increment space */
-	copy            %arg2,%r29              /* Init middle loop count */
-
-fdtmanymiddle:                                  /* Loop if LOOP >= 2 */
-	ADDIB>          -1,%r31,fdtmanymiddle   /* Adjusted inner loop decr */
-	pdtlbe          0(%sr1,%r28)
-	pdtlbe,m        %arg1(%sr1,%r28)        /* Last pdtlbe and addr adjust */
-	ADDIB>          -1,%r29,fdtmanymiddle   /* Middle loop decr */
-	copy            %arg3,%r31              /* Re-init inner loop count */
-
-	movb,tr         %arg0,%r28,fdtmanyloop  /* Re-init base addr */
-	ADDIB<=,n       -1,%r22,fdtdone         /* Outer loop count decr */
-
-fdtoneloop:                                     /* Loop if LOOP = 1 */
-	mtsp            %r20,%sr1
-	copy            %arg0,%r28              /* init base addr */
-	copy            %arg2,%r29              /* init middle loop count */
-
-fdtonemiddle:                                   /* Loop if LOOP = 1 */
-	ADDIB>          -1,%r29,fdtonemiddle    /* Middle loop count decr */
-	pdtlbe,m        %arg1(%sr1,%r28)        /* pdtlbe for one loop */
+	LDREG		DTLB_SID_BASE(%r1), %r20
+	LDREG		DTLB_SID_STRIDE(%r1), %r21
+	LDREG		DTLB_SID_COUNT(%r1), %r22
+	LDREG		DTLB_OFF_BASE(%r1), %arg0
+	LDREG		DTLB_OFF_STRIDE(%r1), %arg1
+	LDREG		DTLB_OFF_COUNT(%r1), %arg2
+	LDREG		DTLB_LOOP(%r1), %arg3
+
+	ADDIB=		-1, %arg3, fdtoneloop	/* Preadjust and test */
+	movb,<,n	%arg3, %r31, fdtdone	/* If loop < 0, skip */
+	copy		%arg0, %r28		/* Init base addr */
+
+fdtmanyloop:					/* Loop if LOOP >= 2 */
+	mtsp		%r20, %sr1
+	add		%r21, %r20, %r20	/* increment space */
+	copy		%arg2, %r29		/* Init middle loop count */
+
+fdtmanymiddle:					/* Loop if LOOP >= 2 */
+	ADDIB>		-1, %r31, fdtmanymiddle	/* Adjusted inner loop decr */
+	pdtlbe		0(%sr1, %r28)
+	pdtlbe,m	%arg1(%sr1, %r28)	/* Last pdtlbe and addr adjust */
+	ADDIB>		-1, %r29, fdtmanymiddle	/* Middle loop decr */
+	copy		%arg3, %r31		/* Re-init inner loop count */
+
+	movb,tr		%arg0, %r28, fdtmanyloop /* Re-init base addr */
+	ADDIB<=,n	-1, %r22,fdtdone	/* Outer loop count decr */
+
+fdtoneloop:					/* Loop if LOOP = 1 */
+	mtsp		%r20, %sr1
+	copy		%arg0, %r28		/* init base addr */
+	copy		%arg2, %r29		/* init middle loop count */
+
+fdtonemiddle:					/* Loop if LOOP = 1 */
+	ADDIB>		-1, %r29, fdtonemiddle	/* Middle loop count decr */
+	pdtlbe,m	%arg1(%sr1, %r28)	/* pdtlbe for one loop */
 
-	ADDIB>          -1,%r22,fdtoneloop      /* Outer loop count decr */
-	add             %r21,%r20,%r20          /* increment space */
+	ADDIB>		-1, %r22, fdtoneloop	/* Outer loop count decr */
+	add		%r21, %r20, %r20	/* increment space */
 
 fdtdone:
 
 	/* Switch back to virtual mode */
 
-	rsm     PSW_SM_Q,%r0       /* clear Q bit to load iia queue */
-	ldil	L%KERNEL_PSW, %r1
-	ldo	R%KERNEL_PSW(%r1), %r1
-	or      %r1,%r19,%r1    /* Set I bit if set on entry */
-	mtctl	%r1, %cr22
-	mtctl	%r0, %cr17	/* Clear IIASQ tail */
-	mtctl	%r0, %cr17	/* Clear IIASQ head */
-	ldil    L%(2f), %r1
-	ldo     R%(2f)(%r1), %r1
-	mtctl	%r1, %cr18	/* IIAOQ head */
-	ldo	4(%r1), %r1
-	mtctl	%r1, %cr18	/* IIAOQ tail */
+	rsm		PSW_SM_Q, %r0		/* clear Q bit to load iia queue */
+	ldil		L%KERNEL_PSW, %r1
+	ldo		R%KERNEL_PSW(%r1), %r1
+	or		%r1, %r19, %r1		/* Set I bit if set on entry */
+	mtctl		%r1, %cr22
+	mtctl		%r0, %cr17		/* Clear IIASQ tail */
+	mtctl		%r0, %cr17		/* Clear IIASQ head */
+	ldil		L%(2f), %r1
+	ldo		R%(2f)(%r1), %r1
+	mtctl		%r1, %cr18		/* IIAOQ head */
+	ldo		4(%r1), %r1
+	mtctl		%r1, %cr18		/* IIAOQ tail */
 	rfi
 	nop
 
-2:      bv      %r0(%r2)
+2:      bv		%r0(%r2)
 	nop
 	.exit
 
@@ -211,140 +211,198 @@
 	.callinfo NO_CALLS
 	.entry
 
-	mtsp            %r0,%sr1
-	ldil            L%cache_info,%r1
-	ldo             R%cache_info(%r1),%r1
+	mtsp		%r0, %sr1
+	ldil		L%cache_info, %r1
+	ldo		R%cache_info(%r1), %r1
 
 	/* Flush Instruction Cache */
 
-	LDREG           ICACHE_BASE(%r1),%arg0
-	LDREG           ICACHE_STRIDE(%r1),%arg1
-	LDREG           ICACHE_COUNT(%r1),%arg2
-	LDREG           ICACHE_LOOP(%r1),%arg3
-	rsm             PSW_SM_I,%r22		/* No mmgt ops during loop*/
-	ADDIB=          -1,%arg3,fioneloop      /* Preadjust and test */
-	movb,<,n        %arg3,%r31,fisync       /* If loop < 0, do sync */
-
-fimanyloop:                                     /* Loop if LOOP >= 2 */
-	ADDIB>          -1,%r31,fimanyloop      /* Adjusted inner loop decr */
-	fice            0(%sr1,%arg0)
-	fice,m          %arg1(%sr1,%arg0)       /* Last fice and addr adjust */
-	movb,tr         %arg3,%r31,fimanyloop   /* Re-init inner loop count */
-	ADDIB<=,n       -1,%arg2,fisync         /* Outer loop decr */
-
-fioneloop:                                      /* Loop if LOOP = 1 */
-	ADDIB>          -1,%arg2,fioneloop      /* Outer loop count decr */
-	fice,m          %arg1(%sr1,%arg0)       /* Fice for one loop */
+	LDREG		ICACHE_BASE(%r1), %arg0
+	LDREG		ICACHE_STRIDE(%r1), %arg1
+	LDREG		ICACHE_COUNT(%r1), %arg2
+	LDREG		ICACHE_LOOP(%r1), %arg3
+	rsm             PSW_SM_I, %r22		/* No mmgt ops during loop*/
+	ADDIB=		-1, %arg3, fioneloop	/* Preadjust and test */
+	movb,<,n	%arg3, %r31, fisync	/* If loop < 0, do sync */
+
+fimanyloop:					/* Loop if LOOP >= 2 */
+	ADDIB>		-1, %r31, fimanyloop	/* Adjusted inner loop decr */
+	fice            0(%sr1, %arg0)
+	fice,m		%arg1(%sr1, %arg0)	/* Last fice and addr adjust */
+	movb,tr		%arg3, %r31, fimanyloop	/* Re-init inner loop count */
+	ADDIB<=,n	-1, %arg2, fisync	/* Outer loop decr */
+
+fioneloop:					/* Loop if LOOP = 1 */
+	ADDIB>		-1, %arg2, fioneloop	/* Outer loop count decr */
+	fice,m		%arg1(%sr1, %arg0)	/* Fice for one loop */
 
 fisync:
 	sync
-	mtsm	%r22
-	bv      %r0(%r2)
+	mtsm		%r22
+	bv		%r0(%r2)
 	nop
 	.exit
 
 	.procend
 
-	.export flush_data_cache_local,code
-	.import cache_info,data
+	.export flush_data_cache_local, code
+	.import cache_info, data
 
 flush_data_cache_local:
 	.proc
 	.callinfo NO_CALLS
 	.entry
 
-	mtsp            %r0,%sr1
-	ldil            L%cache_info,%r1
-	ldo             R%cache_info(%r1),%r1
+	mtsp		%r0, %sr1
+	ldil		L%cache_info, %r1
+	ldo		R%cache_info(%r1), %r1
 
 	/* Flush Data Cache */
 
-	LDREG           DCACHE_BASE(%r1),%arg0
-	LDREG           DCACHE_STRIDE(%r1),%arg1
-	LDREG           DCACHE_COUNT(%r1),%arg2
-	LDREG           DCACHE_LOOP(%r1),%arg3
-	rsm             PSW_SM_I,%r22
-	ADDIB=          -1,%arg3,fdoneloop      /* Preadjust and test */
-	movb,<,n        %arg3,%r31,fdsync       /* If loop < 0, do sync */
-
-fdmanyloop:                                     /* Loop if LOOP >= 2 */
-	ADDIB>          -1,%r31,fdmanyloop      /* Adjusted inner loop decr */
-	fdce            0(%sr1,%arg0)
-	fdce,m          %arg1(%sr1,%arg0)       /* Last fdce and addr adjust */
-	movb,tr         %arg3,%r31,fdmanyloop   /* Re-init inner loop count */
-	ADDIB<=,n       -1,%arg2,fdsync         /* Outer loop decr */
-
-fdoneloop:                                      /* Loop if LOOP = 1 */
-	ADDIB>          -1,%arg2,fdoneloop      /* Outer loop count decr */
-	fdce,m          %arg1(%sr1,%arg0)       /* Fdce for one loop */
+	LDREG		DCACHE_BASE(%r1), %arg0
+	LDREG		DCACHE_STRIDE(%r1), %arg1
+	LDREG		DCACHE_COUNT(%r1), %arg2
+	LDREG		DCACHE_LOOP(%r1), %arg3
+	rsm		PSW_SM_I, %r22
+	ADDIB=		-1, %arg3, fdoneloop	/* Preadjust and test */
+	movb,<,n	%arg3, %r31, fdsync	/* If loop < 0, do sync */
+
+fdmanyloop:					/* Loop if LOOP >= 2 */
+	ADDIB>		-1, %r31, fdmanyloop	/* Adjusted inner loop decr */
+	fdce		0(%sr1, %arg0)
+	fdce,m		%arg1(%sr1, %arg0)	/* Last fdce and addr adjust */
+	movb,tr		%arg3, %r31, fdmanyloop	/* Re-init inner loop count */
+	ADDIB<=,n	-1, %arg2, fdsync	/* Outer loop decr */
+
+fdoneloop:					/* Loop if LOOP = 1 */
+	ADDIB>		-1, %arg2, fdoneloop	/* Outer loop count decr */
+	fdce,m		%arg1(%sr1, %arg0)	/* Fdce for one loop */
 
 fdsync:
 	syncdma
 	sync
-	mtsm    %r22
-	bv      %r0(%r2)
+	mtsm		%r22
+	bv		%r0(%r2)
 	nop
 	.exit
 
 	.procend
 
 	.export copy_user_page_asm,code
+	.align	16
 
 copy_user_page_asm:
 	.proc
 	.callinfo NO_CALLS
 	.entry
 
-	ldi 64,%r1
+#ifdef __LP64__
+	/* PA8x00 CPUs can consume 2 loads or 1 store per cycle.
+	 * Unroll the loop by hand and arrange insn appropriately.
+	 * GCC probably can do this just as well.
+	 */
+
+	ldd		0(%r25), %r19
+	ldi		32, %r1                 /* PAGE_SIZE/128 == 32 */
+	ldw		64(%r25), %r0		/* prefetch 1 cacheline ahead */
+	ldw		128(%r25), %r0		/* prefetch 2 */
+
+1:	ldd		8(%r25), %r20
+	ldw		192(%r25), %r0		/* prefetch 3 */
+	ldw		256(%r25), %r0		/* prefetch 4 */
+
+	ldd		16(%r25), %r21
+	ldd		24(%r25), %r22
+	std		%r19, 0(%r26)
+	std		%r20, 8(%r26)
+
+	ldd		32(%r25), %r19
+	ldd		40(%r25), %r20
+	std		%r21, 16(%r26)
+	std		%r22, 24(%r26)
+
+	ldd		48(%r25), %r21
+	ldd		56(%r25), %r22
+	std		%r19, 32(%r26)
+	std		%r20, 40(%r26)
+
+	ldd		64(%r25), %r19
+	ldd		72(%r25), %r20
+	std		%r21, 48(%r26)
+	std		%r22, 56(%r26)
+
+	ldd		80(%r25), %r21
+	ldd		88(%r25), %r22
+	std		%r19, 64(%r26)
+	std		%r20, 72(%r26)
+
+	ldd		 96(%r25), %r19
+	ldd		104(%r25), %r20
+	std		%r21, 80(%r26)
+	std		%r22, 88(%r26)
+
+	ldd		112(%r25), %r21
+	ldd		120(%r25), %r22
+	std		%r19, 96(%r26)
+	std		%r20, 104(%r26)
+
+	ldo		128(%r25), %r25
+	std		%r21, 112(%r26)
+	std		%r22, 120(%r26)
+	ldo		128(%r26), %r26
+
+	ADDIB>		-1, %r1, 1b		/* bundle 10 */
+	ldd		0(%r25), %r19		/* start next loads */
+
+#else
 
 	/*
 	 * This loop is optimized for PCXL/PCXL2 ldw/ldw and stw/stw
-	 * bundles (very restricted rules for bundling). It probably
-	 * does OK on PCXU and better, but we could do better with
-	 * ldd/std instructions. Note that until (if) we start saving
+	 * bundles (very restricted rules for bundling).
+	 * Note that until (if) we start saving
 	 * the full 64 bit register values on interrupt, we can't
 	 * use ldd/std on a 32 bit kernel.
 	 */
-
+	ldi		64, %r1		/* PAGE_SIZE/64 == 64 */
 
 1:
-	ldw 0(%r25),%r19
-	ldw 4(%r25),%r20
-	ldw 8(%r25),%r21
-	ldw 12(%r25),%r22
-	stw %r19,0(%r26)
-	stw %r20,4(%r26)
-	stw %r21,8(%r26)
-	stw %r22,12(%r26)
-	ldw 16(%r25),%r19
-	ldw 20(%r25),%r20
-	ldw 24(%r25),%r21
-	ldw 28(%r25),%r22
-	stw %r19,16(%r26)
-	stw %r20,20(%r26)
-	stw %r21,24(%r26)
-	stw %r22,28(%r26)
-	ldw 32(%r25),%r19
-	ldw 36(%r25),%r20
-	ldw 40(%r25),%r21
-	ldw 44(%r25),%r22
-	stw %r19,32(%r26)
-	stw %r20,36(%r26)
-	stw %r21,40(%r26)
-	stw %r22,44(%r26)
-	ldw 48(%r25),%r19
-	ldw 52(%r25),%r20
-	ldw 56(%r25),%r21
-	ldw 60(%r25),%r22
-	stw %r19,48(%r26)
-	stw %r20,52(%r26)
-	stw %r21,56(%r26)
-	stw %r22,60(%r26)
-	ldo 64(%r26),%r26
-	ADDIB>  -1,%r1,1b
-	ldo 64(%r25),%r25
-
-	bv      %r0(%r2)
+	ldw		0(%r25), %r19
+	ldw		4(%r25), %r20
+	ldw		8(%r25), %r21
+	ldw		12(%r25), %r22
+	stw		%r19, 0(%r26)
+	stw		%r20, 4(%r26)
+	stw		%r21, 8(%r26)
+	stw		%r22, 12(%r26)
+	ldw		16(%r25), %r19
+	ldw		20(%r25), %r20
+	ldw		24(%r25), %r21
+	ldw		28(%r25), %r22
+	stw		%r19, 16(%r26)
+	stw		%r20, 20(%r26)
+	stw		%r21, 24(%r26)
+	stw		%r22, 28(%r26)
+	ldw		32(%r25), %r19
+	ldw		36(%r25), %r20
+	ldw		40(%r25), %r21
+	ldw		44(%r25), %r22
+	stw		%r19, 32(%r26)
+	stw		%r20, 36(%r26)
+	stw		%r21, 40(%r26)
+	stw		%r22, 44(%r26)
+	ldw		48(%r25), %r19
+	ldw		52(%r25), %r20
+	ldw		56(%r25), %r21
+	ldw		60(%r25), %r22
+	stw		%r19, 48(%r26)
+	stw		%r20, 52(%r26)
+	stw		%r21, 56(%r26)
+	stw		%r22, 60(%r26)
+	ldo		64(%r26), %r26
+	ADDIB>		-1, %r1, 1b
+	ldo		64(%r25), %r25
+#endif
+	bv		%r0(%r2)
 	nop
 	.exit
 
@@ -393,33 +451,33 @@
 	.callinfo NO_CALLS
 	.entry
 
-	ldil    L%(__PAGE_OFFSET),%r1
-	sub     %r26,%r1,%r26
-	sub     %r25,%r1,%r23  /* move physical addr into non shadowed reg */
-
-	ldil    L%(TMPALIAS_MAP_START),%r28
-#ifdef __LP64__
-	extrd,u %r26,56,32,%r26 /* convert phys addr to tlb insert format */
-	extrd,u %r23,56,32,%r23 /* convert phys addr to tlb insert format */
-	depd    %r24,63,22,%r28 /* Form aliased virtual address 'to' */
-	depdi   0,63,12,%r28    /* Clear any offset bits */
-	copy    %r28,%r29
-	depdi   1,41,1,%r29     /* Form aliased virtual address 'from' */
-#else
-	extrw,u %r26,24,25,%r26 /* convert phys addr to tlb insert format */
-	extrw,u %r23,24,25,%r23 /* convert phys addr to tlb insert format */
-	depw    %r24,31,22,%r28 /* Form aliased virtual address 'to' */
-	depwi   0,31,12,%r28    /* Clear any offset bits */
-	copy    %r28,%r29
-	depwi   1,9,1,%r29      /* Form aliased virtual address 'from' */
+	ldil		L%(__PAGE_OFFSET), %r1
+	sub		%r26, %r1, %r26
+	sub		%r25, %r1, %r23		/* move physical addr into non shadowed reg */
+
+	ldil		L%(TMPALIAS_MAP_START), %r28
+#ifdef __LP64__
+	extrd,u		%r26,56,32, %r26		/* convert phys addr to tlb insert format */
+	extrd,u		%r23,56,32, %r23		/* convert phys addr to tlb insert format */
+	depd		%r24,63,22, %r28		/* Form aliased virtual address 'to' */
+	depdi		0, 63,12, %r28		/* Clear any offset bits */
+	copy		%r28, %r29
+	depdi		1, 41,1, %r29		/* Form aliased virtual address 'from' */
+#else
+	extrw,u		%r26, 24,25, %r26	/* convert phys addr to tlb insert format */
+	extrw,u		%r23, 24,25, %r23	/* convert phys addr to tlb insert format */
+	depw		%r24, 31,22, %r28	/* Form aliased virtual address 'to' */
+	depwi		0, 31,12, %r28		/* Clear any offset bits */
+	copy		%r28, %r29
+	depwi		1, 9,1, %r29		/* Form aliased virtual address 'from' */
 #endif
 
 	/* Purge any old translations */
 
-	pdtlb   0(%r28)
-	pdtlb   0(%r29)
+	pdtlb		0(%r28)
+	pdtlb		0(%r29)
 
-	ldi 64,%r1
+	ldi		64, %r1
 
 	/*
 	 * This loop is optimized for PCXL/PCXL2 ldw/ldw and stw/stw
@@ -432,43 +490,43 @@
 
 
 1:
-	ldw 0(%r29),%r19
-	ldw 4(%r29),%r20
-	ldw 8(%r29),%r21
-	ldw 12(%r29),%r22
-	stw %r19,0(%r28)
-	stw %r20,4(%r28)
-	stw %r21,8(%r28)
-	stw %r22,12(%r28)
-	ldw 16(%r29),%r19
-	ldw 20(%r29),%r20
-	ldw 24(%r29),%r21
-	ldw 28(%r29),%r22
-	stw %r19,16(%r28)
-	stw %r20,20(%r28)
-	stw %r21,24(%r28)
-	stw %r22,28(%r28)
-	ldw 32(%r29),%r19
-	ldw 36(%r29),%r20
-	ldw 40(%r29),%r21
-	ldw 44(%r29),%r22
-	stw %r19,32(%r28)
-	stw %r20,36(%r28)
-	stw %r21,40(%r28)
-	stw %r22,44(%r28)
-	ldw 48(%r29),%r19
-	ldw 52(%r29),%r20
-	ldw 56(%r29),%r21
-	ldw 60(%r29),%r22
-	stw %r19,48(%r28)
-	stw %r20,52(%r28)
-	stw %r21,56(%r28)
-	stw %r22,60(%r28)
-	ldo 64(%r28),%r28
-	ADDIB>  -1,%r1,1b
-	ldo 64(%r29),%r29
+	ldw		0(%r29), %r19
+	ldw		4(%r29), %r20
+	ldw		8(%r29), %r21
+	ldw		12(%r29), %r22
+	stw		%r19, 0(%r28)
+	stw		%r20, 4(%r28)
+	stw		%r21, 8(%r28)
+	stw		%r22, 12(%r28)
+	ldw		16(%r29), %r19
+	ldw		20(%r29), %r20
+	ldw		24(%r29), %r21
+	ldw		28(%r29), %r22
+	stw		%r19, 16(%r28)
+	stw		%r20, 20(%r28)
+	stw		%r21, 24(%r28)
+	stw		%r22, 28(%r28)
+	ldw		32(%r29), %r19
+	ldw		36(%r29), %r20
+	ldw		40(%r29), %r21
+	ldw		44(%r29), %r22
+	stw		%r19, 32(%r28)
+	stw		%r20, 36(%r28)
+	stw		%r21, 40(%r28)
+	stw		%r22, 44(%r28)
+	ldw		48(%r29), %r19
+	ldw		52(%r29), %r20
+	ldw		56(%r29), %r21
+	ldw		60(%r29), %r22
+	stw		%r19, 48(%r28)
+	stw		%r20, 52(%r28)
+	stw		%r21, 56(%r28)
+	stw		%r22, 60(%r28)
+	ldo		64(%r28), %r28
+	ADDIB>		-1, %r1,1b
+	ldo		64(%r29), %r29
 
-	bv      %r0(%r2)
+	bv		%r0(%r2)
 	nop
 	.exit
 
@@ -482,49 +540,77 @@
 	.callinfo NO_CALLS
 	.entry
 
-	tophys_r1 %r26
+	tophys_r1	%r26
 
-	ldil    L%(TMPALIAS_MAP_START),%r28
+	ldil		L%(TMPALIAS_MAP_START), %r28
 #ifdef __LP64__
 #if (TMPALIAS_MAP_START >= 0x80000000)
-	depdi	0,31,32,%r28	/* clear any sign extension */
+	depdi		0, 31,32, %r28		/* clear any sign extension */
 #endif
-	extrd,u %r26,56,32,%r26 /* convert phys addr to tlb insert format */
-	depd    %r25,63,22,%r28 /* Form aliased virtual address 'to' */
-	depdi   0,63,12,%r28    /* Clear any offset bits */
-#else
-	extrw,u %r26,24,25,%r26 /* convert phys addr to tlb insert format */
-	depw    %r25,31,22,%r28 /* Form aliased virtual address 'to' */
-	depwi   0,31,12,%r28    /* Clear any offset bits */
+	extrd,u		%r26, 56,32, %r26	/* convert phys addr to tlb insert format */
+	depd		%r25, 63,22, %r28	/* Form aliased virtual address 'to' */
+	depdi		0, 63,12, %r28		/* Clear any offset bits */
+#else
+	extrw,u		%r26, 24,25, %r26	/* convert phys addr to tlb insert format */
+	depw		%r25, 31,22, %r28	/* Form aliased virtual address 'to' */
+	depwi		0, 31,12, %r28		/* Clear any offset bits */
 #endif
 
 	/* Purge any old translation */
 
-	pdtlb   0(%r28)
+	pdtlb		0(%r28)
 
-	ldi 64,%r1
+#ifdef __LP64__
+	ldi		32, %r1			/* PAGE_SIZE/128 == 32 */
+
+	/* PREFETCH (Write) has not (yet) been proven to help here */
+/* #define	PREFETCHW_OP	ldd		256(%0), %r0 */
+
+1:	std		%r0, 0(%r28)
+	std		%r0, 8(%r28)
+	std		%r0, 16(%r28)
+	std		%r0, 24(%r28)
+	std		%r0, 32(%r28)
+	std		%r0, 40(%r28)
+	std		%r0, 48(%r28)
+	std		%r0, 56(%r28)
+	std		%r0, 64(%r28)
+	std		%r0, 72(%r28)
+	std		%r0, 80(%r28)
+	std		%r0, 88(%r28)
+	std		%r0, 96(%r28)
+	std		%r0, 104(%r28)
+	std		%r0, 112(%r28)
+	std		%r0, 120(%r28)
+	ADDIB>		-1, %r1, 1b
+	ldo		128(%r28), %r28
+
+#else	/* ! __LP64 */
+
+	ldi		64, %r1			/* PAGE_SIZE/64 == 64 */
 
 1:
-	stw %r0,0(%r28)
-	stw %r0,4(%r28)
-	stw %r0,8(%r28)
-	stw %r0,12(%r28)
-	stw %r0,16(%r28)
-	stw %r0,20(%r28)
-	stw %r0,24(%r28)
-	stw %r0,28(%r28)
-	stw %r0,32(%r28)
-	stw %r0,36(%r28)
-	stw %r0,40(%r28)
-	stw %r0,44(%r28)
-	stw %r0,48(%r28)
-	stw %r0,52(%r28)
-	stw %r0,56(%r28)
-	stw %r0,60(%r28)
-	ADDIB>  -1,%r1,1b
-	ldo 64(%r28),%r28
+	stw		%r0, 0(%r28)
+	stw		%r0, 4(%r28)
+	stw		%r0, 8(%r28)
+	stw		%r0, 12(%r28)
+	stw		%r0, 16(%r28)
+	stw		%r0, 20(%r28)
+	stw		%r0, 24(%r28)
+	stw		%r0, 28(%r28)
+	stw		%r0, 32(%r28)
+	stw		%r0, 36(%r28)
+	stw		%r0, 40(%r28)
+	stw		%r0, 44(%r28)
+	stw		%r0, 48(%r28)
+	stw		%r0, 52(%r28)
+	stw		%r0, 56(%r28)
+	stw		%r0, 60(%r28)
+	ADDIB>		-1, %r1, 1b
+	ldo		64(%r28), %r28
+#endif	/* __LP64 */
 
-	bv      %r0(%r2)
+	bv		%r0(%r2)
 	nop
 	.exit
 
@@ -537,38 +623,38 @@
 	.callinfo NO_CALLS
 	.entry
 
-	ldil    L%dcache_stride,%r1
-	ldw     R%dcache_stride(%r1),%r23
+	ldil		L%dcache_stride, %r1
+	ldw		R%dcache_stride(%r1), %r23
 
 #ifdef __LP64__
-	depdi,z 1,63-PAGE_SHIFT,1,%r25
+	depdi,z		1, 63-PAGE_SHIFT,1, %r25
 #else
-	depwi,z 1,31-PAGE_SHIFT,1,%r25
+	depwi,z		1, 31-PAGE_SHIFT,1, %r25
 #endif
-	add     %r26,%r25,%r25
-	sub     %r25,%r23,%r25
-
-
-1:      fdc,m   %r23(%r26)
-	fdc,m   %r23(%r26)
-	fdc,m   %r23(%r26)
-	fdc,m   %r23(%r26)
-	fdc,m   %r23(%r26)
-	fdc,m   %r23(%r26)
-	fdc,m   %r23(%r26)
-	fdc,m   %r23(%r26)
-	fdc,m   %r23(%r26)
-	fdc,m   %r23(%r26)
-	fdc,m   %r23(%r26)
-	fdc,m   %r23(%r26)
-	fdc,m   %r23(%r26)
-	fdc,m   %r23(%r26)
-	fdc,m   %r23(%r26)
-	CMPB<<  %r26,%r25,1b
-	fdc,m   %r23(%r26)
+	add		%r26, %r25, %r25
+	sub		%r25, %r23, %r25
+
+
+1:      fdc,m		%r23(%r26)
+	fdc,m		%r23(%r26)
+	fdc,m		%r23(%r26)
+	fdc,m		%r23(%r26)
+	fdc,m		%r23(%r26)
+	fdc,m		%r23(%r26)
+	fdc,m		%r23(%r26)
+	fdc,m		%r23(%r26)
+	fdc,m		%r23(%r26)
+	fdc,m		%r23(%r26)
+	fdc,m		%r23(%r26)
+	fdc,m		%r23(%r26)
+	fdc,m		%r23(%r26)
+	fdc,m		%r23(%r26)
+	fdc,m		%r23(%r26)
+	CMPB<<		%r26, %r25,1b
+	fdc,m		%r23(%r26)
 
 	sync
-	bv      %r0(%r2)
+	bv		%r0(%r2)
 	nop
 	.exit
 
@@ -581,38 +667,38 @@
 	.callinfo NO_CALLS
 	.entry
 
-	ldil    L%dcache_stride,%r1
-	ldw     R%dcache_stride(%r1),%r23
+	ldil		L%dcache_stride, %r1
+	ldw		R%dcache_stride(%r1), %r23
 
 #ifdef __LP64__
-	depdi,z 1,63-PAGE_SHIFT,1,%r25
+	depdi,z		1,63-PAGE_SHIFT,1, %r25
 #else
-	depwi,z 1,31-PAGE_SHIFT,1,%r25
+	depwi,z		1,31-PAGE_SHIFT,1, %r25
 #endif
-	add     %r26,%r25,%r25
-	sub     %r25,%r23,%r25
-
-
-1:      fdc,m   %r23(%sr3,%r26)
-	fdc,m   %r23(%sr3,%r26)
-	fdc,m   %r23(%sr3,%r26)
-	fdc,m   %r23(%sr3,%r26)
-	fdc,m   %r23(%sr3,%r26)
-	fdc,m   %r23(%sr3,%r26)
-	fdc,m   %r23(%sr3,%r26)
-	fdc,m   %r23(%sr3,%r26)
-	fdc,m   %r23(%sr3,%r26)
-	fdc,m   %r23(%sr3,%r26)
-	fdc,m   %r23(%sr3,%r26)
-	fdc,m   %r23(%sr3,%r26)
-	fdc,m   %r23(%sr3,%r26)
-	fdc,m   %r23(%sr3,%r26)
-	fdc,m   %r23(%sr3,%r26)
-	CMPB<<  %r26,%r25,1b
-	fdc,m   %r23(%sr3,%r26)
+	add		%r26, %r25, %r25
+	sub		%r25, %r23, %r25
+
+
+1:      fdc,m		%r23(%sr3, %r26)
+	fdc,m		%r23(%sr3, %r26)
+	fdc,m		%r23(%sr3, %r26)
+	fdc,m		%r23(%sr3, %r26)
+	fdc,m		%r23(%sr3, %r26)
+	fdc,m		%r23(%sr3, %r26)
+	fdc,m		%r23(%sr3, %r26)
+	fdc,m		%r23(%sr3, %r26)
+	fdc,m		%r23(%sr3, %r26)
+	fdc,m		%r23(%sr3, %r26)
+	fdc,m		%r23(%sr3, %r26)
+	fdc,m		%r23(%sr3, %r26)
+	fdc,m		%r23(%sr3, %r26)
+	fdc,m		%r23(%sr3, %r26)
+	fdc,m		%r23(%sr3, %r26)
+	CMPB<<		%r26, %r25,1b
+	fdc,m		%r23(%sr3, %r26)
 
 	sync
-	bv      %r0(%r2)
+	bv		%r0(%r2)
 	nop
 	.exit
 
@@ -625,38 +711,38 @@
 	.callinfo NO_CALLS
 	.entry
 
-	ldil    L%dcache_stride,%r1
-	ldw     R%dcache_stride(%r1),%r23
+	ldil		L%dcache_stride, %r1
+	ldw		R%dcache_stride(%r1), %r23
 
 #ifdef __LP64__
-	depdi,z 1,63-PAGE_SHIFT,1,%r25
+	depdi,z		1, 63-PAGE_SHIFT,1, %r25
 #else
-	depwi,z 1,31-PAGE_SHIFT,1,%r25
+	depwi,z		1, 31-PAGE_SHIFT,1, %r25
 #endif
-	add     %r26,%r25,%r25
-	sub     %r25,%r23,%r25
-
-
-1:      fic,m   %r23(%sr3,%r26)
-	fic,m   %r23(%sr3,%r26)
-	fic,m   %r23(%sr3,%r26)
-	fic,m   %r23(%sr3,%r26)
-	fic,m   %r23(%sr3,%r26)
-	fic,m   %r23(%sr3,%r26)
-	fic,m   %r23(%sr3,%r26)
-	fic,m   %r23(%sr3,%r26)
-	fic,m   %r23(%sr3,%r26)
-	fic,m   %r23(%sr3,%r26)
-	fic,m   %r23(%sr3,%r26)
-	fic,m   %r23(%sr3,%r26)
-	fic,m   %r23(%sr3,%r26)
-	fic,m   %r23(%sr3,%r26)
-	fic,m   %r23(%sr3,%r26)
-	CMPB<<  %r26,%r25,1b
-	fic,m   %r23(%sr3,%r26)
+	add		%r26, %r25, %r25
+	sub		%r25, %r23, %r25
+
+
+1:      fic,m		%r23(%sr3, %r26)
+	fic,m		%r23(%sr3, %r26)
+	fic,m		%r23(%sr3, %r26)
+	fic,m		%r23(%sr3, %r26)
+	fic,m		%r23(%sr3, %r26)
+	fic,m		%r23(%sr3, %r26)
+	fic,m		%r23(%sr3, %r26)
+	fic,m		%r23(%sr3, %r26)
+	fic,m		%r23(%sr3, %r26)
+	fic,m		%r23(%sr3, %r26)
+	fic,m		%r23(%sr3, %r26)
+	fic,m		%r23(%sr3, %r26)
+	fic,m		%r23(%sr3, %r26)
+	fic,m		%r23(%sr3, %r26)
+	fic,m		%r23(%sr3, %r26)
+	CMPB<<		%r26, %r25,1b
+	fic,m		%r23(%sr3, %r26)
 
 	sync
-	bv      %r0(%r2)
+	bv		%r0(%r2)
 	nop
 	.exit
 
@@ -670,37 +756,37 @@
 	.callinfo NO_CALLS
 	.entry
 
-	ldil    L%dcache_stride,%r1
-	ldw     R%dcache_stride(%r1),%r23
+	ldil		L%dcache_stride, %r1
+	ldw		R%dcache_stride(%r1), %r23
 
 #ifdef __LP64__
-	depdi,z 1,63-PAGE_SHIFT,1,%r25
+	depdi,z		1, 63-PAGE_SHIFT,1, %r25
 #else
-	depwi,z 1,31-PAGE_SHIFT,1,%r25
+	depwi,z		1, 31-PAGE_SHIFT,1, %r25
 #endif
-	add      %r26,%r25,%r25
-	sub      %r25,%r23,%r25
-
-1:      pdc,m   %r23(%r26)
-	pdc,m   %r23(%r26)
-	pdc,m   %r23(%r26)
-	pdc,m   %r23(%r26)
-	pdc,m   %r23(%r26)
-	pdc,m   %r23(%r26)
-	pdc,m   %r23(%r26)
-	pdc,m   %r23(%r26)
-	pdc,m   %r23(%r26)
-	pdc,m   %r23(%r26)
-	pdc,m   %r23(%r26)
-	pdc,m   %r23(%r26)
-	pdc,m   %r23(%r26)
-	pdc,m   %r23(%r26)
-	pdc,m   %r23(%r26)
-	CMPB<<  %r26,%r25,1b
-	pdc,m   %r23(%r26)
+	add		%r26, %r25, %r25
+	sub		%r25, %r23, %r25
+
+1:      pdc,m		%r23(%r26)
+	pdc,m		%r23(%r26)
+	pdc,m		%r23(%r26)
+	pdc,m		%r23(%r26)
+	pdc,m		%r23(%r26)
+	pdc,m		%r23(%r26)
+	pdc,m		%r23(%r26)
+	pdc,m		%r23(%r26)
+	pdc,m		%r23(%r26)
+	pdc,m		%r23(%r26)
+	pdc,m		%r23(%r26)
+	pdc,m		%r23(%r26)
+	pdc,m		%r23(%r26)
+	pdc,m		%r23(%r26)
+	pdc,m		%r23(%r26)
+	CMPB<<		%r26, %r25, 1b
+	pdc,m		%r23(%r26)
 
 	sync
-	bv      %r0(%r2)
+	bv		%r0(%r2)
 	nop
 	.exit
 
@@ -718,54 +804,54 @@
 	.callinfo NO_CALLS
 	.entry
 
-	tophys_r1 %r26
+	tophys_r1		%r26
 
-	ldil    L%(TMPALIAS_MAP_START),%r28
+	ldil		L%(TMPALIAS_MAP_START), %r28
 #ifdef __LP64__
-	extrd,u %r26,56,32,%r26 /* convert phys addr to tlb insert format */
-	depd    %r25,63,22,%r28 /* Form aliased virtual address 'to' */
-	depdi   0,63,12,%r28    /* Clear any offset bits */
+	extrd,u		%r26, 56,32, %r26	/* convert phys addr to tlb insert format */
+	depd		%r25, 63,22, %r28	/* Form aliased virtual address 'to' */
+	depdi		0, 63,12, %r28		/* Clear any offset bits */
 #else
-	extrw,u %r26,24,25,%r26 /* convert phys addr to tlb insert format */
-	depw    %r25,31,22,%r28 /* Form aliased virtual address 'to' */
-	depwi   0,31,12,%r28    /* Clear any offset bits */
+	extrw,u		%r26, 24,25, %r26	/* convert phys addr to tlb insert format */
+	depw		%r25, 31,22, %r28	/* Form aliased virtual address 'to' */
+	depwi		0, 31,12, %r28		/* Clear any offset bits */
 #endif
 
 	/* Purge any old translation */
 
-	pdtlb   0(%r28)
+	pdtlb		0(%r28)
 
-	ldil    L%dcache_stride,%r1
-	ldw     R%dcache_stride(%r1),%r23
+	ldil		L%dcache_stride, %r1
+	ldw		R%dcache_stride(%r1), %r23
 
 #ifdef __LP64__
-	depdi,z 1,63-PAGE_SHIFT,1,%r29
+	depdi,z		1, 63-PAGE_SHIFT,1, %r29
 #else
-	depwi,z 1,31-PAGE_SHIFT,1,%r29
-#endif
-	add      %r28,%r29,%r29
-	sub      %r29,%r23,%r29
-
-1:      fdc,m   %r23(%r28)
-	fdc,m   %r23(%r28)
-	fdc,m   %r23(%r28)
-	fdc,m   %r23(%r28)
-	fdc,m   %r23(%r28)
-	fdc,m   %r23(%r28)
-	fdc,m   %r23(%r28)
-	fdc,m   %r23(%r28)
-	fdc,m   %r23(%r28)
-	fdc,m   %r23(%r28)
-	fdc,m   %r23(%r28)
-	fdc,m   %r23(%r28)
-	fdc,m   %r23(%r28)
-	fdc,m   %r23(%r28)
-	fdc,m   %r23(%r28)
-	CMPB<<  %r28,%r29,1b
-	fdc,m   %r23(%r28)
+	depwi,z		1, 31-PAGE_SHIFT,1, %r29
+#endif
+	add		%r28, %r29, %r29
+	sub		%r29, %r23, %r29
+
+1:      fdc,m		%r23(%r28)
+	fdc,m		%r23(%r28)
+	fdc,m		%r23(%r28)
+	fdc,m		%r23(%r28)
+	fdc,m		%r23(%r28)
+	fdc,m		%r23(%r28)
+	fdc,m		%r23(%r28)
+	fdc,m		%r23(%r28)
+	fdc,m		%r23(%r28)
+	fdc,m		%r23(%r28)
+	fdc,m		%r23(%r28)
+	fdc,m		%r23(%r28)
+	fdc,m		%r23(%r28)
+	fdc,m		%r23(%r28)
+	fdc,m		%r23(%r28)
+	CMPB<<		%r28, %r29, 1b
+	fdc,m		%r23(%r28)
 
 	sync
-	bv      %r0(%r2)
+	bv		%r0(%r2)
 	nop
 	.exit
 
@@ -779,16 +865,16 @@
 	.callinfo NO_CALLS
 	.entry
 
-	ldil    L%dcache_stride,%r1
-	ldw     R%dcache_stride(%r1),%r23
-	ldo     -1(%r23),%r21
-	ANDCM   %r26,%r21,%r26
+	ldil		L%dcache_stride, %r1
+	ldw		R%dcache_stride(%r1), %r23
+	ldo		-1(%r23), %r21
+	ANDCM		%r26, %r21, %r26
 
-1:      CMPB<<,n %r26,%r25,1b
-	fdc,m   %r23(%sr3,%r26)
+1:      CMPB<<,n	%r26, %r25, 1b
+	fdc,m		%r23(%sr3, %r26)
 
 	sync
-	bv      %r0(%r2)
+	bv		%r0(%r2)
 	nop
 	.exit
 
@@ -801,17 +887,17 @@
 	.callinfo NO_CALLS
 	.entry
 
-	ldil    L%dcache_stride,%r1
-	ldw     R%dcache_stride(%r1),%r23
-	ldo     -1(%r23),%r21
-	ANDCM   %r26,%r21,%r26
+	ldil		L%dcache_stride, %r1
+	ldw		R%dcache_stride(%r1), %r23
+	ldo		-1(%r23), %r21
+	ANDCM		%r26, %r21, %r26
 
-1:      CMPB<<,n %r26,%r25,1b
-	fdc,m   %r23(%r26)
+1:      CMPB<<,n	%r26, %r25,1b
+	fdc,m		%r23(%r26)
 
 	sync
 	syncdma
-	bv      %r0(%r2)
+	bv		%r0(%r2)
 	nop
 	.exit
 
@@ -824,16 +910,16 @@
 	.callinfo NO_CALLS
 	.entry
 
-	ldil    L%icache_stride,%r1
-	ldw     R%icache_stride(%r1),%r23
-	ldo     -1(%r23),%r21
-	ANDCM   %r26,%r21,%r26
+	ldil		L%icache_stride, %r1
+	ldw		R%icache_stride(%r1), %r23
+	ldo		-1(%r23), %r21
+	ANDCM		%r26, %r21, %r26
 
-1:      CMPB<<,n %r26,%r25,1b
-	fic,m   %r23(%sr3,%r26)
+1:      CMPB<<,n	%r26, %r25,1b
+	fic,m		%r23(%sr3, %r26)
 
 	sync
-	bv      %r0(%r2)
+	bv		%r0(%r2)
 	nop
 	.exit
 
@@ -846,38 +932,38 @@
 	.callinfo NO_CALLS
 	.entry
 
-	ldil    L%icache_stride,%r1
-	ldw     R%icache_stride(%r1),%r23
+	ldil		L%icache_stride, %r1
+	ldw		R%icache_stride(%r1), %r23
 
 #ifdef __LP64__
-	depdi,z 1,63-PAGE_SHIFT,1,%r25
+	depdi,z		1, 63-PAGE_SHIFT,1, %r25
 #else
-	depwi,z 1,31-PAGE_SHIFT,1,%r25
+	depwi,z		1, 31-PAGE_SHIFT,1, %r25
 #endif
-	add     %r26,%r25,%r25
-	sub     %r25,%r23,%r25
-
-
-1:      fic,m   %r23(%r26)
-	fic,m   %r23(%r26)
-	fic,m   %r23(%r26)
-	fic,m   %r23(%r26)
-	fic,m   %r23(%r26)
-	fic,m   %r23(%r26)
-	fic,m   %r23(%r26)
-	fic,m   %r23(%r26)
-	fic,m   %r23(%r26)
-	fic,m   %r23(%r26)
-	fic,m   %r23(%r26)
-	fic,m   %r23(%r26)
-	fic,m   %r23(%r26)
-	fic,m   %r23(%r26)
-	fic,m   %r23(%r26)
-	CMPB<<  %r26,%r25,1b
-	fic,m   %r23(%r26)
+	add		%r26, %r25, %r25
+	sub		%r25, %r23, %r25
+
+
+1:      fic,m		%r23(%r26)
+	fic,m		%r23(%r26)
+	fic,m		%r23(%r26)
+	fic,m		%r23(%r26)
+	fic,m		%r23(%r26)
+	fic,m		%r23(%r26)
+	fic,m		%r23(%r26)
+	fic,m		%r23(%r26)
+	fic,m		%r23(%r26)
+	fic,m		%r23(%r26)
+	fic,m		%r23(%r26)
+	fic,m		%r23(%r26)
+	fic,m		%r23(%r26)
+	fic,m		%r23(%r26)
+	fic,m		%r23(%r26)
+	CMPB<<		%r26, %r25, 1b
+	fic,m		%r23(%r26)
 
 	sync
-	bv      %r0(%r2)
+	bv		%r0(%r2)
 	nop
 	.exit
 
@@ -890,22 +976,22 @@
 	.callinfo NO_CALLS
 	.entry
 
-	ldil    L%icache_stride,%r1
-	ldw     R%icache_stride(%r1),%r23
-	ldo     -1(%r23),%r21
-	ANDCM   %r26,%r21,%r26
+	ldil		L%icache_stride, %r1
+	ldw		R%icache_stride(%r1), %r23
+	ldo		-1(%r23), %r21
+	ANDCM		%r26, %r21, %r26
 
-1:      CMPB<<,n %r26,%r25,1b
-	fic,m   %r23(%r26)
+1:      CMPB<<,n	%r26, %r25, 1b
+	fic,m		%r23(%r26)
 
 	sync
-	bv      %r0(%r2)
+	bv		%r0(%r2)
 	nop
 	.exit
 
 	.procend
 
-	.align 128
+	.align	128
 
 	.export disable_sr_hashing_asm,code
 
@@ -916,7 +1002,7 @@
 
 	/* Switch to real mode */
 
-	ssm     0,%r0           /* relied upon translation! */
+	ssm		0, %r0			/* relied upon translation! */
 	nop
 	nop
 	nop
@@ -925,73 +1011,73 @@
 	nop
 	nop
 	
-	rsm     (PSW_SM_Q|PSW_SM_I),%r0 /* disable Q&I to load the iia queue */
-	ldil    L%REAL_MODE_PSW, %r1
-	ldo     R%REAL_MODE_PSW(%r1), %r1
-	mtctl	%r1, %cr22
-	mtctl	%r0, %cr17	/* Clear IIASQ tail */
-	mtctl	%r0, %cr17	/* Clear IIASQ head */
-	ldil    L%PA(1f),%r1
-	ldo     R%PA(1f)(%r1),%r1
-	mtctl	%r1, %cr18	/* IIAOQ head */
-	ldo	4(%r1), %r1
-	mtctl	%r1, %cr18	/* IIAOQ tail */
+	rsm		(PSW_SM_Q|PSW_SM_I), %r0 /* disable Q&I to load the iia queue */
+	ldil		L%REAL_MODE_PSW, %r1
+	ldo		R%REAL_MODE_PSW(%r1), %r1
+	mtctl		%r1, %cr22
+	mtctl		%r0, %cr17		/* Clear IIASQ tail */
+	mtctl		%r0, %cr17		/* Clear IIASQ head */
+	ldil		L%PA(1f), %r1
+	ldo		R%PA(1f)(%r1), %r1
+	mtctl		%r1, %cr18		/* IIAOQ head */
+	ldo		4(%r1), %r1
+	mtctl		%r1, %cr18		/* IIAOQ tail */
 	rfi
 	nop
 
-1:      cmpib,=,n SRHASH_PCXST,%r26,srdis_pcxs
-	cmpib,=,n SRHASH_PCXL,%r26,srdis_pcxl
-	cmpib,=,n SRHASH_PA20,%r26,srdis_pa20
-	b,n       srdis_done
+1:      cmpib,=,n	SRHASH_PCXST, %r26,srdis_pcxs
+	cmpib,=,n	SRHASH_PCXL, %r26,srdis_pcxl
+	cmpib,=,n	SRHASH_PA20, %r26,srdis_pa20
+	b,n		srdis_done
 
 srdis_pcxs:
 
 	/* Disable Space Register Hashing for PCXS,PCXT,PCXT' */
 
-	.word           0x141c1a00  /* mfdiag %dr0,%r28 */
-	.word           0x141c1a00  /* must issue twice */
-	depwi           0,18,1,%r28 /* Clear DHE (dcache hash enable) */
-	depwi           0,20,1,%r28 /* Clear IHE (icache hash enable) */
-	.word           0x141c1600  /* mtdiag %r28,%dr0 */
-	.word           0x141c1600  /* must issue twice */
-	b,n             srdis_done
+	.word		0x141c1a00		/* mfdiag %dr0, %r28 */
+	.word		0x141c1a00		/* must issue twice */
+	depwi		0,18,1, %r28		/* Clear DHE (dcache hash enable) */
+	depwi		0,20,1, %r28		/* Clear IHE (icache hash enable) */
+	.word		0x141c1600		/* mtdiag %r28, %dr0 */
+	.word		0x141c1600		/* must issue twice */
+	b,n		srdis_done
 
 srdis_pcxl:
 
 	/* Disable Space Register Hashing for PCXL */
 
-	.word           0x141c0600  /* mfdiag %dr0,%r28 */
-	depwi           0,28,2,%r28 /* Clear DHASH_EN & IHASH_EN */
-	.word           0x141c0240  /* mtdiag %r28,%dr0 */
-	b,n             srdis_done
+	.word		0x141c0600		/* mfdiag %dr0, %r28 */
+	depwi           0,28,2, %r28		/* Clear DHASH_EN & IHASH_EN */
+	.word		0x141c0240		/* mtdiag %r28, %dr0 */
+	b,n		srdis_done
 
 srdis_pa20:
 
 	/* Disable Space Register Hashing for PCXU,PCXU+,PCXW,PCXW+ */
 
-	.word           0x144008bc  /* mfdiag %dr2,%r28 */
-	depdi           0,54,1,%r28 /* clear DIAG_SPHASH_ENAB (bit 54) */
-	.word           0x145c1840  /* mtdiag %r28,%dr2 */
+	.word		0x144008bc		/* mfdiag %dr2, %r28 */
+	depdi		0, 54,1, %r28		/* clear DIAG_SPHASH_ENAB (bit 54) */
+	.word		0x145c1840		/* mtdiag %r28, %dr2 */
 
 srdis_done:
 
 	/* Switch back to virtual mode */
 
-	rsm     PSW_SM_Q,%r0           /* clear Q bit to load iia queue */
-	ldil	L%KERNEL_PSW, %r1
-	ldo	R%KERNEL_PSW(%r1), %r1
-	mtctl	%r1, %cr22
-	mtctl	%r0, %cr17	/* Clear IIASQ tail */
-	mtctl	%r0, %cr17	/* Clear IIASQ head */
-	ldil    L%(2f), %r1
-	ldo     R%(2f)(%r1), %r1
-	mtctl	%r1, %cr18	/* IIAOQ head */
-	ldo	4(%r1), %r1
-	mtctl	%r1, %cr18	/* IIAOQ tail */
+	rsm		PSW_SM_Q, %r0		/* clear Q bit to load iia queue */
+	ldil		L%KERNEL_PSW, %r1
+	ldo		R%KERNEL_PSW(%r1), %r1
+	mtctl		%r1, %cr22
+	mtctl		%r0, %cr17		/* Clear IIASQ tail */
+	mtctl		%r0, %cr17		/* Clear IIASQ head */
+	ldil 	   	L%(2f), %r1
+	ldo     	R%(2f)(%r1), %r1
+	mtctl		%r1, %cr18		/* IIAOQ head */
+	ldo		4(%r1), %r1
+	mtctl		%r1, %cr18		/* IIAOQ tail */
 	rfi
 	nop
 
-2:      bv      %r0(%r2)
+2:      bv		%r0(%r2)
 	nop
 	.exit
 
diff -Nru a/arch/parisc/kernel/pci-dma.c b/arch/parisc/kernel/pci-dma.c
--- a/arch/parisc/kernel/pci-dma.c	2005-03-11 12:51:51 -08:00
+++ b/arch/parisc/kernel/pci-dma.c	2005-03-11 12:51:51 -08:00
@@ -180,7 +180,7 @@
 		end = PMD_SIZE;
 	do {
 		pte_t page = *pte;
-		pte_clear(pte);
+		pte_clear(&init_mm, vaddr, pte);
 		purge_tlb_start();
 		pdtlb_kernel(orig_vaddr);
 		purge_tlb_end();
diff -Nru a/arch/parisc/kernel/pdc_chassis.c b/arch/parisc/kernel/pdc_chassis.c
--- a/arch/parisc/kernel/pdc_chassis.c	2005-03-11 12:51:46 -08:00
+++ b/arch/parisc/kernel/pdc_chassis.c	2005-03-11 12:51:46 -08:00
@@ -182,7 +182,7 @@
 
 		DPRINTK(KERN_DEBUG "%s: pdc_chassis_send_status(%d)\n", __FILE__, message);
 
-#ifdef CONFIG_PARISC64
+#ifdef CONFIG_64BIT
 		if (is_pdc_pat()) {
 			switch(message) {
 				case PDC_CHASSIS_DIRECT_BSTART:
@@ -238,7 +238,7 @@
 					retval = -1;
 			}
 		} else retval = -1;
-#endif /* CONFIG_PARISC64 */
+#endif /* CONFIG_64BIT */
 	}	/* if (pdc_chassis_enabled) */
 #endif /* CONFIG_PDC_CHASSIS */
 	return retval;
diff -Nru a/arch/parisc/kernel/perf.c b/arch/parisc/kernel/perf.c
--- a/arch/parisc/kernel/perf.c	2005-03-11 12:51:42 -08:00
+++ b/arch/parisc/kernel/perf.c	2005-03-11 12:51:42 -08:00
@@ -42,7 +42,6 @@
  *  on every box. 
  */
 
-#include <linux/config.h>
 #include <linux/init.h>
 #include <linux/proc_fs.h>
 #include <linux/miscdevice.h>
@@ -157,16 +156,16 @@
  * this array.
  */
 static uint64_t perf_bitmasks[] = {
-	0x0000000000000000,     /* first dbl word must be zero */
-	0xfdffe00000000000,     /* RDR0 bitmask */
-	0x003f000000000000,     /* RDR1 bitmask */
-	0x00ffffffffffffff,     /* RDR20-RDR21 bitmask (152 bits) */
-	0xffffffffffffffff,
-	0xfffffffc00000000,
-	0xffffffffffffffff,     /* RDR22-RDR23 bitmask (233 bits) */
-	0xffffffffffffffff,
-	0xfffffffffffffffc,
-	0xff00000000000000
+	0x0000000000000000ul,     /* first dbl word must be zero */
+	0xfdffe00000000000ul,     /* RDR0 bitmask */
+	0x003f000000000000ul,     /* RDR1 bitmask */
+	0x00fffffffffffffful,     /* RDR20-RDR21 bitmask (152 bits) */
+	0xfffffffffffffffful,
+	0xfffffffc00000000ul,
+	0xfffffffffffffffful,     /* RDR22-RDR23 bitmask (233 bits) */
+	0xfffffffffffffffful,
+	0xfffffffffffffffcul,
+	0xff00000000000000ul
 };
 
 /*
@@ -174,16 +173,16 @@
  * somethings have changed slightly.
  */
 static uint64_t perf_bitmasks_piranha[] = {
-	0x0000000000000000,     /* first dbl word must be zero */
-	0xfdffe00000000000,     /* RDR0 bitmask */
-	0x003f000000000000,     /* RDR1 bitmask */
-	0x00ffffffffffffff,     /* RDR20-RDR21 bitmask (158 bits) */
-	0xffffffffffffffff,
-	0xfffffffc00000000,
-	0xffffffffffffffff,     /* RDR22-RDR23 bitmask (210 bits) */
-	0xffffffffffffffff,
-	0xffffffffffffffff,
-	0xfffc000000000000
+	0x0000000000000000ul,     /* first dbl word must be zero */
+	0xfdffe00000000000ul,     /* RDR0 bitmask */
+	0x003f000000000000ul,     /* RDR1 bitmask */
+	0x00fffffffffffffful,     /* RDR20-RDR21 bitmask (158 bits) */
+	0xfffffffffffffffful,
+	0xfffffffc00000000ul,
+	0xfffffffffffffffful,     /* RDR22-RDR23 bitmask (210 bits) */
+	0xfffffffffffffffful,
+	0xfffffffffffffffful,
+	0xfffc000000000000ul
 };
 
 static uint64_t *bitmask_array;   /* array of bitmasks to use */
@@ -194,8 +193,8 @@
 static int perf_config(uint32_t *image_ptr);
 static int perf_release(struct inode *inode, struct file *file);
 static int perf_open(struct inode *inode, struct file *file);
-static ssize_t perf_read(struct file *file, char *buf, size_t cnt, loff_t *ppos);
-static ssize_t perf_write(struct file *file, const char *buf, size_t count, 
+static ssize_t perf_read(struct file *file, char __user *buf, size_t cnt, loff_t *ppos);
+static ssize_t perf_write(struct file *file, const char __user *buf, size_t count, 
 	loff_t *ppos);
 static int perf_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
 	unsigned long arg);
@@ -287,7 +286,7 @@
 /*
  * Read does nothing for this driver
  */
-static ssize_t perf_read(struct file *file, char *buf, size_t cnt, loff_t *ppos)
+static ssize_t perf_read(struct file *file, char __user *buf, size_t cnt, loff_t *ppos)
 {
 	return 0;
 }
@@ -299,7 +298,7 @@
  * called on the processor that the download should happen
  * on.
  */
-static ssize_t perf_write(struct file *file, const char *buf, size_t count, 
+static ssize_t perf_write(struct file *file, const char __user *buf, size_t count, 
 	loff_t *ppos)
 {
 	int err;
@@ -460,7 +459,7 @@
 			}
 
 			/* copy out the Counters */
-			if (copy_to_user((void *)arg, raddr, 
+			if (copy_to_user((void __user *)arg, raddr, 
 					sizeof (raddr)) != 0) {
 				return -EFAULT;
 			}
@@ -607,7 +606,7 @@
 		 * all of dword 22 and 58 bits (plus 6 don't care bits) of
 		 * dword 23.
 		 */
-		userbuf[21] &= 0xfffffffffffffc00;	/* 0 to last 10 bits */
+		userbuf[21] &= 0xfffffffffffffc00ul;	/* 0 to last 10 bits */
 		userbuf[22] = 0;
 		userbuf[23] = 0;
 
@@ -802,8 +801,8 @@
 	proc_hpa = cpu_device->hpa;
 
 	/* Merge intrigue bits into Runway STATUS 0 */
-	tmp64 = __raw_readq(proc_hpa + RUNWAY_STATUS) & 0xffecffffffffffff;
-	__raw_writeq(tmp64 | (*memaddr++ & 0x0013000000000000), proc_hpa + RUNWAY_STATUS);
+	tmp64 = __raw_readq(proc_hpa + RUNWAY_STATUS) & 0xffecfffffffffffful;
+	__raw_writeq(tmp64 | (*memaddr++ & 0x0013000000000000ul), proc_hpa + RUNWAY_STATUS);
 	
 	/* Write RUNWAY DEBUG registers */
 	for (i = 0; i < 8; i++) {
diff -Nru a/arch/parisc/kernel/perf_asm.S b/arch/parisc/kernel/perf_asm.S
--- a/arch/parisc/kernel/perf_asm.S	2005-03-11 12:51:50 -08:00
+++ b/arch/parisc/kernel/perf_asm.S	2005-03-11 12:51:50 -08:00
@@ -22,9 +22,9 @@
 #include <linux/config.h>
 #include <asm/assembly.h>
 
-#ifdef __LP64__
+#ifdef CONFIG_64BIT
 	.level		2.0w
-#endif /* __LP64__ */
+#endif /* CONFIG_64BIT */
 
 #define MTDIAG_1(gr)    .word 0x14201840 + gr*0x10000
 #define MTDIAG_2(gr)    .word 0x14401840 + gr*0x10000
diff -Nru a/arch/parisc/kernel/process.c b/arch/parisc/kernel/process.c
--- a/arch/parisc/kernel/process.c	2005-03-11 12:51:52 -08:00
+++ b/arch/parisc/kernel/process.c	2005-03-11 12:51:52 -08:00
@@ -251,7 +251,7 @@
 sys_clone(unsigned long clone_flags, unsigned long usp,
 	  struct pt_regs *regs)
 {
-	int *user_tid = (int *)regs->gr[26];
+	int __user *user_tid = (int __user *)regs->gr[26];
 
 	/* usp must be word aligned.  This also prevents users from
 	 * passing in the value 1 (which is the signal for a special
@@ -357,12 +357,12 @@
 	int error;
 	char *filename;
 
-	filename = getname((char *) regs->gr[26]);
+	filename = getname((const char __user *) regs->gr[26]);
 	error = PTR_ERR(filename);
 	if (IS_ERR(filename))
 		goto out;
-	error = do_execve(filename, (char **) regs->gr[25],
-		(char **) regs->gr[24], regs);
+	error = do_execve(filename, (char __user **) regs->gr[25],
+		(char __user **) regs->gr[24], regs);
 	if (error == 0) {
 		task_lock(current);
 		current->ptrace &= ~PT_DTRACE;
diff -Nru a/arch/parisc/kernel/real2.S b/arch/parisc/kernel/real2.S
--- a/arch/parisc/kernel/real2.S	2005-03-11 12:51:46 -08:00
+++ b/arch/parisc/kernel/real2.S	2005-03-11 12:51:46 -08:00
@@ -81,8 +81,7 @@
 	rsm	PSW_SM_W, %r0		/* go narrow */
 #endif
 
-	ldil	L%PA(ric_ret), %r2
-	ldo	R%PA(ric_ret)(%r2), %r2
+	load32	PA(ric_ret), %r2
 	bv	0(%r31)
 	nop
 ric_ret:
diff -Nru a/arch/parisc/kernel/setup.c b/arch/parisc/kernel/setup.c
--- a/arch/parisc/kernel/setup.c	2005-03-11 12:51:51 -08:00
+++ b/arch/parisc/kernel/setup.c	2005-03-11 12:51:51 -08:00
@@ -53,6 +53,15 @@
 struct proc_dir_entry * proc_gsc_root = NULL;
 struct proc_dir_entry * proc_mckinley_root = NULL;
 
+#if !defined(CONFIG_PA20) && (defined(CONFIG_IOMMU_CCIO) || defined(CONFIG_IOMMU_SBA))
+int parisc_bus_is_phys = 1;	/* Assume no IOMMU is present */
+EXPORT_SYMBOL(parisc_bus_is_phys);
+#endif
+
+/* This sets the vmerge boundary and size, it's here because it has to
+ * be available on all platforms (zero means no-virtual merging) */
+unsigned long parisc_vmerge_boundary = 0;
+unsigned long parisc_vmerge_max_size = 0;
 
 void __init setup_cmdline(char **cmdline_p)
 {
@@ -199,7 +208,7 @@
 	case pcxl2:
 		if (NULL == proc_gsc_root)
 		{
-			proc_gsc_root = proc_mkdir("bus/gsc", 0);
+			proc_gsc_root = proc_mkdir("bus/gsc", NULL);
 		}
 		break;
         case pcxt_:
@@ -210,13 +219,13 @@
         case pcxw2:
                 if (NULL == proc_runway_root)
                 {
-                        proc_runway_root = proc_mkdir("bus/runway", 0);
+                        proc_runway_root = proc_mkdir("bus/runway", NULL);
                 }
                 break;
 	case mako:
                 if (NULL == proc_mckinley_root)
                 {
-                        proc_mckinley_root = proc_mkdir("bus/mckinley", 0);
+                        proc_mckinley_root = proc_mkdir("bus/mckinley", NULL);
                 }
                 break;
 	default:
diff -Nru a/arch/parisc/kernel/signal.c b/arch/parisc/kernel/signal.c
--- a/arch/parisc/kernel/signal.c	2005-03-11 12:51:51 -08:00
+++ b/arch/parisc/kernel/signal.c	2005-03-11 12:51:51 -08:00
@@ -69,7 +69,7 @@
 #endif
 
 asmlinkage int
-sys_rt_sigsuspend(sigset_t *unewset, size_t sigsetsize, struct pt_regs *regs)
+sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize, struct pt_regs *regs)
 {
 	sigset_t saveset, newset;
 #ifdef __LP64__
@@ -79,7 +79,7 @@
 		/* XXX: Don't preclude handling different sized sigset_t's.  */
 		if (sigsetsize != sizeof(compat_sigset_t))
 			return -EINVAL;
-		if (copy_from_user(&newset32, (compat_sigset_t *)unewset, sizeof(newset32)))
+		if (copy_from_user(&newset32, (compat_sigset_t __user *)unewset, sizeof(newset32)))
 			return -EFAULT;
 		sigset_32to64(&newset,&newset32);
 		
@@ -125,7 +125,7 @@
 #define INSN_DIE_HORRIBLY 0x68000ccc /* stw %r0,0x666(%sr0,%r0) */
 
 static long
-restore_sigcontext(struct sigcontext *sc, struct pt_regs *regs)
+restore_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs)
 {
 	long err = 0;
 
@@ -143,14 +143,14 @@
 void
 sys_rt_sigreturn(struct pt_regs *regs, int in_syscall)
 {
-	struct rt_sigframe *frame;
+	struct rt_sigframe __user *frame;
 	struct siginfo si;
 	sigset_t set;
 	unsigned long usp = (regs->gr[30] & ~(0x01UL));
 	unsigned long sigframe_size = PARISC_RT_SIGFRAME_SIZE;
 #ifdef __LP64__
 	compat_sigset_t compat_set;
-	struct compat_rt_sigframe * compat_frame;
+	struct compat_rt_sigframe __user * compat_frame;
 	
 	if(personality(current->personality) == PER_LINUX32)
 		sigframe_size = PARISC_RT_SIGFRAME_SIZE32;
@@ -158,12 +158,12 @@
 
 
 	/* Unwind the user stack to get the rt_sigframe structure. */
-	frame = (struct rt_sigframe *)
+	frame = (struct rt_sigframe __user *)
 		(usp - sigframe_size);
 	DBG(2,"sys_rt_sigreturn: frame is %p\n", frame);
 
 #ifdef __LP64__
-	compat_frame = (struct compat_rt_sigframe *)frame;
+	compat_frame = (struct compat_rt_sigframe __user *)frame;
 	
 	if(personality(current->personality) == PER_LINUX32){
 		DBG(2,"sys_rt_sigreturn: ELF32 process.\n");
@@ -238,7 +238,7 @@
  * Set up a signal frame.
  */
 
-static inline void *
+static inline void __user *
 get_sigframe(struct k_sigaction *ka, unsigned long sp, size_t frame_size)
 {
 	/*FIXME: ELF32 vs. ELF64 has different frame_size, but since we
@@ -251,11 +251,11 @@
 		sp = current->sas_ss_sp; /* Stacks grow up! */
 
 	DBG(1,"get_sigframe: Returning sp = %#lx\n", (unsigned long)sp);
-	return (void *) sp; /* Stacks grow up.  Fun. */
+	return (void __user *) sp; /* Stacks grow up.  Fun. */
 }
 
 static long
-setup_sigcontext(struct sigcontext *sc, struct pt_regs *regs, int in_syscall)
+setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs, int in_syscall)
 		 
 {
 	unsigned long flags = 0;
@@ -292,14 +292,14 @@
 setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
 	       sigset_t *set, struct pt_regs *regs, int in_syscall)
 {
-	struct rt_sigframe *frame;
+	struct rt_sigframe __user *frame;
 	unsigned long rp, usp;
 	unsigned long haddr, sigframe_size;
 	struct siginfo si;
 	int err = 0;
 #ifdef __LP64__
 	compat_int_t compat_val;
-	struct compat_rt_sigframe * compat_frame;
+	struct compat_rt_sigframe __user * compat_frame;
 	compat_sigset_t compat_set;
 #endif
 	
@@ -313,7 +313,7 @@
 	
 #ifdef __LP64__
 
-	compat_frame = (struct compat_rt_sigframe *)frame;
+	compat_frame = (struct compat_rt_sigframe __user *)frame;
 	
 	if(personality(current->personality) == PER_LINUX32) {
 		DBG(1,"setup_rt_frame: frame->info = 0x%p\n", &compat_frame->info);
@@ -396,7 +396,7 @@
 #endif
 		if (haddr & PA_PLABEL_FDESC) {
 			Elf32_Fdesc fdesc;
-			Elf32_Fdesc *ufdesc = (Elf32_Fdesc *)A(haddr & ~3);
+			Elf32_Fdesc __user *ufdesc = (Elf32_Fdesc __user *)A(haddr & ~3);
 
 			err = __copy_from_user(&fdesc, ufdesc, sizeof(fdesc));
 
@@ -409,7 +409,7 @@
 #ifdef __LP64__
 	} else {
 		Elf64_Fdesc fdesc;
-		Elf64_Fdesc *ufdesc = (Elf64_Fdesc *)A(haddr & ~3);
+		Elf64_Fdesc __user *ufdesc = (Elf64_Fdesc __user *)A(haddr & ~3);
 		
 		err = __copy_from_user(&fdesc, ufdesc, sizeof(fdesc));
 		
diff -Nru a/arch/parisc/kernel/signal32.c b/arch/parisc/kernel/signal32.c
--- a/arch/parisc/kernel/signal32.c	2005-03-11 12:51:41 -08:00
+++ b/arch/parisc/kernel/signal32.c	2005-03-11 12:51:41 -08:00
@@ -20,7 +20,6 @@
  *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
-#include <linux/config.h>
 #include <linux/compat.h>
 #include <linux/slab.h>
 #include <linux/module.h>
@@ -65,7 +64,7 @@
 }
 
 static int
-put_sigset32(compat_sigset_t *up, sigset_t *set, size_t sz)
+put_sigset32(compat_sigset_t __user *up, sigset_t *set, size_t sz)
 {
 	compat_sigset_t s;
 
@@ -76,7 +75,7 @@
 }
 
 static int
-get_sigset32(compat_sigset_t *up, sigset_t *set, size_t sz)
+get_sigset32(compat_sigset_t __user *up, sigset_t *set, size_t sz)
 {
 	compat_sigset_t s;
 	int r;
@@ -90,7 +89,7 @@
 	return r;
 }
 
-int sys32_rt_sigprocmask(int how, compat_sigset_t *set, compat_sigset_t *oset,
+int sys32_rt_sigprocmask(int how, compat_sigset_t __user *set, compat_sigset_t __user *oset,
 				    unsigned int sigsetsize)
 {
 	sigset_t old_set, new_set;
@@ -99,8 +98,8 @@
 	if (set && get_sigset32(set, &new_set, sigsetsize))
 		return -EFAULT;
 	
-	KERNEL_SYSCALL(ret, sys_rt_sigprocmask, how, set ? &new_set : NULL,
-				 oset ? &old_set : NULL, sigsetsize);
+	KERNEL_SYSCALL(ret, sys_rt_sigprocmask, how, set ? (sigset_t __user *)&new_set : NULL,
+				 oset ? (sigset_t __user *)&old_set : NULL, sigsetsize);
 
 	if (!ret && oset && put_sigset32(oset, &old_set, sigsetsize))
 		return -EFAULT;
@@ -109,12 +108,12 @@
 }
 
 
-int sys32_rt_sigpending(compat_sigset_t *uset, unsigned int sigsetsize)
+int sys32_rt_sigpending(compat_sigset_t __user *uset, unsigned int sigsetsize)
 {
 	int ret;
 	sigset_t set;
 
-	KERNEL_SYSCALL(ret, sys_rt_sigpending, &set, sigsetsize);
+	KERNEL_SYSCALL(ret, sys_rt_sigpending, (sigset_t __user *)&set, sigsetsize);
 
 	if (!ret && put_sigset32(uset, &set, sigsetsize))
 		return -EFAULT;
@@ -123,7 +122,7 @@
 }
 
 long
-sys32_rt_sigaction(int sig, const struct sigaction32 *act, struct sigaction32 *oact,
+sys32_rt_sigaction(int sig, const struct sigaction32 __user *act, struct sigaction32 __user *oact,
                  size_t sigsetsize)
 {
 	struct k_sigaction32 new_sa32, old_sa32;
@@ -151,7 +150,7 @@
 }
 
 int 
-do_sigaltstack32 (const compat_stack_t *uss32, compat_stack_t *uoss32, unsigned long sp)
+do_sigaltstack32 (const compat_stack_t __user *uss32, compat_stack_t __user *uoss32, unsigned long sp)
 {
 	compat_stack_t ss32, oss32;
 	stack_t ss, oss;
@@ -162,7 +161,7 @@
 		if (copy_from_user(&ss32, uss32, sizeof ss32))
 			return -EFAULT;
 
-		ss.ss_sp = (void *)(unsigned long)ss32.ss_sp;
+		ss.ss_sp = (void __user *)(unsigned long)ss32.ss_sp;
 		ss.ss_flags = ss32.ss_flags;
 		ss.ss_size = ss32.ss_size;
 
@@ -172,7 +171,7 @@
 	if (uoss32)
 		ossp = &oss;
 
-	KERNEL_SYSCALL(ret, do_sigaltstack, ssp, ossp, sp);
+	KERNEL_SYSCALL(ret, do_sigaltstack, (const stack_t __user *)ssp, (stack_t __user *)ossp, sp);
 
 	if (!ret && uoss32) {
 		oss32.ss_sp = (unsigned int)(unsigned long)oss.ss_sp;
@@ -186,7 +185,7 @@
 }
 
 long
-restore_sigcontext32(struct compat_sigcontext *sc, struct compat_regfile * rf,
+restore_sigcontext32(struct compat_sigcontext __user *sc, struct compat_regfile __user * rf,
 		struct pt_regs *regs)
 {
 	long err = 0;
@@ -265,7 +264,7 @@
  * truncate for a 32-bit userspace.
  */
 long
-setup_sigcontext32(struct compat_sigcontext *sc, struct compat_regfile * rf, 
+setup_sigcontext32(struct compat_sigcontext __user *sc, struct compat_regfile __user * rf, 
 		struct pt_regs *regs, int in_syscall)		 
 {
 	compat_int_t flags = 0;
diff -Nru a/arch/parisc/kernel/signal32.h b/arch/parisc/kernel/signal32.h
--- a/arch/parisc/kernel/signal32.h	2005-03-11 12:51:41 -08:00
+++ b/arch/parisc/kernel/signal32.h	2005-03-11 12:51:41 -08:00
@@ -31,13 +31,13 @@
 
 void sigset_32to64(sigset_t *s64, compat_sigset_t *s32);
 void sigset_64to32(compat_sigset_t *s32, sigset_t *s64);
-int do_sigaltstack32 (const compat_stack_t *uss32, 
-		compat_stack_t *uoss32, unsigned long sp);
-long restore_sigcontext32(struct compat_sigcontext *sc, 
-		struct compat_regfile *rf,
+int do_sigaltstack32 (const compat_stack_t __user *uss32, 
+		compat_stack_t __user *uoss32, unsigned long sp);
+long restore_sigcontext32(struct compat_sigcontext __user *sc, 
+		struct compat_regfile __user *rf,
 		struct pt_regs *regs);
-long setup_sigcontext32(struct compat_sigcontext *sc, 
-		struct compat_regfile *rf,
+long setup_sigcontext32(struct compat_sigcontext __user *sc, 
+		struct compat_regfile __user *rf,
 		struct pt_regs *regs, int in_syscall);
 
 #endif
diff -Nru a/arch/parisc/kernel/sys_parisc.c b/arch/parisc/kernel/sys_parisc.c
--- a/arch/parisc/kernel/sys_parisc.c	2005-03-11 12:51:51 -08:00
+++ b/arch/parisc/kernel/sys_parisc.c	2005-03-11 12:51:51 -08:00
@@ -32,7 +32,7 @@
 #include <linux/smp_lock.h>
 #include <linux/syscalls.h>
 
-int sys_pipe(int *fildes)
+int sys_pipe(int __user *fildes)
 {
 	int fd[2];
 	int error;
@@ -161,7 +161,7 @@
 	}
 }
 
-long sys_shmat_wrapper(int shmid, char *shmaddr, int shmflag)
+long sys_shmat_wrapper(int shmid, char __user *shmaddr, int shmflag)
 {
 	unsigned long raddr;
 	int r;
@@ -174,8 +174,8 @@
 
 /* Fucking broken ABI */
 
-#ifdef CONFIG_PARISC64
-asmlinkage long parisc_truncate64(const char * path,
+#ifdef CONFIG_64BIT
+asmlinkage long parisc_truncate64(const char __user * path,
 					unsigned int high, unsigned int low)
 {
 	return sys_truncate(path, (long)high << 32 | low);
@@ -189,7 +189,7 @@
 
 /* stubs for the benefit of the syscall_table since truncate64 and truncate 
  * are identical on LP64 */
-asmlinkage long sys_truncate64(const char * path, unsigned long length)
+asmlinkage long sys_truncate64(const char __user * path, unsigned long length)
 {
 	return sys_truncate(path, length);
 }
@@ -203,7 +203,7 @@
 }
 #else
 
-asmlinkage long parisc_truncate64(const char * path,
+asmlinkage long parisc_truncate64(const char __user * path,
 					unsigned int high, unsigned int low)
 {
 	return sys_truncate64(path, (loff_t)high << 32 | low);
@@ -216,13 +216,13 @@
 }
 #endif
 
-asmlinkage ssize_t parisc_pread64(unsigned int fd, char *buf, size_t count,
+asmlinkage ssize_t parisc_pread64(unsigned int fd, char __user *buf, size_t count,
 					unsigned int high, unsigned int low)
 {
 	return sys_pread64(fd, buf, count, (loff_t)high << 32 | low);
 }
 
-asmlinkage ssize_t parisc_pwrite64(unsigned int fd, const char *buf,
+asmlinkage ssize_t parisc_pwrite64(unsigned int fd, const char __user *buf,
 			size_t count, unsigned int high, unsigned int low)
 {
 	return sys_pwrite64(fd, buf, count, (loff_t)high << 32 | low);
diff -Nru a/arch/parisc/kernel/sys_parisc32.c b/arch/parisc/kernel/sys_parisc32.c
--- a/arch/parisc/kernel/sys_parisc32.c	2005-03-11 12:51:42 -08:00
+++ b/arch/parisc/kernel/sys_parisc32.c	2005-03-11 12:51:42 -08:00
@@ -74,7 +74,7 @@
 	char *filename;
 
 	DBG(("sys32_execve(%p) r26 = 0x%lx\n", regs, regs->gr[26]));
-	filename = getname((char *) regs->gr[26]);
+	filename = getname((const char __user *) regs->gr[26]);
 	error = PTR_ERR(filename);
 	if (IS_ERR(filename))
 		goto out;
@@ -111,13 +111,13 @@
 	u32 __unused[4];
 };
 
-asmlinkage long sys32_sysctl(struct __sysctl_args32 *args)
+asmlinkage long sys32_sysctl(struct __sysctl_args32 __user *args)
 {
 	struct __sysctl_args32 tmp;
 	int error;
 	unsigned int oldlen32;
 	size_t oldlen, *oldlenp = NULL;
-	unsigned long addr = (((long)&args->__unused[0]) + 7) & ~7;
+	unsigned long addr = (((long __force)&args->__unused[0]) + 7) & ~7;
 	extern int do_sysctl(int *name, int nlen, void *oldval, size_t *oldlenp,
 	       void *newval, size_t newlen);
 
@@ -159,7 +159,7 @@
 					error = -EFAULT;
 			}
 		}
-		if (copy_to_user(args->__unused, tmp.__unused, sizeof(tmp.__unused)))
+		if (copy_to_user(&args->__unused[0], tmp.__unused, sizeof(tmp.__unused)))
 			error = -EFAULT;
 	}
 	return error;
@@ -168,19 +168,19 @@
 #endif /* CONFIG_SYSCTL */
 
 asmlinkage long sys32_sched_rr_get_interval(pid_t pid,
-	struct compat_timespec *interval)
+	struct compat_timespec __user *interval)
 {
 	struct timespec t;
 	int ret;
-	
-	KERNEL_SYSCALL(ret, sys_sched_rr_get_interval, pid, &t);
+
+	KERNEL_SYSCALL(ret, sys_sched_rr_get_interval, pid, (struct timespec __user *)&t);
 	if (put_compat_timespec(&t, interval))
 		return -EFAULT;
 	return ret;
 }
 
 static int
-put_compat_timeval(struct compat_timeval *u, struct timeval *t)
+put_compat_timeval(struct compat_timeval __user *u, struct timeval *t)
 {
 	struct compat_timeval t32;
 	t32.tv_sec = t->tv_sec;
@@ -188,7 +188,7 @@
 	return copy_to_user(u, &t32, sizeof t32);
 }
 
-static inline long get_ts32(struct timespec *o, struct compat_timeval *i)
+static inline long get_ts32(struct timespec *o, struct compat_timeval __user *i)
 {
 	long usec;
 
@@ -201,7 +201,7 @@
 }
 
 asmlinkage int
-sys32_gettimeofday(struct compat_timeval *tv, struct timezone *tz)
+sys32_gettimeofday(struct compat_timeval __user *tv, struct timezone __user *tz)
 {
     extern void do_gettimeofday(struct timeval *tv);
 
@@ -220,7 +220,7 @@
 }
 
 asmlinkage 
-int sys32_settimeofday(struct compat_timeval *tv, struct timezone *tz)
+int sys32_settimeofday(struct compat_timeval __user *tv, struct timezone __user *tz)
 {
 	struct timespec kts;
 	struct timezone ktz;
@@ -237,7 +237,7 @@
 	return do_sys_settimeofday(tv ? &kts : NULL, tz ? &ktz : NULL);
 }
 
-int cp_compat_stat(struct kstat *stat, struct compat_stat *statbuf)
+int cp_compat_stat(struct kstat *stat, struct compat_stat __user *statbuf)
 {
 	int err;
 
@@ -294,24 +294,24 @@
 };
 
 struct getdents32_callback {
-	struct linux32_dirent * current_dir;
-	struct linux32_dirent * previous;
+	struct linux32_dirent __user * current_dir;
+	struct linux32_dirent __user * previous;
 	int count;
 	int error;
 };
 
 struct readdir32_callback {
-	struct old_linux32_dirent * dirent;
+	struct old_linux32_dirent __user * dirent;
 	int count;
 };
 
 #define ROUND_UP(x,a)	((__typeof__(x))(((unsigned long)(x) + ((a) - 1)) & ~((a) - 1)))
-#define NAME_OFFSET(de) ((int) ((de)->d_name - (char *) (de)))
+#define NAME_OFFSET(de) ((int) ((de)->d_name - (char __user *) (de)))
 static int
 filldir32 (void *__buf, const char *name, int namlen, loff_t offset, ino_t ino,
 	   unsigned int d_type)
 {
-	struct linux32_dirent * dirent;
+	struct linux32_dirent __user * dirent;
 	struct getdents32_callback * buf = (struct getdents32_callback *) __buf;
 	int reclen = ROUND_UP(NAME_OFFSET(dirent) + namlen + 1, 4);
 
@@ -327,17 +327,17 @@
 	put_user(reclen, &dirent->d_reclen);
 	copy_to_user(dirent->d_name, name, namlen);
 	put_user(0, dirent->d_name + namlen);
-	dirent = (struct linux32_dirent *)((char *)dirent + reclen);
+	dirent = ((void __user *)dirent) + reclen;
 	buf->current_dir = dirent;
 	buf->count -= reclen;
 	return 0;
 }
 
 asmlinkage long
-sys32_getdents (unsigned int fd, void * dirent, unsigned int count)
+sys32_getdents (unsigned int fd, void __user * dirent, unsigned int count)
 {
 	struct file * file;
-	struct linux32_dirent * lastdirent;
+	struct linux32_dirent __user * lastdirent;
 	struct getdents32_callback buf;
 	int error;
 
@@ -346,7 +346,7 @@
 	if (!file)
 		goto out;
 
-	buf.current_dir = (struct linux32_dirent *) dirent;
+	buf.current_dir = (struct linux32_dirent __user *) dirent;
 	buf.previous = NULL;
 	buf.count = count;
 	buf.error = 0;
@@ -372,7 +372,7 @@
 	      unsigned int d_type)
 {
 	struct readdir32_callback * buf = (struct readdir32_callback *) __buf;
-	struct old_linux32_dirent * dirent;
+	struct old_linux32_dirent __user * dirent;
 
 	if (buf->count)
 		return -EINVAL;
@@ -387,7 +387,7 @@
 }
 
 asmlinkage long
-sys32_readdir (unsigned int fd, void * dirent, unsigned int count)
+sys32_readdir (unsigned int fd, void __user * dirent, unsigned int count)
 {
 	int error;
 	struct file * file;
@@ -477,7 +477,7 @@
 };
 
 asmlinkage long sys32_msgsnd(int msqid,
-				struct msgbuf32 *umsgp32,
+				struct msgbuf32 __user *umsgp32,
 				size_t msgsz, int msgflg)
 {
 	struct msgbuf *mb;
@@ -494,14 +494,14 @@
 	if (err)
 		err = -EFAULT;
 	else
-		KERNEL_SYSCALL(err, sys_msgsnd, msqid, mb, msgsz, msgflg);
+		KERNEL_SYSCALL(err, sys_msgsnd, msqid, (struct msgbuf __user *)mb, msgsz, msgflg);
 
 	kfree(mb);
 	return err;
 }
 
 asmlinkage long sys32_msgrcv(int msqid,
-				struct msgbuf32 *umsgp32,
+				struct msgbuf32 __user *umsgp32,
 				size_t msgsz, long msgtyp, int msgflg)
 {
 	struct msgbuf *mb;
@@ -511,7 +511,7 @@
 	if ((mb = kmalloc(msgsz + sizeof *mb + 4, GFP_KERNEL)) == NULL)
 		return -ENOMEM;
 
-	KERNEL_SYSCALL(err, sys_msgrcv, msqid, mb, msgsz, msgtyp, msgflg);
+	KERNEL_SYSCALL(err, sys_msgrcv, msqid, (struct msgbuf __user *)mb, msgsz, msgtyp, msgflg);
 
 	if (err >= 0) {
 		len = err;
@@ -528,7 +528,7 @@
 	return err;
 }
 
-asmlinkage int sys32_sendfile(int out_fd, int in_fd, compat_off_t *offset, s32 count)
+asmlinkage int sys32_sendfile(int out_fd, int in_fd, compat_off_t __user *offset, s32 count)
 {
         mm_segment_t old_fs = get_fs();
         int ret;
@@ -538,7 +538,7 @@
                 return -EFAULT;
 
         set_fs(KERNEL_DS);
-        ret = sys_sendfile(out_fd, in_fd, offset ? &of : NULL, count);
+        ret = sys_sendfile(out_fd, in_fd, offset ? (off_t __user *)&of : NULL, count);
         set_fs(old_fs);
 
         if (offset && put_user(of, offset))
@@ -547,9 +547,7 @@
         return ret;
 }
 
-typedef long __kernel_loff_t32;		/* move this to asm/posix_types.h? */
-
-asmlinkage int sys32_sendfile64(int out_fd, int in_fd, __kernel_loff_t32 *offset, s32 count)
+asmlinkage int sys32_sendfile64(int out_fd, int in_fd, compat_loff_t __user *offset, s32 count)
 {
 	mm_segment_t old_fs = get_fs();
 	int ret;
@@ -559,7 +557,7 @@
 		return -EFAULT;
 		
 	set_fs(KERNEL_DS);
-	ret = sys_sendfile64(out_fd, in_fd, offset ? &lof : NULL, count);
+	ret = sys_sendfile64(out_fd, in_fd, offset ? (loff_t __user *)&lof : NULL, count);
 	set_fs(old_fs);
 	
 	if (offset && put_user(lof, offset))
@@ -598,7 +596,7 @@
 	int  :32; int  :32; int  :32; int  :32;
 };
 
-asmlinkage long sys32_adjtimex(struct timex32 *txc_p32)
+asmlinkage long sys32_adjtimex(struct timex32 __user *txc_p32)
 {
 	struct timex txc;
 	struct timex32 t32;
@@ -647,7 +645,7 @@
  * damage, I decided to just duplicate the code from sys_sysinfo here.
  */
 
-asmlinkage int sys32_sysinfo(struct sysinfo32 *info)
+asmlinkage int sys32_sysinfo(struct sysinfo32 __user *info)
 {
 	struct sysinfo val;
 	int err;
@@ -714,7 +712,7 @@
 	return sys_semctl (semid, semnum, cmd, arg);
 }
 
-long sys32_lookup_dcookie(u32 cookie_high, u32 cookie_low, char *buf,
+long sys32_lookup_dcookie(u32 cookie_high, u32 cookie_low, char __user *buf,
 			  size_t len)
 {
 	return sys_lookup_dcookie((u64)cookie_high << 32 | cookie_low,
diff -Nru a/arch/parisc/kernel/traps.c b/arch/parisc/kernel/traps.c
--- a/arch/parisc/kernel/traps.c	2005-03-11 12:51:52 -08:00
+++ b/arch/parisc/kernel/traps.c	2005-03-11 12:51:52 -08:00
@@ -242,7 +242,7 @@
 	struct siginfo si;
 
 	si.si_code = wot;
-	si.si_addr = (void *) (regs->iaoq[0] & ~3);
+	si.si_addr = (void __user *) (regs->iaoq[0] & ~3);
 	si.si_signo = SIGTRAP;
 	si.si_errno = 0;
 	force_sig_info(SIGTRAP, &si, current);
@@ -263,7 +263,7 @@
 		show_regs(regs);
 #endif
 		si.si_code = TRAP_BRKPT;
-		si.si_addr = (void *) (regs->iaoq[0] & ~3);
+		si.si_addr = (void __user *) (regs->iaoq[0] & ~3);
 		si.si_signo = SIGTRAP;
 		force_sig_info(SIGTRAP, &si, current);
 		break;
@@ -281,7 +281,7 @@
 #endif
 		si.si_signo = SIGTRAP;
 		si.si_code = TRAP_BRKPT;
-		si.si_addr = (void *) (regs->iaoq[0] & ~3);
+		si.si_addr = (void __user *) (regs->iaoq[0] & ~3);
 		force_sig_info(SIGTRAP, &si, current);
 		return;
 	}
@@ -569,7 +569,7 @@
 	give_sigill:
 		si.si_signo = SIGILL;
 		si.si_errno = 0;
-		si.si_addr = (void *) regs->iaoq[0];
+		si.si_addr = (void __user *) regs->iaoq[0];
 		force_sig_info(SIGILL, &si, current);
 		return;
 
@@ -577,7 +577,7 @@
 		/* Overflow Trap, let the userland signal handler do the cleanup */
 		si.si_signo = SIGFPE;
 		si.si_code = FPE_INTOVF;
-		si.si_addr = (void *) regs->iaoq[0];
+		si.si_addr = (void __user *) regs->iaoq[0];
 		force_sig_info(SIGFPE, &si, current);
 		return;
 		
@@ -699,9 +699,9 @@
 		si.si_signo = SIGSEGV;
 		si.si_errno = 0;
 		if (code == 7)
-		    si.si_addr = (void *) regs->iaoq[0];
+		    si.si_addr = (void __user *) regs->iaoq[0];
 		else
-		    si.si_addr = (void *) regs->ior;
+		    si.si_addr = (void __user *) regs->ior;
 		force_sig_info(SIGSEGV, &si, current);
 		return;
 
@@ -721,7 +721,7 @@
 			si.si_signo = SIGBUS;
 			si.si_code = BUS_OBJERR;
 			si.si_errno = 0;
-			si.si_addr = (void *) regs->ior;
+			si.si_addr = (void __user *) regs->ior;
 			force_sig_info(SIGBUS, &si, current);
 			return;
 		}
@@ -745,7 +745,7 @@
 		si.si_signo = SIGSEGV;
 		si.si_errno = 0;
 		si.si_code = SEGV_MAPERR;
-		si.si_addr = (void *) regs->ior;
+		si.si_addr = (void __user *) regs->ior;
 		force_sig_info(SIGSEGV, &si, current);
 		return;
 	    }
diff -Nru a/arch/parisc/kernel/unaligned.c b/arch/parisc/kernel/unaligned.c
--- a/arch/parisc/kernel/unaligned.c	2005-03-11 12:51:42 -08:00
+++ b/arch/parisc/kernel/unaligned.c	2005-03-11 12:51:42 -08:00
@@ -744,7 +744,7 @@
 			si.si_signo = SIGSEGV;
 			si.si_errno = 0;
 			si.si_code = SEGV_MAPERR;
-			si.si_addr = (void *)regs->ior;
+			si.si_addr = (void __user *)regs->ior;
 			force_sig_info(SIGSEGV, &si, current);
 		}
 		else
@@ -754,7 +754,7 @@
 			si.si_signo = SIGBUS;
 			si.si_errno = 0;
 			si.si_code = BUS_ADRALN;
-			si.si_addr = (void *)regs->ior;
+			si.si_addr = (void __user *)regs->ior;
 			force_sig_info(SIGBUS, &si, current);
 		}
 		
diff -Nru a/arch/parisc/kernel/unwind.c b/arch/parisc/kernel/unwind.c
--- a/arch/parisc/kernel/unwind.c	2005-03-11 12:51:41 -08:00
+++ b/arch/parisc/kernel/unwind.c	2005-03-11 12:51:41 -08:00
@@ -36,8 +36,7 @@
  * possible (before the slab allocator is initialized)
  */
 static struct unwind_table kernel_unwind_table;
-static struct unwind_table *unwind_tables, *unwind_tables_end;
-
+static LIST_HEAD(unwind_tables);
 
 static inline const struct unwind_table_entry *
 find_unwind_entry_in_table(const struct unwind_table *table, unsigned long addr)
@@ -65,14 +64,14 @@
 static const struct unwind_table_entry *
 find_unwind_entry(unsigned long addr)
 {
-	struct unwind_table *table = unwind_tables;
+	struct unwind_table *table;
 	const struct unwind_table_entry *e = NULL;
 
 	if (addr >= kernel_unwind_table.start && 
 	    addr <= kernel_unwind_table.end)
 		e = find_unwind_entry_in_table(&kernel_unwind_table, addr);
-	else
-		for (; table; table = table->next) {
+	else 
+		list_for_each_entry(table, &unwind_tables, list) {
 			if (addr >= table->start && 
 			    addr <= table->end)
 				e = find_unwind_entry_in_table(table, addr);
@@ -99,7 +98,7 @@
 	table->end = base_addr + end->region_end;
 	table->table = (struct unwind_table_entry *)table_start;
 	table->length = end - start + 1;
-	table->next = NULL;
+	INIT_LIST_HEAD(&table->list);
 
 	for (; start <= end; start++) {
 		if (start < end && 
@@ -112,33 +111,60 @@
 	}
 }
 
-void *
+static void
+unwind_table_sort(struct unwind_table_entry *start,
+		  struct unwind_table_entry *finish)
+{
+	struct unwind_table_entry el, *p, *q;
+
+	for (p = start + 1; p < finish; ++p) {
+		if (p[0].region_start < p[-1].region_start) {
+			el = *p;
+			q = p;
+			do {
+				q[0] = q[-1];
+				--q;
+			} while (q > start && 
+				 el.region_start < q[-1].region_start);
+			*q = el;
+		}
+	}
+}
+
+struct unwind_table *
 unwind_table_add(const char *name, unsigned long base_addr, 
 		 unsigned long gp,
                  void *start, void *end)
 {
 	struct unwind_table *table;
 	unsigned long flags;
+	struct unwind_table_entry *s = (struct unwind_table_entry *)start;
+	struct unwind_table_entry *e = (struct unwind_table_entry *)end;
+
+	unwind_table_sort(s, e);
 
 	table = kmalloc(sizeof(struct unwind_table), GFP_USER);
 	if (table == NULL)
 		return NULL;
 	unwind_table_init(table, name, base_addr, gp, start, end);
 	spin_lock_irqsave(&unwind_lock, flags);
-	if (unwind_tables)
-	{
-		unwind_tables_end->next = table;
-		unwind_tables_end = table;
-	}
-	else
-	{
-		unwind_tables = unwind_tables_end = table;
-	}
+	list_add_tail(&table->list, &unwind_tables);
 	spin_unlock_irqrestore(&unwind_lock, flags);
 
 	return table;
 }
 
+void unwind_table_remove(struct unwind_table *table)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&unwind_lock, flags);
+	list_del(&table->list);
+	spin_unlock_irqrestore(&unwind_lock, flags);
+
+	kfree(table);
+}
+
 /* Called from setup_arch to import the kernel unwind info */
 static int unwind_init(void)
 {
@@ -148,6 +174,8 @@
 	start = (long)&__start___unwind[0];
 	stop = (long)&__stop___unwind[0];
 
+	spin_lock_init(&unwind_lock);
+
 	printk("unwind_init: start = 0x%lx, end = 0x%lx, entries = %lu\n", 
 	    start, stop,
 	    (stop - start) / sizeof(struct unwind_table_entry));
@@ -239,9 +267,9 @@
 		    info->prev_sp, info->prev_ip);
 	} else {
 		dbg("e->start = 0x%x, e->end = 0x%x, Save_SP = %d, "
-		    "Save_RP = %d size = %u\n", e->region_start, 
-		    e->region_end, e->Save_SP, e->Save_RP, 
-		    e->Total_frame_size);
+		    "Save_RP = %d, Millicode = %d size = %u\n", 
+		    e->region_start, e->region_end, e->Save_SP, e->Save_RP, 
+		    e->Millicode, e->Total_frame_size);
 
 		looking_for_rp = e->Save_RP;
 
@@ -284,7 +312,9 @@
 		}
 
 		info->prev_sp = info->sp - frame_size;
-		if (rpoffset)
+		if (e->Millicode)
+			info->rp = info->r31;
+		else if (rpoffset)
 			info->rp = *(unsigned long *)(info->prev_sp - rpoffset);
 		info->prev_ip = info->rp;
 		info->rp = 0;
@@ -296,13 +326,14 @@
 }
 
 void unwind_frame_init(struct unwind_frame_info *info, struct task_struct *t, 
-		       unsigned long sp, unsigned long ip, unsigned long rp)
+		       struct pt_regs *regs)
 {
 	memset(info, 0, sizeof(struct unwind_frame_info));
 	info->t = t;
-	info->sp = sp;
-	info->ip = ip;
-	info->rp = rp;
+	info->sp = regs->gr[30];
+	info->ip = regs->iaoq[0];
+	info->rp = regs->gr[2];
+	info->r31 = regs->gr[31];
 
 	dbg("(%d) Start unwind from sp=%08lx ip=%08lx\n", 
 	    t ? (int)t->pid : -1, info->sp, info->ip);
@@ -310,14 +341,22 @@
 
 void unwind_frame_init_from_blocked_task(struct unwind_frame_info *info, struct task_struct *t)
 {
-	struct pt_regs *regs = &t->thread.regs;
-	unwind_frame_init(info, t, regs->ksp, regs->kpc, 0);
+	struct pt_regs *r = &t->thread.regs;
+	struct pt_regs *r2;
+
+	r2 = (struct pt_regs *)kmalloc(sizeof(struct pt_regs), GFP_KERNEL);
+	if (!r2)
+		return;
+	*r2 = *r;
+	r2->gr[30] = r->ksp;
+	r2->iaoq[0] = r->kpc;
+	unwind_frame_init(info, t, r2);
+	kfree(r2);
 }
 
 void unwind_frame_init_running(struct unwind_frame_info *info, struct pt_regs *regs)
 {
-	unwind_frame_init(info, current, regs->gr[30], regs->iaoq[0],
-			  regs->gr[2]);
+	unwind_frame_init(info, current, regs);
 }
 
 int unwind_once(struct unwind_frame_info *next_frame)
diff -Nru a/arch/parisc/kernel/vmlinux.lds.S b/arch/parisc/kernel/vmlinux.lds.S
--- a/arch/parisc/kernel/vmlinux.lds.S	2005-03-11 12:51:41 -08:00
+++ b/arch/parisc/kernel/vmlinux.lds.S	2005-03-11 12:51:41 -08:00
@@ -29,7 +29,7 @@
 #include <asm/page.h>
 	
 /* ld script to make hppa Linux kernel */
-#ifndef CONFIG_PARISC64
+#ifndef CONFIG_64BIT
 OUTPUT_FORMAT("elf32-hppa-linux")
 OUTPUT_ARCH(hppa)
 #else
@@ -38,7 +38,7 @@
 #endif
 
 ENTRY(_stext)
-#ifndef CONFIG_PARISC64
+#ifndef CONFIG_64BIT
 jiffies = jiffies_64 + 4;
 #else
 jiffies = jiffies_64;
@@ -112,7 +112,7 @@
   . = ALIGN(16384);	
   init_istack : { *(init_istack) }
 
-#ifdef CONFIG_PARISC64
+#ifdef CONFIG_64BIT
   . = ALIGN(16);               /* Linkage tables */
   .opd : { *(.opd) } PROVIDE (__gp = .); 
   .plt : { *(.plt) } 
@@ -180,7 +180,7 @@
   /* Sections to be discarded */
   /DISCARD/ : {
 	*(.exitcall.exit)
-#ifdef CONFIG_PARISC64
+#ifdef CONFIG_64BIT
 	/* temporary hack until binutils is fixed to not emit these
 	 for static binaries */
 	*(.interp)
diff -Nru a/arch/parisc/lib/checksum.c b/arch/parisc/lib/checksum.c
--- a/arch/parisc/lib/checksum.c	2005-03-11 12:51:52 -08:00
+++ b/arch/parisc/lib/checksum.c	2005-03-11 12:51:52 -08:00
@@ -131,9 +131,9 @@
  * Copy from userspace and compute checksum.  If we catch an exception
  * then zero the rest of the buffer.
  */
-unsigned int csum_partial_copy_from_user (const unsigned char *src, unsigned char *dst,
-                                          int len, unsigned int sum,
-                                          int *err_ptr)
+unsigned int csum_partial_copy_from_user(const unsigned char __user *src,
+					unsigned char *dst, int len,
+					unsigned int sum, int *err_ptr)
 {
 	int missing;
 
diff -Nru a/arch/parisc/lib/debuglocks.c b/arch/parisc/lib/debuglocks.c
--- a/arch/parisc/lib/debuglocks.c	2005-03-11 12:51:47 -08:00
+++ b/arch/parisc/lib/debuglocks.c	2005-03-11 12:51:47 -08:00
@@ -1,7 +1,7 @@
 /* 
  *    Debugging versions of SMP locking primitives.
  *
- *    Copyright (C) 2004 Thibaut VARENE <varenet@esiee.fr>
+ *    Copyright (C) 2004 Thibaut VARENE <varenet@parisc-linux.org>
  *
  *    Some code stollen from alpha & sparc64 ;)
  *
@@ -239,8 +239,6 @@
 	if(rw->counter != 0) {
 		/* this basically never happens */
 		_raw_spin_unlock(&rw->lock);
-		
-		
 		return 0;
 	}
 
@@ -250,6 +248,7 @@
 	pdc_printf("%s:%d: try write_lock grabbed in %s at %p(%d)\n",
 		   bfile, bline, current->comm, inline_pc, cpu);
 #endif
+	return 1;
 }
 
 void _dbg_read_lock(rwlock_t * rw, const char *bfile, int bline)
diff -Nru a/arch/parisc/math-emu/driver.c b/arch/parisc/math-emu/driver.c
--- a/arch/parisc/math-emu/driver.c	2005-03-11 12:51:51 -08:00
+++ b/arch/parisc/math-emu/driver.c	2005-03-11 12:51:51 -08:00
@@ -27,7 +27,6 @@
  *  Copyright (C) 2001	      Hewlett-Packard <bame@debian.org>
  */
 
-#include <linux/config.h>
 #include <linux/sched.h>
 #include "float.h"
 #include "math-emu.h"
@@ -120,7 +119,7 @@
 	    si.si_signo = signalcode >> 24;
 	    si.si_errno = 0;
 	    si.si_code = signalcode & 0xffffff;
-	    si.si_addr = (void *) regs->iaoq[0];
+	    si.si_addr = (void __user *) regs->iaoq[0];
 	    force_sig_info(si.si_signo, &si, current);
 	    return -1;
 	}
diff -Nru a/arch/parisc/mm/fault.c b/arch/parisc/mm/fault.c
--- a/arch/parisc/mm/fault.c	2005-03-11 12:51:51 -08:00
+++ b/arch/parisc/mm/fault.c	2005-03-11 12:51:51 -08:00
@@ -225,7 +225,7 @@
 		si.si_signo = SIGSEGV;
 		si.si_errno = 0;
 		si.si_code = SEGV_MAPERR;
-		si.si_addr = (void *) address;
+		si.si_addr = (void __user *) address;
 		force_sig_info(SIGSEGV, &si, current);
 		return;
 	}
diff -Nru a/arch/parisc/mm/kmap.c b/arch/parisc/mm/kmap.c
--- a/arch/parisc/mm/kmap.c	2005-03-11 12:51:43 -08:00
+++ b/arch/parisc/mm/kmap.c	2005-03-11 12:51:43 -08:00
@@ -49,10 +49,10 @@
  * unmap_uncached_page() and save a little code space but I didn't
  * do that since I'm not certain whether this is the right path. -PB
  */
-static void unmap_cached_pte(pte_t * pte, unsigned long arg)
+static void unmap_cached_pte(pte_t * pte, unsigned long addr, unsigned long arg)
 {
 	pte_t page = *pte;
-	pte_clear(pte);
+	pte_clear(&init_mm, addr, pte);
 	if (!pte_none(page)) {
 		if (pte_present(page)) {
 			unsigned long map_nr = pte_pagenr(page);
diff -Nru a/arch/ppc/Kconfig b/arch/ppc/Kconfig
--- a/arch/ppc/Kconfig	2005-03-11 12:51:51 -08:00
+++ b/arch/ppc/Kconfig	2005-03-11 12:51:51 -08:00
@@ -52,17 +52,17 @@
 	default 6xx
 
 config 6xx
-	bool "6xx/7xx/74xx/52xx/8260"
+	bool "6xx/7xx/74xx/52xx/82xx/83xx"
 	help
 	  There are four types of PowerPC chips supported.  The more common
 	  types (601, 603, 604, 740, 750, 7400), the Motorola embedded
-	  versions (821, 823, 850, 855, 860, 52xx, 8260), the IBM embedded
+	  versions (821, 823, 850, 855, 860, 52xx, 82xx, 83xx), the IBM embedded
 	  versions (403 and 405) and the high end 64 bit Power processors
 	  (POWER 3, POWER4, and IBM 970 also known as G5)
 	  Unless you are building a kernel for one of the embedded processor
 	  systems, 64 bit IBM RS/6000 or an Apple G5, choose 6xx.
 	  Note that the kernel runs in 32-bit mode even on 64-bit chips.
-	  Also note that because the 52xx & 82xx family has a 603e core,
+	  Also note that because the 52xx, 82xx, & 83xx family has a 603e core,
 	  specific support for that chipset is asked later on.
 
 config 40x
@@ -109,7 +109,7 @@
 config ALTIVEC
 	bool "AltiVec Support"
 	depends on 6xx || POWER4
-	depends on !8260
+	depends on !8260 && !83xx
 	---help---
 	  This option enables kernel support for the Altivec extensions to the
 	  PowerPC processor. The kernel currently supports saving and restoring
@@ -140,7 +140,7 @@
 
 config TAU
 	bool "Thermal Management Support"
-	depends on 6xx && !8260
+	depends on 6xx && !8260 && !83xx
 	help
 	  G3 and G4 processors have an on-chip temperature sensor called the
 	  'Thermal Assist Unit (TAU)', which, in theory, can measure the on-die
@@ -568,6 +568,10 @@
 	  Select SANDPOINT if configuring for a Motorola Sandpoint X3
 	  (any flavor).
 
+config RADSTONE_PPC7D
+	bool "Radstone Technology PPC7D board"
+	select MV64360
+
 config ADIR
 	bool "SBS-Adirondack"
 
@@ -638,6 +642,11 @@
 	  much but it's only been tested on this board version. I think this
 	  board is also known as IceCube.
 
+config MPC834x_SYS
+	bool "Freescale MPC834x SYS"
+	help
+	  This option enables support for the MPC 834x SYS evaluation board.
+
 endchoice
 
 config PQ2ADS
@@ -676,6 +685,14 @@
 	  The MPC8272 CPM has a different internal dpram setup than other CPM2
 	  devices
 
+config 83xx
+	bool
+	default y if MPC834x_SYS
+
+config MPC834x
+	bool
+	default y if MPC834x_SYS
+
 config CPM2
 	bool
 	depends on 8260 || MPC8560 || MPC8555
@@ -715,7 +732,8 @@
 	bool
 	depends on SANDPOINT || MCPN765 || SPRUCE || PPLUS || PCORE || \
 		PRPMC750 || K2 || PRPMC800 || LOPEC || \
-		(EV64260 && !SERIAL_MPSC) || CHESTNUT
+		(EV64260 && !SERIAL_MPSC) || CHESTNUT || RADSTONE_PPC7D || \
+		MPC834x_SYS
 	default y
 
 config FORCE
@@ -730,7 +748,7 @@
 
 config MV64360
 	bool
-	depends on KATANA
+	depends on KATANA || RADSTONE_PPC7D
 	default y
 
 config MV64360
@@ -1079,8 +1097,8 @@
 	bool
 
 config PCI
-	bool "PCI support" if 40x || CPM2 || 85xx
-	default y if !40x && !CPM2 && !8xx && !APUS && !85xx
+	bool "PCI support" if 40x || CPM2 || 83xx || 85xx
+	default y if !40x && !CPM2 && !8xx && !APUS && !83xx && !85xx
 	default PCI_PERMEDIA if !4xx && !CPM2 && !8xx && APUS
 	default PCI_QSPAN if !4xx && !CPM2 && 8xx
 	help
diff -Nru a/arch/ppc/Makefile b/arch/ppc/Makefile
--- a/arch/ppc/Makefile	2005-03-11 12:51:52 -08:00
+++ b/arch/ppc/Makefile	2005-03-11 12:51:52 -08:00
@@ -57,6 +57,7 @@
 core-y				+= arch/ppc/kernel/ arch/ppc/platforms/ \
 				   arch/ppc/mm/ arch/ppc/lib/ arch/ppc/syslib/
 core-$(CONFIG_4xx)		+= arch/ppc/platforms/4xx/
+core-$(CONFIG_83xx)		+= arch/ppc/platforms/83xx/
 core-$(CONFIG_85xx)		+= arch/ppc/platforms/85xx/
 core-$(CONFIG_MATH_EMULATION)	+= arch/ppc/math-emu/
 core-$(CONFIG_XMON)		+= arch/ppc/xmon/
@@ -112,26 +113,24 @@
 TOUT	:= .tmp_gas_check
 # Ensure this is binutils 2.12.1 (or 2.12.90.0.7) or later for altivec
 # instructions.
-AS_ALTIVEC	:= $(shell echo dssall | $(AS) -many -o $(TOUT) >/dev/null 2>&1 ; echo $$?)
 # gcc-3.4 and binutils-2.14 are a fatal combination.
 GCC_VERSION	:= $(call cc-version)
-BAD_GCC_AS	:= $(shell echo mftb 5 | $(AS) -mppc -many -o $(TOUT) >/dev/null 2>&1 && echo 0 || echo 1)
 
 checkbin:
-ifeq ($(GCC_VERSION)$(BAD_GCC_AS),03041)
-	@echo -n '*** ${VERSION}.${PATCHLEVEL} kernels no longer build '
-	@echo 'correctly with gcc-3.4 and your version of binutils.'
-	@echo '*** Please upgrade your binutils or downgrade your gcc'
-	@false
-endif
-ifneq ($(AS_ALTIVEC),0)
-	echo $(AS_ALTIVEC)
-	@echo -n '*** ${VERSION}.${PATCHLEVEL} kernels no longer build '
-	@echo 'correctly with old versions of binutils.'
-	@echo '*** Please upgrade your binutils to 2.12.1 or newer'
-	@false
-endif
-	@true
+	@if test "$(GCC_VERSION)" = "0304" ; then \
+		if ! /bin/echo mftb 5 | $(AS) -v -mppc -many -o $(TOUT) >/dev/null 2>&1 ; then \
+			echo -n '*** ${VERSION}.${PATCHLEVEL} kernels no longer build '; \
+			echo 'correctly with gcc-3.4 and your version of binutils.'; \
+			echo '*** Please upgrade your binutils or downgrade your gcc'; \
+			false; \
+		fi ; \
+	fi
+	@if ! /bin/echo dssall | $(AS) -many -o $(TOUT) >/dev/null 2>&1 ; then \
+		echo -n '*** ${VERSION}.${PATCHLEVEL} kernels no longer build ' ; \
+		echo 'correctly with old versions of binutils.' ; \
+		echo '*** Please upgrade your binutils to 2.12.1 or newer' ; \
+		false ; \
+	fi
 
 CLEAN_FILES +=	include/asm-$(ARCH)/offsets.h \
 		arch/$(ARCH)/kernel/asm-offsets.s \
diff -Nru a/arch/ppc/boot/simple/Makefile b/arch/ppc/boot/simple/Makefile
--- a/arch/ppc/boot/simple/Makefile	2005-03-11 12:51:40 -08:00
+++ b/arch/ppc/boot/simple/Makefile	2005-03-11 12:51:40 -08:00
@@ -65,6 +65,7 @@
 zimageinitrd-$(CONFIG_EBONY)		:= zImage.initrd-TREE
          end-$(CONFIG_EBONY)		:= ebony
   entrypoint-$(CONFIG_EBONY)		:= 0x01000000
+     extra.o-$(CONFIG_EBONY)		:= openbios.o
 
       zimage-$(CONFIG_LUAN)		:= zImage-TREE
 zimageinitrd-$(CONFIG_LUAN)		:= zImage.initrd-TREE
@@ -96,6 +97,10 @@
      extra.o-$(CONFIG_KATANA)		:= misc-katana.o mv64x60_stub.o
          end-$(CONFIG_KATANA)		:= katana
    cacheflag-$(CONFIG_KATANA)		:= -include $(clear_L2_L3)
+
+     extra.o-$(CONFIG_RADSTONE_PPC7D)	:= misc-radstone_ppc7d.o mv64x60_stub.o
+         end-$(CONFIG_RADSTONE_PPC7D)	:= radstone_ppc7d
+   cacheflag-$(CONFIG_RADSTONE_PPC7D)	:= -include $(clear_L2_L3)
 
 # kconfig 'feature', only one of these will ever be 'y' at a time.
 # The rest will be unset.
diff -Nru a/arch/ppc/boot/simple/misc-mv64x60.S b/arch/ppc/boot/simple/misc-mv64x60.S
--- a/arch/ppc/boot/simple/misc-mv64x60.S	2005-03-11 12:51:47 -08:00
+++ b/arch/ppc/boot/simple/misc-mv64x60.S	2005-03-11 12:51:47 -08:00
@@ -32,7 +32,11 @@
 #if (CONFIG_MV64X60_NEW_BASE != CONFIG_MV64X60_BASE)
 move_base:
 	li	r20,0
+#ifdef CONFIG_GT64260
 	li	r23,20
+#else /* Must be mv64[34]60 which uses top 16 bits */
+	li	r23,16
+#endif
 
 	/* Relocate bridge's regs */
 	addis	r25,0,CONFIG_MV64X60_BASE@h
diff -Nru a/arch/ppc/boot/simple/misc-radstone_ppc7d.c b/arch/ppc/boot/simple/misc-radstone_ppc7d.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/ppc/boot/simple/misc-radstone_ppc7d.c	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,19 @@
+/*
+ * arch/ppc/boot/simple/misc-radstone_ppc7d.c
+ *
+ * Misc data for Radstone PPC7D board.
+ *
+ * Author: James Chapman <jchapman@katalix.com>
+ */
+
+#include <linux/types.h>
+#include <asm/reg.h>
+
+#include "../../platforms/radstone_ppc7d.h"
+
+#if defined(CONFIG_SERIAL_MPSC_CONSOLE)
+long	mv64x60_mpsc_clk_freq = PPC7D_MPSC_CLK_FREQ;;
+long	mv64x60_mpsc_clk_src = PPC7D_MPSC_CLK_SRC;
+long	mv64x60_mpsc_console_baud = PPC7D_DEFAULT_BAUD;
+#endif
+
diff -Nru a/arch/ppc/boot/simple/openbios.c b/arch/ppc/boot/simple/openbios.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/ppc/boot/simple/openbios.c	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,37 @@
+/*
+ * arch/ppc/boot/simple/openbios.c
+ *
+ * 2005 (c) SYSGO AG - g.jaeger@sysgo.com
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without
+ * any warranty of any kind, whether express or implied.
+ *
+ * Derived from arch/ppc/boot/simple/pibs.c (from MontaVista)
+ */
+
+#include <linux/types.h>
+#include <linux/config.h>
+#include <linux/string.h>
+#include <asm/ppcboot.h>
+#include <platforms/4xx/ebony.h>
+
+extern unsigned long decompress_kernel(unsigned long load_addr, int num_words,
+				       unsigned long cksum);
+
+/* We need to make sure that this is before the images to ensure
+ * that it's in a mapped location. */
+bd_t hold_resid_buf __attribute__ ((__section__ (".data.boot")));
+bd_t *hold_residual = &hold_resid_buf;
+
+void *
+load_kernel(unsigned long load_addr, int num_words, unsigned long cksum,
+		void *ign1, void *ign2)
+{
+	decompress_kernel(load_addr, num_words, cksum);
+
+	/* simply copy the MAC addresses */
+	memcpy(hold_residual->bi_enetaddr,  (char *)EBONY_OPENBIOS_MAC_BASE, 6);
+	memcpy(hold_residual->bi_enet1addr, (char *)(EBONY_OPENBIOS_MAC_BASE+EBONY_OPENBIOS_MAC_OFFSET), 6);
+
+	return (void *)hold_residual;
+}
diff -Nru a/arch/ppc/configs/katana_defconfig b/arch/ppc/configs/katana_defconfig
--- a/arch/ppc/configs/katana_defconfig	2005-03-11 12:51:52 -08:00
+++ b/arch/ppc/configs/katana_defconfig	2005-03-11 12:51:52 -08:00
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.11-rc2
-# Tue Jan 25 16:31:13 2005
+# Linux kernel version: 2.6.11-rc4
+# Tue Feb 15 14:27:12 2005
 #
 CONFIG_MMU=y
 CONFIG_GENERIC_HARDIRQS=y
@@ -152,8 +152,8 @@
 CONFIG_TASK_SIZE=0x80000000
 CONFIG_CONSISTENT_START_BOOL=y
 CONFIG_CONSISTENT_START=0xf0000000
-# CONFIG_CONSISTENT_SIZE_BOOL is not set
-CONFIG_CONSISTENT_SIZE=0x00200000
+CONFIG_CONSISTENT_SIZE_BOOL=y
+CONFIG_CONSISTENT_SIZE=0x00400000
 # CONFIG_BOOT_LOAD_BOOL is not set
 CONFIG_BOOT_LOAD=0x00800000
 
@@ -171,7 +171,82 @@
 #
 # Memory Technology Devices (MTD)
 #
-# CONFIG_MTD is not set
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_PARTITIONS=y
+CONFIG_MTD_CONCAT=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+CONFIG_MTD_CFI_ADV_OPTIONS=y
+CONFIG_MTD_CFI_NOSWAP=y
+# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set
+# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set
+CONFIG_MTD_CFI_GEOMETRY=y
+# CONFIG_MTD_MAP_BANK_WIDTH_1 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_2 is not set
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+# CONFIG_MTD_CFI_I1 is not set
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+CONFIG_MTD_CFI_INTELEXT=y
+# CONFIG_MTD_CFI_AMDSTD is not set
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+# CONFIG_MTD_XIP is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+CONFIG_MTD_PHYSMAP=y
+CONFIG_MTD_PHYSMAP_START=0xe0000000
+CONFIG_MTD_PHYSMAP_LEN=0x0
+CONFIG_MTD_PHYSMAP_BANKWIDTH=4
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_PMC551 is not set
+# CONFIG_MTD_SLRAM is not set
+CONFIG_MTD_PHRAM=y
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLKMTD is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+
+#
+# NAND Flash Device Drivers
+#
+# CONFIG_MTD_NAND is not set
 
 #
 # Parallel port support
@@ -531,7 +606,6 @@
 #
 # CONFIG_VGA_CONSOLE is not set
 CONFIG_DUMMY_CONSOLE=y
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
 # Sound
@@ -573,6 +647,10 @@
 # CONFIG_JBD is not set
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
+
+#
+# XFS support
+#
 # CONFIG_XFS_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
@@ -619,6 +697,8 @@
 # CONFIG_BEFS_FS is not set
 # CONFIG_BFS_FS is not set
 # CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
+# CONFIG_JFFS2_FS is not set
 # CONFIG_CRAMFS is not set
 # CONFIG_VXFS_FS is not set
 # CONFIG_HPFS_FS is not set
@@ -637,7 +717,6 @@
 CONFIG_ROOT_NFS=y
 CONFIG_LOCKD=y
 CONFIG_LOCKD_V4=y
-# CONFIG_EXPORTFS is not set
 CONFIG_SUNRPC=y
 # CONFIG_RPCSEC_GSS_KRB5 is not set
 # CONFIG_RPCSEC_GSS_SPKM3 is not set
diff -Nru a/arch/ppc/configs/mpc834x_sys_defconfig b/arch/ppc/configs/mpc834x_sys_defconfig
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/ppc/configs/mpc834x_sys_defconfig	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,644 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.11-rc4
+# Thu Feb 17 16:12:23 2005
+#
+CONFIG_MMU=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_PPC=y
+CONFIG_PPC32=y
+CONFIG_GENERIC_NVRAM=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_HOTPLUG is not set
+CONFIG_KOBJECT_UEVENT=y
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+# CONFIG_KALLSYMS is not set
+CONFIG_FUTEX=y
+# CONFIG_EPOLL is not set
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
+
+#
+# Loadable module support
+#
+# CONFIG_MODULES is not set
+
+#
+# Processor
+#
+CONFIG_6xx=y
+# CONFIG_40x is not set
+# CONFIG_44x is not set
+# CONFIG_POWER3 is not set
+# CONFIG_POWER4 is not set
+# CONFIG_8xx is not set
+# CONFIG_E500 is not set
+# CONFIG_CPU_FREQ is not set
+CONFIG_PPC_GEN550=y
+CONFIG_83xx=y
+
+#
+# Freescale 83xx options
+#
+CONFIG_MPC834x_SYS=y
+CONFIG_MPC834x=y
+CONFIG_PPC_STD_MMU=y
+
+#
+# Platform options
+#
+# CONFIG_SMP is not set
+# CONFIG_PREEMPT is not set
+# CONFIG_HIGHMEM is not set
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_CMDLINE_BOOL is not set
+
+#
+# Bus options
+#
+CONFIG_GENERIC_ISA_DMA=y
+# CONFIG_PCI is not set
+# CONFIG_PCI_DOMAINS is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PC-card bridges
+#
+
+#
+# Advanced setup
+#
+# CONFIG_ADVANCED_OPTIONS is not set
+
+#
+# Default settings for advanced configuration options are used
+#
+CONFIG_HIGHMEM_START=0xfe000000
+CONFIG_LOWMEM_SIZE=0x30000000
+CONFIG_KERNEL_START=0xc0000000
+CONFIG_TASK_SIZE=0x80000000
+CONFIG_BOOT_LOAD=0x00800000
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+# CONFIG_MTD is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=32768
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_LBD is not set
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
+# Macintosh device drivers
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+# CONFIG_NETLINK_DEV is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_IP_TCPDIAG=y
+# CONFIG_IP_TCPDIAG_IPV6 is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+
+#
+# Ethernet (1000 Mbit)
+#
+CONFIG_GIANFAR=y
+# CONFIG_GFAR_NAPI is not set
+
+#
+# Ethernet (10000 Mbit)
+#
+
+#
+# Token Ring devices
+#
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+# CONFIG_SERIO is not set
+# CONFIG_SERIO_I8042 is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+CONFIG_GEN_RTC=y
+# CONFIG_GEN_RTC_X is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+
+#
+# I2C Algorithms
+#
+# CONFIG_I2C_ALGOBIT is not set
+# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
+
+#
+# I2C Hardware Bus support
+#
+# CONFIG_I2C_ISA is not set
+CONFIG_I2C_MPC=y
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_PCA_ISA is not set
+
+#
+# Hardware Sensors Chip support
+#
+# CONFIG_I2C_SENSOR is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ASB100 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_FSCHER is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83627HF is not set
+
+#
+# Other I2C Chip support
+#
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_RTC8564 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB_ARCH_HAS_HCD is not set
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+
+#
+# XFS support
+#
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVPTS_FS_XATTR is not set
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_XATTR is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+# CONFIG_MSDOS_PARTITION is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_SERIAL_TEXT_DEBUG is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Hardware crypto devices
+#
diff -Nru a/arch/ppc/configs/pmac_defconfig b/arch/ppc/configs/pmac_defconfig
--- a/arch/ppc/configs/pmac_defconfig	2005-03-11 12:51:51 -08:00
+++ b/arch/ppc/configs/pmac_defconfig	2005-03-11 12:51:51 -08:00
@@ -1,8 +1,12 @@
 #
 # Automatically generated make config: don't edit
+# Linux kernel version: 2.6.11-rc4
+# Sun Feb 13 14:56:58 2005
 #
 CONFIG_MMU=y
+CONFIG_GENERIC_HARDIRQS=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_HAVE_DEC_LOCK=y
 CONFIG_PPC=y
 CONFIG_PPC32=y
@@ -13,40 +17,45 @@
 #
 CONFIG_EXPERIMENTAL=y
 CONFIG_CLEAN_COMPILE=y
-# CONFIG_STANDALONE is not set
 CONFIG_BROKEN_ON_SMP=y
 
 #
 # General setup
 #
+CONFIG_LOCALVERSION=""
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
 # CONFIG_BSD_PROCESS_ACCT is not set
 CONFIG_SYSCTL=y
-# CONFIG_AUDIT is not set
-CONFIG_LOG_BUF_SHIFT=14
+CONFIG_LOG_BUF_SHIFT=16
 CONFIG_HOTPLUG=y
+CONFIG_KOBJECT_UEVENT=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 # CONFIG_EMBEDDED is not set
 CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
 
 #
 # Loadable module support
 #
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
-CONFIG_MODULE_FORCE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
 CONFIG_OBSOLETE_MODPARM=y
-# CONFIG_MODVERSIONS is not set
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
 CONFIG_KMOD=y
 
 #
@@ -58,17 +67,21 @@
 # CONFIG_POWER3 is not set
 # CONFIG_POWER4 is not set
 # CONFIG_8xx is not set
+# CONFIG_E500 is not set
 CONFIG_ALTIVEC=y
 CONFIG_TAU=y
 # CONFIG_TAU_INT is not set
 # CONFIG_TAU_AVERAGE is not set
 CONFIG_CPU_FREQ=y
-CONFIG_CPU_FREQ_PROC_INTF=y
+# CONFIG_CPU_FREQ_DEBUG is not set
+CONFIG_CPU_FREQ_STAT=m
+CONFIG_CPU_FREQ_STAT_DETAILS=y
 CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y
 # CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set
 CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
-# CONFIG_CPU_FREQ_GOV_POWERSAVE is not set
-# CONFIG_CPU_FREQ_GOV_USERSPACE is not set
+CONFIG_CPU_FREQ_GOV_POWERSAVE=m
+CONFIG_CPU_FREQ_GOV_USERSPACE=m
+CONFIG_CPU_FREQ_GOV_ONDEMAND=m
 CONFIG_CPU_FREQ_PMAC=y
 CONFIG_CPU_FREQ_TABLE=y
 CONFIG_PPC601_SYNC_FIX=y
@@ -80,11 +93,14 @@
 #
 CONFIG_PPC_MULTIPLATFORM=y
 # CONFIG_APUS is not set
+# CONFIG_KATANA is not set
 # CONFIG_WILLOW is not set
+# CONFIG_CPCI690 is not set
 # CONFIG_PCORE is not set
 # CONFIG_POWERPMC250 is not set
-# CONFIG_EV64260 is not set
+# CONFIG_CHESTNUT is not set
 # CONFIG_SPRUCE is not set
+# CONFIG_EV64260 is not set
 # CONFIG_LOPEC is not set
 # CONFIG_MCPN765 is not set
 # CONFIG_MVME5100 is not set
@@ -97,9 +113,13 @@
 # CONFIG_PAL4 is not set
 # CONFIG_GEMINI is not set
 # CONFIG_EST8260 is not set
+# CONFIG_SBC82xx is not set
 # CONFIG_SBS8260 is not set
-# CONFIG_RPX6 is not set
+# CONFIG_RPX8260 is not set
 # CONFIG_TQM8260 is not set
+# CONFIG_ADS8272 is not set
+# CONFIG_PQ2FADS is not set
+# CONFIG_LITE5200 is not set
 CONFIG_PPC_CHRP=y
 CONFIG_PPC_PMAC=y
 CONFIG_PPC_PREP=y
@@ -108,11 +128,9 @@
 # CONFIG_SMP is not set
 # CONFIG_PREEMPT is not set
 # CONFIG_HIGHMEM is not set
-CONFIG_KERNEL_ELF=y
 CONFIG_BINFMT_ELF=y
 CONFIG_BINFMT_MISC=m
 CONFIG_PROC_DEVICETREE=y
-CONFIG_PPC_RTAS=y
 # CONFIG_PREP_RESIDUAL is not set
 # CONFIG_CMDLINE_BOOL is not set
 
@@ -127,14 +145,21 @@
 CONFIG_PCI_NAMES=y
 
 #
-# PCMCIA/CardBus support
+# PCCARD (PCMCIA/CardBus) support
 #
-CONFIG_PCMCIA=m
+CONFIG_PCCARD=m
 # CONFIG_PCMCIA_DEBUG is not set
-CONFIG_YENTA=m
+CONFIG_PCMCIA=m
 CONFIG_CARDBUS=y
-CONFIG_I82092=m
-CONFIG_TCIC=m
+
+#
+# PC-card bridges
+#
+CONFIG_YENTA=m
+# CONFIG_PD6729 is not set
+# CONFIG_I82092 is not set
+# CONFIG_TCIC is not set
+CONFIG_PCCARD_NONSTATIC=m
 
 #
 # Advanced setup
@@ -156,7 +181,10 @@
 #
 # Generic Driver Options
 #
+# CONFIG_STANDALONE is not set
+CONFIG_PREVENT_FIRMWARE_BUILD=y
 # CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
 
 #
 # Memory Technology Devices (MTD)
@@ -176,18 +204,35 @@
 # Block devices
 #
 # CONFIG_BLK_DEV_FD is not set
+CONFIG_MAC_FLOPPY=m
 # CONFIG_BLK_CPQ_DA is not set
 # CONFIG_BLK_CPQ_CISS_DA is not set
 # CONFIG_BLK_DEV_DAC960 is not set
 # CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
 CONFIG_BLK_DEV_LOOP=y
 # CONFIG_BLK_DEV_CRYPTOLOOP is not set
 # CONFIG_BLK_DEV_NBD is not set
-# CONFIG_BLK_DEV_CARMEL is not set
+# CONFIG_BLK_DEV_SX8 is not set
+# CONFIG_BLK_DEV_UB is not set
 CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
 CONFIG_BLK_DEV_RAM_SIZE=4096
 CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
 CONFIG_LBD=y
+CONFIG_CDROM_PKTCDVD=m
+CONFIG_CDROM_PKTCDVD_BUFFERS=8
+# CONFIG_CDROM_PKTCDVD_WCACHE is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
 
 #
 # ATA/ATAPI/MFM/RLL support
@@ -198,16 +243,15 @@
 #
 # Please see Documentation/ide.txt for help/info on IDE drives
 #
+# CONFIG_BLK_DEV_IDE_SATA is not set
 CONFIG_BLK_DEV_IDEDISK=y
 # CONFIG_IDEDISK_MULTI_MODE is not set
-# CONFIG_IDEDISK_STROKE is not set
-CONFIG_BLK_DEV_IDECS=m
+# CONFIG_BLK_DEV_IDECS is not set
 CONFIG_BLK_DEV_IDECD=y
 # CONFIG_BLK_DEV_IDETAPE is not set
 CONFIG_BLK_DEV_IDEFLOPPY=y
 CONFIG_BLK_DEV_IDESCSI=y
 # CONFIG_IDE_TASK_IOCTL is not set
-# CONFIG_IDE_TASKFILE_IO is not set
 
 #
 # IDE chipset support/bugfixes
@@ -218,12 +262,11 @@
 # CONFIG_BLK_DEV_OFFBOARD is not set
 CONFIG_BLK_DEV_GENERIC=y
 # CONFIG_BLK_DEV_OPTI621 is not set
-CONFIG_BLK_DEV_SL82C105=y
+# CONFIG_BLK_DEV_SL82C105 is not set
 CONFIG_BLK_DEV_IDEDMA_PCI=y
 # CONFIG_BLK_DEV_IDEDMA_FORCED is not set
 CONFIG_IDEDMA_PCI_AUTO=y
 # CONFIG_IDEDMA_ONLYDISK is not set
-CONFIG_BLK_DEV_ADMA=y
 # CONFIG_BLK_DEV_AEC62XX is not set
 # CONFIG_BLK_DEV_ALI15X3 is not set
 # CONFIG_BLK_DEV_AMD74XX is not set
@@ -249,7 +292,7 @@
 CONFIG_BLK_DEV_IDE_PMAC_ATA100FIRST=y
 CONFIG_BLK_DEV_IDEDMA_PMAC=y
 CONFIG_BLK_DEV_IDE_PMAC_BLINK=y
-CONFIG_BLK_DEV_IDEDMA_PMAC_AUTO=y
+# CONFIG_IDE_ARM is not set
 CONFIG_BLK_DEV_IDEDMA=y
 # CONFIG_IDEDMA_IVB is not set
 CONFIG_IDEDMA_AUTO=y
@@ -275,7 +318,6 @@
 # Some SCSI devices (e.g. CD jukebox) support multiple LUNs
 #
 # CONFIG_SCSI_MULTI_LUN is not set
-# CONFIG_SCSI_REPORT_LUNS is not set
 CONFIG_SCSI_CONSTANTS=y
 # CONFIG_SCSI_LOGGING is not set
 
@@ -284,33 +326,35 @@
 #
 CONFIG_SCSI_SPI_ATTRS=y
 # CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
 
 #
 # SCSI low-level drivers
 #
 # CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_3W_9XXX is not set
 # CONFIG_SCSI_ACARD is not set
 # CONFIG_SCSI_AACRAID is not set
 CONFIG_SCSI_AIC7XXX=m
 CONFIG_AIC7XXX_CMDS_PER_DEVICE=253
 CONFIG_AIC7XXX_RESET_DELAY_MS=15000
-# CONFIG_AIC7XXX_BUILD_FIRMWARE is not set
 CONFIG_AIC7XXX_DEBUG_ENABLE=y
 CONFIG_AIC7XXX_DEBUG_MASK=0
 CONFIG_AIC7XXX_REG_PRETTY_PRINT=y
 CONFIG_SCSI_AIC7XXX_OLD=m
 # CONFIG_SCSI_AIC79XX is not set
-CONFIG_SCSI_ADVANSYS=m
-# CONFIG_SCSI_MEGARAID is not set
+# CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
 # CONFIG_SCSI_SATA is not set
 # CONFIG_SCSI_BUSLOGIC is not set
-# CONFIG_SCSI_CPQFCTS is not set
 # CONFIG_SCSI_DMX3191D is not set
 # CONFIG_SCSI_EATA is not set
 # CONFIG_SCSI_EATA_PIO is not set
 # CONFIG_SCSI_FUTURE_DOMAIN is not set
 # CONFIG_SCSI_GDTH is not set
 # CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INITIO is not set
 # CONFIG_SCSI_INIA100 is not set
 CONFIG_SCSI_SYM53C8XX_2=y
 CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=0
@@ -327,7 +371,6 @@
 # CONFIG_SCSI_QLA2300 is not set
 # CONFIG_SCSI_QLA2322 is not set
 # CONFIG_SCSI_QLA6312 is not set
-# CONFIG_SCSI_QLA6322 is not set
 # CONFIG_SCSI_DC395x is not set
 # CONFIG_SCSI_DC390T is not set
 # CONFIG_SCSI_NSP32 is not set
@@ -384,7 +427,8 @@
 CONFIG_IEEE1394_ETH1394=m
 CONFIG_IEEE1394_DV1394=m
 CONFIG_IEEE1394_RAWIO=m
-# CONFIG_IEEE1394_CMP is not set
+CONFIG_IEEE1394_CMP=m
+CONFIG_IEEE1394_AMDTP=m
 
 #
 # I2O device support
@@ -400,8 +444,6 @@
 CONFIG_PMAC_PBOOK=y
 CONFIG_PMAC_APM_EMU=y
 CONFIG_PMAC_BACKLIGHT=y
-# CONFIG_MAC_FLOPPY is not set
-CONFIG_MAC_SERIAL=y
 CONFIG_ADB_MACIO=y
 CONFIG_INPUT_ADBHID=y
 CONFIG_MAC_EMUMOUSEBTN=y
@@ -434,6 +476,9 @@
 # CONFIG_INET_AH is not set
 # CONFIG_INET_ESP is not set
 # CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_IP_TCPDIAG=y
+# CONFIG_IP_TCPDIAG_IPV6 is not set
 
 #
 # IP: Virtual Server Configuration
@@ -447,11 +492,14 @@
 # IP: Netfilter Configuration
 #
 CONFIG_IP_NF_CONNTRACK=m
+CONFIG_IP_NF_CT_ACCT=y
+CONFIG_IP_NF_CONNTRACK_MARK=y
+CONFIG_IP_NF_CT_PROTO_SCTP=m
 CONFIG_IP_NF_FTP=m
 CONFIG_IP_NF_IRC=m
 CONFIG_IP_NF_TFTP=m
 CONFIG_IP_NF_AMANDA=m
-# CONFIG_IP_NF_QUEUE is not set
+CONFIG_IP_NF_QUEUE=m
 CONFIG_IP_NF_IPTABLES=m
 CONFIG_IP_NF_MATCH_LIMIT=m
 CONFIG_IP_NF_MATCH_IPRANGE=m
@@ -471,8 +519,17 @@
 CONFIG_IP_NF_MATCH_STATE=m
 CONFIG_IP_NF_MATCH_CONNTRACK=m
 CONFIG_IP_NF_MATCH_OWNER=m
+CONFIG_IP_NF_MATCH_ADDRTYPE=m
+CONFIG_IP_NF_MATCH_REALM=m
+CONFIG_IP_NF_MATCH_SCTP=m
+CONFIG_IP_NF_MATCH_COMMENT=m
+CONFIG_IP_NF_MATCH_CONNMARK=m
+CONFIG_IP_NF_MATCH_HASHLIMIT=m
 CONFIG_IP_NF_FILTER=m
 CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_LOG=m
+CONFIG_IP_NF_TARGET_ULOG=m
+CONFIG_IP_NF_TARGET_TCPMSS=m
 CONFIG_IP_NF_NAT=m
 CONFIG_IP_NF_NAT_NEEDED=y
 CONFIG_IP_NF_TARGET_MASQUERADE=m
@@ -484,17 +541,19 @@
 CONFIG_IP_NF_NAT_FTP=m
 CONFIG_IP_NF_NAT_TFTP=m
 CONFIG_IP_NF_NAT_AMANDA=m
-# CONFIG_IP_NF_MANGLE is not set
-# CONFIG_IP_NF_TARGET_LOG is not set
-CONFIG_IP_NF_TARGET_ULOG=m
-CONFIG_IP_NF_TARGET_TCPMSS=m
+CONFIG_IP_NF_MANGLE=m
+CONFIG_IP_NF_TARGET_TOS=m
+CONFIG_IP_NF_TARGET_ECN=m
+CONFIG_IP_NF_TARGET_DSCP=m
+CONFIG_IP_NF_TARGET_MARK=m
+CONFIG_IP_NF_TARGET_CLASSIFY=m
+CONFIG_IP_NF_TARGET_CONNMARK=m
+CONFIG_IP_NF_TARGET_CLUSTERIP=m
+CONFIG_IP_NF_RAW=m
+CONFIG_IP_NF_TARGET_NOTRACK=m
 CONFIG_IP_NF_ARPTABLES=m
 CONFIG_IP_NF_ARPFILTER=m
 CONFIG_IP_NF_ARP_MANGLE=m
-CONFIG_IP_NF_COMPAT_IPCHAINS=m
-# CONFIG_IP_NF_COMPAT_IPFWADM is not set
-CONFIG_IP_NF_TARGET_NOTRACK=m
-CONFIG_IP_NF_RAW=m
 
 #
 # SCTP Configuration (EXPERIMENTAL)
@@ -512,12 +571,12 @@
 # CONFIG_NET_DIVERT is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
-# CONFIG_NET_HW_FLOWCONTROL is not set
 
 #
 # QoS and/or fair queueing
 #
 # CONFIG_NET_SCHED is not set
+CONFIG_NET_CLS_ROUTE=y
 
 #
 # Network testing
@@ -593,7 +652,6 @@
 CONFIG_MACE=y
 # CONFIG_MACE_AAUI_PORT is not set
 CONFIG_BMAC=y
-# CONFIG_OAKNET is not set
 # CONFIG_HAPPYMEAL is not set
 CONFIG_SUNGEM=y
 # CONFIG_NET_VENDOR_3COM is not set
@@ -634,6 +692,7 @@
 # CONFIG_YELLOWFIN is not set
 # CONFIG_R8169 is not set
 # CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
 
 #
@@ -667,7 +726,6 @@
 #
 # Wireless 802.11b ISA/PCI cards support
 #
-# CONFIG_AIRO is not set
 CONFIG_HERMES=m
 CONFIG_APPLE_AIRPORT=m
 # CONFIG_PLX_HERMES is not set
@@ -691,15 +749,7 @@
 #
 # PCMCIA network device support
 #
-CONFIG_NET_PCMCIA=y
-# CONFIG_PCMCIA_3C589 is not set
-# CONFIG_PCMCIA_3C574 is not set
-# CONFIG_PCMCIA_FMVJ18X is not set
-# CONFIG_PCMCIA_PCNET is not set
-# CONFIG_PCMCIA_NMCLAN is not set
-# CONFIG_PCMCIA_SMC91C92 is not set
-# CONFIG_PCMCIA_XIRC2PS is not set
-# CONFIG_PCMCIA_AXNET is not set
+# CONFIG_NET_PCMCIA is not set
 
 #
 # Wan interfaces
@@ -714,10 +764,9 @@
 CONFIG_PPP_SYNC_TTY=m
 CONFIG_PPP_DEFLATE=y
 CONFIG_PPP_BSDCOMP=m
-# CONFIG_PPPOE is not set
+CONFIG_PPPOE=m
 # CONFIG_SLIP is not set
 # CONFIG_NET_FC is not set
-# CONFIG_RCPCI is not set
 # CONFIG_SHAPER is not set
 # CONFIG_NETCONSOLE is not set
 
@@ -740,7 +789,7 @@
 # Userland interfaces
 #
 CONFIG_INPUT_MOUSEDEV=y
-CONFIG_INPUT_MOUSEDEV_PSAUX=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
 CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
 CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
 # CONFIG_INPUT_JOYDEV is not set
@@ -753,11 +802,8 @@
 #
 # CONFIG_GAMEPORT is not set
 CONFIG_SOUND_GAMEPORT=y
-CONFIG_SERIO=y
+# CONFIG_SERIO is not set
 # CONFIG_SERIO_I8042 is not set
-# CONFIG_SERIO_SERPORT is not set
-# CONFIG_SERIO_CT82C710 is not set
-# CONFIG_SERIO_PCIPS2 is not set
 
 #
 # Input Device Drivers
@@ -796,12 +842,12 @@
 # Non-8250 serial port support
 #
 CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
 CONFIG_SERIAL_PMACZILOG=y
-# CONFIG_SERIAL_PMACZILOG_CONSOLE is not set
+CONFIG_SERIAL_PMACZILOG_CONSOLE=y
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
-# CONFIG_QIC02_TAPE is not set
 
 #
 # IPMI
@@ -822,9 +868,14 @@
 #
 # Ftape, the floppy tape device driver
 #
-# CONFIG_FTAPE is not set
-# CONFIG_AGP is not set
-# CONFIG_DRM is not set
+CONFIG_AGP=m
+CONFIG_AGP_UNINORTH=m
+CONFIG_DRM=m
+# CONFIG_DRM_TDFX is not set
+CONFIG_DRM_R128=m
+CONFIG_DRM_RADEON=m
+# CONFIG_DRM_MGA is not set
+# CONFIG_DRM_SIS is not set
 
 #
 # PCMCIA character devices
@@ -843,6 +894,7 @@
 #
 CONFIG_I2C_ALGOBIT=y
 # CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
 
 #
 # I2C Hardware Bus support
@@ -857,6 +909,7 @@
 # CONFIG_I2C_I810 is not set
 # CONFIG_I2C_ISA is not set
 CONFIG_I2C_KEYWEST=m
+# CONFIG_I2C_MPC is not set
 # CONFIG_I2C_NFORCE2 is not set
 # CONFIG_I2C_PARPORT_LIGHT is not set
 # CONFIG_I2C_PIIX4 is not set
@@ -866,26 +919,38 @@
 # CONFIG_I2C_SIS5595 is not set
 # CONFIG_I2C_SIS630 is not set
 # CONFIG_I2C_SIS96X is not set
+# CONFIG_I2C_STUB is not set
 # CONFIG_I2C_VIA is not set
 # CONFIG_I2C_VIAPRO is not set
 # CONFIG_I2C_VOODOO3 is not set
+# CONFIG_I2C_PCA_ISA is not set
 
 #
 # Hardware Sensors Chip support
 #
 # CONFIG_I2C_SENSOR is not set
 # CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1031 is not set
 # CONFIG_SENSORS_ASB100 is not set
 # CONFIG_SENSORS_DS1621 is not set
 # CONFIG_SENSORS_FSCHER is not set
 # CONFIG_SENSORS_GL518SM is not set
 # CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
 # CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
 # CONFIG_SENSORS_LM78 is not set
 # CONFIG_SENSORS_LM80 is not set
 # CONFIG_SENSORS_LM83 is not set
 # CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
 # CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
 # CONFIG_SENSORS_VIA686A is not set
 # CONFIG_SENSORS_W83781D is not set
 # CONFIG_SENSORS_W83L785TS is not set
@@ -897,12 +962,18 @@
 # CONFIG_SENSORS_EEPROM is not set
 # CONFIG_SENSORS_PCF8574 is not set
 # CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_RTC8564 is not set
 # CONFIG_I2C_DEBUG_CORE is not set
 # CONFIG_I2C_DEBUG_ALGO is not set
 # CONFIG_I2C_DEBUG_BUS is not set
 # CONFIG_I2C_DEBUG_CHIP is not set
 
 #
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
 # Misc devices
 #
 
@@ -920,6 +991,9 @@
 # Graphics support
 #
 CONFIG_FB=y
+CONFIG_FB_MODE_HELPERS=y
+CONFIG_FB_TILEBLITTING=y
+# CONFIG_FB_CIRRUS is not set
 # CONFIG_FB_PM2 is not set
 # CONFIG_FB_CYBER2000 is not set
 CONFIG_FB_OF=y
@@ -927,16 +1001,14 @@
 CONFIG_FB_PLATINUM=y
 CONFIG_FB_VALKYRIE=y
 CONFIG_FB_CT65550=y
+# CONFIG_FB_ASILIANT is not set
 CONFIG_FB_IMSTT=y
-# CONFIG_FB_S3TRIO is not set
 # CONFIG_FB_VGA16 is not set
 # CONFIG_FB_RIVA is not set
 CONFIG_FB_MATROX=y
 CONFIG_FB_MATROX_MILLENIUM=y
 CONFIG_FB_MATROX_MYSTIQUE=y
-# CONFIG_FB_MATROX_G450 is not set
-CONFIG_FB_MATROX_G100A=y
-CONFIG_FB_MATROX_G100=y
+CONFIG_FB_MATROX_G=y
 # CONFIG_FB_MATROX_I2C is not set
 # CONFIG_FB_MATROX_MULTIHEAD is not set
 # CONFIG_FB_RADEON_OLD is not set
@@ -946,12 +1018,15 @@
 CONFIG_FB_ATY128=y
 CONFIG_FB_ATY=y
 CONFIG_FB_ATY_CT=y
-CONFIG_FB_ATY_GX=y
+CONFIG_FB_ATY_GENERIC_LCD=y
 # CONFIG_FB_ATY_XL_INIT is not set
+CONFIG_FB_ATY_GX=y
+# CONFIG_FB_SAVAGE is not set
 # CONFIG_FB_SIS is not set
 # CONFIG_FB_NEOMAGIC is not set
 # CONFIG_FB_KYRO is not set
 CONFIG_FB_3DFX=y
+CONFIG_FB_3DFX_ACCEL=y
 # CONFIG_FB_VOODOO1 is not set
 # CONFIG_FB_TRIDENT is not set
 # CONFIG_FB_VIRTUAL is not set
@@ -960,10 +1035,8 @@
 # Console display driver support
 #
 # CONFIG_VGA_CONSOLE is not set
-# CONFIG_MDA_CONSOLE is not set
 CONFIG_DUMMY_CONSOLE=y
 CONFIG_FRAMEBUFFER_CONSOLE=y
-CONFIG_PCI_CONSOLE=y
 # CONFIG_FONTS is not set
 CONFIG_FONT_8x8=y
 CONFIG_FONT_8x16=y
@@ -975,6 +1048,11 @@
 CONFIG_LOGO_LINUX_MONO=y
 CONFIG_LOGO_LINUX_VGA16=y
 CONFIG_LOGO_LINUX_CLUT224=y
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+CONFIG_BACKLIGHT_DEVICE=y
+CONFIG_LCD_CLASS_DEVICE=y
+CONFIG_LCD_DEVICE=y
 
 #
 # Sound
@@ -989,6 +1067,7 @@
 CONFIG_SND=m
 CONFIG_SND_TIMER=m
 CONFIG_SND_PCM=m
+CONFIG_SND_HWDEP=m
 CONFIG_SND_RAWMIDI=m
 CONFIG_SND_SEQUENCER=m
 CONFIG_SND_SEQ_DUMMY=m
@@ -1013,6 +1092,7 @@
 #
 # CONFIG_SND_ALI5451 is not set
 # CONFIG_SND_ATIIXP is not set
+# CONFIG_SND_ATIIXP_MODEM is not set
 # CONFIG_SND_AU8810 is not set
 # CONFIG_SND_AU8820 is not set
 # CONFIG_SND_AU8830 is not set
@@ -1021,6 +1101,8 @@
 # CONFIG_SND_CS46XX is not set
 # CONFIG_SND_CS4281 is not set
 # CONFIG_SND_EMU10K1 is not set
+# CONFIG_SND_EMU10K1X is not set
+# CONFIG_SND_CA0106 is not set
 # CONFIG_SND_KORG1212 is not set
 # CONFIG_SND_MIXART is not set
 # CONFIG_SND_NM256 is not set
@@ -1044,6 +1126,7 @@
 # CONFIG_SND_INTEL8X0M is not set
 # CONFIG_SND_SONICVIBES is not set
 # CONFIG_SND_VIA82XX is not set
+# CONFIG_SND_VIA82XX_MODEM is not set
 # CONFIG_SND_VX222 is not set
 
 #
@@ -1052,9 +1135,10 @@
 CONFIG_SND_POWERMAC=m
 
 #
-# ALSA USB devices
+# USB devices
 #
 CONFIG_SND_USB_AUDIO=m
+CONFIG_SND_USB_USX2Y=m
 
 #
 # PCMCIA devices
@@ -1077,6 +1161,10 @@
 CONFIG_USB_DEVICEFS=y
 # CONFIG_USB_BANDWIDTH is not set
 CONFIG_USB_DYNAMIC_MINORS=y
+CONFIG_USB_SUSPEND=y
+# CONFIG_USB_OTG is not set
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
 
 #
 # USB Host Controller Drivers
@@ -1084,6 +1172,7 @@
 # CONFIG_USB_EHCI_HCD is not set
 CONFIG_USB_OHCI_HCD=y
 # CONFIG_USB_UHCI_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
 
 #
 # USB Device Class drivers
@@ -1093,20 +1182,25 @@
 # CONFIG_USB_MIDI is not set
 CONFIG_USB_ACM=m
 CONFIG_USB_PRINTER=m
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
 # CONFIG_USB_STORAGE is not set
 
 #
-# USB Human Interface Devices (HID)
+# USB Input Devices
 #
 CONFIG_USB_HID=y
 CONFIG_USB_HIDINPUT=y
 # CONFIG_HID_FF is not set
-# CONFIG_USB_HIDDEV is not set
+CONFIG_USB_HIDDEV=y
 # CONFIG_USB_AIPTEK is not set
 # CONFIG_USB_WACOM is not set
 # CONFIG_USB_KBTAB is not set
 # CONFIG_USB_POWERMATE is not set
 # CONFIG_USB_MTOUCH is not set
+# CONFIG_USB_EGALAX is not set
 # CONFIG_USB_XPAD is not set
 # CONFIG_USB_ATI_REMOTE is not set
 
@@ -1115,7 +1209,6 @@
 #
 # CONFIG_USB_MDC800 is not set
 # CONFIG_USB_MICROTEK is not set
-# CONFIG_USB_HPUSBSCSI is not set
 
 #
 # USB Multimedia devices
@@ -1127,11 +1220,11 @@
 #
 
 #
-# USB Network adaptors
+# USB Network Adapters
 #
 # CONFIG_USB_CATC is not set
 # CONFIG_USB_KAWETH is not set
-# CONFIG_USB_PEGASUS is not set
+CONFIG_USB_PEGASUS=m
 # CONFIG_USB_RTL8150 is not set
 # CONFIG_USB_USBNET is not set
 
@@ -1147,6 +1240,7 @@
 # CONFIG_USB_SERIAL_BELKIN is not set
 # CONFIG_USB_SERIAL_WHITEHEAT is not set
 # CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set
+# CONFIG_USB_SERIAL_CYPRESS_M8 is not set
 # CONFIG_USB_SERIAL_EMPEG is not set
 # CONFIG_USB_SERIAL_FTDI_SIO is not set
 CONFIG_USB_SERIAL_VISOR=m
@@ -1154,41 +1248,75 @@
 # CONFIG_USB_SERIAL_IR is not set
 # CONFIG_USB_SERIAL_EDGEPORT is not set
 # CONFIG_USB_SERIAL_EDGEPORT_TI is not set
+# CONFIG_USB_SERIAL_GARMIN is not set
+# CONFIG_USB_SERIAL_IPW is not set
 # CONFIG_USB_SERIAL_KEYSPAN_PDA is not set
-# CONFIG_USB_SERIAL_KEYSPAN is not set
+CONFIG_USB_SERIAL_KEYSPAN=m
+CONFIG_USB_SERIAL_KEYSPAN_MPR=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28X=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28XA=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28XB=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19=y
+CONFIG_USB_SERIAL_KEYSPAN_USA18X=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19W=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19QW=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19QI=y
+CONFIG_USB_SERIAL_KEYSPAN_USA49W=y
+CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y
 # CONFIG_USB_SERIAL_KLSI is not set
 # CONFIG_USB_SERIAL_KOBIL_SCT is not set
 # CONFIG_USB_SERIAL_MCT_U232 is not set
 # CONFIG_USB_SERIAL_PL2303 is not set
 # CONFIG_USB_SERIAL_SAFE is not set
+# CONFIG_USB_SERIAL_TI is not set
 # CONFIG_USB_SERIAL_CYBERJACK is not set
 # CONFIG_USB_SERIAL_XIRCOM is not set
 # CONFIG_USB_SERIAL_OMNINET is not set
+CONFIG_USB_EZUSB=y
 
 #
 # USB Miscellaneous drivers
 #
 # CONFIG_USB_EMI62 is not set
 # CONFIG_USB_EMI26 is not set
-# CONFIG_USB_TIGL is not set
 # CONFIG_USB_AUERSWALD is not set
 # CONFIG_USB_RIO500 is not set
 # CONFIG_USB_LEGOTOWER is not set
 # CONFIG_USB_LCD is not set
 # CONFIG_USB_LED is not set
 # CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGETKIT is not set
+# CONFIG_USB_PHIDGETSERVO is not set
+# CONFIG_USB_IDMOUSE is not set
 # CONFIG_USB_TEST is not set
 
 #
+# USB ATM/DSL drivers
+#
+
+#
 # USB Gadget Support
 #
 # CONFIG_USB_GADGET is not set
 
 #
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
-# CONFIG_EXT2_FS_XATTR is not set
+CONFIG_EXT2_FS_XATTR=y
+# CONFIG_EXT2_FS_POSIX_ACL is not set
+# CONFIG_EXT2_FS_SECURITY is not set
 CONFIG_EXT3_FS=y
 CONFIG_EXT3_FS_XATTR=y
 # CONFIG_EXT3_FS_POSIX_ACL is not set
@@ -1198,10 +1326,15 @@
 CONFIG_FS_MBCACHE=y
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
+
+#
+# XFS support
+#
 # CONFIG_XFS_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
 # CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
 
@@ -1211,7 +1344,8 @@
 CONFIG_ISO9660_FS=y
 # CONFIG_JOLIET is not set
 # CONFIG_ZISOFS is not set
-# CONFIG_UDF_FS is not set
+CONFIG_UDF_FS=m
+CONFIG_UDF_NLS=y
 
 #
 # DOS/FAT/NT Filesystems
@@ -1219,6 +1353,8 @@
 CONFIG_FAT_FS=m
 CONFIG_MSDOS_FS=m
 CONFIG_VFAT_FS=m
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
 # CONFIG_NTFS_FS is not set
 
 #
@@ -1227,11 +1363,12 @@
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
 CONFIG_SYSFS=y
-CONFIG_DEVFS_FS=y
-# CONFIG_DEVFS_MOUNT is not set
-# CONFIG_DEVFS_DEBUG is not set
-# CONFIG_DEVPTS_FS_XATTR is not set
+# CONFIG_DEVFS_FS is not set
+CONFIG_DEVPTS_FS_XATTR=y
+CONFIG_DEVPTS_FS_SECURITY=y
 CONFIG_TMPFS=y
+CONFIG_TMPFS_XATTR=y
+CONFIG_TMPFS_SECURITY=y
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
 
@@ -1245,7 +1382,7 @@
 # CONFIG_BEFS_FS is not set
 # CONFIG_BFS_FS is not set
 # CONFIG_EFS_FS is not set
-# CONFIG_CRAMFS is not set
+CONFIG_CRAMFS=m
 # CONFIG_VXFS_FS is not set
 # CONFIG_HPFS_FS is not set
 # CONFIG_QNX4FS_FS is not set
@@ -1256,16 +1393,19 @@
 # Network File Systems
 #
 CONFIG_NFS_FS=y
-# CONFIG_NFS_V3 is not set
+CONFIG_NFS_V3=y
 # CONFIG_NFS_V4 is not set
 # CONFIG_NFS_DIRECTIO is not set
 CONFIG_NFSD=y
-# CONFIG_NFSD_V3 is not set
-# CONFIG_NFSD_TCP is not set
+CONFIG_NFSD_V3=y
+# CONFIG_NFSD_V4 is not set
+CONFIG_NFSD_TCP=y
 CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
 CONFIG_EXPORTFS=y
 CONFIG_SUNRPC=y
 # CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
 CONFIG_SMB_FS=m
 # CONFIG_SMB_NLS_DEFAULT is not set
 # CONFIG_CIFS is not set
@@ -1288,7 +1428,6 @@
 # CONFIG_SOLARIS_X86_PARTITION is not set
 # CONFIG_UNIXWARE_DISKLABEL is not set
 # CONFIG_LDM_PARTITION is not set
-# CONFIG_NEC98_PARTITION is not set
 # CONFIG_SGI_PARTITION is not set
 # CONFIG_ULTRIX_PARTITION is not set
 # CONFIG_SUN_PARTITION is not set
@@ -1320,8 +1459,9 @@
 # CONFIG_NLS_CODEPAGE_949 is not set
 # CONFIG_NLS_CODEPAGE_874 is not set
 # CONFIG_NLS_ISO8859_8 is not set
-# CONFIG_NLS_CODEPAGE_1250 is not set
-# CONFIG_NLS_CODEPAGE_1251 is not set
+CONFIG_NLS_CODEPAGE_1250=m
+CONFIG_NLS_CODEPAGE_1251=m
+CONFIG_NLS_ASCII=m
 CONFIG_NLS_ISO8859_1=m
 # CONFIG_NLS_ISO8859_2 is not set
 # CONFIG_NLS_ISO8859_3 is not set
@@ -1332,31 +1472,52 @@
 # CONFIG_NLS_ISO8859_9 is not set
 # CONFIG_NLS_ISO8859_13 is not set
 # CONFIG_NLS_ISO8859_14 is not set
-# CONFIG_NLS_ISO8859_15 is not set
+CONFIG_NLS_ISO8859_15=m
 # CONFIG_NLS_KOI8_R is not set
 # CONFIG_NLS_KOI8_U is not set
-# CONFIG_NLS_UTF8 is not set
+CONFIG_NLS_UTF8=m
 
 #
 # Library routines
 #
+CONFIG_CRC_CCITT=y
 CONFIG_CRC32=y
 # CONFIG_LIBCRC32C is not set
 CONFIG_ZLIB_INFLATE=y
 CONFIG_ZLIB_DEFLATE=y
 
 #
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
 # Kernel hacking
 #
-# CONFIG_DEBUG_KERNEL is not set
+CONFIG_DEBUG_KERNEL=y
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_XMON is not set
+# CONFIG_BDI_SWITCH is not set
 CONFIG_BOOTX_TEXT=y
 
 #
 # Security options
 #
+# CONFIG_KEYS is not set
 # CONFIG_SECURITY is not set
 
 #
 # Cryptographic options
 #
 # CONFIG_CRYPTO is not set
+
+#
+# Hardware crypto devices
+#
diff -Nru a/arch/ppc/configs/radstone_ppc7d_defconfig b/arch/ppc/configs/radstone_ppc7d_defconfig
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/ppc/configs/radstone_ppc7d_defconfig	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,870 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.11-rc4
+# Thu Feb 24 21:26:04 2005
+#
+CONFIG_MMU=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_HAVE_DEC_LOCK=y
+CONFIG_PPC=y
+CONFIG_PPC32=y
+CONFIG_GENERIC_NVRAM=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_HOTPLUG is not set
+CONFIG_KOBJECT_UEVENT=y
+# CONFIG_IKCONFIG is not set
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+CONFIG_KALLSYMS_EXTRA_PASS=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+
+#
+# Processor
+#
+CONFIG_6xx=y
+# CONFIG_40x is not set
+# CONFIG_44x is not set
+# CONFIG_POWER3 is not set
+# CONFIG_POWER4 is not set
+# CONFIG_8xx is not set
+# CONFIG_E500 is not set
+CONFIG_ALTIVEC=y
+# CONFIG_TAU is not set
+# CONFIG_CPU_FREQ is not set
+CONFIG_PPC_GEN550=y
+CONFIG_PPC_STD_MMU=y
+# CONFIG_NOT_COHERENT_CACHE is not set
+
+#
+# Platform options
+#
+# CONFIG_PPC_MULTIPLATFORM is not set
+# CONFIG_APUS is not set
+# CONFIG_KATANA is not set
+# CONFIG_WILLOW is not set
+# CONFIG_CPCI690 is not set
+# CONFIG_PCORE is not set
+# CONFIG_POWERPMC250 is not set
+# CONFIG_CHESTNUT is not set
+# CONFIG_SPRUCE is not set
+# CONFIG_EV64260 is not set
+# CONFIG_LOPEC is not set
+# CONFIG_MCPN765 is not set
+# CONFIG_MVME5100 is not set
+# CONFIG_PPLUS is not set
+# CONFIG_PRPMC750 is not set
+# CONFIG_PRPMC800 is not set
+# CONFIG_SANDPOINT is not set
+CONFIG_RADSTONE_PPC7D=y
+# CONFIG_ADIR is not set
+# CONFIG_K2 is not set
+# CONFIG_PAL4 is not set
+# CONFIG_GEMINI is not set
+# CONFIG_EST8260 is not set
+# CONFIG_SBC82xx is not set
+# CONFIG_SBS8260 is not set
+# CONFIG_RPX8260 is not set
+# CONFIG_TQM8260 is not set
+# CONFIG_ADS8272 is not set
+# CONFIG_PQ2FADS is not set
+# CONFIG_LITE5200 is not set
+CONFIG_MV64360=y
+CONFIG_MV64X60=y
+
+#
+# Set bridge options
+#
+CONFIG_MV64X60_BASE=0xfef00000
+CONFIG_MV64X60_NEW_BASE=0xfef00000
+# CONFIG_SMP is not set
+# CONFIG_PREEMPT is not set
+# CONFIG_HIGHMEM is not set
+CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_MISC=y
+CONFIG_CMDLINE_BOOL=y
+CONFIG_CMDLINE="console=ttyS0,9600"
+
+#
+# Bus options
+#
+CONFIG_GENERIC_ISA_DMA=y
+CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
+CONFIG_PCI_LEGACY_PROC=y
+CONFIG_PCI_NAMES=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PC-card bridges
+#
+
+#
+# Advanced setup
+#
+CONFIG_ADVANCED_OPTIONS=y
+CONFIG_HIGHMEM_START=0xfe000000
+# CONFIG_LOWMEM_SIZE_BOOL is not set
+CONFIG_LOWMEM_SIZE=0x30000000
+# CONFIG_KERNEL_START_BOOL is not set
+CONFIG_KERNEL_START=0xc0000000
+# CONFIG_TASK_SIZE_BOOL is not set
+CONFIG_TASK_SIZE=0x80000000
+# CONFIG_BOOT_LOAD_BOOL is not set
+CONFIG_BOOT_LOAD=0x00800000
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_PARTITIONS is not set
+# CONFIG_MTD_CONCAT is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+CONFIG_FTL=y
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+CONFIG_MTD_CFI_ADV_OPTIONS=y
+CONFIG_MTD_CFI_NOSWAP=y
+# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set
+# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set
+# CONFIG_MTD_CFI_GEOMETRY is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+CONFIG_MTD_CFI_INTELEXT=y
+# CONFIG_MTD_CFI_AMDSTD is not set
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+# CONFIG_MTD_XIP is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PHYSMAP is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_PMC551 is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLKMTD is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+
+#
+# NAND Flash Device Drivers
+#
+# CONFIG_MTD_NAND is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_SX8 is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=8192
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_LBD is not set
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+CONFIG_SCSI=y
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+CONFIG_BLK_DEV_SR=y
+CONFIG_BLK_DEV_SR_VENDOR=y
+CONFIG_CHR_DEV_SG=y
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+CONFIG_SCSI_MULTI_LUN=y
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+
+#
+# SCSI Transport Attributes
+#
+CONFIG_SCSI_SPI_ATTRS=y
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_3W_9XXX is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AACRAID is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_EATA is not set
+# CONFIG_SCSI_EATA_PIO is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_GDTH is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+CONFIG_SCSI_SYM53C8XX_2=y
+CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1
+CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
+CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
+# CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set
+# CONFIG_SCSI_IPR is not set
+# CONFIG_SCSI_QLOGIC_ISP is not set
+# CONFIG_SCSI_QLOGIC_FC is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+CONFIG_SCSI_QLA2XXX=y
+# CONFIG_SCSI_QLA21XX is not set
+# CONFIG_SCSI_QLA22XX is not set
+# CONFIG_SCSI_QLA2300 is not set
+# CONFIG_SCSI_QLA2322 is not set
+# CONFIG_SCSI_QLA6312 is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_NSP32 is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
+# Macintosh device drivers
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+# CONFIG_NETLINK_DEV is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_IP_TCPDIAG=y
+# CONFIG_IP_TCPDIAG_IPV6 is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+CONFIG_BRIDGE=y
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_NET_VENDOR_3COM is not set
+
+#
+# Tulip family network device support
+#
+CONFIG_NET_TULIP=y
+# CONFIG_DE2104X is not set
+CONFIG_TULIP=y
+# CONFIG_TULIP_MWI is not set
+# CONFIG_TULIP_MMIO is not set
+# CONFIG_TULIP_NAPI is not set
+# CONFIG_DE4X5 is not set
+# CONFIG_WINBOND_840 is not set
+# CONFIG_DM9102 is not set
+# CONFIG_HP100 is not set
+CONFIG_NET_PCI=y
+# CONFIG_PCNET32 is not set
+# CONFIG_AMD8111_ETH is not set
+# CONFIG_ADAPTEC_STARFIRE is not set
+# CONFIG_B44 is not set
+# CONFIG_FORCEDETH is not set
+# CONFIG_DGRS is not set
+# CONFIG_EEPRO100 is not set
+CONFIG_E100=y
+# CONFIG_E100_NAPI is not set
+# CONFIG_FEALNX is not set
+# CONFIG_NATSEMI is not set
+# CONFIG_NE2K_PCI is not set
+# CONFIG_8139CP is not set
+# CONFIG_8139TOO is not set
+# CONFIG_SIS900 is not set
+# CONFIG_EPIC100 is not set
+# CONFIG_SUNDANCE is not set
+# CONFIG_TLAN is not set
+# CONFIG_VIA_RHINE is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_E1000 is not set
+# CONFIG_NS83820 is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+CONFIG_R8169=y
+CONFIG_R8169_NAPI=y
+CONFIG_SK98LIN=y
+# CONFIG_VIA_VELOCITY is not set
+CONFIG_TIGON3=y
+
+#
+# Ethernet (10000 Mbit)
+#
+# CONFIG_IXGB is not set
+# CONFIG_S2IO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_NET_FC is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+# CONFIG_SERIO_PCIPS2 is not set
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+CONFIG_KEYBOARD_XTKBD=y
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+# CONFIG_VT_CONSOLE is not set
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_MPSC=y
+# CONFIG_SERIAL_MPSC_CONSOLE is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+CONFIG_WATCHDOG=y
+CONFIG_WATCHDOG_NOWAYOUT=y
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+CONFIG_MV64X60_WDT=y
+
+#
+# PCI-based Watchdog Cards
+#
+# CONFIG_PCIPCWATCHDOG is not set
+# CONFIG_WDTPCI is not set
+# CONFIG_NVRAM is not set
+CONFIG_GEN_RTC=y
+# CONFIG_GEN_RTC_X is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+
+#
+# XFS support
+#
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=y
+# CONFIG_JOLIET is not set
+# CONFIG_ZISOFS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVPTS_FS_XATTR is not set
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_XATTR is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+# CONFIG_JFFS2_FS_NAND is not set
+# CONFIG_JFFS2_FS_NOR_ECC is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Library routines
+#
+CONFIG_CRC_CCITT=y
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_SERIAL_TEXT_DEBUG is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Hardware crypto devices
+#
diff -Nru a/arch/ppc/kernel/cputable.c b/arch/ppc/kernel/cputable.c
--- a/arch/ppc/kernel/cputable.c	2005-03-11 12:51:46 -08:00
+++ b/arch/ppc/kernel/cputable.c	2005-03-11 12:51:46 -08:00
@@ -560,6 +560,18 @@
 		.dcache_bsize		= 32,
 		.cpu_setup		= __setup_cpu_603
 	},
+	{	/* e300 (a 603e core, plus some) on 83xx */
+		.pvr_mask		= 0x7fff0000,
+		.pvr_value		= 0x00830000,
+		.cpu_name		= "e300",
+		.cpu_features		= CPU_FTR_SPLIT_ID_CACHE |
+			CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB |
+			CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_HAS_HIGH_BATS,
+		.cpu_user_features	= COMMON_PPC,
+		.icache_bsize		= 32,
+		.dcache_bsize		= 32,
+		.cpu_setup		= __setup_cpu_603
+	},
 	{	/* default match, we assume split I/D cache & TB (non-601)... */
 		.pvr_mask		= 0x00000000,
 		.pvr_value		= 0x00000000,
diff -Nru a/arch/ppc/kernel/dma-mapping.c b/arch/ppc/kernel/dma-mapping.c
--- a/arch/ppc/kernel/dma-mapping.c	2005-03-11 12:51:40 -08:00
+++ b/arch/ppc/kernel/dma-mapping.c	2005-03-11 12:51:40 -08:00
@@ -219,7 +219,8 @@
 	c = vm_region_alloc(&consistent_head, size,
 			    gfp & ~(__GFP_DMA | __GFP_HIGHMEM));
 	if (c) {
-		pte_t *pte = consistent_pte + CONSISTENT_OFFSET(c->vm_start);
+		unsigned long vaddr = c->vm_start;
+		pte_t *pte = consistent_pte + CONSISTENT_OFFSET(vaddr);
 		struct page *end = page + (1 << order);
 
 		/*
@@ -232,9 +233,11 @@
 
 			set_page_count(page, 1);
 			SetPageReserved(page);
-			set_pte(pte, mk_pte(page, pgprot_noncached(PAGE_KERNEL)));
+			set_pte_at(&init_mm, vaddr,
+				   pte, mk_pte(page, pgprot_noncached(PAGE_KERNEL)));
 			page++;
 			pte++;
+			vaddr += PAGE_SIZE;
 		} while (size -= PAGE_SIZE);
 
 		/*
@@ -262,7 +265,7 @@
 void __dma_free_coherent(size_t size, void *vaddr)
 {
 	struct vm_region *c;
-	unsigned long flags;
+	unsigned long flags, addr;
 	pte_t *ptep;
 
 	size = PAGE_ALIGN(size);
@@ -281,11 +284,13 @@
 	}
 
 	ptep = consistent_pte + CONSISTENT_OFFSET(c->vm_start);
+	addr = c->vm_start;
 	do {
-		pte_t pte = ptep_get_and_clear(ptep);
+		pte_t pte = ptep_get_and_clear(&init_mm, addr, ptep);
 		unsigned long pfn;
 
 		ptep++;
+		addr += PAGE_SIZE;
 
 		if (!pte_none(pte) && pte_present(pte)) {
 			pfn = pte_pfn(pte);
diff -Nru a/arch/ppc/kernel/head_booke.h b/arch/ppc/kernel/head_booke.h
--- a/arch/ppc/kernel/head_booke.h	2005-03-11 12:51:41 -08:00
+++ b/arch/ppc/kernel/head_booke.h	2005-03-11 12:51:41 -08:00
@@ -194,8 +194,8 @@
 	CRITICAL_EXCEPTION_PROLOG;				\
 	addi	r3,r1,STACK_FRAME_OVERHEAD;			\
 	EXC_XFER_TEMPLATE(hdlr, n+2, (MSR_KERNEL & ~(MSR_ME|MSR_DE|MSR_CE)), \
-			  NOCOPY, transfer_to_handler_full, \
-			  ret_from_except_full)
+			  NOCOPY, crit_transfer_to_handler, \
+			  ret_from_crit_exc)
 
 #define MCHECK_EXCEPTION(n, label, hdlr)			\
 	START_EXCEPTION(label);					\
diff -Nru a/arch/ppc/kernel/misc.S b/arch/ppc/kernel/misc.S
--- a/arch/ppc/kernel/misc.S	2005-03-11 12:51:51 -08:00
+++ b/arch/ppc/kernel/misc.S	2005-03-11 12:51:51 -08:00
@@ -1450,3 +1450,4 @@
 	.long sys_add_key
 	.long sys_request_key		/* 270 */
 	.long sys_keyctl
+	.long sys_waitid
diff -Nru a/arch/ppc/kernel/pci.c b/arch/ppc/kernel/pci.c
--- a/arch/ppc/kernel/pci.c	2005-03-11 12:51:46 -08:00
+++ b/arch/ppc/kernel/pci.c	2005-03-11 12:51:46 -08:00
@@ -1058,7 +1058,7 @@
 		return;
  	res = *(bus->resource[0]);
 
-	DBG("Remapping Bus %d, bridge: %s\n", bus->number, bridge->slot_name);
+	DBG("Remapping Bus %d, bridge: %s\n", bus->number, pci_name(bridge));
 	res.start -= ((unsigned long) hose->io_base_virt - isa_io_base);
 	res.end -= ((unsigned long) hose->io_base_virt - isa_io_base);
 	DBG("  IO window: %08lx-%08lx\n", res.start, res.end);
diff -Nru a/arch/ppc/kernel/ppc_htab.c b/arch/ppc/kernel/ppc_htab.c
--- a/arch/ppc/kernel/ppc_htab.c	2005-03-11 12:51:52 -08:00
+++ b/arch/ppc/kernel/ppc_htab.c	2005-03-11 12:51:52 -08:00
@@ -108,7 +108,7 @@
 	PTE *ptr;
 #endif /* CONFIG_PPC_STD_MMU */
 
-	if (cur_cpu_spec[0]->cpu_features & CPU_FTR_604_PERF_MON) {
+	if (cpu_has_feature(CPU_FTR_604_PERF_MON)) {
 		mmcr0 = mfspr(SPRN_MMCR0);
 		pmc1 = mfspr(SPRN_PMC1);
 		pmc2 = mfspr(SPRN_PMC2);
@@ -209,7 +209,7 @@
 
 	if ( !strncmp( buffer, "reset", 5) )
 	{
-		if (cur_cpu_spec[0]->cpu_features & CPU_FTR_604_PERF_MON) {
+		if (cpu_has_feature(CPU_FTR_604_PERF_MON)) {
 			/* reset PMC1 and PMC2 */
 			mtspr(SPRN_PMC1, 0);
 			mtspr(SPRN_PMC2, 0);
@@ -221,7 +221,7 @@
 	}
 
 	/* Everything below here requires the performance monitor feature. */
-	if ( !cur_cpu_spec[0]->cpu_features & CPU_FTR_604_PERF_MON )
+	if (!cpu_has_feature(CPU_FTR_604_PERF_MON))
 		return count;
 
 	/* turn off performance monitoring */
@@ -339,7 +339,7 @@
 		"0.5", "1.0", "(reserved2)", "(reserved3)"
 	};
 
-	if (!(cur_cpu_spec[0]->cpu_features & CPU_FTR_L2CR))
+	if (!cpu_has_feature(CPU_FTR_L2CR))
 		return -EFAULT;
 
 	if ( /*!table->maxlen ||*/ (*ppos && !write)) {
diff -Nru a/arch/ppc/kernel/ppc_ksyms.c b/arch/ppc/kernel/ppc_ksyms.c
--- a/arch/ppc/kernel/ppc_ksyms.c	2005-03-11 12:51:51 -08:00
+++ b/arch/ppc/kernel/ppc_ksyms.c	2005-03-11 12:51:51 -08:00
@@ -319,7 +319,8 @@
 EXPORT_SYMBOL(cpm_install_handler);
 EXPORT_SYMBOL(cpm_free_handler);
 #endif /* CONFIG_8xx */
-#if defined(CONFIG_8xx) || defined(CONFIG_40x) || defined(CONFIG_85xx)
+#if defined(CONFIG_8xx) || defined(CONFIG_40x) || defined(CONFIG_85xx) ||\
+	defined(CONFIG_83xx)
 EXPORT_SYMBOL(__res);
 #endif
 
diff -Nru a/arch/ppc/kernel/setup.c b/arch/ppc/kernel/setup.c
--- a/arch/ppc/kernel/setup.c	2005-03-11 12:51:51 -08:00
+++ b/arch/ppc/kernel/setup.c	2005-03-11 12:51:51 -08:00
@@ -227,6 +227,10 @@
 		maj = ((pvr >> 8) & 0xFF) - 1;
 		min = pvr & 0xFF;
 		break;
+	case 0x8083:	/* e300 */
+		maj = PVR_MAJ(pvr);
+		min = PVR_MIN(pvr);
+		break;
 	case 0x8020:	/* e500 */
 		maj = PVR_MAJ(pvr);
 		min = PVR_MIN(pvr);
@@ -619,7 +623,7 @@
 /* Checks "l2cr=xxxx" command-line option */
 int __init ppc_setup_l2cr(char *str)
 {
-	if (cur_cpu_spec[0]->cpu_features & CPU_FTR_L2CR) {
+	if (cpu_has_feature(CPU_FTR_L2CR)) {
 		unsigned long val = simple_strtoul(str, NULL, 0);
 		printk(KERN_INFO "l2cr set to %lx\n", val);
 		_set_L2CR(0);		/* force invalidate by disable cache */
@@ -720,7 +724,7 @@
 	 * Systems with OF can look in the properties on the cpu node(s)
 	 * for a possibly more accurate value.
 	 */
-	if (cur_cpu_spec[0]->cpu_features & CPU_FTR_SPLIT_ID_CACHE) {
+	if (cpu_has_feature(CPU_FTR_SPLIT_ID_CACHE)) {
 		dcache_bsize = cur_cpu_spec[0]->dcache_bsize;
 		icache_bsize = cur_cpu_spec[0]->icache_bsize;
 		ucache_bsize = 0;
diff -Nru a/arch/ppc/kernel/temp.c b/arch/ppc/kernel/temp.c
--- a/arch/ppc/kernel/temp.c	2005-03-11 12:51:46 -08:00
+++ b/arch/ppc/kernel/temp.c	2005-03-11 12:51:46 -08:00
@@ -223,7 +223,7 @@
 	/* We assume in SMP that if one CPU has TAU support, they
 	 * all have it --BenH
 	 */
-	if (!(cur_cpu_spec[0]->cpu_features & CPU_FTR_TAU)) {
+	if (!cpu_has_feature(CPU_FTR_TAU)) {
 		printk("Thermal assist unit not available\n");
 		tau_initialized = 0;
 		return 1;
diff -Nru a/arch/ppc/mm/init.c b/arch/ppc/mm/init.c
--- a/arch/ppc/mm/init.c	2005-03-11 12:51:41 -08:00
+++ b/arch/ppc/mm/init.c	2005-03-11 12:51:41 -08:00
@@ -490,18 +490,6 @@
 		printk(KERN_INFO "AGP special page: 0x%08lx\n", agp_special_page);
 #endif
 
-	/* Make sure all our pagetable pages have page->mapping
-	   and page->index set correctly. */
-	for (addr = KERNELBASE; addr != 0; addr += PGDIR_SIZE) {
-		struct page *pg;
-		pmd_t *pmd = pmd_offset(pgd_offset_k(addr), addr);
-		if (pmd_present(*pmd)) {
-			pg = pmd_page(*pmd);
-			pg->mapping = (void *) &init_mm;
-			pg->index = addr;
-		}
-	}
-
 	mem_init_done = 1;
 }
 
diff -Nru a/arch/ppc/mm/mmu_decl.h b/arch/ppc/mm/mmu_decl.h
--- a/arch/ppc/mm/mmu_decl.h	2005-03-11 12:51:46 -08:00
+++ b/arch/ppc/mm/mmu_decl.h	2005-03-11 12:51:46 -08:00
@@ -75,7 +75,7 @@
 			      unsigned long pdval)
 {
 	if ((Hash != 0) &&
-	    (cur_cpu_spec[0]->cpu_features & CPU_FTR_HPTE_TABLE))
+	    cpu_has_feature(CPU_FTR_HPTE_TABLE))
 		flush_hash_pages(0, va, pdval, 1);
 	else
 		_tlbie(va);
diff -Nru a/arch/ppc/mm/pgtable.c b/arch/ppc/mm/pgtable.c
--- a/arch/ppc/mm/pgtable.c	2005-03-11 12:51:41 -08:00
+++ b/arch/ppc/mm/pgtable.c	2005-03-11 12:51:41 -08:00
@@ -102,11 +102,6 @@
 
 	if (mem_init_done) {
 		pte = (pte_t *)__get_free_page(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO);
-		if (pte) {
-			struct page *ptepage = virt_to_page(pte);
-			ptepage->mapping = (void *) mm;
-			ptepage->index = address & PMD_MASK;
-		}
 	} else {
 		pte = (pte_t *)early_get_page();
 		if (pte)
@@ -126,11 +121,8 @@
 #endif
 
 	ptepage = alloc_pages(flags, 0);
-	if (ptepage) {
-		ptepage->mapping = (void *) mm;
-		ptepage->index = address & PMD_MASK;
+	if (ptepage)
 		clear_highpage(ptepage);
-	}
 	return ptepage;
 }
 
@@ -139,7 +131,6 @@
 #ifdef CONFIG_SMP
 	hash_page_sync();
 #endif
-	virt_to_page(pte)->mapping = NULL;
 	free_page((unsigned long)pte);
 }
 
@@ -148,7 +139,6 @@
 #ifdef CONFIG_SMP
 	hash_page_sync();
 #endif
-	ptepage->mapping = NULL;
 	__free_page(ptepage);
 }
 
@@ -298,7 +288,7 @@
 	pg = pte_alloc_kernel(&init_mm, pd, va);
 	if (pg != 0) {
 		err = 0;
-		set_pte(pg, pfn_pte(pa >> PAGE_SHIFT, __pgprot(flags)));
+		set_pte_at(&init_mm, va, pg, pfn_pte(pa >> PAGE_SHIFT, __pgprot(flags)));
 		if (mem_init_done)
 			flush_HPTE(0, va, pmd_val(*pd));
 	}
diff -Nru a/arch/ppc/mm/ppc_mmu.c b/arch/ppc/mm/ppc_mmu.c
--- a/arch/ppc/mm/ppc_mmu.c	2005-03-11 12:51:41 -08:00
+++ b/arch/ppc/mm/ppc_mmu.c	2005-03-11 12:51:41 -08:00
@@ -138,7 +138,7 @@
 	union ubat *bat = BATS[index];
 
 	if (((flags & _PAGE_NO_CACHE) == 0) &&
-	    (cur_cpu_spec[0]->cpu_features & CPU_FTR_NEED_COHERENT))
+	    cpu_has_feature(CPU_FTR_NEED_COHERENT))
 		flags |= _PAGE_COHERENT;
 
 	bl = (size >> 17) - 1;
@@ -191,7 +191,7 @@
 	extern unsigned int hash_page[];
 	extern unsigned int flush_hash_patch_A[], flush_hash_patch_B[];
 
-	if ((cur_cpu_spec[0]->cpu_features & CPU_FTR_HPTE_TABLE) == 0) {
+	if (!cpu_has_feature(CPU_FTR_HPTE_TABLE)) {
 		/*
 		 * Put a blr (procedure return) instruction at the
 		 * start of hash_page, since we can still get DSI
diff -Nru a/arch/ppc/mm/tlb.c b/arch/ppc/mm/tlb.c
--- a/arch/ppc/mm/tlb.c	2005-03-11 12:51:52 -08:00
+++ b/arch/ppc/mm/tlb.c	2005-03-11 12:51:52 -08:00
@@ -47,26 +47,6 @@
 }
 
 /*
- * Called by ptep_test_and_clear_young()
- */
-void flush_hash_one_pte(pte_t *ptep)
-{
-	struct page *ptepage;
-	struct mm_struct *mm;
-	unsigned long ptephys;
-	unsigned long addr;
-
-	if (Hash == 0)
-		return;
-	
-	ptepage = virt_to_page(ptep);
-	mm = (struct mm_struct *) ptepage->mapping;
-	ptephys = __pa(ptep) & PAGE_MASK;
-	addr = ptepage->index + (((unsigned long)ptep & ~PAGE_MASK) << 10);
-	flush_hash_pages(mm->context, addr, ptephys, 1);
-}
-
-/*
  * Called by ptep_set_access_flags, must flush on CPUs for which the
  * DSI handler can't just "fixup" the TLB on a write fault
  */
diff -Nru a/arch/ppc/oprofile/op_model_fsl_booke.c b/arch/ppc/oprofile/op_model_fsl_booke.c
--- a/arch/ppc/oprofile/op_model_fsl_booke.c	2005-03-11 12:51:52 -08:00
+++ b/arch/ppc/oprofile/op_model_fsl_booke.c	2005-03-11 12:51:52 -08:00
@@ -150,7 +150,6 @@
 	int is_kernel;
 	int val;
 	int i;
-	unsigned int cpu = smp_processor_id();
 
 	/* set the PMM bit (see comment below) */
 	mtmsr(mfmsr() | MSR_PMM);
@@ -162,7 +161,7 @@
 		val = ctr_read(i);
 		if (val < 0) {
 			if (oprofile_running && ctr[i].enabled) {
-				oprofile_add_sample(pc, is_kernel, i, cpu);
+				oprofile_add_pc(pc, is_kernel, i);
 				ctr_write(i, reset_value[i]);
 			} else {
 				ctr_write(i, 0);
diff -Nru a/arch/ppc/platforms/4xx/ebony.c b/arch/ppc/platforms/4xx/ebony.c
--- a/arch/ppc/platforms/4xx/ebony.c	2005-03-11 12:51:52 -08:00
+++ b/arch/ppc/platforms/4xx/ebony.c	2005-03-11 12:51:52 -08:00
@@ -49,8 +49,19 @@
 #include <asm/todc.h>
 #include <asm/bootinfo.h>
 #include <asm/ppc4xx_pic.h>
+#include <asm/ppcboot.h>
 
 #include <syslib/gen550.h>
+#include <syslib/ibm440gp_common.h>
+
+/*
+ * This is a horrible kludge, we eventually need to abstract this
+ * generic PHY stuff, so the  standard phy mode defines can be
+ * easily used from arch code.
+ */
+#include "../../../../drivers/net/ibm_emac/ibm_emac_phy.h"
+
+bd_t __res;
 
 static struct ibm44x_clocks clocks __initdata;
 
@@ -258,19 +269,21 @@
 static void __init
 ebony_setup_arch(void)
 {
-	unsigned char * vpd_base;
 	struct ocp_def *def;
 	struct ocp_func_emac_data *emacdata;
 
 	/* Set mac_addr for each EMAC */
-	vpd_base = ioremap64(EBONY_VPD_BASE, EBONY_VPD_SIZE);
 	def = ocp_get_one_device(OCP_VENDOR_IBM, OCP_FUNC_EMAC, 0);
 	emacdata = def->additions;
-	memcpy(emacdata->mac_addr, EBONY_NA0_ADDR(vpd_base), 6);
+	emacdata->phy_map = 0x00000001;	/* Skip 0x00 */
+	emacdata->phy_mode = PHY_MODE_RMII;
+	memcpy(emacdata->mac_addr, __res.bi_enetaddr, 6);
+
 	def = ocp_get_one_device(OCP_VENDOR_IBM, OCP_FUNC_EMAC, 1);
 	emacdata = def->additions;
-	memcpy(emacdata->mac_addr, EBONY_NA1_ADDR(vpd_base), 6);
-	iounmap(vpd_base);
+	emacdata->phy_map = 0x00000001;	/* Skip 0x00 */
+	emacdata->phy_mode = PHY_MODE_RMII;
+	memcpy(emacdata->mac_addr, __res.bi_enet1addr, 6);
 
 	/*
 	 * Determine various clocks.
@@ -314,7 +327,14 @@
 void __init platform_init(unsigned long r3, unsigned long r4,
 		unsigned long r5, unsigned long r6, unsigned long r7)
 {
-	parse_bootinfo((struct bi_record *) (r3 + KERNELBASE));
+	parse_bootinfo(find_bootinfo());
+
+	/*
+	 * If we were passed in a board information, copy it into the
+	 * residual data area.
+	 */
+	if (r3)
+		__res = *(bd_t *)(r3 + KERNELBASE);
 
 	ibm44x_platform_init();
 
diff -Nru a/arch/ppc/platforms/4xx/ebony.h b/arch/ppc/platforms/4xx/ebony.h
--- a/arch/ppc/platforms/4xx/ebony.h	2005-03-11 12:51:50 -08:00
+++ b/arch/ppc/platforms/4xx/ebony.h	2005-03-11 12:51:50 -08:00
@@ -23,13 +23,9 @@
 /* F/W TLB mapping used in bootloader glue to reset EMAC */
 #define PPC44x_EMAC0_MR0	0xE0000800
 
-/* Macros to get at Ebony VPD info */
-#define EBONY_VPD_BASE		0x00000001fffffe00ULL
-#define EBONY_VPD_SIZE		0x24
-#define EBONY_NA0_OFFSET	0x0c
-#define EBONY_NA1_OFFSET	0x18
-#define EBONY_NA0_ADDR(base)	(base + EBONY_NA0_OFFSET)
-#define EBONY_NA1_ADDR(base)	(base + EBONY_NA1_OFFSET)
+/* Where to find the MAC info */
+#define EBONY_OPENBIOS_MAC_BASE   0xfffffe0c
+#define EBONY_OPENBIOS_MAC_OFFSET 0x0c
 
 /* Default clock rates for Rev. B and Rev. C silicon */
 #define EBONY_440GP_RB_SYSCLK	33000000
@@ -61,8 +57,8 @@
  */
 
 /* OpenBIOS defined UART mappings, used before early_serial_setup */
-#define UART0_IO_BASE	(u8 *) 0xE0000200
-#define UART1_IO_BASE	(u8 *) 0xE0000300
+#define UART0_IO_BASE	0xE0000200
+#define UART1_IO_BASE	0xE0000300
 
 /* external Epson SG-615P */
 #define BASE_BAUD	691200
diff -Nru a/arch/ppc/platforms/4xx/luan.h b/arch/ppc/platforms/4xx/luan.h
--- a/arch/ppc/platforms/4xx/luan.h	2005-03-11 12:51:47 -08:00
+++ b/arch/ppc/platforms/4xx/luan.h	2005-03-11 12:51:47 -08:00
@@ -47,9 +47,9 @@
 #define RS_TABLE_SIZE	3
 
 /* PIBS defined UART mappings, used before early_serial_setup */
-#define UART0_IO_BASE	(u8 *) 0xa0000200
-#define UART1_IO_BASE	(u8 *) 0xa0000300
-#define UART2_IO_BASE	(u8 *) 0xa0000600
+#define UART0_IO_BASE	0xa0000200
+#define UART1_IO_BASE	0xa0000300
+#define UART2_IO_BASE	0xa0000600
 
 #define BASE_BAUD	11059200
 #define STD_UART_OP(num)					\
diff -Nru a/arch/ppc/platforms/4xx/ocotea.h b/arch/ppc/platforms/4xx/ocotea.h
--- a/arch/ppc/platforms/4xx/ocotea.h	2005-03-11 12:51:46 -08:00
+++ b/arch/ppc/platforms/4xx/ocotea.h	2005-03-11 12:51:46 -08:00
@@ -56,8 +56,8 @@
 #define RS_TABLE_SIZE	2
 
 /* OpenBIOS defined UART mappings, used before early_serial_setup */
-#define UART0_IO_BASE	(u8 *) 0xE0000200
-#define UART1_IO_BASE	(u8 *) 0xE0000300
+#define UART0_IO_BASE	0xE0000200
+#define UART1_IO_BASE	0xE0000300
 
 #define BASE_BAUD	11059200/16
 #define STD_UART_OP(num)					\
diff -Nru a/arch/ppc/platforms/4xx/xilinx_ml300.c b/arch/ppc/platforms/4xx/xilinx_ml300.c
--- a/arch/ppc/platforms/4xx/xilinx_ml300.c	2005-03-11 12:51:41 -08:00
+++ b/arch/ppc/platforms/4xx/xilinx_ml300.c	2005-03-11 12:51:41 -08:00
@@ -122,25 +122,7 @@
 void __init
 ml300_init_irq(void)
 {
-	unsigned int i;
-
 	ppc4xx_init_IRQ();
-
-	/*
-	 * For PowerPC 405 cores the default value for NR_IRQS is 32.
-	 * See include/asm-ppc/irq.h for details.
-	 * This is just fine for ML300.
-	 */
-#if (NR_IRQS != 32)
-#error NR_IRQS must be 32 for ML300
-#endif
-
-	for (i = 0; i < NR_IRQS; i++) {
-		if (XPAR_INTC_0_KIND_OF_INTR & (0x80000000 >> i))
-			irq_desc[i].status &= ~IRQ_LEVEL;
-		else
-			irq_desc[i].status |= IRQ_LEVEL;
-	}
 }
 
 void __init
diff -Nru a/arch/ppc/platforms/83xx/Makefile b/arch/ppc/platforms/83xx/Makefile
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/ppc/platforms/83xx/Makefile	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,6 @@
+#
+# Makefile for the PowerPC 83xx linux kernel.
+#
+obj-$(CONFIG_83xx)		+= mpc83xx_sys.o mpc83xx_devices.o
+
+obj-$(CONFIG_MPC834x_SYS)	+= mpc834x_sys.o
diff -Nru a/arch/ppc/platforms/83xx/mpc834x_sys.c b/arch/ppc/platforms/83xx/mpc834x_sys.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/ppc/platforms/83xx/mpc834x_sys.c	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,290 @@
+/*
+ * arch/ppc/platforms/83xx/mpc834x_sys.c
+ *
+ * MPC834x SYS board specific routines
+ *
+ * Maintainer: Kumar Gala <kumar.gala@freescale.com>
+ *
+ * Copyright 2005 Freescale Semiconductor Inc.
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/config.h>
+#include <linux/stddef.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/reboot.h>
+#include <linux/pci.h>
+#include <linux/kdev_t.h>
+#include <linux/major.h>
+#include <linux/console.h>
+#include <linux/delay.h>
+#include <linux/irq.h>
+#include <linux/seq_file.h>
+#include <linux/root_dev.h>
+#include <linux/serial.h>
+#include <linux/tty.h>	/* for linux/serial_core.h */
+#include <linux/serial_core.h>
+#include <linux/initrd.h>
+#include <linux/module.h>
+#include <linux/fsl_devices.h>
+
+#include <asm/system.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/atomic.h>
+#include <asm/time.h>
+#include <asm/io.h>
+#include <asm/machdep.h>
+#include <asm/prom.h>
+#include <asm/ipic.h>
+#include <asm/bootinfo.h>
+#include <asm/pci-bridge.h>
+#include <asm/mpc83xx.h>
+#include <asm/irq.h>
+#include <asm/kgdb.h>
+#include <asm/ppc_sys.h>
+#include <mm/mmu_decl.h>
+
+#include <syslib/ppc83xx_setup.h>
+
+#ifndef CONFIG_PCI
+unsigned long isa_io_base = 0;
+unsigned long isa_mem_base = 0;
+#endif
+
+extern unsigned long total_memory;	/* in mm/init */
+
+unsigned char __res[sizeof (bd_t)];
+
+#ifdef CONFIG_PCI
+#error "PCI is not supported"
+/* NEED mpc83xx_map_irq & mpc83xx_exclude_device
+   see platforms/85xx/mpc85xx_ads_common.c */
+#endif /* CONFIG_PCI */
+
+/* ************************************************************************
+ *
+ * Setup the architecture
+ *
+ */
+static void __init
+mpc834x_sys_setup_arch(void)
+{
+	bd_t *binfo = (bd_t *) __res;
+	unsigned int freq;
+	struct gianfar_platform_data *pdata;
+
+	/* get the core frequency */
+	freq = binfo->bi_intfreq;
+
+	/* Set loops_per_jiffy to a half-way reasonable value,
+	   for use until calibrate_delay gets called. */
+	loops_per_jiffy = freq / HZ;
+
+#ifdef CONFIG_PCI
+	/* setup PCI host bridges */
+	mpc83xx_sys_setup_hose();
+#endif
+	mpc83xx_early_serial_map();
+
+	/* setup the board related information for the enet controllers */
+	pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC83xx_TSEC1);
+	pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR;
+	pdata->interruptPHY = MPC83xx_IRQ_EXT1;
+	pdata->phyid = 0;
+	/* fixup phy address */
+	pdata->phy_reg_addr += binfo->bi_immr_base;
+	memcpy(pdata->mac_addr, binfo->bi_enetaddr, 6);
+
+	pdata = (struct gianfar_platform_data *) ppc_sys_get_pdata(MPC83xx_TSEC2);
+	pdata->board_flags = FSL_GIANFAR_BRD_HAS_PHY_INTR;
+	pdata->interruptPHY = MPC83xx_IRQ_EXT2;
+	pdata->phyid = 1;
+	/* fixup phy address */
+	pdata->phy_reg_addr += binfo->bi_immr_base;
+	memcpy(pdata->mac_addr, binfo->bi_enet1addr, 6);
+
+#ifdef CONFIG_BLK_DEV_INITRD
+	if (initrd_start)
+		ROOT_DEV = Root_RAM0;
+	else
+#endif
+#ifdef  CONFIG_ROOT_NFS
+		ROOT_DEV = Root_NFS;
+#else
+		ROOT_DEV = Root_HDA1;
+#endif
+}
+
+static void __init
+mpc834x_sys_map_io(void)
+{
+	/* we steal the lowest ioremap addr for virt space */
+	io_block_mapping(VIRT_IMMRBAR, immrbar, 1024*1024, _PAGE_IO);
+	io_block_mapping(BCSR_VIRT_ADDR, BCSR_PHYS_ADDR, BCSR_SIZE, _PAGE_IO);
+}
+
+int
+mpc834x_sys_show_cpuinfo(struct seq_file *m)
+{
+	uint pvid, svid, phid1;
+	bd_t *binfo = (bd_t *) __res;
+	unsigned int freq;
+
+	/* get the core frequency */
+	freq = binfo->bi_intfreq;
+
+	pvid = mfspr(PVR);
+	svid = mfspr(SVR);
+
+	seq_printf(m, "chip\t\t: MPC%s\n", cur_ppc_sys_spec->ppc_sys_name);
+	seq_printf(m, "Vendor\t\t: Freescale Inc.\n");
+	seq_printf(m, "Machine\t\t: mpc%s sys\n", cur_ppc_sys_spec->ppc_sys_name);
+	seq_printf(m, "core clock\t: %d MHz\n"
+			"bus  clock\t: %d MHz\n",
+			(int)(binfo->bi_intfreq / 1000000),
+			(int)(binfo->bi_busfreq / 1000000));
+	seq_printf(m, "PVR\t\t: 0x%x\n", pvid);
+	seq_printf(m, "SVR\t\t: 0x%x\n", svid);
+
+	/* Display cpu Pll setting */
+	phid1 = mfspr(HID1);
+	seq_printf(m, "PLL setting\t: 0x%x\n", ((phid1 >> 24) & 0x3f));
+
+	/* Display the amount of memory */
+	seq_printf(m, "Memory\t\t: %d MB\n", (int)(binfo->bi_memsize / (1024 * 1024)));
+
+	return 0;
+}
+
+
+void __init
+mpc834x_sys_init_IRQ(void)
+{
+	bd_t *binfo = (bd_t *) __res;
+
+	u8 senses[8] = {
+		0,			/* EXT 0 */
+		IRQ_SENSE_LEVEL,	/* EXT 1 */
+		IRQ_SENSE_LEVEL,	/* EXT 2 */
+		0,			/* EXT 3 */
+		0,			/* EXT 4 */
+		0,			/* EXT 5 */
+		0,			/* EXT 6 */
+		0,			/* EXT 7 */
+	};
+
+	ipic_init(binfo->bi_immr_base + 0x00700, 0, MPC83xx_IPIC_IRQ_OFFSET, senses, 8);
+
+	/* Initialize the default interrupt mapping priorities,
+	 * in case the boot rom changed something on us.
+	 */
+	ipic_set_default_priority();
+}
+
+static __inline__ void
+mpc834x_sys_set_bat(void)
+{
+	/* we steal the lowest ioremap addr for virt space */
+	mb();
+	mtspr(DBAT1U, VIRT_IMMRBAR | 0x1e);
+	mtspr(DBAT1L, immrbar | 0x2a);
+	mb();
+}
+
+void __init
+platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
+	      unsigned long r6, unsigned long r7)
+{
+	bd_t *binfo = (bd_t *) __res;
+
+	/* parse_bootinfo must always be called first */
+	parse_bootinfo(find_bootinfo());
+
+	/*
+	 * If we were passed in a board information, copy it into the
+	 * residual data area.
+	 */
+	if (r3) {
+		memcpy((void *) __res, (void *) (r3 + KERNELBASE),
+		       sizeof (bd_t));
+	}
+
+#if defined(CONFIG_BLK_DEV_INITRD)
+	/*
+	 * If the init RAM disk has been configured in, and there's a valid
+	 * starting address for it, set it up.
+	 */
+	if (r4) {
+		initrd_start = r4 + KERNELBASE;
+		initrd_end = r5 + KERNELBASE;
+	}
+#endif /* CONFIG_BLK_DEV_INITRD */
+
+	/* Copy the kernel command line arguments to a safe place. */
+	if (r6) {
+		*(char *) (r7 + KERNELBASE) = 0;
+		strcpy(cmd_line, (char *) (r6 + KERNELBASE));
+	}
+
+	immrbar = binfo->bi_immr_base;
+
+	mpc834x_sys_set_bat();
+
+#if defined(CONFIG_SERIAL_8250) && defined(CONFIG_SERIAL_TEXT_DEBUG)
+	{
+		struct uart_port p;
+
+		memset(&p, 0, sizeof (p));
+		p.iotype = SERIAL_IO_MEM;
+		p.membase = (unsigned char __iomem *)immrbar + 0x4500;
+		p.uartclk = binfo->bi_busfreq;
+
+		gen550_init(0, &p);
+
+		memset(&p, 0, sizeof (p));
+		p.iotype = SERIAL_IO_MEM;
+		p.membase = (unsigned char __iomem *)immrbar + 0x4500;
+		p.uartclk = binfo->bi_busfreq;
+
+		gen550_init(1, &p);
+	}
+#endif
+
+	identify_ppc_sys_by_id(mfspr(SVR));
+
+	/* setup the PowerPC module struct */
+	ppc_md.setup_arch = mpc834x_sys_setup_arch;
+	ppc_md.show_cpuinfo = mpc834x_sys_show_cpuinfo;
+
+	ppc_md.init_IRQ = mpc834x_sys_init_IRQ;
+	ppc_md.get_irq = ipic_get_irq;
+
+	ppc_md.restart = mpc83xx_restart;
+	ppc_md.power_off = mpc83xx_power_off;
+	ppc_md.halt = mpc83xx_halt;
+
+	ppc_md.find_end_of_memory = mpc83xx_find_end_of_memory;
+	ppc_md.setup_io_mappings  = mpc834x_sys_map_io;
+
+	ppc_md.time_init = mpc83xx_time_init;
+	ppc_md.set_rtc_time = NULL;
+	ppc_md.get_rtc_time = NULL;
+	ppc_md.calibrate_decr = mpc83xx_calibrate_decr;
+
+	ppc_md.early_serial_map = mpc83xx_early_serial_map;
+#if defined(CONFIG_SERIAL_8250) && defined(CONFIG_SERIAL_TEXT_DEBUG)
+	ppc_md.progress = gen550_progress;
+#endif	/* CONFIG_SERIAL_8250 && CONFIG_SERIAL_TEXT_DEBUG */
+
+	if (ppc_md.progress)
+		ppc_md.progress("mpc834x_sys_init(): exit", 0);
+
+	return;
+}
diff -Nru a/arch/ppc/platforms/83xx/mpc834x_sys.h b/arch/ppc/platforms/83xx/mpc834x_sys.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/ppc/platforms/83xx/mpc834x_sys.h	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,51 @@
+/*
+ * arch/ppc/platforms/83xx/mpc834x_sys.h
+ *
+ * MPC834X SYS common board definitions
+ *
+ * Maintainer: Kumar Gala <kumar.gala@freescale.com>
+ *
+ * Copyright 2005 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ *
+ */
+
+#ifndef __MACH_MPC83XX_SYS_H__
+#define __MACH_MPC83XX_SYS_H__
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/seq_file.h>
+#include <syslib/ppc83xx_setup.h>
+#include <asm/ppcboot.h>
+
+#define VIRT_IMMRBAR		((uint)0xfe000000)
+
+#define BCSR_PHYS_ADDR		((uint)0xf8000000)
+#define BCSR_VIRT_ADDR		((uint)0xfe100000)
+#define BCSR_SIZE		((uint)(32 * 1024))
+
+#ifdef CONFIG_PCI
+/* PCI interrupt controller */
+#define PIRQA        MPC83xx_IRQ_IRQ4
+#define PIRQB        MPC83xx_IRQ_IRQ5
+#define PIRQC        MPC83xx_IRQ_IRQ6
+#define PIRQD        MPC83xx_IRQ_IRQ7
+
+#define MPC834x_SYS_PCI1_LOWER_IO        0x00000000
+#define MPC834x_SYS_PCI1_UPPER_IO        0x00ffffff
+
+#define MPC834x_SYS_PCI1_LOWER_MEM       0x80000000
+#define MPC834x_SYS_PCI1_UPPER_MEM       0x9fffffff
+
+#define MPC834x_SYS_PCI1_IO_BASE         0xe2000000
+#define MPC834x_SYS_PCI1_MEM_OFFSET      0x00000000
+
+#define MPC834x_SYS_PCI1_IO_SIZE         0x01000000
+#endif /* CONFIG_PCI */
+
+#endif                /* __MACH_MPC83XX_SYS_H__ */
diff -Nru a/arch/ppc/platforms/83xx/mpc83xx_devices.c b/arch/ppc/platforms/83xx/mpc83xx_devices.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/ppc/platforms/83xx/mpc83xx_devices.c	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,237 @@
+/*
+ * arch/ppc/platforms/83xx/mpc83xx_devices.c
+ *
+ * MPC83xx Device descriptions
+ *
+ * Maintainer: Kumar Gala <kumar.gala@freescale.com>
+ *
+ * Copyright 2005 Freescale Semiconductor Inc.
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/serial_8250.h>
+#include <linux/fsl_devices.h>
+#include <asm/mpc83xx.h>
+#include <asm/irq.h>
+#include <asm/ppc_sys.h>
+
+/* We use offsets for IORESOURCE_MEM since we do not know at compile time
+ * what IMMRBAR is, will get fixed up by mach_mpc83xx_fixup
+ */
+
+static struct gianfar_platform_data mpc83xx_tsec1_pdata = {
+	.device_flags = FSL_GIANFAR_DEV_HAS_GIGABIT |
+	    FSL_GIANFAR_DEV_HAS_COALESCE | FSL_GIANFAR_DEV_HAS_RMON |
+	    FSL_GIANFAR_DEV_HAS_MULTI_INTR,
+	.phy_reg_addr = 0x24000,
+};
+
+static struct gianfar_platform_data mpc83xx_tsec2_pdata = {
+	.device_flags = FSL_GIANFAR_DEV_HAS_GIGABIT |
+	    FSL_GIANFAR_DEV_HAS_COALESCE | FSL_GIANFAR_DEV_HAS_RMON |
+	    FSL_GIANFAR_DEV_HAS_MULTI_INTR,
+	.phy_reg_addr = 0x24000,
+};
+
+static struct fsl_i2c_platform_data mpc83xx_fsl_i2c1_pdata = {
+	.device_flags = FSL_I2C_DEV_SEPARATE_DFSRR,
+};
+
+static struct fsl_i2c_platform_data mpc83xx_fsl_i2c2_pdata = {
+	.device_flags = FSL_I2C_DEV_SEPARATE_DFSRR,
+};
+
+static struct plat_serial8250_port serial_platform_data[] = {
+	[0] = {
+		.mapbase	= 0x4500,
+		.irq		= MPC83xx_IRQ_UART1,
+		.iotype		= UPIO_MEM,
+		.flags		= UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
+	},
+	[1] = {
+		.mapbase	= 0x4600,
+		.irq		= MPC83xx_IRQ_UART2,
+		.iotype		= UPIO_MEM,
+		.flags		= UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
+	},
+};
+
+struct platform_device ppc_sys_platform_devices[] = {
+	[MPC83xx_TSEC1] = {
+		.name = "fsl-gianfar",
+		.id	= 1,
+		.dev.platform_data = &mpc83xx_tsec1_pdata,
+		.num_resources	 = 4,
+		.resource = (struct resource[]) {
+			{
+				.start	= 0x24000,
+				.end	= 0x24fff,
+				.flags	= IORESOURCE_MEM,
+			},
+			{
+				.name	= "tx",
+				.start	= MPC83xx_IRQ_TSEC1_TX,
+				.end	= MPC83xx_IRQ_TSEC1_TX,
+				.flags	= IORESOURCE_IRQ,
+			},
+			{
+				.name	= "rx",
+				.start	= MPC83xx_IRQ_TSEC1_RX,
+				.end	= MPC83xx_IRQ_TSEC1_RX,
+				.flags	= IORESOURCE_IRQ,
+			},
+			{
+				.name	= "error",
+				.start	= MPC83xx_IRQ_TSEC1_ERROR,
+				.end	= MPC83xx_IRQ_TSEC1_ERROR,
+				.flags	= IORESOURCE_IRQ,
+			},
+		},
+	},
+	[MPC83xx_TSEC2] = {
+		.name = "fsl-gianfar",
+		.id	= 2,
+		.dev.platform_data = &mpc83xx_tsec2_pdata,
+		.num_resources	 = 4,
+		.resource = (struct resource[]) {
+			{
+				.start	= 0x25000,
+				.end	= 0x25fff,
+				.flags	= IORESOURCE_MEM,
+			},
+			{
+				.name	= "tx",
+				.start	= MPC83xx_IRQ_TSEC2_TX,
+				.end	= MPC83xx_IRQ_TSEC2_TX,
+				.flags	= IORESOURCE_IRQ,
+			},
+			{
+				.name	= "rx",
+				.start	= MPC83xx_IRQ_TSEC2_RX,
+				.end	= MPC83xx_IRQ_TSEC2_RX,
+				.flags	= IORESOURCE_IRQ,
+			},
+			{
+				.name	= "error",
+				.start	= MPC83xx_IRQ_TSEC2_ERROR,
+				.end	= MPC83xx_IRQ_TSEC2_ERROR,
+				.flags	= IORESOURCE_IRQ,
+			},
+		},
+	},
+	[MPC83xx_IIC1] = {
+		.name = "fsl-i2c",
+		.id	= 1,
+		.dev.platform_data = &mpc83xx_fsl_i2c1_pdata,
+		.num_resources	 = 2,
+		.resource = (struct resource[]) {
+			{
+				.start	= 0x3000,
+				.end	= 0x30ff,
+				.flags	= IORESOURCE_MEM,
+			},
+			{
+				.start	= MPC83xx_IRQ_IIC1,
+				.end	= MPC83xx_IRQ_IIC1,
+				.flags	= IORESOURCE_IRQ,
+			},
+		},
+	},
+	[MPC83xx_IIC2] = {
+		.name = "fsl-i2c",
+		.id	= 2,
+		.dev.platform_data = &mpc83xx_fsl_i2c2_pdata,
+		.num_resources	 = 2,
+		.resource = (struct resource[]) {
+			{
+				.start	= 0x3100,
+				.end	= 0x31ff,
+				.flags	= IORESOURCE_MEM,
+			},
+			{
+				.start	= MPC83xx_IRQ_IIC2,
+				.end	= MPC83xx_IRQ_IIC2,
+				.flags	= IORESOURCE_IRQ,
+			},
+		},
+	},
+	[MPC83xx_DUART] = {
+		.name = "serial8250",
+		.id	= 0,
+		.dev.platform_data = serial_platform_data,
+	},
+	[MPC83xx_SEC2] = {
+		.name = "fsl-sec2",
+		.id	= 1,
+		.num_resources	 = 2,
+		.resource = (struct resource[]) {
+			{
+				.start	= 0x30000,
+				.end	= 0x3ffff,
+				.flags	= IORESOURCE_MEM,
+			},
+			{
+				.start	= MPC83xx_IRQ_SEC2,
+				.end	= MPC83xx_IRQ_SEC2,
+				.flags	= IORESOURCE_IRQ,
+			},
+		},
+	},
+	[MPC83xx_USB2_DR] = {
+		.name = "fsl-usb2-dr",
+		.id	= 1,
+		.num_resources	 = 2,
+		.resource = (struct resource[]) {
+			{
+				.start	= 0x22000,
+				.end	= 0x22fff,
+				.flags	= IORESOURCE_MEM,
+			},
+			{
+				.start	= MPC83xx_IRQ_USB2_DR,
+				.end	= MPC83xx_IRQ_USB2_DR,
+				.flags	= IORESOURCE_IRQ,
+			},
+		},
+	},
+	[MPC83xx_USB2_MPH] = {
+		.name = "fsl-usb2-mph",
+		.id	= 1,
+		.num_resources	 = 2,
+		.resource = (struct resource[]) {
+			{
+				.start	= 0x23000,
+				.end	= 0x23fff,
+				.flags	= IORESOURCE_MEM,
+			},
+			{
+				.start	= MPC83xx_IRQ_USB2_MPH,
+				.end	= MPC83xx_IRQ_USB2_MPH,
+				.flags	= IORESOURCE_IRQ,
+			},
+		},
+	},
+};
+
+static int __init mach_mpc83xx_fixup(struct platform_device *pdev)
+{
+	ppc_sys_fixup_mem_resource(pdev, immrbar);
+	return 0;
+}
+
+static int __init mach_mpc83xx_init(void)
+{
+	if (ppc_md.progress)
+		ppc_md.progress("mach_mpc83xx_init:enter", 0);
+	ppc_sys_device_fixup = mach_mpc83xx_fixup;
+	return 0;
+}
+
+postcore_initcall(mach_mpc83xx_init);
diff -Nru a/arch/ppc/platforms/83xx/mpc83xx_sys.c b/arch/ppc/platforms/83xx/mpc83xx_sys.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/ppc/platforms/83xx/mpc83xx_sys.c	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,100 @@
+/*
+ * arch/ppc/platforms/83xx/mpc83xx_sys.c
+ *
+ * MPC83xx System descriptions
+ *
+ * Maintainer: Kumar Gala <kumar.gala@freescale.com>
+ *
+ * Copyright 2005 Freescale Semiconductor Inc.
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <asm/ppc_sys.h>
+
+struct ppc_sys_spec *cur_ppc_sys_spec;
+struct ppc_sys_spec ppc_sys_specs[] = {
+	{
+		.ppc_sys_name	= "8349E",
+		.mask 		= 0xFFFF0000,
+		.value 		= 0x80500000,
+		.num_devices	= 8,
+		.device_list	= (enum ppc_sys_devices[])
+		{
+			MPC83xx_TSEC1, MPC83xx_TSEC2, MPC83xx_IIC1,
+			MPC83xx_IIC2, MPC83xx_DUART, MPC83xx_SEC2,
+			MPC83xx_USB2_DR, MPC83xx_USB2_MPH
+		},
+	},
+	{
+		.ppc_sys_name	= "8349",
+		.mask 		= 0xFFFF0000,
+		.value 		= 0x80510000,
+		.num_devices	= 7,
+		.device_list	= (enum ppc_sys_devices[])
+		{
+			MPC83xx_TSEC1, MPC83xx_TSEC2, MPC83xx_IIC1,
+			MPC83xx_IIC2, MPC83xx_DUART,
+			MPC83xx_USB2_DR, MPC83xx_USB2_MPH
+		},
+	},
+	{
+		.ppc_sys_name	= "8347E",
+		.mask 		= 0xFFFF0000,
+		.value 		= 0x80520000,
+		.num_devices	= 8,
+		.device_list	= (enum ppc_sys_devices[])
+		{
+			MPC83xx_TSEC1, MPC83xx_TSEC2, MPC83xx_IIC1,
+			MPC83xx_IIC2, MPC83xx_DUART, MPC83xx_SEC2,
+			MPC83xx_USB2_DR, MPC83xx_USB2_MPH
+		},
+	},
+	{
+		.ppc_sys_name	= "8347",
+		.mask 		= 0xFFFF0000,
+		.value 		= 0x80530000,
+		.num_devices	= 7,
+		.device_list	= (enum ppc_sys_devices[])
+		{
+			MPC83xx_TSEC1, MPC83xx_TSEC2, MPC83xx_IIC1,
+			MPC83xx_IIC2, MPC83xx_DUART,
+			MPC83xx_USB2_DR, MPC83xx_USB2_MPH
+		},
+	},
+	{
+		.ppc_sys_name	= "8343E",
+		.mask 		= 0xFFFF0000,
+		.value 		= 0x80540000,
+		.num_devices	= 7,
+		.device_list	= (enum ppc_sys_devices[])
+		{
+			MPC83xx_TSEC1, MPC83xx_TSEC2, MPC83xx_IIC1,
+			MPC83xx_IIC2, MPC83xx_DUART, MPC83xx_SEC2,
+			MPC83xx_USB2_DR,
+		},
+	},
+	{
+		.ppc_sys_name	= "8343",
+		.mask 		= 0xFFFF0000,
+		.value 		= 0x80550000,
+		.num_devices	= 6,
+		.device_list	= (enum ppc_sys_devices[])
+		{
+			MPC83xx_TSEC1, MPC83xx_TSEC2, MPC83xx_IIC1,
+			MPC83xx_IIC2, MPC83xx_DUART,
+			MPC83xx_USB2_DR,
+		},
+	},
+	{	/* default match */
+		.ppc_sys_name	= "",
+		.mask 		= 0x00000000,
+		.value 		= 0x00000000,
+	},
+};
diff -Nru a/arch/ppc/platforms/85xx/mpc85xx_ads_common.c b/arch/ppc/platforms/85xx/mpc85xx_ads_common.c
--- a/arch/ppc/platforms/85xx/mpc85xx_ads_common.c	2005-03-11 12:51:51 -08:00
+++ b/arch/ppc/platforms/85xx/mpc85xx_ads_common.c	2005-03-11 12:51:51 -08:00
@@ -43,6 +43,7 @@
 #include <asm/mpc85xx.h>
 #include <asm/irq.h>
 #include <asm/immap_85xx.h>
+#include <asm/ppc_sys.h>
 
 #include <mm/mmu_decl.h>
 
@@ -128,19 +129,9 @@
 	pvid = mfspr(PVR);
 	svid = mfspr(SVR);
 
+	seq_printf(m, "chip\t\t: MPC%s\n", cur_ppc_sys_spec->ppc_sys_name);
 	seq_printf(m, "Vendor\t\t: Freescale Semiconductor\n");
-
-	switch (svid & 0xffff0000) {
-	case SVR_8540:
-		seq_printf(m, "Machine\t\t: mpc8540ads\n");
-		break;
-	case SVR_8560:
-		seq_printf(m, "Machine\t\t: mpc8560ads\n");
-		break;
-	default:
-		seq_printf(m, "Machine\t\t: unknown\n");
-		break;
-	}
+	seq_printf(m, "Machine\t\t: mpc%sads\n", cur_ppc_sys_spec->ppc_sys_name);
 	seq_printf(m, "clock\t\t: %dMHz\n", freq / 1000000);
 	seq_printf(m, "PVR\t\t: 0x%x\n", pvid);
 	seq_printf(m, "SVR\t\t: 0x%x\n", svid);
diff -Nru a/arch/ppc/platforms/85xx/mpc85xx_cds_common.c b/arch/ppc/platforms/85xx/mpc85xx_cds_common.c
--- a/arch/ppc/platforms/85xx/mpc85xx_cds_common.c	2005-03-11 12:51:51 -08:00
+++ b/arch/ppc/platforms/85xx/mpc85xx_cds_common.c	2005-03-11 12:51:51 -08:00
@@ -39,6 +39,7 @@
 #include <asm/page.h>
 #include <asm/atomic.h>
 #include <asm/time.h>
+#include <asm/todc.h>
 #include <asm/io.h>
 #include <asm/machdep.h>
 #include <asm/prom.h>
@@ -73,60 +74,60 @@
 /* Internal interrupts are all Level Sensitive, and Positive Polarity */
 
 static u_char mpc85xx_cds_openpic_initsenses[] __initdata = {
-        (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),        /* Internal  0: L2 Cache */
-        (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),        /* Internal  1: ECM */
-        (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),        /* Internal  2: DDR DRAM */
-        (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),        /* Internal  3: LBIU */
-        (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),        /* Internal  4: DMA 0 */
-        (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),        /* Internal  5: DMA 1 */
-        (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),        /* Internal  6: DMA 2 */
-        (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),        /* Internal  7: DMA 3 */
-        (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),        /* Internal  8: PCI/PCI-X */
-        (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),        /* Internal  9: RIO Inbound Port Write Error */
-        (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),        /* Internal 10: RIO Doorbell Inbound */
-        (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),        /* Internal 11: RIO Outbound Message */
-        (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),        /* Internal 12: RIO Inbound Message */
-        (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),        /* Internal 13: TSEC 0 Transmit */
-        (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),        /* Internal 14: TSEC 0 Receive */
-        (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),        /* Internal 15: Unused */
-        (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),        /* Internal 16: Unused */
-        (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),        /* Internal 17: Unused */
-        (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),        /* Internal 18: TSEC 0 Receive/Transmit Error */
-        (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),        /* Internal 19: TSEC 1 Transmit */
-        (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),        /* Internal 20: TSEC 1 Receive */
-        (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),        /* Internal 21: Unused */
-        (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),        /* Internal 22: Unused */
-        (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),        /* Internal 23: Unused */
-        (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),        /* Internal 24: TSEC 1 Receive/Transmit Error */
-        (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),        /* Internal 25: Fast Ethernet */
-        (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),        /* Internal 26: DUART */
-        (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),        /* Internal 27: I2C */
-        (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),        /* Internal 28: Performance Monitor */
-        (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),        /* Internal 29: Unused */
-        (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),        /* Internal 30: CPM */
-        (IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),        /* Internal 31: Unused */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  0: L2 Cache */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  1: ECM */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  2: DDR DRAM */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  3: LBIU */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  4: DMA 0 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  5: DMA 1 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  6: DMA 2 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  7: DMA 3 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  8: PCI/PCI-X */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal  9: RIO Inbound Port Write Error */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 10: RIO Doorbell Inbound */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 11: RIO Outbound Message */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 12: RIO Inbound Message */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 13: TSEC 0 Transmit */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 14: TSEC 0 Receive */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 15: Unused */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 16: Unused */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 17: Unused */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 18: TSEC 0 Receive/Transmit Error */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 19: TSEC 1 Transmit */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 20: TSEC 1 Receive */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 21: Unused */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 22: Unused */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 23: Unused */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 24: TSEC 1 Receive/Transmit Error */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 25: Fast Ethernet */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 26: DUART */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 27: I2C */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 28: Performance Monitor */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 29: Unused */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 30: CPM */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE),	/* Internal 31: Unused */
 #if defined(CONFIG_PCI)
-        (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),      /* External 0: PCI1 slot */
-        (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),      /* External 1: PCI1 slot */
-        (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),      /* External 2: PCI1 slot */
-        (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),      /* External 3: PCI1 slot */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* External 0: PCI1 slot */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* External 1: PCI1 slot */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* External 2: PCI1 slot */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* External 3: PCI1 slot */
 #else
-        0x0,                            /* External  0: */
-        0x0,                            /* External  1: */
-        0x0,                            /* External  2: */
-        0x0,                            /* External  3: */
-#endif
-        0x0,                            /* External  4: */
-        (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),      /* External 5: PHY */
-        0x0,                            /* External  6: */
-        0x0,                            /* External  7: */
-        0x0,                            /* External  8: */
-        0x0,                            /* External  9: */
-        0x0,                            /* External 10: */
+	0x0,						/* External  0: */
+	0x0,						/* External  1: */
+	0x0,						/* External  2: */
+	0x0,						/* External  3: */
+#endif
+	0x0,						/* External  4: */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* External  5: PHY */
+	0x0,						/* External  6: */
+	0x0,						/* External  7: */
+	0x0,						/* External  8: */
+	0x0,						/* External  9: */
+	0x0,						/* External 10: */
 #if defined(CONFIG_85xx_PCI2) && defined(CONFIG_PCI)
-        (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),      /* External 11: PCI2 slot 0 */
+	(IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE),	/* External 11: PCI2 slot 0 */
 #else
-        0x0,                            /* External 11: */
+	0x0,						/* External 11: */
 #endif
 };
 
@@ -134,31 +135,32 @@
 int
 mpc85xx_cds_show_cpuinfo(struct seq_file *m)
 {
-        uint pvid, svid, phid1;
-        uint memsize = total_memory;
-        bd_t *binfo = (bd_t *) __res;
-        unsigned int freq;
+	uint pvid, svid, phid1;
+	uint memsize = total_memory;
+	bd_t *binfo = (bd_t *) __res;
+	unsigned int freq;
 
-        /* get the core frequency */
-        freq = binfo->bi_intfreq;
+	/* get the core frequency */
+	freq = binfo->bi_intfreq;
 
-        pvid = mfspr(PVR);
-        svid = mfspr(SVR);
+	pvid = mfspr(PVR);
+	svid = mfspr(SVR);
 
-        seq_printf(m, "Vendor\t\t: Freescale Semiconductor\n");
-	seq_printf(m, "Machine\t\t: CDS (%x)\n", cadmus[CM_VER]);
+	seq_printf(m, "chip\t\t: MPC%s\n", cur_ppc_sys_spec->ppc_sys_name);
+	seq_printf(m, "Vendor\t\t: Freescale Semiconductor\n");
+	seq_printf(m, "Machine\t\t: CDS - MPC%s (%x)\n", cur_ppc_sys_spec->ppc_sys_name, cadmus[CM_VER]);
 	seq_printf(m, "clock\t\t: %dMHz\n", freq / 1000000);
-        seq_printf(m, "PVR\t\t: 0x%x\n", pvid);
-        seq_printf(m, "SVR\t\t: 0x%x\n", svid);
+	seq_printf(m, "PVR\t\t: 0x%x\n", pvid);
+	seq_printf(m, "SVR\t\t: 0x%x\n", svid);
 
-        /* Display cpu Pll setting */
-        phid1 = mfspr(HID1);
-        seq_printf(m, "PLL setting\t: 0x%x\n", ((phid1 >> 24) & 0x3f));
+	/* Display cpu Pll setting */
+	phid1 = mfspr(HID1);
+	seq_printf(m, "PLL setting\t: 0x%x\n", ((phid1 >> 24) & 0x3f));
 
-        /* Display the amount of memory */
-        seq_printf(m, "Memory\t\t: %d MB\n", memsize / (1024 * 1024));
+	/* Display the amount of memory */
+	seq_printf(m, "Memory\t\t: %d MB\n", memsize / (1024 * 1024));
 
-        return 0;
+	return 0;
 }
 
 #ifdef CONFIG_CPM2
@@ -185,21 +187,21 @@
 	int i;
 #endif
 
-        /* Determine the Physical Address of the OpenPIC regs */
-        phys_addr_t OpenPIC_PAddr = binfo->bi_immr_base + MPC85xx_OPENPIC_OFFSET;
-        OpenPIC_Addr = ioremap(OpenPIC_PAddr, MPC85xx_OPENPIC_SIZE);
-        OpenPIC_InitSenses = mpc85xx_cds_openpic_initsenses;
-        OpenPIC_NumInitSenses = sizeof (mpc85xx_cds_openpic_initsenses);
-
-        /* Skip reserved space and internal sources */
-        openpic_set_sources(0, 32, OpenPIC_Addr + 0x10200);
-        /* Map PIC IRQs 0-11 */
-        openpic_set_sources(32, 12, OpenPIC_Addr + 0x10000);
-
-        /* we let openpic interrupts starting from an offset, to
-         * leave space for cascading interrupts underneath.
-         */
-        openpic_init(MPC85xx_OPENPIC_IRQ_OFFSET);
+	/* Determine the Physical Address of the OpenPIC regs */
+	phys_addr_t OpenPIC_PAddr = binfo->bi_immr_base + MPC85xx_OPENPIC_OFFSET;
+	OpenPIC_Addr = ioremap(OpenPIC_PAddr, MPC85xx_OPENPIC_SIZE);
+	OpenPIC_InitSenses = mpc85xx_cds_openpic_initsenses;
+	OpenPIC_NumInitSenses = sizeof (mpc85xx_cds_openpic_initsenses);
+
+	/* Skip reserved space and internal sources */
+	openpic_set_sources(0, 32, OpenPIC_Addr + 0x10200);
+	/* Map PIC IRQs 0-11 */
+	openpic_set_sources(32, 12, OpenPIC_Addr + 0x10000);
+
+	/* we let openpic interrupts starting from an offset, to
+	 * leave space for cascading interrupts underneath.
+	 */
+	openpic_init(MPC85xx_OPENPIC_IRQ_OFFSET);
 
 #ifdef CONFIG_CPM2
 	/* disable all CPM interupts */
@@ -219,7 +221,7 @@
 	setup_irq(MPC85xx_IRQ_CPM, &cpm2_irqaction);
 #endif
 
-        return;
+	return;
 }
 
 #ifdef CONFIG_PCI
@@ -278,8 +280,8 @@
 	}
 }
 
-#define ARCADIA_HOST_BRIDGE_IDSEL     17
-#define ARCADIA_2ND_BRIDGE_IDSEL     3
+#define ARCADIA_HOST_BRIDGE_IDSEL	17
+#define ARCADIA_2ND_BRIDGE_IDSEL	3
 
 extern int mpc85xx_pci1_last_busno;
 
@@ -289,7 +291,7 @@
 	if (bus == 0 && PCI_SLOT(devfn) == 0)
 		return PCIBIOS_DEVICE_NOT_FOUND;
 #ifdef CONFIG_85xx_PCI2
-	if (mpc85xx_pci1_last_busno) 
+	if (mpc85xx_pci1_last_busno)
 		if (bus == (mpc85xx_pci1_last_busno + 1) && PCI_SLOT(devfn) == 0)
 			return PCIBIOS_DEVICE_NOT_FOUND;
 #endif
@@ -303,6 +305,8 @@
 }
 #endif /* CONFIG_PCI */
 
+TODC_ALLOC();
+
 /* ************************************************************************
  *
  * Setup the architecture
@@ -311,14 +315,14 @@
 static void __init
 mpc85xx_cds_setup_arch(void)
 {
-        bd_t *binfo = (bd_t *) __res;
-        unsigned int freq;
+	bd_t *binfo = (bd_t *) __res;
+	unsigned int freq;
 	struct gianfar_platform_data *pdata;
 
-        /* get the core frequency */
-        freq = binfo->bi_intfreq;
+	/* get the core frequency */
+	freq = binfo->bi_intfreq;
 
-        printk("mpc85xx_cds_setup_arch\n");
+	printk("mpc85xx_cds_setup_arch\n");
 
 #ifdef CONFIG_CPM2
 	cpm2_reset();
@@ -328,17 +332,24 @@
 	cds_pci_slot = ((cadmus[CM_CSR] >> 6) & 0x3) + 1;
 	printk("CDS Version = %x in PCI slot %d\n", cadmus[CM_VER], cds_pci_slot);
 
-        /* Set loops_per_jiffy to a half-way reasonable value,
-           for use until calibrate_delay gets called. */
-        loops_per_jiffy = freq / HZ;
+	/* Setup TODC access */
+	TODC_INIT(TODC_TYPE_DS1743,
+			0,
+			0,
+			ioremap(CDS_RTC_ADDR, CDS_RTC_SIZE),
+			8);
+
+	/* Set loops_per_jiffy to a half-way reasonable value,
+	   for use until calibrate_delay gets called. */
+	loops_per_jiffy = freq / HZ;
 
 #ifdef CONFIG_PCI
-        /* setup PCI host bridges */
-        mpc85xx_setup_hose();
+	/* setup PCI host bridges */
+	mpc85xx_setup_hose();
 #endif
 
 #ifdef CONFIG_SERIAL_8250
-        mpc85xx_early_serial_map();
+	mpc85xx_early_serial_map();
 #endif
 
 #ifdef CONFIG_SERIAL_TEXT_DEBUG
@@ -366,14 +377,14 @@
 
 
 #ifdef CONFIG_BLK_DEV_INITRD
-        if (initrd_start)
-                ROOT_DEV = Root_RAM0;
-        else
+	if (initrd_start)
+		ROOT_DEV = Root_RAM0;
+	else
 #endif
 #ifdef  CONFIG_ROOT_NFS
-                ROOT_DEV = Root_NFS;
+		ROOT_DEV = Root_NFS;
 #else
-                ROOT_DEV = Root_HDA1;
+	ROOT_DEV = Root_HDA1;
 #endif
 }
 
@@ -382,18 +393,18 @@
 platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
               unsigned long r6, unsigned long r7)
 {
-        /* parse_bootinfo must always be called first */
-        parse_bootinfo(find_bootinfo());
+	/* parse_bootinfo must always be called first */
+	parse_bootinfo(find_bootinfo());
 
-        /*
-         * If we were passed in a board information, copy it into the
-         * residual data area.
-         */
-        if (r3) {
-                memcpy((void *) __res, (void *) (r3 + KERNELBASE),
-                       sizeof (bd_t));
+	/*
+	 * If we were passed in a board information, copy it into the
+	 * residual data area.
+	 */
+	if (r3) {
+		memcpy((void *) __res, (void *) (r3 + KERNELBASE),
+				sizeof (bd_t));
 
-        }
+	}
 #ifdef CONFIG_SERIAL_TEXT_DEBUG
 	{
 		bd_t *binfo = (bd_t *) __res;
@@ -401,7 +412,7 @@
 
 		/* Use the last TLB entry to map CCSRBAR to allow access to DUART regs */
 		settlbcam(NUM_TLBCAMS - 1, binfo->bi_immr_base,
-			  binfo->bi_immr_base, MPC85xx_CCSRBAR_SIZE, _PAGE_IO, 0);
+				binfo->bi_immr_base, MPC85xx_CCSRBAR_SIZE, _PAGE_IO, 0);
 
 		memset(&p, 0, sizeof (p));
 		p.iotype = SERIAL_IO_MEM;
@@ -420,49 +431,53 @@
 #endif
 
 #if defined(CONFIG_BLK_DEV_INITRD)
-        /*
-         * If the init RAM disk has been configured in, and there's a valid
-         * starting address for it, set it up.
-         */
-        if (r4) {
-                initrd_start = r4 + KERNELBASE;
-                initrd_end = r5 + KERNELBASE;
-        }
-#endif                          /* CONFIG_BLK_DEV_INITRD */
-
-        /* Copy the kernel command line arguments to a safe place. */
-
-        if (r6) {
-                *(char *) (r7 + KERNELBASE) = 0;
-                strcpy(cmd_line, (char *) (r6 + KERNELBASE));
-        }
+	/*
+	 * If the init RAM disk has been configured in, and there's a valid
+	 * starting address for it, set it up.
+	 */
+	if (r4) {
+		initrd_start = r4 + KERNELBASE;
+		initrd_end = r5 + KERNELBASE;
+	}
+#endif /* CONFIG_BLK_DEV_INITRD */
+
+	/* Copy the kernel command line arguments to a safe place. */
+
+	if (r6) {
+		*(char *) (r7 + KERNELBASE) = 0;
+		strcpy(cmd_line, (char *) (r6 + KERNELBASE));
+	}
 
 	identify_ppc_sys_by_id(mfspr(SVR));
 
-        /* setup the PowerPC module struct */
-        ppc_md.setup_arch = mpc85xx_cds_setup_arch;
-        ppc_md.show_cpuinfo = mpc85xx_cds_show_cpuinfo;
-
-        ppc_md.init_IRQ = mpc85xx_cds_init_IRQ;
-        ppc_md.get_irq = openpic_get_irq;
-
-        ppc_md.restart = mpc85xx_restart;
-        ppc_md.power_off = mpc85xx_power_off;
-        ppc_md.halt = mpc85xx_halt;
-
-        ppc_md.find_end_of_memory = mpc85xx_find_end_of_memory;
-
-        ppc_md.time_init = NULL;
-        ppc_md.set_rtc_time = NULL;
-        ppc_md.get_rtc_time = NULL;
-        ppc_md.calibrate_decr = mpc85xx_calibrate_decr;
+	/* setup the PowerPC module struct */
+	ppc_md.setup_arch = mpc85xx_cds_setup_arch;
+	ppc_md.show_cpuinfo = mpc85xx_cds_show_cpuinfo;
+
+	ppc_md.init_IRQ = mpc85xx_cds_init_IRQ;
+	ppc_md.get_irq = openpic_get_irq;
+
+	ppc_md.restart = mpc85xx_restart;
+	ppc_md.power_off = mpc85xx_power_off;
+	ppc_md.halt = mpc85xx_halt;
+
+	ppc_md.find_end_of_memory = mpc85xx_find_end_of_memory;
+
+	ppc_md.calibrate_decr = mpc85xx_calibrate_decr;
+
+	ppc_md.time_init = todc_time_init;
+	ppc_md.set_rtc_time = todc_set_rtc_time;
+	ppc_md.get_rtc_time = todc_get_rtc_time;
+
+	ppc_md.nvram_read_val = todc_direct_read_val;
+	ppc_md.nvram_write_val = todc_direct_write_val;
 
 #if defined(CONFIG_SERIAL_8250) && defined(CONFIG_SERIAL_TEXT_DEBUG)
-        ppc_md.progress = gen550_progress;
+	ppc_md.progress = gen550_progress;
 #endif /* CONFIG_SERIAL_8250 && CONFIG_SERIAL_TEXT_DEBUG */
 
-        if (ppc_md.progress)
-                ppc_md.progress("mpc85xx_cds_init(): exit", 0);
+	if (ppc_md.progress)
+		ppc_md.progress("mpc85xx_cds_init(): exit", 0);
 
-        return;
+	return;
 }
diff -Nru a/arch/ppc/platforms/85xx/mpc85xx_cds_common.h b/arch/ppc/platforms/85xx/mpc85xx_cds_common.h
--- a/arch/ppc/platforms/85xx/mpc85xx_cds_common.h	2005-03-11 12:51:41 -08:00
+++ b/arch/ppc/platforms/85xx/mpc85xx_cds_common.h	2005-03-11 12:51:41 -08:00
@@ -33,6 +33,10 @@
 #define CM_CSR	(1)
 #define CM_RST	(2)
 
+/* CDS NVRAM/RTC */
+#define CDS_RTC_ADDR	(0xf8000000)
+#define CDS_RTC_SIZE	(8 * 1024)
+
 /* PCI config */
 #define PCI1_CFG_ADDR_OFFSET	(0x8000)
 #define PCI1_CFG_DATA_OFFSET	(0x8004)
diff -Nru a/arch/ppc/platforms/85xx/mpc85xx_sys.c b/arch/ppc/platforms/85xx/mpc85xx_sys.c
--- a/arch/ppc/platforms/85xx/mpc85xx_sys.c	2005-03-11 12:51:42 -08:00
+++ b/arch/ppc/platforms/85xx/mpc85xx_sys.c	2005-03-11 12:51:42 -08:00
@@ -21,7 +21,7 @@
 struct ppc_sys_spec *cur_ppc_sys_spec;
 struct ppc_sys_spec ppc_sys_specs[] = {
 	{
-		.ppc_sys_name	= "MPC8540",
+		.ppc_sys_name	= "8540",
 		.mask 		= 0xFFFF0000,
 		.value 		= 0x80300000,
 		.num_devices	= 10,
@@ -33,7 +33,7 @@
 		},
 	},
 	{
-		.ppc_sys_name	= "MPC8560",
+		.ppc_sys_name	= "8560",
 		.mask 		= 0xFFFF0000,
 		.value 		= 0x80700000,
 		.num_devices	= 19,
@@ -49,7 +49,7 @@
 		},
 	},
 	{
-		.ppc_sys_name	= "MPC8541",
+		.ppc_sys_name	= "8541",
 		.mask 		= 0xFFFF0000,
 		.value 		= 0x80720000,
 		.num_devices	= 13,
@@ -63,7 +63,7 @@
 		},
 	},
 	{
-		.ppc_sys_name	= "MPC8541E",
+		.ppc_sys_name	= "8541E",
 		.mask 		= 0xFFFF0000,
 		.value 		= 0x807A0000,
 		.num_devices	= 14,
@@ -77,7 +77,7 @@
 		},
 	},
 	{
-		.ppc_sys_name	= "MPC8555",
+		.ppc_sys_name	= "8555",
 		.mask 		= 0xFFFF0000,
 		.value 		= 0x80710000,
 		.num_devices	= 20,
@@ -94,7 +94,7 @@
 		},
 	},
 	{
-		.ppc_sys_name	= "MPC8555E",
+		.ppc_sys_name	= "8555E",
 		.mask 		= 0xFFFF0000,
 		.value 		= 0x80790000,
 		.num_devices	= 21,
diff -Nru a/arch/ppc/platforms/85xx/sbc85xx.c b/arch/ppc/platforms/85xx/sbc85xx.c
--- a/arch/ppc/platforms/85xx/sbc85xx.c	2005-03-11 12:51:47 -08:00
+++ b/arch/ppc/platforms/85xx/sbc85xx.c	2005-03-11 12:51:47 -08:00
@@ -42,6 +42,7 @@
 #include <asm/mpc85xx.h>
 #include <asm/irq.h>
 #include <asm/immap_85xx.h>
+#include <asm/ppc_sys.h>
 
 #include <mm/mmu_decl.h>
 
@@ -128,19 +129,9 @@
 	pvid = mfspr(PVR);
 	svid = mfspr(SVR);
 
+	seq_printf(m, "chip\t\t: MPC%s\n", cur_ppc_sys_spec->ppc_sys_name);
 	seq_printf(m, "Vendor\t\t: Wind River\n");
-
-	switch (svid & 0xffff0000) {
-	case SVR_8540:
-		seq_printf(m, "Machine\t\t: hhmmm, this board isn't made yet!\n");
-		break;
-	case SVR_8560:
-		seq_printf(m, "Machine\t\t: SBC8560\n");
-		break;
-	default:
-		seq_printf(m, "Machine\t\t: unknown\n");
-		break;
-	}
+	seq_printf(m, "Machine\t\t: SBC%s\n", cur_ppc_sys_spec->ppc_sys_name);
 	seq_printf(m, "clock\t\t: %dMHz\n", freq / 1000000);
 	seq_printf(m, "PVR\t\t: 0x%x\n", pvid);
 	seq_printf(m, "SVR\t\t: 0x%x\n", svid);
diff -Nru a/arch/ppc/platforms/85xx/stx_gp3.c b/arch/ppc/platforms/85xx/stx_gp3.c
--- a/arch/ppc/platforms/85xx/stx_gp3.c	2005-03-11 12:51:46 -08:00
+++ b/arch/ppc/platforms/85xx/stx_gp3.c	2005-03-11 12:51:46 -08:00
@@ -34,8 +34,10 @@
 #include <linux/root_dev.h>
 #include <linux/seq_file.h>
 #include <linux/serial.h>
+#include <linux/initrd.h>
 #include <linux/module.h>
 #include <linux/fsl_devices.h>
+#include <linux/interrupt.h>
 
 #include <asm/system.h>
 #include <asm/pgtable.h>
@@ -266,19 +268,9 @@
 
 	memsize = total_memory;
 
+	seq_printf(m, "chip\t\t: MPC%s\n", cur_ppc_sys_spec->ppc_sys_name);
 	seq_printf(m, "Vendor\t\t: RPC Electronics STx \n");
-
-	switch (svid & 0xffff0000) {
-	case SVR_8540:
-		seq_printf(m, "Machine\t\t: GP3 - MPC8540\n");
-		break;
-	case SVR_8560:
-		seq_printf(m, "Machine\t\t: GP3 - MPC8560\n");
-		break;
-	default:
-		seq_printf(m, "Machine\t\t: unknown\n");
-		break;
-	}
+	seq_printf(m, "Machine\t\t: GP3 - MPC%s\n", cur_ppc_sys_spec->ppc_sys_name);
 	seq_printf(m, "bus freq\t: %u.%.6u MHz\n", freq / 1000000,
 		   freq % 1000000);
 	seq_printf(m, "PVR\t\t: 0x%x\n", pvid);
diff -Nru a/arch/ppc/platforms/Makefile b/arch/ppc/platforms/Makefile
--- a/arch/ppc/platforms/Makefile	2005-03-11 12:51:52 -08:00
+++ b/arch/ppc/platforms/Makefile	2005-03-11 12:51:52 -08:00
@@ -39,6 +39,7 @@
 obj-$(CONFIG_PPLUS)		+= pplus.o
 obj-$(CONFIG_PRPMC750)		+= prpmc750.o
 obj-$(CONFIG_PRPMC800)		+= prpmc800.o
+obj-$(CONFIG_RADSTONE_PPC7D)	+= radstone_ppc7d.o
 obj-$(CONFIG_SANDPOINT)		+= sandpoint.o
 obj-$(CONFIG_SBC82xx)		+= sbc82xx.o
 obj-$(CONFIG_SPRUCE)		+= spruce.o
diff -Nru a/arch/ppc/platforms/katana.c b/arch/ppc/platforms/katana.c
--- a/arch/ppc/platforms/katana.c	2005-03-11 12:51:51 -08:00
+++ b/arch/ppc/platforms/katana.c	2005-03-11 12:51:51 -08:00
@@ -1,9 +1,10 @@
 /*
  * arch/ppc/platforms/katana.c
  *
- * Board setup routines for the Artesyn Katana 750 based boards.
+ * Board setup routines for the Artesyn Katana cPCI boards.
  *
- * Tim Montgomery <timm@artesyncp.com>
+ * Athor: Tim Montgomery <timm@artesyncp.com>
+ * Maintained by: Mark A. Greer <mgreer@mvista.com>
  *
  * Based on code done by Rabeeh Khoury - rabeeh@galileo.co.il
  * Based on code done by - Mark A. Greer <mgreer@mvista.com>
@@ -26,7 +27,8 @@
 #include <linux/root_dev.h>
 #include <linux/delay.h>
 #include <linux/seq_file.h>
-#include <linux/smp.h>
+#include <linux/bootmem.h>
+#include <linux/mtd/physmap.h>
 #include <linux/mv643xx.h>
 #ifdef CONFIG_BOOTIMG
 #include <linux/bootimg.h>
@@ -36,13 +38,19 @@
 #include <asm/smp.h>
 #include <asm/todc.h>
 #include <asm/bootinfo.h>
+#include <asm/ppcboot.h>
 #include <asm/mv64x60.h>
 #include <platforms/katana.h>
 
 static struct		mv64x60_handle bh;
 static katana_id_t	katana_id;
-static u32		cpld_base;
-static u32		sram_base;
+static void __iomem	*cpld_base;
+static void __iomem	*sram_base;
+
+static u32		katana_flash_size_0;
+static u32		katana_flash_size_1;
+
+unsigned char	__res[sizeof(bd_t)];
 
 /* PCI Interrupt routing */
 static int __init
@@ -105,7 +113,7 @@
 void __init
 katana_get_board_id(void)
 {
-	switch (in_8((volatile char *)(cpld_base + KATANA_CPLD_PRODUCT_ID))) {
+	switch (in_8(cpld_base + KATANA_CPLD_PRODUCT_ID)) {
 	case KATANA_PRODUCT_ID_3750:
 		katana_id = KATANA_ID_3750;
 		break;
@@ -170,7 +178,7 @@
 static inline int
 katana_is_monarch(void)
 {
-	return in_8((volatile char *)(cpld_base + KATANA_CPLD_BD_CFG_3)) &
+	return in_8(cpld_base + KATANA_CPLD_BD_CFG_3) &
 		KATANA_CPLD_BD_CFG_3_MONARCH;
 }
 
@@ -180,18 +188,17 @@
 	u8 reset_out;
 
 	/* Enable access to IPMI ctlr by clearing IPMI PORTSEL bit in CPLD */
-	reset_out = in_8((volatile char *)(cpld_base + KATANA_CPLD_RESET_OUT));
+	reset_out = in_8(cpld_base + KATANA_CPLD_RESET_OUT);
 	reset_out &= ~KATANA_CPLD_RESET_OUT_PORTSEL;
-	out_8((volatile void *)(cpld_base + KATANA_CPLD_RESET_OUT), reset_out);
-	return;
+	out_8(cpld_base + KATANA_CPLD_RESET_OUT, reset_out);
 }
 
-static unsigned long
+static u32
 katana_bus_freq(void)
 {
 	u8 bd_cfg_0;
 
-	bd_cfg_0 = in_8((volatile char *)(cpld_base + KATANA_CPLD_BD_CFG_0));
+	bd_cfg_0 = in_8(cpld_base + KATANA_CPLD_BD_CFG_0);
 
 	switch (bd_cfg_0 & KATANA_CPLD_BD_CFG_0_SYSCLK_MASK) {
 	case KATANA_CPLD_BD_CFG_0_SYSCLK_200:
@@ -263,13 +270,12 @@
 	 * BIT25 summarizes GPP interrupts 8-15
 	 */
 	mv64x60_set_bits(&bh, MV64360_IC_CPU0_INTR_MASK_HI, (1<<25));
-	return;
 }
 
 void __init
 katana_setup_peripherals(void)
 {
-	u32 base, size_0, size_1;
+	u32 base;
 
 	/* Set up windows for boot CS, soldered & socketed flash, and CPLD */
 	mv64x60_set_32bit_window(&bh, MV64x60_CPU2BOOT_WIN,
@@ -277,19 +283,22 @@
 	bh.ci->enable_window_32bit(&bh, MV64x60_CPU2BOOT_WIN);
 
 	/* Assume firmware set up window sizes correctly for dev 0 & 1 */
-	mv64x60_get_32bit_window(&bh, MV64x60_CPU2DEV_0_WIN, &base, &size_0);
+	mv64x60_get_32bit_window(&bh, MV64x60_CPU2DEV_0_WIN, &base,
+		&katana_flash_size_0);
 
-	if (size_0 > 0) {
+	if (katana_flash_size_0 > 0) {
 		mv64x60_set_32bit_window(&bh, MV64x60_CPU2DEV_0_WIN,
-			 KATANA_SOLDERED_FLASH_BASE, size_0, 0);
+			 KATANA_SOLDERED_FLASH_BASE, katana_flash_size_0, 0);
 		bh.ci->enable_window_32bit(&bh, MV64x60_CPU2DEV_0_WIN);
 	}
 
-	mv64x60_get_32bit_window(&bh, MV64x60_CPU2DEV_1_WIN, &base, &size_1);
+	mv64x60_get_32bit_window(&bh, MV64x60_CPU2DEV_1_WIN, &base,
+		&katana_flash_size_1);
 
-	if (size_1 > 0) {
+	if (katana_flash_size_1 > 0) {
 		mv64x60_set_32bit_window(&bh, MV64x60_CPU2DEV_1_WIN,
-			 (KATANA_SOLDERED_FLASH_BASE + size_0), size_1, 0);
+			 (KATANA_SOLDERED_FLASH_BASE + katana_flash_size_0),
+			 katana_flash_size_1, 0);
 		bh.ci->enable_window_32bit(&bh, MV64x60_CPU2DEV_1_WIN);
 	}
 
@@ -300,12 +309,12 @@
 	mv64x60_set_32bit_window(&bh, MV64x60_CPU2DEV_3_WIN,
 		 KATANA_CPLD_BASE, KATANA_CPLD_SIZE, 0);
 	bh.ci->enable_window_32bit(&bh, MV64x60_CPU2DEV_3_WIN);
-	cpld_base = (u32)ioremap(KATANA_CPLD_BASE, KATANA_CPLD_SIZE);
+	cpld_base = ioremap(KATANA_CPLD_BASE, KATANA_CPLD_SIZE);
 
 	mv64x60_set_32bit_window(&bh, MV64x60_CPU2SRAM_WIN,
 		 KATANA_INTERNAL_SRAM_BASE, MV64360_SRAM_SIZE, 0);
 	bh.ci->enable_window_32bit(&bh, MV64x60_CPU2SRAM_WIN);
-	sram_base = (u32)ioremap(KATANA_INTERNAL_SRAM_BASE, MV64360_SRAM_SIZE);
+	sram_base = ioremap(KATANA_INTERNAL_SRAM_BASE, MV64360_SRAM_SIZE);
 
 	/* Set up Enet->SRAM window */
 	mv64x60_set_32bit_window(&bh, MV64x60_ENET2MEM_4_WIN,
@@ -339,13 +348,11 @@
 	 * internal data path in SRAM since it's first time accessing it
 	 * while after reset it's not configured.
 	 */
-	memset((void *)sram_base, 0, MV64360_SRAM_SIZE);
+	memset(sram_base, 0, MV64360_SRAM_SIZE);
 
 	/* Only processor zero [on 3750] is an PCI interrupt controller */
 	if (katana_get_proc_num() == 0)
 		katana_intr_setup();
-
-	return;
 }
 
 static void __init
@@ -356,7 +363,7 @@
 
 	memset(&si, 0, sizeof(si));
 
-	si.phys_reg_base = KATANA_BRIDGE_REG_BASE;
+	si.phys_reg_base = CONFIG_MV64X60_NEW_BASE;
 
 	si.pci_1.enable_bus = 1;
 	si.pci_1.pci_io.cpu_base = KATANA_PCI1_IO_START_PROC_ADDR;
@@ -410,10 +417,77 @@
 	mv64x60_set_bus(&bh, 1, 0);
 	bh.hose_b->first_busno = 0;
 	bh.hose_b->last_busno = 0xff;
+}
+
+#ifdef CONFIG_MTD_PHYSMAP
 
-	return;
+#ifndef MB
+#define MB	(1 << 20)
+#endif
+
+/*
+ * MTD Layout depends on amount of soldered FLASH in system. Sizes in MB.
+ *
+ * FLASH Amount:	128	64	32	16
+ * -------------	---	--	--	--
+ * Monitor:		1	1	1	1
+ * Primary Kernel:	1.5	1.5	1.5	1.5
+ * Primary fs:		30	30	<end>	<end>
+ * Secondary Kernel:	1.5	1.5	N/A	N/A
+ * Secondary fs:	<end>	<end>	N/A	N/A
+ * User: 		<overlays entire FLASH except for "Monitor" section>
+ */
+static int __init
+katana_setup_mtd(void)
+{
+	u32	size;
+	int	ptbl_entries;
+	static struct mtd_partition	*ptbl;
+
+	size = katana_flash_size_0 + katana_flash_size_1;
+	if (!size)
+		return -ENOMEM;
+
+	ptbl_entries = (size >= (64*MB)) ? 6 : 4;
+
+	if ((ptbl = kmalloc(ptbl_entries * sizeof(struct mtd_partition),
+		GFP_KERNEL)) == NULL) {
+
+		printk(KERN_WARNING "Can't alloc MTD partition table\n");
+		return -ENOMEM;
+	}
+	memset(ptbl, 0, ptbl_entries * sizeof(struct mtd_partition));
+
+	ptbl[0].name = "Monitor";
+	ptbl[0].size = KATANA_MTD_MONITOR_SIZE;
+	ptbl[1].name = "Primary Kernel";
+	ptbl[1].offset = MTDPART_OFS_NXTBLK;
+	ptbl[1].size = 0x00180000; /* 1.5 MB */
+	ptbl[2].name = "Primary Filesystem";
+	ptbl[2].offset = MTDPART_OFS_APPEND;
+	ptbl[2].size = MTDPART_SIZ_FULL; /* Correct for 16 & 32 MB */
+	ptbl[ptbl_entries-1].name = "User FLASH";
+	ptbl[ptbl_entries-1].offset = KATANA_MTD_MONITOR_SIZE;
+	ptbl[ptbl_entries-1].size = MTDPART_SIZ_FULL;
+
+	if (size >= (64*MB)) {
+		ptbl[2].size = 30*MB;
+		ptbl[3].name = "Secondary Kernel";
+		ptbl[3].offset = MTDPART_OFS_NXTBLK;
+		ptbl[3].size = 0x00180000; /* 1.5 MB */
+		ptbl[4].name = "Secondary Filesystem";
+		ptbl[4].offset = MTDPART_OFS_APPEND;
+		ptbl[4].size = MTDPART_SIZ_FULL;
+	}
+
+	physmap_map.size = size;
+	physmap_set_partitions(ptbl, ptbl_entries);
+	return 0;
 }
 
+arch_initcall(katana_setup_mtd);
+#endif
+
 static void __init
 katana_setup_arch(void)
 {
@@ -444,8 +518,7 @@
 		printk(KERN_INFO "DD2.0 detected. Setting L2 cache"
 			"to Writethrough mode\n");
 		_set_L2CR(L2CR_L2E | L2CR_L2PE | L2CR_L2WT);
-	}
-	else
+	} else
 		_set_L2CR(L2CR_L2E | L2CR_L2PE);
 
 	if (ppc_md.progress)
@@ -458,7 +531,6 @@
 	printk(KERN_INFO "Artesyn Communication Products, LLC - Katana(TM)\n");
 	if (ppc_md.progress)
 		ppc_md.progress("katana_setup_arch: exit", 0);
-	return;
 }
 
 /* Platform device data fixup routines. */
@@ -473,9 +545,12 @@
 	pdata->max_idle = 40;
 	pdata->default_baud = KATANA_DEFAULT_BAUD;
 	pdata->brg_clk_src = KATANA_MPSC_CLK_SRC;
-	pdata->brg_clk_freq = KATANA_MPSC_CLK_FREQ;
-
-	return;
+	/*
+	 * TCLK (not SysCLk) is routed to BRG, then to the MPSC.  On most parts,
+	 * TCLK == SysCLK but on 64460, they are separate pins.
+	 * SysCLK can go up to 200 MHz but TCLK can only go up to 133 MHz.
+	 */
+	pdata->brg_clk_freq = min(katana_bus_freq(), MV64x60_TCLK_FREQ_MAX);
 }
 #endif
 
@@ -483,32 +558,18 @@
 static void __init
 katana_fixup_eth_pdata(struct platform_device *pdev)
 {
-	struct mv64xxx_eth_platform_data *eth_pd;
+	struct mv643xx_eth_platform_data *eth_pd;
 	static u16 phy_addr[] = {
 		KATANA_ETH0_PHY_ADDR,
 		KATANA_ETH1_PHY_ADDR,
 		KATANA_ETH2_PHY_ADDR,
 	};
-	int	rx_size = KATANA_ETH_RX_QUEUE_SIZE * MV64340_ETH_DESC_SIZE;
-	int	tx_size = KATANA_ETH_TX_QUEUE_SIZE * MV64340_ETH_DESC_SIZE;
 
 	eth_pd = pdev->dev.platform_data;
 	eth_pd->force_phy_addr = 1;
 	eth_pd->phy_addr = phy_addr[pdev->id];
 	eth_pd->tx_queue_size = KATANA_ETH_TX_QUEUE_SIZE;
 	eth_pd->rx_queue_size = KATANA_ETH_RX_QUEUE_SIZE;
-	eth_pd->tx_sram_addr = mv643xx_sram_alloc(tx_size);
-
-	if (eth_pd->tx_sram_addr)
-		eth_pd->tx_sram_size = tx_size;
-	else
-		printk(KERN_ERR "mv643xx_sram_alloc failed\n");
-
-	eth_pd->rx_sram_addr = mv643xx_sram_alloc(rx_size);
-	if (eth_pd->rx_sram_addr)
-		eth_pd->rx_sram_size = rx_size;
-	else
-		printk(KERN_ERR "mv643xx_sram_alloc failed\n");
 }
 #endif
 
@@ -524,9 +585,9 @@
 		{ MPSC_CTLR_NAME "1", katana_fixup_mpsc_pdata },
 #endif
 #if defined(CONFIG_MV643XX_ETH)
-		{ MV64XXX_ETH_NAME "0", katana_fixup_eth_pdata },
-		{ MV64XXX_ETH_NAME "1", katana_fixup_eth_pdata },
-		{ MV64XXX_ETH_NAME "2", katana_fixup_eth_pdata },
+		{ MV643XX_ETH_NAME "0", katana_fixup_eth_pdata },
+		{ MV643XX_ETH_NAME "1", katana_fixup_eth_pdata },
+		{ MV643XX_ETH_NAME "2", katana_fixup_eth_pdata },
 #endif
 	};
 	struct platform_device	*pdev;
@@ -548,11 +609,10 @@
 static void
 katana_restart(char *cmd)
 {
-	volatile ulong i = 10000000;
+	ulong	i = 10000000;
 
 	/* issue hard reset to the reset command register */
-	out_8((volatile char *)(cpld_base + KATANA_CPLD_RST_CMD),
-		KATANA_CPLD_RST_CMD_HR);
+	out_8(cpld_base + KATANA_CPLD_RST_CMD, KATANA_CPLD_RST_CMD_HR);
 
 	while (i-- > 0) ;
 	panic("restart failed\n");
@@ -561,6 +621,14 @@
 static void
 katana_halt(void)
 {
+	u8	v;
+
+	if (katana_id == KATANA_ID_752I) {
+		   v = in_8(cpld_base + HSL_PLD_BASE + HSL_PLD_HOT_SWAP_OFF);
+		   v |= HSL_PLD_HOT_SWAP_LED_BIT;
+		   out_8(cpld_base + HSL_PLD_BASE + HSL_PLD_HOT_SWAP_OFF, v);
+	}
+
 	while (1) ;
 	/* NOTREACHED */
 }
@@ -598,12 +666,13 @@
 	}
 
 	seq_printf(m, "product ID\t: 0x%x\n",
-		   in_8((volatile char *)(cpld_base + KATANA_CPLD_PRODUCT_ID)));
+		   in_8(cpld_base + KATANA_CPLD_PRODUCT_ID));
 	seq_printf(m, "hardware rev\t: 0x%x\n",
-		   in_8((volatile char *)(cpld_base+KATANA_CPLD_HARDWARE_VER)));
+		   in_8(cpld_base+KATANA_CPLD_HARDWARE_VER));
 	seq_printf(m, "PLD rev\t\t: 0x%x\n",
-		   in_8((volatile char *)(cpld_base + KATANA_CPLD_PLD_VER)));
-	seq_printf(m, "PLB freq\t: %ldMhz\n", katana_bus_freq() / 1000000);
+		   in_8(cpld_base + KATANA_CPLD_PLD_VER));
+	seq_printf(m, "PLB freq\t: %ldMhz\n",
+		(long)katana_bus_freq() / 1000000);
 	seq_printf(m, "PCI\t\t: %sMonarch\n", katana_is_monarch()? "" : "Non-");
 
 	return 0;
@@ -612,23 +681,21 @@
 static void __init
 katana_calibrate_decr(void)
 {
-	ulong freq;
+	u32 freq;
 
 	freq = katana_bus_freq() / 4;
 
 	printk(KERN_INFO "time_init: decrementer frequency = %lu.%.6lu MHz\n",
-	       freq / 1000000, freq % 1000000);
+	       (long)freq / 1000000, (long)freq % 1000000);
 
 	tb_ticks_per_jiffy = freq / HZ;
 	tb_to_us = mulhwu_scale_factor(freq, 1000000);
-
-	return;
 }
 
 unsigned long __init
 katana_find_end_of_memory(void)
 {
-	return mv64x60_get_mem_size(KATANA_BRIDGE_REG_BASE,
+	return mv64x60_get_mem_size(CONFIG_MV64X60_NEW_BASE,
 		MV64x60_TYPE_MV64360);
 }
 
@@ -639,8 +706,6 @@
 	mtspr(DBAT2U, 0xf0001ffe);
 	mtspr(DBAT2L, 0xf000002a);
 	mb();
-
-	return;
 }
 
 #if defined(CONFIG_SERIAL_TEXT_DEBUG) && defined(CONFIG_SERIAL_MPSC_CONSOLE)
@@ -657,6 +722,23 @@
 {
 	parse_bootinfo(find_bootinfo());
 
+	/* ASSUMPTION:  If both r3 (bd_t pointer) and r6 (cmdline pointer)
+	 * are non-zero, then we should use the board info from the bd_t
+	 * structure and the cmdline pointed to by r6 instead of the
+	 * information from birecs, if any.  Otherwise, use the information
+	 * from birecs as discovered by the preceeding call to
+	 * parse_bootinfo().  This rule should work with both PPCBoot, which
+	 * uses a bd_t board info structure, and the kernel boot wrapper,
+	 * which uses birecs.
+	 */
+	if (r3 && r6) {
+		/* copy board info structure */
+		memcpy( (void *)__res,(void *)(r3+KERNELBASE), sizeof(bd_t) );
+		/* copy command line */
+		*(char *)(r7+KERNELBASE) = 0;
+		strcpy(cmd_line, (char *)(r6+KERNELBASE));
+	}
+
 	isa_mem_base = 0;
 
 	ppc_md.setup_arch = katana_setup_arch;
@@ -672,7 +754,7 @@
 #if defined(CONFIG_SERIAL_TEXT_DEBUG) && defined(CONFIG_SERIAL_MPSC_CONSOLE)
 	ppc_md.setup_io_mappings = katana_map_io;
 	ppc_md.progress = mv64x60_mpsc_progress;
-	mv64x60_progress_init(KATANA_BRIDGE_REG_BASE);
+	mv64x60_progress_init(CONFIG_MV64X60_NEW_BASE);
 #endif
 
 #if defined(CONFIG_SERIAL_MPSC) || defined(CONFIG_MV643XX_ETH)
@@ -680,5 +762,4 @@
 #endif
 
 	katana_set_bat(); /* Need for katana_find_end_of_memory and progress */
-	return;
 }
diff -Nru a/arch/ppc/platforms/katana.h b/arch/ppc/platforms/katana.h
--- a/arch/ppc/platforms/katana.h	2005-03-11 12:51:52 -08:00
+++ b/arch/ppc/platforms/katana.h	2005-03-11 12:51:52 -08:00
@@ -19,18 +19,17 @@
  * PCI I/O space and 4 windows from the CPU bus to PCI MEM space.
  * We'll only use one PCI MEM window on each PCI bus.
  *
- * This is the CPU physical memory map (windows must be at least 1MB and start
+ * This is the CPU physical memory map (windows must be at least 64 KB and start
  * on a boundary that is a multiple of the window size):
  *
  *    0xff800000-0xffffffff      - Boot window
  *    0xf8400000-0xf85fffff      - Internal SRAM
- *    0xf8200000-0xf823ffff      - CPLD
- *    0xf8100000-0xf810ffff      - MV64360 Registers
- *    0xf8000000-0xf80fffff      - PLCC socket
- *    0xf0000000-0xf01fffff	 - Consistent memory pool
- *    0xe8000000-0xefffffff      - soldered flash
- *    0xc0000000-0xc0ffffff      - PCI I/O
- *    0x80000000-0xbfffffff      - PCI MEM
+ *    0xf8200000-0xf83fffff      - CPLD
+ *    0xf8100000-0xf810ffff      - MV64360 Registers (CONFIG_MV64X60_NEW_BASE)
+ *    0xf8000000-0xf80fffff      - Socketed FLASH
+ *    0xe0000000-0xefffffff      - Soldered FLASH
+ *    0xc0000000-0xc3ffffff      - PCI I/O (second hose)
+ *    0x80000000-0xbfffffff      - PCI MEM (second hose)
  */
 
 #ifndef __PPC_PLATFORMS_KATANA_H
@@ -38,33 +37,22 @@
 
 /* CPU Physical Memory Map setup. */
 #define KATANA_BOOT_WINDOW_BASE			0xff800000
+#define KATANA_BOOT_WINDOW_SIZE			0x00800000 /* 8 MB */
 #define KATANA_INTERNAL_SRAM_BASE		0xf8400000
 #define KATANA_CPLD_BASE			0xf8200000
-#define KATANA_BRIDGE_REG_BASE			0xf8100000
+#define KATANA_CPLD_SIZE			0x00200000 /* 2 MB */
 #define KATANA_SOCKET_BASE			0xf8000000
-#define KATANA_SOLDERED_FLASH_BASE		0xe8000000
-
-#define KATANA_BOOT_WINDOW_SIZE_ACTUAL		0x00800000 /* 8MB */
-#define KATANA_CPLD_SIZE_ACTUAL			0x00020000 /* 128KB */
-#define KATANA_SOCKETED_FLASH_SIZE_ACTUAL	0x00080000 /* 512KB */
-#define KATANA_SOLDERED_FLASH_SIZE_ACTUAL	0x02000000 /* 32MB */
-
-#define KATANA_BOOT_WINDOW_SIZE		max(MV64360_WINDOW_SIZE_MIN,	\
-		KATANA_BOOT_WINDOW_SIZE_ACTUAL)
-#define KATANA_CPLD_SIZE		max(MV64360_WINDOW_SIZE_MIN,	\
-		KATANA_CPLD_SIZE_ACTUAL)
-#define KATANA_SOCKETED_FLASH_SIZE	max(MV64360_WINDOW_SIZE_MIN,	\
-		KATANA_SOCKETED_FLASH_SIZE_ACTUAL)
-#define KATANA_SOLDERED_FLASH_SIZE	max(MV64360_WINDOW_SIZE_MIN,	\
-		KATANA_SOLDERED_FLASH_SIZE_ACTUAL)
+#define KATANA_SOCKETED_FLASH_SIZE		0x00100000 /* 1 MB */
+#define KATANA_SOLDERED_FLASH_BASE		0xe0000000
+#define KATANA_SOLDERED_FLASH_SIZE		0x10000000 /* 256 MB */
 
 #define KATANA_PCI1_MEM_START_PROC_ADDR         0x80000000
 #define KATANA_PCI1_MEM_START_PCI_HI_ADDR       0x00000000
 #define KATANA_PCI1_MEM_START_PCI_LO_ADDR       0x80000000
-#define KATANA_PCI1_MEM_SIZE                    0x40000000
+#define KATANA_PCI1_MEM_SIZE                    0x40000000 /* 1 GB */
 #define KATANA_PCI1_IO_START_PROC_ADDR          0xc0000000
 #define KATANA_PCI1_IO_START_PCI_ADDR           0x00000000
-#define KATANA_PCI1_IO_SIZE                     0x01000000
+#define KATANA_PCI1_IO_SIZE                     0x04000000 /* 64 MB */
 
 /* Board-specific IRQ info */
 #define  KATANA_PCI_INTA_IRQ_3750		64+8
@@ -138,6 +126,8 @@
 #define HSL_PLD_J4SGA_REG_OFF			0
 #define HSL_PLD_J4GA_REG_OFF			1
 #define HSL_PLD_J2GA_REG_OFF			2
+#define HSL_PLD_HOT_SWAP_OFF			6
+#define HSL_PLD_HOT_SWAP_LED_BIT		0x1
 #define GA_MASK					0x1f
 #define HSL_PLD_SIZE				0x1000
 #define K3750_GPP_GEO_ADDR_PINS			0xf8000000
@@ -162,7 +152,8 @@
 
 #define	KATANA_DEFAULT_BAUD			9600
 #define	KATANA_MPSC_CLK_SRC			8	  /* TCLK */
-#define	KATANA_MPSC_CLK_FREQ			133333333 /* 133.3333... MHz */
+
+#define	KATANA_MTD_MONITOR_SIZE			(1 << 20) /* 1 MB */
 
 #define	KATANA_ETH0_PHY_ADDR			12
 #define	KATANA_ETH1_PHY_ADDR			11
diff -Nru a/arch/ppc/platforms/pmac_cpufreq.c b/arch/ppc/platforms/pmac_cpufreq.c
--- a/arch/ppc/platforms/pmac_cpufreq.c	2005-03-11 12:51:47 -08:00
+++ b/arch/ppc/platforms/pmac_cpufreq.c	2005-03-11 12:51:47 -08:00
@@ -230,7 +230,7 @@
 	enable_kernel_fp();
 
 #ifdef CONFIG_ALTIVEC
-	if (cur_cpu_spec[0]->cpu_features & CPU_FTR_ALTIVEC)
+	if (cpu_has_feature(CPU_FTR_ALTIVEC))
 		enable_kernel_altivec();
 #endif /* CONFIG_ALTIVEC */
 
diff -Nru a/arch/ppc/platforms/pmac_setup.c b/arch/ppc/platforms/pmac_setup.c
--- a/arch/ppc/platforms/pmac_setup.c	2005-03-11 12:51:47 -08:00
+++ b/arch/ppc/platforms/pmac_setup.c	2005-03-11 12:51:47 -08:00
@@ -274,7 +274,7 @@
 	pmac_find_bridges();
 
 	/* Checks "l2cr-value" property in the registry */
-	if (cur_cpu_spec[0]->cpu_features & CPU_FTR_L2CR) {
+	if (cpu_has_feature(CPU_FTR_L2CR)) {
 		struct device_node *np = find_devices("cpus");
 		if (np == 0)
 			np = find_type_devices("cpu");
diff -Nru a/arch/ppc/platforms/pmac_smp.c b/arch/ppc/platforms/pmac_smp.c
--- a/arch/ppc/platforms/pmac_smp.c	2005-03-11 12:51:46 -08:00
+++ b/arch/ppc/platforms/pmac_smp.c	2005-03-11 12:51:46 -08:00
@@ -119,7 +119,7 @@
 
 static void __init core99_init_caches(int cpu)
 {
-	if (!(cur_cpu_spec[0]->cpu_features & CPU_FTR_L2CR))
+	if (!cpu_has_feature(CPU_FTR_L2CR))
 		return;
 
 	if (cpu == 0) {
@@ -132,7 +132,7 @@
 		printk("CPU%d: L2CR set to %lx\n", cpu, core99_l2_cache);
 	}
 
-	if (!(cur_cpu_spec[0]->cpu_features & CPU_FTR_L3CR))
+	if (!cpu_has_feature(CPU_FTR_L3CR))
 		return;
 
 	if (cpu == 0){
diff -Nru a/arch/ppc/platforms/radstone_ppc7d.c b/arch/ppc/platforms/radstone_ppc7d.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/ppc/platforms/radstone_ppc7d.c	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,1408 @@
+/*
+ * arch/ppc/platforms/radstone_ppc7d.c
+ *
+ * Board setup routines for the Radstone PPC7D boards.
+ *
+ * Author: James Chapman <jchapman@katalix.com>
+ *
+ * Based on code done by Rabeeh Khoury - rabeeh@galileo.co.il
+ * Based on code done by - Mark A. Greer <mgreer@mvista.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+/* Radstone PPC7D boards are rugged VME boards with PPC 7447A CPUs,
+ * Discovery-II, dual gigabit ethernet, dual PMC, USB, keyboard/mouse,
+ * 4 serial ports, 2 high speed serial ports (MPSCs) and optional
+ * SCSI / VGA.
+ */
+
+#include <linux/config.h>
+#include <linux/stddef.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/reboot.h>
+#include <linux/pci.h>
+#include <linux/kdev_t.h>
+#include <linux/major.h>
+#include <linux/initrd.h>
+#include <linux/console.h>
+#include <linux/delay.h>
+#include <linux/irq.h>
+#include <linux/ide.h>
+#include <linux/seq_file.h>
+#include <linux/root_dev.h>
+#include <linux/serial.h>
+#include <linux/tty.h>		/* for linux/serial_core.h */
+#include <linux/serial_core.h>
+#include <linux/mv643xx.h>
+#include <linux/netdevice.h>
+
+#include <asm/system.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/time.h>
+#include <asm/dma.h>
+#include <asm/io.h>
+#include <asm/machdep.h>
+#include <asm/prom.h>
+#include <asm/smp.h>
+#include <asm/vga.h>
+#include <asm/open_pic.h>
+#include <asm/i8259.h>
+#include <asm/todc.h>
+#include <asm/bootinfo.h>
+#include <asm/mpc10x.h>
+#include <asm/pci-bridge.h>
+#include <asm/mv64x60.h>
+#include <asm/i8259.h>
+
+#include "radstone_ppc7d.h"
+
+#undef DEBUG
+
+#define PPC7D_RST_PIN			17 	/* GPP17 */
+
+extern u32 mv64360_irq_base;
+
+static struct mv64x60_handle bh;
+static int ppc7d_has_alma;
+
+extern void gen550_progress(char *, unsigned short);
+extern void gen550_init(int, struct uart_port *);
+
+/* residual data */
+unsigned char __res[sizeof(bd_t)];
+
+/*****************************************************************************
+ * Serial port code
+ *****************************************************************************/
+
+#if defined(CONFIG_KGDB) || defined(CONFIG_SERIAL_TEXT_DEBUG)
+static void __init ppc7d_early_serial_map(void)
+{
+#if defined(CONFIG_SERIAL_MPSC_CONSOLE)
+	mv64x60_progress_init(CONFIG_MV64X60_NEW_BASE);
+#elif defined(CONFIG_SERIAL_8250)
+	struct uart_port serial_req;
+
+	/* Setup serial port access */
+	memset(&serial_req, 0, sizeof(serial_req));
+	serial_req.uartclk = UART_CLK;
+	serial_req.irq = 4;
+	serial_req.flags = STD_COM_FLAGS;
+	serial_req.iotype = SERIAL_IO_MEM;
+	serial_req.membase = (u_char *) PPC7D_SERIAL_0;
+
+	gen550_init(0, &serial_req);
+	if (early_serial_setup(&serial_req) != 0)
+		printk(KERN_ERR "Early serial init of port 0 failed\n");
+
+	/* Assume early_serial_setup() doesn't modify serial_req */
+	serial_req.line = 1;
+	serial_req.irq = 3;
+	serial_req.membase = (u_char *) PPC7D_SERIAL_1;
+
+	gen550_init(1, &serial_req);
+	if (early_serial_setup(&serial_req) != 0)
+		printk(KERN_ERR "Early serial init of port 1 failed\n");
+#else
+#error CONFIG_KGDB || CONFIG_SERIAL_TEXT_DEBUG has no supported CONFIG_SERIAL_XXX
+#endif
+}
+#endif /* CONFIG_KGDB || CONFIG_SERIAL_TEXT_DEBUG */
+
+/*****************************************************************************
+ * Low-level board support code
+ *****************************************************************************/
+
+static unsigned long __init ppc7d_find_end_of_memory(void)
+{
+	bd_t *bp = (bd_t *) __res;
+
+	if (bp->bi_memsize)
+		return bp->bi_memsize;
+
+	return (256 * 1024 * 1024);
+}
+
+static void __init ppc7d_map_io(void)
+{
+	/* remove temporary mapping */
+	mtspr(SPRN_DBAT3U, 0x00000000);
+	mtspr(SPRN_DBAT3L, 0x00000000);
+
+	io_block_mapping(0xe8000000, 0xe8000000, 0x08000000, _PAGE_IO);
+	io_block_mapping(0xfe000000, 0xfe000000, 0x02000000, _PAGE_IO);
+}
+
+static void ppc7d_restart(char *cmd)
+{
+	u32 data;
+
+	/* Disable GPP17 interrupt */
+	data = mv64x60_read(&bh, MV64x60_GPP_INTR_MASK);
+	data &= ~(1 << PPC7D_RST_PIN);
+	mv64x60_write(&bh, MV64x60_GPP_INTR_MASK, data);
+
+	/* Configure MPP17 as GPP */
+	data = mv64x60_read(&bh, MV64x60_MPP_CNTL_2);
+	data &= ~(0x0000000f << 4);
+	mv64x60_write(&bh, MV64x60_MPP_CNTL_2, data);
+
+	/* Enable pin GPP17 for output */
+	data = mv64x60_read(&bh, MV64x60_GPP_IO_CNTL);
+	data |= (1 << PPC7D_RST_PIN);
+	mv64x60_write(&bh, MV64x60_GPP_IO_CNTL, data);
+
+	/* Toggle GPP9 pin to reset the board */
+	mv64x60_write(&bh, MV64x60_GPP_VALUE_CLR, 1 << PPC7D_RST_PIN);
+	mv64x60_write(&bh, MV64x60_GPP_VALUE_SET, 1 << PPC7D_RST_PIN);
+
+	for (;;) ;		/* Spin until reset happens */
+	/* NOTREACHED */
+}
+
+static void ppc7d_power_off(void)
+{
+	u32 data;
+
+	local_irq_disable();
+
+	/* Ensure that internal MV643XX watchdog is disabled.
+	 * The Disco watchdog uses MPP17 on this hardware.
+	 */
+	data = mv64x60_read(&bh, MV64x60_MPP_CNTL_2);
+	data &= ~(0x0000000f << 4);
+	mv64x60_write(&bh, MV64x60_MPP_CNTL_2, data);
+
+	data = mv64x60_read(&bh, MV64x60_WDT_WDC);
+	if (data & 0x80000000) {
+		mv64x60_write(&bh, MV64x60_WDT_WDC, 1 << 24);
+		mv64x60_write(&bh, MV64x60_WDT_WDC, 2 << 24);
+	}
+
+	for (;;) ;		/* No way to shut power off with software */
+	/* NOTREACHED */
+}
+
+static void ppc7d_halt(void)
+{
+	ppc7d_power_off();
+	/* NOTREACHED */
+}
+
+static unsigned long ppc7d_led_no_pulse;
+
+static int __init ppc7d_led_pulse_disable(char *str)
+{
+	ppc7d_led_no_pulse = 1;
+	return 1;
+}
+
+/* This kernel option disables the heartbeat pulsing of a board LED */
+__setup("ledoff", ppc7d_led_pulse_disable);
+
+static void ppc7d_heartbeat(void)
+{
+	u32 data32;
+	u8 data8;
+	static int max706_wdog = 0;
+
+	/* Unfortunately we can't access the LED control registers
+	 * during early init because they're on the CPLD which is the
+	 * other side of a PCI bridge which goes unreachable during
+	 * PCI scan. So write the LEDs only if the MV64360 watchdog is
+	 * enabled (i.e. userspace apps are running so kernel is up)..
+	 */
+	data32 = mv64x60_read(&bh, MV64x60_WDT_WDC);
+	if (data32 & 0x80000000) {
+		/* Enable MAX706 watchdog if not done already */
+		if (!max706_wdog) {
+			outb(3, PPC7D_CPLD_RESET);
+			max706_wdog = 1;
+		}
+
+		/* Hit the MAX706 watchdog */
+		outb(0, PPC7D_CPLD_WATCHDOG_TRIG);
+
+		/* Pulse LED DS219 if not disabled */
+		if (!ppc7d_led_no_pulse) {
+			static int led_on = 0;
+
+			data8 = inb(PPC7D_CPLD_LEDS);
+			if (led_on)
+				data8 &= ~PPC7D_CPLD_LEDS_DS219_MASK;
+			else
+				data8 |= PPC7D_CPLD_LEDS_DS219_MASK;
+
+			outb(data8, PPC7D_CPLD_LEDS);
+			led_on = !led_on;
+		}
+	}
+	ppc_md.heartbeat_count = ppc_md.heartbeat_reset;
+}
+
+static int ppc7d_show_cpuinfo(struct seq_file *m)
+{
+	u8 val;
+	u8 val1, val2;
+	static int flash_sizes[4] = { 64, 32, 0, 16 };
+	static int flash_banks[4] = { 4, 3, 2, 1 };
+	static char *pci_modes[] = { "PCI33", "PCI66",
+		"Unknown", "Unknown",
+		"PCIX33", "PCIX66",
+		"PCIX100", "PCIX133"
+	};
+
+	seq_printf(m, "vendor\t\t: Radstone Technology\n");
+	seq_printf(m, "machine\t\t: PPC7D\n");
+
+	val = inb(PPC7D_CPLD_BOARD_REVISION);
+	val1 = (val & PPC7D_CPLD_BOARD_REVISION_NUMBER_MASK) >> 5;
+	val2 = (val & PPC7D_CPLD_BOARD_REVISION_LETTER_MASK);
+	seq_printf(m, "revision\t: %hd%c%c\n",
+		   val1,
+		   (val2 <= 0x18) ? 'A' + val2 : 'Y',
+		   (val2 > 0x18) ? 'A' + (val2 - 0x19) : ' ');
+
+	val = inb(PPC7D_CPLD_MOTHERBOARD_TYPE);
+	val1 = val & PPC7D_CPLD_MB_TYPE_PLL_MASK;
+	val2 = val & (PPC7D_CPLD_MB_TYPE_ECC_FITTED_MASK |
+		      PPC7D_CPLD_MB_TYPE_ECC_ENABLE_MASK);
+	seq_printf(m, "bus speed\t: %dMHz\n",
+		   (val1 == PPC7D_CPLD_MB_TYPE_PLL_133) ? 133 :
+		   (val1 == PPC7D_CPLD_MB_TYPE_PLL_100) ? 100 :
+		   (val1 == PPC7D_CPLD_MB_TYPE_PLL_64) ? 64 : 0);
+
+	val = inb(PPC7D_CPLD_MEM_CONFIG_EXTEND);
+	val1 = val & PPC7D_CPLD_SDRAM_BANK_SIZE_MASK;
+	seq_printf(m, "SDRAM\t\t: %d%c",
+		   (val1 == PPC7D_CPLD_SDRAM_BANK_SIZE_128M) ? 128 :
+		   (val1 == PPC7D_CPLD_SDRAM_BANK_SIZE_256M) ? 256 :
+		   (val1 == PPC7D_CPLD_SDRAM_BANK_SIZE_512M) ? 512 : 1,
+		   (val1 == PPC7D_CPLD_SDRAM_BANK_SIZE_1G) ? 'G' : 'M');
+	if (val2 & PPC7D_CPLD_MB_TYPE_ECC_FITTED_MASK) {
+		seq_printf(m, " [ECC %sabled]",
+			   (val2 & PPC7D_CPLD_MB_TYPE_ECC_ENABLE_MASK) ? "en" :
+			   "dis");
+	}
+	seq_printf(m, "\n");
+
+	val1 = (val & PPC7D_CPLD_FLASH_DEV_SIZE_MASK);
+	val2 = (val & PPC7D_CPLD_FLASH_BANK_NUM_MASK) >> 2;
+	seq_printf(m, "FLASH\t\t: %d banks of %dM, total %dM\n",
+		   flash_banks[val2], flash_sizes[val1],
+		   flash_banks[val2] * flash_sizes[val1]);
+
+	val = inb(PPC7D_CPLD_FLASH_WRITE_CNTL);
+	val1 = inb(PPC7D_CPLD_SW_FLASH_WRITE_PROTECT);
+	seq_printf(m, "  write links\t: %s%s%s%s\n",
+		   (val & PPD7D_CPLD_FLASH_CNTL_WR_LINK_MASK) ? "WRITE " : "",
+		   (val & PPD7D_CPLD_FLASH_CNTL_BOOT_LINK_MASK) ? "BOOT " : "",
+		   (val & PPD7D_CPLD_FLASH_CNTL_USER_LINK_MASK) ? "USER " : "",
+		   (val & (PPD7D_CPLD_FLASH_CNTL_WR_LINK_MASK |
+			   PPD7D_CPLD_FLASH_CNTL_BOOT_LINK_MASK |
+			   PPD7D_CPLD_FLASH_CNTL_USER_LINK_MASK)) ==
+		   0 ? "NONE" : "");
+	seq_printf(m, "  write sector h/w enables: %s%s%s%s%s\n",
+		   (val & PPD7D_CPLD_FLASH_CNTL_RECO_WR_MASK) ? "RECOVERY " :
+		   "",
+		   (val & PPD7D_CPLD_FLASH_CNTL_BOOT_WR_MASK) ? "BOOT " : "",
+		   (val & PPD7D_CPLD_FLASH_CNTL_USER_WR_MASK) ? "USER " : "",
+		   (val1 & PPC7D_CPLD_FLASH_CNTL_NVRAM_PROT_MASK) ? "NVRAM " :
+		   "",
+		   (((val &
+		      (PPD7D_CPLD_FLASH_CNTL_RECO_WR_MASK |
+		       PPD7D_CPLD_FLASH_CNTL_BOOT_WR_MASK |
+		       PPD7D_CPLD_FLASH_CNTL_BOOT_WR_MASK)) == 0)
+		    && ((val1 & PPC7D_CPLD_FLASH_CNTL_NVRAM_PROT_MASK) ==
+			0)) ? "NONE" : "");
+	val1 =
+	    inb(PPC7D_CPLD_SW_FLASH_WRITE_PROTECT) &
+	    (PPC7D_CPLD_SW_FLASH_WRPROT_SYSBOOT_MASK |
+	     PPC7D_CPLD_SW_FLASH_WRPROT_USER_MASK);
+	seq_printf(m, "  software sector enables: %s%s%s\n",
+		   (val1 & PPC7D_CPLD_SW_FLASH_WRPROT_SYSBOOT_MASK) ? "SYSBOOT "
+		   : "",
+		   (val1 & PPC7D_CPLD_SW_FLASH_WRPROT_USER_MASK) ? "USER " : "",
+		   (val1 == 0) ? "NONE " : "");
+
+	seq_printf(m, "Boot options\t: %s%s%s%s\n",
+		   (val & PPC7D_CPLD_FLASH_CNTL_ALTBOOT_LINK_MASK) ?
+		   "ALTERNATE " : "",
+		   (val & PPC7D_CPLD_FLASH_CNTL_VMEBOOT_LINK_MASK) ? "VME " :
+		   "",
+		   (val & PPC7D_CPLD_FLASH_CNTL_RECBOOT_LINK_MASK) ? "RECOVERY "
+		   : "",
+		   ((val &
+		     (PPC7D_CPLD_FLASH_CNTL_ALTBOOT_LINK_MASK |
+		      PPC7D_CPLD_FLASH_CNTL_VMEBOOT_LINK_MASK |
+		      PPC7D_CPLD_FLASH_CNTL_RECBOOT_LINK_MASK)) ==
+		    0) ? "NONE" : "");
+
+	val = inb(PPC7D_CPLD_EQUIPMENT_PRESENT_1);
+	seq_printf(m, "Fitted modules\t: %s%s%s%s\n",
+		   (val & PPC7D_CPLD_EQPT_PRES_1_PMC1_MASK) ? "" : "PMC1 ",
+		   (val & PPC7D_CPLD_EQPT_PRES_1_PMC2_MASK) ? "" : "PMC2 ",
+		   (val & PPC7D_CPLD_EQPT_PRES_1_AFIX_MASK) ? "AFIX " : "",
+		   ((val & (PPC7D_CPLD_EQPT_PRES_1_PMC1_MASK |
+			    PPC7D_CPLD_EQPT_PRES_1_PMC2_MASK |
+			    PPC7D_CPLD_EQPT_PRES_1_AFIX_MASK)) ==
+		    (PPC7D_CPLD_EQPT_PRES_1_PMC1_MASK |
+		     PPC7D_CPLD_EQPT_PRES_1_PMC2_MASK)) ? "NONE" : "");
+
+	if (val & PPC7D_CPLD_EQPT_PRES_1_AFIX_MASK) {
+		static const char *ids[] = {
+			"unknown",
+			"1553 (Dual Channel)",
+			"1553 (Single Channel)",
+			"8-bit SCSI + VGA",
+			"16-bit SCSI + VGA",
+			"1553 (Single Channel with sideband)",
+			"1553 (Dual Channel with sideband)",
+			NULL
+		};
+		u8 id = __raw_readb((void *)PPC7D_AFIX_REG_BASE + 0x03);
+		seq_printf(m, "AFIX module\t: 0x%hx [%s]\n", id,
+			   id < 7 ? ids[id] : "unknown");
+	}
+
+	val = inb(PPC7D_CPLD_PCI_CONFIG);
+	val1 = (val & PPC7D_CPLD_PCI_CONFIG_PCI0_MASK) >> 4;
+	val2 = (val & PPC7D_CPLD_PCI_CONFIG_PCI1_MASK);
+	seq_printf(m, "PCI#0\t\t: %s\nPCI#1\t\t: %s\n",
+		   pci_modes[val1], pci_modes[val2]);
+
+	val = inb(PPC7D_CPLD_EQUIPMENT_PRESENT_2);
+	seq_printf(m, "PMC1\t\t: %s\nPMC2\t\t: %s\n",
+		   (val & PPC7D_CPLD_EQPT_PRES_3_PMC1_V_MASK) ? "3.3v" : "5v",
+		   (val & PPC7D_CPLD_EQPT_PRES_3_PMC2_V_MASK) ? "3.3v" : "5v");
+	seq_printf(m, "PMC power source: %s\n",
+		   (val & PPC7D_CPLD_EQPT_PRES_3_PMC_POWER_MASK) ? "VME" :
+		   "internal");
+
+	val = inb(PPC7D_CPLD_EQUIPMENT_PRESENT_4);
+	val2 = inb(PPC7D_CPLD_EQUIPMENT_PRESENT_2);
+	seq_printf(m, "Fit options\t: %s%s%s%s%s%s%s\n",
+		   (val & PPC7D_CPLD_EQPT_PRES_4_LPT_MASK) ? "LPT " : "",
+		   (val & PPC7D_CPLD_EQPT_PRES_4_PS2_FITTED) ? "PS2 " : "",
+		   (val & PPC7D_CPLD_EQPT_PRES_4_USB2_FITTED) ? "USB2 " : "",
+		   (val2 & PPC7D_CPLD_EQPT_PRES_2_UNIVERSE_MASK) ? "VME " : "",
+		   (val2 & PPC7D_CPLD_EQPT_PRES_2_COM36_MASK) ? "COM3-6 " : "",
+		   (val2 & PPC7D_CPLD_EQPT_PRES_2_GIGE_MASK) ? "eth0 " : "",
+		   (val2 & PPC7D_CPLD_EQPT_PRES_2_DUALGIGE_MASK) ? "eth1 " :
+		   "");
+
+	val = inb(PPC7D_CPLD_ID_LINK);
+	val1 = val & (PPC7D_CPLD_ID_LINK_E6_MASK |
+		      PPC7D_CPLD_ID_LINK_E7_MASK |
+		      PPC7D_CPLD_ID_LINK_E12_MASK |
+		      PPC7D_CPLD_ID_LINK_E13_MASK);
+
+	val = inb(PPC7D_CPLD_FLASH_WRITE_CNTL) &
+	    (PPD7D_CPLD_FLASH_CNTL_WR_LINK_MASK |
+	     PPD7D_CPLD_FLASH_CNTL_BOOT_LINK_MASK |
+	     PPD7D_CPLD_FLASH_CNTL_USER_LINK_MASK);
+
+	seq_printf(m, "Board links present: %s%s%s%s%s%s%s%s\n",
+		   (val1 & PPC7D_CPLD_ID_LINK_E6_MASK) ? "E6 " : "",
+		   (val1 & PPC7D_CPLD_ID_LINK_E7_MASK) ? "E7 " : "",
+		   (val & PPD7D_CPLD_FLASH_CNTL_WR_LINK_MASK) ? "E9 " : "",
+		   (val & PPD7D_CPLD_FLASH_CNTL_BOOT_LINK_MASK) ? "E10 " : "",
+		   (val & PPD7D_CPLD_FLASH_CNTL_USER_LINK_MASK) ? "E11 " : "",
+		   (val1 & PPC7D_CPLD_ID_LINK_E12_MASK) ? "E12 " : "",
+		   (val1 & PPC7D_CPLD_ID_LINK_E13_MASK) ? "E13 " : "",
+		   ((val == 0) && (val1 == 0)) ? "NONE" : "");
+
+	val = inb(PPC7D_CPLD_WDOG_RESETSW_MASK);
+	seq_printf(m, "Front panel reset switch: %sabled\n",
+		   (val & PPC7D_CPLD_WDOG_RESETSW_MASK) ? "dis" : "en");
+
+	return 0;
+}
+
+static void __init ppc7d_calibrate_decr(void)
+{
+	ulong freq;
+
+	freq = 100000000 / 4;
+
+	pr_debug("time_init: decrementer frequency = %lu.%.6lu MHz\n",
+		 freq / 1000000, freq % 1000000);
+
+	tb_ticks_per_jiffy = freq / HZ;
+	tb_to_us = mulhwu_scale_factor(freq, 1000000);
+}
+
+/*****************************************************************************
+ * Interrupt stuff
+ *****************************************************************************/
+
+static irqreturn_t ppc7d_i8259_intr(int irq, void *dev_id, struct pt_regs *regs)
+{
+	u32 temp = mv64x60_read(&bh, MV64x60_GPP_INTR_CAUSE);
+	if (temp & (1 << 28)) {
+		i8259_irq(regs);
+		mv64x60_write(&bh, MV64x60_GPP_INTR_CAUSE, temp & (~(1 << 28)));
+		return IRQ_HANDLED;
+	}
+
+	return IRQ_NONE;
+}
+
+/*
+ * Each interrupt cause is assigned an IRQ number.
+ * Southbridge has 16*2 (two 8259's) interrupts.
+ * Discovery-II has 96 interrupts (cause-hi, cause-lo, gpp x 32).
+ * If multiple interrupts are pending, get_irq() returns the
+ * lowest pending irq number first.
+ *
+ *
+ * IRQ #   Source                              Trig   Active
+ * =============================================================
+ *
+ * Southbridge
+ * -----------
+ * IRQ #   Source                              Trig
+ * =============================================================
+ * 0       ISA High Resolution Counter         Edge
+ * 1       Keyboard                            Edge
+ * 2       Cascade From (IRQ 8-15)             Edge
+ * 3       Com 2 (Uart 2)                      Edge
+ * 4       Com 1 (Uart 1)                      Edge
+ * 5       PCI Int D/AFIX IRQZ ID4 (2,7)       Level
+ * 6       GPIO                                Level
+ * 7       LPT                                 Edge
+ * 8       RTC Alarm                           Edge
+ * 9       PCI Int A/PMC 2/AFIX IRQW ID1 (2,0) Level
+ * 10      PCI Int B/PMC 1/AFIX IRQX ID2 (2,1) Level
+ * 11      USB2                                Level
+ * 12      Mouse                               Edge
+ * 13      Reserved internally by Ali M1535+
+ * 14      PCI Int C/VME/AFIX IRQY ID3 (2,6)   Level
+ * 15      COM 5/6                             Level
+ *
+ * 16..112 Discovery-II...
+ *
+ * MPP28   Southbridge                         Edge   High
+ *
+ *
+ * Interrupts are cascaded through to the Discovery-II.
+ *
+ *  PCI ---
+ *         \
+ * CPLD --> ALI1535 -------> DISCOVERY-II
+ *        INTF           MPP28
+ */
+static void __init ppc7d_init_irq(void)
+{
+	int irq;
+
+	pr_debug("%s\n", __FUNCTION__);
+	i8259_init(0);
+	mv64360_init_irq();
+
+	/* IRQ 0..15 are handled by the cascaded 8259's of the Ali1535 */
+	for (irq = 0; irq < 16; irq++) {
+		irq_desc[irq].handler = &i8259_pic;
+	}
+	/* IRQs 5,6,9,10,11,14,15 are level sensitive */
+	irq_desc[5].status |= IRQ_LEVEL;
+	irq_desc[6].status |= IRQ_LEVEL;
+	irq_desc[9].status |= IRQ_LEVEL;
+	irq_desc[10].status |= IRQ_LEVEL;
+	irq_desc[11].status |= IRQ_LEVEL;
+	irq_desc[14].status |= IRQ_LEVEL;
+	irq_desc[15].status |= IRQ_LEVEL;
+
+	/* GPP28 is edge triggered */
+	irq_desc[mv64360_irq_base + MV64x60_IRQ_GPP28].status &= ~IRQ_LEVEL;
+}
+
+static u32 ppc7d_irq_canonicalize(u32 irq)
+{
+	if ((irq >= 16) && (irq < (16 + 96)))
+		irq -= 16;
+
+	return irq;
+}
+
+static int ppc7d_get_irq(struct pt_regs *regs)
+{
+	int irq;
+
+	irq = mv64360_get_irq(regs);
+	if (irq == (mv64360_irq_base + MV64x60_IRQ_GPP28))
+		irq = i8259_irq(regs);
+	return irq;
+}
+
+/*
+ * 9       PCI Int A/PMC 2/AFIX IRQW ID1 (2,0) Level
+ * 10      PCI Int B/PMC 1/AFIX IRQX ID2 (2,1) Level
+ * 14      PCI Int C/VME/AFIX IRQY ID3 (2,6)   Level
+ * 5       PCI Int D/AFIX IRQZ ID4 (2,7)       Level
+ */
+static int __init ppc7d_map_irq(struct pci_dev *dev, unsigned char idsel,
+				unsigned char pin)
+{
+	static const char pci_irq_table[][4] =
+	    /*
+	     *      PCI IDSEL/INTPIN->INTLINE
+	     *         A   B   C   D
+	     */
+	{
+		{10, 14, 5, 9},	/* IDSEL 10 - PMC2 / AFIX IRQW */
+		{9, 10, 14, 5},	/* IDSEL 11 - PMC1 / AFIX IRQX */
+		{5, 9, 10, 14},	/* IDSEL 12 - AFIX IRQY */
+		{14, 5, 9, 10},	/* IDSEL 13 - AFIX IRQZ */
+	};
+	const long min_idsel = 10, max_idsel = 14, irqs_per_slot = 4;
+
+	pr_debug("%s: %04x/%04x/%x: idsel=%hx pin=%hu\n", __FUNCTION__,
+		 dev->vendor, dev->device, PCI_FUNC(dev->devfn), idsel, pin);
+
+	return PCI_IRQ_TABLE_LOOKUP;
+}
+
+void __init ppc7d_intr_setup(void)
+{
+	u32 data;
+
+	/*
+	 * Define GPP 28 interrupt polarity as active high
+	 * input signal and level triggered
+	 */
+	data = mv64x60_read(&bh, MV64x60_GPP_LEVEL_CNTL);
+	data &= ~(1 << 28);
+	mv64x60_write(&bh, MV64x60_GPP_LEVEL_CNTL, data);
+	data = mv64x60_read(&bh, MV64x60_GPP_IO_CNTL);
+	data &= ~(1 << 28);
+	mv64x60_write(&bh, MV64x60_GPP_IO_CNTL, data);
+
+	/* Config GPP intr ctlr to respond to level trigger */
+	data = mv64x60_read(&bh, MV64x60_COMM_ARBITER_CNTL);
+	data |= (1 << 10);
+	mv64x60_write(&bh, MV64x60_COMM_ARBITER_CNTL, data);
+
+	/* XXXX Erranum FEr PCI-#8 */
+	data = mv64x60_read(&bh, MV64x60_PCI0_CMD);
+	data &= ~((1 << 5) | (1 << 9));
+	mv64x60_write(&bh, MV64x60_PCI0_CMD, data);
+	data = mv64x60_read(&bh, MV64x60_PCI1_CMD);
+	data &= ~((1 << 5) | (1 << 9));
+	mv64x60_write(&bh, MV64x60_PCI1_CMD, data);
+
+	/*
+	 * Dismiss and then enable interrupt on GPP interrupt cause
+	 * for CPU #0
+	 */
+	mv64x60_write(&bh, MV64x60_GPP_INTR_CAUSE, ~(1 << 28));
+	data = mv64x60_read(&bh, MV64x60_GPP_INTR_MASK);
+	data |= (1 << 28);
+	mv64x60_write(&bh, MV64x60_GPP_INTR_MASK, data);
+
+	/*
+	 * Dismiss and then enable interrupt on CPU #0 high cause reg
+	 * BIT27 summarizes GPP interrupts 23-31
+	 */
+	mv64x60_write(&bh, MV64360_IC_MAIN_CAUSE_HI, ~(1 << 27));
+	data = mv64x60_read(&bh, MV64360_IC_CPU0_INTR_MASK_HI);
+	data |= (1 << 27);
+	mv64x60_write(&bh, MV64360_IC_CPU0_INTR_MASK_HI, data);
+}
+
+/*****************************************************************************
+ * Platform device data fixup routines.
+ *****************************************************************************/
+
+#if defined(CONFIG_SERIAL_MPSC)
+static void __init ppc7d_fixup_mpsc_pdata(struct platform_device *pdev)
+{
+	struct mpsc_pdata *pdata;
+
+	pdata = (struct mpsc_pdata *)pdev->dev.platform_data;
+
+	pdata->max_idle = 40;
+	pdata->default_baud = PPC7D_DEFAULT_BAUD;
+	pdata->brg_clk_src = PPC7D_MPSC_CLK_SRC;
+	pdata->brg_clk_freq = PPC7D_MPSC_CLK_FREQ;
+
+	return;
+}
+#endif
+
+#if defined(CONFIG_MV643XX_ETH)
+static void __init ppc7d_fixup_eth_pdata(struct platform_device *pdev)
+{
+	struct mv643xx_eth_platform_data *eth_pd;
+	static u16 phy_addr[] = {
+		PPC7D_ETH0_PHY_ADDR,
+		PPC7D_ETH1_PHY_ADDR,
+		PPC7D_ETH2_PHY_ADDR,
+	};
+	int i;
+
+	eth_pd = pdev->dev.platform_data;
+	eth_pd->force_phy_addr = 1;
+	eth_pd->phy_addr = phy_addr[pdev->id];
+	eth_pd->tx_queue_size = PPC7D_ETH_TX_QUEUE_SIZE;
+	eth_pd->rx_queue_size = PPC7D_ETH_RX_QUEUE_SIZE;
+
+	/* Adjust IRQ by mv64360_irq_base */
+	for (i = 0; i < pdev->num_resources; i++) {
+		struct resource *r = &pdev->resource[i];
+
+		if (r->flags & IORESOURCE_IRQ) {
+			r->start += mv64360_irq_base;
+			r->end += mv64360_irq_base;
+			pr_debug("%s, uses IRQ %d\n", pdev->name,
+				 (int)r->start);
+		}
+	}
+
+}
+#endif
+
+static int __init ppc7d_platform_notify(struct device *dev)
+{
+	static struct {
+		char *bus_id;
+		void ((*rtn) (struct platform_device * pdev));
+	} dev_map[] = {
+#if defined(CONFIG_SERIAL_MPSC)
+		{ MPSC_CTLR_NAME "0", ppc7d_fixup_mpsc_pdata },
+		{ MPSC_CTLR_NAME "1", ppc7d_fixup_mpsc_pdata },
+#endif
+#if defined(CONFIG_MV643XX_ETH)
+		{ MV643XX_ETH_NAME "0", ppc7d_fixup_eth_pdata },
+		{ MV643XX_ETH_NAME "1", ppc7d_fixup_eth_pdata },
+		{ MV643XX_ETH_NAME "2", ppc7d_fixup_eth_pdata },
+#endif
+	};
+	struct platform_device *pdev;
+	int i;
+
+	if (dev && dev->bus_id)
+		for (i = 0; i < ARRAY_SIZE(dev_map); i++)
+			if (!strncmp(dev->bus_id, dev_map[i].bus_id,
+				     BUS_ID_SIZE)) {
+
+				pdev = container_of(dev,
+						    struct platform_device,
+						    dev);
+				dev_map[i].rtn(pdev);
+			}
+
+	return 0;
+}
+
+/*****************************************************************************
+ * PCI device fixups.
+ * These aren't really fixups per se. They are used to init devices as they
+ * are found during PCI scan.
+ *
+ * The PPC7D has an HB8 PCI-X bridge which must be set up during a PCI
+ * scan in order to find other devices on its secondary side.
+ *****************************************************************************/
+
+static void __init ppc7d_fixup_hb8(struct pci_dev *dev)
+{
+	u16 val16;
+
+	if (dev->bus->number == 0) {
+		pr_debug("PCI: HB8 init\n");
+
+		pci_write_config_byte(dev, 0x1c,
+				      ((PPC7D_PCI0_IO_START_PCI_ADDR & 0xf000)
+				       >> 8) | 0x01);
+		pci_write_config_byte(dev, 0x1d,
+				      (((PPC7D_PCI0_IO_START_PCI_ADDR +
+					 PPC7D_PCI0_IO_SIZE -
+					 1) & 0xf000) >> 8) | 0x01);
+		pci_write_config_word(dev, 0x30,
+				      PPC7D_PCI0_IO_START_PCI_ADDR >> 16);
+		pci_write_config_word(dev, 0x32,
+				      ((PPC7D_PCI0_IO_START_PCI_ADDR +
+					PPC7D_PCI0_IO_SIZE -
+					1) >> 16) & 0xffff);
+
+		pci_write_config_word(dev, 0x20,
+				      PPC7D_PCI0_MEM0_START_PCI_LO_ADDR >> 16);
+		pci_write_config_word(dev, 0x22,
+				      ((PPC7D_PCI0_MEM0_START_PCI_LO_ADDR +
+					PPC7D_PCI0_MEM0_SIZE -
+					1) >> 16) & 0xffff);
+		pci_write_config_word(dev, 0x24, 0);
+		pci_write_config_word(dev, 0x26, 0);
+		pci_write_config_dword(dev, 0x28, 0);
+		pci_write_config_dword(dev, 0x2c, 0);
+
+		pci_read_config_word(dev, 0x3e, &val16);
+		val16 |= ((1 << 5) | (1 << 1));	/* signal master aborts and
+						 * SERR to primary
+						 */
+		val16 &= ~(1 << 2);		/* ISA disable, so all ISA
+						 * ports forwarded to secondary
+						 */
+		pci_write_config_word(dev, 0x3e, val16);
+	}
+}
+
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_HINT, 0x0028, ppc7d_fixup_hb8);
+
+/* This should perhaps be a separate driver as we're actually initializing
+ * the chip for this board here. It's hardly a fixup...
+ */
+static void __init ppc7d_fixup_ali1535(struct pci_dev *dev)
+{
+	pr_debug("PCI: ALI1535 init\n");
+
+	if (dev->bus->number == 1) {
+		/* Configure the ISA Port Settings */
+		pci_write_config_byte(dev, 0x43, 0x00);
+
+		/* Disable PCI Interrupt polling mode */
+		pci_write_config_byte(dev, 0x45, 0x00);
+
+		/* Multifunction pin select INTFJ -> INTF */
+		pci_write_config_byte(dev, 0x78, 0x00);
+
+		/* Set PCI INT -> IRQ Routing control in for external
+		 * pins south bridge.
+		 */
+		pci_write_config_byte(dev, 0x48, 0x31);	/* [7-4] INT B -> IRQ10
+							 * [3-0] INT A -> IRQ9
+							 */
+		pci_write_config_byte(dev, 0x49, 0x5D);	/* [7-4] INT D -> IRQ5
+							 * [3-0] INT C -> IRQ14
+							 */
+
+		/* PPC7D setup */
+		/* NEC USB device on IRQ 11 (INTE) - INTF disabled */
+		pci_write_config_byte(dev, 0x4A, 0x09);
+
+		/* GPIO on IRQ 6 */
+		pci_write_config_byte(dev, 0x76, 0x07);
+
+		/* SIRQ I (COMS 5/6) use IRQ line 15.
+		 * Positive (not subtractive) address decode.
+		 */
+		pci_write_config_byte(dev, 0x44, 0x0f);
+
+		/* SIRQ II disabled */
+		pci_write_config_byte(dev, 0x75, 0x0);
+
+		/* On board USB and RTC disabled */
+		pci_write_config_word(dev, 0x52, (1 << 14));
+		pci_write_config_byte(dev, 0x74, 0x00);
+
+		/* On board IDE disabled */
+		pci_write_config_byte(dev, 0x58, 0x00);
+
+		/* Decode 32-bit addresses */
+		pci_write_config_byte(dev, 0x5b, 0);
+
+		/* Disable docking IO */
+		pci_write_config_word(dev, 0x5c, 0x0000);
+
+		/* Disable modem, enable sound */
+		pci_write_config_byte(dev, 0x77, (1 << 6));
+
+		/* Disable hot-docking mode */
+		pci_write_config_byte(dev, 0x7d, 0x00);
+	}
+}
+
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AL, 0x1533, ppc7d_fixup_ali1535);
+
+static int ppc7d_pci_exclude_device(u8 bus, u8 devfn)
+{
+	/* Early versions of this board were fitted with IBM ALMA
+	 * PCI-VME bridge chips. The PCI config space of these devices
+	 * was not set up correctly and causes PCI scan problems.
+	 */
+	if ((bus == 1) && (PCI_SLOT(devfn) == 4) && ppc7d_has_alma)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	return mv64x60_pci_exclude_device(bus, devfn);
+}
+
+/* This hook is called when each PCI bus is probed.
+ */
+static void ppc7d_pci_fixup_bus(struct pci_bus *bus)
+{
+	pr_debug("PCI BUS %hu: %lx/%lx %lx/%lx %lx/%lx %lx/%lx\n",
+		 bus->number,
+		 bus->resource[0] ? bus->resource[0]->start : 0,
+		 bus->resource[0] ? bus->resource[0]->end : 0,
+		 bus->resource[1] ? bus->resource[1]->start : 0,
+		 bus->resource[1] ? bus->resource[1]->end : 0,
+		 bus->resource[2] ? bus->resource[2]->start : 0,
+		 bus->resource[2] ? bus->resource[2]->end : 0,
+		 bus->resource[3] ? bus->resource[3]->start : 0,
+		 bus->resource[3] ? bus->resource[3]->end : 0);
+
+	if ((bus->number == 1) && (bus->resource[2] != NULL)) {
+		/* Hide PCI window 2 of Bus 1 which is used only to
+		 * map legacy ISA memory space.
+		 */
+		bus->resource[2]->start = 0;
+		bus->resource[2]->end = 0;
+		bus->resource[2]->flags = 0;
+	}
+}
+
+/*****************************************************************************
+ * Board device setup code
+ *****************************************************************************/
+
+void __init ppc7d_setup_peripherals(void)
+{
+	u32 val32;
+
+	/* Set up windows for boot CS */
+	mv64x60_set_32bit_window(&bh, MV64x60_CPU2BOOT_WIN,
+				 PPC7D_BOOT_WINDOW_BASE, PPC7D_BOOT_WINDOW_SIZE,
+				 0);
+	bh.ci->enable_window_32bit(&bh, MV64x60_CPU2BOOT_WIN);
+
+	/* Boot firmware configures the following DevCS addresses.
+	 * DevCS0 - board control/status
+	 * DevCS1 - test registers
+	 * DevCS2 - AFIX port/address registers (for identifying)
+	 * DevCS3 - FLASH
+	 *
+	 * We don't use DevCS0, DevCS1.
+	 */
+	val32 = mv64x60_read(&bh, MV64360_CPU_BAR_ENABLE);
+	val32 |= ((1 << 4) | (1 << 5));
+	mv64x60_write(&bh, MV64360_CPU_BAR_ENABLE, val32);
+	mv64x60_write(&bh, MV64x60_CPU2DEV_0_BASE, 0);
+	mv64x60_write(&bh, MV64x60_CPU2DEV_0_SIZE, 0);
+	mv64x60_write(&bh, MV64x60_CPU2DEV_1_BASE, 0);
+	mv64x60_write(&bh, MV64x60_CPU2DEV_1_SIZE, 0);
+
+	mv64x60_set_32bit_window(&bh, MV64x60_CPU2DEV_2_WIN,
+				 PPC7D_AFIX_REG_BASE, PPC7D_AFIX_REG_SIZE, 0);
+	bh.ci->enable_window_32bit(&bh, MV64x60_CPU2DEV_2_WIN);
+
+	mv64x60_set_32bit_window(&bh, MV64x60_CPU2DEV_3_WIN,
+				 PPC7D_FLASH_BASE, PPC7D_FLASH_SIZE_ACTUAL, 0);
+	bh.ci->enable_window_32bit(&bh, MV64x60_CPU2DEV_3_WIN);
+
+	mv64x60_set_32bit_window(&bh, MV64x60_CPU2SRAM_WIN,
+				 PPC7D_INTERNAL_SRAM_BASE, MV64360_SRAM_SIZE,
+				 0);
+	bh.ci->enable_window_32bit(&bh, MV64x60_CPU2SRAM_WIN);
+
+	/* Set up Enet->SRAM window */
+	mv64x60_set_32bit_window(&bh, MV64x60_ENET2MEM_4_WIN,
+				 PPC7D_INTERNAL_SRAM_BASE, MV64360_SRAM_SIZE,
+				 0x2);
+	bh.ci->enable_window_32bit(&bh, MV64x60_ENET2MEM_4_WIN);
+
+	/* Give enet r/w access to memory region */
+	val32 = mv64x60_read(&bh, MV64360_ENET2MEM_ACC_PROT_0);
+	val32 |= (0x3 << (4 << 1));
+	mv64x60_write(&bh, MV64360_ENET2MEM_ACC_PROT_0, val32);
+	val32 = mv64x60_read(&bh, MV64360_ENET2MEM_ACC_PROT_1);
+	val32 |= (0x3 << (4 << 1));
+	mv64x60_write(&bh, MV64360_ENET2MEM_ACC_PROT_1, val32);
+	val32 = mv64x60_read(&bh, MV64360_ENET2MEM_ACC_PROT_2);
+	val32 |= (0x3 << (4 << 1));
+	mv64x60_write(&bh, MV64360_ENET2MEM_ACC_PROT_2, val32);
+
+	val32 = mv64x60_read(&bh, MV64x60_TIMR_CNTR_0_3_CNTL);
+	val32 &= ~((1 << 0) | (1 << 8) | (1 << 16) | (1 << 24));
+	mv64x60_write(&bh, MV64x60_TIMR_CNTR_0_3_CNTL, val32);
+
+	/* Enumerate pci bus.
+	 *
+	 * We scan PCI#0 first (the bus with the HB8 and other
+	 * on-board peripherals). We must configure the 64360 before
+	 * each scan, according to the bus number assignments.  Busses
+	 * are assigned incrementally, starting at 0.  PCI#0 is
+	 * usually assigned bus#0, the secondary side of the HB8 gets
+	 * bus#1 and PCI#1 (second PMC site) gets bus#2.  However, if
+	 * any PMC card has a PCI bridge, these bus assignments will
+	 * change.
+	 */
+
+	/* Turn off PCI retries */
+	val32 = mv64x60_read(&bh, MV64x60_CPU_CONFIG);
+	val32 |= (1 << 17);
+	mv64x60_write(&bh, MV64x60_CPU_CONFIG, val32);
+
+	/* Scan PCI#0 */
+	mv64x60_set_bus(&bh, 0, 0);
+	bh.hose_a->first_busno = 0;
+	bh.hose_a->last_busno = 0xff;
+	bh.hose_a->last_busno = pciauto_bus_scan(bh.hose_a, 0);
+	printk(KERN_INFO "PCI#0: first=%d last=%d\n",
+	       bh.hose_a->first_busno, bh.hose_a->last_busno);
+
+	/* Scan PCI#1 */
+	bh.hose_b->first_busno = bh.hose_a->last_busno + 1;
+	mv64x60_set_bus(&bh, 1, bh.hose_b->first_busno);
+	bh.hose_b->last_busno = 0xff;
+	bh.hose_b->last_busno = pciauto_bus_scan(bh.hose_b,
+		bh.hose_b->first_busno);
+	printk(KERN_INFO "PCI#1: first=%d last=%d\n",
+	       bh.hose_b->first_busno, bh.hose_b->last_busno);
+
+	/* Turn on PCI retries */
+	val32 = mv64x60_read(&bh, MV64x60_CPU_CONFIG);
+	val32 &= ~(1 << 17);
+	mv64x60_write(&bh, MV64x60_CPU_CONFIG, val32);
+
+	/* Setup interrupts */
+	ppc7d_intr_setup();
+}
+
+static void __init ppc7d_setup_bridge(void)
+{
+	struct mv64x60_setup_info si;
+	int i;
+	u32 temp;
+
+	mv64360_irq_base = 16;	/* first 16 intrs are 2 x 8259's */
+
+	memset(&si, 0, sizeof(si));
+
+	si.phys_reg_base = CONFIG_MV64X60_NEW_BASE;
+
+	si.pci_0.enable_bus = 1;
+	si.pci_0.pci_io.cpu_base = PPC7D_PCI0_IO_START_PROC_ADDR;
+	si.pci_0.pci_io.pci_base_hi = 0;
+	si.pci_0.pci_io.pci_base_lo = PPC7D_PCI0_IO_START_PCI_ADDR;
+	si.pci_0.pci_io.size = PPC7D_PCI0_IO_SIZE;
+	si.pci_0.pci_io.swap = MV64x60_CPU2PCI_SWAP_NONE;
+	si.pci_0.pci_mem[0].cpu_base = PPC7D_PCI0_MEM0_START_PROC_ADDR;
+	si.pci_0.pci_mem[0].pci_base_hi = PPC7D_PCI0_MEM0_START_PCI_HI_ADDR;
+	si.pci_0.pci_mem[0].pci_base_lo = PPC7D_PCI0_MEM0_START_PCI_LO_ADDR;
+	si.pci_0.pci_mem[0].size = PPC7D_PCI0_MEM0_SIZE;
+	si.pci_0.pci_mem[0].swap = MV64x60_CPU2PCI_SWAP_NONE;
+	si.pci_0.pci_mem[1].cpu_base = PPC7D_PCI0_MEM1_START_PROC_ADDR;
+	si.pci_0.pci_mem[1].pci_base_hi = PPC7D_PCI0_MEM1_START_PCI_HI_ADDR;
+	si.pci_0.pci_mem[1].pci_base_lo = PPC7D_PCI0_MEM1_START_PCI_LO_ADDR;
+	si.pci_0.pci_mem[1].size = PPC7D_PCI0_MEM1_SIZE;
+	si.pci_0.pci_mem[1].swap = MV64x60_CPU2PCI_SWAP_NONE;
+	si.pci_0.pci_cmd_bits = 0;
+	si.pci_0.latency_timer = 0x80;
+
+	si.pci_1.enable_bus = 1;
+	si.pci_1.pci_io.cpu_base = PPC7D_PCI1_IO_START_PROC_ADDR;
+	si.pci_1.pci_io.pci_base_hi = 0;
+	si.pci_1.pci_io.pci_base_lo = PPC7D_PCI1_IO_START_PCI_ADDR;
+	si.pci_1.pci_io.size = PPC7D_PCI1_IO_SIZE;
+	si.pci_1.pci_io.swap = MV64x60_CPU2PCI_SWAP_NONE;
+	si.pci_1.pci_mem[0].cpu_base = PPC7D_PCI1_MEM0_START_PROC_ADDR;
+	si.pci_1.pci_mem[0].pci_base_hi = PPC7D_PCI1_MEM0_START_PCI_HI_ADDR;
+	si.pci_1.pci_mem[0].pci_base_lo = PPC7D_PCI1_MEM0_START_PCI_LO_ADDR;
+	si.pci_1.pci_mem[0].size = PPC7D_PCI1_MEM0_SIZE;
+	si.pci_1.pci_mem[0].swap = MV64x60_CPU2PCI_SWAP_NONE;
+	si.pci_1.pci_mem[1].cpu_base = PPC7D_PCI1_MEM1_START_PROC_ADDR;
+	si.pci_1.pci_mem[1].pci_base_hi = PPC7D_PCI1_MEM1_START_PCI_HI_ADDR;
+	si.pci_1.pci_mem[1].pci_base_lo = PPC7D_PCI1_MEM1_START_PCI_LO_ADDR;
+	si.pci_1.pci_mem[1].size = PPC7D_PCI1_MEM1_SIZE;
+	si.pci_1.pci_mem[1].swap = MV64x60_CPU2PCI_SWAP_NONE;
+	si.pci_1.pci_cmd_bits = 0;
+	si.pci_1.latency_timer = 0x80;
+
+	/* Don't clear the SRAM window since we use it for debug */
+	si.window_preserve_mask_32_lo = (1 << MV64x60_CPU2SRAM_WIN);
+
+	printk(KERN_INFO "PCI: MV64360 PCI#0 IO at %x, size %x\n",
+	       si.pci_0.pci_io.cpu_base, si.pci_0.pci_io.size);
+	printk(KERN_INFO "PCI: MV64360 PCI#1 IO at %x, size %x\n",
+	       si.pci_1.pci_io.cpu_base, si.pci_1.pci_io.size);
+
+	for (i = 0; i < MV64x60_CPU2MEM_WINDOWS; i++) {
+#if defined(CONFIG_NOT_COHERENT_CACHE)
+		si.cpu_prot_options[i] = 0;
+		si.enet_options[i] = MV64360_ENET2MEM_SNOOP_NONE;
+		si.mpsc_options[i] = MV64360_MPSC2MEM_SNOOP_NONE;
+		si.idma_options[i] = MV64360_IDMA2MEM_SNOOP_NONE;
+
+		si.pci_0.acc_cntl_options[i] =
+		    MV64360_PCI_ACC_CNTL_SNOOP_NONE |
+		    MV64360_PCI_ACC_CNTL_SWAP_NONE |
+		    MV64360_PCI_ACC_CNTL_MBURST_128_BYTES |
+		    MV64360_PCI_ACC_CNTL_RDSIZE_256_BYTES;
+
+		si.pci_1.acc_cntl_options[i] =
+		    MV64360_PCI_ACC_CNTL_SNOOP_NONE |
+		    MV64360_PCI_ACC_CNTL_SWAP_NONE |
+		    MV64360_PCI_ACC_CNTL_MBURST_128_BYTES |
+		    MV64360_PCI_ACC_CNTL_RDSIZE_256_BYTES;
+#else
+		si.cpu_prot_options[i] = 0;
+		/* All PPC7D hardware uses B0 or newer MV64360 silicon which
+		 * does not have snoop bugs.
+		 */
+		si.enet_options[i] = MV64360_ENET2MEM_SNOOP_WB;
+		si.mpsc_options[i] = MV64360_MPSC2MEM_SNOOP_WB;
+		si.idma_options[i] = MV64360_IDMA2MEM_SNOOP_WB;
+
+		si.pci_0.acc_cntl_options[i] =
+		    MV64360_PCI_ACC_CNTL_SNOOP_WB |
+		    MV64360_PCI_ACC_CNTL_SWAP_NONE |
+		    MV64360_PCI_ACC_CNTL_MBURST_32_BYTES |
+		    MV64360_PCI_ACC_CNTL_RDSIZE_32_BYTES;
+
+		si.pci_1.acc_cntl_options[i] =
+		    MV64360_PCI_ACC_CNTL_SNOOP_WB |
+		    MV64360_PCI_ACC_CNTL_SWAP_NONE |
+		    MV64360_PCI_ACC_CNTL_MBURST_32_BYTES |
+		    MV64360_PCI_ACC_CNTL_RDSIZE_32_BYTES;
+#endif
+	}
+
+	/* Lookup PCI host bridges */
+	if (mv64x60_init(&bh, &si))
+		printk(KERN_ERR "MV64360 initialization failed.\n");
+
+	pr_debug("MV64360 regs @ %lx/%p\n", bh.p_base, bh.v_base);
+
+	/* Enable WB Cache coherency on SRAM */
+	temp = mv64x60_read(&bh, MV64360_SRAM_CONFIG);
+	pr_debug("SRAM_CONFIG: %x\n", temp);
+#if defined(CONFIG_NOT_COHERENT_CACHE)
+	mv64x60_write(&bh, MV64360_SRAM_CONFIG, temp & ~0x2);
+#else
+	mv64x60_write(&bh, MV64360_SRAM_CONFIG, temp | 0x2);
+#endif
+	/* If system operates with internal bus arbiter (CPU master
+	 * control bit8) clear AACK Delay bit [25] in CPU
+	 * configuration register.
+	 */
+	temp = mv64x60_read(&bh, MV64x60_CPU_MASTER_CNTL);
+	if (temp & (1 << 8)) {
+		temp = mv64x60_read(&bh, MV64x60_CPU_CONFIG);
+		mv64x60_write(&bh, MV64x60_CPU_CONFIG, (temp & ~(1 << 25)));
+	}
+
+	/* Data and address parity is enabled */
+	temp = mv64x60_read(&bh, MV64x60_CPU_CONFIG);
+	mv64x60_write(&bh, MV64x60_CPU_CONFIG,
+		      (temp | (1 << 26) | (1 << 19)));
+
+	pci_dram_offset = 0;	/* sys mem at same addr on PCI & cpu bus */
+	ppc_md.pci_swizzle = common_swizzle;
+	ppc_md.pci_map_irq = ppc7d_map_irq;
+	ppc_md.pci_exclude_device = ppc7d_pci_exclude_device;
+
+	mv64x60_set_bus(&bh, 0, 0);
+	bh.hose_a->first_busno = 0;
+	bh.hose_a->last_busno = 0xff;
+	bh.hose_a->mem_space.start = PPC7D_PCI0_MEM0_START_PCI_LO_ADDR;
+	bh.hose_a->mem_space.end =
+	    PPC7D_PCI0_MEM0_START_PCI_LO_ADDR + PPC7D_PCI0_MEM0_SIZE;
+
+	/* These will be set later, as a result of PCI0 scan */
+	bh.hose_b->first_busno = 0;
+	bh.hose_b->last_busno = 0xff;
+	bh.hose_b->mem_space.start = PPC7D_PCI1_MEM0_START_PCI_LO_ADDR;
+	bh.hose_b->mem_space.end =
+	    PPC7D_PCI1_MEM0_START_PCI_LO_ADDR + PPC7D_PCI1_MEM0_SIZE;
+
+	pr_debug("MV64360: PCI#0 IO decode %08x/%08x IO remap %08x\n",
+		 mv64x60_read(&bh, 0x48), mv64x60_read(&bh, 0x50),
+		 mv64x60_read(&bh, 0xf0));
+}
+
+static void __init ppc7d_setup_arch(void)
+{
+	int port;
+
+	loops_per_jiffy = 100000000 / HZ;
+
+#ifdef CONFIG_BLK_DEV_INITRD
+	if (initrd_start)
+		ROOT_DEV = Root_RAM0;
+	else
+#endif
+#ifdef	CONFIG_ROOT_NFS
+		ROOT_DEV = Root_NFS;
+#else
+		ROOT_DEV = Root_HDA1;
+#endif
+
+	if ((cur_cpu_spec[0]->cpu_features & CPU_FTR_SPEC7450) ||
+	    (cur_cpu_spec[0]->cpu_features & CPU_FTR_L3CR))
+		/* 745x is different.  We only want to pass along enable. */
+		_set_L2CR(L2CR_L2E);
+	else if (cur_cpu_spec[0]->cpu_features & CPU_FTR_L2CR)
+		/* All modules have 1MB of L2.  We also assume that an
+		 * L2 divisor of 3 will work.
+		 */
+		_set_L2CR(L2CR_L2E | L2CR_L2SIZ_1MB | L2CR_L2CLK_DIV3
+			  | L2CR_L2RAM_PIPE | L2CR_L2OH_1_0 | L2CR_L2DF);
+
+	if (cur_cpu_spec[0]->cpu_features & CPU_FTR_L3CR)
+		/* No L3 cache */
+		_set_L3CR(0);
+
+#ifdef CONFIG_DUMMY_CONSOLE
+	conswitchp = &dummy_con;
+#endif
+
+	/* Lookup PCI host bridges */
+	if (ppc_md.progress)
+		ppc_md.progress("ppc7d_setup_arch: calling setup_bridge", 0);
+
+	ppc7d_setup_bridge();
+	ppc7d_setup_peripherals();
+
+	/* Disable ethernet. It might have been setup by the bootrom */
+	for (port = 0; port < 3; port++)
+		mv64x60_write(&bh, MV64340_ETH_RECEIVE_QUEUE_COMMAND_REG(port),
+			      0x0000ff00);
+
+	/* Clear queue pointers to ensure they are all initialized,
+	 * otherwise since queues 1-7 are unused, they have random
+	 * pointers which look strange in register dumps. Don't bother
+	 * with queue 0 since it will be initialized later.
+	 */
+	for (port = 0; port < 3; port++) {
+		mv64x60_write(&bh,
+			      MV64340_ETH_RX_CURRENT_QUEUE_DESC_PTR_1(port),
+			      0x00000000);
+		mv64x60_write(&bh,
+			      MV64340_ETH_RX_CURRENT_QUEUE_DESC_PTR_2(port),
+			      0x00000000);
+		mv64x60_write(&bh,
+			      MV64340_ETH_RX_CURRENT_QUEUE_DESC_PTR_3(port),
+			      0x00000000);
+		mv64x60_write(&bh,
+			      MV64340_ETH_RX_CURRENT_QUEUE_DESC_PTR_4(port),
+			      0x00000000);
+		mv64x60_write(&bh,
+			      MV64340_ETH_RX_CURRENT_QUEUE_DESC_PTR_5(port),
+			      0x00000000);
+		mv64x60_write(&bh,
+			      MV64340_ETH_RX_CURRENT_QUEUE_DESC_PTR_6(port),
+			      0x00000000);
+		mv64x60_write(&bh,
+			      MV64340_ETH_RX_CURRENT_QUEUE_DESC_PTR_7(port),
+			      0x00000000);
+	}
+
+	printk(KERN_INFO "Radstone Technology PPC7D\n");
+	if (ppc_md.progress)
+		ppc_md.progress("ppc7d_setup_arch: exit", 0);
+}
+
+/* This kernel command line parameter can be used to have the target
+ * wait for a JTAG debugger to attach. Of course, a JTAG debugger
+ * with hardware breakpoint support can have the target stop at any
+ * location during init, but this is a convenience feature that makes
+ * it easier in the common case of loading the code using the ppcboot
+ * bootloader..
+ */
+static unsigned long ppc7d_wait_debugger;
+
+static int __init ppc7d_waitdbg(char *str)
+{
+	ppc7d_wait_debugger = 1;
+	return 1;
+}
+
+__setup("waitdbg", ppc7d_waitdbg);
+
+/* Second phase board init, called after other (architecture common)
+ * low-level services have been initialized.
+ */
+static void ppc7d_init2(void)
+{
+	unsigned long flags;
+	u32 data;
+	u8 data8;
+
+	pr_debug("%s: enter\n", __FUNCTION__);
+
+	/* Wait for debugger? */
+	if (ppc7d_wait_debugger) {
+		printk("Waiting for debugger...\n");
+
+		while (readl(&ppc7d_wait_debugger)) ;
+	}
+
+	/* Hook up i8259 interrupt which is connected to GPP28 */
+	request_irq(mv64360_irq_base + MV64x60_IRQ_GPP28, ppc7d_i8259_intr,
+		    SA_INTERRUPT, "I8259 (GPP28) interrupt", (void *)0);
+
+	/* Configure MPP16 as watchdog NMI, MPP17 as watchdog WDE */
+	spin_lock_irqsave(&mv64x60_lock, flags);
+	data = mv64x60_read(&bh, MV64x60_MPP_CNTL_2);
+	data &= ~(0x0000000f << 0);
+	data |= (0x00000004 << 0);
+	data &= ~(0x0000000f << 4);
+	data |= (0x00000004 << 4);
+	mv64x60_write(&bh, MV64x60_MPP_CNTL_2, data);
+	spin_unlock_irqrestore(&mv64x60_lock, flags);
+
+	/* All LEDs off */
+	data8 = inb(PPC7D_CPLD_LEDS);
+	data8 &= ~0x08;
+	data8 |= 0x07;
+	outb(data8, PPC7D_CPLD_LEDS);
+
+	pr_debug("%s: exit\n", __FUNCTION__);
+}
+
+/* Called from machine_init(), early, before any of the __init functions
+ * have run. We must init software-configurable pins before other functions
+ * such as interrupt controllers are initialised.
+ */
+void __init platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
+			  unsigned long r6, unsigned long r7)
+{
+	u8 val8;
+	u8 rev_num;
+
+	/* Map 0xe0000000-0xffffffff early because we need access to SRAM
+	 * and the ISA memory space (for serial port) here. This mapping
+	 * is redone properly in ppc7d_map_io() later.
+	 */
+	mtspr(SPRN_DBAT3U, 0xe0003fff);
+	mtspr(SPRN_DBAT3L, 0xe000002a);
+
+	/*
+	 * Zero SRAM. Note that this generates parity errors on
+	 * internal data path in SRAM if it's first time accessing it
+	 * after reset.
+	 *
+	 * We do this ASAP to avoid parity errors when reading
+	 * uninitialized SRAM.
+	 */
+	memset((void *)PPC7D_INTERNAL_SRAM_BASE, 0, MV64360_SRAM_SIZE);
+
+	pr_debug("platform_init: r3-r7: %lx %lx %lx %lx %lx\n",
+		 r3, r4, r5, r6, r7);
+
+	parse_bootinfo(find_bootinfo());
+
+	/* ASSUMPTION:  If both r3 (bd_t pointer) and r6 (cmdline pointer)
+	 * are non-zero, then we should use the board info from the bd_t
+	 * structure and the cmdline pointed to by r6 instead of the
+	 * information from birecs, if any.  Otherwise, use the information
+	 * from birecs as discovered by the preceeding call to
+	 * parse_bootinfo().  This rule should work with both PPCBoot, which
+	 * uses a bd_t board info structure, and the kernel boot wrapper,
+	 * which uses birecs.
+	 */
+	if (r3 && r6) {
+		bd_t *bp = (bd_t *) __res;
+
+		/* copy board info structure */
+		memcpy((void *)__res, (void *)(r3 + KERNELBASE), sizeof(bd_t));
+		/* copy command line */
+		*(char *)(r7 + KERNELBASE) = 0;
+		strcpy(cmd_line, (char *)(r6 + KERNELBASE));
+
+		printk(KERN_INFO "Board info data:-\n");
+		printk(KERN_INFO "  Internal freq: %lu MHz, bus freq: %lu MHz\n",
+		       bp->bi_intfreq, bp->bi_busfreq);
+		printk(KERN_INFO "  Memory: %lx, size %lx\n", bp->bi_memstart,
+		       bp->bi_memsize);
+		printk(KERN_INFO "  Console baudrate: %lu\n", bp->bi_baudrate);
+		printk(KERN_INFO "  Ethernet address: "
+		       "%02x:%02x:%02x:%02x:%02x:%02x\n",
+		       bp->bi_enetaddr[0], bp->bi_enetaddr[1],
+		       bp->bi_enetaddr[2], bp->bi_enetaddr[3],
+		       bp->bi_enetaddr[4], bp->bi_enetaddr[5]);
+	}
+#ifdef CONFIG_BLK_DEV_INITRD
+	/* take care of initrd if we have one */
+	if (r4) {
+		initrd_start = r4 + KERNELBASE;
+		initrd_end = r5 + KERNELBASE;
+		printk(KERN_INFO "INITRD @ %lx/%lx\n", initrd_start, initrd_end);
+	}
+#endif /* CONFIG_BLK_DEV_INITRD */
+
+	/* Map in board regs, etc. */
+	isa_io_base = 0xe8000000;
+	isa_mem_base = 0xe8000000;
+	pci_dram_offset = 0x00000000;
+	ISA_DMA_THRESHOLD = 0x00ffffff;
+	DMA_MODE_READ = 0x44;
+	DMA_MODE_WRITE = 0x48;
+
+	ppc_md.setup_arch = ppc7d_setup_arch;
+	ppc_md.init = ppc7d_init2;
+	ppc_md.show_cpuinfo = ppc7d_show_cpuinfo;
+	ppc_md.irq_canonicalize = ppc7d_irq_canonicalize;
+	ppc_md.init_IRQ = ppc7d_init_irq;
+	ppc_md.get_irq = ppc7d_get_irq;
+
+	ppc_md.restart = ppc7d_restart;
+	ppc_md.power_off = ppc7d_power_off;
+	ppc_md.halt = ppc7d_halt;
+
+	ppc_md.find_end_of_memory = ppc7d_find_end_of_memory;
+	ppc_md.setup_io_mappings = ppc7d_map_io;
+
+	ppc_md.time_init = NULL;
+	ppc_md.set_rtc_time = NULL;
+	ppc_md.get_rtc_time = NULL;
+	ppc_md.calibrate_decr = ppc7d_calibrate_decr;
+	ppc_md.nvram_read_val = NULL;
+	ppc_md.nvram_write_val = NULL;
+
+	ppc_md.heartbeat = ppc7d_heartbeat;
+	ppc_md.heartbeat_reset = HZ;
+	ppc_md.heartbeat_count = ppc_md.heartbeat_reset;
+
+	ppc_md.pcibios_fixup_bus = ppc7d_pci_fixup_bus;
+
+#if defined(CONFIG_SERIAL_MPSC) || defined(CONFIG_MV643XX_ETH)
+	platform_notify = ppc7d_platform_notify;
+#endif
+
+#ifdef CONFIG_SERIAL_MPSC
+	/* On PPC7D, we must configure MPSC support via CPLD control
+	 * registers.
+	 */
+	outb(PPC7D_CPLD_RTS_COM4_SCLK |
+	     PPC7D_CPLD_RTS_COM56_ENABLED, PPC7D_CPLD_RTS);
+	outb(PPC7D_CPLD_COMS_COM3_TCLKEN |
+	     PPC7D_CPLD_COMS_COM3_TXEN |
+	     PPC7D_CPLD_COMS_COM4_TCLKEN |
+	     PPC7D_CPLD_COMS_COM4_TXEN, PPC7D_CPLD_COMS);
+#endif /* CONFIG_SERIAL_MPSC */
+
+#if defined(CONFIG_KGDB) || defined(CONFIG_SERIAL_TEXT_DEBUG)
+	ppc7d_early_serial_map();
+#ifdef  CONFIG_SERIAL_TEXT_DEBUG
+#if defined(CONFIG_SERIAL_MPSC_CONSOLE)
+	ppc_md.progress = mv64x60_mpsc_progress;
+#elif defined(CONFIG_SERIAL_8250)
+	ppc_md.progress = gen550_progress;
+#else
+#error CONFIG_KGDB || CONFIG_SERIAL_TEXT_DEBUG has no supported CONFIG_SERIAL_XXX
+#endif /* CONFIG_SERIAL_8250 */
+#endif /* CONFIG_SERIAL_TEXT_DEBUG */
+#endif /* CONFIG_KGDB || CONFIG_SERIAL_TEXT_DEBUG */
+
+	/* Enable write access to user flash.  This is necessary for
+	 * flash probe.
+	 */
+	val8 = readb((void *)isa_io_base + PPC7D_CPLD_SW_FLASH_WRITE_PROTECT);
+	writeb(val8 | (PPC7D_CPLD_SW_FLASH_WRPROT_ENABLED &
+		       PPC7D_CPLD_SW_FLASH_WRPROT_USER_MASK),
+	       (void *)isa_io_base + PPC7D_CPLD_SW_FLASH_WRITE_PROTECT);
+
+	/* Determine if this board has IBM ALMA VME devices */
+	val8 = readb((void *)isa_io_base + PPC7D_CPLD_BOARD_REVISION);
+	rev_num = (val8 & PPC7D_CPLD_BOARD_REVISION_NUMBER_MASK) >> 5;
+	if (rev_num <= 1)
+		ppc7d_has_alma = 1;
+}
diff -Nru a/arch/ppc/platforms/radstone_ppc7d.h b/arch/ppc/platforms/radstone_ppc7d.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/ppc/platforms/radstone_ppc7d.h	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,434 @@
+/*
+ * arch/ppc/platforms/radstone_ppc7d.h
+ *
+ * Board definitions for the Radstone PPC7D boards.
+ *
+ * Author: James Chapman <jchapman@katalix.com>
+ *
+ * Based on code done by Rabeeh Khoury - rabeeh@galileo.co.il
+ * Based on code done by - Mark A. Greer <mgreer@mvista.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+/*
+ * The MV64360 has 2 PCI buses each with 1 window from the CPU bus to
+ * PCI I/O space and 4 windows from the CPU bus to PCI MEM space.
+ * We'll only use one PCI MEM window on each PCI bus.
+ *
+ * This is the CPU physical memory map (windows must be at least 1MB
+ * and start on a boundary that is a multiple of the window size):
+ *
+ *    0xff800000-0xffffffff      - Boot window
+ *    0xff000000-0xff000fff	 - AFIX registers (DevCS2)
+ *    0xfef00000-0xfef0ffff      - Internal MV64x60 registers
+ *    0xfef40000-0xfef7ffff      - Internal SRAM
+ *    0xfef00000-0xfef0ffff      - MV64360 Registers
+ *    0x70000000-0x7fffffff      - soldered flash (DevCS3)
+ *    0xe8000000-0xe9ffffff      - PCI I/O
+ *    0x80000000-0xbfffffff      - PCI MEM
+ */
+
+#ifndef __PPC_PLATFORMS_PPC7D_H
+#define __PPC_PLATFORMS_PPC7D_H
+
+#include <asm/ppcboot.h>
+
+/*****************************************************************************
+ * CPU Physical Memory Map setup.
+ *****************************************************************************/
+
+#define PPC7D_BOOT_WINDOW_BASE			0xff800000
+#define PPC7D_AFIX_REG_BASE			0xff000000
+#define PPC7D_INTERNAL_SRAM_BASE		0xfef40000
+#define PPC7D_FLASH_BASE			0x70000000
+
+#define PPC7D_BOOT_WINDOW_SIZE_ACTUAL		0x00800000 /* 8MB */
+#define PPC7D_FLASH_SIZE_ACTUAL			0x10000000 /* 256MB */
+
+#define PPC7D_BOOT_WINDOW_SIZE		max(MV64360_WINDOW_SIZE_MIN,	\
+		PPC7D_BOOT_WINDOW_SIZE_ACTUAL)
+#define PPC7D_FLASH_SIZE		max(MV64360_WINDOW_SIZE_MIN,	\
+		PPC7D_FLASH_SIZE_ACTUAL)
+#define PPC7D_AFIX_REG_SIZE		max(MV64360_WINDOW_SIZE_MIN, 0xff)
+
+
+#define PPC7D_PCI0_MEM0_START_PROC_ADDR        0x80000000UL
+#define PPC7D_PCI0_MEM0_START_PCI_HI_ADDR      0x00000000UL
+#define PPC7D_PCI0_MEM0_START_PCI_LO_ADDR      0x80000000UL
+#define PPC7D_PCI0_MEM0_SIZE                   0x20000000UL
+#define PPC7D_PCI0_MEM1_START_PROC_ADDR        0xe8010000UL
+#define PPC7D_PCI0_MEM1_START_PCI_HI_ADDR      0x00000000UL
+#define PPC7D_PCI0_MEM1_START_PCI_LO_ADDR      0x00000000UL
+#define PPC7D_PCI0_MEM1_SIZE                   0x000f0000UL
+#define PPC7D_PCI0_IO_START_PROC_ADDR          0xe8000000UL
+#define PPC7D_PCI0_IO_START_PCI_ADDR           0x00000000UL
+#define PPC7D_PCI0_IO_SIZE                     0x00010000UL
+
+#define PPC7D_PCI1_MEM0_START_PROC_ADDR        0xa0000000UL
+#define PPC7D_PCI1_MEM0_START_PCI_HI_ADDR      0x00000000UL
+#define PPC7D_PCI1_MEM0_START_PCI_LO_ADDR      0xa0000000UL
+#define PPC7D_PCI1_MEM0_SIZE                   0x20000000UL
+#define PPC7D_PCI1_MEM1_START_PROC_ADDR        0xe9800000UL
+#define PPC7D_PCI1_MEM1_START_PCI_HI_ADDR      0x00000000UL
+#define PPC7D_PCI1_MEM1_START_PCI_LO_ADDR      0x00000000UL
+#define PPC7D_PCI1_MEM1_SIZE                   0x00800000UL
+#define PPC7D_PCI1_IO_START_PROC_ADDR          0xe9000000UL
+#define PPC7D_PCI1_IO_START_PCI_ADDR           0x00000000UL
+#define PPC7D_PCI1_IO_SIZE                     0x00010000UL
+
+#define	PPC7D_DEFAULT_BAUD			9600
+#define	PPC7D_MPSC_CLK_SRC			8	  /* TCLK */
+#define	PPC7D_MPSC_CLK_FREQ			133333333 /* 133.3333... MHz */
+
+#define	PPC7D_ETH0_PHY_ADDR			8
+#define	PPC7D_ETH1_PHY_ADDR			9
+#define	PPC7D_ETH2_PHY_ADDR			0
+
+#define PPC7D_ETH_TX_QUEUE_SIZE			400
+#define PPC7D_ETH_RX_QUEUE_SIZE			400
+
+#define	PPC7D_ETH_PORT_CONFIG_VALUE			\
+	MV64340_ETH_UNICAST_NORMAL_MODE			|	\
+	MV64340_ETH_DEFAULT_RX_QUEUE_0			|	\
+	MV64340_ETH_DEFAULT_RX_ARP_QUEUE_0		|	\
+	MV64340_ETH_RECEIVE_BC_IF_NOT_IP_OR_ARP		|	\
+	MV64340_ETH_RECEIVE_BC_IF_IP			|	\
+	MV64340_ETH_RECEIVE_BC_IF_ARP			|	\
+	MV64340_ETH_CAPTURE_TCP_FRAMES_DIS		|	\
+	MV64340_ETH_CAPTURE_UDP_FRAMES_DIS		|	\
+	MV64340_ETH_DEFAULT_RX_TCP_QUEUE_0		|	\
+	MV64340_ETH_DEFAULT_RX_UDP_QUEUE_0		|	\
+	MV64340_ETH_DEFAULT_RX_BPDU_QUEUE_0
+
+#define	PPC7D_ETH_PORT_CONFIG_EXTEND_VALUE		\
+	MV64340_ETH_SPAN_BPDU_PACKETS_AS_NORMAL		|	\
+	MV64340_ETH_PARTITION_DISABLE
+
+#define	GT_ETH_IPG_INT_RX(value)			\
+	((value & 0x3fff) << 8)
+
+#define	PPC7D_ETH_PORT_SDMA_CONFIG_VALUE		\
+	MV64340_ETH_RX_BURST_SIZE_4_64BIT		|	\
+	GT_ETH_IPG_INT_RX(0)			|	\
+	MV64340_ETH_TX_BURST_SIZE_4_64BIT
+
+#define	PPC7D_ETH_PORT_SERIAL_CONTROL_VALUE		\
+	MV64340_ETH_ENABLE_AUTO_NEG_FOR_DUPLX		|	\
+	MV64340_ETH_DISABLE_AUTO_NEG_FOR_FLOW_CTRL	|	\
+	MV64340_ETH_ADV_SYMMETRIC_FLOW_CTRL		|	\
+	MV64340_ETH_FORCE_FC_MODE_NO_PAUSE_DIS_TX	|	\
+	MV64340_ETH_FORCE_BP_MODE_NO_JAM		|	\
+	(1 << 9)					|	\
+	MV64340_ETH_DO_NOT_FORCE_LINK_FAIL		|	\
+	MV64340_ETH_RETRANSMIT_16_ATTEMPTS		|	\
+	MV64340_ETH_ENABLE_AUTO_NEG_SPEED_GMII		|	\
+	MV64340_ETH_DTE_ADV_0				|	\
+	MV64340_ETH_DISABLE_AUTO_NEG_BYPASS		|	\
+	MV64340_ETH_AUTO_NEG_NO_CHANGE			|	\
+	MV64340_ETH_MAX_RX_PACKET_9700BYTE		|	\
+	MV64340_ETH_CLR_EXT_LOOPBACK			|	\
+	MV64340_ETH_SET_FULL_DUPLEX_MODE		|	\
+	MV64340_ETH_ENABLE_FLOW_CTRL_TX_RX_IN_FULL_DUPLEX
+
+/*****************************************************************************
+ * Serial defines.
+ *****************************************************************************/
+
+#define PPC7D_SERIAL_0		0xe80003f8
+#define PPC7D_SERIAL_1		0xe80002f8
+
+#define RS_TABLE_SIZE  2
+
+/* Rate for the 1.8432 Mhz clock for the onboard serial chip */
+#define UART_CLK			1843200
+#define BASE_BAUD			( UART_CLK / 16 )
+
+#ifdef CONFIG_SERIAL_DETECT_IRQ
+#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_AUTO_IRQ)
+#else
+#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF)
+#endif
+
+#define STD_SERIAL_PORT_DFNS \
+        { 0, BASE_BAUD, PPC7D_SERIAL_0, 4, STD_COM_FLAGS, /* ttyS0 */ \
+		iomem_base: (u8 *)PPC7D_SERIAL_0,			  \
+		io_type: SERIAL_IO_MEM, },				  \
+        { 0, BASE_BAUD, PPC7D_SERIAL_1, 3, STD_COM_FLAGS, /* ttyS1 */ \
+		iomem_base: (u8 *)PPC7D_SERIAL_1,			  \
+		io_type: SERIAL_IO_MEM },
+
+#define SERIAL_PORT_DFNS \
+        STD_SERIAL_PORT_DFNS
+
+/*****************************************************************************
+ * CPLD defines.
+ *
+ * Register map:-
+ *
+ * 0000 to 000F 	South Bridge DMA 1 Control
+ * 0020 and 0021 	South Bridge Interrupt 1 Control
+ * 0040 to 0043 	South Bridge Counter Control
+ * 0060 		Keyboard
+ * 0061 		South Bridge NMI Status and Control
+ * 0064 		Keyboard
+ * 0071 and 0072 	RTC R/W
+ * 0078 to 007B 	South Bridge BIOS Timer
+ * 0080 to 0090 	South Bridge DMA Pages
+ * 00A0 and 00A1 	South Bridge Interrupt 2 Control
+ * 00C0 to 00DE 	South Bridge DMA 2 Control
+ * 02E8 to 02EF 	COM6 R/W
+ * 02F8 to 02FF 	South Bridge COM2 R/W
+ * 03E8 to 03EF 	COM5 R/W
+ * 03F8 to 03FF 	South Bridge COM1 R/W
+ * 040A 		South Bridge DMA Scatter/Gather RO
+ * 040B 		DMA 1 Extended Mode WO
+ * 0410 to 043F 	South Bridge DMA Scatter/Gather
+ * 0481 to 048B 	South Bridge DMA High Pages
+ * 04D0 and 04D1 	South Bridge Edge/Level Control
+ * 04D6 		DMA 2 Extended Mode WO
+ * 0804 		Memory Configuration RO
+ * 0806 		Memory Configuration Extend RO
+ * 0808 		SCSI Activity LED R/W
+ * 080C 		Equipment Present 1 RO
+ * 080E 		Equipment Present 2 RO
+ * 0810 		Equipment Present 3 RO
+ * 0812 		Equipment Present 4 RO
+ * 0818 		Key Lock RO
+ * 0820 		LEDS R/W
+ * 0824 		COMs R/W
+ * 0826 		RTS R/W
+ * 0828 		Reset R/W
+ * 082C 		Watchdog Trig R/W
+ * 082E 		Interrupt R/W
+ * 0830 		Interrupt Status RO
+ * 0832 		PCI configuration RO
+ * 0854 		Board Revision RO
+ * 0858 		Extended ID RO
+ * 0864 		ID Link RO
+ * 0866 		Motherboard Type RO
+ * 0868 		FLASH Write control RO
+ * 086A 		Software FLASH write protect R/W
+ * 086E 		FLASH Control R/W
+ *****************************************************************************/
+
+#define PPC7D_CPLD_MEM_CONFIG			0x0804
+#define PPC7D_CPLD_MEM_CONFIG_EXTEND		0x0806
+#define PPC7D_CPLD_SCSI_ACTIVITY_LED		0x0808
+#define PPC7D_CPLD_EQUIPMENT_PRESENT_1		0x080C
+#define PPC7D_CPLD_EQUIPMENT_PRESENT_2		0x080E
+#define PPC7D_CPLD_EQUIPMENT_PRESENT_3		0x0810
+#define PPC7D_CPLD_EQUIPMENT_PRESENT_4		0x0812
+#define PPC7D_CPLD_KEY_LOCK			0x0818
+#define PPC7D_CPLD_LEDS				0x0820
+#define PPC7D_CPLD_COMS				0x0824
+#define PPC7D_CPLD_RTS				0x0826
+#define PPC7D_CPLD_RESET			0x0828
+#define PPC7D_CPLD_WATCHDOG_TRIG		0x082C
+#define PPC7D_CPLD_INTR				0x082E
+#define PPC7D_CPLD_INTR_STATUS			0x0830
+#define PPC7D_CPLD_PCI_CONFIG			0x0832
+#define PPC7D_CPLD_BOARD_REVISION		0x0854
+#define PPC7D_CPLD_EXTENDED_ID			0x0858
+#define PPC7D_CPLD_ID_LINK			0x0864
+#define PPC7D_CPLD_MOTHERBOARD_TYPE		0x0866
+#define PPC7D_CPLD_FLASH_WRITE_CNTL		0x0868
+#define PPC7D_CPLD_SW_FLASH_WRITE_PROTECT	0x086A
+#define PPC7D_CPLD_FLASH_CNTL			0x086E
+
+/* MEMORY_CONFIG_EXTEND */
+#define PPC7D_CPLD_SDRAM_BANK_SIZE_MASK		0xc0
+#define PPC7D_CPLD_SDRAM_BANK_SIZE_128M		0
+#define PPC7D_CPLD_SDRAM_BANK_SIZE_256M		0x40
+#define PPC7D_CPLD_SDRAM_BANK_SIZE_512M		0x80
+#define PPC7D_CPLD_SDRAM_BANK_SIZE_1G		0xc0
+#define PPC7D_CPLD_FLASH_DEV_SIZE_MASK		0x03
+#define PPC7D_CPLD_FLASH_BANK_NUM_MASK		0x0c
+#define PPC7D_CPLD_FLASH_DEV_SIZE_64M		0
+#define PPC7D_CPLD_FLASH_DEV_SIZE_32M		1
+#define PPC7D_CPLD_FLASH_DEV_SIZE_16M		3
+#define PPC7D_CPLD_FLASH_BANK_NUM_4		0x00
+#define PPC7D_CPLD_FLASH_BANK_NUM_3		0x04
+#define PPC7D_CPLD_FLASH_BANK_NUM_2		0x08
+#define PPC7D_CPLD_FLASH_BANK_NUM_1		0x0c
+
+/* SCSI_LED */
+#define PPC7D_CPLD_SCSI_ACTIVITY_LED_OFF	0
+#define PPC7D_CPLD_SCSI_ACTIVITY_LED_ON		1
+
+/* EQUIPMENT_PRESENT_1 */
+#define PPC7D_CPLD_EQPT_PRES_1_FITTED		0
+#define PPC7D_CPLD_EQPT_PRES_1_PMC2_MASK	(0x80 >> 2)
+#define PPC7D_CPLD_EQPT_PRES_1_PMC1_MASK	(0x80 >> 3)
+#define PPC7D_CPLD_EQPT_PRES_1_AFIX_MASK	(0x80 >> 4)
+
+/* EQUIPMENT_PRESENT_2 */
+#define PPC7D_CPLD_EQPT_PRES_2_FITTED		!0
+#define PPC7D_CPLD_EQPT_PRES_2_UNIVERSE_MASK	(0x80 >> 0)
+#define PPC7D_CPLD_EQPT_PRES_2_COM36_MASK	(0x80 >> 2)
+#define PPC7D_CPLD_EQPT_PRES_2_GIGE_MASK	(0x80 >> 3)
+#define PPC7D_CPLD_EQPT_PRES_2_DUALGIGE_MASK	(0x80 >> 4)
+
+/* EQUIPMENT_PRESENT_3 */
+#define PPC7D_CPLD_EQPT_PRES_3_PMC2_V_MASK	(0x80 >> 3)
+#define PPC7D_CPLD_EQPT_PRES_3_PMC2_5V		(0 >> 3)
+#define PPC7D_CPLD_EQPT_PRES_3_PMC2_3V		(0x80 >> 3)
+#define PPC7D_CPLD_EQPT_PRES_3_PMC1_V_MASK	(0x80 >> 4)
+#define PPC7D_CPLD_EQPT_PRES_3_PMC1_5V		(0 >> 4)
+#define PPC7D_CPLD_EQPT_PRES_3_PMC1_3V		(0x80 >> 4)
+#define PPC7D_CPLD_EQPT_PRES_3_PMC_POWER_MASK	(0x80 >> 5)
+#define PPC7D_CPLD_EQPT_PRES_3_PMC_POWER_INTER	(0 >> 5)
+#define PPC7D_CPLD_EQPT_PRES_3_PMC_POWER_VME	(0x80 >> 5)
+
+/* EQUIPMENT_PRESENT_4 */
+#define PPC7D_CPLD_EQPT_PRES_4_LPT_MASK		(0x80 >> 2)
+#define PPC7D_CPLD_EQPT_PRES_4_LPT_FITTED	(0x80 >> 2)
+#define PPC7D_CPLD_EQPT_PRES_4_PS2_USB2_MASK	(0xc0 >> 6)
+#define PPC7D_CPLD_EQPT_PRES_4_PS2_FITTED	(0x40 >> 6)
+#define PPC7D_CPLD_EQPT_PRES_4_USB2_FITTED	(0x80 >> 6)
+
+/* CPLD_LEDS */
+#define PPC7D_CPLD_LEDS_ON			(!0)
+#define PPC7D_CPLD_LEDS_OFF			(0)
+#define PPC7D_CPLD_LEDS_NVRAM_PAGE_MASK		(0xc0 >> 2)
+#define PPC7D_CPLD_LEDS_DS201_MASK		(0x80 >> 4)
+#define PPC7D_CPLD_LEDS_DS219_MASK		(0x80 >> 5)
+#define PPC7D_CPLD_LEDS_DS220_MASK		(0x80 >> 6)
+#define PPC7D_CPLD_LEDS_DS221_MASK		(0x80 >> 7)
+
+/* CPLD_COMS */
+#define PPC7D_CPLD_COMS_COM3_TCLKEN		(0x80 >> 0)
+#define PPC7D_CPLD_COMS_COM3_RTCLKEN		(0x80 >> 1)
+#define PPC7D_CPLD_COMS_COM3_MODE_MASK		(0x80 >> 2)
+#define PPC7D_CPLD_COMS_COM3_MODE_RS232		(0)
+#define PPC7D_CPLD_COMS_COM3_MODE_RS422		(0x80 >> 2)
+#define PPC7D_CPLD_COMS_COM3_TXEN		(0x80 >> 3)
+#define PPC7D_CPLD_COMS_COM4_TCLKEN		(0x80 >> 4)
+#define PPC7D_CPLD_COMS_COM4_RTCLKEN		(0x80 >> 5)
+#define PPC7D_CPLD_COMS_COM4_MODE_MASK		(0x80 >> 6)
+#define PPC7D_CPLD_COMS_COM4_MODE_RS232		(0)
+#define PPC7D_CPLD_COMS_COM4_MODE_RS422		(0x80 >> 6)
+#define PPC7D_CPLD_COMS_COM4_TXEN		(0x80 >> 7)
+
+/* CPLD_RTS */
+#define PPC7D_CPLD_RTS_COM36_LOOPBACK		(0x80 >> 0)
+#define PPC7D_CPLD_RTS_COM4_SCLK		(0x80 >> 1)
+#define PPC7D_CPLD_RTS_COM3_TXFUNC_MASK		(0xc0 >> 2)
+#define PPC7D_CPLD_RTS_COM3_TXFUNC_DISABLED	(0 >> 2)
+#define PPC7D_CPLD_RTS_COM3_TXFUNC_ENABLED	(0x80 >> 2)
+#define PPC7D_CPLD_RTS_COM3_TXFUNC_ENABLED_RTG3	(0xc0 >> 2)
+#define PPC7D_CPLD_RTS_COM3_TXFUNC_ENABLED_RTG3S (0xc0 >> 2)
+#define PPC7D_CPLD_RTS_COM56_MODE_MASK		(0x80 >> 4)
+#define PPC7D_CPLD_RTS_COM56_MODE_RS232		(0)
+#define PPC7D_CPLD_RTS_COM56_MODE_RS422		(0x80 >> 4)
+#define PPC7D_CPLD_RTS_COM56_ENABLE_MASK	(0x80 >> 5)
+#define PPC7D_CPLD_RTS_COM56_DISABLED		(0)
+#define PPC7D_CPLD_RTS_COM56_ENABLED		(0x80 >> 5)
+#define PPC7D_CPLD_RTS_COM4_TXFUNC_MASK		(0xc0 >> 6)
+#define PPC7D_CPLD_RTS_COM4_TXFUNC_DISABLED	(0 >> 6)
+#define PPC7D_CPLD_RTS_COM4_TXFUNC_ENABLED	(0x80 >> 6)
+#define PPC7D_CPLD_RTS_COM4_TXFUNC_ENABLED_RTG3	(0x40 >> 6)
+#define PPC7D_CPLD_RTS_COM4_TXFUNC_ENABLED_RTG3S (0x40 >> 6)
+
+/* WATCHDOG_TRIG */
+#define PPC7D_CPLD_WDOG_CAUSE_MASK		(0x80 >> 0)
+#define PPC7D_CPLD_WDOG_CAUSE_NORMAL_RESET	(0 >> 0)
+#define PPC7D_CPLD_WDOG_CAUSE_WATCHDOG		(0x80 >> 0)
+#define PPC7D_CPLD_WDOG_ENABLE_MASK		(0x80 >> 6)
+#define PPC7D_CPLD_WDOG_ENABLE_OFF		(0 >> 6)
+#define PPC7D_CPLD_WDOG_ENABLE_ON		(0x80 >> 6)
+#define PPC7D_CPLD_WDOG_RESETSW_MASK		(0x80 >> 7)
+#define PPC7D_CPLD_WDOG_RESETSW_OFF		(0 >> 7)
+#define PPC7D_CPLD_WDOG_RESETSW_ON		(0x80 >> 7)
+
+/* Interrupt mask and status bits */
+#define PPC7D_CPLD_INTR_TEMP_MASK		(0x80 >> 0)
+#define PPC7D_CPLD_INTR_HB8_MASK		(0x80 >> 1)
+#define PPC7D_CPLD_INTR_PHY1_MASK		(0x80 >> 2)
+#define PPC7D_CPLD_INTR_PHY0_MASK		(0x80 >> 3)
+#define PPC7D_CPLD_INTR_ISANMI_MASK		(0x80 >> 5)
+#define PPC7D_CPLD_INTR_CRITTEMP_MASK		(0x80 >> 6)
+
+/* CPLD_INTR */
+#define PPC7D_CPLD_INTR_ENABLE_OFF		(0)
+#define PPC7D_CPLD_INTR_ENABLE_ON		(!0)
+
+/* CPLD_INTR_STATUS */
+#define PPC7D_CPLD_INTR_STATUS_OFF		(0)
+#define PPC7D_CPLD_INTR_STATUS_ON		(!0)
+
+/* CPLD_PCI_CONFIG */
+#define PPC7D_CPLD_PCI_CONFIG_PCI0_MASK		0x70
+#define PPC7D_CPLD_PCI_CONFIG_PCI0_PCI33	0x00
+#define PPC7D_CPLD_PCI_CONFIG_PCI0_PCI66	0x10
+#define PPC7D_CPLD_PCI_CONFIG_PCI0_PCIX33	0x40
+#define PPC7D_CPLD_PCI_CONFIG_PCI0_PCIX66	0x50
+#define PPC7D_CPLD_PCI_CONFIG_PCI0_PCIX100      0x60
+#define PPC7D_CPLD_PCI_CONFIG_PCI0_PCIX133	0x70
+#define PPC7D_CPLD_PCI_CONFIG_PCI1_MASK		0x07
+#define PPC7D_CPLD_PCI_CONFIG_PCI1_PCI33	0x00
+#define PPC7D_CPLD_PCI_CONFIG_PCI1_PCI66	0x01
+#define PPC7D_CPLD_PCI_CONFIG_PCI1_PCIX33	0x04
+#define PPC7D_CPLD_PCI_CONFIG_PCI1_PCIX66	0x05
+#define PPC7D_CPLD_PCI_CONFIG_PCI1_PCIX100	0x06
+#define PPC7D_CPLD_PCI_CONFIG_PCI1_PCIX133	0x07
+
+/* CPLD_BOARD_REVISION */
+#define PPC7D_CPLD_BOARD_REVISION_NUMBER_MASK	0xe0
+#define PPC7D_CPLD_BOARD_REVISION_LETTER_MASK	0x1f
+
+/* CPLD_EXTENDED_ID */
+#define PPC7D_CPLD_EXTENDED_ID_PPC7D		0x18
+
+/* CPLD_ID_LINK */
+#define PPC7D_CPLD_ID_LINK_VME64_GAP_MASK	(0x80 >> 2)
+#define PPC7D_CPLD_ID_LINK_VME64_GA4_MASK	(0x80 >> 3)
+#define PPC7D_CPLD_ID_LINK_E13_MASK		(0x80 >> 4)
+#define PPC7D_CPLD_ID_LINK_E12_MASK		(0x80 >> 5)
+#define PPC7D_CPLD_ID_LINK_E7_MASK		(0x80 >> 6)
+#define PPC7D_CPLD_ID_LINK_E6_MASK		(0x80 >> 7)
+
+/* CPLD_MOTHERBOARD_TYPE */
+#define PPC7D_CPLD_MB_TYPE_ECC_ENABLE_MASK	(0x80 >> 0)
+#define PPC7D_CPLD_MB_TYPE_ECC_ENABLED		(0x80 >> 0)
+#define PPC7D_CPLD_MB_TYPE_ECC_DISABLED		(0 >> 0)
+#define PPC7D_CPLD_MB_TYPE_ECC_FITTED_MASK	(0x80 >> 3)
+#define PPC7D_CPLD_MB_TYPE_PLL_MASK		0x0c
+#define PPC7D_CPLD_MB_TYPE_PLL_133		0x00
+#define PPC7D_CPLD_MB_TYPE_PLL_100		0x08
+#define PPC7D_CPLD_MB_TYPE_PLL_64		0x04
+#define PPC7D_CPLD_MB_TYPE_HW_ID_MASK		0x03
+
+/* CPLD_FLASH_WRITE_CNTL */
+#define PPD7D_CPLD_FLASH_CNTL_WR_LINK_MASK	(0x80 >> 0)
+#define PPD7D_CPLD_FLASH_CNTL_WR_LINK_FITTED	(0x80 >> 0)
+#define PPD7D_CPLD_FLASH_CNTL_BOOT_LINK_MASK	(0x80 >> 2)
+#define PPD7D_CPLD_FLASH_CNTL_BOOT_LINK_FITTED	(0x80 >> 2)
+#define PPD7D_CPLD_FLASH_CNTL_USER_LINK_MASK	(0x80 >> 3)
+#define PPD7D_CPLD_FLASH_CNTL_USER_LINK_FITTED	(0x80 >> 3)
+#define PPD7D_CPLD_FLASH_CNTL_RECO_WR_MASK	(0x80 >> 5)
+#define PPD7D_CPLD_FLASH_CNTL_RECO_WR_ENABLED	(0x80 >> 5)
+#define PPD7D_CPLD_FLASH_CNTL_BOOT_WR_MASK	(0x80 >> 6)
+#define PPD7D_CPLD_FLASH_CNTL_BOOT_WR_ENABLED	(0x80 >> 6)
+#define PPD7D_CPLD_FLASH_CNTL_USER_WR_MASK	(0x80 >> 7)
+#define PPD7D_CPLD_FLASH_CNTL_USER_WR_ENABLED	(0x80 >> 7)
+
+/* CPLD_SW_FLASH_WRITE_PROTECT */
+#define PPC7D_CPLD_SW_FLASH_WRPROT_ENABLED	(!0)
+#define PPC7D_CPLD_SW_FLASH_WRPROT_DISABLED	(0)
+#define PPC7D_CPLD_SW_FLASH_WRPROT_SYSBOOT_MASK	(0x80 >> 6)
+#define PPC7D_CPLD_SW_FLASH_WRPROT_USER_MASK	(0x80 >> 7)
+
+/* CPLD_FLASH_WRITE_CNTL */
+#define PPC7D_CPLD_FLASH_CNTL_NVRAM_PROT_MASK	(0x80 >> 0)
+#define PPC7D_CPLD_FLASH_CNTL_NVRAM_DISABLED	(0 >> 0)
+#define PPC7D_CPLD_FLASH_CNTL_NVRAM_ENABLED	(0x80 >> 0)
+#define PPC7D_CPLD_FLASH_CNTL_ALTBOOT_LINK_MASK	(0x80 >> 1)
+#define PPC7D_CPLD_FLASH_CNTL_VMEBOOT_LINK_MASK	(0x80 >> 2)
+#define PPC7D_CPLD_FLASH_CNTL_RECBOOT_LINK_MASK	(0x80 >> 3)
+
+
+#endif /* __PPC_PLATFORMS_PPC7D_H */
diff -Nru a/arch/ppc/platforms/sandpoint.c b/arch/ppc/platforms/sandpoint.c
--- a/arch/ppc/platforms/sandpoint.c	2005-03-11 12:51:52 -08:00
+++ b/arch/ppc/platforms/sandpoint.c	2005-03-11 12:51:52 -08:00
@@ -319,10 +319,10 @@
 	 * We will do this now with good known values.  Future versions
 	 * of DINK32 are supposed to get this correct.
 	 */
-	if (cur_cpu_spec[0]->cpu_features & CPU_FTR_SPEC7450)
+	if (cpu_has_feature(CPU_FTR_SPEC7450))
 		/* 745x is different.  We only want to pass along enable. */
 		_set_L2CR(L2CR_L2E);
-	else if (cur_cpu_spec[0]->cpu_features & CPU_FTR_L2CR)
+	else if (cpu_has_feature(CPU_FTR_L2CR))
 		/* All modules have 1MB of L2.  We also assume that an
 		 * L2 divisor of 3 will work.
 		 */
@@ -330,7 +330,7 @@
 				| L2CR_L2RAM_PIPE | L2CR_L2OH_1_0 | L2CR_L2DF);
 #if 0
 	/* Untested right now. */
-	if (cur_cpu_spec[0]->cpu_features & CPU_FTR_L3CR) {
+	if (cpu_has_feature(CPU_FTR_L3CR)) {
 		/* Magic value. */
 		_set_L3CR(0x8f032000);
 	}
diff -Nru a/arch/ppc/syslib/Makefile b/arch/ppc/syslib/Makefile
--- a/arch/ppc/syslib/Makefile	2005-03-11 12:51:41 -08:00
+++ b/arch/ppc/syslib/Makefile	2005-03-11 12:51:41 -08:00
@@ -74,6 +74,7 @@
 					hawk_common.o
 obj-$(CONFIG_HARRIER)		+= harrier.o
 obj-$(CONFIG_PRPMC800)		+= open_pic.o indirect_pci.o pci_auto.o
+obj-$(CONFIG_RADSTONE_PPC7D)	+= i8259.o pci_auto.o
 obj-$(CONFIG_SANDPOINT)		+= i8259.o pci_auto.o todc_time.o
 obj-$(CONFIG_SBC82xx)		+= todc_time.o
 obj-$(CONFIG_SPRUCE)		+= cpc700_pic.o indirect_pci.o pci_auto.o \
@@ -99,4 +100,9 @@
 ifeq ($(CONFIG_85xx),y)
 obj-$(CONFIG_PCI)		+= indirect_pci.o pci_auto.o
 endif
+obj-$(CONFIG_83xx)		+= ipic.o ppc83xx_setup.o ppc_sys.o
+ifeq ($(CONFIG_83xx),y)
+obj-$(CONFIG_PCI)		+= indirect_pci.o pci_auto.o
+endif
+obj-$(CONFIG_MPC8555_CDS)	+= todc_time.o
 obj-$(CONFIG_PPC_MPC52xx)	+= mpc52xx_setup.o mpc52xx_pic.o
diff -Nru a/arch/ppc/syslib/ipic.c b/arch/ppc/syslib/ipic.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/ppc/syslib/ipic.c	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,646 @@
+/*
+ * include/asm-ppc/ipic.c
+ *
+ * IPIC routines implementations.
+ *
+ * Copyright 2005 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/reboot.h>
+#include <linux/slab.h>
+#include <linux/stddef.h>
+#include <linux/sched.h>
+#include <linux/signal.h>
+#include <linux/sysdev.h>
+#include <asm/irq.h>
+#include <asm/io.h>
+#include <asm/ipic.h>
+#include <asm/mpc83xx.h>
+
+#include "ipic.h"
+
+static struct ipic p_ipic;
+static struct ipic * primary_ipic;
+
+static struct ipic_info ipic_info[] = {
+	[9] = {
+		.pend	= IPIC_SIPNR_H,
+		.mask	= IPIC_SIMSR_H,
+		.prio	= IPIC_SIPRR_D,
+		.force	= IPIC_SIFCR_H,
+		.bit	= 24,
+		.prio_mask = 0,
+	},
+	[10] = {
+		.pend	= IPIC_SIPNR_H,
+		.mask	= IPIC_SIMSR_H,
+		.prio	= IPIC_SIPRR_D,
+		.force	= IPIC_SIFCR_H,
+		.bit	= 25,
+		.prio_mask = 1,
+	},
+	[11] = {
+		.pend	= IPIC_SIPNR_H,
+		.mask	= IPIC_SIMSR_H,
+		.prio	= IPIC_SIPRR_D,
+		.force	= IPIC_SIFCR_H,
+		.bit	= 26,
+		.prio_mask = 2,
+	},
+	[14] = {
+		.pend	= IPIC_SIPNR_H,
+		.mask	= IPIC_SIMSR_H,
+		.prio	= IPIC_SIPRR_D,
+		.force	= IPIC_SIFCR_H,
+		.bit	= 29,
+		.prio_mask = 5,
+	},
+	[15] = {
+		.pend	= IPIC_SIPNR_H,
+		.mask	= IPIC_SIMSR_H,
+		.prio	= IPIC_SIPRR_D,
+		.force	= IPIC_SIFCR_H,
+		.bit	= 30,
+		.prio_mask = 6,
+	},
+	[16] = {
+		.pend	= IPIC_SIPNR_H,
+		.mask	= IPIC_SIMSR_H,
+		.prio	= IPIC_SIPRR_D,
+		.force	= IPIC_SIFCR_H,
+		.bit	= 31,
+		.prio_mask = 7,
+	},
+	[17] = {
+		.pend	= IPIC_SIPNR_H,
+		.mask	= IPIC_SEMSR,
+		.prio	= IPIC_SMPRR_A,
+		.force	= IPIC_SEFCR,
+		.bit	= 1,
+		.prio_mask = 5,
+	},
+	[18] = {
+		.pend	= IPIC_SIPNR_H,
+		.mask	= IPIC_SEMSR,
+		.prio	= IPIC_SMPRR_A,
+		.force	= IPIC_SEFCR,
+		.bit	= 2,
+		.prio_mask = 6,
+	},
+	[19] = {
+		.pend	= IPIC_SIPNR_H,
+		.mask	= IPIC_SEMSR,
+		.prio	= IPIC_SMPRR_A,
+		.force	= IPIC_SEFCR,
+		.bit	= 3,
+		.prio_mask = 7,
+	},
+	[20] = {
+		.pend	= IPIC_SIPNR_H,
+		.mask	= IPIC_SEMSR,
+		.prio	= IPIC_SMPRR_B,
+		.force	= IPIC_SEFCR,
+		.bit	= 4,
+		.prio_mask = 4,
+	},
+	[21] = {
+		.pend	= IPIC_SIPNR_H,
+		.mask	= IPIC_SEMSR,
+		.prio	= IPIC_SMPRR_B,
+		.force	= IPIC_SEFCR,
+		.bit	= 5,
+		.prio_mask = 5,
+	},
+	[22] = {
+		.pend	= IPIC_SIPNR_H,
+		.mask	= IPIC_SEMSR,
+		.prio	= IPIC_SMPRR_B,
+		.force	= IPIC_SEFCR,
+		.bit	= 6,
+		.prio_mask = 6,
+	},
+	[23] = {
+		.pend	= IPIC_SIPNR_H,
+		.mask	= IPIC_SEMSR,
+		.prio	= IPIC_SMPRR_B,
+		.force	= IPIC_SEFCR,
+		.bit	= 7,
+		.prio_mask = 7,
+	},
+	[32] = {
+		.pend	= IPIC_SIPNR_H,
+		.mask	= IPIC_SIMSR_H,
+		.prio	= IPIC_SIPRR_A,
+		.force	= IPIC_SIFCR_H,
+		.bit	= 0,
+		.prio_mask = 0,
+	},
+	[33] = {
+		.pend	= IPIC_SIPNR_H,
+		.mask	= IPIC_SIMSR_H,
+		.prio	= IPIC_SIPRR_A,
+		.force	= IPIC_SIFCR_H,
+		.bit	= 1,
+		.prio_mask = 1,
+	},
+	[34] = {
+		.pend	= IPIC_SIPNR_H,
+		.mask	= IPIC_SIMSR_H,
+		.prio	= IPIC_SIPRR_A,
+		.force	= IPIC_SIFCR_H,
+		.bit	= 2,
+		.prio_mask = 2,
+	},
+	[35] = {
+		.pend	= IPIC_SIPNR_H,
+		.mask	= IPIC_SIMSR_H,
+		.prio	= IPIC_SIPRR_A,
+		.force	= IPIC_SIFCR_H,
+		.bit	= 3,
+		.prio_mask = 3,
+	},
+	[36] = {
+		.pend	= IPIC_SIPNR_H,
+		.mask	= IPIC_SIMSR_H,
+		.prio	= IPIC_SIPRR_A,
+		.force	= IPIC_SIFCR_H,
+		.bit	= 4,
+		.prio_mask = 4,
+	},
+	[37] = {
+		.pend	= IPIC_SIPNR_H,
+		.mask	= IPIC_SIMSR_H,
+		.prio	= IPIC_SIPRR_A,
+		.force	= IPIC_SIFCR_H,
+		.bit	= 5,
+		.prio_mask = 5,
+	},
+	[38] = {
+		.pend	= IPIC_SIPNR_H,
+		.mask	= IPIC_SIMSR_H,
+		.prio	= IPIC_SIPRR_A,
+		.force	= IPIC_SIFCR_H,
+		.bit	= 6,
+		.prio_mask = 6,
+	},
+	[39] = {
+		.pend	= IPIC_SIPNR_H,
+		.mask	= IPIC_SIMSR_H,
+		.prio	= IPIC_SIPRR_A,
+		.force	= IPIC_SIFCR_H,
+		.bit	= 7,
+		.prio_mask = 7,
+	},
+	[48] = {
+		.pend	= IPIC_SEPNR,
+		.mask	= IPIC_SEMSR,
+		.prio	= IPIC_SMPRR_A,
+		.force	= IPIC_SEFCR,
+		.bit	= 0,
+		.prio_mask = 4,
+	},
+	[64] = {
+		.pend	= IPIC_SIPNR_H,
+		.mask	= IPIC_SIMSR_L,
+		.prio	= IPIC_SMPRR_A,
+		.force	= IPIC_SIFCR_L,
+		.bit	= 0,
+		.prio_mask = 0,
+	},
+	[65] = {
+		.pend	= IPIC_SIPNR_H,
+		.mask	= IPIC_SIMSR_L,
+		.prio	= IPIC_SMPRR_A,
+		.force	= IPIC_SIFCR_L,
+		.bit	= 1,
+		.prio_mask = 1,
+	},
+	[66] = {
+		.pend	= IPIC_SIPNR_H,
+		.mask	= IPIC_SIMSR_L,
+		.prio	= IPIC_SMPRR_A,
+		.force	= IPIC_SIFCR_L,
+		.bit	= 2,
+		.prio_mask = 2,
+	},
+	[67] = {
+		.pend	= IPIC_SIPNR_H,
+		.mask	= IPIC_SIMSR_L,
+		.prio	= IPIC_SMPRR_A,
+		.force	= IPIC_SIFCR_L,
+		.bit	= 3,
+		.prio_mask = 3,
+	},
+	[68] = {
+		.pend	= IPIC_SIPNR_H,
+		.mask	= IPIC_SIMSR_L,
+		.prio	= IPIC_SMPRR_B,
+		.force	= IPIC_SIFCR_L,
+		.bit	= 4,
+		.prio_mask = 0,
+	},
+	[69] = {
+		.pend	= IPIC_SIPNR_H,
+		.mask	= IPIC_SIMSR_L,
+		.prio	= IPIC_SMPRR_B,
+		.force	= IPIC_SIFCR_L,
+		.bit	= 5,
+		.prio_mask = 1,
+	},
+	[70] = {
+		.pend	= IPIC_SIPNR_H,
+		.mask	= IPIC_SIMSR_L,
+		.prio	= IPIC_SMPRR_B,
+		.force	= IPIC_SIFCR_L,
+		.bit	= 6,
+		.prio_mask = 2,
+	},
+	[71] = {
+		.pend	= IPIC_SIPNR_H,
+		.mask	= IPIC_SIMSR_L,
+		.prio	= IPIC_SMPRR_B,
+		.force	= IPIC_SIFCR_L,
+		.bit	= 7,
+		.prio_mask = 3,
+	},
+	[72] = {
+		.pend	= IPIC_SIPNR_H,
+		.mask	= IPIC_SIMSR_L,
+		.prio	= 0,
+		.force	= IPIC_SIFCR_L,
+		.bit	= 8,
+	},
+	[73] = {
+		.pend	= IPIC_SIPNR_H,
+		.mask	= IPIC_SIMSR_L,
+		.prio	= 0,
+		.force	= IPIC_SIFCR_L,
+		.bit	= 9,
+	},
+	[74] = {
+		.pend	= IPIC_SIPNR_H,
+		.mask	= IPIC_SIMSR_L,
+		.prio	= 0,
+		.force	= IPIC_SIFCR_L,
+		.bit	= 10,
+	},
+	[75] = {
+		.pend	= IPIC_SIPNR_H,
+		.mask	= IPIC_SIMSR_L,
+		.prio	= 0,
+		.force	= IPIC_SIFCR_L,
+		.bit	= 11,
+	},
+	[76] = {
+		.pend	= IPIC_SIPNR_H,
+		.mask	= IPIC_SIMSR_L,
+		.prio	= 0,
+		.force	= IPIC_SIFCR_L,
+		.bit	= 12,
+	},
+	[77] = {
+		.pend	= IPIC_SIPNR_H,
+		.mask	= IPIC_SIMSR_L,
+		.prio	= 0,
+		.force	= IPIC_SIFCR_L,
+		.bit	= 13,
+	},
+	[78] = {
+		.pend	= IPIC_SIPNR_H,
+		.mask	= IPIC_SIMSR_L,
+		.prio	= 0,
+		.force	= IPIC_SIFCR_L,
+		.bit	= 14,
+	},
+	[79] = {
+		.pend	= IPIC_SIPNR_H,
+		.mask	= IPIC_SIMSR_L,
+		.prio	= 0,
+		.force	= IPIC_SIFCR_L,
+		.bit	= 15,
+	},
+	[80] = {
+		.pend	= IPIC_SIPNR_H,
+		.mask	= IPIC_SIMSR_L,
+		.prio	= 0,
+		.force	= IPIC_SIFCR_L,
+		.bit	= 16,
+	},
+	[84] = {
+		.pend	= IPIC_SIPNR_H,
+		.mask	= IPIC_SIMSR_L,
+		.prio	= 0,
+		.force	= IPIC_SIFCR_L,
+		.bit	= 20,
+	},
+	[85] = {
+		.pend	= IPIC_SIPNR_H,
+		.mask	= IPIC_SIMSR_L,
+		.prio	= 0,
+		.force	= IPIC_SIFCR_L,
+		.bit	= 21,
+	},
+	[90] = {
+		.pend	= IPIC_SIPNR_H,
+		.mask	= IPIC_SIMSR_L,
+		.prio	= 0,
+		.force	= IPIC_SIFCR_L,
+		.bit	= 26,
+	},
+	[91] = {
+		.pend	= IPIC_SIPNR_H,
+		.mask	= IPIC_SIMSR_L,
+		.prio	= 0,
+		.force	= IPIC_SIFCR_L,
+		.bit	= 27,
+	},
+};
+
+static inline u32 ipic_read(volatile u32 __iomem *base, unsigned int reg)
+{
+	return in_be32(base + (reg >> 2));
+}
+
+static inline void ipic_write(volatile u32 __iomem *base, unsigned int reg, u32 value)
+{
+	out_be32(base + (reg >> 2), value);
+}
+
+static inline struct ipic * ipic_from_irq(unsigned int irq)
+{
+	return primary_ipic;
+}
+
+static void ipic_enable_irq(unsigned int irq)
+{
+	struct ipic *ipic = ipic_from_irq(irq);
+	unsigned int src = irq - ipic->irq_offset;
+	u32 temp;
+
+	temp = ipic_read(ipic->regs, ipic_info[src].mask);
+	temp |= (1 << (31 - ipic_info[src].bit));
+	ipic_write(ipic->regs, ipic_info[src].mask, temp);
+}
+
+static void ipic_disable_irq(unsigned int irq)
+{
+	struct ipic *ipic = ipic_from_irq(irq);
+	unsigned int src = irq - ipic->irq_offset;
+	u32 temp;
+
+	temp = ipic_read(ipic->regs, ipic_info[src].mask);
+	temp &= ~(1 << (31 - ipic_info[src].bit));
+	ipic_write(ipic->regs, ipic_info[src].mask, temp);
+}
+
+static void ipic_disable_irq_and_ack(unsigned int irq)
+{
+	struct ipic *ipic = ipic_from_irq(irq);
+	unsigned int src = irq - ipic->irq_offset;
+	u32 temp;
+
+	ipic_disable_irq(irq);
+
+	temp = ipic_read(ipic->regs, ipic_info[src].pend);
+	temp |= (1 << (31 - ipic_info[src].bit));
+	ipic_write(ipic->regs, ipic_info[src].pend, temp);
+}
+
+static void ipic_end_irq(unsigned int irq)
+{
+	if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+		ipic_enable_irq(irq);
+}
+
+struct hw_interrupt_type ipic = {
+	.typename = " IPIC  ",
+	.enable = ipic_enable_irq,
+	.disable = ipic_disable_irq,
+	.ack = ipic_disable_irq_and_ack,
+	.end = ipic_end_irq,
+};
+
+void __init ipic_init(phys_addr_t phys_addr,
+		unsigned int flags,
+		unsigned int irq_offset,
+		unsigned char *senses,
+		unsigned int senses_count)
+{
+	u32 i, temp = 0;
+
+	primary_ipic = &p_ipic;
+	primary_ipic->regs = ioremap(phys_addr, MPC83xx_IPIC_SIZE);
+
+	primary_ipic->irq_offset = irq_offset;
+
+	ipic_write(primary_ipic->regs, IPIC_SICNR, 0x0);
+
+	/* default priority scheme is grouped. If spread mode is required
+	 * configure SICFR accordingly */
+	if (flags & IPIC_SPREADMODE_GRP_A)
+		temp |= SICFR_IPSA;
+	if (flags & IPIC_SPREADMODE_GRP_D)
+		temp |= SICFR_IPSD;
+	if (flags & IPIC_SPREADMODE_MIX_A)
+		temp |= SICFR_MPSA;
+	if (flags & IPIC_SPREADMODE_MIX_B)
+		temp |= SICFR_MPSB;
+
+	ipic_write(primary_ipic->regs, IPIC_SICNR, temp);
+
+	/* handle MCP route */
+	temp = 0;
+	if (flags & IPIC_DISABLE_MCP_OUT)
+		temp = SERCR_MCPR;
+	ipic_write(primary_ipic->regs, IPIC_SERCR, temp);
+
+	/* handle routing of IRQ0 to MCP */
+	temp = ipic_read(primary_ipic->regs, IPIC_SEMSR);
+
+	if (flags & IPIC_IRQ0_MCP)
+		temp |= SEMSR_SIRQ0;
+	else
+		temp &= ~SEMSR_SIRQ0;
+
+	ipic_write(primary_ipic->regs, IPIC_SEMSR, temp);
+
+	for (i = 0 ; i < NR_IPIC_INTS ; i++) {
+		irq_desc[i+irq_offset].handler = &ipic;
+		irq_desc[i+irq_offset].status = IRQ_LEVEL;
+	}
+
+	temp = 0;
+	for (i = 0 ; i < senses_count ; i++) {
+		if ((senses[i] & IRQ_SENSE_MASK) == IRQ_SENSE_EDGE) {
+			temp |= 1 << (16 - i);
+			if (i != 0)
+				irq_desc[i + irq_offset + MPC83xx_IRQ_EXT1 - 1].status = 0;
+			else
+				irq_desc[irq_offset + MPC83xx_IRQ_EXT0].status = 0;
+		}
+	}
+	ipic_write(primary_ipic->regs, IPIC_SECNR, temp);
+
+	printk ("IPIC (%d IRQ sources, %d External IRQs) at %p\n", NR_IPIC_INTS,
+			senses_count, primary_ipic->regs);
+}
+
+int ipic_set_priority(unsigned int irq, unsigned int priority)
+{
+	struct ipic *ipic = ipic_from_irq(irq);
+	unsigned int src = irq - ipic->irq_offset;
+	u32 temp;
+
+	if (priority > 7)
+		return -EINVAL;
+	if (src > 127)
+		return -EINVAL;
+	if (ipic_info[src].prio == 0)
+		return -EINVAL;
+
+	temp = ipic_read(ipic->regs, ipic_info[src].prio);
+
+	if (priority < 4) {
+		temp &= ~(0x7 << (20 + (3 - priority) * 3));
+		temp |= ipic_info[src].prio_mask << (20 + (3 - priority) * 3);
+	} else {
+		temp &= ~(0x7 << (4 + (7 - priority) * 3));
+		temp |= ipic_info[src].prio_mask << (4 + (7 - priority) * 3);
+	}
+
+	ipic_write(ipic->regs, ipic_info[src].prio, temp);
+
+	return 0;
+}
+
+void ipic_set_highest_priority(unsigned int irq)
+{
+	struct ipic *ipic = ipic_from_irq(irq);
+	unsigned int src = irq - ipic->irq_offset;
+	u32 temp;
+
+	temp = ipic_read(ipic->regs, IPIC_SICFR);
+
+	/* clear and set HPI */
+	temp &= 0x7f000000;
+	temp |= (src & 0x7f) << 24;
+
+	ipic_write(ipic->regs, IPIC_SICFR, temp);
+}
+
+void ipic_set_default_priority(void)
+{
+	ipic_set_priority(MPC83xx_IRQ_TSEC1_TX, 0);
+	ipic_set_priority(MPC83xx_IRQ_TSEC1_RX, 1);
+	ipic_set_priority(MPC83xx_IRQ_TSEC1_ERROR, 2);
+	ipic_set_priority(MPC83xx_IRQ_TSEC2_TX, 3);
+	ipic_set_priority(MPC83xx_IRQ_TSEC2_RX, 4);
+	ipic_set_priority(MPC83xx_IRQ_TSEC2_ERROR, 5);
+	ipic_set_priority(MPC83xx_IRQ_USB2_DR, 6);
+	ipic_set_priority(MPC83xx_IRQ_USB2_MPH, 7);
+
+	ipic_set_priority(MPC83xx_IRQ_UART1, 0);
+	ipic_set_priority(MPC83xx_IRQ_UART2, 1);
+	ipic_set_priority(MPC83xx_IRQ_SEC2, 2);
+	ipic_set_priority(MPC83xx_IRQ_IIC1, 5);
+	ipic_set_priority(MPC83xx_IRQ_IIC2, 6);
+	ipic_set_priority(MPC83xx_IRQ_SPI, 7);
+	ipic_set_priority(MPC83xx_IRQ_RTC_SEC, 0);
+	ipic_set_priority(MPC83xx_IRQ_PIT, 1);
+	ipic_set_priority(MPC83xx_IRQ_PCI1, 2);
+	ipic_set_priority(MPC83xx_IRQ_PCI2, 3);
+	ipic_set_priority(MPC83xx_IRQ_EXT0, 4);
+	ipic_set_priority(MPC83xx_IRQ_EXT1, 5);
+	ipic_set_priority(MPC83xx_IRQ_EXT2, 6);
+	ipic_set_priority(MPC83xx_IRQ_EXT3, 7);
+	ipic_set_priority(MPC83xx_IRQ_RTC_ALR, 0);
+	ipic_set_priority(MPC83xx_IRQ_MU, 1);
+	ipic_set_priority(MPC83xx_IRQ_SBA, 2);
+	ipic_set_priority(MPC83xx_IRQ_DMA, 3);
+	ipic_set_priority(MPC83xx_IRQ_EXT4, 4);
+	ipic_set_priority(MPC83xx_IRQ_EXT5, 5);
+	ipic_set_priority(MPC83xx_IRQ_EXT6, 6);
+	ipic_set_priority(MPC83xx_IRQ_EXT7, 7);
+}
+
+void ipic_enable_mcp(enum ipic_mcp_irq mcp_irq)
+{
+	struct ipic *ipic = primary_ipic;
+	u32 temp;
+
+	temp = ipic_read(ipic->regs, IPIC_SERMR);
+	temp |= (1 << (31 - mcp_irq));
+	ipic_write(ipic->regs, IPIC_SERMR, temp);
+}
+
+void ipic_disable_mcp(enum ipic_mcp_irq mcp_irq)
+{
+	struct ipic *ipic = primary_ipic;
+	u32 temp;
+
+	temp = ipic_read(ipic->regs, IPIC_SERMR);
+	temp &= (1 << (31 - mcp_irq));
+	ipic_write(ipic->regs, IPIC_SERMR, temp);
+}
+
+u32 ipic_get_mcp_status(void)
+{
+	return ipic_read(primary_ipic->regs, IPIC_SERMR);
+}
+
+void ipic_clear_mcp_status(u32 mask)
+{
+	ipic_write(primary_ipic->regs, IPIC_SERMR, mask);
+}
+
+/* Return an interrupt vector or -1 if no interrupt is pending. */
+int ipic_get_irq(struct pt_regs *regs)
+{
+	int irq;
+
+	irq = ipic_read(primary_ipic->regs, IPIC_SIVCR) & 0x7f;
+
+	if (irq == 0)    /* 0 --> no irq is pending */
+		irq = -1;
+
+	return irq;
+}
+
+static struct sysdev_class ipic_sysclass = {
+	set_kset_name("ipic"),
+};
+
+static struct sys_device device_ipic = {
+	.id		= 0,
+	.cls		= &ipic_sysclass,
+};
+
+static int __init init_ipic_sysfs(void)
+{
+	int rc;
+
+	if (!primary_ipic->regs)
+		return -ENODEV;
+	printk(KERN_DEBUG "Registering ipic with sysfs...\n");
+
+	rc = sysdev_class_register(&ipic_sysclass);
+	if (rc) {
+		printk(KERN_ERR "Failed registering ipic sys class\n");
+		return -ENODEV;
+	}
+	rc = sysdev_register(&device_ipic);
+	if (rc) {
+		printk(KERN_ERR "Failed registering ipic sys device\n");
+		return -ENODEV;
+	}
+	return 0;
+}
+
+subsys_initcall(init_ipic_sysfs);
diff -Nru a/arch/ppc/syslib/ipic.h b/arch/ppc/syslib/ipic.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/ppc/syslib/ipic.h	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,49 @@
+/*
+ * arch/ppc/kernel/ipic.h
+ *
+ * IPIC private definitions and structure.
+ *
+ * Maintainer: Kumar Gala <kumar.gala@freescale.com>
+ *
+ * Copyright 2005 Freescale Semiconductor, Inc
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+#ifndef __IPIC_H__
+#define __IPIC_H__
+
+#include <asm/ipic.h>
+
+#define MPC83xx_IPIC_SIZE	(0x00100)
+
+/* System Global Interrupt Configuration Register */
+#define	SICFR_IPSA	0x00010000
+#define	SICFR_IPSD	0x00080000
+#define	SICFR_MPSA	0x00200000
+#define	SICFR_MPSB	0x00400000
+
+/* System External Interrupt Mask Register */
+#define	SEMSR_SIRQ0	0x00008000
+
+/* System Error Control Register */
+#define SERCR_MCPR	0x00000001
+
+struct ipic {
+	volatile u32 __iomem	*regs;
+	unsigned int		irq_offset;
+};
+
+struct ipic_info {
+	u8	pend;		/* pending register offset from base */
+	u8	mask;		/* mask register offset from base */
+	u8	prio;		/* priority register offset from base */
+	u8	force;		/* force register offset from base */
+	u8	bit;		/* register bit position (as per doc)
+				   bit mask = 1 << (31 - bit) */
+	u8	prio_mask;	/* priority mask value */
+};
+
+#endif /* __IPIC_H__ */
diff -Nru a/arch/ppc/syslib/mv64360_pic.c b/arch/ppc/syslib/mv64360_pic.c
--- a/arch/ppc/syslib/mv64360_pic.c	2005-03-11 12:51:40 -08:00
+++ b/arch/ppc/syslib/mv64360_pic.c	2005-03-11 12:51:40 -08:00
@@ -64,7 +64,7 @@
 /* ========================== local declarations =========================== */
 
 struct hw_interrupt_type mv64360_pic = {
-	.typename = " mv64360_pic ",
+	.typename = " mv64360  ",
 	.enable   = mv64360_unmask_irq,
 	.disable  = mv64360_mask_irq,
 	.ack      = mv64360_mask_irq,
@@ -155,9 +155,10 @@
 	 */
 	int cpu_nr = smp_processor_id();
 	if (cpu_nr == 1) {
-		if (!(mv64x60_read(&bh, MV64360_IC_MAIN_CAUSE_LO) & (1 << 28)))
+		if (!(mv64x60_read(&bh, MV64360_IC_MAIN_CAUSE_LO) &
+		      (1 << MV64x60_IRQ_DOORBELL)))
 			return -1;
-		return 28;
+		return mv64360_irq_base + MV64x60_IRQ_DOORBELL;
 	}
 #endif
 
@@ -171,7 +172,7 @@
 		if (irq == -1)
 			irq = -2; /* bogus interrupt, should never happen */
 		else {
-			if ((irq >= 24) && (irq < 28)) {
+			if ((irq >= 24) && (irq < MV64x60_IRQ_DOORBELL)) {
 				irq_gpp = mv64x60_read(&bh,
 					MV64x60_GPP_INTR_CAUSE);
 				irq_gpp = __ilog2(irq_gpp &
@@ -217,8 +218,9 @@
 {
 #ifdef CONFIG_SMP
 	/* second CPU gets only doorbell interrupts */
-	if ((irq - mv64360_irq_base) == 28) {
-		mv64x60_set_bits(&bh, MV64360_IC_CPU1_INTR_MASK_LO, (1 << 28));
+	if ((irq - mv64360_irq_base) == MV64x60_IRQ_DOORBELL) {
+		mv64x60_set_bits(&bh, MV64360_IC_CPU1_INTR_MASK_LO,
+				 (1 << MV64x60_IRQ_DOORBELL));
 		return;
 	}
 #endif
@@ -257,8 +259,9 @@
 mv64360_mask_irq(unsigned int irq)
 {
 #ifdef CONFIG_SMP
-	if ((irq - mv64360_irq_base) == 28) {
-		mv64x60_clr_bits(&bh, MV64360_IC_CPU1_INTR_MASK_LO, (1 << 28));
+	if ((irq - mv64360_irq_base) == MV64x60_IRQ_DOORBELL) {
+		mv64x60_clr_bits(&bh, MV64360_IC_CPU1_INTR_MASK_LO,
+				 (1 << MV64x60_IRQ_DOORBELL));
 		return;
 	}
 #endif
@@ -371,7 +374,7 @@
 
 	/* Clear old errors and register CPU interface error intr handler */
 	mv64x60_write(&bh, MV64x60_CPU_ERR_CAUSE, 0);
-	if ((rc = request_irq(MV64x60_IRQ_CPU_ERR,
+	if ((rc = request_irq(MV64x60_IRQ_CPU_ERR + mv64360_irq_base,
 		mv64360_cpu_error_int_handler, SA_INTERRUPT, CPU_INTR_STR, 0)))
 		printk(KERN_WARNING "Can't register cpu error handler: %d", rc);
 
@@ -380,7 +383,7 @@
 
 	/* Clear old errors and register internal SRAM error intr handler */
 	mv64x60_write(&bh, MV64360_SRAM_ERR_CAUSE, 0);
-	if ((rc = request_irq(MV64360_IRQ_SRAM_PAR_ERR,
+	if ((rc = request_irq(MV64360_IRQ_SRAM_PAR_ERR + mv64360_irq_base,
 		mv64360_sram_error_int_handler,SA_INTERRUPT,SRAM_INTR_STR, 0)))
 		printk(KERN_WARNING "Can't register SRAM error handler: %d",rc);
 
@@ -397,7 +400,8 @@
 
 	/* Clear old errors and register PCI 0 error intr handler */
 	mv64x60_write(&bh, MV64x60_PCI0_ERR_CAUSE, 0);
-	if ((rc = request_irq(MV64360_IRQ_PCI0, mv64360_pci_error_int_handler,
+	if ((rc = request_irq(MV64360_IRQ_PCI0 + mv64360_irq_base,
+			mv64360_pci_error_int_handler,
 			SA_INTERRUPT, PCI0_INTR_STR, (void *)0)))
 		printk(KERN_WARNING "Can't register pci 0 error handler: %d",
 			rc);
@@ -407,7 +411,8 @@
 
 	/* Clear old errors and register PCI 1 error intr handler */
 	mv64x60_write(&bh, MV64x60_PCI1_ERR_CAUSE, 0);
-	if ((rc = request_irq(MV64360_IRQ_PCI1, mv64360_pci_error_int_handler,
+	if ((rc = request_irq(MV64360_IRQ_PCI1 + mv64360_irq_base,
+			mv64360_pci_error_int_handler,
 			SA_INTERRUPT, PCI1_INTR_STR, (void *)1)))
 		printk(KERN_WARNING "Can't register pci 1 error handler: %d",
 			rc);
diff -Nru a/arch/ppc/syslib/mv64x60.c b/arch/ppc/syslib/mv64x60.c
--- a/arch/ppc/syslib/mv64x60.c	2005-03-11 12:51:42 -08:00
+++ b/arch/ppc/syslib/mv64x60.c	2005-03-11 12:51:42 -08:00
@@ -314,15 +314,15 @@
 static struct resource mv64x60_eth_shared_resources[] = {
 	[0] = {
 		.name	= "ethernet shared base",
-		.start	= MV64340_ETH_SHARED_REGS,
-		.end	= MV64340_ETH_SHARED_REGS +
-					MV64340_ETH_SHARED_REGS_SIZE - 1,
+		.start	= MV643XX_ETH_SHARED_REGS,
+		.end	= MV643XX_ETH_SHARED_REGS +
+					MV643XX_ETH_SHARED_REGS_SIZE - 1,
 		.flags	= IORESOURCE_MEM,
 	},
 };
 
 static struct platform_device mv64x60_eth_shared_device = {
-	.name		= MV64XXX_ETH_SHARED_NAME,
+	.name		= MV643XX_ETH_SHARED_NAME,
 	.id		= 0,
 	.num_resources	= ARRAY_SIZE(mv64x60_eth_shared_resources),
 	.resource	= mv64x60_eth_shared_resources,
@@ -338,10 +338,10 @@
 	},
 };
 
-static struct mv64xxx_eth_platform_data eth0_pd;
+static struct mv643xx_eth_platform_data eth0_pd;
 
 static struct platform_device eth0_device = {
-	.name		= MV64XXX_ETH_NAME,
+	.name		= MV643XX_ETH_NAME,
 	.id		= 0,
 	.num_resources	= ARRAY_SIZE(mv64x60_eth0_resources),
 	.resource	= mv64x60_eth0_resources,
@@ -361,10 +361,10 @@
 	},
 };
 
-static struct mv64xxx_eth_platform_data eth1_pd;
+static struct mv643xx_eth_platform_data eth1_pd;
 
 static struct platform_device eth1_device = {
-	.name		= MV64XXX_ETH_NAME,
+	.name		= MV643XX_ETH_NAME,
 	.id		= 1,
 	.num_resources	= ARRAY_SIZE(mv64x60_eth1_resources),
 	.resource	= mv64x60_eth1_resources,
@@ -384,10 +384,10 @@
 	},
 };
 
-static struct mv64xxx_eth_platform_data eth2_pd;
+static struct mv643xx_eth_platform_data eth2_pd;
 
 static struct platform_device eth2_device = {
-	.name		= MV64XXX_ETH_NAME,
+	.name		= MV643XX_ETH_NAME,
 	.id		= 2,
 	.num_resources	= ARRAY_SIZE(mv64x60_eth2_resources),
 	.resource	= mv64x60_eth2_resources,
diff -Nru a/arch/ppc/syslib/ppc4xx_pic.c b/arch/ppc/syslib/ppc4xx_pic.c
--- a/arch/ppc/syslib/ppc4xx_pic.c	2005-03-11 12:51:40 -08:00
+++ b/arch/ppc/syslib/ppc4xx_pic.c	2005-03-11 12:51:40 -08:00
@@ -4,7 +4,7 @@
  * Interrupt controller driver for PowerPC 4xx-based processors.
  *
  * Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net>
- * Copyright (c) 2004 Zultys Technologies
+ * Copyright (c) 2004, 2005 Zultys Technologies
  *
  * Based on original code by
  *    Copyright (c) 1999 Grant Erickson <grant@lcse.umn.edu>
@@ -29,8 +29,9 @@
 /* See comment in include/arch-ppc/ppc4xx_pic.h
  * for more info about these two variables
  */
-extern struct ppc4xx_uic_settings ppc4xx_core_uic_cfg[NR_UICS] __attribute__((weak));
-extern unsigned char ppc4xx_uic_ext_irq_cfg[] __attribute__((weak));
+extern struct ppc4xx_uic_settings ppc4xx_core_uic_cfg[NR_UICS]
+    __attribute__ ((weak));
+extern unsigned char ppc4xx_uic_ext_irq_cfg[] __attribute__ ((weak));
 
 #define IRQ_MASK_UIC0(irq)		(1 << (31 - (irq)))
 #define IRQ_MASK_UICx(irq)		(1 << (31 - ((irq) & 0x1f)))
@@ -48,6 +49,7 @@
 {									\
 	ppc_cached_irq_mask[n] &= ~IRQ_MASK_UIC##n(irq);		\
 	mtdcr(DCRN_UIC_ER(UIC##n), ppc_cached_irq_mask[n]);		\
+	ACK_UIC##n##_PARENT						\
 }									\
 									\
 static void ppc4xx_uic##n##_ack(unsigned int irq)			\
@@ -63,11 +65,11 @@
 {									\
 	unsigned int status = irq_desc[irq].status;			\
 	u32 mask = IRQ_MASK_UIC##n(irq);				\
-	if (status & IRQ_LEVEL){					\
+	if (status & IRQ_LEVEL) {					\
 		mtdcr(DCRN_UIC_SR(UIC##n), mask);			\
 		ACK_UIC##n##_PARENT					\
 	}								\
-	if (!(status & (IRQ_DISABLED | IRQ_INPROGRESS))){		\
+	if (!(status & (IRQ_DISABLED | IRQ_INPROGRESS))) {		\
 		ppc_cached_irq_mask[n] |= mask;				\
 		mtdcr(DCRN_UIC_ER(UIC##n), ppc_cached_irq_mask[n]);	\
 	}								\
@@ -86,7 +88,9 @@
 #define ACK_UIC0_PARENT	mtdcr(DCRN_UIC_SR(UICB), UICB_UIC0NC);
 #define ACK_UIC1_PARENT	mtdcr(DCRN_UIC_SR(UICB), UICB_UIC1NC);
 #define ACK_UIC2_PARENT	mtdcr(DCRN_UIC_SR(UICB), UICB_UIC2NC);
-UIC_HANDLERS(0); UIC_HANDLERS(1); UIC_HANDLERS(2);
+UIC_HANDLERS(0);
+UIC_HANDLERS(1);
+UIC_HANDLERS(2);
 
 static int ppc4xx_pic_get_irq(struct pt_regs *regs)
 {
@@ -114,7 +118,8 @@
 #elif NR_UICS == 2
 #define ACK_UIC0_PARENT
 #define ACK_UIC1_PARENT	mtdcr(DCRN_UIC_SR(UIC0), UIC0_UIC1NC);
-UIC_HANDLERS(0); UIC_HANDLERS(1);
+UIC_HANDLERS(0);
+UIC_HANDLERS(1);
 
 static int ppc4xx_pic_get_irq(struct pt_regs *regs)
 {
@@ -143,18 +148,20 @@
 	return uic0 ? 32 - ffs(uic0) : -1;
 }
 
-static inline void ppc4xx_pic_impl_init(void){}
+static inline void ppc4xx_pic_impl_init(void)
+{
+}
 #endif
 
 static struct ppc4xx_uic_impl {
 	struct hw_interrupt_type decl;
-	int			 base;		/* Base DCR number */
+	int base;			/* Base DCR number */
 } __uic[] = {
-    { .decl = DECLARE_UIC(0), .base = UIC0 },
+	{ .decl = DECLARE_UIC(0), .base = UIC0 },
 #if NR_UICS > 1
-    { .decl = DECLARE_UIC(1), .base = UIC1 },
+	{ .decl = DECLARE_UIC(1), .base = UIC1 },
 #if NR_UICS > 2
-    { .decl = DECLARE_UIC(2), .base = UIC2 },
+	{ .decl = DECLARE_UIC(2), .base = UIC2 },
 #endif
 #endif
 };
@@ -168,9 +175,9 @@
 void __init ppc4xx_pic_init(void)
 {
 	int i;
-	unsigned char* eirqs = ppc4xx_uic_ext_irq_cfg;
+	unsigned char *eirqs = ppc4xx_uic_ext_irq_cfg;
 
-	for (i = 0; i < NR_UICS; ++i){
+	for (i = 0; i < NR_UICS; ++i) {
 		int base = __uic[i].base;
 
 		/* Disable everything by default */
@@ -181,23 +188,23 @@
 		mtdcr(DCRN_UIC_CR(base), 0);
 
 		/* Configure polarity and triggering */
-		if (ppc4xx_core_uic_cfg){
-			struct ppc4xx_uic_settings* p = ppc4xx_core_uic_cfg + i;
+		if (ppc4xx_core_uic_cfg) {
+			struct ppc4xx_uic_settings *p = ppc4xx_core_uic_cfg + i;
 			u32 mask = p->ext_irq_mask;
 			u32 pr = mfdcr(DCRN_UIC_PR(base)) & mask;
 			u32 tr = mfdcr(DCRN_UIC_TR(base)) & mask;
 
 			/* "Fixed" interrupts (on-chip devices) */
-			pr |= p->polarity   & ~mask;
+			pr |= p->polarity & ~mask;
 			tr |= p->triggering & ~mask;
 
 			/* Merge external IRQs settings if board port
 			 * provided them
 			 */
-			if (eirqs && mask){
+			if (eirqs && mask) {
 				pr &= ~mask;
 				tr &= ~mask;
-				while (mask){
+				while (mask) {
 					/* Extract current external IRQ mask */
 					u32 eirq_mask = 1 << __ilog2(mask);
 
@@ -227,8 +234,8 @@
 	ppc4xx_pic_impl_init();
 
 	/* Attach low-level handlers */
-	for (i = 0; i < (NR_UICS << 5); ++i){
-    		irq_desc[i].handler = &__uic[i >> 5].decl;
+	for (i = 0; i < (NR_UICS << 5); ++i) {
+		irq_desc[i].handler = &__uic[i >> 5].decl;
 		if (is_level_sensitive(i))
 			irq_desc[i].status |= IRQ_LEVEL;
 	}
diff -Nru a/arch/ppc/syslib/ppc83xx_setup.c b/arch/ppc/syslib/ppc83xx_setup.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/ppc/syslib/ppc83xx_setup.c	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,138 @@
+/*
+ * arch/ppc/syslib/ppc83xx_setup.c
+ *
+ * MPC83XX common board code
+ *
+ * Maintainer: Kumar Gala <kumar.gala@freescale.com>
+ *
+ * Copyright 2005 Freescale Semiconductor Inc.
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/serial.h>
+#include <linux/tty.h>	/* for linux/serial_core.h */
+#include <linux/serial_core.h>
+#include <linux/serial_8250.h>
+
+#include <asm/prom.h>
+#include <asm/time.h>
+#include <asm/mpc83xx.h>
+#include <asm/mmu.h>
+#include <asm/ppc_sys.h>
+#include <asm/kgdb.h>
+
+#include <syslib/ppc83xx_setup.h>
+
+phys_addr_t immrbar;
+
+/* Return the amount of memory */
+unsigned long __init
+mpc83xx_find_end_of_memory(void)
+{
+        bd_t *binfo;
+
+        binfo = (bd_t *) __res;
+
+        return binfo->bi_memsize;
+}
+
+long __init
+mpc83xx_time_init(void)
+{
+#define SPCR_OFFS   0x00000110
+#define SPCR_TBEN   0x00400000
+
+	bd_t *binfo = (bd_t *)__res;
+	u32 *spcr = ioremap(binfo->bi_immr_base + SPCR_OFFS, 4);
+
+	*spcr |= SPCR_TBEN;
+
+	iounmap(spcr);
+
+	return 0;
+}
+
+/* The decrementer counts at the system (internal) clock freq divided by 4 */
+void __init
+mpc83xx_calibrate_decr(void)
+{
+        bd_t *binfo = (bd_t *) __res;
+        unsigned int freq, divisor;
+
+	freq = binfo->bi_busfreq;
+	divisor = 4;
+	tb_ticks_per_jiffy = freq / HZ / divisor;
+	tb_to_us = mulhwu_scale_factor(freq / divisor, 1000000);
+}
+
+#ifdef CONFIG_SERIAL_8250
+void __init
+mpc83xx_early_serial_map(void)
+{
+#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB)
+	struct uart_port serial_req;
+#endif
+	struct plat_serial8250_port *pdata;
+	bd_t *binfo = (bd_t *) __res;
+	pdata = (struct plat_serial8250_port *) ppc_sys_get_pdata(MPC83xx_DUART);
+
+	/* Setup serial port access */
+	pdata[0].uartclk = binfo->bi_busfreq;
+	pdata[0].mapbase += binfo->bi_immr_base;
+	pdata[0].membase = ioremap(pdata[0].mapbase, 0x100);
+
+#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB)
+	memset(&serial_req, 0, sizeof (serial_req));
+	serial_req.iotype = SERIAL_IO_MEM;
+	serial_req.mapbase = pdata[0].mapbase;
+	serial_req.membase = pdata[0].membase;
+	serial_req.regshift = 0;
+
+	gen550_init(0, &serial_req);
+#endif
+
+	pdata[1].uartclk = binfo->bi_busfreq;
+	pdata[1].mapbase += binfo->bi_immr_base;
+	pdata[1].membase = ioremap(pdata[1].mapbase, 0x100);
+
+#if defined(CONFIG_SERIAL_TEXT_DEBUG) || defined(CONFIG_KGDB)
+	/* Assume gen550_init() doesn't modify serial_req */
+	serial_req.mapbase = pdata[1].mapbase;
+	serial_req.membase = pdata[1].membase;
+
+	gen550_init(1, &serial_req);
+#endif
+}
+#endif
+
+void
+mpc83xx_restart(char *cmd)
+{
+	local_irq_disable();
+	for(;;);
+}
+
+void
+mpc83xx_power_off(void)
+{
+	local_irq_disable();
+	for(;;);
+}
+
+void
+mpc83xx_halt(void)
+{
+	local_irq_disable();
+	for(;;);
+}
+
+/* PCI SUPPORT DOES NOT EXIT, MODEL after ppc85xx_setup.c */
diff -Nru a/arch/ppc/syslib/ppc83xx_setup.h b/arch/ppc/syslib/ppc83xx_setup.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/ppc/syslib/ppc83xx_setup.h	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,53 @@
+/*
+ * arch/ppc/syslib/ppc83xx_setup.h
+ *
+ * MPC83XX common board definitions
+ *
+ * Maintainer: Kumar Gala <kumar.gala@freescale.com>
+ *
+ * Copyright 2005 Freescale Semiconductor Inc.
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ *
+ */
+
+#ifndef __PPC_SYSLIB_PPC83XX_SETUP_H
+#define __PPC_SYSLIB_PPC83XX_SETUP_H
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <asm/ppcboot.h>
+
+extern unsigned long mpc83xx_find_end_of_memory(void) __init;
+extern long mpc83xx_time_init(void) __init;
+extern void mpc83xx_calibrate_decr(void) __init;
+extern void mpc83xx_early_serial_map(void) __init;
+extern void mpc83xx_restart(char *cmd);
+extern void mpc83xx_power_off(void);
+extern void mpc83xx_halt(void);
+extern void mpc83xx_setup_hose(void) __init;
+
+/* PCI config */
+#if 0
+#define PCI1_CFG_ADDR_OFFSET	(FIXME)
+#define PCI1_CFG_DATA_OFFSET	(FIXME)
+
+#define PCI2_CFG_ADDR_OFFSET	(FIXME)
+#define PCI2_CFG_DATA_OFFSET	(FIXME)
+#endif
+
+/* Serial Config */
+#ifdef CONFIG_SERIAL_MANY_PORTS
+#define RS_TABLE_SIZE  64
+#else
+#define RS_TABLE_SIZE  2
+#endif
+
+#ifndef BASE_BAUD
+#define BASE_BAUD 115200
+#endif
+
+#endif /* __PPC_SYSLIB_PPC83XX_SETUP_H */
diff -Nru a/arch/ppc/syslib/todc_time.c b/arch/ppc/syslib/todc_time.c
--- a/arch/ppc/syslib/todc_time.c	2005-03-11 12:51:50 -08:00
+++ b/arch/ppc/syslib/todc_time.c	2005-03-11 12:51:50 -08:00
@@ -287,6 +287,7 @@
 		limit = 1;
 
 		switch (todc_info->rtc_type) {
+			case TODC_TYPE_DS1553:
 			case TODC_TYPE_DS1557:
 			case TODC_TYPE_DS1743:
 			case TODC_TYPE_DS1746:	/* XXXX BAD HACK -> FIX */
@@ -322,6 +323,7 @@
 
 	if (todc_info->rtc_type != TODC_TYPE_MC146818) {
 		switch (todc_info->rtc_type) {
+			case TODC_TYPE_DS1553:
 			case TODC_TYPE_DS1557:
 			case TODC_TYPE_DS1743:
 			case TODC_TYPE_DS1746:	/* XXXX BAD HACK -> FIX */
@@ -418,6 +420,7 @@
 	unsigned char save_control = 0, val;
 
 	switch (todc_info->rtc_type) {
+		case TODC_TYPE_DS1553:
 		case TODC_TYPE_DS1557:
 		case TODC_TYPE_DS1746:	/* XXXX BAD HACK -> FIX */
 		case TODC_TYPE_DS1747:
@@ -432,6 +435,7 @@
 	val = todc_read_val(addr);
 
 	switch (todc_info->rtc_type) {
+		case TODC_TYPE_DS1553:
 		case TODC_TYPE_DS1557:
 		case TODC_TYPE_DS1746:	/* XXXX BAD HACK -> FIX */
 		case TODC_TYPE_DS1747:
diff -Nru a/arch/ppc/syslib/xilinx_pic.c b/arch/ppc/syslib/xilinx_pic.c
--- a/arch/ppc/syslib/xilinx_pic.c	2005-03-11 12:51:51 -08:00
+++ b/arch/ppc/syslib/xilinx_pic.c	2005-03-11 12:51:51 -08:00
@@ -114,6 +114,14 @@
 {
 	int i;
 
+	/*
+	 * NOTE: The assumption here is that NR_IRQS is 32 or less
+	 * (NR_IRQS is 32 for PowerPC 405 cores by default).
+	 */
+#if (NR_IRQS > 32)
+#error NR_IRQS > 32 not supported
+#endif
+
 #if XPAR_XINTC_USE_DCR == 0
 	intc = ioremap(XPAR_INTC_0_BASEADDR, 32);
 
@@ -138,6 +146,12 @@
 
 	ppc_md.get_irq = xilinx_pic_get_irq;
 
-	for (i = 0; i < NR_IRQS; ++i)
+	for (i = 0; i < NR_IRQS; ++i) {
 		irq_desc[i].handler = &xilinx_intc;
+
+		if (XPAR_INTC_0_KIND_OF_INTR & (0x00000001 << i))
+			irq_desc[i].status &= ~IRQ_LEVEL;
+		else
+			irq_desc[i].status |= IRQ_LEVEL;
+	}
 }
diff -Nru a/arch/ppc64/Kconfig b/arch/ppc64/Kconfig
--- a/arch/ppc64/Kconfig	2005-03-11 12:51:46 -08:00
+++ b/arch/ppc64/Kconfig	2005-03-11 12:51:46 -08:00
@@ -194,7 +194,10 @@
 
 config HMT
 	bool "Hardware multithreading"
-	depends on SMP && PPC_PSERIES
+	depends on SMP && PPC_PSERIES && BROKEN
+	help
+	  This option enables hardware multithreading on RS64 cpus.
+	  pSeries systems p620 and p660 have such a cpu type.
 
 config DISCONTIGMEM
 	bool "Discontiguous Memory Support"
@@ -313,7 +316,7 @@
 
 config HOTPLUG_CPU
 	bool "Support for hot-pluggable CPUs"
-	depends on SMP && EXPERIMENTAL && PPC_PSERIES
+	depends on SMP && EXPERIMENTAL && (PPC_PSERIES || PPC_PMAC)
 	select HOTPLUG
 	---help---
 	  Say Y here to be able to turn CPUs off and on.
diff -Nru a/arch/ppc64/Makefile b/arch/ppc64/Makefile
--- a/arch/ppc64/Makefile	2005-03-11 12:51:41 -08:00
+++ b/arch/ppc64/Makefile	2005-03-11 12:51:41 -08:00
@@ -15,17 +15,38 @@
 
 KERNELLOAD	:= 0xc000000000000000
 
+# Set default 32 bits cross compilers for vdso and boot wrapper
+CROSS32_COMPILE ?=
+
+CROSS32CC		:= $(CROSS32_COMPILE)gcc
+CROSS32AS		:= $(CROSS32_COMPILE)as
+CROSS32LD		:= $(CROSS32_COMPILE)ld
+CROSS32OBJCOPY		:= $(CROSS32_COMPILE)objcopy
+
+# If we have a biarch compiler, use it for 32 bits cross compile if
+# CROSS32_COMPILE wasn't explicitely defined, and add proper explicit
+# target type to target compilers
+
 HAS_BIARCH      := $(call cc-option-yn, -m64)
 ifeq ($(HAS_BIARCH),y)
+ifeq ($(CROSS32_COMPILE),)
+CROSS32CC	:= $(CC) -m32
+CROSS32AS	:= $(AS) -a32
+CROSS32LD	:= $(LD) -m elf32ppc
+CROSS32OBJCOPY	:= $(OBJCOPY)
+endif
 AS              := $(AS) -a64
 LD              := $(LD) -m elf64ppc
 CC		:= $(CC) -m64
 endif
 
+export CROSS32CC CROSS32AS CROSS32LD CROSS32OBJCOPY
+
 new_nm := $(shell if $(NM) --help 2>&1 | grep -- '--synthetic' > /dev/null; then echo y; else echo n; fi)
 
 ifeq ($(new_nm),y)
 NM		:= $(NM) --synthetic
+
 endif
 
 CHECKFLAGS	+= -m64 -D__powerpc__
@@ -65,14 +86,20 @@
 $(boottarget-y): vmlinux
 	$(Q)$(MAKE) $(build)=$(boot) $(boot)/$@
 
-bootimage-$(CONFIG_PPC_PSERIES) := zImage
-bootimage-$(CONFIG_PPC_MAPLE) := zImage
+bootimage-$(CONFIG_PPC_PSERIES) := $(boot)/zImage
+bootimage-$(CONFIG_PPC_PMAC) := vmlinux
+bootimage-$(CONFIG_PPC_MAPLE) := $(boot)/zImage
 bootimage-$(CONFIG_PPC_ISERIES) := vmlinux
 BOOTIMAGE := $(bootimage-y)
 install: vmlinux
 	$(Q)$(MAKE) $(build)=$(boot) BOOTIMAGE=$(BOOTIMAGE) $@
 
-all: $(BOOTIMAGE)
+defaultimage-$(CONFIG_PPC_PSERIES) := zImage
+defaultimage-$(CONFIG_PPC_PMAC) := vmlinux
+defaultimage-$(CONFIG_PPC_MAPLE) := zImage
+defaultimage-$(CONFIG_PPC_ISERIES) := vmlinux
+KBUILD_IMAGE := $(defaultimage-y)
+all: $(KBUILD_IMAGE)
 
 archclean:
 	$(Q)$(MAKE) $(clean)=$(boot)
diff -Nru a/arch/ppc64/boot/Makefile b/arch/ppc64/boot/Makefile
--- a/arch/ppc64/boot/Makefile	2005-03-11 12:51:51 -08:00
+++ b/arch/ppc64/boot/Makefile	2005-03-11 12:51:51 -08:00
@@ -20,17 +20,11 @@
 #	CROSS32_COMPILE is setup as a prefix just like CROSS_COMPILE
 #	in the toplevel makefile.
 
-CROSS32_COMPILE ?=
-#CROSS32_COMPILE = /usr/local/ppc/bin/powerpc-linux-
 
-BOOTCC		:= $(CROSS32_COMPILE)gcc
 HOSTCC		:= gcc
 BOOTCFLAGS	:= $(HOSTCFLAGS) $(LINUXINCLUDE) -fno-builtin 
-BOOTAS		:= $(CROSS32_COMPILE)as
 BOOTAFLAGS	:= -D__ASSEMBLY__ $(BOOTCFLAGS) -traditional
-BOOTLD		:= $(CROSS32_COMPILE)ld
 BOOTLFLAGS	:= -Ttext 0x00400000 -e _start -T $(srctree)/$(src)/zImage.lds
-BOOTOBJCOPY	:= $(CROSS32_COMPILE)objcopy
 OBJCOPYFLAGS    := contents,alloc,load,readonly,data
 
 src-boot := crt0.S string.S prom.c main.c zlib.c imagesize.c div64.S
@@ -38,10 +32,10 @@
 obj-boot := $(addsuffix .o, $(basename $(src-boot)))
 
 quiet_cmd_bootcc = BOOTCC  $@
-      cmd_bootcc = $(BOOTCC) -Wp,-MD,$(depfile) $(BOOTCFLAGS) -c -o $@ $<
+      cmd_bootcc = $(CROSS32CC) -Wp,-MD,$(depfile) $(BOOTCFLAGS) -c -o $@ $<
 
 quiet_cmd_bootas = BOOTAS  $@
-      cmd_bootas = $(BOOTCC) -Wp,-MD,$(depfile) $(BOOTAFLAGS) -c -o $@ $<
+      cmd_bootas = $(CROSS32CC) -Wp,-MD,$(depfile) $(BOOTAFLAGS) -c -o $@ $<
 
 $(patsubst %.c,%.o, $(filter %.c, $(src-boot))): %.o: %.c
 	$(call if_changed_dep,bootcc)
@@ -77,15 +71,15 @@
 $(obj)/vmlinux.initrd: vmlinux.strip $(obj)/addRamDisk $(obj)/ramdisk.image.gz FORCE
 	$(call if_changed,ramdisk)
 
-addsection = $(BOOTOBJCOPY) $(1) \
+addsection = $(CROSS32OBJCOPY) $(1) \
 		--add-section=.kernel:$(strip $(patsubst $(obj)/kernel-%.o,%, $(1)))=$(patsubst %.o,%.gz, $(1)) \
 		--set-section-flags=.kernel:$(strip $(patsubst $(obj)/kernel-%.o,%, $(1)))=$(OBJCOPYFLAGS)
 
 quiet_cmd_addnote = ADDNOTE $@ 
-      cmd_addnote = $(BOOTLD) $(BOOTLFLAGS) -o $@ $(obj-boot) && $(obj)/addnote $@
+      cmd_addnote = $(CROSS32LD) $(BOOTLFLAGS) -o $@ $(obj-boot) && $(obj)/addnote $@
 
 quiet_cmd_piggy = PIGGY   $@
-      cmd_piggy = $(obj)/piggyback $(@:.o=) < $< | $(BOOTAS) -o $@
+      cmd_piggy = $(obj)/piggyback $(@:.o=) < $< | $(CROSS32AS) -o $@
 
 $(call gz-sec, $(required)): $(obj)/kernel-%.gz: % FORCE
 	$(call if_changed,gzip)
@@ -117,7 +111,7 @@
 	awk '{printf "unsigned long vmlinux_memsize = 0x%s;\n", substr($$1,8)}' \
 		>> $(obj)/imagesize.c
 
-install: $(CONFIGURE) $(obj)/$(BOOTIMAGE)
-	sh -x $(srctree)/$(src)/install.sh "$(KERNELRELEASE)" "$(obj)/$(BOOTIMAGE)" "$(INSTALL_PATH)"
+install: $(CONFIGURE) $(BOOTIMAGE)
+	sh -x $(srctree)/$(src)/install.sh "$(KERNELRELEASE)" vmlinux System.map "$(INSTALL_PATH)" "$(BOOTIMAGE)"
 
 clean-files := $(addprefix $(objtree)/, $(obj-boot) vmlinux.strip)
diff -Nru a/arch/ppc64/boot/install.sh b/arch/ppc64/boot/install.sh
--- a/arch/ppc64/boot/install.sh	2005-03-11 12:51:52 -08:00
+++ b/arch/ppc64/boot/install.sh	2005-03-11 12:51:52 -08:00
@@ -17,6 +17,7 @@
 #   $2 - kernel image file
 #   $3 - kernel map file
 #   $4 - default install path (blank if root directory)
+#   $5 - kernel boot file, the zImage
 #
 
 # User may have a custom install script
@@ -27,7 +28,7 @@
 # Default install
 
 # this should work for both the pSeries zImage and the iSeries vmlinux.sm
-image_name=`basename $2`
+image_name=`basename $5`
 
 if [ -f $4/$image_name ]; then
 	mv $4/$image_name $4/$image_name.old
diff -Nru a/arch/ppc64/boot/main.c b/arch/ppc64/boot/main.c
--- a/arch/ppc64/boot/main.c	2005-03-11 12:51:52 -08:00
+++ b/arch/ppc64/boot/main.c	2005-03-11 12:51:52 -08:00
@@ -200,7 +200,7 @@
 	vmlinux.addr += (unsigned long)elf64ph->p_offset;
 	vmlinux.size -= (unsigned long)elf64ph->p_offset;
 
-	flush_cache((void *)vmlinux.addr, vmlinux.memsize);
+	flush_cache((void *)vmlinux.addr, vmlinux.size);
 
 	if (a1)
 		printf("initrd head: 0x%lx\n\r", *((u32 *)initrd.addr));
diff -Nru a/arch/ppc64/configs/g5_defconfig b/arch/ppc64/configs/g5_defconfig
--- a/arch/ppc64/configs/g5_defconfig	2005-03-11 12:51:41 -08:00
+++ b/arch/ppc64/configs/g5_defconfig	2005-03-11 12:51:41 -08:00
@@ -1,11 +1,12 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.9-rc3
-# Thu Oct  7 15:18:38 2004
+# Linux kernel version: 2.6.11-rc3-bk6
+# Wed Feb  9 23:34:53 2005
 #
 CONFIG_64BIT=y
 CONFIG_MMU=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_ISA_DMA=y
 CONFIG_HAVE_DEC_LOCK=y
 CONFIG_EARLY_PRINTK=y
@@ -18,6 +19,7 @@
 #
 CONFIG_EXPERIMENTAL=y
 CONFIG_CLEAN_COMPILE=y
+CONFIG_LOCK_KERNEL=y
 
 #
 # General setup
@@ -25,25 +27,26 @@
 CONFIG_LOCALVERSION=""
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
-# CONFIG_POSIX_MQUEUE is not set
+CONFIG_POSIX_MQUEUE=y
 # CONFIG_BSD_PROCESS_ACCT is not set
 CONFIG_SYSCTL=y
-# CONFIG_AUDIT is not set
 CONFIG_LOG_BUF_SHIFT=17
 CONFIG_HOTPLUG=y
-# CONFIG_IKCONFIG is not set
+CONFIG_KOBJECT_UEVENT=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
 # CONFIG_EMBEDDED is not set
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_ALL is not set
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
 # CONFIG_TINY_SHMEM is not set
 
 #
@@ -51,10 +54,11 @@
 #
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
-CONFIG_MODULE_FORCE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
 CONFIG_OBSOLETE_MODPARM=y
-# CONFIG_MODVERSIONS is not set
-# CONFIG_KMOD is not set
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+CONFIG_KMOD=y
 CONFIG_STOP_MACHINE=y
 CONFIG_SYSVIPC_COMPAT=y
 
@@ -65,6 +69,7 @@
 CONFIG_PPC_MULTIPLATFORM=y
 # CONFIG_PPC_PSERIES is not set
 CONFIG_PPC_PMAC=y
+# CONFIG_PPC_MAPLE is not set
 CONFIG_PPC=y
 CONFIG_PPC64=y
 CONFIG_PPC_OF=y
@@ -75,12 +80,10 @@
 CONFIG_POWER4_ONLY=y
 CONFIG_IOMMU_VMERGE=y
 CONFIG_SMP=y
-CONFIG_IRQ_ALL_CPUS=y
 CONFIG_NR_CPUS=2
 # CONFIG_SCHED_SMT is not set
 # CONFIG_PREEMPT is not set
-# CONFIG_PPC_RTAS is not set
-# CONFIG_LPARCFG is not set
+CONFIG_GENERIC_HARDIRQS=y
 
 #
 # General setup
@@ -91,12 +94,15 @@
 # CONFIG_BINFMT_MISC is not set
 CONFIG_PCI_LEGACY_PROC=y
 CONFIG_PCI_NAMES=y
-# CONFIG_HOTPLUG_CPU is not set
 
 #
-# PCMCIA/CardBus support
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PC-card bridges
 #
-# CONFIG_PCMCIA is not set
 
 #
 # PCI Hotplug Support
@@ -139,14 +145,29 @@
 # CONFIG_BLK_CPQ_CISS_DA is not set
 # CONFIG_BLK_DEV_DAC960 is not set
 # CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
 CONFIG_BLK_DEV_LOOP=y
 # CONFIG_BLK_DEV_CRYPTOLOOP is not set
 CONFIG_BLK_DEV_NBD=m
 # CONFIG_BLK_DEV_SX8 is not set
 # CONFIG_BLK_DEV_UB is not set
 CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_SIZE=8192
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=65536
 CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_CDROM_PKTCDVD=m
+CONFIG_CDROM_PKTCDVD_BUFFERS=8
+# CONFIG_CDROM_PKTCDVD_WCACHE is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
 
 #
 # ATA/ATAPI/MFM/RLL support
@@ -161,11 +182,10 @@
 CONFIG_BLK_DEV_IDEDISK=y
 # CONFIG_IDEDISK_MULTI_MODE is not set
 CONFIG_BLK_DEV_IDECD=y
-CONFIG_BLK_DEV_IDETAPE=y
-CONFIG_BLK_DEV_IDEFLOPPY=y
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
 # CONFIG_BLK_DEV_IDESCSI is not set
 # CONFIG_IDE_TASK_IOCTL is not set
-# CONFIG_IDE_TASKFILE_IO is not set
 
 #
 # IDE chipset support/bugfixes
@@ -205,7 +225,6 @@
 CONFIG_BLK_DEV_IDE_PMAC_ATA100FIRST=y
 CONFIG_BLK_DEV_IDEDMA_PMAC=y
 # CONFIG_BLK_DEV_IDE_PMAC_BLINK is not set
-CONFIG_BLK_DEV_IDEDMA_PMAC_AUTO=y
 # CONFIG_IDE_ARM is not set
 CONFIG_BLK_DEV_IDEDMA=y
 # CONFIG_IDEDMA_IVB is not set
@@ -240,6 +259,7 @@
 #
 CONFIG_SCSI_SPI_ATTRS=y
 # CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
 
 #
 # SCSI low-level drivers
@@ -254,6 +274,7 @@
 # CONFIG_MEGARAID_NEWGEN is not set
 # CONFIG_MEGARAID_LEGACY is not set
 CONFIG_SCSI_SATA=y
+# CONFIG_SCSI_SATA_AHCI is not set
 CONFIG_SCSI_SATA_SVW=y
 # CONFIG_SCSI_ATA_PIIX is not set
 # CONFIG_SCSI_SATA_NV is not set
@@ -261,6 +282,7 @@
 # CONFIG_SCSI_SATA_SX4 is not set
 # CONFIG_SCSI_SATA_SIL is not set
 # CONFIG_SCSI_SATA_SIS is not set
+# CONFIG_SCSI_SATA_ULI is not set
 # CONFIG_SCSI_SATA_VIA is not set
 # CONFIG_SCSI_SATA_VITESSE is not set
 # CONFIG_SCSI_BUSLOGIC is not set
@@ -270,12 +292,9 @@
 # CONFIG_SCSI_FUTURE_DOMAIN is not set
 # CONFIG_SCSI_GDTH is not set
 # CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INITIO is not set
 # CONFIG_SCSI_INIA100 is not set
-CONFIG_SCSI_SYM53C8XX_2=y
-CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=0
-CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
-CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
-# CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set
+# CONFIG_SCSI_SYM53C8XX_2 is not set
 # CONFIG_SCSI_IPR is not set
 # CONFIG_SCSI_QLOGIC_ISP is not set
 # CONFIG_SCSI_QLOGIC_FC is not set
@@ -286,11 +305,9 @@
 # CONFIG_SCSI_QLA2300 is not set
 # CONFIG_SCSI_QLA2322 is not set
 # CONFIG_SCSI_QLA6312 is not set
-# CONFIG_SCSI_QLA6322 is not set
 # CONFIG_SCSI_DC395x is not set
 # CONFIG_SCSI_DC390T is not set
 # CONFIG_SCSI_DEBUG is not set
-# CONFIG_SCSI_MAC53C94 is not set
 
 #
 # Multi-device support (RAID and LVM)
@@ -300,15 +317,16 @@
 CONFIG_MD_LINEAR=y
 CONFIG_MD_RAID0=y
 CONFIG_MD_RAID1=y
-# CONFIG_MD_RAID10 is not set
+CONFIG_MD_RAID10=m
 CONFIG_MD_RAID5=y
-# CONFIG_MD_RAID6 is not set
-# CONFIG_MD_MULTIPATH is not set
+CONFIG_MD_RAID6=m
+CONFIG_MD_MULTIPATH=m
+CONFIG_MD_FAULTY=m
 CONFIG_BLK_DEV_DM=y
-# CONFIG_DM_CRYPT is not set
-# CONFIG_DM_SNAPSHOT is not set
-# CONFIG_DM_MIRROR is not set
-# CONFIG_DM_ZERO is not set
+CONFIG_DM_CRYPT=m
+CONFIG_DM_SNAPSHOT=m
+CONFIG_DM_MIRROR=m
+CONFIG_DM_ZERO=m
 
 #
 # Fusion MPT device support
@@ -386,6 +404,8 @@
 CONFIG_INET_ESP=m
 CONFIG_INET_IPCOMP=m
 CONFIG_INET_TUNNEL=y
+CONFIG_IP_TCPDIAG=m
+# CONFIG_IP_TCPDIAG_IPV6 is not set
 
 #
 # IP: Virtual Server Configuration
@@ -398,61 +418,71 @@
 #
 # IP: Netfilter Configuration
 #
-CONFIG_IP_NF_CONNTRACK=y
-# CONFIG_IP_NF_CT_ACCT is not set
-# CONFIG_IP_NF_CT_PROTO_SCTP is not set
-# CONFIG_IP_NF_FTP is not set
-# CONFIG_IP_NF_IRC is not set
-# CONFIG_IP_NF_TFTP is not set
-# CONFIG_IP_NF_AMANDA is not set
-CONFIG_IP_NF_QUEUE=y
-CONFIG_IP_NF_IPTABLES=y
-CONFIG_IP_NF_MATCH_LIMIT=y
-CONFIG_IP_NF_MATCH_IPRANGE=y
-CONFIG_IP_NF_MATCH_MAC=y
-CONFIG_IP_NF_MATCH_PKTTYPE=y
-CONFIG_IP_NF_MATCH_MARK=y
-CONFIG_IP_NF_MATCH_MULTIPORT=y
-CONFIG_IP_NF_MATCH_TOS=y
-CONFIG_IP_NF_MATCH_RECENT=y
-CONFIG_IP_NF_MATCH_ECN=y
-CONFIG_IP_NF_MATCH_DSCP=y
-CONFIG_IP_NF_MATCH_AH_ESP=y
-CONFIG_IP_NF_MATCH_LENGTH=y
-CONFIG_IP_NF_MATCH_TTL=y
-CONFIG_IP_NF_MATCH_TCPMSS=y
-CONFIG_IP_NF_MATCH_HELPER=y
-CONFIG_IP_NF_MATCH_STATE=y
-CONFIG_IP_NF_MATCH_CONNTRACK=y
-CONFIG_IP_NF_MATCH_OWNER=y
-# CONFIG_IP_NF_MATCH_ADDRTYPE is not set
-# CONFIG_IP_NF_MATCH_REALM is not set
-# CONFIG_IP_NF_MATCH_SCTP is not set
-# CONFIG_IP_NF_MATCH_COMMENT is not set
-CONFIG_IP_NF_FILTER=y
-CONFIG_IP_NF_TARGET_REJECT=y
-CONFIG_IP_NF_TARGET_LOG=y
-CONFIG_IP_NF_TARGET_ULOG=y
-CONFIG_IP_NF_TARGET_TCPMSS=y
-CONFIG_IP_NF_NAT=y
+CONFIG_IP_NF_CONNTRACK=m
+CONFIG_IP_NF_CT_ACCT=y
+CONFIG_IP_NF_CONNTRACK_MARK=y
+CONFIG_IP_NF_CT_PROTO_SCTP=m
+CONFIG_IP_NF_FTP=m
+CONFIG_IP_NF_IRC=m
+CONFIG_IP_NF_TFTP=m
+CONFIG_IP_NF_AMANDA=m
+CONFIG_IP_NF_QUEUE=m
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_MATCH_LIMIT=m
+CONFIG_IP_NF_MATCH_IPRANGE=m
+CONFIG_IP_NF_MATCH_MAC=m
+CONFIG_IP_NF_MATCH_PKTTYPE=m
+CONFIG_IP_NF_MATCH_MARK=m
+CONFIG_IP_NF_MATCH_MULTIPORT=m
+CONFIG_IP_NF_MATCH_TOS=m
+CONFIG_IP_NF_MATCH_RECENT=m
+CONFIG_IP_NF_MATCH_ECN=m
+CONFIG_IP_NF_MATCH_DSCP=m
+CONFIG_IP_NF_MATCH_AH_ESP=m
+CONFIG_IP_NF_MATCH_LENGTH=m
+CONFIG_IP_NF_MATCH_TTL=m
+CONFIG_IP_NF_MATCH_TCPMSS=m
+CONFIG_IP_NF_MATCH_HELPER=m
+CONFIG_IP_NF_MATCH_STATE=m
+CONFIG_IP_NF_MATCH_CONNTRACK=m
+CONFIG_IP_NF_MATCH_OWNER=m
+CONFIG_IP_NF_MATCH_ADDRTYPE=m
+CONFIG_IP_NF_MATCH_REALM=m
+CONFIG_IP_NF_MATCH_SCTP=m
+CONFIG_IP_NF_MATCH_COMMENT=m
+CONFIG_IP_NF_MATCH_CONNMARK=m
+CONFIG_IP_NF_MATCH_HASHLIMIT=m
+CONFIG_IP_NF_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_LOG=m
+CONFIG_IP_NF_TARGET_ULOG=m
+CONFIG_IP_NF_TARGET_TCPMSS=m
+CONFIG_IP_NF_NAT=m
 CONFIG_IP_NF_NAT_NEEDED=y
-CONFIG_IP_NF_TARGET_MASQUERADE=y
-CONFIG_IP_NF_TARGET_REDIRECT=y
-CONFIG_IP_NF_TARGET_NETMAP=y
-CONFIG_IP_NF_TARGET_SAME=y
-# CONFIG_IP_NF_NAT_SNMP_BASIC is not set
-CONFIG_IP_NF_MANGLE=y
-CONFIG_IP_NF_TARGET_TOS=y
-CONFIG_IP_NF_TARGET_ECN=y
-CONFIG_IP_NF_TARGET_DSCP=y
-CONFIG_IP_NF_TARGET_MARK=y
-CONFIG_IP_NF_TARGET_CLASSIFY=y
-# CONFIG_IP_NF_RAW is not set
-CONFIG_IP_NF_ARPTABLES=y
-CONFIG_IP_NF_ARPFILTER=y
-CONFIG_IP_NF_ARP_MANGLE=y
+CONFIG_IP_NF_TARGET_MASQUERADE=m
+CONFIG_IP_NF_TARGET_REDIRECT=m
+CONFIG_IP_NF_TARGET_NETMAP=m
+CONFIG_IP_NF_TARGET_SAME=m
+CONFIG_IP_NF_NAT_SNMP_BASIC=m
+CONFIG_IP_NF_NAT_IRC=m
+CONFIG_IP_NF_NAT_FTP=m
+CONFIG_IP_NF_NAT_TFTP=m
+CONFIG_IP_NF_NAT_AMANDA=m
+CONFIG_IP_NF_MANGLE=m
+CONFIG_IP_NF_TARGET_TOS=m
+CONFIG_IP_NF_TARGET_ECN=m
+CONFIG_IP_NF_TARGET_DSCP=m
+CONFIG_IP_NF_TARGET_MARK=m
+CONFIG_IP_NF_TARGET_CLASSIFY=m
+CONFIG_IP_NF_TARGET_CONNMARK=m
+CONFIG_IP_NF_TARGET_CLUSTERIP=m
+CONFIG_IP_NF_RAW=m
+CONFIG_IP_NF_TARGET_NOTRACK=m
+CONFIG_IP_NF_ARPTABLES=m
+CONFIG_IP_NF_ARPFILTER=m
+CONFIG_IP_NF_ARP_MANGLE=m
 CONFIG_XFRM=y
-# CONFIG_XFRM_USER is not set
+CONFIG_XFRM_USER=m
 
 #
 # SCTP Configuration (EXPERIMENTAL)
@@ -471,13 +501,12 @@
 # CONFIG_NET_DIVERT is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
-# CONFIG_NET_HW_FLOWCONTROL is not set
 
 #
 # QoS and/or fair queueing
 #
 # CONFIG_NET_SCHED is not set
-# CONFIG_NET_CLS_ROUTE is not set
+CONFIG_NET_CLS_ROUTE=y
 
 #
 # Network testing
@@ -587,7 +616,7 @@
 # Userland interfaces
 #
 CONFIG_INPUT_MOUSEDEV=y
-CONFIG_INPUT_MOUSEDEV_PSAUX=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
 CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
 CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
 CONFIG_INPUT_JOYDEV=m
@@ -663,7 +692,6 @@
 #
 # Ftape, the floppy tape device driver
 #
-# CONFIG_AGP is not set
 # CONFIG_DRM is not set
 CONFIG_RAW_DRIVER=y
 CONFIG_MAX_RAW_DEVS=256
@@ -693,6 +721,7 @@
 # CONFIG_I2C_I810 is not set
 # CONFIG_I2C_ISA is not set
 CONFIG_I2C_KEYWEST=y
+# CONFIG_I2C_MPC is not set
 # CONFIG_I2C_NFORCE2 is not set
 # CONFIG_I2C_PARPORT_LIGHT is not set
 # CONFIG_I2C_PROSAVAGE is not set
@@ -701,6 +730,7 @@
 # CONFIG_I2C_SIS5595 is not set
 # CONFIG_I2C_SIS630 is not set
 # CONFIG_I2C_SIS96X is not set
+# CONFIG_I2C_STUB is not set
 # CONFIG_I2C_VIA is not set
 # CONFIG_I2C_VIAPRO is not set
 # CONFIG_I2C_VOODOO3 is not set
@@ -712,20 +742,25 @@
 # CONFIG_I2C_SENSOR is not set
 # CONFIG_SENSORS_ADM1021 is not set
 # CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
 # CONFIG_SENSORS_ADM1031 is not set
 # CONFIG_SENSORS_ASB100 is not set
 # CONFIG_SENSORS_DS1621 is not set
 # CONFIG_SENSORS_FSCHER is not set
 # CONFIG_SENSORS_GL518SM is not set
 # CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
 # CONFIG_SENSORS_LM75 is not set
 # CONFIG_SENSORS_LM77 is not set
 # CONFIG_SENSORS_LM78 is not set
 # CONFIG_SENSORS_LM80 is not set
 # CONFIG_SENSORS_LM83 is not set
 # CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
 # CONFIG_SENSORS_LM90 is not set
 # CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
 # CONFIG_SENSORS_SMSC47M1 is not set
 # CONFIG_SENSORS_VIA686A is not set
 # CONFIG_SENSORS_W83781D is not set
@@ -768,6 +803,7 @@
 #
 CONFIG_FB=y
 CONFIG_FB_MODE_HELPERS=y
+CONFIG_FB_TILEBLITTING=y
 # CONFIG_FB_CIRRUS is not set
 # CONFIG_FB_PM2 is not set
 # CONFIG_FB_CYBER2000 is not set
@@ -789,6 +825,7 @@
 # CONFIG_FB_RADEON_DEBUG is not set
 # CONFIG_FB_ATY128 is not set
 # CONFIG_FB_ATY is not set
+# CONFIG_FB_SAVAGE is not set
 # CONFIG_FB_SIS is not set
 # CONFIG_FB_NEOMAGIC is not set
 # CONFIG_FB_KYRO is not set
@@ -814,6 +851,11 @@
 CONFIG_LOGO_LINUX_MONO=y
 CONFIG_LOGO_LINUX_VGA16=y
 CONFIG_LOGO_LINUX_CLUT224=y
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_BACKLIGHT_CLASS_DEVICE=m
+CONFIG_BACKLIGHT_DEVICE=y
+CONFIG_LCD_CLASS_DEVICE=m
+CONFIG_LCD_DEVICE=y
 
 #
 # Sound
@@ -833,6 +875,8 @@
 # CONFIG_USB_BANDWIDTH is not set
 # CONFIG_USB_DYNAMIC_MINORS is not set
 # CONFIG_USB_OTG is not set
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
 
 #
 # USB Host Controller Drivers
@@ -842,6 +886,7 @@
 # CONFIG_USB_EHCI_ROOT_HUB_TT is not set
 CONFIG_USB_OHCI_HCD=y
 # CONFIG_USB_UHCI_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
 
 #
 # USB Device Class drivers
@@ -849,9 +894,13 @@
 # CONFIG_USB_BLUETOOTH_TTY is not set
 CONFIG_USB_ACM=m
 CONFIG_USB_PRINTER=y
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
 CONFIG_USB_STORAGE=y
 # CONFIG_USB_STORAGE_DEBUG is not set
-# CONFIG_USB_STORAGE_RW_DETECT is not set
+CONFIG_USB_STORAGE_RW_DETECT=y
 CONFIG_USB_STORAGE_DATAFAB=y
 CONFIG_USB_STORAGE_FREECOM=y
 CONFIG_USB_STORAGE_ISD200=y
@@ -862,7 +911,7 @@
 CONFIG_USB_STORAGE_JUMPSHOT=y
 
 #
-# USB Human Interface Devices (HID)
+# USB Input Devices
 #
 CONFIG_USB_HID=y
 CONFIG_USB_HIDINPUT=y
@@ -885,7 +934,6 @@
 #
 # CONFIG_USB_MDC800 is not set
 # CONFIG_USB_MICROTEK is not set
-# CONFIG_USB_HPUSBSCSI is not set
 
 #
 # USB Multimedia devices
@@ -897,12 +945,12 @@
 #
 
 #
-# USB Network adaptors
+# USB Network Adapters
 #
-# CONFIG_USB_CATC is not set
-# CONFIG_USB_KAWETH is not set
-# CONFIG_USB_PEGASUS is not set
-# CONFIG_USB_RTL8150 is not set
+CONFIG_USB_CATC=m
+CONFIG_USB_KAWETH=m
+CONFIG_USB_PEGASUS=m
+CONFIG_USB_RTL8150=m
 CONFIG_USB_USBNET=m
 
 #
@@ -914,6 +962,7 @@
 CONFIG_USB_GENESYS=y
 CONFIG_USB_NET1080=y
 CONFIG_USB_PL2301=y
+CONFIG_USB_KC2190=y
 
 #
 # Intelligent USB Devices/Gadgets
@@ -939,6 +988,7 @@
 CONFIG_USB_SERIAL_GENERIC=y
 CONFIG_USB_SERIAL_BELKIN=m
 CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m
+CONFIG_USB_SERIAL_CYPRESS_M8=m
 CONFIG_USB_SERIAL_EMPEG=m
 CONFIG_USB_SERIAL_FTDI_SIO=m
 CONFIG_USB_SERIAL_VISOR=m
@@ -946,6 +996,8 @@
 CONFIG_USB_SERIAL_IR=m
 CONFIG_USB_SERIAL_EDGEPORT=m
 CONFIG_USB_SERIAL_EDGEPORT_TI=m
+CONFIG_USB_SERIAL_GARMIN=m
+CONFIG_USB_SERIAL_IPW=m
 CONFIG_USB_SERIAL_KEYSPAN_PDA=m
 CONFIG_USB_SERIAL_KEYSPAN=m
 CONFIG_USB_SERIAL_KEYSPAN_MPR=y
@@ -966,6 +1018,7 @@
 CONFIG_USB_SERIAL_PL2303=m
 CONFIG_USB_SERIAL_SAFE=m
 CONFIG_USB_SERIAL_SAFE_PADDED=y
+CONFIG_USB_SERIAL_TI=m
 CONFIG_USB_SERIAL_CYBERJACK=m
 CONFIG_USB_SERIAL_XIRCOM=m
 CONFIG_USB_SERIAL_OMNINET=m
@@ -976,42 +1029,72 @@
 #
 # CONFIG_USB_EMI62 is not set
 # CONFIG_USB_EMI26 is not set
-# CONFIG_USB_TIGL is not set
 # CONFIG_USB_AUERSWALD is not set
 # CONFIG_USB_RIO500 is not set
 # CONFIG_USB_LEGOTOWER is not set
 # CONFIG_USB_LCD is not set
 # CONFIG_USB_LED is not set
 # CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGETKIT is not set
 # CONFIG_USB_PHIDGETSERVO is not set
+# CONFIG_USB_IDMOUSE is not set
 # CONFIG_USB_TEST is not set
 
 #
+# USB ATM/DSL drivers
+#
+
+#
 # USB Gadget Support
 #
 # CONFIG_USB_GADGET is not set
 
 #
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
 CONFIG_EXT2_FS_XATTR=y
 CONFIG_EXT2_FS_POSIX_ACL=y
-# CONFIG_EXT2_FS_SECURITY is not set
+CONFIG_EXT2_FS_SECURITY=y
 CONFIG_EXT3_FS=y
 CONFIG_EXT3_FS_XATTR=y
 CONFIG_EXT3_FS_POSIX_ACL=y
-# CONFIG_EXT3_FS_SECURITY is not set
+CONFIG_EXT3_FS_SECURITY=y
 CONFIG_JBD=y
 # CONFIG_JBD_DEBUG is not set
 CONFIG_FS_MBCACHE=y
-# CONFIG_REISERFS_FS is not set
+CONFIG_REISERFS_FS=y
+# CONFIG_REISERFS_CHECK is not set
+# CONFIG_REISERFS_PROC_INFO is not set
+CONFIG_REISERFS_FS_XATTR=y
+CONFIG_REISERFS_FS_POSIX_ACL=y
+CONFIG_REISERFS_FS_SECURITY=y
 # CONFIG_JFS_FS is not set
 CONFIG_FS_POSIX_ACL=y
-# CONFIG_XFS_FS is not set
+
+#
+# XFS support
+#
+CONFIG_XFS_FS=m
+CONFIG_XFS_EXPORT=y
+# CONFIG_XFS_RT is not set
+# CONFIG_XFS_QUOTA is not set
+CONFIG_XFS_SECURITY=y
+CONFIG_XFS_POSIX_ACL=y
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
 # CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
 CONFIG_AUTOFS_FS=m
 # CONFIG_AUTOFS4_FS is not set
 
@@ -1019,8 +1102,9 @@
 # CD-ROM/DVD Filesystems
 #
 CONFIG_ISO9660_FS=y
-# CONFIG_JOLIET is not set
-# CONFIG_ZISOFS is not set
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_ZISOFS_FS=y
 CONFIG_UDF_FS=m
 CONFIG_UDF_NLS=y
 
@@ -1044,6 +1128,8 @@
 CONFIG_DEVPTS_FS_XATTR=y
 # CONFIG_DEVPTS_FS_SECURITY is not set
 CONFIG_TMPFS=y
+CONFIG_TMPFS_XATTR=y
+CONFIG_TMPFS_SECURITY=y
 CONFIG_HUGETLBFS=y
 CONFIG_HUGETLB_PAGE=y
 CONFIG_RAMFS=y
@@ -1053,8 +1139,8 @@
 #
 # CONFIG_ADFS_FS is not set
 # CONFIG_AFFS_FS is not set
-# CONFIG_HFS_FS is not set
-# CONFIG_HFSPLUS_FS is not set
+CONFIG_HFS_FS=m
+CONFIG_HFSPLUS_FS=m
 # CONFIG_BEFS_FS is not set
 # CONFIG_BFS_FS is not set
 # CONFIG_EFS_FS is not set
@@ -1087,7 +1173,7 @@
 CONFIG_CIFS=m
 # CONFIG_CIFS_STATS is not set
 # CONFIG_CIFS_XATTR is not set
-# CONFIG_CIFS_POSIX is not set
+# CONFIG_CIFS_EXPERIMENTAL is not set
 # CONFIG_NCP_FS is not set
 # CONFIG_CODA_FS is not set
 # CONFIG_AFS_FS is not set
@@ -1117,7 +1203,7 @@
 #
 CONFIG_NLS=y
 CONFIG_NLS_DEFAULT="iso8859-1"
-# CONFIG_NLS_CODEPAGE_437 is not set
+CONFIG_NLS_CODEPAGE_437=y
 # CONFIG_NLS_CODEPAGE_737 is not set
 # CONFIG_NLS_CODEPAGE_775 is not set
 # CONFIG_NLS_CODEPAGE_850 is not set
@@ -1138,10 +1224,10 @@
 # CONFIG_NLS_CODEPAGE_949 is not set
 # CONFIG_NLS_CODEPAGE_874 is not set
 # CONFIG_NLS_ISO8859_8 is not set
-# CONFIG_NLS_CODEPAGE_1250 is not set
-# CONFIG_NLS_CODEPAGE_1251 is not set
-# CONFIG_NLS_ASCII is not set
-# CONFIG_NLS_ISO8859_1 is not set
+CONFIG_NLS_CODEPAGE_1250=y
+CONFIG_NLS_CODEPAGE_1251=y
+CONFIG_NLS_ASCII=y
+CONFIG_NLS_ISO8859_1=y
 # CONFIG_NLS_ISO8859_2 is not set
 # CONFIG_NLS_ISO8859_3 is not set
 # CONFIG_NLS_ISO8859_4 is not set
@@ -1151,10 +1237,10 @@
 # CONFIG_NLS_ISO8859_9 is not set
 # CONFIG_NLS_ISO8859_13 is not set
 # CONFIG_NLS_ISO8859_14 is not set
-# CONFIG_NLS_ISO8859_15 is not set
+CONFIG_NLS_ISO8859_15=y
 # CONFIG_NLS_KOI8_R is not set
 # CONFIG_NLS_KOI8_U is not set
-# CONFIG_NLS_UTF8 is not set
+CONFIG_NLS_UTF8=y
 
 #
 # Profiling support
@@ -1167,19 +1253,23 @@
 #
 CONFIG_DEBUG_KERNEL=y
 CONFIG_MAGIC_SYSRQ=y
+# CONFIG_SCHEDSTATS is not set
 # CONFIG_DEBUG_SLAB is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_KOBJECT is not set
 # CONFIG_DEBUG_INFO is not set
+CONFIG_DEBUG_FS=y
 # CONFIG_DEBUG_STACKOVERFLOW is not set
+# CONFIG_KPROBES is not set
 # CONFIG_DEBUG_STACK_USAGE is not set
 # CONFIG_DEBUGGER is not set
 # CONFIG_PPCDBG is not set
 CONFIG_IRQSTACKS=y
-# CONFIG_SCHEDSTATS is not set
 
 #
 # Security options
 #
+# CONFIG_KEYS is not set
 # CONFIG_SECURITY is not set
 
 #
@@ -1193,7 +1283,7 @@
 CONFIG_CRYPTO_SHA1=m
 CONFIG_CRYPTO_SHA256=m
 CONFIG_CRYPTO_SHA512=m
-# CONFIG_CRYPTO_WP512 is not set
+CONFIG_CRYPTO_WP512=m
 CONFIG_CRYPTO_DES=y
 CONFIG_CRYPTO_BLOWFISH=m
 CONFIG_CRYPTO_TWOFISH=m
@@ -1201,19 +1291,24 @@
 CONFIG_CRYPTO_AES=m
 CONFIG_CRYPTO_CAST5=m
 CONFIG_CRYPTO_CAST6=m
-# CONFIG_CRYPTO_TEA is not set
+CONFIG_CRYPTO_TEA=m
 CONFIG_CRYPTO_ARC4=m
-# CONFIG_CRYPTO_KHAZAD is not set
+CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_ANUBIS=m
 CONFIG_CRYPTO_DEFLATE=m
 CONFIG_CRYPTO_MICHAEL_MIC=m
-# CONFIG_CRYPTO_CRC32C is not set
+CONFIG_CRYPTO_CRC32C=m
 CONFIG_CRYPTO_TEST=m
 
 #
+# Hardware crypto devices
+#
+
+#
 # Library routines
 #
 CONFIG_CRC_CCITT=m
 CONFIG_CRC32=y
-# CONFIG_LIBCRC32C is not set
+CONFIG_LIBCRC32C=m
 CONFIG_ZLIB_INFLATE=y
 CONFIG_ZLIB_DEFLATE=m
diff -Nru a/arch/ppc64/configs/iSeries_defconfig b/arch/ppc64/configs/iSeries_defconfig
--- a/arch/ppc64/configs/iSeries_defconfig	2005-03-11 12:51:52 -08:00
+++ b/arch/ppc64/configs/iSeries_defconfig	2005-03-11 12:51:52 -08:00
@@ -1,9 +1,12 @@
 #
 # Automatically generated make config: don't edit
+# Linux kernel version: 2.6.11-rc3-bk6
+# Wed Feb  9 23:34:52 2005
 #
 CONFIG_64BIT=y
 CONFIG_MMU=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_ISA_DMA=y
 CONFIG_HAVE_DEC_LOCK=y
 CONFIG_EARLY_PRINTK=y
@@ -16,19 +19,20 @@
 #
 CONFIG_EXPERIMENTAL=y
 CONFIG_CLEAN_COMPILE=y
+CONFIG_LOCK_KERNEL=y
 
 #
 # General setup
 #
+CONFIG_LOCALVERSION=""
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
 # CONFIG_BSD_PROCESS_ACCT is not set
 CONFIG_SYSCTL=y
-CONFIG_AUDIT=y
-CONFIG_AUDITSYSCALL=y
 CONFIG_LOG_BUF_SHIFT=17
 CONFIG_HOTPLUG=y
+CONFIG_KOBJECT_UEVENT=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 # CONFIG_EMBEDDED is not set
@@ -37,12 +41,12 @@
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
 # CONFIG_TINY_SHMEM is not set
 
 #
@@ -52,8 +56,9 @@
 CONFIG_MODULE_UNLOAD=y
 # CONFIG_MODULE_FORCE_UNLOAD is not set
 CONFIG_OBSOLETE_MODPARM=y
-# CONFIG_MODVERSIONS is not set
-# CONFIG_KMOD is not set
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+CONFIG_KMOD=y
 CONFIG_STOP_MACHINE=y
 CONFIG_SYSVIPC_COMPAT=y
 
@@ -61,15 +66,17 @@
 # Platform support
 #
 CONFIG_PPC_ISERIES=y
-# CONFIG_PPC_PSERIES is not set
+# CONFIG_PPC_MULTIPLATFORM is not set
 CONFIG_PPC=y
 CONFIG_PPC64=y
+CONFIG_IBMVIO=y
 # CONFIG_POWER4_ONLY is not set
 CONFIG_IOMMU_VMERGE=y
 CONFIG_SMP=y
 CONFIG_NR_CPUS=32
 # CONFIG_SCHED_SMT is not set
 # CONFIG_PREEMPT is not set
+CONFIG_GENERIC_HARDIRQS=y
 CONFIG_MSCHUNKS=y
 CONFIG_LPARCFG=y
 
@@ -82,12 +89,15 @@
 # CONFIG_BINFMT_MISC is not set
 CONFIG_PCI_LEGACY_PROC=y
 CONFIG_PCI_NAMES=y
-# CONFIG_HOTPLUG_CPU is not set
 
 #
-# PCMCIA/CardBus support
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PC-card bridges
 #
-# CONFIG_PCMCIA is not set
 
 #
 # PCI Hotplug Support
@@ -128,13 +138,26 @@
 # CONFIG_BLK_CPQ_CISS_DA is not set
 # CONFIG_BLK_DEV_DAC960 is not set
 # CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
 CONFIG_BLK_DEV_LOOP=y
 # CONFIG_BLK_DEV_CRYPTOLOOP is not set
 CONFIG_BLK_DEV_NBD=m
 # CONFIG_BLK_DEV_SX8 is not set
 CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=65536
 CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
 
 #
 # ATA/ATAPI/MFM/RLL support
@@ -169,6 +192,7 @@
 #
 CONFIG_SCSI_SPI_ATTRS=y
 CONFIG_SCSI_FC_ATTRS=y
+# CONFIG_SCSI_ISCSI_ATTRS is not set
 
 #
 # SCSI low-level drivers
@@ -191,6 +215,7 @@
 # CONFIG_SCSI_GDTH is not set
 # CONFIG_SCSI_IPS is not set
 CONFIG_SCSI_IBMVSCSI=m
+# CONFIG_SCSI_INITIO is not set
 # CONFIG_SCSI_INIA100 is not set
 # CONFIG_SCSI_SYM53C8XX_2 is not set
 # CONFIG_SCSI_IPR is not set
@@ -203,7 +228,6 @@
 # CONFIG_SCSI_QLA2300 is not set
 # CONFIG_SCSI_QLA2322 is not set
 # CONFIG_SCSI_QLA6312 is not set
-# CONFIG_SCSI_QLA6322 is not set
 # CONFIG_SCSI_DC395x is not set
 # CONFIG_SCSI_DC390T is not set
 # CONFIG_SCSI_DEBUG is not set
@@ -220,6 +244,7 @@
 CONFIG_MD_RAID5=y
 CONFIG_MD_RAID6=m
 CONFIG_MD_MULTIPATH=m
+CONFIG_MD_FAULTY=m
 CONFIG_BLK_DEV_DM=y
 CONFIG_DM_CRYPT=m
 CONFIG_DM_SNAPSHOT=m
@@ -271,6 +296,8 @@
 CONFIG_INET_ESP=m
 CONFIG_INET_IPCOMP=m
 CONFIG_INET_TUNNEL=y
+CONFIG_IP_TCPDIAG=m
+# CONFIG_IP_TCPDIAG_IPV6 is not set
 
 #
 # IP: Virtual Server Configuration
@@ -284,6 +311,9 @@
 # IP: Netfilter Configuration
 #
 CONFIG_IP_NF_CONNTRACK=m
+CONFIG_IP_NF_CT_ACCT=y
+CONFIG_IP_NF_CONNTRACK_MARK=y
+CONFIG_IP_NF_CT_PROTO_SCTP=m
 CONFIG_IP_NF_FTP=m
 CONFIG_IP_NF_IRC=m
 CONFIG_IP_NF_TFTP=m
@@ -308,8 +338,17 @@
 CONFIG_IP_NF_MATCH_STATE=m
 CONFIG_IP_NF_MATCH_CONNTRACK=m
 CONFIG_IP_NF_MATCH_OWNER=m
+CONFIG_IP_NF_MATCH_ADDRTYPE=m
+CONFIG_IP_NF_MATCH_REALM=m
+CONFIG_IP_NF_MATCH_SCTP=m
+CONFIG_IP_NF_MATCH_COMMENT=m
+CONFIG_IP_NF_MATCH_CONNMARK=m
+CONFIG_IP_NF_MATCH_HASHLIMIT=m
 CONFIG_IP_NF_FILTER=m
 CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_LOG=m
+CONFIG_IP_NF_TARGET_ULOG=m
+CONFIG_IP_NF_TARGET_TCPMSS=m
 CONFIG_IP_NF_NAT=m
 CONFIG_IP_NF_NAT_NEEDED=y
 CONFIG_IP_NF_TARGET_MASQUERADE=m
@@ -327,21 +366,13 @@
 CONFIG_IP_NF_TARGET_DSCP=m
 CONFIG_IP_NF_TARGET_MARK=m
 CONFIG_IP_NF_TARGET_CLASSIFY=m
-CONFIG_IP_NF_TARGET_LOG=m
-CONFIG_IP_NF_TARGET_ULOG=m
-CONFIG_IP_NF_TARGET_TCPMSS=m
+CONFIG_IP_NF_TARGET_CONNMARK=m
+CONFIG_IP_NF_TARGET_CLUSTERIP=m
+CONFIG_IP_NF_RAW=m
+CONFIG_IP_NF_TARGET_NOTRACK=m
 CONFIG_IP_NF_ARPTABLES=m
 CONFIG_IP_NF_ARPFILTER=m
 CONFIG_IP_NF_ARP_MANGLE=m
-CONFIG_IP_NF_COMPAT_IPCHAINS=m
-CONFIG_IP_NF_COMPAT_IPFWADM=m
-CONFIG_IP_NF_TARGET_NOTRACK=m
-CONFIG_IP_NF_RAW=m
-CONFIG_IP_NF_MATCH_ADDRTYPE=m
-CONFIG_IP_NF_MATCH_REALM=m
-# CONFIG_IP_NF_CT_ACCT is not set
-CONFIG_IP_NF_MATCH_SCTP=m
-CONFIG_IP_NF_CT_PROTO_SCTP=m
 CONFIG_XFRM=y
 CONFIG_XFRM_USER=m
 
@@ -362,7 +393,6 @@
 # CONFIG_NET_DIVERT is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
-# CONFIG_NET_HW_FLOWCONTROL is not set
 
 #
 # QoS and/or fair queueing
@@ -425,19 +455,21 @@
 # CONFIG_EPIC100 is not set
 # CONFIG_SUNDANCE is not set
 # CONFIG_VIA_RHINE is not set
-# CONFIG_VIA_VELOCITY is not set
 
 #
 # Ethernet (1000 Mbit)
 #
-# CONFIG_ACENIC is not set
+CONFIG_ACENIC=m
+# CONFIG_ACENIC_OMIT_TIGON_I is not set
 # CONFIG_DL2K is not set
-# CONFIG_E1000 is not set
+CONFIG_E1000=m
+# CONFIG_E1000_NAPI is not set
 # CONFIG_NS83820 is not set
 # CONFIG_HAMACHI is not set
 # CONFIG_YELLOWFIN is not set
 # CONFIG_R8169 is not set
 # CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
 
 #
@@ -498,7 +530,7 @@
 # Userland interfaces
 #
 CONFIG_INPUT_MOUSEDEV=y
-CONFIG_INPUT_MOUSEDEV_PSAUX=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
 CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
 CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
 # CONFIG_INPUT_JOYDEV is not set
@@ -511,11 +543,8 @@
 #
 # CONFIG_GAMEPORT is not set
 CONFIG_SOUND_GAMEPORT=y
-CONFIG_SERIO=y
+# CONFIG_SERIO is not set
 # CONFIG_SERIO_I8042 is not set
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_CT82C710 is not set
-# CONFIG_SERIO_PCIPS2 is not set
 
 #
 # Input Device Drivers
@@ -563,7 +592,6 @@
 #
 # Ftape, the floppy tape device driver
 #
-# CONFIG_AGP is not set
 # CONFIG_DRM is not set
 CONFIG_RAW_DRIVER=y
 CONFIG_MAX_RAW_DEVS=256
@@ -606,6 +634,12 @@
 # USB support
 #
 # CONFIG_USB is not set
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
 
 #
 # USB Gadget Support
@@ -613,16 +647,26 @@
 # CONFIG_USB_GADGET is not set
 
 #
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
 CONFIG_EXT2_FS_XATTR=y
 CONFIG_EXT2_FS_POSIX_ACL=y
-# CONFIG_EXT2_FS_SECURITY is not set
+CONFIG_EXT2_FS_SECURITY=y
 CONFIG_EXT3_FS=y
 CONFIG_EXT3_FS_XATTR=y
 CONFIG_EXT3_FS_POSIX_ACL=y
-# CONFIG_EXT3_FS_SECURITY is not set
+CONFIG_EXT3_FS_SECURITY=y
 CONFIG_JBD=y
 # CONFIG_JBD_DEBUG is not set
 CONFIG_FS_MBCACHE=y
@@ -631,20 +675,27 @@
 # CONFIG_REISERFS_PROC_INFO is not set
 CONFIG_REISERFS_FS_XATTR=y
 CONFIG_REISERFS_FS_POSIX_ACL=y
-# CONFIG_REISERFS_FS_SECURITY is not set
+CONFIG_REISERFS_FS_SECURITY=y
 CONFIG_JFS_FS=m
 CONFIG_JFS_POSIX_ACL=y
+CONFIG_JFS_SECURITY=y
 # CONFIG_JFS_DEBUG is not set
 # CONFIG_JFS_STATISTICS is not set
 CONFIG_FS_POSIX_ACL=y
+
+#
+# XFS support
+#
 CONFIG_XFS_FS=m
+CONFIG_XFS_EXPORT=y
 # CONFIG_XFS_RT is not set
 # CONFIG_XFS_QUOTA is not set
-# CONFIG_XFS_SECURITY is not set
+CONFIG_XFS_SECURITY=y
 CONFIG_XFS_POSIX_ACL=y
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
 # CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
 CONFIG_AUTOFS_FS=m
 # CONFIG_AUTOFS4_FS is not set
 
@@ -652,8 +703,9 @@
 # CD-ROM/DVD Filesystems
 #
 CONFIG_ISO9660_FS=y
-# CONFIG_JOLIET is not set
-# CONFIG_ZISOFS is not set
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_ZISOFS_FS=y
 CONFIG_UDF_FS=m
 CONFIG_UDF_NLS=y
 
@@ -675,8 +727,10 @@
 CONFIG_SYSFS=y
 # CONFIG_DEVFS_FS is not set
 CONFIG_DEVPTS_FS_XATTR=y
-# CONFIG_DEVPTS_FS_SECURITY is not set
+CONFIG_DEVPTS_FS_SECURITY=y
 CONFIG_TMPFS=y
+CONFIG_TMPFS_XATTR=y
+CONFIG_TMPFS_SECURITY=y
 # CONFIG_HUGETLBFS is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
@@ -721,6 +775,7 @@
 # CONFIG_CIFS_STATS is not set
 CONFIG_CIFS_XATTR=y
 CONFIG_CIFS_POSIX=y
+# CONFIG_CIFS_EXPERIMENTAL is not set
 # CONFIG_NCP_FS is not set
 # CONFIG_CODA_FS is not set
 # CONFIG_AFS_FS is not set
@@ -795,19 +850,23 @@
 #
 CONFIG_DEBUG_KERNEL=y
 CONFIG_MAGIC_SYSRQ=y
+# CONFIG_SCHEDSTATS is not set
 # CONFIG_DEBUG_SLAB is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_KOBJECT is not set
 # CONFIG_DEBUG_INFO is not set
+CONFIG_DEBUG_FS=y
 CONFIG_DEBUG_STACKOVERFLOW=y
+# CONFIG_KPROBES is not set
 CONFIG_DEBUG_STACK_USAGE=y
 # CONFIG_DEBUGGER is not set
 # CONFIG_PPCDBG is not set
-# CONFIG_IRQSTACKS is not set
-# CONFIG_SCHEDSTATS is not set
+CONFIG_IRQSTACKS=y
 
 #
 # Security options
 #
+# CONFIG_KEYS is not set
 # CONFIG_SECURITY is not set
 
 #
@@ -821,7 +880,7 @@
 CONFIG_CRYPTO_SHA1=m
 CONFIG_CRYPTO_SHA256=m
 CONFIG_CRYPTO_SHA512=m
-CONFIG_CRYPTO_WHIRLPOOL=m
+CONFIG_CRYPTO_WP512=m
 CONFIG_CRYPTO_DES=y
 CONFIG_CRYPTO_BLOWFISH=m
 CONFIG_CRYPTO_TWOFISH=m
@@ -832,10 +891,15 @@
 CONFIG_CRYPTO_TEA=m
 CONFIG_CRYPTO_ARC4=m
 CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_ANUBIS=m
 CONFIG_CRYPTO_DEFLATE=m
 CONFIG_CRYPTO_MICHAEL_MIC=m
 CONFIG_CRYPTO_CRC32C=m
 CONFIG_CRYPTO_TEST=m
+
+#
+# Hardware crypto devices
+#
 
 #
 # Library routines
diff -Nru a/arch/ppc64/configs/maple_defconfig b/arch/ppc64/configs/maple_defconfig
--- a/arch/ppc64/configs/maple_defconfig	2005-03-11 12:51:41 -08:00
+++ b/arch/ppc64/configs/maple_defconfig	2005-03-11 12:51:41 -08:00
@@ -1,11 +1,12 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.9
-# Wed Oct 20 15:39:14 2004
+# Linux kernel version: 2.6.11-rc3-bk6
+# Wed Feb  9 23:34:53 2005
 #
 CONFIG_64BIT=y
 CONFIG_MMU=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_ISA_DMA=y
 CONFIG_HAVE_DEC_LOCK=y
 CONFIG_EARLY_PRINTK=y
@@ -18,6 +19,7 @@
 #
 CONFIG_EXPERIMENTAL=y
 CONFIG_CLEAN_COMPILE=y
+CONFIG_LOCK_KERNEL=y
 
 #
 # General setup
@@ -25,12 +27,12 @@
 CONFIG_LOCALVERSION=""
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
-# CONFIG_POSIX_MQUEUE is not set
+CONFIG_POSIX_MQUEUE=y
 # CONFIG_BSD_PROCESS_ACCT is not set
 CONFIG_SYSCTL=y
-# CONFIG_AUDIT is not set
 CONFIG_LOG_BUF_SHIFT=17
 # CONFIG_HOTPLUG is not set
+CONFIG_KOBJECT_UEVENT=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 # CONFIG_EMBEDDED is not set
@@ -39,12 +41,12 @@
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
 # CONFIG_TINY_SHMEM is not set
 
 #
@@ -52,9 +54,10 @@
 #
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
-CONFIG_MODULE_FORCE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
 CONFIG_OBSOLETE_MODPARM=y
-# CONFIG_MODVERSIONS is not set
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
 CONFIG_KMOD=y
 CONFIG_STOP_MACHINE=y
 CONFIG_SYSVIPC_COMPAT=y
@@ -77,10 +80,10 @@
 CONFIG_POWER4_ONLY=y
 CONFIG_IOMMU_VMERGE=y
 CONFIG_SMP=y
-# CONFIG_IRQ_ALL_CPUS is not set
 CONFIG_NR_CPUS=2
 # CONFIG_SCHED_SMT is not set
 # CONFIG_PREEMPT is not set
+CONFIG_GENERIC_HARDIRQS=y
 
 #
 # General setup
@@ -91,6 +94,20 @@
 # CONFIG_BINFMT_MISC is not set
 CONFIG_PCI_LEGACY_PROC=y
 CONFIG_PCI_NAMES=y
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PC-card bridges
+#
+
+#
+# PCI Hotplug Support
+#
+# CONFIG_HOTPLUG_PCI is not set
 CONFIG_PROC_DEVICETREE=y
 # CONFIG_CMDLINE_BOOL is not set
 
@@ -103,6 +120,7 @@
 #
 CONFIG_STANDALONE=y
 CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
 # CONFIG_DEBUG_DRIVER is not set
 
 #
@@ -127,13 +145,26 @@
 # CONFIG_BLK_CPQ_CISS_DA is not set
 # CONFIG_BLK_DEV_DAC960 is not set
 # CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
 # CONFIG_BLK_DEV_LOOP is not set
 # CONFIG_BLK_DEV_NBD is not set
 # CONFIG_BLK_DEV_SX8 is not set
 # CONFIG_BLK_DEV_UB is not set
 CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
 CONFIG_BLK_DEV_RAM_SIZE=8192
 # CONFIG_BLK_DEV_INITRD is not set
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
 
 #
 # ATA/ATAPI/MFM/RLL support
@@ -151,7 +182,6 @@
 # CONFIG_BLK_DEV_IDETAPE is not set
 # CONFIG_BLK_DEV_IDEFLOPPY is not set
 CONFIG_IDE_TASK_IOCTL=y
-CONFIG_IDE_TASKFILE_IO=y
 
 #
 # IDE chipset support/bugfixes
@@ -250,6 +280,8 @@
 # CONFIG_INET_ESP is not set
 # CONFIG_INET_IPCOMP is not set
 # CONFIG_INET_TUNNEL is not set
+CONFIG_IP_TCPDIAG=y
+# CONFIG_IP_TCPDIAG_IPV6 is not set
 # CONFIG_IPV6 is not set
 # CONFIG_NETFILTER is not set
 
@@ -269,7 +301,6 @@
 # CONFIG_NET_DIVERT is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
-# CONFIG_NET_HW_FLOWCONTROL is not set
 
 #
 # QoS and/or fair queueing
@@ -330,7 +361,6 @@
 # CONFIG_EPIC100 is not set
 # CONFIG_SUNDANCE is not set
 # CONFIG_VIA_RHINE is not set
-# CONFIG_VIA_VELOCITY is not set
 
 #
 # Ethernet (1000 Mbit)
@@ -344,6 +374,7 @@
 # CONFIG_YELLOWFIN is not set
 # CONFIG_R8169 is not set
 # CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
 
 #
@@ -461,7 +492,6 @@
 #
 # Ftape, the floppy tape device driver
 #
-# CONFIG_AGP is not set
 # CONFIG_DRM is not set
 # CONFIG_RAW_DRIVER is not set
 
@@ -489,6 +519,7 @@
 # CONFIG_I2C_I801 is not set
 # CONFIG_I2C_I810 is not set
 # CONFIG_I2C_ISA is not set
+# CONFIG_I2C_MPC is not set
 # CONFIG_I2C_NFORCE2 is not set
 # CONFIG_I2C_PARPORT_LIGHT is not set
 # CONFIG_I2C_PROSAVAGE is not set
@@ -497,6 +528,7 @@
 # CONFIG_I2C_SIS5595 is not set
 # CONFIG_I2C_SIS630 is not set
 # CONFIG_I2C_SIS96X is not set
+# CONFIG_I2C_STUB is not set
 # CONFIG_I2C_VIA is not set
 # CONFIG_I2C_VIAPRO is not set
 # CONFIG_I2C_VOODOO3 is not set
@@ -508,20 +540,25 @@
 # CONFIG_I2C_SENSOR is not set
 # CONFIG_SENSORS_ADM1021 is not set
 # CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
 # CONFIG_SENSORS_ADM1031 is not set
 # CONFIG_SENSORS_ASB100 is not set
 # CONFIG_SENSORS_DS1621 is not set
 # CONFIG_SENSORS_FSCHER is not set
 # CONFIG_SENSORS_GL518SM is not set
 # CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
 # CONFIG_SENSORS_LM75 is not set
 # CONFIG_SENSORS_LM77 is not set
 # CONFIG_SENSORS_LM78 is not set
 # CONFIG_SENSORS_LM80 is not set
 # CONFIG_SENSORS_LM83 is not set
 # CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
 # CONFIG_SENSORS_LM90 is not set
 # CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
 # CONFIG_SENSORS_SMSC47M1 is not set
 # CONFIG_SENSORS_VIA686A is not set
 # CONFIG_SENSORS_W83781D is not set
@@ -588,6 +625,8 @@
 # CONFIG_USB_BANDWIDTH is not set
 # CONFIG_USB_DYNAMIC_MINORS is not set
 # CONFIG_USB_OTG is not set
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
 
 #
 # USB Host Controller Drivers
@@ -597,6 +636,7 @@
 CONFIG_USB_EHCI_ROOT_HUB_TT=y
 CONFIG_USB_OHCI_HCD=y
 CONFIG_USB_UHCI_HCD=y
+# CONFIG_USB_SL811_HCD is not set
 
 #
 # USB Device Class drivers
@@ -604,10 +644,14 @@
 # CONFIG_USB_BLUETOOTH_TTY is not set
 # CONFIG_USB_ACM is not set
 # CONFIG_USB_PRINTER is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
 # CONFIG_USB_STORAGE is not set
 
 #
-# USB Human Interface Devices (HID)
+# USB Input Devices
 #
 CONFIG_USB_HID=y
 CONFIG_USB_HIDINPUT=y
@@ -637,7 +681,7 @@
 #
 
 #
-# USB Network adaptors
+# USB Network Adapters
 #
 # CONFIG_USB_CATC is not set
 # CONFIG_USB_KAWETH is not set
@@ -657,6 +701,7 @@
 CONFIG_USB_SERIAL_GENERIC=y
 # CONFIG_USB_SERIAL_BELKIN is not set
 # CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set
+CONFIG_USB_SERIAL_CYPRESS_M8=m
 # CONFIG_USB_SERIAL_EMPEG is not set
 # CONFIG_USB_SERIAL_FTDI_SIO is not set
 # CONFIG_USB_SERIAL_VISOR is not set
@@ -664,6 +709,8 @@
 # CONFIG_USB_SERIAL_IR is not set
 # CONFIG_USB_SERIAL_EDGEPORT is not set
 # CONFIG_USB_SERIAL_EDGEPORT_TI is not set
+CONFIG_USB_SERIAL_GARMIN=m
+CONFIG_USB_SERIAL_IPW=m
 # CONFIG_USB_SERIAL_KEYSPAN_PDA is not set
 CONFIG_USB_SERIAL_KEYSPAN=y
 CONFIG_USB_SERIAL_KEYSPAN_MPR=y
@@ -683,6 +730,7 @@
 # CONFIG_USB_SERIAL_MCT_U232 is not set
 # CONFIG_USB_SERIAL_PL2303 is not set
 # CONFIG_USB_SERIAL_SAFE is not set
+CONFIG_USB_SERIAL_TI=m
 # CONFIG_USB_SERIAL_CYBERJACK is not set
 # CONFIG_USB_SERIAL_XIRCOM is not set
 # CONFIG_USB_SERIAL_OMNINET is not set
@@ -693,22 +741,37 @@
 #
 # CONFIG_USB_EMI62 is not set
 # CONFIG_USB_EMI26 is not set
-# CONFIG_USB_TIGL is not set
 # CONFIG_USB_AUERSWALD is not set
 # CONFIG_USB_RIO500 is not set
 # CONFIG_USB_LEGOTOWER is not set
 # CONFIG_USB_LCD is not set
 # CONFIG_USB_LED is not set
 # CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGETKIT is not set
 # CONFIG_USB_PHIDGETSERVO is not set
+# CONFIG_USB_IDMOUSE is not set
 # CONFIG_USB_TEST is not set
 
 #
+# USB ATM/DSL drivers
+#
+
+#
 # USB Gadget Support
 #
 # CONFIG_USB_GADGET is not set
 
 #
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -719,10 +782,15 @@
 # CONFIG_JBD_DEBUG is not set
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
+
+#
+# XFS support
+#
 # CONFIG_XFS_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
 # CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
 
@@ -752,8 +820,10 @@
 CONFIG_DEVPTS_FS_XATTR=y
 # CONFIG_DEVPTS_FS_SECURITY is not set
 CONFIG_TMPFS=y
-# CONFIG_HUGETLBFS is not set
-# CONFIG_HUGETLB_PAGE is not set
+CONFIG_TMPFS_XATTR=y
+CONFIG_TMPFS_SECURITY=y
+CONFIG_HUGETLBFS=y
+CONFIG_HUGETLB_PAGE=y
 CONFIG_RAMFS=y
 
 #
@@ -766,7 +836,7 @@
 # CONFIG_BEFS_FS is not set
 # CONFIG_BFS_FS is not set
 # CONFIG_EFS_FS is not set
-# CONFIG_CRAMFS is not set
+CONFIG_CRAMFS=y
 # CONFIG_VXFS_FS is not set
 # CONFIG_HPFS_FS is not set
 # CONFIG_QNX4FS_FS is not set
@@ -784,7 +854,6 @@
 CONFIG_ROOT_NFS=y
 CONFIG_LOCKD=y
 CONFIG_LOCKD_V4=y
-# CONFIG_EXPORTFS is not set
 CONFIG_SUNRPC=y
 CONFIG_SUNRPC_GSS=y
 CONFIG_RPCSEC_GSS_KRB5=y
@@ -869,21 +938,25 @@
 #
 CONFIG_DEBUG_KERNEL=y
 CONFIG_MAGIC_SYSRQ=y
+# CONFIG_SCHEDSTATS is not set
 CONFIG_DEBUG_SLAB=y
 CONFIG_DEBUG_SPINLOCK_SLEEP=y
+# CONFIG_DEBUG_KOBJECT is not set
 # CONFIG_DEBUG_INFO is not set
+CONFIG_DEBUG_FS=y
 CONFIG_DEBUG_STACKOVERFLOW=y
+# CONFIG_KPROBES is not set
 CONFIG_DEBUG_STACK_USAGE=y
 CONFIG_DEBUGGER=y
 CONFIG_XMON=y
 CONFIG_XMON_DEFAULT=y
 # CONFIG_PPCDBG is not set
 # CONFIG_IRQSTACKS is not set
-# CONFIG_SCHEDSTATS is not set
 
 #
 # Security options
 #
+# CONFIG_KEYS is not set
 # CONFIG_SECURITY is not set
 
 #
@@ -908,14 +981,20 @@
 # CONFIG_CRYPTO_TEA is not set
 # CONFIG_CRYPTO_ARC4 is not set
 # CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_ANUBIS is not set
 # CONFIG_CRYPTO_DEFLATE is not set
 # CONFIG_CRYPTO_MICHAEL_MIC is not set
 # CONFIG_CRYPTO_CRC32C is not set
 # CONFIG_CRYPTO_TEST is not set
 
 #
+# Hardware crypto devices
+#
+
+#
 # Library routines
 #
 CONFIG_CRC_CCITT=y
 CONFIG_CRC32=y
 # CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
diff -Nru a/arch/ppc64/configs/pSeries_defconfig b/arch/ppc64/configs/pSeries_defconfig
--- a/arch/ppc64/configs/pSeries_defconfig	2005-03-11 12:51:52 -08:00
+++ b/arch/ppc64/configs/pSeries_defconfig	2005-03-11 12:51:52 -08:00
@@ -1,11 +1,12 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.9-rc2
-# Thu Sep 23 16:45:05 2004
+# Linux kernel version: 2.6.11-rc3-bk6
+# Wed Feb  9 23:34:54 2005
 #
 CONFIG_64BIT=y
 CONFIG_MMU=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_ISA_DMA=y
 CONFIG_HAVE_DEC_LOCK=y
 CONFIG_EARLY_PRINTK=y
@@ -18,6 +19,7 @@
 #
 CONFIG_EXPERIMENTAL=y
 CONFIG_CLEAN_COMPILE=y
+CONFIG_LOCK_KERNEL=y
 
 #
 # General setup
@@ -28,10 +30,9 @@
 CONFIG_POSIX_MQUEUE=y
 # CONFIG_BSD_PROCESS_ACCT is not set
 CONFIG_SYSCTL=y
-CONFIG_AUDIT=y
-CONFIG_AUDITSYSCALL=y
 CONFIG_LOG_BUF_SHIFT=17
 CONFIG_HOTPLUG=y
+CONFIG_KOBJECT_UEVENT=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 # CONFIG_EMBEDDED is not set
@@ -40,12 +41,12 @@
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
 # CONFIG_TINY_SHMEM is not set
 
 #
@@ -55,8 +56,9 @@
 CONFIG_MODULE_UNLOAD=y
 # CONFIG_MODULE_FORCE_UNLOAD is not set
 CONFIG_OBSOLETE_MODPARM=y
-# CONFIG_MODVERSIONS is not set
-# CONFIG_KMOD is not set
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+CONFIG_KMOD=y
 CONFIG_STOP_MACHINE=y
 CONFIG_SYSVIPC_COMPAT=y
 
@@ -67,22 +69,25 @@
 CONFIG_PPC_MULTIPLATFORM=y
 CONFIG_PPC_PSERIES=y
 # CONFIG_PPC_PMAC is not set
+# CONFIG_PPC_MAPLE is not set
 CONFIG_PPC=y
 CONFIG_PPC64=y
 CONFIG_PPC_OF=y
 CONFIG_ALTIVEC=y
 CONFIG_PPC_SPLPAR=y
+CONFIG_IBMVIO=y
+# CONFIG_U3_DART is not set
 # CONFIG_BOOTX_TEXT is not set
 # CONFIG_POWER4_ONLY is not set
 CONFIG_IOMMU_VMERGE=y
 CONFIG_SMP=y
-CONFIG_IRQ_ALL_CPUS=y
 CONFIG_NR_CPUS=128
-# CONFIG_HMT is not set
 CONFIG_DISCONTIGMEM=y
 CONFIG_NUMA=y
 CONFIG_SCHED_SMT=y
 # CONFIG_PREEMPT is not set
+CONFIG_EEH=y
+CONFIG_GENERIC_HARDIRQS=y
 CONFIG_PPC_RTAS=y
 CONFIG_RTAS_FLASH=m
 CONFIG_SCANLOG=m
@@ -100,9 +105,13 @@
 CONFIG_HOTPLUG_CPU=y
 
 #
-# PCMCIA/CardBus support
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PC-card bridges
 #
-# CONFIG_PCMCIA is not set
 
 #
 # PCI Hotplug Support
@@ -110,7 +119,6 @@
 CONFIG_HOTPLUG_PCI=m
 # CONFIG_HOTPLUG_PCI_FAKE is not set
 # CONFIG_HOTPLUG_PCI_CPCI is not set
-# CONFIG_HOTPLUG_PCI_PCIE is not set
 # CONFIG_HOTPLUG_PCI_SHPC is not set
 CONFIG_HOTPLUG_PCI_RPA=m
 CONFIG_HOTPLUG_PCI_RPA_DLPAR=m
@@ -137,7 +145,14 @@
 #
 # Parallel port support
 #
-# CONFIG_PARPORT is not set
+CONFIG_PARPORT=m
+CONFIG_PARPORT_PC=m
+CONFIG_PARPORT_PC_CML1=m
+# CONFIG_PARPORT_SERIAL is not set
+# CONFIG_PARPORT_PC_FIFO is not set
+# CONFIG_PARPORT_PC_SUPERIO is not set
+# CONFIG_PARPORT_OTHER is not set
+# CONFIG_PARPORT_1284 is not set
 
 #
 # Plug and Play support
@@ -147,18 +162,32 @@
 # Block devices
 #
 CONFIG_BLK_DEV_FD=m
+# CONFIG_PARIDE is not set
 # CONFIG_BLK_CPQ_DA is not set
 # CONFIG_BLK_CPQ_CISS_DA is not set
 # CONFIG_BLK_DEV_DAC960 is not set
 # CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
 CONFIG_BLK_DEV_LOOP=y
 # CONFIG_BLK_DEV_CRYPTOLOOP is not set
 CONFIG_BLK_DEV_NBD=m
 # CONFIG_BLK_DEV_SX8 is not set
 # CONFIG_BLK_DEV_UB is not set
 CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=65536
 CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
 
 #
 # ATA/ATAPI/MFM/RLL support
@@ -177,7 +206,6 @@
 # CONFIG_BLK_DEV_IDEFLOPPY is not set
 # CONFIG_BLK_DEV_IDESCSI is not set
 # CONFIG_IDE_TASK_IOCTL is not set
-# CONFIG_IDE_TASKFILE_IO is not set
 
 #
 # IDE chipset support/bugfixes
@@ -247,6 +275,7 @@
 #
 CONFIG_SCSI_SPI_ATTRS=y
 CONFIG_SCSI_FC_ATTRS=y
+CONFIG_SCSI_ISCSI_ATTRS=m
 
 #
 # SCSI low-level drivers
@@ -269,15 +298,18 @@
 # CONFIG_SCSI_GDTH is not set
 # CONFIG_SCSI_IPS is not set
 CONFIG_SCSI_IBMVSCSI=y
+# CONFIG_SCSI_INITIO is not set
 # CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_PPA is not set
+# CONFIG_SCSI_IMM is not set
 CONFIG_SCSI_SYM53C8XX_2=y
 CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=0
 CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
 CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
 # CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set
 CONFIG_SCSI_IPR=y
-# CONFIG_SCSI_IPR_TRACE is not set
-# CONFIG_SCSI_IPR_DUMP is not set
+CONFIG_SCSI_IPR_TRACE=y
+CONFIG_SCSI_IPR_DUMP=y
 # CONFIG_SCSI_QLOGIC_ISP is not set
 # CONFIG_SCSI_QLOGIC_FC is not set
 # CONFIG_SCSI_QLOGIC_1280 is not set
@@ -287,7 +319,6 @@
 CONFIG_SCSI_QLA2300=m
 CONFIG_SCSI_QLA2322=m
 CONFIG_SCSI_QLA6312=m
-CONFIG_SCSI_QLA6322=m
 # CONFIG_SCSI_DC395x is not set
 # CONFIG_SCSI_DC390T is not set
 # CONFIG_SCSI_DEBUG is not set
@@ -304,6 +335,7 @@
 CONFIG_MD_RAID5=y
 CONFIG_MD_RAID6=m
 CONFIG_MD_MULTIPATH=m
+CONFIG_MD_FAULTY=m
 CONFIG_BLK_DEV_DM=y
 CONFIG_DM_CRYPT=m
 CONFIG_DM_SNAPSHOT=m
@@ -355,6 +387,8 @@
 CONFIG_INET_ESP=m
 CONFIG_INET_IPCOMP=m
 CONFIG_INET_TUNNEL=y
+CONFIG_IP_TCPDIAG=m
+# CONFIG_IP_TCPDIAG_IPV6 is not set
 
 #
 # IP: Virtual Server Configuration
@@ -368,7 +402,8 @@
 # IP: Netfilter Configuration
 #
 CONFIG_IP_NF_CONNTRACK=m
-# CONFIG_IP_NF_CT_ACCT is not set
+CONFIG_IP_NF_CT_ACCT=y
+CONFIG_IP_NF_CONNTRACK_MARK=y
 CONFIG_IP_NF_CT_PROTO_SCTP=m
 CONFIG_IP_NF_FTP=m
 CONFIG_IP_NF_IRC=m
@@ -397,6 +432,9 @@
 CONFIG_IP_NF_MATCH_ADDRTYPE=m
 CONFIG_IP_NF_MATCH_REALM=m
 CONFIG_IP_NF_MATCH_SCTP=m
+CONFIG_IP_NF_MATCH_COMMENT=m
+CONFIG_IP_NF_MATCH_CONNMARK=m
+CONFIG_IP_NF_MATCH_HASHLIMIT=m
 CONFIG_IP_NF_FILTER=m
 CONFIG_IP_NF_TARGET_REJECT=m
 CONFIG_IP_NF_TARGET_LOG=m
@@ -419,13 +457,13 @@
 CONFIG_IP_NF_TARGET_DSCP=m
 CONFIG_IP_NF_TARGET_MARK=m
 CONFIG_IP_NF_TARGET_CLASSIFY=m
+CONFIG_IP_NF_TARGET_CONNMARK=m
+CONFIG_IP_NF_TARGET_CLUSTERIP=m
 CONFIG_IP_NF_RAW=m
 CONFIG_IP_NF_TARGET_NOTRACK=m
 CONFIG_IP_NF_ARPTABLES=m
 CONFIG_IP_NF_ARPFILTER=m
 CONFIG_IP_NF_ARP_MANGLE=m
-CONFIG_IP_NF_COMPAT_IPCHAINS=m
-CONFIG_IP_NF_COMPAT_IPFWADM=m
 CONFIG_XFRM=y
 CONFIG_XFRM_USER=m
 
@@ -446,7 +484,6 @@
 # CONFIG_NET_DIVERT is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
-# CONFIG_NET_HW_FLOWCONTROL is not set
 
 #
 # QoS and/or fair queueing
@@ -512,7 +549,6 @@
 # CONFIG_EPIC100 is not set
 # CONFIG_SUNDANCE is not set
 # CONFIG_VIA_RHINE is not set
-# CONFIG_VIA_VELOCITY is not set
 
 #
 # Ethernet (1000 Mbit)
@@ -527,6 +563,7 @@
 # CONFIG_YELLOWFIN is not set
 # CONFIG_R8169 is not set
 # CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
 CONFIG_TIGON3=y
 
 #
@@ -536,6 +573,7 @@
 # CONFIG_IXGB_NAPI is not set
 CONFIG_S2IO=m
 # CONFIG_S2IO_NAPI is not set
+# CONFIG_2BUFF_MODE is not set
 
 #
 # Token Ring devices
@@ -556,6 +594,7 @@
 # CONFIG_WAN is not set
 # CONFIG_FDDI is not set
 # CONFIG_HIPPI is not set
+# CONFIG_PLIP is not set
 CONFIG_PPP=m
 # CONFIG_PPP_MULTILINK is not set
 # CONFIG_PPP_FILTER is not set
@@ -588,7 +627,7 @@
 # Userland interfaces
 #
 CONFIG_INPUT_MOUSEDEV=y
-CONFIG_INPUT_MOUSEDEV_PSAUX=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
 CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
 CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
 # CONFIG_INPUT_JOYDEV is not set
@@ -605,7 +644,9 @@
 CONFIG_SERIO_I8042=y
 # CONFIG_SERIO_SERPORT is not set
 # CONFIG_SERIO_CT82C710 is not set
+# CONFIG_SERIO_PARKBD is not set
 # CONFIG_SERIO_PCIPS2 is not set
+CONFIG_SERIO_LIBPS2=y
 # CONFIG_SERIO_RAW is not set
 
 #
@@ -624,7 +665,7 @@
 # CONFIG_INPUT_JOYSTICK is not set
 # CONFIG_INPUT_TOUCHSCREEN is not set
 CONFIG_INPUT_MISC=y
-# CONFIG_INPUT_PCSPKR is not set
+CONFIG_INPUT_PCSPKR=m
 # CONFIG_INPUT_UINPUT is not set
 
 #
@@ -653,6 +694,9 @@
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_PRINTER is not set
+# CONFIG_PPDEV is not set
+# CONFIG_TIPAR is not set
 CONFIG_HVC_CONSOLE=y
 CONFIG_HVCS=m
 
@@ -674,7 +718,6 @@
 #
 # Ftape, the floppy tape device driver
 #
-# CONFIG_AGP is not set
 # CONFIG_DRM is not set
 CONFIG_RAW_DRIVER=y
 CONFIG_MAX_RAW_DEVS=1024
@@ -703,7 +746,9 @@
 # CONFIG_I2C_I801 is not set
 # CONFIG_I2C_I810 is not set
 # CONFIG_I2C_ISA is not set
+# CONFIG_I2C_MPC is not set
 # CONFIG_I2C_NFORCE2 is not set
+# CONFIG_I2C_PARPORT is not set
 # CONFIG_I2C_PARPORT_LIGHT is not set
 # CONFIG_I2C_PROSAVAGE is not set
 # CONFIG_I2C_SAVAGE4 is not set
@@ -711,6 +756,7 @@
 # CONFIG_I2C_SIS5595 is not set
 # CONFIG_I2C_SIS630 is not set
 # CONFIG_I2C_SIS96X is not set
+# CONFIG_I2C_STUB is not set
 # CONFIG_I2C_VIA is not set
 # CONFIG_I2C_VIAPRO is not set
 # CONFIG_I2C_VOODOO3 is not set
@@ -722,20 +768,25 @@
 # CONFIG_I2C_SENSOR is not set
 # CONFIG_SENSORS_ADM1021 is not set
 # CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
 # CONFIG_SENSORS_ADM1031 is not set
 # CONFIG_SENSORS_ASB100 is not set
 # CONFIG_SENSORS_DS1621 is not set
 # CONFIG_SENSORS_FSCHER is not set
 # CONFIG_SENSORS_GL518SM is not set
 # CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
 # CONFIG_SENSORS_LM75 is not set
 # CONFIG_SENSORS_LM77 is not set
 # CONFIG_SENSORS_LM78 is not set
 # CONFIG_SENSORS_LM80 is not set
 # CONFIG_SENSORS_LM83 is not set
 # CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
 # CONFIG_SENSORS_LM90 is not set
 # CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
 # CONFIG_SENSORS_SMSC47M1 is not set
 # CONFIG_SENSORS_VIA686A is not set
 # CONFIG_SENSORS_W83781D is not set
@@ -778,6 +829,7 @@
 #
 CONFIG_FB=y
 CONFIG_FB_MODE_HELPERS=y
+# CONFIG_FB_TILEBLITTING is not set
 # CONFIG_FB_CIRRUS is not set
 # CONFIG_FB_PM2 is not set
 # CONFIG_FB_CYBER2000 is not set
@@ -790,8 +842,7 @@
 CONFIG_FB_MATROX=y
 CONFIG_FB_MATROX_MILLENIUM=y
 CONFIG_FB_MATROX_MYSTIQUE=y
-CONFIG_FB_MATROX_G450=y
-CONFIG_FB_MATROX_G100=y
+CONFIG_FB_MATROX_G=y
 # CONFIG_FB_MATROX_I2C is not set
 CONFIG_FB_MATROX_MULTIHEAD=y
 # CONFIG_FB_RADEON_OLD is not set
@@ -800,6 +851,7 @@
 # CONFIG_FB_RADEON_DEBUG is not set
 # CONFIG_FB_ATY128 is not set
 # CONFIG_FB_ATY is not set
+# CONFIG_FB_SAVAGE is not set
 # CONFIG_FB_SIS is not set
 # CONFIG_FB_NEOMAGIC is not set
 # CONFIG_FB_KYRO is not set
@@ -825,6 +877,11 @@
 CONFIG_LOGO_LINUX_MONO=y
 CONFIG_LOGO_LINUX_VGA16=y
 CONFIG_LOGO_LINUX_CLUT224=y
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_BACKLIGHT_CLASS_DEVICE=m
+CONFIG_BACKLIGHT_DEVICE=y
+CONFIG_LCD_CLASS_DEVICE=m
+CONFIG_LCD_DEVICE=y
 
 #
 # Sound
@@ -844,6 +901,8 @@
 # CONFIG_USB_BANDWIDTH is not set
 # CONFIG_USB_DYNAMIC_MINORS is not set
 # CONFIG_USB_OTG is not set
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
 
 #
 # USB Host Controller Drivers
@@ -853,6 +912,7 @@
 # CONFIG_USB_EHCI_ROOT_HUB_TT is not set
 CONFIG_USB_OHCI_HCD=y
 # CONFIG_USB_UHCI_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
 
 #
 # USB Device Class drivers
@@ -860,6 +920,10 @@
 # CONFIG_USB_BLUETOOTH_TTY is not set
 # CONFIG_USB_ACM is not set
 # CONFIG_USB_PRINTER is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
 CONFIG_USB_STORAGE=y
 # CONFIG_USB_STORAGE_DEBUG is not set
 # CONFIG_USB_STORAGE_RW_DETECT is not set
@@ -873,7 +937,7 @@
 # CONFIG_USB_STORAGE_JUMPSHOT is not set
 
 #
-# USB Human Interface Devices (HID)
+# USB Input Devices
 #
 CONFIG_USB_HID=y
 CONFIG_USB_HIDINPUT=y
@@ -893,7 +957,6 @@
 #
 # CONFIG_USB_MDC800 is not set
 # CONFIG_USB_MICROTEK is not set
-# CONFIG_USB_HPUSBSCSI is not set
 
 #
 # USB Multimedia devices
@@ -905,7 +968,7 @@
 #
 
 #
-# USB Network adaptors
+# USB Network Adapters
 #
 # CONFIG_USB_CATC is not set
 # CONFIG_USB_KAWETH is not set
@@ -916,6 +979,7 @@
 #
 # USB port drivers
 #
+# CONFIG_USB_USS720 is not set
 
 #
 # USB Serial Converter support
@@ -927,32 +991,51 @@
 #
 # CONFIG_USB_EMI62 is not set
 # CONFIG_USB_EMI26 is not set
-# CONFIG_USB_TIGL is not set
 # CONFIG_USB_AUERSWALD is not set
 # CONFIG_USB_RIO500 is not set
 # CONFIG_USB_LEGOTOWER is not set
 # CONFIG_USB_LCD is not set
 # CONFIG_USB_LED is not set
 # CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGETKIT is not set
 # CONFIG_USB_PHIDGETSERVO is not set
+# CONFIG_USB_IDMOUSE is not set
 # CONFIG_USB_TEST is not set
 
 #
+# USB ATM/DSL drivers
+#
+
+#
 # USB Gadget Support
 #
 # CONFIG_USB_GADGET is not set
 
 #
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+CONFIG_INFINIBAND=m
+CONFIG_INFINIBAND_MTHCA=m
+# CONFIG_INFINIBAND_MTHCA_DEBUG is not set
+CONFIG_INFINIBAND_IPOIB=m
+# CONFIG_INFINIBAND_IPOIB_DEBUG is not set
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
 CONFIG_EXT2_FS_XATTR=y
 CONFIG_EXT2_FS_POSIX_ACL=y
-# CONFIG_EXT2_FS_SECURITY is not set
+CONFIG_EXT2_FS_SECURITY=y
 CONFIG_EXT3_FS=y
 CONFIG_EXT3_FS_XATTR=y
 CONFIG_EXT3_FS_POSIX_ACL=y
-# CONFIG_EXT3_FS_SECURITY is not set
+CONFIG_EXT3_FS_SECURITY=y
 CONFIG_JBD=y
 # CONFIG_JBD_DEBUG is not set
 CONFIG_FS_MBCACHE=y
@@ -961,20 +1044,27 @@
 # CONFIG_REISERFS_PROC_INFO is not set
 CONFIG_REISERFS_FS_XATTR=y
 CONFIG_REISERFS_FS_POSIX_ACL=y
-# CONFIG_REISERFS_FS_SECURITY is not set
+CONFIG_REISERFS_FS_SECURITY=y
 CONFIG_JFS_FS=m
 CONFIG_JFS_POSIX_ACL=y
+CONFIG_JFS_SECURITY=y
 # CONFIG_JFS_DEBUG is not set
 # CONFIG_JFS_STATISTICS is not set
 CONFIG_FS_POSIX_ACL=y
+
+#
+# XFS support
+#
 CONFIG_XFS_FS=m
+CONFIG_XFS_EXPORT=y
 # CONFIG_XFS_RT is not set
 # CONFIG_XFS_QUOTA is not set
-# CONFIG_XFS_SECURITY is not set
+CONFIG_XFS_SECURITY=y
 CONFIG_XFS_POSIX_ACL=y
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
 # CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
 CONFIG_AUTOFS_FS=m
 # CONFIG_AUTOFS4_FS is not set
 
@@ -982,8 +1072,9 @@
 # CD-ROM/DVD Filesystems
 #
 CONFIG_ISO9660_FS=y
-# CONFIG_JOLIET is not set
-# CONFIG_ZISOFS is not set
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_ZISOFS_FS=y
 CONFIG_UDF_FS=m
 CONFIG_UDF_NLS=y
 
@@ -1005,8 +1096,10 @@
 CONFIG_SYSFS=y
 # CONFIG_DEVFS_FS is not set
 CONFIG_DEVPTS_FS_XATTR=y
-# CONFIG_DEVPTS_FS_SECURITY is not set
+CONFIG_DEVPTS_FS_SECURITY=y
 CONFIG_TMPFS=y
+CONFIG_TMPFS_XATTR=y
+CONFIG_TMPFS_SECURITY=y
 CONFIG_HUGETLBFS=y
 CONFIG_HUGETLB_PAGE=y
 CONFIG_RAMFS=y
@@ -1035,13 +1128,13 @@
 CONFIG_NFS_V3=y
 CONFIG_NFS_V4=y
 # CONFIG_NFS_DIRECTIO is not set
-CONFIG_NFSD=m
+CONFIG_NFSD=y
 CONFIG_NFSD_V3=y
 CONFIG_NFSD_V4=y
 CONFIG_NFSD_TCP=y
 CONFIG_LOCKD=y
 CONFIG_LOCKD_V4=y
-CONFIG_EXPORTFS=m
+CONFIG_EXPORTFS=y
 CONFIG_SUNRPC=y
 CONFIG_SUNRPC_GSS=y
 CONFIG_RPCSEC_GSS_KRB5=y
@@ -1051,6 +1144,7 @@
 # CONFIG_CIFS_STATS is not set
 CONFIG_CIFS_XATTR=y
 CONFIG_CIFS_POSIX=y
+# CONFIG_CIFS_EXPERIMENTAL is not set
 # CONFIG_NCP_FS is not set
 # CONFIG_CODA_FS is not set
 # CONFIG_AFS_FS is not set
@@ -1116,21 +1210,25 @@
 #
 CONFIG_DEBUG_KERNEL=y
 CONFIG_MAGIC_SYSRQ=y
+# CONFIG_SCHEDSTATS is not set
 # CONFIG_DEBUG_SLAB is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_KOBJECT is not set
 # CONFIG_DEBUG_INFO is not set
+CONFIG_DEBUG_FS=y
 CONFIG_DEBUG_STACKOVERFLOW=y
+# CONFIG_KPROBES is not set
 CONFIG_DEBUG_STACK_USAGE=y
 CONFIG_DEBUGGER=y
 CONFIG_XMON=y
 CONFIG_XMON_DEFAULT=y
 # CONFIG_PPCDBG is not set
 CONFIG_IRQSTACKS=y
-# CONFIG_SCHEDSTATS is not set
 
 #
 # Security options
 #
+# CONFIG_KEYS is not set
 # CONFIG_SECURITY is not set
 
 #
@@ -1144,7 +1242,7 @@
 CONFIG_CRYPTO_SHA1=m
 CONFIG_CRYPTO_SHA256=m
 CONFIG_CRYPTO_SHA512=m
-CONFIG_CRYPTO_WHIRLPOOL=m
+CONFIG_CRYPTO_WP512=m
 CONFIG_CRYPTO_DES=y
 CONFIG_CRYPTO_BLOWFISH=m
 CONFIG_CRYPTO_TWOFISH=m
@@ -1155,10 +1253,15 @@
 CONFIG_CRYPTO_TEA=m
 CONFIG_CRYPTO_ARC4=m
 CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_ANUBIS=m
 CONFIG_CRYPTO_DEFLATE=m
 CONFIG_CRYPTO_MICHAEL_MIC=m
 CONFIG_CRYPTO_CRC32C=m
 CONFIG_CRYPTO_TEST=m
+
+#
+# Hardware crypto devices
+#
 
 #
 # Library routines
diff -Nru a/arch/ppc64/defconfig b/arch/ppc64/defconfig
--- a/arch/ppc64/defconfig	2005-03-11 12:51:42 -08:00
+++ b/arch/ppc64/defconfig	2005-03-11 12:51:42 -08:00
@@ -1,9 +1,12 @@
 #
 # Automatically generated make config: don't edit
+# Linux kernel version: 2.6.11-rc3-bk6
+# Wed Feb  9 23:34:51 2005
 #
 CONFIG_64BIT=y
 CONFIG_MMU=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_GENERIC_ISA_DMA=y
 CONFIG_HAVE_DEC_LOCK=y
 CONFIG_EARLY_PRINTK=y
@@ -16,27 +19,35 @@
 #
 CONFIG_EXPERIMENTAL=y
 CONFIG_CLEAN_COMPILE=y
-CONFIG_STANDALONE=y
+CONFIG_LOCK_KERNEL=y
 
 #
 # General setup
 #
+CONFIG_LOCALVERSION=""
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
 # CONFIG_BSD_PROCESS_ACCT is not set
 CONFIG_SYSCTL=y
 CONFIG_LOG_BUF_SHIFT=17
 CONFIG_HOTPLUG=y
+CONFIG_KOBJECT_UEVENT=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 # CONFIG_EMBEDDED is not set
 CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
 
 #
 # Loadable module support
@@ -45,28 +56,40 @@
 CONFIG_MODULE_UNLOAD=y
 # CONFIG_MODULE_FORCE_UNLOAD is not set
 CONFIG_OBSOLETE_MODPARM=y
-# CONFIG_MODVERSIONS is not set
-# CONFIG_KMOD is not set
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SRCVERSION_ALL=y
+CONFIG_KMOD=y
 CONFIG_STOP_MACHINE=y
+CONFIG_SYSVIPC_COMPAT=y
 
 #
 # Platform support
 #
 # CONFIG_PPC_ISERIES is not set
+CONFIG_PPC_MULTIPLATFORM=y
 CONFIG_PPC_PSERIES=y
+CONFIG_PPC_PMAC=y
+CONFIG_PPC_MAPLE=y
 CONFIG_PPC=y
 CONFIG_PPC64=y
 CONFIG_PPC_OF=y
 CONFIG_ALTIVEC=y
-# CONFIG_PPC_PMAC is not set
-# CONFIG_BOOTX_TEXT is not set
+CONFIG_PPC_SPLPAR=y
+CONFIG_IBMVIO=y
+CONFIG_U3_DART=y
+CONFIG_MPIC_BROKEN_U3=y
+CONFIG_PPC_PMAC64=y
+CONFIG_BOOTX_TEXT=y
 # CONFIG_POWER4_ONLY is not set
-# CONFIG_IOMMU_VMERGE is not set
+CONFIG_IOMMU_VMERGE=y
 CONFIG_SMP=y
-CONFIG_IRQ_ALL_CPUS=y
 CONFIG_NR_CPUS=32
-# CONFIG_HMT is not set
-# CONFIG_DISCONTIGMEM is not set
+CONFIG_DISCONTIGMEM=y
+# CONFIG_NUMA is not set
+# CONFIG_SCHED_SMT is not set
+# CONFIG_PREEMPT is not set
+CONFIG_EEH=y
+CONFIG_GENERIC_HARDIRQS=y
 CONFIG_PPC_RTAS=y
 CONFIG_RTAS_FLASH=m
 CONFIG_SCANLOG=m
@@ -78,14 +101,19 @@
 CONFIG_PCI=y
 CONFIG_PCI_DOMAINS=y
 CONFIG_BINFMT_ELF=y
-# CONFIG_BINFMT_MISC is not set
-CONFIG_PCI_LEGACY_PROC=y
-CONFIG_PCI_NAMES=y
+CONFIG_BINFMT_MISC=m
+# CONFIG_PCI_LEGACY_PROC is not set
+# CONFIG_PCI_NAMES is not set
+CONFIG_HOTPLUG_CPU=y
 
 #
-# PCMCIA/CardBus support
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PC-card bridges
 #
-# CONFIG_PCMCIA is not set
 
 #
 # PCI Hotplug Support
@@ -93,7 +121,6 @@
 CONFIG_HOTPLUG_PCI=m
 # CONFIG_HOTPLUG_PCI_FAKE is not set
 # CONFIG_HOTPLUG_PCI_CPCI is not set
-# CONFIG_HOTPLUG_PCI_PCIE is not set
 # CONFIG_HOTPLUG_PCI_SHPC is not set
 CONFIG_HOTPLUG_PCI_RPA=m
 CONFIG_HOTPLUG_PCI_RPA_DLPAR=m
@@ -107,7 +134,9 @@
 #
 # Generic Driver Options
 #
-CONFIG_FW_LOADER=m
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
 # CONFIG_DEBUG_DRIVER is not set
 
 #
@@ -118,7 +147,14 @@
 #
 # Parallel port support
 #
-# CONFIG_PARPORT is not set
+CONFIG_PARPORT=m
+CONFIG_PARPORT_PC=m
+CONFIG_PARPORT_PC_CML1=m
+# CONFIG_PARPORT_SERIAL is not set
+# CONFIG_PARPORT_PC_FIFO is not set
+# CONFIG_PARPORT_PC_SUPERIO is not set
+# CONFIG_PARPORT_OTHER is not set
+# CONFIG_PARPORT_1284 is not set
 
 #
 # Plug and Play support
@@ -128,17 +164,32 @@
 # Block devices
 #
 CONFIG_BLK_DEV_FD=y
+# CONFIG_PARIDE is not set
 # CONFIG_BLK_CPQ_DA is not set
 # CONFIG_BLK_CPQ_CISS_DA is not set
 # CONFIG_BLK_DEV_DAC960 is not set
 # CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
 CONFIG_BLK_DEV_LOOP=y
 # CONFIG_BLK_DEV_CRYPTOLOOP is not set
 CONFIG_BLK_DEV_NBD=m
-# CONFIG_BLK_DEV_CARMEL is not set
+# CONFIG_BLK_DEV_SX8 is not set
+# CONFIG_BLK_DEV_UB is not set
 CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_SIZE=4096
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=65536
 CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
 
 #
 # ATA/ATAPI/MFM/RLL support
@@ -149,15 +200,14 @@
 #
 # Please see Documentation/ide.txt for help/info on IDE drives
 #
+# CONFIG_BLK_DEV_IDE_SATA is not set
 CONFIG_BLK_DEV_IDEDISK=y
 # CONFIG_IDEDISK_MULTI_MODE is not set
-# CONFIG_IDEDISK_STROKE is not set
 CONFIG_BLK_DEV_IDECD=y
 # CONFIG_BLK_DEV_IDETAPE is not set
 # CONFIG_BLK_DEV_IDEFLOPPY is not set
 # CONFIG_BLK_DEV_IDESCSI is not set
 # CONFIG_IDE_TASK_IOCTL is not set
-# CONFIG_IDE_TASKFILE_IO is not set
 
 #
 # IDE chipset support/bugfixes
@@ -173,7 +223,6 @@
 # CONFIG_BLK_DEV_IDEDMA_FORCED is not set
 CONFIG_IDEDMA_PCI_AUTO=y
 # CONFIG_IDEDMA_ONLYDISK is not set
-CONFIG_BLK_DEV_ADMA=y
 # CONFIG_BLK_DEV_AEC62XX is not set
 # CONFIG_BLK_DEV_ALI15X3 is not set
 CONFIG_BLK_DEV_AMD74XX=y
@@ -194,6 +243,11 @@
 # CONFIG_BLK_DEV_SLC90E66 is not set
 # CONFIG_BLK_DEV_TRM290 is not set
 # CONFIG_BLK_DEV_VIA82CXXX is not set
+CONFIG_BLK_DEV_IDE_PMAC=y
+CONFIG_BLK_DEV_IDE_PMAC_ATA100FIRST=y
+CONFIG_BLK_DEV_IDEDMA_PMAC=y
+# CONFIG_BLK_DEV_IDE_PMAC_BLINK is not set
+# CONFIG_IDE_ARM is not set
 CONFIG_BLK_DEV_IDEDMA=y
 # CONFIG_IDEDMA_IVB is not set
 CONFIG_IDEDMA_AUTO=y
@@ -219,7 +273,6 @@
 # Some SCSI devices (e.g. CD jukebox) support multiple LUNs
 #
 CONFIG_SCSI_MULTI_LUN=y
-CONFIG_SCSI_REPORT_LUNS=y
 CONFIG_SCSI_CONSTANTS=y
 # CONFIG_SCSI_LOGGING is not set
 
@@ -228,33 +281,52 @@
 #
 CONFIG_SCSI_SPI_ATTRS=y
 CONFIG_SCSI_FC_ATTRS=y
+CONFIG_SCSI_ISCSI_ATTRS=m
 
 #
 # SCSI low-level drivers
 #
 # CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_3W_9XXX is not set
 # CONFIG_SCSI_ACARD is not set
 # CONFIG_SCSI_AACRAID is not set
 # CONFIG_SCSI_AIC7XXX is not set
 # CONFIG_SCSI_AIC7XXX_OLD is not set
 # CONFIG_SCSI_AIC79XX is not set
-# CONFIG_SCSI_ADVANSYS is not set
-# CONFIG_SCSI_MEGARAID is not set
-# CONFIG_SCSI_SATA is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+CONFIG_SCSI_SATA=y
+# CONFIG_SCSI_SATA_AHCI is not set
+CONFIG_SCSI_SATA_SVW=y
+# CONFIG_SCSI_ATA_PIIX is not set
+# CONFIG_SCSI_SATA_NV is not set
+# CONFIG_SCSI_SATA_PROMISE is not set
+# CONFIG_SCSI_SATA_SX4 is not set
+# CONFIG_SCSI_SATA_SIL is not set
+# CONFIG_SCSI_SATA_SIS is not set
+# CONFIG_SCSI_SATA_ULI is not set
+# CONFIG_SCSI_SATA_VIA is not set
+# CONFIG_SCSI_SATA_VITESSE is not set
 # CONFIG_SCSI_BUSLOGIC is not set
-# CONFIG_SCSI_CPQFCTS is not set
 # CONFIG_SCSI_DMX3191D is not set
 # CONFIG_SCSI_EATA is not set
 # CONFIG_SCSI_EATA_PIO is not set
 # CONFIG_SCSI_FUTURE_DOMAIN is not set
 # CONFIG_SCSI_GDTH is not set
 # CONFIG_SCSI_IPS is not set
+CONFIG_SCSI_IBMVSCSI=y
+# CONFIG_SCSI_INITIO is not set
 # CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_PPA is not set
+# CONFIG_SCSI_IMM is not set
 CONFIG_SCSI_SYM53C8XX_2=y
 CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=0
 CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
 CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
 # CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set
+CONFIG_SCSI_IPR=y
+CONFIG_SCSI_IPR_TRACE=y
+CONFIG_SCSI_IPR_DUMP=y
 # CONFIG_SCSI_QLOGIC_ISP is not set
 # CONFIG_SCSI_QLOGIC_FC is not set
 # CONFIG_SCSI_QLOGIC_1280 is not set
@@ -264,10 +336,9 @@
 CONFIG_SCSI_QLA2300=m
 CONFIG_SCSI_QLA2322=m
 CONFIG_SCSI_QLA6312=m
-CONFIG_SCSI_QLA6322=m
 # CONFIG_SCSI_DC395x is not set
 # CONFIG_SCSI_DC390T is not set
-# CONFIG_SCSI_DEBUG is not set
+CONFIG_SCSI_DEBUG=m
 
 #
 # Multi-device support (RAID and LVM)
@@ -277,11 +348,16 @@
 CONFIG_MD_LINEAR=y
 CONFIG_MD_RAID0=y
 CONFIG_MD_RAID1=y
+CONFIG_MD_RAID10=y
 CONFIG_MD_RAID5=y
-CONFIG_MD_RAID6=y
-# CONFIG_MD_MULTIPATH is not set
+CONFIG_MD_RAID6=m
+CONFIG_MD_MULTIPATH=m
+CONFIG_MD_FAULTY=m
 CONFIG_BLK_DEV_DM=y
 CONFIG_DM_CRYPT=m
+CONFIG_DM_SNAPSHOT=m
+CONFIG_DM_MIRROR=m
+CONFIG_DM_ZERO=m
 
 #
 # Fusion MPT device support
@@ -291,15 +367,48 @@
 #
 # IEEE 1394 (FireWire) support
 #
-# CONFIG_IEEE1394 is not set
+CONFIG_IEEE1394=y
+
+#
+# Subsystem Options
+#
+# CONFIG_IEEE1394_VERBOSEDEBUG is not set
+# CONFIG_IEEE1394_OUI_DB is not set
+CONFIG_IEEE1394_EXTRA_CONFIG_ROMS=y
+CONFIG_IEEE1394_CONFIG_ROM_IP1394=y
+
+#
+# Device Drivers
+#
+# CONFIG_IEEE1394_PCILYNX is not set
+CONFIG_IEEE1394_OHCI1394=y
+
+#
+# Protocol Drivers
+#
+CONFIG_IEEE1394_VIDEO1394=m
+CONFIG_IEEE1394_SBP2=m
+# CONFIG_IEEE1394_SBP2_PHYS_DMA is not set
+CONFIG_IEEE1394_ETH1394=m
+CONFIG_IEEE1394_DV1394=m
+CONFIG_IEEE1394_RAWIO=y
+CONFIG_IEEE1394_CMP=m
+CONFIG_IEEE1394_AMDTP=m
 
 #
 # I2O device support
 #
+# CONFIG_I2O is not set
 
 #
 # Macintosh device drivers
 #
+CONFIG_ADB=y
+CONFIG_ADB_PMU=y
+# CONFIG_PMAC_PBOOK is not set
+# CONFIG_PMAC_BACKLIGHT is not set
+# CONFIG_INPUT_ADBHID is not set
+CONFIG_THERM_PM72=y
 
 #
 # Networking support
@@ -322,19 +431,19 @@
 # CONFIG_NET_IPGRE is not set
 # CONFIG_IP_MROUTE is not set
 # CONFIG_ARPD is not set
-CONFIG_INET_ECN=y
 CONFIG_SYN_COOKIES=y
 CONFIG_INET_AH=m
 CONFIG_INET_ESP=m
 CONFIG_INET_IPCOMP=m
+CONFIG_INET_TUNNEL=y
+# CONFIG_IP_TCPDIAG is not set
+# CONFIG_IP_TCPDIAG_IPV6 is not set
 
 #
 # IP: Virtual Server Configuration
 #
 # CONFIG_IP_VS is not set
 # CONFIG_IPV6 is not set
-# CONFIG_DECNET is not set
-# CONFIG_BRIDGE is not set
 CONFIG_NETFILTER=y
 # CONFIG_NETFILTER_DEBUG is not set
 
@@ -342,6 +451,9 @@
 # IP: Netfilter Configuration
 #
 CONFIG_IP_NF_CONNTRACK=m
+CONFIG_IP_NF_CT_ACCT=y
+CONFIG_IP_NF_CONNTRACK_MARK=y
+CONFIG_IP_NF_CT_PROTO_SCTP=m
 CONFIG_IP_NF_FTP=m
 CONFIG_IP_NF_IRC=m
 CONFIG_IP_NF_TFTP=m
@@ -366,8 +478,17 @@
 CONFIG_IP_NF_MATCH_STATE=m
 CONFIG_IP_NF_MATCH_CONNTRACK=m
 CONFIG_IP_NF_MATCH_OWNER=m
+CONFIG_IP_NF_MATCH_ADDRTYPE=m
+CONFIG_IP_NF_MATCH_REALM=m
+CONFIG_IP_NF_MATCH_SCTP=m
+CONFIG_IP_NF_MATCH_COMMENT=m
+CONFIG_IP_NF_MATCH_CONNMARK=m
+CONFIG_IP_NF_MATCH_HASHLIMIT=m
 CONFIG_IP_NF_FILTER=m
 CONFIG_IP_NF_TARGET_REJECT=m
+CONFIG_IP_NF_TARGET_LOG=m
+CONFIG_IP_NF_TARGET_ULOG=m
+CONFIG_IP_NF_TARGET_TCPMSS=m
 CONFIG_IP_NF_NAT=m
 CONFIG_IP_NF_NAT_NEEDED=y
 CONFIG_IP_NF_TARGET_MASQUERADE=m
@@ -385,24 +506,24 @@
 CONFIG_IP_NF_TARGET_DSCP=m
 CONFIG_IP_NF_TARGET_MARK=m
 CONFIG_IP_NF_TARGET_CLASSIFY=m
-CONFIG_IP_NF_TARGET_LOG=m
-CONFIG_IP_NF_TARGET_ULOG=m
-CONFIG_IP_NF_TARGET_TCPMSS=m
+CONFIG_IP_NF_TARGET_CONNMARK=m
+CONFIG_IP_NF_TARGET_CLUSTERIP=m
+CONFIG_IP_NF_RAW=m
+CONFIG_IP_NF_TARGET_NOTRACK=m
 CONFIG_IP_NF_ARPTABLES=m
 CONFIG_IP_NF_ARPFILTER=m
 CONFIG_IP_NF_ARP_MANGLE=m
-CONFIG_IP_NF_COMPAT_IPCHAINS=m
-CONFIG_IP_NF_COMPAT_IPFWADM=m
 CONFIG_XFRM=y
 CONFIG_XFRM_USER=m
 
 #
 # SCTP Configuration (EXPERIMENTAL)
 #
-CONFIG_IPV6_SCTP__=y
 # CONFIG_IP_SCTP is not set
 # CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
 # CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
 CONFIG_LLC=y
 # CONFIG_LLC2 is not set
 # CONFIG_IPX is not set
@@ -412,36 +533,42 @@
 # CONFIG_NET_DIVERT is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
-# CONFIG_NET_HW_FLOWCONTROL is not set
 
 #
 # QoS and/or fair queueing
 #
 # CONFIG_NET_SCHED is not set
+CONFIG_NET_CLS_ROUTE=y
 
 #
 # Network testing
 #
 # CONFIG_NET_PKTGEN is not set
+CONFIG_NETPOLL=y
+CONFIG_NETPOLL_RX=y
+CONFIG_NETPOLL_TRAP=y
+CONFIG_NET_POLL_CONTROLLER=y
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
 CONFIG_NETDEVICES=y
+CONFIG_DUMMY=m
+CONFIG_BONDING=m
+# CONFIG_EQUALIZER is not set
+CONFIG_TUN=m
 
 #
 # ARCnet devices
 #
 # CONFIG_ARCNET is not set
-CONFIG_DUMMY=m
-CONFIG_BONDING=m
-# CONFIG_EQUALIZER is not set
-CONFIG_TUN=m
 
 #
 # Ethernet (10 or 100Mbit)
 #
 CONFIG_NET_ETHERNET=y
 CONFIG_MII=y
-# CONFIG_OAKNET is not set
 # CONFIG_HAPPYMEAL is not set
-# CONFIG_SUNGEM is not set
+CONFIG_SUNGEM=y
 CONFIG_NET_VENDOR_3COM=y
 CONFIG_VORTEX=y
 # CONFIG_TYPHOON is not set
@@ -451,6 +578,7 @@
 #
 # CONFIG_NET_TULIP is not set
 # CONFIG_HP100 is not set
+CONFIG_IBMVETH=m
 CONFIG_NET_PCI=y
 CONFIG_PCNET32=y
 # CONFIG_AMD8111_ETH is not set
@@ -483,8 +611,8 @@
 # CONFIG_HAMACHI is not set
 # CONFIG_YELLOWFIN is not set
 # CONFIG_R8169 is not set
-# CONFIG_SIS190 is not set
 # CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
 CONFIG_TIGON3=y
 
 #
@@ -492,59 +620,40 @@
 #
 CONFIG_IXGB=m
 # CONFIG_IXGB_NAPI is not set
-# CONFIG_FDDI is not set
-# CONFIG_HIPPI is not set
-CONFIG_IBMVETH=m
-CONFIG_PPP=m
-# CONFIG_PPP_MULTILINK is not set
-# CONFIG_PPP_FILTER is not set
-CONFIG_PPP_ASYNC=m
-CONFIG_PPP_SYNC_TTY=m
-CONFIG_PPP_DEFLATE=m
-CONFIG_PPP_BSDCOMP=m
-CONFIG_PPPOE=m
-# CONFIG_SLIP is not set
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
+# CONFIG_S2IO is not set
 
 #
 # Token Ring devices
 #
 CONFIG_TR=y
 CONFIG_IBMOL=y
-# CONFIG_IBMLS is not set
 # CONFIG_3C359 is not set
 # CONFIG_TMS380TR is not set
-# CONFIG_NET_FC is not set
-# CONFIG_SHAPER is not set
-CONFIG_NETCONSOLE=y
-
-#
-# Wan interfaces
-#
-# CONFIG_WAN is not set
-
-#
-# Amateur Radio support
-#
-# CONFIG_HAMRADIO is not set
 
 #
-# IrDA (infrared) support
+# Wireless LAN (non-hamradio)
 #
-# CONFIG_IRDA is not set
+# CONFIG_NET_RADIO is not set
 
 #
-# Bluetooth support
+# Wan interfaces
 #
-# CONFIG_BT is not set
-CONFIG_NETPOLL=y
-CONFIG_NETPOLL_RX=y
-CONFIG_NETPOLL_TRAP=y
-CONFIG_NET_POLL_CONTROLLER=y
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PLIP is not set
+CONFIG_PPP=m
+# CONFIG_PPP_MULTILINK is not set
+# CONFIG_PPP_FILTER is not set
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_BSDCOMP=m
+CONFIG_PPPOE=m
+# CONFIG_SLIP is not set
+# CONFIG_NET_FC is not set
+# CONFIG_SHAPER is not set
+CONFIG_NETCONSOLE=y
 
 #
 # ISDN subsystem
@@ -565,12 +674,12 @@
 # Userland interfaces
 #
 CONFIG_INPUT_MOUSEDEV=y
-CONFIG_INPUT_MOUSEDEV_PSAUX=y
+# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
 CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
 CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
 # CONFIG_INPUT_JOYDEV is not set
 # CONFIG_INPUT_TSDEV is not set
-# CONFIG_INPUT_EVDEV is not set
+CONFIG_INPUT_EVDEV=m
 # CONFIG_INPUT_EVBUG is not set
 
 #
@@ -582,7 +691,10 @@
 CONFIG_SERIO_I8042=y
 # CONFIG_SERIO_SERPORT is not set
 # CONFIG_SERIO_CT82C710 is not set
+# CONFIG_SERIO_PARKBD is not set
 # CONFIG_SERIO_PCIPS2 is not set
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
 
 #
 # Input Device Drivers
@@ -590,15 +702,17 @@
 CONFIG_INPUT_KEYBOARD=y
 CONFIG_KEYBOARD_ATKBD=y
 # CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
 # CONFIG_KEYBOARD_XTKBD is not set
 # CONFIG_KEYBOARD_NEWTON is not set
 CONFIG_INPUT_MOUSE=y
 CONFIG_MOUSE_PS2=y
 # CONFIG_MOUSE_SERIAL is not set
+# CONFIG_MOUSE_VSXXXAA is not set
 # CONFIG_INPUT_JOYSTICK is not set
 # CONFIG_INPUT_TOUCHSCREEN is not set
 CONFIG_INPUT_MISC=y
-CONFIG_INPUT_PCSPKR=y
+CONFIG_INPUT_PCSPKR=m
 # CONFIG_INPUT_UINPUT is not set
 
 #
@@ -623,16 +737,16 @@
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
 # CONFIG_SERIAL_PMACZILOG is not set
+CONFIG_SERIAL_ICOM=m
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
+CONFIG_PRINTER=m
+# CONFIG_LP_CONSOLE is not set
+# CONFIG_PPDEV is not set
+# CONFIG_TIPAR is not set
 CONFIG_HVC_CONSOLE=y
-
-#
-# Mice
-#
-# CONFIG_BUSMOUSE is not set
-# CONFIG_QIC02_TAPE is not set
+CONFIG_HVCS=m
 
 #
 # IPMI
@@ -652,7 +766,6 @@
 #
 # Ftape, the floppy tape device driver
 #
-# CONFIG_AGP is not set
 # CONFIG_DRM is not set
 CONFIG_RAW_DRIVER=y
 CONFIG_MAX_RAW_DEVS=256
@@ -661,25 +774,30 @@
 # I2C support
 #
 CONFIG_I2C=y
-# CONFIG_I2C_CHARDEV is not set
+CONFIG_I2C_CHARDEV=y
 
 #
 # I2C Algorithms
 #
 CONFIG_I2C_ALGOBIT=y
 # CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
 
 #
 # I2C Hardware Bus support
 #
 # CONFIG_I2C_ALI1535 is not set
+# CONFIG_I2C_ALI1563 is not set
 # CONFIG_I2C_ALI15X3 is not set
 # CONFIG_I2C_AMD756 is not set
-# CONFIG_I2C_AMD8111 is not set
+CONFIG_I2C_AMD8111=y
 # CONFIG_I2C_I801 is not set
 # CONFIG_I2C_I810 is not set
 # CONFIG_I2C_ISA is not set
+CONFIG_I2C_KEYWEST=y
+# CONFIG_I2C_MPC is not set
 # CONFIG_I2C_NFORCE2 is not set
+# CONFIG_I2C_PARPORT is not set
 # CONFIG_I2C_PARPORT_LIGHT is not set
 # CONFIG_I2C_PROSAVAGE is not set
 # CONFIG_I2C_SAVAGE4 is not set
@@ -687,33 +805,61 @@
 # CONFIG_I2C_SIS5595 is not set
 # CONFIG_I2C_SIS630 is not set
 # CONFIG_I2C_SIS96X is not set
+# CONFIG_I2C_STUB is not set
 # CONFIG_I2C_VIA is not set
 # CONFIG_I2C_VIAPRO is not set
 # CONFIG_I2C_VOODOO3 is not set
+# CONFIG_I2C_PCA_ISA is not set
 
 #
-# I2C Hardware Sensors Chip support
+# Hardware Sensors Chip support
 #
 # CONFIG_I2C_SENSOR is not set
 # CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1031 is not set
 # CONFIG_SENSORS_ASB100 is not set
-# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_DS1621 is not set
 # CONFIG_SENSORS_FSCHER is not set
 # CONFIG_SENSORS_GL518SM is not set
 # CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
 # CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
 # CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
 # CONFIG_SENSORS_LM83 is not set
 # CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
 # CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
 # CONFIG_SENSORS_VIA686A is not set
 # CONFIG_SENSORS_W83781D is not set
 # CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83627HF is not set
+
+#
+# Other I2C Chip support
+#
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_RTC8564 is not set
 # CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
 # CONFIG_I2C_DEBUG_BUS is not set
 # CONFIG_I2C_DEBUG_CHIP is not set
 
 #
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
 # Misc devices
 #
 
@@ -731,20 +877,28 @@
 # Graphics support
 #
 CONFIG_FB=y
+CONFIG_FB_MODE_HELPERS=y
+CONFIG_FB_TILEBLITTING=y
+# CONFIG_FB_CIRRUS is not set
 # CONFIG_FB_PM2 is not set
 # CONFIG_FB_CYBER2000 is not set
 CONFIG_FB_OF=y
+# CONFIG_FB_CONTROL is not set
+# CONFIG_FB_PLATINUM is not set
+# CONFIG_FB_VALKYRIE is not set
 # CONFIG_FB_CT65550 is not set
+# CONFIG_FB_ASILIANT is not set
 # CONFIG_FB_IMSTT is not set
-# CONFIG_FB_S3TRIO is not set
 # CONFIG_FB_VGA16 is not set
-# CONFIG_FB_RIVA is not set
+CONFIG_FB_RIVA=y
+CONFIG_FB_RIVA_I2C=y
+# CONFIG_FB_RIVA_DEBUG is not set
 CONFIG_FB_MATROX=y
 CONFIG_FB_MATROX_MILLENIUM=y
 CONFIG_FB_MATROX_MYSTIQUE=y
-CONFIG_FB_MATROX_G450=y
-CONFIG_FB_MATROX_G100=y
-# CONFIG_FB_MATROX_I2C is not set
+CONFIG_FB_MATROX_G=y
+CONFIG_FB_MATROX_I2C=m
+CONFIG_FB_MATROX_MAVEN=m
 CONFIG_FB_MATROX_MULTIHEAD=y
 # CONFIG_FB_RADEON_OLD is not set
 CONFIG_FB_RADEON=y
@@ -752,6 +906,7 @@
 # CONFIG_FB_RADEON_DEBUG is not set
 # CONFIG_FB_ATY128 is not set
 # CONFIG_FB_ATY is not set
+# CONFIG_FB_SAVAGE is not set
 # CONFIG_FB_SIS is not set
 # CONFIG_FB_NEOMAGIC is not set
 # CONFIG_FB_KYRO is not set
@@ -764,10 +919,8 @@
 # Console display driver support
 #
 # CONFIG_VGA_CONSOLE is not set
-# CONFIG_MDA_CONSOLE is not set
 CONFIG_DUMMY_CONSOLE=y
 CONFIG_FRAMEBUFFER_CONSOLE=y
-CONFIG_PCI_CONSOLE=y
 # CONFIG_FONTS is not set
 CONFIG_FONT_8x8=y
 CONFIG_FONT_8x16=y
@@ -779,6 +932,11 @@
 CONFIG_LOGO_LINUX_MONO=y
 CONFIG_LOGO_LINUX_VGA16=y
 CONFIG_LOGO_LINUX_CLUT224=y
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+CONFIG_BACKLIGHT_DEVICE=y
+CONFIG_LCD_CLASS_DEVICE=y
+CONFIG_LCD_DEVICE=y
 
 #
 # Sound
@@ -797,13 +955,19 @@
 CONFIG_USB_DEVICEFS=y
 # CONFIG_USB_BANDWIDTH is not set
 # CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_OTG is not set
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
 
 #
 # USB Host Controller Drivers
 #
 CONFIG_USB_EHCI_HCD=y
+# CONFIG_USB_EHCI_SPLIT_ISO is not set
+# CONFIG_USB_EHCI_ROOT_HUB_TT is not set
 CONFIG_USB_OHCI_HCD=y
 # CONFIG_USB_UHCI_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
 
 #
 # USB Device Class drivers
@@ -811,8 +975,13 @@
 # CONFIG_USB_BLUETOOTH_TTY is not set
 # CONFIG_USB_ACM is not set
 # CONFIG_USB_PRINTER is not set
-CONFIG_USB_STORAGE=y
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=m
 # CONFIG_USB_STORAGE_DEBUG is not set
+CONFIG_USB_STORAGE_RW_DETECT=y
 # CONFIG_USB_STORAGE_DATAFAB is not set
 # CONFIG_USB_STORAGE_FREECOM is not set
 # CONFIG_USB_STORAGE_ISD200 is not set
@@ -823,7 +992,7 @@
 # CONFIG_USB_STORAGE_JUMPSHOT is not set
 
 #
-# USB Human Interface Devices (HID)
+# USB Input Devices
 #
 CONFIG_USB_HID=y
 CONFIG_USB_HIDINPUT=y
@@ -833,14 +1002,16 @@
 # CONFIG_USB_WACOM is not set
 # CONFIG_USB_KBTAB is not set
 # CONFIG_USB_POWERMATE is not set
+# CONFIG_USB_MTOUCH is not set
+# CONFIG_USB_EGALAX is not set
 # CONFIG_USB_XPAD is not set
+# CONFIG_USB_ATI_REMOTE is not set
 
 #
 # USB Imaging devices
 #
 # CONFIG_USB_MDC800 is not set
 # CONFIG_USB_MICROTEK is not set
-# CONFIG_USB_HPUSBSCSI is not set
 
 #
 # USB Multimedia devices
@@ -852,17 +1023,18 @@
 #
 
 #
-# USB Network adaptors
+# USB Network Adapters
 #
 # CONFIG_USB_CATC is not set
 # CONFIG_USB_KAWETH is not set
-# CONFIG_USB_PEGASUS is not set
+CONFIG_USB_PEGASUS=y
 # CONFIG_USB_RTL8150 is not set
 # CONFIG_USB_USBNET is not set
 
 #
 # USB port drivers
 #
+# CONFIG_USB_USS720 is not set
 
 #
 # USB Serial Converter support
@@ -874,50 +1046,81 @@
 #
 # CONFIG_USB_EMI62 is not set
 # CONFIG_USB_EMI26 is not set
-# CONFIG_USB_TIGL is not set
 # CONFIG_USB_AUERSWALD is not set
 # CONFIG_USB_RIO500 is not set
 # CONFIG_USB_LEGOTOWER is not set
 # CONFIG_USB_LCD is not set
 # CONFIG_USB_LED is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGETKIT is not set
+# CONFIG_USB_PHIDGETSERVO is not set
+# CONFIG_USB_IDMOUSE is not set
 # CONFIG_USB_TEST is not set
 
 #
+# USB ATM/DSL drivers
+#
+
+#
 # USB Gadget Support
 #
 # CONFIG_USB_GADGET is not set
 
 #
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+CONFIG_INFINIBAND=m
+CONFIG_INFINIBAND_MTHCA=m
+# CONFIG_INFINIBAND_MTHCA_DEBUG is not set
+CONFIG_INFINIBAND_IPOIB=m
+# CONFIG_INFINIBAND_IPOIB_DEBUG is not set
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
 CONFIG_EXT2_FS_XATTR=y
 CONFIG_EXT2_FS_POSIX_ACL=y
-# CONFIG_EXT2_FS_SECURITY is not set
+CONFIG_EXT2_FS_SECURITY=y
 CONFIG_EXT3_FS=y
 CONFIG_EXT3_FS_XATTR=y
 CONFIG_EXT3_FS_POSIX_ACL=y
-# CONFIG_EXT3_FS_SECURITY is not set
+CONFIG_EXT3_FS_SECURITY=y
 CONFIG_JBD=y
 # CONFIG_JBD_DEBUG is not set
 CONFIG_FS_MBCACHE=y
 CONFIG_REISERFS_FS=y
 # CONFIG_REISERFS_CHECK is not set
 # CONFIG_REISERFS_PROC_INFO is not set
+CONFIG_REISERFS_FS_XATTR=y
+CONFIG_REISERFS_FS_POSIX_ACL=y
+CONFIG_REISERFS_FS_SECURITY=y
 CONFIG_JFS_FS=y
 CONFIG_JFS_POSIX_ACL=y
+CONFIG_JFS_SECURITY=y
 # CONFIG_JFS_DEBUG is not set
 # CONFIG_JFS_STATISTICS is not set
 CONFIG_FS_POSIX_ACL=y
+
+#
+# XFS support
+#
 CONFIG_XFS_FS=m
+CONFIG_XFS_EXPORT=y
 # CONFIG_XFS_RT is not set
 # CONFIG_XFS_QUOTA is not set
-# CONFIG_XFS_SECURITY is not set
+CONFIG_XFS_SECURITY=y
 CONFIG_XFS_POSIX_ACL=y
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
 # CONFIG_QUOTA is not set
-CONFIG_AUTOFS_FS=m
+CONFIG_DNOTIFY=y
+CONFIG_AUTOFS_FS=y
 # CONFIG_AUTOFS4_FS is not set
 
 #
@@ -927,6 +1130,7 @@
 # CONFIG_JOLIET is not set
 # CONFIG_ZISOFS is not set
 CONFIG_UDF_FS=m
+CONFIG_UDF_NLS=y
 
 #
 # DOS/FAT/NT Filesystems
@@ -934,6 +1138,8 @@
 CONFIG_FAT_FS=y
 CONFIG_MSDOS_FS=y
 CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
 # CONFIG_NTFS_FS is not set
 
 #
@@ -941,10 +1147,13 @@
 #
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
 # CONFIG_DEVFS_FS is not set
 CONFIG_DEVPTS_FS_XATTR=y
-# CONFIG_DEVPTS_FS_SECURITY is not set
+CONFIG_DEVPTS_FS_SECURITY=y
 CONFIG_TMPFS=y
+CONFIG_TMPFS_XATTR=y
+CONFIG_TMPFS_SECURITY=y
 CONFIG_HUGETLBFS=y
 CONFIG_HUGETLB_PAGE=y
 CONFIG_RAMFS=y
@@ -954,8 +1163,8 @@
 #
 # CONFIG_ADFS_FS is not set
 # CONFIG_AFFS_FS is not set
-# CONFIG_HFS_FS is not set
-# CONFIG_HFSPLUS_FS is not set
+CONFIG_HFS_FS=m
+CONFIG_HFSPLUS_FS=m
 # CONFIG_BEFS_FS is not set
 # CONFIG_BFS_FS is not set
 # CONFIG_EFS_FS is not set
@@ -973,18 +1182,23 @@
 CONFIG_NFS_V3=y
 CONFIG_NFS_V4=y
 # CONFIG_NFS_DIRECTIO is not set
-CONFIG_NFSD=y
+CONFIG_NFSD=m
 CONFIG_NFSD_V3=y
 CONFIG_NFSD_V4=y
 CONFIG_NFSD_TCP=y
 CONFIG_LOCKD=y
 CONFIG_LOCKD_V4=y
-CONFIG_EXPORTFS=y
+CONFIG_EXPORTFS=m
 CONFIG_SUNRPC=y
-CONFIG_SUNRPC_GSS=m
-CONFIG_RPCSEC_GSS_KRB5=m
+CONFIG_SUNRPC_GSS=y
+CONFIG_RPCSEC_GSS_KRB5=y
+CONFIG_RPCSEC_GSS_SPKM3=m
 # CONFIG_SMB_FS is not set
 CONFIG_CIFS=m
+# CONFIG_CIFS_STATS is not set
+CONFIG_CIFS_XATTR=y
+CONFIG_CIFS_POSIX=y
+# CONFIG_CIFS_EXPERIMENTAL is not set
 # CONFIG_NCP_FS is not set
 # CONFIG_CODA_FS is not set
 # CONFIG_AFS_FS is not set
@@ -992,51 +1206,66 @@
 #
 # Partition Types
 #
-# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+CONFIG_MAC_PARTITION=y
 CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
 
 #
 # Native Language Support
 #
 CONFIG_NLS=y
 CONFIG_NLS_DEFAULT="iso8859-1"
-# CONFIG_NLS_CODEPAGE_437 is not set
-# CONFIG_NLS_CODEPAGE_737 is not set
-# CONFIG_NLS_CODEPAGE_775 is not set
-# CONFIG_NLS_CODEPAGE_850 is not set
-# CONFIG_NLS_CODEPAGE_852 is not set
-# CONFIG_NLS_CODEPAGE_855 is not set
-# CONFIG_NLS_CODEPAGE_857 is not set
-# CONFIG_NLS_CODEPAGE_860 is not set
-# CONFIG_NLS_CODEPAGE_861 is not set
-# CONFIG_NLS_CODEPAGE_862 is not set
-# CONFIG_NLS_CODEPAGE_863 is not set
-# CONFIG_NLS_CODEPAGE_864 is not set
-# CONFIG_NLS_CODEPAGE_865 is not set
-# CONFIG_NLS_CODEPAGE_866 is not set
-# CONFIG_NLS_CODEPAGE_869 is not set
-# CONFIG_NLS_CODEPAGE_936 is not set
-# CONFIG_NLS_CODEPAGE_950 is not set
-# CONFIG_NLS_CODEPAGE_932 is not set
-# CONFIG_NLS_CODEPAGE_949 is not set
-# CONFIG_NLS_CODEPAGE_874 is not set
-# CONFIG_NLS_ISO8859_8 is not set
-# CONFIG_NLS_CODEPAGE_1250 is not set
-# CONFIG_NLS_CODEPAGE_1251 is not set
-# CONFIG_NLS_ISO8859_1 is not set
-# CONFIG_NLS_ISO8859_2 is not set
-# CONFIG_NLS_ISO8859_3 is not set
-# CONFIG_NLS_ISO8859_4 is not set
-# CONFIG_NLS_ISO8859_5 is not set
-# CONFIG_NLS_ISO8859_6 is not set
-# CONFIG_NLS_ISO8859_7 is not set
-# CONFIG_NLS_ISO8859_9 is not set
-# CONFIG_NLS_ISO8859_13 is not set
-# CONFIG_NLS_ISO8859_14 is not set
-# CONFIG_NLS_ISO8859_15 is not set
-# CONFIG_NLS_KOI8_R is not set
-# CONFIG_NLS_KOI8_U is not set
-# CONFIG_NLS_UTF8 is not set
+CONFIG_NLS_CODEPAGE_437=m
+CONFIG_NLS_CODEPAGE_737=m
+CONFIG_NLS_CODEPAGE_775=m
+CONFIG_NLS_CODEPAGE_850=m
+CONFIG_NLS_CODEPAGE_852=m
+CONFIG_NLS_CODEPAGE_855=m
+CONFIG_NLS_CODEPAGE_857=m
+CONFIG_NLS_CODEPAGE_860=m
+CONFIG_NLS_CODEPAGE_861=m
+CONFIG_NLS_CODEPAGE_862=m
+CONFIG_NLS_CODEPAGE_863=m
+CONFIG_NLS_CODEPAGE_864=m
+CONFIG_NLS_CODEPAGE_865=m
+CONFIG_NLS_CODEPAGE_866=m
+CONFIG_NLS_CODEPAGE_869=m
+CONFIG_NLS_CODEPAGE_936=m
+CONFIG_NLS_CODEPAGE_950=m
+CONFIG_NLS_CODEPAGE_932=m
+CONFIG_NLS_CODEPAGE_949=m
+CONFIG_NLS_CODEPAGE_874=m
+CONFIG_NLS_ISO8859_8=m
+CONFIG_NLS_CODEPAGE_1250=m
+CONFIG_NLS_CODEPAGE_1251=m
+CONFIG_NLS_ASCII=m
+CONFIG_NLS_ISO8859_1=m
+CONFIG_NLS_ISO8859_2=m
+CONFIG_NLS_ISO8859_3=m
+CONFIG_NLS_ISO8859_4=m
+CONFIG_NLS_ISO8859_5=m
+CONFIG_NLS_ISO8859_6=m
+CONFIG_NLS_ISO8859_7=m
+CONFIG_NLS_ISO8859_9=m
+CONFIG_NLS_ISO8859_13=m
+CONFIG_NLS_ISO8859_14=m
+CONFIG_NLS_ISO8859_15=m
+CONFIG_NLS_KOI8_R=m
+CONFIG_NLS_KOI8_U=m
+CONFIG_NLS_UTF8=m
 
 #
 # Profiling support
@@ -1048,19 +1277,26 @@
 # Kernel hacking
 #
 CONFIG_DEBUG_KERNEL=y
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_INFO is not set
+CONFIG_DEBUG_FS=y
 CONFIG_DEBUG_STACKOVERFLOW=y
+# CONFIG_KPROBES is not set
 CONFIG_DEBUG_STACK_USAGE=y
-# CONFIG_DEBUG_SLAB is not set
-CONFIG_MAGIC_SYSRQ=y
 CONFIG_DEBUGGER=y
 CONFIG_XMON=y
-CONFIG_XMON_DEFAULT=y
+# CONFIG_XMON_DEFAULT is not set
 # CONFIG_PPCDBG is not set
-# CONFIG_DEBUG_INFO is not set
+CONFIG_IRQSTACKS=y
 
 #
 # Security options
 #
+# CONFIG_KEYS is not set
 # CONFIG_SECURITY is not set
 
 #
@@ -1070,24 +1306,36 @@
 CONFIG_CRYPTO_HMAC=y
 CONFIG_CRYPTO_NULL=m
 CONFIG_CRYPTO_MD4=m
-CONFIG_CRYPTO_MD5=m
+CONFIG_CRYPTO_MD5=y
 CONFIG_CRYPTO_SHA1=m
 CONFIG_CRYPTO_SHA256=m
 CONFIG_CRYPTO_SHA512=m
-CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_DES=y
 CONFIG_CRYPTO_BLOWFISH=m
 CONFIG_CRYPTO_TWOFISH=m
 CONFIG_CRYPTO_SERPENT=m
 CONFIG_CRYPTO_AES=m
 CONFIG_CRYPTO_CAST5=m
 CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_TEA=m
 CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_ANUBIS=m
 CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_CRC32C=m
 CONFIG_CRYPTO_TEST=m
 
 #
+# Hardware crypto devices
+#
+
+#
 # Library routines
 #
+CONFIG_CRC_CCITT=m
 CONFIG_CRC32=y
+CONFIG_LIBCRC32C=m
 CONFIG_ZLIB_INFLATE=y
 CONFIG_ZLIB_DEFLATE=m
diff -Nru a/arch/ppc64/kernel/LparData.c b/arch/ppc64/kernel/LparData.c
--- a/arch/ppc64/kernel/LparData.c	2005-03-11 12:51:42 -08:00
+++ b/arch/ppc64/kernel/LparData.c	2005-03-11 12:51:42 -08:00
@@ -45,7 +45,7 @@
 	.xSize = sizeof(struct HvReleaseData),
 	.xVpdAreasPtrOffset = offsetof(struct naca_struct, xItVpdAreas),
 	.xSlicNacaAddr = &naca,		/* 64-bit Naca address */
-	.xMsNucDataOffset = 0x6000,	/* offset of LparMap within loadarea (see head.S) */
+	.xMsNucDataOffset = 0x4800,	/* offset of LparMap within loadarea (see head.S) */
 	.xTagsMode = 1,			/* tags inactive       */
 	.xAddressSize = 0,		/* 64 bit              */
 	.xNoSharedProcs = 0,		/* shared processors   */
@@ -224,6 +224,7 @@
 };
 
 struct msChunks msChunks;
+EXPORT_SYMBOL(msChunks);
 
 /* Depending on whether this is called from iSeries or pSeries setup
  * code, the location of the msChunks struct may or may not have
diff -Nru a/arch/ppc64/kernel/Makefile b/arch/ppc64/kernel/Makefile
--- a/arch/ppc64/kernel/Makefile	2005-03-11 12:51:51 -08:00
+++ b/arch/ppc64/kernel/Makefile	2005-03-11 12:51:51 -08:00
@@ -11,7 +11,8 @@
 			udbg.o binfmt_elf32.o sys_ppc32.o ioctl32.o \
 			ptrace32.o signal32.o rtc.o init_task.o \
 			lmb.o cputable.o cpu_setup_power4.o idle_power4.o \
-			iommu.o sysfs.o
+			iommu.o sysfs.o vdso.o pmc.o
+obj-y += vdso32/ vdso64/
 
 obj-$(CONFIG_PPC_OF) +=	of_device.o
 
diff -Nru a/arch/ppc64/kernel/align.c b/arch/ppc64/kernel/align.c
--- a/arch/ppc64/kernel/align.c	2005-03-11 12:51:52 -08:00
+++ b/arch/ppc64/kernel/align.c	2005-03-11 12:51:52 -08:00
@@ -238,7 +238,7 @@
 
 	dsisr = regs->dsisr;
 
-	if (cur_cpu_spec->cpu_features & CPU_FTR_NODSISRALIGN) {
+	if (cpu_has_feature(CPU_FTR_NODSISRALIGN)) {
 	    unsigned int real_instr;
 	    if (__get_user(real_instr, (unsigned int __user *)regs->nip))
 		return 0;
diff -Nru a/arch/ppc64/kernel/asm-offsets.c b/arch/ppc64/kernel/asm-offsets.c
--- a/arch/ppc64/kernel/asm-offsets.c	2005-03-11 12:51:47 -08:00
+++ b/arch/ppc64/kernel/asm-offsets.c	2005-03-11 12:51:47 -08:00
@@ -22,6 +22,7 @@
 #include <linux/types.h>
 #include <linux/mman.h>
 #include <linux/mm.h>
+#include <linux/time.h>
 #include <linux/hardirq.h>
 #include <asm/io.h>
 #include <asm/page.h>
@@ -35,6 +36,8 @@
 #include <asm/rtas.h>
 #include <asm/cputable.h>
 #include <asm/cache.h>
+#include <asm/systemcfg.h>
+#include <asm/compat.h>
 
 #define DEFINE(sym, val) \
 	asm volatile("\n->" #sym " %0 " #val : : "i" (val))
@@ -166,6 +169,25 @@
 	DEFINE(CPU_SPEC_PVR_VALUE, offsetof(struct cpu_spec, pvr_value));
 	DEFINE(CPU_SPEC_FEATURES, offsetof(struct cpu_spec, cpu_features));
 	DEFINE(CPU_SPEC_SETUP, offsetof(struct cpu_spec, cpu_setup));
+
+	/* systemcfg offsets for use by vdso */
+	DEFINE(CFG_TB_ORIG_STAMP, offsetof(struct systemcfg, tb_orig_stamp));
+	DEFINE(CFG_TB_TICKS_PER_SEC, offsetof(struct systemcfg, tb_ticks_per_sec));
+	DEFINE(CFG_TB_TO_XS, offsetof(struct systemcfg, tb_to_xs));
+	DEFINE(CFG_STAMP_XSEC, offsetof(struct systemcfg, stamp_xsec));
+	DEFINE(CFG_TB_UPDATE_COUNT, offsetof(struct systemcfg, tb_update_count));
+	DEFINE(CFG_TZ_MINUTEWEST, offsetof(struct systemcfg, tz_minuteswest));
+	DEFINE(CFG_TZ_DSTTIME, offsetof(struct systemcfg, tz_dsttime));
+	DEFINE(CFG_SYSCALL_MAP32, offsetof(struct systemcfg, syscall_map_32));
+	DEFINE(CFG_SYSCALL_MAP64, offsetof(struct systemcfg, syscall_map_64));
+
+	/* timeval/timezone offsets for use by vdso */
+	DEFINE(TVAL64_TV_SEC, offsetof(struct timeval, tv_sec));
+	DEFINE(TVAL64_TV_USEC, offsetof(struct timeval, tv_usec));
+	DEFINE(TVAL32_TV_SEC, offsetof(struct compat_timeval, tv_sec));
+	DEFINE(TVAL32_TV_USEC, offsetof(struct compat_timeval, tv_usec));
+	DEFINE(TZONE_TZ_MINWEST, offsetof(struct timezone, tz_minuteswest));
+	DEFINE(TZONE_TZ_DSTTIME, offsetof(struct timezone, tz_dsttime));
 
 	return 0;
 }
diff -Nru a/arch/ppc64/kernel/cputable.c b/arch/ppc64/kernel/cputable.c
--- a/arch/ppc64/kernel/cputable.c	2005-03-11 12:51:40 -08:00
+++ b/arch/ppc64/kernel/cputable.c	2005-03-11 12:51:40 -08:00
@@ -17,9 +17,12 @@
 #include <linux/sched.h>
 #include <linux/threads.h>
 #include <linux/init.h>
+#include <linux/module.h>
+
 #include <asm/cputable.h>
 
 struct cpu_spec* cur_cpu_spec = NULL;
+EXPORT_SYMBOL(cur_cpu_spec);
 
 /* NOTE:
  * Unlike ppc32, ppc64 will only call this once for the boot CPU, it's
diff -Nru a/arch/ppc64/kernel/dma.c b/arch/ppc64/kernel/dma.c
--- a/arch/ppc64/kernel/dma.c	2005-03-11 12:51:41 -08:00
+++ b/arch/ppc64/kernel/dma.c	2005-03-11 12:51:41 -08:00
@@ -13,14 +13,23 @@
 #include <asm/scatterlist.h>
 #include <asm/bug.h>
 
-int dma_supported(struct device *dev, u64 mask)
+static struct dma_mapping_ops *get_dma_ops(struct device *dev)
 {
 	if (dev->bus == &pci_bus_type)
-		return pci_dma_supported(to_pci_dev(dev), mask);
+		return &pci_dma_ops;
 #ifdef CONFIG_IBMVIO
 	if (dev->bus == &vio_bus_type)
-		return vio_dma_supported(to_vio_dev(dev), mask);
-#endif /* CONFIG_IBMVIO */
+		return &vio_dma_ops;
+#endif
+	return NULL;
+}
+
+int dma_supported(struct device *dev, u64 mask)
+{
+	struct dma_mapping_ops *dma_ops = get_dma_ops(dev);
+
+	if (dma_ops)
+		return dma_ops->dma_supported(dev, mask);
 	BUG();
 	return 0;
 }
@@ -32,7 +41,7 @@
 		return pci_set_dma_mask(to_pci_dev(dev), dma_mask);
 #ifdef CONFIG_IBMVIO
 	if (dev->bus == &vio_bus_type)
-		return vio_set_dma_mask(to_vio_dev(dev), dma_mask);
+		return -EIO;
 #endif /* CONFIG_IBMVIO */
 	BUG();
 	return 0;
@@ -42,12 +51,10 @@
 void *dma_alloc_coherent(struct device *dev, size_t size,
 		dma_addr_t *dma_handle, int flag)
 {
-	if (dev->bus == &pci_bus_type)
-		return pci_alloc_consistent(to_pci_dev(dev), size, dma_handle);
-#ifdef CONFIG_IBMVIO
-	if (dev->bus == &vio_bus_type)
-		return vio_alloc_consistent(to_vio_dev(dev), size, dma_handle);
-#endif /* CONFIG_IBMVIO */
+	struct dma_mapping_ops *dma_ops = get_dma_ops(dev);
+
+	if (dma_ops)
+		return dma_ops->alloc_coherent(dev, size, dma_handle, flag);
 	BUG();
 	return NULL;
 }
@@ -56,12 +63,10 @@
 void dma_free_coherent(struct device *dev, size_t size, void *cpu_addr,
 		dma_addr_t dma_handle)
 {
-	if (dev->bus == &pci_bus_type)
-		pci_free_consistent(to_pci_dev(dev), size, cpu_addr, dma_handle);
-#ifdef CONFIG_IBMVIO
-	else if (dev->bus == &vio_bus_type)
-		vio_free_consistent(to_vio_dev(dev), size, cpu_addr, dma_handle);
-#endif /* CONFIG_IBMVIO */
+	struct dma_mapping_ops *dma_ops = get_dma_ops(dev);
+
+	if (dma_ops)
+		dma_ops->free_coherent(dev, size, cpu_addr, dma_handle);
 	else
 		BUG();
 }
@@ -70,12 +75,10 @@
 dma_addr_t dma_map_single(struct device *dev, void *cpu_addr, size_t size,
 		enum dma_data_direction direction)
 {
-	if (dev->bus == &pci_bus_type)
-		return pci_map_single(to_pci_dev(dev), cpu_addr, size, (int)direction);
-#ifdef CONFIG_IBMVIO
-	if (dev->bus == &vio_bus_type)
-		return vio_map_single(to_vio_dev(dev), cpu_addr, size, direction);
-#endif /* CONFIG_IBMVIO */
+	struct dma_mapping_ops *dma_ops = get_dma_ops(dev);
+
+	if (dma_ops)
+		return dma_ops->map_single(dev, cpu_addr, size, direction);
 	BUG();
 	return (dma_addr_t)0;
 }
@@ -84,12 +87,10 @@
 void dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
 		enum dma_data_direction direction)
 {
-	if (dev->bus == &pci_bus_type)
-		pci_unmap_single(to_pci_dev(dev), dma_addr, size, (int)direction);
-#ifdef CONFIG_IBMVIO
-	else if (dev->bus == &vio_bus_type)
-		vio_unmap_single(to_vio_dev(dev), dma_addr, size, direction);
-#endif /* CONFIG_IBMVIO */
+	struct dma_mapping_ops *dma_ops = get_dma_ops(dev);
+
+	if (dma_ops)
+		dma_ops->unmap_single(dev, dma_addr, size, direction);
 	else
 		BUG();
 }
@@ -99,12 +100,11 @@
 		unsigned long offset, size_t size,
 		enum dma_data_direction direction)
 {
-	if (dev->bus == &pci_bus_type)
-		return pci_map_page(to_pci_dev(dev), page, offset, size, (int)direction);
-#ifdef CONFIG_IBMVIO
-	if (dev->bus == &vio_bus_type)
-		return vio_map_page(to_vio_dev(dev), page, offset, size, direction);
-#endif /* CONFIG_IBMVIO */
+	struct dma_mapping_ops *dma_ops = get_dma_ops(dev);
+
+	if (dma_ops)
+		return dma_ops->map_single(dev,
+				(page_address(page) + offset), size, direction);
 	BUG();
 	return (dma_addr_t)0;
 }
@@ -113,12 +113,10 @@
 void dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size,
 		enum dma_data_direction direction)
 {
-	if (dev->bus == &pci_bus_type)
-		pci_unmap_page(to_pci_dev(dev), dma_address, size, (int)direction);
-#ifdef CONFIG_IBMVIO
-	else if (dev->bus == &vio_bus_type)
-		vio_unmap_page(to_vio_dev(dev), dma_address, size, direction);
-#endif /* CONFIG_IBMVIO */
+	struct dma_mapping_ops *dma_ops = get_dma_ops(dev);
+
+	if (dma_ops)
+		dma_ops->unmap_single(dev, dma_address, size, direction);
 	else
 		BUG();
 }
@@ -127,12 +125,10 @@
 int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
 		enum dma_data_direction direction)
 {
-	if (dev->bus == &pci_bus_type)
-		return pci_map_sg(to_pci_dev(dev), sg, nents, (int)direction);
-#ifdef CONFIG_IBMVIO
-	if (dev->bus == &vio_bus_type)
-		return vio_map_sg(to_vio_dev(dev), sg, nents, direction);
-#endif /* CONFIG_IBMVIO */
+	struct dma_mapping_ops *dma_ops = get_dma_ops(dev);
+
+	if (dma_ops)
+		return dma_ops->map_sg(dev, sg, nents, direction);
 	BUG();
 	return 0;
 }
@@ -141,12 +137,10 @@
 void dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries,
 		enum dma_data_direction direction)
 {
-	if (dev->bus == &pci_bus_type)
-		pci_unmap_sg(to_pci_dev(dev), sg, nhwentries, (int)direction);
-#ifdef CONFIG_IBMVIO
-	else if (dev->bus == &vio_bus_type)
-		vio_unmap_sg(to_vio_dev(dev), sg, nhwentries, direction);
-#endif /* CONFIG_IBMVIO */
+	struct dma_mapping_ops *dma_ops = get_dma_ops(dev);
+
+	if (dma_ops)
+		dma_ops->unmap_sg(dev, sg, nhwentries, direction);
 	else
 		BUG();
 }
diff -Nru a/arch/ppc64/kernel/eeh.c b/arch/ppc64/kernel/eeh.c
--- a/arch/ppc64/kernel/eeh.c	2005-03-11 12:51:47 -08:00
+++ b/arch/ppc64/kernel/eeh.c	2005-03-11 12:51:47 -08:00
@@ -824,7 +824,7 @@
 	struct pci_controller *phb;
 	struct eeh_early_enable_info info;
 
-	if (!dn || !eeh_subsystem_enabled)
+	if (!dn)
 		return;
 	phb = dn->phb;
 	if (NULL == phb || 0 == phb->buid) {
diff -Nru a/arch/ppc64/kernel/head.S b/arch/ppc64/kernel/head.S
--- a/arch/ppc64/kernel/head.S	2005-03-11 12:51:46 -08:00
+++ b/arch/ppc64/kernel/head.S	2005-03-11 12:51:46 -08:00
@@ -54,7 +54,6 @@
  * 0x0100 - 0x2fff : pSeries Interrupt prologs
  * 0x3000 - 0x3fff : Interrupt support
  * 0x4000 - 0x4fff : NACA
- * 0x5000 - 0x5fff : SystemCfg
  * 0x6000	   : iSeries and common interrupt prologs
  * 0x9000 - 0x9fff : Initial segment table
  */
@@ -517,16 +516,7 @@
 	.globl naca
 naca:
 	.llong itVpdAreas
-#endif
-
-	. = SYSTEMCFG_PHYS_ADDR
-	.globl __start_systemcfg
-__start_systemcfg:
-	. = (SYSTEMCFG_PHYS_ADDR + PAGE_SIZE)
-	.globl __end_systemcfg
-__end_systemcfg:
 
-#ifdef CONFIG_PPC_ISERIES
 	/*
 	 * The iSeries LPAR map is at this fixed address
 	 * so that the HvReleaseData structure can address
@@ -536,6 +526,8 @@
 	 * VSID generation algorithm.  See include/asm/mmu_context.h.
 	 */
 
+	. = 0x4800
+
 	.llong	2		/* # ESIDs to be mapped by hypervisor	 */
 	.llong	1		/* # memory ranges to be mapped by hypervisor */
 	.llong	STAB0_PAGE	/* Page # of segment table within load area	*/
@@ -1264,10 +1256,6 @@
 	addi	r2,r2,0x4000
 	addi	r2,r2,0x4000
 
-	LOADADDR(r9,systemcfg)
-	SET_REG_TO_CONST(r4, SYSTEMCFG_VIRT_ADDR)
-	std	r4,0(r9)		/* set the systemcfg pointer */
-
 	bl	.iSeries_early_setup
 
 	/* relocation is on at this point */
@@ -1772,7 +1760,7 @@
 	sc				/* HvCall_setASR */
 #else
 	/* set the ASR */
-	li	r3,SYSTEMCFG_PHYS_ADDR	/* r3 = ptr to systemcfg	 */
+	ld	r3,systemcfg@got(r2)	/* r3 = ptr to systemcfg	 */
 	lwz	r3,PLATFORM(r3)		/* r3 = platform flags		 */
 	cmpldi 	r3,PLATFORM_PSERIES_LPAR
 	bne	98f
@@ -1861,12 +1849,6 @@
 	ori	r6,r6,MSR_RI
 	mtmsrd	r6			/* RI on */
 
-	/* setup the systemcfg pointer which is needed by *tab_initialize	*/
-	LOADADDR(r6,systemcfg)
-	sub	r6,r6,r26		/* addr of the variable systemcfg */
-	li	r27,SYSTEMCFG_PHYS_ADDR
-	std	r27,0(r6)	 	/* set the value of systemcfg	*/
-
 #ifdef CONFIG_HMT
 	/* Start up the second thread on cpu 0 */
 	mfspr	r3,PVR
@@ -1941,7 +1923,7 @@
 	/* set the ASR */
 	ld	r3,PACASTABREAL(r13)
 	ori	r4,r3,1			/* turn on valid bit		 */
-	li	r3,SYSTEMCFG_PHYS_ADDR	/* r3 = ptr to systemcfg */
+	ld	r3,systemcfg@got(r2)	/* r3 = ptr to systemcfg */
 	lwz	r3,PLATFORM(r3)		/* r3 = platform flags */
 	cmpldi 	r3,PLATFORM_PSERIES_LPAR
 	bne	98f
@@ -1960,7 +1942,7 @@
 	mtasr	r4			/* set the stab location	*/
 99:
 	/* Set SDR1 (hash table pointer) */
-	li	r3,SYSTEMCFG_PHYS_ADDR	/* r3 = ptr to systemcfg */
+	ld	r3,systemcfg@got(r2)	/* r3 = ptr to systemcfg */
 	lwz	r3,PLATFORM(r3)		/* r3 = platform flags */
 	/* Test if bit 0 is set (LPAR bit) */
 	andi.	r3,r3,0x1
@@ -1997,11 +1979,6 @@
 	 */
 	li	r3,0
 	bl	.do_cpu_ftr_fixups
-
-	/* setup the systemcfg pointer */
-	LOADADDR(r9,systemcfg)
-	SET_REG_TO_CONST(r8, SYSTEMCFG_VIRT_ADDR)
-	std	r8,0(r9)
 
 	LOADADDR(r26, boot_cpuid)
 	lwz	r26,0(r26)
diff -Nru a/arch/ppc64/kernel/i8259.c b/arch/ppc64/kernel/i8259.c
--- a/arch/ppc64/kernel/i8259.c	2005-03-11 12:51:52 -08:00
+++ b/arch/ppc64/kernel/i8259.c	2005-03-11 12:51:52 -08:00
@@ -131,14 +131,11 @@
 }
 
 struct hw_interrupt_type i8259_pic = {
-        " i8259    ",
-        NULL,
-        NULL,
-        i8259_unmask_irq,
-        i8259_mask_irq,
-        i8259_mask_and_ack_irq,
-        i8259_end_irq,
-        NULL
+	.typename = " i8259    ",
+	.enable = i8259_unmask_irq,
+	.disable = i8259_mask_irq,
+	.ack = i8259_mask_and_ack_irq,
+	.end = i8259_end_irq,
 };
 
 void __init i8259_init(int offset)
diff -Nru a/arch/ppc64/kernel/iSeries_pci.c b/arch/ppc64/kernel/iSeries_pci.c
--- a/arch/ppc64/kernel/iSeries_pci.c	2005-03-11 12:51:51 -08:00
+++ b/arch/ppc64/kernel/iSeries_pci.c	2005-03-11 12:51:51 -08:00
@@ -610,6 +610,10 @@
 
 	if (node == NULL)
 		return PCIBIOS_DEVICE_NOT_FOUND;
+	if (offset > 255) {
+		*val = ~0;
+		return PCIBIOS_BAD_REGISTER_NUMBER;
+	}
 
 	fn = hv_cfg_read_func[(size - 1) & 3];
 	HvCall3Ret16(fn, &ret, node->DsaAddr.DsaAddr, offset, 0);
@@ -636,6 +640,8 @@
 
 	if (node == NULL)
 		return PCIBIOS_DEVICE_NOT_FOUND;
+	if (offset > 255)
+		return PCIBIOS_BAD_REGISTER_NUMBER;
 
 	fn = hv_cfg_write_func[(size - 1) & 3];
 	ret = HvCall4(fn, node->DsaAddr.DsaAddr, offset, val, 0);
diff -Nru a/arch/ppc64/kernel/iSeries_setup.c b/arch/ppc64/kernel/iSeries_setup.c
--- a/arch/ppc64/kernel/iSeries_setup.c	2005-03-11 12:51:47 -08:00
+++ b/arch/ppc64/kernel/iSeries_setup.c	2005-03-11 12:51:47 -08:00
@@ -267,7 +267,7 @@
 	unsigned long i;
 	unsigned long mem_blocks = 0;
 
-	if (cur_cpu_spec->cpu_features & CPU_FTR_SLB)
+	if (cpu_has_feature(CPU_FTR_SLB))
 		mem_blocks = iSeries_process_Regatta_mainstore_vpd(mb_array,
 				max_entries);
 	else
diff -Nru a/arch/ppc64/kernel/idle.c b/arch/ppc64/kernel/idle.c
--- a/arch/ppc64/kernel/idle.c	2005-03-11 12:51:50 -08:00
+++ b/arch/ppc64/kernel/idle.c	2005-03-11 12:51:50 -08:00
@@ -293,6 +293,10 @@
 			power4_idle();
 		if (need_resched())
 			schedule();
+
+		if (cpu_is_offline(_smp_processor_id()) &&
+		    system_state == SYSTEM_RUNNING)
+			cpu_die();
 	}
 	return 0;
 }
diff -Nru a/arch/ppc64/kernel/ioctl32.c b/arch/ppc64/kernel/ioctl32.c
--- a/arch/ppc64/kernel/ioctl32.c	2005-03-11 12:51:52 -08:00
+++ b/arch/ppc64/kernel/ioctl32.c	2005-03-11 12:51:52 -08:00
@@ -39,7 +39,6 @@
 #include <linux/compat_ioctl.h>
 #define DECLARES
 #include "compat_ioctl.c"
-COMPATIBLE_IOCTL(TCSBRKP)
 COMPATIBLE_IOCTL(TIOCSTART)
 COMPATIBLE_IOCTL(TIOCSTOP)
 COMPATIBLE_IOCTL(TIOCSLTC)
diff -Nru a/arch/ppc64/kernel/iommu.c b/arch/ppc64/kernel/iommu.c
--- a/arch/ppc64/kernel/iommu.c	2005-03-11 12:51:52 -08:00
+++ b/arch/ppc64/kernel/iommu.c	2005-03-11 12:51:52 -08:00
@@ -513,8 +513,8 @@
  * Returns the virtual address of the buffer and sets dma_handle
  * to the dma address (mapping) of the first page.
  */
-void *iommu_alloc_consistent(struct iommu_table *tbl, size_t size,
-		dma_addr_t *dma_handle)
+void *iommu_alloc_coherent(struct iommu_table *tbl, size_t size,
+		dma_addr_t *dma_handle, int flag)
 {
 	void *ret = NULL;
 	dma_addr_t mapping;
@@ -538,7 +538,7 @@
 		return NULL;
 
 	/* Alloc enough pages (and possibly more) */
-	ret = (void *)__get_free_pages(GFP_ATOMIC, order);
+	ret = (void *)__get_free_pages(flag, order);
 	if (!ret)
 		return NULL;
 	memset(ret, 0, size);
@@ -553,7 +553,7 @@
 	return ret;
 }
 
-void iommu_free_consistent(struct iommu_table *tbl, size_t size,
+void iommu_free_coherent(struct iommu_table *tbl, size_t size,
 			 void *vaddr, dma_addr_t dma_handle)
 {
 	unsigned int npages;
diff -Nru a/arch/ppc64/kernel/irq.c b/arch/ppc64/kernel/irq.c
--- a/arch/ppc64/kernel/irq.c	2005-03-11 12:51:42 -08:00
+++ b/arch/ppc64/kernel/irq.c	2005-03-11 12:51:42 -08:00
@@ -61,6 +61,7 @@
 #endif
 
 extern irq_desc_t irq_desc[NR_IRQS];
+EXPORT_SYMBOL(irq_desc);
 
 int distribute_irqs = 1;
 int __irq_offset_value;
@@ -114,6 +115,35 @@
 		seq_printf(p, "BAD: %10u\n", ppc_spurious_interrupts);
 	return 0;
 }
+
+#ifdef CONFIG_HOTPLUG_CPU
+void fixup_irqs(cpumask_t map)
+{
+	unsigned int irq;
+	static int warned;
+
+	for_each_irq(irq) {
+		cpumask_t mask;
+
+		if (irq_desc[irq].status & IRQ_PER_CPU)
+			continue;
+
+		cpus_and(mask, irq_affinity[irq], map);
+		if (any_online_cpu(mask) == NR_CPUS) {
+			printk("Breaking affinity for irq %i\n", irq);
+			mask = map;
+		}
+		if (irq_desc[irq].handler->set_affinity)
+			irq_desc[irq].handler->set_affinity(irq, mask);
+		else if (irq_desc[irq].action && !(warned++))
+			printk("Cannot set affinity for irq %i\n", irq);
+	}
+
+	local_irq_enable();
+	mdelay(1);
+	local_irq_disable();
+}
+#endif
 
 extern int noirqdebug;
 
diff -Nru a/arch/ppc64/kernel/kprobes.c b/arch/ppc64/kernel/kprobes.c
--- a/arch/ppc64/kernel/kprobes.c	2005-03-11 12:51:51 -08:00
+++ b/arch/ppc64/kernel/kprobes.c	2005-03-11 12:51:51 -08:00
@@ -105,9 +105,17 @@
 	p = get_kprobe(addr);
 	if (!p) {
 		unlock_kprobes();
-#if 0
 		if (*addr != BREAKPOINT_INSTRUCTION) {
 			/*
+			 * PowerPC has multiple variants of the "trap"
+			 * instruction. If the current instruction is a
+			 * trap variant, it could belong to someone else
+			 */
+			kprobe_opcode_t cur_insn = *addr;
+			if (IS_TW(cur_insn) || IS_TD(cur_insn) ||
+					IS_TWI(cur_insn) || IS_TDI(cur_insn))
+		       		goto no_kprobe;
+			/*
 			 * The breakpoint instruction was removed right
 			 * after we hit it.  Another cpu has removed
 			 * either a probepoint or a debugger breakpoint
@@ -116,7 +124,6 @@
 			 */
 			ret = 1;
 		}
-#endif
 		/* Not one of ours: let kernel handle it */
 		goto no_kprobe;
 	}
diff -Nru a/arch/ppc64/kernel/lparcfg.c b/arch/ppc64/kernel/lparcfg.c
--- a/arch/ppc64/kernel/lparcfg.c	2005-03-11 12:51:41 -08:00
+++ b/arch/ppc64/kernel/lparcfg.c	2005-03-11 12:51:41 -08:00
@@ -33,8 +33,9 @@
 #include <asm/cputable.h>
 #include <asm/rtas.h>
 #include <asm/system.h>
+#include <asm/time.h>
 
-#define MODULE_VERS "1.5"
+#define MODULE_VERS "1.6"
 #define MODULE_NAME "lparcfg"
 
 /* #define LPARCFG_DEBUG */
@@ -214,13 +215,20 @@
 }
 
 static unsigned long get_purr(void);
-/* ToDo:  get sum of purr across all processors.  The purr collection code
- * is coming, but at this time is still problematic, so for now this
- * function will return 0.
- */
+
+/* Track sum of all purrs across all processors. This is used to further */
+/* calculate usage values by different applications                       */
+
 static unsigned long get_purr(void)
 {
 	unsigned long sum_purr = 0;
+	int cpu;
+	struct cpu_usage *cu;
+
+	for_each_cpu(cpu) {
+		cu = &per_cpu(cpu_usage_array, cpu);
+		sum_purr += cu->current_tb;
+	}
 	return sum_purr;
 }
 
diff -Nru a/arch/ppc64/kernel/misc.S b/arch/ppc64/kernel/misc.S
--- a/arch/ppc64/kernel/misc.S	2005-03-11 12:51:51 -08:00
+++ b/arch/ppc64/kernel/misc.S	2005-03-11 12:51:51 -08:00
@@ -939,6 +939,7 @@
 	.llong .sys32_add_key
 	.llong .sys32_request_key
 	.llong .compat_sys_keyctl
+	.llong .compat_sys_waitid
 
 	.balign 8
 _GLOBAL(sys_call_table)
@@ -1214,3 +1215,4 @@
 	.llong .sys_add_key
 	.llong .sys_request_key		/* 270 */
 	.llong .sys_keyctl
+	.llong .sys_waitid
diff -Nru a/arch/ppc64/kernel/pSeries_lpar.c b/arch/ppc64/kernel/pSeries_lpar.c
--- a/arch/ppc64/kernel/pSeries_lpar.c	2005-03-11 12:51:52 -08:00
+++ b/arch/ppc64/kernel/pSeries_lpar.c	2005-03-11 12:51:52 -08:00
@@ -505,7 +505,7 @@
 	int i;
 	unsigned long flags = 0;
 	struct ppc64_tlb_batch *batch = &__get_cpu_var(ppc64_tlb_batch);
-	int lock_tlbie = !(cur_cpu_spec->cpu_features & CPU_FTR_LOCKLESS_TLBIE);
+	int lock_tlbie = !cpu_has_feature(CPU_FTR_LOCKLESS_TLBIE);
 
 	if (lock_tlbie)
 		spin_lock_irqsave(&pSeries_lpar_tlbie_lock, flags);
diff -Nru a/arch/ppc64/kernel/pSeries_nvram.c b/arch/ppc64/kernel/pSeries_nvram.c
--- a/arch/ppc64/kernel/pSeries_nvram.c	2005-03-11 12:51:50 -08:00
+++ b/arch/ppc64/kernel/pSeries_nvram.c	2005-03-11 12:51:50 -08:00
@@ -11,14 +11,9 @@
  * This perhaps should live in drivers/char
  */
 
-#include <linux/module.h>
 
 #include <linux/types.h>
 #include <linux/errno.h>
-#include <linux/fs.h>
-#include <linux/miscdevice.h>
-#include <linux/fcntl.h>
-#include <linux/nvram.h>
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
diff -Nru a/arch/ppc64/kernel/pSeries_pci.c b/arch/ppc64/kernel/pSeries_pci.c
--- a/arch/ppc64/kernel/pSeries_pci.c	2005-03-11 12:51:52 -08:00
+++ b/arch/ppc64/kernel/pSeries_pci.c	2005-03-11 12:51:52 -08:00
@@ -52,6 +52,16 @@
 
 extern struct mpic *pSeries_mpic;
 
+static int config_access_valid(struct device_node *dn, int where)
+{
+	if (where < 256)
+		return 1;
+	if (where < 4096 && dn->pci_ext_config_space)
+		return 1;
+
+	return 0;
+}
+
 static int rtas_read_config(struct device_node *dn, int where, int size, u32 *val)
 {
 	int returnval = -1;
@@ -60,10 +70,11 @@
 
 	if (!dn)
 		return PCIBIOS_DEVICE_NOT_FOUND;
-	if (where & (size - 1))
+	if (!config_access_valid(dn, where))
 		return PCIBIOS_BAD_REGISTER_NUMBER;
 
-	addr = (dn->busno << 16) | (dn->devfn << 8) | where;
+	addr = ((where & 0xf00) << 20) | (dn->busno << 16) |
+		(dn->devfn << 8) | (where & 0xff);
 	buid = dn->phb->buid;
 	if (buid) {
 		ret = rtas_call(ibm_read_pci_config, 4, 2, &returnval,
@@ -108,10 +119,11 @@
 
 	if (!dn)
 		return PCIBIOS_DEVICE_NOT_FOUND;
-	if (where & (size - 1))
+	if (!config_access_valid(dn, where))
 		return PCIBIOS_BAD_REGISTER_NUMBER;
 
-	addr = (dn->busno << 16) | (dn->devfn << 8) | where;
+	addr = ((where & 0xf00) << 20) | (dn->busno << 16) |
+		(dn->devfn << 8) | (where & 0xff);
 	buid = dn->phb->buid;
 	if (buid) {
 		ret = rtas_call(ibm_write_pci_config, 5, 1, NULL, addr, buid >> 32, buid & 0xffffffff, size, (ulong) val);
@@ -412,16 +424,18 @@
 	unsigned int root_size_cells = 0;
 	struct pci_controller *phb;
 	struct pci_bus *bus;
+	int primary;
 
 	root_size_cells = prom_n_size_cells(root);
 
+	primary = list_empty(&hose_list);
 	phb = alloc_phb_dynamic(dn, root_size_cells);
 	if (!phb)
 		return NULL;
 
 	pci_process_bridge_OF_ranges(phb, dn);
 
-	pci_setup_phb_io_dynamic(phb);
+	pci_setup_phb_io_dynamic(phb, primary);
 	of_node_put(root);
 
 	pci_devs_phb_init_dynamic(phb);
diff -Nru a/arch/ppc64/kernel/pSeries_setup.c b/arch/ppc64/kernel/pSeries_setup.c
--- a/arch/ppc64/kernel/pSeries_setup.c	2005-03-11 12:51:41 -08:00
+++ b/arch/ppc64/kernel/pSeries_setup.c	2005-03-11 12:51:41 -08:00
@@ -320,9 +320,10 @@
 	}
 }
 
-static void pSeries_cpu_die(void)
+static void pSeries_mach_cpu_die(void)
 {
 	local_irq_disable();
+	idle_task_exit();
 	/* Some hardware requires clearing the CPPR, while other hardware does not
 	 * it is safe either way
 	 */
@@ -599,7 +600,7 @@
 	.power_off		= rtas_power_off,
 	.halt			= rtas_halt,
 	.panic			= rtas_os_term,
-	.cpu_die		= pSeries_cpu_die,
+	.cpu_die		= pSeries_mach_cpu_die,
 	.get_boot_time		= pSeries_get_boot_time,
 	.get_rtc_time		= pSeries_get_rtc_time,
 	.set_rtc_time		= pSeries_set_rtc_time,
diff -Nru a/arch/ppc64/kernel/pSeries_smp.c b/arch/ppc64/kernel/pSeries_smp.c
--- a/arch/ppc64/kernel/pSeries_smp.c	2005-03-11 12:51:46 -08:00
+++ b/arch/ppc64/kernel/pSeries_smp.c	2005-03-11 12:51:46 -08:00
@@ -151,7 +151,7 @@
 		if (index) {
 			int state;
 			int rc = rtas_get_sensor(9003, *index, &state);
-			if (rc != 0 || state != 1)
+			if (rc < 0 || state != 1)
 				continue;
 		}
 
diff -Nru a/arch/ppc64/kernel/pacaData.c b/arch/ppc64/kernel/pacaData.c
--- a/arch/ppc64/kernel/pacaData.c	2005-03-11 12:51:50 -08:00
+++ b/arch/ppc64/kernel/pacaData.c	2005-03-11 12:51:50 -08:00
@@ -20,9 +20,14 @@
 #include <asm/iSeries/ItLpQueue.h>
 #include <asm/paca.h>
 
-struct systemcfg *systemcfg;
+static union {
+	struct systemcfg	data;
+	u8			page[PAGE_SIZE];
+} systemcfg_store __page_aligned;
+struct systemcfg *systemcfg = &systemcfg_store.data;
 EXPORT_SYMBOL(systemcfg);
 
+
 /* This symbol is provided by the linker - let it fill in the paca
  * field correctly */
 extern unsigned long __toc_start;
@@ -216,3 +221,4 @@
 #endif
 #endif
 };
+EXPORT_SYMBOL(paca);
diff -Nru a/arch/ppc64/kernel/pci.c b/arch/ppc64/kernel/pci.c
--- a/arch/ppc64/kernel/pci.c	2005-03-11 12:51:51 -08:00
+++ b/arch/ppc64/kernel/pci.c	2005-03-11 12:51:51 -08:00
@@ -63,13 +63,15 @@
  * page is mapped and isa_io_limit prevents access to it.
  */
 unsigned long isa_io_base;	/* NULL if no ISA bus */
+EXPORT_SYMBOL(isa_io_base);
 unsigned long pci_io_base;
+EXPORT_SYMBOL(pci_io_base);
 
 void iSeries_pcibios_init(void);
 
 LIST_HEAD(hose_list);
 
-struct pci_dma_ops pci_dma_ops;
+struct dma_mapping_ops pci_dma_ops;
 EXPORT_SYMBOL(pci_dma_ops);
 
 int global_phb_number;		/* Global phb counter */
@@ -300,19 +302,15 @@
 
 EXPORT_SYMBOL(pci_domain_nr);
 
-/* Set the name of the bus as it appears in /proc/bus/pci */
-int pci_name_bus(char *name, struct pci_bus *bus)
+/* Decide whether to display the domain number in /proc */
+int pci_proc_domain(struct pci_bus *bus)
 {
-#ifndef CONFIG_PPC_ISERIES
+#ifdef CONFIG_PPC_ISERIES
+	return 0;
+#else
 	struct pci_controller *hose = pci_bus_to_host(bus);
-
-	if (hose->buid)
-		sprintf(name, "%04x:%02x", pci_domain_nr(bus), bus->number);
-	else
+	return hose->buid;
 #endif
-		sprintf(name, "%02x", bus->number);
-
-	return 0;
 }
 
 /*
@@ -621,7 +619,8 @@
 	res->end += io_virt_offset;
 }
 
-void __devinit pci_setup_phb_io_dynamic(struct pci_controller *hose)
+void __devinit pci_setup_phb_io_dynamic(struct pci_controller *hose,
+					int primary)
 {
 	unsigned long size = hose->pci_io_size;
 	unsigned long io_virt_offset;
@@ -632,6 +631,9 @@
 	DBG("phb%d io_base_phys 0x%lx io_base_virt 0x%lx\n",
 		hose->global_number, hose->io_base_phys,
 		(unsigned long) hose->io_base_virt);
+
+	if (primary)
+		pci_io_base = (unsigned long)hose->io_base_virt;
 
 	io_virt_offset = (unsigned long)hose->io_base_virt - pci_io_base;
 	res = &hose->io_resource;
diff -Nru a/arch/ppc64/kernel/pci.h b/arch/ppc64/kernel/pci.h
--- a/arch/ppc64/kernel/pci.h	2005-03-11 12:51:40 -08:00
+++ b/arch/ppc64/kernel/pci.h	2005-03-11 12:51:40 -08:00
@@ -16,8 +16,7 @@
 
 extern void pci_setup_pci_controller(struct pci_controller *hose);
 extern void pci_setup_phb_io(struct pci_controller *hose, int primary);
-
-extern void pci_setup_phb_io_dynamic(struct pci_controller *hose);
+extern void pci_setup_phb_io_dynamic(struct pci_controller *hose, int primary);
 
 
 extern struct list_head hose_list;
diff -Nru a/arch/ppc64/kernel/pci_direct_iommu.c b/arch/ppc64/kernel/pci_direct_iommu.c
--- a/arch/ppc64/kernel/pci_direct_iommu.c	2005-03-11 12:51:40 -08:00
+++ b/arch/ppc64/kernel/pci_direct_iommu.c	2005-03-11 12:51:40 -08:00
@@ -30,12 +30,12 @@
 
 #include "pci.h"
 
-static void *pci_direct_alloc_consistent(struct pci_dev *hwdev, size_t size,
-				   dma_addr_t *dma_handle)
+static void *pci_direct_alloc_coherent(struct device *hwdev, size_t size,
+				   dma_addr_t *dma_handle, int flag)
 {
 	void *ret;
 
-	ret = (void *)__get_free_pages(GFP_ATOMIC, get_order(size));
+	ret = (void *)__get_free_pages(flag, get_order(size));
 	if (ret != NULL) {
 		memset(ret, 0, size);
 		*dma_handle = virt_to_abs(ret);
@@ -43,24 +43,24 @@
 	return ret;
 }
 
-static void pci_direct_free_consistent(struct pci_dev *hwdev, size_t size,
+static void pci_direct_free_coherent(struct device *hwdev, size_t size,
 				 void *vaddr, dma_addr_t dma_handle)
 {
 	free_pages((unsigned long)vaddr, get_order(size));
 }
 
-static dma_addr_t pci_direct_map_single(struct pci_dev *hwdev, void *ptr,
+static dma_addr_t pci_direct_map_single(struct device *hwdev, void *ptr,
 		size_t size, enum dma_data_direction direction)
 {
 	return virt_to_abs(ptr);
 }
 
-static void pci_direct_unmap_single(struct pci_dev *hwdev, dma_addr_t dma_addr,
+static void pci_direct_unmap_single(struct device *hwdev, dma_addr_t dma_addr,
 		size_t size, enum dma_data_direction direction)
 {
 }
 
-static int pci_direct_map_sg(struct pci_dev *hwdev, struct scatterlist *sg,
+static int pci_direct_map_sg(struct device *hwdev, struct scatterlist *sg,
 		int nents, enum dma_data_direction direction)
 {
 	int i;
@@ -73,17 +73,23 @@
 	return nents;
 }
 
-static void pci_direct_unmap_sg(struct pci_dev *hwdev, struct scatterlist *sg,
+static void pci_direct_unmap_sg(struct device *hwdev, struct scatterlist *sg,
 		int nents, enum dma_data_direction direction)
 {
 }
 
+static int pci_direct_dma_supported(struct device *dev, u64 mask)
+{
+	return mask < 0x100000000ull;
+}
+
 void __init pci_direct_iommu_init(void)
 {
-	pci_dma_ops.pci_alloc_consistent = pci_direct_alloc_consistent;
-	pci_dma_ops.pci_free_consistent = pci_direct_free_consistent;
-	pci_dma_ops.pci_map_single = pci_direct_map_single;
-	pci_dma_ops.pci_unmap_single = pci_direct_unmap_single;
-	pci_dma_ops.pci_map_sg = pci_direct_map_sg;
-	pci_dma_ops.pci_unmap_sg = pci_direct_unmap_sg;
+	pci_dma_ops.alloc_coherent = pci_direct_alloc_coherent;
+	pci_dma_ops.free_coherent = pci_direct_free_coherent;
+	pci_dma_ops.map_single = pci_direct_map_single;
+	pci_dma_ops.unmap_single = pci_direct_unmap_single;
+	pci_dma_ops.map_sg = pci_direct_map_sg;
+	pci_dma_ops.unmap_sg = pci_direct_unmap_sg;
+	pci_dma_ops.dma_supported = pci_direct_dma_supported;
 }
diff -Nru a/arch/ppc64/kernel/pci_dn.c b/arch/ppc64/kernel/pci_dn.c
--- a/arch/ppc64/kernel/pci_dn.c	2005-03-11 12:51:52 -08:00
+++ b/arch/ppc64/kernel/pci_dn.c	2005-03-11 12:51:52 -08:00
@@ -37,6 +37,7 @@
 static void * __devinit update_dn_pci_info(struct device_node *dn, void *data)
 {
 	struct pci_controller *phb = data;
+	int *type = (int *)get_property(dn, "ibm,pci-config-space-type", NULL);
 	u32 *regs;
 
 	dn->phb = phb;
@@ -46,6 +47,8 @@
 		dn->busno = (regs[0] >> 16) & 0xff;
 		dn->devfn = (regs[0] >> 8) & 0xff;
 	}
+
+	dn->pci_ext_config_space = (type && *type == 1);
 	return NULL;
 }
 
diff -Nru a/arch/ppc64/kernel/pci_iommu.c b/arch/ppc64/kernel/pci_iommu.c
--- a/arch/ppc64/kernel/pci_iommu.c	2005-03-11 12:51:47 -08:00
+++ b/arch/ppc64/kernel/pci_iommu.c	2005-03-11 12:51:47 -08:00
@@ -50,19 +50,23 @@
  */
 #define PCI_GET_DN(dev) ((struct device_node *)((dev)->sysdata))
 
-static inline struct iommu_table *devnode_table(struct pci_dev *dev)
+static inline struct iommu_table *devnode_table(struct device *dev)
 {
-	if (!dev)
-		dev = ppc64_isabridge_dev;
-	if (!dev)
-		return NULL;
+	struct pci_dev *pdev;
+
+	if (!dev) {
+		pdev = ppc64_isabridge_dev;
+		if (!pdev)
+			return NULL;
+	} else
+		pdev = to_pci_dev(dev);
 
 #ifdef CONFIG_PPC_ISERIES
-	return ISERIES_DEVNODE(dev)->iommu_table;
+	return ISERIES_DEVNODE(pdev)->iommu_table;
 #endif /* CONFIG_PPC_ISERIES */
 
 #ifdef CONFIG_PPC_MULTIPLATFORM
-	return PCI_GET_DN(dev)->iommu_table;
+	return PCI_GET_DN(pdev)->iommu_table;
 #endif /* CONFIG_PPC_MULTIPLATFORM */
 }
 
@@ -71,16 +75,17 @@
  * Returns the virtual address of the buffer and sets dma_handle
  * to the dma address (mapping) of the first page.
  */
-static void *pci_iommu_alloc_consistent(struct pci_dev *hwdev, size_t size,
-			   dma_addr_t *dma_handle)
+static void *pci_iommu_alloc_coherent(struct device *hwdev, size_t size,
+			   dma_addr_t *dma_handle, int flag)
 {
-	return iommu_alloc_consistent(devnode_table(hwdev), size, dma_handle);
+	return iommu_alloc_coherent(devnode_table(hwdev), size, dma_handle,
+			flag);
 }
 
-static void pci_iommu_free_consistent(struct pci_dev *hwdev, size_t size,
+static void pci_iommu_free_coherent(struct device *hwdev, size_t size,
 			 void *vaddr, dma_addr_t dma_handle)
 {
-	iommu_free_consistent(devnode_table(hwdev), size, vaddr, dma_handle);
+	iommu_free_coherent(devnode_table(hwdev), size, vaddr, dma_handle);
 }
 
 /* Creates TCEs for a user provided buffer.  The user buffer must be 
@@ -89,46 +94,46 @@
  * need not be page aligned, the dma_addr_t returned will point to the same
  * byte within the page as vaddr.
  */
-static dma_addr_t pci_iommu_map_single(struct pci_dev *hwdev, void *vaddr,
+static dma_addr_t pci_iommu_map_single(struct device *hwdev, void *vaddr,
 		size_t size, enum dma_data_direction direction)
 {
 	return iommu_map_single(devnode_table(hwdev), vaddr, size, direction);
 }
 
 
-static void pci_iommu_unmap_single(struct pci_dev *hwdev, dma_addr_t dma_handle,
+static void pci_iommu_unmap_single(struct device *hwdev, dma_addr_t dma_handle,
 		size_t size, enum dma_data_direction direction)
 {
 	iommu_unmap_single(devnode_table(hwdev), dma_handle, size, direction);
 }
 
 
-static int pci_iommu_map_sg(struct pci_dev *pdev, struct scatterlist *sglist,
+static int pci_iommu_map_sg(struct device *pdev, struct scatterlist *sglist,
 		int nelems, enum dma_data_direction direction)
 {
-	return iommu_map_sg(&pdev->dev, devnode_table(pdev), sglist,
+	return iommu_map_sg(pdev, devnode_table(pdev), sglist,
 			nelems, direction);
 }
 
-static void pci_iommu_unmap_sg(struct pci_dev *pdev, struct scatterlist *sglist,
+static void pci_iommu_unmap_sg(struct device *pdev, struct scatterlist *sglist,
 		int nelems, enum dma_data_direction direction)
 {
 	iommu_unmap_sg(devnode_table(pdev), sglist, nelems, direction);
 }
 
 /* We support DMA to/from any memory page via the iommu */
-static int pci_iommu_dma_supported(struct pci_dev *pdev, u64 mask)
+static int pci_iommu_dma_supported(struct device *dev, u64 mask)
 {
 	return 1;
 }
 
 void pci_iommu_init(void)
 {
-	pci_dma_ops.pci_alloc_consistent = pci_iommu_alloc_consistent;
-	pci_dma_ops.pci_free_consistent = pci_iommu_free_consistent;
-	pci_dma_ops.pci_map_single = pci_iommu_map_single;
-	pci_dma_ops.pci_unmap_single = pci_iommu_unmap_single;
-	pci_dma_ops.pci_map_sg = pci_iommu_map_sg;
-	pci_dma_ops.pci_unmap_sg = pci_iommu_unmap_sg;
-	pci_dma_ops.pci_dma_supported = pci_iommu_dma_supported;
+	pci_dma_ops.alloc_coherent = pci_iommu_alloc_coherent;
+	pci_dma_ops.free_coherent = pci_iommu_free_coherent;
+	pci_dma_ops.map_single = pci_iommu_map_single;
+	pci_dma_ops.unmap_single = pci_iommu_unmap_single;
+	pci_dma_ops.map_sg = pci_iommu_map_sg;
+	pci_dma_ops.unmap_sg = pci_iommu_unmap_sg;
+	pci_dma_ops.dma_supported = pci_iommu_dma_supported;
 }
diff -Nru a/arch/ppc64/kernel/pmac_setup.c b/arch/ppc64/kernel/pmac_setup.c
--- a/arch/ppc64/kernel/pmac_setup.c	2005-03-11 12:51:41 -08:00
+++ b/arch/ppc64/kernel/pmac_setup.c	2005-03-11 12:51:41 -08:00
@@ -244,7 +244,6 @@
 {
 	btext_drawchar(c);
 }
-#endif /* CONFIG_BOOTX_TEXT */
 
 static void __init init_boot_display(void)
 {
@@ -280,6 +279,7 @@
 			return;
 	}
 }
+#endif /* CONFIG_BOOTX_TEXT */
 
 /* 
  * Early initialization.
@@ -439,6 +439,9 @@
 }
 
 struct machdep_calls __initdata pmac_md = {
+#ifdef CONFIG_HOTPLUG_CPU
+	.cpu_die		= generic_mach_cpu_die,
+#endif
 	.probe			= pmac_probe,
 	.setup_arch		= pmac_setup_arch,
 	.init_early		= pmac_init_early,
diff -Nru a/arch/ppc64/kernel/pmac_smp.c b/arch/ppc64/kernel/pmac_smp.c
--- a/arch/ppc64/kernel/pmac_smp.c	2005-03-11 12:51:41 -08:00
+++ b/arch/ppc64/kernel/pmac_smp.c	2005-03-11 12:51:41 -08:00
@@ -308,4 +308,9 @@
 void __init pmac_setup_smp(void)
 {
 	smp_ops = &core99_smp_ops;
+#ifdef CONFIG_HOTPLUG_CPU
+	smp_ops->cpu_enable = generic_cpu_enable;
+	smp_ops->cpu_disable = generic_cpu_disable;
+	smp_ops->cpu_die = generic_cpu_die;
+#endif
 }
diff -Nru a/arch/ppc64/kernel/pmc.c b/arch/ppc64/kernel/pmc.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/ppc64/kernel/pmc.c	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,64 @@
+/*
+ *  linux/arch/ppc64/kernel/pmc.c
+ *
+ *  Copyright (C) 2004 David Gibson, IBM Corporation.
+ *
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU General Public License
+ *  as published by the Free Software Foundation; either version
+ *  2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/config.h>
+#include <linux/errno.h>
+#include <linux/spinlock.h>
+
+#include <asm/processor.h>
+#include <asm/pmc.h>
+
+/* Ensure exceptions are disabled */
+static void dummy_perf(struct pt_regs *regs)
+{
+	unsigned int mmcr0 = mfspr(SPRN_MMCR0);
+
+	mmcr0 &= ~(MMCR0_PMXE|MMCR0_PMAO);
+	mtspr(SPRN_MMCR0, mmcr0);
+}
+
+static spinlock_t pmc_owner_lock = SPIN_LOCK_UNLOCKED;
+static void *pmc_owner_caller; /* mostly for debugging */
+perf_irq_t perf_irq = dummy_perf;
+
+int reserve_pmc_hardware(perf_irq_t new_perf_irq)
+{
+	int err = 0;
+
+	spin_lock(&pmc_owner_lock);
+
+	if (pmc_owner_caller) {
+		printk(KERN_WARNING "reserve_pmc_hardware: "
+		       "PMC hardware busy (reserved by caller %p)\n",
+		       pmc_owner_caller);
+		err = -EBUSY;
+		goto out;
+	}
+
+	pmc_owner_caller = __builtin_return_address(0);
+	perf_irq = new_perf_irq ? : dummy_perf;
+
+ out:
+	spin_unlock(&pmc_owner_lock);
+	return err;
+}
+
+void release_pmc_hardware(void)
+{
+	spin_lock(&pmc_owner_lock);
+
+	WARN_ON(! pmc_owner_caller);
+
+	pmc_owner_caller = NULL;
+	perf_irq = dummy_perf;
+
+	spin_unlock(&pmc_owner_lock);
+}
diff -Nru a/arch/ppc64/kernel/ppc_ksyms.c b/arch/ppc64/kernel/ppc_ksyms.c
--- a/arch/ppc64/kernel/ppc_ksyms.c	2005-03-11 12:51:41 -08:00
+++ b/arch/ppc64/kernel/ppc_ksyms.c	2005-03-11 12:51:41 -08:00
@@ -8,49 +8,18 @@
  */
 #include <linux/config.h>
 #include <linux/module.h>
-#include <linux/threads.h>
-#include <linux/smp.h>
-#include <linux/elfcore.h>
-#include <linux/sched.h>
 #include <linux/string.h>
-#include <linux/interrupt.h>
-#include <linux/spinlock.h>
 #include <linux/console.h>
-#include <linux/irq.h>
-#include <linux/pci.h>
-#include <linux/delay.h>
-#include <linux/smp_lock.h>
-#include <linux/syscalls.h>
-#include <linux/bitops.h>
+#include <net/checksum.h>
 
-#include <asm/page.h>
-#include <asm/semaphore.h>
 #include <asm/processor.h>
 #include <asm/uaccess.h>
 #include <asm/io.h>
-#include <asm/atomic.h>
-#include <asm/checksum.h>
-#include <asm/pgtable.h>
-#include <asm/prom.h>
 #include <asm/system.h>
-#include <asm/pci-bridge.h>
-#include <asm/irq.h>
-#include <asm/dma.h>
-#include <asm/machdep.h>
 #include <asm/hw_irq.h>
 #include <asm/abs_addr.h>
 #include <asm/cacheflush.h>
-#ifdef CONFIG_PPC_ISERIES
 #include <asm/iSeries/HvCallSc.h>
-#include <asm/iSeries/LparData.h>
-#endif
-
-extern int do_signal(sigset_t *, struct pt_regs *);
-
-EXPORT_SYMBOL(do_signal);
-
-EXPORT_SYMBOL(isa_io_base);
-EXPORT_SYMBOL(pci_io_base);
 
 EXPORT_SYMBOL(strcpy);
 EXPORT_SYMBOL(strncpy);
@@ -65,10 +34,6 @@
 EXPORT_SYMBOL(strcmp);
 EXPORT_SYMBOL(strncmp);
 
-EXPORT_SYMBOL(__down_interruptible);
-EXPORT_SYMBOL(__up);
-EXPORT_SYMBOL(__down);
-
 EXPORT_SYMBOL(csum_partial);
 EXPORT_SYMBOL(csum_partial_copy_generic);
 EXPORT_SYMBOL(ip_fast_csum);
@@ -79,11 +44,6 @@
 EXPORT_SYMBOL(__strncpy_from_user);
 EXPORT_SYMBOL(__strnlen_user);
 
-EXPORT_SYMBOL(clear_user_page);
-
-#ifdef CONFIG_MSCHUNKS
-EXPORT_SYMBOL(msChunks);
-#endif
 EXPORT_SYMBOL(reloc_offset);
 
 #ifdef CONFIG_PPC_ISERIES
@@ -107,11 +67,7 @@
 EXPORT_SYMBOL(_outsw_ns);
 EXPORT_SYMBOL(_insl_ns);
 EXPORT_SYMBOL(_outsl_ns);
-EXPORT_SYMBOL(ioremap);
-EXPORT_SYMBOL(__ioremap);
-EXPORT_SYMBOL(iounmap);
 
-EXPORT_SYMBOL(start_thread);
 EXPORT_SYMBOL(kernel_thread);
 
 EXPORT_SYMBOL(giveup_fpu);
@@ -119,8 +75,7 @@
 EXPORT_SYMBOL(giveup_altivec);
 #endif
 EXPORT_SYMBOL(flush_icache_range);
-EXPORT_SYMBOL(flush_icache_user_range);
-EXPORT_SYMBOL(flush_dcache_page);
+
 #ifdef CONFIG_SMP
 #ifdef CONFIG_PPC_ISERIES
 EXPORT_SYMBOL(local_get_flags);
@@ -129,19 +84,6 @@
 #endif
 #endif
 
-EXPORT_SYMBOL(ppc_md);
-
-#ifdef CONFIG_PPC_MULTIPLATFORM
-EXPORT_SYMBOL(find_devices);
-EXPORT_SYMBOL(find_type_devices);
-EXPORT_SYMBOL(find_compatible_devices);
-EXPORT_SYMBOL(find_path_device);
-EXPORT_SYMBOL(device_is_compatible);
-EXPORT_SYMBOL(machine_is_compatible);
-EXPORT_SYMBOL(find_all_nodes);
-EXPORT_SYMBOL(get_property);
-#endif
-
 EXPORT_SYMBOL(memcpy);
 EXPORT_SYMBOL(memset);
 EXPORT_SYMBOL(memmove);
@@ -150,10 +92,4 @@
 EXPORT_SYMBOL(memchr);
 
 EXPORT_SYMBOL(timer_interrupt);
-EXPORT_SYMBOL(irq_desc);
-EXPORT_SYMBOL(get_wchan);
 EXPORT_SYMBOL(console_drivers);
-
-EXPORT_SYMBOL(tb_ticks_per_usec);
-EXPORT_SYMBOL(paca);
-EXPORT_SYMBOL(cur_cpu_spec);
diff -Nru a/arch/ppc64/kernel/proc_ppc64.c b/arch/ppc64/kernel/proc_ppc64.c
--- a/arch/ppc64/kernel/proc_ppc64.c	2005-03-11 12:51:47 -08:00
+++ b/arch/ppc64/kernel/proc_ppc64.c	2005-03-11 12:51:47 -08:00
@@ -89,7 +89,7 @@
 		return 1;
 	pde->nlink = 1;
 	pde->data = systemcfg;
-	pde->size = 4096;
+	pde->size = PAGE_SIZE;
 	pde->proc_fops = &page_map_fops;
 
 #ifdef CONFIG_PPC_PSERIES
diff -Nru a/arch/ppc64/kernel/process.c b/arch/ppc64/kernel/process.c
--- a/arch/ppc64/kernel/process.c	2005-03-11 12:51:47 -08:00
+++ b/arch/ppc64/kernel/process.c	2005-03-11 12:51:47 -08:00
@@ -51,6 +51,7 @@
 #include <asm/cputable.h>
 #include <asm/sections.h>
 #include <asm/tlbflush.h>
+#include <asm/time.h>
 
 #ifndef CONFIG_SMP
 struct task_struct *last_task_used_math = NULL;
@@ -168,6 +169,8 @@
 
 #endif /* CONFIG_ALTIVEC */
 
+DEFINE_PER_CPU(struct cpu_usage, cpu_usage_array);
+
 struct task_struct *__switch_to(struct task_struct *prev,
 				struct task_struct *new)
 {
@@ -206,6 +209,21 @@
 	new_thread = &new->thread;
 	old_thread = &current->thread;
 
+/* Collect purr utilization data per process and per processor wise */
+/* purr is nothing but processor time base                          */
+
+#if defined(CONFIG_PPC_PSERIES)
+	if (cur_cpu_spec->firmware_features & FW_FEATURE_SPLPAR) {
+		struct cpu_usage *cu = &__get_cpu_var(cpu_usage_array);
+		long unsigned start_tb, current_tb;
+		start_tb = old_thread->start_tb;
+		cu->current_tb = current_tb = mfspr(SPRN_PURR);
+		old_thread->accum_tb += (current_tb - start_tb);
+		new_thread->start_tb = current_tb;
+	}
+#endif
+
+
 	local_irq_save(flags);
 	last = _switch(old_thread, new_thread);
 
@@ -388,12 +406,12 @@
 	kregs = (struct pt_regs *) sp;
 	sp -= STACK_FRAME_OVERHEAD;
 	p->thread.ksp = sp;
-	if (cur_cpu_spec->cpu_features & CPU_FTR_SLB) {
+	if (cpu_has_feature(CPU_FTR_SLB)) {
 		unsigned long sp_vsid = get_kernel_vsid(sp);
 
 		sp_vsid <<= SLB_VSID_SHIFT;
 		sp_vsid |= SLB_VSID_KERNEL;
-		if (cur_cpu_spec->cpu_features & CPU_FTR_16M_PAGE)
+		if (cpu_has_feature(CPU_FTR_16M_PAGE))
 			sp_vsid |= SLB_VSID_L;
 
 		p->thread.ksp_vsid = sp_vsid;
@@ -469,6 +487,7 @@
 	current->thread.used_vr = 0;
 #endif /* CONFIG_ALTIVEC */
 }
+EXPORT_SYMBOL(start_thread);
 
 int set_fpexc_mode(struct task_struct *tsk, unsigned int val)
 {
@@ -607,6 +626,7 @@
 	} while (count++ < 16);
 	return 0;
 }
+EXPORT_SYMBOL(get_wchan);
 
 void show_stack(struct task_struct *p, unsigned long *_sp)
 {
diff -Nru a/arch/ppc64/kernel/prom.c b/arch/ppc64/kernel/prom.c
--- a/arch/ppc64/kernel/prom.c	2005-03-11 12:51:47 -08:00
+++ b/arch/ppc64/kernel/prom.c	2005-03-11 12:51:47 -08:00
@@ -32,6 +32,8 @@
 #include <linux/delay.h>
 #include <linux/initrd.h>
 #include <linux/bitops.h>
+#include <linux/module.h>
+
 #include <asm/prom.h>
 #include <asm/rtas.h>
 #include <asm/lmb.h>
@@ -333,7 +335,8 @@
 		while ((l -= sizeof(struct pci_reg_property)) >= 0) {
 			if (!measure_only) {
 				adr[i].space = pci_addrs[i].addr.a_hi;
-				adr[i].address = pci_addrs[i].addr.a_lo;
+				adr[i].address = pci_addrs[i].addr.a_lo |
+					((u64)pci_addrs[i].addr.a_mid << 32);
 				adr[i].size = pci_addrs[i].size_lo;
 			}
 			++i;
@@ -1138,6 +1141,7 @@
 	*prevp = NULL;
 	return head;
 }
+EXPORT_SYMBOL(find_devices);
 
 /**
  * Construct and return a list of the device_nodes with a given type.
@@ -1157,6 +1161,7 @@
 	*prevp = NULL;
 	return head;
 }
+EXPORT_SYMBOL(find_type_devices);
 
 /**
  * Returns all nodes linked together
@@ -1174,6 +1179,7 @@
 	*prevp = NULL;
 	return head;
 }
+EXPORT_SYMBOL(find_all_nodes);
 
 /** Checks if the given "compat" string matches one of the strings in
  * the device's "compatible" property
@@ -1197,6 +1203,7 @@
 
 	return 0;
 }
+EXPORT_SYMBOL(device_is_compatible);
 
 
 /**
@@ -1216,6 +1223,7 @@
 	}
 	return rc;
 }
+EXPORT_SYMBOL(machine_is_compatible);
 
 /**
  * Construct and return a list of the device_nodes with a given type
@@ -1239,6 +1247,7 @@
 	*prevp = NULL;
 	return head;
 }
+EXPORT_SYMBOL(find_compatible_devices);
 
 /**
  * Find the device_node with a given full_name.
@@ -1253,6 +1262,7 @@
 			return np;
 	return NULL;
 }
+EXPORT_SYMBOL(find_path_device);
 
 /*******
  *
@@ -1712,7 +1722,8 @@
 			}
 			while ((l -= sizeof(struct pci_reg_property)) >= 0) {
 				adr[i].space = pci_addrs[i].addr.a_hi;
-				adr[i].address = pci_addrs[i].addr.a_lo;
+				adr[i].address = pci_addrs[i].addr.a_lo |
+					((u64)pci_addrs[i].addr.a_mid << 32);
 				adr[i].size = pci_addrs[i].size_lo;
 				++i;
 			}
@@ -1872,6 +1883,7 @@
 		}
 	return NULL;
 }
+EXPORT_SYMBOL(get_property);
 
 /*
  * Add a property to a node
diff -Nru a/arch/ppc64/kernel/prom_init.c b/arch/ppc64/kernel/prom_init.c
--- a/arch/ppc64/kernel/prom_init.c	2005-03-11 12:51:51 -08:00
+++ b/arch/ppc64/kernel/prom_init.c	2005-03-11 12:51:51 -08:00
@@ -151,7 +151,6 @@
 
 extern void __start(unsigned long r3, unsigned long r4, unsigned long r5);
 
-extern unsigned long reloc_offset(void);
 extern void enter_prom(struct prom_args *args, unsigned long entry);
 extern void copy_and_flush(unsigned long dest, unsigned long src,
 			   unsigned long size, unsigned long offset);
@@ -679,8 +678,7 @@
 	 * point to after it
 	 */
 	if (RELOC(prom_initrd_start)) {
-		if ((RELOC(prom_initrd_start) + RELOC(prom_initrd_end))
-		    > RELOC(alloc_bottom))
+		if (RELOC(prom_initrd_end) > RELOC(alloc_bottom))
 			RELOC(alloc_bottom) = PAGE_ALIGN(RELOC(prom_initrd_end));
 	}
 
diff -Nru a/arch/ppc64/kernel/rtas.c b/arch/ppc64/kernel/rtas.c
--- a/arch/ppc64/kernel/rtas.c	2005-03-11 12:51:41 -08:00
+++ b/arch/ppc64/kernel/rtas.c	2005-03-11 12:51:41 -08:00
@@ -255,29 +255,59 @@
 	return ms; 
 }
 
-int
-rtas_get_power_level(int powerdomain, int *level)
+int rtas_error_rc(int rtas_rc)
+{
+	int rc;
+
+	switch (rtas_rc) {
+		case -1: 		/* Hardware Error */
+			rc = -EIO;
+			break;
+		case -3:		/* Bad indicator/domain/etc */
+			rc = -EINVAL;
+			break;
+		case -9000:		/* Isolation error */
+			rc = -EFAULT;
+			break;
+		case -9001:		/* Outstanding TCE/PTE */
+			rc = -EEXIST;
+			break;
+		case -9002:		/* No usable slot */
+			rc = -ENODEV;
+			break;
+		default:
+			printk(KERN_ERR "%s: unexpected RTAS error %d\n",
+					__FUNCTION__, rtas_rc);
+			rc = -ERANGE;
+			break;
+	}
+	return rc;
+}
+
+int rtas_get_power_level(int powerdomain, int *level)
 {
 	int token = rtas_token("get-power-level");
 	int rc;
 
 	if (token == RTAS_UNKNOWN_SERVICE)
-		return RTAS_UNKNOWN_OP;
+		return -ENOENT;
 
 	while ((rc = rtas_call(token, 1, 2, level, powerdomain)) == RTAS_BUSY)
 		udelay(1);
+
+	if (rc < 0)
+		return rtas_error_rc(rc);
 	return rc;
 }
 
-int
-rtas_set_power_level(int powerdomain, int level, int *setlevel)
+int rtas_set_power_level(int powerdomain, int level, int *setlevel)
 {
 	int token = rtas_token("set-power-level");
 	unsigned int wait_time;
 	int rc;
 
 	if (token == RTAS_UNKNOWN_SERVICE)
-		return RTAS_UNKNOWN_OP;
+		return -ENOENT;
 
 	while (1) {
 		rc = rtas_call(token, 2, 2, setlevel, powerdomain, level);
@@ -289,18 +319,20 @@
 		} else
 			break;
 	}
+
+	if (rc < 0)
+		return rtas_error_rc(rc);
 	return rc;
 }
 
-int
-rtas_get_sensor(int sensor, int index, int *state)
+int rtas_get_sensor(int sensor, int index, int *state)
 {
 	int token = rtas_token("get-sensor-state");
 	unsigned int wait_time;
 	int rc;
 
 	if (token == RTAS_UNKNOWN_SERVICE)
-		return RTAS_UNKNOWN_OP;
+		return -ENOENT;
 
 	while (1) {
 		rc = rtas_call(token, 2, 2, state, sensor, index);
@@ -312,18 +344,20 @@
 		} else
 			break;
 	}
+
+	if (rc < 0)
+		return rtas_error_rc(rc);
 	return rc;
 }
 
-int
-rtas_set_indicator(int indicator, int index, int new_value)
+int rtas_set_indicator(int indicator, int index, int new_value)
 {
 	int token = rtas_token("set-indicator");
 	unsigned int wait_time;
 	int rc;
 
 	if (token == RTAS_UNKNOWN_SERVICE)
-		return RTAS_UNKNOWN_OP;
+		return -ENOENT;
 
 	while (1) {
 		rc = rtas_call(token, 3, 1, NULL, indicator, index, new_value);
@@ -337,6 +371,8 @@
 			break;
 	}
 
+	if (rc < 0)
+		return rtas_error_rc(rc);
 	return rc;
 }
 
diff -Nru a/arch/ppc64/kernel/rtasd.c b/arch/ppc64/kernel/rtasd.c
--- a/arch/ppc64/kernel/rtasd.c	2005-03-11 12:51:42 -08:00
+++ b/arch/ppc64/kernel/rtasd.c	2005-03-11 12:51:42 -08:00
@@ -347,7 +347,7 @@
 	if (error == 0)
 		return 0;
 
-	if (error == RTAS_NO_SUCH_INDICATOR) {
+	if (error == -EINVAL) {
 		printk(KERN_INFO "rtasd: surveillance not supported\n");
 		return 0;
 	}
diff -Nru a/arch/ppc64/kernel/semaphore.c b/arch/ppc64/kernel/semaphore.c
--- a/arch/ppc64/kernel/semaphore.c	2005-03-11 12:51:41 -08:00
+++ b/arch/ppc64/kernel/semaphore.c	2005-03-11 12:51:41 -08:00
@@ -18,6 +18,8 @@
 
 #include <linux/sched.h>
 #include <linux/init.h>
+#include <linux/module.h>
+
 #include <asm/atomic.h>
 #include <asm/semaphore.h>
 #include <asm/errno.h>
@@ -62,6 +64,7 @@
 	__sem_update_count(sem, 1);
 	wake_up(&sem->wait);
 }
+EXPORT_SYMBOL(__up);
 
 /*
  * Note that when we come in to __down or __down_interruptible,
@@ -99,6 +102,7 @@
 	 */
 	wake_up(&sem->wait);
 }
+EXPORT_SYMBOL(__down);
 
 int __sched __down_interruptible(struct semaphore * sem)
 {
@@ -129,3 +133,4 @@
 	wake_up(&sem->wait);
 	return retval;
 }
+EXPORT_SYMBOL(__down_interruptible);
diff -Nru a/arch/ppc64/kernel/setup.c b/arch/ppc64/kernel/setup.c
--- a/arch/ppc64/kernel/setup.c	2005-03-11 12:51:46 -08:00
+++ b/arch/ppc64/kernel/setup.c	2005-03-11 12:51:46 -08:00
@@ -129,6 +129,7 @@
 /* The main machine-dep calls structure
  */
 struct machdep_calls ppc_md;
+EXPORT_SYMBOL(ppc_md);
 
 #ifdef CONFIG_MAGIC_SYSRQ
 unsigned long SYSRQ_KEY;
@@ -315,7 +316,7 @@
 		maxcpus = ireg[num_addr_cell + num_size_cell];
 
 		/* Double maxcpus for processors which have SMT capability */
-		if (cur_cpu_spec->cpu_features & CPU_FTR_SMT)
+		if (cpu_has_feature(CPU_FTR_SMT))
 			maxcpus *= 2;
 
 		if (maxcpus > NR_CPUS) {
@@ -339,7 +340,7 @@
 	 */
 	for_each_cpu(cpu) {
 		cpu_set(cpu, cpu_sibling_map[cpu]);
-		if (cur_cpu_spec->cpu_features & CPU_FTR_SMT)
+		if (cpu_has_feature(CPU_FTR_SMT))
 			cpu_set(cpu ^ 0x1, cpu_sibling_map[cpu]);
 	}
 
@@ -767,7 +768,7 @@
 		seq_printf(m, "unknown (%08x)", pvr);
 
 #ifdef CONFIG_ALTIVEC
-	if (cur_cpu_spec->cpu_features & CPU_FTR_ALTIVEC)
+	if (cpu_has_feature(CPU_FTR_ALTIVEC))
 		seq_printf(m, ", altivec supported");
 #endif /* CONFIG_ALTIVEC */
 
@@ -990,6 +991,34 @@
 }
 
 /*
+ * Called from setup_arch to initialize the bitmap of available
+ * syscalls in the systemcfg page
+ */
+void __init setup_syscall_map(void)
+{
+	unsigned int i, count64 = 0, count32 = 0;
+	extern unsigned long *sys_call_table;
+	extern unsigned long *sys_call_table32;
+	extern unsigned long sys_ni_syscall;
+
+
+	for (i = 0; i < __NR_syscalls; i++) {
+		if (sys_call_table[i] == sys_ni_syscall)
+			continue;
+		count64++;
+		systemcfg->syscall_map_64[i >> 5] |= 0x80000000UL >> (i & 0x1f);
+	}
+	for (i = 0; i < __NR_syscalls; i++) {
+		if (sys_call_table32[i] == sys_ni_syscall)
+			continue;
+		count32++;
+		systemcfg->syscall_map_32[i >> 5] |= 0x80000000UL >> (i & 0x1f);
+	}
+	printk(KERN_INFO "Syscall map setup, %d 32 bits and %d 64 bits syscalls\n",
+	       count32, count64);
+}
+
+/*
  * Called into from start_kernel, after lock_kernel has been called.
  * Initializes bootmem, which is unsed to manage page allocation until
  * mem_init is called.
@@ -1027,6 +1056,9 @@
 	/* set up the bootmem stuff with available memory */
 	do_init_bootmem();
 
+	/* initialize the syscall map in systemcfg */
+	setup_syscall_map();
+
 	ppc_md.setup_arch();
 
 	/* Select the correct idle loop for the platform. */
@@ -1345,9 +1377,6 @@
 
 void cpu_die(void)
 {
-	idle_task_exit();
 	if (ppc_md.cpu_die)
 		ppc_md.cpu_die();
-	local_irq_disable();
-	for (;;);
 }
diff -Nru a/arch/ppc64/kernel/signal.c b/arch/ppc64/kernel/signal.c
--- a/arch/ppc64/kernel/signal.c	2005-03-11 12:51:40 -08:00
+++ b/arch/ppc64/kernel/signal.c	2005-03-11 12:51:40 -08:00
@@ -27,6 +27,8 @@
 #include <linux/stddef.h>
 #include <linux/elf.h>
 #include <linux/ptrace.h>
+#include <linux/module.h>
+
 #include <asm/sigcontext.h>
 #include <asm/ucontext.h>
 #include <asm/uaccess.h>
@@ -34,6 +36,7 @@
 #include <asm/ppcdebug.h>
 #include <asm/unistd.h>
 #include <asm/cacheflush.h>
+#include <asm/vdso.h>
 
 #define DEBUG_SIG 0
 
@@ -426,10 +429,14 @@
 		goto badframe;
 
 	/* Set up to return from userspace. */
-	err |= setup_trampoline(__NR_rt_sigreturn, &frame->tramp[0]);
-	if (err)
-		goto badframe;
-
+	if (vdso64_rt_sigtramp && current->thread.vdso_base) {
+		regs->link = current->thread.vdso_base + vdso64_rt_sigtramp;
+	} else {
+		err |= setup_trampoline(__NR_rt_sigreturn, &frame->tramp[0]);
+		if (err)
+			goto badframe;
+		regs->link = (unsigned long) &frame->tramp[0];
+	}
 	funct_desc_ptr = (func_descr_t __user *) ka->sa.sa_handler;
 
 	/* Allocate a dummy caller frame for the signal handler. */
@@ -438,7 +445,6 @@
 
 	/* Set up "regs" so we "return" to the signal handler. */
 	err |= get_user(regs->nip, &funct_desc_ptr->entry);
-	regs->link = (unsigned long) &frame->tramp[0];
 	regs->gpr[1] = newsp;
 	err |= get_user(regs->gpr[2], &funct_desc_ptr->toc);
 	regs->gpr[3] = signr;
@@ -566,6 +572,4 @@
 
 	return 0;
 }
-
-
-
+EXPORT_SYMBOL(do_signal);
diff -Nru a/arch/ppc64/kernel/signal32.c b/arch/ppc64/kernel/signal32.c
--- a/arch/ppc64/kernel/signal32.c	2005-03-11 12:51:51 -08:00
+++ b/arch/ppc64/kernel/signal32.c	2005-03-11 12:51:51 -08:00
@@ -31,6 +31,7 @@
 #include <asm/ppcdebug.h>
 #include <asm/unistd.h>
 #include <asm/cacheflush.h>
+#include <asm/vdso.h>
 
 #define DEBUG_SIG 0
 
@@ -656,18 +657,24 @@
 
 	/* Save user registers on the stack */
 	frame = &rt_sf->uc.uc_mcontext;
-	if (save_user_regs(regs, frame, __NR_rt_sigreturn))
-		goto badframe;
-
 	if (put_user(regs->gpr[1], (unsigned long __user *)newsp))
 		goto badframe;
+
+	if (vdso32_rt_sigtramp && current->thread.vdso_base) {
+		if (save_user_regs(regs, frame, 0))
+			goto badframe;
+		regs->link = current->thread.vdso_base + vdso32_rt_sigtramp;
+	} else {
+		if (save_user_regs(regs, frame, __NR_rt_sigreturn))
+			goto badframe;
+		regs->link = (unsigned long) frame->tramp;
+	}
 	regs->gpr[1] = (unsigned long) newsp;
 	regs->gpr[3] = sig;
 	regs->gpr[4] = (unsigned long) &rt_sf->info;
 	regs->gpr[5] = (unsigned long) &rt_sf->uc;
 	regs->gpr[6] = (unsigned long) rt_sf;
 	regs->nip = (unsigned long) ka->sa.sa_handler;
-	regs->link = (unsigned long) frame->tramp;
 	regs->trap = 0;
 	regs->result = 0;
 
@@ -825,8 +832,15 @@
 	    || __put_user(sig, &sc->signal))
 		goto badframe;
 
-	if (save_user_regs(regs, &frame->mctx, __NR_sigreturn))
-		goto badframe;
+	if (vdso32_sigtramp && current->thread.vdso_base) {
+		if (save_user_regs(regs, &frame->mctx, 0))
+			goto badframe;
+		regs->link = current->thread.vdso_base + vdso32_sigtramp;
+	} else {
+		if (save_user_regs(regs, &frame->mctx, __NR_sigreturn))
+			goto badframe;
+		regs->link = (unsigned long) frame->mctx.tramp;
+	}
 
 	if (put_user(regs->gpr[1], (unsigned long __user *)newsp))
 		goto badframe;
@@ -834,7 +848,6 @@
 	regs->gpr[3] = sig;
 	regs->gpr[4] = (unsigned long) sc;
 	regs->nip = (unsigned long) ka->sa.sa_handler;
-	regs->link = (unsigned long) frame->mctx.tramp;
 	regs->trap = 0;
 	regs->result = 0;
 
diff -Nru a/arch/ppc64/kernel/smp.c b/arch/ppc64/kernel/smp.c
--- a/arch/ppc64/kernel/smp.c	2005-03-11 12:51:47 -08:00
+++ b/arch/ppc64/kernel/smp.c	2005-03-11 12:51:47 -08:00
@@ -30,6 +30,7 @@
 #include <linux/err.h>
 #include <linux/sysdev.h>
 #include <linux/cpu.h>
+#include <linux/notifier.h>
 
 #include <asm/ptrace.h>
 #include <asm/atomic.h>
@@ -383,7 +384,7 @@
 	 * For now we leave it which means the time can be some
 	 * number of msecs off until someone does a settimeofday()
 	 */
-	do_gtod.tb_orig_stamp = tb_last_stamp;
+	do_gtod.varp->tb_orig_stamp = tb_last_stamp;
 	systemcfg->tb_orig_stamp = tb_last_stamp;
 #endif
 
@@ -406,17 +407,96 @@
 	current_set[boot_cpuid] = current->thread_info;
 }
 
+#ifdef CONFIG_HOTPLUG_CPU
+/* State of each CPU during hotplug phases */
+DEFINE_PER_CPU(int, cpu_state) = { 0 };
+
+int generic_cpu_disable(void)
+{
+	unsigned int cpu = smp_processor_id();
+
+	if (cpu == boot_cpuid)
+		return -EBUSY;
+
+	systemcfg->processorCount--;
+	cpu_clear(cpu, cpu_online_map);
+	fixup_irqs(cpu_online_map);
+	return 0;
+}
+
+int generic_cpu_enable(unsigned int cpu)
+{
+	/* Do the normal bootup if we haven't
+	 * already bootstrapped. */
+	if (system_state != SYSTEM_RUNNING)
+		return -ENOSYS;
+
+	/* get the target out of it's holding state */
+	per_cpu(cpu_state, cpu) = CPU_UP_PREPARE;
+	wmb();
+
+	while (!cpu_online(cpu))
+		cpu_relax();
+
+	fixup_irqs(cpu_online_map);
+	/* counter the irq disable in fixup_irqs */
+	local_irq_enable();
+	return 0;
+}
+
+void generic_cpu_die(unsigned int cpu)
+{
+	int i;
+
+	for (i = 0; i < 100; i++) {
+		rmb();
+		if (per_cpu(cpu_state, cpu) == CPU_DEAD)
+			return;
+		msleep(100);
+	}
+	printk(KERN_ERR "CPU%d didn't die...\n", cpu);
+}
+
+void generic_mach_cpu_die(void)
+{
+	unsigned int cpu;
+
+	local_irq_disable();
+	cpu = smp_processor_id();
+	printk(KERN_DEBUG "CPU%d offline\n", cpu);
+	__get_cpu_var(cpu_state) = CPU_DEAD;
+	wmb();
+	while (__get_cpu_var(cpu_state) != CPU_UP_PREPARE)
+		cpu_relax();
+
+	flush_tlb_pending();
+	cpu_set(cpu, cpu_online_map);
+	local_irq_enable();
+}
+#endif
+
+static int __devinit cpu_enable(unsigned int cpu)
+{
+	if (smp_ops->cpu_enable)
+		return smp_ops->cpu_enable(cpu);
+
+	return -ENOSYS;
+}
+
 int __devinit __cpu_up(unsigned int cpu)
 {
 	int c;
 
+	if (!cpu_enable(cpu))
+		return 0;
+
 	/* At boot, don't bother with non-present cpus -JSCHOPP */
 	if (system_state < SYSTEM_RUNNING && !cpu_present(cpu))
 		return -ENOENT;
 
 	paca[cpu].default_decr = tb_ticks_per_jiffy / decr_overclock;
 
-	if (!(cur_cpu_spec->cpu_features & CPU_FTR_SLB)) {
+	if (!cpu_has_feature(CPU_FTR_SLB)) {
 		void *tmp;
 
 		/* maximum of 48 CPUs on machines with a segment table */
diff -Nru a/arch/ppc64/kernel/sys_ppc32.c b/arch/ppc64/kernel/sys_ppc32.c
--- a/arch/ppc64/kernel/sys_ppc32.c	2005-03-11 12:51:52 -08:00
+++ b/arch/ppc64/kernel/sys_ppc32.c	2005-03-11 12:51:52 -08:00
@@ -1290,14 +1290,7 @@
 	if (ev32 == NULL)
 		return sys_timer_create(clock, NULL, timer_id);
 
-	memset(&event, 0, sizeof(event));
-	if (!access_ok(VERIFY_READ, ev32, sizeof(struct compat_sigevent))
-	    || __get_user(event.sigev_value.sival_int,
-			  &ev32->sigev_value.sival_int)
-	    || __get_user(event.sigev_signo, &ev32->sigev_signo)
-	    || __get_user(event.sigev_notify, &ev32->sigev_notify)
-	    || __get_user(event.sigev_notify_thread_id,
-			  &ev32->sigev_notify_thread_id))
+	if (get_compat_sigevent(&event, ev32))
 		return -EFAULT;
 
 	if (!access_ok(VERIFY_WRITE, timer_id, sizeof(timer_t)))
diff -Nru a/arch/ppc64/kernel/sysfs.c b/arch/ppc64/kernel/sysfs.c
--- a/arch/ppc64/kernel/sysfs.c	2005-03-11 12:51:41 -08:00
+++ b/arch/ppc64/kernel/sysfs.c	2005-03-11 12:51:41 -08:00
@@ -18,7 +18,7 @@
 #include <asm/systemcfg.h>
 #include <asm/paca.h>
 #include <asm/lppaca.h>
-
+#include <asm/machdep.h>
 
 static DEFINE_PER_CPU(struct cpu, cpu_devices);
 
@@ -63,7 +63,7 @@
 	unsigned int *val;
 	unsigned int cpu;
 
-	if (!cur_cpu_spec->cpu_features & CPU_FTR_SMT)
+	if (!cpu_has_feature(CPU_FTR_SMT))
 		return 1;
 
 	options = find_path_device("/options");
@@ -86,7 +86,7 @@
 	unsigned int cpu;
 	int snooze;
 
-	if (!cur_cpu_spec->cpu_features & CPU_FTR_SMT)
+	if (!cpu_has_feature(CPU_FTR_SMT))
 		return 1;
 
 	smt_snooze_cmdline = 1;
@@ -167,7 +167,7 @@
 	 * On SMT machines we have to set the run latch in the ctrl register
 	 * in order to make PMC6 spin.
 	 */
-	if (cur_cpu_spec->cpu_features & CPU_FTR_SMT) {
+	if (cpu_has_feature(CPU_FTR_SMT)) {
 		ctrl = mfspr(CTRLF);
 		ctrl |= RUNLATCH;
 		mtspr(CTRLT, ctrl);
@@ -266,7 +266,7 @@
 	struct sys_device *s = &c->sysdev;
 
 #ifndef CONFIG_PPC_ISERIES
-	if (cur_cpu_spec->cpu_features & CPU_FTR_SMT)
+	if (cpu_has_feature(CPU_FTR_SMT))
 		sysdev_create_file(s, &attr_smt_snooze_delay);
 #endif
 
@@ -275,7 +275,7 @@
 	sysdev_create_file(s, &attr_mmcr0);
 	sysdev_create_file(s, &attr_mmcr1);
 
-	if (cur_cpu_spec->cpu_features & CPU_FTR_MMCRA)
+	if (cpu_has_feature(CPU_FTR_MMCRA))
 		sysdev_create_file(s, &attr_mmcra);
 
 	sysdev_create_file(s, &attr_pmc1);
@@ -285,12 +285,12 @@
 	sysdev_create_file(s, &attr_pmc5);
 	sysdev_create_file(s, &attr_pmc6);
 
-	if (cur_cpu_spec->cpu_features & CPU_FTR_PMC8) {
+	if (cpu_has_feature(CPU_FTR_PMC8)) {
 		sysdev_create_file(s, &attr_pmc7);
 		sysdev_create_file(s, &attr_pmc8);
 	}
 
-	if (cur_cpu_spec->cpu_features & CPU_FTR_SMT)
+	if (cpu_has_feature(CPU_FTR_SMT))
 		sysdev_create_file(s, &attr_purr);
 }
 
@@ -303,7 +303,7 @@
 	BUG_ON(c->no_control);
 
 #ifndef CONFIG_PPC_ISERIES
-	if (cur_cpu_spec->cpu_features & CPU_FTR_SMT)
+	if (cpu_has_feature(CPU_FTR_SMT))
 		sysdev_remove_file(s, &attr_smt_snooze_delay);
 #endif
 
@@ -312,7 +312,7 @@
 	sysdev_remove_file(s, &attr_mmcr0);
 	sysdev_remove_file(s, &attr_mmcr1);
 
-	if (cur_cpu_spec->cpu_features & CPU_FTR_MMCRA)
+	if (cpu_has_feature(CPU_FTR_MMCRA))
 		sysdev_remove_file(s, &attr_mmcra);
 
 	sysdev_remove_file(s, &attr_pmc1);
@@ -322,12 +322,12 @@
 	sysdev_remove_file(s, &attr_pmc5);
 	sysdev_remove_file(s, &attr_pmc6);
 
-	if (cur_cpu_spec->cpu_features & CPU_FTR_PMC8) {
+	if (cpu_has_feature(CPU_FTR_PMC8)) {
 		sysdev_remove_file(s, &attr_pmc7);
 		sysdev_remove_file(s, &attr_pmc8);
 	}
 
-	if (cur_cpu_spec->cpu_features & CPU_FTR_SMT)
+	if (cpu_has_feature(CPU_FTR_SMT))
 		sysdev_remove_file(s, &attr_purr);
 }
 #endif /* CONFIG_HOTPLUG_CPU */
@@ -413,9 +413,7 @@
 		 * CPU.  For instance, the boot cpu might never be valid
 		 * for hotplugging.
 		 */
-#ifdef CONFIG_HOTPLUG_CPU
-		if (systemcfg->platform != PLATFORM_PSERIES_LPAR)
-#endif
+		if (!ppc_md.cpu_die)
 			c->no_control = 1;
 
 		if (cpu_online(cpu) || (c->no_control == 0)) {
diff -Nru a/arch/ppc64/kernel/time.c b/arch/ppc64/kernel/time.c
--- a/arch/ppc64/kernel/time.c	2005-03-11 12:51:51 -08:00
+++ b/arch/ppc64/kernel/time.c	2005-03-11 12:51:51 -08:00
@@ -85,9 +85,8 @@
 
 unsigned long tb_ticks_per_jiffy;
 unsigned long tb_ticks_per_usec = 100; /* sane default */
+EXPORT_SYMBOL(tb_ticks_per_usec);
 unsigned long tb_ticks_per_sec;
-unsigned long next_xtime_sync_tb;
-unsigned long xtime_sync_interval;
 unsigned long tb_to_xs;
 unsigned      tb_to_us;
 unsigned long processor_freq;
@@ -158,8 +157,8 @@
 	 * The conversion to microseconds at the end is done
 	 * without a divide (and in fact, without a multiply)
 	 */
-	tb_ticks = tb_val - do_gtod.tb_orig_stamp;
 	temp_varp = do_gtod.varp;
+	tb_ticks = tb_val - temp_varp->tb_orig_stamp;
 	temp_tb_to_xs = temp_varp->tb_to_xs;
 	temp_stamp_xsec = temp_varp->stamp_xsec;
 	tb_xsec = mulhdu( tb_ticks, temp_tb_to_xs );
@@ -185,17 +184,55 @@
 {
 	struct timeval my_tv;
 
-	if (cur_tb > next_xtime_sync_tb) {
-		next_xtime_sync_tb = cur_tb + xtime_sync_interval;
-		__do_gettimeofday(&my_tv, cur_tb);
-
-		if (xtime.tv_sec <= my_tv.tv_sec) {
-			xtime.tv_sec = my_tv.tv_sec;
-			xtime.tv_nsec = my_tv.tv_usec * 1000;
-		}
+	__do_gettimeofday(&my_tv, cur_tb);
+
+	if (xtime.tv_sec <= my_tv.tv_sec) {
+		xtime.tv_sec = my_tv.tv_sec;
+		xtime.tv_nsec = my_tv.tv_usec * 1000;
 	}
 }
 
+/*
+ * When the timebase - tb_orig_stamp gets too big, we do a manipulation
+ * between tb_orig_stamp and stamp_xsec. The goal here is to keep the
+ * difference tb - tb_orig_stamp small enough to always fit inside a
+ * 32 bits number. This is a requirement of our fast 32 bits userland
+ * implementation in the vdso. If we "miss" a call to this function
+ * (interrupt latency, CPU locked in a spinlock, ...) and we end up
+ * with a too big difference, then the vdso will fallback to calling
+ * the syscall
+ */
+static __inline__ void timer_recalc_offset(unsigned long cur_tb)
+{
+	struct gettimeofday_vars * temp_varp;
+	unsigned temp_idx;
+	unsigned long offset, new_stamp_xsec, new_tb_orig_stamp;
+
+	if (((cur_tb - do_gtod.varp->tb_orig_stamp) & 0x80000000u) == 0)
+		return;
+
+	temp_idx = (do_gtod.var_idx == 0);
+	temp_varp = &do_gtod.vars[temp_idx];
+
+	new_tb_orig_stamp = cur_tb;
+	offset = new_tb_orig_stamp - do_gtod.varp->tb_orig_stamp;
+	new_stamp_xsec = do_gtod.varp->stamp_xsec + mulhdu(offset, do_gtod.varp->tb_to_xs);
+
+	temp_varp->tb_to_xs = do_gtod.varp->tb_to_xs;
+	temp_varp->tb_orig_stamp = new_tb_orig_stamp;
+	temp_varp->stamp_xsec = new_stamp_xsec;
+	mb();
+	do_gtod.varp = temp_varp;
+	do_gtod.var_idx = temp_idx;
+
+	++(systemcfg->tb_update_count);
+	wmb();
+	systemcfg->tb_orig_stamp = new_tb_orig_stamp;
+	systemcfg->stamp_xsec = new_stamp_xsec;
+	wmb();
+	++(systemcfg->tb_update_count);
+}
+
 #ifdef CONFIG_SMP
 unsigned long profile_pc(struct pt_regs *regs)
 {
@@ -311,6 +348,7 @@
 		if (cpu == boot_cpuid) {
 			write_seqlock(&xtime_lock);
 			tb_last_stamp = lpaca->next_jiffy_update_tb;
+			timer_recalc_offset(lpaca->next_jiffy_update_tb);
 			do_timer(regs);
 			timer_sync_xtime(lpaca->next_jiffy_update_tb);
 			timer_check_rtc();
@@ -334,6 +372,14 @@
 	}
 #endif
 
+/* collect purr register values often, for accurate calculations */
+#if defined(CONFIG_PPC_PSERIES)
+	if (cur_cpu_spec->firmware_features & FW_FEATURE_SPLPAR) {
+		struct cpu_usage *cu = &__get_cpu_var(cpu_usage_array);
+		cu->current_tb = mfspr(SPRN_PURR);
+	}
+#endif
+
 	irq_exit();
 
 	return 1;
@@ -398,7 +444,9 @@
 	time_maxerror = NTP_PHASE_LIMIT;
 	time_esterror = NTP_PHASE_LIMIT;
 
-	delta_xsec = mulhdu( (tb_last_stamp-do_gtod.tb_orig_stamp), do_gtod.varp->tb_to_xs );
+	delta_xsec = mulhdu( (tb_last_stamp-do_gtod.varp->tb_orig_stamp),
+			     do_gtod.varp->tb_to_xs );
+
 	new_xsec = (new_nsec * XSEC_PER_SEC) / NSEC_PER_SEC;
 	new_xsec += new_sec * XSEC_PER_SEC;
 	if ( new_xsec > delta_xsec ) {
@@ -411,7 +459,7 @@
 		 * before 1970 ... eg. we booted ten days ago, and we are setting
 		 * the time to Jan 5, 1970 */
 		do_gtod.varp->stamp_xsec = new_xsec;
-		do_gtod.tb_orig_stamp = tb_last_stamp;
+		do_gtod.varp->tb_orig_stamp = tb_last_stamp;
 		systemcfg->stamp_xsec = new_xsec;
 		systemcfg->tb_orig_stamp = tb_last_stamp;
 	}
@@ -464,9 +512,9 @@
 	xtime.tv_sec = mktime(tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
 			      tm.tm_hour, tm.tm_min, tm.tm_sec);
 	tb_last_stamp = get_tb();
-	do_gtod.tb_orig_stamp = tb_last_stamp;
 	do_gtod.varp = &do_gtod.vars[0];
 	do_gtod.var_idx = 0;
+	do_gtod.varp->tb_orig_stamp = tb_last_stamp;
 	do_gtod.varp->stamp_xsec = xtime.tv_sec * XSEC_PER_SEC;
 	do_gtod.tb_ticks_per_sec = tb_ticks_per_sec;
 	do_gtod.varp->tb_to_xs = tb_to_xs;
@@ -477,9 +525,6 @@
 	systemcfg->stamp_xsec = xtime.tv_sec * XSEC_PER_SEC;
 	systemcfg->tb_to_xs = tb_to_xs;
 
-	xtime_sync_interval = tb_ticks_per_sec - (tb_ticks_per_sec/8);
-	next_xtime_sync_tb = tb_last_stamp + xtime_sync_interval;
-
 	time_freq = 0;
 
 	xtime.tv_nsec = 0;
@@ -584,12 +629,12 @@
 	   stamp_xsec which is the time (in 1/2^20 second units) corresponding to tb_orig_stamp.  This 
 	   new value of stamp_xsec compensates for the change in frequency (implied by the new tb_to_xs)
 	   which guarantees that the current time remains the same */ 
-	tb_ticks = get_tb() - do_gtod.tb_orig_stamp;
+	write_seqlock_irqsave( &xtime_lock, flags );
+	tb_ticks = get_tb() - do_gtod.varp->tb_orig_stamp;
 	div128_by_32( 1024*1024, 0, new_tb_ticks_per_sec, &divres );
 	new_tb_to_xs = divres.result_low;
 	new_xsec = mulhdu( tb_ticks, new_tb_to_xs );
 
-	write_seqlock_irqsave( &xtime_lock, flags );
 	old_xsec = mulhdu( tb_ticks, do_gtod.varp->tb_to_xs );
 	new_stamp_xsec = do_gtod.varp->stamp_xsec + old_xsec - new_xsec;
 
@@ -597,16 +642,12 @@
 	   values in do_gettimeofday.  We alternate the copies and as long as a reasonable time elapses between
 	   changes, there will never be inconsistent values.  ntpd has a minimum of one minute between updates */
 
-	if (do_gtod.var_idx == 0) {
-		temp_varp = &do_gtod.vars[1];
-		temp_idx  = 1;
-	}
-	else {
-		temp_varp = &do_gtod.vars[0];
-		temp_idx  = 0;
-	}
+	temp_idx = (do_gtod.var_idx == 0);
+	temp_varp = &do_gtod.vars[temp_idx];
+
 	temp_varp->tb_to_xs = new_tb_to_xs;
 	temp_varp->stamp_xsec = new_stamp_xsec;
+	temp_varp->tb_orig_stamp = do_gtod.varp->tb_orig_stamp;
 	mb();
 	do_gtod.varp = temp_varp;
 	do_gtod.var_idx = temp_idx;
diff -Nru a/arch/ppc64/kernel/traps.c b/arch/ppc64/kernel/traps.c
--- a/arch/ppc64/kernel/traps.c	2005-03-11 12:51:46 -08:00
+++ b/arch/ppc64/kernel/traps.c	2005-03-11 12:51:46 -08:00
@@ -41,6 +41,7 @@
 #include <asm/rtas.h>
 #include <asm/systemcfg.h>
 #include <asm/machdep.h>
+#include <asm/pmc.h>
 
 #ifdef CONFIG_DEBUGGER
 int (*__debugger)(struct pt_regs *regs);
@@ -278,6 +279,9 @@
  * fault.  Return zero on success.
  */
 
+#define INST_MFSPR_PVR		0x7c1f42a6
+#define INST_MFSPR_PVR_MASK	0xfc1fffff
+
 #define INST_DCBA		0x7c0005ec
 #define INST_DCBA_MASK		0x7c0007fe
 
@@ -296,6 +300,15 @@
 	if (get_user(instword, (unsigned int __user *)(regs->nip)))
 		return -EFAULT;
 
+	/* Emulate the mfspr rD, PVR. */
+	if ((instword & INST_MFSPR_PVR_MASK) == INST_MFSPR_PVR) {
+		unsigned int rd;
+
+		rd = (instword >> 21) & 0x1f;
+		regs->gpr[rd] = mfspr(SPRN_PVR);
+		return 0;
+	}
+
 	/* Emulating the dcba insn is just a no-op.  */
 	if ((instword & INST_DCBA_MASK) == INST_DCBA) {
 		static int warned;
@@ -389,11 +402,6 @@
 	if (regs->msr & 0x100000) {
 		/* IEEE FP exception */
 		parse_fpe(regs);
-
-	} else if (regs->msr & 0x40000) {
-		/* Privileged instruction */
-		_exception(SIGILL, regs, ILL_PRVOPC, regs->nip);
-
 	} else if (regs->msr & 0x20000) {
 		/* trap exception */
 
@@ -410,7 +418,7 @@
 		_exception(SIGTRAP, regs, TRAP_BRKPT, regs->nip);
 
 	} else {
-		/* Illegal instruction; try to emulate it.  */
+		/* Privileged or illegal instruction; try to emulate it. */
 		switch (emulate_instruction(regs)) {
 		case 0:
 			regs->nip += 4;
@@ -422,7 +430,12 @@
 			break;
 
 		default:
-			_exception(SIGILL, regs, ILL_ILLOPC, regs->nip);
+			if (regs->msr & 0x40000)
+				/* priveleged */
+				_exception(SIGILL, regs, ILL_PRVOPC, regs->nip);
+			else
+				/* illegal */
+				_exception(SIGILL, regs, ILL_ILLOPC, regs->nip);
 			break;
 		}
 	}
@@ -450,18 +463,7 @@
 	die("Unrecoverable VMX/Altivec Unavailable Exception", regs, SIGABRT);
 }
 
-/* Ensure exceptions are disabled */
-static void dummy_perf(struct pt_regs *regs)
-{
-	unsigned int mmcr0 = mfspr(SPRN_MMCR0);
-
-	mmcr0 &= ~(MMCR0_PMXE|MMCR0_PMAO);
-	mtspr(SPRN_MMCR0, mmcr0);
-}
-
-void (*perf_irq)(struct pt_regs *) = dummy_perf;
-
-EXPORT_SYMBOL(perf_irq);
+extern perf_irq_t perf_irq;
 
 void performance_monitor_exception(struct pt_regs *regs)
 {
diff -Nru a/arch/ppc64/kernel/vdso.c b/arch/ppc64/kernel/vdso.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/ppc64/kernel/vdso.c	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,614 @@
+/*
+ *  linux/arch/ppc64/kernel/vdso.c
+ *
+ *    Copyright (C) 2004 Benjamin Herrenschmidt, IBM Corp.
+ *			 <benh@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 Free Software Foundation; either version
+ *  2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/stddef.h>
+#include <linux/unistd.h>
+#include <linux/slab.h>
+#include <linux/user.h>
+#include <linux/elf.h>
+#include <linux/security.h>
+#include <linux/bootmem.h>
+
+#include <asm/pgtable.h>
+#include <asm/system.h>
+#include <asm/processor.h>
+#include <asm/mmu.h>
+#include <asm/mmu_context.h>
+#include <asm/machdep.h>
+#include <asm/cputable.h>
+#include <asm/sections.h>
+#include <asm/vdso.h>
+
+#undef DEBUG
+
+#ifdef DEBUG
+#define DBG(fmt...) printk(fmt)
+#else
+#define DBG(fmt...)
+#endif
+
+
+/*
+ * The vDSOs themselves are here
+ */
+extern char vdso64_start, vdso64_end;
+extern char vdso32_start, vdso32_end;
+
+static void *vdso64_kbase = &vdso64_start;
+static void *vdso32_kbase = &vdso32_start;
+
+unsigned int vdso64_pages;
+unsigned int vdso32_pages;
+
+/* Signal trampolines user addresses */
+
+unsigned long vdso64_rt_sigtramp;
+unsigned long vdso32_sigtramp;
+unsigned long vdso32_rt_sigtramp;
+
+/* Format of the patch table */
+struct vdso_patch_def
+{
+	u32		pvr_mask, pvr_value;
+	const char	*gen_name;
+	const char	*fix_name;
+};
+
+/* Table of functions to patch based on the CPU type/revision
+ *
+ * TODO: Improve by adding whole lists for each entry
+ */
+static struct vdso_patch_def vdso_patches[] = {
+	{
+		0xffff0000, 0x003a0000,		/* POWER5 */
+		"__kernel_sync_dicache", "__kernel_sync_dicache_p5"
+	},
+	{
+		0xffff0000, 0x003b0000,		/* POWER5 */
+		"__kernel_sync_dicache", "__kernel_sync_dicache_p5"
+	},
+};
+
+/*
+ * Some infos carried around for each of them during parsing at
+ * boot time.
+ */
+struct lib32_elfinfo
+{
+	Elf32_Ehdr	*hdr;		/* ptr to ELF */
+	Elf32_Sym	*dynsym;	/* ptr to .dynsym section */
+	unsigned long	dynsymsize;	/* size of .dynsym section */
+	char		*dynstr;	/* ptr to .dynstr section */
+	unsigned long	text;		/* offset of .text section in .so */
+};
+
+struct lib64_elfinfo
+{
+	Elf64_Ehdr	*hdr;
+	Elf64_Sym	*dynsym;
+	unsigned long	dynsymsize;
+	char		*dynstr;
+	unsigned long	text;
+};
+
+
+#ifdef __DEBUG
+static void dump_one_vdso_page(struct page *pg, struct page *upg)
+{
+	printk("kpg: %p (c:%d,f:%08lx)", __va(page_to_pfn(pg) << PAGE_SHIFT),
+	       page_count(pg),
+	       pg->flags);
+	if (upg/* && pg != upg*/) {
+		printk(" upg: %p (c:%d,f:%08lx)", __va(page_to_pfn(upg) << PAGE_SHIFT),
+		       page_count(upg),
+		       upg->flags);
+	}
+	printk("\n");
+}
+
+static void dump_vdso_pages(struct vm_area_struct * vma)
+{
+	int i;
+
+	if (!vma || test_thread_flag(TIF_32BIT)) {
+		printk("vDSO32 @ %016lx:\n", (unsigned long)vdso32_kbase);
+		for (i=0; i<vdso32_pages; i++) {
+			struct page *pg = virt_to_page(vdso32_kbase + i*PAGE_SIZE);
+			struct page *upg = (vma && vma->vm_mm) ?
+				follow_page(vma->vm_mm, vma->vm_start + i*PAGE_SIZE, 0)
+				: NULL;
+			dump_one_vdso_page(pg, upg);
+		}
+	}
+	if (!vma || !test_thread_flag(TIF_32BIT)) {
+		printk("vDSO64 @ %016lx:\n", (unsigned long)vdso64_kbase);
+		for (i=0; i<vdso64_pages; i++) {
+			struct page *pg = virt_to_page(vdso64_kbase + i*PAGE_SIZE);
+			struct page *upg = (vma && vma->vm_mm) ?
+				follow_page(vma->vm_mm, vma->vm_start + i*PAGE_SIZE, 0)
+				: NULL;
+			dump_one_vdso_page(pg, upg);
+		}
+	}
+}
+#endif /* DEBUG */
+
+/*
+ * Keep a dummy vma_close for now, it will prevent VMA merging.
+ */
+static void vdso_vma_close(struct vm_area_struct * vma)
+{
+}
+
+/*
+ * Our nopage() function, maps in the actual vDSO kernel pages, they will
+ * be mapped read-only by do_no_page(), and eventually COW'ed, either
+ * right away for an initial write access, or by do_wp_page().
+ */
+static struct page * vdso_vma_nopage(struct vm_area_struct * vma,
+				     unsigned long address, int *type)
+{
+	unsigned long offset = address - vma->vm_start;
+	struct page *pg;
+	void *vbase = test_thread_flag(TIF_32BIT) ? vdso32_kbase : vdso64_kbase;
+
+	DBG("vdso_vma_nopage(current: %s, address: %016lx, off: %lx)\n",
+	    current->comm, address, offset);
+
+	if (address < vma->vm_start || address > vma->vm_end)
+		return NOPAGE_SIGBUS;
+
+	/*
+	 * Last page is systemcfg, special handling here, no get_page() a
+	 * this is a reserved page
+	 */
+	if ((vma->vm_end - address) <= PAGE_SIZE)
+		return virt_to_page(systemcfg);
+
+	pg = virt_to_page(vbase + offset);
+	get_page(pg);
+	DBG(" ->page count: %d\n", page_count(pg));
+
+	return pg;
+}
+
+static struct vm_operations_struct vdso_vmops = {
+	.close	= vdso_vma_close,
+	.nopage	= vdso_vma_nopage,
+};
+
+/*
+ * This is called from binfmt_elf, we create the special vma for the
+ * vDSO and insert it into the mm struct tree
+ */
+int arch_setup_additional_pages(struct linux_binprm *bprm, int executable_stack)
+{
+	struct mm_struct *mm = current->mm;
+	struct vm_area_struct *vma;
+	unsigned long vdso_pages;
+	unsigned long vdso_base;
+
+	if (test_thread_flag(TIF_32BIT)) {
+		vdso_pages = vdso32_pages;
+		vdso_base = VDSO32_MBASE;
+	} else {
+		vdso_pages = vdso64_pages;
+		vdso_base = VDSO64_MBASE;
+	}
+
+	/* vDSO has a problem and was disabled, just don't "enable" it for the
+	 * process
+	 */
+	if (vdso_pages == 0) {
+		current->thread.vdso_base = 0;
+		return 0;
+	}
+	vma = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL);
+	if (vma == NULL)
+		return -ENOMEM;
+	if (security_vm_enough_memory(vdso_pages)) {
+		kmem_cache_free(vm_area_cachep, vma);
+		return -ENOMEM;
+	}
+	memset(vma, 0, sizeof(*vma));
+
+	/*
+	 * pick a base address for the vDSO in process space. We have a default
+	 * base of 1Mb on which we had a random offset up to 1Mb.
+	 * XXX: Add possibility for a program header to specify that location
+	 */
+	current->thread.vdso_base = vdso_base;
+	/*  + ((unsigned long)vma & 0x000ff000); */
+
+	vma->vm_mm = mm;
+	vma->vm_start = current->thread.vdso_base;
+
+	/*
+	 * the VMA size is one page more than the vDSO since systemcfg
+	 * is mapped in the last one
+	 */
+	vma->vm_end = vma->vm_start + ((vdso_pages + 1) << PAGE_SHIFT);
+
+	/*
+	 * our vma flags don't have VM_WRITE so by default, the process isn't allowed
+	 * to write those pages.
+	 * gdb can break that with ptrace interface, and thus trigger COW on those
+	 * pages but it's then your responsibility to never do that on the "data" page
+	 * of the vDSO or you'll stop getting kernel updates and your nice userland
+	 * gettimeofday will be totally dead. It's fine to use that for setting
+	 * breakpoints in the vDSO code pages though
+	 */
+	vma->vm_flags = VM_READ | VM_EXEC | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC;
+	vma->vm_flags |= mm->def_flags;
+	vma->vm_page_prot = protection_map[vma->vm_flags & 0x7];
+	vma->vm_ops = &vdso_vmops;
+
+	down_write(&mm->mmap_sem);
+	insert_vm_struct(mm, vma);
+	mm->total_vm += (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
+	up_write(&mm->mmap_sem);
+
+	return 0;
+}
+
+static void * __init find_section32(Elf32_Ehdr *ehdr, const char *secname,
+				  unsigned long *size)
+{
+	Elf32_Shdr *sechdrs;
+	unsigned int i;
+	char *secnames;
+
+	/* Grab section headers and strings so we can tell who is who */
+	sechdrs = (void *)ehdr + ehdr->e_shoff;
+	secnames = (void *)ehdr + sechdrs[ehdr->e_shstrndx].sh_offset;
+
+	/* Find the section they want */
+	for (i = 1; i < ehdr->e_shnum; i++) {
+		if (strcmp(secnames+sechdrs[i].sh_name, secname) == 0) {
+			if (size)
+				*size = sechdrs[i].sh_size;
+			return (void *)ehdr + sechdrs[i].sh_offset;
+		}
+	}
+	*size = 0;
+	return NULL;
+}
+
+static void * __init find_section64(Elf64_Ehdr *ehdr, const char *secname,
+				  unsigned long *size)
+{
+	Elf64_Shdr *sechdrs;
+	unsigned int i;
+	char *secnames;
+
+	/* Grab section headers and strings so we can tell who is who */
+	sechdrs = (void *)ehdr + ehdr->e_shoff;
+	secnames = (void *)ehdr + sechdrs[ehdr->e_shstrndx].sh_offset;
+
+	/* Find the section they want */
+	for (i = 1; i < ehdr->e_shnum; i++) {
+		if (strcmp(secnames+sechdrs[i].sh_name, secname) == 0) {
+			if (size)
+				*size = sechdrs[i].sh_size;
+			return (void *)ehdr + sechdrs[i].sh_offset;
+		}
+	}
+	if (size)
+		*size = 0;
+	return NULL;
+}
+
+static Elf32_Sym * __init find_symbol32(struct lib32_elfinfo *lib, const char *symname)
+{
+	unsigned int i;
+	char name[32], *c;
+
+	for (i = 0; i < (lib->dynsymsize / sizeof(Elf32_Sym)); i++) {
+		if (lib->dynsym[i].st_name == 0)
+			continue;
+		strlcpy(name, lib->dynstr + lib->dynsym[i].st_name, 32);
+		c = strchr(name, '@');
+		if (c)
+			*c = 0;
+		if (strcmp(symname, name) == 0)
+			return &lib->dynsym[i];
+	}
+	return NULL;
+}
+
+static Elf64_Sym * __init find_symbol64(struct lib64_elfinfo *lib, const char *symname)
+{
+	unsigned int i;
+	char name[32], *c;
+
+	for (i = 0; i < (lib->dynsymsize / sizeof(Elf64_Sym)); i++) {
+		if (lib->dynsym[i].st_name == 0)
+			continue;
+		strlcpy(name, lib->dynstr + lib->dynsym[i].st_name, 32);
+		c = strchr(name, '@');
+		if (c)
+			*c = 0;
+		if (strcmp(symname, name) == 0)
+			return &lib->dynsym[i];
+	}
+	return NULL;
+}
+
+/* Note that we assume the section is .text and the symbol is relative to
+ * the library base
+ */
+static unsigned long __init find_function32(struct lib32_elfinfo *lib, const char *symname)
+{
+	Elf32_Sym *sym = find_symbol32(lib, symname);
+
+	if (sym == NULL) {
+		printk(KERN_WARNING "vDSO32: function %s not found !\n", symname);
+		return 0;
+	}
+	return sym->st_value - VDSO32_LBASE;
+}
+
+/* Note that we assume the section is .text and the symbol is relative to
+ * the library base
+ */
+static unsigned long __init find_function64(struct lib64_elfinfo *lib, const char *symname)
+{
+	Elf64_Sym *sym = find_symbol64(lib, symname);
+
+	if (sym == NULL) {
+		printk(KERN_WARNING "vDSO64: function %s not found !\n", symname);
+		return 0;
+	}
+#ifdef VDS64_HAS_DESCRIPTORS
+	return *((u64 *)(vdso64_kbase + sym->st_value - VDSO64_LBASE)) - VDSO64_LBASE;
+#else
+	return sym->st_value - VDSO64_LBASE;
+#endif
+}
+
+
+static __init int vdso_do_find_sections(struct lib32_elfinfo *v32,
+					struct lib64_elfinfo *v64)
+{
+	void *sect;
+
+	/*
+	 * Locate symbol tables & text section
+	 */
+
+	v32->dynsym = find_section32(v32->hdr, ".dynsym", &v32->dynsymsize);
+	v32->dynstr = find_section32(v32->hdr, ".dynstr", NULL);
+	if (v32->dynsym == NULL || v32->dynstr == NULL) {
+		printk(KERN_ERR "vDSO32: a required symbol section was not found\n");
+		return -1;
+	}
+	sect = find_section32(v32->hdr, ".text", NULL);
+	if (sect == NULL) {
+		printk(KERN_ERR "vDSO32: the .text section was not found\n");
+		return -1;
+	}
+	v32->text = sect - vdso32_kbase;
+
+	v64->dynsym = find_section64(v64->hdr, ".dynsym", &v64->dynsymsize);
+	v64->dynstr = find_section64(v64->hdr, ".dynstr", NULL);
+	if (v64->dynsym == NULL || v64->dynstr == NULL) {
+		printk(KERN_ERR "vDSO64: a required symbol section was not found\n");
+		return -1;
+	}
+	sect = find_section64(v64->hdr, ".text", NULL);
+	if (sect == NULL) {
+		printk(KERN_ERR "vDSO64: the .text section was not found\n");
+		return -1;
+	}
+	v64->text = sect - vdso64_kbase;
+
+	return 0;
+}
+
+static __init void vdso_setup_trampolines(struct lib32_elfinfo *v32,
+					  struct lib64_elfinfo *v64)
+{
+	/*
+	 * Find signal trampolines
+	 */
+
+	vdso64_rt_sigtramp	= find_function64(v64, "__kernel_sigtramp_rt64");
+	vdso32_sigtramp		= find_function32(v32, "__kernel_sigtramp32");
+	vdso32_rt_sigtramp	= find_function32(v32, "__kernel_sigtramp_rt32");
+}
+
+static __init int vdso_fixup_datapage(struct lib32_elfinfo *v32,
+				       struct lib64_elfinfo *v64)
+{
+	Elf32_Sym *sym32;
+	Elf64_Sym *sym64;
+
+	sym32 = find_symbol32(v32, "__kernel_datapage_offset");
+	if (sym32 == NULL) {
+		printk(KERN_ERR "vDSO32: Can't find symbol __kernel_datapage_offset !\n");
+		return -1;
+	}
+	*((int *)(vdso32_kbase + (sym32->st_value - VDSO32_LBASE))) =
+		(vdso32_pages << PAGE_SHIFT) - (sym32->st_value - VDSO32_LBASE);
+
+       	sym64 = find_symbol64(v64, "__kernel_datapage_offset");
+	if (sym64 == NULL) {
+		printk(KERN_ERR "vDSO64: Can't find symbol __kernel_datapage_offset !\n");
+		return -1;
+	}
+	*((int *)(vdso64_kbase + sym64->st_value - VDSO64_LBASE)) =
+		(vdso64_pages << PAGE_SHIFT) - (sym64->st_value - VDSO64_LBASE);
+
+	return 0;
+}
+
+static int vdso_do_func_patch32(struct lib32_elfinfo *v32,
+				struct lib64_elfinfo *v64,
+				const char *orig, const char *fix)
+{
+	Elf32_Sym *sym32_gen, *sym32_fix;
+
+	sym32_gen = find_symbol32(v32, orig);
+	if (sym32_gen == NULL) {
+		printk(KERN_ERR "vDSO32: Can't find symbol %s !\n", orig);
+		return -1;
+	}
+	sym32_fix = find_symbol32(v32, fix);
+	if (sym32_fix == NULL) {
+		printk(KERN_ERR "vDSO32: Can't find symbol %s !\n", fix);
+		return -1;
+	}
+	sym32_gen->st_value = sym32_fix->st_value;
+	sym32_gen->st_size = sym32_fix->st_size;
+	sym32_gen->st_info = sym32_fix->st_info;
+	sym32_gen->st_other = sym32_fix->st_other;
+	sym32_gen->st_shndx = sym32_fix->st_shndx;
+
+	return 0;
+}
+
+static int vdso_do_func_patch64(struct lib32_elfinfo *v32,
+				struct lib64_elfinfo *v64,
+				const char *orig, const char *fix)
+{
+	Elf64_Sym *sym64_gen, *sym64_fix;
+
+	sym64_gen = find_symbol64(v64, orig);
+	if (sym64_gen == NULL) {
+		printk(KERN_ERR "vDSO64: Can't find symbol %s !\n", orig);
+		return -1;
+	}
+	sym64_fix = find_symbol64(v64, fix);
+	if (sym64_fix == NULL) {
+		printk(KERN_ERR "vDSO64: Can't find symbol %s !\n", fix);
+		return -1;
+	}
+	sym64_gen->st_value = sym64_fix->st_value;
+	sym64_gen->st_size = sym64_fix->st_size;
+	sym64_gen->st_info = sym64_fix->st_info;
+	sym64_gen->st_other = sym64_fix->st_other;
+	sym64_gen->st_shndx = sym64_fix->st_shndx;
+
+	return 0;
+}
+
+static __init int vdso_fixup_alt_funcs(struct lib32_elfinfo *v32,
+				       struct lib64_elfinfo *v64)
+{
+	u32 pvr;
+	int i;
+
+	pvr = mfspr(SPRN_PVR);
+	for (i = 0; i < ARRAY_SIZE(vdso_patches); i++) {
+		struct vdso_patch_def *patch = &vdso_patches[i];
+		int match = (pvr & patch->pvr_mask) == patch->pvr_value;
+
+		DBG("patch %d (mask: %x, pvr: %x) : %s\n",
+		    i, patch->pvr_mask, patch->pvr_value, match ? "match" : "skip");
+
+		if (!match)
+			continue;
+
+		DBG("replacing %s with %s...\n", patch->gen_name, patch->fix_name);
+
+		/*
+		 * Patch the 32 bits and 64 bits symbols. Note that we do not patch
+		 * the "." symbol on 64 bits. It would be easy to do, but doesn't
+		 * seem to be necessary, patching the OPD symbol is enough.
+		 */
+		vdso_do_func_patch32(v32, v64, patch->gen_name, patch->fix_name);
+		vdso_do_func_patch64(v32, v64, patch->gen_name, patch->fix_name);
+	}
+
+	return 0;
+}
+
+
+static __init int vdso_setup(void)
+{
+	struct lib32_elfinfo	v32;
+	struct lib64_elfinfo	v64;
+
+	v32.hdr = vdso32_kbase;
+	v64.hdr = vdso64_kbase;
+
+	if (vdso_do_find_sections(&v32, &v64))
+		return -1;
+
+	if (vdso_fixup_datapage(&v32, &v64))
+		return -1;
+
+	if (vdso_fixup_alt_funcs(&v32, &v64))
+		return -1;
+
+	vdso_setup_trampolines(&v32, &v64);
+
+	return 0;
+}
+
+void __init vdso_init(void)
+{
+	int i;
+
+	vdso64_pages = (&vdso64_end - &vdso64_start) >> PAGE_SHIFT;
+	vdso32_pages = (&vdso32_end - &vdso32_start) >> PAGE_SHIFT;
+
+	DBG("vdso64_kbase: %p, 0x%x pages, vdso32_kbase: %p, 0x%x pages\n",
+	       vdso64_kbase, vdso64_pages, vdso32_kbase, vdso32_pages);
+
+	/*
+	 * Initialize the vDSO images in memory, that is do necessary
+	 * fixups of vDSO symbols, locate trampolines, etc...
+	 */
+	if (vdso_setup()) {
+		printk(KERN_ERR "vDSO setup failure, not enabled !\n");
+		/* XXX should free pages here ? */
+		vdso64_pages = vdso32_pages = 0;
+		return;
+	}
+
+	/* Make sure pages are in the correct state */
+	for (i = 0; i < vdso64_pages; i++) {
+		struct page *pg = virt_to_page(vdso64_kbase + i*PAGE_SIZE);
+		ClearPageReserved(pg);
+		get_page(pg);
+	}
+	for (i = 0; i < vdso32_pages; i++) {
+		struct page *pg = virt_to_page(vdso32_kbase + i*PAGE_SIZE);
+		ClearPageReserved(pg);
+		get_page(pg);
+	}
+}
+
+int in_gate_area_no_task(unsigned long addr)
+{
+	return 0;
+}
+
+int in_gate_area(struct task_struct *task, unsigned long addr)
+{
+	return 0;
+}
+
+struct vm_area_struct *get_gate_vma(struct task_struct *tsk)
+{
+	return NULL;
+}
+
diff -Nru a/arch/ppc64/kernel/vdso32/Makefile b/arch/ppc64/kernel/vdso32/Makefile
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/ppc64/kernel/vdso32/Makefile	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,36 @@
+
+# List of files in the vdso, has to be asm only for now
+
+obj-vdso32 = sigtramp.o gettimeofday.o datapage.o cacheflush.o
+
+# Build rules
+
+targets := $(obj-vdso32) vdso32.so
+obj-vdso32 := $(addprefix $(obj)/, $(obj-vdso32))
+
+
+EXTRA_CFLAGS := -shared -s -fno-common -fno-builtin
+EXTRA_CFLAGS += -nostdlib -Wl,-soname=linux-vdso32.so.1
+EXTRA_AFLAGS := -D__VDSO32__ -s
+
+obj-y += vdso32_wrapper.o
+extra-y += vdso32.lds
+CPPFLAGS_vdso32.lds += -P -C -U$(ARCH)
+
+# Force dependency (incbin is bad)
+$(obj)/vdso32_wrapper.o : $(obj)/vdso32.so
+
+# link rule for the .so file, .lds has to be first
+$(obj)/vdso32.so: $(src)/vdso32.lds $(obj-vdso32)
+	$(call if_changed,vdso32ld)
+
+# assembly rules for the .S files
+$(obj-vdso32): %.o: %.S
+	$(call if_changed_dep,vdso32as)
+
+# actual build commands
+quiet_cmd_vdso32ld = VDSO32L $@
+      cmd_vdso32ld = $(CROSS32CC) $(c_flags) -Wl,-T $^ -o $@
+quiet_cmd_vdso32as = VDSO32A $@
+      cmd_vdso32as = $(CROSS32CC) $(a_flags) -c -o $@ $<
+
diff -Nru a/arch/ppc64/kernel/vdso32/cacheflush.S b/arch/ppc64/kernel/vdso32/cacheflush.S
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/ppc64/kernel/vdso32/cacheflush.S	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,65 @@
+/*
+ * vDSO provided cache flush routines
+ *
+ * Copyright (C) 2004 Benjamin Herrenschmuidt (benh@kernel.crashing.org),
+ *                    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.
+ */
+#include <linux/config.h>
+#include <asm/processor.h>
+#include <asm/ppc_asm.h>
+#include <asm/vdso.h>
+#include <asm/offsets.h>
+
+	.text
+
+/*
+ * Default "generic" version of __kernel_sync_dicache.
+ *
+ * void __kernel_sync_dicache(unsigned long start, unsigned long end)
+ *
+ * Flushes the data cache & invalidate the instruction cache for the
+ * provided range [start, end[
+ *
+ * Note: all CPUs supported by this kernel have a 128 bytes cache
+ * line size so we don't have to peek that info from the datapage
+ */
+V_FUNCTION_BEGIN(__kernel_sync_dicache)
+  .cfi_startproc
+	li	r5,127
+	andc	r6,r3,r5		/* round low to line bdy */
+	subf	r8,r6,r4		/* compute length */
+	add	r8,r8,r5		/* ensure we get enough */
+	srwi.	r8,r8,7			/* compute line count */
+	beqlr				/* nothing to do? */
+	mtctr	r8
+	mr	r3,r6
+1:	dcbst	0,r3
+	addi	r3,r3,128
+	bdnz	1b
+	sync
+	mtctr	r8
+1:	icbi	0,r6
+	addi	r6,r6,128
+	bdnz	1b
+	isync
+	blr
+  .cfi_endproc
+V_FUNCTION_END(__kernel_sync_dicache)
+
+
+/*
+ * POWER5 version of __kernel_sync_dicache
+ */
+V_FUNCTION_BEGIN(__kernel_sync_dicache_p5)
+  .cfi_startproc
+	sync
+	isync
+	blr
+  .cfi_endproc
+V_FUNCTION_END(__kernel_sync_dicache_p5)
+
diff -Nru a/arch/ppc64/kernel/vdso32/datapage.S b/arch/ppc64/kernel/vdso32/datapage.S
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/ppc64/kernel/vdso32/datapage.S	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,68 @@
+/*
+ * Access to the shared data page by the vDSO & syscall map
+ *
+ * Copyright (C) 2004 Benjamin Herrenschmuidt (benh@kernel.crashing.org), 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.
+ */
+
+#include <linux/config.h>
+#include <asm/processor.h>
+#include <asm/ppc_asm.h>
+#include <asm/offsets.h>
+#include <asm/unistd.h>
+#include <asm/vdso.h>
+
+	.text
+V_FUNCTION_BEGIN(__get_datapage)
+  .cfi_startproc
+	/* We don't want that exposed or overridable as we want other objects
+	 * to be able to bl directly to here
+	 */
+	.protected __get_datapage
+	.hidden __get_datapage
+
+	mflr	r0
+  .cfi_register lr,r0
+
+	bcl	20,31,1f
+	.global	__kernel_datapage_offset;
+__kernel_datapage_offset:
+	.long	0
+1:
+	mflr	r3
+	mtlr	r0
+	lwz	r0,0(r3)
+	add	r3,r0,r3
+	blr
+  .cfi_endproc
+V_FUNCTION_END(__get_datapage)
+
+/*
+ * void *__kernel_get_syscall_map(unsigned int *syscall_count) ;
+ *
+ * returns a pointer to the syscall map. the map is agnostic to the
+ * size of "long", unlike kernel bitops, it stores bits from top to
+ * bottom so that memory actually contains a linear bitmap
+ * check for syscall N by testing bit (0x80000000 >> (N & 0x1f)) of
+ * 32 bits int at N >> 5.
+ */
+V_FUNCTION_BEGIN(__kernel_get_syscall_map)
+  .cfi_startproc
+	mflr	r12
+  .cfi_register lr,r12
+
+	mr	r4,r3
+	bl	__get_datapage@local
+	mtlr	r12
+	addi	r3,r3,CFG_SYSCALL_MAP32
+	cmpli	cr0,r4,0
+	beqlr
+	li	r0,__NR_syscalls
+	stw	r0,0(r4)
+	blr
+  .cfi_endproc
+V_FUNCTION_END(__kernel_get_syscall_map)
diff -Nru a/arch/ppc64/kernel/vdso32/gettimeofday.S b/arch/ppc64/kernel/vdso32/gettimeofday.S
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/ppc64/kernel/vdso32/gettimeofday.S	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,139 @@
+/*
+ * Userland implementation of gettimeofday() for 32 bits processes in a
+ * ppc64 kernel for use in the vDSO
+ *
+ * Copyright (C) 2004 Benjamin Herrenschmuidt (benh@kernel.crashing.org), 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.
+ */
+#include <linux/config.h>
+#include <asm/processor.h>
+#include <asm/ppc_asm.h>
+#include <asm/vdso.h>
+#include <asm/offsets.h>
+#include <asm/unistd.h>
+
+	.text
+/*
+ * Exact prototype of gettimeofday
+ *
+ * int __kernel_gettimeofday(struct timeval *tv, struct timezone *tz);
+ *
+ */
+V_FUNCTION_BEGIN(__kernel_gettimeofday)
+  .cfi_startproc
+	mflr	r12
+  .cfi_register lr,r12
+
+	mr	r10,r3			/* r10 saves tv */
+	mr	r11,r4			/* r11 saves tz */
+	bl	__get_datapage@local	/* get data page */
+	mr	r9, r3			/* datapage ptr in r9 */
+	bl	__do_get_xsec@local	/* get xsec from tb & kernel */
+	bne-	2f			/* out of line -> do syscall */
+
+	/* seconds are xsec >> 20 */
+	rlwinm	r5,r4,12,20,31
+	rlwimi	r5,r3,12,0,19
+	stw	r5,TVAL32_TV_SEC(r10)
+
+	/* get remaining xsec and convert to usec. we scale
+	 * up remaining xsec by 12 bits and get the top 32 bits
+	 * of the multiplication
+	 */
+	rlwinm	r5,r4,12,0,19
+	lis	r6,1000000@h
+	ori	r6,r6,1000000@l
+	mulhwu	r5,r5,r6
+	stw	r5,TVAL32_TV_USEC(r10)
+
+	cmpli	cr0,r11,0		/* check if tz is NULL */
+	beq	1f
+	lwz	r4,CFG_TZ_MINUTEWEST(r9)/* fill tz */
+	lwz	r5,CFG_TZ_DSTTIME(r9)
+	stw	r4,TZONE_TZ_MINWEST(r11)
+	stw	r5,TZONE_TZ_DSTTIME(r11)
+
+1:	mtlr	r12
+	blr
+
+2:	mr	r3,r10
+	mr	r4,r11
+	li	r0,__NR_gettimeofday
+	sc
+	b	1b
+  .cfi_endproc
+V_FUNCTION_END(__kernel_gettimeofday)
+
+/*
+ * This is the core of gettimeofday(), it returns the xsec
+ * value in r3 & r4 and expects the datapage ptr (non clobbered)
+ * in r9. clobbers r0,r4,r5,r6,r7,r8
+*/
+__do_get_xsec:
+  .cfi_startproc
+	/* Check for update count & load values. We use the low
+	 * order 32 bits of the update count
+	 */
+1:	lwz	r8,(CFG_TB_UPDATE_COUNT+4)(r9)
+	andi.	r0,r8,1			/* pending update ? loop */
+	bne-	1b
+	xor	r0,r8,r8		/* create dependency */
+	add	r9,r9,r0
+
+	/* Load orig stamp (offset to TB) */
+	lwz	r5,CFG_TB_ORIG_STAMP(r9)
+	lwz	r6,(CFG_TB_ORIG_STAMP+4)(r9)
+
+	/* Get a stable TB value */
+2:	mftbu	r3
+	mftbl	r4
+	mftbu	r0
+	cmpl	cr0,r3,r0
+	bne-	2b
+
+	/* Substract tb orig stamp. If the high part is non-zero, we jump to the
+	 * slow path which call the syscall. If it's ok, then we have our 32 bits
+	 * tb_ticks value in r7
+	 */
+	subfc	r7,r6,r4
+	subfe.	r0,r5,r3
+	bne-	3f
+
+	/* Load scale factor & do multiplication */
+	lwz	r5,CFG_TB_TO_XS(r9)	/* load values */
+	lwz	r6,(CFG_TB_TO_XS+4)(r9)
+	mulhwu	r4,r7,r5
+	mulhwu	r6,r7,r6
+	mullw	r6,r7,r5
+	addc	r6,r6,r0
+
+	/* At this point, we have the scaled xsec value in r4 + XER:CA
+	 * we load & add the stamp since epoch
+	 */
+	lwz	r5,CFG_STAMP_XSEC(r9)
+	lwz	r6,(CFG_STAMP_XSEC+4)(r9)
+	adde	r4,r4,r6
+	addze	r3,r5
+
+	/* We now have our result in r3,r4. We create a fake dependency
+	 * on that result and re-check the counter
+	 */
+	xor	r0,r4,r4
+	add	r9,r9,r0
+	lwz	r0,(CFG_TB_UPDATE_COUNT+4)(r9)
+        cmpl    cr0,r8,r0		/* check if updated */
+	bne-	1b
+
+	/* Warning ! The caller expects CR:EQ to be set to indicate a
+	 * successful calculation (so it won't fallback to the syscall
+	 * method). We have overriden that CR bit in the counter check,
+	 * but fortunately, the loop exit condition _is_ CR:EQ set, so
+	 * we can exit safely here. If you change this code, be careful
+	 * of that side effect.
+	 */
+3:	blr
+  .cfi_endproc
diff -Nru a/arch/ppc64/kernel/vdso32/sigtramp.S b/arch/ppc64/kernel/vdso32/sigtramp.S
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/ppc64/kernel/vdso32/sigtramp.S	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,300 @@
+/*
+ * Signal trampolines for 32 bits processes in a ppc64 kernel for
+ * use in the vDSO
+ *
+ * Copyright (C) 2004 Benjamin Herrenschmuidt (benh@kernel.crashing.org), IBM Corp.
+ * Copyright (C) 2004 Alan Modra (amodra@au.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.
+ */
+#include <linux/config.h>
+#include <asm/processor.h>
+#include <asm/ppc_asm.h>
+#include <asm/unistd.h>
+#include <asm/vdso.h>
+
+	.text
+
+/* The nop here is a hack.  The dwarf2 unwind routines subtract 1 from
+   the return address to get an address in the middle of the presumed
+   call instruction.  Since we don't have a call here, we artifically
+   extend the range covered by the unwind info by adding a nop before
+   the real start.  */
+	nop
+V_FUNCTION_BEGIN(__kernel_sigtramp32)
+.Lsig_start = . - 4
+	li	r0,__NR_sigreturn
+	sc
+.Lsig_end:
+V_FUNCTION_END(__kernel_sigtramp32)
+
+.Lsigrt_start:
+	nop
+V_FUNCTION_BEGIN(__kernel_sigtramp_rt32)
+	li	r0,__NR_rt_sigreturn
+	sc
+.Lsigrt_end:
+V_FUNCTION_END(__kernel_sigtramp_rt32)
+
+	.section .eh_frame,"a",@progbits
+
+/* Register r1 can be found at offset 4 of a pt_regs structure.
+   A pointer to the pt_regs is stored in memory at the old sp plus PTREGS.  */
+#define cfa_save \
+  .byte 0x0f;			/* DW_CFA_def_cfa_expression */		\
+  .uleb128 9f - 1f;		/*   length */				\
+1:									\
+  .byte 0x71; .sleb128 PTREGS;	/*     DW_OP_breg1 */			\
+  .byte 0x06;			/*     DW_OP_deref */			\
+  .byte 0x23; .uleb128 RSIZE;	/*     DW_OP_plus_uconst */		\
+  .byte 0x06;			/*     DW_OP_deref */			\
+9:
+
+/* Register REGNO can be found at offset OFS of a pt_regs structure.
+   A pointer to the pt_regs is stored in memory at the old sp plus PTREGS.  */
+#define rsave(regno, ofs) \
+  .byte 0x10;			/* DW_CFA_expression */			\
+  .uleb128 regno;		/*   regno */				\
+  .uleb128 9f - 1f;		/*   length */				\
+1:									\
+  .byte 0x71; .sleb128 PTREGS;	/*     DW_OP_breg1 */			\
+  .byte 0x06;			/*     DW_OP_deref */			\
+  .ifne ofs;								\
+    .byte 0x23; .uleb128 ofs;	/*     DW_OP_plus_uconst */		\
+  .endif;								\
+9:
+
+/* If msr bit 1<<25 is set, then VMX register REGNO is at offset REGNO*16
+   of the VMX reg struct.  The VMX reg struct is at offset VREGS of
+   the pt_regs struct.  This macro is for REGNO == 0, and contains
+   'subroutines' that the other macros jump to.  */
+#define vsave_msr0(regno) \
+  .byte 0x10;			/* DW_CFA_expression */			\
+  .uleb128 regno + 77;		/*   regno */				\
+  .uleb128 9f - 1f;		/*   length */				\
+1:									\
+  .byte 0x30 + regno;		/*     DW_OP_lit0 */			\
+2:									\
+  .byte 0x40;			/*     DW_OP_lit16 */			\
+  .byte 0x1e;			/*     DW_OP_mul */			\
+3:									\
+  .byte 0x71; .sleb128 PTREGS;	/*     DW_OP_breg1 */			\
+  .byte 0x06;			/*     DW_OP_deref */			\
+  .byte 0x12;			/*     DW_OP_dup */			\
+  .byte 0x23;			/*     DW_OP_plus_uconst */		\
+    .uleb128 33*RSIZE;		/*       msr offset */			\
+  .byte 0x06;			/*     DW_OP_deref */			\
+  .byte 0x0c; .long 1 << 25;	/*     DW_OP_const4u */			\
+  .byte 0x1a;			/*     DW_OP_and */			\
+  .byte 0x12;			/*     DW_OP_dup, ret 0 if bra taken */	\
+  .byte 0x30;			/*     DW_OP_lit0 */			\
+  .byte 0x29;			/*     DW_OP_eq */			\
+  .byte 0x28; .short 0x7fff;	/*     DW_OP_bra to end */		\
+  .byte 0x13;			/*     DW_OP_drop, pop the 0 */		\
+  .byte 0x23; .uleb128 VREGS;	/*     DW_OP_plus_uconst */		\
+  .byte 0x22;			/*     DW_OP_plus */			\
+  .byte 0x2f; .short 0x7fff;	/*     DW_OP_skip to end */		\
+9:
+
+/* If msr bit 1<<25 is set, then VMX register REGNO is at offset REGNO*16
+   of the VMX reg struct.  REGNO is 1 thru 31.  */
+#define vsave_msr1(regno) \
+  .byte 0x10;			/* DW_CFA_expression */			\
+  .uleb128 regno + 77;		/*   regno */				\
+  .uleb128 9f - 1f;		/*   length */				\
+1:									\
+  .byte 0x30 + regno;		/*     DW_OP_lit n */			\
+  .byte 0x2f; .short 2b - 9f;	/*     DW_OP_skip */			\
+9:
+
+/* If msr bit 1<<25 is set, then VMX register REGNO is at offset OFS of
+   the VMX save block.  */
+#define vsave_msr2(regno, ofs) \
+  .byte 0x10;			/* DW_CFA_expression */			\
+  .uleb128 regno + 77;		/*   regno */				\
+  .uleb128 9f - 1f;		/*   length */				\
+1:									\
+  .byte 0x0a; .short ofs;	/*     DW_OP_const2u */			\
+  .byte 0x2f; .short 3b - 9f;	/*     DW_OP_skip */			\
+9:
+
+/* VMX register REGNO is at offset OFS of the VMX save area.  */
+#define vsave(regno, ofs) \
+  .byte 0x10;			/* DW_CFA_expression */			\
+  .uleb128 regno + 77;		/*   regno */				\
+  .uleb128 9f - 1f;		/*   length */				\
+1:									\
+  .byte 0x71; .sleb128 PTREGS;	/*     DW_OP_breg1 */			\
+  .byte 0x06;			/*     DW_OP_deref */			\
+  .byte 0x23; .uleb128 VREGS;	/*     DW_OP_plus_uconst */		\
+  .byte 0x23; .uleb128 ofs;	/*     DW_OP_plus_uconst */		\
+9:
+
+/* This is where the pt_regs pointer can be found on the stack.  */
+#define PTREGS 64+28
+
+/* Size of regs.  */
+#define RSIZE 4
+
+/* This is the offset of the VMX regs.  */
+#define VREGS 48*RSIZE+34*8
+
+/* Describe where general purpose regs are saved.  */
+#define EH_FRAME_GEN \
+  cfa_save;								\
+  rsave ( 0,  0*RSIZE);							\
+  rsave ( 2,  2*RSIZE);							\
+  rsave ( 3,  3*RSIZE);							\
+  rsave ( 4,  4*RSIZE);							\
+  rsave ( 5,  5*RSIZE);							\
+  rsave ( 6,  6*RSIZE);							\
+  rsave ( 7,  7*RSIZE);							\
+  rsave ( 8,  8*RSIZE);							\
+  rsave ( 9,  9*RSIZE);							\
+  rsave (10, 10*RSIZE);							\
+  rsave (11, 11*RSIZE);							\
+  rsave (12, 12*RSIZE);							\
+  rsave (13, 13*RSIZE);							\
+  rsave (14, 14*RSIZE);							\
+  rsave (15, 15*RSIZE);							\
+  rsave (16, 16*RSIZE);							\
+  rsave (17, 17*RSIZE);							\
+  rsave (18, 18*RSIZE);							\
+  rsave (19, 19*RSIZE);							\
+  rsave (20, 20*RSIZE);							\
+  rsave (21, 21*RSIZE);							\
+  rsave (22, 22*RSIZE);							\
+  rsave (23, 23*RSIZE);							\
+  rsave (24, 24*RSIZE);							\
+  rsave (25, 25*RSIZE);							\
+  rsave (26, 26*RSIZE);							\
+  rsave (27, 27*RSIZE);							\
+  rsave (28, 28*RSIZE);							\
+  rsave (29, 29*RSIZE);							\
+  rsave (30, 30*RSIZE);							\
+  rsave (31, 31*RSIZE);							\
+  rsave (67, 32*RSIZE);		/* ap, used as temp for nip */		\
+  rsave (65, 36*RSIZE);		/* lr */				\
+  rsave (70, 38*RSIZE)		/* cr */
+
+/* Describe where the FP regs are saved.  */
+#define EH_FRAME_FP \
+  rsave (32, 48*RSIZE +  0*8);						\
+  rsave (33, 48*RSIZE +  1*8);						\
+  rsave (34, 48*RSIZE +  2*8);						\
+  rsave (35, 48*RSIZE +  3*8);						\
+  rsave (36, 48*RSIZE +  4*8);						\
+  rsave (37, 48*RSIZE +  5*8);						\
+  rsave (38, 48*RSIZE +  6*8);						\
+  rsave (39, 48*RSIZE +  7*8);						\
+  rsave (40, 48*RSIZE +  8*8);						\
+  rsave (41, 48*RSIZE +  9*8);						\
+  rsave (42, 48*RSIZE + 10*8);						\
+  rsave (43, 48*RSIZE + 11*8);						\
+  rsave (44, 48*RSIZE + 12*8);						\
+  rsave (45, 48*RSIZE + 13*8);						\
+  rsave (46, 48*RSIZE + 14*8);						\
+  rsave (47, 48*RSIZE + 15*8);						\
+  rsave (48, 48*RSIZE + 16*8);						\
+  rsave (49, 48*RSIZE + 17*8);						\
+  rsave (50, 48*RSIZE + 18*8);						\
+  rsave (51, 48*RSIZE + 19*8);						\
+  rsave (52, 48*RSIZE + 20*8);						\
+  rsave (53, 48*RSIZE + 21*8);						\
+  rsave (54, 48*RSIZE + 22*8);						\
+  rsave (55, 48*RSIZE + 23*8);						\
+  rsave (56, 48*RSIZE + 24*8);						\
+  rsave (57, 48*RSIZE + 25*8);						\
+  rsave (58, 48*RSIZE + 26*8);						\
+  rsave (59, 48*RSIZE + 27*8);						\
+  rsave (60, 48*RSIZE + 28*8);						\
+  rsave (61, 48*RSIZE + 29*8);						\
+  rsave (62, 48*RSIZE + 30*8);						\
+  rsave (63, 48*RSIZE + 31*8)
+
+/* Describe where the VMX regs are saved.  */
+#ifdef CONFIG_ALTIVEC
+#define EH_FRAME_VMX \
+  vsave_msr0 ( 0);							\
+  vsave_msr1 ( 1);							\
+  vsave_msr1 ( 2);							\
+  vsave_msr1 ( 3);							\
+  vsave_msr1 ( 4);							\
+  vsave_msr1 ( 5);							\
+  vsave_msr1 ( 6);							\
+  vsave_msr1 ( 7);							\
+  vsave_msr1 ( 8);							\
+  vsave_msr1 ( 9);							\
+  vsave_msr1 (10);							\
+  vsave_msr1 (11);							\
+  vsave_msr1 (12);							\
+  vsave_msr1 (13);							\
+  vsave_msr1 (14);							\
+  vsave_msr1 (15);							\
+  vsave_msr1 (16);							\
+  vsave_msr1 (17);							\
+  vsave_msr1 (18);							\
+  vsave_msr1 (19);							\
+  vsave_msr1 (20);							\
+  vsave_msr1 (21);							\
+  vsave_msr1 (22);							\
+  vsave_msr1 (23);							\
+  vsave_msr1 (24);							\
+  vsave_msr1 (25);							\
+  vsave_msr1 (26);							\
+  vsave_msr1 (27);							\
+  vsave_msr1 (28);							\
+  vsave_msr1 (29);							\
+  vsave_msr1 (30);							\
+  vsave_msr1 (31);							\
+  vsave_msr2 (33, 32*16+12);						\
+  vsave      (32, 32*16)
+#else
+#define EH_FRAME_VMX
+#endif
+
+.Lcie:
+	.long .Lcie_end - .Lcie_start
+.Lcie_start:
+	.long 0			/* CIE ID */
+	.byte 1			/* Version number */
+	.string "zR"		/* NUL-terminated augmentation string */
+	.uleb128 4		/* Code alignment factor */
+	.sleb128 -4		/* Data alignment factor */
+	.byte 67		/* Return address register column, ap */
+	.uleb128 1		/* Augmentation value length */
+	.byte 0x1b		/* DW_EH_PE_pcrel | DW_EH_PE_sdata4. */
+	.byte 0x0c,1,0		/* DW_CFA_def_cfa: r1 ofs 0 */
+	.balign 4
+.Lcie_end:
+
+	.long .Lfde0_end - .Lfde0_start
+.Lfde0_start:
+	.long .Lfde0_start - .Lcie	/* CIE pointer. */
+	.long .Lsig_start - .		/* PC start, length */
+	.long .Lsig_end - .Lsig_start
+	.uleb128 0			/* Augmentation */
+	EH_FRAME_GEN
+	EH_FRAME_FP
+	EH_FRAME_VMX
+	.balign 4
+.Lfde0_end:
+
+/* We have a different stack layout for rt_sigreturn.  */
+#undef PTREGS
+#define PTREGS 64+16+128+20+28
+
+	.long .Lfde1_end - .Lfde1_start
+.Lfde1_start:
+	.long .Lfde1_start - .Lcie	/* CIE pointer. */
+	.long .Lsigrt_start - .		/* PC start, length */
+	.long .Lsigrt_end - .Lsigrt_start
+	.uleb128 0			/* Augmentation */
+	EH_FRAME_GEN
+	EH_FRAME_FP
+	EH_FRAME_VMX
+	.balign 4
+.Lfde1_end:
diff -Nru a/arch/ppc64/kernel/vdso32/vdso32.lds.S b/arch/ppc64/kernel/vdso32/vdso32.lds.S
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/ppc64/kernel/vdso32/vdso32.lds.S	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,111 @@
+
+/*
+ * This is the infamous ld script for the 32 bits vdso
+ * library
+ */
+#include <asm/vdso.h>
+
+/* Default link addresses for the vDSOs */
+OUTPUT_FORMAT("elf32-powerpc", "elf32-powerpc", "elf32-powerpc")
+OUTPUT_ARCH(powerpc:common)
+ENTRY(_start)
+
+SECTIONS
+{
+  . = VDSO32_LBASE + SIZEOF_HEADERS;
+  .hash           : { *(.hash) }			:text
+  .dynsym         : { *(.dynsym) }
+  .dynstr         : { *(.dynstr) }
+  .gnu.version    : { *(.gnu.version) }
+  .gnu.version_d  : { *(.gnu.version_d) }
+  .gnu.version_r  : { *(.gnu.version_r) }
+
+  . = ALIGN (16);
+  .text :
+  {
+    *(.text .stub .text.* .gnu.linkonce.t.*)
+  }
+  PROVIDE (__etext = .);
+  PROVIDE (_etext = .);
+  PROVIDE (etext = .);
+
+  /* Other stuff is appended to the text segment: */
+  .rodata		: { *(.rodata .rodata.* .gnu.linkonce.r.*) }
+  .rodata1		: { *(.rodata1) }
+
+  .eh_frame_hdr		: { *(.eh_frame_hdr) }		:text	:eh_frame_hdr
+  .eh_frame		: { KEEP (*(.eh_frame)) }	:text
+  .gcc_except_table	: { *(.gcc_except_table) }
+  .fixup		: { *(.fixup) }
+
+  .got ALIGN(4)		: { *(.got.plt) *(.got) }
+
+  .dynamic		: { *(.dynamic) }		:text	:dynamic
+
+  _end = .;
+  __end = .;
+  PROVIDE (end = .);
+
+
+  /* Stabs debugging sections are here too
+   */
+  .stab 0 : { *(.stab) }
+  .stabstr 0 : { *(.stabstr) }
+  .stab.excl 0 : { *(.stab.excl) }
+  .stab.exclstr 0 : { *(.stab.exclstr) }
+  .stab.index 0 : { *(.stab.index) }
+  .stab.indexstr 0 : { *(.stab.indexstr) }
+  .comment 0 : { *(.comment) }
+  .debug 0 : { *(.debug) }
+  .line 0 : { *(.line) }
+
+  .debug_srcinfo 0 : { *(.debug_srcinfo) }
+  .debug_sfnames 0 : { *(.debug_sfnames) }
+
+  .debug_aranges 0 : { *(.debug_aranges) }
+  .debug_pubnames 0 : { *(.debug_pubnames) }
+
+  .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }
+  .debug_abbrev 0 : { *(.debug_abbrev) }
+  .debug_line 0 : { *(.debug_line) }
+  .debug_frame 0 : { *(.debug_frame) }
+  .debug_str 0 : { *(.debug_str) }
+  .debug_loc 0 : { *(.debug_loc) }
+  .debug_macinfo 0 : { *(.debug_macinfo) }
+
+  .debug_weaknames 0 : { *(.debug_weaknames) }
+  .debug_funcnames 0 : { *(.debug_funcnames) }
+  .debug_typenames 0 : { *(.debug_typenames) }
+  .debug_varnames 0 : { *(.debug_varnames) }
+
+  /DISCARD/ : { *(.note.GNU-stack) }
+  /DISCARD/ : { *(.data .data.* .gnu.linkonce.d.* .sdata*) }
+  /DISCARD/ : { *(.bss .sbss .dynbss .dynsbss) }
+}
+
+
+PHDRS
+{
+  text PT_LOAD FILEHDR PHDRS FLAGS(5); /* PF_R|PF_X */
+  dynamic PT_DYNAMIC FLAGS(4); /* PF_R */
+  eh_frame_hdr 0x6474e550; /* PT_GNU_EH_FRAME, but ld doesn't match the name */
+}
+
+
+/*
+ * This controls what symbols we export from the DSO.
+ */
+VERSION
+{
+  VDSO_VERSION_STRING {
+    global:
+	__kernel_datapage_offset; /* Has to be there for the kernel to find it */
+	__kernel_get_syscall_map;
+	__kernel_gettimeofday;
+	__kernel_sync_dicache;
+	__kernel_sync_dicache_p5;
+	__kernel_sigtramp32;
+	__kernel_sigtramp_rt32;
+    local: *;
+  };
+}
diff -Nru a/arch/ppc64/kernel/vdso32/vdso32_wrapper.S b/arch/ppc64/kernel/vdso32/vdso32_wrapper.S
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/ppc64/kernel/vdso32/vdso32_wrapper.S	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,13 @@
+#include <linux/init.h>
+#include <asm/page.h>
+
+	.section ".data.page_aligned"
+
+	.globl vdso32_start, vdso32_end
+	.balign PAGE_SIZE
+vdso32_start:
+	.incbin "arch/ppc64/kernel/vdso32/vdso32.so"
+	.balign PAGE_SIZE
+vdso32_end:
+
+	.previous
diff -Nru a/arch/ppc64/kernel/vdso64/Makefile b/arch/ppc64/kernel/vdso64/Makefile
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/ppc64/kernel/vdso64/Makefile	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,35 @@
+# List of files in the vdso, has to be asm only for now
+
+obj-vdso64 = sigtramp.o gettimeofday.o datapage.o cacheflush.o
+
+# Build rules
+
+targets := $(obj-vdso64) vdso64.so
+obj-vdso64 := $(addprefix $(obj)/, $(obj-vdso64))
+
+EXTRA_CFLAGS := -shared -s -fno-common -fno-builtin
+EXTRA_CFLAGS +=  -nostdlib -Wl,-soname=linux-vdso64.so.1
+EXTRA_AFLAGS := -D__VDSO64__ -s
+
+obj-y += vdso64_wrapper.o
+extra-y += vdso64.lds
+CPPFLAGS_vdso64.lds += -P -C -U$(ARCH)
+
+# Force dependency (incbin is bad)
+$(obj)/vdso64_wrapper.o : $(obj)/vdso64.so
+
+# link rule for the .so file, .lds has to be first
+$(obj)/vdso64.so: $(src)/vdso64.lds $(obj-vdso64)
+	$(call if_changed,vdso64ld)
+
+# assembly rules for the .S files
+$(obj-vdso64): %.o: %.S
+	$(call if_changed_dep,vdso64as)
+
+# actual build commands
+quiet_cmd_vdso64ld = VDSO64L $@
+      cmd_vdso64ld = $(CC) $(c_flags) -Wl,-T $^ -o $@
+quiet_cmd_vdso64as = VDSO64A $@
+      cmd_vdso64as = $(CC) $(a_flags) -c -o $@ $<
+
+
diff -Nru a/arch/ppc64/kernel/vdso64/cacheflush.S b/arch/ppc64/kernel/vdso64/cacheflush.S
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/ppc64/kernel/vdso64/cacheflush.S	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,64 @@
+/*
+ * vDSO provided cache flush routines
+ *
+ * Copyright (C) 2004 Benjamin Herrenschmuidt (benh@kernel.crashing.org),
+ *                    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.
+ */
+#include <linux/config.h>
+#include <asm/processor.h>
+#include <asm/ppc_asm.h>
+#include <asm/vdso.h>
+#include <asm/offsets.h>
+
+	.text
+
+/*
+ * Default "generic" version of __kernel_sync_dicache.
+ *
+ * void __kernel_sync_dicache(unsigned long start, unsigned long end)
+ *
+ * Flushes the data cache & invalidate the instruction cache for the
+ * provided range [start, end[
+ *
+ * Note: all CPUs supported by this kernel have a 128 bytes cache
+ * line size so we don't have to peek that info from the datapage
+ */
+V_FUNCTION_BEGIN(__kernel_sync_dicache)
+  .cfi_startproc
+	li	r5,127
+	andc	r6,r3,r5		/* round low to line bdy */
+	subf	r8,r6,r4		/* compute length */
+	add	r8,r8,r5		/* ensure we get enough */
+	srwi.	r8,r8,7			/* compute line count */
+	beqlr				/* nothing to do? */
+	mtctr	r8
+	mr	r3,r6
+1:	dcbst	0,r3
+	addi	r3,r3,128
+	bdnz	1b
+	sync
+	mtctr	r8
+1:	icbi	0,r6
+	addi	r6,r6,128
+	bdnz	1b
+	isync
+	blr
+  .cfi_endproc
+V_FUNCTION_END(__kernel_sync_dicache)
+
+
+/*
+ * POWER5 version of __kernel_sync_dicache
+ */
+V_FUNCTION_BEGIN(__kernel_sync_dicache_p5)
+  .cfi_startproc
+	sync
+	isync
+	blr
+  .cfi_endproc
+V_FUNCTION_END(__kernel_sync_dicache_p5)
diff -Nru a/arch/ppc64/kernel/vdso64/datapage.S b/arch/ppc64/kernel/vdso64/datapage.S
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/ppc64/kernel/vdso64/datapage.S	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,68 @@
+/*
+ * Access to the shared data page by the vDSO & syscall map
+ *
+ * Copyright (C) 2004 Benjamin Herrenschmuidt (benh@kernel.crashing.org), 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.
+ */
+
+#include <linux/config.h>
+#include <asm/processor.h>
+#include <asm/ppc_asm.h>
+#include <asm/offsets.h>
+#include <asm/unistd.h>
+#include <asm/vdso.h>
+
+	.text
+V_FUNCTION_BEGIN(__get_datapage)
+  .cfi_startproc
+	/* We don't want that exposed or overridable as we want other objects
+	 * to be able to bl directly to here
+	 */
+	.protected __get_datapage
+	.hidden __get_datapage
+
+	mflr	r0
+  .cfi_register lr,r0
+
+	bcl	20,31,1f
+	.global	__kernel_datapage_offset;
+__kernel_datapage_offset:
+	.long	0
+1:
+	mflr	r3
+	mtlr	r0
+	lwz	r0,0(r3)
+	add	r3,r0,r3
+	blr
+  .cfi_endproc
+V_FUNCTION_END(__get_datapage)
+
+/*
+ * void *__kernel_get_syscall_map(unsigned int *syscall_count) ;
+ *
+ * returns a pointer to the syscall map. the map is agnostic to the
+ * size of "long", unlike kernel bitops, it stores bits from top to
+ * bottom so that memory actually contains a linear bitmap
+ * check for syscall N by testing bit (0x80000000 >> (N & 0x1f)) of
+ * 32 bits int at N >> 5.
+ */
+V_FUNCTION_BEGIN(__kernel_get_syscall_map)
+  .cfi_startproc
+	mflr	r12
+  .cfi_register lr,r12
+
+	mr	r4,r3
+	bl	V_LOCAL_FUNC(__get_datapage)
+	mtlr	r12
+	addi	r3,r3,CFG_SYSCALL_MAP64
+	cmpli	cr0,r4,0
+	beqlr
+	li	r0,__NR_syscalls
+	stw	r0,0(r4)
+	blr
+  .cfi_endproc
+V_FUNCTION_END(__kernel_get_syscall_map)
diff -Nru a/arch/ppc64/kernel/vdso64/gettimeofday.S b/arch/ppc64/kernel/vdso64/gettimeofday.S
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/ppc64/kernel/vdso64/gettimeofday.S	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,91 @@
+/*
+ * Userland implementation of gettimeofday() for 64 bits processes in a
+ * ppc64 kernel for use in the vDSO
+ *
+ * Copyright (C) 2004 Benjamin Herrenschmuidt (benh@kernel.crashing.org),
+ *                    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.
+ */
+#include <linux/config.h>
+#include <asm/processor.h>
+#include <asm/ppc_asm.h>
+#include <asm/vdso.h>
+#include <asm/offsets.h>
+
+	.text
+/*
+ * Exact prototype of gettimeofday
+ *
+ * int __kernel_gettimeofday(struct timeval *tv, struct timezone *tz);
+ *
+ */
+V_FUNCTION_BEGIN(__kernel_gettimeofday)
+  .cfi_startproc
+	mflr	r12
+  .cfi_register lr,r12
+
+	mr	r11,r3			/* r11 holds tv */
+	mr	r10,r4			/* r10 holds tz */
+	bl	V_LOCAL_FUNC(__get_datapage)		/* get data page */
+	bl	V_LOCAL_FUNC(__do_get_xsec)		/* get xsec from tb & kernel */
+	lis     r7,15			/* r7 = 1000000 = USEC_PER_SEC */
+	ori     r7,r7,16960
+	rldicl  r5,r4,44,20		/* r5 = sec = xsec / XSEC_PER_SEC */
+	rldicr  r6,r5,20,43		/* r6 = sec * XSEC_PER_SEC */
+	std	r5,TVAL64_TV_SEC(r11)	/* store sec in tv */
+	subf	r0,r6,r4		/* r0 = xsec = (xsec - r6) */
+	mulld   r0,r0,r7		/* usec = (xsec * USEC_PER_SEC) / XSEC_PER_SEC */
+	rldicl  r0,r0,44,20
+	cmpldi	cr0,r10,0		/* check if tz is NULL */
+	std	r0,TVAL64_TV_USEC(r11)	/* store usec in tv */
+	beq	1f
+	lwz	r4,CFG_TZ_MINUTEWEST(r3)/* fill tz */
+	lwz	r5,CFG_TZ_DSTTIME(r3)
+	stw	r4,TZONE_TZ_MINWEST(r10)
+	stw	r5,TZONE_TZ_DSTTIME(r10)
+1:	mtlr	r12
+	li	r3,0			/* always success */
+	blr
+  .cfi_endproc
+V_FUNCTION_END(__kernel_gettimeofday)
+
+
+/*
+ * This is the core of gettimeofday(), it returns the xsec
+ * value in r4 and expects the datapage ptr (non clobbered)
+ * in r3. clobbers r0,r4,r5,r6,r7,r8
+*/
+V_FUNCTION_BEGIN(__do_get_xsec)
+  .cfi_startproc
+	/* check for update count & load values */
+1:	ld	r7,CFG_TB_UPDATE_COUNT(r3)
+	andi.	r0,r4,1			/* pending update ? loop */
+	bne-	1b
+	xor	r0,r4,r4		/* create dependency */
+	add	r3,r3,r0
+
+	/* Get TB & offset it */
+	mftb	r8
+	ld	r9,CFG_TB_ORIG_STAMP(r3)
+	subf	r8,r9,r8
+
+	/* Scale result */
+	ld	r5,CFG_TB_TO_XS(r3)
+	mulhdu	r8,r8,r5
+
+	/* Add stamp since epoch */
+	ld	r6,CFG_STAMP_XSEC(r3)
+	add	r4,r6,r8
+
+	xor	r0,r4,r4
+	add	r3,r3,r0
+	ld	r0,CFG_TB_UPDATE_COUNT(r3)
+        cmpld   cr0,r0,r7		/* check if updated */
+	bne-	1b
+	blr
+  .cfi_endproc
+V_FUNCTION_END(__do_get_xsec)
diff -Nru a/arch/ppc64/kernel/vdso64/sigtramp.S b/arch/ppc64/kernel/vdso64/sigtramp.S
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/ppc64/kernel/vdso64/sigtramp.S	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,294 @@
+/*
+ * Signal trampoline for 64 bits processes in a ppc64 kernel for
+ * use in the vDSO
+ *
+ * Copyright (C) 2004 Benjamin Herrenschmuidt (benh@kernel.crashing.org), IBM Corp.
+ * Copyright (C) 2004 Alan Modra (amodra@au.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.
+ */
+#include <linux/config.h>
+#include <asm/processor.h>
+#include <asm/ppc_asm.h>
+#include <asm/unistd.h>
+#include <asm/vdso.h>
+
+	.text
+
+/* The nop here is a hack.  The dwarf2 unwind routines subtract 1 from
+   the return address to get an address in the middle of the presumed
+   call instruction.  Since we don't have a call here, we artifically
+   extend the range covered by the unwind info by padding before the
+   real start.  */
+	nop
+	.balign 8
+V_FUNCTION_BEGIN(__kernel_sigtramp_rt64)
+.Lsigrt_start = . - 4
+	addi	r1, r1, __SIGNAL_FRAMESIZE
+	li	r0,__NR_rt_sigreturn
+	sc
+.Lsigrt_end:
+V_FUNCTION_END(__kernel_sigtramp_rt64)
+/* The ".balign 8" above and the following zeros mimic the old stack
+   trampoline layout.  The last magic value is the ucontext pointer,
+   chosen in such a way that older libgcc unwind code returns a zero
+   for a sigcontext pointer.  */
+	.long 0,0,0
+	.quad 0,-21*8
+
+/* Register r1 can be found at offset 8 of a pt_regs structure.
+   A pointer to the pt_regs is stored in memory at the old sp plus PTREGS.  */
+#define cfa_save \
+  .byte 0x0f;			/* DW_CFA_def_cfa_expression */		\
+  .uleb128 9f - 1f;		/*   length */				\
+1:									\
+  .byte 0x71; .sleb128 PTREGS;	/*     DW_OP_breg1 */			\
+  .byte 0x06;			/*     DW_OP_deref */			\
+  .byte 0x23; .uleb128 RSIZE;	/*     DW_OP_plus_uconst */		\
+  .byte 0x06;			/*     DW_OP_deref */			\
+9:
+
+/* Register REGNO can be found at offset OFS of a pt_regs structure.
+   A pointer to the pt_regs is stored in memory at the old sp plus PTREGS.  */
+#define rsave(regno, ofs) \
+  .byte 0x10;			/* DW_CFA_expression */			\
+  .uleb128 regno;		/*   regno */				\
+  .uleb128 9f - 1f;		/*   length */				\
+1:									\
+  .byte 0x71; .sleb128 PTREGS;	/*     DW_OP_breg1 */			\
+  .byte 0x06;			/*     DW_OP_deref */			\
+  .ifne ofs;								\
+    .byte 0x23; .uleb128 ofs;	/*     DW_OP_plus_uconst */		\
+  .endif;								\
+9:
+
+/* If msr bit 1<<25 is set, then VMX register REGNO is at offset REGNO*16
+   of the VMX reg struct.  A pointer to the VMX reg struct is at VREGS in
+   the pt_regs struct.  This macro is for REGNO == 0, and contains
+   'subroutines' that the other macros jump to.  */
+#define vsave_msr0(regno) \
+  .byte 0x10;			/* DW_CFA_expression */			\
+  .uleb128 regno + 77;		/*   regno */				\
+  .uleb128 9f - 1f;		/*   length */				\
+1:									\
+  .byte 0x30 + regno;		/*     DW_OP_lit0 */			\
+2:									\
+  .byte 0x40;			/*     DW_OP_lit16 */			\
+  .byte 0x1e;			/*     DW_OP_mul */			\
+3:									\
+  .byte 0x71; .sleb128 PTREGS;	/*     DW_OP_breg1 */			\
+  .byte 0x06;			/*     DW_OP_deref */			\
+  .byte 0x12;			/*     DW_OP_dup */			\
+  .byte 0x23;			/*     DW_OP_plus_uconst */		\
+    .uleb128 33*RSIZE;		/*       msr offset */			\
+  .byte 0x06;			/*     DW_OP_deref */			\
+  .byte 0x0c; .long 1 << 25;	/*     DW_OP_const4u */			\
+  .byte 0x1a;			/*     DW_OP_and */			\
+  .byte 0x12;			/*     DW_OP_dup, ret 0 if bra taken */	\
+  .byte 0x30;			/*     DW_OP_lit0 */			\
+  .byte 0x29;			/*     DW_OP_eq */			\
+  .byte 0x28; .short 0x7fff;	/*     DW_OP_bra to end */		\
+  .byte 0x13;			/*     DW_OP_drop, pop the 0 */		\
+  .byte 0x23; .uleb128 VREGS;	/*     DW_OP_plus_uconst */		\
+  .byte 0x06;			/*     DW_OP_deref */			\
+  .byte 0x22;			/*     DW_OP_plus */			\
+  .byte 0x2f; .short 0x7fff;	/*     DW_OP_skip to end */		\
+9:
+
+/* If msr bit 1<<25 is set, then VMX register REGNO is at offset REGNO*16
+   of the VMX reg struct.  REGNO is 1 thru 31.  */
+#define vsave_msr1(regno) \
+  .byte 0x10;			/* DW_CFA_expression */			\
+  .uleb128 regno + 77;		/*   regno */				\
+  .uleb128 9f - 1f;		/*   length */				\
+1:									\
+  .byte 0x30 + regno;		/*     DW_OP_lit n */			\
+  .byte 0x2f; .short 2b - 9f;	/*     DW_OP_skip */			\
+9:
+
+/* If msr bit 1<<25 is set, then VMX register REGNO is at offset OFS of
+   the VMX save block.  */
+#define vsave_msr2(regno, ofs) \
+  .byte 0x10;			/* DW_CFA_expression */			\
+  .uleb128 regno + 77;		/*   regno */				\
+  .uleb128 9f - 1f;		/*   length */				\
+1:									\
+  .byte 0x0a; .short ofs;	/*     DW_OP_const2u */			\
+  .byte 0x2f; .short 3b - 9f;	/*     DW_OP_skip */			\
+9:
+
+/* VMX register REGNO is at offset OFS of the VMX save area.  */
+#define vsave(regno, ofs) \
+  .byte 0x10;			/* DW_CFA_expression */			\
+  .uleb128 regno + 77;		/*   regno */				\
+  .uleb128 9f - 1f;		/*   length */				\
+1:									\
+  .byte 0x71; .sleb128 PTREGS;	/*     DW_OP_breg1 */			\
+  .byte 0x06;			/*     DW_OP_deref */			\
+  .byte 0x23; .uleb128 VREGS;	/*     DW_OP_plus_uconst */		\
+  .byte 0x06;			/*     DW_OP_deref */			\
+  .byte 0x23; .uleb128 ofs;	/*     DW_OP_plus_uconst */		\
+9:
+
+/* This is where the pt_regs pointer can be found on the stack.  */
+#define PTREGS 128+168+56
+
+/* Size of regs.  */
+#define RSIZE 8
+
+/* This is the offset of the VMX reg pointer.  */
+#define VREGS 48*RSIZE+33*8
+
+/* Describe where general purpose regs are saved.  */
+#define EH_FRAME_GEN \
+  cfa_save;								\
+  rsave ( 0,  0*RSIZE);							\
+  rsave ( 2,  2*RSIZE);							\
+  rsave ( 3,  3*RSIZE);							\
+  rsave ( 4,  4*RSIZE);							\
+  rsave ( 5,  5*RSIZE);							\
+  rsave ( 6,  6*RSIZE);							\
+  rsave ( 7,  7*RSIZE);							\
+  rsave ( 8,  8*RSIZE);							\
+  rsave ( 9,  9*RSIZE);							\
+  rsave (10, 10*RSIZE);							\
+  rsave (11, 11*RSIZE);							\
+  rsave (12, 12*RSIZE);							\
+  rsave (13, 13*RSIZE);							\
+  rsave (14, 14*RSIZE);							\
+  rsave (15, 15*RSIZE);							\
+  rsave (16, 16*RSIZE);							\
+  rsave (17, 17*RSIZE);							\
+  rsave (18, 18*RSIZE);							\
+  rsave (19, 19*RSIZE);							\
+  rsave (20, 20*RSIZE);							\
+  rsave (21, 21*RSIZE);							\
+  rsave (22, 22*RSIZE);							\
+  rsave (23, 23*RSIZE);							\
+  rsave (24, 24*RSIZE);							\
+  rsave (25, 25*RSIZE);							\
+  rsave (26, 26*RSIZE);							\
+  rsave (27, 27*RSIZE);							\
+  rsave (28, 28*RSIZE);							\
+  rsave (29, 29*RSIZE);							\
+  rsave (30, 30*RSIZE);							\
+  rsave (31, 31*RSIZE);							\
+  rsave (67, 32*RSIZE);		/* ap, used as temp for nip */		\
+  rsave (65, 36*RSIZE);		/* lr */				\
+  rsave (70, 38*RSIZE)		/* cr */
+
+/* Describe where the FP regs are saved.  */
+#define EH_FRAME_FP \
+  rsave (32, 48*RSIZE +  0*8);						\
+  rsave (33, 48*RSIZE +  1*8);						\
+  rsave (34, 48*RSIZE +  2*8);						\
+  rsave (35, 48*RSIZE +  3*8);						\
+  rsave (36, 48*RSIZE +  4*8);						\
+  rsave (37, 48*RSIZE +  5*8);						\
+  rsave (38, 48*RSIZE +  6*8);						\
+  rsave (39, 48*RSIZE +  7*8);						\
+  rsave (40, 48*RSIZE +  8*8);						\
+  rsave (41, 48*RSIZE +  9*8);						\
+  rsave (42, 48*RSIZE + 10*8);						\
+  rsave (43, 48*RSIZE + 11*8);						\
+  rsave (44, 48*RSIZE + 12*8);						\
+  rsave (45, 48*RSIZE + 13*8);						\
+  rsave (46, 48*RSIZE + 14*8);						\
+  rsave (47, 48*RSIZE + 15*8);						\
+  rsave (48, 48*RSIZE + 16*8);						\
+  rsave (49, 48*RSIZE + 17*8);						\
+  rsave (50, 48*RSIZE + 18*8);						\
+  rsave (51, 48*RSIZE + 19*8);						\
+  rsave (52, 48*RSIZE + 20*8);						\
+  rsave (53, 48*RSIZE + 21*8);						\
+  rsave (54, 48*RSIZE + 22*8);						\
+  rsave (55, 48*RSIZE + 23*8);						\
+  rsave (56, 48*RSIZE + 24*8);						\
+  rsave (57, 48*RSIZE + 25*8);						\
+  rsave (58, 48*RSIZE + 26*8);						\
+  rsave (59, 48*RSIZE + 27*8);						\
+  rsave (60, 48*RSIZE + 28*8);						\
+  rsave (61, 48*RSIZE + 29*8);						\
+  rsave (62, 48*RSIZE + 30*8);						\
+  rsave (63, 48*RSIZE + 31*8)
+
+/* Describe where the VMX regs are saved.  */
+#ifdef CONFIG_ALTIVEC
+#define EH_FRAME_VMX \
+  vsave_msr0 ( 0);							\
+  vsave_msr1 ( 1);							\
+  vsave_msr1 ( 2);							\
+  vsave_msr1 ( 3);							\
+  vsave_msr1 ( 4);							\
+  vsave_msr1 ( 5);							\
+  vsave_msr1 ( 6);							\
+  vsave_msr1 ( 7);							\
+  vsave_msr1 ( 8);							\
+  vsave_msr1 ( 9);							\
+  vsave_msr1 (10);							\
+  vsave_msr1 (11);							\
+  vsave_msr1 (12);							\
+  vsave_msr1 (13);							\
+  vsave_msr1 (14);							\
+  vsave_msr1 (15);							\
+  vsave_msr1 (16);							\
+  vsave_msr1 (17);							\
+  vsave_msr1 (18);							\
+  vsave_msr1 (19);							\
+  vsave_msr1 (20);							\
+  vsave_msr1 (21);							\
+  vsave_msr1 (22);							\
+  vsave_msr1 (23);							\
+  vsave_msr1 (24);							\
+  vsave_msr1 (25);							\
+  vsave_msr1 (26);							\
+  vsave_msr1 (27);							\
+  vsave_msr1 (28);							\
+  vsave_msr1 (29);							\
+  vsave_msr1 (30);							\
+  vsave_msr1 (31);							\
+  vsave_msr2 (33, 32*16+12);						\
+  vsave      (32, 33*16)
+#else
+#define EH_FRAME_VMX
+#endif
+
+	.section .eh_frame,"a",@progbits
+.Lcie:
+	.long .Lcie_end - .Lcie_start
+.Lcie_start:
+	.long 0			/* CIE ID */
+	.byte 1			/* Version number */
+	.string "zR"		/* NUL-terminated augmentation string */
+	.uleb128 4		/* Code alignment factor */
+	.sleb128 -8		/* Data alignment factor */
+	.byte 67		/* Return address register column, ap */
+	.uleb128 1		/* Augmentation value length */
+	.byte 0x14		/* DW_EH_PE_pcrel | DW_EH_PE_udata8. */
+	.byte 0x0c,1,0		/* DW_CFA_def_cfa: r1 ofs 0 */
+	.balign 8
+.Lcie_end:
+
+	.long .Lfde0_end - .Lfde0_start
+.Lfde0_start:
+	.long .Lfde0_start - .Lcie	/* CIE pointer. */
+	.quad .Lsigrt_start - .		/* PC start, length */
+	.quad .Lsigrt_end - .Lsigrt_start
+	.uleb128 0			/* Augmentation */
+	EH_FRAME_GEN
+	EH_FRAME_FP
+	EH_FRAME_VMX
+# Do we really need to describe the frame at this point?  ie. will
+# we ever have some call chain that returns somewhere past the addi?
+# I don't think so, since gcc doesn't support async signals.
+#	.byte 0x41		/* DW_CFA_advance_loc 1*4 */
+#undef PTREGS
+#define PTREGS 168+56
+#	EH_FRAME_GEN
+#	EH_FRAME_FP
+#	EH_FRAME_VMX
+	.balign 8
+.Lfde0_end:
diff -Nru a/arch/ppc64/kernel/vdso64/vdso64.lds.S b/arch/ppc64/kernel/vdso64/vdso64.lds.S
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/ppc64/kernel/vdso64/vdso64.lds.S	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,110 @@
+/*
+ * This is the infamous ld script for the 64 bits vdso
+ * library
+ */
+#include <asm/vdso.h>
+
+OUTPUT_FORMAT("elf64-powerpc", "elf64-powerpc", "elf64-powerpc")
+OUTPUT_ARCH(powerpc:common64)
+ENTRY(_start)
+
+SECTIONS
+{
+  . = VDSO64_LBASE + SIZEOF_HEADERS;
+  .hash           : { *(.hash) }		:text
+  .dynsym         : { *(.dynsym) }
+  .dynstr         : { *(.dynstr) }
+  .gnu.version    : { *(.gnu.version) }
+  .gnu.version_d  : { *(.gnu.version_d) }
+  .gnu.version_r  : { *(.gnu.version_r) }
+
+  . = ALIGN (16);
+  .text           :
+  {
+    *(.text .stub .text.* .gnu.linkonce.t.*)
+    *(.sfpr .glink)
+  }
+  PROVIDE (__etext = .);
+  PROVIDE (_etext = .);
+  PROVIDE (etext = .);
+
+  /* Other stuff is appended to the text segment: */
+  .rodata         : { *(.rodata .rodata.* .gnu.linkonce.r.*) }
+  .rodata1        : { *(.rodata1) }
+  .eh_frame_hdr   : { *(.eh_frame_hdr) }	:text	:eh_frame_hdr
+  .eh_frame       : { KEEP (*(.eh_frame)) }	:text
+  .gcc_except_table   : { *(.gcc_except_table) }
+
+  .opd           ALIGN(8) : { KEEP (*(.opd)) }
+  .got		 ALIGN(8) : { *(.got .toc) }
+  .rela.dyn	 ALIGN(8) : { *(.rela.dyn) }
+
+  .dynamic        : { *(.dynamic) }		:text	:dynamic
+
+  _end = .;
+  PROVIDE (end = .);
+
+  /* Stabs debugging sections are here too
+   */
+  .stab          0 : { *(.stab) }
+  .stabstr       0 : { *(.stabstr) }
+  .stab.excl     0 : { *(.stab.excl) }
+  .stab.exclstr  0 : { *(.stab.exclstr) }
+  .stab.index    0 : { *(.stab.index) }
+  .stab.indexstr 0 : { *(.stab.indexstr) }
+  .comment       0 : { *(.comment) }
+  /* DWARF debug sectio/ns.
+     Symbols in the DWARF debugging sections are relative to the beginning
+     of the section so we begin them at 0.  */
+  /* DWARF 1 */
+  .debug          0 : { *(.debug) }
+  .line           0 : { *(.line) }
+  /* GNU DWARF 1 extensions */
+  .debug_srcinfo  0 : { *(.debug_srcinfo) }
+  .debug_sfnames  0 : { *(.debug_sfnames) }
+  /* DWARF 1.1 and DWARF 2 */
+  .debug_aranges  0 : { *(.debug_aranges) }
+  .debug_pubnames 0 : { *(.debug_pubnames) }
+  /* DWARF 2 */
+  .debug_info     0 : { *(.debug_info .gnu.linkonce.wi.*) }
+  .debug_abbrev   0 : { *(.debug_abbrev) }
+  .debug_line     0 : { *(.debug_line) }
+  .debug_frame    0 : { *(.debug_frame) }
+  .debug_str      0 : { *(.debug_str) }
+  .debug_loc      0 : { *(.debug_loc) }
+  .debug_macinfo  0 : { *(.debug_macinfo) }
+  /* SGI/MIPS DWARF 2 extensions */
+  .debug_weaknames 0 : { *(.debug_weaknames) }
+  .debug_funcnames 0 : { *(.debug_funcnames) }
+  .debug_typenames 0 : { *(.debug_typenames) }
+  .debug_varnames  0 : { *(.debug_varnames) }
+
+  /DISCARD/ : { *(.note.GNU-stack) }
+  /DISCARD/ : { *(.branch_lt) }
+  /DISCARD/ : { *(.data .data.* .gnu.linkonce.d.*) }
+  /DISCARD/ : { *(.bss .sbss .dynbss .dynsbss) }
+}
+
+PHDRS
+{
+  text PT_LOAD FILEHDR PHDRS FLAGS(5); /* PF_R|PF_X */
+  dynamic PT_DYNAMIC FLAGS(4); /* PF_R */
+  eh_frame_hdr 0x6474e550; /* PT_GNU_EH_FRAME, but ld doesn't match the name */
+}
+
+/*
+ * This controls what symbols we export from the DSO.
+ */
+VERSION
+{
+  VDSO_VERSION_STRING {
+    global:
+	__kernel_datapage_offset; /* Has to be there for the kernel to find it */
+	__kernel_get_syscall_map;
+    	__kernel_gettimeofday;
+	__kernel_sync_dicache;
+	__kernel_sync_dicache_p5;
+	__kernel_sigtramp_rt64;
+    local: *;
+  };
+}
diff -Nru a/arch/ppc64/kernel/vdso64/vdso64_wrapper.S b/arch/ppc64/kernel/vdso64/vdso64_wrapper.S
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/ppc64/kernel/vdso64/vdso64_wrapper.S	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,13 @@
+#include <linux/init.h>
+#include <asm/page.h>
+
+	.section ".data.page_aligned"
+
+	.globl vdso64_start, vdso64_end
+	.balign PAGE_SIZE
+vdso64_start:
+	.incbin "arch/ppc64/kernel/vdso64/vdso64.so"
+	.balign PAGE_SIZE
+vdso64_end:
+
+	.previous
diff -Nru a/arch/ppc64/kernel/vio.c b/arch/ppc64/kernel/vio.c
--- a/arch/ppc64/kernel/vio.c	2005-03-11 12:51:42 -08:00
+++ b/arch/ppc64/kernel/vio.c	2005-03-11 12:51:42 -08:00
@@ -557,48 +557,61 @@
 EXPORT_SYMBOL(vio_disable_interrupts);
 #endif
 
-dma_addr_t vio_map_single(struct vio_dev *dev, void *vaddr,
+static dma_addr_t vio_map_single(struct device *dev, void *vaddr,
 			  size_t size, enum dma_data_direction direction)
 {
-	return iommu_map_single(dev->iommu_table, vaddr, size, direction);
+	return iommu_map_single(to_vio_dev(dev)->iommu_table, vaddr, size,
+			direction);
 }
-EXPORT_SYMBOL(vio_map_single);
 
-void vio_unmap_single(struct vio_dev *dev, dma_addr_t dma_handle,
+static void vio_unmap_single(struct device *dev, dma_addr_t dma_handle,
 		      size_t size, enum dma_data_direction direction)
 {
-	iommu_unmap_single(dev->iommu_table, dma_handle, size, direction);
+	iommu_unmap_single(to_vio_dev(dev)->iommu_table, dma_handle, size,
+			direction);
 }
-EXPORT_SYMBOL(vio_unmap_single);
 
-int vio_map_sg(struct vio_dev *vdev, struct scatterlist *sglist, int nelems,
-	       enum dma_data_direction direction)
+static int vio_map_sg(struct device *dev, struct scatterlist *sglist,
+		int nelems, enum dma_data_direction direction)
 {
-	return iommu_map_sg(&vdev->dev, vdev->iommu_table, sglist,
+	return iommu_map_sg(dev, to_vio_dev(dev)->iommu_table, sglist,
 			nelems, direction);
 }
-EXPORT_SYMBOL(vio_map_sg);
 
-void vio_unmap_sg(struct vio_dev *vdev, struct scatterlist *sglist, int nelems,
-		  enum dma_data_direction direction)
+static void vio_unmap_sg(struct device *dev, struct scatterlist *sglist,
+		int nelems, enum dma_data_direction direction)
 {
-	iommu_unmap_sg(vdev->iommu_table, sglist, nelems, direction);
+	iommu_unmap_sg(to_vio_dev(dev)->iommu_table, sglist, nelems, direction);
 }
-EXPORT_SYMBOL(vio_unmap_sg);
 
-void *vio_alloc_consistent(struct vio_dev *dev, size_t size,
-			   dma_addr_t *dma_handle)
+static void *vio_alloc_coherent(struct device *dev, size_t size,
+			   dma_addr_t *dma_handle, int flag)
 {
-	return iommu_alloc_consistent(dev->iommu_table, size, dma_handle);
+	return iommu_alloc_coherent(to_vio_dev(dev)->iommu_table, size,
+			dma_handle, flag);
 }
-EXPORT_SYMBOL(vio_alloc_consistent);
 
-void vio_free_consistent(struct vio_dev *dev, size_t size,
+static void vio_free_coherent(struct device *dev, size_t size,
 			 void *vaddr, dma_addr_t dma_handle)
 {
-	iommu_free_consistent(dev->iommu_table, size, vaddr, dma_handle);
+	iommu_free_coherent(to_vio_dev(dev)->iommu_table, size, vaddr,
+			dma_handle);
 }
-EXPORT_SYMBOL(vio_free_consistent);
+
+static int vio_dma_supported(struct device *dev, u64 mask)
+{
+	return 1;
+}
+
+struct dma_mapping_ops vio_dma_ops = {
+	.alloc_coherent = vio_alloc_coherent,
+	.free_coherent = vio_free_coherent,
+	.map_single = vio_map_single,
+	.unmap_single = vio_unmap_single,
+	.map_sg = vio_map_sg,
+	.unmap_sg = vio_unmap_sg,
+	.dma_supported = vio_dma_supported,
+};
 
 static int vio_bus_match(struct device *dev, struct device_driver *drv)
 {
diff -Nru a/arch/ppc64/kernel/xics.c b/arch/ppc64/kernel/xics.c
--- a/arch/ppc64/kernel/xics.c	2005-03-11 12:51:46 -08:00
+++ b/arch/ppc64/kernel/xics.c	2005-03-11 12:51:46 -08:00
@@ -654,7 +654,7 @@
 	/* remove ourselves from the global interrupt queue */
 	status = rtas_set_indicator(GLOBAL_INTERRUPT_QUEUE,
 		(1UL << interrupt_server_size) - 1 - default_distrib_server, 0);
-	WARN_ON(status != 0);
+	WARN_ON(status < 0);
 
 	/* Allow IPIs again... */
 	ops->cppr_info(cpu, DEFAULT_PRIORITY);
@@ -704,15 +704,8 @@
 		       virq, cpu);
 
 		/* Reset affinity to all cpus */
-		xics_status[0] = default_distrib_server;
-
-		status = rtas_call(ibm_set_xive, 3, 1, NULL, irq,
-				xics_status[0], xics_status[1]);
-		if (status)
-			printk(KERN_ERR "migrate_irqs_away: irq=%d "
-					"ibm,set-xive returns %d\n",
-					virq, status);
-
+		desc->handler->set_affinity(virq, CPU_MASK_ALL);
+		irq_affinity[virq] = CPU_MASK_ALL;
 unlock:
 		spin_unlock_irqrestore(&desc->lock, flags);
 	}
diff -Nru a/arch/ppc64/mm/hash_native.c b/arch/ppc64/mm/hash_native.c
--- a/arch/ppc64/mm/hash_native.c	2005-03-11 12:51:42 -08:00
+++ b/arch/ppc64/mm/hash_native.c	2005-03-11 12:51:42 -08:00
@@ -217,10 +217,10 @@
 	}
 
 	/* Ensure it is out of the tlb too */
-	if ((cur_cpu_spec->cpu_features & CPU_FTR_TLBIEL) && !large && local) {
+	if (cpu_has_feature(CPU_FTR_TLBIEL) && !large && local) {
 		tlbiel(va);
 	} else {
-		int lock_tlbie = !(cur_cpu_spec->cpu_features & CPU_FTR_LOCKLESS_TLBIE);
+		int lock_tlbie = !cpu_has_feature(CPU_FTR_LOCKLESS_TLBIE);
 
 		if (lock_tlbie)
 			spin_lock(&native_tlbie_lock);
@@ -245,7 +245,7 @@
 	unsigned long vsid, va, vpn, flags = 0;
 	long slot;
 	HPTE *hptep;
-	int lock_tlbie = !(cur_cpu_spec->cpu_features & CPU_FTR_LOCKLESS_TLBIE);
+	int lock_tlbie = !cpu_has_feature(CPU_FTR_LOCKLESS_TLBIE);
 
 	vsid = get_kernel_vsid(ea);
 	va = (vsid << 28) | (ea & 0x0fffffff);
@@ -273,7 +273,7 @@
 	Hpte_dword0 dw0;
 	unsigned long avpn = va >> 23;
 	unsigned long flags;
-	int lock_tlbie = !(cur_cpu_spec->cpu_features & CPU_FTR_LOCKLESS_TLBIE);
+	int lock_tlbie = !cpu_has_feature(CPU_FTR_LOCKLESS_TLBIE);
 
 	if (large)
 		avpn &= ~0x1UL;
@@ -292,7 +292,7 @@
 	}
 
 	/* Invalidate the tlb */
-	if ((cur_cpu_spec->cpu_features & CPU_FTR_TLBIEL) && !large && local) {
+	if (cpu_has_feature(CPU_FTR_TLBIEL) && !large && local) {
 		tlbiel(va);
 	} else {
 		if (lock_tlbie)
@@ -360,7 +360,7 @@
 		j++;
 	}
 
-	if ((cur_cpu_spec->cpu_features & CPU_FTR_TLBIEL) && !large && local) {
+	if (cpu_has_feature(CPU_FTR_TLBIEL) && !large && local) {
 		asm volatile("ptesync":::"memory");
 
 		for (i = 0; i < j; i++)
@@ -368,7 +368,7 @@
 
 		asm volatile("ptesync":::"memory");
 	} else {
-		int lock_tlbie = !(cur_cpu_spec->cpu_features & CPU_FTR_LOCKLESS_TLBIE);
+		int lock_tlbie = !cpu_has_feature(CPU_FTR_LOCKLESS_TLBIE);
 
 		if (lock_tlbie)
 			spin_lock(&native_tlbie_lock);
diff -Nru a/arch/ppc64/mm/hash_utils.c b/arch/ppc64/mm/hash_utils.c
--- a/arch/ppc64/mm/hash_utils.c	2005-03-11 12:51:47 -08:00
+++ b/arch/ppc64/mm/hash_utils.c	2005-03-11 12:51:47 -08:00
@@ -190,7 +190,7 @@
 	 * _NOT_ map it to avoid cache paradoxes as it's remapped non
 	 * cacheable later on
 	 */
-	if (cur_cpu_spec->cpu_features & CPU_FTR_16M_PAGE)
+	if (cpu_has_feature(CPU_FTR_16M_PAGE))
 		use_largepages = 1;
 
 	/* create bolted the linear mapping in the hash table */
diff -Nru a/arch/ppc64/mm/hugetlbpage.c b/arch/ppc64/mm/hugetlbpage.c
--- a/arch/ppc64/mm/hugetlbpage.c	2005-03-11 12:51:46 -08:00
+++ b/arch/ppc64/mm/hugetlbpage.c	2005-03-11 12:51:46 -08:00
@@ -149,7 +149,8 @@
 }
 
 static void set_huge_pte(struct mm_struct *mm, struct vm_area_struct *vma,
-			 struct page *page, pte_t *ptep, int write_access)
+			 unsigned long addr, struct page *page,
+			 pte_t *ptep, int write_access)
 {
 	pte_t entry;
 
@@ -163,7 +164,7 @@
 	entry = pte_mkyoung(entry);
 	entry = pte_mkhuge(entry);
 
-	set_pte(ptep, entry);
+	set_pte_at(mm, addr, ptep, entry);
 }
 
 /*
@@ -316,7 +317,7 @@
 		ptepage = pte_page(entry);
 		get_page(ptepage);
 		dst->rss += (HPAGE_SIZE / PAGE_SIZE);
-		set_pte(dst_pte, entry);
+		set_pte_at(dst, addr, dst_pte, entry);
 
 		addr += HPAGE_SIZE;
 	}
@@ -421,7 +422,7 @@
 
 		pte = *ptep;
 		page = pte_page(pte);
-		pte_clear(ptep);
+		pte_clear(mm, addr, ptep);
 
 		put_page(page);
 	}
@@ -486,7 +487,7 @@
 				goto out;
 			}
 		}
-		set_huge_pte(mm, vma, page, pte, vma->vm_flags & VM_WRITE);
+		set_huge_pte(mm, vma, addr, page, pte, vma->vm_flags & VM_WRITE);
 	}
 out:
 	spin_unlock(&mm->page_table_lock);
@@ -709,7 +710,7 @@
 	if (len & ~HPAGE_MASK)
 		return -EINVAL;
 
-	if (!(cur_cpu_spec->cpu_features & CPU_FTR_16M_PAGE))
+	if (!cpu_has_feature(CPU_FTR_16M_PAGE))
 		return -EINVAL;
 
 	if (test_thread_flag(TIF_32BIT)) {
diff -Nru a/arch/ppc64/mm/init.c b/arch/ppc64/mm/init.c
--- a/arch/ppc64/mm/init.c	2005-03-11 12:51:47 -08:00
+++ b/arch/ppc64/mm/init.c	2005-03-11 12:51:47 -08:00
@@ -38,6 +38,7 @@
 #include <linux/highmem.h>
 #include <linux/idr.h>
 #include <linux/nodemask.h>
+#include <linux/module.h>
 
 #include <asm/pgalloc.h>
 #include <asm/page.h>
@@ -62,6 +63,7 @@
 #include <asm/system.h>
 #include <asm/iommu.h>
 #include <asm/abs_addr.h>
+#include <asm/vdso.h>
 
 int mem_init_done;
 unsigned long ioremap_bot = IMALLOC_BASE;
@@ -153,7 +155,7 @@
 		ptep = pte_alloc_kernel(&ioremap_mm, pmdp, ea);
 
 		pa = abs_to_phys(pa);
-		set_pte(ptep, pfn_pte(pa >> PAGE_SHIFT, __pgprot(flags)));
+		set_pte_at(&ioremap_mm, ea, ptep, pfn_pte(pa >> PAGE_SHIFT, __pgprot(flags)));
 		spin_unlock(&ioremap_mm.page_table_lock);
 	} else {
 		unsigned long va, vpn, hash, hpteg;
@@ -286,7 +288,7 @@
 static void unmap_im_area_pte(pmd_t *pmd, unsigned long address,
 				  unsigned long size)
 {
-	unsigned long end;
+	unsigned long base, end;
 	pte_t *pte;
 
 	if (pmd_none(*pmd))
@@ -298,6 +300,7 @@
 	}
 
 	pte = pte_offset_kernel(pmd, address);
+	base = address & PMD_MASK;
 	address &= ~PMD_MASK;
 	end = address + size;
 	if (end > PMD_SIZE)
@@ -305,7 +308,7 @@
 
 	do {
 		pte_t page;
-		page = ptep_get_and_clear(pte);
+		page = ptep_get_and_clear(&ioremap_mm, base + address, pte);
 		address += PAGE_SIZE;
 		pte++;
 		if (pte_none(page))
@@ -319,7 +322,7 @@
 static void unmap_im_area_pmd(pgd_t *dir, unsigned long address,
 				  unsigned long size)
 {
-	unsigned long end;
+	unsigned long base, end;
 	pmd_t *pmd;
 
 	if (pgd_none(*dir))
@@ -331,13 +334,14 @@
 	}
 
 	pmd = pmd_offset(dir, address);
+	base = address & PGDIR_MASK;
 	address &= ~PGDIR_MASK;
 	end = address + size;
 	if (end > PGDIR_SIZE)
 		end = PGDIR_SIZE;
 
 	do {
-		unmap_im_area_pte(pmd, address, end - address);
+		unmap_im_area_pte(pmd, base + address, end - address);
 		address = (address + PMD_SIZE) & PMD_MASK;
 		pmd++;
 	} while (address < end);
@@ -441,6 +445,10 @@
 
 #endif
 
+EXPORT_SYMBOL(ioremap);
+EXPORT_SYMBOL(__ioremap);
+EXPORT_SYMBOL(iounmap);
+
 void free_initmem(void)
 {
 	unsigned long addr;
@@ -743,6 +751,8 @@
 #ifdef CONFIG_PPC_ISERIES
 	iommu_vio_init();
 #endif
+	/* Initialize the vDSO */
+	vdso_init();
 }
 
 /*
@@ -752,18 +762,19 @@
  */
 void flush_dcache_page(struct page *page)
 {
-	if (cur_cpu_spec->cpu_features & CPU_FTR_COHERENT_ICACHE)
+	if (cpu_has_feature(CPU_FTR_COHERENT_ICACHE))
 		return;
 	/* avoid an atomic op if possible */
 	if (test_bit(PG_arch_1, &page->flags))
 		clear_bit(PG_arch_1, &page->flags);
 }
+EXPORT_SYMBOL(flush_dcache_page);
 
 void clear_user_page(void *page, unsigned long vaddr, struct page *pg)
 {
 	clear_page(page);
 
-	if (cur_cpu_spec->cpu_features & CPU_FTR_COHERENT_ICACHE)
+	if (cpu_has_feature(CPU_FTR_COHERENT_ICACHE))
 		return;
 	/*
 	 * We shouldnt have to do this, but some versions of glibc
@@ -775,6 +786,7 @@
 	if (test_bit(PG_arch_1, &pg->flags))
 		clear_bit(PG_arch_1, &pg->flags);
 }
+EXPORT_SYMBOL(clear_user_page);
 
 void copy_user_page(void *vto, void *vfrom, unsigned long vaddr,
 		    struct page *pg)
@@ -796,7 +808,7 @@
 		return;
 #endif
 
-	if (cur_cpu_spec->cpu_features & CPU_FTR_COHERENT_ICACHE)
+	if (cpu_has_feature(CPU_FTR_COHERENT_ICACHE))
 		return;
 
 	/* avoid an atomic op if possible */
@@ -812,6 +824,7 @@
 	maddr = (unsigned long)page_address(page) + (addr & ~PAGE_MASK);
 	flush_icache_range(maddr, maddr + len);
 }
+EXPORT_SYMBOL(flush_icache_user_range);
 
 /*
  * This is called at the end of handling a user page fault, when the
@@ -832,8 +845,8 @@
 	unsigned long flags;
 
 	/* handle i-cache coherency */
-	if (!(cur_cpu_spec->cpu_features & CPU_FTR_COHERENT_ICACHE) &&
-	    !(cur_cpu_spec->cpu_features & CPU_FTR_NOEXECUTE)) {
+	if (!cpu_has_feature(CPU_FTR_COHERENT_ICACHE) &&
+	    !cpu_has_feature(CPU_FTR_NOEXECUTE)) {
 		unsigned long pfn = pte_pfn(pte);
 		if (pfn_valid(pfn)) {
 			struct page *page = pfn_to_page(pfn);
diff -Nru a/arch/ppc64/mm/slb.c b/arch/ppc64/mm/slb.c
--- a/arch/ppc64/mm/slb.c	2005-03-11 12:51:46 -08:00
+++ b/arch/ppc64/mm/slb.c	2005-03-11 12:51:46 -08:00
@@ -51,7 +51,7 @@
 
 	WARN_ON(!irqs_disabled());
 
-	if (cur_cpu_spec->cpu_features & CPU_FTR_16M_PAGE)
+	if (cpu_has_feature(CPU_FTR_16M_PAGE))
 		ksp_flags |= SLB_VSID_L;
 
 	ksp_esid_data = mk_esid_data(get_paca()->kstack, 2);
@@ -139,7 +139,7 @@
 	unsigned long flags = SLB_VSID_KERNEL;
 
  	/* Invalidate the entire SLB (even slot 0) & all the ERATS */
- 	if (cur_cpu_spec->cpu_features & CPU_FTR_16M_PAGE)
+ 	if (cpu_has_feature(CPU_FTR_16M_PAGE))
  		flags |= SLB_VSID_L;
 
  	asm volatile("isync":::"memory");
diff -Nru a/arch/ppc64/mm/stab.c b/arch/ppc64/mm/stab.c
--- a/arch/ppc64/mm/stab.c	2005-03-11 12:51:52 -08:00
+++ b/arch/ppc64/mm/stab.c	2005-03-11 12:51:52 -08:00
@@ -227,7 +227,7 @@
 {
 	unsigned long vsid = get_kernel_vsid(KERNELBASE);
 
-	if (cur_cpu_spec->cpu_features & CPU_FTR_SLB) {
+	if (cpu_has_feature(CPU_FTR_SLB)) {
 		slb_initialize();
 	} else {
 		asm volatile("isync; slbia; isync":::"memory");
diff -Nru a/arch/ppc64/mm/tlb.c b/arch/ppc64/mm/tlb.c
--- a/arch/ppc64/mm/tlb.c	2005-03-11 12:51:46 -08:00
+++ b/arch/ppc64/mm/tlb.c	2005-03-11 12:51:46 -08:00
@@ -74,23 +74,12 @@
  * change the existing HPTE to read-only rather than removing it
  * (if we remove it we should clear the _PTE_HPTEFLAGS bits).
  */
-void hpte_update(pte_t *ptep, unsigned long pte, int wrprot)
+void hpte_update(struct mm_struct *mm, unsigned long addr,
+		 unsigned long pte, int wrprot)
 {
-	struct page *ptepage;
-	struct mm_struct *mm;
-	unsigned long addr;
 	int i;
 	unsigned long context = 0;
 	struct ppc64_tlb_batch *batch = &__get_cpu_var(ppc64_tlb_batch);
-
-	ptepage = virt_to_page(ptep);
-	mm = (struct mm_struct *) ptepage->mapping;
-	addr = ptepage->index;
-	if (pte_huge(pte))
-		addr +=  ((unsigned long)ptep & ~PAGE_MASK)
-			/ sizeof(*ptep) * HPAGE_SIZE;
-	else
-		addr += ((unsigned long)ptep & ~PAGE_MASK) * PTRS_PER_PTE;
 
 	if (REGION_ID(addr) == USER_REGION_ID)
 		context = mm->context.id;
diff -Nru a/arch/ppc64/oprofile/common.c b/arch/ppc64/oprofile/common.c
--- a/arch/ppc64/oprofile/common.c	2005-03-11 12:51:51 -08:00
+++ b/arch/ppc64/oprofile/common.c	2005-03-11 12:51:51 -08:00
@@ -15,6 +15,7 @@
 #include <linux/errno.h>
 #include <asm/ptrace.h>
 #include <asm/system.h>
+#include <asm/pmc.h>
 
 #include "op_impl.h"
 
@@ -22,9 +23,6 @@
 extern struct op_ppc64_model op_model_power4;
 static struct op_ppc64_model *model;
 
-extern void (*perf_irq)(struct pt_regs *);
-static void (*save_perf_irq)(struct pt_regs *);
-
 static struct op_counter_config ctr[OP_MAX_COUNTER];
 static struct op_system_config sys;
 
@@ -35,11 +33,12 @@
 
 static int op_ppc64_setup(void)
 {
-	/* Install our interrupt handler into the existing hook.  */
-	save_perf_irq = perf_irq;
-	perf_irq = op_handle_interrupt;
+	int err;
 
-	mb();
+	/* Grab the hardware */
+	err = reserve_pmc_hardware(op_handle_interrupt);
+	if (err)
+		return err;
 
 	/* Pre-compute the values to stuff in the hardware registers.  */
 	model->reg_setup(ctr, &sys, model->num_counters);
@@ -52,10 +51,7 @@
 
 static void op_ppc64_shutdown(void)
 {
-	mb();
-
-	/* Remove our interrupt handler. We may be removing this module. */
-	perf_irq = save_perf_irq;
+	release_pmc_hardware();
 }
 
 static void op_ppc64_cpu_start(void *dummy)
diff -Nru a/arch/ppc64/oprofile/op_model_power4.c b/arch/ppc64/oprofile/op_model_power4.c
--- a/arch/ppc64/oprofile/op_model_power4.c	2005-03-11 12:51:47 -08:00
+++ b/arch/ppc64/oprofile/op_model_power4.c	2005-03-11 12:51:47 -08:00
@@ -54,7 +54,7 @@
 	 *
 	 * It has been verified to work on POWER5 so we enable it there.
 	 */
-	if (cur_cpu_spec->cpu_features & CPU_FTR_MMCRA_SIHV)
+	if (cpu_has_feature(CPU_FTR_MMCRA_SIHV))
 		mmcra_has_sihv = 1;
 
 	/*
diff -Nru a/arch/ppc64/oprofile/op_model_rs64.c b/arch/ppc64/oprofile/op_model_rs64.c
--- a/arch/ppc64/oprofile/op_model_rs64.c	2005-03-11 12:51:51 -08:00
+++ b/arch/ppc64/oprofile/op_model_rs64.c	2005-03-11 12:51:51 -08:00
@@ -114,7 +114,7 @@
 	/* reset MMCR1, MMCRA */
 	mtspr(SPRN_MMCR1, 0);
 
-	if (cur_cpu_spec->cpu_features & CPU_FTR_MMCRA)
+	if (cpu_has_feature(CPU_FTR_MMCRA))
 		mtspr(SPRN_MMCRA, 0);
 
 	mmcr0 |= MMCR0_FCM1|MMCR0_PMXE|MMCR0_FCECE;
diff -Nru a/arch/ppc64/xmon/xmon.c b/arch/ppc64/xmon/xmon.c
--- a/arch/ppc64/xmon/xmon.c	2005-03-11 12:51:51 -08:00
+++ b/arch/ppc64/xmon/xmon.c	2005-03-11 12:51:51 -08:00
@@ -32,6 +32,7 @@
 #include <asm/rtas.h>
 #include <asm/sstep.h>
 #include <asm/bug.h>
+#include <asm/hvcall.h>
 
 #include "nonstdio.h"
 #include "privinst.h"
@@ -725,7 +726,7 @@
 {
 	if (dabr.enabled)
 		set_controlled_dabr(dabr.address | (dabr.enabled & 7));
-	if (iabr && (cur_cpu_spec->cpu_features & CPU_FTR_IABR))
+	if (iabr && cpu_has_feature(CPU_FTR_IABR))
 		set_iabr(iabr->address
 			 | (iabr->enabled & (BP_IABR|BP_IABR_TE)));
 }
@@ -753,7 +754,7 @@
 static void remove_cpu_bpts(void)
 {
 	set_controlled_dabr(0);
-	if ((cur_cpu_spec->cpu_features & CPU_FTR_IABR))
+	if (cpu_has_feature(CPU_FTR_IABR))
 		set_iabr(0);
 }
 
@@ -1100,7 +1101,7 @@
 		break;
 
 	case 'i':	/* bi - hardware instr breakpoint */
-		if (!(cur_cpu_spec->cpu_features & CPU_FTR_IABR)) {
+		if (!cpu_has_feature(CPU_FTR_IABR)) {
 			printf("Hardware instruction breakpoint "
 			       "not supported on this cpu\n");
 			break;
@@ -2498,7 +2499,7 @@
 
 void dump_segments(void)
 {
-	if (cur_cpu_spec->cpu_features & CPU_FTR_SLB)
+	if (cpu_has_feature(CPU_FTR_SLB))
 		dump_slb();
 	else
 		dump_stab();
diff -Nru a/arch/s390/Kconfig b/arch/s390/Kconfig
--- a/arch/s390/Kconfig	2005-03-11 12:51:42 -08:00
+++ b/arch/s390/Kconfig	2005-03-11 12:51:42 -08:00
@@ -84,12 +84,12 @@
 	  approximately sixteen kilobytes to the kernel image.
 
 config HOTPLUG_CPU
-	bool "Support for hot-pluggable CPUs (EXPERIMENTAL)"
-	depends on SMP && EXPERIMENTAL
+	bool "Support for hot-pluggable CPUs"
+	depends on SMP
 	select HOTPLUG
 	default n
 	help
-	  Say Y here to experiment with turning CPUs off and on.  CPUs
+	  Say Y here to be able to turn CPUs off and on. CPUs
 	  can be controlled through /sys/devices/system/cpu/cpu#.
 	  Say N if you want to disable CPU hotplug.
 
diff -Nru a/arch/s390/Makefile b/arch/s390/Makefile
--- a/arch/s390/Makefile	2005-03-11 12:51:41 -08:00
+++ b/arch/s390/Makefile	2005-03-11 12:51:41 -08:00
@@ -66,7 +66,7 @@
 cflags-$(CONFIG_WARN_STACK) += -mwarn-framesize=$(CONFIG_WARN_STACK_SIZE)
 endif
 
-CFLAGS		+= -mbackchain $(cflags-y)
+CFLAGS		+= -mbackchain -msoft-float $(cflags-y)
 CFLAGS		+= $(call cc-option,-finline-limit=10000)
 CFLAGS 		+= -pipe -fno-strength-reduce -Wno-sign-compare 
 AFLAGS		+= $(aflags-y)
diff -Nru a/arch/s390/defconfig b/arch/s390/defconfig
--- a/arch/s390/defconfig	2005-03-11 12:51:51 -08:00
+++ b/arch/s390/defconfig	2005-03-11 12:51:51 -08:00
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.11-rc2
-# Mon Jan 31 16:27:12 2005
+# Linux kernel version: 2.6.11
+# Wed Mar  2 16:57:55 2005
 #
 CONFIG_MMU=y
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
@@ -54,6 +54,7 @@
 # CONFIG_MODVERSIONS is not set
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_KMOD=y
+CONFIG_STOP_MACHINE=y
 
 #
 # Base setup
@@ -67,7 +68,7 @@
 CONFIG_ARCH_S390_31=y
 CONFIG_SMP=y
 CONFIG_NR_CPUS=32
-# CONFIG_HOTPLUG_CPU is not set
+CONFIG_HOTPLUG_CPU=y
 CONFIG_MATHEMU=y
 
 #
@@ -419,6 +420,10 @@
 CONFIG_FS_MBCACHE=y
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
+
+#
+# XFS support
+#
 # CONFIG_XFS_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
diff -Nru a/arch/s390/kernel/compat_ioctl.c b/arch/s390/kernel/compat_ioctl.c
--- a/arch/s390/kernel/compat_ioctl.c	2005-03-11 12:51:47 -08:00
+++ b/arch/s390/kernel/compat_ioctl.c	2005-03-11 12:51:47 -08:00
@@ -65,9 +65,6 @@
 COMPATIBLE_IOCTL(TAPE390_DISPLAY)
 #endif
 
-/* This one should be architecture independent */
-COMPATIBLE_IOCTL(TCSBRKP)
-
 /* s390 doesn't need handlers here */
 COMPATIBLE_IOCTL(TIOCGSERIAL)
 COMPATIBLE_IOCTL(TIOCSSERIAL)
diff -Nru a/arch/s390/kernel/compat_linux.c b/arch/s390/kernel/compat_linux.c
--- a/arch/s390/kernel/compat_linux.c	2005-03-11 12:51:50 -08:00
+++ b/arch/s390/kernel/compat_linux.c	2005-03-11 12:51:50 -08:00
@@ -1019,7 +1019,7 @@
 sys_timer_create(clockid_t, struct sigevent *, timer_t *);
 
 asmlinkage long
-sys32_timer_create(clockid_t which_clock, struct sigevent32 *se32,
+sys32_timer_create(clockid_t which_clock, struct compat_sigevent *se32,
 		timer_t *timer_id)
 {
 	struct sigevent se;
@@ -1030,16 +1030,7 @@
 	if (se32 == NULL)
 		return sys_timer_create(which_clock, NULL, timer_id);
 
-	/* XXX: converting se32 to se is filthy because of the
-	 * two union members. For now it is ok, because the pointers
-	 * are not touched in kernel.
-	 */
-	memset(&se, 0, sizeof(se));
-	if (get_user(se.sigev_value.sival_int,  &se32->sigev_value.sival_int) ||
-	    get_user(se.sigev_signo, &se32->sigev_signo) ||
-	    get_user(se.sigev_notify, &se32->sigev_notify) ||
-	    copy_from_user(&se._sigev_un._pad, &se32->_sigev_un._pad,
-	    sizeof(se._sigev_un._pad)))
+	if (get_compat_sigevent(&se, se32))
 		return -EFAULT;
 
 	old_fs = get_fs();
diff -Nru a/arch/s390/kernel/compat_linux.h b/arch/s390/kernel/compat_linux.h
--- a/arch/s390/kernel/compat_linux.h	2005-03-11 12:51:47 -08:00
+++ b/arch/s390/kernel/compat_linux.h	2005-03-11 12:51:47 -08:00
@@ -29,11 +29,6 @@
        __u32			sa_restorer;	/* Another 32 bit pointer */
 };
  
-typedef union sigval32 {
-        int     sival_int;
-        __u32   sival_ptr;
-} sigval_t32;
-                 
 typedef struct compat_siginfo {
 	int	si_signo;
 	int	si_errno;
@@ -52,7 +47,7 @@
 		struct {
 			timer_t _tid;		/* timer id */
 			int _overrun;		/* overrun count */
-			sigval_t _sigval;	/* same as below */
+			compat_sigval_t _sigval;	/* same as below */
 			int _sys_private;       /* not to be passed to user */
 		} _timer;
 
@@ -60,7 +55,7 @@
 		struct {
 			pid_t			_pid;	/* sender's pid */
 			uid_t			_uid;	/* sender's uid */
-			sigval_t32		_sigval;
+			compat_sigval_t		_sigval;
 		} _rt;
 
 		/* SIGCHLD */
@@ -197,24 +192,6 @@
 	stack_t32		uc_stack;
 	_sigregs32		uc_mcontext;
 	compat_sigset_t		uc_sigmask;	/* mask last for extensibility */
-};
-
-#define SIGEV_PAD_SIZE32 ((SIGEV_MAX_SIZE/sizeof(int)) - 3)
-struct sigevent32 {
-	union {
-		int sival_int;
-		u32 sival_ptr;
-	} sigev_value;
-	int sigev_signo;
-	int sigev_notify;
-	union {
-		int _pad[SIGEV_PAD_SIZE32];
-		int _tid;
-		struct {
-			u32 *_function;
-			u32 *_attribute;
-		} _sigev_thread;
-	} _sigev_un;
 };
 
 #endif /* _ASM_S390X_S390_H */
diff -Nru a/arch/s390/kernel/compat_wrapper.S b/arch/s390/kernel/compat_wrapper.S
--- a/arch/s390/kernel/compat_wrapper.S	2005-03-11 12:51:52 -08:00
+++ b/arch/s390/kernel/compat_wrapper.S	2005-03-11 12:51:52 -08:00
@@ -1406,3 +1406,20 @@
 	llgtr	%r3,%r3			# struct compat_mq_attr *
 	llgtr	%r4,%r4			# struct compat_mq_attr *
 	jg	compat_sys_mq_getsetattr
+
+	.globl	compat_sys_add_key
+compat_sys_add_key:
+	llgtr	%r2,%r2			# const char *
+	llgtr	%r3,%r3			# const char *
+	llgtr	%r4,%r4			# const void *
+	llgfr	%r5,%r5			# size_t
+	llgfr	%r6,%r6			# (key_serial_t) u32
+	jg	sys_add_key
+
+	.globl	compat_sys_request_key
+compat_sys_request_key:
+	llgtr	%r2,%r2			# const char *
+	llgtr	%r3,%r3			# const char *
+	llgtr	%r4,%r4			# const void *
+	llgfr	%r5,%r5			# (key_serial_t) u32
+	jg	sys_request_key
diff -Nru a/arch/s390/kernel/irq.c b/arch/s390/kernel/irq.c
--- a/arch/s390/kernel/irq.c	2005-03-11 12:51:47 -08:00
+++ b/arch/s390/kernel/irq.c	2005-03-11 12:51:47 -08:00
@@ -25,9 +25,8 @@
 
 	if (i == 0) {
 		seq_puts(p, "           ");
-		for (j=0; j<NR_CPUS; j++)
-			if (cpu_online(j))
-				seq_printf(p, "CPU%d       ",j);
+		for_each_online_cpu(j)
+			seq_printf(p, "CPU%d       ",j);
 		seq_putc(p, '\n');
 	}
 
@@ -36,9 +35,8 @@
 #ifndef CONFIG_SMP
 		seq_printf(p, "%10u ", kstat_irqs(i));
 #else
-		for (j = 0; j < NR_CPUS; j++)
-			if (cpu_online(j))
-				seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]);
+		for_each_online_cpu(j)
+			seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]);
 #endif
                 seq_putc(p, '\n');
 
diff -Nru a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c
--- a/arch/s390/kernel/smp.c	2005-03-11 12:51:52 -08:00
+++ b/arch/s390/kernel/smp.c	2005-03-11 12:51:52 -08:00
@@ -212,29 +212,29 @@
 
 static inline void do_send_stop(void)
 {
-        int i, rc;
+        int cpu, rc;
 
         /* stop all processors */
-        for (i =  0; i < NR_CPUS; i++) {
-                if (!cpu_online(i) || smp_processor_id() == i)
+	for_each_online_cpu(cpu) {
+		if (cpu == smp_processor_id())
 			continue;
 		do {
-			rc = signal_processor(i, sigp_stop);
+			rc = signal_processor(cpu, sigp_stop);
 		} while (rc == sigp_busy);
 	}
 }
 
 static inline void do_store_status(void)
 {
-        int i, rc;
+        int cpu, rc;
 
         /* store status of all processors in their lowcores (real 0) */
-        for (i =  0; i < NR_CPUS; i++) {
-                if (!cpu_online(i) || smp_processor_id() == i) 
+	for_each_online_cpu(cpu) {
+		if (cpu == smp_processor_id())
 			continue;
 		do {
 			rc = signal_processor_p(
-				(__u32)(unsigned long) lowcore_ptr[i], i,
+				(__u32)(unsigned long) lowcore_ptr[cpu], cpu,
 				sigp_store_status_at_address);
 		} while(rc == sigp_busy);
         }
@@ -259,37 +259,41 @@
 /*
  * Reboot, halt and power_off routines for SMP.
  */
-static cpumask_t cpu_restart_map;
 
 static void do_machine_restart(void * __unused)
 {
+	int cpu;
 	static atomic_t cpuid = ATOMIC_INIT(-1);
 
-	cpu_clear(smp_processor_id(), cpu_restart_map);
-	if (atomic_compare_and_swap(-1, smp_processor_id(), &cpuid) == 0) {
-		/* Wait for all other cpus to enter do_machine_restart. */
-		while (!cpus_empty(cpu_restart_map))
+	if (atomic_compare_and_swap(-1, smp_processor_id(), &cpuid))
+		signal_processor(smp_processor_id(), sigp_stop);
+
+	/* Wait for all other cpus to enter stopped state */
+	for_each_online_cpu(cpu) {
+		if (cpu == smp_processor_id())
+			continue;
+		while(!smp_cpu_not_running(cpu))
 			cpu_relax();
-		/* Store status of other cpus. */
-		do_store_status();
-		/*
-		 * Finally call reipl. Because we waited for all other
-		 * cpus to enter this function we know that they do
-		 * not hold any s390irq-locks (the cpus have been
-		 * interrupted by an external interrupt and s390irq
-		 * locks are always held disabled).
-		 */
-		if (MACHINE_IS_VM)
-			cpcmd ("IPL", NULL, 0);
-		else
-			reipl (0x10000 | S390_lowcore.ipl_device);
 	}
-	signal_processor(smp_processor_id(), sigp_stop);
+
+	/* Store status of other cpus. */
+	do_store_status();
+
+	/*
+	 * Finally call reipl. Because we waited for all other
+	 * cpus to enter this function we know that they do
+	 * not hold any s390irq-locks (the cpus have been
+	 * interrupted by an external interrupt and s390irq
+	 * locks are always held disabled).
+	 */
+	if (MACHINE_IS_VM)
+		cpcmd ("IPL", NULL, 0);
+	else
+		reipl (0x10000 | S390_lowcore.ipl_device);
 }
 
 void machine_restart_smp(char * __unused) 
 {
-	cpu_restart_map = cpu_online_map;
         on_each_cpu(do_machine_restart, NULL, 0, 0);
 }
 
@@ -384,16 +388,16 @@
  */
 static void smp_ext_bitcall_others(ec_bit_sig sig)
 {
-        int i;
+        int cpu;
 
-        for (i = 0; i < NR_CPUS; i++) {
-                if (!cpu_online(i) || smp_processor_id() == i)
+	for_each_online_cpu(cpu) {
+		if (cpu == smp_processor_id())
                         continue;
                 /*
                  * Set signaling bit in lowcore of target cpu and kick it
                  */
-		set_bit(sig, (unsigned long *) &lowcore_ptr[i]->ext_call_fast);
-                while (signal_processor(i, sigp_external_call) == sigp_busy)
+		set_bit(sig, (unsigned long *) &lowcore_ptr[cpu]->ext_call_fast);
+		while (signal_processor(cpu, sigp_external_call) == sigp_busy)
 			udelay(10);
         }
 }
@@ -497,7 +501,6 @@
 	 */
 
 	boot_cpu_addr = S390_lowcore.cpu_data.cpu_addr;
-	__cpu_logical_map[0] = boot_cpu_addr;
 	current_thread_info()->cpu = 0;
 	num_cpus = 1;
 	for (cpu = 0; cpu <= 65535 && num_cpus < max_cpus; cpu++) {
@@ -725,7 +728,7 @@
 __cpu_die(unsigned int cpu)
 {
 	/* Wait until target cpu is down */
-	while (!cpu_stopped(cpu))
+	while (!smp_cpu_not_running(cpu))
 		cpu_relax();
 	printk("Processor %d spun down\n", cpu);
 }
@@ -790,6 +793,7 @@
 	BUG_ON(smp_processor_id() != 0);
 
 	cpu_set(0, cpu_online_map);
+	cpu_set(0, cpu_present_map);
 	cpu_set(0, cpu_possible_map);
 	S390_lowcore.percpu_offset = __per_cpu_offset[0];
 	current_set[0] = current;
diff -Nru a/arch/s390/kernel/syscalls.S b/arch/s390/kernel/syscalls.S
--- a/arch/s390/kernel/syscalls.S	2005-03-11 12:51:41 -08:00
+++ b/arch/s390/kernel/syscalls.S	2005-03-11 12:51:41 -08:00
@@ -286,3 +286,6 @@
 SYSCALL(sys_mq_notify,sys_mq_notify,compat_sys_mq_notify_wrapper) /* 275 */
 SYSCALL(sys_mq_getsetattr,sys_mq_getsetattr,compat_sys_mq_getsetattr_wrapper)
 NI_SYSCALL							/* reserved for kexec */
+SYSCALL(sys_add_key,sys_add_key,compat_sys_add_key)
+SYSCALL(sys_request_key,sys_request_key,compat_sys_request_key)
+SYSCALL(sys_keyctl,sys_keyctl,compat_sys_keyctl)		/* 280 */
diff -Nru a/arch/s390/mm/init.c b/arch/s390/mm/init.c
--- a/arch/s390/mm/init.c	2005-03-11 12:51:47 -08:00
+++ b/arch/s390/mm/init.c	2005-03-11 12:51:47 -08:00
@@ -145,7 +145,7 @@
                 for (tmp = 0 ; tmp < PTRS_PER_PTE ; tmp++,pg_table++) {
                         pte = pfn_pte(pfn, PAGE_KERNEL);
                         if (pfn >= max_low_pfn)
-                                pte_clear(&pte);
+                                pte_clear(&init_mm, 0, &pte);
                         set_pte(pg_table, pte);
                         pfn++;
                 }
@@ -229,7 +229,7 @@
                         for (k = 0 ; k < PTRS_PER_PTE ; k++,pt_dir++) {
                                 pte = pfn_pte(pfn, PAGE_KERNEL);
                                 if (pfn >= max_low_pfn) {
-                                        pte_clear(&pte); 
+                                        pte_clear(&init_mm, 0, &pte); 
                                         continue;
                                 }
                                 set_pte(pt_dir, pte);
diff -Nru a/arch/sh/Kconfig b/arch/sh/Kconfig
--- a/arch/sh/Kconfig	2005-03-11 12:51:51 -08:00
+++ b/arch/sh/Kconfig	2005-03-11 12:51:51 -08:00
@@ -25,6 +25,14 @@
 config RWSEM_XCHGADD_ALGORITHM
 	bool
 
+config GENERIC_HARDIRQS
+	bool
+	default y
+
+config GENERIC_IRQ_PROBE
+	bool
+	default y
+
 config GENERIC_CALIBRATE_DELAY
 	bool
 	default y
@@ -754,7 +762,6 @@
 source "drivers/pci/hotplug/Kconfig"
 
 endmenu
-
 
 menu "Executable file formats"
 
diff -Nru a/arch/sh/Makefile b/arch/sh/Makefile
--- a/arch/sh/Makefile	2005-03-11 12:51:47 -08:00
+++ b/arch/sh/Makefile	2005-03-11 12:51:47 -08:00
@@ -31,6 +31,13 @@
 OBJCOPYFLAGS	:= -O binary -R .note -R .comment -R .stab -R .stabstr -S
 
 #
+# arch/sh/defconfig doesn't reflect any real hardware, and as such should
+# never be used by anyone. Use a board-specific defconfig that has a
+# reasonable chance of being current instead.
+#
+KBUILD_DEFCONFIG := rts7751r2d_defconfig
+
+#
 # Choosing incompatible machines durings configuration will result in
 # error messages during linking.
 #
diff -Nru a/arch/sh/boards/hp6xx/hp620/Makefile b/arch/sh/boards/hp6xx/hp620/Makefile
--- a/arch/sh/boards/hp6xx/hp620/Makefile	2005-03-11 12:51:51 -08:00
+++ b/arch/sh/boards/hp6xx/hp620/Makefile	2005-03-11 12:51:51 -08:00
@@ -2,5 +2,5 @@
 # Makefile for the HP620 specific parts of the kernel
 #
 
-obj-y	 := mach.o
+obj-y	 := mach.o setup.o
 
diff -Nru a/arch/sh/boards/hp6xx/hp620/setup.c b/arch/sh/boards/hp6xx/hp620/setup.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/sh/boards/hp6xx/hp620/setup.c	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,45 @@
+/*
+ * linux/arch/sh/boards/hp6xx/hp620/setup.c
+ *
+ * Copyright (C) 2002 Andriy Skulysh, 2005 Kristoffer Ericson
+ *
+ * May be copied or modified under the terms of the GNU General Public
+ * License. See Linux/COPYING for more information.
+ *
+ * Setup code for an HP620.
+ * Due to similiarity with hp680/hp690 same inits are done (for now)
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <asm/hd64461/hd64461.h>
+#include <asm/io.h>
+#include <asm/hp6xx/hp6xx.h>
+#include <asm/cpu/dac.h>
+
+const char *get_system_type(void)
+{
+	return "HP620";
+}
+
+int __init platform_setup(void)
+{
+	u16 v;
+
+	v  = inw(HD64461_STBCR);
+	v |= HD64461_STBCR_SURTST | HD64461_STBCR_SIRST  |
+	     HD64461_STBCR_STM1ST | HD64461_STBCR_STM0ST |
+	     HD64461_STBCR_SAFEST | HD64461_STBCR_SPC0ST |
+	     HD64461_STBCR_SMIAST | HD64461_STBCR_SAFECKE_OST |
+	     HD64461_STBCR_SAFECKE_IST;
+	outw(v, HD64461_STBCR);
+
+	v  = inw(HD64461_GPADR);
+	v |= HD64461_GPADR_SPEAKER | HD64461_GPADR_PCMCIA0;
+	outw(v, HD64461_GPADR);
+
+	sh_dac_disable(DAC_SPEAKER_VOLUME);
+
+	return 0;
+}
+
diff -Nru a/arch/sh/boards/se/7300/io.c b/arch/sh/boards/se/7300/io.c
--- a/arch/sh/boards/se/7300/io.c	2005-03-11 12:51:51 -08:00
+++ b/arch/sh/boards/se/7300/io.c	2005-03-11 12:51:51 -08:00
@@ -1,12 +1,16 @@
 /*
- * linux/arch/sh/boards/se/7300/io.c
+ * arch/sh/boards/se/7300/io.c
  *
  * Copyright (C) 2003 YOSHII Takashi <yoshii-takashi@hitachi-ul.co.jp>
+ * Based on arch/sh/kernel/io_shmse.c
+ *
+ * I/O routine for SH-Mobile3 73180 SolutionEngine.
+ *
  */
 
 #include <linux/config.h>
 #include <linux/kernel.h>
-#include <asm/se7300/se7300.h>
+#include <asm/mach/se7300.h>
 #include <asm/io.h>
 
 #define badio(fn, a) panic("bad i/o operation %s for %08lx.", #fn, a)
diff -Nru a/arch/sh/boards/sh03/rtc.c b/arch/sh/boards/sh03/rtc.c
--- a/arch/sh/boards/sh03/rtc.c	2005-03-11 12:51:41 -08:00
+++ b/arch/sh/boards/sh03/rtc.c	2005-03-11 12:51:41 -08:00
@@ -115,8 +115,6 @@
 	real_minutes %= 60;
 
 	if (abs(real_minutes - cmos_minutes) < 30) {
-		BIN_TO_BCD(real_seconds);
-		BIN_TO_BCD(real_minutes);
 		ctrl_outb(real_seconds % 10, RTC_SEC1);
 		ctrl_outb(real_seconds / 10, RTC_SEC10);
 		ctrl_outb(real_minutes % 10, RTC_MIN1);
diff -Nru a/arch/sh/boards/snapgear/setup.c b/arch/sh/boards/snapgear/setup.c
--- a/arch/sh/boards/snapgear/setup.c	2005-03-11 12:51:41 -08:00
+++ b/arch/sh/boards/snapgear/setup.c	2005-03-11 12:51:41 -08:00
@@ -27,6 +27,7 @@
 #include <asm/mach/io.h>
 #include <asm/irq.h>
 #include <asm/io.h>
+#include <asm/cpu/timer.h>
 
 extern void (*board_time_init)(void);
 extern void secureedge5410_rtc_init(void);
@@ -111,11 +112,6 @@
 #endif
 #define TMU_TSTR_INIT	1
 #define TMU1_TCR_CALIB	0x0000
-#define TMU_TOCR	0xffd80000	/* Byte access */
-#define TMU_TSTR	0xffd80004	/* Byte access */
-#define TMU1_TCOR	0xffd80014	/* Long access */
-#define TMU1_TCNT	0xffd80018	/* Long access */
-#define TMU1_TCR	0xffd8001c	/* Word access */
 
 
 #ifdef FAST_POLL_INTR
diff -Nru a/arch/sh/configs/adx_defconfig b/arch/sh/configs/adx_defconfig
--- a/arch/sh/configs/adx_defconfig	2005-03-11 12:51:46 -08:00
+++ b/arch/sh/configs/adx_defconfig	2005-03-11 12:51:46 -08:00
@@ -1,15 +1,46 @@
 #
-# Automatically generated by make menuconfig: don't edit
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.11-sh
+# Wed Mar  2 15:09:26 2005
 #
 CONFIG_SUPERH=y
 CONFIG_UID16=y
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
-# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
 
 #
 # Code maturity level options
 #
 CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_SWAP=y
+# CONFIG_SYSVIPC is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_SYSCTL is not set
+# CONFIG_AUDIT is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_HOTPLUG is not set
+# CONFIG_IKCONFIG is not set
+# CONFIG_EMBEDDED is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
 
 #
 # Loadable module support
@@ -17,10 +48,13 @@
 # CONFIG_MODULES is not set
 
 #
-# Processor type and features
+# System type
 #
 # CONFIG_SH_SOLUTION_ENGINE is not set
 # CONFIG_SH_7751_SOLUTION_ENGINE is not set
+# CONFIG_SH_7300_SOLUTION_ENGINE is not set
+# CONFIG_SH_73180_SOLUTION_ENGINE is not set
+# CONFIG_SH_7751_SYSTEMH is not set
 # CONFIG_SH_STB1_HARP is not set
 # CONFIG_SH_STB1_OVERDRIVE is not set
 # CONFIG_SH_HP620 is not set
@@ -29,57 +63,115 @@
 # CONFIG_SH_CQREEK is not set
 # CONFIG_SH_DMIDA is not set
 # CONFIG_SH_EC3104 is not set
+# CONFIG_SH_SATURN is not set
 # CONFIG_SH_DREAMCAST is not set
 # CONFIG_SH_CAT68701 is not set
 # CONFIG_SH_BIGSUR is not set
 # CONFIG_SH_SH2000 is not set
 CONFIG_SH_ADX=y
+# CONFIG_SH_MPC1211 is not set
+# CONFIG_SH_SH03 is not set
+# CONFIG_SH_SECUREEDGE5410 is not set
+# CONFIG_SH_HS7751RVOIP is not set
+# CONFIG_SH_RTS7751R2D is not set
+# CONFIG_SH_EDOSK7705 is not set
+# CONFIG_SH_SH4202_MICRODEV is not set
 # CONFIG_SH_UNKNOWN is not set
-CONFIG_SH_RTC=y
+# CONFIG_CPU_SH2 is not set
+# CONFIG_CPU_SH3 is not set
+CONFIG_CPU_SH4=y
+# CONFIG_CPU_SUBTYPE_SH7604 is not set
+# CONFIG_CPU_SUBTYPE_SH7300 is not set
+# CONFIG_CPU_SUBTYPE_SH7705 is not set
 # CONFIG_CPU_SUBTYPE_SH7707 is not set
 # CONFIG_CPU_SUBTYPE_SH7708 is not set
 # CONFIG_CPU_SUBTYPE_SH7709 is not set
 CONFIG_CPU_SUBTYPE_SH7750=y
 # CONFIG_CPU_SUBTYPE_SH7751 is not set
+# CONFIG_CPU_SUBTYPE_SH7760 is not set
+# CONFIG_CPU_SUBTYPE_SH73180 is not set
 # CONFIG_CPU_SUBTYPE_ST40STB1 is not set
-# CONFIG_CPU_SH3 is not set
-CONFIG_CPU_SH4=y
-CONFIG_CPU_LITTLE_ENDIAN=y
+# CONFIG_CPU_SUBTYPE_ST40GX1 is not set
+# CONFIG_CPU_SUBTYPE_SH4_202 is not set
+CONFIG_MMU=y
+# CONFIG_CMDLINE_BOOL is not set
 CONFIG_MEMORY_START=0x08000000
 CONFIG_MEMORY_SIZE=0x00400000
 CONFIG_MEMORY_SET=y
-# CONFIG_DISCONTIGMEM is not set
-
-#
-# General setup
-#
-CONFIG_ISA=y
-# CONFIG_EISA is not set
-# CONFIG_MCA is not set
-# CONFIG_SBUS is not set
-# CONFIG_NET is not set
+# CONFIG_MEMORY_OVERRIDE is not set
 CONFIG_CF_ENABLER=y
 # CONFIG_CF_AREA5 is not set
 CONFIG_CF_AREA6=y
 CONFIG_CF_BASE_ADDR=0xb8000000
-# CONFIG_HD64461 is not set
-# CONFIG_HD64465 is not set
+CONFIG_SH_RTC=y
+CONFIG_SH_FPU=y
+CONFIG_ZERO_PAGE_OFFSET=0x00001000
+CONFIG_BOOT_LINK_OFFSET=0x00800000
+CONFIG_CPU_LITTLE_ENDIAN=y
+# CONFIG_PREEMPT is not set
+# CONFIG_UBC_WAKEUP is not set
+# CONFIG_SH_WRITETHROUGH is not set
+# CONFIG_SH_OCRAM is not set
+# CONFIG_SH_STORE_QUEUES is not set
+# CONFIG_SMP is not set
+CONFIG_SH_PCLK_CALC=y
+CONFIG_SH_PCLK_FREQ=50000000
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# DMA support
+#
 # CONFIG_SH_DMA is not set
+
+#
+# Companion Chips
+#
+# CONFIG_HD6446X_SERIES is not set
+
+#
+# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
+#
 # CONFIG_PCI is not set
-# CONFIG_HOTPLUG is not set
-# CONFIG_PCMCIA is not set
-# CONFIG_SYSVIPC is not set
-# CONFIG_BSD_PROCESS_ACCT is not set
-# CONFIG_SYSCTL is not set
-CONFIG_KCORE_ELF=y
-# CONFIG_KCORE_AOUT is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PC-card bridges
+#
+
+#
+# PCI Hotplug Support
+#
+
+#
+# Executable file formats
+#
 CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_FLAT is not set
 # CONFIG_BINFMT_MISC is not set
 
 #
-# Parallel port support
+# SH initrd options
+#
+# CONFIG_EMBEDDED_RAMDISK is not set
+
+#
+# Device Drivers
 #
-# CONFIG_PARPORT is not set
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
 
 #
 # Memory Technology Devices (MTD)
@@ -87,190 +179,361 @@
 # CONFIG_MTD is not set
 
 #
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
 # Block devices
 #
 # CONFIG_BLK_DEV_FD is not set
-# CONFIG_BLK_DEV_XD is not set
-# CONFIG_PARIDE is not set
-# CONFIG_BLK_CPQ_DA is not set
-# CONFIG_BLK_CPQ_CISS_DA is not set
-# CONFIG_CISS_SCSI_TAPE is not set
-# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
 # CONFIG_BLK_DEV_LOOP is not set
-# CONFIG_BLK_DEV_NBD is not set
 CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
 CONFIG_BLK_DEV_RAM_SIZE=4096
 CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_LBD is not set
+# CONFIG_CDROM_PKTCDVD is not set
 
 #
-# Multi-device support (RAID and LVM)
+# IO Schedulers
 #
-# CONFIG_MD is not set
-# CONFIG_BLK_DEV_MD is not set
-# CONFIG_MD_LINEAR is not set
-# CONFIG_MD_RAID0 is not set
-# CONFIG_MD_RAID1 is not set
-# CONFIG_MD_RAID5 is not set
-# CONFIG_MD_MULTIPATH is not set
-# CONFIG_BLK_DEV_LVM is not set
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
 
 #
-# ATA/IDE/MFM/RLL support
+# ATA/ATAPI/MFM/RLL support
 #
 CONFIG_IDE=y
+CONFIG_IDE_MAX_HWIFS=4
+CONFIG_BLK_DEV_IDE=y
 
 #
-# IDE, ATA and ATAPI Block devices
+# Please see Documentation/ide.txt for help/info on IDE drives
 #
-CONFIG_BLK_DEV_IDE=y
-# CONFIG_BLK_DEV_HD_IDE is not set
-# CONFIG_BLK_DEV_HD is not set
+# CONFIG_BLK_DEV_IDE_SATA is not set
 CONFIG_BLK_DEV_IDEDISK=y
 # CONFIG_IDEDISK_MULTI_MODE is not set
-# CONFIG_BLK_DEV_IDEDISK_VENDOR is not set
-# CONFIG_BLK_DEV_IDEDISK_FUJITSU is not set
-# CONFIG_BLK_DEV_IDEDISK_IBM is not set
-# CONFIG_BLK_DEV_IDEDISK_MAXTOR is not set
-# CONFIG_BLK_DEV_IDEDISK_QUANTUM is not set
-# CONFIG_BLK_DEV_IDEDISK_SEAGATE is not set
-# CONFIG_BLK_DEV_IDEDISK_WD is not set
-# CONFIG_BLK_DEV_COMMERIAL is not set
-# CONFIG_BLK_DEV_TIVO is not set
-# CONFIG_BLK_DEV_IDECS is not set
 # CONFIG_BLK_DEV_IDECD is not set
 # CONFIG_BLK_DEV_IDETAPE is not set
 # CONFIG_BLK_DEV_IDEFLOPPY is not set
-# CONFIG_BLK_DEV_IDESCSI is not set
-# CONFIG_BLK_DEV_CMD640 is not set
-# CONFIG_BLK_DEV_CMD640_ENHANCED is not set
-# CONFIG_BLK_DEV_ISAPNP is not set
-# CONFIG_IDE_CHIPSETS is not set
+# CONFIG_IDE_TASK_IOCTL is not set
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+CONFIG_IDE_SH=y
+# CONFIG_IDE_ARM is not set
+# CONFIG_BLK_DEV_IDEDMA is not set
 # CONFIG_IDEDMA_AUTO is not set
-# CONFIG_DMA_NONPCI is not set
-# CONFIG_BLK_DEV_ATARAID is not set
-# CONFIG_BLK_DEV_ATARAID_PDC is not set
-# CONFIG_BLK_DEV_ATARAID_HPT is not set
+# CONFIG_BLK_DEV_HD is not set
 
 #
-# SCSI support
+# SCSI device support
 #
 # CONFIG_SCSI is not set
 
 #
-# Old CD-ROM drivers (not SCSI, not IDE)
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
 #
-# CONFIG_CD_NO_IDESCSI is not set
 
 #
-# Input core support
+# IEEE 1394 (FireWire) support
+#
+
 #
-# CONFIG_INPUT is not set
-# CONFIG_INPUT_KEYBDEV is not set
-# CONFIG_INPUT_MOUSEDEV is not set
+# I2O device support
+#
+
+#
+# Networking support
+#
+# CONFIG_NET is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+
+#
+# ISDN subsystem
+#
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
 # CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
 # CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+# CONFIG_MOUSE_SERIAL is not set
+# CONFIG_MOUSE_VSXXXAA is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
 
 #
 # Character devices
 #
-# CONFIG_VT is not set
-# CONFIG_SERIAL is not set
-CONFIG_SH_SCI=y
-CONFIG_SERIAL_CONSOLE=y
-# CONFIG_UNIX98_PTYS is not set
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_SH_SCI is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
 
 #
-# Joysticks
+# IPMI
 #
-# CONFIG_INPUT_GAMEPORT is not set
-# CONFIG_PSMOUSE is not set
+# CONFIG_IPMI_HANDLER is not set
 
 #
 # Watchdog Cards
 #
 # CONFIG_WATCHDOG is not set
 # CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Console display driver support
+#
+CONFIG_VGA_CONSOLE=y
+CONFIG_DUMMY_CONSOLE=y
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB_ARCH_HAS_HCD is not set
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
 
 #
 # File systems
 #
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+
+#
+# XFS support
+#
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
 # CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
-# CONFIG_REISERFS_FS is not set
-# CONFIG_REISERFS_CHECK is not set
-# CONFIG_REISERFS_PROC_INFO is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+# CONFIG_PROC_KCORE is not set
+CONFIG_SYSFS=y
+# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVPTS_FS_XATTR is not set
+# CONFIG_TMPFS is not set
+# CONFIG_HUGETLBFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
 # CONFIG_ADFS_FS is not set
-# CONFIG_ADFS_FS_RW is not set
 # CONFIG_AFFS_FS is not set
 # CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
 # CONFIG_BFS_FS is not set
-# CONFIG_EXT3_FS is not set
-# CONFIG_JBD is not set
-# CONFIG_JBD_DEBUG is not set
-# CONFIG_FAT_FS is not set
-# CONFIG_MSDOS_FS is not set
-# CONFIG_UMSDOS_FS is not set
-# CONFIG_VFAT_FS is not set
 # CONFIG_EFS_FS is not set
-# CONFIG_JFFS_FS is not set
-# CONFIG_JFFS2_FS is not set
 # CONFIG_CRAMFS is not set
-# CONFIG_TMPFS is not set
-CONFIG_RAMFS=y
-# CONFIG_ISO9660_FS is not set
-# CONFIG_JOLIET is not set
-# CONFIG_ZISOFS is not set
-# CONFIG_MINIX_FS is not set
 # CONFIG_VXFS_FS is not set
-# CONFIG_NTFS_FS is not set
-# CONFIG_NTFS_RW is not set
 # CONFIG_HPFS_FS is not set
-CONFIG_PROC_FS=y
-# CONFIG_DEVFS_FS is not set
-# CONFIG_DEVFS_MOUNT is not set
-# CONFIG_DEVFS_DEBUG is not set
-# CONFIG_DEVPTS_FS is not set
 # CONFIG_QNX4FS_FS is not set
-# CONFIG_QNX4FS_RW is not set
-# CONFIG_ROMFS_FS is not set
-CONFIG_EXT2_FS=y
 # CONFIG_SYSV_FS is not set
-# CONFIG_UDF_FS is not set
-# CONFIG_UDF_RW is not set
 # CONFIG_UFS_FS is not set
-# CONFIG_UFS_FS_WRITE is not set
-# CONFIG_NCPFS_NLS is not set
-# CONFIG_SMB_FS is not set
-# CONFIG_ZISOFS_FS is not set
-# CONFIG_ZLIB_FS_INFLATE is not set
 
 #
 # Partition Types
 #
 # CONFIG_PARTITION_ADVANCED is not set
 CONFIG_MSDOS_PARTITION=y
-# CONFIG_SMB_NLS is not set
-# CONFIG_NLS is not set
 
 #
-# Multimedia devices
+# Native Language Support
 #
-# CONFIG_VIDEO_DEV is not set
+# CONFIG_NLS is not set
 
 #
-# Sound
+# Profiling support
 #
-# CONFIG_SOUND is not set
+# CONFIG_PROFILING is not set
 
 #
 # Kernel hacking
 #
-# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_FRAME_POINTER is not set
 CONFIG_SH_STANDARD_BIOS=y
-CONFIG_SH_EARLY_PRINTK=y
+# CONFIG_EARLY_SCIF_CONSOLE is not set
+# CONFIG_EARLY_PRINTK is not set
+# CONFIG_KGDB is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Hardware crypto devices
+#
 
 #
 # Library routines
 #
+# CONFIG_CRC_CCITT is not set
 # CONFIG_CRC32 is not set
+# CONFIG_LIBCRC32C is not set
diff -Nru a/arch/sh/configs/cqreek_defconfig b/arch/sh/configs/cqreek_defconfig
--- a/arch/sh/configs/cqreek_defconfig	2005-03-11 12:51:47 -08:00
+++ b/arch/sh/configs/cqreek_defconfig	2005-03-11 12:51:47 -08:00
@@ -1,15 +1,46 @@
 #
-# Automatically generated by make menuconfig: don't edit
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.11-sh
+# Wed Mar  2 15:09:38 2005
 #
 CONFIG_SUPERH=y
 CONFIG_UID16=y
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
-# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
 
 #
 # Code maturity level options
 #
 CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_SWAP=y
+# CONFIG_SYSVIPC is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_SYSCTL is not set
+# CONFIG_AUDIT is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_HOTPLUG is not set
+# CONFIG_IKCONFIG is not set
+# CONFIG_EMBEDDED is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
 
 #
 # Loadable module support
@@ -17,10 +48,13 @@
 # CONFIG_MODULES is not set
 
 #
-# Processor type and features
+# System type
 #
 # CONFIG_SH_SOLUTION_ENGINE is not set
 # CONFIG_SH_7751_SOLUTION_ENGINE is not set
+# CONFIG_SH_7300_SOLUTION_ENGINE is not set
+# CONFIG_SH_73180_SOLUTION_ENGINE is not set
+# CONFIG_SH_7751_SYSTEMH is not set
 # CONFIG_SH_STB1_HARP is not set
 # CONFIG_SH_STB1_OVERDRIVE is not set
 # CONFIG_SH_HP620 is not set
@@ -29,55 +63,110 @@
 CONFIG_SH_CQREEK=y
 # CONFIG_SH_DMIDA is not set
 # CONFIG_SH_EC3104 is not set
+# CONFIG_SH_SATURN is not set
 # CONFIG_SH_DREAMCAST is not set
 # CONFIG_SH_CAT68701 is not set
 # CONFIG_SH_BIGSUR is not set
 # CONFIG_SH_SH2000 is not set
 # CONFIG_SH_ADX is not set
+# CONFIG_SH_MPC1211 is not set
+# CONFIG_SH_SH03 is not set
+# CONFIG_SH_SECUREEDGE5410 is not set
+# CONFIG_SH_HS7751RVOIP is not set
+# CONFIG_SH_RTS7751R2D is not set
+# CONFIG_SH_EDOSK7705 is not set
+# CONFIG_SH_SH4202_MICRODEV is not set
 # CONFIG_SH_UNKNOWN is not set
-CONFIG_SH_RTC=y
+# CONFIG_CPU_SH2 is not set
+CONFIG_CPU_SH3=y
+# CONFIG_CPU_SH4 is not set
+# CONFIG_CPU_SUBTYPE_SH7604 is not set
+# CONFIG_CPU_SUBTYPE_SH7300 is not set
+# CONFIG_CPU_SUBTYPE_SH7705 is not set
 # CONFIG_CPU_SUBTYPE_SH7707 is not set
 CONFIG_CPU_SUBTYPE_SH7708=y
 # CONFIG_CPU_SUBTYPE_SH7709 is not set
 # CONFIG_CPU_SUBTYPE_SH7750 is not set
 # CONFIG_CPU_SUBTYPE_SH7751 is not set
+# CONFIG_CPU_SUBTYPE_SH7760 is not set
+# CONFIG_CPU_SUBTYPE_SH73180 is not set
 # CONFIG_CPU_SUBTYPE_ST40STB1 is not set
-CONFIG_CPU_SH3=y
-# CONFIG_CPU_SH4 is not set
-CONFIG_CPU_LITTLE_ENDIAN=y
+# CONFIG_CPU_SUBTYPE_ST40GX1 is not set
+# CONFIG_CPU_SUBTYPE_SH4_202 is not set
+CONFIG_MMU=y
+# CONFIG_CMDLINE_BOOL is not set
 CONFIG_MEMORY_START=0x0c000000
 CONFIG_MEMORY_SIZE=0x00400000
-# CONFIG_DISCONTIGMEM is not set
+# CONFIG_MEMORY_OVERRIDE is not set
+CONFIG_SH_RTC=y
+CONFIG_SH_DSP=y
+CONFIG_SH_ADC=y
+CONFIG_ZERO_PAGE_OFFSET=0x00001000
+CONFIG_BOOT_LINK_OFFSET=0x00800000
+CONFIG_CPU_LITTLE_ENDIAN=y
+# CONFIG_PREEMPT is not set
+# CONFIG_UBC_WAKEUP is not set
+# CONFIG_SH_WRITETHROUGH is not set
+# CONFIG_SH_OCRAM is not set
+# CONFIG_SMP is not set
+CONFIG_SH_PCLK_CALC=y
+CONFIG_SH_PCLK_FREQ=1193182
 
 #
-# General setup
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# DMA support
 #
-CONFIG_ISA=y
-# CONFIG_EISA is not set
-# CONFIG_MCA is not set
-# CONFIG_SBUS is not set
-# CONFIG_NET is not set
-# CONFIG_CF_AREA5 is not set
-CONFIG_CF_AREA6=y
-CONFIG_CF_BASE_ADDR=0xb8000000
-# CONFIG_HD64461 is not set
-# CONFIG_HD64465 is not set
 # CONFIG_SH_DMA is not set
+
+#
+# Companion Chips
+#
+# CONFIG_HD6446X_SERIES is not set
+
+#
+# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
+#
 # CONFIG_PCI is not set
-# CONFIG_HOTPLUG is not set
-# CONFIG_PCMCIA is not set
-# CONFIG_SYSVIPC is not set
-# CONFIG_BSD_PROCESS_ACCT is not set
-# CONFIG_SYSCTL is not set
-CONFIG_KCORE_ELF=y
-# CONFIG_KCORE_AOUT is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PC-card bridges
+#
+
+#
+# PCI Hotplug Support
+#
+
+#
+# Executable file formats
+#
 CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_FLAT is not set
 # CONFIG_BINFMT_MISC is not set
 
 #
-# Parallel port support
+# SH initrd options
 #
-# CONFIG_PARPORT is not set
+# CONFIG_EMBEDDED_RAMDISK is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
 
 #
 # Memory Technology Devices (MTD)
@@ -85,190 +174,360 @@
 # CONFIG_MTD is not set
 
 #
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
 # Block devices
 #
 # CONFIG_BLK_DEV_FD is not set
-# CONFIG_BLK_DEV_XD is not set
-# CONFIG_PARIDE is not set
-# CONFIG_BLK_CPQ_DA is not set
-# CONFIG_BLK_CPQ_CISS_DA is not set
-# CONFIG_CISS_SCSI_TAPE is not set
-# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
 # CONFIG_BLK_DEV_LOOP is not set
-# CONFIG_BLK_DEV_NBD is not set
 CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
 CONFIG_BLK_DEV_RAM_SIZE=4096
 CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_LBD is not set
+# CONFIG_CDROM_PKTCDVD is not set
 
 #
-# Multi-device support (RAID and LVM)
+# IO Schedulers
 #
-# CONFIG_MD is not set
-# CONFIG_BLK_DEV_MD is not set
-# CONFIG_MD_LINEAR is not set
-# CONFIG_MD_RAID0 is not set
-# CONFIG_MD_RAID1 is not set
-# CONFIG_MD_RAID5 is not set
-# CONFIG_MD_MULTIPATH is not set
-# CONFIG_BLK_DEV_LVM is not set
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
 
 #
-# ATA/IDE/MFM/RLL support
+# ATA/ATAPI/MFM/RLL support
 #
 CONFIG_IDE=y
+CONFIG_IDE_MAX_HWIFS=4
+CONFIG_BLK_DEV_IDE=y
 
 #
-# IDE, ATA and ATAPI Block devices
+# Please see Documentation/ide.txt for help/info on IDE drives
 #
-CONFIG_BLK_DEV_IDE=y
-# CONFIG_BLK_DEV_HD_IDE is not set
-# CONFIG_BLK_DEV_HD is not set
+# CONFIG_BLK_DEV_IDE_SATA is not set
 CONFIG_BLK_DEV_IDEDISK=y
 # CONFIG_IDEDISK_MULTI_MODE is not set
-# CONFIG_BLK_DEV_IDEDISK_VENDOR is not set
-# CONFIG_BLK_DEV_IDEDISK_FUJITSU is not set
-# CONFIG_BLK_DEV_IDEDISK_IBM is not set
-# CONFIG_BLK_DEV_IDEDISK_MAXTOR is not set
-# CONFIG_BLK_DEV_IDEDISK_QUANTUM is not set
-# CONFIG_BLK_DEV_IDEDISK_SEAGATE is not set
-# CONFIG_BLK_DEV_IDEDISK_WD is not set
-# CONFIG_BLK_DEV_COMMERIAL is not set
-# CONFIG_BLK_DEV_TIVO is not set
-# CONFIG_BLK_DEV_IDECS is not set
 # CONFIG_BLK_DEV_IDECD is not set
 # CONFIG_BLK_DEV_IDETAPE is not set
 # CONFIG_BLK_DEV_IDEFLOPPY is not set
-# CONFIG_BLK_DEV_IDESCSI is not set
-# CONFIG_BLK_DEV_CMD640 is not set
-# CONFIG_BLK_DEV_CMD640_ENHANCED is not set
-# CONFIG_BLK_DEV_ISAPNP is not set
-# CONFIG_IDE_CHIPSETS is not set
+# CONFIG_IDE_TASK_IOCTL is not set
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+CONFIG_IDE_SH=y
+# CONFIG_IDE_ARM is not set
+# CONFIG_BLK_DEV_IDEDMA is not set
 # CONFIG_IDEDMA_AUTO is not set
-# CONFIG_DMA_NONPCI is not set
-# CONFIG_BLK_DEV_ATARAID is not set
-# CONFIG_BLK_DEV_ATARAID_PDC is not set
-# CONFIG_BLK_DEV_ATARAID_HPT is not set
+# CONFIG_BLK_DEV_HD is not set
 
 #
-# SCSI support
+# SCSI device support
 #
 # CONFIG_SCSI is not set
 
 #
-# Old CD-ROM drivers (not SCSI, not IDE)
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
+# Networking support
+#
+# CONFIG_NET is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+
+#
+# ISDN subsystem
+#
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
 #
-# CONFIG_CD_NO_IDESCSI is not set
+CONFIG_INPUT=y
 
 #
-# Input core support
+# Userland interfaces
 #
-# CONFIG_INPUT is not set
-# CONFIG_INPUT_KEYBDEV is not set
-# CONFIG_INPUT_MOUSEDEV is not set
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
 # CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
 # CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+# CONFIG_MOUSE_SERIAL is not set
+# CONFIG_MOUSE_VSXXXAA is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
 
 #
 # Character devices
 #
-# CONFIG_VT is not set
-# CONFIG_SERIAL is not set
-CONFIG_SH_SCI=y
-CONFIG_SERIAL_CONSOLE=y
-# CONFIG_UNIX98_PTYS is not set
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
 
 #
-# Joysticks
+# Non-8250 serial port support
 #
-# CONFIG_INPUT_GAMEPORT is not set
-# CONFIG_PSMOUSE is not set
+# CONFIG_SERIAL_SH_SCI is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
 
 #
 # Watchdog Cards
 #
 # CONFIG_WATCHDOG is not set
 # CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Console display driver support
+#
+CONFIG_VGA_CONSOLE=y
+CONFIG_DUMMY_CONSOLE=y
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB_ARCH_HAS_HCD is not set
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
 
 #
 # File systems
 #
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+
+#
+# XFS support
+#
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
 # CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
-# CONFIG_REISERFS_FS is not set
-# CONFIG_REISERFS_CHECK is not set
-# CONFIG_REISERFS_PROC_INFO is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+# CONFIG_PROC_KCORE is not set
+CONFIG_SYSFS=y
+# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVPTS_FS_XATTR is not set
+# CONFIG_TMPFS is not set
+# CONFIG_HUGETLBFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
 # CONFIG_ADFS_FS is not set
-# CONFIG_ADFS_FS_RW is not set
 # CONFIG_AFFS_FS is not set
 # CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
 # CONFIG_BFS_FS is not set
-# CONFIG_EXT3_FS is not set
-# CONFIG_JBD is not set
-# CONFIG_JBD_DEBUG is not set
-# CONFIG_FAT_FS is not set
-# CONFIG_MSDOS_FS is not set
-# CONFIG_UMSDOS_FS is not set
-# CONFIG_VFAT_FS is not set
 # CONFIG_EFS_FS is not set
-# CONFIG_JFFS_FS is not set
-# CONFIG_JFFS2_FS is not set
 # CONFIG_CRAMFS is not set
-# CONFIG_TMPFS is not set
-CONFIG_RAMFS=y
-# CONFIG_ISO9660_FS is not set
-# CONFIG_JOLIET is not set
-# CONFIG_ZISOFS is not set
-# CONFIG_MINIX_FS is not set
 # CONFIG_VXFS_FS is not set
-# CONFIG_NTFS_FS is not set
-# CONFIG_NTFS_RW is not set
 # CONFIG_HPFS_FS is not set
-CONFIG_PROC_FS=y
-# CONFIG_DEVFS_FS is not set
-# CONFIG_DEVFS_MOUNT is not set
-# CONFIG_DEVFS_DEBUG is not set
-# CONFIG_DEVPTS_FS is not set
 # CONFIG_QNX4FS_FS is not set
-# CONFIG_QNX4FS_RW is not set
-# CONFIG_ROMFS_FS is not set
-CONFIG_EXT2_FS=y
 # CONFIG_SYSV_FS is not set
-# CONFIG_UDF_FS is not set
-# CONFIG_UDF_RW is not set
 # CONFIG_UFS_FS is not set
-# CONFIG_UFS_FS_WRITE is not set
-# CONFIG_NCPFS_NLS is not set
-# CONFIG_SMB_FS is not set
-# CONFIG_ZISOFS_FS is not set
-# CONFIG_ZLIB_FS_INFLATE is not set
 
 #
 # Partition Types
 #
 # CONFIG_PARTITION_ADVANCED is not set
 CONFIG_MSDOS_PARTITION=y
-# CONFIG_SMB_NLS is not set
-# CONFIG_NLS is not set
 
 #
-# Multimedia devices
+# Native Language Support
 #
-# CONFIG_VIDEO_DEV is not set
+# CONFIG_NLS is not set
 
 #
-# Sound
+# Profiling support
 #
-# CONFIG_SOUND is not set
+# CONFIG_PROFILING is not set
 
 #
 # Kernel hacking
 #
-# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_FRAME_POINTER is not set
 CONFIG_SH_STANDARD_BIOS=y
-CONFIG_SH_EARLY_PRINTK=y
+# CONFIG_EARLY_PRINTK is not set
+# CONFIG_KGDB is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Hardware crypto devices
+#
 
 #
 # Library routines
 #
+# CONFIG_CRC_CCITT is not set
 # CONFIG_CRC32 is not set
+# CONFIG_LIBCRC32C is not set
diff -Nru a/arch/sh/configs/dreamcast_defconfig b/arch/sh/configs/dreamcast_defconfig
--- a/arch/sh/configs/dreamcast_defconfig	2005-03-11 12:51:47 -08:00
+++ b/arch/sh/configs/dreamcast_defconfig	2005-03-11 12:51:47 -08:00
@@ -1,36 +1,50 @@
 #
 # Automatically generated make config: don't edit
+# Linux kernel version: 2.6.11-sh
+# Wed Mar  2 15:09:40 2005
 #
 CONFIG_SUPERH=y
 CONFIG_UID16=y
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
 
 #
 # Code maturity level options
 #
 CONFIG_EXPERIMENTAL=y
 CONFIG_CLEAN_COMPILE=y
-# CONFIG_STANDALONE is not set
 CONFIG_BROKEN_ON_SMP=y
+CONFIG_LOCK_KERNEL=y
 
 #
 # General setup
 #
+CONFIG_LOCALVERSION=""
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
 CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
 CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_HOTPLUG=y
+CONFIG_KOBJECT_UEVENT=y
 # CONFIG_IKCONFIG is not set
 CONFIG_EMBEDDED=y
 CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
 CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
 
 #
 # Loadable module support
@@ -40,6 +54,7 @@
 # CONFIG_MODULE_FORCE_UNLOAD is not set
 CONFIG_OBSOLETE_MODPARM=y
 # CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_KMOD=y
 
 #
@@ -47,6 +62,8 @@
 #
 # CONFIG_SH_SOLUTION_ENGINE is not set
 # CONFIG_SH_7751_SOLUTION_ENGINE is not set
+# CONFIG_SH_7300_SOLUTION_ENGINE is not set
+# CONFIG_SH_73180_SOLUTION_ENGINE is not set
 # CONFIG_SH_7751_SYSTEMH is not set
 # CONFIG_SH_STB1_HARP is not set
 # CONFIG_SH_STB1_OVERDRIVE is not set
@@ -63,20 +80,29 @@
 # CONFIG_SH_SH2000 is not set
 # CONFIG_SH_ADX is not set
 # CONFIG_SH_MPC1211 is not set
+# CONFIG_SH_SH03 is not set
 # CONFIG_SH_SECUREEDGE5410 is not set
+# CONFIG_SH_HS7751RVOIP is not set
+# CONFIG_SH_RTS7751R2D is not set
+# CONFIG_SH_EDOSK7705 is not set
+# CONFIG_SH_SH4202_MICRODEV is not set
 # CONFIG_SH_UNKNOWN is not set
 # CONFIG_CPU_SH2 is not set
 # CONFIG_CPU_SH3 is not set
 CONFIG_CPU_SH4=y
 # CONFIG_CPU_SUBTYPE_SH7604 is not set
 # CONFIG_CPU_SUBTYPE_SH7300 is not set
+# CONFIG_CPU_SUBTYPE_SH7705 is not set
 # CONFIG_CPU_SUBTYPE_SH7707 is not set
 # CONFIG_CPU_SUBTYPE_SH7708 is not set
 # CONFIG_CPU_SUBTYPE_SH7709 is not set
 CONFIG_CPU_SUBTYPE_SH7750=y
 # CONFIG_CPU_SUBTYPE_SH7751 is not set
 # CONFIG_CPU_SUBTYPE_SH7760 is not set
+# CONFIG_CPU_SUBTYPE_SH73180 is not set
 # CONFIG_CPU_SUBTYPE_ST40STB1 is not set
+# CONFIG_CPU_SUBTYPE_ST40GX1 is not set
+# CONFIG_CPU_SUBTYPE_SH4_202 is not set
 CONFIG_MMU=y
 CONFIG_HUGETLB_PAGE_SIZE_64K=y
 # CONFIG_HUGETLB_PAGE_SIZE_1MB is not set
@@ -85,6 +111,7 @@
 CONFIG_MEMORY_SIZE=0x01000000
 CONFIG_MEMORY_SET=y
 # CONFIG_MEMORY_OVERRIDE is not set
+CONFIG_SH_FPU=y
 CONFIG_ZERO_PAGE_OFFSET=0x00001000
 CONFIG_BOOT_LINK_OFFSET=0x00800000
 CONFIG_CPU_LITTLE_ENDIAN=y
@@ -94,25 +121,36 @@
 CONFIG_SH_OCRAM=y
 CONFIG_SH_STORE_QUEUES=y
 # CONFIG_SMP is not set
+CONFIG_SH_PCLK_CALC=y
 CONFIG_SH_PCLK_FREQ=49876504
 
 #
 # CPU Frequency scaling
 #
 CONFIG_CPU_FREQ=y
-# CONFIG_CPU_FREQ_PROC_INTF is not set
+# CONFIG_CPU_FREQ_DEBUG is not set
+CONFIG_CPU_FREQ_STAT=y
+# CONFIG_CPU_FREQ_STAT_DETAILS is not set
 CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y
 # CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set
 CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
 CONFIG_CPU_FREQ_GOV_POWERSAVE=y
 CONFIG_CPU_FREQ_GOV_USERSPACE=y
-# CONFIG_CPU_FREQ_24_API is not set
+# CONFIG_CPU_FREQ_GOV_ONDEMAND is not set
 CONFIG_CPU_FREQ_TABLE=y
 CONFIG_SH_CPU_FREQ=y
+
+#
+# DMA support
+#
 CONFIG_SH_DMA=y
 CONFIG_NR_ONCHIP_DMA_CHANNELS=4
 CONFIG_NR_DMA_CHANNELS_BOOL=y
 CONFIG_NR_DMA_CHANNELS=9
+
+#
+# Companion Chips
+#
 # CONFIG_HD6446X_SERIES is not set
 
 #
@@ -126,9 +164,13 @@
 CONFIG_PCI_NAMES=y
 
 #
-# PCMCIA/CardBus support
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PC-card bridges
 #
-# CONFIG_PCMCIA is not set
 
 #
 # PCI Hotplug Support
@@ -143,12 +185,19 @@
 # CONFIG_BINFMT_MISC is not set
 
 #
+# SH initrd options
+#
+# CONFIG_EMBEDDED_RAMDISK is not set
+
+#
 # Device Drivers
 #
 
 #
 # Generic Driver Options
 #
+# CONFIG_STANDALONE is not set
+CONFIG_PREVENT_FIRMWARE_BUILD=y
 # CONFIG_FW_LOADER is not set
 
 #
@@ -173,12 +222,26 @@
 # CONFIG_BLK_CPQ_CISS_DA is not set
 # CONFIG_BLK_DEV_DAC960 is not set
 # CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
 # CONFIG_BLK_DEV_LOOP is not set
 # CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_SX8 is not set
 CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
 CONFIG_BLK_DEV_RAM_SIZE=1024
 CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_LBD is not set
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
 
 #
 # ATA/ATAPI/MFM/RLL support
@@ -210,10 +273,6 @@
 # CONFIG_I2O is not set
 
 #
-# Macintosh device drivers
-#
-
-#
 # Networking support
 #
 CONFIG_NET=y
@@ -236,23 +295,24 @@
 # CONFIG_NET_IPIP is not set
 # CONFIG_NET_IPGRE is not set
 # CONFIG_ARPD is not set
-# CONFIG_INET_ECN is not set
 # CONFIG_SYN_COOKIES is not set
 # CONFIG_INET_AH is not set
 # CONFIG_INET_ESP is not set
 # CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_IP_TCPDIAG=y
+# CONFIG_IP_TCPDIAG_IPV6 is not set
 # CONFIG_IPV6 is not set
-# CONFIG_DECNET is not set
-# CONFIG_BRIDGE is not set
 # CONFIG_NETFILTER is not set
 
 #
 # SCTP Configuration (EXPERIMENTAL)
 #
-CONFIG_IPV6_SCTP__=y
 # CONFIG_IP_SCTP is not set
 # CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
 # CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
 # CONFIG_LLC2 is not set
 # CONFIG_IPX is not set
 # CONFIG_ATALK is not set
@@ -261,27 +321,32 @@
 # CONFIG_NET_DIVERT is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
-# CONFIG_NET_HW_FLOWCONTROL is not set
 
 #
 # QoS and/or fair queueing
 #
 # CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
 
 #
 # Network testing
 #
 # CONFIG_NET_PKTGEN is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
 CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
 
 #
 # ARCnet devices
 #
 # CONFIG_ARCNET is not set
-# CONFIG_DUMMY is not set
-# CONFIG_BONDING is not set
-# CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
 
 #
 # Ethernet (10 or 100Mbit)
@@ -292,6 +357,7 @@
 # CONFIG_HAPPYMEAL is not set
 # CONFIG_SUNGEM is not set
 # CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_SMC91X is not set
 
 #
 # Tulip family network device support
@@ -316,7 +382,6 @@
 # CONFIG_8139TOO_TUNE_TWISTER is not set
 # CONFIG_8139TOO_8129 is not set
 # CONFIG_8139_OLD_RX_RESET is not set
-CONFIG_8139_RXBUF_IDX=1
 # CONFIG_SIS900 is not set
 # CONFIG_EPIC100 is not set
 # CONFIG_SUNDANCE is not set
@@ -333,50 +398,36 @@
 # CONFIG_HAMACHI is not set
 # CONFIG_YELLOWFIN is not set
 # CONFIG_R8169 is not set
-# CONFIG_SIS190 is not set
 # CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
 
 #
 # Ethernet (10000 Mbit)
 #
 # CONFIG_IXGB is not set
-# CONFIG_FDDI is not set
-# CONFIG_HIPPI is not set
-# CONFIG_PPP is not set
-# CONFIG_SLIP is not set
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
+# CONFIG_S2IO is not set
 
 #
 # Token Ring devices
 #
 # CONFIG_TR is not set
-# CONFIG_RCPCI is not set
-# CONFIG_SHAPER is not set
-
-#
-# Wan interfaces
-#
-# CONFIG_WAN is not set
 
 #
-# Amateur Radio support
-#
-# CONFIG_HAMRADIO is not set
-
-#
-# IrDA (infrared) support
+# Wireless LAN (non-hamradio)
 #
-# CONFIG_IRDA is not set
+# CONFIG_NET_RADIO is not set
 
 #
-# Bluetooth support
+# Wan interfaces
 #
-# CONFIG_BT is not set
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
 
 #
 # ISDN subsystem
@@ -415,6 +466,8 @@
 # CONFIG_SERIO_SERPORT is not set
 # CONFIG_SERIO_CT82C710 is not set
 # CONFIG_SERIO_PCIPS2 is not set
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
 
 #
 # Input Device Drivers
@@ -422,6 +475,7 @@
 CONFIG_INPUT_KEYBOARD=y
 CONFIG_KEYBOARD_ATKBD=y
 # CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
 # CONFIG_KEYBOARD_XTKBD is not set
 # CONFIG_KEYBOARD_NEWTON is not set
 # CONFIG_KEYBOARD_MAPLE is not set
@@ -429,6 +483,7 @@
 CONFIG_MOUSE_PS2=y
 # CONFIG_MOUSE_SERIAL is not set
 # CONFIG_MOUSE_MAPLE is not set
+# CONFIG_MOUSE_VSXXXAA is not set
 # CONFIG_INPUT_JOYSTICK is not set
 # CONFIG_INPUT_TOUCHSCREEN is not set
 # CONFIG_INPUT_MISC is not set
@@ -458,12 +513,6 @@
 CONFIG_LEGACY_PTY_COUNT=256
 
 #
-# Mice
-#
-# CONFIG_BUSMOUSE is not set
-# CONFIG_QIC02_TAPE is not set
-
-#
 # IPMI
 #
 # CONFIG_IPMI_HANDLER is not set
@@ -485,7 +534,6 @@
 #
 # CONFIG_PCIPCWATCHDOG is not set
 # CONFIG_WDTPCI is not set
-# CONFIG_NVRAM is not set
 # CONFIG_RTC is not set
 # CONFIG_GEN_RTC is not set
 # CONFIG_DTLK is not set
@@ -495,8 +543,6 @@
 #
 # Ftape, the floppy tape device driver
 #
-# CONFIG_FTAPE is not set
-# CONFIG_AGP is not set
 # CONFIG_DRM is not set
 # CONFIG_RAW_DRIVER is not set
 
@@ -506,6 +552,11 @@
 # CONFIG_I2C is not set
 
 #
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
 # Misc devices
 #
 
@@ -523,18 +574,22 @@
 # Graphics support
 #
 CONFIG_FB=y
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+# CONFIG_FB_CIRRUS is not set
 # CONFIG_FB_PM2 is not set
 # CONFIG_FB_CYBER2000 is not set
 # CONFIG_FB_ASILIANT is not set
 # CONFIG_FB_IMSTT is not set
 CONFIG_FB_PVR2=y
-# CONFIG_FB_E1355 is not set
+# CONFIG_FB_EPSON1355 is not set
 # CONFIG_FB_RIVA is not set
 # CONFIG_FB_MATROX is not set
 # CONFIG_FB_RADEON_OLD is not set
 # CONFIG_FB_RADEON is not set
 # CONFIG_FB_ATY128 is not set
 # CONFIG_FB_ATY is not set
+# CONFIG_FB_SAVAGE is not set
 # CONFIG_FB_SIS is not set
 # CONFIG_FB_NEOMAGIC is not set
 # CONFIG_FB_KYRO is not set
@@ -547,10 +602,8 @@
 # Console display driver support
 #
 # CONFIG_VGA_CONSOLE is not set
-# CONFIG_MDA_CONSOLE is not set
 CONFIG_DUMMY_CONSOLE=y
 CONFIG_FRAMEBUFFER_CONSOLE=y
-CONFIG_PCI_CONSOLE=y
 CONFIG_FONTS=y
 CONFIG_FONT_8x8=y
 CONFIG_FONT_8x16=y
@@ -571,6 +624,7 @@
 # CONFIG_LOGO_SUPERH_MONO is not set
 # CONFIG_LOGO_SUPERH_VGA16 is not set
 CONFIG_LOGO_SUPERH_CLUT224=y
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
 # Sound
@@ -581,6 +635,12 @@
 # USB support
 #
 # CONFIG_USB is not set
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
 
 #
 # USB Gadget Support
@@ -588,10 +648,14 @@
 # CONFIG_USB_GADGET is not set
 
 #
-# Maple Bus input peripherals
+# MMC/SD Card support
 #
-# CONFIG_MAPLE_KEYBOARD is not set
-# CONFIG_MAPLE_MOUSE is not set
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
 
 #
 # File systems
@@ -601,10 +665,15 @@
 # CONFIG_JBD is not set
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
+
+#
+# XFS support
+#
 # CONFIG_XFS_FS is not set
 # CONFIG_MINIX_FS is not set
 CONFIG_ROMFS_FS=y
 # CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
 
@@ -617,7 +686,8 @@
 #
 # DOS/FAT/NT Filesystems
 #
-# CONFIG_FAT_FS is not set
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
 # CONFIG_NTFS_FS is not set
 
 #
@@ -625,11 +695,13 @@
 #
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
 CONFIG_DEVFS_FS=y
 CONFIG_DEVFS_MOUNT=y
 # CONFIG_DEVFS_DEBUG is not set
 # CONFIG_DEVPTS_FS_XATTR is not set
 CONFIG_TMPFS=y
+# CONFIG_TMPFS_XATTR is not set
 CONFIG_HUGETLBFS=y
 CONFIG_HUGETLB_PAGE=y
 CONFIG_RAMFS=y
@@ -662,9 +734,9 @@
 CONFIG_ROOT_NFS=y
 CONFIG_LOCKD=y
 CONFIG_LOCKD_V4=y
-# CONFIG_EXPORTFS is not set
 CONFIG_SUNRPC=y
-# CONFIG_SUNRPC_GSS is not set
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
 # CONFIG_SMB_FS is not set
 # CONFIG_CIFS is not set
 # CONFIG_NCP_FS is not set
@@ -691,15 +763,17 @@
 #
 # Kernel hacking
 #
-CONFIG_MAGIC_SYSRQ=y
-# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_DEBUG_PREEMPT=y
+# CONFIG_FRAME_POINTER is not set
 # CONFIG_SH_STANDARD_BIOS is not set
+# CONFIG_EARLY_SCIF_CONSOLE is not set
 # CONFIG_KGDB is not set
-# CONFIG_FRAME_POINTER is not set
 
 #
 # Security options
 #
+# CONFIG_KEYS is not set
 # CONFIG_SECURITY is not set
 
 #
@@ -708,7 +782,13 @@
 # CONFIG_CRYPTO is not set
 
 #
+# Hardware crypto devices
+#
+
+#
 # Library routines
 #
+# CONFIG_CRC_CCITT is not set
 CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
 CONFIG_ZLIB_INFLATE=y
diff -Nru a/arch/sh/configs/hp680_defconfig b/arch/sh/configs/hp680_defconfig
--- a/arch/sh/configs/hp680_defconfig	2005-03-11 12:51:52 -08:00
+++ b/arch/sh/configs/hp680_defconfig	2005-03-11 12:51:52 -08:00
@@ -1,36 +1,47 @@
 #
 # Automatically generated make config: don't edit
+# Linux kernel version: 2.6.11-sh
+# Wed Mar  2 15:09:41 2005
 #
 CONFIG_SUPERH=y
 CONFIG_UID16=y
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
 
 #
 # Code maturity level options
 #
 CONFIG_EXPERIMENTAL=y
 # CONFIG_CLEAN_COMPILE is not set
-# CONFIG_STANDALONE is not set
 CONFIG_BROKEN=y
 CONFIG_BROKEN_ON_SMP=y
 
 #
 # General setup
 #
+CONFIG_LOCALVERSION=""
 CONFIG_SWAP=y
 # CONFIG_SYSVIPC is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
 # CONFIG_SYSCTL is not set
+# CONFIG_AUDIT is not set
 CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_HOTPLUG is not set
 # CONFIG_IKCONFIG is not set
 # CONFIG_EMBEDDED is not set
 CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
 
 #
 # Loadable module support
@@ -42,6 +53,8 @@
 #
 # CONFIG_SH_SOLUTION_ENGINE is not set
 # CONFIG_SH_7751_SOLUTION_ENGINE is not set
+# CONFIG_SH_7300_SOLUTION_ENGINE is not set
+# CONFIG_SH_73180_SOLUTION_ENGINE is not set
 # CONFIG_SH_7751_SYSTEMH is not set
 # CONFIG_SH_STB1_HARP is not set
 # CONFIG_SH_STB1_OVERDRIVE is not set
@@ -58,20 +71,29 @@
 # CONFIG_SH_SH2000 is not set
 # CONFIG_SH_ADX is not set
 # CONFIG_SH_MPC1211 is not set
+# CONFIG_SH_SH03 is not set
 # CONFIG_SH_SECUREEDGE5410 is not set
+# CONFIG_SH_HS7751RVOIP is not set
+# CONFIG_SH_RTS7751R2D is not set
+# CONFIG_SH_EDOSK7705 is not set
+# CONFIG_SH_SH4202_MICRODEV is not set
 # CONFIG_SH_UNKNOWN is not set
 # CONFIG_CPU_SH2 is not set
 CONFIG_CPU_SH3=y
 # CONFIG_CPU_SH4 is not set
 # CONFIG_CPU_SUBTYPE_SH7604 is not set
 # CONFIG_CPU_SUBTYPE_SH7300 is not set
+# CONFIG_CPU_SUBTYPE_SH7705 is not set
 # CONFIG_CPU_SUBTYPE_SH7707 is not set
 # CONFIG_CPU_SUBTYPE_SH7708 is not set
 CONFIG_CPU_SUBTYPE_SH7709=y
 # CONFIG_CPU_SUBTYPE_SH7750 is not set
 # CONFIG_CPU_SUBTYPE_SH7751 is not set
 # CONFIG_CPU_SUBTYPE_SH7760 is not set
+# CONFIG_CPU_SUBTYPE_SH73180 is not set
 # CONFIG_CPU_SUBTYPE_ST40STB1 is not set
+# CONFIG_CPU_SUBTYPE_ST40GX1 is not set
+# CONFIG_CPU_SUBTYPE_SH4_202 is not set
 CONFIG_MMU=y
 # CONFIG_CMDLINE_BOOL is not set
 CONFIG_MEMORY_START=0x0c000000
@@ -80,6 +102,7 @@
 # CONFIG_MEMORY_OVERRIDE is not set
 CONFIG_SH_RTC=y
 # CONFIG_SH_DSP is not set
+CONFIG_SH_ADC=y
 CONFIG_SH_HP600=y
 CONFIG_ZERO_PAGE_OFFSET=0x00001000
 CONFIG_BOOT_LINK_OFFSET=0x00800000
@@ -89,9 +112,22 @@
 # CONFIG_SH_WRITETHROUGH is not set
 # CONFIG_SH_OCRAM is not set
 # CONFIG_SMP is not set
+CONFIG_SH_PCLK_CALC=y
 CONFIG_SH_PCLK_FREQ=1193182
+
+#
+# CPU Frequency scaling
+#
 # CONFIG_CPU_FREQ is not set
+
+#
+# DMA support
+#
 # CONFIG_SH_DMA is not set
+
+#
+# Companion Chips
+#
 CONFIG_HD6446X_SERIES=y
 CONFIG_HD64461=y
 # CONFIG_HD64465 is not set
@@ -102,7 +138,19 @@
 # Bus options (PCI, PCMCIA, EISA, MCA, ISA)
 #
 # CONFIG_PCI is not set
-# CONFIG_HOTPLUG is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PC-card bridges
+#
+
+#
+# PCI Hotplug Support
+#
 
 #
 # Executable file formats
@@ -112,8 +160,20 @@
 # CONFIG_BINFMT_MISC is not set
 
 #
+# SH initrd options
+#
+# CONFIG_EMBEDDED_RAMDISK is not set
+
+#
+# Device Drivers
+#
+
+#
 # Generic Driver Options
 #
+# CONFIG_STANDALONE is not set
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
 
 #
 # Memory Technology Devices (MTD)
@@ -126,40 +186,57 @@
 # CONFIG_PARPORT is not set
 
 #
+# Plug and Play support
+#
+
+#
 # Block devices
 #
 # CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
 # CONFIG_BLK_DEV_LOOP is not set
 CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
 CONFIG_BLK_DEV_RAM_SIZE=4096
 CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_LBD is not set
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
 
 #
 # ATA/ATAPI/MFM/RLL support
 #
 CONFIG_IDE=y
+CONFIG_IDE_MAX_HWIFS=4
 CONFIG_BLK_DEV_IDE=y
 
 #
 # Please see Documentation/ide.txt for help/info on IDE drives
 #
+# CONFIG_BLK_DEV_IDE_SATA is not set
 CONFIG_BLK_DEV_IDEDISK=y
 # CONFIG_IDEDISK_MULTI_MODE is not set
-# CONFIG_IDEDISK_STROKE is not set
 # CONFIG_BLK_DEV_IDECD is not set
 # CONFIG_BLK_DEV_IDETAPE is not set
 # CONFIG_BLK_DEV_IDEFLOPPY is not set
 # CONFIG_IDE_TASK_IOCTL is not set
-# CONFIG_IDE_TASKFILE_IO is not set
 
 #
 # IDE chipset support/bugfixes
 #
 CONFIG_IDE_GENERIC=y
+CONFIG_IDE_SH=y
+# CONFIG_IDE_ARM is not set
 # CONFIG_BLK_DEV_IDEDMA is not set
 # CONFIG_IDEDMA_AUTO is not set
-# CONFIG_DMA_NONPCI is not set
 # CONFIG_BLK_DEV_HD is not set
 
 #
@@ -173,19 +250,24 @@
 # CONFIG_MD is not set
 
 #
-# IEEE 1394 (FireWire) support (EXPERIMENTAL)
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
 #
 # CONFIG_IEEE1394 is not set
 
 #
-# Networking support
+# I2O device support
 #
-# CONFIG_NET is not set
 
 #
-# Amateur Radio support
+# Networking support
 #
-# CONFIG_HAMRADIO is not set
+# CONFIG_NET is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
 
 #
 # ISDN subsystem
@@ -222,6 +304,7 @@
 # CONFIG_SERIO_I8042 is not set
 # CONFIG_SERIO_SERPORT is not set
 # CONFIG_SERIO_CT82C710 is not set
+# CONFIG_SERIO_RAW is not set
 
 #
 # Input Device Drivers
@@ -238,33 +321,125 @@
 CONFIG_VT=y
 CONFIG_VT_CONSOLE=y
 CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
 
 #
-# Unix98 PTY support
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
 #
-# CONFIG_UNIX98_PTYS is not set
-# CONFIG_PSMOUSE is not set
+# CONFIG_SERIAL_SH_SCI is not set
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
 
 #
 # Watchdog Cards
 #
 # CONFIG_WATCHDOG is not set
 # CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
 
 #
-# Serial drivers
+# Ftape, the floppy tape device driver
 #
-# CONFIG_SERIAL_8250 is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
 
 #
-# Non-8250 serial port support
+# I2C support
 #
-# CONFIG_SERIAL_SH_SCI is not set
+# CONFIG_I2C is not set
 
 #
-# I2C support
+# Dallas's 1-wire bus
 #
-# CONFIG_I2C is not set
+# CONFIG_W1 is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+
+#
+# Graphics support
+#
+CONFIG_FB=y
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+# CONFIG_FB_EPSON1355 is not set
+CONFIG_FB_HIT=y
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_FONTS=y
+# CONFIG_FONT_8x8 is not set
+# CONFIG_FONT_8x16 is not set
+# CONFIG_FONT_6x11 is not set
+CONFIG_FONT_PEARL_8x8=y
+# CONFIG_FONT_ACORN_8x8 is not set
+# CONFIG_FONT_MINI_4x6 is not set
+# CONFIG_FONT_SUN8x16 is not set
+# CONFIG_FONT_SUN12x22 is not set
+
+#
+# Logo configuration
+#
+# CONFIG_LOGO is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB_ARCH_HAS_HCD is not set
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
 
 #
 # File systems
@@ -275,10 +450,15 @@
 # CONFIG_JBD is not set
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
+
+#
+# XFS support
+#
 # CONFIG_XFS_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
 # CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
 
@@ -291,7 +471,8 @@
 #
 # DOS/FAT/NT Filesystems
 #
-# CONFIG_FAT_FS is not set
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
 # CONFIG_NTFS_FS is not set
 
 #
@@ -299,9 +480,11 @@
 #
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
 CONFIG_DEVFS_FS=y
 CONFIG_DEVFS_MOUNT=y
 # CONFIG_DEVFS_DEBUG is not set
+# CONFIG_DEVPTS_FS_XATTR is not set
 # CONFIG_TMPFS is not set
 # CONFIG_HUGETLBFS is not set
 # CONFIG_HUGETLB_PAGE is not set
@@ -313,6 +496,7 @@
 # CONFIG_ADFS_FS is not set
 # CONFIG_AFFS_FS is not set
 # CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
 # CONFIG_BEFS_FS is not set
 # CONFIG_BFS_FS is not set
 # CONFIG_EFS_FS is not set
@@ -335,60 +519,6 @@
 # CONFIG_NLS is not set
 
 #
-# Multimedia devices
-#
-# CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-
-#
-# Graphics support
-#
-CONFIG_FB=y
-# CONFIG_FB_E1355 is not set
-CONFIG_FB_HIT=y
-# CONFIG_FB_VIRTUAL is not set
-
-#
-# Console display driver support
-#
-# CONFIG_VGA_CONSOLE is not set
-# CONFIG_MDA_CONSOLE is not set
-CONFIG_DUMMY_CONSOLE=y
-CONFIG_FRAMEBUFFER_CONSOLE=y
-CONFIG_PCI_CONSOLE=y
-CONFIG_FONTS=y
-# CONFIG_FONT_8x8 is not set
-# CONFIG_FONT_8x16 is not set
-# CONFIG_FONT_6x11 is not set
-CONFIG_FONT_PEARL_8x8=y
-# CONFIG_FONT_ACORN_8x8 is not set
-# CONFIG_FONT_MINI_4x6 is not set
-# CONFIG_FONT_SUN8x16 is not set
-# CONFIG_FONT_SUN12x22 is not set
-
-#
-# Logo configuration
-#
-# CONFIG_LOGO is not set
-
-#
-# Sound
-#
-# CONFIG_SOUND is not set
-
-#
-# USB support
-#
-
-#
-# USB Gadget Support
-#
-# CONFIG_USB_GADGET is not set
-
-#
 # Profiling support
 #
 # CONFIG_PROFILING is not set
@@ -396,15 +526,15 @@
 #
 # Kernel hacking
 #
-# CONFIG_MAGIC_SYSRQ is not set
-# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_FRAME_POINTER is not set
 # CONFIG_SH_STANDARD_BIOS is not set
 # CONFIG_KGDB is not set
-# CONFIG_FRAME_POINTER is not set
 
 #
 # Security options
 #
+# CONFIG_KEYS is not set
 # CONFIG_SECURITY is not set
 
 #
@@ -413,6 +543,12 @@
 # CONFIG_CRYPTO is not set
 
 #
+# Hardware crypto devices
+#
+
+#
 # Library routines
 #
-# CONFIG_CRC32 is not set
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
diff -Nru a/arch/sh/configs/microdev_defconfig b/arch/sh/configs/microdev_defconfig
--- a/arch/sh/configs/microdev_defconfig	2005-03-11 12:51:50 -08:00
+++ b/arch/sh/configs/microdev_defconfig	2005-03-11 12:51:50 -08:00
@@ -1,9 +1,14 @@
 #
 # Automatically generated make config: don't edit
+# Linux kernel version: 2.6.11-sh
+# Wed Mar  2 15:09:41 2005
 #
 CONFIG_SUPERH=y
 CONFIG_UID16=y
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
 
 #
 # Code maturity level options
@@ -11,10 +16,12 @@
 CONFIG_EXPERIMENTAL=y
 CONFIG_CLEAN_COMPILE=y
 CONFIG_BROKEN_ON_SMP=y
+CONFIG_LOCK_KERNEL=y
 
 #
 # General setup
 #
+CONFIG_LOCALVERSION=""
 CONFIG_SWAP=y
 # CONFIG_SYSVIPC is not set
 # CONFIG_POSIX_MQUEUE is not set
@@ -24,17 +31,20 @@
 # CONFIG_AUDIT is not set
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_HOTPLUG=y
+CONFIG_KOBJECT_UEVENT=y
 # CONFIG_IKCONFIG is not set
 CONFIG_EMBEDDED=y
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
 
 #
 # Loadable module support
@@ -133,9 +143,13 @@
 # CONFIG_PCI is not set
 
 #
-# PCMCIA/CardBus support
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PC-card bridges
 #
-# CONFIG_PCMCIA is not set
 CONFIG_PCMCIA_PROBE=y
 
 #
@@ -185,12 +199,25 @@
 #
 # CONFIG_BLK_DEV_FD is not set
 # CONFIG_BLK_DEV_XD is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
 # CONFIG_BLK_DEV_LOOP is not set
 # CONFIG_BLK_DEV_NBD is not set
 CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
 CONFIG_BLK_DEV_RAM_SIZE=4096
 CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_LBD is not set
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
 
 #
 # ATA/ATAPI/MFM/RLL support
@@ -209,7 +236,6 @@
 # CONFIG_BLK_DEV_IDETAPE is not set
 # CONFIG_BLK_DEV_IDEFLOPPY is not set
 # CONFIG_IDE_TASK_IOCTL is not set
-# CONFIG_IDE_TASKFILE_IO is not set
 
 #
 # IDE chipset support/bugfixes
@@ -275,6 +301,9 @@
 # CONFIG_INET_AH is not set
 # CONFIG_INET_ESP is not set
 # CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_IP_TCPDIAG=y
+# CONFIG_IP_TCPDIAG_IPV6 is not set
 # CONFIG_IPV6 is not set
 # CONFIG_NETFILTER is not set
 
@@ -294,7 +323,6 @@
 # CONFIG_NET_DIVERT is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
-# CONFIG_NET_HW_FLOWCONTROL is not set
 
 #
 # QoS and/or fair queueing
@@ -419,7 +447,6 @@
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
-# CONFIG_QIC02_TAPE is not set
 
 #
 # IPMI
@@ -437,7 +464,6 @@
 #
 # Ftape, the floppy tape device driver
 #
-# CONFIG_AGP is not set
 # CONFIG_DRM is not set
 # CONFIG_RAW_DRIVER is not set
 
@@ -478,6 +504,12 @@
 #
 # USB support
 #
+# CONFIG_USB_ARCH_HAS_HCD is not set
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
 
 #
 # USB Gadget Support
@@ -485,6 +517,16 @@
 # CONFIG_USB_GADGET is not set
 
 #
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -498,10 +540,15 @@
 CONFIG_FS_MBCACHE=y
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
+
+#
+# XFS support
+#
 # CONFIG_XFS_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
 # CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
 
@@ -533,6 +580,7 @@
 CONFIG_DEVPTS_FS_XATTR=y
 # CONFIG_DEVPTS_FS_SECURITY is not set
 CONFIG_TMPFS=y
+# CONFIG_TMPFS_XATTR is not set
 # CONFIG_HUGETLBFS is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
@@ -565,10 +613,10 @@
 CONFIG_ROOT_NFS=y
 CONFIG_LOCKD=y
 CONFIG_LOCKD_V4=y
-# CONFIG_EXPORTFS is not set
 CONFIG_SUNRPC=y
 CONFIG_SUNRPC_GSS=y
 CONFIG_RPCSEC_GSS_KRB5=y
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
 # CONFIG_SMB_FS is not set
 # CONFIG_CIFS is not set
 # CONFIG_NCP_FS is not set
@@ -633,17 +681,17 @@
 #
 # Kernel hacking
 #
-CONFIG_MAGIC_SYSRQ=y
-# CONFIG_DEBUG_SPINLOCK is not set
-# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_DEBUG_PREEMPT=y
+# CONFIG_FRAME_POINTER is not set
 # CONFIG_SH_STANDARD_BIOS is not set
 # CONFIG_EARLY_SCIF_CONSOLE is not set
 # CONFIG_KGDB is not set
-# CONFIG_FRAME_POINTER is not set
 
 #
 # Security options
 #
+# CONFIG_KEYS is not set
 # CONFIG_SECURITY is not set
 
 #
@@ -657,6 +705,7 @@
 # CONFIG_CRYPTO_SHA1 is not set
 # CONFIG_CRYPTO_SHA256 is not set
 # CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_WP512 is not set
 CONFIG_CRYPTO_DES=y
 # CONFIG_CRYPTO_BLOWFISH is not set
 # CONFIG_CRYPTO_TWOFISH is not set
@@ -667,10 +716,15 @@
 # CONFIG_CRYPTO_TEA is not set
 # CONFIG_CRYPTO_ARC4 is not set
 # CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_ANUBIS is not set
 # CONFIG_CRYPTO_DEFLATE is not set
 # CONFIG_CRYPTO_MICHAEL_MIC is not set
 # CONFIG_CRYPTO_CRC32C is not set
 # CONFIG_CRYPTO_TEST is not set
+
+#
+# Hardware crypto devices
+#
 
 #
 # Library routines
diff -Nru a/arch/sh/configs/rts7751r2d_defconfig b/arch/sh/configs/rts7751r2d_defconfig
--- a/arch/sh/configs/rts7751r2d_defconfig	2005-03-11 12:51:47 -08:00
+++ b/arch/sh/configs/rts7751r2d_defconfig	2005-03-11 12:51:47 -08:00
@@ -1,21 +1,26 @@
 #
 # Automatically generated make config: don't edit
+# Linux kernel version: 2.6.11-sh
+# Wed Mar  2 15:09:42 2005
 #
 CONFIG_SUPERH=y
 CONFIG_UID16=y
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
 
 #
 # Code maturity level options
 #
 CONFIG_EXPERIMENTAL=y
 CONFIG_CLEAN_COMPILE=y
-CONFIG_STANDALONE=y
 CONFIG_BROKEN_ON_SMP=y
 
 #
 # General setup
 #
+CONFIG_LOCALVERSION=""
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
 # CONFIG_POSIX_MQUEUE is not set
@@ -24,16 +29,20 @@
 # CONFIG_AUDIT is not set
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_HOTPLUG=y
+CONFIG_KOBJECT_UEVENT=y
 # CONFIG_IKCONFIG is not set
 CONFIG_EMBEDDED=y
 CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
 
 #
 # Loadable module support
@@ -42,6 +51,7 @@
 # CONFIG_MODULE_UNLOAD is not set
 CONFIG_OBSOLETE_MODPARM=y
 # CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
 # CONFIG_KMOD is not set
 
 #
@@ -50,6 +60,7 @@
 # CONFIG_SH_SOLUTION_ENGINE is not set
 # CONFIG_SH_7751_SOLUTION_ENGINE is not set
 # CONFIG_SH_7300_SOLUTION_ENGINE is not set
+# CONFIG_SH_73180_SOLUTION_ENGINE is not set
 # CONFIG_SH_7751_SYSTEMH is not set
 # CONFIG_SH_STB1_HARP is not set
 # CONFIG_SH_STB1_OVERDRIVE is not set
@@ -66,9 +77,12 @@
 # CONFIG_SH_SH2000 is not set
 # CONFIG_SH_ADX is not set
 # CONFIG_SH_MPC1211 is not set
+# CONFIG_SH_SH03 is not set
 # CONFIG_SH_SECUREEDGE5410 is not set
 # CONFIG_SH_HS7751RVOIP is not set
 CONFIG_SH_RTS7751R2D=y
+# CONFIG_SH_EDOSK7705 is not set
+# CONFIG_SH_SH4202_MICRODEV is not set
 # CONFIG_SH_UNKNOWN is not set
 # CONFIG_CPU_SH2 is not set
 # CONFIG_CPU_SH3 is not set
@@ -82,8 +96,10 @@
 # CONFIG_CPU_SUBTYPE_SH7750 is not set
 CONFIG_CPU_SUBTYPE_SH7751=y
 # CONFIG_CPU_SUBTYPE_SH7760 is not set
+# CONFIG_CPU_SUBTYPE_SH73180 is not set
 # CONFIG_CPU_SUBTYPE_ST40STB1 is not set
 # CONFIG_CPU_SUBTYPE_ST40GX1 is not set
+# CONFIG_CPU_SUBTYPE_SH4_202 is not set
 CONFIG_MMU=y
 CONFIG_CMDLINE_BOOL=y
 CONFIG_CMDLINE="mem=64M console=ttySC0,115200 root=/dev/hda1"
@@ -92,6 +108,7 @@
 CONFIG_MEMORY_SET=y
 # CONFIG_MEMORY_OVERRIDE is not set
 CONFIG_SH_RTC=y
+CONFIG_SH_FPU=y
 CONFIG_ZERO_PAGE_OFFSET=0x00010000
 CONFIG_BOOT_LINK_OFFSET=0x00800000
 CONFIG_CPU_LITTLE_ENDIAN=y
@@ -128,7 +145,6 @@
 #
 # Bus options (PCI, PCMCIA, EISA, MCA, ISA)
 #
-CONFIG_ISA=y
 CONFIG_PCI=y
 CONFIG_SH_PCIDMA_NONCOHERENT=y
 CONFIG_PCI_AUTO=y
@@ -137,16 +153,13 @@
 CONFIG_PCI_NAMES=y
 
 #
-# PCMCIA/CardBus support
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PC-card bridges
 #
-CONFIG_PCMCIA=m
-# CONFIG_PCMCIA_DEBUG is not set
-CONFIG_YENTA=m
-CONFIG_CARDBUS=y
-# CONFIG_I82092 is not set
-# CONFIG_I82365 is not set
-# CONFIG_TCIC is not set
-CONFIG_PCMCIA_PROBE=y
 
 #
 # PCI Hotplug Support
@@ -154,7 +167,6 @@
 CONFIG_HOTPLUG_PCI=y
 # CONFIG_HOTPLUG_PCI_FAKE is not set
 # CONFIG_HOTPLUG_PCI_CPCI is not set
-# CONFIG_HOTPLUG_PCI_PCIE is not set
 # CONFIG_HOTPLUG_PCI_SHPC is not set
 
 #
@@ -171,6 +183,8 @@
 #
 # Generic Driver Options
 #
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
 # CONFIG_FW_LOADER is not set
 
 #
@@ -186,24 +200,35 @@
 #
 # Plug and Play support
 #
-# CONFIG_PNP is not set
 
 #
 # Block devices
 #
 # CONFIG_BLK_DEV_FD is not set
-# CONFIG_BLK_DEV_XD is not set
 # CONFIG_BLK_CPQ_DA is not set
 # CONFIG_BLK_CPQ_CISS_DA is not set
 # CONFIG_BLK_DEV_DAC960 is not set
 # CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
 # CONFIG_BLK_DEV_LOOP is not set
 # CONFIG_BLK_DEV_NBD is not set
-# CONFIG_BLK_DEV_CARMEL is not set
+# CONFIG_BLK_DEV_SX8 is not set
 CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
 CONFIG_BLK_DEV_RAM_SIZE=4096
 # CONFIG_BLK_DEV_INITRD is not set
+CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_LBD is not set
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
 
 #
 # ATA/ATAPI/MFM/RLL support
@@ -215,14 +240,13 @@
 #
 # Please see Documentation/ide.txt for help/info on IDE drives
 #
+# CONFIG_BLK_DEV_IDE_SATA is not set
 CONFIG_BLK_DEV_IDEDISK=y
 # CONFIG_IDEDISK_MULTI_MODE is not set
-CONFIG_BLK_DEV_IDECS=m
 # CONFIG_BLK_DEV_IDECD is not set
 # CONFIG_BLK_DEV_IDETAPE is not set
 # CONFIG_BLK_DEV_IDEFLOPPY is not set
 # CONFIG_IDE_TASK_IOCTL is not set
-# CONFIG_IDE_TASKFILE_IO is not set
 
 #
 # IDE chipset support/bugfixes
@@ -231,7 +255,6 @@
 # CONFIG_BLK_DEV_IDEPCI is not set
 CONFIG_IDE_SH=y
 # CONFIG_IDE_ARM is not set
-# CONFIG_IDE_CHIPSETS is not set
 # CONFIG_BLK_DEV_IDEDMA is not set
 # CONFIG_IDEDMA_AUTO is not set
 # CONFIG_BLK_DEV_HD is not set
@@ -242,11 +265,6 @@
 # CONFIG_SCSI is not set
 
 #
-# Old CD-ROM drivers (not SCSI, not IDE)
-#
-# CONFIG_CD_NO_IDESCSI is not set
-
-#
 # Multi-device support (RAID and LVM)
 #
 # CONFIG_MD is not set
@@ -289,6 +307,9 @@
 # CONFIG_INET_AH is not set
 # CONFIG_INET_ESP is not set
 # CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_IP_TCPDIAG=y
+# CONFIG_IP_TCPDIAG_IPV6 is not set
 # CONFIG_IPV6 is not set
 # CONFIG_NETFILTER is not set
 
@@ -308,13 +329,12 @@
 # CONFIG_NET_DIVERT is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
-# CONFIG_NET_FASTROUTE is not set
-# CONFIG_NET_HW_FLOWCONTROL is not set
 
 #
 # QoS and/or fair queueing
 #
 # CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
 
 #
 # Network testing
@@ -345,38 +365,19 @@
 # CONFIG_HAPPYMEAL is not set
 # CONFIG_SUNGEM is not set
 # CONFIG_NET_VENDOR_3COM is not set
-# CONFIG_LANCE is not set
-# CONFIG_NET_VENDOR_SMC is not set
-# CONFIG_NET_VENDOR_RACAL is not set
+# CONFIG_SMC91X is not set
 
 #
 # Tulip family network device support
 #
 # CONFIG_NET_TULIP is not set
-# CONFIG_AT1700 is not set
-# CONFIG_DEPCA is not set
 # CONFIG_HP100 is not set
-CONFIG_NET_ISA=y
-# CONFIG_E2100 is not set
-# CONFIG_EWRK3 is not set
-# CONFIG_EEXPRESS is not set
-# CONFIG_EEXPRESS_PRO is not set
-# CONFIG_HPLAN_PLUS is not set
-# CONFIG_HPLAN is not set
-# CONFIG_LP486E is not set
-# CONFIG_ETH16I is not set
-CONFIG_NE2000=m
-# CONFIG_ZNET is not set
-# CONFIG_SEEQ8005 is not set
 CONFIG_NET_PCI=y
 # CONFIG_PCNET32 is not set
 # CONFIG_AMD8111_ETH is not set
 # CONFIG_ADAPTEC_STARFIRE is not set
-# CONFIG_AC3200 is not set
-# CONFIG_APRICOT is not set
 # CONFIG_B44 is not set
 # CONFIG_FORCEDETH is not set
-# CONFIG_CS89x0 is not set
 # CONFIG_DGRS is not set
 # CONFIG_EEPRO100 is not set
 # CONFIG_E100 is not set
@@ -394,7 +395,6 @@
 # CONFIG_SUNDANCE is not set
 # CONFIG_TLAN is not set
 # CONFIG_VIA_RHINE is not set
-# CONFIG_NET_POCKET is not set
 
 #
 # Ethernet (1000 Mbit)
@@ -407,6 +407,7 @@
 # CONFIG_YELLOWFIN is not set
 # CONFIG_R8169 is not set
 # CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
 
 #
@@ -429,20 +430,10 @@
 # Obsolete Wireless cards support (pre-802.11)
 #
 # CONFIG_STRIP is not set
-# CONFIG_ARLAN is not set
-# CONFIG_WAVELAN is not set
-# CONFIG_PCMCIA_WAVELAN is not set
-# CONFIG_PCMCIA_NETWAVE is not set
-
-#
-# Wireless 802.11 Frequency Hopping cards support
-#
-# CONFIG_PCMCIA_RAYCS is not set
 
 #
 # Wireless 802.11b ISA/PCI cards support
 #
-# CONFIG_AIRO is not set
 CONFIG_HERMES=m
 # CONFIG_PLX_HERMES is not set
 # CONFIG_TMD_HERMES is not set
@@ -450,24 +441,12 @@
 # CONFIG_ATMEL is not set
 
 #
-# Wireless 802.11b Pcmcia/Cardbus cards support
-#
-CONFIG_PCMCIA_HERMES=m
-# CONFIG_AIRO_CS is not set
-# CONFIG_PCMCIA_WL3501 is not set
-
-#
 # Prism GT/Duette 802.11(a/b/g) PCI/Cardbus support
 #
 # CONFIG_PRISM54 is not set
 CONFIG_NET_WIRELESS=y
 
 #
-# PCMCIA network device support
-#
-# CONFIG_NET_PCMCIA is not set
-
-#
 # Wan interfaces
 #
 # CONFIG_WAN is not set
@@ -527,7 +506,6 @@
 # CONFIG_UNIX98_PTYS is not set
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
-# CONFIG_QIC02_TAPE is not set
 
 #
 # IPMI
@@ -547,14 +525,7 @@
 #
 # Ftape, the floppy tape device driver
 #
-# CONFIG_FTAPE is not set
-# CONFIG_AGP is not set
 # CONFIG_DRM is not set
-
-#
-# PCMCIA character devices
-#
-# CONFIG_SYNCLINK_CS is not set
 # CONFIG_RAW_DRIVER is not set
 
 #
@@ -563,6 +534,11 @@
 # CONFIG_I2C is not set
 
 #
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
 # Misc devices
 #
 
@@ -611,37 +587,12 @@
 # CONFIG_SND_MPU401 is not set
 
 #
-# ISA devices
-#
-# CONFIG_SND_AD1848 is not set
-# CONFIG_SND_CS4231 is not set
-# CONFIG_SND_CS4232 is not set
-# CONFIG_SND_CS4236 is not set
-# CONFIG_SND_ES1688 is not set
-# CONFIG_SND_ES18XX is not set
-# CONFIG_SND_GUSCLASSIC is not set
-# CONFIG_SND_GUSEXTREME is not set
-# CONFIG_SND_GUSMAX is not set
-# CONFIG_SND_INTERWAVE is not set
-# CONFIG_SND_INTERWAVE_STB is not set
-# CONFIG_SND_OPTI92X_AD1848 is not set
-# CONFIG_SND_OPTI92X_CS4231 is not set
-# CONFIG_SND_OPTI93X is not set
-# CONFIG_SND_SB8 is not set
-# CONFIG_SND_SB16 is not set
-# CONFIG_SND_SBAWE is not set
-# CONFIG_SND_WAVEFRONT is not set
-# CONFIG_SND_CMI8330 is not set
-# CONFIG_SND_OPL3SA2 is not set
-# CONFIG_SND_SGALAXY is not set
-# CONFIG_SND_SSCAPE is not set
-
-#
 # PCI devices
 #
 CONFIG_SND_AC97_CODEC=m
 # CONFIG_SND_ALI5451 is not set
 # CONFIG_SND_ATIIXP is not set
+# CONFIG_SND_ATIIXP_MODEM is not set
 # CONFIG_SND_AU8810 is not set
 # CONFIG_SND_AU8820 is not set
 # CONFIG_SND_AU8830 is not set
@@ -650,6 +601,8 @@
 # CONFIG_SND_CS46XX is not set
 # CONFIG_SND_CS4281 is not set
 # CONFIG_SND_EMU10K1 is not set
+# CONFIG_SND_EMU10K1X is not set
+# CONFIG_SND_CA0106 is not set
 # CONFIG_SND_KORG1212 is not set
 # CONFIG_SND_MIXART is not set
 # CONFIG_SND_NM256 is not set
@@ -673,16 +626,10 @@
 # CONFIG_SND_INTEL8X0M is not set
 # CONFIG_SND_SONICVIBES is not set
 # CONFIG_SND_VIA82XX is not set
+# CONFIG_SND_VIA82XX_MODEM is not set
 # CONFIG_SND_VX222 is not set
 
 #
-# PCMCIA devices
-#
-# CONFIG_SND_VXPOCKET is not set
-# CONFIG_SND_VXP440 is not set
-# CONFIG_SND_PDAUDIOCF is not set
-
-#
 # Open Sound System
 #
 CONFIG_SOUND_PRIME=m
@@ -713,6 +660,12 @@
 # USB support
 #
 # CONFIG_USB is not set
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
 
 #
 # USB Gadget Support
@@ -720,6 +673,16 @@
 # CONFIG_USB_GADGET is not set
 
 #
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -728,10 +691,15 @@
 # CONFIG_JBD is not set
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
+
+#
+# XFS support
+#
 # CONFIG_XFS_FS is not set
 CONFIG_MINIX_FS=y
 # CONFIG_ROMFS_FS is not set
 # CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
 
@@ -747,6 +715,8 @@
 CONFIG_FAT_FS=y
 CONFIG_MSDOS_FS=y
 CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
 # CONFIG_NTFS_FS is not set
 
 #
@@ -783,7 +753,6 @@
 #
 # CONFIG_NFS_FS is not set
 # CONFIG_NFSD is not set
-# CONFIG_EXPORTFS is not set
 # CONFIG_SMB_FS is not set
 # CONFIG_CIFS is not set
 # CONFIG_NCP_FS is not set
@@ -824,6 +793,7 @@
 # CONFIG_NLS_ISO8859_8 is not set
 # CONFIG_NLS_CODEPAGE_1250 is not set
 # CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
 # CONFIG_NLS_ISO8859_1 is not set
 # CONFIG_NLS_ISO8859_2 is not set
 # CONFIG_NLS_ISO8859_3 is not set
@@ -848,17 +818,16 @@
 #
 # Kernel hacking
 #
-# CONFIG_MAGIC_SYSRQ is not set
-# CONFIG_DEBUG_SPINLOCK is not set
-# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_FRAME_POINTER is not set
 # CONFIG_SH_STANDARD_BIOS is not set
 # CONFIG_EARLY_SCIF_CONSOLE is not set
 # CONFIG_KGDB is not set
-# CONFIG_FRAME_POINTER is not set
 
 #
 # Security options
 #
+# CONFIG_KEYS is not set
 # CONFIG_SECURITY is not set
 
 #
@@ -867,7 +836,12 @@
 # CONFIG_CRYPTO is not set
 
 #
+# Hardware crypto devices
+#
+
+#
 # Library routines
 #
+# CONFIG_CRC_CCITT is not set
 CONFIG_CRC32=y
 # CONFIG_LIBCRC32C is not set
diff -Nru a/arch/sh/configs/se7300_defconfig b/arch/sh/configs/se7300_defconfig
--- a/arch/sh/configs/se7300_defconfig	2005-03-11 12:51:46 -08:00
+++ b/arch/sh/configs/se7300_defconfig	2005-03-11 12:51:46 -08:00
@@ -1,24 +1,28 @@
 #
 # Automatically generated make config: don't edit
+# Linux kernel version: 2.6.11-sh
+# Wed Mar  2 15:09:43 2005
 #
 CONFIG_SUPERH=y
 CONFIG_UID16=y
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
 
 #
 # Code maturity level options
 #
 CONFIG_EXPERIMENTAL=y
 CONFIG_CLEAN_COMPILE=y
-CONFIG_STANDALONE=y
 CONFIG_BROKEN_ON_SMP=y
 
 #
 # General setup
 #
+CONFIG_LOCALVERSION=""
 # CONFIG_SWAP is not set
 # CONFIG_SYSVIPC is not set
-# CONFIG_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
 CONFIG_SYSCTL=y
 # CONFIG_AUDIT is not set
@@ -29,11 +33,13 @@
 # CONFIG_KALLSYMS is not set
 # CONFIG_FUTEX is not set
 # CONFIG_EPOLL is not set
-CONFIG_IOSCHED_NOOP=y
-# CONFIG_IOSCHED_AS is not set
-# CONFIG_IOSCHED_DEADLINE is not set
-# CONFIG_IOSCHED_CFQ is not set
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
 
 #
 # Loadable module support
@@ -46,6 +52,7 @@
 # CONFIG_SH_SOLUTION_ENGINE is not set
 # CONFIG_SH_7751_SOLUTION_ENGINE is not set
 CONFIG_SH_7300_SOLUTION_ENGINE=y
+# CONFIG_SH_73180_SOLUTION_ENGINE is not set
 # CONFIG_SH_7751_SYSTEMH is not set
 # CONFIG_SH_STB1_HARP is not set
 # CONFIG_SH_STB1_OVERDRIVE is not set
@@ -62,23 +69,29 @@
 # CONFIG_SH_SH2000 is not set
 # CONFIG_SH_ADX is not set
 # CONFIG_SH_MPC1211 is not set
+# CONFIG_SH_SH03 is not set
 # CONFIG_SH_SECUREEDGE5410 is not set
 # CONFIG_SH_HS7751RVOIP is not set
 # CONFIG_SH_RTS7751R2D is not set
+# CONFIG_SH_EDOSK7705 is not set
+# CONFIG_SH_SH4202_MICRODEV is not set
 # CONFIG_SH_UNKNOWN is not set
 # CONFIG_CPU_SH2 is not set
 CONFIG_CPU_SH3=y
 # CONFIG_CPU_SH4 is not set
 # CONFIG_CPU_SUBTYPE_SH7604 is not set
 CONFIG_CPU_SUBTYPE_SH7300=y
+# CONFIG_CPU_SUBTYPE_SH7705 is not set
 # CONFIG_CPU_SUBTYPE_SH7707 is not set
 # CONFIG_CPU_SUBTYPE_SH7708 is not set
 # CONFIG_CPU_SUBTYPE_SH7709 is not set
 # CONFIG_CPU_SUBTYPE_SH7750 is not set
 # CONFIG_CPU_SUBTYPE_SH7751 is not set
 # CONFIG_CPU_SUBTYPE_SH7760 is not set
+# CONFIG_CPU_SUBTYPE_SH73180 is not set
 # CONFIG_CPU_SUBTYPE_ST40STB1 is not set
 # CONFIG_CPU_SUBTYPE_ST40GX1 is not set
+# CONFIG_CPU_SUBTYPE_SH4_202 is not set
 CONFIG_MMU=y
 CONFIG_CMDLINE_BOOL=y
 CONFIG_CMDLINE="console=ttySC0,38400 root=/dev/ram0"
@@ -120,6 +133,19 @@
 # CONFIG_PCI is not set
 
 #
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PC-card bridges
+#
+
+#
+# PCI Hotplug Support
+#
+
+#
 # Executable file formats
 #
 CONFIG_BINFMT_ELF=y
@@ -139,6 +165,9 @@
 #
 # Generic Driver Options
 #
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
 
 #
 # Memory Technology Devices (MTD)
@@ -158,11 +187,23 @@
 # Block devices
 #
 # CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
 # CONFIG_BLK_DEV_LOOP is not set
 CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
 CONFIG_BLK_DEV_RAM_SIZE=4096
 CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_LBD is not set
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_AS is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
 
 #
 # ATA/ATAPI/MFM/RLL support
@@ -186,7 +227,6 @@
 #
 # IEEE 1394 (FireWire) support
 #
-# CONFIG_IEEE1394 is not set
 
 #
 # I2O device support
@@ -234,6 +274,8 @@
 # CONFIG_SERIO_I8042 is not set
 # CONFIG_SERIO_SERPORT is not set
 # CONFIG_SERIO_CT82C710 is not set
+# CONFIG_SERIO_LIBPS2 is not set
+# CONFIG_SERIO_RAW is not set
 
 #
 # Input Device Drivers
@@ -264,7 +306,6 @@
 CONFIG_SERIAL_CORE_CONSOLE=y
 # CONFIG_UNIX98_PTYS is not set
 # CONFIG_LEGACY_PTYS is not set
-# CONFIG_QIC02_TAPE is not set
 
 #
 # IPMI
@@ -274,6 +315,7 @@
 CONFIG_IPMI_DEVICE_INTERFACE=y
 # CONFIG_IPMI_SI is not set
 CONFIG_IPMI_WATCHDOG=y
+# CONFIG_IPMI_POWEROFF is not set
 
 #
 # Watchdog Cards
@@ -290,13 +332,10 @@
 # CONFIG_GEN_RTC is not set
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
 
 #
 # Ftape, the floppy tape device driver
 #
-# CONFIG_FTAPE is not set
-# CONFIG_AGP is not set
 # CONFIG_DRM is not set
 # CONFIG_RAW_DRIVER is not set
 
@@ -306,6 +345,11 @@
 # CONFIG_I2C is not set
 
 #
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
 # Misc devices
 #
 
@@ -331,6 +375,12 @@
 #
 # USB support
 #
+# CONFIG_USB_ARCH_HAS_HCD is not set
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
 
 #
 # USB Gadget Support
@@ -338,6 +388,16 @@
 # CONFIG_USB_GADGET is not set
 
 #
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -346,10 +406,15 @@
 # CONFIG_JBD is not set
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
+
+#
+# XFS support
+#
 # CONFIG_XFS_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
 # CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
 
@@ -362,7 +427,8 @@
 #
 # DOS/FAT/NT Filesystems
 #
-# CONFIG_FAT_FS is not set
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
 # CONFIG_NTFS_FS is not set
 
 #
@@ -415,9 +481,8 @@
 #
 # Kernel hacking
 #
-# CONFIG_MAGIC_SYSRQ is not set
-# CONFIG_DEBUG_SPINLOCK is not set
-# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_FRAME_POINTER is not set
 CONFIG_SH_STANDARD_BIOS=y
 CONFIG_EARLY_PRINTK=y
 CONFIG_KGDB=y
@@ -442,11 +507,11 @@
 # CONFIG_KGDB_DEFPARITY_O is not set
 CONFIG_KGDB_DEFBITS_8=y
 # CONFIG_KGDB_DEFBITS_7 is not set
-# CONFIG_FRAME_POINTER is not set
 
 #
 # Security options
 #
+# CONFIG_KEYS is not set
 # CONFIG_SECURITY is not set
 
 #
@@ -455,7 +520,12 @@
 # CONFIG_CRYPTO is not set
 
 #
+# Hardware crypto devices
+#
+
+#
 # Library routines
 #
+# CONFIG_CRC_CCITT is not set
 CONFIG_CRC32=y
 # CONFIG_LIBCRC32C is not set
diff -Nru a/arch/sh/configs/se73180_defconfig b/arch/sh/configs/se73180_defconfig
--- a/arch/sh/configs/se73180_defconfig	2005-03-11 12:51:41 -08:00
+++ b/arch/sh/configs/se73180_defconfig	2005-03-11 12:51:41 -08:00
@@ -1,24 +1,28 @@
 #
 # Automatically generated make config: don't edit
+# Linux kernel version: 2.6.11-sh
+# Wed Mar  2 15:09:44 2005
 #
 CONFIG_SUPERH=y
 CONFIG_UID16=y
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
 
 #
 # Code maturity level options
 #
 CONFIG_EXPERIMENTAL=y
 CONFIG_CLEAN_COMPILE=y
-CONFIG_STANDALONE=y
 CONFIG_BROKEN_ON_SMP=y
 
 #
 # General setup
 #
+CONFIG_LOCALVERSION=""
 CONFIG_SWAP=y
 # CONFIG_SYSVIPC is not set
-# CONFIG_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
 # CONFIG_SYSCTL is not set
 # CONFIG_AUDIT is not set
@@ -29,11 +33,13 @@
 # CONFIG_KALLSYMS is not set
 # CONFIG_FUTEX is not set
 # CONFIG_EPOLL is not set
-CONFIG_IOSCHED_NOOP=y
-# CONFIG_IOSCHED_AS is not set
-# CONFIG_IOSCHED_DEADLINE is not set
-# CONFIG_IOSCHED_CFQ is not set
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
 
 #
 # Loadable module support
@@ -42,6 +48,7 @@
 # CONFIG_MODULE_UNLOAD is not set
 CONFIG_OBSOLETE_MODPARM=y
 # CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
 # CONFIG_KMOD is not set
 
 #
@@ -67,9 +74,12 @@
 # CONFIG_SH_SH2000 is not set
 # CONFIG_SH_ADX is not set
 # CONFIG_SH_MPC1211 is not set
+# CONFIG_SH_SH03 is not set
 # CONFIG_SH_SECUREEDGE5410 is not set
 # CONFIG_SH_HS7751RVOIP is not set
 # CONFIG_SH_RTS7751R2D is not set
+# CONFIG_SH_EDOSK7705 is not set
+# CONFIG_SH_SH4202_MICRODEV is not set
 # CONFIG_SH_UNKNOWN is not set
 # CONFIG_CPU_SH2 is not set
 # CONFIG_CPU_SH3 is not set
@@ -86,6 +96,7 @@
 CONFIG_CPU_SUBTYPE_SH73180=y
 # CONFIG_CPU_SUBTYPE_ST40STB1 is not set
 # CONFIG_CPU_SUBTYPE_ST40GX1 is not set
+# CONFIG_CPU_SUBTYPE_SH4_202 is not set
 CONFIG_MMU=y
 CONFIG_CMDLINE_BOOL=y
 CONFIG_CMDLINE="console=ttySC0,38400 root=/dev/ram"
@@ -127,6 +138,19 @@
 # CONFIG_PCI is not set
 
 #
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PC-card bridges
+#
+
+#
+# PCI Hotplug Support
+#
+
+#
 # Executable file formats
 #
 CONFIG_BINFMT_ELF=y
@@ -146,6 +170,9 @@
 #
 # Generic Driver Options
 #
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
 
 #
 # Memory Technology Devices (MTD)
@@ -165,12 +192,24 @@
 # Block devices
 #
 # CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
 CONFIG_BLK_DEV_LOOP=y
 # CONFIG_BLK_DEV_CRYPTOLOOP is not set
 CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
 CONFIG_BLK_DEV_RAM_SIZE=4096
 CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_LBD is not set
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+# CONFIG_IOSCHED_AS is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
 
 #
 # ATA/ATAPI/MFM/RLL support
@@ -194,7 +233,6 @@
 #
 # IEEE 1394 (FireWire) support
 #
-# CONFIG_IEEE1394 is not set
 
 #
 # I2O device support
@@ -257,7 +295,6 @@
 CONFIG_SERIAL_CORE_CONSOLE=y
 # CONFIG_UNIX98_PTYS is not set
 # CONFIG_LEGACY_PTYS is not set
-# CONFIG_QIC02_TAPE is not set
 
 #
 # IPMI
@@ -279,13 +316,10 @@
 # CONFIG_GEN_RTC is not set
 # CONFIG_DTLK is not set
 # CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
 
 #
 # Ftape, the floppy tape device driver
 #
-# CONFIG_FTAPE is not set
-# CONFIG_AGP is not set
 # CONFIG_DRM is not set
 # CONFIG_RAW_DRIVER is not set
 
@@ -295,6 +329,11 @@
 # CONFIG_I2C is not set
 
 #
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
 # Misc devices
 #
 
@@ -320,6 +359,12 @@
 #
 # USB support
 #
+# CONFIG_USB_ARCH_HAS_HCD is not set
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
 
 #
 # USB Gadget Support
@@ -327,6 +372,16 @@
 # CONFIG_USB_GADGET is not set
 
 #
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -335,10 +390,15 @@
 # CONFIG_JBD is not set
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
+
+#
+# XFS support
+#
 # CONFIG_XFS_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
 # CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
 
@@ -351,7 +411,8 @@
 #
 # DOS/FAT/NT Filesystems
 #
-# CONFIG_FAT_FS is not set
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
 # CONFIG_NTFS_FS is not set
 
 #
@@ -364,6 +425,7 @@
 CONFIG_DEVFS_MOUNT=y
 # CONFIG_DEVFS_DEBUG is not set
 CONFIG_TMPFS=y
+# CONFIG_TMPFS_XATTR is not set
 # CONFIG_HUGETLBFS is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
@@ -404,18 +466,17 @@
 #
 # Kernel hacking
 #
-# CONFIG_MAGIC_SYSRQ is not set
-# CONFIG_DEBUG_SPINLOCK is not set
-# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_FRAME_POINTER is not set
 CONFIG_SH_STANDARD_BIOS=y
 # CONFIG_EARLY_SCIF_CONSOLE is not set
 # CONFIG_EARLY_PRINTK is not set
 # CONFIG_KGDB is not set
-# CONFIG_FRAME_POINTER is not set
 
 #
 # Security options
 #
+# CONFIG_KEYS is not set
 # CONFIG_SECURITY is not set
 
 #
@@ -424,7 +485,12 @@
 # CONFIG_CRYPTO is not set
 
 #
+# Hardware crypto devices
+#
+
+#
 # Library routines
 #
+# CONFIG_CRC_CCITT is not set
 CONFIG_CRC32=y
 # CONFIG_LIBCRC32C is not set
diff -Nru a/arch/sh/configs/se7705_defconfig b/arch/sh/configs/se7705_defconfig
--- a/arch/sh/configs/se7705_defconfig	2005-03-11 12:51:46 -08:00
+++ b/arch/sh/configs/se7705_defconfig	2005-03-11 12:51:46 -08:00
@@ -1,9 +1,14 @@
 #
 # Automatically generated make config: don't edit
+# Linux kernel version: 2.6.11-sh
+# Wed Mar  2 15:09:45 2005
 #
 CONFIG_SUPERH=y
 CONFIG_UID16=y
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
 
 #
 # Code maturity level options
@@ -11,10 +16,12 @@
 CONFIG_EXPERIMENTAL=y
 CONFIG_CLEAN_COMPILE=y
 CONFIG_BROKEN_ON_SMP=y
+CONFIG_LOCK_KERNEL=y
 
 #
 # General setup
 #
+CONFIG_LOCALVERSION=""
 # CONFIG_SWAP is not set
 # CONFIG_SYSVIPC is not set
 # CONFIG_POSIX_MQUEUE is not set
@@ -23,16 +30,19 @@
 # CONFIG_AUDIT is not set
 CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_HOTPLUG is not set
+CONFIG_KOBJECT_UEVENT=y
 # CONFIG_IKCONFIG is not set
 CONFIG_EMBEDDED=y
 # CONFIG_KALLSYMS is not set
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
-# CONFIG_IOSCHED_NOOP is not set
-CONFIG_IOSCHED_AS=y
-# CONFIG_IOSCHED_DEADLINE is not set
-# CONFIG_IOSCHED_CFQ is not set
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
 
 #
 # Loadable module support
@@ -41,6 +51,7 @@
 # CONFIG_MODULE_UNLOAD is not set
 CONFIG_OBSOLETE_MODPARM=y
 # CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_KMOD=y
 
 #
@@ -66,6 +77,7 @@
 # CONFIG_SH_SH2000 is not set
 # CONFIG_SH_ADX is not set
 # CONFIG_SH_MPC1211 is not set
+# CONFIG_SH_SH03 is not set
 # CONFIG_SH_SECUREEDGE5410 is not set
 # CONFIG_SH_HS7751RVOIP is not set
 # CONFIG_SH_RTS7751R2D is not set
@@ -132,6 +144,19 @@
 # CONFIG_PCI is not set
 
 #
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PC-card bridges
+#
+
+#
+# PCI Hotplug Support
+#
+
+#
 # Executable file formats
 #
 CONFIG_BINFMT_ELF=y
@@ -152,6 +177,7 @@
 #
 CONFIG_STANDALONE=y
 CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
 
 #
 # Memory Technology Devices (MTD)
@@ -215,6 +241,7 @@
 # CONFIG_MTD_PHRAM is not set
 # CONFIG_MTD_MTDRAM is not set
 # CONFIG_MTD_BLKMTD is not set
+# CONFIG_MTD_BLOCK2MTD is not set
 
 #
 # Disk-On-Chip Device Drivers
@@ -241,12 +268,25 @@
 # Block devices
 #
 # CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
 # CONFIG_BLK_DEV_LOOP is not set
 # CONFIG_BLK_DEV_NBD is not set
 CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
 CONFIG_BLK_DEV_RAM_SIZE=8192
 CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_LBD is not set
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
+# CONFIG_ATA_OVER_ETH is not set
 
 #
 # ATA/ATAPI/MFM/RLL support
@@ -302,6 +342,9 @@
 # CONFIG_INET_AH is not set
 # CONFIG_INET_ESP is not set
 # CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_IP_TCPDIAG=y
+# CONFIG_IP_TCPDIAG_IPV6 is not set
 # CONFIG_IPV6 is not set
 # CONFIG_NETFILTER is not set
 
@@ -321,7 +364,6 @@
 # CONFIG_NET_DIVERT is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
-# CONFIG_NET_HW_FLOWCONTROL is not set
 
 #
 # QoS and/or fair queueing
@@ -350,6 +392,7 @@
 CONFIG_NET_ETHERNET=y
 # CONFIG_MII is not set
 CONFIG_STNIC=y
+# CONFIG_SMC91X is not set
 
 #
 # Ethernet (1000 Mbit)
@@ -417,6 +460,8 @@
 # CONFIG_SERIO_I8042 is not set
 # CONFIG_SERIO_SERPORT is not set
 # CONFIG_SERIO_CT82C710 is not set
+# CONFIG_SERIO_LIBPS2 is not set
+# CONFIG_SERIO_RAW is not set
 
 #
 # Input Device Drivers
@@ -447,7 +492,6 @@
 CONFIG_SERIAL_CORE_CONSOLE=y
 CONFIG_UNIX98_PTYS=y
 # CONFIG_LEGACY_PTYS is not set
-# CONFIG_QIC02_TAPE is not set
 
 #
 # IPMI
@@ -466,7 +510,6 @@
 #
 # Ftape, the floppy tape device driver
 #
-# CONFIG_AGP is not set
 # CONFIG_DRM is not set
 # CONFIG_RAW_DRIVER is not set
 
@@ -507,6 +550,12 @@
 #
 # USB support
 #
+# CONFIG_USB_ARCH_HAS_HCD is not set
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
 
 #
 # USB Gadget Support
@@ -514,6 +563,16 @@
 # CONFIG_USB_GADGET is not set
 
 #
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -522,10 +581,15 @@
 # CONFIG_JBD is not set
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
+
+#
+# XFS support
+#
 # CONFIG_XFS_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
 # CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
 
@@ -569,6 +633,7 @@
 CONFIG_JFFS2_FS=y
 CONFIG_JFFS2_FS_DEBUG=0
 # CONFIG_JFFS2_FS_NAND is not set
+# CONFIG_JFFS2_FS_NOR_ECC is not set
 # CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
 CONFIG_JFFS2_ZLIB=y
 CONFIG_JFFS2_RTIME=y
@@ -590,9 +655,9 @@
 # CONFIG_NFSD is not set
 CONFIG_ROOT_NFS=y
 CONFIG_LOCKD=y
-# CONFIG_EXPORTFS is not set
 CONFIG_SUNRPC=y
 # CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
 # CONFIG_SMB_FS is not set
 # CONFIG_CIFS is not set
 # CONFIG_NCP_FS is not set
@@ -618,22 +683,26 @@
 #
 # Kernel hacking
 #
-# CONFIG_MAGIC_SYSRQ is not set
-# CONFIG_DEBUG_SPINLOCK is not set
-# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_DEBUG_PREEMPT=y
+# CONFIG_FRAME_POINTER is not set
 # CONFIG_SH_STANDARD_BIOS is not set
 # CONFIG_KGDB is not set
-# CONFIG_FRAME_POINTER is not set
 
 #
 # Security options
 #
+# CONFIG_KEYS is not set
 # CONFIG_SECURITY is not set
 
 #
 # Cryptographic options
 #
 # CONFIG_CRYPTO is not set
+
+#
+# Hardware crypto devices
+#
 
 #
 # Library routines
diff -Nru a/arch/sh/configs/se7750_defconfig b/arch/sh/configs/se7750_defconfig
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/sh/configs/se7750_defconfig	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,713 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.11-sh
+# Wed Mar  2 15:09:46 2005
+#
+CONFIG_SUPERH=y
+CONFIG_UID16=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_CLEAN_COMPILE=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_HOTPLUG is not set
+CONFIG_KOBJECT_UEVENT=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_EMBEDDED=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+# CONFIG_MODULE_UNLOAD is not set
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+
+#
+# System type
+#
+CONFIG_SH_SOLUTION_ENGINE=y
+# CONFIG_SH_7751_SOLUTION_ENGINE is not set
+# CONFIG_SH_7300_SOLUTION_ENGINE is not set
+# CONFIG_SH_73180_SOLUTION_ENGINE is not set
+# CONFIG_SH_7751_SYSTEMH is not set
+# CONFIG_SH_STB1_HARP is not set
+# CONFIG_SH_STB1_OVERDRIVE is not set
+# CONFIG_SH_HP620 is not set
+# CONFIG_SH_HP680 is not set
+# CONFIG_SH_HP690 is not set
+# CONFIG_SH_CQREEK is not set
+# CONFIG_SH_DMIDA is not set
+# CONFIG_SH_EC3104 is not set
+# CONFIG_SH_SATURN is not set
+# CONFIG_SH_DREAMCAST is not set
+# CONFIG_SH_CAT68701 is not set
+# CONFIG_SH_BIGSUR is not set
+# CONFIG_SH_SH2000 is not set
+# CONFIG_SH_ADX is not set
+# CONFIG_SH_MPC1211 is not set
+# CONFIG_SH_SH03 is not set
+# CONFIG_SH_SECUREEDGE5410 is not set
+# CONFIG_SH_HS7751RVOIP is not set
+# CONFIG_SH_RTS7751R2D is not set
+# CONFIG_SH_EDOSK7705 is not set
+# CONFIG_SH_SH4202_MICRODEV is not set
+# CONFIG_SH_UNKNOWN is not set
+# CONFIG_CPU_SH2 is not set
+# CONFIG_CPU_SH3 is not set
+CONFIG_CPU_SH4=y
+# CONFIG_CPU_SUBTYPE_SH7604 is not set
+# CONFIG_CPU_SUBTYPE_SH7300 is not set
+# CONFIG_CPU_SUBTYPE_SH7705 is not set
+# CONFIG_CPU_SUBTYPE_SH7707 is not set
+# CONFIG_CPU_SUBTYPE_SH7708 is not set
+# CONFIG_CPU_SUBTYPE_SH7709 is not set
+CONFIG_CPU_SUBTYPE_SH7750=y
+# CONFIG_CPU_SUBTYPE_SH7751 is not set
+# CONFIG_CPU_SUBTYPE_SH7760 is not set
+# CONFIG_CPU_SUBTYPE_SH73180 is not set
+# CONFIG_CPU_SUBTYPE_ST40STB1 is not set
+# CONFIG_CPU_SUBTYPE_ST40GX1 is not set
+# CONFIG_CPU_SUBTYPE_SH4_202 is not set
+CONFIG_MMU=y
+CONFIG_CMDLINE_BOOL=y
+CONFIG_CMDLINE="console=ttySC1,38400 root=/dev/nfs ip=bootp"
+CONFIG_MEMORY_START=0x0c000000
+CONFIG_MEMORY_SIZE=0x02000000
+CONFIG_MEMORY_SET=y
+# CONFIG_MEMORY_OVERRIDE is not set
+CONFIG_CF_ENABLER=y
+# CONFIG_CF_AREA5 is not set
+CONFIG_CF_AREA6=y
+CONFIG_CF_BASE_ADDR=0xb8000000
+CONFIG_SH_RTC=y
+CONFIG_SH_FPU=y
+CONFIG_ZERO_PAGE_OFFSET=0x00001000
+CONFIG_BOOT_LINK_OFFSET=0x00800000
+CONFIG_CPU_LITTLE_ENDIAN=y
+# CONFIG_PREEMPT is not set
+# CONFIG_UBC_WAKEUP is not set
+# CONFIG_SH_WRITETHROUGH is not set
+# CONFIG_SH_OCRAM is not set
+# CONFIG_SH_STORE_QUEUES is not set
+# CONFIG_SMP is not set
+CONFIG_SH_PCLK_CALC=y
+CONFIG_SH_PCLK_FREQ=49876504
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# DMA support
+#
+# CONFIG_SH_DMA is not set
+
+#
+# Companion Chips
+#
+# CONFIG_HD6446X_SERIES is not set
+CONFIG_HEARTBEAT=y
+
+#
+# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
+#
+# CONFIG_PCI is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PC-card bridges
+#
+
+#
+# PCI Hotplug Support
+#
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_FLAT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_CONCAT is not set
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_CMDLINE_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_CFI_INTELEXT is not set
+CONFIG_MTD_CFI_AMDSTD=y
+CONFIG_MTD_CFI_AMDSTD_RETRY=0
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+CONFIG_MTD_ROM=y
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PHYSMAP is not set
+CONFIG_MTD_SOLUTIONENGINE=y
+CONFIG_MTD_SUPERH_RESERVE=0x00010000
+# CONFIG_MTD_MPC1211 is not set
+# CONFIG_MTD_RTS7751R2D is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLKMTD is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+
+#
+# NAND Flash Device Drivers
+#
+# CONFIG_MTD_NAND is not set
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_RAM is not set
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_LBD is not set
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_SCSI is not set
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+
+#
+# I2O device support
+#
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+# CONFIG_NETLINK_DEV is not set
+CONFIG_UNIX=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_IP_TCPDIAG=y
+# CONFIG_IP_TCPDIAG_IPV6 is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_MII is not set
+CONFIG_STNIC=y
+# CONFIG_SMC91X is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+
+#
+# Token Ring devices
+#
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Telephony Support
+#
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+# CONFIG_INPUT is not set
+
+#
+# Userland interfaces
+#
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+# CONFIG_SERIO is not set
+# CONFIG_SERIO_I8042 is not set
+
+#
+# Input Device Drivers
+#
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+# CONFIG_SERIAL_8250_CONSOLE is not set
+CONFIG_SERIAL_8250_NR_UARTS=2
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_SH_SCI=y
+CONFIG_SERIAL_SH_SCI_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+CONFIG_SH_WDT=y
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB_ARCH_HAS_HCD is not set
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
+# File systems
+#
+# CONFIG_EXT2_FS is not set
+# CONFIG_EXT3_FS is not set
+# CONFIG_JBD is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+
+#
+# XFS support
+#
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
+# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVPTS_FS_XATTR is not set
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_XATTR is not set
+# CONFIG_HUGETLBFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+# CONFIG_JFFS2_FS_NAND is not set
+# CONFIG_JFFS2_FS_NOR_ECC is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+# CONFIG_MSDOS_PARTITION is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+
+#
+# Native Language Support
+#
+# CONFIG_NLS is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_FRAME_POINTER is not set
+# CONFIG_SH_STANDARD_BIOS is not set
+# CONFIG_EARLY_SCIF_CONSOLE is not set
+# CONFIG_KGDB is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Hardware crypto devices
+#
+
+#
+# Library routines
+#
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
diff -Nru a/arch/sh/configs/se7751_defconfig b/arch/sh/configs/se7751_defconfig
--- a/arch/sh/configs/se7751_defconfig	2005-03-11 12:51:42 -08:00
+++ b/arch/sh/configs/se7751_defconfig	2005-03-11 12:51:42 -08:00
@@ -1,34 +1,49 @@
 #
 # Automatically generated make config: don't edit
+# Linux kernel version: 2.6.11-sh
+# Wed Mar  2 15:09:48 2005
 #
 CONFIG_SUPERH=y
 CONFIG_UID16=y
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
 
 #
 # Code maturity level options
 #
 CONFIG_EXPERIMENTAL=y
 CONFIG_CLEAN_COMPILE=y
-CONFIG_STANDALONE=y
 CONFIG_BROKEN_ON_SMP=y
 
 #
 # General setup
 #
+CONFIG_LOCALVERSION=""
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
 CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
 CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
 CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_HOTPLUG is not set
+CONFIG_KOBJECT_UEVENT=y
 # CONFIG_IKCONFIG is not set
 CONFIG_EMBEDDED=y
 CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
 
 #
 # Loadable module support
@@ -37,6 +52,7 @@
 # CONFIG_MODULE_UNLOAD is not set
 CONFIG_OBSOLETE_MODPARM=y
 # CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
 # CONFIG_KMOD is not set
 
 #
@@ -44,6 +60,8 @@
 #
 # CONFIG_SH_SOLUTION_ENGINE is not set
 CONFIG_SH_7751_SOLUTION_ENGINE=y
+# CONFIG_SH_7300_SOLUTION_ENGINE is not set
+# CONFIG_SH_73180_SOLUTION_ENGINE is not set
 # CONFIG_SH_7751_SYSTEMH is not set
 # CONFIG_SH_STB1_HARP is not set
 # CONFIG_SH_STB1_OVERDRIVE is not set
@@ -60,20 +78,29 @@
 # CONFIG_SH_SH2000 is not set
 # CONFIG_SH_ADX is not set
 # CONFIG_SH_MPC1211 is not set
+# CONFIG_SH_SH03 is not set
 # CONFIG_SH_SECUREEDGE5410 is not set
+# CONFIG_SH_HS7751RVOIP is not set
+# CONFIG_SH_RTS7751R2D is not set
+# CONFIG_SH_EDOSK7705 is not set
+# CONFIG_SH_SH4202_MICRODEV is not set
 # CONFIG_SH_UNKNOWN is not set
 # CONFIG_CPU_SH2 is not set
 # CONFIG_CPU_SH3 is not set
 CONFIG_CPU_SH4=y
 # CONFIG_CPU_SUBTYPE_SH7604 is not set
 # CONFIG_CPU_SUBTYPE_SH7300 is not set
+# CONFIG_CPU_SUBTYPE_SH7705 is not set
 # CONFIG_CPU_SUBTYPE_SH7707 is not set
 # CONFIG_CPU_SUBTYPE_SH7708 is not set
 # CONFIG_CPU_SUBTYPE_SH7709 is not set
 # CONFIG_CPU_SUBTYPE_SH7750 is not set
 CONFIG_CPU_SUBTYPE_SH7751=y
 # CONFIG_CPU_SUBTYPE_SH7760 is not set
+# CONFIG_CPU_SUBTYPE_SH73180 is not set
 # CONFIG_CPU_SUBTYPE_ST40STB1 is not set
+# CONFIG_CPU_SUBTYPE_ST40GX1 is not set
+# CONFIG_CPU_SUBTYPE_SH4_202 is not set
 CONFIG_MMU=y
 CONFIG_CMDLINE_BOOL=y
 CONFIG_CMDLINE="console=ttySC1,38400"
@@ -82,6 +109,7 @@
 CONFIG_MEMORY_SET=y
 # CONFIG_MEMORY_OVERRIDE is not set
 CONFIG_SH_RTC=y
+CONFIG_SH_FPU=y
 CONFIG_ZERO_PAGE_OFFSET=0x00010000
 CONFIG_BOOT_LINK_OFFSET=0x00800000
 CONFIG_CPU_LITTLE_ENDIAN=y
@@ -91,21 +119,48 @@
 # CONFIG_SH_OCRAM is not set
 # CONFIG_SH_STORE_QUEUES is not set
 # CONFIG_SMP is not set
+CONFIG_SH_PCLK_CALC=y
 CONFIG_SH_PCLK_FREQ=60013568
+
+#
+# CPU Frequency scaling
+#
 # CONFIG_CPU_FREQ is not set
+
+#
+# DMA support
+#
 # CONFIG_SH_DMA is not set
 
 #
+# Companion Chips
+#
+# CONFIG_HD6446X_SERIES is not set
+CONFIG_HEARTBEAT=y
+
+#
 # Bus options (PCI, PCMCIA, EISA, MCA, ISA)
 #
 CONFIG_PCI=y
 # CONFIG_SH_PCIDMA_NONCOHERENT is not set
 CONFIG_PCI_AUTO=y
 CONFIG_PCI_AUTO_UPDATE_RESOURCES=y
-CONFIG_PCI_DMA=y
 # CONFIG_PCI_LEGACY_PROC is not set
 # CONFIG_PCI_NAMES is not set
-# CONFIG_HOTPLUG is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PC-card bridges
+#
+
+#
+# PCI Hotplug Support
+#
+# CONFIG_HOTPLUG_PCI is not set
 
 #
 # Executable file formats
@@ -115,8 +170,20 @@
 # CONFIG_BINFMT_MISC is not set
 
 #
+# SH initrd options
+#
+# CONFIG_EMBEDDED_RAMDISK is not set
+
+#
+# Device Drivers
+#
+
+#
 # Generic Driver Options
 #
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
 
 #
 # Memory Technology Devices (MTD)
@@ -144,28 +211,43 @@
 # CONFIG_MTD_JEDECPROBE is not set
 CONFIG_MTD_GEN_PROBE=y
 # CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
 # CONFIG_MTD_CFI_INTELEXT is not set
 CONFIG_MTD_CFI_AMDSTD=y
+CONFIG_MTD_CFI_AMDSTD_RETRY=0
 # CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
 CONFIG_MTD_RAM=y
 # CONFIG_MTD_ROM is not set
 # CONFIG_MTD_ABSENT is not set
-# CONFIG_MTD_OBSOLETE_CHIPS is not set
 
 #
 # Mapping drivers for chip access
 #
 # CONFIG_MTD_COMPLEX_MAPPINGS is not set
 # CONFIG_MTD_PHYSMAP is not set
+# CONFIG_MTD_SOLUTIONENGINE is not set
 # CONFIG_MTD_MPC1211 is not set
+# CONFIG_MTD_RTS7751R2D is not set
 
 #
 # Self-contained MTD device drivers
 #
 # CONFIG_MTD_PMC551 is not set
 # CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
 # CONFIG_MTD_MTDRAM is not set
 # CONFIG_MTD_BLKMTD is not set
+# CONFIG_MTD_BLOCK2MTD is not set
 
 #
 # Disk-On-Chip Device Drivers
@@ -185,6 +267,10 @@
 # CONFIG_PARPORT is not set
 
 #
+# Plug and Play support
+#
+
+#
 # Block devices
 #
 # CONFIG_BLK_DEV_FD is not set
@@ -192,12 +278,26 @@
 # CONFIG_BLK_CPQ_CISS_DA is not set
 # CONFIG_BLK_DEV_DAC960 is not set
 # CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
 # CONFIG_BLK_DEV_LOOP is not set
 # CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_SX8 is not set
 CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
 CONFIG_BLK_DEV_RAM_SIZE=4096
 CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_LBD is not set
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
 
 #
 # ATA/ATAPI/MFM/RLL support
@@ -215,11 +315,20 @@
 # CONFIG_MD is not set
 
 #
-# IEEE 1394 (FireWire) support (EXPERIMENTAL)
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
 #
 # CONFIG_IEEE1394 is not set
 
 #
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
 # Networking support
 #
 CONFIG_NET=y
@@ -243,19 +352,19 @@
 # CONFIG_NET_IPGRE is not set
 # CONFIG_IP_MROUTE is not set
 # CONFIG_ARPD is not set
-# CONFIG_INET_ECN is not set
 # CONFIG_SYN_COOKIES is not set
 # CONFIG_INET_AH is not set
 # CONFIG_INET_ESP is not set
 # CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_IP_TCPDIAG=y
+# CONFIG_IP_TCPDIAG_IPV6 is not set
 
 #
 # IP: Virtual Server Configuration
 #
 # CONFIG_IP_VS is not set
 # CONFIG_IPV6 is not set
-# CONFIG_DECNET is not set
-# CONFIG_BRIDGE is not set
 CONFIG_NETFILTER=y
 CONFIG_NETFILTER_DEBUG=y
 
@@ -263,19 +372,19 @@
 # IP: Netfilter Configuration
 #
 # CONFIG_IP_NF_CONNTRACK is not set
+# CONFIG_IP_NF_CONNTRACK_MARK is not set
 CONFIG_IP_NF_QUEUE=y
 # CONFIG_IP_NF_IPTABLES is not set
 # CONFIG_IP_NF_ARPTABLES is not set
-# CONFIG_IP_NF_COMPAT_IPCHAINS is not set
-# CONFIG_IP_NF_COMPAT_IPFWADM is not set
 
 #
 # SCTP Configuration (EXPERIMENTAL)
 #
-CONFIG_IPV6_SCTP__=y
 # CONFIG_IP_SCTP is not set
 # CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
 # CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
 # CONFIG_LLC2 is not set
 # CONFIG_IPX is not set
 # CONFIG_ATALK is not set
@@ -284,24 +393,23 @@
 # CONFIG_NET_DIVERT is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
-# CONFIG_NET_FASTROUTE is not set
-# CONFIG_NET_HW_FLOWCONTROL is not set
 
 #
 # QoS and/or fair queueing
 #
 # CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
 
 #
 # Network testing
 #
 # CONFIG_NET_PKTGEN is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
 CONFIG_NETDEVICES=y
-
-#
-# ARCnet devices
-#
-# CONFIG_ARCNET is not set
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
 # CONFIG_EQUALIZER is not set
@@ -309,6 +417,11 @@
 # CONFIG_ETHERTAP is not set
 
 #
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
 # Ethernet (10 or 100Mbit)
 #
 CONFIG_NET_ETHERNET=y
@@ -317,6 +430,7 @@
 # CONFIG_HAPPYMEAL is not set
 # CONFIG_SUNGEM is not set
 # CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_SMC91X is not set
 
 #
 # Tulip family network device support
@@ -328,6 +442,7 @@
 # CONFIG_AMD8111_ETH is not set
 # CONFIG_ADAPTEC_STARFIRE is not set
 # CONFIG_B44 is not set
+# CONFIG_FORCEDETH is not set
 # CONFIG_DGRS is not set
 # CONFIG_EEPRO100 is not set
 # CONFIG_E100 is not set
@@ -352,55 +467,41 @@
 # CONFIG_HAMACHI is not set
 # CONFIG_YELLOWFIN is not set
 # CONFIG_R8169 is not set
-# CONFIG_SIS190 is not set
 # CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
 
 #
 # Ethernet (10000 Mbit)
 #
 # CONFIG_IXGB is not set
-# CONFIG_FDDI is not set
-# CONFIG_HIPPI is not set
-# CONFIG_PPP is not set
-# CONFIG_SLIP is not set
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
+# CONFIG_S2IO is not set
 
 #
 # Token Ring devices
 #
 # CONFIG_TR is not set
-# CONFIG_RCPCI is not set
-# CONFIG_SHAPER is not set
-
-#
-# Wan interfaces
-#
-# CONFIG_WAN is not set
 
 #
-# Amateur Radio support
-#
-# CONFIG_HAMRADIO is not set
-
-#
-# IrDA (infrared) support
+# Wireless LAN (non-hamradio)
 #
-# CONFIG_IRDA is not set
+# CONFIG_NET_RADIO is not set
 
 #
-# Bluetooth support
+# Wan interfaces
 #
-# CONFIG_BT is not set
+# CONFIG_WAN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
 
 #
 # ISDN subsystem
 #
-# CONFIG_ISDN_BOOL is not set
+# CONFIG_ISDN is not set
 
 #
 # Telephony Support
@@ -432,35 +533,54 @@
 # Character devices
 #
 # CONFIG_VT is not set
-# CONFIG_SERIAL is not set
-CONFIG_SH_SCI=y
-CONFIG_SERIAL_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
 
 #
-# Unix 98 PTY support
+# Non-8250 serial port support
 #
+# CONFIG_SERIAL_SH_SCI is not set
 CONFIG_UNIX98_PTYS=y
-CONFIG_UNIX98_PTY_COUNT=256
-CONFIG_HEARTBEAT=y
-# CONFIG_PSMOUSE is not set
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
 
 #
 # Watchdog Cards
 #
 CONFIG_WATCHDOG=y
 # CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
 # CONFIG_SH_WDT is not set
-# CONFIG_RTC is not set
 
 #
-# Serial drivers
+# PCI-based Watchdog Cards
 #
-# CONFIG_SERIAL_8250 is not set
+# CONFIG_PCIPCWATCHDOG is not set
+# CONFIG_WDTPCI is not set
+# CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
 
 #
-# Non-8250 serial port support
+# Ftape, the floppy tape device driver
 #
-# CONFIG_SERIAL_SH_SCI is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
 
 #
 # I2C support
@@ -468,17 +588,59 @@
 # CONFIG_I2C is not set
 
 #
-# I2C Algorithms
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
 #
 
 #
-# I2C Hardware Bus support
+# USB Gadget Support
 #
+# CONFIG_USB_GADGET is not set
 
 #
-# I2C Hardware Sensors Chip support
+# MMC/SD Card support
 #
-# CONFIG_I2C_SENSOR is not set
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
 
 #
 # File systems
@@ -489,10 +651,15 @@
 # CONFIG_JBD is not set
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
+
+#
+# XFS support
+#
 # CONFIG_XFS_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
 # CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
 
@@ -505,7 +672,8 @@
 #
 # DOS/FAT/NT Filesystems
 #
-# CONFIG_FAT_FS is not set
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
 # CONFIG_NTFS_FS is not set
 
 #
@@ -513,10 +681,12 @@
 #
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
 # CONFIG_DEVFS_FS is not set
-CONFIG_DEVPTS_FS=y
 # CONFIG_DEVPTS_FS_XATTR is not set
 CONFIG_TMPFS=y
+# CONFIG_TMPFS_XATTR is not set
+# CONFIG_HUGETLBFS is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
 
@@ -526,6 +696,7 @@
 # CONFIG_ADFS_FS is not set
 # CONFIG_AFFS_FS is not set
 # CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
 # CONFIG_BEFS_FS is not set
 # CONFIG_BFS_FS is not set
 # CONFIG_EFS_FS is not set
@@ -533,6 +704,11 @@
 CONFIG_JFFS2_FS=y
 CONFIG_JFFS2_FS_DEBUG=0
 # CONFIG_JFFS2_FS_NAND is not set
+# CONFIG_JFFS2_FS_NOR_ECC is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
 # CONFIG_CRAMFS is not set
 # CONFIG_VXFS_FS is not set
 # CONFIG_HPFS_FS is not set
@@ -545,12 +721,10 @@
 #
 # CONFIG_NFS_FS is not set
 # CONFIG_NFSD is not set
-# CONFIG_EXPORTFS is not set
 # CONFIG_SMB_FS is not set
 # CONFIG_CIFS is not set
 # CONFIG_NCP_FS is not set
 # CONFIG_CODA_FS is not set
-# CONFIG_INTERMEZZO_FS is not set
 # CONFIG_AFS_FS is not set
 
 #
@@ -560,30 +734,9 @@
 CONFIG_MSDOS_PARTITION=y
 
 #
-# Multimedia devices
+# Native Language Support
 #
-# CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
-
-#
-# Graphics support
-#
-# CONFIG_FB is not set
-
-#
-# Sound
-#
-# CONFIG_SOUND is not set
-
-#
-# USB support
-#
-# CONFIG_USB is not set
-# CONFIG_USB_GADGET is not set
+# CONFIG_NLS is not set
 
 #
 # Profiling support
@@ -593,15 +746,16 @@
 #
 # Kernel hacking
 #
-# CONFIG_MAGIC_SYSRQ is not set
-# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_FRAME_POINTER is not set
 # CONFIG_SH_STANDARD_BIOS is not set
+# CONFIG_EARLY_SCIF_CONSOLE is not set
 # CONFIG_KGDB is not set
-# CONFIG_FRAME_POINTER is not set
 
 #
 # Security options
 #
+# CONFIG_KEYS is not set
 # CONFIG_SECURITY is not set
 
 #
@@ -610,8 +764,14 @@
 # CONFIG_CRYPTO is not set
 
 #
+# Hardware crypto devices
+#
+
+#
 # Library routines
 #
+# CONFIG_CRC_CCITT is not set
 CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
 CONFIG_ZLIB_INFLATE=y
 CONFIG_ZLIB_DEFLATE=y
diff -Nru a/arch/sh/configs/sh03_defconfig b/arch/sh/configs/sh03_defconfig
--- a/arch/sh/configs/sh03_defconfig	2005-03-11 12:51:41 -08:00
+++ b/arch/sh/configs/sh03_defconfig	2005-03-11 12:51:41 -08:00
@@ -1,9 +1,14 @@
 #
 # Automatically generated make config: don't edit
+# Linux kernel version: 2.6.11-sh
+# Wed Mar  2 15:09:49 2005
 #
 CONFIG_SUPERH=y
 CONFIG_UID16=y
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
 
 #
 # Code maturity level options
@@ -12,10 +17,12 @@
 # CONFIG_CLEAN_COMPILE is not set
 CONFIG_BROKEN=y
 CONFIG_BROKEN_ON_SMP=y
+CONFIG_LOCK_KERNEL=y
 
 #
 # General setup
 #
+CONFIG_LOCALVERSION=""
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
@@ -25,17 +32,20 @@
 # CONFIG_AUDIT is not set
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_HOTPLUG=y
+CONFIG_KOBJECT_UEVENT=y
 # CONFIG_IKCONFIG is not set
 # CONFIG_EMBEDDED is not set
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_EXTRA_PASS is not set
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
 
 #
 # Loadable module support
@@ -45,6 +55,7 @@
 CONFIG_MODULE_FORCE_UNLOAD=y
 CONFIG_OBSOLETE_MODPARM=y
 CONFIG_MODVERSIONS=y
+# CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_KMOD=y
 
 #
@@ -137,7 +148,6 @@
 #
 # Bus options (PCI, PCMCIA, EISA, MCA, ISA)
 #
-CONFIG_ISA=y
 CONFIG_PCI=y
 CONFIG_SH_PCIDMA_NONCOHERENT=y
 CONFIG_PCI_AUTO=y
@@ -146,16 +156,13 @@
 CONFIG_PCI_NAMES=y
 
 #
-# PCMCIA/CardBus support
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PC-card bridges
 #
-CONFIG_PCMCIA=m
-# CONFIG_PCMCIA_DEBUG is not set
-# CONFIG_YENTA is not set
-# CONFIG_PD6729 is not set
-# CONFIG_I82092 is not set
-# CONFIG_I82365 is not set
-# CONFIG_TCIC is not set
-CONFIG_PCMCIA_PROBE=y
 
 #
 # PCI Hotplug Support
@@ -163,7 +170,6 @@
 CONFIG_HOTPLUG_PCI=m
 # CONFIG_HOTPLUG_PCI_FAKE is not set
 # CONFIG_HOTPLUG_PCI_CPCI is not set
-# CONFIG_HOTPLUG_PCI_PCIE is not set
 # CONFIG_HOTPLUG_PCI_SHPC is not set
 
 #
@@ -202,25 +208,36 @@
 #
 # Plug and Play support
 #
-# CONFIG_PNP is not set
 
 #
 # Block devices
 #
 # CONFIG_BLK_DEV_FD is not set
-# CONFIG_BLK_DEV_XD is not set
 # CONFIG_BLK_CPQ_DA is not set
 # CONFIG_BLK_CPQ_CISS_DA is not set
 # CONFIG_BLK_DEV_DAC960 is not set
 # CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
 CONFIG_BLK_DEV_LOOP=y
 # CONFIG_BLK_DEV_CRYPTOLOOP is not set
 CONFIG_BLK_DEV_NBD=y
 # CONFIG_BLK_DEV_SX8 is not set
 CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
 CONFIG_BLK_DEV_RAM_SIZE=4096
 CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_LBD is not set
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
 
 #
 # ATA/ATAPI/MFM/RLL support
@@ -235,13 +252,11 @@
 # CONFIG_BLK_DEV_IDE_SATA is not set
 CONFIG_BLK_DEV_IDEDISK=y
 CONFIG_IDEDISK_MULTI_MODE=y
-CONFIG_BLK_DEV_IDECS=m
 CONFIG_BLK_DEV_IDECD=m
 CONFIG_BLK_DEV_IDETAPE=m
 CONFIG_BLK_DEV_IDEFLOPPY=m
 # CONFIG_BLK_DEV_IDESCSI is not set
 # CONFIG_IDE_TASK_IOCTL is not set
-# CONFIG_IDE_TASKFILE_IO is not set
 
 #
 # IDE chipset support/bugfixes
@@ -250,7 +265,6 @@
 # CONFIG_BLK_DEV_IDEPCI is not set
 CONFIG_IDE_SH=y
 # CONFIG_IDE_ARM is not set
-# CONFIG_IDE_CHIPSETS is not set
 # CONFIG_BLK_DEV_IDEDMA is not set
 # CONFIG_IDEDMA_AUTO is not set
 # CONFIG_BLK_DEV_HD is not set
@@ -283,46 +297,37 @@
 #
 # CONFIG_SCSI_SPI_ATTRS is not set
 # CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
 
 #
 # SCSI low-level drivers
 #
 # CONFIG_BLK_DEV_3W_XXXX_RAID is not set
 # CONFIG_SCSI_3W_9XXX is not set
-# CONFIG_SCSI_7000FASST is not set
 # CONFIG_SCSI_ACARD is not set
-# CONFIG_SCSI_AHA152X is not set
-# CONFIG_SCSI_AHA1542 is not set
 # CONFIG_SCSI_AACRAID is not set
 # CONFIG_SCSI_AIC7XXX is not set
 # CONFIG_SCSI_AIC7XXX_OLD is not set
 # CONFIG_SCSI_AIC79XX is not set
 # CONFIG_SCSI_DPT_I2O is not set
 # CONFIG_SCSI_ADVANSYS is not set
-# CONFIG_SCSI_IN2000 is not set
-# CONFIG_SCSI_MEGARAID is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
 # CONFIG_SCSI_SATA is not set
 # CONFIG_SCSI_BUSLOGIC is not set
 # CONFIG_SCSI_CPQFCTS is not set
 # CONFIG_SCSI_DMX3191D is not set
-# CONFIG_SCSI_DTC3280 is not set
 # CONFIG_SCSI_EATA is not set
 # CONFIG_SCSI_EATA_PIO is not set
 # CONFIG_SCSI_FUTURE_DOMAIN is not set
 # CONFIG_SCSI_GDTH is not set
-# CONFIG_SCSI_GENERIC_NCR5380 is not set
-# CONFIG_SCSI_GENERIC_NCR5380_MMIO is not set
 # CONFIG_SCSI_IPS is not set
 # CONFIG_SCSI_INITIO is not set
 # CONFIG_SCSI_INIA100 is not set
-# CONFIG_SCSI_NCR53C406A is not set
 # CONFIG_SCSI_SYM53C8XX_2 is not set
 # CONFIG_SCSI_IPR is not set
-# CONFIG_SCSI_PAS16 is not set
 # CONFIG_SCSI_PCI2000 is not set
 # CONFIG_SCSI_PCI2220I is not set
-# CONFIG_SCSI_PSI240I is not set
-# CONFIG_SCSI_QLOGIC_FAS is not set
 # CONFIG_SCSI_QLOGIC_ISP is not set
 # CONFIG_SCSI_QLOGIC_FC is not set
 # CONFIG_SCSI_QLOGIC_1280 is not set
@@ -332,30 +337,12 @@
 # CONFIG_SCSI_QLA2300 is not set
 # CONFIG_SCSI_QLA2322 is not set
 # CONFIG_SCSI_QLA6312 is not set
-# CONFIG_SCSI_QLA6322 is not set
-# CONFIG_SCSI_SYM53C416 is not set
 # CONFIG_SCSI_DC395x is not set
 # CONFIG_SCSI_DC390T is not set
-# CONFIG_SCSI_T128 is not set
-# CONFIG_SCSI_U14_34F is not set
 # CONFIG_SCSI_NSP32 is not set
 # CONFIG_SCSI_DEBUG is not set
 
 #
-# PCMCIA SCSI adapter support
-#
-# CONFIG_PCMCIA_AHA152X is not set
-# CONFIG_PCMCIA_FDOMAIN is not set
-# CONFIG_PCMCIA_NINJA_SCSI is not set
-# CONFIG_PCMCIA_QLOGIC is not set
-# CONFIG_PCMCIA_SYM53C500 is not set
-
-#
-# Old CD-ROM drivers (not SCSI, not IDE)
-#
-# CONFIG_CD_NO_IDESCSI is not set
-
-#
 # Multi-device support (RAID and LVM)
 #
 # CONFIG_MD is not set
@@ -403,6 +390,9 @@
 # CONFIG_INET_AH is not set
 # CONFIG_INET_ESP is not set
 # CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_IP_TCPDIAG=y
+# CONFIG_IP_TCPDIAG_IPV6 is not set
 # CONFIG_IPV6 is not set
 # CONFIG_NETFILTER is not set
 CONFIG_XFRM=y
@@ -424,7 +414,6 @@
 # CONFIG_NET_DIVERT is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
-# CONFIG_NET_HW_FLOWCONTROL is not set
 
 #
 # QoS and/or fair queueing
@@ -461,27 +450,19 @@
 # CONFIG_HAPPYMEAL is not set
 # CONFIG_SUNGEM is not set
 # CONFIG_NET_VENDOR_3COM is not set
-# CONFIG_LANCE is not set
-# CONFIG_NET_VENDOR_SMC is not set
-# CONFIG_NET_VENDOR_RACAL is not set
+# CONFIG_SMC91X is not set
 
 #
 # Tulip family network device support
 #
 # CONFIG_NET_TULIP is not set
-# CONFIG_AT1700 is not set
-# CONFIG_DEPCA is not set
 # CONFIG_HP100 is not set
-# CONFIG_NET_ISA is not set
 CONFIG_NET_PCI=y
 # CONFIG_PCNET32 is not set
 # CONFIG_AMD8111_ETH is not set
 # CONFIG_ADAPTEC_STARFIRE is not set
-# CONFIG_AC3200 is not set
-# CONFIG_APRICOT is not set
 # CONFIG_B44 is not set
 # CONFIG_FORCEDETH is not set
-# CONFIG_CS89x0 is not set
 # CONFIG_DGRS is not set
 # CONFIG_EEPRO100 is not set
 # CONFIG_E100 is not set
@@ -495,8 +476,6 @@
 # CONFIG_SUNDANCE is not set
 # CONFIG_TLAN is not set
 # CONFIG_VIA_RHINE is not set
-# CONFIG_VIA_VELOCITY is not set
-# CONFIG_NET_POCKET is not set
 
 #
 # Ethernet (1000 Mbit)
@@ -509,6 +488,7 @@
 # CONFIG_YELLOWFIN is not set
 # CONFIG_R8169 is not set
 # CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
 
 #
@@ -528,11 +508,6 @@
 # CONFIG_NET_RADIO is not set
 
 #
-# PCMCIA network device support
-#
-# CONFIG_NET_PCMCIA is not set
-
-#
 # Wan interfaces
 #
 # CONFIG_WAN is not set
@@ -600,7 +575,6 @@
 # Serial drivers
 #
 CONFIG_SERIAL_8250=m
-# CONFIG_SERIAL_8250_CS is not set
 CONFIG_SERIAL_8250_NR_UARTS=4
 # CONFIG_SERIAL_8250_EXTENDED is not set
 
@@ -614,7 +588,6 @@
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
-# CONFIG_QIC02_TAPE is not set
 
 #
 # IPMI
@@ -634,13 +607,6 @@
 CONFIG_SH_WDT=m
 
 #
-# ISA-based Watchdog Cards
-#
-# CONFIG_PCWATCHDOG is not set
-# CONFIG_MIXCOMWD is not set
-# CONFIG_WDT is not set
-
-#
 # PCI-based Watchdog Cards
 #
 # CONFIG_PCIPCWATCHDOG is not set
@@ -655,13 +621,7 @@
 #
 # Ftape, the floppy tape device driver
 #
-# CONFIG_AGP is not set
 # CONFIG_DRM is not set
-
-#
-# PCMCIA character devices
-#
-# CONFIG_SYNCLINK_CS is not set
 # CONFIG_RAW_DRIVER is not set
 
 #
@@ -697,7 +657,6 @@
 # Console display driver support
 #
 # CONFIG_VGA_CONSOLE is not set
-# CONFIG_MDA_CONSOLE is not set
 CONFIG_DUMMY_CONSOLE=y
 
 #
@@ -709,6 +668,12 @@
 # USB support
 #
 # CONFIG_USB is not set
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
 
 #
 # USB Gadget Support
@@ -716,6 +681,16 @@
 # CONFIG_USB_GADGET is not set
 
 #
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
@@ -732,10 +707,15 @@
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
 CONFIG_FS_POSIX_ACL=y
+
+#
+# XFS support
+#
 # CONFIG_XFS_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
 # CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
 CONFIG_AUTOFS_FS=y
 CONFIG_AUTOFS4_FS=y
 
@@ -768,6 +748,7 @@
 # CONFIG_DEVFS_FS is not set
 # CONFIG_DEVPTS_FS_XATTR is not set
 CONFIG_TMPFS=y
+# CONFIG_TMPFS_XATTR is not set
 # CONFIG_HUGETLBFS is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
@@ -807,6 +788,7 @@
 CONFIG_SUNRPC=y
 CONFIG_SUNRPC_GSS=y
 CONFIG_RPCSEC_GSS_KRB5=y
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
 # CONFIG_SMB_FS is not set
 # CONFIG_CIFS is not set
 # CONFIG_NCP_FS is not set
@@ -886,18 +868,18 @@
 #
 # Kernel hacking
 #
-# CONFIG_MAGIC_SYSRQ is not set
-# CONFIG_DEBUG_SPINLOCK is not set
-CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_DEBUG_PREEMPT=y
+# CONFIG_FRAME_POINTER is not set
 CONFIG_SH_STANDARD_BIOS=y
 # CONFIG_EARLY_SCIF_CONSOLE is not set
 # CONFIG_EARLY_PRINTK is not set
 # CONFIG_KGDB is not set
-# CONFIG_FRAME_POINTER is not set
 
 #
 # Security options
 #
+# CONFIG_KEYS is not set
 # CONFIG_SECURITY is not set
 
 #
@@ -911,6 +893,7 @@
 CONFIG_CRYPTO_SHA1=y
 # CONFIG_CRYPTO_SHA256 is not set
 # CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_WP512 is not set
 CONFIG_CRYPTO_DES=y
 # CONFIG_CRYPTO_BLOWFISH is not set
 # CONFIG_CRYPTO_TWOFISH is not set
@@ -921,10 +904,15 @@
 # CONFIG_CRYPTO_TEA is not set
 # CONFIG_CRYPTO_ARC4 is not set
 # CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_ANUBIS is not set
 CONFIG_CRYPTO_DEFLATE=y
 # CONFIG_CRYPTO_MICHAEL_MIC is not set
 # CONFIG_CRYPTO_CRC32C is not set
 # CONFIG_CRYPTO_TEST is not set
+
+#
+# Hardware crypto devices
+#
 
 #
 # Library routines
diff -Nru a/arch/sh/configs/snapgear_defconfig b/arch/sh/configs/snapgear_defconfig
--- a/arch/sh/configs/snapgear_defconfig	2005-03-11 12:51:50 -08:00
+++ b/arch/sh/configs/snapgear_defconfig	2005-03-11 12:51:50 -08:00
@@ -1,34 +1,48 @@
 #
 # Automatically generated make config: don't edit
+# Linux kernel version: 2.6.11-sh
+# Wed Mar  2 15:09:51 2005
 #
 CONFIG_SUPERH=y
 CONFIG_UID16=y
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
 
 #
 # Code maturity level options
 #
 CONFIG_EXPERIMENTAL=y
 CONFIG_CLEAN_COMPILE=y
-CONFIG_STANDALONE=y
 CONFIG_BROKEN_ON_SMP=y
 
 #
 # General setup
 #
+CONFIG_LOCALVERSION=""
 CONFIG_SWAP=y
 # CONFIG_SYSVIPC is not set
+# CONFIG_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
 # CONFIG_SYSCTL is not set
+# CONFIG_AUDIT is not set
 CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_HOTPLUG is not set
+CONFIG_KOBJECT_UEVENT=y
 # CONFIG_IKCONFIG is not set
 # CONFIG_EMBEDDED is not set
 CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
 
 #
 # Loadable module support
@@ -40,6 +54,9 @@
 #
 # CONFIG_SH_SOLUTION_ENGINE is not set
 # CONFIG_SH_7751_SOLUTION_ENGINE is not set
+# CONFIG_SH_7300_SOLUTION_ENGINE is not set
+# CONFIG_SH_73180_SOLUTION_ENGINE is not set
+# CONFIG_SH_7751_SYSTEMH is not set
 # CONFIG_SH_STB1_HARP is not set
 # CONFIG_SH_STB1_OVERDRIVE is not set
 # CONFIG_SH_HP620 is not set
@@ -55,19 +72,29 @@
 # CONFIG_SH_SH2000 is not set
 # CONFIG_SH_ADX is not set
 # CONFIG_SH_MPC1211 is not set
+# CONFIG_SH_SH03 is not set
 CONFIG_SH_SECUREEDGE5410=y
+# CONFIG_SH_HS7751RVOIP is not set
+# CONFIG_SH_RTS7751R2D is not set
+# CONFIG_SH_EDOSK7705 is not set
+# CONFIG_SH_SH4202_MICRODEV is not set
 # CONFIG_SH_UNKNOWN is not set
 # CONFIG_CPU_SH2 is not set
 # CONFIG_CPU_SH3 is not set
 CONFIG_CPU_SH4=y
 # CONFIG_CPU_SUBTYPE_SH7604 is not set
 # CONFIG_CPU_SUBTYPE_SH7300 is not set
+# CONFIG_CPU_SUBTYPE_SH7705 is not set
 # CONFIG_CPU_SUBTYPE_SH7707 is not set
 # CONFIG_CPU_SUBTYPE_SH7708 is not set
 # CONFIG_CPU_SUBTYPE_SH7709 is not set
 # CONFIG_CPU_SUBTYPE_SH7750 is not set
 CONFIG_CPU_SUBTYPE_SH7751=y
+# CONFIG_CPU_SUBTYPE_SH7760 is not set
+# CONFIG_CPU_SUBTYPE_SH73180 is not set
 # CONFIG_CPU_SUBTYPE_ST40STB1 is not set
+# CONFIG_CPU_SUBTYPE_ST40GX1 is not set
+# CONFIG_CPU_SUBTYPE_SH4_202 is not set
 CONFIG_MMU=y
 # CONFIG_CMDLINE_BOOL is not set
 CONFIG_MEMORY_START=0x08000000
@@ -75,6 +102,7 @@
 CONFIG_MEMORY_SET=y
 # CONFIG_MEMORY_OVERRIDE is not set
 CONFIG_SH_RTC=y
+CONFIG_SH_FPU=y
 CONFIG_ZERO_PAGE_OFFSET=0x00001000
 CONFIG_BOOT_LINK_OFFSET=0x00800000
 CONFIG_CPU_LITTLE_ENDIAN=y
@@ -84,11 +112,25 @@
 # CONFIG_SH_OCRAM is not set
 # CONFIG_SH_STORE_QUEUES is not set
 # CONFIG_SMP is not set
+CONFIG_SH_PCLK_CALC=y
 CONFIG_SH_PCLK_FREQ=60013568
+
+#
+# CPU Frequency scaling
+#
 # CONFIG_CPU_FREQ is not set
+
+#
+# DMA support
+#
 CONFIG_SH_DMA=y
-CONFIG_NR_DMA_CHANNELS=8
-# CONFIG_DMA_PAGE_OPS is not set
+CONFIG_NR_ONCHIP_DMA_CHANNELS=4
+# CONFIG_NR_DMA_CHANNELS_BOOL is not set
+
+#
+# Companion Chips
+#
+# CONFIG_HD6446X_SERIES is not set
 
 #
 # Bus options (PCI, PCMCIA, EISA, MCA, ISA)
@@ -97,10 +139,22 @@
 # CONFIG_SH_PCIDMA_NONCOHERENT is not set
 CONFIG_PCI_AUTO=y
 CONFIG_PCI_AUTO_UPDATE_RESOURCES=y
-CONFIG_PCI_DMA=y
 # CONFIG_PCI_LEGACY_PROC is not set
 CONFIG_PCI_NAMES=y
-# CONFIG_HOTPLUG is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PC-card bridges
+#
+
+#
+# PCI Hotplug Support
+#
+# CONFIG_HOTPLUG_PCI is not set
 
 #
 # Executable file formats
@@ -110,8 +164,20 @@
 # CONFIG_BINFMT_MISC is not set
 
 #
+# SH initrd options
+#
+# CONFIG_EMBEDDED_RAMDISK is not set
+
+#
+# Device Drivers
+#
+
+#
 # Generic Driver Options
 #
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
 
 #
 # Memory Technology Devices (MTD)
@@ -124,6 +190,10 @@
 # CONFIG_PARPORT is not set
 
 #
+# Plug and Play support
+#
+
+#
 # Block devices
 #
 # CONFIG_BLK_DEV_FD is not set
@@ -131,12 +201,26 @@
 # CONFIG_BLK_CPQ_CISS_DA is not set
 # CONFIG_BLK_DEV_DAC960 is not set
 # CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
 # CONFIG_BLK_DEV_LOOP is not set
 # CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_SX8 is not set
 CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
 CONFIG_BLK_DEV_RAM_SIZE=4096
 CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_LBD is not set
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
 
 #
 # ATA/ATAPI/MFM/RLL support
@@ -154,11 +238,20 @@
 # CONFIG_MD is not set
 
 #
-# IEEE 1394 (FireWire) support (EXPERIMENTAL)
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
 #
 # CONFIG_IEEE1394 is not set
 
 #
+# I2O device support
+#
+# CONFIG_I2O is not set
+
+#
 # Networking support
 #
 CONFIG_NET=y
@@ -180,60 +273,69 @@
 # CONFIG_NET_IPIP is not set
 # CONFIG_NET_IPGRE is not set
 # CONFIG_ARPD is not set
-# CONFIG_INET_ECN is not set
 # CONFIG_SYN_COOKIES is not set
 # CONFIG_INET_AH is not set
 # CONFIG_INET_ESP is not set
 # CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_IP_TCPDIAG=y
+# CONFIG_IP_TCPDIAG_IPV6 is not set
 # CONFIG_IPV6 is not set
-# CONFIG_DECNET is not set
-# CONFIG_BRIDGE is not set
 # CONFIG_NETFILTER is not set
 
 #
 # SCTP Configuration (EXPERIMENTAL)
 #
-CONFIG_IPV6_SCTP__=y
 # CONFIG_IP_SCTP is not set
 # CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
 # CONFIG_VLAN_8021Q is not set
-# CONFIG_LLC is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
 # CONFIG_X25 is not set
 # CONFIG_LAPB is not set
 # CONFIG_NET_DIVERT is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
-# CONFIG_NET_HW_FLOWCONTROL is not set
 
 #
 # QoS and/or fair queueing
 #
 # CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
 
 #
 # Network testing
 #
 # CONFIG_NET_PKTGEN is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
 CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
 
 #
 # ARCnet devices
 #
 # CONFIG_ARCNET is not set
-# CONFIG_DUMMY is not set
-# CONFIG_BONDING is not set
-# CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
 
 #
 # Ethernet (10 or 100Mbit)
 #
 CONFIG_NET_ETHERNET=y
-# CONFIG_MII is not set
+CONFIG_MII=y
 # CONFIG_STNIC is not set
 # CONFIG_HAPPYMEAL is not set
 # CONFIG_SUNGEM is not set
 # CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_SMC91X is not set
 
 #
 # Tulip family network device support
@@ -245,6 +347,7 @@
 # CONFIG_AMD8111_ETH is not set
 # CONFIG_ADAPTEC_STARFIRE is not set
 # CONFIG_B44 is not set
+# CONFIG_FORCEDETH is not set
 # CONFIG_DGRS is not set
 # CONFIG_EEPRO100 is not set
 # CONFIG_E100 is not set
@@ -273,49 +376,41 @@
 # CONFIG_HAMACHI is not set
 # CONFIG_YELLOWFIN is not set
 # CONFIG_R8169 is not set
-# CONFIG_SIS190 is not set
 # CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
 
 #
 # Ethernet (10000 Mbit)
 #
 # CONFIG_IXGB is not set
-# CONFIG_FDDI is not set
-# CONFIG_HIPPI is not set
-# CONFIG_PPP is not set
-# CONFIG_SLIP is not set
+# CONFIG_S2IO is not set
 
 #
-# Wireless LAN (non-hamradio)
+# Token Ring devices
 #
-# CONFIG_NET_RADIO is not set
+# CONFIG_TR is not set
 
 #
-# Token Ring devices (depends on LLC=y)
+# Wireless LAN (non-hamradio)
 #
-# CONFIG_RCPCI is not set
-# CONFIG_SHAPER is not set
+# CONFIG_NET_RADIO is not set
 
 #
 # Wan interfaces
 #
 # CONFIG_WAN is not set
-
-#
-# Amateur Radio support
-#
-# CONFIG_HAMRADIO is not set
-
-#
-# IrDA (infrared) support
-#
-# CONFIG_IRDA is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+# CONFIG_NETCONSOLE is not set
 
 #
 # ISDN subsystem
 #
-# CONFIG_ISDN_BOOL is not set
+# CONFIG_ISDN is not set
 
 #
 # Telephony Support
@@ -344,7 +439,12 @@
 #
 # CONFIG_GAMEPORT is not set
 CONFIG_SOUND_GAMEPORT=y
-# CONFIG_SERIO is not set
+CONFIG_SERIO=y
+CONFIG_SERIO_I8042=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+# CONFIG_SERIO_PCIPS2 is not set
+# CONFIG_SERIO_RAW is not set
 
 #
 # Input Device Drivers
@@ -358,47 +458,110 @@
 #
 # Character devices
 #
-# CONFIG_VT is not set
-# CONFIG_SERIAL is not set
-CONFIG_SH_SCI=y
-CONFIG_SERIAL_CONSOLE=y
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
 
 #
-# Unix 98 PTY support
+# Serial drivers
 #
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_SH_SCI is not set
 CONFIG_UNIX98_PTYS=y
-CONFIG_UNIX98_PTY_COUNT=256
-# CONFIG_PSMOUSE is not set
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
 
 #
 # Watchdog Cards
 #
 # CONFIG_WATCHDOG is not set
 # CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
 
 #
-# Serial drivers
+# Ftape, the floppy tape device driver
 #
-# CONFIG_SERIAL_8250 is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
 
 #
-# Non-8250 serial port support
+# I2C support
 #
-# CONFIG_SERIAL_SH_SCI is not set
+# CONFIG_I2C is not set
 
 #
-# I2C support
+# Dallas's 1-wire bus
 #
-# CONFIG_I2C is not set
+# CONFIG_W1 is not set
 
 #
-# I2C Hardware Sensors Mainboard support
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
 #
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Console display driver support
+#
+CONFIG_VGA_CONSOLE=y
+CONFIG_DUMMY_CONSOLE=y
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
 
 #
-# I2C Hardware Sensors Chip support
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
 #
-# CONFIG_I2C_SENSOR is not set
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
 
 #
 # File systems
@@ -409,10 +572,15 @@
 # CONFIG_JBD is not set
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
+
+#
+# XFS support
+#
 # CONFIG_XFS_FS is not set
 # CONFIG_MINIX_FS is not set
 CONFIG_ROMFS_FS=y
 # CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
 
@@ -425,19 +593,24 @@
 #
 # DOS/FAT/NT Filesystems
 #
-# CONFIG_FAT_FS is not set
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
 # CONFIG_NTFS_FS is not set
 
 #
 # Pseudo filesystems
 #
 CONFIG_PROC_FS=y
+# CONFIG_PROC_KCORE is not set
+CONFIG_SYSFS=y
 CONFIG_DEVFS_FS=y
 CONFIG_DEVFS_MOUNT=y
 # CONFIG_DEVFS_DEBUG is not set
-CONFIG_DEVPTS_FS=y
 # CONFIG_DEVPTS_FS_XATTR is not set
 CONFIG_TMPFS=y
+# CONFIG_TMPFS_XATTR is not set
+# CONFIG_HUGETLBFS is not set
+# CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
 
 #
@@ -446,6 +619,7 @@
 # CONFIG_ADFS_FS is not set
 # CONFIG_AFFS_FS is not set
 # CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
 # CONFIG_BEFS_FS is not set
 # CONFIG_BFS_FS is not set
 # CONFIG_EFS_FS is not set
@@ -462,18 +636,18 @@
 CONFIG_NFS_FS=y
 CONFIG_NFS_V3=y
 # CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
 # CONFIG_NFSD is not set
 CONFIG_ROOT_NFS=y
 CONFIG_LOCKD=y
 CONFIG_LOCKD_V4=y
-# CONFIG_EXPORTFS is not set
 CONFIG_SUNRPC=y
-# CONFIG_SUNRPC_GSS is not set
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
 # CONFIG_SMB_FS is not set
 # CONFIG_CIFS is not set
 # CONFIG_NCP_FS is not set
 # CONFIG_CODA_FS is not set
-# CONFIG_INTERMEZZO_FS is not set
 # CONFIG_AFS_FS is not set
 
 #
@@ -483,48 +657,28 @@
 CONFIG_MSDOS_PARTITION=y
 
 #
-# Multimedia devices
-#
-# CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
-
-#
-# Graphics support
+# Native Language Support
 #
-# CONFIG_FB is not set
+# CONFIG_NLS is not set
 
 #
-# Sound
+# Profiling support
 #
-# CONFIG_SOUND is not set
-
-#
-# USB support
-#
-# CONFIG_USB is not set
-# CONFIG_USB_GADGET is not set
-
-#
-# Bluetooth support
-#
-# CONFIG_BT is not set
+# CONFIG_PROFILING is not set
 
 #
 # Kernel hacking
 #
-# CONFIG_MAGIC_SYSRQ is not set
-# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_KERNEL is not set
+# CONFIG_FRAME_POINTER is not set
 # CONFIG_SH_STANDARD_BIOS is not set
+# CONFIG_EARLY_SCIF_CONSOLE is not set
 # CONFIG_KGDB is not set
-# CONFIG_FRAME_POINTER is not set
 
 #
 # Security options
 #
+# CONFIG_KEYS is not set
 # CONFIG_SECURITY is not set
 
 #
@@ -533,7 +687,13 @@
 # CONFIG_CRYPTO is not set
 
 #
+# Hardware crypto devices
+#
+
+#
 # Library routines
 #
-# CONFIG_CRC32 is not set
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
 CONFIG_ZLIB_INFLATE=y
diff -Nru a/arch/sh/configs/systemh_defconfig b/arch/sh/configs/systemh_defconfig
--- a/arch/sh/configs/systemh_defconfig	2005-03-11 12:51:47 -08:00
+++ b/arch/sh/configs/systemh_defconfig	2005-03-11 12:51:47 -08:00
@@ -1,35 +1,48 @@
 #
 # Automatically generated make config: don't edit
+# Linux kernel version: 2.6.11-sh
+# Wed Mar  2 15:09:53 2005
 #
 CONFIG_SUPERH=y
 CONFIG_UID16=y
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
 
 #
 # Code maturity level options
 #
 CONFIG_EXPERIMENTAL=y
 # CONFIG_CLEAN_COMPILE is not set
-# CONFIG_STANDALONE is not set
 CONFIG_BROKEN=y
 CONFIG_BROKEN_ON_SMP=y
+CONFIG_LOCK_KERNEL=y
 
 #
 # General setup
 #
+CONFIG_LOCALVERSION=""
 CONFIG_SWAP=y
 # CONFIG_SYSVIPC is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
 # CONFIG_SYSCTL is not set
+# CONFIG_AUDIT is not set
 CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_HOTPLUG is not set
 # CONFIG_IKCONFIG is not set
 CONFIG_EMBEDDED=y
 CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
 
 #
 # Loadable module support
@@ -39,6 +52,7 @@
 # CONFIG_MODULE_FORCE_UNLOAD is not set
 CONFIG_OBSOLETE_MODPARM=y
 # CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
 # CONFIG_KMOD is not set
 
 #
@@ -46,6 +60,8 @@
 #
 # CONFIG_SH_SOLUTION_ENGINE is not set
 # CONFIG_SH_7751_SOLUTION_ENGINE is not set
+# CONFIG_SH_7300_SOLUTION_ENGINE is not set
+# CONFIG_SH_73180_SOLUTION_ENGINE is not set
 CONFIG_SH_7751_SYSTEMH=y
 # CONFIG_SH_STB1_HARP is not set
 # CONFIG_SH_STB1_OVERDRIVE is not set
@@ -62,25 +78,36 @@
 # CONFIG_SH_SH2000 is not set
 # CONFIG_SH_ADX is not set
 # CONFIG_SH_MPC1211 is not set
+# CONFIG_SH_SH03 is not set
 # CONFIG_SH_SECUREEDGE5410 is not set
+# CONFIG_SH_HS7751RVOIP is not set
+# CONFIG_SH_RTS7751R2D is not set
+# CONFIG_SH_EDOSK7705 is not set
+# CONFIG_SH_SH4202_MICRODEV is not set
 # CONFIG_SH_UNKNOWN is not set
 # CONFIG_CPU_SH2 is not set
 # CONFIG_CPU_SH3 is not set
 CONFIG_CPU_SH4=y
 # CONFIG_CPU_SUBTYPE_SH7604 is not set
 # CONFIG_CPU_SUBTYPE_SH7300 is not set
+# CONFIG_CPU_SUBTYPE_SH7705 is not set
 # CONFIG_CPU_SUBTYPE_SH7707 is not set
 # CONFIG_CPU_SUBTYPE_SH7708 is not set
 # CONFIG_CPU_SUBTYPE_SH7709 is not set
 # CONFIG_CPU_SUBTYPE_SH7750 is not set
 CONFIG_CPU_SUBTYPE_SH7751=y
+# CONFIG_CPU_SUBTYPE_SH7760 is not set
+# CONFIG_CPU_SUBTYPE_SH73180 is not set
 # CONFIG_CPU_SUBTYPE_ST40STB1 is not set
+# CONFIG_CPU_SUBTYPE_ST40GX1 is not set
+# CONFIG_CPU_SUBTYPE_SH4_202 is not set
 CONFIG_MMU=y
 # CONFIG_CMDLINE_BOOL is not set
 CONFIG_MEMORY_START=0x0c000000
 CONFIG_MEMORY_SIZE=0x00400000
 # CONFIG_MEMORY_OVERRIDE is not set
 CONFIG_SH_RTC=y
+CONFIG_SH_FPU=y
 CONFIG_ZERO_PAGE_OFFSET=0x00001000
 CONFIG_BOOT_LINK_OFFSET=0x00800000
 CONFIG_CPU_LITTLE_ENDIAN=y
@@ -90,21 +117,47 @@
 # CONFIG_SH_OCRAM is not set
 # CONFIG_SH_STORE_QUEUES is not set
 # CONFIG_SMP is not set
+CONFIG_SH_PCLK_CALC=y
 CONFIG_SH_PCLK_FREQ=49876504
+
+#
+# CPU Frequency scaling
+#
 # CONFIG_CPU_FREQ is not set
+
+#
+# DMA support
+#
 # CONFIG_SH_DMA is not set
 
 #
+# Companion Chips
+#
+# CONFIG_HD6446X_SERIES is not set
+
+#
 # Bus options (PCI, PCMCIA, EISA, MCA, ISA)
 #
 CONFIG_PCI=y
 # CONFIG_SH_PCIDMA_NONCOHERENT is not set
 CONFIG_PCI_AUTO=y
 CONFIG_PCI_AUTO_UPDATE_RESOURCES=y
-CONFIG_PCI_DMA=y
 CONFIG_PCI_LEGACY_PROC=y
 CONFIG_PCI_NAMES=y
-# CONFIG_HOTPLUG is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PC-card bridges
+#
+
+#
+# PCI Hotplug Support
+#
+# CONFIG_HOTPLUG_PCI is not set
 
 #
 # Executable file formats
@@ -114,8 +167,20 @@
 # CONFIG_BINFMT_MISC is not set
 
 #
+# SH initrd options
+#
+# CONFIG_EMBEDDED_RAMDISK is not set
+
+#
+# Device Drivers
+#
+
+#
 # Generic Driver Options
 #
+# CONFIG_STANDALONE is not set
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
 
 #
 # Memory Technology Devices (MTD)
@@ -128,17 +193,35 @@
 # CONFIG_PARPORT is not set
 
 #
+# Plug and Play support
+#
+
+#
 # Block devices
 #
+# CONFIG_BLK_DEV_FD is not set
 # CONFIG_BLK_CPQ_DA is not set
 # CONFIG_BLK_CPQ_CISS_DA is not set
 # CONFIG_BLK_DEV_DAC960 is not set
 # CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
 # CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_SX8 is not set
 CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
 CONFIG_BLK_DEV_RAM_SIZE=1024
 CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_LBD is not set
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
 
 #
 # ATA/ATAPI/MFM/RLL support
@@ -156,19 +239,25 @@
 # CONFIG_MD is not set
 
 #
-# IEEE 1394 (FireWire) support (EXPERIMENTAL)
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
 #
 # CONFIG_IEEE1394 is not set
 
 #
-# Networking support
+# I2O device support
 #
-# CONFIG_NET is not set
+# CONFIG_I2O is not set
 
 #
-# Amateur Radio support
+# Networking support
 #
-# CONFIG_HAMRADIO is not set
+# CONFIG_NET is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
 
 #
 # ISDN subsystem
@@ -198,6 +287,8 @@
 # CONFIG_SERIO_SERPORT is not set
 # CONFIG_SERIO_CT82C710 is not set
 # CONFIG_SERIO_PCIPS2 is not set
+# CONFIG_SERIO_LIBPS2 is not set
+# CONFIG_SERIO_RAW is not set
 
 #
 # Input Device Drivers
@@ -207,50 +298,100 @@
 # Character devices
 #
 # CONFIG_VT is not set
-# CONFIG_SERIAL is not set
-CONFIG_SH_SCI=y
-CONFIG_SERIAL_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
 
 #
-# Unix 98 PTY support
+# Serial drivers
 #
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_SH_SCI is not set
 CONFIG_UNIX98_PTYS=y
-CONFIG_UNIX98_PTY_COUNT=256
-# CONFIG_PSMOUSE is not set
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
 
 #
 # Watchdog Cards
 #
 # CONFIG_WATCHDOG is not set
 # CONFIG_RTC is not set
+# CONFIG_GEN_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
 
 #
-# Serial drivers
+# Ftape, the floppy tape device driver
 #
-# CONFIG_SERIAL_8250 is not set
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
 
 #
-# Non-8250 serial port support
+# I2C support
 #
-# CONFIG_SERIAL_SH_SCI is not set
+# CONFIG_I2C is not set
 
 #
-# I2C support
+# Dallas's 1-wire bus
 #
-# CONFIG_I2C is not set
+# CONFIG_W1 is not set
+
+#
+# Misc devices
+#
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+
+#
+# Graphics support
+#
+# CONFIG_FB is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
 
 #
-# I2C Algorithms
+# USB support
+#
+# CONFIG_USB is not set
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
 #
 
 #
-# I2C Hardware Bus support
+# USB Gadget Support
 #
+# CONFIG_USB_GADGET is not set
 
 #
-# I2C Hardware Sensors Chip support
+# MMC/SD Card support
 #
-# CONFIG_I2C_SENSOR is not set
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
 
 #
 # File systems
@@ -260,10 +401,15 @@
 # CONFIG_JBD is not set
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
+
+#
+# XFS support
+#
 # CONFIG_XFS_FS is not set
 # CONFIG_MINIX_FS is not set
 CONFIG_ROMFS_FS=y
 # CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
 
@@ -276,7 +422,8 @@
 #
 # DOS/FAT/NT Filesystems
 #
-# CONFIG_FAT_FS is not set
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
 # CONFIG_NTFS_FS is not set
 
 #
@@ -284,12 +431,13 @@
 #
 CONFIG_PROC_FS=y
 CONFIG_PROC_KCORE=y
+CONFIG_SYSFS=y
 CONFIG_DEVFS_FS=y
 CONFIG_DEVFS_MOUNT=y
 # CONFIG_DEVFS_DEBUG is not set
-CONFIG_DEVPTS_FS=y
 # CONFIG_DEVPTS_FS_XATTR is not set
 CONFIG_TMPFS=y
+# CONFIG_TMPFS_XATTR is not set
 # CONFIG_HUGETLBFS is not set
 # CONFIG_HUGETLB_PAGE is not set
 CONFIG_RAMFS=y
@@ -300,6 +448,7 @@
 # CONFIG_ADFS_FS is not set
 # CONFIG_AFFS_FS is not set
 # CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
 # CONFIG_BEFS_FS is not set
 # CONFIG_BFS_FS is not set
 # CONFIG_EFS_FS is not set
@@ -317,29 +466,9 @@
 CONFIG_MSDOS_PARTITION=y
 
 #
-# Multimedia devices
-#
-# CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-
-#
-# Graphics support
+# Native Language Support
 #
-# CONFIG_FB is not set
-
-#
-# Sound
-#
-# CONFIG_SOUND is not set
-
-#
-# USB support
-#
-# CONFIG_USB is not set
-# CONFIG_USB_GADGET is not set
+# CONFIG_NLS is not set
 
 #
 # Profiling support
@@ -349,15 +478,17 @@
 #
 # Kernel hacking
 #
-# CONFIG_MAGIC_SYSRQ is not set
-# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_DEBUG_PREEMPT=y
+# CONFIG_FRAME_POINTER is not set
 # CONFIG_SH_STANDARD_BIOS is not set
+# CONFIG_EARLY_SCIF_CONSOLE is not set
 # CONFIG_KGDB is not set
-# CONFIG_FRAME_POINTER is not set
 
 #
 # Security options
 #
+# CONFIG_KEYS is not set
 # CONFIG_SECURITY is not set
 
 #
@@ -366,7 +497,13 @@
 # CONFIG_CRYPTO is not set
 
 #
+# Hardware crypto devices
+#
+
+#
 # Library routines
 #
+# CONFIG_CRC_CCITT is not set
 CONFIG_CRC32=y
+# CONFIG_LIBCRC32C is not set
 CONFIG_ZLIB_INFLATE=y
diff -Nru a/arch/sh/defconfig b/arch/sh/defconfig
--- a/arch/sh/defconfig	2005-03-11 12:51:46 -08:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,372 +0,0 @@
-#
-# Automatically generated make config: don't edit
-#
-CONFIG_SUPERH=y
-CONFIG_UID16=y
-CONFIG_RWSEM_GENERIC_SPINLOCK=y
-
-#
-# Code maturity level options
-#
-# CONFIG_EXPERIMENTAL is not set
-CONFIG_CLEAN_COMPILE=y
-CONFIG_STANDALONE=y
-CONFIG_BROKEN_ON_SMP=y
-
-#
-# General setup
-#
-CONFIG_SWAP=y
-# CONFIG_SYSVIPC is not set
-# CONFIG_BSD_PROCESS_ACCT is not set
-# CONFIG_SYSCTL is not set
-CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_IKCONFIG is not set
-CONFIG_EMBEDDED=y
-CONFIG_KALLSYMS=y
-CONFIG_FUTEX=y
-CONFIG_EPOLL=y
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-
-#
-# Loadable module support
-#
-# CONFIG_MODULES is not set
-
-#
-# System type
-#
-# CONFIG_SH_SOLUTION_ENGINE is not set
-# CONFIG_SH_7751_SOLUTION_ENGINE is not set
-# CONFIG_SH_7751_SYSTEMH is not set
-# CONFIG_SH_STB1_HARP is not set
-# CONFIG_SH_STB1_OVERDRIVE is not set
-# CONFIG_SH_HP620 is not set
-# CONFIG_SH_HP680 is not set
-# CONFIG_SH_HP690 is not set
-# CONFIG_SH_CQREEK is not set
-# CONFIG_SH_DMIDA is not set
-# CONFIG_SH_EC3104 is not set
-# CONFIG_SH_SATURN is not set
-# CONFIG_SH_DREAMCAST is not set
-# CONFIG_SH_CAT68701 is not set
-# CONFIG_SH_BIGSUR is not set
-# CONFIG_SH_SH2000 is not set
-# CONFIG_SH_ADX is not set
-# CONFIG_SH_MPC1211 is not set
-# CONFIG_SH_SECUREEDGE5410 is not set
-CONFIG_SH_UNKNOWN=y
-# CONFIG_CPU_SH2 is not set
-CONFIG_CPU_SH3=y
-# CONFIG_CPU_SH4 is not set
-# CONFIG_CPU_SUBTYPE_SH7604 is not set
-# CONFIG_CPU_SUBTYPE_SH7300 is not set
-# CONFIG_CPU_SUBTYPE_SH7707 is not set
-CONFIG_CPU_SUBTYPE_SH7708=y
-# CONFIG_CPU_SUBTYPE_SH7709 is not set
-# CONFIG_CPU_SUBTYPE_SH7750 is not set
-# CONFIG_CPU_SUBTYPE_SH7751 is not set
-# CONFIG_CPU_SUBTYPE_SH7760 is not set
-# CONFIG_CPU_SUBTYPE_ST40STB1 is not set
-CONFIG_MMU=y
-# CONFIG_CMDLINE_BOOL is not set
-CONFIG_MEMORY_START=0x0c000000
-CONFIG_MEMORY_SIZE=0x00400000
-# CONFIG_MEMORY_OVERRIDE is not set
-CONFIG_CF_ENABLER=y
-# CONFIG_CF_AREA5 is not set
-CONFIG_CF_AREA6=y
-CONFIG_CF_BASE_ADDR=0xb8000000
-CONFIG_SH_RTC=y
-CONFIG_SH_DSP=y
-CONFIG_ZERO_PAGE_OFFSET=0x00001000
-CONFIG_BOOT_LINK_OFFSET=0x00800000
-CONFIG_CPU_LITTLE_ENDIAN=y
-# CONFIG_UBC_WAKEUP is not set
-# CONFIG_SH_WRITETHROUGH is not set
-# CONFIG_SH_OCRAM is not set
-# CONFIG_SMP is not set
-CONFIG_SH_PCLK_FREQ=1193182
-# CONFIG_CPU_FREQ is not set
-# CONFIG_SH_DMA is not set
-
-#
-# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
-#
-# CONFIG_PCI is not set
-# CONFIG_HOTPLUG is not set
-
-#
-# Executable file formats
-#
-CONFIG_BINFMT_ELF=y
-# CONFIG_BINFMT_FLAT is not set
-# CONFIG_BINFMT_MISC is not set
-
-#
-# Generic Driver Options
-#
-
-#
-# Memory Technology Devices (MTD)
-#
-# CONFIG_MTD is not set
-
-#
-# Parallel port support
-#
-# CONFIG_PARPORT is not set
-
-#
-# Block devices
-#
-# CONFIG_BLK_DEV_FD is not set
-# CONFIG_BLK_DEV_LOOP is not set
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_SIZE=4096
-CONFIG_BLK_DEV_INITRD=y
-# CONFIG_LBD is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
-CONFIG_IDE=y
-CONFIG_BLK_DEV_IDE=y
-
-#
-# Please see Documentation/ide.txt for help/info on IDE drives
-#
-CONFIG_BLK_DEV_IDEDISK=y
-# CONFIG_IDEDISK_MULTI_MODE is not set
-# CONFIG_IDEDISK_STROKE is not set
-# CONFIG_BLK_DEV_IDECD is not set
-# CONFIG_BLK_DEV_IDEFLOPPY is not set
-# CONFIG_IDE_TASK_IOCTL is not set
-
-#
-# IDE chipset support/bugfixes
-#
-CONFIG_IDE_GENERIC=y
-# CONFIG_BLK_DEV_IDEDMA is not set
-# CONFIG_IDEDMA_AUTO is not set
-# CONFIG_BLK_DEV_HD is not set
-
-#
-# SCSI device support
-#
-# CONFIG_SCSI is not set
-
-#
-# Multi-device support (RAID and LVM)
-#
-# CONFIG_MD is not set
-
-#
-# Networking support
-#
-# CONFIG_NET is not set
-
-#
-# Amateur Radio support
-#
-# CONFIG_HAMRADIO is not set
-
-#
-# ISDN subsystem
-#
-
-#
-# Telephony Support
-#
-# CONFIG_PHONE is not set
-
-#
-# Input device support
-#
-CONFIG_INPUT=y
-
-#
-# Userland interfaces
-#
-CONFIG_INPUT_MOUSEDEV=y
-CONFIG_INPUT_MOUSEDEV_PSAUX=y
-CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
-CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
-# CONFIG_INPUT_JOYDEV is not set
-# CONFIG_INPUT_TSDEV is not set
-# CONFIG_INPUT_EVDEV is not set
-# CONFIG_INPUT_EVBUG is not set
-
-#
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-CONFIG_SERIO=y
-CONFIG_SERIO_I8042=y
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_CT82C710 is not set
-
-#
-# Input Device Drivers
-#
-CONFIG_INPUT_KEYBOARD=y
-CONFIG_KEYBOARD_ATKBD=y
-# CONFIG_KEYBOARD_SUNKBD is not set
-# CONFIG_KEYBOARD_XTKBD is not set
-# CONFIG_KEYBOARD_NEWTON is not set
-CONFIG_INPUT_MOUSE=y
-CONFIG_MOUSE_PS2=y
-# CONFIG_MOUSE_SERIAL is not set
-# CONFIG_INPUT_JOYSTICK is not set
-# CONFIG_INPUT_TOUCHSCREEN is not set
-# CONFIG_INPUT_MISC is not set
-
-#
-# Character devices
-#
-# CONFIG_VT is not set
-# CONFIG_SERIAL is not set
-CONFIG_SH_SCI=y
-CONFIG_SERIAL_CONSOLE=y
-
-#
-# Unix98 PTY support
-#
-# CONFIG_UNIX98_PTYS is not set
-# CONFIG_PSMOUSE is not set
-
-#
-# Watchdog Cards
-#
-# CONFIG_WATCHDOG is not set
-# CONFIG_RTC is not set
-
-#
-# Serial drivers
-#
-# CONFIG_SERIAL_8250 is not set
-
-#
-# Non-8250 serial port support
-#
-# CONFIG_SERIAL_SH_SCI is not set
-
-#
-# I2C support
-#
-# CONFIG_I2C is not set
-
-#
-# File systems
-#
-CONFIG_EXT2_FS=y
-# CONFIG_EXT2_FS_XATTR is not set
-# CONFIG_EXT3_FS is not set
-# CONFIG_JBD is not set
-# CONFIG_REISERFS_FS is not set
-# CONFIG_JFS_FS is not set
-# CONFIG_XFS_FS is not set
-# CONFIG_MINIX_FS is not set
-# CONFIG_ROMFS_FS is not set
-# CONFIG_QUOTA is not set
-# CONFIG_AUTOFS_FS is not set
-# CONFIG_AUTOFS4_FS is not set
-
-#
-# CD-ROM/DVD Filesystems
-#
-# CONFIG_ISO9660_FS is not set
-# CONFIG_UDF_FS is not set
-
-#
-# DOS/FAT/NT Filesystems
-#
-# CONFIG_FAT_FS is not set
-# CONFIG_NTFS_FS is not set
-
-#
-# Pseudo filesystems
-#
-CONFIG_PROC_FS=y
-CONFIG_PROC_KCORE=y
-# CONFIG_TMPFS is not set
-# CONFIG_HUGETLB_PAGE is not set
-CONFIG_RAMFS=y
-
-#
-# Miscellaneous filesystems
-#
-# CONFIG_CRAMFS is not set
-# CONFIG_VXFS_FS is not set
-# CONFIG_HPFS_FS is not set
-# CONFIG_QNX4FS_FS is not set
-# CONFIG_SYSV_FS is not set
-# CONFIG_UFS_FS is not set
-
-#
-# Partition Types
-#
-# CONFIG_PARTITION_ADVANCED is not set
-CONFIG_MSDOS_PARTITION=y
-
-#
-# Native Language Support
-#
-# CONFIG_NLS is not set
-
-#
-# Multimedia devices
-#
-# CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-
-#
-# Graphics support
-#
-# CONFIG_FB is not set
-
-#
-# Sound
-#
-# CONFIG_SOUND is not set
-
-#
-# USB support
-#
-
-#
-# USB Gadget Support
-#
-# CONFIG_USB_GADGET is not set
-
-#
-# Kernel hacking
-#
-# CONFIG_MAGIC_SYSRQ is not set
-# CONFIG_DEBUG_SPINLOCK is not set
-CONFIG_SH_STANDARD_BIOS=y
-CONFIG_EARLY_PRINTK=y
-# CONFIG_KGDB is not set
-# CONFIG_FRAME_POINTER is not set
-
-#
-# Security options
-#
-# CONFIG_SECURITY is not set
-
-#
-# Cryptographic options
-#
-# CONFIG_CRYPTO is not set
-
-#
-# Library routines
-#
-# CONFIG_CRC32 is not set
diff -Nru a/arch/sh/drivers/pci/fixups-sh03.c b/arch/sh/drivers/pci/fixups-sh03.c
--- a/arch/sh/drivers/pci/fixups-sh03.c	2005-03-11 12:51:42 -08:00
+++ b/arch/sh/drivers/pci/fixups-sh03.c	2005-03-11 12:51:42 -08:00
@@ -46,11 +46,11 @@
 	/* now lookup the actual IRQ on a platform specific basis (pci-'platform'.c) */
 	irq = pcibios_map_platform_irq(slot, pin, dev);
 	if( irq < 0 ) {
-		pr_debug("PCI: Error mapping IRQ on device %s\n", dev->slot_name);
+		pr_debug("PCI: Error mapping IRQ on device %s\n", pci_name(dev));
 		return irq;
 	}
 
-	pr_debug("Setting IRQ for slot %s to %d\n", dev->slot_name, irq);
+	pr_debug("Setting IRQ for slot %s to %d\n", pci_name(dev), irq);
 
 	return irq;
 }
diff -Nru a/arch/sh/drivers/pci/pci-sh7751.c b/arch/sh/drivers/pci/pci-sh7751.c
--- a/arch/sh/drivers/pci/pci-sh7751.c	2005-03-11 12:51:50 -08:00
+++ b/arch/sh/drivers/pci/pci-sh7751.c	2005-03-11 12:51:50 -08:00
@@ -169,7 +169,7 @@
 	 */
 	if ((d->class >> 8) != PCI_CLASS_STORAGE_IDE)
 		return;
-	pr_debug("PCI: IDE base address fixup for %s\n", d->slot_name);
+	pr_debug("PCI: IDE base address fixup for %s\n", pci_name(d));
 	for(i=0; i<4; i++) {
 		struct resource *r = &d->resource[i];
 		if ((r->start & ~0x80) == 0x374) {
@@ -178,8 +178,8 @@
 		}
 	}
 }
+
 DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pci_fixup_ide_bases);
-#endif
 
 /*
  *  Called after each bus is probed, but before its children
@@ -401,11 +401,11 @@
 	/* now lookup the actual IRQ on a platform specific basis (pci-'platform'.c) */
 	irq = pcibios_map_platform_irq(slot,pin);
 	if( irq < 0 ) {
-		pr_debug("PCI: Error mapping IRQ on device %s\n", dev->slot_name);
+		pr_debug("PCI: Error mapping IRQ on device %s\n", pci_name(dev));
 		return irq;
 	}
-	
-	pr_debug("Setting IRQ for slot %s to %d\n", dev->slot_name, irq);
+
+	pr_debug("Setting IRQ for slot %s to %d\n", pci_name(dev), irq);
 
 	return irq;
 }
diff -Nru a/arch/sh/drivers/pci/pci-st40.c b/arch/sh/drivers/pci/pci-st40.c
--- a/arch/sh/drivers/pci/pci-st40.c	2005-03-11 12:51:47 -08:00
+++ b/arch/sh/drivers/pci/pci-st40.c	2005-03-11 12:51:47 -08:00
@@ -246,7 +246,7 @@
 	 */
 	if ((d->class >> 8) != PCI_CLASS_STORAGE_IDE)
 		return;
-	printk("PCI: IDE base address fixup for %s\n", d->slot_name);
+	printk("PCI: IDE base address fixup for %s\n", pci_name(d));
 	for(i=0; i<4; i++) {
 		struct resource *r = &d->resource[i];
 		if ((r->start & ~0x80) == 0x374) {
diff -Nru a/arch/sh/kernel/cpufreq.c b/arch/sh/kernel/cpufreq.c
--- a/arch/sh/kernel/cpufreq.c	2005-03-11 12:51:51 -08:00
+++ b/arch/sh/kernel/cpufreq.c	2005-03-11 12:51:51 -08:00
@@ -3,7 +3,7 @@
  *
  * cpufreq driver for the SuperH processors.
  *
- * Copyright (C) 2002, 2003 Paul Mundt
+ * Copyright (C) 2002, 2003, 2004, 2005 Paul Mundt
  * Copyright (C) 2002 M. R. Brown
  *
  * This program is free software; you can redistribute it and/or modify it
@@ -18,6 +18,7 @@
 #include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/delay.h>
+#include <linux/cpumask.h>
 #include <linux/smp.h>
 
 #include <asm/processor.h>
@@ -46,9 +47,8 @@
 #endif
 };
 
-#define NR_CLOCK_SETS	(sizeof(clock_sets) / sizeof(struct clock_set))
 #define MIN_CLOCK_SET	0
-#define MAX_CLOCK_SET	(NR_CLOCK_SETS - 1)
+#define MAX_CLOCK_SET	(ARRAY_SIZE(clock_sets) - 1)
 
 /*
  * For the time being, we only support two frequencies, which in turn are
@@ -83,18 +83,16 @@
 static int sh_cpufreq_setstate(unsigned int cpu, unsigned int set)
 {
 	unsigned short frqcr = ctrl_inw(FRQCR);
-	unsigned long cpus_allowed;
+	cpumask_t cpus_allowed;
 	struct cpufreq_freqs freqs;
-	int allowable_cpu_map;
 
 	if (!cpu_online(cpu))
 		return -ENODEV;
 
 	cpus_allowed = current->cpus_allowed;
-	allowable_cpu_map = 1 << cpu;
-	set_cpus_allowed(current, allowable_cpu_map);
-	
-	BUG_ON(!(allowable_cpu_map & (1 << smp_processor_id())));
+	set_cpus_allowed(current, cpumask_of_cpu(cpu));
+
+	BUG_ON(smp_processor_id() != cpu);
 
 	freqs.cpu = cpu;
 	freqs.old = current_cpu_data.cpu_clock / 1000;
@@ -134,7 +132,7 @@
 
 	set_cpus_allowed(current, cpus_allowed);
 	cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
-	
+
 	return 0;
 }
 
diff -Nru a/arch/sh/kernel/irq.c b/arch/sh/kernel/irq.c
--- a/arch/sh/kernel/irq.c	2005-03-11 12:51:42 -08:00
+++ b/arch/sh/kernel/irq.c	2005-03-11 12:51:42 -08:00
@@ -40,58 +40,17 @@
 #include <asm/irq.h>
 #include <linux/irq.h>
 
-/*
- * Controller mappings for all interrupt sources:
- */
-irq_desc_t irq_desc[NR_IRQS] __cacheline_aligned = {
-	[0 ... NR_IRQS-1] = {
-		.handler = &no_irq_type,
-		.lock = SPIN_LOCK_UNLOCKED
-	}
-};
-
-/*
- * Special irq handlers.
- */
 
-irqreturn_t no_action(int cpl, void *dev_id, struct pt_regs *regs)
-{ return IRQ_NONE; }
-
-/*
- * Generic no controller code
- */
-
-static void enable_none(unsigned int irq) { }
-static unsigned int startup_none(unsigned int irq) { return 0; }
-static void disable_none(unsigned int irq) { }
-static void ack_none(unsigned int irq)
-{
 /*
  * 'what should we do if we get a hw irq event on an illegal vector'.
  * each architecture has to answer this themselves, it doesn't deserve
  * a generic callback i think.
  */
+void ack_bad_irq(unsigned int irq)
+{
 	printk("unexpected IRQ trap at vector %02x\n", irq);
 }
 
-/* startup is the same as "enable", shutdown is same as "disable" */
-#define shutdown_none	disable_none
-#define end_none	enable_none
-
-struct hw_interrupt_type no_irq_type = {
-	"none",
-	startup_none,
-	shutdown_none,
-	enable_none,
-	disable_none,
-	ack_none,
-	end_none
-};
-
-/*
- * Generic, controller-independent functions:
- */
-
 #if defined(CONFIG_PROC_FS)
 int show_interrupts(struct seq_file *p, void *v)
 {
@@ -127,210 +86,13 @@
 }
 #endif
 
-/*
- * This should really return information about whether
- * we should do bottom half handling etc. Right now we
- * end up _always_ checking the bottom half, which is a
- * waste of time and is not what some drivers would
- * prefer.
- */
-int handle_IRQ_event(unsigned int irq, struct pt_regs * regs, struct irqaction * action)
-{
-	int status = 1;	/* Force the "do bottom halves" bit */
-	int ret, retval = 0;
-
-	if (!(action->flags & SA_INTERRUPT))
-		local_irq_enable();
-
-	do {
-		ret = action->handler(irq, action->dev_id, regs);
-		if (ret == IRQ_HANDLED)
-			status |= action->flags;
-		retval |= ret;
-		action = action->next;
-	} while (action);
-
-	if (status & SA_SAMPLE_RANDOM)
-		add_interrupt_randomness(irq);
-
-	local_irq_disable();
-	return retval;
-}
-
-static void __report_bad_irq(int irq, irq_desc_t *desc, irqreturn_t action_ret)
-{
-	struct irqaction *action;
-
-	if (action_ret != IRQ_HANDLED && action_ret != IRQ_NONE) {
-		printk(KERN_ERR "irq event %d: bogus return value %x\n",
-				irq, action_ret);
-	} else {
-		printk(KERN_ERR "irq %d: nobody cared!\n", irq);
-	}
-	dump_stack();
-	printk(KERN_ERR "handlers:\n");
-	action = desc->action;
-	do {
-		printk(KERN_ERR "[<%p>]", action->handler);
-		print_symbol(" (%s)",
-			(unsigned long)action->handler);
-		printk("\n");
-		action = action->next;
-	} while (action);
-}
-
-static void report_bad_irq(int irq, irq_desc_t *desc, irqreturn_t action_ret)
-{
-	static int count = 100;
-
-	if (count) {
-		count--;
-		__report_bad_irq(irq, desc, action_ret);
-	}
-}
-
-static int noirqdebug;
-
-static int __init noirqdebug_setup(char *str)
-{
-	noirqdebug = 1;
-	printk("IRQ lockup detection disabled\n");
-	return 1;
-}
-
-__setup("noirqdebug", noirqdebug_setup);
-
-/*
- * If 99,900 of the previous 100,000 interrupts have not been handled then
- * assume that the IRQ is stuck in some manner.  Drop a diagnostic and try to
- * turn the IRQ off.
- *
- * (The other 100-of-100,000 interrupts may have been a correctly-functioning
- *  device sharing an IRQ with the failing one)
- *
- * Called under desc->lock
- */
-static void note_interrupt(int irq, irq_desc_t *desc, irqreturn_t action_ret)
-{
-	if (action_ret != IRQ_HANDLED) {
-		desc->irqs_unhandled++;
-		if (action_ret != IRQ_NONE)
-			report_bad_irq(irq, desc, action_ret);
-	}
-
-	desc->irq_count++;
-	if (desc->irq_count < 100000)
-		return;
-
-	desc->irq_count = 0;
-	if (desc->irqs_unhandled > 99900) {
-		/*
-		 * The interrupt is stuck
-		 */
-		__report_bad_irq(irq, desc, action_ret);
-		/*
-		 * Now kill the IRQ
-		 */
-		printk(KERN_EMERG "Disabling IRQ #%d\n", irq);
-		desc->status |= IRQ_DISABLED;
-		desc->handler->disable(irq);
-	}
-	desc->irqs_unhandled = 0;
-}
-
-/*
- * Generic enable/disable code: this just calls
- * down into the PIC-specific version for the actual
- * hardware disable after having gotten the irq
- * controller lock. 
- */
-inline void disable_irq_nosync(unsigned int irq)
-{
-	irq_desc_t *desc = irq_desc + irq;
-	unsigned long flags;
-
-	spin_lock_irqsave(&desc->lock, flags);
-	if (!desc->depth++) {
-		desc->status |= IRQ_DISABLED;
-		desc->handler->disable(irq);
-	}
-	spin_unlock_irqrestore(&desc->lock, flags);
-}
-
-/*
- * Synchronous version of the above, making sure the IRQ is
- * no longer running on any other IRQ..
- */
-void disable_irq(unsigned int irq)
-{
-	irq_desc_t *desc = irq_desc + irq;
-	disable_irq_nosync(irq);
-	if (desc->action)
-		synchronize_irq(irq);
-}
-
-void enable_irq(unsigned int irq)
-{
-	irq_desc_t *desc = irq_desc + irq;
-	unsigned long flags;
-
-	spin_lock_irqsave(&desc->lock, flags);
-	switch (desc->depth) {
-	case 1: {
-		unsigned int status = desc->status & ~(IRQ_DISABLED | IRQ_INPROGRESS);
-		desc->status = status;
-		if ((status & (IRQ_PENDING | IRQ_REPLAY)) == IRQ_PENDING) {
-			desc->status = status | IRQ_REPLAY;
-			hw_resend_irq(desc->handler,irq);
-		}
-		desc->handler->enable(irq);
-		/* fall-through */
-	}
-	default:
-		desc->depth--;
-		break;
-	case 0:
-		printk("enable_irq() unbalanced from %p\n",
-		       __builtin_return_address(0));
-	}
-	spin_unlock_irqrestore(&desc->lock, flags);
-}
-
-/*
- * do_IRQ handles all normal device IRQ's.
- */
 asmlinkage int do_IRQ(unsigned long r4, unsigned long r5,
 		      unsigned long r6, unsigned long r7,
 		      struct pt_regs regs)
 {	
-	/* 
-	 * We ack quickly, we don't want the irq controller
-	 * thinking we're snobs just because some other CPU has
-	 * disabled global interrupts (we have already done the
-	 * INT_ACK cycles, it's too late to try to pretend to the
-	 * controller that we aren't taking the interrupt).
-	 *
-	 * 0 return value means that this irq is already being
-	 * handled by some other CPU. (or is disabled)
-	 */
 	int irq;
-	irq_desc_t *desc;
-	struct irqaction * action;
-	unsigned int status;
 
 	irq_enter();
-
-#ifdef CONFIG_PREEMPT
-	/*
-	 * At this point we're now about to actually call handlers,
-	 * and interrupts might get reenabled during them... bump
-	 * preempt_count to prevent any preemption while the handler
-	 * called here is pending...
-	 */
-	preempt_disable();
-#endif
-
-	/* Get IRQ number */
 	asm volatile("stc	r2_bank, %0\n\t"
 		     "shlr2	%0\n\t"
 		     "shlr2	%0\n\t"
@@ -338,394 +100,7 @@
 		     "add	#-16, %0\n\t"
 		     :"=z" (irq));
 	irq = irq_demux(irq);
-
-	kstat_this_cpu.irqs[irq]++;
-	desc = irq_desc + irq;
-	spin_lock(&desc->lock);
-	desc->handler->ack(irq);
-	/*
-	   REPLAY is when Linux resends an IRQ that was dropped earlier
-	   WAITING is used by probe to mark irqs that are being tested
-	   */
-	status = desc->status & ~(IRQ_REPLAY | IRQ_WAITING);
-	status |= IRQ_PENDING; /* we _want_ to handle it */
-
-	/*
-	 * If the IRQ is disabled for whatever reason, we cannot
-	 * use the action we have.
-	 */
-	action = NULL;
-	if (likely(!(status & (IRQ_DISABLED | IRQ_INPROGRESS)))) {
-		action = desc->action;
-		status &= ~IRQ_PENDING; /* we commit to handling */
-		status |= IRQ_INPROGRESS; /* we are handling it */
-	}
-	desc->status = status;
-
-	/*
-	 * If there is no IRQ handler or it was disabled, exit early.
-	   Since we set PENDING, if another processor is handling
-	   a different instance of this same irq, the other processor
-	   will take care of it.
-	 */
-	if (unlikely(!action))
-		goto out;
-
-	/*
-	 * Edge triggered interrupts need to remember
-	 * pending events.
-	 * This applies to any hw interrupts that allow a second
-	 * instance of the same irq to arrive while we are in do_IRQ
-	 * or in the handler. But the code here only handles the _second_
-	 * instance of the irq, not the third or fourth. So it is mostly
-	 * useful for irq hardware that does not mask cleanly in an
-	 * SMP environment.
-	 */
-	for (;;) {
-		irqreturn_t action_ret;
-
-		spin_unlock(&desc->lock);
-		action_ret = handle_IRQ_event(irq, &regs, action);
-		spin_lock(&desc->lock);
-		if (!noirqdebug)
-			note_interrupt(irq, desc, action_ret);
-		if (likely(!(desc->status & IRQ_PENDING)))
-			break;
-		desc->status &= ~IRQ_PENDING;
-	}
-	desc->status &= ~IRQ_INPROGRESS;
-
-out:
-	/*
-	 * The ->end() handler has to deal with interrupts which got
-	 * disabled while the handler was running.
-	 */
-	desc->handler->end(irq);
-	spin_unlock(&desc->lock);
-
+	__do_IRQ(irq, &regs);
 	irq_exit();
-
-#ifdef CONFIG_PREEMPT
-	/*
-	 * We're done with the handlers, interrupts should be
-	 * currently disabled; decrement preempt_count now so
-	 * as we return preemption may be allowed...
-	 */
-	preempt_enable_no_resched();
-#endif
-
 	return 1;
 }
-
-int request_irq(unsigned int irq, 
-		irqreturn_t (*handler)(int, void *, struct pt_regs *),
-		unsigned long irqflags, 
-		const char * devname,
-		void *dev_id)
-{
-	int retval;
-	struct irqaction * action;
-
-	if (irq >= ACTUAL_NR_IRQS)
-		return -EINVAL;
-	if (!handler)
-		return -EINVAL;
-
-	action = (struct irqaction *)
-			kmalloc(sizeof(struct irqaction), GFP_ATOMIC);
-	if (!action)
-		return -ENOMEM;
-
-	action->handler = handler;
-	action->flags = irqflags;
-	cpus_clear(action->mask);
-	action->name = devname;
-	action->next = NULL;
-	action->dev_id = dev_id;
-
-	retval = setup_irq(irq, action);
-	if (retval)
-		kfree(action);
-	return retval;
-}
-
-EXPORT_SYMBOL(request_irq);
-
-void free_irq(unsigned int irq, void *dev_id)
-{
-	irq_desc_t *desc;
-	struct irqaction **p;
-	unsigned long flags;
-
-	if (irq >= ACTUAL_NR_IRQS)
-		return;
-
-	desc = irq_desc + irq;
-	spin_lock_irqsave(&desc->lock,flags);
-	p = &desc->action;
-	for (;;) {
-		struct irqaction * action = *p;
-		if (action) {
-			struct irqaction **pp = p;
-			p = &action->next;
-			if (action->dev_id != dev_id)
-				continue;
-
-			/* Found it - now remove it from the list of entries */
-			*pp = action->next;
-			if (!desc->action) {
-				desc->status |= IRQ_DISABLED;
-				desc->handler->shutdown(irq);
-			}
-			spin_unlock_irqrestore(&desc->lock,flags);
-			synchronize_irq(irq);
-			kfree(action);
-			return;
-		}
-		printk("Trying to free free IRQ%d\n",irq);
-		spin_unlock_irqrestore(&desc->lock,flags);
-		return;
-	}
-}
-
-EXPORT_SYMBOL(free_irq);
-
-static DECLARE_MUTEX(probe_sem);
-
-/*
- * IRQ autodetection code..
- *
- * This depends on the fact that any interrupt that
- * comes in on to an unassigned handler will get stuck
- * with "IRQ_WAITING" cleared and the interrupt
- * disabled.
- */
-unsigned long probe_irq_on(void)
-{
-	unsigned int i;
-	irq_desc_t *desc;
-	unsigned long val;
-	unsigned long delay;
-
-	down(&probe_sem);
-	/* 
-	 * something may have generated an irq long ago and we want to
-	 * flush such a longstanding irq before considering it as spurious. 
-	 */
-	for (i = NR_IRQS-1; i > 0; i--) {
-		desc = irq_desc + i;
-
-		spin_lock_irq(&desc->lock);
-		if (!desc->action)
-			desc->handler->startup(i);
-		spin_unlock_irq(&desc->lock);
-	}
-
-	/* Wait for longstanding interrupts to trigger. */
-	for (delay = jiffies + HZ/50; time_after(delay, jiffies); )
-		/* about 20ms delay */ barrier();
-
-	/*
-	 * enable any unassigned irqs
-	 * (we must startup again here because if a longstanding irq
-	 * happened in the previous stage, it may have masked itself)
-	 */
-	for (i = NR_IRQS-1; i > 0; i--) {
-		desc = irq_desc + i;
-
-		spin_lock_irq(&desc->lock);
-		if (!desc->action) {
-			desc->status |= IRQ_AUTODETECT | IRQ_WAITING;
-			if (desc->handler->startup(i))
-				desc->status |= IRQ_PENDING;
-		}
-		spin_unlock_irq(&desc->lock);
-	}
-
-	/*
-	 * Wait for spurious interrupts to trigger
-	 */
-	for (delay = jiffies + HZ/10; time_after(delay, jiffies); )
-		/* about 100ms delay */ barrier();
-
-	/*
-	 * Now filter out any obviously spurious interrupts
-	 */
-	val = 0;
-	for (i=0; i<NR_IRQS; i++) {
-		unsigned int status;
-
-		desc = irq_desc + i;
-
-		spin_lock_irq(&desc->lock);
-		status = desc->status;
-
-		if (status & IRQ_AUTODETECT) {
-			/* It triggered already - consider it spurious. */
-			if (!(status & IRQ_WAITING)) {
-				desc->status = status & ~IRQ_AUTODETECT;
-				desc->handler->shutdown(i);
-			} else
-				if (i < 32)
-					val |= 1 << i;
-		}
-		spin_unlock_irq(&desc->lock);
-	}
-
-	return val;
-}
-
-EXPORT_SYMBOL(probe_irq_on);
-
-/* Return a mask of triggered interrupts (this
- * can handle only legacy ISA interrupts).
- */
-
-/*
- *	probe_irq_mask - scan a bitmap of interrupt lines
- *	@val:	mask of interrupts to consider
- *
- *	Scan the ISA bus interrupt lines and return a bitmap of
- *	active interrupts. The interrupt probe logic state is then
- *	returned to its previous value.
- *
- *	Note: we need to scan all the irq's even though we will
- *	only return ISA irq numbers - just so that we reset them
- *	all to a known state.
- */
-unsigned int probe_irq_mask(unsigned long val)
-{
-	int i;
-	unsigned int mask;
-
-	mask = 0;
-	for (i = 0; i < NR_IRQS; i++) {
-		irq_desc_t *desc = irq_desc + i;
-		unsigned int status;
-
-		spin_lock_irq(&desc->lock);
-		status = desc->status;
-
-		if (status & IRQ_AUTODETECT) {
-			if (i < 16 && !(status & IRQ_WAITING))
-				mask |= 1 << i;
-
-			desc->status = status & ~IRQ_AUTODETECT;
-			desc->handler->shutdown(i);
-		}
-		spin_unlock_irq(&desc->lock);
-	}
-	up(&probe_sem);
-
-	return mask & val;
-}
-
-int probe_irq_off(unsigned long val)
-{
-	int i, irq_found, nr_irqs;
-
-	nr_irqs = 0;
-	irq_found = 0;
-	for (i=0; i<NR_IRQS; i++) {
-		irq_desc_t *desc = irq_desc + i;
-		unsigned int status;
-
-		spin_lock_irq(&desc->lock);
-		status = desc->status;
-
-		if (status & IRQ_AUTODETECT) {
-			if (!(status & IRQ_WAITING)) {
-				if (!nr_irqs)
-					irq_found = i;
-				nr_irqs++;
-			}
-			desc->status = status & ~IRQ_AUTODETECT;
-			desc->handler->shutdown(i);
-		}
-		spin_unlock_irq(&desc->lock);
-	}
-	up(&probe_sem);
-
-	if (nr_irqs > 1)
-		irq_found = -irq_found;
-	return irq_found;
-}
-
-EXPORT_SYMBOL(probe_irq_off);
-
-int setup_irq(unsigned int irq, struct irqaction * new)
-{
-	int shared = 0;
-	struct irqaction *old, **p;
-	unsigned long flags;
-	irq_desc_t *desc = irq_desc + irq;
-
-	if (desc->handler == &no_irq_type)
-		return -ENOSYS;
- 	/*
-	 * Some drivers like serial.c use request_irq() heavily,
-	 * so we have to be careful not to interfere with a
-	 * running system.
-	 */
-	if (new->flags & SA_SAMPLE_RANDOM) {
-		/*
-		 * This function might sleep, we want to call it first,
-		 * outside of the atomic block.
-		 * Yes, this might clear the entropy pool if the wrong
-		 * driver is attempted to be loaded, without actually
-		 * installing a new handler, but is this really a problem,
-		 * only the sysadmin is able to do this.
-		 */
-		rand_initialize_irq(irq);
-	}
-
-	/*
-	 * The following block of code has to be executed atomically
-	 */
-	spin_lock_irqsave(&desc->lock,flags);
-	p = &desc->action;
-	if ((old = *p) != NULL) {
-		/* Can't share interrupts unless both agree to */
-		if (!(old->flags & new->flags & SA_SHIRQ)) {
-			spin_unlock_irqrestore(&desc->lock,flags);
-			return -EBUSY;
-		}
-
-		/* add new interrupt at end of irq queue */
-		do {
-			p = &old->next;
-			old = *p;
-		} while (old);
-		shared = 1;
-	}
-
-	*p = new;
-
-	if (!shared) {
-		desc->depth = 0;
-		desc->status &= ~(IRQ_DISABLED | IRQ_AUTODETECT | IRQ_WAITING | IRQ_INPROGRESS);
-		desc->handler->startup(irq);
-	}
-	spin_unlock_irqrestore(&desc->lock,flags);
-	return 0;
-}
-
-#if defined(CONFIG_PROC_FS) && defined(CONFIG_SYSCTL)
-
-void init_irq_proc(void)
-{
-}
-#endif
-
-/* Taken from the 2.5 alpha port */
-#ifdef CONFIG_SMP
-void synchronize_irq(unsigned int irq)
-{
-	/* is there anything to synchronize with? */
-	if (!irq_desc[irq].action)
-		return;
-
-	while (irq_desc[irq].status & IRQ_INPROGRESS)
-		barrier();
-}
-#endif
diff -Nru a/arch/sh/kernel/ptrace.c b/arch/sh/kernel/ptrace.c
--- a/arch/sh/kernel/ptrace.c	2005-03-11 12:51:41 -08:00
+++ b/arch/sh/kernel/ptrace.c	2005-03-11 12:51:41 -08:00
@@ -1,5 +1,4 @@
-/* $Id: ptrace.c,v 1.15 2004/05/07 05:32:05 sugioka Exp $
- *
+/*
  * linux/arch/sh/kernel/ptrace.c
  *
  * Original x86 implementation:
diff -Nru a/arch/sh/kernel/sh_ksyms.c b/arch/sh/kernel/sh_ksyms.c
--- a/arch/sh/kernel/sh_ksyms.c	2005-03-11 12:51:41 -08:00
+++ b/arch/sh/kernel/sh_ksyms.c	2005-03-11 12:51:41 -08:00
@@ -65,13 +65,6 @@
 EXPORT_SYMBOL(memcmp);
 EXPORT_SYMBOL(memscan);
 EXPORT_SYMBOL(__copy_user);
-
-#ifdef CONFIG_VT
-/* XXX: MRB-remove - what was screen_info changed to?
-EXPORT_SYMBOL(screen_info);
-*/
-#endif
-
 EXPORT_SYMBOL(boot_cpu_data);
 
 #ifdef CONFIG_MMU
diff -Nru a/arch/sh/kernel/signal.c b/arch/sh/kernel/signal.c
--- a/arch/sh/kernel/signal.c	2005-03-11 12:51:52 -08:00
+++ b/arch/sh/kernel/signal.c	2005-03-11 12:51:52 -08:00
@@ -1,5 +1,4 @@
-/* $Id: signal.c,v 1.21 2004/06/28 13:18:44 doyu Exp $
- *
+/*
  *  linux/arch/sh/kernel/signal.c
  *
  *  Copyright (C) 1991, 1992  Linus Torvalds
@@ -341,8 +340,10 @@
 static inline void __user *
 get_sigframe(struct k_sigaction *ka, unsigned long sp, size_t frame_size)
 {
-	if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && ! on_sig_stack(sp))
-		sp = current->sas_ss_sp + current->sas_ss_size;
+	if (ka->sa.sa_flags & SA_ONSTACK) {
+		if (sas_ss_flags(sp) == 0)
+			sp = current->sas_ss_sp + current->sas_ss_size;
+	}
 
 	return (void __user *)((sp - frame_size) & -8ul);
 }
diff -Nru a/arch/sh/kernel/time.c b/arch/sh/kernel/time.c
--- a/arch/sh/kernel/time.c	2005-03-11 12:51:40 -08:00
+++ b/arch/sh/kernel/time.c	2005-03-11 12:51:40 -08:00
@@ -33,6 +33,7 @@
 #include <asm/machvec.h>
 #include <asm/rtc.h>
 #include <asm/freq.h>
+#include <asm/cpu/timer.h>
 #ifdef CONFIG_SH_KGDB
 #include <asm/kgdb.h>
 #endif
@@ -46,40 +47,10 @@
 
 #define TMU0_TCR_CALIB	0x0000
 
-#if defined(CONFIG_CPU_SH3)
-#if defined(CONFIG_CPU_SUBTYPE_SH7300)
-#define TMU_TSTR        0xA412FE92      /* Byte access */
-
-#define TMU0_TCOR       0xA412FE94      /* Long access */
-#define TMU0_TCNT       0xA412FE98      /* Long access */
-#define TMU0_TCR        0xA412FE9C      /* Word access */
-
-#define TMU1_TCOR	0xA412FEA0	/* Long access */
-#define TMU1_TCNT	0xA412FEA4	/* Long access */
-#define TMU1_TCR	0xA412FEA8	/* Word access */
-
-#define FRQCR           0xA415FF80
-#else
-#define TMU_TOCR	0xfffffe90	/* Byte access */
-#define TMU_TSTR	0xfffffe92	/* Byte access */
-
-#define TMU0_TCOR	0xfffffe94	/* Long access */
-#define TMU0_TCNT	0xfffffe98	/* Long access */
-#define TMU0_TCR	0xfffffe9c	/* Word access */
-#endif
-#elif defined(CONFIG_CPU_SH4)
-#define TMU_TOCR	0xffd80000	/* Byte access */
-#define TMU_TSTR	0xffd80004	/* Byte access */
-
-#define TMU0_TCOR	0xffd80008	/* Long access */
-#define TMU0_TCNT	0xffd8000c	/* Long access */
-#define TMU0_TCR	0xffd80010	/* Word access */
-
 #ifdef CONFIG_CPU_SUBTYPE_ST40STB1
 #define CLOCKGEN_MEMCLKCR 0xbb040038
 #define MEMCLKCR_RATIO_MASK 0x7
 #endif /* CONFIG_CPU_SUBTYPE_ST40STB1 */
-#endif /* CONFIG_CPU_SH3 or CONFIG_CPU_SH4 */
 
 extern unsigned long wall_jiffies;
 #define TICK_SIZE (tick_nsec / 1000)
@@ -272,7 +243,7 @@
 	profile_tick(CPU_PROFILING, regs);
 
 #ifdef CONFIG_HEARTBEAT
-	if (sh_mv.mv_heartbeat != NULL) 
+	if (sh_mv.mv_heartbeat != NULL)
 		sh_mv.mv_heartbeat();
 #endif
 
diff -Nru a/arch/sh/mm/cache-sh4.c b/arch/sh/mm/cache-sh4.c
--- a/arch/sh/mm/cache-sh4.c	2005-03-11 12:51:41 -08:00
+++ b/arch/sh/mm/cache-sh4.c	2005-03-11 12:51:41 -08:00
@@ -258,10 +258,16 @@
 	flush_cache_all();
 }
 
-static void __flush_cache_page(struct vm_area_struct *vma,
-			       unsigned long address,
-			       unsigned long phys)
+/*
+ * Write back and invalidate I/D-caches for the page.
+ *
+ * ADDR: Virtual Address (U0 address)
+ * PFN: Physical page number
+ */
+void flush_cache_page(struct vm_area_struct *vma, unsigned long address, unsigned long pfn)
 {
+	unsigned long phys = pfn << PAGE_SHIFT;
+
 	/* We only need to flush D-cache when we have alias */
 	if ((address^phys) & CACHE_ALIAS) {
 		/* Loop 4K of the D-cache */
@@ -342,32 +348,6 @@
 }
 
 /*
- * Write back and invalidate I/D-caches for the page.
- *
- * ADDR: Virtual Address (U0 address)
- */
-void flush_cache_page(struct vm_area_struct *vma, unsigned long address)
-{
-	pgd_t *dir;
-	pmd_t *pmd;
-	pte_t *pte;
-	pte_t entry;
-	unsigned long phys;
-
-	dir = pgd_offset(vma->vm_mm, address);
-	pmd = pmd_offset(dir, address);
-	if (pmd_none(*pmd) || pmd_bad(*pmd))
-		return;
-	pte = pte_offset_kernel(pmd, address);
-	entry = *pte;
-	if (!(pte_val(entry) & _PAGE_PRESENT))
-		return;
-
-	phys = pte_val(entry)&PTE_PHYS_MASK;
-	__flush_cache_page(vma, address, phys);
-}
-
-/*
  * flush_icache_user_range
  * @vma: VMA of the process
  * @page: page
@@ -377,6 +357,6 @@
 void flush_icache_user_range(struct vm_area_struct *vma,
 			     struct page *page, unsigned long addr, int len)
 {
-	__flush_cache_page(vma, addr, PHYSADDR(page_address(page)));
+	flush_cache_page(vma, addr, page_to_pfn(page));
 }
 
diff -Nru a/arch/sh/mm/cache-sh7705.c b/arch/sh/mm/cache-sh7705.c
--- a/arch/sh/mm/cache-sh7705.c	2005-03-11 12:51:42 -08:00
+++ b/arch/sh/mm/cache-sh7705.c	2005-03-11 12:51:42 -08:00
@@ -186,25 +186,9 @@
  *
  * ADDRESS: Virtual Address (U0 address)
  */
-void flush_cache_page(struct vm_area_struct *vma, unsigned long address)
+void flush_cache_page(struct vm_area_struct *vma, unsigned long address, unsigned long pfn)
 {
-	pgd_t *dir;
-	pmd_t *pmd;
-	pte_t *pte;
-	pte_t entry;
-	unsigned long phys;
-
-	dir = pgd_offset(vma->vm_mm, address);
-	pmd = pmd_offset(dir, address);
-	if (pmd_none(*pmd) || pmd_bad(*pmd))
-		return;
-	pte = pte_offset(pmd, address);
-	entry = *pte;
-	if (pte_none(entry) || !pte_present(entry))
-		return;
-
-	phys = pte_val(entry)&PTE_PHYS_MASK;
-	__flush_dcache_page(phys);
+	__flush_dcache_page(pfn << PAGE_SHIFT);
 }
 
 /*
diff -Nru a/arch/sh/mm/hugetlbpage.c b/arch/sh/mm/hugetlbpage.c
--- a/arch/sh/mm/hugetlbpage.c	2005-03-11 12:51:47 -08:00
+++ b/arch/sh/mm/hugetlbpage.c	2005-03-11 12:51:47 -08:00
@@ -202,7 +202,7 @@
 		page = pte_page(*pte);
 		put_page(page);
 		for (i = 0; i < (1 << HUGETLB_PAGE_ORDER); i++) {
-			pte_clear(pte);
+			pte_clear(mm, address+(i*PAGE_SIZE), pte);
 			pte++;
 		}
 	}
diff -Nru a/arch/sh/mm/pg-sh4.c b/arch/sh/mm/pg-sh4.c
--- a/arch/sh/mm/pg-sh4.c	2005-03-11 12:51:42 -08:00
+++ b/arch/sh/mm/pg-sh4.c	2005-03-11 12:51:42 -08:00
@@ -56,7 +56,7 @@
 		local_irq_restore(flags);
 		update_mmu_cache(NULL, p3_addr, entry);
 		__clear_user_page((void *)p3_addr, to);
-		pte_clear(pte);
+		pte_clear(&init_mm, p3_addr, pte);
 		up(&p3map_sem[(address & CACHE_ALIAS)>>12]);
 	}
 }
@@ -95,7 +95,7 @@
 		local_irq_restore(flags);
 		update_mmu_cache(NULL, p3_addr, entry);
 		__copy_user_page((void *)p3_addr, from, to);
-		pte_clear(pte);
+		pte_clear(&init_mm, p3_addr, pte);
 		up(&p3map_sem[(address & CACHE_ALIAS)>>12]);
 	}
 }
@@ -103,11 +103,11 @@
 /*
  * For SH-4, we have our own implementation for ptep_get_and_clear
  */
-inline pte_t ptep_get_and_clear(pte_t *ptep)
+inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
 {
 	pte_t pte = *ptep;
 
-	pte_clear(ptep);
+	pte_clear(mm, addr, ptep);
 	if (!pte_not_present(pte)) {
 		unsigned long pfn = pte_pfn(pte);
 		if (pfn_valid(pfn)) {
diff -Nru a/arch/sh/mm/pg-sh7705.c b/arch/sh/mm/pg-sh7705.c
--- a/arch/sh/mm/pg-sh7705.c	2005-03-11 12:51:46 -08:00
+++ b/arch/sh/mm/pg-sh7705.c	2005-03-11 12:51:46 -08:00
@@ -117,11 +117,11 @@
  * For SH7705, we have our own implementation for ptep_get_and_clear
  * Copied from pg-sh4.c
  */
-inline pte_t ptep_get_and_clear(pte_t *ptep)
+inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
 {
 	pte_t pte = *ptep;
 
-	pte_clear(ptep);
+	pte_clear(mm, addr, ptep);
 	if (!pte_not_present(pte)) {
 		unsigned long pfn = pte_pfn(pte);
 		if (pfn_valid(pfn)) {
diff -Nru a/arch/sh64/Kconfig b/arch/sh64/Kconfig
--- a/arch/sh64/Kconfig	2005-03-11 12:51:50 -08:00
+++ b/arch/sh64/Kconfig	2005-03-11 12:51:50 -08:00
@@ -98,7 +98,12 @@
 
 endchoice
 
+config SH_FPU
+	bool "FPU support"
+	default y
+
 config SH64_FPU_DENORM_FLUSH
+	depends on SH_FPU
 	bool "Flush floating point denorms to zero"
 
 choice
@@ -274,3 +279,15 @@
 source "crypto/Kconfig"
 
 source "lib/Kconfig"
+
+#
+# Use the generic interrupt handling code in kernel/irq/:
+#
+config GENERIC_HARDIRQS
+	bool
+	default y
+
+config GENERIC_IRQ_PROBE
+	bool
+	default y
+
diff -Nru a/arch/sh64/Kconfig.debug b/arch/sh64/Kconfig.debug
--- a/arch/sh64/Kconfig.debug	2005-03-11 12:51:42 -08:00
+++ b/arch/sh64/Kconfig.debug	2005-03-11 12:51:42 -08:00
@@ -19,6 +19,13 @@
 config SH64_SR_WATCH
 	bool "Debug: set SR.WATCH to enable hardware watchpoints and trace"
 
+config POOR_MANS_STRACE
+	bool "Debug: enable rudimentary strace facility"
+	help
+	  This option allows system calls to be traced to the console.  It also
+	  aids in detecting kernel stack underflow.  It is useful for debugging
+	  early-userland problems (e.g. init incurring fatal exceptions.)
+
 config SH_ALPHANUMERIC
 	bool "Enable debug outputs to on-board alphanumeric display"
 
diff -Nru a/arch/sh64/Makefile b/arch/sh64/Makefile
--- a/arch/sh64/Makefile	2005-03-11 12:51:41 -08:00
+++ b/arch/sh64/Makefile	2005-03-11 12:51:41 -08:00
@@ -11,13 +11,6 @@
 # for "archclean" and "archdep" for cleaning up and making dependencies for
 # this architecture
 #
-# Note that top level Makefile automagically builds dependencies for SUBDIRS
-# but does not automagically clean SUBDIRS. Therefore "archclean" should clean
-# up all, "archdep" does nothing on added SUBDIRS.
-#
-ifndef include_config
--include .config
-endif
 
 cpu-y				:= -mb
 cpu-$(CONFIG_LITTLE_ENDIAN)	:= -ml
@@ -37,10 +30,17 @@
 CFLAGS		+= $(cpu-y)
 
 LDFLAGS_vmlinux	+= --defsym phys_stext=_stext-$(CONFIG_CACHED_MEMORY_OFFSET) \
-		   -e phys_stext
+		  --defsym phys_stext_shmedia=phys_stext+1 \
+		  -e phys_stext_shmedia
 
 OBJCOPYFLAGS	:= -O binary -R .note -R .comment -R .stab -R .stabstr -S
 
+#
+# arch/sh64/defconfig never had any hope of being
+# frequently updated, so use one that does
+#
+KBUILD_DEFCONFIG	:= cayman_defconfig
+
 ifdef LOADADDR
 LINKFLAGS     += -Ttext $(word 1,$(LOADADDR))
 endif
@@ -52,7 +52,11 @@
 
 head-y := arch/$(ARCH)/kernel/head.o arch/$(ARCH)/kernel/init_task.o
 
-core-y += $(addprefix arch/$(ARCH)/, kernel/ mm/ mach-$(machine-y)/)
+core-y	+= arch/sh64/kernel/ arch/sh64/mm/
+
+ifneq ($(machine-y),)
+core-y	+= arch/sh64/mach-$(machine-y)/
+endif
 
 LIBGCC := $(shell $(CC) $(CFLAGS) -print-libgcc-file-name)
 libs-y	+= arch/$(ARCH)/lib/ $(LIBGCC)
@@ -92,7 +96,7 @@
 	echo "struct syscall_info {"; \
 	echo "	const char *name;"; \
 	echo "} syscall_info_table[] = {"; \
-	sed -e '/^.*\.long /!d;s//\t{ "/;s/\(\([^/]*\)\/\)\{1\}.*/\2/; \
+	sed -e '/^.*\.long /!d;s//    { "/;s/\(\([^/]*\)\/\)\{1\}.*/\2/; \
 		s/[ \t]*$$//g;s/$$/" },/;s/\("\)sys_/\1/g'; \
 	echo "};"; \
 	echo ""; \
diff -Nru a/arch/sh64/configs/cayman_defconfig b/arch/sh64/configs/cayman_defconfig
--- a/arch/sh64/configs/cayman_defconfig	2005-03-11 12:51:42 -08:00
+++ b/arch/sh64/configs/cayman_defconfig	2005-03-11 12:51:42 -08:00
@@ -1,11 +1,14 @@
 #
 # Automatically generated make config: don't edit
+# Linux kernel version: 2.6.11
+# Fri Feb 25 18:14:31 2005
 #
 CONFIG_SUPERH=y
 CONFIG_SUPERH64=y
 CONFIG_MMU=y
 CONFIG_UID16=y
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_LOG_BUF_SHIFT=14
 
 #
@@ -13,12 +16,12 @@
 #
 CONFIG_EXPERIMENTAL=y
 CONFIG_CLEAN_COMPILE=y
-CONFIG_STANDALONE=y
 CONFIG_BROKEN_ON_SMP=y
 
 #
 # General setup
 #
+CONFIG_LOCALVERSION=""
 CONFIG_SWAP=y
 # CONFIG_SYSVIPC is not set
 CONFIG_POSIX_MQUEUE=y
@@ -26,16 +29,21 @@
 CONFIG_SYSCTL=y
 # CONFIG_AUDIT is not set
 # CONFIG_HOTPLUG is not set
+CONFIG_KOBJECT_UEVENT=y
 # CONFIG_IKCONFIG is not set
 # CONFIG_EMBEDDED is not set
 CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SHMEM=y
+CONFIG_CC_ALIGN_FUNCTIONS=0
+CONFIG_CC_ALIGN_LABELS=0
+CONFIG_CC_ALIGN_LOOPS=0
+CONFIG_CC_ALIGN_JUMPS=0
+# CONFIG_TINY_SHMEM is not set
 
 #
 # Loadable module support
@@ -50,15 +58,12 @@
 CONFIG_SH_CAYMAN=y
 # CONFIG_SH_ROMRAM is not set
 # CONFIG_SH_HARP is not set
-
-#
-# Processor type and features
-#
 CONFIG_CPU_SH5=y
 CONFIG_CPU_SUBTYPE_SH5_101=y
 # CONFIG_CPU_SUBTYPE_SH5_103 is not set
 CONFIG_LITTLE_ENDIAN=y
 # CONFIG_BIG_ENDIAN is not set
+CONFIG_SH_FPU=y
 # CONFIG_SH64_FPU_DENORM_FLUSH is not set
 CONFIG_SH64_PGTABLE_2_LEVEL=y
 # CONFIG_SH64_PGTABLE_3_LEVEL is not set
@@ -102,12 +107,27 @@
 #
 # Bus options (PCI, PCMCIA, EISA, MCA, ISA)
 #
+CONFIG_SUPERHYWAY=y
 CONFIG_PCI=y
 CONFIG_SH_PCIDMA_NONCOHERENT=y
 CONFIG_PCI_LEGACY_PROC=y
 CONFIG_PCI_NAMES=y
 
 #
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PC-card bridges
+#
+
+#
+# PCI Hotplug Support
+#
+# CONFIG_HOTPLUG_PCI is not set
+
+#
 # Executable file formats
 #
 CONFIG_BINFMT_ELF=y
@@ -121,6 +141,10 @@
 #
 # Generic Driver Options
 #
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
 
 #
 # Memory Technology Devices (MTD)
@@ -144,14 +168,27 @@
 # CONFIG_BLK_CPQ_CISS_DA is not set
 # CONFIG_BLK_DEV_DAC960 is not set
 # CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
 CONFIG_BLK_DEV_LOOP=y
 # CONFIG_BLK_DEV_CRYPTOLOOP is not set
 # CONFIG_BLK_DEV_NBD is not set
-# CONFIG_BLK_DEV_CARMEL is not set
+# CONFIG_BLK_DEV_SX8 is not set
 CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
 CONFIG_BLK_DEV_RAM_SIZE=4096
 # CONFIG_BLK_DEV_INITRD is not set
+CONFIG_INITRAMFS_SOURCE=""
 # CONFIG_LBD is not set
+# CONFIG_CDROM_PKTCDVD is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
 
 #
 # ATA/ATAPI/MFM/RLL support
@@ -161,7 +198,74 @@
 #
 # SCSI device support
 #
-# CONFIG_SCSI is not set
+CONFIG_SCSI=y
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+# CONFIG_CHR_DEV_SG is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+CONFIG_SCSI_MULTI_LUN=y
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+
+#
+# SCSI Transport Attributes
+#
+CONFIG_SCSI_SPI_ATTRS=y
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_3W_9XXX is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AACRAID is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_EATA is not set
+# CONFIG_SCSI_EATA_PIO is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_GDTH is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+CONFIG_SCSI_SYM53C8XX_2=y
+CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=0
+CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
+CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
+# CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set
+# CONFIG_SCSI_IPR is not set
+# CONFIG_SCSI_QLOGIC_ISP is not set
+# CONFIG_SCSI_QLOGIC_FC is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+CONFIG_SCSI_QLA2XXX=y
+# CONFIG_SCSI_QLA21XX is not set
+# CONFIG_SCSI_QLA22XX is not set
+# CONFIG_SCSI_QLA2300 is not set
+# CONFIG_SCSI_QLA2322 is not set
+# CONFIG_SCSI_QLA6312 is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_NSP32 is not set
+# CONFIG_SCSI_DEBUG is not set
 
 #
 # Multi-device support (RAID and LVM)
@@ -171,6 +275,7 @@
 #
 # Fusion MPT device support
 #
+# CONFIG_FUSION is not set
 
 #
 # IEEE 1394 (FireWire) support
@@ -209,6 +314,9 @@
 # CONFIG_INET_AH is not set
 # CONFIG_INET_ESP is not set
 # CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+CONFIG_IP_TCPDIAG=y
+# CONFIG_IP_TCPDIAG_IPV6 is not set
 # CONFIG_IPV6 is not set
 # CONFIG_NETFILTER is not set
 
@@ -228,12 +336,12 @@
 # CONFIG_NET_DIVERT is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
-# CONFIG_NET_HW_FLOWCONTROL is not set
 
 #
 # QoS and/or fair queueing
 #
 # CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
 
 #
 # Network testing
@@ -309,6 +417,7 @@
 # CONFIG_YELLOWFIN is not set
 # CONFIG_R8169 is not set
 # CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
 
 #
@@ -335,6 +444,7 @@
 # CONFIG_HIPPI is not set
 # CONFIG_PPP is not set
 # CONFIG_SLIP is not set
+# CONFIG_NET_FC is not set
 # CONFIG_SHAPER is not set
 # CONFIG_NETCONSOLE is not set
 
@@ -375,6 +485,8 @@
 CONFIG_SERIO_SERPORT=y
 # CONFIG_SERIO_CT82C710 is not set
 # CONFIG_SERIO_PCIPS2 is not set
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
 
 #
 # Input Device Drivers
@@ -416,7 +528,6 @@
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
-# CONFIG_QIC02_TAPE is not set
 
 #
 # IPMI
@@ -449,8 +560,6 @@
 #
 # Ftape, the floppy tape device driver
 #
-# CONFIG_FTAPE is not set
-# CONFIG_AGP is not set
 # CONFIG_DRM is not set
 # CONFIG_RAW_DRIVER is not set
 
@@ -460,6 +569,11 @@
 # CONFIG_I2C is not set
 
 #
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
 # Misc devices
 #
 
@@ -477,17 +591,21 @@
 # Graphics support
 #
 CONFIG_FB=y
+CONFIG_FB_MODE_HELPERS=y
+# CONFIG_FB_TILEBLITTING is not set
+# CONFIG_FB_CIRRUS is not set
 # CONFIG_FB_PM2 is not set
 # CONFIG_FB_CYBER2000 is not set
 # CONFIG_FB_ASILIANT is not set
 # CONFIG_FB_IMSTT is not set
-# CONFIG_FB_E1355 is not set
+# CONFIG_FB_EPSON1355 is not set
 # CONFIG_FB_RIVA is not set
 # CONFIG_FB_MATROX is not set
 # CONFIG_FB_RADEON_OLD is not set
 # CONFIG_FB_RADEON is not set
 # CONFIG_FB_ATY128 is not set
 # CONFIG_FB_ATY is not set
+# CONFIG_FB_SAVAGE is not set
 # CONFIG_FB_SIS is not set
 # CONFIG_FB_NEOMAGIC is not set
 CONFIG_FB_KYRO=y
@@ -500,10 +618,8 @@
 # Console display driver support
 #
 # CONFIG_VGA_CONSOLE is not set
-# CONFIG_MDA_CONSOLE is not set
 CONFIG_DUMMY_CONSOLE=y
 CONFIG_FRAMEBUFFER_CONSOLE=y
-CONFIG_PCI_CONSOLE=y
 CONFIG_FONTS=y
 # CONFIG_FONT_8x8 is not set
 CONFIG_FONT_8x16=y
@@ -524,6 +640,7 @@
 # CONFIG_LOGO_SUPERH_MONO is not set
 # CONFIG_LOGO_SUPERH_VGA16 is not set
 CONFIG_LOGO_SUPERH_CLUT224=y
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
 
 #
 # Sound
@@ -534,6 +651,12 @@
 # USB support
 #
 # CONFIG_USB is not set
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
+#
 
 #
 # USB Gadget Support
@@ -541,18 +664,38 @@
 # CONFIG_USB_GADGET is not set
 
 #
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
 # File systems
 #
 CONFIG_EXT2_FS=y
 # CONFIG_EXT2_FS_XATTR is not set
-# CONFIG_EXT3_FS is not set
-# CONFIG_JBD is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
+
+#
+# XFS support
+#
 # CONFIG_XFS_FS is not set
 CONFIG_MINIX_FS=y
 CONFIG_ROMFS_FS=y
 # CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
 
@@ -565,7 +708,8 @@
 #
 # DOS/FAT/NT Filesystems
 #
-# CONFIG_FAT_FS is not set
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
 # CONFIG_NTFS_FS is not set
 
 #
@@ -577,6 +721,7 @@
 # CONFIG_DEVFS_FS is not set
 # CONFIG_DEVPTS_FS_XATTR is not set
 CONFIG_TMPFS=y
+# CONFIG_TMPFS_XATTR is not set
 CONFIG_HUGETLBFS=y
 CONFIG_HUGETLB_PAGE=y
 CONFIG_RAMFS=y
@@ -609,9 +754,9 @@
 CONFIG_ROOT_NFS=y
 CONFIG_LOCKD=y
 CONFIG_LOCKD_V4=y
-# CONFIG_EXPORTFS is not set
 CONFIG_SUNRPC=y
 # CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
 # CONFIG_SMB_FS is not set
 # CONFIG_CIFS is not set
 # CONFIG_NCP_FS is not set
@@ -621,8 +766,22 @@
 #
 # Partition Types
 #
-# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
 CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
 
 #
 # Native Language Support
@@ -630,21 +789,33 @@
 # CONFIG_NLS is not set
 
 #
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
 # Kernel hacking
 #
+CONFIG_DEBUG_KERNEL=y
 CONFIG_MAGIC_SYSRQ=y
+CONFIG_SCHEDSTATS=y
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_FS=y
+CONFIG_FRAME_POINTER=y
 # CONFIG_EARLY_PRINTK is not set
 # CONFIG_DEBUG_KERNEL_WITH_GDB_STUB is not set
-# CONFIG_SH64_PROC_TLB is not set
-# CONFIG_SH64_PROC_ASIDS is not set
+CONFIG_SH64_PROC_TLB=y
+CONFIG_SH64_PROC_ASIDS=y
 CONFIG_SH64_SR_WATCH=y
+# CONFIG_POOR_MANS_STRACE is not set
 # CONFIG_SH_ALPHANUMERIC is not set
 # CONFIG_SH_NO_BSS_INIT is not set
-CONFIG_FRAME_POINTER=y
 
 #
 # Security options
 #
+# CONFIG_KEYS is not set
 # CONFIG_SECURITY is not set
 
 #
@@ -653,7 +824,14 @@
 # CONFIG_CRYPTO is not set
 
 #
+# Hardware crypto devices
+#
+
+#
 # Library routines
 #
+# CONFIG_CRC_CCITT is not set
 CONFIG_CRC32=y
 # CONFIG_LIBCRC32C is not set
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
diff -Nru a/arch/sh64/defconfig b/arch/sh64/defconfig
--- a/arch/sh64/defconfig	2005-03-11 12:51:47 -08:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,667 +0,0 @@
-#
-# Automatically generated make config: don't edit
-#
-CONFIG_SUPERH=y
-CONFIG_SUPERH64=y
-CONFIG_MMU=y
-CONFIG_UID16=y
-CONFIG_RWSEM_GENERIC_SPINLOCK=y
-CONFIG_LOG_BUF_SHIFT=14
-
-#
-# Code maturity level options
-#
-CONFIG_EXPERIMENTAL=y
-CONFIG_CLEAN_COMPILE=y
-CONFIG_STANDALONE=y
-CONFIG_BROKEN_ON_SMP=y
-
-#
-# General setup
-#
-CONFIG_SWAP=y
-# CONFIG_SYSVIPC is not set
-CONFIG_POSIX_MQUEUE=y
-# CONFIG_BSD_PROCESS_ACCT is not set
-CONFIG_SYSCTL=y
-# CONFIG_AUDIT is not set
-# CONFIG_HOTPLUG is not set
-# CONFIG_IKCONFIG is not set
-# CONFIG_EMBEDDED is not set
-CONFIG_KALLSYMS=y
-# CONFIG_KALLSYMS_EXTRA_PASS is not set
-CONFIG_FUTEX=y
-CONFIG_EPOLL=y
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-
-#
-# Loadable module support
-#
-# CONFIG_MODULES is not set
-
-#
-# System type
-#
-# CONFIG_SH_GENERIC is not set
-# CONFIG_SH_SIMULATOR is not set
-CONFIG_SH_CAYMAN=y
-# CONFIG_SH_ROMRAM is not set
-# CONFIG_SH_HARP is not set
-CONFIG_CPU_SH5=y
-CONFIG_CPU_SUBTYPE_SH5_101=y
-# CONFIG_CPU_SUBTYPE_SH5_103 is not set
-CONFIG_LITTLE_ENDIAN=y
-# CONFIG_BIG_ENDIAN is not set
-# CONFIG_SH64_FPU_DENORM_FLUSH is not set
-CONFIG_SH64_PGTABLE_2_LEVEL=y
-# CONFIG_SH64_PGTABLE_3_LEVEL is not set
-CONFIG_HUGETLB_PAGE_SIZE_64K=y
-# CONFIG_HUGETLB_PAGE_SIZE_1MB is not set
-# CONFIG_HUGETLB_PAGE_SIZE_512MB is not set
-CONFIG_SH64_USER_MISALIGNED_FIXUP=y
-
-#
-# Memory options
-#
-CONFIG_CACHED_MEMORY_OFFSET=0x20000000
-CONFIG_MEMORY_START=0x80000000
-CONFIG_MEMORY_SIZE_IN_MB=128
-
-#
-# Cache options
-#
-# CONFIG_DCACHE_DISABLED is not set
-CONFIG_DCACHE_WRITE_BACK=y
-# CONFIG_DCACHE_WRITE_THROUGH is not set
-# CONFIG_ICACHE_DISABLED is not set
-CONFIG_PCIDEVICE_MEMORY_START=C0000000
-CONFIG_DEVICE_MEMORY_START=E0000000
-CONFIG_FLASH_MEMORY_START=0x00000000
-CONFIG_PCI_BLOCK_START=0x40000000
-
-#
-# CPU Subtype specific options
-#
-CONFIG_SH64_ID2815_WORKAROUND=y
-
-#
-# Misc options
-#
-CONFIG_HEARTBEAT=y
-CONFIG_HDSP253_LED=y
-CONFIG_SH_DMA=y
-CONFIG_PREEMPT=y
-
-#
-# Bus options (PCI, PCMCIA, EISA, MCA, ISA)
-#
-CONFIG_PCI=y
-CONFIG_SH_PCIDMA_NONCOHERENT=y
-CONFIG_PCI_LEGACY_PROC=y
-CONFIG_PCI_NAMES=y
-
-#
-# Executable file formats
-#
-CONFIG_BINFMT_ELF=y
-# CONFIG_BINFMT_FLAT is not set
-# CONFIG_BINFMT_MISC is not set
-
-#
-# Device Drivers
-#
-
-#
-# Generic Driver Options
-#
-CONFIG_PREVENT_FIRMWARE_BUILD=y
-
-#
-# Memory Technology Devices (MTD)
-#
-# CONFIG_MTD is not set
-
-#
-# Parallel port support
-#
-# CONFIG_PARPORT is not set
-
-#
-# Plug and Play support
-#
-
-#
-# Block devices
-#
-# CONFIG_BLK_DEV_FD is not set
-# CONFIG_BLK_CPQ_DA is not set
-# CONFIG_BLK_CPQ_CISS_DA is not set
-# CONFIG_BLK_DEV_DAC960 is not set
-# CONFIG_BLK_DEV_UMEM is not set
-CONFIG_BLK_DEV_LOOP=y
-# CONFIG_BLK_DEV_CRYPTOLOOP is not set
-# CONFIG_BLK_DEV_NBD is not set
-# CONFIG_BLK_DEV_SX8 is not set
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_SIZE=4096
-# CONFIG_BLK_DEV_INITRD is not set
-# CONFIG_LBD is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
-# CONFIG_IDE is not set
-
-#
-# SCSI device support
-#
-# CONFIG_SCSI is not set
-
-#
-# Multi-device support (RAID and LVM)
-#
-# CONFIG_MD is not set
-
-#
-# Fusion MPT device support
-#
-
-#
-# IEEE 1394 (FireWire) support
-#
-# CONFIG_IEEE1394 is not set
-
-#
-# I2O device support
-#
-# CONFIG_I2O is not set
-
-#
-# Networking support
-#
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-# CONFIG_PACKET_MMAP is not set
-# CONFIG_NETLINK_DEV is not set
-CONFIG_UNIX=y
-# CONFIG_NET_KEY is not set
-CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_PNP=y
-# CONFIG_IP_PNP_DHCP is not set
-# CONFIG_IP_PNP_BOOTP is not set
-# CONFIG_IP_PNP_RARP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_ARPD is not set
-# CONFIG_SYN_COOKIES is not set
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
-# CONFIG_INET_IPCOMP is not set
-# CONFIG_IPV6 is not set
-# CONFIG_NETFILTER is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
-# CONFIG_IP_SCTP is not set
-# CONFIG_ATM is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_DECNET is not set
-# CONFIG_LLC2 is not set
-# CONFIG_IPX is not set
-# CONFIG_ATALK is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_NET_DIVERT is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-# CONFIG_NET_HW_FLOWCONTROL is not set
-
-#
-# QoS and/or fair queueing
-#
-# CONFIG_NET_SCHED is not set
-# CONFIG_NET_CLS_ROUTE is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-# CONFIG_HAMRADIO is not set
-# CONFIG_IRDA is not set
-# CONFIG_BT is not set
-CONFIG_NETDEVICES=y
-# CONFIG_DUMMY is not set
-# CONFIG_BONDING is not set
-# CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
-
-#
-# ARCnet devices
-#
-# CONFIG_ARCNET is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
-CONFIG_NET_ETHERNET=y
-# CONFIG_MII is not set
-# CONFIG_STNIC is not set
-# CONFIG_HAPPYMEAL is not set
-# CONFIG_SUNGEM is not set
-# CONFIG_NET_VENDOR_3COM is not set
-
-#
-# Tulip family network device support
-#
-CONFIG_NET_TULIP=y
-# CONFIG_DE2104X is not set
-CONFIG_TULIP=y
-# CONFIG_TULIP_MWI is not set
-# CONFIG_TULIP_MMIO is not set
-# CONFIG_TULIP_NAPI is not set
-# CONFIG_DE4X5 is not set
-# CONFIG_WINBOND_840 is not set
-# CONFIG_DM9102 is not set
-# CONFIG_HP100 is not set
-CONFIG_NET_PCI=y
-# CONFIG_PCNET32 is not set
-# CONFIG_AMD8111_ETH is not set
-# CONFIG_ADAPTEC_STARFIRE is not set
-# CONFIG_B44 is not set
-# CONFIG_FORCEDETH is not set
-# CONFIG_DGRS is not set
-# CONFIG_EEPRO100 is not set
-# CONFIG_E100 is not set
-# CONFIG_FEALNX is not set
-# CONFIG_NATSEMI is not set
-# CONFIG_NE2K_PCI is not set
-# CONFIG_8139CP is not set
-# CONFIG_8139TOO is not set
-# CONFIG_SIS900 is not set
-# CONFIG_EPIC100 is not set
-# CONFIG_SUNDANCE is not set
-# CONFIG_TLAN is not set
-# CONFIG_VIA_RHINE is not set
-# CONFIG_VIA_VELOCITY is not set
-
-#
-# Ethernet (1000 Mbit)
-#
-# CONFIG_ACENIC is not set
-# CONFIG_DL2K is not set
-# CONFIG_E1000 is not set
-# CONFIG_NS83820 is not set
-# CONFIG_HAMACHI is not set
-# CONFIG_YELLOWFIN is not set
-# CONFIG_R8169 is not set
-# CONFIG_SK98LIN is not set
-# CONFIG_TIGON3 is not set
-
-#
-# Ethernet (10000 Mbit)
-#
-# CONFIG_IXGB is not set
-# CONFIG_S2IO is not set
-
-#
-# Token Ring devices
-#
-# CONFIG_TR is not set
-
-#
-# Wireless LAN (non-hamradio)
-#
-# CONFIG_NET_RADIO is not set
-
-#
-# Wan interfaces
-#
-# CONFIG_WAN is not set
-# CONFIG_FDDI is not set
-# CONFIG_HIPPI is not set
-# CONFIG_PPP is not set
-# CONFIG_SLIP is not set
-# CONFIG_SHAPER is not set
-# CONFIG_NETCONSOLE is not set
-
-#
-# ISDN subsystem
-#
-# CONFIG_ISDN is not set
-
-#
-# Telephony Support
-#
-# CONFIG_PHONE is not set
-
-#
-# Input device support
-#
-CONFIG_INPUT=y
-
-#
-# Userland interfaces
-#
-CONFIG_INPUT_MOUSEDEV=y
-CONFIG_INPUT_MOUSEDEV_PSAUX=y
-CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
-CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
-# CONFIG_INPUT_JOYDEV is not set
-# CONFIG_INPUT_TSDEV is not set
-# CONFIG_INPUT_EVDEV is not set
-# CONFIG_INPUT_EVBUG is not set
-
-#
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=y
-CONFIG_SERIO=y
-CONFIG_SERIO_I8042=y
-CONFIG_SERIO_SERPORT=y
-# CONFIG_SERIO_CT82C710 is not set
-# CONFIG_SERIO_PCIPS2 is not set
-
-#
-# Input Device Drivers
-#
-CONFIG_INPUT_KEYBOARD=y
-CONFIG_KEYBOARD_ATKBD=y
-# CONFIG_KEYBOARD_SUNKBD is not set
-# CONFIG_KEYBOARD_LKKBD is not set
-# CONFIG_KEYBOARD_XTKBD is not set
-# CONFIG_KEYBOARD_NEWTON is not set
-CONFIG_INPUT_MOUSE=y
-CONFIG_MOUSE_PS2=y
-# CONFIG_MOUSE_SERIAL is not set
-# CONFIG_MOUSE_VSXXXAA is not set
-# CONFIG_INPUT_JOYSTICK is not set
-# CONFIG_INPUT_TOUCHSCREEN is not set
-# CONFIG_INPUT_MISC is not set
-
-#
-# Character devices
-#
-CONFIG_VT=y
-CONFIG_VT_CONSOLE=y
-CONFIG_HW_CONSOLE=y
-# CONFIG_SERIAL_NONSTANDARD is not set
-
-#
-# Serial drivers
-#
-# CONFIG_SERIAL_8250 is not set
-
-#
-# Non-8250 serial port support
-#
-CONFIG_SERIAL_SH_SCI=y
-CONFIG_SERIAL_SH_SCI_CONSOLE=y
-CONFIG_SERIAL_CORE=y
-CONFIG_SERIAL_CORE_CONSOLE=y
-CONFIG_UNIX98_PTYS=y
-CONFIG_LEGACY_PTYS=y
-CONFIG_LEGACY_PTY_COUNT=256
-# CONFIG_QIC02_TAPE is not set
-
-#
-# IPMI
-#
-# CONFIG_IPMI_HANDLER is not set
-
-#
-# Watchdog Cards
-#
-CONFIG_WATCHDOG=y
-# CONFIG_WATCHDOG_NOWAYOUT is not set
-
-#
-# Watchdog Device Drivers
-#
-# CONFIG_SOFT_WATCHDOG is not set
-# CONFIG_SH_WDT is not set
-
-#
-# PCI-based Watchdog Cards
-#
-# CONFIG_PCIPCWATCHDOG is not set
-# CONFIG_WDTPCI is not set
-# CONFIG_RTC is not set
-# CONFIG_GEN_RTC is not set
-# CONFIG_DTLK is not set
-# CONFIG_R3964 is not set
-# CONFIG_APPLICOM is not set
-
-#
-# Ftape, the floppy tape device driver
-#
-# CONFIG_FTAPE is not set
-# CONFIG_AGP is not set
-# CONFIG_DRM is not set
-# CONFIG_RAW_DRIVER is not set
-
-#
-# I2C support
-#
-# CONFIG_I2C is not set
-
-#
-# Misc devices
-#
-
-#
-# Multimedia devices
-#
-# CONFIG_VIDEO_DEV is not set
-
-#
-# Digital Video Broadcasting Devices
-#
-# CONFIG_DVB is not set
-
-#
-# Graphics support
-#
-CONFIG_FB=y
-# CONFIG_FB_CIRRUS is not set
-# CONFIG_FB_PM2 is not set
-# CONFIG_FB_CYBER2000 is not set
-# CONFIG_FB_ASILIANT is not set
-# CONFIG_FB_IMSTT is not set
-# CONFIG_FB_E1355 is not set
-# CONFIG_FB_RIVA is not set
-# CONFIG_FB_MATROX is not set
-# CONFIG_FB_RADEON_OLD is not set
-# CONFIG_FB_RADEON is not set
-# CONFIG_FB_ATY128 is not set
-# CONFIG_FB_ATY is not set
-# CONFIG_FB_SIS is not set
-# CONFIG_FB_NEOMAGIC is not set
-CONFIG_FB_KYRO=y
-# CONFIG_FB_3DFX is not set
-# CONFIG_FB_VOODOO1 is not set
-# CONFIG_FB_TRIDENT is not set
-# CONFIG_FB_VIRTUAL is not set
-
-#
-# Console display driver support
-#
-# CONFIG_VGA_CONSOLE is not set
-# CONFIG_MDA_CONSOLE is not set
-CONFIG_DUMMY_CONSOLE=y
-CONFIG_FRAMEBUFFER_CONSOLE=y
-CONFIG_PCI_CONSOLE=y
-CONFIG_FONTS=y
-# CONFIG_FONT_8x8 is not set
-CONFIG_FONT_8x16=y
-# CONFIG_FONT_6x11 is not set
-# CONFIG_FONT_PEARL_8x8 is not set
-# CONFIG_FONT_ACORN_8x8 is not set
-# CONFIG_FONT_MINI_4x6 is not set
-# CONFIG_FONT_SUN8x16 is not set
-# CONFIG_FONT_SUN12x22 is not set
-
-#
-# Logo configuration
-#
-CONFIG_LOGO=y
-# CONFIG_LOGO_LINUX_MONO is not set
-# CONFIG_LOGO_LINUX_VGA16 is not set
-# CONFIG_LOGO_LINUX_CLUT224 is not set
-# CONFIG_LOGO_SUPERH_MONO is not set
-# CONFIG_LOGO_SUPERH_VGA16 is not set
-CONFIG_LOGO_SUPERH_CLUT224=y
-
-#
-# Sound
-#
-# CONFIG_SOUND is not set
-
-#
-# USB support
-#
-# CONFIG_USB is not set
-
-#
-# USB Gadget Support
-#
-# CONFIG_USB_GADGET is not set
-
-#
-# File systems
-#
-CONFIG_EXT2_FS=y
-# CONFIG_EXT2_FS_XATTR is not set
-# CONFIG_EXT3_FS is not set
-# CONFIG_JBD is not set
-# CONFIG_REISERFS_FS is not set
-# CONFIG_JFS_FS is not set
-# CONFIG_XFS_FS is not set
-CONFIG_MINIX_FS=y
-CONFIG_ROMFS_FS=y
-# CONFIG_QUOTA is not set
-# CONFIG_AUTOFS_FS is not set
-# CONFIG_AUTOFS4_FS is not set
-
-#
-# CD-ROM/DVD Filesystems
-#
-# CONFIG_ISO9660_FS is not set
-# CONFIG_UDF_FS is not set
-
-#
-# DOS/FAT/NT Filesystems
-#
-# CONFIG_FAT_FS is not set
-# CONFIG_NTFS_FS is not set
-
-#
-# Pseudo filesystems
-#
-CONFIG_PROC_FS=y
-CONFIG_PROC_KCORE=y
-CONFIG_SYSFS=y
-# CONFIG_DEVFS_FS is not set
-# CONFIG_DEVPTS_FS_XATTR is not set
-CONFIG_TMPFS=y
-CONFIG_HUGETLBFS=y
-CONFIG_HUGETLB_PAGE=y
-CONFIG_RAMFS=y
-
-#
-# Miscellaneous filesystems
-#
-# CONFIG_ADFS_FS is not set
-# CONFIG_AFFS_FS is not set
-# CONFIG_HFS_FS is not set
-# CONFIG_HFSPLUS_FS is not set
-# CONFIG_BEFS_FS is not set
-# CONFIG_BFS_FS is not set
-# CONFIG_EFS_FS is not set
-# CONFIG_CRAMFS is not set
-# CONFIG_VXFS_FS is not set
-# CONFIG_HPFS_FS is not set
-# CONFIG_QNX4FS_FS is not set
-# CONFIG_SYSV_FS is not set
-# CONFIG_UFS_FS is not set
-
-#
-# Network File Systems
-#
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
-# CONFIG_NFS_V4 is not set
-# CONFIG_NFS_DIRECTIO is not set
-# CONFIG_NFSD is not set
-CONFIG_ROOT_NFS=y
-CONFIG_LOCKD=y
-CONFIG_LOCKD_V4=y
-# CONFIG_EXPORTFS is not set
-CONFIG_SUNRPC=y
-# CONFIG_RPCSEC_GSS_KRB5 is not set
-# CONFIG_SMB_FS is not set
-# CONFIG_CIFS is not set
-# CONFIG_NCP_FS is not set
-# CONFIG_CODA_FS is not set
-# CONFIG_AFS_FS is not set
-
-#
-# Partition Types
-#
-# CONFIG_PARTITION_ADVANCED is not set
-CONFIG_MSDOS_PARTITION=y
-
-#
-# Native Language Support
-#
-# CONFIG_NLS is not set
-
-#
-# Profiling support
-#
-CONFIG_PROFILING=y
-# CONFIG_OPROFILE is not set
-
-#
-# Kernel hacking
-#
-CONFIG_MAGIC_SYSRQ=y
-# CONFIG_EARLY_PRINTK is not set
-# CONFIG_DEBUG_KERNEL_WITH_GDB_STUB is not set
-# CONFIG_SH64_PROC_TLB is not set
-# CONFIG_SH64_PROC_ASIDS is not set
-CONFIG_SH64_SR_WATCH=y
-# CONFIG_SH_ALPHANUMERIC is not set
-# CONFIG_SH_NO_BSS_INIT is not set
-CONFIG_FRAME_POINTER=y
-
-#
-# Security options
-#
-# CONFIG_SECURITY is not set
-
-#
-# Cryptographic options
-#
-# CONFIG_CRYPTO is not set
-
-#
-# Library routines
-#
-# CONFIG_CRC16 is not set
-CONFIG_CRC32=y
-# CONFIG_LIBCRC32C is not set
diff -Nru a/arch/sh64/kernel/Makefile b/arch/sh64/kernel/Makefile
--- a/arch/sh64/kernel/Makefile	2005-03-11 12:51:47 -08:00
+++ b/arch/sh64/kernel/Makefile	2005-03-11 12:51:47 -08:00
@@ -13,7 +13,7 @@
 # unless it's something special (ie not a .c file).
 #
 
-extra-y	:= head.o init_task.o vmlinux.lds.s
+extra-y	:= head.o init_task.o vmlinux.lds
 
 obj-y	:= process.o signal.o entry.o traps.o irq.o irq_intc.o \
 	   ptrace.o setup.o time.o sys_sh64.o semaphore.o sh_ksyms.o \
@@ -22,16 +22,14 @@
 obj-$(CONFIG_HEARTBEAT)		+= led.o
 obj-$(CONFIG_SH_ALPHANUMERIC)	+= alphanum.o
 obj-$(CONFIG_SH_DMA)		+= dma.o
+obj-$(CONFIG_SH_FPU)		+= fpu.o
 obj-$(CONFIG_EARLY_PRINTK)	+= early_printk.o
 obj-$(CONFIG_KALLSYMS)		+= unwind.o
 obj-$(CONFIG_PCI)		+= pci-dma.o pcibios.o
+obj-$(CONFIG_MODULES)		+= module.o
 
 ifeq ($(CONFIG_PCI),y)
 obj-$(CONFIG_CPU_SH5)		+= pci_sh5.o
-endif
-
-ifndef CONFIG_NOFPU_SUPPORT
-obj-y				+= fpu.o
 endif
 
 USE_STANDARD_AS_RULE := true
diff -Nru a/arch/sh64/kernel/dma.c b/arch/sh64/kernel/dma.c
--- a/arch/sh64/kernel/dma.c	2005-03-11 12:51:41 -08:00
+++ b/arch/sh64/kernel/dma.c	2005-03-11 12:51:41 -08:00
@@ -31,7 +31,7 @@
 } dma_info_t;
 
 static dma_info_t dma_info[MAX_DMA_CHANNELS];
-extern spinlock_t dma_spin_lock;
+static DEFINE_SPINLOCK(dma_spin_lock);
 
 /* arch/sh64/kernel/irq_intc.c */
 extern void make_intc_irq(unsigned int irq);
diff -Nru a/arch/sh64/kernel/early_printk.c b/arch/sh64/kernel/early_printk.c
--- a/arch/sh64/kernel/early_printk.c	2005-03-11 12:51:52 -08:00
+++ b/arch/sh64/kernel/early_printk.c	2005-03-11 12:51:52 -08:00
@@ -16,8 +16,6 @@
 #include <asm/io.h>
 #include <asm/hardware.h>
 
-extern void cpu_relax(void);
-
 #define SCIF_BASE_ADDR	0x01030000
 #define SCIF_ADDR_SH5	PHYS_PERIPHERAL_BLOCK+SCIF_BASE_ADDR
 
diff -Nru a/arch/sh64/kernel/entry.S b/arch/sh64/kernel/entry.S
--- a/arch/sh64/kernel/entry.S	2005-03-11 12:51:42 -08:00
+++ b/arch/sh64/kernel/entry.S	2005-03-11 12:51:42 -08:00
@@ -6,7 +6,7 @@
  * arch/sh64/kernel/entry.S
  *
  * Copyright (C) 2000, 2001  Paolo Alberelli
- * Copyright (C) 2004  Paul Mundt
+ * Copyright (C) 2004, 2005  Paul Mundt
  * Copyright (C) 2003, 2004 Richard Curnow
  *
  */
@@ -155,7 +155,7 @@
 	.long	tlb_miss_store				/* 0x0C0 */
 	.long	do_address_error_load	/* 0x0E0 */
 	.long	do_address_error_store	/* 0x100 */
-#ifndef CONFIG_NOFPU_SUPPORT
+#ifdef CONFIG_SH_FPU
 	.long	do_fpu_error		/* 0x120 */
 #else
 	.long	do_exception_error		/* 0x120 */
@@ -237,6 +237,7 @@
 	.space	256, 0			/* Power-on class handler, */
 					/* not required here       */
 not_a_tlb_miss:
+	synco	/* TAKum03020 (but probably a good idea anyway.) */
 	/* Save original stack pointer into KCR1 */
 	putcon	SP, KCR1
 
@@ -278,6 +279,7 @@
 	 * block making sure the final alignment is correct.
 	 */
 tlb_miss:
+	synco	/* TAKum03020 (but probably a good idea anyway.) */
 	putcon	SP, KCR1
 	movi	reg_save_area, SP
 	/* SP is guaranteed 32-byte aligned. */
@@ -393,6 +395,7 @@
 	/* VBR + 0x600 */
 
 interrupt:
+	synco	/* TAKum03020 (but probably a good idea anyway.) */
 	/* Save original stack pointer into KCR1 */
 	putcon	SP, KCR1
 
@@ -429,6 +432,7 @@
 	 *			(this may need to be extended...)
 	 */
 reset_or_panic:
+	synco	/* TAKum03020 (but probably a good idea anyway.) */
 	putcon	SP, DCR
 	/* First save r0-1 and tr0, as we need to use these */
 	movi	resvec_save_area-CONFIG_CACHED_MEMORY_OFFSET, SP
@@ -481,6 +485,7 @@
 
 	.balign	256
 debug_exception:
+	synco	/* TAKum03020 (but probably a good idea anyway.) */
 	/*
 	 * Single step/software_break_point first level handler.
 	 * Called with MMU off, so the first thing we do is enable it
@@ -788,9 +793,7 @@
 	! exceptions
 	add	SP, ZERO, r14
 
-#define POOR_MANS_STRACE 0
-
-#if POOR_MANS_STRACE
+#ifdef CONFIG_POOR_MANS_STRACE
 	/* We've pushed all the registers now, so only r2-r4 hold anything
 	 * useful. Move them into callee save registers */
 	or	r2, ZERO, r28
@@ -811,7 +814,6 @@
 	or	r30, ZERO, r4
 #endif
 
-
 	/* For syscall and debug race condition, get TRA now */
 	getcon	TRA, r5
 
@@ -866,7 +868,7 @@
  */
 	.global ret_from_irq
 ret_from_irq:
-#if POOR_MANS_STRACE
+#ifdef CONFIG_POOR_MANS_STRACE
 	pta	evt_debug_ret_from_irq, tr0
 	ori	SP, 0, r2
 	blink	tr0, LINK
@@ -884,7 +886,7 @@
 ret_from_exception:
 	preempt_stop()
 
-#if POOR_MANS_STRACE
+#ifdef CONFIG_POOR_MANS_STRACE
 	pta	evt_debug_ret_from_exc, tr0
 	ori	SP, 0, r2
 	blink	tr0, LINK
@@ -1141,7 +1143,7 @@
 fpu_error_or_IRQA:
 	pta	its_IRQ, tr0
 	beqi/l	r4, EVENT_INTERRUPT, tr0
-#ifndef CONFIG_NOFPU_SUPPORT
+#ifdef CONFIG_SH_FPU
 	movi	do_fpu_state_restore, r6
 #else
 	movi	do_exception_error, r6
@@ -1152,7 +1154,7 @@
 fpu_error_or_IRQB:
 	pta	its_IRQ, tr0
 	beqi/l	r4, EVENT_INTERRUPT, tr0
-#ifndef CONFIG_NOFPU_SUPPORT
+#ifdef CONFIG_SH_FPU
 	movi	do_fpu_state_restore, r6
 #else
 	movi	do_exception_error, r6
@@ -1223,7 +1225,7 @@
 syscall_ret:
 	st.q	SP, FRAME_R(9), r2	/* Expecting SP back to BASIC frame */
 
-#if POOR_MANS_STRACE
+#ifdef CONFIG_POOR_MANS_STRACE
 	/* nothing useful in registers at this point */
 
 	movi	evt_debug2, r5
@@ -1254,7 +1256,7 @@
 	ptabs	r5, tr0
 	blink	tr0, LINK
 
-#if POOR_MANS_STRACE
+#ifdef CONFIG_POOR_MANS_STRACE
 	/* nothing useful in registers at this point */
 
 	movi	evt_debug2, r5
diff -Nru a/arch/sh64/kernel/head.S b/arch/sh64/kernel/head.S
--- a/arch/sh64/kernel/head.S	2005-03-11 12:51:46 -08:00
+++ b/arch/sh64/kernel/head.S	2005-03-11 12:51:46 -08:00
@@ -96,8 +96,8 @@
 	.long	0		/* RAMDISK_FLAGS */
 	.long	0x0200		/* ORIG_ROOT_DEV */
 	.long	1		/* LOADER_TYPE */
-	.long	0x00360000	/* INITRD_START */
-	.long	0x000a0000	/* INITRD_SIZE */
+	.long	0x00800000	/* INITRD_START */
+	.long	0x00800000	/* INITRD_SIZE */
 	.long	0
 
 	.text
@@ -310,7 +310,7 @@
 	 */
 	movi fpu_in_use, r31	/* Temporary */
 
-#ifndef CONFIG_NOFPU_SUPPORT
+#ifdef CONFIG_SH_FPU
 	getcon	SR, r21
 	movi	SR_ENABLE_FPU, r22
 	and	r21, r22, r22
diff -Nru a/arch/sh64/kernel/irq.c b/arch/sh64/kernel/irq.c
--- a/arch/sh64/kernel/irq.c	2005-03-11 12:51:41 -08:00
+++ b/arch/sh64/kernel/irq.c	2005-03-11 12:51:41 -08:00
@@ -39,57 +39,11 @@
 #include <asm/irq.h>
 #include <linux/irq.h>
 
-/*
- * Controller mappings for all interrupt sources:
- */
-irq_desc_t irq_desc[NR_IRQS] __cacheline_aligned = {
-	[0 ... NR_IRQS-1] = {
-		.handler = &no_irq_type,
-		.lock = SPIN_LOCK_UNLOCKED
-	}
-};
-
-
-/*
- * Special irq handlers.
- */
-
-irqreturn_t no_action(int cpl, void *dev_id, struct pt_regs *regs)
+void ack_bad_irq(unsigned int irq)
 {
-	return IRQ_NONE;
-}
-
-/*
- * Generic no controller code
- */
-
-static void enable_none(unsigned int irq) { }
-static unsigned int startup_none(unsigned int irq) { return 0; }
-static void disable_none(unsigned int irq) { }
-static void ack_none(unsigned int irq)
-{
-/*
- * 'what should we do if we get a hw irq event on an illegal vector'.
- * each architecture has to answer this themselves, it doesnt deserve
- * a generic callback i think.
- */
 	printk("unexpected IRQ trap at irq %02x\n", irq);
 }
 
-/* startup is the same as "enable", shutdown is same as "disable" */
-#define shutdown_none	disable_none
-#define end_none	enable_none
-
-struct hw_interrupt_type no_irq_type = {
-	"none",
-	startup_none,
-	shutdown_none,
-	enable_none,
-	disable_none,
-	ack_none,
-	end_none
-};
-
 #if defined(CONFIG_PROC_FS)
 int show_interrupts(struct seq_file *p, void *v)
 {
@@ -139,584 +93,24 @@
 }
 
 /*
- * This should really return information about whether
- * we should do bottom half handling etc. Right now we
- * end up _always_ checking the bottom half, which is a
- * waste of time and is not what some drivers would
- * prefer.
- */
-int handle_IRQ_event(unsigned int irq, struct pt_regs * regs, struct irqaction * action)
-{
-	int status;
-	int ret;
-
-	status = 1;	/* Force the "do bottom halves" bit */
-
-        if (!(action->flags & SA_INTERRUPT))
-                local_irq_enable();
-
-	do {
-		ret = action->handler(irq, action->dev_id, regs);
-		if (ret == IRQ_HANDLED)
-			status |= action->flags;
-		action = action->next;
-	} while (action);
-	if (status & SA_SAMPLE_RANDOM)
-		add_interrupt_randomness(irq);
-
-	local_irq_disable();
-
-	return status;
-}
-
-/*
- * Generic enable/disable code: this just calls
- * down into the PIC-specific version for the actual
- * hardware disable after having gotten the irq
- * controller lock.
- */
-
-/**
- *	disable_irq_nosync - disable an irq without waiting
- *	@irq: Interrupt to disable
- *
- *	Disable the selected interrupt line. Disables of an interrupt
- *	stack. Unlike disable_irq(), this function does not ensure existing
- *	instances of the IRQ handler have completed before returning.
- *
- *	This function may be called from IRQ context.
- */
-void disable_irq_nosync(unsigned int irq)
-{
-	irq_desc_t *desc = irq_desc + irq;
-	unsigned long flags;
-
-	spin_lock_irqsave(&desc->lock, flags);
-	if (!desc->depth++) {
-		desc->status |= IRQ_DISABLED;
-		desc->handler->disable(irq);
-	}
-	spin_unlock_irqrestore(&desc->lock, flags);
-}
-
-/**
- *	disable_irq - disable an irq and wait for completion
- *	@irq: Interrupt to disable
- *
- *	Disable the selected interrupt line. Disables of an interrupt
- *	stack. That is for two disables you need two enables. This
- *	function waits for any pending IRQ handlers for this interrupt
- *	to complete before returning. If you use this function while
- *	holding a resource the IRQ handler may need you will deadlock.
- *
- *	This function may be called - with care - from IRQ context.
- */
-void disable_irq(unsigned int irq)
-{
-	disable_irq_nosync(irq);
-	synchronize_irq(irq);
-}
-
-/**
- *	enable_irq - enable interrupt handling on an irq
- *	@irq: Interrupt to enable
- *
- *	Re-enables the processing of interrupts on this IRQ line
- *	providing no disable_irq calls are now in effect.
- *
- *	This function may be called from IRQ context.
- */
-void enable_irq(unsigned int irq)
-{
-	irq_desc_t *desc = irq_desc + irq;
-	unsigned long flags;
-
-	spin_lock_irqsave(&desc->lock, flags);
-	switch (desc->depth) {
-	case 1: {
-		unsigned int status = desc->status & ~IRQ_DISABLED;
-		desc->status = status;
-		if ((status & (IRQ_PENDING | IRQ_REPLAY)) == IRQ_PENDING) {
-			desc->status = status | IRQ_REPLAY;
-			hw_resend_irq(desc->handler,irq);
-		}
-		desc->handler->enable(irq);
-		/* fall-through */
-	}
-	default:
-		desc->depth--;
-		break;
-	case 0:
-		printk("enable_irq() unbalanced from %p\n",
-		       __builtin_return_address(0));
-	}
-	spin_unlock_irqrestore(&desc->lock, flags);
-}
-
-/*
  * do_IRQ handles all normal device IRQ's.
  */
 asmlinkage int do_IRQ(unsigned long vector_num, struct pt_regs * regs)
 {
-	/*
-	 * We ack quickly, we don't want the irq controller
-	 * thinking we're snobs just because some other CPU has
-	 * disabled global interrupts (we have already done the
-	 * INT_ACK cycles, it's too late to try to pretend to the
-	 * controller that we aren't taking the interrupt).
-	 *
-	 * 0 return value means that this irq is already being
-	 * handled by some other CPU. (or is disabled)
-	 */
 	int irq;
-	int cpu = smp_processor_id();
-	irq_desc_t *desc = NULL;
-	struct irqaction * action;
-	unsigned int status;
 
 	irq_enter();
 
-#ifdef CONFIG_PREEMPT
-	/*
-	 * At this point we're now about to actually call handlers,
-	 * and interrupts might get reenabled during them... bump
-	 * preempt_count to prevent any preemption while the handler
-	 * called here is pending...
-	 */
-	preempt_disable();
-#endif
-
 	irq = irq_demux(vector_num);
 
-	/*
-	 * Should never happen, if it does check
-	 * vectorN_to_IRQ[] against trap_jtable[].
-	 */
-	if (irq == -1) {
+	if (irq >= 0) {
+		__do_IRQ(irq, regs);
+	} else {
 		printk("unexpected IRQ trap at vector %03lx\n", vector_num);
-		goto out;
-	}
-
-	desc = irq_desc + irq;
-
-	kstat_cpu(cpu).irqs[irq]++;
-	spin_lock(&desc->lock);
-	desc->handler->ack(irq);
-	/*
-	   REPLAY is when Linux resends an IRQ that was dropped earlier
-	   WAITING is used by probe to mark irqs that are being tested
-	   */
-	status = desc->status & ~(IRQ_REPLAY | IRQ_WAITING | IRQ_INPROGRESS);
-	status |= IRQ_PENDING; /* we _want_ to handle it */
-
-	/*
-	 * If the IRQ is disabled for whatever reason, we cannot
-	 * use the action we have.
-	 */
-	action = NULL;
-	if (!(status & (IRQ_DISABLED | IRQ_INPROGRESS))) {
-		action = desc->action;
-		status &= ~IRQ_PENDING; /* we commit to handling */
-		status |= IRQ_INPROGRESS; /* we are handling it */
-	}
-	desc->status = status;
-
-	/*
-	 * If there is no IRQ handler or it was disabled, exit early.
-	   Since we set PENDING, if another processor is handling
-	   a different instance of this same irq, the other processor
-	   will take care of it.
-	 */
-	if (!action)
-		goto out;
-
-	/*
-	 * Edge triggered interrupts need to remember
-	 * pending events.
-	 * This applies to any hw interrupts that allow a second
-	 * instance of the same irq to arrive while we are in do_IRQ
-	 * or in the handler. But the code here only handles the _second_
-	 * instance of the irq, not the third or fourth. So it is mostly
-	 * useful for irq hardware that does not mask cleanly in an
-	 * SMP environment.
-	 */
-	for (;;) {
-		spin_unlock(&desc->lock);
-		handle_IRQ_event(irq, regs, action);
-		spin_lock(&desc->lock);
-
-		if (!(desc->status & IRQ_PENDING))
-			break;
-		desc->status &= ~IRQ_PENDING;
-	}
-	desc->status &= ~IRQ_INPROGRESS;
-out:
-	/*
-	 * The ->end() handler has to deal with interrupts which got
-	 * disabled while the handler was running.
-	 */
-	if (desc) {
-		desc->handler->end(irq);
-		spin_unlock(&desc->lock);
 	}
 
 	irq_exit();
 
-#ifdef CONFIG_PREEMPT
-	/*
-	 * We're done with the handlers, interrupts should be
-	 * currently disabled; decrement preempt_count now so
-	 * as we return preemption may be allowed...
-	 */
-	preempt_enable_no_resched();
-#endif
-
 	return 1;
 }
 
-/**
- *	request_irq - allocate an interrupt line
- *	@irq: Interrupt line to allocate
- *	@handler: Function to be called when the IRQ occurs
- *	@irqflags: Interrupt type flags
- *	@devname: An ascii name for the claiming device
- *	@dev_id: A cookie passed back to the handler function
- *
- *	This call allocates interrupt resources and enables the
- *	interrupt line and IRQ handling. From the point this
- *	call is made your handler function may be invoked. Since
- *	your handler function must clear any interrupt the board
- *	raises, you must take care both to initialise your hardware
- *	and to set up the interrupt handler in the right order.
- *
- *	Dev_id must be globally unique. Normally the address of the
- *	device data structure is used as the cookie. Since the handler
- *	receives this value it makes sense to use it.
- *
- *	If your interrupt is shared you must pass a non NULL dev_id
- *	as this is required when freeing the interrupt.
- *
- *	Flags:
- *
- *	SA_SHIRQ		Interrupt is shared
- *
- *	SA_INTERRUPT		Disable local interrupts while processing
- *
- *	SA_SAMPLE_RANDOM	The interrupt can be used for entropy
- *
- */
-int request_irq(unsigned int irq,
-		irqreturn_t (*handler)(int, void *, struct pt_regs *),
-		unsigned long irqflags,
-		const char * devname,
-		void *dev_id)
-{
-	int retval;
-	struct irqaction * action;
-
-#if 1
-	/*
-	 * Sanity-check: shared interrupts should REALLY pass in
-	 * a real dev-ID, otherwise we'll have trouble later trying
-	 * to figure out which interrupt is which (messes up the
-	 * interrupt freeing logic etc).
-	 */
-	if (irqflags & SA_SHIRQ) {
-		if (!dev_id)
-			printk("Bad boy: %s (at 0x%x) called us without a dev_id!\n", devname, (&irq)[-1]);
-	}
-#endif
-
-	if (irq >= NR_IRQS)
-		return -EINVAL;
-	if (!handler)
-		return -EINVAL;
-
-	action = (struct irqaction *)
-			kmalloc(sizeof(struct irqaction), GFP_KERNEL);
-	if (!action)
-		return -ENOMEM;
-
-	action->handler = handler;
-	action->flags = irqflags;
-	cpus_clear(action->mask);
-	action->name = devname;
-	action->next = NULL;
-	action->dev_id = dev_id;
-
-	retval = setup_irq(irq, action);
-	if (retval)
-		kfree(action);
-	return retval;
-}
-
-/**
- *	free_irq - free an interrupt
- *	@irq: Interrupt line to free
- *	@dev_id: Device identity to free
- *
- *	Remove an interrupt handler. The handler is removed and if the
- *	interrupt line is no longer in use by any driver it is disabled.
- *	On a shared IRQ the caller must ensure the interrupt is disabled
- *	on the card it drives before calling this function. The function
- *	does not return until any executing interrupts for this IRQ
- *	have completed.
- *
- *	This function may be called from interrupt context.
- *
- *	Bugs: Attempting to free an irq in a handler for the same irq hangs
- *	      the machine.
- */
-void free_irq(unsigned int irq, void *dev_id)
-{
-	irq_desc_t *desc;
-	struct irqaction **p;
-	unsigned long flags;
-
-	if (irq >= NR_IRQS)
-		return;
-
-	desc = irq_desc + irq;
-	spin_lock_irqsave(&desc->lock,flags);
-	p = &desc->action;
-	for (;;) {
-		struct irqaction * action = *p;
-		if (action) {
-			struct irqaction **pp = p;
-			p = &action->next;
-			if (action->dev_id != dev_id)
-				continue;
-
-			/* Found it - now remove it from the list of entries */
-			*pp = action->next;
-			if (!desc->action) {
-				desc->status |= IRQ_DISABLED;
-				desc->handler->shutdown(irq);
-			}
-			spin_unlock_irqrestore(&desc->lock,flags);
-			kfree(action);
-			return;
-		}
-		printk("Trying to free free IRQ%d\n",irq);
-		spin_unlock_irqrestore(&desc->lock,flags);
-		return;
-	}
-}
-
-/*
- * IRQ autodetection code..
- *
- * This depends on the fact that any interrupt that
- * comes in on to an unassigned handler will get stuck
- * with "IRQ_WAITING" cleared and the interrupt
- * disabled.
- */
-
-/**
- *	probe_irq_on	- begin an interrupt autodetect
- *
- *	Commence probing for an interrupt. The interrupts are scanned
- *	and a mask of potential interrupt lines is returned.
- *
- */
-unsigned long probe_irq_on(void)
-{
-	unsigned int i;
-	irq_desc_t *desc;
-	unsigned long val;
-	unsigned long delay;
-
-	/*
-	 * something may have generated an irq long ago and we want to
-	 * flush such a longstanding irq before considering it as spurious.
-	 */
-	for (i = NR_IRQS-1; i >= 0; i--) {
-		desc = irq_desc + i;
-
-		spin_lock_irq(&desc->lock);
-		if (!irq_desc[i].action) {
-			irq_desc[i].handler->startup(i);
-		}
-		spin_unlock_irq(&desc->lock);
-	}
-
-	/* Wait for longstanding interrupts to trigger. */
-	for (delay = jiffies + HZ/50; time_after(delay, jiffies); )
-		/* about 20ms delay */ synchronize_irq();
-
-	/*
-	 * enable any unassigned irqs
-	 * (we must startup again here because if a longstanding irq
-	 * happened in the previous stage, it may have masked itself)
-	 */
-	for (i = NR_IRQS-1; i >= 0; i--) {
-		desc = irq_desc + 1;
-
-		spin_lock_irq(&desc->lock);
-		if (!desc->action) {
-			desc->status |= IRQ_AUTODETECT | IRQ_WAITING;
-			if (desc->handler->startup(i))
-				desc->status |= IRQ_PENDING;
-		}
-		spin_unlock_irq(&desc->lock);
-	}
-
-	/*
-	 * Wait for spurious interrupts to trigger
-	 */
-	for (delay = jiffies + HZ/10; time_after(delay, jiffies); )
-		/* about 100ms delay */ synchronize_irq();
-
-	/*
-	 * Now filter out any obviously spurious interrupts
-	 */
-	val = 0;
-	for (i = 0; i < NR_IRQS; i++) {
-		irq_desc_t *desc = irq_desc + i;
-		unsigned int status;
-
-		spin_lock_irq(&desc->lock);
-		status = desc->status;
-
-		if (status & IRQ_AUTODETECT) {
-			/* It triggered already - consider it spurious. */
-			if (!(status & IRQ_WAITING)) {
-				desc->status = status & ~IRQ_AUTODETECT;
-				desc->handler->shutdown(i);
-			} else
-				if (i < 32)
-					val |= 1 << i;
-		}
-		spin_unlock_irq(&desc->lock);
-	}
-
-	return val;
-}
-
-/*
- * Return the one interrupt that triggered (this can
- * handle any interrupt source).
- */
-
-/**
- *	probe_irq_off   - end an interrupt autodetect
- *	@val: mask of potential interrupts (unused)
- *
- *	Scans the unused interrupt lines and returns the line which
- *	appears to have triggered the interrupt. If no interrupt was
- *	found then zero is returned. If more than one interrupt is
- *	found then minus the first candidate is returned to indicate
- *	their is doubt.
- *
- *	The interrupt probe logic state is returned to its previous
- *	value.
- *
- *	BUGS: When used in a module (which arguably shouldnt happen)
- *	nothing prevents two IRQ probe callers from overlapping. The
- *	results of this are non-optimal.
- */
-int probe_irq_off(unsigned long val)
-{
-	int i, irq_found, nr_irqs;
-
-	nr_irqs = 0;
-	irq_found = 0;
-	for (i=0; i<NR_IRQS; i++) {
-		irq_desc_t *desc = irq_desc + i;
-		unsigned int status;
-
-		spin_lock_irq(&desc->lock);
-		status = desc->status;
-		if (!(status & IRQ_AUTODETECT))
-			continue;
-
-		if (status & IRQ_AUTODETECT) {
-			if (!(status & IRQ_WAITING)) {
-				if (!nr_irqs)
-					irq_found = i;
-				nr_irqs++;
-			}
-
-			desc->status = status & ~IRQ_AUTODETECT;
-			desc->handler->shutdown(i);
-		}
-		spin_unlock_irq(&desc->lock);
-	}
-
-	if (nr_irqs > 1)
-		irq_found = -irq_found;
-	return irq_found;
-}
-
-int setup_irq(unsigned int irq, struct irqaction * new)
-{
-	int shared = 0;
-	unsigned long flags;
-	struct irqaction *old, **p;
-	irq_desc_t *desc = irq_desc + irq;
-
-	/*
-	 * Some drivers like serial.c use request_irq() heavily,
-	 * so we have to be careful not to interfere with a
-	 * running system.
-	 */
-	if (new->flags & SA_SAMPLE_RANDOM) {
-		/*
-		 * This function might sleep, we want to call it first,
-		 * outside of the atomic block.
-		 * Yes, this might clear the entropy pool if the wrong
-		 * driver is attempted to be loaded, without actually
-		 * installing a new handler, but is this really a problem,
-		 * only the sysadmin is able to do this.
-		 */
-		rand_initialize_irq(irq);
-	}
-
-	/*
-	 * The following block of code has to be executed atomically
-	 */
-	spin_lock_irqsave(&desc->lock,flags);
-	p = &desc->action;
-	if ((old = *p) != NULL) {
-		/* Can't share interrupts unless both agree to */
-		if (!(old->flags & new->flags & SA_SHIRQ)) {
-			spin_unlock_irqrestore(&desc->lock,flags);
-			return -EBUSY;
-		}
-
-		/* add new interrupt at end of irq queue */
-		do {
-			p = &old->next;
-			old = *p;
-		} while (old);
-		shared = 1;
-	}
-
-	*p = new;
-
-	if (!shared) {
-		desc->depth = 0;
-		desc->status &= ~IRQ_DISABLED;
-		desc->handler->startup(irq);
-	}
-	spin_unlock_irqrestore(&desc->lock,flags);
-
-	/*
-	 * No PROC FS support for interrupts.
-	 * For improvements in this area please check
-	 * the i386 branch.
-	 */
-	return 0;
-}
-
-#if defined(CONFIG_PROC_FS) && defined(CONFIG_SYSCTL)
-
-void init_irq_proc(void)
-{
-	/*
-	 * No PROC FS support for interrupts.
-	 * For improvements in this area please check
-	 * the i386 branch.
-	 */
-}
-#endif
diff -Nru a/arch/sh64/kernel/module.c b/arch/sh64/kernel/module.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/sh64/kernel/module.c	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,161 @@
+/*  Kernel module help for sh64.
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+    Copyright 2004 SuperH (UK) Ltd
+    Author: Richard Curnow
+
+    Based on the sh version, and on code from the sh64-specific parts of
+    modutils, originally written by Richard Curnow and Ben Gaster.
+
+*/
+#include <linux/moduleloader.h>
+#include <linux/elf.h>
+#include <linux/vmalloc.h>
+#include <linux/fs.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+
+#if 0
+#define DEBUGP printk
+#else
+#define DEBUGP(fmt...)
+#endif
+
+void *module_alloc(unsigned long size)
+{
+	if (size == 0)
+		return NULL;
+	return vmalloc(size);
+}
+
+
+/* Free memory returned from module_alloc */
+void module_free(struct module *mod, void *module_region)
+{
+	vfree(module_region);
+	/* FIXME: If module_region == mod->init_region, trim exception
+           table entries. */
+}
+
+/* We don't need anything special. */
+int module_frob_arch_sections(Elf_Ehdr *hdr,
+			      Elf_Shdr *sechdrs,
+			      char *secstrings,
+			      struct module *mod)
+{
+	return 0;
+}
+
+int apply_relocate_add(Elf32_Shdr *sechdrs,
+		   const char *strtab,
+		   unsigned int symindex,
+		   unsigned int relsec,
+		   struct module *me)
+{
+	unsigned int i;
+	Elf32_Rela *rel = (void *)sechdrs[relsec].sh_addr;
+	Elf32_Sym *sym;
+	Elf32_Addr relocation;
+	uint32_t *location;
+	int align;
+	int is_shmedia;
+
+	DEBUGP("Applying relocate section %u to %u\n", relsec,
+	       sechdrs[relsec].sh_info);
+	for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
+		/* This is where to make the change */
+		location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
+			+ rel[i].r_offset;
+		/* This is the symbol it is referring to.  Note that all
+		   undefined symbols have been resolved.  */
+		sym = (Elf32_Sym *)sechdrs[symindex].sh_addr
+			+ ELF32_R_SYM(rel[i].r_info);
+		relocation = sym->st_value + rel[i].r_addend;
+		align = (int)location & 3;
+
+		/* For text addresses, bit2 of the st_other field indicates
+		 * whether the symbol is SHmedia (1) or SHcompact (0).  If
+		 * SHmedia, the LSB of the symbol needs to be asserted
+		 * for the CPU to be in SHmedia mode when it starts executing
+		 * the branch target. */
+		is_shmedia = (sym->st_other & 4) ? 1 : 0;
+		if (is_shmedia) {
+			relocation |= 1;
+		}
+
+		switch (ELF32_R_TYPE(rel[i].r_info)) {
+		case R_SH_DIR32:
+			DEBUGP("R_SH_DIR32 @%08lx = %08lx\n", (unsigned long) location, (unsigned long) relocation);
+			*location += relocation;
+			break;
+		case R_SH_REL32:
+			DEBUGP("R_SH_REL32 @%08lx = %08lx\n", (unsigned long) location, (unsigned long) relocation);
+			relocation -= (Elf32_Addr) location;
+			*location += relocation;
+			break;
+		case R_SH_IMM_LOW16:
+			DEBUGP("R_SH_IMM_LOW16 @%08lx = %08lx\n", (unsigned long) location, (unsigned long) relocation);
+			*location = (*location & ~0x3fffc00) |
+				((relocation & 0xffff) << 10);
+			break;
+		case R_SH_IMM_MEDLOW16:
+			DEBUGP("R_SH_IMM_MEDLOW16 @%08lx = %08lx\n", (unsigned long) location, (unsigned long) relocation);
+			*location = (*location & ~0x3fffc00) |
+				(((relocation >> 16) & 0xffff) << 10);
+			break;
+		case R_SH_IMM_LOW16_PCREL:
+			DEBUGP("R_SH_IMM_LOW16_PCREL @%08lx = %08lx\n", (unsigned long) location, (unsigned long) relocation);
+			relocation -= (Elf32_Addr) location;
+			*location = (*location & ~0x3fffc00) |
+				((relocation & 0xffff) << 10);
+			break;
+		case R_SH_IMM_MEDLOW16_PCREL:
+			DEBUGP("R_SH_IMM_MEDLOW16_PCREL @%08lx = %08lx\n", (unsigned long) location, (unsigned long) relocation);
+			relocation -= (Elf32_Addr) location;
+			*location = (*location & ~0x3fffc00) |
+				(((relocation >> 16) & 0xffff) << 10);
+			break;
+		default:
+			printk(KERN_ERR "module %s: Unknown relocation: %u\n",
+			       me->name, ELF32_R_TYPE(rel[i].r_info));
+			return -ENOEXEC;
+		}
+	}
+	return 0;
+}
+
+int apply_relocate(Elf32_Shdr *sechdrs,
+		       const char *strtab,
+		       unsigned int symindex,
+		       unsigned int relsec,
+		       struct module *me)
+{
+	printk(KERN_ERR "module %s: REL RELOCATION unsupported\n",
+	       me->name);
+	return -ENOEXEC;
+}
+
+int module_finalize(const Elf_Ehdr *hdr,
+		    const Elf_Shdr *sechdrs,
+		    struct module *me)
+{
+	return 0;
+}
+
+void module_arch_cleanup(struct module *mod)
+{
+}
+
diff -Nru a/arch/sh64/kernel/pci_sh5.c b/arch/sh64/kernel/pci_sh5.c
--- a/arch/sh64/kernel/pci_sh5.c	2005-03-11 12:51:52 -08:00
+++ b/arch/sh64/kernel/pci_sh5.c	2005-03-11 12:51:52 -08:00
@@ -39,7 +39,7 @@
 	 */
 	if ((d->class >> 8) != PCI_CLASS_STORAGE_IDE)
 		return;
-	printk("PCI: IDE base address fixup for %s\n", d->slot_name);
+	printk("PCI: IDE base address fixup for %s\n", pci_name(d));
 	for(i=0; i<4; i++) {
 		struct resource *r = &d->resource[i];
 		if ((r->start & ~0x80) == 0x374) {
diff -Nru a/arch/sh64/kernel/pcibios.c b/arch/sh64/kernel/pcibios.c
--- a/arch/sh64/kernel/pcibios.c	2005-03-11 12:51:47 -08:00
+++ b/arch/sh64/kernel/pcibios.c	2005-03-11 12:51:47 -08:00
@@ -57,7 +57,7 @@
 	pci_read_config_dword(dev, reg, &check);
 	if ((new ^ check) & ((new & PCI_BASE_ADDRESS_SPACE_IO) ? PCI_BASE_ADDRESS_IO_MASK : PCI_BASE_ADDRESS_MEM_MASK)) {
 		printk(KERN_ERR "PCI: Error while updating region "
-		       "%s/%d (%08x != %08x)\n", dev->slot_name, resource,
+		       "%s/%d (%08x != %08x)\n", pci_name(dev), resource,
 		       new, check);
 	}
 }
@@ -125,7 +125,7 @@
 			continue;
 		r = &dev->resource[idx];
 		if (!r->start && r->end) {
-			printk(KERN_ERR "PCI: Device %s not available because of resource collisions\n", dev->slot_name);
+			printk(KERN_ERR "PCI: Device %s not available because of resource collisions\n", pci_name(dev));
 			return -EINVAL;
 		}
 		if (r->flags & IORESOURCE_IO)
diff -Nru a/arch/sh64/kernel/process.c b/arch/sh64/kernel/process.c
--- a/arch/sh64/kernel/process.c	2005-03-11 12:51:52 -08:00
+++ b/arch/sh64/kernel/process.c	2005-03-11 12:51:52 -08:00
@@ -638,7 +638,6 @@
 int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
 {
 	/* A bit less processor dependent than older sh ... */
-
 	unsigned int reply;
 
 static __inline__ _syscall2(int,clone,unsigned long,flags,unsigned long,newsp)
@@ -671,7 +670,7 @@
 	   null it here, there is no other path through which it would get safely
 	   nulled. */
 
-#ifndef CONFIG_NOFPU_SUPPORT
+#ifdef CONFIG_SH_FPU
 	if (last_task_used_math == current) {
 		last_task_used_math = NULL;
 	}
@@ -683,7 +682,7 @@
 
 	/* Called by fs/exec.c (flush_old_exec) to remove traces of a
 	 * previously running executable. */
-#ifndef CONFIG_NOFPU_SUPPORT
+#ifdef CONFIG_SH_FPU
 	if (last_task_used_math == current) {
 		last_task_used_math = NULL;
 	}
@@ -709,7 +708,7 @@
 /* Fill in the fpu structure for a core dump.. */
 int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu)
 {
-#ifndef CONFIG_NOFPU_SUPPORT
+#ifdef CONFIG_SH_FPU
 	int fpvalid;
 	struct task_struct *tsk = current;
 
@@ -741,7 +740,7 @@
 	struct pt_regs *childregs;
 	unsigned long long se;			/* Sign extension */
 
-#ifndef CONFIG_NOFPU_SUPPORT
+#ifdef CONFIG_SH_FPU
 	if(last_task_used_math == current) {
 		grab_fpu();
 		fpsave(&current->thread.fpu.hard);
@@ -933,7 +932,7 @@
 	int len=0;
 	struct task_struct *p;
 	read_lock(&tasklist_lock);
-	for_each_task(p) {
+	for_each_process(p) {
 		int pid = p->pid;
 		struct mm_struct *mm;
 		if (!pid) continue;
@@ -942,7 +941,7 @@
 			unsigned long asid, context;
 			context = mm->context;
 			asid = (context & 0xff);
-			len += sprintf(buf+len, "%5d : %02x\n", pid, asid);
+			len += sprintf(buf+len, "%5d : %02lx\n", pid, asid);
 		} else {
 			len += sprintf(buf+len, "%5d : (none)\n", pid);
 		}
diff -Nru a/arch/sh64/kernel/ptrace.c b/arch/sh64/kernel/ptrace.c
--- a/arch/sh64/kernel/ptrace.c	2005-03-11 12:51:52 -08:00
+++ b/arch/sh64/kernel/ptrace.c	2005-03-11 12:51:52 -08:00
@@ -123,9 +123,26 @@
 asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
 {
 	struct task_struct *child;
+	extern void poke_real_address_q(unsigned long long addr, unsigned long long data);
+#define WPC_DBRMODE 0x0d104008
+	static int first_call = 1;
 	int ret;
 
 	lock_kernel();
+
+	if (first_call) {
+		/* Set WPC.DBRMODE to 0.  This makes all debug events get
+		 * delivered through RESVEC, i.e. into the handlers in entry.S.
+		 * (If the kernel was downloaded using a remote gdb, WPC.DBRMODE
+		 * would normally be left set to 1, which makes debug events get
+		 * delivered through DBRVEC, i.e. into the remote gdb's
+		 * handlers.  This prevents ptrace getting them, and confuses
+		 * the remote gdb.) */
+		printk("DBRMODE set to 0 to permit native debugging\n");
+		poke_real_address_q(WPC_DBRMODE, 0);
+		first_call = 0;
+	}
+
 	ret = -EPERM;
 	if (request == PTRACE_TRACEME) {
 		/* are we already being traced? */
diff -Nru a/arch/sh64/kernel/sh_ksyms.c b/arch/sh64/kernel/sh_ksyms.c
--- a/arch/sh64/kernel/sh_ksyms.c	2005-03-11 12:51:41 -08:00
+++ b/arch/sh64/kernel/sh_ksyms.c	2005-03-11 12:51:41 -08:00
@@ -19,6 +19,7 @@
 #include <linux/in6.h>
 #include <linux/interrupt.h>
 #include <linux/smp_lock.h>
+#include <linux/tty.h>
 
 #include <asm/semaphore.h>
 #include <asm/processor.h>
@@ -50,7 +51,6 @@
 /* Networking helper routines. */
 EXPORT_SYMBOL(csum_partial_copy);
 
-EXPORT_SYMBOL(strtok);
 EXPORT_SYMBOL(strpbrk);
 EXPORT_SYMBOL(strstr);
 
@@ -72,12 +72,18 @@
 
 EXPORT_SYMBOL(flush_dcache_page);
 
+/* For ext3 */
+EXPORT_SYMBOL(sh64_page_clear);
+
 /* Ugh.  These come in from libgcc.a at link time. */
 
 extern void __sdivsi3(void);
 extern void __muldi3(void);
 extern void __udivsi3(void);
+extern char __div_table;
 EXPORT_SYMBOL(__sdivsi3);
 EXPORT_SYMBOL(__muldi3);
 EXPORT_SYMBOL(__udivsi3);
+EXPORT_SYMBOL(__div_table);
+
 
diff -Nru a/arch/sh64/kernel/signal.c b/arch/sh64/kernel/signal.c
--- a/arch/sh64/kernel/signal.c	2005-03-11 12:51:46 -08:00
+++ b/arch/sh64/kernel/signal.c	2005-03-11 12:51:46 -08:00
@@ -178,7 +178,7 @@
 	long long retcode[2];
 };
 
-#ifndef CONFIG_NOFPU_SUPPORT
+#ifdef CONFIG_SH_FPU
 static inline int
 restore_sigcontext_fpu(struct pt_regs *regs, struct sigcontext __user *sc)
 {
@@ -634,11 +634,9 @@
  */
 
 static void
-handle_signal(unsigned long sig, siginfo_t *info, sigset_t *oldset,
-	      struct pt_regs * regs)
+handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
+		sigset_t *oldset, struct pt_regs * regs)
 {
-	struct k_sigaction *ka = &current->sighand->action[sig-1];
-
 	/* Are we from a system call? */
 	if (regs->syscall_nr >= 0) {
 		/* If so, check system call restarting.. */
@@ -666,9 +664,6 @@
 	else
 		setup_frame(sig, ka, oldset, regs);
 
-	if (ka->sa.sa_flags & SA_ONESHOT)
-		ka->sa.sa_handler = SIG_DFL;
-
 	if (!(ka->sa.sa_flags & SA_NODEFER)) {
 		spin_lock_irq(&current->sighand->siglock);
 		sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
@@ -691,6 +686,7 @@
 {
 	siginfo_t info;
 	int signr;
+	struct k_sigaction ka;
 
 	/*
 	 * We want the common case to go fast, which
@@ -707,11 +703,11 @@
 	if (!oldset)
 		oldset = &current->blocked;
 
-	signr = get_signal_to_deliver(&info, regs, 0);
+	signr = get_signal_to_deliver(&info, &ka, regs, 0);
 
 	if (signr > 0) {
 		/* Whee!  Actually deliver the signal.  */
-		handle_signal(signr, &info, oldset, regs);
+		handle_signal(signr, &info, &ka, oldset, regs);
 		return 1;
 	}
 
diff -Nru a/arch/sh64/kernel/switchto.S b/arch/sh64/kernel/switchto.S
--- a/arch/sh64/kernel/switchto.S	2005-03-11 12:51:42 -08:00
+++ b/arch/sh64/kernel/switchto.S	2005-03-11 12:51:42 -08:00
@@ -27,7 +27,7 @@
    r5 - &next->thread
 
    Outgoing results
-   r2 - last (=prev)
+   r2 - last (=prev) : this just stays in r2 throughout
 
    Want to create a full (struct pt_regs) on the stack to allow backtracing
    functions to work.  However, we only need to populate the callee-save
@@ -188,7 +188,6 @@
 	! epilogue
 	ld.l	r15, 0, r18
 	ld.l	r15, 4, r14
-	ori	r4, 0, r2	! last = prev
 	ptabs	r18, tr0
 	movi	FRAME_SIZE, r0
 	add	r15, r0, r15
diff -Nru a/arch/sh64/kernel/sys_sh64.c b/arch/sh64/kernel/sys_sh64.c
--- a/arch/sh64/kernel/sys_sh64.c	2005-03-11 12:51:52 -08:00
+++ b/arch/sh64/kernel/sys_sh64.c	2005-03-11 12:51:52 -08:00
@@ -284,3 +284,17 @@
 	return err?-EFAULT:0;
 }
 
+/* Copy from mips version */
+asmlinkage long sys_shmatcall(int shmid, char __user *shmaddr,
+		int shmflg)
+{
+	unsigned long raddr;
+	int err;
+
+	err = do_shmat(shmid, shmaddr, shmflg, &raddr);
+	if (err)
+		return err;
+
+	err = raddr;
+	return err;
+}
diff -Nru a/arch/sh64/kernel/syscalls.S b/arch/sh64/kernel/syscalls.S
--- a/arch/sh64/kernel/syscalls.S	2005-03-11 12:51:47 -08:00
+++ b/arch/sh64/kernel/syscalls.S	2005-03-11 12:51:47 -08:00
@@ -268,7 +268,7 @@
 	.long sys_msgrcv
 	.long sys_msgget
 	.long sys_msgctl
-	.long sys_ni_syscall /* sys_shmatcall */
+	.long sys_shmatcall
 	.long sys_shmdt			/* 245 */
 	.long sys_shmget
 	.long sys_shmctl
@@ -337,4 +337,9 @@
 	.long sys_mq_timedreceive
 	.long sys_mq_notify
 	.long sys_mq_getsetattr		/* 310 */
+	.long sys_ni_syscall	/* Reserved for kexec */
+	.long sys_waitid
+	.long sys_add_key
+	.long sys_request_key
+	.long sys_keyctl		/* 315 */
 
diff -Nru a/arch/sh64/kernel/time.c b/arch/sh64/kernel/time.c
--- a/arch/sh64/kernel/time.c	2005-03-11 12:51:46 -08:00
+++ b/arch/sh64/kernel/time.c	2005-03-11 12:51:46 -08:00
@@ -45,6 +45,7 @@
 #define TMU_TOCR_INIT	0x00
 #define TMU0_TCR_INIT	0x0020
 #define TMU_TSTR_INIT	1
+#define TMU_TSTR_OFF	0
 
 /* RCR1 Bits */
 #define RCR1_CF		0x80	/* Carry Flag             */
@@ -424,7 +425,7 @@
 	*/
 	register unsigned long long  __rtc_irq_flag __asm__ ("r3");
 
-	sti();
+	local_irq_enable();
 	do {} while (ctrl_inb(R64CNT) != 0);
 	ctrl_outb(RCR1_CIE, RCR1); /* Enable carry interrupt */
 
@@ -443,7 +444,7 @@
 		     "getcon	" __CTC ", %0\n\t"
 		: "=r"(ctc_val), "=r" (__dummy), "=r" (__rtc_irq_flag)
 		: "0" (0));
-	cli();
+	local_irq_disable();
 	/*
 	 * SH-3:
 	 * CPU clock = 4 stages * loop
@@ -561,6 +562,7 @@
 	current_cpu_data.module_clock = module_clock;
 
 	/* Start TMU0 */
+	ctrl_outb(TMU_TSTR_OFF, TMU_TSTR);
 	ctrl_outb(TMU_TOCR_INIT, TMU_TOCR);
 	ctrl_outw(TMU0_TCR_INIT, TMU0_TCR);
 	ctrl_outl(interval, TMU0_TCOR);
diff -Nru a/arch/sh64/kernel/traps.c b/arch/sh64/kernel/traps.c
--- a/arch/sh64/kernel/traps.c	2005-03-11 12:51:51 -08:00
+++ b/arch/sh64/kernel/traps.c	2005-03-11 12:51:51 -08:00
@@ -30,6 +30,7 @@
 #include <linux/kallsyms.h>
 #include <linux/interrupt.h>
 #include <linux/sysctl.h>
+#include <linux/module.h>
 
 #include <asm/system.h>
 #include <asm/uaccess.h>
@@ -286,6 +287,8 @@
 {
 	show_task(NULL);
 }
+/* Needed by any user of WARN_ON in view of the defn in include/asm-sh/bug.h */
+EXPORT_SYMBOL(dump_stack);
 
 static void do_unhandled_exception(int trapnr, int signr, char *str, char *fn_name,
 		unsigned long error_code, struct pt_regs *regs, struct task_struct *tsk)
diff -Nru a/arch/sh64/lib/Makefile b/arch/sh64/lib/Makefile
--- a/arch/sh64/lib/Makefile	2005-03-11 12:51:51 -08:00
+++ b/arch/sh64/lib/Makefile	2005-03-11 12:51:51 -08:00
@@ -15,5 +15,5 @@
 
 # Panic should really be compiled as PIC
 lib-y  := udelay.o c-checksum.o dbg.o io.o panic.o memcpy.o copy_user_memcpy.o \
-		page_copy.o page_clear.o
+		page_copy.o page_clear.o iomap.o
 
diff -Nru a/arch/sh64/lib/copy_user_memcpy.S b/arch/sh64/lib/copy_user_memcpy.S
--- a/arch/sh64/lib/copy_user_memcpy.S	2005-03-11 12:51:40 -08:00
+++ b/arch/sh64/lib/copy_user_memcpy.S	2005-03-11 12:51:40 -08:00
@@ -46,6 +46,11 @@
 
 */
 
+/* NOTE : Prefetches removed and allocos guarded by synco to avoid TAKum03020
+ * erratum.  The first two prefetches are nop-ed out to avoid upsetting the
+ * instruction counts used in the jump address calculation.
+ * */
+
 	.section .text..SHmedia32,"ax"
 	.little
 	.balign 32
@@ -58,7 +63,7 @@
 #define LDUAL(P,O,D0,D1) ldlo.l P,O,D0; ldhi.l P,O+3,D1
 #define STUAL(P,O,D0,D1) stlo.l P,O,D0; sthi.l P,O+3,D1
 
-	ld.b r3,0,r63
+	nop ! ld.b r3,0,r63 ! TAKum03020
 	pta/l Large,tr0
 	movi 25,r0
 	bgeu/u r4,r0,tr0
@@ -108,7 +113,7 @@
 
 	/* 2 or 3 byte memcpy */
 	ld.b r3,0,r0
-	ld.b r2,0,r63
+	nop ! ld.b r2,0,r63 ! TAKum03020
 	ld.b r3,1,r1
 	st.b r2,0,r0
 	pta/l L2_3,tr0
@@ -151,7 +156,7 @@
 	blink tr1,r63
 
 Large:
-	ld.b r2, 0, r63
+	! ld.b r2, 0, r63 ! TAKum03020
 	pta/l  Loop_ua, tr1
 	ori r3, -8, r7
 	sub r2, r7, r22
@@ -173,8 +178,7 @@
 	addi r6, -8, r21
 
 Loop_line:
-	ldx.q r22, r36, r63
-	synco
+	! ldx.q r22, r36, r63 ! TAKum03020
 	alloco r22, 32
 	synco
 	addi r22, 32, r22
diff -Nru a/arch/sh64/lib/dbg.c b/arch/sh64/lib/dbg.c
--- a/arch/sh64/lib/dbg.c	2005-03-11 12:51:52 -08:00
+++ b/arch/sh64/lib/dbg.c	2005-03-11 12:51:52 -08:00
@@ -8,6 +8,7 @@
 -- Copyright 2004 Richard Curnow (evt_debug etc)
 --
 --------------------------------------------------------------------------*/
+#include <linux/config.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
@@ -136,6 +137,8 @@
 
 /* ======================================================================= */
 
+#ifdef CONFIG_POOR_MANS_STRACE
+
 #include "syscalltab.h"
 
 struct ring_node {
@@ -151,6 +154,17 @@
 static struct ring_node event_ring[16];
 static int event_ptr = 0;
 
+struct stored_syscall_data {
+	int pid;
+	int syscall_number;
+};
+
+#define N_STORED_SYSCALLS 16
+
+static struct stored_syscall_data stored_syscalls[N_STORED_SYSCALLS];
+static int syscall_next=0;
+static int syscall_next_print=0;
+
 void evt_debug(int evt, int ret_addr, int event, int tra, struct pt_regs *regs)
 {
 	int syscallno = tra & 0xff;
@@ -187,15 +201,35 @@
 	event_ptr = (event_ptr + 1) & 15;
 
 	if ((event == 2) && (evt == 0x160)) {
-		if (syscallno < NUM_SYSCALL_INFO_ENTRIES)
-			printk("Task %d: %s()\n",
-			       current->pid,
-			       syscall_info_table[syscallno].name);
+		if (syscallno < NUM_SYSCALL_INFO_ENTRIES) {
+			/* Store the syscall information to print later.  We
+			 * can't print this now - currently we're running with
+			 * SR.BL=1, so we can't take a tlbmiss (which could occur
+			 * in the console drivers under printk).
+			 *
+			 * Just overwrite old entries on ring overflow - this
+			 * is only for last-hope debugging. */
+			stored_syscalls[syscall_next].pid = current->pid;
+			stored_syscalls[syscall_next].syscall_number = syscallno;
+			syscall_next++;
+			syscall_next &= (N_STORED_SYSCALLS - 1);
+		}
+	}
+}
+
+static void drain_syscalls(void) {
+	while (syscall_next_print != syscall_next) {
+		printk("Task %d: %s()\n",
+			stored_syscalls[syscall_next_print].pid,
+			syscall_info_table[stored_syscalls[syscall_next_print].syscall_number].name);
+			syscall_next_print++;
+			syscall_next_print &= (N_STORED_SYSCALLS - 1);
 	}
 }
 
 void evt_debug2(unsigned int ret)
 {
+	drain_syscalls();
 	printk("Task %d: syscall returns %08x\n", current->pid, ret);
 }
 
@@ -230,6 +264,8 @@
 	rr->pc = regs->pc;
 	event_ptr = (event_ptr + 1) & 15;
 }
+
+#endif /* CONFIG_POOR_MANS_STRACE */
 
 /* ======================================================================= */
 
diff -Nru a/arch/sh64/lib/io.c b/arch/sh64/lib/io.c
--- a/arch/sh64/lib/io.c	2005-03-11 12:51:41 -08:00
+++ b/arch/sh64/lib/io.c	2005-03-11 12:51:41 -08:00
@@ -9,14 +9,12 @@
  */
 
 #include <linux/config.h>
+#include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/delay.h>
 #include <asm/system.h>
 #include <asm/processor.h>
 #include <asm/io.h>
-#ifdef CONFIG_SH_CAYMAN
-#include <asm/cayman.h>
-#endif
 
 /*
  * readX/writeX() are used to access memory mapped devices. On some
@@ -25,71 +23,6 @@
  * memory location directly.
  */
 
-#define dprintk(x...)
-
-static int io_addr(int x) {
-	if (x < 0x400) {
-#ifdef CONFIG_SH_CAYMAN
-		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
-		panic ("Illegal access to I/O port 0x%04x\n", x);
-		return 0;
-#endif
-	}
-}
-
-unsigned long inb(unsigned long port)
-{
-	unsigned long r;
-
-	r = ctrl_inb(io_addr(port));
-	dprintk("inb(0x%x)=0x%x (0x%x)\n", port, r, io_addr(port));
-	return r;
-}
-
-unsigned long inw(unsigned long port)
-{
-	unsigned long r;
-
-	r = ctrl_inw(io_addr(port));
-	dprintk("inw(0x%x)=0x%x (0x%x)\n", port, r, io_addr(port));
-	return r;
-}
-
-unsigned long inl(unsigned long port)
-{
-	unsigned long r;
-
-	r = ctrl_inl(io_addr(port));
-	dprintk("inl(0x%x)=0x%x (0x%x)\n", port, r, io_addr(port));
-	return r;
-}
-
-void outb(unsigned long value, unsigned long port)
-{
-	dprintk("outb(0x%x,0x%x) (0x%x)\n", value, port, io_addr(port));
-	ctrl_outb(value, io_addr(port));
-}
-
-void outw(unsigned long value, unsigned long port)
-{
-	dprintk("outw(0x%x,0x%x) (0x%x)\n", value, port, io_addr(port));
-	ctrl_outw(value, io_addr(port));
-}
-
-void outl(unsigned long value, unsigned long port)
-{
-	dprintk("outw(0x%x,0x%x) (0x%x)\n", value, port, io_addr(port));
-	ctrl_outl(value, io_addr(port));
-}
-
 /* This is horrible at the moment - needs more work to do something sensible */
 #define IO_DELAY()
 
@@ -185,7 +118,7 @@
 	}
 }
 
-void memcpy_toio(unsigned long to, const void *from, long count)
+void memcpy_toio(void __iomem *to, const void *from, long count)
 {
 	unsigned char *p = (unsigned char *) from;
 
@@ -195,7 +128,7 @@
 	}
 }
 
-void memcpy_fromio(void *to, unsigned long from, long count)
+void memcpy_fromio(void *to, void __iomem *from, long count)
 {
 	int i;
 	unsigned char *p = (unsigned char *) to;
diff -Nru a/arch/sh64/lib/iomap.c b/arch/sh64/lib/iomap.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/sh64/lib/iomap.c	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,55 @@
+/*
+ * arch/sh64/lib/iomap.c
+ *
+ * Generic sh64 iomap interface
+ *
+ * Copyright (C) 2004  Paul Mundt
+ *
+ * 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/config.h>
+#include <linux/pci.h>
+#include <asm/io.h>
+
+void __iomem *__attribute__ ((weak))
+ioport_map(unsigned long port, unsigned int len)
+{
+	return (void __iomem *)port;
+}
+
+void ioport_unmap(void __iomem *addr)
+{
+	/* Nothing .. */
+}
+
+void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long max)
+{
+	unsigned long start = pci_resource_start(dev, bar);
+	unsigned long len = pci_resource_len(dev, bar);
+	unsigned long flags = pci_resource_flags(dev, bar);
+
+	if (!len)
+		return NULL;
+	if (max && len > max)
+		len = max;
+	if (flags & IORESOURCE_IO)
+		return ioport_map(start + pciio_virt, len);
+	if (flags & IORESOURCE_MEM)
+		return (void __iomem *)start;
+
+	/* What? */
+	return NULL;
+}
+
+void pci_iounmap(struct pci_dev *dev, void __iomem *addr)
+{
+	/* Nothing .. */
+}
+
+EXPORT_SYMBOL(ioport_map);
+EXPORT_SYMBOL(ioport_unmap);
+EXPORT_SYMBOL(pci_iomap);
+EXPORT_SYMBOL(pci_iounmap);
+
diff -Nru a/arch/sh64/lib/old-checksum.c b/arch/sh64/lib/old-checksum.c
--- a/arch/sh64/lib/old-checksum.c	2005-03-11 12:51:42 -08:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,17 +0,0 @@
-/*
- * FIXME: old compatibility stuff, will be removed soon.
- */
-
-#include <net/checksum.h>
-
-unsigned int csum_partial_copy( const char *src, char *dst, int len, int sum)
-{
-	int src_err=0, dst_err=0;
-
-	sum = csum_partial_copy_generic ( src, dst, len, sum, &src_err, &dst_err);
-
-	if (src_err || dst_err)
-		printk("old csum_partial_copy_fromuser(), tell mingo to convert me.\n");
-
-	return sum;
-}
diff -Nru a/arch/sh64/lib/page_clear.S b/arch/sh64/lib/page_clear.S
--- a/arch/sh64/lib/page_clear.S	2005-03-11 12:51:47 -08:00
+++ b/arch/sh64/lib/page_clear.S	2005-03-11 12:51:47 -08:00
@@ -17,6 +17,8 @@
 
    Always clears 4096 bytes.
 
+   Note : alloco guarded by synco to avoid TAKum03020 erratum
+
 */
 
 	.section .text..SHmedia32,"ax"
@@ -34,6 +36,7 @@
 	add  r2, r63, r6
 1:
 	alloco r6, 0
+	synco	! TAKum03020
 	addi	r6, 32, r6
 	bgt/l	r7, r6, tr1
 
diff -Nru a/arch/sh64/lib/page_copy.S b/arch/sh64/lib/page_copy.S
--- a/arch/sh64/lib/page_copy.S	2005-03-11 12:51:47 -08:00
+++ b/arch/sh64/lib/page_copy.S	2005-03-11 12:51:47 -08:00
@@ -39,12 +39,17 @@
 	pta 3f, tr3
 	ptabs r18, tr0
 
+#if 0
+	/* TAKum03020 */
 	ld.q r2, 0x00, r63
 	ld.q r2, 0x20, r63
 	ld.q r2, 0x40, r63
 	ld.q r2, 0x60, r63
+#endif
 	alloco r3, 0x00
+	synco		! TAKum03020
 	alloco r3, 0x20
+	synco		! TAKum03020
 
 	movi 3968, r6
 	add  r3, r6, r6
@@ -60,11 +65,15 @@
    because they overlap with the time spent waiting for prefetches to
    complete. */
 1:
+#if 0
+	/* TAKum03020 */
 	bge/u r3, r6, tr2  ! skip prefetch for last 4 lines
 	ldx.q r3, r22, r63 ! prefetch 4 lines hence
+#endif
 2:
 	bge/u r3, r7, tr3  ! skip alloco for last 2 lines
 	alloco r3, 0x40    ! alloc destination line 2 lines ahead
+	synco		! TAKum03020
 3:
 	ldx.q r3, r60, r36
 	ldx.q r3, r61, r37
diff -Nru a/arch/sh64/mach-cayman/Makefile b/arch/sh64/mach-cayman/Makefile
--- a/arch/sh64/mach-cayman/Makefile	2005-03-11 12:51:51 -08:00
+++ b/arch/sh64/mach-cayman/Makefile	2005-03-11 12:51:51 -08:00
@@ -6,6 +6,6 @@
 # unless it's something special (ie not a .c file).
 #
 
-obj-y := setup.o irq.o
+obj-y := setup.o irq.o iomap.o
 obj-$(CONFIG_HEARTBEAT)	+= led.o
 
diff -Nru a/arch/sh64/mach-cayman/iomap.c b/arch/sh64/mach-cayman/iomap.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/sh64/mach-cayman/iomap.c	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,24 @@
+/*
+ * arch/sh64/mach-cayman/iomap.c
+ *
+ * Cayman iomap interface
+ *
+ * Copyright (C) 2004  Paul Mundt
+ *
+ * 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/config.h>
+#include <linux/pci.h>
+#include <asm/io.h>
+#include <asm/cayman.h>
+
+void __iomem *ioport_map(unsigned long port, unsigned int len)
+{
+	if (port < 0x400)
+		return (void __iomem *)((port << 2) | smsc_superio_virt);
+
+	return (void __iomem *)port;
+}
+
diff -Nru a/arch/sh64/mach-cayman/irq.c b/arch/sh64/mach-cayman/irq.c
--- a/arch/sh64/mach-cayman/irq.c	2005-03-11 12:51:52 -08:00
+++ b/arch/sh64/mach-cayman/irq.c	2005-03-11 12:51:52 -08:00
@@ -64,11 +64,11 @@
 	irq -= START_EXT_IRQS;
 	reg = EPLD_MASK_BASE + ((irq / 8) << 2);
 	bit = 1<<(irq % 8);
-	save_and_cli(flags);
+	local_irq_save(flags);
 	mask = ctrl_inl(reg);
 	mask |= bit;
 	ctrl_outl(mask, reg);
-	restore_flags(flags);
+	local_irq_restore(flags);
 }
 
 void disable_cayman_irq(unsigned int irq)
@@ -81,11 +81,11 @@
 	irq -= START_EXT_IRQS;
 	reg = EPLD_MASK_BASE + ((irq / 8) << 2);
 	bit = 1<<(irq % 8);
-	save_and_cli(flags);
+	local_irq_save(flags);
 	mask = ctrl_inl(reg);
 	mask &= ~bit;
 	ctrl_outl(mask, reg);
-	restore_flags(flags);
+	local_irq_restore(flags);
 }
 
 static void ack_cayman_irq(unsigned int irq)
diff -Nru a/arch/sh64/mach-cayman/setup.c b/arch/sh64/mach-cayman/setup.c
--- a/arch/sh64/mach-cayman/setup.c	2005-03-11 12:51:50 -08:00
+++ b/arch/sh64/mach-cayman/setup.c	2005-03-11 12:51:50 -08:00
@@ -33,8 +33,6 @@
 #include <asm/irq.h>
 #include <asm/page.h>
 
-#define RES_COUNT(res) ((sizeof((res))/sizeof(struct resource)))
-
 /*
  * Platform Dependent Interrupt Priorities.
  */
@@ -86,10 +84,14 @@
 #define SMSC_DEVICE_ID_INDEX	0x20
 #define SMSC_DEVICE_REV_INDEX	0x21
 #define SMSC_ACTIVATE_INDEX	0x30
+#define SMSC_PRIMARY_BASE_INDEX  0x60
+#define SMSC_SECONDARY_BASE_INDEX 0x62
 #define SMSC_PRIMARY_INT_INDEX	0x70
 #define SMSC_SECONDARY_INT_INDEX 0x72
 
-#define SMSC_KEYBOARD_DEVICE 7
+#define SMSC_IDE1_DEVICE	1
+#define SMSC_KEYBOARD_DEVICE	7
+#define SMSC_CONFIG_REGISTERS	8
 
 #define SMSC_SUPERIO_READ_INDEXED(index) ({ \
 	outb((index), SMSC_INDEX_PORT_ADDR); \
@@ -98,6 +100,9 @@
 	outb((index), SMSC_INDEX_PORT_ADDR); \
 	outb((val),   SMSC_DATA_PORT_ADDR); })
 
+#define IDE1_PRIMARY_BASE	0x01f0
+#define IDE1_SECONDARY_BASE	0x03f6
+
 unsigned long smsc_superio_virt;
 
 /*
@@ -125,13 +130,13 @@
 	.initial_root_dev =	0x0100,
 	.loader_type =		1,
 	.io_res_p =		io_resources,
-	.io_res_count =		RES_COUNT(io_resources),
+	.io_res_count =		ARRAY_SIZE(io_resources),
 	.kram_res_p =		kram_resources,
-	.kram_res_count =	RES_COUNT(kram_resources),
+	.kram_res_count =	ARRAY_SIZE(kram_resources),
 	.xram_res_p =		xram_resources,
-	.xram_res_count =	RES_COUNT(xram_resources),
+	.xram_res_count =	ARRAY_SIZE(xram_resources),
 	.rom_res_p =		rom_resources,
-	.rom_res_count =	RES_COUNT(rom_resources),
+	.rom_res_count =	ARRAY_SIZE(rom_resources),
 };
 
 int platform_int_priority[NR_INTC_IRQS] = {
@@ -174,6 +179,38 @@
 	/* On a PC keyboard is IRQ1, mouse is IRQ12 */
 	SMSC_SUPERIO_WRITE_INDEXED(1, SMSC_PRIMARY_INT_INDEX);
 	SMSC_SUPERIO_WRITE_INDEXED(12, SMSC_SECONDARY_INT_INDEX);
+
+#ifdef CONFIG_IDE
+	/*
+	 * Only IDE1 exists on the Cayman
+	 */
+
+	/* Power it on */
+	SMSC_SUPERIO_WRITE_INDEXED(1 << SMSC_IDE1_DEVICE, 0x22);
+
+	SMSC_SUPERIO_WRITE_INDEXED(SMSC_IDE1_DEVICE, SMCS_LOGICAL_DEV_INDEX);
+	SMSC_SUPERIO_WRITE_INDEXED(1, SMSC_ACTIVATE_INDEX);
+
+	SMSC_SUPERIO_WRITE_INDEXED(IDE1_PRIMARY_BASE >> 8,
+				   SMSC_PRIMARY_BASE_INDEX + 0);
+	SMSC_SUPERIO_WRITE_INDEXED(IDE1_PRIMARY_BASE & 0xff,
+				   SMSC_PRIMARY_BASE_INDEX + 1);
+
+	SMSC_SUPERIO_WRITE_INDEXED(IDE1_SECONDARY_BASE >> 8,
+				   SMSC_SECONDARY_BASE_INDEX + 0);
+	SMSC_SUPERIO_WRITE_INDEXED(IDE1_SECONDARY_BASE & 0xff,
+				   SMSC_SECONDARY_BASE_INDEX + 1);
+
+	SMSC_SUPERIO_WRITE_INDEXED(14, SMSC_PRIMARY_INT_INDEX);
+
+	SMSC_SUPERIO_WRITE_INDEXED(SMSC_CONFIG_REGISTERS,
+				   SMCS_LOGICAL_DEV_INDEX);
+
+	SMSC_SUPERIO_WRITE_INDEXED(0x00, 0xc2); /* GP42 = nIDE1_OE */
+	SMSC_SUPERIO_WRITE_INDEXED(0x01, 0xc5); /* GP45 = IDE1_IRQ */
+	SMSC_SUPERIO_WRITE_INDEXED(0x00, 0xc6); /* GP46 = nIOROP */
+	SMSC_SUPERIO_WRITE_INDEXED(0x00, 0xc7); /* GP47 = nIOWOP */
+#endif
 
 	/* Exit the configuraton state */
 	outb(SMSC_EXIT_CONFIG_KEY, SMSC_CONFIG_PORT_ADDR);
diff -Nru a/arch/sh64/mm/cache.c b/arch/sh64/mm/cache.c
--- a/arch/sh64/mm/cache.c	2005-03-11 12:51:52 -08:00
+++ b/arch/sh64/mm/cache.c	2005-03-11 12:51:52 -08:00
@@ -114,6 +114,16 @@
 	return 0;
 }
 
+#ifdef CONFIG_DCACHE_DISABLED
+#define sh64_dcache_purge_all()					do { } while (0)
+#define sh64_dcache_purge_coloured_phy_page(paddr, eaddr)	do { } while (0)
+#define sh64_dcache_purge_user_range(mm, start, end)		do { } while (0)
+#define sh64_dcache_purge_phy_page(paddr)			do { } while (0)
+#define sh64_dcache_purge_virt_page(mm, eaddr)			do { } while (0)
+#define sh64_dcache_purge_kernel_range(start, end)		do { } while (0)
+#define sh64_dcache_wback_current_user_range(start, end)	do { } while (0)
+#endif
+
 /*##########################################################################*/
 
 /* From here onwards, a rewrite of the implementation,
@@ -436,6 +446,7 @@
 		eaddr1 = eaddr0 + cpu_data->dcache.way_ofs * cpu_data->dcache.ways;
 		for (eaddr=eaddr0; eaddr<eaddr1; eaddr+=cpu_data->dcache.way_ofs) {
 			asm __volatile__ ("alloco %0, 0" : : "r" (eaddr));
+			asm __volatile__ ("synco"); /* TAKum03020 */
 		}
 
 		eaddr1 = eaddr0 + cpu_data->dcache.way_ofs * cpu_data->dcache.ways;
@@ -573,31 +584,6 @@
 	}
 }
 
-static void sh64_dcache_purge_virt_page(struct mm_struct *mm, unsigned long eaddr)
-{
-	unsigned long phys;
-	pgd_t *pgd;
-	pmd_t *pmd;
-	pte_t *pte;
-	pte_t entry;
-
-	pgd = pgd_offset(mm, eaddr);
-	pmd = pmd_offset(pgd, eaddr);
-
-	if (pmd_none(*pmd) || pmd_bad(*pmd))
-		return;
-
-	pte = pte_offset_kernel(pmd, eaddr);
-	entry = *pte;
-
-	if (pte_none(entry) || !pte_present(entry))
-		return;
-
-	phys = pte_val(entry) & PAGE_MASK;
-
-	sh64_dcache_purge_phy_page(phys);
-}
-
 static void sh64_dcache_purge_user_page(struct mm_struct *mm, unsigned long eaddr)
 {
 	pgd_t *pgd;
@@ -766,8 +752,6 @@
 	}
 }
 
-#endif /* !CONFIG_DCACHE_DISABLED */
-
 /****************************************************************************/
 
 /* These *MUST* lie in an area of virtual address space that's otherwise unused. */
@@ -830,6 +814,8 @@
 	sh64_teardown_dtlb_cache_slot();
 }
 
+#endif /* !CONFIG_DCACHE_DISABLED */
+
 /****************************************************************************/
 
 /*##########################################################################
@@ -904,7 +890,7 @@
 
 /****************************************************************************/
 
-void flush_cache_page(struct vm_area_struct *vma, unsigned long eaddr)
+void flush_cache_page(struct vm_area_struct *vma, unsigned long eaddr, unsigned long pfn)
 {
 	/* Invalidate any entries in either cache for the vma within the user
 	   address space vma->vm_mm for the page starting at virtual address
@@ -915,7 +901,7 @@
 	   Note(1), this is called with mm->page_table_lock held.
 	   */
 
-	sh64_dcache_purge_virt_page(vma->vm_mm, eaddr);
+	sh64_dcache_purge_phy_page(pfn << PAGE_SHIFT);
 
 	if (vma->vm_flags & VM_EXEC) {
 		sh64_icache_inv_user_page(vma, eaddr);
diff -Nru a/arch/sh64/mm/extable.c b/arch/sh64/mm/extable.c
--- a/arch/sh64/mm/extable.c	2005-03-11 12:51:46 -08:00
+++ b/arch/sh64/mm/extable.c	2005-03-11 12:51:46 -08:00
@@ -15,7 +15,8 @@
 #include <linux/module.h>
 #include <asm/uaccess.h>
 
-extern unsigned long copy_user_memcpy, copy_user_memcpy_end, __copy_user_fixup;
+extern unsigned long copy_user_memcpy, copy_user_memcpy_end;
+extern void __copy_user_fixup(void);
 
 static const struct exception_table_entry __copy_user_fixup_ex = {
 	.fixup = (unsigned long)&__copy_user_fixup,
diff -Nru a/arch/sh64/mm/fault.c b/arch/sh64/mm/fault.c
--- a/arch/sh64/mm/fault.c	2005-03-11 12:51:46 -08:00
+++ b/arch/sh64/mm/fault.c	2005-03-11 12:51:46 -08:00
@@ -148,7 +148,7 @@
 	mm = tsk->mm;
 
 	/* Not an IO address, so reenable interrupts */
-	sti();
+	local_irq_enable();
 
 	/*
 	 * If we're in an interrupt or have no user
@@ -203,17 +203,17 @@
  * we can handle it..
  */
 good_area:
-	if (writeaccess) {
-		if (!(vma->vm_flags & VM_WRITE))
-			goto bad_area;
-	} else {
-		if (!(vma->vm_flags & (VM_READ | VM_EXEC)))
-			goto bad_area;
-	}
-
 	if (textaccess) {
 		if (!(vma->vm_flags & VM_EXEC))
 			goto bad_area;
+	} else {
+		if (writeaccess) {
+			if (!(vma->vm_flags & VM_WRITE))
+				goto bad_area;
+		} else {
+			if (!(vma->vm_flags & VM_READ))
+				goto bad_area;
+		}
 	}
 
 	/*
@@ -264,17 +264,28 @@
 	up_read(&mm->mmap_sem);
 
 	if (user_mode(regs)) {
-		printk("user mode bad_area address=%08lx pid=%d (%s) pc=%08lx opcode=%08lx\n",
-			address, current->pid, current->comm,
-			(unsigned long) regs->pc,
-			*(unsigned long *)(u32)(regs->pc & ~3));
-		show_regs(regs);
+		static int count=0;
+		siginfo_t info;
+		if (count < 4) {
+			/* This is really to help debug faults when starting
+			 * usermode, so only need a few */
+			count++;
+			printk("user mode bad_area address=%08lx pid=%d (%s) pc=%08lx\n",
+				address, current->pid, current->comm,
+				(unsigned long) regs->pc);
+#if 0
+			show_regs(regs);
+#endif
+		}
 		if (tsk->pid == 1) {
 			panic("INIT had user mode bad_area\n");
 		}
 		tsk->thread.address = address;
 		tsk->thread.error_code = writeaccess;
-		force_sig(SIGSEGV, tsk);
+		info.si_signo = SIGSEGV;
+		info.si_errno = 0;
+		info.si_addr = (void *) address;
+		force_sig_info(SIGSEGV, &info, tsk);
 		return;
 	}
 
diff -Nru a/arch/sh64/mm/hugetlbpage.c b/arch/sh64/mm/hugetlbpage.c
--- a/arch/sh64/mm/hugetlbpage.c	2005-03-11 12:51:42 -08:00
+++ b/arch/sh64/mm/hugetlbpage.c	2005-03-11 12:51:42 -08:00
@@ -202,7 +202,7 @@
 		page = pte_page(*pte);
 		put_page(page);
 		for (i = 0; i < (1 << HUGETLB_PAGE_ORDER); i++) {
-			pte_clear(pte);
+			pte_clear(mm, address+(i*PAGE_SIZE), pte);
 			pte++;
 		}
 	}
diff -Nru a/arch/sh64/mm/ioremap.c b/arch/sh64/mm/ioremap.c
--- a/arch/sh64/mm/ioremap.c	2005-03-11 12:51:47 -08:00
+++ b/arch/sh64/mm/ioremap.c	2005-03-11 12:51:47 -08:00
@@ -182,8 +182,8 @@
 }
 
 static struct resource shmedia_iomap = {
-        .name	= "shmedia_iomap",
-	.start	= IOBASE_VADDR,
+	.name	= "shmedia_iomap",
+	.start	= IOBASE_VADDR + PAGE_SIZE,
 	.end	= IOBASE_END - 1,
 };
 
@@ -400,7 +400,7 @@
 		return;
 
 	clear_page((void *)ptep);
-	pte_clear(ptep);
+	pte_clear(&init_mm, vaddr, ptep);
 }
 
 unsigned long onchip_remap(unsigned long phys, unsigned long size, const char *name)
diff -Nru a/arch/sh64/mm/tlbmiss.c b/arch/sh64/mm/tlbmiss.c
--- a/arch/sh64/mm/tlbmiss.c	2005-03-11 12:51:41 -08:00
+++ b/arch/sh64/mm/tlbmiss.c	2005-03-11 12:51:41 -08:00
@@ -75,7 +75,6 @@
 
 	/* Set PTEL register, set_pte has performed the sign extension */
 	ptel &= _PAGE_FLAGS_HARDWARE_MASK; /* drop software flags */
-	ptel |= _PAGE_FLAGS_HARDWARE_DEFAULT; /* add default flags */
 
 	tlbp = is_text_not_data ? &(cpu_data->itlb) : &(cpu_data->dtlb);
 	next = tlbp->next;
diff -Nru a/arch/sh64/oprofile/op_model_null.c b/arch/sh64/oprofile/op_model_null.c
--- a/arch/sh64/oprofile/op_model_null.c	2005-03-11 12:51:47 -08:00
+++ b/arch/sh64/oprofile/op_model_null.c	2005-03-11 12:51:47 -08:00
@@ -12,7 +12,7 @@
 #include <linux/init.h>
 #include <linux/errno.h>
 
-int __init oprofile_arch_init(struct oprofile_operations **ops)
+int __init oprofile_arch_init(struct oprofile_operations *ops)
 {
 	return -ENODEV;
 }
diff -Nru a/arch/sparc/kernel/ioport.c b/arch/sparc/kernel/ioport.c
--- a/arch/sparc/kernel/ioport.c	2005-03-11 12:51:51 -08:00
+++ b/arch/sparc/kernel/ioport.c	2005-03-11 12:51:51 -08:00
@@ -54,11 +54,11 @@
 
 /* This points to the next to use virtual memory for DVMA mappings */
 static struct resource _sparc_dvma = {
-	"sparc_dvma", DVMA_VADDR, DVMA_END - 1
+	.name = "sparc_dvma", .start = DVMA_VADDR, .end = DVMA_END - 1
 };
 /* This points to the start of I/O mappings, cluable from outside. */
 /*ext*/ struct resource sparc_iomap = {
-	"sparc_iomap", IOBASE_VADDR, IOBASE_END - 1
+	.name = "sparc_iomap", .start = IOBASE_VADDR, .end = IOBASE_END - 1
 };
 
 /*
diff -Nru a/arch/sparc/mm/generic.c b/arch/sparc/mm/generic.c
--- a/arch/sparc/mm/generic.c	2005-03-11 12:51:51 -08:00
+++ b/arch/sparc/mm/generic.c	2005-03-11 12:51:51 -08:00
@@ -47,7 +47,7 @@
  * They use a pgprot that sets PAGE_IO and does not check the
  * mem_map table as this is independent of normal memory.
  */
-static inline void io_remap_pte_range(pte_t * pte, unsigned long address, unsigned long size,
+static inline void io_remap_pte_range(struct mm_struct *mm, pte_t * pte, unsigned long address, unsigned long size,
 	unsigned long offset, pgprot_t prot, int space)
 {
 	unsigned long end;
@@ -58,7 +58,7 @@
 		end = PMD_SIZE;
 	do {
 		pte_t oldpage = *pte;
-		pte_clear(pte);
+		pte_clear(mm, address, pte);
 		set_pte(pte, mk_pte_io(offset, prot, space));
 		forget_pte(oldpage);
 		address += PAGE_SIZE;
@@ -67,7 +67,7 @@
 	} while (address < end);
 }
 
-static inline int io_remap_pmd_range(pmd_t * pmd, unsigned long address, unsigned long size,
+static inline int io_remap_pmd_range(struct mm_struct *mm, pmd_t * pmd, unsigned long address, unsigned long size,
 	unsigned long offset, pgprot_t prot, int space)
 {
 	unsigned long end;
@@ -78,10 +78,10 @@
 		end = PGDIR_SIZE;
 	offset -= address;
 	do {
-		pte_t * pte = pte_alloc_map(current->mm, pmd, address);
+		pte_t * pte = pte_alloc_map(mm, pmd, address);
 		if (!pte)
 			return -ENOMEM;
-		io_remap_pte_range(pte, address, end - address, address + offset, prot, space);
+		io_remap_pte_range(mm, pte, address, end - address, address + offset, prot, space);
 		address = (address + PMD_SIZE) & PMD_MASK;
 		pmd++;
 	} while (address < end);
@@ -107,7 +107,7 @@
 		error = -ENOMEM;
 		if (!pmd)
 			break;
-		error = io_remap_pmd_range(pmd, from, end - from, offset + from, prot, space);
+		error = io_remap_pmd_range(mm, pmd, from, end - from, offset + from, prot, space);
 		if (error)
 			break;
 		from = (from + PGDIR_SIZE) & PGDIR_MASK;
diff -Nru a/arch/sparc/mm/highmem.c b/arch/sparc/mm/highmem.c
--- a/arch/sparc/mm/highmem.c	2005-03-11 12:51:42 -08:00
+++ b/arch/sparc/mm/highmem.c	2005-03-11 12:51:42 -08:00
@@ -88,7 +88,7 @@
 	 * force other mappings to Oops if they'll try to access
 	 * this pte without first remap it
 	 */
-	pte_clear(kmap_pte-idx);
+	pte_clear(&init_mm, vaddr, kmap_pte-idx);
 /* XXX Fix - Anton */
 #if 0
 	__flush_tlb_one(vaddr);
diff -Nru a/arch/sparc/mm/srmmu.c b/arch/sparc/mm/srmmu.c
--- a/arch/sparc/mm/srmmu.c	2005-03-11 12:51:47 -08:00
+++ b/arch/sparc/mm/srmmu.c	2005-03-11 12:51:47 -08:00
@@ -1003,8 +1003,7 @@
 extern void viking_flush_cache_mm(struct mm_struct *mm);
 extern void viking_flush_cache_range(struct vm_area_struct *vma, unsigned long start,
 				     unsigned long end);
-extern void viking_flush_cache_page(struct vm_area_struct *vma,
-				    unsigned long page);
+extern void viking_flush_cache_page(struct vm_area_struct *vma, unsigned long page);
 extern void viking_flush_page_to_ram(unsigned long page);
 extern void viking_flush_page_for_dma(unsigned long page);
 extern void viking_flush_sig_insns(struct mm_struct *mm, unsigned long addr);
diff -Nru a/arch/sparc64/defconfig b/arch/sparc64/defconfig
--- a/arch/sparc64/defconfig	2005-03-11 12:51:42 -08:00
+++ b/arch/sparc64/defconfig	2005-03-11 12:51:42 -08:00
@@ -1,7 +1,7 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.11-rc4
-# Thu Feb 17 15:32:19 2005
+# Linux kernel version: 2.6.11
+# Sun Mar  6 20:47:29 2005
 #
 CONFIG_64BIT=y
 CONFIG_MMU=y
@@ -368,6 +368,7 @@
 CONFIG_SCSI_ATA_PIIX=m
 CONFIG_SCSI_SATA_NV=m
 CONFIG_SCSI_SATA_PROMISE=m
+CONFIG_SCSI_SATA_QSTOR=m
 CONFIG_SCSI_SATA_SX4=m
 CONFIG_SCSI_SATA_SIL=m
 CONFIG_SCSI_SATA_SIS=m
@@ -737,6 +738,7 @@
 CONFIG_NET_QOS=y
 CONFIG_NET_ESTIMATOR=y
 CONFIG_NET_CLS=y
+CONFIG_NET_CLS_BASIC=m
 CONFIG_NET_CLS_TCINDEX=m
 CONFIG_NET_CLS_ROUTE4=m
 CONFIG_NET_CLS_ROUTE=y
@@ -747,6 +749,12 @@
 CONFIG_CLS_U32_MARK=y
 CONFIG_NET_CLS_RSVP=m
 CONFIG_NET_CLS_RSVP6=m
+CONFIG_NET_EMATCH=y
+CONFIG_NET_EMATCH_STACK=32
+CONFIG_NET_EMATCH_CMP=m
+CONFIG_NET_EMATCH_NBYTE=m
+CONFIG_NET_EMATCH_U32=m
+CONFIG_NET_EMATCH_META=m
 CONFIG_NET_CLS_ACT=y
 CONFIG_NET_ACT_POLICE=m
 CONFIG_NET_ACT_GACT=m
@@ -899,7 +907,6 @@
 CONFIG_DGRS=m
 CONFIG_EEPRO100=m
 CONFIG_E100=m
-CONFIG_E100_NAPI=y
 CONFIG_FEALNX=m
 CONFIG_NATSEMI=m
 CONFIG_NE2K_PCI=m
@@ -1171,6 +1178,7 @@
 CONFIG_I2C_NFORCE2=m
 CONFIG_I2C_PARPORT=m
 CONFIG_I2C_PARPORT_LIGHT=m
+CONFIG_I2C_PIIX4=m
 CONFIG_I2C_PROSAVAGE=m
 CONFIG_I2C_SAVAGE4=m
 CONFIG_SCx200_ACB=m
@@ -1194,7 +1202,9 @@
 CONFIG_SENSORS_ASB100=m
 CONFIG_SENSORS_DS1621=m
 CONFIG_SENSORS_FSCHER=m
+CONFIG_SENSORS_FSCPOS=m
 CONFIG_SENSORS_GL518SM=m
+CONFIG_SENSORS_GL520SM=m
 CONFIG_SENSORS_IT87=m
 CONFIG_SENSORS_LM63=m
 CONFIG_SENSORS_LM75=m
@@ -1208,6 +1218,7 @@
 CONFIG_SENSORS_MAX1619=m
 CONFIG_SENSORS_PC87360=m
 CONFIG_SENSORS_SMSC47B397=m
+CONFIG_SENSORS_SIS5595=m
 CONFIG_SENSORS_SMSC47M1=m
 CONFIG_SENSORS_VIA686A=m
 CONFIG_SENSORS_W83781D=m
@@ -1909,6 +1920,7 @@
 CONFIG_CRYPTO_SHA256=m
 CONFIG_CRYPTO_SHA512=m
 CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_TGR192=m
 CONFIG_CRYPTO_DES=y
 CONFIG_CRYPTO_BLOWFISH=m
 CONFIG_CRYPTO_TWOFISH=m
diff -Nru a/arch/sparc64/kernel/ioctl32.c b/arch/sparc64/kernel/ioctl32.c
--- a/arch/sparc64/kernel/ioctl32.c	2005-03-11 12:51:51 -08:00
+++ b/arch/sparc64/kernel/ioctl32.c	2005-03-11 12:51:51 -08:00
@@ -475,7 +475,6 @@
 #include <linux/compat_ioctl.h>
 #define DECLARES
 #include "compat_ioctl.c"
-COMPATIBLE_IOCTL(TCSBRKP)
 COMPATIBLE_IOCTL(TIOCSTART)
 COMPATIBLE_IOCTL(TIOCSTOP)
 COMPATIBLE_IOCTL(TIOCSLTC)
diff -Nru a/arch/sparc64/kernel/irq.c b/arch/sparc64/kernel/irq.c
--- a/arch/sparc64/kernel/irq.c	2005-03-11 12:51:51 -08:00
+++ b/arch/sparc64/kernel/irq.c	2005-03-11 12:51:51 -08:00
@@ -1112,7 +1112,7 @@
 void init_irqwork_curcpu(void)
 {
 	register struct irq_work_struct *workp asm("o2");
-	unsigned long tmp;
+	register unsigned long tmp asm("o3");
 	int cpu = hard_smp_processor_id();
 
 	memset(__irq_work + cpu, 0, sizeof(*workp));
diff -Nru a/arch/sparc64/kernel/pci.c b/arch/sparc64/kernel/pci.c
--- a/arch/sparc64/kernel/pci.c	2005-03-11 12:51:40 -08:00
+++ b/arch/sparc64/kernel/pci.c	2005-03-11 12:51:40 -08:00
@@ -794,12 +794,6 @@
 }
 EXPORT_SYMBOL(pci_domain_nr);
 
-int pci_name_bus(char *name, struct pci_bus *bus)
-{
-	sprintf(name, "%04x:%02x", pci_domain_nr(bus), bus->number);
-	return 0;
-}
-
 int pcibios_prep_mwi(struct pci_dev *dev)
 {
 	/* We set correct PCI_CACHE_LINE_SIZE register values for every
diff -Nru a/arch/sparc64/kernel/pci_schizo.c b/arch/sparc64/kernel/pci_schizo.c
--- a/arch/sparc64/kernel/pci_schizo.c	2005-03-11 12:51:47 -08:00
+++ b/arch/sparc64/kernel/pci_schizo.c	2005-03-11 12:51:47 -08:00
@@ -326,9 +326,9 @@
 	return ret;
 }
 
-static unsigned int __init schizo_irq_build(struct pci_pbm_info *pbm,
-					    struct pci_dev *pdev,
-					    unsigned int ino)
+static unsigned int schizo_irq_build(struct pci_pbm_info *pbm,
+				     struct pci_dev *pdev,
+				     unsigned int ino)
 {
 	struct ino_bucket *bucket;
 	unsigned long imap, iclr;
@@ -382,19 +382,57 @@
 static unsigned long stc_tag_buf[16];
 static unsigned long stc_line_buf[16];
 
-/* These offsets look weird because I keep in pbm->controller_regs
- * the second PROM register property minus 0x10000 which is the
- * base of the Safari and UPA64S registers of SCHIZO.
- */
-#define SCHIZO_PBM_A_REGS_OFF	(0x600000UL - 0x400000UL)
-#define SCHIZO_PBM_B_REGS_OFF	(0x700000UL - 0x400000UL)
+#define SCHIZO_UE_INO		0x30 /* Uncorrectable ECC error */
+#define SCHIZO_CE_INO		0x31 /* Correctable ECC error */
+#define SCHIZO_PCIERR_A_INO	0x32 /* PBM A PCI bus error */
+#define SCHIZO_PCIERR_B_INO	0x33 /* PBM B PCI bus error */
+#define SCHIZO_SERR_INO		0x34 /* Safari interface error */
 
-static void schizo_clear_other_err_intr(int irq)
+struct pci_pbm_info *pbm_for_ino(struct pci_controller_info *p, u32 ino)
 {
-	struct ino_bucket *bucket = __bucket(irq);
-	unsigned long iclr = bucket->iclr;
+	ino &= IMAP_INO;
+	if (p->pbm_A.ino_bitmap & (1UL << ino))
+		return &p->pbm_A;
+	if (p->pbm_B.ino_bitmap & (1UL << ino))
+		return &p->pbm_B;
+
+	printk("PCI%d: No ino_bitmap entry for ino[%x], bitmaps "
+	       "PBM_A[%016lx] PBM_B[%016lx]",
+	       p->index, ino,
+	       p->pbm_A.ino_bitmap,
+	       p->pbm_B.ino_bitmap);
+	printk("PCI%d: Using PBM_A, report this problem immediately.\n",
+	       p->index);
+
+	return &p->pbm_A;
+}
+
+static void schizo_clear_other_err_intr(struct pci_controller_info *p, int irq)
+{
+	struct pci_pbm_info *pbm;
+	struct ino_bucket *bucket;
+	unsigned long iclr;
+
+	/* Do not clear the interrupt for the other PCI bus.
+	 *
+	 * This "ACK both PBM IRQs" only needs to be performed
+	 * for chip-wide error interrupts.
+	 */
+	if ((irq & IMAP_INO) == SCHIZO_PCIERR_A_INO ||
+	    (irq & IMAP_INO) == SCHIZO_PCIERR_B_INO)
+		return;
+
+	pbm = pbm_for_ino(p, irq);
+	if (pbm == &p->pbm_A)
+		pbm = &p->pbm_B;
+	else
+		pbm = &p->pbm_A;
+
+	irq = schizo_irq_build(pbm, NULL,
+			       (pbm->portid << 6) | (irq & IMAP_INO));
+	bucket = __bucket(irq);
+	iclr = bucket->iclr;
 
-	iclr += (SCHIZO_PBM_B_REGS_OFF - SCHIZO_PBM_A_REGS_OFF);
 	upa_writel(ICLR_IDLE, iclr);
 }
 
@@ -728,7 +766,7 @@
 	/* Interrogate IOMMU for error status. */
 	schizo_check_iommu_error(p, UE_ERR);
 
-	schizo_clear_other_err_intr(irq);
+	schizo_clear_other_err_intr(p, irq);
 
 	return IRQ_HANDLED;
 }
@@ -819,7 +857,7 @@
 		printk("(none)");
 	printk("]\n");
 
-	schizo_clear_other_err_intr(irq);
+	schizo_clear_other_err_intr(p, irq);
 
 	return IRQ_HANDLED;
 }
@@ -856,9 +894,9 @@
 #define SCHIZO_PCICTRL_SBH_ERR	(1UL << 35UL) /* Safari */
 #define SCHIZO_PCICTRL_SERR	(1UL << 34UL) /* Safari/Tomatillo */
 #define SCHIZO_PCICTRL_PCISPD	(1UL << 33UL) /* Safari */
-#define SCHIZO_PCICTRL_MRM_PREF	(1UL << 28UL) /* Tomatillo */
-#define SCHIZO_PCICTRL_RDO_PREF	(1UL << 27UL) /* Tomatillo */
-#define SCHIZO_PCICTRL_RDL_PREF	(1UL << 26UL) /* Tomatillo */
+#define SCHIZO_PCICTRL_MRM_PREF	(1UL << 30UL) /* Tomatillo */
+#define SCHIZO_PCICTRL_RDO_PREF	(1UL << 29UL) /* Tomatillo */
+#define SCHIZO_PCICTRL_RDL_PREF	(1UL << 28UL) /* Tomatillo */
 #define SCHIZO_PCICTRL_PTO	(3UL << 24UL) /* Safari/Tomatillo */
 #define SCHIZO_PCICTRL_PTO_SHIFT 24UL
 #define SCHIZO_PCICTRL_TRWSW	(7UL << 21UL) /* Tomatillo */
@@ -1040,7 +1078,7 @@
 	if (error_bits & (SCHIZO_PCIAFSR_PPERR | SCHIZO_PCIAFSR_SPERR))
 		pci_scan_for_parity_error(p, pbm, pbm->pci_bus);
 
-	schizo_clear_other_err_intr(irq);
+	schizo_clear_other_err_intr(p, irq);
 
 	return IRQ_HANDLED;
 }
@@ -1097,7 +1135,7 @@
 		printk("PCI%d: Unexpected Safari/JBUS error interrupt, errlog[%016lx]\n",
 		       p->index, errlog);
 
-		schizo_clear_other_err_intr(irq);
+		schizo_clear_other_err_intr(p, irq);
 		return IRQ_HANDLED;
 	}
 
@@ -1105,7 +1143,7 @@
 	       p->index);
 	schizo_check_iommu_error(p, SAFARI_ERR);
 
-	schizo_clear_other_err_intr(irq);
+	schizo_clear_other_err_intr(p, irq);
 	return IRQ_HANDLED;
 }
 
@@ -1120,26 +1158,6 @@
 #define SCHIZO_SAFARI_IRQCTRL	0x10010UL
 #define  SCHIZO_SAFIRQCTRL_EN	 0x8000000000000000UL
 
-#define SCHIZO_UE_INO		0x30 /* Uncorrectable ECC error */
-#define SCHIZO_CE_INO		0x31 /* Correctable ECC error */
-#define SCHIZO_PCIERR_A_INO	0x32 /* PBM A PCI bus error */
-#define SCHIZO_PCIERR_B_INO	0x33 /* PBM B PCI bus error */
-#define SCHIZO_SERR_INO		0x34 /* Safari interface error */
-
-struct pci_pbm_info *pbm_for_ino(struct pci_controller_info *p, u32 ino)
-{
-	ino &= IMAP_INO;
-	if (p->pbm_A.ino_bitmap & (1UL << ino))
-		return &p->pbm_A;
-	if (p->pbm_B.ino_bitmap & (1UL << ino))
-		return &p->pbm_B;
-	prom_printf("TOMATILLO%d: No entry in ino bitmap for %d\n",
-		    p->index, ino);
-	prom_halt();
-	/* NOTREACHED */
-	return NULL;
-}
-
 /* How the Tomatillo IRQs are routed around is pure guesswork here.
  *
  * All the Tomatillo devices I see in prtconf dumps seem to have only
@@ -1887,7 +1905,7 @@
 
 	tmp &= ~SCHIZO_PCICTRL_PTO;
 	if (pbm->chip_type == PBM_CHIP_TYPE_TOMATILLO &&
-	    pbm->chip_version == 0x2)
+	    pbm->chip_version >= 0x2)
 		tmp |= 0x3UL << SCHIZO_PCICTRL_PTO_SHIFT;
 	else
 		tmp |= 0x1UL << SCHIZO_PCICTRL_PTO_SHIFT;
@@ -1895,8 +1913,16 @@
 	if (!prom_getbool(pbm->prom_node, "no-bus-parking"))
 		tmp |= SCHIZO_PCICTRL_PARK;
 
+	if (pbm->chip_type == PBM_CHIP_TYPE_TOMATILLO &&
+	    pbm->chip_version <= 0x1)
+		tmp |= (1UL << 61);
+	else
+		tmp &= ~(1UL << 61);
+
 	if (pbm->chip_type == PBM_CHIP_TYPE_TOMATILLO)
-		tmp |= SCHIZO_PCICTRL_MRM_PREF;
+		tmp |= (SCHIZO_PCICTRL_MRM_PREF |
+			SCHIZO_PCICTRL_RDO_PREF |
+			SCHIZO_PCICTRL_RDL_PREF);
 
 	schizo_write(pbm->pbm_regs + SCHIZO_PCI_CTRL, tmp);
 
diff -Nru a/arch/sparc64/kernel/signal.c b/arch/sparc64/kernel/signal.c
--- a/arch/sparc64/kernel/signal.c	2005-03-11 12:51:52 -08:00
+++ b/arch/sparc64/kernel/signal.c	2005-03-11 12:51:52 -08:00
@@ -53,7 +53,7 @@
 	flush_user_windows();
 	if (get_thread_wsaved()					||
 	    (((unsigned long)ucp) & (sizeof(unsigned long)-1))	||
-	    (!__access_ok((unsigned long)ucp, sizeof(*ucp))))
+	    (!__access_ok(ucp, sizeof(*ucp))))
 		goto do_sigsegv;
 	grp  = &ucp->uc_mcontext.mc_gregs;
 	err  = __get_user(pc, &((*grp)[MC_PC]));
diff -Nru a/arch/sparc64/kernel/signal32.c b/arch/sparc64/kernel/signal32.c
--- a/arch/sparc64/kernel/signal32.c	2005-03-11 12:51:52 -08:00
+++ b/arch/sparc64/kernel/signal32.c	2005-03-11 12:51:52 -08:00
@@ -104,7 +104,7 @@
 		struct {
 			timer_t _tid;			/* timer id */
 			int _overrun;			/* overrun count */
-			sigval_t32 _sigval;		/* same as below */
+			compat_sigval_t _sigval;		/* same as below */
 			int _sys_private;		/* not to be passed to user */
 		} _timer;
 
@@ -112,7 +112,7 @@
 		struct {
 			compat_pid_t _pid;		/* sender's pid */
 			unsigned int _uid;		/* sender's uid */
-			sigval_t32 _sigval;
+			compat_sigval_t _sigval;
 		} _rt;
 
 		/* SIGCHLD */
@@ -1102,7 +1102,7 @@
 		goto sigsegv;
 	}
 
-	if (!__access_ok((unsigned long)c, sizeof(*c))) {
+	if (!__access_ok(c, sizeof(*c))) {
 		/* Miguel, add nice debugging msg _here_. ;-) */
 		goto sigsegv;
 	}
diff -Nru a/arch/sparc64/kernel/sys_sparc32.c b/arch/sparc64/kernel/sys_sparc32.c
--- a/arch/sparc64/kernel/sys_sparc32.c	2005-03-11 12:51:47 -08:00
+++ b/arch/sparc64/kernel/sys_sparc32.c	2005-03-11 12:51:47 -08:00
@@ -268,7 +268,7 @@
 			/* sign extend semid */
 			return compat_sys_semtimedop((int)first,
 						     compat_ptr(ptr), second,
-						     compat_ptr(third));
+						     compat_ptr(fifth));
 		/* else fall through for normal semop() */
 	case SEMOP:
 		/* struct sembuf is the same on 32 and 64bit :)) */
@@ -1087,7 +1087,7 @@
 		 timer_t __user *created_timer_id);
 
 long
-sys32_timer_create(u32 clock, struct sigevent32 __user *se32,
+sys32_timer_create(u32 clock, struct compat_sigevent __user *se32,
 		   timer_t __user *timer_id)
 {
 	struct sigevent se;
@@ -1098,12 +1098,7 @@
 	if (se32 == NULL)
 		return sys_timer_create(clock, NULL, timer_id);
 
-	memset(&se, 0, sizeof(struct sigevent));
-	if (get_user(se.sigev_value.sival_int,  &se32->sigev_value.sival_int) ||
-	    __get_user(se.sigev_signo, &se32->sigev_signo) ||
-	    __get_user(se.sigev_notify, &se32->sigev_notify) ||
-	    __copy_from_user(&se._sigev_un._pad, &se32->_sigev_un._pad,
-	    sizeof(se._sigev_un._pad)))
+	if (get_compat_sigevent(&se, se32))
 		return -EFAULT;
 
 	if (!access_ok(VERIFY_WRITE,timer_id,sizeof(timer_t)))
@@ -1120,35 +1115,4 @@
 		err = __put_user (t, timer_id);
 
 	return err;
-}
-
-asmlinkage long compat_sys_waitid(u32 which, u32 pid,
-				  struct compat_siginfo __user *uinfo,
-				  u32 options, struct compat_rusage __user *uru)
-{
-	siginfo_t info;
-	struct rusage ru;
-	long ret;
-	mm_segment_t old_fs = get_fs();
-
-	memset(&info, 0, sizeof(info));
-
-	set_fs (KERNEL_DS);
-	ret = sys_waitid(which, pid, (siginfo_t __user *) &info,
-			 options,
-			 uru ? (struct rusage __user *) &ru : NULL);
-	set_fs (old_fs);
-
-	if (ret < 0 || info.si_signo == 0)
-		return ret;
-
-	if (uru) {
-		ret = put_compat_rusage(&ru, uru);
-		if (ret)
-			return ret;
-	}
-
-	BUG_ON(info.si_code & __SI_MASK);
-	info.si_code |= __SI_CHLD;
-	return copy_siginfo_to_user32(uinfo, &info);
 }
diff -Nru a/arch/sparc64/kernel/time.c b/arch/sparc64/kernel/time.c
--- a/arch/sparc64/kernel/time.c	2005-03-11 12:51:46 -08:00
+++ b/arch/sparc64/kernel/time.c	2005-03-11 12:51:46 -08:00
@@ -779,6 +779,7 @@
 		    strcmp(model, "mk48t59") &&
 		    strcmp(model, "m5819") &&
 		    strcmp(model, "m5819p") &&
+		    strcmp(model, "m5823") &&
 		    strcmp(model, "ds1287")) {
 			if (cbus != NULL) {
 				prom_printf("clock_probe: Central bus lacks timer chip.\n");
@@ -838,7 +839,8 @@
 
 			if (!strcmp(model, "ds1287") ||
 			    !strcmp(model, "m5819") ||
-			    !strcmp(model, "m5819p")) {
+			    !strcmp(model, "m5819p") ||
+			    !strcmp(model, "m5823")) {
 				ds1287_regs = edev->resource[0].start;
 			} else {
 				mstk48t59_regs = edev->resource[0].start;
@@ -859,7 +861,8 @@
 			}
 			if (!strcmp(model, "ds1287") ||
 			    !strcmp(model, "m5819") ||
-			    !strcmp(model, "m5819p")) {
+			    !strcmp(model, "m5819p") ||
+			    !strcmp(model, "m5823")) {
 				ds1287_regs = isadev->resource.start;
 			} else {
 				mstk48t59_regs = isadev->resource.start;
diff -Nru a/arch/sparc64/mm/generic.c b/arch/sparc64/mm/generic.c
--- a/arch/sparc64/mm/generic.c	2005-03-11 12:51:51 -08:00
+++ b/arch/sparc64/mm/generic.c	2005-03-11 12:51:51 -08:00
@@ -25,8 +25,11 @@
  * side-effect bit will be turned off.  This is used as a
  * performance improvement on FFB/AFB. -DaveM
  */
-static inline void io_remap_pte_range(pte_t * pte, unsigned long address, unsigned long size,
-	unsigned long offset, pgprot_t prot, int space)
+static inline void io_remap_pte_range(struct mm_struct *mm, pte_t * pte,
+				      unsigned long address,
+				      unsigned long size,
+				      unsigned long offset, pgprot_t prot,
+				      int space)
 {
 	unsigned long end;
 
@@ -67,14 +70,14 @@
 			pte_val(entry) &= ~(_PAGE_E);
 		do {
 			BUG_ON(!pte_none(*pte));
-			set_pte(pte, entry);
+			set_pte_at(mm, address, pte, entry);
 			address += PAGE_SIZE;
 			pte++;
 		} while (address < curend);
 	} while (address < end);
 }
 
-static inline int io_remap_pmd_range(pmd_t * pmd, unsigned long address, unsigned long size,
+static inline int io_remap_pmd_range(struct mm_struct *mm, pmd_t * pmd, unsigned long address, unsigned long size,
 	unsigned long offset, pgprot_t prot, int space)
 {
 	unsigned long end;
@@ -85,10 +88,10 @@
 		end = PGDIR_SIZE;
 	offset -= address;
 	do {
-		pte_t * pte = pte_alloc_map(current->mm, pmd, address);
+		pte_t * pte = pte_alloc_map(mm, pmd, address);
 		if (!pte)
 			return -ENOMEM;
-		io_remap_pte_range(pte, address, end - address, address + offset, prot, space);
+		io_remap_pte_range(mm, pte, address, end - address, address + offset, prot, space);
 		pte_unmap(pte);
 		address = (address + PMD_SIZE) & PMD_MASK;
 		pmd++;
@@ -96,7 +99,7 @@
 	return 0;
 }
 
-static inline int io_remap_pud_range(pud_t * pud, unsigned long address, unsigned long size,
+static inline int io_remap_pud_range(struct mm_struct *mm, pud_t * pud, unsigned long address, unsigned long size,
 	unsigned long offset, pgprot_t prot, int space)
 {
 	unsigned long end;
@@ -107,10 +110,10 @@
 		end = PUD_SIZE;
 	offset -= address;
 	do {
-		pmd_t *pmd = pmd_alloc(current->mm, pud, address);
+		pmd_t *pmd = pmd_alloc(mm, pud, address);
 		if (!pud)
 			return -ENOMEM;
-		io_remap_pmd_range(pmd, address, end - address, address + offset, prot, space);
+		io_remap_pmd_range(mm, pmd, address, end - address, address + offset, prot, space);
 		address = (address + PUD_SIZE) & PUD_MASK;
 		pud++;
 	} while (address < end);
@@ -132,11 +135,11 @@
 
 	spin_lock(&mm->page_table_lock);
 	while (from < end) {
-		pud_t *pud = pud_alloc(current->mm, dir, from);
+		pud_t *pud = pud_alloc(mm, dir, from);
 		error = -ENOMEM;
 		if (!pud)
 			break;
-		error = io_remap_pud_range(pud, from, end - from, offset + from, prot, space);
+		error = io_remap_pud_range(mm, pud, from, end - from, offset + from, prot, space);
 		if (error)
 			break;
 		from = (from + PGDIR_SIZE) & PGDIR_MASK;
diff -Nru a/arch/sparc64/mm/hugetlbpage.c b/arch/sparc64/mm/hugetlbpage.c
--- a/arch/sparc64/mm/hugetlbpage.c	2005-03-11 12:51:47 -08:00
+++ b/arch/sparc64/mm/hugetlbpage.c	2005-03-11 12:51:47 -08:00
@@ -62,6 +62,7 @@
 #define mk_pte_huge(entry) do { pte_val(entry) |= _PAGE_SZHUGE; } while (0)
 
 static void set_huge_pte(struct mm_struct *mm, struct vm_area_struct *vma,
+			 unsigned long addr,
 			 struct page *page, pte_t * page_table, int write_access)
 {
 	unsigned long i;
@@ -78,8 +79,9 @@
 	mk_pte_huge(entry);
 
 	for (i = 0; i < (1 << HUGETLB_PAGE_ORDER); i++) {
-		set_pte(page_table, entry);
+		set_pte_at(mm, addr, page_table, entry);
 		page_table++;
+		addr += PAGE_SIZE;
 
 		pte_val(entry) += PAGE_SIZE;
 	}
@@ -116,12 +118,12 @@
 		ptepage = pte_page(entry);
 		get_page(ptepage);
 		for (i = 0; i < (1 << HUGETLB_PAGE_ORDER); i++) {
-			set_pte(dst_pte, entry);
+			set_pte_at(dst, addr, dst_pte, entry);
 			pte_val(entry) += PAGE_SIZE;
 			dst_pte++;
+			addr += PAGE_SIZE;
 		}
 		dst->rss += (HPAGE_SIZE / PAGE_SIZE);
-		addr += HPAGE_SIZE;
 	}
 	return 0;
 
@@ -207,7 +209,7 @@
 		page = pte_page(*pte);
 		put_page(page);
 		for (i = 0; i < (1 << HUGETLB_PAGE_ORDER); i++) {
-			pte_clear(pte);
+			pte_clear(mm, address+(i*PAGE_SIZE), pte);
 			pte++;
 		}
 	}
@@ -261,7 +263,7 @@
 				goto out;
 			}
 		}
-		set_huge_pte(mm, vma, page, pte, vma->vm_flags & VM_WRITE);
+		set_huge_pte(mm, vma, addr, page, pte, vma->vm_flags & VM_WRITE);
 	}
 out:
 	spin_unlock(&mm->page_table_lock);
diff -Nru a/arch/sparc64/mm/init.c b/arch/sparc64/mm/init.c
--- a/arch/sparc64/mm/init.c	2005-03-11 12:51:42 -08:00
+++ b/arch/sparc64/mm/init.c	2005-03-11 12:51:42 -08:00
@@ -431,7 +431,8 @@
 				if (tlb_type == spitfire)
 					val &= ~0x0003fe0000000000UL;
 
-				set_pte (ptep, __pte(val | _PAGE_MODIFIED));
+				set_pte_at(&init_mm, vaddr,
+					   ptep, __pte(val | _PAGE_MODIFIED));
 				trans[i].data += BASE_PAGE_SIZE;
 			}
 		}
diff -Nru a/arch/sparc64/mm/tlb.c b/arch/sparc64/mm/tlb.c
--- a/arch/sparc64/mm/tlb.c	2005-03-11 12:51:46 -08:00
+++ b/arch/sparc64/mm/tlb.c	2005-03-11 12:51:46 -08:00
@@ -41,24 +41,12 @@
 	}
 }
 
-void tlb_batch_add(pte_t *ptep, pte_t orig)
+void tlb_batch_add(struct mm_struct *mm, unsigned long vaddr, pte_t *ptep, pte_t orig)
 {
 	struct mmu_gather *mp = &__get_cpu_var(mmu_gathers);
-	struct page *ptepage;
-	struct mm_struct *mm;
-	unsigned long vaddr, nr;
+	unsigned long nr;
 
-	ptepage = virt_to_page(ptep);
-	mm = (struct mm_struct *) ptepage->mapping;
-
-	/* It is more efficient to let flush_tlb_kernel_range()
-	 * handle these cases.
-	 */
-	if (mm == &init_mm)
-		return;
-
-	vaddr = ptepage->index +
-		(((unsigned long)ptep & ~PAGE_MASK) * PTRS_PER_PTE);
+	vaddr &= PAGE_MASK;
 	if (pte_exec(orig))
 		vaddr |= 0x1UL;
 
diff -Nru a/arch/um/Kconfig.debug b/arch/um/Kconfig.debug
--- a/arch/um/Kconfig.debug	2005-03-11 12:51:42 -08:00
+++ b/arch/um/Kconfig.debug	2005-03-11 12:51:42 -08:00
@@ -40,4 +40,14 @@
         If you're involved in UML kernel development and want to use gcov,
         say Y.  If you're unsure, say N.
 
+config SYSCALL_DEBUG
+	bool "Enable system call debugging"
+	default N
+	depends on DEBUG_INFO
+	help
+	This adds some system debugging to UML, including keeping a ring buffer
+	with recent system calls and some global and per-task statistics.
+
+	If unsure, say N
+
 endmenu
diff -Nru a/arch/um/Kconfig_char b/arch/um/Kconfig_char
--- a/arch/um/Kconfig_char	2005-03-11 12:51:43 -08:00
+++ b/arch/um/Kconfig_char	2005-03-11 12:51:43 -08:00
@@ -190,5 +190,19 @@
 	tristate
 	default UML_SOUND
 
+config UML_RANDOM
+	tristate "Hardware random number generator"
+	help
+	This option enables UML's "hardware" random number generator.  It
+	attaches itself to the host's /dev/random, supplying as much entropy
+	as the host has, rather than the small amount the UML gets from its
+	own drivers.  It registers itself as a standard hardware random number
+	generator, major 10, minor 183, and the canonical device name is
+	/dev/hwrng.
+	The way to make use of this is to install the rng-tools package
+	(check your distro, or download from
+	http://sourceforge.net/projects/gkernel/).  rngd periodically reads
+	/dev/hwrng and injects the entropy into /dev/random.
+
 endmenu
 
diff -Nru a/arch/um/Makefile b/arch/um/Makefile
--- a/arch/um/Makefile	2005-03-11 12:51:47 -08:00
+++ b/arch/um/Makefile	2005-03-11 12:51:47 -08:00
@@ -182,13 +182,18 @@
 $(ARCH_DIR)/include/task.h: $(ARCH_DIR)/util/mk_task
 	$(call filechk,gen_header)
 
+$(ARCH_DIR)/include/user_constants.h: $(ARCH_DIR)/os/util/mk_user_constants
+	$(call filechk,gen_header)
+
 $(ARCH_DIR)/include/kern_constants.h: $(ARCH_DIR)/util/mk_constants
 	$(call filechk,gen_header)
 
 $(ARCH_DIR)/include/skas_ptregs.h: $(ARCH_DIR)/kernel/skas/util/mk_ptregs
 	$(call filechk,gen_header)
 
-$(ARCH_DIR)/util/mk_task $(ARCH_DIR)/util/mk_constants: $(ARCH_DIR)/util \
+$(ARCH_DIR)/os/util/mk_user_constants: $(ARCH_DIR)/os/util FORCE ;
+
+$(ARCH_DIR)/util/mk_task $(ARCH_DIR)/util/mk_constants: $(ARCH_DIR)/include/user_constants.h $(ARCH_DIR)/util \
 	FORCE ;
 
 $(ARCH_DIR)/kernel/skas/util/mk_ptregs: $(ARCH_DIR)/kernel/skas/util FORCE ;
@@ -197,6 +202,9 @@
 	$(Q)$(MAKE) $(build)=$@
 
 $(ARCH_DIR)/kernel/skas/util: scripts_basic FORCE
+	$(Q)$(MAKE) $(build)=$@
+
+$(ARCH_DIR)/os/util: scripts_basic FORCE
 	$(Q)$(MAKE) $(build)=$@
 
 export SUBARCH USER_CFLAGS OS
diff -Nru a/arch/um/defconfig b/arch/um/defconfig
--- a/arch/um/defconfig	2005-03-11 12:51:52 -08:00
+++ b/arch/um/defconfig	2005-03-11 12:51:52 -08:00
@@ -1,13 +1,11 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.10-rc2-mm4
-# Wed Dec  1 13:45:40 2004
+# Linux kernel version: 2.6.11
+# Fri Mar  4 15:38:53 2005
 #
 CONFIG_GENERIC_HARDIRQS=y
 CONFIG_USERMODE=y
 CONFIG_MMU=y
-# CONFIG_64_BIT is not set
-CONFIG_TOP_ADDR=0xc0000000
 CONFIG_UID16=y
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
@@ -17,17 +15,22 @@
 #
 CONFIG_MODE_TT=y
 CONFIG_MODE_SKAS=y
+# CONFIG_64_BIT is not set
+CONFIG_TOP_ADDR=0xc0000000
 # CONFIG_3_LEVEL_PGTABLES is not set
+CONFIG_ARCH_HAS_SC_SIGNALS=y
+CONFIG_ARCH_REUSE_HOST_VSYSCALL_AREA=y
+CONFIG_LD_SCRIPT_STATIC=y
 CONFIG_NET=y
 CONFIG_BINFMT_ELF=y
 CONFIG_BINFMT_MISC=m
 CONFIG_HOSTFS=y
 CONFIG_MCONSOLE=y
+# CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_HOST_2G_2G is not set
 # CONFIG_SMP is not set
 CONFIG_NEST_LEVEL=0
 CONFIG_KERNEL_HALF_GIGS=1
-# CONFIG_HIGHMEM is not set
 CONFIG_KERNEL_STACK_ORDER=2
 CONFIG_UML_REAL_TIME_CLOCK=y
 
@@ -49,7 +52,6 @@
 # CONFIG_BSD_PROCESS_ACCT_V3 is not set
 CONFIG_SYSCTL=y
 # CONFIG_AUDIT is not set
-CONFIG_LOG_BUF_SHIFT=14
 # CONFIG_HOTPLUG is not set
 CONFIG_KOBJECT_UEVENT=y
 CONFIG_IKCONFIG=y
@@ -58,9 +60,10 @@
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_ALL is not set
 CONFIG_KALLSYMS_EXTRA_PASS=y
+CONFIG_BASE_FULL=y
+CONFIG_BASE_SMALL=0
 CONFIG_FUTEX=y
 CONFIG_EPOLL=y
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_SHMEM=y
 CONFIG_CC_ALIGN_FUNCTIONS=0
 CONFIG_CC_ALIGN_LABELS=0
@@ -75,7 +78,6 @@
 CONFIG_MODULE_UNLOAD=y
 # CONFIG_MODULE_FORCE_UNLOAD is not set
 CONFIG_OBSOLETE_MODPARM=y
-# CONFIG_MODVERSIONS is not set
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_KMOD=y
 
@@ -84,6 +86,7 @@
 #
 CONFIG_STANDALONE=y
 CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
 # CONFIG_DEBUG_DRIVER is not set
 
 #
@@ -97,7 +100,7 @@
 CONFIG_PTY_CHAN=y
 CONFIG_TTY_CHAN=y
 CONFIG_XTERM_CHAN=y
-CONFIG_NOCONFIG_CHAN=y
+# CONFIG_NOCONFIG_CHAN is not set
 CONFIG_CON_ZERO_CHAN="fd:0,fd:1"
 CONFIG_CON_CHAN="xterm"
 CONFIG_SSL_CHAN="pty"
@@ -108,17 +111,21 @@
 CONFIG_UML_SOUND=m
 CONFIG_SOUND=m
 CONFIG_HOSTAUDIO=m
+CONFIG_UML_RANDOM=y
 
 #
-# Block Devices
+# Block devices
 #
 CONFIG_BLK_DEV_UBD=y
 CONFIG_BLK_DEV_UBD_SYNC=y
 CONFIG_BLK_DEV_COW_COMMON=y
 CONFIG_BLK_DEV_LOOP=m
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
 CONFIG_BLK_DEV_NBD=m
 # CONFIG_BLK_DEV_RAM is not set
+CONFIG_BLK_DEV_RAM_COUNT=16
 CONFIG_INITRAMFS_SOURCE=""
+# CONFIG_LBD is not set
 
 #
 # IO Schedulers
@@ -127,6 +134,7 @@
 CONFIG_IOSCHED_AS=y
 CONFIG_IOSCHED_DEADLINE=y
 CONFIG_IOSCHED_CFQ=y
+# CONFIG_ATA_OVER_ETH is not set
 CONFIG_NETDEVICES=y
 
 #
@@ -196,10 +204,7 @@
 # Network testing
 #
 # CONFIG_NET_PKTGEN is not set
-# CONFIG_KGDBOE is not set
 # CONFIG_NETPOLL is not set
-# CONFIG_NETPOLL_RX is not set
-# CONFIG_NETPOLL_TRAP is not set
 # CONFIG_NET_POLL_CONTROLLER is not set
 # CONFIG_HAMRADIO is not set
 # CONFIG_IRDA is not set
@@ -232,6 +237,16 @@
 # CONFIG_NET_RADIO is not set
 
 #
+# PCMCIA network device support
+#
+# CONFIG_NET_PCMCIA is not set
+
+#
+# PCMCIA network device support
+#
+# CONFIG_NET_PCMCIA is not set
+
+#
 # Wan interfaces
 #
 # CONFIG_WAN is not set
@@ -259,12 +274,15 @@
 # CONFIG_EXT3_FS_XATTR is not set
 CONFIG_JBD=y
 # CONFIG_JBD_DEBUG is not set
-# CONFIG_REISER4_FS is not set
 CONFIG_REISERFS_FS=y
 # CONFIG_REISERFS_CHECK is not set
 # CONFIG_REISERFS_PROC_INFO is not set
 # CONFIG_REISERFS_FS_XATTR is not set
 # CONFIG_JFS_FS is not set
+
+#
+# XFS support
+#
 # CONFIG_XFS_FS is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_ROMFS_FS is not set
@@ -277,11 +295,6 @@
 CONFIG_AUTOFS4_FS=m
 
 #
-# Caches
-#
-# CONFIG_FSCACHE is not set
-
-#
 # CD-ROM/DVD Filesystems
 #
 CONFIG_ISO9660_FS=m
@@ -331,7 +344,6 @@
 #
 # CONFIG_NFS_FS is not set
 # CONFIG_NFSD is not set
-# CONFIG_EXPORTFS is not set
 # CONFIG_SMB_FS is not set
 # CONFIG_CIFS is not set
 # CONFIG_NCP_FS is not set
@@ -400,10 +412,14 @@
 # CONFIG_CRYPTO is not set
 
 #
+# Hardware crypto devices
+#
+
+#
 # Library routines
 #
 # CONFIG_CRC_CCITT is not set
-# CONFIG_CRC32 is not set
+CONFIG_CRC32=m
 # CONFIG_LIBCRC32C is not set
 
 #
@@ -416,14 +432,15 @@
 # Kernel hacking
 #
 CONFIG_DEBUG_KERNEL=y
-# CONFIG_MAGIC_SYSRQ is not set
 # CONFIG_SCHEDSTATS is not set
 # CONFIG_DEBUG_SLAB is not set
 # CONFIG_DEBUG_SPINLOCK is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_KOBJECT is not set
 CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_FS is not set
 CONFIG_FRAME_POINTER=y
 CONFIG_PT_PROXY=y
 # CONFIG_GPROF is not set
 # CONFIG_GCOV is not set
+# CONFIG_SYSCALL_DEBUG is not set
diff -Nru a/arch/um/drivers/Makefile b/arch/um/drivers/Makefile
--- a/arch/um/drivers/Makefile	2005-03-11 12:51:52 -08:00
+++ b/arch/um/drivers/Makefile	2005-03-11 12:51:52 -08:00
@@ -3,8 +3,6 @@
 # Licensed under the GPL
 #
 
-CHAN_OBJS := chan_kern.o chan_user.o line.o 
-
 # pcap is broken in 2.5 because kbuild doesn't allow pcap.a to be linked
 # in to pcap.o
 
@@ -20,7 +18,7 @@
 port-objs := port_kern.o port_user.o
 harddog-objs := harddog_kern.o harddog_user.o
 
-obj-y := stdio_console.o fd.o $(CHAN_OBJS)
+obj-y := stdio_console.o fd.o chan_kern.o chan_user.o line.o
 obj-$(CONFIG_SSL) += ssl.o
 obj-$(CONFIG_STDERR_CONSOLE) += stderr_console.o
 
@@ -41,7 +39,7 @@
 obj-$(CONFIG_XTERM_CHAN) += xterm.o xterm_kern.o
 obj-$(CONFIG_UML_WATCHDOG) += harddog.o
 obj-$(CONFIG_BLK_DEV_COW_COMMON) += cow_user.o
-
+obj-$(CONFIG_UML_RANDOM) += random.o
 
 USER_SINGLE_OBJS = $(foreach f,$(patsubst %.o,%,$(obj-y) $(obj-m)),$($(f)-objs))
 
diff -Nru a/arch/um/drivers/cow_user.c b/arch/um/drivers/cow_user.c
--- a/arch/um/drivers/cow_user.c	2005-03-11 12:51:47 -08:00
+++ b/arch/um/drivers/cow_user.c	2005-03-11 12:51:47 -08:00
@@ -1,6 +1,9 @@
 #include <stddef.h>
 #include <string.h>
 #include <errno.h>
+/* _XOPEN_SOURCE is needed for pread, but we define _GNU_SOURCE, which defines
+ * that.
+ */
 #include <unistd.h>
 #include <byteswap.h>
 #include <sys/time.h>
diff -Nru a/arch/um/drivers/fd.c b/arch/um/drivers/fd.c
--- a/arch/um/drivers/fd.c	2005-03-11 12:51:51 -08:00
+++ b/arch/um/drivers/fd.c	2005-03-11 12:51:51 -08:00
@@ -19,7 +19,7 @@
 	char str[sizeof("1234567890\0")];
 };
 
-void *fd_init(char *str, int device, struct chan_opts *opts)
+static void *fd_init(char *str, int device, struct chan_opts *opts)
 {
 	struct fd_chan *data;
 	char *end;
@@ -43,7 +43,7 @@
 	return(data);
 }
 
-int fd_open(int input, int output, int primary, void *d, char **dev_out)
+static int fd_open(int input, int output, int primary, void *d, char **dev_out)
 {
 	struct fd_chan *data = d;
 	int err;
@@ -62,7 +62,7 @@
 	return(data->fd);
 }
 
-void fd_close(int fd, void *d)
+static void fd_close(int fd, void *d)
 {
 	struct fd_chan *data = d;
 	int err;
@@ -76,7 +76,7 @@
 	}
 }
 
-int fd_console_write(int fd, const char *buf, int n, void *d)
+static int fd_console_write(int fd, const char *buf, int n, void *d)
 {
 	struct fd_chan *data = d;
 
diff -Nru a/arch/um/drivers/net_kern.c b/arch/um/drivers/net_kern.c
--- a/arch/um/drivers/net_kern.c	2005-03-11 12:51:46 -08:00
+++ b/arch/um/drivers/net_kern.c	2005-03-11 12:51:46 -08:00
@@ -728,7 +728,8 @@
 
 	list_for_each(ele, &opened){
 		lp = list_entry(ele, struct uml_net_private, list);
-		if(lp->close != NULL) (*lp->close)(lp->fd, &lp->user);
+		if((lp->close != NULL) && (lp->fd >= 0))
+			(*lp->close)(lp->fd, &lp->user);
 		if(lp->remove != NULL) (*lp->remove)(&lp->user);
 	}
 }
diff -Nru a/arch/um/drivers/null.c b/arch/um/drivers/null.c
--- a/arch/um/drivers/null.c	2005-03-11 12:51:41 -08:00
+++ b/arch/um/drivers/null.c	2005-03-11 12:51:41 -08:00
@@ -10,23 +10,24 @@
 
 static int null_chan;
 
-void *null_init(char *str, int device, struct chan_opts *opts)
+static void *null_init(char *str, int device, struct chan_opts *opts)
 {
 	return(&null_chan);
 }
 
-int null_open(int input, int output, int primary, void *d, char **dev_out)
+static int null_open(int input, int output, int primary, void *d,
+		     char **dev_out)
 {
 	*dev_out = NULL;
 	return(os_open_file(DEV_NULL, of_rdwr(OPENFLAGS()), 0));
 }
 
-int null_read(int fd, char *c_out, void *unused)
+static int null_read(int fd, char *c_out, void *unused)
 {
 	return(-ENODEV);
 }
 
-void null_free(void *data)
+static void null_free(void *data)
 {
 }
 
diff -Nru a/arch/um/drivers/port_kern.c b/arch/um/drivers/port_kern.c
--- a/arch/um/drivers/port_kern.c	2005-03-11 12:51:41 -08:00
+++ b/arch/um/drivers/port_kern.c	2005-03-11 12:51:41 -08:00
@@ -10,6 +10,7 @@
 #include "linux/irq.h"
 #include "linux/spinlock.h"
 #include "linux/errno.h"
+#include "asm/atomic.h"
 #include "asm/semaphore.h"
 #include "asm/errno.h"
 #include "kern_util.h"
@@ -22,8 +23,9 @@
 
 struct port_list {
 	struct list_head list;
+	atomic_t wait_count;
 	int has_connection;
-	struct semaphore sem;
+	struct completion done;
 	int port;
 	int fd;
 	spinlock_t lock;
@@ -66,10 +68,17 @@
 	conn->fd = fd;
 	list_add(&conn->list, &conn->port->connections);
 
-	up(&conn->port->sem);
+	complete(&conn->port->done);
 	return(IRQ_HANDLED);
 }
 
+#define NO_WAITER_MSG \
+    "****\n" \
+    "There are currently no UML consoles waiting for port connections.\n" \
+    "Either disconnect from one to make it available or activate some more\n" \
+    "by enabling more consoles in the UML /etc/inittab.\n" \
+    "****\n"
+
 static int port_accept(struct port_list *port)
 {
 	struct connection *conn;
@@ -104,6 +113,10 @@
 		goto out_free;
 	}
 
+	if(atomic_read(&port->wait_count) == 0){
+		os_write_file(fd, NO_WAITER_MSG, sizeof(NO_WAITER_MSG));
+		printk("No one waiting for port\n");
+	}
 	list_add(&conn->list, &port->pending);
 	return(1);
 
@@ -182,14 +195,14 @@
 
 	*port = ((struct port_list) 
 		{ .list 	 	= LIST_HEAD_INIT(port->list),
+		  .wait_count		= ATOMIC_INIT(0),
 		  .has_connection 	= 0,
-		  .sem 			= __SEMAPHORE_INITIALIZER(port->sem, 
-								  0),
-		  .lock 		= SPIN_LOCK_UNLOCKED,
 		  .port 	 	= port_num,
 		  .fd  			= fd,
 		  .pending 		= LIST_HEAD_INIT(port->pending),
 		  .connections 		= LIST_HEAD_INIT(port->connections) });
+	spin_lock_init(&port->lock);
+	init_completion(&port->done);
 	list_add(&port->list, &ports);
 
  found:
@@ -220,9 +233,11 @@
 	struct port_list *port = dev->port;
 	int fd;
 
+        atomic_inc(&port->wait_count);
 	while(1){
-		if(down_interruptible(&port->sem))
-			return(-ERESTARTSYS);
+		fd = -ERESTARTSYS;
+                if(wait_for_completion_interruptible(&port->done))
+                        goto out;
 
 		spin_lock(&port->lock);
 
@@ -254,8 +269,9 @@
 	dev->helper_pid = conn->helper_pid;
 	dev->telnetd_pid = conn->telnetd_pid;
 	kfree(conn);
-
-	return(fd);
+ out:
+	atomic_dec(&port->wait_count);
+	return fd;
 }
 
 void port_remove_dev(void *d)
@@ -291,14 +307,3 @@
 }
 
 __uml_exitcall(free_port);
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff -Nru a/arch/um/drivers/port_user.c b/arch/um/drivers/port_user.c
--- a/arch/um/drivers/port_user.c	2005-03-11 12:51:47 -08:00
+++ b/arch/um/drivers/port_user.c	2005-03-11 12:51:47 -08:00
@@ -28,7 +28,7 @@
 	char dev[sizeof("32768\0")];
 };
 
-void *port_init(char *str, int device, struct chan_opts *opts)
+static void *port_init(char *str, int device, struct chan_opts *opts)
 {
 	struct port_chan *data;
 	void *kern_data;
@@ -65,7 +65,7 @@
 	return(NULL);
 }
 
-void port_free(void *d)
+static void port_free(void *d)
 {
 	struct port_chan *data = d;
 
@@ -73,7 +73,8 @@
 	kfree(data);
 }
 
-int port_open(int input, int output, int primary, void *d, char **dev_out)
+static int port_open(int input, int output, int primary, void *d,
+		     char **dev_out)
 {
 	struct port_chan *data = d;
 	int fd, err;
@@ -92,7 +93,7 @@
 	return(fd);
 }
 
-void port_close(int fd, void *d)
+static void port_close(int fd, void *d)
 {
 	struct port_chan *data = d;
 
@@ -100,7 +101,7 @@
 	os_close_file(fd);
 }
 
-int port_console_write(int fd, const char *buf, int n, void *d)
+static int port_console_write(int fd, const char *buf, int n, void *d)
 {
 	struct port_chan *data = d;
 
diff -Nru a/arch/um/drivers/pty.c b/arch/um/drivers/pty.c
--- a/arch/um/drivers/pty.c	2005-03-11 12:51:51 -08:00
+++ b/arch/um/drivers/pty.c	2005-03-11 12:51:51 -08:00
@@ -22,7 +22,7 @@
 	char dev_name[sizeof("/dev/pts/0123456\0")];
 };
 
-void *pty_chan_init(char *str, int device, struct chan_opts *opts)
+static void *pty_chan_init(char *str, int device, struct chan_opts *opts)
 {
 	struct pty_chan *data;
 
@@ -34,7 +34,8 @@
 	return(data);
 }
 
-int pts_open(int input, int output, int primary, void *d, char **dev_out)
+static int pts_open(int input, int output, int primary, void *d,
+		    char **dev_out)
 {
 	struct pty_chan *data = d;
 	char *dev;
@@ -63,7 +64,7 @@
 	return(fd);
 }
 
-int getmaster(char *line)
+static int getmaster(char *line)
 {
 	char *pty, *bank, *cp;
 	int master, err;
@@ -92,7 +93,8 @@
 	return(-1);
 }
 
-int pty_open(int input, int output, int primary, void *d, char **dev_out)
+static int pty_open(int input, int output, int primary, void *d,
+		    char **dev_out)
 {
 	struct pty_chan *data = d;
 	int fd, err;
@@ -115,7 +117,7 @@
 	return(fd);
 }
 
-int pty_console_write(int fd, const char *buf, int n, void *d)
+static int pty_console_write(int fd, const char *buf, int n, void *d)
 {
 	struct pty_chan *data = d;
 
diff -Nru a/arch/um/drivers/random.c b/arch/um/drivers/random.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/um/drivers/random.c	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,122 @@
+/* Much of this ripped from hw_random.c */
+
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/miscdevice.h>
+#include <linux/delay.h>
+#include <asm/uaccess.h>
+#include "os.h"
+
+/*
+ * core module and version information
+ */
+#define RNG_VERSION "1.0.0"
+#define RNG_MODULE_NAME "random"
+#define RNG_DRIVER_NAME   RNG_MODULE_NAME " virtual driver " RNG_VERSION
+#define PFX RNG_MODULE_NAME ": "
+
+#define RNG_MISCDEV_MINOR		183 /* official */
+
+static int random_fd = -1;
+
+static int rng_dev_open (struct inode *inode, struct file *filp)
+{
+	/* enforce read-only access to this chrdev */
+	if ((filp->f_mode & FMODE_READ) == 0)
+		return -EINVAL;
+	if (filp->f_mode & FMODE_WRITE)
+		return -EINVAL;
+
+	return 0;
+}
+
+static ssize_t rng_dev_read (struct file *filp, char __user *buf, size_t size,
+                             loff_t * offp)
+{
+        u32 data;
+        int n, ret = 0, have_data;
+
+        while(size){
+                n = os_read_file(random_fd, &data, sizeof(data));
+                if(n > 0){
+                        have_data = n;
+                        while (have_data && size) {
+                                if (put_user((u8)data, buf++)) {
+                                        ret = ret ? : -EFAULT;
+                                        break;
+                                }
+                                size--;
+                                ret++;
+                                have_data--;
+                                data>>=8;
+                        }
+                }
+                else if(n == -EAGAIN){
+                        if (filp->f_flags & O_NONBLOCK)
+                                return ret ? : -EAGAIN;
+
+                        if(need_resched()){
+                                current->state = TASK_INTERRUPTIBLE;
+                                schedule_timeout(1);
+                        }
+                }
+                else return n;
+		if (signal_pending (current))
+			return ret ? : -ERESTARTSYS;
+	}
+	return ret;
+}
+
+static struct file_operations rng_chrdev_ops = {
+	.owner		= THIS_MODULE,
+	.open		= rng_dev_open,
+	.read		= rng_dev_read,
+};
+
+static struct miscdevice rng_miscdev = {
+	RNG_MISCDEV_MINOR,
+	RNG_MODULE_NAME,
+	&rng_chrdev_ops,
+};
+
+/*
+ * rng_init - initialize RNG module
+ */
+static int __init rng_init (void)
+{
+	int err;
+
+        err = os_open_file("/dev/random", of_read(OPENFLAGS()), 0);
+        if(err < 0)
+                goto out;
+
+        random_fd = err;
+
+        err = os_set_fd_block(random_fd, 0);
+        if(err)
+		goto err_out_cleanup_hw;
+
+	err = misc_register (&rng_miscdev);
+	if (err) {
+		printk (KERN_ERR PFX "misc device register failed\n");
+		goto err_out_cleanup_hw;
+	}
+
+ out:
+        return err;
+
+ err_out_cleanup_hw:
+        random_fd = -1;
+        goto out;
+}
+
+/*
+ * rng_cleanup - shutdown RNG module
+ */
+static void __exit rng_cleanup (void)
+{
+	misc_deregister (&rng_miscdev);
+}
+
+module_init (rng_init);
+module_exit (rng_cleanup);
diff -Nru a/arch/um/drivers/slirp_kern.c b/arch/um/drivers/slirp_kern.c
--- a/arch/um/drivers/slirp_kern.c	2005-03-11 12:51:51 -08:00
+++ b/arch/um/drivers/slirp_kern.c	2005-03-11 12:51:51 -08:00
@@ -33,8 +33,11 @@
 
 	dev->init = NULL;
 	dev->hard_header_len = 0;
-	dev->addr_len = 4;
-	dev->type = ARPHRD_ETHER;
+	dev->header_cache_update = NULL;
+	dev->hard_header_cache = NULL;
+	dev->hard_header = NULL;
+	dev->addr_len = 0;
+	dev->type = ARPHRD_SLIP;
 	dev->tx_queue_len = 256;
 	dev->flags = IFF_NOARP;
 	printk("SLIRP backend - command line:");
diff -Nru a/arch/um/drivers/tty.c b/arch/um/drivers/tty.c
--- a/arch/um/drivers/tty.c	2005-03-11 12:51:42 -08:00
+++ b/arch/um/drivers/tty.c	2005-03-11 12:51:42 -08:00
@@ -18,7 +18,7 @@
 	struct termios tt;
 };
 
-void *tty_chan_init(char *str, int device, struct chan_opts *opts)
+static void *tty_chan_init(char *str, int device, struct chan_opts *opts)
 {
 	struct tty_chan *data;
 
@@ -38,7 +38,8 @@
 	return(data);
 }
 
-int tty_open(int input, int output, int primary, void *d, char **dev_out)
+static int tty_open(int input, int output, int primary, void *d,
+		    char **dev_out)
 {
 	struct tty_chan *data = d;
 	int fd, err;
@@ -59,7 +60,7 @@
 	return(fd);
 }
 
-int tty_console_write(int fd, const char *buf, int n, void *d)
+static int tty_console_write(int fd, const char *buf, int n, void *d)
 {
 	struct tty_chan *data = d;
 
diff -Nru a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c
--- a/arch/um/drivers/ubd_kern.c	2005-03-11 12:51:46 -08:00
+++ b/arch/um/drivers/ubd_kern.c	2005-03-11 12:51:46 -08:00
@@ -453,6 +453,22 @@
 "    an 's' will cause data to be written to disk on the host immediately.\n\n"
 );
 
+static int udb_setup(char *str)
+{
+	printk("udb%s specified on command line is almost certainly a ubd -> "
+	       "udb TYPO\n", str);
+	return(1);
+}
+
+__setup("udb", udb_setup);
+__uml_help(udb_setup,
+"udb\n"
+"    This option is here solely to catch ubd -> udb typos, which can be\n\n"
+"    to impossible to catch visually unless you specifically look for\n\n"
+"    them.  The only result of any option starting with 'udb' is an error\n\n"
+"    in the boot output.\n\n"
+);
+
 static int fakehd_set = 0;
 static int fakehd(char *str)
 {
@@ -605,7 +621,11 @@
 		}
 	}
 
-	if(dev->fd < 0) return(dev->fd);
+	if(dev->fd < 0){
+		printk("Failed to open '%s', errno = %d\n", dev->file,
+		       -dev->fd);
+		return(dev->fd);
+	}
 
 	if(dev->cow.file != NULL){
 		err = -ENOMEM;
@@ -746,15 +766,9 @@
 static int ubd_get_config(char *name, char *str, int size, char **error_out)
 {
 	struct ubd *dev;
-	char *end;
 	int n, len = 0;
 
-	n = simple_strtoul(name, &end, 0);
-	if((*end != '\0') || (end == name)){
-		*error_out = "ubd_get_config : didn't parse device number";
-		return(-1);
-	}
-
+	n = parse_unit(&name);
 	if((n >= MAX_DEV) || (n < 0)){
 		*error_out = "ubd_get_config : device number out of range";
 		return(-1);
diff -Nru a/arch/um/drivers/xterm.c b/arch/um/drivers/xterm.c
--- a/arch/um/drivers/xterm.c	2005-03-11 12:51:41 -08:00
+++ b/arch/um/drivers/xterm.c	2005-03-11 12:51:41 -08:00
@@ -31,6 +31,7 @@
 	int direct_rcv;
 };
 
+/* Not static because it's called directly by the tt mode gdb code */
 void *xterm_init(char *str, int device, struct chan_opts *opts)
 {
 	struct xterm_chan *data;
@@ -83,8 +84,11 @@
 "    are 'xterm=gnome-terminal,-t,-x'.\n\n"
 );
 
-/* XXX This badly needs some cleaning up in the error paths */
-int xterm_open(int input, int output, int primary, void *d, char **dev_out)
+/* XXX This badly needs some cleaning up in the error paths
+ * Not static because it's called directly by the tt mode gdb code
+ */
+int xterm_open(int input, int output, int primary, void *d,
+		      char **dev_out)
 {
 	struct xterm_chan *data = d;
 	unsigned long stack;
@@ -170,6 +174,7 @@
 	return(new);
 }
 
+/* Not static because it's called directly by the tt mode gdb code */
 void xterm_close(int fd, void *d)
 {
 	struct xterm_chan *data = d;
@@ -183,12 +188,12 @@
 	os_close_file(fd);
 }
 
-void xterm_free(void *d)
+static void xterm_free(void *d)
 {
 	free(d);
 }
 
-int xterm_console_write(int fd, const char *buf, int n, void *d)
+static int xterm_console_write(int fd, const char *buf, int n, void *d)
 {
 	struct xterm_chan *data = d;
 
diff -Nru a/arch/um/drivers/xterm_kern.c b/arch/um/drivers/xterm_kern.c
--- a/arch/um/drivers/xterm_kern.c	2005-03-11 12:51:47 -08:00
+++ b/arch/um/drivers/xterm_kern.c	2005-03-11 12:51:47 -08:00
@@ -16,7 +16,7 @@
 #include "xterm.h"
 
 struct xterm_wait {
-	struct semaphore sem;
+	struct completion ready;
 	int fd;
 	int pid;
 	int new_fd;
@@ -32,7 +32,7 @@
 		return(IRQ_NONE);
 
 	xterm->new_fd = fd;
-	up(&xterm->sem);
+	complete(&xterm->ready);
 	return(IRQ_HANDLED);
 }
 
@@ -49,10 +49,10 @@
 
 	/* This is a locked semaphore... */
 	*data = ((struct xterm_wait) 
-		{ .sem  	= __SEMAPHORE_INITIALIZER(data->sem, 0),
-		  .fd 		= socket,
+		{ .fd 		= socket,
 		  .pid 		= -1,
 		  .new_fd 	= -1 });
+	init_completion(&data->ready);
 
 	err = um_request_irq(XTERM_IRQ, socket, IRQ_READ, xterm_interrupt, 
 			     SA_INTERRUPT | SA_SHIRQ | SA_SAMPLE_RANDOM, 
@@ -68,7 +68,7 @@
 	 *
 	 * XXX Note, if the xterm doesn't work for some reason (eg. DISPLAY
 	 * isn't set) this will hang... */
-	down(&data->sem);
+	wait_for_completion(&data->ready);
 
 	free_irq_by_irq_and_dev(XTERM_IRQ, data);
 	free_irq(XTERM_IRQ, data);
diff -Nru a/arch/um/include/kern.h b/arch/um/include/kern.h
--- a/arch/um/include/kern.h	2005-03-11 12:51:52 -08:00
+++ b/arch/um/include/kern.h	2005-03-11 12:51:52 -08:00
@@ -26,6 +26,7 @@
 extern void perror(char *err);
 extern int kill(int pid, int sig);
 extern int getuid(void);
+extern int getgid(void);
 extern int pause(void);
 extern int write(int, const void *, int);
 extern int exit(int);
diff -Nru a/arch/um/include/registers.h b/arch/um/include/registers.h
--- a/arch/um/include/registers.h	2005-03-11 12:51:42 -08:00
+++ b/arch/um/include/registers.h	2005-03-11 12:51:42 -08:00
@@ -9,6 +9,8 @@
 #include "sysdep/ptrace.h"
 
 extern void init_thread_registers(union uml_pt_regs *to);
+extern int save_fp_registers(int pid, unsigned long *fp_regs);
+extern int restore_fp_registers(int pid, unsigned long *fp_regs);
 extern void save_registers(int pid, union uml_pt_regs *regs);
 extern void restore_registers(int pid, union uml_pt_regs *regs);
 extern void init_registers(int pid);
diff -Nru a/arch/um/include/sysdep-i386/ptrace.h b/arch/um/include/sysdep-i386/ptrace.h
--- a/arch/um/include/sysdep-i386/ptrace.h	2005-03-11 12:51:41 -08:00
+++ b/arch/um/include/sysdep-i386/ptrace.h	2005-03-11 12:51:41 -08:00
@@ -7,6 +7,7 @@
 #define __SYSDEP_I386_PTRACE_H
 
 #include "uml-config.h"
+#include "user_constants.h"
 
 #ifdef UML_CONFIG_MODE_TT
 #include "sysdep/sc.h"
@@ -14,6 +15,9 @@
 
 #ifdef UML_CONFIG_MODE_SKAS
 
+#define MAX_REG_NR (UM_FRAME_SIZE / sizeof(unsigned long))
+#define MAX_REG_OFFSET (UM_FRAME_SIZE)
+
 /* syscall emulation path in ptrace */
 
 #ifndef PTRACE_SYSEMU
@@ -26,7 +30,7 @@
 
 #include "skas_ptregs.h"
 
-#define HOST_FRAME_SIZE 17
+extern void update_debugregs(int seq);
 
 #define REGS_IP(r) ((r)[HOST_IP])
 #define REGS_SP(r) ((r)[HOST_SP])
diff -Nru a/arch/um/include/sysdep-i386/ptrace_user.h b/arch/um/include/sysdep-i386/ptrace_user.h
--- a/arch/um/include/sysdep-i386/ptrace_user.h	2005-03-11 12:51:51 -08:00
+++ b/arch/um/include/sysdep-i386/ptrace_user.h	2005-03-11 12:51:51 -08:00
@@ -6,6 +6,8 @@
 #ifndef __SYSDEP_I386_PTRACE_USER_H__
 #define __SYSDEP_I386_PTRACE_USER_H__
 
+#include <sys/ptrace.h>
+#include <linux/ptrace.h>
 #include <asm/ptrace.h>
 
 #define PT_OFFSET(r) ((r) * sizeof(long))
@@ -33,9 +35,6 @@
 #define FP_FRAME_SIZE (27)
 #define FPX_FRAME_SIZE (128)
 
-#define MAX_REG_OFFSET (FRAME_SIZE_OFFSET)
-#define MAX_REG_NR (FRAME_SIZE)
-
 #ifdef PTRACE_GETREGS
 #define UM_HAVE_GETREGS
 #endif
@@ -59,7 +58,5 @@
 #ifdef PTRACE_SETFPXREGS
 #define UM_HAVE_SETFPXREGS
 #endif
-
-extern void update_debugregs(int seq);
 
 #endif
diff -Nru a/arch/um/include/sysdep-x86_64/checksum.h b/arch/um/include/sysdep-x86_64/checksum.h
--- a/arch/um/include/sysdep-x86_64/checksum.h	2005-03-11 12:51:42 -08:00
+++ b/arch/um/include/sysdep-x86_64/checksum.h	2005-03-11 12:51:42 -08:00
@@ -9,7 +9,7 @@
 #include "linux/in6.h"
 #include "asm/uaccess.h"
 
-extern unsigned int csum_partial_copy_from(const char *src, char *dst, int len,
+extern unsigned int csum_partial_copy_from(const unsigned char *src, unsigned char *dst, int len,
 					   int sum, int *err_ptr);
 extern unsigned csum_partial(const unsigned char *buff, unsigned len,
                              unsigned sum);
@@ -23,7 +23,7 @@
  */
 
 static __inline__
-unsigned int csum_partial_copy_nocheck(const char *src, char *dst,
+unsigned int csum_partial_copy_nocheck(const unsigned char *src, unsigned char *dst,
 				       int len, int sum)
 {
 	memcpy(dst, src, len);
@@ -31,7 +31,7 @@
 }
 
 static __inline__
-unsigned int csum_partial_copy_from_user(const char *src, char *dst,
+unsigned int csum_partial_copy_from_user(const unsigned char *src, unsigned char *dst,
 					 int len, int sum, int *err_ptr)
 {
 	return csum_partial_copy_from(src, dst, len, sum, err_ptr);
diff -Nru a/arch/um/include/sysdep-x86_64/ptrace.h b/arch/um/include/sysdep-x86_64/ptrace.h
--- a/arch/um/include/sysdep-x86_64/ptrace.h	2005-03-11 12:51:51 -08:00
+++ b/arch/um/include/sysdep-x86_64/ptrace.h	2005-03-11 12:51:51 -08:00
@@ -8,6 +8,7 @@
 #define __SYSDEP_X86_64_PTRACE_H
 
 #include "uml-config.h"
+#include "user_constants.h"
 
 #ifdef UML_CONFIG_MODE_TT
 #include "sysdep/sc.h"
@@ -15,6 +16,9 @@
 
 #ifdef UML_CONFIG_MODE_SKAS
 #include "skas_ptregs.h"
+
+#define MAX_REG_OFFSET (UM_FRAME_SIZE)
+#define MAX_REG_NR ((MAX_REG_OFFSET) / sizeof(unsigned long))
 
 #define REGS_IP(r) ((r)[HOST_IP])
 #define REGS_SP(r) ((r)[HOST_SP])
diff -Nru a/arch/um/include/sysdep-x86_64/ptrace_user.h b/arch/um/include/sysdep-x86_64/ptrace_user.h
--- a/arch/um/include/sysdep-x86_64/ptrace_user.h	2005-03-11 12:51:41 -08:00
+++ b/arch/um/include/sysdep-x86_64/ptrace_user.h	2005-03-11 12:51:41 -08:00
@@ -8,6 +8,8 @@
 #define __SYSDEP_X86_64_PTRACE_USER_H__
 
 #define __FRAME_OFFSETS
+#include <sys/ptrace.h>
+#include <linux/ptrace.h>
 #include <asm/ptrace.h>
 #undef __FRAME_OFFSETS
 
@@ -44,9 +46,6 @@
 
 #define PT_ORIG_RAX_OFFSET (ORIG_RAX)
 #define PT_ORIG_RAX(regs) ((regs)[PT_INDEX(ORIG_RAX)])
-
-#define MAX_REG_OFFSET (FRAME_SIZE)
-#define MAX_REG_NR ((MAX_REG_OFFSET) / sizeof(unsigned long))
 
 /* x86_64 FC3 doesn't define this in /usr/include/linux/ptrace.h even though
  * it's defined in the kernel's include/linux/ptrace.h. Additionally, use the
diff -Nru a/arch/um/include/tlb.h b/arch/um/include/tlb.h
--- a/arch/um/include/tlb.h	2005-03-11 12:51:42 -08:00
+++ b/arch/um/include/tlb.h	2005-03-11 12:51:42 -08:00
@@ -6,9 +6,53 @@
 #ifndef __TLB_H__
 #define __TLB_H__
 
+#include "um_mmu.h"
+
+struct host_vm_op {
+	enum { MMAP, MUNMAP, MPROTECT } type;
+	union {
+		struct {
+			unsigned long addr;
+			unsigned long len;
+			unsigned int r:1;
+			unsigned int w:1;
+			unsigned int x:1;
+			int fd;
+			__u64 offset;
+		} mmap;
+		struct {
+			unsigned long addr;
+			unsigned long len;
+		} munmap;
+		struct {
+			unsigned long addr;
+			unsigned long len;
+			unsigned int r:1;
+			unsigned int w:1;
+			unsigned int x:1;
+		} mprotect;
+	} u;
+};
+
 extern void mprotect_kernel_vm(int w);
 extern void force_flush_all(void);
+extern void fix_range_common(struct mm_struct *mm, unsigned long start_addr,
+			     unsigned long end_addr, int force, int data,
+			     void (*do_ops)(int, struct host_vm_op *, int));
+extern int flush_tlb_kernel_range_common(unsigned long start,
+					 unsigned long end);
 
+extern int add_mmap(unsigned long virt, unsigned long phys, unsigned long len,
+		    int r, int w, int x, struct host_vm_op *ops, int index,
+		    int last_filled, int data,
+		    void (*do_ops)(int, struct host_vm_op *, int));
+extern int add_munmap(unsigned long addr, unsigned long len,
+		      struct host_vm_op *ops, int index, int last_filled,
+		      int data, void (*do_ops)(int, struct host_vm_op *, int));
+extern int add_mprotect(unsigned long addr, unsigned long len, int r, int w,
+			int x, struct host_vm_op *ops, int index,
+			int last_filled, int data,
+			void (*do_ops)(int, struct host_vm_op *, int));
 #endif
 
 /*
diff -Nru a/arch/um/include/um_mmu.h b/arch/um/include/um_mmu.h
--- a/arch/um/include/um_mmu.h	2005-03-11 12:51:47 -08:00
+++ b/arch/um/include/um_mmu.h	2005-03-11 12:51:47 -08:00
@@ -6,22 +6,22 @@
 #ifndef __ARCH_UM_MMU_H
 #define __ARCH_UM_MMU_H
 
-#include "linux/config.h"
+#include "uml-config.h"
 #include "choose-mode.h"
 
-#ifdef CONFIG_MODE_TT
+#ifdef UML_CONFIG_MODE_TT
 #include "mmu-tt.h"
 #endif
 
-#ifdef CONFIG_MODE_SKAS
+#ifdef UML_CONFIG_MODE_SKAS
 #include "mmu-skas.h"
 #endif
 
-typedef union {
-#ifdef CONFIG_MODE_TT
+typedef union mm_context {
+#ifdef UML_CONFIG_MODE_TT
 	struct mmu_context_tt tt;
 #endif
-#ifdef CONFIG_MODE_SKAS
+#ifdef UML_CONFIG_MODE_SKAS
 	struct mmu_context_skas skas;
 #endif
 } mm_context_t;
diff -Nru a/arch/um/kernel/Makefile b/arch/um/kernel/Makefile
--- a/arch/um/kernel/Makefile	2005-03-11 12:51:47 -08:00
+++ b/arch/um/kernel/Makefile	2005-03-11 12:51:47 -08:00
@@ -4,20 +4,21 @@
 #
 
 extra-y := vmlinux.lds
-clean-files := vmlinux.lds.S
+clean-files := vmlinux.lds.S config.tmp
 
 obj-y = checksum.o config.o exec_kern.o exitcode.o \
 	helper.o init_task.o irq.o irq_user.o ksyms.o main.o mem.o mem_user.o \
 	physmem.o process.o process_kern.o ptrace.o reboot.o resource.o \
 	sigio_user.o sigio_kern.o signal_kern.o signal_user.o smp.o \
-	syscall_kern.o syscall_user.o sysrq.o sys_call_table.o tempfile.o \
-	time.o time_kern.o tlb.o trap_kern.o trap_user.o uaccess_user.o \
-	um_arch.o umid.o user_util.o
+	syscall_kern.o sysrq.o sys_call_table.o tempfile.o time.o time_kern.o \
+	tlb.o trap_kern.o trap_user.o uaccess_user.o um_arch.o umid.o \
+	user_util.o
 
 obj-$(CONFIG_BLK_DEV_INITRD) += initrd_kern.o initrd_user.o
 obj-$(CONFIG_GPROF)	+= gprof_syms.o
 obj-$(CONFIG_GCOV)	+= gmon_syms.o
 obj-$(CONFIG_TTY_LOG)	+= tty_log.o
+obj-$(CONFIG_SYSCALL_DEBUG) += syscall_user.o
 
 obj-$(CONFIG_MODE_TT) += tt/
 obj-$(CONFIG_MODE_SKAS) += skas/
@@ -33,11 +34,25 @@
 $(USER_OBJS) : %.o: %.c
 	$(CC) $(USER_CFLAGS) $(CFLAGS_$(notdir $@)) -c -o $@ $<
 
-QUOTE = 'my $$config=`cat $(TOPDIR)/.config`; $$config =~ s/"/\\"/g ; $$config =~ s/\n/\\n"\n"/g ; while(<STDIN>) { $$_ =~ s/CONFIG/$$config/; print $$_ }'
+targets += config.c
 
-quiet_cmd_quote = QUOTE   $@
-cmd_quote = $(PERL) -e $(QUOTE) < $< > $@
+# Be careful with the below Sed code - sed is pitfall-rich!
+# We use sed to lower build requirements, for "embedded" builders for instance.
 
-targets += config.c
-$(obj)/config.c : $(src)/config.c.in $(TOPDIR)/.config FORCE
-	$(call if_changed,quote)
+$(obj)/config.tmp: $(objtree)/.config FORCE
+	$(call if_changed,quote1)
+
+quiet_cmd_quote1 = QUOTE   $@
+      cmd_quote1 = sed -e 's/"/\\"/g' -e 's/^/"/' -e 's/$$/\\n"/' \
+		   $< > $@
+
+$(obj)/config.c: $(src)/config.c.in $(obj)/config.tmp FORCE
+	$(call if_changed,quote2)
+
+quiet_cmd_quote2 = QUOTE   $@
+      cmd_quote2 = sed -e '/CONFIG/{'          \
+		  -e 's/"CONFIG"\;/""/'        \
+		  -e 'r $(obj)/config.tmp'     \
+		  -e 'a""\;'                   \
+		  -e '}'                       \
+		  $< > $@
diff -Nru a/arch/um/kernel/checksum.c b/arch/um/kernel/checksum.c
--- a/arch/um/kernel/checksum.c	2005-03-11 12:51:47 -08:00
+++ b/arch/um/kernel/checksum.c	2005-03-11 12:51:47 -08:00
@@ -6,40 +6,31 @@
 
 unsigned int csum_partial(unsigned char *buff, int len, int sum)
 {
-	return arch_csum_partial(buff, len, sum);
+        return arch_csum_partial(buff, len, sum);
 }
 
 EXPORT_SYMBOL(csum_partial);
 
-unsigned int csum_partial_copy_to(const unsigned char *src, char __user *dst,
-				int len, int sum, int *err_ptr)
+unsigned int csum_partial_copy_to(const unsigned char *src,
+                                  unsigned char __user *dst, int len, int sum,
+                                  int *err_ptr)
 {
-	if(copy_to_user(dst, src, len)){
-		*err_ptr = -EFAULT;
-		return(-1);
-	}
+        if(copy_to_user(dst, src, len)){
+                *err_ptr = -EFAULT;
+                return(-1);
+        }
 
-	return(arch_csum_partial(src, len, sum));
+        return(arch_csum_partial(src, len, sum));
 }
 
-unsigned int csum_partial_copy_from(const unsigned char __user *src, char *dst,
-				int len, int sum, int *err_ptr)
+unsigned int csum_partial_copy_from(const unsigned char __user *src,
+                                    unsigned char *dst,	int len, int sum,
+                                    int *err_ptr)
 {
-	if(copy_from_user(dst, src, len)){
-		*err_ptr = -EFAULT;
-		return(-1);
-	}
+        if(copy_from_user(dst, src, len)){
+                *err_ptr = -EFAULT;
+                return(-1);
+        }
 
-	return arch_csum_partial(dst, len, sum);
+        return arch_csum_partial(dst, len, sum);
 }
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff -Nru a/arch/um/kernel/gmon_syms.c b/arch/um/kernel/gmon_syms.c
--- a/arch/um/kernel/gmon_syms.c	2005-03-11 12:51:51 -08:00
+++ b/arch/um/kernel/gmon_syms.c	2005-03-11 12:51:51 -08:00
@@ -5,8 +5,14 @@
 
 #include "linux/module.h"
 
+#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ > 3) || \
+	(__GNUC__ == 3 && __GNUC_MINOR__ == 3 && __GNUC_PATCHLEVEL__ >= 4)
+extern void __gcov_init(void *);
+EXPORT_SYMBOL(__gcov_init);
+#else
 extern void __bb_init_func(void *);
 EXPORT_SYMBOL(__bb_init_func);
+#endif
 
 /*
  * Overrides for Emacs so that we follow Linus's tabbing style.
diff -Nru a/arch/um/kernel/process.c b/arch/um/kernel/process.c
--- a/arch/um/kernel/process.c	2005-03-11 12:51:51 -08:00
+++ b/arch/um/kernel/process.c	2005-03-11 12:51:51 -08:00
@@ -12,11 +12,6 @@
 #include <stdlib.h>
 #include <setjmp.h>
 #include <sys/time.h>
-#include <sys/ptrace.h>
-
-/*Userspace header, must be after sys/ptrace.h, and both must be included. */
-#include <linux/ptrace.h>
-
 #include <sys/wait.h>
 #include <sys/mman.h>
 #include <asm/unistd.h>
@@ -28,7 +23,6 @@
 #include "signal_kern.h"
 #include "signal_user.h"
 #include "sysdep/ptrace.h"
-#include "sysdep/ptrace_user.h"
 #include "sysdep/sigcontext.h"
 #include "irq_user.h"
 #include "ptrace_user.h"
@@ -36,6 +30,7 @@
 #include "init.h"
 #include "os.h"
 #include "uml-config.h"
+#include "ptrace_user.h"
 #include "choose-mode.h"
 #include "mode.h"
 #ifdef UML_CONFIG_MODE_SKAS
@@ -259,7 +254,7 @@
 		panic("check_sysemu : expected SIGTRAP, "
 		      "got status = %d", status);
 
-	n = ptrace(PTRACE_POKEUSER, pid, PT_SYSCALL_RET_OFFSET,
+	n = ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_RET_OFFSET,
 		   os_getpid());
 	if(n < 0)
 		panic("check_sysemu : failed to modify system "
@@ -285,12 +280,12 @@
 			panic("check_ptrace : expected (SIGTRAP|SYSCALL_TRAP), "
 			      "got status = %d", status);
 
-		syscall = ptrace(PTRACE_PEEKUSER, pid, PT_SYSCALL_NR_OFFSET,
+		syscall = ptrace(PTRACE_PEEKUSR, pid, PT_SYSCALL_NR_OFFSET,
 				 0);
 		if(syscall == __NR_getpid){
 			if (!count)
 				panic("check_ptrace : SYSEMU_SINGLESTEP doesn't singlestep");
-			n = ptrace(PTRACE_POKEUSER, pid, PT_SYSCALL_RET_OFFSET,
+			n = ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_RET_OFFSET,
 				   os_getpid());
 			if(n < 0)
 				panic("check_sysemu : failed to modify system "
@@ -336,10 +331,10 @@
 			panic("check_ptrace : expected SIGTRAP + 0x80, "
 			      "got status = %d", status);
 		
-		syscall = ptrace(PTRACE_PEEKUSER, pid, PT_SYSCALL_NR_OFFSET,
+		syscall = ptrace(PTRACE_PEEKUSR, pid, PT_SYSCALL_NR_OFFSET,
 				 0);
 		if(syscall == __NR_getpid){
-			n = ptrace(PTRACE_POKEUSER, pid, PT_SYSCALL_NR_OFFSET,
+			n = ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_NR_OFFSET,
 				   __NR_getppid);
 			if(n < 0)
 				panic("check_ptrace : failed to modify system "
diff -Nru a/arch/um/kernel/process_kern.c b/arch/um/kernel/process_kern.c
--- a/arch/um/kernel/process_kern.c	2005-03-11 12:51:46 -08:00
+++ b/arch/um/kernel/process_kern.c	2005-03-11 12:51:46 -08:00
@@ -21,6 +21,7 @@
 #include "linux/spinlock.h"
 #include "linux/proc_fs.h"
 #include "linux/ptrace.h"
+#include "linux/random.h"
 #include "asm/unistd.h"
 #include "asm/mman.h"
 #include "asm/segment.h"
@@ -478,6 +479,14 @@
 
 	return 2;
 }
+
+unsigned long arch_align_stack(unsigned long sp)
+{
+	if (randomize_va_space)
+		sp -= get_random_int() % 8192;
+	return sp & ~0xf;
+}
+
 
 /*
  * Overrides for Emacs so that we follow Linus's tabbing style.
diff -Nru a/arch/um/kernel/ptrace.c b/arch/um/kernel/ptrace.c
--- a/arch/um/kernel/ptrace.c	2005-03-11 12:51:52 -08:00
+++ b/arch/um/kernel/ptrace.c	2005-03-11 12:51:52 -08:00
@@ -15,8 +15,8 @@
 #include "asm/ptrace.h"
 #include "asm/uaccess.h"
 #include "kern_util.h"
-#include "ptrace_user.h"
 #include "skas_ptrace.h"
+#include "sysdep/ptrace.h"
 
 /*
  * Called by kernel/ptrace.c when detaching..
diff -Nru a/arch/um/kernel/skas/include/skas.h b/arch/um/kernel/skas/include/skas.h
--- a/arch/um/kernel/skas/include/skas.h	2005-03-11 12:51:42 -08:00
+++ b/arch/um/kernel/skas/include/skas.h	2005-03-11 12:51:42 -08:00
@@ -22,14 +22,15 @@
 extern void remove_sigstack(void);
 extern void new_thread_handler(int sig);
 extern void handle_syscall(union uml_pt_regs *regs);
-extern void map(int fd, unsigned long virt, unsigned long phys, 
-		unsigned long len, int r, int w, int x);
-extern int unmap(int fd, void *addr, int len);
+extern void map(int fd, unsigned long virt, unsigned long len, int r, int w,
+		int x, int phys_fd, unsigned long long offset);
+extern int unmap(int fd, void *addr, unsigned long len);
 extern int protect(int fd, unsigned long addr, unsigned long len, 
-		   int r, int w, int x, int must_succeed);
+		   int r, int w, int x);
 extern void user_signal(int sig, union uml_pt_regs *regs);
 extern int new_mm(int from);
 extern void start_userspace(int cpu);
+extern long execute_syscall_skas(void *r);
 
 #endif
 
diff -Nru a/arch/um/kernel/skas/mem_user.c b/arch/um/kernel/skas/mem_user.c
--- a/arch/um/kernel/skas/mem_user.c	2005-03-11 12:51:42 -08:00
+++ b/arch/um/kernel/skas/mem_user.c	2005-03-11 12:51:42 -08:00
@@ -5,23 +5,20 @@
 
 #include <errno.h>
 #include <sys/mman.h>
-#include <sys/ptrace.h>
 #include "mem_user.h"
 #include "mem.h"
 #include "user.h"
 #include "os.h"
 #include "proc_mm.h"
 
-void map(int fd, unsigned long virt, unsigned long phys, unsigned long len, 
-	 int r, int w, int x)
+void map(int fd, unsigned long virt, unsigned long len, int r, int w,
+	 int x, int phys_fd, unsigned long long offset)
 {
 	struct proc_mm_op map;
-	__u64 offset;
-	int prot, n, phys_fd;
+	int prot, n;
 
 	prot = (r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) | 
 		(x ? PROT_EXEC : 0);
-	phys_fd = phys_mapping(phys, &offset);
 
 	map = ((struct proc_mm_op) { .op 	= MM_MMAP,
 				     .u 	= 
@@ -39,7 +36,7 @@
 		printk("map : /proc/mm map failed, err = %d\n", -n);
 }
 
-int unmap(int fd, void *addr, int len)
+int unmap(int fd, void *addr, unsigned long len)
 {
 	struct proc_mm_op unmap;
 	int n;
diff -Nru a/arch/um/kernel/skas/process.c b/arch/um/kernel/skas/process.c
--- a/arch/um/kernel/skas/process.c	2005-03-11 12:51:51 -08:00
+++ b/arch/um/kernel/skas/process.c	2005-03-11 12:51:51 -08:00
@@ -10,8 +10,6 @@
 #include <setjmp.h>
 #include <sched.h>
 #include <sys/wait.h>
-#include <sys/ptrace.h>
-#include <linux/ptrace.h>
 #include <sys/mman.h>
 #include <sys/user.h>
 #include <asm/unistd.h>
@@ -62,7 +60,7 @@
 
 	if (!local_using_sysemu)
 	{
-		err = ptrace(PTRACE_POKEUSER, pid, PT_SYSCALL_NR_OFFSET, __NR_getpid);
+		err = ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_NR_OFFSET, __NR_getpid);
 		if(err < 0)
 			panic("handle_trap - nullifying syscall failed errno = %d\n",
 			      errno);
@@ -139,17 +137,20 @@
 	int err, status, op, pid = userspace_pid[0];
 	int local_using_sysemu; /*To prevent races if using_sysemu changes under us.*/
 
-	restore_registers(pid, regs);
-		
-	local_using_sysemu = get_using_sysemu();
+	while(1){
+		restore_registers(pid, regs);
 
-	op = local_using_sysemu ? PTRACE_SYSEMU : PTRACE_SYSCALL;
-	err = ptrace(op, pid, 0, 0);
+		/* Now we set local_using_sysemu to be used for one loop */
+		local_using_sysemu = get_using_sysemu();
+
+		op = SELECT_PTRACE_OPERATION(local_using_sysemu, singlestepping(NULL));
+
+		err = ptrace(op, pid, 0, 0);
+		if(err)
+			panic("userspace - could not resume userspace process, "
+			      "pid=%d, ptrace operation = %d, errno = %d\n",
+			      op, errno);
 
-	if(err)
-		panic("userspace - PTRACE_%s failed, errno = %d\n",
-		       local_using_sysemu ? "SYSEMU" : "SYSCALL", errno);
-	while(1){
 		CATCH_EINTR(err = waitpid(pid, &status, WUNTRACED));
 		if(err < 0)
 			panic("userspace - waitpid failed, errno = %d\n", 
@@ -187,19 +188,6 @@
 			/* Avoid -ERESTARTSYS handling in host */
 			PT_SYSCALL_NR(regs->skas.regs) = -1;
 		}
-
-		restore_registers(pid, regs);
-
-		/*Now we ended the syscall, so re-read local_using_sysemu.*/
-		local_using_sysemu = get_using_sysemu();
-
-		op = SELECT_PTRACE_OPERATION(local_using_sysemu, singlestepping(NULL));
-
-		err = ptrace(op, pid, 0, 0);
-		if(err)
-			panic("userspace - PTRACE_%s failed, "
-			      "errno = %d\n",
-			      local_using_sysemu ? "SYSEMU" : "SYSCALL", errno);
 	}
 }
 
diff -Nru a/arch/um/kernel/skas/syscall_user.c b/arch/um/kernel/skas/syscall_user.c
--- a/arch/um/kernel/skas/syscall_user.c	2005-03-11 12:51:51 -08:00
+++ b/arch/um/kernel/skas/syscall_user.c	2005-03-11 12:51:51 -08:00
@@ -6,25 +6,30 @@
 #include <stdlib.h>
 #include <signal.h>
 #include "kern_util.h"
+#include "uml-config.h"
 #include "syscall_user.h"
 #include "sysdep/ptrace.h"
 #include "sysdep/sigcontext.h"
-
+#include "skas.h"
 
 void handle_syscall(union uml_pt_regs *regs)
 {
 	long result;
-	int index;
+#if UML_CONFIG_SYSCALL_DEBUG
+  	int index;
 
-	index = record_syscall_start(UPT_SYSCALL_NR(regs));
+  	index = record_syscall_start(UPT_SYSCALL_NR(regs));
+#endif
 
 	syscall_trace(regs, 0);
-	result = execute_syscall(regs);
+	result = execute_syscall_skas(regs);
 
 	REGS_SET_SYSCALL_RETURN(regs->skas.regs, result);
 
 	syscall_trace(regs, 1);
-	record_syscall_end(index, result);
+#if UML_CONFIG_SYSCALL_DEBUG
+  	record_syscall_end(index, result);
+#endif
 }
 
 /*
diff -Nru a/arch/um/kernel/skas/tlb.c b/arch/um/kernel/skas/tlb.c
--- a/arch/um/kernel/skas/tlb.c	2005-03-11 12:51:46 -08:00
+++ b/arch/um/kernel/skas/tlb.c	2005-03-11 12:51:46 -08:00
@@ -12,215 +12,74 @@
 #include "asm/mmu.h"
 #include "user_util.h"
 #include "mem_user.h"
+#include "mem.h"
 #include "skas.h"
 #include "os.h"
+#include "tlb.h"
 
-static void fix_range(struct mm_struct *mm, unsigned long start_addr,
-		      unsigned long end_addr, int force)
+static void do_ops(int fd, struct host_vm_op *ops, int last)
 {
-	pgd_t *npgd;
-	pud_t *npud;
-	pmd_t *npmd;
-	pte_t *npte;
-	unsigned long addr,  end;
-	int r, w, x, err, fd;
-
-	if(mm == NULL) return;
-	fd = mm->context.skas.mm_fd;
-	for(addr = start_addr; addr < end_addr;){
-		npgd = pgd_offset(mm, addr);
-		if(!pgd_present(*npgd)){
-			if(force || pgd_newpage(*npgd)){
-				end = addr + PGDIR_SIZE;
-				if(end > end_addr)
-					end = end_addr;
-				err = unmap(fd, (void *) addr, end - addr);
-				if(err < 0)
-					panic("munmap failed, errno = %d\n",
-					      -err);
-				pgd_mkuptodate(*npgd);
-			}
-			addr += PGDIR_SIZE;
-			continue;
-		}
-
-		npud = pud_offset(npgd, addr);
-		if(!pud_present(*npud)){
-			if(force || pud_newpage(*npud)){
-				end = addr + PUD_SIZE;
-				if(end > end_addr)
-					end = end_addr;
-				err = unmap(fd, (void *) addr, end - addr);
-				if(err < 0)
-					panic("munmap failed, errno = %d\n",
-					      -err);
-				pud_mkuptodate(*npud);
-			}
-			addr += PUD_SIZE;
-			continue;
-		}
-
-		npmd = pmd_offset(npud, addr);
-		if(!pmd_present(*npmd)){
-			if(force || pmd_newpage(*npmd)){
-				end = addr + PMD_SIZE;
-				if(end > end_addr)
-					end = end_addr;
-				err = unmap(fd, (void *) addr, end - addr);
-				if(err < 0)
-					panic("munmap failed, errno = %d\n",
-					      -err);
-				pmd_mkuptodate(*npmd);
-			}
-			addr += PMD_SIZE;
-			continue;
-		}
+	struct host_vm_op *op;
+	int i;
 
-		npte = pte_offset_kernel(npmd, addr);
-		r = pte_read(*npte);
-		w = pte_write(*npte);
-		x = pte_exec(*npte);
-		if(!pte_dirty(*npte))
-			w = 0;
-		if(!pte_young(*npte)){
-			r = 0;
-			w = 0;
-		}
-		if(force || pte_newpage(*npte)){
-			err = unmap(fd, (void *) addr, PAGE_SIZE);
-			if(err < 0)
-				panic("munmap failed, errno = %d\n", -err);
-			if(pte_present(*npte))
-				map(fd, addr, pte_val(*npte) & PAGE_MASK,
-				    PAGE_SIZE, r, w, x);
+	for(i = 0; i <= last; i++){
+		op = &ops[i];
+		switch(op->type){
+		case MMAP:
+			map(fd, op->u.mmap.addr, op->u.mmap.len,
+			    op->u.mmap.r, op->u.mmap.w, op->u.mmap.x,
+			    op->u.mmap.fd, op->u.mmap.offset);
+			break;
+		case MUNMAP:
+			unmap(fd, (void *) op->u.munmap.addr,
+			      op->u.munmap.len);
+			break;
+		case MPROTECT:
+			protect(fd, op->u.mprotect.addr, op->u.mprotect.len,
+				op->u.mprotect.r, op->u.mprotect.w,
+				op->u.mprotect.x);
+			break;
+		default:
+			printk("Unknown op type %d in do_ops\n", op->type);
+			break;
 		}
-		else if(pte_newprot(*npte))
-			protect(fd, addr, PAGE_SIZE, r, w, x, 1);
-
-		*npte = pte_mkuptodate(*npte);
-		addr += PAGE_SIZE;
 	}
 }
 
-void flush_tlb_kernel_range_skas(unsigned long start, unsigned long end)
+static void fix_range(struct mm_struct *mm, unsigned long start_addr,
+		      unsigned long end_addr, int force)
 {
-	struct mm_struct *mm;
-	pgd_t *pgd;
-	pud_t *pud;
-	pmd_t *pmd;
-	pte_t *pte;
-	unsigned long addr, last;
-	int updated = 0, err;
-
-	mm = &init_mm;
-	for(addr = start; addr < end;){
-		pgd = pgd_offset(mm, addr);
-		pud = pud_offset(pgd, addr);
-		pmd = pmd_offset(pud, addr);
- 		if(!pgd_present(*pgd)){
-			if(pgd_newpage(*pgd)){
-				updated = 1;
-				last = addr + PGDIR_SIZE;
-				if(last > end)
-					last = end;
-				err = os_unmap_memory((void *) addr, 
-						      last - addr);
-				if(err < 0)
-					panic("munmap failed, errno = %d\n",
-					      -err);
-			}
-			addr += PGDIR_SIZE;
-			continue;
-		}
+        int fd = mm->context.skas.mm_fd;
 
-		pud = pud_offset(pgd, addr);
-		if(!pud_present(*pud)){
-			if(pud_newpage(*pud)){
-				updated = 1;
-				last = addr + PUD_SIZE;
-				if(last > end)
-					last = end;
-				err = os_unmap_memory((void *) addr,
-						      last - addr);
-				if(err < 0)
-					panic("munmap failed, errno = %d\n",
-					      -err);
-			}
-			addr += PUD_SIZE;
-			continue;
-		}
-
-		pmd = pmd_offset(pud, addr);
-		if(!pmd_present(*pmd)){
-			if(pmd_newpage(*pmd)){
-				updated = 1;
-				last = addr + PMD_SIZE;
-				if(last > end)
-					last = end;
-				err = os_unmap_memory((void *) addr,
-						      last - addr);
-				if(err < 0)
-					panic("munmap failed, errno = %d\n",
-					      -err);
-			}
-			addr += PMD_SIZE;
-			continue;
-		}
-
-		pte = pte_offset_kernel(pmd, addr);
-		if(!pte_present(*pte) || pte_newpage(*pte)){
-			updated = 1;
-			err = os_unmap_memory((void *) addr, PAGE_SIZE);
-			if(err < 0)
-				panic("munmap failed, errno = %d\n", -err);
-			if(pte_present(*pte))
-				map_memory(addr, pte_val(*pte) & PAGE_MASK,
-					   PAGE_SIZE, 1, 1, 1);
-		}
-		else if(pte_newprot(*pte)){
-			updated = 1;
-			protect_memory(addr, PAGE_SIZE, 1, 1, 1, 1);
-  		}
-		addr += PAGE_SIZE;
-	}
-}
-
-void flush_tlb_kernel_vm_skas(void)
-{
-	flush_tlb_kernel_range_skas(start_vm, end_vm);
+        fix_range_common(mm, start_addr, end_addr, force, fd, do_ops);
 }
 
 void __flush_tlb_one_skas(unsigned long addr)
 {
-	flush_tlb_kernel_range_skas(addr, addr + PAGE_SIZE);
+        flush_tlb_kernel_range_common(addr, addr + PAGE_SIZE);
 }
 
 void flush_tlb_range_skas(struct vm_area_struct *vma, unsigned long start, 
 		     unsigned long end)
 {
-	if(vma->vm_mm == NULL)
-		flush_tlb_kernel_range_skas(start, end);
-	else fix_range(vma->vm_mm, start, end, 0);
+        if(vma->vm_mm == NULL)
+                flush_tlb_kernel_range_common(start, end);
+        else fix_range(vma->vm_mm, start, end, 0);
 }
 
 void flush_tlb_mm_skas(struct mm_struct *mm)
 {
-	flush_tlb_kernel_vm_skas();
-	fix_range(mm, 0, host_task_size, 0);
+	/* Don't bother flushing if this address space is about to be
+         * destroyed.
+         */
+        if(atomic_read(&mm->mm_users) == 0)
+                return;
+
+        fix_range(mm, 0, host_task_size, 0);
+        flush_tlb_kernel_range_common(start_vm, end_vm);
 }
 
 void force_flush_all_skas(void)
 {
-	fix_range(current->mm, 0, host_task_size, 1);
+        fix_range(current->mm, 0, host_task_size, 1);
 }
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff -Nru a/arch/um/kernel/sys_call_table.c b/arch/um/kernel/sys_call_table.c
--- a/arch/um/kernel/sys_call_table.c	2005-03-11 12:51:51 -08:00
+++ b/arch/um/kernel/sys_call_table.c	2005-03-11 12:51:51 -08:00
@@ -31,7 +31,6 @@
 extern syscall_handler_t sys_fork;
 extern syscall_handler_t sys_execve;
 extern syscall_handler_t um_time;
-extern syscall_handler_t um_mount;
 extern syscall_handler_t um_stime;
 extern syscall_handler_t sys_pipe;
 extern syscall_handler_t sys_olduname;
@@ -77,7 +76,7 @@
 	[ __NR_lchown ] = (syscall_handler_t *) sys_lchown16,
 	[ __NR_lseek ] = (syscall_handler_t *) sys_lseek,
 	[ __NR_getpid ] = (syscall_handler_t *) sys_getpid,
-	[ __NR_mount ] = um_mount,
+	[ __NR_mount ] = (syscall_handler_t *) sys_mount,
 	[ __NR_setuid ] = (syscall_handler_t *) sys_setuid16,
 	[ __NR_getuid ] = (syscall_handler_t *) sys_getuid16,
  	[ __NR_ptrace ] = (syscall_handler_t *) sys_ptrace,
diff -Nru a/arch/um/kernel/syscall_kern.c b/arch/um/kernel/syscall_kern.c
--- a/arch/um/kernel/syscall_kern.c	2005-03-11 12:51:47 -08:00
+++ b/arch/um/kernel/syscall_kern.c	2005-03-11 12:51:47 -08:00
@@ -27,12 +27,6 @@
 /*  Unlocked, I don't care if this is a bit off */
 int nsyscalls = 0;
 
-long um_mount(char __user * dev_name, char __user * dir_name,
-	      char __user * type, unsigned long new_flags, void __user * data)
-{
-	return(sys_mount(dev_name, dir_name, type, new_flags, data));
-}
-
 long sys_fork(void)
 {
 	long ret;
@@ -152,11 +146,6 @@
 	error = error ? -EFAULT : 0;
 
 	return error;
-}
-
-long execute_syscall(void *r)
-{
-	return(CHOOSE_MODE_PROC(execute_syscall_tt, execute_syscall_skas, r));
 }
 
 DEFINE_SPINLOCK(syscall_lock);
diff -Nru a/arch/um/kernel/syscall_user.c b/arch/um/kernel/syscall_user.c
--- a/arch/um/kernel/syscall_user.c	2005-03-11 12:51:48 -08:00
+++ b/arch/um/kernel/syscall_user.c	2005-03-11 12:51:48 -08:00
@@ -46,3 +46,51 @@
  * c-file-style: "linux"
  * End:
  */
+/*
+ * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
+ * Licensed under the GPL
+ */
+
+#include <stdlib.h>
+#include <sys/time.h>
+#include "kern_util.h"
+#include "syscall_user.h"
+
+struct {
+	int syscall;
+	int pid;
+	long result;
+	struct timeval start;
+	struct timeval end;
+} syscall_record[1024];
+
+int record_syscall_start(int syscall)
+{
+	int max, index;
+
+	max = sizeof(syscall_record)/sizeof(syscall_record[0]);
+	index = next_syscall_index(max);
+
+	syscall_record[index].syscall = syscall;
+	syscall_record[index].pid = current_pid();
+	syscall_record[index].result = 0xdeadbeef;
+	gettimeofday(&syscall_record[index].start, NULL);
+	return(index);
+}
+
+void record_syscall_end(int index, long result)
+{
+	syscall_record[index].result = result;
+	gettimeofday(&syscall_record[index].end, NULL);
+}
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only.  This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-file-style: "linux"
+ * End:
+ */
diff -Nru a/arch/um/kernel/tlb.c b/arch/um/kernel/tlb.c
--- a/arch/um/kernel/tlb.c	2005-03-11 12:51:48 -08:00
+++ b/arch/um/kernel/tlb.c	2005-03-11 12:51:48 -08:00
@@ -9,87 +9,361 @@
 #include "asm/tlbflush.h"
 #include "choose-mode.h"
 #include "mode_kern.h"
+#include "user_util.h"
+#include "tlb.h"
+#include "mem.h"
+#include "mem_user.h"
+#include "os.h"
+
+#define ADD_ROUND(n, inc) (((n) + (inc)) & ~((inc) - 1))
+
+void fix_range_common(struct mm_struct *mm, unsigned long start_addr,
+                      unsigned long end_addr, int force, int data,
+                      void (*do_ops)(int, struct host_vm_op *, int))
+{
+        pgd_t *npgd;
+        pud_t *npud;
+        pmd_t *npmd;
+        pte_t *npte;
+        unsigned long addr, end;
+        int r, w, x;
+        struct host_vm_op ops[16];
+        int op_index = -1, last_op = sizeof(ops) / sizeof(ops[0]) - 1;
+
+        if(mm == NULL) return;
+
+        for(addr = start_addr; addr < end_addr;){
+                npgd = pgd_offset(mm, addr);
+                if(!pgd_present(*npgd)){
+                        end = ADD_ROUND(addr, PGDIR_SIZE);
+                        if(end > end_addr)
+                                end = end_addr;
+                        if(force || pgd_newpage(*npgd)){
+                                op_index = add_munmap(addr, end - addr, ops,
+                                                      op_index, last_op, data,
+                                                      do_ops);
+                                pgd_mkuptodate(*npgd);
+                        }
+                        addr = end;
+                        continue;
+                }
+
+                npud = pud_offset(npgd, addr);
+                if(!pud_present(*npud)){
+                        end = ADD_ROUND(addr, PUD_SIZE);
+                        if(end > end_addr)
+                                end = end_addr;
+                        if(force || pud_newpage(*npud)){
+                                op_index = add_munmap(addr, end - addr, ops,
+                                                      op_index, last_op, data,
+                                                      do_ops);
+                                pud_mkuptodate(*npud);
+                        }
+                        addr = end;
+                        continue;
+                }
+
+                npmd = pmd_offset(npud, addr);
+                if(!pmd_present(*npmd)){
+                        end = ADD_ROUND(addr, PMD_SIZE);
+                        if(end > end_addr)
+                                end = end_addr;
+                        if(force || pmd_newpage(*npmd)){
+                                op_index = add_munmap(addr, end - addr, ops,
+                                                      op_index, last_op, data,
+                                                      do_ops);
+                                pmd_mkuptodate(*npmd);
+                        }
+                        addr = end;
+                        continue;
+                }
+
+                npte = pte_offset_kernel(npmd, addr);
+                r = pte_read(*npte);
+                w = pte_write(*npte);
+                x = pte_exec(*npte);
+                if(!pte_dirty(*npte))
+                        w = 0;
+                if(!pte_young(*npte)){
+                        r = 0;
+                        w = 0;
+                }
+                if(force || pte_newpage(*npte)){
+                        if(pte_present(*npte))
+                                op_index = add_mmap(addr,
+                                                    pte_val(*npte) & PAGE_MASK,
+                                                    PAGE_SIZE, r, w, x, ops,
+                                                    op_index, last_op, data,
+                                                    do_ops);
+                        else op_index = add_munmap(addr, PAGE_SIZE, ops,
+                                                   op_index, last_op, data,
+                                                   do_ops);
+                }
+                else if(pte_newprot(*npte))
+                        op_index = add_mprotect(addr, PAGE_SIZE, r, w, x, ops,
+                                                op_index, last_op, data,
+                                                do_ops);
+
+                *npte = pte_mkuptodate(*npte);
+                addr += PAGE_SIZE;
+        }
+        (*do_ops)(data, ops, op_index);
+}
+
+int flush_tlb_kernel_range_common(unsigned long start, unsigned long end)
+{
+        struct mm_struct *mm;
+        pgd_t *pgd;
+        pud_t *pud;
+        pmd_t *pmd;
+        pte_t *pte;
+        unsigned long addr, last;
+        int updated = 0, err;
+
+        mm = &init_mm;
+        for(addr = start; addr < end;){
+                pgd = pgd_offset(mm, addr);
+                if(!pgd_present(*pgd)){
+                        last = ADD_ROUND(addr, PGDIR_SIZE);
+                        if(last > end)
+                                last = end;
+                        if(pgd_newpage(*pgd)){
+                                updated = 1;
+                                err = os_unmap_memory((void *) addr,
+                                                      last - addr);
+                                if(err < 0)
+                                        panic("munmap failed, errno = %d\n",
+                                              -err);
+                        }
+                        addr = last;
+                        continue;
+                }
+
+                pud = pud_offset(pgd, addr);
+                if(!pud_present(*pud)){
+                        last = ADD_ROUND(addr, PUD_SIZE);
+                        if(last > end)
+                                last = end;
+                        if(pud_newpage(*pud)){
+                                updated = 1;
+                                err = os_unmap_memory((void *) addr,
+                                                      last - addr);
+                                if(err < 0)
+                                        panic("munmap failed, errno = %d\n",
+                                              -err);
+                        }
+                        addr = last;
+                        continue;
+                }
+
+                pmd = pmd_offset(pud, addr);
+                if(!pmd_present(*pmd)){
+                        last = ADD_ROUND(addr, PMD_SIZE);
+                        if(last > end)
+                                last = end;
+                        if(pmd_newpage(*pmd)){
+                                updated = 1;
+                                err = os_unmap_memory((void *) addr,
+                                                      last - addr);
+                                if(err < 0)
+                                        panic("munmap failed, errno = %d\n",
+                                              -err);
+                        }
+                        addr = last;
+                        continue;
+                }
+
+                pte = pte_offset_kernel(pmd, addr);
+                if(!pte_present(*pte) || pte_newpage(*pte)){
+                        updated = 1;
+                        err = os_unmap_memory((void *) addr,
+                                              PAGE_SIZE);
+                        if(err < 0)
+                                panic("munmap failed, errno = %d\n",
+                                      -err);
+                        if(pte_present(*pte))
+                                map_memory(addr,
+                                           pte_val(*pte) & PAGE_MASK,
+                                           PAGE_SIZE, 1, 1, 1);
+                }
+                else if(pte_newprot(*pte)){
+                        updated = 1;
+                        protect_memory(addr, PAGE_SIZE, 1, 1, 1, 1);
+                }
+                addr += PAGE_SIZE;
+        }
+        return(updated);
+}
 
 void flush_tlb_page(struct vm_area_struct *vma, unsigned long address)
 {
-	address &= PAGE_MASK;
-	flush_tlb_range(vma, address, address + PAGE_SIZE);
+        address &= PAGE_MASK;
+        flush_tlb_range(vma, address, address + PAGE_SIZE);
 }
 
 void flush_tlb_all(void)
 {
-	flush_tlb_mm(current->mm);
+        flush_tlb_mm(current->mm);
 }
   
 void flush_tlb_kernel_range(unsigned long start, unsigned long end)
 {
-	CHOOSE_MODE_PROC(flush_tlb_kernel_range_tt, 
-			 flush_tlb_kernel_range_skas, start, end);
+        CHOOSE_MODE_PROC(flush_tlb_kernel_range_tt,
+                         flush_tlb_kernel_range_common, start, end);
 }
 
 void flush_tlb_kernel_vm(void)
 {
-	CHOOSE_MODE(flush_tlb_kernel_vm_tt(), flush_tlb_kernel_vm_skas());
+        CHOOSE_MODE(flush_tlb_kernel_vm_tt(),
+                    flush_tlb_kernel_range_common(start_vm, end_vm));
 }
 
 void __flush_tlb_one(unsigned long addr)
 {
-	CHOOSE_MODE_PROC(__flush_tlb_one_tt, __flush_tlb_one_skas, addr);
+        CHOOSE_MODE_PROC(__flush_tlb_one_tt, __flush_tlb_one_skas, addr);
 }
 
 void flush_tlb_range(struct vm_area_struct *vma, unsigned long start, 
-		     unsigned long end)
+     unsigned long end)
 {
-	CHOOSE_MODE_PROC(flush_tlb_range_tt, flush_tlb_range_skas, vma, start, 
-			 end);
+        CHOOSE_MODE_PROC(flush_tlb_range_tt, flush_tlb_range_skas, vma, start,
+                         end);
 }
 
 void flush_tlb_mm(struct mm_struct *mm)
 {
-	CHOOSE_MODE_PROC(flush_tlb_mm_tt, flush_tlb_mm_skas, mm);
+        CHOOSE_MODE_PROC(flush_tlb_mm_tt, flush_tlb_mm_skas, mm);
 }
 
 void force_flush_all(void)
 {
-	CHOOSE_MODE(force_flush_all_tt(), force_flush_all_skas());
+        CHOOSE_MODE(force_flush_all_tt(), force_flush_all_skas());
 }
 
 pgd_t *pgd_offset_proc(struct mm_struct *mm, unsigned long address)
 {
-	return(pgd_offset(mm, address));
+        return(pgd_offset(mm, address));
 }
 
 pud_t *pud_offset_proc(pgd_t *pgd, unsigned long address)
 {
-	return(pud_offset(pgd, address));
+        return(pud_offset(pgd, address));
 }
 
 pmd_t *pmd_offset_proc(pud_t *pud, unsigned long address)
 {
-	return(pmd_offset(pud, address));
+        return(pmd_offset(pud, address));
 }
 
 pte_t *pte_offset_proc(pmd_t *pmd, unsigned long address)
 {
-	return(pte_offset_kernel(pmd, address));
+        return(pte_offset_kernel(pmd, address));
 }
 
 pte_t *addr_pte(struct task_struct *task, unsigned long addr)
 {
-	pgd_t *pgd = pgd_offset(task->mm, addr);
-	pud_t *pud = pud_offset(pgd, addr);
-	pmd_t *pmd = pmd_offset(pud, addr);
-
-	return(pte_offset_map(pmd, addr));
-}
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
+        pgd_t *pgd = pgd_offset(task->mm, addr);
+        pud_t *pud = pud_offset(pgd, addr);
+        pmd_t *pmd = pmd_offset(pud, addr);
+
+        return(pte_offset_map(pmd, addr));
+}
+
+int add_mmap(unsigned long virt, unsigned long phys, unsigned long len,
+     int r, int w, int x, struct host_vm_op *ops, int index,
+     int last_filled, int data,
+     void (*do_ops)(int, struct host_vm_op *, int))
+{
+        __u64 offset;
+	struct host_vm_op *last;
+	int fd;
+
+	fd = phys_mapping(phys, &offset);
+	if(index != -1){
+		last = &ops[index];
+		if((last->type == MMAP) &&
+		   (last->u.mmap.addr + last->u.mmap.len == virt) &&
+		   (last->u.mmap.r == r) && (last->u.mmap.w == w) &&
+		   (last->u.mmap.x == x) && (last->u.mmap.fd == fd) &&
+		   (last->u.mmap.offset + last->u.mmap.len == offset)){
+			last->u.mmap.len += len;
+			return(index);
+		}
+	}
+
+	if(index == last_filled){
+		(*do_ops)(data, ops, last_filled);
+		index = -1;
+	}
+
+	ops[++index] = ((struct host_vm_op) { .type	= MMAP,
+					      .u = { .mmap = {
+						      .addr	= virt,
+						      .len	= len,
+						      .r	= r,
+						      .w	= w,
+						      .x	= x,
+						      .fd	= fd,
+						      .offset	= offset }
+					      } });
+	return(index);
+}
+
+int add_munmap(unsigned long addr, unsigned long len, struct host_vm_op *ops,
+	       int index, int last_filled, int data,
+	       void (*do_ops)(int, struct host_vm_op *, int))
+{
+	struct host_vm_op *last;
+
+	if(index != -1){
+		last = &ops[index];
+		if((last->type == MUNMAP) &&
+		   (last->u.munmap.addr + last->u.mmap.len == addr)){
+			last->u.munmap.len += len;
+			return(index);
+		}
+	}
+
+	if(index == last_filled){
+		(*do_ops)(data, ops, last_filled);
+		index = -1;
+	}
+
+	ops[++index] = ((struct host_vm_op) { .type	= MUNMAP,
+					      .u = { .munmap = {
+						      .addr	= addr,
+						      .len	= len } } });
+	return(index);
+}
+
+int add_mprotect(unsigned long addr, unsigned long len, int r, int w, int x,
+		 struct host_vm_op *ops, int index, int last_filled, int data,
+		 void (*do_ops)(int, struct host_vm_op *, int))
+{
+	struct host_vm_op *last;
+
+	if(index != -1){
+		last = &ops[index];
+		if((last->type == MPROTECT) &&
+		   (last->u.mprotect.addr + last->u.mprotect.len == addr) &&
+		   (last->u.mprotect.r == r) && (last->u.mprotect.w == w) &&
+		   (last->u.mprotect.x == x)){
+			last->u.mprotect.len += len;
+			return(index);
+		}
+	}
+
+	if(index == last_filled){
+		(*do_ops)(data, ops, last_filled);
+		index = -1;
+	}
+
+	ops[++index] = ((struct host_vm_op) { .type	= MPROTECT,
+					      .u = { .mprotect = {
+						      .addr	= addr,
+						      .len	= len,
+						      .r	= r,
+						      .w	= w,
+						      .x	= x } } });
+	return(index);
+}
diff -Nru a/arch/um/kernel/trap_user.c b/arch/um/kernel/trap_user.c
--- a/arch/um/kernel/trap_user.c	2005-03-11 12:51:46 -08:00
+++ b/arch/um/kernel/trap_user.c	2005-03-11 12:51:46 -08:00
@@ -8,7 +8,6 @@
 #include <setjmp.h>
 #include <signal.h>
 #include <sys/time.h>
-#include <sys/ptrace.h>
 #include <sys/wait.h>
 #include <asm/page.h>
 #include <asm/unistd.h>
diff -Nru a/arch/um/kernel/tt/exec_user.c b/arch/um/kernel/tt/exec_user.c
--- a/arch/um/kernel/tt/exec_user.c	2005-03-11 12:51:51 -08:00
+++ b/arch/um/kernel/tt/exec_user.c	2005-03-11 12:51:51 -08:00
@@ -9,8 +9,6 @@
 #include <sched.h>
 #include <errno.h>
 #include <sys/wait.h>
-#include <sys/ptrace.h>
-#include <linux/ptrace.h>
 #include <signal.h>
 #include "user_util.h"
 #include "kern_util.h"
diff -Nru a/arch/um/kernel/tt/gdb.c b/arch/um/kernel/tt/gdb.c
--- a/arch/um/kernel/tt/gdb.c	2005-03-11 12:51:41 -08:00
+++ b/arch/um/kernel/tt/gdb.c	2005-03-11 12:51:41 -08:00
@@ -8,8 +8,8 @@
 #include <errno.h>
 #include <string.h>
 #include <signal.h>
-#include <sys/ptrace.h>
 #include <sys/types.h>
+#include "ptrace_user.h"
 #include "uml-config.h"
 #include "kern_constants.h"
 #include "chan_user.h"
diff -Nru a/arch/um/kernel/tt/include/tt.h b/arch/um/kernel/tt/include/tt.h
--- a/arch/um/kernel/tt/include/tt.h	2005-03-11 12:51:46 -08:00
+++ b/arch/um/kernel/tt/include/tt.h	2005-03-11 12:51:46 -08:00
@@ -30,6 +30,7 @@
 extern void do_sigtrap(void *task);
 extern int is_valid_pid(int pid);
 extern void remap_data(void *segment_start, void *segment_end, int w);
+extern long execute_syscall_tt(void *r);
 
 #endif
 
diff -Nru a/arch/um/kernel/tt/mem.c b/arch/um/kernel/tt/mem.c
--- a/arch/um/kernel/tt/mem.c	2005-03-11 12:51:42 -08:00
+++ b/arch/um/kernel/tt/mem.c	2005-03-11 12:51:42 -08:00
@@ -15,7 +15,7 @@
 
 void before_mem_tt(unsigned long brk_start)
 {
-	if(!jail || debug)
+	if(debug)
 		remap_data(UML_ROUND_DOWN(&_stext), UML_ROUND_UP(&_etext), 1);
 	remap_data(UML_ROUND_DOWN(&_sdata), UML_ROUND_UP(&_edata), 1);
 	remap_data(UML_ROUND_DOWN(&__bss_start), UML_ROUND_UP(&_end), 1);
diff -Nru a/arch/um/kernel/tt/process_kern.c b/arch/um/kernel/tt/process_kern.c
--- a/arch/um/kernel/tt/process_kern.c	2005-03-11 12:51:51 -08:00
+++ b/arch/um/kernel/tt/process_kern.c	2005-03-11 12:51:51 -08:00
@@ -85,24 +85,6 @@
 	   (prev_sched->exit_state == EXIT_DEAD))
 		os_kill_process(prev_sched->thread.mode.tt.extern_pid, 1);
 
-	/* This works around a nasty race with 'jail'.  If we are switching
-	 * between two threads of a threaded app and the incoming process 
-	 * runs before the outgoing process reaches the read, and it makes
-	 * it all the way out to userspace, then it will have write-protected 
-	 * the outgoing process stack.  Then, when the outgoing process 
-	 * returns from the write, it will segfault because it can no longer
-	 * write its own stack.  So, in order to avoid that, the incoming 
-	 * thread sits in a loop yielding until 'reading' is set.  This 
-	 * isn't entirely safe, since there may be a reschedule from a timer
-	 * happening between setting 'reading' and sleeping in read.  But,
-	 * it should get a whole quantum in which to reach the read and sleep,
-	 * which should be enough.
-	 */
-
-	if(jail){
-		while(!reading) sched_yield();
-	}
-
 	change_sig(SIGVTALRM, vtalrm);
 	change_sig(SIGALRM, alrm);
 	change_sig(SIGPROF, prof);
@@ -392,84 +374,6 @@
 void init_idle_tt(void)
 {
 	default_idle();
-}
-
-/* Changed by jail_setup, which is a setup */
-int jail = 0;
-
-int __init jail_setup(char *line, int *add)
-{
-	int ok = 1;
-
-	if(jail) return(0);
-#ifdef CONFIG_SMP
-	printf("'jail' may not used used in a kernel with CONFIG_SMP "
-	       "enabled\n");
-	ok = 0;
-#endif
-#ifdef CONFIG_HOSTFS
-	printf("'jail' may not used used in a kernel with CONFIG_HOSTFS "
-	       "enabled\n");
-	ok = 0;
-#endif
-#ifdef CONFIG_MODULES
-	printf("'jail' may not used used in a kernel with CONFIG_MODULES "
-	       "enabled\n");
-	ok = 0;
-#endif	
-	if(!ok) exit(1);
-
-	/* CAP_SYS_RAWIO controls the ability to open /dev/mem and /dev/kmem.
-	 * Removing it from the bounding set eliminates the ability of anything
-	 * to acquire it, and thus read or write kernel memory.
-	 */
-	cap_lower(cap_bset, CAP_SYS_RAWIO);
-	jail = 1;
-	return(0);
-}
-
-__uml_setup("jail", jail_setup,
-"jail\n"
-"    Enables the protection of kernel memory from processes.\n\n"
-);
-
-static void mprotect_kernel_mem(int w)
-{
-	unsigned long start, end;
-	int pages;
-
-	if(!jail || (current == &init_task)) return;
-
-	pages = (1 << CONFIG_KERNEL_STACK_ORDER);
-
-	start = (unsigned long) current_thread + PAGE_SIZE;
-	end = (unsigned long) current_thread + PAGE_SIZE * pages;
-	protect_memory(uml_reserved, start - uml_reserved, 1, w, 1, 1);
-	protect_memory(end, high_physmem - end, 1, w, 1, 1);
-
-	start = (unsigned long) UML_ROUND_DOWN(&_stext);
-	end = (unsigned long) UML_ROUND_UP(&_etext);
-	protect_memory(start, end - start, 1, w, 1, 1);
-
-	start = (unsigned long) UML_ROUND_DOWN(&_unprotected_end);
-	end = (unsigned long) UML_ROUND_UP(&_edata);
-	protect_memory(start, end - start, 1, w, 1, 1);
-
-	start = (unsigned long) UML_ROUND_DOWN(&__bss_start);
-	end = (unsigned long) UML_ROUND_UP(brk_start);
-	protect_memory(start, end - start, 1, w, 1, 1);
-
-	mprotect_kernel_vm(w);
-}
-
-void unprotect_kernel_mem(void)
-{
-	mprotect_kernel_mem(1);
-}
-
-void protect_kernel_mem(void)
-{
-	mprotect_kernel_mem(0);
 }
 
 extern void start_kernel(void);
diff -Nru a/arch/um/kernel/tt/ptproxy/proxy.c b/arch/um/kernel/tt/ptproxy/proxy.c
--- a/arch/um/kernel/tt/ptproxy/proxy.c	2005-03-11 12:51:47 -08:00
+++ b/arch/um/kernel/tt/ptproxy/proxy.c	2005-03-11 12:51:47 -08:00
@@ -18,9 +18,9 @@
 #include <termios.h>
 #include <sys/wait.h>
 #include <sys/types.h>
-#include <sys/ptrace.h>
 #include <sys/ioctl.h>
 #include <asm/unistd.h>
+#include "ptrace_user.h"
 
 #include "ptproxy.h"
 #include "sysdep.h"
diff -Nru a/arch/um/kernel/tt/ptproxy/ptrace.c b/arch/um/kernel/tt/ptproxy/ptrace.c
--- a/arch/um/kernel/tt/ptproxy/ptrace.c	2005-03-11 12:51:51 -08:00
+++ b/arch/um/kernel/tt/ptproxy/ptrace.c	2005-03-11 12:51:51 -08:00
@@ -12,9 +12,7 @@
 #include <signal.h>
 #include <sys/types.h>
 #include <sys/time.h>
-#include <sys/ptrace.h>
 #include <sys/wait.h>
-#include <asm/ptrace.h>
 
 #include "ptproxy.h"
 #include "debug.h"
@@ -127,7 +125,7 @@
 
 	case PTRACE_PEEKDATA:
 	case PTRACE_PEEKTEXT:
-	case PTRACE_PEEKUSER:
+	case PTRACE_PEEKUSR:
 		/* The value being read out could be -1, so we have to 
 		 * check errno to see if there's an error, and zero it
 		 * beforehand so we're not faked out by an old error
@@ -144,11 +142,11 @@
 
 	case PTRACE_POKEDATA:
 	case PTRACE_POKETEXT:
-	case PTRACE_POKEUSER:
+	case PTRACE_POKEUSR:
 		result = ptrace(arg1, child, arg3, arg4);
 		if(result == -1) return(-errno);
 
-		if(arg1 == PTRACE_POKEUSER) ptrace_pokeuser(arg3, arg4);
+		if(arg1 == PTRACE_POKEUSR) ptrace_pokeuser(arg3, arg4);
 		return(result);
 
 #ifdef UM_HAVE_SETFPREGS
diff -Nru a/arch/um/kernel/tt/ptproxy/sysdep.c b/arch/um/kernel/tt/ptproxy/sysdep.c
--- a/arch/um/kernel/tt/ptproxy/sysdep.c	2005-03-11 12:51:48 -08:00
+++ b/arch/um/kernel/tt/ptproxy/sysdep.c	2005-03-11 12:51:48 -08:00
@@ -11,7 +11,6 @@
 #include <signal.h>
 #include <errno.h>
 #include <sys/types.h>
-#include <sys/ptrace.h>
 #include <linux/unistd.h>
 #include "ptrace_user.h"
 #include "user_util.h"
@@ -20,21 +19,21 @@
 int get_syscall(pid_t pid, long *arg1, long *arg2, long *arg3, long *arg4, 
 		long *arg5)
 {
-	*arg1 = ptrace(PTRACE_PEEKUSER, pid, PT_SYSCALL_ARG1_OFFSET, 0);
-	*arg2 = ptrace(PTRACE_PEEKUSER, pid, PT_SYSCALL_ARG2_OFFSET, 0);
-	*arg3 = ptrace(PTRACE_PEEKUSER, pid, PT_SYSCALL_ARG3_OFFSET, 0);
-	*arg4 = ptrace(PTRACE_PEEKUSER, pid, PT_SYSCALL_ARG4_OFFSET, 0);
-	*arg5 = ptrace(PTRACE_PEEKUSER, pid, PT_SYSCALL_ARG5_OFFSET, 0);
-	return(ptrace(PTRACE_PEEKUSER, pid, PT_SYSCALL_NR_OFFSET, 0));
+	*arg1 = ptrace(PTRACE_PEEKUSR, pid, PT_SYSCALL_ARG1_OFFSET, 0);
+	*arg2 = ptrace(PTRACE_PEEKUSR, pid, PT_SYSCALL_ARG2_OFFSET, 0);
+	*arg3 = ptrace(PTRACE_PEEKUSR, pid, PT_SYSCALL_ARG3_OFFSET, 0);
+	*arg4 = ptrace(PTRACE_PEEKUSR, pid, PT_SYSCALL_ARG4_OFFSET, 0);
+	*arg5 = ptrace(PTRACE_PEEKUSR, pid, PT_SYSCALL_ARG5_OFFSET, 0);
+	return(ptrace(PTRACE_PEEKUSR, pid, PT_SYSCALL_NR_OFFSET, 0));
 }
 
 void syscall_cancel(pid_t pid, int result)
 {
-	if((ptrace(PTRACE_POKEUSER, pid, PT_SYSCALL_NR_OFFSET, 
+	if((ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_NR_OFFSET,
 		   __NR_getpid) < 0) ||
 	   (ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0) ||
 	   (wait_for_stop(pid, SIGTRAP, PTRACE_SYSCALL, NULL) < 0) ||
-	   (ptrace(PTRACE_POKEUSER, pid, PT_SYSCALL_RET_OFFSET, result) < 0) ||
+	   (ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_RET_OFFSET, result) < 0) ||
 	   (ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0))
 		printk("ptproxy: couldn't cancel syscall: errno = %d\n", 
 		       errno);
@@ -42,7 +41,7 @@
 
 void syscall_set_result(pid_t pid, long result)
 {
-	ptrace(PTRACE_POKEUSER, pid, PT_SYSCALL_RET_OFFSET, result);
+	ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_RET_OFFSET, result);
 }
 
 void syscall_continue(pid_t pid)
@@ -52,7 +51,7 @@
 
 int syscall_pause(pid_t pid) 
 {
-	if(ptrace(PTRACE_POKEUSER, pid, PT_SYSCALL_NR_OFFSET, __NR_pause) < 0){
+	if(ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_NR_OFFSET, __NR_pause) < 0){
 		printk("syscall_change - ptrace failed, errno = %d\n", errno);
 		return(-1);
 	}
diff -Nru a/arch/um/kernel/tt/ptproxy/wait.c b/arch/um/kernel/tt/ptproxy/wait.c
--- a/arch/um/kernel/tt/ptproxy/wait.c	2005-03-11 12:51:51 -08:00
+++ b/arch/um/kernel/tt/ptproxy/wait.c	2005-03-11 12:51:51 -08:00
@@ -9,14 +9,13 @@
 #include <errno.h>
 #include <signal.h>
 #include <sys/wait.h>
-#include <sys/ptrace.h>
 
 #include "ptproxy.h"
 #include "sysdep.h"
 #include "wait.h"
 #include "user_util.h"
+#include "ptrace_user.h"
 #include "sysdep/ptrace.h"
-#include "sysdep/ptrace_user.h"
 #include "sysdep/sigcontext.h"
 
 int proxy_wait_return(struct debugger *debugger, pid_t unused)
@@ -59,10 +58,10 @@
 
 	pid = debugger->pid;
 
-	ip = ptrace(PTRACE_PEEKUSER, pid, PT_IP_OFFSET, 0);
+	ip = ptrace(PTRACE_PEEKUSR, pid, PT_IP_OFFSET, 0);
 	IP_RESTART_SYSCALL(ip);
 
-	if(ptrace(PTRACE_POKEUSER, pid, PT_IP_OFFSET, ip) < 0)
+	if(ptrace(PTRACE_POKEUSR, pid, PT_IP_OFFSET, ip) < 0)
 		tracer_panic("real_wait_return : Failed to restart system "
 			     "call, errno = %d\n", errno);
 
diff -Nru a/arch/um/kernel/tt/syscall_kern.c b/arch/um/kernel/tt/syscall_kern.c
--- a/arch/um/kernel/tt/syscall_kern.c	2005-03-11 12:51:40 -08:00
+++ b/arch/um/kernel/tt/syscall_kern.c	2005-03-11 12:51:40 -08:00
@@ -22,8 +22,10 @@
 	long res;
 	int syscall;
 
+#ifdef CONFIG_SYSCALL_DEBUG
 	current->thread.nsyscalls++;
 	nsyscalls++;
+#endif
 	syscall = UPT_SYSCALL_NR(&regs->regs);
 
 	if((syscall >= NR_syscalls) || (syscall < 0))
diff -Nru a/arch/um/kernel/tt/syscall_user.c b/arch/um/kernel/tt/syscall_user.c
--- a/arch/um/kernel/tt/syscall_user.c	2005-03-11 12:51:47 -08:00
+++ b/arch/um/kernel/tt/syscall_user.c	2005-03-11 12:51:47 -08:00
@@ -6,7 +6,6 @@
 #include <unistd.h>
 #include <signal.h>
 #include <errno.h>
-#include <sys/ptrace.h>
 #include <asm/unistd.h>
 #include "sysdep/ptrace.h"
 #include "sigcontext.h"
@@ -22,15 +21,20 @@
 {
 	void *sc;
 	long result;
-	int index, syscall;
+	int syscall;
+#ifdef UML_CONFIG_DEBUG_SYSCALL
+	int index;
+#endif
 
 	syscall = UPT_SYSCALL_NR(regs);
 	sc = UPT_SC(regs);
 	SC_START_SYSCALL(sc);
 
-	index = record_syscall_start(syscall);
+#ifdef UML_CONFIG_DEBUG_SYSCALL
+  	index = record_syscall_start(syscall);
+#endif
 	syscall_trace(regs, 0);
-	result = execute_syscall(regs);
+	result = execute_syscall_tt(regs);
 
 	/* regs->sc may have changed while the system call ran (there may
 	 * have been an interrupt or segfault), so it needs to be refreshed.
@@ -40,7 +44,9 @@
 	SC_SET_SYSCALL_RETURN(sc, result);
 
 	syscall_trace(regs, 1);
-	record_syscall_end(index, result);
+#ifdef UML_CONFIG_DEBUG_SYSCALL
+  	record_syscall_end(index, result);
+#endif
 }
 
 void do_sigtrap(void *task)
@@ -66,7 +72,7 @@
 		return;
 
 	/* syscall number -1 in sysemu skips syscall restarting in host */
-	if(ptrace(PTRACE_POKEUSER, pid, PT_SYSCALL_NR_OFFSET, 
+	if(ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_NR_OFFSET,
 		  local_using_sysemu ? -1 : __NR_getpid) < 0)
 		tracer_panic("do_syscall : Nullifying syscall failed, "
 			     "errno = %d", errno);
diff -Nru a/arch/um/kernel/tt/tlb.c b/arch/um/kernel/tt/tlb.c
--- a/arch/um/kernel/tt/tlb.c	2005-03-11 12:51:41 -08:00
+++ b/arch/um/kernel/tt/tlb.c	2005-03-11 12:51:41 -08:00
@@ -15,203 +15,55 @@
 #include "user_util.h"
 #include "mem_user.h"
 #include "os.h"
+#include "tlb.h"
 
-static void fix_range(struct mm_struct *mm, unsigned long start_addr, 
-		      unsigned long end_addr, int force)
+static void do_ops(int unused, struct host_vm_op *ops, int last)
 {
-	pgd_t *npgd;
-	pud_t *npud;
-	pmd_t *npmd;
-	pte_t *npte;
-	unsigned long addr, end;
-	int r, w, x, err;
-
-	if((current->thread.mode.tt.extern_pid != -1) && 
-	   (current->thread.mode.tt.extern_pid != os_getpid()))
-		panic("fix_range fixing wrong address space, current = 0x%p",
-		      current);
-	if(mm == NULL) return;
-	for(addr=start_addr;addr<end_addr;){
-		if(addr == TASK_SIZE){
-			/* Skip over kernel text, kernel data, and physical
-			 * memory, which don't have ptes, plus kernel virtual
-			 * memory, which is flushed separately, and remap
-			 * the process stack.  The only way to get here is
-			 * if (end_addr == STACK_TOP) > TASK_SIZE, which is
-			 * only true in the honeypot case.
-			 */
-			addr = STACK_TOP - ABOVE_KMEM;
-			continue;
-		}
-
-		npgd = pgd_offset(mm, addr);
- 		if(!pgd_present(*npgd)){
- 			if(force || pgd_newpage(*npgd)){
- 				end = addr + PGDIR_SIZE;
- 				if(end > end_addr)
- 					end = end_addr;
-				err = os_unmap_memory((void *) addr,
- 						      end - addr);
-				if(err < 0)
-					panic("munmap failed, errno = %d\n",
-					      -err);
-				pgd_mkuptodate(*npgd);
- 			}
-			addr += PGDIR_SIZE;
-			continue;
- 		}
-
-		npud = pud_offset(npgd, addr);
-		if(!pud_present(*npud)){
-			if(force || pud_newpage(*npud)){
- 				end = addr + PUD_SIZE;
- 				if(end > end_addr)
- 					end = end_addr;
-				err = os_unmap_memory((void *) addr, 
-						      end - addr);
-				if(err < 0)
-					panic("munmap failed, errno = %d\n",
-					      -err);
-				pud_mkuptodate(*npud);
-			}
-			addr += PUD_SIZE;
-			continue;
-		}
+	struct host_vm_op *op;
+	int i;
 
-		npmd = pmd_offset(npud, addr);
-		if(!pmd_present(*npmd)){
-			if(force || pmd_newpage(*npmd)){
- 				end = addr + PMD_SIZE;
- 				if(end > end_addr)
- 					end = end_addr;
-				err = os_unmap_memory((void *) addr,
-						      end - addr);
-				if(err < 0)
-					panic("munmap failed, errno = %d\n",
-					      -err);
-				pmd_mkuptodate(*npmd);
-			}
-			addr += PMD_SIZE;
-			continue;
+	for(i = 0; i <= last; i++){
+		op = &ops[i];
+		switch(op->type){
+		case MMAP:
+                        os_map_memory((void *) op->u.mmap.addr, op->u.mmap.fd,
+				      op->u.mmap.offset, op->u.mmap.len,
+				      op->u.mmap.r, op->u.mmap.w,
+				      op->u.mmap.x);
+			break;
+		case MUNMAP:
+			os_unmap_memory((void *) op->u.munmap.addr,
+					op->u.munmap.len);
+			break;
+		case MPROTECT:
+			protect_memory(op->u.mprotect.addr, op->u.munmap.len,
+				       op->u.mprotect.r, op->u.mprotect.w,
+				       op->u.mprotect.x, 1);
+			break;
+		default:
+			printk("Unknown op type %d in do_ops\n", op->type);
+			break;
 		}
-
-		npte = pte_offset_kernel(npmd, addr);
-		r = pte_read(*npte);
-		w = pte_write(*npte);
-		x = pte_exec(*npte);
-		if(!pte_dirty(*npte))
-			w = 0;
-		if(!pte_young(*npte)){
-			r = 0;
-			w = 0;
-		}
-		if(force || pte_newpage(*npte)){
-			err = os_unmap_memory((void *) addr, PAGE_SIZE);
-			if(err < 0)
-				panic("munmap failed, errno = %d\n", -err);
-			if(pte_present(*npte))
-				map_memory(addr, pte_val(*npte) & PAGE_MASK,
-					   PAGE_SIZE, r, w, x);
-		}
-		else if(pte_newprot(*npte))
-			protect_memory(addr, PAGE_SIZE, r, w, x, 1);
-
-		*npte = pte_mkuptodate(*npte);
-		addr += PAGE_SIZE;
 	}
 }
 
-atomic_t vmchange_seq = ATOMIC_INIT(1);
-
-static void flush_kernel_vm_range(unsigned long start, unsigned long end, 
-				  int update_seq)
+static void fix_range(struct mm_struct *mm, unsigned long start_addr, 
+		      unsigned long end_addr, int force)
 {
-	struct mm_struct *mm;
-	pgd_t *pgd;
-	pud_t *pud;
-	pmd_t *pmd;
-	pte_t *pte;
-	unsigned long addr, last;
-	int updated = 0, err;
+        if((current->thread.mode.tt.extern_pid != -1) &&
+           (current->thread.mode.tt.extern_pid != os_getpid()))
+                panic("fix_range fixing wrong address space, current = 0x%p",
+                      current);
 
-	mm = &init_mm;
-	for(addr = start; addr < end;){
-		pgd = pgd_offset(mm, addr);
- 		if(!pgd_present(*pgd)){
- 			if(pgd_newpage(*pgd)){
-				updated = 1;
- 				last = addr + PGDIR_SIZE;
- 				if(last > end)
- 					last = end;
-				err = os_unmap_memory((void *) addr, 
-						      last - addr);
-				if(err < 0)
-					panic("munmap failed, errno = %d\n",
-					      -err);
-			}
-			addr += PGDIR_SIZE;
-			continue;
-		}
-
-		pud = pud_offset(pgd, addr);
-		if(!pud_present(*pud)){
-			if(pud_newpage(*pud)){
-				updated = 1;
-				last = addr + PUD_SIZE;
-				if(last > end)
-					last = end;
-				err = os_unmap_memory((void *) addr,
-						      last - addr);
-				if(err < 0)
-					panic("munmap failed, errno = %d\n",
-					      -err);
-			}
-			addr += PUD_SIZE;
-			continue;
-		}
-
-		pmd = pmd_offset(pud, addr);
-		if(!pmd_present(*pmd)){
-			if(pmd_newpage(*pmd)){
-				updated = 1;
-				last = addr + PMD_SIZE;
-				if(last > end)
-					last = end;
-				err = os_unmap_memory((void *) addr,
-						      last - addr);
-				if(err < 0)
-					panic("munmap failed, errno = %d\n",
-					      -err);
-			}
-			addr += PMD_SIZE;
-			continue;
-		}
-
-		pte = pte_offset_kernel(pmd, addr);
-		if(!pte_present(*pte) || pte_newpage(*pte)){
-			updated = 1;
-			err = os_unmap_memory((void *) addr,
-					      PAGE_SIZE);
-			if(err < 0)
-				panic("munmap failed, errno = %d\n",
-				      -err);
-			if(pte_present(*pte))
-				map_memory(addr,
-					   pte_val(*pte) & PAGE_MASK,
-					   PAGE_SIZE, 1, 1, 1);
-		}
-		else if(pte_newprot(*pte)){
-			updated = 1;
-			protect_memory(addr, PAGE_SIZE, 1, 1, 1, 1);
-		}
-		addr += PAGE_SIZE;
-	}
-	if(updated && update_seq) atomic_inc(&vmchange_seq);
+        fix_range_common(mm, start_addr, end_addr, force, 0, do_ops);
 }
 
+atomic_t vmchange_seq = ATOMIC_INIT(1);
+
 void flush_tlb_kernel_range_tt(unsigned long start, unsigned long end)
 {
-        flush_kernel_vm_range(start, end, 1);
+        if(flush_tlb_kernel_range_common(start, end))
+                atomic_inc(&vmchange_seq);
 }
 
 static void protect_vm_page(unsigned long addr, int w, int must_succeed)
@@ -268,8 +120,10 @@
 	/* Assumes that the range start ... end is entirely within
 	 * either process memory or kernel vm
 	 */
-	if((start >= start_vm) && (start < end_vm)) 
-		flush_kernel_vm_range(start, end, 1);
+	if((start >= start_vm) && (start < end_vm)){
+		if(flush_tlb_kernel_range_common(start, end))
+			atomic_inc(&vmchange_seq);
+	}
 	else fix_range(vma->vm_mm, start, end, 0);
 }
 
@@ -282,24 +136,14 @@
 	fix_range(mm, 0, STACK_TOP, 0);
 
 	seq = atomic_read(&vmchange_seq);
-	if(current->thread.mode.tt.vm_seq == seq) return;
+	if(current->thread.mode.tt.vm_seq == seq)
+		return;
 	current->thread.mode.tt.vm_seq = seq;
-	flush_kernel_vm_range(start_vm, end_vm, 0);
+	flush_tlb_kernel_range_common(start_vm, end_vm);
 }
 
 void force_flush_all_tt(void)
 {
 	fix_range(current->mm, 0, STACK_TOP, 1);
-	flush_kernel_vm_range(start_vm, end_vm, 0);
+	flush_tlb_kernel_range_common(start_vm, end_vm);
 }
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff -Nru a/arch/um/kernel/tt/tracer.c b/arch/um/kernel/tt/tracer.c
--- a/arch/um/kernel/tt/tracer.c	2005-03-11 12:51:41 -08:00
+++ b/arch/um/kernel/tt/tracer.c	2005-03-11 12:51:41 -08:00
@@ -12,8 +12,6 @@
 #include <sched.h>
 #include <string.h>
 #include <sys/mman.h>
-#include <sys/ptrace.h>
-#include <linux/ptrace.h>
 #include <sys/time.h>
 #include <sys/wait.h>
 #include "user.h"
@@ -184,11 +182,13 @@
 int tracer(int (*init_proc)(void *), void *sp)
 {
 	void *task = NULL;
-	unsigned long eip = 0;
 	int status, pid = 0, sig = 0, cont_type, tracing = 0, op = 0;
-	int last_index, proc_id = 0, n, err, old_tracing = 0, strace = 0;
+	int proc_id = 0, n, err, old_tracing = 0, strace = 0;
 	int local_using_sysemu = 0;
-
+#ifdef UML_CONFIG_SYSCALL_DEBUG
+	unsigned long eip = 0;
+	int last_index;
+#endif
 	signal(SIGPIPE, SIG_IGN);
 	setup_tracer_winch();
 	tracing_pid = os_getpid();
@@ -279,22 +279,23 @@
 		else if(WIFSTOPPED(status)){
 			proc_id = pid_to_processor_id(pid);
 			sig = WSTOPSIG(status);
+#ifdef UML_CONFIG_SYSCALL_DEBUG
 			if(signal_index[proc_id] == 1024){
 				signal_index[proc_id] = 0;
 				last_index = 1023;
 			}
 			else last_index = signal_index[proc_id] - 1;
-			if(((sig == SIGPROF) || (sig == SIGVTALRM) || 
+			if(((sig == SIGPROF) || (sig == SIGVTALRM) ||
 			    (sig == SIGALRM)) &&
 			   (signal_record[proc_id][last_index].signal == sig)&&
 			   (signal_record[proc_id][last_index].pid == pid))
 				signal_index[proc_id] = last_index;
 			signal_record[proc_id][signal_index[proc_id]].pid = pid;
 			gettimeofday(&signal_record[proc_id][signal_index[proc_id]].time, NULL);
-			eip = ptrace(PTRACE_PEEKUSER, pid, PT_IP_OFFSET, 0);
+			eip = ptrace(PTRACE_PEEKUSR, pid, PT_IP_OFFSET, 0);
 			signal_record[proc_id][signal_index[proc_id]].addr = eip;
 			signal_record[proc_id][signal_index[proc_id]++].signal = sig;
-			
+#endif
 			if(proc_id == -1){
 				sleeping_process_signal(pid, sig);
 				continue;
@@ -465,19 +466,6 @@
 "    debugger and continued.  This is mostly for debugging crashes\n"
 "    early during boot, and should be pretty much obsoleted by\n"
 "    the debug switch.\n\n"
-);
-
-static int __init uml_honeypot_setup(char *line, int *add)
-{
-	jail_setup("", add);
-	honeypot = 1;
-	return 0;
-}
-__uml_setup("honeypot", uml_honeypot_setup, 
-"honeypot\n"
-"    This makes UML put process stacks in the same location as they are\n"
-"    on the host, allowing expoits such as stack smashes to work against\n"
-"    UML.  This implies 'jail'.\n\n"
 );
 
 /*
diff -Nru a/arch/um/kernel/tt/trap_user.c b/arch/um/kernel/tt/trap_user.c
--- a/arch/um/kernel/tt/trap_user.c	2005-03-11 12:51:47 -08:00
+++ b/arch/um/kernel/tt/trap_user.c	2005-03-11 12:51:47 -08:00
@@ -20,8 +20,6 @@
 	struct signal_info *info;
 	int save_errno = errno, is_user;
 
-	unprotect_kernel_mem();
-
 	/* This is done because to allow SIGSEGV to be delivered inside a SEGV
 	 * handler.  This can happen in copy_user, and if SEGV is disabled,
 	 * the process will die.
@@ -48,7 +46,6 @@
 	}
 	*r = save_regs;
 	errno = save_errno;
-	if(is_user) protect_kernel_mem();
 }
 
 /*
diff -Nru a/arch/um/kernel/user_util.c b/arch/um/kernel/user_util.c
--- a/arch/um/kernel/user_util.c	2005-03-11 12:51:41 -08:00
+++ b/arch/um/kernel/user_util.c	2005-03-11 12:51:41 -08:00
@@ -10,7 +10,6 @@
 #include <setjmp.h>
 #include <sys/mman.h>
 #include <sys/stat.h>
-#include <sys/ptrace.h>
 #include <sys/utsname.h>
 #include <sys/param.h>
 #include <sys/time.h>
@@ -29,6 +28,7 @@
 #include "mem_user.h"
 #include "init.h"
 #include "helper.h"
+#include "ptrace_user.h"
 #include "uml-config.h"
 
 #define COMMAND_LINE_SIZE _POSIX_ARG_MAX
diff -Nru a/arch/um/os-Linux/process.c b/arch/um/os-Linux/process.c
--- a/arch/um/os-Linux/process.c	2005-03-11 12:51:41 -08:00
+++ b/arch/um/os-Linux/process.c	2005-03-11 12:51:41 -08:00
@@ -8,9 +8,9 @@
 #include <errno.h>
 #include <signal.h>
 #include <linux/unistd.h>
-#include <sys/ptrace.h>
 #include <sys/mman.h>
 #include <sys/wait.h>
+#include "ptrace_user.h"
 #include "os.h"
 #include "user.h"
 #include "user_util.h"
diff -Nru a/arch/um/os-Linux/sys-i386/registers.c b/arch/um/os-Linux/sys-i386/registers.c
--- a/arch/um/os-Linux/sys-i386/registers.c	2005-03-11 12:51:42 -08:00
+++ b/arch/um/os-Linux/sys-i386/registers.c	2005-03-11 12:51:42 -08:00
@@ -5,7 +5,7 @@
 
 #include <errno.h>
 #include <string.h>
-#include <sys/ptrace.h>
+#include "sysdep/ptrace_user.h"
 #include "sysdep/ptrace.h"
 #include "uml-config.h"
 #include "skas_ptregs.h"
@@ -25,6 +25,23 @@
 	memcpy(to->skas.fp, exec_fp_regs, sizeof(to->skas.fp));
 	if(have_fpx_regs)
 		memcpy(to->skas.xfp, exec_fpx_regs, sizeof(to->skas.xfp));
+}
+
+/* XXX These need to use [GS]ETFPXREGS and copy_sc_{to,from}_user_skas needs
+ * to pass in a sufficiently large buffer
+ */
+int save_fp_registers(int pid, unsigned long *fp_regs)
+{
+	if(ptrace(PTRACE_GETFPREGS, pid, 0, fp_regs) < 0)
+		return(-errno);
+	return(0);
+}
+
+int restore_fp_registers(int pid, unsigned long *fp_regs)
+{
+	if(ptrace(PTRACE_SETFPREGS, pid, 0, fp_regs) < 0)
+		return(-errno);
+	return(0);
 }
 
 static int move_registers(int pid, int int_op, union uml_pt_regs *regs,
diff -Nru a/arch/um/os-Linux/sys-x86_64/registers.c b/arch/um/os-Linux/sys-x86_64/registers.c
--- a/arch/um/os-Linux/sys-x86_64/registers.c	2005-03-11 12:51:40 -08:00
+++ b/arch/um/os-Linux/sys-x86_64/registers.c	2005-03-11 12:51:40 -08:00
@@ -5,8 +5,7 @@
 
 #include <errno.h>
 #include <string.h>
-#include <sys/ptrace.h>
-#include "sysdep/ptrace.h"
+#include "ptrace_user.h"
 #include "uml-config.h"
 #include "skas_ptregs.h"
 #include "registers.h"
diff -Nru a/arch/um/os-Linux/util/Makefile b/arch/um/os-Linux/util/Makefile
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/um/os-Linux/util/Makefile	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,4 @@
+hostprogs-y		:= mk_user_constants
+always			:= $(hostprogs-y)
+
+mk_user_constants-objs	:= mk_user_constants.o
diff -Nru a/arch/um/os-Linux/util/mk_user_constants.c b/arch/um/os-Linux/util/mk_user_constants.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/arch/um/os-Linux/util/mk_user_constants.c	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,29 @@
+#include <stdio.h>
+#include <asm/types.h>
+/* For some reason, x86_64 nowhere defines u64 and u32, even though they're
+ * used throughout the headers.
+ */
+typedef __u64 u64;
+typedef __u32 u32;
+#include <asm/user.h>
+
+int main(int argc, char **argv)
+{
+  printf("/*\n");
+  printf(" * Generated by mk_user_constants\n");
+  printf(" */\n");
+  printf("\n");
+  printf("#ifndef __UM_USER_CONSTANTS_H\n");
+  printf("#define __UM_USER_CONSTANTS_H\n");
+  printf("\n");
+  /* I'd like to use FRAME_SIZE from ptrace.h here, but that's wrong on
+   * x86_64 (216 vs 168 bytes).  user_regs_struct is the correct size on
+   * both x86_64 and i386.
+   */
+  printf("#define UM_FRAME_SIZE %d\n", (int) sizeof(struct user_regs_struct));
+
+  printf("\n");
+  printf("#endif\n");
+
+  return(0);
+}
diff -Nru a/arch/um/sys-i386/ptrace.c b/arch/um/sys-i386/ptrace.c
--- a/arch/um/sys-i386/ptrace.c	2005-03-11 12:51:52 -08:00
+++ b/arch/um/sys-i386/ptrace.c	2005-03-11 12:51:52 -08:00
@@ -10,7 +10,7 @@
 #include "asm/ptrace.h"
 #include "asm/uaccess.h"
 #include "asm/unistd.h"
-#include "ptrace_user.h"
+#include "sysdep/ptrace.h"
 #include "sysdep/sigcontext.h"
 #include "sysdep/sc.h"
 
diff -Nru a/arch/um/sys-i386/ptrace_user.c b/arch/um/sys-i386/ptrace_user.c
--- a/arch/um/sys-i386/ptrace_user.c	2005-03-11 12:51:52 -08:00
+++ b/arch/um/sys-i386/ptrace_user.c	2005-03-11 12:51:52 -08:00
@@ -7,8 +7,8 @@
 #include <errno.h>
 #include <unistd.h>
 #include <linux/stddef.h>
-#include <sys/ptrace.h>
-#include <asm/ptrace.h>
+#include "ptrace_user.h"
+/* Grr, asm/user.h includes asm/ptrace.h, so has to follow ptrace_user.h */
 #include <asm/user.h>
 #include "kern_util.h"
 #include "sysdep/thread.h"
@@ -52,7 +52,7 @@
 	nregs = sizeof(dummy->u_debugreg)/sizeof(dummy->u_debugreg[0]);
 	for(i = 0; i < nregs; i++){
 		if((i == 4) || (i == 5)) continue;
-		if(ptrace(PTRACE_POKEUSER, pid, &dummy->u_debugreg[i],
+		if(ptrace(PTRACE_POKEUSR, pid, &dummy->u_debugreg[i],
 			  regs[i]) < 0)
 			printk("write_debugregs - ptrace failed on "
 			       "register %d, value = 0x%x, errno = %d\n", i,
@@ -68,7 +68,7 @@
 	dummy = NULL;
 	nregs = sizeof(dummy->u_debugreg)/sizeof(dummy->u_debugreg[0]);
 	for(i = 0; i < nregs; i++){
-		regs[i] = ptrace(PTRACE_PEEKUSER, pid,
+		regs[i] = ptrace(PTRACE_PEEKUSR, pid,
 				 &dummy->u_debugreg[i], 0);
 	}
 }
diff -Nru a/arch/um/sys-i386/signal.c b/arch/um/sys-i386/signal.c
--- a/arch/um/sys-i386/signal.c	2005-03-11 12:51:48 -08:00
+++ b/arch/um/sys-i386/signal.c	2005-03-11 12:51:48 -08:00
@@ -11,8 +11,8 @@
 #include "asm/unistd.h"
 #include "frame_kern.h"
 #include "signal_user.h"
-#include "ptrace_user.h"
 #include "sigcontext.h"
+#include "registers.h"
 #include "mode.h"
 
 #ifdef CONFIG_MODE_SKAS
@@ -51,7 +51,7 @@
 	regs->regs.skas.fault_type = FAULT_WRITE(sc.err);
 	regs->regs.skas.trap_type = sc.trapno;
 
-	err = ptrace_setfpregs(userspace_pid[0], fpregs);
+	err = restore_fp_registers(userspace_pid[0], fpregs);
 	if(err < 0){
 	  	printk("copy_sc_from_user_skas - PTRACE_SETFPREGS failed, "
 		       "errno = %d\n", err);
@@ -90,7 +90,7 @@
 	sc.err = TO_SC_ERR(fault_type);
 	sc.trapno = regs->regs.skas.trap_type;
 
-	err = ptrace_getfpregs(userspace_pid[0], fpregs);
+	err = save_fp_registers(userspace_pid[0], fpregs);
 	if(err < 0){
 	  	printk("copy_sc_to_user_skas - PTRACE_GETFPREGS failed, "
 		       "errno = %d\n", err);
@@ -108,6 +108,15 @@
 #endif
 
 #ifdef CONFIG_MODE_TT
+
+/* These copy a sigcontext to/from userspace.  They copy the fpstate pointer,
+ * blowing away the old, good one.  So, that value is saved, and then restored
+ * after the sigcontext copy.  In copy_from, the variable holding the saved
+ * fpstate pointer, and the sigcontext that it should be restored to are both
+ * in the kernel, so we can just restore using an assignment.  In copy_to, the
+ * saved pointer is in the kernel, but the sigcontext is in userspace, so we
+ * copy_to_user it.
+ */
 int copy_sc_from_user_tt(struct sigcontext *to, struct sigcontext *from,
 			 int fpsize)
 {
@@ -120,11 +129,9 @@
 	sigs = to->oldmask;
 	err = copy_from_user(to, from, sizeof(*to));
 	to->oldmask = sigs;
-	if(to_fp != NULL){
-		err |= copy_from_user(&to->fpstate, &to_fp,
-				      sizeof(to->fpstate));
+	to->fpstate = to_fp;
+	if(to_fp != NULL)
 		err |= copy_from_user(to_fp, from_fp, fpsize);
-	}
 	return(err);
 }
 
@@ -138,8 +145,7 @@
 	from_fp = from->fpstate;
 	err = copy_to_user(to, from, sizeof(*to));
 	if(from_fp != NULL){
-		err |= copy_to_user(&to->fpstate, &to_fp,
-					 sizeof(to->fpstate));
+		err |= copy_to_user(&to->fpstate, &to_fp, sizeof(to->fpstate));
 		err |= copy_to_user(to_fp, from_fp, fpsize);
 	}
 	return(err);
@@ -303,7 +309,7 @@
 
 long sys_sigreturn(struct pt_regs regs)
 {
-	unsigned long __user sp = PT_REGS_SP(&current->thread.regs);
+	unsigned long sp = PT_REGS_SP(&current->thread.regs);
 	struct sigframe __user *frame = (struct sigframe *)(sp - 8);
 	sigset_t set;
 	struct sigcontext __user *sc = &frame->sc;
diff -Nru a/arch/um/sys-i386/syscalls.c b/arch/um/sys-i386/syscalls.c
--- a/arch/um/sys-i386/syscalls.c	2005-03-11 12:51:46 -08:00
+++ b/arch/um/sys-i386/syscalls.c	2005-03-11 12:51:46 -08:00
@@ -88,7 +88,7 @@
  * This is really horribly ugly.
  */
 long sys_ipc (uint call, int first, int second,
-	     int third, void *__user ptr, long fifth)
+	     int third, void __user *ptr, long fifth)
 {
 	int version, ret;
 
diff -Nru a/arch/um/sys-ppc/ptrace_user.c b/arch/um/sys-ppc/ptrace_user.c
--- a/arch/um/sys-ppc/ptrace_user.c	2005-03-11 12:51:41 -08:00
+++ b/arch/um/sys-ppc/ptrace_user.c	2005-03-11 12:51:41 -08:00
@@ -1,4 +1,3 @@
-#include <sys/ptrace.h>
 #include <errno.h>
 #include <asm/ptrace.h>
 #include "sysdep/ptrace.h"
@@ -8,7 +7,7 @@
     int i;
     for (i=0; i < sizeof(struct sys_pt_regs)/sizeof(PPC_REG); ++i) {
 	errno = 0;
-	regs_out->regs[i] = ptrace(PTRACE_PEEKUSER, pid, i*4, 0);
+	regs_out->regs[i] = ptrace(PTRACE_PEEKUSR, pid, i*4, 0);
 	if (errno) {
 	    return -errno;
 	}
@@ -21,7 +20,7 @@
     int i;
     for (i=0; i < sizeof(struct sys_pt_regs)/sizeof(PPC_REG); ++i) {
 	if (i != 34 /* FIXME: PT_ORIG_R3 */ && i <= PT_MQ) {
-	    if (ptrace(PTRACE_POKEUSER, pid, i*4, regs_in->regs[i]) < 0) {
+	    if (ptrace(PTRACE_POKEUSR, pid, i*4, regs_in->regs[i]) < 0) {
 		return -errno;
 	    }
 	}
diff -Nru a/arch/um/sys-x86_64/ptrace_user.c b/arch/um/sys-x86_64/ptrace_user.c
--- a/arch/um/sys-x86_64/ptrace_user.c	2005-03-11 12:51:42 -08:00
+++ b/arch/um/sys-x86_64/ptrace_user.c	2005-03-11 12:51:42 -08:00
@@ -6,9 +6,7 @@
 
 #include <stddef.h>
 #include <errno.h>
-#define __FRAME_OFFSETS
-#include <sys/ptrace.h>
-#include <asm/ptrace.h>
+#include "ptrace_user.h"
 #include "user.h"
 #include "kern_constants.h"
 
@@ -42,23 +40,12 @@
 void arch_leave_kernel(void *task, int pid)
 {
 #ifdef UM_USER_CS
-	if(ptrace(PTRACE_POKEUSER, pid, CS, UM_USER_CS) < 0)
-		tracer_panic("POKEUSER CS failed");
+        if(ptrace(PTRACE_POKEUSR, pid, CS, UM_USER_CS) < 0)
+                printk("POKEUSR CS failed");
 #endif
 
-	if(ptrace(PTRACE_POKEUSER, pid, DS, __USER_DS) < 0)
-		tracer_panic("POKEUSER DS failed");
-	if(ptrace(PTRACE_POKEUSER, pid, ES, __USER_DS) < 0)
-		tracer_panic("POKEUSER ES failed");
+        if(ptrace(PTRACE_POKEUSR, pid, DS, __USER_DS) < 0)
+                printk("POKEUSR DS failed");
+        if(ptrace(PTRACE_POKEUSR, pid, ES, __USER_DS) < 0)
+                printk("POKEUSR ES failed");
 }
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
diff -Nru a/arch/um/sys-x86_64/signal.c b/arch/um/sys-x86_64/signal.c
--- a/arch/um/sys-x86_64/signal.c	2005-03-11 12:51:41 -08:00
+++ b/arch/um/sys-x86_64/signal.c	2005-03-11 12:51:41 -08:00
@@ -237,7 +237,7 @@
 
 long sys_rt_sigreturn(struct pt_regs *regs)
 {
-	unsigned long __user sp = PT_REGS_SP(&current->thread.regs);
+	unsigned long sp = PT_REGS_SP(&current->thread.regs);
 	struct rt_sigframe __user *frame =
 		(struct rt_sigframe __user *)(sp - 8);
 	struct ucontext __user *uc = &frame->uc;
diff -Nru a/arch/um/sys-x86_64/syscalls.c b/arch/um/sys-x86_64/syscalls.c
--- a/arch/um/sys-x86_64/syscalls.c	2005-03-11 12:51:52 -08:00
+++ b/arch/um/sys-x86_64/syscalls.c	2005-03-11 12:51:52 -08:00
@@ -36,15 +36,11 @@
 #endif
 
 #ifdef CONFIG_MODE_SKAS
-extern int userspace_pid;
-
-#ifndef __NR_mm_indirect
-#define __NR_mm_indirect 241
-#endif
+extern int userspace_pid[];
 
 long sys_modify_ldt_skas(int func, void *ptr, unsigned long bytecount)
 {
-	unsigned long args[6];
+	struct ptrace_ldt ldt;
         void *buf;
         int res, n;
 
@@ -66,12 +62,11 @@
                 goto out;
         }
 
-	args[0] = func;
-	args[1] = (unsigned long) buf;
-	args[2] = bytecount;
-	res = syscall(__NR_mm_indirect, &current->mm->context.u,
-		      __NR_modify_ldt, args);
-
+	ldt = ((struct ptrace_ldt) { .func	= func,
+				     .ptr	= buf,
+				     .bytecount = bytecount });
+#warning Need to look up userspace_pid by cpu
+	res = ptrace(PTRACE_LDT, userspace_pid[0], 0, (unsigned long) &ldt);
         if(res < 0)
                 goto out;
 
diff -Nru a/arch/x86_64/Kconfig b/arch/x86_64/Kconfig
--- a/arch/x86_64/Kconfig	2005-03-11 12:51:50 -08:00
+++ b/arch/x86_64/Kconfig	2005-03-11 12:51:50 -08:00
@@ -350,6 +350,24 @@
 	help
 	   Additional support for intel specific MCE features such as
 	   the thermal monitor.
+
+config SECCOMP
+	bool "Enable seccomp to safely compute untrusted bytecode"
+	depends on PROC_FS
+	default y
+	help
+	  This kernel feature is useful for number crunching applications
+	  that may need to compute untrusted bytecode during their
+	  execution. By using pipes or other transports made available to
+	  the process as file descriptors supporting the read/write
+	  syscalls, it's possible to isolate those applications in
+	  their own address space using seccomp. Once seccomp is
+	  enabled via /proc/<pid>/seccomp, it cannot be disabled
+	  and the task is only allowed to execute a few safe syscalls
+	  defined by each seccomp mode.
+
+	  If unsure, say Y. Only embedded should say N here.
+
 endmenu
 
 #
diff -Nru a/arch/x86_64/defconfig b/arch/x86_64/defconfig
--- a/arch/x86_64/defconfig	2005-03-11 12:51:47 -08:00
+++ b/arch/x86_64/defconfig	2005-03-11 12:51:47 -08:00
@@ -672,7 +672,6 @@
 #
 CONFIG_AGP=y
 CONFIG_AGP_AMD64=y
-# CONFIG_AGP_INTEL_MCH is not set
 # CONFIG_DRM is not set
 # CONFIG_MWAVE is not set
 CONFIG_RAW_DRIVER=y
diff -Nru a/arch/x86_64/ia32/ia32entry.S b/arch/x86_64/ia32/ia32entry.S
--- a/arch/x86_64/ia32/ia32entry.S	2005-03-11 12:51:43 -08:00
+++ b/arch/x86_64/ia32/ia32entry.S	2005-03-11 12:51:43 -08:00
@@ -78,7 +78,7 @@
  	.quad 1b,ia32_badarg
  	.previous	
 	GET_THREAD_INFO(%r10)
-	testl  $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT),threadinfo_flags(%r10)
+	testl  $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SECCOMP),threadinfo_flags(%r10)
 	jnz  sysenter_tracesys
 sysenter_do_call:	
 	cmpl	$(IA32_NR_syscalls),%eax
@@ -163,7 +163,7 @@
 	.quad 1b,ia32_badarg
 	.previous	
 	GET_THREAD_INFO(%r10)
-	testl $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT),threadinfo_flags(%r10)
+	testl $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SECCOMP),threadinfo_flags(%r10)
 	jnz   cstar_tracesys
 cstar_do_call:	
 	cmpl $IA32_NR_syscalls,%eax
@@ -236,7 +236,7 @@
 	   this could be a problem. */
 	SAVE_ARGS 0,0,1
 	GET_THREAD_INFO(%r10)
-	testl $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT),threadinfo_flags(%r10)
+	testl $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SECCOMP),threadinfo_flags(%r10)
 	jnz ia32_tracesys
 ia32_do_syscall:	
 	cmpl $(IA32_NR_syscalls),%eax
@@ -590,7 +590,7 @@
 	.quad compat_sys_mq_notify
 	.quad compat_sys_mq_getsetattr
 	.quad quiet_ni_syscall		/* reserved for kexec */
-	.quad sys32_waitid
+	.quad compat_sys_waitid
 	.quad quiet_ni_syscall		/* sys_altroot */
 	.quad sys_add_key
 	.quad sys_request_key
diff -Nru a/arch/x86_64/ia32/sys_ia32.c b/arch/x86_64/ia32/sys_ia32.c
--- a/arch/x86_64/ia32/sys_ia32.c	2005-03-11 12:51:42 -08:00
+++ b/arch/x86_64/ia32/sys_ia32.c	2005-03-11 12:51:42 -08:00
@@ -955,32 +955,6 @@
         return do_fork(clone_flags, newsp, regs, 0, parent_tid, child_tid);
 }
 
-asmlinkage long sys32_waitid(int which, compat_pid_t pid,
-			     compat_siginfo_t __user *uinfo, int options,
-			     struct compat_rusage __user *uru)
-{
-	siginfo_t info;
-	struct rusage ru;
-	long ret;
-	mm_segment_t old_fs = get_fs();
-
-	info.si_signo = 0;
-	set_fs (KERNEL_DS);
-	ret = sys_waitid(which, pid, (siginfo_t __user *) &info, options,
-			 uru ? &ru : NULL);
-	set_fs (old_fs);
-
-	if (ret < 0 || info.si_signo == 0)
-		return ret;
-
-	if (uru && (ret = put_compat_rusage(&ru, uru)))
-		return ret;
-
-	BUG_ON(info.si_code & __SI_MASK);
-	info.si_code |= __SI_CHLD;
-	return copy_siginfo_to_user32(uinfo, &info);
-}
-
 /*
  * Some system calls that need sign extended arguments. This could be done by a generic wrapper.
  */ 
@@ -1019,31 +993,19 @@
 	return fd;
 }
 
-struct sigevent32 { 
-	u32 sigev_value;
-	u32 sigev_signo; 
-	u32 sigev_notify; 
-	u32 payload[(64 / 4) - 3]; 
-}; 
-
 extern asmlinkage long
 sys_timer_create(clockid_t which_clock,
 		 struct sigevent __user *timer_event_spec,
 		 timer_t __user * created_timer_id);
 
 long
-sys32_timer_create(u32 clock, struct sigevent32 __user *se32, timer_t __user *timer_id)
+sys32_timer_create(u32 clock, struct compat_sigevent __user *se32, timer_t __user *timer_id)
 {
 	struct sigevent __user *p = NULL;
 	if (se32) { 
 		struct sigevent se;
 		p = compat_alloc_user_space(sizeof(struct sigevent));
-		memset(&se, 0, sizeof(struct sigevent)); 
-		if (get_user(se.sigev_value.sival_int,  &se32->sigev_value) ||
-		    __get_user(se.sigev_signo, &se32->sigev_signo) ||
-		    __get_user(se.sigev_notify, &se32->sigev_notify) ||
-		    __copy_from_user(&se._sigev_un._pad, &se32->payload, 
-				     sizeof(se32->payload)) ||
+		if (get_compat_sigevent(&se, se32) ||
 		    copy_to_user(p, &se, sizeof(se)))
 			return -EFAULT;
 	} 
diff -Nru a/arch/x86_64/kernel/entry.S b/arch/x86_64/kernel/entry.S
--- a/arch/x86_64/kernel/entry.S	2005-03-11 12:51:42 -08:00
+++ b/arch/x86_64/kernel/entry.S	2005-03-11 12:51:42 -08:00
@@ -184,7 +184,7 @@
 	movq  %rax,ORIG_RAX-ARGOFFSET(%rsp) 
 	movq  %rcx,RIP-ARGOFFSET(%rsp)  
 	GET_THREAD_INFO(%rcx)
-	testl $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT),threadinfo_flags(%rcx)
+	testl $(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SECCOMP),threadinfo_flags(%rcx)
 	jnz tracesys
 	cmpq $__NR_syscall_max,%rax
 	ja badsys
diff -Nru a/arch/x86_64/kernel/pci-gart.c b/arch/x86_64/kernel/pci-gart.c
--- a/arch/x86_64/kernel/pci-gart.c	2005-03-11 12:51:42 -08:00
+++ b/arch/x86_64/kernel/pci-gart.c	2005-03-11 12:51:42 -08:00
@@ -789,7 +789,7 @@
 	/* Add other K8 AGP bridge drivers here */
 	no_agp = no_agp || 
 		(agp_amd64_init() < 0) || 
-		(agp_copy_info(&info) < 0); 
+		(agp_copy_info(agp_bridge, &info) < 0);
 #endif	
 
 	if (swiotlb) { 
diff -Nru a/arch/x86_64/kernel/process.c b/arch/x86_64/kernel/process.c
--- a/arch/x86_64/kernel/process.c	2005-03-11 12:51:46 -08:00
+++ b/arch/x86_64/kernel/process.c	2005-03-11 12:51:46 -08:00
@@ -33,6 +33,7 @@
 #include <linux/irq.h>
 #include <linux/ptrace.h>
 #include <linux/utsname.h>
+#include <linux/random.h>
 
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
@@ -748,4 +749,11 @@
 	elf_core_copy_regs(regs, &ptregs);
  
 	return 1;
+}
+
+unsigned long arch_align_stack(unsigned long sp)
+{
+	if (randomize_va_space)
+		sp -= get_random_int() % 8192;
+	return sp & ~0xf;
 }
diff -Nru a/arch/x86_64/kernel/ptrace.c b/arch/x86_64/kernel/ptrace.c
--- a/arch/x86_64/kernel/ptrace.c	2005-03-11 12:51:42 -08:00
+++ b/arch/x86_64/kernel/ptrace.c	2005-03-11 12:51:42 -08:00
@@ -17,6 +17,7 @@
 #include <linux/user.h>
 #include <linux/security.h>
 #include <linux/audit.h>
+#include <linux/seccomp.h>
 
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
@@ -521,6 +522,9 @@
 
 asmlinkage void syscall_trace_enter(struct pt_regs *regs)
 {
+	/* do the secure computing check first */
+	secure_computing(regs->orig_rax);
+
 	if (unlikely(current->audit_context))
 		audit_syscall_entry(current, regs->orig_rax,
 				    regs->rdi, regs->rsi,
diff -Nru a/arch/x86_64/mm/extable.c b/arch/x86_64/mm/extable.c
--- a/arch/x86_64/mm/extable.c	2005-03-11 12:51:51 -08:00
+++ b/arch/x86_64/mm/extable.c	2005-03-11 12:51:51 -08:00
@@ -33,26 +33,3 @@
         }
         return NULL;
 }
-
-/* When an exception handler is in an non standard section (like __init)
-   the fixup table can end up unordered. Fix that here. */
-void sort_extable(struct exception_table_entry *start,
-		  struct exception_table_entry *finish)
-{
-	struct exception_table_entry *e;
-	int change;
-
-	/* The input is near completely presorted, which makes bubble sort the
-	   best (and simplest) sort algorithm. */
-	do {
-		change = 0;
-		for (e = start+1; e < finish; e++) {
-			if (e->insn < e[-1].insn) {
-				struct exception_table_entry tmp = e[-1];
-				e[-1] = e[0];
-				e[0] = tmp;
-				change = 1;
-			}
-		}
-	} while (change != 0);
-}
diff -Nru a/arch/x86_64/mm/ioremap.c b/arch/x86_64/mm/ioremap.c
--- a/arch/x86_64/mm/ioremap.c	2005-03-11 12:51:51 -08:00
+++ b/arch/x86_64/mm/ioremap.c	2005-03-11 12:51:51 -08:00
@@ -267,8 +267,8 @@
 		p->phys_addr + p->size - 1 < virt_to_phys(high_memory)) {
 		/* p->size includes the guard page, but cpa doesn't like that */
 		change_page_attr(virt_to_page(__va(p->phys_addr)),
-				 (p->size - PAGE_SIZE) >> PAGE_SHIFT,
-				 PAGE_KERNEL); 				 
+				 p->size >> PAGE_SHIFT,
+				 PAGE_KERNEL);
 		global_flush_tlb();
 	} 
 out_unlock:
diff -Nru a/arch/x86_64/pci/mmconfig.c b/arch/x86_64/pci/mmconfig.c
--- a/arch/x86_64/pci/mmconfig.c	2005-03-11 12:51:41 -08:00
+++ b/arch/x86_64/pci/mmconfig.c	2005-03-11 12:51:41 -08:00
@@ -17,12 +17,13 @@
 /* Static virtual mapping of the MMCONFIG aperture */
 char *pci_mmcfg_virt;
 
-static inline char *pci_dev_base(int bus, int devfn)
+static inline char *pci_dev_base(unsigned int bus, unsigned int devfn)
 {
 	return pci_mmcfg_virt + ((bus << 20) | (devfn << 12));
 }
 
-static int pci_mmcfg_read(int seg, int bus, int devfn, int reg, int len, u32 *value)
+static int pci_mmcfg_read(unsigned int seg, unsigned int bus,
+			  unsigned int devfn, int reg, int len, u32 *value)
 {
 	char *addr = pci_dev_base(bus, devfn); 
 
@@ -44,7 +45,8 @@
 	return 0;
 }
 
-static int pci_mmcfg_write(int seg, int bus, int devfn, int reg, int len, u32 value)
+static int pci_mmcfg_write(unsigned int seg, unsigned int bus,
+			   unsigned int devfn, int reg, int len, u32 value)
 {
 	char *addr = pci_dev_base(bus,devfn);
 
diff -Nru a/crypto/Kconfig b/crypto/Kconfig
--- a/crypto/Kconfig	2005-03-11 12:51:51 -08:00
+++ b/crypto/Kconfig	2005-03-11 12:51:51 -08:00
@@ -79,6 +79,19 @@
 	  See also:
 	  <http://planeta.terra.com.br/informatica/paulobarreto/WhirlpoolPage.html>
 
+config CRYPTO_TGR192
+	tristate "Tiger digest algorithms"
+	depends on CRYPTO
+	help
+	  Tiger hash algorithm 192, 160 and 128-bit hashes
+
+	  Tiger is a hash function optimized for 64-bit processors while
+	  still having decent performance on 32-bit processors.
+	  Tiger was developed by Ross Anderson and Eli Biham.
+
+	  See also:
+	  <http://www.cs.technion.ac.il/~biham/Reports/Tiger/>.
+
 config CRYPTO_DES
 	tristate "DES and Triple DES EDE cipher algorithms"
 	depends on CRYPTO
diff -Nru a/crypto/Makefile b/crypto/Makefile
--- a/crypto/Makefile	2005-03-11 12:51:51 -08:00
+++ b/crypto/Makefile	2005-03-11 12:51:51 -08:00
@@ -15,6 +15,7 @@
 obj-$(CONFIG_CRYPTO_SHA256) += sha256.o
 obj-$(CONFIG_CRYPTO_SHA512) += sha512.o
 obj-$(CONFIG_CRYPTO_WP512) += wp512.o
+obj-$(CONFIG_CRYPTO_TGR192) += tgr192.o
 obj-$(CONFIG_CRYPTO_DES) += des.o
 obj-$(CONFIG_CRYPTO_BLOWFISH) += blowfish.o
 obj-$(CONFIG_CRYPTO_TWOFISH) += twofish.o
diff -Nru a/crypto/aes.c b/crypto/aes.c
--- a/crypto/aes.c	2005-03-11 12:51:52 -08:00
+++ b/crypto/aes.c	2005-03-11 12:51:52 -08:00
@@ -64,23 +64,6 @@
 
 #define AES_BLOCK_SIZE		16
 
-static inline 
-u32 generic_rotr32 (const u32 x, const unsigned bits)
-{
-	const unsigned n = bits % 32;
-	return (x >> n) | (x << (32 - n));
-}
-
-static inline 
-u32 generic_rotl32 (const u32 x, const unsigned bits)
-{
-	const unsigned n = bits % 32;
-	return (x << n) | (x >> (32 - n));
-}
-
-#define rotl generic_rotl32
-#define rotr generic_rotr32
-
 /*
  * #define byte(x, nr) ((unsigned char)((x) >> (nr*8))) 
  */
@@ -191,26 +174,26 @@
 
 		t = p;
 		fl_tab[0][i] = t;
-		fl_tab[1][i] = rotl (t, 8);
-		fl_tab[2][i] = rotl (t, 16);
-		fl_tab[3][i] = rotl (t, 24);
+		fl_tab[1][i] = rol32(t, 8);
+		fl_tab[2][i] = rol32(t, 16);
+		fl_tab[3][i] = rol32(t, 24);
 
 		t = ((u32) ff_mult (2, p)) |
 		    ((u32) p << 8) |
 		    ((u32) p << 16) | ((u32) ff_mult (3, p) << 24);
 
 		ft_tab[0][i] = t;
-		ft_tab[1][i] = rotl (t, 8);
-		ft_tab[2][i] = rotl (t, 16);
-		ft_tab[3][i] = rotl (t, 24);
+		ft_tab[1][i] = rol32(t, 8);
+		ft_tab[2][i] = rol32(t, 16);
+		ft_tab[3][i] = rol32(t, 24);
 
 		p = isb_tab[i];
 
 		t = p;
 		il_tab[0][i] = t;
-		il_tab[1][i] = rotl (t, 8);
-		il_tab[2][i] = rotl (t, 16);
-		il_tab[3][i] = rotl (t, 24);
+		il_tab[1][i] = rol32(t, 8);
+		il_tab[2][i] = rol32(t, 16);
+		il_tab[3][i] = rol32(t, 24);
 
 		t = ((u32) ff_mult (14, p)) |
 		    ((u32) ff_mult (9, p) << 8) |
@@ -218,9 +201,9 @@
 		    ((u32) ff_mult (11, p) << 24);
 
 		it_tab[0][i] = t;
-		it_tab[1][i] = rotl (t, 8);
-		it_tab[2][i] = rotl (t, 16);
-		it_tab[3][i] = rotl (t, 24);
+		it_tab[1][i] = rol32(t, 8);
+		it_tab[2][i] = rol32(t, 16);
+		it_tab[3][i] = rol32(t, 24);
 	}
 }
 
@@ -232,14 +215,14 @@
     w   = star_x(v);        \
     t   = w ^ (x);          \
    (y)  = u ^ v ^ w;        \
-   (y) ^= rotr(u ^ t,  8) ^ \
-          rotr(v ^ t, 16) ^ \
-          rotr(t,24)
+   (y) ^= ror32(u ^ t,  8) ^ \
+          ror32(v ^ t, 16) ^ \
+          ror32(t,24)
 
 /* initialise the key schedule from the user supplied key */
 
 #define loop4(i)                                    \
-{   t = rotr(t,  8); t = ls_box(t) ^ rco_tab[i];    \
+{   t = ror32(t,  8); t = ls_box(t) ^ rco_tab[i];    \
     t ^= E_KEY[4 * i];     E_KEY[4 * i + 4] = t;    \
     t ^= E_KEY[4 * i + 1]; E_KEY[4 * i + 5] = t;    \
     t ^= E_KEY[4 * i + 2]; E_KEY[4 * i + 6] = t;    \
@@ -247,7 +230,7 @@
 }
 
 #define loop6(i)                                    \
-{   t = rotr(t,  8); t = ls_box(t) ^ rco_tab[i];    \
+{   t = ror32(t,  8); t = ls_box(t) ^ rco_tab[i];    \
     t ^= E_KEY[6 * i];     E_KEY[6 * i + 6] = t;    \
     t ^= E_KEY[6 * i + 1]; E_KEY[6 * i + 7] = t;    \
     t ^= E_KEY[6 * i + 2]; E_KEY[6 * i + 8] = t;    \
@@ -257,7 +240,7 @@
 }
 
 #define loop8(i)                                    \
-{   t = rotr(t,  8); ; t = ls_box(t) ^ rco_tab[i];  \
+{   t = ror32(t,  8); ; t = ls_box(t) ^ rco_tab[i];  \
     t ^= E_KEY[8 * i];     E_KEY[8 * i + 8] = t;    \
     t ^= E_KEY[8 * i + 1]; E_KEY[8 * i + 9] = t;    \
     t ^= E_KEY[8 * i + 2]; E_KEY[8 * i + 10] = t;   \
diff -Nru a/crypto/cast5.c b/crypto/cast5.c
--- a/crypto/cast5.c	2005-03-11 12:51:46 -08:00
+++ b/crypto/cast5.c	2005-03-11 12:51:46 -08:00
@@ -567,14 +567,11 @@
 	0xeaee6801, 0x8db2a283, 0xea8bf59e
 };
 
-
-#define rol(n,x) ( ((x) << (n)) | ((x) >> (32-(n))) )
-
-#define F1(D,m,r)  (  (I = ((m) + (D))), (I=rol((r),I)),   \
+#define F1(D,m,r)  (  (I = ((m) + (D))), (I=rol32(I,(r))),   \
     (((s1[I >> 24] ^ s2[(I>>16)&0xff]) - s3[(I>>8)&0xff]) + s4[I&0xff]) )
-#define F2(D,m,r)  (  (I = ((m) ^ (D))), (I=rol((r),I)),   \
+#define F2(D,m,r)  (  (I = ((m) ^ (D))), (I=rol32(I,(r))),   \
     (((s1[I >> 24] - s2[(I>>16)&0xff]) + s3[(I>>8)&0xff]) ^ s4[I&0xff]) )
-#define F3(D,m,r)  (  (I = ((m) - (D))), (I=rol((r),I)),   \
+#define F3(D,m,r)  (  (I = ((m) - (D))), (I=rol32(I,(r))),   \
     (((s1[I >> 24] + s2[(I>>16)&0xff]) ^ s3[(I>>8)&0xff]) - s4[I&0xff]) )
 
 
diff -Nru a/crypto/cast6.c b/crypto/cast6.c
--- a/crypto/cast6.c	2005-03-11 12:51:52 -08:00
+++ b/crypto/cast6.c	2005-03-11 12:51:52 -08:00
@@ -33,13 +33,11 @@
 	u8 Kr[12][4];
 };
 
-#define rol(n,x) ( ((x) << (n)) | ((x) >> (32-(n))) )
-
-#define F1(D,r,m)  (  (I = ((m) + (D))), (I=rol((r),I)),   \
+#define F1(D,r,m)  (  (I = ((m) + (D))), (I=rol32(I,(r))),   \
     (((s1[I >> 24] ^ s2[(I>>16)&0xff]) - s3[(I>>8)&0xff]) + s4[I&0xff]) )
-#define F2(D,r,m)  (  (I = ((m) ^ (D))), (I=rol((r),I)),   \
+#define F2(D,r,m)  (  (I = ((m) ^ (D))), (I=rol32(I,(r))),   \
     (((s1[I >> 24] - s2[(I>>16)&0xff]) + s3[(I>>8)&0xff]) ^ s4[I&0xff]) )
-#define F3(D,r,m)  (  (I = ((m) - (D))), (I=rol((r),I)),   \
+#define F3(D,r,m)  (  (I = ((m) - (D))), (I=rol32(I,(r))),   \
     (((s1[I >> 24] + s2[(I>>16)&0xff]) ^ s3[(I>>8)&0xff]) - s4[I&0xff]) )
 
 static const u32 s1[256] = {
diff -Nru a/crypto/michael_mic.c b/crypto/michael_mic.c
--- a/crypto/michael_mic.c	2005-03-11 12:51:47 -08:00
+++ b/crypto/michael_mic.c	2005-03-11 12:51:47 -08:00
@@ -24,18 +24,6 @@
 };
 
 
-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);
@@ -44,13 +32,13 @@
 
 #define michael_block(l, r)	\
 do {				\
-	r ^= rotl(l, 17);	\
+	r ^= rol32(l, 17);	\
 	l += r;			\
 	r ^= xswap(l);		\
 	l += r;			\
-	r ^= rotl(l, 3);	\
+	r ^= rol32(l, 3);	\
 	l += r;			\
-	r ^= rotr(l, 2);	\
+	r ^= ror32(l, 2);	\
 	l += r;			\
 } while (0)
 
diff -Nru a/crypto/serpent.c b/crypto/serpent.c
--- a/crypto/serpent.c	2005-03-11 12:51:42 -08:00
+++ b/crypto/serpent.c	2005-03-11 12:51:42 -08:00
@@ -31,11 +31,9 @@
 #define SERPENT_BLOCK_SIZE		 16
 
 #define PHI 0x9e3779b9UL
-#define ROL(x,r) ((x) = ((x) << (r)) | ((x) >> (32-(r))))
-#define ROR(x,r) ((x) = ((x) >> (r)) | ((x) << (32-(r))))
 
 #define keyiter(a,b,c,d,i,j) \
-        b ^= d; b ^= c; b ^= a; b ^= PHI ^ i; ROL(b,11); k[j] = b;
+        b ^= d; b ^= c; b ^= a; b ^= PHI ^ i; b = rol32(b,11); k[j] = b;
 
 #define loadkeys(x0,x1,x2,x3,i) \
 	x0=k[i]; x1=k[i+1]; x2=k[i+2]; x3=k[i+3];
@@ -48,24 +46,24 @@
 	x1 ^= k[4*(i)+1];        x0 ^= k[4*(i)+0];
 
 #define LK(x0,x1,x2,x3,x4,i)				\
-					ROL(x0,13);	\
-	ROL(x2,3);	x1 ^= x0;	x4  = x0 << 3;	\
+					x0=rol32(x0,13);\
+	x2=rol32(x2,3);	x1 ^= x0;	x4  = x0 << 3;	\
 	x3 ^= x2;	x1 ^= x2;			\
-	ROL(x1,1);	x3 ^= x4;			\
-	ROL(x3,7);	x4  = x1;			\
+	x1=rol32(x1,1);	x3 ^= x4;			\
+	x3=rol32(x3,7);	x4  = x1;			\
 	x0 ^= x1;	x4 <<= 7;	x2 ^= x3;	\
 	x0 ^= x3;	x2 ^= x4;	x3 ^= k[4*i+3];	\
-	x1 ^= k[4*i+1];	ROL(x0,5);	ROL(x2,22);	\
+	x1 ^= k[4*i+1];	x0=rol32(x0,5);	x2=rol32(x2,22);\
 	x0 ^= k[4*i+0];	x2 ^= k[4*i+2];
 
 #define KL(x0,x1,x2,x3,x4,i)				\
 	x0 ^= k[4*i+0];	x1 ^= k[4*i+1];	x2 ^= k[4*i+2];	\
-	x3 ^= k[4*i+3];	ROR(x0,5);	ROR(x2,22);	\
+	x3 ^= k[4*i+3];	x0=ror32(x0,5);	x2=ror32(x2,22);\
 	x4 =  x1;	x2 ^= x3;	x0 ^= x3;	\
-	x4 <<= 7;	x0 ^= x1;	ROR(x1,1);	\
-	x2 ^= x4;	ROR(x3,7);	x4 = x0 << 3;	\
-	x1 ^= x0;	x3 ^= x4;	ROR(x0,13);	\
-	x1 ^= x2;	x3 ^= x2;	ROR(x2,3);
+	x4 <<= 7;	x0 ^= x1;	x1=ror32(x1,1);	\
+	x2 ^= x4;	x3=ror32(x3,7);	x4 = x0 << 3;	\
+	x1 ^= x0;	x3 ^= x4;	x0=ror32(x0,13);\
+	x1 ^= x2;	x3 ^= x2;	x2=ror32(x2,3);
 
 #define S0(x0,x1,x2,x3,x4)				\
 					x4  = x3;	\
diff -Nru a/crypto/sha1.c b/crypto/sha1.c
--- a/crypto/sha1.c	2005-03-11 12:51:42 -08:00
+++ b/crypto/sha1.c	2005-03-11 12:51:42 -08:00
@@ -4,8 +4,7 @@
  * SHA1 Secure Hash Algorithm.
  *
  * Derived from cryptoapi implementation, adapted for in-place
- * scatterlist interface.  Originally based on the public domain
- * implementation written by Steve Reid.
+ * scatterlist interface.
  *
  * Copyright (c) Alan Smithee.
  * Copyright (c) Andrew McDonald <andrew@mcdonald.org.uk>
@@ -13,7 +12,7 @@
  *
  * 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) 
+ * Software Foundation; either version 2 of the License, or (at your option)
  * any later version.
  *
  */
@@ -21,89 +20,19 @@
 #include <linux/module.h>
 #include <linux/mm.h>
 #include <linux/crypto.h>
+#include <linux/cryptohash.h>
 #include <asm/scatterlist.h>
 #include <asm/byteorder.h>
 
 #define SHA1_DIGEST_SIZE	20
 #define SHA1_HMAC_BLOCK_SIZE	64
 
-static inline u32 rol(u32 value, u32 bits)
-{
-	return (((value) << (bits)) | ((value) >> (32 - (bits))));
-}
-
-/* blk0() and blk() perform the initial expand. */
-/* I got the idea of expanding during the round function from SSLeay */
-# define blk0(i) block32[i]
-
-#define blk(i) (block32[i&15] = rol(block32[(i+13)&15]^block32[(i+8)&15] \
-    ^block32[(i+2)&15]^block32[i&15],1))
-
-/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
-#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5); \
-                        w=rol(w,30);
-#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5); \
-                        w=rol(w,30);
-#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30);
-#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5); \
-                        w=rol(w,30);
-#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30);
-
 struct sha1_ctx {
         u64 count;
         u32 state[5];
         u8 buffer[64];
 };
 
-/* Hash a single 512-bit block. This is the core of the algorithm. */
-static void sha1_transform(u32 *state, const u8 *in)
-{
-	u32 a, b, c, d, e;
-	u32 block32[16];
-
-	/* convert/copy data to workspace */
-	for (a = 0; a < sizeof(block32)/sizeof(u32); a++)
-	  block32[a] = be32_to_cpu (((const u32 *)in)[a]);
-
-	/* Copy context->state[] to working vars */
-	a = state[0];
-	b = state[1];
-	c = state[2];
-	d = state[3];
-	e = state[4];
-
-	/* 4 rounds of 20 operations each. Loop unrolled. */
-	R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3);
-	R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7);
-	R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11);
-	R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15);
-	R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19);
-	R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23);
-	R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27);
-	R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31);
-	R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35);
-	R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39);
-	R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43);
-	R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47);
-	R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51);
-	R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55);
-	R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59);
-	R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63);
-	R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67);
-	R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71);
-	R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75);
-	R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79);
-	/* Add the working vars back into context.state[] */
-	state[0] += a;
-	state[1] += b;
-	state[2] += c;
-	state[3] += d;
-	state[4] += e;
-	/* Wipe variables */
-	a = b = c = d = e = 0;
-	memset (block32, 0x00, sizeof block32);
-}
-
 static void sha1_init(void *ctx)
 {
 	struct sha1_ctx *sctx = ctx;
@@ -120,19 +49,21 @@
 {
 	struct sha1_ctx *sctx = ctx;
 	unsigned int i, j;
+	u32 temp[SHA_WORKSPACE_WORDS];
 
 	j = (sctx->count >> 3) & 0x3f;
 	sctx->count += len << 3;
 
 	if ((j + len) > 63) {
 		memcpy(&sctx->buffer[j], data, (i = 64-j));
-		sha1_transform(sctx->state, sctx->buffer);
+		sha_transform(sctx->state, sctx->buffer, temp);
 		for ( ; i + 63 < len; i += 64) {
-			sha1_transform(sctx->state, &data[i]);
+			sha_transform(sctx->state, &data[i], temp);
 		}
 		j = 0;
 	}
 	else i = 0;
+	memset(temp, 0, sizeof(temp));
 	memcpy(&sctx->buffer[j], &data[i], len - i);
 }
 
diff -Nru a/crypto/sha256.c b/crypto/sha256.c
--- a/crypto/sha256.c	2005-03-11 12:51:42 -08:00
+++ b/crypto/sha256.c	2005-03-11 12:51:42 -08:00
@@ -42,15 +42,10 @@
 	return (x & y) | (z & (x | y));
 }
 
-static inline u32 RORu32(u32 x, u32 y)
-{
-	return (x >> y) | (x << (32 - y));
-}
-
-#define e0(x)       (RORu32(x, 2) ^ RORu32(x,13) ^ RORu32(x,22))
-#define e1(x)       (RORu32(x, 6) ^ RORu32(x,11) ^ RORu32(x,25))
-#define s0(x)       (RORu32(x, 7) ^ RORu32(x,18) ^ (x >> 3))
-#define s1(x)       (RORu32(x,17) ^ RORu32(x,19) ^ (x >> 10))
+#define e0(x)       (ror32(x, 2) ^ ror32(x,13) ^ ror32(x,22))
+#define e1(x)       (ror32(x, 6) ^ ror32(x,11) ^ ror32(x,25))
+#define s0(x)       (ror32(x, 7) ^ ror32(x,18) ^ (x >> 3))
+#define s1(x)       (ror32(x,17) ^ ror32(x,19) ^ (x >> 10))
 
 #define H0         0x6a09e667
 #define H1         0xbb67ae85
diff -Nru a/crypto/tcrypt.c b/crypto/tcrypt.c
--- a/crypto/tcrypt.c	2005-03-11 12:51:50 -08:00
+++ b/crypto/tcrypt.c	2005-03-11 12:51:50 -08:00
@@ -695,6 +695,9 @@
 		test_hash("wp512", wp512_tv_template, WP512_TEST_VECTORS);
 		test_hash("wp384", wp384_tv_template, WP384_TEST_VECTORS);
 		test_hash("wp256", wp256_tv_template, WP256_TEST_VECTORS);
+		test_hash("tgr192", tgr192_tv_template, TGR192_TEST_VECTORS);
+		test_hash("tgr160", tgr160_tv_template, TGR160_TEST_VECTORS);
+		test_hash("tgr128", tgr128_tv_template, TGR128_TEST_VECTORS);
 		test_deflate();
 		test_crc32c();
 #ifdef CONFIG_CRYPTO_HMAC
@@ -830,6 +833,19 @@
 		test_cipher ("anubis", MODE_ECB, DECRYPT, anubis_dec_tv_template, ANUBIS_DEC_TEST_VECTORS);
 		test_cipher ("anubis", MODE_CBC, ENCRYPT, anubis_cbc_enc_tv_template, ANUBIS_CBC_ENC_TEST_VECTORS);
 		test_cipher ("anubis", MODE_CBC, DECRYPT, anubis_cbc_dec_tv_template, ANUBIS_CBC_ENC_TEST_VECTORS);
+		break;
+
+	case 27:
+		test_hash("tgr192", tgr192_tv_template, TGR192_TEST_VECTORS);
+		break;
+
+	case 28:
+
+		test_hash("tgr160", tgr160_tv_template, TGR160_TEST_VECTORS);
+		break;
+
+	case 29:
+		test_hash("tgr128", tgr128_tv_template, TGR128_TEST_VECTORS);
 		break;
 
 #ifdef CONFIG_CRYPTO_HMAC
diff -Nru a/crypto/tcrypt.h b/crypto/tcrypt.h
--- a/crypto/tcrypt.h	2005-03-11 12:51:51 -08:00
+++ b/crypto/tcrypt.h	2005-03-11 12:51:51 -08:00
@@ -553,6 +553,137 @@
 	},
 };
 
+/*
+ * TIGER test vectors from Tiger website 
+ */
+#define TGR192_TEST_VECTORS	6
+
+static struct hash_testvec tgr192_tv_template[] = {
+	{
+		.plaintext = "",
+		.psize	= 0,
+		.digest = { 0x24, 0xf0, 0x13, 0x0c, 0x63, 0xac, 0x93, 0x32,
+			    0x16, 0x16, 0x6e, 0x76, 0xb1, 0xbb, 0x92, 0x5f,
+			    0xf3, 0x73, 0xde, 0x2d, 0x49, 0x58, 0x4e, 0x7a },
+	}, {
+		.plaintext = "abc",
+		.psize	= 3,
+		.digest = { 0xf2, 0x58, 0xc1, 0xe8, 0x84, 0x14, 0xab, 0x2a,
+			    0x52, 0x7a, 0xb5, 0x41, 0xff, 0xc5, 0xb8, 0xbf,
+			    0x93, 0x5f, 0x7b, 0x95, 0x1c, 0x13, 0x29, 0x51 },
+	}, {
+		.plaintext = "Tiger",
+		.psize	= 5,
+		.digest = { 0x9f, 0x00, 0xf5, 0x99, 0x07, 0x23, 0x00, 0xdd,
+			    0x27, 0x6a, 0xbb, 0x38, 0xc8, 0xeb, 0x6d, 0xec,
+			    0x37, 0x79, 0x0c, 0x11, 0x6f, 0x9d, 0x2b, 0xdf },
+	}, {
+		.plaintext = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-",
+		.psize	= 64,
+		.digest = { 0x87, 0xfb, 0x2a, 0x90, 0x83, 0x85, 0x1c, 0xf7,
+			    0x47, 0x0d, 0x2c, 0xf8, 0x10, 0xe6, 0xdf, 0x9e,
+			    0xb5, 0x86, 0x44, 0x50, 0x34, 0xa5, 0xa3, 0x86 },
+	}, {
+		.plaintext = "ABCDEFGHIJKLMNOPQRSTUVWXYZ=abcdefghijklmnopqrstuvwxyz+0123456789",
+		.psize	= 64,
+		.digest = { 0x46, 0x7d, 0xb8, 0x08, 0x63, 0xeb, 0xce, 0x48,
+			    0x8d, 0xf1, 0xcd, 0x12, 0x61, 0x65, 0x5d, 0xe9,
+			    0x57, 0x89, 0x65, 0x65, 0x97, 0x5f, 0x91, 0x97 },
+	}, {
+		.plaintext = "Tiger - A Fast New Hash Function, "
+			     "by Ross Anderson and Eli Biham, "
+			     "proceedings of Fast Software Encryption 3, "
+			     "Cambridge, 1996.",
+		.psize  = 125,
+		.digest = { 0x3d, 0x9a, 0xeb, 0x03, 0xd1, 0xbd, 0x1a, 0x63,
+			    0x57, 0xb2, 0x77, 0x4d, 0xfd, 0x6d, 0x5b, 0x24,
+			    0xdd, 0x68, 0x15, 0x1d, 0x50, 0x39, 0x74, 0xfc },
+	},
+};
+
+#define TGR160_TEST_VECTORS	6
+
+static struct hash_testvec tgr160_tv_template[] = {
+	{
+		.plaintext = "",
+		.psize	= 0,
+		.digest = { 0x24, 0xf0, 0x13, 0x0c, 0x63, 0xac, 0x93, 0x32,
+			    0x16, 0x16, 0x6e, 0x76, 0xb1, 0xbb, 0x92, 0x5f,
+			    0xf3, 0x73, 0xde, 0x2d },
+	}, {
+		.plaintext = "abc",
+		.psize	= 3,
+		.digest = { 0xf2, 0x58, 0xc1, 0xe8, 0x84, 0x14, 0xab, 0x2a,
+			    0x52, 0x7a, 0xb5, 0x41, 0xff, 0xc5, 0xb8, 0xbf,
+			    0x93, 0x5f, 0x7b, 0x95 },
+	}, {
+		.plaintext = "Tiger",
+		.psize	= 5,
+		.digest = { 0x9f, 0x00, 0xf5, 0x99, 0x07, 0x23, 0x00, 0xdd,
+			    0x27, 0x6a, 0xbb, 0x38, 0xc8, 0xeb, 0x6d, 0xec,
+			    0x37, 0x79, 0x0c, 0x11 },
+	}, {
+		.plaintext = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-",
+		.psize	= 64,
+		.digest = { 0x87, 0xfb, 0x2a, 0x90, 0x83, 0x85, 0x1c, 0xf7,
+			    0x47, 0x0d, 0x2c, 0xf8, 0x10, 0xe6, 0xdf, 0x9e,
+			    0xb5, 0x86, 0x44, 0x50 },
+	}, {
+		.plaintext = "ABCDEFGHIJKLMNOPQRSTUVWXYZ=abcdefghijklmnopqrstuvwxyz+0123456789",
+		.psize	= 64,
+		.digest = { 0x46, 0x7d, 0xb8, 0x08, 0x63, 0xeb, 0xce, 0x48,
+			    0x8d, 0xf1, 0xcd, 0x12, 0x61, 0x65, 0x5d, 0xe9,
+			    0x57, 0x89, 0x65, 0x65 },
+	}, {
+		.plaintext = "Tiger - A Fast New Hash Function, "
+			     "by Ross Anderson and Eli Biham, "
+			     "proceedings of Fast Software Encryption 3, "
+			     "Cambridge, 1996.",
+		.psize  = 125,
+		.digest = { 0x3d, 0x9a, 0xeb, 0x03, 0xd1, 0xbd, 0x1a, 0x63,
+			    0x57, 0xb2, 0x77, 0x4d, 0xfd, 0x6d, 0x5b, 0x24,
+			    0xdd, 0x68, 0x15, 0x1d },
+	},
+};
+
+#define TGR128_TEST_VECTORS	6
+
+static struct hash_testvec tgr128_tv_template[] = {
+	{
+		.plaintext = "",
+		.psize	= 0,
+		.digest = { 0x24, 0xf0, 0x13, 0x0c, 0x63, 0xac, 0x93, 0x32,
+			    0x16, 0x16, 0x6e, 0x76, 0xb1, 0xbb, 0x92, 0x5f },
+	}, {
+		.plaintext = "abc",
+		.psize	= 3,
+		.digest = { 0xf2, 0x58, 0xc1, 0xe8, 0x84, 0x14, 0xab, 0x2a,
+			    0x52, 0x7a, 0xb5, 0x41, 0xff, 0xc5, 0xb8, 0xbf },
+	}, {
+		.plaintext = "Tiger",
+		.psize	= 5,
+		.digest = { 0x9f, 0x00, 0xf5, 0x99, 0x07, 0x23, 0x00, 0xdd,
+			    0x27, 0x6a, 0xbb, 0x38, 0xc8, 0xeb, 0x6d, 0xec },
+	}, {
+		.plaintext = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-",
+		.psize	= 64,
+		.digest = { 0x87, 0xfb, 0x2a, 0x90, 0x83, 0x85, 0x1c, 0xf7,
+			    0x47, 0x0d, 0x2c, 0xf8, 0x10, 0xe6, 0xdf, 0x9e },
+	}, {
+		.plaintext = "ABCDEFGHIJKLMNOPQRSTUVWXYZ=abcdefghijklmnopqrstuvwxyz+0123456789",
+		.psize	= 64,
+		.digest = { 0x46, 0x7d, 0xb8, 0x08, 0x63, 0xeb, 0xce, 0x48,
+			    0x8d, 0xf1, 0xcd, 0x12, 0x61, 0x65, 0x5d, 0xe9 },
+	}, {
+		.plaintext = "Tiger - A Fast New Hash Function, "
+			     "by Ross Anderson and Eli Biham, "
+			     "proceedings of Fast Software Encryption 3, "
+			     "Cambridge, 1996.",
+		.psize  = 125,
+		.digest = { 0x3d, 0x9a, 0xeb, 0x03, 0xd1, 0xbd, 0x1a, 0x63,
+			    0x57, 0xb2, 0x77, 0x4d, 0xfd, 0x6d, 0x5b, 0x24 },
+	},
+};
 
 #ifdef CONFIG_CRYPTO_HMAC
 /*
diff -Nru a/crypto/tgr192.c b/crypto/tgr192.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/crypto/tgr192.c	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,735 @@
+/*
+ * Cryptographic API.
+ *
+ * Tiger hashing Algorithm
+ *
+ *      Copyright (C) 1998 Free Software Foundation, Inc.
+ *
+ * The Tiger algorithm was developed by Ross Anderson and Eli Biham.
+ * It was optimized for 64-bit processors while still delievering
+ * decent performance on 32 and 16-bit processors.
+ *
+ * This version is derived from the GnuPG implementation and the
+ * Tiger-Perl interface written by Rafael Sevilla
+ *
+ * Adapted for Linux Kernel Crypto  by Aaron Grothe 
+ * ajgrothe@yahoo.com, February 22, 2005
+ *
+ * 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 TGR192_DIGEST_SIZE 24
+#define TGR160_DIGEST_SIZE 20
+#define TGR128_DIGEST_SIZE 16
+
+#define TGR192_BLOCK_SIZE  64
+
+struct tgr192_ctx {
+	u64 a, b, c;
+	u8 hash[64];
+	int count;
+	u32 nblocks;
+};
+
+static const u64 sbox1[256] = {
+	0x02aab17cf7e90c5eULL, 0xac424b03e243a8ecULL, 0x72cd5be30dd5fcd3ULL,
+	0x6d019b93f6f97f3aULL, 0xcd9978ffd21f9193ULL, 0x7573a1c9708029e2ULL,
+	0xb164326b922a83c3ULL, 0x46883eee04915870ULL, 0xeaace3057103ece6ULL,
+	0xc54169b808a3535cULL, 0x4ce754918ddec47cULL, 0x0aa2f4dfdc0df40cULL,
+	0x10b76f18a74dbefaULL, 0xc6ccb6235ad1ab6aULL, 0x13726121572fe2ffULL,
+	0x1a488c6f199d921eULL, 0x4bc9f9f4da0007caULL, 0x26f5e6f6e85241c7ULL,
+	0x859079dbea5947b6ULL, 0x4f1885c5c99e8c92ULL, 0xd78e761ea96f864bULL,
+	0x8e36428c52b5c17dULL, 0x69cf6827373063c1ULL, 0xb607c93d9bb4c56eULL,
+	0x7d820e760e76b5eaULL, 0x645c9cc6f07fdc42ULL, 0xbf38a078243342e0ULL,
+	0x5f6b343c9d2e7d04ULL, 0xf2c28aeb600b0ec6ULL, 0x6c0ed85f7254bcacULL,
+	0x71592281a4db4fe5ULL, 0x1967fa69ce0fed9fULL, 0xfd5293f8b96545dbULL,
+	0xc879e9d7f2a7600bULL, 0x860248920193194eULL, 0xa4f9533b2d9cc0b3ULL,
+	0x9053836c15957613ULL, 0xdb6dcf8afc357bf1ULL, 0x18beea7a7a370f57ULL,
+	0x037117ca50b99066ULL, 0x6ab30a9774424a35ULL, 0xf4e92f02e325249bULL,
+	0x7739db07061ccae1ULL, 0xd8f3b49ceca42a05ULL, 0xbd56be3f51382f73ULL,
+	0x45faed5843b0bb28ULL, 0x1c813d5c11bf1f83ULL, 0x8af0e4b6d75fa169ULL,
+	0x33ee18a487ad9999ULL, 0x3c26e8eab1c94410ULL, 0xb510102bc0a822f9ULL,
+	0x141eef310ce6123bULL, 0xfc65b90059ddb154ULL, 0xe0158640c5e0e607ULL,
+	0x884e079826c3a3cfULL, 0x930d0d9523c535fdULL, 0x35638d754e9a2b00ULL,
+	0x4085fccf40469dd5ULL, 0xc4b17ad28be23a4cULL, 0xcab2f0fc6a3e6a2eULL,
+	0x2860971a6b943fcdULL, 0x3dde6ee212e30446ULL, 0x6222f32ae01765aeULL,
+	0x5d550bb5478308feULL, 0xa9efa98da0eda22aULL, 0xc351a71686c40da7ULL,
+	0x1105586d9c867c84ULL, 0xdcffee85fda22853ULL, 0xccfbd0262c5eef76ULL,
+	0xbaf294cb8990d201ULL, 0xe69464f52afad975ULL, 0x94b013afdf133e14ULL,
+	0x06a7d1a32823c958ULL, 0x6f95fe5130f61119ULL, 0xd92ab34e462c06c0ULL,
+	0xed7bde33887c71d2ULL, 0x79746d6e6518393eULL, 0x5ba419385d713329ULL,
+	0x7c1ba6b948a97564ULL, 0x31987c197bfdac67ULL, 0xde6c23c44b053d02ULL,
+	0x581c49fed002d64dULL, 0xdd474d6338261571ULL, 0xaa4546c3e473d062ULL,
+	0x928fce349455f860ULL, 0x48161bbacaab94d9ULL, 0x63912430770e6f68ULL,
+	0x6ec8a5e602c6641cULL, 0x87282515337ddd2bULL, 0x2cda6b42034b701bULL,
+	0xb03d37c181cb096dULL, 0xe108438266c71c6fULL, 0x2b3180c7eb51b255ULL,
+	0xdf92b82f96c08bbcULL, 0x5c68c8c0a632f3baULL, 0x5504cc861c3d0556ULL,
+	0xabbfa4e55fb26b8fULL, 0x41848b0ab3baceb4ULL, 0xb334a273aa445d32ULL,
+	0xbca696f0a85ad881ULL, 0x24f6ec65b528d56cULL, 0x0ce1512e90f4524aULL,
+	0x4e9dd79d5506d35aULL, 0x258905fac6ce9779ULL, 0x2019295b3e109b33ULL,
+	0xf8a9478b73a054ccULL, 0x2924f2f934417eb0ULL, 0x3993357d536d1bc4ULL,
+	0x38a81ac21db6ff8bULL, 0x47c4fbf17d6016bfULL, 0x1e0faadd7667e3f5ULL,
+	0x7abcff62938beb96ULL, 0xa78dad948fc179c9ULL, 0x8f1f98b72911e50dULL,
+	0x61e48eae27121a91ULL, 0x4d62f7ad31859808ULL, 0xeceba345ef5ceaebULL,
+	0xf5ceb25ebc9684ceULL, 0xf633e20cb7f76221ULL, 0xa32cdf06ab8293e4ULL,
+	0x985a202ca5ee2ca4ULL, 0xcf0b8447cc8a8fb1ULL, 0x9f765244979859a3ULL,
+	0xa8d516b1a1240017ULL, 0x0bd7ba3ebb5dc726ULL, 0xe54bca55b86adb39ULL,
+	0x1d7a3afd6c478063ULL, 0x519ec608e7669eddULL, 0x0e5715a2d149aa23ULL,
+	0x177d4571848ff194ULL, 0xeeb55f3241014c22ULL, 0x0f5e5ca13a6e2ec2ULL,
+	0x8029927b75f5c361ULL, 0xad139fabc3d6e436ULL, 0x0d5df1a94ccf402fULL,
+	0x3e8bd948bea5dfc8ULL, 0xa5a0d357bd3ff77eULL, 0xa2d12e251f74f645ULL,
+	0x66fd9e525e81a082ULL, 0x2e0c90ce7f687a49ULL, 0xc2e8bcbeba973bc5ULL,
+	0x000001bce509745fULL, 0x423777bbe6dab3d6ULL, 0xd1661c7eaef06eb5ULL,
+	0xa1781f354daacfd8ULL, 0x2d11284a2b16affcULL, 0xf1fc4f67fa891d1fULL,
+	0x73ecc25dcb920adaULL, 0xae610c22c2a12651ULL, 0x96e0a810d356b78aULL,
+	0x5a9a381f2fe7870fULL, 0xd5ad62ede94e5530ULL, 0xd225e5e8368d1427ULL,
+	0x65977b70c7af4631ULL, 0x99f889b2de39d74fULL, 0x233f30bf54e1d143ULL,
+	0x9a9675d3d9a63c97ULL, 0x5470554ff334f9a8ULL, 0x166acb744a4f5688ULL,
+	0x70c74caab2e4aeadULL, 0xf0d091646f294d12ULL, 0x57b82a89684031d1ULL,
+	0xefd95a5a61be0b6bULL, 0x2fbd12e969f2f29aULL, 0x9bd37013feff9fe8ULL,
+	0x3f9b0404d6085a06ULL, 0x4940c1f3166cfe15ULL, 0x09542c4dcdf3defbULL,
+	0xb4c5218385cd5ce3ULL, 0xc935b7dc4462a641ULL, 0x3417f8a68ed3b63fULL,
+	0xb80959295b215b40ULL, 0xf99cdaef3b8c8572ULL, 0x018c0614f8fcb95dULL,
+	0x1b14accd1a3acdf3ULL, 0x84d471f200bb732dULL, 0xc1a3110e95e8da16ULL,
+	0x430a7220bf1a82b8ULL, 0xb77e090d39df210eULL, 0x5ef4bd9f3cd05e9dULL,
+	0x9d4ff6da7e57a444ULL, 0xda1d60e183d4a5f8ULL, 0xb287c38417998e47ULL,
+	0xfe3edc121bb31886ULL, 0xc7fe3ccc980ccbefULL, 0xe46fb590189bfd03ULL,
+	0x3732fd469a4c57dcULL, 0x7ef700a07cf1ad65ULL, 0x59c64468a31d8859ULL,
+	0x762fb0b4d45b61f6ULL, 0x155baed099047718ULL, 0x68755e4c3d50baa6ULL,
+	0xe9214e7f22d8b4dfULL, 0x2addbf532eac95f4ULL, 0x32ae3909b4bd0109ULL,
+	0x834df537b08e3450ULL, 0xfa209da84220728dULL, 0x9e691d9b9efe23f7ULL,
+	0x0446d288c4ae8d7fULL, 0x7b4cc524e169785bULL, 0x21d87f0135ca1385ULL,
+	0xcebb400f137b8aa5ULL, 0x272e2b66580796beULL, 0x3612264125c2b0deULL,
+	0x057702bdad1efbb2ULL, 0xd4babb8eacf84be9ULL, 0x91583139641bc67bULL,
+	0x8bdc2de08036e024ULL, 0x603c8156f49f68edULL, 0xf7d236f7dbef5111ULL,
+	0x9727c4598ad21e80ULL, 0xa08a0896670a5fd7ULL, 0xcb4a8f4309eba9cbULL,
+	0x81af564b0f7036a1ULL, 0xc0b99aa778199abdULL, 0x959f1ec83fc8e952ULL,
+	0x8c505077794a81b9ULL, 0x3acaaf8f056338f0ULL, 0x07b43f50627a6778ULL,
+	0x4a44ab49f5eccc77ULL, 0x3bc3d6e4b679ee98ULL, 0x9cc0d4d1cf14108cULL,
+	0x4406c00b206bc8a0ULL, 0x82a18854c8d72d89ULL, 0x67e366b35c3c432cULL,
+	0xb923dd61102b37f2ULL, 0x56ab2779d884271dULL, 0xbe83e1b0ff1525afULL,
+	0xfb7c65d4217e49a9ULL, 0x6bdbe0e76d48e7d4ULL, 0x08df828745d9179eULL,
+	0x22ea6a9add53bd34ULL, 0xe36e141c5622200aULL, 0x7f805d1b8cb750eeULL,
+	0xafe5c7a59f58e837ULL, 0xe27f996a4fb1c23cULL, 0xd3867dfb0775f0d0ULL,
+	0xd0e673de6e88891aULL, 0x123aeb9eafb86c25ULL, 0x30f1d5d5c145b895ULL,
+	0xbb434a2dee7269e7ULL, 0x78cb67ecf931fa38ULL, 0xf33b0372323bbf9cULL,
+	0x52d66336fb279c74ULL, 0x505f33ac0afb4eaaULL, 0xe8a5cd99a2cce187ULL,
+	0x534974801e2d30bbULL, 0x8d2d5711d5876d90ULL, 0x1f1a412891bc038eULL,
+	0xd6e2e71d82e56648ULL, 0x74036c3a497732b7ULL, 0x89b67ed96361f5abULL,
+	0xffed95d8f1ea02a2ULL, 0xe72b3bd61464d43dULL, 0xa6300f170bdc4820ULL,
+	0xebc18760ed78a77aULL
+};
+
+static const u64 sbox2[256] = {
+	0xe6a6be5a05a12138ULL, 0xb5a122a5b4f87c98ULL, 0x563c6089140b6990ULL,
+	0x4c46cb2e391f5dd5ULL, 0xd932addbc9b79434ULL, 0x08ea70e42015aff5ULL,
+	0xd765a6673e478cf1ULL, 0xc4fb757eab278d99ULL, 0xdf11c6862d6e0692ULL,
+	0xddeb84f10d7f3b16ULL, 0x6f2ef604a665ea04ULL, 0x4a8e0f0ff0e0dfb3ULL,
+	0xa5edeef83dbcba51ULL, 0xfc4f0a2a0ea4371eULL, 0xe83e1da85cb38429ULL,
+	0xdc8ff882ba1b1ce2ULL, 0xcd45505e8353e80dULL, 0x18d19a00d4db0717ULL,
+	0x34a0cfeda5f38101ULL, 0x0be77e518887caf2ULL, 0x1e341438b3c45136ULL,
+	0xe05797f49089ccf9ULL, 0xffd23f9df2591d14ULL, 0x543dda228595c5cdULL,
+	0x661f81fd99052a33ULL, 0x8736e641db0f7b76ULL, 0x15227725418e5307ULL,
+	0xe25f7f46162eb2faULL, 0x48a8b2126c13d9feULL, 0xafdc541792e76eeaULL,
+	0x03d912bfc6d1898fULL, 0x31b1aafa1b83f51bULL, 0xf1ac2796e42ab7d9ULL,
+	0x40a3a7d7fcd2ebacULL, 0x1056136d0afbbcc5ULL, 0x7889e1dd9a6d0c85ULL,
+	0xd33525782a7974aaULL, 0xa7e25d09078ac09bULL, 0xbd4138b3eac6edd0ULL,
+	0x920abfbe71eb9e70ULL, 0xa2a5d0f54fc2625cULL, 0xc054e36b0b1290a3ULL,
+	0xf6dd59ff62fe932bULL, 0x3537354511a8ac7dULL, 0xca845e9172fadcd4ULL,
+	0x84f82b60329d20dcULL, 0x79c62ce1cd672f18ULL, 0x8b09a2add124642cULL,
+	0xd0c1e96a19d9e726ULL, 0x5a786a9b4ba9500cULL, 0x0e020336634c43f3ULL,
+	0xc17b474aeb66d822ULL, 0x6a731ae3ec9baac2ULL, 0x8226667ae0840258ULL,
+	0x67d4567691caeca5ULL, 0x1d94155c4875adb5ULL, 0x6d00fd985b813fdfULL,
+	0x51286efcb774cd06ULL, 0x5e8834471fa744afULL, 0xf72ca0aee761ae2eULL,
+	0xbe40e4cdaee8e09aULL, 0xe9970bbb5118f665ULL, 0x726e4beb33df1964ULL,
+	0x703b000729199762ULL, 0x4631d816f5ef30a7ULL, 0xb880b5b51504a6beULL,
+	0x641793c37ed84b6cULL, 0x7b21ed77f6e97d96ULL, 0x776306312ef96b73ULL,
+	0xae528948e86ff3f4ULL, 0x53dbd7f286a3f8f8ULL, 0x16cadce74cfc1063ULL,
+	0x005c19bdfa52c6ddULL, 0x68868f5d64d46ad3ULL, 0x3a9d512ccf1e186aULL,
+	0x367e62c2385660aeULL, 0xe359e7ea77dcb1d7ULL, 0x526c0773749abe6eULL,
+	0x735ae5f9d09f734bULL, 0x493fc7cc8a558ba8ULL, 0xb0b9c1533041ab45ULL,
+	0x321958ba470a59bdULL, 0x852db00b5f46c393ULL, 0x91209b2bd336b0e5ULL,
+	0x6e604f7d659ef19fULL, 0xb99a8ae2782ccb24ULL, 0xccf52ab6c814c4c7ULL,
+	0x4727d9afbe11727bULL, 0x7e950d0c0121b34dULL, 0x756f435670ad471fULL,
+	0xf5add442615a6849ULL, 0x4e87e09980b9957aULL, 0x2acfa1df50aee355ULL,
+	0xd898263afd2fd556ULL, 0xc8f4924dd80c8fd6ULL, 0xcf99ca3d754a173aULL,
+	0xfe477bacaf91bf3cULL, 0xed5371f6d690c12dULL, 0x831a5c285e687094ULL,
+	0xc5d3c90a3708a0a4ULL, 0x0f7f903717d06580ULL, 0x19f9bb13b8fdf27fULL,
+	0xb1bd6f1b4d502843ULL, 0x1c761ba38fff4012ULL, 0x0d1530c4e2e21f3bULL,
+	0x8943ce69a7372c8aULL, 0xe5184e11feb5ce66ULL, 0x618bdb80bd736621ULL,
+	0x7d29bad68b574d0bULL, 0x81bb613e25e6fe5bULL, 0x071c9c10bc07913fULL,
+	0xc7beeb7909ac2d97ULL, 0xc3e58d353bc5d757ULL, 0xeb017892f38f61e8ULL,
+	0xd4effb9c9b1cc21aULL, 0x99727d26f494f7abULL, 0xa3e063a2956b3e03ULL,
+	0x9d4a8b9a4aa09c30ULL, 0x3f6ab7d500090fb4ULL, 0x9cc0f2a057268ac0ULL,
+	0x3dee9d2dedbf42d1ULL, 0x330f49c87960a972ULL, 0xc6b2720287421b41ULL,
+	0x0ac59ec07c00369cULL, 0xef4eac49cb353425ULL, 0xf450244eef0129d8ULL,
+	0x8acc46e5caf4deb6ULL, 0x2ffeab63989263f7ULL, 0x8f7cb9fe5d7a4578ULL,
+	0x5bd8f7644e634635ULL, 0x427a7315bf2dc900ULL, 0x17d0c4aa2125261cULL,
+	0x3992486c93518e50ULL, 0xb4cbfee0a2d7d4c3ULL, 0x7c75d6202c5ddd8dULL,
+	0xdbc295d8e35b6c61ULL, 0x60b369d302032b19ULL, 0xce42685fdce44132ULL,
+	0x06f3ddb9ddf65610ULL, 0x8ea4d21db5e148f0ULL, 0x20b0fce62fcd496fULL,
+	0x2c1b912358b0ee31ULL, 0xb28317b818f5a308ULL, 0xa89c1e189ca6d2cfULL,
+	0x0c6b18576aaadbc8ULL, 0xb65deaa91299fae3ULL, 0xfb2b794b7f1027e7ULL,
+	0x04e4317f443b5bebULL, 0x4b852d325939d0a6ULL, 0xd5ae6beefb207ffcULL,
+	0x309682b281c7d374ULL, 0xbae309a194c3b475ULL, 0x8cc3f97b13b49f05ULL,
+	0x98a9422ff8293967ULL, 0x244b16b01076ff7cULL, 0xf8bf571c663d67eeULL,
+	0x1f0d6758eee30da1ULL, 0xc9b611d97adeb9b7ULL, 0xb7afd5887b6c57a2ULL,
+	0x6290ae846b984fe1ULL, 0x94df4cdeacc1a5fdULL, 0x058a5bd1c5483affULL,
+	0x63166cc142ba3c37ULL, 0x8db8526eb2f76f40ULL, 0xe10880036f0d6d4eULL,
+	0x9e0523c9971d311dULL, 0x45ec2824cc7cd691ULL, 0x575b8359e62382c9ULL,
+	0xfa9e400dc4889995ULL, 0xd1823ecb45721568ULL, 0xdafd983b8206082fULL,
+	0xaa7d29082386a8cbULL, 0x269fcd4403b87588ULL, 0x1b91f5f728bdd1e0ULL,
+	0xe4669f39040201f6ULL, 0x7a1d7c218cf04adeULL, 0x65623c29d79ce5ceULL,
+	0x2368449096c00bb1ULL, 0xab9bf1879da503baULL, 0xbc23ecb1a458058eULL,
+	0x9a58df01bb401eccULL, 0xa070e868a85f143dULL, 0x4ff188307df2239eULL,
+	0x14d565b41a641183ULL, 0xee13337452701602ULL, 0x950e3dcf3f285e09ULL,
+	0x59930254b9c80953ULL, 0x3bf299408930da6dULL, 0xa955943f53691387ULL,
+	0xa15edecaa9cb8784ULL, 0x29142127352be9a0ULL, 0x76f0371fff4e7afbULL,
+	0x0239f450274f2228ULL, 0xbb073af01d5e868bULL, 0xbfc80571c10e96c1ULL,
+	0xd267088568222e23ULL, 0x9671a3d48e80b5b0ULL, 0x55b5d38ae193bb81ULL,
+	0x693ae2d0a18b04b8ULL, 0x5c48b4ecadd5335fULL, 0xfd743b194916a1caULL,
+	0x2577018134be98c4ULL, 0xe77987e83c54a4adULL, 0x28e11014da33e1b9ULL,
+	0x270cc59e226aa213ULL, 0x71495f756d1a5f60ULL, 0x9be853fb60afef77ULL,
+	0xadc786a7f7443dbfULL, 0x0904456173b29a82ULL, 0x58bc7a66c232bd5eULL,
+	0xf306558c673ac8b2ULL, 0x41f639c6b6c9772aULL, 0x216defe99fda35daULL,
+	0x11640cc71c7be615ULL, 0x93c43694565c5527ULL, 0xea038e6246777839ULL,
+	0xf9abf3ce5a3e2469ULL, 0x741e768d0fd312d2ULL, 0x0144b883ced652c6ULL,
+	0xc20b5a5ba33f8552ULL, 0x1ae69633c3435a9dULL, 0x97a28ca4088cfdecULL,
+	0x8824a43c1e96f420ULL, 0x37612fa66eeea746ULL, 0x6b4cb165f9cf0e5aULL,
+	0x43aa1c06a0abfb4aULL, 0x7f4dc26ff162796bULL, 0x6cbacc8e54ed9b0fULL,
+	0xa6b7ffefd2bb253eULL, 0x2e25bc95b0a29d4fULL, 0x86d6a58bdef1388cULL,
+	0xded74ac576b6f054ULL, 0x8030bdbc2b45805dULL, 0x3c81af70e94d9289ULL,
+	0x3eff6dda9e3100dbULL, 0xb38dc39fdfcc8847ULL, 0x123885528d17b87eULL,
+	0xf2da0ed240b1b642ULL, 0x44cefadcd54bf9a9ULL, 0x1312200e433c7ee6ULL,
+	0x9ffcc84f3a78c748ULL, 0xf0cd1f72248576bbULL, 0xec6974053638cfe4ULL,
+	0x2ba7b67c0cec4e4cULL, 0xac2f4df3e5ce32edULL, 0xcb33d14326ea4c11ULL,
+	0xa4e9044cc77e58bcULL, 0x5f513293d934fcefULL, 0x5dc9645506e55444ULL,
+	0x50de418f317de40aULL, 0x388cb31a69dde259ULL, 0x2db4a83455820a86ULL,
+	0x9010a91e84711ae9ULL, 0x4df7f0b7b1498371ULL, 0xd62a2eabc0977179ULL,
+	0x22fac097aa8d5c0eULL
+};
+
+static const u64 sbox3[256] = {
+	0xf49fcc2ff1daf39bULL, 0x487fd5c66ff29281ULL, 0xe8a30667fcdca83fULL,
+	0x2c9b4be3d2fcce63ULL, 0xda3ff74b93fbbbc2ULL, 0x2fa165d2fe70ba66ULL,
+	0xa103e279970e93d4ULL, 0xbecdec77b0e45e71ULL, 0xcfb41e723985e497ULL,
+	0xb70aaa025ef75017ULL, 0xd42309f03840b8e0ULL, 0x8efc1ad035898579ULL,
+	0x96c6920be2b2abc5ULL, 0x66af4163375a9172ULL, 0x2174abdcca7127fbULL,
+	0xb33ccea64a72ff41ULL, 0xf04a4933083066a5ULL, 0x8d970acdd7289af5ULL,
+	0x8f96e8e031c8c25eULL, 0xf3fec02276875d47ULL, 0xec7bf310056190ddULL,
+	0xf5adb0aebb0f1491ULL, 0x9b50f8850fd58892ULL, 0x4975488358b74de8ULL,
+	0xa3354ff691531c61ULL, 0x0702bbe481d2c6eeULL, 0x89fb24057deded98ULL,
+	0xac3075138596e902ULL, 0x1d2d3580172772edULL, 0xeb738fc28e6bc30dULL,
+	0x5854ef8f63044326ULL, 0x9e5c52325add3bbeULL, 0x90aa53cf325c4623ULL,
+	0xc1d24d51349dd067ULL, 0x2051cfeea69ea624ULL, 0x13220f0a862e7e4fULL,
+	0xce39399404e04864ULL, 0xd9c42ca47086fcb7ULL, 0x685ad2238a03e7ccULL,
+	0x066484b2ab2ff1dbULL, 0xfe9d5d70efbf79ecULL, 0x5b13b9dd9c481854ULL,
+	0x15f0d475ed1509adULL, 0x0bebcd060ec79851ULL, 0xd58c6791183ab7f8ULL,
+	0xd1187c5052f3eee4ULL, 0xc95d1192e54e82ffULL, 0x86eea14cb9ac6ca2ULL,
+	0x3485beb153677d5dULL, 0xdd191d781f8c492aULL, 0xf60866baa784ebf9ULL,
+	0x518f643ba2d08c74ULL, 0x8852e956e1087c22ULL, 0xa768cb8dc410ae8dULL,
+	0x38047726bfec8e1aULL, 0xa67738b4cd3b45aaULL, 0xad16691cec0dde19ULL,
+	0xc6d4319380462e07ULL, 0xc5a5876d0ba61938ULL, 0x16b9fa1fa58fd840ULL,
+	0x188ab1173ca74f18ULL, 0xabda2f98c99c021fULL, 0x3e0580ab134ae816ULL,
+	0x5f3b05b773645abbULL, 0x2501a2be5575f2f6ULL, 0x1b2f74004e7e8ba9ULL,
+	0x1cd7580371e8d953ULL, 0x7f6ed89562764e30ULL, 0xb15926ff596f003dULL,
+	0x9f65293da8c5d6b9ULL, 0x6ecef04dd690f84cULL, 0x4782275fff33af88ULL,
+	0xe41433083f820801ULL, 0xfd0dfe409a1af9b5ULL, 0x4325a3342cdb396bULL,
+	0x8ae77e62b301b252ULL, 0xc36f9e9f6655615aULL, 0x85455a2d92d32c09ULL,
+	0xf2c7dea949477485ULL, 0x63cfb4c133a39ebaULL, 0x83b040cc6ebc5462ULL,
+	0x3b9454c8fdb326b0ULL, 0x56f56a9e87ffd78cULL, 0x2dc2940d99f42bc6ULL,
+	0x98f7df096b096e2dULL, 0x19a6e01e3ad852bfULL, 0x42a99ccbdbd4b40bULL,
+	0xa59998af45e9c559ULL, 0x366295e807d93186ULL, 0x6b48181bfaa1f773ULL,
+	0x1fec57e2157a0a1dULL, 0x4667446af6201ad5ULL, 0xe615ebcacfb0f075ULL,
+	0xb8f31f4f68290778ULL, 0x22713ed6ce22d11eULL, 0x3057c1a72ec3c93bULL,
+	0xcb46acc37c3f1f2fULL, 0xdbb893fd02aaf50eULL, 0x331fd92e600b9fcfULL,
+	0xa498f96148ea3ad6ULL, 0xa8d8426e8b6a83eaULL, 0xa089b274b7735cdcULL,
+	0x87f6b3731e524a11ULL, 0x118808e5cbc96749ULL, 0x9906e4c7b19bd394ULL,
+	0xafed7f7e9b24a20cULL, 0x6509eadeeb3644a7ULL, 0x6c1ef1d3e8ef0edeULL,
+	0xb9c97d43e9798fb4ULL, 0xa2f2d784740c28a3ULL, 0x7b8496476197566fULL,
+	0x7a5be3e6b65f069dULL, 0xf96330ed78be6f10ULL, 0xeee60de77a076a15ULL,
+	0x2b4bee4aa08b9bd0ULL, 0x6a56a63ec7b8894eULL, 0x02121359ba34fef4ULL,
+	0x4cbf99f8283703fcULL, 0x398071350caf30c8ULL, 0xd0a77a89f017687aULL,
+	0xf1c1a9eb9e423569ULL, 0x8c7976282dee8199ULL, 0x5d1737a5dd1f7abdULL,
+	0x4f53433c09a9fa80ULL, 0xfa8b0c53df7ca1d9ULL, 0x3fd9dcbc886ccb77ULL,
+	0xc040917ca91b4720ULL, 0x7dd00142f9d1dcdfULL, 0x8476fc1d4f387b58ULL,
+	0x23f8e7c5f3316503ULL, 0x032a2244e7e37339ULL, 0x5c87a5d750f5a74bULL,
+	0x082b4cc43698992eULL, 0xdf917becb858f63cULL, 0x3270b8fc5bf86ddaULL,
+	0x10ae72bb29b5dd76ULL, 0x576ac94e7700362bULL, 0x1ad112dac61efb8fULL,
+	0x691bc30ec5faa427ULL, 0xff246311cc327143ULL, 0x3142368e30e53206ULL,
+	0x71380e31e02ca396ULL, 0x958d5c960aad76f1ULL, 0xf8d6f430c16da536ULL,
+	0xc8ffd13f1be7e1d2ULL, 0x7578ae66004ddbe1ULL, 0x05833f01067be646ULL,
+	0xbb34b5ad3bfe586dULL, 0x095f34c9a12b97f0ULL, 0x247ab64525d60ca8ULL,
+	0xdcdbc6f3017477d1ULL, 0x4a2e14d4decad24dULL, 0xbdb5e6d9be0a1eebULL,
+	0x2a7e70f7794301abULL, 0xdef42d8a270540fdULL, 0x01078ec0a34c22c1ULL,
+	0xe5de511af4c16387ULL, 0x7ebb3a52bd9a330aULL, 0x77697857aa7d6435ULL,
+	0x004e831603ae4c32ULL, 0xe7a21020ad78e312ULL, 0x9d41a70c6ab420f2ULL,
+	0x28e06c18ea1141e6ULL, 0xd2b28cbd984f6b28ULL, 0x26b75f6c446e9d83ULL,
+	0xba47568c4d418d7fULL, 0xd80badbfe6183d8eULL, 0x0e206d7f5f166044ULL,
+	0xe258a43911cbca3eULL, 0x723a1746b21dc0bcULL, 0xc7caa854f5d7cdd3ULL,
+	0x7cac32883d261d9cULL, 0x7690c26423ba942cULL, 0x17e55524478042b8ULL,
+	0xe0be477656a2389fULL, 0x4d289b5e67ab2da0ULL, 0x44862b9c8fbbfd31ULL,
+	0xb47cc8049d141365ULL, 0x822c1b362b91c793ULL, 0x4eb14655fb13dfd8ULL,
+	0x1ecbba0714e2a97bULL, 0x6143459d5cde5f14ULL, 0x53a8fbf1d5f0ac89ULL,
+	0x97ea04d81c5e5b00ULL, 0x622181a8d4fdb3f3ULL, 0xe9bcd341572a1208ULL,
+	0x1411258643cce58aULL, 0x9144c5fea4c6e0a4ULL, 0x0d33d06565cf620fULL,
+	0x54a48d489f219ca1ULL, 0xc43e5eac6d63c821ULL, 0xa9728b3a72770dafULL,
+	0xd7934e7b20df87efULL, 0xe35503b61a3e86e5ULL, 0xcae321fbc819d504ULL,
+	0x129a50b3ac60bfa6ULL, 0xcd5e68ea7e9fb6c3ULL, 0xb01c90199483b1c7ULL,
+	0x3de93cd5c295376cULL, 0xaed52edf2ab9ad13ULL, 0x2e60f512c0a07884ULL,
+	0xbc3d86a3e36210c9ULL, 0x35269d9b163951ceULL, 0x0c7d6e2ad0cdb5faULL,
+	0x59e86297d87f5733ULL, 0x298ef221898db0e7ULL, 0x55000029d1a5aa7eULL,
+	0x8bc08ae1b5061b45ULL, 0xc2c31c2b6c92703aULL, 0x94cc596baf25ef42ULL,
+	0x0a1d73db22540456ULL, 0x04b6a0f9d9c4179aULL, 0xeffdafa2ae3d3c60ULL,
+	0xf7c8075bb49496c4ULL, 0x9cc5c7141d1cd4e3ULL, 0x78bd1638218e5534ULL,
+	0xb2f11568f850246aULL, 0xedfabcfa9502bc29ULL, 0x796ce5f2da23051bULL,
+	0xaae128b0dc93537cULL, 0x3a493da0ee4b29aeULL, 0xb5df6b2c416895d7ULL,
+	0xfcabbd25122d7f37ULL, 0x70810b58105dc4b1ULL, 0xe10fdd37f7882a90ULL,
+	0x524dcab5518a3f5cULL, 0x3c9e85878451255bULL, 0x4029828119bd34e2ULL,
+	0x74a05b6f5d3ceccbULL, 0xb610021542e13ecaULL, 0x0ff979d12f59e2acULL,
+	0x6037da27e4f9cc50ULL, 0x5e92975a0df1847dULL, 0xd66de190d3e623feULL,
+	0x5032d6b87b568048ULL, 0x9a36b7ce8235216eULL, 0x80272a7a24f64b4aULL,
+	0x93efed8b8c6916f7ULL, 0x37ddbff44cce1555ULL, 0x4b95db5d4b99bd25ULL,
+	0x92d3fda169812fc0ULL, 0xfb1a4a9a90660bb6ULL, 0x730c196946a4b9b2ULL,
+	0x81e289aa7f49da68ULL, 0x64669a0f83b1a05fULL, 0x27b3ff7d9644f48bULL,
+	0xcc6b615c8db675b3ULL, 0x674f20b9bcebbe95ULL, 0x6f31238275655982ULL,
+	0x5ae488713e45cf05ULL, 0xbf619f9954c21157ULL, 0xeabac46040a8eae9ULL,
+	0x454c6fe9f2c0c1cdULL, 0x419cf6496412691cULL, 0xd3dc3bef265b0f70ULL,
+	0x6d0e60f5c3578a9eULL
+};
+
+static const u64 sbox4[256] = {
+	0x5b0e608526323c55ULL, 0x1a46c1a9fa1b59f5ULL, 0xa9e245a17c4c8ffaULL,
+	0x65ca5159db2955d7ULL, 0x05db0a76ce35afc2ULL, 0x81eac77ea9113d45ULL,
+	0x528ef88ab6ac0a0dULL, 0xa09ea253597be3ffULL, 0x430ddfb3ac48cd56ULL,
+	0xc4b3a67af45ce46fULL, 0x4ececfd8fbe2d05eULL, 0x3ef56f10b39935f0ULL,
+	0x0b22d6829cd619c6ULL, 0x17fd460a74df2069ULL, 0x6cf8cc8e8510ed40ULL,
+	0xd6c824bf3a6ecaa7ULL, 0x61243d581a817049ULL, 0x048bacb6bbc163a2ULL,
+	0xd9a38ac27d44cc32ULL, 0x7fddff5baaf410abULL, 0xad6d495aa804824bULL,
+	0xe1a6a74f2d8c9f94ULL, 0xd4f7851235dee8e3ULL, 0xfd4b7f886540d893ULL,
+	0x247c20042aa4bfdaULL, 0x096ea1c517d1327cULL, 0xd56966b4361a6685ULL,
+	0x277da5c31221057dULL, 0x94d59893a43acff7ULL, 0x64f0c51ccdc02281ULL,
+	0x3d33bcc4ff6189dbULL, 0xe005cb184ce66af1ULL, 0xff5ccd1d1db99beaULL,
+	0xb0b854a7fe42980fULL, 0x7bd46a6a718d4b9fULL, 0xd10fa8cc22a5fd8cULL,
+	0xd31484952be4bd31ULL, 0xc7fa975fcb243847ULL, 0x4886ed1e5846c407ULL,
+	0x28cddb791eb70b04ULL, 0xc2b00be2f573417fULL, 0x5c9590452180f877ULL,
+	0x7a6bddfff370eb00ULL, 0xce509e38d6d9d6a4ULL, 0xebeb0f00647fa702ULL,
+	0x1dcc06cf76606f06ULL, 0xe4d9f28ba286ff0aULL, 0xd85a305dc918c262ULL,
+	0x475b1d8732225f54ULL, 0x2d4fb51668ccb5feULL, 0xa679b9d9d72bba20ULL,
+	0x53841c0d912d43a5ULL, 0x3b7eaa48bf12a4e8ULL, 0x781e0e47f22f1ddfULL,
+	0xeff20ce60ab50973ULL, 0x20d261d19dffb742ULL, 0x16a12b03062a2e39ULL,
+	0x1960eb2239650495ULL, 0x251c16fed50eb8b8ULL, 0x9ac0c330f826016eULL,
+	0xed152665953e7671ULL, 0x02d63194a6369570ULL, 0x5074f08394b1c987ULL,
+	0x70ba598c90b25ce1ULL, 0x794a15810b9742f6ULL, 0x0d5925e9fcaf8c6cULL,
+	0x3067716cd868744eULL, 0x910ab077e8d7731bULL, 0x6a61bbdb5ac42f61ULL,
+	0x93513efbf0851567ULL, 0xf494724b9e83e9d5ULL, 0xe887e1985c09648dULL,
+	0x34b1d3c675370cfdULL, 0xdc35e433bc0d255dULL, 0xd0aab84234131be0ULL,
+	0x08042a50b48b7eafULL, 0x9997c4ee44a3ab35ULL, 0x829a7b49201799d0ULL,
+	0x263b8307b7c54441ULL, 0x752f95f4fd6a6ca6ULL, 0x927217402c08c6e5ULL,
+	0x2a8ab754a795d9eeULL, 0xa442f7552f72943dULL, 0x2c31334e19781208ULL,
+	0x4fa98d7ceaee6291ULL, 0x55c3862f665db309ULL, 0xbd0610175d53b1f3ULL,
+	0x46fe6cb840413f27ULL, 0x3fe03792df0cfa59ULL, 0xcfe700372eb85e8fULL,
+	0xa7be29e7adbce118ULL, 0xe544ee5cde8431ddULL, 0x8a781b1b41f1873eULL,
+	0xa5c94c78a0d2f0e7ULL, 0x39412e2877b60728ULL, 0xa1265ef3afc9a62cULL,
+	0xbcc2770c6a2506c5ULL, 0x3ab66dd5dce1ce12ULL, 0xe65499d04a675b37ULL,
+	0x7d8f523481bfd216ULL, 0x0f6f64fcec15f389ULL, 0x74efbe618b5b13c8ULL,
+	0xacdc82b714273e1dULL, 0xdd40bfe003199d17ULL, 0x37e99257e7e061f8ULL,
+	0xfa52626904775aaaULL, 0x8bbbf63a463d56f9ULL, 0xf0013f1543a26e64ULL,
+	0xa8307e9f879ec898ULL, 0xcc4c27a4150177ccULL, 0x1b432f2cca1d3348ULL,
+	0xde1d1f8f9f6fa013ULL, 0x606602a047a7ddd6ULL, 0xd237ab64cc1cb2c7ULL,
+	0x9b938e7225fcd1d3ULL, 0xec4e03708e0ff476ULL, 0xfeb2fbda3d03c12dULL,
+	0xae0bced2ee43889aULL, 0x22cb8923ebfb4f43ULL, 0x69360d013cf7396dULL,
+	0x855e3602d2d4e022ULL, 0x073805bad01f784cULL, 0x33e17a133852f546ULL,
+	0xdf4874058ac7b638ULL, 0xba92b29c678aa14aULL, 0x0ce89fc76cfaadcdULL,
+	0x5f9d4e0908339e34ULL, 0xf1afe9291f5923b9ULL, 0x6e3480f60f4a265fULL,
+	0xeebf3a2ab29b841cULL, 0xe21938a88f91b4adULL, 0x57dfeff845c6d3c3ULL,
+	0x2f006b0bf62caaf2ULL, 0x62f479ef6f75ee78ULL, 0x11a55ad41c8916a9ULL,
+	0xf229d29084fed453ULL, 0x42f1c27b16b000e6ULL, 0x2b1f76749823c074ULL,
+	0x4b76eca3c2745360ULL, 0x8c98f463b91691bdULL, 0x14bcc93cf1ade66aULL,
+	0x8885213e6d458397ULL, 0x8e177df0274d4711ULL, 0xb49b73b5503f2951ULL,
+	0x10168168c3f96b6bULL, 0x0e3d963b63cab0aeULL, 0x8dfc4b5655a1db14ULL,
+	0xf789f1356e14de5cULL, 0x683e68af4e51dac1ULL, 0xc9a84f9d8d4b0fd9ULL,
+	0x3691e03f52a0f9d1ULL, 0x5ed86e46e1878e80ULL, 0x3c711a0e99d07150ULL,
+	0x5a0865b20c4e9310ULL, 0x56fbfc1fe4f0682eULL, 0xea8d5de3105edf9bULL,
+	0x71abfdb12379187aULL, 0x2eb99de1bee77b9cULL, 0x21ecc0ea33cf4523ULL,
+	0x59a4d7521805c7a1ULL, 0x3896f5eb56ae7c72ULL, 0xaa638f3db18f75dcULL,
+	0x9f39358dabe9808eULL, 0xb7defa91c00b72acULL, 0x6b5541fd62492d92ULL,
+	0x6dc6dee8f92e4d5bULL, 0x353f57abc4beea7eULL, 0x735769d6da5690ceULL,
+	0x0a234aa642391484ULL, 0xf6f9508028f80d9dULL, 0xb8e319a27ab3f215ULL,
+	0x31ad9c1151341a4dULL, 0x773c22a57bef5805ULL, 0x45c7561a07968633ULL,
+	0xf913da9e249dbe36ULL, 0xda652d9b78a64c68ULL, 0x4c27a97f3bc334efULL,
+	0x76621220e66b17f4ULL, 0x967743899acd7d0bULL, 0xf3ee5bcae0ed6782ULL,
+	0x409f753600c879fcULL, 0x06d09a39b5926db6ULL, 0x6f83aeb0317ac588ULL,
+	0x01e6ca4a86381f21ULL, 0x66ff3462d19f3025ULL, 0x72207c24ddfd3bfbULL,
+	0x4af6b6d3e2ece2ebULL, 0x9c994dbec7ea08deULL, 0x49ace597b09a8bc4ULL,
+	0xb38c4766cf0797baULL, 0x131b9373c57c2a75ULL, 0xb1822cce61931e58ULL,
+	0x9d7555b909ba1c0cULL, 0x127fafdd937d11d2ULL, 0x29da3badc66d92e4ULL,
+	0xa2c1d57154c2ecbcULL, 0x58c5134d82f6fe24ULL, 0x1c3ae3515b62274fULL,
+	0xe907c82e01cb8126ULL, 0xf8ed091913e37fcbULL, 0x3249d8f9c80046c9ULL,
+	0x80cf9bede388fb63ULL, 0x1881539a116cf19eULL, 0x5103f3f76bd52457ULL,
+	0x15b7e6f5ae47f7a8ULL, 0xdbd7c6ded47e9ccfULL, 0x44e55c410228bb1aULL,
+	0xb647d4255edb4e99ULL, 0x5d11882bb8aafc30ULL, 0xf5098bbb29d3212aULL,
+	0x8fb5ea14e90296b3ULL, 0x677b942157dd025aULL, 0xfb58e7c0a390acb5ULL,
+	0x89d3674c83bd4a01ULL, 0x9e2da4df4bf3b93bULL, 0xfcc41e328cab4829ULL,
+	0x03f38c96ba582c52ULL, 0xcad1bdbd7fd85db2ULL, 0xbbb442c16082ae83ULL,
+	0xb95fe86ba5da9ab0ULL, 0xb22e04673771a93fULL, 0x845358c9493152d8ULL,
+	0xbe2a488697b4541eULL, 0x95a2dc2dd38e6966ULL, 0xc02c11ac923c852bULL,
+	0x2388b1990df2a87bULL, 0x7c8008fa1b4f37beULL, 0x1f70d0c84d54e503ULL,
+	0x5490adec7ece57d4ULL, 0x002b3c27d9063a3aULL, 0x7eaea3848030a2bfULL,
+	0xc602326ded2003c0ULL, 0x83a7287d69a94086ULL, 0xc57a5fcb30f57a8aULL,
+	0xb56844e479ebe779ULL, 0xa373b40f05dcbce9ULL, 0xd71a786e88570ee2ULL,
+	0x879cbacdbde8f6a0ULL, 0x976ad1bcc164a32fULL, 0xab21e25e9666d78bULL,
+	0x901063aae5e5c33cULL, 0x9818b34448698d90ULL, 0xe36487ae3e1e8abbULL,
+	0xafbdf931893bdcb4ULL, 0x6345a0dc5fbbd519ULL, 0x8628fe269b9465caULL,
+	0x1e5d01603f9c51ecULL, 0x4de44006a15049b7ULL, 0xbf6c70e5f776cbb1ULL,
+	0x411218f2ef552bedULL, 0xcb0c0708705a36a3ULL, 0xe74d14754f986044ULL,
+	0xcd56d9430ea8280eULL, 0xc12591d7535f5065ULL, 0xc83223f1720aef96ULL,
+	0xc3a0396f7363a51fULL
+};
+
+
+static void tgr192_round(u64 * ra, u64 * rb, u64 * rc, u64 x, int mul)
+{
+	u64 a = *ra;
+	u64 b = *rb;
+	u64 c = *rc;
+
+	c ^= x;
+	a -= sbox1[c         & 0xff] ^ sbox2[(c >> 16) & 0xff]
+	   ^ sbox3[(c >> 32) & 0xff] ^ sbox4[(c >> 48) & 0xff];
+	b += sbox4[(c >>  8) & 0xff] ^ sbox3[(c >> 24) & 0xff]
+	   ^ sbox2[(c >> 40) & 0xff] ^ sbox1[(c >> 56) & 0xff];
+	b *= mul;
+
+	*ra = a;
+	*rb = b;
+	*rc = c;
+}
+
+
+static void tgr192_pass(u64 * ra, u64 * rb, u64 * rc, u64 * x, int mul)
+{
+	u64 a = *ra;
+	u64 b = *rb;
+	u64 c = *rc;
+
+	tgr192_round(&a, &b, &c, x[0], mul);
+	tgr192_round(&b, &c, &a, x[1], mul);
+	tgr192_round(&c, &a, &b, x[2], mul);
+	tgr192_round(&a, &b, &c, x[3], mul);
+	tgr192_round(&b, &c, &a, x[4], mul);
+	tgr192_round(&c, &a, &b, x[5], mul);
+	tgr192_round(&a, &b, &c, x[6], mul);
+	tgr192_round(&b, &c, &a, x[7], mul);
+
+	*ra = a;
+	*rb = b;
+	*rc = c;
+}
+
+
+static void tgr192_key_schedule(u64 * x)
+{
+	x[0] -= x[7] ^ 0xa5a5a5a5a5a5a5a5ULL;
+	x[1] ^= x[0];
+	x[2] += x[1];
+	x[3] -= x[2] ^ ((~x[1]) << 19);
+	x[4] ^= x[3];
+	x[5] += x[4];
+	x[6] -= x[5] ^ ((~x[4]) >> 23);
+	x[7] ^= x[6];
+	x[0] += x[7];
+	x[1] -= x[0] ^ ((~x[7]) << 19);
+	x[2] ^= x[1];
+	x[3] += x[2];
+	x[4] -= x[3] ^ ((~x[2]) >> 23);
+	x[5] ^= x[4];
+	x[6] += x[5];
+	x[7] -= x[6] ^ 0x0123456789abcdefULL;
+}
+
+
+/****************
+ * Transform the message DATA which consists of 512 bytes (8 words)
+ */
+
+static void tgr192_transform(struct tgr192_ctx *tctx, const u8 * data)
+{
+	u64 a, b, c, aa, bb, cc;
+	u64 x[8];
+	int i;
+	const u8 *ptr = data;
+
+	for (i = 0; i < 8; i++, ptr += 8) {
+		x[i] = (((u64)ptr[7] ) << 56) ^
+		(((u64)ptr[6] & 0xffL) << 48) ^
+		(((u64)ptr[5] & 0xffL) << 40) ^
+		(((u64)ptr[4] & 0xffL) << 32) ^
+		(((u64)ptr[3] & 0xffL) << 24) ^
+		(((u64)ptr[2] & 0xffL) << 16) ^
+		(((u64)ptr[1] & 0xffL) <<  8) ^
+		(((u64)ptr[0] & 0xffL)      );
+	}
+
+	/* save */
+	a = aa = tctx->a;
+	b = bb = tctx->b;
+	c = cc = tctx->c;
+
+	tgr192_pass(&a, &b, &c, x, 5);
+	tgr192_key_schedule(x);
+	tgr192_pass(&c, &a, &b, x, 7);
+	tgr192_key_schedule(x);
+	tgr192_pass(&b, &c, &a, x, 9);
+
+
+	/* feedforward */
+	a ^= aa;
+	b -= bb;
+	c += cc;
+	/* store */
+	tctx->a = a;
+	tctx->b = b;
+	tctx->c = c;
+}
+
+static void tgr192_init(void *ctx)
+{
+	struct tgr192_ctx *tctx = ctx;
+
+	memset (tctx->hash, 0, 64);
+	tctx->a = 0x0123456789abcdefULL;
+	tctx->b = 0xfedcba9876543210ULL;
+	tctx->c = 0xf096a5b4c3b2e187ULL;
+	tctx->nblocks = 0;
+	tctx->count = 0;
+}
+
+
+/* Update the message digest with the contents
+ * of INBUF with length INLEN. */
+static void tgr192_update(void *ctx, const u8 * inbuf, unsigned int len)
+{
+	struct tgr192_ctx *tctx = ctx;
+
+	if (tctx->count == 64) {	/* flush the buffer */
+		tgr192_transform(tctx, tctx->hash);
+		tctx->count = 0;
+		tctx->nblocks++;
+	}
+	if (!inbuf) {
+		return;
+	}
+	if (tctx->count) {
+		for (; len && tctx->count < 64; len--) {
+			tctx->hash[tctx->count++] = *inbuf++;
+		}
+		tgr192_update(tctx, NULL, 0);
+		if (!len) {
+			return;
+		}
+
+	}
+
+	while (len >= 64) {
+		tgr192_transform(tctx, inbuf);
+		tctx->count = 0;
+		tctx->nblocks++;
+		len -= 64;
+		inbuf += 64;
+	}
+	for (; len && tctx->count < 64; len--) {
+		tctx->hash[tctx->count++] = *inbuf++;
+	}
+}
+
+
+
+/* The routine terminates the computation */
+static void tgr192_final(void *ctx, u8 * out)
+{
+	struct tgr192_ctx *tctx = ctx;
+	u32 t, msb, lsb;
+	u8 *p;
+	int i, j;
+
+	tgr192_update(tctx, NULL, 0); /* flush */ ;
+
+	msb = 0;
+	t = tctx->nblocks;
+	if ((lsb = t << 6) < t) { /* multiply by 64 to make a byte count */
+		msb++;
+	}
+	msb += t >> 26;
+	t = lsb;
+	if ((lsb = t + tctx->count) < t) {	/* add the count */
+		msb++;
+	}
+	t = lsb;
+	if ((lsb = t << 3) < t)	{ /* multiply by 8 to make a bit count */
+		msb++;
+	}
+	msb += t >> 29;
+
+	if (tctx->count < 56) {	/* enough room */
+		tctx->hash[tctx->count++] = 0x01;	/* pad */
+		while (tctx->count < 56) {
+			tctx->hash[tctx->count++] = 0;	/* pad */
+		}
+	} else {		/* need one extra block */
+		tctx->hash[tctx->count++] = 0x01;	/* pad character */
+		while (tctx->count < 64) {
+			tctx->hash[tctx->count++] = 0;
+		}
+		tgr192_update(tctx, NULL, 0); /* flush */ ;
+		memset(tctx->hash, 0, 56);    /* fill next block with zeroes */
+	}
+	/* append the 64 bit count */
+	tctx->hash[56] = lsb;
+	tctx->hash[57] = lsb >> 8;
+	tctx->hash[58] = lsb >> 16;
+	tctx->hash[59] = lsb >> 24;
+	tctx->hash[60] = msb;
+	tctx->hash[61] = msb >> 8;
+	tctx->hash[62] = msb >> 16;
+	tctx->hash[63] = msb >> 24;
+	tgr192_transform(tctx, tctx->hash);
+
+	p = tctx->hash;
+	*p++ = tctx->a >> 56; *p++ = tctx->a >> 48; *p++ = tctx->a >> 40;
+	*p++ = tctx->a >> 32; *p++ = tctx->a >> 24; *p++ = tctx->a >> 16;
+	*p++ = tctx->a >>  8; *p++ = tctx->a;\
+	*p++ = tctx->b >> 56; *p++ = tctx->b >> 48; *p++ = tctx->b >> 40;
+	*p++ = tctx->b >> 32; *p++ = tctx->b >> 24; *p++ = tctx->b >> 16;
+	*p++ = tctx->b >>  8; *p++ = tctx->b;
+	*p++ = tctx->c >> 56; *p++ = tctx->c >> 48; *p++ = tctx->c >> 40;
+	*p++ = tctx->c >> 32; *p++ = tctx->c >> 24; *p++ = tctx->c >> 16;
+	*p++ = tctx->c >>  8; *p++ = tctx->c;
+
+
+	/* unpack the hash */
+	j = 7;
+	for (i = 0; i < 8; i++) {
+		out[j--] = (tctx->a >> 8 * i) & 0xff;
+	}
+	j = 15;
+	for (i = 0; i < 8; i++) {
+		out[j--] = (tctx->b >> 8 * i) & 0xff;
+	}
+	j = 23;
+	for (i = 0; i < 8; i++) {
+		out[j--] = (tctx->c >> 8 * i) & 0xff;
+	}
+}
+
+static void tgr160_final(void *ctx, u8 * out)
+{
+	struct tgr192_ctx *wctx = ctx;
+	u8 D[64];
+
+	tgr192_final(wctx, D);
+	memcpy(out, D, TGR160_DIGEST_SIZE);
+	memset(D, 0, TGR192_DIGEST_SIZE);
+}
+
+static void tgr128_final(void *ctx, u8 * out)
+{
+	struct tgr192_ctx *wctx = ctx;
+	u8 D[64];
+
+	tgr192_final(wctx, D);
+	memcpy(out, D, TGR128_DIGEST_SIZE);
+	memset(D, 0, TGR192_DIGEST_SIZE);
+}
+
+static struct crypto_alg tgr192 = {
+	.cra_name = "tgr192",
+	.cra_flags = CRYPTO_ALG_TYPE_DIGEST,
+	.cra_blocksize = TGR192_BLOCK_SIZE,
+	.cra_ctxsize = sizeof(struct tgr192_ctx),
+	.cra_module = THIS_MODULE,
+	.cra_list = LIST_HEAD_INIT(tgr192.cra_list),
+	.cra_u = {.digest = {
+			     .dia_digestsize = TGR192_DIGEST_SIZE,
+			     .dia_init = tgr192_init,
+			     .dia_update = tgr192_update,
+			     .dia_final = tgr192_final}}
+};
+
+static struct crypto_alg tgr160 = {
+	.cra_name = "tgr160",
+	.cra_flags = CRYPTO_ALG_TYPE_DIGEST,
+	.cra_blocksize = TGR192_BLOCK_SIZE,
+	.cra_ctxsize = sizeof(struct tgr192_ctx),
+	.cra_module = THIS_MODULE,
+	.cra_list = LIST_HEAD_INIT(tgr160.cra_list),
+	.cra_u = {.digest = {
+			     .dia_digestsize = TGR160_DIGEST_SIZE,
+			     .dia_init = tgr192_init,
+			     .dia_update = tgr192_update,
+			     .dia_final = tgr160_final}}
+};
+
+static struct crypto_alg tgr128 = {
+	.cra_name = "tgr128",
+	.cra_flags = CRYPTO_ALG_TYPE_DIGEST,
+	.cra_blocksize = TGR192_BLOCK_SIZE,
+	.cra_ctxsize = sizeof(struct tgr192_ctx),
+	.cra_module = THIS_MODULE,
+	.cra_list = LIST_HEAD_INIT(tgr128.cra_list),
+	.cra_u = {.digest = {
+			     .dia_digestsize = TGR128_DIGEST_SIZE,
+			     .dia_init = tgr192_init,
+			     .dia_update = tgr192_update,
+			     .dia_final = tgr128_final}}
+};
+
+static int __init init(void)
+{
+	int ret = 0;
+
+	ret = crypto_register_alg(&tgr192);
+
+	if (ret < 0) {
+		goto out;
+	}
+
+	ret = crypto_register_alg(&tgr160);
+	if (ret < 0) {
+		crypto_unregister_alg(&tgr192);
+		goto out;
+	}
+
+	ret = crypto_register_alg(&tgr128);
+	if (ret < 0) {
+		crypto_unregister_alg(&tgr192);
+		crypto_unregister_alg(&tgr160);
+	}
+      out:
+	return ret;
+}
+
+static void __exit fini(void)
+{
+	crypto_unregister_alg(&tgr192);
+	crypto_unregister_alg(&tgr160);
+	crypto_unregister_alg(&tgr128);
+}
+
+MODULE_ALIAS("tgr160");
+MODULE_ALIAS("tgr128");
+
+module_init(init);
+module_exit(fini);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Tiger Message Digest Algorithm");
diff -Nru a/drivers/Makefile b/drivers/Makefile
--- a/drivers/Makefile	2005-03-11 12:51:52 -08:00
+++ b/drivers/Makefile	2005-03-11 12:51:52 -08:00
@@ -47,8 +47,8 @@
 obj-$(CONFIG_TC)		+= tc/
 obj-$(CONFIG_USB)		+= usb/
 obj-$(CONFIG_USB_GADGET)	+= usb/gadget/
-obj-$(CONFIG_INPUT)		+= input/
 obj-$(CONFIG_GAMEPORT)		+= input/gameport/
+obj-$(CONFIG_INPUT)		+= input/
 obj-$(CONFIG_I2O)		+= message/
 obj-$(CONFIG_I2C)		+= i2c/
 obj-$(CONFIG_W1)		+= w1/
@@ -61,5 +61,6 @@
 obj-$(CONFIG_CPU_FREQ)		+= cpufreq/
 obj-$(CONFIG_MMC)		+= mmc/
 obj-$(CONFIG_INFINIBAND)	+= infiniband/
+obj-$(CONFIG_BLK_DEV_SGIIOC4)	+= sn/
 obj-y				+= firmware/
 obj-$(CONFIG_CRYPTO)		+= crypto/
diff -Nru a/drivers/acorn/char/i2c.c b/drivers/acorn/char/i2c.c
--- a/drivers/acorn/char/i2c.c	2005-03-11 12:51:52 -08:00
+++ b/drivers/acorn/char/i2c.c	2005-03-11 12:51:52 -08:00
@@ -313,7 +313,7 @@
 
 static int ioc_client_reg(struct i2c_client *client)
 {
-	if (client->id == I2C_DRIVERID_PCF8583 &&
+	if (client->driver->id == I2C_DRIVERID_PCF8583 &&
 	    client->addr == 0x50) {
 		struct rtc_tm rtctm;
 		unsigned int year;
diff -Nru a/drivers/acorn/char/pcf8583.c b/drivers/acorn/char/pcf8583.c
--- a/drivers/acorn/char/pcf8583.c	2005-03-11 12:51:52 -08:00
+++ b/drivers/acorn/char/pcf8583.c	2005-03-11 12:51:52 -08:00
@@ -51,7 +51,6 @@
 		return -ENOMEM;
 
 	memset(c, 0, sizeof(*c));
-	c->id		= pcf8583_driver.id;
 	c->addr		= addr;
 	c->adapter	= adap;
 	c->driver	= &pcf8583_driver;
diff -Nru a/drivers/atm/ambassador.c b/drivers/atm/ambassador.c
--- a/drivers/atm/ambassador.c	2005-03-11 12:51:41 -08:00
+++ b/drivers/atm/ambassador.c	2005-03-11 12:51:41 -08:00
@@ -296,16 +296,16 @@
 #endif
 #define UCODE2(x) #x
 
-static u32 __initdata ucode_start = 
+static u32 __devinitdata ucode_start =
 #include UCODE(start)
 ;
 
-static region __initdata ucode_regions[] = {
+static region __devinitdata ucode_regions[] = {
 #include UCODE(regions)
   { 0, 0 }
 };
 
-static u32 __initdata ucode_data[] = {
+static u32 __devinitdata ucode_data[] = {
 #include UCODE(data)
   0xdeadbeef
 };
@@ -1539,7 +1539,7 @@
 
 /********** creation of communication queues **********/
 
-static int __init create_queues (amb_dev * dev, unsigned int cmds,
+static int __devinit create_queues (amb_dev * dev, unsigned int cmds,
 				 unsigned int txs, unsigned int * rxs,
 				 unsigned int * rx_buffer_sizes) {
   unsigned char pool;
@@ -1769,7 +1769,7 @@
 	return res;
 }
 
-static int __init do_loader_command (volatile loader_block * lb,
+static int __devinit do_loader_command (volatile loader_block * lb,
 				     const amb_dev * dev, loader_command cmd) {
   
   unsigned long timeout;
@@ -1825,7 +1825,7 @@
 
 /* loader: determine loader version */
 
-static int __init get_loader_version (loader_block * lb,
+static int __devinit get_loader_version (loader_block * lb,
 				      const amb_dev * dev, u32 * version) {
   int res;
   
@@ -1841,7 +1841,7 @@
 
 /* loader: write memory data blocks */
 
-static int __init loader_write (loader_block * lb,
+static int __devinit loader_write (loader_block * lb,
 				const amb_dev * dev, const u32 * data,
 				u32 address, unsigned int count) {
   unsigned int i;
@@ -1860,7 +1860,7 @@
 
 /* loader: verify memory data blocks */
 
-static int __init loader_verify (loader_block * lb,
+static int __devinit loader_verify (loader_block * lb,
 				 const amb_dev * dev, const u32 * data,
 				 u32 address, unsigned int count) {
   unsigned int i;
@@ -1885,7 +1885,7 @@
 
 /* loader: start microcode */
 
-static int __init loader_start (loader_block * lb,
+static int __devinit loader_start (loader_block * lb,
 				const amb_dev * dev, u32 address) {
   PRINTD (DBG_FLOW|DBG_LOAD, "loader_start");
   
@@ -1961,7 +1961,7 @@
 
 /********** transfer and start the microcode **********/
 
-static int __init ucode_init (loader_block * lb, amb_dev * dev) {
+static int __devinit ucode_init (loader_block * lb, amb_dev * dev) {
   unsigned int i = 0;
   unsigned int total = 0;
   const u32 * pointer = ucode_data;
@@ -2011,7 +2011,7 @@
     return cpu_to_be32 (virt_to_bus (addr));
 }
 
-static int __init amb_talk (amb_dev * dev) {
+static int __devinit amb_talk (amb_dev * dev) {
   adap_talk_block a;
   unsigned char pool;
   unsigned long timeout;
@@ -2058,7 +2058,7 @@
 }
 
 // get microcode version
-static void __init amb_ucode_version (amb_dev * dev) {
+static void __devinit amb_ucode_version (amb_dev * dev) {
   u32 major;
   u32 minor;
   command cmd;
@@ -2085,7 +2085,7 @@
 }
 
 // get end station address
-static void __init amb_esi (amb_dev * dev, u8 * esi) {
+static void __devinit amb_esi (amb_dev * dev, u8 * esi) {
   u32 lower4;
   u16 upper2;
   command cmd;
@@ -2131,7 +2131,7 @@
 	return;
 }
 
-static int __init amb_init (amb_dev * dev)
+static int __devinit amb_init (amb_dev * dev)
 {
   loader_block lb;
   
@@ -2447,7 +2447,7 @@
   amb_check_args();
   
   // get the juice
-  return pci_module_init(&amb_driver);
+  return pci_register_driver(&amb_driver);
 }
 
 /********** module exit **********/
diff -Nru a/drivers/atm/atmtcp.c b/drivers/atm/atmtcp.c
--- a/drivers/atm/atmtcp.c	2005-03-11 12:51:47 -08:00
+++ b/drivers/atm/atmtcp.c	2005-03-11 12:51:47 -08:00
@@ -67,7 +67,7 @@
 	*(struct atm_vcc **) &new_msg->vcc = vcc;
 	old_test = test_bit(flag,&vcc->flags);
 	out_vcc->push(out_vcc,skb);
-	add_wait_queue(vcc->sk->sk_sleep, &wait);
+	add_wait_queue(sk_atm(vcc)->sk_sleep, &wait);
 	while (test_bit(flag,&vcc->flags) == old_test) {
 		mb();
 		out_vcc = PRIV(vcc->dev) ? PRIV(vcc->dev)->vcc : NULL;
@@ -79,7 +79,7 @@
 		schedule();
 	}
 	set_current_state(TASK_RUNNING);
-	remove_wait_queue(vcc->sk->sk_sleep, &wait);
+	remove_wait_queue(sk_atm(vcc)->sk_sleep, &wait);
 	return error;
 }
 
@@ -91,7 +91,7 @@
 	vcc->vpi = msg->addr.sap_addr.vpi;
 	vcc->vci = msg->addr.sap_addr.vci;
 	vcc->qos = msg->qos;
-	vcc->sk->sk_err = -msg->result;
+	sk_atm(vcc)->sk_err = -msg->result;
 	switch (msg->type) {
 	    case ATMTCP_CTRL_OPEN:
 		change_bit(ATM_VF_READY,&vcc->flags);
@@ -104,7 +104,7 @@
 		    msg->type);
 		return -EINVAL;
 	}
-	wake_up(vcc->sk->sk_sleep);
+	wake_up(sk_atm(vcc)->sk_sleep);
 	return 0;
 }
 
@@ -135,7 +135,7 @@
 	clear_bit(ATM_VF_READY,&vcc->flags); /* just in case ... */
 	error = atmtcp_send_control(vcc,ATMTCP_CTRL_OPEN,&msg,ATM_VF_READY);
 	if (error) return error;
-	return -vcc->sk->sk_err;
+	return -sk_atm(vcc)->sk_err;
 }
 
 
@@ -267,7 +267,7 @@
 			walk = atm_sk(s);
 			if (walk->dev != atmtcp_dev)
 				continue;
-			wake_up(walk->sk->sk_sleep);
+			wake_up(s->sk_sleep);
 		}
 	}
 	read_unlock(&vcc_sklist_lock);
@@ -417,7 +417,7 @@
 	}
 	PRIV(dev)->vcc = vcc;
 	vcc->dev = &atmtcp_control_dev;
-	vcc_insert_socket(vcc->sk);
+	vcc_insert_socket(sk_atm(vcc));
 	set_bit(ATM_VF_META,&vcc->flags);
 	set_bit(ATM_VF_READY,&vcc->flags);
 	vcc->dev_data = dev;
diff -Nru a/drivers/atm/firestream.c b/drivers/atm/firestream.c
--- a/drivers/atm/firestream.c	2005-03-11 12:51:41 -08:00
+++ b/drivers/atm/firestream.c	2005-03-11 12:51:41 -08:00
@@ -2034,7 +2034,7 @@
 	int error;
 
 	func_enter ();
-	error = pci_module_init(&firestream_driver);
+	error = pci_register_driver(&firestream_driver);
 	func_exit ();
 	return error;
 }
diff -Nru a/drivers/atm/fore200e.c b/drivers/atm/fore200e.c
--- a/drivers/atm/fore200e.c	2005-03-11 12:51:52 -08:00
+++ b/drivers/atm/fore200e.c	2005-03-11 12:51:52 -08:00
@@ -96,10 +96,6 @@
 
 #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", \
@@ -114,7 +110,7 @@
 static const struct atmdev_ops   fore200e_ops;
 static const struct fore200e_bus fore200e_bus[];
 
-static struct fore200e* fore200e_boards = NULL;
+static LIST_HEAD(fore200e_boards);
 
 
 MODULE_AUTHOR("Christophe Lizzi - credits to Uwe Dannowski and Heikki Vatiainen");
@@ -246,7 +242,7 @@
 static void
 fore200e_spin(int msecs)
 {
-    unsigned long timeout = jiffies + MSECS(msecs);
+    unsigned long timeout = jiffies + msecs_to_jiffies(msecs);
     while (time_before(jiffies, timeout));
 }
 
@@ -254,7 +250,7 @@
 static int
 fore200e_poll(struct fore200e* fore200e, volatile u32* addr, u32 val, int msecs)
 {
-    unsigned long timeout = jiffies + MSECS(msecs);
+    unsigned long timeout = jiffies + msecs_to_jiffies(msecs);
     int           ok;
 
     mb();
@@ -278,7 +274,7 @@
 static int
 fore200e_io_poll(struct fore200e* fore200e, volatile u32 __iomem *addr, u32 val, int msecs)
 {
-    unsigned long timeout = jiffies + MSECS(msecs);
+    unsigned long timeout = jiffies + msecs_to_jiffies(msecs);
     int           ok;
 
     do {
@@ -637,39 +633,6 @@
 }
 
 
-static struct fore200e* __init
-fore200e_pca_detect(const struct fore200e_bus* bus, int index)
-{
-    struct fore200e* fore200e;
-    struct pci_dev*  pci_dev = NULL;
-    int              count = index;
-    
-    do {
-	pci_dev = pci_find_device(PCI_VENDOR_ID_FORE, PCI_DEVICE_ID_FORE_PCA200E, pci_dev);
-	if (pci_dev == NULL)
-	    return NULL;
-    } while (count--);
-
-    if (pci_enable_device(pci_dev))
-	return NULL;
-    
-    fore200e = fore200e_kmalloc(sizeof(struct fore200e), GFP_KERNEL);
-    if (fore200e == NULL)
-	return NULL;
-
-    fore200e->bus       = bus;
-    fore200e->bus_dev   = pci_dev;    
-    fore200e->irq       = pci_dev->irq;
-    fore200e->phys_base = pci_resource_start(pci_dev, 0);
-
-    sprintf(fore200e->name, "%s-%d", bus->model_name, index - 1);
-
-    pci_set_master(pci_dev);
-
-    return fore200e;
-}
-
-
 static int __init
 fore200e_pca_prom_read(struct fore200e* fore200e, struct prom_data* prom)
 {
@@ -1027,7 +990,7 @@
 		/* 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->sk_wmem_alloc
+		   to the prior incarnation of that vcc. otherwise, sk_atm(vcc)->sk_wmem_alloc
 		   would be decremented by the size of the (unrelated) skb, possibly
 		   leading to a negative sk->sk_wmem_alloc count, ultimately freezing the vcc.
 		   we thus bind the tx entry to the current incarnation of the vcc
@@ -1054,8 +1017,8 @@
 		}
 #if 1
 		/* race fixed by the above incarnation mechanism, but... */
-		if (atomic_read(&vcc->sk->sk_wmem_alloc) < 0) {
-		    atomic_set(&vcc->sk->sk_wmem_alloc, 0);
+		if (atomic_read(&sk_atm(vcc)->sk_wmem_alloc) < 0) {
+		    atomic_set(&sk_atm(vcc)->sk_wmem_alloc, 0);
 		}
 #endif
 		/* check error condition */
@@ -1258,12 +1221,12 @@
 	return -ENOMEM;
     }
 
-    ASSERT(atomic_read(&vcc->sk->sk_wmem_alloc) >= 0);
+    ASSERT(atomic_read(&sk_atm(vcc)->sk_wmem_alloc) >= 0);
 
     vcc->push(vcc, skb);
     atomic_inc(&vcc->stats->rx);
 
-    ASSERT(atomic_read(&vcc->sk->sk_wmem_alloc) >= 0);
+    ASSERT(atomic_read(&sk_atm(vcc)->sk_wmem_alloc) >= 0);
 
     return 0;
 }
@@ -1700,7 +1663,7 @@
     unsigned long           flags;
 
     ASSERT(vcc);
-    ASSERT(atomic_read(&vcc->sk->sk_wmem_alloc) >= 0);
+    ASSERT(atomic_read(&sk_atm(vcc)->sk_wmem_alloc) >= 0);
     ASSERT(fore200e);
     ASSERT(fore200e_vcc);
 
@@ -2596,7 +2559,7 @@
 fore200e_monitor_getc(struct fore200e* fore200e)
 {
     struct cp_monitor __iomem * monitor = fore200e->cp_monitor;
-    unsigned long      timeout = jiffies + MSECS(50);
+    unsigned long      timeout = jiffies + msecs_to_jiffies(50);
     int                c;
 
     while (time_before(jiffies, timeout)) {
@@ -2768,20 +2731,107 @@
     return 0;
 }
 
+
+static int __devinit
+fore200e_pca_detect(struct pci_dev *pci_dev, const struct pci_device_id *pci_ent)
+{
+    const struct fore200e_bus* bus = (struct fore200e_bus*) pci_ent->driver_data;
+    struct fore200e* fore200e;
+    int err = 0;
+    static int index = 0;
+
+    if (pci_enable_device(pci_dev)) {
+	err = -EINVAL;
+	goto out;
+    }
+    
+    fore200e = fore200e_kmalloc(sizeof(struct fore200e), GFP_KERNEL);
+    if (fore200e == NULL) {
+	err = -ENOMEM;
+	goto out_disable;
+    }
+
+    fore200e->bus       = bus;
+    fore200e->bus_dev   = pci_dev;    
+    fore200e->irq       = pci_dev->irq;
+    fore200e->phys_base = pci_resource_start(pci_dev, 0);
+
+    sprintf(fore200e->name, "%s-%d", bus->model_name, index - 1);
+
+    pci_set_master(pci_dev);
+
+    printk(FORE200E "device %s found at 0x%lx, IRQ %s\n",
+	   fore200e->bus->model_name, 
+	   fore200e->phys_base, fore200e_irq_itoa(fore200e->irq));
+
+    sprintf(fore200e->name, "%s-%d", bus->model_name, index);
+
+    err = fore200e_init(fore200e);
+    if (err < 0) {
+	fore200e_shutdown(fore200e);
+	goto out_free;
+    }
+
+    ++index;
+    pci_set_drvdata(pci_dev, fore200e);
+
+out:
+    return err;
+
+out_free:
+    kfree(fore200e);
+out_disable:
+    pci_disable_device(pci_dev);
+    goto out;
+}
+
+
+static void __devexit fore200e_pca_remove_one(struct pci_dev *pci_dev)
+{
+    struct fore200e *fore200e;
+
+    fore200e = pci_get_drvdata(pci_dev);
+
+    list_del(&fore200e->entry);
+
+    fore200e_shutdown(fore200e);
+    kfree(fore200e);
+    pci_disable_device(pci_dev);
+}
+
+
+#ifdef CONFIG_ATM_FORE200E_PCA
+static struct pci_device_id fore200e_pca_tbl[] = {
+    { PCI_VENDOR_ID_FORE, PCI_DEVICE_ID_FORE_PCA200E, PCI_ANY_ID, PCI_ANY_ID,
+      0, 0, (unsigned long) &fore200e_bus[0] },
+    { 0, }
+};
+
+MODULE_DEVICE_TABLE(pci, fore200e_pca_tbl);
+
+static struct pci_driver fore200e_pca_driver = {
+    .name =     "fore_200e",
+    .probe =    fore200e_pca_detect,
+    .remove =   __devexit_p(fore200e_pca_remove_one),
+    .id_table = fore200e_pca_tbl,
+};
+#endif
+
+
 static int __init
 fore200e_module_init(void)
 {
     const struct fore200e_bus* bus;
     struct       fore200e*     fore200e;
-    int                        index, link;
+    int                        index;
 
     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++) {
+    for (bus = fore200e_bus; bus->model_name; bus++) {
 
 	/* detect all boards present on that bus */
-	for (index = 0; (fore200e = bus->detect(bus, index)); index++) {
+	for (index = 0; bus->detect && (fore200e = bus->detect(bus, index)); index++) {
 	    
 	    printk(FORE200E "device %s found at 0x%lx, IRQ %s\n",
 		   fore200e->bus->model_name, 
@@ -2795,15 +2845,18 @@
 		break;
 	    }
 
-	    link++;
-
-	    fore200e->next  = fore200e_boards;
-	    fore200e_boards = fore200e;
+	    list_add(&fore200e->entry, &fore200e_boards);
 	}
     }
 
-    if (link)
-        return 0;
+#ifdef CONFIG_ATM_FORE200E_PCA
+    if (!pci_module_init(&fore200e_pca_driver))
+	return 0;
+#endif
+
+    if (!list_empty(&fore200e_boards))
+	return 0;
+
     return -ENODEV;
 }
 
@@ -2811,11 +2864,14 @@
 static void __exit
 fore200e_module_cleanup(void)
 {
-    while (fore200e_boards) {
-        struct fore200e* fore200e = fore200e_boards;
+    struct fore200e *fore200e, *next;
+
+#ifdef CONFIG_ATM_FORE200E_PCA
+    pci_unregister_driver(&fore200e_pca_driver);
+#endif
 
+    list_for_each_entry_safe(fore200e, next, &fore200e_boards, entry) {
 	fore200e_shutdown(fore200e);
-	fore200e_boards = fore200e->next;
 	kfree(fore200e);
     }
     DPRINTK(1, "module being removed\n");
@@ -3150,7 +3206,7 @@
       fore200e_pca_dma_sync_for_device,
       fore200e_pca_dma_chunk_alloc,
       fore200e_pca_dma_chunk_free,
-      fore200e_pca_detect,
+      NULL,
       fore200e_pca_configure,
       fore200e_pca_map,
       fore200e_pca_reset,
diff -Nru a/drivers/atm/fore200e.h b/drivers/atm/fore200e.h
--- a/drivers/atm/fore200e.h	2005-03-11 12:51:46 -08:00
+++ b/drivers/atm/fore200e.h	2005-03-11 12:51:46 -08:00
@@ -841,7 +841,7 @@
 /* per-device data */
 
 typedef struct fore200e {
-    struct       fore200e*     next;                   /* next device                        */
+    struct       list_head     entry;                  /* next device                        */
     const struct fore200e_bus* bus;                    /* bus-dependent code and data        */
     union        fore200e_regs regs;                   /* bus-dependent registers            */
     struct       atm_dev*      atm_dev;                /* ATM device                         */
diff -Nru a/drivers/atm/he.c b/drivers/atm/he.c
--- a/drivers/atm/he.c	2005-03-11 12:51:41 -08:00
+++ b/drivers/atm/he.c	2005-03-11 12:51:41 -08:00
@@ -2610,7 +2610,7 @@
 		 * TBRQ, the host issues the close command to the adapter.
 		 */
 
-		while (((tx_inuse = atomic_read(&vcc->sk->sk_wmem_alloc)) > 0) &&
+		while (((tx_inuse = atomic_read(&sk_atm(vcc)->sk_wmem_alloc)) > 0) &&
 		       (retry < MAX_RETRY)) {
 			msleep(sleep);
 			if (sleep < 250)
@@ -3079,7 +3079,7 @@
 
 static int __init he_init(void)
 {
-	return pci_module_init(&he_driver);
+	return pci_register_driver(&he_driver);
 }
 
 static void __exit he_cleanup(void)
diff -Nru a/drivers/atm/horizon.c b/drivers/atm/horizon.c
--- a/drivers/atm/horizon.c	2005-03-11 12:51:40 -08:00
+++ b/drivers/atm/horizon.c	2005-03-11 12:51:40 -08:00
@@ -2938,7 +2938,7 @@
   hrz_check_args();
   
   // get the juice
-  return pci_module_init(&hrz_driver);
+  return pci_register_driver(&hrz_driver);
 }
 
 /********** module exit **********/
diff -Nru a/drivers/atm/idt77252.c b/drivers/atm/idt77252.c
--- a/drivers/atm/idt77252.c	2005-03-11 12:51:46 -08:00
+++ b/drivers/atm/idt77252.c	2005-03-11 12:51:46 -08:00
@@ -727,10 +727,11 @@
 	spin_lock_irqsave(&vc->lock, flags);
 	if (vc->estimator) {
 		struct atm_vcc *vcc = vc->tx_vcc;
+		struct sock *sk = sk_atm(vcc);
 
 		vc->estimator->cells += (skb->len + 47) / 48;
-		if (atomic_read(&vcc->sk->sk_wmem_alloc) >
-		    (vcc->sk->sk_sndbuf >> 1)) {
+		if (atomic_read(&sk->sk_wmem_alloc) >
+		    (sk->sk_sndbuf >> 1)) {
 			u32 cps = vc->estimator->maxcps;
 
 			vc->estimator->cps = cps;
@@ -1325,7 +1326,7 @@
 			goto drop;
 		}
 
-		if ((vcc->sk != NULL) && !atm_charge(vcc, sb->truesize)) {
+		if (!atm_charge(vcc, sb->truesize)) {
 			RXPRINTK("%s: atm_charge() dropped AAL0 packets.\n",
 				 card->name);
 			dev_kfree_skb(sb);
@@ -2029,7 +2030,7 @@
 		atomic_inc(&vcc->stats->tx_err);
 		return -ENOMEM;
 	}
-	atomic_add(skb->truesize, &vcc->sk->sk_wmem_alloc);
+	atomic_add(skb->truesize, &sk_atm(vcc)->sk_wmem_alloc);
 
 	memcpy(skb_put(skb, 52), cell, 52);
 
diff -Nru a/drivers/atm/iphase.c b/drivers/atm/iphase.c
--- a/drivers/atm/iphase.c	2005-03-11 12:51:51 -08:00
+++ b/drivers/atm/iphase.c	2005-03-11 12:51:51 -08:00
@@ -1778,16 +1778,18 @@
         if (ia_vcc->pcr < iadev->rate_limit)
            skb_queue_head_init (&ia_vcc->txing_skb);
         if (ia_vcc->pcr < iadev->rate_limit) {
-           if (vcc->qos.txtp.max_sdu != 0) {
+	   struct sock *sk = sk_atm(vcc);
+
+	   if (vcc->qos.txtp.max_sdu != 0) {
                if (ia_vcc->pcr > 60000)
-                  vcc->sk->sk_sndbuf = vcc->qos.txtp.max_sdu * 5;
+                  sk->sk_sndbuf = vcc->qos.txtp.max_sdu * 5;
                else if (ia_vcc->pcr > 2000)
-                  vcc->sk->sk_sndbuf = vcc->qos.txtp.max_sdu * 4;
+                  sk->sk_sndbuf = vcc->qos.txtp.max_sdu * 4;
                else
-                 vcc->sk->sk_sndbuf = vcc->qos.txtp.max_sdu * 3;
+                 sk->sk_sndbuf = vcc->qos.txtp.max_sdu * 3;
            }
            else
-             vcc->sk->sk_sndbuf = 24576;
+             sk->sk_sndbuf = 24576;
         }
            
 	vc = (struct main_vc *)iadev->MAIN_VC_TABLE_ADDR;  
@@ -3244,8 +3246,8 @@
 	iadev_count--;
 	ia_dev[iadev_count] = NULL;
 	_ia_dev[iadev_count] = NULL;
+	IF_EVENT(printk("deregistering iav at (itf:%d)\n", dev->number);)
 	atm_dev_deregister(dev);
-	IF_EVENT(printk("iav deregistered at (itf:%d)\n", dev->number);)
 
       	iounmap(iadev->base);  
 	pci_disable_device(pdev);
@@ -3274,7 +3276,7 @@
 {
 	int ret;
 
-	ret = pci_module_init(&ia_driver);
+	ret = pci_register_driver(&ia_driver);
 	if (ret >= 0) {
 		ia_timer.expires = jiffies + 3*HZ;
 		add_timer(&ia_timer); 
diff -Nru a/drivers/atm/lanai.c b/drivers/atm/lanai.c
--- a/drivers/atm/lanai.c	2005-03-11 12:51:42 -08:00
+++ b/drivers/atm/lanai.c	2005-03-11 12:51:42 -08:00
@@ -566,7 +566,7 @@
 	return -EIO;
 }
 
-static int __init sram_test_pass(const struct lanai_dev *lanai, u32 pattern)
+static int __devinit sram_test_pass(const struct lanai_dev *lanai, u32 pattern)
 {
 	int offset, result = 0;
 	for (offset = 0; offset < SRAM_BYTES && result == 0; offset += 4)
@@ -574,7 +574,7 @@
 	return result;
 }
 
-static int __init sram_test_and_clear(const struct lanai_dev *lanai)
+static int __devinit sram_test_and_clear(const struct lanai_dev *lanai)
 {
 #ifdef FULL_MEMORY_TEST
 	int result;
@@ -650,7 +650,7 @@
 	enum lanai_vcc_offset offset)
 {
 	u32 val;
-	APRINTK(lvcc->vbase != 0, "cardvcc_read: unbound vcc!\n");
+	APRINTK(lvcc->vbase != NULL, "cardvcc_read: unbound vcc!\n");
 	val= readl(lvcc->vbase + offset);
 	RWDEBUG("VR vci=%04d 0x%02X = 0x%08X\n",
 	    lvcc->vci, (int) offset, val);
@@ -660,7 +660,7 @@
 static inline void cardvcc_write(const struct lanai_vcc *lvcc,
 	u32 val, enum lanai_vcc_offset offset)
 {
-	APRINTK(lvcc->vbase != 0, "cardvcc_write: unbound vcc!\n");
+	APRINTK(lvcc->vbase != NULL, "cardvcc_write: unbound vcc!\n");
 	APRINTK((val & ~0xFFFF) == 0,
 	    "cardvcc_write: bad val 0x%X (vci=%d, addr=0x%02X)\n",
 	    (unsigned int) val, lvcc->vci, (unsigned int) offset);
@@ -748,7 +748,7 @@
 /* Shutdown receiving on card */
 static void lanai_shutdown_rx_vci(const struct lanai_vcc *lvcc)
 {
-	if (lvcc->vbase == 0)		/* We were never bound to a VCI */
+	if (lvcc->vbase == NULL)	/* We were never bound to a VCI */
 		return;
 	/* 15.1.1 - set to trashing, wait one cell time (15us) */
 	cardvcc_write(lvcc,
@@ -779,7 +779,7 @@
 	int read, write, lastread = -1;
 	APRINTK(!in_interrupt(),
 	    "lanai_shutdown_tx_vci called w/o process context!\n");
-	if (lvcc->vbase == 0)		/* We were never bound to a VCI */
+	if (lvcc->vbase == NULL)	/* We were never bound to a VCI */
 		return;
 	/* 15.2.1 - wait for queue to drain */
 	while ((skb = skb_dequeue(&lvcc->tx.backlog)) != NULL)
@@ -860,7 +860,7 @@
 #ifndef READ_EEPROM
 
 /* Stub functions to use if EEPROM reading is disabled */
-static int __init eeprom_read(struct lanai_dev *lanai)
+static int __devinit eeprom_read(struct lanai_dev *lanai)
 {
 	printk(KERN_INFO DEV_LABEL "(itf %d): *NOT* reading EEPROM\n",
 	    lanai->number);
@@ -868,7 +868,7 @@
 	return 0;
 }
 
-static int __init eeprom_validate(struct lanai_dev *lanai)
+static int __devinit eeprom_validate(struct lanai_dev *lanai)
 {
 	lanai->serialno = 0;
 	lanai->magicno = EEPROM_MAGIC_VALUE;
@@ -877,7 +877,7 @@
 
 #else /* READ_EEPROM */
 
-static int __init eeprom_read(struct lanai_dev *lanai)
+static int __devinit eeprom_read(struct lanai_dev *lanai)
 {
 	int i, address;
 	u8 data;
@@ -953,7 +953,7 @@
 }
 
 /* Checksum/validate EEPROM contents */
-static int __init eeprom_validate(struct lanai_dev *lanai)
+static int __devinit eeprom_validate(struct lanai_dev *lanai)
 {
 	int i, s;
 	u32 v;
@@ -1449,7 +1449,7 @@
 #include <linux/vmalloc.h>
 #endif
 
-static int __init vcc_table_allocate(struct lanai_dev *lanai)
+static int __devinit vcc_table_allocate(struct lanai_dev *lanai)
 {
 #ifdef VCCTABLE_GETFREEPAGE
 	APRINTK((lanai->num_vci) * sizeof(struct lanai_vcc *) <= PAGE_SIZE,
@@ -1544,7 +1544,7 @@
 static inline void host_vcc_bind(struct lanai_dev *lanai,
 	struct lanai_vcc *lvcc, vci_t vci)
 {
-	if (lvcc->vbase != 0)
+	if (lvcc->vbase != NULL)
 		return;    /* We already were bound in the other direction */
 	DPRINTK("Binding vci %d\n", vci);
 #ifdef USE_POWERDOWN
@@ -1562,7 +1562,7 @@
 static inline void host_vcc_unbind(struct lanai_dev *lanai,
 	struct lanai_vcc *lvcc)
 {
-	if (lvcc->vbase == 0)
+	if (lvcc->vbase == NULL)
 		return;	/* This vcc was never bound */
 	DPRINTK("Unbinding vci %d\n", lvcc->vci);
 	lvcc->vbase = NULL;
@@ -1596,7 +1596,7 @@
 /*
  * Allocate service buffer and tell card about it
  */
-static int __init service_buffer_allocate(struct lanai_dev *lanai)
+static int __devinit service_buffer_allocate(struct lanai_dev *lanai)
 {
 	lanai_buf_allocate(&lanai->service, SERVICE_ENTRIES * 4, 8,
 	    lanai->pci);
@@ -1952,7 +1952,7 @@
 
 /* -------------------- PCI INITIALIZATION/SHUTDOWN: */
 
-static int __init lanai_pci_start(struct lanai_dev *lanai)
+static int __devinit lanai_pci_start(struct lanai_dev *lanai)
 {
 	struct pci_dev *pci = lanai->pci;
 	int result;
@@ -1964,7 +1964,7 @@
 		return -ENXIO;
 	}
 	pci_set_master(pci);
-	if (pci_set_dma_mask(pci, 0xFFFFFFFF) != 0) {
+	if (pci_set_dma_mask(pci, DMA_32BIT_MASK) != 0) {
 		printk(KERN_WARNING DEV_LABEL
 		    "(itf %d): No suitable DMA available.\n", lanai->number);
 		return -EBUSY;
@@ -2148,7 +2148,7 @@
 /* -------------------- OPERATIONS: */
 
 /* setup a newly detected device */
-static int __init lanai_dev_open(struct atm_dev *atmdev)
+static int __devinit lanai_dev_open(struct atm_dev *atmdev)
 {
 	struct lanai_dev *lanai = (struct lanai_dev *) atmdev->dev_data;
 	unsigned long raw_base;
@@ -2179,7 +2179,7 @@
 		goto error;
 	raw_base = lanai->pci->resource[0].start;
 	lanai->base = (bus_addr_t) ioremap(raw_base, LANAI_MAPPING_SIZE);
-	if (lanai->base == 0) {
+	if (lanai->base == NULL) {
 		printk(KERN_ERR DEV_LABEL ": couldn't remap I/O space\n");
 		goto error_pci;
 	}
@@ -2333,7 +2333,7 @@
 	}
 	if (lvcc->tx.atmvcc == atmvcc) {
 		if (atmvcc == lanai->cbrvcc) {
-			if (lvcc->vbase != 0)
+			if (lvcc->vbase != NULL)
 				lanai_cbr_shutdown(lanai);
 			lanai->cbrvcc = NULL;
 		}
@@ -2524,7 +2524,7 @@
 	struct lanai_vcc *lvcc = (struct lanai_vcc *) atmvcc->dev_data;
 	struct lanai_dev *lanai = (struct lanai_dev *) atmvcc->dev->dev_data;
 	unsigned long flags;
-	if (unlikely(lvcc == NULL || lvcc->vbase == 0 ||
+	if (unlikely(lvcc == NULL || lvcc->vbase == NULL ||
 	      lvcc->tx.atmvcc != atmvcc))
 		goto einval;
 #ifdef DEBUG
@@ -2746,7 +2746,7 @@
 {
 	int x;
 
-	x = pci_module_init(&lanai_driver);
+	x = pci_register_driver(&lanai_driver);
 	if (x != 0)
 		printk(KERN_ERR DEV_LABEL ": no adapter found\n");
 	return x;
diff -Nru a/drivers/atm/nicstar.c b/drivers/atm/nicstar.c
--- a/drivers/atm/nicstar.c	2005-03-11 12:51:41 -08:00
+++ b/drivers/atm/nicstar.c	2005-03-11 12:51:41 -08:00
@@ -381,7 +381,7 @@
 
    XPRINTK("nicstar: nicstar_init() called.\n");
 
-   error = pci_module_init(&nicstar_driver);
+   error = pci_register_driver(&nicstar_driver);
    
    TXPRINTK("nicstar: TX debug enabled.\n");
    RXPRINTK("nicstar: RX debug enabled.\n");
diff -Nru a/drivers/atm/zatm.c b/drivers/atm/zatm.c
--- a/drivers/atm/zatm.c	2005-03-11 12:51:41 -08:00
+++ b/drivers/atm/zatm.c	2005-03-11 12:51:41 -08:00
@@ -1090,7 +1090,7 @@
 /*----------------------------- (E)EPROM access -----------------------------*/
 
 
-static void __init eprom_set(struct zatm_dev *zatm_dev,unsigned long value,
+static void __devinit eprom_set(struct zatm_dev *zatm_dev,unsigned long value,
     unsigned short cmd)
 {
 	int error;
@@ -1101,7 +1101,7 @@
 }
 
 
-static unsigned long __init eprom_get(struct zatm_dev *zatm_dev,
+static unsigned long __devinit eprom_get(struct zatm_dev *zatm_dev,
     unsigned short cmd)
 {
 	unsigned int value;
@@ -1114,7 +1114,7 @@
 }
 
 
-static void __init eprom_put_bits(struct zatm_dev *zatm_dev,
+static void __devinit eprom_put_bits(struct zatm_dev *zatm_dev,
     unsigned long data,int bits,unsigned short cmd)
 {
 	unsigned long value;
@@ -1129,7 +1129,7 @@
 }
 
 
-static void __init eprom_get_byte(struct zatm_dev *zatm_dev,
+static void __devinit eprom_get_byte(struct zatm_dev *zatm_dev,
     unsigned char *byte,unsigned short cmd)
 {
 	int i;
@@ -1145,7 +1145,7 @@
 }
 
 
-static unsigned char __init eprom_try_esi(struct atm_dev *dev,
+static unsigned char __devinit eprom_try_esi(struct atm_dev *dev,
     unsigned short cmd,int offset,int swap)
 {
 	unsigned char buf[ZEPROM_SIZE];
@@ -1166,7 +1166,7 @@
 }
 
 
-static void __init eprom_get_esi(struct atm_dev *dev)
+static void __devinit eprom_get_esi(struct atm_dev *dev)
 {
 	if (eprom_try_esi(dev,ZEPROM_V1_REG,ZEPROM_V1_ESI_OFF,1)) return;
 	(void) eprom_try_esi(dev,ZEPROM_V2_REG,ZEPROM_V2_ESI_OFF,0);
@@ -1639,7 +1639,7 @@
 
 static int __init zatm_init_module(void)
 {
-	return pci_module_init(&zatm_driver);
+	return pci_register_driver(&zatm_driver);
 }
 
 module_init(zatm_init_module);
diff -Nru a/drivers/base/bus.c b/drivers/base/bus.c
--- a/drivers/base/bus.c	2005-03-11 12:51:42 -08:00
+++ b/drivers/base/bus.c	2005-03-11 12:51:42 -08:00
@@ -65,7 +65,7 @@
 static void driver_release(struct kobject * kobj)
 {
 	struct device_driver * drv = to_driver(kobj);
-	up(&drv->unload_sem);
+	complete(&drv->unloaded);
 }
 
 static struct kobj_type ktype_driver = {
@@ -465,6 +465,7 @@
 		up_write(&dev->bus->subsys.rwsem);
 		device_add_attrs(bus, dev);
 		sysfs_create_link(&bus->devices.kobj, &dev->kobj, dev->bus_id);
+		sysfs_create_link(&dev->kobj, &dev->bus->subsys.kset.kobj, "bus");
 	}
 	return error;
 }
@@ -481,6 +482,7 @@
 void bus_remove_device(struct device * dev)
 {
 	if (dev->bus) {
+		sysfs_remove_link(&dev->kobj, "bus");
 		sysfs_remove_link(&dev->bus->devices.kobj, dev->bus_id);
 		device_remove_attrs(dev->bus, dev);
 		down_write(&dev->bus->subsys.rwsem);
diff -Nru a/drivers/base/class.c b/drivers/base/class.c
--- a/drivers/base/class.c	2005-03-11 12:51:52 -08:00
+++ b/drivers/base/class.c	2005-03-11 12:51:52 -08:00
@@ -15,6 +15,7 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/string.h>
+#include <linux/kdev_t.h>
 #include "base.h"
 
 #define to_class_attr(_attr) container_of(_attr, struct class_attribute, attr)
@@ -139,6 +140,7 @@
 
 	INIT_LIST_HEAD(&cls->children);
 	INIT_LIST_HEAD(&cls->interfaces);
+	init_MUTEX(&cls->sem);
 	error = kobject_set_name(&cls->subsys.kset.kobj, "%s", cls->name);
 	if (error)
 		return error;
@@ -195,33 +197,6 @@
 		sysfs_remove_bin_file(&class_dev->kobj, attr);
 }
 
-static int class_device_dev_link(struct class_device * class_dev)
-{
-	if (class_dev->dev)
-		return sysfs_create_link(&class_dev->kobj,
-					 &class_dev->dev->kobj, "device");
-	return 0;
-}
-
-static void class_device_dev_unlink(struct class_device * class_dev)
-{
-	sysfs_remove_link(&class_dev->kobj, "device");
-}
-
-static int class_device_driver_link(struct class_device * class_dev)
-{
-	if ((class_dev->dev) && (class_dev->dev->driver))
-		return sysfs_create_link(&class_dev->kobj,
-					 &class_dev->dev->driver->kobj, "driver");
-	return 0;
-}
-
-static void class_device_driver_unlink(struct class_device * class_dev)
-{
-	sysfs_remove_link(&class_dev->kobj, "driver");
-}
-
-
 static ssize_t
 class_device_attr_show(struct kobject * kobj, struct attribute * attr,
 		       char * buf)
@@ -298,9 +273,9 @@
 			 int num_envp, char *buffer, int buffer_size)
 {
 	struct class_device *class_dev = to_class_dev(kobj);
-	int retval = 0;
 	int i = 0;
 	int length = 0;
+	int retval = 0;
 
 	pr_debug("%s - name = %s\n", __FUNCTION__, class_dev->class_id);
 
@@ -313,26 +288,34 @@
 				    &length, "PHYSDEVPATH=%s", path);
 		kfree(path);
 
-		/* add bus name of physical device */
 		if (dev->bus)
 			add_hotplug_env_var(envp, num_envp, &i,
 					    buffer, buffer_size, &length,
 					    "PHYSDEVBUS=%s", dev->bus->name);
 
-		/* add driver name of physical device */
 		if (dev->driver)
 			add_hotplug_env_var(envp, num_envp, &i,
 					    buffer, buffer_size, &length,
 					    "PHYSDEVDRIVER=%s", dev->driver->name);
-
-		/* terminate, set to next free slot, shrink available space */
-		envp[i] = NULL;
-		envp = &envp[i];
-		num_envp -= i;
-		buffer = &buffer[length];
-		buffer_size -= length;
 	}
 
+	if (MAJOR(class_dev->devt)) {
+		add_hotplug_env_var(envp, num_envp, &i,
+				    buffer, buffer_size, &length,
+				    "MAJOR=%u", MAJOR(class_dev->devt));
+
+		add_hotplug_env_var(envp, num_envp, &i,
+				    buffer, buffer_size, &length,
+				    "MINOR=%u", MINOR(class_dev->devt));
+	}
+
+	/* terminate, set to next free slot, shrink available space */
+	envp[i] = NULL;
+	envp = &envp[i];
+	num_envp -= i;
+	buffer = &buffer[length];
+	buffer_size -= length;
+
 	if (class_dev->class->hotplug) {
 		/* have the bus specific function add its stuff */
 		retval = class_dev->class->hotplug (class_dev, envp, num_envp,
@@ -388,6 +371,12 @@
 	}
 }
 
+static ssize_t show_dev(struct class_device *class_dev, char *buf)
+{
+	return print_dev_t(buf, class_dev->devt);
+}
+static CLASS_DEVICE_ATTR(dev, S_IRUGO, show_dev, NULL);
+
 void class_device_initialize(struct class_device *class_dev)
 {
 	kobj_set_kset_s(class_dev, class_obj_subsys);
@@ -425,16 +414,21 @@
 
 	/* now take care of our own registration */
 	if (parent) {
-		down_write(&parent->subsys.rwsem);
+		down(&parent->sem);
 		list_add_tail(&class_dev->node, &parent->children);
 		list_for_each_entry(class_intf, &parent->interfaces, node)
 			if (class_intf->add)
 				class_intf->add(class_dev);
-		up_write(&parent->subsys.rwsem);
+		up(&parent->sem);
 	}
+
+	if (MAJOR(class_dev->devt))
+		class_device_create_file(class_dev, &class_device_attr_dev);
+
 	class_device_add_attrs(class_dev);
-	class_device_dev_link(class_dev);
-	class_device_driver_link(class_dev);
+	if (class_dev->dev)
+		sysfs_create_link(&class_dev->kobj,
+				  &class_dev->dev->kobj, "device");
 
  register_done:
 	if (error && parent)
@@ -455,16 +449,16 @@
 	struct class_interface * class_intf;
 
 	if (parent) {
-		down_write(&parent->subsys.rwsem);
+		down(&parent->sem);
 		list_del_init(&class_dev->node);
 		list_for_each_entry(class_intf, &parent->interfaces, node)
 			if (class_intf->remove)
 				class_intf->remove(class_dev);
-		up_write(&parent->subsys.rwsem);
+		up(&parent->sem);
 	}
 
-	class_device_dev_unlink(class_dev);
-	class_device_driver_unlink(class_dev);
+	if (class_dev->dev)
+		sysfs_remove_link(&class_dev->kobj, "device");
 	class_device_remove_attrs(class_dev);
 
 	kobject_del(&class_dev->kobj);
@@ -516,8 +510,8 @@
 
 int class_interface_register(struct class_interface *class_intf)
 {
-	struct class * parent;
-	struct class_device * class_dev;
+	struct class *parent;
+	struct class_device *class_dev;
 
 	if (!class_intf || !class_intf->class)
 		return -ENODEV;
@@ -526,14 +520,13 @@
 	if (!parent)
 		return -EINVAL;
 
-	down_write(&parent->subsys.rwsem);
+	down(&parent->sem);
 	list_add_tail(&class_intf->node, &parent->interfaces);
-
 	if (class_intf->add) {
 		list_for_each_entry(class_dev, &parent->children, node)
 			class_intf->add(class_dev);
 	}
-	up_write(&parent->subsys.rwsem);
+	up(&parent->sem);
 
 	return 0;
 }
@@ -546,14 +539,13 @@
 	if (!parent)
 		return;
 
-	down_write(&parent->subsys.rwsem);
+	down(&parent->sem);
 	list_del_init(&class_intf->node);
-
 	if (class_intf->remove) {
 		list_for_each_entry(class_dev, &parent->children, node)
 			class_intf->remove(class_dev);
 	}
-	up_write(&parent->subsys.rwsem);
+	up(&parent->sem);
 
 	class_put(parent);
 }
diff -Nru a/drivers/base/class_simple.c b/drivers/base/class_simple.c
--- a/drivers/base/class_simple.c	2005-03-11 12:51:42 -08:00
+++ b/drivers/base/class_simple.c	2005-03-11 12:51:42 -08:00
@@ -10,18 +10,15 @@
 
 #include <linux/config.h>
 #include <linux/device.h>
-#include <linux/kdev_t.h>
 #include <linux/err.h>
 
 struct class_simple {
-	struct class_device_attribute attr;
 	struct class class;
 };
 #define to_class_simple(d) container_of(d, struct class_simple, class)
 
 struct simple_dev {
 	struct list_head node;
-	dev_t dev;
 	struct class_device class_dev;
 };
 #define to_simple_dev(d) container_of(d, struct simple_dev, class_dev)
@@ -35,12 +32,6 @@
 	kfree(s_dev);
 }
 
-static ssize_t show_dev(struct class_device *class_dev, char *buf)
-{
-	struct simple_dev *s_dev = to_simple_dev(class_dev);
-	return print_dev_t(buf, s_dev->dev);
-}
-
 static void class_simple_release(struct class *class)
 {
 	struct class_simple *cs = to_class_simple(class);
@@ -75,12 +66,6 @@
 	cs->class.class_release = class_simple_release;
 	cs->class.release = release_simple_dev;
 
-	cs->attr.attr.name = "dev";
-	cs->attr.attr.mode = S_IRUGO;
-	cs->attr.attr.owner = owner;
-	cs->attr.show = show_dev;
-	cs->attr.store = NULL;
-
 	retval = class_register(&cs->class);
 	if (retval)
 		goto error;
@@ -143,7 +128,7 @@
 	}
 	memset(s_dev, 0x00, sizeof(*s_dev));
 
-	s_dev->dev = dev;
+	s_dev->class_dev.devt = dev;
 	s_dev->class_dev.dev = device;
 	s_dev->class_dev.class = &cs->class;
 
@@ -154,8 +139,6 @@
 	if (retval)
 		goto error;
 
-	class_device_create_file(&s_dev->class_dev, &cs->attr);
-
 	spin_lock(&simple_dev_list_lock);
 	list_add(&s_dev->node, &simple_dev_list);
 	spin_unlock(&simple_dev_list_lock);
@@ -200,7 +183,7 @@
 
 	spin_lock(&simple_dev_list_lock);
 	list_for_each_entry(s_dev, &simple_dev_list, node) {
-		if (s_dev->dev == dev) {
+		if (s_dev->class_dev.devt == dev) {
 			found = 1;
 			break;
 		}
diff -Nru a/drivers/base/driver.c b/drivers/base/driver.c
--- a/drivers/base/driver.c	2005-03-11 12:51:51 -08:00
+++ b/drivers/base/driver.c	2005-03-11 12:51:51 -08:00
@@ -79,14 +79,14 @@
  *	since most of the things we have to do deal with the bus
  *	structures.
  *
- *	The one interesting aspect is that we initialize @drv->unload_sem
- *	to a locked state here. It will be unlocked when the driver
- *	reference count reaches 0.
+ *	The one interesting aspect is that we setup @drv->unloaded
+ *	as a completion that gets complete when the driver reference
+ *	count reaches 0.
  */
 int driver_register(struct device_driver * drv)
 {
 	INIT_LIST_HEAD(&drv->devices);
-	init_MUTEX_LOCKED(&drv->unload_sem);
+	init_completion(&drv->unloaded);
 	return bus_add_driver(drv);
 }
 
@@ -97,7 +97,7 @@
  *
  *	Again, we pass off most of the work to the bus-level call.
  *
- *	Though, once that is done, we attempt to take @drv->unload_sem.
+ *	Though, once that is done, we wait until @drv->unloaded is completed.
  *	This will block until the driver refcount reaches 0, and it is
  *	released. Only modular drivers will call this function, and we
  *	have to guarantee that it won't complete, letting the driver
@@ -107,8 +107,7 @@
 void driver_unregister(struct device_driver * drv)
 {
 	bus_remove_driver(drv);
-	down(&drv->unload_sem);
-	up(&drv->unload_sem);
+	wait_for_completion(&drv->unloaded);
 }
 
 /**
diff -Nru a/drivers/base/map.c b/drivers/base/map.c
--- a/drivers/base/map.c	2005-03-11 12:51:47 -08:00
+++ b/drivers/base/map.c	2005-03-11 12:51:47 -08:00
@@ -25,7 +25,7 @@
 		int (*lock)(dev_t, void *);
 		void *data;
 	} *probes[255];
-	struct rw_semaphore *sem;
+	struct semaphore *sem;
 };
 
 int kobj_map(struct kobj_map *domain, dev_t dev, unsigned long range,
@@ -53,7 +53,7 @@
 		p->range = range;
 		p->data = data;
 	}
-	down_write(domain->sem);
+	down(domain->sem);
 	for (i = 0, p -= n; i < n; i++, p++, index++) {
 		struct probe **s = &domain->probes[index % 255];
 		while (*s && (*s)->range < range)
@@ -61,7 +61,7 @@
 		p->next = *s;
 		*s = p;
 	}
-	up_write(domain->sem);
+	up(domain->sem);
 	return 0;
 }
 
@@ -75,7 +75,7 @@
 	if (n > 255)
 		n = 255;
 
-	down_write(domain->sem);
+	down(domain->sem);
 	for (i = 0; i < n; i++, index++) {
 		struct probe **s;
 		for (s = &domain->probes[index % 255]; *s; s = &(*s)->next) {
@@ -88,7 +88,7 @@
 			}
 		}
 	}
-	up_write(domain->sem);
+	up(domain->sem);
 	kfree(found);
 }
 
@@ -99,7 +99,7 @@
 	unsigned long best = ~0UL;
 
 retry:
-	down_read(domain->sem);
+	down(domain->sem);
 	for (p = domain->probes[MAJOR(dev) % 255]; p; p = p->next) {
 		struct kobject *(*probe)(dev_t, int *, void *);
 		struct module *owner;
@@ -120,7 +120,7 @@
 			module_put(owner);
 			continue;
 		}
-		up_read(domain->sem);
+		up(domain->sem);
 		kobj = probe(dev, index, data);
 		/* Currently ->owner protects _only_ ->probe() itself. */
 		module_put(owner);
@@ -128,12 +128,11 @@
 			return kobj;
 		goto retry;
 	}
-	up_read(domain->sem);
+	up(domain->sem);
 	return NULL;
 }
 
-struct kobj_map *kobj_map_init(kobj_probe_t *base_probe,
-		struct subsystem *s)
+struct kobj_map *kobj_map_init(kobj_probe_t *base_probe, struct semaphore *sem)
 {
 	struct kobj_map *p = kmalloc(sizeof(struct kobj_map), GFP_KERNEL);
 	struct probe *base = kmalloc(sizeof(struct probe), GFP_KERNEL);
@@ -151,6 +150,6 @@
 	base->get = base_probe;
 	for (i = 0; i < 255; i++)
 		p->probes[i] = base;
-	p->sem = &s->rwsem;
+	p->sem = sem;
 	return p;
 }
diff -Nru a/drivers/base/platform.c b/drivers/base/platform.c
--- a/drivers/base/platform.c	2005-03-11 12:51:41 -08:00
+++ b/drivers/base/platform.c	2005-03-11 12:51:41 -08:00
@@ -131,7 +131,7 @@
 	pdev->dev.bus = &platform_bus_type;
 
 	if (pdev->id != -1)
-		snprintf(pdev->dev.bus_id, BUS_ID_SIZE, "%s%u", pdev->name, pdev->id);
+		snprintf(pdev->dev.bus_id, BUS_ID_SIZE, "%s.%u", pdev->name, pdev->id);
 	else
 		strlcpy(pdev->dev.bus_id, pdev->name, BUS_ID_SIZE);
 
diff -Nru a/drivers/base/sys.c b/drivers/base/sys.c
--- a/drivers/base/sys.c	2005-03-11 12:51:40 -08:00
+++ b/drivers/base/sys.c	2005-03-11 12:51:40 -08:00
@@ -79,7 +79,7 @@
 /*
  * declare system_subsys
  */
-decl_subsys(system, &ktype_sysdev, NULL);
+static decl_subsys(system, &ktype_sysdev, NULL);
 
 int sysdev_class_register(struct sysdev_class * cls)
 {
@@ -102,7 +102,8 @@
 EXPORT_SYMBOL_GPL(sysdev_class_unregister);
 
 
-static LIST_HEAD(global_drivers);
+static LIST_HEAD(sysdev_drivers);
+static DECLARE_MUTEX(sysdev_drivers_lock);
 
 /**
  *	sysdev_driver_register - Register auxillary driver
@@ -112,14 +113,14 @@
  *	If @cls is valid, then @drv is inserted into @cls->drivers to be
  *	called on each operation on devices of that class. The refcount
  *	of @cls is incremented.
- *	Otherwise, @drv is inserted into global_drivers, and called for
+ *	Otherwise, @drv is inserted into sysdev_drivers, and called for
  *	each device.
  */
 
 int sysdev_driver_register(struct sysdev_class * cls,
 			   struct sysdev_driver * drv)
 {
-	down_write(&system_subsys.rwsem);
+	down(&sysdev_drivers_lock);
 	if (cls && kset_get(&cls->kset)) {
 		list_add_tail(&drv->entry, &cls->drivers);
 
@@ -130,8 +131,8 @@
 				drv->add(dev);
 		}
 	} else
-		list_add_tail(&drv->entry, &global_drivers);
-	up_write(&system_subsys.rwsem);
+		list_add_tail(&drv->entry, &sysdev_drivers);
+	up(&sysdev_drivers_lock);
 	return 0;
 }
 
@@ -144,7 +145,7 @@
 void sysdev_driver_unregister(struct sysdev_class * cls,
 			      struct sysdev_driver * drv)
 {
-	down_write(&system_subsys.rwsem);
+	down(&sysdev_drivers_lock);
 	list_del_init(&drv->entry);
 	if (cls) {
 		if (drv->remove) {
@@ -154,7 +155,7 @@
 		}
 		kset_put(&cls->kset);
 	}
-	up_write(&system_subsys.rwsem);
+	up(&sysdev_drivers_lock);
 }
 
 EXPORT_SYMBOL_GPL(sysdev_driver_register);
@@ -193,13 +194,13 @@
 	if (!error) {
 		struct sysdev_driver * drv;
 
-		down_write(&system_subsys.rwsem);
+		down(&sysdev_drivers_lock);
 		/* Generic notification is implicit, because it's that
 		 * code that should have called us.
 		 */
 
 		/* Notify global drivers */
-		list_for_each_entry(drv, &global_drivers, entry) {
+		list_for_each_entry(drv, &sysdev_drivers, entry) {
 			if (drv->add)
 				drv->add(sysdev);
 		}
@@ -209,7 +210,7 @@
 			if (drv->add)
 				drv->add(sysdev);
 		}
-		up_write(&system_subsys.rwsem);
+		up(&sysdev_drivers_lock);
 	}
 	return error;
 }
@@ -218,8 +219,8 @@
 {
 	struct sysdev_driver * drv;
 
-	down_write(&system_subsys.rwsem);
-	list_for_each_entry(drv, &global_drivers, entry) {
+	down(&sysdev_drivers_lock);
+	list_for_each_entry(drv, &sysdev_drivers, entry) {
 		if (drv->remove)
 			drv->remove(sysdev);
 	}
@@ -228,7 +229,7 @@
 		if (drv->remove)
 			drv->remove(sysdev);
 	}
-	up_write(&system_subsys.rwsem);
+	up(&sysdev_drivers_lock);
 
 	kobject_unregister(&sysdev->kobj);
 }
@@ -255,7 +256,7 @@
 
 	pr_debug("Shutting Down System Devices\n");
 
-	down_write(&system_subsys.rwsem);
+	down(&sysdev_drivers_lock);
 	list_for_each_entry_reverse(cls, &system_subsys.kset.list,
 				    kset.kobj.entry) {
 		struct sys_device * sysdev;
@@ -268,7 +269,7 @@
 			pr_debug(" %s\n", kobject_name(&sysdev->kobj));
 
 			/* Call global drivers first. */
-			list_for_each_entry(drv, &global_drivers, entry) {
+			list_for_each_entry(drv, &sysdev_drivers, entry) {
 				if (drv->shutdown)
 					drv->shutdown(sysdev);
 			}
@@ -284,7 +285,7 @@
 				cls->shutdown(sysdev);
 		}
 	}
-	up_write(&system_subsys.rwsem);
+	up(&sysdev_drivers_lock);
 }
 
 
@@ -319,7 +320,7 @@
 			pr_debug(" %s\n", kobject_name(&sysdev->kobj));
 
 			/* Call global drivers first. */
-			list_for_each_entry(drv, &global_drivers, entry) {
+			list_for_each_entry(drv, &sysdev_drivers, entry) {
 				if (drv->suspend)
 					drv->suspend(sysdev, state);
 			}
@@ -375,7 +376,7 @@
 			}
 
 			/* Call global drivers. */
-			list_for_each_entry(drv, &global_drivers, entry) {
+			list_for_each_entry(drv, &sysdev_drivers, entry) {
 				if (drv->resume)
 					drv->resume(sysdev);
 			}
diff -Nru a/drivers/block/aoe/aoe.h b/drivers/block/aoe/aoe.h
--- a/drivers/block/aoe/aoe.h	2005-03-11 12:51:48 -08:00
+++ b/drivers/block/aoe/aoe.h	2005-03-11 12:51:48 -08:00
@@ -143,7 +143,6 @@
 int aoechr_init(void);
 void aoechr_exit(void);
 void aoechr_error(char *);
-void aoechr_hdump(char *, int len);
 
 void aoecmd_work(struct aoedev *d);
 void aoecmd_cfg(ushort, unsigned char);
diff -Nru a/drivers/block/aoe/aoeblk.c b/drivers/block/aoe/aoeblk.c
--- a/drivers/block/aoe/aoeblk.c	2005-03-11 12:51:42 -08:00
+++ b/drivers/block/aoe/aoeblk.c	2005-03-11 12:51:42 -08:00
@@ -28,7 +28,8 @@
 {
 	struct aoedev *d = disk->private_data;
 
-	return snprintf(page, PAGE_SIZE, "%012llx\n", mac_addr(d->addr));
+	return snprintf(page, PAGE_SIZE, "%012llx\n",
+			(unsigned long long)mac_addr(d->addr));
 }
 static ssize_t aoedisk_show_netif(struct gendisk * disk, char *page)
 {
@@ -241,7 +242,8 @@
 	aoedisk_add_sysfs(d);
 	
 	printk(KERN_INFO "aoe: %012llx e%lu.%lu v%04x has %llu "
-		"sectors\n", mac_addr(d->addr), d->aoemajor, d->aoeminor,
+		"sectors\n", (unsigned long long)mac_addr(d->addr),
+		d->aoemajor, d->aoeminor,
 		d->fw_ver, (long long)d->ssize);
 }
 
diff -Nru a/drivers/block/aoe/aoechr.c b/drivers/block/aoe/aoechr.c
--- a/drivers/block/aoe/aoechr.c	2005-03-11 12:51:52 -08:00
+++ b/drivers/block/aoe/aoechr.c	2005-03-11 12:51:52 -08:00
@@ -99,41 +99,6 @@
 		up(&emsgs_sema);
 }
 
-#define PERLINE 16
-void
-aoechr_hdump(char *buf, int n)
-{
-	int bufsiz;
-	char *fbuf;
-	int linelen;
-	char *p, *e, *fp;
-
-	bufsiz = n * 3;			/* 2 hex digits and a space */
-	bufsiz += n / PERLINE + 1;	/* the newline characters */
-	bufsiz += 1;			/* the final '\0' */
-
-	fbuf = kmalloc(bufsiz, GFP_ATOMIC);
-	if (!fbuf) {
-		printk(KERN_INFO
-		       "%s: cannot allocate memory\n",
-		       __FUNCTION__);
-		return;
-	}
-	
-	for (p = buf; n <= 0;) {
-		linelen = n > PERLINE ? PERLINE : n;
-		n -= linelen;
-
-		fp = fbuf;
-		for (e=p+linelen; p<e; p++)
-			fp += sprintf(fp, "%2.2X ", *p & 255);
-		sprintf(fp, "\n");
-		aoechr_error(fbuf);
-	}
-
-	kfree(fbuf);
-}
-
 static ssize_t
 aoechr_write(struct file *filp, const char __user *buf, size_t cnt, loff_t *offp)
 {
@@ -178,13 +143,13 @@
 static ssize_t
 aoechr_read(struct file *filp, char __user *buf, size_t cnt, loff_t *off)
 {
-	int n;
+	unsigned long n;
 	char *mp;
 	struct ErrMsg *em;
 	ssize_t len;
 	ulong flags;
 
-	n = (int) filp->private_data;
+	n = (unsigned long) filp->private_data;
 	switch (n) {
 	case MINOR_ERR:
 		spin_lock_irqsave(&emsgs_lock, flags);
@@ -233,7 +198,7 @@
 	}
 }
 
-struct file_operations aoe_fops = {
+static struct file_operations aoe_fops = {
 	.write = aoechr_write,
 	.read = aoechr_read,
 	.open = aoechr_open,
diff -Nru a/drivers/block/aoe/aoecmd.c b/drivers/block/aoe/aoecmd.c
--- a/drivers/block/aoe/aoecmd.c	2005-03-11 12:51:47 -08:00
+++ b/drivers/block/aoe/aoecmd.c	2005-03-11 12:51:47 -08:00
@@ -416,7 +416,9 @@
 
 	if (ahin->cmdstat & 0xa9) {	/* these bits cleared on success */
 		printk(KERN_CRIT "aoe: aoecmd_ata_rsp: ata error cmd=%2.2Xh "
-			"stat=%2.2Xh\n", ahout->cmdstat, ahin->cmdstat);
+			"stat=%2.2Xh from e%ld.%ld\n", 
+			ahout->cmdstat, ahin->cmdstat,
+			d->aoemajor, d->aoeminor);
 		if (buf)
 			buf->flags |= BUFFL_FAIL;
 	} else {
@@ -458,8 +460,8 @@
 	if (buf) {
 		buf->nframesout -= 1;
 		if (buf->nframesout == 0 && buf->resid == 0) {
-			n = !(buf->flags & BUFFL_FAIL);
-			bio_endio(buf->bio, buf->bio->bi_size, 0);
+			n = (buf->flags & BUFFL_FAIL) ? -EIO : 0;
+			bio_endio(buf->bio, buf->bio->bi_size, n);
 			mempool_free(buf, d->bufpool);
 		}
 	}
diff -Nru a/drivers/block/as-iosched.c b/drivers/block/as-iosched.c
--- a/drivers/block/as-iosched.c	2005-03-11 12:51:52 -08:00
+++ b/drivers/block/as-iosched.c	2005-03-11 12:51:52 -08:00
@@ -1463,35 +1463,36 @@
 	arq->state = AS_RQ_QUEUED;
 }
 
-/*
- * requeue the request. The request has not been completed, nor is it a
- * new request, so don't touch accounting.
- */
-static void as_requeue_request(request_queue_t *q, struct request *rq)
+static void as_deactivate_request(request_queue_t *q, struct request *rq)
 {
 	struct as_data *ad = q->elevator->elevator_data;
 	struct as_rq *arq = RQ_DATA(rq);
 
 	if (arq) {
-		if (arq->state != AS_RQ_REMOVED) {
-			printk("arq->state %d\n", arq->state);
-			WARN_ON(1);
+		if (arq->state == AS_RQ_REMOVED) {
+			arq->state = AS_RQ_DISPATCHED;
+			if (arq->io_context && arq->io_context->aic)
+				atomic_inc(&arq->io_context->aic->nr_dispatched);
 		}
-
-		arq->state = AS_RQ_DISPATCHED;
-		if (arq->io_context && arq->io_context->aic)
-			atomic_inc(&arq->io_context->aic->nr_dispatched);
 	} else
 		WARN_ON(blk_fs_request(rq)
 			&& (!(rq->flags & (REQ_HARDBARRIER|REQ_SOFTBARRIER))) );
 
-	list_add(&rq->queuelist, ad->dispatch);
-
 	/* Stop anticipating - let this request get through */
 	as_antic_stop(ad);
 }
 
 /*
+ * requeue the request. The request has not been completed, nor is it a
+ * new request, so don't touch accounting.
+ */
+static void as_requeue_request(request_queue_t *q, struct request *rq)
+{
+	as_deactivate_request(q, rq);
+	list_add(&rq->queuelist, &q->queue_head);
+}
+
+/*
  * Account a request that is inserted directly onto the dispatch queue.
  * arq->io_context->aic->nr_dispatched should not need to be incremented
  * because only new requests should come through here: requeues go through
@@ -2080,6 +2081,7 @@
 		.elevator_add_req_fn =		as_insert_request,
 		.elevator_remove_req_fn =	as_remove_request,
 		.elevator_requeue_req_fn = 	as_requeue_request,
+		.elevator_deactivate_req_fn = 	as_deactivate_request,
 		.elevator_queue_empty_fn =	as_queue_empty,
 		.elevator_completed_req_fn =	as_completed_request,
 		.elevator_former_req_fn =	as_former_request,
diff -Nru a/drivers/block/cciss.c b/drivers/block/cciss.c
--- a/drivers/block/cciss.c	2005-03-11 12:51:51 -08:00
+++ b/drivers/block/cciss.c	2005-03-11 12:51:51 -08:00
@@ -46,14 +46,14 @@
 #include <linux/completion.h>
 
 #define CCISS_DRIVER_VERSION(maj,min,submin) ((maj<<16)|(min<<8)|(submin))
-#define DRIVER_NAME "HP CISS Driver (v 2.6.4)"
-#define DRIVER_VERSION CCISS_DRIVER_VERSION(2,6,4)
+#define DRIVER_NAME "HP CISS Driver (v 2.6.6)"
+#define DRIVER_VERSION CCISS_DRIVER_VERSION(2,6,6)
 
 /* Embedded module documentation macros - see modules.h */
 MODULE_AUTHOR("Hewlett-Packard Company");
-MODULE_DESCRIPTION("Driver for HP Controller SA5xxx SA6xxx version 2.6.4");
+MODULE_DESCRIPTION("Driver for HP Controller SA5xxx SA6xxx version 2.6.6");
 MODULE_SUPPORTED_DEVICE("HP SA5i SA5i+ SA532 SA5300 SA5312 SA641 SA642 SA6400"
-			" SA6i P600");
+			" SA6i P600 P800 E400");
 MODULE_LICENSE("GPL");
 
 #include "cciss_cmd.h"
@@ -82,6 +82,10 @@
 		0x0E11, 0x4091, 0, 0, 0},
 	{ PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSA,
 		0x103C, 0x3225, 0, 0, 0},
+	{ PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSB,
+		0x103c, 0x3223, 0, 0, 0},
+	{ PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSB,
+		0x103c, 0x3231, 0, 0, 0},
 	{0,}
 };
 MODULE_DEVICE_TABLE(pci, cciss_pci_device_id);
@@ -103,6 +107,8 @@
 	{ 0x409D0E11, "Smart Array 6400 EM", &SA5_access},
 	{ 0x40910E11, "Smart Array 6i", &SA5_access},
 	{ 0x3225103C, "Smart Array P600", &SA5_access},
+	{ 0x3223103C, "Smart Array P800", &SA5_access},
+	{ 0x3231103C, "Smart Array E400", &SA5_access},
 };
 
 /* How long to wait (in millesconds) for board to go into simple mode */
@@ -114,7 +120,11 @@
 
 #define READ_AHEAD 	 1024
 #define NR_CMDS		 384 /* #commands that can be outstanding */
-#define MAX_CTLR 8
+#define MAX_CTLR	32
+
+/* Originally cciss driver only supports 8 major numbers */
+#define MAX_CTLR_ORIG 	8
+
 
 #define CCISS_DMA_MASK	0xFFFFFFFF	/* 32 bit DMA */
 
@@ -2080,6 +2090,9 @@
 	drive_info_struct *drv;
 	int i, dir;
 
+	/* We call start_io here in case there is a command waiting on the
+	 * queue that has not been sent.
+	*/
 	if (blk_queue_plugged(q))
 		goto startio;
 
@@ -2168,6 +2181,9 @@
 full:
 	blk_stop_queue(q);
 startio:
+	/* We will already have the driver lock here so not need
+	 * to lock it.
+	*/
 	start_io(h);
 }
 
@@ -2177,7 +2193,8 @@
 	CommandList_struct *c;
 	unsigned long flags;
 	__u32 a, a1;
-
+	int j;
+	int start_queue = h->next_to_run;
 
 	/* Is this interrupt for us? */
 	if (( h->access.intr_pending(h) == 0) || (h->interrupts_enabled == 0))
@@ -2224,13 +2241,50 @@
 		}
 	}
 
-	/*
-	 * See if we can queue up some more IO
+ 	/* check to see if we have maxed out the number of commands that can
+ 	 * be placed on the queue.  If so then exit.  We do this check here
+ 	 * in case the interrupt we serviced was from an ioctl and did not
+ 	 * free any new commands.
 	 */
-	blk_start_queue(h->queue);
+ 	if ((find_first_zero_bit(h->cmd_pool_bits, NR_CMDS)) == NR_CMDS)
+ 		goto cleanup;
+
+ 	/* We have room on the queue for more commands.  Now we need to queue
+ 	 * them up.  We will also keep track of the next queue to run so
+ 	 * that every queue gets a chance to be started first.
+ 	*/
+ 	for (j=0; j < NWD; j++){
+ 		int curr_queue = (start_queue + j) % NWD;
+ 		/* make sure the disk has been added and the drive is real
+ 		 * because this can be called from the middle of init_one.
+ 		*/
+ 		if(!(h->gendisk[curr_queue]->queue) ||
+		 		   !(h->drv[curr_queue].heads))
+ 			continue;
+ 		blk_start_queue(h->gendisk[curr_queue]->queue);
+
+ 		/* check to see if we have maxed out the number of commands
+ 		 * that can be placed on the queue.
+ 		*/
+ 		if ((find_first_zero_bit(h->cmd_pool_bits, NR_CMDS)) == NR_CMDS)
+ 		{
+ 			if (curr_queue == start_queue){
+ 				h->next_to_run = (start_queue + 1) % NWD;
+ 				goto cleanup;
+ 			} else {
+ 				h->next_to_run = curr_queue;
+ 				goto cleanup;
+ 	}
+ 		} else {
+ 			curr_queue = (curr_queue + 1) % NWD;
+ 		}
+ 	}
+
+cleanup:
 	spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags);
 	return IRQ_HANDLED;
 }
+
 /* 
  *  We cannot read the structure directly, for portablity we must use 
  *   the io functions.
@@ -2644,7 +2698,7 @@
 		}
 	}
 	printk(KERN_WARNING "cciss: This driver supports a maximum"
-		" of 8 controllers.\n");
+		" of %d controllers.\n", MAX_CTLR);
 	goto out;
 Enomem:
 	printk(KERN_ERR "cciss: out of memory.\n");
@@ -2676,13 +2730,14 @@
 	request_queue_t *q;
 	int i;
 	int j;
+	int rc;
 
 	printk(KERN_DEBUG "cciss: Device 0x%x has been found at"
 			" bus %d dev %d func %d\n",
 		pdev->device, pdev->bus->number, PCI_SLOT(pdev->devfn),
 			PCI_FUNC(pdev->devfn));
 	i = alloc_cciss_hba();
-	if( i < 0 ) 
+	if(i < 0)
 		return (-1);
 	if (cciss_pci_init(hba[i], pdev) != 0)
 		goto clean1;
@@ -2701,11 +2756,24 @@
 		goto clean1;
 	}
 
-	if (register_blkdev(COMPAQ_CISS_MAJOR+i, hba[i]->devname)) {
-		printk(KERN_ERR "cciss: Unable to register device %s\n",
-				hba[i]->devname);
+	/*
+	 * register with the major number, or get a dynamic major number
+	 * by passing 0 as argument.  This is done for greater than
+	 * 8 controller support.
+	 */
+	if (i < MAX_CTLR_ORIG)
+		hba[i]->major = MAJOR_NR + i;
+	rc = register_blkdev(hba[i]->major, hba[i]->devname);
+	if(rc == -EBUSY || rc == -EINVAL) {
+		printk(KERN_ERR
+			"cciss:  Unable to get major number %d for %s "
+			"on hba %d\n", hba[i]->major, hba[i]->devname, i);
 		goto clean1;
 	}
+	else {
+		if (i >= MAX_CTLR_ORIG)
+			hba[i]->major = rc;
+	}
 
 	/* make sure the board interrupts are off */
 	hba[i]->access.set_intr_mask(hba[i], CCISS_INTR_OFF);
@@ -2776,7 +2844,7 @@
 
 		sprintf(disk->disk_name, "cciss/c%dd%d", i, j);
 		sprintf(disk->devfs_name, "cciss/host%d/target%d", i, j);
-		disk->major = COMPAQ_CISS_MAJOR + i;
+		disk->major = hba[i]->major;
 		disk->first_minor = j << NWD_SHIFT;
 		disk->fops = &cciss_fops;
 		disk->queue = hba[i]->queue;
@@ -2805,7 +2873,7 @@
 			hba[i]->errinfo_pool_dhandle);
 	free_irq(hba[i]->intr, hba[i]);
 clean2:
-	unregister_blkdev(COMPAQ_CISS_MAJOR+i, hba[i]->devname);
+	unregister_blkdev(hba[i]->major, hba[i]->devname);
 clean1:
 	release_io_mem(hba[i]);
 	free_hba(i);
@@ -2847,7 +2915,7 @@
 	pci_set_drvdata(pdev, NULL);
 	iounmap(hba[i]->vaddr);
 	cciss_unregister_scsi(i);  /* unhook from SCSI subsystem */
-	unregister_blkdev(COMPAQ_CISS_MAJOR+i, hba[i]->devname);
+	unregister_blkdev(hba[i]->major, hba[i]->devname);
 	remove_proc_entry(hba[i]->devname, proc_cciss);	
 	
 	/* remove it from the disk list */
diff -Nru a/drivers/block/cciss.h b/drivers/block/cciss.h
--- a/drivers/block/cciss.h	2005-03-11 12:51:40 -08:00
+++ b/drivers/block/cciss.h	2005-03-11 12:51:40 -08:00
@@ -13,6 +13,8 @@
 #define IO_OK		0
 #define IO_ERROR	1
 
+#define MAJOR_NR COMPAQ_CISS_MAJOR
+
 struct ctlr_info;
 typedef struct ctlr_info ctlr_info_t;
 
@@ -50,6 +52,7 @@
 	CfgTable_struct __iomem *cfgtable;
 	unsigned int intr;
 	int	interrupts_enabled;
+	int	major;
 	int 	max_commands;
 	int	commands_outstanding;
 	int 	max_outstanding; /* Debug */ 
@@ -80,6 +83,11 @@
 	int			nr_allocs;
 	int			nr_frees; 
 	int			busy_configuring;
+
+	/* This element holds the zero based queue number of the last
+	 * queue to be started.  It is used for fairness.
+	*/
+	int			next_to_run;
 
 	// Disk structures we need to pass back
 	struct gendisk   *gendisk[NWD];
diff -Nru a/drivers/block/cfq-iosched.c b/drivers/block/cfq-iosched.c
--- a/drivers/block/cfq-iosched.c	2005-03-11 12:51:47 -08:00
+++ b/drivers/block/cfq-iosched.c	2005-03-11 12:51:47 -08:00
@@ -607,10 +607,7 @@
 	return NULL;
 }
 
-/*
- * make sure the service time gets corrected on reissue of this request
- */
-static void cfq_requeue_request(request_queue_t *q, struct request *rq)
+static void cfq_deactivate_request(request_queue_t *q, struct request *rq)
 {
 	struct cfq_rq *crq = RQ_DATA(rq);
 
@@ -627,6 +624,14 @@
 			cfqq->cfqd->rq_in_driver--;
 		}
 	}
+}
+
+/*
+ * make sure the service time gets corrected on reissue of this request
+ */
+static void cfq_requeue_request(request_queue_t *q, struct request *rq)
+{
+	cfq_deactivate_request(q, rq);
 	list_add(&rq->queuelist, &q->queue_head);
 }
 
@@ -1804,6 +1809,7 @@
 		.elevator_add_req_fn =		cfq_insert_request,
 		.elevator_remove_req_fn =	cfq_remove_request,
 		.elevator_requeue_req_fn =	cfq_requeue_request,
+		.elevator_deactivate_req_fn =	cfq_deactivate_request,
 		.elevator_queue_empty_fn =	cfq_queue_empty,
 		.elevator_completed_req_fn =	cfq_completed_request,
 		.elevator_former_req_fn =	cfq_former_request,
diff -Nru a/drivers/block/elevator.c b/drivers/block/elevator.c
--- a/drivers/block/elevator.c	2005-03-11 12:51:50 -08:00
+++ b/drivers/block/elevator.c	2005-03-11 12:51:50 -08:00
@@ -255,8 +255,16 @@
 		e->ops->elevator_merge_req_fn(q, rq, next);
 }
 
-void elv_requeue_request(request_queue_t *q, struct request *rq)
+/*
+ * For careful internal use by the block layer. Essentially the same as
+ * a requeue in that it tells the io scheduler that this request is not
+ * active in the driver or hardware anymore, but we don't want the request
+ * added back to the scheduler. Function is not exported.
+ */
+void elv_deactivate_request(request_queue_t *q, struct request *rq)
 {
+	elevator_t *e = q->elevator;
+
 	/*
 	 * it already went through dequeue, we need to decrement the
 	 * in_flight count again
@@ -264,6 +272,24 @@
 	if (blk_account_rq(rq))
 		q->in_flight--;
 
+	rq->flags &= ~REQ_STARTED;
+
+	if (e->ops->elevator_deactivate_req_fn)
+		e->ops->elevator_deactivate_req_fn(q, rq);
+}
+
+void elv_requeue_request(request_queue_t *q, struct request *rq)
+{
+	elv_deactivate_request(q, rq);
+
+	/*
+	 * if this is the flush, requeue the original instead and drop the flush
+	 */
+	if (rq->flags & REQ_BAR_FLUSH) {
+		clear_bit(QUEUE_FLAG_FLUSH, &q->queue_flags);
+		rq = rq->end_io_data;
+	}
+
 	/*
 	 * if iosched has an explicit requeue hook, then use that. otherwise
 	 * just put the request at the front of the queue
@@ -320,7 +346,21 @@
 
 static inline struct request *__elv_next_request(request_queue_t *q)
 {
-	return q->elevator->ops->elevator_next_req_fn(q);
+	struct request *rq = q->elevator->ops->elevator_next_req_fn(q);
+
+	/*
+	 * if this is a barrier write and the device has to issue a
+	 * flush sequence to support it, check how far we are
+	 */
+	if (rq && blk_fs_request(rq) && blk_barrier_rq(rq)) {
+		BUG_ON(q->ordered == QUEUE_ORDERED_NONE);
+
+		if (q->ordered == QUEUE_ORDERED_FLUSH &&
+		    !blk_barrier_preflush(rq))
+			rq = blk_start_pre_flush(q, rq);
+	}
+
+	return rq;
 }
 
 struct request *elv_next_request(request_queue_t *q)
diff -Nru a/drivers/block/floppy.c b/drivers/block/floppy.c
--- a/drivers/block/floppy.c	2005-03-11 12:51:41 -08:00
+++ b/drivers/block/floppy.c	2005-03-11 12:51:41 -08:00
@@ -4370,6 +4370,10 @@
 		goto out_flush_work;
 	}
 
+	err = platform_device_register(&floppy_device);
+	if (err)
+		goto out_flush_work;
+
 	for (drive = 0; drive < N_DRIVE; drive++) {
 		if (!(allowed_drive_mask & (1 << drive)))
 			continue;
@@ -4379,23 +4383,12 @@
 		disks[drive]->private_data = (void *)(long)drive;
 		disks[drive]->queue = floppy_queue;
 		disks[drive]->flags |= GENHD_FL_REMOVABLE;
+		disks[drive]->driverfs_dev = &floppy_device.dev;
 		add_disk(disks[drive]);
 	}
 
-	err = platform_device_register(&floppy_device);
-	if (err)
-		goto out_del_disk;
-
 	return 0;
 
-out_del_disk:
-	for (drive = 0; drive < N_DRIVE; drive++) {
-		if (!(allowed_drive_mask & (1 << drive)))
-			continue;
-		if (fdc_state[FDC(drive)].version == FDC_NONE)
-			continue;
-		del_gendisk(disks[drive]);
-	}
 out_flush_work:
 	flush_scheduled_work();
 	if (usage_count)
@@ -4600,7 +4593,6 @@
 	int drive;
 
 	init_completion(&device_release);
-	platform_device_unregister(&floppy_device);
 	blk_unregister_region(MKDEV(FLOPPY_MAJOR, 0), 256);
 	unregister_blkdev(FLOPPY_MAJOR, "fd");
 
@@ -4614,6 +4606,7 @@
 		}
 		put_disk(disks[drive]);
 	}
+	platform_device_unregister(&floppy_device);
 	devfs_remove("floppy");
 
 	del_timer_sync(&fd_timeout);
diff -Nru a/drivers/block/genhd.c b/drivers/block/genhd.c
--- a/drivers/block/genhd.c	2005-03-11 12:51:46 -08:00
+++ b/drivers/block/genhd.c	2005-03-11 12:51:46 -08:00
@@ -302,7 +302,7 @@
 
 static int __init genhd_device_init(void)
 {
-	bdev_map = kobj_map_init(base_probe, &block_subsys);
+	bdev_map = kobj_map_init(base_probe, &block_subsys_sem);
 	blk_dev_init();
 	subsystem_register(&block_subsys);
 	return 0;
@@ -430,42 +430,57 @@
 static int block_hotplug(struct kset *kset, struct kobject *kobj, char **envp,
 			 int num_envp, char *buffer, int buffer_size)
 {
-	struct device *dev = NULL;
 	struct kobj_type *ktype = get_ktype(kobj);
+	struct device *physdev;
+	struct gendisk *disk;
+	struct hd_struct *part;
 	int length = 0;
 	int i = 0;
 
-	/* get physical device backing disk or partition */
 	if (ktype == &ktype_block) {
-		struct gendisk *disk = container_of(kobj, struct gendisk, kobj);
-		dev = disk->driverfs_dev;
+		disk = container_of(kobj, struct gendisk, kobj);
+		add_hotplug_env_var(envp, num_envp, &i, buffer, buffer_size,
+				    &length, "MINOR=%u", disk->first_minor);
 	} else if (ktype == &ktype_part) {
-		struct gendisk *disk = container_of(kobj->parent, struct gendisk, kobj);
-		dev = disk->driverfs_dev;
-	}
-
-	if (dev) {
-		/* add physical device, backing this device  */
-		char *path = kobject_get_path(&dev->kobj, GFP_KERNEL);
+		disk = container_of(kobj->parent, struct gendisk, kobj);
+		part = container_of(kobj, struct hd_struct, kobj);
+		add_hotplug_env_var(envp, num_envp, &i, buffer, buffer_size,
+				    &length, "MINOR=%u",
+				    disk->first_minor + part->partno);
+	} else
+		return 0;
+
+	add_hotplug_env_var(envp, num_envp, &i, buffer, buffer_size, &length,
+			    "MAJOR=%u", disk->major);
+
+	/* add physical device, backing this device  */
+	physdev = disk->driverfs_dev;
+	if (physdev) {
+		char *path = kobject_get_path(&physdev->kobj, GFP_KERNEL);
 
 		add_hotplug_env_var(envp, num_envp, &i, buffer, buffer_size,
 				    &length, "PHYSDEVPATH=%s", path);
 		kfree(path);
 
-		/* add bus name of physical device */
-		if (dev->bus)
+		if (physdev->bus)
 			add_hotplug_env_var(envp, num_envp, &i,
 					    buffer, buffer_size, &length,
-					    "PHYSDEVBUS=%s", dev->bus->name);
+					    "PHYSDEVBUS=%s",
+					    physdev->bus->name);
 
-		/* add driver name of physical device */
-		if (dev->driver)
+		if (physdev->driver)
 			add_hotplug_env_var(envp, num_envp, &i,
 					    buffer, buffer_size, &length,
-					    "PHYSDEVDRIVER=%s", dev->driver->name);
-
-		envp[i] = NULL;
+					    "PHYSDEVDRIVER=%s",
+					    physdev->driver->name);
 	}
+
+	/* terminate, set to next free slot, shrink available space */
+	envp[i] = NULL;
+	envp = &envp[i];
+	num_envp -= i;
+	buffer = &buffer[length];
+	buffer_size -= length;
 
 	return 0;
 }
diff -Nru a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c
--- a/drivers/block/ll_rw_blk.c	2005-03-11 12:51:41 -08:00
+++ b/drivers/block/ll_rw_blk.c	2005-03-11 12:51:41 -08:00
@@ -267,6 +267,25 @@
 
 EXPORT_SYMBOL(blk_queue_make_request);
 
+static inline void rq_init(request_queue_t *q, struct request *rq)
+{
+	INIT_LIST_HEAD(&rq->queuelist);
+
+	rq->errors = 0;
+	rq->rq_status = RQ_ACTIVE;
+	rq->bio = rq->biotail = NULL;
+	rq->buffer = NULL;
+	rq->ref_count = 1;
+	rq->q = q;
+	rq->waiting = NULL;
+	rq->special = NULL;
+	rq->data_len = 0;
+	rq->data = NULL;
+	rq->sense = NULL;
+	rq->end_io = NULL;
+	rq->end_io_data = NULL;
+}
+
 /**
  * blk_queue_ordered - does this queue support ordered writes
  * @q:     the request queue
@@ -281,10 +300,26 @@
  **/
 void blk_queue_ordered(request_queue_t *q, int flag)
 {
-	if (flag)
-		set_bit(QUEUE_FLAG_ORDERED, &q->queue_flags);
-	else
-		clear_bit(QUEUE_FLAG_ORDERED, &q->queue_flags);
+	switch (flag) {
+		case QUEUE_ORDERED_NONE:
+			if (q->flush_rq)
+				kmem_cache_free(request_cachep, q->flush_rq);
+			q->flush_rq = NULL;
+			q->ordered = flag;
+			break;
+		case QUEUE_ORDERED_TAG:
+			q->ordered = flag;
+			break;
+		case QUEUE_ORDERED_FLUSH:
+			q->ordered = flag;
+			if (!q->flush_rq)
+				q->flush_rq = kmem_cache_alloc(request_cachep,
+								GFP_KERNEL);
+			break;
+		default:
+			printk("blk_queue_ordered: bad value %d\n", flag);
+			break;
+	}
 }
 
 EXPORT_SYMBOL(blk_queue_ordered);
@@ -306,6 +341,169 @@
 
 EXPORT_SYMBOL(blk_queue_issue_flush_fn);
 
+/*
+ * Cache flushing for ordered writes handling
+ */
+static void blk_pre_flush_end_io(struct request *flush_rq)
+{
+	struct request *rq = flush_rq->end_io_data;
+	request_queue_t *q = rq->q;
+
+	rq->flags |= REQ_BAR_PREFLUSH;
+
+	if (!flush_rq->errors)
+		elv_requeue_request(q, rq);
+	else {
+		q->end_flush_fn(q, flush_rq);
+		clear_bit(QUEUE_FLAG_FLUSH, &q->queue_flags);
+		q->request_fn(q);
+	}
+}
+
+static void blk_post_flush_end_io(struct request *flush_rq)
+{
+	struct request *rq = flush_rq->end_io_data;
+	request_queue_t *q = rq->q;
+
+	rq->flags |= REQ_BAR_POSTFLUSH;
+
+	q->end_flush_fn(q, flush_rq);
+	clear_bit(QUEUE_FLAG_FLUSH, &q->queue_flags);
+	q->request_fn(q);
+}
+
+struct request *blk_start_pre_flush(request_queue_t *q, struct request *rq)
+{
+	struct request *flush_rq = q->flush_rq;
+
+	BUG_ON(!blk_barrier_rq(rq));
+
+	if (test_and_set_bit(QUEUE_FLAG_FLUSH, &q->queue_flags))
+		return NULL;
+
+	rq_init(q, flush_rq);
+	flush_rq->elevator_private = NULL;
+	flush_rq->flags = REQ_BAR_FLUSH;
+	flush_rq->rq_disk = rq->rq_disk;
+	flush_rq->rl = NULL;
+
+	/*
+	 * prepare_flush returns 0 if no flush is needed, just mark both
+	 * pre and post flush as done in that case
+	 */
+	if (!q->prepare_flush_fn(q, flush_rq)) {
+		rq->flags |= REQ_BAR_PREFLUSH | REQ_BAR_POSTFLUSH;
+		clear_bit(QUEUE_FLAG_FLUSH, &q->queue_flags);
+		return rq;
+	}
+
+	/*
+	 * some drivers dequeue requests right away, some only after io
+	 * completion. make sure the request is dequeued.
+	 */
+	if (!list_empty(&rq->queuelist))
+		blkdev_dequeue_request(rq);
+
+	elv_deactivate_request(q, rq);
+
+	flush_rq->end_io_data = rq;
+	flush_rq->end_io = blk_pre_flush_end_io;
+
+	__elv_add_request(q, flush_rq, ELEVATOR_INSERT_FRONT, 0);
+	return flush_rq;
+}
+
+static void blk_start_post_flush(request_queue_t *q, struct request *rq)
+{
+	struct request *flush_rq = q->flush_rq;
+
+	BUG_ON(!blk_barrier_rq(rq));
+
+	rq_init(q, flush_rq);
+	flush_rq->elevator_private = NULL;
+	flush_rq->flags = REQ_BAR_FLUSH;
+	flush_rq->rq_disk = rq->rq_disk;
+	flush_rq->rl = NULL;
+
+	if (q->prepare_flush_fn(q, flush_rq)) {
+		flush_rq->end_io_data = rq;
+		flush_rq->end_io = blk_post_flush_end_io;
+
+		__elv_add_request(q, flush_rq, ELEVATOR_INSERT_FRONT, 0);
+		q->request_fn(q);
+	}
+}
+
+static inline int blk_check_end_barrier(request_queue_t *q, struct request *rq,
+					int sectors)
+{
+	if (sectors > rq->nr_sectors)
+		sectors = rq->nr_sectors;
+
+	rq->nr_sectors -= sectors;
+	return rq->nr_sectors;
+}
+
+static int __blk_complete_barrier_rq(request_queue_t *q, struct request *rq,
+				     int sectors, int queue_locked)
+{
+	if (q->ordered != QUEUE_ORDERED_FLUSH)
+		return 0;
+	if (!blk_fs_request(rq) || !blk_barrier_rq(rq))
+		return 0;
+	if (blk_barrier_postflush(rq))
+		return 0;
+
+	if (!blk_check_end_barrier(q, rq, sectors)) {
+		unsigned long flags = 0;
+
+		if (!queue_locked)
+			spin_lock_irqsave(q->queue_lock, flags);
+
+		blk_start_post_flush(q, rq);
+
+		if (!queue_locked)
+			spin_unlock_irqrestore(q->queue_lock, flags);
+	}
+
+	return 1;
+}
+
+/**
+ * blk_complete_barrier_rq - complete possible barrier request
+ * @q:  the request queue for the device
+ * @rq:  the request
+ * @sectors:  number of sectors to complete
+ *
+ * Description:
+ *   Used in driver end_io handling to determine whether to postpone
+ *   completion of a barrier request until a post flush has been done. This
+ *   is the unlocked variant, used if the caller doesn't already hold the
+ *   queue lock.
+ **/
+int blk_complete_barrier_rq(request_queue_t *q, struct request *rq, int sectors)
+{
+	return __blk_complete_barrier_rq(q, rq, sectors, 0);
+}
+EXPORT_SYMBOL(blk_complete_barrier_rq);
+
+/**
+ * blk_complete_barrier_rq_locked - complete possible barrier request
+ * @q:  the request queue for the device
+ * @rq:  the request
+ * @sectors:  number of sectors to complete
+ *
+ * Description:
+ *   See blk_complete_barrier_rq(). This variant must be used if the caller
+ *   holds the queue lock.
+ **/
+int blk_complete_barrier_rq_locked(request_queue_t *q, struct request *rq,
+				   int sectors)
+{
+	return __blk_complete_barrier_rq(q, rq, sectors, 1);
+}
+EXPORT_SYMBOL(blk_complete_barrier_rq_locked);
+
 /**
  * blk_queue_bounce_limit - set bounce buffer limit for queue
  * @q:  the request queue for the device
@@ -1428,6 +1626,8 @@
 	if (q->queue_tags)
 		__blk_queue_free_tags(q);
 
+	blk_queue_ordered(q, QUEUE_ORDERED_NONE);
+
 	kmem_cache_free(requestq_cachep, q);
 }
 
@@ -1739,21 +1939,8 @@
 	if (ioc_batching(q, ioc))
 		ioc->nr_batch_requests--;
 	
-	INIT_LIST_HEAD(&rq->queuelist);
-
-	rq->errors = 0;
-	rq->rq_status = RQ_ACTIVE;
-	rq->bio = rq->biotail = NULL;
-	rq->buffer = NULL;
-	rq->ref_count = 1;
-	rq->q = q;
+	rq_init(q, rq);
 	rq->rl = rl;
-	rq->waiting = NULL;
-	rq->special = NULL;
-	rq->data_len = 0;
-	rq->data = NULL;
-	rq->sense = NULL;
-
 out:
 	put_io_context(ioc);
 	return rq;
@@ -2018,11 +2205,11 @@
 	}
 
 	rq->flags |= REQ_NOMERGE;
-	if (!rq->waiting)
-		rq->waiting = &wait;
+	rq->waiting = &wait;
+	rq->end_io = blk_end_sync_rq;
 	elv_add_request(q, rq, ELEVATOR_INSERT_BACK, 1);
 	generic_unplug_device(q);
-	wait_for_completion(rq->waiting);
+	wait_for_completion(&wait);
 	rq->waiting = NULL;
 
 	if (rq->errors)
@@ -2171,7 +2358,7 @@
 /*
  * queue lock must be held
  */
-void __blk_put_request(request_queue_t *q, struct request *req)
+static void __blk_put_request(request_queue_t *q, struct request *req)
 {
 	struct request_list *rl = req->rl;
 
@@ -2219,6 +2406,25 @@
 EXPORT_SYMBOL(blk_put_request);
 
 /**
+ * blk_end_sync_rq - executes a completion event on a request
+ * @rq: request to complete
+ */
+void blk_end_sync_rq(struct request *rq)
+{
+	struct completion *waiting = rq->waiting;
+
+	rq->waiting = NULL;
+	__blk_put_request(rq->q, rq);
+
+	/*
+	 * complete last, if this is a stack request the process (and thus
+	 * the rq pointer) could be invalid right after this complete()
+	 */
+	complete(waiting);
+}
+EXPORT_SYMBOL(blk_end_sync_rq);
+
+/**
  * blk_congestion_wait - wait for a queue to become uncongested
  * @rw: READ or WRITE
  * @timeout: timeout in jiffies
@@ -2371,7 +2577,7 @@
 	spin_lock_prefetch(q->queue_lock);
 
 	barrier = bio_barrier(bio);
-	if (barrier && !(q->queue_flags & (1 << QUEUE_FLAG_ORDERED))) {
+	if (barrier && (q->ordered == QUEUE_ORDERED_NONE)) {
 		err = -EOPNOTSUPP;
 		goto end_io;
 	}
@@ -2978,7 +3184,6 @@
 void end_that_request_last(struct request *req)
 {
 	struct gendisk *disk = req->rq_disk;
-	struct completion *waiting = req->waiting;
 
 	if (unlikely(laptop_mode) && blk_fs_request(req))
 		laptop_io_completion();
@@ -2998,10 +3203,10 @@
 		disk_round_stats(disk);
 		disk->in_flight--;
 	}
-	__blk_put_request(req->q, req);
-	/* Do this LAST! The structure may be freed immediately afterwards */
-	if (waiting)
-		complete(waiting);
+	if (req->end_io)
+		req->end_io(req);
+	else
+		__blk_put_request(req->q, req);
 }
 
 EXPORT_SYMBOL(end_that_request_last);
diff -Nru a/drivers/block/loop.c b/drivers/block/loop.c
--- a/drivers/block/loop.c	2005-03-11 12:51:47 -08:00
+++ b/drivers/block/loop.c	2005-03-11 12:51:47 -08:00
@@ -39,6 +39,11 @@
  * Support up to 256 loop devices
  * Heinz Mauelshagen <mge@sistina.com>, Feb 2002
  *
+ * Support for falling back on the write file operation when the address space
+ * operations prepare_write and/or commit_write are not available on the
+ * backing filesystem.
+ * Anton Altaparmakov, 16 Feb 2005
+ *
  * Still To Fix:
  * - Advisory locking is ignored here.
  * - Should use an own CAP_* category instead of CAP_SYS_ADMIN
@@ -67,6 +72,8 @@
 #include <linux/writeback.h>
 #include <linux/buffer_head.h>		/* for invalidate_bdev() */
 #include <linux/completion.h>
+#include <linux/highmem.h>
+#include <linux/gfp.h>
 
 #include <asm/uaccess.h>
 
@@ -127,7 +134,7 @@
 
 static int xor_init(struct loop_device *lo, const struct loop_info64 *info)
 {
-	if (info->lo_encrypt_key_size <= 0)
+	if (unlikely(info->lo_encrypt_key_size <= 0))
 		return -EINVAL;
 	return 0;
 }
@@ -173,7 +180,7 @@
 	loff_t size = get_loop_size(lo, lo->lo_backing_file);
 	sector_t x = (sector_t)size;
 
-	if ((loff_t)x != size)
+	if (unlikely((loff_t)x != size))
 		return -EFBIG;
 
 	set_capacity(disks[lo->lo_number], x);
@@ -186,23 +193,27 @@
 	       struct page *lpage, unsigned loffs,
 	       int size, sector_t rblock)
 {
-	if (!lo->transfer)
+	if (unlikely(!lo->transfer))
 		return 0;
 
 	return lo->transfer(lo, cmd, rpage, roffs, lpage, loffs, size, rblock);
 }
 
-static int
-do_lo_send(struct loop_device *lo, struct bio_vec *bvec, int bsize, loff_t pos)
+/**
+ * do_lo_send_aops - helper for writing data to a loop device
+ *
+ * This is the fast version for backing filesystems which implement the address
+ * space operations prepare_write and commit_write.
+ */
+static int do_lo_send_aops(struct loop_device *lo, struct bio_vec *bvec,
+		int bsize, loff_t pos, struct page *page)
 {
 	struct file *file = lo->lo_backing_file; /* kudos to NFsckingS */
 	struct address_space *mapping = file->f_mapping;
 	struct address_space_operations *aops = mapping->a_ops;
-	struct page *page;
 	pgoff_t index;
-	unsigned size, offset, bv_offs;
-	int len;
-	int ret = 0;
+	unsigned offset, bv_offs;
+	int len, ret = 0;
 
 	down(&mapping->host->i_sem);
 	index = pos >> PAGE_CACHE_SHIFT;
@@ -211,23 +222,22 @@
 	len = bvec->bv_len;
 	while (len > 0) {
 		sector_t IV;
+		unsigned size;
 		int transfer_result;
 
 		IV = ((sector_t)index << (PAGE_CACHE_SHIFT - 9))+(offset >> 9);
-
 		size = PAGE_CACHE_SIZE - offset;
 		if (size > len)
 			size = len;
-
 		page = grab_cache_page(mapping, index);
-		if (!page)
+		if (unlikely(!page))
 			goto fail;
-		if (aops->prepare_write(file, page, offset, offset+size))
+		if (unlikely(aops->prepare_write(file, page, offset,
+				offset + size)))
 			goto unlock;
 		transfer_result = lo_do_transfer(lo, WRITE, page, offset,
-						 bvec->bv_page, bv_offs,
-						 size, IV);
-		if (transfer_result) {
+				bvec->bv_page, bv_offs, size, IV);
+		if (unlikely(transfer_result)) {
 			char *kaddr;
 
 			/*
@@ -241,9 +251,10 @@
 			kunmap_atomic(kaddr, KM_USER0);
 		}
 		flush_dcache_page(page);
-		if (aops->commit_write(file, page, offset, offset+size))
+		if (unlikely(aops->commit_write(file, page, offset,
+				offset + size)))
 			goto unlock;
-		if (transfer_result)
+		if (unlikely(transfer_result))
 			goto unlock;
 		bv_offs += size;
 		len -= size;
@@ -253,32 +264,125 @@
 		unlock_page(page);
 		page_cache_release(page);
 	}
-	up(&mapping->host->i_sem);
 out:
+	up(&mapping->host->i_sem);
 	return ret;
-
 unlock:
 	unlock_page(page);
 	page_cache_release(page);
 fail:
-	up(&mapping->host->i_sem);
 	ret = -1;
 	goto out;
 }
 
-static int
-lo_send(struct loop_device *lo, struct bio *bio, int bsize, loff_t pos)
+/**
+ * __do_lo_send_write - helper for writing data to a loop device
+ *
+ * This helper just factors out common code between do_lo_send_direct_write()
+ * and do_lo_send_write().
+ */
+static inline int __do_lo_send_write(struct file *file,
+		u8 __user *buf, const int len, loff_t pos)
 {
+	ssize_t bw;
+	mm_segment_t old_fs = get_fs();
+
+	set_fs(get_ds());
+	bw = file->f_op->write(file, buf, len, &pos);
+	set_fs(old_fs);
+	if (likely(bw == len))
+		return 0;
+	printk(KERN_ERR "loop: Write error at byte offset %llu, length %i.\n",
+			(unsigned long long)pos, len);
+	if (bw >= 0)
+		bw = -EIO;
+	return bw;
+}
+
+/**
+ * do_lo_send_direct_write - helper for writing data to a loop device
+ *
+ * This is the fast, non-transforming version for backing filesystems which do
+ * not implement the address space operations prepare_write and commit_write.
+ * It uses the write file operation which should be present on all writeable
+ * filesystems.
+ */
+static int do_lo_send_direct_write(struct loop_device *lo,
+		struct bio_vec *bvec, int bsize, loff_t pos, struct page *page)
+{
+	ssize_t bw = __do_lo_send_write(lo->lo_backing_file,
+			(u8 __user *)kmap(bvec->bv_page) + bvec->bv_offset,
+			bvec->bv_len, pos);
+	kunmap(bvec->bv_page);
+	cond_resched();
+	return bw;
+}
+
+/**
+ * do_lo_send_write - helper for writing data to a loop device
+ *
+ * This is the slow, transforming version for filesystems which do not
+ * implement the address space operations prepare_write and commit_write.  It
+ * uses the write file operation which should be present on all writeable
+ * filesystems.
+ *
+ * Using fops->write is slower than using aops->{prepare,commit}_write in the
+ * transforming case because we need to double buffer the data as we cannot do
+ * the transformations in place as we do not have direct access to the
+ * destination pages of the backing file.
+ */
+static int do_lo_send_write(struct loop_device *lo, struct bio_vec *bvec,
+		int bsize, loff_t pos, struct page *page)
+{
+	int ret = lo_do_transfer(lo, WRITE, page, 0, bvec->bv_page,
+			bvec->bv_offset, bvec->bv_len, pos >> 9);
+	if (likely(!ret))
+		return __do_lo_send_write(lo->lo_backing_file,
+				(u8 __user *)page_address(page), bvec->bv_len,
+				pos);
+	printk(KERN_ERR "loop: Transfer error at byte offset %llu, "
+			"length %i.\n", (unsigned long long)pos, bvec->bv_len);
+	if (ret > 0)
+		ret = -EIO;
+	return ret;
+}
+
+static int lo_send(struct loop_device *lo, struct bio *bio, int bsize,
+		loff_t pos)
+{
+	int (*do_lo_send)(struct loop_device *, struct bio_vec *, int, loff_t,
+			struct page *page);
 	struct bio_vec *bvec;
+	struct page *page = NULL;
 	int i, ret = 0;
 
+	do_lo_send = do_lo_send_aops;
+	if (!(lo->lo_flags & LO_FLAGS_USE_AOPS)) {
+		do_lo_send = do_lo_send_direct_write;
+		if (lo->transfer != transfer_none) {
+			page = alloc_page(GFP_NOIO | __GFP_HIGHMEM);
+			if (unlikely(!page))
+				goto fail;
+			kmap(page);
+			do_lo_send = do_lo_send_write;
+		}
+	}
 	bio_for_each_segment(bvec, bio, i) {
-		ret = do_lo_send(lo, bvec, bsize, pos);
+		ret = do_lo_send(lo, bvec, bsize, pos, page);
 		if (ret < 0)
 			break;
 		pos += bvec->bv_len;
 	}
+	if (page) {
+		kunmap(page);
+		__free_page(page);
+	}
+out:
 	return ret;
+fail:
+	printk(KERN_ERR "loop: Failed to allocate temporary page for write.\n");
+	ret = -ENOMEM;
+	goto out;
 }
 
 struct lo_read_data {
@@ -584,7 +688,7 @@
 
 	/* the loop device has to be read-only */
 	error = -EINVAL;
-	if (lo->lo_flags != LO_FLAGS_READ_ONLY)
+	if (!(lo->lo_flags & LO_FLAGS_READ_ONLY))
 		goto out;
 
 	error = -EBADF;
@@ -683,8 +787,9 @@
 		 */
 		if (!file->f_op->sendfile)
 			goto out_putf;
-
-		if (!aops->prepare_write || !aops->commit_write)
+		if (aops->prepare_write && aops->commit_write)
+			lo_flags |= LO_FLAGS_USE_AOPS;
+		if (!(lo_flags & LO_FLAGS_USE_AOPS) && !file->f_op->write)
 			lo_flags |= LO_FLAGS_READ_ONLY;
 
 		lo_blocksize = inode->i_blksize;
diff -Nru a/drivers/block/paride/pd.c b/drivers/block/paride/pd.c
--- a/drivers/block/paride/pd.c	2005-03-11 12:51:52 -08:00
+++ b/drivers/block/paride/pd.c	2005-03-11 12:51:52 -08:00
@@ -743,6 +743,7 @@
 	rq.rq_disk = disk->gd;
 	rq.ref_count = 1;
 	rq.waiting = &wait;
+	rq.end_io = blk_end_sync_rq;
 	blk_insert_request(disk->gd->queue, &rq, 0, func, 0);
 	wait_for_completion(&wait);
 	rq.waiting = NULL;
diff -Nru a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c
--- a/drivers/block/pktcdvd.c	2005-03-11 12:51:40 -08:00
+++ b/drivers/block/pktcdvd.c	2005-03-11 12:51:40 -08:00
@@ -375,6 +375,7 @@
 	rq->ref_count++;
 	rq->flags |= REQ_NOMERGE;
 	rq->waiting = &wait;
+	rq->end_io = blk_end_sync_rq;
 	elv_add_request(q, rq, ELEVATOR_INSERT_BACK, 1);
 	generic_unplug_device(q);
 	wait_for_completion(&wait);
diff -Nru a/drivers/bluetooth/bfusb.c b/drivers/bluetooth/bfusb.c
--- a/drivers/bluetooth/bfusb.c	2005-03-11 12:51:47 -08:00
+++ b/drivers/bluetooth/bfusb.c	2005-03-11 12:51:47 -08:00
@@ -63,7 +63,7 @@
 
 #define BFUSB_MAX_BLOCK_SIZE	256
 
-#define BFUSB_BLOCK_TIMEOUT	(HZ * 3)
+#define BFUSB_BLOCK_TIMEOUT	3000
 
 #define BFUSB_TX_PROCESS	1
 #define BFUSB_TX_WAKEUP		2
@@ -582,7 +582,7 @@
 	pipe = usb_sndctrlpipe(bfusb->udev, 0);
 
 	if (usb_control_msg(bfusb->udev, pipe, USB_REQ_SET_CONFIGURATION,
-				0, 1, 0, NULL, 0, HZ * USB_CTRL_SET_TIMEOUT) < 0) {
+				0, 1, 0, NULL, 0, USB_CTRL_SET_TIMEOUT) < 0) {
 		BT_ERR("Can't change to loading configuration");
 		return -EBUSY;
 	}
@@ -623,7 +623,7 @@
 	pipe = usb_sndctrlpipe(bfusb->udev, 0);
 
         if ((err = usb_control_msg(bfusb->udev, pipe, USB_REQ_SET_CONFIGURATION,
-				0, 2, 0, NULL, 0, HZ * USB_CTRL_SET_TIMEOUT)) < 0) {
+				0, 2, 0, NULL, 0, USB_CTRL_SET_TIMEOUT)) < 0) {
 		BT_ERR("Can't change to running configuration");
 		goto error;
 	}
@@ -641,7 +641,7 @@
 	pipe = usb_sndctrlpipe(bfusb->udev, 0);
 
 	usb_control_msg(bfusb->udev, pipe, USB_REQ_SET_CONFIGURATION,
-				0, 0, 0, NULL, 0, HZ * USB_CTRL_SET_TIMEOUT);
+				0, 0, 0, NULL, 0, USB_CTRL_SET_TIMEOUT);
 
 	return err;
 }
diff -Nru a/drivers/bluetooth/bluecard_cs.c b/drivers/bluetooth/bluecard_cs.c
--- a/drivers/bluetooth/bluecard_cs.c	2005-03-11 12:51:46 -08:00
+++ b/drivers/bluetooth/bluecard_cs.c	2005-03-11 12:51:46 -08:00
@@ -35,6 +35,7 @@
 #include <linux/ioport.h>
 #include <linux/spinlock.h>
 #include <linux/moduleparam.h>
+#include <linux/wait.h>
 
 #include <linux/skbuff.h>
 #include <asm/io.h>
@@ -289,8 +290,9 @@
 		clear_bit(ready_bit, &(info->tx_state));
 
 		if (skb->pkt_type & 0x80) {
+			DECLARE_WAIT_QUEUE_HEAD(wq);
+			DEFINE_WAIT(wait);
 
-			wait_queue_head_t wait;
 			unsigned char baud_reg;
 
 			switch (skb->pkt_type) {
@@ -311,8 +313,9 @@
 			}
 
 			/* Wait until the command reaches the baseband */
-			init_waitqueue_head(&wait);
-			interruptible_sleep_on_timeout(&wait, HZ / 10);
+			prepare_to_wait(&wq, &wait, TASK_INTERRUPTIBLE);
+			schedule_timeout(HZ/10);
+			finish_wait(&wq, &wait);
 
 			/* Set baud on baseband */
 			info->ctrl_reg &= ~0x03;
@@ -324,8 +327,9 @@
 			outb(info->ctrl_reg, iobase + REG_CONTROL);
 
 			/* Wait before the next HCI packet can be send */
-			interruptible_sleep_on_timeout(&wait, HZ);
-
+			prepare_to_wait(&wq, &wait, TASK_INTERRUPTIBLE);
+			schedule_timeout(HZ);
+			finish_wait(&wq, &wait);
 		}
 
 		if (len == skb->len) {
diff -Nru a/drivers/bluetooth/hci_usb.c b/drivers/bluetooth/hci_usb.c
--- a/drivers/bluetooth/hci_usb.c	2005-03-11 12:51:51 -08:00
+++ b/drivers/bluetooth/hci_usb.c	2005-03-11 12:51:51 -08:00
@@ -888,7 +888,7 @@
 	isoc_ifnum = 1;
 
 #ifdef CONFIG_BT_HCIUSB_SCO
-	if (isoc && !(id->driver_info & HCI_BROKEN_ISOC))
+	if (isoc && !(id->driver_info & (HCI_BROKEN_ISOC | HCI_SNIFFER)))
 		isoc_iface = usb_ifnum_to_if(udev, isoc_ifnum);
 
 	if (isoc_iface) {
diff -Nru a/drivers/char/Kconfig b/drivers/char/Kconfig
--- a/drivers/char/Kconfig	2005-03-11 12:51:41 -08:00
+++ b/drivers/char/Kconfig	2005-03-11 12:51:41 -08:00
@@ -839,6 +839,10 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called sonypi.
 
+config TANBAC_TB0219
+	tristate "TANBAC TB0219 base board support"
+	depends TANBAC_TB0229
+
 
 menu "Ftape, the floppy tape device driver"
 
@@ -990,6 +994,8 @@
 	help
 	  The mmtimer device allows direct userspace access to the
 	  Altix system timer.
+
+source "drivers/char/tpm/Kconfig"
 
 endmenu
 
diff -Nru a/drivers/char/Makefile b/drivers/char/Makefile
--- a/drivers/char/Makefile	2005-03-11 12:51:51 -08:00
+++ b/drivers/char/Makefile	2005-03-11 12:51:51 -08:00
@@ -73,13 +73,13 @@
 obj-$(CONFIG_I8K) += i8k.o
 obj-$(CONFIG_DS1620) += ds1620.o
 obj-$(CONFIG_HW_RANDOM) += hw_random.o
-obj-$(CONFIG_QIC02_TAPE) += tpqic02.o
 obj-$(CONFIG_FTAPE) += ftape/
 obj-$(CONFIG_COBALT_LCD) += lcd.o
 obj-$(CONFIG_PPDEV) += ppdev.o
 obj-$(CONFIG_NWBUTTON) += nwbutton.o
 obj-$(CONFIG_NWFLASH) += nwflash.o
 obj-$(CONFIG_SCx200_GPIO) += scx200_gpio.o
+obj-$(CONFIG_TANBAC_TB0219) += tb0219.o
 
 obj-$(CONFIG_WATCHDOG)	+= watchdog/
 obj-$(CONFIG_MWAVE) += mwave/
@@ -89,7 +89,7 @@
 obj-$(CONFIG_IPMI_HANDLER) += ipmi/
 
 obj-$(CONFIG_HANGCHECK_TIMER) += hangcheck-timer.o
-
+obj-$(CONFIG_TCG_TPM) += tpm/
 # Files generated that shall be removed upon make clean
 clean-files := consolemap_deftbl.c defkeymap.c qtronixmap.c
 
diff -Nru a/drivers/char/agp/Kconfig b/drivers/char/agp/Kconfig
--- a/drivers/char/agp/Kconfig	2005-03-11 12:51:47 -08:00
+++ b/drivers/char/agp/Kconfig	2005-03-11 12:51:47 -08:00
@@ -1,6 +1,6 @@
 config AGP
 	tristate "/dev/agpgart (AGP Support)" if !GART_IOMMU
-	depends on ALPHA || IA64 || PPC32 || X86
+	depends on ALPHA || IA64 || PPC || X86
 	default y if GART_IOMMU
 	---help---
 	  AGP (Accelerated Graphics Port) is a bus system mainly used to
@@ -89,16 +89,6 @@
 	  use GLX or DRI, or if you have any Intel integrated graphics
 	  chipsets.  If unsure, say Y.
 
-config AGP_INTEL_MCH
-	tristate "Intel i865 chipset support"
-	depends on AGP && X86
-	help
-	  This option gives you AGP support for the GLX component of XFree86 4.x
-	  on Intel chipsets that support Intel EM64T processors.
-
-	  You should say Y here if you use XFree86 3.3.6 or 4.x and want to
-	  use GLX or DRI.  If unsure, say Y.
-
 config AGP_NVIDIA
 	tristate "NVIDIA nForce/nForce2 chipset support"
 	depends on AGP && X86 && !X86_64
@@ -156,11 +146,11 @@
 	default AGP
 
 config AGP_UNINORTH
-	tristate "Apple UniNorth AGP support"
+	tristate "Apple UniNorth & U3 AGP support"
 	depends on AGP && PPC_PMAC
 	help
 	  This option gives you AGP support for Apple machines with a
-	  UniNorth bridge.
+	  UniNorth or U3 (Apple G5) bridge.
 
 config AGP_EFFICEON
 	tristate "Transmeta Efficeon support"
diff -Nru a/drivers/char/agp/Makefile b/drivers/char/agp/Makefile
--- a/drivers/char/agp/Makefile	2005-03-11 12:51:42 -08:00
+++ b/drivers/char/agp/Makefile	2005-03-11 12:51:42 -08:00
@@ -9,7 +9,6 @@
 obj-$(CONFIG_AGP_EFFICEON)	+= efficeon-agp.o
 obj-$(CONFIG_AGP_HP_ZX1)	+= hp-agp.o
 obj-$(CONFIG_AGP_I460)		+= i460-agp.o
-obj-$(CONFIG_AGP_INTEL_MCH)		+= intel-mch-agp.o
 obj-$(CONFIG_AGP_INTEL)		+= intel-agp.o
 obj-$(CONFIG_AGP_NVIDIA)	+= nvidia-agp.o
 obj-$(CONFIG_AGP_SIS)		+= sis-agp.o
diff -Nru a/drivers/char/agp/agp.h b/drivers/char/agp/agp.h
--- a/drivers/char/agp/agp.h	2005-03-11 12:51:42 -08:00
+++ b/drivers/char/agp/agp.h	2005-03-11 12:51:42 -08:00
@@ -1,5 +1,6 @@
 /*
  * AGPGART
+ * Copyright (C) 2004 Silicon Graphics, Inc.
  * Copyright (C) 2002-2004 Dave Jones
  * Copyright (C) 1999 Jeff Hartmann
  * Copyright (C) 1999 Precision Insight, Inc.
@@ -100,18 +101,19 @@
 	struct gatt_mask *masks;
 	int (*fetch_size)(void);
 	int (*configure)(void);
-	void (*agp_enable)(u32);
+	void (*agp_enable)(struct agp_bridge_data *, u32);
 	void (*cleanup)(void);
 	void (*tlb_flush)(struct agp_memory *);
-	unsigned long (*mask_memory)(unsigned long, int);
+	unsigned long (*mask_memory)(struct agp_bridge_data *,
+		unsigned long, int);
 	void (*cache_flush)(void);
-	int (*create_gatt_table)(void);
-	int (*free_gatt_table)(void);
+	int (*create_gatt_table)(struct agp_bridge_data *);
+	int (*free_gatt_table)(struct agp_bridge_data *);
 	int (*insert_memory)(struct agp_memory *, off_t, int);
 	int (*remove_memory)(struct agp_memory *, off_t, int);
 	struct agp_memory *(*alloc_by_type) (size_t, int);
 	void (*free_by_type)(struct agp_memory *);
-	void *(*agp_alloc_page)(void);
+	void *(*agp_alloc_page)(struct agp_bridge_data *);
 	void (*agp_destroy_page)(void *);
 };
 
@@ -137,8 +139,10 @@
 	int max_memory_agp;	/* in number of pages */
 	int aperture_size_idx;
 	int capndx;
+	int flags;
 	char major_version;
 	char minor_version;
+	struct list_head list;
 };
 
 #define KB(x)	((x) * 1024)
@@ -243,24 +247,26 @@
 void agp_frontend_cleanup(void);
 
 /* Generic routines. */
-void agp_generic_enable(u32 mode);
-int agp_generic_create_gatt_table(void);
-int agp_generic_free_gatt_table(void);
+void agp_generic_enable(struct agp_bridge_data *bridge, u32 mode);
+int agp_generic_create_gatt_table(struct agp_bridge_data *bridge);
+int agp_generic_free_gatt_table(struct agp_bridge_data *bridge);
 struct agp_memory *agp_create_memory(int scratch_pages);
 int agp_generic_insert_memory(struct agp_memory *mem, off_t pg_start, int type);
 int agp_generic_remove_memory(struct agp_memory *mem, off_t pg_start, int type);
 struct agp_memory *agp_generic_alloc_by_type(size_t page_count, int type);
 void agp_generic_free_by_type(struct agp_memory *curr);
-void *agp_generic_alloc_page(void);
+void *agp_generic_alloc_page(struct agp_bridge_data *bridge);
 void agp_generic_destroy_page(void *addr);
 void agp_free_key(int key);
 int agp_num_entries(void);
-u32 agp_collect_device_status(u32 mode, u32 command);
+u32 agp_collect_device_status(struct agp_bridge_data *bridge, u32 mode, u32 command);
 void agp_device_command(u32 command, int agp_v3);
 int agp_3_5_enable(struct agp_bridge_data *bridge);
 void global_cache_flush(void);
 void get_agp_version(struct agp_bridge_data *bridge);
-unsigned long agp_generic_mask_memory(unsigned long addr, int type);
+unsigned long agp_generic_mask_memory(struct agp_bridge_data *bridge,
+	unsigned long addr, int type);
+struct agp_bridge_data *agp_generic_find_bridge(struct pci_dev *pdev);
 
 /* generic routines for agp>=3 */
 int agp3_generic_fetch_size(void);
@@ -314,5 +320,12 @@
 
 #define AGPCTRL_APERENB		(1<<8)
 #define AGPCTRL_GTLBEN		(1<<7)
+
+#define AGP2_RESERVED_MASK 0x00fffcc8
+#define AGP3_RESERVED_MASK 0x00ff00c4
+
+#define AGP_ERRATA_FASTWRITES 1<<0
+#define AGP_ERRATA_SBA	 1<<1
+#define AGP_ERRATA_1X 1<<2
 
 #endif	/* _AGP_BACKEND_PRIV_H */
diff -Nru a/drivers/char/agp/ali-agp.c b/drivers/char/agp/ali-agp.c
--- a/drivers/char/agp/ali-agp.c	2005-03-11 12:51:47 -08:00
+++ b/drivers/char/agp/ali-agp.c	2005-03-11 12:51:47 -08:00
@@ -139,9 +139,9 @@
 	}
 }
 
-static void *m1541_alloc_page(void)
+static void *m1541_alloc_page(struct agp_bridge_data *bridge)
 {
-	void *addr = agp_generic_alloc_page();
+	void *addr = agp_generic_alloc_page(agp_bridge);
 	u32 temp;
 
 	if (!addr)
@@ -398,7 +398,7 @@
 {
 	if (agp_off)
 		return -EINVAL;
-	return pci_module_init(&agp_ali_pci_driver);
+	return pci_register_driver(&agp_ali_pci_driver);
 }
 
 static void __exit agp_ali_cleanup(void)
diff -Nru a/drivers/char/agp/alpha-agp.c b/drivers/char/agp/alpha-agp.c
--- a/drivers/char/agp/alpha-agp.c	2005-03-11 12:51:47 -08:00
+++ b/drivers/char/agp/alpha-agp.c	2005-03-11 12:51:47 -08:00
@@ -76,11 +76,12 @@
 	alpha_mv.mv_pci_tbi(agp->hose, 0, -1);
 }
 
-static void alpha_core_agp_enable(u32 mode)
+static void alpha_core_agp_enable(struct agp_bridge_data *bridge, u32 mode)
 {
-	alpha_agp_info *agp = agp_bridge->dev_private_data;
+	alpha_agp_info *agp = bridge->dev_private_data;
 
-	agp->mode.lw = agp_collect_device_status(mode, agp->capability.lw);
+	agp->mode.lw = agp_collect_device_status(bridge, mode,
+					agp->capability.lw);
 
 	agp->mode.bits.enable = 1;
 	agp->ops->configure(agp);
diff -Nru a/drivers/char/agp/amd-k7-agp.c b/drivers/char/agp/amd-k7-agp.c
--- a/drivers/char/agp/amd-k7-agp.c	2005-03-11 12:51:52 -08:00
+++ b/drivers/char/agp/amd-k7-agp.c	2005-03-11 12:51:52 -08:00
@@ -132,7 +132,7 @@
 #define GET_GATT(addr) (amd_irongate_private.gatt_pages[\
 	GET_PAGE_DIR_IDX(addr)]->remapped)
 
-static int amd_create_gatt_table(void)
+static int amd_create_gatt_table(struct agp_bridge_data *bridge)
 {
 	struct aper_size_info_lvl2 *value;
 	struct amd_page_map page_dir;
@@ -175,7 +175,7 @@
 	return 0;
 }
 
-static int amd_free_gatt_table(void)
+static int amd_free_gatt_table(struct agp_bridge_data *bridge)
 {
 	struct amd_page_map page_dir;
 
@@ -314,7 +314,8 @@
 	for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
 		addr = (j * PAGE_SIZE) + agp_bridge->gart_bus_addr;
 		cur_gatt = GET_GATT(addr);
-		writel(agp_generic_mask_memory(mem->memory[i], mem->type), cur_gatt+GET_GATT_OFF(addr));
+		writel(agp_generic_mask_memory(agp_bridge,
+			mem->memory[i], mem->type), cur_gatt+GET_GATT_OFF(addr));
 		readl(cur_gatt+GET_GATT_OFF(addr));	/* PCI Posting. */
 	}
 	amd_irongate_tlbflush(mem);
@@ -421,6 +422,53 @@
 	bridge->dev = pdev;
 	bridge->capndx = cap_ptr;
 
+	/* 751 Errata (22564_B-1.PDF)
+	   erratum 20: strobe glitch with Nvidia NV10 GeForce cards.
+	   system controller may experience noise due to strong drive strengths
+	 */
+	if (agp_bridge->dev->device == PCI_DEVICE_ID_AMD_FE_GATE_7006) {
+		u8 cap_ptr=0;
+		struct pci_dev *gfxcard=NULL;
+		while (!cap_ptr) {
+			gfxcard = pci_get_class(PCI_CLASS_DISPLAY_VGA<<8, gfxcard);
+			if (!gfxcard) {
+				printk (KERN_INFO PFX "Couldn't find an AGP VGA controller.\n");
+				return -ENODEV;
+			}
+			cap_ptr = pci_find_capability(gfxcard, PCI_CAP_ID_AGP);
+			if (!cap_ptr) {
+				pci_dev_put(gfxcard);
+				continue;
+			}
+		}
+
+		/* With so many variants of NVidia cards, it's simpler just
+		   to blacklist them all, and then whitelist them as needed
+		   (if necessary at all). */
+		if (gfxcard->vendor == PCI_VENDOR_ID_NVIDIA) {
+			agp_bridge->flags |= AGP_ERRATA_1X;
+			printk (KERN_INFO PFX "AMD 751 chipset with NVidia GeForce detected. Forcing to 1X due to errata.\n");
+		}
+		pci_dev_put(gfxcard);
+	}
+
+	/* 761 Errata (23613_F.pdf)
+	 * Revisions B0/B1 were a disaster.
+	 * erratum 44: SYSCLK/AGPCLK skew causes 2X failures -- Force mode to 1X
+	 * erratum 45: Timing problem prevents fast writes -- Disable fast write.
+	 * erratum 46: Setup violation on AGP SBA pins - Disable side band addressing.
+	 * With this lot disabled, we should prevent lockups. */
+	if (agp_bridge->dev->device == PCI_DEVICE_ID_AMD_FE_GATE_700E) {
+		u8 revision=0;
+		pci_read_config_byte(pdev, PCI_REVISION_ID, &revision);
+		if (revision == 0x10 || revision == 0x11) {
+			agp_bridge->flags = AGP_ERRATA_FASTWRITES;
+			agp_bridge->flags |= AGP_ERRATA_SBA;
+			agp_bridge->flags |= AGP_ERRATA_1X;
+			printk (KERN_INFO PFX "AMD 761 chipset with errata detected - disabling AGP fast writes & SBA and forcing to 1X.\n");
+		}
+	}
+
 	/* Fill in the mode register */
 	pci_read_config_dword(pdev,
 			bridge->capndx+PCI_AGP_STATUS,
@@ -480,7 +528,7 @@
 {
 	if (agp_off)
 		return -EINVAL;
-	return pci_module_init(&agp_amdk7_pci_driver);
+	return pci_register_driver(&agp_amdk7_pci_driver);
 }
 
 static void __exit agp_amdk7_cleanup(void)
diff -Nru a/drivers/char/agp/amd64-agp.c b/drivers/char/agp/amd64-agp.c
--- a/drivers/char/agp/amd64-agp.c	2005-03-11 12:51:47 -08:00
+++ b/drivers/char/agp/amd64-agp.c	2005-03-11 12:51:47 -08:00
@@ -106,7 +106,8 @@
 	}
 
 	for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
-		tmp = agp_bridge->driver->mask_memory(mem->memory[i], mem->type);
+		tmp = agp_bridge->driver->mask_memory(agp_bridge,
+			mem->memory[i], mem->type);
 
 		BUG_ON(tmp & 0xffffff0000000ffcULL);
 		pte = (tmp & 0x000000ff00000000ULL) >> 28;
@@ -709,7 +710,7 @@
 
 	if (agp_off)
 		return -EINVAL;
-	if (pci_module_init(&agp_amd64_pci_driver) > 0) {
+	if (pci_register_driver(&agp_amd64_pci_driver) > 0) {
 		struct pci_dev *dev;
 		if (!agp_try_unsupported && !agp_try_unsupported_boot) {
 			printk(KERN_INFO PFX "No supported AGP bridge found.\n");
diff -Nru a/drivers/char/agp/ati-agp.c b/drivers/char/agp/ati-agp.c
--- a/drivers/char/agp/ati-agp.c	2005-03-11 12:51:47 -08:00
+++ b/drivers/char/agp/ati-agp.c	2005-03-11 12:51:47 -08:00
@@ -291,7 +291,8 @@
 	for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
 		addr = (j * PAGE_SIZE) + agp_bridge->gart_bus_addr;
 		cur_gatt = GET_GATT(addr);
-		writel(agp_bridge->driver->mask_memory(mem->memory[i], mem->type), cur_gatt+GET_GATT_OFF(addr));
+		writel(agp_bridge->driver->mask_memory(agp_bridge,
+			mem->memory[i], mem->type), cur_gatt+GET_GATT_OFF(addr));
 		readl(cur_gatt+GET_GATT_OFF(addr));	/* PCI Posting. */
 	}
 	agp_bridge->driver->tlb_flush(mem);
@@ -319,7 +320,7 @@
 	return 0;
 }
 
-static int ati_create_gatt_table(void)
+static int ati_create_gatt_table(struct agp_bridge_data *bridge)
 {
 	struct aper_size_info_lvl2 *value;
 	ati_page_map page_dir;
@@ -380,7 +381,7 @@
 	return 0;
 }
 
-static int ati_free_gatt_table(void)
+static int ati_free_gatt_table(struct agp_bridge_data *bridge)
 {
 	ati_page_map page_dir;
 
@@ -531,7 +532,7 @@
 {
 	if (agp_off)
 		return -EINVAL;
-	return pci_module_init(&agp_ati_pci_driver);
+	return pci_register_driver(&agp_ati_pci_driver);
 }
 
 static void __exit agp_ati_cleanup(void)
diff -Nru a/drivers/char/agp/backend.c b/drivers/char/agp/backend.c
--- a/drivers/char/agp/backend.c	2005-03-11 12:51:47 -08:00
+++ b/drivers/char/agp/backend.c	2005-03-11 12:51:47 -08:00
@@ -1,5 +1,6 @@
 /*
  * AGPGART driver backend routines.
+ * Copyright (C) 2004 Silicon Graphics, Inc.
  * Copyright (C) 2002-2003 Dave Jones.
  * Copyright (C) 1999 Jeff Hartmann.
  * Copyright (C) 1999 Precision Insight, Inc.
@@ -18,12 +19,12 @@
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * JEFF HARTMANN, DAVE JONES, OR ANY OTHER CONTRIBUTORS BE LIABLE FOR ANY CLAIM, 
- * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 
- * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE 
+ * JEFF HARTMANN, DAVE JONES, OR ANY OTHER CONTRIBUTORS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
  * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  *
- * TODO: 
+ * TODO:
  * - Allocate more than order 0 pages to avoid too much linear map splitting.
  */
 #include <linux/module.h>
@@ -42,34 +43,38 @@
  * fix some real stupidity. It's only by chance we can bump
  * past 0.99 at all due to some boolean logic error. */
 #define AGPGART_VERSION_MAJOR 0
-#define AGPGART_VERSION_MINOR 100
+#define AGPGART_VERSION_MINOR 101
 static struct agp_version agp_current_version =
 {
 	.major = AGPGART_VERSION_MAJOR,
 	.minor = AGPGART_VERSION_MINOR,
 };
 
-static int agp_count=0;
+struct agp_bridge_data *(*agp_find_bridge)(struct pci_dev *) =
+	&agp_generic_find_bridge;
 
-struct agp_bridge_data agp_bridge_dummy = { .type = NOT_SUPPORTED };
-struct agp_bridge_data *agp_bridge = &agp_bridge_dummy;
+struct agp_bridge_data *agp_bridge;
+LIST_HEAD(agp_bridges);
 EXPORT_SYMBOL(agp_bridge);
-
+EXPORT_SYMBOL(agp_bridges);
 
 /**
- *	agp_backend_acquire  -  attempt to acquire the agp backend.
+ *	agp_backend_acquire  -  attempt to acquire an agp backend.
  *
- *	returns -EBUSY if agp is in use,
- *	returns 0 if the caller owns the agp backend
  */
-int agp_backend_acquire(void)
+struct agp_bridge_data *agp_backend_acquire(struct pci_dev *pdev)
 {
-	if (agp_bridge->type == NOT_SUPPORTED)
-		return -EINVAL;
-	if (atomic_read(&agp_bridge->agp_in_use))
-		return -EBUSY;
-	atomic_inc(&agp_bridge->agp_in_use);
-	return 0;
+	struct agp_bridge_data *bridge;
+
+	bridge = agp_find_bridge(pdev);
+
+	if (!bridge)
+		return NULL;
+
+	if (atomic_read(&bridge->agp_in_use))
+		return NULL;
+	atomic_inc(&bridge->agp_in_use);
+	return bridge;
 }
 EXPORT_SYMBOL(agp_backend_acquire);
 
@@ -82,10 +87,11 @@
  *
  *	(Ensure that all memory it bound is unbound.)
  */
-void agp_backend_release(void)
+void agp_backend_release(struct agp_bridge_data *bridge)
 {
-	if (agp_bridge->type != NOT_SUPPORTED)
-		atomic_dec(&agp_bridge->agp_in_use);
+
+	if (bridge)
+		atomic_dec(&bridge->agp_in_use);
 }
 EXPORT_SYMBOL(agp_backend_release);
 
@@ -121,7 +127,6 @@
 	     (maxes_table[index].agp - maxes_table[index - 1].agp)) /
 	   (maxes_table[index].mem - maxes_table[index - 1].mem);
 
-	printk(KERN_INFO PFX "Maximum main memory to use for agp memory: %ldM\n", result);
 	result = result << (20 - PAGE_SHIFT);
 	return result;
 }
@@ -135,7 +140,7 @@
 	bridge->version = &agp_current_version;
 
 	if (bridge->driver->needs_scratch_page) {
-		void *addr = bridge->driver->agp_alloc_page();
+		void *addr = bridge->driver->agp_alloc_page(bridge);
 
 		if (!addr) {
 			printk(KERN_ERR PFX "unable to get memory for scratch page.\n");
@@ -144,7 +149,7 @@
 
 		bridge->scratch_page_real = virt_to_phys(addr);
 		bridge->scratch_page =
-		    bridge->driver->mask_memory(bridge->scratch_page_real, 0);
+		    bridge->driver->mask_memory(bridge, bridge->scratch_page_real, 0);
 	}
 
 	size_value = bridge->driver->fetch_size();
@@ -153,14 +158,14 @@
 		rc = -EINVAL;
 		goto err_out;
 	}
-	if (bridge->driver->create_gatt_table()) {
+	if (bridge->driver->create_gatt_table(bridge)) {
 		printk(KERN_ERR PFX
 		    "unable to get memory for graphics translation table.\n");
 		rc = -ENOMEM;
 		goto err_out;
 	}
 	got_gatt = 1;
-	
+
 	bridge->key_list = vmalloc(PAGE_SIZE * 4);
 	if (bridge->key_list == NULL) {
 		printk(KERN_ERR PFX "error allocating memory for key lists.\n");
@@ -168,7 +173,7 @@
 		goto err_out;
 	}
 	got_keylist = 1;
-	
+
 	/* FIXME vmalloc'd memory not guaranteed contiguous */
 	memset(bridge->key_list, 0, PAGE_SIZE * 4);
 
@@ -178,9 +183,6 @@
 		goto err_out;
 	}
 
-	printk(KERN_INFO PFX "AGP aperture is %dM @ 0x%lx\n",
-	       size_value, bridge->gart_bus_addr);
-
 	return 0;
 
 err_out:
@@ -188,7 +190,7 @@
 		bridge->driver->agp_destroy_page(
 				phys_to_virt(bridge->scratch_page_real));
 	if (got_gatt)
-		bridge->driver->free_gatt_table();
+		bridge->driver->free_gatt_table(bridge);
 	if (got_keylist) {
 		vfree(bridge->key_list);
 		bridge->key_list = NULL;
@@ -202,7 +204,7 @@
 	if (bridge->driver->cleanup)
 		bridge->driver->cleanup();
 	if (bridge->driver->free_gatt_table)
-		bridge->driver->free_gatt_table();
+		bridge->driver->free_gatt_table(bridge);
 	if (bridge->key_list) {
 		vfree(bridge->key_list);
 		bridge->key_list = NULL;
@@ -214,16 +216,35 @@
 				phys_to_virt(bridge->scratch_page_real));
 }
 
-/* XXX Kludge alert: agpgart isn't ready for multiple bridges yet */
+/* When we remove the global variable agp_bridge from all drivers
+ * then agp_alloc_bridge and agp_generic_find_bridge need to be updated
+ */
+
 struct agp_bridge_data *agp_alloc_bridge(void)
 {
-	return agp_bridge;
+	struct agp_bridge_data *bridge = kmalloc(sizeof(*bridge), GFP_KERNEL);
+
+	if (!bridge)
+		return NULL;
+
+	memset(bridge, 0, sizeof(*bridge));
+	atomic_set(&bridge->agp_in_use, 0);
+	atomic_set(&bridge->current_memory_agp, 0);
+
+	if (list_empty(&agp_bridges))
+		agp_bridge = bridge;
+
+	return bridge;
 }
 EXPORT_SYMBOL(agp_alloc_bridge);
 
 
 void agp_put_bridge(struct agp_bridge_data *bridge)
 {
+        kfree(bridge);
+
+        if (list_empty(&agp_bridges))
+                agp_bridge = NULL;
 }
 EXPORT_SYMBOL(agp_put_bridge);
 
@@ -240,40 +261,38 @@
 		return -EINVAL;
 	}
 
-	if (agp_count) {
-		printk (KERN_INFO PFX
-		       "Only one agpgart device currently supported.\n");
-		return -ENODEV;
-	}
-
 	/* Grab reference on the chipset driver. */
 	if (!try_module_get(bridge->driver->owner)) {
 		printk (KERN_INFO PFX "Couldn't lock chipset driver.\n");
 		return -EINVAL;
 	}
 
-	bridge->type = SUPPORTED;
-
-	error = agp_backend_initialize(agp_bridge);
+	error = agp_backend_initialize(bridge);
 	if (error) {
 		printk (KERN_INFO PFX "agp_backend_initialize() failed.\n");
 		goto err_out;
 	}
 
-	error = agp_frontend_initialize();
-	if (error) {
-		printk (KERN_INFO PFX "agp_frontend_initialize() failed.\n");
-		goto frontend_err;
+	if (list_empty(&agp_bridges)) {
+		error = agp_frontend_initialize();
+		if (error) {
+			printk (KERN_INFO PFX "agp_frontend_initialize() failed.\n");
+			goto frontend_err;
+		}
+
+		printk(KERN_INFO PFX "AGP aperture is %dM @ 0x%lx\n",
+			bridge->driver->fetch_size(), bridge->gart_bus_addr);
+
 	}
 
-	agp_count++;
+	list_add(&bridge->list, &agp_bridges);
 	return 0;
 
 frontend_err:
-	agp_backend_cleanup(agp_bridge);
+	agp_backend_cleanup(bridge);
 err_out:
-	bridge->type = NOT_SUPPORTED;
 	module_put(bridge->driver->owner);
+	agp_put_bridge(bridge);
 	return error;
 }
 EXPORT_SYMBOL_GPL(agp_add_bridge);
@@ -281,10 +300,10 @@
 
 void agp_remove_bridge(struct agp_bridge_data *bridge)
 {
-	bridge->type = NOT_SUPPORTED;
-	agp_frontend_cleanup();
 	agp_backend_cleanup(bridge);
-	agp_count--;
+	list_del(&bridge->list);
+	if (list_empty(&agp_bridges))
+		agp_frontend_cleanup();
 	module_put(bridge->driver->owner);
 }
 EXPORT_SYMBOL_GPL(agp_remove_bridge);
diff -Nru a/drivers/char/agp/efficeon-agp.c b/drivers/char/agp/efficeon-agp.c
--- a/drivers/char/agp/efficeon-agp.c	2005-03-11 12:51:40 -08:00
+++ b/drivers/char/agp/efficeon-agp.c	2005-03-11 12:51:40 -08:00
@@ -148,7 +148,7 @@
 	return 0;
 }
 
-static int efficeon_free_gatt_table(void)
+static int efficeon_free_gatt_table(struct agp_bridge_data *bridge)
 {
 	int index, freed = 0;
 
@@ -183,7 +183,7 @@
 #define GET_GATT(addr) (efficeon_private.gatt_pages[\
 	GET_PAGE_DIR_IDX(addr)]->remapped)
 
-static int efficeon_create_gatt_table(void)
+static int efficeon_create_gatt_table(struct agp_bridge_data *bridge)
 {
 	int index;
 	const int pati    = EFFICEON_PATI;
@@ -209,7 +209,7 @@
 
 		page = get_zeroed_page(GFP_KERNEL);
 		if (!page) {
-			efficeon_free_gatt_table();
+			efficeon_free_gatt_table(agp_bridge);
 			return -ENOMEM;
 		}
 		SetPageReserved(virt_to_page((char *)page));
@@ -448,7 +448,7 @@
 		return 0;
 	agp_initialised=1;
 
-	return pci_module_init(&agp_efficeon_pci_driver);
+	return pci_register_driver(&agp_efficeon_pci_driver);
 }
 
 static void __exit agp_efficeon_cleanup(void)
diff -Nru a/drivers/char/agp/frontend.c b/drivers/char/agp/frontend.c
--- a/drivers/char/agp/frontend.c	2005-03-11 12:51:41 -08:00
+++ b/drivers/char/agp/frontend.c	2005-03-11 12:51:41 -08:00
@@ -1,5 +1,6 @@
 /*
  * AGPGART driver frontend
+ * Copyright (C) 2004 Silicon Graphics, Inc.
  * Copyright (C) 2002-2003 Dave Jones
  * Copyright (C) 1999 Jeff Hartmann
  * Copyright (C) 1999 Precision Insight, Inc.
@@ -18,9 +19,9 @@
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * JEFF HARTMANN, OR ANY OTHER CONTRIBUTORS BE LIABLE FOR ANY CLAIM, 
- * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 
- * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE 
+ * JEFF HARTMANN, OR ANY OTHER CONTRIBUTORS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
  * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  *
  */
@@ -152,8 +153,8 @@
 
 /* Originally taken from linux/mm/mmap.c from the array
  * protection_map.
- * The original really should be exported to modules, or 
- * some routine which does the conversion for you 
+ * The original really should be exported to modules, or
+ * some routine which does the conversion for you
  */
 
 static const pgprot_t my_protect_map[16] =
@@ -285,8 +286,8 @@
 
 /* End - File flag list routines */
 
-/* 
- * Wrappers for agp_free_memory & agp_allocate_memory 
+/*
+ * Wrappers for agp_free_memory & agp_allocate_memory
  * These make sure that internal lists are kept updated.
  */
 static void agp_free_memory_wrap(struct agp_memory *memory)
@@ -299,7 +300,7 @@
 {
 	struct agp_memory *memory;
 
-	memory = agp_allocate_memory(pg_count, type);
+	memory = agp_allocate_memory(agp_bridge, pg_count, type);
 	if (memory == NULL)
 		return NULL;
 
@@ -420,7 +421,7 @@
 	if (agp_fe.current_controller == controller) {
 		agp_fe.current_controller = NULL;
 		agp_fe.backend_acquired = FALSE;
-		agp_backend_release();
+		agp_backend_release(agp_bridge);
 	}
 	kfree(controller);
 	return 0;
@@ -468,10 +469,10 @@
 
 	agp_fe.current_controller = NULL;
 	agp_fe.used_by_controller = FALSE;
-	agp_backend_release();
+	agp_backend_release(agp_bridge);
 }
 
-/* 
+/*
  * Routines for managing client lists -
  * These routines are for managing the list of auth'ed clients.
  */
@@ -605,7 +606,7 @@
 	if (!(test_bit(AGP_FF_IS_VALID, &priv->access_flags)))
 		goto out_eperm;
 
-	agp_copy_info(&kerninfo);
+	agp_copy_info(agp_bridge, &kerninfo);
 	size = vma->vm_end - vma->vm_start;
 	current_size = kerninfo.aper_size;
 	current_size = current_size * 0x100000;
@@ -757,7 +758,7 @@
 	struct agp_info userinfo;
 	struct agp_kern_info kerninfo;
 
-	agp_copy_info(&kerninfo);
+	agp_copy_info(agp_bridge, &kerninfo);
 
 	userinfo.version.major = kerninfo.version.major;
 	userinfo.version.minor = kerninfo.version.minor;
@@ -777,7 +778,6 @@
 
 static int agpioc_acquire_wrap(struct agp_file_private *priv)
 {
-	int ret;
 	struct agp_controller *controller;
 
 	DBG("");
@@ -788,11 +788,15 @@
 	if (agp_fe.current_controller != NULL)
 		return -EBUSY;
 
-	ret = agp_backend_acquire();
-	if (ret == 0)
-		agp_fe.backend_acquired = TRUE;
-	else
-		return ret;
+	if(!agp_bridge)
+		return -ENODEV;
+
+        if (atomic_read(&agp_bridge->agp_in_use))
+                return -EBUSY;
+
+	atomic_inc(&agp_bridge->agp_in_use);
+
+	agp_fe.backend_acquired = TRUE;
 
 	controller = agp_find_controller_by_pid(priv->my_pid);
 
@@ -803,7 +807,7 @@
 
 		if (controller == NULL) {
 			agp_fe.backend_acquired = FALSE;
-			agp_backend_release();
+			agp_backend_release(agp_bridge);
 			return -ENOMEM;
 		}
 		agp_insert_controller(controller);
@@ -830,7 +834,7 @@
 	if (copy_from_user(&mode, arg, sizeof(struct agp_setup)))
 		return -EFAULT;
 
-	agp_enable(mode.agp_mode);
+	agp_enable(agp_bridge, mode.agp_mode);
 	return 0;
 }
 
@@ -993,24 +997,24 @@
 	if ((agp_fe.current_controller == NULL) &&
 	    (cmd != AGPIOC_ACQUIRE)) {
 		ret_val = -EINVAL;
-	   	goto ioctl_out;
+		goto ioctl_out;
 	}
 	if ((agp_fe.backend_acquired != TRUE) &&
 	    (cmd != AGPIOC_ACQUIRE)) {
 		ret_val = -EBUSY;
-	   	goto ioctl_out;
+		goto ioctl_out;
 	}
 	if (cmd != AGPIOC_ACQUIRE) {
 		if (!(test_bit(AGP_FF_IS_CONTROLLER, &curr_priv->access_flags))) {
 			ret_val = -EPERM;
-		   	goto ioctl_out;
+			goto ioctl_out;
 		}
 		/* Use the original pid of the controller,
 		 * in case it's threaded */
 
 		if (agp_fe.current_controller->pid != curr_priv->my_pid) {
 			ret_val = -EBUSY;
-		   	goto ioctl_out;
+			goto ioctl_out;
 		}
 	}
 
@@ -1022,35 +1026,35 @@
 	case AGPIOC_ACQUIRE:
 		ret_val = agpioc_acquire_wrap(curr_priv);
 		break;
-	   	
+
 	case AGPIOC_RELEASE:
 		ret_val = agpioc_release_wrap(curr_priv);
 		break;
-	   	
+
 	case AGPIOC_SETUP:
 		ret_val = agpioc_setup_wrap(curr_priv, (void __user *) arg);
 		break;
-	   	
+
 	case AGPIOC_RESERVE:
 		ret_val = agpioc_reserve_wrap(curr_priv, (void __user *) arg);
 		break;
-	   	
+
 	case AGPIOC_PROTECT:
 		ret_val = agpioc_protect_wrap(curr_priv);
 		break;
-	  	
+
 	case AGPIOC_ALLOCATE:
 		ret_val = agpioc_allocate_wrap(curr_priv, (void __user *) arg);
 		break;
-	   	
+
 	case AGPIOC_DEALLOCATE:
 		ret_val = agpioc_deallocate_wrap(curr_priv, (int) arg);
 		break;
-	   	
+
 	case AGPIOC_BIND:
 		ret_val = agpioc_bind_wrap(curr_priv, (void __user *) arg);
 		break;
-	   	
+
 	case AGPIOC_UNBIND:
 		ret_val = agpioc_unbind_wrap(curr_priv, (void __user *) arg);
 		break;
diff -Nru a/drivers/char/agp/generic.c b/drivers/char/agp/generic.c
--- a/drivers/char/agp/generic.c	2005-03-11 12:51:42 -08:00
+++ b/drivers/char/agp/generic.c	2005-03-11 12:51:42 -08:00
@@ -1,6 +1,7 @@
 /*
  * AGPGART driver.
- * Copyright (C) 2002-2004 Dave Jones.
+ * Copyright (C) 2004 Silicon Graphics, Inc.
+ * Copyright (C) 2002-2005 Dave Jones.
  * Copyright (C) 1999 Jeff Hartmann.
  * Copyright (C) 1999 Precision Insight, Inc.
  * Copyright (C) 1999 Xi Graphics, Inc.
@@ -139,19 +140,19 @@
 {
 	size_t i;
 
-	if ((agp_bridge->type == NOT_SUPPORTED) || (curr == NULL))
+	if (curr == NULL)
 		return;
 
 	if (curr->is_bound == TRUE)
 		agp_unbind_memory(curr);
 
 	if (curr->type != 0) {
-		agp_bridge->driver->free_by_type(curr);
+		curr->bridge->driver->free_by_type(curr);
 		return;
 	}
 	if (curr->page_count != 0) {
 		for (i = 0; i < curr->page_count; i++) {
-			agp_bridge->driver->agp_destroy_page(phys_to_virt(curr->memory[i]));
+			curr->bridge->driver->agp_destroy_page(phys_to_virt(curr->memory[i]));
 		}
 	}
 	agp_free_key(curr->key);
@@ -173,20 +174,23 @@
  *
  *	It returns NULL whenever memory is unavailable.
  */
-struct agp_memory *agp_allocate_memory(size_t page_count, u32 type)
+struct agp_memory *agp_allocate_memory(struct agp_bridge_data *bridge,
+					size_t page_count, u32 type)
 {
 	int scratch_pages;
 	struct agp_memory *new;
 	size_t i;
 
-	if (agp_bridge->type == NOT_SUPPORTED)
+	if (!bridge)
 		return NULL;
 
-	if ((atomic_read(&agp_bridge->current_memory_agp) + page_count) > agp_bridge->max_memory_agp)
+	if ((atomic_read(&bridge->current_memory_agp) + page_count) > bridge->max_memory_agp)
 		return NULL;
 
 	if (type != 0) {
-		new = agp_bridge->driver->alloc_by_type(page_count, type);
+		new = bridge->driver->alloc_by_type(page_count, type);
+		if (new)
+			new->bridge = bridge;
 		return new;
 	}
 
@@ -198,7 +202,7 @@
 		return NULL;
 
 	for (i = 0; i < page_count; i++) {
-		void *addr = agp_bridge->driver->agp_alloc_page();
+		void *addr = bridge->driver->agp_alloc_page(bridge);
 
 		if (addr == NULL) {
 			agp_free_memory(new);
@@ -207,6 +211,7 @@
 		new->memory[i] = virt_to_phys(addr);
 		new->page_count++;
 	}
+       new->bridge = bridge;
 
 	flush_agp_mappings();
 
@@ -289,6 +294,19 @@
 EXPORT_SYMBOL_GPL(agp_num_entries);
 
 
+static int check_bridge_mode(struct pci_dev *dev)
+{
+	u32 agp3;
+	u8 cap_ptr;
+
+	cap_ptr = pci_find_capability(dev, PCI_CAP_ID_AGP);
+	pci_read_config_dword(dev, cap_ptr+AGPSTAT, &agp3);
+	if (agp3 & AGPSTAT_MODE_3_0)
+		return 1;
+	return 0;
+}
+
+
 /**
  *	agp_copy_info  -  copy bridge state information
  *
@@ -297,35 +315,36 @@
  *	This function copies information about the agp bridge device and the state of
  *	the agp backend into an agp_kern_info pointer.
  */
-int agp_copy_info(struct agp_kern_info *info)
+int agp_copy_info(struct agp_bridge_data *bridge, struct agp_kern_info *info)
 {
 	memset(info, 0, sizeof(struct agp_kern_info));
-	if (!agp_bridge || agp_bridge->type == NOT_SUPPORTED ||
-	    !agp_bridge->version) {
+	if (!bridge) {
 		info->chipset = NOT_SUPPORTED;
 		return -EIO;
 	}
 
-	info->version.major = agp_bridge->version->major;
-	info->version.minor = agp_bridge->version->minor;
-	info->chipset = agp_bridge->type;
-	info->device = agp_bridge->dev;
-	info->mode = agp_bridge->mode;
-	info->aper_base = agp_bridge->gart_bus_addr;
+	info->version.major = bridge->version->major;
+	info->version.minor = bridge->version->minor;
+	info->chipset = SUPPORTED;
+	info->device = bridge->dev;
+	if (check_bridge_mode(bridge->dev))
+		info->mode = bridge->mode & ~AGP3_RESERVED_MASK;
+	else
+		info->mode = bridge->mode & ~AGP2_RESERVED_MASK;
+	info->mode = bridge->mode;
+	info->aper_base = bridge->gart_bus_addr;
 	info->aper_size = agp_return_size();
-	info->max_memory = agp_bridge->max_memory_agp;
-	info->current_memory = atomic_read(&agp_bridge->current_memory_agp);
-	info->cant_use_aperture = agp_bridge->driver->cant_use_aperture;
-	info->vm_ops = agp_bridge->vm_ops;
+	info->max_memory = bridge->max_memory_agp;
+	info->current_memory = atomic_read(&bridge->current_memory_agp);
+	info->cant_use_aperture = bridge->driver->cant_use_aperture;
+	info->vm_ops = bridge->vm_ops;
 	info->page_mask = ~0UL;
 	return 0;
 }
 EXPORT_SYMBOL(agp_copy_info);
 
-
 /* End - Routine to copy over information structure */
 
-
 /*
  * Routines for handling swapping of agp_memory into the GATT -
  * These routines take agp_memory and insert them into the GATT.
@@ -345,7 +364,7 @@
 {
 	int ret_val;
 
-	if ((agp_bridge->type == NOT_SUPPORTED) || (curr == NULL))
+	if (curr == NULL)
 		return -EINVAL;
 
 	if (curr->is_bound == TRUE) {
@@ -353,10 +372,10 @@
 		return -EINVAL;
 	}
 	if (curr->is_flushed == FALSE) {
-		agp_bridge->driver->cache_flush();
+		curr->bridge->driver->cache_flush();
 		curr->is_flushed = TRUE;
 	}
-	ret_val = agp_bridge->driver->insert_memory(curr, pg_start, curr->type);
+	ret_val = curr->bridge->driver->insert_memory(curr, pg_start, curr->type);
 
 	if (ret_val != 0)
 		return ret_val;
@@ -380,7 +399,7 @@
 {
 	int ret_val;
 
-	if ((agp_bridge->type == NOT_SUPPORTED) || (curr == NULL))
+	if (curr == NULL)
 		return -EINVAL;
 
 	if (curr->is_bound != TRUE) {
@@ -388,7 +407,7 @@
 		return -EINVAL;
 	}
 
-	ret_val = agp_bridge->driver->remove_memory(curr, curr->pg_start, curr->type);
+	ret_val = curr->bridge->driver->remove_memory(curr, curr->pg_start, curr->type);
 
 	if (ret_val != 0)
 		return ret_val;
@@ -403,71 +422,133 @@
 
 
 /* Generic Agp routines - Start */
-static void agp_v2_parse_one(u32 *mode, u32 *cmd, u32 *tmp)
+static void agp_v2_parse_one(u32 *requested_mode, u32 *bridge_agpstat, u32 *vga_agpstat)
 {
+	u32 tmp;
+
+	if (*requested_mode & AGP2_RESERVED_MASK) {
+		printk (KERN_INFO PFX "reserved bits set in mode 0x%x. Fixed.\n", *requested_mode);
+		*requested_mode &= ~AGP2_RESERVED_MASK;
+	}
+
+	/* Check the speed bits make sense. Only one should be set. */
+	tmp = *requested_mode & 7;
+	switch (tmp) {
+		case 0:
+			printk (KERN_INFO PFX "%s tried to set rate=x0. Setting to x1 mode.\n", current->comm);
+			*requested_mode |= AGPSTAT2_1X;
+			break;
+		case 1:
+		case 2:
+			break;
+		case 3:
+			*requested_mode &= ~(AGPSTAT2_1X);	/* rate=2 */
+			break;
+		case 4:
+			break;
+		case 5:
+		case 6:
+		case 7:
+			*requested_mode &= ~(AGPSTAT2_1X|AGPSTAT2_2X); /* rate=4*/
+			break;
+	}
+
 	/* disable SBA if it's not supported */
-	if (!((*cmd & AGPSTAT_SBA) && (*tmp & AGPSTAT_SBA) && (*mode & AGPSTAT_SBA)))
-		*cmd &= ~AGPSTAT_SBA;
+	if (!((*bridge_agpstat & AGPSTAT_SBA) && (*vga_agpstat & AGPSTAT_SBA) && (*requested_mode & AGPSTAT_SBA)))
+		*bridge_agpstat &= ~AGPSTAT_SBA;
 
-	/* Set speed */
-	if (!((*cmd & AGPSTAT2_4X) && (*tmp & AGPSTAT2_4X) && (*mode & AGPSTAT2_4X)))
-		*cmd &= ~AGPSTAT2_4X;
+	/* Set rate */
+	if (!((*bridge_agpstat & AGPSTAT2_4X) && (*vga_agpstat & AGPSTAT2_4X) && (*requested_mode & AGPSTAT2_4X)))
+		*bridge_agpstat &= ~AGPSTAT2_4X;
 
-	if (!((*cmd & AGPSTAT2_2X) && (*tmp & AGPSTAT2_2X) && (*mode & AGPSTAT2_2X)))
-		*cmd &= ~AGPSTAT2_2X;
+	if (!((*bridge_agpstat & AGPSTAT2_2X) && (*vga_agpstat & AGPSTAT2_2X) && (*requested_mode & AGPSTAT2_2X)))
+		*bridge_agpstat &= ~AGPSTAT2_2X;
 
-	if (!((*cmd & AGPSTAT2_1X) && (*tmp & AGPSTAT2_1X) && (*mode & AGPSTAT2_1X)))
-		*cmd &= ~AGPSTAT2_1X;
+	if (!((*bridge_agpstat & AGPSTAT2_1X) && (*vga_agpstat & AGPSTAT2_1X) && (*requested_mode & AGPSTAT2_1X)))
+		*bridge_agpstat &= ~AGPSTAT2_1X;
 
 	/* Now we know what mode it should be, clear out the unwanted bits. */
-	if (*cmd & AGPSTAT2_4X)
-		*cmd &= ~(AGPSTAT2_1X | AGPSTAT2_2X);	/* 4X */
+	if (*bridge_agpstat & AGPSTAT2_4X)
+		*bridge_agpstat &= ~(AGPSTAT2_1X | AGPSTAT2_2X);	/* 4X */
+
+	if (*bridge_agpstat & AGPSTAT2_2X)
+		*bridge_agpstat &= ~(AGPSTAT2_1X | AGPSTAT2_4X);	/* 2X */
+
+	if (*bridge_agpstat & AGPSTAT2_1X)
+		*bridge_agpstat &= ~(AGPSTAT2_2X | AGPSTAT2_4X);	/* 1X */
+
+	/* Apply any errata. */
+	if (agp_bridge->flags & AGP_ERRATA_FASTWRITES)
+		*bridge_agpstat &= ~AGPSTAT_FW;
 
-	if (*cmd & AGPSTAT2_2X)
-		*cmd &= ~(AGPSTAT2_1X | AGPSTAT2_4X);	/* 2X */
+	if (agp_bridge->flags & AGP_ERRATA_SBA)
+		*bridge_agpstat &= ~AGPSTAT_SBA;
 
-	if (*cmd & AGPSTAT2_1X)
-		*cmd &= ~(AGPSTAT2_2X | AGPSTAT2_4X);	/* 1X */
+	if (agp_bridge->flags & AGP_ERRATA_1X) {
+		*bridge_agpstat &= ~(AGPSTAT2_2X | AGPSTAT2_4X);
+		*bridge_agpstat |= AGPSTAT2_1X;
+	}
+
+	/* If we've dropped down to 1X, disable fast writes. */
+	if (*bridge_agpstat & AGPSTAT2_1X)
+		*bridge_agpstat &= ~AGPSTAT_FW;
 }
 
 /*
- * mode = requested mode.
- * cmd = PCI_AGP_STATUS from agp bridge.
- * tmp = PCI_AGP_STATUS from graphic card.
+ * requested_mode = Mode requested by (typically) X.
+ * bridge_agpstat = PCI_AGP_STATUS from agp bridge.
+ * vga_agpstat = PCI_AGP_STATUS from graphic card.
  */
-static void agp_v3_parse_one(u32 *mode, u32 *cmd, u32 *tmp)
+static void agp_v3_parse_one(u32 *requested_mode, u32 *bridge_agpstat, u32 *vga_agpstat)
 {
-	u32 origcmd=*cmd, origtmp=*tmp;
+	u32 origbridge=*bridge_agpstat, origvga=*vga_agpstat;
+	u32 tmp;
+
+	if (*requested_mode & AGP3_RESERVED_MASK) {
+		printk (KERN_INFO PFX "reserved bits set in mode 0x%x. Fixed.\n", *requested_mode);
+		*requested_mode &= ~AGP3_RESERVED_MASK;
+	}
+
+	/* Check the speed bits make sense. */
+	tmp = *requested_mode & 7;
+	if (tmp == 0) {
+		printk (KERN_INFO PFX "%s tried to set rate=x0. Setting to AGP3 x4 mode.\n", current->comm);
+		*requested_mode |= AGPSTAT3_4X;
+	}
+	if (tmp >= 3) {
+		printk (KERN_INFO PFX "%s tried to set rate=x%d. Setting to AGP3 x8 mode.\n", current->comm, tmp * 4);
+		*requested_mode = (*requested_mode & ~7) | AGPSTAT3_8X;
+	}
 
 	/* ARQSZ - Set the value to the maximum one.
 	 * Don't allow the mode register to override values. */
-	*cmd = ((*cmd & ~AGPSTAT_ARQSZ) |
-		max_t(u32,(*cmd & AGPSTAT_ARQSZ),(*tmp & AGPSTAT_ARQSZ)));
+	*bridge_agpstat = ((*bridge_agpstat & ~AGPSTAT_ARQSZ) |
+		max_t(u32,(*bridge_agpstat & AGPSTAT_ARQSZ),(*vga_agpstat & AGPSTAT_ARQSZ)));
 
 	/* Calibration cycle.
 	 * Don't allow the mode register to override values. */
-	*cmd = ((*cmd & ~AGPSTAT_CAL_MASK) |
-		min_t(u32,(*cmd & AGPSTAT_CAL_MASK),(*tmp & AGPSTAT_CAL_MASK)));
+	*bridge_agpstat = ((*bridge_agpstat & ~AGPSTAT_CAL_MASK) |
+		min_t(u32,(*bridge_agpstat & AGPSTAT_CAL_MASK),(*vga_agpstat & AGPSTAT_CAL_MASK)));
 
 	/* SBA *must* be supported for AGP v3 */
-	*cmd |= AGPSTAT_SBA;
+	*bridge_agpstat |= AGPSTAT_SBA;
 
 	/*
 	 * Set speed.
 	 * Check for invalid speeds. This can happen when applications
 	 * written before the AGP 3.0 standard pass AGP2.x modes to AGP3 hardware
 	 */
-	if (*mode & AGPSTAT_MODE_3_0) {
+	if (*requested_mode & AGPSTAT_MODE_3_0) {
 		/*
-		 * Caller hasn't a clue what its doing. We are in 3.0 mode,
+		 * Caller hasn't a clue what it is doing. Bridge is in 3.0 mode,
 		 * have been passed a 3.0 mode, but with 2.x speed bits set.
 		 * AGP2.x 4x -> AGP3.0 4x.
 		 */
-		if (*mode & AGPSTAT2_4X) {
+		if (*requested_mode & AGPSTAT2_4X) {
 			printk (KERN_INFO PFX "%s passes broken AGP3 flags (%x). Fixed.\n",
-						current->comm, *mode);
-			*mode &= ~AGPSTAT2_4X;
-			*mode |= AGPSTAT3_4X;
+						current->comm, *requested_mode);
+			*requested_mode &= ~AGPSTAT2_4X;
+			*requested_mode |= AGPSTAT3_4X;
 		}
 	} else {
 		/*
@@ -476,27 +557,27 @@
 		 * Convert AGP 1x,2x,4x -> AGP 3.0 4x.
 		 */
 		printk (KERN_INFO PFX "%s passes broken AGP2 flags (%x) in AGP3 mode. Fixed.\n",
-					current->comm, *mode);
-		*mode &= ~(AGPSTAT2_4X | AGPSTAT2_2X | AGPSTAT2_1X);
-		*mode |= AGPSTAT3_4X;
+					current->comm, *requested_mode);
+		*requested_mode &= ~(AGPSTAT2_4X | AGPSTAT2_2X | AGPSTAT2_1X);
+		*requested_mode |= AGPSTAT3_4X;
 	}
 
-	if (*mode & AGPSTAT3_8X) {
-		if (!(*cmd & AGPSTAT3_8X)) {
-			*cmd &= ~(AGPSTAT3_8X | AGPSTAT3_RSVD);
-			*cmd |= AGPSTAT3_4X;
+	if (*requested_mode & AGPSTAT3_8X) {
+		if (!(*bridge_agpstat & AGPSTAT3_8X)) {
+			*bridge_agpstat &= ~(AGPSTAT3_8X | AGPSTAT3_RSVD);
+			*bridge_agpstat |= AGPSTAT3_4X;
 			printk ("%s requested AGPx8 but bridge not capable.\n", current->comm);
 			return;
 		}
-		if (!(*tmp & AGPSTAT3_8X)) {
-			*cmd &= ~(AGPSTAT3_8X | AGPSTAT3_RSVD);
-			*cmd |= AGPSTAT3_4X;
+		if (!(*vga_agpstat & AGPSTAT3_8X)) {
+			*bridge_agpstat &= ~(AGPSTAT3_8X | AGPSTAT3_RSVD);
+			*bridge_agpstat |= AGPSTAT3_4X;
 			printk ("%s requested AGPx8 but graphic card not capable.\n", current->comm);
 			return;
 		}
 		/* All set, bridge & device can do AGP x8*/
-		*cmd &= ~(AGPSTAT3_4X | AGPSTAT3_RSVD);
-		return;
+		*bridge_agpstat &= ~(AGPSTAT3_4X | AGPSTAT3_RSVD);
+		goto done;
 
 	} else {
 
@@ -505,71 +586,97 @@
 		 * If the hardware can't do x4, we're up shit creek, and never
 		 *  should have got this far.
 		 */
-		*cmd &= ~(AGPSTAT3_8X | AGPSTAT3_RSVD);
-		if ((*cmd & AGPSTAT3_4X) && (*tmp & AGPSTAT3_4X))
-			*cmd |= AGPSTAT3_4X;
+		*bridge_agpstat &= ~(AGPSTAT3_8X | AGPSTAT3_RSVD);
+		if ((*bridge_agpstat & AGPSTAT3_4X) && (*vga_agpstat & AGPSTAT3_4X))
+			*bridge_agpstat |= AGPSTAT3_4X;
 		else {
 			printk (KERN_INFO PFX "Badness. Don't know which AGP mode to set. "
-							"[cmd:%x tmp:%x fell back to:- cmd:%x tmp:%x]\n",
-							origcmd, origtmp, *cmd, *tmp);
-			if (!(*cmd & AGPSTAT3_4X))
+							"[bridge_agpstat:%x vga_agpstat:%x fell back to:- bridge_agpstat:%x vga_agpstat:%x]\n",
+							origbridge, origvga, *bridge_agpstat, *vga_agpstat);
+			if (!(*bridge_agpstat & AGPSTAT3_4X))
 				printk (KERN_INFO PFX "Bridge couldn't do AGP x4.\n");
-			if (!(*tmp & AGPSTAT3_4X))
+			if (!(*vga_agpstat & AGPSTAT3_4X))
 				printk (KERN_INFO PFX "Graphic card couldn't do AGP x4.\n");
+			return;
 		}
 	}
+
+done:
+	/* Apply any errata. */
+	if (agp_bridge->flags & AGP_ERRATA_FASTWRITES)
+		*bridge_agpstat &= ~AGPSTAT_FW;
+
+	if (agp_bridge->flags & AGP_ERRATA_SBA)
+		*bridge_agpstat &= ~AGPSTAT_SBA;
+
+	if (agp_bridge->flags & AGP_ERRATA_1X) {
+		*bridge_agpstat &= ~(AGPSTAT2_2X | AGPSTAT2_4X);
+		*bridge_agpstat |= AGPSTAT2_1X;
+	}
 }
 
-//FIXME: This doesn't smell right.
-//We need a function we pass an agp_device to.
-u32 agp_collect_device_status(u32 mode, u32 cmd)
+
+/**
+ * agp_collect_device_status - determine correct agp_cmd from various agp_stat's
+ * @bridge: an agp_bridge_data struct allocated for the AGP host bridge.
+ * @requested_mode: requested agp_stat from userspace (Typically from X)
+ * @bridge_agpstat: current agp_stat from AGP bridge.
+ *
+ * This function will hunt for an AGP graphics card, and try to match
+ * the requested mode to the capabilities of both the bridge and the card.
+ */
+u32 agp_collect_device_status(struct agp_bridge_data *bridge, u32 requested_mode, u32 bridge_agpstat)
 {
 	struct pci_dev *device = NULL;
+	u32 vga_agpstat;
 	u8 cap_ptr;
-	u32 tmp;
-	u32 agp3;
 
-	for_each_pci_dev(device) {
+	for (;;) {
+		device = pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, device);
+		if (!device) {
+			printk (KERN_INFO PFX "Couldn't find an AGP VGA controller.\n");
+			return 0;
+		}
 		cap_ptr = pci_find_capability(device, PCI_CAP_ID_AGP);
-		if (!cap_ptr)
-			continue;
+		if (cap_ptr)
+			break;
+	}
 
-		//FIXME: We should probably skip anything here that
-		// isn't an AGP graphic card.
-		/*
-		 * Ok, here we have a AGP device. Disable impossible
-		 * settings, and adjust the readqueue to the minimum.
-		 */
-		pci_read_config_dword(device, cap_ptr+PCI_AGP_STATUS, &tmp);
+	/*
+	 * Ok, here we have a AGP device. Disable impossible
+	 * settings, and adjust the readqueue to the minimum.
+	 */
+	pci_read_config_dword(device, cap_ptr+PCI_AGP_STATUS, &vga_agpstat);
 
-		/* adjust RQ depth */
-		cmd = ((cmd & ~AGPSTAT_RQ_DEPTH) |
-		     min_t(u32, (mode & AGPSTAT_RQ_DEPTH),
-			 min_t(u32, (cmd & AGPSTAT_RQ_DEPTH), (tmp & AGPSTAT_RQ_DEPTH))));
-
-		/* disable FW if it's not supported */
-		if (!((cmd & AGPSTAT_FW) && (tmp & AGPSTAT_FW) && (mode & AGPSTAT_FW)))
-			cmd &= ~AGPSTAT_FW;
-
-		/* Check to see if we are operating in 3.0 mode */
-		pci_read_config_dword(device, cap_ptr+AGPSTAT, &agp3);
-		if (agp3 & AGPSTAT_MODE_3_0) {
-			agp_v3_parse_one(&mode, &cmd, &tmp);
-		} else {
-			agp_v2_parse_one(&mode, &cmd, &tmp);
-		}
-	}
-	return cmd;
+	/* adjust RQ depth */
+	bridge_agpstat = ((bridge_agpstat & ~AGPSTAT_RQ_DEPTH) |
+	     min_t(u32, (requested_mode & AGPSTAT_RQ_DEPTH),
+		 min_t(u32, (bridge_agpstat & AGPSTAT_RQ_DEPTH), (vga_agpstat & AGPSTAT_RQ_DEPTH))));
+
+	/* disable FW if it's not supported */
+	if (!((bridge_agpstat & AGPSTAT_FW) &&
+		 (vga_agpstat & AGPSTAT_FW) &&
+		 (requested_mode & AGPSTAT_FW)))
+		bridge_agpstat &= ~AGPSTAT_FW;
+
+	/* Check to see if we are operating in 3.0 mode */
+	if (check_bridge_mode(agp_bridge->dev))
+		agp_v3_parse_one(&requested_mode, &bridge_agpstat, &vga_agpstat);
+	else
+		agp_v2_parse_one(&requested_mode, &bridge_agpstat, &vga_agpstat);
+
+	pci_dev_put(device);
+	return bridge_agpstat;
 }
 EXPORT_SYMBOL(agp_collect_device_status);
 
 
-void agp_device_command(u32 command, int agp_v3)
+void agp_device_command(u32 bridge_agpstat, int agp_v3)
 {
 	struct pci_dev *device = NULL;
 	int mode;
 
-	mode = command & 0x7;
+	mode = bridge_agpstat & 0x7;
 	if (agp_v3)
 		mode *= 4;
 
@@ -580,7 +687,7 @@
 
 		printk(KERN_INFO PFX "Putting AGP V%d device at %s into %dx mode\n",
 				agp_v3 ? 3 : 2, pci_name(device), mode);
-		pci_write_config_dword(device, agp + PCI_AGP_COMMAND, command);
+		pci_write_config_dword(device, agp + PCI_AGP_COMMAND, bridge_agpstat);
 	}
 }
 EXPORT_SYMBOL(agp_device_command);
@@ -591,52 +698,53 @@
 	u32 ncapid;
 
 	/* Exit early if already set by errata workarounds. */
-	if (agp_bridge->major_version != 0)
+	if (bridge->major_version != 0)
 		return;
 
-	pci_read_config_dword(agp_bridge->dev, agp_bridge->capndx, &ncapid);
-	agp_bridge->major_version = (ncapid >> AGP_MAJOR_VERSION_SHIFT) & 0xf;
-	agp_bridge->minor_version = (ncapid >> AGP_MINOR_VERSION_SHIFT) & 0xf;
+	pci_read_config_dword(bridge->dev, bridge->capndx, &ncapid);
+	bridge->major_version = (ncapid >> AGP_MAJOR_VERSION_SHIFT) & 0xf;
+	bridge->minor_version = (ncapid >> AGP_MINOR_VERSION_SHIFT) & 0xf;
 }
 EXPORT_SYMBOL(get_agp_version);
 
 
-void agp_generic_enable(u32 mode)
+void agp_generic_enable(struct agp_bridge_data *bridge, u32 requested_mode)
 {
-	u32 command, temp;
-	u32 agp3;
+	u32 bridge_agpstat, temp;
 
 	get_agp_version(agp_bridge);
 
 	printk(KERN_INFO PFX "Found an AGP %d.%d compliant device at %s.\n",
 				agp_bridge->major_version,
 				agp_bridge->minor_version,
-				agp_bridge->dev->slot_name);
+				pci_name(agp_bridge->dev));
 
 	pci_read_config_dword(agp_bridge->dev,
-		      agp_bridge->capndx + PCI_AGP_STATUS, &command);
+		      agp_bridge->capndx + PCI_AGP_STATUS, &bridge_agpstat);
 
-	command = agp_collect_device_status(mode, command);
-	command |= AGPSTAT_AGP_ENABLE;
+	bridge_agpstat = agp_collect_device_status(agp_bridge, requested_mode, bridge_agpstat);
+	if (bridge_agpstat == 0)
+		/* Something bad happened. FIXME: Return error code? */
+		return;
 
-	/* Do AGP version specific frobbing. */
-	if(agp_bridge->major_version >= 3) {
-		pci_read_config_dword(agp_bridge->dev,
-			agp_bridge->capndx+AGPSTAT, &agp3);
+	bridge_agpstat |= AGPSTAT_AGP_ENABLE;
 
-		/* Check to see if we are operating in 3.0 mode */
-		if (agp3 & AGPSTAT_MODE_3_0) {
+	/* Do AGP version specific frobbing. */
+	if (bridge->major_version >= 3) {
+		if (check_bridge_mode(bridge->dev)) {
 			/* If we have 3.5, we can do the isoch stuff. */
-			if (agp_bridge->minor_version >= 5)
-				agp_3_5_enable(agp_bridge);
-			agp_device_command(command, TRUE);
+			if (bridge->minor_version >= 5)
+				agp_3_5_enable(bridge);
+			agp_device_command(bridge_agpstat, TRUE);
 			return;
 		} else {
 		    /* Disable calibration cycle in RX91<1> when not in AGP3.0 mode of operation.*/
-		    command &= ~(7<<10) ;
-		    pci_read_config_dword(agp_bridge->dev, agp_bridge->capndx+AGPCTRL, &temp);
+		    bridge_agpstat &= ~(7<<10) ;
+		    pci_read_config_dword(bridge->dev,
+					bridge->capndx+AGPCTRL, &temp);
 		    temp |= (1<<9);
-		    pci_write_config_dword(agp_bridge->dev, agp_bridge->capndx+AGPCTRL, temp);
+		    pci_write_config_dword(bridge->dev,
+					bridge->capndx+AGPCTRL, temp);
 
 		    printk (KERN_INFO PFX "Device is in legacy mode,"
 				" falling back to 2.x\n");
@@ -644,12 +752,12 @@
 	}
 
 	/* AGP v<3 */
-	agp_device_command(command, FALSE);
+	agp_device_command(bridge_agpstat, FALSE);
 }
 EXPORT_SYMBOL(agp_generic_enable);
 
 
-int agp_generic_create_gatt_table(void)
+int agp_generic_create_gatt_table(struct agp_bridge_data *bridge)
 {
 	char *table;
 	char *table_end;
@@ -661,17 +769,17 @@
 	struct page *page;
 
 	/* The generic routines can't handle 2 level gatt's */
-	if (agp_bridge->driver->size_type == LVL2_APER_SIZE)
+	if (bridge->driver->size_type == LVL2_APER_SIZE)
 		return -EINVAL;
 
 	table = NULL;
-	i = agp_bridge->aperture_size_idx;
-	temp = agp_bridge->current_size;
+	i = bridge->aperture_size_idx;
+	temp = bridge->current_size;
 	size = page_order = num_entries = 0;
 
-	if (agp_bridge->driver->size_type != FIXED_APER_SIZE) {
+	if (bridge->driver->size_type != FIXED_APER_SIZE) {
 		do {
-			switch (agp_bridge->driver->size_type) {
+			switch (bridge->driver->size_type) {
 			case U8_APER_SIZE:
 				size = A_SIZE_8(temp)->size;
 				page_order =
@@ -702,29 +810,29 @@
 
 			if (table == NULL) {
 				i++;
-				switch (agp_bridge->driver->size_type) {
+				switch (bridge->driver->size_type) {
 				case U8_APER_SIZE:
-					agp_bridge->current_size = A_IDX8(agp_bridge);
+					bridge->current_size = A_IDX8(bridge);
 					break;
 				case U16_APER_SIZE:
-					agp_bridge->current_size = A_IDX16(agp_bridge);
+					bridge->current_size = A_IDX16(bridge);
 					break;
 				case U32_APER_SIZE:
-					agp_bridge->current_size = A_IDX32(agp_bridge);
+					bridge->current_size = A_IDX32(bridge);
 					break;
 					/* This case will never really happen. */
 				case FIXED_APER_SIZE:
 				case LVL2_APER_SIZE:
 				default:
-					agp_bridge->current_size =
-					    agp_bridge->current_size;
+					bridge->current_size =
+					    bridge->current_size;
 					break;
 				}
-				temp = agp_bridge->current_size;
+				temp = bridge->current_size;
 			} else {
-				agp_bridge->aperture_size_idx = i;
+				bridge->aperture_size_idx = i;
 			}
-		} while (!table && (i < agp_bridge->driver->num_aperture_sizes));
+		} while (!table && (i < bridge->driver->num_aperture_sizes));
 	} else {
 		size = ((struct aper_size_info_fixed *) temp)->size;
 		page_order = ((struct aper_size_info_fixed *) temp)->page_order;
@@ -740,15 +848,15 @@
 	for (page = virt_to_page(table); page <= virt_to_page(table_end); page++)
 		SetPageReserved(page);
 
-	agp_bridge->gatt_table_real = (u32 *) table;
+	bridge->gatt_table_real = (u32 *) table;
 	agp_gatt_table = (void *)table;
 
-	agp_bridge->driver->cache_flush();
-	agp_bridge->gatt_table = ioremap_nocache(virt_to_phys(table),
+	bridge->driver->cache_flush();
+	bridge->gatt_table = ioremap_nocache(virt_to_phys(table),
 					(PAGE_SIZE * (1 << page_order)));
-	agp_bridge->driver->cache_flush();
+	bridge->driver->cache_flush();
 
-	if (agp_bridge->gatt_table == NULL) {
+	if (bridge->gatt_table == NULL) {
 		for (page = virt_to_page(table); page <= virt_to_page(table_end); page++)
 			ClearPageReserved(page);
 
@@ -756,28 +864,28 @@
 
 		return -ENOMEM;
 	}
-	agp_bridge->gatt_bus_addr = virt_to_phys(agp_bridge->gatt_table_real);
+	bridge->gatt_bus_addr = virt_to_phys(bridge->gatt_table_real);
 
 	/* AK: bogus, should encode addresses > 4GB */
 	for (i = 0; i < num_entries; i++) {
-		writel(agp_bridge->scratch_page, agp_bridge->gatt_table+i);
-		readl(agp_bridge->gatt_table+i);	/* PCI Posting. */
+		writel(bridge->scratch_page, bridge->gatt_table+i);
+		readl(bridge->gatt_table+i);	/* PCI Posting. */
 	}
 
 	return 0;
 }
 EXPORT_SYMBOL(agp_generic_create_gatt_table);
 
-int agp_generic_free_gatt_table(void)
+int agp_generic_free_gatt_table(struct agp_bridge_data *bridge)
 {
 	int page_order;
 	char *table, *table_end;
 	void *temp;
 	struct page *page;
 
-	temp = agp_bridge->current_size;
+	temp = bridge->current_size;
 
-	switch (agp_bridge->driver->size_type) {
+	switch (bridge->driver->size_type) {
 	case U8_APER_SIZE:
 		page_order = A_SIZE_8(temp)->page_order;
 		break;
@@ -803,19 +911,19 @@
 	 * called, then all agp memory is deallocated and removed
 	 * from the table. */
 
-	iounmap(agp_bridge->gatt_table);
-	table = (char *) agp_bridge->gatt_table_real;
+	iounmap(bridge->gatt_table);
+	table = (char *) bridge->gatt_table_real;
 	table_end = table + ((PAGE_SIZE * (1 << page_order)) - 1);
 
 	for (page = virt_to_page(table); page <= virt_to_page(table_end); page++)
 		ClearPageReserved(page);
 
-	free_pages((unsigned long) agp_bridge->gatt_table_real, page_order);
+	free_pages((unsigned long) bridge->gatt_table_real, page_order);
 
 	agp_gatt_table = NULL;
-	agp_bridge->gatt_table = NULL;
-	agp_bridge->gatt_table_real = NULL;
-	agp_bridge->gatt_bus_addr = 0;
+	bridge->gatt_table = NULL;
+	bridge->gatt_table_real = NULL;
+	bridge->gatt_bus_addr = 0;
 
 	return 0;
 }
@@ -828,10 +936,15 @@
 	size_t i;
 	off_t j;
 	void *temp;
+	struct agp_bridge_data *bridge;
 
-	temp = agp_bridge->current_size;
+	bridge = mem->bridge;
+	if (!bridge)
+		return -EINVAL;
 
-	switch (agp_bridge->driver->size_type) {
+	temp = bridge->current_size;
+
+	switch (bridge->driver->size_type) {
 	case U8_APER_SIZE:
 		num_entries = A_SIZE_8(temp)->num_entries;
 		break;
@@ -868,22 +981,22 @@
 	j = pg_start;
 
 	while (j < (pg_start + mem->page_count)) {
-		if (!PGE_EMPTY(agp_bridge, readl(agp_bridge->gatt_table+j)))
+		if (!PGE_EMPTY(bridge, readl(bridge->gatt_table+j)))
 			return -EBUSY;
 		j++;
 	}
 
 	if (mem->is_flushed == FALSE) {
-		agp_bridge->driver->cache_flush();
+		bridge->driver->cache_flush();
 		mem->is_flushed = TRUE;
 	}
 
 	for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
-		writel(agp_bridge->driver->mask_memory(mem->memory[i], mem->type), agp_bridge->gatt_table+j);
-		readl(agp_bridge->gatt_table+j);	/* PCI Posting. */
+		writel(bridge->driver->mask_memory(bridge, mem->memory[i], mem->type), bridge->gatt_table+j);
+		readl(bridge->gatt_table+j);	/* PCI Posting. */
 	}
 
-	agp_bridge->driver->tlb_flush(mem);
+	bridge->driver->tlb_flush(mem);
 	return 0;
 }
 EXPORT_SYMBOL(agp_generic_insert_memory);
@@ -892,6 +1005,11 @@
 int agp_generic_remove_memory(struct agp_memory *mem, off_t pg_start, int type)
 {
 	size_t i;
+	struct agp_bridge_data *bridge;
+
+	bridge = mem->bridge;
+	if (!bridge)
+		return -EINVAL;
 
 	if (type != 0 || mem->type != 0) {
 		/* The generic routines know nothing of memory types */
@@ -900,12 +1018,12 @@
 
 	/* AK: bogus, should encode addresses > 4GB */
 	for (i = pg_start; i < (mem->page_count + pg_start); i++) {
-		writel(agp_bridge->scratch_page, agp_bridge->gatt_table+i);
-		readl(agp_bridge->gatt_table+i);	/* PCI Posting. */
+		writel(bridge->scratch_page, bridge->gatt_table+i);
+		readl(bridge->gatt_table+i);	/* PCI Posting. */
 	}
 
 	global_cache_flush();
-	agp_bridge->driver->tlb_flush(mem);
+	bridge->driver->tlb_flush(mem);
 	return 0;
 }
 EXPORT_SYMBOL(agp_generic_remove_memory);
@@ -920,9 +1038,7 @@
 
 void agp_generic_free_by_type(struct agp_memory *curr)
 {
-	if (curr->memory != NULL)
-		vfree(curr->memory);
-
+	vfree(curr->memory);
 	agp_free_key(curr->key);
 	kfree(curr);
 }
@@ -936,7 +1052,7 @@
  * against a maximum value.
  */
 
-void *agp_generic_alloc_page(void)
+void *agp_generic_alloc_page(struct agp_bridge_data *bridge)
 {
 	struct page * page;
 
@@ -978,14 +1094,25 @@
  *
  * @mode:	agp mode register value to configure with.
  */
-void agp_enable(u32 mode)
+void agp_enable(struct agp_bridge_data *bridge, u32 mode)
 {
-	if (agp_bridge->type == NOT_SUPPORTED)
+	if (!bridge)
 		return;
-	agp_bridge->driver->agp_enable(mode);
+	bridge->driver->agp_enable(bridge, mode);
 }
 EXPORT_SYMBOL(agp_enable);
 
+/* When we remove the global variable agp_bridge from all drivers
+ * then agp_alloc_bridge and agp_generic_find_bridge need to be updated
+ */
+
+struct agp_bridge_data *agp_generic_find_bridge(struct pci_dev *pdev)
+{
+	if (list_empty(&agp_bridges))
+		return NULL;
+
+	return agp_bridge;
+}
 
 static void ipi_handler(void *null)
 {
@@ -999,11 +1126,12 @@
 }
 EXPORT_SYMBOL(global_cache_flush);
 
-unsigned long agp_generic_mask_memory(unsigned long addr, int type)
+unsigned long agp_generic_mask_memory(struct agp_bridge_data *bridge,
+	unsigned long addr, int type)
 {
 	/* memory type is ignored in the generic routine */
-	if (agp_bridge->driver->masks)
-		return addr | agp_bridge->driver->masks[0].mask;
+	if (bridge->driver->masks)
+		return addr | bridge->driver->masks[0].mask;
 	else
 		return addr;
 }
diff -Nru a/drivers/char/agp/hp-agp.c b/drivers/char/agp/hp-agp.c
--- a/drivers/char/agp/hp-agp.c	2005-03-11 12:51:50 -08:00
+++ b/drivers/char/agp/hp-agp.c	2005-03-11 12:51:50 -08:00
@@ -289,7 +289,7 @@
 }
 
 static int
-hp_zx1_create_gatt_table (void)
+hp_zx1_create_gatt_table (struct agp_bridge_data *bridge)
 {
 	struct _hp_private *hp = &hp_private;
 	int i;
@@ -317,7 +317,7 @@
 }
 
 static int
-hp_zx1_free_gatt_table (void)
+hp_zx1_free_gatt_table (struct agp_bridge_data *bridge)
 {
 	struct _hp_private *hp = &hp_private;
 
@@ -367,7 +367,9 @@
 		for (k = 0;
 		     k < hp->io_pages_per_kpage;
 		     k++, j++, paddr += hp->io_page_size) {
-			hp->gatt[j] = agp_bridge->driver->mask_memory(paddr, type);
+			hp->gatt[j] =
+				agp_bridge->driver->mask_memory(agp_bridge,
+					paddr, type);
 		}
 	}
 
@@ -396,19 +398,20 @@
 }
 
 static unsigned long
-hp_zx1_mask_memory (unsigned long addr, int type)
+hp_zx1_mask_memory (struct agp_bridge_data *bridge,
+	unsigned long addr, int type)
 {
 	return HP_ZX1_PDIR_VALID_BIT | addr;
 }
 
 static void
-hp_zx1_enable (u32 mode)
+hp_zx1_enable (struct agp_bridge_data *bridge, u32 mode)
 {
 	struct _hp_private *hp = &hp_private;
 	u32 command;
 
 	command = readl(hp->lba_regs+hp->lba_cap_offset+PCI_AGP_STATUS);
-	command = agp_collect_device_status(mode, command);
+	command = agp_collect_device_status(bridge, mode, command);
 	command |= 0x00000100;
 
 	writel(command, hp->lba_regs+hp->lba_cap_offset+PCI_AGP_COMMAND);
diff -Nru a/drivers/char/agp/i460-agp.c b/drivers/char/agp/i460-agp.c
--- a/drivers/char/agp/i460-agp.c	2005-03-11 12:51:47 -08:00
+++ b/drivers/char/agp/i460-agp.c	2005-03-11 12:51:47 -08:00
@@ -233,7 +233,7 @@
 	return 0;
 }
 
-static int i460_create_gatt_table (void)
+static int i460_create_gatt_table (struct agp_bridge_data *bridge)
 {
 	int page_order, num_entries, i;
 	void *temp;
@@ -258,7 +258,7 @@
 	return 0;
 }
 
-static int i460_free_gatt_table (void)
+static int i460_free_gatt_table (struct agp_bridge_data *bridge)
 {
 	int num_entries, i;
 	void *temp;
@@ -314,7 +314,8 @@
 	for (i = 0, j = io_pg_start; i < mem->page_count; i++) {
 		paddr = mem->memory[i];
 		for (k = 0; k < I460_IOPAGES_PER_KPAGE; k++, j++, paddr += io_page_size)
-			WR_GATT(j, agp_bridge->driver->mask_memory(paddr, mem->type));
+			WR_GATT(j, agp_bridge->driver->mask_memory(agp_bridge,
+				paddr, mem->type));
 	}
 	WR_FLUSH_GATT(j - 1);
 	return 0;
@@ -427,7 +428,8 @@
 			if (i460_alloc_large_page(lp) < 0)
 				return -ENOMEM;
 			pg = lp - i460.lp_desc;
-			WR_GATT(pg, agp_bridge->driver->mask_memory(lp->paddr, 0));
+			WR_GATT(pg, agp_bridge->driver->mask_memory(agp_bridge,
+				lp->paddr, 0));
 			WR_FLUSH_GATT(pg);
 		}
 
@@ -508,12 +510,12 @@
  * Let's just hope nobody counts on the allocated AGP memory being there before bind time
  * (I don't think current drivers do)...
  */
-static void *i460_alloc_page (void)
+static void *i460_alloc_page (struct agp_bridge_data *bridge)
 {
 	void *page;
 
 	if (I460_IO_PAGE_SHIFT <= PAGE_SHIFT)
-		page = agp_generic_alloc_page();
+		page = agp_generic_alloc_page(agp_bridge);
 	else
 		/* Returning NULL would cause problems */
 		/* AK: really dubious code. */
@@ -529,10 +531,11 @@
 
 #endif /* I460_LARGE_IO_PAGES */
 
-static unsigned long i460_mask_memory (unsigned long addr, int type)
+static unsigned long i460_mask_memory (struct agp_bridge_data *bridge,
+	unsigned long addr, int type)
 {
 	/* Make sure the returned address is a valid GATT entry */
-	return agp_bridge->driver->masks[0].mask
+	return bridge->driver->masks[0].mask
 		| (((addr & ~((1 << I460_IO_PAGE_SHIFT) - 1)) & 0xffffff000) >> 12);
 }
 
@@ -624,7 +627,7 @@
 {
 	if (agp_off)
 		return -EINVAL;
-	return pci_module_init(&agp_intel_i460_pci_driver);
+	return pci_register_driver(&agp_intel_i460_pci_driver);
 }
 
 static void __exit agp_intel_i460_cleanup(void)
diff -Nru a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c
--- a/drivers/char/agp/intel-agp.c	2005-03-11 12:51:46 -08:00
+++ b/drivers/char/agp/intel-agp.c	2005-03-11 12:51:46 -08:00
@@ -150,7 +150,7 @@
 	return;
 }
 
-static void intel_i810_agp_enable(u32 mode)
+static void intel_i810_agp_enable(struct agp_bridge_data *bridge, u32 mode)
 {
 	return;
 }
@@ -229,8 +229,9 @@
 insert:
 	global_cache_flush();
 	for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
-		writel(agp_bridge->driver->mask_memory(mem->memory[i], mem->type),
-				intel_i810_private.registers+I810_PTE_BASE+(j*4));
+		writel(agp_bridge->driver->mask_memory(agp_bridge,
+			mem->memory[i], mem->type),
+			intel_i810_private.registers+I810_PTE_BASE+(j*4));
 		readl(intel_i810_private.registers+I810_PTE_BASE+(j*4));	/* PCI Posting. */
 	}
 	global_cache_flush();
@@ -268,7 +269,7 @@
 		return NULL;
 
 	switch (pg_count) {
-	case 1: addr = agp_bridge->driver->agp_alloc_page();
+	case 1: addr = agp_bridge->driver->agp_alloc_page(agp_bridge);
 		break;
 	case 4:
 		/* kludge to get 4 physical pages for ARGB cursor */
@@ -337,10 +338,11 @@
 	kfree(curr);
 }
 
-static unsigned long intel_i810_mask_memory(unsigned long addr, int type)
+static unsigned long intel_i810_mask_memory(struct agp_bridge_data *bridge,
+	unsigned long addr, int type)
 {
 	/* Type checking must be done elsewhere */
-	return addr | agp_bridge->driver->masks[type].mask;
+	return addr | bridge->driver->masks[type].mask;
 }
 
 static struct aper_size_info_fixed intel_i830_sizes[] =
@@ -447,7 +449,7 @@
 /* The intel i830 automatically initializes the agp aperture during POST.
  * Use the memory already set aside for in the GTT.
  */
-static int intel_i830_create_gatt_table(void)
+static int intel_i830_create_gatt_table(struct agp_bridge_data *bridge)
 {
 	int page_order;
 	struct aper_size_info_fixed *size;
@@ -482,7 +484,7 @@
 /* Return the gatt table to a sane state. Use the top of stolen
  * memory for the GTT.
  */
-static int intel_i830_free_gatt_table(void)
+static int intel_i830_free_gatt_table(struct agp_bridge_data *bridge)
 {
 	return 0;
 }
@@ -582,8 +584,9 @@
 	global_cache_flush();	/* FIXME: Necessary ?*/
 
 	for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
-		writel(agp_bridge->driver->mask_memory(mem->memory[i], mem->type),
-				intel_i830_private.registers+I810_PTE_BASE+(j*4));
+		writel(agp_bridge->driver->mask_memory(agp_bridge,
+			mem->memory[i], mem->type),
+			intel_i830_private.registers+I810_PTE_BASE+(j*4));
 		readl(intel_i830_private.registers+I810_PTE_BASE+(j*4));	/* PCI Posting. */
 	}
 
@@ -691,7 +694,8 @@
 	global_cache_flush();
 
 	for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
-		writel(agp_bridge->driver->mask_memory(mem->memory[i], mem->type), intel_i830_private.gtt+j);
+		writel(agp_bridge->driver->mask_memory(agp_bridge,
+			mem->memory[i], mem->type), intel_i830_private.gtt+j);
 		readl(intel_i830_private.gtt+j);	/* PCI Posting. */
 	}
 
@@ -743,7 +747,7 @@
 /* The intel i915 automatically initializes the agp aperture during POST.
  * Use the memory already set aside for in the GTT.
  */
-static int intel_i915_create_gatt_table(void)
+static int intel_i915_create_gatt_table(struct agp_bridge_data *bridge)
 {
 	int page_order;
 	struct aper_size_info_fixed *size;
@@ -1758,6 +1762,8 @@
 		intel_i915_configure();
 	else if (bridge->driver == &intel_830_driver)
 		intel_i830_configure();
+	else if (bridge->driver == &intel_810_driver)
+		intel_i810_configure();
 
 	return 0;
 }
@@ -1810,7 +1816,9 @@
 
 static int __init agp_intel_init(void)
 {
-	return pci_module_init(&agp_intel_pci_driver);
+	if (agp_off)
+		return -EINVAL;
+	return pci_register_driver(&agp_intel_pci_driver);
 }
 
 static void __exit agp_intel_cleanup(void)
diff -Nru a/drivers/char/agp/intel-mch-agp.c b/drivers/char/agp/intel-mch-agp.c
--- a/drivers/char/agp/intel-mch-agp.c	2005-03-11 12:51:41 -08:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,643 +0,0 @@
-/*
- * Intel MCH AGPGART routines.
- */
-
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/init.h>
-#include <linux/agp_backend.h>
-#include "agp.h"
-
-
-#define AGP_DCACHE_MEMORY	1
-#define AGP_PHYS_MEMORY		2
-
-static struct gatt_mask intel_i810_masks[] =
-{
-	{.mask = I810_PTE_VALID, .type = 0},
-	{.mask = (I810_PTE_VALID | I810_PTE_LOCAL), .type = AGP_DCACHE_MEMORY},
-	{.mask = I810_PTE_VALID, .type = 0}
-};
-
-static void intel_i810_tlbflush(struct agp_memory *mem)
-{
-	return;
-}
-
-static void intel_i810_agp_enable(u32 mode)
-{
-	return;
-}
-
-
-/*
- * The i810/i830 requires a physical address to program its mouse
- * pointer into hardware.
- * However the Xserver still writes to it through the agp aperture.
- */
-static struct agp_memory *alloc_agpphysmem_i8xx(size_t pg_count, int type)
-{
-	struct agp_memory *new;
-	void *addr;
-
-	if (pg_count != 1)
-		return NULL;
-
-	addr = agp_bridge->driver->agp_alloc_page();
-	if (addr == NULL)
-		return NULL;
-
-	new = agp_create_memory(1);
-	if (new == NULL)
-		return NULL;
-
-	new->memory[0] = virt_to_phys(addr);
-	new->page_count = 1;
-	new->num_scratch_pages = 1;
-	new->type = AGP_PHYS_MEMORY;
-	new->physical = new->memory[0];
-	return new;
-}
-
-static void intel_i810_free_by_type(struct agp_memory *curr)
-{
-	agp_free_key(curr->key);
-	if(curr->type == AGP_PHYS_MEMORY) {
-		agp_bridge->driver->agp_destroy_page(phys_to_virt(curr->memory[0]));
-		vfree(curr->memory);
-	}
-	kfree(curr);
-}
-
-static unsigned long intel_i810_mask_memory(unsigned long addr, int type)
-{
-	/* Type checking must be done elsewhere */
-	return addr | agp_bridge->driver->masks[type].mask;
-}
-
-static struct aper_size_info_fixed intel_i830_sizes[] =
-{
-	{128, 32768, 5},
-	/* The 64M mode still requires a 128k gatt */
-	{64, 16384, 5}
-};
-
-static struct _intel_i830_private {
-	struct pci_dev *i830_dev;		/* device one */
-	volatile u8 __iomem *registers;
-	int gtt_entries;
-} intel_i830_private;
-
-static void intel_i830_init_gtt_entries(void)
-{
-	u16 gmch_ctrl;
-	int gtt_entries;
-	u8 rdct;
-	int local = 0;
-	static const int ddt[4] = { 0, 16, 32, 64 };
-
-	pci_read_config_word(agp_bridge->dev,I830_GMCH_CTRL,&gmch_ctrl);
-
-	if (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82830_HB ||
-	    agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82845G_HB) {
-		switch (gmch_ctrl & I830_GMCH_GMS_MASK) {
-		case I830_GMCH_GMS_STOLEN_512:
-			gtt_entries = KB(512) - KB(132);
-			break;
-		case I830_GMCH_GMS_STOLEN_1024:
-			gtt_entries = MB(1) - KB(132);
-			break;
-		case I830_GMCH_GMS_STOLEN_8192:
-			gtt_entries = MB(8) - KB(132);
-			break;
-		case I830_GMCH_GMS_LOCAL:
-			rdct = readb(intel_i830_private.registers+I830_RDRAM_CHANNEL_TYPE);
-			gtt_entries = (I830_RDRAM_ND(rdct) + 1) *
-					MB(ddt[I830_RDRAM_DDT(rdct)]);
-			local = 1;
-			break;
-		default:
-			gtt_entries = 0;
-			break;
-		}
-	} else {
-		switch (gmch_ctrl & I830_GMCH_GMS_MASK) {
-		case I855_GMCH_GMS_STOLEN_1M:
-			gtt_entries = MB(1) - KB(132);
-			break;
-		case I855_GMCH_GMS_STOLEN_4M:
-			gtt_entries = MB(4) - KB(132);
-			break;
-		case I855_GMCH_GMS_STOLEN_8M:
-			gtt_entries = MB(8) - KB(132);
-			break;
-		case I855_GMCH_GMS_STOLEN_16M:
-			gtt_entries = MB(16) - KB(132);
-			break;
-		case I855_GMCH_GMS_STOLEN_32M:
-			gtt_entries = MB(32) - KB(132);
-			break;
-		default:
-			gtt_entries = 0;
-			break;
-		}
-	}
-	if (gtt_entries > 0)
-		printk(KERN_INFO PFX "Detected %dK %s memory.\n",
-		       gtt_entries / KB(1), local ? "local" : "stolen");
-	else
-		printk(KERN_INFO PFX
-		       "No pre-allocated video memory detected.\n");
-	gtt_entries /= KB(4);
-
-	intel_i830_private.gtt_entries = gtt_entries;
-}
-
-/* The intel i830 automatically initializes the agp aperture during POST.
- * Use the memory already set aside for in the GTT.
- */
-static int intel_i830_create_gatt_table(void)
-{
-	int page_order;
-	struct aper_size_info_fixed *size;
-	int num_entries;
-	u32 temp;
-
-	size = agp_bridge->current_size;
-	page_order = size->page_order;
-	num_entries = size->num_entries;
-	agp_bridge->gatt_table_real = NULL;
-
-	pci_read_config_dword(intel_i830_private.i830_dev,I810_MMADDR,&temp);
-	temp &= 0xfff80000;
-
-	intel_i830_private.registers = (volatile u8 __iomem*) ioremap(temp,128 * 4096);
-	if (!intel_i830_private.registers)
-		return -ENOMEM;
-
-	temp = readl(intel_i830_private.registers+I810_PGETBL_CTL) & 0xfffff000;
-	global_cache_flush();	/* FIXME: ?? */
-
-	/* we have to call this as early as possible after the MMIO base address is known */
-	intel_i830_init_gtt_entries();
-
-	agp_bridge->gatt_table = NULL;
-
-	agp_bridge->gatt_bus_addr = temp;
-
-	return 0;
-}
-
-/* Return the gatt table to a sane state. Use the top of stolen
- * memory for the GTT.
- */
-static int intel_i830_free_gatt_table(void)
-{
-	return 0;
-}
-
-static int intel_i830_fetch_size(void)
-{
-	u16 gmch_ctrl;
-	struct aper_size_info_fixed *values;
-
-	values = A_SIZE_FIX(agp_bridge->driver->aperture_sizes);
-
-	if (agp_bridge->dev->device != PCI_DEVICE_ID_INTEL_82830_HB &&
-	    agp_bridge->dev->device != PCI_DEVICE_ID_INTEL_82845G_HB) {
-		/* 855GM/852GM/865G has 128MB aperture size */
-		agp_bridge->previous_size = agp_bridge->current_size = (void *) values;
-		agp_bridge->aperture_size_idx = 0;
-		return values[0].size;
-	}
-
-	pci_read_config_word(agp_bridge->dev,I830_GMCH_CTRL,&gmch_ctrl);
-
-	if ((gmch_ctrl & I830_GMCH_MEM_MASK) == I830_GMCH_MEM_128M) {
-		agp_bridge->previous_size = agp_bridge->current_size = (void *) values;
-		agp_bridge->aperture_size_idx = 0;
-		return values[0].size;
-	} else {
-		agp_bridge->previous_size = agp_bridge->current_size = (void *) values;
-		agp_bridge->aperture_size_idx = 1;
-		return values[1].size;
-	}
-
-	return 0;
-}
-
-static int intel_i830_configure(void)
-{
-	struct aper_size_info_fixed *current_size;
-	u32 temp;
-	u16 gmch_ctrl;
-	int i;
-
-	current_size = A_SIZE_FIX(agp_bridge->current_size);
-
-	pci_read_config_dword(intel_i830_private.i830_dev,I810_GMADDR,&temp);
-	agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
-
-	pci_read_config_word(agp_bridge->dev,I830_GMCH_CTRL,&gmch_ctrl);
-	gmch_ctrl |= I830_GMCH_ENABLED;
-	pci_write_config_word(agp_bridge->dev,I830_GMCH_CTRL,gmch_ctrl);
-
-	writel(agp_bridge->gatt_bus_addr|I810_PGETBL_ENABLED, intel_i830_private.registers+I810_PGETBL_CTL);
-	readl(intel_i830_private.registers+I810_PGETBL_CTL);	/* PCI Posting. */
-
-	if (agp_bridge->driver->needs_scratch_page) {
-		for (i = intel_i830_private.gtt_entries; i < current_size->num_entries; i++) {
-			writel(agp_bridge->scratch_page, intel_i830_private.registers+I810_PTE_BASE+(i*4));
-			readl(intel_i830_private.registers+I810_PTE_BASE+(i*4));	/* PCI Posting. */
-		}
-	}
-	global_cache_flush();
-	return 0;
-}
-
-static void intel_i830_cleanup(void)
-{
-	iounmap((void __iomem *) intel_i830_private.registers);
-}
-
-static int intel_i830_insert_entries(struct agp_memory *mem,off_t pg_start,
-				int type)
-{
-	int i,j,num_entries;
-	void *temp;
-
-	temp = agp_bridge->current_size;
-	num_entries = A_SIZE_FIX(temp)->num_entries;
-
-	if (pg_start < intel_i830_private.gtt_entries) {
-		printk (KERN_DEBUG PFX "pg_start == 0x%.8lx,intel_i830_private.gtt_entries == 0x%.8x\n",
-				pg_start,intel_i830_private.gtt_entries);
-
-		printk (KERN_INFO PFX "Trying to insert into local/stolen memory\n");
-		return -EINVAL;
-	}
-
-	if ((pg_start + mem->page_count) > num_entries)
-		return -EINVAL;
-
-	/* The i830 can't check the GTT for entries since its read only,
-	 * depend on the caller to make the correct offset decisions.
-	 */
-
-	if ((type != 0 && type != AGP_PHYS_MEMORY) ||
-		(mem->type != 0 && mem->type != AGP_PHYS_MEMORY))
-		return -EINVAL;
-
-	global_cache_flush();	/* FIXME: ?? */
-
-	for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
-		writel(agp_bridge->driver->mask_memory(mem->memory[i], mem->type),
-				intel_i830_private.registers+I810_PTE_BASE+(j*4));
-		readl(intel_i830_private.registers+I810_PTE_BASE+(j*4));	/* PCI Posting. */
-	}
-
-	global_cache_flush();
-
-	agp_bridge->driver->tlb_flush(mem);
-
-	return 0;
-}
-
-static int intel_i830_remove_entries(struct agp_memory *mem,off_t pg_start,
-				int type)
-{
-	int i;
-
-	global_cache_flush();
-
-	if (pg_start < intel_i830_private.gtt_entries) {
-		printk (KERN_INFO PFX "Trying to disable local/stolen memory\n");
-		return -EINVAL;
-	}
-
-	for (i = pg_start; i < (mem->page_count + pg_start); i++) {
-		writel(agp_bridge->scratch_page, intel_i830_private.registers+I810_PTE_BASE+(i*4));
-		readl(intel_i830_private.registers+I810_PTE_BASE+(i*4));	/* PCI Posting. */
-	}
-
-	global_cache_flush();
-	agp_bridge->driver->tlb_flush(mem);
-	return 0;
-}
-
-static struct agp_memory *intel_i830_alloc_by_type(size_t pg_count,int type)
-{
-	if (type == AGP_PHYS_MEMORY)
-		return alloc_agpphysmem_i8xx(pg_count, type);
-
-	/* always return NULL for other allocation types for now */
-	return NULL;
-}
-
-static int intel_8xx_fetch_size(void)
-{
-	u8 temp;
-	int i;
-	struct aper_size_info_8 *values;
-
-	pci_read_config_byte(agp_bridge->dev, INTEL_APSIZE, &temp);
-
-	values = A_SIZE_8(agp_bridge->driver->aperture_sizes);
-
-	for (i = 0; i < agp_bridge->driver->num_aperture_sizes; i++) {
-		if (temp == values[i].size_value) {
-			agp_bridge->previous_size =
-				agp_bridge->current_size = (void *) (values + i);
-			agp_bridge->aperture_size_idx = i;
-			return values[i].size;
-		}
-	}
-	return 0;
-}
-
-static void intel_8xx_tlbflush(struct agp_memory *mem)
-{
-	u32 temp;
-	pci_read_config_dword(agp_bridge->dev, INTEL_AGPCTRL, &temp);
-	pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, temp & ~(1 << 7));
-	pci_read_config_dword(agp_bridge->dev, INTEL_AGPCTRL, &temp);
-	pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, temp | (1 << 7));
-}
-
-static void intel_8xx_cleanup(void)
-{
-	u16 temp;
-	struct aper_size_info_8 *previous_size;
-
-	previous_size = A_SIZE_8(agp_bridge->previous_size);
-	pci_read_config_word(agp_bridge->dev, INTEL_NBXCFG, &temp);
-	pci_write_config_word(agp_bridge->dev, INTEL_NBXCFG, temp & ~(1 << 9));
-	pci_write_config_byte(agp_bridge->dev, INTEL_APSIZE, previous_size->size_value);
-}
-
-static int intel_845_configure(void)
-{
-	u32 temp;
-	u8 temp2;
-	struct aper_size_info_8 *current_size;
-
-	current_size = A_SIZE_8(agp_bridge->current_size);
-
-	/* aperture size */
-	pci_write_config_byte(agp_bridge->dev, INTEL_APSIZE, current_size->size_value); 
-
-	/* address to map to */
-	pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &temp);
-	agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
-
-	/* attbase - aperture base */
-	pci_write_config_dword(agp_bridge->dev, INTEL_ATTBASE, agp_bridge->gatt_bus_addr); 
-
-	/* agpctrl */
-	pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, 0x0000); 
-
-	/* agpm */
-	pci_read_config_byte(agp_bridge->dev, INTEL_I845_AGPM, &temp2);
-	pci_write_config_byte(agp_bridge->dev, INTEL_I845_AGPM, temp2 | (1 << 1));
-	/* clear any possible error conditions */
-	pci_write_config_word(agp_bridge->dev, INTEL_I845_ERRSTS, 0x001c); 
-	return 0;
-}
-
-
-/* Setup function */
-static struct gatt_mask intel_generic_masks[] =
-{
-	{.mask = 0x00000017, .type = 0}
-};
-
-static struct aper_size_info_8 intel_8xx_sizes[7] =
-{
-	{256, 65536, 6, 0},
-	{128, 32768, 5, 32},
-	{64, 16384, 4, 48},
-	{32, 8192, 3, 56},
-	{16, 4096, 2, 60},
-	{8, 2048, 1, 62},
-	{4, 1024, 0, 63}
-};
-
-static struct agp_bridge_driver intel_830_driver = {
-	.owner			= THIS_MODULE,
-	.aperture_sizes		= intel_i830_sizes,
-	.size_type		= FIXED_APER_SIZE,
-	.num_aperture_sizes 	= 2,
-	.needs_scratch_page	= TRUE,
-	.configure		= intel_i830_configure,
-	.fetch_size		= intel_i830_fetch_size,
-	.cleanup		= intel_i830_cleanup,
-	.tlb_flush		= intel_i810_tlbflush,
-	.mask_memory		= intel_i810_mask_memory,
-	.masks			= intel_i810_masks,
-	.agp_enable		= intel_i810_agp_enable,
-	.cache_flush		= global_cache_flush,
-	.create_gatt_table	= intel_i830_create_gatt_table,
-	.free_gatt_table	= intel_i830_free_gatt_table,
-	.insert_memory		= intel_i830_insert_entries,
-	.remove_memory		= intel_i830_remove_entries,
-	.alloc_by_type		= intel_i830_alloc_by_type,
-	.free_by_type		= intel_i810_free_by_type,
-	.agp_alloc_page		= agp_generic_alloc_page,
-	.agp_destroy_page	= agp_generic_destroy_page,
-};
-
-static struct agp_bridge_driver intel_845_driver = {
-	.owner			= THIS_MODULE,
-	.aperture_sizes		= intel_8xx_sizes,
-	.size_type		= U8_APER_SIZE,
-	.num_aperture_sizes	= 7,
-	.configure		= intel_845_configure,
-	.fetch_size		= intel_8xx_fetch_size,
-	.cleanup		= intel_8xx_cleanup,
-	.tlb_flush		= intel_8xx_tlbflush,
-	.mask_memory		= agp_generic_mask_memory,
-	.masks			= intel_generic_masks,
-	.agp_enable		= agp_generic_enable,
-	.cache_flush		= global_cache_flush,
-	.create_gatt_table	= agp_generic_create_gatt_table,
-	.free_gatt_table	= agp_generic_free_gatt_table,
-	.insert_memory		= agp_generic_insert_memory,
-	.remove_memory		= agp_generic_remove_memory,
-	.alloc_by_type		= agp_generic_alloc_by_type,
-	.free_by_type		= agp_generic_free_by_type,
-	.agp_alloc_page		= agp_generic_alloc_page,
-	.agp_destroy_page	= agp_generic_destroy_page,
-};
-
-
-static int find_i830(u16 device)
-{
-	struct pci_dev *i830_dev;
-
-	i830_dev = pci_get_device(PCI_VENDOR_ID_INTEL, device, NULL);
-	if (i830_dev && PCI_FUNC(i830_dev->devfn) != 0) {
-		i830_dev = pci_get_device(PCI_VENDOR_ID_INTEL,
-				device, i830_dev);
-	}
-
-	if (!i830_dev)
-		return 0;
-
-	intel_i830_private.i830_dev = i830_dev;
-	return 1;
-}
-
-static int __devinit agp_intelmch_probe(struct pci_dev *pdev,
-				     const struct pci_device_id *ent)
-{
-	struct agp_bridge_data *bridge;
-	struct resource *r;
-	char *name = "(unknown)";
-	u8 cap_ptr = 0;
-
-	cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP);
-	if (!cap_ptr) 
-		return -ENODEV;
-
-	bridge = agp_alloc_bridge();
-	if (!bridge)
-		return -ENOMEM;
-
-	switch (pdev->device) {
-	case PCI_DEVICE_ID_INTEL_82865_HB:
-		if (find_i830(PCI_DEVICE_ID_INTEL_82865_IG)) {
-			bridge->driver = &intel_830_driver;
-		} else {
-			bridge->driver = &intel_845_driver;
-		}
-		name = "865";
-		break;
-	case PCI_DEVICE_ID_INTEL_82875_HB:
-		bridge->driver = &intel_845_driver;
-		name = "i875";
-		break;
-
-	default:
-		printk(KERN_ERR PFX "Unsupported Intel chipset (device id: %04x)\n",
-			    pdev->device);
-		return -ENODEV;
-	};
-
-	bridge->dev = pdev;
-	bridge->capndx = cap_ptr;
-
-	if (bridge->driver == &intel_830_driver)
-		bridge->dev_private_data = &intel_i830_private;
-
-	printk(KERN_INFO PFX "Detected an Intel %s Chipset.\n", name);
-
-	/*
-	* The following fixes the case where the BIOS has "forgotten" to
-	* provide an address range for the GART.
-	* 20030610 - hamish@zot.org
-	*/
-	r = &pdev->resource[0];
-	if (!r->start && r->end) {
-		if(pci_assign_resource(pdev, 0)) {
-			printk(KERN_ERR PFX "could not assign resource 0\n");
-			return -ENODEV;
-		}
-	}
-
-	/*
-	* If the device has not been properly setup, the following will catch
-	* the problem and should stop the system from crashing.
-	* 20030610 - hamish@zot.org
-	*/
-	if (pci_enable_device(pdev)) {
-		printk(KERN_ERR PFX "Unable to Enable PCI device\n");
-		return -ENODEV;
-	}
-
-	/* Fill in the mode register */
-	if (cap_ptr) {
-		pci_read_config_dword(pdev,
-				bridge->capndx+PCI_AGP_STATUS,
-				&bridge->mode);
-	}
-
-	pci_set_drvdata(pdev, bridge);
-	return agp_add_bridge(bridge);
-}
-
-static void __devexit agp_intelmch_remove(struct pci_dev *pdev)
-{
-	struct agp_bridge_data *bridge = pci_get_drvdata(pdev);
-
-	agp_remove_bridge(bridge);
-	if (intel_i830_private.i830_dev)
-		pci_dev_put(intel_i830_private.i830_dev);
-	agp_put_bridge(bridge);
-}
-
-static int agp_intelmch_resume(struct pci_dev *pdev)
-{
-	struct agp_bridge_data *bridge = pci_get_drvdata(pdev);
-
-	pci_restore_state(pdev);
-
-	if (bridge->driver == &intel_845_driver)
-		intel_845_configure();
-
-	return 0;
-}
-
-static struct pci_device_id agp_intelmch_pci_table[] = {
-	{
-	.class		= (PCI_CLASS_BRIDGE_HOST << 8),
-	.class_mask	= ~0,
-	.vendor		= PCI_VENDOR_ID_INTEL,
-	.device		= PCI_DEVICE_ID_INTEL_82865_HB,
-	.subvendor	= PCI_ANY_ID,
-	.subdevice	= PCI_ANY_ID,
-	},
-	{
-	.class		= (PCI_CLASS_BRIDGE_HOST << 8),
-	.class_mask	= ~0,
-	.vendor		= PCI_VENDOR_ID_INTEL,
-	.device		= PCI_DEVICE_ID_INTEL_82875_HB,
-	.subvendor	= PCI_ANY_ID,
-	.subdevice	= PCI_ANY_ID,
-	},
-	{ }
-};
-
-MODULE_DEVICE_TABLE(pci, agp_intelmch_pci_table);
-
-static struct pci_driver agp_intelmch_pci_driver = {
-	.name		= "agpgart-intel-mch",
-	.id_table	= agp_intelmch_pci_table,
-	.probe		= agp_intelmch_probe,
-	.remove		= agp_intelmch_remove,
-	.resume		= agp_intelmch_resume,
-};
-
-/* intel_agp_init() must not be declared static for explicit
-   early initialization to work (ie i810fb) */
-int __init agp_intelmch_init(void)
-{
-	static int agp_initialised=0;
-
-	if (agp_initialised == 1)
-		return 0;
-	agp_initialised=1;
-
-	return pci_module_init(&agp_intelmch_pci_driver);
-}
-
-static void __exit agp_intelmch_cleanup(void)
-{
-	pci_unregister_driver(&agp_intelmch_pci_driver);
-}
-
-module_init(agp_intelmch_init);
-module_exit(agp_intelmch_cleanup);
-
-MODULE_AUTHOR("Dave Jones <davej@codemonkey.org.uk>");
-MODULE_LICENSE("GPL");
-
diff -Nru a/drivers/char/agp/nvidia-agp.c b/drivers/char/agp/nvidia-agp.c
--- a/drivers/char/agp/nvidia-agp.c	2005-03-11 12:51:41 -08:00
+++ b/drivers/char/agp/nvidia-agp.c	2005-03-11 12:51:41 -08:00
@@ -215,7 +215,8 @@
 		mem->is_flushed = TRUE;
 	}
 	for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
-		writel(agp_bridge->driver->mask_memory(mem->memory[i], mem->type),
+		writel(agp_bridge->driver->mask_memory(agp_bridge,
+			mem->memory[i], mem->type),
 			agp_bridge->gatt_table+nvidia_private.pg_offset+j);
 		readl(agp_bridge->gatt_table+nvidia_private.pg_offset+j);	/* PCI Posting. */
 	}
@@ -407,7 +408,7 @@
 {
 	if (agp_off)
 		return -EINVAL;
-	return pci_module_init(&agp_nvidia_pci_driver);
+	return pci_register_driver(&agp_nvidia_pci_driver);
 }
 
 static void __exit agp_nvidia_cleanup(void)
diff -Nru a/drivers/char/agp/sis-agp.c b/drivers/char/agp/sis-agp.c
--- a/drivers/char/agp/sis-agp.c	2005-03-11 12:51:41 -08:00
+++ b/drivers/char/agp/sis-agp.c	2005-03-11 12:51:41 -08:00
@@ -1,5 +1,5 @@
 /*
- * SiS AGPGART routines. 
+ * SiS AGPGART routines.
  */
 
 #include <linux/module.h>
@@ -70,7 +70,7 @@
 			      (previous_size->size_value & ~(0x03)));
 }
 
-static void sis_delayed_enable(u32 mode)
+static void sis_delayed_enable(struct agp_bridge_data *bridge, u32 mode)
 {
 	struct pci_dev *device = NULL;
 	u32 command;
@@ -79,10 +79,10 @@
 	printk(KERN_INFO PFX "Found an AGP %d.%d compliant device at %s.\n",
 		agp_bridge->major_version,
 		agp_bridge->minor_version,
-		agp_bridge->dev->slot_name);
+		pci_name(agp_bridge->dev));
 
 	pci_read_config_dword(agp_bridge->dev, agp_bridge->capndx + PCI_AGP_STATUS, &command);
-	command = agp_collect_device_status(mode, command);
+	command = agp_collect_device_status(bridge, mode, command);
 	command |= AGPSTAT_AGP_ENABLE;
 	rate = (command & 0x7) << 2;
 
@@ -99,9 +99,9 @@
 		/*
 		 * Weird: on some sis chipsets any rate change in the target
 		 * command register triggers a 5ms screwup during which the master
-		 * cannot be configured		 
+		 * cannot be configured
 		 */
-		if (device->device == agp_bridge->dev->device) {
+		if (device->device == bridge->dev->device) {
 			printk(KERN_INFO PFX "SiS delay workaround: giving bridge time to recover.\n");
 			msleep(10);
 		}
@@ -342,7 +342,7 @@
 {
 	if (agp_off)
 		return -EINVAL;
-	return pci_module_init(&agp_sis_pci_driver);
+	return pci_register_driver(&agp_sis_pci_driver);
 }
 
 static void __exit agp_sis_cleanup(void)
diff -Nru a/drivers/char/agp/sworks-agp.c b/drivers/char/agp/sworks-agp.c
--- a/drivers/char/agp/sworks-agp.c	2005-03-11 12:51:52 -08:00
+++ b/drivers/char/agp/sworks-agp.c	2005-03-11 12:51:52 -08:00
@@ -141,7 +141,7 @@
 #define GET_GATT_OFF(addr) ((addr & 0x003ff000) >> 12)
 #endif
 
-static int serverworks_create_gatt_table(void)
+static int serverworks_create_gatt_table(struct agp_bridge_data *bridge)
 {
 	struct aper_size_info_lvl2 *value;
 	struct serverworks_page_map page_dir;
@@ -192,7 +192,7 @@
 	return 0;
 }
 
-static int serverworks_free_gatt_table(void)
+static int serverworks_free_gatt_table(struct agp_bridge_data *bridge)
 {
 	struct serverworks_page_map page_dir;
    
@@ -341,7 +341,7 @@
 	for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
 		addr = (j * PAGE_SIZE) + agp_bridge->gart_bus_addr;
 		cur_gatt = SVRWRKS_GET_GATT(addr);
-		writel(agp_bridge->driver->mask_memory(mem->memory[i], mem->type), cur_gatt+GET_GATT_OFF(addr));
+		writel(agp_bridge->driver->mask_memory(agp_bridge, mem->memory[i], mem->type), cur_gatt+GET_GATT_OFF(addr));
 	}
 	serverworks_tlbflush(mem);
 	return 0;
@@ -387,15 +387,15 @@
 	{32, 8192, 0xfe000000}
 };
 
-static void serverworks_agp_enable(u32 mode)
+static void serverworks_agp_enable(struct agp_bridge_data *bridge, u32 mode)
 {
 	u32 command;
 
 	pci_read_config_dword(serverworks_private.svrwrks_dev,
-			      agp_bridge->capndx + PCI_AGP_STATUS,
+			      bridge->capndx + PCI_AGP_STATUS,
 			      &command);
 
-	command = agp_collect_device_status(mode, command);
+	command = agp_collect_device_status(bridge, mode, command);
 
 	command &= ~0x10;	/* disable FW */
 	command &= ~0x08;
@@ -403,7 +403,7 @@
 	command |= 0x100;
 
 	pci_write_config_dword(serverworks_private.svrwrks_dev,
-			       agp_bridge->capndx + PCI_AGP_COMMAND,
+			       bridge->capndx + PCI_AGP_COMMAND,
 			       command);
 
 	agp_device_command(command, 0);
@@ -541,7 +541,7 @@
 {
 	if (agp_off)
 		return -EINVAL;
-	return pci_module_init(&agp_serverworks_pci_driver);
+	return pci_register_driver(&agp_serverworks_pci_driver);
 }
 
 static void __exit agp_serverworks_cleanup(void)
diff -Nru a/drivers/char/agp/uninorth-agp.c b/drivers/char/agp/uninorth-agp.c
--- a/drivers/char/agp/uninorth-agp.c	2005-03-11 12:51:46 -08:00
+++ b/drivers/char/agp/uninorth-agp.c	2005-03-11 12:51:46 -08:00
@@ -6,10 +6,26 @@
 #include <linux/init.h>
 #include <linux/pagemap.h>
 #include <linux/agp_backend.h>
+#include <linux/delay.h>
 #include <asm/uninorth.h>
 #include <asm/pci-bridge.h>
+#include <asm/prom.h>
 #include "agp.h"
 
+/*
+ * NOTES for uninorth3 (G5 AGP) supports :
+ *
+ * There maybe also possibility to have bigger cache line size for
+ * agp (see pmac_pci.c and look for cache line). Need to be investigated
+ * by someone.
+ *
+ * PAGE size are hardcoded but this may change, see asm/page.h.
+ *
+ * Jerome Glisse <j.glisse@gmail.com>
+ */
+static int uninorth_rev;
+static int is_u3;
+
 static int uninorth_fetch_size(void)
 {
 	int i;
@@ -39,26 +55,39 @@
 
 static void uninorth_tlbflush(struct agp_memory *mem)
 {
+	u32 ctrl = UNI_N_CFG_GART_ENABLE;
+
+	if (is_u3)
+		ctrl |= U3_N_CFG_GART_PERFRD;
 	pci_write_config_dword(agp_bridge->dev, UNI_N_CFG_GART_CTRL,
-			UNI_N_CFG_GART_ENABLE | UNI_N_CFG_GART_INVAL);
-	pci_write_config_dword(agp_bridge->dev, UNI_N_CFG_GART_CTRL,
-			UNI_N_CFG_GART_ENABLE);
-	pci_write_config_dword(agp_bridge->dev, UNI_N_CFG_GART_CTRL,
-			UNI_N_CFG_GART_ENABLE | UNI_N_CFG_GART_2xRESET);
-	pci_write_config_dword(agp_bridge->dev, UNI_N_CFG_GART_CTRL,
-			UNI_N_CFG_GART_ENABLE);
+			       ctrl | UNI_N_CFG_GART_INVAL);
+	pci_write_config_dword(agp_bridge->dev, UNI_N_CFG_GART_CTRL, ctrl);
+
+	if (uninorth_rev <= 0x30) {
+		pci_write_config_dword(agp_bridge->dev, UNI_N_CFG_GART_CTRL,
+				       ctrl | UNI_N_CFG_GART_2xRESET);
+		pci_write_config_dword(agp_bridge->dev, UNI_N_CFG_GART_CTRL,
+				       ctrl);
+	}
 }
 
 static void uninorth_cleanup(void)
 {
-	pci_write_config_dword(agp_bridge->dev, UNI_N_CFG_GART_CTRL,
-			UNI_N_CFG_GART_ENABLE | UNI_N_CFG_GART_INVAL);
-	pci_write_config_dword(agp_bridge->dev, UNI_N_CFG_GART_CTRL,
-			0);
-	pci_write_config_dword(agp_bridge->dev, UNI_N_CFG_GART_CTRL,
-			UNI_N_CFG_GART_2xRESET);
-	pci_write_config_dword(agp_bridge->dev, UNI_N_CFG_GART_CTRL,
-			0);
+	u32 tmp;
+
+	pci_read_config_dword(agp_bridge->dev, UNI_N_CFG_GART_CTRL, &tmp);
+	if (!(tmp & UNI_N_CFG_GART_ENABLE))
+		return;
+	tmp |= UNI_N_CFG_GART_INVAL;
+	pci_write_config_dword(agp_bridge->dev, UNI_N_CFG_GART_CTRL, tmp);
+	pci_write_config_dword(agp_bridge->dev, UNI_N_CFG_GART_CTRL, 0);
+
+	if (uninorth_rev <= 0x30) {
+		pci_write_config_dword(agp_bridge->dev, UNI_N_CFG_GART_CTRL,
+				       UNI_N_CFG_GART_2xRESET);
+		pci_write_config_dword(agp_bridge->dev, UNI_N_CFG_GART_CTRL,
+				       0);
+	}
 }
 
 static int uninorth_configure(void)
@@ -81,8 +110,21 @@
 	 * the AGP aperture isn't mapped at bus physical address 0
 	 */
 	agp_bridge->gart_bus_addr = 0;
+#ifdef CONFIG_PPC64
+	/* Assume U3 or later on PPC64 systems */
+	/* high 4 bits of GART physical address go in UNI_N_CFG_AGP_BASE */
+	pci_write_config_dword(agp_bridge->dev, UNI_N_CFG_AGP_BASE,
+			       (agp_bridge->gatt_bus_addr >> 32) & 0xf);
+#else
 	pci_write_config_dword(agp_bridge->dev,
 		UNI_N_CFG_AGP_BASE, agp_bridge->gart_bus_addr);
+#endif
+
+	if (is_u3) {
+		pci_write_config_dword(agp_bridge->dev,
+				       UNI_N_CFG_GART_DUMMY_PAGE,
+				       agp_bridge->scratch_page_real >> 12);
+	}
 	
 	return 0;
 }
@@ -105,13 +147,14 @@
 	j = pg_start;
 
 	while (j < (pg_start + mem->page_count)) {
-		if (!PGE_EMPTY(agp_bridge, agp_bridge->gatt_table[j]))
+		if (agp_bridge->gatt_table[j])
 			return -EBUSY;
 		j++;
 	}
 
 	for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
-		agp_bridge->gatt_table[j] = cpu_to_le32((mem->memory[i] & 0xfffff000) | 0x00000001UL);
+		agp_bridge->gatt_table[j] =
+		    cpu_to_le32((mem->memory[i] & 0xFFFFF000UL) | 0x1UL);
 		flush_dcache_range((unsigned long)__va(mem->memory[i]),
 				   (unsigned long)__va(mem->memory[i])+0x1000);
 	}
@@ -124,38 +167,173 @@
 	return 0;
 }
 
-static void uninorth_agp_enable(u32 mode)
+static int u3_insert_memory(struct agp_memory *mem, off_t pg_start, int type)
+{
+	int i, num_entries;
+	void *temp;
+	u32 *gp;
+
+	temp = agp_bridge->current_size;
+	num_entries = A_SIZE_32(temp)->num_entries;
+
+	if (type != 0 || mem->type != 0)
+		/* We know nothing of memory types */
+		return -EINVAL;
+	if ((pg_start + mem->page_count) > num_entries)
+		return -EINVAL;
+
+	gp = (u32 *) &agp_bridge->gatt_table[pg_start];
+	for (i = 0; i < mem->page_count; ++i) {
+		if (gp[i]) {
+			printk("u3_insert_memory: entry 0x%x occupied (%x)\n",
+			       i, gp[i]);
+			return -EBUSY;
+		}
+	}
+
+	for (i = 0; i < mem->page_count; i++) {
+		gp[i] = (mem->memory[i] >> PAGE_SHIFT) | 0x80000000UL;
+		flush_dcache_range((unsigned long)__va(mem->memory[i]),
+				   (unsigned long)__va(mem->memory[i])+0x1000);
+	}
+	mb();
+	flush_dcache_range((unsigned long)gp, (unsigned long) &gp[i]);
+	uninorth_tlbflush(mem);
+
+	return 0;
+}
+
+int u3_remove_memory(struct agp_memory *mem, off_t pg_start, int type)
 {
-	u32 command, scratch;
+	size_t i;
+	u32 *gp;
+
+	if (type != 0 || mem->type != 0)
+		/* We know nothing of memory types */
+		return -EINVAL;
+
+	gp = (u32 *) &agp_bridge->gatt_table[pg_start];
+	for (i = 0; i < mem->page_count; ++i)
+		gp[i] = 0;
+	mb();
+	flush_dcache_range((unsigned long)gp, (unsigned long) &gp[i]);
+	uninorth_tlbflush(mem);
+
+	return 0;
+}
+
+static void uninorth_agp_enable(struct agp_bridge_data *bridge, u32 mode)
+{
+	u32 command, scratch, status;
 	int timeout;
 
-	pci_read_config_dword(agp_bridge->dev,
-			      agp_bridge->capndx + PCI_AGP_STATUS,
-			      &command);
+	pci_read_config_dword(bridge->dev,
+			      bridge->capndx + PCI_AGP_STATUS,
+			      &status);
 
-	command = agp_collect_device_status(mode, command);
-	command |= 0x100;
+	command = agp_collect_device_status(bridge, mode, status);
+	command |= PCI_AGP_COMMAND_AGP;
+	
+	if (uninorth_rev == 0x21) {
+		/*
+		 * Darwin disable AGP 4x on this revision, thus we
+		 * may assume it's broken. This is an AGP2 controller.
+		 */
+		command &= ~AGPSTAT2_4X;
+	}
+
+	if ((uninorth_rev >= 0x30) && (uninorth_rev <= 0x33)) {
+		/*
+		 * We need to to set REQ_DEPTH to 7 for U3 versions 1.0, 2.1,
+		 * 2.2 and 2.3, Darwin do so.
+		 */
+		if ((command >> AGPSTAT_RQ_DEPTH_SHIFT) > 7)
+			command = (command & ~AGPSTAT_RQ_DEPTH)
+				| (7 << AGPSTAT_RQ_DEPTH_SHIFT);
+	}
 
 	uninorth_tlbflush(NULL);
 
 	timeout = 0;
 	do {
-		pci_write_config_dword(agp_bridge->dev,
-				       agp_bridge->capndx + PCI_AGP_COMMAND,
+		pci_write_config_dword(bridge->dev,
+				       bridge->capndx + PCI_AGP_COMMAND,
 				       command);
-		pci_read_config_dword(agp_bridge->dev,
-				       agp_bridge->capndx + PCI_AGP_COMMAND,
+		pci_read_config_dword(bridge->dev,
+				      bridge->capndx + PCI_AGP_COMMAND,
 				       &scratch);
-	} while ((scratch & 0x100) == 0 && ++timeout < 1000);
-	if ((scratch & 0x100) == 0)
+	} while ((scratch & PCI_AGP_COMMAND_AGP) == 0 && ++timeout < 1000);
+	if ((scratch & PCI_AGP_COMMAND_AGP) == 0)
 		printk(KERN_ERR PFX "failed to write UniNorth AGP command reg\n");
 
-	agp_device_command(command, 0);
+	if (uninorth_rev >= 0x30) {
+		/* This is an AGP V3 */
+		agp_device_command(command, (status & AGPSTAT_MODE_3_0));
+	} else {
+		/* AGP V2 */
+		agp_device_command(command, 0);
+	}
 
 	uninorth_tlbflush(NULL);
 }
 
-static int uninorth_create_gatt_table(void)
+#ifdef CONFIG_PM
+static int agp_uninorth_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+	u32 cmd;
+	u8 agp;
+	struct pci_dev *device = NULL;
+
+	if (state != PMSG_SUSPEND)
+		return 0;
+
+	/* turn off AGP on the video chip, if it was enabled */
+	for_each_pci_dev(device) {
+		/* Don't touch the bridge yet, device first */
+		if (device == pdev)
+			continue;
+		/* Only deal with devices on the same bus here, no Mac has a P2P
+		 * bridge on the AGP port, and mucking around the entire PCI
+		 * tree is source of problems on some machines because of a bug
+		 * in some versions of pci_find_capability() when hitting a dead
+		 * device
+		 */
+		if (device->bus != pdev->bus)
+			continue;
+		agp = pci_find_capability(device, PCI_CAP_ID_AGP);
+		if (!agp)
+			continue;
+		pci_read_config_dword(device, agp + PCI_AGP_COMMAND, &cmd);
+		if (!(cmd & PCI_AGP_COMMAND_AGP))
+			continue;
+		printk("uninorth-agp: disabling AGP on device %s\n",
+				pci_name(device));
+		cmd &= ~PCI_AGP_COMMAND_AGP;
+		pci_write_config_dword(device, agp + PCI_AGP_COMMAND, cmd);
+	}
+
+	/* turn off AGP on the bridge */
+	agp = pci_find_capability(pdev, PCI_CAP_ID_AGP);
+	pci_read_config_dword(pdev, agp + PCI_AGP_COMMAND, &cmd);
+	if (cmd & PCI_AGP_COMMAND_AGP) {
+		printk("uninorth-agp: disabling AGP on bridge %s\n",
+				pci_name(pdev));
+		cmd &= ~PCI_AGP_COMMAND_AGP;
+		pci_write_config_dword(pdev, agp + PCI_AGP_COMMAND, cmd);
+	}
+	/* turn off the GART */
+	uninorth_cleanup();
+
+	return 0;
+}
+
+static int agp_uninorth_resume(struct pci_dev *pdev)
+{
+	return 0;
+}
+#endif
+
+static int uninorth_create_gatt_table(struct agp_bridge_data *bridge)
 {
 	char *table;
 	char *table_end;
@@ -167,12 +345,12 @@
 	struct page *page;
 
 	/* We can't handle 2 level gatt's */
-	if (agp_bridge->driver->size_type == LVL2_APER_SIZE)
+	if (bridge->driver->size_type == LVL2_APER_SIZE)
 		return -EINVAL;
 
 	table = NULL;
-	i = agp_bridge->aperture_size_idx;
-	temp = agp_bridge->current_size;
+	i = bridge->aperture_size_idx;
+	temp = bridge->current_size;
 	size = page_order = num_entries = 0;
 
 	do {
@@ -184,11 +362,11 @@
 
 		if (table == NULL) {
 			i++;
-			agp_bridge->current_size = A_IDX32(agp_bridge);
+			bridge->current_size = A_IDX32(bridge);
 		} else {
-			agp_bridge->aperture_size_idx = i;
+			bridge->aperture_size_idx = i;
 		}
-	} while (!table && (i < agp_bridge->driver->num_aperture_sizes));
+	} while (!table && (i < bridge->driver->num_aperture_sizes));
 
 	if (table == NULL)
 		return -ENOMEM;
@@ -198,28 +376,26 @@
 	for (page = virt_to_page(table); page <= virt_to_page(table_end); page++)
 		SetPageReserved(page);
 
-	agp_bridge->gatt_table_real = (u32 *) table;
-	agp_bridge->gatt_table = (u32 *)table;
-	agp_bridge->gatt_bus_addr = virt_to_phys(table);
-
-	for (i = 0; i < num_entries; i++) {
-		agp_bridge->gatt_table[i] =
-		    (unsigned long) agp_bridge->scratch_page;
-	}
+	bridge->gatt_table_real = (u32 *) table;
+	bridge->gatt_table = (u32 *)table;
+	bridge->gatt_bus_addr = virt_to_phys(table);
+
+	for (i = 0; i < num_entries; i++)
+		bridge->gatt_table[i] = 0;
 
 	flush_dcache_range((unsigned long)table, (unsigned long)table_end);
 
 	return 0;
 }
 
-static int uninorth_free_gatt_table(void)
+static int uninorth_free_gatt_table(struct agp_bridge_data *bridge)
 {
 	int page_order;
 	char *table, *table_end;
 	void *temp;
 	struct page *page;
 
-	temp = agp_bridge->current_size;
+	temp = bridge->current_size;
 	page_order = A_SIZE_32(temp)->page_order;
 
 	/* Do not worry about freeing memory, because if this is
@@ -227,13 +403,13 @@
 	 * from the table.
 	 */
 
-	table = (char *) agp_bridge->gatt_table_real;
+	table = (char *) bridge->gatt_table_real;
 	table_end = table + ((PAGE_SIZE * (1 << page_order)) - 1);
 
 	for (page = virt_to_page(table); page <= virt_to_page(table_end); page++)
 		ClearPageReserved(page);
 
-	free_pages((unsigned long) agp_bridge->gatt_table_real, page_order);
+	free_pages((unsigned long) bridge->gatt_table_real, page_order);
 
 	return 0;
 }
@@ -258,6 +434,22 @@
 	{4, 1024, 0, 1}
 };
 
+/*
+ * Not sure that u3 supports that high aperture sizes but it
+ * would strange if it did not :)
+ */
+static struct aper_size_info_32 u3_sizes[8] =
+{
+	{512, 131072, 7, 128},
+	{256, 65536, 6, 64},
+	{128, 32768, 5, 32},
+	{64, 16384, 4, 16},
+	{32, 8192, 3, 8},
+	{16, 4096, 2, 4},
+	{8, 2048, 1, 2},
+	{4, 1024, 0, 1}
+};
+
 struct agp_bridge_driver uninorth_agp_driver = {
 	.owner			= THIS_MODULE,
 	.aperture_sizes		= (void *)uninorth_sizes,
@@ -282,6 +474,31 @@
 	.cant_use_aperture	= 1,
 };
 
+struct agp_bridge_driver u3_agp_driver = {
+	.owner			= THIS_MODULE,
+	.aperture_sizes		= (void *)u3_sizes,
+	.size_type		= U32_APER_SIZE,
+	.num_aperture_sizes	= 8,
+	.configure		= uninorth_configure,
+	.fetch_size		= uninorth_fetch_size,
+	.cleanup		= uninorth_cleanup,
+	.tlb_flush		= uninorth_tlbflush,
+	.mask_memory		= agp_generic_mask_memory,
+	.masks			= NULL,
+	.cache_flush		= null_cache_flush,
+	.agp_enable		= uninorth_agp_enable,
+	.create_gatt_table	= uninorth_create_gatt_table,
+	.free_gatt_table	= uninorth_free_gatt_table,
+	.insert_memory		= u3_insert_memory,
+	.remove_memory		= u3_remove_memory,
+	.alloc_by_type		= agp_generic_alloc_by_type,
+	.free_by_type		= agp_generic_free_by_type,
+	.agp_alloc_page		= agp_generic_alloc_page,
+	.agp_destroy_page	= agp_generic_destroy_page,
+	.cant_use_aperture	= 1,
+	.needs_scratch_page	= 1,
+};
+
 static struct agp_device_ids uninorth_agp_device_ids[] __devinitdata = {
 	{
 		.device_id	= PCI_DEVICE_ID_APPLE_UNI_N_AGP,
@@ -299,6 +516,18 @@
 		.device_id	= PCI_DEVICE_ID_APPLE_UNI_N_AGP2,
 		.chipset_name	= "UniNorth 2",
 	},
+	{
+		.device_id	= PCI_DEVICE_ID_APPLE_U3_AGP,
+		.chipset_name	= "U3",
+	},
+	{
+		.device_id	= PCI_DEVICE_ID_APPLE_U3L_AGP,
+		.chipset_name	= "U3L",
+	},
+	{
+		.device_id	= PCI_DEVICE_ID_APPLE_U3H_AGP,
+		.chipset_name	= "U3H",
+	},
 };
 
 static int __devinit agp_uninorth_probe(struct pci_dev *pdev,
@@ -306,6 +535,7 @@
 {
 	struct agp_device_ids *devs = uninorth_agp_device_ids;
 	struct agp_bridge_data *bridge;
+	struct device_node *uninorth_node;
 	u8 cap_ptr;
 	int j;
 
@@ -327,13 +557,36 @@
 	return -ENODEV;
 
  found:
+	/* Set revision to 0 if we could not read it. */
+	uninorth_rev = 0;
+	is_u3 = 0;
+	/* Locate core99 Uni-N */
+	uninorth_node = of_find_node_by_name(NULL, "uni-n");
+	/* Locate G5 u3 */
+	if (uninorth_node == NULL) {
+		is_u3 = 1;
+		uninorth_node = of_find_node_by_name(NULL, "u3");
+	}
+	if (uninorth_node) {
+		int *revprop = (int *)
+			get_property(uninorth_node, "device-rev", NULL);
+		if (revprop != NULL)
+			uninorth_rev = *revprop & 0x3f;
+		of_node_put(uninorth_node);
+	}
+
 	bridge = agp_alloc_bridge();
 	if (!bridge)
 		return -ENOMEM;
 
-	bridge->driver = &uninorth_agp_driver;
+	if (is_u3)
+		bridge->driver = &u3_agp_driver;
+	else
+		bridge->driver = &uninorth_agp_driver;
+
 	bridge->dev = pdev;
 	bridge->capndx = cap_ptr;
+	bridge->flags = AGP_ERRATA_FASTWRITES;
 
 	/* Fill in the mode register */
 	pci_read_config_dword(pdev, cap_ptr+PCI_AGP_STATUS, &bridge->mode);
@@ -369,13 +622,17 @@
 	.id_table	= agp_uninorth_pci_table,
 	.probe		= agp_uninorth_probe,
 	.remove		= agp_uninorth_remove,
+#ifdef CONFIG_PM
+	.suspend	= agp_uninorth_suspend,
+	.resume		= agp_uninorth_resume,
+#endif
 };
 
 static int __init agp_uninorth_init(void)
 {
 	if (agp_off)
 		return -EINVAL;
-	return pci_module_init(&agp_uninorth_pci_driver);
+	return pci_register_driver(&agp_uninorth_pci_driver);
 }
 
 static void __exit agp_uninorth_cleanup(void)
diff -Nru a/drivers/char/agp/via-agp.c b/drivers/char/agp/via-agp.c
--- a/drivers/char/agp/via-agp.c	2005-03-11 12:51:52 -08:00
+++ b/drivers/char/agp/via-agp.c	2005-03-11 12:51:52 -08:00
@@ -1,5 +1,5 @@
 /*
- * VIA AGPGART routines. 
+ * VIA AGPGART routines.
  */
 
 #include <linux/types.h>
@@ -36,6 +36,7 @@
 			return values[i].size;
 		}
 	}
+	printk(KERN_ERR PFX "Unknown aperture size from AGP bridge (0x%x)\n", temp);
 	return 0;
 }
 
@@ -78,12 +79,19 @@
 
 static void via_tlbflush(struct agp_memory *mem)
 {
-	pci_write_config_dword(agp_bridge->dev, VIA_GARTCTRL, 0x0000008f);
-	pci_write_config_dword(agp_bridge->dev, VIA_GARTCTRL, 0x0000000f);
+	u32 temp;
+
+	pci_read_config_dword(agp_bridge->dev, VIA_GARTCTRL, &temp);
+	temp |= (1<<7);
+	temp &= ~0x7f;
+	pci_write_config_dword(agp_bridge->dev, VIA_GARTCTRL, temp);
+	temp &= ~(1<<7);
+	temp &= ~0x7f;
+	pci_write_config_dword(agp_bridge->dev, VIA_GARTCTRL, temp);
 }
 
 
-static struct aper_size_info_8 via_generic_sizes[7] =
+static struct aper_size_info_8 via_generic_sizes[9] =
 {
 	{256, 65536, 6, 0},
 	{128, 32768, 5, 128},
@@ -91,7 +99,9 @@
 	{32, 8192, 3, 224},
 	{16, 4096, 2, 240},
 	{8, 2048, 1, 248},
-	{4, 1024, 0, 252}
+	{4, 1024, 0, 252},
+	{2, 512, 0, 254},
+	{1, 256, 0, 255}
 };
 
 
@@ -121,7 +131,7 @@
 {
 	u32 temp;
 	struct aper_size_info_16 *current_size;
-    
+
 	current_size = A_SIZE_16(agp_bridge->current_size);
 
 	/* address to map too */
@@ -132,13 +142,13 @@
 	pci_write_config_dword(agp_bridge->dev, VIA_AGP3_ATTBASE,
 		agp_bridge->gatt_bus_addr & 0xfffff000);
 
-	/* 1. Enable GTLB in RX90<7>, all AGP aperture access needs to fetch 
+	/* 1. Enable GTLB in RX90<7>, all AGP aperture access needs to fetch
 	 *    translation table first.
 	 * 2. Enable AGP aperture in RX91<0>. This bit controls the enabling of the
 	 *    graphics AGP aperture for the AGP3.0 port.
 	 */
 	pci_read_config_dword(agp_bridge->dev, VIA_AGP3_GARTCTRL, &temp);
-	pci_write_config_dword(agp_bridge->dev, VIA_AGP3_GARTCTRL, temp | (3<<7));		
+	pci_write_config_dword(agp_bridge->dev, VIA_AGP3_GARTCTRL, temp | (3<<7));
 	return 0;
 }
 
@@ -189,7 +199,7 @@
 	.owner			= THIS_MODULE,
 	.aperture_sizes		= via_generic_sizes,
 	.size_type		= U8_APER_SIZE,
-	.num_aperture_sizes	= 7,
+	.num_aperture_sizes	= 9,
 	.configure		= via_configure,
 	.fetch_size		= via_fetch_size,
 	.cleanup		= via_cleanup,
@@ -525,7 +535,7 @@
 {
 	if (agp_off)
 		return -EINVAL;
-	return pci_module_init(&agp_via_pci_driver);
+	return pci_register_driver(&agp_via_pci_driver);
 }
 
 static void __exit agp_via_cleanup(void)
diff -Nru a/drivers/char/console_macros.h b/drivers/char/console_macros.h
--- a/drivers/char/console_macros.h	2005-03-11 12:51:41 -08:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,71 +0,0 @@
-#define cons_num	(vc_cons[currcons].d->vc_num)
-#define video_scan_lines (vc_cons[currcons].d->vc_scan_lines)
-#define sw		(vc_cons[currcons].d->vc_sw)
-#define screenbuf	(vc_cons[currcons].d->vc_screenbuf)
-#define screenbuf_size	(vc_cons[currcons].d->vc_screenbuf_size)
-#define origin		(vc_cons[currcons].d->vc_origin)
-#define scr_top		(vc_cons[currcons].d->vc_scr_top)
-#define visible_origin  (vc_cons[currcons].d->vc_visible_origin)
-#define scr_end		(vc_cons[currcons].d->vc_scr_end)
-#define pos		(vc_cons[currcons].d->vc_pos)
-#define top		(vc_cons[currcons].d->vc_top)
-#define bottom		(vc_cons[currcons].d->vc_bottom)
-#define x		(vc_cons[currcons].d->vc_x)
-#define y		(vc_cons[currcons].d->vc_y)
-#define vc_state	(vc_cons[currcons].d->vc_state)
-#define npar		(vc_cons[currcons].d->vc_npar)
-#define par		(vc_cons[currcons].d->vc_par)
-#define ques		(vc_cons[currcons].d->vc_ques)
-#define attr		(vc_cons[currcons].d->vc_attr)
-#define saved_x		(vc_cons[currcons].d->vc_saved_x)
-#define saved_y		(vc_cons[currcons].d->vc_saved_y)
-#define translate	(vc_cons[currcons].d->vc_translate)
-#define G0_charset	(vc_cons[currcons].d->vc_G0_charset)
-#define G1_charset	(vc_cons[currcons].d->vc_G1_charset)
-#define saved_G0	(vc_cons[currcons].d->vc_saved_G0)
-#define saved_G1	(vc_cons[currcons].d->vc_saved_G1)
-#define utf		(vc_cons[currcons].d->vc_utf)
-#define utf_count	(vc_cons[currcons].d->vc_utf_count)
-#define utf_char	(vc_cons[currcons].d->vc_utf_char)
-#define video_erase_char (vc_cons[currcons].d->vc_video_erase_char)
-#define disp_ctrl	(vc_cons[currcons].d->vc_disp_ctrl)
-#define toggle_meta	(vc_cons[currcons].d->vc_toggle_meta)
-#define decscnm		(vc_cons[currcons].d->vc_decscnm)
-#define decom		(vc_cons[currcons].d->vc_decom)
-#define decawm		(vc_cons[currcons].d->vc_decawm)
-#define deccm		(vc_cons[currcons].d->vc_deccm)
-#define decim		(vc_cons[currcons].d->vc_decim)
-#define deccolm		(vc_cons[currcons].d->vc_deccolm)
-#define need_wrap	(vc_cons[currcons].d->vc_need_wrap)
-#define kmalloced	(vc_cons[currcons].d->vc_kmalloced)
-#define report_mouse	(vc_cons[currcons].d->vc_report_mouse)
-#define color		(vc_cons[currcons].d->vc_color)
-#define s_color		(vc_cons[currcons].d->vc_s_color)
-#define def_color	(vc_cons[currcons].d->vc_def_color)
-#define foreground	(color & 0x0f)
-#define background	(color & 0xf0)
-#define charset		(vc_cons[currcons].d->vc_charset)
-#define s_charset	(vc_cons[currcons].d->vc_s_charset)
-#define	intensity	(vc_cons[currcons].d->vc_intensity)
-#define	underline	(vc_cons[currcons].d->vc_underline)
-#define	blink		(vc_cons[currcons].d->vc_blink)
-#define	reverse		(vc_cons[currcons].d->vc_reverse)
-#define	s_intensity	(vc_cons[currcons].d->vc_s_intensity)
-#define	s_underline	(vc_cons[currcons].d->vc_s_underline)
-#define	s_blink		(vc_cons[currcons].d->vc_s_blink)
-#define	s_reverse	(vc_cons[currcons].d->vc_s_reverse)
-#define	ulcolor		(vc_cons[currcons].d->vc_ulcolor)
-#define	halfcolor	(vc_cons[currcons].d->vc_halfcolor)
-#define tab_stop	(vc_cons[currcons].d->vc_tab_stop)
-#define palette		(vc_cons[currcons].d->vc_palette)
-#define bell_pitch	(vc_cons[currcons].d->vc_bell_pitch)
-#define bell_duration	(vc_cons[currcons].d->vc_bell_duration)
-#define cursor_type	(vc_cons[currcons].d->vc_cursor_type)
-#define display_fg	(vc_cons[currcons].d->vc_display_fg)
-#define complement_mask (vc_cons[currcons].d->vc_complement_mask)
-#define s_complement_mask (vc_cons[currcons].d->vc_s_complement_mask)
-#define hi_font_mask	(vc_cons[currcons].d->vc_hi_font_mask)
-
-#define vcmode		(vt_cons[currcons]->vc_mode)
-
-#define structsize	(sizeof(struct vc_data) + sizeof(struct vt_struct))
diff -Nru a/drivers/char/consolemap.c b/drivers/char/consolemap.c
--- a/drivers/char/consolemap.c	2005-03-11 12:51:47 -08:00
+++ b/drivers/char/consolemap.c	2005-03-11 12:51:47 -08:00
@@ -208,9 +208,9 @@
 	}
 }
 
-unsigned short *set_translate(int m,int currcons)
+unsigned short *set_translate(int m, struct vc_data *vc)
 {
-	inv_translate[currcons] = m;
+	inv_translate[vc->vc_num] = m;
 	return translations[m];
 }
 
@@ -362,15 +362,16 @@
 		}
 }
 
-void con_free_unimap(int con)
+void con_free_unimap(struct vc_data *vc)
 {
 	struct uni_pagedir *p;
-	struct vc_data *conp = vc_cons[con].d;
-	
-	p = (struct uni_pagedir *)*conp->vc_uni_pagedir_loc;
-	if (!p) return;
-	*conp->vc_uni_pagedir_loc = 0;
-	if (--p->refcount) return;
+
+	p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
+	if (!p)
+		return;
+	*vc->vc_uni_pagedir_loc = 0;
+	if (--p->refcount)
+		return;
 	con_release_unimap(p);
 	kfree(p);
 }
@@ -442,12 +443,11 @@
 }
 
 /* ui is a leftover from using a hashtable, but might be used again */
-int con_clear_unimap(int con, struct unimapinit *ui)
+int con_clear_unimap(struct vc_data *vc, struct unimapinit *ui)
 {
 	struct uni_pagedir *p, *q;
-	struct vc_data *conp = vc_cons[con].d;
   
-	p = (struct uni_pagedir *)*conp->vc_uni_pagedir_loc;
+	p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
 	if (p && p->readonly) return -EIO;
 	if (!p || --p->refcount) {
 		q = (struct uni_pagedir *)kmalloc(sizeof(*p), GFP_KERNEL);
@@ -457,7 +457,7 @@
 		}
 		memset(q, 0, sizeof(*q));
 		q->refcount=1;
-		*conp->vc_uni_pagedir_loc = (unsigned long)q;
+		*vc->vc_uni_pagedir_loc = (unsigned long)q;
 	} else {
 		if (p == dflt) dflt = NULL;
 		p->refcount++;
@@ -467,14 +467,12 @@
 	return 0;
 }
 
-int
-con_set_unimap(int con, ushort ct, struct unipair __user *list)
+int con_set_unimap(struct vc_data *vc, ushort ct, struct unipair __user *list)
 {
 	int err = 0, err1, i;
 	struct uni_pagedir *p, *q;
-	struct vc_data *conp = vc_cons[con].d;
 
-	p = (struct uni_pagedir *)*conp->vc_uni_pagedir_loc;
+	p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
 	if (p->readonly) return -EIO;
 	
 	if (!ct) return 0;
@@ -483,10 +481,10 @@
 		int j, k;
 		u16 **p1, *p2, l;
 		
-		err1 = con_clear_unimap(con, NULL);
+		err1 = con_clear_unimap(vc, NULL);
 		if (err1) return err1;
 		
-		q = (struct uni_pagedir *)*conp->vc_uni_pagedir_loc;
+		q = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
 		for (i = 0, l = 0; i < 32; i++)
 		if ((p1 = p->uni_pgdir[i]))
 			for (j = 0; j < 32; j++)
@@ -496,7 +494,7 @@
 					err1 = con_insert_unipair(q, l, p2[k]);
 					if (err1) {
 						p->refcount++;
-						*conp->vc_uni_pagedir_loc = (unsigned long)p;
+						*vc->vc_uni_pagedir_loc = (unsigned long)p;
 						con_release_unimap(q);
 						kfree(q);
 						return err1; 
@@ -515,11 +513,11 @@
 			list++;
 	}
 	
-	if (con_unify_unimap(conp, p))
+	if (con_unify_unimap(vc, p))
 		return err;
 
 	for (i = 0; i <= 3; i++)
-		set_inverse_transl(conp, p, i); /* Update all inverse translations */
+		set_inverse_transl(vc, p, i); /* Update all inverse translations */
   
 	return err;
 }
@@ -529,20 +527,18 @@
    with.  This routine is executed at sys_setup time, and when the
    PIO_FONTRESET ioctl is called. */
 
-int
-con_set_default_unimap(int con)
+int con_set_default_unimap(struct vc_data *vc)
 {
 	int i, j, err = 0, err1;
 	u16 *q;
 	struct uni_pagedir *p;
-	struct vc_data *conp = vc_cons[con].d;
-	
+
 	if (dflt) {
-		p = (struct uni_pagedir *)*conp->vc_uni_pagedir_loc;
+		p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
 		if (p == dflt)
 			return 0;
 		dflt->refcount++;
-		*conp->vc_uni_pagedir_loc = (unsigned long)dflt;
+		*vc->vc_uni_pagedir_loc = (unsigned long)dflt;
 		if (p && --p->refcount) {
 			con_release_unimap(p);
 			kfree(p);
@@ -552,10 +548,10 @@
 	
 	/* The default font is always 256 characters */
 
-	err = con_clear_unimap(con,NULL);
+	err = con_clear_unimap(vc, NULL);
 	if (err) return err;
     
-	p = (struct uni_pagedir *)*conp->vc_uni_pagedir_loc;
+	p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
 	q = dfont_unitable;
 	
 	for (i = 0; i < 256; i++)
@@ -565,47 +561,42 @@
 				err = err1;
 		}
 			
-	if (con_unify_unimap(conp, p)) {
-		dflt = (struct uni_pagedir *)*conp->vc_uni_pagedir_loc;
+	if (con_unify_unimap(vc, p)) {
+		dflt = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
 		return err;
 	}
 
 	for (i = 0; i <= 3; i++)
-		set_inverse_transl(conp, p, i);	/* Update all inverse translations */
+		set_inverse_transl(vc, p, i);	/* Update all inverse translations */
 	dflt = p;
 	return err;
 }
 EXPORT_SYMBOL(con_set_default_unimap);
 
-int
-con_copy_unimap(int dstcon, int srccon)
+int con_copy_unimap(struct vc_data *dst_vc, struct vc_data *src_vc)
 {
-	struct vc_data *sconp = vc_cons[srccon].d;
-	struct vc_data *dconp = vc_cons[dstcon].d;
 	struct uni_pagedir *q;
-	
-	if (!vc_cons_allocated(srccon) || !*sconp->vc_uni_pagedir_loc)
+
+	if (!*src_vc->vc_uni_pagedir_loc)
 		return -EINVAL;
-	if (*dconp->vc_uni_pagedir_loc == *sconp->vc_uni_pagedir_loc)
+	if (*dst_vc->vc_uni_pagedir_loc == *src_vc->vc_uni_pagedir_loc)
 		return 0;
-	con_free_unimap(dstcon);
-	q = (struct uni_pagedir *)*sconp->vc_uni_pagedir_loc;
+	con_free_unimap(dst_vc);
+	q = (struct uni_pagedir *)*src_vc->vc_uni_pagedir_loc;
 	q->refcount++;
-	*dconp->vc_uni_pagedir_loc = (long)q;
+	*dst_vc->vc_uni_pagedir_loc = (long)q;
 	return 0;
 }
 
-int
-con_get_unimap(int con, ushort ct, ushort __user *uct, struct unipair __user *list)
+int con_get_unimap(struct vc_data *vc, ushort ct, ushort __user *uct, struct unipair __user *list)
 {
 	int i, j, k, ect;
 	u16 **p1, *p2;
 	struct uni_pagedir *p;
-	struct vc_data *conp = vc_cons[con].d;
 
 	ect = 0;
-	if (*conp->vc_uni_pagedir_loc) {
-		p = (struct uni_pagedir *)*conp->vc_uni_pagedir_loc;
+	if (*vc->vc_uni_pagedir_loc) {
+		p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
 		for (i = 0; i < 32; i++)
 		if ((p1 = p->uni_pgdir[i]))
 			for (j = 0; j < 32; j++)
@@ -625,12 +616,12 @@
 	return ((ect <= ct) ? 0 : -ENOMEM);
 }
 
-void con_protect_unimap(int con, int rdonly)
+void con_protect_unimap(struct vc_data *vc, int rdonly)
 {
-	struct uni_pagedir *p = (struct uni_pagedir *)
-		*vc_cons[con].d->vc_uni_pagedir_loc;
+	struct uni_pagedir *p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
 	
-	if (p) p->readonly = rdonly;
+	if (p)
+		p->readonly = rdonly;
 }
 
 int
@@ -679,7 +670,7 @@
 	
 	for (i = 0; i < MAX_NR_CONSOLES; i++)
 		if (vc_cons_allocated(i) && !*vc_cons[i].d->vc_uni_pagedir_loc)
-			con_set_default_unimap(i);
+			con_set_default_unimap(vc_cons[i].d);
 }
 
 EXPORT_SYMBOL(con_copy_unimap);
diff -Nru a/drivers/char/drm/drmP.h b/drivers/char/drm/drmP.h
--- a/drivers/char/drm/drmP.h	2005-03-11 12:51:47 -08:00
+++ b/drivers/char/drm/drmP.h	2005-03-11 12:51:47 -08:00
@@ -422,7 +422,7 @@
 	unsigned long	  ioctl_count;
 	struct drm_file	  *next;
 	struct drm_file	  *prev;
-	struct drm_device *dev;
+	struct drm_head   *head;
 	int 		  remove_auth_on_close;
 	unsigned long     lock_count;
 	void              *driver_priv;
@@ -497,6 +497,7 @@
 	DRM_AGP_KERN       agp_info;	/**< AGP device information */
 	drm_agp_mem_t      *memory;	/**< memory entries */
 	unsigned long      mode;	/**< AGP mode */
+	struct agp_bridge_data  *bridge;
 	int                enabled;	/**< whether the AGP bus as been enabled */
 	int                acquired;	/**< whether the AGP device has been acquired */
 	unsigned long      base;
@@ -592,19 +593,31 @@
 	struct file_operations fops;
 	struct pci_driver pci_driver;
 };
+
 /**
- * DRM device structure.
+ * DRM head structure. This structure represent a video head on a card
+ * that may contain multiple heads. Embed one per head of these in the
+ * private drm_device structure.
+ */
+typedef struct drm_head {
+	int minor;			/**< Minor device number */
+	struct drm_device *dev;
+	struct proc_dir_entry *dev_root;  /**< proc directory entry */
+	dev_t device;			/**< Device number for mknod */
+	struct class_device *dev_class;
+} drm_head_t;
+
+/**
+ * DRM device structure. This structure represent a complete card that
+ * may contain multiple heads.
  */
 typedef struct drm_device {
 	char		  *unique;	/**< Unique identifier: e.g., busid */
 	int		  unique_len;	/**< Length of unique field */
-	dev_t		  device;	/**< Device number for mknod */
 	char		  *devname;	/**< For /proc/interrupts */
-	int		  minor;        /**< Minor device number */
 	int		  if_version;	/**< Highest interface version set */
 
 	int		  blocked;	/**< Blocked due to VC switch? */
-	struct proc_dir_entry *root;	/**< Root for this device's entries */
 
 	/** \name Locks */
 	/*@{*/
@@ -720,17 +733,9 @@
 
 	struct            drm_driver *driver;
 	drm_local_map_t   *agp_buffer_map;
+	drm_head_t primary;		/**< primary screen head */
 } drm_device_t;
 
-typedef struct drm_minor {
-	enum {
-		DRM_MINOR_FREE = 0,
-		DRM_MINOR_PRIMARY,
-	} type;
-	drm_device_t *dev;
-	struct proc_dir_entry  *dev_root; /**< proc directory entry */
-} drm_minor_t;
-
 static __inline__ int drm_core_check_feature(struct drm_device *dev, int feature)
 {
 	return ((dev->driver->driver_features & feature) ? 1 : 0);
@@ -807,7 +812,7 @@
 					   drm_device_t *dev);
 extern void	     drm_ioremapfree(void *pt, unsigned long size, drm_device_t *dev);
 
-extern DRM_AGP_MEM   *drm_alloc_agp(int pages, u32 type);
+extern DRM_AGP_MEM   *drm_alloc_agp(struct agp_bridge_data *bridge, int pages, u32 type);
 extern int           drm_free_agp(DRM_AGP_MEM *handle, int pages);
 extern int           drm_bind_agp(DRM_AGP_MEM *handle, unsigned int start);
 extern int           drm_unbind_agp(DRM_AGP_MEM *handle);
@@ -930,10 +935,10 @@
 extern void          drm_vbl_send_signals( drm_device_t *dev );
 
 				/* AGP/GART support (drm_agpsupport.h) */
-extern drm_agp_head_t *drm_agp_init(void);
+extern drm_agp_head_t *drm_agp_init(drm_device_t *dev);
 extern int            drm_agp_acquire(struct inode *inode, struct file *filp,
 				       unsigned int cmd, unsigned long arg);
-extern void           drm_agp_do_release(void);
+extern void           drm_agp_do_release(drm_device_t *dev);
 extern int            drm_agp_release(struct inode *inode, struct file *filp,
 				       unsigned int cmd, unsigned long arg);
 extern int            drm_agp_enable(struct inode *inode, struct file *filp,
@@ -948,18 +953,20 @@
 				      unsigned int cmd, unsigned long arg);
 extern int            drm_agp_bind(struct inode *inode, struct file *filp,
 				    unsigned int cmd, unsigned long arg);
-extern DRM_AGP_MEM    *drm_agp_allocate_memory(size_t pages, u32 type);
+extern DRM_AGP_MEM    *drm_agp_allocate_memory(struct agp_bridge_data *bridge, size_t pages, u32 type);
 extern int            drm_agp_free_memory(DRM_AGP_MEM *handle);
 extern int            drm_agp_bind_memory(DRM_AGP_MEM *handle, off_t start);
 extern int            drm_agp_unbind_memory(DRM_AGP_MEM *handle);
 
 				/* Stub support (drm_stub.h) */
-extern int            drm_probe(struct pci_dev *pdev, const struct pci_device_id *ent, struct drm_driver *driver);
-
-extern int 	      drm_put_minor(drm_device_t *dev);
+extern int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent,
+		     struct drm_driver *driver);
+extern int drm_put_dev(drm_device_t * dev);
+extern int drm_get_head(drm_device_t * dev, drm_head_t *head);
+extern int drm_put_head(drm_head_t * head);
 extern unsigned int   drm_debug;
 extern unsigned int   drm_cards_limit;
-extern drm_minor_t    *drm_minors;
+extern drm_head_t **drm_heads;
 extern struct drm_sysfs_class *drm_class;
 extern struct proc_dir_entry *drm_proc_root;
 
diff -Nru a/drivers/char/drm/drm_agpsupport.c b/drivers/char/drm/drm_agpsupport.c
--- a/drivers/char/drm/drm_agpsupport.c	2005-03-11 12:51:40 -08:00
+++ b/drivers/char/drm/drm_agpsupport.c	2005-03-11 12:51:40 -08:00
@@ -52,7 +52,7 @@
 		  unsigned int cmd, unsigned long arg)
 {
 	drm_file_t	 *priv	 = filp->private_data;
-	drm_device_t	 *dev	 = priv->dev;
+	drm_device_t	 *dev	 = priv->head->dev;
 	DRM_AGP_KERN     *kern;
 	drm_agp_info_t   info;
 
@@ -91,15 +91,14 @@
 		     unsigned int cmd, unsigned long arg)
 {
 	drm_file_t	 *priv	 = filp->private_data;
-	drm_device_t	 *dev	 = priv->dev;
-	int              retcode;
+	drm_device_t	 *dev	 = priv->head->dev;
 
 	if (!dev->agp)
 		return -ENODEV;
 	if (dev->agp->acquired)
 		return -EBUSY;
-	if ((retcode = agp_backend_acquire()))
-		return retcode;
+	if (!(dev->agp->bridge = agp_backend_acquire(dev->pdev)))
+		return -ENODEV;
 	dev->agp->acquired = 1;
 	return 0;
 }
@@ -119,11 +118,11 @@
 		     unsigned int cmd, unsigned long arg)
 {
 	drm_file_t	 *priv	 = filp->private_data;
-	drm_device_t	 *dev	 = priv->dev;
+	drm_device_t	 *dev	 = priv->head->dev;
 
 	if (!dev->agp || !dev->agp->acquired)
 		return -EINVAL;
-	agp_backend_release();
+	agp_backend_release(dev->agp->bridge);
 	dev->agp->acquired = 0;
 	return 0;
 
@@ -134,9 +133,9 @@
  *
  * Calls agp_backend_release().
  */
-void drm_agp_do_release(void)
+void drm_agp_do_release(drm_device_t *dev)
 {
-  agp_backend_release();
+  agp_backend_release(dev->agp->bridge);
 }
 
 /**
@@ -155,7 +154,7 @@
 		    unsigned int cmd, unsigned long arg)
 {
 	drm_file_t	 *priv	 = filp->private_data;
-	drm_device_t	 *dev	 = priv->dev;
+	drm_device_t	 *dev	 = priv->head->dev;
 	drm_agp_mode_t   mode;
 
 	if (!dev->agp || !dev->agp->acquired)
@@ -165,7 +164,7 @@
 		return -EFAULT;
 
 	dev->agp->mode    = mode.mode;
-	agp_enable(mode.mode);
+	agp_enable(dev->agp->bridge, mode.mode);
 	dev->agp->base    = dev->agp->agp_info.aper_base;
 	dev->agp->enabled = 1;
 	return 0;
@@ -187,7 +186,7 @@
 		   unsigned int cmd, unsigned long arg)
 {
 	drm_file_t	 *priv	 = filp->private_data;
-	drm_device_t	 *dev	 = priv->dev;
+	drm_device_t	 *dev	 = priv->head->dev;
 	drm_agp_buffer_t request;
 	drm_agp_mem_t    *entry;
 	DRM_AGP_MEM      *memory;
@@ -207,7 +206,7 @@
 	pages = (request.size + PAGE_SIZE - 1) / PAGE_SIZE;
 	type = (u32) request.type;
 
-	if (!(memory = drm_alloc_agp(pages, type))) {
+	if (!(memory = drm_alloc_agp(dev->agp->bridge, pages, type))) {
 		drm_free(entry, sizeof(*entry), DRM_MEM_AGPLISTS);
 		return -ENOMEM;
 	}
@@ -272,7 +271,7 @@
 		    unsigned int cmd, unsigned long arg)
 {
 	drm_file_t	  *priv	 = filp->private_data;
-	drm_device_t	  *dev	 = priv->dev;
+	drm_device_t	  *dev	 = priv->head->dev;
 	drm_agp_binding_t request;
 	drm_agp_mem_t     *entry;
 	int ret;
@@ -308,7 +307,7 @@
 		  unsigned int cmd, unsigned long arg)
 {
 	drm_file_t	  *priv	 = filp->private_data;
-	drm_device_t	  *dev	 = priv->dev;
+	drm_device_t	  *dev	 = priv->head->dev;
 	drm_agp_binding_t request;
 	drm_agp_mem_t     *entry;
 	int               retcode;
@@ -349,7 +348,7 @@
 		  unsigned int cmd, unsigned long arg)
 {
 	drm_file_t	 *priv	 = filp->private_data;
-	drm_device_t	 *dev	 = priv->dev;
+	drm_device_t	 *dev	 = priv->head->dev;
 	drm_agp_buffer_t request;
 	drm_agp_mem_t    *entry;
 
@@ -381,14 +380,19 @@
  * \return pointer to a drm_agp_head structure.
  *
  */
-drm_agp_head_t *drm_agp_init(void)
+drm_agp_head_t *drm_agp_init(drm_device_t *dev)
 {
 	drm_agp_head_t *head         = NULL;
 
 	if (!(head = drm_alloc(sizeof(*head), DRM_MEM_AGPLISTS)))
 		return NULL;
 	memset((void *)head, 0, sizeof(*head));
-	agp_copy_info(&head->agp_info);
+	if (!(head->bridge = agp_backend_acquire(dev->pdev))) {
+		drm_free(head, sizeof(*head), DRM_MEM_AGPLISTS);
+		return NULL;
+	}
+	agp_copy_info(head->bridge, &head->agp_info);
+	agp_backend_release(head->bridge);
 	if (head->agp_info.chipset == NOT_SUPPORTED) {
 		drm_free(head, sizeof(*head), DRM_MEM_AGPLISTS);
 		return NULL;
@@ -406,9 +410,9 @@
 }
 
 /** Calls agp_allocate_memory() */
-DRM_AGP_MEM *drm_agp_allocate_memory(size_t pages, u32 type)
+DRM_AGP_MEM *drm_agp_allocate_memory(struct agp_bridge_data *bridge, size_t pages, u32 type)
 {
-	return agp_allocate_memory(pages, type);
+	return agp_allocate_memory(bridge, pages, type);
 }
 
 /** Calls agp_free_memory() */
diff -Nru a/drivers/char/drm/drm_auth.c b/drivers/char/drm/drm_auth.c
--- a/drivers/char/drm/drm_auth.c	2005-03-11 12:51:51 -08:00
+++ b/drivers/char/drm/drm_auth.c	2005-03-11 12:51:51 -08:00
@@ -176,7 +176,7 @@
 	static drm_magic_t sequence = 0;
 	static DEFINE_SPINLOCK(lock);
 	drm_file_t	   *priv    = filp->private_data;
-	drm_device_t	   *dev	    = priv->dev;
+	drm_device_t	   *dev	    = priv->head->dev;
 	drm_auth_t	   auth;
 
 				/* Find unique magic */
@@ -214,7 +214,7 @@
 		   unsigned int cmd, unsigned long arg)
 {
 	drm_file_t	   *priv    = filp->private_data;
-	drm_device_t	   *dev	    = priv->dev;
+	drm_device_t	   *dev	    = priv->head->dev;
 	drm_auth_t	   auth;
 	drm_file_t	   *file;
 
diff -Nru a/drivers/char/drm/drm_bufs.c b/drivers/char/drm/drm_bufs.c
--- a/drivers/char/drm/drm_bufs.c	2005-03-11 12:51:41 -08:00
+++ b/drivers/char/drm/drm_bufs.c	2005-03-11 12:51:41 -08:00
@@ -77,7 +77,7 @@
 		 unsigned int cmd, unsigned long arg )
 {
 	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev = priv->dev;
+	drm_device_t *dev = priv->head->dev;
 	drm_map_t *map;
 	drm_map_t __user *argp = (void __user *)arg;
 	drm_map_list_t *list;
@@ -221,7 +221,7 @@
 	       unsigned int cmd, unsigned long arg)
 {
 	drm_file_t	*priv	= filp->private_data;
-	drm_device_t	*dev	= priv->dev;
+	drm_device_t	*dev	= priv->head->dev;
 	struct list_head *list;
 	drm_map_list_t *r_list = NULL;
 	drm_vma_entry_t *pt, *prev;
@@ -349,7 +349,7 @@
 		      unsigned int cmd, unsigned long arg )
 {
 	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev = priv->dev;
+	drm_device_t *dev = priv->head->dev;
 	drm_device_dma_t *dma = dev->dma;
 	drm_buf_desc_t request;
 	drm_buf_entry_t *entry;
@@ -514,7 +514,7 @@
 		      unsigned int cmd, unsigned long arg )
 {
    	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev = priv->dev;
+	drm_device_t *dev = priv->head->dev;
 	drm_device_dma_t *dma = dev->dma;
 	drm_buf_desc_t request;
 	int count;
@@ -744,7 +744,7 @@
                      unsigned int cmd, unsigned long arg )
 {
 	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev = priv->dev;
+	drm_device_t *dev = priv->head->dev;
 	drm_device_dma_t *dma = dev->dma;
 	drm_buf_desc_t __user *argp = (void __user *)arg;
 	drm_buf_desc_t request;
@@ -925,7 +925,7 @@
 {
 	drm_buf_desc_t request;
 	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev = priv->dev;
+	drm_device_t *dev = priv->head->dev;
 	
 	if (!drm_core_check_feature(dev, DRIVER_HAVE_DMA))
 		return -EINVAL;
@@ -967,7 +967,7 @@
 		   unsigned int cmd, unsigned long arg )
 {
 	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev = priv->dev;
+	drm_device_t *dev = priv->head->dev;
 	drm_device_dma_t *dma = dev->dma;
 	drm_buf_info_t request;
 	drm_buf_info_t __user *argp = (void __user *)arg;
@@ -1052,7 +1052,7 @@
 		   unsigned int cmd, unsigned long arg )
 {
 	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev = priv->dev;
+	drm_device_t *dev = priv->head->dev;
 	drm_device_dma_t *dma = dev->dma;
 	drm_buf_desc_t request;
 	int order;
@@ -1101,7 +1101,7 @@
 		   unsigned int cmd, unsigned long arg )
 {
 	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev = priv->dev;
+	drm_device_t *dev = priv->head->dev;
 	drm_device_dma_t *dma = dev->dma;
 	drm_buf_free_t request;
 	int i;
@@ -1158,7 +1158,7 @@
 		  unsigned int cmd, unsigned long arg )
 {
 	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev = priv->dev;
+	drm_device_t *dev = priv->head->dev;
 	drm_device_dma_t *dma = dev->dma;
 	drm_buf_map_t __user *argp = (void __user *)arg;
 	int retcode = 0;
diff -Nru a/drivers/char/drm/drm_context.c b/drivers/char/drm/drm_context.c
--- a/drivers/char/drm/drm_context.c	2005-03-11 12:51:40 -08:00
+++ b/drivers/char/drm/drm_context.c	2005-03-11 12:51:40 -08:00
@@ -208,7 +208,7 @@
 		     unsigned int cmd, unsigned long arg)
 {
 	drm_file_t	*priv	= filp->private_data;
-	drm_device_t	*dev	= priv->dev;
+	drm_device_t	*dev	= priv->head->dev;
 	drm_ctx_priv_map_t __user *argp = (void __user *)arg;
 	drm_ctx_priv_map_t request;
 	drm_map_t *map;
@@ -247,7 +247,7 @@
 		     unsigned int cmd, unsigned long arg)
 {
 	drm_file_t	*priv	= filp->private_data;
-	drm_device_t	*dev	= priv->dev;
+	drm_device_t	*dev	= priv->head->dev;
 	drm_ctx_priv_map_t request;
 	drm_map_t *map = NULL;
 	drm_map_list_t *r_list = NULL;
@@ -395,7 +395,7 @@
 		 unsigned int cmd, unsigned long arg )
 {
 	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev = priv->dev;
+	drm_device_t *dev = priv->head->dev;
 	drm_ctx_list_t * ctx_entry;
 	drm_ctx_t __user *argp = (void __user *)arg;
 	drm_ctx_t ctx;
@@ -489,7 +489,7 @@
 		    unsigned int cmd, unsigned long arg )
 {
 	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev = priv->dev;
+	drm_device_t *dev = priv->head->dev;
 	drm_ctx_t ctx;
 
 	if ( copy_from_user( &ctx, (drm_ctx_t __user *)arg, sizeof(ctx) ) )
@@ -514,7 +514,7 @@
 		 unsigned int cmd, unsigned long arg )
 {
 	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev = priv->dev;
+	drm_device_t *dev = priv->head->dev;
 	drm_ctx_t ctx;
 
 	if ( copy_from_user( &ctx, (drm_ctx_t __user *)arg, sizeof(ctx) ) )
@@ -541,7 +541,7 @@
 		unsigned int cmd, unsigned long arg )
 {
 	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev = priv->dev;
+	drm_device_t *dev = priv->head->dev;
 	drm_ctx_t ctx;
 
 	if ( copy_from_user( &ctx, (drm_ctx_t __user *)arg, sizeof(ctx) ) )
diff -Nru a/drivers/char/drm/drm_drv.c b/drivers/char/drm/drm_drv.c
--- a/drivers/char/drm/drm_drv.c	2005-03-11 12:51:51 -08:00
+++ b/drivers/char/drm/drm_drv.c	2005-03-11 12:51:51 -08:00
@@ -149,18 +149,6 @@
 	down( &dev->struct_sem );
 	del_timer( &dev->timer );
 
-	if ( dev->devname ) {
-		drm_free( dev->devname, strlen( dev->devname ) + 1,
-			   DRM_MEM_DRIVER );
-		dev->devname = NULL;
-	}
-
-	if ( dev->unique ) {
-		drm_free( dev->unique, strlen( dev->unique ) + 1,
-			   DRM_MEM_DRIVER );
-		dev->unique = NULL;
-		dev->unique_len = 0;
-	}
 				/* Clear pid list */
 	for ( i = 0 ; i < DRM_HASH_SIZE ; i++ ) {
 		for ( pt = dev->magiclist[i].head ; pt ; pt = next ) {
@@ -185,7 +173,7 @@
 		}
 		dev->agp->memory = NULL;
 
-		if ( dev->agp->acquired ) drm_agp_do_release();
+		if ( dev->agp->acquired ) drm_agp_do_release(dev);
 
 		dev->agp->acquired = 0;
 		dev->agp->enabled  = 0;
@@ -307,7 +295,7 @@
 		while ((pdev = pci_get_subsys(pid->vendor, pid->device, pid->subvendor, pid->subdevice, pdev)) != NULL) {
 			/* stealth mode requires a manual probe */
 			pci_dev_get(pdev);
-			drm_probe(pdev, pid, driver);
+			drm_get_dev(pdev, pid, driver);
 		}
 	}
 	return 0;
@@ -351,7 +339,8 @@
 	if (dev->driver->postcleanup)
 		dev->driver->postcleanup(dev);
 	
-	if ( drm_put_minor(dev) )
+	drm_put_head(&dev->primary);
+	if ( drm_put_dev(dev) )
 		DRM_ERROR( "Cannot unload module\n" );
 }
 
@@ -359,19 +348,19 @@
 {
 	int i;
 	drm_device_t *dev = NULL;
-	drm_minor_t *minor;
+	drm_head_t *head;
 	
 	DRM_DEBUG( "\n" );
 
 	for (i = 0; i < drm_cards_limit; i++) {
-		minor = &drm_minors[i];
-		if (!minor->dev)
+		head = drm_heads[i];
+		if (!head)
 			continue;
-		if (minor->dev->driver!=driver)
+		if (!head->dev)
 			continue;
-
-		dev = minor->dev;
-		
+		if (head->dev->driver!=driver)
+			continue;
+		dev=head->dev;
 	}
 	if (dev) {
 		/* release the pci driver */
@@ -379,7 +368,6 @@
 			pci_dev_put(dev->pdev);
 		drm_cleanup(dev);
 	}
-	
 	DRM_INFO( "Module unloaded\n" );
 }
 EXPORT_SYMBOL(drm_exit);
@@ -395,9 +383,9 @@
 	int ret = -ENOMEM;
 	
 	drm_cards_limit = (drm_cards_limit < DRM_MAX_MINOR + 1 ? drm_cards_limit : DRM_MAX_MINOR + 1);
-	drm_minors = drm_calloc(drm_cards_limit,
-				sizeof(*drm_minors), DRM_MEM_STUB);
-	if(!drm_minors) 
+	drm_heads = drm_calloc(drm_cards_limit,
+				sizeof(*drm_heads), DRM_MEM_STUB);
+	if(!drm_heads) 
 		goto err_p1;
 	
 	if (register_chrdev(DRM_MAJOR, "drm", &drm_stub_fops))
@@ -429,7 +417,7 @@
 	drm_sysfs_destroy(drm_class);
 err_p2:
 	unregister_chrdev(DRM_MAJOR, "drm");
-	drm_free(drm_minors, sizeof(*drm_minors) * drm_cards_limit, DRM_MEM_STUB);
+	drm_free(drm_heads, sizeof(*drm_heads) * drm_cards_limit, DRM_MEM_STUB);
 err_p1:	
 	return ret;
 }
@@ -441,7 +429,7 @@
 
 	unregister_chrdev(DRM_MAJOR, "drm");
 
-	drm_free(drm_minors, sizeof(*drm_minors) *
+	drm_free(drm_heads, sizeof(*drm_heads) *
 				drm_cards_limit, DRM_MEM_STUB);
 }
 
@@ -465,7 +453,7 @@
 		  unsigned int cmd, unsigned long arg )
 {
 	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev = priv->dev;
+	drm_device_t *dev = priv->head->dev;
 	drm_version_t __user *argp = (void __user *)arg;
 	drm_version_t version;
 	int ret;
@@ -500,7 +488,7 @@
 		unsigned int cmd, unsigned long arg )
 {
 	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev = priv->dev;
+	drm_device_t *dev = priv->head->dev;
 	drm_ioctl_desc_t *ioctl;
 	drm_ioctl_t *func;
 	unsigned int nr = DRM_IOCTL_NR(cmd);
@@ -511,7 +499,7 @@
 	++priv->ioctl_count;
 
 	DRM_DEBUG( "pid=%d, cmd=0x%02x, nr=0x%02x, dev 0x%lx, auth=%d\n",
-		   current->pid, cmd, nr, (long)old_encode_dev(dev->device), 
+		   current->pid, cmd, nr, (long)old_encode_dev(priv->head->device), 
 		   priv->authenticated );
 	
 	if (nr < DRIVER_IOCTL_COUNT)
diff -Nru a/drivers/char/drm/drm_fops.c b/drivers/char/drm/drm_fops.c
--- a/drivers/char/drm/drm_fops.c	2005-03-11 12:51:46 -08:00
+++ b/drivers/char/drm/drm_fops.c	2005-03-11 12:51:46 -08:00
@@ -143,8 +143,10 @@
 	if (!((minor >= 0) && (minor < drm_cards_limit)))
 		return -ENODEV;
 		
-	dev = drm_minors[minor].dev;
-	if (!dev)
+	if (!drm_heads[minor])
+		return -ENODEV;
+
+	if (!(dev = drm_heads[minor]->dev))
 		return -ENODEV;
 	
 	retcode = drm_open_helper( inode, filp, dev );
@@ -181,7 +183,7 @@
 	int retcode = 0;
 
 	lock_kernel();
-	dev = priv->dev;
+	dev = priv->head->dev;
 
 	DRM_DEBUG( "open_count = %d\n", dev->open_count );
 
@@ -193,7 +195,7 @@
 	 */
 
 	DRM_DEBUG( "pid = %d, device = 0x%lx, open_count = %d\n",
-		   current->pid, (long)old_encode_dev(dev->device), dev->open_count );
+		   current->pid, (long)old_encode_dev(priv->head->device), dev->open_count );
 
 	if ( priv->lock_count && dev->lock.hw_lock &&
 	     _DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock) &&
@@ -358,7 +360,7 @@
 	priv->uid	    = current->euid;
 	priv->pid	    = current->pid;
 	priv->minor	    = minor;
-	priv->dev	    = dev;
+	priv->head          = drm_heads[minor];
 	priv->ioctl_count   = 0;
 	priv->authenticated = capable(CAP_SYS_ADMIN);
 	priv->lock_count    = 0;
@@ -412,10 +414,10 @@
 int drm_flush(struct file *filp)
 {
 	drm_file_t    *priv   = filp->private_data;
-	drm_device_t  *dev    = priv->dev;
+	drm_device_t  *dev    = priv->head->dev;
 
 	DRM_DEBUG("pid = %d, device = 0x%lx, open_count = %d\n",
-		  current->pid, (long)old_encode_dev(dev->device), dev->open_count);
+		  current->pid, (long)old_encode_dev(priv->head->device), dev->open_count);
 	return 0;
 }
 EXPORT_SYMBOL(drm_flush);
@@ -424,10 +426,10 @@
 int drm_fasync(int fd, struct file *filp, int on)
 {
 	drm_file_t    *priv   = filp->private_data;
-	drm_device_t  *dev    = priv->dev;
+	drm_device_t  *dev    = priv->head->dev;
 	int	      retcode;
 
-	DRM_DEBUG("fd = %d, device = 0x%lx\n", fd, (long)old_encode_dev(dev->device));
+	DRM_DEBUG("fd = %d, device = 0x%lx\n", fd, (long)old_encode_dev(priv->head->device));
 	retcode = fasync_helper(fd, filp, on, &dev->buf_async);
 	if (retcode < 0) return retcode;
 	return 0;
diff -Nru a/drivers/char/drm/drm_ioctl.c b/drivers/char/drm/drm_ioctl.c
--- a/drivers/char/drm/drm_ioctl.c	2005-03-11 12:51:41 -08:00
+++ b/drivers/char/drm/drm_ioctl.c	2005-03-11 12:51:42 -08:00
@@ -53,7 +53,7 @@
 		   unsigned int cmd, unsigned long arg)
 {
 	drm_file_t	 *priv	 = filp->private_data;
-	drm_device_t	 *dev	 = priv->dev;
+	drm_device_t	 *dev	 = priv->head->dev;
 	drm_unique_t	 __user *argp = (void __user *)arg;
 	drm_unique_t	 u;
 
@@ -87,7 +87,7 @@
 		   unsigned int cmd, unsigned long arg)
 {
 	drm_file_t	 *priv	 = filp->private_data;
-	drm_device_t	 *dev	 = priv->dev;
+	drm_device_t	 *dev	 = priv->head->dev;
 	drm_unique_t	 u;
 	int		 domain, bus, slot, func, ret;
 
@@ -173,7 +173,7 @@
 		 unsigned int cmd, unsigned long arg )
 {
 	drm_file_t   *priv = filp->private_data;
-	drm_device_t *dev  = priv->dev;
+	drm_device_t *dev  = priv->head->dev;
 	drm_map_t    __user *argp = (void __user *)arg;
 	drm_map_t    map;
 	drm_map_list_t *r_list = NULL;
@@ -233,7 +233,7 @@
 		    unsigned int cmd, unsigned long arg )
 {
 	drm_file_t   *priv = filp->private_data;
-	drm_device_t *dev  = priv->dev;
+	drm_device_t *dev  = priv->head->dev;
 	drm_client_t __user *argp = (void __user *)arg;
 	drm_client_t client;
 	drm_file_t   *pt;
@@ -277,7 +277,7 @@
 		   unsigned int cmd, unsigned long arg )
 {
 	drm_file_t   *priv = filp->private_data;
-	drm_device_t *dev  = priv->dev;
+	drm_device_t *dev  = priv->head->dev;
 	drm_stats_t  stats;
 	int          i;
 
@@ -325,6 +325,8 @@
 	drm_version_t version;
 
 	DRM_COPY_FROM_USER_IOCTL(sv, argp, sizeof(sv));
+
+	memset(&version, 0, sizeof(version));
 
 	dev->driver->version(&version);
 	retv.drm_di_major = DRM_IF_MAJOR;
diff -Nru a/drivers/char/drm/drm_irq.c b/drivers/char/drm/drm_irq.c
--- a/drivers/char/drm/drm_irq.c	2005-03-11 12:51:47 -08:00
+++ b/drivers/char/drm/drm_irq.c	2005-03-11 12:51:47 -08:00
@@ -54,7 +54,7 @@
 		   unsigned int cmd, unsigned long arg)
 {
 	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev = priv->dev;
+	drm_device_t *dev = priv->head->dev;
 	drm_irq_busid_t __user *argp = (void __user *)arg;
 	drm_irq_busid_t p;
 
@@ -196,7 +196,7 @@
 		  unsigned int cmd, unsigned long arg )
 {
 	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev = priv->dev;
+	drm_device_t *dev = priv->head->dev;
 	drm_control_t ctl;
 	
 	/* if we haven't irq we fallback for compatibility reasons - this used to be a separate function in drm_dma.h */
@@ -243,7 +243,7 @@
 int drm_wait_vblank( DRM_IOCTL_ARGS )
 {
 	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev = priv->dev;
+	drm_device_t *dev = priv->head->dev;
 	drm_wait_vblank_t __user *argp = (void __user *)data;
 	drm_wait_vblank_t vblwait;
 	struct timeval now;
diff -Nru a/drivers/char/drm/drm_lock.c b/drivers/char/drm/drm_lock.c
--- a/drivers/char/drm/drm_lock.c	2005-03-11 12:51:52 -08:00
+++ b/drivers/char/drm/drm_lock.c	2005-03-11 12:51:52 -08:00
@@ -50,7 +50,7 @@
 	       unsigned int cmd, unsigned long arg )
 {
         drm_file_t *priv = filp->private_data;
-        drm_device_t *dev = priv->dev;
+        drm_device_t *dev = priv->head->dev;
         DECLARE_WAITQUEUE( entry, current );
         drm_lock_t lock;
         int ret = 0;
@@ -145,7 +145,7 @@
 		 unsigned int cmd, unsigned long arg )
 {
 	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev = priv->dev;
+	drm_device_t *dev = priv->head->dev;
 	drm_lock_t lock;
 
 	if ( copy_from_user( &lock, (drm_lock_t __user *)arg, sizeof(lock) ) )
diff -Nru a/drivers/char/drm/drm_memory.c b/drivers/char/drm/drm_memory.c
--- a/drivers/char/drm/drm_memory.c	2005-03-11 12:51:47 -08:00
+++ b/drivers/char/drm/drm_memory.c	2005-03-11 12:51:47 -08:00
@@ -155,9 +155,9 @@
 
 #if __OS_HAS_AGP
 /** Wrapper around agp_allocate_memory() */
-DRM_AGP_MEM *drm_alloc_agp(int pages, u32 type)
+DRM_AGP_MEM *drm_alloc_agp(struct agp_bridge_data *bridge, int pages, u32 type)
 {
-	return drm_agp_allocate_memory(pages, type);
+	return drm_agp_allocate_memory(bridge, pages, type);
 }
 
 /** Wrapper around agp_free_memory() */
diff -Nru a/drivers/char/drm/drm_os_linux.h b/drivers/char/drm/drm_os_linux.h
--- a/drivers/char/drm/drm_os_linux.h	2005-03-11 12:51:51 -08:00
+++ b/drivers/char/drm/drm_os_linux.h	2005-03-11 12:51:51 -08:00
@@ -35,7 +35,7 @@
 #define DRM_MEMORYBARRIER()		mb()
 /** DRM device local declaration */
 #define DRM_DEVICE	drm_file_t	*priv	= filp->private_data; \
-			drm_device_t	*dev	= priv->dev
+			drm_device_t	*dev	= priv->head->dev
 
 /** IRQ handler arguments and return type and values */
 #define DRM_IRQ_ARGS		int irq, void *arg, struct pt_regs *regs
diff -Nru a/drivers/char/drm/drm_pciids.h b/drivers/char/drm/drm_pciids.h
--- a/drivers/char/drm/drm_pciids.h	2005-03-11 12:51:43 -08:00
+++ b/drivers/char/drm/drm_pciids.h	2005-03-11 12:51:43 -08:00
@@ -65,7 +65,7 @@
 	{0x1002, 0x5963, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \
 	{0x1002, 0x5964, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \
 	{0x1002, 0x5968, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \
-	{0x1002, 0x5969, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \
+	{0x1002, 0x5969, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV100}, \
 	{0x1002, 0x596A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \
 	{0x1002, 0x596B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280}, \
 	{0x1002, 0x5c61, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RV280|CHIP_IS_MOBILITY}, \
diff -Nru a/drivers/char/drm/drm_proc.c b/drivers/char/drm/drm_proc.c
--- a/drivers/char/drm/drm_proc.c	2005-03-11 12:51:41 -08:00
+++ b/drivers/char/drm/drm_proc.c	2005-03-11 12:51:41 -08:00
@@ -175,10 +175,10 @@
 	*eof   = 0;
 
 	if (dev->unique) {
-		DRM_PROC_PRINT("%s 0x%lx %s\n",
-			       dev->driver->pci_driver.name, (long)old_encode_dev(dev->device), dev->unique);
+		DRM_PROC_PRINT("%s %s %s\n",
+			       dev->driver->pci_driver.name, pci_name(dev->pdev), dev->unique);
 	} else {
-		DRM_PROC_PRINT("%s 0x%lx\n", dev->driver->pci_driver.name, (long)old_encode_dev(dev->device));
+		DRM_PROC_PRINT("%s %s\n", dev->driver->pci_driver.name, pci_name(dev->pdev));
 	}
 
 	if (len > request + offset) return request;
diff -Nru a/drivers/char/drm/drm_scatter.c b/drivers/char/drm/drm_scatter.c
--- a/drivers/char/drm/drm_scatter.c	2005-03-11 12:51:47 -08:00
+++ b/drivers/char/drm/drm_scatter.c	2005-03-11 12:51:47 -08:00
@@ -65,7 +65,7 @@
 		   unsigned int cmd, unsigned long arg )
 {
 	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev = priv->dev;
+	drm_device_t *dev = priv->head->dev;
 	drm_scatter_gather_t __user *argp = (void __user *)arg;
 	drm_scatter_gather_t request;
 	drm_sg_mem_t *entry;
@@ -205,7 +205,7 @@
 		 unsigned int cmd, unsigned long arg )
 {
 	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev = priv->dev;
+	drm_device_t *dev = priv->head->dev;
 	drm_scatter_gather_t request;
 	drm_sg_mem_t *entry;
 
diff -Nru a/drivers/char/drm/drm_stub.c b/drivers/char/drm/drm_stub.c
--- a/drivers/char/drm/drm_stub.c	2005-03-11 12:51:52 -08:00
+++ b/drivers/char/drm/drm_stub.c	2005-03-11 12:51:52 -08:00
@@ -49,7 +49,7 @@
 module_param_named(cards_limit, drm_cards_limit, int, 0444);
 module_param_named(debug, drm_debug, int, 0666);
 
-drm_minor_t *drm_minors;
+drm_head_t **drm_heads;
 struct drm_sysfs_class *drm_class;
 struct proc_dir_entry *drm_proc_root;
 
@@ -91,7 +91,7 @@
 			goto error_out_unreg;
 
 	if (drm_core_has_AGP(dev)) {
-		dev->agp = drm_agp_init();
+		dev->agp = drm_agp_init(dev);
 		if (drm_core_check_feature(dev, DRIVER_REQUIRE_AGP) && (dev->agp == NULL)) {
 			DRM_ERROR( "Cannot initialize the agpgart module.\n" );
 			retcode = -EINVAL;
@@ -112,12 +112,6 @@
 		goto error_out_unreg;
 	}
 
-	dev->device = MKDEV(DRM_MAJOR, dev->minor );
-
-	/* postinit is a required function to display the signon banner */
-	if ((retcode = dev->driver->postinit(dev, ent->driver_data)))
-		goto error_out_unreg;
-
 	return 0;
 	
 error_out_unreg:
@@ -146,8 +140,10 @@
 	if (!((minor >= 0) && (minor < drm_cards_limit)))
 		return -ENODEV;
 
-	dev = drm_minors[minor].dev;
-	if (!dev)
+	if (!drm_heads[minor])
+		return -ENODEV;
+	
+	if (!(dev = drm_heads[minor]->dev))
 		return -ENODEV;
 
 	old_fops = filp->f_op;
@@ -161,10 +157,11 @@
 	return err;
 }
 
+
 /**
- * Get a device minor number.
+ * Register.
  *
- * \param pdev PCI device structure
+ * \param pdev - PCI device structure
  * \param ent entry from the PCI ID table with device type flags
  * \return zero on success or a negative number on failure.
  *
@@ -172,50 +169,86 @@
  * then register the character device and inter module information.
  * Try and register, if we fail to register, backout previous work.
  */
-int drm_probe(struct pci_dev *pdev, const struct pci_device_id *ent, struct drm_driver *driver)
+int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent,
+	      struct drm_driver *driver)
 {
-	struct class_device *dev_class;
 	drm_device_t *dev;
 	int ret;
-	int minor;
-	drm_minor_t *minors = &drm_minors[0];
 
 	DRM_DEBUG("\n");
 
-	for (minor = 0; minor < drm_cards_limit; minor++, minors++) {
-		if (minors->type == DRM_MINOR_FREE) {
+	dev = drm_calloc(1, sizeof(*dev), DRM_MEM_STUB);
+	if (!dev)
+		return -ENOMEM;
 
-			DRM_DEBUG("assigning minor %d\n", minor);
-			dev = drm_calloc(1, sizeof(*dev), DRM_MEM_STUB);
-			if (!dev)
-				return -ENOMEM;
+	pci_enable_device(pdev);
 
-			*minors = (drm_minor_t){.dev = dev, .type=DRM_MINOR_PRIMARY};
-			dev->minor = minor;
+	if ((ret = drm_fill_in_dev(dev, pdev, ent, driver))) {
+		printk(KERN_ERR "DRM: Fill_in_dev failed.\n");
+		goto err_g1;
+	}
+	if ((ret = drm_get_head(dev, &dev->primary)))
+		goto err_g1;
 
-			pci_enable_device(pdev);
+	/* postinit is a required function to display the signon banner */
+	/* drivers add secondary heads here if needed */
+	if ((ret = dev->driver->postinit(dev, ent->driver_data)))
+		goto err_g1;
 
-			if ((ret=drm_fill_in_dev(dev, pdev, ent, driver))) {
-				printk(KERN_ERR "DRM: Fill_in_dev failed.\n");
-				goto err_g1;
-			}
-			if ((ret = drm_proc_init(dev, minor, drm_proc_root, &minors->dev_root))) {
+	return 0;
+
+err_g1:
+	drm_free(dev, sizeof(*dev), DRM_MEM_STUB);
+	return ret;
+}
+EXPORT_SYMBOL(drm_get_dev);
+
+/**
+ * Get a secondary minor number.
+ *
+ * \param dev device data structure
+ * \param sec-minor structure to hold the assigned minor
+ * \return negative number on failure.
+ *
+ * Search an empty entry and initialize it to the given parameters, and
+ * create the proc init entry via proc_init(). This routines assigns
+ * minor numbers to secondary heads of multi-headed cards
+ */
+int drm_get_head(drm_device_t *dev, drm_head_t *head)
+{
+	drm_head_t **heads = drm_heads;
+	int ret;
+	int minor;
+
+	DRM_DEBUG("\n");
+
+	for (minor = 0; minor < drm_cards_limit; minor++, heads++) {
+		if (!*heads) {
+			
+			*head = (drm_head_t) {
+				.dev = dev,
+				.device = MKDEV(DRM_MAJOR, minor),
+				.minor = minor,
+			};
+			
+			if ((ret = drm_proc_init(dev, minor, drm_proc_root, &head->dev_root))) {
 				printk (KERN_ERR "DRM: Failed to initialize /proc/dri.\n");
 				goto err_g1;
 			}
 
 			
-			dev_class = drm_sysfs_device_add(drm_class,
-							 MKDEV(DRM_MAJOR,
-							       minor),
-							 &pdev->dev,
-							 "card%d", minor);
-			if (IS_ERR(dev_class)) {
+			head->dev_class = drm_sysfs_device_add(drm_class,
+							       MKDEV(DRM_MAJOR,
+								     minor),
+							       &dev->pdev->dev,
+							       "card%d", minor);
+			if (IS_ERR(head->dev_class)) {
 				printk(KERN_ERR "DRM: Error sysfs_device_add.\n");
-				ret = PTR_ERR(dev_class);
+				ret = PTR_ERR(head->dev_class);
 				goto err_g2;
 			}
-			
+			*heads = head;
+
 			DRM_DEBUG("new minor assigned %d\n", minor);
 			return 0;
 		}
@@ -223,36 +256,63 @@
 	DRM_ERROR("out of minors\n");
 	return -ENOMEM;
 err_g2:
-	drm_proc_cleanup(minor, drm_proc_root, minors->dev_root);
+	drm_proc_cleanup(minor, drm_proc_root, head->dev_root);
 err_g1:
-	*minors = (drm_minor_t){.dev = NULL, .type = DRM_MINOR_FREE};
-	drm_free(dev, sizeof(*dev), DRM_MEM_STUB);
+	*head = (drm_head_t) {.dev = NULL};
 	return ret;
 }
-EXPORT_SYMBOL(drm_probe);
 		
 
 /**
  * Put a device minor number.
  *
- * \param minor minor number.
- * \return always zero.
+ * \param dev device data structure
+ * \return always zero
  *
- * Cleans up the proc resources. If a minor is zero then release the foreign
- * "drm" data, otherwise unregisters the "drm" data, frees the stub list and
- * unregisters the character device. 
+ * Cleans up the proc resources. If it is the last minor then release the foreign
+ * "drm" data, otherwise unregisters the "drm" data, frees the dev list and
+ * unregisters the character device.
  */
-int drm_put_minor(drm_device_t *dev)
+int drm_put_dev(drm_device_t * dev)
 {
-	drm_minor_t *minors = &drm_minors[dev->minor];
+	DRM_DEBUG("release primary %s\n", dev->driver->pci_driver.name);
+
+	if (dev->unique) {
+		drm_free(dev->unique, strlen(dev->unique) + 1, DRM_MEM_DRIVER);
+		dev->unique = NULL;
+		dev->unique_len = 0;
+	}
+	if (dev->devname) {
+		drm_free(dev->devname, strlen(dev->devname) + 1,
+			 DRM_MEM_DRIVER);
+		dev->devname = NULL;
+	}
+	drm_free(dev, sizeof(*dev), DRM_MEM_STUB);
+	return 0;
+}
+
+/**
+ * Put a secondary minor number.
+ *
+ * \param sec_minor - structure to be released
+ * \return always zero
+ *
+ * Cleans up the proc resources. Not legal for this to be the
+ * last minor released.
+ *
+ */
+int drm_put_head(drm_head_t *head)
+{
+	int minor = head->minor;
 	
-	DRM_DEBUG("release minor %d\n", dev->minor);
+	DRM_DEBUG("release secondary minor %d\n", minor);
 	
-	drm_proc_cleanup(dev->minor, drm_proc_root, minors->dev_root);
-	drm_sysfs_device_remove(MKDEV(DRM_MAJOR, dev->minor));
+	drm_proc_cleanup(minor, drm_proc_root, head->dev_root);
+	drm_sysfs_device_remove(MKDEV(DRM_MAJOR, head->minor));
 	
-	*minors = (drm_minor_t){.dev = NULL, .type = DRM_MINOR_FREE};
-	drm_free(dev, sizeof(*dev), DRM_MEM_STUB);
+	*head = (drm_head_t){.dev = NULL};
+
+	drm_heads[minor] = NULL;
 	
 	return 0;
 }
diff -Nru a/drivers/char/drm/drm_vm.c b/drivers/char/drm/drm_vm.c
--- a/drivers/char/drm/drm_vm.c	2005-03-11 12:51:52 -08:00
+++ b/drivers/char/drm/drm_vm.c	2005-03-11 12:51:52 -08:00
@@ -54,7 +54,7 @@
 						 unsigned long address)
 {
 	drm_file_t *priv  = vma->vm_file->private_data;
-	drm_device_t *dev = priv->dev;
+	drm_device_t *dev = priv->head->dev;
 	drm_map_t *map    = NULL;
 	drm_map_list_t  *r_list;
 	struct list_head *list;
@@ -166,7 +166,7 @@
 void drm_vm_shm_close(struct vm_area_struct *vma)
 {
 	drm_file_t	*priv	= vma->vm_file->private_data;
-	drm_device_t	*dev	= priv->dev;
+	drm_device_t	*dev	= priv->head->dev;
 	drm_vma_entry_t *pt, *prev, *next;
 	drm_map_t *map;
 	drm_map_list_t *r_list;
@@ -246,7 +246,7 @@
 						     unsigned long address)
 {
 	drm_file_t	 *priv	 = vma->vm_file->private_data;
-	drm_device_t	 *dev	 = priv->dev;
+	drm_device_t	 *dev	 = priv->head->dev;
 	drm_device_dma_t *dma	 = dev->dma;
 	unsigned long	 offset;
 	unsigned long	 page_nr;
@@ -281,7 +281,7 @@
 {
 	drm_map_t        *map    = (drm_map_t *)vma->vm_private_data;
 	drm_file_t *priv = vma->vm_file->private_data;
-	drm_device_t *dev = priv->dev;
+	drm_device_t *dev = priv->head->dev;
 	drm_sg_mem_t *entry = dev->sg;
 	unsigned long offset;
 	unsigned long map_offset;
@@ -402,7 +402,7 @@
 void drm_vm_open(struct vm_area_struct *vma)
 {
 	drm_file_t	*priv	= vma->vm_file->private_data;
-	drm_device_t	*dev	= priv->dev;
+	drm_device_t	*dev	= priv->head->dev;
 	drm_vma_entry_t *vma_entry;
 
 	DRM_DEBUG("0x%08lx,0x%08lx\n",
@@ -431,7 +431,7 @@
 void drm_vm_close(struct vm_area_struct *vma)
 {
 	drm_file_t	*priv	= vma->vm_file->private_data;
-	drm_device_t	*dev	= priv->dev;
+	drm_device_t	*dev	= priv->head->dev;
 	drm_vma_entry_t *pt, *prev;
 
 	DRM_DEBUG("0x%08lx,0x%08lx\n",
@@ -471,7 +471,7 @@
 	unsigned long	 length	 = vma->vm_end - vma->vm_start;
 
 	lock_kernel();
-	dev	 = priv->dev;
+	dev	 = priv->head->dev;
 	dma	 = dev->dma;
 	DRM_DEBUG("start = 0x%lx, end = 0x%lx, offset = 0x%lx\n",
 		  vma->vm_start, vma->vm_end, VM_OFFSET(vma));
@@ -528,7 +528,7 @@
 int drm_mmap(struct file *filp, struct vm_area_struct *vma)
 {
 	drm_file_t	*priv	= filp->private_data;
-	drm_device_t	*dev	= priv->dev;
+	drm_device_t	*dev	= priv->head->dev;
 	drm_map_t	*map	= NULL;
 	drm_map_list_t  *r_list;
 	unsigned long   offset  = 0;
diff -Nru a/drivers/char/drm/i810_dma.c b/drivers/char/drm/i810_dma.c
--- a/drivers/char/drm/i810_dma.c	2005-03-11 12:51:42 -08:00
+++ b/drivers/char/drm/i810_dma.c	2005-03-11 12:51:42 -08:00
@@ -50,26 +50,6 @@
 #define up_write up
 #endif
 
-drm_ioctl_desc_t i810_ioctls[] = {
-	[DRM_IOCTL_NR(DRM_I810_INIT)]    = { i810_dma_init,    1, 1 },
-	[DRM_IOCTL_NR(DRM_I810_VERTEX)]  = { i810_dma_vertex,  1, 0 },
-	[DRM_IOCTL_NR(DRM_I810_CLEAR)]   = { i810_clear_bufs,  1, 0 },
-	[DRM_IOCTL_NR(DRM_I810_FLUSH)]   = { i810_flush_ioctl, 1, 0 },
-	[DRM_IOCTL_NR(DRM_I810_GETAGE)]  = { i810_getage,      1, 0 },
-	[DRM_IOCTL_NR(DRM_I810_GETBUF)]  = { i810_getbuf,      1, 0 },
-	[DRM_IOCTL_NR(DRM_I810_SWAP)]    = { i810_swap_bufs,   1, 0 },
-	[DRM_IOCTL_NR(DRM_I810_COPY)]    = { i810_copybuf,     1, 0 },
-	[DRM_IOCTL_NR(DRM_I810_DOCOPY)]  = { i810_docopy,      1, 0 },
-	[DRM_IOCTL_NR(DRM_I810_OV0INFO)] = { i810_ov0_info,    1, 0 },
-	[DRM_IOCTL_NR(DRM_I810_FSTATUS)] = { i810_fstatus,     1, 0 },
-	[DRM_IOCTL_NR(DRM_I810_OV0FLIP)] = { i810_ov0_flip,    1, 0 },
-	[DRM_IOCTL_NR(DRM_I810_MC)]      = { i810_dma_mc,      1, 1 },
-	[DRM_IOCTL_NR(DRM_I810_RSTATUS)] = { i810_rstatus,     1, 0 },
-	[DRM_IOCTL_NR(DRM_I810_FLIP)]    = { i810_flip_bufs,   1, 0 }
-};
-
-int i810_max_ioctl = DRM_ARRAY_SIZE(i810_ioctls);
-
 static drm_buf_t *i810_freelist_get(drm_device_t *dev)
 {
    	drm_device_dma_t *dma = dev->dma;
@@ -128,7 +108,7 @@
 	drm_i810_buf_priv_t *buf_priv;
 
 	lock_kernel();
-	dev	 = priv->dev;
+	dev	 = priv->head->dev;
 	dev_priv = dev->dev_private;
 	buf      = dev_priv->mmap_buffer;
 	buf_priv = buf->dev_private;
@@ -149,7 +129,7 @@
 static int i810_map_buffer(drm_buf_t *buf, struct file *filp)
 {
 	drm_file_t	  *priv	  = filp->private_data;
-	drm_device_t	  *dev	  = priv->dev;
+	drm_device_t	  *dev	  = priv->head->dev;
 	drm_i810_buf_priv_t *buf_priv = buf->dev_private;
       	drm_i810_private_t *dev_priv = dev->dev_private;
    	struct file_operations *old_fops;
@@ -229,7 +209,7 @@
 	return retcode;
 }
 
-int i810_dma_cleanup(drm_device_t *dev)
+static int i810_dma_cleanup(drm_device_t *dev)
 {
 	drm_device_dma_t *dma = dev->dma;
 
@@ -455,7 +435,7 @@
  *    If it isn't then we have a v1.1 client. Fix up params.
  *    If it is, then we have a 1.2 client... get the rest of the data.
  */
-int i810_dma_init_compat(drm_i810_init_t *init, unsigned long arg)
+static int i810_dma_init_compat(drm_i810_init_t *init, unsigned long arg)
 {
 
 	/* Get v1.1 init data */
@@ -487,11 +467,11 @@
 	return 0;
 }
 
-int i810_dma_init(struct inode *inode, struct file *filp,
+static int i810_dma_init(struct inode *inode, struct file *filp,
 		  unsigned int cmd, unsigned long arg)
 {
    	drm_file_t *priv = filp->private_data;
-   	drm_device_t *dev = priv->dev;
+   	drm_device_t *dev = priv->head->dev;
    	drm_i810_private_t *dev_priv;
    	drm_i810_init_t init;
    	int retcode = 0;
@@ -942,7 +922,7 @@
 
 }
 
-void i810_dma_quiescent(drm_device_t *dev)
+static void i810_dma_quiescent(drm_device_t *dev)
 {
       	drm_i810_private_t *dev_priv = dev->dev_private;
    	RING_LOCALS;
@@ -1027,7 +1007,7 @@
 		     unsigned int cmd, unsigned long arg)
 {
    	drm_file_t	  *priv	  = filp->private_data;
-   	drm_device_t	  *dev	  = priv->dev;
+   	drm_device_t	  *dev	  = priv->head->dev;
 
 	LOCK_TEST_WITH_RETURN(dev, filp);
 
@@ -1036,11 +1016,11 @@
 }
 
 
-int i810_dma_vertex(struct inode *inode, struct file *filp,
+static int i810_dma_vertex(struct inode *inode, struct file *filp,
 	       unsigned int cmd, unsigned long arg)
 {
 	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev = priv->dev;
+	drm_device_t *dev = priv->head->dev;
 	drm_device_dma_t *dma = dev->dma;
    	drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private;
       	u32 *hw_status = dev_priv->hw_status_page;
@@ -1073,11 +1053,11 @@
 
 
 
-int i810_clear_bufs(struct inode *inode, struct file *filp,
+static int i810_clear_bufs(struct inode *inode, struct file *filp,
 		   unsigned int cmd, unsigned long arg)
 {
 	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev = priv->dev;
+	drm_device_t *dev = priv->head->dev;
 	drm_i810_clear_t clear;
 
    	if (copy_from_user(&clear, (drm_i810_clear_t __user *)arg, sizeof(clear)))
@@ -1096,11 +1076,11 @@
    	return 0;
 }
 
-int i810_swap_bufs(struct inode *inode, struct file *filp,
+static int i810_swap_bufs(struct inode *inode, struct file *filp,
 		  unsigned int cmd, unsigned long arg)
 {
 	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev = priv->dev;
+	drm_device_t *dev = priv->head->dev;
 
 	DRM_DEBUG("i810_swap_bufs\n");
 
@@ -1110,11 +1090,11 @@
    	return 0;
 }
 
-int i810_getage(struct inode *inode, struct file *filp, unsigned int cmd,
+static int i810_getage(struct inode *inode, struct file *filp, unsigned int cmd,
 		unsigned long arg)
 {
    	drm_file_t	  *priv	    = filp->private_data;
-	drm_device_t	  *dev	    = priv->dev;
+	drm_device_t	  *dev	    = priv->head->dev;
    	drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private;
       	u32 *hw_status = dev_priv->hw_status_page;
    	drm_i810_sarea_t *sarea_priv = (drm_i810_sarea_t *)
@@ -1124,11 +1104,11 @@
 	return 0;
 }
 
-int i810_getbuf(struct inode *inode, struct file *filp, unsigned int cmd,
+static int i810_getbuf(struct inode *inode, struct file *filp, unsigned int cmd,
 		unsigned long arg)
 {
 	drm_file_t	  *priv	    = filp->private_data;
-	drm_device_t	  *dev	    = priv->dev;
+	drm_device_t	  *dev	    = priv->head->dev;
 	int		  retcode   = 0;
 	drm_i810_dma_t	  d;
    	drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private;
@@ -1155,17 +1135,15 @@
 	return retcode;
 }
 
-int i810_copybuf(struct inode *inode,
-		 struct file *filp, 
-		 unsigned int cmd,
-		 unsigned long arg)
+static int i810_copybuf(struct inode *inode,
+			 struct file *filp, unsigned int cmd, unsigned long arg)
 {
 	/* Never copy - 2.4.x doesn't need it */
 	return 0;
 }
 
-int i810_docopy(struct inode *inode, struct file *filp, unsigned int cmd,
-		unsigned long arg)
+static int i810_docopy(struct inode *inode, struct file *filp, unsigned int cmd,
+			unsigned long arg)
 {
 	/* Never copy - 2.4.x doesn't need it */
 	return 0;
@@ -1234,11 +1212,11 @@
 	ADVANCE_LP_RING();
 }
 
-int i810_dma_mc(struct inode *inode, struct file *filp,
+static int i810_dma_mc(struct inode *inode, struct file *filp,
 	unsigned int cmd, unsigned long arg)
 {
 	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev = priv->dev;
+	drm_device_t *dev = priv->head->dev;
 	drm_device_dma_t *dma = dev->dma;
 	drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private;
 	u32 *hw_status = dev_priv->hw_status_page;
@@ -1265,21 +1243,21 @@
 	return 0;
 }
 
-int i810_rstatus(struct inode *inode, struct file *filp,
-		unsigned int cmd, unsigned long arg)
+static int i810_rstatus(struct inode *inode, struct file *filp,
+			unsigned int cmd, unsigned long arg)
 {
 	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev = priv->dev;
+	drm_device_t *dev = priv->head->dev;
 	drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private;
 
 	return (int)(((u32 *)(dev_priv->hw_status_page))[4]);
 }
 
-int i810_ov0_info(struct inode *inode, struct file *filp,
-		unsigned int cmd, unsigned long arg)
+static int i810_ov0_info(struct inode *inode, struct file *filp,
+			unsigned int cmd, unsigned long arg)
 {
 	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev = priv->dev;
+	drm_device_t *dev = priv->head->dev;
 	drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private;
 	drm_i810_overlay_t data;
 
@@ -1290,11 +1268,11 @@
 	return 0;
 }
 
-int i810_fstatus(struct inode *inode, struct file *filp,
-		unsigned int cmd, unsigned long arg)
+static int i810_fstatus(struct inode *inode, struct file *filp,
+			unsigned int cmd, unsigned long arg)
 {
 	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev = priv->dev;
+	drm_device_t *dev = priv->head->dev;
 	drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private;
 
 	LOCK_TEST_WITH_RETURN(dev, filp);
@@ -1302,11 +1280,11 @@
 	return I810_READ(0x30008);
 }
 
-int i810_ov0_flip(struct inode *inode, struct file *filp,
-		unsigned int cmd, unsigned long arg)
+static int i810_ov0_flip(struct inode *inode, struct file *filp,
+			unsigned int cmd, unsigned long arg)
 {
 	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev = priv->dev;
+	drm_device_t *dev = priv->head->dev;
 	drm_i810_private_t *dev_priv = (drm_i810_private_t *)dev->dev_private;
 
 	LOCK_TEST_WITH_RETURN(dev, filp);
@@ -1330,7 +1308,7 @@
 	dev_priv->sarea_priv->pf_current_page = dev_priv->current_page;
 }
 
-int i810_do_cleanup_pageflip( drm_device_t *dev )
+static int i810_do_cleanup_pageflip( drm_device_t *dev )
 {
 	drm_i810_private_t *dev_priv = dev->dev_private;
 
@@ -1342,11 +1320,11 @@
 	return 0;
 }
 
-int i810_flip_bufs(struct inode *inode, struct file *filp,
-		   unsigned int cmd, unsigned long arg)
+static int i810_flip_bufs(struct inode *inode, struct file *filp,
+			unsigned int cmd, unsigned long arg)
 {
 	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev = priv->dev;
+	drm_device_t *dev = priv->head->dev;
 	drm_i810_private_t *dev_priv = dev->dev_private;
 
 	DRM_DEBUG("%s\n", __FUNCTION__);
@@ -1365,6 +1343,16 @@
 	i810_dma_cleanup( dev );
 }
 
+void i810_driver_prerelease(drm_device_t *dev, DRMFILE filp)
+{
+	if (dev->dev_private) {
+		drm_i810_private_t *dev_priv = dev->dev_private;
+		if (dev_priv->page_flipping) {
+			i810_do_cleanup_pageflip(dev);
+		}
+	}
+}
+
 void i810_driver_release(drm_device_t *dev, struct file *filp)
 {
 	i810_reclaim_buffers(dev, filp);
@@ -1376,4 +1364,22 @@
 	return 0;
 }
 
+drm_ioctl_desc_t i810_ioctls[] = {
+	[DRM_IOCTL_NR(DRM_I810_INIT)]    = { i810_dma_init,    1, 1 },
+	[DRM_IOCTL_NR(DRM_I810_VERTEX)]  = { i810_dma_vertex,  1, 0 },
+	[DRM_IOCTL_NR(DRM_I810_CLEAR)]   = { i810_clear_bufs,  1, 0 },
+	[DRM_IOCTL_NR(DRM_I810_FLUSH)]   = { i810_flush_ioctl, 1, 0 },
+	[DRM_IOCTL_NR(DRM_I810_GETAGE)]  = { i810_getage,      1, 0 },
+	[DRM_IOCTL_NR(DRM_I810_GETBUF)]  = { i810_getbuf,      1, 0 },
+	[DRM_IOCTL_NR(DRM_I810_SWAP)]    = { i810_swap_bufs,   1, 0 },
+	[DRM_IOCTL_NR(DRM_I810_COPY)]    = { i810_copybuf,     1, 0 },
+	[DRM_IOCTL_NR(DRM_I810_DOCOPY)]  = { i810_docopy,      1, 0 },
+	[DRM_IOCTL_NR(DRM_I810_OV0INFO)] = { i810_ov0_info,    1, 0 },
+	[DRM_IOCTL_NR(DRM_I810_FSTATUS)] = { i810_fstatus,     1, 0 },
+	[DRM_IOCTL_NR(DRM_I810_OV0FLIP)] = { i810_ov0_flip,    1, 0 },
+	[DRM_IOCTL_NR(DRM_I810_MC)]      = { i810_dma_mc,      1, 1 },
+	[DRM_IOCTL_NR(DRM_I810_RSTATUS)] = { i810_rstatus,     1, 0 },
+	[DRM_IOCTL_NR(DRM_I810_FLIP)]    = { i810_flip_bufs,   1, 0 }
+};
 
+int i810_max_ioctl = DRM_ARRAY_SIZE(i810_ioctls);
diff -Nru a/drivers/char/drm/i810_drv.c b/drivers/char/drm/i810_drv.c
--- a/drivers/char/drm/i810_drv.c	2005-03-11 12:51:51 -08:00
+++ b/drivers/char/drm/i810_drv.c	2005-03-11 12:51:51 -08:00
@@ -53,7 +53,7 @@
 		DRIVER_MINOR,
 		DRIVER_PATCHLEVEL,
 		DRIVER_DATE,
-		dev->minor,
+		dev->primary.minor,
 		pci_pretty_name(dev->pdev)
 		);
 	return 0;
@@ -83,6 +83,7 @@
 	.driver_features = DRIVER_USE_AGP | DRIVER_REQUIRE_AGP | DRIVER_USE_MTRR | DRIVER_HAVE_DMA | DRIVER_DMA_QUEUE,
 	.dev_priv_size = sizeof(drm_i810_buf_priv_t),
 	.pretakedown = i810_driver_pretakedown,
+	.prerelease = i810_driver_prerelease,
 	.release = i810_driver_release,
 	.dma_quiescent = i810_driver_dma_quiescent,
 	.reclaim_buffers = i810_reclaim_buffers,
diff -Nru a/drivers/char/drm/i810_drv.h b/drivers/char/drm/i810_drv.h
--- a/drivers/char/drm/i810_drv.h	2005-03-11 12:51:51 -08:00
+++ b/drivers/char/drm/i810_drv.h	2005-03-11 12:51:51 -08:00
@@ -114,57 +114,13 @@
 } drm_i810_private_t;
 
 				/* i810_dma.c */
-extern int  i810_dma_schedule(drm_device_t *dev, int locked);
-extern int  i810_getbuf(struct inode *inode, struct file *filp,
-			unsigned int cmd, unsigned long arg);
-extern int  i810_dma_init(struct inode *inode, struct file *filp,
-			  unsigned int cmd, unsigned long arg);
-extern int  i810_dma_cleanup(drm_device_t *dev);
-extern int  i810_flush_ioctl(struct inode *inode, struct file *filp,
-			     unsigned int cmd, unsigned long arg);
 extern void i810_reclaim_buffers(drm_device_t *dev, struct file *filp);
-extern int  i810_getage(struct inode *inode, struct file *filp,
-			unsigned int cmd, unsigned long arg);
 extern int i810_mmap_buffers(struct file *filp, struct vm_area_struct *vma);
 
-/* Obsolete:
- */
-extern int i810_copybuf(struct inode *inode, struct file *filp,
-			unsigned int cmd, unsigned long arg);
-/* Obsolete:
- */
-extern int i810_docopy(struct inode *inode, struct file *filp,
-		       unsigned int cmd, unsigned long arg);
-
-extern int i810_rstatus(struct inode *inode, struct file *filp,
-			unsigned int cmd, unsigned long arg);
-extern int i810_ov0_info(struct inode *inode, struct file *filp,
-			unsigned int cmd, unsigned long arg);
-extern int i810_fstatus(struct inode *inode, struct file *filp,
-			unsigned int cmd, unsigned long arg);
-extern int i810_ov0_flip(struct inode *inode, struct file *filp,
-			unsigned int cmd, unsigned long arg);
-extern int i810_dma_mc(struct inode *inode, struct file *filp,
-			unsigned int cmd, unsigned long arg);
-
-
-extern void i810_dma_quiescent(drm_device_t *dev);
-
-extern int i810_dma_vertex(struct inode *inode, struct file *filp,
-		    unsigned int cmd, unsigned long arg);
-
-extern int i810_swap_bufs(struct inode *inode, struct file *filp,
-		   unsigned int cmd, unsigned long arg);
-
-extern int i810_clear_bufs(struct inode *inode, struct file *filp,
-		    unsigned int cmd, unsigned long arg);
-
-extern int i810_flip_bufs(struct inode *inode, struct file *filp,
-		   unsigned int cmd, unsigned long arg);
-
 extern int i810_driver_dma_quiescent(drm_device_t *dev);
 extern void i810_driver_release(drm_device_t *dev, struct file *filp);
 extern void i810_driver_pretakedown(drm_device_t *dev);
+extern void i810_driver_prerelease(drm_device_t *dev, DRMFILE filp);
 
 #define I810_BASE(reg)		((unsigned long) \
 				dev_priv->mmio_map->handle)
diff -Nru a/drivers/char/drm/i830_dma.c b/drivers/char/drm/i830_dma.c
--- a/drivers/char/drm/i830_dma.c	2005-03-11 12:51:41 -08:00
+++ b/drivers/char/drm/i830_dma.c	2005-03-11 12:51:41 -08:00
@@ -52,42 +52,6 @@
 #define up_write up
 #endif
 
-drm_ioctl_desc_t i830_ioctls[] = {
-	[DRM_IOCTL_NR(DRM_I830_INIT)]     = { i830_dma_init,    1, 1 },
-	[DRM_IOCTL_NR(DRM_I830_VERTEX)]   = { i830_dma_vertex,  1, 0 },
-	[DRM_IOCTL_NR(DRM_I830_CLEAR)]    = { i830_clear_bufs,  1, 0 },
-	[DRM_IOCTL_NR(DRM_I830_FLUSH)]    = { i830_flush_ioctl, 1, 0 },
-	[DRM_IOCTL_NR(DRM_I830_GETAGE)]   = { i830_getage,      1, 0 },
-	[DRM_IOCTL_NR(DRM_I830_GETBUF)]   = { i830_getbuf,      1, 0 },
-	[DRM_IOCTL_NR(DRM_I830_SWAP)]     = { i830_swap_bufs,   1, 0 },
-	[DRM_IOCTL_NR(DRM_I830_COPY)]     = { i830_copybuf,     1, 0 },
-	[DRM_IOCTL_NR(DRM_I830_DOCOPY)]   = { i830_docopy,      1, 0 },
-	[DRM_IOCTL_NR(DRM_I830_FLIP)]     = { i830_flip_bufs,   1, 0 },
-	[DRM_IOCTL_NR(DRM_I830_IRQ_EMIT)] = { i830_irq_emit,    1, 0 },
-	[DRM_IOCTL_NR(DRM_I830_IRQ_WAIT)] = { i830_irq_wait,    1, 0 },
-	[DRM_IOCTL_NR(DRM_I830_GETPARAM)] = { i830_getparam,    1, 0 },
-	[DRM_IOCTL_NR(DRM_I830_SETPARAM)] = { i830_setparam,    1, 0 } 
-};
-
-int i830_max_ioctl = DRM_ARRAY_SIZE(i830_ioctls);
-
-static inline void i830_print_status_page(drm_device_t *dev)
-{
-   	drm_device_dma_t *dma = dev->dma;
-      	drm_i830_private_t *dev_priv = dev->dev_private;
-	u32 *temp = dev_priv->hw_status_page;
-   	int i;
-
-   	DRM_DEBUG(  "hw_status: Interrupt Status : %x\n", temp[0]);
-   	DRM_DEBUG(  "hw_status: LpRing Head ptr : %x\n", temp[1]);
-   	DRM_DEBUG(  "hw_status: IRing Head ptr : %x\n", temp[2]);
-      	DRM_DEBUG(  "hw_status: Reserved : %x\n", temp[3]);
-   	DRM_DEBUG(  "hw_status: Driver Counter : %d\n", temp[5]);
-   	for(i = 9; i < dma->buf_count + 9; i++) {
-	   	DRM_DEBUG( "buffer status idx : %d used: %d\n", i - 9, temp[i]);
-	}
-}
-
 static drm_buf_t *i830_freelist_get(drm_device_t *dev)
 {
    	drm_device_dma_t *dma = dev->dma;
@@ -146,7 +110,7 @@
 	drm_i830_buf_priv_t *buf_priv;
 
 	lock_kernel();
-	dev	 = priv->dev;
+	dev	 = priv->head->dev;
 	dev_priv = dev->dev_private;
 	buf      = dev_priv->mmap_buffer;
 	buf_priv = buf->dev_private;
@@ -167,7 +131,7 @@
 static int i830_map_buffer(drm_buf_t *buf, struct file *filp)
 {
 	drm_file_t	  *priv	  = filp->private_data;
-	drm_device_t	  *dev	  = priv->dev;
+	drm_device_t	  *dev	  = priv->head->dev;
 	drm_i830_buf_priv_t *buf_priv = buf->dev_private;
       	drm_i830_private_t *dev_priv = dev->dev_private;
    	struct file_operations *old_fops;
@@ -247,7 +211,7 @@
 	return retcode;
 }
 
-int i830_dma_cleanup(drm_device_t *dev)
+static int i830_dma_cleanup(drm_device_t *dev)
 {
 	drm_device_dma_t *dma = dev->dma;
 
@@ -479,11 +443,11 @@
    	return 0;
 }
 
-int i830_dma_init(struct inode *inode, struct file *filp,
+static int i830_dma_init(struct inode *inode, struct file *filp,
 		  unsigned int cmd, unsigned long arg)
 {
    	drm_file_t *priv = filp->private_data;
-   	drm_device_t *dev = priv->dev;
+   	drm_device_t *dev = priv->head->dev;
    	drm_i830_private_t *dev_priv;
    	drm_i830_init_t init;
    	int retcode = 0;
@@ -1252,7 +1216,7 @@
 }
 
 
-void i830_dma_quiescent(drm_device_t *dev)
+static void i830_dma_quiescent(drm_device_t *dev)
 {
       	drm_i830_private_t *dev_priv = dev->dev_private;
    	RING_LOCALS;
@@ -1329,11 +1293,11 @@
 	}
 }
 
-int i830_flush_ioctl(struct inode *inode, struct file *filp, 
-		     unsigned int cmd, unsigned long arg)
+static int i830_flush_ioctl(struct inode *inode, struct file *filp, 
+			     unsigned int cmd, unsigned long arg)
 {
    	drm_file_t	  *priv	  = filp->private_data;
-   	drm_device_t	  *dev	  = priv->dev;
+   	drm_device_t	  *dev	  = priv->head->dev;
 
 	LOCK_TEST_WITH_RETURN(dev, filp);
 
@@ -1341,11 +1305,11 @@
    	return 0;
 }
 
-int i830_dma_vertex(struct inode *inode, struct file *filp,
-	       unsigned int cmd, unsigned long arg)
+static int i830_dma_vertex(struct inode *inode, struct file *filp,
+		       unsigned int cmd, unsigned long arg)
 {
 	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev = priv->dev;
+	drm_device_t *dev = priv->head->dev;
 	drm_device_dma_t *dma = dev->dma;
    	drm_i830_private_t *dev_priv = (drm_i830_private_t *)dev->dev_private;
       	u32 *hw_status = dev_priv->hw_status_page;
@@ -1373,11 +1337,11 @@
 	return 0;
 }
 
-int i830_clear_bufs(struct inode *inode, struct file *filp,
-		   unsigned int cmd, unsigned long arg)
+static int i830_clear_bufs(struct inode *inode, struct file *filp,
+			   unsigned int cmd, unsigned long arg)
 {
 	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev = priv->dev;
+	drm_device_t *dev = priv->head->dev;
 	drm_i830_clear_t clear;
 
    	if (copy_from_user(&clear, (drm_i830_clear_t __user *)arg, sizeof(clear)))
@@ -1397,11 +1361,11 @@
    	return 0;
 }
 
-int i830_swap_bufs(struct inode *inode, struct file *filp,
-		  unsigned int cmd, unsigned long arg)
+static int i830_swap_bufs(struct inode *inode, struct file *filp,
+			  unsigned int cmd, unsigned long arg)
 {
 	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev = priv->dev;
+	drm_device_t *dev = priv->head->dev;
    
 	DRM_DEBUG("i830_swap_bufs\n");
 
@@ -1425,7 +1389,7 @@
 	dev_priv->sarea_priv->pf_current_page = dev_priv->current_page;
 }
 
-int i830_do_cleanup_pageflip( drm_device_t *dev )
+static int i830_do_cleanup_pageflip( drm_device_t *dev )
 {
 	drm_i830_private_t *dev_priv = dev->dev_private;
 
@@ -1437,11 +1401,11 @@
 	return 0;
 }
 
-int i830_flip_bufs(struct inode *inode, struct file *filp,
-		   unsigned int cmd, unsigned long arg)
+static int i830_flip_bufs(struct inode *inode, struct file *filp,
+			   unsigned int cmd, unsigned long arg)
 {
 	drm_file_t *priv = filp->private_data;
-	drm_device_t *dev = priv->dev;
+	drm_device_t *dev = priv->head->dev;
 	drm_i830_private_t *dev_priv = dev->dev_private;
 
 	DRM_DEBUG("%s\n", __FUNCTION__);
@@ -1455,11 +1419,11 @@
    	return 0;
 }
 
-int i830_getage(struct inode *inode, struct file *filp, unsigned int cmd,
-		unsigned long arg)
+static int i830_getage(struct inode *inode, struct file *filp, unsigned int cmd,
+			unsigned long arg)
 {
    	drm_file_t	  *priv	    = filp->private_data;
-	drm_device_t	  *dev	    = priv->dev;
+	drm_device_t	  *dev	    = priv->head->dev;
    	drm_i830_private_t *dev_priv = (drm_i830_private_t *)dev->dev_private;
       	u32 *hw_status = dev_priv->hw_status_page;
    	drm_i830_sarea_t *sarea_priv = (drm_i830_sarea_t *) 
@@ -1469,11 +1433,11 @@
 	return 0;
 }
 
-int i830_getbuf(struct inode *inode, struct file *filp, unsigned int cmd,
-		unsigned long arg)
+static int i830_getbuf(struct inode *inode, struct file *filp, unsigned int cmd,
+			unsigned long arg)
 {
 	drm_file_t	  *priv	    = filp->private_data;
-	drm_device_t	  *dev	    = priv->dev;
+	drm_device_t	  *dev	    = priv->head->dev;
 	int		  retcode   = 0;
 	drm_i830_dma_t	  d;
    	drm_i830_private_t *dev_priv = (drm_i830_private_t *)dev->dev_private;
@@ -1501,28 +1465,26 @@
 	return retcode;
 }
 
-int i830_copybuf(struct inode *inode,
-		 struct file *filp, 
-		 unsigned int cmd,
-		 unsigned long arg)
+static int i830_copybuf(struct inode *inode,
+			 struct file *filp, unsigned int cmd, unsigned long arg)
 {
 	/* Never copy - 2.4.x doesn't need it */
 	return 0;
 }
 
-int i830_docopy(struct inode *inode, struct file *filp, unsigned int cmd,
-		unsigned long arg)
+static int i830_docopy(struct inode *inode, struct file *filp, unsigned int cmd,
+			unsigned long arg)
 {
 	return 0;
 }
 
 
 
-int i830_getparam( struct inode *inode, struct file *filp, unsigned int cmd,
-		      unsigned long arg )
+static int i830_getparam( struct inode *inode, struct file *filp, 
+			unsigned int cmd, unsigned long arg )
 {
 	drm_file_t	  *priv	    = filp->private_data;
-	drm_device_t	  *dev	    = priv->dev;
+	drm_device_t	  *dev	    = priv->head->dev;
 	drm_i830_private_t *dev_priv = dev->dev_private;
 	drm_i830_getparam_t param;
 	int value;
@@ -1552,11 +1514,11 @@
 }
 
 
-int i830_setparam( struct inode *inode, struct file *filp, unsigned int cmd,
-		   unsigned long arg )
+static int i830_setparam( struct inode *inode, struct file *filp,
+			unsigned int cmd, unsigned long arg )
 {
 	drm_file_t	  *priv	    = filp->private_data;
-	drm_device_t	  *dev	    = priv->dev;
+	drm_device_t	  *dev	    = priv->head->dev;
 	drm_i830_private_t *dev_priv = dev->dev_private;
 	drm_i830_setparam_t param;
 
@@ -1585,6 +1547,16 @@
 	i830_dma_cleanup( dev );
 }
 
+void i830_driver_prerelease(drm_device_t *dev, DRMFILE filp)
+{
+	if (dev->dev_private) {
+		drm_i830_private_t *dev_priv = dev->dev_private;
+		if (dev_priv->page_flipping) {
+			i830_do_cleanup_pageflip(dev);
+		}
+	}
+}
+
 void i830_driver_release(drm_device_t *dev, struct file *filp)
 {
 	i830_reclaim_buffers(dev, filp);
@@ -1596,3 +1568,21 @@
 	return 0;
 }
 
+drm_ioctl_desc_t i830_ioctls[] = {
+	[DRM_IOCTL_NR(DRM_I830_INIT)]     = { i830_dma_init,    1, 1 },
+	[DRM_IOCTL_NR(DRM_I830_VERTEX)]   = { i830_dma_vertex,  1, 0 },
+	[DRM_IOCTL_NR(DRM_I830_CLEAR)]    = { i830_clear_bufs,  1, 0 },
+	[DRM_IOCTL_NR(DRM_I830_FLUSH)]    = { i830_flush_ioctl, 1, 0 },
+	[DRM_IOCTL_NR(DRM_I830_GETAGE)]   = { i830_getage,      1, 0 },
+	[DRM_IOCTL_NR(DRM_I830_GETBUF)]   = { i830_getbuf,      1, 0 },
+	[DRM_IOCTL_NR(DRM_I830_SWAP)]     = { i830_swap_bufs,   1, 0 },
+	[DRM_IOCTL_NR(DRM_I830_COPY)]     = { i830_copybuf,     1, 0 },
+	[DRM_IOCTL_NR(DRM_I830_DOCOPY)]   = { i830_docopy,      1, 0 },
+	[DRM_IOCTL_NR(DRM_I830_FLIP)]     = { i830_flip_bufs,   1, 0 },
+	[DRM_IOCTL_NR(DRM_I830_IRQ_EMIT)] = { i830_irq_emit,    1, 0 },
+	[DRM_IOCTL_NR(DRM_I830_IRQ_WAIT)] = { i830_irq_wait,    1, 0 },
+	[DRM_IOCTL_NR(DRM_I830_GETPARAM)] = { i830_getparam,    1, 0 },
+	[DRM_IOCTL_NR(DRM_I830_SETPARAM)] = { i830_setparam,    1, 0 } 
+};
+
+int i830_max_ioctl = DRM_ARRAY_SIZE(i830_ioctls);
diff -Nru a/drivers/char/drm/i830_drv.c b/drivers/char/drm/i830_drv.c
--- a/drivers/char/drm/i830_drv.c	2005-03-11 12:51:42 -08:00
+++ b/drivers/char/drm/i830_drv.c	2005-03-11 12:51:42 -08:00
@@ -54,7 +54,7 @@
 		DRIVER_MINOR,
 		DRIVER_PATCHLEVEL,
 		DRIVER_DATE,
-		dev->minor,
+		dev->primary.minor,
 		pci_pretty_name(dev->pdev)
 		);
 	return 0;
@@ -87,6 +87,7 @@
 #endif
 	.dev_priv_size = sizeof(drm_i830_buf_priv_t),
 	.pretakedown = i830_driver_pretakedown,
+	.prerelease = i830_driver_prerelease,
 	.release = i830_driver_release,
 	.dma_quiescent = i830_driver_dma_quiescent,
 	.reclaim_buffers = i830_reclaim_buffers,
diff -Nru a/drivers/char/drm/i830_drv.h b/drivers/char/drm/i830_drv.h
--- a/drivers/char/drm/i830_drv.h	2005-03-11 12:51:47 -08:00
+++ b/drivers/char/drm/i830_drv.h	2005-03-11 12:51:47 -08:00
@@ -120,51 +120,16 @@
 
 } drm_i830_private_t;
 
-				/* i830_dma.c */
-extern int  i830_dma_schedule(drm_device_t *dev, int locked);
-extern int  i830_getbuf(struct inode *inode, struct file *filp,
-			unsigned int cmd, unsigned long arg);
-extern int  i830_dma_init(struct inode *inode, struct file *filp,
-			  unsigned int cmd, unsigned long arg);
-extern int  i830_dma_cleanup(drm_device_t *dev);
-extern int  i830_flush_ioctl(struct inode *inode, struct file *filp,
-			     unsigned int cmd, unsigned long arg);
+/* i830_dma.c */
 extern void i830_reclaim_buffers(drm_device_t *dev, struct file *filp);
-extern int  i830_getage(struct inode *inode, struct file *filp, unsigned int cmd,
-			unsigned long arg);
-extern int i830_mmap_buffers(struct file *filp, struct vm_area_struct *vma);
-extern int i830_copybuf(struct inode *inode, struct file *filp, 
-			unsigned int cmd, unsigned long arg);
-extern int i830_docopy(struct inode *inode, struct file *filp, 
-		       unsigned int cmd, unsigned long arg);
-
-extern void i830_dma_quiescent(drm_device_t *dev);
-
-extern int i830_dma_vertex(struct inode *inode, struct file *filp,
-			  unsigned int cmd, unsigned long arg);
-
-extern int i830_swap_bufs(struct inode *inode, struct file *filp,
-			 unsigned int cmd, unsigned long arg);
-
-extern int i830_clear_bufs(struct inode *inode, struct file *filp,
-			  unsigned int cmd, unsigned long arg);
 
-extern int i830_flip_bufs(struct inode *inode, struct file *filp,
-			 unsigned int cmd, unsigned long arg);
-
-extern int i830_getparam( struct inode *inode, struct file *filp,
-			  unsigned int cmd, unsigned long arg );
-
-extern int i830_setparam( struct inode *inode, struct file *filp,
-			  unsigned int cmd, unsigned long arg );
+extern int i830_mmap_buffers(struct file *filp, struct vm_area_struct *vma);
 
 /* i830_irq.c */
 extern int i830_irq_emit( struct inode *inode, struct file *filp, 
 			  unsigned int cmd, unsigned long arg );
 extern int i830_irq_wait( struct inode *inode, struct file *filp,
 			  unsigned int cmd, unsigned long arg );
-extern int i830_wait_irq(drm_device_t *dev, int irq_nr);
-extern int i830_emit_irq(drm_device_t *dev);
 
 extern irqreturn_t i830_driver_irq_handler( DRM_IRQ_ARGS );
 extern void i830_driver_irq_preinstall( drm_device_t *dev );
@@ -173,6 +138,7 @@
 extern void i830_driver_pretakedown(drm_device_t *dev);
 extern void i830_driver_release(drm_device_t *dev, struct file *filp);
 extern int i830_driver_dma_quiescent(drm_device_t *dev);
+extern void i830_driver_prerelease(drm_device_t *dev, DRMFILE filp);
 
 #define I830_BASE(reg)		((unsigned long) \
 				dev_priv->mmio_map->handle)
diff -Nru a/drivers/char/drm/i830_irq.c b/drivers/char/drm/i830_irq.c
--- a/drivers/char/drm/i830_irq.c	2005-03-11 12:51:48 -08:00
+++ b/drivers/char/drm/i830_irq.c	2005-03-11 12:51:48 -08:00
@@ -123,7 +123,7 @@
 		   unsigned long arg )
 {
 	drm_file_t	  *priv	    = filp->private_data;
-	drm_device_t	  *dev	    = priv->dev;
+	drm_device_t	  *dev	    = priv->head->dev;
 	drm_i830_private_t *dev_priv = dev->dev_private;
 	drm_i830_irq_emit_t emit;
 	int result;
@@ -155,7 +155,7 @@
 		   unsigned long arg )
 {
 	drm_file_t	  *priv	    = filp->private_data;
-	drm_device_t	  *dev	    = priv->dev;
+	drm_device_t	  *dev	    = priv->head->dev;
 	drm_i830_private_t *dev_priv = dev->dev_private;
 	drm_i830_irq_wait_t irqwait;
 
diff -Nru a/drivers/char/drm/i915_drv.c b/drivers/char/drm/i915_drv.c
--- a/drivers/char/drm/i915_drv.c	2005-03-11 12:51:42 -08:00
+++ b/drivers/char/drm/i915_drv.c	2005-03-11 12:51:42 -08:00
@@ -29,7 +29,7 @@
 		DRIVER_MINOR,
 		DRIVER_PATCHLEVEL,
 		DRIVER_DATE,
-		dev->minor,
+		dev->primary.minor,
 		pci_pretty_name(dev->pdev)
 		);
 	return 0;
diff -Nru a/drivers/char/drm/mga_dma.c b/drivers/char/drm/mga_dma.c
--- a/drivers/char/drm/mga_dma.c	2005-03-11 12:51:51 -08:00
+++ b/drivers/char/drm/mga_dma.c	2005-03-11 12:51:51 -08:00
@@ -41,6 +41,7 @@
 #define MGA_DEFAULT_USEC_TIMEOUT	10000
 #define MGA_FREELIST_DEBUG		0
 
+static int mga_do_cleanup_dma( drm_device_t *dev );
 
 /* ================================================================
  * Engine control
@@ -68,25 +69,7 @@
 	return DRM_ERR(EBUSY);
 }
 
-int mga_do_dma_idle( drm_mga_private_t *dev_priv )
-{
-	u32 status = 0;
-	int i;
-	DRM_DEBUG( "\n" );
-
-	for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) {
-		status = MGA_READ( MGA_STATUS ) & MGA_DMA_IDLE_MASK;
-		if ( status == MGA_ENDPRDMASTS ) return 0;
-		DRM_UDELAY( 1 );
-	}
-
-#if MGA_DMA_DEBUG
-	DRM_ERROR( "failed! status=0x%08x\n", status );
-#endif
-	return DRM_ERR(EBUSY);
-}
-
-int mga_do_dma_reset( drm_mga_private_t *dev_priv )
+static int mga_do_dma_reset( drm_mga_private_t *dev_priv )
 {
 	drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
 	drm_mga_primary_buffer_t *primary = &dev_priv->prim;
@@ -110,44 +93,6 @@
 	return 0;
 }
 
-int mga_do_engine_reset( drm_mga_private_t *dev_priv )
-{
-	DRM_DEBUG( "\n" );
-
-	/* Okay, so we've completely screwed up and locked the engine.
-	 * How about we clean up after ourselves?
-	 */
-	MGA_WRITE( MGA_RST, MGA_SOFTRESET );
-	DRM_UDELAY( 15 );				/* Wait at least 10 usecs */
-	MGA_WRITE( MGA_RST, 0 );
-
-	/* Initialize the registers that get clobbered by the soft
-	 * reset.  Many of the core register values survive a reset,
-	 * but the drawing registers are basically all gone.
-	 *
-	 * 3D clients should probably die after calling this.  The X
-	 * server should reset the engine state to known values.
-	 */
-#if 0
-	MGA_WRITE( MGA_PRIMPTR,
-		   virt_to_bus((void *)dev_priv->prim.status_page) |
-		   MGA_PRIMPTREN0 |
-		   MGA_PRIMPTREN1 );
-#endif
-
-	MGA_WRITE( MGA_ICLEAR, MGA_SOFTRAPICLR );
-	MGA_WRITE( MGA_IEN,    MGA_SOFTRAPIEN );
-
-	/* The primary DMA stream should look like new right about now.
-	 */
-	mga_do_dma_reset( dev_priv );
-
-	/* This bad boy will never fail.
-	 */
-	return 0;
-}
-
-
 /* ================================================================
  * Primary DMA stream
  */
@@ -625,7 +570,7 @@
 	return 0;
 }
 
-int mga_do_cleanup_dma( drm_device_t *dev )
+static int mga_do_cleanup_dma( drm_device_t *dev )
 {
 	DRM_DEBUG( "\n" );
 
diff -Nru a/drivers/char/drm/mga_drv.c b/drivers/char/drm/mga_drv.c
--- a/drivers/char/drm/mga_drv.c	2005-03-11 12:51:42 -08:00
+++ b/drivers/char/drm/mga_drv.c	2005-03-11 12:51:42 -08:00
@@ -51,7 +51,7 @@
 		DRIVER_MINOR,
 		DRIVER_PATCHLEVEL,
 		DRIVER_DATE,
-		dev->minor,
+		dev->primary.minor,
 		pci_pretty_name(dev->pdev)
 		);
 	return 0;
diff -Nru a/drivers/char/drm/mga_drv.h b/drivers/char/drm/mga_drv.h
--- a/drivers/char/drm/mga_drv.h	2005-03-11 12:51:51 -08:00
+++ b/drivers/char/drm/mga_drv.h	2005-03-11 12:51:51 -08:00
@@ -121,25 +121,12 @@
 extern int mga_driver_dma_quiescent(drm_device_t *dev);
 
 extern int mga_do_wait_for_idle( drm_mga_private_t *dev_priv );
-extern int mga_do_dma_idle( drm_mga_private_t *dev_priv );
-extern int mga_do_dma_reset( drm_mga_private_t *dev_priv );
-extern int mga_do_engine_reset( drm_mga_private_t *dev_priv );
-extern int mga_do_cleanup_dma( drm_device_t *dev );
 
 extern void mga_do_dma_flush( drm_mga_private_t *dev_priv );
 extern void mga_do_dma_wrap_start( drm_mga_private_t *dev_priv );
 extern void mga_do_dma_wrap_end( drm_mga_private_t *dev_priv );
 
 extern int mga_freelist_put( drm_device_t *dev, drm_buf_t *buf );
-
-				/* mga_state.c */
-extern int  mga_dma_clear( DRM_IOCTL_ARGS );
-extern int  mga_dma_swap( DRM_IOCTL_ARGS );
-extern int  mga_dma_vertex( DRM_IOCTL_ARGS );
-extern int  mga_dma_indices( DRM_IOCTL_ARGS );
-extern int  mga_dma_iload( DRM_IOCTL_ARGS );
-extern int  mga_dma_blit( DRM_IOCTL_ARGS );
-extern int  mga_getparam( DRM_IOCTL_ARGS );
 
 				/* mga_warp.c */
 extern int mga_warp_install_microcode( drm_mga_private_t *dev_priv );
diff -Nru a/drivers/char/drm/mga_state.c b/drivers/char/drm/mga_state.c
--- a/drivers/char/drm/mga_state.c	2005-03-11 12:51:42 -08:00
+++ b/drivers/char/drm/mga_state.c	2005-03-11 12:51:42 -08:00
@@ -37,21 +37,6 @@
 #include "mga_drm.h"
 #include "mga_drv.h"
 
-drm_ioctl_desc_t mga_ioctls[] = {
-	[DRM_IOCTL_NR(DRM_MGA_INIT)]    = { mga_dma_init,    1, 1 },
-	[DRM_IOCTL_NR(DRM_MGA_FLUSH)]   = { mga_dma_flush,   1, 0 },
-	[DRM_IOCTL_NR(DRM_MGA_RESET)]   = { mga_dma_reset,   1, 0 },
-	[DRM_IOCTL_NR(DRM_MGA_SWAP)]    = { mga_dma_swap,    1, 0 },
-	[DRM_IOCTL_NR(DRM_MGA_CLEAR)]   = { mga_dma_clear,   1, 0 },
-	[DRM_IOCTL_NR(DRM_MGA_VERTEX)]  = { mga_dma_vertex,  1, 0 },
-	[DRM_IOCTL_NR(DRM_MGA_INDICES)] = { mga_dma_indices, 1, 0 },
-	[DRM_IOCTL_NR(DRM_MGA_ILOAD)]   = { mga_dma_iload,   1, 0 },
-	[DRM_IOCTL_NR(DRM_MGA_BLIT)]    = { mga_dma_blit,    1, 0 },
-	[DRM_IOCTL_NR(DRM_MGA_GETPARAM)]= { mga_getparam,    1, 0 },
-};
-
-int mga_max_ioctl = DRM_ARRAY_SIZE(mga_ioctls);
-
 /* ================================================================
  * DMA hardware state programming functions
  */
@@ -893,7 +878,7 @@
  *
  */
 
-int mga_dma_clear( DRM_IOCTL_ARGS )
+static int mga_dma_clear( DRM_IOCTL_ARGS )
 {
 	DRM_DEVICE;
 	drm_mga_private_t *dev_priv = dev->dev_private;
@@ -918,7 +903,7 @@
 	return 0;
 }
 
-int mga_dma_swap( DRM_IOCTL_ARGS )
+static int mga_dma_swap( DRM_IOCTL_ARGS )
 {
 	DRM_DEVICE;
 	drm_mga_private_t *dev_priv = dev->dev_private;
@@ -940,7 +925,7 @@
 	return 0;
 }
 
-int mga_dma_vertex( DRM_IOCTL_ARGS )
+static int mga_dma_vertex( DRM_IOCTL_ARGS )
 {
 	DRM_DEVICE;
 	drm_mga_private_t *dev_priv = dev->dev_private;
@@ -979,7 +964,7 @@
 	return 0;
 }
 
-int mga_dma_indices( DRM_IOCTL_ARGS )
+static int mga_dma_indices( DRM_IOCTL_ARGS )
 {
 	DRM_DEVICE;
 	drm_mga_private_t *dev_priv = dev->dev_private;
@@ -1018,7 +1003,7 @@
 	return 0;
 }
 
-int mga_dma_iload( DRM_IOCTL_ARGS )
+static int mga_dma_iload( DRM_IOCTL_ARGS )
 {
 	DRM_DEVICE;
 	drm_device_dma_t *dma = dev->dma;
@@ -1060,7 +1045,7 @@
 	return 0;
 }
 
-int mga_dma_blit( DRM_IOCTL_ARGS )
+static int mga_dma_blit( DRM_IOCTL_ARGS )
 {
 	DRM_DEVICE;
 	drm_mga_private_t *dev_priv = dev->dev_private;
@@ -1089,7 +1074,7 @@
 	return 0;
 }
 
-int mga_getparam( DRM_IOCTL_ARGS )
+static int mga_getparam( DRM_IOCTL_ARGS )
 {
 	DRM_DEVICE;
 	drm_mga_private_t *dev_priv = dev->dev_private;
@@ -1121,3 +1106,18 @@
 	
 	return 0;
 }
+
+drm_ioctl_desc_t mga_ioctls[] = {
+	[DRM_IOCTL_NR(DRM_MGA_INIT)]    = { mga_dma_init,    1, 1 },
+	[DRM_IOCTL_NR(DRM_MGA_FLUSH)]   = { mga_dma_flush,   1, 0 },
+	[DRM_IOCTL_NR(DRM_MGA_RESET)]   = { mga_dma_reset,   1, 0 },
+	[DRM_IOCTL_NR(DRM_MGA_SWAP)]    = { mga_dma_swap,    1, 0 },
+	[DRM_IOCTL_NR(DRM_MGA_CLEAR)]   = { mga_dma_clear,   1, 0 },
+	[DRM_IOCTL_NR(DRM_MGA_VERTEX)]  = { mga_dma_vertex,  1, 0 },
+	[DRM_IOCTL_NR(DRM_MGA_INDICES)] = { mga_dma_indices, 1, 0 },
+	[DRM_IOCTL_NR(DRM_MGA_ILOAD)]   = { mga_dma_iload,   1, 0 },
+	[DRM_IOCTL_NR(DRM_MGA_BLIT)]    = { mga_dma_blit,    1, 0 },
+	[DRM_IOCTL_NR(DRM_MGA_GETPARAM)]= { mga_getparam,    1, 0 },
+};
+
+int mga_max_ioctl = DRM_ARRAY_SIZE(mga_ioctls);
diff -Nru a/drivers/char/drm/r128_cce.c b/drivers/char/drm/r128_cce.c
--- a/drivers/char/drm/r128_cce.c	2005-03-11 12:51:41 -08:00
+++ b/drivers/char/drm/r128_cce.c	2005-03-11 12:51:41 -08:00
@@ -80,7 +80,7 @@
 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
 };
 
-int R128_READ_PLL(drm_device_t *dev, int addr)
+static int R128_READ_PLL(drm_device_t *dev, int addr)
 {
 	drm_r128_private_t *dev_priv = dev->dev_private;
 
@@ -808,7 +808,7 @@
 }
 #endif
 
-drm_buf_t *r128_freelist_get( drm_device_t *dev )
+static drm_buf_t *r128_freelist_get( drm_device_t *dev )
 {
 	drm_device_dma_t *dma = dev->dma;
 	drm_r128_private_t *dev_priv = dev->dev_private;
diff -Nru a/drivers/char/drm/r128_drv.c b/drivers/char/drm/r128_drv.c
--- a/drivers/char/drm/r128_drv.c	2005-03-11 12:51:42 -08:00
+++ b/drivers/char/drm/r128_drv.c	2005-03-11 12:51:42 -08:00
@@ -45,7 +45,7 @@
 		DRIVER_MINOR,
 		DRIVER_PATCHLEVEL,
 		DRIVER_DATE,
-		dev->minor,
+		dev->primary.minor,
 		pci_pretty_name(dev->pdev)
 		);
 	return 0;
diff -Nru a/drivers/char/drm/r128_drv.h b/drivers/char/drm/r128_drv.h
--- a/drivers/char/drm/r128_drv.h	2005-03-11 12:51:52 -08:00
+++ b/drivers/char/drm/r128_drv.h	2005-03-11 12:51:52 -08:00
@@ -139,27 +139,13 @@
 extern int r128_engine_reset( DRM_IOCTL_ARGS );
 extern int r128_fullscreen( DRM_IOCTL_ARGS );
 extern int r128_cce_buffers( DRM_IOCTL_ARGS );
-extern int r128_getparam( DRM_IOCTL_ARGS );
 
 extern void r128_freelist_reset( drm_device_t *dev );
-extern drm_buf_t *r128_freelist_get( drm_device_t *dev );
 
 extern int r128_wait_ring( drm_r128_private_t *dev_priv, int n );
 
 extern int r128_do_cce_idle( drm_r128_private_t *dev_priv );
 extern int r128_do_cleanup_cce( drm_device_t *dev );
-extern int r128_do_cleanup_pageflip( drm_device_t *dev );
-
-				/* r128_state.c */
-extern int r128_cce_clear( DRM_IOCTL_ARGS );
-extern int r128_cce_swap( DRM_IOCTL_ARGS );
-extern int r128_cce_flip( DRM_IOCTL_ARGS );
-extern int r128_cce_vertex( DRM_IOCTL_ARGS );
-extern int r128_cce_indices( DRM_IOCTL_ARGS );
-extern int r128_cce_blit( DRM_IOCTL_ARGS );
-extern int r128_cce_depth( DRM_IOCTL_ARGS );
-extern int r128_cce_stipple( DRM_IOCTL_ARGS );
-extern int r128_cce_indirect( DRM_IOCTL_ARGS );
 
 extern int r128_driver_vblank_wait(drm_device_t *dev, unsigned int *sequence);
 
@@ -405,8 +391,6 @@
 		    ((addr) & 0x1f) | R128_PLL_WR_EN);			\
 	R128_WRITE(R128_CLOCK_CNTL_DATA, (val));			\
 } while (0)
-
-extern int R128_READ_PLL(drm_device_t *dev, int addr);
 
 
 #define CCE_PACKET0( reg, n )		(R128_CCE_PACKET0 |		\
diff -Nru a/drivers/char/drm/r128_state.c b/drivers/char/drm/r128_state.c
--- a/drivers/char/drm/r128_state.c	2005-03-11 12:51:41 -08:00
+++ b/drivers/char/drm/r128_state.c	2005-03-11 12:51:41 -08:00
@@ -32,27 +32,6 @@
 #include "r128_drm.h"
 #include "r128_drv.h"
 
-drm_ioctl_desc_t r128_ioctls[] = {
-	[DRM_IOCTL_NR(DRM_R128_INIT)]       = { r128_cce_init,     1, 1 },
-	[DRM_IOCTL_NR(DRM_R128_CCE_START)]  = { r128_cce_start,    1, 1 },
-	[DRM_IOCTL_NR(DRM_R128_CCE_STOP)]   = { r128_cce_stop,     1, 1 },
-	[DRM_IOCTL_NR(DRM_R128_CCE_RESET)]  = { r128_cce_reset,    1, 1 },
-	[DRM_IOCTL_NR(DRM_R128_CCE_IDLE)]   = { r128_cce_idle,     1, 0 },
-	[DRM_IOCTL_NR(DRM_R128_RESET)]      = { r128_engine_reset, 1, 0 },
-	[DRM_IOCTL_NR(DRM_R128_FULLSCREEN)] = { r128_fullscreen,   1, 0 },
-	[DRM_IOCTL_NR(DRM_R128_SWAP)]       = { r128_cce_swap,     1, 0 },
-	[DRM_IOCTL_NR(DRM_R128_FLIP)]       = { r128_cce_flip,     1, 0 },
-	[DRM_IOCTL_NR(DRM_R128_CLEAR)]      = { r128_cce_clear,    1, 0 },
-	[DRM_IOCTL_NR(DRM_R128_VERTEX)]     = { r128_cce_vertex,   1, 0 },
-	[DRM_IOCTL_NR(DRM_R128_INDICES)]    = { r128_cce_indices,  1, 0 },
-	[DRM_IOCTL_NR(DRM_R128_BLIT)]       = { r128_cce_blit,     1, 0 },
-	[DRM_IOCTL_NR(DRM_R128_DEPTH)]      = { r128_cce_depth,    1, 0 },
-	[DRM_IOCTL_NR(DRM_R128_STIPPLE)]    = { r128_cce_stipple,  1, 0 },
-	[DRM_IOCTL_NR(DRM_R128_INDIRECT)]   = { r128_cce_indirect, 1, 1 },
-	[DRM_IOCTL_NR(DRM_R128_GETPARAM)]   = { r128_getparam, 1, 0 },
-};
-
-int r128_max_ioctl = DRM_ARRAY_SIZE(r128_ioctls);
 
 /* ================================================================
  * CCE hardware state programming functions
@@ -1281,7 +1260,7 @@
  * IOCTL functions
  */
 
-int r128_cce_clear( DRM_IOCTL_ARGS )
+static int r128_cce_clear( DRM_IOCTL_ARGS )
 {
 	DRM_DEVICE;
 	drm_r128_private_t *dev_priv = dev->dev_private;
@@ -1349,7 +1328,7 @@
  * They can & should be intermixed to support multiple 3d windows.  
  */
 
-int r128_cce_flip( DRM_IOCTL_ARGS )
+static int r128_cce_flip( DRM_IOCTL_ARGS )
 {
 	DRM_DEVICE;
 	drm_r128_private_t *dev_priv = dev->dev_private;
@@ -1368,7 +1347,7 @@
 	return 0;
 }
 
-int r128_cce_swap( DRM_IOCTL_ARGS )
+static int r128_cce_swap( DRM_IOCTL_ARGS )
 {
 	DRM_DEVICE;
 	drm_r128_private_t *dev_priv = dev->dev_private;
@@ -1390,7 +1369,7 @@
 	return 0;
 }
 
-int r128_cce_vertex( DRM_IOCTL_ARGS )
+static int r128_cce_vertex( DRM_IOCTL_ARGS )
 {
 	DRM_DEVICE;
 	drm_r128_private_t *dev_priv = dev->dev_private;
@@ -1450,7 +1429,7 @@
 	return 0;
 }
 
-int r128_cce_indices( DRM_IOCTL_ARGS )
+static int r128_cce_indices( DRM_IOCTL_ARGS )
 {
 	DRM_DEVICE;
 	drm_r128_private_t *dev_priv = dev->dev_private;
@@ -1522,7 +1501,7 @@
 	return 0;
 }
 
-int r128_cce_blit( DRM_IOCTL_ARGS )
+static int r128_cce_blit( DRM_IOCTL_ARGS )
 {
 	DRM_DEVICE;
 	drm_device_dma_t *dma = dev->dma;
@@ -1552,7 +1531,7 @@
 	return ret;
 }
 
-int r128_cce_depth( DRM_IOCTL_ARGS )
+static int r128_cce_depth( DRM_IOCTL_ARGS )
 {
 	DRM_DEVICE;
 	drm_r128_private_t *dev_priv = dev->dev_private;
@@ -1582,7 +1561,7 @@
 	return ret;
 }
 
-int r128_cce_stipple( DRM_IOCTL_ARGS )
+static int r128_cce_stipple( DRM_IOCTL_ARGS )
 {
 	DRM_DEVICE;
 	drm_r128_private_t *dev_priv = dev->dev_private;
@@ -1606,7 +1585,7 @@
 	return 0;
 }
 
-int r128_cce_indirect( DRM_IOCTL_ARGS )
+static int r128_cce_indirect( DRM_IOCTL_ARGS )
 {
 	DRM_DEVICE;
 	drm_r128_private_t *dev_priv = dev->dev_private;
@@ -1682,7 +1661,7 @@
 	return 0;
 }
 
-int r128_getparam( DRM_IOCTL_ARGS )
+static int r128_getparam( DRM_IOCTL_ARGS )
 {
 	DRM_DEVICE;
 	drm_r128_private_t *dev_priv = dev->dev_private;
@@ -1730,3 +1709,24 @@
 	r128_do_cleanup_cce( dev );
 }
 
+drm_ioctl_desc_t r128_ioctls[] = {
+	[DRM_IOCTL_NR(DRM_R128_INIT)]       = { r128_cce_init,     1, 1 },
+	[DRM_IOCTL_NR(DRM_R128_CCE_START)]  = { r128_cce_start,    1, 1 },
+	[DRM_IOCTL_NR(DRM_R128_CCE_STOP)]   = { r128_cce_stop,     1, 1 },
+	[DRM_IOCTL_NR(DRM_R128_CCE_RESET)]  = { r128_cce_reset,    1, 1 },
+	[DRM_IOCTL_NR(DRM_R128_CCE_IDLE)]   = { r128_cce_idle,     1, 0 },
+	[DRM_IOCTL_NR(DRM_R128_RESET)]      = { r128_engine_reset, 1, 0 },
+	[DRM_IOCTL_NR(DRM_R128_FULLSCREEN)] = { r128_fullscreen,   1, 0 },
+	[DRM_IOCTL_NR(DRM_R128_SWAP)]       = { r128_cce_swap,     1, 0 },
+	[DRM_IOCTL_NR(DRM_R128_FLIP)]       = { r128_cce_flip,     1, 0 },
+	[DRM_IOCTL_NR(DRM_R128_CLEAR)]      = { r128_cce_clear,    1, 0 },
+	[DRM_IOCTL_NR(DRM_R128_VERTEX)]     = { r128_cce_vertex,   1, 0 },
+	[DRM_IOCTL_NR(DRM_R128_INDICES)]    = { r128_cce_indices,  1, 0 },
+	[DRM_IOCTL_NR(DRM_R128_BLIT)]       = { r128_cce_blit,     1, 0 },
+	[DRM_IOCTL_NR(DRM_R128_DEPTH)]      = { r128_cce_depth,    1, 0 },
+	[DRM_IOCTL_NR(DRM_R128_STIPPLE)]    = { r128_cce_stipple,  1, 0 },
+	[DRM_IOCTL_NR(DRM_R128_INDIRECT)]   = { r128_cce_indirect, 1, 1 },
+	[DRM_IOCTL_NR(DRM_R128_GETPARAM)]   = { r128_getparam, 1, 0 },
+};
+
+int r128_max_ioctl = DRM_ARRAY_SIZE(r128_ioctls);
diff -Nru a/drivers/char/drm/radeon_cp.c b/drivers/char/drm/radeon_cp.c
--- a/drivers/char/drm/radeon_cp.c	2005-03-11 12:51:41 -08:00
+++ b/drivers/char/drm/radeon_cp.c	2005-03-11 12:51:41 -08:00
@@ -35,6 +35,7 @@
 
 #define RADEON_FIFO_DEBUG	0
 
+static int radeon_do_cleanup_cp( drm_device_t *dev );
 
 /* CP microcode (from ATI) */
 static u32 R200_cp_microcode[][2] = {
@@ -815,7 +816,7 @@
 	{ 0000000000, 0000000000 },
 };
 
-int RADEON_READ_PLL(drm_device_t *dev, int addr)
+static int RADEON_READ_PLL(drm_device_t *dev, int addr)
 {
 	drm_radeon_private_t *dev_priv = dev->dev_private;
 
@@ -1538,7 +1539,7 @@
 	return 0;
 }
 
-int radeon_do_cleanup_cp( drm_device_t *dev )
+static int radeon_do_cleanup_cp( drm_device_t *dev )
 {
 	drm_radeon_private_t *dev_priv = dev->dev_private;
 	DRM_DEBUG( "\n" );
diff -Nru a/drivers/char/drm/radeon_drm.h b/drivers/char/drm/radeon_drm.h
--- a/drivers/char/drm/radeon_drm.h	2005-03-11 12:51:47 -08:00
+++ b/drivers/char/drm/radeon_drm.h	2005-03-11 12:51:47 -08:00
@@ -146,8 +146,13 @@
 #define RADEON_EMIT_PP_TEX_SIZE_2                   75
 #define R200_EMIT_RB3D_BLENDCOLOR                   76
 #define R200_EMIT_TCL_POINT_SPRITE_CNTL             77
-#define RADEON_MAX_STATE_PACKETS                    78
-
+#define RADEON_EMIT_PP_CUBIC_FACES_0                78
+#define RADEON_EMIT_PP_CUBIC_OFFSETS_T0             79
+#define RADEON_EMIT_PP_CUBIC_FACES_1                80
+#define RADEON_EMIT_PP_CUBIC_OFFSETS_T1             81
+#define RADEON_EMIT_PP_CUBIC_FACES_2                82
+#define RADEON_EMIT_PP_CUBIC_OFFSETS_T2             83
+#define RADEON_MAX_STATE_PACKETS                    84
 
 /* Commands understood by cmd_buffer ioctl.  More can be added but
  * obviously these can't be removed or changed:
diff -Nru a/drivers/char/drm/radeon_drv.c b/drivers/char/drm/radeon_drv.c
--- a/drivers/char/drm/radeon_drv.c	2005-03-11 12:51:47 -08:00
+++ b/drivers/char/drm/radeon_drv.c	2005-03-11 12:51:47 -08:00
@@ -46,7 +46,7 @@
 		DRIVER_MINOR,
 		DRIVER_PATCHLEVEL,
 		DRIVER_DATE,
-		dev->minor,
+		dev->primary.minor,
 		pci_pretty_name(dev->pdev)
 		);
 	return 0;
diff -Nru a/drivers/char/drm/radeon_drv.h b/drivers/char/drm/radeon_drv.h
--- a/drivers/char/drm/radeon_drv.h	2005-03-11 12:51:46 -08:00
+++ b/drivers/char/drm/radeon_drv.h	2005-03-11 12:51:46 -08:00
@@ -78,9 +78,11 @@
  *     - Add hyperz support, add hyperz flags to clear ioctl.
  * 1.14- Add support for color tiling
  *     - Add R100/R200 surface allocation/free support
+ * 1.15- Add support for texture micro tiling
+ *     - Add support for r100 cube maps
  */
 #define DRIVER_MAJOR		1
-#define DRIVER_MINOR		14
+#define DRIVER_MINOR		15
 #define DRIVER_PATCHLEVEL	0
 
 #define GET_RING_HEAD(dev_priv)		DRM_READ32(  (dev_priv)->ring_rptr, 0 )
@@ -284,42 +286,20 @@
 extern int radeon_wait_ring( drm_radeon_private_t *dev_priv, int n );
 
 extern int radeon_do_cp_idle( drm_radeon_private_t *dev_priv );
-extern int radeon_do_cleanup_cp( drm_device_t *dev );
-extern int radeon_do_cleanup_pageflip( drm_device_t *dev );
 
 extern int radeon_driver_preinit(struct drm_device *dev, unsigned long flags);
 extern int radeon_driver_postcleanup(struct drm_device *dev);
 
-				/* radeon_state.c */
-extern int radeon_cp_clear( DRM_IOCTL_ARGS );
-extern int radeon_cp_swap( DRM_IOCTL_ARGS );
-extern int radeon_cp_vertex( DRM_IOCTL_ARGS );
-extern int radeon_cp_indices( DRM_IOCTL_ARGS );
-extern int radeon_cp_texture( DRM_IOCTL_ARGS );
-extern int radeon_cp_stipple( DRM_IOCTL_ARGS );
-extern int radeon_cp_indirect( DRM_IOCTL_ARGS );
-extern int radeon_cp_vertex2( DRM_IOCTL_ARGS );
-extern int radeon_cp_cmdbuf( DRM_IOCTL_ARGS );
-extern int radeon_cp_getparam( DRM_IOCTL_ARGS );
-extern int radeon_cp_setparam( DRM_IOCTL_ARGS );
-extern int radeon_cp_flip( DRM_IOCTL_ARGS );
-
 extern int radeon_mem_alloc( DRM_IOCTL_ARGS );
 extern int radeon_mem_free( DRM_IOCTL_ARGS );
 extern int radeon_mem_init_heap( DRM_IOCTL_ARGS );
 extern void radeon_mem_takedown( struct mem_block **heap );
 extern void radeon_mem_release( DRMFILE filp, struct mem_block *heap );
-extern int radeon_surface_alloc(DRM_IOCTL_ARGS);
-extern int radeon_surface_free(DRM_IOCTL_ARGS);
 
 				/* radeon_irq.c */
 extern int radeon_irq_emit( DRM_IOCTL_ARGS );
 extern int radeon_irq_wait( DRM_IOCTL_ARGS );
 
-extern int radeon_emit_and_wait_irq(drm_device_t *dev);
-extern int radeon_wait_irq(drm_device_t *dev, int swi_nr);
-extern int radeon_emit_irq(drm_device_t *dev);
-
 extern void radeon_do_release(drm_device_t *dev);
 extern int radeon_driver_vblank_wait(drm_device_t *dev, unsigned int *sequence);
 extern irqreturn_t radeon_driver_irq_handler( DRM_IRQ_ARGS );
@@ -817,6 +797,12 @@
 #define RADEON_PP_TEX_SIZE_1                0x1d0c
 #define RADEON_PP_TEX_SIZE_2                0x1d14
 
+#define RADEON_PP_CUBIC_FACES_0             0x1d24
+#define RADEON_PP_CUBIC_FACES_1             0x1d28
+#define RADEON_PP_CUBIC_FACES_2             0x1d2c
+#define RADEON_PP_CUBIC_OFFSET_T0_0         0x1dd0	/* bits [31:5] */
+#define RADEON_PP_CUBIC_OFFSET_T1_0         0x1e00
+#define RADEON_PP_CUBIC_OFFSET_T2_0         0x1e14
 
 #define SE_VAP_CNTL__TCL_ENA_MASK                          0x00000001
 #define SE_VAP_CNTL__FORCE_W_TO_ONE_MASK                   0x00010000
@@ -859,9 +845,6 @@
 		       ((addr) & 0x1f) | RADEON_PLL_WR_EN );		\
 	RADEON_WRITE( RADEON_CLOCK_CNTL_DATA, (val) );			\
 } while (0)
-
-extern int RADEON_READ_PLL( drm_device_t *dev, int addr );
-
 
 #define CP_PACKET0( reg, n )						\
 	(RADEON_CP_PACKET0 | ((n) << 16) | ((reg) >> 2))
diff -Nru a/drivers/char/drm/radeon_irq.c b/drivers/char/drm/radeon_irq.c
--- a/drivers/char/drm/radeon_irq.c	2005-03-11 12:51:51 -08:00
+++ b/drivers/char/drm/radeon_irq.c	2005-03-11 12:51:51 -08:00
@@ -93,7 +93,7 @@
 		RADEON_WRITE( RADEON_GEN_INT_STATUS, tmp );
 }
 
-int radeon_emit_irq(drm_device_t *dev)
+static int radeon_emit_irq(drm_device_t *dev)
 {
 	drm_radeon_private_t *dev_priv = dev->dev_private;
 	unsigned int ret;
@@ -112,7 +112,7 @@
 }
 
 
-int radeon_wait_irq(drm_device_t *dev, int swi_nr)
+static int radeon_wait_irq(drm_device_t *dev, int swi_nr)
 {
   	drm_radeon_private_t *dev_priv = 
 	   (drm_radeon_private_t *)dev->dev_private;
@@ -133,12 +133,6 @@
 
 	return ret;
 }
-
-int radeon_emit_and_wait_irq(drm_device_t *dev)
-{
-	return radeon_wait_irq( dev, radeon_emit_irq(dev) );
-}
-
 
 int radeon_driver_vblank_wait(drm_device_t *dev, unsigned int *sequence)
 {
diff -Nru a/drivers/char/drm/radeon_state.c b/drivers/char/drm/radeon_state.c
--- a/drivers/char/drm/radeon_state.c	2005-03-11 12:51:51 -08:00
+++ b/drivers/char/drm/radeon_state.c	2005-03-11 12:51:51 -08:00
@@ -33,38 +33,6 @@
 #include "radeon_drm.h"
 #include "radeon_drv.h"
 
-drm_ioctl_desc_t radeon_ioctls[] = {
-	[DRM_IOCTL_NR(DRM_RADEON_CP_INIT)]    = { radeon_cp_init,      1, 1 },
-	[DRM_IOCTL_NR(DRM_RADEON_CP_START)]   = { radeon_cp_start,     1, 1 },
-	[DRM_IOCTL_NR(DRM_RADEON_CP_STOP)]    = { radeon_cp_stop,      1, 1 },
-	[DRM_IOCTL_NR(DRM_RADEON_CP_RESET)]   = { radeon_cp_reset,     1, 1 },
-	[DRM_IOCTL_NR(DRM_RADEON_CP_IDLE)]    = { radeon_cp_idle,      1, 0 },
-	[DRM_IOCTL_NR(DRM_RADEON_CP_RESUME)]  = { radeon_cp_resume,    1, 0 },
-	[DRM_IOCTL_NR(DRM_RADEON_RESET)]      = { radeon_engine_reset, 1, 0 },
-	[DRM_IOCTL_NR(DRM_RADEON_FULLSCREEN)] = { radeon_fullscreen,   1, 0 },
-	[DRM_IOCTL_NR(DRM_RADEON_SWAP)]       = { radeon_cp_swap,      1, 0 },
-	[DRM_IOCTL_NR(DRM_RADEON_CLEAR)]      = { radeon_cp_clear,     1, 0 },
-	[DRM_IOCTL_NR(DRM_RADEON_VERTEX)]     = { radeon_cp_vertex,    1, 0 },
-	[DRM_IOCTL_NR(DRM_RADEON_INDICES)]    = { radeon_cp_indices,   1, 0 },
-	[DRM_IOCTL_NR(DRM_RADEON_TEXTURE)]    = { radeon_cp_texture,   1, 0 },
-	[DRM_IOCTL_NR(DRM_RADEON_STIPPLE)]    = { radeon_cp_stipple,   1, 0 },
-	[DRM_IOCTL_NR(DRM_RADEON_INDIRECT)]   = { radeon_cp_indirect,  1, 1 },
-	[DRM_IOCTL_NR(DRM_RADEON_VERTEX2)]    = { radeon_cp_vertex2,   1, 0 },
-	[DRM_IOCTL_NR(DRM_RADEON_CMDBUF)]     = { radeon_cp_cmdbuf,    1, 0 },
-	[DRM_IOCTL_NR(DRM_RADEON_GETPARAM)]   = { radeon_cp_getparam,  1, 0 },
-	[DRM_IOCTL_NR(DRM_RADEON_FLIP)]       = { radeon_cp_flip,      1, 0 },
-	[DRM_IOCTL_NR(DRM_RADEON_ALLOC)]      = { radeon_mem_alloc,    1, 0 },
-	[DRM_IOCTL_NR(DRM_RADEON_FREE)]       = { radeon_mem_free,     1, 0 },
-	[DRM_IOCTL_NR(DRM_RADEON_INIT_HEAP)]  = { radeon_mem_init_heap,1, 1 },
-	[DRM_IOCTL_NR(DRM_RADEON_IRQ_EMIT)]   = { radeon_irq_emit,     1, 0 },
-	[DRM_IOCTL_NR(DRM_RADEON_IRQ_WAIT)]   = { radeon_irq_wait,     1, 0 },
-	[DRM_IOCTL_NR(DRM_RADEON_SETPARAM)]   = { radeon_cp_setparam,  1, 0 },
-	[DRM_IOCTL_NR(DRM_RADEON_SURF_ALLOC)] = { radeon_surface_alloc,1, 0 },
-	[DRM_IOCTL_NR(DRM_RADEON_SURF_FREE)]  = { radeon_surface_free, 1, 0 }
-};
-
-int radeon_max_ioctl = DRM_ARRAY_SIZE(radeon_ioctls);
-
 /* ================================================================
  * Helper functions for client state checking and fixup
  */
@@ -158,6 +126,22 @@
 		break;
 	}
 
+	case RADEON_EMIT_PP_CUBIC_OFFSETS_T0:
+	case RADEON_EMIT_PP_CUBIC_OFFSETS_T1:
+	case RADEON_EMIT_PP_CUBIC_OFFSETS_T2:{
+			int i;
+			for (i = 0; i < 5; i++) {
+				if (radeon_check_and_fixup_offset(dev_priv,
+								  filp_priv,
+								  &data[i])) {
+					DRM_ERROR
+					    ("Invalid R100 cubic texture offset\n");
+					return DRM_ERR(EINVAL);
+				}
+			}
+		}
+		break;
+
 	case RADEON_EMIT_RB3D_COLORPITCH:
 	case RADEON_EMIT_RE_LINE_PATTERN:
 	case RADEON_EMIT_SE_LINE_WIDTH:
@@ -1514,6 +1498,7 @@
 	int size, dwords, tex_width, blit_width;
 	u32 height;
 	int i;
+	u32 texpitch, microtile;
 	RING_LOCALS;
 
 	DRM_GET_PRIV_WITH_RETURN( filp_priv, filp );
@@ -1576,6 +1561,16 @@
 		DRM_ERROR( "invalid texture format %d\n", tex->format );
 		return DRM_ERR(EINVAL);
 	}
+	texpitch = tex->pitch;
+	if ((texpitch << 22) & RADEON_DST_TILE_MICRO) {
+		microtile = 1;
+		if (tex_width < 64) {
+			texpitch &= ~(RADEON_DST_TILE_MICRO >> 22);
+			/* we got tiled coordinates, untile them */
+			image->x *= 2;
+		}
+	}
+	else microtile = 0;
 
 	DRM_DEBUG("tex=%dx%d blit=%d\n", tex_width, tex->height, blit_width );
 
@@ -1628,7 +1623,7 @@
 			     RADEON_GMC_CLR_CMP_CNTL_DIS |
 			     RADEON_GMC_WR_MSK_DIS);
 		
-		buffer[2] = (tex->pitch << 22) | (tex->offset >> 10);
+		buffer[2] = (texpitch << 22) | (tex->offset >> 10);
 		buffer[3] = 0xffffffff;
 		buffer[4] = 0xffffffff;
 		buffer[5] = (image->y << 16) | image->x;
@@ -1636,30 +1631,110 @@
 		buffer[7] = dwords;
 		buffer += 8;
 
-		if ( tex_width >= 32 ) {
-			/* Texture image width is larger than the minimum, so we
-			 * can upload it directly.
-			 */
-			if ( DRM_COPY_FROM_USER( buffer, data, 
-						 dwords * sizeof(u32) ) ) {
-				DRM_ERROR( "EFAULT on data, %d dwords\n", 
-					   dwords );
-				return DRM_ERR(EFAULT);
+		
+
+		if (microtile) {
+			/* texture micro tiling in use, minimum texture width is thus 16 bytes.
+			   however, we cannot use blitter directly for texture width < 64 bytes,
+			   since minimum tex pitch is 64 bytes and we need this to match
+			   the texture width, otherwise the blitter will tile it wrong.
+			   Thus, tiling manually in this case. Additionally, need to special
+			   case tex height = 1, since our actual image will have height 2
+			   and we need to ensure we don't read beyond the texture size
+			   from user space. */
+			if (tex->height == 1) {
+				if (tex_width >= 64 || tex_width <= 16) {
+					if (DRM_COPY_FROM_USER(buffer, data,
+							       tex_width * sizeof(u32))) {
+						DRM_ERROR("EFAULT on pad, %d bytes\n",
+							  tex_width);
+						return DRM_ERR(EFAULT);
+					}
+				} else if (tex_width == 32) {
+					if (DRM_COPY_FROM_USER(buffer, data, 16)) {
+						DRM_ERROR("EFAULT on pad, %d bytes\n",
+							  tex_width);
+						return DRM_ERR(EFAULT);
+					}
+					if (DRM_COPY_FROM_USER(buffer + 8, data + 16, 16)) {
+						DRM_ERROR("EFAULT on pad, %d bytes\n",
+							  tex_width);
+						return DRM_ERR(EFAULT);
+					}
+				}
+			} else if (tex_width >= 64 || tex_width == 16) {
+				if (DRM_COPY_FROM_USER(buffer, data,
+						       dwords * sizeof(u32))) {
+					DRM_ERROR("EFAULT on data, %d dwords\n",
+						  dwords);
+					return DRM_ERR(EFAULT);
+				}
+			} else if (tex_width < 16) {
+				for (i = 0; i < tex->height; i++) {
+					if (DRM_COPY_FROM_USER(buffer, data, tex_width)) {
+						DRM_ERROR("EFAULT on pad, %d bytes\n",
+							  tex_width);
+						return DRM_ERR(EFAULT);
+					}
+					buffer += 4;
+					data += tex_width;
+				}
+			} else if (tex_width == 32) {
+				/* TODO: make sure this works when not fitting in one buffer
+				   (i.e. 32bytes x 2048...) */
+				for (i = 0; i < tex->height; i += 2) {
+					if (DRM_COPY_FROM_USER(buffer, data, 16)) {
+						DRM_ERROR("EFAULT on pad, %d bytes\n",
+							  tex_width);
+						return DRM_ERR(EFAULT);
+					}
+					data += 16;
+					if (DRM_COPY_FROM_USER(buffer + 8, data, 16)) {
+						DRM_ERROR("EFAULT on pad, %d bytes\n",
+							  tex_width);
+						return DRM_ERR(EFAULT);
+					}
+					data += 16;
+					if (DRM_COPY_FROM_USER(buffer + 4, data, 16)) {
+						DRM_ERROR("EFAULT on pad, %d bytes\n",
+							  tex_width);
+						return DRM_ERR(EFAULT);
+					}
+					data += 16;
+					if (DRM_COPY_FROM_USER(buffer + 12, data, 16)) {
+						DRM_ERROR("EFAULT on pad, %d bytes\n",
+							  tex_width);
+						return DRM_ERR(EFAULT);
+					}
+					data += 16;
+					buffer += 16;
+				}
 			}
-		} else {
-			/* Texture image width is less than the minimum, so we
-			 * need to pad out each image scanline to the minimum
-			 * width.
-			 */
-			for ( i = 0 ; i < tex->height ; i++ ) {
-				if ( DRM_COPY_FROM_USER( buffer, data, 
-							 tex_width ) ) {
-					DRM_ERROR( "EFAULT on pad, %d bytes\n",
-						   tex_width );
+		}
+		else {
+			if (tex_width >= 32) {
+				/* Texture image width is larger than the minimum, so we
+				 * can upload it directly.
+				 */
+				if (DRM_COPY_FROM_USER(buffer, data,
+						       dwords * sizeof(u32))) {
+					DRM_ERROR("EFAULT on data, %d dwords\n",
+						  dwords);
 					return DRM_ERR(EFAULT);
 				}
-				buffer += 8;
-				data += tex_width;
+			} else {
+				/* Texture image width is less than the minimum, so we
+				 * need to pad out each image scanline to the minimum
+				 * width.
+				 */
+				for (i = 0 ; i < tex->height ; i++) {
+					if (DRM_COPY_FROM_USER(buffer, data, tex_width )) {
+						DRM_ERROR("EFAULT on pad, %d bytes\n", tex_width);
+						return DRM_ERR(EFAULT);
+					}
+					buffer += 8;
+					data += tex_width;
+				}
 			}
 		}
 
@@ -1864,7 +1939,7 @@
 /* ================================================================
  * IOCTL functions
  */
-int radeon_surface_alloc(DRM_IOCTL_ARGS)
+static int radeon_surface_alloc(DRM_IOCTL_ARGS)
 {
 	DRM_DEVICE;
 	drm_radeon_private_t *dev_priv = dev->dev_private;
@@ -1884,7 +1959,7 @@
 		return 0;
 }
 
-int radeon_surface_free(DRM_IOCTL_ARGS)
+static int radeon_surface_free(DRM_IOCTL_ARGS)
 {
 	DRM_DEVICE;
 	drm_radeon_private_t *dev_priv = dev->dev_private;
@@ -1904,7 +1979,7 @@
 		return 0;
 }
 
-int radeon_cp_clear( DRM_IOCTL_ARGS )
+static int radeon_cp_clear( DRM_IOCTL_ARGS )
 {
 	DRM_DEVICE;
 	drm_radeon_private_t *dev_priv = dev->dev_private;
@@ -1961,7 +2036,7 @@
 /* Called whenever a client dies, from drm_release.
  * NOTE:  Lock isn't necessarily held when this is called!
  */
-int radeon_do_cleanup_pageflip( drm_device_t *dev )
+static int radeon_do_cleanup_pageflip( drm_device_t *dev )
 {
 	drm_radeon_private_t *dev_priv = dev->dev_private;
 	DRM_DEBUG( "\n" );
@@ -1976,7 +2051,7 @@
 /* Swapping and flipping are different operations, need different ioctls.
  * They can & should be intermixed to support multiple 3d windows.  
  */
-int radeon_cp_flip( DRM_IOCTL_ARGS )
+static int radeon_cp_flip( DRM_IOCTL_ARGS )
 {
 	DRM_DEVICE;
 	drm_radeon_private_t *dev_priv = dev->dev_private;
@@ -1995,7 +2070,7 @@
 	return 0;
 }
 
-int radeon_cp_swap( DRM_IOCTL_ARGS )
+static int radeon_cp_swap( DRM_IOCTL_ARGS )
 {
 	DRM_DEVICE;
 	drm_radeon_private_t *dev_priv = dev->dev_private;
@@ -2016,7 +2091,7 @@
 	return 0;
 }
 
-int radeon_cp_vertex( DRM_IOCTL_ARGS )
+static int radeon_cp_vertex( DRM_IOCTL_ARGS )
 {
 	DRM_DEVICE;
 	drm_radeon_private_t *dev_priv = dev->dev_private;
@@ -2101,7 +2176,7 @@
 	return 0;
 }
 
-int radeon_cp_indices( DRM_IOCTL_ARGS )
+static int radeon_cp_indices( DRM_IOCTL_ARGS )
 {
 	DRM_DEVICE;
 	drm_radeon_private_t *dev_priv = dev->dev_private;
@@ -2203,7 +2278,7 @@
 	return 0;
 }
 
-int radeon_cp_texture( DRM_IOCTL_ARGS )
+static int radeon_cp_texture( DRM_IOCTL_ARGS )
 {
 	DRM_DEVICE;
 	drm_radeon_private_t *dev_priv = dev->dev_private;
@@ -2234,7 +2309,7 @@
 	return ret;
 }
 
-int radeon_cp_stipple( DRM_IOCTL_ARGS )
+static int radeon_cp_stipple( DRM_IOCTL_ARGS )
 {
 	DRM_DEVICE;
 	drm_radeon_private_t *dev_priv = dev->dev_private;
@@ -2257,7 +2332,7 @@
 	return 0;
 }
 
-int radeon_cp_indirect( DRM_IOCTL_ARGS )
+static int radeon_cp_indirect( DRM_IOCTL_ARGS )
 {
 	DRM_DEVICE;
 	drm_radeon_private_t *dev_priv = dev->dev_private;
@@ -2332,7 +2407,7 @@
 	return 0;
 }
 
-int radeon_cp_vertex2( DRM_IOCTL_ARGS )
+static int radeon_cp_vertex2( DRM_IOCTL_ARGS )
 {
 	DRM_DEVICE;
 	drm_radeon_private_t *dev_priv = dev->dev_private;
@@ -2661,7 +2736,7 @@
 	return 0;
 }
 
-int radeon_cp_cmdbuf( DRM_IOCTL_ARGS )
+static int radeon_cp_cmdbuf( DRM_IOCTL_ARGS )
 {
 	DRM_DEVICE;
 	drm_radeon_private_t *dev_priv = dev->dev_private;
@@ -2813,7 +2888,7 @@
 
 
 
-int radeon_cp_getparam( DRM_IOCTL_ARGS )
+static int radeon_cp_getparam( DRM_IOCTL_ARGS )
 {
 	DRM_DEVICE;
 	drm_radeon_private_t *dev_priv = dev->dev_private;
@@ -2887,7 +2962,7 @@
 	return 0;
 }
 
-int radeon_cp_setparam( DRM_IOCTL_ARGS ) {
+static int radeon_cp_setparam( DRM_IOCTL_ARGS ) {
 	DRM_DEVICE;
 	drm_radeon_private_t *dev_priv = dev->dev_private;
 	drm_file_t *filp_priv;
@@ -2980,3 +3055,35 @@
 	 
 	 drm_free(radeon_priv, sizeof(*radeon_priv), DRM_MEM_FILES);
 }
+
+drm_ioctl_desc_t radeon_ioctls[] = {
+	[DRM_IOCTL_NR(DRM_RADEON_CP_INIT)]    = { radeon_cp_init,      1, 1 },
+	[DRM_IOCTL_NR(DRM_RADEON_CP_START)]   = { radeon_cp_start,     1, 1 },
+	[DRM_IOCTL_NR(DRM_RADEON_CP_STOP)]    = { radeon_cp_stop,      1, 1 },
+	[DRM_IOCTL_NR(DRM_RADEON_CP_RESET)]   = { radeon_cp_reset,     1, 1 },
+	[DRM_IOCTL_NR(DRM_RADEON_CP_IDLE)]    = { radeon_cp_idle,      1, 0 },
+	[DRM_IOCTL_NR(DRM_RADEON_CP_RESUME)]  = { radeon_cp_resume,    1, 0 },
+	[DRM_IOCTL_NR(DRM_RADEON_RESET)]      = { radeon_engine_reset, 1, 0 },
+	[DRM_IOCTL_NR(DRM_RADEON_FULLSCREEN)] = { radeon_fullscreen,   1, 0 },
+	[DRM_IOCTL_NR(DRM_RADEON_SWAP)]       = { radeon_cp_swap,      1, 0 },
+	[DRM_IOCTL_NR(DRM_RADEON_CLEAR)]      = { radeon_cp_clear,     1, 0 },
+	[DRM_IOCTL_NR(DRM_RADEON_VERTEX)]     = { radeon_cp_vertex,    1, 0 },
+	[DRM_IOCTL_NR(DRM_RADEON_INDICES)]    = { radeon_cp_indices,   1, 0 },
+	[DRM_IOCTL_NR(DRM_RADEON_TEXTURE)]    = { radeon_cp_texture,   1, 0 },
+	[DRM_IOCTL_NR(DRM_RADEON_STIPPLE)]    = { radeon_cp_stipple,   1, 0 },
+	[DRM_IOCTL_NR(DRM_RADEON_INDIRECT)]   = { radeon_cp_indirect,  1, 1 },
+	[DRM_IOCTL_NR(DRM_RADEON_VERTEX2)]    = { radeon_cp_vertex2,   1, 0 },
+	[DRM_IOCTL_NR(DRM_RADEON_CMDBUF)]     = { radeon_cp_cmdbuf,    1, 0 },
+	[DRM_IOCTL_NR(DRM_RADEON_GETPARAM)]   = { radeon_cp_getparam,  1, 0 },
+	[DRM_IOCTL_NR(DRM_RADEON_FLIP)]       = { radeon_cp_flip,      1, 0 },
+	[DRM_IOCTL_NR(DRM_RADEON_ALLOC)]      = { radeon_mem_alloc,    1, 0 },
+	[DRM_IOCTL_NR(DRM_RADEON_FREE)]       = { radeon_mem_free,     1, 0 },
+	[DRM_IOCTL_NR(DRM_RADEON_INIT_HEAP)]  = { radeon_mem_init_heap,1, 1 },
+	[DRM_IOCTL_NR(DRM_RADEON_IRQ_EMIT)]   = { radeon_irq_emit,     1, 0 },
+	[DRM_IOCTL_NR(DRM_RADEON_IRQ_WAIT)]   = { radeon_irq_wait,     1, 0 },
+	[DRM_IOCTL_NR(DRM_RADEON_SETPARAM)]   = { radeon_cp_setparam,  1, 0 },
+	[DRM_IOCTL_NR(DRM_RADEON_SURF_ALLOC)] = { radeon_surface_alloc,1, 0 },
+	[DRM_IOCTL_NR(DRM_RADEON_SURF_FREE)]  = { radeon_surface_free, 1, 0 }
+};
+
+int radeon_max_ioctl = DRM_ARRAY_SIZE(radeon_ioctls);
diff -Nru a/drivers/char/drm/sis_drv.c b/drivers/char/drm/sis_drv.c
--- a/drivers/char/drm/sis_drv.c	2005-03-11 12:51:40 -08:00
+++ b/drivers/char/drm/sis_drv.c	2005-03-11 12:51:40 -08:00
@@ -40,7 +40,7 @@
 		DRIVER_MINOR,
 		DRIVER_PATCHLEVEL,
 		DRIVER_DATE,
-		dev->minor,
+		dev->primary.minor,
 		pci_pretty_name(dev->pdev)
 		);
 	return 0;
diff -Nru a/drivers/char/drm/sis_drv.h b/drivers/char/drm/sis_drv.h
--- a/drivers/char/drm/sis_drv.h	2005-03-11 12:51:41 -08:00
+++ b/drivers/char/drm/sis_drv.h	2005-03-11 12:51:41 -08:00
@@ -46,13 +46,6 @@
 	memHeap_t *FBHeap;
 } drm_sis_private_t;
 
-extern int sis_fb_alloc( DRM_IOCTL_ARGS );
-extern int sis_fb_free( DRM_IOCTL_ARGS );
-extern int sis_ioctl_agp_init( DRM_IOCTL_ARGS );
-extern int sis_ioctl_agp_alloc( DRM_IOCTL_ARGS );
-extern int sis_ioctl_agp_free( DRM_IOCTL_ARGS );
-extern int sis_fb_init( DRM_IOCTL_ARGS );
-
 extern int sis_init_context(drm_device_t *dev, int context);
 extern int sis_final_context(drm_device_t *dev, int context);
 
diff -Nru a/drivers/char/drm/sis_ds.c b/drivers/char/drm/sis_ds.c
--- a/drivers/char/drm/sis_ds.c	2005-03-11 12:51:51 -08:00
+++ b/drivers/char/drm/sis_ds.c	2005-03-11 12:51:51 -08:00
@@ -194,32 +194,6 @@
 		return 0;
 }
 
-/* Kludgey workaround for existing i810 server.  Remove soon.
- */
-memHeap_t *mmAddRange( memHeap_t *heap,
-		       int ofs,
-		       int size )
-{
-	PMemBlock blocks;
-	blocks = (TMemBlock *)drm_calloc(2, sizeof(TMemBlock), DRM_MEM_DRIVER);
-	if (blocks != NULL) {
-		blocks[0].size = size;
-		blocks[0].free = 1;
-		blocks[0].ofs = ofs;
-		blocks[0].next = &blocks[1];
-
-		/* Discontinuity - stops JoinBlock from trying to join
-		 * non-adjacent ranges.
-		 */
-		blocks[1].size = 0;
-		blocks[1].free = 0;
-		blocks[1].ofs = ofs+size;
-		blocks[1].next = (PMemBlock)heap;
-		return (memHeap_t *)blocks;
-	} else
-		return heap;
-}
-
 static TMemBlock* SliceBlock(TMemBlock *p, 
 			     int startofs, int size, 
 			     int reserved, int alignment)
@@ -325,61 +299,3 @@
 	return 0;
 }
 
-int mmReserveMem(memHeap_t *heap, int offset,int size)
-{
-	int endofs;
-	TMemBlock *p;
-
-	if (heap == NULL || size <= 0)
-		return -1;
-
-	endofs = offset + size;
-	p = (TMemBlock *)heap;
-	while (p && p->ofs <= offset) {
-		if (ISFREE(p) && endofs <= (p->ofs+p->size)) {
-			SliceBlock(p,offset,size,1,1);
-			return 0;
-		}
-		p = p->next;
-	}
-	return -1;
-}
-
-int mmFreeReserved(memHeap_t *heap, int offset)
-{
-	TMemBlock *p,*prev;
-
-	if (heap == NULL)
-		return -1;
-
-	p = (TMemBlock *)heap;
-	prev = NULL;
-	while (p != NULL && p->ofs != offset) {
-		prev = p;
-		p = p->next;
-	}
-	if (p == NULL || !p->reserved)
-		return -1;
-
-	p->free = 1;
-	p->reserved = 0;
-	Join2Blocks(p);
-	if (prev != NULL)
-		Join2Blocks(prev);
-	return 0;
-}
-
-void mmDestroy(memHeap_t *heap)
-{
-	TMemBlock *p,*q;
-
-	if (heap == NULL)
-		return;
-
-	p = (TMemBlock *)heap;
-	while (p != NULL) {
-		q = p->next;
-		drm_free(p, sizeof(TMemBlock), DRM_MEM_DRIVER);
-		p = q;
-	}
-}
diff -Nru a/drivers/char/drm/sis_ds.h b/drivers/char/drm/sis_ds.h
--- a/drivers/char/drm/sis_ds.h	2005-03-11 12:51:46 -08:00
+++ b/drivers/char/drm/sis_ds.h	2005-03-11 12:51:46 -08:00
@@ -115,10 +115,6 @@
  */
 memHeap_t *mmInit( int ofs, int size );
 
-memHeap_t *mmAddRange( memHeap_t *heap,
-		       int ofs,
-		       int size );
-
 /*
  * Allocate 'size' bytes with 2^align2 bytes alignment,
  * restrict the search to free memory after 'startSearch'
@@ -142,21 +138,6 @@
  * return: 0 if OK, -1 if error
  */
 int mmFreeMem( PMemBlock b );
-
-/*
- * Reserve 'size' bytes block start at offset
- * This is used to prevent allocation of memory already used
- * by the X server for the front buffer, pixmaps, and cursor
- * input: size, offset
- * output: 0 if OK, -1 if error
- */
-int mmReserveMem( memHeap_t *heap, int offset,int size );
-int mmFreeReserved( memHeap_t *heap, int offset );
-
-/*
- * destroy MM
- */
-void mmDestroy( memHeap_t *mmInit );
 
 /* For debuging purpose. */
 void mmDumpMemInfo( memHeap_t *mmInit );
diff -Nru a/drivers/char/drm/sis_mm.c b/drivers/char/drm/sis_mm.c
--- a/drivers/char/drm/sis_mm.c	2005-03-11 12:51:47 -08:00
+++ b/drivers/char/drm/sis_mm.c	2005-03-11 12:51:47 -08:00
@@ -36,17 +36,6 @@
 #include <video/sisfb.h>
 #endif
 
-drm_ioctl_desc_t sis_ioctls[] = {
-	[DRM_IOCTL_NR(DRM_SIS_FB_ALLOC)]  = { sis_fb_alloc,        1, 0 },
-	[DRM_IOCTL_NR(DRM_SIS_FB_FREE)]   = { sis_fb_free,         1, 0 },
-	[DRM_IOCTL_NR(DRM_SIS_AGP_INIT)]  = { sis_ioctl_agp_init,  1, 1 },
-	[DRM_IOCTL_NR(DRM_SIS_AGP_ALLOC)] = { sis_ioctl_agp_alloc, 1, 0 },
-	[DRM_IOCTL_NR(DRM_SIS_AGP_FREE)]  = { sis_ioctl_agp_free,  1, 0 },
-	[DRM_IOCTL_NR(DRM_SIS_FB_INIT)]   = { sis_fb_init,         1, 1 }
-};
-
-int sis_max_ioctl = DRM_ARRAY_SIZE(sis_ioctls);
-
 #define MAX_CONTEXT 100
 #define VIDEO_TYPE 0 
 #define AGP_TYPE 1
@@ -91,12 +80,12 @@
 /* fb management via fb device */ 
 #if defined(__linux__) && defined(CONFIG_FB_SIS)
 
-int sis_fb_init( DRM_IOCTL_ARGS )
+static int sis_fb_init( DRM_IOCTL_ARGS )
 {
 	return 0;
 }
 
-int sis_fb_alloc( DRM_IOCTL_ARGS )
+static int sis_fb_alloc( DRM_IOCTL_ARGS )
 {
 	drm_sis_mem_t fb;
 	struct sis_memreq req;
@@ -129,7 +118,7 @@
 	return retval;
 }
 
-int sis_fb_free( DRM_IOCTL_ARGS )
+static int sis_fb_free( DRM_IOCTL_ARGS )
 {
 	drm_sis_mem_t fb;
 	int retval = 0;
@@ -160,7 +149,7 @@
  *    X driver/sisfb                                  HW-   Command-
  *  framebuffer memory           DRI heap           Cursor   queue
  */
-int sis_fb_init( DRM_IOCTL_ARGS )
+static int sis_fb_init( DRM_IOCTL_ARGS )
 {
 	DRM_DEVICE;
 	drm_sis_private_t *dev_priv = dev->dev_private;
@@ -186,7 +175,7 @@
 	return 0;
 }
 
-int sis_fb_alloc( DRM_IOCTL_ARGS )
+static int sis_fb_alloc( DRM_IOCTL_ARGS )
 {
 	DRM_DEVICE;
 	drm_sis_private_t *dev_priv = dev->dev_private;
@@ -223,7 +212,7 @@
 	return retval;
 }
 
-int sis_fb_free( DRM_IOCTL_ARGS )
+static int sis_fb_free( DRM_IOCTL_ARGS )
 {
 	DRM_DEVICE;
 	drm_sis_private_t *dev_priv = dev->dev_private;
@@ -250,7 +239,7 @@
 
 /* agp memory management */ 
 
-int sis_ioctl_agp_init( DRM_IOCTL_ARGS )
+static int sis_ioctl_agp_init( DRM_IOCTL_ARGS )
 {
 	DRM_DEVICE;
 	drm_sis_private_t *dev_priv = dev->dev_private;
@@ -276,7 +265,7 @@
 	return 0;
 }
 
-int sis_ioctl_agp_alloc( DRM_IOCTL_ARGS )
+static int sis_ioctl_agp_alloc( DRM_IOCTL_ARGS )
 {
 	DRM_DEVICE;
 	drm_sis_private_t *dev_priv = dev->dev_private;
@@ -313,7 +302,7 @@
 	return retval;
 }
 
-int sis_ioctl_agp_free( DRM_IOCTL_ARGS )
+static int sis_ioctl_agp_free( DRM_IOCTL_ARGS )
 {
 	DRM_DEVICE;
 	drm_sis_private_t *dev_priv = dev->dev_private;
@@ -414,3 +403,15 @@
 	
 	return 1;
 }
+
+drm_ioctl_desc_t sis_ioctls[] = {
+	[DRM_IOCTL_NR(DRM_SIS_FB_ALLOC)]  = { sis_fb_alloc,        1, 0 },
+	[DRM_IOCTL_NR(DRM_SIS_FB_FREE)]   = { sis_fb_free,         1, 0 },
+	[DRM_IOCTL_NR(DRM_SIS_AGP_INIT)]  = { sis_ioctl_agp_init,  1, 1 },
+	[DRM_IOCTL_NR(DRM_SIS_AGP_ALLOC)] = { sis_ioctl_agp_alloc, 1, 0 },
+	[DRM_IOCTL_NR(DRM_SIS_AGP_FREE)]  = { sis_ioctl_agp_free,  1, 0 },
+	[DRM_IOCTL_NR(DRM_SIS_FB_INIT)]   = { sis_fb_init,         1, 1 }
+};
+
+int sis_max_ioctl = DRM_ARRAY_SIZE(sis_ioctls);
+
diff -Nru a/drivers/char/drm/tdfx_drv.c b/drivers/char/drm/tdfx_drv.c
--- a/drivers/char/drm/tdfx_drv.c	2005-03-11 12:51:46 -08:00
+++ b/drivers/char/drm/tdfx_drv.c	2005-03-11 12:51:46 -08:00
@@ -44,7 +44,7 @@
 		DRIVER_MINOR,
 		DRIVER_PATCHLEVEL,
 		DRIVER_DATE,
-		dev->minor,
+		dev->primary.minor,
 		pci_pretty_name(dev->pdev)
 		);
 	return 0;
diff -Nru a/drivers/char/esp.c b/drivers/char/esp.c
--- a/drivers/char/esp.c	2005-03-11 12:51:40 -08:00
+++ b/drivers/char/esp.c	2005-03-11 12:51:40 -08:00
@@ -129,8 +129,6 @@
 #undef SERIAL_DEBUG_OPEN
 #undef SERIAL_DEBUG_FLOW
 
-#define _INLINE_ inline
-  
 #if defined(MODULE) && defined(SERIAL_DEBUG_MCOUNT)
 #define DBG_CNT(s) printk("(%s): [%x] refc=%d, serc=%d, ttyc=%d -> %s\n", \
  tty->name, (info->flags), serial_driver.refcount,info->count,tty->count,s)
@@ -211,15 +209,14 @@
 
 	if (serial_paranoia_check(info, tty->name, "rs_stop"))
 		return;
-	
-	save_flags(flags); cli();
+
+	spin_lock_irqsave(&info->lock, flags);
 	if (info->IER & UART_IER_THRI) {
 		info->IER &= ~UART_IER_THRI;
 		serial_out(info, UART_ESI_CMD1, ESI_SET_SRV_MASK);
 		serial_out(info, UART_ESI_CMD2, info->IER);
 	}
-
-	restore_flags(flags);
+	spin_unlock_irqrestore(&info->lock, flags);
 }
 
 static void rs_start(struct tty_struct *tty)
@@ -230,13 +227,13 @@
 	if (serial_paranoia_check(info, tty->name, "rs_start"))
 		return;
 	
-	save_flags(flags); cli();
+	spin_lock_irqsave(&info->lock, flags);
 	if (info->xmit_cnt && info->xmit_buf && !(info->IER & UART_IER_THRI)) {
 		info->IER |= UART_IER_THRI;
 		serial_out(info, UART_ESI_CMD1, ESI_SET_SRV_MASK);
 		serial_out(info, UART_ESI_CMD2, info->IER);
 	}
-	restore_flags(flags);
+	spin_unlock_irqrestore(&info->lock, flags);
 }
 
 /*
@@ -264,34 +261,41 @@
  * This routine is used by the interrupt handler to schedule
  * processing in the software interrupt portion of the driver.
  */
-static _INLINE_ void rs_sched_event(struct esp_struct *info,
+static inline void rs_sched_event(struct esp_struct *info,
 				  int event)
 {
 	info->event |= 1 << event;
 	schedule_work(&info->tqueue);
 }
 
-static _INLINE_ struct esp_pio_buffer *get_pio_buffer(void)
+static DEFINE_SPINLOCK(pio_lock);
+
+static inline struct esp_pio_buffer *get_pio_buffer(void)
 {
 	struct esp_pio_buffer *buf;
+	unsigned long flags;
 
+	spin_lock_irqsave(&pio_lock, flags);
 	if (free_pio_buf) {
 		buf = free_pio_buf;
 		free_pio_buf = buf->next;
 	} else {
 		buf = kmalloc(sizeof(struct esp_pio_buffer), GFP_ATOMIC);
 	}
-
+	spin_unlock_irqrestore(&pio_lock, flags);
 	return buf;
 }
 
-static _INLINE_ void release_pio_buffer(struct esp_pio_buffer *buf)
+static inline void release_pio_buffer(struct esp_pio_buffer *buf)
 {
+	unsigned long flags;
+	spin_lock_irqsave(&pio_lock, flags);
 	buf->next = free_pio_buf;
 	free_pio_buf = buf;
+	spin_unlock_irqrestore(&pio_lock, flags);
 }
 
-static _INLINE_ void receive_chars_pio(struct esp_struct *info, int num_bytes)
+static inline void receive_chars_pio(struct esp_struct *info, int num_bytes)
 {
 	struct tty_struct *tty = info->tty;
 	int i;
@@ -311,8 +315,6 @@
 		return;
 	}
 
-	sti();
-	
 	status_mask = (info->read_status_mask >> 2) & 0x07;
 		
 	for (i = 0; i < num_bytes - 1; i += 2) {
@@ -329,8 +331,6 @@
 			(serial_in(info, UART_ESI_RWS) >> 3) & status_mask;
 	}
 
-	cli();
-
 	/* make sure everything is still ok since interrupts were enabled */
 	tty = info->tty;
 
@@ -371,7 +371,7 @@
 	release_pio_buffer(err_buf);
 }
 
-static _INLINE_ void receive_chars_dma(struct esp_struct *info, int num_bytes)
+static inline void receive_chars_dma(struct esp_struct *info, int num_bytes)
 {
 	unsigned long flags;
 	info->stat_flags &= ~ESP_STAT_RX_TIMEOUT;
@@ -390,7 +390,7 @@
         serial_out(info, UART_ESI_CMD1, ESI_START_DMA_RX);
 }
 
-static _INLINE_ void receive_chars_dma_done(struct esp_struct *info,
+static inline void receive_chars_dma_done(struct esp_struct *info,
 					    int status)
 {
 	struct tty_struct *tty = info->tty;
@@ -450,7 +450,9 @@
 		dma_bytes = 0;
 }
 
-static _INLINE_ void transmit_chars_pio(struct esp_struct *info,
+/* Caller must hold info->lock */
+
+static inline void transmit_chars_pio(struct esp_struct *info,
 					int space_avail)
 {
 	int i;
@@ -478,8 +480,6 @@
 		info->xmit_tail = (info->xmit_tail + space_avail) &
 			(ESP_XMIT_SIZE - 1);
 
-		sti();
-
 		for (i = 0; i < space_avail - 1; i += 2) {
 			outw(*((unsigned short *)(pio_buf->data + i)),
 			     info->port + UART_ESI_TX);
@@ -489,8 +489,6 @@
 			serial_out(info, UART_ESI_TX,
 				   pio_buf->data[space_avail - 1]);
 
-		cli();
-
 		if (info->xmit_cnt) {
 			serial_out(info, UART_ESI_CMD1, ESI_NO_COMMAND);
 			serial_out(info, UART_ESI_CMD1, ESI_GET_TX_AVAIL);
@@ -520,7 +518,8 @@
 	release_pio_buffer(pio_buf);
 }
 
-static _INLINE_ void transmit_chars_dma(struct esp_struct *info, int num_bytes)
+/* Caller must hold info->lock */
+static inline void transmit_chars_dma(struct esp_struct *info, int num_bytes)
 {
 	unsigned long flags;
 	
@@ -567,7 +566,7 @@
         serial_out(info, UART_ESI_CMD1, ESI_START_DMA_TX);
 }
 
-static _INLINE_ void transmit_chars_dma_done(struct esp_struct *info)
+static inline void transmit_chars_dma_done(struct esp_struct *info)
 {
 	int num_bytes;
 	unsigned long flags;
@@ -601,7 +600,7 @@
 	}
 }
 
-static _INLINE_ void check_modem_status(struct esp_struct *info)
+static inline void check_modem_status(struct esp_struct *info)
 {
 	int	status;
 	
@@ -654,10 +653,10 @@
 	err_status = 0;
 	scratch = serial_in(info, UART_ESI_SID);
 
-	cli();
+	spin_lock(&info->lock);
 	
 	if (!info->tty) {
-		sti();
+		spin_unlock(&info->lock);
 		return IRQ_NONE;
 	}
 
@@ -740,7 +739,7 @@
 #ifdef SERIAL_DEBUG_INTR
 	printk("end.\n");
 #endif
-	sti();
+	spin_unlock(&info->lock);
 	return IRQ_HANDLED;
 }
 
@@ -789,10 +788,12 @@
  * figure out the appropriate timeout for an interrupt chain, routines
  * to initialize and startup a serial port, and routines to shutdown a
  * serial port.  Useful stuff like that.
+ *
+ * Caller should hold lock
  * ---------------------------------------------------------------
  */
 
-static _INLINE_ void esp_basic_init(struct esp_struct * info)
+static inline void esp_basic_init(struct esp_struct * info)
 {
 	/* put ESPC in enhanced mode */
 	serial_out(info, UART_ESI_CMD1, ESI_SET_MODE);
@@ -859,13 +860,13 @@
 	int	retval=0;
         unsigned int num_chars;
 
-	save_flags(flags); cli();
+        spin_lock_irqsave(&info->lock, flags);
 
 	if (info->flags & ASYNC_INITIALIZED)
 		goto out;
 
 	if (!info->xmit_buf) {
-		info->xmit_buf = (unsigned char *)get_zeroed_page(GFP_KERNEL);
+		info->xmit_buf = (unsigned char *)get_zeroed_page(GFP_ATOMIC);
 		retval = -ENOMEM;
 		if (!info->xmit_buf)
 			goto out;
@@ -901,6 +902,8 @@
 	if (info->stat_flags & ESP_STAT_NEVER_DMA)
 		info->stat_flags |= ESP_STAT_USE_PIO;
 
+	spin_unlock_irqrestore(&info->lock, flags);
+
 	/*
 	 * Allocate the IRQ
 	 */
@@ -915,7 +918,7 @@
 					&info->tty->flags);
 			retval = 0;
 		}
-		goto out;
+		goto out_unlocked;
 	}
 
 	if (!(info->stat_flags & ESP_STAT_USE_PIO) && !dma_buffer) {
@@ -935,6 +938,8 @@
 	}
 
 	info->MCR = UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2;
+
+	spin_lock_irqsave(&info->lock, flags);
 	serial_out(info, UART_ESI_CMD1, ESI_WRITE_UART);
 	serial_out(info, UART_ESI_CMD2, UART_MCR);
 	serial_out(info, UART_ESI_CMD2, info->MCR);
@@ -951,6 +956,7 @@
 	if (info->tty)
 		clear_bit(TTY_IO_ERROR, &info->tty->flags);
 	info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
+	spin_unlock_irqrestore(&info->lock, flags);
 
 	/*
 	 * Set up the tty->alt_speed kludge
@@ -970,10 +976,12 @@
 	 * set the speed of the serial port
 	 */
 	change_speed(info);
-
 	info->flags |= ASYNC_INITIALIZED;
-	retval = 0;
-out:	restore_flags(flags);
+	return 0;
+
+out:
+	spin_unlock_irqrestore(&info->lock, flags);
+out_unlocked:
 	return retval;
 }
 
@@ -993,8 +1001,7 @@
 	       info->irq);
 #endif
 	
-	save_flags(flags); cli(); /* Disable interrupts */
-
+	spin_lock_irqsave(&info->lock, flags);
 	/*
 	 * clear delta_msr_wait queue to avoid mem leaks: we may free the irq
 	 * here so the queue might never be waken up
@@ -1003,7 +1010,7 @@
 	wake_up_interruptible(&info->break_wait);
 
 	/* stop a DMA transfer on the port being closed */
-	   
+	/* DMA lock is higher priority always */
 	if (info->stat_flags & (ESP_STAT_DMA_RX | ESP_STAT_DMA_TX)) {
 		f=claim_dma_lock();
 		disable_dma(dma);
@@ -1058,7 +1065,7 @@
 		set_bit(TTY_IO_ERROR, &info->tty->flags);
 	
 	info->flags &= ~ASYNC_INITIALIZED;
-	restore_flags(flags);
+	spin_unlock_irqrestore(&info->lock, flags);
 }
 
 /*
@@ -1172,7 +1179,7 @@
 	if (I_IXOFF(info->tty))
 		flow1 |= 0x81;
 
-	save_flags(flags); cli();
+	spin_lock_irqsave(&info->lock, flags);
 	/* set baud */
 	serial_out(info, UART_ESI_CMD1, ESI_SET_BAUD);
 	serial_out(info, UART_ESI_CMD2, quot >> 8);
@@ -1219,7 +1226,7 @@
 	serial_out(info, UART_ESI_CMD2, info->config.flow_on >> 8);
 	serial_out(info, UART_ESI_CMD2, info->config.flow_on);
 
-	restore_flags(flags);
+	spin_unlock_irqrestore(&info->lock, flags);
 }
 
 static void rs_put_char(struct tty_struct *tty, unsigned char ch)
@@ -1233,16 +1240,13 @@
 	if (!tty || !info->xmit_buf)
 		return;
 
-	save_flags(flags); cli();
-	if (info->xmit_cnt >= ESP_XMIT_SIZE - 1) {
-		restore_flags(flags);
-		return;
+	spin_lock_irqsave(&info->lock, flags);
+	if (info->xmit_cnt < ESP_XMIT_SIZE - 1) {
+		info->xmit_buf[info->xmit_head++] = ch;
+		info->xmit_head &= ESP_XMIT_SIZE-1;
+		info->xmit_cnt++;
 	}
-
-	info->xmit_buf[info->xmit_head++] = ch;
-	info->xmit_head &= ESP_XMIT_SIZE-1;
-	info->xmit_cnt++;
-	restore_flags(flags);
+	spin_unlock_irqrestore(&info->lock, flags);
 }
 
 static void rs_flush_chars(struct tty_struct *tty)
@@ -1253,16 +1257,18 @@
 	if (serial_paranoia_check(info, tty->name, "rs_flush_chars"))
 		return;
 
+	spin_lock_irqsave(&info->lock, flags);
+
 	if (info->xmit_cnt <= 0 || tty->stopped || !info->xmit_buf)
-		return;
+		goto out;
 
-	save_flags(flags); cli();
 	if (!(info->IER & UART_IER_THRI)) {
 		info->IER |= UART_IER_THRI;
 		serial_out(info, UART_ESI_CMD1, ESI_SET_SRV_MASK);
 		serial_out(info, UART_ESI_CMD2, info->IER);
 	}
-	restore_flags(flags);
+out:
+	spin_unlock_irqrestore(&info->lock, flags);
 }
 
 static int rs_write(struct tty_struct * tty,
@@ -1305,7 +1311,7 @@
 		ret += c;
 	}
 
-	save_flags(flags); cli();
+	spin_lock_irqsave(&info->lock, flags);
 
 	if (info->xmit_cnt && !tty->stopped && !(info->IER & UART_IER_THRI)) {
 		info->IER |= UART_IER_THRI;
@@ -1313,7 +1319,7 @@
 		serial_out(info, UART_ESI_CMD2, info->IER);
 	}
 
-	restore_flags(flags);
+	spin_unlock_irqrestore(&info->lock, flags);
 	return ret;
 }
 
@@ -1321,12 +1327,17 @@
 {
 	struct esp_struct *info = (struct esp_struct *)tty->driver_data;
 	int	ret;
+	unsigned long flags;
 				
 	if (serial_paranoia_check(info, tty->name, "rs_write_room"))
 		return 0;
+
+	spin_lock_irqsave(&info->lock, flags);
+
 	ret = ESP_XMIT_SIZE - info->xmit_cnt - 1;
 	if (ret < 0)
 		ret = 0;
+	spin_unlock_irqrestore(&info->lock, flags);
 	return ret;
 }
 
@@ -1342,12 +1353,13 @@
 static void rs_flush_buffer(struct tty_struct *tty)
 {
 	struct esp_struct *info = (struct esp_struct *)tty->driver_data;
+	unsigned long flags;
 				
 	if (serial_paranoia_check(info, tty->name, "rs_flush_buffer"))
 		return;
-	cli();
+	spin_lock_irqsave(&info->lock, flags);
 	info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
-	sti();
+	spin_unlock_irqrestore(&info->lock, flags);
 	tty_wakeup(tty);
 }
 
@@ -1362,6 +1374,7 @@
 static void rs_throttle(struct tty_struct * tty)
 {
 	struct esp_struct *info = (struct esp_struct *)tty->driver_data;
+	unsigned long flags;
 #ifdef SERIAL_DEBUG_THROTTLE
 	char	buf[64];
 	
@@ -1371,19 +1384,20 @@
 
 	if (serial_paranoia_check(info, tty->name, "rs_throttle"))
 		return;
-	
-	cli();
+
+	spin_lock_irqsave(&info->lock, flags);
 	info->IER &= ~UART_IER_RDI;
 	serial_out(info, UART_ESI_CMD1, ESI_SET_SRV_MASK);
 	serial_out(info, UART_ESI_CMD2, info->IER);
 	serial_out(info, UART_ESI_CMD1, ESI_SET_RX_TIMEOUT);
 	serial_out(info, UART_ESI_CMD2, 0x00);
-	sti();
+	spin_unlock_irqrestore(&info->lock, flags);
 }
 
 static void rs_unthrottle(struct tty_struct * tty)
 {
 	struct esp_struct *info = (struct esp_struct *)tty->driver_data;
+	unsigned long flags;
 #ifdef SERIAL_DEBUG_THROTTLE
 	char	buf[64];
 	
@@ -1394,13 +1408,13 @@
 	if (serial_paranoia_check(info, tty->name, "rs_unthrottle"))
 		return;
 	
-	cli();
+	spin_lock_irqsave(&info->lock, flags);
 	info->IER |= UART_IER_RDI;
 	serial_out(info, UART_ESI_CMD1, ESI_SET_SRV_MASK);
 	serial_out(info, UART_ESI_CMD2, info->IER);
 	serial_out(info, UART_ESI_CMD1, ESI_SET_RX_TIMEOUT);
 	serial_out(info, UART_ESI_CMD2, info->config.rx_timeout);
-	sti();
+	spin_unlock_irqrestore(&info->lock, flags);
 }
 
 /*
@@ -1573,6 +1587,7 @@
 	unsigned int change_dma;
 	int retval = 0;
 	struct esp_struct *current_async;
+	unsigned long flags;
 
 	/* Perhaps a non-sysadmin user should be able to do some of these */
 	/* operations.  I haven't decided yet. */
@@ -1628,12 +1643,14 @@
 			
                         /* all ports must use the same DMA channel */
 
+			spin_lock_irqsave(&info->lock, flags);
 			current_async = ports;
 
 			while (current_async) {
 				esp_basic_init(current_async);
 				current_async = current_async->next_port;
 			}
+			spin_unlock_irqrestore(&info->lock, flags);
 		} else {
 			/* DMA mode to PIO mode only */
 			
@@ -1641,8 +1658,10 @@
 				return -EBUSY;
 
 			shutdown(info);
+			spin_lock_irqsave(&info->lock, flags);
 			info->stat_flags |= ESP_STAT_NEVER_DMA;
 			esp_basic_init(info);
+			spin_unlock_irqrestore(&info->lock, flags);
 		}
 	}
 
@@ -1654,13 +1673,14 @@
 
 		info->config.flow_off = new_config.flow_off;
 		info->config.flow_on = new_config.flow_on;
-		save_flags(flags); cli();
+
+		spin_lock_irqsave(&info->lock, flags);
 		serial_out(info, UART_ESI_CMD1, ESI_SET_FLOW_LVL);
 		serial_out(info, UART_ESI_CMD2, new_config.flow_off >> 8);
 		serial_out(info, UART_ESI_CMD2, new_config.flow_off);
 		serial_out(info, UART_ESI_CMD2, new_config.flow_on >> 8);
 		serial_out(info, UART_ESI_CMD2, new_config.flow_on);
-		restore_flags(flags);
+		spin_unlock_irqrestore(&info->lock, flags);
 	}
 
 	if ((new_config.rx_trigger != info->config.rx_trigger) ||
@@ -1669,7 +1689,7 @@
 
 		info->config.rx_trigger = new_config.rx_trigger;
 		info->config.tx_trigger = new_config.tx_trigger;
-		save_flags(flags); cli();
+		spin_lock_irqsave(&info->lock, flags);
 		serial_out(info, UART_ESI_CMD1, ESI_SET_TRIGGER);
 		serial_out(info, UART_ESI_CMD2,
 			   new_config.rx_trigger >> 8);
@@ -1677,14 +1697,14 @@
 		serial_out(info, UART_ESI_CMD2,
 			   new_config.tx_trigger >> 8);
 		serial_out(info, UART_ESI_CMD2, new_config.tx_trigger);
-		restore_flags(flags);
+		spin_unlock_irqrestore(&info->lock, flags);
 	}
 
 	if (new_config.rx_timeout != info->config.rx_timeout) {
 		unsigned long flags;
 
 		info->config.rx_timeout = new_config.rx_timeout;
-		save_flags(flags); cli();
+		spin_lock_irqsave(&info->lock, flags);
 
 		if (info->IER & UART_IER_RDI) {
 			serial_out(info, UART_ESI_CMD1,
@@ -1693,7 +1713,7 @@
 				   new_config.rx_timeout);
 		}
 
-		restore_flags(flags);
+		spin_unlock_irqrestore(&info->lock, flags);
 	}
 
 	if (!(info->flags & ASYNC_INITIALIZED))
@@ -1716,11 +1736,12 @@
 {
 	unsigned char status;
 	unsigned int result;
+	unsigned long flags;
 
-	cli();
+	spin_lock_irqsave(&info->lock, flags);
 	serial_out(info, UART_ESI_CMD1, ESI_GET_UART_STAT);
 	status = serial_in(info, UART_ESI_STAT1);
-	sti();
+	spin_unlock_irqrestore(&info->lock, flags);
 	result = ((status & UART_LSR_TEMT) ? TIOCSER_TEMT : 0);
 	return put_user(result,value);
 }
@@ -1730,6 +1751,7 @@
 {
 	struct esp_struct * info = (struct esp_struct *)tty->driver_data;
 	unsigned char control, status;
+	unsigned long flags;
 
 	if (serial_paranoia_check(info, tty->name, __FUNCTION__))
 		return -ENODEV;
@@ -1737,10 +1759,12 @@
 		return -EIO;
 
 	control = info->MCR;
-	cli();
+
+	spin_lock_irqsave(&info->lock, flags);
 	serial_out(info, UART_ESI_CMD1, ESI_GET_UART_STAT);
 	status = serial_in(info, UART_ESI_STAT2);
-	sti();
+	spin_unlock_irqrestore(&info->lock, flags);
+
 	return    ((control & UART_MCR_RTS) ? TIOCM_RTS : 0)
 		| ((control & UART_MCR_DTR) ? TIOCM_DTR : 0)
 		| ((status  & UART_MSR_DCD) ? TIOCM_CAR : 0)
@@ -1753,13 +1777,14 @@
 			unsigned int set, unsigned int clear)
 {
 	struct esp_struct * info = (struct esp_struct *)tty->driver_data;
+	unsigned long flags;
 
 	if (serial_paranoia_check(info, tty->name, __FUNCTION__))
 		return -ENODEV;
 	if (tty->flags & (1 << TTY_IO_ERROR))
 		return -EIO;
 
-	cli();
+	spin_lock_irqsave(&info->lock, flags);
 
 	if (set & TIOCM_RTS)
 		info->MCR |= UART_MCR_RTS;
@@ -1774,7 +1799,8 @@
 	serial_out(info, UART_ESI_CMD1, ESI_WRITE_UART);
 	serial_out(info, UART_ESI_CMD2, UART_MCR);
 	serial_out(info, UART_ESI_CMD2, info->MCR);
-	sti();
+
+	spin_unlock_irqrestore(&info->lock, flags);
 	return 0;
 }
 
@@ -1789,17 +1815,20 @@
 	if (serial_paranoia_check(info, tty->name, "esp_break"))
 		return;
 
-	save_flags(flags); cli();
 	if (break_state == -1) {
+		spin_lock_irqsave(&info->lock, flags);
 		serial_out(info, UART_ESI_CMD1, ESI_ISSUE_BREAK);
 		serial_out(info, UART_ESI_CMD2, 0x01);
+		spin_unlock_irqrestore(&info->lock, flags);
 
+		/* FIXME - new style wait needed here */
 		interruptible_sleep_on(&info->break_wait);
 	} else {
+		spin_lock_irqsave(&info->lock, flags);
 		serial_out(info, UART_ESI_CMD1, ESI_ISSUE_BREAK);
 		serial_out(info, UART_ESI_CMD2, 0x00);
+		spin_unlock_irqrestore(&info->lock, flags);
 	}
-	restore_flags(flags);
 }
 
 static int rs_ioctl(struct tty_struct *tty, struct file * file,
@@ -1809,6 +1838,7 @@
 	struct async_icount cprev, cnow;	/* kernel counter temps */
 	struct serial_icounter_struct __user *p_cuser;	/* user space */
 	void __user *argp = (void __user *)arg;
+	unsigned long flags;
 
 	if (serial_paranoia_check(info, tty->name, "rs_ioctl"))
 		return -ENODEV;
@@ -1849,17 +1879,18 @@
 		 * Caller should use TIOCGICOUNT to see which one it was
 		 */
 		 case TIOCMIWAIT:
-			cli();
+			spin_lock_irqsave(&info->lock, flags);
 			cprev = info->icount;	/* note the counters on entry */
-			sti();
+			spin_unlock_irqrestore(&info->lock, flags);
 			while (1) {
+				/* FIXME: convert to new style wakeup */
 				interruptible_sleep_on(&info->delta_msr_wait);
 				/* see if a signal did it */
 				if (signal_pending(current))
 					return -ERESTARTSYS;
-				cli();
+				spin_lock_irqsave(&info->lock, flags);
 				cnow = info->icount;	/* atomic copy */
-				sti();
+				spin_unlock_irqrestore(&info->lock, flags);
 				if (cnow.rng == cprev.rng &&
 				    cnow.dsr == cprev.dsr && 
 				    cnow.dcd == cprev.dcd &&
@@ -1886,9 +1917,9 @@
 		 *     RI where only 0->1 is counted.
 		 */
 		case TIOCGICOUNT:
-			cli();
+			spin_lock_irqsave(&info->lock, flags);
 			cnow = info->icount;
-			sti();
+			spin_unlock_irqrestore(&info->lock, flags);
 			p_cuser = argp;
 			if (put_user(cnow.cts, &p_cuser->cts) ||
 			    put_user(cnow.dsr, &p_cuser->dsr) ||
@@ -1911,53 +1942,42 @@
 static void rs_set_termios(struct tty_struct *tty, struct termios *old_termios)
 {
 	struct esp_struct *info = (struct esp_struct *)tty->driver_data;
+	unsigned long flags;
 
 	if (   (tty->termios->c_cflag == old_termios->c_cflag)
 	    && (   RELEVANT_IFLAG(tty->termios->c_iflag) 
 		== RELEVANT_IFLAG(old_termios->c_iflag)))
-	  return;
+		return;
 
 	change_speed(info);
 
+	spin_lock_irqsave(&info->lock, flags);
+
 	/* Handle transition to B0 status */
 	if ((old_termios->c_cflag & CBAUD) &&
 		!(tty->termios->c_cflag & CBAUD)) {
 		info->MCR &= ~(UART_MCR_DTR|UART_MCR_RTS);
-		cli();
 		serial_out(info, UART_ESI_CMD1, ESI_WRITE_UART);
 		serial_out(info, UART_ESI_CMD2, UART_MCR);
 		serial_out(info, UART_ESI_CMD2, info->MCR);
-		sti();
 	}
 
 	/* Handle transition away from B0 status */
 	if (!(old_termios->c_cflag & CBAUD) &&
 		(tty->termios->c_cflag & CBAUD)) {
 		info->MCR |= (UART_MCR_DTR | UART_MCR_RTS);
-		cli();
 		serial_out(info, UART_ESI_CMD1, ESI_WRITE_UART);
 		serial_out(info, UART_ESI_CMD2, UART_MCR);
 		serial_out(info, UART_ESI_CMD2, info->MCR);
-		sti();
 	}
 
+	spin_unlock_irqrestore(&info->lock, flags);
+
 	/* Handle turning of CRTSCTS */
 	if ((old_termios->c_cflag & CRTSCTS) &&
 	    !(tty->termios->c_cflag & CRTSCTS)) {
 		rs_start(tty);
 	}
-
-#if 0
-	/*
-	 * No need to wake up processes in open wait, since they
-	 * sample the CLOCAL flag once, and don't recheck it.
-	 * XXX  It's not clear whether the current behavior is correct
-	 * or not.  Hence, this may change.....
-	 */
-	if (!(old_termios->c_cflag & CLOCAL) &&
-	    (tty->termios->c_cflag & CLOCAL))
-		wake_up_interruptible(&info->open_wait);
-#endif
 }
 
 /*
@@ -1978,7 +1998,7 @@
 	if (!info || serial_paranoia_check(info, tty->name, "rs_close"))
 		return;
 	
-	save_flags(flags); cli();
+	spin_lock_irqsave(&info->lock, flags);
 	
 	if (tty_hung_up_p(filp)) {
 		DBG_CNT("before DEC-hung");
@@ -2010,6 +2030,8 @@
 		goto out;
 	}
 	info->flags |= ASYNC_CLOSING;
+
+	spin_unlock_irqrestore(&info->lock, flags);
 	/*
 	 * Now we wait for the transmit buffer to clear; and we notify 
 	 * the line discipline to only process XON/XOFF characters.
@@ -2027,6 +2049,8 @@
 	info->IER &= ~UART_IER_RDI;
 	info->read_status_mask &= ~UART_LSR_DR;
 	if (info->flags & ASYNC_INITIALIZED) {
+
+		spin_lock_irqsave(&info->lock, flags);
 		serial_out(info, UART_ESI_CMD1, ESI_SET_SRV_MASK);
 		serial_out(info, UART_ESI_CMD2, info->IER);
 
@@ -2034,6 +2058,8 @@
 		serial_out(info, UART_ESI_CMD1, ESI_SET_RX_TIMEOUT);
 		serial_out(info, UART_ESI_CMD2, 0x00);
 
+		spin_unlock_irqrestore(&info->lock, flags);
+
 		/*
 		 * Before we drop DTR, make sure the UART transmitter
 		 * has completely drained; this is especially
@@ -2057,8 +2083,10 @@
 	}
 	info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING);
 	wake_up_interruptible(&info->close_wait);
+	return;
+
 out:
-	restore_flags(flags);
+	spin_unlock_irqrestore(&info->lock, flags);
 }
 
 static void rs_wait_until_sent(struct tty_struct *tty, int timeout)
@@ -2076,12 +2104,14 @@
 	if (!char_time)
 		char_time = 1;
 
-	save_flags(flags); cli();
+	spin_lock_irqsave(&info->lock, flags);
 	serial_out(info, UART_ESI_CMD1, ESI_NO_COMMAND);
 	serial_out(info, UART_ESI_CMD1, ESI_GET_TX_AVAIL);
 
 	while ((serial_in(info, UART_ESI_STAT1) != 0x03) ||
 		(serial_in(info, UART_ESI_STAT2) != 0xff)) {
+
+		spin_unlock_irqrestore(&info->lock, flags);
 		msleep_interruptible(jiffies_to_msecs(char_time));
 
 		if (signal_pending(current))
@@ -2090,11 +2120,11 @@
 		if (timeout && time_after(jiffies, orig_jiffies + timeout))
 			break;
 
+		spin_lock_irqsave(&info->lock, flags);
 		serial_out(info, UART_ESI_CMD1, ESI_NO_COMMAND);
 		serial_out(info, UART_ESI_CMD1, ESI_GET_TX_AVAIL);
 	}
-	
-	restore_flags(flags);
+	spin_unlock_irqrestore(&info->lock, flags);
 	set_current_state(TASK_RUNNING);
 }
 
@@ -2174,15 +2204,11 @@
 	printk("block_til_ready before block: ttys%d, count = %d\n",
 	       info->line, info->count);
 #endif
-	save_flags(flags);
-	cli();
+	spin_lock_irqsave(&info->lock, flags);
 	if (!tty_hung_up_p(filp)) 
 		info->count--;
-	restore_flags(flags);
 	info->blocked_open++;
 	while (1) {
-		save_flags(flags);
-		cli();
 		if ((tty->termios->c_cflag & CBAUD)) {
 			unsigned int scratch;
 
@@ -2194,7 +2220,6 @@
 			serial_out(info, UART_ESI_CMD2,
 				scratch | UART_MCR_DTR | UART_MCR_RTS);
 		}
-		restore_flags(flags);
 		set_current_state(TASK_INTERRUPTIBLE);
 		if (tty_hung_up_p(filp) ||
 		    !(info->flags & ASYNC_INITIALIZED)) {
@@ -2224,13 +2249,16 @@
 		printk("block_til_ready blocking: ttys%d, count = %d\n",
 		       info->line, info->count);
 #endif
+		spin_unlock_irqrestore(&info->lock, flags);
 		schedule();
+		spin_lock_irqsave(&info->lock, flags);
 	}
 	set_current_state(TASK_RUNNING);
 	remove_wait_queue(&info->open_wait, &wait);
 	if (!tty_hung_up_p(filp))
 		info->count++;
 	info->blocked_open--;
+	spin_unlock_irqrestore(&info->lock, flags);
 #ifdef SERIAL_DEBUG_OPEN
 	printk("block_til_ready after blocking: ttys%d, count = %d\n",
 	       info->line, info->count);
@@ -2251,6 +2279,7 @@
 {
 	struct esp_struct	*info;
 	int 			retval, line;
+	unsigned long		flags;
 
 	line = tty->index;
 	if ((line < 0) || (line >= NR_PORTS))
@@ -2271,6 +2300,7 @@
 #ifdef SERIAL_DEBUG_OPEN
 	printk("esp_open %s, count = %d\n", tty->name, info->count);
 #endif
+	spin_lock_irqsave(&info->lock, flags);
 	info->count++;
 	tty->driver_data = info;
 	info->tty = tty;
@@ -2317,7 +2347,7 @@
  * driver.
  */
  
-static _INLINE_ void show_serial_version(void)
+static inline void show_serial_version(void)
 {
  	printk(KERN_INFO "%s version %s (DMA %u)\n",
 		serial_name, serial_version, dma);
@@ -2327,7 +2357,7 @@
  * This routine is called by espserial_init() to initialize a specific serial
  * port.
  */
-static _INLINE_ int autoconfig(struct esp_struct * info)
+static inline int autoconfig(struct esp_struct * info)
 {
 	int port_detected = 0;
 	unsigned long flags;
@@ -2335,8 +2365,7 @@
 	if (!request_region(info->port, REGION_SIZE, "esp serial"))
 		return -EIO;
 
-	save_flags(flags); cli();
-	
+	spin_lock_irqsave(&info->lock, flags);
 	/*
 	 * Check for ESP card
 	 */
@@ -2372,7 +2401,7 @@
 	if (!port_detected)
 		release_region(info->port, REGION_SIZE);
 
-	restore_flags(flags);
+	spin_unlock_irqrestore(&info->lock, flags);
 	return (port_detected);
 }
 
@@ -2513,6 +2542,7 @@
 		init_waitqueue_head(&info->close_wait);
 		init_waitqueue_head(&info->delta_msr_wait);
 		init_waitqueue_head(&info->break_wait);
+		spin_lock_init(&info->lock);
 		ports = info;
 		printk(KERN_INFO "ttyP%d at 0x%04x (irq = %d) is an ESP ",
 			info->line, info->port, info->irq);
@@ -2563,18 +2593,14 @@
 
 static void __exit espserial_exit(void) 
 {
-	unsigned long flags;
 	int e1;
 	struct esp_struct *temp_async;
 	struct esp_pio_buffer *pio_buf;
 
 	/* printk("Unloading %s: version %s\n", serial_name, serial_version); */
-	save_flags(flags);
-	cli();
 	if ((e1 = tty_unregister_driver(esp_driver)))
 		printk("SERIAL: failed to unregister serial driver (%d)\n",
 		       e1);
-	restore_flags(flags);
 	put_tty_driver(esp_driver);
 
 	while (ports) {
diff -Nru a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c
--- a/drivers/char/ipmi/ipmi_msghandler.c	2005-03-11 12:51:46 -08:00
+++ b/drivers/char/ipmi/ipmi_msghandler.c	2005-03-11 12:51:46 -08:00
@@ -612,6 +612,7 @@
 	unsigned long flags;
 	ipmi_user_t   new_user;
 	int           rv = 0;
+	ipmi_smi_t    intf;
 
 	/* There is no module usecount here, because it's not
            required.  Since this can only be used by and called from
@@ -646,19 +647,29 @@
 		goto out_unlock;
 	}
 
+	intf = ipmi_interfaces[if_num];
+
 	new_user->handler = handler;
 	new_user->handler_data = handler_data;
-	new_user->intf = ipmi_interfaces[if_num];
+	new_user->intf = intf;
 	new_user->gets_events = 0;
 
-	if (!try_module_get(new_user->intf->handlers->owner)) {
+	if (!try_module_get(intf->handlers->owner)) {
 		rv = -ENODEV;
 		goto out_unlock;
 	}
 
-	write_lock_irqsave(&new_user->intf->users_lock, flags);
-	list_add_tail(&new_user->link, &new_user->intf->users);
-	write_unlock_irqrestore(&new_user->intf->users_lock, flags);
+	if (intf->handlers->inc_usecount) {
+		rv = intf->handlers->inc_usecount(intf->send_info);
+		if (rv) {
+			module_put(intf->handlers->owner);
+			goto out_unlock;
+		}
+	}
+
+	write_lock_irqsave(&intf->users_lock, flags);
+	list_add_tail(&new_user->link, &intf->users);
+	write_unlock_irqrestore(&intf->users_lock, flags);
 
  out_unlock:	
 	if (rv) {
@@ -729,8 +740,11 @@
 	down_read(&interfaces_sem);
 	write_lock_irqsave(&intf->users_lock, flags);
 	rv = ipmi_destroy_user_nolock(user);
-	if (!rv)
+	if (!rv) {
 		module_put(intf->handlers->owner);
+		if (intf->handlers->dec_usecount)
+			intf->handlers->dec_usecount(intf->send_info);
+	}
 		
 	write_unlock_irqrestore(&intf->users_lock, flags);
 	up_read(&interfaces_sem);
@@ -1629,6 +1643,7 @@
 		      void		       *send_info,
 		      unsigned char            version_major,
 		      unsigned char            version_minor,
+		      unsigned char            slave_addr,
 		      ipmi_smi_t               *intf)
 {
 	int              i, j;
@@ -1664,7 +1679,10 @@
 			new_intf->intf_num = i;
 			new_intf->version_major = version_major;
 			new_intf->version_minor = version_minor;
-			new_intf->my_address = IPMI_BMC_SLAVE_ADDR;
+			if (slave_addr == 0)
+				new_intf->my_address = IPMI_BMC_SLAVE_ADDR;
+			else
+				new_intf->my_address = slave_addr;
 			new_intf->my_lun = 2;  /* the SMS LUN. */
 			rwlock_init(&(new_intf->users_lock));
 			INIT_LIST_HEAD(&(new_intf->users));
diff -Nru a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c
--- a/drivers/char/ipmi/ipmi_si_intf.c	2005-03-11 12:51:41 -08:00
+++ b/drivers/char/ipmi/ipmi_si_intf.c	2005-03-11 12:51:41 -08:00
@@ -176,6 +176,9 @@
 	unsigned char ipmi_version_major;
 	unsigned char ipmi_version_minor;
 
+	/* Slave address, could be reported from DMI. */
+	unsigned char slave_addr;
+
 	/* Counters and things for the proc filesystem. */
 	spinlock_t count_lock;
 	unsigned long short_timeouts;
@@ -407,7 +410,7 @@
 			/* Error fetching flags, just give up for
 			   now. */
 			smi_info->si_state = SI_NORMAL;
-		} else if (len < 3) {
+		} else if (len < 4) {
 			/* Hmm, no flags.  That's technically illegal, but
 			   don't use uninitialized data. */
 			smi_info->si_state = SI_NORMAL;
@@ -897,21 +900,23 @@
 #define DEFAULT_REGSPACING	1
 
 static int           si_trydefaults = 1;
-static char          *si_type[SI_MAX_PARMS] = { NULL, NULL, NULL, NULL };
+static char          *si_type[SI_MAX_PARMS];
 #define MAX_SI_TYPE_STR 30
 static char          si_type_str[MAX_SI_TYPE_STR];
-static unsigned long addrs[SI_MAX_PARMS] = { 0, 0, 0, 0 };
-static int num_addrs = 0;
-static unsigned int  ports[SI_MAX_PARMS] = { 0, 0, 0, 0 };
-static int num_ports = 0;
-static int           irqs[SI_MAX_PARMS] = { 0, 0, 0, 0 };
-static int num_irqs = 0;
-static int           regspacings[SI_MAX_PARMS] = { 0, 0, 0, 0 };
+static unsigned long addrs[SI_MAX_PARMS];
+static int num_addrs;
+static unsigned int  ports[SI_MAX_PARMS];
+static int num_ports;
+static int           irqs[SI_MAX_PARMS];
+static int num_irqs;
+static int           regspacings[SI_MAX_PARMS];
 static int num_regspacings = 0;
-static int           regsizes[SI_MAX_PARMS] = { 0, 0, 0, 0 };
+static int           regsizes[SI_MAX_PARMS];
 static int num_regsizes = 0;
-static int           regshifts[SI_MAX_PARMS] = { 0, 0, 0, 0 };
+static int           regshifts[SI_MAX_PARMS];
 static int num_regshifts = 0;
+static int slave_addrs[SI_MAX_PARMS];
+static int num_slave_addrs = 0;
 
 
 module_param_named(trydefaults, si_trydefaults, bool, 0);
@@ -955,6 +960,12 @@
 		 " IPMI register, in bits.  For instance, if the data"
 		 " is read from a 32-bit word and the IPMI data is in"
 		 " bit 8-15, then the shift would be 8");
+module_param_array(slave_addrs, int, &num_slave_addrs, 0);
+MODULE_PARM_DESC(slave_addrs, "Set the default IPMB slave address for"
+		 " the controller.  Normally this is 0x20, but can be"
+		 " overridden by this parm.  This is an array indexed"
+		 " by interface number.");
+
 
 #define IPMI_MEM_ADDR_SPACE 1
 #define IPMI_IO_ADDR_SPACE  2
@@ -1542,7 +1553,6 @@
 #endif
 
 #ifdef CONFIG_X86
-
 typedef struct dmi_ipmi_data
 {
 	u8   		type;
@@ -1550,21 +1560,26 @@
 	unsigned long	base_addr;
 	u8   		irq;
 	u8              offset;
-}dmi_ipmi_data_t;
+	u8              slave_addr;
+} dmi_ipmi_data_t;
+
+static dmi_ipmi_data_t dmi_data[SI_MAX_DRIVERS];
+static int dmi_data_entries;
 
 typedef struct dmi_header
 {
 	u8	type;
 	u8	length;
 	u16	handle;
-}dmi_header_t;
+} dmi_header_t;
 
-static int decode_dmi(dmi_header_t *dm, dmi_ipmi_data_t *ipmi_data)
+static int decode_dmi(dmi_header_t *dm, int intf_num)
 {
 	u8		*data = (u8 *)dm;
 	unsigned long  	base_addr;
 	u8		reg_spacing;
 	u8              len = dm->length;
+	dmi_ipmi_data_t *ipmi_data = dmi_data+intf_num;
 
 	ipmi_data->type = data[4];
 
@@ -1608,22 +1623,26 @@
 		ipmi_data->offset = 1;
 	}
 
-	if (is_new_interface(-1, ipmi_data->addr_space,ipmi_data->base_addr))
+	ipmi_data->slave_addr = data[6];
+
+	if (is_new_interface(-1, ipmi_data->addr_space,ipmi_data->base_addr)) {
+		dmi_data_entries++;
 		return 0;
+	}
 
 	memset(ipmi_data, 0, sizeof(dmi_ipmi_data_t));
 
 	return -1;
 }
 
-static int dmi_table(u32 base, int len, int num,
-	dmi_ipmi_data_t *ipmi_data)
+static int dmi_table(u32 base, int len, int num)
 {
 	u8 		  *buf;
 	struct dmi_header *dm;
 	u8 		  *data;
 	int 		  i=1;
 	int		  status=-1;
+	int               intf_num = 0;
 
 	buf = ioremap(base, len);
 	if(buf==NULL)
@@ -1639,9 +1658,10 @@
         		break;
 
 		if (dm->type == 38) {
-			if (decode_dmi(dm, ipmi_data) == 0) {
-				status = 0;
-				break;
+			if (decode_dmi(dm, intf_num) == 0) {
+				intf_num++;
+				if (intf_num >= SI_MAX_DRIVERS)
+					break;
 			}
 		}
 
@@ -1666,7 +1686,7 @@
 	return (sum==0);
 }
 
-static int dmi_iterator(dmi_ipmi_data_t *ipmi_data)
+static int dmi_decode(void)
 {
 	u8   buf[15];
 	u32  fp=0xF0000;
@@ -1684,7 +1704,7 @@
 			u16 len=buf[7]<<8|buf[6];
 			u32 base=buf[11]<<24|buf[10]<<16|buf[9]<<8|buf[8];
 
-			if(dmi_table(base, len, num, ipmi_data) == 0)
+			if(dmi_table(base, len, num) == 0)
 				return 0;
 		}
 		fp+=16;
@@ -1696,16 +1716,13 @@
 static int try_init_smbios(int intf_num, struct smi_info **new_info)
 {
 	struct smi_info   *info;
-	dmi_ipmi_data_t   ipmi_data;
+	dmi_ipmi_data_t   *ipmi_data = dmi_data+intf_num;
 	char              *io_type;
-	int               status;
-
-	status = dmi_iterator(&ipmi_data);
 
-	if (status < 0)
+	if (intf_num >= dmi_data_entries)
 		return -ENODEV;
 
-	switch(ipmi_data.type) {
+	switch(ipmi_data->type) {
 		case 0x01: /* KCS */
 			si_type[intf_num] = "kcs";
 			break;
@@ -1716,7 +1733,6 @@
 			si_type[intf_num] = "bt";
 			break;
 		default:
-			printk("ipmi_si: Unknown SMBIOS SI type.\n");
 			return -EIO;
 	}
 
@@ -1727,15 +1743,15 @@
 	}
 	memset(info, 0, sizeof(*info));
 
-	if (ipmi_data.addr_space == 1) {
+	if (ipmi_data->addr_space == 1) {
 		io_type = "memory";
 		info->io_setup = mem_setup;
-		addrs[intf_num] = ipmi_data.base_addr;
+		addrs[intf_num] = ipmi_data->base_addr;
 		info->io.info = &(addrs[intf_num]);
-	} else if (ipmi_data.addr_space == 2) {
+	} else if (ipmi_data->addr_space == 2) {
 		io_type = "I/O";
 		info->io_setup = port_setup;
-		ports[intf_num] = ipmi_data.base_addr;
+		ports[intf_num] = ipmi_data->base_addr;
 		info->io.info = &(ports[intf_num]);
 	} else {
 		kfree(info);
@@ -1743,20 +1759,23 @@
 		return -EIO;
 	}
 
-	regspacings[intf_num] = ipmi_data.offset;
+	regspacings[intf_num] = ipmi_data->offset;
 	info->io.regspacing = regspacings[intf_num];
 	if (!info->io.regspacing)
 		info->io.regspacing = DEFAULT_REGSPACING;
 	info->io.regsize = DEFAULT_REGSPACING;
 	info->io.regshift = regshifts[intf_num];
 
-	irqs[intf_num] = ipmi_data.irq;
+	info->slave_addr = ipmi_data->slave_addr;
+
+	irqs[intf_num] = ipmi_data->irq;
 
 	*new_info = info;
 
 	printk("ipmi_si: Found SMBIOS-specified state machine at %s"
-	       " address 0x%lx\n",
-	       io_type, (unsigned long)ipmi_data.base_addr);
+	       " address 0x%lx, slave address 0x%x\n",
+	       io_type, (unsigned long)ipmi_data->base_addr,
+	       ipmi_data->slave_addr);
 	return 0;
 }
 #endif /* CONFIG_X86 */
@@ -2121,6 +2140,7 @@
 			       new_smi,
 			       new_smi->ipmi_version_major,
 			       new_smi->ipmi_version_minor,
+			       new_smi->slave_addr,
 			       &(new_smi->intf));
 	if (rv) {
 		printk(KERN_ERR
@@ -2221,6 +2241,10 @@
 	if (bt_smi_handlers.version)
    	        printk(", BT version %s", bt_smi_handlers.version);
 	printk("\n");
+
+#ifdef CONFIG_X86
+	dmi_decode();
+#endif
 
 	rv = init_one_smi(0, &(smi_infos[pos]));
 	if (rv && !ports[0] && si_trydefaults) {
diff -Nru a/drivers/char/keyboard.c b/drivers/char/keyboard.c
--- a/drivers/char/keyboard.c	2005-03-11 12:51:52 -08:00
+++ b/drivers/char/keyboard.c	2005-03-11 12:51:52 -08:00
@@ -141,7 +141,7 @@
 /* Simple translation table for the SysRq keys */
 
 #ifdef CONFIG_MAGIC_SYSRQ
-unsigned char kbd_sysrq_xlate[KEY_MAX] =
+unsigned char kbd_sysrq_xlate[KEY_MAX + 1] =
         "\000\0331234567890-=\177\t"                    /* 0x00 - 0x0f */
         "qwertyuiop[]\r\000as"                          /* 0x10 - 0x1f */
         "dfghjkl;'`\000\\zxcv"                          /* 0x20 - 0x2f */
@@ -173,7 +173,7 @@
 	if (!dev)
 		return -ENODEV;
 
-	if (scancode < 0 || scancode >= dev->keycodemax)
+	if (scancode >= dev->keycodemax)
 		return -EINVAL;
 
 	return INPUT_KEYCODE(dev, scancode);
@@ -183,7 +183,7 @@
 {
 	struct list_head * node;
 	struct input_dev *dev = NULL;
-	int i, oldkey;
+	unsigned int i, oldkey;
 
 	list_for_each(node,&kbd_handler.h_list) {
 		struct input_handle *handle = to_handle_h(node);
@@ -196,7 +196,9 @@
 	if (!dev)
 		return -ENODEV;
 
-	if (scancode < 0 || scancode >= dev->keycodemax)
+	if (scancode >= dev->keycodemax)
+		return -EINVAL;
+	if (keycode > KEY_MAX)
 		return -EINVAL;
 	if (keycode < 0 || keycode > KEY_MAX)
 		return -EINVAL;
@@ -355,7 +357,7 @@
  */
 void compute_shiftstate(void)
 {
-	int i, j, k, sym, val;
+	unsigned int i, j, k, sym, val;
 
 	shift_state = 0;
 	memset(shift_down, 0, sizeof(shift_down));
@@ -396,7 +398,7 @@
 static unsigned char handle_diacr(struct vc_data *vc, unsigned char ch)
 {
 	int d = diacr;
-	int i;
+	unsigned int i;
 
 	diacr = 0;
 
@@ -536,12 +538,12 @@
 
 static void fn_scroll_forw(struct vc_data *vc, struct pt_regs *regs)
 {
-	scrollfront(0);
+	scrollfront(vc, 0);
 }
 
 static void fn_scroll_back(struct vc_data *vc, struct pt_regs *regs)
 {
-	scrollback(0);
+	scrollback(vc, 0);
 }
 
 static void fn_show_mem(struct vc_data *vc, struct pt_regs *regs)
@@ -581,7 +583,7 @@
 	 */
 	if (tty)
 		do_SAK(tty);
-	reset_vc(fg_console);
+	reset_vc(vc);
 }
 
 static void fn_null(struct vc_data *vc, struct pt_regs *regs)
@@ -931,7 +933,7 @@
 #if defined(CONFIG_X86) || defined(CONFIG_IA64) || defined(CONFIG_ALPHA) ||\
     defined(CONFIG_MIPS) || defined(CONFIG_PPC) || defined(CONFIG_SPARC32) ||\
     defined(CONFIG_SPARC64) || defined(CONFIG_PARISC) || defined(CONFIG_SUPERH) ||\
-    (defined(CONFIG_ARM) && defined(CONFIG_KEYBOARD_ATKBD) && !defined(CONFIG_RPC))
+    (defined(CONFIG_ARM) && defined(CONFIG_KEYBOARD_ATKBD) && !defined(CONFIG_ARCH_RPC))
 
 #define HW_RAW(dev) (test_bit(EV_MSC, dev->evbit) && test_bit(MSC_RAW, dev->mscbit) &&\
 			((dev)->id.bustype == BUS_I8042) && ((dev)->id.vendor == 0x0001) && ((dev)->id.product == 0x0001))
diff -Nru a/drivers/char/lp.c b/drivers/char/lp.c
--- a/drivers/char/lp.c	2005-03-11 12:51:40 -08:00
+++ b/drivers/char/lp.c	2005-03-11 12:51:40 -08:00
@@ -314,12 +314,14 @@
 	if (copy_size > LP_BUFFER_SIZE)
 		copy_size = LP_BUFFER_SIZE;
 
-	if (copy_from_user (kbuf, buf, copy_size))
-		return -EFAULT;
-
 	if (down_interruptible (&lp_table[minor].port_mutex))
 		return -EINTR;
 
+	if (copy_from_user (kbuf, buf, copy_size)) {
+		retv = -EFAULT;
+		goto out_unlock;
+	}
+
  	/* Claim Parport or sleep until it becomes available
  	 */
 	lp_claim_parport_or_block (&lp_table[minor]);
@@ -398,7 +400,7 @@
 		lp_table[minor].current_mode = IEEE1284_MODE_COMPAT;
 		lp_release_parport (&lp_table[minor]);
 	}
-
+out_unlock:
 	up (&lp_table[minor].port_mutex);
 
  	return retv;
diff -Nru a/drivers/char/mmtimer.c b/drivers/char/mmtimer.c
--- a/drivers/char/mmtimer.c	2005-03-11 12:51:47 -08:00
+++ b/drivers/char/mmtimer.c	2005-03-11 12:51:47 -08:00
@@ -376,7 +376,7 @@
 static struct timespec sgi_clock_offset;
 static int sgi_clock_period;
 
-static int sgi_clock_get(struct timespec *tp)
+static int sgi_clock_get(clockid_t clockid, struct timespec *tp)
 {
 	u64 nsec;
 
@@ -387,7 +387,7 @@
 	return 0;
 };
 
-static int sgi_clock_set(struct timespec *tp)
+static int sgi_clock_set(clockid_t clockid, struct timespec *tp)
 {
 
 	u64 nsec;
@@ -418,19 +418,19 @@
 	int n;
 	struct k_itimer *t = x->timer;
 
-	t->it_timer.magic = x->i;
+	t->it.mmtimer.clock = x->i;
 	t->it_overrun--;
 
 	n = 0;
 	do {
 
-		t->it_timer.expires += t->it_incr << n;
+		t->it.mmtimer.expires += t->it.mmtimer.incr << n;
 		t->it_overrun += 1 << n;
 		n++;
 		if (n > 20)
 			return 1;
 
-	} while (mmtimer_setup(x->i, t->it_timer.expires));
+	} while (mmtimer_setup(x->i, t->it.mmtimer.expires));
 
 	return 0;
 }
@@ -466,7 +466,7 @@
 		spin_lock(&base[i].lock);
 		if (base[i].cpu == smp_processor_id()) {
 			if (base[i].timer)
-				expires = base[i].timer->it_timer.expires;
+				expires = base[i].timer->it.mmtimer.expires;
 			/* expires test won't work with shared irqs */
 			if ((mmtimer_int_pending(i) > 0) ||
 				(expires && (expires < rtc_time()))) {
@@ -503,7 +503,7 @@
 
 		t->it_overrun++;
 	}
-	if(t->it_incr) {
+	if(t->it.mmtimer.incr) {
 		/* Periodic timer */
 		if (reschedule_periodic_timer(x)) {
 			printk(KERN_WARNING "mmtimer: unable to reschedule\n");
@@ -511,7 +511,7 @@
 		}
 	} else {
 		/* Ensure we don't false trigger in mmtimer_interrupt */
-		t->it_timer.expires = 0;
+		t->it.mmtimer.expires = 0;
 	}
 	t->it_overrun_last = t->it_overrun;
 out:
@@ -522,7 +522,7 @@
 static int sgi_timer_create(struct k_itimer *timer)
 {
 	/* Insure that a newly created timer is off */
-	timer->it_timer.magic = TIMER_OFF;
+	timer->it.mmtimer.clock = TIMER_OFF;
 	return 0;
 }
 
@@ -533,8 +533,8 @@
  */
 static int sgi_timer_del(struct k_itimer *timr)
 {
-	int i = timr->it_timer.magic;
-	cnodeid_t nodeid = timr->it_timer.data;
+	int i = timr->it.mmtimer.clock;
+	cnodeid_t nodeid = timr->it.mmtimer.node;
 	mmtimer_t *t = timers + nodeid * NUM_COMPARATORS +i;
 	unsigned long irqflags;
 
@@ -542,8 +542,8 @@
 		spin_lock_irqsave(&t->lock, irqflags);
 		mmtimer_disable_int(cnodeid_to_nasid(nodeid),i);
 		t->timer = NULL;
-		timr->it_timer.magic = TIMER_OFF;
-		timr->it_timer.expires = 0;
+		timr->it.mmtimer.clock = TIMER_OFF;
+		timr->it.mmtimer.expires = 0;
 		spin_unlock_irqrestore(&t->lock, irqflags);
 	}
 	return 0;
@@ -556,7 +556,7 @@
 static void sgi_timer_get(struct k_itimer *timr, struct itimerspec *cur_setting)
 {
 
-	if (timr->it_timer.magic == TIMER_OFF) {
+	if (timr->it.mmtimer.clock == TIMER_OFF) {
 		cur_setting->it_interval.tv_nsec = 0;
 		cur_setting->it_interval.tv_sec = 0;
 		cur_setting->it_value.tv_nsec = 0;
@@ -564,8 +564,8 @@
 		return;
 	}
 
-	ns_to_timespec(cur_setting->it_interval, timr->it_incr * sgi_clock_period);
-	ns_to_timespec(cur_setting->it_value, (timr->it_timer.expires - rtc_time())* sgi_clock_period);
+	ns_to_timespec(cur_setting->it_interval, timr->it.mmtimer.incr * sgi_clock_period);
+	ns_to_timespec(cur_setting->it_value, (timr->it.mmtimer.expires - rtc_time())* sgi_clock_period);
 	return;
 }
 
@@ -638,19 +638,19 @@
 	base[i].timer = timr;
 	base[i].cpu = smp_processor_id();
 
-	timr->it_timer.magic = i;
-	timr->it_timer.data = nodeid;
-	timr->it_incr = period;
-	timr->it_timer.expires = when;
+	timr->it.mmtimer.clock = i;
+	timr->it.mmtimer.node = nodeid;
+	timr->it.mmtimer.incr = period;
+	timr->it.mmtimer.expires = when;
 
 	if (period == 0) {
 		if (mmtimer_setup(i, when)) {
 			mmtimer_disable_int(-1, i);
 			posix_timer_event(timr, 0);
-			timr->it_timer.expires = 0;
+			timr->it.mmtimer.expires = 0;
 		}
 	} else {
-		timr->it_timer.expires -= period;
+		timr->it.mmtimer.expires -= period;
 		if (reschedule_periodic_timer(base+i))
 			err = -EINVAL;
 	}
diff -Nru a/drivers/char/random.c b/drivers/char/random.c
--- a/drivers/char/random.c	2005-03-11 12:51:41 -08:00
+++ b/drivers/char/random.c	2005-03-11 12:51:41 -08:00
@@ -218,13 +218,6 @@
  * Any flaws in the design are solely my responsibility, and should
  * not be attributed to the Phil, Colin, or any of authors of PGP.
  *
- * The code for SHA transform was taken from Peter Gutmann's
- * implementation, which has been placed in the public domain.
- * The code for MD5 transform was taken from Colin Plumb's
- * implementation, which has been placed in the public domain.
- * The MD5 cryptographic checksum was devised by Ronald Rivest, and is
- * documented in RFC 1321, "The MD5 Message Digest Algorithm".
- *
  * Further background information on this topic may be obtained from
  * RFC 1750, "Randomness Recommendations for Security", by Donald
  * Eastlake, Steve Crocker, and Jeff Schiller.
@@ -242,11 +235,11 @@
 #include <linux/poll.h>
 #include <linux/init.h>
 #include <linux/fs.h>
-#include <linux/workqueue.h>
 #include <linux/genhd.h>
 #include <linux/interrupt.h>
 #include <linux/spinlock.h>
 #include <linux/percpu.h>
+#include <linux/cryptohash.h>
 
 #include <asm/processor.h>
 #include <asm/uaccess.h>
@@ -256,10 +249,9 @@
 /*
  * Configuration information
  */
-#define DEFAULT_POOL_SIZE 512
-#define SECONDARY_POOL_SIZE 128
-#define BATCH_ENTROPY_SIZE 256
-#define USE_SHA
+#define INPUT_POOL_WORDS 128
+#define OUTPUT_POOL_WORDS 32
+#define SEC_XFER_SIZE 512
 
 /*
  * The minimum number of bits of entropy before we wake up a read on
@@ -279,7 +271,7 @@
  * samples to avoid wasting CPU time and reduce lock contention.
  */
 
-static int trickle_thresh = DEFAULT_POOL_SIZE * 7;
+static int trickle_thresh = INPUT_POOL_WORDS * 28;
 
 static DEFINE_PER_CPU(int, trickle_count) = 0;
 
@@ -295,42 +287,37 @@
 	int poolwords;
 	int tap1, tap2, tap3, tap4, tap5;
 } poolinfo_table[] = {
+	/* x^128 + x^103 + x^76 + x^51 +x^25 + x + 1 -- 105 */
+	{ 128,	103,	76,	51,	25,	1 },
+	/* x^32 + x^26 + x^20 + x^14 + x^7 + x + 1 -- 15 */
+	{ 32,	26,	20,	14,	7,	1 },
+#if 0
 	/* x^2048 + x^1638 + x^1231 + x^819 + x^411 + x + 1  -- 115 */
 	{ 2048,	1638,	1231,	819,	411,	1 },
 
 	/* x^1024 + x^817 + x^615 + x^412 + x^204 + x + 1 -- 290 */
 	{ 1024,	817,	615,	412,	204,	1 },
-#if 0				/* Alternate polynomial */
+
 	/* x^1024 + x^819 + x^616 + x^410 + x^207 + x^2 + 1 -- 115 */
 	{ 1024,	819,	616,	410,	207,	2 },
-#endif
 
 	/* x^512 + x^411 + x^308 + x^208 + x^104 + x + 1 -- 225 */
 	{ 512,	411,	308,	208,	104,	1 },
-#if 0				/* Alternates */
+
 	/* x^512 + x^409 + x^307 + x^206 + x^102 + x^2 + 1 -- 95 */
 	{ 512,	409,	307,	206,	102,	2 },
 	/* x^512 + x^409 + x^309 + x^205 + x^103 + x^2 + 1 -- 95 */
 	{ 512,	409,	309,	205,	103,	2 },
-#endif
 
 	/* x^256 + x^205 + x^155 + x^101 + x^52 + x + 1 -- 125 */
 	{ 256,	205,	155,	101,	52,	1 },
 
-	/* x^128 + x^103 + x^76 + x^51 +x^25 + x + 1 -- 105 */
-	{ 128,	103,	76,	51,	25,	1 },
-#if 0	/* Alternate polynomial */
 	/* x^128 + x^103 + x^78 + x^51 + x^27 + x^2 + 1 -- 70 */
 	{ 128,	103,	78,	51,	27,	2 },
-#endif
 
 	/* x^64 + x^52 + x^39 + x^26 + x^14 + x + 1 -- 15 */
 	{ 64,	52,	39,	26,	14,	1 },
-
-	/* x^32 + x^26 + x^20 + x^14 + x^7 + x + 1 -- 15 */
-	{ 32,	26,	20,	14,	7,	1 },
-
-	{ 0,	0,	0,	0,	0,	0 },
+#endif
 };
 
 #define POOLBITS	poolwords*32
@@ -380,104 +367,20 @@
  */
 
 /*
- * Linux 2.2 compatibility
- */
-#ifndef DECLARE_WAITQUEUE
-#define DECLARE_WAITQUEUE(WAIT, PTR) struct wait_queue WAIT = { PTR, NULL }
-#endif
-#ifndef DECLARE_WAIT_QUEUE_HEAD
-#define DECLARE_WAIT_QUEUE_HEAD(WAIT) struct wait_queue *WAIT
-#endif
-
-/*
  * Static global variables
  */
-static struct entropy_store *random_state; /* The default global store */
-static struct entropy_store *sec_random_state; /* secondary store */
-static struct entropy_store *urandom_state; /* For urandom */
 static DECLARE_WAIT_QUEUE_HEAD(random_read_wait);
 static DECLARE_WAIT_QUEUE_HEAD(random_write_wait);
 
-/*
- * Forward procedure declarations
- */
-#ifdef CONFIG_SYSCTL
-static void sysctl_init_random(struct entropy_store *random_state);
-#endif
-
-/*****************************************************************
- *
- * Utility functions, with some ASM defined functions for speed
- * purposes
- *
- *****************************************************************/
-
-/*
- * Unfortunately, while the GCC optimizer for the i386 understands how
- * to optimize a static rotate left of x bits, it doesn't know how to
- * deal with a variable rotate of x bits.  So we use a bit of asm magic.
- */
-#if (!defined (__i386__))
-static inline __u32 rotate_left(int i, __u32 word)
-{
-	return (word << i) | (word >> (32 - i));
-}
-#else
-static inline __u32 rotate_left(int i, __u32 word)
-{
-	__asm__("roll %%cl,%0"
-		:"=r" (word)
-		:"0" (word),"c" (i));
-	return word;
-}
-#endif
-
-/*
- * More asm magic....
- *
- * For entropy estimation, we need to do an integral base 2
- * logarithm.
- *
- * Note the "12bits" suffix - this is used for numbers between
- * 0 and 4095 only.  This allows a few shortcuts.
- */
-#if 0	/* Slow but clear version */
-static inline __u32 int_ln_12bits(__u32 word)
-{
-	__u32 nbits = 0;
-
-	while (word >>= 1)
-		nbits++;
-	return nbits;
-}
-#else	/* Faster (more clever) version, courtesy Colin Plumb */
-static inline __u32 int_ln_12bits(__u32 word)
-{
-	/* Smear msbit right to make an n-bit mask */
-	word |= word >> 8;
-	word |= word >> 4;
-	word |= word >> 2;
-	word |= word >> 1;
-	/* Remove one bit to make this a logarithm */
-	word >>= 1;
-	/* Count the bits set in the word */
-	word -= (word >> 1) & 0x555;
-	word = (word & 0x333) + ((word >> 2) & 0x333);
-	word += (word >> 4);
-	word += (word >> 8);
-	return word & 15;
-}
-#endif
-
 #if 0
 static int debug = 0;
 module_param(debug, bool, 0644);
 #define DEBUG_ENT(fmt, arg...) do { if (debug) \
 	printk(KERN_DEBUG "random %04d %04d %04d: " \
 	fmt,\
-	random_state->entropy_count,\
-	sec_random_state->entropy_count,\
-	urandom_state->entropy_count,\
+	input_pool.entropy_count,\
+	blocking_pool.entropy_count,\
+	nonblocking_pool.entropy_count,\
 	## arg); } while (0)
 #else
 #define DEBUG_ENT(fmt, arg...) do {} while (0)
@@ -490,11 +393,14 @@
  *
  **********************************************************************/
 
+struct entropy_store;
 struct entropy_store {
 	/* mostly-read data: */
-	struct poolinfo poolinfo;
+	struct poolinfo *poolinfo;
 	__u32 *pool;
 	const char *name;
+	int limit;
+	struct entropy_store *pull;
 
 	/* read-write data: */
 	spinlock_t lock ____cacheline_aligned_in_smp;
@@ -503,57 +409,34 @@
 	int input_rotate;
 };
 
-/*
- * Initialize the entropy store.  The input argument is the size of
- * the random pool.
- *
- * Returns an negative error if there is a problem.
- */
-static int create_entropy_store(int size, const char *name,
-				struct entropy_store **ret_bucket)
-{
-	struct entropy_store *r;
-	struct poolinfo *p;
-	int poolwords;
-
-	poolwords = (size + 3) / 4; /* Convert bytes->words */
-	/* The pool size must be a multiple of 16 32-bit words */
-	poolwords = ((poolwords + 15) / 16) * 16;
-
-	for (p = poolinfo_table; p->poolwords; p++) {
-		if (poolwords == p->poolwords)
-			break;
-	}
-	if (p->poolwords == 0)
-		return -EINVAL;
+static __u32 input_pool_data[INPUT_POOL_WORDS];
+static __u32 blocking_pool_data[OUTPUT_POOL_WORDS];
+static __u32 nonblocking_pool_data[OUTPUT_POOL_WORDS];
+
+static struct entropy_store input_pool = {
+	.poolinfo = &poolinfo_table[0],
+	.name = "input",
+	.limit = 1,
+	.lock = SPIN_LOCK_UNLOCKED,
+	.pool = input_pool_data
+};
 
-	r = kmalloc(sizeof(struct entropy_store), GFP_KERNEL);
-	if (!r)
-		return -ENOMEM;
-
-	memset (r, 0, sizeof(struct entropy_store));
-	r->poolinfo = *p;
-
-	r->pool = kmalloc(POOLBYTES, GFP_KERNEL);
-	if (!r->pool) {
-		kfree(r);
-		return -ENOMEM;
-	}
-	memset(r->pool, 0, POOLBYTES);
-	spin_lock_init(&r->lock);
-	r->name = name;
-	*ret_bucket = r;
-	return 0;
-}
+static struct entropy_store blocking_pool = {
+	.poolinfo = &poolinfo_table[1],
+	.name = "blocking",
+	.limit = 1,
+	.pull = &input_pool,
+	.lock = SPIN_LOCK_UNLOCKED,
+	.pool = blocking_pool_data
+};
 
-/* Clear the entropy pool and associated counters. */
-static void clear_entropy_store(struct entropy_store *r)
-{
-	r->add_ptr = 0;
-	r->entropy_count = 0;
-	r->input_rotate = 0;
-	memset(r->pool, 0, r->poolinfo.POOLBYTES);
-}
+static struct entropy_store nonblocking_pool = {
+	.poolinfo = &poolinfo_table[1],
+	.name = "nonblocking",
+	.pull = &input_pool,
+	.lock = SPIN_LOCK_UNLOCKED,
+	.pool = nonblocking_pool_data
+};
 
 /*
  * This function adds a byte into the entropy "pool".  It does not
@@ -573,16 +456,16 @@
 		0xedb88320, 0xd6d6a3e8, 0x9b64c2b0, 0xa00ae278 };
 	unsigned long i, add_ptr, tap1, tap2, tap3, tap4, tap5;
 	int new_rotate, input_rotate;
-	int wordmask = r->poolinfo.poolwords - 1;
+	int wordmask = r->poolinfo->poolwords - 1;
 	__u32 w, next_w;
 	unsigned long flags;
 
 	/* Taps are constant, so we can load them without holding r->lock.  */
-	tap1 = r->poolinfo.tap1;
-	tap2 = r->poolinfo.tap2;
-	tap3 = r->poolinfo.tap3;
-	tap4 = r->poolinfo.tap4;
-	tap5 = r->poolinfo.tap5;
+	tap1 = r->poolinfo->tap1;
+	tap2 = r->poolinfo->tap2;
+	tap3 = r->poolinfo->tap3;
+	tap4 = r->poolinfo->tap4;
+	tap5 = r->poolinfo->tap5;
 	next_w = *in++;
 
 	spin_lock_irqsave(&r->lock, flags);
@@ -591,7 +474,7 @@
 	add_ptr = r->add_ptr;
 
 	while (nwords--) {
-		w = rotate_left(input_rotate, next_w);
+		w = rol32(next_w, input_rotate);
 		if (nwords > 0)
 			next_w = *in++;
 		i = add_ptr = (add_ptr - 1) & wordmask;
@@ -648,8 +531,8 @@
 		DEBUG_ENT("negative entropy/overflow (%d+%d)\n",
 			  r->entropy_count, nbits);
 		r->entropy_count = 0;
-	} else if (r->entropy_count + nbits > r->poolinfo.POOLBITS) {
-		r->entropy_count = r->poolinfo.POOLBITS;
+	} else if (r->entropy_count + nbits > r->poolinfo->POOLBITS) {
+		r->entropy_count = r->poolinfo->POOLBITS;
 	} else {
 		r->entropy_count += nbits;
 		if (nbits)
@@ -660,118 +543,6 @@
 	spin_unlock_irqrestore(&r->lock, flags);
 }
 
-/**********************************************************************
- *
- * Entropy batch input management
- *
- * We batch entropy to be added to avoid increasing interrupt latency
- *
- **********************************************************************/
-
-struct sample {
-	__u32 data[2];
-	int credit;
-};
-
-static struct sample *batch_entropy_pool, *batch_entropy_copy;
-static int batch_head, batch_tail;
-static DEFINE_SPINLOCK(batch_lock);
-
-static int batch_max;
-static void batch_entropy_process(void *private_);
-static DECLARE_WORK(batch_work, batch_entropy_process, NULL);
-
-/* note: the size must be a power of 2 */
-static int __init batch_entropy_init(int size, struct entropy_store *r)
-{
-	batch_entropy_pool = kmalloc(size*sizeof(struct sample), GFP_KERNEL);
-	if (!batch_entropy_pool)
-		return -1;
-	batch_entropy_copy = kmalloc(size*sizeof(struct sample), GFP_KERNEL);
-	if (!batch_entropy_copy) {
-		kfree(batch_entropy_pool);
-		return -1;
-	}
-	batch_head = batch_tail = 0;
-	batch_work.data = r;
-	batch_max = size;
-	return 0;
-}
-
-/*
- * Changes to the entropy data is put into a queue rather than being added to
- * the entropy counts directly.  This is presumably to avoid doing heavy
- * hashing calculations during an interrupt in add_timer_randomness().
- * Instead, the entropy is only added to the pool by keventd.
- */
-static void batch_entropy_store(u32 a, u32 b, int num)
-{
-	int new;
-	unsigned long flags;
-
-	if (!batch_max)
-		return;
-
-	spin_lock_irqsave(&batch_lock, flags);
-
-	batch_entropy_pool[batch_head].data[0] = a;
-	batch_entropy_pool[batch_head].data[1] = b;
-	batch_entropy_pool[batch_head].credit = num;
-
-	if (((batch_head - batch_tail) & (batch_max - 1)) >= (batch_max / 2))
-		schedule_delayed_work(&batch_work, 1);
-
-	new = (batch_head + 1) & (batch_max - 1);
-	if (new == batch_tail)
-		DEBUG_ENT("batch entropy buffer full\n");
-	else
-		batch_head = new;
-
-	spin_unlock_irqrestore(&batch_lock, flags);
-}
-
-/*
- * Flush out the accumulated entropy operations, adding entropy to the passed
- * store (normally random_state).  If that store has enough entropy, alternate
- * between randomizing the data of the primary and secondary stores.
- */
-static void batch_entropy_process(void *private_)
-{
-	struct entropy_store *r	= (struct entropy_store *) private_, *p;
-	int max_entropy = r->poolinfo.POOLBITS;
-	unsigned head, tail;
-
-	/* Mixing into the pool is expensive, so copy over the batch
-	 * data and release the batch lock. The pool is at least half
-	 * full, so don't worry too much about copying only the used
-	 * part.
-	 */
-	spin_lock_irq(&batch_lock);
-
-	memcpy(batch_entropy_copy, batch_entropy_pool,
-	       batch_max * sizeof(struct sample));
-
-	head = batch_head;
-	tail = batch_tail;
-	batch_tail = batch_head;
-
-	spin_unlock_irq(&batch_lock);
-
-	p = r;
-	while (head != tail) {
-		if (r->entropy_count >= max_entropy) {
-			r = (r == sec_random_state) ? random_state :
-				sec_random_state;
-			max_entropy = r->poolinfo.POOLBITS;
-		}
-		add_entropy_words(r, batch_entropy_copy[tail].data, 2);
-		credit_entropy_store(r, batch_entropy_copy[tail].credit);
-		tail = (tail + 1) & (batch_max - 1);
-	}
-	if (p->entropy_count >= random_read_wakeup_thresh)
-		wake_up_interruptible(&random_read_wait);
-}
-
 /*********************************************************************
  *
  * Entropy input management
@@ -786,7 +557,6 @@
 };
 
 static struct timer_rand_state input_timer_state;
-static struct timer_rand_state extract_timer_state;
 static struct timer_rand_state *irq_timer_state[NR_IRQS];
 
 /*
@@ -801,26 +571,33 @@
  */
 static void add_timer_randomness(struct timer_rand_state *state, unsigned num)
 {
-	cycles_t data;
-	long delta, delta2, delta3, time;
-	int entropy = 0;
+	struct {
+		cycles_t cycles;
+		long jiffies;
+		unsigned num;
+	} sample;
+	long delta, delta2, delta3;
 
 	preempt_disable();
 	/* if over the trickle threshold, use only 1 in 4096 samples */
-	if (random_state->entropy_count > trickle_thresh &&
+	if (input_pool.entropy_count > trickle_thresh &&
 	    (__get_cpu_var(trickle_count)++ & 0xfff))
 		goto out;
 
+	sample.jiffies = jiffies;
+	sample.cycles = get_cycles();
+	sample.num = num;
+	add_entropy_words(&input_pool, (u32 *)&sample, sizeof(sample)/4);
+
 	/*
 	 * Calculate number of bits of randomness we probably added.
 	 * We take into account the first, second and third-order deltas
 	 * in order to make our estimate.
 	 */
-	time = jiffies;
 
 	if (!state->dont_count_entropy) {
-		delta = time - state->last_time;
-		state->last_time = time;
+		delta = sample.jiffies - state->last_time;
+		state->last_time = sample.jiffies;
 
 		delta2 = delta - state->last_delta;
 		state->last_delta = delta;
@@ -844,23 +621,13 @@
 		 * Round down by 1 bit on general principles,
 		 * and limit entropy entimate to 12 bits.
 		 */
-		delta >>= 1;
-		delta &= (1 << 12) - 1;
-
-		entropy = int_ln_12bits(delta);
+		credit_entropy_store(&input_pool,
+				     min_t(int, fls(delta>>1), 11));
 	}
 
-	/*
-	 * Use get_cycles() if implemented, otherwise fall back to
-	 * jiffies.
-	 */
-	data = get_cycles();
-	if (data)
-		num ^= (u32)((data >> 31) >> 1);
-	else
-		data = time;
+	if(input_pool.entropy_count >= random_read_wakeup_thresh)
+		wake_up_interruptible(&random_read_wait);
 
-	batch_entropy_store(num, data, entropy);
 out:
 	preempt_enable();
 }
@@ -902,391 +669,7 @@
 
 EXPORT_SYMBOL(add_disk_randomness);
 
-/******************************************************************
- *
- * Hash function definition
- *
- *******************************************************************/
-
-/*
- * This chunk of code defines a function
- * void HASH_TRANSFORM(__u32 digest[HASH_BUFFER_SIZE + HASH_EXTRA_SIZE],
- * 		__u32 const data[16])
- *
- * The function hashes the input data to produce a digest in the first
- * HASH_BUFFER_SIZE words of the digest[] array, and uses HASH_EXTRA_SIZE
- * more words for internal purposes.  (This buffer is exported so the
- * caller can wipe it once rather than this code doing it each call,
- * and tacking it onto the end of the digest[] array is the quick and
- * dirty way of doing it.)
- *
- * It so happens that MD5 and SHA share most of the initial vector
- * used to initialize the digest[] array before the first call:
- * 1) 0x67452301
- * 2) 0xefcdab89
- * 3) 0x98badcfe
- * 4) 0x10325476
- * 5) 0xc3d2e1f0 (SHA only)
- *
- * For /dev/random purposes, the length of the data being hashed is
- * fixed in length, so appending a bit count in the usual way is not
- * cryptographically necessary.
- */
-
-#ifdef USE_SHA
-
-#define HASH_BUFFER_SIZE 5
-#define HASH_EXTRA_SIZE 80
-#define HASH_TRANSFORM SHATransform
-
-/* Various size/speed tradeoffs are available.  Choose 0..3. */
-#define SHA_CODE_SIZE 0
-
-/*
- * SHA transform algorithm, taken from code written by Peter Gutmann,
- * and placed in the public domain.
- */
-
-/* The SHA f()-functions.  */
-
-#define f1(x,y,z)   (z ^ (x & (y ^ z)))		/* Rounds  0-19: x ? y : z */
-#define f2(x,y,z)   (x ^ y ^ z)			/* Rounds 20-39: XOR */
-#define f3(x,y,z)   ((x & y) + (z & (x ^ y)))	/* Rounds 40-59: majority */
-#define f4(x,y,z)   (x ^ y ^ z)			/* Rounds 60-79: XOR */
-
-/* The SHA Mysterious Constants */
-
-#define K1  0x5A827999L			/* Rounds  0-19: sqrt(2) * 2^30 */
-#define K2  0x6ED9EBA1L			/* Rounds 20-39: sqrt(3) * 2^30 */
-#define K3  0x8F1BBCDCL			/* Rounds 40-59: sqrt(5) * 2^30 */
-#define K4  0xCA62C1D6L			/* Rounds 60-79: sqrt(10) * 2^30 */
-
-#define ROTL(n,X)  (((X) << n ) | ((X) >> (32 - n)))
-
-#define subRound(a, b, c, d, e, f, k, data) \
-    (e += ROTL(5, a) + f(b, c, d) + k + data, b = ROTL(30, b))
-
-static void SHATransform(__u32 digest[85], __u32 const data[16])
-{
-	__u32 A, B, C, D, E;     /* Local vars */
-	__u32 TEMP;
-	int i;
-#define W (digest + HASH_BUFFER_SIZE)	/* Expanded data array */
-
-	/*
-	 * Do the preliminary expansion of 16 to 80 words.  Doing it
-	 * out-of-line line this is faster than doing it in-line on
-	 * register-starved machines like the x86, and not really any
-	 * slower on real processors.
-	 */
-	memcpy(W, data, 16*sizeof(__u32));
-	for (i = 0; i < 64; i++) {
-		TEMP = W[i] ^ W[i+2] ^ W[i+8] ^ W[i+13];
-		W[i+16] = ROTL(1, TEMP);
-	}
-
-	/* Set up first buffer and local data buffer */
-	A = digest[ 0 ];
-	B = digest[ 1 ];
-	C = digest[ 2 ];
-	D = digest[ 3 ];
-	E = digest[ 4 ];
-
-	/* Heavy mangling, in 4 sub-rounds of 20 iterations each. */
-#if SHA_CODE_SIZE == 0
-	/*
-	 * Approximately 50% of the speed of the largest version, but
-	 * takes up 1/16 the space.  Saves about 6k on an i386 kernel.
-	 */
-	for (i = 0; i < 80; i++) {
-		if (i < 40) {
-			if (i < 20)
-				TEMP = f1(B, C, D) + K1;
-			else
-				TEMP = f2(B, C, D) + K2;
-		} else {
-			if (i < 60)
-				TEMP = f3(B, C, D) + K3;
-			else
-				TEMP = f4(B, C, D) + K4;
-		}
-		TEMP += ROTL(5, A) + E + W[i];
-		E = D; D = C; C = ROTL(30, B); B = A; A = TEMP;
-	}
-#elif SHA_CODE_SIZE == 1
-	for (i = 0; i < 20; i++) {
-		TEMP = f1(B, C, D) + K1 + ROTL(5, A) + E + W[i];
-		E = D; D = C; C = ROTL(30, B); B = A; A = TEMP;
-	}
-	for (; i < 40; i++) {
-		TEMP = f2(B, C, D) + K2 + ROTL(5, A) + E + W[i];
-		E = D; D = C; C = ROTL(30, B); B = A; A = TEMP;
-	}
-	for (; i < 60; i++) {
-		TEMP = f3(B, C, D) + K3 + ROTL(5, A) + E + W[i];
-		E = D; D = C; C = ROTL(30, B); B = A; A = TEMP;
-	}
-	for (; i < 80; i++) {
-		TEMP = f4(B, C, D) + K4 + ROTL(5, A) + E + W[i];
-		E = D; D = C; C = ROTL(30, B); B = A; A = TEMP;
-	}
-#elif SHA_CODE_SIZE == 2
-	for (i = 0; i < 20; i += 5) {
-		subRound(A, B, C, D, E, f1, K1, W[i  ]);
-		subRound(E, A, B, C, D, f1, K1, W[i+1]);
-		subRound(D, E, A, B, C, f1, K1, W[i+2]);
-		subRound(C, D, E, A, B, f1, K1, W[i+3]);
-		subRound(B, C, D, E, A, f1, K1, W[i+4]);
-	}
-	for (; i < 40; i += 5) {
-		subRound(A, B, C, D, E, f2, K2, W[i  ]);
-		subRound(E, A, B, C, D, f2, K2, W[i+1]);
-		subRound(D, E, A, B, C, f2, K2, W[i+2]);
-		subRound(C, D, E, A, B, f2, K2, W[i+3]);
-		subRound(B, C, D, E, A, f2, K2, W[i+4]);
-	}
-	for (; i < 60; i += 5) {
-		subRound(A, B, C, D, E, f3, K3, W[i  ]);
-		subRound(E, A, B, C, D, f3, K3, W[i+1]);
-		subRound(D, E, A, B, C, f3, K3, W[i+2]);
-		subRound(C, D, E, A, B, f3, K3, W[i+3]);
-		subRound(B, C, D, E, A, f3, K3, W[i+4]);
-	}
-	for (; i < 80; i += 5) {
-		subRound(A, B, C, D, E, f4, K4, W[i  ]);
-		subRound(E, A, B, C, D, f4, K4, W[i+1]);
-		subRound(D, E, A, B, C, f4, K4, W[i+2]);
-		subRound(C, D, E, A, B, f4, K4, W[i+3]);
-		subRound(B, C, D, E, A, f4, K4, W[i+4]);
-	}
-#elif SHA_CODE_SIZE == 3 /* Really large version */
-	subRound(A, B, C, D, E, f1, K1, W[ 0]);
-	subRound(E, A, B, C, D, f1, K1, W[ 1]);
-	subRound(D, E, A, B, C, f1, K1, W[ 2]);
-	subRound(C, D, E, A, B, f1, K1, W[ 3]);
-	subRound(B, C, D, E, A, f1, K1, W[ 4]);
-	subRound(A, B, C, D, E, f1, K1, W[ 5]);
-	subRound(E, A, B, C, D, f1, K1, W[ 6]);
-	subRound(D, E, A, B, C, f1, K1, W[ 7]);
-	subRound(C, D, E, A, B, f1, K1, W[ 8]);
-	subRound(B, C, D, E, A, f1, K1, W[ 9]);
-	subRound(A, B, C, D, E, f1, K1, W[10]);
-	subRound(E, A, B, C, D, f1, K1, W[11]);
-	subRound(D, E, A, B, C, f1, K1, W[12]);
-	subRound(C, D, E, A, B, f1, K1, W[13]);
-	subRound(B, C, D, E, A, f1, K1, W[14]);
-	subRound(A, B, C, D, E, f1, K1, W[15]);
-	subRound(E, A, B, C, D, f1, K1, W[16]);
-	subRound(D, E, A, B, C, f1, K1, W[17]);
-	subRound(C, D, E, A, B, f1, K1, W[18]);
-	subRound(B, C, D, E, A, f1, K1, W[19]);
-
-	subRound(A, B, C, D, E, f2, K2, W[20]);
-	subRound(E, A, B, C, D, f2, K2, W[21]);
-	subRound(D, E, A, B, C, f2, K2, W[22]);
-	subRound(C, D, E, A, B, f2, K2, W[23]);
-	subRound(B, C, D, E, A, f2, K2, W[24]);
-	subRound(A, B, C, D, E, f2, K2, W[25]);
-	subRound(E, A, B, C, D, f2, K2, W[26]);
-	subRound(D, E, A, B, C, f2, K2, W[27]);
-	subRound(C, D, E, A, B, f2, K2, W[28]);
-	subRound(B, C, D, E, A, f2, K2, W[29]);
-	subRound(A, B, C, D, E, f2, K2, W[30]);
-	subRound(E, A, B, C, D, f2, K2, W[31]);
-	subRound(D, E, A, B, C, f2, K2, W[32]);
-	subRound(C, D, E, A, B, f2, K2, W[33]);
-	subRound(B, C, D, E, A, f2, K2, W[34]);
-	subRound(A, B, C, D, E, f2, K2, W[35]);
-	subRound(E, A, B, C, D, f2, K2, W[36]);
-	subRound(D, E, A, B, C, f2, K2, W[37]);
-	subRound(C, D, E, A, B, f2, K2, W[38]);
-	subRound(B, C, D, E, A, f2, K2, W[39]);
-
-	subRound(A, B, C, D, E, f3, K3, W[40]);
-	subRound(E, A, B, C, D, f3, K3, W[41]);
-	subRound(D, E, A, B, C, f3, K3, W[42]);
-	subRound(C, D, E, A, B, f3, K3, W[43]);
-	subRound(B, C, D, E, A, f3, K3, W[44]);
-	subRound(A, B, C, D, E, f3, K3, W[45]);
-	subRound(E, A, B, C, D, f3, K3, W[46]);
-	subRound(D, E, A, B, C, f3, K3, W[47]);
-	subRound(C, D, E, A, B, f3, K3, W[48]);
-	subRound(B, C, D, E, A, f3, K3, W[49]);
-	subRound(A, B, C, D, E, f3, K3, W[50]);
-	subRound(E, A, B, C, D, f3, K3, W[51]);
-	subRound(D, E, A, B, C, f3, K3, W[52]);
-	subRound(C, D, E, A, B, f3, K3, W[53]);
-	subRound(B, C, D, E, A, f3, K3, W[54]);
-	subRound(A, B, C, D, E, f3, K3, W[55]);
-	subRound(E, A, B, C, D, f3, K3, W[56]);
-	subRound(D, E, A, B, C, f3, K3, W[57]);
-	subRound(C, D, E, A, B, f3, K3, W[58]);
-	subRound(B, C, D, E, A, f3, K3, W[59]);
-
-	subRound(A, B, C, D, E, f4, K4, W[60]);
-	subRound(E, A, B, C, D, f4, K4, W[61]);
-	subRound(D, E, A, B, C, f4, K4, W[62]);
-	subRound(C, D, E, A, B, f4, K4, W[63]);
-	subRound(B, C, D, E, A, f4, K4, W[64]);
-	subRound(A, B, C, D, E, f4, K4, W[65]);
-	subRound(E, A, B, C, D, f4, K4, W[66]);
-	subRound(D, E, A, B, C, f4, K4, W[67]);
-	subRound(C, D, E, A, B, f4, K4, W[68]);
-	subRound(B, C, D, E, A, f4, K4, W[69]);
-	subRound(A, B, C, D, E, f4, K4, W[70]);
-	subRound(E, A, B, C, D, f4, K4, W[71]);
-	subRound(D, E, A, B, C, f4, K4, W[72]);
-	subRound(C, D, E, A, B, f4, K4, W[73]);
-	subRound(B, C, D, E, A, f4, K4, W[74]);
-	subRound(A, B, C, D, E, f4, K4, W[75]);
-	subRound(E, A, B, C, D, f4, K4, W[76]);
-	subRound(D, E, A, B, C, f4, K4, W[77]);
-	subRound(C, D, E, A, B, f4, K4, W[78]);
-	subRound(B, C, D, E, A, f4, K4, W[79]);
-#else
-#error Illegal SHA_CODE_SIZE
-#endif
-
-	/* Build message digest */
-	digest[0] += A;
-	digest[1] += B;
-	digest[2] += C;
-	digest[3] += D;
-	digest[4] += E;
-
-	/* W is wiped by the caller */
-#undef W
-}
-
-#undef ROTL
-#undef f1
-#undef f2
-#undef f3
-#undef f4
-#undef K1
-#undef K2
-#undef K3
-#undef K4
-#undef subRound
-
-#else /* !USE_SHA - Use MD5 */
-
-#define HASH_BUFFER_SIZE 4
-#define HASH_EXTRA_SIZE 0
-#define HASH_TRANSFORM MD5Transform
-
-/*
- * MD5 transform algorithm, taken from code written by Colin Plumb,
- * and put into the public domain
- */
-
-/* The four core functions - F1 is optimized somewhat */
-
-/* #define F1(x, y, z) (x & y | ~x & z) */
-#define F1(x, y, z) (z ^ (x & (y ^ z)))
-#define F2(x, y, z) F1(z, x, y)
-#define F3(x, y, z) (x ^ y ^ z)
-#define F4(x, y, z) (y ^ (x | ~z))
-
-/* This is the central step in the MD5 algorithm. */
-#define MD5STEP(f, w, x, y, z, data, s) \
-	(w += f(x, y, z) + data,  w = w << s | w >> (32 - s),  w += x )
-
-/*
- * The core of the MD5 algorithm, this alters an existing MD5 hash to
- * reflect the addition of 16 longwords of new data.  MD5Update blocks
- * the data and converts bytes into longwords for this routine.
- */
-static void MD5Transform(__u32 buf[HASH_BUFFER_SIZE], __u32 const in[16])
-{
-	__u32 a, b, c, d;
-
-	a = buf[0];
-	b = buf[1];
-	c = buf[2];
-	d = buf[3];
-
-	MD5STEP(F1, a, b, c, d, in[ 0]+0xd76aa478,  7);
-	MD5STEP(F1, d, a, b, c, in[ 1]+0xe8c7b756, 12);
-	MD5STEP(F1, c, d, a, b, in[ 2]+0x242070db, 17);
-	MD5STEP(F1, b, c, d, a, in[ 3]+0xc1bdceee, 22);
-	MD5STEP(F1, a, b, c, d, in[ 4]+0xf57c0faf,  7);
-	MD5STEP(F1, d, a, b, c, in[ 5]+0x4787c62a, 12);
-	MD5STEP(F1, c, d, a, b, in[ 6]+0xa8304613, 17);
-	MD5STEP(F1, b, c, d, a, in[ 7]+0xfd469501, 22);
-	MD5STEP(F1, a, b, c, d, in[ 8]+0x698098d8,  7);
-	MD5STEP(F1, d, a, b, c, in[ 9]+0x8b44f7af, 12);
-	MD5STEP(F1, c, d, a, b, in[10]+0xffff5bb1, 17);
-	MD5STEP(F1, b, c, d, a, in[11]+0x895cd7be, 22);
-	MD5STEP(F1, a, b, c, d, in[12]+0x6b901122,  7);
-	MD5STEP(F1, d, a, b, c, in[13]+0xfd987193, 12);
-	MD5STEP(F1, c, d, a, b, in[14]+0xa679438e, 17);
-	MD5STEP(F1, b, c, d, a, in[15]+0x49b40821, 22);
-
-	MD5STEP(F2, a, b, c, d, in[ 1]+0xf61e2562,  5);
-	MD5STEP(F2, d, a, b, c, in[ 6]+0xc040b340,  9);
-	MD5STEP(F2, c, d, a, b, in[11]+0x265e5a51, 14);
-	MD5STEP(F2, b, c, d, a, in[ 0]+0xe9b6c7aa, 20);
-	MD5STEP(F2, a, b, c, d, in[ 5]+0xd62f105d,  5);
-	MD5STEP(F2, d, a, b, c, in[10]+0x02441453,  9);
-	MD5STEP(F2, c, d, a, b, in[15]+0xd8a1e681, 14);
-	MD5STEP(F2, b, c, d, a, in[ 4]+0xe7d3fbc8, 20);
-	MD5STEP(F2, a, b, c, d, in[ 9]+0x21e1cde6,  5);
-	MD5STEP(F2, d, a, b, c, in[14]+0xc33707d6,  9);
-	MD5STEP(F2, c, d, a, b, in[ 3]+0xf4d50d87, 14);
-	MD5STEP(F2, b, c, d, a, in[ 8]+0x455a14ed, 20);
-	MD5STEP(F2, a, b, c, d, in[13]+0xa9e3e905,  5);
-	MD5STEP(F2, d, a, b, c, in[ 2]+0xfcefa3f8,  9);
-	MD5STEP(F2, c, d, a, b, in[ 7]+0x676f02d9, 14);
-	MD5STEP(F2, b, c, d, a, in[12]+0x8d2a4c8a, 20);
-
-	MD5STEP(F3, a, b, c, d, in[ 5]+0xfffa3942,  4);
-	MD5STEP(F3, d, a, b, c, in[ 8]+0x8771f681, 11);
-	MD5STEP(F3, c, d, a, b, in[11]+0x6d9d6122, 16);
-	MD5STEP(F3, b, c, d, a, in[14]+0xfde5380c, 23);
-	MD5STEP(F3, a, b, c, d, in[ 1]+0xa4beea44,  4);
-	MD5STEP(F3, d, a, b, c, in[ 4]+0x4bdecfa9, 11);
-	MD5STEP(F3, c, d, a, b, in[ 7]+0xf6bb4b60, 16);
-	MD5STEP(F3, b, c, d, a, in[10]+0xbebfbc70, 23);
-	MD5STEP(F3, a, b, c, d, in[13]+0x289b7ec6,  4);
-	MD5STEP(F3, d, a, b, c, in[ 0]+0xeaa127fa, 11);
-	MD5STEP(F3, c, d, a, b, in[ 3]+0xd4ef3085, 16);
-	MD5STEP(F3, b, c, d, a, in[ 6]+0x04881d05, 23);
-	MD5STEP(F3, a, b, c, d, in[ 9]+0xd9d4d039,  4);
-	MD5STEP(F3, d, a, b, c, in[12]+0xe6db99e5, 11);
-	MD5STEP(F3, c, d, a, b, in[15]+0x1fa27cf8, 16);
-	MD5STEP(F3, b, c, d, a, in[ 2]+0xc4ac5665, 23);
-
-	MD5STEP(F4, a, b, c, d, in[ 0]+0xf4292244,  6);
-	MD5STEP(F4, d, a, b, c, in[ 7]+0x432aff97, 10);
-	MD5STEP(F4, c, d, a, b, in[14]+0xab9423a7, 15);
-	MD5STEP(F4, b, c, d, a, in[ 5]+0xfc93a039, 21);
-	MD5STEP(F4, a, b, c, d, in[12]+0x655b59c3,  6);
-	MD5STEP(F4, d, a, b, c, in[ 3]+0x8f0ccc92, 10);
-	MD5STEP(F4, c, d, a, b, in[10]+0xffeff47d, 15);
-	MD5STEP(F4, b, c, d, a, in[ 1]+0x85845dd1, 21);
-	MD5STEP(F4, a, b, c, d, in[ 8]+0x6fa87e4f,  6);
-	MD5STEP(F4, d, a, b, c, in[15]+0xfe2ce6e0, 10);
-	MD5STEP(F4, c, d, a, b, in[ 6]+0xa3014314, 15);
-	MD5STEP(F4, b, c, d, a, in[13]+0x4e0811a1, 21);
-	MD5STEP(F4, a, b, c, d, in[ 4]+0xf7537e82,  6);
-	MD5STEP(F4, d, a, b, c, in[11]+0xbd3af235, 10);
-	MD5STEP(F4, c, d, a, b, in[ 2]+0x2ad7d2bb, 15);
-	MD5STEP(F4, b, c, d, a, in[ 9]+0xeb86d391, 21);
-
-	buf[0] += a;
-	buf[1] += b;
-	buf[2] += c;
-	buf[3] += d;
-}
-
-#undef F1
-#undef F2
-#undef F3
-#undef F4
-#undef MD5STEP
-
-#endif /* !USE_SHA */
+#define EXTRACT_SIZE 10
 
 /*********************************************************************
  *
@@ -1294,157 +677,174 @@
  *
  *********************************************************************/
 
-#define EXTRACT_ENTROPY_USER		1
-#define EXTRACT_ENTROPY_SECONDARY	2
-#define EXTRACT_ENTROPY_LIMIT		4
-#define TMP_BUF_SIZE			(HASH_BUFFER_SIZE + HASH_EXTRA_SIZE)
-#define SEC_XFER_SIZE			(TMP_BUF_SIZE*4)
-
 static ssize_t extract_entropy(struct entropy_store *r, void * buf,
-			       size_t nbytes, int flags);
+			       size_t nbytes, int min, int rsvd);
 
 /*
  * This utility inline function is responsible for transfering entropy
  * from the primary pool to the secondary extraction pool. We make
  * sure we pull enough for a 'catastrophic reseed'.
  */
-static inline void xfer_secondary_pool(struct entropy_store *r,
-				       size_t nbytes, __u32 *tmp)
+static void xfer_secondary_pool(struct entropy_store *r, size_t nbytes)
 {
-	if (r->entropy_count < nbytes * 8 &&
-	    r->entropy_count < r->poolinfo.POOLBITS) {
+	__u32 tmp[OUTPUT_POOL_WORDS];
+
+	if (r->pull && r->entropy_count < nbytes * 8 &&
+	    r->entropy_count < r->poolinfo->POOLBITS) {
 		int bytes = max_t(int, random_read_wakeup_thresh / 8,
-				min_t(int, nbytes, TMP_BUF_SIZE));
+				min_t(int, nbytes, sizeof(tmp)));
+		int rsvd = r->limit ? 0 : random_read_wakeup_thresh/4;
 
 		DEBUG_ENT("going to reseed %s with %d bits "
 			  "(%d of %d requested)\n",
 			  r->name, bytes * 8, nbytes * 8, r->entropy_count);
 
-		bytes=extract_entropy(random_state, tmp, bytes,
-				      EXTRACT_ENTROPY_LIMIT);
+		bytes=extract_entropy(r->pull, tmp, bytes,
+				      random_read_wakeup_thresh / 8, rsvd);
 		add_entropy_words(r, tmp, (bytes + 3) / 4);
 		credit_entropy_store(r, bytes*8);
 	}
 }
 
 /*
- * This function extracts randomness from the "entropy pool", and
- * returns it in a buffer.  This function computes how many remaining
- * bits of entropy are left in the pool, but it does not restrict the
- * number of bytes that are actually obtained.  If the EXTRACT_ENTROPY_USER
- * flag is given, then the buf pointer is assumed to be in user space.
- *
- * If the EXTRACT_ENTROPY_SECONDARY flag is given, then we are actually
- * extracting entropy from the secondary pool, and can refill from the
- * primary pool if needed.
+ * These functions extracts randomness from the "entropy pool", and
+ * returns it in a buffer.
+ *
+ * The min parameter specifies the minimum amount we can pull before
+ * failing to avoid races that defeat catastrophic reseeding while the
+ * reserved parameter indicates how much entropy we must leave in the
+ * pool after each pull to avoid starving other readers.
  *
  * Note: extract_entropy() assumes that .poolwords is a multiple of 16 words.
  */
-static ssize_t extract_entropy(struct entropy_store *r, void * buf,
-			       size_t nbytes, int flags)
+
+static size_t account(struct entropy_store *r, size_t nbytes, int min,
+		      int reserved)
 {
-	ssize_t ret, i;
-	__u32 tmp[TMP_BUF_SIZE], data[16];
-	__u32 x;
-	unsigned long cpuflags;
-
-	/* Redundant, but just in case... */
-	if (r->entropy_count > r->poolinfo.POOLBITS)
-		r->entropy_count = r->poolinfo.POOLBITS;
+	unsigned long flags;
 
-	if (flags & EXTRACT_ENTROPY_SECONDARY)
-		xfer_secondary_pool(r, nbytes, tmp);
+	BUG_ON(r->entropy_count > r->poolinfo->POOLBITS);
 
 	/* Hold lock while accounting */
-	spin_lock_irqsave(&r->lock, cpuflags);
+	spin_lock_irqsave(&r->lock, flags);
 
 	DEBUG_ENT("trying to extract %d bits from %s\n",
 		  nbytes * 8, r->name);
 
-	if (flags & EXTRACT_ENTROPY_LIMIT && nbytes >= r->entropy_count / 8)
-		nbytes = r->entropy_count / 8;
-
-	if (r->entropy_count / 8 >= nbytes)
-		r->entropy_count -= nbytes*8;
-	else
-		r->entropy_count = 0;
+	/* Can we pull enough? */
+	if (r->entropy_count / 8 < min + reserved) {
+		nbytes = 0;
+	} else {
+		/* If limited, never pull more than available */
+		if (r->limit && nbytes + reserved >= r->entropy_count / 8)
+			nbytes = r->entropy_count/8 - reserved;
+
+		if(r->entropy_count / 8 >= nbytes + reserved)
+			r->entropy_count -= nbytes*8;
+		else
+			r->entropy_count = reserved;
 
-	if (r->entropy_count < random_write_wakeup_thresh)
-		wake_up_interruptible(&random_write_wait);
+		if (r->entropy_count < random_write_wakeup_thresh)
+			wake_up_interruptible(&random_write_wait);
+	}
 
 	DEBUG_ENT("debiting %d entropy credits from %s%s\n",
-		  nbytes * 8, r->name,
-		  flags & EXTRACT_ENTROPY_LIMIT ? "" : " (unlimited)");
+		  nbytes * 8, r->name, r->limit ? "" : " (unlimited)");
 
-	spin_unlock_irqrestore(&r->lock, cpuflags);
+	spin_unlock_irqrestore(&r->lock, flags);
+
+	return nbytes;
+}
+
+static void extract_buf(struct entropy_store *r, __u8 *out)
+{
+	int i, x;
+	__u32 data[16], buf[5 + SHA_WORKSPACE_WORDS];
+
+	sha_init(buf);
+	/*
+	 * As we hash the pool, we mix intermediate values of
+	 * the hash back into the pool.  This eliminates
+	 * backtracking attacks (where the attacker knows
+	 * the state of the pool plus the current outputs, and
+	 * attempts to find previous ouputs), unless the hash
+	 * function can be inverted.
+	 */
+	for (i = 0, x = 0; i < r->poolinfo->poolwords; i += 16, x+=2) {
+		sha_transform(buf, (__u8 *)r->pool+i, buf + 5);
+		add_entropy_words(r, &buf[x % 5], 1);
+	}
+
+	/*
+	 * To avoid duplicates, we atomically extract a
+	 * portion of the pool while mixing, and hash one
+	 * final time.
+	 */
+	__add_entropy_words(r, &buf[x % 5], 1, data);
+	sha_transform(buf, (__u8 *)data, buf + 5);
+
+	/*
+	 * In case the hash function has some recognizable
+	 * output pattern, we fold it in half.
+	 */
+
+	buf[0] ^= buf[3];
+	buf[1] ^= buf[4];
+	buf[0] ^= rol32(buf[3], 16);
+	memcpy(out, buf, EXTRACT_SIZE);
+	memset(buf, 0, sizeof(buf));
+}
+
+static ssize_t extract_entropy(struct entropy_store *r, void * buf,
+			       size_t nbytes, int min, int reserved)
+{
+	ssize_t ret = 0, i;
+	__u8 tmp[EXTRACT_SIZE];
+
+	xfer_secondary_pool(r, nbytes);
+	nbytes = account(r, nbytes, min, reserved);
 
-	ret = 0;
 	while (nbytes) {
-		/*
-		 * Check if we need to break out or reschedule....
-		 */
-		if ((flags & EXTRACT_ENTROPY_USER) && need_resched()) {
+		extract_buf(r, tmp);
+		i = min_t(int, nbytes, EXTRACT_SIZE);
+		memcpy(buf, tmp, i);
+		nbytes -= i;
+		buf += i;
+		ret += i;
+	}
+
+	/* Wipe data just returned from memory */
+	memset(tmp, 0, sizeof(tmp));
+
+	return ret;
+}
+
+static ssize_t extract_entropy_user(struct entropy_store *r, void __user *buf,
+				    size_t nbytes)
+{
+	ssize_t ret = 0, i;
+	__u8 tmp[EXTRACT_SIZE];
+
+	xfer_secondary_pool(r, nbytes);
+	nbytes = account(r, nbytes, 0, 0);
+
+	while (nbytes) {
+		if (need_resched()) {
 			if (signal_pending(current)) {
 				if (ret == 0)
 					ret = -ERESTARTSYS;
 				break;
 			}
-
 			schedule();
 		}
 
-		/* Hash the pool to get the output */
-		tmp[0] = 0x67452301;
-		tmp[1] = 0xefcdab89;
-		tmp[2] = 0x98badcfe;
-		tmp[3] = 0x10325476;
-#ifdef USE_SHA
-		tmp[4] = 0xc3d2e1f0;
-#endif
-		/*
-		 * As we hash the pool, we mix intermediate values of
-		 * the hash back into the pool.  This eliminates
-		 * backtracking attacks (where the attacker knows
-		 * the state of the pool plus the current outputs, and
-		 * attempts to find previous ouputs), unless the hash
-		 * function can be inverted.
-		 */
-		for (i = 0, x = 0; i < r->poolinfo.poolwords; i += 16, x+=2) {
-			HASH_TRANSFORM(tmp, r->pool+i);
-			add_entropy_words(r, &tmp[x%HASH_BUFFER_SIZE], 1);
+		extract_buf(r, tmp);
+		i = min_t(int, nbytes, EXTRACT_SIZE);
+		if (copy_to_user(buf, tmp, i)) {
+			ret = -EFAULT;
+			break;
 		}
 
-		/*
-		 * To avoid duplicates, we atomically extract a
-		 * portion of the pool while mixing, and hash one
-		 * final time.
-		 */
-		__add_entropy_words(r, &tmp[x%HASH_BUFFER_SIZE], 1, data);
-		HASH_TRANSFORM(tmp, data);
-
-		/*
-		 * In case the hash function has some recognizable
-		 * output pattern, we fold it in half.
-		 */
-		for (i = 0; i <  HASH_BUFFER_SIZE/2; i++)
-			tmp[i] ^= tmp[i + (HASH_BUFFER_SIZE+1)/2];
-#if HASH_BUFFER_SIZE & 1	/* There's a middle word to deal with */
-		x = tmp[HASH_BUFFER_SIZE/2];
-		x ^= (x >> 16);		/* Fold it in half */
-		((__u16 *)tmp)[HASH_BUFFER_SIZE-1] = (__u16)x;
-#endif
-
-		/* Copy data to destination buffer */
-		i = min(nbytes, HASH_BUFFER_SIZE*sizeof(__u32)/2);
-		if (flags & EXTRACT_ENTROPY_USER) {
-			i -= copy_to_user(buf, (__u8 const *)tmp, i);
-			if (!i) {
-				ret = -EFAULT;
-				break;
-			}
-		} else
-			memcpy(buf, (__u8 const *)tmp, i);
-
 		nbytes -= i;
 		buf += i;
 		ret += i;
@@ -1463,91 +863,41 @@
  */
 void get_random_bytes(void *buf, int nbytes)
 {
-	struct entropy_store *r = urandom_state;
-	int flags = EXTRACT_ENTROPY_SECONDARY;
-
-	if (!r)
-		r = sec_random_state;
-	if (!r) {
-		r = random_state;
-		flags = 0;
-	}
-	if (!r) {
-		printk(KERN_NOTICE "get_random_bytes called before "
-				   "random driver initialization\n");
-		return;
-	}
-	extract_entropy(r, (char *) buf, nbytes, flags);
+	extract_entropy(&nonblocking_pool, buf, nbytes, 0, 0);
 }
 
 EXPORT_SYMBOL(get_random_bytes);
 
-/*********************************************************************
- *
- * Functions to interface with Linux
- *
- *********************************************************************/
-
 /*
- * Initialize the random pool with standard stuff.
+ * init_std_data - initialize pool with system data
+ *
+ * @r: pool to initialize
  *
- * NOTE: This is an OS-dependent function.
+ * This function clears the pool's entropy count and mixes some system
+ * data into the pool to prepare it for use. The pool is not cleared
+ * as that can only decrease the entropy in the pool.
  */
 static void init_std_data(struct entropy_store *r)
 {
 	struct timeval tv;
-	__u32 words[2];
-	char *p;
-	int i;
+	unsigned long flags;
 
-	do_gettimeofday(&tv);
-	words[0] = tv.tv_sec;
-	words[1] = tv.tv_usec;
-	add_entropy_words(r, words, 2);
+	spin_lock_irqsave(&r->lock, flags);
+	r->entropy_count = 0;
+	spin_unlock_irqrestore(&r->lock, flags);
 
-	/*
-	 *	This doesn't lock system.utsname. However, we are generating
-	 *	entropy so a race with a name set here is fine.
-	 */
-	p = (char *) &system_utsname;
-	for (i = sizeof(system_utsname) / sizeof(words); i; i--) {
-		memcpy(words, p, sizeof(words));
-		add_entropy_words(r, words, sizeof(words)/4);
-		p += sizeof(words);
-	}
+	do_gettimeofday(&tv);
+	add_entropy_words(r, (__u32 *)&tv, sizeof(tv)/4);
+	add_entropy_words(r, (__u32 *)&system_utsname,
+			  sizeof(system_utsname)/4);
 }
 
 static int __init rand_initialize(void)
 {
-	int i;
-
-	if (create_entropy_store(DEFAULT_POOL_SIZE, "primary", &random_state))
-		goto err;
-	if (batch_entropy_init(BATCH_ENTROPY_SIZE, random_state))
-		goto err;
-	if (create_entropy_store(SECONDARY_POOL_SIZE, "secondary",
-				 &sec_random_state))
-		goto err;
-	if (create_entropy_store(SECONDARY_POOL_SIZE, "urandom",
-				 &urandom_state))
-		goto err;
-	clear_entropy_store(random_state);
-	clear_entropy_store(sec_random_state);
-	clear_entropy_store(urandom_state);
-	init_std_data(random_state);
-	init_std_data(sec_random_state);
-	init_std_data(urandom_state);
-#ifdef CONFIG_SYSCTL
-	sysctl_init_random(random_state);
-#endif
-	for (i = 0; i < NR_IRQS; i++)
-		irq_timer_state[i] = NULL;
-	memset(&input_timer_state, 0, sizeof(struct timer_rand_state));
-	memset(&extract_timer_state, 0, sizeof(struct timer_rand_state));
-	extract_timer_state.dont_count_entropy = 1;
+	init_std_data(&input_pool);
+	init_std_data(&blocking_pool);
+	init_std_data(&nonblocking_pool);
 	return 0;
-err:
-	return -1;
 }
 module_init(rand_initialize);
 
@@ -1587,7 +937,6 @@
 static ssize_t
 random_read(struct file * file, char __user * buf, size_t nbytes, loff_t *ppos)
 {
-	DECLARE_WAITQUEUE(wait, current);
 	ssize_t n, retval = 0, count = 0;
 
 	if (nbytes == 0)
@@ -1600,10 +949,7 @@
 
 		DEBUG_ENT("reading %d bits\n", n*8);
 
-		n = extract_entropy(sec_random_state, buf, n,
-				    EXTRACT_ENTROPY_USER |
-				    EXTRACT_ENTROPY_LIMIT |
-				    EXTRACT_ENTROPY_SECONDARY);
+		n = extract_entropy_user(&blocking_pool, buf, n);
 
 		DEBUG_ENT("read got %d bits (%d still needed)\n",
 			  n*8, (nbytes-n)*8);
@@ -1613,20 +959,20 @@
 				retval = -EAGAIN;
 				break;
 			}
+
+			DEBUG_ENT("sleeping?\n");
+
+			wait_event_interruptible(random_read_wait,
+				input_pool.entropy_count >=
+						 random_read_wakeup_thresh);
+
+			DEBUG_ENT("awake\n");
+
 			if (signal_pending(current)) {
 				retval = -ERESTARTSYS;
 				break;
 			}
 
-			set_current_state(TASK_INTERRUPTIBLE);
-			add_wait_queue(&random_read_wait, &wait);
-
-			if (sec_random_state->entropy_count / 8 == 0)
-				schedule();
-
-			set_current_state(TASK_RUNNING);
-			remove_wait_queue(&random_read_wait, &wait);
-
 			continue;
 		}
 
@@ -1654,15 +1000,7 @@
 urandom_read(struct file * file, char __user * buf,
 		      size_t nbytes, loff_t *ppos)
 {
-	int flags = EXTRACT_ENTROPY_USER;
-	unsigned long cpuflags;
-
-	spin_lock_irqsave(&random_state->lock, cpuflags);
-	if (random_state->entropy_count > random_state->poolinfo.POOLBITS)
-		flags |= EXTRACT_ENTROPY_SECONDARY;
-	spin_unlock_irqrestore(&random_state->lock, cpuflags);
-
-	return extract_entropy(urandom_state, buf, nbytes, flags);
+	return extract_entropy_user(&nonblocking_pool, buf, nbytes);
 }
 
 static unsigned int
@@ -1673,9 +1011,9 @@
 	poll_wait(file, &random_read_wait, wait);
 	poll_wait(file, &random_write_wait, wait);
 	mask = 0;
-	if (random_state->entropy_count >= random_read_wakeup_thresh)
+	if (input_pool.entropy_count >= random_read_wakeup_thresh)
 		mask |= POLLIN | POLLRDNORM;
-	if (random_state->entropy_count < random_write_wakeup_thresh)
+	if (input_pool.entropy_count < random_write_wakeup_thresh)
 		mask |= POLLOUT | POLLWRNORM;
 	return mask;
 }
@@ -1701,7 +1039,7 @@
 		c -= bytes;
 		p += bytes;
 
-		add_entropy_words(random_state, buf, (bytes + 3) / 4);
+		add_entropy_words(&input_pool, buf, (bytes + 3) / 4);
 	}
 	if (p == buffer) {
 		return (ssize_t)ret;
@@ -1723,7 +1061,7 @@
 
 	switch (cmd) {
 	case RNDGETENTCNT:
-		ent_count = random_state->entropy_count;
+		ent_count = input_pool.entropy_count;
 		if (put_user(ent_count, p))
 			return -EFAULT;
 		return 0;
@@ -1732,12 +1070,12 @@
 			return -EPERM;
 		if (get_user(ent_count, p))
 			return -EFAULT;
-		credit_entropy_store(random_state, ent_count);
+		credit_entropy_store(&input_pool, ent_count);
 		/*
 		 * Wake up waiting processes if we have enough
 		 * entropy.
 		 */
-		if (random_state->entropy_count >= random_read_wakeup_thresh)
+		if (input_pool.entropy_count >= random_read_wakeup_thresh)
 			wake_up_interruptible(&random_read_wait);
 		return 0;
 	case RNDADDENTROPY:
@@ -1753,25 +1091,22 @@
 				      size, &file->f_pos);
 		if (retval < 0)
 			return retval;
-		credit_entropy_store(random_state, ent_count);
+		credit_entropy_store(&input_pool, ent_count);
 		/*
 		 * Wake up waiting processes if we have enough
 		 * entropy.
 		 */
-		if (random_state->entropy_count >= random_read_wakeup_thresh)
+		if (input_pool.entropy_count >= random_read_wakeup_thresh)
 			wake_up_interruptible(&random_read_wait);
 		return 0;
 	case RNDZAPENTCNT:
-		if (!capable(CAP_SYS_ADMIN))
-			return -EPERM;
-		random_state->entropy_count = 0;
-		return 0;
 	case RNDCLEARPOOL:
-		/* Clear the entropy pool and associated counters. */
+		/* Clear the entropy pool counters. */
 		if (!capable(CAP_SYS_ADMIN))
 			return -EPERM;
-		clear_entropy_store(random_state);
-		init_std_data(random_state);
+		init_std_data(&input_pool);
+		init_std_data(&blocking_pool);
+		init_std_data(&nonblocking_pool);
 		return 0;
 	default:
 		return -EINVAL;
@@ -1822,8 +1157,9 @@
 
 #include <linux/sysctl.h>
 
-static int min_read_thresh, max_read_thresh;
-static int min_write_thresh, max_write_thresh;
+static int min_read_thresh = 8, min_write_thresh;
+static int max_read_thresh = INPUT_POOL_WORDS * 32;
+static int max_write_thresh = INPUT_POOL_WORDS * 32;
 static char sysctl_bootid[16];
 
 /*
@@ -1891,7 +1227,7 @@
 	return 1;
 }
 
-static int sysctl_poolsize = DEFAULT_POOL_SIZE;
+static int sysctl_poolsize = INPUT_POOL_WORDS * 32;
 ctl_table random_table[] = {
 	{
 		.ctl_name 	= RANDOM_POOLSIZE,
@@ -1907,6 +1243,7 @@
 		.maxlen		= sizeof(int),
 		.mode		= 0444,
 		.proc_handler	= &proc_dointvec,
+		.data		= &input_pool.entropy_count,
 	},
 	{
 		.ctl_name	= RANDOM_READ_THRESH,
@@ -1949,14 +1286,6 @@
 	},
 	{ .ctl_name = 0 }
 };
-
-static void sysctl_init_random(struct entropy_store *random_state)
-{
-	min_read_thresh = 8;
-	min_write_thresh = 0;
-	max_read_thresh = max_write_thresh = random_state->poolinfo.POOLBITS;
-	random_table[1].data = &random_state->entropy_count;
-}
 #endif 	/* CONFIG_SYSCTL */
 
 /********************************************************************
@@ -1965,7 +1294,6 @@
  *
  ********************************************************************/
 
-#ifdef CONFIG_INET
 /*
  * TCP initial sequence number picking.  This uses the random number
  * generator to pick an initial secret value.  This value is hashed
@@ -1996,47 +1324,6 @@
 #define K2 013240474631UL
 #define K3 015666365641UL
 
-/*
- * Basic cut-down MD4 transform.  Returns only 32 bits of result.
- */
-static __u32 halfMD4Transform (__u32 const buf[4], __u32 const in[8])
-{
-	__u32 a = buf[0], b = buf[1], c = buf[2], d = buf[3];
-
-	/* Round 1 */
-	ROUND(F, a, b, c, d, in[0] + K1,  3);
-	ROUND(F, d, a, b, c, in[1] + K1,  7);
-	ROUND(F, c, d, a, b, in[2] + K1, 11);
-	ROUND(F, b, c, d, a, in[3] + K1, 19);
-	ROUND(F, a, b, c, d, in[4] + K1,  3);
-	ROUND(F, d, a, b, c, in[5] + K1,  7);
-	ROUND(F, c, d, a, b, in[6] + K1, 11);
-	ROUND(F, b, c, d, a, in[7] + K1, 19);
-
-	/* Round 2 */
-	ROUND(G, a, b, c, d, in[1] + K2,  3);
-	ROUND(G, d, a, b, c, in[3] + K2,  5);
-	ROUND(G, c, d, a, b, in[5] + K2,  9);
-	ROUND(G, b, c, d, a, in[7] + K2, 13);
-	ROUND(G, a, b, c, d, in[0] + K2,  3);
-	ROUND(G, d, a, b, c, in[2] + K2,  5);
-	ROUND(G, c, d, a, b, in[4] + K2,  9);
-	ROUND(G, b, c, d, a, in[6] + K2, 13);
-
-	/* Round 3 */
-	ROUND(H, a, b, c, d, in[3] + K3,  3);
-	ROUND(H, d, a, b, c, in[7] + K3,  9);
-	ROUND(H, c, d, a, b, in[2] + K3, 11);
-	ROUND(H, b, c, d, a, in[6] + K3, 15);
-	ROUND(H, a, b, c, d, in[1] + K3,  3);
-	ROUND(H, d, a, b, c, in[5] + K3,  9);
-	ROUND(H, c, d, a, b, in[0] + K3, 11);
-	ROUND(H, b, c, d, a, in[4] + K3, 15);
-
-	return buf[1] + b;	/* "most hashed" word */
-	/* Alternative: return sum of all words? */
-}
-
 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
 
 static __u32 twothirdsMD4Transform (__u32 const buf[4], __u32 const in[12])
@@ -2202,6 +1489,31 @@
 EXPORT_SYMBOL(secure_tcpv6_sequence_number);
 #endif
 
+/*  The code below is shamelessly stolen from secure_tcp_sequence_number().
+ *  All blames to Andrey V. Savochkin <saw@msu.ru>.
+ */
+__u32 secure_ip_id(__u32 daddr)
+{
+	struct keydata *keyptr;
+	__u32 hash[4];
+
+	keyptr = get_keyptr();
+
+	/*
+	 *  Pick a unique starting offset for each IP destination.
+	 *  The dest ip address is placed in the starting vector,
+	 *  which is then hashed with random data.
+	 */
+	hash[0] = daddr;
+	hash[1] = keyptr->secret[9];
+	hash[2] = keyptr->secret[10];
+	hash[3] = keyptr->secret[11];
+
+	return half_md4_transform(hash, keyptr->secret);
+}
+
+#ifdef CONFIG_INET
+
 __u32 secure_tcp_sequence_number(__u32 saddr, __u32 daddr,
 				 __u16 sport, __u16 dport)
 {
@@ -2221,7 +1533,7 @@
 	hash[2]=(sport << 16) + dport;
 	hash[3]=keyptr->secret[11];
 
-	seq = halfMD4Transform(hash, keyptr->secret) & HASH_MASK;
+	seq = half_md4_transform(hash, keyptr->secret) & HASH_MASK;
 	seq += keyptr->count;
 	/*
 	 *	As close as possible to RFC 793, which
@@ -2242,28 +1554,7 @@
 
 EXPORT_SYMBOL(secure_tcp_sequence_number);
 
-/*  The code below is shamelessly stolen from secure_tcp_sequence_number().
- *  All blames to Andrey V. Savochkin <saw@msu.ru>.
- */
-__u32 secure_ip_id(__u32 daddr)
-{
-	struct keydata *keyptr;
-	__u32 hash[4];
-
-	keyptr = get_keyptr();
-
-	/*
-	 *  Pick a unique starting offset for each IP destination.
-	 *  The dest ip address is placed in the starting vector,
-	 *  which is then hashed with random data.
-	 */
-	hash[0] = daddr;
-	hash[1] = keyptr->secret[9];
-	hash[2] = keyptr->secret[10];
-	hash[3] = keyptr->secret[11];
 
-	return halfMD4Transform(hash, keyptr->secret);
-}
 
 /* Generate secure starting point for ephemeral TCP port search */
 u32 secure_tcp_port_ephemeral(__u32 saddr, __u32 daddr, __u16 dport)
@@ -2280,106 +1571,59 @@
 	hash[2] = dport ^ keyptr->secret[10];
 	hash[3] = keyptr->secret[11];
 
-	return halfMD4Transform(hash, keyptr->secret);
+	return half_md4_transform(hash, keyptr->secret);
 }
 
-#ifdef CONFIG_SYN_COOKIES
-/*
- * Secure SYN cookie computation. This is the algorithm worked out by
- * Dan Bernstein and Eric Schenk.
- *
- * For linux I implement the 1 minute counter by looking at the jiffies clock.
- * The count is passed in as a parameter, so this code doesn't much care.
- */
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+u32 secure_tcpv6_port_ephemeral(const __u32 *saddr, const __u32 *daddr, __u16 dport)
+{
+	struct keydata *keyptr = get_keyptr();
+	u32 hash[12];
 
-#define COOKIEBITS 24	/* Upper bits store count */
-#define COOKIEMASK (((__u32)1 << COOKIEBITS) - 1)
+	memcpy(hash, saddr, 16);
+	hash[4] = dport;
+	memcpy(&hash[5],keyptr->secret,sizeof(__u32) * 7);
 
-static int syncookie_init;
-static __u32 syncookie_secret[2][16-3+HASH_BUFFER_SIZE];
+	return twothirdsMD4Transform(daddr, hash);
+}
+EXPORT_SYMBOL(secure_tcpv6_port_ephemeral);
+#endif
 
-__u32 secure_tcp_syn_cookie(__u32 saddr, __u32 daddr, __u16 sport,
-		__u16 dport, __u32 sseq, __u32 count, __u32 data)
-{
-	__u32 tmp[16 + HASH_BUFFER_SIZE + HASH_EXTRA_SIZE];
-	__u32 seq;
+#endif /* CONFIG_INET */
 
-	/*
-	 * Pick two random secrets the first time we need a cookie.
-	 */
-	if (syncookie_init == 0) {
-		get_random_bytes(syncookie_secret, sizeof(syncookie_secret));
-		syncookie_init = 1;
-	}
 
+/*
+ * Get a random word for internal kernel use only. Similar to urandom but
+ * with the goal of minimal entropy pool depletion. As a result, the random
+ * value is not cryptographically secure but for several uses the cost of
+ * depleting entropy is too high
+ */
+unsigned int get_random_int(void)
+{
 	/*
-	 * Compute the secure sequence number.
-	 * The output should be:
-   	 *   HASH(sec1,saddr,sport,daddr,dport,sec1) + sseq + (count * 2^24)
-	 *      + (HASH(sec2,saddr,sport,daddr,dport,count,sec2) % 2^24).
-	 * Where sseq is their sequence number and count increases every
-	 * minute by 1.
-	 * As an extra hack, we add a small "data" value that encodes the
-	 * MSS into the second hash value.
+	 * Use IP's RNG. It suits our purpose perfectly: it re-keys itself
+	 * every second, from the entropy pool (and thus creates a limited
+	 * drain on it), and uses halfMD4Transform within the second. We
+	 * also mix it with jiffies and the PID:
 	 */
-
-	memcpy(tmp + 3, syncookie_secret[0], sizeof(syncookie_secret[0]));
-	tmp[0]=saddr;
-	tmp[1]=daddr;
-	tmp[2]=(sport << 16) + dport;
-	HASH_TRANSFORM(tmp+16, tmp);
-	seq = tmp[17] + sseq + (count << COOKIEBITS);
-
-	memcpy(tmp + 3, syncookie_secret[1], sizeof(syncookie_secret[1]));
-	tmp[0]=saddr;
-	tmp[1]=daddr;
-	tmp[2]=(sport << 16) + dport;
-	tmp[3] = count;	/* minute counter */
-	HASH_TRANSFORM(tmp + 16, tmp);
-
-	/* Add in the second hash and the data */
-	return seq + ((tmp[17] + data) & COOKIEMASK);
+	return secure_ip_id(current->pid + jiffies);
 }
 
 /*
- * This retrieves the small "data" value from the syncookie.
- * If the syncookie is bad, the data returned will be out of
- * range.  This must be checked by the caller.
- *
- * The count value used to generate the cookie must be within
- * "maxdiff" if the current (passed-in) "count".  The return value
- * is (__u32)-1 if this test fails.
- */
-__u32 check_tcp_syn_cookie(__u32 cookie, __u32 saddr, __u32 daddr, __u16 sport,
-		__u16 dport, __u32 sseq, __u32 count, __u32 maxdiff)
-{
-	__u32 tmp[16 + HASH_BUFFER_SIZE + HASH_EXTRA_SIZE];
-	__u32 diff;
-
-	if (syncookie_init == 0)
-		return (__u32)-1; /* Well, duh! */
-
-	/* Strip away the layers from the cookie */
-	memcpy(tmp + 3, syncookie_secret[0], sizeof(syncookie_secret[0]));
-	tmp[0]=saddr;
-	tmp[1]=daddr;
-	tmp[2]=(sport << 16) + dport;
-	HASH_TRANSFORM(tmp + 16, tmp);
-	cookie -= tmp[17] + sseq;
-	/* Cookie is now reduced to (count * 2^24) ^ (hash % 2^24) */
-
-	diff = (count - (cookie >> COOKIEBITS)) & ((__u32)-1 >> COOKIEBITS);
-	if (diff >= maxdiff)
-		return (__u32)-1;
-
-	memcpy(tmp+3, syncookie_secret[1], sizeof(syncookie_secret[1]));
-	tmp[0] = saddr;
-	tmp[1] = daddr;
-	tmp[2] = (sport << 16) + dport;
-	tmp[3] = count - diff;	/* minute counter */
-	HASH_TRANSFORM(tmp + 16, tmp);
+ * randomize_range() returns a start address such that
+ *
+ *    [...... <range> .....]
+ *  start                  end
+ *
+ * a <range> with size "len" starting at the return value is inside in the
+ * area defined by [start, end], but is otherwise randomized.
+ */
+unsigned long
+randomize_range(unsigned long start, unsigned long end, unsigned long len)
+{
+	unsigned long range = end - len - start;
 
-	return (cookie - tmp[17]) & COOKIEMASK;	/* Leaving the data behind */
+	if (end <= start + len)
+		return 0;
+	return PAGE_ALIGN(get_random_int() % range + start);
 }
-#endif
-#endif /* CONFIG_INET */
diff -Nru a/drivers/char/rtc.c b/drivers/char/rtc.c
--- a/drivers/char/rtc.c	2005-03-11 12:51:52 -08:00
+++ b/drivers/char/rtc.c	2005-03-11 12:51:52 -08:00
@@ -73,6 +73,7 @@
 #include <linux/init.h>
 #include <linux/poll.h>
 #include <linux/proc_fs.h>
+#include <linux/seq_file.h>
 #include <linux/spinlock.h>
 #include <linux/sysctl.h>
 #include <linux/wait.h>
@@ -151,8 +152,7 @@
 static void mask_rtc_irq_bit(unsigned char bit);
 #endif
 
-static int rtc_read_proc(char *page, char **start, off_t off,
-                         int count, int *eof, void *data);
+static int rtc_proc_open(struct inode *inode, struct file *file);
 
 /*
  *	Bits in rtc_status. (6 bits of room for future expansion)
@@ -871,11 +871,18 @@
 	.fasync		= rtc_fasync,
 };
 
-static struct miscdevice rtc_dev=
-{
-	RTC_MINOR,
-	"rtc",
-	&rtc_fops
+static struct miscdevice rtc_dev = {
+	.minor		= RTC_MINOR,
+	.name		= "rtc",
+	.fops		= &rtc_fops,
+};
+
+static struct file_operations rtc_proc_fops = {
+	.owner = THIS_MODULE,
+	.open = rtc_proc_open,
+	.read  = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
 };
 
 #if defined(RTC_IRQ) && !defined(__sparc__)
@@ -884,6 +891,7 @@
 
 static int __init rtc_init(void)
 {
+	struct proc_dir_entry *ent;
 #if defined(__alpha__) || defined(__mips__)
 	unsigned int year, ctrl;
 	unsigned long uip_watchdog;
@@ -974,7 +982,9 @@
 		release_region(RTC_PORT(0), RTC_IO_EXTENT);
 		return -ENODEV;
 	}
-	if (!create_proc_read_entry ("driver/rtc", 0, NULL, rtc_read_proc, NULL)) {
+
+	ent = create_proc_entry("driver/rtc", 0, NULL);
+	if (!ent) {
 #ifdef RTC_IRQ
 		free_irq(RTC_IRQ, NULL);
 #endif
@@ -982,6 +992,7 @@
 		misc_deregister(&rtc_dev);
 		return -ENOMEM;
 	}
+	ent->proc_fops = &rtc_proc_fops;
 
 #if defined(__alpha__) || defined(__mips__)
 	rtc_freq = HZ;
@@ -1119,11 +1130,10 @@
  *	Info exported via "/proc/driver/rtc".
  */
 
-static int rtc_proc_output (char *buf)
+static int rtc_proc_show(struct seq_file *seq, void *v)
 {
 #define YN(bit) ((ctrl & bit) ? "yes" : "no")
 #define NY(bit) ((ctrl & bit) ? "no" : "yes")
-	char *p;
 	struct rtc_time tm;
 	unsigned char batt, ctrl;
 	unsigned long freq;
@@ -1134,7 +1144,6 @@
 	freq = rtc_freq;
 	spin_unlock_irq(&rtc_lock);
 
-	p = buf;
 
 	rtc_get_rtc_time(&tm);
 
@@ -1142,12 +1151,12 @@
 	 * There is no way to tell if the luser has the RTC set for local
 	 * time or for Universal Standard Time (GMT). Probably local though.
 	 */
-	p += sprintf(p,
-		     "rtc_time\t: %02d:%02d:%02d\n"
-		     "rtc_date\t: %04d-%02d-%02d\n"
-	 	     "rtc_epoch\t: %04lu\n",
-		     tm.tm_hour, tm.tm_min, tm.tm_sec,
-		     tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, epoch);
+	seq_printf(seq,
+		   "rtc_time\t: %02d:%02d:%02d\n"
+		   "rtc_date\t: %04d-%02d-%02d\n"
+		   "rtc_epoch\t: %04lu\n",
+		   tm.tm_hour, tm.tm_min, tm.tm_sec,
+		   tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, epoch);
 
 	get_rtc_alm_time(&tm);
 
@@ -1156,57 +1165,50 @@
 	 * match any value for that particular field. Values that are
 	 * greater than a valid time, but less than 0xc0 shouldn't appear.
 	 */
-	p += sprintf(p, "alarm\t\t: ");
+	seq_puts(seq, "alarm\t\t: ");
 	if (tm.tm_hour <= 24)
-		p += sprintf(p, "%02d:", tm.tm_hour);
+		seq_printf(seq, "%02d:", tm.tm_hour);
 	else
-		p += sprintf(p, "**:");
+		seq_puts(seq, "**:");
 
 	if (tm.tm_min <= 59)
-		p += sprintf(p, "%02d:", tm.tm_min);
+		seq_printf(seq, "%02d:", tm.tm_min);
 	else
-		p += sprintf(p, "**:");
+		seq_puts(seq, "**:");
 
 	if (tm.tm_sec <= 59)
-		p += sprintf(p, "%02d\n", tm.tm_sec);
+		seq_printf(seq, "%02d\n", tm.tm_sec);
 	else
-		p += sprintf(p, "**\n");
+		seq_puts(seq, "**\n");
 
-	p += sprintf(p,
-		     "DST_enable\t: %s\n"
-		     "BCD\t\t: %s\n"
-		     "24hr\t\t: %s\n"
-		     "square_wave\t: %s\n"
-		     "alarm_IRQ\t: %s\n"
-		     "update_IRQ\t: %s\n"
-		     "periodic_IRQ\t: %s\n"
-		     "periodic_freq\t: %ld\n"
-		     "batt_status\t: %s\n",
-		     YN(RTC_DST_EN),
-		     NY(RTC_DM_BINARY),
-		     YN(RTC_24H),
-		     YN(RTC_SQWE),
-		     YN(RTC_AIE),
-		     YN(RTC_UIE),
-		     YN(RTC_PIE),
-		     freq,
-		     batt ? "okay" : "dead");
+	seq_printf(seq,
+		   "DST_enable\t: %s\n"
+		   "BCD\t\t: %s\n"
+		   "24hr\t\t: %s\n"
+		   "square_wave\t: %s\n"
+		   "alarm_IRQ\t: %s\n"
+		   "update_IRQ\t: %s\n"
+		   "periodic_IRQ\t: %s\n"
+		   "periodic_freq\t: %ld\n"
+		   "batt_status\t: %s\n",
+		   YN(RTC_DST_EN),
+		   NY(RTC_DM_BINARY),
+		   YN(RTC_24H),
+		   YN(RTC_SQWE),
+		   YN(RTC_AIE),
+		   YN(RTC_UIE),
+		   YN(RTC_PIE),
+		   freq,
+		   batt ? "okay" : "dead");
 
-	return  p - buf;
+	return  0;
 #undef YN
 #undef NY
 }
 
-static int rtc_read_proc(char *page, char **start, off_t off,
-                         int count, int *eof, void *data)
+static int rtc_proc_open(struct inode *inode, struct file *file)
 {
-        int len = rtc_proc_output (page);
-        if (len <= off+count) *eof = 1;
-        *start = page + off;
-        len -= off;
-        if (len>count) len = count;
-        if (len<0) len = 0;
-        return len;
+	return single_open(file, rtc_proc_show, NULL);
 }
 
 void rtc_get_rtc_time(struct rtc_time *rtc_tm)
diff -Nru a/drivers/char/s3c2410-rtc.c b/drivers/char/s3c2410-rtc.c
--- a/drivers/char/s3c2410-rtc.c	2005-03-11 12:51:46 -08:00
+++ b/drivers/char/s3c2410-rtc.c	2005-03-11 12:51:46 -08:00
@@ -13,6 +13,7 @@
  *	08-Nov-2004	BJD	Initial creation
  *	12-Nov-2004	BJD	Added periodic IRQ and PM code
  *	22-Nov-2004	BJD	Sign-test on alarm code to check for <0
+ *	10-Mar-2005	LCVR	Changed S3C2410_VA_RTC to S3C24XX_VA_RTC
 */
 
 #include <linux/module.h>
@@ -38,8 +39,8 @@
 /* need this for the RTC_AF definitions */
 #include <linux/mc146818rtc.h>
 
-#undef S3C2410_VA_RTC
-#define S3C2410_VA_RTC s3c2410_rtc_base
+#undef S3C24XX_VA_RTC
+#define S3C24XX_VA_RTC s3c2410_rtc_base
 
 static struct resource *s3c2410_rtc_mem;
 
diff -Nru a/drivers/char/selection.c b/drivers/char/selection.c
--- a/drivers/char/selection.c	2005-03-11 12:51:51 -08:00
+++ b/drivers/char/selection.c	2005-03-11 12:51:51 -08:00
@@ -43,15 +43,13 @@
    from interrupt (via scrollback/front) */
 
 /* set reverse video on characters s-e of console with selection. */
-inline static void
-highlight(const int s, const int e)
+static inline void highlight(const int s, const int e)
 {
 	invert_screen(sel_cons, s, e-s+2, 1);
 }
 
 /* use complementary color to show the pointer */
-inline static void
-highlight_pointer(const int where)
+static inline void highlight_pointer(const int where)
 {
 	complement_pos(sel_cons, where);
 }
@@ -277,7 +275,7 @@
  */
 int paste_selection(struct tty_struct *tty)
 {
-	struct vt_struct *vt = (struct vt_struct *) tty->driver_data;
+	struct vc_data *vc = (struct vc_data *)tty->driver_data;
 	int	pasted = 0, count;
 	struct  tty_ldisc *ld;
 	DECLARE_WAITQUEUE(wait, current);
@@ -288,7 +286,7 @@
 
 	ld = tty_ldisc_ref_wait(tty);
 	
-	add_wait_queue(&vt->paste_wait, &wait);
+	add_wait_queue(&vc->paste_wait, &wait);
 	while (sel_buffer && sel_buffer_lth > pasted) {
 		set_current_state(TASK_INTERRUPTIBLE);
 		if (test_bit(TTY_THROTTLED, &tty->flags)) {
@@ -300,7 +298,7 @@
 		tty->ldisc.receive_buf(tty, sel_buffer + pasted, NULL, count);
 		pasted += count;
 	}
-	remove_wait_queue(&vt->paste_wait, &wait);
+	remove_wait_queue(&vc->paste_wait, &wait);
 	current->state = TASK_RUNNING;
 
 	tty_ldisc_deref(ld);
diff -Nru a/drivers/char/stallion.c b/drivers/char/stallion.c
--- a/drivers/char/stallion.c	2005-03-11 12:51:48 -08:00
+++ b/drivers/char/stallion.c	2005-03-11 12:51:48 -08:00
@@ -174,14 +174,6 @@
  */
 static char		stl_unwanted[SC26198_RXFIFOSIZE];
 
-/*
- *	Keep track of what interrupts we have requested for us.
- *	We don't need to request an interrupt twice if it is being
- *	shared with another Stallion board.
- */
-static int	stl_gotintrs[STL_MAXBRDS];
-static int	stl_numintrs;
-
 /*****************************************************************************/
 
 static stlbrd_t		*stl_brds[STL_MAXBRDS];
@@ -504,7 +496,6 @@
 
 static int	stl_brdinit(stlbrd_t *brdp);
 static int	stl_initports(stlbrd_t *brdp, stlpanel_t *panelp);
-static int	stl_mapirq(int irq, char *name);
 static int	stl_getserial(stlport_t *portp, struct serial_struct __user *sp);
 static int	stl_setserial(stlport_t *portp, struct serial_struct __user *sp);
 static int	stl_getbrdstats(combrd_t __user *bp);
@@ -513,11 +504,11 @@
 static int	stl_getportstruct(stlport_t __user *arg);
 static int	stl_getbrdstruct(stlbrd_t __user *arg);
 static int	stl_waitcarrier(stlport_t *portp, struct file *filp);
-static void	stl_eiointr(stlbrd_t *brdp);
-static void	stl_echatintr(stlbrd_t *brdp);
-static void	stl_echmcaintr(stlbrd_t *brdp);
-static void	stl_echpciintr(stlbrd_t *brdp);
-static void	stl_echpci64intr(stlbrd_t *brdp);
+static int	stl_eiointr(stlbrd_t *brdp);
+static int	stl_echatintr(stlbrd_t *brdp);
+static int	stl_echmcaintr(stlbrd_t *brdp);
+static int	stl_echpciintr(stlbrd_t *brdp);
+static int	stl_echpci64intr(stlbrd_t *brdp);
 static void	stl_offintr(void *private);
 static void	*stl_memalloc(int len);
 static stlbrd_t *stl_allocbrd(void);
@@ -807,6 +798,9 @@
 	for (i = 0; (i < stl_nrbrds); i++) {
 		if ((brdp = stl_brds[i]) == (stlbrd_t *) NULL)
 			continue;
+
+		free_irq(brdp->irq, brdp);
+
 		for (j = 0; (j < STL_MAXPANELS); j++) {
 			panelp = brdp->panels[j];
 			if (panelp == (stlpanel_t *) NULL)
@@ -832,9 +826,6 @@
 		stl_brds[i] = (stlbrd_t *) NULL;
 	}
 
-	for (i = 0; (i < stl_numintrs); i++)
-		free_irq(stl_gotintrs[i], NULL);
-
 	restore_flags(flags);
 }
 
@@ -1992,23 +1983,14 @@
 
 static irqreturn_t stl_intr(int irq, void *dev_id, struct pt_regs *regs)
 {
-	stlbrd_t	*brdp;
-	int		i;
-	int handled = 0;
+	stlbrd_t	*brdp = (stlbrd_t *) dev_id;
 
 #ifdef DEBUG
-	printk("stl_intr(irq=%d,regs=%x)\n", irq, (int) regs);
+	printk("stl_intr(brdp=%x,irq=%d,regs=%x)\n", (int) brdp, irq,
+	    (int) regs);
 #endif
 
-	for (i = 0; (i < stl_nrbrds); i++) {
-		if ((brdp = stl_brds[i]) == (stlbrd_t *) NULL)
-			continue;
-		if (brdp->state == 0)
-			continue;
-		handled = 1;
-		(* brdp->isr)(brdp);
-	}
-	return IRQ_RETVAL(handled);
+	return IRQ_RETVAL((* brdp->isr)(brdp));
 }
 
 /*****************************************************************************/
@@ -2017,15 +1999,19 @@
  *	Interrupt service routine for EasyIO board types.
  */
 
-static void stl_eiointr(stlbrd_t *brdp)
+static int stl_eiointr(stlbrd_t *brdp)
 {
 	stlpanel_t	*panelp;
 	unsigned int	iobase;
+	int		handled = 0;
 
 	panelp = brdp->panels[0];
 	iobase = panelp->iobase;
-	while (inb(brdp->iostatus) & EIO_INTRPEND)
+	while (inb(brdp->iostatus) & EIO_INTRPEND) {
+		handled = 1;
 		(* panelp->isr)(panelp, iobase);
+	}
+	return handled;
 }
 
 /*****************************************************************************/
@@ -2034,15 +2020,17 @@
  *	Interrupt service routine for ECH-AT board types.
  */
 
-static void stl_echatintr(stlbrd_t *brdp)
+static int stl_echatintr(stlbrd_t *brdp)
 {
 	stlpanel_t	*panelp;
 	unsigned int	ioaddr;
 	int		bnknr;
+	int		handled = 0;
 
 	outb((brdp->ioctrlval | ECH_BRDENABLE), brdp->ioctrl);
 
 	while (inb(brdp->iostatus) & ECH_INTRPEND) {
+		handled = 1;
 		for (bnknr = 0; (bnknr < brdp->nrbnks); bnknr++) {
 			ioaddr = brdp->bnkstataddr[bnknr];
 			if (inb(ioaddr) & ECH_PNLINTRPEND) {
@@ -2053,6 +2041,8 @@
 	}
 
 	outb((brdp->ioctrlval | ECH_BRDDISABLE), brdp->ioctrl);
+
+	return handled;
 }
 
 /*****************************************************************************/
@@ -2061,13 +2051,15 @@
  *	Interrupt service routine for ECH-MCA board types.
  */
 
-static void stl_echmcaintr(stlbrd_t *brdp)
+static int stl_echmcaintr(stlbrd_t *brdp)
 {
 	stlpanel_t	*panelp;
 	unsigned int	ioaddr;
 	int		bnknr;
+	int		handled = 0;
 
 	while (inb(brdp->iostatus) & ECH_INTRPEND) {
+		handled = 1;
 		for (bnknr = 0; (bnknr < brdp->nrbnks); bnknr++) {
 			ioaddr = brdp->bnkstataddr[bnknr];
 			if (inb(ioaddr) & ECH_PNLINTRPEND) {
@@ -2076,6 +2068,7 @@
 			}
 		}
 	}
+	return handled;
 }
 
 /*****************************************************************************/
@@ -2084,11 +2077,12 @@
  *	Interrupt service routine for ECH-PCI board types.
  */
 
-static void stl_echpciintr(stlbrd_t *brdp)
+static int stl_echpciintr(stlbrd_t *brdp)
 {
 	stlpanel_t	*panelp;
 	unsigned int	ioaddr;
 	int		bnknr, recheck;
+	int		handled = 0;
 
 	while (1) {
 		recheck = 0;
@@ -2099,11 +2093,13 @@
 				panelp = brdp->bnk2panel[bnknr];
 				(* panelp->isr)(panelp, (ioaddr & 0xfffc));
 				recheck++;
+				handled = 1;
 			}
 		}
 		if (! recheck)
 			break;
 	}
+	return handled;
 }
 
 /*****************************************************************************/
@@ -2112,13 +2108,15 @@
  *	Interrupt service routine for ECH-8/64-PCI board types.
  */
 
-static void stl_echpci64intr(stlbrd_t *brdp)
+static int stl_echpci64intr(stlbrd_t *brdp)
 {
 	stlpanel_t	*panelp;
 	unsigned int	ioaddr;
 	int		bnknr;
+	int		handled = 0;
 
 	while (inb(brdp->ioctrl) & 0x1) {
+		handled = 1;
 		for (bnknr = 0; (bnknr < brdp->nrbnks); bnknr++) {
 			ioaddr = brdp->bnkstataddr[bnknr];
 			if (inb(ioaddr) & ECH_PNLINTRPEND) {
@@ -2127,6 +2125,8 @@
 			}
 		}
 	}
+
+	return handled;
 }
 
 /*****************************************************************************/
@@ -2174,39 +2174,6 @@
 /*****************************************************************************/
 
 /*
- *	Map in interrupt vector to this driver. Check that we don't
- *	already have this vector mapped, we might be sharing this
- *	interrupt across multiple boards.
- */
-
-static int __init stl_mapirq(int irq, char *name)
-{
-	int	rc, i;
-
-#ifdef DEBUG
-	printk("stl_mapirq(irq=%d,name=%s)\n", irq, name);
-#endif
-
-	rc = 0;
-	for (i = 0; (i < stl_numintrs); i++) {
-		if (stl_gotintrs[i] == irq)
-			break;
-	}
-	if (i >= stl_numintrs) {
-		if (request_irq(irq, stl_intr, SA_SHIRQ, name, NULL) != 0) {
-			printk("STALLION: failed to register interrupt "
-				"routine for %s irq=%d\n", name, irq);
-			rc = -ENODEV;
-		} else {
-			stl_gotintrs[stl_numintrs++] = irq;
-		}
-	}
-	return(rc);
-}
-
-/*****************************************************************************/
-
-/*
  *	Initialize all the ports on a panel.
  */
 
@@ -2389,7 +2356,13 @@
 	brdp->nrpanels = 1;
 	brdp->state |= BRD_FOUND;
 	brdp->hwid = status;
-	rc = stl_mapirq(brdp->irq, name);
+	if (request_irq(brdp->irq, stl_intr, SA_SHIRQ, name, brdp) != 0) {
+		printk("STALLION: failed to register interrupt "
+		    "routine for %s irq=%d\n", name, brdp->irq);
+		rc = -ENODEV;
+	} else {
+		rc = 0;
+	}
 	return(rc);
 }
 
@@ -2594,7 +2567,14 @@
 		outb((brdp->ioctrlval | ECH_BRDDISABLE), brdp->ioctrl);
 
 	brdp->state |= BRD_FOUND;
-	i = stl_mapirq(brdp->irq, name);
+	if (request_irq(brdp->irq, stl_intr, SA_SHIRQ, name, brdp) != 0) {
+		printk("STALLION: failed to register interrupt "
+		    "routine for %s irq=%d\n", name, brdp->irq);
+		i = -ENODEV;
+	} else {
+		i = 0;
+	}
+
 	return(i);
 }
 
diff -Nru a/drivers/char/synclinkmp.c b/drivers/char/synclinkmp.c
--- a/drivers/char/synclinkmp.c	2005-03-11 12:51:41 -08:00
+++ b/drivers/char/synclinkmp.c	2005-03-11 12:51:41 -08:00
@@ -1,5 +1,5 @@
 /*
- * $Id: synclinkmp.c,v 4.29 2004/08/27 20:06:41 paulkf Exp $
+ * $Id: synclinkmp.c,v 4.34 2005/03/04 15:07:10 paulkf Exp $
  *
  * Device driver for Microgate SyncLink Multiport
  * high speed multiprotocol serial adapter.
@@ -487,7 +487,7 @@
 module_param_array(dosyncppp, int, NULL, 0);
 
 static char *driver_name = "SyncLink MultiPort driver";
-static char *driver_version = "$Revision: 4.29 $";
+static char *driver_version = "$Revision: 4.34 $";
 
 static int synclinkmp_init_one(struct pci_dev *dev,const struct pci_device_id *ent);
 static void synclinkmp_remove_one(struct pci_dev *dev);
@@ -4528,7 +4528,7 @@
 	 * 07..05  Reserved, must be 0
 	 * 04..00  RRC<4..0> Rx FIFO trigger active 0x00 = 1 byte
 	 */
-	write_reg(info, TRC0, 0x00);
+	write_reg(info, RRC, 0x00);
 
 	/* TRC0 Transmit Ready Control 0
 	 *
diff -Nru a/drivers/char/sysrq.c b/drivers/char/sysrq.c
--- a/drivers/char/sysrq.c	2005-03-11 12:51:51 -08:00
+++ b/drivers/char/sysrq.c	2005-03-11 12:51:51 -08:00
@@ -33,11 +33,10 @@
 #include <linux/buffer_head.h>		/* for fsync_bdev() */
 
 #include <linux/spinlock.h>
+#include <linux/vt_kern.h>
 
 #include <asm/ptrace.h>
 
-extern void reset_vc(unsigned int);
-
 /* Whether we react on sysrq keys or just ignore them */
 int sysrq_enabled = 1;
 
@@ -68,7 +67,7 @@
 {
 	if (tty)
 		do_SAK(tty);
-	reset_vc(fg_console);
+	reset_vc(vc_cons[fg_console].d);
 }
 static struct sysrq_key_op sysrq_SAK_op = {
 	.handler	= sysrq_handle_SAK,
diff -Nru a/drivers/char/tb0219.c b/drivers/char/tb0219.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/char/tb0219.c	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,347 @@
+/*
+ *  Driver for TANBAC TB0219 base board.
+ *
+ *  Copyright (C) 2005  Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#include <linux/device.h>
+#include <linux/fs.h>
+#include <linux/init.h>
+#include <linux/module.h>
+
+#include <asm/io.h>
+#include <asm/reboot.h>
+
+MODULE_AUTHOR("Yoichi Yuasa <yuasa@hh.iij4u.or.jp>");
+MODULE_DESCRIPTION("TANBAC TB0219 base board driver");
+MODULE_LICENSE("GPL");
+
+static int major;	/* default is dynamic major device number */
+module_param(major, int, 0);
+MODULE_PARM_DESC(major, "Major device number");
+
+static void (*old_machine_restart)(char *command);
+static void __iomem *tb0219_base;
+static spinlock_t tb0219_lock;
+
+#define tb0219_read(offset)		readw(tb0219_base + (offset))
+#define tb0219_write(offset, value)	writew((value), tb0219_base + (offset))
+
+#define TB0219_START	0x0a000000UL
+#define TB0219_SIZE	0x20UL
+
+#define TB0219_LED			0x00
+#define TB0219_GPIO_INPUT		0x02
+#define TB0219_GPIO_OUTPUT		0x04
+#define TB0219_DIP_SWITCH		0x06
+#define TB0219_MISC			0x08
+#define TB0219_RESET			0x0e
+#define TB0219_PCI_SLOT1_IRQ_STATUS	0x10
+#define TB0219_PCI_SLOT2_IRQ_STATUS	0x12
+#define TB0219_PCI_SLOT3_IRQ_STATUS	0x14
+
+typedef enum {
+	TYPE_LED,
+	TYPE_GPIO_OUTPUT,
+} tb0219_type_t;
+
+/*
+ * Minor device number
+ *	 0 = 7 segment LED
+ *
+ *	16 = GPIO IN 0
+ *	17 = GPIO IN 1
+ *	18 = GPIO IN 2
+ *	19 = GPIO IN 3
+ *	20 = GPIO IN 4
+ *	21 = GPIO IN 5
+ *	22 = GPIO IN 6
+ *	23 = GPIO IN 7
+ *
+ *	32 = GPIO OUT 0
+ *	33 = GPIO OUT 1
+ *	34 = GPIO OUT 2
+ *	35 = GPIO OUT 3
+ *	36 = GPIO OUT 4
+ *	37 = GPIO OUT 5
+ *	38 = GPIO OUT 6
+ *	39 = GPIO OUT 7
+ *
+ *	48 = DIP switch 1
+ *	49 = DIP switch 2
+ *	50 = DIP switch 3
+ *	51 = DIP switch 4
+ *	52 = DIP switch 5
+ *	53 = DIP switch 6
+ *	54 = DIP switch 7
+ *	55 = DIP switch 8
+ */
+
+static inline char get_led(void)
+{
+	return (char)tb0219_read(TB0219_LED);
+}
+
+static inline char get_gpio_input_pin(unsigned int pin)
+{
+	uint16_t values;
+
+	values = tb0219_read(TB0219_GPIO_INPUT);
+	if (values & (1 << pin))
+		return '1';
+
+	return '0';
+}
+
+static inline char get_gpio_output_pin(unsigned int pin)
+{
+	uint16_t values;
+
+	values = tb0219_read(TB0219_GPIO_OUTPUT);
+	if (values & (1 << pin))
+		return '1';
+
+	return '0';
+}
+
+static inline char get_dip_switch(unsigned int pin)
+{
+	uint16_t values;
+
+	values = tb0219_read(TB0219_DIP_SWITCH);
+	if (values & (1 << pin))
+		return '1';
+
+	return '0';
+}
+
+static inline int set_led(char command)
+{
+	tb0219_write(TB0219_LED, command);
+
+	return 0;
+}
+
+static inline int set_gpio_output_pin(unsigned int pin, char command)
+{
+	unsigned long flags;
+	uint16_t value;
+
+	if (command != '0' && command != '1')
+		return -EINVAL;
+
+	spin_lock_irqsave(&tb0219_lock, flags);
+	value = tb0219_read(TB0219_GPIO_OUTPUT);
+	if (command == '0')
+		value &= ~(1 << pin);
+	else
+		value |= 1 << pin;
+	tb0219_write(TB0219_GPIO_OUTPUT, value);
+	spin_unlock_irqrestore(&tb0219_lock, flags);
+
+	return 0;
+
+}
+
+static ssize_t tanbac_tb0219_read(struct file *file, char __user *buf, size_t len,
+                                  loff_t *ppos)
+{
+	unsigned int minor;
+	char value;
+
+	minor = iminor(file->f_dentry->d_inode);
+	switch (minor) {
+	case 0:
+		value = get_led();
+		break;
+	case 16 ... 23:
+		value = get_gpio_input_pin(minor - 16);
+		break;
+	case 32 ... 39:
+		value = get_gpio_output_pin(minor - 32);
+		break;
+	case 48 ... 55:
+		value = get_dip_switch(minor - 48);
+		break;
+	default:
+		return -EBADF;
+	}
+
+	if (len <= 0)
+		return -EFAULT;
+
+	if (put_user(value, buf))
+		return -EFAULT;
+
+	return 1;
+}
+
+static ssize_t tanbac_tb0219_write(struct file *file, const char __user *data,
+                                   size_t len, loff_t *ppos)
+{
+	unsigned int minor;
+	tb0219_type_t type;
+	size_t i;
+	int retval = 0;
+	char c;
+
+	minor = iminor(file->f_dentry->d_inode);
+	switch (minor) {
+	case 0:
+		type = TYPE_LED;
+		break;
+	case 32 ... 39:
+		type = TYPE_GPIO_OUTPUT;
+		break;
+	default:
+		return -EBADF;
+	}
+
+	for (i = 0; i < len; i++) {
+		if (get_user(c, data + i))
+			return -EFAULT;
+
+		switch (type) {
+		case TYPE_LED:
+			retval = set_led(c);
+			break;
+		case TYPE_GPIO_OUTPUT:
+			retval = set_gpio_output_pin(minor - 32, c);
+			break;
+		}
+
+		if (retval < 0)
+			break;
+	}
+
+	return i;
+}
+
+static int tanbac_tb0219_open(struct inode *inode, struct file *file)
+{
+	unsigned int minor;
+
+	minor = iminor(inode);
+	switch (minor) {
+	case 0:
+	case 16 ... 23:
+	case 32 ... 39:
+	case 48 ... 55:
+		return nonseekable_open(inode, file);
+	default:
+		break;
+	}
+
+	return -EBADF;
+}
+
+static int tanbac_tb0219_release(struct inode *inode, struct file *file)
+{
+	return 0;
+}
+
+static struct file_operations tb0219_fops = {
+	.owner		= THIS_MODULE,
+	.read		= tanbac_tb0219_read,
+	.write		= tanbac_tb0219_write,
+	.open		= tanbac_tb0219_open,
+	.release	= tanbac_tb0219_release,
+};
+
+static void tb0219_restart(char *command)
+{
+	tb0219_write(TB0219_RESET, 0);
+}
+
+static int tb0219_probe(struct device *dev)
+{
+	int retval;
+
+	if (request_mem_region(TB0219_START, TB0219_SIZE, "TB0219") == NULL)
+		return -EBUSY;
+
+	tb0219_base = ioremap(TB0219_START, TB0219_SIZE);
+	if (tb0219_base == NULL) {
+		release_mem_region(TB0219_START, TB0219_SIZE);
+		return -ENOMEM;
+	}
+
+	retval = register_chrdev(major, "TB0219", &tb0219_fops);
+	if (retval < 0) {
+		iounmap(tb0219_base);
+		tb0219_base = NULL;
+		release_mem_region(TB0219_START, TB0219_SIZE);
+		return retval;
+	}
+
+	spin_lock_init(&tb0219_lock);
+
+	old_machine_restart = _machine_restart;
+	_machine_restart = tb0219_restart;
+
+	if (major == 0) {
+		major = retval;
+		printk(KERN_INFO "TB0219: major number %d\n", major);
+	}
+
+	return 0;
+}
+
+static int tb0219_remove(struct device *dev)
+{
+	_machine_restart = old_machine_restart;
+
+	iounmap(tb0219_base);
+	tb0219_base = NULL;
+
+	release_mem_region(TB0219_START, TB0219_SIZE);
+
+	return 0;
+}
+
+static struct platform_device *tb0219_platform_device;
+
+static struct device_driver tb0219_device_driver = {
+	.name		= "TB0219",
+	.bus		= &platform_bus_type,
+	.probe		= tb0219_probe,
+	.remove		= tb0219_remove,
+};
+
+static int __devinit tanbac_tb0219_init(void)
+{
+	int retval;
+
+	tb0219_platform_device = platform_device_register_simple("TB0219", -1, NULL, 0);
+	if (IS_ERR(tb0219_platform_device))
+		return PTR_ERR(tb0219_platform_device);
+
+	retval = driver_register(&tb0219_device_driver);
+	if (retval < 0)
+		platform_device_unregister(tb0219_platform_device);
+
+	return retval;
+}
+
+static void __devexit tanbac_tb0219_exit(void)
+{
+	driver_unregister(&tb0219_device_driver);
+
+	platform_device_unregister(tb0219_platform_device);
+}
+
+module_init(tanbac_tb0219_init);
+module_exit(tanbac_tb0219_exit);
diff -Nru a/drivers/char/tpm/Kconfig b/drivers/char/tpm/Kconfig
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/char/tpm/Kconfig	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,39 @@
+#
+# TPM device configuration
+#
+
+menu "TPM devices"
+
+config TCG_TPM
+	tristate "TPM Hardware Support"
+	depends on EXPERIMENTAL
+	---help---
+	  If you have a TPM security chip in your system, which
+	  implements the Trusted Computing Group's specification,
+	  say Yes and it will be accessible from within Linux.  For
+	  more information see <http://www.trustedcomputinggroup.org>. 
+	  An implementation of the Trusted Software Stack (TSS), the 
+	  userspace enablement piece of the specification, can be 
+	  obtained at: <http://sourceforge.net/projects/trousers>.  To 
+	  compile this driver as a module, choose M here; the module 
+	  will be called tpm. If unsure, say N.
+
+config TCG_NSC
+	tristate "National Semiconductor TPM Interface"
+	depends on TCG_TPM
+	---help---
+	  If you have a TPM security chip from National Semicondutor 
+	  say Yes and it will be accessible from within Linux.  To 
+	  compile this driver as a module, choose M here; the module 
+	  will be called tpm_nsc.
+
+config TCG_ATMEL
+	tristate "Atmel TPM Interface"
+	depends on TCG_TPM
+	---help---
+	  If you have a TPM security chip from Atmel say Yes and it 
+	  will be accessible from within Linux.  To compile this driver 
+	  as a module, choose M here; the module will be called tpm_atmel.
+
+endmenu
+
diff -Nru a/drivers/char/tpm/Makefile b/drivers/char/tpm/Makefile
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/char/tpm/Makefile	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,7 @@
+#
+# Makefile for the kernel tpm device drivers.
+#
+obj-$(CONFIG_TCG_TPM) += tpm.o
+obj-$(CONFIG_TCG_NSC) += tpm_nsc.o
+obj-$(CONFIG_TCG_ATMEL) += tpm_atmel.o
+
diff -Nru a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/char/tpm/tpm.c	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,697 @@
+/*
+ * Copyright (C) 2004 IBM Corporation
+ *
+ * Authors:
+ * Leendert van Doorn <leendert@watson.ibm.com>
+ * Dave Safford <safford@watson.ibm.com>
+ * Reiner Sailer <sailer@watson.ibm.com>
+ * Kylene Hall <kjhall@us.ibm.com>
+ *
+ * Maintained by: <tpmdd_devel@lists.sourceforge.net>
+ *
+ * Device driver for TCG/TCPA TPM (trusted platform module).
+ * Specifications at www.trustedcomputinggroup.org	 
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2 of the
+ * License.
+ * 
+ * Note, the TPM chip is not interrupt driven (only polling)
+ * and can have very long timeouts (minutes!). Hence the unusual
+ * calls to schedule_timeout.
+ *
+ */
+
+#include <linux/sched.h>
+#include <linux/poll.h>
+#include <linux/spinlock.h>
+#include "tpm.h"
+
+#define	TPM_MINOR			224	/* officially assigned */
+
+#define	TPM_BUFSIZE			2048
+
+/* PCI configuration addresses */
+#define	PCI_GEN_PMCON_1			0xA0
+#define	PCI_GEN1_DEC			0xE4
+#define	PCI_LPC_EN			0xE6
+#define	PCI_GEN2_DEC			0xEC
+
+static LIST_HEAD(tpm_chip_list);
+static spinlock_t driver_lock = SPIN_LOCK_UNLOCKED;
+static int dev_mask[32];
+
+static void user_reader_timeout(unsigned long ptr)
+{
+	struct tpm_chip *chip = (struct tpm_chip *) ptr;
+
+	down(&chip->buffer_mutex);
+	atomic_set(&chip->data_pending, 0);
+	memset(chip->data_buffer, 0, TPM_BUFSIZE);
+	up(&chip->buffer_mutex);
+}
+
+void tpm_time_expired(unsigned long ptr)
+{
+	int *exp = (int *) ptr;
+	*exp = 1;
+}
+
+EXPORT_SYMBOL_GPL(tpm_time_expired);
+
+/*
+ * Initialize the LPC bus and enable the TPM ports
+ */
+int tpm_lpc_bus_init(struct pci_dev *pci_dev, u16 base)
+{
+	u32 lpcenable, tmp;
+	int is_lpcm = 0;
+
+	switch (pci_dev->vendor) {
+	case PCI_VENDOR_ID_INTEL:
+		switch (pci_dev->device) {
+		case PCI_DEVICE_ID_INTEL_82801CA_12:
+		case PCI_DEVICE_ID_INTEL_82801DB_12:
+			is_lpcm = 1;
+			break;
+		}
+		/* init ICH (enable LPC) */
+		pci_read_config_dword(pci_dev, PCI_GEN1_DEC, &lpcenable);
+		lpcenable |= 0x20000000;
+		pci_write_config_dword(pci_dev, PCI_GEN1_DEC, lpcenable);
+
+		if (is_lpcm) {
+			pci_read_config_dword(pci_dev, PCI_GEN1_DEC,
+					      &lpcenable);
+			if ((lpcenable & 0x20000000) == 0) {
+				dev_err(&pci_dev->dev,
+					"cannot enable LPC\n");
+				return -ENODEV;
+			}
+		}
+
+		/* initialize TPM registers */
+		pci_read_config_dword(pci_dev, PCI_GEN2_DEC, &tmp);
+
+		if (!is_lpcm)
+			tmp = (tmp & 0xFFFF0000) | (base & 0xFFF0);
+		else
+			tmp =
+			    (tmp & 0xFFFF0000) | (base & 0xFFF0) |
+			    0x00000001;
+
+		pci_write_config_dword(pci_dev, PCI_GEN2_DEC, tmp);
+
+		if (is_lpcm) {
+			pci_read_config_dword(pci_dev, PCI_GEN_PMCON_1,
+					      &tmp);
+			tmp |= 0x00000004;	/* enable CLKRUN */
+			pci_write_config_dword(pci_dev, PCI_GEN_PMCON_1,
+					       tmp);
+		}
+		tpm_write_index(0x0D, 0x55);	/* unlock 4F */
+		tpm_write_index(0x0A, 0x00);	/* int disable */
+		tpm_write_index(0x08, base);	/* base addr lo */
+		tpm_write_index(0x09, (base & 0xFF00) >> 8);	/* base addr hi */
+		tpm_write_index(0x0D, 0xAA);	/* lock 4F */
+		break;
+	case PCI_VENDOR_ID_AMD:
+		/* nothing yet */
+		break;
+	}
+
+	return 0;
+}
+
+EXPORT_SYMBOL_GPL(tpm_lpc_bus_init);
+
+/*
+ * Internal kernel interface to transmit TPM commands
+ */
+static ssize_t tpm_transmit(struct tpm_chip *chip, const char *buf,
+			    size_t bufsiz)
+{
+	ssize_t len;
+	u32 count;
+	__be32 *native_size;
+
+	native_size = (__force __be32 *) (buf + 2);
+	count = be32_to_cpu(*native_size);
+
+	if (count == 0)
+		return -ENODATA;
+	if (count > bufsiz) {
+		dev_err(&chip->pci_dev->dev,
+			"invalid count value %x %x \n", count, bufsiz);
+		return -E2BIG;
+	}
+
+	down(&chip->tpm_mutex);
+
+	if ((len = chip->vendor->send(chip, (u8 *) buf, count)) < 0) {
+		dev_err(&chip->pci_dev->dev,
+			"tpm_transmit: tpm_send: error %d\n", len);
+		return len;
+	}
+
+	down(&chip->timer_manipulation_mutex);
+	chip->time_expired = 0;
+	init_timer(&chip->device_timer);
+	chip->device_timer.function = tpm_time_expired;
+	chip->device_timer.expires = jiffies + 2 * 60 * HZ;
+	chip->device_timer.data = (unsigned long) &chip->time_expired;
+	add_timer(&chip->device_timer);
+	up(&chip->timer_manipulation_mutex);
+
+	do {
+		u8 status = inb(chip->vendor->base + 1);
+		if ((status & chip->vendor->req_complete_mask) ==
+		    chip->vendor->req_complete_val) {
+			down(&chip->timer_manipulation_mutex);
+			del_singleshot_timer_sync(&chip->device_timer);
+			up(&chip->timer_manipulation_mutex);
+			goto out_recv;
+		}
+		set_current_state(TASK_UNINTERRUPTIBLE);
+		schedule_timeout(TPM_TIMEOUT);
+		rmb();
+	} while (!chip->time_expired);
+
+
+	chip->vendor->cancel(chip);
+	dev_err(&chip->pci_dev->dev, "Time expired\n");
+	up(&chip->tpm_mutex);
+	return -EIO;
+
+out_recv:
+	len = chip->vendor->recv(chip, (u8 *) buf, bufsiz);
+	if (len < 0)
+		dev_err(&chip->pci_dev->dev,
+			"tpm_transmit: tpm_recv: error %d\n", len);
+	up(&chip->tpm_mutex);
+	return len;
+}
+
+#define TPM_DIGEST_SIZE 20
+#define CAP_PCR_RESULT_SIZE 18
+static u8 cap_pcr[] = {
+	0, 193,			/* TPM_TAG_RQU_COMMAND */
+	0, 0, 0, 22,		/* length */
+	0, 0, 0, 101,		/* TPM_ORD_GetCapability */
+	0, 0, 0, 5,
+	0, 0, 0, 4,
+	0, 0, 1, 1
+};
+
+#define READ_PCR_RESULT_SIZE 30
+static u8 pcrread[] = {
+	0, 193,			/* TPM_TAG_RQU_COMMAND */
+	0, 0, 0, 14,		/* length */
+	0, 0, 0, 21,		/* TPM_ORD_PcrRead */
+	0, 0, 0, 0		/* PCR index */
+};
+
+static ssize_t show_pcrs(struct device *dev, char *buf)
+{
+	u8 data[READ_PCR_RESULT_SIZE];
+	ssize_t len;
+	int i, j, index, num_pcrs;
+	char *str = buf;
+
+	struct tpm_chip *chip =
+	    pci_get_drvdata(container_of(dev, struct pci_dev, dev));
+	if (chip == NULL)
+		return -ENODEV;
+
+	memcpy(data, cap_pcr, sizeof(cap_pcr));
+	if ((len = tpm_transmit(chip, data, sizeof(data)))
+	    < CAP_PCR_RESULT_SIZE)
+		return len;
+
+	num_pcrs = be32_to_cpu(*((__force __be32 *) (data + 14)));
+
+	for (i = 0; i < num_pcrs; i++) {
+		memcpy(data, pcrread, sizeof(pcrread));
+		index = cpu_to_be32(i);
+		memcpy(data + 10, &index, 4);
+		if ((len = tpm_transmit(chip, data, sizeof(data)))
+		    < READ_PCR_RESULT_SIZE)
+			return len;
+		str += sprintf(str, "PCR-%02d: ", i);
+		for (j = 0; j < TPM_DIGEST_SIZE; j++)
+			str += sprintf(str, "%02X ", *(data + 10 + j));
+		str += sprintf(str, "\n");
+	}
+	return str - buf;
+}
+
+static DEVICE_ATTR(pcrs, S_IRUGO, show_pcrs, NULL);
+
+#define  READ_PUBEK_RESULT_SIZE 314
+static u8 readpubek[] = {
+	0, 193,			/* TPM_TAG_RQU_COMMAND */
+	0, 0, 0, 30,		/* length */
+	0, 0, 0, 124,		/* TPM_ORD_ReadPubek */
+};
+
+static ssize_t show_pubek(struct device *dev, char *buf)
+{
+	u8 data[READ_PUBEK_RESULT_SIZE];
+	ssize_t len;
+	__be32 *native_val;
+	int i;
+	char *str = buf;
+
+	struct tpm_chip *chip =
+	    pci_get_drvdata(container_of(dev, struct pci_dev, dev));
+	if (chip == NULL)
+		return -ENODEV;
+
+	memcpy(data, readpubek, sizeof(readpubek));
+	memset(data + sizeof(readpubek), 0, 20);	/* zero nonce */
+
+	if ((len = tpm_transmit(chip, data, sizeof(data))) <
+	    READ_PUBEK_RESULT_SIZE)
+		return len;
+
+	/* 
+	   ignore header 10 bytes
+	   algorithm 32 bits (1 == RSA )
+	   encscheme 16 bits
+	   sigscheme 16 bits
+	   parameters (RSA 12->bytes: keybit, #primes, expbit)  
+	   keylenbytes 32 bits
+	   256 byte modulus
+	   ignore checksum 20 bytes
+	 */
+
+	native_val = (__force __be32 *) (data + 34);
+
+	str +=
+	    sprintf(str,
+		    "Algorithm: %02X %02X %02X %02X\nEncscheme: %02X %02X\n"
+		    "Sigscheme: %02X %02X\nParameters: %02X %02X %02X %02X"
+		    " %02X %02X %02X %02X %02X %02X %02X %02X\n"
+		    "Modulus length: %d\nModulus: \n",
+		    data[10], data[11], data[12], data[13], data[14],
+		    data[15], data[16], data[17], data[22], data[23],
+		    data[24], data[25], data[26], data[27], data[28],
+		    data[29], data[30], data[31], data[32], data[33],
+		    be32_to_cpu(*native_val)
+	    );
+
+	for (i = 0; i < 256; i++) {
+		str += sprintf(str, "%02X ", data[i + 39]);
+		if ((i + 1) % 16 == 0)
+			str += sprintf(str, "\n");
+	}
+	return str - buf;
+}
+
+static DEVICE_ATTR(pubek, S_IRUGO, show_pubek, NULL);
+
+#define CAP_VER_RESULT_SIZE 18
+static u8 cap_version[] = {
+	0, 193,			/* TPM_TAG_RQU_COMMAND */
+	0, 0, 0, 18,		/* length */
+	0, 0, 0, 101,		/* TPM_ORD_GetCapability */
+	0, 0, 0, 6,
+	0, 0, 0, 0
+};
+
+#define CAP_MANUFACTURER_RESULT_SIZE 18
+static u8 cap_manufacturer[] = {
+	0, 193,			/* TPM_TAG_RQU_COMMAND */
+	0, 0, 0, 22,		/* length */
+	0, 0, 0, 101,		/* TPM_ORD_GetCapability */
+	0, 0, 0, 5,
+	0, 0, 0, 4,
+	0, 0, 1, 3
+};
+
+static ssize_t show_caps(struct device *dev, char *buf)
+{
+	u8 data[READ_PUBEK_RESULT_SIZE];
+	ssize_t len;
+	char *str = buf;
+
+	struct tpm_chip *chip =
+	    pci_get_drvdata(container_of(dev, struct pci_dev, dev));
+	if (chip == NULL)
+		return -ENODEV;
+
+	memcpy(data, cap_manufacturer, sizeof(cap_manufacturer));
+
+	if ((len = tpm_transmit(chip, data, sizeof(data))) <
+	    CAP_MANUFACTURER_RESULT_SIZE)
+		return len;
+
+	str += sprintf(str, "Manufacturer: 0x%x\n",
+		       be32_to_cpu(*(data + 14)));
+
+	memcpy(data, cap_version, sizeof(cap_version));
+
+	if ((len = tpm_transmit(chip, data, sizeof(data))) <
+	    CAP_VER_RESULT_SIZE)
+		return len;
+
+	str +=
+	    sprintf(str, "TCG version: %d.%d\nFirmware version: %d.%d\n",
+		    (int) data[14], (int) data[15], (int) data[16],
+		    (int) data[17]);
+
+	return str - buf;
+}
+
+static DEVICE_ATTR(caps, S_IRUGO, show_caps, NULL);
+
+/*
+ * Device file system interface to the TPM
+ */
+int tpm_open(struct inode *inode, struct file *file)
+{
+	int rc = 0, minor = iminor(inode);
+	struct tpm_chip *chip = NULL, *pos;
+
+	spin_lock(&driver_lock);
+
+	list_for_each_entry(pos, &tpm_chip_list, list) {
+		if (pos->vendor->miscdev.minor == minor) {
+			chip = pos;
+			break;
+		}
+	}
+
+	if (chip == NULL) {
+		rc = -ENODEV;
+		goto err_out;
+	}
+
+	if (chip->num_opens) {
+		dev_dbg(&chip->pci_dev->dev,
+			"Another process owns this TPM\n");
+		rc = -EBUSY;
+		goto err_out;
+	}
+
+	chip->num_opens++;
+	pci_dev_get(chip->pci_dev);
+
+	spin_unlock(&driver_lock);
+
+	chip->data_buffer = kmalloc(TPM_BUFSIZE * sizeof(u8), GFP_KERNEL);
+	if (chip->data_buffer == NULL) {
+		chip->num_opens--;
+		pci_dev_put(chip->pci_dev);
+		return -ENOMEM;
+	}
+
+	atomic_set(&chip->data_pending, 0);
+
+	file->private_data = chip;
+	return 0;
+
+err_out:
+	spin_unlock(&driver_lock);
+	return rc;
+}
+
+EXPORT_SYMBOL_GPL(tpm_open);
+
+int tpm_release(struct inode *inode, struct file *file)
+{
+	struct tpm_chip *chip = file->private_data;
+	
+	file->private_data = NULL;
+
+	spin_lock(&driver_lock);
+	chip->num_opens--;
+	spin_unlock(&driver_lock);
+
+	down(&chip->timer_manipulation_mutex);
+	if (timer_pending(&chip->user_read_timer))
+		del_singleshot_timer_sync(&chip->user_read_timer);
+	else if (timer_pending(&chip->device_timer))
+		del_singleshot_timer_sync(&chip->device_timer);
+	up(&chip->timer_manipulation_mutex);
+
+	kfree(chip->data_buffer);
+	atomic_set(&chip->data_pending, 0);
+
+	pci_dev_put(chip->pci_dev);
+	return 0;
+}
+
+EXPORT_SYMBOL_GPL(tpm_release);
+
+ssize_t tpm_write(struct file * file, const char __user * buf,
+		  size_t size, loff_t * off)
+{
+	struct tpm_chip *chip = file->private_data;
+	int in_size = size, out_size;
+
+	/* cannot perform a write until the read has cleared
+	   either via tpm_read or a user_read_timer timeout */
+	while (atomic_read(&chip->data_pending) != 0) {
+		set_current_state(TASK_UNINTERRUPTIBLE);
+		schedule_timeout(TPM_TIMEOUT);
+	}
+
+	down(&chip->buffer_mutex);
+
+	if (in_size > TPM_BUFSIZE)
+		in_size = TPM_BUFSIZE;
+
+	if (copy_from_user
+	    (chip->data_buffer, (void __user *) buf, in_size)) {
+		up(&chip->buffer_mutex);
+		return -EFAULT;
+	}
+
+	/* atomic tpm command send and result receive */
+	out_size = tpm_transmit(chip, chip->data_buffer, TPM_BUFSIZE);
+
+	atomic_set(&chip->data_pending, out_size);
+	up(&chip->buffer_mutex);
+
+	/* Set a timeout by which the reader must come claim the result */
+	down(&chip->timer_manipulation_mutex);
+	init_timer(&chip->user_read_timer);
+	chip->user_read_timer.function = user_reader_timeout;
+	chip->user_read_timer.data = (unsigned long) chip;
+	chip->user_read_timer.expires = jiffies + (60 * HZ);
+	add_timer(&chip->user_read_timer);
+	up(&chip->timer_manipulation_mutex);
+
+	return in_size;
+}
+
+EXPORT_SYMBOL_GPL(tpm_write);
+
+ssize_t tpm_read(struct file * file, char __user * buf,
+		 size_t size, loff_t * off)
+{
+	struct tpm_chip *chip = file->private_data;
+	int ret_size = -ENODATA;
+
+	if (atomic_read(&chip->data_pending) != 0) {	/* Result available */
+		down(&chip->timer_manipulation_mutex);
+		del_singleshot_timer_sync(&chip->user_read_timer);
+		up(&chip->timer_manipulation_mutex);
+
+		down(&chip->buffer_mutex);
+
+		ret_size = atomic_read(&chip->data_pending);
+		atomic_set(&chip->data_pending, 0);
+
+		if (ret_size == 0)	/* timeout just occurred */
+			ret_size = -ETIME;
+		else if (ret_size > 0) {	/* relay data */
+			if (size < ret_size)
+				ret_size = size;
+
+			if (copy_to_user((void __user *) buf,
+					 chip->data_buffer, ret_size)) {
+				ret_size = -EFAULT;
+			}
+		}
+		up(&chip->buffer_mutex);
+	}
+
+	return ret_size;
+}
+
+EXPORT_SYMBOL_GPL(tpm_read);
+
+void __devexit tpm_remove(struct pci_dev *pci_dev)
+{
+	struct tpm_chip *chip = pci_get_drvdata(pci_dev);
+
+	if (chip == NULL) {
+		dev_err(&pci_dev->dev, "No device data found\n");
+		return;
+	}
+
+	spin_lock(&driver_lock);
+
+	list_del(&chip->list);
+
+	spin_unlock(&driver_lock);
+
+	pci_set_drvdata(pci_dev, NULL);
+	misc_deregister(&chip->vendor->miscdev);
+
+	device_remove_file(&pci_dev->dev, &dev_attr_pubek);
+	device_remove_file(&pci_dev->dev, &dev_attr_pcrs);
+	device_remove_file(&pci_dev->dev, &dev_attr_caps);
+
+	pci_disable_device(pci_dev);
+
+	dev_mask[chip->dev_num / 32] &= !(1 << (chip->dev_num % 32));
+
+	kfree(chip);
+
+	pci_dev_put(pci_dev);
+}
+
+EXPORT_SYMBOL_GPL(tpm_remove);
+
+static u8 savestate[] = {
+	0, 193,			/* TPM_TAG_RQU_COMMAND */
+	0, 0, 0, 10,		/* blob length (in bytes) */
+	0, 0, 0, 152		/* TPM_ORD_SaveState */
+};
+
+/*
+ * We are about to suspend. Save the TPM state
+ * so that it can be restored.
+ */
+int tpm_pm_suspend(struct pci_dev *pci_dev, u32 pm_state)
+{
+	struct tpm_chip *chip = pci_get_drvdata(pci_dev);
+	if (chip == NULL)
+		return -ENODEV;
+
+	tpm_transmit(chip, savestate, sizeof(savestate));
+	return 0;
+}
+
+EXPORT_SYMBOL_GPL(tpm_pm_suspend);
+
+/*
+ * Resume from a power safe. The BIOS already restored
+ * the TPM state.
+ */
+int tpm_pm_resume(struct pci_dev *pci_dev)
+{
+	struct tpm_chip *chip = pci_get_drvdata(pci_dev);
+
+	if (chip == NULL)
+		return -ENODEV;
+
+	spin_lock(&driver_lock);
+	tpm_lpc_bus_init(pci_dev, chip->vendor->base);
+	spin_unlock(&driver_lock);
+
+	return 0;
+}
+
+EXPORT_SYMBOL_GPL(tpm_pm_resume);
+
+/*
+ * Called from tpm_<specific>.c probe function only for devices 
+ * the driver has determined it should claim.  Prior to calling
+ * this function the specific probe function has called pci_enable_device
+ * upon errant exit from this function specific probe function should call
+ * pci_disable_device
+ */
+int tpm_register_hardware(struct pci_dev *pci_dev,
+			  struct tpm_vendor_specific *entry)
+{
+	char devname[7];
+	struct tpm_chip *chip;
+	int i, j;
+
+	/* Driver specific per-device data */
+	chip = kmalloc(sizeof(*chip), GFP_KERNEL);
+	if (chip == NULL)
+		return -ENOMEM;
+
+	memset(chip, 0, sizeof(struct tpm_chip));
+
+	init_MUTEX(&chip->buffer_mutex);
+	init_MUTEX(&chip->tpm_mutex);
+	init_MUTEX(&chip->timer_manipulation_mutex);
+	INIT_LIST_HEAD(&chip->list);
+
+	chip->vendor = entry;
+
+	chip->dev_num = -1;
+
+	for (i = 0; i < 32; i++)
+		for (j = 0; j < 8; j++)
+			if ((dev_mask[i] & (1 << j)) == 0) {
+				chip->dev_num = i * 32 + j;
+				dev_mask[i] |= 1 << j;
+				goto dev_num_search_complete;
+			}
+
+dev_num_search_complete:
+	if (chip->dev_num < 0) {
+		dev_err(&pci_dev->dev,
+			"No available tpm device numbers\n");
+		kfree(chip);
+		return -ENODEV;
+	} else if (chip->dev_num == 0)
+		chip->vendor->miscdev.minor = TPM_MINOR;
+	else
+		chip->vendor->miscdev.minor = MISC_DYNAMIC_MINOR;
+
+	snprintf(devname, sizeof(devname), "%s%d", "tpm", chip->dev_num);
+	chip->vendor->miscdev.name = devname;
+
+	chip->vendor->miscdev.dev = &(pci_dev->dev);
+	chip->pci_dev = pci_dev_get(pci_dev);
+
+	if (misc_register(&chip->vendor->miscdev)) {
+		dev_err(&chip->pci_dev->dev,
+			"unable to misc_register %s, minor %d\n",
+			chip->vendor->miscdev.name,
+			chip->vendor->miscdev.minor);
+		pci_dev_put(pci_dev);
+		kfree(chip);
+		dev_mask[i] &= !(1 << j);
+		return -ENODEV;
+	}
+
+	pci_set_drvdata(pci_dev, chip);
+
+	list_add(&chip->list, &tpm_chip_list);
+
+	device_create_file(&pci_dev->dev, &dev_attr_pubek);
+	device_create_file(&pci_dev->dev, &dev_attr_pcrs);
+	device_create_file(&pci_dev->dev, &dev_attr_caps);
+
+	return 0;
+}
+
+EXPORT_SYMBOL_GPL(tpm_register_hardware);
+
+static int __init init_tpm(void)
+{
+	return 0;
+}
+
+static void __exit cleanup_tpm(void)
+{
+
+}
+
+module_init(init_tpm);
+module_exit(cleanup_tpm);
+
+MODULE_AUTHOR("Leendert van Doorn (leendert@watson.ibm.com)");
+MODULE_DESCRIPTION("TPM Driver");
+MODULE_VERSION("2.0");
+MODULE_LICENSE("GPL");
diff -Nru a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/char/tpm/tpm.h	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2004 IBM Corporation
+ *
+ * Authors:
+ * Leendert van Doorn <leendert@watson.ibm.com>
+ * Dave Safford <safford@watson.ibm.com>
+ * Reiner Sailer <sailer@watson.ibm.com>
+ * Kylene Hall <kjhall@us.ibm.com>
+ *
+ * Maintained by: <tpmdd_devel@lists.sourceforge.net>
+ *
+ * Device driver for TCG/TCPA TPM (trusted platform module).
+ * Specifications at www.trustedcomputinggroup.org	 
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2 of the
+ * License.
+ * 
+ */
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/miscdevice.h>
+
+#define TPM_TIMEOUT msecs_to_jiffies(5)
+
+/* TPM addresses */
+#define	TPM_ADDR			0x4E
+#define	TPM_DATA			0x4F
+
+struct tpm_chip;
+
+struct tpm_vendor_specific {
+	u8 req_complete_mask;
+	u8 req_complete_val;
+	u16 base;		/* TPM base address */
+
+	int (*recv) (struct tpm_chip *, u8 *, size_t);
+	int (*send) (struct tpm_chip *, u8 *, size_t);
+	void (*cancel) (struct tpm_chip *);
+	struct miscdevice miscdev;
+};
+
+struct tpm_chip {
+	struct pci_dev *pci_dev;	/* PCI device stuff */
+
+	int dev_num;		/* /dev/tpm# */
+	int num_opens;		/* only one allowed */
+	int time_expired;
+
+	/* Data passed to and from the tpm via the read/write calls */
+	u8 *data_buffer;
+	atomic_t data_pending;
+	struct semaphore buffer_mutex;
+
+	struct timer_list user_read_timer;	/* user needs to claim result */
+	struct semaphore tpm_mutex;	/* tpm is processing */
+	struct timer_list device_timer;	/* tpm is processing */
+	struct semaphore timer_manipulation_mutex;
+
+	struct tpm_vendor_specific *vendor;
+
+	struct list_head list;
+};
+
+static inline int tpm_read_index(int index)
+{
+	outb(index, TPM_ADDR);
+	return inb(TPM_DATA) & 0xFF;
+}
+
+static inline void tpm_write_index(int index, int value)
+{
+	outb(index, TPM_ADDR);
+	outb(value & 0xFF, TPM_DATA);
+}
+
+extern void tpm_time_expired(unsigned long);
+extern int tpm_lpc_bus_init(struct pci_dev *, u16);
+
+extern int tpm_register_hardware(struct pci_dev *,
+				 struct tpm_vendor_specific *);
+extern int tpm_open(struct inode *, struct file *);
+extern int tpm_release(struct inode *, struct file *);
+extern ssize_t tpm_write(struct file *, const char __user *, size_t,
+			 loff_t *);
+extern ssize_t tpm_read(struct file *, char __user *, size_t, loff_t *);
+extern void __devexit tpm_remove(struct pci_dev *);
+extern int tpm_pm_suspend(struct pci_dev *, u32);
+extern int tpm_pm_resume(struct pci_dev *);
diff -Nru a/drivers/char/tpm/tpm_atmel.c b/drivers/char/tpm/tpm_atmel.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/char/tpm/tpm_atmel.c	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,216 @@
+/*
+ * Copyright (C) 2004 IBM Corporation
+ *
+ * Authors:
+ * Leendert van Doorn <leendert@watson.ibm.com>
+ * Dave Safford <safford@watson.ibm.com>
+ * Reiner Sailer <sailer@watson.ibm.com>
+ * Kylene Hall <kjhall@us.ibm.com>
+ *
+ * Maintained by: <tpmdd_devel@lists.sourceforge.net>
+ *
+ * Device driver for TCG/TCPA TPM (trusted platform module).
+ * Specifications at www.trustedcomputinggroup.org	 
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2 of the
+ * License.
+ * 
+ */
+
+#include "tpm.h"
+
+/* Atmel definitions */
+#define	TPM_ATML_BASE			0x400
+
+/* write status bits */
+#define	ATML_STATUS_ABORT		0x01
+#define	ATML_STATUS_LASTBYTE		0x04
+
+/* read status bits */
+#define	ATML_STATUS_BUSY		0x01
+#define	ATML_STATUS_DATA_AVAIL		0x02
+#define	ATML_STATUS_REWRITE		0x04
+
+
+static int tpm_atml_recv(struct tpm_chip *chip, u8 * buf, size_t count)
+{
+	u8 status, *hdr = buf;
+	u32 size;
+	int i;
+	__be32 *native_size;
+
+	/* start reading header */
+	if (count < 6)
+		return -EIO;
+
+	for (i = 0; i < 6; i++) {
+		status = inb(chip->vendor->base + 1);
+		if ((status & ATML_STATUS_DATA_AVAIL) == 0) {
+			dev_err(&chip->pci_dev->dev,
+				"error reading header\n");
+			return -EIO;
+		}
+		*buf++ = inb(chip->vendor->base);
+	}
+
+	/* size of the data received */
+	native_size = (__force __be32 *) (hdr + 2);
+	size = be32_to_cpu(*native_size);
+
+	if (count < size) {
+		dev_err(&chip->pci_dev->dev,
+			"Recv size(%d) less than available space\n", size);
+		for (; i < size; i++) {	/* clear the waiting data anyway */
+			status = inb(chip->vendor->base + 1);
+			if ((status & ATML_STATUS_DATA_AVAIL) == 0) {
+				dev_err(&chip->pci_dev->dev,
+					"error reading data\n");
+				return -EIO;
+			}
+		}
+		return -EIO;
+	}
+
+	/* read all the data available */
+	for (; i < size; i++) {
+		status = inb(chip->vendor->base + 1);
+		if ((status & ATML_STATUS_DATA_AVAIL) == 0) {
+			dev_err(&chip->pci_dev->dev,
+				"error reading data\n");
+			return -EIO;
+		}
+		*buf++ = inb(chip->vendor->base);
+	}
+
+	/* make sure data available is gone */
+	status = inb(chip->vendor->base + 1);
+	if (status & ATML_STATUS_DATA_AVAIL) {
+		dev_err(&chip->pci_dev->dev, "data available is stuck\n");
+		return -EIO;
+	}
+
+	return size;
+}
+
+static int tpm_atml_send(struct tpm_chip *chip, u8 * buf, size_t count)
+{
+	int i;
+
+	dev_dbg(&chip->pci_dev->dev, "tpm_atml_send: ");
+	for (i = 0; i < count; i++) {
+		dev_dbg(&chip->pci_dev->dev, "0x%x(%d) ", buf[i], buf[i]);
+		outb(buf[i], chip->vendor->base);
+	}
+
+	return count;
+}
+
+static void tpm_atml_cancel(struct tpm_chip *chip)
+{
+	outb(ATML_STATUS_ABORT, chip->vendor->base + 1);
+}
+
+static struct file_operations atmel_ops = {
+	.owner = THIS_MODULE,
+	.llseek = no_llseek,
+	.open = tpm_open,
+	.read = tpm_read,
+	.write = tpm_write,
+	.release = tpm_release,
+};
+
+static struct tpm_vendor_specific tpm_atmel = {
+	.recv = tpm_atml_recv,
+	.send = tpm_atml_send,
+	.cancel = tpm_atml_cancel,
+	.req_complete_mask = ATML_STATUS_BUSY | ATML_STATUS_DATA_AVAIL,
+	.req_complete_val = ATML_STATUS_DATA_AVAIL,
+	.base = TPM_ATML_BASE,
+	.miscdev = { .fops = &atmel_ops, },
+};
+
+static int __devinit tpm_atml_init(struct pci_dev *pci_dev,
+				   const struct pci_device_id *pci_id)
+{
+	u8 version[4];
+	int rc = 0;
+
+	if (pci_enable_device(pci_dev))
+		return -EIO;
+
+	if (tpm_lpc_bus_init(pci_dev, TPM_ATML_BASE)) {
+		rc = -ENODEV;
+		goto out_err;
+	}
+
+	/* verify that it is an Atmel part */
+	if (tpm_read_index(4) != 'A' || tpm_read_index(5) != 'T'
+	    || tpm_read_index(6) != 'M' || tpm_read_index(7) != 'L') {
+		rc = -ENODEV;
+		goto out_err;
+	}
+
+	/* query chip for its version number */
+	if ((version[0] = tpm_read_index(0x00)) != 0xFF) {
+		version[1] = tpm_read_index(0x01);
+		version[2] = tpm_read_index(0x02);
+		version[3] = tpm_read_index(0x03);
+	} else {
+		dev_info(&pci_dev->dev, "version query failed\n");
+		rc = -ENODEV;
+		goto out_err;
+	}
+
+	if ((rc = tpm_register_hardware(pci_dev, &tpm_atmel)) < 0)
+		goto out_err;
+
+	dev_info(&pci_dev->dev,
+		 "Atmel TPM version %d.%d.%d.%d\n", version[0], version[1],
+		 version[2], version[3]);
+
+	return 0;
+out_err:
+	pci_disable_device(pci_dev);
+	return rc;
+}
+
+static struct pci_device_id tpm_pci_tbl[] __devinitdata = {
+	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_0)},
+	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_12)},
+	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_0)},
+	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_12)},
+	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0)},
+	{PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8111_LPC)},
+	{0,}
+};
+
+MODULE_DEVICE_TABLE(pci, tpm_pci_tbl);
+
+static struct pci_driver atmel_pci_driver = {
+	.name = "tpm_atmel",
+	.id_table = tpm_pci_tbl,
+	.probe = tpm_atml_init,
+	.remove = __devexit_p(tpm_remove),
+	.suspend = tpm_pm_suspend,
+	.resume = tpm_pm_resume,
+};
+
+static int __init init_atmel(void)
+{
+	return pci_register_driver(&atmel_pci_driver);
+}
+
+static void __exit cleanup_atmel(void)
+{
+	pci_unregister_driver(&atmel_pci_driver);
+}
+
+module_init(init_atmel);
+module_exit(cleanup_atmel);
+
+MODULE_AUTHOR("Leendert van Doorn (leendert@watson.ibm.com)");
+MODULE_DESCRIPTION("TPM Driver");
+MODULE_VERSION("2.0");
+MODULE_LICENSE("GPL");
diff -Nru a/drivers/char/tpm/tpm_nsc.c b/drivers/char/tpm/tpm_nsc.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/char/tpm/tpm_nsc.c	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,373 @@
+/*
+ * Copyright (C) 2004 IBM Corporation
+ *
+ * Authors:
+ * Leendert van Doorn <leendert@watson.ibm.com>
+ * Dave Safford <safford@watson.ibm.com>
+ * Reiner Sailer <sailer@watson.ibm.com>
+ * Kylene Hall <kjhall@us.ibm.com>
+ *
+ * Maintained by: <tpmdd_devel@lists.sourceforge.net>
+ *
+ * Device driver for TCG/TCPA TPM (trusted platform module).
+ * Specifications at www.trustedcomputinggroup.org	 
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, version 2 of the
+ * License.
+ * 
+ */
+
+#include "tpm.h"
+
+/* National definitions */
+#define	TPM_NSC_BASE			0x360
+#define	TPM_NSC_IRQ			0x07
+
+#define	NSC_LDN_INDEX			0x07
+#define	NSC_SID_INDEX			0x20
+#define	NSC_LDC_INDEX			0x30
+#define	NSC_DIO_INDEX			0x60
+#define	NSC_CIO_INDEX			0x62
+#define	NSC_IRQ_INDEX			0x70
+#define	NSC_ITS_INDEX			0x71
+
+#define	NSC_STATUS			0x01
+#define	NSC_COMMAND			0x01
+#define	NSC_DATA			0x00
+
+/* status bits */
+#define	NSC_STATUS_OBF			0x01	/* output buffer full */
+#define	NSC_STATUS_IBF			0x02	/* input buffer full */
+#define	NSC_STATUS_F0			0x04	/* F0 */
+#define	NSC_STATUS_A2			0x08	/* A2 */
+#define	NSC_STATUS_RDY			0x10	/* ready to receive command */
+#define	NSC_STATUS_IBR			0x20	/* ready to receive data */
+
+/* command bits */
+#define	NSC_COMMAND_NORMAL		0x01	/* normal mode */
+#define	NSC_COMMAND_EOC			0x03
+#define	NSC_COMMAND_CANCEL		0x22
+
+/*
+ * Wait for a certain status to appear
+ */
+static int wait_for_stat(struct tpm_chip *chip, u8 mask, u8 val, u8 * data)
+{
+	int expired = 0;
+	struct timer_list status_timer =
+	    TIMER_INITIALIZER(tpm_time_expired, jiffies + 10 * HZ,
+			      (unsigned long) &expired);
+
+	/* status immediately available check */
+	*data = inb(chip->vendor->base + NSC_STATUS);
+	if ((*data & mask) == val)
+		return 0;
+
+	/* wait for status */
+	add_timer(&status_timer);
+	do {
+		set_current_state(TASK_UNINTERRUPTIBLE);
+		schedule_timeout(TPM_TIMEOUT);
+		*data = inb(chip->vendor->base + 1);
+		if ((*data & mask) == val) {
+			del_singleshot_timer_sync(&status_timer);
+			return 0;
+		}
+	}
+	while (!expired);
+
+	return -EBUSY;
+}
+
+static int nsc_wait_for_ready(struct tpm_chip *chip)
+{
+	int status;
+	int expired = 0;
+	struct timer_list status_timer =
+	    TIMER_INITIALIZER(tpm_time_expired, jiffies + 100,
+			      (unsigned long) &expired);
+
+	/* status immediately available check */
+	status = inb(chip->vendor->base + NSC_STATUS);
+	if (status & NSC_STATUS_OBF)
+		status = inb(chip->vendor->base + NSC_DATA);
+	if (status & NSC_STATUS_RDY)
+		return 0;
+
+	/* wait for status */
+	add_timer(&status_timer);
+	do {
+		set_current_state(TASK_UNINTERRUPTIBLE);
+		schedule_timeout(TPM_TIMEOUT);
+		status = inb(chip->vendor->base + NSC_STATUS);
+		if (status & NSC_STATUS_OBF)
+			status = inb(chip->vendor->base + NSC_DATA);
+		if (status & NSC_STATUS_RDY) {
+			del_singleshot_timer_sync(&status_timer);
+			return 0;
+		}
+	}
+	while (!expired);
+
+	dev_info(&chip->pci_dev->dev, "wait for ready failed\n");
+	return -EBUSY;
+}
+
+
+static int tpm_nsc_recv(struct tpm_chip *chip, u8 * buf, size_t count)
+{
+	u8 *buffer = buf;
+	u8 data, *p;
+	u32 size;
+	__be32 *native_size;
+
+	if (count < 6)
+		return -EIO;
+
+	if (wait_for_stat(chip, NSC_STATUS_F0, NSC_STATUS_F0, &data) < 0) {
+		dev_err(&chip->pci_dev->dev, "F0 timeout\n");
+		return -EIO;
+	}
+	if ((data =
+	     inb(chip->vendor->base + NSC_DATA)) != NSC_COMMAND_NORMAL) {
+		dev_err(&chip->pci_dev->dev, "not in normal mode (0x%x)\n",
+			data);
+		return -EIO;
+	}
+
+	/* read the whole packet */
+	for (p = buffer; p < &buffer[count]; p++) {
+		if (wait_for_stat
+		    (chip, NSC_STATUS_OBF, NSC_STATUS_OBF, &data) < 0) {
+			dev_err(&chip->pci_dev->dev,
+				"OBF timeout (while reading data)\n");
+			return -EIO;
+		}
+		if (data & NSC_STATUS_F0)
+			break;
+		*p = inb(chip->vendor->base + NSC_DATA);
+	}
+
+	if ((data & NSC_STATUS_F0) == 0) {
+		dev_err(&chip->pci_dev->dev, "F0 not set\n");
+		return -EIO;
+	}
+	if ((data = inb(chip->vendor->base + NSC_DATA)) != NSC_COMMAND_EOC) {
+		dev_err(&chip->pci_dev->dev,
+			"expected end of command(0x%x)\n", data);
+		return -EIO;
+	}
+
+	native_size = (__force __be32 *) (buf + 2);
+	size = be32_to_cpu(*native_size);
+
+	if (count < size)
+		return -EIO;
+
+	return size;
+}
+
+static int tpm_nsc_send(struct tpm_chip *chip, u8 * buf, size_t count)
+{
+	u8 data;
+	int i;
+
+	/*
+	 * If we hit the chip with back to back commands it locks up
+	 * and never set IBF. Hitting it with this "hammer" seems to
+	 * fix it. Not sure why this is needed, we followed the flow
+	 * chart in the manual to the letter.
+	 */
+	outb(NSC_COMMAND_CANCEL, chip->vendor->base + NSC_COMMAND);
+
+	if (nsc_wait_for_ready(chip) != 0)
+		return -EIO;
+
+	if (wait_for_stat(chip, NSC_STATUS_IBF, 0, &data) < 0) {
+		dev_err(&chip->pci_dev->dev, "IBF timeout\n");
+		return -EIO;
+	}
+
+	outb(NSC_COMMAND_NORMAL, chip->vendor->base + NSC_COMMAND);
+	if (wait_for_stat(chip, NSC_STATUS_IBR, NSC_STATUS_IBR, &data) < 0) {
+		dev_err(&chip->pci_dev->dev, "IBR timeout\n");
+		return -EIO;
+	}
+
+	for (i = 0; i < count; i++) {
+		if (wait_for_stat(chip, NSC_STATUS_IBF, 0, &data) < 0) {
+			dev_err(&chip->pci_dev->dev,
+				"IBF timeout (while writing data)\n");
+			return -EIO;
+		}
+		outb(buf[i], chip->vendor->base + NSC_DATA);
+	}
+
+	if (wait_for_stat(chip, NSC_STATUS_IBF, 0, &data) < 0) {
+		dev_err(&chip->pci_dev->dev, "IBF timeout\n");
+		return -EIO;
+	}
+	outb(NSC_COMMAND_EOC, chip->vendor->base + NSC_COMMAND);
+
+	return count;
+}
+
+static void tpm_nsc_cancel(struct tpm_chip *chip)
+{
+	outb(NSC_COMMAND_CANCEL, chip->vendor->base + NSC_COMMAND);
+}
+
+static struct file_operations nsc_ops = {
+	.owner = THIS_MODULE,
+	.llseek = no_llseek,
+	.open = tpm_open,
+	.read = tpm_read,
+	.write = tpm_write,
+	.release = tpm_release,
+};
+
+static struct tpm_vendor_specific tpm_nsc = {
+	.recv = tpm_nsc_recv,
+	.send = tpm_nsc_send,
+	.cancel = tpm_nsc_cancel,
+	.req_complete_mask = NSC_STATUS_OBF,
+	.req_complete_val = NSC_STATUS_OBF,
+	.base = TPM_NSC_BASE,
+	.miscdev = { .fops = &nsc_ops, },
+	
+};
+
+static int __devinit tpm_nsc_init(struct pci_dev *pci_dev,
+				  const struct pci_device_id *pci_id)
+{
+	int rc = 0;
+
+	if (pci_enable_device(pci_dev))
+		return -EIO;
+
+	if (tpm_lpc_bus_init(pci_dev, TPM_NSC_BASE)) {
+		rc = -ENODEV;
+		goto out_err;
+	}
+
+	/* verify that it is a National part (SID) */
+	if (tpm_read_index(NSC_SID_INDEX) != 0xEF) {
+		rc = -ENODEV;
+		goto out_err;
+	}
+
+	dev_dbg(&pci_dev->dev, "NSC TPM detected\n");
+	dev_dbg(&pci_dev->dev,
+		"NSC LDN 0x%x, SID 0x%x, SRID 0x%x\n",
+		tpm_read_index(0x07), tpm_read_index(0x20),
+		tpm_read_index(0x27));
+	dev_dbg(&pci_dev->dev,
+		"NSC SIOCF1 0x%x SIOCF5 0x%x SIOCF6 0x%x SIOCF8 0x%x\n",
+		tpm_read_index(0x21), tpm_read_index(0x25),
+		tpm_read_index(0x26), tpm_read_index(0x28));
+	dev_dbg(&pci_dev->dev, "NSC IO Base0 0x%x\n",
+		(tpm_read_index(0x60) << 8) | tpm_read_index(0x61));
+	dev_dbg(&pci_dev->dev, "NSC IO Base1 0x%x\n",
+		(tpm_read_index(0x62) << 8) | tpm_read_index(0x63));
+	dev_dbg(&pci_dev->dev, "NSC Interrupt number and wakeup 0x%x\n",
+		tpm_read_index(0x70));
+	dev_dbg(&pci_dev->dev, "NSC IRQ type select 0x%x\n",
+		tpm_read_index(0x71));
+	dev_dbg(&pci_dev->dev,
+		"NSC DMA channel select0 0x%x, select1 0x%x\n",
+		tpm_read_index(0x74), tpm_read_index(0x75));
+	dev_dbg(&pci_dev->dev,
+		"NSC Config "
+		"0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n",
+		tpm_read_index(0xF0), tpm_read_index(0xF1),
+		tpm_read_index(0xF2), tpm_read_index(0xF3),
+		tpm_read_index(0xF4), tpm_read_index(0xF5),
+		tpm_read_index(0xF6), tpm_read_index(0xF7),
+		tpm_read_index(0xF8), tpm_read_index(0xF9));
+
+	dev_info(&pci_dev->dev,
+		 "NSC PC21100 TPM revision %d\n",
+		 tpm_read_index(0x27) & 0x1F);
+
+	if (tpm_read_index(NSC_LDC_INDEX) == 0)
+		dev_info(&pci_dev->dev, ": NSC TPM not active\n");
+
+	/* select PM channel 1 */
+	tpm_write_index(NSC_LDN_INDEX, 0x12);
+	tpm_read_index(NSC_LDN_INDEX);
+
+	/* disable the DPM module */
+	tpm_write_index(NSC_LDC_INDEX, 0);
+	tpm_read_index(NSC_LDC_INDEX);
+
+	/* set the data register base addresses */
+	tpm_write_index(NSC_DIO_INDEX, TPM_NSC_BASE >> 8);
+	tpm_write_index(NSC_DIO_INDEX + 1, TPM_NSC_BASE);
+	tpm_read_index(NSC_DIO_INDEX);
+	tpm_read_index(NSC_DIO_INDEX + 1);
+
+	/* set the command register base addresses */
+	tpm_write_index(NSC_CIO_INDEX, (TPM_NSC_BASE + 1) >> 8);
+	tpm_write_index(NSC_CIO_INDEX + 1, (TPM_NSC_BASE + 1));
+	tpm_read_index(NSC_DIO_INDEX);
+	tpm_read_index(NSC_DIO_INDEX + 1);
+
+	/* set the interrupt number to be used for the host interface */
+	tpm_write_index(NSC_IRQ_INDEX, TPM_NSC_IRQ);
+	tpm_write_index(NSC_ITS_INDEX, 0x00);
+	tpm_read_index(NSC_IRQ_INDEX);
+
+	/* enable the DPM module */
+	tpm_write_index(NSC_LDC_INDEX, 0x01);
+	tpm_read_index(NSC_LDC_INDEX);
+
+	if ((rc = tpm_register_hardware(pci_dev, &tpm_nsc)) < 0)
+		goto out_err;
+
+	return 0;
+
+out_err:
+	pci_disable_device(pci_dev);
+	return rc;
+}
+
+static struct pci_device_id tpm_pci_tbl[] __devinitdata = {
+	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_0)},
+	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_12)},
+	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_0)},
+	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_12)},
+	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0)},
+	{PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8111_LPC)},
+	{0,}
+};
+
+MODULE_DEVICE_TABLE(pci, tpm_pci_tbl);
+
+static struct pci_driver nsc_pci_driver = {
+	.name = "tpm_nsc",
+	.id_table = tpm_pci_tbl,
+	.probe = tpm_nsc_init,
+	.remove = __devexit_p(tpm_remove),
+	.suspend = tpm_pm_suspend,
+	.resume = tpm_pm_resume,
+};
+
+static int __init init_nsc(void)
+{
+	return pci_register_driver(&nsc_pci_driver);
+}
+
+static void __exit cleanup_nsc(void)
+{
+	pci_unregister_driver(&nsc_pci_driver);
+}
+
+module_init(init_nsc);
+module_exit(cleanup_nsc);
+
+MODULE_AUTHOR("Leendert van Doorn (leendert@watson.ibm.com)");
+MODULE_DESCRIPTION("TPM Driver");
+MODULE_VERSION("2.0");
+MODULE_LICENSE("GPL");
diff -Nru a/drivers/char/tpqic02.c b/drivers/char/tpqic02.c
--- a/drivers/char/tpqic02.c	2005-03-11 12:51:46 -08:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,2812 +0,0 @@
-/* $Id: tpqic02.c,v 1.10 1997/01/26 07:13:20 davem Exp $
- *
- * Driver for tape drive support for Linux-i386
- *
- * Copyright (c) 1992--1996 by H. H. Bergman. All rights reserved.
- * Current e-mail address: hennus@cybercomm.nl
- *
- * Distribution of this program in executable form is only allowed if
- * all of the corresponding source files are made available through the same
- * medium at no extra cost.
- *
- * I will not accept any responsibility for damage caused directly or
- * indirectly by this program, or code derived from this program.
- *
- * Use this code at your own risk. Don't blame me if it destroys your data!
- * Make sure you have a backup before you try this code.
- *
- * If you make changes to my code and redistribute it in source or binary
- * form you must make it clear to even casual users of your code that you
- * have modified my code, clearly point out what the changes exactly are
- * (preferably in the form of a context diff file), how to undo your changes,
- * where the original can be obtained, and that complaints/requests about the
- * modified code should be directed to you instead of me.
- *
- * This driver was partially inspired by the 'wt' driver in the 386BSD
- * source distribution, which carries the following copyright notice:
- *
- *  Copyright (c) 1991 The Regents of the University of California.
- *  All rights reserved.
- *
- * You are not allowed to change this line nor the text above.
- *
- * 2001/02/26	Minor s/suser/capable/
- *
- * 1996/10/10   Emerald changes
- *
- * 1996/05/21	Misc changes+merges+cleanups + I/O reservations
- *
- * 1996/05/20	Module support patches submitted by Brian McCauley.
- *
- * 1994/05/03	Initial attempt at Mountain support for the Mountain 7150.
- * Based on patches provided by Erik Jacobson. Still incomplete, I suppose.
- *
- * 1994/02/07	Archive changes & some cleanups by Eddy Olk.
- *
- * 1994/01/19	Speed measuring stuff moved from aperf.h to delay.h.
- *		BogoMips (tm) introduced by Linus.
- *
- * 1993/01/25	Kernel udelay. Eof fixups.
- * 
- * 1992/09/19	Some changes based on patches by Eddy Olk to support
- * 		Archive SC402/SC499R controller cards.
- *
- * 1992/05/27	First release.
- *
- * 1992/05/26	Initial version. Copyright H. H. Bergman 1992
- */
-
-/* After the legalese, now the important bits:
- * 
- * This is a driver for the Wangtek 5150 tape drive with 
- * a QIC-02 controller for ISA-PC type computers.
- * Hopefully it will work with other QIC-02 tape drives as well.
- *
- * Make sure your setup matches the configuration parameters.
- * Also, be careful to avoid IO conflicts with other devices!
- */
-
-
-/*
-#define TDEBUG
-*/
-
-#define REALLY_SLOW_IO		/* it sure is ... */
-
-#include <linux/module.h>
-
-#include <linux/config.h>
-
-#include <linux/interrupt.h>
-#include <linux/sched.h>
-#include <linux/timer.h>
-#include <linux/fs.h>
-#include <linux/kernel.h>
-#include <linux/major.h>
-#include <linux/errno.h>
-#include <linux/mtio.h>
-#include <linux/fcntl.h>
-#include <linux/delay.h>
-#include <linux/ioport.h>
-#include <linux/tpqic02.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-#include <linux/smp_lock.h>
-#include <linux/devfs_fs_kernel.h>
-#include <linux/device.h>
-
-#include <asm/dma.h>
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/uaccess.h>
-
-/* check existence of required configuration parameters */
-#if !defined(QIC02_CMD_PORT) || !defined(QIC02_TAPE_IRQ) || !defined(QIC02_TAPE_DMA)
-# error qic02_tape configuration error
-#endif
-
-
-#define TPQIC02_NAME	"tpqic02"
-
-/* Linux outb() commands have (value,port) as parameters.
- * One might expect (port,value) instead, so beware!
- */
-
-#ifdef CONFIG_QIC02_DYNCONF
-/* This holds the dynamic configuration info for the interface
- * card+drive info if runtime configuration has been selected.
- */
-
-static struct mtconfiginfo qic02_tape_dynconf =	 {
-	/* user settable */
-	0, 0, BOGUS_IRQ, 0, 0, TPQD_DEFAULT_FLAGS, 
-};
-static struct qic02_ccb qic02_tape_ccb;	/* private stuff */
-
-#else
-
-static unsigned long qic02_tape_debug = TPQD_DEFAULT_FLAGS;
-
-# if ((QIC02_TAPE_IFC!=WANGTEK) && (QIC02_TAPE_IFC!=ARCHIVE) && (QIC02_TAPE_IFC!=MOUNTAIN))
-#  error No valid interface card specified
-# endif
-#endif				/* CONFIG_QIC02_DYNCONF */
-
-static int ctlbits;	/* control reg bits for tape interface */
-
-static wait_queue_head_t qic02_tape_transfer;	/* sync rw with interrupts */
-
-static struct mtget ioctl_status;	/* current generic status */
-
-static struct tpstatus tperror;	/* last drive status */
-
-static char rcs_revision[] = "$Revision: 1.10 $";
-static char rcs_date[] = "$Date: 1997/01/26 07:13:20 $";
-
-/* Flag bits for status and outstanding requests.
- * (Could all be put in one bit-field-struct.)
- * Some variables need `volatile' because they may be modified
- * by an interrupt.
- */
-static flag status_dead = YES;	/* device is legally dead until proven alive */
-static flag status_zombie = YES;	/* it's `zombie' until irq/dma allocated */
-
-static flag status_bytes_wr = NO;	/* write FM at close or not */
-static flag status_bytes_rd = NO;	/* (rd|wr) used for rewinding */
-
-static volatile unsigned long status_cmd_pending;	/* cmd in progress */
-static flag status_expect_int = NO;	/* ready for interrupts */
-static flag status_timer_on = NO;	/* using time-out */
-static int status_error;	/* int handler may detect error */
-static flag status_eof_detected = NO;	/* end of file */
-static flag status_eom_detected = NO;	/* end of recorded media */
-static flag status_eot_detected = NO;	/* end of tape */
-static flag doing_read = NO;
-static flag doing_write = NO;
-
-static unsigned long dma_bytes_todo;
-static unsigned long dma_bytes_done;
-static volatile unsigned dma_mode;	/* !=0 also means DMA in use */
-static flag need_rewind = YES;
-
-static int current_type;
-static int extra_blocks_left = BLOCKS_BEYOND_EW;
-static struct timer_list tp_timer;
-
-static unsigned long tape_open;		/* Guard open one only */
-static DECLARE_MUTEX(tape_op);		/* Serialize tape operations */
-
-/* return_*_eof:
- *	NO:	not at EOF,
- *	YES:	tell app EOF was reached (return 0).
- *
- * return_*_eof==YES && reported_*_eof==NO  ==>
- *	return current buffer, next time(s) return EOF.
- *
- * return_*_eof==YES && reported_*_eof==YES  ==>
- *	at EOF and application knows it, so we can
- *	move on to the next file.
- *
- */
- 
-static flag return_read_eof = NO;	/* set to signal app EOF was reached */
-static flag return_write_eof = NO;
-static flag reported_read_eof = NO;	/* set when we've done that */
-static flag reported_write_eof = NO;
-
-
-/* This is for doing `mt seek <blocknr>' */
-static char seek_addr_buf[AR_SEEK_BUF_SIZE];
-
-
-/* In write mode, we have to write a File Mark after the last block written, 
- * when the tape device is closed. Tape repositioning and reading in write
- * mode is allowed as long as no actual writing has been done. After writing
- * the File Mark, repositioning and reading are allowed again.
- */
-static int mode_access;		/* access mode: READ or WRITE */
-
-static int qic02_get_resources(void);
-static void qic02_release_resources(void);
-
-/* This is a pointer to the actual kernel buffer where the interrupt routines
- * read from/write to. It is needed because the DMA channels 1 and 3 cannot
- * always access the user buffers. [The kernel buffer must reside in the
- * lower 16MBytes of system memory because of the DMA controller.] The user
- * must ensure that a large enough buffer is passed to the kernel, in order
- * to reduce tape repositioning wear and tear.
- */
-static void *buffaddr;		/* virtual address of buffer */
-
-/* This translates minor numbers to the corresponding recording format: */
-static const char *format_names[] = {
-	"not set",		/* for dumb drives unable to handle format selection */
-	"11",			/* extinct */
-	"24",
-	"120",
-	"150",
-	"300",			/* untested. */
-	"600"			/* untested. */
-};
-
-static struct class_simple *tpqic02_class;
-
-
-/* `exception_list' is needed for exception status reporting.
- * Exceptions 1..14 are defined by QIC-02 rev F.
- * The drive status is matched sequentially to each entry,
- * ignoring irrelevant bits, until a match is found. If no
- * match is found, exception number 0 is used. (That should of
- * course never happen...) The original table was based on the
- * "Exception Status Summary" in QIC-02 rev F, but some changes
- * were required to make it work with real-world drives.
- *
- * Exception 2 (CNI) is changed to also cover status 0x00e0 (mask USL),
- * Exception 4 (EOM) is changed to also cover status 0x8288 (mask EOR),
- * Exception 11 (FIL) is changed to also cover status 0x0089 (mask EOM).
- * Exception 15 (EOR) is added for seek-to-end-of-data (catch EOR),
- * Exception 16 (BOM) is added for beginning-of-media (catch BOM).
- *
- * Had to swap EXC_NDRV and EXC_NCART to ensure that extended EXC_NCART
- * (because of the incorrect Wangtek status code) doesn't catch the
- * EXC_NDRV first.
- */
-static struct exception_list_type {
-	unsigned short mask, code;
-	const char *msg;
-	/* EXC_nr attribute should match with tpqic02.h */
-} exception_list[] = {
-	{ 0, 0, "Unknown exception status code", /* extra: 0 */ },
-	{ ~(0), TP_ST0 | TP_CNI | TP_USL | TP_WRP, "Drive not online" /* 1 */ }, /* Drive presence goes before cartridge presence. */
-	{ ~(TP_WRP | TP_USL), TP_ST0 | TP_CNI,
-		    /* My Wangtek 5150EQ sometimes reports a status code
-		     * of 0x00e0, which is not a valid exception code, but
-		     * I think it should be recognized as "NO CARTRIDGE".
-		     */
-			"Cartridge not in place" /* 2 */ },
-	{ (unsigned short) ~(TP_ST1 | TP_BOM), (TP_ST0 | TP_WRP), "Write protected cartridge" /* 3 */ },
-	{ (unsigned short) ~(TP_ST1 | TP_EOR), (TP_ST0 | TP_EOM), "End of media" /* 4 */ },
-	{ ~TP_WRP, TP_ST0 | TP_UDA | TP_ST1 | TP_BOM, "Read or Write abort. Rewind tape." /* 5 */ },
-	{ ~TP_WRP, TP_ST0 | TP_UDA, "Read error. Bad block transferred." /* 6 */ },
-	{ ~TP_WRP, TP_ST0 | TP_UDA | TP_BNL, "Read error. Filler block transferred." /* 7 */ },
-	{ ~TP_WRP, TP_ST0 | TP_UDA | TP_BNL | TP_ST1 | TP_NDT, "Read error. No data detected." /* 8 */ },
-	{ ~TP_WRP, TP_ST0 | TP_EOM | TP_UDA | TP_BNL | TP_ST1 | TP_NDT, "Read error. No data detected. EOM." /* 9 */ },
-	{ ~(TP_WRP | TP_MBD | TP_PAR | TP_EOR), TP_ST0 | TP_UDA | TP_BNL | TP_ST1 | TP_NDT | TP_BOM, "Read error. No data detected. BOM." /* 10 */ },
-	{ ~(TP_WRP | TP_EOM), TP_ST0 | TP_FIL,
-		    /* Status 0x0089 (EOM & FM) is viewed as an FM,
-		     * because it can only happen during a read.
-		     * EOM is checked separately for an FM condition.
-		     */
-			"File mark detected" /* 11 */ },
-	{ ~(TP_ST0 | TP_CNI | TP_USL | TP_WRP | TP_BOM), TP_ST1 | TP_ILL, "Illegal command" /* 12 */ },
-	{ ~(TP_ST0 | TP_CNI | TP_USL | TP_WRP | TP_BOM), TP_ST1 | TP_POR, "Reset occurred" /* 13 */ },
-	{ ~TP_WRP, TP_ST0 | TP_FIL | TP_MBD,	/* NOTE: ST1 not set! */ "Marginal block detected" /* 14 */ },
-	{ ~(TP_ST0 | TP_WRP | TP_EOM | TP_UDA | TP_BNL | TP_FIL |  TP_NDT), TP_ST1 | TP_EOR,	/********** Is the extra TP_NDT really needed Eddy? **********/ "End of recorded media" /* extra: 15 */ },
-	    /* 15 is returned when SEEKEOD completes successfully */
-	{ ~(TP_WRP | TP_ST0), TP_ST1 | TP_BOM, "Beginning of media" /* extra: 16 */ }
-};
-
-#define NR_OF_EXC	(sizeof(exception_list)/sizeof(struct exception_list_type))
-
-/* Compare expected struct size and actual struct size. This
- * is useful to catch programs compiled with old #includes.
- */
-#define CHECK_IOC_SIZE(structure) \
-	if (_IOC_SIZE(iocmd) != sizeof(struct structure)) { \
-		tpqputs(TPQD_ALWAYS, "sizeof(struct " #structure \
-			") does not match!"); \
-		return -EFAULT; \
-	} \
-
-static void tpqputs(unsigned long flags, const char *s)
-{
-	if ((flags & TPQD_ALWAYS) || (flags & QIC02_TAPE_DEBUG))
-		printk(TPQIC02_NAME ": %s\n", s);
-}				/* tpqputs */
-
-
-/* Init control register bits on interface card.
- * For Archive, interrupts must be enabled explicitly.
- * Wangtek interface card requires ONLINE to be set, Archive SC402/SC499R
- * cards keep it active all the time.
- */
-
-static void ifc_init(void)
-{
-	if (QIC02_TAPE_IFC == WANGTEK) {	/* || (QIC02_TAPE_IFC == EVEREX) */
-		ctlbits = WT_CTL_ONLINE;	/* online */
-		outb_p(ctlbits, QIC02_CTL_PORT);
-	} else if (QIC02_TAPE_IFC == ARCHIVE) {
-		ctlbits = 0;	/* no interrupts yet */
-		outb_p(ctlbits, QIC02_CTL_PORT);
-		outb_p(0, AR_RESET_DMA_PORT);	/* dummy write to reset DMA */
-	} else {		/* MOUNTAIN */
-
-		ctlbits = MTN_CTL_ONLINE;	/* online, and logic enabled */
-		outb_p(ctlbits, QIC02_CTL_PORT);
-	}
-}				/* ifc_init */
-
-
-static void report_qic_exception(unsigned n)
-{
-	if (n >= NR_OF_EXC) {
-		tpqputs(TPQD_ALWAYS, "Oops -- report_qic_exception");
-		n = 0;
-	}
-	if (TPQDBG(SENSE_TEXT) || n == 0)
-		printk(TPQIC02_NAME ": sense: %s\n", exception_list[n].msg);
-}				/* report_qic_exception */
-
-
-/* Try to map the drive-exception bits `s' to a predefined "exception number",
- * by comparing the significant exception bits for each entry in the
- * exception table (`exception_list[]').
- * It is assumed that s!=0.
- */
-static int decode_qic_exception_nr(unsigned s)
-{
-	int i;
-
-	for (i = 1; i < NR_OF_EXC; i++) {
-		if ((s & exception_list[i].mask) == exception_list[i].code) {
-			return i;
-		}
-	}
-	printk(TPQIC02_NAME ": decode_qic_exception_nr: exception(%x) not recognized\n", s);
-	return 0;
-}				/* decode_qic_exception_nr */
-
-
-
-/* Perform appropriate action for certain exceptions.
- * should return a value to indicate stop/continue (in case of bad blocks)
- */
-static void handle_qic_exception(int exnr, int exbits)
-{
-	if (exnr == EXC_NCART) {
-		/* Cartridge was changed. Redo sense().
-		 * EXC_NCART should be handled in open().
-		 * It is not permitted to remove the tape while
-		 * the tape driver has open files. 
-		 */
-		need_rewind = YES;
-		status_eof_detected = NO;
-		status_eom_detected = NO;
-	} else if (exnr == EXC_XFILLER) {
-		tpqputs(TPQD_ALWAYS,
-			"[Bad block -- filler data transferred.]");
-	} else if (exnr == EXC_XBAD) {
-		tpqputs(TPQD_ALWAYS, "[CRC failed!]");
-	} else if (exnr == EXC_MARGINAL) {
-		/* A marginal block behaves much like a FM.
-		 * User may continue reading, if desired.
-		 */
-		tpqputs(TPQD_ALWAYS, "[Marginal block]");
-		doing_read = NO;
-	} else if (exnr == EXC_FM) {
-		doing_read = NO;
-	}
-}				/* handle_qic_exception */
-
-
-static inline int is_exception(void)
-{
-	return (inb(QIC02_STAT_PORT) & QIC02_STAT_EXCEPTION) == 0;
-}				/* is_exception */
-
-
-/* Reset the tape drive and controller.
- * When reset fails, it marks  the drive as dead and all
- * requests (except reset) are to be ignored (ENXIO).
- */
-static int tape_reset(int verbose)
-{
-	ifc_init();		/* reset interface card */
-
-	/* assert reset */
-	if (QIC02_TAPE_IFC == MOUNTAIN) {
-		outb_p(ctlbits & ~MTN_QIC02_CTL_RESET_NOT, QIC02_CTL_PORT);
-	} else {		/* WANGTEK, ARCHIVE */
-
-		outb_p(ctlbits | QIC02_CTL_RESET, QIC02_CTL_PORT);
-	}
-
-	/* Next, we need to wait >=25 usec. */
-	udelay(30);
-
-	/* after reset, we will be at BOT (modulo an automatic rewind) */
-	status_eof_detected = NO;
-	status_eom_detected = NO;
-	status_cmd_pending = 0;
-	need_rewind = YES;
-	doing_read = doing_write = NO;
-	ioctl_status.mt_fileno = ioctl_status.mt_blkno = 0;
-
-	/* de-assert reset */
-	if (QIC02_TAPE_IFC == MOUNTAIN) {
-		outb_p(ctlbits | MTN_QIC02_CTL_RESET_NOT, QIC02_CTL_PORT);
-	} else {
-		outb_p(ctlbits & ~QIC02_CTL_RESET, QIC02_CTL_PORT);
-	}
-
-	/* KLUDGE FOR G++ BUG */
-	{
-		int stat = inb_p(QIC02_STAT_PORT);
-		status_dead = ((stat & QIC02_STAT_RESETMASK) != QIC02_STAT_RESETVAL);
-	}
-	/* if successful, inb(STAT) returned RESETVAL */
-	if (status_dead == YES)
-		printk(TPQIC02_NAME ": reset failed!\n");
-	else if (verbose)
-		printk(TPQIC02_NAME ": reset successful\n");
-
-	return (status_dead == YES) ? TE_DEAD : TE_OK;
-}				/* tape_reset */
-
-
-
-/* Notify tape drive of a new command. It only waits for the
- * command to be accepted, not for the actual command to complete.
- *
- * Before calling this routine, QIC02_CMD_PORT must have been loaded
- * with the command to be executed.
- * After this routine, the exception bit must be checked.
- * This routine is also used by rdstatus(), so in that case, any exception
- * must be ignored (`ignore_ex' flag).
- */
-static int notify_cmd(char cmd, short ignore_ex)
-{
-	int i;
-
-	outb_p(cmd, QIC02_CMD_PORT);	/* output the command */
-
-	/* wait 1 usec before asserting /REQUEST */
-	udelay(1);
-
-	if ((!ignore_ex) && is_exception()) {
-		tpqputs(TPQD_ALWAYS, "*** exception detected in notify_cmd");
-		/** force a reset here **/
-		if (tape_reset(1) == TE_DEAD)
-			return TE_DEAD;
-		if (is_exception()) {
-			tpqputs(TPQD_ALWAYS, "exception persists after reset.");
-			tpqputs(TPQD_ALWAYS, " ^ exception ignored.");
-		}
-	}
-
-	outb_p(ctlbits | QIC02_CTL_REQUEST, QIC02_CTL_PORT);	/* set request bit */
-	i = TAPE_NOTIFY_TIMEOUT;
-	/* The specs say this takes about 500 usec, but there is no upper limit!
-	 * If the drive were busy retensioning or something like that,
-	 * it could be *much* longer!
-	 */
-	while ((inb_p(QIC02_STAT_PORT) & QIC02_STAT_READY) && (--i > 0))
-		udelay(1);
-	/* wait for ready */
-	if (i == 0) {
-		tpqputs(TPQD_ALWAYS, "timed out waiting for ready in notify_cmd");
-		status_dead = YES;
-		return TE_TIM;
-	}
-
-	outb_p(ctlbits & ~QIC02_CTL_REQUEST, QIC02_CTL_PORT);	/* reset request bit */
-	i = TAPE_NOTIFY_TIMEOUT;
-	/* according to the specs this one should never time-out */
-	while (((inb_p(QIC02_STAT_PORT) & QIC02_STAT_READY) == 0) && (--i > 0))
-		udelay(1);
-	/* wait for not ready */
-	if (i == 0) {
-		tpqputs(TPQD_ALWAYS, "timed out waiting for !ready in notify_cmd");
-		status_dead = YES;
-		return TE_TIM;
-	}
-	/* command accepted */
-	return TE_OK;
-}				/* notify_cmd */
-
-
-
-/* Wait for a command to complete, with timeout */
-static int wait_for_ready(time_t timeout)
-{
-	int stat;
-	unsigned long spin_t;
-
-	/* Wait for ready or exception, without driving the loadavg up too much.
-	 * In most cases, the tape drive already has READY asserted,
-	 * so optimize for that case.
-	 *
-	 * First, busy wait a few usec:
-	 */
-	spin_t = 50;
-	while (((stat = inb_p(QIC02_STAT_PORT) & QIC02_STAT_MASK) == QIC02_STAT_MASK) && (--spin_t > 0))
-		udelay(1);
-	if ((stat & QIC02_STAT_READY) == 0)
-		return TE_OK;	/* covers 99.99% of all calls */
-
-	/* Then use schedule() a few times */
-	spin_t = 3;		/* max 0.03 sec busy waiting */
-	if (spin_t > timeout)
-		spin_t = timeout;
-	timeout -= spin_t;
-	spin_t += jiffies;
-
-	/* FIXME...*/
-	while (((stat = inb_p(QIC02_STAT_PORT) & QIC02_STAT_MASK) == QIC02_STAT_MASK)  && time_before(jiffies, spin_t))
-	{
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		schedule_timeout(1);	/* don't waste all the CPU time */
-	}
-	if ((stat & QIC02_STAT_READY) == 0)
-		return TE_OK;
-
-	/* If we reach this point, we probably need to wait much longer, or
-	 * an exception occurred. Either case is not very time-critical.
-	 * Check the status port only a few times every second.
-	 * A interval of less than 0.10 sec will not be noticed by the user,
-	 * more than 0.40 sec may give noticeable delays.
-	 */
-	spin_t += timeout;
-	TPQDEB({printk("wait_for_ready: additional timeout: %d\n", spin_t);})
-
-	    /* not ready and no exception && timeout not expired yet */
-	while (((stat = inb_p(QIC02_STAT_PORT) & QIC02_STAT_MASK) == QIC02_STAT_MASK) && time_before(jiffies, spin_t)) {
-		/* be `nice` to other processes on long operations... */
-		/* nap 0.30 sec between checks, */
-		/* but could be woken up earlier by signals... */
-		msleep_interruptible(300);
-	}
-
-	/* don't use jiffies for this test because it may have changed by now */
-	if ((stat & QIC02_STAT_MASK) == QIC02_STAT_MASK) {
-		tpqputs(TPQD_ALWAYS, "wait_for_ready() timed out");
-		return TE_TIM;
-	}
-
-	if ((stat & QIC02_STAT_EXCEPTION) == 0) {
-		tpqputs(TPQD_ALWAYS, "exception detected after waiting_for_ready");
-		return TE_EX;
-	} else {
-		return TE_OK;
-	}
-}				/* wait_for_ready */
-
-
-
-/* Send some data to the drive */
-static int send_qic02_data(char sb[], unsigned size, int ignore_ex)
-{
-	int i, stat;
-
-	for (i = 0; i < size; i++) {
-		stat = wait_for_ready(TIM_S);
-		if (stat != TE_OK)
-			return stat;
-
-		stat = notify_cmd(sb[i], ignore_ex);
-		if (stat != TE_OK)
-			return stat;
-	}
-	return TE_OK;
-
-}				/* send_qic02_data */
-
-
-/* Send a QIC-02 command (`cmd') to the tape drive, with
- * a time-out (`timeout').
- * This one is also used by tp_sense(), so we must have
- * a flag to disable exception checking (`ignore_ex'). 
- *
- * On entry, the controller is supposed to be READY.
- */
-static int send_qic02_cmd(int cmd, time_t timeout, int ignore_ex)
-{
-	int stat;
-
-	stat = inb_p(QIC02_STAT_PORT);
-	if ((stat & QIC02_STAT_EXCEPTION) == 0) {	/* if exception */
-		tpqputs(TPQD_ALWAYS, "send_qic02_cmd: Exception!");
-		return TE_EX;
-	}
-	if (stat & QIC02_STAT_READY) {	/* if not ready */
-		tpqputs(TPQD_ALWAYS, "send_qic02_cmd: not Ready!");
-		return TE_ERR;
-	}
-
-	/* assert(ready & !exception) */
-
-	/* Remember current command for later re-use with dma transfers.
-	 * (For reading/writing multiple blocks.)
-	 */
-	status_cmd_pending = cmd;
-
-	stat = notify_cmd(cmd, ignore_ex);	/* tell drive new command was loaded, */
-	/* inherit exception check. */
-	if (TP_HAVE_SEEK && (cmd == AR_QCMDV_SEEK_BLK)) {
-		/* This one needs to send 3 more bytes, MSB first */
-		stat = send_qic02_data(seek_addr_buf, sizeof(seek_addr_buf), ignore_ex);
-	}
-
-	if (stat != TE_OK) {
-		tpqputs(TPQD_ALWAYS, "send_qic02_cmd failed");
-	}
-	return stat;
-}				/* send_qic02_cmd */
-
-
-
-/* Get drive status. Assume drive is ready or has exception set.
- * (or will be in <1000 usec.)
- * Extra parameters added because of 'Read Extended Status 3' command.
- */
-static int rdstatus(char *stp, unsigned size, char qcmd)
-{
-	int s, n;
-	char *q = stp;
-
-	/* Try to busy-wait a few (700) usec, after that de-schedule.
-	 *
-	 * The problem is, if we don't de-schedule, performance will
-	 * drop to zero when the drive is not responding and if we
-	 * de-schedule immediately, we waste a lot of time because a
-	 * task switch is much longer than we usually have to wait here.
-	 */
-	n = 700;
-	while ((n > 0) && ((inb_p(QIC02_STAT_PORT) & QIC02_STAT_MASK) == QIC02_STAT_MASK))
-	{
-		udelay(1);
-		n--;		/* wait for ready or exception or timeout */
-	}
-	if (n == 0) {
-		/* n (above) should be chosen such that on your machine
-		 * you rarely ever see the message below, and it should
-		 * be small enough to give reasonable response time.]
-		 */
-	 	/* FIXME */
-		tpqputs(TPQD_ALWAYS, "waiting looong in rdstatus() -- drive dead?");
-		while ((inb_p(QIC02_STAT_PORT) & QIC02_STAT_MASK) == QIC02_STAT_MASK)
-		{
-			set_current_state(TASK_UNINTERRUPTIBLE);
-			schedule_timeout(1);
-		}
-		tpqputs(TPQD_ALWAYS, "finished waiting in rdstatus()");
-	}
-
-	(void) notify_cmd(qcmd, 1);	/* send read status command */
-	/* ignore return code -- should always be ok, STAT may contain 
-	 * exception flag from previous exception which we are trying to clear.
-	 */
-
-	if (TP_DIAGS(current_type))
-		printk(TPQIC02_NAME ": reading status bytes: ");
-
-	for (q = stp; q < stp + size; q++) {
-		do
-			s = inb_p(QIC02_STAT_PORT);
-		while ((s & QIC02_STAT_MASK) == QIC02_STAT_MASK);	/* wait for ready or exception */
-
-		if ((s & QIC02_STAT_EXCEPTION) == 0) {	/* if exception */
-			tpqputs(TPQD_ALWAYS, "rdstatus: exception error");
-			ioctl_status.mt_erreg = 0;	/* dunno... */
-			return TE_NS;	/* error, shouldn't happen... */
-		}
-
-		*q = inb_p(QIC02_DATA_PORT);	/* read status byte */
-
-		if (TP_DIAGS(current_type))
-			printk("[%1zd]=0x%x  ", q - stp, (unsigned) (*q) & 0xff);
-
-		outb_p(ctlbits | QIC02_CTL_REQUEST, QIC02_CTL_PORT);	/* set request */
-
-		while ((inb_p(QIC02_STAT_PORT) & QIC02_STAT_READY) == 0)
-			cpu_relax();	/* wait for not ready */
-
-		udelay(22);	/* delay >20 usec */
-
-		outb_p(ctlbits & ~QIC02_CTL_REQUEST, QIC02_CTL_PORT);	/* un-set request */
-
-	}
-
-	/* Specs say we should wait for READY here.
-	 * My drive doesn't seem to need it here yet, but others do?
-	 */
-	while (inb_p(QIC02_STAT_PORT) & QIC02_STAT_READY)
-		cpu_relax();
-	/* wait for ready */
-
-	if (TP_DIAGS(current_type))
-		printk("\n");
-
-	return TE_OK;
-}				/* rdstatus */
-
-
-
-/* Get standard status (6 bytes).
- * The `.dec' and `.urc' fields are in MSB-first byte-order,
- * so they have to be swapped first.
- */
-static int get_status(volatile struct tpstatus *stp)
-{
-	int stat = rdstatus((char *) stp, TPSTATSIZE, QCMD_RD_STAT);
-	stp->dec = be16_to_cpu(stp->dec);
-	stp->urc = be16_to_cpu(stp->urc);
-	return stat;
-}				/* get_status */
-
-
-#if 0
-/* This fails for my Wangtek drive */
-/* get "Extended Status Register 3" (64 bytes)
- *
- * If the meaning of the returned bytes were known, the MT_TYPE
- * identifier could be used to decode them, since they are
- * "vendor unique". :-(
- */
-static int get_ext_status3(void)
-{
-	char vus[64];		/* vendor unique status */
-	int stat, i;
-
-	tpqputs(TPQD_ALWAYS, "Attempting to read Extended Status 3...");
-	stat = rdstatus(vus, sizeof(vus), QCMD_RD_STAT_X3);
-	if (stat != TE_OK)
-		return stat;
-
-	tpqputs(TPQD_ALWAYS, "Returned status bytes:");
-	for (i = 0; i < sizeof(vus); i++) {
-		if (i % 8 == 0)
-			printk("\n" TPQIC02_NAME ": %2d:");
-		printk(" %2x", vus[i] & 0xff);
-	}
-	printk("\n");
-
-	return TE_OK;
-}				/* get_ext_status3 */
-#endif
-
-
-/* Read drive status and set generic status too.
- * NOTE: Once we do a tp_sense(), read/write transfers are killed.
- */
-static int tp_sense(int ignore)
-{
-	unsigned err = 0, exnr = 0, gs = 0;
-	static void finish_rw(int cmd);
-
-	if (TPQDBG(SENSE_TEXT))
-		printk(TPQIC02_NAME ": tp_sense(ignore=0x%x) enter\n", ignore);
-
-	/* sense() is not allowed during a read or write cycle */
-	if (doing_write == YES)
-		tpqputs(TPQD_ALWAYS, "Warning: File Mark inserted because of sense() request");
-	/* The extra test is to avoid calling finish_rw during booting */
-	if ((doing_read != NO) || (doing_write != NO))
-		finish_rw(QCMD_RD_STAT);
-
-	if (get_status(&tperror) != TE_OK) {
-		tpqputs(TPQD_ALWAYS, "tp_sense: could not read tape drive status");
-		return TE_ERR;
-	}
-
-	err = tperror.exs;	/* get exception status bits */
-	if (err & (TP_ST0 | TP_ST1))
-		printk(TPQIC02_NAME ": tp_sense: status: %x, error count: %d, underruns: %d\n",
-		       tperror.exs, tperror.dec, tperror.urc);
-	else if ((tperror.dec != 0) || (tperror.urc != 0) || TPQDBG(SENSE_CNTS))
-		printk(TPQIC02_NAME ": tp_sense: no hard errors, soft error count: %d, underruns: %d\n", tperror.dec, tperror.urc);
-
-	/* Set generic status. HP-UX defines these, but some extra would 
-	 * be useful. Problem is to remain compatible. [Do we want to be
-	 * compatible??]
-	 */
-	if (err & TP_ST0) {
-		if (err & TP_CNI)	/* no cartridge */
-			gs |= GMT_DR_OPEN(-1);
-		if (status_dead == NO)
-			gs |= GMT_ONLINE(-1);	/* always online */
-		if (err & TP_USL)	/* not online */
-			gs &= ~GMT_ONLINE(-1);
-		if (err & TP_WRP)
-			gs |= GMT_WR_PROT(-1);
-		if (err & TP_EOM) {	/* end of media */
-			gs |= GMT_EOT(-1);	/* not sure this is correct for writes */
-			status_eom_detected = YES;
-			/* I don't know whether drive always reports EOF at or before EOM. */
-			status_eof_detected = YES;
-		}
-		/** if (err & TP_UDA) "Unrecoverable data error" **/
-		/** if (err & TP_BNL) "Bad block not located" **/
-		if (err & TP_FIL) {
-			gs |= GMT_EOF(-1);
-			status_eof_detected = YES;
-		}
-	}
-	if (err & TP_ST1) {
-		/** if (err & TP_ILL) "Illegal command" **/
-		/** if (err & TP_NDT) "No data detected" **/
-		/** if (err & TP_MBD) "Marginal block detected" **/
-		if (err & TP_BOM)
-			gs |= GMT_BOT(-1);	/* beginning of tape */
-	}
-	ioctl_status.mt_gstat = gs;
-	ioctl_status.mt_dsreg = tperror.exs;	/* "drive status" */
-	ioctl_status.mt_erreg = tperror.dec;	/* "sense key error" */
-
-	if (err & (TP_ST0 | TP_ST1)) {
-		/* My Wangtek occasionally reports `status' 1212 which should be ignored. */
-		exnr = decode_qic_exception_nr(err);
-		handle_qic_exception(exnr, err);	/* update driver state wrt drive status */
-		report_qic_exception(exnr);
-	}
-	err &= ~ignore;		/* mask unwanted errors -- not the correct way, use exception nrs?? */
-	if (((err & TP_ST0) && (err & REPORT_ERR0)) ||
-	    ((err & TP_ST1) && (err & REPORT_ERR1)))
-		return TE_ERR;
-	return TE_OK;
-}				/* tp_sense */
-
-
-
-/* Wait for a wind or rewind operation to finish or
- * to time-out. (May take very long).
- */
-static int wait_for_rewind(time_t timeout)
-{
-	int stat;
-
-	stat = inb(QIC02_STAT_PORT) & QIC02_STAT_MASK;
-	if (TPQDBG(REWIND))
-		printk(TPQIC02_NAME ": Waiting for (re-)wind to finish: stat=0x%x\n", stat);
-
-	stat = wait_for_ready(timeout);
-
-	if (stat != TE_OK) {
-		tpqputs(TPQD_ALWAYS, "(re-) winding failed\n");
-	}
-	return stat;
-}				/* wait_for_rewind */
-
-
-
-/* Perform a full QIC02 command, and wait for completion,
- * check status when done. Complain about exceptions.
- *
- * This function should return an OS error code when
- * something goes wrong, 0 otherwise.
- */
-static int ll_do_qic_cmd(int cmd, time_t timeout)
-{
-	int stat;
-
-	if (status_dead == YES) {
-		tpqputs(TPQD_ALWAYS, "Drive is dead. Do a `mt reset`.");
-		return -ENXIO;	/* User should do an MTRESET. */
-	}
-
-	stat = wait_for_ready(timeout);	/* wait for ready or exception */
-	if (stat == TE_EX) {
-		if (tp_sense(TP_WRP | TP_BOM | TP_EOM | TP_FIL) != TE_OK)
-			return -EIO;
-		/* else nothing to worry about, I hope */
-		stat = TE_OK;
-	}
-	if (stat != TE_OK) {
-		printk(TPQIC02_NAME ": ll_do_qic_cmd(%x, %ld) failed\n", cmd, (long) timeout);
-		return -EIO;
-	}
-#ifdef OBSOLETE
-	/* wait for ready since it may not be active immediately after reading status */
-	while ((inb_p(QIC02_STAT_PORT) & QIC02_STAT_READY) != 0)
-		cpu_relax();
-#endif
-
-	stat = send_qic02_cmd(cmd, timeout, 0);	/* (checks for exceptions) */
-
-	if (cmd == QCMD_RD_FM) {
-		status_eof_detected = NO;
-		ioctl_status.mt_fileno++;
-		/* Should update block count as well, but can't.
-		 * Can do a `read address' for some drives, when MTNOP is done.
-		 */
-	} else if (cmd == QCMD_WRT_FM) {
-		status_eof_detected = NO;
-		ioctl_status.mt_fileno++;
-	} else if ((cmd == QCMD_REWIND) || (cmd == QCMD_ERASE)
-		   || (cmd == QCMD_RETEN)) {
-		status_eof_detected = NO;
-		status_eom_detected = NO;
-		status_eot_detected = NO;
-		need_rewind = NO;
-		ioctl_status.mt_fileno = ioctl_status.mt_blkno = 0;
-		extra_blocks_left = BLOCKS_BEYOND_EW;
-		return_write_eof = NO;
-		return_read_eof = NO;
-		reported_read_eof = NO;
-		reported_write_eof = NO;
-	}
-	/* sense() will set eof/eom as required */
-	if (stat == TE_EX) {
-		if (tp_sense(TP_WRP | TP_BOM | TP_EOM | TP_FIL) != TE_OK) {
-			printk(TPQIC02_NAME ": Exception persist in ll_do_qic_cmd[1](%x, %ld)", cmd, (long) timeout);
-			status_dead = YES;
-			return -ENXIO;
-			/* if rdstatus fails too, we're in trouble */
-		}
-	} else if (stat != TE_OK) {
-		printk(TPQIC02_NAME ": ll_do_qic_cmd: send_qic02_cmd failed, stat = 0x%x\n", stat);
-		return -EIO;	/*** -EIO is probably not always appropriate */
-	}
-
-	if (timeout == TIM_R)
-		stat = wait_for_rewind(timeout);
-	else
-		stat = wait_for_ready(timeout);
-
-	if (stat == TE_EX) {
-		if (tp_sense((cmd == QCMD_SEEK_EOD ?		/*****************************/
-			      TP_EOR | TP_NDT | TP_UDA | TP_BNL | TP_WRP |
-			      TP_BOM | TP_EOM | TP_FIL : TP_WRP | TP_BOM |
-			      TP_EOM | TP_FIL)) != TE_OK) {
-			printk(TPQIC02_NAME ": Exception persist in ll_do_qic_cmd[2](%x, %ld)\n", cmd, (long) timeout);
-			if (cmd != QCMD_RD_FM)
-				status_dead = YES;
-			return -ENXIO;
-			/* if rdstatus fails too, we're in trouble */
-		}
-	} else if (stat != TE_OK) {
-		printk(TPQIC02_NAME ": ll_do_qic_cmd %x: wait failed, stat == 0x%x\n", cmd, stat);
-		return -EIO;
-	}
-	return 0;
-}				/* ll_do_qic_cmd */
-
-
-/* 
- * Problem: What to do when the user cancels a read/write operation
- * in-progress?
- *
- * "Deactivating ONLINE during a READ also causes the"
- * "tape to be rewound to BOT." Ditto for WRITEs, except
- * a FM is written first. "The host may alternatively terminate
- * the READ/WRITE command by issuing a RFM/WFM command."
- *
- * For READs:
- * Neither option will leave the tape positioned where it was.
- * Another (better?) solution is to terminate the READ by two
- * subsequent sense() operations, the first to stop the current
- * READ cycle, the second to clear the `Illegal command' exception,
- * because the QIC-02 specs didn't anticipate this. This is
- * delayed until actually needed, so a tar listing can be aborted
- * by the user and continued later.
- * If anybody has a better solution, let me know! [Also, let me
- * know if your drive (mine is a Wangtek5150EQ) does not accept
- * this sequence for canceling the read-cycle.]
- *
- * For WRITEs it's simple: Just do a WRITE_FM, leaving the tape
- * positioned after the FM.
- */
-
-static void terminate_read(int cmd)
-{
-	if (doing_read != YES)
-		return;
-		
-	doing_read = NO;
-	
-	if (cmd == QCMD_RD_FM)
-		return;
-		
-	/* if the command is a RFM, there is no need to do this
-	 * because a RFM will legally terminate the read-cycle.
-	 */
-	tpqputs(TPQD_ALWAYS, "terminating pending read-cycle");
-
-	/* I'm not too sure about this part  -- hhb */
-	if (QIC02_TAPE_IFC == MOUNTAIN) {
-		/* Mountain reference says can terminate by de-asserting online */
-		ctlbits &= ~MTN_QIC02_CTL_ONLINE;
-	}
-
-	if (tp_sense(TP_FIL | TP_EOM | TP_WRP) != TE_OK) {
-		tpqputs(TPQD_ALWAYS, "finish_rw[read1]: ignore the 2 lines above");
-		if (is_exception()) {
-			if (tp_sense(TP_ILL | TP_FIL | TP_EOM | TP_WRP) != TE_OK)
-				tpqputs(TPQD_ALWAYS,"finish_rw[read2]: read cycle error");
-		}
-	}
-}				/* terminate_read */
-
-
-static void terminate_write(int cmd)
-{
-	int stat;
-
-	if (doing_write != YES)
-		return;
-
-	doing_write = NO;
-	/* Finish writing by appending a FileMark at the end. */
-	if (cmd != QCMD_WRT_FM) {
-		/* finish off write cycle */
-		stat = ll_do_qic_cmd(QCMD_WRT_FM, TIM_M);
-		if (stat != TE_OK)
-			tpqputs(TPQD_ALWAYS, "Couldn't finish write cycle properly");
-		(void) tp_sense(0);
-	}
-	/* If there is an EOF token waiting to be returned to
-	 * the (writing) application, discard it now.
-	 * We could be at EOT, so don't reset return_write_eof.
-	 */
-	reported_write_eof = YES;
-}				/* terminate_write */
-
-
-/* terminate read or write cycle because of command `cmd' */
-static void finish_rw(int cmd)
-{
-	if (wait_for_ready(TIM_S) != TE_OK) {
-		tpqputs(TPQD_ALWAYS, "error: drive not ready in finish_rw() !");
-		return;
-	}
-	terminate_read(cmd);
-	terminate_write(cmd);
-}				/* finish_rw */
-
-
-/* Perform a QIC command through ll_do_qic_cmd().
- * If necessary, rewind the tape first.
- * Return an OS error code if something goes wrong, 0 if all is well.
- */
-static int do_qic_cmd(int cmd, time_t timeout)
-{
-	int stat;
-
-
-	finish_rw(cmd);
-
-	if (need_rewind) {
-		tpqputs(TPQD_REWIND, "Rewinding tape...");
-		stat = ll_do_qic_cmd(QCMD_REWIND, TIM_R);
-		if (stat != 0) {
-			printk(TPQIC02_NAME ": rewind failed in do_qic_cmd(). stat=0x%2x", stat);
-			return stat;
-		}
-		need_rewind = NO;
-		if (cmd == QCMD_REWIND)	/* don't wind beyond BOT ;-) */
-			return 0;
-	}
-
-	return ll_do_qic_cmd(cmd, timeout);
-}				/* do_qic_cmd */
-
-
-/* Not all ioctls are supported for all drives. Some rely on
- * optional QIC-02 commands. Check tpqic02.h for configuration.
- * Some of these commands may require ONLINE to be active.
- */
-static int do_ioctl_cmd(int cmd)
-{
-	int stat;
-
-	/* It is not permitted to read or wind the tape after bytes have
-	 * been written. It is not permitted to write the tape while in
-	 * read mode.
-	 * We try to be kind and allow reading again after writing a FM...
-	 */
-
-	switch (cmd) {
-	case MTRESET:
-		/* reset verbose */
-		return (tape_reset(1) == TE_OK) ? 0 : -EIO;
-
-	case MTFSF:
-		tpqputs(TPQD_IOCTLS, "MTFSF forward searching filemark");
-		if ((mode_access == WRITE) && status_bytes_wr)
-			return -EACCES;
-		return do_qic_cmd(QCMD_RD_FM, TIM_F);
-
-	case MTBSF:
-		if (TP_HAVE_BSF) {
-			tpqputs(TPQD_IOCTLS, "MTBSF backward searching filemark -- optional command");
-			if ((mode_access == WRITE) && status_bytes_wr)
-				return -EACCES;
-			stat = do_qic_cmd(QCMD_RD_FM_BCK, TIM_F);
-		} else {
-			stat = -ENXIO;
-		}
-		status_eom_detected = status_eof_detected = NO;
-		return stat;
-
-	case MTFSR:
-		if (TP_HAVE_FSR) {	/* This is an optional QIC-02 command */
-			tpqputs(TPQD_IOCTLS, "MTFSR forward space record");
-			if ((mode_access == WRITE) && status_bytes_wr)
-				return -EACCES;
-			stat = do_qic_cmd(QCMD_SPACE_FWD, TIM_F);
-		} else {
-				/**** fake it by doing a read data block command? ******/
-			tpqputs(TPQD_IOCTLS, "MTFSR not supported");
-			stat = -ENXIO;
-		}
-		return stat;
-
-	case MTBSR:
-		if (TP_HAVE_BSR) {	/* This is an optional QIC-02 command */
-			/* we need this for appending files with GNU tar!! */
-			tpqputs(TPQD_IOCTLS, "MTFSR backward space record");
-			if ((mode_access == WRITE) && status_bytes_wr)
-				return -EACCES;
-			stat = do_qic_cmd(QCMD_SPACE_BCK, TIM_F);
-		} else {
-			tpqputs(TPQD_IOCTLS, "MTBSR not supported");
-			stat = -ENXIO;
-		}
-		status_eom_detected = status_eof_detected = NO;
-		return stat;
-
-	case MTWEOF:
-		tpqputs(TPQD_IOCTLS, "MTWEOF write eof mark");
-		/* Plain GNU mt(1) 2.2 uses read-only mode for writing FM. :-( */
-		if (mode_access == READ)
-			return -EACCES;
-
-		/* allow tape movement after writing FM */
-		status_bytes_rd = status_bytes_wr;	/* Kludge-O-Matic */
-		status_bytes_wr = NO;
-		return do_qic_cmd(QCMD_WRT_FM, TIM_M);
-		/* not sure what to do with status_bytes when WFM should fail */
-
-	case MTREW:
-		tpqputs(TPQD_IOCTLS, "MTREW rewinding tape");
-		if ((mode_access == WRITE) && status_bytes_wr)
-			return -EACCES;
-		status_eom_detected = status_eof_detected = NO;
-		return do_qic_cmd(QCMD_REWIND, TIM_R);
-
-	case MTOFFL:
-		tpqputs(TPQD_IOCTLS, "MTOFFL rewinding & going offline");
-		/* Doing a drive select will clear (unlock) the current drive.
-		 * But that requires support for multiple drives and locking.
-		 */
-		if ((mode_access == WRITE) && status_bytes_wr)
-			return -EACCES;
-		status_eom_detected = status_eof_detected = NO;
-			/**** do rewind depending on minor bits??? ***/
-		stat = do_qic_cmd(QCMD_REWIND, TIM_R);
-		return stat;
-
-	case MTNOP:
-		tpqputs(TPQD_IOCTLS, "MTNOP setting status only");
-		/********** should do `read position' for drives that support it **********/
-		return (tp_sense(-1) == TE_OK) ? 0 : -EIO;	/**** check return codes ****/
-
-	case MTRETEN:
-		tpqputs(TPQD_IOCTLS, "MTRETEN retension tape");
-		if ((mode_access == WRITE) && status_bytes_wr)
-			return -EACCES;
-		status_eom_detected = status_eof_detected = NO;
-		return do_qic_cmd(QCMD_RETEN, TIM_R);
-
-	case MTBSFM:
-		/* Think think is like MTBSF, except that
-		 * we shouldn't skip the FM. Tricky.
-		 * Maybe use RD_FM_BCK, then do a SPACE_FWD?
-		 */
-		tpqputs(TPQD_IOCTLS, "MTBSFM not supported");
-		if ((mode_access == WRITE) && status_bytes_wr)
-			return -EACCES;
-		return -ENXIO;
-
-	case MTFSFM:
-		/* I think this is like MTFSF, except that
-		 * we shouldn't skip the FM. Tricky.
-		 * Maybe use QCMD_RD_DATA until we get a TP_FIL exception?
-		 * But then the FM will have been skipped...
-		 * Maybe use RD_FM, then RD_FM_BCK, but not all
-		 * drives will support that!
-		 */
-		tpqputs(TPQD_IOCTLS, "MTFSFM not supported");
-		if ((mode_access == WRITE) && status_bytes_wr)
-			return -EACCES;
-		return -ENXIO;
-
-	case MTEOM:
-		/* This should leave the tape ready for appending
-		 * another file to the end, such that it would append
-		 * after the last FM on tape.
-		 */
-		tpqputs(TPQD_IOCTLS, "MTEOM search for End Of recorded Media");
-		if ((mode_access == WRITE) && status_bytes_wr)
-			return -EACCES;
-		if (TP_HAVE_EOD) {
-			/* Use faster seeking when possible.
-			 * This requires the absence of data beyond the EOM.
-			 * It seems that my drive does not always perform the
-			 * SEEK_EOD correctly, unless it is preceded by a
-			 * rewind command.
-			 */
-# if 0
-			status_eom_detected = status_eof_detected = NO;
-# endif
-			stat = do_qic_cmd(QCMD_REWIND, TIM_R);
-			if (stat)
-				return stat;
-			stat = do_qic_cmd(QCMD_SEEK_EOD, TIM_F);
-			/* After a successful seek, TP_EOR should be returned */
-		} else {
-			/* else just seek until the drive returns exception "No Data" */
-			stat = 0;
-			while ((stat == 0) && (!status_eom_detected)) {
-				stat = do_qic_cmd(QCMD_RD_FM, TIM_F);	      /***** should use MTFSFM here???? ******/
-			}
-			if (tperror.exs & TP_NDT)
-				return 0;
-		}
-		return stat;
-
-	case MTERASE:
-		tpqputs(TPQD_IOCTLS, "MTERASE -- ERASE TAPE !");
-		if ((tperror.exs & TP_ST0) && (tperror.exs & TP_WRP)) {
-			tpqputs(TPQD_ALWAYS, "Cartridge is write-protected.");
-			return -EACCES;
-		} else {
-			time_t t = jiffies;
-
-			/* Plain GNU mt(1) 2.2 erases a tape in O_RDONLY. :-( */
-			if (mode_access == READ)
-				return -EACCES;
-
-			/* FIXME */
-			/* give user a few seconds to pull out tape */
-			while (jiffies - t < 4 * HZ)
-				schedule();
-		}
-
-		/* don't bother writing filemark first */
-		status_eom_detected = status_eof_detected = NO;
-		return do_qic_cmd(QCMD_ERASE, TIM_R);
-
-	case MTRAS1:
-		if (TP_HAVE_RAS1) {
-			tpqputs(TPQD_IOCTLS, "MTRAS1: non-destructive self test");
-			stat = do_qic_cmd(QCMD_SELF_TST1, TIM_R);
-			if (stat != 0) {
-				tpqputs(TPQD_ALWAYS, "RAS1 failed");
-				return stat;
-			}
-			return (tp_sense(0) == TE_OK) ? 0 : -EIO;	/* get_ext_status3(); */
-		}
-		tpqputs(TPQD_IOCTLS, "RAS1 not supported");
-		return -ENXIO;
-
-	case MTRAS2:
-		if (TP_HAVE_RAS2) {
-			tpqputs(TPQD_IOCTLS, "MTRAS2: destructive self test");
-			stat = do_qic_cmd(QCMD_SELF_TST2, TIM_R);
-			if (stat != 0) {
-				tpqputs(TPQD_ALWAYS, "RAS2 failed");
-				return stat;
-			}
-			return (tp_sense(0) == TE_OK) ? 0 : -EIO;	/* get_ext_status3(); */
-		}
-		tpqputs(TPQD_IOCTLS, "RAS2 not supported");
-		return -ENXIO;
-
-	case MTSEEK:
-		if (TP_HAVE_SEEK && (QIC02_TAPE_IFC == ARCHIVE)) {
-			tpqputs(TPQD_IOCTLS, "MTSEEK seeking block");
-			if ((mode_access == WRITE) && status_bytes_wr)
-				return -EACCES;
-			/* NOTE: address (24 bits) is in seek_addr_buf[] */
-			return do_qic_cmd(AR_QCMDV_SEEK_BLK, TIM_F);
-		} else
-			return -ENOTTY;
-
-	default:
-		return -ENOTTY;
-	}
-}				/* do_ioctl_cmd */
-
-
-/* dma_transfer(): This routine is called for every 512 bytes to be read
- * from/written to the tape controller. Speed is important here!
- * (There must be enough time left for the hd controller!)
- * The dma lock protects the DMA controller
- *
- * This routine merely does the least possible to keep
- * the transfers going:
- *	- set the DMA count register for the next 512 bytes
- *	- adjust the DMA address and page registers
- *	- adjust the timeout
- *	- tell the tape controller to start transferring
- * We assume the dma address and mode are, and remain, valid.
- */
-static inline void dma_transfer(void)
-{
-	unsigned long flags;
-
-	if (QIC02_TAPE_IFC == WANGTEK)	/* or EVEREX */
-		outb_p(WT_CTL_ONLINE, QIC02_CTL_PORT);	/* back to normal */
-	else if (QIC02_TAPE_IFC == ARCHIVE)
-		outb_p(0, AR_RESET_DMA_PORT);
-	else			/* QIC02_TAPE_IFC == MOUNTAIN */
-		outb_p(ctlbits, QIC02_CTL_PORT);
-
-
-	flags = claim_dma_lock();
-	clear_dma_ff(QIC02_TAPE_DMA);
-	set_dma_mode(QIC02_TAPE_DMA, dma_mode);
-	set_dma_addr(QIC02_TAPE_DMA, isa_virt_to_bus(buffaddr) + dma_bytes_done);
-	set_dma_count(QIC02_TAPE_DMA, TAPE_BLKSIZE);
-
-	/* start tape DMA controller */
-	if (QIC02_TAPE_IFC == WANGTEK)	/* or EVEREX */
-		outb_p(WT_CTL_DMA | WT_CTL_ONLINE, QIC02_CTL_PORT);	/* trigger DMA transfer */
-
-	else if (QIC02_TAPE_IFC == ARCHIVE) {
-		outb_p(AR_CTL_IEN | AR_CTL_DNIEN, QIC02_CTL_PORT);	/* enable interrupts again */
-		outb_p(0, AR_START_DMA_PORT);	/* start DMA transfer */
-		/* In dma_end() AR_RESET_DMA_PORT is written too. */
-
-	} else {		/* QIC02_TAPE_IFC == MOUNTAIN */
-
-		inb(MTN_R_DESELECT_DMA_PORT);
-		outb_p(ctlbits | (MTN_CTL_EXC_IEN | MTN_CTL_DNIEN),
-		       QIC02_CTL_PORT);
-		outb_p(0, MTN_W_SELECT_DMA_PORT);	/* start DMA transfer */
-		if (dma_mode == DMA_MODE_WRITE)
-			outb_p(0, MTN_W_DMA_WRITE_PORT);	/* start DMA transfer */
-	}
-
-	/* start computer DMA controller */
-	enable_dma(QIC02_TAPE_DMA);
-
-	release_dma_lock(flags);
-
-	/* block transfer should start now, jumping to the 
-	 * interrupt routine when done or an exception was detected.
-	 */
-}				/* dma_transfer */
-
-
-/* start_dma() sets a DMA transfer up between the tape controller and
- * the kernel qic02_tape_buf buffer.
- * Normally bytes_todo==dma_bytes_done at the end of a DMA transfer. If not,
- * a filemark was read, or an attempt to write beyond the End Of Tape 
- * was made. [Or some other bad thing happened.]
- * Must do a sense() before returning error.
- */
-static int start_dma(short mode, unsigned long bytes_todo)
-/* assume 'bytes_todo'>0 */
-{
-	int stat;
-
-	tpqputs(TPQD_DEBUG, "start_dma() enter");
-	TPQDEB( {printk(TPQIC02_NAME ": doing_read==%d, doing_write==%d\n",
-		      doing_read, doing_write);})
-
-	dma_bytes_done = 0;
-	dma_bytes_todo = bytes_todo;
-	status_error = NO;
-	/* dma_mode!=0 indicates that the dma controller is in use */
-	dma_mode = (mode == WRITE) ? DMA_MODE_WRITE : DMA_MODE_READ;
-
-	/* Only give READ/WRITE DATA command to tape drive if we haven't
-	 * done that already. Otherwise the drive will rewind to the beginning
-	 * of the current file on tape. Any QIC command given other than
-	 * R/W FM will break the read/write transfer cycle.
-	 * do_qic_cmd() will terminate doing_{read,write}
-	 */
-	if ((doing_read == NO) && (doing_write == NO)) {
-		/* First, we have to clear the status -- maybe remove TP_FIL???
-		 */
-
-#if 0
-		/* Next dummy get status is to make sure CNI is valid,
-		   since we're only just starting a read/write it doesn't
-		   matter some exceptions are cleared by reading the status;
-		   we're only interested in CNI and WRP. -Eddy */
-		get_status(&tperror);
-#else
-		/* TP_CNI should now be handled in open(). -Hennus */
-#endif
-
-		stat = tp_sense(((mode == WRITE) ? 0 : TP_WRP) | TP_BOM | TP_FIL);
-		if (stat != TE_OK)
-			return stat;
-
-#ifdef OBSOLETE
-		/************* not needed iff rd_status() would wait for ready!!!!!! **********/
-		if (wait_for_ready(TIM_S) != TE_OK) {	/*** not sure this is needed ***/
-			tpqputs(TPQD_ALWAYS, "wait_for_ready failed in start_dma");
-			return -EIO;
-		}
-#endif
-
-		if (QIC02_TAPE_IFC == MOUNTAIN) {
-			/* Set control bits to select ONLINE during command */
-			ctlbits |= MTN_QIC02_CTL_ONLINE;
-		}
-
-		/* Tell the controller the data direction */
-
-		/* r/w, timeout medium, check exceptions, sets status_cmd_pending. */
-		stat = send_qic02_cmd((mode == WRITE) ? QCMD_WRT_DATA : QCMD_RD_DATA, TIM_M, 0);
-		if (stat != TE_OK) {
-			printk(TPQIC02_NAME ": start_dma: init %s failed\n", (mode == WRITE) ? "write" : "read");
-			(void) tp_sense(0);
-			return stat;
-		}
-
-		/* Do this last, because sense() will clear the doing_{read,write}
-		 * flags, causing trouble next time around.
-		 */
-		if (wait_for_ready(TIM_M) != TE_OK)
-			return -EIO;
-		switch (mode) {
-		case READ:
-			doing_read = YES;
-			break;
-		case WRITE:
-			doing_write = YES;
-			break;
-		default:
-			printk(TPQIC02_NAME ": requested unknown mode %d\n", mode);
-			panic(TPQIC02_NAME ": invalid mode in start_dma()");
-		}
-
-	} else if (is_exception()) {
-		/* This is for Archive drives, to handle reads with 0 bytes
-		 * left for the last read request.
-		 *
-		 * ******** this also affects EOF/EOT handling! ************
-		 */
-		tpqputs(TPQD_ALWAYS, "detected exception in start_dma() while transfer in progress");
-		status_error = YES;
-		return TE_END;
-	}
-
-
-	status_expect_int = YES;
-
-	/* This assumes tape is already positioned, but these
-	 * semi-'intelligent' drives are unpredictable...
-	 */
-	TIMERON(TIM_M * 2);
-
-	/* initiate first data block read from/write to the tape controller */
-
-	dma_transfer();
-
-	TPQPUTS("start_dma() end");
-	return TE_OK;
-}				/* start_dma */
-
-
-/* This cleans up after the dma transfer has completed
- * (or failed). If an exception occurred, a sense()
- * must be done. If the exception was caused by a FM,
- * sense() will set `status_eof_detected' and
- * `status_eom_detected', as required.
- */
-static void end_dma(unsigned long *bytes_done)
-{
-	int stat = TE_OK;
-	unsigned long flags;
-
-	TIMEROFF;
-
-	TPQPUTS("end_dma() enter");
-
-	flags = claim_dma_lock();
-
-	disable_dma(QIC02_TAPE_DMA);
-	clear_dma_ff(QIC02_TAPE_DMA);
-
-	release_dma_lock(flags);
-
-	if (QIC02_TAPE_IFC == WANGTEK)	/* or EVEREX */
-		outb_p(WT_CTL_ONLINE, QIC02_CTL_PORT);	/* back to normal */
-	else if (QIC02_TAPE_IFC == ARCHIVE)
-		outb_p(0, AR_RESET_DMA_PORT);
-	else {			/* QIC02_TAPE_IFC == MOUNTAIN */
-		/* Clear control bits, de-select ONLINE during tp_sense */
-		ctlbits &= ~MTN_QIC02_CTL_ONLINE;
-	}
-
-	stat = wait_for_ready(TIM_M);
-	if (status_error || (stat != TE_OK)) {
-		tpqputs(TPQD_DMAX, "DMA transfer exception");
-		stat = tp_sense((dma_mode == READ) ? TP_WRP : 0);
-		/* no return here -- got to clean up first! */
-	} else {		/* if (QIC02_TAPE_IFC == MOUNTAIN) */
-		outb_p(ctlbits, QIC02_CTL_PORT);
-	}
-
-	if (QIC02_TAPE_IFC == MOUNTAIN)
-		inb(MTN_R_DESELECT_DMA_PORT);
-
-	/* take the tape controller offline */
-
-	/* finish off DMA stuff */
-
-
-	dma_mode = 0;
-	/* Note: The drive is left on-line, ready for the next
-	 * data transfer.
-	 * If the next command to the drive does not continue
-	 * the pending cycle, it must do 2 sense()s first.
-	 */
-
-	*bytes_done = dma_bytes_done;
-	status_expect_int = NO;
-	ioctl_status.mt_blkno += (dma_bytes_done / TAPE_BLKSIZE);
-
-	TPQPUTS("end_dma() exit");
-	/*** could return stat here ***/
-}				/* end_dma */
-
-/*********** Below are the (public) OS-interface procedures ***********/
-
-
-/* qic02_tape_times_out() is called when a DMA transfer doesn't complete
- * quickly enough. Usually this means there is something seriously wrong
- * with the hardware/software, but it could just be that the controller
- * has decided to do a long rewind, just when I didn't expect it.
- * Just try again.
- */
-static void qic02_tape_times_out(unsigned long dummy)
-{
-	printk("time-out in %s driver\n", TPQIC02_NAME);
-	if ((status_cmd_pending > 0) || dma_mode) {
-		/* takes tooo long, shut it down */
-		status_dead = YES;
-		status_cmd_pending = 0;
-		status_timer_on = NO;
-		status_expect_int = NO;
-		status_error = YES;
-		if (dma_mode) {
-			dma_mode = 0;	/* signal end to read/write routine */
-			wake_up(&qic02_tape_transfer);
-		}
-	}
-}				/* qic02_tape_times_out */
-
-/*
- * Interrupt handling:
- *
- * 1) Interrupt is generated iff at the end of 
- *    a 512-DMA-block transfer.
- * 2) EXCEPTION is not raised unless something 
- *    is wrong or EOT/FM is detected.
- * 3) FM EXCEPTION is set *after* the last byte has
- *    been transferred by DMA. By the time the interrupt
- *    is handled, the EXCEPTION may already be set.
- *
- * So,
- * 1) On EXCEPTION, assume data has been transferred, so
- *    continue as usual, but set a flag to indicate the
- *    exception was detected.
- *    Do a sense status when the flag is found set.
- * 2) Do not attempt to continue a transfer after an exception.
- *    [??? What about marginal blocks???????]
- */
-
-
-/* qic02_tape_interrupt() is called when the tape controller completes 
- * a DMA transfer.
- * We are not allowed to sleep here! 
- *
- * Check if the transfer was successful, check if we need to transfer
- * more. If the buffer contains enough data/is empty enough, signal the
- * read/write() thread to copy to/from user space.
- * When we are finished, set flags to indicate end, disable timer.
- * NOTE: This *must* be fast! 
- */
-static irqreturn_t qic02_tape_interrupt(int irq, void *dev_id,
-				 struct pt_regs *regs)
-{
-	int stat, r, i;
-	unsigned long flags;
-
-	TIMEROFF;
-
-	if (status_expect_int) {
-#ifdef WANT_EXTRA_FULL_DEBUGGING
-		if (TP_DIAGS(current_type))
-			printk("@");
-#endif
-		stat = inb(QIC02_STAT_PORT);	/* Knock, knock */
-		if (QIC02_TAPE_IFC == ARCHIVE) {	/* "Who's there?" */
-			if (((stat & (AR_STAT_DMADONE)) == 0) &&
-			    ((stat & (QIC02_STAT_EXCEPTION)) != 0)) {
-				TIMERCONT;
-				return IRQ_NONE;/* "Linux with IRQ sharing" */
-			}
-		}
-
-		if ((stat & QIC02_STAT_EXCEPTION) == 0) {	/* exception occurred */
-			/* Possible causes for an exception during a transfer:
-			 *      - during a write-cycle: end of tape (EW) hole detected.
-			 *      - during a read-cycle: filemark or EOD detected.
-			 *      - something went wrong
-			 * So don't continue with the next block.
-			 */
-			tpqputs(TPQD_ALWAYS, "isr: exception on tape controller");
-			printk("      status %02x\n", stat);
-			status_error = TE_EX;
-
-			dma_bytes_done += TAPE_BLKSIZE;
-
-			dma_mode = 0;	/* wake up rw() */
-			status_expect_int = NO;
-			wake_up(&qic02_tape_transfer);
-			return IRQ_HANDLED;
-		}
-		/* return if tape controller not ready, or
-		 * if dma channel hasn't finished last byte yet.
-		 */
-		r = 0;
-
-		/* Skip next ready check for Archive controller because
-		 * it may be busy reading ahead. Weird. --hhb
-		 */
-		if (QIC02_TAPE_IFC == WANGTEK)	/* I think this is a drive-dependency, not IFC -- hhb */
-			if (stat & QIC02_STAT_READY) {	/* not ready */
-				tpqputs(TPQD_ALWAYS, "isr: ? Tape controller not ready");
-				r = 1;
-			}
-
-		flags = claim_dma_lock();
-
-		if ((i = get_dma_residue(QIC02_TAPE_DMA)) != 0) {
-			printk(TPQIC02_NAME ": dma_residue == %x !!!\n", i);
-			r = 1;	/* big trouble, but can't do much about it... */
-		}
-
-		release_dma_lock(flags);
-
-		if (r)
-			return IRQ_HANDLED;
-
-		/* finish DMA cycle */
-
-		/* no errors detected, continue */
-		dma_bytes_done += TAPE_BLKSIZE;
-		if (dma_bytes_done >= dma_bytes_todo) {
-			/* finished! Wakeup rw() */
-			dma_mode = 0;
-			status_expect_int = NO;
-			TPQPUTS("isr: dma_bytes_done");
-			wake_up(&qic02_tape_transfer);
-		} else {
-			/* start next transfer, account for track-switching time */
-			mod_timer(&tp_timer, jiffies + 6 * HZ);
-			dma_transfer();
-		}
-	} else {
-		printk(TPQIC02_NAME ": Unexpected interrupt, stat == %x\n", inb(QIC02_STAT_PORT));
-	}
-	return IRQ_HANDLED;
-}				/* qic02_tape_interrupt */
-
-
-/* read/write routines:
- * This code copies between a kernel buffer and a user buffer. The 
- * actual data transfer is done using DMA and interrupts. Time-outs
- * are also used.
- *
- * When a filemark is read, we return '0 bytes read' and continue with the
- * next file after that.
- * When EOM is read, we return '0 bytes read' twice.
- * When the EOT marker is detected on writes, '0 bytes read' should be
- * returned twice. If user program does a MTNOP after that, 2 additional
- * blocks may be written.	------- FIXME: Implement this correctly  *************************************************
- *
- * Only read/writes in multiples of 512 bytes are accepted.
- * When no bytes are available, we sleep() until they are. The controller will
- * generate an interrupt, and we (should) get a wake_up() call.
- *
- * Simple buffering is used. User program should ensure that a large enough
- * buffer is used. Usually the drive does some buffering as well (something
- * like 4k or so).
- *
- * Scott S. Bertilson suggested to continue filling the user buffer, rather
- * than waste time on a context switch, when the kernel buffer fills up.
- */
-
-/*
- * Problem: tar(1) doesn't always read the entire file. Sometimes the entire file
- * has been read, but the EOF token is never returned to tar(1), simply because
- * tar(1) knows it has already read all of the data it needs. So we must use
- * open/release to reset the `reported_read_eof' flag. If we don't, the next read
- * request would return the EOF flag for the previous file.
- */
-
-static ssize_t qic02_tape_read(struct file *filp, char __user *buf, size_t count, loff_t * ppos)
-{
-	int type = iminor(filp->f_dentry->d_inode);
-	unsigned short flags = filp->f_flags;
-	unsigned long bytes_todo, bytes_done, total_bytes_done = 0;
-	int stat;
-
-	if (status_zombie == YES) {
-		tpqputs(TPQD_ALWAYS, "configs not set");
-		return -ENXIO;
-	}
-
-	if (TP_DIAGS(current_type))
-		printk(TPQIC02_NAME ": request READ, minor=%x, buf=%p, count=%lx, pos=%Lx, flags=%x\n", type, buf,
-		       (long) count, filp->f_pos, flags);
-
-	if (count % TAPE_BLKSIZE) {	/* Only allow mod 512 bytes at a time. */
-		tpqputs(TPQD_BLKSZ, "Wrong block size");
-		return -EINVAL;
-	}
-
-	/* Just assume everything is ok. Controller will scream if not. */
-
-	if (status_bytes_wr) {	/* Once written, no more reads, 'till after WFM. */
-		return -EACCES;
-	}
-
-	/* This is rather ugly because it has to implement a finite state
-	 * machine in order to handle the EOF situations properly.
-	 */
-	while ((signed) count >= 0) {
-		bytes_done = 0;
-		/* see how much fits in the kernel buffer */
-		bytes_todo = TPQBUF_SIZE;
-		if (bytes_todo > count) {
-			bytes_todo = count;
-		}
-
-		/* Must ensure that user program sees exactly one EOF token (==0) */
-		if (return_read_eof == YES) {
-			if (TPQDBG(DEBUG)) {
-				printk("read: return_read_eof==%d, reported_read_eof==%d, total_bytes_done==%lu\n", return_read_eof, reported_read_eof, total_bytes_done);
-			}
-
-			if (reported_read_eof == NO) {
-				/* have not yet returned EOF to user program */
-				if (total_bytes_done > 0) {
-					return total_bytes_done;	/* next time return EOF */
-				} else {
-					reported_read_eof = YES;	/* move on next time */
-					return 0;	/* return EOF */
-				}
-			} else {
-				/* Application program has already received EOF
-				 * (above), now continue with next file on tape,
-				 * if possible.
-				 * When the FM is reached, EXCEPTION is set,
-				 * causing a sense(). Subsequent read/writes will
-				 * continue after the FM.
-				 */
-		/*********** ?????????? this should check for (EOD|NDT), not EOM, 'cause we can read past EW: ************/
-				if (status_eom_detected) {
-					/* If EOM, nothing left to read, so keep returning EOFs.
-					 *** should probably set some flag to avoid clearing
-					 *** status_eom_detected through ioctls or something
-					 */
-					return 0;
-				} else {
-					/* just eof, there may be more files ahead... */
-					return_read_eof = NO;
-					reported_read_eof = NO;
-					status_eof_detected = NO;	/* reset this too */
-					/*fall through */
-				}
-			}
-		}
-
-		if (bytes_todo == 0) {
-			return total_bytes_done;
-		}
-
-		if (bytes_todo > 0) {
-			/* start reading data */
-			if (is_exception()) {
-				tpqputs(TPQD_DMAX, "is_exception() before start_dma()!");
-			}
-
-/******************************************************************
- ***** if start_dma() fails because the head is positioned 0 bytes
- ***** before the FM, (causing EXCEPTION to be set) return_read_eof should
- ***** be set to YES, and we should return total_bytes_done, rather than -ENXIO.
- ***** The app should recognize this as an EOF condition.
- ***************************************************************************/
-			stat = start_dma(READ, bytes_todo);
-			if (stat == TE_OK) {
-				/* Wait for transfer to complete, interrupt should wake us */
-				
-				wait_event(qic02_tape_transfer, dma_mode != 0);
-
-				if (status_error)
-					return_read_eof = YES;
-
-			} else if (stat != TE_END) {
-				/* should do sense() on error here */
-#if 0
-				return -ENXIO;
-#else
-				printk("Trouble: stat==%02x\n", stat);
-				return_read_eof = YES;
-		/*************** check EOF/EOT handling!!!!!! **/
-#endif
-			}
-			end_dma(&bytes_done);
-			if (bytes_done > bytes_todo) {
-				tpqputs(TPQD_ALWAYS, "read: Oops, read more bytes than requested");
-				return -EIO;
-			}
-			/* copy buffer to user-space in one go */
-			if (bytes_done > 0) {
-				if (copy_to_user(buf, buffaddr, bytes_done))
-					return -EFAULT;
-			}
-#if 1
-			/* Checks Ton's patch below */
-			if ((return_read_eof == NO)  && (status_eof_detected == YES)) {
-				printk(TPQIC02_NAME ": read(): return_read_eof=%d, status_eof_detected=YES. return_read_eof:=YES\n",
-				       return_read_eof);
-			}
-#endif
-			if ((bytes_todo != bytes_done) || (status_eof_detected == YES)) {
-				/* EOF or EOM detected. return EOF next time. */
-				return_read_eof = YES;
-			}
-
-		}
-		/* else: ignore read request for 0 bytes */
-		if (bytes_done > 0) {
-			status_bytes_rd = YES;
-			buf += bytes_done;
-			*ppos += bytes_done;
-			total_bytes_done += bytes_done;
-			count -= bytes_done;
-		}
-	}
-	tpqputs(TPQD_ALWAYS, "read request for <0 bytes");
-	return -EINVAL;
-}				/* qic02_tape_read */
-
-
-
-/* The drive detects near-EOT by means of the holes in the tape.
- * When the holes are detected, there is some space left. The drive
- * reports this as a TP_EOM exception. After clearing the exception,
- * the drive should accept two extra blocks.
- *
- * It seems there are some archiver programs that would like to use the
- * extra space for writing a continuation marker. The driver should return
- * end-of-file to the user program on writes, when the holes are detected.
- * If the user-program wants to use the extra space, it should use the
- * MTNOP ioctl() to get the generic status register and may then continue
- * writing (max 1kB).	----------- doesn't work yet...............
- *
- * EOF behaviour on writes:
- * If there is enough room, write all of the data.
- * If there is insufficient room, write as much as will fit and
- * return the amount written. If the requested amount differs from the
- * written amount, the application program should recognize that as the
- * end of file. Subsequent writes will return -ENOSPC.
- * Unless the minor bits specify a rewind-on-close, the tape will not
- * be rewound when it is full. The user-program should do that, if desired.
- * If the driver were to do that automatically, a user-program could be 
- * confused about the EOT/BOT condition after re-opening the tape device.
- *
- * Multiple volume support: Tar closes the tape device before prompting for
- * the next tape. The user may then insert a new tape and tar will open the
- * tape device again. The driver will detect an exception status in (No Cartridge)
- * and force a rewind. After that tar may continue writing.
- */
-static ssize_t qic02_tape_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos)
-{
-	int type = iminor(filp->f_dentry->d_inode);
-	unsigned short flags = filp->f_flags;
-	unsigned long bytes_todo, bytes_done, total_bytes_done = 0;
-
-	if (status_zombie == YES) {
-		tpqputs(TPQD_ALWAYS, "configs not set");
-		return -ENXIO;
-	}
-
-	if (TP_DIAGS(current_type)) {
-		printk(TPQIC02_NAME ": request WRITE, minor=%x, buf=%p, count=%lx, pos=%Lx, flags=%x\n",
-		       type, buf, (long) count, filp->f_pos, flags);
-	}
-
-	if (count % TAPE_BLKSIZE) {	/* only allow mod 512 bytes at a time */
-		tpqputs(TPQD_BLKSZ, "Wrong block size");
-		return -EINVAL;
-	}
-
-	if (mode_access == READ) {
-		tpqputs(TPQD_ALWAYS, "Not in write mode");
-		return -EACCES;
-	}
-
-	/* open() does a sense() and we can assume the tape isn't changed
-	 * between open() and release(), so the tperror.exs bits will still
-	 * be valid.
-	 */
-	if ((tperror.exs & TP_ST0) && (tperror.exs & TP_WRP)) {
-		tpqputs(TPQD_ALWAYS, "Cartridge is write-protected.");
-		return -EACCES;	/* don't even try when write protected */
-	}
-
-	if (doing_read == YES) {
-		terminate_read(0);
-	}
-
-	while ((signed) count >= 0) {
-		/* see how much fits in the kernel buffer */
-		bytes_done = 0;
-		bytes_todo = TPQBUF_SIZE;
-		if (bytes_todo > count) {
-			bytes_todo = count;
-		}
-
-		if (return_write_eof == YES) {
-			/* return_write_eof should be reset on reverse tape movements. */
-
-			if (reported_write_eof == NO) {
-				if (bytes_todo > 0) {
-					tpqputs(TPQD_ALWAYS, "partial write");
-					/* partial write signals EOF to user program */
-				}
-				reported_write_eof = YES;
-				return total_bytes_done;
-			} else {
-				return -ENOSPC;	/* return error */
-			}
-		}
-
-		/* Quit when done. */
-		if (bytes_todo == 0) {
-			return total_bytes_done;
-		}
-
-		/* copy from user to DMA buffer and initiate transfer. */
-		if (bytes_todo > 0) {
-			if (copy_from_user(buffaddr, buf, bytes_todo))
-				return -EFAULT;
-
-/****************** similar problem with read() at FM could happen here at EOT.
- ******************/
-
-/***** if at EOT, 0 bytes can be written. start_dma() will
- ***** fail and write() will return ENXIO error
- *****/
-			if (start_dma(WRITE, bytes_todo) != TE_OK) {
-				tpqputs(TPQD_ALWAYS, "write: start_dma() failed");
-				/* should do sense() on error here */
-				return -ENXIO;
-				/*********** FIXTHIS **************/
-			}
-
-			/* Wait for write to complete, interrupt should wake us. */
-			wait_event(qic02_tape_transfer, (status_error == 0 && dma_mode != 0));
-
-			end_dma(&bytes_done);
-			if (bytes_done > bytes_todo) {
-				tpqputs(TPQD_ALWAYS, "write: Oops, wrote more bytes than requested");
-				return -EIO;
-			}
-			/* If the dma-transfer was aborted because of an exception,
-			 * status_error will have been set in the interrupt handler.
-			 * Then end_dma() will do a sense().
-			 * If the exception was EXC_EOM, the EW-hole was encountered
-			 * and two more blocks could be written. For the time being we'll
-			 * just consider this to be the EOT.
-			 * Otherwise, something Bad happened, such as the maximum number
-			 * of block-rewrites was exceeded. [e.g. A very bad spot on tape was
-			 * encountered. Normally short dropouts are compensated for by
-			 * rewriting the block in error, up to 16 times. I'm not sure
-			 * QIC-24 drives can do this.]
-			 */
-			if (status_error) {
-				if (status_eom_detected == YES) {
-					tpqputs(TPQD_ALWAYS, "write: EW detected");
-					return_write_eof = YES;
-				} else {
-					/* probably EXC_RWA */
-					tpqputs(TPQD_ALWAYS, "write: dma: error in writing");
-					return -EIO;
-				}
-			}
-			if (bytes_todo != bytes_done) {
-				/* EOF or EOM detected. return EOT next time. */
-				return_write_eof = YES;
-			}
-		}
-		/* else: ignore write request for 0 bytes. */
-
-		if (bytes_done > 0) {
-			status_bytes_wr = YES;
-			buf += bytes_done;
-			*ppos += bytes_done;
-			total_bytes_done += bytes_done;
-			count -= bytes_done;
-		}
-	}
-
-	tpqputs(TPQD_ALWAYS, "write request for <0 bytes");
-	if (TPQDBG(DEBUG)) {
-		printk(TPQIC02_NAME ": status_bytes_wr %x, buf %p"
-		       ", total_bytes_done %lx, count %lx\n",
-		       status_bytes_wr, buf, total_bytes_done,
-		       (long) count);
-	}
-	return -EINVAL;
-}				/* qic02_tape_write */
-
-
-
-/* qic02_tape_open()
- * We allow the device to be opened, even if it is marked 'dead' because
- * we want to be able to reset the tape device without rebooting.
- * Only one open tape file at a time, except when minor=255.
- * Minor 255 is only allowed for resetting and always returns <0.
- * 
- * The density command is only allowed when TP_BOM is set. Thus, remember
- * the most recently used minor bits. When they are different from the
- * remembered values, rewind the tape and set the required density.
- * Don't rewind if the minor bits specify density 0.
- */
-
-static int qic02_tape_open(struct inode *inode, struct file *filp)
-{
-	static int qic02_tape_open_no_use_count(struct inode *,
-						struct file *);
-	int open_error;
-
-	open_error = qic02_tape_open_no_use_count(inode, filp);
-	return open_error;
-}
-
-static int qic02_tape_open_no_use_count(struct inode *inode,
-					struct file *filp)
-{
-	int type = iminor(inode);
-	unsigned short flags = filp->f_flags;
-	unsigned short dens = 0;
-	int s;
-
-
-	if (TP_DIAGS(type)) {
-		printk("qic02_tape_open: dev=tpqic2(%d), flags=%x     ",
-			type, flags);
-	}
-
-	if (type == 255) {	/* special case for resetting */
-		if (capable(CAP_SYS_ADMIN)) {
-			return (tape_reset(1) == TE_OK) ? -EAGAIN : -ENXIO;
-		} else {
-			return -EPERM;
-		}
-	}
-
-	if (status_dead == YES) {
-		/* Allow `mt reset' ioctl() even when already open()ed. */
-		return 0;
-	}
-
-	if(test_and_set_bit(0, &tape_open))
-		return -EBUSY;
-		
-	if (status_zombie == YES) {
-		/* no irq/dma/port stuff allocated yet, no reset done
-		 * yet, so return until MTSETCONFIG has been done.
-		 */
-		return 0;
-	}
-
-	status_bytes_rd = NO;
-	status_bytes_wr = NO;
-
-	return_read_eof = NO;	/********????????????????*****/
-	return_write_eof = (status_eot_detected) ? YES : NO;
-
-	/* Clear this in case user app close()d before reading EOF token */
-	status_eof_detected = NO;
-
-	reported_read_eof = NO;
-	reported_write_eof = NO;
-
-
-	switch (flags & O_ACCMODE) {
-	case O_RDONLY:
-		mode_access = READ;
-		break;
-	case O_WRONLY:		/* Fallthru... Strictly speaking this is not correct... */
-	case O_RDWR:		/* Reads are allowed as long as nothing is written */
-		mode_access = WRITE;
-		break;
-	}
-
-	/* This is to avoid tape-changed problems (TP_CNI exception).
-	 *
-	 * Since removing the cartridge will not raise an exception,
-	 * we always do a tp_sense() to make sure we have the proper
-	 * CNI status, the 2150L may need an additional sense.... - Eddy
-	 */
-	s = tp_sense(TP_WRP | TP_EOM | TP_BOM | TP_CNI | TP_EOR);
-
-	if (s == TE_OK) {
-		/* Try to clear cartridge-changed status for Archive-2150L */
-		if ((tperror.exs & TP_ST0) && (tperror.exs & TP_CNI)) {
-			s = tp_sense(TP_WRP | TP_EOM | TP_BOM | TP_CNI | TP_EOR);
-		}
-	}
-
-	if (s != TE_OK) {
-		tpqputs(TPQD_ALWAYS, "open: sense() failed");
-		clear_bit(0, &tape_open);
-		return -EIO;
-	}
-
-	/* exception bits should be up-to-date now, so check for
-	 * tape presence and exit if absent.
-	 * Even `mt stat' will fail without a tape.
-	 */
-	if ((tperror.exs & TP_ST0) && (tperror.exs & TP_CNI)) {
-		tpqputs(TPQD_ALWAYS, "No tape present.");
-		clear_bit(0, &tape_open);
-		return -EIO;
-	}
-
-	/* At this point we can assume that a tape is present and
-	 * that it will remain present until release() is called.
-	 */
-
-	/* not allowed to do QCMD_DENS_* unless tape is rewound */
-	if ((TP_DENS(type) != 0) && (TP_DENS(current_type) != TP_DENS(type))) {
-		/* force rewind if minor bits have changed,
-		 * i.e. user wants to use tape in different format.
-		 * [assuming single drive operation]
-		 */
-		if (TP_HAVE_DENS) {
-			tpqputs(TPQD_REWIND, "Density minor bits have changed. Forcing rewind.");
-			need_rewind = YES;
-		}
-	} else {
-		/* density bits still the same, but TP_DIAGS bit 
-		 * may have changed.
-		 */
-		current_type = type;
-	}
-
-	if (need_rewind == YES) {
-/***************** CHECK THIS!!!!!!!! **********/
-		s = do_qic_cmd(QCMD_REWIND, TIM_R);
-		if (s != 0) {
-			tpqputs(TPQD_ALWAYS, "open: rewind failed");
-			return -EIO;
-		}
-	}
-
-
-/* Note: After a reset command, the controller will rewind the tape
- *	 just before performing any tape movement operation! ************ SO SET need_rewind flag!!!!!
- */
-	if (status_dead == YES) {
-		tpqputs(TPQD_ALWAYS, "open: tape dead, attempting reset");
-		if (tape_reset(1) != TE_OK) {
-			return -ENXIO;
-		} else {
-			status_dead = NO;
-			if (tp_sense(~(TP_ST1 | TP_ILL)) != TE_OK) {
-				tpqputs(TPQD_ALWAYS, "open: tp_sense() failed\n");
-				status_dead = YES;	/* try reset next time */
-				return -EIO;
-			}
-		}
-	}
-
-	/* things should be ok, once we get here */
-
-
-	/* set density: only allowed when TP_BOM status bit is set,
-	 * so we must have done a rewind by now. If not, just skip over.
-	 * Only give set density command when minor bits have changed.
-	 */
-	if (TP_DENS(current_type) == TP_DENS(type)) {
-		return 0;
-	}
-
-	current_type = type;
-	need_rewind = NO;
-	if (TP_HAVE_DENS) {
-		dens = TP_DENS(type);
-	}
-
-	if (dens < sizeof(format_names) / sizeof(char *))
-		printk(TPQIC02_NAME ": format: %s%s\n", (dens != 0) ? "QIC-" : "", format_names[dens]);
-	else
-		tpqputs(TPQD_REWIND, "Wait for retensioning...");
-
-	switch (TP_DENS(type)) {
-	case 0:		/* Minor 0 is for drives without set-density support */
-		s = 0;
-		break;
-	case 1:
-		s = do_qic_cmd(QCMD_DENS_11, TIM_S);
-		break;
-	case 2:
-		s = do_qic_cmd(QCMD_DENS_24, TIM_S);
-		break;
-	case 3:
-		s = do_qic_cmd(QCMD_DENS_120, TIM_S);
-		break;
-	case 4:
-		s = do_qic_cmd(QCMD_DENS_150, TIM_S);
-		break;
-	case 5:
-		s = do_qic_cmd(QCMD_DENS_300, TIM_S);
-		break;
-	case 6:
-		s = do_qic_cmd(QCMD_DENS_600, TIM_S);
-		break;
-	default:		/* otherwise do a retension before anything else */
-		s = do_qic_cmd(QCMD_RETEN, TIM_R);
-	}
-	if (s != 0) {
-		status_dead = YES;	/* force reset */
-		current_type = 0;/* earlier 0xff80 */
-		return -EIO;
-	}
-
-	return 0;
-}				/* qic02_tape_open */
-
-
-static int qic02_tape_release(struct inode *inode, struct file *filp)
-{
-	int type = iminor(inode);
-
-	if (TP_DIAGS(type)) {
-		printk("qic02_tape_release: dev=tpqic2(%d)\n", type);
-	}
-
-	if (status_zombie == NO) {	/* don't rewind in zombie mode */
-		/* Terminate any pending write cycle. Terminating the read-cycle
-		 * is delayed until it is required to do so for a new command.
-		 */
-		terminate_write(-1);
-
-		if (status_dead == YES) {
-			tpqputs(TPQD_ALWAYS, "release: device dead!?");
-		}
-
-		/* Rewind only if minor number requires it AND 
-		 * read/writes have been done. ************* IS THIS CORRECT??????????
-		 */
-		if (TP_REWCLOSE(type) && (status_bytes_rd | status_bytes_wr)) {
-			tpqputs(TPQD_REWIND, "release: Doing rewind...");
-			(void) do_qic_cmd(QCMD_REWIND, TIM_R);
-		}
-	}
-	clear_bit(0, &tape_open);
-	return 0;
-}				/* qic02_tape_release */
-
-
-#ifdef CONFIG_QIC02_DYNCONF
-/* Set masks etc. based on the interface card type. */
-static int update_ifc_masks(int ifc)
-{
-	QIC02_TAPE_IFC = ifc;
-
-	if ((QIC02_TAPE_IFC == WANGTEK) || (QIC02_TAPE_IFC == EVEREX)) {
-		QIC02_STAT_PORT = QIC02_TAPE_PORT;
-		QIC02_CTL_PORT = QIC02_TAPE_PORT;
-		QIC02_CMD_PORT = QIC02_TAPE_PORT + 1;
-		QIC02_DATA_PORT = QIC02_TAPE_PORT + 1;
-		QIC02_STAT_READY = WT_QIC02_STAT_READY;
-		QIC02_STAT_EXCEPTION = WT_QIC02_STAT_EXCEPTION;
-		QIC02_STAT_MASK = WT_QIC02_STAT_MASK;
-
-		QIC02_STAT_RESETMASK = WT_QIC02_STAT_RESETMASK;
-		QIC02_STAT_RESETVAL = WT_QIC02_STAT_RESETVAL;
-
-		QIC02_CTL_RESET = WT_QIC02_CTL_RESET;
-		QIC02_CTL_REQUEST = WT_QIC02_CTL_REQUEST;
-
-		if (QIC02_TAPE_DMA == 3) {
-			WT_CTL_DMA = WT_CTL_DMA3;
-		} else if (QIC02_TAPE_DMA == 1) {
-			WT_CTL_DMA = WT_CTL_DMA1;
-		} else {
-			tpqputs(TPQD_ALWAYS,
-				"Unsupported or incorrect DMA channel");
-			return -EIO;
-		}
-
-		if (QIC02_TAPE_IFC == EVEREX) {
-			/* Everex is a special case for Wangtek (actually
-			 * it's the other way 'round, but I saw Wangtek first)
-			 */
-			if (QIC02_TAPE_DMA == 3) {
-				WT_CTL_DMA = WT_CTL_DMA1;
-			}
-
-			/* Fixup the kernel copy of the IFC type to that
-			 * we don't have to distinguish between Wangtek and
-			 * and Everex at runtime.
-			 */
-			QIC02_TAPE_IFC = WANGTEK;
-		}
-	} else if (QIC02_TAPE_IFC == ARCHIVE) {
-		QIC02_STAT_PORT = QIC02_TAPE_PORT + 1;
-		QIC02_CTL_PORT = QIC02_TAPE_PORT + 1;
-		QIC02_CMD_PORT = QIC02_TAPE_PORT;
-		QIC02_DATA_PORT = QIC02_TAPE_PORT;
-		QIC02_STAT_READY = AR_QIC02_STAT_READY;
-		QIC02_STAT_EXCEPTION = AR_QIC02_STAT_EXCEPTION;
-		QIC02_STAT_MASK = AR_QIC02_STAT_MASK;
-
-		QIC02_STAT_RESETMASK = AR_QIC02_STAT_RESETMASK;
-		QIC02_STAT_RESETVAL = AR_QIC02_STAT_RESETVAL;
-
-		QIC02_CTL_RESET = AR_QIC02_CTL_RESET;
-		QIC02_CTL_REQUEST = AR_QIC02_CTL_REQUEST;
-
-		if (QIC02_TAPE_DMA > 3) {
-			tpqputs(TPQD_ALWAYS,
-				"Unsupported or incorrect DMA channel");
-			return -EIO;
-		}
-	} else if (QIC02_TAPE_IFC == MOUNTAIN) {
-		QIC02_STAT_PORT = QIC02_TAPE_PORT + 1;
-		QIC02_CTL_PORT = QIC02_TAPE_PORT + 1;
-		QIC02_CMD_PORT = QIC02_TAPE_PORT;
-		QIC02_DATA_PORT = QIC02_TAPE_PORT;
-
-		QIC02_STAT_READY = MTN_QIC02_STAT_READY;
-		QIC02_STAT_EXCEPTION = MTN_QIC02_STAT_EXCEPTION;
-		QIC02_STAT_MASK = MTN_QIC02_STAT_MASK;
-
-		QIC02_STAT_RESETMASK = MTN_QIC02_STAT_RESETMASK;
-		QIC02_STAT_RESETVAL = MTN_QIC02_STAT_RESETVAL;
-
-		QIC02_CTL_RESET = MTN_QIC02_CTL_RESET;
-		QIC02_CTL_REQUEST = MTN_QIC02_CTL_REQUEST;
-
-		if (QIC02_TAPE_DMA > 3) {
-			tpqputs(TPQD_ALWAYS,
-				"Unsupported or incorrect DMA channel");
-			return -EIO;
-		}
-	} else {
-		tpqputs(TPQD_ALWAYS, "Invalid interface type");
-		return -ENXIO;
-	}
-	return qic02_get_resources();
-}				/* update_ifc_masks */
-#endif
-
-
-/* ioctl allows user programs to rewind the tape and stuff like that */
-static int qic02_tape_ioctl(struct inode *inode, struct file *filp, unsigned int iocmd, unsigned long ioarg)
-{
-	int error;
-	int c;
-	struct mtop operation;
-	unsigned char blk_addr[6];
-	struct mtpos ioctl_tell;
-	void __user *argp = (void __user *)ioarg;
-
-
-	if (TP_DIAGS(current_type))
-		printk(TPQIC02_NAME ": ioctl(%4x, %4lx)\n", iocmd, ioarg);
-
-	if (!inode)
-		return -EINVAL;
-
-	/* check iocmd first */
-
-	c = _IOC_NR(iocmd);
-
-#ifdef CONFIG_QIC02_DYNCONF
-	if (c == _IOC_NR(MTIOCGETCONFIG)) {
-		CHECK_IOC_SIZE(mtconfiginfo);
-
-		if (copy_to_user(argp, &qic02_tape_dynconf, sizeof(qic02_tape_dynconf)))
-			return -EFAULT;
-		return 0;
-	} else if (c == _IOC_NR(MTIOCSETCONFIG)) {
-		/* One should always do a MTIOCGETCONFIG first, then update
-		 * user-settings, then write back with MTIOCSETCONFIG.
-		 * The qic02conf program should re-open() the device before actual
-		 * use, to make sure everything is initialized.
-		 */
-
-		CHECK_IOC_SIZE(mtconfiginfo);
-
-		if (!capable(CAP_SYS_RAWIO))
-			return -EPERM;
-
-		if (doing_read != NO || doing_write != NO)
-			return -EBUSY;
-
-		if (status_zombie == NO)
-			qic02_release_resources();	/* and go zombie */
-
-		/* copy struct from user space to kernel space */
-		if (copy_from_user(&qic02_tape_dynconf, argp, sizeof(qic02_tape_dynconf)))
-			return -EFAULT;
-		
-		return update_ifc_masks(qic02_tape_dynconf.ifc_type);
-	}
-	if (status_zombie == YES) {
-		tpqputs(TPQD_ALWAYS, "Configs not set");
-		return -ENXIO;
-	}
-#endif
-	if (c == _IOC_NR(MTIOCTOP)) {
-		CHECK_IOC_SIZE(mtop);
-
-		/* copy mtop struct from user space to kernel space */
-		if (copy_from_user(&operation, argp, sizeof(operation)))
-			return -EFAULT;
-
-		/* ---note: mt_count is signed, negative seeks must be
-		 * ---      translated to seeks in opposite direction!
-		 * (only needed for Sun-programs, I think.)
-		 */
-		/* ---note: MTFSF with count 0 should position the
-		 * ---      tape at the beginning of the current file.
-		 */
-
-		if (TP_DIAGS(current_type))
-			printk("OP op=%4x, count=%4x\n", operation.mt_op, operation.mt_count);
-
-		if (operation.mt_count < 0)
-			tpqputs(TPQD_ALWAYS, "Warning: negative mt_count ignored");
-
-		ioctl_status.mt_resid = operation.mt_count;
-		if (operation.mt_op == MTSEEK) {
-			if (!TP_HAVE_SEEK)
-				return -ENOTTY;
-
-			seek_addr_buf[0] = (operation.mt_count >> 16) & 0xff;
-			seek_addr_buf[1] = (operation.mt_count >> 8) & 0xff;
-			seek_addr_buf[2] = (operation.mt_count) & 0xff;
-			if (operation.mt_count >> 24)
-				return -EINVAL;
-			
-			if ((error = do_ioctl_cmd(operation.mt_op)) != 0)
-				return error;
-
-			ioctl_status.mt_resid = 0;
-		} else {
-			while (operation.mt_count > 0) {
-				operation.mt_count--;
-				if ((error = do_ioctl_cmd(operation.mt_op)) != 0)
-					return error;
-
-				ioctl_status.mt_resid = operation.mt_count;
-			}
-		}
-		return 0;
-
-	} else if (c == _IOC_NR(MTIOCGET)) {
-		if (TP_DIAGS(current_type))
-			printk("GET ");
-
-		CHECK_IOC_SIZE(mtget);
-
-		/* It appears (gmt(1)) that it is normal behaviour to
-		 * first set the status with MTNOP, and then to read
-		 * it out with MTIOCGET
-		 */
-
-		/* copy results to user space */
-		if (copy_to_user(argp, &ioctl_status, sizeof(ioctl_status)))
-			return -EFAULT;
-		return 0;
-	} else if (TP_HAVE_TELL && (c == _IOC_NR(MTIOCPOS))) {
-		if (TP_DIAGS(current_type))
-			printk("POS ");
-
-		CHECK_IOC_SIZE(mtpos);
-
-		tpqputs(TPQD_IOCTLS, "MTTELL reading block address");
-		if (doing_read == YES || doing_write == YES)
-			finish_rw(AR_QCMDV_TELL_BLK);
-
-		c = rdstatus((char *) blk_addr, sizeof(blk_addr), AR_QCMDV_TELL_BLK);
-		if (c != TE_OK)
-			return -EIO;
-
-		ioctl_tell.mt_blkno = (blk_addr[3] << 16) | (blk_addr[4] << 8) | blk_addr[5];
-
-		/* copy results to user space */
-		if (copy_to_user(argp, &ioctl_tell, sizeof(ioctl_tell)))
-			return -EFAULT;
-		return 0;
-
-	} else
-		return -ENOTTY;	/* Other cmds not supported. */
-}				/* qic02_tape_ioctl */
-
-
-static ssize_t qic02_do_tape_read(struct file *filp, char __user *buf, size_t count, loff_t * ppos)
-{
-	int err;
-	
-	down(&tape_op);	
-	err = qic02_tape_read(filp, buf, count, ppos);
-	up(&tape_op);
-	
-	return err;
-}
-
-static ssize_t qic02_do_tape_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos)
-{
-	int err;
-
-	down(&tape_op);	
-	err = qic02_tape_write(filp, buf, count, ppos);
-	up(&tape_op);
-	
-	return err;
-}
-
-static int qic02_do_tape_ioctl(struct inode *inode, struct file *filp, unsigned int iocmd, unsigned long ioarg)
-{
-	int err;
-	
-	down(&tape_op);	
-	err = qic02_tape_ioctl(inode, filp,  iocmd, ioarg);
-	up(&tape_op);
-	
-	return err;
-}
-
-/* These are (most) of the interface functions: */
-static struct file_operations qic02_tape_fops = {
-	.owner = THIS_MODULE,
-	.llseek = no_llseek,
-	.read = qic02_do_tape_read,
-	.write = qic02_do_tape_write,
-	.ioctl = qic02_do_tape_ioctl,
-	.open = qic02_tape_open,
-	.release = qic02_tape_release,
-};
-
-
-static void qic02_release_resources(void)
-{
-	free_irq(QIC02_TAPE_IRQ, NULL);
-	free_dma(QIC02_TAPE_DMA);
-	release_region(QIC02_TAPE_PORT, QIC02_TAPE_PORT_RANGE);
-	if (buffaddr)
-		free_pages((unsigned long) buffaddr, get_order(TPQBUF_SIZE));
-	buffaddr = NULL;	/* Better to cause a panic than overwite someone else */
-	status_zombie = YES;
-}				/* qic02_release_resources */
-
-
-static int qic02_get_resources(void)
-{
-	/* First perform some checks. If one of them fails,
-	 * the tape driver will not be registered to the system.
-	 */
-
-	/* for DYNCONF, allocating IO, DMA and IRQ should not be done until 
-	 * the config parameters have been set using MTSETCONFIG.
-	 */
-
-	/* Grab the IO region. */
-	if (!request_region(QIC02_TAPE_PORT, QIC02_TAPE_PORT_RANGE, TPQIC02_NAME)) {
-		printk(TPQIC02_NAME ": IO space at 0x%x [%d ports] already reserved\n",
-		       QIC02_TAPE_PORT, QIC02_TAPE_PORT_RANGE);
-		return -ENXIO;
-	}
-
-	/* get IRQ */
-	if (request_irq(QIC02_TAPE_IRQ, qic02_tape_interrupt, SA_INTERRUPT, "QIC-02", NULL)) {
-		printk(TPQIC02_NAME ": can't allocate IRQ%d for QIC-02 tape\n", QIC02_TAPE_IRQ);
-		release_region(QIC02_TAPE_PORT, QIC02_TAPE_PORT_RANGE);
-		return -EBUSY;
-	}
-
-	/* After IRQ, allocate DMA channel */
-	if (request_dma(QIC02_TAPE_DMA, "QIC-02")) {
-		printk(TPQIC02_NAME ": can't allocate DMA%d for QIC-02 tape\n", QIC02_TAPE_DMA);
-		free_irq(QIC02_TAPE_IRQ, NULL);
-		release_region(QIC02_TAPE_PORT, QIC02_TAPE_PORT_RANGE);
-		return -EBUSY;
-	}
-
-	/* Setup the page-address for the dma transfer. */
-	buffaddr = (void *) __get_dma_pages(GFP_KERNEL, get_order(TPQBUF_SIZE));
-	if (!buffaddr) {
-		qic02_release_resources();
-		return -EBUSY;	/* Not ideal, EAGAIN perhaps? */
-	}
-
-	memset(buffaddr, 0, TPQBUF_SIZE);
-
-	printk(TPQIC02_NAME ": Settings: IRQ %d, DMA %d, IO 0x%x, IFC %s\n",
-	       QIC02_TAPE_IRQ, QIC02_TAPE_DMA, ((QIC02_TAPE_IFC == ARCHIVE)
-						|| (QIC02_TAPE_IFC ==
-						    MOUNTAIN)) ?
-	       QIC02_CMD_PORT : QIC02_STAT_PORT,
-	       (QIC02_TAPE_IFC ==
-		MOUNTAIN) ? "Mountain" : ((QIC02_TAPE_IFC ==
-					   ARCHIVE) ? "Archive" :
-					  "Wangtek"));
-
-	if (tape_reset(0) != TE_OK || tp_sense(TP_WRP | TP_POR | TP_CNI) != TE_OK) {
-		/* No drive detected, so vanish */
-		tpqputs(TPQD_ALWAYS, "No drive detected -- releasing IO/IRQ/DMA.");
-		status_dead = YES;
-		qic02_release_resources();
-		return -EIO;
-	}
-
-	/* All should be ok now */
-	status_zombie = NO;
-	return 0;
-}				/* qic02_get_resources */
-
-int __init qic02_tape_init(void)
-{
-	if (TPSTATSIZE != 6) {
-		printk(TPQIC02_NAME ": internal error: tpstatus struct incorrect!\n");
-		return -ENODEV;
-	}
-	if ((TPQBUF_SIZE < 512) || (TPQBUF_SIZE >= 0x10000)) {
-		printk(TPQIC02_NAME ": internal error: DMA buffer size out of range\n");
-		return -ENODEV;
-	}
-
-	current_type = 0;
-
-#ifndef CONFIG_QIC02_DYNCONF
-	printk(TPQIC02_NAME ": IRQ %d, DMA %d, IO 0x%x, IFC %s, %s, %s\n",
-	       QIC02_TAPE_IRQ, QIC02_TAPE_DMA,
-# if QIC02_TAPE_IFC == WANGTEK
-	       QIC02_STAT_PORT, "Wangtek",
-# elif QIC02_TAPE_IFC == ARCHIVE
-	       QIC02_CMD_PORT, "Archive",
-# elif QIC02_TAPE_IFC == MOUNTAIN
-	       QIC02_CMD_PORT, "Mountain",
-# else
-#  error
-# endif
-	       rcs_revision, rcs_date);
-	if (qic02_get_resources())
-		return -ENODEV;
-#else
-	printk(TPQIC02_NAME ": Runtime config, %s, %s\n", rcs_revision, rcs_date);
-#endif
-	printk(TPQIC02_NAME ": DMA buffers: %u blocks\n", NR_BLK_BUF);
-	/* If we got this far, install driver functions */
-	if (register_chrdev(QIC02_TAPE_MAJOR, TPQIC02_NAME, &qic02_tape_fops)) 
-	{
-		printk(TPQIC02_NAME ": Unable to get chrdev major %d\n", QIC02_TAPE_MAJOR);
-#ifndef CONFIG_QIC02_DYNCONF
-		qic02_release_resources();
-#endif
-		return -ENODEV;
-	}
-
-	tpqic02_class = class_simple_create(THIS_MODULE, TPQIC02_NAME);
-	class_simple_device_add(tpqic02_class, MKDEV(QIC02_TAPE_MAJOR, 2), NULL, "ntpqic11");
-	devfs_mk_cdev(MKDEV(QIC02_TAPE_MAJOR, 2),
-		       S_IFCHR|S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP, "ntpqic11");
-	class_simple_device_add(tpqic02_class, MKDEV(QIC02_TAPE_MAJOR, 3), NULL, "tpqic11");
-	devfs_mk_cdev(MKDEV(QIC02_TAPE_MAJOR, 3),
-		       S_IFCHR|S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP, "tpqic11");
-
-	class_simple_device_add(tpqic02_class, MKDEV(QIC02_TAPE_MAJOR, 4), NULL, "ntpqic24");
-	devfs_mk_cdev(MKDEV(QIC02_TAPE_MAJOR, 4),
-		       S_IFCHR|S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP, "ntpqic24");
-	class_simple_device_add(tpqic02_class, MKDEV(QIC02_TAPE_MAJOR, 5), NULL, "tpqic24");
-	devfs_mk_cdev(MKDEV(QIC02_TAPE_MAJOR, 5),
-		       S_IFCHR|S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP, "tpqic24");
-
-	class_simple_device_add(tpqic02_class, MKDEV(QIC02_TAPE_MAJOR, 6), NULL, "ntpqic20");
-	devfs_mk_cdev(MKDEV(QIC02_TAPE_MAJOR, 6),
-		       S_IFCHR|S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP, "ntpqic120");
-	class_simple_device_add(tpqic02_class, MKDEV(QIC02_TAPE_MAJOR, 7), NULL, "tpqic20");
-	devfs_mk_cdev(MKDEV(QIC02_TAPE_MAJOR, 7),
-		       S_IFCHR|S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP, "tpqic120");
-
-	class_simple_device_add(tpqic02_class, MKDEV(QIC02_TAPE_MAJOR, 8), NULL, "ntpqic50");
-	devfs_mk_cdev(MKDEV(QIC02_TAPE_MAJOR, 8),
-		       S_IFCHR|S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP, "ntpqic150");
-	class_simple_device_add(tpqic02_class, MKDEV(QIC02_TAPE_MAJOR, 9), NULL, "tpqic50");
-	devfs_mk_cdev(MKDEV(QIC02_TAPE_MAJOR, 9),
-		       S_IFCHR|S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP, "tpqic150");
-
-	init_waitqueue_head(&qic02_tape_transfer);
-	/* prepare timer */
-	TIMEROFF;
-	init_timer(&tp_timer);
-	tp_timer.function = qic02_tape_times_out;
-
-#ifndef CONFIG_QIC02_DYNCONF
-	if (tape_reset(0) != TE_OK || tp_sense(TP_WRP | TP_POR | TP_CNI) != TE_OK) {
-		/* No drive detected, so vanish */
-		tpqputs(TPQD_ALWAYS, "No drive detected -- driver going on vacation...");
-		qic02_release_resources();
-		status_dead = YES;
-		return -ENODEV;
-	} else {
-		if (is_exception()) {
-			tpqputs(TPQD_ALWAYS, "exception detected\n");
-			(void) tp_sense(TP_WRP | TP_POR | TP_CNI);
-		}
-	}
-#endif
-
-	/* initialize generic status for ioctl requests */
-
-	ioctl_status.mt_type = QIC02_TAPE_DRIVE;	/* MT_IS* id nr */
-
-	ioctl_status.mt_resid = 0;	/* ---residual count */
-	ioctl_status.mt_gstat = 0;	/* ---generic status */
-	ioctl_status.mt_erreg = 0;	/* not used */
-	ioctl_status.mt_fileno = 0;	/* number of current file on tape */
-	ioctl_status.mt_blkno = 0;	/* number of current (logical) block */
-
-	return 0;
-}				/* qic02_tape_init */
-
-static void qic02_module_exit(void)
-{
-	unregister_chrdev(QIC02_TAPE_MAJOR, TPQIC02_NAME);
-	if (status_zombie == NO)
-		qic02_release_resources();
-		
-	devfs_remove("ntpqic11");
-	class_simple_device_remove(MKDEV(QIC02_TAPE_MAJOR, 2));
-	devfs_remove("tpqic11");
-	class_simple_device_remove(MKDEV(QIC02_TAPE_MAJOR, 3));
-	devfs_remove("ntpqic24");
-	class_simple_device_remove(MKDEV(QIC02_TAPE_MAJOR, 4));
-	devfs_remove("tpqic24");
-	class_simple_device_remove(MKDEV(QIC02_TAPE_MAJOR, 5));
-	devfs_remove("ntpqic120");
-	class_simple_device_remove(MKDEV(QIC02_TAPE_MAJOR, 6));
-	devfs_remove("tpqic120");
-	class_simple_device_remove(MKDEV(QIC02_TAPE_MAJOR, 7));
-	devfs_remove("ntpqic150");
-	class_simple_device_remove(MKDEV(QIC02_TAPE_MAJOR, 8));
-	devfs_remove("tpqic150");
-	class_simple_device_remove(MKDEV(QIC02_TAPE_MAJOR, 9));
-
-	class_simple_destroy(tpqic02_class);
-}
-
-static int qic02_module_init(void)
-{
-	int retval;
-	retval = qic02_tape_init();
-# ifdef CONFIG_QIC02_DYNCONF
-	/* This allows the dynamic config program to setup the card
-	 * by presetting qic02_tape_dynconf via insmod
-	 */
-	if (!retval && qic02_tape_dynconf.ifc_type) {
-		retval = update_ifc_masks(qic02_tape_dynconf.ifc_type);
-		if (retval) {
-			qic02_module_exit();
-		}
-	}
-# endif
-	return retval;
-}
-
-MODULE_LICENSE("GPL");
-
-module_init(qic02_module_init);
-module_exit(qic02_module_exit);
diff -Nru a/drivers/char/tty_io.c b/drivers/char/tty_io.c
--- a/drivers/char/tty_io.c	2005-03-11 12:51:47 -08:00
+++ b/drivers/char/tty_io.c	2005-03-11 12:51:47 -08:00
@@ -1789,7 +1789,6 @@
 	}
 #ifdef CONFIG_VT
 	if (device == MKDEV(TTY_MAJOR,0)) {
-		extern int fg_console;
 		extern struct tty_driver *console_driver;
 		driver = console_driver;
 		index = fg_console;
@@ -2016,11 +2015,10 @@
 		return 0;
 #ifdef CONFIG_VT
 	if (tty->driver->type == TTY_DRIVER_TYPE_CONSOLE) {
-		unsigned int currcons = tty->index;
 		int rc;
 
 		acquire_console_sem();
-		rc = vc_resize(currcons, tmp_ws.ws_col, tmp_ws.ws_row);
+		rc = vc_resize(tty->driver_data, tmp_ws.ws_col, tmp_ws.ws_row);
 		release_console_sem();
 		if (rc)
 			return -ENXIO;
diff -Nru a/drivers/char/vc_screen.c b/drivers/char/vc_screen.c
--- a/drivers/char/vc_screen.c	2005-03-11 12:51:42 -08:00
+++ b/drivers/char/vc_screen.c	2005-03-11 12:51:42 -08:00
@@ -52,14 +52,17 @@
 	int size;
 	int minor = iminor(inode);
 	int currcons = minor & 127;
+	struct vc_data *vc;
+
 	if (currcons == 0)
 		currcons = fg_console;
 	else
 		currcons--;
 	if (!vc_cons_allocated(currcons))
 		return -ENXIO;
+	vc = vc_cons[currcons].d;
 
-	size = vc_cons[currcons].d->vc_rows * vc_cons[currcons].d->vc_cols;
+	size = vc->vc_rows * vc->vc_cols;
 
 	if (minor & 128)
 		size = 2*size + HEADER_SIZE;
@@ -442,7 +445,7 @@
 		buf += orig_count;
 		pos += orig_count;
 		if (org0)
-			update_region(currcons, (unsigned long)(org0), org-org0);
+			update_region(vc, (unsigned long)(org0), org - org0);
 	}
 	*ppos += written;
 	ret = written;
diff -Nru a/drivers/char/vt.c b/drivers/char/vt.c
--- a/drivers/char/vt.c	2005-03-11 12:51:51 -08:00
+++ b/drivers/char/vt.c	2005-03-11 12:51:51 -08:00
@@ -98,8 +98,6 @@
 #include <asm/system.h>
 #include <asm/uaccess.h>
 
-#include "console_macros.h"
-
 
 const struct consw *conswitchp;
 
@@ -135,11 +133,11 @@
 #endif
 
 static int con_open(struct tty_struct *, struct file *);
-static void vc_init(unsigned int console, unsigned int rows,
+static void vc_init(struct vc_data *vc, unsigned int rows,
 		    unsigned int cols, int do_clear);
 static void gotoxy(struct vc_data *vc, int new_x, int new_y);
-static void save_cur(int currcons);
-static void reset_terminal(int currcons, int do_clear);
+static void save_cur(struct vc_data *vc);
+static void reset_terminal(struct vc_data *vc, int do_clear);
 static void con_flush_chars(struct tty_struct *tty);
 static void set_vesa_blanking(char __user *p);
 static void set_cursor(struct vc_data *vc);
@@ -214,17 +212,12 @@
  *	Low-Level Functions
  */
 
-#define IS_FG			(currcons == fg_console)
-#define IS_FG_VC(vc)		(vc == vc_cons[fg_console].d)
-
-#define IS_VISIBLE CON_IS_VISIBLE(vc_cons[currcons].d)
+#define IS_FG(vc)	((vc)->vc_num == fg_console)
 
 #ifdef VT_BUF_VRAM_ONLY
-#define DO_UPDATE		0
-#define DO_UPDATE_VC(vc)	0
+#define DO_UPDATE(vc)	0
 #else
-#define DO_UPDATE 		IS_VISIBLE
-#define DO_UPDATE_VC(vc)	CON_IS_VISIBLE(vc)
+#define DO_UPDATE(vc)	CON_IS_VISIBLE(vc)
 #endif
 
 static int pm_con_request(struct pm_dev *dev, pm_request_t rqst, void *data);
@@ -254,39 +247,38 @@
 	schedule_work(&console_work);
 }
 
-static void scrup(int currcons, unsigned int t, unsigned int b, int nr)
+static void scrup(struct vc_data *vc, unsigned int t, unsigned int b, int nr)
 {
 	unsigned short *d, *s;
 
 	if (t+nr >= b)
 		nr = b - t - 1;
-	if (b > vc_cons[currcons].d->vc_rows || t >= b || nr < 1)
+	if (b > vc->vc_rows || t >= b || nr < 1)
 		return;
-	if (IS_VISIBLE && sw->con_scroll(vc_cons[currcons].d, t, b, SM_UP, nr))
+	if (CON_IS_VISIBLE(vc) && vc->vc_sw->con_scroll(vc, t, b, SM_UP, nr))
 		return;
-	d = (unsigned short *) (origin+vc_cons[currcons].d->vc_size_row*t);
-	s = (unsigned short *) (origin+vc_cons[currcons].d->vc_size_row*(t+nr));
-	scr_memmovew(d, s, (b-t-nr) * vc_cons[currcons].d->vc_size_row);
-	scr_memsetw(d + (b-t-nr) * vc_cons[currcons].d->vc_cols, video_erase_char,
-			vc_cons[currcons].d->vc_size_row * nr);
+	d = (unsigned short *)(vc->vc_origin + vc->vc_size_row * t);
+	s = (unsigned short *)(vc->vc_origin + vc->vc_size_row * (t + nr));
+	scr_memmovew(d, s, (b - t - nr) * vc->vc_size_row);
+	scr_memsetw(d + (b - t - nr) * vc->vc_cols, vc->vc_video_erase_char,
+		    vc->vc_size_row * nr);
 }
 
-static void
-scrdown(int currcons, unsigned int t, unsigned int b, int nr)
+static void scrdown(struct vc_data *vc, unsigned int t, unsigned int b, int nr)
 {
 	unsigned short *s;
 	unsigned int step;
 
 	if (t+nr >= b)
 		nr = b - t - 1;
-	if (b > vc_cons[currcons].d->vc_rows || t >= b || nr < 1)
+	if (b > vc->vc_rows || t >= b || nr < 1)
 		return;
-	if (IS_VISIBLE && sw->con_scroll(vc_cons[currcons].d, t, b, SM_DOWN, nr))
+	if (CON_IS_VISIBLE(vc) && vc->vc_sw->con_scroll(vc, t, b, SM_DOWN, nr))
 		return;
-	s = (unsigned short *) (origin+vc_cons[currcons].d->vc_size_row*t);
-	step = vc_cons[currcons].d->vc_cols * nr;
-	scr_memmovew(s + step, s, (b-t-nr)*vc_cons[currcons].d->vc_size_row);
-	scr_memsetw(s, video_erase_char, 2*step);
+	s = (unsigned short *)(vc->vc_origin + vc->vc_size_row * t);
+	step = vc->vc_cols * nr;
+	scr_memmovew(s + step, s, (b - t - nr) * vc->vc_size_row);
+	scr_memsetw(s, vc->vc_video_erase_char, 2 * step);
 }
 
 static void do_update_region(struct vc_data *vc, unsigned long start, int count)
@@ -335,23 +327,23 @@
 #endif
 }
 
-void update_region(int currcons, unsigned long start, int count)
+void update_region(struct vc_data *vc, unsigned long start, int count)
 {
 	WARN_CONSOLE_UNLOCKED();
 
-	if (DO_UPDATE) {
-		hide_cursor(vc_cons[currcons].d);
-		do_update_region(vc_cons[currcons].d, start, count);
-		set_cursor(vc_cons[currcons].d);
+	if (DO_UPDATE(vc)) {
+		hide_cursor(vc);
+		do_update_region(vc, start, count);
+		set_cursor(vc);
 	}
 }
 
 /* Structure of attributes is hardware-dependent */
 
-static u8 build_attr(int currcons, u8 _color, u8 _intensity, u8 _blink, u8 _underline, u8 _reverse)
+static u8 build_attr(struct vc_data *vc, u8 _color, u8 _intensity, u8 _blink, u8 _underline, u8 _reverse)
 {
-	if (sw->con_build_attr)
-		return sw->con_build_attr(vc_cons[currcons].d, _color, _intensity, _blink, _underline, _reverse);
+	if (vc->vc_sw->con_build_attr)
+		return vc->vc_sw->con_build_attr(vc, _color, _intensity, _blink, _underline, _reverse);
 
 #ifndef VT_BUF_VRAM_ONLY
 /*
@@ -365,23 +357,23 @@
  *  Bit 7   : blink
  */
 	{
-	u8 a = color;
-	if (!vc_cons[currcons].d->vc_can_do_color)
+	u8 a = vc->vc_color;
+	if (!vc->vc_can_do_color)
 		return _intensity |
 		       (_underline ? 4 : 0) |
 		       (_reverse ? 8 : 0) |
 		       (_blink ? 0x80 : 0);
 	if (_underline)
-		a = (a & 0xf0) | ulcolor;
+		a = (a & 0xf0) | vc->vc_ulcolor;
 	else if (_intensity == 0)
-		a = (a & 0xf0) | halfcolor;
+		a = (a & 0xf0) | vc->vc_ulcolor;
 	if (_reverse)
 		a = ((a) & 0x88) | ((((a) >> 4) | ((a) << 4)) & 0x77);
 	if (_blink)
 		a ^= 0x80;
 	if (_intensity == 2)
 		a ^= 0x08;
-	if (hi_font_mask == 0x100)
+	if (vc->vc_hi_font_mask == 0x100)
 		a <<= 1;
 	return a;
 	}
@@ -390,10 +382,10 @@
 #endif
 }
 
-static void update_attr(int currcons)
+static void update_attr(struct vc_data *vc)
 {
-	attr = build_attr(currcons, color, intensity, blink, underline, reverse ^ decscnm);
-	video_erase_char = (build_attr(currcons, color, 1, blink, 0, decscnm) << 8) | ' ';
+	vc->vc_attr = build_attr(vc, vc->vc_color, vc->vc_intensity, vc->vc_blink, vc->vc_underline, vc->vc_reverse ^ vc->vc_decscnm);
+	vc->vc_video_erase_char = (build_attr(vc, vc->vc_color, 1, vc->vc_blink, 0, vc->vc_decscnm) << 8) | ' ';
 }
 
 /* Note: inverting the screen twice should revert to the original state */
@@ -437,7 +429,7 @@
 		}
 	}
 #endif
-	if (DO_UPDATE_VC(vc))
+	if (DO_UPDATE(vc))
 		do_update_region(vc, (unsigned long) p, count);
 }
 
@@ -452,7 +444,7 @@
 
 	if (p) {
 		scr_writew(old, p);
-		if (DO_UPDATE_VC(vc))
+		if (DO_UPDATE(vc))
 			vc->vc_sw->con_putc(vc, old, oldy, oldx);
 	}
 	if (offset == -1)
@@ -463,7 +455,7 @@
 		old = scr_readw(p);
 		new = old ^ vc->vc_complement_mask;
 		scr_writew(new, p);
-		if (DO_UPDATE_VC(vc)) {
+		if (DO_UPDATE(vc)) {
 			oldx = (offset >> 1) % vc->vc_cols;
 			oldy = (offset >> 1) / vc->vc_cols;
 			vc->vc_sw->con_putc(vc, new, oldy, oldx);
@@ -471,48 +463,46 @@
 	}
 }
 
-static void insert_char(int currcons, unsigned int nr)
+static void insert_char(struct vc_data *vc, unsigned int nr)
 {
-	unsigned short *p, *q = (unsigned short *) pos;
+	unsigned short *p, *q = (unsigned short *)vc->vc_pos;
 
-	p = q + vc_cons[currcons].d->vc_cols - nr - x;
+	p = q + vc->vc_cols - nr - vc->vc_x;
 	while (--p >= q)
 		scr_writew(scr_readw(p), p + nr);
-	scr_memsetw(q, video_erase_char, nr*2);
-	need_wrap = 0;
-	if (DO_UPDATE) {
-		unsigned short oldattr = attr;
-		sw->con_bmove(vc_cons[currcons].d,y,x,y,x+nr,1,
-			      vc_cons[currcons].d->vc_cols-x-nr);
-		attr = video_erase_char >> 8;
+	scr_memsetw(q, vc->vc_video_erase_char, nr * 2);
+	vc->vc_need_wrap = 0;
+	if (DO_UPDATE(vc)) {
+		unsigned short oldattr = vc->vc_attr;
+		vc->vc_sw->con_bmove(vc, vc->vc_y, vc->vc_x, vc->vc_y, vc->vc_x + nr, 1,
+				     vc->vc_cols - vc->vc_x - nr);
+		vc->vc_attr = vc->vc_video_erase_char >> 8;
 		while (nr--)
-			sw->con_putc(vc_cons[currcons].d,
-				     video_erase_char,y,x+nr);
-		attr = oldattr;
+			vc->vc_sw->con_putc(vc, vc->vc_video_erase_char, vc->vc_y, vc->vc_x + nr);
+		vc->vc_attr = oldattr;
 	}
 }
 
-static void delete_char(int currcons, unsigned int nr)
+static void delete_char(struct vc_data *vc, unsigned int nr)
 {
-	unsigned int i = x;
-	unsigned short *p = (unsigned short *) pos;
+	unsigned int i = vc->vc_x;
+	unsigned short *p = (unsigned short *)vc->vc_pos;
 
-	while (++i <= vc_cons[currcons].d->vc_cols - nr) {
+	while (++i <= vc->vc_cols - nr) {
 		scr_writew(scr_readw(p+nr), p);
 		p++;
 	}
-	scr_memsetw(p, video_erase_char, nr*2);
-	need_wrap = 0;
-	if (DO_UPDATE) {
-		unsigned short oldattr = attr;
-		sw->con_bmove(vc_cons[currcons].d, y, x+nr, y, x, 1,
-			      vc_cons[currcons].d->vc_cols-x-nr);
-		attr = video_erase_char >> 8;
+	scr_memsetw(p, vc->vc_video_erase_char, nr * 2);
+	vc->vc_need_wrap = 0;
+	if (DO_UPDATE(vc)) {
+		unsigned short oldattr = vc->vc_attr;
+		vc->vc_sw->con_bmove(vc, vc->vc_y, vc->vc_x + nr, vc->vc_y, vc->vc_x, 1,
+				     vc->vc_cols - vc->vc_x - nr);
+		vc->vc_attr = vc->vc_video_erase_char >> 8;
 		while (nr--)
-			sw->con_putc(vc_cons[currcons].d,
-				     video_erase_char, y,
-				     vc_cons[currcons].d->vc_cols-1-nr);
-		attr = oldattr;
+			vc->vc_sw->con_putc(vc, vc->vc_video_erase_char, vc->vc_y,
+				     vc->vc_cols - 1 - nr);
+		vc->vc_attr = oldattr;
 	}
 }
 
@@ -531,7 +521,7 @@
 	if ((type & 0x20) && ((softcursor_original & 0x7000) == (i & 0x7000))) i ^= 0x7000;
 	if ((type & 0x40) && ((i & 0x700) == ((i & 0x7000) >> 4))) i ^= 0x0700;
 	scr_writew(i, (u16 *) vc->vc_pos);
-	if (DO_UPDATE_VC(vc))
+	if (DO_UPDATE(vc))
 		vc->vc_sw->con_putc(vc, i, vc->vc_y, vc->vc_x);
 }
 
@@ -539,7 +529,7 @@
 {
 	if (softcursor_original != -1) {
 		scr_writew(softcursor_original, (u16 *)vc->vc_pos);
-		if (DO_UPDATE_VC(vc))
+		if (DO_UPDATE(vc))
 			vc->vc_sw->con_putc(vc, softcursor_original,
 					vc->vc_y, vc->vc_x);
 		softcursor_original = -1;
@@ -556,8 +546,8 @@
 
 static void set_cursor(struct vc_data *vc)
 {
-	if (!IS_FG_VC(vc) || console_blanked ||
-	    vc->vc_vt->vc_mode == KD_GRAPHICS)
+	if (!IS_FG(vc) || console_blanked ||
+	    vc->vc_mode == KD_GRAPHICS)
 		return;
 	if (vc->vc_deccm) {
 		if (vc == sel_cons)
@@ -569,98 +559,93 @@
 		hide_cursor(vc);
 }
 
-static void set_origin(int currcons)
+static void set_origin(struct vc_data *vc)
 {
 	WARN_CONSOLE_UNLOCKED();
 
-	if (!IS_VISIBLE ||
-	    !sw->con_set_origin ||
-	    !sw->con_set_origin(vc_cons[currcons].d))
-		origin = (unsigned long) screenbuf;
-	visible_origin = origin;
-	scr_end = origin + screenbuf_size;
-	pos = origin + vc_cons[currcons].d->vc_size_row*y + 2*x;
+	if (!CON_IS_VISIBLE(vc) ||
+	    !vc->vc_sw->con_set_origin ||
+	    !vc->vc_sw->con_set_origin(vc))
+		vc->vc_origin = (unsigned long)vc->vc_screenbuf;
+	vc->vc_visible_origin = vc->vc_origin;
+	vc->vc_scr_end = vc->vc_origin + vc->vc_screenbuf_size;
+	vc->vc_pos = vc->vc_origin + vc->vc_size_row * vc->vc_y + 2 * vc->vc_x;
 }
 
-static inline void save_screen(int currcons)
+static inline void save_screen(struct vc_data *vc)
 {
 	WARN_CONSOLE_UNLOCKED();
 
-	if (sw->con_save_screen)
-		sw->con_save_screen(vc_cons[currcons].d);
+	if (vc->vc_sw->con_save_screen)
+		vc->vc_sw->con_save_screen(vc);
 }
 
 /*
  *	Redrawing of screen
  */
 
-static void clear_buffer_attributes(int currcons)
+static void clear_buffer_attributes(struct vc_data *vc)
 {
-	unsigned short *p = (unsigned short *) origin;
-	int count = screenbuf_size/2;
-	int mask = hi_font_mask | 0xff;
+	unsigned short *p = (unsigned short *)vc->vc_origin;
+	int count = vc->vc_screenbuf_size / 2;
+	int mask = vc->vc_hi_font_mask | 0xff;
 
 	for (; count > 0; count--, p++) {
-		scr_writew((scr_readw(p)&mask) | (video_erase_char&~mask), p);
+		scr_writew((scr_readw(p)&mask) | (vc->vc_video_erase_char & ~mask), p);
 	}
 }
 
-void redraw_screen(int new_console, int is_switch)
+void redraw_screen(struct vc_data *vc, int is_switch)
 {
-	int redraw = 1;
-	int currcons, old_console;
+	int redraw = 0;
 
 	WARN_CONSOLE_UNLOCKED();
 
-	if (!vc_cons_allocated(new_console)) {
+	if (!vc) {
 		/* strange ... */
 		/* printk("redraw_screen: tty %d not allocated ??\n", new_console+1); */
 		return;
 	}
 
 	if (is_switch) {
-		currcons = fg_console;
-		hide_cursor(vc_cons[currcons].d);
-		if (fg_console != new_console) {
-			struct vc_data **display = vc_cons[new_console].d->vc_display_fg;
-			old_console = (*display) ? (*display)->vc_num : fg_console;
-			*display = vc_cons[new_console].d;
-			fg_console = new_console;
-			currcons = old_console;
-			if (!IS_VISIBLE) {
-				save_screen(currcons);
-				set_origin(currcons);
-			}
-			currcons = new_console;
-			if (old_console == new_console)
-				redraw = 0;
+		struct vc_data *old_vc = vc_cons[fg_console].d;
+		if (old_vc == vc)
+			return;
+		if (!CON_IS_VISIBLE(vc))
+			redraw = 1;
+		*vc->vc_display_fg = vc;
+		fg_console = vc->vc_num;
+		hide_cursor(old_vc);
+		if (!CON_IS_VISIBLE(old_vc)) {
+			save_screen(old_vc);
+			set_origin(old_vc);
 		}
 	} else {
-		currcons = new_console;
-		hide_cursor(vc_cons[currcons].d);
+		hide_cursor(vc);
+		redraw = 1;
 	}
 
 	if (redraw) {
 		int update;
-		int old_was_color = vc_cons[currcons].d->vc_can_do_color;
+		int old_was_color = vc->vc_can_do_color;
 
-		set_origin(currcons);
-		update = sw->con_switch(vc_cons[currcons].d);
-		set_palette(currcons);
+		set_origin(vc);
+		update = vc->vc_sw->con_switch(vc);
+		set_palette(vc);
 		/*
 		 * If console changed from mono<->color, the best we can do
 		 * is to clear the buffer attributes. As it currently stands,
 		 * rebuilding new attributes from the old buffer is not doable
 		 * without overly complex code.
 		 */
-		if (old_was_color != vc_cons[currcons].d->vc_can_do_color) {
-			update_attr(currcons);
-			clear_buffer_attributes(currcons);
+		if (old_was_color != vc->vc_can_do_color) {
+			update_attr(vc);
+			clear_buffer_attributes(vc);
 		}
-		if (update && vcmode != KD_GRAPHICS)
-			do_update_region(vc_cons[currcons].d, origin, screenbuf_size/2);
+		if (update && vc->vc_mode != KD_GRAPHICS)
+			do_update_region(vc, vc->vc_origin, vc->vc_screenbuf_size / 2);
 	}
-	set_cursor(vc_cons[currcons].d);
+	set_cursor(vc);
 	if (is_switch) {
 		set_leds();
 		compute_shiftstate();
@@ -676,31 +661,30 @@
 	return (i < MAX_NR_CONSOLES && vc_cons[i].d);
 }
 
-static void visual_init(int currcons, int init)
+static void visual_init(struct vc_data *vc, int num, int init)
 {
-    /* ++Geert: sw->con_init determines console size */
-    if (sw)
-	module_put(sw->owner);
-    sw = conswitchp;
+	/* ++Geert: vc->vc_sw->con_init determines console size */
+	if (vc->vc_sw)
+		module_put(vc->vc_sw->owner);
+	vc->vc_sw = conswitchp;
 #ifndef VT_SINGLE_DRIVER
-    if (con_driver_map[currcons])
-	sw = con_driver_map[currcons];
+	if (con_driver_map[num])
+		vc->vc_sw = con_driver_map[num];
 #endif
-    __module_get(sw->owner);
-    cons_num = currcons;
-    display_fg = &master_display_fg;
-    vc_cons[currcons].d->vc_uni_pagedir_loc = &vc_cons[currcons].d->vc_uni_pagedir;
-    vc_cons[currcons].d->vc_uni_pagedir = 0;
-    hi_font_mask = 0;
-    complement_mask = 0;
-    vc_cons[currcons].d->vc_can_do_color = 0;
-    sw->con_init(vc_cons[currcons].d, init);
-    if (!complement_mask)
-        complement_mask =
-		vc_cons[currcons].d->vc_can_do_color ? 0x7700 : 0x0800;
-    s_complement_mask = complement_mask;
-    vc_cons[currcons].d->vc_size_row = vc_cons[currcons].d->vc_cols<<1;
-    screenbuf_size = vc_cons[currcons].d->vc_rows * vc_cons[currcons].d->vc_size_row;
+	__module_get(vc->vc_sw->owner);
+	vc->vc_num = num;
+	vc->vc_display_fg = &master_display_fg;
+	vc->vc_uni_pagedir_loc = &vc->vc_uni_pagedir;
+	vc->vc_uni_pagedir = 0;
+	vc->vc_hi_font_mask = 0;
+	vc->vc_complement_mask = 0;
+	vc->vc_can_do_color = 0;
+	vc->vc_sw->con_init(vc, init);
+	if (!vc->vc_complement_mask)
+		vc->vc_complement_mask = vc->vc_can_do_color ? 0x7700 : 0x0800;
+	vc->vc_s_complement_mask = vc->vc_complement_mask;
+	vc->vc_size_row = vc->vc_cols << 1;
+	vc->vc_screenbuf_size = vc->vc_rows * vc->vc_size_row;
 }
 
 int vc_allocate(unsigned int currcons)	/* return 0 on success */
@@ -710,7 +694,7 @@
 	if (currcons >= MAX_NR_CONSOLES)
 		return -ENXIO;
 	if (!vc_cons[currcons].d) {
-	    long p, q;
+	    struct vc_data *vc;
 
 	    /* prevent users from taking too much memory */
 	    if (currcons >= MAX_NR_USER_CONSOLES && !capable(CAP_SYS_RESOURCE))
@@ -722,26 +706,22 @@
 	    /* although the numbers above are not valid since long ago, the
 	       point is still up-to-date and the comment still has its value
 	       even if only as a historical artifact.  --mj, July 1998 */
-	    p = (long) kmalloc(structsize, GFP_KERNEL);
-	    if (!p)
+	    vc = kmalloc(sizeof(struct vc_data), GFP_KERNEL);
+	    if (!vc)
 		return -ENOMEM;
-	    memset((void *)p, 0, structsize);
-	    vc_cons[currcons].d = (struct vc_data *)p;
-	    vt_cons[currcons] = (struct vt_struct *)(p+sizeof(struct vc_data));
-	    vc_cons[currcons].d->vc_vt = vt_cons[currcons];
-	    visual_init(currcons, 1);
-	    if (!*vc_cons[currcons].d->vc_uni_pagedir_loc)
-		con_set_default_unimap(currcons);
-	    q = (long)kmalloc(screenbuf_size, GFP_KERNEL);
-	    if (!q) {
-		kfree((char *) p);
+	    memset(vc, 0, sizeof(*vc));
+	    vc_cons[currcons].d = vc;
+	    visual_init(vc, currcons, 1);
+	    if (!*vc->vc_uni_pagedir_loc)
+		con_set_default_unimap(vc);
+	    vc->vc_screenbuf = kmalloc(vc->vc_screenbuf_size, GFP_KERNEL);
+	    if (!vc->vc_screenbuf) {
+		kfree(vc);
 		vc_cons[currcons].d = NULL;
-		vt_cons[currcons] = NULL;
 		return -ENOMEM;
 	    }
-	    screenbuf = (unsigned short *) q;
-	    kmalloced = 1;
-	    vc_init(currcons, vc_cons[currcons].d->vc_rows, vc_cons[currcons].d->vc_cols, 1);
+	    vc->vc_kmalloced = 1;
+	    vc_init(vc, vc->vc_rows, vc->vc_cols, 1);
 
 	    if (!pm_con) {
 		    pm_con = pm_register(PM_SYS_DEV,
@@ -752,13 +732,13 @@
 	return 0;
 }
 
-inline int resize_screen(int currcons, int width, int height)
+inline int resize_screen(struct vc_data *vc, int width, int height)
 {
 	/* Resizes the resolution of the display adapater */
 	int err = 0;
 
-	if (vcmode != KD_GRAPHICS && sw->con_resize)
-		err = sw->con_resize(vc_cons[currcons].d, width, height);
+	if (vc->vc_mode != KD_GRAPHICS && vc->vc_sw->con_resize)
+		err = vc->vc_sw->con_resize(vc, width, height);
 	return err;
 }
 
@@ -769,7 +749,7 @@
  */
 #define VC_RESIZE_MAXCOL (32767)
 #define VC_RESIZE_MAXROW (32767)
-int vc_resize(int currcons, unsigned int cols, unsigned int lines)
+int vc_resize(struct vc_data *vc, unsigned int cols, unsigned int lines)
 {
 	unsigned long old_origin, new_origin, new_scr_end, rlth, rrem, err = 0;
 	unsigned int old_cols, old_rows, old_row_size, old_screen_size;
@@ -778,87 +758,87 @@
 
 	WARN_CONSOLE_UNLOCKED();
 
-	if (!vc_cons_allocated(currcons))
+	if (!vc)
 		return -ENXIO;
 
 	if (cols > VC_RESIZE_MAXCOL || lines > VC_RESIZE_MAXROW)
 		return -EINVAL;
 
-	new_cols = (cols ? cols : vc_cons[currcons].d->vc_cols);
-	new_rows = (lines ? lines : vc_cons[currcons].d->vc_rows);
+	new_cols = (cols ? cols : vc->vc_cols);
+	new_rows = (lines ? lines : vc->vc_rows);
 	new_row_size = new_cols << 1;
 	new_screen_size = new_row_size * new_rows;
 
-	if (new_cols == vc_cons[currcons].d->vc_cols && new_rows == vc_cons[currcons].d->vc_rows)
+	if (new_cols == vc->vc_cols && new_rows == vc->vc_rows)
 		return 0;
 
 	newscreen = (unsigned short *) kmalloc(new_screen_size, GFP_USER);
 	if (!newscreen)
 		return -ENOMEM;
 
-	old_rows = vc_cons[currcons].d->vc_rows;
-	old_cols = vc_cons[currcons].d->vc_cols;
-	old_row_size = vc_cons[currcons].d->vc_size_row;
-	old_screen_size = screenbuf_size;
+	old_rows = vc->vc_rows;
+	old_cols = vc->vc_cols;
+	old_row_size = vc->vc_size_row;
+	old_screen_size = vc->vc_screenbuf_size;
 
-	err = resize_screen(currcons, new_cols, new_rows);
+	err = resize_screen(vc, new_cols, new_rows);
 	if (err) {
 		kfree(newscreen);
 		return err;
 	}
 
-	vc_cons[currcons].d->vc_rows = new_rows;
-	vc_cons[currcons].d->vc_cols = new_cols;
-	vc_cons[currcons].d->vc_size_row = new_row_size;
-	screenbuf_size = new_screen_size;
+	vc->vc_rows = new_rows;
+	vc->vc_cols = new_cols;
+	vc->vc_size_row = new_row_size;
+	vc->vc_screenbuf_size = new_screen_size;
 
 	rlth = min(old_row_size, new_row_size);
 	rrem = new_row_size - rlth;
-	old_origin = origin;
+	old_origin = vc->vc_origin;
 	new_origin = (long) newscreen;
 	new_scr_end = new_origin + new_screen_size;
 	if (new_rows < old_rows)
 		old_origin += (old_rows - new_rows) * old_row_size;
 
-	update_attr(currcons);
+	update_attr(vc);
 
-	while (old_origin < scr_end) {
+	while (old_origin < vc->vc_scr_end) {
 		scr_memcpyw((unsigned short *) new_origin, (unsigned short *) old_origin, rlth);
 		if (rrem)
-			scr_memsetw((void *)(new_origin + rlth), video_erase_char, rrem);
+			scr_memsetw((void *)(new_origin + rlth), vc->vc_video_erase_char, rrem);
 		old_origin += old_row_size;
 		new_origin += new_row_size;
 	}
 	if (new_scr_end > new_origin)
-		scr_memsetw((void *) new_origin, video_erase_char, new_scr_end - new_origin);
-	if (kmalloced)
-		kfree(screenbuf);
-	screenbuf = newscreen;
-	kmalloced = 1;
-	screenbuf_size = new_screen_size;
-	set_origin(currcons);
+		scr_memsetw((void *)new_origin, vc->vc_video_erase_char, new_scr_end - new_origin);
+	if (vc->vc_kmalloced)
+		kfree(vc->vc_screenbuf);
+	vc->vc_screenbuf = newscreen;
+	vc->vc_kmalloced = 1;
+	vc->vc_screenbuf_size = new_screen_size;
+	set_origin(vc);
 
 	/* do part of a reset_terminal() */
-	top = 0;
-	bottom = vc_cons[currcons].d->vc_rows;
-	gotoxy(vc_cons[currcons].d, x, y);
-	save_cur(currcons);
+	vc->vc_top = 0;
+	vc->vc_bottom = vc->vc_rows;
+	gotoxy(vc, vc->vc_x, vc->vc_y);
+	save_cur(vc);
 
-	if (vc_cons[currcons].d->vc_tty) {
-		struct winsize ws, *cws = &vc_cons[currcons].d->vc_tty->winsize;
+	if (vc->vc_tty) {
+		struct winsize ws, *cws = &vc->vc_tty->winsize;
 
 		memset(&ws, 0, sizeof(ws));
-		ws.ws_row = vc_cons[currcons].d->vc_rows;
-		ws.ws_col = vc_cons[currcons].d->vc_cols;
-		ws.ws_ypixel = video_scan_lines;
+		ws.ws_row = vc->vc_rows;
+		ws.ws_col = vc->vc_cols;
+		ws.ws_ypixel = vc->vc_scan_lines;
 		if ((ws.ws_row != cws->ws_row || ws.ws_col != cws->ws_col) &&
-		    vc_cons[currcons].d->vc_tty->pgrp > 0)
-			kill_pg(vc_cons[currcons].d->vc_tty->pgrp, SIGWINCH, 1);
+		    vc->vc_tty->pgrp > 0)
+			kill_pg(vc->vc_tty->pgrp, SIGWINCH, 1);
 		*cws = ws;
 	}
 
-	if (IS_VISIBLE)
-		update_screen(currcons);
+	if (CON_IS_VISIBLE(vc))
+		update_screen(vc);
 	return err;
 }
 
@@ -868,12 +848,13 @@
 	WARN_CONSOLE_UNLOCKED();
 
 	if (vc_cons_allocated(currcons)) {
-	    sw->con_deinit(vc_cons[currcons].d);
-	    if (kmalloced)
-		kfree(screenbuf);
-	    if (currcons >= MIN_NR_CONSOLES)
-		kfree(vc_cons[currcons].d);
-	    vc_cons[currcons].d = NULL;
+		struct vc_data *vc = vc_cons[currcons].d;
+		vc->vc_sw->con_deinit(vc);
+		if (vc->vc_kmalloced)
+			kfree(vc->vc_screenbuf);
+		if (currcons >= MIN_NR_CONSOLES)
+			kfree(vc);
+		vc_cons[currcons].d = NULL;
 	}
 }
 
@@ -881,9 +862,9 @@
  *	VT102 emulator
  */
 
-#define set_kbd(x) set_vc_kbd_mode(kbd_table+currcons,x)
-#define clr_kbd(x) clr_vc_kbd_mode(kbd_table+currcons,x)
-#define is_kbd(x) vc_kbd_mode(kbd_table+currcons,x)
+#define set_kbd(vc, x)	set_vc_kbd_mode(kbd_table + (vc)->vc_num, (x))
+#define clr_kbd(vc, x)	clr_vc_kbd_mode(kbd_table + (vc)->vc_num, (x))
+#define is_kbd(vc, x)	vc_kbd_mode(kbd_table + (vc)->vc_num, (x))
 
 #define decarm		VC_REPEAT
 #define decckm		VC_CKMODE
@@ -943,272 +924,268 @@
 }
 
 /* for absolute user moves, when decom is set */
-static void gotoxay(int currcons, int new_x, int new_y)
+static void gotoxay(struct vc_data *vc, int new_x, int new_y)
 {
-	gotoxy(vc_cons[currcons].d, new_x, decom ? (top+new_y) : new_y);
+	gotoxy(vc, new_x, vc->vc_decom ? (vc->vc_top + new_y) : new_y);
 }
 
-void scrollback(int lines)
+void scrollback(struct vc_data *vc, int lines)
 {
-	int currcons = fg_console;
-
 	if (!lines)
-		lines = vc_cons[currcons].d->vc_rows/2;
+		lines = vc->vc_rows / 2;
 	scrolldelta(-lines);
 }
 
-void scrollfront(int lines)
+void scrollfront(struct vc_data *vc, int lines)
 {
-	int currcons = fg_console;
-
 	if (!lines)
-		lines = vc_cons[currcons].d->vc_rows/2;
+		lines = vc->vc_rows / 2;
 	scrolldelta(lines);
 }
 
-static void lf(int currcons)
+static void lf(struct vc_data *vc)
 {
     	/* don't scroll if above bottom of scrolling region, or
 	 * if below scrolling region
 	 */
-    	if (y+1 == bottom)
-		scrup(currcons,top,bottom,1);
-	else if (y < vc_cons[currcons].d->vc_rows-1) {
-	    	y++;
-		pos += vc_cons[currcons].d->vc_size_row;
+    	if (vc->vc_y + 1 == vc->vc_bottom)
+		scrup(vc, vc->vc_top, vc->vc_bottom, 1);
+	else if (vc->vc_y < vc->vc_rows - 1) {
+	    	vc->vc_y++;
+		vc->vc_pos += vc->vc_size_row;
 	}
-	need_wrap = 0;
+	vc->vc_need_wrap = 0;
 }
 
-static void ri(int currcons)
+static void ri(struct vc_data *vc)
 {
     	/* don't scroll if below top of scrolling region, or
 	 * if above scrolling region
 	 */
-	if (y == top)
-		scrdown(currcons,top,bottom,1);
-	else if (y > 0) {
-		y--;
-		pos -= vc_cons[currcons].d->vc_size_row;
+	if (vc->vc_y == vc->vc_top)
+		scrdown(vc, vc->vc_top, vc->vc_bottom, 1);
+	else if (vc->vc_y > 0) {
+		vc->vc_y--;
+		vc->vc_pos -= vc->vc_size_row;
 	}
-	need_wrap = 0;
+	vc->vc_need_wrap = 0;
 }
 
-static inline void cr(int currcons)
+static inline void cr(struct vc_data *vc)
 {
-	pos -= x<<1;
-	need_wrap = x = 0;
+	vc->vc_pos -= vc->vc_x << 1;
+	vc->vc_need_wrap = vc->vc_x = 0;
 }
 
-static inline void bs(int currcons)
+static inline void bs(struct vc_data *vc)
 {
-	if (x) {
-		pos -= 2;
-		x--;
-		need_wrap = 0;
+	if (vc->vc_x) {
+		vc->vc_pos -= 2;
+		vc->vc_x--;
+		vc->vc_need_wrap = 0;
 	}
 }
 
-static inline void del(int currcons)
+static inline void del(struct vc_data *vc)
 {
 	/* ignored */
 }
 
-static void csi_J(int currcons, int vpar)
+static void csi_J(struct vc_data *vc, int vpar)
 {
 	unsigned int count;
 	unsigned short * start;
 
 	switch (vpar) {
 		case 0:	/* erase from cursor to end of display */
-			count = (scr_end-pos)>>1;
-			start = (unsigned short *) pos;
-			if (DO_UPDATE) {
+			count = (vc->vc_scr_end - vc->vc_pos) >> 1;
+			start = (unsigned short *)vc->vc_pos;
+			if (DO_UPDATE(vc)) {
 				/* do in two stages */
-				sw->con_clear(vc_cons[currcons].d, y, x, 1,
-					      vc_cons[currcons].d->vc_cols-x);
-				sw->con_clear(vc_cons[currcons].d, y+1, 0,
-					      vc_cons[currcons].d->vc_rows-y-1,
-					      vc_cons[currcons].d->vc_cols);
+				vc->vc_sw->con_clear(vc, vc->vc_y, vc->vc_x, 1,
+					      vc->vc_cols - vc->vc_x);
+				vc->vc_sw->con_clear(vc, vc->vc_y + 1, 0,
+					      vc->vc_rows - vc->vc_y - 1,
+					      vc->vc_cols);
 			}
 			break;
 		case 1:	/* erase from start to cursor */
-			count = ((pos-origin)>>1)+1;
-			start = (unsigned short *) origin;
-			if (DO_UPDATE) {
+			count = ((vc->vc_pos - vc->vc_origin) >> 1) + 1;
+			start = (unsigned short *)vc->vc_origin;
+			if (DO_UPDATE(vc)) {
 				/* do in two stages */
-				sw->con_clear(vc_cons[currcons].d, 0, 0, y,
-					      vc_cons[currcons].d->vc_cols);
-				sw->con_clear(vc_cons[currcons].d, y, 0, 1,
-					      x + 1);
+				vc->vc_sw->con_clear(vc, 0, 0, vc->vc_y,
+					      vc->vc_cols);
+				vc->vc_sw->con_clear(vc, vc->vc_y, 0, 1,
+					      vc->vc_x + 1);
 			}
 			break;
 		case 2: /* erase whole display */
-			count = vc_cons[currcons].d->vc_cols * vc_cons[currcons].d->vc_rows;
-			start = (unsigned short *) origin;
-			if (DO_UPDATE)
-				sw->con_clear(vc_cons[currcons].d, 0, 0,
-					      vc_cons[currcons].d->vc_rows,
-					      vc_cons[currcons].d->vc_cols);
+			count = vc->vc_cols * vc->vc_rows;
+			start = (unsigned short *)vc->vc_origin;
+			if (DO_UPDATE(vc))
+				vc->vc_sw->con_clear(vc, 0, 0,
+					      vc->vc_rows,
+					      vc->vc_cols);
 			break;
 		default:
 			return;
 	}
-	scr_memsetw(start, video_erase_char, 2*count);
-	need_wrap = 0;
+	scr_memsetw(start, vc->vc_video_erase_char, 2 * count);
+	vc->vc_need_wrap = 0;
 }
 
-static void csi_K(int currcons, int vpar)
+static void csi_K(struct vc_data *vc, int vpar)
 {
 	unsigned int count;
 	unsigned short * start;
 
 	switch (vpar) {
 		case 0:	/* erase from cursor to end of line */
-			count = vc_cons[currcons].d->vc_cols-x;
-			start = (unsigned short *) pos;
-			if (DO_UPDATE)
-				sw->con_clear(vc_cons[currcons].d, y, x, 1,
-					      vc_cons[currcons].d->vc_cols-x);
+			count = vc->vc_cols - vc->vc_x;
+			start = (unsigned short *)vc->vc_pos;
+			if (DO_UPDATE(vc))
+				vc->vc_sw->con_clear(vc, vc->vc_y, vc->vc_x, 1,
+						     vc->vc_cols - vc->vc_x);
 			break;
 		case 1:	/* erase from start of line to cursor */
-			start = (unsigned short *) (pos - (x<<1));
-			count = x+1;
-			if (DO_UPDATE)
-				sw->con_clear(vc_cons[currcons].d, y, 0, 1,
-					      x + 1);
+			start = (unsigned short *)(vc->vc_pos - (vc->vc_x << 1));
+			count = vc->vc_x + 1;
+			if (DO_UPDATE(vc))
+				vc->vc_sw->con_clear(vc, vc->vc_y, 0, 1,
+						     vc->vc_x + 1);
 			break;
 		case 2: /* erase whole line */
-			start = (unsigned short *) (pos - (x<<1));
-			count = vc_cons[currcons].d->vc_cols;
-			if (DO_UPDATE)
-				sw->con_clear(vc_cons[currcons].d, y, 0, 1,
-					      vc_cons[currcons].d->vc_cols);
+			start = (unsigned short *)(vc->vc_pos - (vc->vc_x << 1));
+			count = vc->vc_cols;
+			if (DO_UPDATE(vc))
+				vc->vc_sw->con_clear(vc, vc->vc_y, 0, 1,
+					      vc->vc_cols);
 			break;
 		default:
 			return;
 	}
-	scr_memsetw(start, video_erase_char, 2 * count);
-	need_wrap = 0;
+	scr_memsetw(start, vc->vc_video_erase_char, 2 * count);
+	vc->vc_need_wrap = 0;
 }
 
-static void csi_X(int currcons, int vpar) /* erase the following vpar positions */
+static void csi_X(struct vc_data *vc, int vpar) /* erase the following vpar positions */
 {					  /* not vt100? */
 	int count;
 
 	if (!vpar)
 		vpar++;
-	count = (vpar > vc_cons[currcons].d->vc_cols-x) ? (vc_cons[currcons].d->vc_cols-x) : vpar;
+	count = (vpar > vc->vc_cols - vc->vc_x) ? (vc->vc_cols - vc->vc_x) : vpar;
 
-	scr_memsetw((unsigned short *) pos, video_erase_char, 2 * count);
-	if (DO_UPDATE)
-		sw->con_clear(vc_cons[currcons].d, y, x, 1, count);
-	need_wrap = 0;
+	scr_memsetw((unsigned short *)vc->vc_pos, vc->vc_video_erase_char, 2 * count);
+	if (DO_UPDATE(vc))
+		vc->vc_sw->con_clear(vc, vc->vc_y, vc->vc_x, 1, count);
+	vc->vc_need_wrap = 0;
 }
 
-static void default_attr(int currcons)
+static void default_attr(struct vc_data *vc)
 {
-	intensity = 1;
-	underline = 0;
-	reverse = 0;
-	blink = 0;
-	color = def_color;
+	vc->vc_intensity = 1;
+	vc->vc_underline = 0;
+	vc->vc_reverse = 0;
+	vc->vc_blink = 0;
+	vc->vc_color = vc->vc_def_color;
 }
 
 /* console_sem is held */
-static void csi_m(int currcons)
+static void csi_m(struct vc_data *vc)
 {
 	int i;
 
-	for (i=0;i<=npar;i++)
-		switch (par[i]) {
+	for (i = 0; i <= vc->vc_npar; i++)
+		switch (vc->vc_par[i]) {
 			case 0:	/* all attributes off */
-				default_attr(currcons);
+				default_attr(vc);
 				break;
 			case 1:
-				intensity = 2;
+				vc->vc_intensity = 2;
 				break;
 			case 2:
-				intensity = 0;
+				vc->vc_intensity = 0;
 				break;
 			case 4:
-				underline = 1;
+				vc->vc_underline = 1;
 				break;
 			case 5:
-				blink = 1;
+				vc->vc_blink = 1;
 				break;
 			case 7:
-				reverse = 1;
+				vc->vc_reverse = 1;
 				break;
 			case 10: /* ANSI X3.64-1979 (SCO-ish?)
 				  * Select primary font, don't display
 				  * control chars if defined, don't set
 				  * bit 8 on output.
 				  */
-				translate = set_translate(charset == 0
-						? G0_charset
-						: G1_charset,currcons);
-				disp_ctrl = 0;
-				toggle_meta = 0;
+				vc->vc_translate = set_translate(vc->vc_charset == 0
+						? vc->vc_G0_charset
+						: vc->vc_G1_charset, vc);
+				vc->vc_disp_ctrl = 0;
+				vc->vc_toggle_meta = 0;
 				break;
 			case 11: /* ANSI X3.64-1979 (SCO-ish?)
 				  * Select first alternate font, lets
 				  * chars < 32 be displayed as ROM chars.
 				  */
-				translate = set_translate(IBMPC_MAP,currcons);
-				disp_ctrl = 1;
-				toggle_meta = 0;
+				vc->vc_translate = set_translate(IBMPC_MAP, vc);
+				vc->vc_disp_ctrl = 1;
+				vc->vc_toggle_meta = 0;
 				break;
 			case 12: /* ANSI X3.64-1979 (SCO-ish?)
 				  * Select second alternate font, toggle
 				  * high bit before displaying as ROM char.
 				  */
-				translate = set_translate(IBMPC_MAP,currcons);
-				disp_ctrl = 1;
-				toggle_meta = 1;
+				vc->vc_translate = set_translate(IBMPC_MAP, vc);
+				vc->vc_disp_ctrl = 1;
+				vc->vc_toggle_meta = 1;
 				break;
 			case 21:
 			case 22:
-				intensity = 1;
+				vc->vc_intensity = 1;
 				break;
 			case 24:
-				underline = 0;
+				vc->vc_underline = 0;
 				break;
 			case 25:
-				blink = 0;
+				vc->vc_blink = 0;
 				break;
 			case 27:
-				reverse = 0;
+				vc->vc_reverse = 0;
 				break;
 			case 38: /* ANSI X3.64-1979 (SCO-ish?)
 				  * Enables underscore, white foreground
 				  * with white underscore (Linux - use
 				  * default foreground).
 				  */
-				color = (def_color & 0x0f) | background;
-				underline = 1;
+				vc->vc_color = (vc->vc_def_color & 0x0f) | (vc->vc_color & 0xf0);
+				vc->vc_underline = 1;
 				break;
 			case 39: /* ANSI X3.64-1979 (SCO-ish?)
 				  * Disable underline option.
 				  * Reset colour to default? It did this
 				  * before...
 				  */
-				color = (def_color & 0x0f) | background;
-				underline = 0;
+				vc->vc_color = (vc->vc_def_color & 0x0f) | (vc->vc_color & 0xf0);
+				vc->vc_underline = 0;
 				break;
 			case 49:
-				color = (def_color & 0xf0) | foreground;
+				vc->vc_color = (vc->vc_def_color & 0xf0) | (vc->vc_color & 0x0f);
 				break;
 			default:
-				if (par[i] >= 30 && par[i] <= 37)
-					color = color_table[par[i]-30]
-						| background;
-				else if (par[i] >= 40 && par[i] <= 47)
-					color = (color_table[par[i]-40]<<4)
-						| foreground;
+				if (vc->vc_par[i] >= 30 && vc->vc_par[i] <= 37)
+					vc->vc_color = color_table[vc->vc_par[i] - 30]
+						| (vc->vc_color & 0xf0);
+				else if (vc->vc_par[i] >= 40 && vc->vc_par[i] <= 47)
+					vc->vc_color = (color_table[vc->vc_par[i] - 40] << 4)
+						| (vc->vc_color & 0x0f);
 				break;
 		}
-	update_attr(currcons);
+	update_attr(vc);
 }
 
 static void respond_string(const char *p, struct tty_struct *tty)
@@ -1220,11 +1197,11 @@
 	con_schedule_flip(tty);
 }
 
-static void cursor_report(int currcons, struct tty_struct *tty)
+static void cursor_report(struct vc_data *vc, struct tty_struct *tty)
 {
 	char buf[40];
 
-	sprintf(buf, "\033[%d;%dR", y + (decom ? top+1 : 1), x+1);
+	sprintf(buf, "\033[%d;%dR", vc->vc_y + (vc->vc_decom ? vc->vc_top + 1 : 1), vc->vc_x + 1);
 	respond_string(buf, tty);
 }
 
@@ -1250,130 +1227,132 @@
 /* invoked via ioctl(TIOCLINUX) and through set_selection */
 int mouse_reporting(void)
 {
-	int currcons = fg_console;
-
-	return report_mouse;
+	return vc_cons[fg_console].d->vc_report_mouse;
 }
 
 /* console_sem is held */
-static void set_mode(int currcons, int on_off)
+static void set_mode(struct vc_data *vc, int on_off)
 {
 	int i;
 
-	for (i=0; i<=npar; i++)
-		if (ques) switch(par[i]) {	/* DEC private modes set/reset */
+	for (i = 0; i <= vc->vc_npar; i++)
+		if (vc->vc_ques) {
+			switch(vc->vc_par[i]) {	/* DEC private modes set/reset */
 			case 1:			/* Cursor keys send ^[Ox/^[[x */
 				if (on_off)
-					set_kbd(decckm);
+					set_kbd(vc, decckm);
 				else
-					clr_kbd(decckm);
+					clr_kbd(vc, decckm);
 				break;
 			case 3:	/* 80/132 mode switch unimplemented */
-				deccolm = on_off;
+				vc->vc_deccolm = on_off;
 #if 0
-				(void) vc_resize(deccolm ? 132 : 80, vc_cons[currcons].d->vc_rows);
+				vc_resize(deccolm ? 132 : 80, vc->vc_rows);
 				/* this alone does not suffice; some user mode
 				   utility has to change the hardware regs */
 #endif
 				break;
 			case 5:			/* Inverted screen on/off */
-				if (decscnm != on_off) {
-					decscnm = on_off;
-					invert_screen(vc_cons[currcons].d, 0, screenbuf_size, 0);
-					update_attr(currcons);
+				if (vc->vc_decscnm != on_off) {
+					vc->vc_decscnm = on_off;
+					invert_screen(vc, 0, vc->vc_screenbuf_size, 0);
+					update_attr(vc);
 				}
 				break;
 			case 6:			/* Origin relative/absolute */
-				decom = on_off;
-				gotoxay(currcons,0,0);
+				vc->vc_decom = on_off;
+				gotoxay(vc, 0, 0);
 				break;
 			case 7:			/* Autowrap on/off */
-				decawm = on_off;
+				vc->vc_decawm = on_off;
 				break;
 			case 8:			/* Autorepeat on/off */
 				if (on_off)
-					set_kbd(decarm);
+					set_kbd(vc, decarm);
 				else
-					clr_kbd(decarm);
+					clr_kbd(vc, decarm);
 				break;
 			case 9:
-				report_mouse = on_off ? 1 : 0;
+				vc->vc_report_mouse = on_off ? 1 : 0;
 				break;
 			case 25:		/* Cursor on/off */
-				deccm = on_off;
+				vc->vc_deccm = on_off;
 				break;
 			case 1000:
-				report_mouse = on_off ? 2 : 0;
+				vc->vc_report_mouse = on_off ? 2 : 0;
 				break;
-		} else switch(par[i]) {		/* ANSI modes set/reset */
+			}
+		} else {
+			switch(vc->vc_par[i]) {	/* ANSI modes set/reset */
 			case 3:			/* Monitor (display ctrls) */
-				disp_ctrl = on_off;
+				vc->vc_disp_ctrl = on_off;
 				break;
 			case 4:			/* Insert Mode on/off */
-				decim = on_off;
+				vc->vc_decim = on_off;
 				break;
 			case 20:		/* Lf, Enter == CrLf/Lf */
 				if (on_off)
-					set_kbd(lnm);
+					set_kbd(vc, lnm);
 				else
-					clr_kbd(lnm);
+					clr_kbd(vc, lnm);
 				break;
+			}
 		}
 }
 
 /* console_sem is held */
-static void setterm_command(int currcons)
+static void setterm_command(struct vc_data *vc)
 {
-	switch(par[0]) {
+	switch(vc->vc_par[0]) {
 		case 1:	/* set color for underline mode */
-			if (vc_cons[currcons].d->vc_can_do_color &&
-					par[1] < 16) {
-				ulcolor = color_table[par[1]];
-				if (underline)
-					update_attr(currcons);
+			if (vc->vc_can_do_color &&
+					vc->vc_par[1] < 16) {
+				vc->vc_ulcolor = color_table[vc->vc_par[1]];
+				if (vc->vc_underline)
+					update_attr(vc);
 			}
 			break;
 		case 2:	/* set color for half intensity mode */
-			if (vc_cons[currcons].d->vc_can_do_color &&
-					par[1] < 16) {
-				halfcolor = color_table[par[1]];
-				if (intensity == 0)
-					update_attr(currcons);
+			if (vc->vc_can_do_color &&
+					vc->vc_par[1] < 16) {
+				vc->vc_halfcolor = color_table[vc->vc_par[1]];
+				if (vc->vc_intensity == 0)
+					update_attr(vc);
 			}
 			break;
 		case 8:	/* store colors as defaults */
-			def_color = attr;
-			if (hi_font_mask == 0x100)
-				def_color >>= 1;
-			default_attr(currcons);
-			update_attr(currcons);
+			vc->vc_def_color = vc->vc_attr;
+			if (vc->vc_hi_font_mask == 0x100)
+				vc->vc_def_color >>= 1;
+			default_attr(vc);
+			update_attr(vc);
 			break;
 		case 9:	/* set blanking interval */
-			blankinterval = ((par[1] < 60) ? par[1] : 60) * 60 * HZ;
+			blankinterval = ((vc->vc_par[1] < 60) ? vc->vc_par[1] : 60) * 60 * HZ;
 			poke_blanked_console();
 			break;
 		case 10: /* set bell frequency in Hz */
-			if (npar >= 1)
-				bell_pitch = par[1];
+			if (vc->vc_npar >= 1)
+				vc->vc_bell_pitch = vc->vc_par[1];
 			else
-				bell_pitch = DEFAULT_BELL_PITCH;
+				vc->vc_bell_pitch = DEFAULT_BELL_PITCH;
 			break;
 		case 11: /* set bell duration in msec */
-			if (npar >= 1)
-				bell_duration = (par[1] < 2000) ?
-					par[1]*HZ/1000 : 0;
+			if (vc->vc_npar >= 1)
+				vc->vc_bell_duration = (vc->vc_par[1] < 2000) ?
+					vc->vc_par[1] * HZ / 1000 : 0;
 			else
-				bell_duration = DEFAULT_BELL_DURATION;
+				vc->vc_bell_duration = DEFAULT_BELL_DURATION;
 			break;
 		case 12: /* bring specified console to the front */
-			if (par[1] >= 1 && vc_cons_allocated(par[1]-1))
-				set_console(par[1] - 1);
+			if (vc->vc_par[1] >= 1 && vc_cons_allocated(vc->vc_par[1] - 1))
+				set_console(vc->vc_par[1] - 1);
 			break;
 		case 13: /* unblank the screen */
 			poke_blanked_console();
 			break;
 		case 14: /* set vesa powerdown interval */
-			vesa_off_interval = ((par[1] < 60) ? par[1] : 60) * 60 * HZ;
+			vesa_off_interval = ((vc->vc_par[1] < 60) ? vc->vc_par[1] : 60) * 60 * HZ;
 			break;
 		case 15: /* activate the previous console */
 			set_console(last_console);
@@ -1382,77 +1361,77 @@
 }
 
 /* console_sem is held */
-static void csi_at(int currcons, unsigned int nr)
+static void csi_at(struct vc_data *vc, unsigned int nr)
 {
-	if (nr > vc_cons[currcons].d->vc_cols - x)
-		nr = vc_cons[currcons].d->vc_cols - x;
+	if (nr > vc->vc_cols - vc->vc_x)
+		nr = vc->vc_cols - vc->vc_x;
 	else if (!nr)
 		nr = 1;
-	insert_char(currcons, nr);
+	insert_char(vc, nr);
 }
 
 /* console_sem is held */
-static void csi_L(int currcons, unsigned int nr)
+static void csi_L(struct vc_data *vc, unsigned int nr)
 {
-	if (nr > vc_cons[currcons].d->vc_rows - y)
-		nr = vc_cons[currcons].d->vc_rows - y;
+	if (nr > vc->vc_rows - vc->vc_y)
+		nr = vc->vc_rows - vc->vc_y;
 	else if (!nr)
 		nr = 1;
-	scrdown(currcons,y,bottom,nr);
-	need_wrap = 0;
+	scrdown(vc, vc->vc_y, vc->vc_bottom, nr);
+	vc->vc_need_wrap = 0;
 }
 
 /* console_sem is held */
-static void csi_P(int currcons, unsigned int nr)
+static void csi_P(struct vc_data *vc, unsigned int nr)
 {
-	if (nr > vc_cons[currcons].d->vc_cols - x)
-		nr = vc_cons[currcons].d->vc_cols - x;
+	if (nr > vc->vc_cols - vc->vc_x)
+		nr = vc->vc_cols - vc->vc_x;
 	else if (!nr)
 		nr = 1;
-	delete_char(currcons, nr);
+	delete_char(vc, nr);
 }
 
 /* console_sem is held */
-static void csi_M(int currcons, unsigned int nr)
+static void csi_M(struct vc_data *vc, unsigned int nr)
 {
-	if (nr > vc_cons[currcons].d->vc_rows - y)
-		nr = vc_cons[currcons].d->vc_rows - y;
+	if (nr > vc->vc_rows - vc->vc_y)
+		nr = vc->vc_rows - vc->vc_y;
 	else if (!nr)
 		nr=1;
-	scrup(currcons,y,bottom,nr);
-	need_wrap = 0;
+	scrup(vc, vc->vc_y, vc->vc_bottom, nr);
+	vc->vc_need_wrap = 0;
 }
 
 /* console_sem is held (except via vc_init->reset_terminal */
-static void save_cur(int currcons)
+static void save_cur(struct vc_data *vc)
 {
-	saved_x		= x;
-	saved_y		= y;
-	s_intensity	= intensity;
-	s_underline	= underline;
-	s_blink		= blink;
-	s_reverse	= reverse;
-	s_charset	= charset;
-	s_color		= color;
-	saved_G0	= G0_charset;
-	saved_G1	= G1_charset;
+	vc->vc_saved_x		= vc->vc_x;
+	vc->vc_saved_y		= vc->vc_y;
+	vc->vc_s_intensity	= vc->vc_intensity;
+	vc->vc_s_underline	= vc->vc_underline;
+	vc->vc_s_blink		= vc->vc_blink;
+	vc->vc_s_reverse	= vc->vc_reverse;
+	vc->vc_s_charset	= vc->vc_charset;
+	vc->vc_s_color		= vc->vc_color;
+	vc->vc_saved_G0		= vc->vc_G0_charset;
+	vc->vc_saved_G1		= vc->vc_G1_charset;
 }
 
 /* console_sem is held */
-static void restore_cur(int currcons)
+static void restore_cur(struct vc_data *vc)
 {
-	gotoxy(vc_cons[currcons].d,saved_x,saved_y);
-	intensity	= s_intensity;
-	underline	= s_underline;
-	blink		= s_blink;
-	reverse		= s_reverse;
-	charset		= s_charset;
-	color		= s_color;
-	G0_charset	= saved_G0;
-	G1_charset	= saved_G1;
-	translate	= set_translate(charset ? G1_charset : G0_charset,currcons);
-	update_attr(currcons);
-	need_wrap = 0;
+	gotoxy(vc, vc->vc_saved_x, vc->vc_saved_y);
+	vc->vc_intensity	= vc->vc_s_intensity;
+	vc->vc_underline	= vc->vc_s_underline;
+	vc->vc_blink		= vc->vc_s_blink;
+	vc->vc_reverse		= vc->vc_s_reverse;
+	vc->vc_charset		= vc->vc_s_charset;
+	vc->vc_color		= vc->vc_s_color;
+	vc->vc_G0_charset	= vc->vc_saved_G0;
+	vc->vc_G1_charset	= vc->vc_saved_G1;
+	vc->vc_translate	= set_translate(vc->vc_charset ? vc->vc_G1_charset : vc->vc_G0_charset, vc);
+	update_attr(vc);
+	vc->vc_need_wrap = 0;
 }
 
 enum { ESnormal, ESesc, ESsquare, ESgetpars, ESgotpars, ESfunckey,
@@ -1460,64 +1439,64 @@
 	ESpalette };
 
 /* console_sem is held (except via vc_init()) */
-static void reset_terminal(int currcons, int do_clear)
+static void reset_terminal(struct vc_data *vc, int do_clear)
 {
-	top		= 0;
-	bottom		= vc_cons[currcons].d->vc_rows;
-	vc_state	= ESnormal;
-	ques		= 0;
-	translate	= set_translate(LAT1_MAP,currcons);
-	G0_charset	= LAT1_MAP;
-	G1_charset	= GRAF_MAP;
-	charset		= 0;
-	need_wrap	= 0;
-	report_mouse	= 0;
-	utf             = 0;
-	utf_count       = 0;
-
-	disp_ctrl	= 0;
-	toggle_meta	= 0;
-
-	decscnm		= 0;
-	decom		= 0;
-	decawm		= 1;
-	deccm		= 1;
-	decim		= 0;
-
-	set_kbd(decarm);
-	clr_kbd(decckm);
-	clr_kbd(kbdapplic);
-	clr_kbd(lnm);
-	kbd_table[currcons].lockstate = 0;
-	kbd_table[currcons].slockstate = 0;
-	kbd_table[currcons].ledmode = LED_SHOW_FLAGS;
-	kbd_table[currcons].ledflagstate = kbd_table[currcons].default_ledflagstate;
+	vc->vc_top		= 0;
+	vc->vc_bottom		= vc->vc_rows;
+	vc->vc_state		= ESnormal;
+	vc->vc_ques		= 0;
+	vc->vc_translate	= set_translate(LAT1_MAP, vc);
+	vc->vc_G0_charset	= LAT1_MAP;
+	vc->vc_G1_charset	= GRAF_MAP;
+	vc->vc_charset		= 0;
+	vc->vc_need_wrap	= 0;
+	vc->vc_report_mouse	= 0;
+	vc->vc_utf		= 0;
+	vc->vc_utf_count	= 0;
+
+	vc->vc_disp_ctrl	= 0;
+	vc->vc_toggle_meta	= 0;
+
+	vc->vc_decscnm		= 0;
+	vc->vc_decom		= 0;
+	vc->vc_decawm		= 1;
+	vc->vc_deccm		= 1;
+	vc->vc_decim		= 0;
+
+	set_kbd(vc, decarm);
+	clr_kbd(vc, decckm);
+	clr_kbd(vc, kbdapplic);
+	clr_kbd(vc, lnm);
+	kbd_table[vc->vc_num].lockstate = 0;
+	kbd_table[vc->vc_num].slockstate = 0;
+	kbd_table[vc->vc_num].ledmode = LED_SHOW_FLAGS;
+	kbd_table[vc->vc_num].ledflagstate = kbd_table[vc->vc_num].default_ledflagstate;
 	/* do not do set_leds here because this causes an endless tasklet loop
 	   when the keyboard hasn't been initialized yet */
 
-	cursor_type = CUR_DEFAULT;
-	complement_mask = s_complement_mask;
+	vc->vc_cursor_type = CUR_DEFAULT;
+	vc->vc_complement_mask = vc->vc_s_complement_mask;
 
-	default_attr(currcons);
-	update_attr(currcons);
+	default_attr(vc);
+	update_attr(vc);
 
-	tab_stop[0]	= 0x01010100;
-	tab_stop[1]	=
-	tab_stop[2]	=
-	tab_stop[3]	=
-	tab_stop[4]	= 0x01010101;
+	vc->vc_tab_stop[0]	= 0x01010100;
+	vc->vc_tab_stop[1]	=
+	vc->vc_tab_stop[2]	=
+	vc->vc_tab_stop[3]	=
+	vc->vc_tab_stop[4]	= 0x01010101;
 
-	bell_pitch = DEFAULT_BELL_PITCH;
-	bell_duration = DEFAULT_BELL_DURATION;
+	vc->vc_bell_pitch = DEFAULT_BELL_PITCH;
+	vc->vc_bell_duration = DEFAULT_BELL_DURATION;
 
-	gotoxy(vc_cons[currcons].d, 0, 0);
-	save_cur(currcons);
+	gotoxy(vc, 0, 0);
+	save_cur(vc);
 	if (do_clear)
-	    csi_J(currcons,2);
+	    csi_J(vc, 2);
 }
 
 /* console_sem is held */
-static void do_con_trol(struct tty_struct *tty, unsigned int currcons, int c)
+static void do_con_trol(struct tty_struct *tty, struct vc_data *vc, int c)
 {
 	/*
 	 *  Control characters can be used in the _middle_
@@ -1527,360 +1506,371 @@
 	case 0:
 		return;
 	case 7:
-		if (bell_duration)
-			kd_mksound(bell_pitch, bell_duration);
+		if (vc->vc_bell_duration)
+			kd_mksound(vc->vc_bell_pitch, vc->vc_bell_duration);
 		return;
 	case 8:
-		bs(currcons);
+		bs(vc);
 		return;
 	case 9:
-		pos -= (x << 1);
-		while (x < vc_cons[currcons].d->vc_cols - 1) {
-			x++;
-			if (tab_stop[x >> 5] & (1 << (x & 31)))
+		vc->vc_pos -= (vc->vc_x << 1);
+		while (vc->vc_x < vc->vc_cols - 1) {
+			vc->vc_x++;
+			if (vc->vc_tab_stop[vc->vc_x >> 5] & (1 << (vc->vc_x & 31)))
 				break;
 		}
-		pos += (x << 1);
+		vc->vc_pos += (vc->vc_x << 1);
 		return;
 	case 10: case 11: case 12:
-		lf(currcons);
-		if (!is_kbd(lnm))
+		lf(vc);
+		if (!is_kbd(vc, lnm))
 			return;
 	case 13:
-		cr(currcons);
+		cr(vc);
 		return;
 	case 14:
-		charset = 1;
-		translate = set_translate(G1_charset,currcons);
-		disp_ctrl = 1;
+		vc->vc_charset = 1;
+		vc->vc_translate = set_translate(vc->vc_G1_charset, vc);
+		vc->vc_disp_ctrl = 1;
 		return;
 	case 15:
-		charset = 0;
-		translate = set_translate(G0_charset,currcons);
-		disp_ctrl = 0;
+		vc->vc_charset = 0;
+		vc->vc_translate = set_translate(vc->vc_G0_charset, vc);
+		vc->vc_disp_ctrl = 0;
 		return;
 	case 24: case 26:
-		vc_state = ESnormal;
+		vc->vc_state = ESnormal;
 		return;
 	case 27:
-		vc_state = ESesc;
+		vc->vc_state = ESesc;
 		return;
 	case 127:
-		del(currcons);
+		del(vc);
 		return;
 	case 128+27:
-		vc_state = ESsquare;
+		vc->vc_state = ESsquare;
 		return;
 	}
-	switch(vc_state) {
+	switch(vc->vc_state) {
 	case ESesc:
-		vc_state = ESnormal;
+		vc->vc_state = ESnormal;
 		switch (c) {
 		case '[':
-			vc_state = ESsquare;
+			vc->vc_state = ESsquare;
 			return;
 		case ']':
-			vc_state = ESnonstd;
+			vc->vc_state = ESnonstd;
 			return;
 		case '%':
-			vc_state = ESpercent;
+			vc->vc_state = ESpercent;
 			return;
 		case 'E':
-			cr(currcons);
-			lf(currcons);
+			cr(vc);
+			lf(vc);
 			return;
 		case 'M':
-			ri(currcons);
+			ri(vc);
 			return;
 		case 'D':
-			lf(currcons);
+			lf(vc);
 			return;
 		case 'H':
-			tab_stop[x >> 5] |= (1 << (x & 31));
+			vc->vc_tab_stop[vc->vc_x >> 5] |= (1 << (vc->vc_x & 31));
 			return;
 		case 'Z':
 			respond_ID(tty);
 			return;
 		case '7':
-			save_cur(currcons);
+			save_cur(vc);
 			return;
 		case '8':
-			restore_cur(currcons);
+			restore_cur(vc);
 			return;
 		case '(':
-			vc_state = ESsetG0;
+			vc->vc_state = ESsetG0;
 			return;
 		case ')':
-			vc_state = ESsetG1;
+			vc->vc_state = ESsetG1;
 			return;
 		case '#':
-			vc_state = EShash;
+			vc->vc_state = EShash;
 			return;
 		case 'c':
-			reset_terminal(currcons,1);
+			reset_terminal(vc, 1);
 			return;
 		case '>':  /* Numeric keypad */
-			clr_kbd(kbdapplic);
+			clr_kbd(vc, kbdapplic);
 			return;
 		case '=':  /* Appl. keypad */
-			set_kbd(kbdapplic);
+			set_kbd(vc, kbdapplic);
 			return;
 		}
 		return;
 	case ESnonstd:
 		if (c=='P') {   /* palette escape sequence */
-			for (npar=0; npar<NPAR; npar++)
-				par[npar] = 0 ;
-			npar = 0 ;
-			vc_state = ESpalette;
+			for (vc->vc_npar = 0; vc->vc_npar < NPAR; vc->vc_npar++)
+				vc->vc_par[vc->vc_npar] = 0;
+			vc->vc_npar = 0;
+			vc->vc_state = ESpalette;
 			return;
 		} else if (c=='R') {   /* reset palette */
-			reset_palette(currcons);
-			vc_state = ESnormal;
+			reset_palette(vc);
+			vc->vc_state = ESnormal;
 		} else
-			vc_state = ESnormal;
+			vc->vc_state = ESnormal;
 		return;
 	case ESpalette:
 		if ( (c>='0'&&c<='9') || (c>='A'&&c<='F') || (c>='a'&&c<='f') ) {
-			par[npar++] = (c>'9' ? (c&0xDF)-'A'+10 : c-'0') ;
-			if (npar==7) {
-				int i = par[0]*3, j = 1;
-				palette[i] = 16*par[j++];
-				palette[i++] += par[j++];
-				palette[i] = 16*par[j++];
-				palette[i++] += par[j++];
-				palette[i] = 16*par[j++];
-				palette[i] += par[j];
-				set_palette(currcons);
-				vc_state = ESnormal;
+			vc->vc_par[vc->vc_npar++] = (c > '9' ? (c & 0xDF) - 'A' + 10 : c - '0');
+			if (vc->vc_npar == 7) {
+				int i = vc->vc_par[0] * 3, j = 1;
+				vc->vc_palette[i] = 16 * vc->vc_par[j++];
+				vc->vc_palette[i++] += vc->vc_par[j++];
+				vc->vc_palette[i] = 16 * vc->vc_par[j++];
+				vc->vc_palette[i++] += vc->vc_par[j++];
+				vc->vc_palette[i] = 16 * vc->vc_par[j++];
+				vc->vc_palette[i] += vc->vc_par[j];
+				set_palette(vc);
+				vc->vc_state = ESnormal;
 			}
 		} else
-			vc_state = ESnormal;
+			vc->vc_state = ESnormal;
 		return;
 	case ESsquare:
-		for(npar = 0 ; npar < NPAR ; npar++)
-			par[npar] = 0;
-		npar = 0;
-		vc_state = ESgetpars;
+		for (vc->vc_npar = 0; vc->vc_npar < NPAR; vc->vc_npar++)
+			vc->vc_par[vc->vc_npar] = 0;
+		vc->vc_npar = 0;
+		vc->vc_state = ESgetpars;
 		if (c == '[') { /* Function key */
-			vc_state=ESfunckey;
+			vc->vc_state=ESfunckey;
 			return;
 		}
-		ques = (c=='?');
-		if (ques)
+		vc->vc_ques = (c == '?');
+		if (vc->vc_ques)
 			return;
 	case ESgetpars:
-		if (c==';' && npar<NPAR-1) {
-			npar++;
+		if (c == ';' && vc->vc_npar < NPAR - 1) {
+			vc->vc_npar++;
 			return;
 		} else if (c>='0' && c<='9') {
-			par[npar] *= 10;
-			par[npar] += c-'0';
+			vc->vc_par[vc->vc_npar] *= 10;
+			vc->vc_par[vc->vc_npar] += c - '0';
 			return;
-		} else vc_state=ESgotpars;
+		} else
+			vc->vc_state = ESgotpars;
 	case ESgotpars:
-		vc_state = ESnormal;
+		vc->vc_state = ESnormal;
 		switch(c) {
 		case 'h':
-			set_mode(currcons,1);
+			set_mode(vc, 1);
 			return;
 		case 'l':
-			set_mode(currcons,0);
+			set_mode(vc, 0);
 			return;
 		case 'c':
-			if (ques) {
-				if (par[0])
-					cursor_type = par[0] | (par[1]<<8) | (par[2]<<16);
+			if (vc->vc_ques) {
+				if (vc->vc_par[0])
+					vc->vc_cursor_type = vc->vc_par[0] | (vc->vc_par[1] << 8) | (vc->vc_par[2] << 16);
 				else
-					cursor_type = CUR_DEFAULT;
+					vc->vc_cursor_type = CUR_DEFAULT;
 				return;
 			}
 			break;
 		case 'm':
-			if (ques) {
+			if (vc->vc_ques) {
 				clear_selection();
-				if (par[0])
-					complement_mask = par[0]<<8 | par[1];
+				if (vc->vc_par[0])
+					vc->vc_complement_mask = vc->vc_par[0] << 8 | vc->vc_par[1];
 				else
-					complement_mask = s_complement_mask;
+					vc->vc_complement_mask = vc->vc_s_complement_mask;
 				return;
 			}
 			break;
 		case 'n':
-			if (!ques) {
-				if (par[0] == 5)
+			if (!vc->vc_ques) {
+				if (vc->vc_par[0] == 5)
 					status_report(tty);
-				else if (par[0] == 6)
-					cursor_report(currcons,tty);
+				else if (vc->vc_par[0] == 6)
+					cursor_report(vc, tty);
 			}
 			return;
 		}
-		if (ques) {
-			ques = 0;
+		if (vc->vc_ques) {
+			vc->vc_ques = 0;
 			return;
 		}
 		switch(c) {
 		case 'G': case '`':
-			if (par[0]) par[0]--;
-			gotoxy(vc_cons[currcons].d, par[0], y);
+			if (vc->vc_par[0])
+				vc->vc_par[0]--;
+			gotoxy(vc, vc->vc_par[0], vc->vc_y);
 			return;
 		case 'A':
-			if (!par[0]) par[0]++;
-			gotoxy(vc_cons[currcons].d, x, y-par[0]);
+			if (!vc->vc_par[0])
+				vc->vc_par[0]++;
+			gotoxy(vc, vc->vc_x, vc->vc_y - vc->vc_par[0]);
 			return;
 		case 'B': case 'e':
-			if (!par[0]) par[0]++;
-			gotoxy(vc_cons[currcons].d, x, y+par[0]);
+			if (!vc->vc_par[0])
+				vc->vc_par[0]++;
+			gotoxy(vc, vc->vc_x, vc->vc_y + vc->vc_par[0]);
 			return;
 		case 'C': case 'a':
-			if (!par[0]) par[0]++;
-			gotoxy(vc_cons[currcons].d, x+par[0], y);
+			if (!vc->vc_par[0])
+				vc->vc_par[0]++;
+			gotoxy(vc, vc->vc_x + vc->vc_par[0], vc->vc_y);
 			return;
 		case 'D':
-			if (!par[0]) par[0]++;
-			gotoxy(vc_cons[currcons].d, x-par[0], y);
+			if (!vc->vc_par[0])
+				vc->vc_par[0]++;
+			gotoxy(vc, vc->vc_x - vc->vc_par[0], vc->vc_y);
 			return;
 		case 'E':
-			if (!par[0]) par[0]++;
-			gotoxy(vc_cons[currcons].d, 0, y+par[0]);
+			if (!vc->vc_par[0])
+				vc->vc_par[0]++;
+			gotoxy(vc, 0, vc->vc_y + vc->vc_par[0]);
 			return;
 		case 'F':
-			if (!par[0]) par[0]++;
-			gotoxy(vc_cons[currcons].d, 0, y-par[0]);
+			if (!vc->vc_par[0])
+				vc->vc_par[0]++;
+			gotoxy(vc, 0, vc->vc_y - vc->vc_par[0]);
 			return;
 		case 'd':
-			if (par[0]) par[0]--;
-			gotoxay(currcons,x,par[0]);
+			if (vc->vc_par[0])
+				vc->vc_par[0]--;
+			gotoxay(vc, vc->vc_x ,vc->vc_par[0]);
 			return;
 		case 'H': case 'f':
-			if (par[0]) par[0]--;
-			if (par[1]) par[1]--;
-			gotoxay(currcons,par[1],par[0]);
+			if (vc->vc_par[0])
+				vc->vc_par[0]--;
+			if (vc->vc_par[1])
+				vc->vc_par[1]--;
+			gotoxay(vc, vc->vc_par[1], vc->vc_par[0]);
 			return;
 		case 'J':
-			csi_J(currcons,par[0]);
+			csi_J(vc, vc->vc_par[0]);
 			return;
 		case 'K':
-			csi_K(currcons,par[0]);
+			csi_K(vc, vc->vc_par[0]);
 			return;
 		case 'L':
-			csi_L(currcons,par[0]);
+			csi_L(vc, vc->vc_par[0]);
 			return;
 		case 'M':
-			csi_M(currcons,par[0]);
+			csi_M(vc, vc->vc_par[0]);
 			return;
 		case 'P':
-			csi_P(currcons,par[0]);
+			csi_P(vc, vc->vc_par[0]);
 			return;
 		case 'c':
-			if (!par[0])
+			if (!vc->vc_par[0])
 				respond_ID(tty);
 			return;
 		case 'g':
-			if (!par[0])
-				tab_stop[x >> 5] &= ~(1 << (x & 31));
-			else if (par[0] == 3) {
-				tab_stop[0] =
-					tab_stop[1] =
-					tab_stop[2] =
-					tab_stop[3] =
-					tab_stop[4] = 0;
+			if (!vc->vc_par[0])
+				vc->vc_tab_stop[vc->vc_x >> 5] &= ~(1 << (vc->vc_x & 31));
+			else if (vc->vc_par[0] == 3) {
+				vc->vc_tab_stop[0] =
+					vc->vc_tab_stop[1] =
+					vc->vc_tab_stop[2] =
+					vc->vc_tab_stop[3] =
+					vc->vc_tab_stop[4] = 0;
 			}
 			return;
 		case 'm':
-			csi_m(currcons);
+			csi_m(vc);
 			return;
 		case 'q': /* DECLL - but only 3 leds */
 			/* map 0,1,2,3 to 0,1,2,4 */
-			if (par[0] < 4)
-				setledstate(kbd_table + currcons,
-					    (par[0] < 3) ? par[0] : 4);
+			if (vc->vc_par[0] < 4)
+				setledstate(kbd_table + vc->vc_num,
+					    (vc->vc_par[0] < 3) ? vc->vc_par[0] : 4);
 			return;
 		case 'r':
-			if (!par[0])
-				par[0]++;
-			if (!par[1])
-				par[1] = vc_cons[currcons].d->vc_rows;
+			if (!vc->vc_par[0])
+				vc->vc_par[0]++;
+			if (!vc->vc_par[1])
+				vc->vc_par[1] = vc->vc_rows;
 			/* Minimum allowed region is 2 lines */
-			if (par[0] < par[1] &&
-			    par[1] <= vc_cons[currcons].d->vc_rows) {
-				top=par[0]-1;
-				bottom=par[1];
-				gotoxay(currcons,0,0);
+			if (vc->vc_par[0] < vc->vc_par[1] &&
+			    vc->vc_par[1] <= vc->vc_rows) {
+				vc->vc_top = vc->vc_par[0] - 1;
+				vc->vc_bottom = vc->vc_par[1];
+				gotoxay(vc, 0, 0);
 			}
 			return;
 		case 's':
-			save_cur(currcons);
+			save_cur(vc);
 			return;
 		case 'u':
-			restore_cur(currcons);
+			restore_cur(vc);
 			return;
 		case 'X':
-			csi_X(currcons, par[0]);
+			csi_X(vc, vc->vc_par[0]);
 			return;
 		case '@':
-			csi_at(currcons,par[0]);
+			csi_at(vc, vc->vc_par[0]);
 			return;
 		case ']': /* setterm functions */
-			setterm_command(currcons);
+			setterm_command(vc);
 			return;
 		}
 		return;
 	case ESpercent:
-		vc_state = ESnormal;
+		vc->vc_state = ESnormal;
 		switch (c) {
 		case '@':  /* defined in ISO 2022 */
-			utf = 0;
+			vc->vc_utf = 0;
 			return;
 		case 'G':  /* prelim official escape code */
 		case '8':  /* retained for compatibility */
-			utf = 1;
+			vc->vc_utf = 1;
 			return;
 		}
 		return;
 	case ESfunckey:
-		vc_state = ESnormal;
+		vc->vc_state = ESnormal;
 		return;
 	case EShash:
-		vc_state = ESnormal;
+		vc->vc_state = ESnormal;
 		if (c == '8') {
 			/* DEC screen alignment test. kludge :-) */
-			video_erase_char =
-				(video_erase_char & 0xff00) | 'E';
-			csi_J(currcons, 2);
-			video_erase_char =
-				(video_erase_char & 0xff00) | ' ';
-			do_update_region(vc_cons[currcons].d, origin, screenbuf_size/2);
+			vc->vc_video_erase_char =
+				(vc->vc_video_erase_char & 0xff00) | 'E';
+			csi_J(vc, 2);
+			vc->vc_video_erase_char =
+				(vc->vc_video_erase_char & 0xff00) | ' ';
+			do_update_region(vc, vc->vc_origin, vc->vc_screenbuf_size / 2);
 		}
 		return;
 	case ESsetG0:
 		if (c == '0')
-			G0_charset = GRAF_MAP;
+			vc->vc_G0_charset = GRAF_MAP;
 		else if (c == 'B')
-			G0_charset = LAT1_MAP;
+			vc->vc_G0_charset = LAT1_MAP;
 		else if (c == 'U')
-			G0_charset = IBMPC_MAP;
+			vc->vc_G0_charset = IBMPC_MAP;
 		else if (c == 'K')
-			G0_charset = USER_MAP;
-		if (charset == 0)
-			translate = set_translate(G0_charset,currcons);
-		vc_state = ESnormal;
+			vc->vc_G0_charset = USER_MAP;
+		if (vc->vc_charset == 0)
+			vc->vc_translate = set_translate(vc->vc_G0_charset, vc);
+		vc->vc_state = ESnormal;
 		return;
 	case ESsetG1:
 		if (c == '0')
-			G1_charset = GRAF_MAP;
+			vc->vc_G1_charset = GRAF_MAP;
 		else if (c == 'B')
-			G1_charset = LAT1_MAP;
+			vc->vc_G1_charset = LAT1_MAP;
 		else if (c == 'U')
-			G1_charset = IBMPC_MAP;
+			vc->vc_G1_charset = IBMPC_MAP;
 		else if (c == 'K')
-			G1_charset = USER_MAP;
-		if (charset == 1)
-			translate = set_translate(G1_charset,currcons);
-		vc_state = ESnormal;
+			vc->vc_G1_charset = USER_MAP;
+		if (vc->vc_charset == 1)
+			vc->vc_translate = set_translate(vc->vc_G1_charset, vc);
+		vc->vc_state = ESnormal;
 		return;
 	default:
-		vc_state = ESnormal;
+		vc->vc_state = ESnormal;
 	}
 }
 
@@ -1903,7 +1893,7 @@
 #define FLUSH do { } while(0);
 #else
 #define FLUSH if (draw_x >= 0) { \
-	sw->con_putcs(vc_cons[currcons].d, (u16 *)draw_from, (u16 *)draw_to-(u16 *)draw_from, y, draw_x); \
+	vc->vc_sw->con_putcs(vc, (u16 *)draw_from, (u16 *)draw_to - (u16 *)draw_from, vc->vc_y, draw_x); \
 	draw_x = -1; \
 	}
 #endif
@@ -1911,7 +1901,7 @@
 	int c, tc, ok, n = 0, draw_x = -1;
 	unsigned int currcons;
 	unsigned long draw_from = 0, draw_to = 0;
-	struct vt_struct *vt;
+	struct vc_data *vc;
 	u16 himask, charmask;
 	const unsigned char *orig_buf = NULL;
 	int orig_count;
@@ -1922,14 +1912,14 @@
 	might_sleep();
 
 	acquire_console_sem();
-	vt = tty->driver_data;
-	if (vt == NULL) {
+	vc = tty->driver_data;
+	if (vc == NULL) {
 		printk(KERN_ERR "vt: argh, driver_data is NULL !\n");
 		release_console_sem();
 		return 0;
 	}
 
-	currcons = vt->vc_num;
+	currcons = vc->vc_num;
 	if (!vc_cons_allocated(currcons)) {
 	    /* could this happen? */
 	    static int error = 0;
@@ -1954,19 +1944,19 @@
 
 	acquire_console_sem();
 
-	vt = tty->driver_data;
-	if (vt == NULL) {
+	vc = tty->driver_data;
+	if (vc == NULL) {
 		printk(KERN_ERR "vt: argh, driver_data _became_ NULL !\n");
 		release_console_sem();
 		goto out;
 	}
 
-	himask = hi_font_mask;
+	himask = vc->vc_hi_font_mask;
 	charmask = himask ? 0x1ff : 0xff;
 
 	/* undraw cursor first */
-	if (IS_FG)
-		hide_cursor(vc_cons[currcons].d);
+	if (IS_FG(vc))
+		hide_cursor(vc);
 
 	while (!tty->stopped && count) {
 		int orig = *buf;
@@ -1976,44 +1966,44 @@
 		count--;
 
 		/* Do no translation at all in control states */
-		if (vc_state != ESnormal) {
+		if (vc->vc_state != ESnormal) {
 			tc = c;
-		} else if (utf) {
+		} else if (vc->vc_utf) {
 		    /* Combine UTF-8 into Unicode */
 		    /* Incomplete characters silently ignored */
 		    if(c > 0x7f) {
-			if (utf_count > 0 && (c & 0xc0) == 0x80) {
-				utf_char = (utf_char << 6) | (c & 0x3f);
-				utf_count--;
-				if (utf_count == 0)
-				    tc = c = utf_char;
+			if (vc->vc_utf_count > 0 && (c & 0xc0) == 0x80) {
+				vc->vc_utf_char = (vc->vc_utf_char << 6) | (c & 0x3f);
+				vc->vc_utf_count--;
+				if (vc->vc_utf_count == 0)
+				    tc = c = vc->vc_utf_char;
 				else continue;
 			} else {
 				if ((c & 0xe0) == 0xc0) {
-				    utf_count = 1;
-				    utf_char = (c & 0x1f);
+				    vc->vc_utf_count = 1;
+				    vc->vc_utf_char = (c & 0x1f);
 				} else if ((c & 0xf0) == 0xe0) {
-				    utf_count = 2;
-				    utf_char = (c & 0x0f);
+				    vc->vc_utf_count = 2;
+				    vc->vc_utf_char = (c & 0x0f);
 				} else if ((c & 0xf8) == 0xf0) {
-				    utf_count = 3;
-				    utf_char = (c & 0x07);
+				    vc->vc_utf_count = 3;
+				    vc->vc_utf_char = (c & 0x07);
 				} else if ((c & 0xfc) == 0xf8) {
-				    utf_count = 4;
-				    utf_char = (c & 0x03);
+				    vc->vc_utf_count = 4;
+				    vc->vc_utf_char = (c & 0x03);
 				} else if ((c & 0xfe) == 0xfc) {
-				    utf_count = 5;
-				    utf_char = (c & 0x01);
+				    vc->vc_utf_count = 5;
+				    vc->vc_utf_char = (c & 0x01);
 				} else
-				    utf_count = 0;
+				    vc->vc_utf_count = 0;
 				continue;
 			      }
 		    } else {
 		      tc = c;
-		      utf_count = 0;
+		      vc->vc_utf_count = 0;
 		    }
 		} else {	/* no utf */
-		  tc = translate[toggle_meta ? (c|0x80) : c];
+		  tc = vc->vc_translate[vc->vc_toggle_meta ? (c | 0x80) : c];
 		}
 
                 /* If the original code was a control character we
@@ -2027,18 +2017,18 @@
                  * direct-to-font zone in UTF-8 mode.
                  */
                 ok = tc && (c >= 32 ||
-                            (!utf && !(((disp_ctrl ? CTRL_ALWAYS
-                                         : CTRL_ACTION) >> c) & 1)))
-                        && (c != 127 || disp_ctrl)
+			    (!vc->vc_utf && !(((vc->vc_disp_ctrl ? CTRL_ALWAYS
+						: CTRL_ACTION) >> c) & 1)))
+			&& (c != 127 || vc->vc_disp_ctrl)
 			&& (c != 128+27);
 
-		if (vc_state == ESnormal && ok) {
+		if (vc->vc_state == ESnormal && ok) {
 			/* Now try to find out how to display it */
-			tc = conv_uni_to_pc(vc_cons[currcons].d, tc);
+			tc = conv_uni_to_pc(vc, tc);
 			if ( tc == -4 ) {
                                 /* If we got -4 (not found) then see if we have
                                    defined a replacement character (U+FFFD) */
-                                tc = conv_uni_to_pc(vc_cons[currcons].d, 0xfffd);
+                                tc = conv_uni_to_pc(vc, 0xfffd);
 
 				/* One reason for the -4 can be that we just
 				   did a clear_unimap();
@@ -2052,33 +2042,33 @@
 			if (tc & ~charmask)
                                 continue; /* Conversion failed */
 
-			if (need_wrap || decim)
+			if (vc->vc_need_wrap || vc->vc_decim)
 				FLUSH
-			if (need_wrap) {
-				cr(currcons);
-				lf(currcons);
+			if (vc->vc_need_wrap) {
+				cr(vc);
+				lf(vc);
 			}
-			if (decim)
-				insert_char(currcons, 1);
+			if (vc->vc_decim)
+				insert_char(vc, 1);
 			scr_writew(himask ?
-				     ((attr << 8) & ~himask) + ((tc & 0x100) ? himask : 0) + (tc & 0xff) :
-				     (attr << 8) + tc,
-				   (u16 *) pos);
-			if (DO_UPDATE && draw_x < 0) {
-				draw_x = x;
-				draw_from = pos;
-			}
-			if (x == vc_cons[currcons].d->vc_cols - 1) {
-				need_wrap = decawm;
-				draw_to = pos+2;
+				     ((vc->vc_attr << 8) & ~himask) + ((tc & 0x100) ? himask : 0) + (tc & 0xff) :
+				     (vc->vc_attr << 8) + tc,
+				   (u16 *) vc->vc_pos);
+			if (DO_UPDATE(vc) && draw_x < 0) {
+				draw_x = vc->vc_x;
+				draw_from = vc->vc_pos;
+			}
+			if (vc->vc_x == vc->vc_cols - 1) {
+				vc->vc_need_wrap = vc->vc_decawm;
+				draw_to = vc->vc_pos + 2;
 			} else {
-				x++;
-				draw_to = (pos+=2);
+				vc->vc_x++;
+				draw_to = (vc->vc_pos += 2);
 			}
 			continue;
 		}
 		FLUSH
-		do_con_trol(tty, currcons, orig);
+		do_con_trol(tty, vc, orig);
 	}
 	FLUSH
 	console_conditional_schedule();
@@ -2106,7 +2096,7 @@
 		if (want_console != fg_console &&
 		    vc_cons_allocated(want_console)) {
 			hide_cursor(vc_cons[fg_console].d);
-			change_console(want_console);
+			change_console(vc_cons[want_console].d);
 			/* we only changed when the console had already
 			   been allocated - a new console is not created
 			   in an interrupt routine */
@@ -2118,10 +2108,10 @@
 		poke_blanked_console();
 	}
 	if (scrollback_delta) {
-		int currcons = fg_console;
+		struct vc_data *vc = vc_cons[fg_console].d;
 		clear_selection();
-		if (vcmode == KD_TEXT)
-			sw->con_scrolldelta(vc_cons[currcons].d, scrollback_delta);
+		if (vc->vc_mode == KD_TEXT)
+			vc->vc_sw->con_scrolldelta(vc, scrollback_delta);
 		scrollback_delta = 0;
 	}
 	if (blank_timer_expired) {
@@ -2150,7 +2140,7 @@
 
 void vt_console_print(struct console *co, const char *b, unsigned count)
 {
-	int currcons = fg_console;
+	struct vc_data *vc = vc_cons[fg_console].d;
 	unsigned char c;
 	static unsigned long printing;
 	const ushort *start;
@@ -2162,73 +2152,73 @@
 		return;
 
 	if (kmsg_redirect && vc_cons_allocated(kmsg_redirect - 1))
-		currcons = kmsg_redirect - 1;
+		vc = vc_cons[kmsg_redirect - 1].d;
 
 	/* read `x' only after setting currcons properly (otherwise
 	   the `x' macro will read the x of the foreground console). */
-	myx = x;
+	myx = vc->vc_x;
 
-	if (!vc_cons_allocated(currcons)) {
+	if (!vc_cons_allocated(fg_console)) {
 		/* impossible */
 		/* printk("vt_console_print: tty %d not allocated ??\n", currcons+1); */
 		goto quit;
 	}
 
-	if (vcmode != KD_TEXT)
+	if (vc->vc_mode != KD_TEXT)
 		goto quit;
 
 	/* undraw cursor first */
-	if (IS_FG)
-		hide_cursor(vc_cons[currcons].d);
+	if (IS_FG(vc))
+		hide_cursor(vc);
 
-	start = (ushort *)pos;
+	start = (ushort *)vc->vc_pos;
 
 	/* Contrived structure to try to emulate original need_wrap behaviour
 	 * Problems caused when we have need_wrap set on '\n' character */
 	while (count--) {
 		c = *b++;
-		if (c == 10 || c == 13 || c == 8 || need_wrap) {
+		if (c == 10 || c == 13 || c == 8 || vc->vc_need_wrap) {
 			if (cnt > 0) {
-				if (IS_VISIBLE)
-					sw->con_putcs(vc_cons[currcons].d, start, cnt, y, x);
-				x += cnt;
-				if (need_wrap)
-					x--;
+				if (CON_IS_VISIBLE(vc))
+					vc->vc_sw->con_putcs(vc, start, cnt, vc->vc_y, vc->vc_x);
+				vc->vc_x += cnt;
+				if (vc->vc_need_wrap)
+					vc->vc_x--;
 				cnt = 0;
 			}
 			if (c == 8) {		/* backspace */
-				bs(currcons);
-				start = (ushort *)pos;
-				myx = x;
+				bs(vc);
+				start = (ushort *)vc->vc_pos;
+				myx = vc->vc_x;
 				continue;
 			}
 			if (c != 13)
-				lf(currcons);
-			cr(currcons);
-			start = (ushort *)pos;
-			myx = x;
+				lf(vc);
+			cr(vc);
+			start = (ushort *)vc->vc_pos;
+			myx = vc->vc_x;
 			if (c == 10 || c == 13)
 				continue;
 		}
-		scr_writew((attr << 8) + c, (unsigned short *) pos);
+		scr_writew((vc->vc_attr << 8) + c, (unsigned short *)vc->vc_pos);
 		cnt++;
-		if (myx == vc_cons[currcons].d->vc_cols - 1) {
-			need_wrap = 1;
+		if (myx == vc->vc_cols - 1) {
+			vc->vc_need_wrap = 1;
 			continue;
 		}
-		pos+=2;
+		vc->vc_pos += 2;
 		myx++;
 	}
 	if (cnt > 0) {
-		if (IS_VISIBLE)
-			sw->con_putcs(vc_cons[currcons].d, start, cnt, y, x);
-		x += cnt;
-		if (x == vc_cons[currcons].d->vc_cols) {
-			x--;
-			need_wrap = 1;
+		if (CON_IS_VISIBLE(vc))
+			vc->vc_sw->con_putcs(vc, start, cnt, vc->vc_y, vc->vc_x);
+		vc->vc_x += cnt;
+		if (vc->vc_x == vc->vc_cols) {
+			vc->vc_x--;
+			vc->vc_need_wrap = 1;
 		}
 	}
-	set_cursor(vc_cons[currcons].d);
+	set_cursor(vc);
 
 	if (!oops_in_progress)
 		poke_blanked_console();
@@ -2333,7 +2323,7 @@
 			if (get_user(lines, (s32 __user *)(p+4))) {
 				ret = -EFAULT;
 			} else {
-				scrollfront(lines);
+				scrollfront(vc_cons[fg_console].d, lines);
 				ret = 0;
 			}
 			break;
@@ -2395,9 +2385,9 @@
 
 static void con_unthrottle(struct tty_struct *tty)
 {
-	struct vt_struct *vt = tty->driver_data;
+	struct vc_data *vc = tty->driver_data;
 
-	wake_up_interruptible(&vt->paste_wait);
+	wake_up_interruptible(&vc->paste_wait);
 }
 
 /*
@@ -2432,16 +2422,16 @@
 
 static void con_flush_chars(struct tty_struct *tty)
 {
-	struct vt_struct *vt;
+	struct vc_data *vc;
 
 	if (in_interrupt())	/* from flush_to_ldisc */
 		return;
 
 	/* if we race with con_close(), vt may be null */
 	acquire_console_sem();
-	vt = tty->driver_data;
-	if (vt)
-		set_cursor(vc_cons[vt->vc_num].d);
+	vc = tty->driver_data;
+	if (vc)
+		set_cursor(vc);
 	release_console_sem();
 }
 
@@ -2457,9 +2447,9 @@
 	if (tty->count == 1) {
 		ret = vc_allocate(currcons);
 		if (ret == 0) {
-			vt_cons[currcons]->vc_num = currcons;
-			tty->driver_data = vt_cons[currcons];
-			vc_cons[currcons].d->vc_tty = tty;
+			struct vc_data *vc = vc_cons[currcons].d;
+			tty->driver_data = vc;
+			vc->vc_tty = tty;
 
 			if (!tty->winsize.ws_row && !tty->winsize.ws_col) {
 				tty->winsize.ws_row = vc_cons[currcons].d->vc_rows;
@@ -2486,11 +2476,10 @@
 	down(&tty_sem);
 	acquire_console_sem();
 	if (tty && tty->count == 1) {
-		struct vt_struct *vt;
+		struct vc_data *vc = tty->driver_data;
 
-		vt = tty->driver_data;
-		if (vt)
-			vc_cons[vt->vc_num].d->vc_tty = NULL;
+		if (vc)
+			vc->vc_tty = NULL;
 		tty->driver_data = NULL;
 		release_console_sem();
 		vcs_remove_devfs(tty);
@@ -2505,29 +2494,29 @@
 	up(&tty_sem);
 }
 
-static void vc_init(unsigned int currcons, unsigned int rows,
-			unsigned int cols, int do_clear)
+static void vc_init(struct vc_data *vc, unsigned int rows,
+		    unsigned int cols, int do_clear)
 {
 	int j, k ;
 
-	vc_cons[currcons].d->vc_cols = cols;
-	vc_cons[currcons].d->vc_rows = rows;
-	vc_cons[currcons].d->vc_size_row = cols<<1;
-	screenbuf_size = vc_cons[currcons].d->vc_rows * vc_cons[currcons].d->vc_size_row;
-
-	set_origin(currcons);
-	pos = origin;
-	reset_vc(currcons);
+	vc->vc_cols = cols;
+	vc->vc_rows = rows;
+	vc->vc_size_row = cols << 1;
+	vc->vc_screenbuf_size = vc->vc_rows * vc->vc_size_row;
+
+	set_origin(vc);
+	vc->vc_pos = vc->vc_origin;
+	reset_vc(vc);
 	for (j=k=0; j<16; j++) {
-		vc_cons[currcons].d->vc_palette[k++] = default_red[j] ;
-		vc_cons[currcons].d->vc_palette[k++] = default_grn[j] ;
-		vc_cons[currcons].d->vc_palette[k++] = default_blu[j] ;
-	}
-	def_color       = 0x07;   /* white */
-	ulcolor		= 0x0f;   /* bold white */
-	halfcolor       = 0x08;   /* grey */
-	init_waitqueue_head(&vt_cons[currcons]->paste_wait);
-	reset_terminal(currcons, do_clear);
+		vc->vc_palette[k++] = default_red[j] ;
+		vc->vc_palette[k++] = default_grn[j] ;
+		vc->vc_palette[k++] = default_blu[j] ;
+	}
+	vc->vc_def_color       = 0x07;   /* white */
+	vc->vc_ulcolor		= 0x0f;   /* bold white */
+	vc->vc_halfcolor       = 0x08;   /* grey */
+	init_waitqueue_head(&vc->paste_wait);
+	reset_terminal(vc, do_clear);
 }
 
 /*
@@ -2539,6 +2528,7 @@
 static int __init con_init(void)
 {
 	const char *display_desc = NULL;
+	struct vc_data *vc;
 	unsigned int currcons = 0;
 
 	acquire_console_sem();
@@ -2562,27 +2552,23 @@
 	 * kmalloc is not running yet - we use the bootmem allocator.
 	 */
 	for (currcons = 0; currcons < MIN_NR_CONSOLES; currcons++) {
-		vc_cons[currcons].d = (struct vc_data *)
-				alloc_bootmem(sizeof(struct vc_data));
-		vt_cons[currcons] = (struct vt_struct *)
-				alloc_bootmem(sizeof(struct vt_struct));
-		vc_cons[currcons].d->vc_vt = vt_cons[currcons];
-		visual_init(currcons, 1);
-		screenbuf = (unsigned short *) alloc_bootmem(screenbuf_size);
-		kmalloced = 0;
-		vc_init(currcons, vc_cons[currcons].d->vc_rows, vc_cons[currcons].d->vc_cols,
-			currcons || !sw->con_save_screen);
+		vc_cons[currcons].d = vc = alloc_bootmem(sizeof(struct vc_data));
+		visual_init(vc, currcons, 1);
+		vc->vc_screenbuf = (unsigned short *)alloc_bootmem(vc->vc_screenbuf_size);
+		vc->vc_kmalloced = 0;
+		vc_init(vc, vc->vc_rows, vc->vc_cols,
+			currcons || !vc->vc_sw->con_save_screen);
 	}
 	currcons = fg_console = 0;
-	master_display_fg = vc_cons[currcons].d;
-	set_origin(currcons);
-	save_screen(currcons);
-	gotoxy(vc_cons[currcons].d, x, y);
-	csi_J(currcons, 0);
-	update_screen(fg_console);
+	master_display_fg = vc = vc_cons[currcons].d;
+	set_origin(vc);
+	save_screen(vc);
+	gotoxy(vc, vc->vc_x, vc->vc_y);
+	csi_J(vc, 0);
+	update_screen(vc);
 	printk("Console: %s %s %dx%d",
-		vc_cons[currcons].d->vc_can_do_color ? "colour" : "mono",
-		display_desc, vc_cons[currcons].d->vc_cols, vc_cons[currcons].d->vc_rows);
+		vc->vc_can_do_color ? "colour" : "mono",
+		display_desc, vc->vc_cols, vc->vc_rows);
 	printable = 1;
 	printk("\n");
 
@@ -2676,37 +2662,37 @@
 
 	for (i = first; i <= last; i++) {
 		int old_was_color;
-		int currcons = i;
+		struct vc_data *vc = vc_cons[i].d;
 
 		if (con_driver_map[i])
 			module_put(con_driver_map[i]->owner);
 		__module_get(owner);
 		con_driver_map[i] = csw;
 
-		if (!vc_cons[i].d || !vc_cons[i].d->vc_sw)
+		if (!vc || !vc->vc_sw)
 			continue;
 
 		j = i;
-		if (IS_VISIBLE)
-			save_screen(i);
-		old_was_color = vc_cons[i].d->vc_can_do_color;
-		vc_cons[i].d->vc_sw->con_deinit(vc_cons[i].d);
-		origin = (unsigned long) screenbuf;
-		visible_origin = origin;
-		scr_end = origin + screenbuf_size;
-		pos = origin + vc_cons[currcons].d->vc_size_row*y + 2*x;
-		visual_init(i, 0);
-		update_attr(i);
+		if (CON_IS_VISIBLE(vc))
+			save_screen(vc);
+		old_was_color = vc->vc_can_do_color;
+		vc->vc_sw->con_deinit(vc);
+		vc->vc_origin = (unsigned long)vc->vc_screenbuf;
+		vc->vc_visible_origin = vc->vc_origin;
+		vc->vc_scr_end = vc->vc_origin + vc->vc_screenbuf_size;
+		vc->vc_pos = vc->vc_origin + vc->vc_size_row * vc->vc_y + 2 * vc->vc_x;
+		visual_init(vc, i, 0);
+		update_attr(vc);
 
 		/* If the console changed between mono <-> color, then
 		 * the attributes in the screenbuf will be wrong.  The
 		 * following resets all attributes to something sane.
 		 */
-		if (old_was_color != vc_cons[i].d->vc_can_do_color)
-			clear_buffer_attributes(i);
+		if (old_was_color != vc->vc_can_do_color)
+			clear_buffer_attributes(vc);
 
-		if (IS_VISIBLE)
-			update_screen(i);
+		if (CON_IS_VISIBLE(vc))
+			update_screen(vc);
 	}
 	printk("Console: switching ");
 	if (!deflt)
@@ -2773,7 +2759,7 @@
 
 void do_blank_screen(int entering_gfx)
 {
-	int currcons = fg_console;
+	struct vc_data *vc = vc_cons[fg_console].d;
 	int i;
 
 	WARN_CONSOLE_UNLOCKED();
@@ -2792,30 +2778,30 @@
 
 	/* entering graphics mode? */
 	if (entering_gfx) {
-		hide_cursor(vc_cons[currcons].d);
-		save_screen(currcons);
-		sw->con_blank(vc_cons[currcons].d, -1, 1);
+		hide_cursor(vc);
+		save_screen(vc);
+		vc->vc_sw->con_blank(vc, -1, 1);
 		console_blanked = fg_console + 1;
-		set_origin(currcons);
+		set_origin(vc);
 		return;
 	}
 
 	/* don't blank graphics */
-	if (vcmode != KD_TEXT) {
+	if (vc->vc_mode != KD_TEXT) {
 		console_blanked = fg_console + 1;
 		return;
 	}
 
-	hide_cursor(vc_cons[currcons].d);
+	hide_cursor(vc);
 	del_timer_sync(&console_timer);
 	blank_timer_expired = 0;
 
-	save_screen(currcons);
+	save_screen(vc);
 	/* In case we need to reset origin, blanking hook returns 1 */
-	i = sw->con_blank(vc_cons[currcons].d, 1, 0);
+	i = vc->vc_sw->con_blank(vc, 1, 0);
 	console_blanked = fg_console + 1;
 	if (i)
-		set_origin(currcons);
+		set_origin(vc);
 
 	if (console_blank_hook && console_blank_hook(1))
 		return;
@@ -2826,7 +2812,7 @@
 	}
 
     	if (vesa_blank_mode)
-		sw->con_blank(vc_cons[currcons].d, vesa_blank_mode + 1, 0);
+		vc->vc_sw->con_blank(vc, vesa_blank_mode + 1, 0);
 }
 EXPORT_SYMBOL(do_blank_screen);
 
@@ -2835,7 +2821,7 @@
  */
 void do_unblank_screen(int leaving_gfx)
 {
-	int currcons;
+	struct vc_data *vc;
 
 	WARN_CONSOLE_UNLOCKED();
 
@@ -2847,8 +2833,8 @@
 		printk("unblank_screen: tty %d not allocated ??\n", fg_console+1);
 		return;
 	}
-	currcons = fg_console;
-	if (vcmode != KD_TEXT)
+	vc = vc_cons[fg_console].d;
+	if (vc->vc_mode != KD_TEXT)
 		return; /* but leave console_blanked != 0 */
 
 	if (blankinterval) {
@@ -2857,13 +2843,13 @@
 	}
 
 	console_blanked = 0;
-	if (sw->con_blank(vc_cons[currcons].d, 0, leaving_gfx))
+	if (vc->vc_sw->con_blank(vc, 0, leaving_gfx))
 		/* Low-level driver cannot restore -> do it ourselves */
-		update_screen(fg_console);
+		update_screen(vc);
 	if (console_blank_hook)
 		console_blank_hook(0);
-	set_palette(currcons);
-	set_cursor(vc_cons[fg_console].d);
+	set_palette(vc);
+	set_cursor(vc);
 }
 EXPORT_SYMBOL(do_unblank_screen);
 
@@ -2899,7 +2885,7 @@
 	del_timer(&console_timer);
 	blank_timer_expired = 0;
 
-	if (ignore_poke || !vt_cons[fg_console] || vt_cons[fg_console]->vc_mode == KD_GRAPHICS)
+	if (ignore_poke || !vc_cons[fg_console].d || vc_cons[fg_console].d->vc_mode == KD_GRAPHICS)
 		return;
 	if (console_blanked)
 		unblank_screen();
@@ -2913,12 +2899,12 @@
  *	Palettes
  */
 
-void set_palette(int currcons)
+void set_palette(struct vc_data *vc)
 {
 	WARN_CONSOLE_UNLOCKED();
 
-	if (vcmode != KD_GRAPHICS)
-		sw->con_set_palette(vc_cons[currcons].d, color_table);
+	if (vc->vc_mode != KD_GRAPHICS)
+		vc->vc_sw->con_set_palette(vc, color_table);
 }
 
 static int set_get_cmap(unsigned char __user *arg, int set)
@@ -2945,7 +2931,7 @@
 		    vc_cons[i].d->vc_palette[k++] = default_grn[j];
 		    vc_cons[i].d->vc_palette[k++] = default_blu[j];
 		}
-		set_palette(i);
+		set_palette(vc_cons[i].d);
 	    }
     }
     return 0;
@@ -2978,15 +2964,15 @@
 	return rc;
 }
 
-void reset_palette(int currcons)
+void reset_palette(struct vc_data *vc)
 {
 	int j, k;
 	for (j=k=0; j<16; j++) {
-		palette[k++] = default_red[j];
-		palette[k++] = default_grn[j];
-		palette[k++] = default_blu[j];
+		vc->vc_palette[k++] = default_red[j];
+		vc->vc_palette[k++] = default_grn[j];
+		vc->vc_palette[k++] = default_blu[j];
 	}
-	set_palette(currcons);
+	set_palette(vc);
 }
 
 /*
@@ -3004,13 +2990,13 @@
 
 #define max_font_size 65536
 
-int con_font_get(int currcons, struct console_font_op *op)
+int con_font_get(struct vc_data *vc, struct console_font_op *op)
 {
 	struct console_font font;
 	int rc = -EINVAL;
 	int c;
 
-	if (vt_cons[currcons]->vc_mode != KD_TEXT)
+	if (vc->vc_mode != KD_TEXT)
 		return -EINVAL;
 
 	if (op->data) {
@@ -3021,8 +3007,8 @@
 		font.data = NULL;
 
 	acquire_console_sem();
-	if (sw->con_font_get)
-		rc = sw->con_font_get(vc_cons[currcons].d, &font);
+	if (vc->vc_sw->con_font_get)
+		rc = vc->vc_sw->con_font_get(vc, &font);
 	else
 		rc = -ENOSYS;
 	release_console_sem();
@@ -3059,13 +3045,13 @@
 	return rc;
 }
 
-int con_font_set(int currcons, struct console_font_op *op)
+int con_font_set(struct vc_data *vc, struct console_font_op *op)
 {
 	struct console_font font;
 	int rc = -EINVAL;
 	int size;
 
-	if (vt_cons[currcons]->vc_mode != KD_TEXT)
+	if (vc->vc_mode != KD_TEXT)
 		return -EINVAL;
 	if (!op->data)
 		return -EINVAL;
@@ -3107,8 +3093,8 @@
 		return -EFAULT;
 	}
 	acquire_console_sem();
-	if (sw->con_font_set)
-		rc = sw->con_font_set(vc_cons[currcons].d, &font, op->flags);
+	if (vc->vc_sw->con_font_set)
+		rc = vc->vc_sw->con_font_set(vc, &font, op->flags);
 	else
 		rc = -ENOSYS;
 	release_console_sem();
@@ -3116,14 +3102,14 @@
 	return rc;
 }
 
-int con_font_default(int currcons, struct console_font_op *op)
+int con_font_default(struct vc_data *vc, struct console_font_op *op)
 {
 	struct console_font font = {.width = op->width, .height = op->height};
 	char name[MAX_FONT_NAME];
 	char *s = name;
 	int rc;
 
-	if (vt_cons[currcons]->vc_mode != KD_TEXT)
+	if (vc->vc_mode != KD_TEXT)
 		return -EINVAL;
 
 	if (!op->data)
@@ -3134,8 +3120,8 @@
 		name[MAX_FONT_NAME - 1] = 0;
 
 	acquire_console_sem();
-	if (sw->con_font_default)
-		rc = sw->con_font_default(vc_cons[currcons].d, &font, s);
+	if (vc->vc_sw->con_font_default)
+		rc = vc->vc_sw->con_font_default(vc, &font, s);
 	else
 		rc = -ENOSYS;
 	release_console_sem();
@@ -3146,40 +3132,38 @@
 	return rc;
 }
 
-int con_font_copy(int currcons, struct console_font_op *op)
+int con_font_copy(struct vc_data *vc, struct console_font_op *op)
 {
 	int con = op->height;
-	struct vc_data *vc;
 	int rc;
 
-	if (vt_cons[currcons]->vc_mode != KD_TEXT)
+	if (vc->vc_mode != KD_TEXT)
 		return -EINVAL;
 
 	acquire_console_sem();
-	vc = vc_cons[currcons].d;
-	if (!sw->con_font_copy)
+	if (!vc->vc_sw->con_font_copy)
 		rc = -ENOSYS;
 	else if (con < 0 || !vc_cons_allocated(con))
 		rc = -ENOTTY;
 	else if (con == vc->vc_num)	/* nothing to do */
 		rc = 0;
 	else
-		rc = sw->con_font_copy(vc, con);
+		rc = vc->vc_sw->con_font_copy(vc, con);
 	release_console_sem();
 	return rc;
 }
 
-int con_font_op(int currcons, struct console_font_op *op)
+int con_font_op(struct vc_data *vc, struct console_font_op *op)
 {
 	switch (op->op) {
 	case KD_FONT_OP_SET:
-		return con_font_set(currcons, op);
+		return con_font_set(vc, op);
 	case KD_FONT_OP_GET:
-		return con_font_get(currcons, op);
+		return con_font_get(vc, op);
 	case KD_FONT_OP_SET_DEFAULT:
-		return con_font_default(currcons, op);
+		return con_font_default(vc, op);
 	case KD_FONT_OP_COPY:
-		return con_font_copy(currcons, op);
+		return con_font_copy(vc, op);
 	}
 	return -ENOSYS;
 }
@@ -3265,7 +3249,6 @@
 EXPORT_SYMBOL(fg_console);
 EXPORT_SYMBOL(console_blank_hook);
 EXPORT_SYMBOL(console_blanked);
-EXPORT_SYMBOL(vt_cons);
 EXPORT_SYMBOL(vc_cons);
 #ifndef VT_SINGLE_DRIVER
 EXPORT_SYMBOL(take_over_console);
diff -Nru a/drivers/char/vt_ioctl.c b/drivers/char/vt_ioctl.c
--- a/drivers/char/vt_ioctl.c	2005-03-11 12:51:52 -08:00
+++ b/drivers/char/vt_ioctl.c	2005-03-11 12:51:52 -08:00
@@ -52,8 +52,6 @@
  * to the current console is done by the main ioctl code.
  */
 
-struct vt_struct *vt_cons[MAX_NR_CONSOLES];
-
 /* Keyboard type: Default is KB_101, but can be set by machine
  * specific code.
  */
@@ -311,7 +309,7 @@
 		op->height = cfdarg.charheight;
 		op->charcount = cfdarg.charcount;
 		op->data = cfdarg.chardata;
-		return con_font_op(fg_console, op);
+		return con_font_op(vc_cons[fg_console].d, op);
 	case GIO_FONTX: {
 		op->op = KD_FONT_OP_GET;
 		op->flags = KD_FONT_FLAG_OLD;
@@ -319,7 +317,7 @@
 		op->height = cfdarg.charheight;
 		op->charcount = cfdarg.charcount;
 		op->data = cfdarg.chardata;
-		i = con_font_op(fg_console, op);
+		i = con_font_op(vc_cons[fg_console].d, op);
 		if (i)
 			return i;
 		cfdarg.charheight = op->height;
@@ -333,7 +331,7 @@
 }
 
 static inline int 
-do_unimap_ioctl(int cmd, struct unimapdesc __user *user_ud, int perm, unsigned int console)
+do_unimap_ioctl(int cmd, struct unimapdesc __user *user_ud, int perm, struct vc_data *vc)
 {
 	struct unimapdesc tmp;
 	int i = 0; 
@@ -349,11 +347,11 @@
 	case PIO_UNIMAP:
 		if (!perm)
 			return -EPERM;
-		return con_set_unimap(console, tmp.entry_ct, tmp.entries);
+		return con_set_unimap(vc, tmp.entry_ct, tmp.entries);
 	case GIO_UNIMAP:
-		if (!perm && fg_console != console)
+		if (!perm && fg_console != vc->vc_num)
 			return -EPERM;
-		return con_get_unimap(console, tmp.entry_ct, &(user_ud->entry_ct), tmp.entries);
+		return con_get_unimap(vc, tmp.entry_ct, &(user_ud->entry_ct), tmp.entries);
 	}
 	return 0;
 }
@@ -365,8 +363,7 @@
 int vt_ioctl(struct tty_struct *tty, struct file * file,
 	     unsigned int cmd, unsigned long arg)
 {
-	struct vt_struct *vt = (struct vt_struct *)tty->driver_data;
-	struct vc_data *vc = vc_cons[vt->vc_num].d;
+	struct vc_data *vc = (struct vc_data *)tty->driver_data;
 	struct console_font_op op;	/* used in multiple places here */
 	struct kbd_struct * kbd;
 	unsigned int console;
@@ -374,7 +371,7 @@
 	void __user *up = (void __user *)arg;
 	int i, perm;
 	
-	console = vt->vc_num;
+	console = vc->vc_num;
 
 	if (!vc_cons_allocated(console)) 	/* impossible? */
 		return -ENOIOCTLCMD;
@@ -487,9 +484,9 @@
 		default:
 			return -EINVAL;
 		}
-		if (vt_cons[console]->vc_mode == (unsigned char) arg)
+		if (vc->vc_mode == (unsigned char) arg)
 			return 0;
-		vt_cons[console]->vc_mode = (unsigned char) arg;
+		vc->vc_mode = (unsigned char) arg;
 		if (console != fg_console)
 			return 0;
 		/*
@@ -504,7 +501,7 @@
 		return 0;
 
 	case KDGETMODE:
-		ucval = vt_cons[console]->vc_mode;
+		ucval = vc->vc_mode;
 		goto setint;
 
 	case KDMAPDISP:
@@ -667,12 +664,12 @@
 		if (tmp.mode != VT_AUTO && tmp.mode != VT_PROCESS)
 			return -EINVAL;
 		acquire_console_sem();
-		vt_cons[console]->vt_mode = tmp;
+		vc->vt_mode = tmp;
 		/* the frsig is ignored, so we set it to 0 */
-		vt_cons[console]->vt_mode.frsig = 0;
-		vt_cons[console]->vt_pid = current->pid;
+		vc->vt_mode.frsig = 0;
+		vc->vt_pid = current->pid;
 		/* no switch is required -- saw@shade.msu.ru */
-		vt_cons[console]->vt_newvt = -1; 
+		vc->vt_newvt = -1;
 		release_console_sem();
 		return 0;
 	}
@@ -683,7 +680,7 @@
 		int rc;
 
 		acquire_console_sem();
-		memcpy(&tmp, &vt_cons[console]->vt_mode, sizeof(struct vt_mode));
+		memcpy(&tmp, &vc->vt_mode, sizeof(struct vt_mode));
 		release_console_sem();
 
 		rc = copy_to_user(up, &tmp, sizeof(struct vt_mode));
@@ -761,31 +758,29 @@
 	case VT_RELDISP:
 		if (!perm)
 			return -EPERM;
-		if (vt_cons[console]->vt_mode.mode != VT_PROCESS)
+		if (vc->vt_mode.mode != VT_PROCESS)
 			return -EINVAL;
 
 		/*
 		 * Switching-from response
 		 */
-		if (vt_cons[console]->vt_newvt >= 0)
-		{
+		if (vc->vt_newvt >= 0) {
 			if (arg == 0)
 				/*
 				 * Switch disallowed, so forget we were trying
 				 * to do it.
 				 */
-				vt_cons[console]->vt_newvt = -1;
+				vc->vt_newvt = -1;
 
-			else
-			{
+			else {
 				/*
 				 * The current vt has been released, so
 				 * complete the switch.
 				 */
 				int newvt;
 				acquire_console_sem();
-				newvt = vt_cons[console]->vt_newvt;
-				vt_cons[console]->vt_newvt = -1;
+				newvt = vc->vt_newvt;
+				vc->vt_newvt = -1;
 				i = vc_allocate(newvt);
 				if (i) {
 					release_console_sem();
@@ -796,7 +791,7 @@
 				 * make sure we are atomic with respect to
 				 * other console switches..
 				 */
-				complete_change_console(newvt);
+				complete_change_console(vc_cons[newvt].d);
 				release_console_sem();
 			}
 		}
@@ -852,7 +847,7 @@
 			return -EFAULT;
 		for (i = 0; i < MAX_NR_CONSOLES; i++) {
 			acquire_console_sem();
-                        vc_resize(i, cc, ll);
+			vc_resize(vc_cons[i].d, cc, ll);
 			release_console_sem();
 		}
 		return 0;
@@ -900,7 +895,7 @@
 				vc_cons[i].d->vc_scan_lines = vlin;
 			if (clin)
 				vc_cons[i].d->vc_font.height = clin;
-			vc_resize(i, cc, ll);
+			vc_resize(vc_cons[i].d, cc, ll);
 			release_console_sem();
 		}
   		return 0;
@@ -915,7 +910,7 @@
 		op.height = 0;
 		op.charcount = 256;
 		op.data = up;
-		return con_font_op(fg_console, &op);
+		return con_font_op(vc_cons[fg_console].d, &op);
 	}
 
 	case GIO_FONT: {
@@ -925,7 +920,7 @@
 		op.height = 32;
 		op.charcount = 256;
 		op.data = up;
-		return con_font_op(fg_console, &op);
+		return con_font_op(vc_cons[fg_console].d, &op);
 	}
 
 	case PIO_CMAP:
@@ -953,9 +948,10 @@
 		{
 		op.op = KD_FONT_OP_SET_DEFAULT;
 		op.data = NULL;
-		i = con_font_op(fg_console, &op);
-		if (i) return i;
-		con_set_default_unimap(fg_console);
+		i = con_font_op(vc_cons[fg_console].d, &op);
+		if (i)
+			return i;
+		con_set_default_unimap(vc_cons[fg_console].d);
 		return 0;
 		}
 #endif
@@ -966,7 +962,7 @@
 			return -EFAULT;
 		if (!perm && op.op != KD_FONT_OP_GET)
 			return -EPERM;
-		i = con_font_op(console, &op);
+		i = con_font_op(vc, &op);
 		if (i) return i;
 		if (copy_to_user(up, &op, sizeof(op)))
 			return -EFAULT;
@@ -995,13 +991,13 @@
 			return -EPERM;
 		i = copy_from_user(&ui, up, sizeof(struct unimapinit));
 		if (i) return -EFAULT;
-		con_clear_unimap(console, &ui);
+		con_clear_unimap(vc, &ui);
 		return 0;
 	      }
 
 	case PIO_UNIMAP:
 	case GIO_UNIMAP:
-		return do_unimap_ioctl(cmd, up, perm, console);
+		return do_unimap_ioctl(cmd, up, perm, vc);
 
 	case VT_LOCKSWITCH:
 		if (!capable(CAP_SYS_TTY_CONFIG))
@@ -1054,25 +1050,25 @@
 
 #define vt_wake_waitactive() wake_up(&vt_activate_queue)
 
-void reset_vc(unsigned int new_console)
+void reset_vc(struct vc_data *vc)
 {
-	vt_cons[new_console]->vc_mode = KD_TEXT;
-	kbd_table[new_console].kbdmode = VC_XLATE;
-	vt_cons[new_console]->vt_mode.mode = VT_AUTO;
-	vt_cons[new_console]->vt_mode.waitv = 0;
-	vt_cons[new_console]->vt_mode.relsig = 0;
-	vt_cons[new_console]->vt_mode.acqsig = 0;
-	vt_cons[new_console]->vt_mode.frsig = 0;
-	vt_cons[new_console]->vt_pid = -1;
-	vt_cons[new_console]->vt_newvt = -1;
+	vc->vc_mode = KD_TEXT;
+	kbd_table[vc->vc_num].kbdmode = VC_XLATE;
+	vc->vt_mode.mode = VT_AUTO;
+	vc->vt_mode.waitv = 0;
+	vc->vt_mode.relsig = 0;
+	vc->vt_mode.acqsig = 0;
+	vc->vt_mode.frsig = 0;
+	vc->vt_pid = -1;
+	vc->vt_newvt = -1;
 	if (!in_interrupt())    /* Via keyboard.c:SAK() - akpm */
-		reset_palette(new_console) ;
+		reset_palette(vc);
 }
 
 /*
  * Performs the back end of a vt switch
  */
-void complete_change_console(unsigned int new_console)
+void complete_change_console(struct vc_data *vc)
 {
 	unsigned char old_vc_mode;
 
@@ -1083,8 +1079,8 @@
 	 * KD_TEXT mode or vice versa, which means we need to blank or
 	 * unblank the screen later.
 	 */
-	old_vc_mode = vt_cons[fg_console]->vc_mode;
-	switch_screen(new_console);
+	old_vc_mode = vc_cons[fg_console].d->vc_mode;
+	switch_screen(vc);
 
 	/*
 	 * This can't appear below a successful kill_proc().  If it did,
@@ -1096,9 +1092,8 @@
 	 * To account for this we duplicate this code below only if the
 	 * controlling process is gone and we've called reset_vc.
 	 */
-	if (old_vc_mode != vt_cons[new_console]->vc_mode)
-	{
-		if (vt_cons[new_console]->vc_mode == KD_TEXT)
+	if (old_vc_mode != vc->vc_mode) {
+		if (vc->vc_mode == KD_TEXT)
 			do_unblank_screen(1);
 		else
 			do_blank_screen(1);
@@ -1109,17 +1104,13 @@
 	 * telling it that it has acquired. Also check if it has died and
 	 * clean up (similar to logic employed in change_console())
 	 */
-	if (vt_cons[new_console]->vt_mode.mode == VT_PROCESS)
-	{
+	if (vc->vt_mode.mode == VT_PROCESS) {
 		/*
 		 * Send the signal as privileged - kill_proc() will
 		 * tell us if the process has gone or something else
 		 * is awry
 		 */
-		if (kill_proc(vt_cons[new_console]->vt_pid,
-			      vt_cons[new_console]->vt_mode.acqsig,
-			      1) != 0)
-		{
+		if (kill_proc(vc->vt_pid, vc->vt_mode.acqsig, 1) != 0) {
 		/*
 		 * The controlling process has died, so we revert back to
 		 * normal operation. In this case, we'll also change back
@@ -1129,11 +1120,10 @@
 		 * this outside of VT_PROCESS but there is no single process
 		 * to account for and tracking tty count may be undesirable.
 		 */
-		        reset_vc(new_console);
+			reset_vc(vc);
 
-			if (old_vc_mode != vt_cons[new_console]->vc_mode)
-			{
-				if (vt_cons[new_console]->vc_mode == KD_TEXT)
+			if (old_vc_mode != vc->vc_mode) {
+				if (vc->vc_mode == KD_TEXT)
 					do_unblank_screen(1);
 				else
 					do_blank_screen(1);
@@ -1151,11 +1141,11 @@
 /*
  * Performs the front-end of a vt switch
  */
-void change_console(unsigned int new_console)
+void change_console(struct vc_data *new_vc)
 {
-        if ((new_console == fg_console) || (vt_dont_switch))
-                return;
-        if (!vc_cons_allocated(new_console))
+	struct vc_data *vc;
+
+	if (!new_vc || new_vc->vc_num == fg_console || vt_dont_switch)
 		return;
 
 	/*
@@ -1173,23 +1163,20 @@
 	 * the user waits just the right amount of time :-) and revert the
 	 * vt to auto control.
 	 */
-	if (vt_cons[fg_console]->vt_mode.mode == VT_PROCESS)
-	{
+	vc = vc_cons[fg_console].d;
+	if (vc->vt_mode.mode == VT_PROCESS) {
 		/*
 		 * Send the signal as privileged - kill_proc() will
 		 * tell us if the process has gone or something else
 		 * is awry
 		 */
-		if (kill_proc(vt_cons[fg_console]->vt_pid,
-			      vt_cons[fg_console]->vt_mode.relsig,
-			      1) == 0)
-		{
+		if (kill_proc(vc->vt_pid, vc->vt_mode.relsig, 1) == 0) {
 			/*
 			 * It worked. Mark the vt to switch to and
 			 * return. The process needs to send us a
 			 * VT_RELDISP ioctl to complete the switch.
 			 */
-			vt_cons[fg_console]->vt_newvt = new_console;
+			vc->vt_newvt = new_vc->vc_num;
 			return;
 		}
 
@@ -1202,7 +1189,7 @@
 		 * this outside of VT_PROCESS but there is no single process
 		 * to account for and tracking tty count may be undesirable.
 		 */
-		reset_vc(fg_console);
+		reset_vc(vc);
 
 		/*
 		 * Fall through to normal (VT_AUTO) handling of the switch...
@@ -1212,8 +1199,8 @@
 	/*
 	 * Ignore all switches in KD_GRAPHICS+VT_AUTO mode
 	 */
-	if (vt_cons[fg_console]->vc_mode == KD_GRAPHICS)
+	if (vc->vc_mode == KD_GRAPHICS)
 		return;
 
-	complete_change_console(new_console);
+	complete_change_console(new_vc);
 }
diff -Nru a/drivers/char/watchdog/Kconfig b/drivers/char/watchdog/Kconfig
--- a/drivers/char/watchdog/Kconfig	2005-03-11 12:51:47 -08:00
+++ b/drivers/char/watchdog/Kconfig	2005-03-11 12:51:47 -08:00
@@ -268,12 +268,12 @@
 
 config SCx200_WDT
 	tristate "National Semiconductor SCx200 Watchdog"
-	depends on WATCHDOG && X86 && PCI
+	depends on WATCHDOG && SCx200 && PCI
 	help
 	  Enable the built-in watchdog timer support on the National
 	  Semiconductor SCx200 processors.
 
-	  If compiled as a module, it will be called scx200_watchdog.
+	  If compiled as a module, it will be called scx200_wdt.
 
 config 60XX_WDT
 	tristate "SBC-60XX Watchdog Timer"
diff -Nru a/drivers/char/watchdog/pcwd_usb.c b/drivers/char/watchdog/pcwd_usb.c
--- a/drivers/char/watchdog/pcwd_usb.c	2005-03-11 12:51:42 -08:00
+++ b/drivers/char/watchdog/pcwd_usb.c	2005-03-11 12:51:42 -08:00
@@ -227,7 +227,7 @@
 	if (usb_control_msg(usb_pcwd->udev, usb_sndctrlpipe(usb_pcwd->udev, 0),
 			HID_REQ_SET_REPORT, HID_DT_REPORT,
 			0x0200, usb_pcwd->interface_number, buf, sizeof(buf),
-			HZ) != sizeof(buf)) {
+			1000) != sizeof(buf)) {
 		dbg("usb_pcwd_send_command: error in usb_control_msg for cmd 0x%x 0x%x 0x%x\n", cmd, *msb, *lsb);
 	}
 	/* wait till the usb card processed the command,
diff -Nru a/drivers/char/watchdog/s3c2410_wdt.c b/drivers/char/watchdog/s3c2410_wdt.c
--- a/drivers/char/watchdog/s3c2410_wdt.c	2005-03-11 12:51:47 -08:00
+++ b/drivers/char/watchdog/s3c2410_wdt.c	2005-03-11 12:51:47 -08:00
@@ -26,6 +26,8 @@
  *	05-Oct-2004	BJD	Added semaphore init to stop crashes on open
  *				Fixed tmr_count / wdt_count confusion
  *				Added configurable debug
+ *
+ *	10-Mar-2005	LCVR	Changed S3C2410_VA to S3C24XX_VA
 */
 
 #include <linux/module.h>
@@ -48,8 +50,8 @@
 #include <asm/arch/map.h>
 #include <asm/hardware/clock.h>
 
-#undef S3C2410_VA_WATCHDOG
-#define S3C2410_VA_WATCHDOG (0)
+#undef S3C24XX_VA_WATCHDOG
+#define S3C24XX_VA_WATCHDOG (0)
 
 #include <asm/arch/regs-watchdog.h>
 
diff -Nru a/drivers/char/watchdog/sa1100_wdt.c b/drivers/char/watchdog/sa1100_wdt.c
--- a/drivers/char/watchdog/sa1100_wdt.c	2005-03-11 12:51:46 -08:00
+++ b/drivers/char/watchdog/sa1100_wdt.c	2005-03-11 12:51:46 -08:00
@@ -35,7 +35,7 @@
 #include <asm/bitops.h>
 #include <asm/uaccess.h>
 
-#define OSCR_FREQ		3686400
+#define OSCR_FREQ		CLOCK_TICK_RATE
 #define SA1100_CLOSE_MAGIC	(0x5afc4453)
 
 static unsigned long sa1100wdt_users;
diff -Nru a/drivers/char/watchdog/scx200_wdt.c b/drivers/char/watchdog/scx200_wdt.c
--- a/drivers/char/watchdog/scx200_wdt.c	2005-03-11 12:51:47 -08:00
+++ b/drivers/char/watchdog/scx200_wdt.c	2005-03-11 12:51:47 -08:00
@@ -4,7 +4,7 @@
 
    Copyright (c) 2001,2002 Christer Weinigel <wingel@nano-system.com>
 
-   Som code taken from:
+   Some code taken from:
    National Semiconductor PC87307/PC97307 (ala SC1200) WDT driver
    (c) Copyright 2002 Zwane Mwaikambo <zwane@commfireservices.com>
 
@@ -64,7 +64,7 @@
 
 static void scx200_wdt_ping(void)
 {
-	outw(wdto_restart, SCx200_CB_BASE + SCx200_WDT_WDTO);
+	outw(wdto_restart, scx200_cb_base + SCx200_WDT_WDTO);
 }
 
 static void scx200_wdt_update_margin(void)
@@ -78,9 +78,9 @@
 	printk(KERN_DEBUG NAME ": enabling watchdog timer, wdto_restart = %d\n",
 	       wdto_restart);
 
-	outw(0, SCx200_CB_BASE + SCx200_WDT_WDTO);
-	outb(SCx200_WDT_WDSTS_WDOVF, SCx200_CB_BASE + SCx200_WDT_WDSTS);
-	outw(W_ENABLE, SCx200_CB_BASE + SCx200_WDT_WDCNFG);
+	outw(0, scx200_cb_base + SCx200_WDT_WDTO);
+	outb(SCx200_WDT_WDSTS_WDOVF, scx200_cb_base + SCx200_WDT_WDSTS);
+	outw(W_ENABLE, scx200_cb_base + SCx200_WDT_WDCNFG);
 
 	scx200_wdt_ping();
 }
@@ -89,9 +89,9 @@
 {
 	printk(KERN_DEBUG NAME ": disabling watchdog timer\n");
 
-	outw(0, SCx200_CB_BASE + SCx200_WDT_WDTO);
-	outb(SCx200_WDT_WDSTS_WDOVF, SCx200_CB_BASE + SCx200_WDT_WDSTS);
-	outw(W_DISABLE, SCx200_CB_BASE + SCx200_WDT_WDCNFG);
+	outw(0, scx200_cb_base + SCx200_WDT_WDTO);
+	outb(SCx200_WDT_WDSTS_WDOVF, scx200_cb_base + SCx200_WDT_WDSTS);
+	outw(W_DISABLE, scx200_cb_base + SCx200_WDT_WDCNFG);
 }
 
 static int scx200_wdt_open(struct inode *inode, struct file *file)
@@ -217,28 +217,14 @@
 static int __init scx200_wdt_init(void)
 {
 	int r;
-	static struct pci_device_id ns_sc[] = {
-		{ PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_SCx200_BRIDGE) },
-		{ PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_SC1100_BRIDGE) },
-		{ },
-	};
 
 	printk(KERN_DEBUG NAME ": NatSemi SCx200 Watchdog Driver\n");
 
-	/*
-	 * First check that this really is a NatSemi SCx200 CPU or a Geode
-	 * SC1100 processor
-	 */
-	if (!pci_dev_present(ns_sc))
-		return -ENODEV;
-
-	/* More sanity checks, verify that the configuration block is there */
-	if (!scx200_cb_probe(SCx200_CB_BASE)) {
-		printk(KERN_WARNING NAME ": no configuration block found\n");
+	/* check that we have found the configuration block */
+	if (!scx200_cb_present())
 		return -ENODEV;
-	}
 
-	if (!request_region(SCx200_CB_BASE + SCx200_WDT_OFFSET,
+	if (!request_region(scx200_cb_base + SCx200_WDT_OFFSET,
 			    SCx200_WDT_SIZE,
 			    "NatSemi SCx200 Watchdog")) {
 		printk(KERN_WARNING NAME ": watchdog I/O region busy\n");
@@ -252,7 +238,7 @@
 
 	r = misc_register(&scx200_wdt_miscdev);
 	if (r) {
-		release_region(SCx200_CB_BASE + SCx200_WDT_OFFSET,
+		release_region(scx200_cb_base + SCx200_WDT_OFFSET,
 				SCx200_WDT_SIZE);
 		return r;
 	}
@@ -261,7 +247,7 @@
 	if (r) {
 		printk(KERN_ERR NAME ": unable to register reboot notifier");
 		misc_deregister(&scx200_wdt_miscdev);
-		release_region(SCx200_CB_BASE + SCx200_WDT_OFFSET,
+		release_region(scx200_cb_base + SCx200_WDT_OFFSET,
 				SCx200_WDT_SIZE);
 		return r;
 	}
@@ -273,7 +259,7 @@
 {
 	unregister_reboot_notifier(&scx200_wdt_notifier);
 	misc_deregister(&scx200_wdt_miscdev);
-	release_region(SCx200_CB_BASE + SCx200_WDT_OFFSET,
+	release_region(scx200_cb_base + SCx200_WDT_OFFSET,
 		       SCx200_WDT_SIZE);
 }
 
diff -Nru a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c
--- a/drivers/firmware/efivars.c	2005-03-11 12:51:51 -08:00
+++ b/drivers/firmware/efivars.c	2005-03-11 12:51:51 -08:00
@@ -665,14 +665,22 @@
 {
 	efi_status_t status = EFI_NOT_FOUND;
 	efi_guid_t vendor_guid;
-	efi_char16_t *variable_name = kmalloc(1024, GFP_KERNEL);
+	efi_char16_t *variable_name;
 	struct subsys_attribute *attr;
 	unsigned long variable_name_size = 1024;
-	int i, rc = 0, error = 0;
+	int i, error = 0;
 
 	if (!efi_enabled)
 		return -ENODEV;
 
+	variable_name = kmalloc(variable_name_size, GFP_KERNEL);
+	if (!variable_name) {
+		printk(KERN_ERR "efivars: Memory allocation failed.\n");
+		return -ENOMEM;
+	}
+
+	memset(variable_name, 0, variable_name_size);
+
 	printk(KERN_INFO "EFI Variables Facility v%s %s\n", EFIVARS_VERSION,
 	       EFIVARS_DATE);
 
@@ -680,21 +688,27 @@
 	 * For now we'll register the efi subsys within this driver
 	 */
 
-	rc = firmware_register(&efi_subsys);
+	error = firmware_register(&efi_subsys);
 
-	if (rc)
-		return rc;
+	if (error) {
+		printk(KERN_ERR "efivars: Firmware registration failed with error %d.\n", error);
+		goto out_free;
+	}
 
 	kset_set_kset_s(&vars_subsys, efi_subsys);
-	subsystem_register(&vars_subsys);
+
+	error = subsystem_register(&vars_subsys);
+
+	if (error) {
+		printk(KERN_ERR "efivars: Subsystem registration failed with error %d.\n", error);
+		goto out_firmware_unregister;
+	}
 
 	/*
 	 * Per EFI spec, the maximum storage allocated for both
 	 * the variable name and variable data is 1024 bytes.
 	 */
 
-	memset(variable_name, 0, 1024);
-
 	do {
 		variable_name_size = 1024;
 
@@ -734,8 +748,20 @@
 			error = subsys_create_file(&efi_subsys, attr);
 	}
 
+	if (error)
+		printk(KERN_ERR "efivars: Sysfs attribute export failed with error %d.\n", error);
+	else
+		goto out_free;
+
+	subsystem_unregister(&vars_subsys);
+
+out_firmware_unregister:
+	firmware_unregister(&efi_subsys);
+
+out_free:
 	kfree(variable_name);
-	return 0;
+
+	return error;
 }
 
 static void __exit
diff -Nru a/drivers/i2c/algos/i2c-algo-ite.c b/drivers/i2c/algos/i2c-algo-ite.c
--- a/drivers/i2c/algos/i2c-algo-ite.c	2005-03-11 12:51:51 -08:00
+++ b/drivers/i2c/algos/i2c-algo-ite.c	2005-03-11 12:51:51 -08:00
@@ -490,7 +490,7 @@
  * condition.
  */
 #if 0
-static int iic_combined_transaction(struct i2c_adapter *i2c_adap, struct i2c_msg msgs[], int num) 
+static int iic_combined_transaction(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, int num) 
 {
    int i;
    struct i2c_msg *pmsg;
@@ -600,7 +600,7 @@
  * verify that the bus is not busy or in some unknown state.
  */
 static int iic_xfer(struct i2c_adapter *i2c_adap,
-		    struct i2c_msg msgs[], 
+		    struct i2c_msg *msgs, 
 		    int num)
 {
 	struct i2c_algo_iic_data *adap = i2c_adap->algo_data;
diff -Nru a/drivers/i2c/algos/i2c-algo-pca.c b/drivers/i2c/algos/i2c-algo-pca.c
--- a/drivers/i2c/algos/i2c-algo-pca.c	2005-03-11 12:51:47 -08:00
+++ b/drivers/i2c/algos/i2c-algo-pca.c	2005-03-11 12:51:47 -08:00
@@ -178,7 +178,7 @@
 }
 
 static int pca_xfer(struct i2c_adapter *i2c_adap,
-                    struct i2c_msg msgs[],
+                    struct i2c_msg *msgs,
                     int num)
 {
         struct i2c_algo_pca_data *adap = i2c_adap->algo_data;
@@ -186,6 +186,7 @@
         int curmsg;
 	int numbytes = 0;
 	int state;
+	int ret;
 
 	state = pca_status(adap);
 	if ( state != 0xF8 ) {
@@ -218,6 +219,7 @@
 	}
 
 	curmsg = 0;
+	ret = -EREMOTEIO;
 	while (curmsg < num) {
 		state = pca_status(adap);
 
@@ -251,7 +253,7 @@
 		case 0x20: /* SLA+W has been transmitted; NOT ACK has been received */
 			DEB2("NOT ACK received after SLA+W\n");
 			pca_stop(adap);
-			return -EREMOTEIO;
+			goto out;
 
 		case 0x40: /* SLA+R has been transmitted; ACK has been received */
 			pca_rx_ack(adap, msg->len > 1);
@@ -263,7 +265,7 @@
 				numbytes++;
 				pca_rx_ack(adap, numbytes < msg->len - 1);
 				break;
-			} 
+			}
 			curmsg++; numbytes = 0;
 			if (curmsg == num)
 				pca_stop(adap);
@@ -274,15 +276,15 @@
 		case 0x48: /* SLA+R has been transmitted; NOT ACK has been received */
 			DEB2("NOT ACK received after SLA+R\n");
 			pca_stop(adap);
-			return -EREMOTEIO;
+			goto out;
 
 		case 0x30: /* Data byte in I2CDAT has been transmitted; NOT ACK has been received */
 			DEB2("NOT ACK received after data byte\n");
-			return -EREMOTEIO;
+			goto out;
 
 		case 0x38: /* Arbitration lost during SLA+W, SLA+R or data bytes */
 			DEB2("Arbitration lost\n");
-			return -EREMOTEIO;
+			goto out;
 			
 		case 0x58: /* Data byte has been received; NOT ACK has been returned */
 			if ( numbytes == msg->len - 1 ) {
@@ -297,21 +299,21 @@
 				     "Not final byte. numbytes %d. len %d\n",
 				     numbytes, msg->len);
 				pca_stop(adap);
-				return -EREMOTEIO;
+				goto out;
 			}
 			break;
 		case 0x70: /* Bus error - SDA stuck low */
 			DEB2("BUS ERROR - SDA Stuck low\n");
 			pca_reset(adap);
-			return -EREMOTEIO;
+			goto out;
 		case 0x90: /* Bus error - SCL stuck low */
 			DEB2("BUS ERROR - SCL Stuck low\n");
 			pca_reset(adap);
-			return -EREMOTEIO;
+			goto out;
 		case 0x00: /* Bus error during master or slave mode due to illegal START or STOP condition */
 			DEB2("BUS ERROR - Illegal START or STOP\n");
 			pca_reset(adap);
-			return -EREMOTEIO;
+			goto out;
 		default:
 			printk(KERN_ERR DRIVER ": unhandled SIO state 0x%02x\n", state);
 			break;
@@ -319,11 +321,13 @@
 		
 	}
 
-	DEB1(KERN_CRIT "}}} transfered %d messages. "
+	ret = curmsg;
+ out:
+	DEB1(KERN_CRIT "}}} transfered %d/%d messages. "
 	     "status is %#04x. control is %#04x\n", 
-	     num, pca_status(adap),
+	     curmsg, num, pca_status(adap),
 	     pca_get_con(adap));
-	return curmsg;
+	return ret;
 }
 
 static u32 pca_func(struct i2c_adapter *adap)
diff -Nru a/drivers/i2c/algos/i2c-algo-pcf.c b/drivers/i2c/algos/i2c-algo-pcf.c
--- a/drivers/i2c/algos/i2c-algo-pcf.c	2005-03-11 12:51:50 -08:00
+++ b/drivers/i2c/algos/i2c-algo-pcf.c	2005-03-11 12:51:50 -08:00
@@ -332,7 +332,7 @@
 }
 
 static int pcf_xfer(struct i2c_adapter *i2c_adap,
-		    struct i2c_msg msgs[], 
+		    struct i2c_msg *msgs, 
 		    int num)
 {
 	struct i2c_algo_pcf_data *adap = i2c_adap->algo_data;
diff -Nru a/drivers/i2c/algos/i2c-algo-sgi.c b/drivers/i2c/algos/i2c-algo-sgi.c
--- a/drivers/i2c/algos/i2c-algo-sgi.c	2005-03-11 12:51:41 -08:00
+++ b/drivers/i2c/algos/i2c-algo-sgi.c	2005-03-11 12:51:41 -08:00
@@ -131,7 +131,7 @@
 	return 0;
 }
 
-static int sgi_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msgs[],
+static int sgi_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs,
 		    int num)
 {
 	struct i2c_algo_sgi_data *adap = i2c_adap->algo_data;
diff -Nru a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
--- a/drivers/i2c/busses/Kconfig	2005-03-11 12:51:51 -08:00
+++ b/drivers/i2c/busses/Kconfig	2005-03-11 12:51:51 -08:00
@@ -287,7 +287,7 @@
 
 config I2C_PIIX4
 	tristate "Intel PIIX4"
-	depends on I2C && PCI && EXPERIMENTAL && !64BIT
+	depends on I2C && PCI && EXPERIMENTAL
 	help
 	  If you say yes to this option, support will be included for the Intel
 	  PIIX4 family of mainboard I2C interfaces.  Specifically, the following
@@ -485,5 +485,15 @@
 	  
 	  This driver can also be built as a module.  If so, the module
 	  will be called i2c-pca-isa.
+
+config I2C_MV64XXX
+	tristate "Marvell mv64xxx I2C Controller"
+	depends on I2C && MV64X60 && EXPERIMENTAL
+	help
+	  If you say yes to this option, support will be included for the
+	  built-in I2C interface on the Marvell 64xxx line of host bridges.
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called i2c-mv64xxx.
 
 endmenu
diff -Nru a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
--- a/drivers/i2c/busses/Makefile	2005-03-11 12:51:52 -08:00
+++ b/drivers/i2c/busses/Makefile	2005-03-11 12:51:52 -08:00
@@ -21,6 +21,7 @@
 obj-$(CONFIG_I2C_IXP4XX)	+= i2c-ixp4xx.o
 obj-$(CONFIG_I2C_KEYWEST)	+= i2c-keywest.o
 obj-$(CONFIG_I2C_MPC)		+= i2c-mpc.o
+obj-$(CONFIG_I2C_MV64XXX)	+= i2c-mv64xxx.o
 obj-$(CONFIG_I2C_NFORCE2)	+= i2c-nforce2.o
 obj-$(CONFIG_I2C_PARPORT)	+= i2c-parport.o
 obj-$(CONFIG_I2C_PARPORT_LIGHT)	+= i2c-parport-light.o
diff -Nru a/drivers/i2c/busses/i2c-au1550.c b/drivers/i2c/busses/i2c-au1550.c
--- a/drivers/i2c/busses/i2c-au1550.c	2005-03-11 12:51:51 -08:00
+++ b/drivers/i2c/busses/i2c-au1550.c	2005-03-11 12:51:51 -08:00
@@ -253,7 +253,7 @@
 }
 
 static int
-au1550_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msgs[], int num)
+au1550_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, int num)
 {
 	struct i2c_au1550_data *adap = i2c_adap->algo_data;
 	struct i2c_msg *p;
diff -Nru a/drivers/i2c/busses/i2c-elektor.c b/drivers/i2c/busses/i2c-elektor.c
--- a/drivers/i2c/busses/i2c-elektor.c	2005-03-11 12:51:41 -08:00
+++ b/drivers/i2c/busses/i2c-elektor.c	2005-03-11 12:51:41 -08:00
@@ -183,6 +183,7 @@
 
 static struct i2c_adapter pcf_isa_ops = {
 	.owner		= THIS_MODULE,
+	.class		= I2C_CLASS_HWMON,
 	.id		= I2C_HW_P_ELEK,
 	.algo_data	= &pcf_isa_data,
 	.name		= "PCF8584 ISA adapter",
diff -Nru a/drivers/i2c/busses/i2c-ibm_iic.c b/drivers/i2c/busses/i2c-ibm_iic.c
--- a/drivers/i2c/busses/i2c-ibm_iic.c	2005-03-11 12:51:47 -08:00
+++ b/drivers/i2c/busses/i2c-ibm_iic.c	2005-03-11 12:51:47 -08:00
@@ -549,7 +549,7 @@
  * Generic master transfer entrypoint. 
  * Returns the number of processed messages or error (<0)
  */
-static int iic_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
+static int iic_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
 {
     	struct ibm_iic_private* dev = (struct ibm_iic_private*)(i2c_get_adapdata(adap));
 	volatile struct iic_regs __iomem *iic = dev->vaddr;
diff -Nru a/drivers/i2c/busses/i2c-iop3xx.c b/drivers/i2c/busses/i2c-iop3xx.c
--- a/drivers/i2c/busses/i2c-iop3xx.c	2005-03-11 12:51:46 -08:00
+++ b/drivers/i2c/busses/i2c-iop3xx.c	2005-03-11 12:51:46 -08:00
@@ -361,7 +361,7 @@
  * master_xfer() - main read/write entry
  */
 static int 
-iop3xx_i2c_master_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msgs[], 
+iop3xx_i2c_master_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, 
 				int num)
 {
 	struct i2c_algo_iop3xx_data *iop3xx_adap = i2c_adap->algo_data;
diff -Nru a/drivers/i2c/busses/i2c-ixp4xx.c b/drivers/i2c/busses/i2c-ixp4xx.c
--- a/drivers/i2c/busses/i2c-ixp4xx.c	2005-03-11 12:51:46 -08:00
+++ b/drivers/i2c/busses/i2c-ixp4xx.c	2005-03-11 12:51:46 -08:00
@@ -133,8 +133,8 @@
 	drv_data->algo_data.mdelay = 10;
 	drv_data->algo_data.timeout = 100;
 
-	drv_data->adapter.id = I2C_HW_B_IXP4XX,
-	drv_data->adapter.algo_data = &drv_data->algo_data,
+	drv_data->adapter.id = I2C_HW_B_IXP4XX;
+	drv_data->adapter.algo_data = &drv_data->algo_data;
 
 	drv_data->adapter.dev.parent = &plat_dev->dev;
 
diff -Nru a/drivers/i2c/busses/i2c-keywest.c b/drivers/i2c/busses/i2c-keywest.c
--- a/drivers/i2c/busses/i2c-keywest.c	2005-03-11 12:51:47 -08:00
+++ b/drivers/i2c/busses/i2c-keywest.c	2005-03-11 12:51:47 -08:00
@@ -399,7 +399,7 @@
  */
 static int
 keywest_xfer(	struct i2c_adapter *adap,
-		struct i2c_msg msgs[], 
+		struct i2c_msg *msgs, 
 		int num)
 {
 	struct keywest_chan* chan = i2c_get_adapdata(adap);
diff -Nru a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c
--- a/drivers/i2c/busses/i2c-mpc.c	2005-03-11 12:51:43 -08:00
+++ b/drivers/i2c/busses/i2c-mpc.c	2005-03-11 12:51:43 -08:00
@@ -233,7 +233,7 @@
 	return length;
 }
 
-static int mpc_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
+static int mpc_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
 {
 	struct i2c_msg *pmsg;
 	int i;
diff -Nru a/drivers/i2c/busses/i2c-mv64xxx.c b/drivers/i2c/busses/i2c-mv64xxx.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/i2c/busses/i2c-mv64xxx.c	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,596 @@
+/*
+ * drivers/i2c/busses/i2c-mv64xxx.c
+ * 
+ * Driver for the i2c controller on the Marvell line of host bridges for MIPS
+ * and PPC (e.g, gt642[46]0, mv643[46]0, mv644[46]0).
+ *
+ * Author: Mark A. Greer <mgreer@mvista.com>
+ *
+ * 2005 (c) MontaVista, Software, Inc.  This file is licensed under
+ * the terms of the GNU General Public License version 2.  This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/mv643xx.h>
+#include <asm/io.h>
+
+/* Register defines */
+#define	MV64XXX_I2C_REG_SLAVE_ADDR			0x00
+#define	MV64XXX_I2C_REG_DATA				0x04
+#define	MV64XXX_I2C_REG_CONTROL				0x08
+#define	MV64XXX_I2C_REG_STATUS				0x0c
+#define	MV64XXX_I2C_REG_BAUD				0x0c
+#define	MV64XXX_I2C_REG_EXT_SLAVE_ADDR			0x10
+#define	MV64XXX_I2C_REG_SOFT_RESET			0x1c
+
+#define	MV64XXX_I2C_REG_CONTROL_ACK			0x00000004
+#define	MV64XXX_I2C_REG_CONTROL_IFLG			0x00000008
+#define	MV64XXX_I2C_REG_CONTROL_STOP			0x00000010
+#define	MV64XXX_I2C_REG_CONTROL_START			0x00000020
+#define	MV64XXX_I2C_REG_CONTROL_TWSIEN			0x00000040
+#define	MV64XXX_I2C_REG_CONTROL_INTEN			0x00000080
+
+/* Ctlr status values */
+#define	MV64XXX_I2C_STATUS_BUS_ERR			0x00
+#define	MV64XXX_I2C_STATUS_MAST_START			0x08
+#define	MV64XXX_I2C_STATUS_MAST_REPEAT_START		0x10
+#define	MV64XXX_I2C_STATUS_MAST_WR_ADDR_ACK		0x18
+#define	MV64XXX_I2C_STATUS_MAST_WR_ADDR_NO_ACK		0x20
+#define	MV64XXX_I2C_STATUS_MAST_WR_ACK			0x28
+#define	MV64XXX_I2C_STATUS_MAST_WR_NO_ACK		0x30
+#define	MV64XXX_I2C_STATUS_MAST_LOST_ARB		0x38
+#define	MV64XXX_I2C_STATUS_MAST_RD_ADDR_ACK		0x40
+#define	MV64XXX_I2C_STATUS_MAST_RD_ADDR_NO_ACK		0x48
+#define	MV64XXX_I2C_STATUS_MAST_RD_DATA_ACK		0x50
+#define	MV64XXX_I2C_STATUS_MAST_RD_DATA_NO_ACK		0x58
+#define	MV64XXX_I2C_STATUS_MAST_WR_ADDR_2_ACK		0xd0
+#define	MV64XXX_I2C_STATUS_MAST_WR_ADDR_2_NO_ACK	0xd8
+#define	MV64XXX_I2C_STATUS_MAST_RD_ADDR_2_ACK		0xe0
+#define	MV64XXX_I2C_STATUS_MAST_RD_ADDR_2_NO_ACK	0xe8
+#define	MV64XXX_I2C_STATUS_NO_STATUS			0xf8
+
+/* Driver states */
+enum {
+	MV64XXX_I2C_STATE_INVALID,
+	MV64XXX_I2C_STATE_IDLE,
+	MV64XXX_I2C_STATE_WAITING_FOR_START_COND,
+	MV64XXX_I2C_STATE_WAITING_FOR_ADDR_1_ACK,
+	MV64XXX_I2C_STATE_WAITING_FOR_ADDR_2_ACK,
+	MV64XXX_I2C_STATE_WAITING_FOR_SLAVE_ACK,
+	MV64XXX_I2C_STATE_WAITING_FOR_SLAVE_DATA,
+	MV64XXX_I2C_STATE_ABORTING,
+};
+
+/* Driver actions */
+enum {
+	MV64XXX_I2C_ACTION_INVALID,
+	MV64XXX_I2C_ACTION_CONTINUE,
+	MV64XXX_I2C_ACTION_SEND_START,
+	MV64XXX_I2C_ACTION_SEND_ADDR_1,
+	MV64XXX_I2C_ACTION_SEND_ADDR_2,
+	MV64XXX_I2C_ACTION_SEND_DATA,
+	MV64XXX_I2C_ACTION_RCV_DATA,
+	MV64XXX_I2C_ACTION_RCV_DATA_STOP,
+	MV64XXX_I2C_ACTION_SEND_STOP,
+};
+
+struct mv64xxx_i2c_data {
+	int			irq;
+	u32			state;
+	u32			action;
+	u32			cntl_bits;
+	void __iomem		*reg_base;
+	u32			reg_base_p;
+	u32			addr1;
+	u32			addr2;
+	u32			bytes_left;
+	u32			byte_posn;
+	u32			block;
+	int			rc;
+	u32			freq_m;
+	u32			freq_n;
+	wait_queue_head_t	waitq;
+	spinlock_t		lock;
+	struct i2c_msg		*msg;
+	struct i2c_adapter	adapter;
+};
+
+/*
+ *****************************************************************************
+ *
+ *	Finite State Machine & Interrupt Routines
+ *
+ *****************************************************************************
+ */
+static void
+mv64xxx_i2c_fsm(struct mv64xxx_i2c_data *drv_data, u32 status)
+{
+	/*
+	 * If state is idle, then this is likely the remnants of an old
+	 * operation that driver has given up on or the user has killed.
+	 * If so, issue the stop condition and go to idle.
+	 */
+	if (drv_data->state == MV64XXX_I2C_STATE_IDLE) {
+		drv_data->action = MV64XXX_I2C_ACTION_SEND_STOP;
+		return;
+	}
+
+	if (drv_data->state == MV64XXX_I2C_STATE_ABORTING) {
+		drv_data->action = MV64XXX_I2C_ACTION_SEND_STOP;
+		drv_data->state = MV64XXX_I2C_STATE_IDLE;
+		return;
+	}
+
+	/* The status from the ctlr [mostly] tells us what to do next */
+	switch (status) {
+	/* Start condition interrupt */
+	case MV64XXX_I2C_STATUS_MAST_START: /* 0x08 */
+	case MV64XXX_I2C_STATUS_MAST_REPEAT_START: /* 0x10 */
+		drv_data->action = MV64XXX_I2C_ACTION_SEND_ADDR_1;
+		drv_data->state = MV64XXX_I2C_STATE_WAITING_FOR_ADDR_1_ACK;
+		break;
+
+	/* Performing a write */
+	case MV64XXX_I2C_STATUS_MAST_WR_ADDR_ACK: /* 0x18 */
+		if (drv_data->msg->flags & I2C_M_TEN) {
+			drv_data->action = MV64XXX_I2C_ACTION_SEND_ADDR_2;
+			drv_data->state =
+				MV64XXX_I2C_STATE_WAITING_FOR_ADDR_2_ACK;
+			break;
+		}
+		/* FALLTHRU */
+	case MV64XXX_I2C_STATUS_MAST_WR_ADDR_2_ACK: /* 0xd0 */
+	case MV64XXX_I2C_STATUS_MAST_WR_ACK: /* 0x28 */
+		if (drv_data->bytes_left > 0) {
+			drv_data->action = MV64XXX_I2C_ACTION_SEND_DATA;
+			drv_data->state =
+				MV64XXX_I2C_STATE_WAITING_FOR_SLAVE_ACK;
+			drv_data->bytes_left--;
+		} else {
+			drv_data->action = MV64XXX_I2C_ACTION_SEND_STOP;
+			drv_data->state = MV64XXX_I2C_STATE_IDLE;
+		}
+		break;
+
+	/* Performing a read */
+	case MV64XXX_I2C_STATUS_MAST_RD_ADDR_ACK: /* 40 */
+		if (drv_data->msg->flags & I2C_M_TEN) {
+			drv_data->action = MV64XXX_I2C_ACTION_SEND_ADDR_2;
+			drv_data->state =
+				MV64XXX_I2C_STATE_WAITING_FOR_ADDR_2_ACK;
+			break;
+		}
+		/* FALLTHRU */
+	case MV64XXX_I2C_STATUS_MAST_RD_ADDR_2_ACK: /* 0xe0 */
+		if (drv_data->bytes_left == 0) {
+			drv_data->action = MV64XXX_I2C_ACTION_SEND_STOP;
+			drv_data->state = MV64XXX_I2C_STATE_IDLE;
+			break;
+		}
+		/* FALLTHRU */
+	case MV64XXX_I2C_STATUS_MAST_RD_DATA_ACK: /* 0x50 */
+		if (status != MV64XXX_I2C_STATUS_MAST_RD_DATA_ACK)
+			drv_data->action = MV64XXX_I2C_ACTION_CONTINUE;
+		else {
+			drv_data->action = MV64XXX_I2C_ACTION_RCV_DATA;
+			drv_data->bytes_left--;
+		}
+		drv_data->state = MV64XXX_I2C_STATE_WAITING_FOR_SLAVE_DATA;
+
+		if (drv_data->bytes_left == 1)
+			drv_data->cntl_bits &= ~MV64XXX_I2C_REG_CONTROL_ACK;
+		break;
+
+	case MV64XXX_I2C_STATUS_MAST_RD_DATA_NO_ACK: /* 0x58 */
+		drv_data->action = MV64XXX_I2C_ACTION_RCV_DATA_STOP;
+		drv_data->state = MV64XXX_I2C_STATE_IDLE;
+		break;
+
+	case MV64XXX_I2C_STATUS_MAST_WR_ADDR_NO_ACK: /* 0x20 */
+	case MV64XXX_I2C_STATUS_MAST_WR_NO_ACK: /* 30 */
+	case MV64XXX_I2C_STATUS_MAST_RD_ADDR_NO_ACK: /* 48 */
+		/* Doesn't seem to be a device at other end */
+		drv_data->action = MV64XXX_I2C_ACTION_SEND_STOP;
+		drv_data->state = MV64XXX_I2C_STATE_IDLE;
+		drv_data->rc = -ENODEV;
+		break;
+
+	default:
+		dev_err(&drv_data->adapter.dev,
+			"mv64xxx_i2c_fsm: Ctlr Error -- state: 0x%x, "
+			"status: 0x%x, addr: 0x%x, flags: 0x%x\n",
+			 drv_data->state, status, drv_data->msg->addr,
+			 drv_data->msg->flags);
+		drv_data->action = MV64XXX_I2C_ACTION_SEND_STOP;
+		drv_data->state = MV64XXX_I2C_STATE_IDLE;
+		drv_data->rc = -EIO;
+	}
+}
+
+static void
+mv64xxx_i2c_do_action(struct mv64xxx_i2c_data *drv_data)
+{
+	switch(drv_data->action) {
+	case MV64XXX_I2C_ACTION_CONTINUE:
+		writel(drv_data->cntl_bits,
+			drv_data->reg_base + MV64XXX_I2C_REG_CONTROL);
+		break;
+
+	case MV64XXX_I2C_ACTION_SEND_START:
+		writel(drv_data->cntl_bits | MV64XXX_I2C_REG_CONTROL_START,
+			drv_data->reg_base + MV64XXX_I2C_REG_CONTROL);
+		break;
+
+	case MV64XXX_I2C_ACTION_SEND_ADDR_1:
+		writel(drv_data->addr1,
+			drv_data->reg_base + MV64XXX_I2C_REG_DATA);
+		writel(drv_data->cntl_bits,
+			drv_data->reg_base + MV64XXX_I2C_REG_CONTROL);
+		break;
+
+	case MV64XXX_I2C_ACTION_SEND_ADDR_2:
+		writel(drv_data->addr2,
+			drv_data->reg_base + MV64XXX_I2C_REG_DATA);
+		writel(drv_data->cntl_bits,
+			drv_data->reg_base + MV64XXX_I2C_REG_CONTROL);
+		break;
+
+	case MV64XXX_I2C_ACTION_SEND_DATA:
+		writel(drv_data->msg->buf[drv_data->byte_posn++],
+			drv_data->reg_base + MV64XXX_I2C_REG_DATA);
+		writel(drv_data->cntl_bits,
+			drv_data->reg_base + MV64XXX_I2C_REG_CONTROL);
+		break;
+
+	case MV64XXX_I2C_ACTION_RCV_DATA:
+		drv_data->msg->buf[drv_data->byte_posn++] =
+			readl(drv_data->reg_base + MV64XXX_I2C_REG_DATA);
+		writel(drv_data->cntl_bits,
+			drv_data->reg_base + MV64XXX_I2C_REG_CONTROL);
+		break;
+
+	case MV64XXX_I2C_ACTION_RCV_DATA_STOP:
+		drv_data->msg->buf[drv_data->byte_posn++] =
+			readl(drv_data->reg_base + MV64XXX_I2C_REG_DATA);
+		drv_data->cntl_bits &= ~MV64XXX_I2C_REG_CONTROL_INTEN;
+		writel(drv_data->cntl_bits | MV64XXX_I2C_REG_CONTROL_STOP,
+			drv_data->reg_base + MV64XXX_I2C_REG_CONTROL);
+		drv_data->block = 0;
+		wake_up_interruptible(&drv_data->waitq);
+		break;
+
+	case MV64XXX_I2C_ACTION_INVALID:
+	default:
+		dev_err(&drv_data->adapter.dev,
+			"mv64xxx_i2c_do_action: Invalid action: %d\n",
+			drv_data->action);
+		drv_data->rc = -EIO;
+		/* FALLTHRU */
+	case MV64XXX_I2C_ACTION_SEND_STOP:
+		drv_data->cntl_bits &= ~MV64XXX_I2C_REG_CONTROL_INTEN;
+		writel(drv_data->cntl_bits | MV64XXX_I2C_REG_CONTROL_STOP,
+			drv_data->reg_base + MV64XXX_I2C_REG_CONTROL);
+		drv_data->block = 0;
+		wake_up_interruptible(&drv_data->waitq);
+		break;
+	}
+}
+
+static int
+mv64xxx_i2c_intr(int irq, void *dev_id, struct pt_regs *regs)
+{
+	struct mv64xxx_i2c_data	*drv_data = dev_id;
+	unsigned long	flags;
+	u32		status;
+	int		rc = IRQ_NONE;
+
+	spin_lock_irqsave(&drv_data->lock, flags);
+	while (readl(drv_data->reg_base + MV64XXX_I2C_REG_CONTROL) &
+						MV64XXX_I2C_REG_CONTROL_IFLG) {
+		status = readl(drv_data->reg_base + MV64XXX_I2C_REG_STATUS);
+		mv64xxx_i2c_fsm(drv_data, status);
+		mv64xxx_i2c_do_action(drv_data);
+		rc = IRQ_HANDLED;
+	}
+	spin_unlock_irqrestore(&drv_data->lock, flags);
+
+	return rc;
+}
+
+/*
+ *****************************************************************************
+ *
+ *	I2C Msg Execution Routines
+ *
+ *****************************************************************************
+ */
+static void
+mv64xxx_i2c_prepare_for_io(struct mv64xxx_i2c_data *drv_data,
+	struct i2c_msg *msg)
+{
+	u32	dir = 0;
+
+	drv_data->msg = msg;
+	drv_data->byte_posn = 0;
+	drv_data->bytes_left = msg->len;
+	drv_data->rc = 0;
+	drv_data->cntl_bits = MV64XXX_I2C_REG_CONTROL_ACK |
+		MV64XXX_I2C_REG_CONTROL_INTEN | MV64XXX_I2C_REG_CONTROL_TWSIEN;
+
+	if (msg->flags & I2C_M_RD)
+		dir = 1;
+
+	if (msg->flags & I2C_M_REV_DIR_ADDR)
+		dir ^= 1;
+
+	if (msg->flags & I2C_M_TEN) {
+		drv_data->addr1 = 0xf0 | (((u32)msg->addr & 0x300) >> 7) | dir;
+		drv_data->addr2 = (u32)msg->addr & 0xff;
+	} else {
+		drv_data->addr1 = ((u32)msg->addr & 0x7f) << 1 | dir;
+		drv_data->addr2 = 0;
+	}
+}
+
+static void
+mv64xxx_i2c_wait_for_completion(struct mv64xxx_i2c_data *drv_data)
+{
+	long		time_left;
+	unsigned long	flags;
+	char		abort = 0;
+
+	time_left = wait_event_interruptible_timeout(drv_data->waitq,
+		!drv_data->block, msecs_to_jiffies(drv_data->adapter.timeout));
+
+	spin_lock_irqsave(&drv_data->lock, flags);
+	if (!time_left) { /* Timed out */
+		drv_data->rc = -ETIMEDOUT;
+		abort = 1;
+	} else if (time_left < 0) { /* Interrupted/Error */
+		drv_data->rc = time_left; /* errno value */
+		abort = 1;
+	}
+
+	if (abort && drv_data->block) {
+		drv_data->state = MV64XXX_I2C_STATE_ABORTING;
+		spin_unlock_irqrestore(&drv_data->lock, flags);
+
+		time_left = wait_event_timeout(drv_data->waitq,
+			!drv_data->block,
+			msecs_to_jiffies(drv_data->adapter.timeout));
+
+		if (time_left <= 0) {
+			drv_data->state = MV64XXX_I2C_STATE_IDLE;
+			dev_err(&drv_data->adapter.dev,
+				"mv64xxx: I2C bus locked\n");
+		}
+	} else
+		spin_unlock_irqrestore(&drv_data->lock, flags);
+}
+
+static int
+mv64xxx_i2c_execute_msg(struct mv64xxx_i2c_data *drv_data, struct i2c_msg *msg)
+{
+	unsigned long	flags;
+
+	spin_lock_irqsave(&drv_data->lock, flags);
+	mv64xxx_i2c_prepare_for_io(drv_data, msg);
+
+	if (unlikely(msg->flags & I2C_M_NOSTART)) { /* Skip start/addr phases */
+		if (drv_data->msg->flags & I2C_M_RD) {
+			/* No action to do, wait for slave to send a byte */
+			drv_data->action = MV64XXX_I2C_ACTION_CONTINUE;
+			drv_data->state =
+				MV64XXX_I2C_STATE_WAITING_FOR_SLAVE_DATA;
+		} else {
+			drv_data->action = MV64XXX_I2C_ACTION_SEND_DATA;
+			drv_data->state =
+				MV64XXX_I2C_STATE_WAITING_FOR_SLAVE_ACK;
+			drv_data->bytes_left--;
+		}
+	} else {
+		drv_data->action = MV64XXX_I2C_ACTION_SEND_START;
+		drv_data->state = MV64XXX_I2C_STATE_WAITING_FOR_START_COND;
+	}
+
+	drv_data->block = 1;
+	mv64xxx_i2c_do_action(drv_data);
+	spin_unlock_irqrestore(&drv_data->lock, flags);
+
+	mv64xxx_i2c_wait_for_completion(drv_data);
+	return drv_data->rc;
+}
+
+/*
+ *****************************************************************************
+ *
+ *	I2C Core Support Routines (Interface to higher level I2C code)
+ *
+ *****************************************************************************
+ */
+static u32
+mv64xxx_i2c_functionality(struct i2c_adapter *adap)
+{
+	return I2C_FUNC_I2C | I2C_FUNC_10BIT_ADDR | I2C_FUNC_SMBUS_EMUL;
+}
+
+static int
+mv64xxx_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
+{
+	struct mv64xxx_i2c_data *drv_data = i2c_get_adapdata(adap);
+	int	i, rc = 0;
+
+	for (i=0; i<num; i++)
+		if ((rc = mv64xxx_i2c_execute_msg(drv_data, &msgs[i])) != 0)
+			break;
+
+	return rc;
+}
+
+static struct i2c_algorithm mv64xxx_i2c_algo = {
+	.name = MV64XXX_I2C_CTLR_NAME " algorithm",
+	.id = I2C_ALGO_MV64XXX,
+	.master_xfer = mv64xxx_i2c_xfer,
+	.functionality = mv64xxx_i2c_functionality,
+};
+
+/*
+ *****************************************************************************
+ *
+ *	Driver Interface & Early Init Routines
+ *
+ *****************************************************************************
+ */
+static void __devinit
+mv64xxx_i2c_hw_init(struct mv64xxx_i2c_data *drv_data)
+{
+	writel(0, drv_data->reg_base + MV64XXX_I2C_REG_SOFT_RESET);
+	writel((((drv_data->freq_m & 0xf) << 3) | (drv_data->freq_n & 0x7)),
+		drv_data->reg_base + MV64XXX_I2C_REG_BAUD);
+	writel(0, drv_data->reg_base + MV64XXX_I2C_REG_SLAVE_ADDR);
+	writel(0, drv_data->reg_base + MV64XXX_I2C_REG_EXT_SLAVE_ADDR);
+	writel(MV64XXX_I2C_REG_CONTROL_TWSIEN | MV64XXX_I2C_REG_CONTROL_STOP,
+		drv_data->reg_base + MV64XXX_I2C_REG_CONTROL);
+	drv_data->state = MV64XXX_I2C_STATE_IDLE;
+}
+
+static int __devinit
+mv64xxx_i2c_map_regs(struct platform_device *pd,
+	struct mv64xxx_i2c_data *drv_data)
+{
+	struct resource	*r;
+
+	if ((r = platform_get_resource(pd, IORESOURCE_MEM, 0)) &&
+		request_mem_region(r->start, MV64XXX_I2C_REG_BLOCK_SIZE,
+			drv_data->adapter.name)) {
+
+		drv_data->reg_base = ioremap(r->start,
+			MV64XXX_I2C_REG_BLOCK_SIZE);
+		drv_data->reg_base_p = r->start;
+	} else
+		return -ENOMEM;
+
+	return 0;
+}
+
+static void __devexit
+mv64xxx_i2c_unmap_regs(struct mv64xxx_i2c_data *drv_data)
+{
+	if (drv_data->reg_base) {
+		iounmap(drv_data->reg_base);
+		release_mem_region(drv_data->reg_base_p,
+			MV64XXX_I2C_REG_BLOCK_SIZE);
+	}
+
+	drv_data->reg_base = NULL;
+	drv_data->reg_base_p = 0;
+}
+
+static int __devinit
+mv64xxx_i2c_probe(struct device *dev)
+{
+	struct platform_device		*pd = to_platform_device(dev);
+	struct mv64xxx_i2c_data		*drv_data;
+	struct mv64xxx_i2c_pdata	*pdata = dev->platform_data;
+	int	rc;
+
+	if ((pd->id != 0) || !pdata)
+		return -ENODEV;
+
+	drv_data = kmalloc(sizeof(struct mv64xxx_i2c_data), GFP_KERNEL);
+
+	if (!drv_data)
+		return -ENOMEM;
+
+	memset(drv_data, 0, sizeof(struct mv64xxx_i2c_data));
+
+	if (mv64xxx_i2c_map_regs(pd, drv_data)) {
+		rc = -ENODEV;
+		goto exit_kfree;
+	}
+
+	strncpy(drv_data->adapter.name, MV64XXX_I2C_CTLR_NAME " adapter",
+		I2C_NAME_SIZE);
+
+	init_waitqueue_head(&drv_data->waitq);
+	spin_lock_init(&drv_data->lock);
+
+	drv_data->freq_m = pdata->freq_m;
+	drv_data->freq_n = pdata->freq_n;
+	drv_data->irq = platform_get_irq(pd, 0);
+	drv_data->adapter.id = I2C_ALGO_MV64XXX | I2C_HW_MV64XXX;
+	drv_data->adapter.algo = &mv64xxx_i2c_algo;
+	drv_data->adapter.timeout = pdata->timeout;
+	drv_data->adapter.retries = pdata->retries;
+	dev_set_drvdata(dev, drv_data);
+	i2c_set_adapdata(&drv_data->adapter, drv_data);
+
+	if (request_irq(drv_data->irq, mv64xxx_i2c_intr, 0,
+		MV64XXX_I2C_CTLR_NAME, drv_data)) {
+
+		dev_err(dev, "mv64xxx: Can't register intr handler "
+			"irq: %d\n", drv_data->irq);
+		rc = -EINVAL;
+		goto exit_unmap_regs;
+	} else if ((rc = i2c_add_adapter(&drv_data->adapter)) != 0) {
+		dev_err(dev, "mv64xxx: Can't add i2c adapter, rc: %d\n", -rc);
+		goto exit_free_irq;
+	}
+
+	mv64xxx_i2c_hw_init(drv_data);
+
+	return 0;
+
+	exit_free_irq:
+		free_irq(drv_data->irq, drv_data);
+	exit_unmap_regs:
+		mv64xxx_i2c_unmap_regs(drv_data);
+	exit_kfree:
+		kfree(drv_data);
+	return rc;
+}
+
+static int __devexit
+mv64xxx_i2c_remove(struct device *dev)
+{
+	struct mv64xxx_i2c_data		*drv_data = dev_get_drvdata(dev);
+	int	rc;
+
+	rc = i2c_del_adapter(&drv_data->adapter);
+	free_irq(drv_data->irq, drv_data);
+	mv64xxx_i2c_unmap_regs(drv_data);
+	kfree(drv_data);
+
+	return rc;
+}
+
+static struct device_driver mv64xxx_i2c_driver = {
+	.name	= MV64XXX_I2C_CTLR_NAME,
+	.bus	= &platform_bus_type,
+	.probe	= mv64xxx_i2c_probe,
+	.remove	= mv64xxx_i2c_remove,
+};
+
+static int __init
+mv64xxx_i2c_init(void)
+{
+	return driver_register(&mv64xxx_i2c_driver);
+}
+
+static void __exit
+mv64xxx_i2c_exit(void)
+{
+	driver_unregister(&mv64xxx_i2c_driver);
+}
+
+module_init(mv64xxx_i2c_init);
+module_exit(mv64xxx_i2c_exit);
+
+MODULE_AUTHOR("Mark A. Greer <mgreer@mvista.com>");
+MODULE_DESCRIPTION("Marvell mv64xxx host bridge i2c ctlr driver");
+MODULE_LICENSE("GPL");
diff -Nru a/drivers/i2c/busses/i2c-nforce2.c b/drivers/i2c/busses/i2c-nforce2.c
--- a/drivers/i2c/busses/i2c-nforce2.c	2005-03-11 12:51:41 -08:00
+++ b/drivers/i2c/busses/i2c-nforce2.c	2005-03-11 12:51:41 -08:00
@@ -29,9 +29,10 @@
     nForce2 Ultra 400 MCP	0084
     nForce3 Pro150 MCP		00D4
     nForce3 250Gb MCP		00E4
+    nForce4 MCP			0052
 
-    This driver supports the 2 SMBuses that are included in the MCP2 of the
-    nForce2 chipset.
+    This driver supports the 2 SMBuses that are included in the MCP of the
+    nForce2/3/4 chipsets.
 */
 
 /* Note: we assume there can only be one nForce2, with two SMBus interfaces */
@@ -295,6 +296,7 @@
 	{ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2S_SMBUS) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3_SMBUS) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3S_SMBUS) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE4_SMBUS) },
 	{ 0 }
 };
 
diff -Nru a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c
--- a/drivers/i2c/busses/i2c-s3c2410.c	2005-03-11 12:51:42 -08:00
+++ b/drivers/i2c/busses/i2c-s3c2410.c	2005-03-11 12:51:42 -08:00
@@ -483,7 +483,7 @@
  * this starts an i2c transfer
 */
 
-static int s3c24xx_i2c_doxfer(struct s3c24xx_i2c *i2c, struct i2c_msg msgs[], int num)
+static int s3c24xx_i2c_doxfer(struct s3c24xx_i2c *i2c, struct i2c_msg *msgs, int num)
 {
 	unsigned long timeout;
 	int ret;
@@ -534,7 +534,7 @@
 */
 
 static int s3c24xx_i2c_xfer(struct i2c_adapter *adap,
-			struct i2c_msg msgs[], int num)
+			struct i2c_msg *msgs, int num)
 {
 	struct s3c24xx_i2c *i2c = (struct s3c24xx_i2c *)adap->algo_data;
 	int retry;
@@ -569,6 +569,7 @@
 		.name			= "s3c2410-i2c",
 		.algo			= &s3c24xx_i2c_algorithm,
 		.retries		= 2,
+		.class			= I2C_CLASS_HWMON,
 	},
 };
 
diff -Nru a/drivers/i2c/chips/Kconfig b/drivers/i2c/chips/Kconfig
--- a/drivers/i2c/chips/Kconfig	2005-03-11 12:51:46 -08:00
+++ b/drivers/i2c/chips/Kconfig	2005-03-11 12:51:46 -08:00
@@ -63,7 +63,7 @@
 	  will be called asb100.
 
 config SENSORS_DS1621
-      	tristate "Dallas Semiconductor DS1621 and DS1625"
+	tristate "Dallas Semiconductor DS1621 and DS1625"
 	depends on I2C && EXPERIMENTAL
 	select I2C_SENSOR
 	help
@@ -84,6 +84,17 @@
 	  This driver can also be built as a module.  If so, the module
 	  will be called fscher.
 
+config SENSORS_FSCPOS
+	tristate "FSC Poseidon"
+	depends on I2C && EXPERIMENTAL
+	select I2C_SENSOR
+	help
+	  If you say yes here you get support for Fujitsu Siemens
+	  Computers Poseidon sensor chips.
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called fscpos.
+
 config SENSORS_GL518SM
 	tristate "Genesys Logic GL518SM"
 	depends on I2C && EXPERIMENTAL
@@ -95,6 +106,17 @@
 	  This driver can also be built as a module.  If so, the module
 	  will be called gl518sm.
 
+config SENSORS_GL520SM
+	tristate "Genesys Logic GL520SM"
+	depends on I2C && EXPERIMENTAL
+	select I2C_SENSOR
+	help
+	  If you say yes here you get support for Genesys Logic GL520SM
+	  sensor chips.
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called gl520sm.
+
 config SENSORS_IT87
 	tristate "ITE IT87xx and compatibles"
 	depends on I2C && EXPERIMENTAL
@@ -251,6 +273,18 @@
 	  This driver can also be built as a module.  If so, the module
 	  will be called smsc47b397.
 
+config SENSORS_SIS5595
+	tristate "Silicon Integrated Systems Corp. SiS5595"
+	depends on I2C && PCI && EXPERIMENTAL
+	select I2C_SENSOR
+	select I2C_ISA
+	help
+	  If you say yes here you get support for the integrated sensors in
+	  SiS5595 South Bridges.
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called sis5595.
+
 config SENSORS_SMSC47M1
 	tristate "SMSC LPC47M10x and compatibles"
 	depends on I2C && EXPERIMENTAL
@@ -304,6 +338,7 @@
 	tristate "Winbond W83627HF, W83627THF, W83637HF, W83697HF"
 	depends on I2C && EXPERIMENTAL
 	select I2C_SENSOR
+	select I2C_ISA
 	help
 	  If you say yes here you get support for the Winbond W836X7 series
 	  of sensor chips: the W83627HF, W83627THF, W83637HF, and the W83697HF
@@ -370,5 +405,14 @@
 	  
 	  This driver can also be built as a module.  If so, the module
 	  will be called isp1301_omap.
+
+config SENSORS_M41T00
+	tristate "ST M41T00 RTC chip"
+	depends on I2C && PPC32
+	help
+	  If you say yes here you get support for the ST M41T00 RTC chip.
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called m41t00.
 
 endmenu
diff -Nru a/drivers/i2c/chips/Makefile b/drivers/i2c/chips/Makefile
--- a/drivers/i2c/chips/Makefile	2005-03-11 12:51:52 -08:00
+++ b/drivers/i2c/chips/Makefile	2005-03-11 12:51:52 -08:00
@@ -14,7 +14,9 @@
 obj-$(CONFIG_SENSORS_DS1621)	+= ds1621.o
 obj-$(CONFIG_SENSORS_EEPROM)	+= eeprom.o
 obj-$(CONFIG_SENSORS_FSCHER)	+= fscher.o
+obj-$(CONFIG_SENSORS_FSCPOS)	+= fscpos.o
 obj-$(CONFIG_SENSORS_GL518SM)	+= gl518sm.o
+obj-$(CONFIG_SENSORS_GL520SM)	+= gl520sm.o
 obj-$(CONFIG_SENSORS_IT87)	+= it87.o
 obj-$(CONFIG_SENSORS_LM63)	+= lm63.o
 obj-$(CONFIG_SENSORS_LM75)	+= lm75.o
@@ -26,10 +28,12 @@
 obj-$(CONFIG_SENSORS_LM87)	+= lm87.o
 obj-$(CONFIG_SENSORS_LM90)	+= lm90.o
 obj-$(CONFIG_SENSORS_MAX1619)	+= max1619.o
+obj-$(CONFIG_SENSORS_M41T00)	+= m41t00.o
 obj-$(CONFIG_SENSORS_PC87360)	+= pc87360.o
 obj-$(CONFIG_SENSORS_PCF8574)	+= pcf8574.o
 obj-$(CONFIG_SENSORS_PCF8591)	+= pcf8591.o
 obj-$(CONFIG_SENSORS_RTC8564)	+= rtc8564.o
+obj-$(CONFIG_SENSORS_SIS5595)	+= sis5595.o
 obj-$(CONFIG_SENSORS_SMSC47B397)+= smsc47b397.o
 obj-$(CONFIG_SENSORS_SMSC47M1)	+= smsc47m1.o
 obj-$(CONFIG_SENSORS_VIA686A)	+= via686a.o
diff -Nru a/drivers/i2c/chips/adm1021.c b/drivers/i2c/chips/adm1021.c
--- a/drivers/i2c/chips/adm1021.c	2005-03-11 12:51:41 -08:00
+++ b/drivers/i2c/chips/adm1021.c	2005-03-11 12:51:41 -08:00
@@ -23,6 +23,7 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/slab.h>
+#include <linux/jiffies.h>
 #include <linux/i2c.h>
 #include <linux/i2c-sensor.h>
 
@@ -147,8 +148,6 @@
 	.detach_client	= adm1021_detach_client,
 };
 
-static int adm1021_id;
-
 #define show(value)	\
 static ssize_t show_##value(struct device *dev, char *buf)		\
 {									\
@@ -299,8 +298,6 @@
 	/* Fill in the remaining client fields and put it into the global list */
 	strlcpy(new_client->name, type_name, I2C_NAME_SIZE);
 	data->type = kind;
-
-	new_client->id = adm1021_id++;
 	data->valid = 0;
 	init_MUTEX(&data->update_lock);
 
@@ -373,8 +370,8 @@
 
 	down(&data->update_lock);
 
-	if ((jiffies - data->last_updated > HZ + HZ / 2) ||
-	    (jiffies < data->last_updated) || !data->valid) {
+	if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
+	    || !data->valid) {
 		dev_dbg(&client->dev, "Starting adm1021 update\n");
 
 		data->temp_input = adm1021_read_value(client, ADM1021_REG_TEMP);
diff -Nru a/drivers/i2c/chips/adm1025.c b/drivers/i2c/chips/adm1025.c
--- a/drivers/i2c/chips/adm1025.c	2005-03-11 12:51:40 -08:00
+++ b/drivers/i2c/chips/adm1025.c	2005-03-11 12:51:40 -08:00
@@ -49,6 +49,7 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/slab.h>
+#include <linux/jiffies.h>
 #include <linux/i2c.h>
 #include <linux/i2c-sensor.h>
 #include <linux/i2c-vid.h>
@@ -148,12 +149,6 @@
 };
 
 /*
- * Internal variables
- */
-
-static int adm1025_id;
-
-/*
  * Sysfs stuff
  */
 
@@ -397,7 +392,6 @@
 
 	/* We can fill in the remaining client fields */
 	strlcpy(new_client->name, name, I2C_NAME_SIZE);
-	new_client->id = adm1025_id++;
 	data->valid = 0;
 	init_MUTEX(&data->update_lock);
 
@@ -512,9 +506,7 @@
 
 	down(&data->update_lock);
 
-	if ((jiffies - data->last_updated > HZ * 2) ||
-	    (jiffies < data->last_updated) ||
-	    !data->valid) {
+	if (time_after(jiffies, data->last_updated + HZ * 2) || !data->valid) {
 		int i;
 
 		dev_dbg(&client->dev, "Updating data.\n");
diff -Nru a/drivers/i2c/chips/adm1026.c b/drivers/i2c/chips/adm1026.c
--- a/drivers/i2c/chips/adm1026.c	2005-03-11 12:51:42 -08:00
+++ b/drivers/i2c/chips/adm1026.c	2005-03-11 12:51:42 -08:00
@@ -27,6 +27,7 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/slab.h>
+#include <linux/jiffies.h>
 #include <linux/i2c.h>
 #include <linux/i2c-sensor.h>
 #include <linux/i2c-vid.h>
@@ -313,8 +314,6 @@
 	.detach_client  = adm1026_detach_client,
 };
 
-static int adm1026_id;
-
 int adm1026_attach_adapter(struct i2c_adapter *adapter)
 {
 	if (!(adapter->class & I2C_CLASS_HWMON)) {
@@ -363,49 +362,47 @@
 	int value, i;
 	struct adm1026_data *data = i2c_get_clientdata(client);
 
-        dev_dbg(&client->dev,"(%d): Initializing device\n", client->id);
+        dev_dbg(&client->dev, "Initializing device\n");
 	/* Read chip config */
 	data->config1 = adm1026_read_value(client, ADM1026_REG_CONFIG1);
 	data->config2 = adm1026_read_value(client, ADM1026_REG_CONFIG2);
 	data->config3 = adm1026_read_value(client, ADM1026_REG_CONFIG3);
 
 	/* Inform user of chip config */
-	dev_dbg(&client->dev, "(%d): ADM1026_REG_CONFIG1 is: 0x%02x\n",
-		client->id, data->config1);
+	dev_dbg(&client->dev, "ADM1026_REG_CONFIG1 is: 0x%02x\n",
+		data->config1);
 	if ((data->config1 & CFG1_MONITOR) == 0) {
-		dev_dbg(&client->dev, "(%d): Monitoring not currently "
-			"enabled.\n", client->id);
+		dev_dbg(&client->dev, "Monitoring not currently "
+			"enabled.\n");
 	}
 	if (data->config1 & CFG1_INT_ENABLE) {
-		dev_dbg(&client->dev, "(%d): SMBALERT interrupts are "
-			"enabled.\n", client->id);
+		dev_dbg(&client->dev, "SMBALERT interrupts are "
+			"enabled.\n");
 	}
 	if (data->config1 & CFG1_AIN8_9) {
-		dev_dbg(&client->dev, "(%d): in8 and in9 enabled. "
-			"temp3 disabled.\n", client->id);
+		dev_dbg(&client->dev, "in8 and in9 enabled. "
+			"temp3 disabled.\n");
 	} else {
-		dev_dbg(&client->dev, "(%d): temp3 enabled.  in8 and "
-			"in9 disabled.\n", client->id);
+		dev_dbg(&client->dev, "temp3 enabled.  in8 and "
+			"in9 disabled.\n");
 	}
 	if (data->config1 & CFG1_THERM_HOT) {
-		dev_dbg(&client->dev, "(%d): Automatic THERM, PWM, "
-			"and temp limits enabled.\n", client->id);
+		dev_dbg(&client->dev, "Automatic THERM, PWM, "
+			"and temp limits enabled.\n");
 	}
 
 	value = data->config3;
 	if (data->config3 & CFG3_GPIO16_ENABLE) {
-		dev_dbg(&client->dev, "(%d): GPIO16 enabled.  THERM"
-			"pin disabled.\n", client->id);
+		dev_dbg(&client->dev, "GPIO16 enabled.  THERM"
+			"pin disabled.\n");
 	} else {
-		dev_dbg(&client->dev, "(%d): THERM pin enabled.  "
-			"GPIO16 disabled.\n", client->id);
+		dev_dbg(&client->dev, "THERM pin enabled.  "
+			"GPIO16 disabled.\n");
 	}
 	if (data->config3 & CFG3_VREF_250) {
-		dev_dbg(&client->dev, "(%d): Vref is 2.50 Volts.\n",
-			client->id);
+		dev_dbg(&client->dev, "Vref is 2.50 Volts.\n");
 	} else {
-		dev_dbg(&client->dev, "(%d): Vref is 1.82 Volts.\n",
-			client->id);
+		dev_dbg(&client->dev, "Vref is 1.82 Volts.\n");
 	}
 	/* Read and pick apart the existing GPIO configuration */
 	value = 0;
@@ -423,12 +420,11 @@
 	adm1026_print_gpio(client);
 
 	/* If the user asks us to reprogram the GPIO config, then
-	 *   do it now.  But only if this is the first ADM1026.
+	 * do it now.
 	 */
-	if (client->id == 0
-	    && (gpio_input[0] != -1 || gpio_output[0] != -1
+	if (gpio_input[0] != -1 || gpio_output[0] != -1
 		|| gpio_inverted[0] != -1 || gpio_normal[0] != -1
-		|| gpio_fan[0] != -1)) {
+		|| gpio_fan[0] != -1) {
 		adm1026_fixup_gpio(client);
 	}
 
@@ -448,8 +444,7 @@
 	value = adm1026_read_value(client, ADM1026_REG_CONFIG1);
 	/* Set MONITOR, clear interrupt acknowledge and s/w reset */
 	value = (value | CFG1_MONITOR) & (~CFG1_INT_CLEAR & ~CFG1_RESET);
-	dev_dbg(&client->dev, "(%d): Setting CONFIG to: 0x%02x\n",
-		client->id, value);
+	dev_dbg(&client->dev, "Setting CONFIG to: 0x%02x\n", value);
 	data->config1 = value;
 	adm1026_write_value(client, ADM1026_REG_CONFIG1, value);
 
@@ -467,31 +462,30 @@
 	struct adm1026_data *data = i2c_get_clientdata(client);
 	int  i;
 
-	dev_dbg(&client->dev, "(%d): GPIO config is:", client->id);
+	dev_dbg(&client->dev, "GPIO config is:");
 	for (i = 0;i <= 7;++i) {
 		if (data->config2 & (1 << i)) {
-			dev_dbg(&client->dev, "\t(%d): %sGP%s%d\n", client->id,
+			dev_dbg(&client->dev, "\t%sGP%s%d\n",
 				data->gpio_config[i] & 0x02 ? "" : "!",
 				data->gpio_config[i] & 0x01 ? "OUT" : "IN",
 				i);
 		} else {
-			dev_dbg(&client->dev, "\t(%d): FAN%d\n",
-				client->id, i);
+			dev_dbg(&client->dev, "\tFAN%d\n", i);
 		}
 	}
 	for (i = 8;i <= 15;++i) {
-		dev_dbg(&client->dev, "\t(%d): %sGP%s%d\n", client->id,
+		dev_dbg(&client->dev, "\t%sGP%s%d\n",
 			data->gpio_config[i] & 0x02 ? "" : "!",
 			data->gpio_config[i] & 0x01 ? "OUT" : "IN",
 			i);
 	}
 	if (data->config3 & CFG3_GPIO16_ENABLE) {
-		dev_dbg(&client->dev, "\t(%d): %sGP%s16\n", client->id,
+		dev_dbg(&client->dev, "\t%sGP%s16\n",
 			data->gpio_config[16] & 0x02 ? "" : "!",
 			data->gpio_config[16] & 0x01 ? "OUT" : "IN");
 	} else {
 		/* GPIO16 is THERM  */
-		dev_dbg(&client->dev, "\t(%d): THERM\n", client->id);
+		dev_dbg(&client->dev, "\tTHERM\n");
 	}
 }
 
@@ -580,10 +574,9 @@
 
 	down(&data->update_lock);
 	if (!data->valid
-	    || (jiffies - data->last_reading > ADM1026_DATA_INTERVAL)) {
+	    || time_after(jiffies, data->last_reading + ADM1026_DATA_INTERVAL)) {
 		/* Things that change quickly */
-		dev_dbg(&client->dev,"(%d): Reading sensor values\n", 
-			client->id);
+		dev_dbg(&client->dev,"Reading sensor values\n");
 		for (i = 0;i <= 16;++i) {
 			data->in[i] =
 			    adm1026_read_value(client, ADM1026_REG_IN[i]);
@@ -628,11 +621,10 @@
 		data->last_reading = jiffies;
 	};  /* last_reading */
 
-	if (!data->valid || (jiffies - data->last_config > 
-		ADM1026_CONFIG_INTERVAL)) {
+	if (!data->valid ||
+	    time_after(jiffies, data->last_config + ADM1026_CONFIG_INTERVAL)) {
 		/* Things that don't change often */
-		dev_dbg(&client->dev, "(%d): Reading config values\n", 
-			client->id);
+		dev_dbg(&client->dev, "Reading config values\n");
 		for (i = 0;i <= 16;++i) {
 			data->in_min[i] = adm1026_read_value(client, 
 				ADM1026_REG_IN_MIN[i]);
@@ -712,8 +704,7 @@
 		data->last_config = jiffies;
 	};  /* last_config */
 
-	dev_dbg(&client->dev, "(%d): Setting VID from GPIO11-15.\n", 
-		client->id);
+	dev_dbg(&client->dev, "Setting VID from GPIO11-15.\n");
 	data->vid = (data->gpio >> 11) & 0x1f;
 	data->valid = 1;
 	up(&data->update_lock);
@@ -1608,15 +1599,9 @@
 	strlcpy(new_client->name, type_name, I2C_NAME_SIZE);
 
 	/* Fill in the remaining client fields */
-	new_client->id = adm1026_id++;
 	data->type = kind;
 	data->valid = 0;
 	init_MUTEX(&data->update_lock);
-
-	dev_dbg(&new_client->dev, "(%d): Assigning ID %d to %s at %d,0x%02x\n",
-		new_client->id, new_client->id, new_client->name,
-		i2c_adapter_id(new_client->adapter),
-		new_client->addr);
 
 	/* Tell the I2C layer a new client has arrived */
 	if ((err = i2c_attach_client(new_client)))
diff -Nru a/drivers/i2c/chips/adm1031.c b/drivers/i2c/chips/adm1031.c
--- a/drivers/i2c/chips/adm1031.c	2005-03-11 12:51:43 -08:00
+++ b/drivers/i2c/chips/adm1031.c	2005-03-11 12:51:43 -08:00
@@ -24,6 +24,7 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/slab.h>
+#include <linux/jiffies.h>
 #include <linux/i2c.h>
 #include <linux/i2c-sensor.h>
 
@@ -110,8 +111,6 @@
 	.detach_client = adm1031_detach_client,
 };
 
-static int adm1031_id;
-
 static inline u8 adm1031_read_value(struct i2c_client *client, u8 reg)
 {
 	return i2c_smbus_read_byte_data(client, reg);
@@ -781,8 +780,6 @@
 	data->chip_type = kind;
 
 	strlcpy(new_client->name, name, I2C_NAME_SIZE);
-
-	new_client->id = adm1031_id++;
 	data->valid = 0;
 	init_MUTEX(&data->update_lock);
 
@@ -888,8 +885,8 @@
 
 	down(&data->update_lock);
 
-	if ((jiffies - data->last_updated > HZ + HZ / 2) ||
-	    (jiffies < data->last_updated) || !data->valid) {
+	if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
+	    || !data->valid) {
 
 		dev_dbg(&client->dev, "Starting adm1031 update\n");
 		for (chan = 0;
diff -Nru a/drivers/i2c/chips/asb100.c b/drivers/i2c/chips/asb100.c
--- a/drivers/i2c/chips/asb100.c	2005-03-11 12:51:46 -08:00
+++ b/drivers/i2c/chips/asb100.c	2005-03-11 12:51:46 -08:00
@@ -36,17 +36,12 @@
     asb100	7	3	1	4	0x31	0x0694	yes	no
 */
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/slab.h>
-#include <linux/ioport.h>
-#include <linux/types.h>
 #include <linux/i2c.h>
 #include <linux/i2c-sensor.h>
 #include <linux/i2c-vid.h>
 #include <linux/init.h>
-#include <asm/errno.h>
-#include <asm/io.h>
 #include "lm75.h"
 
 /*
@@ -970,8 +965,8 @@
 
 	down(&data->update_lock);
 
-	if (time_after(jiffies - data->last_updated, (unsigned long)(HZ+HZ/2))
-		|| time_before(jiffies, data->last_updated) || !data->valid) {
+	if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
+		|| !data->valid) {
 
 		dev_dbg(&client->dev, "starting device update...\n");
 
diff -Nru a/drivers/i2c/chips/ds1621.c b/drivers/i2c/chips/ds1621.c
--- a/drivers/i2c/chips/ds1621.c	2005-03-11 12:51:52 -08:00
+++ b/drivers/i2c/chips/ds1621.c	2005-03-11 12:51:52 -08:00
@@ -24,6 +24,7 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/slab.h>
+#include <linux/jiffies.h>
 #include <linux/i2c.h>
 #include <linux/i2c-sensor.h>
 #include "lm75.h"
@@ -95,8 +96,6 @@
 	.detach_client	= ds1621_detach_client,
 };
 
-static int ds1621_id;
-
 /* All registers are word-sized, except for the configuration register.
    DS1621 uses a high-byte first convention, which is exactly opposite to
    the usual practice. */
@@ -236,8 +235,6 @@
 
 	/* Fill in remaining client fields and put it into the global list */
 	strlcpy(new_client->name, "ds1621", I2C_NAME_SIZE);
-
-	new_client->id = ds1621_id++;
 	data->valid = 0;
 	init_MUTEX(&data->update_lock);
 
@@ -288,8 +285,8 @@
 
 	down(&data->update_lock);
 
-	if ((jiffies - data->last_updated > HZ + HZ / 2) ||
-	    (jiffies < data->last_updated) || !data->valid) {
+	if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
+	    || !data->valid) {
 
 		dev_dbg(&client->dev, "Starting ds1621 update\n");
 
diff -Nru a/drivers/i2c/chips/eeprom.c b/drivers/i2c/chips/eeprom.c
--- a/drivers/i2c/chips/eeprom.c	2005-03-11 12:51:42 -08:00
+++ b/drivers/i2c/chips/eeprom.c	2005-03-11 12:51:42 -08:00
@@ -32,6 +32,7 @@
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/sched.h>
+#include <linux/jiffies.h>
 #include <linux/i2c.h>
 #include <linux/i2c-sensor.h>
 
@@ -86,8 +87,7 @@
 	down(&data->update_lock);
 
 	if (!(data->valid & (1 << slice)) ||
-	    (jiffies - data->last_updated[slice] > 300 * HZ) ||
-	    (jiffies < data->last_updated[slice])) {
+	    time_after(jiffies, data->last_updated[slice] + 300 * HZ)) {
 		dev_dbg(&client->dev, "Starting eeprom update, slice %u\n", slice);
 
 		if (i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_READ_I2C_BLOCK)) {
diff -Nru a/drivers/i2c/chips/fscher.c b/drivers/i2c/chips/fscher.c
--- a/drivers/i2c/chips/fscher.c	2005-03-11 12:51:46 -08:00
+++ b/drivers/i2c/chips/fscher.c	2005-03-11 12:51:46 -08:00
@@ -30,6 +30,7 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/slab.h>
+#include <linux/jiffies.h>
 #include <linux/i2c.h>
 #include <linux/i2c-sensor.h>
 
@@ -151,12 +152,6 @@
 };
 
 /*
- * Internal variables
- */
-
-static int fscher_id;
-
-/*
  * Sysfs stuff
  */
 
@@ -337,7 +332,6 @@
 	/* Fill in the remaining client fields and put it into the
 	 * global list */
 	strlcpy(new_client->name, "fscher", I2C_NAME_SIZE);
-	new_client->id = fscher_id++;
 	data->valid = 0;
 	init_MUTEX(&data->update_lock);
 
@@ -418,8 +412,7 @@
 
 	down(&data->update_lock);
 
-	if ((jiffies - data->last_updated > 2 * HZ) ||
-	    (jiffies < data->last_updated) || !data->valid) {
+	if (time_after(jiffies, data->last_updated + 2 * HZ) || !data->valid) {
 
 		dev_dbg(&client->dev, "Starting fscher update\n");
 
diff -Nru a/drivers/i2c/chips/fscpos.c b/drivers/i2c/chips/fscpos.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/i2c/chips/fscpos.c	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,631 @@
+/*
+	fscpos.c - Kernel module for hardware monitoring with FSC Poseidon chips
+	Copyright (C) 2004, 2005 Stefan Ott <stefan@desire.ch>
+
+	This program is free software; you can redistribute it and/or modify
+	it under the terms of the GNU General Public License as published by
+	the Free Software Foundation; either version 2 of the License, or
+	(at your option) any later version.
+
+	This program is distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+	GNU General Public License for more details.
+
+	You should have received a copy of the GNU General Public License
+	along with this program; if not, write to the Free Software
+	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+/*
+	fujitsu siemens poseidon chip,
+	module based on the old fscpos module by Hermann Jung <hej@odn.de> and
+	the fscher module by Reinhard Nissl <rnissl@gmx.de>
+
+	original module based on lm80.c
+	Copyright (C) 1998, 1999 Frodo Looijaard <frodol@dds.nl>
+	and Philip Edelbrock <phil@netroedge.com>
+
+	Thanks to Jean Delvare for reviewing my code and suggesting a lot of
+	improvements.
+*/
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/i2c-sensor.h>
+#include <linux/init.h>
+
+/*
+ * Addresses to scan
+ */
+static unsigned short normal_i2c[] = { 0x73, I2C_CLIENT_END };
+static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
+
+/*
+ * Insmod parameters
+ */
+SENSORS_INSMOD_1(fscpos);
+
+/*
+ * The FSCPOS registers
+ */
+
+/* chip identification */
+#define FSCPOS_REG_IDENT_0		0x00
+#define FSCPOS_REG_IDENT_1		0x01
+#define FSCPOS_REG_IDENT_2		0x02
+#define FSCPOS_REG_REVISION		0x03
+
+/* global control and status */
+#define FSCPOS_REG_EVENT_STATE		0x04
+#define FSCPOS_REG_CONTROL		0x05
+
+/* watchdog */
+#define FSCPOS_REG_WDOG_PRESET		0x28
+#define FSCPOS_REG_WDOG_STATE		0x23
+#define FSCPOS_REG_WDOG_CONTROL		0x21
+
+/* voltages */
+#define FSCPOS_REG_VOLT_12		0x45
+#define FSCPOS_REG_VOLT_5		0x42
+#define FSCPOS_REG_VOLT_BATT		0x48
+
+/* fans - the chip does not support minimum speed for fan2 */
+static u8 FSCPOS_REG_PWM[] = { 0x55, 0x65 };
+static u8 FSCPOS_REG_FAN_ACT[] = { 0x0e, 0x6b, 0xab };
+static u8 FSCPOS_REG_FAN_STATE[] = { 0x0d, 0x62, 0xa2 };
+static u8 FSCPOS_REG_FAN_RIPPLE[] = { 0x0f, 0x6f, 0xaf };
+
+/* temperatures */
+static u8 FSCPOS_REG_TEMP_ACT[] = { 0x64, 0x32, 0x35 };
+static u8 FSCPOS_REG_TEMP_STATE[] = { 0x71, 0x81, 0x91 };
+
+/*
+ * Functions declaration
+ */
+static int fscpos_attach_adapter(struct i2c_adapter *adapter);
+static int fscpos_detect(struct i2c_adapter *adapter, int address, int kind);
+static int fscpos_detach_client(struct i2c_client *client);
+
+static int fscpos_read_value(struct i2c_client *client, u8 register);
+static int fscpos_write_value(struct i2c_client *client, u8 register, u8 value);
+static struct fscpos_data *fscpos_update_device(struct device *dev);
+static void fscpos_init_client(struct i2c_client *client);
+
+static void reset_fan_alarm(struct i2c_client *client, int nr);
+
+/*
+ * Driver data (common to all clients)
+ */
+static struct i2c_driver fscpos_driver = {
+	.owner		= THIS_MODULE,
+	.name		= "fscpos",
+	.id		= I2C_DRIVERID_FSCPOS,
+	.flags		= I2C_DF_NOTIFY,
+	.attach_adapter	= fscpos_attach_adapter,
+	.detach_client	= fscpos_detach_client,
+};
+
+/*
+ * Client data (each client gets its own)
+ */
+struct fscpos_data {
+	struct i2c_client client;
+	struct semaphore update_lock;
+	char valid; 		/* 0 until following fields are valid */
+	unsigned long last_updated;	/* In jiffies */
+
+	/* register values */
+	u8 revision;		/* revision of chip */
+	u8 global_event;	/* global event status */
+	u8 global_control;	/* global control register */
+	u8 wdog_control;	/* watchdog control */
+	u8 wdog_state;		/* watchdog status */
+	u8 wdog_preset;		/* watchdog preset */
+	u8 volt[3];		/* 12, 5, battery current */
+	u8 temp_act[3];		/* temperature */
+	u8 temp_status[3];	/* status of sensor */
+	u8 fan_act[3];		/* fans revolutions per second */
+	u8 fan_status[3];	/* fan status */
+	u8 pwm[2];		/* fan min value for rps */
+	u8 fan_ripple[3];	/* divider for rps */
+};
+
+/* Temperature */
+#define TEMP_FROM_REG(val)	(((val) - 128) * 1000)
+
+static ssize_t show_temp_input(struct fscpos_data *data, char *buf, int nr)
+{
+	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_act[nr - 1]));
+}
+
+static ssize_t show_temp_status(struct fscpos_data *data, char *buf, int nr)
+{
+	/* bits 2..7 reserved => mask with 0x03 */
+	return sprintf(buf, "%u\n", data->temp_status[nr - 1] & 0x03);
+}
+
+static ssize_t show_temp_reset(struct fscpos_data *data, char *buf, int nr)
+{
+	return sprintf(buf, "1\n");
+}
+
+static ssize_t set_temp_reset(struct i2c_client *client, struct fscpos_data
+			*data, const char *buf,	size_t count, int nr, int reg)
+{
+	unsigned long v = simple_strtoul(buf, NULL, 10);
+	if (v != 1) {
+		dev_err(&client->dev, "temp_reset value %ld not supported. "
+					"Use 1 to reset the alarm!\n", v);
+		return -EINVAL;
+	}
+
+	dev_info(&client->dev, "You used the temp_reset feature which has not "
+				"been proplerly tested. Please report your "
+				"experience to the module author.\n");
+
+	/* Supported value: 2 (clears the status) */
+	fscpos_write_value(client, FSCPOS_REG_TEMP_STATE[nr], 2);
+	return count;
+}
+
+/* Fans */
+#define RPM_FROM_REG(val)	((val) * 60)
+
+static ssize_t show_fan_status(struct fscpos_data *data, char *buf, int nr)
+{
+	/* bits 0..1, 3..7 reserved => mask with 0x04 */
+	return sprintf(buf, "%u\n", data->fan_status[nr - 1] & 0x04);
+}
+
+static ssize_t show_fan_input(struct fscpos_data *data, char *buf, int nr)
+{
+	return sprintf(buf, "%u\n", RPM_FROM_REG(data->fan_act[nr - 1]));
+}
+
+static ssize_t show_fan_ripple(struct fscpos_data *data, char *buf, int nr)
+{
+	/* bits 2..7 reserved => mask with 0x03 */
+	return sprintf(buf, "%u\n", data->fan_ripple[nr - 1] & 0x03);
+}
+
+static ssize_t set_fan_ripple(struct i2c_client *client, struct fscpos_data
+			*data, const char *buf,	size_t count, int nr, int reg)
+{
+	/* supported values: 2, 4, 8 */
+	unsigned long v = simple_strtoul(buf, NULL, 10);
+
+	switch (v) {
+		case 2: v = 1; break;
+		case 4: v = 2; break;
+		case 8: v = 3; break;
+	default:
+		dev_err(&client->dev, "fan_ripple value %ld not supported. "
+					"Must be one of 2, 4 or 8!\n", v);
+		return -EINVAL;
+	}
+	
+	/* bits 2..7 reserved => mask with 0x03 */
+	data->fan_ripple[nr - 1] &= ~0x03;
+	data->fan_ripple[nr - 1] |= v;
+	
+	fscpos_write_value(client, reg, data->fan_ripple[nr - 1]);
+	return count;
+}
+
+static ssize_t show_pwm(struct fscpos_data *data, char *buf, int nr)
+{
+	return sprintf(buf, "%u\n", data->pwm[nr - 1]);
+}
+
+static ssize_t set_pwm(struct i2c_client *client, struct fscpos_data *data,
+				const char *buf, size_t count, int nr, int reg)
+{
+	unsigned long v = simple_strtoul(buf, NULL, 10);
+
+	/* Range: 0..255 */
+	if (v < 0) v = 0;
+	if (v > 255) v = 255;
+
+	data->pwm[nr - 1] = v;
+	fscpos_write_value(client, reg, data->pwm[nr - 1]);
+	return count;
+}
+
+static void reset_fan_alarm(struct i2c_client *client, int nr)
+{
+	fscpos_write_value(client, FSCPOS_REG_FAN_STATE[nr], 4);
+}
+
+/* Volts */
+#define VOLT_FROM_REG(val, mult)	((val) * (mult) / 255)
+
+static ssize_t show_volt_12(struct device *dev, char *buf)
+{
+	struct fscpos_data *data = fscpos_update_device(dev);
+	return sprintf(buf, "%u\n", VOLT_FROM_REG(data->volt[0], 14200));
+}
+
+static ssize_t show_volt_5(struct device *dev, char *buf)
+{
+	struct fscpos_data *data = fscpos_update_device(dev);
+	return sprintf(buf, "%u\n", VOLT_FROM_REG(data->volt[1], 6600));
+}
+
+static ssize_t show_volt_batt(struct device *dev, char *buf)
+{
+	struct fscpos_data *data = fscpos_update_device(dev);
+	return sprintf(buf, "%u\n", VOLT_FROM_REG(data->volt[2], 3300));
+}
+
+/* Watchdog */
+static ssize_t show_wdog_control(struct fscpos_data *data, char *buf)
+{
+	/* bits 0..3 reserved, bit 6 write only => mask with 0xb0 */
+	return sprintf(buf, "%u\n", data->wdog_control & 0xb0);
+}
+
+static ssize_t set_wdog_control(struct i2c_client *client, struct fscpos_data
+				*data, const char *buf,	size_t count, int reg)
+{
+	/* bits 0..3 reserved => mask with 0xf0 */
+	unsigned long v = simple_strtoul(buf, NULL, 10) & 0xf0;
+	data->wdog_control &= ~0xf0;
+	data->wdog_control |= v;
+	
+	fscpos_write_value(client, reg, data->wdog_control);
+	return count;
+}
+
+static ssize_t show_wdog_state(struct fscpos_data *data, char *buf)
+{
+	/* bits 0, 2..7 reserved => mask with 0x02 */
+	return sprintf(buf, "%u\n", data->wdog_state & 0x02);
+}
+
+static ssize_t set_wdog_state(struct i2c_client *client, struct fscpos_data
+				*data, const char *buf, size_t count, int reg)
+{
+	unsigned long v = simple_strtoul(buf, NULL, 10) & 0x02;
+
+	/* Valid values: 2 (clear) */
+	if (v != 2) {
+		dev_err(&client->dev, "wdog_state value %ld not supported. "
+					"Must be 2 to clear the state!\n", v);
+		return -EINVAL;
+	}
+
+	data->wdog_state &= ~v;
+	
+	fscpos_write_value(client, reg, v);
+	return count;
+}
+
+static ssize_t show_wdog_preset(struct fscpos_data *data, char *buf)
+{
+	return sprintf(buf, "%u\n", data->wdog_preset);
+}
+
+static ssize_t set_wdog_preset(struct i2c_client *client, struct fscpos_data
+				*data, const char *buf,	size_t count, int reg)
+{
+	data->wdog_preset = simple_strtoul(buf, NULL, 10) & 0xff;
+	
+	fscpos_write_value(client, reg, data->wdog_preset);
+	return count;
+}
+
+/* Event */
+static ssize_t show_event(struct device *dev, char *buf)
+{
+	/* bits 5..7 reserved => mask with 0x1f */
+	struct fscpos_data *data = fscpos_update_device(dev);
+	return sprintf(buf, "%u\n", data->global_event & 0x9b);
+}
+
+/*
+ * Sysfs stuff
+ */
+#define create_getter(kind, sub) \
+	static ssize_t sysfs_show_##kind##sub(struct device *dev, char *buf) \
+	{ \
+		struct fscpos_data *data = fscpos_update_device(dev); \
+		return show_##kind##sub(data, buf); \
+	}
+
+#define create_getter_n(kind, offset, sub) \
+	static ssize_t sysfs_show_##kind##offset##sub(struct device *dev, char\
+								 	*buf) \
+	{ \
+		struct fscpos_data *data = fscpos_update_device(dev); \
+		return show_##kind##sub(data, buf, offset); \
+	}
+
+#define create_setter(kind, sub, reg) \
+	static ssize_t sysfs_set_##kind##sub (struct device *dev, const char \
+							*buf, size_t count) \
+	{ \
+		struct i2c_client *client = to_i2c_client(dev); \
+		struct fscpos_data *data = i2c_get_clientdata(client); \
+		return set_##kind##sub(client, data, buf, count, reg); \
+	}
+
+#define create_setter_n(kind, offset, sub, reg) \
+	static ssize_t sysfs_set_##kind##offset##sub (struct device *dev, \
+					const char *buf, size_t count) \
+	{ \
+		struct i2c_client *client = to_i2c_client(dev); \
+		struct fscpos_data *data = i2c_get_clientdata(client); \
+		return set_##kind##sub(client, data, buf, count, offset, reg);\
+	}
+
+#define create_sysfs_device_ro(kind, sub, offset) \
+	static DEVICE_ATTR(kind##offset##sub, S_IRUGO, \
+					sysfs_show_##kind##offset##sub, NULL);
+
+#define create_sysfs_device_rw(kind, sub, offset) \
+	static DEVICE_ATTR(kind##offset##sub, S_IRUGO | S_IWUSR, \
+		sysfs_show_##kind##offset##sub, sysfs_set_##kind##offset##sub);
+
+#define sysfs_ro_n(kind, sub, offset) \
+	create_getter_n(kind, offset, sub); \
+	create_sysfs_device_ro(kind, sub, offset);
+
+#define sysfs_rw_n(kind, sub, offset, reg) \
+	create_getter_n(kind, offset, sub); \
+	create_setter_n(kind, offset, sub, reg); \
+	create_sysfs_device_rw(kind, sub, offset);
+
+#define sysfs_rw(kind, sub, reg) \
+	create_getter(kind, sub); \
+	create_setter(kind, sub, reg); \
+	create_sysfs_device_rw(kind, sub,);
+
+#define sysfs_fan_with_min(offset, reg_status, reg_ripple, reg_min) \
+	sysfs_fan(offset, reg_status, reg_ripple); \
+	sysfs_rw_n(pwm,, offset, reg_min);
+
+#define sysfs_fan(offset, reg_status, reg_ripple) \
+	sysfs_ro_n(fan, _input, offset); \
+	sysfs_ro_n(fan, _status, offset); \
+	sysfs_rw_n(fan, _ripple, offset, reg_ripple);
+
+#define sysfs_temp(offset, reg_status) \
+	sysfs_ro_n(temp, _input, offset); \
+	sysfs_ro_n(temp, _status, offset); \
+	sysfs_rw_n(temp, _reset, offset, reg_status);
+
+#define sysfs_watchdog(reg_wdog_preset, reg_wdog_state, reg_wdog_control) \
+	sysfs_rw(wdog, _control, reg_wdog_control); \
+	sysfs_rw(wdog, _preset, reg_wdog_preset); \
+	sysfs_rw(wdog, _state, reg_wdog_state);
+
+sysfs_fan_with_min(1, FSCPOS_REG_FAN_STATE[0], FSCPOS_REG_FAN_RIPPLE[0],
+							FSCPOS_REG_PWM[0]);
+sysfs_fan_with_min(2, FSCPOS_REG_FAN_STATE[1], FSCPOS_REG_FAN_RIPPLE[1],
+							FSCPOS_REG_PWM[1]);
+sysfs_fan(3, FSCPOS_REG_FAN_STATE[2], FSCPOS_REG_FAN_RIPPLE[2]);
+
+sysfs_temp(1, FSCPOS_REG_TEMP_STATE[0]);
+sysfs_temp(2, FSCPOS_REG_TEMP_STATE[1]);
+sysfs_temp(3, FSCPOS_REG_TEMP_STATE[2]);
+
+sysfs_watchdog(FSCPOS_REG_WDOG_PRESET, FSCPOS_REG_WDOG_STATE,
+						FSCPOS_REG_WDOG_CONTROL);
+
+static DEVICE_ATTR(event, S_IRUGO, show_event, NULL);
+static DEVICE_ATTR(in0_input, S_IRUGO, show_volt_12, NULL);
+static DEVICE_ATTR(in1_input, S_IRUGO, show_volt_5, NULL);
+static DEVICE_ATTR(in2_input, S_IRUGO, show_volt_batt, NULL);
+
+static int fscpos_attach_adapter(struct i2c_adapter *adapter)
+{
+	if (!(adapter->class & I2C_CLASS_HWMON))
+		return 0;
+	return i2c_detect(adapter, &addr_data, fscpos_detect);
+}
+
+int fscpos_detect(struct i2c_adapter *adapter, int address, int kind)
+{
+	struct i2c_client *new_client;
+	struct fscpos_data *data;
+	int err = 0;
+
+	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+		goto exit;
+
+	/*
+	 * OK. For now, we presume we have a valid client. We now create the
+	 * client structure, even though we cannot fill it completely yet.
+	 * But it allows us to access fscpos_{read,write}_value.
+	 */
+
+	if (!(data = kmalloc(sizeof(struct fscpos_data), GFP_KERNEL))) {
+		err = -ENOMEM;
+		goto exit;
+	}
+	memset(data, 0, sizeof(struct fscpos_data));
+
+	new_client = &data->client;
+	i2c_set_clientdata(new_client, data);
+	new_client->addr = address;
+	new_client->adapter = adapter;
+	new_client->driver = &fscpos_driver;
+	new_client->flags = 0;
+
+	/* Do the remaining detection unless force or force_fscpos parameter */
+	if (kind < 0) {
+		if ((fscpos_read_value(new_client, FSCPOS_REG_IDENT_0)
+			!= 0x50) /* 'P' */
+		|| (fscpos_read_value(new_client, FSCPOS_REG_IDENT_1)
+			!= 0x45) /* 'E' */
+		|| (fscpos_read_value(new_client, FSCPOS_REG_IDENT_2)
+			!= 0x47))/* 'G' */
+		{
+			dev_dbg(&new_client->dev, "fscpos detection failed\n");
+			goto exit_free;
+		}
+	}
+
+	/* Fill in the remaining client fields and put it in the global list */
+	strlcpy(new_client->name, "fscpos", I2C_NAME_SIZE);
+
+	data->valid = 0;
+	init_MUTEX(&data->update_lock);
+
+	/* Tell the I2C layer a new client has arrived */
+	if ((err = i2c_attach_client(new_client)))
+		goto exit_free;
+
+	/* Inizialize the fscpos chip */
+	fscpos_init_client(new_client);
+
+	/* Announce that the chip was found */
+	dev_info(&new_client->dev, "Found fscpos chip, rev %u\n", data->revision);
+
+	/* Register sysfs hooks */
+	device_create_file(&new_client->dev, &dev_attr_event);
+	device_create_file(&new_client->dev, &dev_attr_in0_input);
+	device_create_file(&new_client->dev, &dev_attr_in1_input);
+	device_create_file(&new_client->dev, &dev_attr_in2_input);
+	device_create_file(&new_client->dev, &dev_attr_wdog_control);
+	device_create_file(&new_client->dev, &dev_attr_wdog_preset);
+	device_create_file(&new_client->dev, &dev_attr_wdog_state);
+	device_create_file(&new_client->dev, &dev_attr_temp1_input);
+	device_create_file(&new_client->dev, &dev_attr_temp1_status);
+	device_create_file(&new_client->dev, &dev_attr_temp1_reset);
+	device_create_file(&new_client->dev, &dev_attr_temp2_input);
+	device_create_file(&new_client->dev, &dev_attr_temp2_status);
+	device_create_file(&new_client->dev, &dev_attr_temp2_reset);
+	device_create_file(&new_client->dev, &dev_attr_temp3_input);
+	device_create_file(&new_client->dev, &dev_attr_temp3_status);
+	device_create_file(&new_client->dev, &dev_attr_temp3_reset);
+	device_create_file(&new_client->dev, &dev_attr_fan1_input);
+	device_create_file(&new_client->dev, &dev_attr_fan1_status);
+	device_create_file(&new_client->dev, &dev_attr_fan1_ripple);
+	device_create_file(&new_client->dev, &dev_attr_pwm1);
+	device_create_file(&new_client->dev, &dev_attr_fan2_input);
+	device_create_file(&new_client->dev, &dev_attr_fan2_status);
+	device_create_file(&new_client->dev, &dev_attr_fan2_ripple);
+	device_create_file(&new_client->dev, &dev_attr_pwm2);
+	device_create_file(&new_client->dev, &dev_attr_fan3_input);
+	device_create_file(&new_client->dev, &dev_attr_fan3_status);
+	device_create_file(&new_client->dev, &dev_attr_fan3_ripple);
+
+	return 0;
+
+exit_free:
+	kfree(data);
+exit:
+	return err;
+}
+
+static int fscpos_detach_client(struct i2c_client *client)
+{
+	int err;
+
+	if ((err = i2c_detach_client(client))) {
+		dev_err(&client->dev, "Client deregistration failed, client"
+							" not detached.\n");
+		return err;
+	}
+	kfree(i2c_get_clientdata(client));
+	return 0;
+}
+
+static int fscpos_read_value(struct i2c_client *client, u8 reg)
+{
+	dev_dbg(&client->dev, "Read reg 0x%02x\n", reg);
+	return i2c_smbus_read_byte_data(client, reg);
+}
+
+static int fscpos_write_value(struct i2c_client *client, u8 reg, u8 value)
+{
+	dev_dbg(&client->dev, "Write reg 0x%02x, val 0x%02x\n", reg, value);
+	return i2c_smbus_write_byte_data(client, reg, value);
+}
+
+/* Called when we have found a new FSCPOS chip */
+static void fscpos_init_client(struct i2c_client *client)
+{
+	struct fscpos_data *data = i2c_get_clientdata(client);
+
+	/* read revision from chip */
+	data->revision = fscpos_read_value(client, FSCPOS_REG_REVISION);
+}
+
+static struct fscpos_data *fscpos_update_device(struct device *dev)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct fscpos_data *data = i2c_get_clientdata(client);
+
+	down(&data->update_lock);
+
+	if ((jiffies - data->last_updated > 2 * HZ) ||
+			(jiffies < data->last_updated) || !data->valid) {
+		int i;
+
+		dev_dbg(&client->dev, "Starting fscpos update\n");
+
+		for (i = 0; i < 3; i++) {
+			data->temp_act[i] = fscpos_read_value(client,
+						FSCPOS_REG_TEMP_ACT[i]);
+			data->temp_status[i] = fscpos_read_value(client,
+						FSCPOS_REG_TEMP_STATE[i]);
+			data->fan_act[i] = fscpos_read_value(client,
+						FSCPOS_REG_FAN_ACT[i]);
+			data->fan_status[i] = fscpos_read_value(client,
+						FSCPOS_REG_FAN_STATE[i]);
+			data->fan_ripple[i] = fscpos_read_value(client,
+						FSCPOS_REG_FAN_RIPPLE[i]);
+			if (i < 2) {
+				/* fan2_min is not supported by the chip */
+				data->pwm[i] = fscpos_read_value(client,
+							FSCPOS_REG_PWM[i]);
+			}
+			/* reset fan status if speed is back to > 0 */
+			if (data->fan_status[i] != 0 && data->fan_act[i] > 0) {
+				reset_fan_alarm(client, i);
+			}
+		}
+
+		data->volt[0] = fscpos_read_value(client, FSCPOS_REG_VOLT_12);
+		data->volt[1] = fscpos_read_value(client, FSCPOS_REG_VOLT_5);
+		data->volt[2] = fscpos_read_value(client, FSCPOS_REG_VOLT_BATT);
+
+		data->wdog_preset = fscpos_read_value(client,
+							FSCPOS_REG_WDOG_PRESET);
+		data->wdog_state = fscpos_read_value(client,
+							FSCPOS_REG_WDOG_STATE);
+		data->wdog_control = fscpos_read_value(client,
+						FSCPOS_REG_WDOG_CONTROL);
+
+		data->global_event = fscpos_read_value(client,
+						FSCPOS_REG_EVENT_STATE);
+
+		data->last_updated = jiffies;
+		data->valid = 1;
+	}
+	up(&data->update_lock);
+	return data;
+}
+
+static int __init sm_fscpos_init(void)
+{
+	return i2c_add_driver(&fscpos_driver);
+}
+
+static void __exit sm_fscpos_exit(void)
+{
+	i2c_del_driver(&fscpos_driver);
+}
+
+MODULE_AUTHOR("Stefan Ott <stefan@desire.ch> based on work from Hermann Jung "
+				"<hej@odn.de>, Frodo Looijaard <frodol@dds.nl>"
+				" and Philip Edelbrock <phil@netroedge.com>");
+MODULE_DESCRIPTION("fujitsu siemens poseidon chip driver");
+MODULE_LICENSE("GPL");
+
+module_init(sm_fscpos_init);
+module_exit(sm_fscpos_exit);
diff -Nru a/drivers/i2c/chips/gl518sm.c b/drivers/i2c/chips/gl518sm.c
--- a/drivers/i2c/chips/gl518sm.c	2005-03-11 12:51:51 -08:00
+++ b/drivers/i2c/chips/gl518sm.c	2005-03-11 12:51:51 -08:00
@@ -40,6 +40,7 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/slab.h>
+#include <linux/jiffies.h>
 #include <linux/i2c.h>
 #include <linux/i2c-sensor.h>
 
@@ -159,12 +160,6 @@
 };
 
 /*
- * Internal variables
- */
-
-static int gl518_id;
-
-/*
  * Sysfs stuff
  */
 
@@ -396,7 +391,6 @@
 
 	/* Fill in the remaining client fields */
 	strlcpy(new_client->name, "gl518sm", I2C_NAME_SIZE);
-	new_client->id = gl518_id++;
 	data->type = kind;
 	data->valid = 0;
 	init_MUTEX(&data->update_lock);
@@ -512,8 +506,8 @@
 
 	down(&data->update_lock);
 
-	if ((jiffies - data->last_updated > HZ + HZ / 2) ||
-	    (jiffies < data->last_updated) || !data->valid) {
+	if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
+	    || !data->valid) {
 		dev_dbg(&client->dev, "Starting gl518 update\n");
 
 		data->alarms = gl518_read_value(client, GL518_REG_INT);
diff -Nru a/drivers/i2c/chips/gl520sm.c b/drivers/i2c/chips/gl520sm.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/i2c/chips/gl520sm.c	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,754 @@
+/*
+    gl520sm.c - Part of lm_sensors, Linux kernel modules for hardware
+                monitoring
+    Copyright (c) 1998, 1999  Frodo Looijaard <frodol@dds.nl>,
+                              Kyösti Mälkki <kmalkki@cc.hut.fi>
+    Copyright (c) 2005        Maarten Deprez <maartendeprez@users.sourceforge.net>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/i2c-sensor.h>
+#include <linux/i2c-vid.h>
+
+/* Type of the extra sensor */
+static unsigned short extra_sensor_type;
+module_param(extra_sensor_type, ushort, 0);
+MODULE_PARM_DESC(extra_sensor_type, "Type of extra sensor (0=autodetect, 1=temperature, 2=voltage)");
+
+/* Addresses to scan */
+static unsigned short normal_i2c[] = { 0x2c, 0x2d, I2C_CLIENT_END };
+static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
+
+/* Insmod parameters */
+SENSORS_INSMOD_1(gl520sm);
+
+/* Many GL520 constants specified below 
+One of the inputs can be configured as either temp or voltage.
+That's why _TEMP2 and _IN4 access the same register 
+*/
+
+/* The GL520 registers */
+#define GL520_REG_CHIP_ID		0x00
+#define GL520_REG_REVISION		0x01
+#define GL520_REG_CONF			0x03
+#define GL520_REG_MASK			0x11
+
+#define GL520_REG_VID_INPUT		0x02
+
+#define GL520_REG_IN0_INPUT		0x15
+#define GL520_REG_IN0_LIMIT		0x0c
+#define GL520_REG_IN0_MIN		GL520_REG_IN0_LIMIT
+#define GL520_REG_IN0_MAX		GL520_REG_IN0_LIMIT
+
+#define GL520_REG_IN1_INPUT		0x14
+#define GL520_REG_IN1_LIMIT		0x09
+#define GL520_REG_IN1_MIN		GL520_REG_IN1_LIMIT
+#define GL520_REG_IN1_MAX		GL520_REG_IN1_LIMIT
+
+#define GL520_REG_IN2_INPUT		0x13
+#define GL520_REG_IN2_LIMIT		0x0a
+#define GL520_REG_IN2_MIN		GL520_REG_IN2_LIMIT
+#define GL520_REG_IN2_MAX		GL520_REG_IN2_LIMIT
+
+#define GL520_REG_IN3_INPUT		0x0d
+#define GL520_REG_IN3_LIMIT		0x0b
+#define GL520_REG_IN3_MIN		GL520_REG_IN3_LIMIT
+#define GL520_REG_IN3_MAX		GL520_REG_IN3_LIMIT
+
+#define GL520_REG_IN4_INPUT		0x0e
+#define GL520_REG_IN4_MAX		0x17
+#define GL520_REG_IN4_MIN		0x18
+
+#define GL520_REG_TEMP1_INPUT		0x04
+#define GL520_REG_TEMP1_MAX		0x05
+#define GL520_REG_TEMP1_MAX_HYST	0x06
+
+#define GL520_REG_TEMP2_INPUT		0x0e
+#define GL520_REG_TEMP2_MAX		0x17
+#define GL520_REG_TEMP2_MAX_HYST	0x18
+
+#define GL520_REG_FAN_INPUT		0x07
+#define GL520_REG_FAN_MIN		0x08
+#define GL520_REG_FAN_DIV		0x0f
+#define GL520_REG_FAN_OFF		GL520_REG_FAN_DIV
+
+#define GL520_REG_ALARMS		0x12
+#define GL520_REG_BEEP_MASK		0x10
+#define GL520_REG_BEEP_ENABLE		GL520_REG_CONF
+
+/*
+ * Function declarations
+ */
+
+static int gl520_attach_adapter(struct i2c_adapter *adapter);
+static int gl520_detect(struct i2c_adapter *adapter, int address, int kind);
+static void gl520_init_client(struct i2c_client *client);
+static int gl520_detach_client(struct i2c_client *client);
+static int gl520_read_value(struct i2c_client *client, u8 reg);
+static int gl520_write_value(struct i2c_client *client, u8 reg, u16 value);
+static struct gl520_data *gl520_update_device(struct device *dev);
+
+/* Driver data */
+static struct i2c_driver gl520_driver = {
+	.owner		= THIS_MODULE,
+	.name		= "gl520sm",
+	.id		= I2C_DRIVERID_GL520,
+	.flags		= I2C_DF_NOTIFY,
+	.attach_adapter	= gl520_attach_adapter,
+	.detach_client	= gl520_detach_client,
+};
+
+/* Client data */
+struct gl520_data {
+	struct i2c_client client;
+	struct semaphore update_lock;
+	char valid;		/* zero until the following fields are valid */
+	unsigned long last_updated;	/* in jiffies */
+
+	u8 vid;
+	u8 vrm;
+	u8 in_input[5];		/* [0] = VVD */
+	u8 in_min[5];		/* [0] = VDD */
+	u8 in_max[5];		/* [0] = VDD */
+	u8 fan_input[2];
+	u8 fan_min[2];
+	u8 fan_div[2];
+	u8 fan_off;
+	u8 temp_input[2];
+	u8 temp_max[2];
+	u8 temp_max_hyst[2];
+	u8 alarms;
+	u8 beep_enable;
+	u8 beep_mask;
+	u8 alarm_mask;
+	u8 two_temps;
+};
+
+/*
+ * Sysfs stuff
+ */
+
+#define sysfs_r(type, n, item, reg) \
+static ssize_t get_##type##item (struct gl520_data *, char *, int); \
+static ssize_t get_##type##n##item (struct device *, char *); \
+static ssize_t get_##type##n##item (struct device *dev, char *buf) \
+{ \
+	struct gl520_data *data = gl520_update_device(dev); \
+	return get_##type##item(data, buf, (n)); \
+}
+
+#define sysfs_w(type, n, item, reg) \
+static ssize_t set_##type##item (struct i2c_client *, struct gl520_data *, const char *, size_t, int, int); \
+static ssize_t set_##type##n##item (struct device *, const char *, size_t); \
+static ssize_t set_##type##n##item (struct device *dev, const char *buf, size_t count) \
+{ \
+	struct i2c_client *client = to_i2c_client(dev); \
+	struct gl520_data *data = i2c_get_clientdata(client); \
+	return set_##type##item(client, data, buf, count, (n), reg); \
+}
+
+#define sysfs_rw_n(type, n, item, reg) \
+sysfs_r(type, n, item, reg) \
+sysfs_w(type, n, item, reg) \
+static DEVICE_ATTR(type##n##item, S_IRUGO | S_IWUSR, get_##type##n##item, set_##type##n##item);
+
+#define sysfs_ro_n(type, n, item, reg) \
+sysfs_r(type, n, item, reg) \
+static DEVICE_ATTR(type##n##item, S_IRUGO, get_##type##n##item, NULL);
+
+#define sysfs_rw(type, item, reg) \
+sysfs_r(type, 0, item, reg) \
+sysfs_w(type, 0, item, reg) \
+static DEVICE_ATTR(type##item, S_IRUGO | S_IWUSR, get_##type##0##item, set_##type##0##item);
+
+#define sysfs_ro(type, item, reg) \
+sysfs_r(type, 0, item, reg) \
+static DEVICE_ATTR(type##item, S_IRUGO, get_##type##0##item, NULL);
+
+
+#define sysfs_vid(n) \
+sysfs_ro_n(cpu, n, _vid, GL520_REG_VID_INPUT)
+
+#define device_create_file_vid(client, n) \
+device_create_file(&client->dev, &dev_attr_cpu##n##_vid)
+
+#define sysfs_in(n) \
+sysfs_ro_n(in, n, _input, GL520_REG_IN##n##INPUT) \
+sysfs_rw_n(in, n, _min, GL520_REG_IN##n##_MIN) \
+sysfs_rw_n(in, n, _max, GL520_REG_IN##n##_MAX) \
+
+#define device_create_file_in(client, n) \
+({device_create_file(&client->dev, &dev_attr_in##n##_input); \
+device_create_file(&client->dev, &dev_attr_in##n##_min); \
+device_create_file(&client->dev, &dev_attr_in##n##_max);})
+
+#define sysfs_fan(n) \
+sysfs_ro_n(fan, n, _input, GL520_REG_FAN_INPUT) \
+sysfs_rw_n(fan, n, _min, GL520_REG_FAN_MIN) \
+sysfs_rw_n(fan, n, _div, GL520_REG_FAN_DIV)
+
+#define device_create_file_fan(client, n) \
+({device_create_file(&client->dev, &dev_attr_fan##n##_input); \
+device_create_file(&client->dev, &dev_attr_fan##n##_min); \
+device_create_file(&client->dev, &dev_attr_fan##n##_div);})
+
+#define sysfs_fan_off(n) \
+sysfs_rw_n(fan, n, _off, GL520_REG_FAN_OFF) \
+
+#define device_create_file_fan_off(client, n) \
+device_create_file(&client->dev, &dev_attr_fan##n##_off)
+
+#define sysfs_temp(n) \
+sysfs_ro_n(temp, n, _input, GL520_REG_TEMP##n##_INPUT) \
+sysfs_rw_n(temp, n, _max, GL520_REG_TEMP##n##_MAX) \
+sysfs_rw_n(temp, n, _max_hyst, GL520_REG_TEMP##n##_MAX_HYST)
+
+#define device_create_file_temp(client, n) \
+({device_create_file(&client->dev, &dev_attr_temp##n##_input); \
+device_create_file(&client->dev, &dev_attr_temp##n##_max); \
+device_create_file(&client->dev, &dev_attr_temp##n##_max_hyst);})
+
+#define sysfs_alarms() \
+sysfs_ro(alarms, , GL520_REG_ALARMS) \
+sysfs_rw(beep_enable, , GL520_REG_BEEP_ENABLE) \
+sysfs_rw(beep_mask, , GL520_REG_BEEP_MASK)
+
+#define device_create_file_alarms(client) \
+({device_create_file(&client->dev, &dev_attr_alarms); \
+device_create_file(&client->dev, &dev_attr_beep_enable); \
+device_create_file(&client->dev, &dev_attr_beep_mask);})
+
+
+sysfs_vid(0)
+
+sysfs_in(0)
+sysfs_in(1)
+sysfs_in(2)
+sysfs_in(3)
+sysfs_in(4)
+
+sysfs_fan(1)
+sysfs_fan(2)
+sysfs_fan_off(1)
+
+sysfs_temp(1)
+sysfs_temp(2)
+
+sysfs_alarms()
+
+
+static ssize_t get_cpu_vid(struct gl520_data *data, char *buf, int n)
+{
+	return sprintf(buf, "%u\n", vid_from_reg(data->vid, data->vrm));
+}
+
+#define VDD_FROM_REG(val) (((val)*95+2)/4)
+#define VDD_TO_REG(val) (SENSORS_LIMIT((((val)*4+47)/95),0,255))
+
+#define IN_FROM_REG(val) ((val)*19)
+#define IN_TO_REG(val) (SENSORS_LIMIT((((val)+9)/19),0,255))
+
+static ssize_t get_in_input(struct gl520_data *data, char *buf, int n)
+{
+	u8 r = data->in_input[n];
+
+	if (n == 0)
+		return sprintf(buf, "%d\n", VDD_FROM_REG(r));
+	else
+		return sprintf(buf, "%d\n", IN_FROM_REG(r));
+}
+
+static ssize_t get_in_min(struct gl520_data *data, char *buf, int n)
+{
+	u8 r = data->in_min[n];
+
+	if (n == 0)
+		return sprintf(buf, "%d\n", VDD_FROM_REG(r));
+	else
+		return sprintf(buf, "%d\n", IN_FROM_REG(r));
+}
+
+static ssize_t get_in_max(struct gl520_data *data, char *buf, int n)
+{
+	u8 r = data->in_max[n];
+
+	if (n == 0)
+		return sprintf(buf, "%d\n", VDD_FROM_REG(r));
+	else
+		return sprintf(buf, "%d\n", IN_FROM_REG(r));
+}
+
+static ssize_t set_in_min(struct i2c_client *client, struct gl520_data *data, const char *buf, size_t count, int n, int reg)
+{
+	long v = simple_strtol(buf, NULL, 10);
+	u8 r;
+
+	if (n == 0)
+		r = VDD_TO_REG(v);
+	else
+		r = IN_TO_REG(v);
+
+	data->in_min[n] = r;
+
+	if (n < 4)
+		gl520_write_value(client, reg, (gl520_read_value(client, reg) & ~0xff) | r);
+	else
+		gl520_write_value(client, reg, r);
+
+	return count;
+}
+
+static ssize_t set_in_max(struct i2c_client *client, struct gl520_data *data, const char *buf, size_t count, int n, int reg)
+{
+	long v = simple_strtol(buf, NULL, 10);
+	u8 r;
+
+	if (n == 0)
+		r = VDD_TO_REG(v);
+	else
+		r = IN_TO_REG(v);
+
+	data->in_max[n] = r;
+
+	if (n < 4)
+		gl520_write_value(client, reg, (gl520_read_value(client, reg) & ~0xff00) | (r << 8));
+	else
+		gl520_write_value(client, reg, r);
+
+	return count;
+}
+
+#define DIV_FROM_REG(val) (1 << (val))
+#define FAN_FROM_REG(val,div) ((val)==0 ? 0 : (480000/((val) << (div))))
+#define FAN_TO_REG(val,div) ((val)<=0?0:SENSORS_LIMIT((480000 + ((val) << ((div)-1))) / ((val) << (div)), 1, 255));
+
+static ssize_t get_fan_input(struct gl520_data *data, char *buf, int n)
+{
+	return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan_input[n - 1], data->fan_div[n - 1]));
+}
+
+static ssize_t get_fan_min(struct gl520_data *data, char *buf, int n)
+{
+	return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan_min[n - 1], data->fan_div[n - 1]));
+}
+
+static ssize_t get_fan_div(struct gl520_data *data, char *buf, int n)
+{
+	return sprintf(buf, "%d\n", DIV_FROM_REG(data->fan_div[n - 1]));
+}
+
+static ssize_t get_fan_off(struct gl520_data *data, char *buf, int n)
+{
+	return sprintf(buf, "%d\n", data->fan_off);
+}
+
+static ssize_t set_fan_min(struct i2c_client *client, struct gl520_data *data, const char *buf, size_t count, int n, int reg)
+{
+	unsigned long v = simple_strtoul(buf, NULL, 10);
+	u8 r = FAN_TO_REG(v, data->fan_div[n - 1]);
+
+	data->fan_min[n - 1] = r;
+
+	if (n == 1)
+		gl520_write_value(client, reg, (gl520_read_value(client, reg) & ~0xff00) | (r << 8));
+	else
+		gl520_write_value(client, reg, (gl520_read_value(client, reg) & ~0xff) | r);
+
+	data->beep_mask = gl520_read_value(client, GL520_REG_BEEP_MASK);
+	if (data->fan_min[n - 1] == 0)
+		data->alarm_mask &= (n == 1) ? ~0x20 : ~0x40;
+	else
+		data->alarm_mask |= (n == 1) ? 0x20 : 0x40;
+	data->beep_mask &= data->alarm_mask;
+	gl520_write_value(client, GL520_REG_BEEP_MASK, data->beep_mask);
+
+	return count;
+}
+
+static ssize_t set_fan_div(struct i2c_client *client, struct gl520_data *data, const char *buf, size_t count, int n, int reg)
+{
+	unsigned long v = simple_strtoul(buf, NULL, 10);
+	u8 r;
+
+	switch (v) {
+	case 1: r = 0; break;
+	case 2: r = 1; break;
+	case 4: r = 2; break;
+	case 8: r = 3; break;
+	default:
+		dev_err(&client->dev, "fan_div value %ld not supported. Choose one of 1, 2, 4 or 8!\n", v);
+		return -EINVAL;
+	}
+
+	data->fan_div[n - 1] = r;
+
+	if (n == 1)
+		gl520_write_value(client, reg, (gl520_read_value(client, reg) & ~0xc0) | (r << 6));
+	else
+		gl520_write_value(client, reg, (gl520_read_value(client, reg) & ~0x30) | (r << 4));
+
+	return count;
+}
+
+static ssize_t set_fan_off(struct i2c_client *client, struct gl520_data *data, const char *buf, size_t count, int n, int reg)
+{
+	u8 r = simple_strtoul(buf, NULL, 10)?1:0;
+
+	data->fan_off = r;
+	gl520_write_value(client, reg, (gl520_read_value(client, reg) & ~0x0c) | (r << 2));
+
+	return count;
+}
+
+#define TEMP_FROM_REG(val) (((val) - 130) * 1000)
+#define TEMP_TO_REG(val) (SENSORS_LIMIT(((((val)<0?(val)-500:(val)+500) / 1000)+130),0,255))
+
+static ssize_t get_temp_input(struct gl520_data *data, char *buf, int n)
+{
+	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_input[n - 1]));
+}
+
+static ssize_t get_temp_max(struct gl520_data *data, char *buf, int n)
+{
+	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_max[n - 1]));
+}
+
+static ssize_t get_temp_max_hyst(struct gl520_data *data, char *buf, int n)
+{
+	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_max_hyst[n - 1]));
+}
+
+static ssize_t set_temp_max(struct i2c_client *client, struct gl520_data *data, const char *buf, size_t count, int n, int reg)
+{
+	long v = simple_strtol(buf, NULL, 10);
+	u8 r = TEMP_TO_REG(v);
+
+	data->temp_max[n - 1] = r;
+	gl520_write_value(client, reg, r);
+
+	return count;
+}
+
+static ssize_t set_temp_max_hyst(struct i2c_client *client, struct gl520_data *data, const char *buf, size_t count, int n, int reg)
+{
+	long v = simple_strtol(buf, NULL, 10);
+	u8 r = TEMP_TO_REG(v);
+
+	data->temp_max_hyst[n - 1] = r;
+	gl520_write_value(client, reg, r);
+
+	return count;
+}
+
+static ssize_t get_alarms(struct gl520_data *data, char *buf, int n)
+{
+	return sprintf(buf, "%d\n", data->alarms);
+}
+
+static ssize_t get_beep_enable(struct gl520_data *data, char *buf, int n)
+{
+	return sprintf(buf, "%d\n", data->beep_enable);
+}
+
+static ssize_t get_beep_mask(struct gl520_data *data, char *buf, int n)
+{
+	return sprintf(buf, "%d\n", data->beep_mask);
+}
+
+static ssize_t set_beep_enable(struct i2c_client *client, struct gl520_data *data, const char *buf, size_t count, int n, int reg)
+{
+	u8 r = simple_strtoul(buf, NULL, 10)?0:1;
+
+	data->beep_enable = !r;
+	gl520_write_value(client, reg, (gl520_read_value(client, reg) & ~0x04) | (r << 2));
+
+	return count;
+}
+
+static ssize_t set_beep_mask(struct i2c_client *client, struct gl520_data *data, const char *buf, size_t count, int n, int reg)
+{
+	u8 r = simple_strtoul(buf, NULL, 10) & data->alarm_mask;
+
+	data->beep_mask = r;
+	gl520_write_value(client, reg, r);
+
+	return count;
+}
+
+
+/*
+ * Real code
+ */
+
+static int gl520_attach_adapter(struct i2c_adapter *adapter)
+{
+	if (!(adapter->class & I2C_CLASS_HWMON))
+		return 0;
+	return i2c_detect(adapter, &addr_data, gl520_detect);
+}
+
+static int gl520_detect(struct i2c_adapter *adapter, int address, int kind)
+{
+	struct i2c_client *new_client;
+	struct gl520_data *data;
+	int err = 0;
+
+	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA |
+				     I2C_FUNC_SMBUS_WORD_DATA))
+		goto exit;
+
+	/* OK. For now, we presume we have a valid client. We now create the
+	   client structure, even though we cannot fill it completely yet.
+	   But it allows us to access gl520_{read,write}_value. */
+
+	if (!(data = kmalloc(sizeof(struct gl520_data), GFP_KERNEL))) {
+		err = -ENOMEM;
+		goto exit;
+	}
+	memset(data, 0, sizeof(struct gl520_data));
+
+	new_client = &data->client;
+	i2c_set_clientdata(new_client, data);
+	new_client->addr = address;
+	new_client->adapter = adapter;
+	new_client->driver = &gl520_driver;
+	new_client->flags = 0;
+
+	/* Determine the chip type. */
+	if (kind < 0) {
+		if ((gl520_read_value(new_client, GL520_REG_CHIP_ID) != 0x20) ||
+		    ((gl520_read_value(new_client, GL520_REG_REVISION) & 0x7f) != 0x00) ||
+		    ((gl520_read_value(new_client, GL520_REG_CONF) & 0x80) != 0x00)) {
+			dev_dbg(&new_client->dev, "Unknown chip type, skipping\n");
+			goto exit_free;
+		}
+	}
+
+	/* Fill in the remaining client fields */
+	strlcpy(new_client->name, "gl520sm", I2C_NAME_SIZE);
+	data->valid = 0;
+	init_MUTEX(&data->update_lock);
+
+	/* Tell the I2C layer a new client has arrived */
+	if ((err = i2c_attach_client(new_client)))
+		goto exit_free;
+
+	/* Initialize the GL520SM chip */
+	gl520_init_client(new_client);
+
+	/* Register sysfs hooks */
+	device_create_file_vid(new_client, 0);
+
+	device_create_file_in(new_client, 0);
+	device_create_file_in(new_client, 1);
+	device_create_file_in(new_client, 2);
+	device_create_file_in(new_client, 3);
+	if (!data->two_temps)
+		device_create_file_in(new_client, 4);
+
+	device_create_file_fan(new_client, 1);
+	device_create_file_fan(new_client, 2);
+	device_create_file_fan_off(new_client, 1);
+
+	device_create_file_temp(new_client, 1);
+	if (data->two_temps)
+		device_create_file_temp(new_client, 2);
+
+	device_create_file_alarms(new_client);
+
+	return 0;
+
+exit_free:
+	kfree(data);
+exit:
+	return err;
+}
+
+
+/* Called when we have found a new GL520SM. */
+static void gl520_init_client(struct i2c_client *client)
+{
+	struct gl520_data *data = i2c_get_clientdata(client);
+	u8 oldconf, conf;
+
+	conf = oldconf = gl520_read_value(client, GL520_REG_CONF);
+
+	data->alarm_mask = 0xff;
+	data->vrm = i2c_which_vrm();
+
+	if (extra_sensor_type == 1)
+		conf &= ~0x10;
+	else if (extra_sensor_type == 2)
+		conf |= 0x10;
+	data->two_temps = !(conf & 0x10);
+
+	/* If IRQ# is disabled, we can safely force comparator mode */
+	if (!(conf & 0x20))
+		conf &= 0xf7;
+
+	/* Enable monitoring if needed */
+	conf |= 0x40;
+
+	if (conf != oldconf)
+		gl520_write_value(client, GL520_REG_CONF, conf);
+
+	gl520_update_device(&(client->dev));
+
+	if (data->fan_min[0] == 0)
+		data->alarm_mask &= ~0x20;
+	if (data->fan_min[1] == 0)
+		data->alarm_mask &= ~0x40;
+
+	data->beep_mask &= data->alarm_mask;
+	gl520_write_value(client, GL520_REG_BEEP_MASK, data->beep_mask);
+}
+
+static int gl520_detach_client(struct i2c_client *client)
+{
+	int err;
+
+	if ((err = i2c_detach_client(client))) {
+		dev_err(&client->dev, "Client deregistration failed, "
+			"client not detached.\n");
+		return err;
+	}
+
+	kfree(i2c_get_clientdata(client));
+	return 0;
+}
+
+
+/* Registers 0x07 to 0x0c are word-sized, others are byte-sized 
+   GL520 uses a high-byte first convention */
+static int gl520_read_value(struct i2c_client *client, u8 reg)
+{
+	if ((reg >= 0x07) && (reg <= 0x0c))
+		return swab16(i2c_smbus_read_word_data(client, reg));
+	else
+		return i2c_smbus_read_byte_data(client, reg);
+}
+
+static int gl520_write_value(struct i2c_client *client, u8 reg, u16 value)
+{
+	if ((reg >= 0x07) && (reg <= 0x0c))
+		return i2c_smbus_write_word_data(client, reg, swab16(value));
+	else
+		return i2c_smbus_write_byte_data(client, reg, value);
+}
+
+
+static struct gl520_data *gl520_update_device(struct device *dev)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct gl520_data *data = i2c_get_clientdata(client);
+	int val;
+
+	down(&data->update_lock);
+
+	if ((jiffies - data->last_updated > 2 * HZ) ||
+	    (jiffies < data->last_updated) || !data->valid) {
+
+		dev_dbg(&client->dev, "Starting gl520sm update\n");
+
+		data->alarms = gl520_read_value(client, GL520_REG_ALARMS);
+		data->beep_mask = gl520_read_value(client, GL520_REG_BEEP_MASK);
+		data->vid = gl520_read_value(client, GL520_REG_VID_INPUT) & 0x1f;
+
+		val = gl520_read_value(client, GL520_REG_IN0_LIMIT);
+		data->in_min[0] = val & 0xff;
+		data->in_max[0] = (val >> 8) & 0xff;
+		val = gl520_read_value(client, GL520_REG_IN1_LIMIT);
+		data->in_min[1] = val & 0xff;
+		data->in_max[1] = (val >> 8) & 0xff;
+		val = gl520_read_value(client, GL520_REG_IN2_LIMIT);
+		data->in_min[2] = val & 0xff;
+		data->in_max[2] = (val >> 8) & 0xff;
+		val = gl520_read_value(client, GL520_REG_IN3_LIMIT);
+		data->in_min[3] = val & 0xff;
+		data->in_max[3] = (val >> 8) & 0xff;
+
+		val = gl520_read_value(client, GL520_REG_FAN_INPUT);
+		data->fan_input[0] = (val >> 8) & 0xff;
+		data->fan_input[1] = val & 0xff;
+
+		val = gl520_read_value(client, GL520_REG_FAN_MIN);
+		data->fan_min[0] = (val >> 8) & 0xff;
+		data->fan_min[1] = val & 0xff;
+
+		data->temp_input[0] = gl520_read_value(client, GL520_REG_TEMP1_INPUT);
+		data->temp_max[0] = gl520_read_value(client, GL520_REG_TEMP1_MAX);
+		data->temp_max_hyst[0] = gl520_read_value(client, GL520_REG_TEMP1_MAX_HYST);
+
+		val = gl520_read_value(client, GL520_REG_FAN_DIV);
+		data->fan_div[0] = (val >> 6) & 0x03;
+		data->fan_div[1] = (val >> 4) & 0x03;
+		data->fan_off = (val >> 2) & 0x01;
+
+		data->alarms &= data->alarm_mask;
+
+		val = gl520_read_value(client, GL520_REG_CONF);
+		data->beep_enable = !((val >> 2) & 1);
+
+		data->in_input[0] = gl520_read_value(client, GL520_REG_IN0_INPUT);
+		data->in_input[1] = gl520_read_value(client, GL520_REG_IN1_INPUT);
+		data->in_input[2] = gl520_read_value(client, GL520_REG_IN2_INPUT);
+		data->in_input[3] = gl520_read_value(client, GL520_REG_IN3_INPUT);
+
+		/* Temp1 and Vin4 are the same input */
+		if (data->two_temps) {
+			data->temp_input[1] = gl520_read_value(client, GL520_REG_TEMP2_INPUT);
+			data->temp_max[1] = gl520_read_value(client, GL520_REG_TEMP2_MAX);
+			data->temp_max_hyst[1] = gl520_read_value(client, GL520_REG_TEMP2_MAX_HYST);
+		} else {
+			data->in_input[4] = gl520_read_value(client, GL520_REG_IN4_INPUT);
+			data->in_min[4] = gl520_read_value(client, GL520_REG_IN4_MIN);
+			data->in_max[4] = gl520_read_value(client, GL520_REG_IN4_MAX);
+		}
+
+		data->last_updated = jiffies;
+		data->valid = 1;
+	}
+
+	up(&data->update_lock);
+
+	return data;
+}
+
+
+static int __init sensors_gl520sm_init(void)
+{
+	return i2c_add_driver(&gl520_driver);
+}
+
+static void __exit sensors_gl520sm_exit(void)
+{
+	i2c_del_driver(&gl520_driver);
+}
+
+
+MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>, "
+	"Kyösti Mälkki <kmalkki@cc.hut.fi>, "
+	"Maarten Deprez <maartendeprez@users.sourceforge.net>");
+MODULE_DESCRIPTION("GL520SM driver");
+MODULE_LICENSE("GPL");
+
+module_init(sensors_gl520sm_init);
+module_exit(sensors_gl520sm_exit);
diff -Nru a/drivers/i2c/chips/isp1301_omap.c b/drivers/i2c/chips/isp1301_omap.c
--- a/drivers/i2c/chips/isp1301_omap.c	2005-03-11 12:51:51 -08:00
+++ b/drivers/i2c/chips/isp1301_omap.c	2005-03-11 12:51:51 -08:00
@@ -1503,7 +1503,6 @@
 	isp->client.addr = address;
 	i2c_set_clientdata(&isp->client, isp);
 	isp->client.adapter = bus;
-	isp->client.id = 1301;
 	isp->client.driver = &isp1301_driver;
 	strlcpy(isp->client.name, DRIVER_NAME, I2C_NAME_SIZE);
 	i2c = &isp->client;
diff -Nru a/drivers/i2c/chips/it87.c b/drivers/i2c/chips/it87.c
--- a/drivers/i2c/chips/it87.c	2005-03-11 12:51:50 -08:00
+++ b/drivers/i2c/chips/it87.c	2005-03-11 12:51:50 -08:00
@@ -35,6 +35,7 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/slab.h>
+#include <linux/jiffies.h>
 #include <linux/i2c.h>
 #include <linux/i2c-sensor.h>
 #include <linux/i2c-vid.h>
@@ -104,6 +105,9 @@
 /* Update battery voltage after every reading if true */
 static int update_vbat;
 
+/* Not all BIOSes properly configure the PWM registers */
+static int fix_pwm_polarity;
+
 /* Chip Type */
 
 static u16 chip_type;
@@ -224,6 +228,7 @@
 static int it87_write_value(struct i2c_client *client, u8 register,
 			u8 value);
 static struct it87_data *it87_update_device(struct device *dev);
+static int it87_check_pwm(struct i2c_client *client);
 static void it87_init_client(struct i2c_client *client, struct it87_data *data);
 
 
@@ -718,7 +723,6 @@
 	const char *name = "";
 	int is_isa = i2c_is_isa_adapter(adapter);
 	int enable_pwm_interface;
-	int tmp;
 
 	if (!is_isa && 
 	    !i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
@@ -822,20 +826,12 @@
 	if ((err = i2c_attach_client(new_client)))
 		goto ERROR2;
 
+	/* Check PWM configuration */
+	enable_pwm_interface = it87_check_pwm(new_client);
+
 	/* Initialize the IT87 chip */
 	it87_init_client(new_client, data);
 
-	/* Some BIOSes fail to correctly configure the IT87 fans. All fans off
-	 * and polarity set to active low is sign that this is the case so we
-	 * disable pwm control to protect the user. */
-	enable_pwm_interface = 1;
-	tmp = it87_read_value(new_client, IT87_REG_FAN_CTL);
-	if ((tmp & 0x87) == 0) {
-		enable_pwm_interface = 0;
-		dev_info(&new_client->dev,
-			"detected broken BIOS defaults, disabling pwm interface");
-	}
-
 	/* Register sysfs hooks */
 	device_create_file(&new_client->dev, &dev_attr_in0_input);
 	device_create_file(&new_client->dev, &dev_attr_in1_input);
@@ -966,6 +962,56 @@
 		return i2c_smbus_write_byte_data(client, reg, value);
 }
 
+/* Return 1 if and only if the PWM interface is safe to use */
+static int it87_check_pwm(struct i2c_client *client)
+{
+	/* Some BIOSes fail to correctly configure the IT87 fans. All fans off
+	 * and polarity set to active low is sign that this is the case so we
+	 * disable pwm control to protect the user. */
+	int tmp = it87_read_value(client, IT87_REG_FAN_CTL);
+	if ((tmp & 0x87) == 0) {
+		if (fix_pwm_polarity) {
+			/* The user asks us to attempt a chip reconfiguration.
+			 * This means switching to active high polarity and
+			 * inverting all fan speed values. */
+			int i;
+			u8 pwm[3];
+
+			for (i = 0; i < 3; i++)
+				pwm[i] = it87_read_value(client,
+							 IT87_REG_PWM(i));
+
+			/* If any fan is in automatic pwm mode, the polarity
+			 * might be correct, as suspicious as it seems, so we
+			 * better don't change anything (but still disable the
+			 * PWM interface). */
+			if (!((pwm[0] | pwm[1] | pwm[2]) & 0x80)) {
+				dev_info(&client->dev, "Reconfiguring PWM to "
+					 "active high polarity\n");
+				it87_write_value(client, IT87_REG_FAN_CTL,
+						 tmp | 0x87);
+				for (i = 0; i < 3; i++)
+					it87_write_value(client,
+							 IT87_REG_PWM(i),
+							 0x7f & ~pwm[i]);
+				return 1;
+			}
+
+			dev_info(&client->dev, "PWM configuration is "
+				 "too broken to be fixed\n");
+		}
+
+		dev_info(&client->dev, "Detected broken BIOS "
+			 "defaults, disabling PWM interface\n");
+		return 0;
+	} else if (fix_pwm_polarity) {
+		dev_info(&client->dev, "PWM configuration looks "
+			 "sane, won't touch\n");
+	}
+
+	return 1;
+}
+
 /* Called when we have found a new IT87. */
 static void it87_init_client(struct i2c_client *client, struct it87_data *data)
 {
@@ -1038,8 +1084,8 @@
 
 	down(&data->update_lock);
 
-	if ((jiffies - data->last_updated > HZ + HZ / 2) ||
-	    (jiffies < data->last_updated) || !data->valid) {
+	if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
+	    || !data->valid) {
 
 		if (update_vbat) {
 			/* Cleared after each update, so reenable.  Value
@@ -1126,6 +1172,8 @@
 MODULE_DESCRIPTION("IT8705F, IT8712F, Sis950 driver");
 module_param(update_vbat, bool, 0);
 MODULE_PARM_DESC(update_vbat, "Update vbat if set else return powerup value");
+module_param(fix_pwm_polarity, bool, 0);
+MODULE_PARM_DESC(fix_pwm_polarity, "Force PWM polarity to active high (DANGEROUS)");
 MODULE_LICENSE("GPL");
 
 module_init(sm_it87_init);
diff -Nru a/drivers/i2c/chips/lm63.c b/drivers/i2c/chips/lm63.c
--- a/drivers/i2c/chips/lm63.c	2005-03-11 12:51:52 -08:00
+++ b/drivers/i2c/chips/lm63.c	2005-03-11 12:51:52 -08:00
@@ -41,6 +41,7 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/slab.h>
+#include <linux/jiffies.h>
 #include <linux/i2c.h>
 #include <linux/i2c-sensor.h>
 
@@ -492,9 +493,7 @@
 
 	down(&data->update_lock);
 
-	if ((jiffies - data->last_updated > HZ) ||
-	    (jiffies < data->last_updated) ||
-	    !data->valid) {
+	if (time_after(jiffies, data->last_updated + HZ) || !data->valid) {
 		if (data->config & 0x04) { /* tachometer enabled  */
 			/* order matters for fan1_input */
 			data->fan1_input = i2c_smbus_read_byte_data(client,
diff -Nru a/drivers/i2c/chips/lm75.c b/drivers/i2c/chips/lm75.c
--- a/drivers/i2c/chips/lm75.c	2005-03-11 12:51:52 -08:00
+++ b/drivers/i2c/chips/lm75.c	2005-03-11 12:51:52 -08:00
@@ -22,6 +22,7 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/slab.h>
+#include <linux/jiffies.h>
 #include <linux/i2c.h>
 #include <linux/i2c-sensor.h>
 #include "lm75.h"
@@ -73,8 +74,6 @@
 	.detach_client	= lm75_detach_client,
 };
 
-static int lm75_id;
-
 #define show(value)	\
 static ssize_t show_##value(struct device *dev, char *buf)		\
 {									\
@@ -196,8 +195,6 @@
 
 	/* Fill in the remaining client fields and put it into the global list */
 	strlcpy(new_client->name, name, I2C_NAME_SIZE);
-
-	new_client->id = lm75_id++;
 	data->valid = 0;
 	init_MUTEX(&data->update_lock);
 
@@ -263,8 +260,8 @@
 
 	down(&data->update_lock);
 
-	if ((jiffies - data->last_updated > HZ + HZ / 2) ||
-	    (jiffies < data->last_updated) || !data->valid) {
+	if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
+	    || !data->valid) {
 		dev_dbg(&client->dev, "Starting lm75 update\n");
 
 		data->temp_input = lm75_read_value(client, LM75_REG_TEMP);
diff -Nru a/drivers/i2c/chips/lm77.c b/drivers/i2c/chips/lm77.c
--- a/drivers/i2c/chips/lm77.c	2005-03-11 12:51:52 -08:00
+++ b/drivers/i2c/chips/lm77.c	2005-03-11 12:51:52 -08:00
@@ -29,6 +29,7 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/slab.h>
+#include <linux/jiffies.h>
 #include <linux/i2c.h>
 #include <linux/i2c-sensor.h>
 
@@ -81,8 +82,6 @@
 	.detach_client	= lm77_detach_client,
 };
 
-static int lm77_id;
-
 /* straight from the datasheet */
 #define LM77_TEMP_MIN (-55000)
 #define LM77_TEMP_MAX 125000
@@ -295,8 +294,6 @@
 
 	/* Fill in the remaining client fields and put it into the global list */
 	strlcpy(new_client->name, name, I2C_NAME_SIZE);
-
-	new_client->id = lm77_id++;
 	data->valid = 0;
 	init_MUTEX(&data->update_lock);
 
@@ -364,8 +361,8 @@
 
 	down(&data->update_lock);
 
-	if ((jiffies - data->last_updated > HZ + HZ / 2) ||
-	    (jiffies < data->last_updated) || !data->valid) {
+	if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
+	    || !data->valid) {
 		dev_dbg(&client->dev, "Starting lm77 update\n");
 		data->temp_input =
 			LM77_TEMP_FROM_REG(lm77_read_value(client,
diff -Nru a/drivers/i2c/chips/lm78.c b/drivers/i2c/chips/lm78.c
--- a/drivers/i2c/chips/lm78.c	2005-03-11 12:51:51 -08:00
+++ b/drivers/i2c/chips/lm78.c	2005-03-11 12:51:51 -08:00
@@ -22,6 +22,7 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/slab.h>
+#include <linux/jiffies.h>
 #include <linux/i2c.h>
 #include <linux/i2c-sensor.h>
 #include <asm/io.h>
@@ -81,9 +82,8 @@
 
 static inline u8 FAN_TO_REG(long rpm, int div)
 {
-	if (rpm == 0)
+	if (rpm <= 0)
 		return 255;
-	rpm = SENSORS_LIMIT(rpm, 1, 1000000);
 	return SENSORS_LIMIT((1350000 + rpm * div / 2) / (rpm * div), 1, 254);
 }
 
@@ -94,15 +94,15 @@
 
 /* TEMP: mC (-128C to +127C)
    REG: 1C/bit, two's complement */
-static inline u8 TEMP_TO_REG(int val)
+static inline s8 TEMP_TO_REG(int val)
 {
 	int nval = SENSORS_LIMIT(val, -128000, 127000) ;
-	return nval<0 ? (nval-500)/1000+0x100 : (nval+500)/1000;
+	return nval<0 ? (nval-500)/1000 : (nval+500)/1000;
 }
 
-static inline int TEMP_FROM_REG(u8 val)
+static inline int TEMP_FROM_REG(s8 val)
 {
-	return (val>=0x80 ? val-0x100 : val) * 1000;
+	return val * 1000;
 }
 
 /* VID: mV
@@ -112,16 +112,6 @@
 	return val==0x1f ? 0 : val>=0x10 ? 5100-val*100 : 2050-val*50;
 }
 
-/* ALARMS: chip-specific bitmask
-   REG: (same) */
-#define ALARMS_FROM_REG(val) (val)
-
-/* FAN DIV: 1, 2, 4, or 8 (defaults to 2)
-   REG: 0, 1, 2, or 3 (respectively) (defaults to 1) */
-static inline u8 DIV_TO_REG(int val)
-{
-	return val==8 ? 3 : val==4 ? 2 : val==1 ? 0 : 1;
-}
 #define DIV_FROM_REG(val) (1 << (val))
 
 /* There are some complications in a module like this. First off, LM78 chips
@@ -157,9 +147,9 @@
 	u8 in_min[7];		/* Register value */
 	u8 fan[3];		/* Register value */
 	u8 fan_min[3];		/* Register value */
-	u8 temp;		/* Register value */
-	u8 temp_over;		/* Register value */
-	u8 temp_hyst;		/* Register value */
+	s8 temp;		/* Register value */
+	s8 temp_over;		/* Register value */
+	s8 temp_hyst;		/* Register value */
 	u8 fan_div[3];		/* Register encoding, shifted right */
 	u8 vid;			/* Register encoding, combined */
 	u16 alarms;		/* Register encoding, combined */
@@ -357,7 +347,17 @@
 			DIV_FROM_REG(data->fan_div[nr]));
 	unsigned long val = simple_strtoul(buf, NULL, 10);
 	int reg = lm78_read_value(client, LM78_REG_VID_FANDIV);
-	data->fan_div[nr] = DIV_TO_REG(val);
+	switch (val) {
+	case 1: data->fan_div[nr] = 0; break;
+	case 2: data->fan_div[nr] = 1; break;
+	case 4: data->fan_div[nr] = 2; break;
+	case 8: data->fan_div[nr] = 3; break;
+	default:
+		dev_err(&client->dev, "fan_div value %ld not "
+			"supported. Choose one of 1, 2, 4 or 8!\n", val);
+		return -EINVAL;
+	}
+
 	switch (nr) {
 	case 0:
 		reg = (reg & 0xcf) | (data->fan_div[nr] << 4);
@@ -430,7 +430,7 @@
 static ssize_t show_alarms(struct device *dev, char *buf)
 {
 	struct lm78_data *data = lm78_update_device(dev);
-	return sprintf(buf, "%d\n", ALARMS_FROM_REG(data->alarms));
+	return sprintf(buf, "%u\n", data->alarms);
 }
 static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
 
@@ -633,17 +633,15 @@
 {
 	int err;
 
-	/* release ISA region first */
-	if(i2c_is_isa_client(client))
-		release_region(client->addr, LM78_EXTENT);
-
-	/* now it's safe to scrap the rest */
 	if ((err = i2c_detach_client(client))) {
 		dev_err(&client->dev,
 		    "Client deregistration failed, client not detached.\n");
 		return err;
 	}
 
+	if(i2c_is_isa_client(client))
+		release_region(client->addr, LM78_EXTENT);
+
 	kfree(i2c_get_clientdata(client));
 
 	return 0;
@@ -653,9 +651,7 @@
    We don't want to lock the whole ISA bus, so we lock each client
    separately.
    We ignore the LM78 BUSY flag at this moment - it could lead to deadlocks,
-   would slow down the LM78 access and should not be necessary. 
-   There are some ugly typecasts here, but the good new is - they should
-   nowhere else be necessary! */
+   would slow down the LM78 access and should not be necessary.  */
 static int lm78_read_value(struct i2c_client *client, u8 reg)
 {
 	int res;
@@ -709,8 +705,8 @@
 
 	down(&data->update_lock);
 
-	if ((jiffies - data->last_updated > HZ + HZ / 2) ||
-	    (jiffies < data->last_updated) || !data->valid) {
+	if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
+	    || !data->valid) {
 
 		dev_dbg(&client->dev, "Starting lm78 update\n");
 
diff -Nru a/drivers/i2c/chips/lm80.c b/drivers/i2c/chips/lm80.c
--- a/drivers/i2c/chips/lm80.c	2005-03-11 12:51:41 -08:00
+++ b/drivers/i2c/chips/lm80.c	2005-03-11 12:51:41 -08:00
@@ -25,6 +25,7 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/slab.h>
+#include <linux/jiffies.h>
 #include <linux/i2c.h>
 #include <linux/i2c-sensor.h>
 
@@ -99,10 +100,7 @@
 #define TEMP_LIMIT_TO_REG(val)		SENSORS_LIMIT((val)<0?\
 					((val)-500)/1000:((val)+500)/1000,0,255)
 
-#define ALARMS_FROM_REG(val)		(val)
-
 #define DIV_FROM_REG(val)		(1 << (val))
-#define DIV_TO_REG(val)			((val)==8?3:(val)==4?2:(val)==1?0:1)
 
 /*
  * Client data (each client gets its own)
@@ -141,12 +139,6 @@
 static int lm80_write_value(struct i2c_client *client, u8 reg, u8 value);
 
 /*
- * Internal variables
- */
-
-static int lm80_id;
-
-/*
  * Driver data (common to all clients)
  */
 
@@ -269,7 +261,17 @@
 			   DIV_FROM_REG(data->fan_div[nr]));
 
 	val = simple_strtoul(buf, NULL, 10);
-	data->fan_div[nr] = DIV_TO_REG(val);
+
+	switch (val) {
+	case 1: data->fan_div[nr] = 0; break;
+	case 2: data->fan_div[nr] = 1; break;
+	case 4: data->fan_div[nr] = 2; break;
+	case 8: data->fan_div[nr] = 3; break;
+	default:
+		dev_err(&client->dev, "fan_div value %ld not "
+			"supported. Choose one of 1, 2, 4 or 8!\n", val);
+		return -EINVAL;
+	}
 
 	reg = (lm80_read_value(client, LM80_REG_FANDIV) & ~(3 << (2 * (nr + 1))))
 	    | (data->fan_div[nr] << (2 * (nr + 1)));
@@ -327,7 +329,7 @@
 static ssize_t show_alarms(struct device *dev, char *buf)
 {
 	struct lm80_data *data = lm80_update_device(dev);
-	return sprintf(buf, "%d\n", ALARMS_FROM_REG(data->alarms));
+	return sprintf(buf, "%u\n", data->alarms);
 }
 
 static DEVICE_ATTR(in0_min, S_IWUSR | S_IRUGO, show_in_min0, set_in_min0);
@@ -425,8 +427,6 @@
 
 	/* Fill in the remaining client fields and put it into the global list */
 	strlcpy(new_client->name, name, I2C_NAME_SIZE);
-
-	new_client->id = lm80_id++;
 	data->valid = 0;
 	init_MUTEX(&data->update_lock);
 
@@ -530,9 +530,7 @@
 
 	down(&data->update_lock);
 
-	if ((jiffies - data->last_updated > 2 * HZ) ||
-	    (jiffies < data->last_updated) || !data->valid) {
-
+	if (time_after(jiffies, data->last_updated + 2 * HZ) || !data->valid) {
 		dev_dbg(&client->dev, "Starting lm80 update\n");
 		for (i = 0; i <= 6; i++) {
 			data->in[i] =
diff -Nru a/drivers/i2c/chips/lm83.c b/drivers/i2c/chips/lm83.c
--- a/drivers/i2c/chips/lm83.c	2005-03-11 12:51:42 -08:00
+++ b/drivers/i2c/chips/lm83.c	2005-03-11 12:51:42 -08:00
@@ -31,6 +31,7 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/slab.h>
+#include <linux/jiffies.h>
 #include <linux/i2c.h>
 #include <linux/i2c-sensor.h>
 
@@ -150,12 +151,6 @@
 };
 
 /*
- * Internal variables
- */
-
-static int lm83_id;
-
-/*
  * Sysfs stuff
  */
 
@@ -312,7 +307,6 @@
 
 	/* We can fill in the remaining client fields */
 	strlcpy(new_client->name, name, I2C_NAME_SIZE);
-	new_client->id = lm83_id++;
 	data->valid = 0;
 	init_MUTEX(&data->update_lock);
 
@@ -369,9 +363,7 @@
 
 	down(&data->update_lock);
 
-	if ((jiffies - data->last_updated > HZ * 2) ||
-	    (jiffies < data->last_updated) ||
-	    !data->valid) {
+	if (time_after(jiffies, data->last_updated + HZ * 2) || !data->valid) {
 		int nr;
 
 		dev_dbg(&client->dev, "Updating lm83 data.\n");
diff -Nru a/drivers/i2c/chips/lm85.c b/drivers/i2c/chips/lm85.c
--- a/drivers/i2c/chips/lm85.c	2005-03-11 12:51:42 -08:00
+++ b/drivers/i2c/chips/lm85.c	2005-03-11 12:51:42 -08:00
@@ -27,6 +27,7 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/slab.h>
+#include <linux/jiffies.h>
 #include <linux/i2c.h>
 #include <linux/i2c-sensor.h>
 #include <linux/i2c-vid.h>
@@ -389,9 +390,6 @@
 	.detach_client  = lm85_detach_client,
 };
 
-/* Unique ID assigned to each LM85 detected */
-static int lm85_id;
-
 
 /* 4 Fans */
 static ssize_t show_fan(struct device *dev, char *buf, int nr)
@@ -1148,16 +1146,10 @@
 	strlcpy(new_client->name, type_name, I2C_NAME_SIZE);
 
 	/* Fill in the remaining client fields */
-	new_client->id = lm85_id++;
 	data->type = kind;
 	data->valid = 0;
 	init_MUTEX(&data->update_lock);
 
-	dev_dbg(&adapter->dev, "Assigning ID %d to %s at %d,0x%02x\n",
-		new_client->id, new_client->name,
-		i2c_adapter_id(new_client->adapter),
-		new_client->addr);
-
 	/* Tell the I2C layer a new client has arrived */
 	if ((err = i2c_attach_client(new_client)))
 		goto ERROR1;
@@ -1363,7 +1355,7 @@
 	down(&data->update_lock);
 
 	if ( !data->valid ||
-	     (jiffies - data->last_reading > LM85_DATA_INTERVAL ) ) {
+	     time_after(jiffies, data->last_reading + LM85_DATA_INTERVAL) ) {
 		/* Things that change quickly */
 		dev_dbg(&client->dev, "Reading sensor values\n");
 		
@@ -1417,7 +1409,7 @@
 	};  /* last_reading */
 
 	if ( !data->valid ||
-	     (jiffies - data->last_config > LM85_CONFIG_INTERVAL) ) {
+	     time_after(jiffies, data->last_config + LM85_CONFIG_INTERVAL) ) {
 		/* Things that don't change often */
 		dev_dbg(&client->dev, "Reading config values\n");
 
diff -Nru a/drivers/i2c/chips/lm87.c b/drivers/i2c/chips/lm87.c
--- a/drivers/i2c/chips/lm87.c	2005-03-11 12:51:51 -08:00
+++ b/drivers/i2c/chips/lm87.c	2005-03-11 12:51:51 -08:00
@@ -56,6 +56,7 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/slab.h>
+#include <linux/jiffies.h>
 #include <linux/i2c.h>
 #include <linux/i2c-sensor.h>
 #include <linux/i2c-vid.h>
@@ -203,12 +204,6 @@
 };
 
 /*
- * Internal variables
- */
-
-static int lm87_id;
-
-/*
  * Sysfs stuff
  */
 
@@ -569,7 +564,6 @@
 
 	/* We can fill in the remaining client fields */
 	strlcpy(new_client->name, "lm87", I2C_NAME_SIZE);
-	new_client->id = lm87_id++;
 	data->valid = 0;
 	init_MUTEX(&data->update_lock);
 
@@ -720,9 +714,7 @@
 
 	down(&data->update_lock);
 
-	if (jiffies - data->last_updated > HZ
-	  || jiffies < data->last_updated
-	  || !data->valid) {
+	if (time_after(jiffies, data->last_updated + HZ) || !data->valid) {
 		int i, j;
 
 		dev_dbg(&client->dev, "Updating data.\n");
diff -Nru a/drivers/i2c/chips/lm90.c b/drivers/i2c/chips/lm90.c
--- a/drivers/i2c/chips/lm90.c	2005-03-11 12:51:41 -08:00
+++ b/drivers/i2c/chips/lm90.c	2005-03-11 12:51:41 -08:00
@@ -66,6 +66,7 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/slab.h>
+#include <linux/jiffies.h>
 #include <linux/i2c.h>
 #include <linux/i2c-sensor.h>
 
@@ -190,12 +191,6 @@
 };
 
 /*
- * Internal variables
- */
-
-static int lm90_id;
-
-/*
  * Sysfs stuff
  */
 
@@ -427,7 +422,6 @@
 
 	/* We can fill in the remaining client fields */
 	strlcpy(new_client->name, name, I2C_NAME_SIZE);
-	new_client->id = lm90_id++;
 	data->valid = 0;
 	init_MUTEX(&data->update_lock);
 
@@ -495,9 +489,7 @@
 
 	down(&data->update_lock);
 
-	if ((jiffies - data->last_updated > HZ * 2) ||
-	    (jiffies < data->last_updated) ||
-	    !data->valid) {
+	if (time_after(jiffies, data->last_updated + HZ * 2) || !data->valid) {
 		u8 oldh, newh;
 
 		dev_dbg(&client->dev, "Updating lm90 data.\n");
diff -Nru a/drivers/i2c/chips/m41t00.c b/drivers/i2c/chips/m41t00.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/i2c/chips/m41t00.c	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,247 @@
+/*
+ * drivers/i2c/chips/m41t00.c
+ *
+ * I2C client/driver for the ST M41T00 Real-Time Clock chip.
+ *
+ * Author: Mark A. Greer <mgreer@mvista.com>
+ *
+ * 2005 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+/*
+ * This i2c client/driver wedges between the drivers/char/genrtc.c RTC
+ * interface and the SMBus interface of the i2c subsystem.
+ * It would be more efficient to use i2c msgs/i2c_transfer directly but, as
+ * recommened in .../Documentation/i2c/writing-clients section
+ * "Sending and receiving", using SMBus level communication is preferred.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/i2c.h>
+#include <linux/rtc.h>
+#include <linux/bcd.h>
+
+#include <asm/time.h>
+#include <asm/rtc.h>
+
+#define	M41T00_DRV_NAME		"m41t00"
+
+static DECLARE_MUTEX(m41t00_mutex);
+
+static struct i2c_driver m41t00_driver;
+static struct i2c_client *save_client;
+
+static unsigned short ignore[] = { I2C_CLIENT_END };
+static unsigned short normal_addr[] = { 0x68, I2C_CLIENT_END };
+
+static struct i2c_client_address_data addr_data = {
+	.normal_i2c		= normal_addr,
+	.normal_i2c_range	= ignore,
+	.probe			= ignore,
+	.probe_range		= ignore,
+	.ignore			= ignore,
+	.ignore_range		= ignore,
+	.force			= ignore,
+};
+
+ulong
+m41t00_get_rtc_time(void)
+{
+	s32	sec, min, hour, day, mon, year;
+	s32	sec1, min1, hour1, day1, mon1, year1;
+	ulong	limit = 10;
+
+	sec = min = hour = day = mon = year = 0;
+	sec1 = min1 = hour1 = day1 = mon1 = year1 = 0;
+
+	down(&m41t00_mutex);
+	do {
+		if (((sec = i2c_smbus_read_byte_data(save_client, 0)) >= 0)
+			&& ((min = i2c_smbus_read_byte_data(save_client, 1))
+				>= 0)
+			&& ((hour = i2c_smbus_read_byte_data(save_client, 2))
+				>= 0)
+			&& ((day = i2c_smbus_read_byte_data(save_client, 4))
+				>= 0)
+			&& ((mon = i2c_smbus_read_byte_data(save_client, 5))
+				>= 0)
+			&& ((year = i2c_smbus_read_byte_data(save_client, 6))
+				>= 0)
+			&& ((sec == sec1) && (min == min1) && (hour == hour1)
+				&& (day == day1) && (mon == mon1)
+				&& (year == year1)))
+
+				break;
+
+		sec1 = sec;
+		min1 = min;
+		hour1 = hour;
+		day1 = day;
+		mon1 = mon;
+		year1 = year;
+	} while (--limit > 0);
+	up(&m41t00_mutex);
+
+	if (limit == 0) {
+		dev_warn(&save_client->dev,
+			"m41t00: can't read rtc chip\n");
+		sec = min = hour = day = mon = year = 0;
+	}
+
+	sec &= 0x7f;
+	min &= 0x7f;
+	hour &= 0x3f;
+	day &= 0x3f;
+	mon &= 0x1f;
+	year &= 0xff;
+
+	BCD_TO_BIN(sec);
+	BCD_TO_BIN(min);
+	BCD_TO_BIN(hour);
+	BCD_TO_BIN(day);
+	BCD_TO_BIN(mon);
+	BCD_TO_BIN(year);
+
+	year += 1900;
+	if (year < 1970)
+		year += 100;
+
+	return mktime(year, mon, day, hour, min, sec);
+}
+
+static void
+m41t00_set_tlet(ulong arg)
+{
+	struct rtc_time	tm;
+	ulong	nowtime = *(ulong *)arg;
+
+	to_tm(nowtime, &tm);
+	tm.tm_year = (tm.tm_year - 1900) % 100;
+
+	BIN_TO_BCD(tm.tm_sec);
+	BIN_TO_BCD(tm.tm_min);
+	BIN_TO_BCD(tm.tm_hour);
+	BIN_TO_BCD(tm.tm_mon);
+	BIN_TO_BCD(tm.tm_mday);
+	BIN_TO_BCD(tm.tm_year);
+
+	down(&m41t00_mutex);
+	if ((i2c_smbus_write_byte_data(save_client, 0, tm.tm_sec & 0x7f) < 0)
+		|| (i2c_smbus_write_byte_data(save_client, 1, tm.tm_min & 0x7f)
+			< 0)
+		|| (i2c_smbus_write_byte_data(save_client, 2, tm.tm_hour & 0x7f)
+			< 0)
+		|| (i2c_smbus_write_byte_data(save_client, 4, tm.tm_mday & 0x7f)
+			< 0)
+		|| (i2c_smbus_write_byte_data(save_client, 5, tm.tm_mon & 0x7f)
+			< 0)
+		|| (i2c_smbus_write_byte_data(save_client, 6, tm.tm_year & 0x7f)
+			< 0))
+
+		dev_warn(&save_client->dev,"m41t00: can't write to rtc chip\n");
+
+	up(&m41t00_mutex);
+	return;
+}
+
+ulong	new_time;
+
+DECLARE_TASKLET_DISABLED(m41t00_tasklet, m41t00_set_tlet, (ulong)&new_time);
+
+int
+m41t00_set_rtc_time(ulong nowtime)
+{
+	new_time = nowtime;
+
+	if (in_interrupt())
+		tasklet_schedule(&m41t00_tasklet);
+	else
+		m41t00_set_tlet((ulong)&new_time);
+
+	return 0;
+}
+
+/*
+ *****************************************************************************
+ *
+ *	Driver Interface
+ *
+ *****************************************************************************
+ */
+static int
+m41t00_probe(struct i2c_adapter *adap, int addr, int kind)
+{
+	struct i2c_client *client;
+	int rc;
+
+	client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
+	if (!client)
+		return -ENOMEM;
+
+	memset(client, 0, sizeof(struct i2c_client));
+	strncpy(client->name, M41T00_DRV_NAME, I2C_NAME_SIZE);
+	client->id = m41t00_driver.id;
+	client->flags = I2C_DF_NOTIFY;
+	client->addr = addr;
+	client->adapter = adap;
+	client->driver = &m41t00_driver;
+
+	if ((rc = i2c_attach_client(client)) != 0) {
+		kfree(client);
+		return rc;
+	}
+
+	save_client = client;
+	return 0;
+}
+
+static int
+m41t00_attach(struct i2c_adapter *adap)
+{
+	return i2c_probe(adap, &addr_data, m41t00_probe);
+}
+
+static int
+m41t00_detach(struct i2c_client *client)
+{
+	int	rc;
+
+	if ((rc = i2c_detach_client(client)) == 0) {
+		kfree(i2c_get_clientdata(client));
+		tasklet_kill(&m41t00_tasklet);
+	}
+	return rc;
+}
+
+static struct i2c_driver m41t00_driver = {
+	.owner		= THIS_MODULE,
+	.name		= M41T00_DRV_NAME,
+	.id		= I2C_DRIVERID_STM41T00,
+	.flags		= I2C_DF_NOTIFY,
+	.attach_adapter	= m41t00_attach,
+	.detach_client	= m41t00_detach,
+};
+
+static int __init
+m41t00_init(void)
+{
+	return i2c_add_driver(&m41t00_driver);
+}
+
+static void __exit
+m41t00_exit(void)
+{
+	i2c_del_driver(&m41t00_driver);
+	return;
+}
+
+module_init(m41t00_init);
+module_exit(m41t00_exit);
+
+MODULE_AUTHOR("Mark A. Greer <mgreer@mvista.com>");
+MODULE_DESCRIPTION("ST Microelectronics M41T00 RTC I2C Client Driver");
+MODULE_LICENSE("GPL");
diff -Nru a/drivers/i2c/chips/max1619.c b/drivers/i2c/chips/max1619.c
--- a/drivers/i2c/chips/max1619.c	2005-03-11 12:51:51 -08:00
+++ b/drivers/i2c/chips/max1619.c	2005-03-11 12:51:51 -08:00
@@ -30,6 +30,7 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/slab.h>
+#include <linux/jiffies.h>
 #include <linux/i2c.h>
 #include <linux/i2c-sensor.h>
 
@@ -117,12 +118,6 @@
 };
 
 /*
- * Internal variables
- */
-
-static int max1619_id;
-
-/*
  * Sysfs stuff
  */
 
@@ -267,7 +262,6 @@
 
 	/* We can fill in the remaining client fields */
 	strlcpy(new_client->name, name, I2C_NAME_SIZE);
-	new_client->id = max1619_id++;
 	data->valid = 0;
 	init_MUTEX(&data->update_lock);
 
@@ -331,10 +325,7 @@
 
 	down(&data->update_lock);
 
-	if ((jiffies - data->last_updated > HZ * 2) ||
-	    (jiffies < data->last_updated) ||
-	    !data->valid) {
-		
+	if (time_after(jiffies, data->last_updated + HZ * 2) || !data->valid) {
 		dev_dbg(&client->dev, "Updating max1619 data.\n");
 		data->temp_input1 = i2c_smbus_read_byte_data(client,
 					MAX1619_REG_R_LOCAL_TEMP);
diff -Nru a/drivers/i2c/chips/pc87360.c b/drivers/i2c/chips/pc87360.c
--- a/drivers/i2c/chips/pc87360.c	2005-03-11 12:51:42 -08:00
+++ b/drivers/i2c/chips/pc87360.c	2005-03-11 12:51:42 -08:00
@@ -37,6 +37,7 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/slab.h>
+#include <linux/jiffies.h>
 #include <linux/i2c.h>
 #include <linux/i2c-sensor.h>
 #include <linux/i2c-vid.h>
@@ -1174,8 +1175,7 @@
 
 	down(&data->update_lock);
 
-	if ((jiffies - data->last_updated > HZ * 2)
-	 || (jiffies < data->last_updated) || !data->valid) {
+	if (time_after(jiffies, data->last_updated + HZ * 2) || !data->valid) {
 		dev_dbg(&client->dev, "Data update\n");
 
 		/* Fans */
diff -Nru a/drivers/i2c/chips/pcf8574.c b/drivers/i2c/chips/pcf8574.c
--- a/drivers/i2c/chips/pcf8574.c	2005-03-11 12:51:41 -08:00
+++ b/drivers/i2c/chips/pcf8574.c	2005-03-11 12:51:41 -08:00
@@ -77,8 +77,6 @@
 	.detach_client	= pcf8574_detach_client,
 };
 
-static int pcf8574_id;
-
 /* following are the sysfs callback functions */
 static ssize_t show_read(struct device *dev, char *buf)
 {
@@ -159,8 +157,6 @@
 
 	/* Fill in the remaining client fields and put it into the global list */
 	strlcpy(new_client->name, client_name, I2C_NAME_SIZE);
-
-	new_client->id = pcf8574_id++;
 	init_MUTEX(&data->update_lock);
 
 	/* Tell the I2C layer a new client has arrived */
diff -Nru a/drivers/i2c/chips/pcf8591.c b/drivers/i2c/chips/pcf8591.c
--- a/drivers/i2c/chips/pcf8591.c	2005-03-11 12:51:52 -08:00
+++ b/drivers/i2c/chips/pcf8591.c	2005-03-11 12:51:52 -08:00
@@ -98,8 +98,6 @@
 	.detach_client	= pcf8591_detach_client,
 };
 
-static int pcf8591_id;
-
 /* following are the sysfs callback functions */
 #define show_in_channel(channel)					\
 static ssize_t show_in##channel##_input(struct device *dev, char *buf)	\
@@ -201,8 +199,6 @@
 	/* Fill in the remaining client fields and put it into the global 
 	   list */
 	strlcpy(new_client->name, "pcf8591", I2C_NAME_SIZE);
-
-	new_client->id = pcf8591_id++;
 	init_MUTEX(&data->update_lock);
 
 	/* Tell the I2C layer a new client has arrived */
diff -Nru a/drivers/i2c/chips/rtc8564.c b/drivers/i2c/chips/rtc8564.c
--- a/drivers/i2c/chips/rtc8564.c	2005-03-11 12:51:40 -08:00
+++ b/drivers/i2c/chips/rtc8564.c	2005-03-11 12:51:40 -08:00
@@ -89,7 +89,7 @@
 
 	_DBG(1, "client=%p, adr=%d, buf=%p, len=%d", client, adr, buf, len);
 
-	if (!buf || !client) {
+	if (!buf) {
 		ret = -EINVAL;
 		goto done;
 	}
@@ -111,7 +111,7 @@
 	struct i2c_msg wr;
 	int i;
 
-	if (!client || !data || len > 15) {
+	if (!data || len > 15) {
 		ret = -EINVAL;
 		goto done;
 	}
@@ -163,14 +163,12 @@
 
 	strlcpy(new_client->name, "RTC8564", I2C_NAME_SIZE);
 	i2c_set_clientdata(new_client, d);
-	new_client->id = rtc8564_driver.id;
 	new_client->flags = I2C_CLIENT_ALLOW_USE | I2C_DF_NOTIFY;
 	new_client->addr = addr;
 	new_client->adapter = adap;
 	new_client->driver = &rtc8564_driver;
 
 	_DBG(1, "client=%p", new_client);
-	_DBG(1, "client.id=%d", new_client->id);
 
 	/* init ctrl1 reg */
 	data[0] = 0;
@@ -222,7 +220,7 @@
 
 	_DBG(1, "client=%p, dt=%p", client, dt);
 
-	if (!dt || !client)
+	if (!dt)
 		return -EINVAL;
 
 	memset(buf, 0, sizeof(buf));
@@ -256,7 +254,7 @@
 
 	_DBG(1, "client=%p, dt=%p", client, dt);
 
-	if (!dt || !client)
+	if (!dt)
 		return -EINVAL;
 
 	_DBGRTCTM(2, *dt);
@@ -295,7 +293,7 @@
 {
 	struct rtc8564_data *data = i2c_get_clientdata(client);
 
-	if (!ctrl || !client)
+	if (!ctrl)
 		return -1;
 
 	*ctrl = data->ctrl;
@@ -307,7 +305,7 @@
 	struct rtc8564_data *data = i2c_get_clientdata(client);
 	unsigned char buf[2];
 
-	if (!ctrl || !client)
+	if (!ctrl)
 		return -1;
 
 	buf[0] = *ctrl & 0xff;
@@ -320,7 +318,7 @@
 static int rtc8564_read_mem(struct i2c_client *client, struct mem *mem)
 {
 
-	if (!mem || !client)
+	if (!mem)
 		return -EINVAL;
 
 	return rtc8564_read(client, mem->loc, mem->data, mem->nr);
@@ -329,7 +327,7 @@
 static int rtc8564_write_mem(struct i2c_client *client, struct mem *mem)
 {
 
-	if (!mem || !client)
+	if (!mem)
 		return -EINVAL;
 
 	return rtc8564_write(client, mem->loc, mem->data, mem->nr);
diff -Nru a/drivers/i2c/chips/sis5595.c b/drivers/i2c/chips/sis5595.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/i2c/chips/sis5595.c	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,794 @@
+/*
+    sis5595.c - Part of lm_sensors, Linux kernel modules
+		for hardware monitoring
+
+    Copyright (C) 1998 - 2001 Frodo Looijaard <frodol@dds.nl>,
+			Kyösti Mälkki <kmalkki@cc.hut.fi>, and
+			Mark D. Studebaker <mdsxyz123@yahoo.com>
+    Ported to Linux 2.6 by Aurelien Jarno <aurelien@aurel32.net> with
+    the help of Jean Delvare <khali@linux-fr.org>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+/*
+   SiS southbridge has a LM78-like chip integrated on the same IC.
+   This driver is a customized copy of lm78.c
+   
+   Supports following revisions:
+	Version		PCI ID		PCI Revision
+	1		1039/0008	AF or less
+	2		1039/0008	B0 or greater
+
+   Note: these chips contain a 0008 device which is incompatible with the
+	 5595. We recognize these by the presence of the listed
+	 "blacklist" PCI ID and refuse to load.
+
+   NOT SUPPORTED	PCI ID		BLACKLIST PCI ID	
+	 540		0008		0540
+	 550		0008		0550
+	5513		0008		5511
+	5581		0008		5597
+	5582		0008		5597
+	5597		0008		5597
+	5598		0008		5597/5598
+	 630		0008		0630
+	 645		0008		0645
+	 730		0008		0730
+	 735		0008		0735
+*/
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/ioport.h>
+#include <linux/pci.h>
+#include <linux/i2c.h>
+#include <linux/i2c-sensor.h>
+#include <linux/init.h>
+#include <asm/io.h>
+
+
+/* If force_addr is set to anything different from 0, we forcibly enable
+   the device at the given address. */
+static u16 force_addr;
+module_param(force_addr, ushort, 0);
+MODULE_PARM_DESC(force_addr,
+		 "Initialize the base address of the sensors");
+
+/* Addresses to scan.
+   Note that we can't determine the ISA address until we have initialized
+   our module */
+static unsigned short normal_i2c[] = { I2C_CLIENT_END };
+static unsigned int normal_isa[] = { 0x0000, I2C_CLIENT_ISA_END };
+
+/* Insmod parameters */
+SENSORS_INSMOD_1(sis5595);
+
+/* Many SIS5595 constants specified below */
+
+/* Length of ISA address segment */
+#define SIS5595_EXTENT 8
+/* PCI Config Registers */
+#define SIS5595_REVISION_REG 0x08
+#define SIS5595_BASE_REG 0x68
+#define SIS5595_PIN_REG 0x7A
+#define SIS5595_ENABLE_REG 0x7B
+
+/* Where are the ISA address/data registers relative to the base address */
+#define SIS5595_ADDR_REG_OFFSET 5
+#define SIS5595_DATA_REG_OFFSET 6
+
+/* The SIS5595 registers */
+#define SIS5595_REG_IN_MAX(nr) (0x2b + (nr) * 2)
+#define SIS5595_REG_IN_MIN(nr) (0x2c + (nr) * 2)
+#define SIS5595_REG_IN(nr) (0x20 + (nr))
+
+#define SIS5595_REG_FAN_MIN(nr) (0x3b + (nr))
+#define SIS5595_REG_FAN(nr) (0x28 + (nr))
+
+/* On the first version of the chip, the temp registers are separate.
+   On the second version,
+   TEMP pin is shared with IN4, configured in PCI register 0x7A.
+   The registers are the same as well.
+   OVER and HYST are really MAX and MIN. */
+
+#define REV2MIN	0xb0
+#define SIS5595_REG_TEMP 	(( data->revision) >= REV2MIN) ? \
+					SIS5595_REG_IN(4) : 0x27
+#define SIS5595_REG_TEMP_OVER	(( data->revision) >= REV2MIN) ? \
+					SIS5595_REG_IN_MAX(4) : 0x39
+#define SIS5595_REG_TEMP_HYST	(( data->revision) >= REV2MIN) ? \
+					SIS5595_REG_IN_MIN(4) : 0x3a
+
+#define SIS5595_REG_CONFIG 0x40
+#define SIS5595_REG_ALARM1 0x41
+#define SIS5595_REG_ALARM2 0x42
+#define SIS5595_REG_FANDIV 0x47
+
+/* Conversions. Limit checking is only done on the TO_REG
+   variants. */
+
+/* IN: mV, (0V to 4.08V)
+   REG: 16mV/bit */
+static inline u8 IN_TO_REG(unsigned long val)
+{
+	unsigned long nval = SENSORS_LIMIT(val, 0, 4080);
+	return (nval + 8) / 16;
+}
+#define IN_FROM_REG(val) ((val) *  16)
+
+static inline u8 FAN_TO_REG(long rpm, int div)
+{
+	if (rpm <= 0)
+		return 255;
+	return SENSORS_LIMIT((1350000 + rpm * div / 2) / (rpm * div), 1, 254);
+}
+
+static inline int FAN_FROM_REG(u8 val, int div)
+{
+	return val==0 ? -1 : val==255 ? 0 : 1350000/(val*div);
+}
+
+/* TEMP: mC (-54.12C to +157.53C)
+   REG: 0.83C/bit + 52.12, two's complement  */
+static inline int TEMP_FROM_REG(s8 val)
+{
+	return val * 830 + 52120;
+}
+static inline s8 TEMP_TO_REG(int val)
+{
+	int nval = SENSORS_LIMIT(val, -54120, 157530) ;
+	return nval<0 ? (nval-5212-415)/830 : (nval-5212+415)/830;
+}
+
+/* FAN DIV: 1, 2, 4, or 8 (defaults to 2)
+   REG: 0, 1, 2, or 3 (respectively) (defaults to 1) */
+static inline u8 DIV_TO_REG(int val)
+{
+	return val==8 ? 3 : val==4 ? 2 : val==1 ? 0 : 1;
+}
+#define DIV_FROM_REG(val) (1 << (val))
+
+/* For the SIS5595, we need to keep some data in memory. That
+   data is pointed to by sis5595_list[NR]->data. The structure itself is
+   dynamically allocated, at the time when the new sis5595 client is
+   allocated. */
+struct sis5595_data {
+	struct i2c_client client;
+	struct semaphore lock;
+
+	struct semaphore update_lock;
+	char valid;		/* !=0 if following fields are valid */
+	unsigned long last_updated;	/* In jiffies */
+	char maxins;		/* == 3 if temp enabled, otherwise == 4 */
+	u8 revision;		/* Reg. value */
+
+	u8 in[5];		/* Register value */
+	u8 in_max[5];		/* Register value */
+	u8 in_min[5];		/* Register value */
+	u8 fan[2];		/* Register value */
+	u8 fan_min[2];		/* Register value */
+	s8 temp;		/* Register value */
+	s8 temp_over;		/* Register value */
+	s8 temp_hyst;		/* Register value */
+	u8 fan_div[2];		/* Register encoding, shifted right */
+	u16 alarms;		/* Register encoding, combined */
+};
+
+static struct pci_dev *s_bridge;	/* pointer to the (only) sis5595 */
+
+static int sis5595_attach_adapter(struct i2c_adapter *adapter);
+static int sis5595_detect(struct i2c_adapter *adapter, int address, int kind);
+static int sis5595_detach_client(struct i2c_client *client);
+
+static int sis5595_read_value(struct i2c_client *client, u8 register);
+static int sis5595_write_value(struct i2c_client *client, u8 register, u8 value);
+static struct sis5595_data *sis5595_update_device(struct device *dev);
+static void sis5595_init_client(struct i2c_client *client);
+
+static struct i2c_driver sis5595_driver = {
+	.owner		= THIS_MODULE,
+	.name		= "sis5595",
+	.id		= I2C_DRIVERID_SIS5595,
+	.flags		= I2C_DF_NOTIFY,
+	.attach_adapter	= sis5595_attach_adapter,
+	.detach_client	= sis5595_detach_client,
+};
+
+/* 4 Voltages */
+static ssize_t show_in(struct device *dev, char *buf, int nr)
+{
+	struct sis5595_data *data = sis5595_update_device(dev);
+	return sprintf(buf, "%d\n", IN_FROM_REG(data->in[nr]));
+}
+
+static ssize_t show_in_min(struct device *dev, char *buf, int nr)
+{
+	struct sis5595_data *data = sis5595_update_device(dev);
+	return sprintf(buf, "%d\n", IN_FROM_REG(data->in_min[nr]));
+}
+
+static ssize_t show_in_max(struct device *dev, char *buf, int nr)
+{
+	struct sis5595_data *data = sis5595_update_device(dev);
+	return sprintf(buf, "%d\n", IN_FROM_REG(data->in_max[nr]));
+}
+
+static ssize_t set_in_min(struct device *dev, const char *buf,
+	       size_t count, int nr)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct sis5595_data *data = i2c_get_clientdata(client);
+	unsigned long val = simple_strtoul(buf, NULL, 10);
+	data->in_min[nr] = IN_TO_REG(val);
+	sis5595_write_value(client, SIS5595_REG_IN_MIN(nr), data->in_min[nr]);
+	return count;
+}
+
+static ssize_t set_in_max(struct device *dev, const char *buf,
+	       size_t count, int nr)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct sis5595_data *data = i2c_get_clientdata(client);
+	unsigned long val = simple_strtoul(buf, NULL, 10);
+	data->in_max[nr] = IN_TO_REG(val);
+	sis5595_write_value(client, SIS5595_REG_IN_MAX(nr), data->in_max[nr]);
+	return count;
+}
+
+#define show_in_offset(offset)					\
+static ssize_t							\
+	show_in##offset (struct device *dev, char *buf)		\
+{								\
+	return show_in(dev, buf, offset);			\
+}								\
+static DEVICE_ATTR(in##offset##_input, S_IRUGO, 		\
+		show_in##offset, NULL);				\
+static ssize_t							\
+	show_in##offset##_min (struct device *dev, char *buf)	\
+{								\
+	return show_in_min(dev, buf, offset);			\
+}								\
+static ssize_t							\
+	show_in##offset##_max (struct device *dev, char *buf)	\
+{								\
+	return show_in_max(dev, buf, offset);			\
+}								\
+static ssize_t set_in##offset##_min (struct device *dev,	\
+		const char *buf, size_t count)			\
+{								\
+	return set_in_min(dev, buf, count, offset);		\
+}								\
+static ssize_t set_in##offset##_max (struct device *dev,	\
+		const char *buf, size_t count)			\
+{								\
+	return set_in_max(dev, buf, count, offset);		\
+}								\
+static DEVICE_ATTR(in##offset##_min, S_IRUGO | S_IWUSR,		\
+		show_in##offset##_min, set_in##offset##_min);	\
+static DEVICE_ATTR(in##offset##_max, S_IRUGO | S_IWUSR,		\
+		show_in##offset##_max, set_in##offset##_max);
+
+show_in_offset(0);
+show_in_offset(1);
+show_in_offset(2);
+show_in_offset(3);
+show_in_offset(4);
+
+/* Temperature */
+static ssize_t show_temp(struct device *dev, char *buf)
+{
+	struct sis5595_data *data = sis5595_update_device(dev);
+	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp));
+}
+
+static ssize_t show_temp_over(struct device *dev, char *buf)
+{
+	struct sis5595_data *data = sis5595_update_device(dev);
+	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_over));
+}
+
+static ssize_t set_temp_over(struct device *dev, const char *buf, size_t count)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct sis5595_data *data = i2c_get_clientdata(client);
+	long val = simple_strtol(buf, NULL, 10);
+	data->temp_over = TEMP_TO_REG(val);
+	sis5595_write_value(client, SIS5595_REG_TEMP_OVER, data->temp_over);
+	return count;
+}
+
+static ssize_t show_temp_hyst(struct device *dev, char *buf)
+{
+	struct sis5595_data *data = sis5595_update_device(dev);
+	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_hyst));
+}
+
+static ssize_t set_temp_hyst(struct device *dev, const char *buf, size_t count)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct sis5595_data *data = i2c_get_clientdata(client);
+	long val = simple_strtol(buf, NULL, 10);
+	data->temp_hyst = TEMP_TO_REG(val);
+	sis5595_write_value(client, SIS5595_REG_TEMP_HYST, data->temp_hyst);
+	return count;
+}
+
+static DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL);
+static DEVICE_ATTR(temp1_max, S_IRUGO | S_IWUSR,
+		show_temp_over, set_temp_over);
+static DEVICE_ATTR(temp1_max_hyst, S_IRUGO | S_IWUSR,
+		show_temp_hyst, set_temp_hyst);
+
+/* 2 Fans */
+static ssize_t show_fan(struct device *dev, char *buf, int nr)
+{
+	struct sis5595_data *data = sis5595_update_device(dev);
+	return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan[nr],
+		DIV_FROM_REG(data->fan_div[nr])) );
+}
+
+static ssize_t show_fan_min(struct device *dev, char *buf, int nr)
+{
+	struct sis5595_data *data = sis5595_update_device(dev);
+	return sprintf(buf,"%d\n", FAN_FROM_REG(data->fan_min[nr],
+		DIV_FROM_REG(data->fan_div[nr])) );
+}
+
+static ssize_t set_fan_min(struct device *dev, const char *buf,
+		size_t count, int nr)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct sis5595_data *data = i2c_get_clientdata(client);
+	unsigned long val = simple_strtoul(buf, NULL, 10);
+	data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr]));
+	sis5595_write_value(client, SIS5595_REG_FAN_MIN(nr), data->fan_min[nr]);
+	return count;
+}
+
+static ssize_t show_fan_div(struct device *dev, char *buf, int nr)
+{
+	struct sis5595_data *data = sis5595_update_device(dev);
+	return sprintf(buf, "%d\n", DIV_FROM_REG(data->fan_div[nr]) );
+}
+
+/* Note: we save and restore the fan minimum here, because its value is
+   determined in part by the fan divisor.  This follows the principle of
+   least suprise; the user doesn't expect the fan minimum to change just
+   because the divisor changed. */
+static ssize_t set_fan_div(struct device *dev, const char *buf,
+	size_t count, int nr)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct sis5595_data *data = i2c_get_clientdata(client);
+	unsigned long min = FAN_FROM_REG(data->fan_min[nr],
+			DIV_FROM_REG(data->fan_div[nr]));
+	unsigned long val = simple_strtoul(buf, NULL, 10);
+	int reg = sis5595_read_value(client, SIS5595_REG_FANDIV);
+	switch (val) {
+	case 1: data->fan_div[nr] = 0; break;
+	case 2: data->fan_div[nr] = 1; break;
+	case 4: data->fan_div[nr] = 2; break;
+	case 8: data->fan_div[nr] = 3; break;
+	default:
+		dev_err(&client->dev, "fan_div value %ld not "
+			"supported. Choose one of 1, 2, 4 or 8!\n", val);
+		return -EINVAL;
+	}
+	
+	switch (nr) {
+	case 0:
+		reg = (reg & 0xcf) | (data->fan_div[nr] << 4);
+		break;
+	case 1:
+		reg = (reg & 0x3f) | (data->fan_div[nr] << 6);
+		break;
+	}
+	sis5595_write_value(client, SIS5595_REG_FANDIV, reg);
+	data->fan_min[nr] =
+		FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[nr]));
+	sis5595_write_value(client, SIS5595_REG_FAN_MIN(nr), data->fan_min[nr]);
+	return count;
+}
+
+#define show_fan_offset(offset)						\
+static ssize_t show_fan_##offset (struct device *dev, char *buf)	\
+{									\
+	return show_fan(dev, buf, offset - 1);			\
+}									\
+static ssize_t show_fan_##offset##_min (struct device *dev, char *buf)	\
+{									\
+	return show_fan_min(dev, buf, offset - 1);			\
+}									\
+static ssize_t show_fan_##offset##_div (struct device *dev, char *buf)	\
+{									\
+	return show_fan_div(dev, buf, offset - 1);			\
+}									\
+static ssize_t set_fan_##offset##_min (struct device *dev,		\
+		const char *buf, size_t count)				\
+{									\
+	return set_fan_min(dev, buf, count, offset - 1);		\
+}									\
+static DEVICE_ATTR(fan##offset##_input, S_IRUGO, show_fan_##offset, NULL);\
+static DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR,		\
+		show_fan_##offset##_min, set_fan_##offset##_min);
+
+show_fan_offset(1);
+show_fan_offset(2);
+
+static ssize_t set_fan_1_div(struct device *dev, const char *buf,
+		size_t count)
+{
+	return set_fan_div(dev, buf, count, 0) ;
+}
+
+static ssize_t set_fan_2_div(struct device *dev, const char *buf,
+		size_t count)
+{
+	return set_fan_div(dev, buf, count, 1) ;
+}
+static DEVICE_ATTR(fan1_div, S_IRUGO | S_IWUSR,
+		show_fan_1_div, set_fan_1_div);
+static DEVICE_ATTR(fan2_div, S_IRUGO | S_IWUSR,
+		show_fan_2_div, set_fan_2_div);
+
+/* Alarms */
+static ssize_t show_alarms(struct device *dev, char *buf)
+{
+	struct sis5595_data *data = sis5595_update_device(dev);
+	return sprintf(buf, "%d\n", data->alarms);
+}
+static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
+ 
+/* This is called when the module is loaded */
+static int sis5595_attach_adapter(struct i2c_adapter *adapter)
+{
+	if (!(adapter->class & I2C_CLASS_HWMON))
+		return 0;
+	return i2c_detect(adapter, &addr_data, sis5595_detect);
+}
+
+int sis5595_detect(struct i2c_adapter *adapter, int address, int kind)
+{
+	int err = 0;
+	int i;
+	struct i2c_client *new_client;
+	struct sis5595_data *data;
+	char val;
+	u16 a;
+
+	/* Make sure we are probing the ISA bus!!  */
+	if (!i2c_is_isa_adapter(adapter))
+		goto exit;
+
+	if (force_addr)
+		address = force_addr & ~(SIS5595_EXTENT - 1);
+	/* Reserve the ISA region */
+	if (!request_region(address, SIS5595_EXTENT, sis5595_driver.name)) {
+		err = -EBUSY;
+		goto exit;
+	}
+	if (force_addr) {
+		dev_warn(&adapter->dev, "forcing ISA address 0x%04X\n", address);
+		if (PCIBIOS_SUCCESSFUL !=
+		    pci_write_config_word(s_bridge, SIS5595_BASE_REG, address))
+			goto exit_release;
+		if (PCIBIOS_SUCCESSFUL !=
+		    pci_read_config_word(s_bridge, SIS5595_BASE_REG, &a))
+			goto exit_release;
+		if ((a & ~(SIS5595_EXTENT - 1)) != address)
+			/* doesn't work for some chips? */
+			goto exit_release;
+	}
+
+	if (PCIBIOS_SUCCESSFUL !=
+	    pci_read_config_byte(s_bridge, SIS5595_ENABLE_REG, &val)) {
+		goto exit_release;
+	}
+	if ((val & 0x80) == 0) {
+		if (PCIBIOS_SUCCESSFUL !=
+		    pci_write_config_byte(s_bridge, SIS5595_ENABLE_REG,
+					  val | 0x80))
+			goto exit_release;
+		if (PCIBIOS_SUCCESSFUL !=
+		    pci_read_config_byte(s_bridge, SIS5595_ENABLE_REG, &val))
+			goto exit_release;
+		if ((val & 0x80) == 0) 
+			/* doesn't work for some chips! */
+			goto exit_release;
+	}
+
+	if (!(data = kmalloc(sizeof(struct sis5595_data), GFP_KERNEL))) {
+		err = -ENOMEM;
+		goto exit_release;
+	}
+	memset(data, 0, sizeof(struct sis5595_data));
+
+	new_client = &data->client;
+	new_client->addr = address;
+	init_MUTEX(&data->lock);
+	i2c_set_clientdata(new_client, data);
+	new_client->adapter = adapter;
+	new_client->driver = &sis5595_driver;
+	new_client->flags = 0;
+
+	/* Check revision and pin registers to determine whether 4 or 5 voltages */
+	pci_read_config_byte(s_bridge, SIS5595_REVISION_REG, &(data->revision));
+	/* 4 voltages, 1 temp */
+	data->maxins = 3;
+	if (data->revision >= REV2MIN) {
+		pci_read_config_byte(s_bridge, SIS5595_PIN_REG, &val);
+		if (!(val & 0x80))
+			/* 5 voltages, no temps */
+			data->maxins = 4;
+	}
+	
+	/* Fill in the remaining client fields and put it into the global list */
+	strlcpy(new_client->name, "sis5595", I2C_NAME_SIZE);
+
+	data->valid = 0;
+	init_MUTEX(&data->update_lock);
+
+	/* Tell the I2C layer a new client has arrived */
+	if ((err = i2c_attach_client(new_client)))
+		goto exit_free;
+	
+	/* Initialize the SIS5595 chip */
+	sis5595_init_client(new_client);
+
+	/* A few vars need to be filled upon startup */
+	for (i = 0; i < 2; i++) {
+		data->fan_min[i] = sis5595_read_value(new_client,
+					SIS5595_REG_FAN_MIN(i));
+	}
+
+	/* Register sysfs hooks */
+	device_create_file(&new_client->dev, &dev_attr_in0_input);
+	device_create_file(&new_client->dev, &dev_attr_in0_min);
+	device_create_file(&new_client->dev, &dev_attr_in0_max);
+	device_create_file(&new_client->dev, &dev_attr_in1_input);
+	device_create_file(&new_client->dev, &dev_attr_in1_min);
+	device_create_file(&new_client->dev, &dev_attr_in1_max);
+	device_create_file(&new_client->dev, &dev_attr_in2_input);
+	device_create_file(&new_client->dev, &dev_attr_in2_min);
+	device_create_file(&new_client->dev, &dev_attr_in2_max);
+	device_create_file(&new_client->dev, &dev_attr_in3_input);
+	device_create_file(&new_client->dev, &dev_attr_in3_min);
+	device_create_file(&new_client->dev, &dev_attr_in3_max);
+	if (data->maxins == 4) {
+		device_create_file(&new_client->dev, &dev_attr_in4_input);
+		device_create_file(&new_client->dev, &dev_attr_in4_min);
+		device_create_file(&new_client->dev, &dev_attr_in4_max);
+	}
+	device_create_file(&new_client->dev, &dev_attr_fan1_input);
+	device_create_file(&new_client->dev, &dev_attr_fan1_min);
+	device_create_file(&new_client->dev, &dev_attr_fan1_div);
+	device_create_file(&new_client->dev, &dev_attr_fan2_input);
+	device_create_file(&new_client->dev, &dev_attr_fan2_min);
+	device_create_file(&new_client->dev, &dev_attr_fan2_div);
+	device_create_file(&new_client->dev, &dev_attr_alarms);
+	if (data->maxins == 3) {
+		device_create_file(&new_client->dev, &dev_attr_temp1_input);
+		device_create_file(&new_client->dev, &dev_attr_temp1_max);
+		device_create_file(&new_client->dev, &dev_attr_temp1_max_hyst);
+	}
+	return 0;
+	
+exit_free:
+	kfree(data);
+exit_release:
+	release_region(address, SIS5595_EXTENT);
+exit:
+	return err;
+}
+
+static int sis5595_detach_client(struct i2c_client *client)
+{
+	int err;
+
+	if ((err = i2c_detach_client(client))) {
+		dev_err(&client->dev,
+		    "Client deregistration failed, client not detached.\n");
+		return err;
+	}
+
+	if (i2c_is_isa_client(client))
+		release_region(client->addr, SIS5595_EXTENT);
+
+	kfree(i2c_get_clientdata(client));
+
+	return 0;
+}
+
+
+/* ISA access must be locked explicitly. */
+static int sis5595_read_value(struct i2c_client *client, u8 reg)
+{
+	int res;
+
+	struct sis5595_data *data = i2c_get_clientdata(client);
+	down(&data->lock);
+	outb_p(reg, client->addr + SIS5595_ADDR_REG_OFFSET);
+	res = inb_p(client->addr + SIS5595_DATA_REG_OFFSET);
+	up(&data->lock);
+	return res;
+}
+
+static int sis5595_write_value(struct i2c_client *client, u8 reg, u8 value)
+{
+	struct sis5595_data *data = i2c_get_clientdata(client);
+	down(&data->lock);
+	outb_p(reg, client->addr + SIS5595_ADDR_REG_OFFSET);
+	outb_p(value, client->addr + SIS5595_DATA_REG_OFFSET);
+	up(&data->lock);
+	return 0;
+}
+
+/* Called when we have found a new SIS5595. */
+static void sis5595_init_client(struct i2c_client *client)
+{
+	u8 config = sis5595_read_value(client, SIS5595_REG_CONFIG);
+	if (!(config & 0x01))
+		sis5595_write_value(client, SIS5595_REG_CONFIG,
+				(config & 0xf7) | 0x01);
+}
+
+static struct sis5595_data *sis5595_update_device(struct device *dev)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct sis5595_data *data = i2c_get_clientdata(client);
+	int i;
+
+	down(&data->update_lock);
+
+	if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
+	    || !data->valid) {
+
+		for (i = 0; i <= data->maxins; i++) {
+			data->in[i] =
+			    sis5595_read_value(client, SIS5595_REG_IN(i));
+			data->in_min[i] =
+			    sis5595_read_value(client,
+					       SIS5595_REG_IN_MIN(i));
+			data->in_max[i] =
+			    sis5595_read_value(client,
+					       SIS5595_REG_IN_MAX(i));
+		}
+		for (i = 0; i < 2; i++) {
+			data->fan[i] =
+			    sis5595_read_value(client, SIS5595_REG_FAN(i));
+			data->fan_min[i] =
+			    sis5595_read_value(client,
+					       SIS5595_REG_FAN_MIN(i));
+		}
+		if (data->maxins == 3) {
+			data->temp =
+			    sis5595_read_value(client, SIS5595_REG_TEMP);
+			data->temp_over =
+			    sis5595_read_value(client, SIS5595_REG_TEMP_OVER);
+			data->temp_hyst =
+			    sis5595_read_value(client, SIS5595_REG_TEMP_HYST);
+		}
+		i = sis5595_read_value(client, SIS5595_REG_FANDIV);
+		data->fan_div[0] = (i >> 4) & 0x03;
+		data->fan_div[1] = i >> 6;
+		data->alarms =
+		    sis5595_read_value(client, SIS5595_REG_ALARM1) |
+		    (sis5595_read_value(client, SIS5595_REG_ALARM2) << 8);
+		data->last_updated = jiffies;
+		data->valid = 1;
+	}
+
+	up(&data->update_lock);
+
+	return data;
+}
+
+static struct pci_device_id sis5595_pci_ids[] = {
+	{ PCI_DEVICE(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_503) },
+	{ 0, }
+};
+
+MODULE_DEVICE_TABLE(pci, sis5595_pci_ids);
+
+static int blacklist[] __devinitdata = {
+	PCI_DEVICE_ID_SI_540,
+	PCI_DEVICE_ID_SI_550,
+	PCI_DEVICE_ID_SI_630,
+	PCI_DEVICE_ID_SI_645,
+	PCI_DEVICE_ID_SI_730,
+	PCI_DEVICE_ID_SI_735,
+	PCI_DEVICE_ID_SI_5511, /* 5513 chip has the 0008 device but
+				  that ID shows up in other chips so we
+				  use the 5511 ID for recognition */
+	PCI_DEVICE_ID_SI_5597,
+	PCI_DEVICE_ID_SI_5598,
+	0 };
+
+static int __devinit sis5595_pci_probe(struct pci_dev *dev,
+				       const struct pci_device_id *id)
+{
+	u16 val;
+	int *i;
+	int addr = 0;
+
+	for (i = blacklist; *i != 0; i++) {
+		struct pci_dev *dev;
+		dev = pci_get_device(PCI_VENDOR_ID_SI, *i, NULL);
+		if (dev) {
+			dev_err(&dev->dev, "Looked for SIS5595 but found unsupported device %.4x\n", *i);
+			pci_dev_put(dev);
+			return -ENODEV;
+		}
+	}
+	
+	if (PCIBIOS_SUCCESSFUL !=
+	    pci_read_config_word(dev, SIS5595_BASE_REG, &val))
+		return -ENODEV;
+	
+	addr = val & ~(SIS5595_EXTENT - 1);
+	if (addr == 0 && force_addr == 0) {
+		dev_err(&dev->dev, "Base address not set - upgrade BIOS or use force_addr=0xaddr\n");
+		return -ENODEV;
+	}
+	if (force_addr)
+		addr = force_addr;	/* so detect will get called */
+
+	if (!addr) {
+		dev_err(&dev->dev,"No SiS 5595 sensors found.\n");
+		return -ENODEV;
+	}
+	normal_isa[0] = addr;
+
+	s_bridge = pci_dev_get(dev);
+	if (i2c_add_driver(&sis5595_driver)) {
+		pci_dev_put(s_bridge);
+		s_bridge = NULL;
+	}
+
+	/* Always return failure here.  This is to allow other drivers to bind
+	 * to this pci device.  We don't really want to have control over the
+	 * pci device, we only wanted to read as few register values from it.
+	 */
+	return -ENODEV;
+}
+
+static struct pci_driver sis5595_pci_driver = {
+	.name            = "sis5595",
+	.id_table        = sis5595_pci_ids,
+	.probe           = sis5595_pci_probe,
+};
+
+static int __init sm_sis5595_init(void)
+{
+	return pci_register_driver(&sis5595_pci_driver);
+}
+
+static void __exit sm_sis5595_exit(void)
+{
+	pci_unregister_driver(&sis5595_pci_driver);
+	if (s_bridge != NULL) {
+		i2c_del_driver(&sis5595_driver);
+		pci_dev_put(s_bridge);
+		s_bridge = NULL;
+	}
+}
+
+MODULE_AUTHOR("Aurelien Jarno <aurelien@aurel32.net>");
+MODULE_DESCRIPTION("SiS 5595 Sensor device");
+MODULE_LICENSE("GPL");
+
+module_init(sm_sis5595_init);
+module_exit(sm_sis5595_exit);
diff -Nru a/drivers/i2c/chips/smsc47b397.c b/drivers/i2c/chips/smsc47b397.c
--- a/drivers/i2c/chips/smsc47b397.c	2005-03-11 12:51:52 -08:00
+++ b/drivers/i2c/chips/smsc47b397.c	2005-03-11 12:51:52 -08:00
@@ -29,6 +29,7 @@
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/ioport.h>
+#include <linux/jiffies.h>
 #include <linux/i2c.h>
 #include <linux/i2c-sensor.h>
 #include <linux/init.h>
@@ -130,9 +131,7 @@
 
 	down(&data->update_lock);
 
-	if (time_after(jiffies - data->last_updated, (unsigned long)HZ)
-		|| time_before(jiffies, data->last_updated) || !data->valid) {
-
+	if (time_after(jiffies, data->last_updated + HZ) || !data->valid) {
 		dev_dbg(&client->dev, "starting device update...\n");
 
 		/* 4 temperature inputs, 4 fan inputs */
diff -Nru a/drivers/i2c/chips/smsc47m1.c b/drivers/i2c/chips/smsc47m1.c
--- a/drivers/i2c/chips/smsc47m1.c	2005-03-11 12:51:42 -08:00
+++ b/drivers/i2c/chips/smsc47m1.c	2005-03-11 12:51:42 -08:00
@@ -28,6 +28,7 @@
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/ioport.h>
+#include <linux/jiffies.h>
 #include <linux/i2c.h>
 #include <linux/i2c-sensor.h>
 #include <linux/init.h>
@@ -108,7 +109,6 @@
 struct smsc47m1_data {
 	struct i2c_client client;
 	struct semaphore lock;
-	int sysctl_id;
 
 	struct semaphore update_lock;
 	unsigned long last_updated;	/* In jiffies */
@@ -133,8 +133,6 @@
 		int init);
 
 
-static int smsc47m1_id;
-
 static struct i2c_driver smsc47m1_driver = {
 	.owner		= THIS_MODULE,
 	.name		= "smsc47m1",
@@ -420,8 +418,6 @@
 	new_client->flags = 0;
 
 	strlcpy(new_client->name, "smsc47m1", I2C_NAME_SIZE);
-
-	new_client->id = smsc47m1_id++;
 	init_MUTEX(&data->update_lock);
 
 	/* If no function is properly configured, there's no point in
@@ -532,8 +528,7 @@
 
 	down(&data->update_lock);
 
-	if ((jiffies - data->last_updated > HZ + HZ / 2) ||
-	    (jiffies < data->last_updated) || init) {
+	if (time_after(jiffies, data->last_updated + HZ + HZ / 2) || init) {
 		int i;
 
 		for (i = 0; i < 2; i++) {
diff -Nru a/drivers/i2c/chips/via686a.c b/drivers/i2c/chips/via686a.c
--- a/drivers/i2c/chips/via686a.c	2005-03-11 12:51:41 -08:00
+++ b/drivers/i2c/chips/via686a.c	2005-03-11 12:51:41 -08:00
@@ -35,6 +35,7 @@
 #include <linux/slab.h>
 #include <linux/pci.h>
 #include <linux/delay.h>
+#include <linux/jiffies.h>
 #include <linux/i2c.h>
 #include <linux/i2c-sensor.h>
 #include <linux/init.h>
@@ -726,9 +727,8 @@
 
 	down(&data->update_lock);
 
-       if ((jiffies - data->last_updated > HZ + HZ / 2) ||
-           (jiffies < data->last_updated) || !data->valid) {
-
+	if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
+	    || !data->valid) {
 		for (i = 0; i <= 4; i++) {
 			data->in[i] =
 			    via686a_read_value(client, VIA686A_REG_IN(i));
diff -Nru a/drivers/i2c/chips/w83627hf.c b/drivers/i2c/chips/w83627hf.c
--- a/drivers/i2c/chips/w83627hf.c	2005-03-11 12:51:47 -08:00
+++ b/drivers/i2c/chips/w83627hf.c	2005-03-11 12:51:47 -08:00
@@ -40,6 +40,7 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/slab.h>
+#include <linux/jiffies.h>
 #include <linux/i2c.h>
 #include <linux/i2c-sensor.h>
 #include <linux/i2c-vid.h>
@@ -1321,6 +1322,27 @@
 	data->pwmenable[2] = 1;
 
 	if(init) {
+		/* Enable temp2 */
+		tmp = w83627hf_read_value(client, W83781D_REG_TEMP2_CONFIG);
+		if (tmp & 0x01) {
+			dev_warn(&client->dev, "Enabling temp2, readings "
+				 "might not make sense\n");
+			w83627hf_write_value(client, W83781D_REG_TEMP2_CONFIG,
+				tmp & 0xfe);
+		}
+
+		/* Enable temp3 */
+		if (type != w83697hf) {
+			tmp = w83627hf_read_value(client,
+				W83781D_REG_TEMP3_CONFIG);
+			if (tmp & 0x01) {
+				dev_warn(&client->dev, "Enabling temp3, "
+					 "readings might not make sense\n");
+				w83627hf_write_value(client,
+					W83781D_REG_TEMP3_CONFIG, tmp & 0xfe);
+			}
+		}
+
 		if (type == w83627hf) {
 			/* enable PWM2 control (can't hurt since PWM reg
 		           should have been reset to 0xff) */
@@ -1350,8 +1372,8 @@
 
 	down(&data->update_lock);
 
-	if ((jiffies - data->last_updated > HZ + HZ / 2) ||
-	    (jiffies < data->last_updated) || !data->valid) {
+	if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
+	    || !data->valid) {
 		for (i = 0; i <= 8; i++) {
 			/* skip missing sensors */
 			if (((data->type == w83697hf) && (i == 1)) ||
diff -Nru a/drivers/i2c/chips/w83781d.c b/drivers/i2c/chips/w83781d.c
--- a/drivers/i2c/chips/w83781d.c	2005-03-11 12:51:40 -08:00
+++ b/drivers/i2c/chips/w83781d.c	2005-03-11 12:51:40 -08:00
@@ -39,6 +39,7 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/slab.h>
+#include <linux/jiffies.h>
 #include <linux/i2c.h>
 #include <linux/i2c-sensor.h>
 #include <linux/i2c-vid.h>
@@ -1562,11 +1563,28 @@
 	}
 #endif				/* W83781D_RT */
 
-	if (init) {
+	if (init && type != as99127f) {
+		/* Enable temp2 */
+		tmp = w83781d_read_value(client, W83781D_REG_TEMP2_CONFIG);
+		if (tmp & 0x01) {
+			dev_warn(&client->dev, "Enabling temp2, readings "
+				 "might not make sense\n");
+			w83781d_write_value(client, W83781D_REG_TEMP2_CONFIG,
+				tmp & 0xfe);
+		}
+
+		/* Enable temp3 */
 		if (type != w83783s && type != w83697hf) {
-			w83781d_write_value(client, W83781D_REG_TEMP3_CONFIG,
-					    0x00);
+			tmp = w83781d_read_value(client,
+				W83781D_REG_TEMP3_CONFIG);
+			if (tmp & 0x01) {
+				dev_warn(&client->dev, "Enabling temp3, "
+					 "readings might not make sense\n");
+				w83781d_write_value(client,
+					W83781D_REG_TEMP3_CONFIG, tmp & 0xfe);
+			}
 		}
+
 		if (type != w83781d) {
 			/* enable comparator mode for temp2 and temp3 so
 			   alarm indication will work correctly */
@@ -1592,9 +1610,8 @@
 
 	down(&data->update_lock);
 
-	if (time_after
-	    (jiffies - data->last_updated, (unsigned long) (HZ + HZ / 2))
-	    || time_before(jiffies, data->last_updated) || !data->valid) {
+	if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
+	    || !data->valid) {
 		dev_dbg(dev, "Starting device update\n");
 
 		for (i = 0; i <= 8; i++) {
diff -Nru a/drivers/i2c/chips/w83l785ts.c b/drivers/i2c/chips/w83l785ts.c
--- a/drivers/i2c/chips/w83l785ts.c	2005-03-11 12:51:42 -08:00
+++ b/drivers/i2c/chips/w83l785ts.c	2005-03-11 12:51:42 -08:00
@@ -35,6 +35,7 @@
 #include <linux/delay.h>
 #include <linux/init.h>
 #include <linux/slab.h>
+#include <linux/jiffies.h>
 #include <linux/i2c.h>
 #include <linux/i2c-sensor.h>
 
@@ -114,12 +115,6 @@
 };
 
 /*
- * Internal variables
- */
-
-static int w83l785ts_id = 0;
-
-/*
  * Sysfs stuff
  */
 
@@ -229,7 +224,6 @@
 
 	/* We can fill in the remaining client fields. */
 	strlcpy(new_client->name, "w83l785ts", I2C_NAME_SIZE);
-	new_client->id = w83l785ts_id++;
 	data->valid = 0;
 	init_MUTEX(&data->update_lock);
 
@@ -301,9 +295,7 @@
 
 	down(&data->update_lock);
 
-	if (!data->valid
-	 || (jiffies - data->last_updated > HZ * 2)
-	 || (jiffies < data->last_updated)) {
+	if (!data->valid || time_after(jiffies, data->last_updated + HZ * 2)) {
 		dev_dbg(&client->dev, "Updating w83l785ts data.\n");
 		data->temp = w83l785ts_read_value(client,
 			     W83L785TS_REG_TEMP, data->temp);
diff -Nru a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
--- a/drivers/i2c/i2c-core.c	2005-03-11 12:51:41 -08:00
+++ b/drivers/i2c/i2c-core.c	2005-03-11 12:51:41 -08:00
@@ -38,12 +38,43 @@
 static DECLARE_MUTEX(core_lists);
 static DEFINE_IDR(i2c_adapter_idr);
 
-int i2c_device_probe(struct device *dev)
+/* match always succeeds, as we want the probe() to tell if we really accept this match */
+static int i2c_device_match(struct device *dev, struct device_driver *drv)
+{
+	return 1;
+}
+
+static int i2c_bus_suspend(struct device * dev, pm_message_t state)
+{
+	int rc = 0;
+
+	if (dev->driver && dev->driver->suspend)
+		rc = dev->driver->suspend(dev,state,0);
+	return rc;
+}
+
+static int i2c_bus_resume(struct device * dev)
+{
+	int rc = 0;
+	
+	if (dev->driver && dev->driver->resume)
+		rc = dev->driver->resume(dev,0);
+	return rc;
+}
+
+static struct bus_type i2c_bus_type = {
+	.name =		"i2c",
+	.match =	i2c_device_match,
+	.suspend =      i2c_bus_suspend,
+	.resume =       i2c_bus_resume,
+};
+
+static int i2c_device_probe(struct device *dev)
 {
 	return -ENODEV;
 }
 
-int i2c_device_remove(struct device *dev)
+static int i2c_device_remove(struct device *dev)
 {
 	return 0;
 }
@@ -523,38 +554,6 @@
        up(&adap->clist_lock);
 }
 
-
-/* match always succeeds, as we want the probe() to tell if we really accept this match */
-static int i2c_device_match(struct device *dev, struct device_driver *drv)
-{
-	return 1;
-}
-
-static int i2c_bus_suspend(struct device * dev, u32 state)
-{
-	int rc = 0;
-
-	if (dev->driver && dev->driver->suspend)
-		rc = dev->driver->suspend(dev,state,0);
-	return rc;
-}
-
-static int i2c_bus_resume(struct device * dev)
-{
-	int rc = 0;
-	
-	if (dev->driver && dev->driver->resume)
-		rc = dev->driver->resume(dev,0);
-	return rc;
-}
-
-struct bus_type i2c_bus_type = {
-	.name =		"i2c",
-	.match =	i2c_device_match,
-	.suspend =      i2c_bus_suspend,
-	.resume =       i2c_bus_resume,
-};
-
 static int __init i2c_init(void)
 {
 	int retval;
@@ -583,7 +582,7 @@
  * ----------------------------------------------------
  */
 
-int i2c_transfer(struct i2c_adapter * adap, struct i2c_msg msgs[],int num)
+int i2c_transfer(struct i2c_adapter * adap, struct i2c_msg *msgs, int num)
 {
 	int ret;
 
@@ -860,7 +859,7 @@
 /* CRC over count bytes in the first array plus the bytes in the rest
    array if it is non-null. rest[0] is the (length of rest) - 1
    and is included. */
-u8 i2c_smbus_partial_pec(u8 crc, int count, u8 *first, u8 *rest)
+static u8 i2c_smbus_partial_pec(u8 crc, int count, u8 *first, u8 *rest)
 {
 	int i;
 
@@ -872,7 +871,7 @@
 	return crc;
 }
 
-u8 i2c_smbus_pec(int count, u8 *first, u8 *rest)
+static u8 i2c_smbus_pec(int count, u8 *first, u8 *rest)
 {
 	return i2c_smbus_partial_pec(0, count, first, rest);
 }
@@ -880,8 +879,8 @@
 /* Returns new "size" (transaction type)
    Note that we convert byte to byte_data and byte_data to word_data
    rather than invent new xxx_PEC transactions. */
-int i2c_smbus_add_pec(u16 addr, u8 command, int size,
-                      union i2c_smbus_data *data)
+static int i2c_smbus_add_pec(u16 addr, u8 command, int size,
+			     union i2c_smbus_data *data)
 {
 	u8 buf[3];
 
@@ -910,8 +909,8 @@
 	return size;	
 }
 
-int i2c_smbus_check_pec(u16 addr, u8 command, int size, u8 partial,
-                        union i2c_smbus_data *data)
+static int i2c_smbus_check_pec(u16 addr, u8 command, int size, u8 partial,
+			       union i2c_smbus_data *data)
 {
 	u8 buf[3], rpec, cpec;
 
diff -Nru a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c
--- a/drivers/i2c/i2c-dev.c	2005-03-11 12:51:50 -08:00
+++ b/drivers/i2c/i2c-dev.c	2005-03-11 12:51:50 -08:00
@@ -55,7 +55,7 @@
 static struct i2c_dev *i2c_dev_array[I2C_MINORS];
 static DEFINE_SPINLOCK(i2c_dev_array_lock);
 
-struct i2c_dev *i2c_dev_get_by_minor(unsigned index)
+static struct i2c_dev *i2c_dev_get_by_minor(unsigned index)
 {
 	struct i2c_dev *i2c_dev;
 
@@ -65,7 +65,7 @@
 	return i2c_dev;
 }
 
-struct i2c_dev *i2c_dev_get_by_adapter(struct i2c_adapter *adap)
+static struct i2c_dev *i2c_dev_get_by_adapter(struct i2c_adapter *adap)
 {
 	struct i2c_dev *i2c_dev = NULL;
 
@@ -108,13 +108,6 @@
 	spin_unlock(&i2c_dev_array_lock);
 }
 
-static ssize_t show_dev(struct class_device *class_dev, char *buf)
-{
-	struct i2c_dev *i2c_dev = to_i2c_dev(class_dev);
-	return print_dev_t(buf, MKDEV(I2C_MAJOR, i2c_dev->minor));
-}
-static CLASS_DEVICE_ATTR(dev, S_IRUGO, show_dev, NULL);
-
 static ssize_t show_adapter_name(struct class_device *class_dev, char *buf)
 {
 	struct i2c_dev *i2c_dev = to_i2c_dev(class_dev);
@@ -173,8 +166,8 @@
 	return ret;
 }
 
-int i2cdev_ioctl (struct inode *inode, struct file *file, unsigned int cmd, 
-                  unsigned long arg)
+static int i2cdev_ioctl(struct inode *inode, struct file *file,
+		unsigned int cmd, unsigned long arg)
 {
 	struct i2c_client *client = (struct i2c_client *)file->private_data;
 	struct i2c_rdwr_ioctl_data rdwr_arg;
@@ -451,11 +444,11 @@
 	else
 		i2c_dev->class_dev.dev = adap->dev.parent;
 	i2c_dev->class_dev.class = &i2c_dev_class;
+	i2c_dev->class_dev.devt = MKDEV(I2C_MAJOR, i2c_dev->minor);
 	snprintf(i2c_dev->class_dev.class_id, BUS_ID_SIZE, "i2c-%d", i2c_dev->minor);
 	retval = class_device_register(&i2c_dev->class_dev);
 	if (retval)
 		goto error;
-	class_device_create_file(&i2c_dev->class_dev, &class_device_attr_dev);
 	class_device_create_file(&i2c_dev->class_dev, &class_device_attr_name);
 	return 0;
 error:
@@ -507,7 +500,6 @@
 
 static struct i2c_client i2cdev_client_template = {
 	.name		= "I2C /dev entry",
-	.id		= 1,
 	.addr		= -1,
 	.driver		= &i2cdev_driver,
 };
diff -Nru a/drivers/i2c/i2c-sensor-detect.c b/drivers/i2c/i2c-sensor-detect.c
--- a/drivers/i2c/i2c-sensor-detect.c	2005-03-11 12:51:46 -08:00
+++ b/drivers/i2c/i2c-sensor-detect.c	2005-03-11 12:51:46 -08:00
@@ -19,17 +19,10 @@
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/ctype.h>
-#include <linux/sysctl.h>
-#include <linux/init.h>
-#include <linux/ioport.h>
 #include <linux/i2c.h>
 #include <linux/i2c-sensor.h>
-#include <asm/uaccess.h>
 
 static unsigned short empty[] = {I2C_CLIENT_END};
 static unsigned int empty_isa[] = {I2C_CLIENT_ISA_END};
diff -Nru a/drivers/ide/Kconfig b/drivers/ide/Kconfig
--- a/drivers/ide/Kconfig	2005-03-11 12:51:46 -08:00
+++ b/drivers/ide/Kconfig	2005-03-11 12:51:46 -08:00
@@ -150,7 +150,6 @@
 
 config IDEDISK_MULTI_MODE
 	bool "Use multi-mode by default"
-	depends on BLK_DEV_IDEDISK
 	help
 	  If you get this error, try to say Y here:
 
diff -Nru a/drivers/ide/arm/icside.c b/drivers/ide/arm/icside.c
--- a/drivers/ide/arm/icside.c	2005-03-11 12:51:46 -08:00
+++ b/drivers/ide/arm/icside.c	2005-03-11 12:51:46 -08:00
@@ -713,7 +713,7 @@
 icside_probe(struct expansion_card *ec, const struct ecard_id *id)
 {
 	struct icside_state *state;
-	void *idmem;
+	void __iomem *idmem;
 	int ret;
 
 	ret = ecard_request_resources(ec);
diff -Nru a/drivers/ide/arm/rapide.c b/drivers/ide/arm/rapide.c
--- a/drivers/ide/arm/rapide.c	2005-03-11 12:51:50 -08:00
+++ b/drivers/ide/arm/rapide.c	2005-03-11 12:51:50 -08:00
@@ -17,7 +17,7 @@
  * Something like this really should be in generic code, but isn't.
  */
 static ide_hwif_t *
-rapide_locate_hwif(void __iomem *base, void *ctrl, unsigned int sz, int irq)
+rapide_locate_hwif(void __iomem *base, void __iomem *ctrl, unsigned int sz, int irq)
 {
 	unsigned long port = (unsigned long)base;
 	ide_hwif_t *hwif;
diff -Nru a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c
--- a/drivers/ide/ide-cd.c	2005-03-11 12:51:43 -08:00
+++ b/drivers/ide/ide-cd.c	2005-03-11 12:51:43 -08:00
@@ -3088,7 +3088,6 @@
 		drive->queue->unplug_delay = 1;
 
 	drive->special.all	= 0;
-	drive->ready_stat	= 0;
 
 	CDROM_STATE_FLAGS(drive)->media_changed = 1;
 	CDROM_STATE_FLAGS(drive)->toc_valid     = 0;
@@ -3252,45 +3251,25 @@
 
 static int ide_cdrom_attach (ide_drive_t *drive);
 
-/*
- * Power Management state machine.
- *
- * We don't do much for CDs right now.
- */
-
-static void ide_cdrom_complete_power_step (ide_drive_t *drive, struct request *rq, u8 stat, u8 error)
+#ifdef CONFIG_PROC_FS
+static int proc_idecd_read_capacity
+	(char *page, char **start, off_t off, int count, int *eof, void *data)
 {
-}
-
-static ide_startstop_t ide_cdrom_start_power_step (ide_drive_t *drive, struct request *rq)
-{
-	ide_task_t *args = rq->special;
-
-	memset(args, 0, sizeof(*args));
+	ide_drive_t*drive = (ide_drive_t *)data;
+	int len;
 
-	switch (rq->pm->pm_step) {
-	case ide_pm_state_start_suspend:
-		break;
-
-	case ide_pm_state_start_resume:	/* Resume step 1 (restore DMA) */
-		/*
-		 * Right now, all we do is call hwif->ide_dma_check(drive),
-		 * we could be smarter and check for current xfer_speed
-		 * in struct drive etc...
-		 * Also, this step could be implemented as a generic helper
-		 * as most subdrivers will use it.
-		 */
-		if ((drive->id->capability & 1) == 0)
-			break;
-		if (HWIF(drive)->ide_dma_check == NULL)
-			break;
-		HWIF(drive)->ide_dma_check(drive);
-		break;
-	}
-	rq->pm->pm_step = ide_pm_state_completed;
-	return ide_stopped;
+	len = sprintf(page,"%llu\n", (long long)ide_cdrom_capacity(drive));
+	PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
 }
 
+static ide_proc_entry_t idecd_proc[] = {
+	{ "capacity", S_IFREG|S_IRUGO, proc_idecd_read_capacity, NULL },
+	{ NULL, 0, NULL, NULL }
+};
+#else
+# define idecd_proc	NULL
+#endif
+
 static ide_driver_t ide_cdrom_driver = {
 	.owner			= THIS_MODULE,
 	.name			= "ide-cdrom",
@@ -3300,11 +3279,12 @@
 	.supports_dsc_overlap	= 1,
 	.cleanup		= ide_cdrom_cleanup,
 	.do_request		= ide_do_rw_cdrom,
-	.capacity		= ide_cdrom_capacity,
+	.end_request		= ide_end_request,
+	.error			= __ide_error,
+	.abort			= __ide_abort,
+	.proc			= idecd_proc,
 	.attach			= ide_cdrom_attach,
 	.drives			= LIST_HEAD_INIT(ide_cdrom_driver.drives),
-	.start_power_step	= ide_cdrom_start_power_step,
-	.complete_power_step	= ide_cdrom_complete_power_step,
 };
 
 static int idecd_open(struct inode * inode, struct file * file)
diff -Nru a/drivers/ide/ide-default.c b/drivers/ide/ide-default.c
--- a/drivers/ide/ide-default.c	2005-03-11 12:51:51 -08:00
+++ b/drivers/ide/ide-default.c	2005-03-11 12:51:51 -08:00
@@ -38,6 +38,12 @@
 
 static int idedefault_attach(ide_drive_t *drive);
 
+static ide_startstop_t idedefault_do_request(ide_drive_t *drive, struct request *rq, sector_t block)
+{
+	ide_end_request(drive, 0, 0);
+	return ide_stopped;
+}
+
 /*
  *	IDE subdriver functions, registered with ide.c
  */
@@ -47,6 +53,10 @@
 	.version	=	IDEDEFAULT_VERSION,
 	.attach		=	idedefault_attach,
 	.cleanup	=	ide_unregister_subdriver,
+	.do_request	=	idedefault_do_request,
+	.end_request	=	ide_end_request,
+	.error		=	__ide_error,
+	.abort		=	__ide_abort,
 	.drives		=	LIST_HEAD_INIT(idedefault_driver.drives)
 };
 
@@ -57,13 +67,6 @@
 			"driver with ide.c\n", drive->name);
 		return 1;
 	}
-	
-	/* For the sake of the request layer, we must make sure we have a
-	 * correct ready_stat value, that is 0 for ATAPI devices or we will
-	 * fail any request like Power Management
-	 */
-	if (drive->media != ide_disk)
-		drive->ready_stat = 0;
 
 	return 0;
 }
diff -Nru a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c
--- a/drivers/ide/ide-disk.c	2005-03-11 12:51:42 -08:00
+++ b/drivers/ide/ide-disk.c	2005-03-11 12:51:42 -08:00
@@ -133,6 +133,8 @@
 	if (hwif->no_lba48_dma && lba48 && dma) {
 		if (block + rq->nr_sectors > 1ULL << 28)
 			dma = 0;
+		else
+			lba48 = 0;
 	}
 
 	if (!dma) {
@@ -146,7 +148,7 @@
 	/* FIXME: SELECT_MASK(drive, 0) ? */
 
 	if (drive->select.b.lba) {
-		if (drive->addressing == 1) {
+		if (lba48) {
 			task_ioreg_t tasklets[10];
 
 			pr_debug("%s: LBA=0x%012llx\n", drive->name, block);
@@ -514,75 +516,6 @@
 	return drive->capacity64 - drive->sect0;
 }
 
-#define IS_PDC4030_DRIVE	0
-
-static ide_startstop_t idedisk_special (ide_drive_t *drive)
-{
-	special_t *s = &drive->special;
-
-	if (s->b.set_geometry) {
-		s->b.set_geometry	= 0;
-		if (!IS_PDC4030_DRIVE) {
-			ide_task_t args;
-			memset(&args, 0, sizeof(ide_task_t));
-			args.tfRegister[IDE_NSECTOR_OFFSET] = drive->sect;
-			args.tfRegister[IDE_SECTOR_OFFSET]  = drive->sect;
-			args.tfRegister[IDE_LCYL_OFFSET]    = drive->cyl;
-			args.tfRegister[IDE_HCYL_OFFSET]    = drive->cyl>>8;
-			args.tfRegister[IDE_SELECT_OFFSET]  = ((drive->head-1)|drive->select.all)&0xBF;
-			args.tfRegister[IDE_COMMAND_OFFSET] = WIN_SPECIFY;
-			args.command_type = IDE_DRIVE_TASK_NO_DATA;
-			args.handler	  = &set_geometry_intr;
-			do_rw_taskfile(drive, &args);
-		}
-	} else if (s->b.recalibrate) {
-		s->b.recalibrate = 0;
-		if (!IS_PDC4030_DRIVE) {
-			ide_task_t args;
-			memset(&args, 0, sizeof(ide_task_t));
-			args.tfRegister[IDE_NSECTOR_OFFSET] = drive->sect;
-			args.tfRegister[IDE_COMMAND_OFFSET] = WIN_RESTORE;
-			args.command_type = IDE_DRIVE_TASK_NO_DATA;
-			args.handler	  = &recal_intr;
-			do_rw_taskfile(drive, &args);
-		}
-	} else if (s->b.set_multmode) {
-		s->b.set_multmode = 0;
-		if (drive->mult_req > drive->id->max_multsect)
-			drive->mult_req = drive->id->max_multsect;
-		if (!IS_PDC4030_DRIVE) {
-			ide_task_t args;
-			memset(&args, 0, sizeof(ide_task_t));
-			args.tfRegister[IDE_NSECTOR_OFFSET] = drive->mult_req;
-			args.tfRegister[IDE_COMMAND_OFFSET] = WIN_SETMULT;
-			args.command_type = IDE_DRIVE_TASK_NO_DATA;
-			args.handler	  = &set_multmode_intr;
-			do_rw_taskfile(drive, &args);
-		}
-	} else if (s->all) {
-		int special = s->all;
-		s->all = 0;
-		printk(KERN_ERR "%s: bad special flag: 0x%02x\n", drive->name, special);
-		return ide_stopped;
-	}
-	return IS_PDC4030_DRIVE ? ide_stopped : ide_started;
-}
-
-static void idedisk_pre_reset (ide_drive_t *drive)
-{
-	int legacy = (drive->id->cfs_enable_2 & 0x0400) ? 0 : 1;
-
-	drive->special.all = 0;
-	drive->special.b.set_geometry = legacy;
-	drive->special.b.recalibrate  = legacy;
-	if (OK_TO_RESET_CONTROLLER)
-		drive->mult_count = 0;
-	if (!drive->keep_settings && !drive->using_dma)
-		drive->mult_req = 0;
-	if (drive->mult_req != drive->mult_count)
-		drive->special.b.set_multmode = 1;
-}
-
 #ifdef CONFIG_PROC_FS
 
 static int smart_enable(ide_drive_t *drive)
@@ -646,6 +579,16 @@
 	PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
 }
 
+static int proc_idedisk_read_capacity
+	(char *page, char **start, off_t off, int count, int *eof, void *data)
+{
+	ide_drive_t*drive = (ide_drive_t *)data;
+	int len;
+
+	len = sprintf(page,"%llu\n", (long long)idedisk_capacity(drive));
+	PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
+}
+
 static int proc_idedisk_read_smart_thresholds
 	(char *page, char **start, off_t off, int count, int *eof, void *data)
 {
@@ -686,6 +629,7 @@
 
 static ide_proc_entry_t idedisk_proc[] = {
 	{ "cache",		S_IFREG|S_IRUGO,	proc_idedisk_read_cache,		NULL },
+	{ "capacity",		S_IFREG|S_IRUGO,	proc_idedisk_read_capacity,		NULL },
 	{ "geometry",		S_IFREG|S_IRUGO,	proc_ide_read_geometry,			NULL },
 	{ "smart_values",	S_IFREG|S_IRUSR,	proc_idedisk_read_smart_values,		NULL },
 	{ "smart_thresholds",	S_IFREG|S_IRUSR,	proc_idedisk_read_smart_thresholds,	NULL },
@@ -698,18 +642,51 @@
 
 #endif	/* CONFIG_PROC_FS */
 
-static int idedisk_issue_flush(request_queue_t *q, struct gendisk *disk,
-			       sector_t *error_sector)
+static void idedisk_end_flush(request_queue_t *q, struct request *flush_rq)
+{
+	ide_drive_t *drive = q->queuedata;
+	struct request *rq = flush_rq->end_io_data;
+	int good_sectors = rq->hard_nr_sectors;
+	int bad_sectors;
+	sector_t sector;
+
+	if (flush_rq->errors & ABRT_ERR) {
+		printk(KERN_ERR "%s: barrier support doesn't work\n", drive->name);
+		blk_queue_ordered(drive->queue, QUEUE_ORDERED_NONE);
+		blk_queue_issue_flush_fn(drive->queue, NULL);
+		good_sectors = 0;
+	} else if (flush_rq->errors) {
+		good_sectors = 0;
+		if (blk_barrier_preflush(rq)) {
+			sector = ide_get_error_location(drive,flush_rq->buffer);
+			if ((sector >= rq->hard_sector) &&
+			    (sector < rq->hard_sector + rq->hard_nr_sectors))
+				good_sectors = sector - rq->hard_sector;
+		}
+	}
+
+	if (flush_rq->errors)
+		printk(KERN_ERR "%s: failed barrier write: "
+				"sector=%Lx(good=%d/bad=%d)\n",
+				drive->name, (unsigned long long)rq->sector,
+				good_sectors,
+				(int) (rq->hard_nr_sectors-good_sectors));
+
+	bad_sectors = rq->hard_nr_sectors - good_sectors;
+
+	if (good_sectors)
+		__ide_end_request(drive, rq, 1, good_sectors);
+	if (bad_sectors)
+		__ide_end_request(drive, rq, 0, bad_sectors);
+}
+
+static int idedisk_prepare_flush(request_queue_t *q, struct request *rq)
 {
 	ide_drive_t *drive = q->queuedata;
-	struct request *rq;
-	int ret;
 
 	if (!drive->wcache)
 		return 0;
 
-	rq = blk_get_request(q, WRITE, __GFP_WAIT);
-
 	memset(rq->cmd, 0, sizeof(rq->cmd));
 
 	if (ide_id_has_flush_cache_ext(drive->id) &&
@@ -721,6 +698,22 @@
 
 	rq->flags |= REQ_DRIVE_TASK | REQ_SOFTBARRIER;
 	rq->buffer = rq->cmd;
+	return 1;
+}
+
+static int idedisk_issue_flush(request_queue_t *q, struct gendisk *disk,
+			       sector_t *error_sector)
+{
+	ide_drive_t *drive = q->queuedata;
+	struct request *rq;
+	int ret;
+
+	if (!drive->wcache)
+		return 0;
+
+	rq = blk_get_request(q, WRITE, __GFP_WAIT);
+
+	idedisk_prepare_flush(q, rq);
 
 	ret = blk_execute_rq(q, disk, rq);
 
@@ -852,90 +845,6 @@
  	ide_add_setting(drive,	"max_failures",		SETTING_RW,					-1,			-1,			TYPE_INT,	0,	65535,				1,	1,	&drive->max_failures,		NULL);
 }
 
-/*
- * Power Management state machine. This one is rather trivial for now,
- * we should probably add more, like switching back to PIO on suspend
- * to help some BIOSes, re-do the door locking on resume, etc...
- */
-
-enum {
-	idedisk_pm_flush_cache	= ide_pm_state_start_suspend,
-	idedisk_pm_standby,
-
-	idedisk_pm_idle		= ide_pm_state_start_resume,
-	idedisk_pm_restore_dma,
-};
-
-static void idedisk_complete_power_step (ide_drive_t *drive, struct request *rq, u8 stat, u8 error)
-{
-	switch (rq->pm->pm_step) {
-	case idedisk_pm_flush_cache:	/* Suspend step 1 (flush cache) complete */
-		if (rq->pm->pm_state == 4)
-			rq->pm->pm_step = ide_pm_state_completed;
-		else
-			rq->pm->pm_step = idedisk_pm_standby;
-		break;
-	case idedisk_pm_standby:	/* Suspend step 2 (standby) complete */
-		rq->pm->pm_step = ide_pm_state_completed;
-		break;
-	case idedisk_pm_idle:		/* Resume step 1 (idle) complete */
-		rq->pm->pm_step = idedisk_pm_restore_dma;
-		break;
-	}
-}
-
-static ide_startstop_t idedisk_start_power_step (ide_drive_t *drive, struct request *rq)
-{
-	ide_task_t *args = rq->special;
-
-	memset(args, 0, sizeof(*args));
-
-	switch (rq->pm->pm_step) {
-	case idedisk_pm_flush_cache:	/* Suspend step 1 (flush cache) */
-		/* Not supported? Switch to next step now. */
-		if (!drive->wcache || !ide_id_has_flush_cache(drive->id)) {
-			idedisk_complete_power_step(drive, rq, 0, 0);
-			return ide_stopped;
-		}
-		if (ide_id_has_flush_cache_ext(drive->id))
-			args->tfRegister[IDE_COMMAND_OFFSET] = WIN_FLUSH_CACHE_EXT;
-		else
-			args->tfRegister[IDE_COMMAND_OFFSET] = WIN_FLUSH_CACHE;
-		args->command_type = IDE_DRIVE_TASK_NO_DATA;
-		args->handler	   = &task_no_data_intr;
-		return do_rw_taskfile(drive, args);
-
-	case idedisk_pm_standby:	/* Suspend step 2 (standby) */
-		args->tfRegister[IDE_COMMAND_OFFSET] = WIN_STANDBYNOW1;
-		args->command_type = IDE_DRIVE_TASK_NO_DATA;
-		args->handler	   = &task_no_data_intr;
-		return do_rw_taskfile(drive, args);
-
-	case idedisk_pm_idle:		/* Resume step 1 (idle) */
-		args->tfRegister[IDE_COMMAND_OFFSET] = WIN_IDLEIMMEDIATE;
-		args->command_type = IDE_DRIVE_TASK_NO_DATA;
-		args->handler = task_no_data_intr;
-		return do_rw_taskfile(drive, args);
-
-	case idedisk_pm_restore_dma:	/* Resume step 2 (restore DMA) */
-		/*
-		 * Right now, all we do is call hwif->ide_dma_check(drive),
-		 * we could be smarter and check for current xfer_speed
-		 * in struct drive etc...
-		 * Also, this step could be implemented as a generic helper
-		 * as most subdrivers will use it
-		 */
-		if ((drive->id->capability & 1) == 0)
-			break;
-		if (HWIF(drive)->ide_dma_check == NULL)
-			break;
-		HWIF(drive)->ide_dma_check(drive);
-		break;
-	}
-	rq->pm->pm_step = ide_pm_state_completed;
-	return ide_stopped;
-}
-
 static void idedisk_setup (ide_drive_t *drive)
 {
 	struct hd_driveid *id = drive->id;
@@ -974,28 +883,6 @@
 
 	printk(KERN_INFO "%s: max request size: %dKiB\n", drive->name, drive->queue->max_sectors / 2);
 
-	/* Extract geometry if we did not already have one for the drive */
-	if (!drive->cyl || !drive->head || !drive->sect) {
-		drive->cyl     = drive->bios_cyl  = id->cyls;
-		drive->head    = drive->bios_head = id->heads;
-		drive->sect    = drive->bios_sect = id->sectors;
-	}
-
-	/* Handle logical geometry translation by the drive */
-	if ((id->field_valid & 1) && id->cur_cyls &&
-	    id->cur_heads && (id->cur_heads <= 16) && id->cur_sectors) {
-		drive->cyl  = id->cur_cyls;
-		drive->head = id->cur_heads;
-		drive->sect = id->cur_sectors;
-	}
-
-	/* Use physical geometry if what we have still makes no sense */
-	if (drive->head > 16 && id->heads && id->heads <= 16) {
-		drive->cyl  = id->cyls;
-		drive->head = id->heads;
-		drive->sect = id->sectors;
-	}
-
 	/* calculate drive capacity, and select LBA if possible */
 	init_idedisk_capacity (drive);
 
@@ -1059,21 +946,6 @@
 		ide_dma_verbose(drive);
 	printk("\n");
 
-	drive->mult_count = 0;
-	if (id->max_multsect) {
-#ifdef CONFIG_IDEDISK_MULTI_MODE
-		id->multsect = ((id->max_multsect/2) > 1) ? id->max_multsect : 0;
-		id->multsect_valid = id->multsect ? 1 : 0;
-		drive->mult_req = id->multsect_valid ? id->max_multsect : INITIAL_MULT_COUNT;
-		drive->special.b.set_multmode = drive->mult_req ? 1 : 0;
-#else	/* original, pre IDE-NFG, per request of AC */
-		drive->mult_req = INITIAL_MULT_COUNT;
-		if (drive->mult_req > id->max_multsect)
-			drive->mult_req = id->max_multsect;
-		if (drive->mult_req || ((id->multsect_valid & 1) && id->multsect))
-			drive->special.b.set_multmode = 1;
-#endif	/* CONFIG_IDEDISK_MULTI_MODE */
-	}
 	drive->no_io_32bit = id->dword_io ? 1 : 0;
 
 	/* write cache enabled? */
@@ -1098,10 +970,12 @@
 			barrier = 0;
 	}
 
-	printk(KERN_DEBUG "%s: cache flushes %ssupported\n",
+	printk(KERN_INFO "%s: cache flushes %ssupported\n",
 		drive->name, barrier ? "" : "not ");
 	if (barrier) {
-		blk_queue_ordered(drive->queue, 1);
+		blk_queue_ordered(drive->queue, QUEUE_ORDERED_FLUSH);
+		drive->queue->prepare_flush_fn = idedisk_prepare_flush;
+		drive->queue->end_flush_fn = idedisk_end_flush;
 		blk_queue_issue_flush_fn(drive->queue, idedisk_issue_flush);
 	}
 }
@@ -1172,14 +1046,12 @@
 	.supports_dsc_overlap	= 0,
 	.cleanup		= idedisk_cleanup,
 	.do_request		= ide_do_rw_disk,
-	.pre_reset		= idedisk_pre_reset,
-	.capacity		= idedisk_capacity,
-	.special		= idedisk_special,
+	.end_request		= ide_end_request,
+	.error			= __ide_error,
+	.abort			= __ide_abort,
 	.proc			= idedisk_proc,
 	.attach			= idedisk_attach,
 	.drives			= LIST_HEAD_INIT(idedisk_driver.drives),
-	.start_power_step	= idedisk_start_power_step,
-	.complete_power_step	= idedisk_complete_power_step,
 };
 
 static int idedisk_open(struct inode *inode, struct file *filp)
diff -Nru a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c
--- a/drivers/ide/ide-floppy.c	2005-03-11 12:51:46 -08:00
+++ b/drivers/ide/ide-floppy.c	2005-03-11 12:51:46 -08:00
@@ -1793,7 +1793,6 @@
 
 	*((u16 *) &gcw) = drive->id->config;
 	drive->driver_data = floppy;
-	drive->ready_stat = 0;
 	memset(floppy, 0, sizeof(idefloppy_floppy_t));
 	floppy->drive = drive;
 	floppy->pc = floppy->pc_stack;
@@ -1848,7 +1847,18 @@
 
 #ifdef CONFIG_PROC_FS
 
+static int proc_idefloppy_read_capacity
+	(char *page, char **start, off_t off, int count, int *eof, void *data)
+{
+	ide_drive_t*drive = (ide_drive_t *)data;
+	int len;
+
+	len = sprintf(page,"%llu\n", (long long)idefloppy_capacity(drive));
+	PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
+}
+
 static ide_proc_entry_t idefloppy_proc[] = {
+	{ "capacity",	S_IFREG|S_IRUGO,	proc_idefloppy_read_capacity, NULL },
 	{ "geometry",	S_IFREG|S_IRUGO,	proc_ide_read_geometry,	NULL },
 	{ NULL, 0, NULL, NULL }
 };
@@ -1874,7 +1884,8 @@
 	.cleanup		= idefloppy_cleanup,
 	.do_request		= idefloppy_do_request,
 	.end_request		= idefloppy_do_end_request,
-	.capacity		= idefloppy_capacity,
+	.error			= __ide_error,
+	.abort			= __ide_abort,
 	.proc			= idefloppy_proc,
 	.attach			= idefloppy_attach,
 	.drives			= LIST_HEAD_INIT(idefloppy_driver.drives),
diff -Nru a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c
--- a/drivers/ide/ide-io.c	2005-03-11 12:51:50 -08:00
+++ b/drivers/ide/ide-io.c	2005-03-11 12:51:50 -08:00
@@ -55,62 +55,8 @@
 #include <asm/io.h>
 #include <asm/bitops.h>
 
-static void ide_fill_flush_cmd(ide_drive_t *drive, struct request *rq)
-{
-	char *buf = rq->cmd;
-
-	/*
-	 * reuse cdb space for ata command
-	 */
-	memset(buf, 0, sizeof(rq->cmd));
-
-	rq->flags |= REQ_DRIVE_TASK | REQ_STARTED;
-	rq->buffer = buf;
-	rq->buffer[0] = WIN_FLUSH_CACHE;
-
-	if (ide_id_has_flush_cache_ext(drive->id) &&
-	    (drive->capacity64 >= (1UL << 28)))
-		rq->buffer[0] = WIN_FLUSH_CACHE_EXT;
-}
-
-/*
- * preempt pending requests, and store this cache flush for immediate
- * execution
- */
-static struct request *ide_queue_flush_cmd(ide_drive_t *drive,
-					   struct request *rq, int post)
-{
-	struct request *flush_rq = &HWGROUP(drive)->wrq;
-
-	/*
-	 * write cache disabled, clear the barrier bit and treat it like
-	 * an ordinary write
-	 */
-	if (!drive->wcache) {
-		rq->flags |= REQ_BAR_PREFLUSH;
-		return rq;
-	}
-
-	ide_init_drive_cmd(flush_rq);
-	ide_fill_flush_cmd(drive, flush_rq);
-
-	flush_rq->special = rq;
-	flush_rq->nr_sectors = rq->nr_sectors;
-
-	if (!post) {
-		drive->doing_barrier = 1;
-		flush_rq->flags |= REQ_BAR_PREFLUSH;
-		blkdev_dequeue_request(rq);
-	} else
-		flush_rq->flags |= REQ_BAR_POSTFLUSH;
-
-	__elv_add_request(drive->queue, flush_rq, ELEVATOR_INSERT_FRONT, 0);
-	HWGROUP(drive)->rq = NULL;
-	return flush_rq;
-}
-
-static int __ide_end_request(ide_drive_t *drive, struct request *rq,
-			     int uptodate, int nr_sectors)
+int __ide_end_request(ide_drive_t *drive, struct request *rq, int uptodate,
+		      int nr_sectors)
 {
 	int ret = 1;
 
@@ -148,6 +94,7 @@
 	}
 	return ret;
 }
+EXPORT_SYMBOL(__ide_end_request);
 
 /**
  *	ide_end_request		-	complete an IDE I/O
@@ -172,23 +119,109 @@
 	if (!nr_sectors)
 		nr_sectors = rq->hard_cur_sectors;
 
-	if (!blk_barrier_rq(rq) || !drive->wcache)
+	if (blk_complete_barrier_rq_locked(drive->queue, rq, nr_sectors))
+		ret = rq->nr_sectors != 0;
+	else
 		ret = __ide_end_request(drive, rq, uptodate, nr_sectors);
-	else {
-		struct request *flush_rq = &HWGROUP(drive)->wrq;
-
-		flush_rq->nr_sectors -= nr_sectors;
-		if (!flush_rq->nr_sectors) {
-			ide_queue_flush_cmd(drive, rq, 1);
-			ret = 0;
-		}
-	}
 
 	spin_unlock_irqrestore(&ide_lock, flags);
 	return ret;
 }
 EXPORT_SYMBOL(ide_end_request);
 
+/*
+ * Power Management state machine. This one is rather trivial for now,
+ * we should probably add more, like switching back to PIO on suspend
+ * to help some BIOSes, re-do the door locking on resume, etc...
+ */
+
+enum {
+	ide_pm_flush_cache	= ide_pm_state_start_suspend,
+	idedisk_pm_standby,
+
+	idedisk_pm_idle		= ide_pm_state_start_resume,
+	ide_pm_restore_dma,
+};
+
+static void ide_complete_power_step(ide_drive_t *drive, struct request *rq, u8 stat, u8 error)
+{
+	if (drive->media != ide_disk)
+		return;
+
+	switch (rq->pm->pm_step) {
+	case ide_pm_flush_cache:	/* Suspend step 1 (flush cache) complete */
+		if (rq->pm->pm_state == 4)
+			rq->pm->pm_step = ide_pm_state_completed;
+		else
+			rq->pm->pm_step = idedisk_pm_standby;
+		break;
+	case idedisk_pm_standby:	/* Suspend step 2 (standby) complete */
+		rq->pm->pm_step = ide_pm_state_completed;
+		break;
+	case idedisk_pm_idle:		/* Resume step 1 (idle) complete */
+		rq->pm->pm_step = ide_pm_restore_dma;
+		break;
+	}
+}
+
+static ide_startstop_t ide_start_power_step(ide_drive_t *drive, struct request *rq)
+{
+	ide_task_t *args = rq->special;
+
+	memset(args, 0, sizeof(*args));
+
+	if (drive->media != ide_disk) {
+		/* skip idedisk_pm_idle for ATAPI devices */
+		if (rq->pm->pm_step == idedisk_pm_idle)
+			rq->pm->pm_step = ide_pm_restore_dma;
+	}
+
+	switch (rq->pm->pm_step) {
+	case ide_pm_flush_cache:	/* Suspend step 1 (flush cache) */
+		if (drive->media != ide_disk)
+			break;
+		/* Not supported? Switch to next step now. */
+		if (!drive->wcache || !ide_id_has_flush_cache(drive->id)) {
+			ide_complete_power_step(drive, rq, 0, 0);
+			return ide_stopped;
+		}
+		if (ide_id_has_flush_cache_ext(drive->id))
+			args->tfRegister[IDE_COMMAND_OFFSET] = WIN_FLUSH_CACHE_EXT;
+		else
+			args->tfRegister[IDE_COMMAND_OFFSET] = WIN_FLUSH_CACHE;
+		args->command_type = IDE_DRIVE_TASK_NO_DATA;
+		args->handler	   = &task_no_data_intr;
+		return do_rw_taskfile(drive, args);
+
+	case idedisk_pm_standby:	/* Suspend step 2 (standby) */
+		args->tfRegister[IDE_COMMAND_OFFSET] = WIN_STANDBYNOW1;
+		args->command_type = IDE_DRIVE_TASK_NO_DATA;
+		args->handler	   = &task_no_data_intr;
+		return do_rw_taskfile(drive, args);
+
+	case idedisk_pm_idle:		/* Resume step 1 (idle) */
+		args->tfRegister[IDE_COMMAND_OFFSET] = WIN_IDLEIMMEDIATE;
+		args->command_type = IDE_DRIVE_TASK_NO_DATA;
+		args->handler = task_no_data_intr;
+		return do_rw_taskfile(drive, args);
+
+	case ide_pm_restore_dma:	/* Resume step 2 (restore DMA) */
+		/*
+		 * Right now, all we do is call hwif->ide_dma_check(drive),
+		 * we could be smarter and check for current xfer_speed
+		 * in struct drive etc...
+		 */
+		if ((drive->id->capability & 1) == 0)
+			break;
+		if (drive->hwif->ide_dma_check == NULL)
+			break;
+		drive->hwif->ide_dma_check(drive);
+		break;
+	}
+	rq->pm->pm_step = ide_pm_state_completed;
+	return ide_stopped;
+}
+
 /**
  *	ide_complete_pm_request - end the current Power Management request
  *	@drive: target drive
@@ -253,79 +286,6 @@
 }
 EXPORT_SYMBOL(ide_get_error_location);
 
-static void ide_complete_barrier(ide_drive_t *drive, struct request *rq,
-				 int error)
-{
-	struct request *real_rq = rq->special;
-	int good_sectors, bad_sectors;
-	sector_t sector;
-
-	if (!error) {
-		if (blk_barrier_postflush(rq)) {
-			/*
-			 * this completes the barrier write
-			 */
-			__ide_end_request(drive, real_rq, 1, real_rq->hard_nr_sectors);
-			drive->doing_barrier = 0;
-		} else {
-			/*
-			 * just indicate that we did the pre flush
-			 */
-			real_rq->flags |= REQ_BAR_PREFLUSH;
-			elv_requeue_request(drive->queue, real_rq);
-		}
-		/*
-		 * all is fine, return
-		 */
-		return;
-	}
-
-	/*
-	 * we need to end real_rq, but it's not on the queue currently.
-	 * put it back on the queue, so we don't have to special case
-	 * anything else for completing it
-	 */
-	if (!blk_barrier_postflush(rq))
-		elv_requeue_request(drive->queue, real_rq);
-
-	/*
-	 * drive aborted flush command, assume FLUSH_CACHE_* doesn't
-	 * work and disable barrier support
-	 */
-	if (error & ABRT_ERR) {
-		printk(KERN_ERR "%s: barrier support doesn't work\n", drive->name);
-		__ide_end_request(drive, real_rq, -EOPNOTSUPP, real_rq->hard_nr_sectors);
-		blk_queue_ordered(drive->queue, 0);
-		blk_queue_issue_flush_fn(drive->queue, NULL);
-	} else {
-		/*
-		 * find out what part of the request failed
-		 */
-		good_sectors = 0;
-		if (blk_barrier_postflush(rq)) {
-			sector = ide_get_error_location(drive, rq->buffer);
-
-			if ((sector >= real_rq->hard_sector) &&
-			    (sector < real_rq->hard_sector + real_rq->hard_nr_sectors))
-				good_sectors = sector - real_rq->hard_sector;
-		} else
-			sector = real_rq->hard_sector;
-
-		bad_sectors = real_rq->hard_nr_sectors - good_sectors;
-		if (good_sectors)
-			__ide_end_request(drive, real_rq, 1, good_sectors);
-		if (bad_sectors)
-			__ide_end_request(drive, real_rq, 0, bad_sectors);
-
-		printk(KERN_ERR "%s: failed barrier write: "
-				"sector=%Lx(good=%d/bad=%d)\n",
-				drive->name, (unsigned long long)sector,
-				good_sectors, bad_sectors);
-	}
-
-	drive->doing_barrier = 0;
-}
-
 /**
  *	ide_end_drive_cmd	-	end an explicit drive command
  *	@drive: command 
@@ -409,7 +369,7 @@
 		printk("%s: complete_power_step(step: %d, stat: %x, err: %x)\n",
 			drive->name, rq->pm->pm_step, stat, err);
 #endif
-		DRIVER(drive)->complete_power_step(drive, rq, stat, err);
+		ide_complete_power_step(drive, rq, stat, err);
 		if (rq->pm->pm_step == ide_pm_state_completed)
 			ide_complete_pm_request(drive, rq);
 		return;
@@ -417,11 +377,8 @@
 
 	spin_lock_irqsave(&ide_lock, flags);
 	blkdev_dequeue_request(rq);
-
-	if (blk_barrier_preflush(rq) || blk_barrier_postflush(rq))
-		ide_complete_barrier(drive, rq, err);
-
 	HWGROUP(drive)->rq = NULL;
+	rq->errors = err;
 	end_that_request_last(rq);
 	spin_unlock_irqrestore(&ide_lock, flags);
 }
@@ -536,6 +493,8 @@
 	return ide_atapi_error(drive, rq, stat, err);
 }
 
+EXPORT_SYMBOL_GPL(__ide_error);
+
 /**
  *	ide_error	-	handle an error on the IDE
  *	@drive: drive the error occurred on
@@ -580,6 +539,8 @@
 	return ide_stopped;
 }
 
+EXPORT_SYMBOL_GPL(__ide_abort);
+
 /**
  *	ide_abort	-	abort pending IDE operatins
  *	@drive: drive the error occurred on
@@ -668,6 +629,65 @@
 	return ide_stopped;
 }
 
+static void ide_init_specify_cmd(ide_drive_t *drive, ide_task_t *task)
+{
+	task->tfRegister[IDE_NSECTOR_OFFSET] = drive->sect;
+	task->tfRegister[IDE_SECTOR_OFFSET]  = drive->sect;
+	task->tfRegister[IDE_LCYL_OFFSET]    = drive->cyl;
+	task->tfRegister[IDE_HCYL_OFFSET]    = drive->cyl>>8;
+	task->tfRegister[IDE_SELECT_OFFSET]  = ((drive->head-1)|drive->select.all)&0xBF;
+	task->tfRegister[IDE_COMMAND_OFFSET] = WIN_SPECIFY;
+
+	task->handler = &set_geometry_intr;
+}
+
+static void ide_init_restore_cmd(ide_drive_t *drive, ide_task_t *task)
+{
+	task->tfRegister[IDE_NSECTOR_OFFSET] = drive->sect;
+	task->tfRegister[IDE_COMMAND_OFFSET] = WIN_RESTORE;
+
+	task->handler = &recal_intr;
+}
+
+static void ide_init_setmult_cmd(ide_drive_t *drive, ide_task_t *task)
+{
+	task->tfRegister[IDE_NSECTOR_OFFSET] = drive->mult_req;
+	task->tfRegister[IDE_COMMAND_OFFSET] = WIN_SETMULT;
+
+	task->handler = &set_multmode_intr;
+}
+
+static ide_startstop_t ide_disk_special(ide_drive_t *drive)
+{
+	special_t *s = &drive->special;
+	ide_task_t args;
+
+	memset(&args, 0, sizeof(ide_task_t));
+	args.command_type = IDE_DRIVE_TASK_NO_DATA;
+
+	if (s->b.set_geometry) {
+		s->b.set_geometry = 0;
+		ide_init_specify_cmd(drive, &args);
+	} else if (s->b.recalibrate) {
+		s->b.recalibrate = 0;
+		ide_init_restore_cmd(drive, &args);
+	} else if (s->b.set_multmode) {
+		s->b.set_multmode = 0;
+		if (drive->mult_req > drive->id->max_multsect)
+			drive->mult_req = drive->id->max_multsect;
+		ide_init_setmult_cmd(drive, &args);
+	} else if (s->all) {
+		int special = s->all;
+		s->all = 0;
+		printk(KERN_ERR "%s: bad special flag: 0x%02x\n", drive->name, special);
+		return ide_stopped;
+	}
+
+	do_rw_taskfile(drive, &args);
+
+	return ide_started;
+}
+
 /**
  *	do_special		-	issue some special commands
  *	@drive: drive the command is for
@@ -689,9 +709,14 @@
 		if (HWIF(drive)->tuneproc != NULL)
 			HWIF(drive)->tuneproc(drive, drive->tune_req);
 		return ide_stopped;
+	} else {
+		if (drive->media == ide_disk)
+			return ide_disk_special(drive);
+
+		s->all = 0;
+		drive->mult_req = 0;
+		return ide_stopped;
 	}
-	else
-		return DRIVER(drive)->special(drive);
 }
 
 void ide_map_sg(ide_drive_t *drive, struct request *rq)
@@ -906,7 +931,7 @@
 			printk("%s: start_power_step(step: %d)\n",
 				drive->name, rq->pm->pm_step);
 #endif
-			startstop = DRIVER(drive)->start_power_step(drive, rq);
+			startstop = ide_start_power_step(drive, rq);
 			if (startstop == ide_stopped &&
 			    rq->pm->pm_step == ide_pm_state_completed)
 				ide_complete_pm_request(drive, rq);
@@ -963,7 +988,7 @@
 	 * though that is 3 requests, it must be seen as a single transaction.
 	 * we must not preempt this drive until that is complete
 	 */
-	if (drive->doing_barrier) {
+	if (blk_queue_flushing(drive->queue)) {
 		/*
 		 * small race where queue could get replugged during
 		 * the 3-request flush cycle, just yank the plug since
@@ -1128,13 +1153,6 @@
 		}
 
 		/*
-		 * if rq is a barrier write, issue pre cache flush if not
-		 * already done
-		 */
-		if (blk_barrier_rq(rq) && !blk_barrier_preflush(rq))
-			rq = ide_queue_flush_cmd(drive, rq, 0);
-
-		/*
 		 * Sanity: don't accept a request that isn't a PM request
 		 * if we are currently power managed. This is very important as
 		 * blk_stop_queue() doesn't prevent the elv_next_request()
@@ -1607,6 +1625,7 @@
 	if (must_wait) {
 		rq->ref_count++;
 		rq->waiting = &wait;
+		rq->end_io = blk_end_sync_rq;
 	}
 
 	spin_lock_irqsave(&ide_lock, flags);
diff -Nru a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c
--- a/drivers/ide/ide-iops.c	2005-03-11 12:51:42 -08:00
+++ b/drivers/ide/ide-iops.c	2005-03-11 12:51:42 -08:00
@@ -1107,9 +1107,27 @@
 #endif
 }
 
+static void ide_disk_pre_reset(ide_drive_t *drive)
+{
+	int legacy = (drive->id->cfs_enable_2 & 0x0400) ? 0 : 1;
+
+	drive->special.all = 0;
+	drive->special.b.set_geometry = legacy;
+	drive->special.b.recalibrate  = legacy;
+	if (OK_TO_RESET_CONTROLLER)
+		drive->mult_count = 0;
+	if (!drive->keep_settings && !drive->using_dma)
+		drive->mult_req = 0;
+	if (drive->mult_req != drive->mult_count)
+		drive->special.b.set_multmode = 1;
+}
+
 static void pre_reset(ide_drive_t *drive)
 {
-	DRIVER(drive)->pre_reset(drive);
+	if (drive->media == ide_disk)
+		ide_disk_pre_reset(drive);
+	else
+		drive->post_reset = 1;
 
 	if (!drive->keep_settings) {
 		if (drive->using_dma) {
diff -Nru a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c
--- a/drivers/ide/ide-probe.c	2005-03-11 12:51:47 -08:00
+++ b/drivers/ide/ide-probe.c	2005-03-11 12:51:47 -08:00
@@ -74,7 +74,55 @@
 	drive->id->cur_heads = drive->head;
 	drive->id->cur_sectors = drive->sect;
 }
-		
+
+static void ide_disk_init_chs(ide_drive_t *drive)
+{
+	struct hd_driveid *id = drive->id;
+
+	/* Extract geometry if we did not already have one for the drive */
+	if (!drive->cyl || !drive->head || !drive->sect) {
+		drive->cyl  = drive->bios_cyl  = id->cyls;
+		drive->head = drive->bios_head = id->heads;
+		drive->sect = drive->bios_sect = id->sectors;
+	}
+
+	/* Handle logical geometry translation by the drive */
+	if ((id->field_valid & 1) && id->cur_cyls &&
+	    id->cur_heads && (id->cur_heads <= 16) && id->cur_sectors) {
+		drive->cyl  = id->cur_cyls;
+		drive->head = id->cur_heads;
+		drive->sect = id->cur_sectors;
+	}
+
+	/* Use physical geometry if what we have still makes no sense */
+	if (drive->head > 16 && id->heads && id->heads <= 16) {
+		drive->cyl  = id->cyls;
+		drive->head = id->heads;
+		drive->sect = id->sectors;
+	}
+}
+
+static void ide_disk_init_mult_count(ide_drive_t *drive)
+{
+	struct hd_driveid *id = drive->id;
+
+	drive->mult_count = 0;
+	if (id->max_multsect) {
+#ifdef CONFIG_IDEDISK_MULTI_MODE
+		id->multsect = ((id->max_multsect/2) > 1) ? id->max_multsect : 0;
+		id->multsect_valid = id->multsect ? 1 : 0;
+		drive->mult_req = id->multsect_valid ? id->max_multsect : INITIAL_MULT_COUNT;
+		drive->special.b.set_multmode = drive->mult_req ? 1 : 0;
+#else	/* original, pre IDE-NFG, per request of AC */
+		drive->mult_req = INITIAL_MULT_COUNT;
+		if (drive->mult_req > id->max_multsect)
+			drive->mult_req = id->max_multsect;
+		if (drive->mult_req || ((id->multsect_valid & 1) && id->multsect))
+			drive->special.b.set_multmode = 1;
+#endif
+	}
+}
+
 /**
  *	drive_is_flashcard	-	check for compact flash
  *	@drive: drive to check
@@ -221,6 +269,8 @@
 		}
 		printk (" drive\n");
 		drive->media = type;
+		/* an ATAPI device ignores DRDY */
+		drive->ready_stat = 0;
 		return;
 	}
 
@@ -588,8 +638,16 @@
 	if(!drive->present)
 		return 0;
 	/* The drive wasn't being helpful. Add generic info only */
-	if(!drive->id_read)
+	if (drive->id_read == 0) {
 		generic_id(drive);
+		return 1;
+	}
+
+	if (drive->media == ide_disk) {
+		ide_disk_init_chs(drive);
+		ide_disk_init_mult_count(drive);
+	}
+
 	return drive->present;
 }
 
diff -Nru a/drivers/ide/ide-proc.c b/drivers/ide/ide-proc.c
--- a/drivers/ide/ide-proc.c	2005-03-11 12:51:46 -08:00
+++ b/drivers/ide/ide-proc.c	2005-03-11 12:51:46 -08:00
@@ -269,13 +269,11 @@
 int proc_ide_read_capacity
 	(char *page, char **start, off_t off, int count, int *eof, void *data)
 {
-	ide_drive_t	*drive = (ide_drive_t *) data;
-	int		len;
-
-	len = sprintf(page,"%llu\n",
-		      (long long) (DRIVER(drive)->capacity(drive)));
+	int len = sprintf(page,"%llu\n", (long long)0x7fffffff);
 	PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
 }
+
+EXPORT_SYMBOL_GPL(proc_ide_read_capacity);
 
 int proc_ide_read_geometry
 	(char *page, char **start, off_t off, int count, int *eof, void *data)
diff -Nru a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c
--- a/drivers/ide/ide-tape.c	2005-03-11 12:51:42 -08:00
+++ b/drivers/ide/ide-tape.c	2005-03-11 12:51:42 -08:00
@@ -2428,6 +2428,11 @@
 	if (!drive->dsc_overlap && !(rq->cmd[0] & REQ_IDETAPE_PC2))
 		set_bit(IDETAPE_IGNORE_DSC, &tape->flags);
 
+	if (drive->post_reset == 1) {
+		set_bit(IDETAPE_IGNORE_DSC, &tape->flags);
+		drive->post_reset = 0;
+	}
+
 	if (tape->tape_still_time > 100 && tape->tape_still_time < 200)
 		tape->measure_insert_time = 1;
 	if (time_after(jiffies, tape->insert_time))
@@ -2720,6 +2725,7 @@
 	}
 #endif /* IDETAPE_DEBUG_BUGS */
 	rq->waiting = &wait;
+	rq->end_io = blk_end_sync_rq;
 	spin_unlock_irq(&tape->spinlock);
 	wait_for_completion(&wait);
 	/* The stage and its struct request have been deallocated */
@@ -3558,16 +3564,6 @@
 }
 
 /*
- *	idetape_pre_reset is called before an ATAPI/ATA software reset.
- */
-static void idetape_pre_reset (ide_drive_t *drive)
-{
-	idetape_tape_t *tape = drive->driver_data;
-	if (tape != NULL)
-		set_bit(IDETAPE_IGNORE_DSC, &tape->flags);
-}
-
-/*
  *	idetape_space_over_filemarks is now a bit more complicated than just
  *	passing the command to the tape since we may have crossed some
  *	filemarks during our pipelined read-ahead mode.
@@ -4100,7 +4096,13 @@
 	idetape_pc_t pc;
 	int retval;
 
-	nonseekable_open(inode, filp);
+	/*
+	 * We really want to do nonseekable_open(inode, filp); here, but some
+	 * versions of tar incorrectly call lseek on tapes and bail out if that
+	 * fails.  So we disallow pread() and pwrite(), but permit lseeks.
+	 */
+	filp->f_mode &= ~(FMODE_PREAD | FMODE_PWRITE);
+
 #if IDETAPE_DEBUG_LOG
 	printk(KERN_INFO "ide-tape: Reached idetape_chrdev_open\n");
 #endif /* IDETAPE_DEBUG_LOG */
@@ -4530,8 +4532,6 @@
 	memset(tape, 0, sizeof (idetape_tape_t));
 	spin_lock_init(&tape->spinlock);
 	drive->driver_data = tape;
-	/* An ATAPI device ignores DRDY */
-	drive->ready_stat = 0;
 	drive->dsc_overlap = 1;
 #ifdef CONFIG_BLK_DEV_IDEPCI
 	if (HWIF(drive)->pci_dev != NULL) {
@@ -4667,6 +4667,7 @@
 }
 
 static ide_proc_entry_t idetape_proc[] = {
+	{ "capacity",	S_IFREG|S_IRUGO,	proc_ide_read_capacity, NULL },
 	{ "name",	S_IFREG|S_IRUGO,	proc_idetape_read_name,	NULL },
 	{ NULL, 0, NULL, NULL }
 };
@@ -4692,7 +4693,8 @@
 	.cleanup		= idetape_cleanup,
 	.do_request		= idetape_do_request,
 	.end_request		= idetape_end_request,
-	.pre_reset		= idetape_pre_reset,
+	.error			= __ide_error,
+	.abort			= __ide_abort,
 	.proc			= idetape_proc,
 	.attach			= idetape_attach,
 	.drives			= LIST_HEAD_INIT(idetape_driver.drives),
diff -Nru a/drivers/ide/ide-taskfile.c b/drivers/ide/ide-taskfile.c
--- a/drivers/ide/ide-taskfile.c	2005-03-11 12:51:40 -08:00
+++ b/drivers/ide/ide-taskfile.c	2005-03-11 12:51:40 -08:00
@@ -181,8 +181,6 @@
 	return ide_stopped;
 }
 
-EXPORT_SYMBOL(set_multmode_intr);
-
 /*
  * set_geometry_intr() is invoked on completion of a WIN_SPECIFY cmd.
  */
@@ -207,8 +205,6 @@
 	return ide_started;
 }
 
-EXPORT_SYMBOL(set_geometry_intr);
-
 /*
  * recal_intr() is invoked on completion of a WIN_RESTORE (recalibrate) cmd.
  */
@@ -221,8 +217,6 @@
 		return ide_error(drive, "recal_intr", stat);
 	return ide_stopped;
 }
-
-EXPORT_SYMBOL(recal_intr);
 
 /*
  * Handler for commands without a data phase
diff -Nru a/drivers/ide/ide.c b/drivers/ide/ide.c
--- a/drivers/ide/ide.c	2005-03-11 12:51:42 -08:00
+++ b/drivers/ide/ide.c	2005-03-11 12:51:42 -08:00
@@ -197,7 +197,6 @@
 EXPORT_SYMBOL(ide_hwifs);
 
 extern ide_driver_t idedefault_driver;
-static void setup_driver_defaults(ide_driver_t *driver);
 
 /*
  * Do not even *think* about calling this!
@@ -301,8 +300,6 @@
 		return;		/* already initialized */
 	magic_cookie = 0;
 
-	setup_driver_defaults(&idedefault_driver);
-
 	/* Initialise all interface structures */
 	for (index = 0; index < MAX_HWIFS; ++index) {
 		hwif = &ide_hwifs[index];
@@ -417,11 +414,6 @@
 
 #ifdef CONFIG_PROC_FS
 struct proc_dir_entry *proc_ide_root;
-
-static ide_proc_entry_t generic_subdriver_entries[] = {
-	{ "capacity",	S_IFREG|S_IRUGO,	proc_ide_read_capacity,	NULL },
-	{ NULL, 0, NULL, NULL }
-};
 #endif
 
 static struct resource* hwif_request_region(ide_hwif_t *hwif,
@@ -1751,6 +1743,8 @@
 			case -4: /* "cdrom" */
 				drive->present = 1;
 				drive->media = ide_cdrom;
+				/* an ATAPI device ignores DRDY */
+				drive->ready_stat = 0;
 				hwif->noprobe = 0;
 				goto done;
 			case -5: /* "serialize" */
@@ -1777,6 +1771,7 @@
 				goto done;
 			case 3: /* cyl,head,sect */
 				drive->media	= ide_disk;
+				drive->ready_stat = READY_STAT;
 				drive->cyl	= drive->bios_cyl  = vals[0];
 				drive->head	= drive->bios_head = vals[1];
 				drive->sect	= drive->bios_sect = vals[2];
@@ -2022,68 +2017,6 @@
 #endif
 }
 
-static ide_startstop_t default_do_request (ide_drive_t *drive, struct request *rq, sector_t block)
-{
-	ide_end_request(drive, 0, 0);
-	return ide_stopped;
-}
-
-static int default_end_request (ide_drive_t *drive, int uptodate, int nr_sects)
-{
-	return ide_end_request(drive, uptodate, nr_sects);
-}
-
-static ide_startstop_t
-default_error(ide_drive_t *drive, struct request *rq, u8 stat, u8 err)
-{
-	return __ide_error(drive, rq, stat, err);
-}
-
-static void default_pre_reset (ide_drive_t *drive)
-{
-}
-
-static sector_t default_capacity (ide_drive_t *drive)
-{
-	return 0x7fffffff;
-}
-
-static ide_startstop_t default_special (ide_drive_t *drive)
-{
-	special_t *s = &drive->special;
-
-	s->all = 0;
-	drive->mult_req = 0;
-	return ide_stopped;
-}
-
-static ide_startstop_t default_abort(ide_drive_t *drive, struct request *rq)
-{
-	return __ide_abort(drive, rq);
-}
-
-static ide_startstop_t default_start_power_step(ide_drive_t *drive,
-						struct request *rq)
-{
-	rq->pm->pm_step = ide_pm_state_completed;
-	return ide_stopped;
-}
-
-static void setup_driver_defaults (ide_driver_t *d)
-{
-	BUG_ON(d->attach == NULL || d->cleanup == NULL);
-
-	if (d->do_request == NULL)	d->do_request = default_do_request;
-	if (d->end_request == NULL)	d->end_request = default_end_request;
-	if (d->error == NULL)		d->error = default_error;
-	if (d->abort == NULL)		d->abort = default_abort;
-	if (d->pre_reset == NULL)	d->pre_reset = default_pre_reset;
-	if (d->capacity == NULL)	d->capacity = default_capacity;
-	if (d->special == NULL)		d->special = default_special;
-	if (d->start_power_step == NULL)
-		d->start_power_step = default_start_power_step;
-}
-
 int ide_register_subdriver(ide_drive_t *drive, ide_driver_t *driver)
 {
 	unsigned long flags;
@@ -2109,10 +2042,8 @@
 		drive->nice1 = 1;
 	}
 #ifdef CONFIG_PROC_FS
-	if (drive->driver != &idedefault_driver) {
-		ide_add_proc_entries(drive->proc, generic_subdriver_entries, drive);
+	if (drive->driver != &idedefault_driver)
 		ide_add_proc_entries(drive->proc, driver->proc, drive);
-	}
 #endif
 	return 0;
 }
@@ -2146,7 +2077,6 @@
 	}
 #ifdef CONFIG_PROC_FS
 	ide_remove_proc_entries(drive->proc, DRIVER(drive)->proc);
-	ide_remove_proc_entries(drive->proc, generic_subdriver_entries);
 #endif
 	auto_remove_settings(drive);
 	drive->driver = &idedefault_driver;
@@ -2184,8 +2114,6 @@
 	struct list_head list;
 	struct list_head *list_loop;
 	struct list_head *tmp_storage;
-
-	setup_driver_defaults(driver);
 
 	spin_lock(&drivers_lock);
 	list_add(&driver->drivers, &drivers);
diff -Nru a/drivers/ide/pci/sgiioc4.c b/drivers/ide/pci/sgiioc4.c
--- a/drivers/ide/pci/sgiioc4.c	2005-03-11 12:51:46 -08:00
+++ b/drivers/ide/pci/sgiioc4.c	2005-03-11 12:51:46 -08:00
@@ -34,6 +34,7 @@
 #include <linux/mm.h>
 #include <linux/ioport.h>
 #include <linux/blkdev.h>
+#include <linux/ioc4_common.h>
 #include <asm/io.h>
 
 #include <linux/ide.h>
@@ -684,23 +685,14 @@
 	unsigned int class_rev;
 	int ret;
 
-	ret = pci_enable_device(dev);
-	if (ret < 0) {
-		printk(KERN_ERR
-		       "Failed to enable device %s at slot %s\n",
-		       d->name, dev->slot_name);
-		goto out;
-	}
-	pci_set_master(dev);
-
 	pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev);
 	class_rev &= 0xff;
 	printk(KERN_INFO "%s: IDE controller at PCI slot %s, revision %d\n",
-			d->name, dev->slot_name, class_rev);
+			d->name, pci_name(dev), class_rev);
 	if (class_rev < IOC4_SUPPORTED_FIRMWARE_REV) {
 		printk(KERN_ERR "Skipping %s IDE controller in slot %s: "
 			"firmware is obsolete - please upgrade to revision"
-			"46 or higher\n", d->name, dev->slot_name);
+			"46 or higher\n", d->name, pci_name(dev));
 		ret = -EAGAIN;
 		goto out;
 	}
@@ -722,34 +714,15 @@
 	}
 };
 
-static int __devinit
-sgiioc4_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+int
+ioc4_ide_attach_one(struct pci_dev *dev, const struct pci_device_id *id)
 {
-	pci_init_sgiioc4(dev, &sgiioc4_chipsets[id->driver_data]);
-	return 0;
+	return pci_init_sgiioc4(dev, &sgiioc4_chipsets[id->driver_data]);
 }
 
-static struct pci_device_id sgiioc4_pci_tbl[] = {
-	{PCI_VENDOR_ID_SGI, PCI_DEVICE_ID_SGI_IOC4, PCI_ANY_ID,
-	 PCI_ANY_ID, 0x0b4000, 0xFFFFFF, 0},
-	{0}
-};
-MODULE_DEVICE_TABLE(pci, sgiioc4_pci_tbl);
-
-static struct pci_driver __devinitdata driver = {
-	.name = "SGI-IOC4_IDE",
-	.id_table = sgiioc4_pci_tbl,
-	.probe = sgiioc4_init_one,
-};
-
-static int __devinit
-sgiioc4_ide_init(void)
-{
-	return ide_pci_register_driver(&driver);
-}
-
-module_init(sgiioc4_ide_init);
 
 MODULE_AUTHOR("Aniket Malatpure - Silicon Graphics Inc. (SGI)");
-MODULE_DESCRIPTION("PCI driver module for SGI IOC4 Base-IO Card");
+MODULE_DESCRIPTION("IDE PCI driver module for SGI IOC4 Base-IO Card");
 MODULE_LICENSE("GPL");
+
+EXPORT_SYMBOL(ioc4_ide_attach_one);
diff -Nru a/drivers/ieee1394/Kconfig b/drivers/ieee1394/Kconfig
--- a/drivers/ieee1394/Kconfig	2005-03-11 12:51:41 -08:00
+++ b/drivers/ieee1394/Kconfig	2005-03-11 12:51:41 -08:00
@@ -5,6 +5,7 @@
 config IEEE1394
 	tristate "IEEE 1394 (FireWire) support"
 	depends on PCI || BROKEN
+	select NET
 	help
 	  IEEE 1394 describes a high performance serial bus, which is also
 	  known as FireWire(tm) or i.Link(tm) and is used for connecting all
diff -Nru a/drivers/ieee1394/amdtp.c b/drivers/ieee1394/amdtp.c
--- a/drivers/ieee1394/amdtp.c	2005-03-11 12:51:47 -08:00
+++ b/drivers/ieee1394/amdtp.c	2005-03-11 12:51:47 -08:00
@@ -286,7 +286,7 @@
 #define OHCI1394_CONTEXT_DEAD        0x00000800
 #define OHCI1394_CONTEXT_ACTIVE      0x00000400
 
-void ohci1394_start_it_ctx(struct ti_ohci *ohci, int ctx,
+static void ohci1394_start_it_ctx(struct ti_ohci *ohci, int ctx,
 			   dma_addr_t first_cmd, int z, int cycle_match)
 {
 	reg_write(ohci, OHCI1394_IsoXmitIntMaskSet, 1 << ctx);
@@ -298,13 +298,13 @@
 		  OHCI1394_CONTEXT_RUN);
 }
 
-void ohci1394_wake_it_ctx(struct ti_ohci *ohci, int ctx)
+static void ohci1394_wake_it_ctx(struct ti_ohci *ohci, int ctx)
 {
 	reg_write(ohci, OHCI1394_IsoXmitContextControlSet + ctx * 16,
 		  OHCI1394_CONTEXT_WAKE);
 }
 
-void ohci1394_stop_it_ctx(struct ti_ohci *ohci, int ctx, int synchronous)
+static void ohci1394_stop_it_ctx(struct ti_ohci *ohci, int ctx, int synchronous)
 {
 	u32 control;
 	int wait;
@@ -530,7 +530,7 @@
 	return frac->integer + (frac->numerator > 0 ? 1 : 0);
 }
 
-void packet_initialize(struct packet *p, struct packet *next)
+static void packet_initialize(struct packet *p, struct packet *next)
 {
 	/* Here we initialize the dma descriptor block for
 	 * transferring one iso packet.  We use two descriptors per
@@ -559,7 +559,7 @@
 	p->db->payload_desc.status = 0;
 }
 
-struct packet_list *packet_list_alloc(struct stream *s)
+static struct packet_list *packet_list_alloc(struct stream *s)
 {
 	int i;
 	struct packet_list *pl;
@@ -588,7 +588,7 @@
 	return pl;
 }
 
-void packet_list_free(struct packet_list *pl, struct stream *s)
+static void packet_list_free(struct packet_list *pl, struct stream *s)
 {
 	int i;
 
@@ -1010,7 +1010,7 @@
 	return 0;
 }
 
-struct stream *stream_alloc(struct amdtp_host *host)
+static struct stream *stream_alloc(struct amdtp_host *host)
 {
 	struct stream *s;
 	unsigned long flags;
@@ -1062,7 +1062,7 @@
 	return s;
 }
 
-void stream_free(struct stream *s)
+static void stream_free(struct stream *s)
 {
 	unsigned long flags;
 
diff -Nru a/drivers/ieee1394/config_roms.c b/drivers/ieee1394/config_roms.c
--- a/drivers/ieee1394/config_roms.c	2005-03-11 12:51:41 -08:00
+++ b/drivers/ieee1394/config_roms.c	2005-03-11 12:51:41 -08:00
@@ -67,8 +67,8 @@
 	ret = csr1212_associate_keyval(vend_id, text);
 	csr1212_release_keyval(text);
 	ret |= csr1212_attach_keyval_to_directory(root, vend_id);
+	csr1212_release_keyval(vend_id);
 	if (ret != CSR1212_SUCCESS) {
-		csr1212_release_keyval(vend_id);
 		csr1212_destroy_csr(host->csr.rom);
 		return -ENOMEM;
 	}
diff -Nru a/drivers/ieee1394/csr1212.c b/drivers/ieee1394/csr1212.c
--- a/drivers/ieee1394/csr1212.c	2005-03-11 12:51:47 -08:00
+++ b/drivers/ieee1394/csr1212.c	2005-03-11 12:51:47 -08:00
@@ -87,7 +87,8 @@
 
 static inline void free_keyval(struct csr1212_keyval *kv)
 {
-	if (kv->key.type == CSR1212_KV_TYPE_LEAF)
+	if ((kv->key.type == CSR1212_KV_TYPE_LEAF) &&
+	    (kv->key.id != CSR1212_KV_ID_EXTENDED_ROM))
 		CSR1212_FREE(kv->value.leaf.data);
 
 	CSR1212_FREE(kv);
@@ -155,7 +156,7 @@
 {
 	struct csr1212_keyval *kv;
 
-	for (kv = kv_list; kv != NULL; kv = kv->next) {
+	for (kv = kv_list->next; kv && (kv != kv_list); kv = kv->next) {
 		if (kv->offset == offset)
 			return kv;
 	}
@@ -181,9 +182,9 @@
 		return NULL;
 	}
 
-        /* The keyval key id is not used for the root node, but a valid key id
-         * that can be used for a directory needs to be passed to
-         * csr1212_new_directory(). */
+	/* The keyval key id is not used for the root node, but a valid key id
+	 * that can be used for a directory needs to be passed to
+	 * csr1212_new_directory(). */
 	csr->root_kv = csr1212_new_directory(CSR1212_KV_ID_VENDOR);
 	if (!csr->root_kv) {
 		CSR1212_FREE(csr->cache_head);
@@ -709,7 +710,7 @@
 					tail->next = k->value.directory.dentries_head;
 					k->value.directory.dentries_head->prev = tail;
 					tail = k->value.directory.dentries_tail;
-                                }
+				}
 			}
 			free_keyval(k);
 			k = a;
@@ -796,7 +797,8 @@
 		return CSR1212_ENOMEM;
 	}
 	cache->ext_rom->offset = csr_addr - CSR1212_REGISTER_SPACE_BASE;
-	cache->ext_rom->value.leaf.len = 0;
+	cache->ext_rom->value.leaf.len = -1;
+	cache->ext_rom->value.leaf.data = cache->data;
 
 	/* Add cache to tail of cache list */
 	cache->prev = csr->cache_tail;
@@ -864,20 +866,20 @@
 			default:
 			case CSR1212_KV_TYPE_IMMEDIATE:
 			case CSR1212_KV_TYPE_CSR_OFFSET:
-				continue;
+				break;
 			case CSR1212_KV_TYPE_LEAF:
 			case CSR1212_KV_TYPE_DIRECTORY:
 				/* Remove from list */
-				if (dkv->prev)
+				if (dkv->prev && (dkv->prev->next == dkv))
 					dkv->prev->next = dkv->next;
-				if (dkv->next)
+				if (dkv->next && (dkv->next->prev == dkv))
 					dkv->next->prev = dkv->prev;
-				if (dkv == *layout_tail)
-					*layout_tail = dkv->prev;
+				//if (dkv == *layout_tail)
+				//	*layout_tail = dkv->prev;
 
 				/* Special case: Extended ROM leafs */
 				if (dkv->key.id == CSR1212_KV_ID_EXTENDED_ROM) {
-					dkv->value.leaf.len = 0; /* initialize to zero */
+					dkv->value.leaf.len = -1;
 					/* Don't add Extended ROM leafs in the layout list,
 					 * they are handled differently. */
 					break;
@@ -919,8 +921,8 @@
 }
 
 struct csr1212_keyval *csr1212_generate_positions(struct csr1212_csr_rom_cache *cache,
-                                                  struct csr1212_keyval *start_kv,
-                                                  int start_pos)
+						  struct csr1212_keyval *start_kv,
+						  int start_pos)
 {
 	struct csr1212_keyval *kv = start_kv;
 	struct csr1212_keyval *okv = start_kv;
@@ -930,7 +932,10 @@
 	cache->layout_head = kv;
 
 	while(kv && pos < cache->size) {
-		kv->offset = cache->offset + pos;
+		/* Special case: Extended ROM leafs */
+		if (kv->key.id != CSR1212_KV_ID_EXTENDED_ROM) {
+			kv->offset = cache->offset + pos;
+		}
 
 		switch(kv->key.type) {
 		case CSR1212_KV_TYPE_LEAF:
@@ -1090,6 +1095,9 @@
 	bi->crc_length = bi->length;
 	bi->crc = csr1212_crc16(bi->data, bi->crc_length);
 
+	csr->root_kv->next = NULL;
+	csr->root_kv->prev = NULL;
+
 	agg_size = csr1212_generate_layout_order(csr->root_kv);
 
 	init_offset = csr->bus_info_len;
@@ -1158,6 +1166,17 @@
 
 		/* Copy the data into the cache buffer */
 		csr1212_fill_cache(cache);
+
+		if (cache != csr->cache_head) {
+			/* Set the length and CRC of the extended ROM. */
+			struct csr1212_keyval_img *kvi =
+				(struct csr1212_keyval_img*)cache->data;
+
+			kvi->length = CSR1212_CPU_TO_BE16(bytes_to_quads(cache->len) - 1);
+			kvi->crc = csr1212_crc16(kvi->data,
+						 bytes_to_quads(cache->len) - 1);
+
+		}
 	}
 
 	return CSR1212_SUCCESS;
@@ -1174,11 +1193,6 @@
 			       &cache->data[bytes_to_quads(offset - cache->offset)],
 			       len);
 			return CSR1212_SUCCESS;
-		} else if (((offset < cache->offset) &&
-			    ((offset + len) >= cache->offset)) ||
-			   ((offset >= cache->offset) &&
-			    ((offset + len) > (cache->offset + cache->size)))) {
-			return CSR1212_EINVAL;
 		}
 	}
 	return CSR1212_ENOENT;
@@ -1227,8 +1241,8 @@
 		return CSR1212_EINVAL;
 
 #if 0
-        /* Apparently there are too many differnt wrong implementations of the
-         * CRC algorithm that verifying them is moot. */
+	/* Apparently there are too many differnt wrong implementations of the
+	 * CRC algorithm that verifying them is moot. */
 	if ((csr1212_crc16(bi->data, bi->crc_length) != bi->crc) &&
 	    (csr1212_msft_crc16(bi->data, bi->crc_length) != bi->crc))
 		return CSR1212_EINVAL;
@@ -1249,10 +1263,9 @@
 	return CSR1212_SUCCESS;
 }
 
-static inline int csr1212_parse_dir_entry(struct csr1212_keyval *dir,
-					  csr1212_quad_t ki,
-					  u_int32_t kv_pos,
-					  struct csr1212_csr_rom_cache *cache)
+static int csr1212_parse_dir_entry(struct csr1212_keyval *dir,
+				   csr1212_quad_t ki,
+				   u_int32_t kv_pos)
 {
 	int ret = CSR1212_SUCCESS;
 	struct csr1212_keyval *k = NULL;
@@ -1291,7 +1304,7 @@
 			goto fail;
 		}
 
-		k = csr1212_find_keyval_offset(cache->layout_head, offset);
+		k = csr1212_find_keyval_offset(dir, offset);
 
 		if (k)
 			break;		/* Found it. */
@@ -1309,11 +1322,10 @@
 		k->valid = 0;	/* Contents not read yet so it's not valid. */
 		k->offset = offset;
 
-		k->prev = cache->layout_tail;
-		k->next = NULL;
-		if (cache->layout_tail)
-			cache->layout_tail->next = k;
-		cache->layout_tail = k;
+		k->prev = dir;
+		k->next = dir->next;
+		dir->next->prev = k;
+		dir->next = k;
 	}
 	ret = csr1212_attach_keyval_to_directory(dir, k);
 
@@ -1325,6 +1337,7 @@
 	return ret;
 }
 
+
 int csr1212_parse_keyval(struct csr1212_keyval *kv,
 			 struct csr1212_csr_rom_cache *cache)
 {
@@ -1338,8 +1351,8 @@
 	kvi_len = CSR1212_BE16_TO_CPU(kvi->length);
 
 #if 0
-        /* Apparently there are too many differnt wrong implementations of the
-         * CRC algorithm that verifying them is moot. */
+	/* Apparently there are too many differnt wrong implementations of the
+	 * CRC algorithm that verifying them is moot. */
 	if ((csr1212_crc16(kvi->data, kvi_len) != kvi->crc) &&
 	    (csr1212_msft_crc16(kvi->data, kvi_len) != kvi->crc)) {
 		ret = CSR1212_EINVAL;
@@ -1353,22 +1366,19 @@
 			csr1212_quad_t ki = kvi->data[i];
 
 			/* Some devices put null entries in their unit
-			 * directories.  If we come across such and entry,
+			 * directories.  If we come across such an entry,
 			 * then skip it. */
 			if (ki == 0x0)
 				continue;
 			ret = csr1212_parse_dir_entry(kv, ki,
 						      (kv->offset +
-						       quads_to_bytes(i + 1)),
-						      cache);
+						       quads_to_bytes(i + 1)));
 		}
 		kv->value.directory.len = kvi_len;
 		break;
 
 	case CSR1212_KV_TYPE_LEAF:
-		if (kv->key.id == CSR1212_KV_ID_EXTENDED_ROM) {
-			kv->value.leaf.data = cache->data;
-		} else {
+		if (kv->key.id != CSR1212_KV_ID_EXTENDED_ROM) {
 			kv->value.leaf.data = CSR1212_MALLOC(quads_to_bytes(kvi_len));
 			if (!kv->value.leaf.data)
 			{
@@ -1399,7 +1409,6 @@
 	u_int32_t *cache_ptr;
 	u_int16_t kv_len = 0;
 
-
 	if (!csr || !kv)
 		return CSR1212_EINVAL;
 
@@ -1413,7 +1422,7 @@
 
 	if (!cache) {
 		csr1212_quad_t q;
-		struct csr1212_csr_rom_cache *nc;
+		u_int32_t cache_size;
 
 		/* Only create a new cache for Extended ROM leaves. */
 		if (kv->key.id != CSR1212_KV_ID_EXTENDED_ROM)
@@ -1425,12 +1434,20 @@
 			return CSR1212_EIO;
 		}
 
-		kv->value.leaf.len = quads_to_bytes(CSR1212_BE32_TO_CPU(q)>>16);
+		kv->value.leaf.len = CSR1212_BE32_TO_CPU(q) >> 16;
+
+		cache_size = (quads_to_bytes(kv->value.leaf.len + 1) +
+			      (csr->max_rom - 1)) & ~(csr->max_rom - 1);
 
-		nc = csr1212_rom_cache_malloc(kv->offset, kv->value.leaf.len);
-		cache->next = nc;
-		nc->prev = cache;
-		csr->cache_tail = nc;
+		cache = csr1212_rom_cache_malloc(kv->offset, cache_size);
+		if (!cache)
+			return CSR1212_ENOMEM;
+
+		kv->value.leaf.data = &cache->data[1];
+		csr->cache_tail->next = cache;
+		cache->prev = csr->cache_tail;
+		cache->next = NULL;
+		csr->cache_tail = cache;
 		cache->filled_head =
 			CSR1212_MALLOC(sizeof(struct csr1212_cache_region));
 		if (!cache->filled_head) {
@@ -1443,6 +1460,10 @@
 		cache->filled_head->next = NULL;
 		cache->filled_head->prev = NULL;
 		cache->data[0] = q;
+
+		/* Don't read the entire extended ROM now.  Pieces of it will
+		 * be read when entries inside it are read. */
+		return csr1212_parse_keyval(kv, cache);
 	}
 
 	cache_index = kv->offset - cache->offset;
@@ -1548,6 +1569,7 @@
 int csr1212_parse_csr(struct csr1212_csr *csr)
 {
 	static const int mr_map[] = { 4, 64, 1024, 0 };
+	struct csr1212_dentry *dentry;
 	int ret;
 
 	if (!csr || !csr->ops->bus_read)
@@ -1570,7 +1592,21 @@
 		csr->bus_info_len;
 
 	csr->root_kv->valid = 0;
+	csr->root_kv->next = csr->root_kv;
+	csr->root_kv->prev = csr->root_kv;
 	csr1212_get_keyval(csr, csr->root_kv);
+
+	/* Scan through the Root directory finding all extended ROM regions
+	 * and make cache regions for them */
+	for (dentry = csr->root_kv->value.directory.dentries_head;
+	     dentry; dentry = dentry->next) {
+		if (dentry->kv->key.id == CSR1212_KV_ID_EXTENDED_ROM) {
+			csr1212_get_keyval(csr, dentry->kv);
+
+			if (ret != CSR1212_SUCCESS)
+				return ret;
+		}
+	}
 
 	return CSR1212_SUCCESS;
 }
diff -Nru a/drivers/ieee1394/dma.c b/drivers/ieee1394/dma.c
--- a/drivers/ieee1394/dma.c	2005-03-11 12:51:46 -08:00
+++ b/drivers/ieee1394/dma.c	2005-03-11 12:51:46 -08:00
@@ -127,16 +127,12 @@
 		dma->dev = NULL;
 	}
 
-	if (dma->sglist) {
-		vfree(dma->sglist);
-		dma->sglist = NULL;
-	}
+	vfree(dma->sglist);
+	dma->sglist = NULL;
 
-	if (dma->kvirt) {
-		vfree(dma->kvirt);
-		dma->kvirt = NULL;
-		dma->n_pages = 0;
-	}
+	vfree(dma->kvirt);
+	dma->kvirt = NULL;
+	dma->n_pages = 0;
 }
 
 /* find the scatterlist index and remaining offset corresponding to a
diff -Nru a/drivers/ieee1394/dv1394.c b/drivers/ieee1394/dv1394.c
--- a/drivers/ieee1394/dv1394.c	2005-03-11 12:51:47 -08:00
+++ b/drivers/ieee1394/dv1394.c	2005-03-11 12:51:47 -08:00
@@ -1277,7 +1277,7 @@
 	error-prone code in dv1394.
 */
 
-int dv1394_mmap(struct file *file, struct vm_area_struct *vma)
+static int dv1394_mmap(struct file *file, struct vm_area_struct *vma)
 {
 	struct video_card *video = file_to_video_card(file);
 	int retval = -EINVAL;
@@ -2343,6 +2343,8 @@
 			dv1394_un_init(video);
 	} while (video != NULL);
 
+	class_simple_device_remove(MKDEV(
+		IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_DV1394 * 16 + (id<<2)));
 	devfs_remove("ieee1394/dv/host%d/NTSC", id);
 	devfs_remove("ieee1394/dv/host%d/PAL", id);
 	devfs_remove("ieee1394/dv/host%d", id);
@@ -2359,6 +2361,9 @@
 
 	ohci = (struct ti_ohci *)host->hostdata;
 
+	class_simple_device_add(hpsb_protocol_class, MKDEV(
+		IEEE1394_MAJOR,	IEEE1394_MINOR_BLOCK_DV1394 * 16 + (id<<2)), 
+		NULL, "dv1394-%d", id);
 	devfs_mk_dir("ieee1394/dv/host%d", id);
 	devfs_mk_dir("ieee1394/dv/host%d/NTSC", id);
 	devfs_mk_dir("ieee1394/dv/host%d/PAL", id);
diff -Nru a/drivers/ieee1394/eth1394.c b/drivers/ieee1394/eth1394.c
--- a/drivers/ieee1394/eth1394.c	2005-03-11 12:51:47 -08:00
+++ b/drivers/ieee1394/eth1394.c	2005-03-11 12:51:47 -08:00
@@ -89,7 +89,7 @@
 #define TRACE() printk(KERN_ERR "%s:%s[%d] ---- TRACE\n", driver_name, __FUNCTION__, __LINE__)
 
 static char version[] __devinitdata =
-	"$Rev: 1224 $ Ben Collins <bcollins@debian.org>";
+	"$Rev: 1247 $ Ben Collins <bcollins@debian.org>";
 
 struct fragment_info {
 	struct list_head list;
@@ -165,8 +165,7 @@
 /* The max_partial_datagrams parameter is the maximum number of fragmented
  * datagrams per node that eth1394 will keep in memory.  Providing an upper
  * bound allows us to limit the amount of memory that partial datagrams
- * consume in the event that some partial datagrams are never completed.  This
- * should probably change to a sysctl item or the like if possible.
+ * consume in the event that some partial datagrams are never completed.
  */
 static int max_partial_datagrams = 25;
 module_param(max_partial_datagrams, int, S_IRUGO | S_IWUSR);
@@ -186,7 +185,7 @@
 					  unsigned char * haddr);
 static int ether1394_mac_addr(struct net_device *dev, void *p);
 
-static inline void purge_partial_datagram(struct list_head *old);
+static void purge_partial_datagram(struct list_head *old);
 static int ether1394_tx(struct sk_buff *skb, struct net_device *dev);
 static void ether1394_iso(struct hpsb_iso *iso);
 
@@ -289,7 +288,7 @@
 	return 0;
 }
 
-static inline void purge_partial_datagram(struct list_head *old)
+static void purge_partial_datagram(struct list_head *old)
 {
 	struct partial_datagram *pd = list_entry(old, struct partial_datagram, list);
 	struct list_head *lh, *n;
@@ -449,7 +448,7 @@
 		if (!node_info) {
 			kfree(node);
 			return -ENOMEM;
-                }
+		}
 
 		spin_lock_init(&node_info->pdg.lock);
 		INIT_LIST_HEAD(&node_info->pdg.list);
@@ -1187,7 +1186,7 @@
 		lh = find_partial_datagram(pdgl, dgl);
 
 		if (lh == NULL) {
-			if (pdg->sz == max_partial_datagrams) {
+			while (pdg->sz >= max_partial_datagrams) {
 				/* remove the oldest */
 				purge_partial_datagram(pdgl->prev);
 				pdg->sz--;
@@ -1583,7 +1582,7 @@
 	struct sk_buff *skb = ptask->skb;
 	struct net_device *dev = skb->dev;
 	struct eth1394_priv *priv = netdev_priv(dev);
-        unsigned long flags;
+	unsigned long flags;
 
 	/* Statistics */
 	spin_lock_irqsave(&priv->lock, flags);
@@ -1771,7 +1770,7 @@
 static void ether1394_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
 {
 	strcpy (info->driver, driver_name);
-	strcpy (info->version, "$Rev: 1224 $");
+	strcpy (info->version, "$Rev: 1247 $");
 	/* FIXME XXX provide sane businfo */
 	strcpy (info->bus_info, "ieee1394");
 }
diff -Nru a/drivers/ieee1394/highlevel.c b/drivers/ieee1394/highlevel.c
--- a/drivers/ieee1394/highlevel.c	2005-03-11 12:51:51 -08:00
+++ b/drivers/ieee1394/highlevel.c	2005-03-11 12:51:51 -08:00
@@ -173,18 +173,6 @@
 }
 
 
-unsigned long hpsb_get_hostinfo_key(struct hpsb_highlevel *hl, struct hpsb_host *host)
-{
-	struct hl_host_info *hi;
-
-	hi = hl_get_hostinfo(hl, host);
-	if (hi)
-		return hi->key;
-
-	return 0;
-}
-
-
 void *hpsb_get_hostinfo_bykey(struct hpsb_highlevel *hl, unsigned long key)
 {
 	struct hl_host_info *hi;
@@ -206,26 +194,6 @@
 }
 
 
-struct hpsb_host *hpsb_get_host_bykey(struct hpsb_highlevel *hl, unsigned long key)
-{
-	struct hl_host_info *hi;
-	struct hpsb_host *host = NULL;
-
-	if (!hl)
-		return NULL;
-
-	read_lock(&hl->host_info_lock);
-	list_for_each_entry(hi, &hl->host_info_list, list) {
-		if (hi->key == key) {
-			host = hi->host;
-			break;
-		}
-	}
-	read_unlock(&hl->host_info_lock);
-
-	return host;
-}
-
 static int highlevel_for_each_host_reg(struct hpsb_host *host, void *__data)
 {
 	struct hpsb_highlevel *hl = __data;
@@ -416,7 +384,7 @@
         }
 
         as = (struct hpsb_address_serve *)
-                kmalloc(sizeof(struct hpsb_address_serve), GFP_KERNEL);
+                kmalloc(sizeof(struct hpsb_address_serve), GFP_ATOMIC);
         if (as == NULL) {
                 return 0;
         }
diff -Nru a/drivers/ieee1394/ieee1394.h b/drivers/ieee1394/ieee1394.h
--- a/drivers/ieee1394/ieee1394.h	2005-03-11 12:51:42 -08:00
+++ b/drivers/ieee1394/ieee1394.h	2005-03-11 12:51:42 -08:00
@@ -77,6 +77,30 @@
 #define SELFID_PORT_NONE         0x0
 
 
+/* 1394a PHY bitmasks */
+#define PHY_00_PHYSICAL_ID       0xFC
+#define PHY_00_R                 0x02 /* Root */
+#define PHY_00_PS                0x01 /* Power Status*/
+#define PHY_01_RHB               0x80 /* Root Hold-Off */
+#define PHY_01_IBR               0x80 /* Initiate Bus Reset */
+#define PHY_01_GAP_COUNT         0x3F
+#define PHY_02_EXTENDED          0xE0 /* 0x7 for 1394a-compliant PHY */
+#define PHY_02_TOTAL_PORTS       0x1F
+#define PHY_03_MAX_SPEED         0xE0
+#define PHY_03_DELAY             0x0F
+#define PHY_04_LCTRL             0x80 /* Link Active Report Control */
+#define PHY_04_CONTENDER         0x40
+#define PHY_04_JITTER            0x38
+#define PHY_04_PWR_CLASS         0x07 /* Power Class */
+#define PHY_05_WATCHDOG          0x80
+#define PHY_05_ISBR              0x40 /* Initiate Short Bus Reset */
+#define PHY_05_LOOP              0x20 /* Loop Detect */
+#define PHY_05_PWR_FAIL          0x10 /* Cable Power Failure Detect */
+#define PHY_05_TIMEOUT           0x08 /* Arbitration State Machine Timeout */
+#define PHY_05_PORT_EVENT        0x04 /* Port Event Detect */
+#define PHY_05_ENAB_ACCEL        0x02 /* Enable Arbitration Acceleration */
+#define PHY_05_ENAB_MULTI        0x01 /* Ena. Multispeed Packet Concatenation */
+
 #include <asm/byteorder.h>
 
 #ifdef __BIG_ENDIAN_BITFIELD
diff -Nru a/drivers/ieee1394/ieee1394_core.c b/drivers/ieee1394/ieee1394_core.c
--- a/drivers/ieee1394/ieee1394_core.c	2005-03-11 12:51:42 -08:00
+++ b/drivers/ieee1394/ieee1394_core.c	2005-03-11 12:51:42 -08:00
@@ -56,11 +56,18 @@
 module_param(disable_nodemgr, int, 0444);
 MODULE_PARM_DESC(disable_nodemgr, "Disable nodemgr functionality.");
 
+/* Disable Isochronous Resource Manager functionality */
+int hpsb_disable_irm = 0;
+module_param_named(disable_irm, hpsb_disable_irm, bool, 0);
+MODULE_PARM_DESC(disable_irm,
+		 "Disable Isochronous Resource Manager functionality.");
+
 /* We are GPL, so treat us special */
 MODULE_LICENSE("GPL");
 
 /* Some globals used */
 const char *hpsb_speedto_str[] = { "S100", "S200", "S400", "S800", "S1600", "S3200" };
+struct class_simple *hpsb_protocol_class;
 
 #ifdef CONFIG_IEEE1394_VERBOSEDEBUG
 static void dump_packet(const char *text, quadlet_t *data, int size)
@@ -79,6 +86,7 @@
 #define dump_packet(x,y,z)
 #endif
 
+static void abort_requests(struct hpsb_host *host);
 static void queue_packet_complete(struct hpsb_packet *packet);
 
 
@@ -512,6 +520,7 @@
 
 	if (!packet->no_waiter || packet->expect_response) {
 		atomic_inc(&packet->refcnt);
+		packet->sendtime = jiffies;
 		skb_queue_tail(&host->pending_packet_queue, packet->skb);
 	}
 
@@ -939,7 +948,7 @@
 }
 
 
-void abort_requests(struct hpsb_host *host)
+static void abort_requests(struct hpsb_host *host)
 {
 	struct hpsb_packet *packet;
 	struct sk_buff *skb;
@@ -1002,7 +1011,7 @@
  * the stack. */
 static int khpsbpkt_pid = -1, khpsbpkt_kill;
 static DECLARE_COMPLETION(khpsbpkt_complete);
-struct sk_buff_head hpsbpkt_queue;
+static struct sk_buff_head hpsbpkt_queue;
 static DECLARE_MUTEX_LOCKED(khpsbpkt_sig);
 
 
@@ -1030,15 +1039,19 @@
 
 	daemonize("khpsbpkt");
 
-	while (!down_interruptible(&khpsbpkt_sig)) {
-		if (khpsbpkt_kill)
+	while (1) {
+		if (down_interruptible(&khpsbpkt_sig)) {
+			if (current->flags & PF_FREEZE) {
+				refrigerator(0);
+				continue;
+			}
+			printk("khpsbpkt: received unexpected signal?!\n" );
 			break;
-
-		if (current->flags & PF_FREEZE) {
-			refrigerator(0);
-			continue;
 		}
 
+		if (khpsbpkt_kill)
+			break;
+
 		while ((skb = skb_dequeue(&hpsbpkt_queue)) != NULL) {
 			packet = (struct hpsb_packet *)skb->data;
 
@@ -1054,7 +1067,6 @@
 	complete_and_exit(&khpsbpkt_complete, 0);
 }
 
-
 static int __init ieee1394_init(void)
 {
 	int i, ret;
@@ -1109,18 +1121,33 @@
 	if (ret < 0)
 		goto release_all_bus;
 
+	hpsb_protocol_class = class_simple_create(THIS_MODULE, "ieee1394_protocol");
+	if (IS_ERR(hpsb_protocol_class)) {
+		ret = PTR_ERR(hpsb_protocol_class);
+		goto release_class_host;
+	}
+
 	ret = init_csr();
 	if (ret) {
 		HPSB_INFO("init csr failed");
 		ret = -ENOMEM;
-		goto release_class;
+		goto release_class_protocol;
 	}
 
 	if (disable_nodemgr) {
-		HPSB_INFO("nodemgr functionality disabled");
+		HPSB_INFO("nodemgr and IRM functionality disabled");
+		/* We shouldn't contend for IRM with nodemgr disabled, since
+		   nodemgr implements functionality required of ieee1394a-2000
+		   IRMs */
+		hpsb_disable_irm = 1;
+                      
 		return 0;
 	}
 
+	if (hpsb_disable_irm) {
+		HPSB_INFO("IRM functionality disabled");
+	}
+
 	ret = init_ieee1394_nodemgr();
 	if (ret < 0) {
 		HPSB_INFO("init nodemgr failed");
@@ -1131,7 +1158,9 @@
 
 cleanup_csr:
 	cleanup_csr();
-release_class:
+release_class_protocol:
+	class_simple_destroy(hpsb_protocol_class);
+release_class_host:
 	class_unregister(&hpsb_host_class);
 release_all_bus:
 	for (i = 0; fw_bus_attrs[i]; i++)
@@ -1160,6 +1189,7 @@
 
 	cleanup_csr();
 
+	class_simple_destroy(hpsb_protocol_class);
 	class_unregister(&hpsb_host_class);
 	for (i = 0; fw_bus_attrs[i]; i++)
 		bus_remove_file(&ieee1394_bus_type, fw_bus_attrs[i]);
@@ -1191,6 +1221,7 @@
 
 /** ieee1394_core.c **/
 EXPORT_SYMBOL(hpsb_speedto_str);
+EXPORT_SYMBOL(hpsb_protocol_class);
 EXPORT_SYMBOL(hpsb_set_packet_complete_task);
 EXPORT_SYMBOL(hpsb_alloc_packet);
 EXPORT_SYMBOL(hpsb_free_packet);
@@ -1203,6 +1234,7 @@
 EXPORT_SYMBOL(hpsb_selfid_complete);
 EXPORT_SYMBOL(hpsb_packet_sent);
 EXPORT_SYMBOL(hpsb_packet_received);
+EXPORT_SYMBOL_GPL(hpsb_disable_irm);
 
 /** ieee1394_transactions.c **/
 EXPORT_SYMBOL(hpsb_get_tlabel);
@@ -1217,8 +1249,6 @@
 EXPORT_SYMBOL(hpsb_read);
 EXPORT_SYMBOL(hpsb_write);
 EXPORT_SYMBOL(hpsb_lock);
-EXPORT_SYMBOL(hpsb_lock64);
-EXPORT_SYMBOL(hpsb_send_gasp);
 EXPORT_SYMBOL(hpsb_packet_success);
 
 /** highlevel.c **/
@@ -1230,28 +1260,18 @@
 EXPORT_SYMBOL(hpsb_listen_channel);
 EXPORT_SYMBOL(hpsb_unlisten_channel);
 EXPORT_SYMBOL(hpsb_get_hostinfo);
-EXPORT_SYMBOL(hpsb_get_host_bykey);
 EXPORT_SYMBOL(hpsb_create_hostinfo);
 EXPORT_SYMBOL(hpsb_destroy_hostinfo);
 EXPORT_SYMBOL(hpsb_set_hostinfo_key);
-EXPORT_SYMBOL(hpsb_get_hostinfo_key);
 EXPORT_SYMBOL(hpsb_get_hostinfo_bykey);
 EXPORT_SYMBOL(hpsb_set_hostinfo);
-EXPORT_SYMBOL(highlevel_read);
-EXPORT_SYMBOL(highlevel_write);
-EXPORT_SYMBOL(highlevel_lock);
-EXPORT_SYMBOL(highlevel_lock64);
 EXPORT_SYMBOL(highlevel_add_host);
 EXPORT_SYMBOL(highlevel_remove_host);
 EXPORT_SYMBOL(highlevel_host_reset);
 
 /** nodemgr.c **/
-EXPORT_SYMBOL(hpsb_guid_get_entry);
-EXPORT_SYMBOL(hpsb_nodeid_get_entry);
 EXPORT_SYMBOL(hpsb_node_fill_packet);
-EXPORT_SYMBOL(hpsb_node_read);
 EXPORT_SYMBOL(hpsb_node_write);
-EXPORT_SYMBOL(hpsb_node_lock);
 EXPORT_SYMBOL(hpsb_register_protocol);
 EXPORT_SYMBOL(hpsb_unregister_protocol);
 EXPORT_SYMBOL(ieee1394_bus_type);
@@ -1295,27 +1315,14 @@
 EXPORT_SYMBOL(csr1212_create_csr);
 EXPORT_SYMBOL(csr1212_init_local_csr);
 EXPORT_SYMBOL(csr1212_new_immediate);
-EXPORT_SYMBOL(csr1212_new_leaf);
-EXPORT_SYMBOL(csr1212_new_csr_offset);
 EXPORT_SYMBOL(csr1212_new_directory);
 EXPORT_SYMBOL(csr1212_associate_keyval);
 EXPORT_SYMBOL(csr1212_attach_keyval_to_directory);
-EXPORT_SYMBOL(csr1212_new_extended_immediate);
-EXPORT_SYMBOL(csr1212_new_extended_leaf);
-EXPORT_SYMBOL(csr1212_new_descriptor_leaf);
-EXPORT_SYMBOL(csr1212_new_textual_descriptor_leaf);
 EXPORT_SYMBOL(csr1212_new_string_descriptor_leaf);
-EXPORT_SYMBOL(csr1212_new_icon_descriptor_leaf);
-EXPORT_SYMBOL(csr1212_new_modifiable_descriptor_leaf);
-EXPORT_SYMBOL(csr1212_new_keyword_leaf);
 EXPORT_SYMBOL(csr1212_detach_keyval_from_directory);
-EXPORT_SYMBOL(csr1212_disassociate_keyval);
 EXPORT_SYMBOL(csr1212_release_keyval);
 EXPORT_SYMBOL(csr1212_destroy_csr);
 EXPORT_SYMBOL(csr1212_read);
-EXPORT_SYMBOL(csr1212_generate_positions);
-EXPORT_SYMBOL(csr1212_generate_layout_order);
-EXPORT_SYMBOL(csr1212_fill_cache);
 EXPORT_SYMBOL(csr1212_generate_csr_image);
 EXPORT_SYMBOL(csr1212_parse_keyval);
 EXPORT_SYMBOL(csr1212_parse_csr);
diff -Nru a/drivers/ieee1394/ieee1394_core.h b/drivers/ieee1394/ieee1394_core.h
--- a/drivers/ieee1394/ieee1394_core.h	2005-03-11 12:51:41 -08:00
+++ b/drivers/ieee1394/ieee1394_core.h	2005-03-11 12:51:41 -08:00
@@ -89,7 +89,6 @@
 }
 
 void abort_timedouts(unsigned long __opaque);
-void abort_requests(struct hpsb_host *host);
 
 struct hpsb_packet *hpsb_alloc_packet(size_t data_size);
 void hpsb_free_packet(struct hpsb_packet *packet);
@@ -219,9 +218,11 @@
 	return file->f_dentry->d_inode->i_cindex;
 }
 
+extern int hpsb_disable_irm;
 
 /* Our sysfs bus entry */
 extern struct bus_type ieee1394_bus_type;
 extern struct class hpsb_host_class;
+extern struct class_simple *hpsb_protocol_class;
 
 #endif /* _IEEE1394_CORE_H */
diff -Nru a/drivers/ieee1394/ieee1394_transactions.c b/drivers/ieee1394/ieee1394_transactions.c
--- a/drivers/ieee1394/ieee1394_transactions.c	2005-03-11 12:51:42 -08:00
+++ b/drivers/ieee1394/ieee1394_transactions.c	2005-03-11 12:51:42 -08:00
@@ -566,34 +566,6 @@
         return retval;
 }
 
-int hpsb_lock64(struct hpsb_host *host, nodeid_t node, unsigned int generation,
-		u64 addr, int extcode, octlet_t *data, octlet_t arg)
-{
-	struct hpsb_packet *packet;
-	int retval = 0;
-
-	BUG_ON(in_interrupt()); // We can't be called in an interrupt, yet
-
-	packet = hpsb_make_lock64packet(host, node, addr, extcode, data, arg);
-	if (!packet)
-		return -ENOMEM;
-
-	packet->generation = generation;
-	retval = hpsb_send_packet_and_wait(packet);
-	if (retval < 0)
-		goto hpsb_lock64_fail;
-
-	retval = hpsb_packet_success(packet);
-
-	if (retval == 0)
-		*data = (u64)packet->data[1] << 32 | packet->data[0];
-
-hpsb_lock64_fail:
-	hpsb_free_tlabel(packet);
-	hpsb_free_packet(packet);
-
-        return retval;
-}
 
 int hpsb_send_gasp(struct hpsb_host *host, int channel, unsigned int generation,
 		   quadlet_t *buffer, size_t length, u32 specifier_id,
diff -Nru a/drivers/ieee1394/nodemgr.c b/drivers/ieee1394/nodemgr.c
--- a/drivers/ieee1394/nodemgr.c	2005-03-11 12:51:47 -08:00
+++ b/drivers/ieee1394/nodemgr.c	2005-03-11 12:51:47 -08:00
@@ -23,6 +23,7 @@
 
 #include "ieee1394_types.h"
 #include "ieee1394.h"
+#include "ieee1394_core.h"
 #include "hosts.h"
 #include "ieee1394_transactions.h"
 #include "highlevel.h"
@@ -146,7 +147,7 @@
 	put_device(&container_of((class_dev), struct node_entry, class_dev)->device);
 }
 
-struct class nodemgr_ne_class = {
+static struct class nodemgr_ne_class = {
 	.name		= "ieee1394_node",
 	.release	= ne_cls_release,
 };
@@ -158,7 +159,7 @@
 
 /* The name here is only so that unit directory hotplug works with old
  * style hotplug, which only ever did unit directories anyway. */
-struct class nodemgr_ud_class = {
+static struct class nodemgr_ud_class = {
 	.name		= "ieee1394",
 	.release	= ud_cls_release,
 	.hotplug	= nodemgr_hotplug,
@@ -831,6 +832,31 @@
 }
 
 
+static void nodemgr_register_device(struct node_entry *ne, 
+	struct unit_directory *ud, struct device *parent)
+{
+	memcpy(&ud->device, &nodemgr_dev_template_ud,
+	       sizeof(ud->device));
+
+	ud->device.parent = parent;
+
+	snprintf(ud->device.bus_id, BUS_ID_SIZE, "%s-%u",
+		 ne->device.bus_id, ud->id);
+
+	ud->class_dev.dev = &ud->device;
+	ud->class_dev.class = &nodemgr_ud_class;
+	snprintf(ud->class_dev.class_id, BUS_ID_SIZE, "%s-%u",
+		 ne->device.bus_id, ud->id);
+
+	device_register(&ud->device);
+	class_device_register(&ud->class_dev);
+	get_device(&ud->device);
+
+	if (ud->vendor_oui)
+		device_create_file(&ud->device, &dev_attr_ud_vendor_oui);
+	nodemgr_create_ud_dev_files(ud);
+}	
+
 
 /* This implementation currently only scans the config rom and its
  * immediate unit directories looking for software_id and
@@ -840,7 +866,7 @@
 	 unsigned int *id, struct unit_directory *parent)
 {
 	struct unit_directory *ud;
-	struct unit_directory *ud_temp = NULL;
+	struct unit_directory *ud_child = NULL;
 	struct csr1212_dentry *dentry;
 	struct csr1212_keyval *kv;
 	u8 last_key_id = 0;
@@ -907,42 +933,61 @@
 			break;
 
 		case CSR1212_KV_ID_DEPENDENT_INFO:
-			if (kv->key.type == CSR1212_KV_TYPE_DIRECTORY) {
+			/* Logical Unit Number */
+			if (kv->key.type == CSR1212_KV_TYPE_IMMEDIATE) {
+				if (ud->flags & UNIT_DIRECTORY_HAS_LUN) {
+					ud_child = kmalloc(sizeof(struct unit_directory), GFP_KERNEL);
+					if (!ud_child)
+						goto unit_directory_error;
+					memcpy(ud_child, ud, sizeof(struct unit_directory));
+					nodemgr_register_device(ne, ud_child, &ne->device);
+					ud_child = NULL;
+					
+					ud->id = (*id)++;
+				}
+				ud->lun = kv->value.immediate;
+				ud->flags |= UNIT_DIRECTORY_HAS_LUN;
+
+			/* Logical Unit Directory */
+			} else if (kv->key.type == CSR1212_KV_TYPE_DIRECTORY) {
 				/* This should really be done in SBP2 as this is
-				 * doing SBP2 specific parsing. */
+				 * doing SBP2 specific parsing.
+				 */
+				
+				/* first register the parent unit */
 				ud->flags |= UNIT_DIRECTORY_HAS_LUN_DIRECTORY;
-				ud_temp = nodemgr_process_unit_directory(hi, ne, kv, id,
-									 parent);
+				if (ud->device.bus != &ieee1394_bus_type)
+					nodemgr_register_device(ne, ud, &ne->device);
+				
+				/* process the child unit */
+				ud_child = nodemgr_process_unit_directory(hi, ne, kv, id, ud);
 
-				if (ud_temp == NULL)
+				if (ud_child == NULL)
 					break;
-
-				/* inherit unspecified values */
-				if ((ud->flags & UNIT_DIRECTORY_VENDOR_ID) &&
-				    !(ud_temp->flags & UNIT_DIRECTORY_VENDOR_ID))
-				{
-					ud_temp->flags |=  UNIT_DIRECTORY_VENDOR_ID;
-					ud_temp->vendor_id = ud->vendor_id;
-					ud_temp->vendor_oui = ud->vendor_oui;
-				}
+				
+				/* inherit unspecified values so hotplug picks it up */
 				if ((ud->flags & UNIT_DIRECTORY_MODEL_ID) &&
-				    !(ud_temp->flags & UNIT_DIRECTORY_MODEL_ID))
+				    !(ud_child->flags & UNIT_DIRECTORY_MODEL_ID))
 				{
-					ud_temp->flags |=  UNIT_DIRECTORY_MODEL_ID;
-					ud_temp->model_id = ud->model_id;
+					ud_child->flags |=  UNIT_DIRECTORY_MODEL_ID;
+					ud_child->model_id = ud->model_id;
 				}
 				if ((ud->flags & UNIT_DIRECTORY_SPECIFIER_ID) &&
-				    !(ud_temp->flags & UNIT_DIRECTORY_SPECIFIER_ID))
+				    !(ud_child->flags & UNIT_DIRECTORY_SPECIFIER_ID))
 				{
-					ud_temp->flags |=  UNIT_DIRECTORY_SPECIFIER_ID;
-					ud_temp->specifier_id = ud->specifier_id;
+					ud_child->flags |=  UNIT_DIRECTORY_SPECIFIER_ID;
+					ud_child->specifier_id = ud->specifier_id;
 				}
 				if ((ud->flags & UNIT_DIRECTORY_VERSION) &&
-				    !(ud_temp->flags & UNIT_DIRECTORY_VERSION))
+				    !(ud_child->flags & UNIT_DIRECTORY_VERSION))
 				{
-					ud_temp->flags |=  UNIT_DIRECTORY_VERSION;
-					ud_temp->version = ud->version;
+					ud_child->flags |=  UNIT_DIRECTORY_VERSION;
+					ud_child->version = ud->version;
 				}
+				
+				/* register the child unit */
+				ud_child->flags |= UNIT_DIRECTORY_LUN_DIRECTORY;
+				nodemgr_register_device(ne, ud_child, &ud->device);
 			}
 
 			break;
@@ -952,31 +997,10 @@
 		}
 		last_key_id = kv->key.id;
 	}
-
-	memcpy(&ud->device, &nodemgr_dev_template_ud,
-	       sizeof(ud->device));
-
-	if (parent) {
-		ud->flags |= UNIT_DIRECTORY_LUN_DIRECTORY;
-		ud->device.parent = &parent->device;
-	} else
-		ud->device.parent = &ne->device;
-
-	snprintf(ud->device.bus_id, BUS_ID_SIZE, "%s-%u",
-		 ne->device.bus_id, ud->id);
-
-	ud->class_dev.dev = &ud->device;
-	ud->class_dev.class = &nodemgr_ud_class;
-	snprintf(ud->class_dev.class_id, BUS_ID_SIZE, "%s-%u",
-		 ne->device.bus_id, ud->id);
-
-	device_register(&ud->device);
-	class_device_register(&ud->class_dev);
-	get_device(&ud->device);
-
-	if (ud->vendor_oui)
-		device_create_file(&ud->device, &dev_attr_ud_vendor_oui);
-	nodemgr_create_ud_dev_files(ud);
+	
+	/* do not process child units here and only if not already registered */
+	if (!parent && ud->device.bus != &ieee1394_bus_type)
+		nodemgr_register_device(ne, ud, &ne->device);
 
 	return ud;
 
@@ -1141,6 +1165,13 @@
 
 		/* Mark the node as new, so it gets re-probed */
 		ne->needs_probe = 1;
+	} else {
+		/* old cache is valid, so update its generation */
+		struct nodemgr_csr_info *ci = ne->csr->private;
+		ci->generation = generation;
+		/* free the partially filled now unneeded new cache */
+		kfree(csr->private);
+		csr1212_destroy_csr(csr);
 	}
 
 	if (ne->in_limbo)
@@ -1431,7 +1462,7 @@
 	quadlet_t bc;
 	int status;
 
-	if (host->is_irm)
+	if (hpsb_disable_irm || host->is_irm)
 		return 1;
 
 	status = hpsb_read(host, LOCAL_BUS | (host->irm_id),
@@ -1553,29 +1584,6 @@
 	complete_and_exit(&hi->exited, 0);
 }
 
-struct node_entry *hpsb_guid_get_entry(u64 guid)
-{
-        struct node_entry *ne;
-
-	down(&nodemgr_serialize);
-        ne = find_entry_by_guid(guid);
-	up(&nodemgr_serialize);
-
-        return ne;
-}
-
-struct node_entry *hpsb_nodeid_get_entry(struct hpsb_host *host, nodeid_t nodeid)
-{
-	struct node_entry *ne;
-
-	down(&nodemgr_serialize);
-	ne = find_entry_by_nodeid(host, nodeid);
-	up(&nodemgr_serialize);
-
-	return ne;
-}
-
-
 int nodemgr_for_each_host(void *__data, int (*cb)(struct hpsb_host *, void *))
 {
 	struct class *class = &hpsb_host_class;
@@ -1618,16 +1626,6 @@
         pkt->node_id = ne->nodeid;
 }
 
-int hpsb_node_read(struct node_entry *ne, u64 addr,
-		   quadlet_t *buffer, size_t length)
-{
-	unsigned int generation = ne->generation;
-
-	barrier();
-	return hpsb_read(ne->host, ne->nodeid, generation,
-			 addr, buffer, length);
-}
-
 int hpsb_node_write(struct node_entry *ne, u64 addr,
 		    quadlet_t *buffer, size_t length)
 {
@@ -1636,16 +1634,6 @@
 	barrier();
 	return hpsb_write(ne->host, ne->nodeid, generation,
 			  addr, buffer, length);
-}
-
-int hpsb_node_lock(struct node_entry *ne, u64 addr,
-		   int extcode, quadlet_t *data, quadlet_t arg)
-{
-	unsigned int generation = ne->generation;
-
-	barrier();
-	return hpsb_lock(ne->host, ne->nodeid, generation,
-			 addr, extcode, data, arg);
 }
 
 static void nodemgr_add_host(struct hpsb_host *host)
diff -Nru a/drivers/ieee1394/nodemgr.h b/drivers/ieee1394/nodemgr.h
--- a/drivers/ieee1394/nodemgr.h	2005-03-11 12:51:46 -08:00
+++ b/drivers/ieee1394/nodemgr.h	2005-03-11 12:51:46 -08:00
@@ -51,6 +51,7 @@
 #define UNIT_DIRECTORY_VERSION			0x08
 #define UNIT_DIRECTORY_HAS_LUN_DIRECTORY	0x10
 #define UNIT_DIRECTORY_LUN_DIRECTORY		0x20
+#define UNIT_DIRECTORY_HAS_LUN			0x40
 
 /*
  * A unit directory corresponds to a protocol supported by the
@@ -82,6 +83,7 @@
 	struct class_device class_dev;
 
 	struct csr1212_keyval *ud_kv;
+	u32 lun;                /* logical unit number immediate value */
 };
 
 struct node_entry {
diff -Nru a/drivers/ieee1394/ohci1394.c b/drivers/ieee1394/ohci1394.c
--- a/drivers/ieee1394/ohci1394.c	2005-03-11 12:51:51 -08:00
+++ b/drivers/ieee1394/ohci1394.c	2005-03-11 12:51:51 -08:00
@@ -162,7 +162,7 @@
 printk(level "%s: fw-host%d: " fmt "\n" , OHCI1394_DRIVER_NAME, ohci->host->id , ## args)
 
 static char version[] __devinitdata =
-	"$Rev: 1223 $ Ben Collins <bcollins@debian.org>";
+	"$Rev: 1250 $ Ben Collins <bcollins@debian.org>";
 
 /* Module Parameters */
 static int phys_dma = 1;
@@ -482,7 +482,9 @@
 
 	/* Put some defaults to these undefined bus options */
 	buf = reg_read(ohci, OHCI1394_BusOptions);
-	buf |=  0xE0000000; /* Enable IRMC, CMC and ISC */
+	buf |=  0x60000000; /* Enable CMC and ISC */
+	if (!hpsb_disable_irm)
+		buf |=  0x80000000; /* Enable IRMC */
 	buf &= ~0x00ff0000; /* XXX: Set cyc_clk_acc to zero for now */
 	buf &= ~0x18000000; /* Disable PMC and BMC */
 	reg_write(ohci, OHCI1394_BusOptions, buf);
@@ -497,10 +499,12 @@
 	reg_write(ohci, OHCI1394_LinkControlClear, 0xffffffff);
 
 	/* Enable cycle timer and cycle master and set the IRM
-	 * contender bit in our self ID packets. */
-	reg_write(ohci, OHCI1394_LinkControlSet, OHCI1394_LinkControl_CycleTimerEnable |
+	 * contender bit in our self ID packets if appropriate. */
+	reg_write(ohci, OHCI1394_LinkControlSet,
+		  OHCI1394_LinkControl_CycleTimerEnable |
 		  OHCI1394_LinkControl_CycleMaster);
-	set_phy_reg_mask(ohci, 4, 0xc0);
+	set_phy_reg_mask(ohci, 4, PHY_04_LCTRL |
+			 (hpsb_disable_irm ? 0 : PHY_04_CONTENDER));
 
 	/* Set up self-id dma buffer */
 	reg_write(ohci, OHCI1394_SelfIDBuffer, ohci->selfid_buf_bus);
@@ -515,12 +519,6 @@
 	/* Now get our max packet size */
 	ohci->max_packet_size =
 		1<<(((reg_read(ohci, OHCI1394_BusOptions)>>12)&0xf)+1);
-
-	if (ohci->max_packet_size < 512) {
-		HPSB_ERR("warning: Invalid max packet size of %d, setting to 512",
-			     ohci->max_packet_size);
-		ohci->max_packet_size = 512;
-	}
 		
 	/* Don't accept phy packets into AR request context */
 	reg_write(ohci, OHCI1394_LinkControlClear, 0x00000400);
@@ -2545,6 +2543,10 @@
 	idx = (idx + d->num_desc - 1 ) % d->num_desc;
 	d->prg_cpu[idx]->branchAddress |= le32_to_cpu(0x00000001);
 
+	/* To avoid a race, ensure 1394 interface hardware sees the inserted
+	 * context program descriptors before it sees the wakeup bit set. */
+	wmb();
+	
 	/* wake up the dma context if necessary */
 	if (!(reg_read(ohci, d->ctrlSet) & 0x400)) {
 		PRINT(KERN_INFO,
diff -Nru a/drivers/ieee1394/pcilynx.c b/drivers/ieee1394/pcilynx.c
--- a/drivers/ieee1394/pcilynx.c	2005-03-11 12:51:42 -08:00
+++ b/drivers/ieee1394/pcilynx.c	2005-03-11 12:51:42 -08:00
@@ -384,7 +384,8 @@
         lsid = 0x80400000 | ((phyreg[0] & 0xfc) << 22);
         lsid |= (phyreg[1] & 0x3f) << 16; /* gap count */
         lsid |= (phyreg[2] & 0xc0) << 8; /* max speed */
-        lsid |= (phyreg[6] & 0x01) << 11; /* contender (phy dependent) */
+	if (!hpsb_disable_irm)
+		lsid |= (phyreg[6] & 0x01) << 11; /* contender (phy dependent) */
         /* lsid |= 1 << 11; *//* set contender (hack) */
         lsid |= (phyreg[6] & 0x10) >> 3; /* initiated reset */
 
@@ -500,7 +501,7 @@
         pcl.async_error_next = PCL_NEXT_INVALID;
         pcl.pcl_status = 0;
         pcl.buffer[0].control = packet->speed_code << 14 | packet->header_size;
-#ifdef __BIG_ENDIAN
+#ifndef __BIG_ENDIAN
         pcl.buffer[0].control |= PCL_BIGENDIAN;
 #endif
         pcl.buffer[0].pointer = d->header_dma;
@@ -1521,10 +1522,6 @@
         int i;
         int error;
 
-        /* needed for i2c communication with serial eeprom */
-        struct i2c_adapter i2c_adapter;
-        struct i2c_algo_bit_data i2c_adapter_data;
-
         error = -ENXIO;
 
         if (pci_set_dma_mask(dev, 0xffffffff))
@@ -1697,7 +1694,7 @@
         pcl.async_error_next = PCL_NEXT_INVALID;
 
         pcl.buffer[0].control = PCL_CMD_RCV | 16;
-#ifdef __BIG_ENDIAN
+#ifndef __BIG_ENDIAN
 	pcl.buffer[0].control |= PCL_BIGENDIAN;
 #endif
 	pcl.buffer[1].control = PCL_LAST_BUFF | 4080;
@@ -1779,26 +1776,40 @@
                   | LINK_CONTROL_TX_ASYNC_EN | LINK_CONTROL_RX_ASYNC_EN
                   | LINK_CONTROL_RESET_TX    | LINK_CONTROL_RESET_RX);
 
-        if (!lynx->phyic.reg_1394a) {
-                /* attempt to enable contender bit -FIXME- would this work
-                 * elsewhere? */
-                reg_set_bits(lynx, GPIO_CTRL_A, 0x1);
-                reg_write(lynx, GPIO_DATA_BASE + 0x3c, 0x1);
-        } else {
-                /* 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 | 0xc0);
-        }
-
-
+	if (!lynx->phyic.reg_1394a) {
+		if (!hpsb_disable_irm) {
+			/* attempt to enable contender bit -FIXME- would this
+			 * work elsewhere? */
+			reg_set_bits(lynx, GPIO_CTRL_A, 0x1);
+			reg_write(lynx, GPIO_DATA_BASE + 0x3c, 0x1);
+		}
+	} else {
+		/* set the contender (if appropriate) and LCtrl bit in the
+		 * extended PHY register set. (Should check that PHY_02_EXTENDED
+		 * is set in register 2?)
+		 */
+		i = get_phy_reg(lynx, 4);
+		i |= PHY_04_LCTRL;
+		if (hpsb_disable_irm)
+			i &= !PHY_04_CONTENDER;
+		else
+			i |= PHY_04_CONTENDER;
+		if (i != -1) set_phy_reg(lynx, 4, i);
+	}
+	
         if (!skip_eeprom)
         {
-                i2c_adapter = bit_ops;
+        	/* needed for i2c communication with serial eeprom */
+        	struct i2c_adapter *i2c_ad;
+        	struct i2c_algo_bit_data i2c_adapter_data;
+
+        	error = -ENOMEM;
+		i2c_ad = kmalloc(sizeof(struct i2c_adapter), SLAB_KERNEL);
+        	if (!i2c_ad) FAIL("failed to allocate I2C adapter memory");
+
+		memcpy(i2c_ad, &bit_ops, sizeof(struct i2c_adapter));
                 i2c_adapter_data = bit_data;
-                i2c_adapter.algo_data = &i2c_adapter_data;
+                i2c_ad->algo_data = &i2c_adapter_data;
                 i2c_adapter_data.data = lynx;
 
 		PRINTD(KERN_DEBUG, lynx->id,"original eeprom control: %d",
@@ -1808,8 +1819,9 @@
         	lynx->i2c_driven_state = 0x00000070;
         	reg_write(lynx, SERIAL_EEPROM_CONTROL, lynx->i2c_driven_state);
 
-        	if (i2c_bit_add_bus(&i2c_adapter) < 0)
+        	if (i2c_bit_add_bus(i2c_ad) < 0)
         	{
+			kfree(i2c_ad);
 			error = -ENXIO;
 			FAIL("unable to register i2c");
         	}
@@ -1825,13 +1837,13 @@
 #ifdef CONFIG_IEEE1394_VERBOSEDEBUG
                         union i2c_smbus_data data;
 
-                        if (i2c_smbus_xfer(&i2c_adapter, 80, 0, I2C_SMBUS_WRITE, 0, I2C_SMBUS_BYTE,NULL))
+                        if (i2c_smbus_xfer(i2c_ad, 80, 0, I2C_SMBUS_WRITE, 0, I2C_SMBUS_BYTE,NULL))
                                 PRINT(KERN_ERR, lynx->id,"eeprom read start has failed");
                         else
                         {
                                 u16 addr;
                                 for (addr=0x00; addr < 0x100; addr++) {
-                                        if (i2c_smbus_xfer(&i2c_adapter, 80, 0, I2C_SMBUS_READ, 0, I2C_SMBUS_BYTE,& data)) {
+                                        if (i2c_smbus_xfer(i2c_ad, 80, 0, I2C_SMBUS_READ, 0, I2C_SMBUS_BYTE,& data)) {
                                                 PRINT(KERN_ERR, lynx->id, "unable to read i2c %x", addr);
                                                 break;
                                         }
@@ -1843,7 +1855,7 @@
 
                         /* we use i2c_transfer, because i2c_smbus_read_block_data does not work properly and we
                            do it more efficiently in one transaction rather then using several reads */
-                        if (i2c_transfer(&i2c_adapter, msg, 2) < 0) {
+                        if (i2c_transfer(i2c_ad, msg, 2) < 0) {
                                 PRINT(KERN_ERR, lynx->id, "unable to read bus info block from i2c");
                         } else {
                                 int i;
@@ -1863,13 +1875,15 @@
                                 {
                                         PRINT(KERN_DEBUG, lynx->id, "read a valid bus info block from");
                                 } else {
+					kfree(i2c_ad);
 					error = -ENXIO;
 					FAIL("read something from serial eeprom, but it does not seem to be a valid bus info block");
                                 }
 
                         }
 
-                        i2c_bit_del_bus(&i2c_adapter);
+                        i2c_bit_del_bus(i2c_ad);
+			kfree(i2c_ad);
                 }
         }
 
diff -Nru a/drivers/ieee1394/raw1394.c b/drivers/ieee1394/raw1394.c
--- a/drivers/ieee1394/raw1394.c	2005-03-11 12:51:40 -08:00
+++ b/drivers/ieee1394/raw1394.c	2005-03-11 12:51:40 -08:00
@@ -75,58 +75,60 @@
 static atomic_t internal_generation = ATOMIC_INIT(0);
 
 static atomic_t iso_buffer_size;
-static const int iso_buffer_max = 4 * 1024 * 1024; /* 4 MB */
+static const int iso_buffer_max = 4 * 1024 * 1024;	/* 4 MB */
 
 static struct hpsb_highlevel raw1394_highlevel;
 
-static int arm_read (struct hpsb_host *host, int nodeid, quadlet_t *buffer,
-		     u64 addr, size_t length, u16 flags);
-static int arm_write (struct hpsb_host *host, int nodeid, int destid,
-		      quadlet_t *data, u64 addr, size_t length, u16 flags);
-static int arm_lock (struct hpsb_host *host, int nodeid, quadlet_t *store,
-             u64 addr, quadlet_t data, quadlet_t arg, int ext_tcode, u16 flags);
-static int arm_lock64 (struct hpsb_host *host, int nodeid, octlet_t *store,
-               u64 addr, octlet_t data, octlet_t arg, int ext_tcode, u16 flags);
+static int arm_read(struct hpsb_host *host, int nodeid, quadlet_t * buffer,
+		    u64 addr, size_t length, u16 flags);
+static int arm_write(struct hpsb_host *host, int nodeid, int destid,
+		     quadlet_t * data, u64 addr, size_t length, u16 flags);
+static int arm_lock(struct hpsb_host *host, int nodeid, quadlet_t * store,
+		    u64 addr, quadlet_t data, quadlet_t arg, int ext_tcode,
+		    u16 flags);
+static int arm_lock64(struct hpsb_host *host, int nodeid, octlet_t * store,
+		      u64 addr, octlet_t data, octlet_t arg, int ext_tcode,
+		      u16 flags);
 static struct hpsb_address_ops arm_ops = {
-	.read	= arm_read,
-	.write	= arm_write,
-	.lock	= arm_lock,
-	.lock64	= arm_lock64,
+	.read = arm_read,
+	.write = arm_write,
+	.lock = arm_lock,
+	.lock64 = arm_lock64,
 };
 
 static void queue_complete_cb(struct pending_request *req);
 
 static struct pending_request *__alloc_pending_request(int flags)
 {
-        struct pending_request *req;
+	struct pending_request *req;
 
-        req = (struct pending_request *)kmalloc(sizeof(struct pending_request),
-                                                flags);
-        if (req != NULL) {
-                memset(req, 0, sizeof(struct pending_request));
-                INIT_LIST_HEAD(&req->list);
-        }
+	req = (struct pending_request *)kmalloc(sizeof(struct pending_request),
+						flags);
+	if (req != NULL) {
+		memset(req, 0, sizeof(struct pending_request));
+		INIT_LIST_HEAD(&req->list);
+	}
 
-        return req;
+	return req;
 }
 
 static inline struct pending_request *alloc_pending_request(void)
 {
-        return __alloc_pending_request(SLAB_KERNEL);
+	return __alloc_pending_request(SLAB_KERNEL);
 }
 
 static void free_pending_request(struct pending_request *req)
 {
-        if (req->ibs) {
-                if (atomic_dec_and_test(&req->ibs->refcount)) {
-                        atomic_sub(req->ibs->data_size, &iso_buffer_size);
-                        kfree(req->ibs);
-                }
-        } else if (req->free_data) {
-                kfree(req->data);
-        }
-        hpsb_free_packet(req->packet);
-        kfree(req);
+	if (req->ibs) {
+		if (atomic_dec_and_test(&req->ibs->refcount)) {
+			atomic_sub(req->ibs->data_size, &iso_buffer_size);
+			kfree(req->ibs);
+		}
+	} else if (req->free_data) {
+		kfree(req->data);
+	}
+	hpsb_free_packet(req->packet);
+	kfree(req);
 }
 
 /* fi->reqlists_lock must be taken */
@@ -134,494 +136,505 @@
 {
 	struct file_info *fi = req->file_info;
 	list_del(&req->list);
-        list_add_tail(&req->list, &fi->req_complete);
+	list_add_tail(&req->list, &fi->req_complete);
 
 	up(&fi->complete_sem);
-        wake_up_interruptible(&fi->poll_wait_complete);
+	wake_up_interruptible(&fi->poll_wait_complete);
 }
 
 static void queue_complete_req(struct pending_request *req)
 {
-        unsigned long flags;
-        struct file_info *fi = req->file_info;
+	unsigned long flags;
+	struct file_info *fi = req->file_info;
 
-        spin_lock_irqsave(&fi->reqlists_lock, flags);
+	spin_lock_irqsave(&fi->reqlists_lock, flags);
 	__queue_complete_req(req);
-        spin_unlock_irqrestore(&fi->reqlists_lock, flags);
+	spin_unlock_irqrestore(&fi->reqlists_lock, flags);
 }
 
 static void queue_complete_cb(struct pending_request *req)
 {
-        struct hpsb_packet *packet = req->packet;
-        int rcode = (packet->header[1] >> 12) & 0xf;
+	struct hpsb_packet *packet = req->packet;
+	int rcode = (packet->header[1] >> 12) & 0xf;
 
-        switch (packet->ack_code) {
-        case ACKX_NONE:
-        case ACKX_SEND_ERROR:
-                req->req.error = RAW1394_ERROR_SEND_ERROR;
-                break;
-        case ACKX_ABORTED:
-                req->req.error = RAW1394_ERROR_ABORTED;
-                break;
-        case ACKX_TIMEOUT:
-                req->req.error = RAW1394_ERROR_TIMEOUT;
-                break;
-        default:
-                req->req.error = (packet->ack_code << 16) | rcode;
-                break;
-        }
-
-        if (!((packet->ack_code == ACK_PENDING) && (rcode == RCODE_COMPLETE))) {
-                req->req.length = 0;
-        }
+	switch (packet->ack_code) {
+	case ACKX_NONE:
+	case ACKX_SEND_ERROR:
+		req->req.error = RAW1394_ERROR_SEND_ERROR;
+		break;
+	case ACKX_ABORTED:
+		req->req.error = RAW1394_ERROR_ABORTED;
+		break;
+	case ACKX_TIMEOUT:
+		req->req.error = RAW1394_ERROR_TIMEOUT;
+		break;
+	default:
+		req->req.error = (packet->ack_code << 16) | rcode;
+		break;
+	}
+
+	if (!((packet->ack_code == ACK_PENDING) && (rcode == RCODE_COMPLETE))) {
+		req->req.length = 0;
+	}
 
-        if ((req->req.type == RAW1394_REQ_ASYNC_READ) ||
+	if ((req->req.type == RAW1394_REQ_ASYNC_READ) ||
 	    (req->req.type == RAW1394_REQ_ASYNC_WRITE) ||
 	    (req->req.type == RAW1394_REQ_ASYNC_STREAM) ||
 	    (req->req.type == RAW1394_REQ_LOCK) ||
 	    (req->req.type == RAW1394_REQ_LOCK64))
-                hpsb_free_tlabel(packet);
+		hpsb_free_tlabel(packet);
 
-        queue_complete_req(req);
+	queue_complete_req(req);
 }
 
-
 static void add_host(struct hpsb_host *host)
 {
-        struct host_info *hi;
-        unsigned long flags;
+	struct host_info *hi;
+	unsigned long flags;
 
-        hi = (struct host_info *)kmalloc(sizeof(struct host_info), GFP_KERNEL);
+	hi = (struct host_info *)kmalloc(sizeof(struct host_info), GFP_KERNEL);
 
-        if (hi != NULL) {
-                INIT_LIST_HEAD(&hi->list);
-                hi->host = host;
-                INIT_LIST_HEAD(&hi->file_info_list);
-
-                spin_lock_irqsave(&host_info_lock, flags);
-                list_add_tail(&hi->list, &host_info_list);
-                host_count++;
-                spin_unlock_irqrestore(&host_info_lock, flags);
-        }
+	if (hi != NULL) {
+		INIT_LIST_HEAD(&hi->list);
+		hi->host = host;
+		INIT_LIST_HEAD(&hi->file_info_list);
+
+		spin_lock_irqsave(&host_info_lock, flags);
+		list_add_tail(&hi->list, &host_info_list);
+		host_count++;
+		spin_unlock_irqrestore(&host_info_lock, flags);
+	}
 
-        atomic_inc(&internal_generation);
+	atomic_inc(&internal_generation);
 }
 
-
 static struct host_info *find_host_info(struct hpsb_host *host)
 {
-        struct host_info *hi;
+	struct host_info *hi;
 
-        list_for_each_entry(hi, &host_info_list, list)
-                if (hi->host == host)
-                        return hi;
+	list_for_each_entry(hi, &host_info_list, list)
+	    if (hi->host == host)
+		return hi;
 
-        return NULL;
+	return NULL;
 }
 
 static void remove_host(struct hpsb_host *host)
 {
-        struct host_info *hi;
-        unsigned long flags;
+	struct host_info *hi;
+	unsigned long flags;
+
+	spin_lock_irqsave(&host_info_lock, flags);
+	hi = find_host_info(host);
 
-        spin_lock_irqsave(&host_info_lock, flags);
-        hi = find_host_info(host);
+	if (hi != NULL) {
+		list_del(&hi->list);
+		host_count--;
+		/*
+		   FIXME: address ranges should be removed
+		   and fileinfo states should be initialized
+		   (including setting generation to
+		   internal-generation ...)
+		 */
+	}
+	spin_unlock_irqrestore(&host_info_lock, flags);
 
-        if (hi != NULL) {
-                list_del(&hi->list);
-                host_count--;
-                /*
-                   FIXME: address ranges should be removed
-                   and fileinfo states should be initialized
-                   (including setting generation to
-                   internal-generation ...)
-                */
-        }
-        spin_unlock_irqrestore(&host_info_lock, flags);
-
-        if (hi == NULL) {
-                printk(KERN_ERR "raw1394: attempt to remove unknown host "
-                       "0x%p\n", host);
-                return;
-        }
+	if (hi == NULL) {
+		printk(KERN_ERR "raw1394: attempt to remove unknown host "
+		       "0x%p\n", host);
+		return;
+	}
 
-        kfree(hi);
+	kfree(hi);
 
-        atomic_inc(&internal_generation);
+	atomic_inc(&internal_generation);
 }
 
 static void host_reset(struct hpsb_host *host)
 {
-        unsigned long flags;
-        struct host_info *hi;
-        struct file_info *fi;
-        struct pending_request *req;
-
-        spin_lock_irqsave(&host_info_lock, flags);
-        hi = find_host_info(host);
-
-        if (hi != NULL) {
-                list_for_each_entry(fi, &hi->file_info_list, list) {
-                        if (fi->notification == RAW1394_NOTIFY_ON) {
-                                req = __alloc_pending_request(SLAB_ATOMIC);
-
-                                if (req != NULL) {
-                                        req->file_info = fi;
-                                        req->req.type = RAW1394_REQ_BUS_RESET;
-                                        req->req.generation = get_hpsb_generation(host);
-                                        req->req.misc = (host->node_id << 16)
-                                                | host->node_count;
-                                        if (fi->protocol_version > 3) {
-                                                req->req.misc |= (NODEID_TO_NODE(host->irm_id)
-                                                                  << 8);
-                                        }
-
-                                        queue_complete_req(req);
-                                }
-                        }
-                }
-        }
-        spin_unlock_irqrestore(&host_info_lock, flags);
-}
-
-static void iso_receive(struct hpsb_host *host, int channel, quadlet_t *data,
-                        size_t length)
-{
-        unsigned long flags;
-        struct host_info *hi;
-        struct file_info *fi;
-        struct pending_request *req, *req_next;
-        struct iso_block_store *ibs = NULL;
-        LIST_HEAD(reqs);
-
-        if ((atomic_read(&iso_buffer_size) + length) > iso_buffer_max) {
-                HPSB_INFO("dropped iso packet");
-                return;
-        }
+	unsigned long flags;
+	struct host_info *hi;
+	struct file_info *fi;
+	struct pending_request *req;
+
+	spin_lock_irqsave(&host_info_lock, flags);
+	hi = find_host_info(host);
+
+	if (hi != NULL) {
+		list_for_each_entry(fi, &hi->file_info_list, list) {
+			if (fi->notification == RAW1394_NOTIFY_ON) {
+				req = __alloc_pending_request(SLAB_ATOMIC);
+
+				if (req != NULL) {
+					req->file_info = fi;
+					req->req.type = RAW1394_REQ_BUS_RESET;
+					req->req.generation =
+					    get_hpsb_generation(host);
+					req->req.misc = (host->node_id << 16)
+					    | host->node_count;
+					if (fi->protocol_version > 3) {
+						req->req.misc |=
+						    (NODEID_TO_NODE
+						     (host->irm_id)
+						     << 8);
+					}
+
+					queue_complete_req(req);
+				}
+			}
+		}
+	}
+	spin_unlock_irqrestore(&host_info_lock, flags);
+}
+
+static void iso_receive(struct hpsb_host *host, int channel, quadlet_t * data,
+			size_t length)
+{
+	unsigned long flags;
+	struct host_info *hi;
+	struct file_info *fi;
+	struct pending_request *req, *req_next;
+	struct iso_block_store *ibs = NULL;
+	LIST_HEAD(reqs);
+
+	if ((atomic_read(&iso_buffer_size) + length) > iso_buffer_max) {
+		HPSB_INFO("dropped iso packet");
+		return;
+	}
 
-        spin_lock_irqsave(&host_info_lock, flags);
-        hi = find_host_info(host);
+	spin_lock_irqsave(&host_info_lock, flags);
+	hi = find_host_info(host);
 
-        if (hi != NULL) {
+	if (hi != NULL) {
 		list_for_each_entry(fi, &hi->file_info_list, list) {
-                        if (!(fi->listen_channels & (1ULL << channel)))
-                                continue;
+			if (!(fi->listen_channels & (1ULL << channel)))
+				continue;
+
+			req = __alloc_pending_request(SLAB_ATOMIC);
+			if (!req)
+				break;
+
+			if (!ibs) {
+				ibs = kmalloc(sizeof(struct iso_block_store)
+					      + length, SLAB_ATOMIC);
+				if (!ibs) {
+					kfree(req);
+					break;
+				}
+
+				atomic_add(length, &iso_buffer_size);
+				atomic_set(&ibs->refcount, 0);
+				ibs->data_size = length;
+				memcpy(ibs->data, data, length);
+			}
+
+			atomic_inc(&ibs->refcount);
 
-                        req = __alloc_pending_request(SLAB_ATOMIC);
-                        if (!req) break;
+			req->file_info = fi;
+			req->ibs = ibs;
+			req->data = ibs->data;
+			req->req.type = RAW1394_REQ_ISO_RECEIVE;
+			req->req.generation = get_hpsb_generation(host);
+			req->req.misc = 0;
+			req->req.recvb = ptr2int(fi->iso_buffer);
+			req->req.length = min(length, fi->iso_buffer_length);
 
-                        if (!ibs) {
-                                ibs = kmalloc(sizeof(struct iso_block_store)
-                                              + length, SLAB_ATOMIC);
-                                if (!ibs) {
-                                        kfree(req);
-                                        break;
-                                }
-
-                                atomic_add(length, &iso_buffer_size);
-                                atomic_set(&ibs->refcount, 0);
-                                ibs->data_size = length;
-                                memcpy(ibs->data, data, length);
-                        }
-
-                        atomic_inc(&ibs->refcount);
-
-                        req->file_info = fi;
-                        req->ibs = ibs;
-                        req->data = ibs->data;
-                        req->req.type = RAW1394_REQ_ISO_RECEIVE;
-                        req->req.generation = get_hpsb_generation(host);
-                        req->req.misc = 0;
-                        req->req.recvb = ptr2int(fi->iso_buffer);
-                        req->req.length = min(length, fi->iso_buffer_length);
-
-                        list_add_tail(&req->list, &reqs);
-                }
-        }
-        spin_unlock_irqrestore(&host_info_lock, flags);
+			list_add_tail(&req->list, &reqs);
+		}
+	}
+	spin_unlock_irqrestore(&host_info_lock, flags);
 
 	list_for_each_entry_safe(req, req_next, &reqs, list)
-                queue_complete_req(req);
+	    queue_complete_req(req);
 }
 
 static void fcp_request(struct hpsb_host *host, int nodeid, int direction,
-			int cts, u8 *data, size_t length)
+			int cts, u8 * data, size_t length)
 {
-        unsigned long flags;
-        struct host_info *hi;
-        struct file_info *fi;
-        struct pending_request *req, *req_next;
-        struct iso_block_store *ibs = NULL;
-        LIST_HEAD(reqs);
-
-        if ((atomic_read(&iso_buffer_size) + length) > iso_buffer_max) {
-                HPSB_INFO("dropped fcp request");
-                return;
-        }
+	unsigned long flags;
+	struct host_info *hi;
+	struct file_info *fi;
+	struct pending_request *req, *req_next;
+	struct iso_block_store *ibs = NULL;
+	LIST_HEAD(reqs);
+
+	if ((atomic_read(&iso_buffer_size) + length) > iso_buffer_max) {
+		HPSB_INFO("dropped fcp request");
+		return;
+	}
 
-        spin_lock_irqsave(&host_info_lock, flags);
-        hi = find_host_info(host);
+	spin_lock_irqsave(&host_info_lock, flags);
+	hi = find_host_info(host);
 
-        if (hi != NULL) {
+	if (hi != NULL) {
 		list_for_each_entry(fi, &hi->file_info_list, list) {
-                        if (!fi->fcp_buffer)
-                                continue;
+			if (!fi->fcp_buffer)
+				continue;
 
-                        req = __alloc_pending_request(SLAB_ATOMIC);
-                        if (!req) break;
+			req = __alloc_pending_request(SLAB_ATOMIC);
+			if (!req)
+				break;
+
+			if (!ibs) {
+				ibs = kmalloc(sizeof(struct iso_block_store)
+					      + length, SLAB_ATOMIC);
+				if (!ibs) {
+					kfree(req);
+					break;
+				}
+
+				atomic_add(length, &iso_buffer_size);
+				atomic_set(&ibs->refcount, 0);
+				ibs->data_size = length;
+				memcpy(ibs->data, data, length);
+			}
 
-                        if (!ibs) {
-                                ibs = kmalloc(sizeof(struct iso_block_store)
-                                              + length, SLAB_ATOMIC);
-                                if (!ibs) {
-                                        kfree(req);
-                                        break;
-                                }
-
-                                atomic_add(length, &iso_buffer_size);
-                                atomic_set(&ibs->refcount, 0);
-                                ibs->data_size = length;
-                                memcpy(ibs->data, data, length);
-                        }
-
-                        atomic_inc(&ibs->refcount);
-
-                        req->file_info = fi;
-                        req->ibs = ibs;
-                        req->data = ibs->data;
-                        req->req.type = RAW1394_REQ_FCP_REQUEST;
-                        req->req.generation = get_hpsb_generation(host);
-                        req->req.misc = nodeid | (direction << 16);
-                        req->req.recvb = ptr2int(fi->fcp_buffer);
-                        req->req.length = length;
-
-                        list_add_tail(&req->list, &reqs);
-                }
-        }
-        spin_unlock_irqrestore(&host_info_lock, flags);
+			atomic_inc(&ibs->refcount);
+
+			req->file_info = fi;
+			req->ibs = ibs;
+			req->data = ibs->data;
+			req->req.type = RAW1394_REQ_FCP_REQUEST;
+			req->req.generation = get_hpsb_generation(host);
+			req->req.misc = nodeid | (direction << 16);
+			req->req.recvb = ptr2int(fi->fcp_buffer);
+			req->req.length = length;
+
+			list_add_tail(&req->list, &reqs);
+		}
+	}
+	spin_unlock_irqrestore(&host_info_lock, flags);
 
 	list_for_each_entry_safe(req, req_next, &reqs, list)
-                queue_complete_req(req);
+	    queue_complete_req(req);
 }
 
-
-static ssize_t raw1394_read(struct file *file, char __user *buffer, size_t count,
-                    loff_t *offset_is_ignored)
+static ssize_t raw1394_read(struct file *file, char __user * buffer,
+			    size_t count, loff_t * offset_is_ignored)
 {
-        struct file_info *fi = (struct file_info *)file->private_data;
-        struct list_head *lh;
-        struct pending_request *req;
-
-        if (count != sizeof(struct raw1394_request)) {
-                return -EINVAL;
-        }
-
-        if (!access_ok(VERIFY_WRITE, buffer, count)) {
-                return -EFAULT;
-        }
-
-        if (file->f_flags & O_NONBLOCK) {
-                if (down_trylock(&fi->complete_sem)) {
-                        return -EAGAIN;
-                }
-        } else {
-                if (down_interruptible(&fi->complete_sem)) {
-                        return -ERESTARTSYS;
-                }
-        }
-
-        spin_lock_irq(&fi->reqlists_lock);
-        lh = fi->req_complete.next;
-        list_del(lh);
-        spin_unlock_irq(&fi->reqlists_lock);
-
-        req = list_entry(lh, struct pending_request, list);
-
-        if (req->req.length) {
-                if (copy_to_user(int2ptr(req->req.recvb), req->data,
-                                 req->req.length)) {
-                        req->req.error = RAW1394_ERROR_MEMFAULT;
-                }
-        }
-        __copy_to_user(buffer, &req->req, sizeof(req->req));
+	struct file_info *fi = (struct file_info *)file->private_data;
+	struct list_head *lh;
+	struct pending_request *req;
+	ssize_t ret;
 
-        free_pending_request(req);
-        return sizeof(struct raw1394_request);
-}
+	if (count != sizeof(struct raw1394_request)) {
+		return -EINVAL;
+	}
 
+	if (!access_ok(VERIFY_WRITE, buffer, count)) {
+		return -EFAULT;
+	}
+
+	if (file->f_flags & O_NONBLOCK) {
+		if (down_trylock(&fi->complete_sem)) {
+			return -EAGAIN;
+		}
+	} else {
+		if (down_interruptible(&fi->complete_sem)) {
+			return -ERESTARTSYS;
+		}
+	}
+
+	spin_lock_irq(&fi->reqlists_lock);
+	lh = fi->req_complete.next;
+	list_del(lh);
+	spin_unlock_irq(&fi->reqlists_lock);
+
+	req = list_entry(lh, struct pending_request, list);
+
+	if (req->req.length) {
+		if (copy_to_user(int2ptr(req->req.recvb), req->data,
+				 req->req.length)) {
+			req->req.error = RAW1394_ERROR_MEMFAULT;
+		}
+	}
+	if (copy_to_user(buffer, &req->req, sizeof(req->req))) {
+		ret = -EFAULT;
+		goto out;
+	}
+
+	ret = (ssize_t) sizeof(struct raw1394_request);
+      out:
+	free_pending_request(req);
+	return ret;
+}
 
 static int state_opened(struct file_info *fi, struct pending_request *req)
 {
-        if (req->req.type == RAW1394_REQ_INITIALIZE) {
-                switch (req->req.misc) {
-                case RAW1394_KERNELAPI_VERSION:
-                case 3:
-                        fi->state = initialized;
-                        fi->protocol_version = req->req.misc;
-                        req->req.error = RAW1394_ERROR_NONE;
-                        req->req.generation = atomic_read(&internal_generation);
-                        break;
-
-                default:
-                        req->req.error = RAW1394_ERROR_COMPAT;
-                        req->req.misc = RAW1394_KERNELAPI_VERSION;
-                }
-        } else {
-                req->req.error = RAW1394_ERROR_STATE_ORDER;
-        }
-
-        req->req.length = 0;
-        queue_complete_req(req);
-        return sizeof(struct raw1394_request);
+	if (req->req.type == RAW1394_REQ_INITIALIZE) {
+		switch (req->req.misc) {
+		case RAW1394_KERNELAPI_VERSION:
+		case 3:
+			fi->state = initialized;
+			fi->protocol_version = req->req.misc;
+			req->req.error = RAW1394_ERROR_NONE;
+			req->req.generation = atomic_read(&internal_generation);
+			break;
+
+		default:
+			req->req.error = RAW1394_ERROR_COMPAT;
+			req->req.misc = RAW1394_KERNELAPI_VERSION;
+		}
+	} else {
+		req->req.error = RAW1394_ERROR_STATE_ORDER;
+	}
+
+	req->req.length = 0;
+	queue_complete_req(req);
+	return sizeof(struct raw1394_request);
 }
 
 static int state_initialized(struct file_info *fi, struct pending_request *req)
 {
-        struct host_info *hi;
-        struct raw1394_khost_list *khl;
+	struct host_info *hi;
+	struct raw1394_khost_list *khl;
+
+	if (req->req.generation != atomic_read(&internal_generation)) {
+		req->req.error = RAW1394_ERROR_GENERATION;
+		req->req.generation = atomic_read(&internal_generation);
+		req->req.length = 0;
+		queue_complete_req(req);
+		return sizeof(struct raw1394_request);
+	}
+
+	switch (req->req.type) {
+	case RAW1394_REQ_LIST_CARDS:
+		spin_lock_irq(&host_info_lock);
+		khl = kmalloc(sizeof(struct raw1394_khost_list) * host_count,
+			      SLAB_ATOMIC);
+
+		if (khl != NULL) {
+			req->req.misc = host_count;
+			req->data = (quadlet_t *) khl;
 
-        if (req->req.generation != atomic_read(&internal_generation)) {
-                req->req.error = RAW1394_ERROR_GENERATION;
-                req->req.generation = atomic_read(&internal_generation);
-                req->req.length = 0;
-                queue_complete_req(req);
-                return sizeof(struct raw1394_request);
-        }
-
-        switch (req->req.type) {
-        case RAW1394_REQ_LIST_CARDS:
-                spin_lock_irq(&host_info_lock);
-                khl = kmalloc(sizeof(struct raw1394_khost_list) * host_count,
-                              SLAB_ATOMIC);
-
-                if (khl != NULL) {
-                        req->req.misc = host_count;
-                        req->data = (quadlet_t *)khl;
-
-                        list_for_each_entry(hi, &host_info_list, list) {
-                                khl->nodes = hi->host->node_count;
-                                strcpy(khl->name, hi->host->driver->name);
-                                khl++;
-                        }
-                }
-                spin_unlock_irq(&host_info_lock);
-
-                if (khl != NULL) {
-                        req->req.error = RAW1394_ERROR_NONE;
-                        req->req.length = min(req->req.length,
-                                              (u32)(sizeof(struct raw1394_khost_list)
-                                              * req->req.misc));
-                        req->free_data = 1;
-                } else {
-                        return -ENOMEM;
-                }
-                break;
-
-        case RAW1394_REQ_SET_CARD:
-                spin_lock_irq(&host_info_lock);
-                if (req->req.misc < host_count) {
+			list_for_each_entry(hi, &host_info_list, list) {
+				khl->nodes = hi->host->node_count;
+				strcpy(khl->name, hi->host->driver->name);
+				khl++;
+			}
+		}
+		spin_unlock_irq(&host_info_lock);
+
+		if (khl != NULL) {
+			req->req.error = RAW1394_ERROR_NONE;
+			req->req.length = min(req->req.length,
+					      (u32) (sizeof
+						     (struct raw1394_khost_list)
+						     * req->req.misc));
+			req->free_data = 1;
+		} else {
+			return -ENOMEM;
+		}
+		break;
+
+	case RAW1394_REQ_SET_CARD:
+		spin_lock_irq(&host_info_lock);
+		if (req->req.misc < host_count) {
 			list_for_each_entry(hi, &host_info_list, list) {
 				if (!req->req.misc--)
 					break;
 			}
-			get_device(&hi->host->device); // XXX Need to handle failure case
-                        list_add_tail(&fi->list, &hi->file_info_list);
-                        fi->host = hi->host;
-                        fi->state = connected;
-
-                        req->req.error = RAW1394_ERROR_NONE;
-                        req->req.generation = get_hpsb_generation(fi->host);
-                        req->req.misc = (fi->host->node_id << 16)
-                                | fi->host->node_count;
-                        if (fi->protocol_version > 3) {
-                                req->req.misc |= NODEID_TO_NODE(fi->host->irm_id) << 8;
-                        }
-                } else {
-                        req->req.error = RAW1394_ERROR_INVALID_ARG;
-                }
+			get_device(&hi->host->device);	// XXX Need to handle failure case
+			list_add_tail(&fi->list, &hi->file_info_list);
+			fi->host = hi->host;
+			fi->state = connected;
+
+			req->req.error = RAW1394_ERROR_NONE;
+			req->req.generation = get_hpsb_generation(fi->host);
+			req->req.misc = (fi->host->node_id << 16)
+			    | fi->host->node_count;
+			if (fi->protocol_version > 3) {
+				req->req.misc |=
+				    NODEID_TO_NODE(fi->host->irm_id) << 8;
+			}
+		} else {
+			req->req.error = RAW1394_ERROR_INVALID_ARG;
+		}
 		spin_unlock_irq(&host_info_lock);
 
-                req->req.length = 0;
-                break;
+		req->req.length = 0;
+		break;
 
-        default:
-                req->req.error = RAW1394_ERROR_STATE_ORDER;
-                req->req.length = 0;
-                break;
-        }
+	default:
+		req->req.error = RAW1394_ERROR_STATE_ORDER;
+		req->req.length = 0;
+		break;
+	}
 
-        queue_complete_req(req);
-        return sizeof(struct raw1394_request);
+	queue_complete_req(req);
+	return sizeof(struct raw1394_request);
 }
 
 static void handle_iso_listen(struct file_info *fi, struct pending_request *req)
 {
-        int channel = req->req.misc;
+	int channel = req->req.misc;
 
-        spin_lock_irq(&host_info_lock);
-        if ((channel > 63) || (channel < -64)) {
-                req->req.error = RAW1394_ERROR_INVALID_ARG;
-        } else if (channel >= 0) {
-                /* allocate channel req.misc */
-                if (fi->listen_channels & (1ULL << channel)) {
-                        req->req.error = RAW1394_ERROR_ALREADY;
-                } else {
-                        if (hpsb_listen_channel(&raw1394_highlevel, fi->host, channel)) {
+	spin_lock_irq(&host_info_lock);
+	if ((channel > 63) || (channel < -64)) {
+		req->req.error = RAW1394_ERROR_INVALID_ARG;
+	} else if (channel >= 0) {
+		/* allocate channel req.misc */
+		if (fi->listen_channels & (1ULL << channel)) {
+			req->req.error = RAW1394_ERROR_ALREADY;
+		} else {
+			if (hpsb_listen_channel
+			    (&raw1394_highlevel, fi->host, channel)) {
 				req->req.error = RAW1394_ERROR_ALREADY;
 			} else {
 				fi->listen_channels |= 1ULL << channel;
 				fi->iso_buffer = int2ptr(req->req.recvb);
 				fi->iso_buffer_length = req->req.length;
 			}
-                }
-        } else {
-                /* deallocate channel (one's complement neg) req.misc */
-                channel = ~channel;
-
-                if (fi->listen_channels & (1ULL << channel)) {
-                        hpsb_unlisten_channel(&raw1394_highlevel, fi->host, channel);
-                        fi->listen_channels &= ~(1ULL << channel);
-                } else {
-                        req->req.error = RAW1394_ERROR_INVALID_ARG;
-                }
-        }
-
-        req->req.length = 0;
-        queue_complete_req(req);
-        spin_unlock_irq(&host_info_lock);
+		}
+	} else {
+		/* deallocate channel (one's complement neg) req.misc */
+		channel = ~channel;
+
+		if (fi->listen_channels & (1ULL << channel)) {
+			hpsb_unlisten_channel(&raw1394_highlevel, fi->host,
+					      channel);
+			fi->listen_channels &= ~(1ULL << channel);
+		} else {
+			req->req.error = RAW1394_ERROR_INVALID_ARG;
+		}
+	}
+
+	req->req.length = 0;
+	queue_complete_req(req);
+	spin_unlock_irq(&host_info_lock);
 }
 
 static void handle_fcp_listen(struct file_info *fi, struct pending_request *req)
 {
-        if (req->req.misc) {
-                if (fi->fcp_buffer) {
-                        req->req.error = RAW1394_ERROR_ALREADY;
-                } else {
-                        fi->fcp_buffer = int2ptr(req->req.recvb);
-                }
-        } else {
-                if (!fi->fcp_buffer) {
-                        req->req.error = RAW1394_ERROR_ALREADY;
-                } else {
-                        fi->fcp_buffer = NULL;
-                }
-        }
+	if (req->req.misc) {
+		if (fi->fcp_buffer) {
+			req->req.error = RAW1394_ERROR_ALREADY;
+		} else {
+			fi->fcp_buffer = int2ptr(req->req.recvb);
+		}
+	} else {
+		if (!fi->fcp_buffer) {
+			req->req.error = RAW1394_ERROR_ALREADY;
+		} else {
+			fi->fcp_buffer = NULL;
+		}
+	}
 
-        req->req.length = 0;
-        queue_complete_req(req);
+	req->req.length = 0;
+	queue_complete_req(req);
 }
 
-
 static int handle_async_request(struct file_info *fi,
-                                struct pending_request *req, int node)
+				struct pending_request *req, int node)
 {
-        struct hpsb_packet *packet = NULL;
-        u64 addr = req->req.address & 0xffffffffffffULL;
+	struct hpsb_packet *packet = NULL;
+	u64 addr = req->req.address & 0xffffffffffffULL;
 
-        switch (req->req.type) {
-        case RAW1394_REQ_ASYNC_READ:
+	switch (req->req.type) {
+	case RAW1394_REQ_ASYNC_READ:
 		DBGMSG("read_request called");
-		packet = hpsb_make_readpacket(fi->host, node, addr, req->req.length);
+		packet =
+		    hpsb_make_readpacket(fi->host, node, addr, req->req.length);
 
 		if (!packet)
 			return -ENOMEM;
@@ -631,7 +644,7 @@
 		else
 			req->data = packet->data;
 
-                break;
+		break;
 
 	case RAW1394_REQ_ASYNC_WRITE:
 		DBGMSG("write_request called");
@@ -642,1105 +655,1207 @@
 			return -ENOMEM;
 
 		if (req->req.length == 4) {
-			if (copy_from_user(&packet->header[3], int2ptr(req->req.sendb),
-					req->req.length))
+			if (copy_from_user
+			    (&packet->header[3], int2ptr(req->req.sendb),
+			     req->req.length))
 				req->req.error = RAW1394_ERROR_MEMFAULT;
 		} else {
-			if (copy_from_user(packet->data, int2ptr(req->req.sendb),
-					req->req.length))
+			if (copy_from_user
+			    (packet->data, int2ptr(req->req.sendb),
+			     req->req.length))
 				req->req.error = RAW1394_ERROR_MEMFAULT;
 		}
 
 		req->req.length = 0;
-	    break;
+		break;
 
 	case RAW1394_REQ_ASYNC_STREAM:
 		DBGMSG("stream_request called");
 
-		packet = hpsb_make_streampacket(fi->host, NULL, req->req.length, node & 0x3f/*channel*/,
-                                        (req->req.misc >> 16) & 0x3, req->req.misc & 0xf);
+		packet =
+		    hpsb_make_streampacket(fi->host, NULL, req->req.length,
+					   node & 0x3f /*channel */ ,
+					   (req->req.misc >> 16) & 0x3,
+					   req->req.misc & 0xf);
 		if (!packet)
 			return -ENOMEM;
 
 		if (copy_from_user(packet->data, int2ptr(req->req.sendb),
-		                   req->req.length))
+				   req->req.length))
 			req->req.error = RAW1394_ERROR_MEMFAULT;
 
 		req->req.length = 0;
 		break;
 
-        case RAW1394_REQ_LOCK:
-                DBGMSG("lock_request called");
-                if ((req->req.misc == EXTCODE_FETCH_ADD)
-                    || (req->req.misc == EXTCODE_LITTLE_ADD)) {
-                        if (req->req.length != 4) {
-                                req->req.error = RAW1394_ERROR_INVALID_ARG;
-                                break;
-                        }
-                } else {
-                        if (req->req.length != 8) {
-                                req->req.error = RAW1394_ERROR_INVALID_ARG;
-                                break;
-                        }
-                }
-
-                packet = hpsb_make_lockpacket(fi->host, node, addr,
-                                              req->req.misc, NULL, 0);
-                if (!packet) return -ENOMEM;
-
-                if (copy_from_user(packet->data, int2ptr(req->req.sendb),
-                                   req->req.length)) {
-                        req->req.error = RAW1394_ERROR_MEMFAULT;
-                        break;
-                }
-
-                req->data = packet->data;
-                req->req.length = 4;
-                break;
-
-        case RAW1394_REQ_LOCK64:
-                DBGMSG("lock64_request called");
-                if ((req->req.misc == EXTCODE_FETCH_ADD)
-                    || (req->req.misc == EXTCODE_LITTLE_ADD)) {
-                        if (req->req.length != 8) {
-                                req->req.error = RAW1394_ERROR_INVALID_ARG;
-                                break;
-                        }
-                } else {
-                        if (req->req.length != 16) {
-                                req->req.error = RAW1394_ERROR_INVALID_ARG;
-                                break;
-                        }
-                }
-                packet = hpsb_make_lock64packet(fi->host, node, addr,
-                                                req->req.misc, NULL, 0);
-                if (!packet) return -ENOMEM;
-
-                if (copy_from_user(packet->data, int2ptr(req->req.sendb),
-                                   req->req.length)) {
-                        req->req.error = RAW1394_ERROR_MEMFAULT;
-                        break;
-                }
-
-                req->data = packet->data;
-                req->req.length = 8;
-                break;
-
-        default:
-                req->req.error = RAW1394_ERROR_STATE_ORDER;
-        }
-
-        req->packet = packet;
-
-        if (req->req.error) {
-                req->req.length = 0;
-                queue_complete_req(req);
-                return sizeof(struct raw1394_request);
-        }
-
-	hpsb_set_packet_complete_task(packet, (void(*)(void*))queue_complete_cb, req);
-
-        spin_lock_irq(&fi->reqlists_lock);
-        list_add_tail(&req->list, &fi->req_pending);
-        spin_unlock_irq(&fi->reqlists_lock);
+	case RAW1394_REQ_LOCK:
+		DBGMSG("lock_request called");
+		if ((req->req.misc == EXTCODE_FETCH_ADD)
+		    || (req->req.misc == EXTCODE_LITTLE_ADD)) {
+			if (req->req.length != 4) {
+				req->req.error = RAW1394_ERROR_INVALID_ARG;
+				break;
+			}
+		} else {
+			if (req->req.length != 8) {
+				req->req.error = RAW1394_ERROR_INVALID_ARG;
+				break;
+			}
+		}
+
+		packet = hpsb_make_lockpacket(fi->host, node, addr,
+					      req->req.misc, NULL, 0);
+		if (!packet)
+			return -ENOMEM;
+
+		if (copy_from_user(packet->data, int2ptr(req->req.sendb),
+				   req->req.length)) {
+			req->req.error = RAW1394_ERROR_MEMFAULT;
+			break;
+		}
+
+		req->data = packet->data;
+		req->req.length = 4;
+		break;
+
+	case RAW1394_REQ_LOCK64:
+		DBGMSG("lock64_request called");
+		if ((req->req.misc == EXTCODE_FETCH_ADD)
+		    || (req->req.misc == EXTCODE_LITTLE_ADD)) {
+			if (req->req.length != 8) {
+				req->req.error = RAW1394_ERROR_INVALID_ARG;
+				break;
+			}
+		} else {
+			if (req->req.length != 16) {
+				req->req.error = RAW1394_ERROR_INVALID_ARG;
+				break;
+			}
+		}
+		packet = hpsb_make_lock64packet(fi->host, node, addr,
+						req->req.misc, NULL, 0);
+		if (!packet)
+			return -ENOMEM;
+
+		if (copy_from_user(packet->data, int2ptr(req->req.sendb),
+				   req->req.length)) {
+			req->req.error = RAW1394_ERROR_MEMFAULT;
+			break;
+		}
+
+		req->data = packet->data;
+		req->req.length = 8;
+		break;
+
+	default:
+		req->req.error = RAW1394_ERROR_STATE_ORDER;
+	}
+
+	req->packet = packet;
+
+	if (req->req.error) {
+		req->req.length = 0;
+		queue_complete_req(req);
+		return sizeof(struct raw1394_request);
+	}
+
+	hpsb_set_packet_complete_task(packet,
+				      (void (*)(void *))queue_complete_cb, req);
+
+	spin_lock_irq(&fi->reqlists_lock);
+	list_add_tail(&req->list, &fi->req_pending);
+	spin_unlock_irq(&fi->reqlists_lock);
 
 	packet->generation = req->req.generation;
 
-        if (hpsb_send_packet(packet) < 0) {
-                req->req.error = RAW1394_ERROR_SEND_ERROR;
-                req->req.length = 0;
-                hpsb_free_tlabel(packet);
-                queue_complete_req(req);
-        }
-        return sizeof(struct raw1394_request);
+	if (hpsb_send_packet(packet) < 0) {
+		req->req.error = RAW1394_ERROR_SEND_ERROR;
+		req->req.length = 0;
+		hpsb_free_tlabel(packet);
+		queue_complete_req(req);
+	}
+	return sizeof(struct raw1394_request);
 }
 
 static int handle_iso_send(struct file_info *fi, struct pending_request *req,
-                           int channel)
+			   int channel)
 {
-        struct hpsb_packet *packet;
+	struct hpsb_packet *packet;
 
 	packet = hpsb_make_isopacket(fi->host, req->req.length, channel & 0x3f,
-				     (req->req.misc >> 16) & 0x3, req->req.misc & 0xf);
+				     (req->req.misc >> 16) & 0x3,
+				     req->req.misc & 0xf);
 	if (!packet)
 		return -ENOMEM;
 
-        packet->speed_code = req->req.address & 0x3;
+	packet->speed_code = req->req.address & 0x3;
 
 	req->packet = packet;
 
-        if (copy_from_user(packet->data, int2ptr(req->req.sendb),
-                           req->req.length)) {
-                req->req.error = RAW1394_ERROR_MEMFAULT;
-                req->req.length = 0;
-                queue_complete_req(req);
-                return sizeof(struct raw1394_request);
-        }
-
-        req->req.length = 0;
-	hpsb_set_packet_complete_task(packet, (void (*)(void*))queue_complete_req, req);
-
-        spin_lock_irq(&fi->reqlists_lock);
-        list_add_tail(&req->list, &fi->req_pending);
-        spin_unlock_irq(&fi->reqlists_lock);
+	if (copy_from_user(packet->data, int2ptr(req->req.sendb),
+			   req->req.length)) {
+		req->req.error = RAW1394_ERROR_MEMFAULT;
+		req->req.length = 0;
+		queue_complete_req(req);
+		return sizeof(struct raw1394_request);
+	}
+
+	req->req.length = 0;
+	hpsb_set_packet_complete_task(packet,
+				      (void (*)(void *))queue_complete_req,
+				      req);
+
+	spin_lock_irq(&fi->reqlists_lock);
+	list_add_tail(&req->list, &fi->req_pending);
+	spin_unlock_irq(&fi->reqlists_lock);
 
 	/* Update the generation of the packet just before sending. */
 	packet->generation = req->req.generation;
 
-        if (hpsb_send_packet(packet) < 0) {
-                req->req.error = RAW1394_ERROR_SEND_ERROR;
-                queue_complete_req(req);
-        }
+	if (hpsb_send_packet(packet) < 0) {
+		req->req.error = RAW1394_ERROR_SEND_ERROR;
+		queue_complete_req(req);
+	}
 
-        return sizeof(struct raw1394_request);
+	return sizeof(struct raw1394_request);
 }
 
 static int handle_async_send(struct file_info *fi, struct pending_request *req)
 {
-        struct hpsb_packet *packet;
-        int header_length = req->req.misc & 0xffff;
-        int expect_response = req->req.misc >> 16;
-
-        if ((header_length > req->req.length) ||
-            (header_length  < 12)) {
-                req->req.error = RAW1394_ERROR_INVALID_ARG;
-                req->req.length = 0;
-                queue_complete_req(req);
-                return sizeof(struct raw1394_request);
-        }
-
-        packet = hpsb_alloc_packet(req->req.length-header_length);
-        req->packet = packet;
-        if (!packet) return -ENOMEM;
-
-        if (copy_from_user(packet->header, int2ptr(req->req.sendb),
-                           header_length)) {
-                req->req.error = RAW1394_ERROR_MEMFAULT;
-                req->req.length = 0;
-                queue_complete_req(req);
-                return sizeof(struct raw1394_request);
-        }
-
-        if (copy_from_user(packet->data, int2ptr(req->req.sendb) + header_length,
-                           packet->data_size)) {
-                req->req.error = RAW1394_ERROR_MEMFAULT;
-                req->req.length = 0;
-                queue_complete_req(req);
-                return sizeof(struct raw1394_request);
-        }
-
-        packet->type = hpsb_async;
-        packet->node_id = packet->header[0] >> 16;
-        packet->tcode = (packet->header[0] >> 4) & 0xf;
-        packet->tlabel = (packet->header[0] >> 10) &0x3f;
-        packet->host = fi->host;
-        packet->expect_response = expect_response;
-        packet->header_size=header_length;
-        packet->data_size=req->req.length-header_length;
-
-        req->req.length = 0;
-        hpsb_set_packet_complete_task(packet, (void(*)(void*))queue_complete_cb, req);
-
-        spin_lock_irq(&fi->reqlists_lock);
-        list_add_tail(&req->list, &fi->req_pending);
-        spin_unlock_irq(&fi->reqlists_lock);
-
-        /* Update the generation of the packet just before sending. */
-        packet->generation = req->req.generation;
-
-        if (hpsb_send_packet(packet) < 0) {
-                req->req.error = RAW1394_ERROR_SEND_ERROR;
-                queue_complete_req(req);
-        }
-
-        return sizeof(struct raw1394_request);
-}
-
-static int arm_read (struct hpsb_host *host, int nodeid, quadlet_t *buffer,
-		     u64 addr, size_t length, u16 flags)
-{
-        struct pending_request *req;
-        struct host_info *hi;
-        struct file_info *fi = NULL;
-        struct list_head *entry;
-        struct arm_addr  *arm_addr = NULL;
-        struct arm_request  *arm_req = NULL;
-        struct arm_response *arm_resp = NULL;
-        int found=0, size=0, rcode=-1;
-        struct arm_request_response *arm_req_resp = NULL;
-
-        DBGMSG("arm_read  called by node: %X"
-              "addr: %4.4x %8.8x length: %Zu", nodeid,
-              (u16) ((addr >>32) & 0xFFFF), (u32) (addr & 0xFFFFFFFF),
-              length);
-        spin_lock(&host_info_lock);
-        hi = find_host_info(host); /* search address-entry */
-        if (hi != NULL) {
-                list_for_each_entry(fi, &hi->file_info_list, list) {
-                        entry = fi->addr_list.next;
-                        while (entry != &(fi->addr_list)) {
-                                arm_addr = list_entry(entry, struct arm_addr, addr_list);
-                                if (((arm_addr->start) <= (addr)) &&
-                                        ((arm_addr->end) >= (addr+length))) {
-                                        found = 1;
-                                        break;
-                                }
-                                entry = entry->next;
-                        }
-                        if (found) {
-                                break;
-                        }
-                }
-        }
-        rcode = -1;
-        if (!found) {
-                printk(KERN_ERR "raw1394: arm_read FAILED addr_entry not found"
-                " -> rcode_address_error\n");
-                spin_unlock(&host_info_lock);
-                return (RCODE_ADDRESS_ERROR);
-        } else {
-                DBGMSG("arm_read addr_entry FOUND");
-        }
-        if (arm_addr->rec_length < length) {
-                DBGMSG("arm_read blocklength too big -> rcode_data_error");
-                rcode = RCODE_DATA_ERROR; /* hardware error, data is unavailable */
-        }
-        if (rcode == -1) {
-                if (arm_addr->access_rights & ARM_READ) {
-                        if (!(arm_addr->client_transactions & ARM_READ)) {
-                                memcpy(buffer,(arm_addr->addr_space_buffer)+(addr-(arm_addr->start)),
-                                       length);
-                                DBGMSG("arm_read -> (rcode_complete)");
-                                rcode = RCODE_COMPLETE;
-                        }
-                } else {
-                        rcode = RCODE_TYPE_ERROR; /* function not allowed */
-                        DBGMSG("arm_read -> rcode_type_error (access denied)");
-                }
-        }
-        if (arm_addr->notification_options & ARM_READ) {
-                DBGMSG("arm_read -> entering notification-section");
-                req = __alloc_pending_request(SLAB_ATOMIC);
-                if (!req) {
-                        DBGMSG("arm_read -> rcode_conflict_error");
-                        spin_unlock(&host_info_lock);
-                        return(RCODE_CONFLICT_ERROR); /* A resource conflict was detected.
-                                                        The request may be retried */
-                }
-                if (rcode == RCODE_COMPLETE) {
-                        size =  sizeof(struct arm_request)+sizeof(struct arm_response) +
-                                length * sizeof(byte_t) +
-                                sizeof (struct arm_request_response);
-                } else {
-                        size =  sizeof(struct arm_request)+sizeof(struct arm_response) +
-                                sizeof (struct arm_request_response);
-                }
-                req->data = kmalloc(size, SLAB_ATOMIC);
-                if (!(req->data)) {
-                        free_pending_request(req);
-                        DBGMSG("arm_read -> rcode_conflict_error");
-                        spin_unlock(&host_info_lock);
-                        return(RCODE_CONFLICT_ERROR); /* A resource conflict was detected.
-                                                        The request may be retried */
-                }
-                req->free_data=1;
-                req->file_info = fi;
-                req->req.type = RAW1394_REQ_ARM;
-                req->req.generation = get_hpsb_generation(host);
-                req->req.misc = ( ((length << 16) & (0xFFFF0000)) | (ARM_READ & 0xFF));
-                req->req.tag  = arm_addr->arm_tag;
-                req->req.recvb = arm_addr->recvb;
-                req->req.length = size;
-                arm_req_resp = (struct arm_request_response *) (req->data);
-                arm_req  = (struct arm_request *) ((byte_t *)(req->data) +
-                        (sizeof (struct arm_request_response)));
-                arm_resp = (struct arm_response *) ((byte_t *)(arm_req) +
-                        (sizeof(struct arm_request)));
-                arm_req->buffer  = NULL;
-                arm_resp->buffer = NULL;
-                if (rcode == RCODE_COMPLETE) {
-                        byte_t *buf = (byte_t *)arm_resp + sizeof(struct arm_response);
-                        memcpy (buf,
-                                (arm_addr->addr_space_buffer)+(addr-(arm_addr->start)),
-                                length);
-                        arm_resp->buffer = int2ptr((arm_addr->recvb) +
-                                sizeof (struct arm_request_response) +
-                                sizeof (struct arm_request) +
-                                sizeof (struct arm_response));
-                }
-                arm_resp->buffer_length = (rcode == RCODE_COMPLETE) ? length : 0;
-                arm_resp->response_code = rcode;
-                arm_req->buffer_length = 0;
-                arm_req->generation = req->req.generation;
-                arm_req->extended_transaction_code = 0;
-                arm_req->destination_offset = addr;
-                arm_req->source_nodeid = nodeid;
-                arm_req->destination_nodeid = host->node_id;
-                arm_req->tlabel = (flags >> 10) & 0x3f;
-                arm_req->tcode = (flags >> 4) & 0x0f;
-                arm_req_resp->request  = int2ptr((arm_addr->recvb) +
-                        sizeof (struct arm_request_response));
-                arm_req_resp->response = int2ptr((arm_addr->recvb) +
-                        sizeof (struct arm_request_response) +
-                        sizeof (struct arm_request));
-                queue_complete_req(req);
-        }
-        spin_unlock(&host_info_lock);
-        return(rcode);
-}
-
-static int arm_write (struct hpsb_host *host, int nodeid, int destid,
-		      quadlet_t *data, u64 addr, size_t length, u16 flags)
-{
-        struct pending_request *req;
-        struct host_info *hi;
-        struct file_info *fi = NULL;
-        struct list_head *entry;
-        struct arm_addr  *arm_addr = NULL;
-        struct arm_request  *arm_req = NULL;
-        struct arm_response *arm_resp = NULL;
-        int found=0, size=0, rcode=-1, length_conflict=0;
-        struct arm_request_response *arm_req_resp = NULL;
-
-        DBGMSG("arm_write called by node: %X"
-              "addr: %4.4x %8.8x length: %Zu", nodeid,
-              (u16) ((addr >>32) & 0xFFFF), (u32) (addr & 0xFFFFFFFF),
-              length);
-        spin_lock(&host_info_lock);
-        hi = find_host_info(host); /* search address-entry */
-        if (hi != NULL) {
-                list_for_each_entry(fi, &hi->file_info_list, list) {
-                        entry = fi->addr_list.next;
-                        while (entry != &(fi->addr_list)) {
-                                arm_addr = list_entry(entry, struct arm_addr, addr_list);
-                                if (((arm_addr->start) <= (addr)) &&
-                                        ((arm_addr->end) >= (addr+length))) {
-                                        found = 1;
-                                        break;
-                                }
-                                entry = entry->next;
-                        }
-                        if (found) {
-                                break;
-                        }
-                }
-        }
-        rcode = -1;
-        if (!found) {
-                printk(KERN_ERR "raw1394: arm_write FAILED addr_entry not found"
-                " -> rcode_address_error\n");
-                spin_unlock(&host_info_lock);
-                return (RCODE_ADDRESS_ERROR);
-        } else {
-                DBGMSG("arm_write addr_entry FOUND");
-        }
-        if (arm_addr->rec_length < length) {
-                DBGMSG("arm_write blocklength too big -> rcode_data_error");
-                length_conflict = 1;
-                rcode = RCODE_DATA_ERROR; /* hardware error, data is unavailable */
-        }
-        if (rcode == -1) {
-                if (arm_addr->access_rights & ARM_WRITE) {
-                        if (!(arm_addr->client_transactions & ARM_WRITE)) {
-                                memcpy((arm_addr->addr_space_buffer)+(addr-(arm_addr->start)),
-                                        data, length);
-                                DBGMSG("arm_write -> (rcode_complete)");
-                                rcode = RCODE_COMPLETE;
-                        }
-                } else {
-                        rcode = RCODE_TYPE_ERROR; /* function not allowed */
-                        DBGMSG("arm_write -> rcode_type_error (access denied)");
-                }
-        }
-        if (arm_addr->notification_options & ARM_WRITE) {
-                DBGMSG("arm_write -> entering notification-section");
-                req = __alloc_pending_request(SLAB_ATOMIC);
-                if (!req) {
-                        DBGMSG("arm_write -> rcode_conflict_error");
-                        spin_unlock(&host_info_lock);
-                        return(RCODE_CONFLICT_ERROR); /* A resource conflict was detected.
-                                                        The request my be retried */
-                }
-                size =  sizeof(struct arm_request)+sizeof(struct arm_response) +
-                        (length) * sizeof(byte_t) +
-                        sizeof (struct arm_request_response);
-                req->data = kmalloc(size, SLAB_ATOMIC);
-                if (!(req->data)) {
-                        free_pending_request(req);
-                        DBGMSG("arm_write -> rcode_conflict_error");
-                        spin_unlock(&host_info_lock);
-                        return(RCODE_CONFLICT_ERROR); /* A resource conflict was detected.
-                                                        The request may be retried */
-                }
-                req->free_data=1;
-                req->file_info = fi;
-                req->req.type = RAW1394_REQ_ARM;
-                req->req.generation = get_hpsb_generation(host);
-                req->req.misc = ( ((length << 16) & (0xFFFF0000)) | (ARM_WRITE & 0xFF));
-                req->req.tag  = arm_addr->arm_tag;
-                req->req.recvb = arm_addr->recvb;
-                req->req.length = size;
-                arm_req_resp = (struct arm_request_response *) (req->data);
-                arm_req  = (struct arm_request *) ((byte_t *)(req->data) +
-                        (sizeof (struct arm_request_response)));
-                arm_resp = (struct arm_response *) ((byte_t *)(arm_req) +
-                        (sizeof(struct arm_request)));
-                arm_resp->buffer = NULL;
-                memcpy ((byte_t *)arm_resp + sizeof(struct arm_response),
-			data, length);
-                arm_req->buffer = int2ptr((arm_addr->recvb) +
-                        sizeof (struct arm_request_response) +
-                        sizeof (struct arm_request) +
-                        sizeof (struct arm_response));
-                arm_req->buffer_length = length;
-                arm_req->generation = req->req.generation;
-                arm_req->extended_transaction_code = 0;
-                arm_req->destination_offset = addr;
-                arm_req->source_nodeid = nodeid;
-                arm_req->destination_nodeid = destid;
-                arm_req->tlabel = (flags >> 10) & 0x3f;
-                arm_req->tcode = (flags >> 4) & 0x0f;
-                arm_resp->buffer_length = 0;
-                arm_resp->response_code = rcode;
-                arm_req_resp->request  = int2ptr((arm_addr->recvb) +
-                        sizeof (struct arm_request_response));
-                arm_req_resp->response = int2ptr((arm_addr->recvb) +
-                        sizeof (struct arm_request_response) +
-                        sizeof (struct arm_request));
-                queue_complete_req(req);
-        }
-        spin_unlock(&host_info_lock);
-        return(rcode);
-}
-
-static int arm_lock (struct hpsb_host *host, int nodeid, quadlet_t *store,
-             u64 addr, quadlet_t data, quadlet_t arg, int ext_tcode, u16 flags)
-{
-        struct pending_request *req;
-        struct host_info *hi;
-        struct file_info *fi = NULL;
-        struct list_head *entry;
-        struct arm_addr  *arm_addr = NULL;
-        struct arm_request  *arm_req = NULL;
-        struct arm_response *arm_resp = NULL;
-        int found=0, size=0, rcode=-1;
-        quadlet_t old, new;
-        struct arm_request_response *arm_req_resp = NULL;
-
-        if (((ext_tcode & 0xFF) == EXTCODE_FETCH_ADD) ||
-                ((ext_tcode & 0xFF) == EXTCODE_LITTLE_ADD)) {
-                DBGMSG("arm_lock  called by node: %X "
-                      "addr: %4.4x %8.8x extcode: %2.2X data: %8.8X",
-                      nodeid, (u16) ((addr >>32) & 0xFFFF), (u32) (addr & 0xFFFFFFFF),
-                      ext_tcode & 0xFF , be32_to_cpu(data));
-        } else {
-                DBGMSG("arm_lock  called by node: %X "
-                      "addr: %4.4x %8.8x extcode: %2.2X data: %8.8X arg: %8.8X",
-                      nodeid, (u16) ((addr >>32) & 0xFFFF), (u32) (addr & 0xFFFFFFFF),
-                      ext_tcode & 0xFF , be32_to_cpu(data), be32_to_cpu(arg));
-        }
-        spin_lock(&host_info_lock);
-        hi = find_host_info(host); /* search address-entry */
-        if (hi != NULL) {
-                list_for_each_entry(fi, &hi->file_info_list, list) {
-                        entry = fi->addr_list.next;
-                        while (entry != &(fi->addr_list)) {
-                                arm_addr = list_entry(entry, struct arm_addr, addr_list);
-                                if (((arm_addr->start) <= (addr)) &&
-                                        ((arm_addr->end) >= (addr+sizeof(*store)))) {
-                                        found = 1;
-                                        break;
-                                }
-                                entry = entry->next;
-                        }
-                        if (found) {
-                                break;
-                        }
-                }
-        }
-        rcode = -1;
-        if (!found) {
-                printk(KERN_ERR "raw1394: arm_lock FAILED addr_entry not found"
-                " -> rcode_address_error\n");
-                spin_unlock(&host_info_lock);
-                return (RCODE_ADDRESS_ERROR);
-        } else {
-                DBGMSG("arm_lock addr_entry FOUND");
-        }
-        if (rcode == -1) {
-                if (arm_addr->access_rights & ARM_LOCK) {
-                        if (!(arm_addr->client_transactions & ARM_LOCK)) {
-                                memcpy(&old,(arm_addr->addr_space_buffer)+(addr-(arm_addr->start)),
-                                        sizeof(old));
-                                switch (ext_tcode) {
-                                        case (EXTCODE_MASK_SWAP):
-                                                new = data | (old & ~arg);
-                                                break;
-                                        case (EXTCODE_COMPARE_SWAP):
-                                                if (old == arg) {
-                                                        new = data;
-                                                } else {
-                                                        new = old;
-                                                }
-                                                break;
-                                        case (EXTCODE_FETCH_ADD):
-                                                new = cpu_to_be32(be32_to_cpu(data) + be32_to_cpu(old));
-                                                break;
-                                        case (EXTCODE_LITTLE_ADD):
-                                                new = cpu_to_le32(le32_to_cpu(data) + le32_to_cpu(old));
-                                                break;
-                                        case (EXTCODE_BOUNDED_ADD):
-                                                if (old != arg) {
-                                                        new = cpu_to_be32(be32_to_cpu(data) +
-                                                                be32_to_cpu(old));
-                                                } else {
-                                                        new = old;
-                                                }
-                                                break;
-                                        case (EXTCODE_WRAP_ADD):
-                                                if (old != arg) {
-                                                        new = cpu_to_be32(be32_to_cpu(data) +
-                                                                be32_to_cpu(old));
-                                                } else {
-                                                        new = data;
-                                                }
-                                                break;
-                                        default:
-                                                rcode = RCODE_TYPE_ERROR; /* function not allowed */
-                                                printk(KERN_ERR "raw1394: arm_lock FAILED "
-                                                "ext_tcode not allowed -> rcode_type_error\n");
-                                                break;
-                                } /*switch*/
-                                if (rcode == -1) {
-                                        DBGMSG("arm_lock -> (rcode_complete)");
-                                        rcode = RCODE_COMPLETE;
-                                        memcpy (store, &old, sizeof(*store));
-                                        memcpy ((arm_addr->addr_space_buffer)+
-                                                (addr-(arm_addr->start)),
-                                                &new, sizeof(*store));
-                                }
-                        }
-                } else {
-                        rcode = RCODE_TYPE_ERROR; /* function not allowed */
-                        DBGMSG("arm_lock -> rcode_type_error (access denied)");
-                }
-        }
-        if (arm_addr->notification_options & ARM_LOCK) {
+	struct hpsb_packet *packet;
+	int header_length = req->req.misc & 0xffff;
+	int expect_response = req->req.misc >> 16;
+
+	if ((header_length > req->req.length) || (header_length < 12)) {
+		req->req.error = RAW1394_ERROR_INVALID_ARG;
+		req->req.length = 0;
+		queue_complete_req(req);
+		return sizeof(struct raw1394_request);
+	}
+
+	packet = hpsb_alloc_packet(req->req.length - header_length);
+	req->packet = packet;
+	if (!packet)
+		return -ENOMEM;
+
+	if (copy_from_user(packet->header, int2ptr(req->req.sendb),
+			   header_length)) {
+		req->req.error = RAW1394_ERROR_MEMFAULT;
+		req->req.length = 0;
+		queue_complete_req(req);
+		return sizeof(struct raw1394_request);
+	}
+
+	if (copy_from_user
+	    (packet->data, int2ptr(req->req.sendb) + header_length,
+	     packet->data_size)) {
+		req->req.error = RAW1394_ERROR_MEMFAULT;
+		req->req.length = 0;
+		queue_complete_req(req);
+		return sizeof(struct raw1394_request);
+	}
+
+	packet->type = hpsb_async;
+	packet->node_id = packet->header[0] >> 16;
+	packet->tcode = (packet->header[0] >> 4) & 0xf;
+	packet->tlabel = (packet->header[0] >> 10) & 0x3f;
+	packet->host = fi->host;
+	packet->expect_response = expect_response;
+	packet->header_size = header_length;
+	packet->data_size = req->req.length - header_length;
+
+	req->req.length = 0;
+	hpsb_set_packet_complete_task(packet,
+				      (void (*)(void *))queue_complete_cb, req);
+
+	spin_lock_irq(&fi->reqlists_lock);
+	list_add_tail(&req->list, &fi->req_pending);
+	spin_unlock_irq(&fi->reqlists_lock);
+
+	/* Update the generation of the packet just before sending. */
+	packet->generation = req->req.generation;
+
+	if (hpsb_send_packet(packet) < 0) {
+		req->req.error = RAW1394_ERROR_SEND_ERROR;
+		queue_complete_req(req);
+	}
+
+	return sizeof(struct raw1394_request);
+}
+
+static int arm_read(struct hpsb_host *host, int nodeid, quadlet_t * buffer,
+		    u64 addr, size_t length, u16 flags)
+{
+	struct pending_request *req;
+	struct host_info *hi;
+	struct file_info *fi = NULL;
+	struct list_head *entry;
+	struct arm_addr *arm_addr = NULL;
+	struct arm_request *arm_req = NULL;
+	struct arm_response *arm_resp = NULL;
+	int found = 0, size = 0, rcode = -1;
+	struct arm_request_response *arm_req_resp = NULL;
+
+	DBGMSG("arm_read  called by node: %X"
+	       "addr: %4.4x %8.8x length: %Zu", nodeid,
+	       (u16) ((addr >> 32) & 0xFFFF), (u32) (addr & 0xFFFFFFFF),
+	       length);
+	spin_lock(&host_info_lock);
+	hi = find_host_info(host);	/* search address-entry */
+	if (hi != NULL) {
+		list_for_each_entry(fi, &hi->file_info_list, list) {
+			entry = fi->addr_list.next;
+			while (entry != &(fi->addr_list)) {
+				arm_addr =
+				    list_entry(entry, struct arm_addr,
+					       addr_list);
+				if (((arm_addr->start) <= (addr))
+				    && ((arm_addr->end) >= (addr + length))) {
+					found = 1;
+					break;
+				}
+				entry = entry->next;
+			}
+			if (found) {
+				break;
+			}
+		}
+	}
+	rcode = -1;
+	if (!found) {
+		printk(KERN_ERR "raw1394: arm_read FAILED addr_entry not found"
+		       " -> rcode_address_error\n");
+		spin_unlock(&host_info_lock);
+		return (RCODE_ADDRESS_ERROR);
+	} else {
+		DBGMSG("arm_read addr_entry FOUND");
+	}
+	if (arm_addr->rec_length < length) {
+		DBGMSG("arm_read blocklength too big -> rcode_data_error");
+		rcode = RCODE_DATA_ERROR;	/* hardware error, data is unavailable */
+	}
+	if (rcode == -1) {
+		if (arm_addr->access_rights & ARM_READ) {
+			if (!(arm_addr->client_transactions & ARM_READ)) {
+				memcpy(buffer,
+				       (arm_addr->addr_space_buffer) + (addr -
+									(arm_addr->
+									 start)),
+				       length);
+				DBGMSG("arm_read -> (rcode_complete)");
+				rcode = RCODE_COMPLETE;
+			}
+		} else {
+			rcode = RCODE_TYPE_ERROR;	/* function not allowed */
+			DBGMSG("arm_read -> rcode_type_error (access denied)");
+		}
+	}
+	if (arm_addr->notification_options & ARM_READ) {
+		DBGMSG("arm_read -> entering notification-section");
+		req = __alloc_pending_request(SLAB_ATOMIC);
+		if (!req) {
+			DBGMSG("arm_read -> rcode_conflict_error");
+			spin_unlock(&host_info_lock);
+			return (RCODE_CONFLICT_ERROR);	/* A resource conflict was detected.
+							   The request may be retried */
+		}
+		if (rcode == RCODE_COMPLETE) {
+			size =
+			    sizeof(struct arm_request) +
+			    sizeof(struct arm_response) +
+			    length * sizeof(byte_t) +
+			    sizeof(struct arm_request_response);
+		} else {
+			size =
+			    sizeof(struct arm_request) +
+			    sizeof(struct arm_response) +
+			    sizeof(struct arm_request_response);
+		}
+		req->data = kmalloc(size, SLAB_ATOMIC);
+		if (!(req->data)) {
+			free_pending_request(req);
+			DBGMSG("arm_read -> rcode_conflict_error");
+			spin_unlock(&host_info_lock);
+			return (RCODE_CONFLICT_ERROR);	/* A resource conflict was detected.
+							   The request may be retried */
+		}
+		req->free_data = 1;
+		req->file_info = fi;
+		req->req.type = RAW1394_REQ_ARM;
+		req->req.generation = get_hpsb_generation(host);
+		req->req.misc =
+		    (((length << 16) & (0xFFFF0000)) | (ARM_READ & 0xFF));
+		req->req.tag = arm_addr->arm_tag;
+		req->req.recvb = arm_addr->recvb;
+		req->req.length = size;
+		arm_req_resp = (struct arm_request_response *)(req->data);
+		arm_req = (struct arm_request *)((byte_t *) (req->data) +
+						 (sizeof
+						  (struct
+						   arm_request_response)));
+		arm_resp =
+		    (struct arm_response *)((byte_t *) (arm_req) +
+					    (sizeof(struct arm_request)));
+		arm_req->buffer = NULL;
+		arm_resp->buffer = NULL;
+		if (rcode == RCODE_COMPLETE) {
+			byte_t *buf =
+			    (byte_t *) arm_resp + sizeof(struct arm_response);
+			memcpy(buf,
+			       (arm_addr->addr_space_buffer) + (addr -
+								(arm_addr->
+								 start)),
+			       length);
+			arm_resp->buffer =
+			    int2ptr((arm_addr->recvb) +
+				    sizeof(struct arm_request_response) +
+				    sizeof(struct arm_request) +
+				    sizeof(struct arm_response));
+		}
+		arm_resp->buffer_length =
+		    (rcode == RCODE_COMPLETE) ? length : 0;
+		arm_resp->response_code = rcode;
+		arm_req->buffer_length = 0;
+		arm_req->generation = req->req.generation;
+		arm_req->extended_transaction_code = 0;
+		arm_req->destination_offset = addr;
+		arm_req->source_nodeid = nodeid;
+		arm_req->destination_nodeid = host->node_id;
+		arm_req->tlabel = (flags >> 10) & 0x3f;
+		arm_req->tcode = (flags >> 4) & 0x0f;
+		arm_req_resp->request = int2ptr((arm_addr->recvb) +
+						sizeof(struct
+						       arm_request_response));
+		arm_req_resp->response =
+		    int2ptr((arm_addr->recvb) +
+			    sizeof(struct arm_request_response) +
+			    sizeof(struct arm_request));
+		queue_complete_req(req);
+	}
+	spin_unlock(&host_info_lock);
+	return (rcode);
+}
+
+static int arm_write(struct hpsb_host *host, int nodeid, int destid,
+		     quadlet_t * data, u64 addr, size_t length, u16 flags)
+{
+	struct pending_request *req;
+	struct host_info *hi;
+	struct file_info *fi = NULL;
+	struct list_head *entry;
+	struct arm_addr *arm_addr = NULL;
+	struct arm_request *arm_req = NULL;
+	struct arm_response *arm_resp = NULL;
+	int found = 0, size = 0, rcode = -1, length_conflict = 0;
+	struct arm_request_response *arm_req_resp = NULL;
+
+	DBGMSG("arm_write called by node: %X"
+	       "addr: %4.4x %8.8x length: %Zu", nodeid,
+	       (u16) ((addr >> 32) & 0xFFFF), (u32) (addr & 0xFFFFFFFF),
+	       length);
+	spin_lock(&host_info_lock);
+	hi = find_host_info(host);	/* search address-entry */
+	if (hi != NULL) {
+		list_for_each_entry(fi, &hi->file_info_list, list) {
+			entry = fi->addr_list.next;
+			while (entry != &(fi->addr_list)) {
+				arm_addr =
+				    list_entry(entry, struct arm_addr,
+					       addr_list);
+				if (((arm_addr->start) <= (addr))
+				    && ((arm_addr->end) >= (addr + length))) {
+					found = 1;
+					break;
+				}
+				entry = entry->next;
+			}
+			if (found) {
+				break;
+			}
+		}
+	}
+	rcode = -1;
+	if (!found) {
+		printk(KERN_ERR "raw1394: arm_write FAILED addr_entry not found"
+		       " -> rcode_address_error\n");
+		spin_unlock(&host_info_lock);
+		return (RCODE_ADDRESS_ERROR);
+	} else {
+		DBGMSG("arm_write addr_entry FOUND");
+	}
+	if (arm_addr->rec_length < length) {
+		DBGMSG("arm_write blocklength too big -> rcode_data_error");
+		length_conflict = 1;
+		rcode = RCODE_DATA_ERROR;	/* hardware error, data is unavailable */
+	}
+	if (rcode == -1) {
+		if (arm_addr->access_rights & ARM_WRITE) {
+			if (!(arm_addr->client_transactions & ARM_WRITE)) {
+				memcpy((arm_addr->addr_space_buffer) +
+				       (addr - (arm_addr->start)), data,
+				       length);
+				DBGMSG("arm_write -> (rcode_complete)");
+				rcode = RCODE_COMPLETE;
+			}
+		} else {
+			rcode = RCODE_TYPE_ERROR;	/* function not allowed */
+			DBGMSG("arm_write -> rcode_type_error (access denied)");
+		}
+	}
+	if (arm_addr->notification_options & ARM_WRITE) {
+		DBGMSG("arm_write -> entering notification-section");
+		req = __alloc_pending_request(SLAB_ATOMIC);
+		if (!req) {
+			DBGMSG("arm_write -> rcode_conflict_error");
+			spin_unlock(&host_info_lock);
+			return (RCODE_CONFLICT_ERROR);	/* A resource conflict was detected.
+							   The request my be retried */
+		}
+		size =
+		    sizeof(struct arm_request) + sizeof(struct arm_response) +
+		    (length) * sizeof(byte_t) +
+		    sizeof(struct arm_request_response);
+		req->data = kmalloc(size, SLAB_ATOMIC);
+		if (!(req->data)) {
+			free_pending_request(req);
+			DBGMSG("arm_write -> rcode_conflict_error");
+			spin_unlock(&host_info_lock);
+			return (RCODE_CONFLICT_ERROR);	/* A resource conflict was detected.
+							   The request may be retried */
+		}
+		req->free_data = 1;
+		req->file_info = fi;
+		req->req.type = RAW1394_REQ_ARM;
+		req->req.generation = get_hpsb_generation(host);
+		req->req.misc =
+		    (((length << 16) & (0xFFFF0000)) | (ARM_WRITE & 0xFF));
+		req->req.tag = arm_addr->arm_tag;
+		req->req.recvb = arm_addr->recvb;
+		req->req.length = size;
+		arm_req_resp = (struct arm_request_response *)(req->data);
+		arm_req = (struct arm_request *)((byte_t *) (req->data) +
+						 (sizeof
+						  (struct
+						   arm_request_response)));
+		arm_resp =
+		    (struct arm_response *)((byte_t *) (arm_req) +
+					    (sizeof(struct arm_request)));
+		arm_resp->buffer = NULL;
+		memcpy((byte_t *) arm_resp + sizeof(struct arm_response),
+		       data, length);
+		arm_req->buffer = int2ptr((arm_addr->recvb) +
+					  sizeof(struct arm_request_response) +
+					  sizeof(struct arm_request) +
+					  sizeof(struct arm_response));
+		arm_req->buffer_length = length;
+		arm_req->generation = req->req.generation;
+		arm_req->extended_transaction_code = 0;
+		arm_req->destination_offset = addr;
+		arm_req->source_nodeid = nodeid;
+		arm_req->destination_nodeid = destid;
+		arm_req->tlabel = (flags >> 10) & 0x3f;
+		arm_req->tcode = (flags >> 4) & 0x0f;
+		arm_resp->buffer_length = 0;
+		arm_resp->response_code = rcode;
+		arm_req_resp->request = int2ptr((arm_addr->recvb) +
+						sizeof(struct
+						       arm_request_response));
+		arm_req_resp->response =
+		    int2ptr((arm_addr->recvb) +
+			    sizeof(struct arm_request_response) +
+			    sizeof(struct arm_request));
+		queue_complete_req(req);
+	}
+	spin_unlock(&host_info_lock);
+	return (rcode);
+}
+
+static int arm_lock(struct hpsb_host *host, int nodeid, quadlet_t * store,
+		    u64 addr, quadlet_t data, quadlet_t arg, int ext_tcode,
+		    u16 flags)
+{
+	struct pending_request *req;
+	struct host_info *hi;
+	struct file_info *fi = NULL;
+	struct list_head *entry;
+	struct arm_addr *arm_addr = NULL;
+	struct arm_request *arm_req = NULL;
+	struct arm_response *arm_resp = NULL;
+	int found = 0, size = 0, rcode = -1;
+	quadlet_t old, new;
+	struct arm_request_response *arm_req_resp = NULL;
+
+	if (((ext_tcode & 0xFF) == EXTCODE_FETCH_ADD) ||
+	    ((ext_tcode & 0xFF) == EXTCODE_LITTLE_ADD)) {
+		DBGMSG("arm_lock  called by node: %X "
+		       "addr: %4.4x %8.8x extcode: %2.2X data: %8.8X",
+		       nodeid, (u16) ((addr >> 32) & 0xFFFF),
+		       (u32) (addr & 0xFFFFFFFF), ext_tcode & 0xFF,
+		       be32_to_cpu(data));
+	} else {
+		DBGMSG("arm_lock  called by node: %X "
+		       "addr: %4.4x %8.8x extcode: %2.2X data: %8.8X arg: %8.8X",
+		       nodeid, (u16) ((addr >> 32) & 0xFFFF),
+		       (u32) (addr & 0xFFFFFFFF), ext_tcode & 0xFF,
+		       be32_to_cpu(data), be32_to_cpu(arg));
+	}
+	spin_lock(&host_info_lock);
+	hi = find_host_info(host);	/* search address-entry */
+	if (hi != NULL) {
+		list_for_each_entry(fi, &hi->file_info_list, list) {
+			entry = fi->addr_list.next;
+			while (entry != &(fi->addr_list)) {
+				arm_addr =
+				    list_entry(entry, struct arm_addr,
+					       addr_list);
+				if (((arm_addr->start) <= (addr))
+				    && ((arm_addr->end) >=
+					(addr + sizeof(*store)))) {
+					found = 1;
+					break;
+				}
+				entry = entry->next;
+			}
+			if (found) {
+				break;
+			}
+		}
+	}
+	rcode = -1;
+	if (!found) {
+		printk(KERN_ERR "raw1394: arm_lock FAILED addr_entry not found"
+		       " -> rcode_address_error\n");
+		spin_unlock(&host_info_lock);
+		return (RCODE_ADDRESS_ERROR);
+	} else {
+		DBGMSG("arm_lock addr_entry FOUND");
+	}
+	if (rcode == -1) {
+		if (arm_addr->access_rights & ARM_LOCK) {
+			if (!(arm_addr->client_transactions & ARM_LOCK)) {
+				memcpy(&old,
+				       (arm_addr->addr_space_buffer) + (addr -
+									(arm_addr->
+									 start)),
+				       sizeof(old));
+				switch (ext_tcode) {
+				case (EXTCODE_MASK_SWAP):
+					new = data | (old & ~arg);
+					break;
+				case (EXTCODE_COMPARE_SWAP):
+					if (old == arg) {
+						new = data;
+					} else {
+						new = old;
+					}
+					break;
+				case (EXTCODE_FETCH_ADD):
+					new =
+					    cpu_to_be32(be32_to_cpu(data) +
+							be32_to_cpu(old));
+					break;
+				case (EXTCODE_LITTLE_ADD):
+					new =
+					    cpu_to_le32(le32_to_cpu(data) +
+							le32_to_cpu(old));
+					break;
+				case (EXTCODE_BOUNDED_ADD):
+					if (old != arg) {
+						new =
+						    cpu_to_be32(be32_to_cpu
+								(data) +
+								be32_to_cpu
+								(old));
+					} else {
+						new = old;
+					}
+					break;
+				case (EXTCODE_WRAP_ADD):
+					if (old != arg) {
+						new =
+						    cpu_to_be32(be32_to_cpu
+								(data) +
+								be32_to_cpu
+								(old));
+					} else {
+						new = data;
+					}
+					break;
+				default:
+					rcode = RCODE_TYPE_ERROR;	/* function not allowed */
+					printk(KERN_ERR
+					       "raw1394: arm_lock FAILED "
+					       "ext_tcode not allowed -> rcode_type_error\n");
+					break;
+				}	/*switch */
+				if (rcode == -1) {
+					DBGMSG("arm_lock -> (rcode_complete)");
+					rcode = RCODE_COMPLETE;
+					memcpy(store, &old, sizeof(*store));
+					memcpy((arm_addr->addr_space_buffer) +
+					       (addr - (arm_addr->start)),
+					       &new, sizeof(*store));
+				}
+			}
+		} else {
+			rcode = RCODE_TYPE_ERROR;	/* function not allowed */
+			DBGMSG("arm_lock -> rcode_type_error (access denied)");
+		}
+	}
+	if (arm_addr->notification_options & ARM_LOCK) {
 		byte_t *buf1, *buf2;
-                DBGMSG("arm_lock -> entering notification-section");
-                req = __alloc_pending_request(SLAB_ATOMIC);
-                if (!req) {
-                        DBGMSG("arm_lock -> rcode_conflict_error");
-                        spin_unlock(&host_info_lock);
-                        return(RCODE_CONFLICT_ERROR); /* A resource conflict was detected.
-                                                        The request may be retried */
-                }
-                size =  sizeof(struct arm_request)+sizeof(struct arm_response) +
-                        3 * sizeof(*store) +
-                        sizeof (struct arm_request_response);  /* maximum */
-                req->data = kmalloc(size, SLAB_ATOMIC);
-                if (!(req->data)) {
-                        free_pending_request(req);
-                        DBGMSG("arm_lock -> rcode_conflict_error");
-                        spin_unlock(&host_info_lock);
-                        return(RCODE_CONFLICT_ERROR); /* A resource conflict was detected.
-                                                        The request may be retried */
-                }
-                req->free_data=1;
-                arm_req_resp = (struct arm_request_response *) (req->data);
-                arm_req  = (struct arm_request *) ((byte_t *)(req->data) +
-                        (sizeof (struct arm_request_response)));
-                arm_resp = (struct arm_response *) ((byte_t *)(arm_req) +
-                        (sizeof(struct arm_request)));
-                buf1 = (byte_t *)arm_resp + sizeof(struct arm_response);
+		DBGMSG("arm_lock -> entering notification-section");
+		req = __alloc_pending_request(SLAB_ATOMIC);
+		if (!req) {
+			DBGMSG("arm_lock -> rcode_conflict_error");
+			spin_unlock(&host_info_lock);
+			return (RCODE_CONFLICT_ERROR);	/* A resource conflict was detected.
+							   The request may be retried */
+		}
+		size = sizeof(struct arm_request) + sizeof(struct arm_response) + 3 * sizeof(*store) + sizeof(struct arm_request_response);	/* maximum */
+		req->data = kmalloc(size, SLAB_ATOMIC);
+		if (!(req->data)) {
+			free_pending_request(req);
+			DBGMSG("arm_lock -> rcode_conflict_error");
+			spin_unlock(&host_info_lock);
+			return (RCODE_CONFLICT_ERROR);	/* A resource conflict was detected.
+							   The request may be retried */
+		}
+		req->free_data = 1;
+		arm_req_resp = (struct arm_request_response *)(req->data);
+		arm_req = (struct arm_request *)((byte_t *) (req->data) +
+						 (sizeof
+						  (struct
+						   arm_request_response)));
+		arm_resp =
+		    (struct arm_response *)((byte_t *) (arm_req) +
+					    (sizeof(struct arm_request)));
+		buf1 = (byte_t *) arm_resp + sizeof(struct arm_response);
 		buf2 = buf1 + 2 * sizeof(*store);
-                if ((ext_tcode == EXTCODE_FETCH_ADD) ||
-                        (ext_tcode == EXTCODE_LITTLE_ADD)) {
-                        arm_req->buffer_length = sizeof(*store);
-                        memcpy (buf1, &data, sizeof(*store));
-
-                } else {
-                        arm_req->buffer_length = 2 * sizeof(*store);
-                        memcpy (buf1, &arg,  sizeof(*store));
-                        memcpy (buf1 + sizeof(*store), &data, sizeof(*store));
-                }
-                if (rcode == RCODE_COMPLETE) {
-                        arm_resp->buffer_length = sizeof(*store);
-                        memcpy (buf2, &old, sizeof(*store));
-                } else {
-                        arm_resp->buffer_length = 0;
-                }
-                req->file_info = fi;
-                req->req.type = RAW1394_REQ_ARM;
-                req->req.generation = get_hpsb_generation(host);
-                req->req.misc = ( (((sizeof(*store)) << 16) & (0xFFFF0000)) |
-                        (ARM_LOCK & 0xFF));
-                req->req.tag  = arm_addr->arm_tag;
-                req->req.recvb = arm_addr->recvb;
-                req->req.length = size;
-                arm_req->generation = req->req.generation;
-                arm_req->extended_transaction_code = ext_tcode;
-                arm_req->destination_offset = addr;
-                arm_req->source_nodeid = nodeid;
-                arm_req->destination_nodeid = host->node_id;
-                arm_req->tlabel = (flags >> 10) & 0x3f;
-                arm_req->tcode = (flags >> 4) & 0x0f;
-                arm_resp->response_code = rcode;
-                arm_req_resp->request  = int2ptr((arm_addr->recvb) +
-                        sizeof (struct arm_request_response));
-                arm_req_resp->response = int2ptr((arm_addr->recvb) +
-                        sizeof (struct arm_request_response) +
-                        sizeof (struct arm_request));
-                arm_req->buffer = int2ptr((arm_addr->recvb) +
-                        sizeof (struct arm_request_response) +
-                        sizeof (struct arm_request) +
-                        sizeof (struct arm_response));
-                arm_resp->buffer = int2ptr((arm_addr->recvb) +
-                        sizeof (struct arm_request_response) +
-                        sizeof (struct arm_request) +
-                        sizeof (struct arm_response) +
-                        2* sizeof (*store));
-                queue_complete_req(req);
-        }
-        spin_unlock(&host_info_lock);
-        return(rcode);
-}
-
-static int arm_lock64 (struct hpsb_host *host, int nodeid, octlet_t *store,
-               u64 addr, octlet_t data, octlet_t arg, int ext_tcode, u16 flags)
-{
-        struct pending_request *req;
-        struct host_info *hi;
-        struct file_info *fi = NULL;
-        struct list_head *entry;
-        struct arm_addr  *arm_addr = NULL;
-        struct arm_request  *arm_req = NULL;
-        struct arm_response *arm_resp = NULL;
-        int found=0, size=0, rcode=-1;
-        octlet_t old, new;
-        struct arm_request_response *arm_req_resp = NULL;
-
-        if (((ext_tcode & 0xFF) == EXTCODE_FETCH_ADD) ||
-                ((ext_tcode & 0xFF) == EXTCODE_LITTLE_ADD)) {
-                DBGMSG("arm_lock64 called by node: %X "
-                      "addr: %4.4x %8.8x extcode: %2.2X data: %8.8X %8.8X ",
-                      nodeid, (u16) ((addr >>32) & 0xFFFF),
-                      (u32) (addr & 0xFFFFFFFF),
-                      ext_tcode & 0xFF ,
-                      (u32) ((be64_to_cpu(data) >> 32) & 0xFFFFFFFF),
-                      (u32) (be64_to_cpu(data) & 0xFFFFFFFF));
-        } else {
-                DBGMSG("arm_lock64 called by node: %X "
-                      "addr: %4.4x %8.8x extcode: %2.2X data: %8.8X %8.8X arg: "
-                      "%8.8X %8.8X ",
-                      nodeid, (u16) ((addr >>32) & 0xFFFF),
-                      (u32) (addr & 0xFFFFFFFF),
-                      ext_tcode & 0xFF ,
-                      (u32) ((be64_to_cpu(data) >> 32) & 0xFFFFFFFF),
-                      (u32) (be64_to_cpu(data) & 0xFFFFFFFF),
-                      (u32) ((be64_to_cpu(arg)  >> 32) & 0xFFFFFFFF),
-                      (u32) (be64_to_cpu(arg)  & 0xFFFFFFFF));
-        }
-        spin_lock(&host_info_lock);
-        hi = find_host_info(host); /* search addressentry in file_info's for host */
-        if (hi != NULL) {
-                list_for_each_entry(fi, &hi->file_info_list, list) {
-                        entry = fi->addr_list.next;
-                        while (entry != &(fi->addr_list)) {
-                                arm_addr = list_entry(entry, struct arm_addr, addr_list);
-                                if (((arm_addr->start) <= (addr)) &&
-                                        ((arm_addr->end) >= (addr+sizeof(*store)))) {
-                                        found = 1;
-                                        break;
-                                }
-                                entry = entry->next;
-                        }
-                        if (found) {
-                                break;
-                        }
-                }
-        }
-        rcode = -1;
-        if (!found) {
-                printk(KERN_ERR "raw1394: arm_lock64 FAILED addr_entry not found"
-                " -> rcode_address_error\n");
-                spin_unlock(&host_info_lock);
-                return (RCODE_ADDRESS_ERROR);
-        } else {
-                DBGMSG("arm_lock64 addr_entry FOUND");
-        }
-        if (rcode == -1) {
-                if (arm_addr->access_rights & ARM_LOCK) {
-                        if (!(arm_addr->client_transactions & ARM_LOCK)) {
-                                memcpy(&old,(arm_addr->addr_space_buffer)+(addr-(arm_addr->start)),
-                                        sizeof(old));
-                                switch (ext_tcode) {
-                                        case (EXTCODE_MASK_SWAP):
-                                                new = data | (old & ~arg);
-                                                break;
-                                        case (EXTCODE_COMPARE_SWAP):
-                                                if (old == arg) {
-                                                        new = data;
-                                                } else {
-                                                        new = old;
-                                                }
-                                                break;
-                                        case (EXTCODE_FETCH_ADD):
-                                                new = cpu_to_be64(be64_to_cpu(data) + be64_to_cpu(old));
-                                                break;
-                                        case (EXTCODE_LITTLE_ADD):
-                                                new = cpu_to_le64(le64_to_cpu(data) + le64_to_cpu(old));
-                                                break;
-                                        case (EXTCODE_BOUNDED_ADD):
-                                                if (old != arg) {
-                                                        new = cpu_to_be64(be64_to_cpu(data) +
-                                                                be64_to_cpu(old));
-                                                } else {
-                                                        new = old;
-                                                }
-                                                break;
-                                        case (EXTCODE_WRAP_ADD):
-                                                if (old != arg) {
-                                                        new = cpu_to_be64(be64_to_cpu(data) +
-                                                                be64_to_cpu(old));
-                                                } else {
-                                                        new = data;
-                                                }
-                                                break;
-                                        default:
-                                                printk(KERN_ERR "raw1394: arm_lock64 FAILED "
-                                                "ext_tcode not allowed -> rcode_type_error\n");
-                                                rcode = RCODE_TYPE_ERROR; /* function not allowed */
-                                                break;
-                                } /*switch*/
-                                if (rcode == -1) {
-                                        DBGMSG("arm_lock64 -> (rcode_complete)");
-                                        rcode = RCODE_COMPLETE;
-                                        memcpy (store, &old, sizeof(*store));
-                                        memcpy ((arm_addr->addr_space_buffer)+
-                                                (addr-(arm_addr->start)),
-                                                &new, sizeof(*store));
-                                }
-                        }
-                } else {
-                        rcode = RCODE_TYPE_ERROR; /* function not allowed */
-                        DBGMSG("arm_lock64 -> rcode_type_error (access denied)");
-                }
-        }
-        if (arm_addr->notification_options & ARM_LOCK) {
+		if ((ext_tcode == EXTCODE_FETCH_ADD) ||
+		    (ext_tcode == EXTCODE_LITTLE_ADD)) {
+			arm_req->buffer_length = sizeof(*store);
+			memcpy(buf1, &data, sizeof(*store));
+
+		} else {
+			arm_req->buffer_length = 2 * sizeof(*store);
+			memcpy(buf1, &arg, sizeof(*store));
+			memcpy(buf1 + sizeof(*store), &data, sizeof(*store));
+		}
+		if (rcode == RCODE_COMPLETE) {
+			arm_resp->buffer_length = sizeof(*store);
+			memcpy(buf2, &old, sizeof(*store));
+		} else {
+			arm_resp->buffer_length = 0;
+		}
+		req->file_info = fi;
+		req->req.type = RAW1394_REQ_ARM;
+		req->req.generation = get_hpsb_generation(host);
+		req->req.misc = ((((sizeof(*store)) << 16) & (0xFFFF0000)) |
+				 (ARM_LOCK & 0xFF));
+		req->req.tag = arm_addr->arm_tag;
+		req->req.recvb = arm_addr->recvb;
+		req->req.length = size;
+		arm_req->generation = req->req.generation;
+		arm_req->extended_transaction_code = ext_tcode;
+		arm_req->destination_offset = addr;
+		arm_req->source_nodeid = nodeid;
+		arm_req->destination_nodeid = host->node_id;
+		arm_req->tlabel = (flags >> 10) & 0x3f;
+		arm_req->tcode = (flags >> 4) & 0x0f;
+		arm_resp->response_code = rcode;
+		arm_req_resp->request = int2ptr((arm_addr->recvb) +
+						sizeof(struct
+						       arm_request_response));
+		arm_req_resp->response =
+		    int2ptr((arm_addr->recvb) +
+			    sizeof(struct arm_request_response) +
+			    sizeof(struct arm_request));
+		arm_req->buffer =
+		    int2ptr((arm_addr->recvb) +
+			    sizeof(struct arm_request_response) +
+			    sizeof(struct arm_request) +
+			    sizeof(struct arm_response));
+		arm_resp->buffer =
+		    int2ptr((arm_addr->recvb) +
+			    sizeof(struct arm_request_response) +
+			    sizeof(struct arm_request) +
+			    sizeof(struct arm_response) + 2 * sizeof(*store));
+		queue_complete_req(req);
+	}
+	spin_unlock(&host_info_lock);
+	return (rcode);
+}
+
+static int arm_lock64(struct hpsb_host *host, int nodeid, octlet_t * store,
+		      u64 addr, octlet_t data, octlet_t arg, int ext_tcode,
+		      u16 flags)
+{
+	struct pending_request *req;
+	struct host_info *hi;
+	struct file_info *fi = NULL;
+	struct list_head *entry;
+	struct arm_addr *arm_addr = NULL;
+	struct arm_request *arm_req = NULL;
+	struct arm_response *arm_resp = NULL;
+	int found = 0, size = 0, rcode = -1;
+	octlet_t old, new;
+	struct arm_request_response *arm_req_resp = NULL;
+
+	if (((ext_tcode & 0xFF) == EXTCODE_FETCH_ADD) ||
+	    ((ext_tcode & 0xFF) == EXTCODE_LITTLE_ADD)) {
+		DBGMSG("arm_lock64 called by node: %X "
+		       "addr: %4.4x %8.8x extcode: %2.2X data: %8.8X %8.8X ",
+		       nodeid, (u16) ((addr >> 32) & 0xFFFF),
+		       (u32) (addr & 0xFFFFFFFF),
+		       ext_tcode & 0xFF,
+		       (u32) ((be64_to_cpu(data) >> 32) & 0xFFFFFFFF),
+		       (u32) (be64_to_cpu(data) & 0xFFFFFFFF));
+	} else {
+		DBGMSG("arm_lock64 called by node: %X "
+		       "addr: %4.4x %8.8x extcode: %2.2X data: %8.8X %8.8X arg: "
+		       "%8.8X %8.8X ",
+		       nodeid, (u16) ((addr >> 32) & 0xFFFF),
+		       (u32) (addr & 0xFFFFFFFF),
+		       ext_tcode & 0xFF,
+		       (u32) ((be64_to_cpu(data) >> 32) & 0xFFFFFFFF),
+		       (u32) (be64_to_cpu(data) & 0xFFFFFFFF),
+		       (u32) ((be64_to_cpu(arg) >> 32) & 0xFFFFFFFF),
+		       (u32) (be64_to_cpu(arg) & 0xFFFFFFFF));
+	}
+	spin_lock(&host_info_lock);
+	hi = find_host_info(host);	/* search addressentry in file_info's for host */
+	if (hi != NULL) {
+		list_for_each_entry(fi, &hi->file_info_list, list) {
+			entry = fi->addr_list.next;
+			while (entry != &(fi->addr_list)) {
+				arm_addr =
+				    list_entry(entry, struct arm_addr,
+					       addr_list);
+				if (((arm_addr->start) <= (addr))
+				    && ((arm_addr->end) >=
+					(addr + sizeof(*store)))) {
+					found = 1;
+					break;
+				}
+				entry = entry->next;
+			}
+			if (found) {
+				break;
+			}
+		}
+	}
+	rcode = -1;
+	if (!found) {
+		printk(KERN_ERR
+		       "raw1394: arm_lock64 FAILED addr_entry not found"
+		       " -> rcode_address_error\n");
+		spin_unlock(&host_info_lock);
+		return (RCODE_ADDRESS_ERROR);
+	} else {
+		DBGMSG("arm_lock64 addr_entry FOUND");
+	}
+	if (rcode == -1) {
+		if (arm_addr->access_rights & ARM_LOCK) {
+			if (!(arm_addr->client_transactions & ARM_LOCK)) {
+				memcpy(&old,
+				       (arm_addr->addr_space_buffer) + (addr -
+									(arm_addr->
+									 start)),
+				       sizeof(old));
+				switch (ext_tcode) {
+				case (EXTCODE_MASK_SWAP):
+					new = data | (old & ~arg);
+					break;
+				case (EXTCODE_COMPARE_SWAP):
+					if (old == arg) {
+						new = data;
+					} else {
+						new = old;
+					}
+					break;
+				case (EXTCODE_FETCH_ADD):
+					new =
+					    cpu_to_be64(be64_to_cpu(data) +
+							be64_to_cpu(old));
+					break;
+				case (EXTCODE_LITTLE_ADD):
+					new =
+					    cpu_to_le64(le64_to_cpu(data) +
+							le64_to_cpu(old));
+					break;
+				case (EXTCODE_BOUNDED_ADD):
+					if (old != arg) {
+						new =
+						    cpu_to_be64(be64_to_cpu
+								(data) +
+								be64_to_cpu
+								(old));
+					} else {
+						new = old;
+					}
+					break;
+				case (EXTCODE_WRAP_ADD):
+					if (old != arg) {
+						new =
+						    cpu_to_be64(be64_to_cpu
+								(data) +
+								be64_to_cpu
+								(old));
+					} else {
+						new = data;
+					}
+					break;
+				default:
+					printk(KERN_ERR
+					       "raw1394: arm_lock64 FAILED "
+					       "ext_tcode not allowed -> rcode_type_error\n");
+					rcode = RCODE_TYPE_ERROR;	/* function not allowed */
+					break;
+				}	/*switch */
+				if (rcode == -1) {
+					DBGMSG
+					    ("arm_lock64 -> (rcode_complete)");
+					rcode = RCODE_COMPLETE;
+					memcpy(store, &old, sizeof(*store));
+					memcpy((arm_addr->addr_space_buffer) +
+					       (addr - (arm_addr->start)),
+					       &new, sizeof(*store));
+				}
+			}
+		} else {
+			rcode = RCODE_TYPE_ERROR;	/* function not allowed */
+			DBGMSG
+			    ("arm_lock64 -> rcode_type_error (access denied)");
+		}
+	}
+	if (arm_addr->notification_options & ARM_LOCK) {
 		byte_t *buf1, *buf2;
-                DBGMSG("arm_lock64 -> entering notification-section");
-                req = __alloc_pending_request(SLAB_ATOMIC);
-                if (!req) {
-                        spin_unlock(&host_info_lock);
-                        DBGMSG("arm_lock64 -> rcode_conflict_error");
-                        return(RCODE_CONFLICT_ERROR); /* A resource conflict was detected.
-                                                        The request may be retried */
-                }
-                size =  sizeof(struct arm_request)+sizeof(struct arm_response) +
-                        3 * sizeof(*store) +
-                        sizeof (struct arm_request_response); /* maximum */
-                req->data = kmalloc(size, SLAB_ATOMIC);
-                if (!(req->data)) {
-                        free_pending_request(req);
-                        spin_unlock(&host_info_lock);
-                        DBGMSG("arm_lock64 -> rcode_conflict_error");
-                        return(RCODE_CONFLICT_ERROR); /* A resource conflict was detected.
-                                                        The request may be retried */
-                }
-                req->free_data=1;
-                arm_req_resp = (struct arm_request_response *) (req->data);
-                arm_req  = (struct arm_request *) ((byte_t *)(req->data) +
-                        (sizeof (struct arm_request_response)));
-                arm_resp = (struct arm_response *) ((byte_t *)(arm_req) +
-                        (sizeof(struct arm_request)));
-                buf1 = (byte_t *)arm_resp + sizeof(struct arm_response);
-                buf2 = buf1 + 2 * sizeof(*store);
-                if ((ext_tcode == EXTCODE_FETCH_ADD) ||
-                        (ext_tcode == EXTCODE_LITTLE_ADD)) {
-                        arm_req->buffer_length = sizeof(*store);
-                        memcpy (buf1, &data, sizeof(*store));
-
-                } else {
-                        arm_req->buffer_length = 2 * sizeof(*store);
-                        memcpy (buf1, &arg,  sizeof(*store));
-                        memcpy (buf1 + sizeof(*store), &data, sizeof(*store));
-                }
-                if (rcode == RCODE_COMPLETE) {
-                        arm_resp->buffer_length = sizeof(*store);
-                        memcpy (buf2, &old, sizeof(*store));
-                } else {
-                        arm_resp->buffer_length = 0;
-                }
-                req->file_info = fi;
-                req->req.type = RAW1394_REQ_ARM;
-                req->req.generation = get_hpsb_generation(host);
-                req->req.misc = ( (((sizeof(*store)) << 16) & (0xFFFF0000)) |
-                        (ARM_LOCK & 0xFF));
-                req->req.tag  = arm_addr->arm_tag;
-                req->req.recvb = arm_addr->recvb;
-                req->req.length = size;
-                arm_req->generation = req->req.generation;
-                arm_req->extended_transaction_code = ext_tcode;
-                arm_req->destination_offset = addr;
-                arm_req->source_nodeid = nodeid;
-                arm_req->destination_nodeid = host->node_id;
-                arm_req->tlabel = (flags >> 10) & 0x3f;
-                arm_req->tcode = (flags >> 4) & 0x0f;
-                arm_resp->response_code = rcode;
-                arm_req_resp->request  = int2ptr((arm_addr->recvb) +
-                        sizeof (struct arm_request_response));
-                arm_req_resp->response = int2ptr((arm_addr->recvb) +
-                        sizeof (struct arm_request_response) +
-                        sizeof (struct arm_request));
-                arm_req->buffer = int2ptr((arm_addr->recvb) +
-                        sizeof (struct arm_request_response) +
-                        sizeof (struct arm_request) +
-                        sizeof (struct arm_response));
-                arm_resp->buffer = int2ptr((arm_addr->recvb) +
-                        sizeof (struct arm_request_response) +
-                        sizeof (struct arm_request) +
-                        sizeof (struct arm_response) +
-                        2* sizeof (*store));
-                queue_complete_req(req);
-        }
-        spin_unlock(&host_info_lock);
-        return(rcode);
+		DBGMSG("arm_lock64 -> entering notification-section");
+		req = __alloc_pending_request(SLAB_ATOMIC);
+		if (!req) {
+			spin_unlock(&host_info_lock);
+			DBGMSG("arm_lock64 -> rcode_conflict_error");
+			return (RCODE_CONFLICT_ERROR);	/* A resource conflict was detected.
+							   The request may be retried */
+		}
+		size = sizeof(struct arm_request) + sizeof(struct arm_response) + 3 * sizeof(*store) + sizeof(struct arm_request_response);	/* maximum */
+		req->data = kmalloc(size, SLAB_ATOMIC);
+		if (!(req->data)) {
+			free_pending_request(req);
+			spin_unlock(&host_info_lock);
+			DBGMSG("arm_lock64 -> rcode_conflict_error");
+			return (RCODE_CONFLICT_ERROR);	/* A resource conflict was detected.
+							   The request may be retried */
+		}
+		req->free_data = 1;
+		arm_req_resp = (struct arm_request_response *)(req->data);
+		arm_req = (struct arm_request *)((byte_t *) (req->data) +
+						 (sizeof
+						  (struct
+						   arm_request_response)));
+		arm_resp =
+		    (struct arm_response *)((byte_t *) (arm_req) +
+					    (sizeof(struct arm_request)));
+		buf1 = (byte_t *) arm_resp + sizeof(struct arm_response);
+		buf2 = buf1 + 2 * sizeof(*store);
+		if ((ext_tcode == EXTCODE_FETCH_ADD) ||
+		    (ext_tcode == EXTCODE_LITTLE_ADD)) {
+			arm_req->buffer_length = sizeof(*store);
+			memcpy(buf1, &data, sizeof(*store));
+
+		} else {
+			arm_req->buffer_length = 2 * sizeof(*store);
+			memcpy(buf1, &arg, sizeof(*store));
+			memcpy(buf1 + sizeof(*store), &data, sizeof(*store));
+		}
+		if (rcode == RCODE_COMPLETE) {
+			arm_resp->buffer_length = sizeof(*store);
+			memcpy(buf2, &old, sizeof(*store));
+		} else {
+			arm_resp->buffer_length = 0;
+		}
+		req->file_info = fi;
+		req->req.type = RAW1394_REQ_ARM;
+		req->req.generation = get_hpsb_generation(host);
+		req->req.misc = ((((sizeof(*store)) << 16) & (0xFFFF0000)) |
+				 (ARM_LOCK & 0xFF));
+		req->req.tag = arm_addr->arm_tag;
+		req->req.recvb = arm_addr->recvb;
+		req->req.length = size;
+		arm_req->generation = req->req.generation;
+		arm_req->extended_transaction_code = ext_tcode;
+		arm_req->destination_offset = addr;
+		arm_req->source_nodeid = nodeid;
+		arm_req->destination_nodeid = host->node_id;
+		arm_req->tlabel = (flags >> 10) & 0x3f;
+		arm_req->tcode = (flags >> 4) & 0x0f;
+		arm_resp->response_code = rcode;
+		arm_req_resp->request = int2ptr((arm_addr->recvb) +
+						sizeof(struct
+						       arm_request_response));
+		arm_req_resp->response =
+		    int2ptr((arm_addr->recvb) +
+			    sizeof(struct arm_request_response) +
+			    sizeof(struct arm_request));
+		arm_req->buffer =
+		    int2ptr((arm_addr->recvb) +
+			    sizeof(struct arm_request_response) +
+			    sizeof(struct arm_request) +
+			    sizeof(struct arm_response));
+		arm_resp->buffer =
+		    int2ptr((arm_addr->recvb) +
+			    sizeof(struct arm_request_response) +
+			    sizeof(struct arm_request) +
+			    sizeof(struct arm_response) + 2 * sizeof(*store));
+		queue_complete_req(req);
+	}
+	spin_unlock(&host_info_lock);
+	return (rcode);
 }
 
 static int arm_register(struct file_info *fi, struct pending_request *req)
 {
-        int retval;
-        struct arm_addr *addr;
-        struct host_info *hi;
-        struct file_info *fi_hlp = NULL;
-        struct list_head *entry;
-        struct arm_addr  *arm_addr = NULL;
-        int same_host, another_host;
-        unsigned long flags;
-
-        DBGMSG("arm_register called "
-              "addr(Offset): %8.8x %8.8x length: %u "
-              "rights: %2.2X notify: %2.2X "
-              "max_blk_len: %4.4X",
-              (u32) ((req->req.address >>32) & 0xFFFF),
-              (u32) (req->req.address & 0xFFFFFFFF),
-              req->req.length, ((req->req.misc >> 8) & 0xFF),
-              (req->req.misc & 0xFF),((req->req.misc >> 16) & 0xFFFF));
-        /* check addressrange */
-        if ((((req->req.address) & ~(0xFFFFFFFFFFFFULL)) != 0) ||
-                (((req->req.address + req->req.length) & ~(0xFFFFFFFFFFFFULL)) != 0)) {
-                req->req.length = 0;
-                return (-EINVAL);
-        }
-        /* addr-list-entry for fileinfo */
-        addr = (struct arm_addr *)kmalloc(sizeof(struct arm_addr), SLAB_KERNEL);
-        if (!addr) {
-                req->req.length = 0;
-                return (-ENOMEM);
-        }
-        /* allocation of addr_space_buffer */
-        addr->addr_space_buffer = (u8 *)vmalloc(req->req.length);
-        if (!(addr->addr_space_buffer)) {
-                kfree(addr);
-                req->req.length = 0;
-                return (-ENOMEM);
-        }
-        /* initialization of addr_space_buffer */
-        if ((req->req.sendb)== (unsigned long)NULL) {
-                /* init: set 0 */
-                memset(addr->addr_space_buffer, 0,req->req.length);
-        } else {
-                /* init: user -> kernel */
-                if (copy_from_user(addr->addr_space_buffer,int2ptr(req->req.sendb),
-                        req->req.length)) {
-                        vfree(addr->addr_space_buffer);
-                        kfree(addr);
-                        return (-EFAULT);
-                }
-        }
-        INIT_LIST_HEAD(&addr->addr_list);
-        addr->arm_tag   = req->req.tag;
-        addr->start     = req->req.address;
-        addr->end       = req->req.address + req->req.length;
-        addr->access_rights = (u8) (req->req.misc & 0x0F);
-        addr->notification_options = (u8) ((req->req.misc >> 4) & 0x0F);
-        addr->client_transactions = (u8) ((req->req.misc >> 8) & 0x0F);
-        addr->access_rights |= addr->client_transactions;
-        addr->notification_options |= addr->client_transactions;
-        addr->recvb     = req->req.recvb;
-        addr->rec_length = (u16) ((req->req.misc >> 16) & 0xFFFF);
-        spin_lock_irqsave(&host_info_lock, flags);
-        hi = find_host_info(fi->host);
-        same_host = 0;
-        another_host = 0;
-        /* same host with address-entry containing same addressrange ? */
-        list_for_each_entry(fi_hlp, &hi->file_info_list, list) {
-                entry = fi_hlp->addr_list.next;
-                while (entry != &(fi_hlp->addr_list)) {
-                        arm_addr = list_entry(entry, struct arm_addr, addr_list);
-                        if ( (arm_addr->start == addr->start) &&
-                                (arm_addr->end == addr->end)) {
-                                DBGMSG("same host ownes same "
-                                        "addressrange -> EALREADY");
-                                same_host = 1;
-                                break;
-                        }
-                        entry = entry->next;
-                }
-                if (same_host) {
-                        break;
-                }
-        }
-        if (same_host) {
-                /* addressrange occupied by same host */
-                vfree(addr->addr_space_buffer);
-                kfree(addr);
-                spin_unlock_irqrestore(&host_info_lock, flags);
-                return (-EALREADY);
-        }
-        /* another host with valid address-entry containing same addressrange */
-        list_for_each_entry(hi, &host_info_list, list) {
-                if (hi->host != fi->host) {
-                        list_for_each_entry(fi_hlp, &hi->file_info_list, list) {
-                                entry = fi_hlp->addr_list.next;
-                                while (entry != &(fi_hlp->addr_list)) {
-                                        arm_addr = list_entry(entry, struct arm_addr, addr_list);
-                                        if ( (arm_addr->start == addr->start) &&
-                                                (arm_addr->end == addr->end)) {
-                                                DBGMSG("another host ownes same "
-                                                "addressrange");
-                                                another_host = 1;
-                                                break;
-                                        }
-                                        entry = entry->next;
-                                }
-                                if (another_host) {
-                                        break;
-                                }
-                        }
-                }
-        }
-        if (another_host) {
-                DBGMSG("another hosts entry is valid -> SUCCESS");
-                if (copy_to_user(int2ptr(req->req.recvb),
-                        &addr->start,sizeof(u64))) {
-                        printk(KERN_ERR "raw1394: arm_register failed "
-                              " address-range-entry is invalid -> EFAULT !!!\n");
-                        vfree(addr->addr_space_buffer);
-                        kfree(addr);
-                        spin_unlock_irqrestore(&host_info_lock, flags);
-                        return (-EFAULT);
-                }
-                free_pending_request(req); /* immediate success or fail */
-                /* INSERT ENTRY */
-                list_add_tail(&addr->addr_list, &fi->addr_list);
-                spin_unlock_irqrestore(&host_info_lock, flags);
-                return sizeof(struct raw1394_request);
-        }
-        retval = hpsb_register_addrspace(&raw1394_highlevel, fi->host, &arm_ops, req->req.address,
-                req->req.address + req->req.length);
-        if (retval) {
-               /* INSERT ENTRY */
-               list_add_tail(&addr->addr_list, &fi->addr_list);
-        } else {
-                DBGMSG("arm_register failed errno: %d \n",retval);
-                vfree(addr->addr_space_buffer);
-                kfree(addr);
-                spin_unlock_irqrestore(&host_info_lock, flags);
-                return (-EALREADY);
-        }
-        spin_unlock_irqrestore(&host_info_lock, flags);
-        free_pending_request(req); /* immediate success or fail */
-        return sizeof(struct raw1394_request);
+	int retval;
+	struct arm_addr *addr;
+	struct host_info *hi;
+	struct file_info *fi_hlp = NULL;
+	struct list_head *entry;
+	struct arm_addr *arm_addr = NULL;
+	int same_host, another_host;
+	unsigned long flags;
+
+	DBGMSG("arm_register called "
+	       "addr(Offset): %8.8x %8.8x length: %u "
+	       "rights: %2.2X notify: %2.2X "
+	       "max_blk_len: %4.4X",
+	       (u32) ((req->req.address >> 32) & 0xFFFF),
+	       (u32) (req->req.address & 0xFFFFFFFF),
+	       req->req.length, ((req->req.misc >> 8) & 0xFF),
+	       (req->req.misc & 0xFF), ((req->req.misc >> 16) & 0xFFFF));
+	/* check addressrange */
+	if ((((req->req.address) & ~(0xFFFFFFFFFFFFULL)) != 0) ||
+	    (((req->req.address + req->req.length) & ~(0xFFFFFFFFFFFFULL)) !=
+	     0)) {
+		req->req.length = 0;
+		return (-EINVAL);
+	}
+	/* addr-list-entry for fileinfo */
+	addr = (struct arm_addr *)kmalloc(sizeof(struct arm_addr), SLAB_KERNEL);
+	if (!addr) {
+		req->req.length = 0;
+		return (-ENOMEM);
+	}
+	/* allocation of addr_space_buffer */
+	addr->addr_space_buffer = (u8 *) vmalloc(req->req.length);
+	if (!(addr->addr_space_buffer)) {
+		kfree(addr);
+		req->req.length = 0;
+		return (-ENOMEM);
+	}
+	/* initialization of addr_space_buffer */
+	if ((req->req.sendb) == (unsigned long)NULL) {
+		/* init: set 0 */
+		memset(addr->addr_space_buffer, 0, req->req.length);
+	} else {
+		/* init: user -> kernel */
+		if (copy_from_user
+		    (addr->addr_space_buffer, int2ptr(req->req.sendb),
+		     req->req.length)) {
+			vfree(addr->addr_space_buffer);
+			kfree(addr);
+			return (-EFAULT);
+		}
+	}
+	INIT_LIST_HEAD(&addr->addr_list);
+	addr->arm_tag = req->req.tag;
+	addr->start = req->req.address;
+	addr->end = req->req.address + req->req.length;
+	addr->access_rights = (u8) (req->req.misc & 0x0F);
+	addr->notification_options = (u8) ((req->req.misc >> 4) & 0x0F);
+	addr->client_transactions = (u8) ((req->req.misc >> 8) & 0x0F);
+	addr->access_rights |= addr->client_transactions;
+	addr->notification_options |= addr->client_transactions;
+	addr->recvb = req->req.recvb;
+	addr->rec_length = (u16) ((req->req.misc >> 16) & 0xFFFF);
+	spin_lock_irqsave(&host_info_lock, flags);
+	hi = find_host_info(fi->host);
+	same_host = 0;
+	another_host = 0;
+	/* same host with address-entry containing same addressrange ? */
+	list_for_each_entry(fi_hlp, &hi->file_info_list, list) {
+		entry = fi_hlp->addr_list.next;
+		while (entry != &(fi_hlp->addr_list)) {
+			arm_addr =
+			    list_entry(entry, struct arm_addr, addr_list);
+			if ((arm_addr->start == addr->start)
+			    && (arm_addr->end == addr->end)) {
+				DBGMSG("same host ownes same "
+				       "addressrange -> EALREADY");
+				same_host = 1;
+				break;
+			}
+			entry = entry->next;
+		}
+		if (same_host) {
+			break;
+		}
+	}
+	if (same_host) {
+		/* addressrange occupied by same host */
+		vfree(addr->addr_space_buffer);
+		kfree(addr);
+		spin_unlock_irqrestore(&host_info_lock, flags);
+		return (-EALREADY);
+	}
+	/* another host with valid address-entry containing same addressrange */
+	list_for_each_entry(hi, &host_info_list, list) {
+		if (hi->host != fi->host) {
+			list_for_each_entry(fi_hlp, &hi->file_info_list, list) {
+				entry = fi_hlp->addr_list.next;
+				while (entry != &(fi_hlp->addr_list)) {
+					arm_addr =
+					    list_entry(entry, struct arm_addr,
+						       addr_list);
+					if ((arm_addr->start == addr->start)
+					    && (arm_addr->end == addr->end)) {
+						DBGMSG
+						    ("another host ownes same "
+						     "addressrange");
+						another_host = 1;
+						break;
+					}
+					entry = entry->next;
+				}
+				if (another_host) {
+					break;
+				}
+			}
+		}
+	}
+	if (another_host) {
+		DBGMSG("another hosts entry is valid -> SUCCESS");
+		if (copy_to_user(int2ptr(req->req.recvb),
+				 &addr->start, sizeof(u64))) {
+			printk(KERN_ERR "raw1394: arm_register failed "
+			       " address-range-entry is invalid -> EFAULT !!!\n");
+			vfree(addr->addr_space_buffer);
+			kfree(addr);
+			spin_unlock_irqrestore(&host_info_lock, flags);
+			return (-EFAULT);
+		}
+		free_pending_request(req);	/* immediate success or fail */
+		/* INSERT ENTRY */
+		list_add_tail(&addr->addr_list, &fi->addr_list);
+		spin_unlock_irqrestore(&host_info_lock, flags);
+		return sizeof(struct raw1394_request);
+	}
+	retval =
+	    hpsb_register_addrspace(&raw1394_highlevel, fi->host, &arm_ops,
+				    req->req.address,
+				    req->req.address + req->req.length);
+	if (retval) {
+		/* INSERT ENTRY */
+		list_add_tail(&addr->addr_list, &fi->addr_list);
+	} else {
+		DBGMSG("arm_register failed errno: %d \n", retval);
+		vfree(addr->addr_space_buffer);
+		kfree(addr);
+		spin_unlock_irqrestore(&host_info_lock, flags);
+		return (-EALREADY);
+	}
+	spin_unlock_irqrestore(&host_info_lock, flags);
+	free_pending_request(req);	/* immediate success or fail */
+	return sizeof(struct raw1394_request);
 }
 
 static int arm_unregister(struct file_info *fi, struct pending_request *req)
 {
-        int found  = 0;
-        int retval = 0;
-        struct list_head *entry;
-        struct arm_addr  *addr = NULL;
-        struct host_info *hi;
-        struct file_info *fi_hlp = NULL;
-        struct arm_addr  *arm_addr = NULL;
-        int another_host;
-        unsigned long flags;
-
-        DBGMSG("arm_Unregister called addr(Offset): "
-              "%8.8x %8.8x",
-              (u32) ((req->req.address >>32) & 0xFFFF),
-              (u32) (req->req.address & 0xFFFFFFFF));
-        spin_lock_irqsave(&host_info_lock, flags);
-        /* get addr */
-        entry = fi->addr_list.next;
-        while (entry != &(fi->addr_list)) {
-                addr = list_entry(entry, struct arm_addr, addr_list);
-                if (addr->start == req->req.address) {
-                        found = 1;
-                        break;
-                }
-                entry = entry->next;
-        }
-        if (!found) {
-                DBGMSG("arm_Unregister addr not found");
-                spin_unlock_irqrestore(&host_info_lock, flags);
-                return (-EINVAL);
-        }
-        DBGMSG("arm_Unregister addr found");
-        another_host = 0;
-        /* another host with valid address-entry containing
-           same addressrange */
-        list_for_each_entry(hi, &host_info_list, list) {
-                if (hi->host != fi->host) {
-                        list_for_each_entry(fi_hlp, &hi->file_info_list, list) {
-                                entry = fi_hlp->addr_list.next;
-                                while (entry != &(fi_hlp->addr_list)) {
-                                        arm_addr = list_entry(entry,
-                                                struct arm_addr, addr_list);
-                                        if (arm_addr->start ==
-                                                addr->start) {
-                                                DBGMSG("another host ownes "
-                                                "same addressrange");
-                                                another_host = 1;
-                                                break;
-                                        }
-                                        entry = entry->next;
-                                }
-                                if (another_host) {
-                                        break;
-                                }
-                        }
-                }
-        }
-        if (another_host) {
-                DBGMSG("delete entry from list -> success");
-                list_del(&addr->addr_list);
-                vfree(addr->addr_space_buffer);
-                kfree(addr);
-                free_pending_request(req); /* immediate success or fail */
-                spin_unlock_irqrestore(&host_info_lock, flags);
-                return sizeof(struct raw1394_request);
-        }
-        retval = hpsb_unregister_addrspace(&raw1394_highlevel, fi->host, addr->start);
-        if (!retval) {
-                printk(KERN_ERR "raw1394: arm_Unregister failed -> EINVAL\n");
-                spin_unlock_irqrestore(&host_info_lock, flags);
-                return (-EINVAL);
-        }
-        DBGMSG("delete entry from list -> success");
-        list_del(&addr->addr_list);
-        spin_unlock_irqrestore(&host_info_lock, flags);
-        vfree(addr->addr_space_buffer);
-        kfree(addr);
-        free_pending_request(req); /* immediate success or fail */
-        return sizeof(struct raw1394_request);
+	int found = 0;
+	int retval = 0;
+	struct list_head *entry;
+	struct arm_addr *addr = NULL;
+	struct host_info *hi;
+	struct file_info *fi_hlp = NULL;
+	struct arm_addr *arm_addr = NULL;
+	int another_host;
+	unsigned long flags;
+
+	DBGMSG("arm_Unregister called addr(Offset): "
+	       "%8.8x %8.8x",
+	       (u32) ((req->req.address >> 32) & 0xFFFF),
+	       (u32) (req->req.address & 0xFFFFFFFF));
+	spin_lock_irqsave(&host_info_lock, flags);
+	/* get addr */
+	entry = fi->addr_list.next;
+	while (entry != &(fi->addr_list)) {
+		addr = list_entry(entry, struct arm_addr, addr_list);
+		if (addr->start == req->req.address) {
+			found = 1;
+			break;
+		}
+		entry = entry->next;
+	}
+	if (!found) {
+		DBGMSG("arm_Unregister addr not found");
+		spin_unlock_irqrestore(&host_info_lock, flags);
+		return (-EINVAL);
+	}
+	DBGMSG("arm_Unregister addr found");
+	another_host = 0;
+	/* another host with valid address-entry containing
+	   same addressrange */
+	list_for_each_entry(hi, &host_info_list, list) {
+		if (hi->host != fi->host) {
+			list_for_each_entry(fi_hlp, &hi->file_info_list, list) {
+				entry = fi_hlp->addr_list.next;
+				while (entry != &(fi_hlp->addr_list)) {
+					arm_addr = list_entry(entry,
+							      struct arm_addr,
+							      addr_list);
+					if (arm_addr->start == addr->start) {
+						DBGMSG("another host ownes "
+						       "same addressrange");
+						another_host = 1;
+						break;
+					}
+					entry = entry->next;
+				}
+				if (another_host) {
+					break;
+				}
+			}
+		}
+	}
+	if (another_host) {
+		DBGMSG("delete entry from list -> success");
+		list_del(&addr->addr_list);
+		vfree(addr->addr_space_buffer);
+		kfree(addr);
+		free_pending_request(req);	/* immediate success or fail */
+		spin_unlock_irqrestore(&host_info_lock, flags);
+		return sizeof(struct raw1394_request);
+	}
+	retval =
+	    hpsb_unregister_addrspace(&raw1394_highlevel, fi->host,
+				      addr->start);
+	if (!retval) {
+		printk(KERN_ERR "raw1394: arm_Unregister failed -> EINVAL\n");
+		spin_unlock_irqrestore(&host_info_lock, flags);
+		return (-EINVAL);
+	}
+	DBGMSG("delete entry from list -> success");
+	list_del(&addr->addr_list);
+	spin_unlock_irqrestore(&host_info_lock, flags);
+	vfree(addr->addr_space_buffer);
+	kfree(addr);
+	free_pending_request(req);	/* immediate success or fail */
+	return sizeof(struct raw1394_request);
 }
 
 /* Copy data from ARM buffer(s) to user buffer. */
 static int arm_get_buf(struct file_info *fi, struct pending_request *req)
 {
-	struct arm_addr  *arm_addr = NULL;
+	struct arm_addr *arm_addr = NULL;
 	unsigned long flags;
 	unsigned long offset;
 
@@ -1749,8 +1864,7 @@
 	DBGMSG("arm_get_buf "
 	       "addr(Offset): %04X %08X length: %u",
 	       (u32) ((req->req.address >> 32) & 0xFFFF),
-	       (u32) (req->req.address & 0xFFFFFFFF),
-	       (u32) req->req.length);
+	       (u32) (req->req.address & 0xFFFFFFFF), (u32) req->req.length);
 
 	spin_lock_irqsave(&host_info_lock, flags);
 	entry = fi->addr_list.next;
@@ -1761,13 +1875,18 @@
 			if (req->req.address + req->req.length <= arm_addr->end) {
 				offset = req->req.address - arm_addr->start;
 
-				DBGMSG("arm_get_buf copy_to_user( %08X, %p, %u )",
-				       (u32) req->req.recvb,
-				       arm_addr->addr_space_buffer+offset,
-				       (u32) req->req.length);
-
-				if (copy_to_user(int2ptr(req->req.recvb), arm_addr->addr_space_buffer+offset, req->req.length)) {
-					spin_unlock_irqrestore(&host_info_lock, flags);
+				DBGMSG
+				    ("arm_get_buf copy_to_user( %08X, %p, %u )",
+				     (u32) req->req.recvb,
+				     arm_addr->addr_space_buffer + offset,
+				     (u32) req->req.length);
+
+				if (copy_to_user
+				    (int2ptr(req->req.recvb),
+				     arm_addr->addr_space_buffer + offset,
+				     req->req.length)) {
+					spin_unlock_irqrestore(&host_info_lock,
+							       flags);
 					return (-EFAULT);
 				}
 
@@ -1789,11 +1908,10 @@
 	return (-EINVAL);
 }
 
-
 /* Copy data from user buffer to ARM buffer(s). */
 static int arm_set_buf(struct file_info *fi, struct pending_request *req)
 {
-	struct arm_addr  *arm_addr = NULL;
+	struct arm_addr *arm_addr = NULL;
 	unsigned long flags;
 	unsigned long offset;
 
@@ -1802,9 +1920,7 @@
 	DBGMSG("arm_set_buf "
 	       "addr(Offset): %04X %08X length: %u",
 	       (u32) ((req->req.address >> 32) & 0xFFFF),
-	       (u32) (req->req.address & 0xFFFFFFFF),
-	       (u32) req->req.length);
-
+	       (u32) (req->req.address & 0xFFFFFFFF), (u32) req->req.length);
 
 	spin_lock_irqsave(&host_info_lock, flags);
 	entry = fi->addr_list.next;
@@ -1815,18 +1931,23 @@
 			if (req->req.address + req->req.length <= arm_addr->end) {
 				offset = req->req.address - arm_addr->start;
 
-				DBGMSG("arm_set_buf copy_from_user( %p, %08X, %u )",
-				       arm_addr->addr_space_buffer+offset,
-				       (u32) req->req.sendb,
-				       (u32) req->req.length);
-
-				if (copy_from_user(arm_addr->addr_space_buffer+offset, int2ptr(req->req.sendb), req->req.length)) {
-					spin_unlock_irqrestore(&host_info_lock, flags);
+				DBGMSG
+				    ("arm_set_buf copy_from_user( %p, %08X, %u )",
+				     arm_addr->addr_space_buffer + offset,
+				     (u32) req->req.sendb,
+				     (u32) req->req.length);
+
+				if (copy_from_user
+				    (arm_addr->addr_space_buffer + offset,
+				     int2ptr(req->req.sendb),
+				     req->req.length)) {
+					spin_unlock_irqrestore(&host_info_lock,
+							       flags);
 					return (-EFAULT);
 				}
 
 				spin_unlock_irqrestore(&host_info_lock, flags);
-				free_pending_request(req); /* we have to free the request, because we queue no response, and therefore nobody will free it */
+				free_pending_request(req);	/* we have to free the request, because we queue no response, and therefore nobody will free it */
 				return sizeof(struct raw1394_request);
 			} else {
 				DBGMSG("arm_set_buf request exceeded mapping");
@@ -1842,96 +1963,100 @@
 
 static int reset_notification(struct file_info *fi, struct pending_request *req)
 {
-        DBGMSG("reset_notification called - switch %s ",
-                (req->req.misc == RAW1394_NOTIFY_OFF)?"OFF":"ON");
-        if ((req->req.misc == RAW1394_NOTIFY_OFF) ||
-                (req->req.misc == RAW1394_NOTIFY_ON)) {
-                fi->notification=(u8)req->req.misc;
-                free_pending_request(req); /* we have to free the request, because we queue no response, and therefore nobody will free it */
-                return sizeof(struct raw1394_request);
-        }
-        /* error EINVAL (22) invalid argument */
-        return (-EINVAL);
+	DBGMSG("reset_notification called - switch %s ",
+	       (req->req.misc == RAW1394_NOTIFY_OFF) ? "OFF" : "ON");
+	if ((req->req.misc == RAW1394_NOTIFY_OFF) ||
+	    (req->req.misc == RAW1394_NOTIFY_ON)) {
+		fi->notification = (u8) req->req.misc;
+		free_pending_request(req);	/* we have to free the request, because we queue no response, and therefore nobody will free it */
+		return sizeof(struct raw1394_request);
+	}
+	/* error EINVAL (22) invalid argument */
+	return (-EINVAL);
 }
 
 static int write_phypacket(struct file_info *fi, struct pending_request *req)
 {
-        struct hpsb_packet *packet = NULL;
-        int retval=0;
-        quadlet_t data;
-
-        data = be32_to_cpu((u32)req->req.sendb);
-        DBGMSG("write_phypacket called - quadlet 0x%8.8x ",data);
-        packet = hpsb_make_phypacket (fi->host, data);
-        if (!packet) return -ENOMEM;
-        req->req.length=0;
-        req->packet=packet;
-        hpsb_set_packet_complete_task(packet, (void(*)(void*))queue_complete_cb, req);
-        spin_lock_irq(&fi->reqlists_lock);
-        list_add_tail(&req->list, &fi->req_pending);
-        spin_unlock_irq(&fi->reqlists_lock);
-        packet->generation = req->req.generation;
-        retval = hpsb_send_packet(packet);
-        DBGMSG("write_phypacket send_packet called => retval: %d ", retval);
-        if (retval < 0) {
-                req->req.error = RAW1394_ERROR_SEND_ERROR;
-                req->req.length = 0;
-                queue_complete_req(req);
-        }
-        return sizeof(struct raw1394_request);
+	struct hpsb_packet *packet = NULL;
+	int retval = 0;
+	quadlet_t data;
+
+	data = be32_to_cpu((u32) req->req.sendb);
+	DBGMSG("write_phypacket called - quadlet 0x%8.8x ", data);
+	packet = hpsb_make_phypacket(fi->host, data);
+	if (!packet)
+		return -ENOMEM;
+	req->req.length = 0;
+	req->packet = packet;
+	hpsb_set_packet_complete_task(packet,
+				      (void (*)(void *))queue_complete_cb, req);
+	spin_lock_irq(&fi->reqlists_lock);
+	list_add_tail(&req->list, &fi->req_pending);
+	spin_unlock_irq(&fi->reqlists_lock);
+	packet->generation = req->req.generation;
+	retval = hpsb_send_packet(packet);
+	DBGMSG("write_phypacket send_packet called => retval: %d ", retval);
+	if (retval < 0) {
+		req->req.error = RAW1394_ERROR_SEND_ERROR;
+		req->req.length = 0;
+		queue_complete_req(req);
+	}
+	return sizeof(struct raw1394_request);
 }
 
 static int get_config_rom(struct file_info *fi, struct pending_request *req)
 {
-        int ret=sizeof(struct raw1394_request);
-        quadlet_t *data = kmalloc(req->req.length, SLAB_KERNEL);
-        int status;
-
-        if (!data) return -ENOMEM;
-
-	status = csr1212_read(fi->host->csr.rom, CSR1212_CONFIG_ROM_SPACE_OFFSET,
-			      data, req->req.length);
-        if (copy_to_user(int2ptr(req->req.recvb), data,
-                req->req.length))
-                ret = -EFAULT;
-	if (copy_to_user(int2ptr(req->req.tag), &fi->host->csr.rom->cache_head->len,
-			 sizeof(fi->host->csr.rom->cache_head->len)))
-                ret = -EFAULT;
+	int ret = sizeof(struct raw1394_request);
+	quadlet_t *data = kmalloc(req->req.length, SLAB_KERNEL);
+	int status;
+
+	if (!data)
+		return -ENOMEM;
+
+	status =
+	    csr1212_read(fi->host->csr.rom, CSR1212_CONFIG_ROM_SPACE_OFFSET,
+			 data, req->req.length);
+	if (copy_to_user(int2ptr(req->req.recvb), data, req->req.length))
+		ret = -EFAULT;
+	if (copy_to_user
+	    (int2ptr(req->req.tag), &fi->host->csr.rom->cache_head->len,
+	     sizeof(fi->host->csr.rom->cache_head->len)))
+		ret = -EFAULT;
 	if (copy_to_user(int2ptr(req->req.address), &fi->host->csr.generation,
 			 sizeof(fi->host->csr.generation)))
-                ret = -EFAULT;
-        if (copy_to_user(int2ptr(req->req.sendb), &status,
-                sizeof(status)))
-                ret = -EFAULT;
-        kfree(data);
-        if (ret >= 0) {
-                free_pending_request(req); /* we have to free the request, because we queue no response, and therefore nobody will free it */
-        }
-        return ret;
+		ret = -EFAULT;
+	if (copy_to_user(int2ptr(req->req.sendb), &status, sizeof(status)))
+		ret = -EFAULT;
+	kfree(data);
+	if (ret >= 0) {
+		free_pending_request(req);	/* we have to free the request, because we queue no response, and therefore nobody will free it */
+	}
+	return ret;
 }
 
 static int update_config_rom(struct file_info *fi, struct pending_request *req)
 {
-        int ret=sizeof(struct raw1394_request);
-        quadlet_t *data = kmalloc(req->req.length, SLAB_KERNEL);
-        if (!data) return -ENOMEM;
-        if (copy_from_user(data,int2ptr(req->req.sendb),
-                req->req.length)) {
-                ret= -EFAULT;
-        } else {
-                int status = hpsb_update_config_rom(fi->host,
-                        data, req->req.length,
-                        (unsigned char) req->req.misc);
-                if (copy_to_user(int2ptr(req->req.recvb),
-                        &status, sizeof(status)))
-                        ret = -ENOMEM;
-        }
-        kfree(data);
-        if (ret >= 0) {
-                free_pending_request(req); /* we have to free the request, because we queue no response, and therefore nobody will free it */
+	int ret = sizeof(struct raw1394_request);
+	quadlet_t *data = kmalloc(req->req.length, SLAB_KERNEL);
+	if (!data)
+		return -ENOMEM;
+	if (copy_from_user(data, int2ptr(req->req.sendb), req->req.length)) {
+		ret = -EFAULT;
+	} else {
+		int status = hpsb_update_config_rom(fi->host,
+						    data, req->req.length,
+						    (unsigned char)req->req.
+						    misc);
+		if (copy_to_user
+		    (int2ptr(req->req.recvb), &status, sizeof(status)))
+			ret = -ENOMEM;
+	}
+	kfree(data);
+	if (ret >= 0) {
+		free_pending_request(req);	/* we have to free the request, because we queue no response, and therefore nobody will free it */
 		fi->cfgrom_upd = 1;
-        }
-        return ret;
+	}
+	return ret;
 }
 
 static int modify_config_rom(struct file_info *fi, struct pending_request *req)
@@ -1943,23 +2068,32 @@
 	int ret = 0;
 
 	if (req->req.misc == ~0) {
-		if (req->req.length == 0) return -EINVAL;
+		if (req->req.length == 0)
+			return -EINVAL;
 
 		/* Find an unused slot */
-		for (dr = 0; dr < RAW1394_MAX_USER_CSR_DIRS && fi->csr1212_dirs[dr]; dr++);
+		for (dr = 0;
+		     dr < RAW1394_MAX_USER_CSR_DIRS && fi->csr1212_dirs[dr];
+		     dr++) ;
 
-		if (dr == RAW1394_MAX_USER_CSR_DIRS) return -ENOMEM;
+		if (dr == RAW1394_MAX_USER_CSR_DIRS)
+			return -ENOMEM;
 
-		fi->csr1212_dirs[dr] = csr1212_new_directory(CSR1212_KV_ID_VENDOR);
-		if (!fi->csr1212_dirs[dr]) return -ENOMEM;
+		fi->csr1212_dirs[dr] =
+		    csr1212_new_directory(CSR1212_KV_ID_VENDOR);
+		if (!fi->csr1212_dirs[dr])
+			return -ENOMEM;
 	} else {
 		dr = req->req.misc;
-		if (!fi->csr1212_dirs[dr]) return -EINVAL;
+		if (!fi->csr1212_dirs[dr])
+			return -EINVAL;
 
 		/* Delete old stuff */
-		for (dentry = fi->csr1212_dirs[dr]->value.directory.dentries_head;
+		for (dentry =
+		     fi->csr1212_dirs[dr]->value.directory.dentries_head;
 		     dentry; dentry = dentry->next) {
-			csr1212_detach_keyval_from_directory(fi->host->csr.rom->root_kv,
+			csr1212_detach_keyval_from_directory(fi->host->csr.rom->
+							     root_kv,
 							     dentry->kv);
 		}
 
@@ -1980,7 +2114,8 @@
 		return -ENOMEM;
 	}
 
-	cache->filled_head = kmalloc(sizeof(struct csr1212_cache_region), GFP_KERNEL);
+	cache->filled_head =
+	    kmalloc(sizeof(struct csr1212_cache_region), GFP_KERNEL);
 	if (!cache->filled_head) {
 		csr1212_release_keyval(fi->csr1212_dirs[dr]);
 		fi->csr1212_dirs[dr] = NULL;
@@ -1994,11 +2129,11 @@
 		csr1212_release_keyval(fi->csr1212_dirs[dr]);
 		fi->csr1212_dirs[dr] = NULL;
 		CSR1212_FREE(cache);
-		ret= -EFAULT;
+		ret = -EFAULT;
 	} else {
 		cache->len = req->req.length;
 		cache->filled_head->offset_start = 0;
-		cache->filled_head->offset_end = cache->size -1;
+		cache->filled_head->offset_end = cache->size - 1;
 
 		cache->layout_head = cache->layout_tail = fi->csr1212_dirs[dr];
 
@@ -2010,17 +2145,20 @@
 		}
 
 		/* attach top level items to the root directory */
-		for (dentry = fi->csr1212_dirs[dr]->value.directory.dentries_head;
+		for (dentry =
+		     fi->csr1212_dirs[dr]->value.directory.dentries_head;
 		     ret == CSR1212_SUCCESS && dentry; dentry = dentry->next) {
-			ret = csr1212_attach_keyval_to_directory(fi->host->csr.rom->root_kv,
-								 dentry->kv);
+			ret =
+			    csr1212_attach_keyval_to_directory(fi->host->csr.
+							       rom->root_kv,
+							       dentry->kv);
 		}
 
 		if (ret == CSR1212_SUCCESS) {
 			ret = hpsb_update_config_rom_image(fi->host);
 
 			if (ret >= 0 && copy_to_user(int2ptr(req->req.recvb),
-						    &dr, sizeof(dr))) {
+						     &dr, sizeof(dr))) {
 				ret = -ENOMEM;
 			}
 		}
@@ -2034,9 +2172,11 @@
 		free_pending_request(req);
 		return sizeof(struct raw1394_request);
 	} else {
-		for (dentry = fi->csr1212_dirs[dr]->value.directory.dentries_head;
+		for (dentry =
+		     fi->csr1212_dirs[dr]->value.directory.dentries_head;
 		     dentry; dentry = dentry->next) {
-			csr1212_detach_keyval_from_directory(fi->host->csr.rom->root_kv,
+			csr1212_detach_keyval_from_directory(fi->host->csr.rom->
+							     root_kv,
 							     dentry->kv);
 		}
 		csr1212_release_keyval(fi->csr1212_dirs[dr]);
@@ -2047,133 +2187,132 @@
 
 static int state_connected(struct file_info *fi, struct pending_request *req)
 {
-        int node = req->req.address >> 48;
+	int node = req->req.address >> 48;
+
+	req->req.error = RAW1394_ERROR_NONE;
 
-        req->req.error = RAW1394_ERROR_NONE;
+	switch (req->req.type) {
 
-        switch (req->req.type) {
+	case RAW1394_REQ_ECHO:
+		queue_complete_req(req);
+		return sizeof(struct raw1394_request);
+
+	case RAW1394_REQ_ISO_SEND:
+		return handle_iso_send(fi, req, node);
+
+	case RAW1394_REQ_ARM_REGISTER:
+		return arm_register(fi, req);
+
+	case RAW1394_REQ_ARM_UNREGISTER:
+		return arm_unregister(fi, req);
+
+	case RAW1394_REQ_ARM_SET_BUF:
+		return arm_set_buf(fi, req);
 
-        case RAW1394_REQ_ECHO:
-                queue_complete_req(req);
-                return sizeof(struct raw1394_request);
-
-        case RAW1394_REQ_ISO_SEND:
-                return handle_iso_send(fi, req, node);
-
-        case RAW1394_REQ_ARM_REGISTER:
-                return arm_register(fi, req);
-
-        case RAW1394_REQ_ARM_UNREGISTER:
-                return arm_unregister(fi, req);
-
-        case RAW1394_REQ_ARM_SET_BUF:
-                return arm_set_buf(fi, req);
-
-        case RAW1394_REQ_ARM_GET_BUF:
-                return arm_get_buf(fi, req);
-
-        case RAW1394_REQ_RESET_NOTIFY:
-                return reset_notification(fi, req);
-
-        case RAW1394_REQ_ISO_LISTEN:
-                handle_iso_listen(fi, req);
-                return sizeof(struct raw1394_request);
-
-        case RAW1394_REQ_FCP_LISTEN:
-                handle_fcp_listen(fi, req);
-                return sizeof(struct raw1394_request);
-
-        case RAW1394_REQ_RESET_BUS:
-                if (req->req.misc == RAW1394_LONG_RESET) {
-                        DBGMSG("busreset called (type: LONG)");
-                        hpsb_reset_bus(fi->host, LONG_RESET);
-                        free_pending_request(req); /* we have to free the request, because we queue no response, and therefore nobody will free it */
-                        return sizeof(struct raw1394_request);
-                }
-                if (req->req.misc == RAW1394_SHORT_RESET) {
-                        DBGMSG("busreset called (type: SHORT)");
-                        hpsb_reset_bus(fi->host, SHORT_RESET);
-                        free_pending_request(req); /* we have to free the request, because we queue no response, and therefore nobody will free it */
-                        return sizeof(struct raw1394_request);
-                }
-                /* error EINVAL (22) invalid argument */
-                return (-EINVAL);
-        case RAW1394_REQ_GET_ROM:
-                return get_config_rom(fi, req);
+	case RAW1394_REQ_ARM_GET_BUF:
+		return arm_get_buf(fi, req);
 
-        case RAW1394_REQ_UPDATE_ROM:
-                return update_config_rom(fi, req);
+	case RAW1394_REQ_RESET_NOTIFY:
+		return reset_notification(fi, req);
+
+	case RAW1394_REQ_ISO_LISTEN:
+		handle_iso_listen(fi, req);
+		return sizeof(struct raw1394_request);
+
+	case RAW1394_REQ_FCP_LISTEN:
+		handle_fcp_listen(fi, req);
+		return sizeof(struct raw1394_request);
+
+	case RAW1394_REQ_RESET_BUS:
+		if (req->req.misc == RAW1394_LONG_RESET) {
+			DBGMSG("busreset called (type: LONG)");
+			hpsb_reset_bus(fi->host, LONG_RESET);
+			free_pending_request(req);	/* we have to free the request, because we queue no response, and therefore nobody will free it */
+			return sizeof(struct raw1394_request);
+		}
+		if (req->req.misc == RAW1394_SHORT_RESET) {
+			DBGMSG("busreset called (type: SHORT)");
+			hpsb_reset_bus(fi->host, SHORT_RESET);
+			free_pending_request(req);	/* we have to free the request, because we queue no response, and therefore nobody will free it */
+			return sizeof(struct raw1394_request);
+		}
+		/* error EINVAL (22) invalid argument */
+		return (-EINVAL);
+	case RAW1394_REQ_GET_ROM:
+		return get_config_rom(fi, req);
+
+	case RAW1394_REQ_UPDATE_ROM:
+		return update_config_rom(fi, req);
 
 	case RAW1394_REQ_MODIFY_ROM:
 		return modify_config_rom(fi, req);
-        }
+	}
 
-        if (req->req.generation != get_hpsb_generation(fi->host)) {
-                req->req.error = RAW1394_ERROR_GENERATION;
-                req->req.generation = get_hpsb_generation(fi->host);
-                req->req.length = 0;
-                queue_complete_req(req);
-                return sizeof(struct raw1394_request);
-        }
-
-        switch (req->req.type) {
-        case RAW1394_REQ_PHYPACKET:
-                return write_phypacket(fi, req);
-        case RAW1394_REQ_ASYNC_SEND:
-                return handle_async_send(fi, req);
-        }
-
-        if (req->req.length == 0) {
-                req->req.error = RAW1394_ERROR_INVALID_ARG;
-                queue_complete_req(req);
-                return sizeof(struct raw1394_request);
-        }
-
-        return handle_async_request(fi, req, node);
-}
-
-
-static ssize_t raw1394_write(struct file *file, const char __user *buffer, size_t count,
-                     loff_t *offset_is_ignored)
-{
-        struct file_info *fi = (struct file_info *)file->private_data;
-        struct pending_request *req;
-        ssize_t retval = 0;
-
-        if (count != sizeof(struct raw1394_request)) {
-                return -EINVAL;
-        }
-
-        req = alloc_pending_request();
-        if (req == NULL) {
-                return -ENOMEM;
-        }
-        req->file_info = fi;
-
-        if (copy_from_user(&req->req, buffer, sizeof(struct raw1394_request))) {
-                free_pending_request(req);
-                return -EFAULT;
-        }
-
-        switch (fi->state) {
-        case opened:
-                retval = state_opened(fi, req);
-                break;
-
-        case initialized:
-                retval = state_initialized(fi, req);
-                break;
-
-        case connected:
-                retval = state_connected(fi, req);
-                break;
-        }
-
-        if (retval < 0) {
-                free_pending_request(req);
-        }
+	if (req->req.generation != get_hpsb_generation(fi->host)) {
+		req->req.error = RAW1394_ERROR_GENERATION;
+		req->req.generation = get_hpsb_generation(fi->host);
+		req->req.length = 0;
+		queue_complete_req(req);
+		return sizeof(struct raw1394_request);
+	}
+
+	switch (req->req.type) {
+	case RAW1394_REQ_PHYPACKET:
+		return write_phypacket(fi, req);
+	case RAW1394_REQ_ASYNC_SEND:
+		return handle_async_send(fi, req);
+	}
 
-        return retval;
+	if (req->req.length == 0) {
+		req->req.error = RAW1394_ERROR_INVALID_ARG;
+		queue_complete_req(req);
+		return sizeof(struct raw1394_request);
+	}
+
+	return handle_async_request(fi, req, node);
+}
+
+static ssize_t raw1394_write(struct file *file, const char __user * buffer,
+			     size_t count, loff_t * offset_is_ignored)
+{
+	struct file_info *fi = (struct file_info *)file->private_data;
+	struct pending_request *req;
+	ssize_t retval = 0;
+
+	if (count != sizeof(struct raw1394_request)) {
+		return -EINVAL;
+	}
+
+	req = alloc_pending_request();
+	if (req == NULL) {
+		return -ENOMEM;
+	}
+	req->file_info = fi;
+
+	if (copy_from_user(&req->req, buffer, sizeof(struct raw1394_request))) {
+		free_pending_request(req);
+		return -EFAULT;
+	}
+
+	switch (fi->state) {
+	case opened:
+		retval = state_opened(fi, req);
+		break;
+
+	case initialized:
+		retval = state_initialized(fi, req);
+		break;
+
+	case connected:
+		retval = state_connected(fi, req);
+		break;
+	}
+
+	if (retval < 0) {
+		free_pending_request(req);
+	}
+
+	return retval;
 }
 
 /* rawiso operations */
@@ -2185,8 +2324,8 @@
 	struct pending_request *req;
 
 	list_for_each_entry(req, &fi->req_complete, list)
-		if (req->req.type == RAW1394_REQ_RAWISO_ACTIVITY)
-			return 1;
+	    if (req->req.type == RAW1394_REQ_RAWISO_ACTIVITY)
+		return 1;
 
 	return 0;
 }
@@ -2200,7 +2339,8 @@
 
 	/* only one ISO activity event may be in the queue */
 	if (!__rawiso_event_in_queue(fi)) {
-		struct pending_request *req = __alloc_pending_request(SLAB_ATOMIC);
+		struct pending_request *req =
+		    __alloc_pending_request(SLAB_ATOMIC);
 
 		if (req) {
 			req->file_info = fi;
@@ -2220,11 +2360,11 @@
 static void rawiso_activity_cb(struct hpsb_iso *iso)
 {
 	unsigned long flags;
-        struct host_info *hi;
+	struct host_info *hi;
 	struct file_info *fi;
 
-        spin_lock_irqsave(&host_info_lock, flags);
-        hi = find_host_info(iso->host);
+	spin_lock_irqsave(&host_info_lock, flags);
+	hi = find_host_info(iso->host);
 
 	if (hi != NULL) {
 		list_for_each_entry(fi, &hi->file_info_list, list) {
@@ -2237,7 +2377,8 @@
 }
 
 /* helper function - gather all the kernel iso status bits for returning to user-space */
-static void raw1394_iso_fill_status(struct hpsb_iso *iso, struct raw1394_iso_status *stat)
+static void raw1394_iso_fill_status(struct hpsb_iso *iso,
+				    struct raw1394_iso_status *stat)
 {
 	stat->config.data_buf_size = iso->buf_size;
 	stat->config.buf_packets = iso->buf_packets;
@@ -2249,7 +2390,7 @@
 	stat->xmit_cycle = iso->xmit_cycle;
 }
 
-static int raw1394_iso_xmit_init(struct file_info *fi, void __user *uaddr)
+static int raw1394_iso_xmit_init(struct file_info *fi, void __user * uaddr)
 {
 	struct raw1394_iso_status stat;
 
@@ -2281,7 +2422,7 @@
 	return 0;
 }
 
-static int raw1394_iso_recv_init(struct file_info *fi, void __user *uaddr)
+static int raw1394_iso_recv_init(struct file_info *fi, void __user * uaddr)
 {
 	struct raw1394_iso_status stat;
 
@@ -2295,7 +2436,7 @@
 					    stat.config.data_buf_size,
 					    stat.config.buf_packets,
 					    stat.config.channel,
- 					    stat.config.dma_mode,
+					    stat.config.dma_mode,
 					    stat.config.irq_interval,
 					    rawiso_activity_cb);
 	if (!fi->iso_handle)
@@ -2309,7 +2450,7 @@
 	return 0;
 }
 
-static int raw1394_iso_get_status(struct file_info *fi, void __user *uaddr)
+static int raw1394_iso_get_status(struct file_info *fi, void __user * uaddr)
 {
 	struct raw1394_iso_status stat;
 	struct hpsb_iso *iso = fi->iso_handle;
@@ -2325,7 +2466,7 @@
 }
 
 /* copy N packet_infos out of the ringbuffer into user-supplied array */
-static int raw1394_iso_recv_packets(struct file_info *fi, void __user *uaddr)
+static int raw1394_iso_recv_packets(struct file_info *fi, void __user * uaddr)
 {
 	struct raw1394_iso_packets upackets;
 	unsigned int packet = fi->iso_handle->first_packet;
@@ -2339,14 +2480,15 @@
 
 	/* ensure user-supplied buffer is accessible and big enough */
 	if (verify_area(VERIFY_WRITE, upackets.infos,
-		       upackets.n_packets * sizeof(struct raw1394_iso_packet_info)))
+			upackets.n_packets *
+			sizeof(struct raw1394_iso_packet_info)))
 		return -EFAULT;
 
 	/* copy the packet_infos out */
 	for (i = 0; i < upackets.n_packets; i++) {
 		if (__copy_to_user(&upackets.infos[i],
-				  &fi->iso_handle->infos[packet],
-				  sizeof(struct raw1394_iso_packet_info)))
+				   &fi->iso_handle->infos[packet],
+				   sizeof(struct raw1394_iso_packet_info)))
 			return -EFAULT;
 
 		packet = (packet + 1) % fi->iso_handle->buf_packets;
@@ -2356,7 +2498,7 @@
 }
 
 /* copy N packet_infos from user to ringbuffer, and queue them for transmission */
-static int raw1394_iso_send_packets(struct file_info *fi, void __user *uaddr)
+static int raw1394_iso_send_packets(struct file_info *fi, void __user * uaddr)
 {
 	struct raw1394_iso_packets upackets;
 	int i, rv;
@@ -2369,7 +2511,8 @@
 
 	/* ensure user-supplied buffer is accessible and big enough */
 	if (verify_area(VERIFY_READ, upackets.infos,
-		       upackets.n_packets * sizeof(struct raw1394_iso_packet_info)))
+			upackets.n_packets *
+			sizeof(struct raw1394_iso_packet_info)))
 		return -EFAULT;
 
 	/* copy the infos structs in and queue the packets */
@@ -2377,7 +2520,7 @@
 		struct raw1394_iso_packet_info info;
 
 		if (__copy_from_user(&info, &upackets.infos[i],
-				    sizeof(struct raw1394_iso_packet_info)))
+				     sizeof(struct raw1394_iso_packet_info)))
 			return -EFAULT;
 
 		rv = hpsb_iso_xmit_queue_packet(fi->iso_handle, info.offset,
@@ -2410,14 +2553,15 @@
 }
 
 /* ioctl is only used for rawiso operations */
-static int raw1394_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+static int raw1394_ioctl(struct inode *inode, struct file *file,
+			 unsigned int cmd, unsigned long arg)
 {
 	struct file_info *fi = file->private_data;
 	void __user *argp = (void __user *)arg;
 
-	switch(fi->iso_state) {
+	switch (fi->iso_state) {
 	case RAW1394_ISO_INACTIVE:
-		switch(cmd) {
+		switch (cmd) {
 		case RAW1394_IOC_ISO_XMIT_INIT:
 			return raw1394_iso_xmit_init(fi, argp);
 		case RAW1394_IOC_ISO_RECV_INIT:
@@ -2427,34 +2571,42 @@
 		}
 		break;
 	case RAW1394_ISO_RECV:
-		switch(cmd) {
-		case RAW1394_IOC_ISO_RECV_START: {
-			/* copy args from user-space */
-			int args[3];
-			if (copy_from_user(&args[0], argp, sizeof(args)))
-				return -EFAULT;
-			return hpsb_iso_recv_start(fi->iso_handle, args[0], args[1], args[2]);
-		}
+		switch (cmd) {
+		case RAW1394_IOC_ISO_RECV_START:{
+				/* copy args from user-space */
+				int args[3];
+				if (copy_from_user
+				    (&args[0], argp, sizeof(args)))
+					return -EFAULT;
+				return hpsb_iso_recv_start(fi->iso_handle,
+							   args[0], args[1],
+							   args[2]);
+			}
 		case RAW1394_IOC_ISO_XMIT_RECV_STOP:
 			hpsb_iso_stop(fi->iso_handle);
 			return 0;
 		case RAW1394_IOC_ISO_RECV_LISTEN_CHANNEL:
-			return hpsb_iso_recv_listen_channel(fi->iso_handle, arg);
+			return hpsb_iso_recv_listen_channel(fi->iso_handle,
+							    arg);
 		case RAW1394_IOC_ISO_RECV_UNLISTEN_CHANNEL:
-			return hpsb_iso_recv_unlisten_channel(fi->iso_handle, arg);
-		case RAW1394_IOC_ISO_RECV_SET_CHANNEL_MASK: {
-			/* copy the u64 from user-space */
-			u64 mask;
-			if (copy_from_user(&mask, argp, sizeof(mask)))
-				return -EFAULT;
-			return hpsb_iso_recv_set_channel_mask(fi->iso_handle, mask);
-		}
+			return hpsb_iso_recv_unlisten_channel(fi->iso_handle,
+							      arg);
+		case RAW1394_IOC_ISO_RECV_SET_CHANNEL_MASK:{
+				/* copy the u64 from user-space */
+				u64 mask;
+				if (copy_from_user(&mask, argp, sizeof(mask)))
+					return -EFAULT;
+				return hpsb_iso_recv_set_channel_mask(fi->
+								      iso_handle,
+								      mask);
+			}
 		case RAW1394_IOC_ISO_GET_STATUS:
 			return raw1394_iso_get_status(fi, argp);
 		case RAW1394_IOC_ISO_RECV_PACKETS:
 			return raw1394_iso_recv_packets(fi, argp);
 		case RAW1394_IOC_ISO_RECV_RELEASE_PACKETS:
-			return hpsb_iso_recv_release_packets(fi->iso_handle, arg);
+			return hpsb_iso_recv_release_packets(fi->iso_handle,
+							     arg);
 		case RAW1394_IOC_ISO_RECV_FLUSH:
 			return hpsb_iso_recv_flush(fi->iso_handle);
 		case RAW1394_IOC_ISO_SHUTDOWN:
@@ -2466,14 +2618,16 @@
 		}
 		break;
 	case RAW1394_ISO_XMIT:
-		switch(cmd) {
-		case RAW1394_IOC_ISO_XMIT_START: {
-			/* copy two ints from user-space */
-			int args[2];
-			if (copy_from_user(&args[0], argp, sizeof(args)))
-				return -EFAULT;
-			return hpsb_iso_xmit_start(fi->iso_handle, args[0], args[1]);
-		}
+		switch (cmd) {
+		case RAW1394_IOC_ISO_XMIT_START:{
+				/* copy two ints from user-space */
+				int args[2];
+				if (copy_from_user
+				    (&args[0], argp, sizeof(args)))
+					return -EFAULT;
+				return hpsb_iso_xmit_start(fi->iso_handle,
+							   args[0], args[1]);
+			}
 		case RAW1394_IOC_ISO_XMIT_SYNC:
 			return hpsb_iso_xmit_sync(fi->iso_handle);
 		case RAW1394_IOC_ISO_XMIT_RECV_STOP:
@@ -2498,270 +2652,303 @@
 	return -EINVAL;
 }
 
-static unsigned int raw1394_poll(struct file *file, poll_table *pt)
+static unsigned int raw1394_poll(struct file *file, poll_table * pt)
 {
-        struct file_info *fi = file->private_data;
-        unsigned int mask = POLLOUT | POLLWRNORM;
+	struct file_info *fi = file->private_data;
+	unsigned int mask = POLLOUT | POLLWRNORM;
 
-        poll_wait(file, &fi->poll_wait_complete, pt);
+	poll_wait(file, &fi->poll_wait_complete, pt);
 
-        spin_lock_irq(&fi->reqlists_lock);
-        if (!list_empty(&fi->req_complete)) {
-                mask |= POLLIN | POLLRDNORM;
-        }
-        spin_unlock_irq(&fi->reqlists_lock);
+	spin_lock_irq(&fi->reqlists_lock);
+	if (!list_empty(&fi->req_complete)) {
+		mask |= POLLIN | POLLRDNORM;
+	}
+	spin_unlock_irq(&fi->reqlists_lock);
 
-        return mask;
+	return mask;
 }
 
 static int raw1394_open(struct inode *inode, struct file *file)
 {
-        struct file_info *fi;
+	struct file_info *fi;
+
+	fi = kmalloc(sizeof(struct file_info), SLAB_KERNEL);
+	if (fi == NULL)
+		return -ENOMEM;
+
+	memset(fi, 0, sizeof(struct file_info));
+	fi->notification = (u8) RAW1394_NOTIFY_ON;	/* busreset notification */
 
-        fi = kmalloc(sizeof(struct file_info), SLAB_KERNEL);
-        if (fi == NULL)
-                return -ENOMEM;
-
-        memset(fi, 0, sizeof(struct file_info));
-        fi->notification = (u8) RAW1394_NOTIFY_ON; /* busreset notification */
-
-        INIT_LIST_HEAD(&fi->list);
-        fi->state = opened;
-        INIT_LIST_HEAD(&fi->req_pending);
-        INIT_LIST_HEAD(&fi->req_complete);
-        sema_init(&fi->complete_sem, 0);
-        spin_lock_init(&fi->reqlists_lock);
-        init_waitqueue_head(&fi->poll_wait_complete);
-        INIT_LIST_HEAD(&fi->addr_list);
+	INIT_LIST_HEAD(&fi->list);
+	fi->state = opened;
+	INIT_LIST_HEAD(&fi->req_pending);
+	INIT_LIST_HEAD(&fi->req_complete);
+	sema_init(&fi->complete_sem, 0);
+	spin_lock_init(&fi->reqlists_lock);
+	init_waitqueue_head(&fi->poll_wait_complete);
+	INIT_LIST_HEAD(&fi->addr_list);
 
-        file->private_data = fi;
+	file->private_data = fi;
 
-        return 0;
+	return 0;
 }
 
 static int raw1394_release(struct inode *inode, struct file *file)
 {
-        struct file_info *fi = file->private_data;
-        struct list_head *lh;
-        struct pending_request *req;
-        int done = 0, i, fail = 0;
-        int retval = 0;
-        struct list_head *entry;
-        struct arm_addr  *addr = NULL;
-        struct host_info *hi;
-        struct file_info *fi_hlp = NULL;
-        struct arm_addr  *arm_addr = NULL;
-        int another_host;
+	struct file_info *fi = file->private_data;
+	struct list_head *lh;
+	struct pending_request *req;
+	int done = 0, i, fail = 0;
+	int retval = 0;
+	struct list_head *entry;
+	struct arm_addr *addr = NULL;
+	struct host_info *hi;
+	struct file_info *fi_hlp = NULL;
+	struct arm_addr *arm_addr = NULL;
+	int another_host;
 	int csr_mod = 0;
 
 	if (fi->iso_state != RAW1394_ISO_INACTIVE)
 		raw1394_iso_shutdown(fi);
 
-        for (i = 0; i < 64; i++) {
-                if (fi->listen_channels & (1ULL << i)) {
-                        hpsb_unlisten_channel(&raw1394_highlevel, fi->host, i);
-                }
-        }
-
-        spin_lock_irq(&host_info_lock);
-        fi->listen_channels = 0;
-        spin_unlock_irq(&host_info_lock);
-
-        fail = 0;
-        /* set address-entries invalid */
-        spin_lock_irq(&host_info_lock);
-
-        while (!list_empty(&fi->addr_list)) {
-                another_host = 0;
-                lh = fi->addr_list.next;
-                addr = list_entry(lh, struct arm_addr, addr_list);
-                /* another host with valid address-entry containing
-                   same addressrange? */
-                list_for_each_entry(hi, &host_info_list, list) {
-                        if (hi->host != fi->host) {
-                                list_for_each_entry(fi_hlp, &hi->file_info_list, list) {
-                                        entry = fi_hlp->addr_list.next;
-                                        while (entry != &(fi_hlp->addr_list)) {
-                                                arm_addr = list_entry(entry,
-                                                        struct arm_addr, addr_list);
-                                                if (arm_addr->start ==
-                                                        addr->start) {
-                                                        DBGMSG("raw1394_release: "
-                                                        "another host ownes "
-                                                        "same addressrange");
-                                                        another_host = 1;
-                                                        break;
-                                                }
-                                                entry = entry->next;
-                                        }
-                                        if (another_host) {
-                                                break;
-                                        }
-                                }
-                        }
-                }
-                if (!another_host) {
-                        DBGMSG("raw1394_release: call hpsb_arm_unregister");
-                        retval = hpsb_unregister_addrspace(&raw1394_highlevel, fi->host, addr->start);
-                        if (!retval) {
-                                ++fail;
-                                printk(KERN_ERR "raw1394_release arm_Unregister failed\n");
-                        }
-                }
-                DBGMSG("raw1394_release: delete addr_entry from list");
-                list_del(&addr->addr_list);
-                vfree(addr->addr_space_buffer);
-                kfree(addr);
-        } /* while */
-        spin_unlock_irq(&host_info_lock);
-        if (fail > 0) {
-                printk(KERN_ERR "raw1394: during addr_list-release "
-                        "error(s) occurred \n");
-        }
-
-        while (!done) {
-                spin_lock_irq(&fi->reqlists_lock);
-
-                while (!list_empty(&fi->req_complete)) {
-                        lh = fi->req_complete.next;
-                        list_del(lh);
-
-                        req = list_entry(lh, struct pending_request, list);
-
-                        free_pending_request(req);
-                }
+	for (i = 0; i < 64; i++) {
+		if (fi->listen_channels & (1ULL << i)) {
+			hpsb_unlisten_channel(&raw1394_highlevel, fi->host, i);
+		}
+	}
+
+	spin_lock_irq(&host_info_lock);
+	fi->listen_channels = 0;
+	spin_unlock_irq(&host_info_lock);
+
+	fail = 0;
+	/* set address-entries invalid */
+	spin_lock_irq(&host_info_lock);
+
+	while (!list_empty(&fi->addr_list)) {
+		another_host = 0;
+		lh = fi->addr_list.next;
+		addr = list_entry(lh, struct arm_addr, addr_list);
+		/* another host with valid address-entry containing
+		   same addressrange? */
+		list_for_each_entry(hi, &host_info_list, list) {
+			if (hi->host != fi->host) {
+				list_for_each_entry(fi_hlp, &hi->file_info_list,
+						    list) {
+					entry = fi_hlp->addr_list.next;
+					while (entry != &(fi_hlp->addr_list)) {
+						arm_addr = list_entry(entry, struct
+								      arm_addr,
+								      addr_list);
+						if (arm_addr->start ==
+						    addr->start) {
+							DBGMSG
+							    ("raw1394_release: "
+							     "another host ownes "
+							     "same addressrange");
+							another_host = 1;
+							break;
+						}
+						entry = entry->next;
+					}
+					if (another_host) {
+						break;
+					}
+				}
+			}
+		}
+		if (!another_host) {
+			DBGMSG("raw1394_release: call hpsb_arm_unregister");
+			retval =
+			    hpsb_unregister_addrspace(&raw1394_highlevel,
+						      fi->host, addr->start);
+			if (!retval) {
+				++fail;
+				printk(KERN_ERR
+				       "raw1394_release arm_Unregister failed\n");
+			}
+		}
+		DBGMSG("raw1394_release: delete addr_entry from list");
+		list_del(&addr->addr_list);
+		vfree(addr->addr_space_buffer);
+		kfree(addr);
+	}			/* while */
+	spin_unlock_irq(&host_info_lock);
+	if (fail > 0) {
+		printk(KERN_ERR "raw1394: during addr_list-release "
+		       "error(s) occurred \n");
+	}
+
+	while (!done) {
+		spin_lock_irq(&fi->reqlists_lock);
+
+		while (!list_empty(&fi->req_complete)) {
+			lh = fi->req_complete.next;
+			list_del(lh);
+
+			req = list_entry(lh, struct pending_request, list);
 
-                if (list_empty(&fi->req_pending)) done = 1;
+			free_pending_request(req);
+		}
 
-                spin_unlock_irq(&fi->reqlists_lock);
+		if (list_empty(&fi->req_pending))
+			done = 1;
 
-                if (!done) down_interruptible(&fi->complete_sem);
-        }
+		spin_unlock_irq(&fi->reqlists_lock);
+
+		if (!done)
+			down_interruptible(&fi->complete_sem);
+	}
 
 	/* Remove any sub-trees left by user space programs */
 	for (i = 0; i < RAW1394_MAX_USER_CSR_DIRS; i++) {
 		struct csr1212_dentry *dentry;
-		if (!fi->csr1212_dirs[i]) continue;
-		for (dentry = fi->csr1212_dirs[i]->value.directory.dentries_head;
-		     dentry; dentry = dentry->next) {
-			csr1212_detach_keyval_from_directory(fi->host->csr.rom->root_kv, dentry->kv);
+		if (!fi->csr1212_dirs[i])
+			continue;
+		for (dentry =
+		     fi->csr1212_dirs[i]->value.directory.dentries_head; dentry;
+		     dentry = dentry->next) {
+			csr1212_detach_keyval_from_directory(fi->host->csr.rom->
+							     root_kv,
+							     dentry->kv);
 		}
 		csr1212_release_keyval(fi->csr1212_dirs[i]);
 		fi->csr1212_dirs[i] = NULL;
 		csr_mod = 1;
 	}
 
-	if ((csr_mod || fi->cfgrom_upd) && hpsb_update_config_rom_image(fi->host) < 0)
-		HPSB_ERR("Failed to generate Configuration ROM image for host %d", fi->host->id);
-
-        if (fi->state == connected) {
-                spin_lock_irq(&host_info_lock);
-                list_del(&fi->list);
-                spin_unlock_irq(&host_info_lock);
+	if ((csr_mod || fi->cfgrom_upd)
+	    && hpsb_update_config_rom_image(fi->host) < 0)
+		HPSB_ERR
+		    ("Failed to generate Configuration ROM image for host %d",
+		     fi->host->id);
+
+	if (fi->state == connected) {
+		spin_lock_irq(&host_info_lock);
+		list_del(&fi->list);
+		spin_unlock_irq(&host_info_lock);
 
 		put_device(&fi->host->device);
-        }
+	}
 
-        kfree(fi);
+	kfree(fi);
 
-        return 0;
+	return 0;
 }
 
-
 /*** HOTPLUG STUFF **********************************************************/
 /*
  * Export information about protocols/devices supported by this driver.
  */
 static struct ieee1394_device_id raw1394_id_table[] = {
 	{
-		.match_flags	= IEEE1394_MATCH_SPECIFIER_ID | IEEE1394_MATCH_VERSION,
-		.specifier_id	= AVC_UNIT_SPEC_ID_ENTRY & 0xffffff,
-		.version	= AVC_SW_VERSION_ENTRY & 0xffffff
-	},
+	 .match_flags = IEEE1394_MATCH_SPECIFIER_ID | IEEE1394_MATCH_VERSION,
+	 .specifier_id = AVC_UNIT_SPEC_ID_ENTRY & 0xffffff,
+	 .version = AVC_SW_VERSION_ENTRY & 0xffffff},
+	{
+	 .match_flags = IEEE1394_MATCH_SPECIFIER_ID | IEEE1394_MATCH_VERSION,
+	 .specifier_id = CAMERA_UNIT_SPEC_ID_ENTRY & 0xffffff,
+	 .version = CAMERA_SW_VERSION_ENTRY & 0xffffff},
 	{
-		.match_flags	= IEEE1394_MATCH_SPECIFIER_ID | IEEE1394_MATCH_VERSION,
-		.specifier_id	= CAMERA_UNIT_SPEC_ID_ENTRY & 0xffffff,
-		.version	= CAMERA_SW_VERSION_ENTRY & 0xffffff
-	},
-	{ }
+	 .match_flags = IEEE1394_MATCH_SPECIFIER_ID | IEEE1394_MATCH_VERSION,
+	 .specifier_id = CAMERA_UNIT_SPEC_ID_ENTRY & 0xffffff,
+	 .version = (CAMERA_SW_VERSION_ENTRY + 1) & 0xffffff},
+	{
+	 .match_flags = IEEE1394_MATCH_SPECIFIER_ID | IEEE1394_MATCH_VERSION,
+	 .specifier_id = CAMERA_UNIT_SPEC_ID_ENTRY & 0xffffff,
+	 .version = (CAMERA_SW_VERSION_ENTRY + 2) & 0xffffff},
+	{}
 };
 
 MODULE_DEVICE_TABLE(ieee1394, raw1394_id_table);
 
 static struct hpsb_protocol_driver raw1394_driver = {
-	.name		= "raw1394 Driver",
-	.id_table	= raw1394_id_table,
-	.driver		= {
-		.name	= "raw1394",
-		.bus	= &ieee1394_bus_type,
-	},
+	.name = "raw1394 Driver",
+	.id_table = raw1394_id_table,
+	.driver = {
+		   .name = "raw1394",
+		   .bus = &ieee1394_bus_type,
+		   },
 };
 
-
 /******************************************************************************/
 
-
 static struct hpsb_highlevel raw1394_highlevel = {
-	.name =		RAW1394_DEVICE_NAME,
-        .add_host =    add_host,
-        .remove_host = remove_host,
-        .host_reset =  host_reset,
-        .iso_receive = iso_receive,
-        .fcp_request = fcp_request,
+	.name = RAW1394_DEVICE_NAME,
+	.add_host = add_host,
+	.remove_host = remove_host,
+	.host_reset = host_reset,
+	.iso_receive = iso_receive,
+	.fcp_request = fcp_request,
 };
 
 static struct cdev raw1394_cdev;
 static struct file_operations raw1394_fops = {
-	.owner =	THIS_MODULE,
-        .read =		raw1394_read,
-        .write =	raw1394_write,
-	.mmap =         raw1394_mmap,
-	.ioctl =        raw1394_ioctl,
-        .poll =		raw1394_poll,
-        .open =		raw1394_open,
-        .release =	raw1394_release,
+	.owner = THIS_MODULE,
+	.read = raw1394_read,
+	.write = raw1394_write,
+	.mmap = raw1394_mmap,
+	.ioctl = raw1394_ioctl,
+	.poll = raw1394_poll,
+	.open = raw1394_open,
+	.release = raw1394_release,
 };
 
 static int __init init_raw1394(void)
 {
-	int ret;
+	int ret = 0;
 
 	hpsb_register_highlevel(&raw1394_highlevel);
 
-        devfs_mk_cdev(MKDEV(IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_RAW1394 * 16),
-			S_IFCHR | S_IRUSR | S_IWUSR, RAW1394_DEVICE_NAME);
+	if (IS_ERR(class_simple_device_add(hpsb_protocol_class, MKDEV(
+		IEEE1394_MAJOR,	IEEE1394_MINOR_BLOCK_RAW1394 * 16), 
+		NULL, RAW1394_DEVICE_NAME))) {
+		ret = -EFAULT;
+		goto out_unreg;
+	}
+	
+	devfs_mk_cdev(MKDEV(
+		IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_RAW1394 * 16),
+		S_IFCHR | S_IRUSR | S_IWUSR, RAW1394_DEVICE_NAME);
 
 	cdev_init(&raw1394_cdev, &raw1394_fops);
 	raw1394_cdev.owner = THIS_MODULE;
 	kobject_set_name(&raw1394_cdev.kobj, RAW1394_DEVICE_NAME);
 	ret = cdev_add(&raw1394_cdev, IEEE1394_RAW1394_DEV, 1);
 	if (ret) {
-                HPSB_ERR("raw1394 failed to register minor device block");
-                devfs_remove(RAW1394_DEVICE_NAME);
-                hpsb_unregister_highlevel(&raw1394_highlevel);
-                return ret;
-        }
+		HPSB_ERR("raw1394 failed to register minor device block");
+		goto out_dev;
+	}
 
-        HPSB_INFO("raw1394: /dev/%s device initialized", RAW1394_DEVICE_NAME);
+	HPSB_INFO("raw1394: /dev/%s device initialized", RAW1394_DEVICE_NAME);
 
 	ret = hpsb_register_protocol(&raw1394_driver);
 	if (ret) {
 		HPSB_ERR("raw1394: failed to register protocol");
 		cdev_del(&raw1394_cdev);
-		devfs_remove(RAW1394_DEVICE_NAME);
-		hpsb_unregister_highlevel(&raw1394_highlevel);
-		return ret;
+		goto out_dev;
 	}
 
-        return 0;
+	goto out;
+
+out_dev:
+	devfs_remove(RAW1394_DEVICE_NAME);
+	class_simple_device_remove(MKDEV(
+		IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_RAW1394 * 16));
+out_unreg:
+	hpsb_unregister_highlevel(&raw1394_highlevel);
+out:
+	return ret;
 }
 
 static void __exit cleanup_raw1394(void)
 {
+	class_simple_device_remove(MKDEV(
+		IEEE1394_MAJOR, IEEE1394_MINOR_BLOCK_RAW1394 * 16));
 	hpsb_unregister_protocol(&raw1394_driver);
 	cdev_del(&raw1394_cdev);
-        devfs_remove(RAW1394_DEVICE_NAME);
-        hpsb_unregister_highlevel(&raw1394_highlevel);
+	devfs_remove(RAW1394_DEVICE_NAME);
+	hpsb_unregister_highlevel(&raw1394_highlevel);
 }
 
 module_init(init_raw1394);
diff -Nru a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c
--- a/drivers/ieee1394/sbp2.c	2005-03-11 12:51:41 -08:00
+++ b/drivers/ieee1394/sbp2.c	2005-03-11 12:51:41 -08:00
@@ -64,7 +64,10 @@
 #include <asm/system.h>
 #include <asm/scatterlist.h>
 
-#include "../scsi/scsi.h"
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_dbg.h>
+#include <scsi/scsi_device.h>
 #include <scsi/scsi_host.h>
 
 #include "csr1212.h"
@@ -224,12 +227,12 @@
 					   u32 status);
 
 static void sbp2scsi_complete_command(struct scsi_id_instance_data *scsi_id,
-				      u32 scsi_status, Scsi_Cmnd *SCpnt,
-				      void (*done)(Scsi_Cmnd *));
+				      u32 scsi_status, struct scsi_cmnd *SCpnt,
+				      void (*done)(struct scsi_cmnd *));
 
-static Scsi_Host_Template scsi_driver_template;
+static struct scsi_host_template scsi_driver_template;
 
-const u8 sbp2_speedto_max_payload[] = { 0x7, 0x8, 0x9, 0xA, 0xB, 0xC };
+static const u8 sbp2_speedto_max_payload[] = { 0x7, 0x8, 0x9, 0xA, 0xB, 0xC };
 
 static void sbp2_host_reset(struct hpsb_host *host);
 
@@ -373,7 +376,7 @@
 /* This is much like hpsb_node_write(), except it ignores the response
  * subaction and returns immediately. Can be used from interrupts.
  */
-int sbp2util_node_write_no_wait(struct node_entry *ne, u64 addr,
+static int sbp2util_node_write_no_wait(struct node_entry *ne, u64 addr,
 				quadlet_t *buffer, size_t length)
 {
 	struct hpsb_packet *packet;
@@ -520,8 +523,8 @@
  */
 static struct sbp2_command_info *sbp2util_allocate_command_orb(
 		struct scsi_id_instance_data *scsi_id,
-		Scsi_Cmnd *Current_SCpnt,
-		void (*Current_done)(Scsi_Cmnd *))
+		struct scsi_cmnd *Current_SCpnt,
+		void (*Current_done)(struct scsi_cmnd *))
 {
 	struct list_head *lh;
 	struct sbp2_command_info *command = NULL;
@@ -1521,8 +1524,9 @@
 
 				SBP2_DEBUG("sbp2_management_agent_addr = %x",
 					   (unsigned int) management_agent_addr);
-			} else
+			} else if (kv->key.type == CSR1212_KV_TYPE_IMMEDIATE) {
 				scsi_id->sbp2_device_type_and_lun = kv->value.immediate;
+			}
 			break;
 
 		case SBP2_COMMAND_SET_SPEC_ID_KEY:
@@ -1613,6 +1617,8 @@
 		scsi_id->sbp2_unit_characteristics = unit_characteristics;
 		scsi_id->sbp2_firmware_revision = firmware_revision;
 		scsi_id->workarounds = workarounds;
+		if (ud->flags & UNIT_DIRECTORY_HAS_LUN)
+			scsi_id->sbp2_device_type_and_lun = ud->lun;
 	}
 }
 
@@ -1700,14 +1706,14 @@
 				   unsigned int scsi_use_sg,
 				   unsigned int scsi_request_bufflen,
 				   void *scsi_request_buffer,
-				   unsigned char scsi_dir)
+				   enum dma_data_direction dma_dir)
+
 {
 	struct sbp2scsi_host_info *hi = scsi_id->hi;
 	struct scatterlist *sgpnt = (struct scatterlist *) scsi_request_buffer;
 	struct sbp2_command_orb *command_orb = &command->command_orb;
 	struct sbp2_unrestricted_page_table *scatter_gather_element =
 		&command->scatter_gather_element[0];
-	int dma_dir = scsi_to_pci_dma_dir (scsi_dir);
 	u32 sg_count, sg_len, orb_direction;
 	dma_addr_t sg_addr;
 	int i;
@@ -1730,22 +1736,22 @@
 	 * Get the direction of the transfer. If the direction is unknown, then use our
 	 * goofy table as a back-up.
 	 */
-	switch (scsi_dir) {
-		case SCSI_DATA_NONE:
+	switch (dma_dir) {
+		case DMA_NONE:
 			orb_direction = ORB_DIRECTION_NO_DATA_TRANSFER;
 			break;
-		case SCSI_DATA_WRITE:
+		case DMA_TO_DEVICE:
 			orb_direction = ORB_DIRECTION_WRITE_TO_MEDIA;
 			break;
-		case SCSI_DATA_READ:
+		case DMA_FROM_DEVICE:
 			orb_direction = ORB_DIRECTION_READ_FROM_MEDIA;
 			break;
-		case SCSI_DATA_UNKNOWN:
+		case DMA_BIDIRECTIONAL:
 		default:
 			SBP2_ERR("SCSI data transfer direction not specified. "
 				 "Update the SBP2 direction table in sbp2.h if "
 				 "necessary for your application");
-			print_command (scsi_cmd);
+			__scsi_print_command(scsi_cmd);
 			orb_direction = sbp2scsi_direction_table[*scsi_cmd];
 			break;
 	}
@@ -2031,7 +2037,8 @@
  * This function is called in order to begin a regular SBP-2 command.
  */
 static int sbp2_send_command(struct scsi_id_instance_data *scsi_id,
-			     Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
+			     struct scsi_cmnd *SCpnt,
+			     void (*done)(struct scsi_cmnd *))
 {
 	unchar *cmd = (unchar *) SCpnt->cmnd;
 	unsigned int request_bufflen = SCpnt->request_bufflen;
@@ -2040,7 +2047,7 @@
 	SBP2_DEBUG("sbp2_send_command");
 #if (CONFIG_IEEE1394_SBP2_DEBUG >= 2) || defined(CONFIG_IEEE1394_SBP2_PACKET_DUMP)
 	printk("[scsi command]\n   ");
-	print_command (cmd);
+	scsi_print_command(SCpnt);
 #endif
 	SBP2_DEBUG("SCSI transfer size = %x", request_bufflen);
 	SBP2_DEBUG("SCSI s/g elements = %x", (unsigned int)SCpnt->use_sg);
@@ -2233,7 +2240,7 @@
  * response data translations for the SCSI stack
  */
 static void sbp2_check_sbp2_response(struct scsi_id_instance_data *scsi_id, 
-				     Scsi_Cmnd *SCpnt)
+				     struct scsi_cmnd *SCpnt)
 {
 	u8 *scsi_buf = SCpnt->request_buffer;
 	u8 device_type = SBP2_DEVICE_TYPE (scsi_id->sbp2_device_type_and_lun);
@@ -2312,7 +2319,7 @@
 	struct sbp2scsi_host_info *hi;
 	struct scsi_id_instance_data *scsi_id = NULL, *scsi_id_tmp;
 	u32 id;
-	Scsi_Cmnd *SCpnt = NULL;
+	struct scsi_cmnd *SCpnt = NULL;
 	u32 scsi_status = SBP2_SCSI_STATUS_GOOD;
 	struct sbp2_command_info *command;
 
@@ -2454,7 +2461,8 @@
  * This routine is the main request entry routine for doing I/O. It is
  * called from the scsi stack directly.
  */
-static int sbp2scsi_queuecommand (Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
+static int sbp2scsi_queuecommand(struct scsi_cmnd *SCpnt,
+				 void (*done)(struct scsi_cmnd *))
 {
 	struct scsi_id_instance_data *scsi_id =
 		(struct scsi_id_instance_data *)SCpnt->device->host->hostdata[0];
@@ -2550,9 +2558,8 @@
 					    PCI_DMA_BIDIRECTIONAL);
 		sbp2util_mark_command_completed(scsi_id, command);
 		if (command->Current_SCpnt) {
-			void (*done)(Scsi_Cmnd *) = command->Current_done;
 			command->Current_SCpnt->result = status << 16;
-			done (command->Current_SCpnt);
+			command->Current_done(command->Current_SCpnt);
 		}
 	}
 
@@ -2565,8 +2572,8 @@
  * This can be called in interrupt context.
  */
 static void sbp2scsi_complete_command(struct scsi_id_instance_data *scsi_id,
-				      u32 scsi_status, Scsi_Cmnd *SCpnt,
-				      void (*done)(Scsi_Cmnd *))
+				      u32 scsi_status, struct scsi_cmnd *SCpnt,
+				      void (*done)(struct scsi_cmnd *))
 {
 	unsigned long flags;
 
@@ -2611,8 +2618,8 @@
 			 * Debug stuff
 			 */
 #if CONFIG_IEEE1394_SBP2_DEBUG >= 1
-			print_command (SCpnt->cmnd);
-			print_sense("bh", SCpnt);
+			scsi_print_command(SCpnt);
+			scsi_print_sense("bh", SCpnt);
 #endif
 
 			break;
@@ -2620,7 +2627,7 @@
 		case SBP2_SCSI_STATUS_SELECTION_TIMEOUT:
 			SBP2_ERR("SBP2_SCSI_STATUS_SELECTION_TIMEOUT");
 			SCpnt->result = DID_NO_CONNECT << 16;
-			print_command (SCpnt->cmnd);
+			scsi_print_command(SCpnt);
 			break;
 
 		case SBP2_SCSI_STATUS_CONDITION_MET:
@@ -2628,7 +2635,7 @@
 		case SBP2_SCSI_STATUS_COMMAND_TERMINATED:
 			SBP2_ERR("Bad SCSI status = %x", scsi_status);
 			SCpnt->result = DID_ERROR << 16;
-			print_command (SCpnt->cmnd);
+			scsi_print_command(SCpnt);
 			break;
 
 		default:
@@ -2688,7 +2695,7 @@
  * Called by scsi stack when something has really gone wrong.  Usually
  * called when a command has timed-out for some reason.
  */
-static int sbp2scsi_abort (Scsi_Cmnd *SCpnt)
+static int sbp2scsi_abort(struct scsi_cmnd *SCpnt)
 {
 	struct scsi_id_instance_data *scsi_id =
 		(struct scsi_id_instance_data *)SCpnt->device->host->hostdata[0];
@@ -2696,7 +2703,7 @@
 	struct sbp2_command_info *command;
 
 	SBP2_ERR("aborting sbp2 command");
-	print_command (SCpnt->cmnd);
+	scsi_print_command(SCpnt);
 
 	if (scsi_id) {
 
@@ -2717,9 +2724,8 @@
 						    PCI_DMA_BIDIRECTIONAL);
 			sbp2util_mark_command_completed(scsi_id, command);
 			if (command->Current_SCpnt) {
-				void (*done)(Scsi_Cmnd *) = command->Current_done;
 				command->Current_SCpnt->result = DID_ABORT << 16;
-				done (command->Current_SCpnt);
+				command->Current_done(command->Current_SCpnt);
 			}
 		}
 
@@ -2736,7 +2742,7 @@
 /*
  * Called by scsi stack when something has really gone wrong.
  */
-static int sbp2scsi_reset (Scsi_Cmnd *SCpnt)
+static int sbp2scsi_reset(struct scsi_cmnd *SCpnt)
 {
 	struct scsi_id_instance_data *scsi_id =
 		(struct scsi_id_instance_data *)SCpnt->device->host->hostdata[0];
@@ -2789,7 +2795,7 @@
 MODULE_LICENSE("GPL");
 
 /* SCSI host template */
-static Scsi_Host_Template scsi_driver_template = {
+static struct scsi_host_template scsi_driver_template = {
 	.module =			THIS_MODULE,
 	.name =				"SBP-2 IEEE-1394",
 	.proc_name =			SBP2_DEVICE_NAME,
diff -Nru a/drivers/ieee1394/sbp2.h b/drivers/ieee1394/sbp2.h
--- a/drivers/ieee1394/sbp2.h	2005-03-11 12:51:41 -08:00
+++ b/drivers/ieee1394/sbp2.h	2005-03-11 12:51:41 -08:00
@@ -324,8 +324,8 @@
 	struct list_head list;
 	struct sbp2_command_orb command_orb ____cacheline_aligned;
 	dma_addr_t command_orb_dma ____cacheline_aligned;
-	Scsi_Cmnd *Current_SCpnt;
-	void (*Current_done)(Scsi_Cmnd *);
+	struct scsi_cmnd *Current_SCpnt;
+	void (*Current_done)(struct scsi_cmnd *);
 
 	/* Also need s/g structure for each sbp2 command */
 	struct sbp2_unrestricted_page_table scatter_gather_element[SG_ALL] ____cacheline_aligned;
@@ -434,8 +434,8 @@
 static struct sbp2_command_info *sbp2util_find_command_for_orb(struct scsi_id_instance_data *scsi_id, dma_addr_t orb);
 static struct sbp2_command_info *sbp2util_find_command_for_SCpnt(struct scsi_id_instance_data *scsi_id, void *SCpnt);
 static struct sbp2_command_info *sbp2util_allocate_command_orb(struct scsi_id_instance_data *scsi_id,
-							  Scsi_Cmnd *Current_SCpnt,
-							  void (*Current_done)(Scsi_Cmnd *));
+							  struct scsi_cmnd *Current_SCpnt,
+							  void (*Current_done)(struct scsi_cmnd *));
 static void sbp2util_mark_command_completed(struct scsi_id_instance_data *scsi_id,
 		struct sbp2_command_info *command);
 
@@ -466,14 +466,16 @@
 				   unsigned int scsi_use_sg,
 				   unsigned int scsi_request_bufflen,
 				   void *scsi_request_buffer,
-				   unsigned char scsi_dir);
+				   enum dma_data_direction dma_dir);
 static int sbp2_link_orb_command(struct scsi_id_instance_data *scsi_id,
 				 struct sbp2_command_info *command);
 static int sbp2_send_command(struct scsi_id_instance_data *scsi_id,
-			     Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *));
+			     struct scsi_cmnd *SCpnt,
+			     void (*done)(struct scsi_cmnd *));
 static unsigned int sbp2_status_to_sense_data(unchar *sbp2_status, unchar *sense_data);
 static void sbp2_check_sbp2_command(struct scsi_id_instance_data *scsi_id, unchar *cmd);
-static void sbp2_check_sbp2_response(struct scsi_id_instance_data *scsi_id, Scsi_Cmnd *SCpnt);
+static void sbp2_check_sbp2_response(struct scsi_id_instance_data *scsi_id,
+				     struct scsi_cmnd *SCpnt);
 static void sbp2_parse_unit_directory(struct scsi_id_instance_data *scsi_id,
 				      struct unit_directory *ud);
 static int sbp2_set_busy_timeout(struct scsi_id_instance_data *scsi_id);
diff -Nru a/drivers/ieee1394/video1394.c b/drivers/ieee1394/video1394.c
--- a/drivers/ieee1394/video1394.c	2005-03-11 12:51:41 -08:00
+++ b/drivers/ieee1394/video1394.c	2005-03-11 12:51:41 -08:00
@@ -16,14 +16,25 @@
  * 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.
+ *
+ * NOTES:
+ *
+ * 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.
+ * 
+ * ioctl return codes:
+ * EFAULT is only for invalid address for the argp
+ * EINVAL for out of range values
+ * EBUSY when trying to use an already used resource
+ * ESRCH when trying to free/stop a not used resource
+ * EAGAIN for resource allocation failure that could perhaps succeed later
+ * ENOTTY for unsupported ioctl request
+ *
  */
 
-/* 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>
@@ -146,8 +157,8 @@
 #define PRINT(level, card, fmt, args...) \
 printk(level "video1394_%d: " fmt "\n" , card , ## args)
 
-void wakeup_dma_ir_ctx(unsigned long l);
-void wakeup_dma_it_ctx(unsigned long l);
+static void wakeup_dma_ir_ctx(unsigned long l);
+static void wakeup_dma_it_ctx(unsigned long l);
 
 static struct hpsb_highlevel video1394_highlevel;
 
@@ -487,7 +498,7 @@
 	return NULL;
 }
 
-void wakeup_dma_ir_ctx(unsigned long l)
+static void wakeup_dma_ir_ctx(unsigned long l)
 {
 	struct dma_iso_ctx *d = (struct dma_iso_ctx *) l;
 	int i;
@@ -560,7 +571,7 @@
 #endif
 }
 
-void wakeup_dma_it_ctx(unsigned long l)
+static void wakeup_dma_it_ctx(unsigned long l)
 {
 	struct dma_iso_ctx *d = (struct dma_iso_ctx *) l;
 	struct ti_ohci *ohci = d->ohci;
@@ -723,7 +734,12 @@
 		/* if channel < 0, find lowest available one */
 		if (v.channel < 0) {
 		    mask = (u64)0x1;
-		    for (i=0; i<ISO_CHANNELS; i++) {
+		    for (i=0; ; i++) {
+			if (i == ISO_CHANNELS) {
+			    PRINT(KERN_ERR, ohci->host->id, 
+				  "No free channel found");
+			    return EAGAIN;
+			}
 			if (!(ohci->ISO_channel_usage & mask)) {
 			    v.channel = i;
 			    PRINT(KERN_INFO, ohci->host->id, "Found free channel %d", i);
@@ -731,42 +747,40 @@
 			}
 			mask = mask << 1;
 		    }
-		}
-
-		if (v.channel<0 || v.channel>(ISO_CHANNELS-1)) {
+		} else if (v.channel >= ISO_CHANNELS) {
 			PRINT(KERN_ERR, ohci->host->id,
 			      "Iso channel %d out of bounds", v.channel);
-			return -EFAULT;
+			return -EINVAL;
+		} else {
+			mask = (u64)0x1<<v.channel;
 		}
-		mask = (u64)0x1<<v.channel;
-		printk("mask: %08X%08X usage: %08X%08X\n",
-		       (u32)(mask>>32),(u32)(mask&0xffffffff),
-		       (u32)(ohci->ISO_channel_usage>>32),
-		       (u32)(ohci->ISO_channel_usage&0xffffffff));
+		PRINT(KERN_INFO, ohci->host->id, "mask: %08X%08X usage: %08X%08X\n",
+			(u32)(mask>>32),(u32)(mask&0xffffffff),
+			(u32)(ohci->ISO_channel_usage>>32),
+			(u32)(ohci->ISO_channel_usage&0xffffffff));
 		if (ohci->ISO_channel_usage & mask) {
 			PRINT(KERN_ERR, ohci->host->id,
 			      "Channel %d is already taken", v.channel);
-			return -EFAULT;
+			return -EBUSY;
 		}
-		ohci->ISO_channel_usage |= mask;
 
 		if (v.buf_size == 0 || v.buf_size > VIDEO1394_MAX_SIZE) {
 			PRINT(KERN_ERR, ohci->host->id,
 			      "Invalid %d length buffer requested",v.buf_size);
-			return -EFAULT;
+			return -EINVAL;
 		}
 
 		if (v.nb_buffers == 0 || v.nb_buffers > VIDEO1394_MAX_SIZE) {
 			PRINT(KERN_ERR, ohci->host->id,
 			      "Invalid %d buffers requested",v.nb_buffers);
-			return -EFAULT;
+			return -EINVAL;
 		}
 
 		if (v.nb_buffers * v.buf_size > VIDEO1394_MAX_SIZE) {
 			PRINT(KERN_ERR, ohci->host->id,
 			      "%d buffers of size %d bytes is too big",
 			      v.nb_buffers, v.buf_size);
-			return -EFAULT;
+			return -EINVAL;
 		}
 
 		if (cmd == VIDEO1394_IOC_LISTEN_CHANNEL) {
@@ -777,7 +791,7 @@
 			if (d == NULL) {
 				PRINT(KERN_ERR, ohci->host->id,
 				      "Couldn't allocate ir context");
-				return -EFAULT;
+				return -EAGAIN;
 			}
 			initialize_dma_ir_ctx(d, v.sync_tag, v.flags);
 
@@ -798,7 +812,7 @@
 			if (d == NULL) {
 				PRINT(KERN_ERR, ohci->host->id,
 				      "Couldn't allocate it context");
-				return -EFAULT;
+				return -EAGAIN;
 			}
 			initialize_dma_it_ctx(d, v.sync_tag,
 					      v.syt_offset, v.flags);
@@ -814,8 +828,12 @@
 			      v.channel);
 		}
 
-		if (copy_to_user(argp, &v, sizeof(v)))
+		if (copy_to_user((void *)arg, &v, sizeof(v))) {
+			/* FIXME : free allocated dma resources */
 			return -EFAULT;
+		}
+		
+		ohci->ISO_channel_usage |= mask;
 
 		return 0;
 	}
@@ -829,16 +847,16 @@
 		if (copy_from_user(&channel, argp, sizeof(int)))
 			return -EFAULT;
 
-		if (channel<0 || channel>(ISO_CHANNELS-1)) {
+		if (channel < 0 || channel >= ISO_CHANNELS) {
 			PRINT(KERN_ERR, ohci->host->id,
 			      "Iso channel %d out of bound", channel);
-			return -EFAULT;
+			return -EINVAL;
 		}
 		mask = (u64)0x1<<channel;
 		if (!(ohci->ISO_channel_usage & mask)) {
 			PRINT(KERN_ERR, ohci->host->id,
 			      "Channel %d is not being used", channel);
-			return -EFAULT;
+			return -ESRCH;
 		}
 
 		/* Mark this channel as unused */
@@ -849,7 +867,7 @@
 		else
 			d = find_ctx(&ctx->context_list, OHCI_ISO_TRANSMIT, channel);
 
-		if (d == NULL) return -EFAULT;
+		if (d == NULL) return -ESRCH;
 		PRINT(KERN_INFO, ohci->host->id, "Iso context %d "
 		      "stop talking on channel %d", d->ctx, channel);
 		free_dma_iso_ctx(d);
@@ -870,7 +888,7 @@
 		if ((v.buffer<0) || (v.buffer>d->num_desc)) {
 			PRINT(KERN_ERR, ohci->host->id,
 			      "Buffer %d out of range",v.buffer);
-			return -EFAULT;
+			return -EINVAL;
 		}
 
 		spin_lock_irqsave(&d->lock,flags);
@@ -879,7 +897,7 @@
 			PRINT(KERN_ERR, ohci->host->id,
 			      "Buffer %d is already used",v.buffer);
 			spin_unlock_irqrestore(&d->lock,flags);
-			return -EFAULT;
+			return -EBUSY;
 		}
 
 		d->buffer_status[v.buffer]=VIDEO1394_BUFFER_QUEUED;
@@ -933,7 +951,7 @@
 		if ((v.buffer<0) || (v.buffer>d->num_desc)) {
 			PRINT(KERN_ERR, ohci->host->id,
 			      "Buffer %d out of range",v.buffer);
-			return -EFAULT;
+			return -EINVAL;
 		}
 
 		/*
@@ -976,7 +994,7 @@
 			PRINT(KERN_ERR, ohci->host->id,
 			      "Buffer %d is not queued",v.buffer);
 			spin_unlock_irqrestore(&d->lock, flags);
-			return -EFAULT;
+			return -ESRCH;
 		}
 
 		/* set time of buffer */
@@ -1015,7 +1033,7 @@
 		if ((v.buffer<0) || (v.buffer>d->num_desc)) {
 			PRINT(KERN_ERR, ohci->host->id,
 			      "Buffer %d out of range",v.buffer);
-			return -EFAULT;
+			return -EINVAL;
 		}
 
 		if (d->flags & VIDEO1394_VARIABLE_PACKET_SIZE) {
@@ -1044,7 +1062,7 @@
 			spin_unlock_irqrestore(&d->lock,flags);
 			if (psizes)
 				kfree(psizes);
-			return -EFAULT;
+			return -EBUSY;
 		}
 
 		if (d->flags & VIDEO1394_VARIABLE_PACKET_SIZE) {
@@ -1118,7 +1136,7 @@
 		if ((v.buffer<0) || (v.buffer>d->num_desc)) {
 			PRINT(KERN_ERR, ohci->host->id,
 			      "Buffer %d out of range",v.buffer);
-			return -EFAULT;
+			return -EINVAL;
 		}
 
 		switch(d->buffer_status[v.buffer]) {
@@ -1144,11 +1162,11 @@
 		default:
 			PRINT(KERN_ERR, ohci->host->id,
 			      "Buffer %d is not queued",v.buffer);
-			return -EFAULT;
+			return -ESRCH;
 		}
 	}
 	default:
-		return -EINVAL;
+		return -ENOTTY;
 	}
 }
 
@@ -1170,7 +1188,7 @@
  *    But e.g. pte_alloc() does not work in modules ... :-(
  */
 
-int video1394_mmap(struct file *file, struct vm_area_struct *vma)
+static int video1394_mmap(struct file *file, struct vm_area_struct *vma)
 {
 	struct file_ctx *ctx = (struct file_ctx *)file->private_data;
 	int res = -EINVAL;
@@ -1269,6 +1287,16 @@
 		.specifier_id	= CAMERA_UNIT_SPEC_ID_ENTRY & 0xffffff,
 		.version	= CAMERA_SW_VERSION_ENTRY & 0xffffff
 	},
+        {
+                .match_flags    = IEEE1394_MATCH_SPECIFIER_ID | IEEE1394_MATCH_VERSION,
+                .specifier_id   = CAMERA_UNIT_SPEC_ID_ENTRY & 0xffffff,
+                .version        = (CAMERA_SW_VERSION_ENTRY + 1) & 0xffffff
+        },
+        {
+                .match_flags    = IEEE1394_MATCH_SPECIFIER_ID | IEEE1394_MATCH_VERSION,
+                .specifier_id   = CAMERA_UNIT_SPEC_ID_ENTRY & 0xffffff,
+                .version        = (CAMERA_SW_VERSION_ENTRY + 2) & 0xffffff
+        },
 	{ }
 };
 
@@ -1304,6 +1332,9 @@
 	hpsb_set_hostinfo_key(&video1394_highlevel, host, ohci->host->id);
 
 	minor = IEEE1394_MINOR_BLOCK_VIDEO1394 * 16 + ohci->host->id;
+	class_simple_device_add(hpsb_protocol_class, MKDEV(
+		IEEE1394_MAJOR,	minor), 
+		NULL, "%s-%d", VIDEO1394_DRIVER_NAME, ohci->host->id);
 	devfs_mk_cdev(MKDEV(IEEE1394_MAJOR, minor),
 		       S_IFCHR | S_IRUSR | S_IWUSR,
 		       "%s/%d", VIDEO1394_DRIVER_NAME, ohci->host->id);
@@ -1314,9 +1345,12 @@
 {
 	struct ti_ohci *ohci = hpsb_get_hostinfo(&video1394_highlevel, host);
 
-	if (ohci)
+	if (ohci) {
+		class_simple_device_remove(MKDEV(IEEE1394_MAJOR, 
+			IEEE1394_MINOR_BLOCK_VIDEO1394 * 16 + ohci->host->id));
 		devfs_remove("%s/%d", VIDEO1394_DRIVER_NAME, ohci->host->id);
-
+	}
+	
 	return;
 }
 
diff -Nru a/drivers/infiniband/core/agent.c b/drivers/infiniband/core/agent.c
--- a/drivers/infiniband/core/agent.c	2005-03-11 12:51:43 -08:00
+++ b/drivers/infiniband/core/agent.c	2005-03-11 12:51:43 -08:00
@@ -45,14 +45,11 @@
 #include "smi.h"
 #include "agent_priv.h"
 #include "mad_priv.h"
-
+#include "agent.h"
 
 spinlock_t ib_agent_port_list_lock;
 static LIST_HEAD(ib_agent_port_list);
 
-extern kmem_cache_t *ib_mad_cache;
-
-
 /*
  * Caller must hold ib_agent_port_list_lock
  */
@@ -66,14 +63,13 @@
 
 	if (device) {
 		list_for_each_entry(entry, &ib_agent_port_list, port_list) {
-			if (entry->dr_smp_agent->device == device &&
+			if (entry->smp_agent->device == device &&
 			    entry->port_num == port_num)
 				return entry;
 		}
 	} else {
 		list_for_each_entry(entry, &ib_agent_port_list, port_list) {
-			if ((entry->dr_smp_agent == mad_agent) ||
-			    (entry->lr_smp_agent == mad_agent) ||
+			if ((entry->smp_agent == mad_agent) ||
 			    (entry->perf_mgmt_agent == mad_agent))
 				return entry;
 		}
@@ -111,7 +107,7 @@
 		return 1;
 	}
 
-	return smi_check_local_smp(port_priv->dr_smp_agent, smp);
+	return smi_check_local_smp(port_priv->smp_agent, smp);
 }
 
 static int agent_mad_send(struct ib_mad_agent *mad_agent,
@@ -231,10 +227,8 @@
 	/* Get mad agent based on mgmt_class in MAD */
 	switch (mad->mad.mad.mad_hdr.mgmt_class) {
 		case IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE:
-			mad_agent = port_priv->dr_smp_agent;
-			break;
 		case IB_MGMT_CLASS_SUBN_LID_ROUTED:
-			mad_agent = port_priv->lr_smp_agent;
+			mad_agent = port_priv->smp_agent;
 			break;
 		case IB_MGMT_CLASS_PERF_MGMT:
 			mad_agent = port_priv->perf_mgmt_agent;
@@ -284,7 +278,6 @@
 {
 	int ret;
 	struct ib_agent_port_private *port_priv;
-	struct ib_mad_reg_req reg_req;
 	unsigned long flags;
 
 	/* First, check if port already open for SMI */
@@ -308,35 +301,19 @@
 	spin_lock_init(&port_priv->send_list_lock);
 	INIT_LIST_HEAD(&port_priv->send_posted_list);
 
-	/* Obtain MAD agent for directed route SM class */
-	reg_req.mgmt_class = IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE;
-	reg_req.mgmt_class_version = 1;
-
-	port_priv->dr_smp_agent = ib_register_mad_agent(device, port_num,
-							IB_QPT_SMI,
-							NULL, 0,
-						       &agent_send_handler,
-							NULL, NULL);
+	/* Obtain send only MAD agent for SM class (SMI QP) */
+	port_priv->smp_agent = ib_register_mad_agent(device, port_num,
+						     IB_QPT_SMI,
+						     NULL, 0,
+						    &agent_send_handler,
+						     NULL, NULL);
 
-	if (IS_ERR(port_priv->dr_smp_agent)) {
-		ret = PTR_ERR(port_priv->dr_smp_agent);
+	if (IS_ERR(port_priv->smp_agent)) {
+		ret = PTR_ERR(port_priv->smp_agent);
 		goto error2;
 	}
 
-	/* Obtain MAD agent for LID routed SM class */
-	reg_req.mgmt_class = IB_MGMT_CLASS_SUBN_LID_ROUTED;
-	port_priv->lr_smp_agent = ib_register_mad_agent(device, port_num,
-							IB_QPT_SMI,
-							NULL, 0,
-						       &agent_send_handler,
-							NULL, NULL);
-	if (IS_ERR(port_priv->lr_smp_agent)) {
-		ret = PTR_ERR(port_priv->lr_smp_agent);
-		goto error3;
-	}
-
-	/* Obtain MAD agent for PerfMgmt class */
-	reg_req.mgmt_class = IB_MGMT_CLASS_PERF_MGMT;
+	/* Obtain send only MAD agent for PerfMgmt class (GSI QP) */
 	port_priv->perf_mgmt_agent = ib_register_mad_agent(device, port_num,
 							   IB_QPT_GSI,
 							   NULL, 0,
@@ -344,15 +321,15 @@
 							   NULL, NULL);
 	if (IS_ERR(port_priv->perf_mgmt_agent)) {
 		ret = PTR_ERR(port_priv->perf_mgmt_agent);
-		goto error4;
+		goto error3;
 	}
 
-	port_priv->mr = ib_get_dma_mr(port_priv->dr_smp_agent->qp->pd,
+	port_priv->mr = ib_get_dma_mr(port_priv->smp_agent->qp->pd,
 				      IB_ACCESS_LOCAL_WRITE);
 	if (IS_ERR(port_priv->mr)) {
 		printk(KERN_ERR SPFX "Couldn't get DMA MR\n");
 		ret = PTR_ERR(port_priv->mr);
-		goto error5;
+		goto error4;
 	}
 
 	spin_lock_irqsave(&ib_agent_port_list_lock, flags);
@@ -361,12 +338,10 @@
 
 	return 0;
 
-error5:
-	ib_unregister_mad_agent(port_priv->perf_mgmt_agent);
 error4:
-	ib_unregister_mad_agent(port_priv->lr_smp_agent);
+	ib_unregister_mad_agent(port_priv->perf_mgmt_agent);
 error3:
-	ib_unregister_mad_agent(port_priv->dr_smp_agent);
+	ib_unregister_mad_agent(port_priv->smp_agent);
 error2:
 	kfree(port_priv);
 error1:
@@ -391,8 +366,7 @@
 	ib_dereg_mr(port_priv->mr);
 
 	ib_unregister_mad_agent(port_priv->perf_mgmt_agent);
-	ib_unregister_mad_agent(port_priv->lr_smp_agent);
-	ib_unregister_mad_agent(port_priv->dr_smp_agent);
+	ib_unregister_mad_agent(port_priv->smp_agent);
 	kfree(port_priv);
 
 	return 0;
diff -Nru a/drivers/infiniband/core/agent_priv.h b/drivers/infiniband/core/agent_priv.h
--- a/drivers/infiniband/core/agent_priv.h	2005-03-11 12:51:50 -08:00
+++ b/drivers/infiniband/core/agent_priv.h	2005-03-11 12:51:50 -08:00
@@ -55,8 +55,7 @@
 	struct list_head send_posted_list;
 	spinlock_t send_list_lock;
 	int port_num;
-	struct ib_mad_agent *dr_smp_agent;    /* DR SM class */
-	struct ib_mad_agent *lr_smp_agent;    /* LR SM class */
+	struct ib_mad_agent *smp_agent;	      /* SM class */
 	struct ib_mad_agent *perf_mgmt_agent; /* PerfMgmt class */
 	struct ib_mr *mr;
 };
diff -Nru a/drivers/infiniband/core/cache.c b/drivers/infiniband/core/cache.c
--- a/drivers/infiniband/core/cache.c	2005-03-11 12:51:46 -08:00
+++ b/drivers/infiniband/core/cache.c	2005-03-11 12:51:46 -08:00
@@ -37,6 +37,8 @@
 #include <linux/errno.h>
 #include <linux/slab.h>
 
+#include <ib_cache.h>
+
 #include "core_priv.h"
 
 struct ib_pkey_cache {
@@ -112,7 +114,7 @@
 		cache = device->cache.gid_cache[p];
 		for (i = 0; i < cache->table_len; ++i) {
 			if (!memcmp(gid, &cache->table[i], sizeof *gid)) {
-				*port_num = p;
+				*port_num = p + start_port(device);
 				if (index)
 					*index = i;
 				ret = 0;
diff -Nru a/drivers/infiniband/core/mad.c b/drivers/infiniband/core/mad.c
--- a/drivers/infiniband/core/mad.c	2005-03-11 12:51:51 -08:00
+++ b/drivers/infiniband/core/mad.c	2005-03-11 12:51:51 -08:00
@@ -41,7 +41,6 @@
 #include "smi.h"
 #include "agent.h"
 
-
 MODULE_LICENSE("Dual BSD/GPL");
 MODULE_DESCRIPTION("kernel IB MAD API");
 MODULE_AUTHOR("Hal Rosenstock");
@@ -69,6 +68,7 @@
 static void ib_mad_complete_send_wr(struct ib_mad_send_wr_private *mad_send_wr,
 				    struct ib_mad_send_wc *mad_send_wc);
 static void timeout_sends(void *data);
+static void cancel_sends(void *data);
 static void local_completions(void *data);
 static int solicited_mad(struct ib_mad *mad);
 static int add_nonoui_reg_req(struct ib_mad_reg_req *mad_reg_req,
@@ -342,6 +342,8 @@
 	INIT_LIST_HEAD(&mad_agent_priv->local_list);
 	INIT_WORK(&mad_agent_priv->local_work, local_completions,
 		   mad_agent_priv);
+	INIT_LIST_HEAD(&mad_agent_priv->canceled_list);
+	INIT_WORK(&mad_agent_priv->canceled_work, cancel_sends, mad_agent_priv);
 	atomic_set(&mad_agent_priv->refcount, 1);
 	init_waitqueue_head(&mad_agent_priv->wait);
 
@@ -490,6 +492,7 @@
 	cancel_mads(mad_agent_priv);
 
 	port_priv = mad_agent_priv->qp_info->port_priv;
+
 	cancel_delayed_work(&mad_agent_priv->timed_work);
 	flush_workqueue(port_priv->wq);
 
@@ -1266,12 +1269,12 @@
 	}
 
 	port_priv = agent_priv->qp_info->port_priv;
+	mgmt_class = convert_mgmt_class(agent_priv->reg_req->mgmt_class);
 	class = port_priv->version[
 			agent_priv->reg_req->mgmt_class_version].class;
 	if (!class)
 		goto vendor_check;
 
-	mgmt_class = convert_mgmt_class(agent_priv->reg_req->mgmt_class);
 	method = class->method_table[mgmt_class];
 	if (method) {
 		/* Remove any methods for this mad agent */
@@ -1293,16 +1296,21 @@
 	}
 
 vendor_check:
+	if (!is_vendor_class(mgmt_class))
+		goto out;
+
+	/* normalize mgmt_class to vendor range 2 */
+	mgmt_class = vendor_class_index(agent_priv->reg_req->mgmt_class);
 	vendor = port_priv->version[
 			agent_priv->reg_req->mgmt_class_version].vendor;
+
 	if (!vendor)
 		goto out;
 
-	mgmt_class = vendor_class_index(agent_priv->reg_req->mgmt_class);
 	vendor_class = vendor->vendor_class[mgmt_class];
 	if (vendor_class) {
 		index = find_vendor_oui(vendor_class, agent_priv->reg_req->oui);
-		if (index == -1)
+		if (index < 0)
 			goto out;
 		method = vendor_class->method_table[index];
 		if (method) {
@@ -1999,12 +2007,44 @@
 	return NULL;
 }
 
+void cancel_sends(void *data)
+{
+	struct ib_mad_agent_private *mad_agent_priv;
+	struct ib_mad_send_wr_private *mad_send_wr;
+	struct ib_mad_send_wc mad_send_wc;
+	unsigned long flags;
+
+	mad_agent_priv = data;
+
+	mad_send_wc.status = IB_WC_WR_FLUSH_ERR;
+	mad_send_wc.vendor_err = 0;
+
+	spin_lock_irqsave(&mad_agent_priv->lock, flags);
+	while (!list_empty(&mad_agent_priv->canceled_list)) {
+		mad_send_wr = list_entry(mad_agent_priv->canceled_list.next,
+					 struct ib_mad_send_wr_private,
+					 agent_list);
+
+		list_del(&mad_send_wr->agent_list);
+		spin_unlock_irqrestore(&mad_agent_priv->lock, flags);
+
+		mad_send_wc.wr_id = mad_send_wr->wr_id;
+		mad_agent_priv->agent.send_handler(&mad_agent_priv->agent,
+						   &mad_send_wc);
+
+		kfree(mad_send_wr);
+		if (atomic_dec_and_test(&mad_agent_priv->refcount))
+			wake_up(&mad_agent_priv->wait);
+		spin_lock_irqsave(&mad_agent_priv->lock, flags);
+	}
+	spin_unlock_irqrestore(&mad_agent_priv->lock, flags);
+}
+
 void ib_cancel_mad(struct ib_mad_agent *mad_agent,
 		  u64 wr_id)
 {
 	struct ib_mad_agent_private *mad_agent_priv;
 	struct ib_mad_send_wr_private *mad_send_wr;
-	struct ib_mad_send_wc mad_send_wc;
 	unsigned long flags;
 
 	mad_agent_priv = container_of(mad_agent, struct ib_mad_agent_private,
@@ -2026,19 +2066,12 @@
 	}
 
 	list_del(&mad_send_wr->agent_list);
+	list_add_tail(&mad_send_wr->agent_list, &mad_agent_priv->canceled_list);
 	adjust_timeout(mad_agent_priv);
 	spin_unlock_irqrestore(&mad_agent_priv->lock, flags);
 
-	mad_send_wc.status = IB_WC_WR_FLUSH_ERR;
-	mad_send_wc.vendor_err = 0;
-	mad_send_wc.wr_id = mad_send_wr->wr_id;
-	mad_agent_priv->agent.send_handler(&mad_agent_priv->agent,
-					   &mad_send_wc);
-
-	kfree(mad_send_wr);
-	if (atomic_dec_and_test(&mad_agent_priv->refcount))
-		wake_up(&mad_agent_priv->wait);
-
+	queue_work(mad_agent_priv->qp_info->port_priv->wq,
+		   &mad_agent_priv->canceled_work);
 out:
 	return;
 }
@@ -2186,7 +2219,6 @@
 	recv_wr.next = NULL;
 	recv_wr.sg_list = &sg_list;
 	recv_wr.num_sge = 1;
-	recv_wr.recv_flags = IB_RECV_SIGNALED;
 
 	do {
 		/* Allocate and map receive buffer */
@@ -2381,7 +2413,6 @@
 	qp_init_attr.send_cq = qp_info->port_priv->cq;
 	qp_init_attr.recv_cq = qp_info->port_priv->cq;
 	qp_init_attr.sq_sig_type = IB_SIGNAL_ALL_WR;
-	qp_init_attr.rq_sig_type = IB_SIGNAL_ALL_WR;
 	qp_init_attr.cap.max_send_wr = IB_MAD_QP_SEND_SIZE;
 	qp_init_attr.cap.max_recv_wr = IB_MAD_QP_RECV_SIZE;
 	qp_init_attr.cap.max_send_sge = IB_MAD_SEND_REQ_MAX_SG;
diff -Nru a/drivers/infiniband/core/mad_priv.h b/drivers/infiniband/core/mad_priv.h
--- a/drivers/infiniband/core/mad_priv.h	2005-03-11 12:51:52 -08:00
+++ b/drivers/infiniband/core/mad_priv.h	2005-03-11 12:51:52 -08:00
@@ -58,8 +58,8 @@
 #define MAX_MGMT_CLASS		80
 #define MAX_MGMT_VERSION	8
 #define MAX_MGMT_OUI		8
-#define MAX_MGMT_VENDOR_RANGE2	IB_MGMT_CLASS_VENDOR_RANGE2_END - \
-				IB_MGMT_CLASS_VENDOR_RANGE2_START + 1
+#define MAX_MGMT_VENDOR_RANGE2	(IB_MGMT_CLASS_VENDOR_RANGE2_END - \
+				IB_MGMT_CLASS_VENDOR_RANGE2_START + 1)
 
 struct ib_mad_list_head {
 	struct list_head list;
@@ -95,6 +95,8 @@
 	unsigned long timeout;
 	struct list_head local_list;
 	struct work_struct local_work;
+	struct list_head canceled_list;
+	struct work_struct canceled_work;
 
 	atomic_t refcount;
 	wait_queue_head_t wait;
@@ -191,5 +193,7 @@
 	struct work_struct work;
 	struct ib_mad_qp_info qp_info[IB_MAD_QPS_CORE];
 };
+
+extern kmem_cache_t *ib_mad_cache;
 
 #endif	/* __IB_MAD_PRIV_H__ */
diff -Nru a/drivers/infiniband/core/smi.c b/drivers/infiniband/core/smi.c
--- a/drivers/infiniband/core/smi.c	2005-03-11 12:51:47 -08:00
+++ b/drivers/infiniband/core/smi.c	2005-03-11 12:51:47 -08:00
@@ -37,7 +37,7 @@
  */
 
 #include <ib_smi.h>
-
+#include "smi.h"
 
 /*
  * Fixup a directed route SMP for sending
diff -Nru a/drivers/infiniband/hw/mthca/Makefile b/drivers/infiniband/hw/mthca/Makefile
--- a/drivers/infiniband/hw/mthca/Makefile	2005-03-11 12:51:47 -08:00
+++ b/drivers/infiniband/hw/mthca/Makefile	2005-03-11 12:51:47 -08:00
@@ -9,4 +9,4 @@
 ib_mthca-y :=	mthca_main.o mthca_cmd.o mthca_profile.o mthca_reset.o \
 		mthca_allocator.o mthca_eq.o mthca_pd.o mthca_cq.o \
 		mthca_mr.o mthca_qp.o mthca_av.o mthca_mcg.o mthca_mad.o \
-		mthca_provider.o mthca_memfree.o
+		mthca_provider.o mthca_memfree.o mthca_uar.o
diff -Nru a/drivers/infiniband/hw/mthca/mthca_av.c b/drivers/infiniband/hw/mthca/mthca_av.c
--- a/drivers/infiniband/hw/mthca/mthca_av.c	2005-03-11 12:51:51 -08:00
+++ b/drivers/infiniband/hw/mthca/mthca_av.c	2005-03-11 12:51:51 -08:00
@@ -60,27 +60,34 @@
 	u32 index = -1;
 	struct mthca_av *av = NULL;
 
-	ah->on_hca = 0;
+	ah->type = MTHCA_AH_PCI_POOL;
 
-	if (!atomic_read(&pd->sqp_count) &&
-	    !(dev->mthca_flags & MTHCA_FLAG_DDR_HIDDEN)) {
+	if (dev->hca_type == ARBEL_NATIVE) {
+		ah->av   = kmalloc(sizeof *ah->av, GFP_KERNEL);
+		if (!ah->av)
+			return -ENOMEM;
+
+		ah->type = MTHCA_AH_KMALLOC;
+		av       = ah->av;
+	} else if (!atomic_read(&pd->sqp_count) &&
+		 !(dev->mthca_flags & MTHCA_FLAG_DDR_HIDDEN)) {
 		index = mthca_alloc(&dev->av_table.alloc);
 
 		/* fall back to allocate in host memory */
 		if (index == -1)
-			goto host_alloc;
+			goto on_hca_fail;
 
 		av = kmalloc(sizeof *av, GFP_KERNEL);
 		if (!av)
-			goto host_alloc;
+			goto on_hca_fail;
 
-		ah->on_hca = 1;
+		ah->type = MTHCA_AH_ON_HCA;
 		ah->avdma  = dev->av_table.ddr_av_base +
 			index * MTHCA_AV_SIZE;
 	}
 
- host_alloc:
-	if (!ah->on_hca) {
+on_hca_fail:
+	if (ah->type == MTHCA_AH_PCI_POOL) {
 		ah->av = pci_pool_alloc(dev->av_table.pool,
 					SLAB_KERNEL, &ah->avdma);
 		if (!ah->av)
@@ -123,7 +130,7 @@
 			       j * 4, be32_to_cpu(((u32 *) av)[j]));
 	}
 
-	if (ah->on_hca) {
+	if (ah->type == MTHCA_AH_ON_HCA) {
 		memcpy_toio(dev->av_table.av_map + index * MTHCA_AV_SIZE,
 			    av, MTHCA_AV_SIZE);
 		kfree(av);
@@ -134,12 +141,21 @@
 
 int mthca_destroy_ah(struct mthca_dev *dev, struct mthca_ah *ah)
 {
-	if (ah->on_hca)
+	switch (ah->type) {
+	case MTHCA_AH_ON_HCA:
 		mthca_free(&dev->av_table.alloc,
  			   (ah->avdma - dev->av_table.ddr_av_base) /
 			   MTHCA_AV_SIZE);
-	else
+		break;
+
+	case MTHCA_AH_PCI_POOL:
 		pci_pool_free(dev->av_table.pool, ah->av, ah->avdma);
+		break;
+
+	case MTHCA_AH_KMALLOC:
+		kfree(ah->av);
+		break;
+	}
 
 	return 0;
 }
@@ -147,7 +163,7 @@
 int mthca_read_ah(struct mthca_dev *dev, struct mthca_ah *ah,
 		  struct ib_ud_header *header)
 {
-	if (ah->on_hca)
+	if (ah->type == MTHCA_AH_ON_HCA)
 		return -EINVAL;
 
 	header->lrh.service_level   = be32_to_cpu(ah->av->sl_tclass_flowlabel) >> 28;
@@ -176,6 +192,9 @@
 {
 	int err;
 
+	if (dev->hca_type == ARBEL_NATIVE)
+		return 0;
+
 	err = mthca_alloc_init(&dev->av_table.alloc,
 			       dev->av_table.num_ddr_avs,
 			       dev->av_table.num_ddr_avs - 1,
@@ -212,6 +231,9 @@
 
 void __devexit mthca_cleanup_av_table(struct mthca_dev *dev)
 {
+	if (dev->hca_type == ARBEL_NATIVE)
+		return;
+
 	if (dev->av_table.av_map)
 		iounmap(dev->av_table.av_map);
 	pci_pool_destroy(dev->av_table.pool);
diff -Nru a/drivers/infiniband/hw/mthca/mthca_cmd.c b/drivers/infiniband/hw/mthca/mthca_cmd.c
--- a/drivers/infiniband/hw/mthca/mthca_cmd.c	2005-03-11 12:51:50 -08:00
+++ b/drivers/infiniband/hw/mthca/mthca_cmd.c	2005-03-11 12:51:50 -08:00
@@ -1290,7 +1290,7 @@
 		return -ENOMEM;
 
 	inbox[0] = cpu_to_be64(virt);
-	inbox[1] = cpu_to_be64(dma_addr | (PAGE_SHIFT - 12));
+	inbox[1] = cpu_to_be64(dma_addr);
 
 	err = mthca_cmd(dev, indma, 1, 0, CMD_MAP_ICM, CMD_TIME_CLASS_B, status);
 
@@ -1305,6 +1305,9 @@
 
 int mthca_UNMAP_ICM(struct mthca_dev *dev, u64 virt, u32 page_count, u8 *status)
 {
+	mthca_dbg(dev, "Unmapping %d pages at %llx from ICM.\n",
+		  page_count, (unsigned long long) virt);
+
 	return mthca_cmd(dev, virt, page_count, 0, CMD_UNMAP_ICM, CMD_TIME_CLASS_B, status);
 }
 
@@ -1538,10 +1541,10 @@
 		if (0) {
 			int i;
 			mthca_dbg(dev, "Dumping QP context:\n");
-			printk(" %08x\n", be32_to_cpup(qp_context));
+			printk("  opt param mask: %08x\n", be32_to_cpup(qp_context));
 			for (i = 0; i < 0x100 / 4; ++i) {
 				if (i % 8 == 0)
-					printk("[%02x] ", i * 4);
+					printk("  [%02x] ", i * 4);
 				printk(" %08x", be32_to_cpu(((u32 *) qp_context)[i + 2]));
 				if ((i + 1) % 8 == 0)
 					printk("\n");
diff -Nru a/drivers/infiniband/hw/mthca/mthca_cmd.h b/drivers/infiniband/hw/mthca/mthca_cmd.h
--- a/drivers/infiniband/hw/mthca/mthca_cmd.h	2005-03-11 12:51:42 -08:00
+++ b/drivers/infiniband/hw/mthca/mthca_cmd.h	2005-03-11 12:51:42 -08:00
@@ -95,7 +95,21 @@
 };
 
 enum {
-	DEV_LIM_FLAG_SRQ = 1 << 6
+	DEV_LIM_FLAG_RC                 = 1 << 0,
+	DEV_LIM_FLAG_UC                 = 1 << 1,
+	DEV_LIM_FLAG_UD                 = 1 << 2,
+	DEV_LIM_FLAG_RD                 = 1 << 3,
+	DEV_LIM_FLAG_RAW_IPV6           = 1 << 4,
+	DEV_LIM_FLAG_RAW_ETHER          = 1 << 5,
+	DEV_LIM_FLAG_SRQ                = 1 << 6,
+	DEV_LIM_FLAG_BAD_PKEY_CNTR      = 1 << 8,
+	DEV_LIM_FLAG_BAD_QKEY_CNTR      = 1 << 9,
+	DEV_LIM_FLAG_MW                 = 1 << 16,
+	DEV_LIM_FLAG_AUTO_PATH_MIG      = 1 << 17,
+	DEV_LIM_FLAG_ATOMIC             = 1 << 18,
+	DEV_LIM_FLAG_RAW_MULTI          = 1 << 19,
+	DEV_LIM_FLAG_UD_AV_PORT_ENFORCE = 1 << 20,
+	DEV_LIM_FLAG_UD_MULTI           = 1 << 21,
 };
 
 struct mthca_dev_lim {
diff -Nru a/drivers/infiniband/hw/mthca/mthca_config_reg.h b/drivers/infiniband/hw/mthca/mthca_config_reg.h
--- a/drivers/infiniband/hw/mthca/mthca_config_reg.h	2005-03-11 12:51:46 -08:00
+++ b/drivers/infiniband/hw/mthca/mthca_config_reg.h	2005-03-11 12:51:46 -08:00
@@ -46,5 +46,6 @@
 #define MTHCA_MAP_ECR_SIZE     (MTHCA_ECR_SIZE + MTHCA_ECR_CLR_SIZE)
 #define MTHCA_CLR_INT_BASE     0xf00d8
 #define MTHCA_CLR_INT_SIZE     0x00008
+#define MTHCA_EQ_SET_CI_SIZE   (8 * 32)
 
 #endif /* MTHCA_CONFIG_REG_H */
diff -Nru a/drivers/infiniband/hw/mthca/mthca_cq.c b/drivers/infiniband/hw/mthca/mthca_cq.c
--- a/drivers/infiniband/hw/mthca/mthca_cq.c	2005-03-11 12:51:41 -08:00
+++ b/drivers/infiniband/hw/mthca/mthca_cq.c	2005-03-11 12:51:41 -08:00
@@ -33,11 +33,13 @@
  */
 
 #include <linux/init.h>
+#include <linux/hardirq.h>
 
 #include <ib_pack.h>
 
 #include "mthca_dev.h"
 #include "mthca_cmd.h"
+#include "mthca_memfree.h"
 
 enum {
 	MTHCA_MAX_DIRECT_CQ_SIZE = 4 * PAGE_SIZE
@@ -54,7 +56,7 @@
 	u32 flags;
 	u64 start;
 	u32 logsize_usrpage;
-	u32 error_eqn;
+	u32 error_eqn;		/* Tavor only */
 	u32 comp_eqn;
 	u32 pd;
 	u32 lkey;
@@ -63,7 +65,9 @@
 	u32 consumer_index;
 	u32 producer_index;
 	u32 cqn;
-	u32 reserved[3];
+	u32 ci_db;		/* Arbel only */
+	u32 state_db;		/* Arbel only */
+	u32 reserved;
 } __attribute__((packed));
 
 #define MTHCA_CQ_STATUS_OK          ( 0 << 28)
@@ -132,11 +136,15 @@
 #define MTHCA_CQ_ENTRY_OWNER_SW      (0 << 7)
 #define MTHCA_CQ_ENTRY_OWNER_HW      (1 << 7)
 
-#define MTHCA_CQ_DB_INC_CI       (1 << 24)
-#define MTHCA_CQ_DB_REQ_NOT      (2 << 24)
-#define MTHCA_CQ_DB_REQ_NOT_SOL  (3 << 24)
-#define MTHCA_CQ_DB_SET_CI       (4 << 24)
-#define MTHCA_CQ_DB_REQ_NOT_MULT (5 << 24)
+#define MTHCA_TAVOR_CQ_DB_INC_CI       (1 << 24)
+#define MTHCA_TAVOR_CQ_DB_REQ_NOT      (2 << 24)
+#define MTHCA_TAVOR_CQ_DB_REQ_NOT_SOL  (3 << 24)
+#define MTHCA_TAVOR_CQ_DB_SET_CI       (4 << 24)
+#define MTHCA_TAVOR_CQ_DB_REQ_NOT_MULT (5 << 24)
+
+#define MTHCA_ARBEL_CQ_DB_REQ_NOT_SOL  (1 << 24)
+#define MTHCA_ARBEL_CQ_DB_REQ_NOT      (2 << 24)
+#define MTHCA_ARBEL_CQ_DB_REQ_NOT_MULT (3 << 24)
 
 static inline struct mthca_cqe *get_cqe(struct mthca_cq *cq, int entry)
 {
@@ -147,54 +155,58 @@
 			+ (entry * MTHCA_CQ_ENTRY_SIZE) % PAGE_SIZE;
 }
 
-static inline int cqe_sw(struct mthca_cq *cq, int i)
+static inline struct mthca_cqe *cqe_sw(struct mthca_cq *cq, int i)
 {
-	return !(MTHCA_CQ_ENTRY_OWNER_HW &
-		 get_cqe(cq, i)->owner);
+	struct mthca_cqe *cqe = get_cqe(cq, i);
+	return MTHCA_CQ_ENTRY_OWNER_HW & cqe->owner ? NULL : cqe;
 }
 
-static inline int next_cqe_sw(struct mthca_cq *cq)
+static inline struct mthca_cqe *next_cqe_sw(struct mthca_cq *cq)
 {
-	return cqe_sw(cq, cq->cons_index);
+	return cqe_sw(cq, cq->cons_index & cq->ibcq.cqe);
 }
 
-static inline void set_cqe_hw(struct mthca_cq *cq, int entry)
+static inline void set_cqe_hw(struct mthca_cqe *cqe)
 {
-	get_cqe(cq, entry)->owner = MTHCA_CQ_ENTRY_OWNER_HW;
+	cqe->owner = MTHCA_CQ_ENTRY_OWNER_HW;
 }
 
-static inline void inc_cons_index(struct mthca_dev *dev, struct mthca_cq *cq,
-				  int nent)
+/*
+ * incr is ignored in native Arbel (mem-free) mode, so cq->cons_index
+ * should be correct before calling update_cons_index().
+ */
+static inline void update_cons_index(struct mthca_dev *dev, struct mthca_cq *cq,
+				     int incr)
 {
 	u32 doorbell[2];
 
-	doorbell[0] = cpu_to_be32(MTHCA_CQ_DB_INC_CI | cq->cqn);
-	doorbell[1] = cpu_to_be32(nent - 1);
+	if (dev->hca_type == ARBEL_NATIVE) {
+		*cq->set_ci_db = cpu_to_be32(cq->cons_index);
+		wmb();
+	} else {
+		doorbell[0] = cpu_to_be32(MTHCA_TAVOR_CQ_DB_INC_CI | cq->cqn);
+		doorbell[1] = cpu_to_be32(incr - 1);
 
-	mthca_write64(doorbell,
-		      dev->kar + MTHCA_CQ_DOORBELL,
-		      MTHCA_GET_DOORBELL_LOCK(&dev->doorbell_lock));
+		mthca_write64(doorbell,
+			      dev->kar + MTHCA_CQ_DOORBELL,
+			      MTHCA_GET_DOORBELL_LOCK(&dev->doorbell_lock));
+	}
 }
 
 void mthca_cq_event(struct mthca_dev *dev, u32 cqn)
 {
 	struct mthca_cq *cq;
 
-	spin_lock(&dev->cq_table.lock);
 	cq = mthca_array_get(&dev->cq_table.cq, cqn & (dev->limits.num_cqs - 1));
-	if (cq)
-		atomic_inc(&cq->refcount);
-	spin_unlock(&dev->cq_table.lock);
 
 	if (!cq) {
 		mthca_warn(dev, "Completion event for bogus CQ %08x\n", cqn);
 		return;
 	}
 
-	cq->ibcq.comp_handler(&cq->ibcq, cq->ibcq.cq_context);
+	++cq->arm_sn;
 
-	if (atomic_dec_and_test(&cq->refcount))
-		wake_up(&cq->wait);
+	cq->ibcq.comp_handler(&cq->ibcq, cq->ibcq.cq_context);
 }
 
 void mthca_cq_clean(struct mthca_dev *dev, u32 cqn, u32 qpn)
@@ -250,8 +262,8 @@
 
 	if (nfreed) {
 		wmb();
-		inc_cons_index(dev, cq, nfreed);
-		cq->cons_index = (cq->cons_index + nfreed) & cq->ibcq.cqe;
+		cq->cons_index += nfreed;
+		update_cons_index(dev, cq, nfreed);
 	}
 
 	spin_unlock_irq(&cq->lock);
@@ -344,7 +356,7 @@
 		break;
 	}
 
-	err = mthca_free_err_wqe(qp, is_send, wqe_index, &dbd, &new_wqe);
+	err = mthca_free_err_wqe(dev, qp, is_send, wqe_index, &dbd, &new_wqe);
 	if (err)
 		return err;
 
@@ -383,12 +395,13 @@
 	struct mthca_wq *wq;
 	struct mthca_cqe *cqe;
 	int wqe_index;
-	int is_error = 0;
+	int is_error;
 	int is_send;
 	int free_cqe = 1;
 	int err = 0;
 
-	if (!next_cqe_sw(cq))
+	cqe = next_cqe_sw(cq);
+	if (!cqe)
 		return -EAGAIN;
 
 	/*
@@ -397,8 +410,6 @@
 	 */
 	rmb();
 
-	cqe = get_cqe(cq, cq->cons_index);
-
 	if (0) {
 		mthca_dbg(dev, "%x/%d: CQE -> QPN %06x, WQE @ %08x\n",
 			  cq->cqn, cq->cons_index, be32_to_cpu(cqe->my_qpn),
@@ -407,39 +418,25 @@
 		dump_cqe(cqe);
 	}
 
-	if ((cqe->opcode & MTHCA_ERROR_CQE_OPCODE_MASK) ==
-	    MTHCA_ERROR_CQE_OPCODE_MASK) {
-		is_error = 1;
-		is_send = cqe->opcode & 1;
-	} else
-		is_send = cqe->is_send & 0x80;
+	is_error = (cqe->opcode & MTHCA_ERROR_CQE_OPCODE_MASK) ==
+		MTHCA_ERROR_CQE_OPCODE_MASK;
+	is_send  = is_error ? cqe->opcode & 0x01 : cqe->is_send & 0x80;
 
 	if (!*cur_qp || be32_to_cpu(cqe->my_qpn) != (*cur_qp)->qpn) {
-		if (*cur_qp) {
-			if (*freed) {
-				wmb();
-				inc_cons_index(dev, cq, *freed);
-				*freed = 0;
-			}
-			spin_unlock(&(*cur_qp)->lock);
-		}
-
-		spin_lock(&dev->qp_table.lock);
+		/*
+		 * We do not have to take the QP table lock here,
+		 * because CQs will be locked while QPs are removed
+		 * from the table.
+		 */
 		*cur_qp = mthca_array_get(&dev->qp_table.qp,
 					  be32_to_cpu(cqe->my_qpn) &
 					  (dev->limits.num_qps - 1));
-		if (*cur_qp)
-			atomic_inc(&(*cur_qp)->refcount);
-		spin_unlock(&dev->qp_table.lock);
-
 		if (!*cur_qp) {
 			mthca_warn(dev, "CQ entry for unknown QP %06x\n",
 				   be32_to_cpu(cqe->my_qpn) & 0xffffff);
 			err = -EINVAL;
 			goto out;
 		}
-
-		spin_lock(&(*cur_qp)->lock);
 	}
 
 	entry->qp_num = (*cur_qp)->qpn;
@@ -457,9 +454,9 @@
 	}
 
 	if (wq->last_comp < wqe_index)
-		wq->cur -= wqe_index - wq->last_comp;
+		wq->tail += wqe_index - wq->last_comp;
 	else
-		wq->cur -= wq->max - wq->last_comp + wqe_index;
+		wq->tail += wqe_index + wq->max - wq->last_comp;
 
 	wq->last_comp = wqe_index;
 
@@ -509,10 +506,10 @@
 	entry->status = IB_WC_SUCCESS;
 
  out:
-	if (free_cqe) {
-		set_cqe_hw(cq, cq->cons_index);
+	if (likely(free_cqe)) {
+		set_cqe_hw(cqe);
 		++(*freed);
-		cq->cons_index = (cq->cons_index + 1) & cq->ibcq.cqe;
+		++cq->cons_index;
 	}
 
 	return err;
@@ -540,63 +537,101 @@
 
 	if (freed) {
 		wmb();
-		inc_cons_index(dev, cq, freed);
+		update_cons_index(dev, cq, freed);
 	}
 
-	if (qp) {
-		spin_unlock(&qp->lock);
-		if (atomic_dec_and_test(&qp->refcount))
-			wake_up(&qp->wait);
-	}
-
-
 	spin_unlock_irqrestore(&cq->lock, flags);
 
 	return err == 0 || err == -EAGAIN ? npolled : err;
 }
 
-void mthca_arm_cq(struct mthca_dev *dev, struct mthca_cq *cq,
-		  int solicited)
+int mthca_tavor_arm_cq(struct ib_cq *cq, enum ib_cq_notify notify)
 {
 	u32 doorbell[2];
 
-	doorbell[0] =  cpu_to_be32((solicited ?
-				    MTHCA_CQ_DB_REQ_NOT_SOL :
-				    MTHCA_CQ_DB_REQ_NOT)      |
-				   cq->cqn);
+	doorbell[0] = cpu_to_be32((notify == IB_CQ_SOLICITED ?
+				   MTHCA_TAVOR_CQ_DB_REQ_NOT_SOL :
+				   MTHCA_TAVOR_CQ_DB_REQ_NOT)      |
+				  to_mcq(cq)->cqn);
 	doorbell[1] = 0xffffffff;
 
 	mthca_write64(doorbell,
-		      dev->kar + MTHCA_CQ_DOORBELL,
-		      MTHCA_GET_DOORBELL_LOCK(&dev->doorbell_lock));
+		      to_mdev(cq->device)->kar + MTHCA_CQ_DOORBELL,
+		      MTHCA_GET_DOORBELL_LOCK(&to_mdev(cq->device)->doorbell_lock));
+
+	return 0;
 }
 
-int mthca_init_cq(struct mthca_dev *dev, int nent,
-		  struct mthca_cq *cq)
+int mthca_arbel_arm_cq(struct ib_cq *ibcq, enum ib_cq_notify notify)
+{
+	struct mthca_cq *cq = to_mcq(ibcq);
+	u32 doorbell[2];
+	u32 sn;
+	u32 ci;
+
+	sn = cq->arm_sn & 3;
+	ci = cpu_to_be32(cq->cons_index);
+
+	doorbell[0] = ci;
+	doorbell[1] = cpu_to_be32((cq->cqn << 8) | (2 << 5) | (sn << 3) |
+				  (notify == IB_CQ_SOLICITED ? 1 : 2));
+
+	mthca_write_db_rec(doorbell, cq->arm_db);
+
+	/*
+	 * Make sure that the doorbell record in host memory is
+	 * written before ringing the doorbell via PCI MMIO.
+	 */
+	wmb();
+
+	doorbell[0] = cpu_to_be32((sn << 28)                       |
+				  (notify == IB_CQ_SOLICITED ?
+				   MTHCA_ARBEL_CQ_DB_REQ_NOT_SOL :
+				   MTHCA_ARBEL_CQ_DB_REQ_NOT)      |
+				  cq->cqn);
+	doorbell[1] = ci;
+
+	mthca_write64(doorbell,
+		      to_mdev(ibcq->device)->kar + MTHCA_CQ_DOORBELL,
+		      MTHCA_GET_DOORBELL_LOCK(&to_mdev(ibcq->device)->doorbell_lock));
+
+	return 0;
+}
+
+static void mthca_free_cq_buf(struct mthca_dev *dev, struct mthca_cq *cq)
 {
-	int size = nent * MTHCA_CQ_ENTRY_SIZE;
-	dma_addr_t t;
-	void *mailbox = NULL;
-	int npages, shift;
-	u64 *dma_list = NULL;
-	struct mthca_cq_context *cq_context;
-	int err = -ENOMEM;
-	u8 status;
 	int i;
+	int size;
 
-	might_sleep();
+	if (cq->is_direct)
+		pci_free_consistent(dev->pdev,
+				    (cq->ibcq.cqe + 1) * MTHCA_CQ_ENTRY_SIZE,
+				    cq->queue.direct.buf,
+				    pci_unmap_addr(&cq->queue.direct,
+						   mapping));
+	else {
+		size = (cq->ibcq.cqe + 1) * MTHCA_CQ_ENTRY_SIZE;
+		for (i = 0; i < (size + PAGE_SIZE - 1) / PAGE_SIZE; ++i)
+			if (cq->queue.page_list[i].buf)
+				pci_free_consistent(dev->pdev, PAGE_SIZE,
+						    cq->queue.page_list[i].buf,
+						    pci_unmap_addr(&cq->queue.page_list[i],
+								   mapping));
 
-	mailbox = kmalloc(sizeof (struct mthca_cq_context) + MTHCA_CMD_MAILBOX_EXTRA,
-			  GFP_KERNEL);
-	if (!mailbox)
-		goto err_out;
+		kfree(cq->queue.page_list);
+	}
+}
 
-	cq_context = MAILBOX_ALIGN(mailbox);
+static int mthca_alloc_cq_buf(struct mthca_dev *dev, int size,
+			      struct mthca_cq *cq)
+{
+	int err = -ENOMEM;
+	int npages, shift;
+	u64 *dma_list = NULL;
+	dma_addr_t t;
+	int i;
 
 	if (size <= MTHCA_MAX_DIRECT_CQ_SIZE) {
-		if (0)
-			mthca_dbg(dev, "Creating direct CQ of size %d\n", size);
-
 		cq->is_direct = 1;
 		npages        = 1;
 		shift         = get_order(size) + PAGE_SHIFT;
@@ -604,7 +639,7 @@
 		cq->queue.direct.buf = pci_alloc_consistent(dev->pdev,
 							    size, &t);
 		if (!cq->queue.direct.buf)
-			goto err_out;
+			return -ENOMEM;
 
 		pci_unmap_addr_set(&cq->queue.direct, mapping, t);
 
@@ -617,7 +652,7 @@
 
 		dma_list = kmalloc(npages * sizeof *dma_list, GFP_KERNEL);
 		if (!dma_list)
-			goto err_out_free;
+			goto err_free;
 
 		for (i = 0; i < npages; ++i)
 			dma_list[i] = t + i * (1 << shift);
@@ -626,12 +661,9 @@
 		npages        = (size + PAGE_SIZE - 1) / PAGE_SIZE;
 		shift         = PAGE_SHIFT;
 
-		if (0)
-			mthca_dbg(dev, "Creating indirect CQ with %d pages\n", npages);
-
 		dma_list = kmalloc(npages * sizeof *dma_list, GFP_KERNEL);
 		if (!dma_list)
-			goto err_out;
+			return -ENOMEM;
 
 		cq->queue.page_list = kmalloc(npages * sizeof *cq->queue.page_list,
 					      GFP_KERNEL);
@@ -645,7 +677,7 @@
 			cq->queue.page_list[i].buf =
 				pci_alloc_consistent(dev->pdev, PAGE_SIZE, &t);
 			if (!cq->queue.page_list[i].buf)
-				goto err_out_free;
+				goto err_free;
 
 			dma_list[i] = t;
 			pci_unmap_addr_set(&cq->queue.page_list[i], mapping, t);
@@ -654,13 +686,6 @@
 		}
 	}
 
-	for (i = 0; i < nent; ++i)
-		set_cqe_hw(cq, i);
-
-	cq->cqn = mthca_alloc(&dev->cq_table.alloc);
-	if (cq->cqn == -1)
-		goto err_out_free;
-
 	err = mthca_mr_alloc_phys(dev, dev->driver_pd.pd_num,
 				  dma_list, shift, npages,
 				  0, size,
@@ -668,7 +693,72 @@
 				  MTHCA_MPT_FLAG_LOCAL_READ,
 				  &cq->mr);
 	if (err)
-		goto err_out_free_cq;
+		goto err_free;
+
+	kfree(dma_list);
+
+	return 0;
+
+err_free:
+	mthca_free_cq_buf(dev, cq);
+
+err_out:
+	kfree(dma_list);
+
+	return err;
+}
+
+int mthca_init_cq(struct mthca_dev *dev, int nent,
+		  struct mthca_cq *cq)
+{
+	int size = nent * MTHCA_CQ_ENTRY_SIZE;
+	void *mailbox = NULL;
+	struct mthca_cq_context *cq_context;
+	int err = -ENOMEM;
+	u8 status;
+	int i;
+
+	might_sleep();
+
+	cq->ibcq.cqe = nent - 1;
+
+	cq->cqn = mthca_alloc(&dev->cq_table.alloc);
+	if (cq->cqn == -1)
+		return -ENOMEM;
+
+	if (dev->hca_type == ARBEL_NATIVE) {
+		cq->arm_sn = 1;
+
+		err = mthca_table_get(dev, dev->cq_table.table, cq->cqn);
+		if (err)
+			goto err_out;
+
+		err = -ENOMEM;
+
+		cq->set_ci_db_index = mthca_alloc_db(dev, MTHCA_DB_TYPE_CQ_SET_CI,
+						     cq->cqn, &cq->set_ci_db);
+		if (cq->set_ci_db_index < 0)
+			goto err_out_icm;
+
+		cq->arm_db_index = mthca_alloc_db(dev, MTHCA_DB_TYPE_CQ_ARM,
+						  cq->cqn, &cq->arm_db);
+		if (cq->arm_db_index < 0)
+			goto err_out_ci;
+	}
+
+	mailbox = kmalloc(sizeof (struct mthca_cq_context) + MTHCA_CMD_MAILBOX_EXTRA,
+			  GFP_KERNEL);
+	if (!mailbox)
+		goto err_out_mailbox;
+
+	cq_context = MAILBOX_ALIGN(mailbox);
+
+	err = mthca_alloc_cq_buf(dev, size, cq);
+	if (err)
+		goto err_out_mailbox;
+
+	for (i = 0; i < nent; ++i)
+		set_cqe_hw(get_cqe(cq, i));
 
 	spin_lock_init(&cq->lock);
 	atomic_set(&cq->refcount, 1);
@@ -680,13 +770,18 @@
 						  MTHCA_CQ_FLAG_TR);
 	cq_context->start           = cpu_to_be64(0);
 	cq_context->logsize_usrpage = cpu_to_be32((ffs(nent) - 1) << 24 |
-						  MTHCA_KAR_PAGE);
+						  dev->driver_uar.index);
 	cq_context->error_eqn       = cpu_to_be32(dev->eq_table.eq[MTHCA_EQ_ASYNC].eqn);
 	cq_context->comp_eqn        = cpu_to_be32(dev->eq_table.eq[MTHCA_EQ_COMP].eqn);
 	cq_context->pd              = cpu_to_be32(dev->driver_pd.pd_num);
 	cq_context->lkey            = cpu_to_be32(cq->mr.ibmr.lkey);
 	cq_context->cqn             = cpu_to_be32(cq->cqn);
 
+	if (dev->hca_type == ARBEL_NATIVE) {
+		cq_context->ci_db    = cpu_to_be32(cq->set_ci_db_index);
+		cq_context->state_db = cpu_to_be32(cq->arm_db_index);
+	}
+
 	err = mthca_SW2HW_CQ(dev, cq_context, cq->cqn, &status);
 	if (err) {
 		mthca_warn(dev, "SW2HW_CQ failed (%d)\n", err);
@@ -711,36 +806,27 @@
 
 	cq->cons_index = 0;
 
-	kfree(dma_list);
 	kfree(mailbox);
 
 	return 0;
 
- err_out_free_mr:
+err_out_free_mr:
 	mthca_free_mr(dev, &cq->mr);
+	mthca_free_cq_buf(dev, cq);
 
- err_out_free_cq:
-	mthca_free(&dev->cq_table.alloc, cq->cqn);
+err_out_mailbox:
+	kfree(mailbox);
 
- err_out_free:
-	if (cq->is_direct)
-		pci_free_consistent(dev->pdev, size,
-				    cq->queue.direct.buf,
-				    pci_unmap_addr(&cq->queue.direct, mapping));
-	else {
-		for (i = 0; i < npages; ++i)
-			if (cq->queue.page_list[i].buf)
-				pci_free_consistent(dev->pdev, PAGE_SIZE,
-						    cq->queue.page_list[i].buf,
-						    pci_unmap_addr(&cq->queue.page_list[i],
-								   mapping));
+	mthca_free_db(dev, MTHCA_DB_TYPE_CQ_ARM, cq->arm_db_index);
 
-		kfree(cq->queue.page_list);
-	}
+err_out_ci:
+	mthca_free_db(dev, MTHCA_DB_TYPE_CQ_SET_CI, cq->set_ci_db_index);
 
- err_out:
-	kfree(dma_list);
-	kfree(mailbox);
+err_out_icm:
+	mthca_table_put(dev, dev->cq_table.table, cq->cqn);
+
+err_out:
+	mthca_free(&dev->cq_table.alloc, cq->cqn);
 
 	return err;
 }
@@ -773,7 +859,7 @@
 		int j;
 
 		printk(KERN_ERR "context for CQN %x (cons index %x, next sw %d)\n",
-		       cq->cqn, cq->cons_index, next_cqe_sw(cq));
+		       cq->cqn, cq->cons_index, !!next_cqe_sw(cq));
 		for (j = 0; j < 16; ++j)
 			printk(KERN_ERR "[%2x] %08x\n", j * 4, be32_to_cpu(ctx[j]));
 	}
@@ -783,30 +869,21 @@
 			  cq->cqn & (dev->limits.num_cqs - 1));
 	spin_unlock_irq(&dev->cq_table.lock);
 
+	if (dev->mthca_flags & MTHCA_FLAG_MSI_X)
+		synchronize_irq(dev->eq_table.eq[MTHCA_EQ_COMP].msi_x_vector);
+	else
+		synchronize_irq(dev->pdev->irq);
+
 	atomic_dec(&cq->refcount);
 	wait_event(cq->wait, !atomic_read(&cq->refcount));
 
 	mthca_free_mr(dev, &cq->mr);
+	mthca_free_cq_buf(dev, cq);
 
-	if (cq->is_direct)
-		pci_free_consistent(dev->pdev,
-				    (cq->ibcq.cqe + 1) * MTHCA_CQ_ENTRY_SIZE,
-				    cq->queue.direct.buf,
-				    pci_unmap_addr(&cq->queue.direct,
-						   mapping));
-	else {
-		int i;
-
-		for (i = 0;
-		     i < ((cq->ibcq.cqe + 1) * MTHCA_CQ_ENTRY_SIZE + PAGE_SIZE - 1) /
-			     PAGE_SIZE;
-		     ++i)
-			pci_free_consistent(dev->pdev, PAGE_SIZE,
-					    cq->queue.page_list[i].buf,
-					    pci_unmap_addr(&cq->queue.page_list[i],
-							   mapping));
-
-		kfree(cq->queue.page_list);
+	if (dev->hca_type == ARBEL_NATIVE) {
+		mthca_free_db(dev, MTHCA_DB_TYPE_CQ_ARM,    cq->arm_db_index);
+		mthca_free_db(dev, MTHCA_DB_TYPE_CQ_SET_CI, cq->set_ci_db_index);
+		mthca_table_put(dev, dev->cq_table.table, cq->cqn);
 	}
 
 	mthca_free(&dev->cq_table.alloc, cq->cqn);
diff -Nru a/drivers/infiniband/hw/mthca/mthca_dev.h b/drivers/infiniband/hw/mthca/mthca_dev.h
--- a/drivers/infiniband/hw/mthca/mthca_dev.h	2005-03-11 12:51:41 -08:00
+++ b/drivers/infiniband/hw/mthca/mthca_dev.h	2005-03-11 12:51:41 -08:00
@@ -65,7 +65,6 @@
 };
 
 enum {
-	MTHCA_KAR_PAGE  = 1,
 	MTHCA_MAX_PORTS = 2
 };
 
@@ -108,6 +107,7 @@
 	int      gid_table_len;
 	int      pkey_table_len;
 	int      local_ca_ack_delay;
+	int      num_uars;
 	int      max_sg;
 	int      num_qps;
 	int      reserved_qps;
@@ -148,6 +148,12 @@
 	} *page_list;
 };
 
+struct mthca_uar_table {
+	struct mthca_alloc alloc;
+	u64                uarc_base;
+	int                uarc_size;
+};
+
 struct mthca_pd_table {
 	struct mthca_alloc alloc;
 };
@@ -165,6 +171,7 @@
 	struct mthca_alloc alloc;
 	void __iomem      *clr_int;
 	u32                clr_mask;
+	u32                arm_mask;
 	struct mthca_eq    eq[MTHCA_NUM_EQ];
 	u64                icm_virt;
 	struct page       *icm_page;
@@ -200,8 +207,9 @@
 };
 
 struct mthca_mcg_table {
-	struct semaphore   sem;
-	struct mthca_alloc alloc;
+	struct semaphore   	sem;
+	struct mthca_alloc 	alloc;
+	struct mthca_icm_table *table;
 };
 
 struct mthca_dev {
@@ -210,6 +218,7 @@
 
 	int          	 hca_type;
 	unsigned long	 mthca_flags;
+	unsigned long    device_cap_flags;
 
 	u32              rev_id;
 
@@ -237,13 +246,22 @@
 	struct semaphore cap_mask_mutex;
 
 	void __iomem    *hcr;
-	void __iomem    *ecr_base;
-	void __iomem    *clr_base;
 	void __iomem    *kar;
+	void __iomem    *clr_base;
+	union {
+		struct {
+			void __iomem *ecr_base;
+		} tavor;
+		struct {
+			void __iomem *eq_arm;
+			void __iomem *eq_set_ci_base;
+		} arbel;
+	} eq_regs;
 
 	struct mthca_cmd    cmd;
 	struct mthca_limits limits;
 
+	struct mthca_uar_table uar_table;
 	struct mthca_pd_table  pd_table;
 	struct mthca_mr_table  mr_table;
 	struct mthca_eq_table  eq_table;
@@ -252,8 +270,10 @@
 	struct mthca_av_table  av_table;
 	struct mthca_mcg_table mcg_table;
 
-	struct mthca_pd       driver_pd;
-	struct mthca_mr       driver_mr;
+	struct mthca_uar       driver_uar;
+	struct mthca_db_table *db_tab;
+	struct mthca_pd        driver_pd;
+	struct mthca_mr        driver_mr;
 
 	struct ib_mad_agent  *send_agent[MTHCA_MAX_PORTS][2];
 	struct ib_ah         *sm_ah[MTHCA_MAX_PORTS];
@@ -310,6 +330,7 @@
 int mthca_array_init(struct mthca_array *array, int nent);
 void mthca_array_cleanup(struct mthca_array *array, int nent);
 
+int mthca_init_uar_table(struct mthca_dev *dev);
 int mthca_init_pd_table(struct mthca_dev *dev);
 int mthca_init_mr_table(struct mthca_dev *dev);
 int mthca_init_eq_table(struct mthca_dev *dev);
@@ -318,6 +339,7 @@
 int mthca_init_av_table(struct mthca_dev *dev);
 int mthca_init_mcg_table(struct mthca_dev *dev);
 
+void mthca_cleanup_uar_table(struct mthca_dev *dev);
 void mthca_cleanup_pd_table(struct mthca_dev *dev);
 void mthca_cleanup_mr_table(struct mthca_dev *dev);
 void mthca_cleanup_eq_table(struct mthca_dev *dev);
@@ -329,6 +351,9 @@
 int mthca_register_device(struct mthca_dev *dev);
 void mthca_unregister_device(struct mthca_dev *dev);
 
+int mthca_uar_alloc(struct mthca_dev *dev, struct mthca_uar *uar);
+void mthca_uar_free(struct mthca_dev *dev, struct mthca_uar *uar);
+
 int mthca_pd_alloc(struct mthca_dev *dev, struct mthca_pd *pd);
 void mthca_pd_free(struct mthca_dev *dev, struct mthca_pd *pd);
 
@@ -345,8 +370,8 @@
 
 int mthca_poll_cq(struct ib_cq *ibcq, int num_entries,
 		  struct ib_wc *entry);
-void mthca_arm_cq(struct mthca_dev *dev, struct mthca_cq *cq,
-		  int solicited);
+int mthca_tavor_arm_cq(struct ib_cq *cq, enum ib_cq_notify notify);
+int mthca_arbel_arm_cq(struct ib_cq *cq, enum ib_cq_notify notify);
 int mthca_init_cq(struct mthca_dev *dev, int nent,
 		  struct mthca_cq *cq);
 void mthca_free_cq(struct mthca_dev *dev,
@@ -357,11 +382,15 @@
 void mthca_qp_event(struct mthca_dev *dev, u32 qpn,
 		    enum ib_event_type event_type);
 int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask);
-int mthca_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
-		    struct ib_send_wr **bad_wr);
-int mthca_post_receive(struct ib_qp *ibqp, struct ib_recv_wr *wr,
-		       struct ib_recv_wr **bad_wr);
-int mthca_free_err_wqe(struct mthca_qp *qp, int is_send,
+int mthca_tavor_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
+			  struct ib_send_wr **bad_wr);
+int mthca_tavor_post_receive(struct ib_qp *ibqp, struct ib_recv_wr *wr,
+			     struct ib_recv_wr **bad_wr);
+int mthca_arbel_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
+			  struct ib_send_wr **bad_wr);
+int mthca_arbel_post_receive(struct ib_qp *ibqp, struct ib_recv_wr *wr,
+			     struct ib_recv_wr **bad_wr);
+int mthca_free_err_wqe(struct mthca_dev *dev, struct mthca_qp *qp, int is_send,
 		       int index, int *dbd, u32 *new_wqe);
 int mthca_alloc_qp(struct mthca_dev *dev,
 		   struct mthca_pd *pd,
@@ -369,14 +398,12 @@
 		   struct mthca_cq *recv_cq,
 		   enum ib_qp_type type,
 		   enum ib_sig_type send_policy,
-		   enum ib_sig_type recv_policy,
 		   struct mthca_qp *qp);
 int mthca_alloc_sqp(struct mthca_dev *dev,
 		    struct mthca_pd *pd,
 		    struct mthca_cq *send_cq,
 		    struct mthca_cq *recv_cq,
 		    enum ib_sig_type send_policy,
-		    enum ib_sig_type recv_policy,
 		    int qpn,
 		    int port,
 		    struct mthca_sqp *sqp);
diff -Nru a/drivers/infiniband/hw/mthca/mthca_doorbell.h b/drivers/infiniband/hw/mthca/mthca_doorbell.h
--- a/drivers/infiniband/hw/mthca/mthca_doorbell.h	2005-03-11 12:51:46 -08:00
+++ b/drivers/infiniband/hw/mthca/mthca_doorbell.h	2005-03-11 12:51:46 -08:00
@@ -57,6 +57,11 @@
 	__raw_writeq(*(u64 *) val, dest);
 }
 
+static inline void mthca_write_db_rec(u32 val[2], u32 *db)
+{
+	*(u64 *) db = *(u64 *) val;
+}
+
 #else
 
 /*
@@ -78,6 +83,13 @@
 	__raw_writel(val[0], dest);
 	__raw_writel(val[1], dest + 4);
 	spin_unlock_irqrestore(doorbell_lock, flags);
+}
+
+static inline void mthca_write_db_rec(u32 val[2], u32 *db)
+{
+	db[0] = val[0];
+	wmb();
+	db[1] = val[1];
 }
 
 #endif
diff -Nru a/drivers/infiniband/hw/mthca/mthca_eq.c b/drivers/infiniband/hw/mthca/mthca_eq.c
--- a/drivers/infiniband/hw/mthca/mthca_eq.c	2005-03-11 12:51:47 -08:00
+++ b/drivers/infiniband/hw/mthca/mthca_eq.c	2005-03-11 12:51:47 -08:00
@@ -54,10 +54,10 @@
 	u32 flags;
 	u64 start;
 	u32 logsize_usrpage;
-	u32 pd;
+	u32 tavor_pd;		/* reserved for Arbel */
 	u8  reserved1[3];
 	u8  intr;
-	u32 lost_count;
+	u32 arbel_pd;		/* lost_count for Tavor */
 	u32 lkey;
 	u32 reserved2[2];
 	u32 consumer_index;
@@ -75,6 +75,7 @@
 #define MTHCA_EQ_STATE_ARMED        ( 1 <<  8)
 #define MTHCA_EQ_STATE_FIRED        ( 2 <<  8)
 #define MTHCA_EQ_STATE_ALWAYS_ARMED ( 3 <<  8)
+#define MTHCA_EQ_STATE_ARBEL        ( 8 <<  8)
 
 enum {
 	MTHCA_EVENT_TYPE_COMP       	    = 0x00,
@@ -164,19 +165,46 @@
 		MTHCA_ASYNC_EVENT_MASK;
 }
 
-static inline void set_eq_ci(struct mthca_dev *dev, struct mthca_eq *eq, u32 ci)
+static inline void tavor_set_eq_ci(struct mthca_dev *dev, struct mthca_eq *eq, u32 ci)
 {
 	u32 doorbell[2];
 
 	doorbell[0] = cpu_to_be32(MTHCA_EQ_DB_SET_CI | eq->eqn);
 	doorbell[1] = cpu_to_be32(ci & (eq->nent - 1));
 
+	/*
+	 * This barrier makes sure that all updates to ownership bits
+	 * done by set_eqe_hw() hit memory before the consumer index
+	 * is updated.  set_eq_ci() allows the HCA to possibly write
+	 * more EQ entries, and we want to avoid the exceedingly
+	 * unlikely possibility of the HCA writing an entry and then
+	 * having set_eqe_hw() overwrite the owner field.
+	 */
+	wmb();
 	mthca_write64(doorbell,
 		      dev->kar + MTHCA_EQ_DOORBELL,
 		      MTHCA_GET_DOORBELL_LOCK(&dev->doorbell_lock));
 }
 
-static inline void eq_req_not(struct mthca_dev *dev, int eqn)
+static inline void arbel_set_eq_ci(struct mthca_dev *dev, struct mthca_eq *eq, u32 ci)
+{
+	/* See comment in tavor_set_eq_ci() above. */
+	wmb();
+	__raw_writel(cpu_to_be32(ci), dev->eq_regs.arbel.eq_set_ci_base +
+		     eq->eqn * 8);
+	/* We still want ordering, just not swabbing, so add a barrier */
+	mb();
+}
+
+static inline void set_eq_ci(struct mthca_dev *dev, struct mthca_eq *eq, u32 ci)
+{
+	if (dev->hca_type == ARBEL_NATIVE)
+		arbel_set_eq_ci(dev, eq, ci);
+	else
+		tavor_set_eq_ci(dev, eq, ci);
+}
+
+static inline void tavor_eq_req_not(struct mthca_dev *dev, int eqn)
 {
 	u32 doorbell[2];
 
@@ -188,16 +216,23 @@
 		      MTHCA_GET_DOORBELL_LOCK(&dev->doorbell_lock));
 }
 
+static inline void arbel_eq_req_not(struct mthca_dev *dev, u32 eqn_mask)
+{
+	writel(eqn_mask, dev->eq_regs.arbel.eq_arm);
+}
+
 static inline void disarm_cq(struct mthca_dev *dev, int eqn, int cqn)
 {
-	u32 doorbell[2];
+	if (dev->hca_type != ARBEL_NATIVE) {
+		u32 doorbell[2];
 
-	doorbell[0] = cpu_to_be32(MTHCA_EQ_DB_DISARM_CQ | eqn);
-	doorbell[1] = cpu_to_be32(cqn);
+		doorbell[0] = cpu_to_be32(MTHCA_EQ_DB_DISARM_CQ | eqn);
+		doorbell[1] = cpu_to_be32(cqn);
 
-	mthca_write64(doorbell,
-		      dev->kar + MTHCA_EQ_DOORBELL,
-		      MTHCA_GET_DOORBELL_LOCK(&dev->doorbell_lock));
+		mthca_write64(doorbell,
+			      dev->kar + MTHCA_EQ_DOORBELL,
+			      MTHCA_GET_DOORBELL_LOCK(&dev->doorbell_lock));
+	}
 }
 
 static inline struct mthca_eqe *get_eqe(struct mthca_eq *eq, u32 entry)
@@ -232,7 +267,7 @@
 	ib_dispatch_event(&record);
 }
 
-static void mthca_eq_int(struct mthca_dev *dev, struct mthca_eq *eq)
+static int mthca_eq_int(struct mthca_dev *dev, struct mthca_eq *eq)
 {
 	struct mthca_eqe *eqe;
 	int disarm_cqn;
@@ -333,60 +368,93 @@
 		++eq->cons_index;
 		eqes_found = 1;
 
-		if (set_ci) {
-			wmb(); /* see comment below */
+		if (unlikely(set_ci)) {
+			/*
+			 * Conditional on hca_type is OK here because
+			 * this is a rare case, not the fast path.
+			 */
 			set_eq_ci(dev, eq, eq->cons_index);
 			set_ci = 0;
 		}
 	}
 
 	/*
-	 * This barrier makes sure that all updates to
-	 * ownership bits done by set_eqe_hw() hit memory
-	 * before the consumer index is updated.  set_eq_ci()
-	 * allows the HCA to possibly write more EQ entries,
-	 * and we want to avoid the exceedingly unlikely
-	 * possibility of the HCA writing an entry and then
-	 * having set_eqe_hw() overwrite the owner field.
+	 * Rely on caller to set consumer index so that we don't have
+	 * to test hca_type in our interrupt handling fast path.
 	 */
-	if (likely(eqes_found)) {
-		wmb();
-		set_eq_ci(dev, eq, eq->cons_index);
-	}
-	eq_req_not(dev, eq->eqn);
+	return eqes_found;
 }
 
-static irqreturn_t mthca_interrupt(int irq, void *dev_ptr, struct pt_regs *regs)
+static irqreturn_t mthca_tavor_interrupt(int irq, void *dev_ptr, struct pt_regs *regs)
 {
 	struct mthca_dev *dev = dev_ptr;
 	u32 ecr;
-	int work = 0;
 	int i;
 
 	if (dev->eq_table.clr_mask)
 		writel(dev->eq_table.clr_mask, dev->eq_table.clr_int);
 
-	if ((ecr = readl(dev->ecr_base + 4)) != 0) {
-		work = 1;
-
-		writel(ecr, dev->ecr_base +
+	ecr = readl(dev->eq_regs.tavor.ecr_base + 4);
+	if (ecr) {
+		writel(ecr, dev->eq_regs.tavor.ecr_base +
 		       MTHCA_ECR_CLR_BASE - MTHCA_ECR_BASE + 4);
 
 		for (i = 0; i < MTHCA_NUM_EQ; ++i)
-			if (ecr & dev->eq_table.eq[i].ecr_mask)
-				mthca_eq_int(dev, &dev->eq_table.eq[i]);
+			if (ecr & dev->eq_table.eq[i].eqn_mask &&
+			    mthca_eq_int(dev, &dev->eq_table.eq[i])) {
+				tavor_set_eq_ci(dev, &dev->eq_table.eq[i],
+						dev->eq_table.eq[i].cons_index);
+				tavor_eq_req_not(dev, dev->eq_table.eq[i].eqn);
+			}
 	}
 
-	return IRQ_RETVAL(work);
+	return IRQ_RETVAL(ecr);
 }
 
-static irqreturn_t mthca_msi_x_interrupt(int irq, void *eq_ptr,
+static irqreturn_t mthca_tavor_msi_x_interrupt(int irq, void *eq_ptr,
 					 struct pt_regs *regs)
 {
 	struct mthca_eq  *eq  = eq_ptr;
 	struct mthca_dev *dev = eq->dev;
 
 	mthca_eq_int(dev, eq);
+	tavor_set_eq_ci(dev, eq, eq->cons_index);
+	tavor_eq_req_not(dev, eq->eqn);
+
+	/* MSI-X vectors always belong to us */
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t mthca_arbel_interrupt(int irq, void *dev_ptr, struct pt_regs *regs)
+{
+	struct mthca_dev *dev = dev_ptr;
+	int work = 0;
+	int i;
+
+	if (dev->eq_table.clr_mask)
+		writel(dev->eq_table.clr_mask, dev->eq_table.clr_int);
+
+	for (i = 0; i < MTHCA_NUM_EQ; ++i)
+		if (mthca_eq_int(dev, &dev->eq_table.eq[i])) {
+			work = 1;
+			arbel_set_eq_ci(dev, &dev->eq_table.eq[i],
+					dev->eq_table.eq[i].cons_index);
+		}
+
+	arbel_eq_req_not(dev, dev->eq_table.arm_mask);
+
+	return IRQ_RETVAL(work);
+}
+
+static irqreturn_t mthca_arbel_msi_x_interrupt(int irq, void *eq_ptr,
+					       struct pt_regs *regs)
+{
+	struct mthca_eq  *eq  = eq_ptr;
+	struct mthca_dev *dev = eq->dev;
+
+	mthca_eq_int(dev, eq);
+	arbel_set_eq_ci(dev, eq, eq->cons_index);
+	arbel_eq_req_not(dev, eq->eqn_mask);
 
 	/* MSI-X vectors always belong to us */
 	return IRQ_HANDLED;
@@ -467,10 +535,16 @@
 						  MTHCA_EQ_OWNER_HW    |
 						  MTHCA_EQ_STATE_ARMED |
 						  MTHCA_EQ_FLAG_TR);
-	eq_context->start           = cpu_to_be64(0);
-	eq_context->logsize_usrpage = cpu_to_be32((ffs(nent) - 1) << 24 |
-						  MTHCA_KAR_PAGE);
-	eq_context->pd              = cpu_to_be32(dev->driver_pd.pd_num);
+	if (dev->hca_type == ARBEL_NATIVE)
+		eq_context->flags  |= cpu_to_be32(MTHCA_EQ_STATE_ARBEL);
+
+	eq_context->logsize_usrpage = cpu_to_be32((ffs(nent) - 1) << 24);
+	if (dev->hca_type == ARBEL_NATIVE) {
+		eq_context->arbel_pd = cpu_to_be32(dev->driver_pd.pd_num);
+	} else {
+		eq_context->logsize_usrpage |= cpu_to_be32(dev->driver_uar.index);
+		eq_context->tavor_pd         = cpu_to_be32(dev->driver_pd.pd_num);
+	}
 	eq_context->intr            = intr;
 	eq_context->lkey            = cpu_to_be32(eq->mr.ibmr.lkey);
 
@@ -489,10 +563,10 @@
 	kfree(dma_list);
 	kfree(mailbox);
 
-	eq->ecr_mask   = swab32(1 << eq->eqn);
+	eq->eqn_mask   = swab32(1 << eq->eqn);
 	eq->cons_index = 0;
 
-	eq_req_not(dev, eq->eqn);
+	dev->eq_table.arm_mask |= eq->eqn_mask;
 
 	mthca_dbg(dev, "Allocated EQ %d with %d entries\n",
 		  eq->eqn, nent);
@@ -544,6 +618,8 @@
 		mthca_warn(dev, "HW2SW_EQ returned status 0x%02x\n",
 			   status);
 
+	dev->eq_table.arm_mask &= ~eq->eqn_mask;
+
 	if (0) {
 		mthca_dbg(dev, "Dumping EQ context %02x:\n", eq->eqn);
 		for (i = 0; i < sizeof (struct mthca_eq_context) / 4; ++i) {
@@ -555,7 +631,6 @@
 		}
 	}
 
-
 	mthca_free_mr(dev, &eq->mr);
 	for (i = 0; i < npages; ++i)
 		pci_free_consistent(dev->pdev, PAGE_SIZE,
@@ -578,6 +653,129 @@
 				 dev->eq_table.eq + i);
 }
 
+static int __devinit mthca_map_reg(struct mthca_dev *dev,
+				   unsigned long offset, unsigned long size,
+				   void __iomem **map)
+{
+	unsigned long base = pci_resource_start(dev->pdev, 0);
+
+	if (!request_mem_region(base + offset, size, DRV_NAME))
+		return -EBUSY;
+
+	*map = ioremap(base + offset, size);
+	if (!*map) {
+		release_mem_region(base + offset, size);
+		return -ENOMEM;
+	}
+
+	return 0;
+}
+
+static void mthca_unmap_reg(struct mthca_dev *dev, unsigned long offset,
+			    unsigned long size, void __iomem *map)
+{
+	unsigned long base = pci_resource_start(dev->pdev, 0);
+
+	release_mem_region(base + offset, size);
+	iounmap(map);
+}
+
+static int __devinit mthca_map_eq_regs(struct mthca_dev *dev)
+{
+	unsigned long mthca_base;
+
+	mthca_base = pci_resource_start(dev->pdev, 0);
+
+	if (dev->hca_type == ARBEL_NATIVE) {
+		/*
+		 * We assume that the EQ arm and EQ set CI registers
+		 * fall within the first BAR.  We can't trust the
+		 * values firmware gives us, since those addresses are
+		 * valid on the HCA's side of the PCI bus but not
+		 * necessarily the host side.
+		 */
+		if (mthca_map_reg(dev, (pci_resource_len(dev->pdev, 0) - 1) &
+				  dev->fw.arbel.clr_int_base, MTHCA_CLR_INT_SIZE,
+				  &dev->clr_base)) {
+			mthca_err(dev, "Couldn't map interrupt clear register, "
+				  "aborting.\n");
+			return -ENOMEM;
+		}
+
+		/*
+		 * Add 4 because we limit ourselves to EQs 0 ... 31,
+		 * so we only need the low word of the register.
+		 */
+		if (mthca_map_reg(dev, ((pci_resource_len(dev->pdev, 0) - 1) &
+					dev->fw.arbel.eq_arm_base) + 4, 4,
+				  &dev->eq_regs.arbel.eq_arm)) {
+			mthca_err(dev, "Couldn't map interrupt clear register, "
+				  "aborting.\n");
+			mthca_unmap_reg(dev, (pci_resource_len(dev->pdev, 0) - 1) &
+					dev->fw.arbel.clr_int_base, MTHCA_CLR_INT_SIZE,
+					dev->clr_base);
+			return -ENOMEM;
+		}
+
+		if (mthca_map_reg(dev, (pci_resource_len(dev->pdev, 0) - 1) &
+				  dev->fw.arbel.eq_set_ci_base,
+				  MTHCA_EQ_SET_CI_SIZE,
+				  &dev->eq_regs.arbel.eq_set_ci_base)) {
+			mthca_err(dev, "Couldn't map interrupt clear register, "
+				  "aborting.\n");
+			mthca_unmap_reg(dev, ((pci_resource_len(dev->pdev, 0) - 1) &
+					      dev->fw.arbel.eq_arm_base) + 4, 4,
+					dev->eq_regs.arbel.eq_arm);
+			mthca_unmap_reg(dev, (pci_resource_len(dev->pdev, 0) - 1) &
+					dev->fw.arbel.clr_int_base, MTHCA_CLR_INT_SIZE,
+					dev->clr_base);
+			return -ENOMEM;
+		}
+	} else {
+		if (mthca_map_reg(dev, MTHCA_CLR_INT_BASE, MTHCA_CLR_INT_SIZE,
+				  &dev->clr_base)) {
+			mthca_err(dev, "Couldn't map interrupt clear register, "
+				  "aborting.\n");
+			return -ENOMEM;
+		}
+
+		if (mthca_map_reg(dev, MTHCA_ECR_BASE,
+				  MTHCA_ECR_SIZE + MTHCA_ECR_CLR_SIZE,
+				  &dev->eq_regs.tavor.ecr_base)) {
+			mthca_err(dev, "Couldn't map ecr register, "
+				  "aborting.\n");
+			mthca_unmap_reg(dev, MTHCA_CLR_INT_BASE, MTHCA_CLR_INT_SIZE,
+					dev->clr_base);
+			return -ENOMEM;
+		}
+	}
+
+	return 0;
+
+}
+
+static void __devexit mthca_unmap_eq_regs(struct mthca_dev *dev)
+{
+	if (dev->hca_type == ARBEL_NATIVE) {
+		mthca_unmap_reg(dev, (pci_resource_len(dev->pdev, 0) - 1) &
+				dev->fw.arbel.eq_set_ci_base,
+				MTHCA_EQ_SET_CI_SIZE,
+				dev->eq_regs.arbel.eq_set_ci_base);
+		mthca_unmap_reg(dev, ((pci_resource_len(dev->pdev, 0) - 1) &
+				      dev->fw.arbel.eq_arm_base) + 4, 4,
+				dev->eq_regs.arbel.eq_arm);
+		mthca_unmap_reg(dev, (pci_resource_len(dev->pdev, 0) - 1) &
+				dev->fw.arbel.clr_int_base, MTHCA_CLR_INT_SIZE,
+				dev->clr_base);
+	} else {
+		mthca_unmap_reg(dev, MTHCA_ECR_BASE,
+				MTHCA_ECR_SIZE + MTHCA_ECR_CLR_SIZE,
+				dev->eq_regs.tavor.ecr_base);
+		mthca_unmap_reg(dev, MTHCA_CLR_INT_BASE, MTHCA_CLR_INT_SIZE,
+				dev->clr_base);
+	}
+}
+
 int __devinit mthca_map_eq_icm(struct mthca_dev *dev, u64 icm_virt)
 {
 	int ret;
@@ -636,6 +834,10 @@
 	if (err)
 		return err;
 
+	err = mthca_map_eq_regs(dev);
+	if (err)
+		goto err_out_free;
+
 	if (dev->mthca_flags & MTHCA_FLAG_MSI ||
 	    dev->mthca_flags & MTHCA_FLAG_MSI_X) {
 		dev->eq_table.clr_mask = 0;
@@ -646,6 +848,8 @@
 			(dev->eq_table.inta_pin < 31 ? 4 : 0);
 	}
 
+	dev->eq_table.arm_mask = 0;
+
 	intr = (dev->mthca_flags & MTHCA_FLAG_MSI) ?
 		128 : dev->eq_table.inta_pin;
 
@@ -653,7 +857,7 @@
 			      (dev->mthca_flags & MTHCA_FLAG_MSI_X) ? 128 : intr,
 			      &dev->eq_table.eq[MTHCA_EQ_COMP]);
 	if (err)
-		goto err_out_free;
+		goto err_out_unmap;
 
 	err = mthca_create_eq(dev, MTHCA_NUM_ASYNC_EQE,
 			      (dev->mthca_flags & MTHCA_FLAG_MSI_X) ? 129 : intr,
@@ -676,15 +880,20 @@
 
 		for (i = 0; i < MTHCA_NUM_EQ; ++i) {
 			err = request_irq(dev->eq_table.eq[i].msi_x_vector,
-					  mthca_msi_x_interrupt, 0,
-					  eq_name[i], dev->eq_table.eq + i);
+					  dev->hca_type == ARBEL_NATIVE ?
+					  mthca_arbel_msi_x_interrupt :
+					  mthca_tavor_msi_x_interrupt,
+					  0, eq_name[i], dev->eq_table.eq + i);
 			if (err)
 				goto err_out_cmd;
 			dev->eq_table.eq[i].have_irq = 1;
 		}
 	} else {
-		err = request_irq(dev->pdev->irq, mthca_interrupt, SA_SHIRQ,
-				  DRV_NAME, dev);
+		err = request_irq(dev->pdev->irq,
+				  dev->hca_type == ARBEL_NATIVE ?
+				  mthca_arbel_interrupt :
+				  mthca_tavor_interrupt,
+				  SA_SHIRQ, DRV_NAME, dev);
 		if (err)
 			goto err_out_cmd;
 		dev->eq_table.have_irq = 1;
@@ -708,6 +917,12 @@
 		mthca_warn(dev, "MAP_EQ for cmd EQ %d returned status 0x%02x\n",
 			   dev->eq_table.eq[MTHCA_EQ_CMD].eqn, status);
 
+	for (i = 0; i < MTHCA_EQ_CMD; ++i)
+		if (dev->hca_type == ARBEL_NATIVE)
+			arbel_eq_req_not(dev, dev->eq_table.eq[i].eqn_mask);
+		else
+			tavor_eq_req_not(dev, dev->eq_table.eq[i].eqn);
+
 	return 0;
 
 err_out_cmd:
@@ -720,6 +935,9 @@
 err_out_comp:
 	mthca_free_eq(dev, &dev->eq_table.eq[MTHCA_EQ_COMP]);
 
+err_out_unmap:
+	mthca_unmap_eq_regs(dev);
+
 err_out_free:
 	mthca_alloc_cleanup(&dev->eq_table.alloc);
 	return err;
@@ -739,6 +957,8 @@
 
 	for (i = 0; i < MTHCA_NUM_EQ; ++i)
 		mthca_free_eq(dev, &dev->eq_table.eq[i]);
+
+	mthca_unmap_eq_regs(dev);
 
 	mthca_alloc_cleanup(&dev->eq_table.alloc);
 }
diff -Nru a/drivers/infiniband/hw/mthca/mthca_main.c b/drivers/infiniband/hw/mthca/mthca_main.c
--- a/drivers/infiniband/hw/mthca/mthca_main.c	2005-03-11 12:51:46 -08:00
+++ b/drivers/infiniband/hw/mthca/mthca_main.c	2005-03-11 12:51:46 -08:00
@@ -171,6 +171,33 @@
 	mdev->limits.reserved_uars      = dev_lim->reserved_uars;
 	mdev->limits.reserved_pds       = dev_lim->reserved_pds;
 
+	/* IB_DEVICE_RESIZE_MAX_WR not supported by driver.
+	   May be doable since hardware supports it for SRQ.
+
+	   IB_DEVICE_N_NOTIFY_CQ is supported by hardware but not by driver.
+
+	   IB_DEVICE_SRQ_RESIZE is supported by hardware but SRQ is not
+	   supported by driver. */
+	mdev->device_cap_flags = IB_DEVICE_CHANGE_PHY_PORT |
+		IB_DEVICE_PORT_ACTIVE_EVENT |
+		IB_DEVICE_SYS_IMAGE_GUID |
+		IB_DEVICE_RC_RNR_NAK_GEN;
+
+	if (dev_lim->flags & DEV_LIM_FLAG_BAD_PKEY_CNTR)
+		mdev->device_cap_flags |= IB_DEVICE_BAD_PKEY_CNTR;
+
+	if (dev_lim->flags & DEV_LIM_FLAG_BAD_QKEY_CNTR)
+		mdev->device_cap_flags |= IB_DEVICE_BAD_QKEY_CNTR;
+
+	if (dev_lim->flags & DEV_LIM_FLAG_RAW_MULTI)
+		mdev->device_cap_flags |= IB_DEVICE_RAW_MULTI;
+
+	if (dev_lim->flags & DEV_LIM_FLAG_AUTO_PATH_MIG)
+		mdev->device_cap_flags |= IB_DEVICE_AUTO_PATH_MIG;
+
+	if (dev_lim->flags & DEV_LIM_FLAG_UD_AV_PORT_ENFORCE)
+		mdev->device_cap_flags |= IB_DEVICE_UD_AV_PORT_ENFORCE;
+
 	if (dev_lim->flags & DEV_LIM_FLAG_SRQ)
 		mdev->mthca_flags |= MTHCA_FLAG_SRQ;
 
@@ -363,10 +390,9 @@
 	}
 
 	mdev->mr_table.mtt_table = mthca_alloc_icm_table(mdev, init_hca->mtt_base,
-							 mdev->limits.num_mtt_segs *
 							 init_hca->mtt_seg_sz,
-							 mdev->limits.reserved_mtts *
-							 init_hca->mtt_seg_sz, 1);
+							 mdev->limits.num_mtt_segs,
+							 mdev->limits.reserved_mtts, 1);
 	if (!mdev->mr_table.mtt_table) {
 		mthca_err(mdev, "Failed to map MTT context memory, aborting.\n");
 		err = -ENOMEM;
@@ -374,10 +400,9 @@
 	}
 
 	mdev->mr_table.mpt_table = mthca_alloc_icm_table(mdev, init_hca->mpt_base,
-							 mdev->limits.num_mpts *
 							 dev_lim->mpt_entry_sz,
-							 mdev->limits.reserved_mrws *
-							 dev_lim->mpt_entry_sz, 1);
+							 mdev->limits.num_mpts,
+							 mdev->limits.reserved_mrws, 1);
 	if (!mdev->mr_table.mpt_table) {
 		mthca_err(mdev, "Failed to map MPT context memory, aborting.\n");
 		err = -ENOMEM;
@@ -385,10 +410,9 @@
 	}
 
 	mdev->qp_table.qp_table = mthca_alloc_icm_table(mdev, init_hca->qpc_base,
-							mdev->limits.num_qps *
 							dev_lim->qpc_entry_sz,
-							mdev->limits.reserved_qps *
-							dev_lim->qpc_entry_sz, 1);
+							mdev->limits.num_qps,
+							mdev->limits.reserved_qps, 0);
 	if (!mdev->qp_table.qp_table) {
 		mthca_err(mdev, "Failed to map QP context memory, aborting.\n");
 		err = -ENOMEM;
@@ -396,10 +420,9 @@
 	}
 
 	mdev->qp_table.eqp_table = mthca_alloc_icm_table(mdev, init_hca->eqpc_base,
-							 mdev->limits.num_qps *
 							 dev_lim->eqpc_entry_sz,
-							 mdev->limits.reserved_qps *
-							 dev_lim->eqpc_entry_sz, 1);
+							 mdev->limits.num_qps,
+							 mdev->limits.reserved_qps, 0);
 	if (!mdev->qp_table.eqp_table) {
 		mthca_err(mdev, "Failed to map EQP context memory, aborting.\n");
 		err = -ENOMEM;
@@ -407,18 +430,38 @@
 	}
 
 	mdev->cq_table.table = mthca_alloc_icm_table(mdev, init_hca->cqc_base,
-						     mdev->limits.num_cqs *
 						     dev_lim->cqc_entry_sz,
-						     mdev->limits.reserved_cqs *
-						     dev_lim->cqc_entry_sz, 1);
+						     mdev->limits.num_cqs,
+						     mdev->limits.reserved_cqs, 0);
 	if (!mdev->cq_table.table) {
 		mthca_err(mdev, "Failed to map CQ context memory, aborting.\n");
 		err = -ENOMEM;
 		goto err_unmap_eqp;
 	}
 
+	/*
+	 * It's not strictly required, but for simplicity just map the
+	 * whole multicast group table now.  The table isn't very big
+	 * and it's a lot easier than trying to track ref counts.
+	 */
+	mdev->mcg_table.table = mthca_alloc_icm_table(mdev, init_hca->mc_base,
+						      MTHCA_MGM_ENTRY_SIZE,
+						      mdev->limits.num_mgms +
+						      mdev->limits.num_amgms,
+						      mdev->limits.num_mgms +
+						      mdev->limits.num_amgms,
+						      0);
+	if (!mdev->mcg_table.table) {
+		mthca_err(mdev, "Failed to map MCG context memory, aborting.\n");
+		err = -ENOMEM;
+		goto err_unmap_cq;
+	}
+
 	return 0;
 
+err_unmap_cq:
+	mthca_free_icm_table(mdev, mdev->cq_table.table);
+
 err_unmap_eqp:
 	mthca_free_icm_table(mdev, mdev->qp_table.eqp_table);
 
@@ -570,11 +613,33 @@
 
 	MTHCA_INIT_DOORBELL_LOCK(&dev->doorbell_lock);
 
+	err = mthca_init_uar_table(dev);
+	if (err) {
+		mthca_err(dev, "Failed to initialize "
+			  "user access region table, aborting.\n");
+		return err;
+	}
+
+	err = mthca_uar_alloc(dev, &dev->driver_uar);
+	if (err) {
+		mthca_err(dev, "Failed to allocate driver access region, "
+			  "aborting.\n");
+		goto err_uar_table_free;
+	}
+
+	dev->kar = ioremap(dev->driver_uar.pfn << PAGE_SHIFT, PAGE_SIZE);
+	if (!dev->kar) {
+		mthca_err(dev, "Couldn't map kernel access region, "
+			  "aborting.\n");
+		err = -ENOMEM;
+		goto err_uar_free;
+	}
+
 	err = mthca_init_pd_table(dev);
 	if (err) {
 		mthca_err(dev, "Failed to initialize "
 			  "protection domain table, aborting.\n");
-		return err;
+		goto err_kar_unmap;
 	}
 
 	err = mthca_init_mr_table(dev);
@@ -591,13 +656,6 @@
 		goto err_mr_table_free;
 	}
 
-	if (dev->hca_type == ARBEL_NATIVE) {
-		mthca_warn(dev, "Sorry, native MT25208 mode support is not done, "
-			   "aborting.\n");
-		err = -ENODEV;
-		goto err_pd_free;
-	}
-
 	err = mthca_init_eq_table(dev);
 	if (err) {
 		mthca_err(dev, "Failed to initialize "
@@ -621,8 +679,9 @@
 			mthca_err(dev, "BIOS or ACPI interrupt routing problem?\n");
 
 		goto err_cmd_poll;
-	} else
-		mthca_dbg(dev, "NOP command IRQ test passed\n");
+	}
+
+	mthca_dbg(dev, "NOP command IRQ test passed\n");
 
 	err = mthca_init_cq_table(dev);
 	if (err) {
@@ -677,6 +736,15 @@
 
 err_pd_table_free:
 	mthca_cleanup_pd_table(dev);
+
+err_kar_unmap:
+	iounmap(dev->kar);
+
+err_uar_free:
+	mthca_uar_free(dev, &dev->driver_uar);
+
+err_uar_table_free:
+	mthca_cleanup_uar_table(dev);
 	return err;
 }
 
@@ -686,37 +754,18 @@
 	int err;
 
 	/*
-	 * We request our first BAR in two chunks, since the MSI-X
-	 * vector table is right in the middle.
+	 * We can't just use pci_request_regions() because the MSI-X
+	 * table is right in the middle of the first BAR.  If we did
+	 * pci_request_region and grab all of the first BAR, then
+	 * setting up MSI-X would fail, since the PCI core wants to do
+	 * request_mem_region on the MSI-X vector table.
 	 *
-	 * This is why we can't just use pci_request_regions() -- if
-	 * we did then setting up MSI-X would fail, since the PCI core
-	 * wants to do request_mem_region on the MSI-X vector table.
+	 * So just request what we need right now, and request any
+	 * other regions we need when setting up EQs.
 	 */
-	if (!request_mem_region(pci_resource_start(pdev, 0) +
-				MTHCA_HCR_BASE,
-				MTHCA_HCR_SIZE,
-				DRV_NAME)) {
-		err = -EBUSY;
-		goto err_hcr_failed;
-	}
-
-	if (!request_mem_region(pci_resource_start(pdev, 0) +
-				MTHCA_ECR_BASE,
-				MTHCA_MAP_ECR_SIZE,
-				DRV_NAME)) {
-		err = -EBUSY;
-		goto err_ecr_failed;
-	}
-
-	if (!request_mem_region(pci_resource_start(pdev, 0) +
-				MTHCA_CLR_INT_BASE,
-				MTHCA_CLR_INT_SIZE,
-				DRV_NAME)) {
-		err = -EBUSY;
-		goto err_int_failed;
-	}
-
+	if (!request_mem_region(pci_resource_start(pdev, 0) + MTHCA_HCR_BASE,
+				MTHCA_HCR_SIZE, DRV_NAME))
+		return -EBUSY;
 
 	err = pci_request_region(pdev, 2, DRV_NAME);
 	if (err)
@@ -731,24 +780,11 @@
 	return 0;
 
 err_bar4_failed:
-
 	pci_release_region(pdev, 2);
-err_bar2_failed:
-
-	release_mem_region(pci_resource_start(pdev, 0) +
-			   MTHCA_CLR_INT_BASE,
-			   MTHCA_CLR_INT_SIZE);
-err_int_failed:
-
-	release_mem_region(pci_resource_start(pdev, 0) +
-			   MTHCA_ECR_BASE,
-			   MTHCA_MAP_ECR_SIZE);
-err_ecr_failed:
 
-	release_mem_region(pci_resource_start(pdev, 0) +
-			   MTHCA_HCR_BASE,
+err_bar2_failed:
+	release_mem_region(pci_resource_start(pdev, 0) + MTHCA_HCR_BASE,
 			   MTHCA_HCR_SIZE);
-err_hcr_failed:
 
 	return err;
 }
@@ -761,16 +797,7 @@
 
 	pci_release_region(pdev, 2);
 
-	release_mem_region(pci_resource_start(pdev, 0) +
-			   MTHCA_CLR_INT_BASE,
-			   MTHCA_CLR_INT_SIZE);
-
-	release_mem_region(pci_resource_start(pdev, 0) +
-			   MTHCA_ECR_BASE,
-			   MTHCA_MAP_ECR_SIZE);
-
-	release_mem_region(pci_resource_start(pdev, 0) +
-			   MTHCA_HCR_BASE,
+	release_mem_region(pci_resource_start(pdev, 0) + MTHCA_HCR_BASE,
 			   MTHCA_HCR_SIZE);
 }
 
@@ -828,9 +855,9 @@
 				    const struct pci_device_id *id)
 {
 	static int mthca_version_printed = 0;
+	static int mthca_memfree_warned = 0;
 	int ddr_hidden = 0;
 	int err;
-	unsigned long mthca_base;
 	struct mthca_dev *mdev;
 
 	if (!mthca_version_printed) {
@@ -908,6 +935,10 @@
 	mdev->pdev     = pdev;
 	mdev->hca_type = id->driver_data;
 
+	if (mdev->hca_type == ARBEL_NATIVE && !mthca_memfree_warned++)
+		mthca_warn(mdev, "Warning: native MT25208 mode support is incomplete.  "
+			   "Your HCA may not work properly.\n");
+
 	if (ddr_hidden)
 		mdev->mthca_flags |= MTHCA_FLAG_DDR_HIDDEN;
 
@@ -932,8 +963,7 @@
 	sema_init(&mdev->cmd.poll_sem, 1);
 	mdev->cmd.use_events = 0;
 
-	mthca_base = pci_resource_start(pdev, 0);
-	mdev->hcr = ioremap(mthca_base + MTHCA_HCR_BASE, MTHCA_HCR_SIZE);
+	mdev->hcr = ioremap(pci_resource_start(pdev, 0) + MTHCA_HCR_BASE, MTHCA_HCR_SIZE);
 	if (!mdev->hcr) {
 		mthca_err(mdev, "Couldn't map command register, "
 			  "aborting.\n");
@@ -941,40 +971,13 @@
 		goto err_free_dev;
 	}
 
-	mdev->clr_base = ioremap(mthca_base + MTHCA_CLR_INT_BASE,
-				 MTHCA_CLR_INT_SIZE);
-	if (!mdev->clr_base) {
-		mthca_err(mdev, "Couldn't map interrupt clear register, "
-			  "aborting.\n");
-		err = -ENOMEM;
-		goto err_iounmap;
-	}
-
-	mdev->ecr_base = ioremap(mthca_base + MTHCA_ECR_BASE,
-				 MTHCA_ECR_SIZE + MTHCA_ECR_CLR_SIZE);
-	if (!mdev->ecr_base) {
-		mthca_err(mdev, "Couldn't map ecr register, "
-			  "aborting.\n");
-		err = -ENOMEM;
-		goto err_iounmap_clr;
-	}
-
-	mthca_base = pci_resource_start(pdev, 2);
-	mdev->kar = ioremap(mthca_base + PAGE_SIZE * MTHCA_KAR_PAGE, PAGE_SIZE);
-	if (!mdev->kar) {
-		mthca_err(mdev, "Couldn't map kernel access region, "
-			  "aborting.\n");
-		err = -ENOMEM;
-		goto err_iounmap_ecr;
-	}
-
 	err = mthca_tune_pci(mdev);
 	if (err)
-		goto err_iounmap_kar;
+		goto err_iounmap;
 
 	err = mthca_init_hca(mdev);
 	if (err)
-		goto err_iounmap_kar;
+		goto err_iounmap;
 
 	err = mthca_setup_hca(mdev);
 	if (err)
@@ -1007,19 +1010,11 @@
 
 	mthca_cleanup_mr_table(mdev);
 	mthca_cleanup_pd_table(mdev);
+	mthca_cleanup_uar_table(mdev);
 
 err_close:
 	mthca_close_hca(mdev);
 
-err_iounmap_kar:
-	iounmap(mdev->kar);
-
-err_iounmap_ecr:
-	iounmap(mdev->ecr_base);
-
-err_iounmap_clr:
-	iounmap(mdev->clr_base);
-
 err_iounmap:
 	iounmap(mdev->hcr);
 
@@ -1065,11 +1060,13 @@
 		mthca_cleanup_mr_table(mdev);
 		mthca_cleanup_pd_table(mdev);
 
+		iounmap(mdev->kar);
+		mthca_uar_free(mdev, &mdev->driver_uar);
+		mthca_cleanup_uar_table(mdev);
+
 		mthca_close_hca(mdev);
 
 		iounmap(mdev->hcr);
-		iounmap(mdev->ecr_base);
-		iounmap(mdev->clr_base);
 
 		if (mdev->mthca_flags & MTHCA_FLAG_MSI_X)
 			pci_disable_msix(pdev);
diff -Nru a/drivers/infiniband/hw/mthca/mthca_memfree.c b/drivers/infiniband/hw/mthca/mthca_memfree.c
--- a/drivers/infiniband/hw/mthca/mthca_memfree.c	2005-03-11 12:51:42 -08:00
+++ b/drivers/infiniband/hw/mthca/mthca_memfree.c	2005-03-11 12:51:42 -08:00
@@ -79,6 +79,7 @@
 	if (!icm)
 		return icm;
 
+	icm->refcount = 0;
 	INIT_LIST_HEAD(&icm->chunk_list);
 
 	cur_order = get_order(MTHCA_ICM_ALLOC_SIZE);
@@ -138,9 +139,62 @@
 	return NULL;
 }
 
+int mthca_table_get(struct mthca_dev *dev, struct mthca_icm_table *table, int obj)
+{
+	int i = (obj & (table->num_obj - 1)) * table->obj_size / MTHCA_TABLE_CHUNK_SIZE;
+	int ret = 0;
+	u8 status;
+
+	down(&table->mutex);
+
+	if (table->icm[i]) {
+		++table->icm[i]->refcount;
+		goto out;
+	}
+
+	table->icm[i] = mthca_alloc_icm(dev, MTHCA_TABLE_CHUNK_SIZE >> PAGE_SHIFT,
+					(table->lowmem ? GFP_KERNEL : GFP_HIGHUSER) |
+					__GFP_NOWARN);
+	if (!table->icm[i]) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	if (mthca_MAP_ICM(dev, table->icm[i], table->virt + i * MTHCA_TABLE_CHUNK_SIZE,
+			  &status) || status) {
+		mthca_free_icm(dev, table->icm[i]);
+		table->icm[i] = NULL;
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	++table->icm[i]->refcount;
+
+out:
+	up(&table->mutex);
+	return ret;
+}
+
+void mthca_table_put(struct mthca_dev *dev, struct mthca_icm_table *table, int obj)
+{
+	int i = (obj & (table->num_obj - 1)) * table->obj_size / MTHCA_TABLE_CHUNK_SIZE;
+	u8 status;
+
+	down(&table->mutex);
+
+	if (--table->icm[i]->refcount == 0) {
+		mthca_UNMAP_ICM(dev, table->virt + i * MTHCA_TABLE_CHUNK_SIZE,
+				MTHCA_TABLE_CHUNK_SIZE >> 12, &status);
+		mthca_free_icm(dev, table->icm[i]);
+		table->icm[i] = NULL;
+	}
+
+	up(&table->mutex);
+}
+
 struct mthca_icm_table *mthca_alloc_icm_table(struct mthca_dev *dev,
-					      u64 virt, unsigned size,
-					      unsigned reserved,
+					      u64 virt, int obj_size,
+					      int nobj, int reserved,
 					      int use_lowmem)
 {
 	struct mthca_icm_table *table;
@@ -148,20 +202,23 @@
 	int i;
 	u8 status;
 
-	num_icm = size / MTHCA_TABLE_CHUNK_SIZE;
+	num_icm = obj_size * nobj / MTHCA_TABLE_CHUNK_SIZE;
 
 	table = kmalloc(sizeof *table + num_icm * sizeof *table->icm, GFP_KERNEL);
 	if (!table)
 		return NULL;
 
-	table->virt    = virt;
-	table->num_icm = num_icm;
-	init_MUTEX(&table->sem);
+	table->virt     = virt;
+	table->num_icm  = num_icm;
+	table->num_obj  = nobj;
+	table->obj_size = obj_size;
+	table->lowmem   = use_lowmem;
+	init_MUTEX(&table->mutex);
 
 	for (i = 0; i < num_icm; ++i)
 		table->icm[i] = NULL;
 
-	for (i = 0; i < (reserved + MTHCA_TABLE_CHUNK_SIZE - 1) / MTHCA_TABLE_CHUNK_SIZE; ++i) {
+	for (i = 0; i * MTHCA_TABLE_CHUNK_SIZE < reserved * obj_size; ++i) {
 		table->icm[i] = mthca_alloc_icm(dev, MTHCA_TABLE_CHUNK_SIZE >> PAGE_SHIFT,
 						(use_lowmem ? GFP_KERNEL : GFP_HIGHUSER) |
 						__GFP_NOWARN);
@@ -173,6 +230,12 @@
 			table->icm[i] = NULL;
 			goto err;
 		}
+
+		/*
+		 * Add a reference to this ICM chunk so that it never
+		 * gets freed (since it contains reserved firmware objects).
+		 */
+		++table->icm[i]->refcount;
 	}
 
 	return table;
@@ -203,4 +266,200 @@
 		}
 
 	kfree(table);
+}
+
+static u64 mthca_uarc_virt(struct mthca_dev *dev, int page)
+{
+	return dev->uar_table.uarc_base +
+		dev->driver_uar.index * dev->uar_table.uarc_size +
+		page * 4096;
+}
+
+int mthca_alloc_db(struct mthca_dev *dev, int type, u32 qn, u32 **db)
+{
+	int group;
+	int start, end, dir;
+	int i, j;
+	struct mthca_db_page *page;
+	int ret = 0;
+	u8 status;
+
+	down(&dev->db_tab->mutex);
+
+	switch (type) {
+	case MTHCA_DB_TYPE_CQ_ARM:
+	case MTHCA_DB_TYPE_SQ:
+		group = 0;
+		start = 0;
+		end   = dev->db_tab->max_group1;
+		dir   = 1;
+		break;
+
+	case MTHCA_DB_TYPE_CQ_SET_CI:
+	case MTHCA_DB_TYPE_RQ:
+	case MTHCA_DB_TYPE_SRQ:
+		group = 1;
+		start = dev->db_tab->npages - 1;
+		end   = dev->db_tab->min_group2;
+		dir   = -1;
+		break;
+
+	default:
+		return -1;
+	}
+
+	for (i = start; i != end; i += dir)
+		if (dev->db_tab->page[i].db_rec &&
+		    !bitmap_full(dev->db_tab->page[i].used,
+				 MTHCA_DB_REC_PER_PAGE)) {
+			page = dev->db_tab->page + i;
+			goto found;
+		}
+
+	if (dev->db_tab->max_group1 >= dev->db_tab->min_group2 - 1) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	page = dev->db_tab->page + end;
+	page->db_rec = dma_alloc_coherent(&dev->pdev->dev, 4096,
+					  &page->mapping, GFP_KERNEL);
+	if (!page->db_rec) {
+		ret = -ENOMEM;
+		goto out;
+	}
+	memset(page->db_rec, 0, 4096);
+
+	ret = mthca_MAP_ICM_page(dev, page->mapping, mthca_uarc_virt(dev, i), &status);
+	if (!ret && status)
+		ret = -EINVAL;
+	if (ret) {
+		dma_free_coherent(&dev->pdev->dev, 4096,
+				  page->db_rec, page->mapping);
+		goto out;
+	}
+
+	bitmap_zero(page->used, MTHCA_DB_REC_PER_PAGE);
+	if (group == 0)
+		++dev->db_tab->max_group1;
+	else
+		--dev->db_tab->min_group2;
+
+found:
+	j = find_first_zero_bit(page->used, MTHCA_DB_REC_PER_PAGE);
+	set_bit(j, page->used);
+
+	if (group == 1)
+		j = MTHCA_DB_REC_PER_PAGE - 1 - j;
+
+	ret = i * MTHCA_DB_REC_PER_PAGE + j;
+
+	page->db_rec[j] = cpu_to_be64((qn << 8) | (type << 5));
+
+	*db = (u32 *) &page->db_rec[j];
+
+out:
+	up(&dev->db_tab->mutex);
+
+	return ret;
+}
+
+void mthca_free_db(struct mthca_dev *dev, int type, int db_index)
+{
+	int i, j;
+	struct mthca_db_page *page;
+	u8 status;
+
+	i = db_index / MTHCA_DB_REC_PER_PAGE;
+	j = db_index % MTHCA_DB_REC_PER_PAGE;
+
+	page = dev->db_tab->page + i;
+
+	down(&dev->db_tab->mutex);
+
+	page->db_rec[j] = 0;
+	if (i >= dev->db_tab->min_group2)
+		j = MTHCA_DB_REC_PER_PAGE - 1 - j;
+	clear_bit(j, page->used);
+
+	if (bitmap_empty(page->used, MTHCA_DB_REC_PER_PAGE) &&
+	    i >= dev->db_tab->max_group1 - 1) {
+		mthca_UNMAP_ICM(dev, mthca_uarc_virt(dev, i), 1, &status);
+
+		dma_free_coherent(&dev->pdev->dev, 4096,
+				  page->db_rec, page->mapping);
+		page->db_rec = NULL;
+
+		if (i == dev->db_tab->max_group1) {
+			--dev->db_tab->max_group1;
+			/* XXX may be able to unmap more pages now */
+		}
+		if (i == dev->db_tab->min_group2)
+			++dev->db_tab->min_group2;
+	}
+
+	up(&dev->db_tab->mutex);
+}
+
+int mthca_init_db_tab(struct mthca_dev *dev)
+{
+	int i;
+
+	if (dev->hca_type != ARBEL_NATIVE)
+		return 0;
+
+	dev->db_tab = kmalloc(sizeof *dev->db_tab, GFP_KERNEL);
+	if (!dev->db_tab)
+		return -ENOMEM;
+
+	init_MUTEX(&dev->db_tab->mutex);
+
+	dev->db_tab->npages     = dev->uar_table.uarc_size / PAGE_SIZE;
+	dev->db_tab->max_group1 = 0;
+	dev->db_tab->min_group2 = dev->db_tab->npages - 1;
+
+	dev->db_tab->page = kmalloc(dev->db_tab->npages *
+				    sizeof *dev->db_tab->page,
+				    GFP_KERNEL);
+	if (!dev->db_tab->page) {
+		kfree(dev->db_tab);
+		return -ENOMEM;
+	}
+
+	for (i = 0; i < dev->db_tab->npages; ++i)
+		dev->db_tab->page[i].db_rec = NULL;
+
+	return 0;
+}
+
+void mthca_cleanup_db_tab(struct mthca_dev *dev)
+{
+	int i;
+	u8 status;
+
+	if (dev->hca_type != ARBEL_NATIVE)
+		return;
+
+	/*
+	 * Because we don't always free our UARC pages when they
+	 * become empty to make mthca_free_db() simpler we need to
+	 * make a sweep through the doorbell pages and free any
+	 * leftover pages now.
+	 */
+	for (i = 0; i < dev->db_tab->npages; ++i) {
+		if (!dev->db_tab->page[i].db_rec)
+			continue;
+
+		if (!bitmap_empty(dev->db_tab->page[i].used, MTHCA_DB_REC_PER_PAGE))
+			mthca_warn(dev, "Kernel UARC page %d not empty\n", i);
+
+		mthca_UNMAP_ICM(dev, mthca_uarc_virt(dev, i), 1, &status);
+
+		dma_free_coherent(&dev->pdev->dev, 4096,
+				  dev->db_tab->page[i].db_rec,
+				  dev->db_tab->page[i].mapping);
+	}
+
+	kfree(dev->db_tab->page);
+	kfree(dev->db_tab);
 }
diff -Nru a/drivers/infiniband/hw/mthca/mthca_memfree.h b/drivers/infiniband/hw/mthca/mthca_memfree.h
--- a/drivers/infiniband/hw/mthca/mthca_memfree.h	2005-03-11 12:51:47 -08:00
+++ b/drivers/infiniband/hw/mthca/mthca_memfree.h	2005-03-11 12:51:47 -08:00
@@ -53,12 +53,16 @@
 
 struct mthca_icm {
 	struct list_head chunk_list;
+	int              refcount;
 };
 
 struct mthca_icm_table {
 	u64               virt;
 	int               num_icm;
-	struct semaphore  sem;
+	int               num_obj;
+	int               obj_size;
+	int               lowmem;
+	struct semaphore  mutex;
 	struct mthca_icm *icm[0];
 };
 
@@ -75,10 +79,12 @@
 void mthca_free_icm(struct mthca_dev *dev, struct mthca_icm *icm);
 
 struct mthca_icm_table *mthca_alloc_icm_table(struct mthca_dev *dev,
-					      u64 virt, unsigned size,
-					      unsigned reserved,
+					      u64 virt, int obj_size,
+					      int nobj, int reserved,
 					      int use_lowmem);
 void mthca_free_icm_table(struct mthca_dev *dev, struct mthca_icm_table *table);
+int mthca_table_get(struct mthca_dev *dev, struct mthca_icm_table *table, int obj);
+void mthca_table_put(struct mthca_dev *dev, struct mthca_icm_table *table, int obj);
 
 static inline void mthca_icm_first(struct mthca_icm *icm,
 				   struct mthca_icm_iter *iter)
@@ -118,5 +124,38 @@
 {
 	return sg_dma_len(&iter->chunk->mem[iter->page_idx]);
 }
+
+enum {
+	MTHCA_DB_REC_PER_PAGE = 4096 / 8
+};
+
+struct mthca_db_page {
+	DECLARE_BITMAP(used, MTHCA_DB_REC_PER_PAGE);
+	u64       *db_rec;
+	dma_addr_t mapping;
+};
+
+struct mthca_db_table {
+	int 	       	      npages;
+	int 	       	      max_group1;
+	int 	       	      min_group2;
+	struct mthca_db_page *page;
+	struct semaphore      mutex;
+};
+
+enum {
+	MTHCA_DB_TYPE_INVALID   = 0x0,
+	MTHCA_DB_TYPE_CQ_SET_CI = 0x1,
+	MTHCA_DB_TYPE_CQ_ARM    = 0x2,
+	MTHCA_DB_TYPE_SQ        = 0x3,
+	MTHCA_DB_TYPE_RQ        = 0x4,
+	MTHCA_DB_TYPE_SRQ       = 0x5,
+	MTHCA_DB_TYPE_GROUP_SEP = 0x7
+};
+
+int mthca_init_db_tab(struct mthca_dev *dev);
+void mthca_cleanup_db_tab(struct mthca_dev *dev);
+int mthca_alloc_db(struct mthca_dev *dev, int type, u32 qn, u32 **db);
+void mthca_free_db(struct mthca_dev *dev, int type, int db_index);
 
 #endif /* MTHCA_MEMFREE_H */
diff -Nru a/drivers/infiniband/hw/mthca/mthca_mr.c b/drivers/infiniband/hw/mthca/mthca_mr.c
--- a/drivers/infiniband/hw/mthca/mthca_mr.c	2005-03-11 12:51:52 -08:00
+++ b/drivers/infiniband/hw/mthca/mthca_mr.c	2005-03-11 12:51:52 -08:00
@@ -53,7 +53,8 @@
 	u32 window_count;
 	u32 window_count_limit;
 	u64 mtt_seg;
-	u32 reserved[3];
+	u32 mtt_sz;		/* Arbel only */
+	u32 reserved[2];
 } __attribute__((packed));
 
 #define MTHCA_MPT_FLAG_SW_OWNS       (0xfUL << 28)
@@ -121,21 +122,38 @@
 	spin_unlock(&dev->mr_table.mpt_alloc.lock);
 }
 
+static inline u32 hw_index_to_key(struct mthca_dev *dev, u32 ind)
+{
+	if (dev->hca_type == ARBEL_NATIVE)
+		return (ind >> 24) | (ind << 8);
+	else
+		return ind;
+}
+
+static inline u32 key_to_hw_index(struct mthca_dev *dev, u32 key)
+{
+	if (dev->hca_type == ARBEL_NATIVE)
+		return (key << 24) | (key >> 8);
+	else
+		return key;
+}
+
 int mthca_mr_alloc_notrans(struct mthca_dev *dev, u32 pd,
 			   u32 access, struct mthca_mr *mr)
 {
 	void *mailbox;
 	struct mthca_mpt_entry *mpt_entry;
+	u32 key;
 	int err;
 	u8 status;
 
 	might_sleep();
 
 	mr->order = -1;
-	mr->ibmr.lkey = mthca_alloc(&dev->mr_table.mpt_alloc);
-	if (mr->ibmr.lkey == -1)
+	key = mthca_alloc(&dev->mr_table.mpt_alloc);
+	if (key == -1)
 		return -ENOMEM;
-	mr->ibmr.rkey = mr->ibmr.lkey;
+	mr->ibmr.rkey = mr->ibmr.lkey = hw_index_to_key(dev, key);
 
 	mailbox = kmalloc(sizeof *mpt_entry + MTHCA_CMD_MAILBOX_EXTRA,
 			  GFP_KERNEL);
@@ -151,7 +169,7 @@
 				       MTHCA_MPT_FLAG_REGION      |
 				       access);
 	mpt_entry->page_size = 0;
-	mpt_entry->key       = cpu_to_be32(mr->ibmr.lkey);
+	mpt_entry->key       = cpu_to_be32(key);
 	mpt_entry->pd        = cpu_to_be32(pd);
 	mpt_entry->start     = 0;
 	mpt_entry->length    = ~0ULL;
@@ -160,7 +178,7 @@
 	       sizeof *mpt_entry - offsetof(struct mthca_mpt_entry, lkey));
 
 	err = mthca_SW2HW_MPT(dev, mpt_entry,
-			      mr->ibmr.lkey & (dev->limits.num_mpts - 1),
+			      key & (dev->limits.num_mpts - 1),
 			      &status);
 	if (err)
 		mthca_warn(dev, "SW2HW_MPT failed (%d)\n", err);
@@ -182,6 +200,7 @@
 	void *mailbox;
 	u64 *mtt_entry;
 	struct mthca_mpt_entry *mpt_entry;
+	u32 key;
 	int err = -ENOMEM;
 	u8 status;
 	int i;
@@ -189,10 +208,10 @@
 	might_sleep();
 	WARN_ON(buffer_size_shift >= 32);
 
-	mr->ibmr.lkey = mthca_alloc(&dev->mr_table.mpt_alloc);
-	if (mr->ibmr.lkey == -1)
+	key = mthca_alloc(&dev->mr_table.mpt_alloc);
+	if (key == -1)
 		return -ENOMEM;
-	mr->ibmr.rkey = mr->ibmr.lkey;
+	mr->ibmr.rkey = mr->ibmr.lkey = hw_index_to_key(dev, key);
 
 	for (i = dev->limits.mtt_seg_size / 8, mr->order = 0;
 	     i < list_len;
@@ -254,7 +273,7 @@
 				       access);
 
 	mpt_entry->page_size = cpu_to_be32(buffer_size_shift - 12);
-	mpt_entry->key       = cpu_to_be32(mr->ibmr.lkey);
+	mpt_entry->key       = cpu_to_be32(key);
 	mpt_entry->pd        = cpu_to_be32(pd);
 	mpt_entry->start     = cpu_to_be64(iova);
 	mpt_entry->length    = cpu_to_be64(total_size);
@@ -275,7 +294,7 @@
 	}
 
 	err = mthca_SW2HW_MPT(dev, mpt_entry,
-			      mr->ibmr.lkey & (dev->limits.num_mpts - 1),
+			      key & (dev->limits.num_mpts - 1),
 			      &status);
 	if (err)
 		mthca_warn(dev, "SW2HW_MPT failed (%d)\n", err);
@@ -307,7 +326,8 @@
 	might_sleep();
 
 	err = mthca_HW2SW_MPT(dev, NULL,
-			      mr->ibmr.lkey & (dev->limits.num_mpts - 1),
+			      key_to_hw_index(dev, mr->ibmr.lkey) &
+			      (dev->limits.num_mpts - 1),
 			      &status);
 	if (err)
 		mthca_warn(dev, "HW2SW_MPT failed (%d)\n", err);
@@ -318,7 +338,7 @@
 	if (mr->order >= 0)
 		mthca_free_mtt(dev, mr->first_seg, mr->order);
 
-	mthca_free(&dev->mr_table.mpt_alloc, mr->ibmr.lkey);
+	mthca_free(&dev->mr_table.mpt_alloc, key_to_hw_index(dev, mr->ibmr.lkey));
 }
 
 int __devinit mthca_init_mr_table(struct mthca_dev *dev)
diff -Nru a/drivers/infiniband/hw/mthca/mthca_profile.c b/drivers/infiniband/hw/mthca/mthca_profile.c
--- a/drivers/infiniband/hw/mthca/mthca_profile.c	2005-03-11 12:51:52 -08:00
+++ b/drivers/infiniband/hw/mthca/mthca_profile.c	2005-03-11 12:51:52 -08:00
@@ -236,15 +236,20 @@
 			init_hca->mtt_seg_sz     = ffs(dev_lim->mtt_seg_sz) - 7;
 			break;
 		case MTHCA_RES_UAR:
+			dev->limits.num_uars       = profile[i].num;
 			init_hca->uar_scratch_base = profile[i].start;
 			break;
 		case MTHCA_RES_UDAV:
 			dev->av_table.ddr_av_base = profile[i].start;
 			dev->av_table.num_ddr_avs = profile[i].num;
+			break;
 		case MTHCA_RES_UARC:
-			init_hca->uarc_base   = profile[i].start;
-			init_hca->log_uarc_sz = ffs(request->uarc_size) - 13;
-			init_hca->log_uar_sz  = ffs(request->num_uar) - 1;
+			dev->uar_table.uarc_size = request->uarc_size;
+			dev->uar_table.uarc_base = profile[i].start;
+			init_hca->uarc_base   	 = profile[i].start;
+			init_hca->log_uarc_sz 	 = ffs(request->uarc_size) - 13;
+			init_hca->log_uar_sz  	 = ffs(request->num_uar) - 1;
+			break;
 		default:
 			break;
 		}
diff -Nru a/drivers/infiniband/hw/mthca/mthca_provider.c b/drivers/infiniband/hw/mthca/mthca_provider.c
--- a/drivers/infiniband/hw/mthca/mthca_provider.c	2005-03-11 12:51:50 -08:00
+++ b/drivers/infiniband/hw/mthca/mthca_provider.c	2005-03-11 12:51:50 -08:00
@@ -43,6 +43,8 @@
 	struct ib_smp *in_mad  = NULL;
 	struct ib_smp *out_mad = NULL;
 	int err = -ENOMEM;
+	struct mthca_dev* mdev = to_mdev(ibdev);
+
 	u8 status;
 
 	in_mad  = kmalloc(sizeof *in_mad, GFP_KERNEL);
@@ -50,7 +52,7 @@
 	if (!in_mad || !out_mad)
 		goto out;
 
-	props->fw_ver        = to_mdev(ibdev)->fw_ver;
+	props->fw_ver              = mdev->fw_ver;
 
 	memset(in_mad, 0, sizeof *in_mad);
 	in_mad->base_version       = 1;
@@ -59,7 +61,7 @@
 	in_mad->method         	   = IB_MGMT_METHOD_GET;
 	in_mad->attr_id   	   = IB_SMP_ATTR_NODE_INFO;
 
-	err = mthca_MAD_IFC(to_mdev(ibdev), 1, 1,
+	err = mthca_MAD_IFC(mdev, 1, 1,
 			    1, NULL, NULL, in_mad, out_mad,
 			    &status);
 	if (err)
@@ -69,10 +71,11 @@
 		goto out;
 	}
 
-	props->vendor_id      = be32_to_cpup((u32 *) (out_mad->data + 36)) &
+	props->device_cap_flags = mdev->device_cap_flags;
+	props->vendor_id        = be32_to_cpup((u32 *) (out_mad->data + 36)) &
 		0xffffff;
-	props->vendor_part_id = be16_to_cpup((u16 *) (out_mad->data + 30));
-	props->hw_ver         = be16_to_cpup((u16 *) (out_mad->data + 32));
+	props->vendor_part_id   = be16_to_cpup((u16 *) (out_mad->data + 30));
+	props->hw_ver           = be16_to_cpup((u16 *) (out_mad->data + 32));
 	memcpy(&props->sys_image_guid, out_mad->data +  4, 8);
 	memcpy(&props->node_guid,      out_mad->data + 12, 8);
 
@@ -343,7 +346,7 @@
 				     to_mcq(init_attr->send_cq),
 				     to_mcq(init_attr->recv_cq),
 				     init_attr->qp_type, init_attr->sq_sig_type,
-				     init_attr->rq_sig_type, qp);
+				     qp);
 		qp->ibqp.qp_num = qp->qpn;
 		break;
 	}
@@ -364,7 +367,7 @@
 		err = mthca_alloc_sqp(to_mdev(pd->device), to_mpd(pd),
 				      to_mcq(init_attr->send_cq),
 				      to_mcq(init_attr->recv_cq),
-				      init_attr->sq_sig_type, init_attr->rq_sig_type,
+				      init_attr->sq_sig_type,
 				      qp->ibqp.qp_num, init_attr->port_num,
 				      to_msqp(qp));
 		break;
@@ -408,8 +411,7 @@
 	if (err) {
 		kfree(cq);
 		cq = ERR_PTR(err);
-	} else
-		cq->ibcq.cqe = nent - 1;
+	}
 
 	return &cq->ibcq;
 }
@@ -422,13 +424,6 @@
 	return 0;
 }
 
-static int mthca_req_notify_cq(struct ib_cq *cq, enum ib_cq_notify notify)
-{
-	mthca_arm_cq(to_mdev(cq->device), to_mcq(cq),
-		     notify == IB_CQ_SOLICITED);
-	return 0;
-}
-
 static inline u32 convert_access(int acc)
 {
 	return (acc & IB_ACCESS_REMOTE_ATOMIC ? MTHCA_MPT_FLAG_ATOMIC       : 0) |
@@ -621,18 +616,25 @@
 	dev->ib_dev.create_qp            = mthca_create_qp;
 	dev->ib_dev.modify_qp            = mthca_modify_qp;
 	dev->ib_dev.destroy_qp           = mthca_destroy_qp;
-	dev->ib_dev.post_send            = mthca_post_send;
-	dev->ib_dev.post_recv            = mthca_post_receive;
 	dev->ib_dev.create_cq            = mthca_create_cq;
 	dev->ib_dev.destroy_cq           = mthca_destroy_cq;
 	dev->ib_dev.poll_cq              = mthca_poll_cq;
-	dev->ib_dev.req_notify_cq        = mthca_req_notify_cq;
 	dev->ib_dev.get_dma_mr           = mthca_get_dma_mr;
 	dev->ib_dev.reg_phys_mr          = mthca_reg_phys_mr;
 	dev->ib_dev.dereg_mr             = mthca_dereg_mr;
 	dev->ib_dev.attach_mcast         = mthca_multicast_attach;
 	dev->ib_dev.detach_mcast         = mthca_multicast_detach;
 	dev->ib_dev.process_mad          = mthca_process_mad;
+
+	if (dev->hca_type == ARBEL_NATIVE) {
+		dev->ib_dev.req_notify_cq = mthca_arbel_arm_cq;
+		dev->ib_dev.post_send     = mthca_arbel_post_send;
+		dev->ib_dev.post_recv     = mthca_arbel_post_receive;
+	} else {
+		dev->ib_dev.req_notify_cq = mthca_tavor_arm_cq;
+		dev->ib_dev.post_send     = mthca_tavor_post_send;
+		dev->ib_dev.post_recv     = mthca_tavor_post_receive;
+	}
 
 	init_MUTEX(&dev->cap_mask_mutex);
 
diff -Nru a/drivers/infiniband/hw/mthca/mthca_provider.h b/drivers/infiniband/hw/mthca/mthca_provider.h
--- a/drivers/infiniband/hw/mthca/mthca_provider.h	2005-03-11 12:51:42 -08:00
+++ b/drivers/infiniband/hw/mthca/mthca_provider.h	2005-03-11 12:51:42 -08:00
@@ -49,6 +49,11 @@
 	DECLARE_PCI_UNMAP_ADDR(mapping)
 };
 
+struct mthca_uar {
+	unsigned long pfn;
+	int           index;
+};
+
 struct mthca_mr {
 	struct ib_mr ibmr;
 	int order;
@@ -65,7 +70,7 @@
 struct mthca_eq {
 	struct mthca_dev      *dev;
 	int                    eqn;
-	u32                    ecr_mask;
+	u32                    eqn_mask;
 	u32                    cons_index;
 	u16                    msi_x_vector;
 	u16                    msi_x_entry;
@@ -77,12 +82,18 @@
 
 struct mthca_av;
 
+enum mthca_ah_type {
+	MTHCA_AH_ON_HCA,
+	MTHCA_AH_PCI_POOL,
+	MTHCA_AH_KMALLOC
+};
+
 struct mthca_ah {
-	struct ib_ah     ibah;
-	int              on_hca;
-	u32              key;
-	struct mthca_av *av;
-	dma_addr_t       avdma;
+	struct ib_ah       ibah;
+	enum mthca_ah_type type;
+	u32                key;
+	struct mthca_av   *av;
+	dma_addr_t         avdma;
 };
 
 /*
@@ -136,8 +147,16 @@
 	spinlock_t             lock;
 	atomic_t               refcount;
 	int                    cqn;
-	int                    cons_index;
+	u32                    cons_index;
 	int                    is_direct;
+
+	/* Next fields are Arbel only */
+	int                    set_ci_db_index;
+	u32                   *set_ci_db;
+	int                    arm_db_index;
+	u32                   *arm_db;
+	int                    arm_sn;
+
 	union {
 		struct mthca_buf_list direct;
 		struct mthca_buf_list *page_list;
@@ -147,19 +166,22 @@
 };
 
 struct mthca_wq {
-	int   max;
-	int   cur;
-	int   next;
-	int   last_comp;
-	void *last;
-	int   max_gs;
-	int   wqe_shift;
-	enum ib_sig_type policy;
+	spinlock_t lock;
+	int        max;
+	unsigned   next_ind;
+	unsigned   last_comp;
+	unsigned   head;
+	unsigned   tail;
+	void      *last;
+	int        max_gs;
+	int        wqe_shift;
+
+	int        db_index;	/* Arbel only */
+	u32       *db;
 };
 
 struct mthca_qp {
 	struct ib_qp           ibqp;
-	spinlock_t             lock;
 	atomic_t               refcount;
 	u32                    qpn;
 	int                    is_direct;
@@ -172,6 +194,7 @@
 
 	struct mthca_wq        rq;
 	struct mthca_wq        sq;
+	enum ib_sig_type       sq_policy;
 	int                    send_wqe_offset;
 
 	u64                   *wrid;
diff -Nru a/drivers/infiniband/hw/mthca/mthca_qp.c b/drivers/infiniband/hw/mthca/mthca_qp.c
--- a/drivers/infiniband/hw/mthca/mthca_qp.c	2005-03-11 12:51:41 -08:00
+++ b/drivers/infiniband/hw/mthca/mthca_qp.c	2005-03-11 12:51:41 -08:00
@@ -40,6 +40,7 @@
 
 #include "mthca_dev.h"
 #include "mthca_cmd.h"
+#include "mthca_memfree.h"
 
 enum {
 	MTHCA_MAX_DIRECT_QP_SIZE = 4 * PAGE_SIZE,
@@ -105,8 +106,11 @@
 
 struct mthca_qp_context {
 	u32 flags;
-	u32 sched_queue;
-	u32 mtu_msgmax;
+	u32 tavor_sched_queue;	/* Reserved on Arbel */
+	u8  mtu_msgmax;
+	u8  rq_size_stride;	/* Reserved on Tavor */
+	u8  sq_size_stride;	/* Reserved on Tavor */
+	u8  rlkey_arbel_sched_queue;	/* Reserved on Tavor */
 	u32 usr_page;
 	u32 local_qpn;
 	u32 remote_qpn;
@@ -121,18 +125,22 @@
 	u32 reserved2;
 	u32 next_send_psn;
 	u32 cqn_snd;
-	u32 next_snd_wqe[2];
+	u32 snd_wqe_base_l;	/* Next send WQE on Tavor */
+	u32 snd_db_index;	/* (debugging only entries) */
 	u32 last_acked_psn;
 	u32 ssn;
 	u32 params2;
 	u32 rnr_nextrecvpsn;
 	u32 ra_buff_indx;
 	u32 cqn_rcv;
-	u32 next_rcv_wqe[2];
+	u32 rcv_wqe_base_l;	/* Next recv WQE on Tavor */
+	u32 rcv_db_index;	/* (debugging only entries) */
 	u32 qkey;
 	u32 srqn;
 	u32 rmsn;
-	u32 reserved3[19];
+	u16 rq_wqe_counter;	/* reserved on Tavor */
+	u16 sq_wqe_counter;	/* reserved on Tavor */
+	u32 reserved3[18];
 } __attribute__((packed));
 
 struct mthca_qp_param {
@@ -193,7 +201,7 @@
 	u32 imm;		/* immediate data */
 };
 
-struct mthca_ud_seg {
+struct mthca_tavor_ud_seg {
 	u32 reserved1;
 	u32 lkey;
 	u64 av_addr;
@@ -203,6 +211,13 @@
 	u32 reserved3[2];
 };
 
+struct mthca_arbel_ud_seg {
+	u32 av[8];
+	u32 dqpn;
+	u32 qkey;
+	u32 reserved[2];
+};
+
 struct mthca_bind_seg {
 	u32 flags;		/* [31] Atomic [30] rem write [29] rem read */
 	u32 reserved;
@@ -238,6 +253,16 @@
 	u16 vcrc;
 };
 
+static const u8 mthca_opcode[] = {
+	[IB_WR_SEND]                 = MTHCA_OPCODE_SEND,
+	[IB_WR_SEND_WITH_IMM]        = MTHCA_OPCODE_SEND_IMM,
+	[IB_WR_RDMA_WRITE]           = MTHCA_OPCODE_RDMA_WRITE,
+	[IB_WR_RDMA_WRITE_WITH_IMM]  = MTHCA_OPCODE_RDMA_WRITE_IMM,
+	[IB_WR_RDMA_READ]            = MTHCA_OPCODE_RDMA_READ,
+	[IB_WR_ATOMIC_CMP_AND_SWP]   = MTHCA_OPCODE_ATOMIC_CS,
+	[IB_WR_ATOMIC_FETCH_AND_ADD] = MTHCA_OPCODE_ATOMIC_FA,
+};
+
 static int is_sqp(struct mthca_dev *dev, struct mthca_qp *qp)
 {
 	return qp->qpn >= dev->qp_table.sqp_start &&
@@ -552,9 +577,11 @@
 		else
 			cur_state = attr->cur_qp_state;
 	} else {
-		spin_lock_irq(&qp->lock);
+		spin_lock_irq(&qp->sq.lock);
+		spin_lock(&qp->rq.lock);
 		cur_state = qp->state;
-		spin_unlock_irq(&qp->lock);
+		spin_unlock(&qp->rq.lock);
+		spin_unlock_irq(&qp->sq.lock);
 	}
 
 	if (attr_mask & IB_QP_STATE) {
@@ -617,15 +644,24 @@
 			break;
 		}
 	}
-	/* leave sched_queue as 0 */
+
+	/* leave tavor_sched_queue as 0 */
+
 	if (qp->transport == MLX || qp->transport == UD)
-		qp_context->mtu_msgmax = cpu_to_be32((IB_MTU_2048 << 29) |
-						     (11 << 24));
-	else if (attr_mask & IB_QP_PATH_MTU) {
-		qp_context->mtu_msgmax = cpu_to_be32((attr->path_mtu << 29) |
-						     (31 << 24));
+		qp_context->mtu_msgmax = (IB_MTU_2048 << 5) | 11;
+	else if (attr_mask & IB_QP_PATH_MTU)
+		qp_context->mtu_msgmax = (attr->path_mtu << 5) | 31;
+
+	if (dev->hca_type == ARBEL_NATIVE) {
+		qp_context->rq_size_stride =
+			((ffs(qp->rq.max) - 1) << 3) | (qp->rq.wqe_shift - 4);
+		qp_context->sq_size_stride =
+			((ffs(qp->sq.max) - 1) << 3) | (qp->sq.wqe_shift - 4);
 	}
-	qp_context->usr_page   = cpu_to_be32(MTHCA_KAR_PAGE);
+
+	/* leave arbel_sched_queue as 0 */
+
+	qp_context->usr_page   = cpu_to_be32(dev->driver_uar.index);
 	qp_context->local_qpn  = cpu_to_be32(qp->qpn);
 	if (attr_mask & IB_QP_DEST_QPN) {
 		qp_context->remote_qpn = cpu_to_be32(attr->dest_qp_num);
@@ -690,7 +726,7 @@
 					     MTHCA_QP_BIT_SRE           |
 					     MTHCA_QP_BIT_SWE           |
 					     MTHCA_QP_BIT_SAE);
-	if (qp->sq.policy == IB_SIGNAL_ALL_WR)
+	if (qp->sq_policy == IB_SIGNAL_ALL_WR)
 		qp_context->params1 |= cpu_to_be32(MTHCA_QP_BIT_SSC);
 	if (attr_mask & IB_QP_RETRY_CNT) {
 		qp_context->params1 |= cpu_to_be32(attr->retry_cnt << 16);
@@ -708,6 +744,11 @@
 		qp_context->next_send_psn = cpu_to_be32(attr->sq_psn);
 	qp_context->cqn_snd = cpu_to_be32(to_mcq(ibqp->send_cq)->cqn);
 
+	if (dev->hca_type == ARBEL_NATIVE) {
+		qp_context->snd_wqe_base_l = cpu_to_be32(qp->send_wqe_offset);
+		qp_context->snd_db_index   = cpu_to_be32(qp->sq.db_index);
+	}
+
 	if (attr_mask & IB_QP_ACCESS_FLAGS) {
 		/*
 		 * Only enable RDMA/atomics if we have responder
@@ -778,8 +819,8 @@
 		qp->resp_depth = attr->max_rd_atomic;
 	}
 
-	if (qp->rq.policy == IB_SIGNAL_ALL_WR)
-		qp_context->params2 |= cpu_to_be32(MTHCA_QP_BIT_RSC);
+	qp_context->params2 |= cpu_to_be32(MTHCA_QP_BIT_RSC);
+
 	if (attr_mask & IB_QP_MIN_RNR_TIMER) {
 		qp_context->rnr_nextrecvpsn |= cpu_to_be32(attr->min_rnr_timer << 24);
 		qp_param->opt_param_mask |= cpu_to_be32(MTHCA_QP_OPTPAR_RNR_TIMEOUT);
@@ -787,12 +828,16 @@
 	if (attr_mask & IB_QP_RQ_PSN)
 		qp_context->rnr_nextrecvpsn |= cpu_to_be32(attr->rq_psn);
 
-	qp_context->ra_buff_indx = dev->qp_table.rdb_base +
-		((qp->qpn & (dev->limits.num_qps - 1)) * MTHCA_RDB_ENTRY_SIZE <<
-		 dev->qp_table.rdb_shift);
+	qp_context->ra_buff_indx =
+		cpu_to_be32(dev->qp_table.rdb_base +
+			    ((qp->qpn & (dev->limits.num_qps - 1)) * MTHCA_RDB_ENTRY_SIZE <<
+			     dev->qp_table.rdb_shift));
 
 	qp_context->cqn_rcv = cpu_to_be32(to_mcq(ibqp->recv_cq)->cqn);
 
+	if (dev->hca_type == ARBEL_NATIVE)
+		qp_context->rcv_db_index   = cpu_to_be32(qp->rq.db_index);
+
 	if (attr_mask & IB_QP_QKEY) {
 		qp_context->qkey = cpu_to_be32(attr->qkey);
 		qp_param->opt_param_mask |= cpu_to_be32(MTHCA_QP_OPTPAR_Q_KEY);
@@ -860,12 +905,20 @@
 
 	size = sizeof (struct mthca_next_seg) +
 		qp->sq.max_gs * sizeof (struct mthca_data_seg);
-	if (qp->transport == MLX)
+	switch (qp->transport) {
+	case MLX:
 		size += 2 * sizeof (struct mthca_data_seg);
-	else if (qp->transport == UD)
-		size += sizeof (struct mthca_ud_seg);
-	else /* bind seg is as big as atomic + raddr segs */
+		break;
+	case UD:
+		if (dev->hca_type == ARBEL_NATIVE)
+			size += sizeof (struct mthca_arbel_ud_seg);
+		else
+			size += sizeof (struct mthca_tavor_ud_seg);
+		break;
+	default:
+		/* bind seg is as big as atomic + raddr segs */
 		size += sizeof (struct mthca_bind_seg);
+	}
 
 	for (qp->sq.wqe_shift = 6; 1 << qp->sq.wqe_shift < size;
 	     qp->sq.wqe_shift++)
@@ -942,7 +995,6 @@
 
 	err = mthca_mr_alloc_phys(dev, pd->pd_num, dma_list, shift,
 				  npages, 0, size,
-				  MTHCA_MPT_FLAG_LOCAL_WRITE |
 				  MTHCA_MPT_FLAG_LOCAL_READ,
 				  &qp->mr);
 	if (err)
@@ -972,34 +1024,134 @@
 	return err;
 }
 
+static int mthca_alloc_memfree(struct mthca_dev *dev,
+			       struct mthca_qp *qp)
+{
+	int ret = 0;
+
+	if (dev->hca_type == ARBEL_NATIVE) {
+		ret = mthca_table_get(dev, dev->qp_table.qp_table, qp->qpn);
+		if (ret)
+			return ret;
+
+		ret = mthca_table_get(dev, dev->qp_table.eqp_table, qp->qpn);
+		if (ret)
+			goto err_qpc;
+
+		qp->rq.db_index = mthca_alloc_db(dev, MTHCA_DB_TYPE_RQ,
+						 qp->qpn, &qp->rq.db);
+		if (qp->rq.db_index < 0) {
+			ret = -ENOMEM;
+			goto err_eqpc;
+		}
+
+		qp->sq.db_index = mthca_alloc_db(dev, MTHCA_DB_TYPE_SQ,
+						 qp->qpn, &qp->sq.db);
+		if (qp->sq.db_index < 0) {
+			ret = -ENOMEM;
+			goto err_rq_db;
+		}
+	}
+
+	return 0;
+
+err_rq_db:
+	mthca_free_db(dev, MTHCA_DB_TYPE_RQ, qp->rq.db_index);
+
+err_eqpc:
+	mthca_table_put(dev, dev->qp_table.eqp_table, qp->qpn);
+
+err_qpc:
+	mthca_table_put(dev, dev->qp_table.qp_table, qp->qpn);
+
+	return ret;
+}
+
+static void mthca_free_memfree(struct mthca_dev *dev,
+			       struct mthca_qp *qp)
+{
+	if (dev->hca_type == ARBEL_NATIVE) {
+		mthca_free_db(dev, MTHCA_DB_TYPE_SQ, qp->sq.db_index);
+		mthca_free_db(dev, MTHCA_DB_TYPE_RQ, qp->rq.db_index);
+		mthca_table_put(dev, dev->qp_table.eqp_table, qp->qpn);
+		mthca_table_put(dev, dev->qp_table.qp_table, qp->qpn);
+	}
+}
+
+static void mthca_wq_init(struct mthca_wq* wq)
+{
+	spin_lock_init(&wq->lock);
+	wq->next_ind  = 0;
+	wq->last_comp = wq->max - 1;
+	wq->head      = 0;
+	wq->tail      = 0;
+	wq->last      = NULL;
+}
+
 static int mthca_alloc_qp_common(struct mthca_dev *dev,
 				 struct mthca_pd *pd,
 				 struct mthca_cq *send_cq,
 				 struct mthca_cq *recv_cq,
 				 enum ib_sig_type send_policy,
-				 enum ib_sig_type recv_policy,
 				 struct mthca_qp *qp)
 {
-	int err;
+	struct mthca_next_seg *wqe;
+	int ret;
+	int i;
 
-	spin_lock_init(&qp->lock);
 	atomic_set(&qp->refcount, 1);
 	qp->state    	 = IB_QPS_RESET;
 	qp->atomic_rd_en = 0;
 	qp->resp_depth   = 0;
-	qp->sq.policy    = send_policy;
-	qp->rq.policy    = recv_policy;
-	qp->rq.cur       = 0;
-	qp->sq.cur       = 0;
-	qp->rq.next      = 0;
-	qp->sq.next      = 0;
-	qp->rq.last_comp = qp->rq.max - 1;
-	qp->sq.last_comp = qp->sq.max - 1;
-	qp->rq.last      = NULL;
-	qp->sq.last      = NULL;
+	qp->sq_policy    = send_policy;
+	mthca_wq_init(&qp->sq);
+	mthca_wq_init(&qp->rq);
+
+	ret = mthca_alloc_memfree(dev, qp);
+	if (ret)
+		return ret;
+
+	ret = mthca_alloc_wqe_buf(dev, pd, qp);
+	if (ret) {
+		mthca_free_memfree(dev, qp);
+		return ret;
+	}
+
+	if (dev->hca_type == ARBEL_NATIVE) {
+		for (i = 0; i < qp->rq.max; ++i) {
+			wqe = get_recv_wqe(qp, i);
+			wqe->nda_op = cpu_to_be32(((i + 1) & (qp->rq.max - 1)) <<
+						  qp->rq.wqe_shift);
+			wqe->ee_nds = cpu_to_be32(1 << (qp->rq.wqe_shift - 4));
+		}
+
+		for (i = 0; i < qp->sq.max; ++i) {
+			wqe = get_send_wqe(qp, i);
+			wqe->nda_op = cpu_to_be32((((i + 1) & (qp->sq.max - 1)) <<
+						   qp->sq.wqe_shift) +
+						  qp->send_wqe_offset);
+		}
+	}
 
-	err = mthca_alloc_wqe_buf(dev, pd, qp);
-	return err;
+	return 0;
+}
+
+static void mthca_align_qp_size(struct mthca_dev *dev, struct mthca_qp *qp)
+{
+	int i;
+
+	if (dev->hca_type != ARBEL_NATIVE)
+		return;
+
+	for (i = 0; 1 << i < qp->rq.max; ++i)
+		; /* nothing */
+
+	qp->rq.max = 1 << i;
+
+	for (i = 0; 1 << i < qp->sq.max; ++i)
+		; /* nothing */
+
+	qp->sq.max = 1 << i;
 }
 
 int mthca_alloc_qp(struct mthca_dev *dev,
@@ -1008,11 +1160,12 @@
 		   struct mthca_cq *recv_cq,
 		   enum ib_qp_type type,
 		   enum ib_sig_type send_policy,
-		   enum ib_sig_type recv_policy,
 		   struct mthca_qp *qp)
 {
 	int err;
 
+	mthca_align_qp_size(dev, qp);
+
 	switch (type) {
 	case IB_QPT_RC: qp->transport = RC; break;
 	case IB_QPT_UC: qp->transport = UC; break;
@@ -1025,7 +1178,7 @@
 		return -ENOMEM;
 
 	err = mthca_alloc_qp_common(dev, pd, send_cq, recv_cq,
-				    send_policy, recv_policy, qp);
+				    send_policy, qp);
 	if (err) {
 		mthca_free(&dev->qp_table.alloc, qp->qpn);
 		return err;
@@ -1044,7 +1197,6 @@
 		    struct mthca_cq *send_cq,
 		    struct mthca_cq *recv_cq,
 		    enum ib_sig_type send_policy,
-		    enum ib_sig_type recv_policy,
 		    int qpn,
 		    int port,
 		    struct mthca_sqp *sqp)
@@ -1052,6 +1204,8 @@
 	int err = 0;
 	u32 mqpn = qpn * 2 + dev->qp_table.sqp_start + port - 1;
 
+	mthca_align_qp_size(dev, &sqp->qp);
+
 	sqp->header_buf_size = sqp->qp.sq.max * MTHCA_UD_HEADER_SIZE;
 	sqp->header_buf = dma_alloc_coherent(&dev->pdev->dev, sqp->header_buf_size,
 					     &sqp->header_dma, GFP_KERNEL);
@@ -1073,8 +1227,7 @@
 	sqp->qp.transport = MLX;
 
 	err = mthca_alloc_qp_common(dev, pd, send_cq, recv_cq,
-				    send_policy, recv_policy,
-				    &sqp->qp);
+				    send_policy, &sqp->qp);
 	if (err)
 		goto err_out_free;
 
@@ -1083,9 +1236,21 @@
 	return 0;
 
  err_out_free:
-	spin_lock_irq(&dev->qp_table.lock);
+	/*
+	 * Lock CQs here, so that CQ polling code can do QP lookup
+	 * without taking a lock.
+	 */
+	spin_lock_irq(&send_cq->lock);
+	if (send_cq != recv_cq)
+		spin_lock(&recv_cq->lock);
+
+	spin_lock(&dev->qp_table.lock);
 	mthca_array_clear(&dev->qp_table.qp, mqpn);
-	spin_unlock_irq(&dev->qp_table.lock);
+	spin_unlock(&dev->qp_table.lock);
+
+	if (send_cq != recv_cq)
+		spin_unlock(&recv_cq->lock);
+	spin_unlock_irq(&send_cq->lock);
 
  err_out:
 	dma_free_coherent(&dev->pdev->dev, sqp->header_buf_size,
@@ -1100,11 +1265,28 @@
 	u8 status;
 	int size;
 	int i;
+	struct mthca_cq *send_cq;
+	struct mthca_cq *recv_cq;
 
-	spin_lock_irq(&dev->qp_table.lock);
+	send_cq = to_mcq(qp->ibqp.send_cq);
+	recv_cq = to_mcq(qp->ibqp.recv_cq);
+
+	/*
+	 * Lock CQs here, so that CQ polling code can do QP lookup
+	 * without taking a lock.
+	 */
+	spin_lock_irq(&send_cq->lock);
+	if (send_cq != recv_cq)
+		spin_lock(&recv_cq->lock);
+
+	spin_lock(&dev->qp_table.lock);
 	mthca_array_clear(&dev->qp_table.qp,
 			  qp->qpn & (dev->limits.num_qps - 1));
-	spin_unlock_irq(&dev->qp_table.lock);
+	spin_unlock(&dev->qp_table.lock);
+
+	if (send_cq != recv_cq)
+		spin_unlock(&recv_cq->lock);
+	spin_unlock_irq(&send_cq->lock);
 
 	atomic_dec(&qp->refcount);
 	wait_event(qp->wait, !atomic_read(&qp->refcount));
@@ -1136,14 +1318,15 @@
 
 	kfree(qp->wrid);
 
+	mthca_free_memfree(dev, qp);
+
 	if (is_sqp(dev, qp)) {
 		atomic_dec(&(to_mpd(qp->ibqp.pd)->sqp_count));
 		dma_free_coherent(&dev->pdev->dev,
 				  to_msqp(qp)->header_buf_size,
 				  to_msqp(qp)->header_buf,
 				  to_msqp(qp)->header_dma);
-	}
-	else
+	} else
 		mthca_free(&dev->qp_table.alloc, qp->qpn);
 }
 
@@ -1216,8 +1399,26 @@
 	return 0;
 }
 
-int mthca_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
-		    struct ib_send_wr **bad_wr)
+static inline int mthca_wq_overflow(struct mthca_wq *wq, int nreq,
+				    struct ib_cq *ib_cq)
+{
+	unsigned cur;
+	struct mthca_cq *cq;
+
+	cur = wq->head - wq->tail;
+	if (likely(cur + nreq < wq->max))
+		return 0;
+
+	cq = to_mcq(ib_cq);
+	spin_lock(&cq->lock);
+	cur = wq->head - wq->tail;
+	spin_unlock(&cq->lock);
+
+	return cur + nreq >= wq->max;
+}
+
+int mthca_tavor_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
+			  struct ib_send_wr **bad_wr)
 {
 	struct mthca_dev *dev = to_mdev(ibqp->device);
 	struct mthca_qp *qp = to_mqp(ibqp);
@@ -1233,26 +1434,18 @@
 	int ind;
 	u8 op0 = 0;
 
-	static const u8 opcode[] = {
-		[IB_WR_SEND]                 = MTHCA_OPCODE_SEND,
-		[IB_WR_SEND_WITH_IMM]        = MTHCA_OPCODE_SEND_IMM,
-		[IB_WR_RDMA_WRITE]           = MTHCA_OPCODE_RDMA_WRITE,
-		[IB_WR_RDMA_WRITE_WITH_IMM]  = MTHCA_OPCODE_RDMA_WRITE_IMM,
-		[IB_WR_RDMA_READ]            = MTHCA_OPCODE_RDMA_READ,
-		[IB_WR_ATOMIC_CMP_AND_SWP]   = MTHCA_OPCODE_ATOMIC_CS,
-		[IB_WR_ATOMIC_FETCH_AND_ADD] = MTHCA_OPCODE_ATOMIC_FA,
-	};
-
-	spin_lock_irqsave(&qp->lock, flags);
+	spin_lock_irqsave(&qp->sq.lock, flags);
 
 	/* XXX check that state is OK to post send */
 
-	ind = qp->sq.next;
+	ind = qp->sq.next_ind;
 
 	for (nreq = 0; wr; ++nreq, wr = wr->next) {
-		if (qp->sq.cur + nreq >= qp->sq.max) {
-			mthca_err(dev, "SQ full (%d posted, %d max, %d nreq)\n",
-				  qp->sq.cur, qp->sq.max, nreq);
+		if (mthca_wq_overflow(&qp->sq, nreq, qp->ibqp.send_cq)) {
+			mthca_err(dev, "SQ %06x full (%u head, %u tail,"
+					" %d max, %d nreq)\n", qp->qpn,
+					qp->sq.head, qp->sq.tail,
+					qp->sq.max, nreq);
 			err = -ENOMEM;
 			*bad_wr = wr;
 			goto out;
@@ -1326,17 +1519,17 @@
 			break;
 
 		case UD:
-			((struct mthca_ud_seg *) wqe)->lkey =
+			((struct mthca_tavor_ud_seg *) wqe)->lkey =
 				cpu_to_be32(to_mah(wr->wr.ud.ah)->key);
-			((struct mthca_ud_seg *) wqe)->av_addr =
+			((struct mthca_tavor_ud_seg *) wqe)->av_addr =
 				cpu_to_be64(to_mah(wr->wr.ud.ah)->avdma);
-			((struct mthca_ud_seg *) wqe)->dqpn =
+			((struct mthca_tavor_ud_seg *) wqe)->dqpn =
 				cpu_to_be32(wr->wr.ud.remote_qpn);
-			((struct mthca_ud_seg *) wqe)->qkey =
+			((struct mthca_tavor_ud_seg *) wqe)->qkey =
 				cpu_to_be32(wr->wr.ud.remote_qkey);
 
-			wqe += sizeof (struct mthca_ud_seg);
-			size += sizeof (struct mthca_ud_seg) / 16;
+			wqe += sizeof (struct mthca_tavor_ud_seg);
+			size += sizeof (struct mthca_tavor_ud_seg) / 16;
 			break;
 
 		case MLX:
@@ -1381,7 +1574,7 @@
 
 		qp->wrid[ind + qp->rq.max] = wr->wr_id;
 
-		if (wr->opcode >= ARRAY_SIZE(opcode)) {
+		if (wr->opcode >= ARRAY_SIZE(mthca_opcode)) {
 			mthca_err(dev, "opcode invalid\n");
 			err = -EINVAL;
 			*bad_wr = wr;
@@ -1392,15 +1585,15 @@
 			((struct mthca_next_seg *) prev_wqe)->nda_op =
 				cpu_to_be32(((ind << qp->sq.wqe_shift) +
 					     qp->send_wqe_offset) |
-					    opcode[wr->opcode]);
-			smp_wmb();
+					    mthca_opcode[wr->opcode]);
+			wmb();
 			((struct mthca_next_seg *) prev_wqe)->ee_nds =
 				cpu_to_be32((size0 ? 0 : MTHCA_NEXT_DBD) | size);
 		}
 
 		if (!size0) {
 			size0 = size;
-			op0   = opcode[wr->opcode];
+			op0   = mthca_opcode[wr->opcode];
 		}
 
 		++ind;
@@ -1409,10 +1602,10 @@
 	}
 
 out:
-	if (nreq) {
+	if (likely(nreq)) {
 		u32 doorbell[2];
 
-		doorbell[0] = cpu_to_be32(((qp->sq.next << qp->sq.wqe_shift) +
+		doorbell[0] = cpu_to_be32(((qp->sq.next_ind << qp->sq.wqe_shift) +
 					   qp->send_wqe_offset) | f0 | op0);
 		doorbell[1] = cpu_to_be32((qp->qpn << 8) | size0);
 
@@ -1423,15 +1616,15 @@
 			      MTHCA_GET_DOORBELL_LOCK(&dev->doorbell_lock));
 	}
 
-	qp->sq.cur += nreq;
-	qp->sq.next = ind;
+	qp->sq.next_ind = ind;
+	qp->sq.head    += nreq;
 
-	spin_unlock_irqrestore(&qp->lock, flags);
+	spin_unlock_irqrestore(&qp->sq.lock, flags);
 	return err;
 }
 
-int mthca_post_receive(struct ib_qp *ibqp, struct ib_recv_wr *wr,
-		       struct ib_recv_wr **bad_wr)
+int mthca_tavor_post_receive(struct ib_qp *ibqp, struct ib_recv_wr *wr,
+			     struct ib_recv_wr **bad_wr)
 {
 	struct mthca_dev *dev = to_mdev(ibqp->device);
 	struct mthca_qp *qp = to_mqp(ibqp);
@@ -1445,15 +1638,18 @@
 	void *wqe;
 	void *prev_wqe;
 
-	spin_lock_irqsave(&qp->lock, flags);
+	spin_lock_irqsave(&qp->rq.lock, flags);
 
 	/* XXX check that state is OK to post receive */
 
-	ind = qp->rq.next;
+	ind = qp->rq.next_ind;
 
 	for (nreq = 0; wr; ++nreq, wr = wr->next) {
-		if (qp->rq.cur + nreq >= qp->rq.max) {
-			mthca_err(dev, "RQ %06x full\n", qp->qpn);
+		if (mthca_wq_overflow(&qp->rq, nreq, qp->ibqp.recv_cq)) {
+			mthca_err(dev, "RQ %06x full (%u head, %u tail,"
+					" %d max, %d nreq)\n", qp->qpn,
+					qp->rq.head, qp->rq.tail,
+					qp->rq.max, nreq);
 			err = -ENOMEM;
 			*bad_wr = wr;
 			goto out;
@@ -1466,14 +1662,12 @@
 		((struct mthca_next_seg *) wqe)->nda_op = 0;
 		((struct mthca_next_seg *) wqe)->ee_nds =
 			cpu_to_be32(MTHCA_NEXT_DBD);
-		((struct mthca_next_seg *) wqe)->flags =
-			(wr->recv_flags & IB_RECV_SIGNALED) ?
-			cpu_to_be32(MTHCA_NEXT_CQ_UPDATE) : 0;
+		((struct mthca_next_seg *) wqe)->flags = 0;
 
 		wqe += sizeof (struct mthca_next_seg);
 		size = sizeof (struct mthca_next_seg) / 16;
 
-		if (wr->num_sge > qp->rq.max_gs) {
+		if (unlikely(wr->num_sge > qp->rq.max_gs)) {
 			err = -EINVAL;
 			*bad_wr = wr;
 			goto out;
@@ -1492,10 +1686,10 @@
 
 		qp->wrid[ind] = wr->wr_id;
 
-		if (prev_wqe) {
+		if (likely(prev_wqe)) {
 			((struct mthca_next_seg *) prev_wqe)->nda_op =
 				cpu_to_be32((ind << qp->rq.wqe_shift) | 1);
-			smp_wmb();
+			wmb();
 			((struct mthca_next_seg *) prev_wqe)->ee_nds =
 				cpu_to_be32(MTHCA_NEXT_DBD | size);
 		}
@@ -1509,10 +1703,10 @@
 	}
 
 out:
-	if (nreq) {
+	if (likely(nreq)) {
 		u32 doorbell[2];
 
-		doorbell[0] = cpu_to_be32((qp->rq.next << qp->rq.wqe_shift) | size0);
+		doorbell[0] = cpu_to_be32((qp->rq.next_ind << qp->rq.wqe_shift) | size0);
 		doorbell[1] = cpu_to_be32((qp->qpn << 8) | nreq);
 
 		wmb();
@@ -1522,14 +1716,258 @@
 			      MTHCA_GET_DOORBELL_LOCK(&dev->doorbell_lock));
 	}
 
-	qp->rq.cur += nreq;
-	qp->rq.next = ind;
+	qp->rq.next_ind = ind;
+	qp->rq.head    += nreq;
+
+	spin_unlock_irqrestore(&qp->rq.lock, flags);
+	return err;
+}
+
+int mthca_arbel_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
+			  struct ib_send_wr **bad_wr)
+{
+	struct mthca_dev *dev = to_mdev(ibqp->device);
+	struct mthca_qp *qp = to_mqp(ibqp);
+	void *wqe;
+	void *prev_wqe;
+	unsigned long flags;
+	int err = 0;
+	int nreq;
+	int i;
+	int size;
+	int size0 = 0;
+	u32 f0 = 0;
+	int ind;
+	u8 op0 = 0;
+
+	spin_lock_irqsave(&qp->sq.lock, flags);
+
+	/* XXX check that state is OK to post send */
+
+	ind = qp->sq.head & (qp->sq.max - 1);
+
+	for (nreq = 0; wr; ++nreq, wr = wr->next) {
+		if (mthca_wq_overflow(&qp->sq, nreq, qp->ibqp.send_cq)) {
+			mthca_err(dev, "SQ %06x full (%u head, %u tail,"
+					" %d max, %d nreq)\n", qp->qpn,
+					qp->sq.head, qp->sq.tail,
+					qp->sq.max, nreq);
+			err = -ENOMEM;
+			*bad_wr = wr;
+			goto out;
+		}
+
+		wqe = get_send_wqe(qp, ind);
+		prev_wqe = qp->sq.last;
+		qp->sq.last = wqe;
+
+		((struct mthca_next_seg *) wqe)->flags =
+			((wr->send_flags & IB_SEND_SIGNALED) ?
+			 cpu_to_be32(MTHCA_NEXT_CQ_UPDATE) : 0) |
+			((wr->send_flags & IB_SEND_SOLICITED) ?
+			 cpu_to_be32(MTHCA_NEXT_SOLICIT) : 0)   |
+			cpu_to_be32(1);
+		if (wr->opcode == IB_WR_SEND_WITH_IMM ||
+		    wr->opcode == IB_WR_RDMA_WRITE_WITH_IMM)
+			((struct mthca_next_seg *) wqe)->flags = wr->imm_data;
+
+		wqe += sizeof (struct mthca_next_seg);
+		size = sizeof (struct mthca_next_seg) / 16;
+
+		switch (qp->transport) {
+		case UD:
+			memcpy(((struct mthca_arbel_ud_seg *) wqe)->av,
+			       to_mah(wr->wr.ud.ah)->av, MTHCA_AV_SIZE);
+			((struct mthca_arbel_ud_seg *) wqe)->dqpn =
+				cpu_to_be32(wr->wr.ud.remote_qpn);
+			((struct mthca_arbel_ud_seg *) wqe)->qkey =
+				cpu_to_be32(wr->wr.ud.remote_qkey);
+
+			wqe += sizeof (struct mthca_arbel_ud_seg);
+			size += sizeof (struct mthca_arbel_ud_seg) / 16;
+			break;
+
+		case MLX:
+			err = build_mlx_header(dev, to_msqp(qp), ind, wr,
+					       wqe - sizeof (struct mthca_next_seg),
+					       wqe);
+			if (err) {
+				*bad_wr = wr;
+				goto out;
+			}
+			wqe += sizeof (struct mthca_data_seg);
+			size += sizeof (struct mthca_data_seg) / 16;
+			break;
+		}
+
+		if (wr->num_sge > qp->sq.max_gs) {
+			mthca_err(dev, "too many gathers\n");
+			err = -EINVAL;
+			*bad_wr = wr;
+			goto out;
+		}
+
+		for (i = 0; i < wr->num_sge; ++i) {
+			((struct mthca_data_seg *) wqe)->byte_count =
+				cpu_to_be32(wr->sg_list[i].length);
+			((struct mthca_data_seg *) wqe)->lkey =
+				cpu_to_be32(wr->sg_list[i].lkey);
+			((struct mthca_data_seg *) wqe)->addr =
+				cpu_to_be64(wr->sg_list[i].addr);
+			wqe += sizeof (struct mthca_data_seg);
+			size += sizeof (struct mthca_data_seg) / 16;
+		}
+
+		/* Add one more inline data segment for ICRC */
+		if (qp->transport == MLX) {
+			((struct mthca_data_seg *) wqe)->byte_count =
+				cpu_to_be32((1 << 31) | 4);
+			((u32 *) wqe)[1] = 0;
+			wqe += sizeof (struct mthca_data_seg);
+			size += sizeof (struct mthca_data_seg) / 16;
+		}
+
+		qp->wrid[ind + qp->rq.max] = wr->wr_id;
+
+		if (wr->opcode >= ARRAY_SIZE(mthca_opcode)) {
+			mthca_err(dev, "opcode invalid\n");
+			err = -EINVAL;
+			*bad_wr = wr;
+			goto out;
+		}
+
+		if (likely(prev_wqe)) {
+			((struct mthca_next_seg *) prev_wqe)->nda_op =
+				cpu_to_be32(((ind << qp->sq.wqe_shift) +
+					     qp->send_wqe_offset) |
+					    mthca_opcode[wr->opcode]);
+			wmb();
+			((struct mthca_next_seg *) prev_wqe)->ee_nds =
+				cpu_to_be32(MTHCA_NEXT_DBD | size);
+		}
+
+		if (!size0) {
+			size0 = size;
+			op0   = mthca_opcode[wr->opcode];
+		}
+
+		++ind;
+		if (unlikely(ind >= qp->sq.max))
+			ind -= qp->sq.max;
+	}
+
+out:
+	if (likely(nreq)) {
+		u32 doorbell[2];
+
+		doorbell[0] = cpu_to_be32((nreq << 24)                  |
+					  ((qp->sq.head & 0xffff) << 8) |
+					  f0 | op0);
+		doorbell[1] = cpu_to_be32((qp->qpn << 8) | size0);
+
+		qp->sq.head += nreq;
+
+		/*
+		 * Make sure that descriptors are written before
+		 * doorbell record.
+		 */
+		wmb();
+		*qp->sq.db = cpu_to_be32(qp->sq.head & 0xffff);
+
+		/*
+		 * Make sure doorbell record is written before we
+		 * write MMIO send doorbell.
+		 */
+		wmb();
+		mthca_write64(doorbell,
+			      dev->kar + MTHCA_SEND_DOORBELL,
+			      MTHCA_GET_DOORBELL_LOCK(&dev->doorbell_lock));
+	}
+
+	spin_unlock_irqrestore(&qp->sq.lock, flags);
+	return err;
+}
+
+int mthca_arbel_post_receive(struct ib_qp *ibqp, struct ib_recv_wr *wr,
+			     struct ib_recv_wr **bad_wr)
+{
+	struct mthca_dev *dev = to_mdev(ibqp->device);
+	struct mthca_qp *qp = to_mqp(ibqp);
+	unsigned long flags;
+	int err = 0;
+	int nreq;
+	int ind;
+	int i;
+	void *wqe;
+
+ 	spin_lock_irqsave(&qp->rq.lock, flags);
+
+	/* XXX check that state is OK to post receive */
+
+	ind = qp->rq.head & (qp->rq.max - 1);
 
-	spin_unlock_irqrestore(&qp->lock, flags);
+	for (nreq = 0; wr; ++nreq, wr = wr->next) {
+		if (mthca_wq_overflow(&qp->rq, nreq, qp->ibqp.recv_cq)) {
+			mthca_err(dev, "RQ %06x full (%u head, %u tail,"
+					" %d max, %d nreq)\n", qp->qpn,
+					qp->rq.head, qp->rq.tail,
+					qp->rq.max, nreq);
+			err = -ENOMEM;
+			*bad_wr = wr;
+			goto out;
+		}
+
+		wqe = get_recv_wqe(qp, ind);
+
+		((struct mthca_next_seg *) wqe)->flags = 0;
+
+		wqe += sizeof (struct mthca_next_seg);
+
+		if (unlikely(wr->num_sge > qp->rq.max_gs)) {
+			err = -EINVAL;
+			*bad_wr = wr;
+			goto out;
+		}
+
+		for (i = 0; i < wr->num_sge; ++i) {
+			((struct mthca_data_seg *) wqe)->byte_count =
+				cpu_to_be32(wr->sg_list[i].length);
+			((struct mthca_data_seg *) wqe)->lkey =
+				cpu_to_be32(wr->sg_list[i].lkey);
+			((struct mthca_data_seg *) wqe)->addr =
+				cpu_to_be64(wr->sg_list[i].addr);
+			wqe += sizeof (struct mthca_data_seg);
+		}
+
+		if (i < qp->rq.max_gs) {
+			((struct mthca_data_seg *) wqe)->byte_count = 0;
+			((struct mthca_data_seg *) wqe)->lkey = cpu_to_be32(0x100);
+			((struct mthca_data_seg *) wqe)->addr = 0;
+		}
+
+		qp->wrid[ind] = wr->wr_id;
+
+		++ind;
+		if (unlikely(ind >= qp->rq.max))
+			ind -= qp->rq.max;
+	}
+out:
+	if (likely(nreq)) {
+		qp->rq.head += nreq;
+
+		/*
+		 * Make sure that descriptors are written before
+		 * doorbell record.
+		 */
+		wmb();
+		*qp->rq.db = cpu_to_be32(qp->rq.head & 0xffff);
+	}
+
+	spin_unlock_irqrestore(&qp->rq.lock, flags);
 	return err;
 }
 
-int mthca_free_err_wqe(struct mthca_qp *qp, int is_send,
+int mthca_free_err_wqe(struct mthca_dev *dev, struct mthca_qp *qp, int is_send,
 		       int index, int *dbd, u32 *new_wqe)
 {
 	struct mthca_next_seg *next;
@@ -1539,7 +1977,10 @@
 	else
 		next = get_recv_wqe(qp, index);
 
-	*dbd = !!(next->ee_nds & cpu_to_be32(MTHCA_NEXT_DBD));
+	if (dev->hca_type == ARBEL_NATIVE)
+		*dbd = 1;
+	else
+		*dbd = !!(next->ee_nds & cpu_to_be32(MTHCA_NEXT_DBD));
 	if (next->ee_nds & cpu_to_be32(0x3f))
 		*new_wqe = (next->nda_op & cpu_to_be32(~0x3f)) |
 			(next->ee_nds & cpu_to_be32(0x3f));
diff -Nru a/drivers/infiniband/hw/mthca/mthca_reset.c b/drivers/infiniband/hw/mthca/mthca_reset.c
--- a/drivers/infiniband/hw/mthca/mthca_reset.c	2005-03-11 12:51:41 -08:00
+++ b/drivers/infiniband/hw/mthca/mthca_reset.c	2005-03-11 12:51:41 -08:00
@@ -50,7 +50,7 @@
 	struct pci_dev *bridge = NULL;
 
 #define MTHCA_RESET_OFFSET 0xf0010
-#define MTHCA_RESET_VALUE  cpu_to_be32(1)
+#define MTHCA_RESET_VALUE  swab32(1)
 
 	/*
 	 * Reset the chip.  This is somewhat ugly because we have to
diff -Nru a/drivers/infiniband/hw/mthca/mthca_uar.c b/drivers/infiniband/hw/mthca/mthca_uar.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/infiniband/hw/mthca/mthca_uar.c	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2005 Topspin Communications.  All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * $Id$
+ */
+
+#include "mthca_dev.h"
+#include "mthca_memfree.h"
+
+int mthca_uar_alloc(struct mthca_dev *dev, struct mthca_uar *uar)
+{
+	uar->index = mthca_alloc(&dev->uar_table.alloc);
+	if (uar->index == -1)
+		return -ENOMEM;
+
+	uar->pfn = (pci_resource_start(dev->pdev, 2) >> PAGE_SHIFT) + uar->index;
+
+	return 0;
+}
+
+void mthca_uar_free(struct mthca_dev *dev, struct mthca_uar *uar)
+{
+	mthca_free(&dev->uar_table.alloc, uar->index);
+}
+
+int mthca_init_uar_table(struct mthca_dev *dev)
+{
+	int ret;
+
+	ret = mthca_alloc_init(&dev->uar_table.alloc,
+			       dev->limits.num_uars,
+			       dev->limits.num_uars - 1,
+			       dev->limits.reserved_uars);
+	if (ret)
+		return ret;
+
+	ret = mthca_init_db_tab(dev);
+	if (ret)
+		mthca_alloc_cleanup(&dev->uar_table.alloc);
+
+	return ret;
+}
+
+void mthca_cleanup_uar_table(struct mthca_dev *dev)
+{
+	mthca_cleanup_db_tab(dev);
+
+	/* XXX check if any UARs are still allocated? */
+	mthca_alloc_cleanup(&dev->uar_table.alloc);
+}
diff -Nru a/drivers/infiniband/include/ib_verbs.h b/drivers/infiniband/include/ib_verbs.h
--- a/drivers/infiniband/include/ib_verbs.h	2005-03-11 12:51:42 -08:00
+++ b/drivers/infiniband/include/ib_verbs.h	2005-03-11 12:51:42 -08:00
@@ -73,7 +73,6 @@
 	IB_DEVICE_RC_RNR_NAK_GEN	= (1<<12),
 	IB_DEVICE_SRQ_RESIZE		= (1<<13),
 	IB_DEVICE_N_NOTIFY_CQ		= (1<<14),
-	IB_DEVICE_RQ_SIG_TYPE		= (1<<15)
 };
 
 enum ib_atomic_cap {
@@ -408,7 +407,6 @@
 	struct ib_srq	       *srq;
 	struct ib_qp_cap	cap;
 	enum ib_sig_type	sq_sig_type;
-	enum ib_sig_type	rq_sig_type;
 	enum ib_qp_type		qp_type;
 	u8			port_num; /* special QP types only */
 };
@@ -533,10 +531,6 @@
 	IB_SEND_INLINE		= (1<<3)
 };
 
-enum ib_recv_flags {
-	IB_RECV_SIGNALED	= 1
-};
-
 struct ib_sge {
 	u64	addr;
 	u32	length;
@@ -579,7 +573,6 @@
 	u64			wr_id;
 	struct ib_sge	       *sg_list;
 	int			num_sge;
-	int			recv_flags;
 };
 
 enum ib_access_flags {
diff -Nru a/drivers/infiniband/ulp/ipoib/ipoib.h b/drivers/infiniband/ulp/ipoib/ipoib.h
--- a/drivers/infiniband/ulp/ipoib/ipoib.h	2005-03-11 12:51:41 -08:00
+++ b/drivers/infiniband/ulp/ipoib/ipoib.h	2005-03-11 12:51:41 -08:00
@@ -308,11 +308,11 @@
 
 
 #ifdef CONFIG_INFINIBAND_IPOIB_DEBUG
-extern int debug_level;
+extern int ipoib_debug_level;
 
 #define ipoib_dbg(priv, format, arg...)			\
 	do {					        \
-		if (debug_level > 0)			\
+		if (ipoib_debug_level > 0)			\
 			ipoib_printk(KERN_DEBUG, priv, format , ## arg); \
 	} while (0)
 #define ipoib_dbg_mcast(priv, format, arg...)		\
diff -Nru a/drivers/infiniband/ulp/ipoib/ipoib_ib.c b/drivers/infiniband/ulp/ipoib/ipoib_ib.c
--- a/drivers/infiniband/ulp/ipoib/ipoib_ib.c	2005-03-11 12:51:52 -08:00
+++ b/drivers/infiniband/ulp/ipoib/ipoib_ib.c	2005-03-11 12:51:52 -08:00
@@ -40,7 +40,7 @@
 #include "ipoib.h"
 
 #ifdef CONFIG_INFINIBAND_IPOIB_DEBUG_DATA
-int data_debug_level;
+static int data_debug_level;
 
 module_param(data_debug_level, int, 0644);
 MODULE_PARM_DESC(data_debug_level,
@@ -105,7 +105,6 @@
 		.wr_id 	    = wr_id | IPOIB_OP_RECV,
 		.sg_list    = &list,
 		.num_sge    = 1,
-		.recv_flags = IB_RECV_SIGNALED
 	};
 	struct ib_recv_wr *bad_wr;
 
@@ -137,6 +136,9 @@
 	if (ret) {
 		ipoib_warn(priv, "ipoib_ib_receive failed for buf %d (%d)\n",
 			   id, ret);
+		dma_unmap_single(priv->ca->dma_device, addr,
+				 IPOIB_BUF_SIZE, DMA_FROM_DEVICE);
+		dev_kfree_skb_any(skb);
 		priv->rx_ring[id].skb = NULL;
 	}
 
diff -Nru a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c
--- a/drivers/infiniband/ulp/ipoib/ipoib_main.c	2005-03-11 12:51:42 -08:00
+++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c	2005-03-11 12:51:42 -08:00
@@ -51,9 +51,9 @@
 MODULE_LICENSE("Dual BSD/GPL");
 
 #ifdef CONFIG_INFINIBAND_IPOIB_DEBUG
-int debug_level;
+int ipoib_debug_level;
 
-module_param(debug_level, int, 0644);
+module_param_named(debug_level, ipoib_debug_level, int, 0644);
 MODULE_PARM_DESC(debug_level, "Enable debug tracing if > 0");
 #endif
 
@@ -215,16 +215,25 @@
 	return 0;
 }
 
-static void __path_free(struct net_device *dev, struct ipoib_path *path)
+static void path_free(struct net_device *dev, struct ipoib_path *path)
 {
 	struct ipoib_dev_priv *priv = netdev_priv(dev);
 	struct ipoib_neigh *neigh, *tn;
 	struct sk_buff *skb;
+	unsigned long flags;
 
 	while ((skb = __skb_dequeue(&path->queue)))
 		dev_kfree_skb_irq(skb);
 
+	spin_lock_irqsave(&priv->lock, flags);
+
 	list_for_each_entry_safe(neigh, tn, &path->neigh_list, list) {
+		/*
+		 * It's safe to call ipoib_put_ah() inside priv->lock
+		 * here, because we know that path->ah will always
+		 * hold one more reference, so ipoib_put_ah() will
+		 * never do more than decrement the ref count.
+		 */
 		if (neigh->ah)
 			ipoib_put_ah(neigh->ah);
 		*to_ipoib_neigh(neigh->neighbour) = NULL;
@@ -232,11 +241,11 @@
 		kfree(neigh);
 	}
 
+	spin_unlock_irqrestore(&priv->lock, flags);
+
 	if (path->ah)
 		ipoib_put_ah(path->ah);
 
-	rb_erase(&path->rb_node, &priv->path_tree);
-	list_del(&path->list);
 	kfree(path);
 }
 
@@ -248,15 +257,20 @@
 	unsigned long flags;
 
 	spin_lock_irqsave(&priv->lock, flags);
+
 	list_splice(&priv->path_list, &remove_list);
 	INIT_LIST_HEAD(&priv->path_list);
+
+	list_for_each_entry(path, &remove_list, list)
+		rb_erase(&path->rb_node, &priv->path_tree);
+
 	spin_unlock_irqrestore(&priv->lock, flags);
 
 	list_for_each_entry_safe(path, tp, &remove_list, list) {
 		if (path->query)
 			ib_sa_cancel_query(path->query_id, path->query);
 		wait_for_completion(&path->done);
-		__path_free(dev, path);
+		path_free(dev, path);
 	}
 }
 
@@ -346,8 +360,9 @@
 	if (!path)
 		return NULL;
 
-	path->dev = dev;
+	path->dev          = dev;
 	path->pathrec.dlid = 0;
+	path->ah           = NULL;
 
 	skb_queue_head_init(&path->queue);
 
@@ -360,8 +375,6 @@
 	path->pathrec.pkey      = cpu_to_be16(priv->pkey);
 	path->pathrec.numb_path = 1;
 
-	__path_add(dev, path);
-
 	return path;
 }
 
@@ -421,6 +434,8 @@
 				       (union ib_gid *) (skb->dst->neighbour->ha + 4));
 		if (!path)
 			goto err;
+
+		__path_add(dev, path);
 	}
 
 	list_add_tail(&neigh->list, &path->neigh_list);
@@ -450,8 +465,8 @@
 err:
 	*to_ipoib_neigh(skb->dst->neighbour) = NULL;
 	list_del(&neigh->list);
-	kfree(neigh);
 	neigh->neighbour->ops->destructor = NULL;
+	kfree(neigh);
 
 	++priv->stats.tx_dropped;
 	dev_kfree_skb_any(skb);
@@ -496,8 +511,12 @@
 			skb_push(skb, sizeof *phdr);
 			__skb_queue_tail(&path->queue, skb);
 
-			if (path_rec_start(dev, path))
-				__path_free(dev, path);
+			if (path_rec_start(dev, path)) {
+				spin_unlock(&priv->lock);
+				path_free(dev, path);
+				return;
+			} else
+				__path_add(dev, path);
 		} else {
 			++priv->stats.tx_dropped;
 			dev_kfree_skb_any(skb);
@@ -657,9 +676,10 @@
 
 static void ipoib_neigh_destructor(struct neighbour *n)
 {
-	struct ipoib_neigh *neigh = *to_ipoib_neigh(n);
+	struct ipoib_neigh *neigh;
 	struct ipoib_dev_priv *priv = netdev_priv(n->dev);
 	unsigned long flags;
+	struct ipoib_ah *ah = NULL;
 
 	ipoib_dbg(priv,
 		  "neigh_destructor for %06x " IPOIB_GID_FMT "\n",
@@ -668,15 +688,19 @@
 
 	spin_lock_irqsave(&priv->lock, flags);
 
+	neigh = *to_ipoib_neigh(n);
 	if (neigh) {
 		if (neigh->ah)
-			ipoib_put_ah(neigh->ah);
+			ah = neigh->ah;
 		list_del(&neigh->list);
 		*to_ipoib_neigh(n) = NULL;
 		kfree(neigh);
 	}
 
 	spin_unlock_irqrestore(&priv->lock, flags);
+
+	if (ah)
+		ipoib_put_ah(ah);
 }
 
 static int ipoib_neigh_setup(struct neighbour *neigh)
diff -Nru a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
--- a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c	2005-03-11 12:51:51 -08:00
+++ b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c	2005-03-11 12:51:51 -08:00
@@ -93,6 +93,8 @@
 	struct ipoib_dev_priv *priv = netdev_priv(dev);
 	struct ipoib_neigh *neigh, *tmp;
 	unsigned long flags;
+	LIST_HEAD(ah_list);
+	struct ipoib_ah *ah, *tah;
 
 	ipoib_dbg_mcast(netdev_priv(dev),
 			"deleting multicast group " IPOIB_GID_FMT "\n",
@@ -101,7 +103,8 @@
 	spin_lock_irqsave(&priv->lock, flags);
 
 	list_for_each_entry_safe(neigh, tmp, &mcast->neigh_list, list) {
-		ipoib_put_ah(neigh->ah);
+		if (neigh->ah)
+			list_add_tail(&neigh->ah->list, &ah_list);
 		*to_ipoib_neigh(neigh->neighbour) = NULL;
 		neigh->neighbour->ops->destructor = NULL;
 		kfree(neigh);
@@ -109,6 +112,9 @@
 
 	spin_unlock_irqrestore(&priv->lock, flags);
 
+	list_for_each_entry_safe(ah, tah, &ah_list, list)
+		ipoib_put_ah(ah);
+
 	if (mcast->ah)
 		ipoib_put_ah(mcast->ah);
 
@@ -790,7 +796,7 @@
 
 	spin_unlock_irqrestore(&priv->lock, flags);
 
-	list_for_each_entry(mcast, &remove_list, list) {
+	list_for_each_entry_safe(mcast, tmcast, &remove_list, list) {
 		ipoib_mcast_leave(dev, mcast);
 		ipoib_mcast_free(mcast);
 	}
@@ -902,7 +908,7 @@
 	spin_unlock_irqrestore(&priv->lock, flags);
 
 	/* We have to cancel outside of the spinlock */
-	list_for_each_entry(mcast, &remove_list, list) {
+	list_for_each_entry_safe(mcast, tmcast, &remove_list, list) {
 		ipoib_mcast_leave(mcast->dev, mcast);
 		ipoib_mcast_free(mcast);
 	}
diff -Nru a/drivers/infiniband/ulp/ipoib/ipoib_verbs.c b/drivers/infiniband/ulp/ipoib/ipoib_verbs.c
--- a/drivers/infiniband/ulp/ipoib/ipoib_verbs.c	2005-03-11 12:51:46 -08:00
+++ b/drivers/infiniband/ulp/ipoib/ipoib_verbs.c	2005-03-11 12:51:46 -08:00
@@ -165,7 +165,6 @@
 			.max_recv_sge = 1
 		},
 		.sq_sig_type = IB_SIGNAL_ALL_WR,
-		.rq_sig_type = IB_SIGNAL_ALL_WR,
 		.qp_type     = IB_QPT_UD
 	};
 
diff -Nru a/drivers/input/Kconfig b/drivers/input/Kconfig
--- a/drivers/input/Kconfig	2005-03-11 12:51:41 -08:00
+++ b/drivers/input/Kconfig	2005-03-11 12:51:41 -08:00
@@ -5,7 +5,7 @@
 menu "Input device support"
 
 config INPUT
-	tristate "Input devices (needed for keyboard, mouse, ...)" if EMBEDDED
+	tristate "Generic input layer (needed for keyboard, mouse, ...)" if EMBEDDED
 	default y
 	---help---
 	  Say Y here if you have any input device (mouse, keyboard, tablet,
@@ -22,12 +22,13 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called input.
 
+if INPUT
+
 comment "Userland interfaces"
 
 config INPUT_MOUSEDEV
 	tristate "Mouse interface" if EMBEDDED
 	default y
-	depends on INPUT
 	---help---
 	  Say Y here if you want your mouse to be accessible as char devices
 	  13:32+ - /dev/input/mouseX and 13:63 - /dev/input/mice as an
@@ -74,7 +75,6 @@
 
 config INPUT_JOYDEV
 	tristate "Joystick interface"
-	depends on INPUT
 	---help---
 	  Say Y here if you want your joystick or gamepad to be
 	  accessible as char device 13:0+ - /dev/input/jsX device.
@@ -88,7 +88,6 @@
 
 config INPUT_TSDEV
 	tristate "Touchscreen interface"
-	depends on INPUT
 	---help---
 	  Say Y here if you have an application that only can understand the
 	  Compaq touchscreen protocol for absolute pointer data. This is
@@ -111,7 +110,6 @@
 
 config INPUT_EVDEV
 	tristate "Event interface"
-	depends on INPUT
 	help
 	  Say Y here if you want your input device events be accessible
 	  under char device 13:64+ - /dev/input/eventX in a generic way.
@@ -121,7 +119,6 @@
 
 config INPUT_EVBUG
 	tristate "Event debugging"
-	depends on INPUT
 	---help---
 	  Say Y here if you have a problem with the input subsystem and
 	  want all events (keypresses, mouse movements), to be output to
@@ -134,12 +131,6 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called evbug.
 
-comment "Input I/O drivers"
-
-source "drivers/input/gameport/Kconfig"
-
-source "drivers/input/serio/Kconfig"
-
 comment "Input Device Drivers"
 
 source "drivers/input/keyboard/Kconfig"
@@ -151,6 +142,16 @@
 source "drivers/input/touchscreen/Kconfig"
 
 source "drivers/input/misc/Kconfig"
+
+endif
+
+menu "Hardware I/O ports"
+
+source "drivers/input/serio/Kconfig"
+
+source "drivers/input/gameport/Kconfig"
+
+endmenu
 
 endmenu
 
diff -Nru a/drivers/input/evbug.c b/drivers/input/evbug.c
--- a/drivers/input/evbug.c	2005-03-11 12:51:42 -08:00
+++ b/drivers/input/evbug.c	2005-03-11 12:51:42 -08:00
@@ -88,13 +88,13 @@
 	.id_table =	evbug_ids,
 };
 
-int __init evbug_init(void)
+static int __init evbug_init(void)
 {
 	input_register_handler(&evbug_handler);
 	return 0;
 }
 
-void __exit evbug_exit(void)
+static void __exit evbug_exit(void)
 {
 	input_unregister_handler(&evbug_handler);
 }
diff -Nru a/drivers/input/evdev.c b/drivers/input/evdev.c
--- a/drivers/input/evdev.c	2005-03-11 12:51:47 -08:00
+++ b/drivers/input/evdev.c	2005-03-11 12:51:47 -08:00
@@ -169,6 +169,9 @@
 	struct evdev_list *list = file->private_data;
 	int retval;
 
+	if (count < sizeof(struct input_event))
+		return -EINVAL;
+
 	if (list->head == list->tail && list->evdev->exist && (file->f_flags & O_NONBLOCK))
 		return -EAGAIN;
 
@@ -196,9 +199,8 @@
 {
 	struct evdev_list *list = file->private_data;
 	poll_wait(file, &list->evdev->wait, wait);
-	if (list->head != list->tail)
-		return POLLIN | POLLRDNORM;
-	return 0;
+	return ((list->head == list->tail) ? 0 : (POLLIN | POLLRDNORM)) |
+		(list->evdev->exist ? 0 : (POLLHUP | POLLERR));
 }
 
 static int evdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
@@ -223,14 +225,15 @@
 
 		case EVIOCGKEYCODE:
 			if (get_user(t, ip)) return -EFAULT;
-			if (t < 0 || t > dev->keycodemax || !dev->keycodesize) return -EINVAL;
+			if (t < 0 || t >= dev->keycodemax || !dev->keycodesize) return -EINVAL;
 			if (put_user(INPUT_KEYCODE(dev, t), ip + 1)) return -EFAULT;
 			return 0;
 
 		case EVIOCSKEYCODE:
 			if (get_user(t, ip)) return -EFAULT;
-			if (t < 0 || t > dev->keycodemax || !dev->keycodesize) return -EINVAL;
+			if (t < 0 || t >= dev->keycodemax || !dev->keycodesize) return -EINVAL;
 			if (get_user(v, ip + 1)) return -EFAULT;
+			if (v < 0 || v > KEY_MAX) return -EINVAL;
 			u = SET_INPUT_KEYCODE(dev, t, v);
 			clear_bit(u, dev->keybit);
 			set_bit(v, dev->keybit);
@@ -438,6 +441,7 @@
 static void evdev_disconnect(struct input_handle *handle)
 {
 	struct evdev *evdev = handle->private;
+	struct evdev_list *list;
 
 	class_simple_device_remove(MKDEV(INPUT_MAJOR, EVDEV_MINOR_BASE + evdev->minor));
 	devfs_remove("input/event%d", evdev->minor);
@@ -446,6 +450,8 @@
 	if (evdev->open) {
 		input_close_device(handle);
 		wake_up_interruptible(&evdev->wait);
+		list_for_each_entry(list, &evdev->list, node)
+			kill_fasync(&list->fasync, SIGIO, POLL_HUP);
 	} else
 		evdev_free(evdev);
 }
diff -Nru a/drivers/input/gameport/Kconfig b/drivers/input/gameport/Kconfig
--- a/drivers/input/gameport/Kconfig	2005-03-11 12:51:41 -08:00
+++ b/drivers/input/gameport/Kconfig	2005-03-11 12:51:41 -08:00
@@ -19,30 +19,10 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called gameport.
 
-
-# Yes, SOUND_GAMEPORT looks a bit odd. Yes, it ends up being turned on
-# in every .config. Please don't touch it. It is here to handle an
-# unusual dependency between GAMEPORT and sound drivers.
-#
-# Some sound drivers call gameport functions. If GAMEPORT is
-# not selected, empty stubs are provided for the functions and all is
-# well.
-# If GAMEPORT is built in, everything is fine.
-# If GAMEPORT is a module, however, it would need to be loaded for the
-# sound driver to be able to link properly. Therefore, the sound
-# driver must be a module as well in that case. Since there's no way
-# to express that directly in Kconfig, we use SOUND_GAMEPORT to
-# express it. SOUND_GAMEPORT boils down to "if GAMEPORT is 'm',
-# anything that depends on SOUND_GAMEPORT must be 'm' as well. if
-# GAMEPORT is 'y' or 'n', it can be anything".
-config SOUND_GAMEPORT
-	tristate
-	default y if GAMEPORT!=m
-	default m if GAMEPORT=m
+if GAMEPORT
 
 config GAMEPORT_NS558
 	tristate "Classic ISA and PnP gameport support"
-	depends on GAMEPORT
 	help
 	  Say Y here if you have an ISA or PnP gameport.
 
@@ -53,7 +33,6 @@
 
 config GAMEPORT_L4
 	tristate "PDPI Lightning 4 gamecard support"
-	depends on GAMEPORT
 	help
 	  Say Y here if you have a PDPI Lightning 4 gamecard.
 
@@ -62,7 +41,6 @@
 
 config GAMEPORT_EMU10K1
 	tristate "SB Live and Audigy gameport support"
-	depends on GAMEPORT
 	help
 	  Say Y here if you have a SoundBlaster Live! or SoundBlaster
 	  Audigy card and want to use its gameport.
@@ -72,7 +50,6 @@
 
 config GAMEPORT_VORTEX
 	tristate "Aureal Vortex, Vortex 2 gameport support"
-	depends on GAMEPORT
 	help
 	  Say Y here if you have an Aureal Vortex 1 or 2  card and want
 	  to use its gameport.
@@ -82,9 +59,28 @@
 
 config GAMEPORT_FM801
 	tristate "ForteMedia FM801 gameport support"
-	depends on GAMEPORT
 
 config GAMEPORT_CS461X
 	tristate "Crystal SoundFusion gameport support"
-	depends on GAMEPORT
 
+endif
+
+# Yes, SOUND_GAMEPORT looks a bit odd. Yes, it ends up being turned on
+# in every .config. Please don't touch it. It is here to handle an
+# unusual dependency between GAMEPORT and sound drivers.
+#
+# Some sound drivers call gameport functions. If GAMEPORT is
+# not selected, empty stubs are provided for the functions and all is
+# well.
+# If GAMEPORT is built in, everything is fine.
+# If GAMEPORT is a module, however, it would need to be loaded for the
+# sound driver to be able to link properly. Therefore, the sound
+# driver must be a module as well in that case. Since there's no way
+# to express that directly in Kconfig, we use SOUND_GAMEPORT to
+# express it. SOUND_GAMEPORT boils down to "if GAMEPORT is 'm',
+# anything that depends on SOUND_GAMEPORT must be 'm' as well. if
+# GAMEPORT is 'y' or 'n', it can be anything".
+config SOUND_GAMEPORT
+	tristate
+	default m if GAMEPORT=m
+	default y
diff -Nru a/drivers/input/gameport/cs461x.c b/drivers/input/gameport/cs461x.c
--- a/drivers/input/gameport/cs461x.c	2005-03-11 12:51:41 -08:00
+++ b/drivers/input/gameport/cs461x.c	2005-03-11 12:51:41 -08:00
@@ -16,7 +16,7 @@
 #include <linux/slab.h>
 #include <linux/pci.h>
 
-MODULE_AUTHOR("Victor Krapivin <vik@belcaf.minsk.by>");
+MODULE_AUTHOR("Victor Krapivin");
 MODULE_LICENSE("GPL");
 
 /*
@@ -120,9 +120,6 @@
 static unsigned long ba0_addr;
 static unsigned int __iomem *ba0;
 
-static char phys[32];
-static char name[] = "CS416x Gameport";
-
 #ifdef CS461X_FULL_MAP
 static unsigned long ba1_addr;
 static union ba1_t {
@@ -160,10 +157,10 @@
 static int cs461x_free(struct pci_dev *pdev)
 {
 	struct gameport *port = pci_get_drvdata(pdev);
-	if(port){
+
+	if (port)
 	    gameport_unregister_port(port);
-	    kfree(port);
-	}
+
 	if (ba0) iounmap(ba0);
 #ifdef CS461X_FULL_MAP
 	if (ba1.name.data0) iounmap(ba1.name.data0);
@@ -267,18 +264,17 @@
                 return -ENOMEM;
         }
 #else
-	if (ba0 == NULL){
+	if (ba0 == NULL) {
 		cs461x_free(pdev);
 		return -ENOMEM;
 	}
 #endif
 
-	if (!(port = kmalloc(sizeof(struct gameport), GFP_KERNEL))) {
-		printk(KERN_ERR "Memory allocation failed.\n");
+	if (!(port = gameport_allocate_port())) {
+		printk(KERN_ERR "cs461x: Memory allocation failed\n");
 		cs461x_free(pdev);
 		return -ENOMEM;
 	}
-	memset(port, 0, sizeof(struct gameport));
 
 	pci_set_drvdata(pdev, port);
 
@@ -287,22 +283,15 @@
 	port->read = cs461x_gameport_read;
 	port->cooked_read = cs461x_gameport_cooked_read;
 
-	sprintf(phys, "pci%s/gameport0", pci_name(pdev));
-
-	port->name = name;
-	port->phys = phys;
-	port->id.bustype = BUS_PCI;
-	port->id.vendor = pdev->vendor;
-	port->id.product = pdev->device;
+	gameport_set_name(port, "CS416x");
+	gameport_set_phys(port, "pci%s/gameport0", pci_name(pdev));
+	port->dev.parent = &pdev->dev;
 
 	cs461x_pokeBA0(BA0_JSIO, 0xFF); // ?
 	cs461x_pokeBA0(BA0_JSCTL, JSCTL_SP_MEDIUM_SLOW);
 
 	gameport_register_port(port);
 
-	printk(KERN_INFO "gameport: %s on pci%s speed %d kHz\n",
-		name, pci_name(pdev), port->speed);
-
 	return 0;
 }
 
@@ -318,12 +307,12 @@
         .remove =       __devexit_p(cs461x_pci_remove),
 };
 
-int __init cs461x_init(void)
+static int __init cs461x_init(void)
 {
-        return pci_module_init(&cs461x_pci_driver);
+        return pci_register_driver(&cs461x_pci_driver);
 }
 
-void __exit cs461x_exit(void)
+static void __exit cs461x_exit(void)
 {
         pci_unregister_driver(&cs461x_pci_driver);
 }
diff -Nru a/drivers/input/gameport/emu10k1-gp.c b/drivers/input/gameport/emu10k1-gp.c
--- a/drivers/input/gameport/emu10k1-gp.c	2005-03-11 12:51:47 -08:00
+++ b/drivers/input/gameport/emu10k1-gp.c	2005-03-11 12:51:47 -08:00
@@ -44,13 +44,13 @@
 
 struct emu {
 	struct pci_dev *dev;
-	struct gameport gameport;
+	struct gameport *gameport;
+	int io;
 	int size;
-	char phys[32];
 };
 
 static struct pci_device_id emu_tbl[] = {
- 
+
 	{ 0x1102, 0x7002, PCI_ANY_ID, PCI_ANY_ID }, /* SB Live gameport */
 	{ 0x1102, 0x7003, PCI_ANY_ID, PCI_ANY_ID }, /* Audigy gameport */
 	{ 0x1102, 0x7004, PCI_ANY_ID, PCI_ANY_ID }, /* Dell SB Live */
@@ -64,6 +64,7 @@
 {
 	int ioport, iolen;
 	struct emu *emu;
+	struct gameport *port;
 
 	if (pci_enable_device(pdev))
 		return -EBUSY;
@@ -74,31 +75,29 @@
 	if (!request_region(ioport, iolen, "emu10k1-gp"))
 		return -EBUSY;
 
-	if (!(emu = kmalloc(sizeof(struct emu), GFP_KERNEL))) {
-		printk(KERN_ERR "emu10k1-gp: Memory allocation failed.\n");
+	emu = kcalloc(1, sizeof(struct emu), GFP_KERNEL);
+	port = gameport_allocate_port();
+	if (!emu || !port) {
+		printk(KERN_ERR "emu10k1-gp: Memory allocation failed\n");
 		release_region(ioport, iolen);
+		kfree(emu);
+		gameport_free_port(port);
 		return -ENOMEM;
 	}
-	memset(emu, 0, sizeof(struct emu));
-
-	sprintf(emu->phys, "pci%s/gameport0", pci_name(pdev));
 
+	emu->io = ioport;
 	emu->size = iolen;
 	emu->dev = pdev;
+	emu->gameport = port;
 
-	emu->gameport.io = ioport;
-	emu->gameport.name = pci_name(pdev);
-	emu->gameport.phys = emu->phys;
-	emu->gameport.id.bustype = BUS_PCI;
-	emu->gameport.id.vendor = pdev->vendor;
-	emu->gameport.id.product = pdev->device;
+	gameport_set_name(port, "EMU10K1");
+	gameport_set_phys(port, "pci%s/gameport0", pci_name(pdev));
+	port->dev.parent = &pdev->dev;
+	port->io = ioport;
 
 	pci_set_drvdata(pdev, emu);
 
-	gameport_register_port(&emu->gameport);
-
-	printk(KERN_INFO "gameport: pci%s speed %d kHz\n",
-		pci_name(pdev), emu->gameport.speed);
+	gameport_register_port(port);
 
 	return 0;
 }
@@ -106,8 +105,9 @@
 static void __devexit emu_remove(struct pci_dev *pdev)
 {
 	struct emu *emu = pci_get_drvdata(pdev);
-	gameport_unregister_port(&emu->gameport);
-	release_region(emu->gameport.io, emu->size);
+
+	gameport_unregister_port(emu->gameport);
+	release_region(emu->io, emu->size);
 	kfree(emu);
 }
 
@@ -118,12 +118,12 @@
         .remove =       __devexit_p(emu_remove),
 };
 
-int __init emu_init(void)
+static int __init emu_init(void)
 {
-	return pci_module_init(&emu_driver);
+	return pci_register_driver(&emu_driver);
 }
 
-void __exit emu_exit(void)
+static void __exit emu_exit(void)
 {
 	pci_unregister_driver(&emu_driver);
 }
diff -Nru a/drivers/input/gameport/fm801-gp.c b/drivers/input/gameport/fm801-gp.c
--- a/drivers/input/gameport/fm801-gp.c	2005-03-11 12:51:47 -08:00
+++ b/drivers/input/gameport/fm801-gp.c	2005-03-11 12:51:47 -08:00
@@ -37,10 +37,8 @@
 #define HAVE_COOKED
 
 struct fm801_gp {
-	struct gameport gameport;
+	struct gameport *gameport;
 	struct resource *res_port;
-	char phys[32];
-	char name[32];
 };
 
 #ifdef HAVE_COOKED
@@ -83,40 +81,42 @@
 static int __devinit fm801_gp_probe(struct pci_dev *pci, const struct pci_device_id *id)
 {
 	struct fm801_gp *gp;
+	struct gameport *port;
 
-	if (! (gp = kmalloc(sizeof(*gp), GFP_KERNEL))) {
-		printk("cannot malloc for fm801-gp\n");
-		return -1;
+	gp = kcalloc(1, sizeof(struct fm801_gp), GFP_KERNEL);
+	port = gameport_allocate_port();
+	if (!gp || !port) {
+		printk(KERN_ERR "fm801-gp: Memory allocation failed\n");
+		kfree(gp);
+		gameport_free_port(port);
+		return -ENOMEM;
 	}
-	memset(gp, 0, sizeof(*gp));
 
-	gp->gameport.open = fm801_gp_open;
+	pci_enable_device(pci);
+
+	port->open = fm801_gp_open;
 #ifdef HAVE_COOKED
-	gp->gameport.cooked_read = fm801_gp_cooked_read;
+	port->cooked_read = fm801_gp_cooked_read;
 #endif
-
-	pci_enable_device(pci);
-	gp->gameport.io = pci_resource_start(pci, 0);
-	if ((gp->res_port = request_region(gp->gameport.io, 0x10, "FM801 GP")) == NULL) {
-		printk("unable to grab region 0x%x-0x%x\n", gp->gameport.io, gp->gameport.io + 0x0f);
+	gameport_set_name(port, "FM801");
+	gameport_set_phys(port, "pci%s/gameport0", pci_name(pci));
+	port->dev.parent = &pci->dev;
+	port->io = pci_resource_start(pci, 0);
+
+	gp->gameport = port;
+	gp->res_port = request_region(port->io, 0x10, "FM801 GP");
+	if (!gp->res_port) {
 		kfree(gp);
-		return -1;
+		gameport_free_port(port);
+		printk(KERN_DEBUG "fm801-gp: unable to grab region 0x%x-0x%x\n",
+			port->io, port->io + 0x0f);
+		return -EBUSY;
 	}
 
-	gp->gameport.phys = gp->phys;
-	gp->gameport.name = gp->name;
-	gp->gameport.id.bustype = BUS_PCI;
-	gp->gameport.id.vendor = pci->vendor;
-	gp->gameport.id.product = pci->device;
-
 	pci_set_drvdata(pci, gp);
 
-	outb(0x60, gp->gameport.io + 0x0d); /* enable joystick 1 and 2 */
-
-	gameport_register_port(&gp->gameport);
-
-	printk(KERN_INFO "gameport: at pci%s speed %d kHz\n",
-		pci_name(pci), gp->gameport.speed);
+	outb(0x60, port->io + 0x0d); /* enable joystick 1 and 2 */
+	gameport_register_port(port);
 
 	return 0;
 }
@@ -124,8 +124,9 @@
 static void __devexit fm801_gp_remove(struct pci_dev *pci)
 {
 	struct fm801_gp *gp = pci_get_drvdata(pci);
+
 	if (gp) {
-		gameport_unregister_port(&gp->gameport);
+		gameport_unregister_port(gp->gameport);
 		release_resource(gp->res_port);
 		kfree(gp);
 	}
@@ -143,12 +144,12 @@
 	.remove =	__devexit_p(fm801_gp_remove),
 };
 
-int __init fm801_gp_init(void)
+static int __init fm801_gp_init(void)
 {
-	return pci_module_init(&fm801_gp_driver);
+	return pci_register_driver(&fm801_gp_driver);
 }
 
-void __exit fm801_gp_exit(void)
+static void __exit fm801_gp_exit(void)
 {
 	pci_unregister_driver(&fm801_gp_driver);
 }
diff -Nru a/drivers/input/gameport/gameport.c b/drivers/input/gameport/gameport.c
--- a/drivers/input/gameport/gameport.c	2005-03-11 12:51:46 -08:00
+++ b/drivers/input/gameport/gameport.c	2005-03-11 12:51:46 -08:00
@@ -2,6 +2,7 @@
  * Generic gameport layer
  *
  * Copyright (c) 1999-2002 Vojtech Pavlik
+ * Copyright (c) 2005 Dmitry Torokhov
  */
 
 /*
@@ -10,32 +11,55 @@
  * the Free Software Foundation.
  */
 
-#include <asm/io.h>
+#include <linux/stddef.h>
 #include <linux/module.h>
 #include <linux/ioport.h>
 #include <linux/init.h>
 #include <linux/gameport.h>
+#include <linux/wait.h>
+#include <linux/completion.h>
+#include <linux/sched.h>
+#include <linux/smp_lock.h>
 #include <linux/slab.h>
-#include <linux/stddef.h>
 #include <linux/delay.h>
 
+/*#include <asm/io.h>*/
+
 MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
 MODULE_DESCRIPTION("Generic gameport layer");
 MODULE_LICENSE("GPL");
 
-EXPORT_SYMBOL(gameport_register_port);
+EXPORT_SYMBOL(__gameport_register_port);
 EXPORT_SYMBOL(gameport_unregister_port);
-EXPORT_SYMBOL(gameport_register_device);
-EXPORT_SYMBOL(gameport_unregister_device);
+EXPORT_SYMBOL(__gameport_register_driver);
+EXPORT_SYMBOL(gameport_unregister_driver);
 EXPORT_SYMBOL(gameport_open);
 EXPORT_SYMBOL(gameport_close);
 EXPORT_SYMBOL(gameport_rescan);
 EXPORT_SYMBOL(gameport_cooked_read);
+EXPORT_SYMBOL(gameport_set_name);
+EXPORT_SYMBOL(gameport_set_phys);
+EXPORT_SYMBOL(gameport_start_polling);
+EXPORT_SYMBOL(gameport_stop_polling);
+
+/*
+ * gameport_sem protects entire gameport subsystem and is taken
+ * every time gameport port or driver registrered or unregistered.
+ */
+static DECLARE_MUTEX(gameport_sem);
 
 static LIST_HEAD(gameport_list);
-static LIST_HEAD(gameport_dev_list);
 
-#ifdef __i386__
+static struct bus_type gameport_bus = {
+	.name =	"gameport",
+};
+
+static void gameport_add_port(struct gameport *gameport);
+static void gameport_destroy_port(struct gameport *gameport);
+static void gameport_reconnect_port(struct gameport *gameport);
+static void gameport_disconnect_port(struct gameport *gameport);
+
+#if defined(__i386__)
 
 #define DELTA(x,y)      ((y)-(x)+((y)<(x)?1193182/HZ:0))
 #define GET_TIME(x)     do { x = get_time_pit(); } while (0)
@@ -57,13 +81,15 @@
 
 #endif
 
+
+
 /*
  * gameport_measure_speed() measures the gameport i/o speed.
  */
 
 static int gameport_measure_speed(struct gameport *gameport)
 {
-#ifdef __i386__
+#if defined(__i386__)
 
 	unsigned int i, t, t1, t2, t3, tx;
 	unsigned long flags;
@@ -76,7 +102,7 @@
 	for(i = 0; i < 50; i++) {
 		local_irq_save(flags);
 		GET_TIME(t1);
-		for(t = 0; t < 50; t++) gameport_read(gameport);
+		for (t = 0; t < 50; t++) gameport_read(gameport);
 		GET_TIME(t2);
 		GET_TIME(t3);
 		local_irq_restore(flags);
@@ -87,10 +113,36 @@
 	gameport_close(gameport);
 	return 59659 / (tx < 1 ? 1 : tx);
 
+#elif defined (__x86_64__)
+
+	unsigned int i, t;
+	unsigned long tx, t1, t2, flags;
+
+	if (gameport_open(gameport, NULL, GAMEPORT_MODE_RAW))
+		return 0;
+
+	tx = 1 << 30;
+
+	for(i = 0; i < 50; i++) {
+		local_irq_save(flags);
+		rdtscl(t1);
+		for (t = 0; t < 50; t++) gameport_read(gameport);
+		rdtscl(t2);
+		local_irq_restore(flags);
+		udelay(i * 10);
+		if (t2 - t1 < tx) tx = t2 - t1;
+	}
+
+	gameport_close(gameport);
+	return (cpu_data[_smp_processor_id()].loops_per_jiffy * (unsigned long)HZ / (1000 / 50)) / (tx < 1 ? 1 : tx);
+
 #else
 
 	unsigned int j, t = 0;
 
+	if (gameport_open(gameport, NULL, GAMEPORT_MODE_RAW))
+		return 0;
+
 	j = jiffies; while (j == jiffies);
 	j = jiffies; while (j == jiffies) { t++; gameport_read(gameport); }
 
@@ -100,81 +152,646 @@
 #endif
 }
 
-static void gameport_find_dev(struct gameport *gameport)
+void gameport_start_polling(struct gameport *gameport)
+{
+	spin_lock(&gameport->timer_lock);
+
+	if (!gameport->poll_cnt++) {
+		BUG_ON(!gameport->poll_handler);
+		BUG_ON(!gameport->poll_interval);
+		mod_timer(&gameport->poll_timer, jiffies + msecs_to_jiffies(gameport->poll_interval));
+	}
+
+	spin_unlock(&gameport->timer_lock);
+}
+
+void gameport_stop_polling(struct gameport *gameport)
+{
+	spin_lock(&gameport->timer_lock);
+
+	if (!--gameport->poll_cnt)
+		del_timer(&gameport->poll_timer);
+
+	spin_unlock(&gameport->timer_lock);
+}
+
+static void gameport_run_poll_handler(unsigned long d)
+{
+	struct gameport *gameport = (struct gameport *)d;
+
+	gameport->poll_handler(gameport);
+	if (gameport->poll_cnt)
+		mod_timer(&gameport->poll_timer, jiffies + msecs_to_jiffies(gameport->poll_interval));
+}
+
+/*
+ * Basic gameport -> driver core mappings
+ */
+
+static void gameport_bind_driver(struct gameport *gameport, struct gameport_driver *drv)
+{
+	down_write(&gameport_bus.subsys.rwsem);
+
+	gameport->dev.driver = &drv->driver;
+	if (drv->connect(gameport, drv)) {
+		gameport->dev.driver = NULL;
+		goto out;
+	}
+	device_bind_driver(&gameport->dev);
+out:
+	up_write(&gameport_bus.subsys.rwsem);
+}
+
+static void gameport_release_driver(struct gameport *gameport)
+{
+	down_write(&gameport_bus.subsys.rwsem);
+	device_release_driver(&gameport->dev);
+	up_write(&gameport_bus.subsys.rwsem);
+}
+
+static void gameport_find_driver(struct gameport *gameport)
+{
+	down_write(&gameport_bus.subsys.rwsem);
+	device_attach(&gameport->dev);
+	up_write(&gameport_bus.subsys.rwsem);
+}
+
+
+/*
+ * Gameport event processing.
+ */
+
+enum gameport_event_type {
+	GAMEPORT_RESCAN,
+	GAMEPORT_RECONNECT,
+	GAMEPORT_REGISTER_PORT,
+	GAMEPORT_REGISTER_DRIVER,
+};
+
+struct gameport_event {
+	enum gameport_event_type type;
+	void *object;
+	struct module *owner;
+	struct list_head node;
+};
+
+static DEFINE_SPINLOCK(gameport_event_lock);	/* protects gameport_event_list */
+static LIST_HEAD(gameport_event_list);
+static DECLARE_WAIT_QUEUE_HEAD(gameport_wait);
+static DECLARE_COMPLETION(gameport_exited);
+static int gameport_pid;
+
+static void gameport_queue_event(void *object, struct module *owner,
+			      enum gameport_event_type event_type)
 {
-        struct gameport_dev *dev;
+	unsigned long flags;
+	struct gameport_event *event;
+
+	spin_lock_irqsave(&gameport_event_lock, flags);
 
-        list_for_each_entry(dev, &gameport_dev_list, node) {
-		if (gameport->dev)
+	/*
+ 	 * Scan event list for the other events for the same gameport port,
+	 * starting with the most recent one. If event is the same we
+	 * do not need add new one. If event is of different type we
+	 * need to add this event and should not look further because
+	 * we need to preseve sequence of distinct events.
+ 	 */
+	list_for_each_entry_reverse(event, &gameport_event_list, node) {
+		if (event->object == object) {
+			if (event->type == event_type)
+				goto out;
 			break;
-		if (dev->connect)
-                	dev->connect(gameport, dev);
-        }
+		}
+	}
+
+	if ((event = kmalloc(sizeof(struct gameport_event), GFP_ATOMIC))) {
+		if (!try_module_get(owner)) {
+			printk(KERN_WARNING "gameport: Can't get module reference, dropping event %d\n", event_type);
+			goto out;
+		}
+
+		event->type = event_type;
+		event->object = object;
+		event->owner = owner;
+
+		list_add_tail(&event->node, &gameport_event_list);
+		wake_up(&gameport_wait);
+	} else {
+		printk(KERN_ERR "gameport: Not enough memory to queue event %d\n", event_type);
+	}
+out:
+	spin_unlock_irqrestore(&gameport_event_lock, flags);
 }
 
-void gameport_rescan(struct gameport *gameport)
+static void gameport_free_event(struct gameport_event *event)
 {
-	gameport_close(gameport);
-	gameport_find_dev(gameport);
+	module_put(event->owner);
+	kfree(event);
 }
 
-void gameport_register_port(struct gameport *gameport)
+static void gameport_remove_duplicate_events(struct gameport_event *event)
 {
-	list_add_tail(&gameport->node, &gameport_list);
+	struct list_head *node, *next;
+	struct gameport_event *e;
+	unsigned long flags;
+
+	spin_lock_irqsave(&gameport_event_lock, flags);
+
+	list_for_each_safe(node, next, &gameport_event_list) {
+		e = list_entry(node, struct gameport_event, node);
+		if (event->object == e->object) {
+			/*
+			 * If this event is of different type we should not
+			 * look further - we only suppress duplicate events
+			 * that were sent back-to-back.
+			 */
+			if (event->type != e->type)
+				break;
+
+			list_del_init(node);
+			gameport_free_event(e);
+		}
+	}
+
+	spin_unlock_irqrestore(&gameport_event_lock, flags);
+}
+
+
+static struct gameport_event *gameport_get_event(void)
+{
+	struct gameport_event *event;
+	struct list_head *node;
+	unsigned long flags;
+
+	spin_lock_irqsave(&gameport_event_lock, flags);
+
+	if (list_empty(&gameport_event_list)) {
+		spin_unlock_irqrestore(&gameport_event_lock, flags);
+		return NULL;
+	}
+
+	node = gameport_event_list.next;
+	event = list_entry(node, struct gameport_event, node);
+	list_del_init(node);
+
+	spin_unlock_irqrestore(&gameport_event_lock, flags);
+
+	return event;
+}
+
+static void gameport_handle_events(void)
+{
+	struct gameport_event *event;
+	struct gameport_driver *gameport_drv;
+
+	down(&gameport_sem);
+
+	while ((event = gameport_get_event())) {
+
+		switch (event->type) {
+			case GAMEPORT_REGISTER_PORT:
+				gameport_add_port(event->object);
+				break;
+
+			case GAMEPORT_RECONNECT:
+				gameport_reconnect_port(event->object);
+				break;
+
+			case GAMEPORT_RESCAN:
+				gameport_disconnect_port(event->object);
+				gameport_find_driver(event->object);
+				break;
+
+			case GAMEPORT_REGISTER_DRIVER:
+				gameport_drv = event->object;
+				driver_register(&gameport_drv->driver);
+				break;
+
+			default:
+				break;
+		}
+
+		gameport_remove_duplicate_events(event);
+		gameport_free_event(event);
+	}
+
+	up(&gameport_sem);
+}
+
+/*
+ * Remove all events that have been submitted for a given gameport port.
+ */
+static void gameport_remove_pending_events(struct gameport *gameport)
+{
+	struct list_head *node, *next;
+	struct gameport_event *event;
+	unsigned long flags;
+
+	spin_lock_irqsave(&gameport_event_lock, flags);
+
+	list_for_each_safe(node, next, &gameport_event_list) {
+		event = list_entry(node, struct gameport_event, node);
+		if (event->object == gameport) {
+			list_del_init(node);
+			gameport_free_event(event);
+		}
+	}
+
+	spin_unlock_irqrestore(&gameport_event_lock, flags);
+}
+
+/*
+ * Destroy child gameport port (if any) that has not been fully registered yet.
+ *
+ * Note that we rely on the fact that port can have only one child and therefore
+ * only one child registration request can be pending. Additionally, children
+ * are registered by driver's connect() handler so there can't be a grandchild
+ * pending registration together with a child.
+ */
+static struct gameport *gameport_get_pending_child(struct gameport *parent)
+{
+	struct gameport_event *event;
+	struct gameport *gameport, *child = NULL;
+	unsigned long flags;
+
+	spin_lock_irqsave(&gameport_event_lock, flags);
+
+	list_for_each_entry(event, &gameport_event_list, node) {
+		if (event->type == GAMEPORT_REGISTER_PORT) {
+			gameport = event->object;
+			if (gameport->parent == parent) {
+				child = gameport;
+				break;
+			}
+		}
+	}
+
+	spin_unlock_irqrestore(&gameport_event_lock, flags);
+	return child;
+}
+
+static int gameport_thread(void *nothing)
+{
+	lock_kernel();
+	daemonize("kgameportd");
+	allow_signal(SIGTERM);
+
+	do {
+		gameport_handle_events();
+		wait_event_interruptible(gameport_wait, !list_empty(&gameport_event_list));
+		try_to_freeze(PF_FREEZE);
+	} while (!signal_pending(current));
+
+	printk(KERN_DEBUG "gameport: kgameportd exiting\n");
+
+	unlock_kernel();
+	complete_and_exit(&gameport_exited, 0);
+}
+
+
+/*
+ * Gameport port operations
+ */
+
+static ssize_t gameport_show_description(struct device *dev, char *buf)
+{
+	struct gameport *gameport = to_gameport_port(dev);
+	return sprintf(buf, "%s\n", gameport->name);
+}
+
+static ssize_t gameport_rebind_driver(struct device *dev, const char *buf, size_t count)
+{
+	struct gameport *gameport = to_gameport_port(dev);
+	struct device_driver *drv;
+	int retval;
+
+	retval = down_interruptible(&gameport_sem);
+	if (retval)
+		return retval;
+
+	retval = count;
+	if (!strncmp(buf, "none", count)) {
+		gameport_disconnect_port(gameport);
+	} else if (!strncmp(buf, "reconnect", count)) {
+		gameport_reconnect_port(gameport);
+	} else if (!strncmp(buf, "rescan", count)) {
+		gameport_disconnect_port(gameport);
+		gameport_find_driver(gameport);
+	} else if ((drv = driver_find(buf, &gameport_bus)) != NULL) {
+		gameport_disconnect_port(gameport);
+		gameport_bind_driver(gameport, to_gameport_driver(drv));
+		put_driver(drv);
+	} else {
+		retval = -EINVAL;
+	}
+
+	up(&gameport_sem);
+
+	return retval;
+}
+
+static struct device_attribute gameport_device_attrs[] = {
+	__ATTR(description, S_IRUGO, gameport_show_description, NULL),
+	__ATTR(drvctl, S_IWUSR, NULL, gameport_rebind_driver),
+	__ATTR_NULL
+};
+
+static void gameport_release_port(struct device *dev)
+{
+	struct gameport *gameport = to_gameport_port(dev);
+
+	kfree(gameport);
+	module_put(THIS_MODULE);
+}
+
+void gameport_set_phys(struct gameport *gameport, const char *fmt, ...)
+{
+	va_list args;
+
+	va_start(args, fmt);
+	vsnprintf(gameport->phys, sizeof(gameport->phys), fmt, args);
+	va_end(args);
+}
+
+/*
+ * Prepare gameport port for registration.
+ */
+static void gameport_init_port(struct gameport *gameport)
+{
+	static atomic_t gameport_no = ATOMIC_INIT(0);
+
+	__module_get(THIS_MODULE);
+
+	init_MUTEX(&gameport->drv_sem);
+	device_initialize(&gameport->dev);
+	snprintf(gameport->dev.bus_id, sizeof(gameport->dev.bus_id),
+		 "gameport%lu", (unsigned long)atomic_inc_return(&gameport_no) - 1);
+	gameport->dev.bus = &gameport_bus;
+	gameport->dev.release = gameport_release_port;
+	if (gameport->parent)
+		gameport->dev.parent = &gameport->parent->dev;
+
+	spin_lock_init(&gameport->timer_lock);
+	init_timer(&gameport->poll_timer);
+	gameport->poll_timer.function = gameport_run_poll_handler;
+	gameport->poll_timer.data = (unsigned long)gameport;
+}
+
+/*
+ * Complete gameport port registration.
+ * Driver core will attempt to find appropriate driver for the port.
+ */
+static void gameport_add_port(struct gameport *gameport)
+{
+	if (gameport->parent)
+		gameport->parent->child = gameport;
+
 	gameport->speed = gameport_measure_speed(gameport);
-	gameport_find_dev(gameport);
+
+	list_add_tail(&gameport->node, &gameport_list);
+
+	if (gameport->io)
+		printk(KERN_INFO "gameport: %s is %s, io %#x, speed %dkHz\n",
+			gameport->name, gameport->phys, gameport->io, gameport->speed);
+	else
+		printk(KERN_INFO "gameport: %s is %s, speed %dkHz\n",
+			gameport->name, gameport->phys, gameport->speed);
+
+	device_add(&gameport->dev);
+	gameport->registered = 1;
+}
+
+/*
+ * gameport_destroy_port() completes deregistration process and removes
+ * port from the system
+ */
+static void gameport_destroy_port(struct gameport *gameport)
+{
+	struct gameport *child;
+
+	child = gameport_get_pending_child(gameport);
+	if (child) {
+		gameport_remove_pending_events(child);
+		put_device(&child->dev);
+	}
+
+	if (gameport->parent) {
+		gameport->parent->child = NULL;
+		gameport->parent = NULL;
+	}
+
+	if (gameport->registered) {
+		device_del(&gameport->dev);
+		list_del_init(&gameport->node);
+		gameport->registered = 0;
+	}
+
+	gameport_remove_pending_events(gameport);
+	put_device(&gameport->dev);
 }
 
+/*
+ * Reconnect gameport port and all its children (re-initialize attached devices)
+ */
+static void gameport_reconnect_port(struct gameport *gameport)
+{
+	do {
+		if (!gameport->drv || !gameport->drv->reconnect || gameport->drv->reconnect(gameport)) {
+			gameport_disconnect_port(gameport);
+			gameport_find_driver(gameport);
+			/* Ok, old children are now gone, we are done */
+			break;
+		}
+		gameport = gameport->child;
+	} while (gameport);
+}
+
+/*
+ * gameport_disconnect_port() unbinds a port from its driver. As a side effect
+ * all child ports are unbound and destroyed.
+ */
+static void gameport_disconnect_port(struct gameport *gameport)
+{
+	struct gameport *s, *parent;
+
+	if (gameport->child) {
+		/*
+		 * Children ports should be disconnected and destroyed
+		 * first, staring with the leaf one, since we don't want
+		 * to do recursion
+		 */
+		for (s = gameport; s->child; s = s->child)
+			/* empty */;
+
+		do {
+			parent = s->parent;
+
+			gameport_release_driver(s);
+			gameport_destroy_port(s);
+		} while ((s = parent) != gameport);
+	}
+
+	/*
+	 * Ok, no children left, now disconnect this port
+	 */
+	gameport_release_driver(gameport);
+}
+
+void gameport_rescan(struct gameport *gameport)
+{
+	gameport_queue_event(gameport, NULL, GAMEPORT_RESCAN);
+}
+
+void gameport_reconnect(struct gameport *gameport)
+{
+	gameport_queue_event(gameport, NULL, GAMEPORT_RECONNECT);
+}
+
+/*
+ * Submits register request to kgameportd for subsequent execution.
+ * Note that port registration is always asynchronous.
+ */
+void __gameport_register_port(struct gameport *gameport, struct module *owner)
+{
+	gameport_init_port(gameport);
+	gameport_queue_event(gameport, owner, GAMEPORT_REGISTER_PORT);
+}
+
+/*
+ * Synchronously unregisters gameport port.
+ */
 void gameport_unregister_port(struct gameport *gameport)
 {
-	list_del_init(&gameport->node);
-	if (gameport->dev && gameport->dev->disconnect)
-		gameport->dev->disconnect(gameport);
+	down(&gameport_sem);
+	gameport_disconnect_port(gameport);
+	gameport_destroy_port(gameport);
+	up(&gameport_sem);
 }
 
-void gameport_register_device(struct gameport_dev *dev)
+
+/*
+ * Gameport driver operations
+ */
+
+static ssize_t gameport_driver_show_description(struct device_driver *drv, char *buf)
 {
-	struct gameport *gameport;
+	struct gameport_driver *driver = to_gameport_driver(drv);
+	return sprintf(buf, "%s\n", driver->description ? driver->description : "(none)");
+}
+
+static struct driver_attribute gameport_driver_attrs[] = {
+	__ATTR(description, S_IRUGO, gameport_driver_show_description, NULL),
+	__ATTR_NULL
+};
+
+static int gameport_driver_probe(struct device *dev)
+{
+	struct gameport *gameport = to_gameport_port(dev);
+	struct gameport_driver *drv = to_gameport_driver(dev->driver);
+
+	drv->connect(gameport, drv);
+	return gameport->drv ? 0 : -ENODEV;
+}
+
+static int gameport_driver_remove(struct device *dev)
+{
+	struct gameport *gameport = to_gameport_port(dev);
+	struct gameport_driver *drv = to_gameport_driver(dev->driver);
+
+	drv->disconnect(gameport);
+	return 0;
+}
 
-	list_add_tail(&dev->node, &gameport_dev_list);
-	list_for_each_entry(gameport, &gameport_list, node)
-		if (!gameport->dev && dev->connect)
-			dev->connect(gameport, dev);
+void __gameport_register_driver(struct gameport_driver *drv, struct module *owner)
+{
+	drv->driver.bus = &gameport_bus;
+	drv->driver.probe = gameport_driver_probe;
+	drv->driver.remove = gameport_driver_remove;
+	gameport_queue_event(drv, owner, GAMEPORT_REGISTER_DRIVER);
 }
 
-void gameport_unregister_device(struct gameport_dev *dev)
+void gameport_unregister_driver(struct gameport_driver *drv)
 {
 	struct gameport *gameport;
 
-	list_del_init(&dev->node);
+	down(&gameport_sem);
+	drv->ignore = 1;	/* so gameport_find_driver ignores it */
+
+start_over:
 	list_for_each_entry(gameport, &gameport_list, node) {
-		if (gameport->dev == dev && dev->disconnect)
-			dev->disconnect(gameport);
-		gameport_find_dev(gameport);
+		if (gameport->drv == drv) {
+			gameport_disconnect_port(gameport);
+			gameport_find_driver(gameport);
+			/* we could've deleted some ports, restart */
+			goto start_over;
+		}
 	}
+
+	driver_unregister(&drv->driver);
+	up(&gameport_sem);
 }
 
-int gameport_open(struct gameport *gameport, struct gameport_dev *dev, int mode)
+static int gameport_bus_match(struct device *dev, struct device_driver *drv)
 {
+	struct gameport_driver *gameport_drv = to_gameport_driver(drv);
+
+	return !gameport_drv->ignore;
+}
+
+static void gameport_set_drv(struct gameport *gameport, struct gameport_driver *drv)
+{
+	down(&gameport->drv_sem);
+	gameport->drv = drv;
+	up(&gameport->drv_sem);
+}
+
+int gameport_open(struct gameport *gameport, struct gameport_driver *drv, int mode)
+{
+
 	if (gameport->open) {
-		if (gameport->open(gameport, mode))
+		if (gameport->open(gameport, mode)) {
 			return -1;
+		}
 	} else {
 		if (mode != GAMEPORT_MODE_RAW)
 			return -1;
 	}
 
-	if (gameport->dev)
-		return -1;
-
-	gameport->dev = dev;
-
+	gameport_set_drv(gameport, drv);
 	return 0;
 }
 
 void gameport_close(struct gameport *gameport)
 {
-	gameport->dev = NULL;
+	del_timer_sync(&gameport->poll_timer);
+	gameport->poll_handler = NULL;
+	gameport->poll_interval = 0;
+	gameport_set_drv(gameport, NULL);
 	if (gameport->close)
 		gameport->close(gameport);
 }
+
+static int __init gameport_init(void)
+{
+	if (!(gameport_pid = kernel_thread(gameport_thread, NULL, CLONE_KERNEL))) {
+		printk(KERN_ERR "gameport: Failed to start kgameportd\n");
+		return -1;
+	}
+
+	gameport_bus.dev_attrs = gameport_device_attrs;
+	gameport_bus.drv_attrs = gameport_driver_attrs;
+	gameport_bus.match = gameport_bus_match;
+	bus_register(&gameport_bus);
+
+	return 0;
+}
+
+static void __exit gameport_exit(void)
+{
+	bus_unregister(&gameport_bus);
+	kill_proc(gameport_pid, SIGTERM, 1);
+	wait_for_completion(&gameport_exited);
+}
+
+module_init(gameport_init);
+module_exit(gameport_exit);
diff -Nru a/drivers/input/gameport/lightning.c b/drivers/input/gameport/lightning.c
--- a/drivers/input/gameport/lightning.c	2005-03-11 12:51:42 -08:00
+++ b/drivers/input/gameport/lightning.c	2005-03-11 12:51:42 -08:00
@@ -54,12 +54,11 @@
 MODULE_LICENSE("GPL");
 
 struct l4 {
-	struct gameport gameport;
+	struct gameport *gameport;
 	unsigned char port;
-	char phys[32];
-} *l4_port[8];
+};
 
-char l4_name[] = "PDPI Lightning 4";
+static struct l4 l4_ports[8];
 
 /*
  * l4_wait_ready() waits for the L4 to become ready.
@@ -67,10 +66,10 @@
 
 static int l4_wait_ready(void)
 {
-	unsigned int t;
-	t = L4_TIMEOUT;
+	unsigned int t = L4_TIMEOUT;
+
 	while ((inb(L4_PORT) & L4_BUSY) && t > 0) t--;
-	return -(t<=0);
+	return -(t <= 0);
 }
 
 /*
@@ -79,7 +78,7 @@
 
 static int l4_cooked_read(struct gameport *gameport, int *axes, int *buttons)
 {
-	struct l4 *l4 = gameport->driver;
+	struct l4 *l4 = gameport->port_data;
 	unsigned char status;
 	int i, result = -1;
 
@@ -112,7 +111,8 @@
 
 static int l4_open(struct gameport *gameport, int mode)
 {
-	struct l4 *l4 = gameport->driver;
+	struct l4 *l4 = gameport->port_data;
+
         if (l4->port != 0 && mode != GAMEPORT_MODE_COOKED)
 		return -1;
 	outb(L4_SELECT_ANALOG, L4_PORT);
@@ -129,24 +129,29 @@
 
 	outb(L4_SELECT_ANALOG, L4_PORT);
 	outb(L4_SELECT_DIGITAL + (port >> 2), L4_PORT);
+	if (inb(L4_PORT) & L4_BUSY)
+		goto out;
 
-	if (inb(L4_PORT) & L4_BUSY) goto fail;
 	outb(L4_CMD_GETCAL, L4_PORT);
+	if (l4_wait_ready())
+		goto out;
 
-	if (l4_wait_ready()) goto fail;
-	if (inb(L4_PORT) != L4_SELECT_DIGITAL + (port >> 2)) goto fail;
+	if (inb(L4_PORT) != L4_SELECT_DIGITAL + (port >> 2))
+		goto out;
 
-	if (l4_wait_ready()) goto fail;
+	if (l4_wait_ready())
+		goto out;
         outb(port & 3, L4_PORT);
 
 	for (i = 0; i < 4; i++) {
-		if (l4_wait_ready()) goto fail;
+		if (l4_wait_ready())
+			goto out;
 		cal[i] = inb(L4_PORT);
 	}
 
 	result = 0;
 
-fail:	outb(L4_SELECT_ANALOG, L4_PORT);
+out:	outb(L4_SELECT_ANALOG, L4_PORT);
 	return result;
 }
 
@@ -160,24 +165,29 @@
 
 	outb(L4_SELECT_ANALOG, L4_PORT);
 	outb(L4_SELECT_DIGITAL + (port >> 2), L4_PORT);
+	if (inb(L4_PORT) & L4_BUSY)
+		goto out;
 
-	if (inb(L4_PORT) & L4_BUSY) goto fail;
 	outb(L4_CMD_SETCAL, L4_PORT);
+	if (l4_wait_ready())
+		goto out;
 
-	if (l4_wait_ready()) goto fail;
-	if (inb(L4_PORT) != L4_SELECT_DIGITAL + (port >> 2)) goto fail;
+	if (inb(L4_PORT) != L4_SELECT_DIGITAL + (port >> 2))
+		goto out;
 
-	if (l4_wait_ready()) goto fail;
+	if (l4_wait_ready())
+		goto out;
         outb(port & 3, L4_PORT);
 
 	for (i = 0; i < 4; i++) {
-		if (l4_wait_ready()) goto fail;
+		if (l4_wait_ready())
+			goto out;
 		outb(cal[i], L4_PORT);
 	}
 
 	result = 0;
 
-fail:	outb(L4_SELECT_ANALOG, L4_PORT);
+out:	outb(L4_SELECT_ANALOG, L4_PORT);
 	return result;
 }
 
@@ -190,7 +200,7 @@
 {
 	int i, t;
 	int cal[4];
-	struct l4 *l4 = gameport->driver;
+	struct l4 *l4 = gameport->port_data;
 
 	if (l4_getcal(l4->port, cal))
 		return -1;
@@ -209,73 +219,102 @@
 	return 0;
 }
 
-static int __init l4_init(void)
+static int __init l4_create_ports(int card_no)
 {
-	int cal[4] = {255,255,255,255};
-	int i, j, rev, cards = 0;
-	struct gameport *gameport;
 	struct l4 *l4;
+	struct gameport *port;
+	int i, idx;
 
-	if (!request_region(L4_PORT, 1, "lightning"))
-		return -1;
+	for (i = 0; i < 4; i++) {
 
-	for (i = 0; i < 2; i++) {
+		idx = card_no * 4 + i;
+		l4 = &l4_ports[idx];
 
-		outb(L4_SELECT_ANALOG, L4_PORT);
-		outb(L4_SELECT_DIGITAL + i, L4_PORT);
+		if (!(l4->gameport = port = gameport_allocate_port())) {
+			printk(KERN_ERR "lightning: Memory allocation failed\n");
+			while (--i >= 0) {
+				gameport_free_port(l4->gameport);
+				l4->gameport = NULL;
+			}
+			return -ENOMEM;
+		}
+		l4->port = idx;
 
-		if (inb(L4_PORT) & L4_BUSY) continue;
-		outb(L4_CMD_ID, L4_PORT);
+		port->port_data = l4;
+		port->open = l4_open;
+		port->cooked_read = l4_cooked_read;
+		port->calibrate = l4_calibrate;
 
-		if (l4_wait_ready()) continue;
-		if (inb(L4_PORT) != L4_SELECT_DIGITAL + i) continue;
+		gameport_set_name(port, "PDPI Lightning 4");
+		gameport_set_phys(port, "isa%04x/gameport%d", L4_PORT, idx);
 
-		if (l4_wait_ready()) continue;
-		if (inb(L4_PORT) != L4_ID) continue;
+		if (idx == 0)
+			port->io = L4_PORT;
+	}
 
-		if (l4_wait_ready()) continue;
-		rev = inb(L4_PORT);
+	return 0;
+}
 
-		if (!rev) continue;
+static int __init l4_add_card(int card_no)
+{
+	int cal[4] = { 255, 255, 255, 255 };
+	int i, rev, result;
+	struct l4 *l4;
 
-		if (!(l4_port[i * 4] = kmalloc(sizeof(struct l4) * 4, GFP_KERNEL))) {
-			printk(KERN_ERR "lightning: Out of memory allocating ports.\n");
-			continue;
-		}
-		memset(l4_port[i * 4], 0, sizeof(struct l4) * 4);
+	outb(L4_SELECT_ANALOG, L4_PORT);
+	outb(L4_SELECT_DIGITAL + card_no, L4_PORT);
 
-		for (j = 0; j < 4; j++) {
+	if (inb(L4_PORT) & L4_BUSY)
+		return -1;
+	outb(L4_CMD_ID, L4_PORT);
 
-			l4 = l4_port[i * 4 + j] = l4_port[i * 4] + j;
-			l4->port = i * 4 + j;
+	if (l4_wait_ready())
+		return -1;
 
-			sprintf(l4->phys, "isa%04x/gameport%d", L4_PORT, 4 * i + j);
+	if (inb(L4_PORT) != L4_SELECT_DIGITAL + card_no)
+		return -1;
 
-			gameport = &l4->gameport;
-			gameport->driver = l4;
-			gameport->open = l4_open;
-			gameport->cooked_read = l4_cooked_read;
-			gameport->calibrate = l4_calibrate;
+	if (l4_wait_ready())
+		return -1;
+	if (inb(L4_PORT) != L4_ID)
+		return -1;
 
-			gameport->name = l4_name;
-			gameport->phys = l4->phys;
-			gameport->id.bustype = BUS_ISA;
+	if (l4_wait_ready())
+		return -1;
+	rev = inb(L4_PORT);
 
-			if (!i && !j)
-				gameport->io = L4_PORT;
+	if (!rev)
+		return -1;
 
-			if (rev > 0x28)		/* on 2.9+ the setcal command works correctly */
-				l4_setcal(l4->port, cal);
+	result = l4_create_ports(card_no);
+	if (result)
+		return result;
 
-			gameport_register_port(gameport);
-		}
+	printk(KERN_INFO "gameport: PDPI Lightning 4 %s card v%d.%d at %#x\n",
+		card_no ? "secondary" : "primary", rev >> 4, rev, L4_PORT);
 
-		printk(KERN_INFO "gameport: PDPI Lightning 4 %s card v%d.%d at %#x\n",
-			i ? "secondary" : "primary", rev >> 4, rev, L4_PORT);
+	for (i = 0; i < 4; i++) {
+		l4 = &l4_ports[card_no * 4 + i];
 
-		cards++;
+		if (rev > 0x28)		/* on 2.9+ the setcal command works correctly */
+			l4_setcal(l4->port, cal);
+		gameport_register_port(l4->gameport);
 	}
 
+	return 0;
+}
+
+static int __init l4_init(void)
+{
+	int i, cards = 0;
+
+	if (!request_region(L4_PORT, 1, "lightning"))
+		return -1;
+
+	for (i = 0; i < 2; i++)
+		if (l4_add_card(i) == 0)
+			cards++;
+
 	outb(L4_SELECT_ANALOG, L4_PORT);
 
 	if (!cards) {
@@ -289,13 +328,14 @@
 static void __exit l4_exit(void)
 {
 	int i;
-	int cal[4] = {59, 59, 59, 59};
+	int cal[4] = { 59, 59, 59, 59 };
 
 	for (i = 0; i < 8; i++)
-		if (l4_port[i]) {
-			l4_setcal(l4_port[i]->port, cal);
-			gameport_unregister_port(&l4_port[i]->gameport);
+		if (l4_ports[i].gameport) {
+			l4_setcal(l4_ports[i].port, cal);
+			gameport_unregister_port(l4_ports[i].gameport);
 		}
+
 	outb(L4_SELECT_ANALOG, L4_PORT);
 	release_region(L4_PORT, 1);
 }
diff -Nru a/drivers/input/gameport/ns558.c b/drivers/input/gameport/ns558.c
--- a/drivers/input/gameport/ns558.c	2005-03-11 12:51:51 -08:00
+++ b/drivers/input/gameport/ns558.c	2005-03-11 12:51:51 -08:00
@@ -44,20 +44,16 @@
 MODULE_DESCRIPTION("Classic gameport (ISA/PnP) driver");
 MODULE_LICENSE("GPL");
 
-#define NS558_ISA	1
-#define NS558_PNP	2
-
 static int ns558_isa_portlist[] = { 0x201, 0x200, 0x202, 0x203, 0x204, 0x205, 0x207, 0x209,
 				    0x20b, 0x20c, 0x20e, 0x20f, 0x211, 0x219, 0x101, 0 };
 
 struct ns558 {
 	int type;
+	int io;
 	int size;
 	struct pnp_dev *dev;
+	struct gameport *gameport;
 	struct list_head node;
-	struct gameport gameport;
-	char phys[32];
-	char name[32];
 };
 
 static LIST_HEAD(ns558_list);
@@ -68,18 +64,19 @@
  * A joystick must be attached for this to work.
  */
 
-static void ns558_isa_probe(int io)
+static int ns558_isa_probe(int io)
 {
 	int i, j, b;
 	unsigned char c, u, v;
-	struct ns558 *port;
+	struct ns558 *ns558;
+	struct gameport *port;
 
 /*
  * No one should be using this address.
  */
 
 	if (!request_region(io, 1, "ns558-isa"))
-		return;
+		return -EBUSY;
 
 /*
  * We must not be able to write arbitrary values to the port.
@@ -90,8 +87,8 @@
 	outb(~c & ~3, io);
 	if (~(u = v = inb(io)) & 3) {
 		outb(c, io);
-		i = 0;
-		goto out;
+		release_region(io, 1);
+		return -ENODEV;
 	}
 /*
  * After a trigger, there must be at least some bits changing.
@@ -101,8 +98,8 @@
 
 	if (u == v) {
 		outb(c, io);
-		i = 0;
-		goto out;
+		release_region(io, 1);
+		return -ENODEV;
 	}
 	msleep(3);
 /*
@@ -113,8 +110,8 @@
 	for (i = 0; i < 1000; i++)
 		if ((u ^ inb(io)) & 0xf) {
 			outb(c, io);
-			i = 0;
-			goto out;
+			release_region(io, 1);
+			return -ENODEV;
 		}
 /*
  * And now find the number of mirrors of the port.
@@ -122,17 +119,17 @@
 
 	for (i = 1; i < 5; i++) {
 
-		release_region(io & (-1 << (i-1)), (1 << (i-1)));
+		release_region(io & (-1 << (i - 1)), (1 << (i - 1)));
 
-		if (!request_region(io & (-1 << i), (1 << i), "ns558-isa"))	/* Don't disturb anyone */
-			break;
+		if (!request_region(io & (-1 << i), (1 << i), "ns558-isa"))
+			break;				/* Don't disturb anyone */
 
 		outb(0xff, io & (-1 << i));
 		for (j = b = 0; j < 1000; j++)
 			if (inb(io & (-1 << i)) != inb((io & (-1 << i)) + (1 << i) - 1)) b++;
 		msleep(3);
 
-		if (b > 300) {					/* We allow 30% difference */
+		if (b > 300) {				/* We allow 30% difference */
 			release_region(io & (-1 << i), (1 << i));
 			break;
 		}
@@ -142,35 +139,33 @@
 
 	if (i != 4) {
 		if (!request_region(io & (-1 << i), (1 << i), "ns558-isa"))
-			return;
+			return -EBUSY;
 	}
 
-	if (!(port = kmalloc(sizeof(struct ns558), GFP_KERNEL))) {
+	ns558 = kcalloc(1, sizeof(struct ns558), GFP_KERNEL);
+	port = gameport_allocate_port();
+	if (!ns558 || !port) {
 		printk(KERN_ERR "ns558: Memory allocation failed.\n");
-		goto out;
+		release_region(io & (-1 << i), (1 << i));
+		kfree(ns558);
+		gameport_free_port(port);
+		return -ENOMEM;
 	}
-	memset(port, 0, sizeof(struct ns558));
 
-	port->type = NS558_ISA;
-	port->size = (1 << i);
-	port->gameport.io = io;
-	port->gameport.phys = port->phys;
-	port->gameport.name = port->name;
-	port->gameport.id.bustype = BUS_ISA;
-
-	sprintf(port->phys, "isa%04x/gameport0", io & (-1 << i));
-	sprintf(port->name, "NS558 ISA");
-
-	gameport_register_port(&port->gameport);
-
-	printk(KERN_INFO "gameport: NS558 ISA at %#x", port->gameport.io);
-	if (port->size > 1) printk(" size %d", port->size);
-	printk(" speed %d kHz\n", port->gameport.speed);
-
-	list_add(&port->node, &ns558_list);
-	return;
-out:
-	release_region(io & (-1 << i), (1 << i));
+	memset(ns558, 0, sizeof(struct ns558));
+	ns558->io = io;
+	ns558->size = 1 << i;
+	ns558->gameport = port;
+
+	port->io = io;
+	gameport_set_name(port, "NS558 ISA Gameport");
+	gameport_set_phys(port, "isa%04x/gameport0", io & (-1 << i));
+
+	gameport_register_port(port);
+
+	list_add(&ns558->node, &ns558_list);
+
+	return 0;
 }
 
 #ifdef CONFIG_PNP
@@ -206,46 +201,42 @@
 static int ns558_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *did)
 {
 	int ioport, iolen;
-	struct ns558 *port;
+	struct ns558 *ns558;
+	struct gameport *port;
 
 	if (!pnp_port_valid(dev, 0)) {
 		printk(KERN_WARNING "ns558: No i/o ports on a gameport? Weird\n");
 		return -ENODEV;
 	}
 
-	ioport = pnp_port_start(dev,0);
-	iolen = pnp_port_len(dev,0);
+	ioport = pnp_port_start(dev, 0);
+	iolen = pnp_port_len(dev, 0);
 
 	if (!request_region(ioport, iolen, "ns558-pnp"))
 		return -EBUSY;
 
-	if (!(port = kmalloc(sizeof(struct ns558), GFP_KERNEL))) {
-		printk(KERN_ERR "ns558: Memory allocation failed.\n");
+	ns558 = kcalloc(1, sizeof(struct ns558), GFP_KERNEL);
+	port = gameport_allocate_port();
+	if (!ns558 || !port) {
+		printk(KERN_ERR "ns558: Memory allocation failed\n");
+		kfree(ns558);
+		gameport_free_port(port);
 		return -ENOMEM;
 	}
-	memset(port, 0, sizeof(struct ns558));
 
-	port->type = NS558_PNP;
-	port->size = iolen;
-	port->dev = dev;
+	ns558->io = ioport;
+	ns558->size = iolen;
+	ns558->dev = dev;
+	ns558->gameport = port;
+
+	gameport_set_name(port, "NS558 PnP Gameport");
+	gameport_set_phys(port, "pnp%s/gameport0", dev->dev.bus_id);
+	port->dev.parent = &dev->dev;
+	port->io = ioport;
 
-	port->gameport.io = ioport;
-	port->gameport.phys = port->phys;
-	port->gameport.name = port->name;
-	port->gameport.id.bustype = BUS_ISAPNP;
-	port->gameport.id.version = 0x100;
+	gameport_register_port(port);
 
-	sprintf(port->phys, "pnp%s/gameport0", dev->dev.bus_id);
-	sprintf(port->name, "%s", "NS558 PnP Gameport");
-
-	gameport_register_port(&port->gameport);
-
-	printk(KERN_INFO "gameport: NS558 PnP at pnp%s io %#x",
-		dev->dev.bus_id, port->gameport.io);
-	if (iolen > 1) printk(" size %d", iolen);
-	printk(" speed %d kHz\n", port->gameport.speed);
-
-	list_add_tail(&port->node, &ns558_list);
+	list_add_tail(&ns558->node, &ns558_list);
 	return 0;
 }
 
@@ -261,43 +252,39 @@
 
 #endif
 
-int __init ns558_init(void)
+static int pnp_registered = 0;
+
+static int __init ns558_init(void)
 {
 	int i = 0;
 
 /*
- * Probe for ISA ports.
+ * Probe ISA ports first so that PnP gets to choose free port addresses
+ * not occupied by the ISA ports.
  */
 
 	while (ns558_isa_portlist[i])
 		ns558_isa_probe(ns558_isa_portlist[i++]);
 
-	pnp_register_driver(&ns558_pnp_driver);
-	return list_empty(&ns558_list) ? -ENODEV : 0;
-}
+	if (pnp_register_driver(&ns558_pnp_driver) >= 0)
+		pnp_registered = 1;
 
-void __exit ns558_exit(void)
-{
-	struct ns558 *port;
 
-	list_for_each_entry(port, &ns558_list, node) {
-		gameport_unregister_port(&port->gameport);
-		switch (port->type) {
+	return (list_empty(&ns558_list) && !pnp_registered) ? -ENODEV : 0;
+}
 
-#ifdef CONFIG_PNP
-			case NS558_PNP:
-				/* fall through */
-#endif
-			case NS558_ISA:
-				release_region(port->gameport.io & ~(port->size - 1), port->size);
-				kfree(port);
-				break;
+static void __exit ns558_exit(void)
+{
+	struct ns558 *ns558;
 
-			default:
-				break;
-		}
+	list_for_each_entry(ns558, &ns558_list, node) {
+		gameport_unregister_port(ns558->gameport);
+		release_region(ns558->io & ~(ns558->size - 1), ns558->size);
+		kfree(ns558);
 	}
-	pnp_unregister_driver(&ns558_pnp_driver);
+
+	if (pnp_registered)
+		pnp_unregister_driver(&ns558_pnp_driver);
 }
 
 module_init(ns558_init);
diff -Nru a/drivers/input/gameport/vortex.c b/drivers/input/gameport/vortex.c
--- a/drivers/input/gameport/vortex.c	2005-03-11 12:51:50 -08:00
+++ b/drivers/input/gameport/vortex.c	2005-03-11 12:51:50 -08:00
@@ -53,28 +53,27 @@
 #define VORTEX_DATA_WAIT	20	/* 20 ms */
 
 struct vortex {
-	struct gameport gameport;
+	struct gameport *gameport;
 	struct pci_dev *dev;
-        unsigned char __iomem *base;
-        unsigned char __iomem *io;
-	char phys[32];
+	unsigned char __iomem *base;
+	unsigned char __iomem *io;
 };
 
 static unsigned char vortex_read(struct gameport *gameport)
 {
-	struct vortex *vortex = gameport->driver;
+	struct vortex *vortex = gameport->port_data;
 	return readb(vortex->io + VORTEX_LEG);
 }
 
 static void vortex_trigger(struct gameport *gameport)
 {
-	struct vortex *vortex = gameport->driver;
+	struct vortex *vortex = gameport->port_data;
 	writeb(0xff, vortex->io + VORTEX_LEG);
 }
 
 static int vortex_cooked_read(struct gameport *gameport, int *axes, int *buttons)
 {
-	struct vortex *vortex = gameport->driver;
+	struct vortex *vortex = gameport->port_data;
 	int i;
 
 	*buttons = (~readb(vortex->base + VORTEX_LEG) >> 4) & 0xf;
@@ -89,7 +88,7 @@
 
 static int vortex_open(struct gameport *gameport, int mode)
 {
-	struct vortex *vortex = gameport->driver;
+	struct vortex *vortex = gameport->port_data;
 
 	switch (mode) {
 		case GAMEPORT_MODE_COOKED:
@@ -109,30 +108,17 @@
 static int __devinit vortex_probe(struct pci_dev *dev, const struct pci_device_id *id)
 {
 	struct vortex *vortex;
+	struct gameport *port;
 	int i;
 
-	if (!(vortex = kmalloc(sizeof(struct vortex), GFP_KERNEL)))
-		return -1;
-        memset(vortex, 0, sizeof(struct vortex));
-
-	vortex->dev = dev;
-	sprintf(vortex->phys, "pci%s/gameport0", pci_name(dev));
-
-	pci_set_drvdata(dev, vortex);
-
-	vortex->gameport.driver = vortex;
-	vortex->gameport.fuzz = 64;
-
-	vortex->gameport.read = vortex_read;
-	vortex->gameport.trigger = vortex_trigger;
-	vortex->gameport.cooked_read = vortex_cooked_read;
-	vortex->gameport.open = vortex_open;
-
-	vortex->gameport.name = pci_name(dev);
-	vortex->gameport.phys = vortex->phys;
-	vortex->gameport.id.bustype = BUS_PCI;
-	vortex->gameport.id.vendor = dev->vendor;
-	vortex->gameport.id.product = dev->device;
+	vortex = kcalloc(1, sizeof(struct vortex), GFP_KERNEL);
+	port = gameport_allocate_port();
+	if (!vortex || !port) {
+		printk(KERN_ERR "vortex: Memory allocation failed.\n");
+		kfree(vortex);
+		gameport_free_port(port);
+		return -ENOMEM;
+	}
 
 	for (i = 0; i < 6; i++)
 		if (~pci_resource_flags(dev, i) & IORESOURCE_IO)
@@ -140,14 +126,26 @@
 
 	pci_enable_device(dev);
 
+	vortex->dev = dev;
+	vortex->gameport = port;
 	vortex->base = ioremap(pci_resource_start(vortex->dev, i),
 				pci_resource_len(vortex->dev, i));
 	vortex->io = vortex->base + id->driver_data;
 
-	gameport_register_port(&vortex->gameport);
+	pci_set_drvdata(dev, vortex);
+
+	port->port_data = vortex;
+	port->fuzz = 64;
 
-	printk(KERN_INFO "gameport at pci%s speed %d kHz\n",
-		pci_name(dev), vortex->gameport.speed);
+	gameport_set_name(port, "AU88x0");
+	gameport_set_phys(port, "pci%s/gameport0", pci_name(dev));
+	port->dev.parent = &dev->dev;
+	port->read = vortex_read;
+	port->trigger = vortex_trigger;
+	port->cooked_read = vortex_cooked_read;
+	port->open = vortex_open;
+
+	gameport_register_port(port);
 
 	return 0;
 }
@@ -155,15 +153,17 @@
 static void __devexit vortex_remove(struct pci_dev *dev)
 {
 	struct vortex *vortex = pci_get_drvdata(dev);
-	gameport_unregister_port(&vortex->gameport);
+
+	gameport_unregister_port(vortex->gameport);
 	iounmap(vortex->base);
 	kfree(vortex);
 }
 
-static struct pci_device_id vortex_id_table[] =
-{{ 0x12eb, 0x0001, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0x11000 },
- { 0x12eb, 0x0002, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0x28800 },
- { 0 }};
+static struct pci_device_id vortex_id_table[] = {
+	{ 0x12eb, 0x0001, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0x11000 },
+	{ 0x12eb, 0x0002, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0x28800 },
+	{ 0 }
+};
 
 static struct pci_driver vortex_driver = {
 	.name =		"vortex_gameport",
@@ -172,12 +172,12 @@
 	.remove =	__devexit_p(vortex_remove),
 };
 
-int __init vortex_init(void)
+static int __init vortex_init(void)
 {
-	return pci_module_init(&vortex_driver);
+	return pci_register_driver(&vortex_driver);
 }
 
-void __exit vortex_exit(void)
+static void __exit vortex_exit(void)
 {
 	pci_unregister_driver(&vortex_driver);
 }
diff -Nru a/drivers/input/input.c b/drivers/input/input.c
--- a/drivers/input/input.c	2005-03-11 12:51:46 -08:00
+++ b/drivers/input/input.c	2005-03-11 12:51:46 -08:00
@@ -50,18 +50,10 @@
 
 #ifdef CONFIG_PROC_FS
 static struct proc_dir_entry *proc_bus_input_dir;
-DECLARE_WAIT_QUEUE_HEAD(input_devices_poll_wait);
+static DECLARE_WAIT_QUEUE_HEAD(input_devices_poll_wait);
 static int input_devices_state;
 #endif
 
-static inline unsigned int ms_to_jiffies(unsigned int ms)
-{
-        unsigned int j;
-        j = (ms * HZ + 500) / 1000;
-        return (j > 0) ? j : 1;
-}
-
-
 void input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
 {
 	struct input_handle *handle;
@@ -96,9 +88,9 @@
 
 			change_bit(code, dev->key);
 
-			if (test_bit(EV_REP, dev->evbit) && dev->rep[REP_PERIOD] && dev->timer.data && value) {
+			if (test_bit(EV_REP, dev->evbit) && dev->rep[REP_PERIOD] && dev->rep[REP_DELAY] && dev->timer.data && value) {
 				dev->repeat_key = code;
-				mod_timer(&dev->timer, jiffies + ms_to_jiffies(dev->rep[REP_DELAY]));
+				mod_timer(&dev->timer, jiffies + msecs_to_jiffies(dev->rep[REP_DELAY]));
 			}
 
 			break;
@@ -198,7 +190,8 @@
 	input_event(dev, EV_KEY, dev->repeat_key, 2);
 	input_sync(dev);
 
-	mod_timer(&dev->timer, jiffies + ms_to_jiffies(dev->rep[REP_PERIOD]));
+	if (dev->rep[REP_PERIOD])
+		mod_timer(&dev->timer, jiffies + msecs_to_jiffies(dev->rep[REP_PERIOD]));
 }
 
 int input_accept_process(struct input_handle *handle, struct file *file)
diff -Nru a/drivers/input/joydev.c b/drivers/input/joydev.c
--- a/drivers/input/joydev.c	2005-03-11 12:51:46 -08:00
+++ b/drivers/input/joydev.c	2005-03-11 12:51:46 -08:00
@@ -47,15 +47,15 @@
 	struct input_handle handle;
 	wait_queue_head_t wait;
 	struct list_head list;
-	struct js_corr corr[ABS_MAX];
+	struct js_corr corr[ABS_MAX + 1];
 	struct JS_DATA_SAVE_TYPE glue;
 	int nabs;
 	int nkey;
-	__u16 keymap[KEY_MAX - BTN_MISC];
-	__u16 keypam[KEY_MAX - BTN_MISC];
-	__u8 absmap[ABS_MAX];
-	__u8 abspam[ABS_MAX];
-	__s16 abs[ABS_MAX];
+	__u16 keymap[KEY_MAX - BTN_MISC + 1];
+	__u16 keypam[KEY_MAX - BTN_MISC + 1];
+	__u8 absmap[ABS_MAX + 1];
+	__u8 abspam[ABS_MAX + 1];
+	__s16 abs[ABS_MAX + 1];
 };
 
 struct joydev_list {
@@ -281,9 +281,8 @@
 {
 	struct joydev_list *list = file->private_data;
 	poll_wait(file, &list->joydev->wait, wait);
-	if (list->head != list->tail || list->startup < list->joydev->nabs + list->joydev->nkey)
-		return POLLIN | POLLRDNORM;
-	return 0;
+	return ((list->head != list->tail || list->startup < list->joydev->nabs + list->joydev->nkey) ? 
+		(POLLIN | POLLRDNORM) : 0) | (list->joydev->exist ? 0 : (POLLHUP | POLLERR));
 }
 
 static int joydev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
@@ -338,7 +337,7 @@
 			return copy_to_user(argp, joydev->corr,
 						sizeof(struct js_corr) * joydev->nabs) ? -EFAULT : 0;
 		case JSIOCSAXMAP:
-			if (copy_from_user(joydev->abspam, argp, sizeof(__u8) * ABS_MAX))
+			if (copy_from_user(joydev->abspam, argp, sizeof(__u8) * (ABS_MAX + 1)))
 				return -EFAULT;
 			for (i = 0; i < joydev->nabs; i++) {
 				if (joydev->abspam[i] > ABS_MAX) return -EINVAL;
@@ -347,9 +346,9 @@
 			return 0;
 		case JSIOCGAXMAP:
 			return copy_to_user(argp, joydev->abspam,
-						sizeof(__u8) * ABS_MAX) ? -EFAULT : 0;
+						sizeof(__u8) * (ABS_MAX + 1)) ? -EFAULT : 0;
 		case JSIOCSBTNMAP:
-			if (copy_from_user(joydev->keypam, argp, sizeof(__u16) * (KEY_MAX - BTN_MISC)))
+			if (copy_from_user(joydev->keypam, argp, sizeof(__u16) * (KEY_MAX - BTN_MISC + 1)))
 				return -EFAULT;
 			for (i = 0; i < joydev->nkey; i++) {
 				if (joydev->keypam[i] > KEY_MAX || joydev->keypam[i] < BTN_MISC) return -EINVAL;
@@ -358,7 +357,7 @@
 			return 0;
 		case JSIOCGBTNMAP:
 			return copy_to_user(argp, joydev->keypam,
-						sizeof(__u16) * (KEY_MAX - BTN_MISC)) ? -EFAULT : 0;
+						sizeof(__u16) * (KEY_MAX - BTN_MISC + 1)) ? -EFAULT : 0;
 		default:
 			if ((cmd & ~(_IOC_SIZEMASK << _IOC_SIZESHIFT)) == JSIOCGNAME(0)) {
 				int len;
@@ -409,21 +408,21 @@
 	joydev->handle.private = joydev;
 	sprintf(joydev->name, "js%d", minor);
 
-	for (i = 0; i < ABS_MAX; i++)
+	for (i = 0; i < ABS_MAX + 1; i++)
 		if (test_bit(i, dev->absbit)) {
 			joydev->absmap[i] = joydev->nabs;
 			joydev->abspam[joydev->nabs] = i;
 			joydev->nabs++;
 		}
 
-	for (i = BTN_JOYSTICK - BTN_MISC; i < KEY_MAX - BTN_MISC; i++)
+	for (i = BTN_JOYSTICK - BTN_MISC; i < KEY_MAX - BTN_MISC + 1; i++)
 		if (test_bit(i + BTN_MISC, dev->keybit)) {
 			joydev->keymap[i] = joydev->nkey;
 			joydev->keypam[joydev->nkey] = i + BTN_MISC;
 			joydev->nkey++;
 		}
 
-	for (i = 0; i < BTN_JOYSTICK - BTN_MISC; i++)
+	for (i = 0; i < BTN_JOYSTICK - BTN_MISC + 1; i++)
 		if (test_bit(i + BTN_MISC, dev->keybit)) {
 			joydev->keymap[i] = joydev->nkey;
 			joydev->keypam[joydev->nkey] = i + BTN_MISC;
@@ -463,14 +462,18 @@
 static void joydev_disconnect(struct input_handle *handle)
 {
 	struct joydev *joydev = handle->private;
+	struct joydev_list *list;
 
 	class_simple_device_remove(MKDEV(INPUT_MAJOR, JOYDEV_MINOR_BASE + joydev->minor));
 	devfs_remove("input/js%d", joydev->minor);
 	joydev->exist = 0;
 
-	if (joydev->open)
+	if (joydev->open) {
 		input_close_device(handle);
-	else
+		wake_up_interruptible(&joydev->wait);
+		list_for_each_entry(list, &joydev->list, node)
+			kill_fasync(&list->fasync, SIGIO, POLL_HUP);
+	} else
 		joydev_free(joydev);
 }
 
diff -Nru a/drivers/input/joystick/Kconfig b/drivers/input/joystick/Kconfig
--- a/drivers/input/joystick/Kconfig	2005-03-11 12:51:40 -08:00
+++ b/drivers/input/joystick/Kconfig	2005-03-11 12:51:40 -08:00
@@ -1,9 +1,8 @@
 #
 # Joystick driver configuration
 #
-config INPUT_JOYSTICK
+menuconfig INPUT_JOYSTICK
 	bool "Joysticks"
-	depends on INPUT
 	help
 	  If you have a joystick, 6dof controller, gamepad, steering wheel,
 	  weapon control system or something like that you can say Y here
@@ -13,9 +12,11 @@
 	  Please read the file <file:Documentation/input/joystick.txt> which
 	  contains more information.
 
+if INPUT_JOYSTICK
+
 config JOYSTICK_ANALOG
 	tristate "Classic PC analog joysticks and gamepads"
-	depends on INPUT && INPUT_JOYSTICK && GAMEPORT
+	select GAMEPORT
 	---help---
 	  Say Y here if you have a joystick that connects to the PC
 	  gameport. In addition to the usual PC analog joystick, this driver
@@ -32,7 +33,7 @@
 
 config JOYSTICK_A3D
 	tristate "Assasin 3D and MadCatz Panther devices"
-	depends on INPUT && INPUT_JOYSTICK && GAMEPORT
+	select GAMEPORT
 	help
 	  Say Y here if you have an FPGaming or MadCatz controller using the
 	  A3D protocol over the PC gameport.
@@ -42,7 +43,7 @@
 
 config JOYSTICK_ADI
 	tristate "Logitech ADI digital joysticks and gamepads"
-	depends on INPUT && INPUT_JOYSTICK && GAMEPORT
+	select GAMEPORT
 	help
 	  Say Y here if you have a Logitech controller using the ADI
 	  protocol over the PC gameport.
@@ -52,7 +53,7 @@
 
 config JOYSTICK_COBRA
 	tristate "Creative Labs Blaster Cobra gamepad"
-	depends on INPUT && INPUT_JOYSTICK && GAMEPORT
+	select GAMEPORT
 	help
 	  Say Y here if you have a Creative Labs Blaster Cobra gamepad.
 
@@ -61,7 +62,7 @@
 
 config JOYSTICK_GF2K
 	tristate "Genius Flight2000 Digital joysticks and gamepads"
-	depends on INPUT && INPUT_JOYSTICK && GAMEPORT
+	select GAMEPORT
 	help
 	  Say Y here if you have a Genius Flight2000 or MaxFighter digitally
 	  communicating joystick or gamepad.
@@ -71,7 +72,7 @@
 
 config JOYSTICK_GRIP
 	tristate "Gravis GrIP joysticks and gamepads"
-	depends on INPUT && INPUT_JOYSTICK && GAMEPORT
+	select GAMEPORT
 	help
 	  Say Y here if you have a Gravis controller using the GrIP protocol
 	  over the PC gameport.
@@ -81,7 +82,7 @@
 
 config JOYSTICK_GRIP_MP
 	tristate "Gravis GrIP MultiPort"
-	depends on INPUT && INPUT_JOYSTICK && GAMEPORT
+	select GAMEPORT
 	help
 	  Say Y here if you have the original Gravis GrIP MultiPort, a hub
 	  that connects to the gameport and you connect gamepads to it.
@@ -91,7 +92,7 @@
 
 config JOYSTICK_GUILLEMOT
 	tristate "Guillemot joysticks and gamepads"
-	depends on INPUT && INPUT_JOYSTICK && GAMEPORT
+	select GAMEPORT
 	help
 	  Say Y here if you have a Guillemot joystick using a digital
 	  protocol over the PC gameport.
@@ -101,7 +102,7 @@
 
 config JOYSTICK_INTERACT
 	tristate "InterAct digital joysticks and gamepads"
-	depends on INPUT && INPUT_JOYSTICK && GAMEPORT
+	select GAMEPORT
 	help
 	  Say Y here if you have an InterAct gameport or joystick
 	  communicating digitally over the gameport.
@@ -111,7 +112,7 @@
 
 config JOYSTICK_SIDEWINDER
 	tristate "Microsoft SideWinder digital joysticks and gamepads"
-	depends on INPUT && INPUT_JOYSTICK && GAMEPORT
+	select GAMEPORT
 	help
 	  Say Y here if you have a Microsoft controller using the Digital
 	  Overdrive protocol over PC gameport.
@@ -121,7 +122,7 @@
 
 config JOYSTICK_TMDC
 	tristate "ThrustMaster DirectConnect joysticks and gamepads"
-	depends on INPUT && INPUT_JOYSTICK && GAMEPORT
+	select GAMEPORT
 	help
 	  Say Y here if you have a ThrustMaster controller using the
 	  DirectConnect (BSP) protocol over the PC gameport.
@@ -133,7 +134,6 @@
 
 config JOYSTICK_WARRIOR
 	tristate "Logitech WingMan Warrior joystick"
-	depends on INPUT && INPUT_JOYSTICK
 	select SERIO
 	help
 	  Say Y here if you have a Logitech WingMan Warrior joystick connected
@@ -144,7 +144,6 @@
 
 config JOYSTICK_MAGELLAN
 	tristate "LogiCad3d Magellan/SpaceMouse 6dof controllers"
-	depends on INPUT && INPUT_JOYSTICK
 	select SERIO
 	help
 	  Say Y here if you have a Magellan or Space Mouse 6DOF controller
@@ -155,7 +154,6 @@
 
 config JOYSTICK_SPACEORB
 	tristate "SpaceTec SpaceOrb/Avenger 6dof controllers"
-	depends on INPUT && INPUT_JOYSTICK
 	select SERIO
 	help
 	  Say Y here if you have a SpaceOrb 360 or SpaceBall Avenger 6DOF
@@ -166,7 +164,6 @@
 
 config JOYSTICK_SPACEBALL
 	tristate "SpaceTec SpaceBall 6dof controllers"
-	depends on INPUT && INPUT_JOYSTICK
 	select SERIO
 	help
 	  Say Y here if you have a SpaceTec SpaceBall 2003/3003/4000 FLX
@@ -178,7 +175,6 @@
 
 config JOYSTICK_STINGER
 	tristate "Gravis Stinger gamepad"
-	depends on INPUT && INPUT_JOYSTICK
 	select SERIO
 	help
 	  Say Y here if you have a Gravis Stinger connected to one of your
@@ -187,9 +183,8 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called stinger.
 
-config JOYSTICK_TWIDDLER
+config JOYSTICK_TWIDJOY
 	tristate "Twiddler as a joystick"
-	depends on INPUT && INPUT_JOYSTICK
 	select SERIO
 	help
 	  Say Y here if you have a Handykey Twiddler connected to your
@@ -200,7 +195,7 @@
 
 config JOYSTICK_DB9
 	tristate "Multisystem, Sega Genesis, Saturn joysticks and gamepads"
-	depends on INPUT && INPUT_JOYSTICK && PARPORT
+	depends on PARPORT
 	---help---
 	  Say Y here if you have a Sega Master System gamepad, Sega Genesis
 	  gamepad, Sega Saturn gamepad, or a Multisystem -- Atari, Amiga,
@@ -213,7 +208,7 @@
 
 config JOYSTICK_GAMECON
 	tristate "Multisystem, NES, SNES, N64, PSX joysticks and gamepads"
-	depends on INPUT && INPUT_JOYSTICK && PARPORT
+	depends on PARPORT
 	---help---
 	  Say Y here if you have a Nintendo Entertainment System gamepad,
 	  Super Nintendo Entertainment System gamepad, Nintendo 64 gamepad,
@@ -227,7 +222,7 @@
 
 config JOYSTICK_TURBOGRAFX
 	tristate "Multisystem joysticks via TurboGraFX device"
-	depends on INPUT && INPUT_JOYSTICK && PARPORT
+	depends on PARPORT
 	help
 	  Say Y here if you have the TurboGraFX interface by Steffen Schwenke,
 	  and want to use it with Multisystem -- Atari, Amiga, Commodore,
@@ -239,7 +234,7 @@
 
 config JOYSTICK_AMIGA
 	tristate "Amiga joysticks"
-	depends on AMIGA && INPUT && INPUT_JOYSTICK
+	depends on AMIGA
 	help
 	  Say Y here if you have an Amiga with a digital joystick connected
 	  to it.
@@ -249,7 +244,7 @@
 
 config JOYSTICK_JOYDUMP
 	tristate "Gameport data dumper"
-	depends on INPUT && INPUT_JOYSTICK && GAMEPORT
+	select GAMEPORT
 	help
 	  Say Y here if you want to dump data from your joystick into the system
 	  log for debugging purposes. Say N if you are making a production
@@ -258,3 +253,4 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called joydump.
 
+endif
diff -Nru a/drivers/input/joystick/a3d.c b/drivers/input/joystick/a3d.c
--- a/drivers/input/joystick/a3d.c	2005-03-11 12:51:40 -08:00
+++ b/drivers/input/joystick/a3d.c	2005-03-11 12:51:40 -08:00
@@ -35,38 +35,35 @@
 #include <linux/gameport.h>
 #include <linux/input.h>
 
+#define DRIVER_DESC	"FP-Gaming Assasin 3D joystick driver"
+
 MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
-MODULE_DESCRIPTION("FP-Gaming Assasin 3D joystick driver");
+MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
 
-#define A3D_MAX_START		400	/* 400 us */
-#define A3D_MAX_STROBE		60	/* 40 us */
-#define A3D_DELAY_READ		3	/* 3 ms */
+#define A3D_MAX_START		600	/* 600 us */
+#define A3D_MAX_STROBE		80	/* 80 us */
 #define A3D_MAX_LENGTH		40	/* 40*3 bits */
-#define A3D_REFRESH_TIME	HZ/50	/* 20 ms */
 
 #define A3D_MODE_A3D		1	/* Assassin 3D */
 #define A3D_MODE_PAN		2	/* Panther */
 #define A3D_MODE_OEM		3	/* Panther OEM version */
 #define A3D_MODE_PXL		4	/* Panther XL */
 
-char *a3d_names[] = { NULL, "FP-Gaming Assassin 3D", "MadCatz Panther", "OEM Panther",
+static char *a3d_names[] = { NULL, "FP-Gaming Assassin 3D", "MadCatz Panther", "OEM Panther",
 			"MadCatz Panther XL", "MadCatz Panther XL w/ rudder" };
 
 struct a3d {
 	struct gameport *gameport;
-	struct gameport adc;
+	struct gameport *adc;
 	struct input_dev dev;
-	struct timer_list timer;
 	int axes[4];
 	int buttons;
 	int mode;
 	int length;
-	int used;
 	int reads;
 	int bads;
 	char phys[32];
-	char adcphys[32];
 };
 
 /*
@@ -109,7 +106,9 @@
 static int a3d_csum(char *data, int count)
 {
 	int i, csum = 0;
-	for (i = 0; i < count - 2; i++) csum += data[i];
+
+	for (i = 0; i < count - 2; i++)
+		csum += data[i];
 	return (csum & 0x3f) != ((data[count - 2] << 3) | data[count - 1]);
 }
 
@@ -139,7 +138,7 @@
 
 			a3d->buttons = ((data[3] << 3) | data[4]) & 0xf;
 
-			return;
+			break;
 
 		case A3D_MODE_PXL:
 
@@ -169,24 +168,26 @@
 
 			input_sync(dev);
 
-			return;
+			break;
 	}
 }
 
 
 /*
- * a3d_timer() reads and analyzes A3D joystick data.
+ * a3d_poll() reads and analyzes A3D joystick data.
  */
 
-static void a3d_timer(unsigned long private)
+static void a3d_poll(struct gameport *gameport)
 {
-	struct a3d *a3d = (void *) private;
+	struct a3d *a3d = gameport_get_drvdata(gameport);
 	unsigned char data[A3D_MAX_LENGTH];
+
 	a3d->reads++;
-	if (a3d_read_packet(a3d->gameport, a3d->length, data) != a3d->length
-		|| data[0] != a3d->mode || a3d_csum(data, a3d->length))
-	 	a3d->bads++; else a3d_read(a3d, data);
-	mod_timer(&a3d->timer, jiffies + A3D_REFRESH_TIME);
+	if (a3d_read_packet(a3d->gameport, a3d->length, data) != a3d->length ||
+	    data[0] != a3d->mode || a3d_csum(data, a3d->length))
+	 	a3d->bads++;
+	else
+		a3d_read(a3d, data);
 }
 
 /*
@@ -195,10 +196,11 @@
  * call this more than 50 times a second, which would use too much CPU.
  */
 
-int a3d_adc_cooked_read(struct gameport *gameport, int *axes, int *buttons)
+static int a3d_adc_cooked_read(struct gameport *gameport, int *axes, int *buttons)
 {
-	struct a3d *a3d = gameport->driver;
+	struct a3d *a3d = gameport->port_data;
 	int i;
+
 	for (i = 0; i < 4; i++)
 		axes[i] = (a3d->axes[i] < 254) ? a3d->axes[i] : -1;
 	*buttons = a3d->buttons;
@@ -210,13 +212,14 @@
  * any but cooked data.
  */
 
-int a3d_adc_open(struct gameport *gameport, int mode)
+static int a3d_adc_open(struct gameport *gameport, int mode)
 {
-	struct a3d *a3d = gameport->driver;
+	struct a3d *a3d = gameport->port_data;
+
 	if (mode != GAMEPORT_MODE_COOKED)
 		return -1;
-	if (!a3d->used++)
-		mod_timer(&a3d->timer, jiffies + A3D_REFRESH_TIME);
+
+	gameport_start_polling(a3d->gameport);
 	return 0;
 }
 
@@ -226,9 +229,9 @@
 
 static void a3d_adc_close(struct gameport *gameport)
 {
-	struct a3d *a3d = gameport->driver;
-	if (!--a3d->used)
-		del_timer(&a3d->timer);
+	struct a3d *a3d = gameport->port_data;
+
+	gameport_stop_polling(a3d->gameport);
 }
 
 /*
@@ -238,8 +241,8 @@
 static int a3d_open(struct input_dev *dev)
 {
 	struct a3d *a3d = dev->private;
-	if (!a3d->used++)
-		mod_timer(&a3d->timer, jiffies + A3D_REFRESH_TIME);
+
+	gameport_start_polling(a3d->gameport);
 	return 0;
 }
 
@@ -250,49 +253,53 @@
 static void a3d_close(struct input_dev *dev)
 {
 	struct a3d *a3d = dev->private;
-	if (!--a3d->used)
-		del_timer(&a3d->timer);
+
+	gameport_stop_polling(a3d->gameport);
 }
 
 /*
  * a3d_connect() probes for A3D joysticks.
  */
 
-static void a3d_connect(struct gameport *gameport, struct gameport_dev *dev)
+static int a3d_connect(struct gameport *gameport, struct gameport_driver *drv)
 {
 	struct a3d *a3d;
+	struct gameport *adc;
 	unsigned char data[A3D_MAX_LENGTH];
 	int i;
+	int err;
 
-	if (!(a3d = kmalloc(sizeof(struct a3d), GFP_KERNEL)))
-		return;
-	memset(a3d, 0, sizeof(struct a3d));
-
-	gameport->private = a3d;
+	if (!(a3d = kcalloc(1, sizeof(struct a3d), GFP_KERNEL)))
+		return -ENOMEM;
 
 	a3d->gameport = gameport;
-	init_timer(&a3d->timer);
-	a3d->timer.data = (long) a3d;
-	a3d->timer.function = a3d_timer;
 
-	if (gameport_open(gameport, dev, GAMEPORT_MODE_RAW))
+	gameport_set_drvdata(gameport, a3d);
+
+	err = gameport_open(gameport, drv, GAMEPORT_MODE_RAW);
+	if (err)
 		goto fail1;
 
 	i = a3d_read_packet(gameport, A3D_MAX_LENGTH, data);
 
-	if (!i || a3d_csum(data, i))
+	if (!i || a3d_csum(data, i)) {
+		err = -ENODEV;
 		goto fail2;
+	}
 
 	a3d->mode = data[0];
 
 	if (!a3d->mode || a3d->mode > 5) {
 		printk(KERN_WARNING "a3d.c: Unknown A3D device detected "
 			"(%s, id=%d), contact <vojtech@ucw.cz>\n", gameport->phys, a3d->mode);
+		err = -ENODEV;
 		goto fail2;
 	}
 
+	gameport_set_poll_handler(gameport, a3d_poll);
+	gameport_set_poll_interval(gameport, 20);
+
 	sprintf(a3d->phys, "%s/input0", gameport->phys);
-	sprintf(a3d->adcphys, "%s/gameport0", gameport->phys);
 
 	if (a3d->mode == A3D_MODE_PXL) {
 
@@ -315,16 +322,11 @@
 		a3d_read(a3d, data);
 
 		for (i = 0; i < 4; i++) {
-			if (i < 2) {
-				a3d->dev.absmin[axes[i]] = 48;
-				a3d->dev.absmax[axes[i]] = a3d->dev.abs[axes[i]] * 2 - 48;
-				a3d->dev.absflat[axes[i]] = 8;
-			} else {
-				a3d->dev.absmin[axes[i]] = 2;
-				a3d->dev.absmax[axes[i]] = 253;
-			}
-			a3d->dev.absmin[ABS_HAT0X + i] = -1;
-			a3d->dev.absmax[ABS_HAT0X + i] = 1;
+			if (i < 2)
+				input_set_abs_params(&a3d->dev, axes[i], 48, a3d->dev.abs[axes[i]] * 2 - 48, 0, 8);
+			else
+				input_set_abs_params(&a3d->dev, axes[i], 2, 253, 0, 0);
+			input_set_abs_params(&a3d->dev, ABS_HAT0X + i, -1, 1, 0, 0);
 		}
 
 	} else {
@@ -336,23 +338,23 @@
 		a3d->dev.relbit[0] |= BIT(REL_X) | BIT(REL_Y);
 		a3d->dev.keybit[LONG(BTN_MOUSE)] |= BIT(BTN_RIGHT) | BIT(BTN_LEFT) | BIT(BTN_MIDDLE);
 
-		a3d->adc.driver = a3d;
-		a3d->adc.open = a3d_adc_open;
-		a3d->adc.close = a3d_adc_close;
-		a3d->adc.cooked_read = a3d_adc_cooked_read;
-		a3d->adc.fuzz = 1;
-
-		a3d->adc.name = a3d_names[a3d->mode];
-		a3d->adc.phys = a3d->adcphys;
-		a3d->adc.id.bustype = BUS_GAMEPORT;
-		a3d->adc.id.vendor = GAMEPORT_ID_VENDOR_MADCATZ;
-		a3d->adc.id.product = a3d->mode;
-		a3d->adc.id.version = 0x0100;
-
 		a3d_read(a3d, data);
 
-		gameport_register_port(&a3d->adc);
-		printk(KERN_INFO "gameport: %s on %s\n", a3d_names[a3d->mode], gameport->phys);
+		if (!(a3d->adc = adc = gameport_allocate_port()))
+			printk(KERN_ERR "a3d: Not enough memory for ADC port\n");
+		else {
+			adc->port_data = a3d;
+			adc->open = a3d_adc_open;
+			adc->close = a3d_adc_close;
+			adc->cooked_read = a3d_adc_cooked_read;
+			adc->fuzz = 1;
+
+			gameport_set_name(adc, a3d_names[a3d->mode]);
+			gameport_set_phys(adc, "%s/gameport0", gameport->phys);
+			adc->dev.parent = &gameport->dev;
+
+			gameport_register_port(adc);
+		}
 	}
 
 	a3d->dev.private = a3d;
@@ -369,36 +371,46 @@
 	input_register_device(&a3d->dev);
 	printk(KERN_INFO "input: %s on %s\n", a3d_names[a3d->mode], a3d->phys);
 
-	return;
+	return 0;
+
 fail2:	gameport_close(gameport);
-fail1:  kfree(a3d);
+fail1:  gameport_set_drvdata(gameport, NULL);
+	kfree(a3d);
+	return err;
 }
 
 static void a3d_disconnect(struct gameport *gameport)
 {
+	struct a3d *a3d = gameport_get_drvdata(gameport);
 
-	struct a3d *a3d = gameport->private;
 	input_unregister_device(&a3d->dev);
-	if (a3d->mode < A3D_MODE_PXL)
-		gameport_unregister_port(&a3d->adc);
+	if (a3d->adc) {
+		gameport_unregister_port(a3d->adc);
+		a3d->adc = NULL;
+	}
 	gameport_close(gameport);
+	gameport_set_drvdata(gameport, NULL);
 	kfree(a3d);
 }
 
-static struct gameport_dev a3d_dev = {
-	.connect =	a3d_connect,
-	.disconnect =	a3d_disconnect,
+static struct gameport_driver a3d_drv = {
+	.driver		= {
+		.name	= "adc",
+	},
+	.description	= DRIVER_DESC,
+	.connect	= a3d_connect,
+	.disconnect	= a3d_disconnect,
 };
 
-int __init a3d_init(void)
+static int __init a3d_init(void)
 {
-	gameport_register_device(&a3d_dev);
+	gameport_register_driver(&a3d_drv);
 	return 0;
 }
 
-void __exit a3d_exit(void)
+static void __exit a3d_exit(void)
 {
-	gameport_unregister_device(&a3d_dev);
+	gameport_unregister_driver(&a3d_drv);
 }
 
 module_init(a3d_init);
diff -Nru a/drivers/input/joystick/adi.c b/drivers/input/joystick/adi.c
--- a/drivers/input/joystick/adi.c	2005-03-11 12:51:42 -08:00
+++ b/drivers/input/joystick/adi.c	2005-03-11 12:51:42 -08:00
@@ -1,7 +1,5 @@
 /*
- * $Id: adi.c,v 1.23 2002/01/22 20:26:17 vojtech Exp $
- *
- *  Copyright (c) 1998-2001 Vojtech Pavlik
+ *  Copyright (c) 1998-2005 Vojtech Pavlik
  */
 
 /*
@@ -37,8 +35,10 @@
 #include <linux/gameport.h>
 #include <linux/init.h>
 
+#define DRIVER_DESC	"Logitech ADI joystick family driver"
+
 MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
-MODULE_DESCRIPTION("Logitech ADI joystick family driver");
+MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
 
 /*
@@ -47,7 +47,6 @@
 
 #define ADI_MAX_START		200	/* Trigger to packet timeout [200us] */
 #define ADI_MAX_STROBE		40	/* Single bit timeout [40us] */
-#define ADI_REFRESH_TIME	HZ/50	/* How often to poll the joystick [20 ms] */
 #define ADI_INIT_DELAY		10	/* Delay after init packet [10ms] */
 #define ADI_DATA_DELAY		4	/* Delay after data packet [4ms] */
 
@@ -57,7 +56,7 @@
 #define ADI_MIN_ID_LENGTH	66
 #define ADI_MAX_NAME_LENGTH	48
 #define ADI_MAX_CNAME_LENGTH	16
-#define ADI_MAX_PHYS_LENGTH	32
+#define ADI_MAX_PHYS_LENGTH	64
 
 #define ADI_FLAG_HAT		0x04
 #define ADI_FLAG_10BIT		0x08
@@ -127,11 +126,9 @@
 
 struct adi_port {
 	struct gameport *gameport;
-	struct timer_list timer;
 	struct adi adi[2];
 	int bad;
 	int reads;
-	int used;
 };
 
 /*
@@ -275,15 +272,15 @@
 }
 
 /*
- * adi_timer() repeatedly polls the Logitech joysticks.
+ * adi_poll() repeatedly polls the Logitech joysticks.
  */
 
-static void adi_timer(unsigned long data)
+static void adi_poll(struct gameport *gameport)
 {
-	struct adi_port *port = (void *) data;
+	struct adi_port *port = gameport_get_drvdata(gameport);
+
 	port->bad -= adi_read(port);
 	port->reads++;
-	mod_timer(&port->timer, jiffies + ADI_REFRESH_TIME);
 }
 
 /*
@@ -293,8 +290,8 @@
 static int adi_open(struct input_dev *dev)
 {
 	struct adi_port *port = dev->private;
-	if (!port->used++)
-		mod_timer(&port->timer, jiffies + ADI_REFRESH_TIME);
+
+	gameport_start_polling(port->gameport);
 	return 0;
 }
 
@@ -305,8 +302,8 @@
 static void adi_close(struct input_dev *dev)
 {
 	struct adi_port *port = dev->private;
-	if (!--port->used)
-		del_timer(&port->timer);
+
+	gameport_stop_polling(port->gameport);
 }
 
 /*
@@ -316,13 +313,16 @@
 
 static void adi_init_digital(struct gameport *gameport)
 {
-	int seq[] = { 3, -2, -3, 10, -6, -11, -7, -9, 11, 0 };
+	int seq[] = { 4, -2, -3, 10, -6, -11, -7, -9, 11, 0 };
 	int i;
 
 	for (i = 0; seq[i]; i++) {
 		gameport_trigger(gameport);
 		if (seq[i] > 0) msleep(seq[i]);
-		if (seq[i] < 0) mdelay(-seq[i]);
+		if (seq[i] < 0) {
+			mdelay(-seq[i]);
+			udelay(-seq[i]*14);	/* It looks like mdelay() is off by approx 1.4% */
+		}
 	}
 }
 
@@ -408,9 +408,9 @@
 
 	t = adi->id < ADI_ID_MAX ? adi->id : ADI_ID_MAX;
 
-	sprintf(buf, adi_names[t], adi->id);
-	sprintf(adi->name, "Logitech %s", buf);
-	sprintf(adi->phys, "%s/input%d", port->gameport->phys, half);
+	snprintf(buf, ADI_MAX_PHYS_LENGTH, adi_names[t], adi->id);
+	snprintf(adi->name, ADI_MAX_NAME_LENGTH, "Logitech %s", buf);
+	snprintf(adi->phys, ADI_MAX_PHYS_LENGTH, "%s/input%d", port->gameport->phys, half);
 
 	adi->abs = adi_abs[t];
 	adi->key = adi_key[t];
@@ -439,35 +439,23 @@
 {
 	int i, t, x;
 
-	if (!adi->length) return;
+	if (!adi->length)
+		return;
 
 	for (i = 0; i < adi->axes10 + adi->axes8 + (adi->hats + (adi->pad != -1)) * 2; i++) {
 
 		t = adi->abs[i];
 		x = adi->dev.abs[t];
 
-		if (t == ABS_THROTTLE || t == ABS_RUDDER || adi->id == ADI_ID_WGPE) {
-			if (i < adi->axes10) x = 512; else x = 128;
-		}
-
-		if (i < adi->axes10) {
-			adi->dev.absmax[t] = x * 2 - 64;
-			adi->dev.absmin[t] = 64;
-			adi->dev.absfuzz[t] = 2;
-			adi->dev.absflat[t] = 16;
-			continue;
-		}
+		if (t == ABS_THROTTLE || t == ABS_RUDDER || adi->id == ADI_ID_WGPE)
+			x = i < adi->axes10 ? 512 : 128;
 
-		if (i < adi->axes10 + adi->axes8) {
-			adi->dev.absmax[t] = x * 2 - 48;
-			adi->dev.absmin[t] = 48;
-			adi->dev.absfuzz[t] = 1;
-			adi->dev.absflat[t] = 16;
-			continue;
-		}
-
-		adi->dev.absmax[t] = 1;
-		adi->dev.absmin[t] = -1;
+		if (i < adi->axes10)
+			input_set_abs_params(&adi->dev, t, 64, x * 2 - 64, 2, 16);
+		else if (i < adi->axes10 + adi->axes8)
+			input_set_abs_params(&adi->dev, t, 48, x * 2 - 48, 1, 16);
+		else
+			input_set_abs_params(&adi->dev, t, -1, 1, 0, 0);
 	}
 }
 
@@ -475,25 +463,23 @@
  * adi_connect() probes for Logitech ADI joysticks.
  */
 
-static void adi_connect(struct gameport *gameport, struct gameport_dev *dev)
+static int adi_connect(struct gameport *gameport, struct gameport_driver *drv)
 {
 	struct adi_port *port;
 	int i;
+	int err;
 
-	if (!(port = kmalloc(sizeof(struct adi_port), GFP_KERNEL)))
-		return;
-	memset(port, 0, sizeof(struct adi_port));
-
-	gameport->private = port;
+	if (!(port = kcalloc(1, sizeof(struct adi_port), GFP_KERNEL)))
+		return -ENOMEM;
 
 	port->gameport = gameport;
-	init_timer(&port->timer);
-	port->timer.data = (long) port;
-	port->timer.function = adi_timer;
 
-	if (gameport_open(gameport, dev, GAMEPORT_MODE_RAW)) {
+	gameport_set_drvdata(gameport, port);
+
+	err = gameport_open(gameport, drv, GAMEPORT_MODE_RAW);
+	if (err) {
 		kfree(port);
-		return;
+		return err;
 	}
 
 	adi_init_digital(gameport);
@@ -510,9 +496,12 @@
 	if (!port->adi[0].length && !port->adi[1].length) {
 		gameport_close(gameport);
 		kfree(port);
-		return;
+		return -ENODEV;
 	}
 
+	gameport_set_poll_handler(gameport, adi_poll);
+	gameport_set_poll_interval(gameport, 20);
+
 	msleep(ADI_INIT_DELAY);
 	if (adi_read(port)) {
 		msleep(ADI_DATA_DELAY);
@@ -526,17 +515,20 @@
 			printk(KERN_INFO "input: %s [%s] on %s\n",
 				port->adi[i].name, port->adi[i].cname, gameport->phys);
 		}
+
+	return 0;
 }
 
 static void adi_disconnect(struct gameport *gameport)
 {
 	int i;
+	struct adi_port *port = gameport_get_drvdata(gameport);
 
-	struct adi_port *port = gameport->private;
 	for (i = 0; i < 2; i++)
 		if (port->adi[i].length > 0)
 			input_unregister_device(&port->adi[i].dev);
 	gameport_close(gameport);
+	gameport_set_drvdata(gameport, NULL);
 	kfree(port);
 }
 
@@ -544,20 +536,24 @@
  * The gameport device structure.
  */
 
-static struct gameport_dev adi_dev = {
-	.connect =	adi_connect,
-	.disconnect =	adi_disconnect,
+static struct gameport_driver adi_drv = {
+	.driver		= {
+		.name	= "adi",
+	},
+	.description	= DRIVER_DESC,
+	.connect	= adi_connect,
+	.disconnect	= adi_disconnect,
 };
 
-int __init adi_init(void)
+static int __init adi_init(void)
 {
-	gameport_register_device(&adi_dev);
+	gameport_register_driver(&adi_drv);
 	return 0;
 }
 
-void __exit adi_exit(void)
+static void __exit adi_exit(void)
 {
-	gameport_unregister_device(&adi_dev);
+	gameport_unregister_driver(&adi_drv);
 }
 
 module_init(adi_init);
diff -Nru a/drivers/input/joystick/analog.c b/drivers/input/joystick/analog.c
--- a/drivers/input/joystick/analog.c	2005-03-11 12:51:51 -08:00
+++ b/drivers/input/joystick/analog.c	2005-03-11 12:51:51 -08:00
@@ -40,8 +40,10 @@
 #include <linux/gameport.h>
 #include <asm/timex.h>
 
+#define DRIVER_DESC	"Analog joystick and gamepad driver"
+
 MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
-MODULE_DESCRIPTION("Analog joystick and gamepad driver");
+MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
 
 /*
@@ -88,7 +90,6 @@
 
 #define ANALOG_MAX_TIME		3	/* 3 ms */
 #define ANALOG_LOOP_TIME	2000	/* 2 * loop */
-#define ANALOG_REFRESH_TIME	HZ/100	/* 10 ms */
 #define ANALOG_SAITEK_DELAY	200	/* 200 us */
 #define ANALOG_SAITEK_TIME	2000	/* 2000 us */
 #define ANALOG_AXIS_TIME	2	/* 2 * refresh */
@@ -119,7 +120,6 @@
 
 struct analog_port {
 	struct gameport *gameport;
-	struct timer_list timer;
 	struct analog analog[2];
 	unsigned char mask;
 	char saitek;
@@ -132,7 +132,6 @@
 	int axes[4];
 	int buttons;
 	int initial[4];
-	int used;
 	int axtime;
 };
 
@@ -305,12 +304,12 @@
 }
 
 /*
- * analog_timer() repeatedly polls the Analog joysticks.
+ * analog_poll() repeatedly polls the Analog joysticks.
  */
 
-static void analog_timer(unsigned long data)
+static void analog_poll(struct gameport *gameport)
 {
-	struct analog_port *port = (void *) data;
+	struct analog_port *port = gameport_get_drvdata(gameport);
 	int i;
 
 	char saitek = !!(port->analog[0].mask & ANALOG_SAITEK);
@@ -336,8 +335,6 @@
 	for (i = 0; i < 2; i++)
 		if (port->analog[i].mask)
 			analog_decode(port->analog + i, port->axes, port->initial, port->buttons);
-
-	mod_timer(&port->timer, jiffies + ANALOG_REFRESH_TIME);
 }
 
 /*
@@ -347,8 +344,8 @@
 static int analog_open(struct input_dev *dev)
 {
 	struct analog_port *port = dev->private;
-	if (!port->used++)
-		mod_timer(&port->timer, jiffies + ANALOG_REFRESH_TIME);
+
+	gameport_start_polling(port->gameport);
 	return 0;
 }
 
@@ -359,8 +356,8 @@
 static void analog_close(struct input_dev *dev)
 {
 	struct analog_port *port = dev->private;
-	if (!--port->used)
-		del_timer(&port->timer);
+
+	gameport_stop_polling(port->gameport);
 }
 
 /*
@@ -379,7 +376,7 @@
 #ifdef FAKE_TIME
 	analog_faketime += 830;
 #endif
-	udelay(1000);
+	mdelay(1);
 	GET_TIME(t2);
 	GET_TIME(t3);
 	local_irq_restore(flags);
@@ -587,17 +584,15 @@
 	return -!(analog[0].mask || analog[1].mask);
 }
 
-static int analog_init_port(struct gameport *gameport, struct gameport_dev *dev, struct analog_port *port)
+static int analog_init_port(struct gameport *gameport, struct gameport_driver *drv, struct analog_port *port)
 {
 	int i, t, u, v;
 
-	gameport->private = port;
 	port->gameport = gameport;
-	init_timer(&port->timer);
-	port->timer.data = (long) port;
-	port->timer.function = analog_timer;
 
-	if (!gameport_open(gameport, dev, GAMEPORT_MODE_RAW)) {
+	gameport_set_drvdata(gameport, port);
+
+	if (!gameport_open(gameport, drv, GAMEPORT_MODE_RAW)) {
 
 		analog_calibrate_timer(port);
 
@@ -608,7 +603,8 @@
 		port->fuzz = (port->speed * ANALOG_FUZZ_MAGIC) / port->loop / 1000 + ANALOG_FUZZ_BITS;
 
 		for (i = 0; i < ANALOG_INIT_RETRIES; i++) {
-			if (!analog_cooked_read(port)) break;
+			if (!analog_cooked_read(port))
+				break;
 			msleep(ANALOG_MAX_TIME);
 		}
 
@@ -617,11 +613,13 @@
 		msleep(ANALOG_MAX_TIME);
 		t = gameport_time(gameport, ANALOG_MAX_TIME * 1000);
 		gameport_trigger(gameport);
-		while ((gameport_read(port->gameport) & port->mask) && (u < t)) u++;
+		while ((gameport_read(port->gameport) & port->mask) && (u < t))
+			u++;
 		udelay(ANALOG_SAITEK_DELAY);
 		t = gameport_time(gameport, ANALOG_SAITEK_TIME);
 		gameport_trigger(gameport);
-		while ((gameport_read(port->gameport) & port->mask) && (v < t)) v++;
+		while ((gameport_read(port->gameport) & port->mask) && (v < t))
+			v++;
 
 		if (v < (u >> 1)) { /* FIXME - more than one port */
 			analog_options[0] |= /* FIXME - more than one port */
@@ -632,59 +630,66 @@
 		gameport_close(gameport);
 	}
 
-	if (!gameport_open(gameport, dev, GAMEPORT_MODE_COOKED)) {
+	if (!gameport_open(gameport, drv, GAMEPORT_MODE_COOKED)) {
 
 		for (i = 0; i < ANALOG_INIT_RETRIES; i++)
 			if (!gameport_cooked_read(gameport, port->axes, &port->buttons))
 				break;
 		for (i = 0; i < 4; i++)
-			if (port->axes[i] != -1) port->mask |= 1 << i;
+			if (port->axes[i] != -1)
+				port->mask |= 1 << i;
 
 		port->fuzz = gameport->fuzz;
 		port->cooked = 1;
 		return 0;
 	}
 
-	if (!gameport_open(gameport, dev, GAMEPORT_MODE_RAW))
-		return 0;
-
-	return -1;
+	return gameport_open(gameport, drv, GAMEPORT_MODE_RAW);
 }
 
-static void analog_connect(struct gameport *gameport, struct gameport_dev *dev)
+static int analog_connect(struct gameport *gameport, struct gameport_driver *drv)
 {
 	struct analog_port *port;
 	int i;
+	int err;
 
-	if (!(port = kmalloc(sizeof(struct analog_port), GFP_KERNEL)))
-		return;
-	memset(port, 0, sizeof(struct analog_port));
+	if (!(port = kcalloc(1, sizeof(struct analog_port), GFP_KERNEL)))
+		return - ENOMEM;
 
-	if (analog_init_port(gameport, dev, port)) {
+	err = analog_init_port(gameport, drv, port);
+	if (err) {
 		kfree(port);
-		return;
+		return err;
 	}
 
-	if (analog_init_masks(port)) {
+	err = analog_init_masks(port);
+	if (err) {
 		gameport_close(gameport);
+		gameport_set_drvdata(gameport, NULL);
 		kfree(port);
-		return;
+		return err;
 	}
 
+	gameport_set_poll_handler(gameport, analog_poll);
+	gameport_set_poll_interval(gameport, 10);
+
 	for (i = 0; i < 2; i++)
 		if (port->analog[i].mask)
 			analog_init_device(port, port->analog + i, i);
+
+	return 0;
 }
 
 static void analog_disconnect(struct gameport *gameport)
 {
 	int i;
+	struct analog_port *port = gameport_get_drvdata(gameport);
 
-	struct analog_port *port = gameport->private;
 	for (i = 0; i < 2; i++)
 		if (port->analog[i].mask)
 			input_unregister_device(&port->analog[i].dev);
 	gameport_close(gameport);
+	gameport_set_drvdata(gameport, NULL);
 	printk(KERN_INFO "analog.c: %d out of %d reads (%d%%) on %s failed\n",
 		port->bads, port->reads, port->reads ? (port->bads * 100 / port->reads) : 0,
 		port->gameport->phys);
@@ -696,7 +701,7 @@
 	int value;
 };
 
-struct analog_types analog_types[] = {
+static struct analog_types analog_types[] = {
 	{ "none",	0x00000000 },
 	{ "auto",	0x000000ff },
 	{ "2btn",	0x0000003f },
@@ -741,21 +746,26 @@
  * The gameport device structure.
  */
 
-static struct gameport_dev analog_dev = {
-	.connect =	analog_connect,
-	.disconnect =	analog_disconnect,
+static struct gameport_driver analog_drv = {
+	.driver		= {
+		.name	= "analog",
+	},
+	.description	= DRIVER_DESC,
+	.connect	= analog_connect,
+	.disconnect	= analog_disconnect,
 };
 
-int __init analog_init(void)
+static int __init analog_init(void)
 {
 	analog_parse_options();
-	gameport_register_device(&analog_dev);
+	gameport_register_driver(&analog_drv);
+
 	return 0;
 }
 
-void __exit analog_exit(void)
+static void __exit analog_exit(void)
 {
-	gameport_unregister_device(&analog_dev);
+	gameport_unregister_driver(&analog_drv);
 }
 
 module_init(analog_init);
diff -Nru a/drivers/input/joystick/cobra.c b/drivers/input/joystick/cobra.c
--- a/drivers/input/joystick/cobra.c	2005-03-11 12:51:46 -08:00
+++ b/drivers/input/joystick/cobra.c	2005-03-11 12:51:46 -08:00
@@ -35,12 +35,13 @@
 #include <linux/gameport.h>
 #include <linux/input.h>
 
+#define DRIVER_DESC	"Creative Labs Blaster GamePad Cobra driver"
+
 MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
-MODULE_DESCRIPTION("Creative Labs Blaster GamePad Cobra driver");
+MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
 
 #define COBRA_MAX_STROBE	45	/* 45 us max wait for first strobe */
-#define COBRA_REFRESH_TIME	HZ/50	/* 20 ms between reads */
 #define COBRA_LENGTH		36
 
 static char* cobra_name = "Creative Labs Blaster GamePad Cobra";
@@ -49,9 +50,7 @@
 
 struct cobra {
 	struct gameport *gameport;
-	struct timer_list timer;
 	struct input_dev dev[2];
-	int used;
 	int reads;
 	int bads;
 	unsigned char exists;
@@ -112,18 +111,19 @@
 	return ret;
 }
 
-static void cobra_timer(unsigned long private)
+static void cobra_poll(struct gameport *gameport)
 {
-	struct cobra *cobra = (void *) private;
+	struct cobra *cobra = gameport_get_drvdata(gameport);
 	struct input_dev *dev;
 	unsigned int data[2];
 	int i, j, r;
 
 	cobra->reads++;
 
-	if ((r = cobra_read_packet(cobra->gameport, data)) != cobra->exists)
+	if ((r = cobra_read_packet(gameport, data)) != cobra->exists) {
 		cobra->bads++;
-	else
+		return;
+	}
 
 	for (i = 0; i < 2; i++)
 		if (cobra->exists & r & (1 << i)) {
@@ -139,43 +139,39 @@
 			input_sync(dev);
 
 		}
-
-	mod_timer(&cobra->timer, jiffies + COBRA_REFRESH_TIME);
 }
 
 static int cobra_open(struct input_dev *dev)
 {
 	struct cobra *cobra = dev->private;
-	if (!cobra->used++)
-		mod_timer(&cobra->timer, jiffies + COBRA_REFRESH_TIME);
+
+	gameport_start_polling(cobra->gameport);
 	return 0;
 }
 
 static void cobra_close(struct input_dev *dev)
 {
 	struct cobra *cobra = dev->private;
-	if (!--cobra->used)
-		del_timer(&cobra->timer);
+
+	gameport_stop_polling(cobra->gameport);
 }
 
-static void cobra_connect(struct gameport *gameport, struct gameport_dev *dev)
+static int cobra_connect(struct gameport *gameport, struct gameport_driver *drv)
 {
 	struct cobra *cobra;
 	unsigned int data[2];
 	int i, j;
+	int err;
 
-	if (!(cobra = kmalloc(sizeof(struct cobra), GFP_KERNEL)))
-		return;
-	memset(cobra, 0, sizeof(struct cobra));
-
-	gameport->private = cobra;
+	if (!(cobra = kcalloc(1, sizeof(struct cobra), GFP_KERNEL)))
+		return -ENOMEM;
 
 	cobra->gameport = gameport;
-	init_timer(&cobra->timer);
-	cobra->timer.data = (long) cobra;
-	cobra->timer.function = cobra_timer;
 
-	if (gameport_open(gameport, dev, GAMEPORT_MODE_RAW))
+	gameport_set_drvdata(gameport, cobra);
+
+	err = gameport_open(gameport, drv, GAMEPORT_MODE_RAW);
+	if (err)
 		goto fail1;
 
 	cobra->exists = cobra_read_packet(gameport, data);
@@ -187,8 +183,13 @@
 			cobra->exists &= ~(1 << i);
 		}
 
-	if (!cobra->exists)
+	if (!cobra->exists) {
+		err = -ENODEV;
 		goto fail2;
+	}
+
+	gameport_set_poll_handler(gameport, cobra_poll);
+	gameport_set_poll_interval(gameport, 20);
 
 	for (i = 0; i < 2; i++)
 		if ((cobra->exists >> i) & 1) {
@@ -207,49 +208,56 @@
 			cobra->dev[i].id.version = 0x0100;
 
 			cobra->dev[i].evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
-			cobra->dev[i].absbit[0] = BIT(ABS_X) | BIT(ABS_Y);
+
+			input_set_abs_params(&cobra->dev[i], ABS_X, -1, 1, 0, 0);
+			input_set_abs_params(&cobra->dev[i], ABS_Y, -1, 1, 0, 0);
 
 			for (j = 0; cobra_btn[j]; j++)
 				set_bit(cobra_btn[j], cobra->dev[i].keybit);
 
-			cobra->dev[i].absmin[ABS_X] = -1; cobra->dev[i].absmax[ABS_X] = 1;
-			cobra->dev[i].absmin[ABS_Y] = -1; cobra->dev[i].absmax[ABS_Y] = 1;
-
-			input_register_device(cobra->dev + i);
+			input_register_device(&cobra->dev[i]);
 			printk(KERN_INFO "input: %s on %s\n", cobra_name, gameport->phys);
 		}
 
-	return;
+	return 0;
+
 fail2:	gameport_close(gameport);
-fail1:	kfree(cobra);
+fail1:	gameport_set_drvdata(gameport, NULL);
+	kfree(cobra);
+	return err;
 }
 
 static void cobra_disconnect(struct gameport *gameport)
 {
+	struct cobra *cobra = gameport_get_drvdata(gameport);
 	int i;
 
-	struct cobra *cobra = gameport->private;
 	for (i = 0; i < 2; i++)
 		if ((cobra->exists >> i) & 1)
 			input_unregister_device(cobra->dev + i);
 	gameport_close(gameport);
+	gameport_set_drvdata(gameport, NULL);
 	kfree(cobra);
 }
 
-static struct gameport_dev cobra_dev = {
-	.connect =	cobra_connect,
-	.disconnect =	cobra_disconnect,
+static struct gameport_driver cobra_drv = {
+	.driver		= {
+		.name	= "cobra",
+	},
+	.description	= DRIVER_DESC,
+	.connect	= cobra_connect,
+	.disconnect	= cobra_disconnect,
 };
 
-int __init cobra_init(void)
+static int __init cobra_init(void)
 {
-	gameport_register_device(&cobra_dev);
+	gameport_register_driver(&cobra_drv);
 	return 0;
 }
 
-void __exit cobra_exit(void)
+static void __exit cobra_exit(void)
 {
-	gameport_unregister_device(&cobra_dev);
+	gameport_unregister_driver(&cobra_drv);
 }
 
 module_init(cobra_init);
diff -Nru a/drivers/input/joystick/db9.c b/drivers/input/joystick/db9.c
--- a/drivers/input/joystick/db9.c	2005-03-11 12:51:42 -08:00
+++ b/drivers/input/joystick/db9.c	2005-03-11 12:51:42 -08:00
@@ -619,7 +619,7 @@
 	return db9;
 }
 
-int __init db9_init(void)
+static int __init db9_init(void)
 {
 	db9_base[0] = db9_probe(db9, db9_nargs);
 	db9_base[1] = db9_probe(db9_2, db9_nargs_2);
@@ -631,7 +631,7 @@
 	return -ENODEV;
 }
 
-void __exit db9_exit(void)
+static void __exit db9_exit(void)
 {
 	int i, j;
 
diff -Nru a/drivers/input/joystick/gamecon.c b/drivers/input/joystick/gamecon.c
--- a/drivers/input/joystick/gamecon.c	2005-03-11 12:51:52 -08:00
+++ b/drivers/input/joystick/gamecon.c	2005-03-11 12:51:52 -08:00
@@ -227,7 +227,8 @@
  */
 
 #define GC_PSX_DELAY	25		/* 25 usec */
-#define GC_PSX_LENGTH	8		/* talk to the controller in bytes */
+#define GC_PSX_LENGTH	8		/* talk to the controller in bits */
+#define GC_PSX_BYTES	6		/* the maximum number of bytes to read off the controller */
 
 #define GC_PSX_MOUSE	1		/* Mouse */
 #define GC_PSX_NEGCON	2		/* NegCon */
@@ -241,7 +242,7 @@
 #define GC_PSX_SELECT	0x02		/* Pin 3 */
 
 #define GC_PSX_ID(x)	((x) >> 4)	/* High nibble is device type */
-#define GC_PSX_LEN(x)	((x) & 0xf)	/* Low nibble is length in words */
+#define GC_PSX_LEN(x)	(((x) & 0xf) << 1)	/* Low nibble is length in bytes/2 */
 
 static int gc_psx_delay = GC_PSX_DELAY;
 module_param_named(psx_delay, gc_psx_delay, uint, 0);
@@ -259,13 +260,13 @@
  * the psx pad.
  */
 
-static void gc_psx_command(struct gc *gc, int b, unsigned char data[GC_PSX_LENGTH])
+static void gc_psx_command(struct gc *gc, int b, unsigned char data[5])
 {
 	int i, j, cmd, read;
 	for (i = 0; i < 5; i++)
 		data[i] = 0;
 
-	for (i = 0; i < 8; i++, b >>= 1) {
+	for (i = 0; i < GC_PSX_LENGTH; i++, b >>= 1) {
 		cmd = (b & 1) ? GC_PSX_COMMAND : 0;
 		parport_write_data(gc->pd->port, cmd | GC_PSX_POWER);
 		udelay(gc_psx_delay);
@@ -282,7 +283,7 @@
  * device identifier code.
  */
 
-static void gc_psx_read_packet(struct gc *gc, unsigned char data[5][GC_PSX_LENGTH], unsigned char id[5])
+static void gc_psx_read_packet(struct gc *gc, unsigned char data[5][GC_PSX_BYTES], unsigned char id[5])
 {
 	int i, j, max_len = 0;
 	unsigned long flags;
@@ -300,10 +301,12 @@
 	gc_psx_command(gc, 0, data2);							/* Dump status */
 
 	for (i =0; i < 5; i++)								/* Find the longest pad */
-		if((gc_status_bit[i] & (gc->pads[GC_PSX] | gc->pads[GC_DDR])) && (GC_PSX_LEN(id[i]) > max_len))
+		if((gc_status_bit[i] & (gc->pads[GC_PSX] | gc->pads[GC_DDR]))
+			&& (GC_PSX_LEN(id[i]) > max_len)
+			&& (GC_PSX_LEN(id[i]) <= GC_PSX_BYTES))
 			max_len = GC_PSX_LEN(id[i]);
 
-	for (i = 0; i < max_len * 2; i++) {						/* Read in all the data */
+	for (i = 0; i < max_len; i++) {						/* Read in all the data */
 		gc_psx_command(gc, 0, data2);
 		for (j = 0; j < 5; j++)
 			data[j][i] = data2[j];
@@ -328,7 +331,7 @@
 	struct gc *gc = (void *) private;
 	struct input_dev *dev = gc->dev;
 	unsigned char data[GC_MAX_LENGTH];
-	unsigned char data_psx[5][GC_PSX_LENGTH];
+	unsigned char data_psx[5][GC_PSX_BYTES];
 	int i, j, s;
 
 /*
@@ -665,7 +668,7 @@
 	return gc;
 }
 
-int __init gc_init(void)
+static int __init gc_init(void)
 {
 	gc_base[0] = gc_probe(gc, gc_nargs);
 	gc_base[1] = gc_probe(gc_2, gc_nargs_2);
@@ -677,7 +680,7 @@
 	return -ENODEV;
 }
 
-void __exit gc_exit(void)
+static void __exit gc_exit(void)
 {
 	int i, j;
 
diff -Nru a/drivers/input/joystick/gf2k.c b/drivers/input/joystick/gf2k.c
--- a/drivers/input/joystick/gf2k.c	2005-03-11 12:51:47 -08:00
+++ b/drivers/input/joystick/gf2k.c	2005-03-11 12:51:47 -08:00
@@ -36,15 +36,16 @@
 #include <linux/input.h>
 #include <linux/gameport.h>
 
+#define DRIVER_DESC	"Genius Flight 2000 joystick driver"
+
 MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
-MODULE_DESCRIPTION("Genius Flight 2000 joystick driver");
+MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
 
 #define GF2K_START		400	/* The time we wait for the first bit [400 us] */
 #define GF2K_STROBE		40	/* The time we wait for the first bit [40 us] */
 #define GF2K_TIMEOUT		4	/* Wait for everything to settle [4 ms] */
 #define GF2K_LENGTH		80	/* Max number of triplets in a packet */
-#define GF2K_REFRESH		HZ/50	/* Time between joystick polls [20 ms] */
 
 /*
  * Genius joystick ids ...
@@ -80,11 +81,9 @@
 
 struct gf2k {
 	struct gameport *gameport;
-	struct timer_list timer;
 	struct input_dev dev;
 	int reads;
 	int bads;
-	int used;
 	unsigned char id;
 	unsigned char length;
 	char phys[32];
@@ -202,60 +201,56 @@
 }
 
 /*
- * gf2k_timer() reads and analyzes Genius joystick data.
+ * gf2k_poll() reads and analyzes Genius joystick data.
  */
 
-static void gf2k_timer(unsigned long private)
+static void gf2k_poll(struct gameport *gameport)
 {
-	struct gf2k *gf2k = (void *) private;
+	struct gf2k *gf2k = gameport_get_drvdata(gameport);
 	unsigned char data[GF2K_LENGTH];
 
 	gf2k->reads++;
 
-	if (gf2k_read_packet(gf2k->gameport, gf2k_length[gf2k->id], data) < gf2k_length[gf2k->id]) {
+	if (gf2k_read_packet(gf2k->gameport, gf2k_length[gf2k->id], data) < gf2k_length[gf2k->id])
 		gf2k->bads++;
-	} else gf2k_read(gf2k, data);
-
-	mod_timer(&gf2k->timer, jiffies + GF2K_REFRESH);
+	else
+		gf2k_read(gf2k, data);
 }
 
 static int gf2k_open(struct input_dev *dev)
 {
 	struct gf2k *gf2k = dev->private;
-	if (!gf2k->used++)
-		mod_timer(&gf2k->timer, jiffies + GF2K_REFRESH);
+
+	gameport_start_polling(gf2k->gameport);
 	return 0;
 }
 
 static void gf2k_close(struct input_dev *dev)
 {
 	struct gf2k *gf2k = dev->private;
-	if (!--gf2k->used)
-		del_timer(&gf2k->timer);
+
+	gameport_stop_polling(gf2k->gameport);
 }
 
 /*
  * gf2k_connect() probes for Genius id joysticks.
  */
 
-static void gf2k_connect(struct gameport *gameport, struct gameport_dev *dev)
+static int gf2k_connect(struct gameport *gameport, struct gameport_driver *drv)
 {
 	struct gf2k *gf2k;
 	unsigned char data[GF2K_LENGTH];
-	int i;
-
-	if (!(gf2k = kmalloc(sizeof(struct gf2k), GFP_KERNEL)))
-		return;
-	memset(gf2k, 0, sizeof(struct gf2k));
+	int i, err;
 
-	gameport->private = gf2k;
+	if (!(gf2k = kcalloc(1, sizeof(struct gf2k), GFP_KERNEL)))
+		return -ENOMEM;
 
 	gf2k->gameport = gameport;
-	init_timer(&gf2k->timer);
-	gf2k->timer.data = (long) gf2k;
-	gf2k->timer.function = gf2k_timer;
 
-	if (gameport_open(gameport, dev, GAMEPORT_MODE_RAW))
+	gameport_set_drvdata(gameport, gf2k);
+
+	err = gameport_open(gameport, drv, GAMEPORT_MODE_RAW);
+	if (err)
 		goto fail1;
 
 	gf2k_trigger_seq(gameport, gf2k_seq_reset);
@@ -266,16 +261,22 @@
 
 	msleep(GF2K_TIMEOUT);
 
-	if (gf2k_read_packet(gameport, GF2K_LENGTH, data) < 12)
+	if (gf2k_read_packet(gameport, GF2K_LENGTH, data) < 12) {
+		err = -ENODEV;
 		goto fail2;
+	}
 
-	if (!(gf2k->id = GB(7,2,0) | GB(3,3,2) | GB(0,3,5)))
+	if (!(gf2k->id = GB(7,2,0) | GB(3,3,2) | GB(0,3,5))) {
+		err = -ENODEV;
 		goto fail2;
+	}
 
 #ifdef RESET_WORKS
 	if ((gf2k->id != (GB(19,2,0) | GB(15,3,2) | GB(12,3,5))) ||
-	    (gf2k->id != (GB(31,2,0) | GB(27,3,2) | GB(24,3,5))))
+	    (gf2k->id != (GB(31,2,0) | GB(27,3,2) | GB(24,3,5)))) {
+		err = -ENODEV;
 		goto fail2;
+	}
 #else
 	gf2k->id = 6;
 #endif
@@ -283,9 +284,13 @@
 	if (gf2k->id > GF2K_ID_MAX || !gf2k_axes[gf2k->id]) {
 		printk(KERN_WARNING "gf2k.c: Not yet supported joystick on %s. [id: %d type:%s]\n",
 			gameport->phys, gf2k->id, gf2k->id > GF2K_ID_MAX ? "Unknown" : gf2k_names[gf2k->id]);
+		err = -ENODEV;
 		goto fail2;
 	}
 
+	gameport_set_poll_handler(gameport, gf2k_poll);
+	gameport_set_poll_interval(gameport, 20);
+
 	sprintf(gf2k->phys, "%s/input0", gameport->phys);
 
 	gf2k->length = gf2k_lens[gf2k->id];
@@ -333,33 +338,42 @@
 	input_register_device(&gf2k->dev);
 	printk(KERN_INFO "input: %s on %s\n", gf2k_names[gf2k->id], gameport->phys);
 
-	return;
+	return 0;
+
 fail2:	gameport_close(gameport);
-fail1:	kfree(gf2k);
+fail1:	gameport_set_drvdata(gameport, NULL);
+	kfree(gf2k);
+	return err;
 }
 
 static void gf2k_disconnect(struct gameport *gameport)
 {
-	struct gf2k *gf2k = gameport->private;
+	struct gf2k *gf2k = gameport_get_drvdata(gameport);
+
 	input_unregister_device(&gf2k->dev);
 	gameport_close(gameport);
+	gameport_set_drvdata(gameport, NULL);
 	kfree(gf2k);
 }
 
-static struct gameport_dev gf2k_dev = {
-	.connect =	gf2k_connect,
-	.disconnect =	gf2k_disconnect,
+static struct gameport_driver gf2k_drv = {
+	.driver		= {
+		.name	= "gf2k",
+	},
+	.description	= DRIVER_DESC,
+	.connect	= gf2k_connect,
+	.disconnect	= gf2k_disconnect,
 };
 
-int __init gf2k_init(void)
+static int __init gf2k_init(void)
 {
-	gameport_register_device(&gf2k_dev);
+	gameport_register_driver(&gf2k_drv);
 	return 0;
 }
 
-void __exit gf2k_exit(void)
+static void __exit gf2k_exit(void)
 {
-	gameport_unregister_device(&gf2k_dev);
+	gameport_unregister_driver(&gf2k_drv);
 }
 
 module_init(gf2k_init);
diff -Nru a/drivers/input/joystick/grip.c b/drivers/input/joystick/grip.c
--- a/drivers/input/joystick/grip.c	2005-03-11 12:51:42 -08:00
+++ b/drivers/input/joystick/grip.c	2005-03-11 12:51:42 -08:00
@@ -35,8 +35,10 @@
 #include <linux/gameport.h>
 #include <linux/input.h>
 
+#define DRIVER_DESC	"Gravis GrIP protocol joystick driver"
+
 MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
-MODULE_DESCRIPTION("Gravis GrIP protocol joystick driver");
+MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
 
 #define GRIP_MODE_GPP		1
@@ -51,14 +53,10 @@
 #define GRIP_MAX_CHUNKS_XT	10
 #define GRIP_MAX_BITS_XT	30
 
-#define GRIP_REFRESH_TIME	HZ/50	/* 20 ms */
-
 struct grip {
 	struct gameport *gameport;
-	struct timer_list timer;
 	struct input_dev dev[2];
 	unsigned char mode[2];
-	int used;
 	int reads;
 	int bads;
 	char phys[2][32];
@@ -183,9 +181,9 @@
  * grip_timer() repeatedly polls the joysticks and generates events.
  */
 
-static void grip_timer(unsigned long private)
+static void grip_poll(struct gameport *gameport)
 {
-	struct grip *grip = (void*) private;
+	struct grip *grip = gameport_get_drvdata(gameport);
 	unsigned int data[GRIP_LENGTH_XT];
 	struct input_dev *dev;
 	int i, j;
@@ -279,43 +277,39 @@
 
 		input_sync(dev);
 	}
-
-	mod_timer(&grip->timer, jiffies + GRIP_REFRESH_TIME);
 }
 
 static int grip_open(struct input_dev *dev)
 {
 	struct grip *grip = dev->private;
-	if (!grip->used++)
-		mod_timer(&grip->timer, jiffies + GRIP_REFRESH_TIME);
+
+	gameport_start_polling(grip->gameport);
 	return 0;
 }
 
 static void grip_close(struct input_dev *dev)
 {
 	struct grip *grip = dev->private;
-	if (!--grip->used)
-		del_timer(&grip->timer);
+
+	gameport_stop_polling(grip->gameport);
 }
 
-static void grip_connect(struct gameport *gameport, struct gameport_dev *dev)
+static int grip_connect(struct gameport *gameport, struct gameport_driver *drv)
 {
 	struct grip *grip;
 	unsigned int data[GRIP_LENGTH_XT];
 	int i, j, t;
+	int err;
 
-	if (!(grip = kmalloc(sizeof(struct grip), GFP_KERNEL)))
-		return;
-	memset(grip, 0, sizeof(struct grip));
-
-	gameport->private = grip;
+	if (!(grip = kcalloc(1, sizeof(struct grip), GFP_KERNEL)))
+		return -ENOMEM;
 
 	grip->gameport = gameport;
-	init_timer(&grip->timer);
-	grip->timer.data = (long) grip;
-	grip->timer.function = grip_timer;
 
-	 if (gameport_open(gameport, dev, GAMEPORT_MODE_RAW))
+	gameport_set_drvdata(gameport, grip);
+
+	err = gameport_open(gameport, drv, GAMEPORT_MODE_RAW);
+	if (err)
 		goto fail1;
 
 	for (i = 0; i < 2; i++) {
@@ -337,8 +331,13 @@
 		}
 	}
 
-	if (!grip->mode[0] && !grip->mode[1])
+	if (!grip->mode[0] && !grip->mode[1]) {
+		err = -ENODEV;
 		goto fail2;
+	}
+
+	gameport_set_poll_handler(gameport, grip_poll);
+	gameport_set_poll_interval(gameport, 20);
 
 	for (i = 0; i < 2; i++)
 		if (grip->mode[i]) {
@@ -361,68 +360,62 @@
 
 			for (j = 0; (t = grip_abs[grip->mode[i]][j]) >= 0; j++) {
 
-				set_bit(t, grip->dev[i].absbit);
-
-				if (j < grip_cen[grip->mode[i]]) {
-					grip->dev[i].absmin[t] = 14;
-					grip->dev[i].absmax[t] = 52;
-					grip->dev[i].absfuzz[t] = 1;
-					grip->dev[i].absflat[t] = 2;
-					continue;
-				}
-
-				if (j < grip_anx[grip->mode[i]]) {
-					grip->dev[i].absmin[t] = 3;
-					grip->dev[i].absmax[t] = 57;
-					grip->dev[i].absfuzz[t] = 1;
-					continue;
-				}
-
-				grip->dev[i].absmin[t] = -1;
-				grip->dev[i].absmax[t] = 1;
+				if (j < grip_cen[grip->mode[i]])
+					input_set_abs_params(&grip->dev[i], t, 14, 52, 1, 2);
+				else if (j < grip_anx[grip->mode[i]])
+					input_set_abs_params(&grip->dev[i], t, 3, 57, 1, 0);
+				else
+					input_set_abs_params(&grip->dev[i], t, -1, 1, 0, 0);
 			}
 
 			for (j = 0; (t = grip_btn[grip->mode[i]][j]) >= 0; j++)
 				if (t > 0)
 					set_bit(t, grip->dev[i].keybit);
 
-			input_register_device(grip->dev + i);
-
 			printk(KERN_INFO "input: %s on %s\n",
 				grip_name[grip->mode[i]], gameport->phys);
+			input_register_device(grip->dev + i);
 		}
 
-	return;
+	return 0;
+
 fail2:	gameport_close(gameport);
-fail1:	kfree(grip);
+fail1:	gameport_set_drvdata(gameport, NULL);
+	kfree(grip);
+	return err;
 }
 
 static void grip_disconnect(struct gameport *gameport)
 {
+	struct grip *grip = gameport_get_drvdata(gameport);
 	int i;
 
-	struct grip *grip = gameport->private;
 	for (i = 0; i < 2; i++)
 		if (grip->mode[i])
 			input_unregister_device(grip->dev + i);
 	gameport_close(gameport);
+	gameport_set_drvdata(gameport, NULL);
 	kfree(grip);
 }
 
-static struct gameport_dev grip_dev = {
-	.connect =	grip_connect,
-	.disconnect =	grip_disconnect,
+static struct gameport_driver grip_drv = {
+	.driver		= {
+		.name	= "grip",
+	},
+	.description	= DRIVER_DESC,
+	.connect	= grip_connect,
+	.disconnect	= grip_disconnect,
 };
 
-int __init grip_init(void)
+static int __init grip_init(void)
 {
-	gameport_register_device(&grip_dev);
+	gameport_register_driver(&grip_drv);
 	return 0;
 }
 
-void __exit grip_exit(void)
+static void __exit grip_exit(void)
 {
-	gameport_unregister_device(&grip_dev);
+	gameport_unregister_driver(&grip_drv);
 }
 
 module_init(grip_init);
diff -Nru a/drivers/input/joystick/grip_mp.c b/drivers/input/joystick/grip_mp.c
--- a/drivers/input/joystick/grip_mp.c	2005-03-11 12:51:51 -08:00
+++ b/drivers/input/joystick/grip_mp.c	2005-03-11 12:51:51 -08:00
@@ -20,8 +20,10 @@
 #include <linux/delay.h>
 #include <linux/proc_fs.h>
 
+#define DRIVER_DESC	"Gravis Grip Multiport driver"
+
 MODULE_AUTHOR("Brian Bonnlander");
-MODULE_DESCRIPTION("Gravis Grip Multiport driver");
+MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
 
 #ifdef GRIP_DEBUG
@@ -36,11 +38,9 @@
 
 struct grip_mp {
 	struct gameport *gameport;
-	struct timer_list timer;
 	struct input_dev dev[4];
 	int mode[4];
 	int registered[4];
-	int used;
 	int reads;
 	int bads;
 
@@ -79,7 +79,6 @@
  */
 
 #define GRIP_INIT_DELAY         2000          /*  2 ms */
-#define GRIP_REFRESH_TIME       HZ/50	      /* 20 ms */
 
 #define GRIP_MODE_NONE		0
 #define GRIP_MODE_RESET         1
@@ -477,9 +476,9 @@
 	}
 
 	if (dig_mode)
-		dbg("multiport_init(): digital mode achieved.\n");
+		dbg("multiport_init(): digital mode activated.\n");
 	else {
-		dbg("multiport_init(): unable to achieve digital mode.\n");
+		dbg("multiport_init(): unable to activate digital mode.\n");
 		return 0;
 	}
 
@@ -524,8 +523,9 @@
  * Get the multiport state.
  */
 
-static void get_and_report_mp_state(struct grip_mp *grip)
+static void grip_poll(struct gameport *gameport)
 {
+	struct grip_mp *grip = gameport_get_drvdata(gameport);
 	int i, npkts, flags;
 
 	for (npkts = 0; npkts < 4; npkts++) {
@@ -551,8 +551,8 @@
 static int grip_open(struct input_dev *dev)
 {
 	struct grip_mp *grip = dev->private;
-	if (!grip->used++)
-		mod_timer(&grip->timer, jiffies + GRIP_REFRESH_TIME);
+
+	gameport_start_polling(grip->gameport);
 	return 0;
 }
 
@@ -563,8 +563,8 @@
 static void grip_close(struct input_dev *dev)
 {
 	struct grip_mp *grip = dev->private;
-	if (!--grip->used)
-		del_timer(&grip->timer);
+
+	gameport_start_polling(grip->gameport);
 }
 
 /*
@@ -585,11 +585,8 @@
 	grip->dev[slot].id.version = 0x0100;
 	grip->dev[slot].evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
 
-	for (j = 0; (t = grip_abs[grip->mode[slot]][j]) >= 0; j++) {
-		set_bit(t, grip->dev[slot].absbit);
-		grip->dev[slot].absmin[t] = -1;
-		grip->dev[slot].absmax[t] = 1;
-	}
+	for (j = 0; (t = grip_abs[grip->mode[slot]][j]) >= 0; j++)
+		input_set_abs_params(&grip->dev[slot], t, -1, 1, 0, 0);
 
 	for (j = 0; (t = grip_btn[grip->mode[slot]][j]) >= 0; j++)
 		if (t > 0)
@@ -605,69 +602,75 @@
 	       grip_name[grip->mode[slot]], slot);
 }
 
-/*
- * Repeatedly polls the multiport and generates events.
- */
-
-static void grip_timer(unsigned long private)
-{
-	struct grip_mp *grip = (void*) private;
-	get_and_report_mp_state(grip);
-	mod_timer(&grip->timer, jiffies + GRIP_REFRESH_TIME);
-}
-
-static void grip_connect(struct gameport *gameport, struct gameport_dev *dev)
+static int grip_connect(struct gameport *gameport, struct gameport_driver *drv)
 {
 	struct grip_mp *grip;
+	int err;
+
+	if (!(grip = kcalloc(1, sizeof(struct grip_mp), GFP_KERNEL)))
+		return -ENOMEM;
 
-	if (!(grip = kmalloc(sizeof(struct grip_mp), GFP_KERNEL)))
-		return;
-	memset(grip, 0, sizeof(struct grip_mp));
-	gameport->private = grip;
 	grip->gameport = gameport;
-	init_timer(&grip->timer);
-	grip->timer.data = (long) grip;
-	grip->timer.function = grip_timer;
 
-	if (gameport_open(gameport, dev, GAMEPORT_MODE_RAW))
+	gameport_set_drvdata(gameport, grip);
+
+	err = gameport_open(gameport, drv, GAMEPORT_MODE_RAW);
+	if (err)
 		goto fail1;
-	if (!multiport_init(grip))
+
+	gameport_set_poll_handler(gameport, grip_poll);
+	gameport_set_poll_interval(gameport, 20);
+
+	if (!multiport_init(grip)) {
+		err = -ENODEV;
 		goto fail2;
-	if (!grip->mode[0] && !grip->mode[1] &&   /* nothing plugged in */
-	    !grip->mode[2] && !grip->mode[3])
+	}
+
+	if (!grip->mode[0] && !grip->mode[1] && !grip->mode[2] && !grip->mode[3]) {
+		/* nothing plugged in */
+		err = -ENODEV;
 		goto fail2;
-	return;
+	}
+
+	return 0;
 
 fail2:	gameport_close(gameport);
-fail1:	kfree(grip);
+fail1:	gameport_set_drvdata(gameport, NULL);
+	kfree(grip);
+	return err;
 }
 
 static void grip_disconnect(struct gameport *gameport)
 {
+	struct grip_mp *grip = gameport_get_drvdata(gameport);
 	int i;
 
-	struct grip_mp *grip = gameport->private;
 	for (i = 0; i < 4; i++)
 		if (grip->registered[i])
 			input_unregister_device(grip->dev + i);
 	gameport_close(gameport);
+	gameport_set_drvdata(gameport, NULL);
 	kfree(grip);
 }
 
-static struct gameport_dev grip_dev = {
+static struct gameport_driver grip_drv = {
+	.driver		= {
+		.name	= "grip_mp",
+	},
+	.description	= DRIVER_DESC,
 	.connect	= grip_connect,
 	.disconnect	= grip_disconnect,
 };
 
-static int grip_init(void)
+static int __init grip_init(void)
 {
-	gameport_register_device(&grip_dev);
+	gameport_register_driver(&grip_drv);
 	return 0;
 }
 
-static void grip_exit(void)
+static void __exit grip_exit(void)
 {
-	gameport_unregister_device(&grip_dev);
+	gameport_unregister_driver(&grip_drv);
 }
 
 module_init(grip_init);
diff -Nru a/drivers/input/joystick/guillemot.c b/drivers/input/joystick/guillemot.c
--- a/drivers/input/joystick/guillemot.c	2005-03-11 12:51:42 -08:00
+++ b/drivers/input/joystick/guillemot.c	2005-03-11 12:51:42 -08:00
@@ -36,14 +36,15 @@
 #include <linux/gameport.h>
 #include <linux/input.h>
 
+#define DRIVER_DESC	"Guillemot Digital joystick driver"
+
 MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
-MODULE_DESCRIPTION("Guillemot Digital joystick driver");
+MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
 
 #define GUILLEMOT_MAX_START	600	/* 600 us */
 #define GUILLEMOT_MAX_STROBE	60	/* 60 us */
 #define GUILLEMOT_MAX_LENGTH	17	/* 17 bytes */
-#define GUILLEMOT_REFRESH_TIME	HZ/50	/* 20 ms */
 
 static short guillemot_abs_pad[] =
 	{ ABS_X, ABS_Y, ABS_THROTTLE, ABS_RUDDER, -1 };
@@ -67,8 +68,6 @@
 struct guillemot {
 	struct gameport *gameport;
 	struct input_dev dev;
-	struct timer_list timer;
-	int used;
 	int bads;
 	int reads;
 	struct guillemot_type *type;
@@ -118,12 +117,12 @@
 }
 
 /*
- * guillemot_timer() reads and analyzes Guillemot joystick data.
+ * guillemot_poll() reads and analyzes Guillemot joystick data.
  */
 
-static void guillemot_timer(unsigned long private)
+static void guillemot_poll(struct gameport *gameport)
 {
-	struct guillemot *guillemot = (struct guillemot *) private;
+	struct guillemot *guillemot = gameport_get_drvdata(gameport);
 	struct input_dev *dev = &guillemot->dev;
 	u8 data[GUILLEMOT_MAX_LENGTH];
 	int i;
@@ -148,8 +147,6 @@
 	}
 
 	input_sync(dev);
-
-	mod_timer(&guillemot->timer, jiffies + GUILLEMOT_REFRESH_TIME);
 }
 
 /*
@@ -159,8 +156,8 @@
 static int guillemot_open(struct input_dev *dev)
 {
 	struct guillemot *guillemot = dev->private;
-	if (!guillemot->used++)
-		mod_timer(&guillemot->timer, jiffies + GUILLEMOT_REFRESH_TIME);
+
+	gameport_start_polling(guillemot->gameport);
 	return 0;
 }
 
@@ -171,38 +168,38 @@
 static void guillemot_close(struct input_dev *dev)
 {
 	struct guillemot *guillemot = dev->private;
-	if (!--guillemot->used)
-		del_timer(&guillemot->timer);
+
+	gameport_stop_polling(guillemot->gameport);
 }
 
 /*
  * guillemot_connect() probes for Guillemot joysticks.
  */
 
-static void guillemot_connect(struct gameport *gameport, struct gameport_dev *dev)
+static int guillemot_connect(struct gameport *gameport, struct gameport_driver *drv)
 {
 	struct guillemot *guillemot;
 	u8 data[GUILLEMOT_MAX_LENGTH];
 	int i, t;
+	int err;
 
-	if (!(guillemot = kmalloc(sizeof(struct guillemot), GFP_KERNEL)))
-		return;
-	memset(guillemot, 0, sizeof(struct guillemot));
-
-	gameport->private = guillemot;
+	if (!(guillemot = kcalloc(1, sizeof(struct guillemot), GFP_KERNEL)))
+		return -ENOMEM;
 
 	guillemot->gameport = gameport;
-	init_timer(&guillemot->timer);
-	guillemot->timer.data = (long) guillemot;
-	guillemot->timer.function = guillemot_timer;
 
-	if (gameport_open(gameport, dev, GAMEPORT_MODE_RAW))
+	gameport_set_drvdata(gameport, guillemot);
+
+	err = gameport_open(gameport, drv, GAMEPORT_MODE_RAW);
+	if (err)
 		goto fail1;
 
 	i = guillemot_read_packet(gameport, data);
 
-	if (i != GUILLEMOT_MAX_LENGTH * 8 || data[0] != 0x55 || data[16] != 0xaa)
+	if (i != GUILLEMOT_MAX_LENGTH * 8 || data[0] != 0x55 || data[16] != 0xaa) {
+		err = -ENODEV;
 		goto fail2;
+	}
 
 	for (i = 0; guillemot_type[i].name; i++)
 		if (guillemot_type[i].id == data[11])
@@ -211,9 +208,13 @@
 	if (!guillemot_type[i].name) {
 		printk(KERN_WARNING "guillemot.c: Unknown joystick on %s. [ %02x%02x:%04x, ver %d.%02d ]\n",
 			gameport->phys, data[12], data[13], data[11], data[14], data[15]);
+		err = -ENODEV;
 		goto fail2;
 	}
 
+	gameport_set_poll_handler(gameport, guillemot_poll);
+	gameport_set_poll_interval(gameport, 20);
+
 	sprintf(guillemot->phys, "%s/input0", gameport->phys);
 
 	guillemot->type = guillemot_type + i;
@@ -231,19 +232,13 @@
 
 	guillemot->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
 
-	for (i = 0; (t = guillemot->type->abs[i]) >= 0; i++) {
-		set_bit(t, guillemot->dev.absbit);
-		guillemot->dev.absmin[t] = 0;
-		guillemot->dev.absmax[t] = 255;
-	}
+	for (i = 0; (t = guillemot->type->abs[i]) >= 0; i++)
+		input_set_abs_params(&guillemot->dev, t, 0, 255, 0, 0);
 
-	if (guillemot->type->hat)
-		for (i = 0; i < 2; i++) {
-			t = ABS_HAT0X + i;
-			set_bit(t, guillemot->dev.absbit);
-			guillemot->dev.absmin[t] = -1;
-			guillemot->dev.absmax[t] = 1;
-		}
+	if (guillemot->type->hat) {
+		input_set_abs_params(&guillemot->dev, ABS_HAT0X, -1, 1, 0, 0);
+		input_set_abs_params(&guillemot->dev, ABS_HAT0Y, -1, 1, 0, 0);
+	}
 
 	for (i = 0; (t = guillemot->type->btn[i]) >= 0; i++)
 		set_bit(t, guillemot->dev.keybit);
@@ -252,34 +247,42 @@
 	printk(KERN_INFO "input: %s ver %d.%02d on %s\n",
 		guillemot->type->name, data[14], data[15], gameport->phys);
 
-	return;
+	return 0;
+
 fail2:	gameport_close(gameport);
-fail1:  kfree(guillemot);
+fail1:  gameport_set_drvdata(gameport, NULL);
+	kfree(guillemot);
+	return err;
 }
 
 static void guillemot_disconnect(struct gameport *gameport)
 {
-	struct guillemot *guillemot = gameport->private;
+	struct guillemot *guillemot = gameport_get_drvdata(gameport);
+
 	printk(KERN_INFO "guillemot.c: Failed %d reads out of %d on %s\n", guillemot->reads, guillemot->bads, guillemot->phys);
 	input_unregister_device(&guillemot->dev);
 	gameport_close(gameport);
 	kfree(guillemot);
 }
 
-static struct gameport_dev guillemot_dev = {
-	.connect =	guillemot_connect,
-	.disconnect =	guillemot_disconnect,
+static struct gameport_driver guillemot_drv = {
+	.driver		= {
+		.name	= "guillemot",
+	},
+	.description	= DRIVER_DESC,
+	.connect	= guillemot_connect,
+	.disconnect	= guillemot_disconnect,
 };
 
-int __init guillemot_init(void)
+static int __init guillemot_init(void)
 {
-	gameport_register_device(&guillemot_dev);
+	gameport_register_driver(&guillemot_drv);
 	return 0;
 }
 
-void __exit guillemot_exit(void)
+static void __exit guillemot_exit(void)
 {
-	gameport_unregister_device(&guillemot_dev);
+	gameport_unregister_driver(&guillemot_drv);
 }
 
 module_init(guillemot_init);
diff -Nru a/drivers/input/joystick/iforce/iforce-serio.c b/drivers/input/joystick/iforce/iforce-serio.c
--- a/drivers/input/joystick/iforce/iforce-serio.c	2005-03-11 12:51:41 -08:00
+++ b/drivers/input/joystick/iforce/iforce-serio.c	2005-03-11 12:51:41 -08:00
@@ -75,13 +75,15 @@
 
 static void iforce_serio_write_wakeup(struct serio *serio)
 {
-	iforce_serial_xmit((struct iforce *)serio->private);
+	struct iforce *iforce = serio_get_drvdata(serio);
+
+	iforce_serial_xmit(iforce);
 }
 
 static irqreturn_t iforce_serio_irq(struct serio *serio,
 		unsigned char data, unsigned int flags, struct pt_regs *regs)
 {
-	struct iforce* iforce = serio->private;
+	struct iforce *iforce = serio_get_drvdata(serio);
 
 	if (!iforce->pkt) {
 		if (data == 0x2b)
@@ -124,45 +126,66 @@
 	return IRQ_HANDLED;
 }
 
-static void iforce_serio_connect(struct serio *serio, struct serio_driver *drv)
+static int iforce_serio_connect(struct serio *serio, struct serio_driver *drv)
 {
 	struct iforce *iforce;
-	if (serio->type != (SERIO_RS232 | SERIO_IFORCE))
-		return;
+	int err;
+
+	if (!(iforce = kmalloc(sizeof(struct iforce), GFP_KERNEL)))
+		return -ENOMEM;
 
-	if (!(iforce = kmalloc(sizeof(struct iforce), GFP_KERNEL))) return;
 	memset(iforce, 0, sizeof(struct iforce));
 
 	iforce->bus = IFORCE_232;
 	iforce->serio = serio;
-	serio->private = iforce;
 
-	if (serio_open(serio, drv)) {
+	serio_set_drvdata(serio, iforce);
+
+	err = serio_open(serio, drv);
+	if (err) {
+		serio_set_drvdata(serio, NULL);
 		kfree(iforce);
-		return;
+		return err;
 	}
 
 	if (iforce_init_device(iforce)) {
 		serio_close(serio);
+		serio_set_drvdata(serio, NULL);
 		kfree(iforce);
-		return;
+		return -ENODEV;
 	}
+
+	return 0;
 }
 
 static void iforce_serio_disconnect(struct serio *serio)
 {
-	struct iforce* iforce = serio->private;
+	struct iforce *iforce = serio_get_drvdata(serio);
 
 	input_unregister_device(&iforce->dev);
 	serio_close(serio);
+	serio_set_drvdata(serio, NULL);
 	kfree(iforce);
 }
 
+static struct serio_device_id iforce_serio_ids[] = {
+	{
+		.type	= SERIO_RS232,
+		.proto	= SERIO_IFORCE,
+		.id	= SERIO_ANY,
+		.extra	= SERIO_ANY,
+	},
+	{ 0 }
+};
+
+MODULE_DEVICE_TABLE(serio, iforce_serio_ids);
+
 struct serio_driver iforce_serio_drv = {
 	.driver		= {
 		.name	= "iforce",
 	},
 	.description	= "RS232 I-Force joysticks and wheels driver",
+	.id_table	= iforce_serio_ids,
 	.write_wakeup	= iforce_serio_write_wakeup,
 	.interrupt	= iforce_serio_irq,
 	.connect	= iforce_serio_connect,
diff -Nru a/drivers/input/joystick/interact.c b/drivers/input/joystick/interact.c
--- a/drivers/input/joystick/interact.c	2005-03-11 12:51:47 -08:00
+++ b/drivers/input/joystick/interact.c	2005-03-11 12:51:47 -08:00
@@ -39,14 +39,15 @@
 #include <linux/gameport.h>
 #include <linux/input.h>
 
+#define DRIVER_DESC	"InterAct digital joystick driver"
+
 MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
-MODULE_DESCRIPTION("InterAct digital joystick driver");
+MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
 
-#define INTERACT_MAX_START	400	/* 400 us */
-#define INTERACT_MAX_STROBE	40	/* 40 us */
+#define INTERACT_MAX_START	600	/* 400 us */
+#define INTERACT_MAX_STROBE	60	/* 40 us */
 #define INTERACT_MAX_LENGTH	32	/* 32 bits */
-#define INTERACT_REFRESH_TIME	HZ/50	/* 20 ms */
 
 #define INTERACT_TYPE_HHFX	0	/* HammerHead/FX */
 #define INTERACT_TYPE_PP8D	1	/* ProPad 8 */
@@ -54,8 +55,6 @@
 struct interact {
 	struct gameport *gameport;
 	struct input_dev dev;
-	struct timer_list timer;
-	int used;
 	int bads;
 	int reads;
 	unsigned char type;
@@ -125,12 +124,12 @@
 }
 
 /*
- * interact_timer() reads and analyzes InterAct joystick data.
+ * interact_poll() reads and analyzes InterAct joystick data.
  */
 
-static void interact_timer(unsigned long private)
+static void interact_poll(struct gameport *gameport)
 {
-	struct interact *interact = (struct interact *) private;
+	struct interact *interact = gameport_get_drvdata(gameport);
 	struct input_dev *dev = &interact->dev;
 	u32 data[3];
 	int i;
@@ -177,9 +176,6 @@
 	}
 
 	input_sync(dev);
-
-	mod_timer(&interact->timer, jiffies + INTERACT_REFRESH_TIME);
-
 }
 
 /*
@@ -189,8 +185,8 @@
 static int interact_open(struct input_dev *dev)
 {
 	struct interact *interact = dev->private;
-	if (!interact->used++)
-		mod_timer(&interact->timer, jiffies + INTERACT_REFRESH_TIME);
+
+	gameport_start_polling(interact->gameport);
 	return 0;
 }
 
@@ -201,37 +197,36 @@
 static void interact_close(struct input_dev *dev)
 {
 	struct interact *interact = dev->private;
-	if (!--interact->used)
-		del_timer(&interact->timer);
+
+	gameport_stop_polling(interact->gameport);
 }
 
 /*
  * interact_connect() probes for InterAct joysticks.
  */
 
-static void interact_connect(struct gameport *gameport, struct gameport_dev *dev)
+static int interact_connect(struct gameport *gameport, struct gameport_driver *drv)
 {
 	struct interact *interact;
 	__u32 data[3];
 	int i, t;
+	int err;
 
-	if (!(interact = kmalloc(sizeof(struct interact), GFP_KERNEL)))
-		return;
-	memset(interact, 0, sizeof(struct interact));
-
-	gameport->private = interact;
+	if (!(interact = kcalloc(1, sizeof(struct interact), GFP_KERNEL)))
+		return -ENOMEM;
 
 	interact->gameport = gameport;
-	init_timer(&interact->timer);
-	interact->timer.data = (long) interact;
-	interact->timer.function = interact_timer;
 
-	if (gameport_open(gameport, dev, GAMEPORT_MODE_RAW))
+	gameport_set_drvdata(gameport, interact);
+
+	err = gameport_open(gameport, drv, GAMEPORT_MODE_RAW);
+	if (err)
 		goto fail1;
 
 	i = interact_read_packet(gameport, INTERACT_MAX_LENGTH * 2, data);
 
 	if (i != 32 || (data[0] >> 24) != 0x0c || (data[1] >> 24) != 0x02) {
+		err = -ENODEV;
 		goto fail2;
 	}
 
@@ -242,9 +237,13 @@
 	if (!interact_type[i].length) {
 		printk(KERN_WARNING "interact.c: Unknown joystick on %s. [len %d d0 %08x d1 %08x i2 %08x]\n",
 			gameport->phys, i, data[0], data[1], data[2]);
+		err = -ENODEV;
 		goto fail2;
 	}
 
+	gameport_set_poll_handler(gameport, interact_poll);
+	gameport_set_poll_interval(gameport, 20);
+
 	sprintf(interact->phys, "%s/input0", gameport->phys);
 
 	interact->type = i;
@@ -281,33 +280,42 @@
 	printk(KERN_INFO "input: %s on %s\n",
 		interact_type[interact->type].name, gameport->phys);
 
-	return;
+	return 0;
+
 fail2:	gameport_close(gameport);
-fail1:  kfree(interact);
+fail1:  gameport_set_drvdata(gameport, NULL);
+	kfree(interact);
+	return err;
 }
 
 static void interact_disconnect(struct gameport *gameport)
 {
-	struct interact *interact = gameport->private;
+	struct interact *interact = gameport_get_drvdata(gameport);
+
 	input_unregister_device(&interact->dev);
 	gameport_close(gameport);
+	gameport_set_drvdata(gameport, NULL);
 	kfree(interact);
 }
 
-static struct gameport_dev interact_dev = {
-	.connect =	interact_connect,
-	.disconnect =	interact_disconnect,
+static struct gameport_driver interact_drv = {
+	.driver		= {
+		.name	= "interact",
+	},
+	.description	= DRIVER_DESC,
+	.connect	= interact_connect,
+	.disconnect	= interact_disconnect,
 };
 
-int __init interact_init(void)
+static int __init interact_init(void)
 {
-	gameport_register_device(&interact_dev);
+	gameport_register_driver(&interact_drv);
 	return 0;
 }
 
-void __exit interact_exit(void)
+static void __exit interact_exit(void)
 {
-	gameport_unregister_device(&interact_dev);
+	gameport_unregister_driver(&interact_drv);
 }
 
 module_init(interact_init);
diff -Nru a/drivers/input/joystick/joydump.c b/drivers/input/joystick/joydump.c
--- a/drivers/input/joystick/joydump.c	2005-03-11 12:51:51 -08:00
+++ b/drivers/input/joystick/joydump.c	2005-03-11 12:51:51 -08:00
@@ -35,8 +35,10 @@
 #include <linux/delay.h>
 #include <linux/init.h>
 
+#define DRIVER_DESC	"Gameport data dumper module"
+
 MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
-MODULE_DESCRIPTION("Gameport data dumper module");
+MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
 
 #define BUF_SIZE 256
@@ -46,38 +48,46 @@
 	unsigned char data;
 };
 
-static void __devinit joydump_connect(struct gameport *gameport, struct gameport_dev *dev)
+static int joydump_connect(struct gameport *gameport, struct gameport_driver *drv)
 {
-	struct joydump buf[BUF_SIZE];
+	struct joydump *buf;	/* all entries */
+	struct joydump *dump, *prev;	/* one entry each */
 	int axes[4], buttons;
 	int i, j, t, timeout;
 	unsigned long flags;
 	unsigned char u;
 
-	printk(KERN_INFO "joydump: ,------------------- START ------------------.\n");
-	printk(KERN_INFO "joydump: | Dumping gameport%s.\n", gameport->phys);
-	printk(KERN_INFO "joydump: | Speed: %4d kHz.                            |\n", gameport->speed);
+	printk(KERN_INFO "joydump: ,------------------ START ----------------.\n");
+	printk(KERN_INFO "joydump: | Dumping: %30s |\n", gameport->phys);
+	printk(KERN_INFO "joydump: | Speed: %28d kHz |\n", gameport->speed);
 
-	if (gameport_open(gameport, dev, GAMEPORT_MODE_RAW)) {
+	if (gameport_open(gameport, drv, GAMEPORT_MODE_RAW)) {
 
 		printk(KERN_INFO "joydump: | Raw mode not available - trying cooked.    |\n");
 
-		if (gameport_open(gameport, dev, GAMEPORT_MODE_COOKED)) {
+		if (gameport_open(gameport, drv, GAMEPORT_MODE_COOKED)) {
 
-			printk(KERN_INFO "joydump: | Cooked not available either. Failing.      |\n");
-			printk(KERN_INFO "joydump: `-------------------- END -------------------'\n");
-			return;
+			printk(KERN_INFO "joydump: | Cooked not available either. Failing.   |\n");
+			printk(KERN_INFO "joydump: `------------------- END -----------------'\n");
+			return -ENODEV;
 		}
 
 		gameport_cooked_read(gameport, axes, &buttons);
 
 		for (i = 0; i < 4; i++)
-			printk(KERN_INFO "joydump: | Axis %d: %4d.                              |\n", i, axes[i]);
-		printk(KERN_INFO "joydump: | Buttons %02x.                                |\n", buttons);
-		printk(KERN_INFO "joydump: `-------------------- END -------------------'\n");
+			printk(KERN_INFO "joydump: | Axis %d: %4d.                           |\n", i, axes[i]);
+		printk(KERN_INFO "joydump: | Buttons %02x.                             |\n", buttons);
+		printk(KERN_INFO "joydump: `------------------- END -----------------'\n");
 	}
 
 	timeout = gameport_time(gameport, 10000); /* 10 ms */
+
+	buf = kmalloc(BUF_SIZE * sizeof(struct joydump), GFP_KERNEL);
+	if (!buf) {
+		printk(KERN_INFO "joydump: no memory for testing\n");
+		goto jd_end;
+	}
+	dump = buf;
 	t = 0;
 	i = 1;
 
@@ -85,19 +95,21 @@
 
 	u = gameport_read(gameport);
 
-	buf[0].data = u;
-	buf[0].time = t;
+	dump->data = u;
+	dump->time = t;
+	dump++;
 
 	gameport_trigger(gameport);
 
 	while (i < BUF_SIZE && t < timeout) {
 
-		buf[i].data = gameport_read(gameport);
+		dump->data = gameport_read(gameport);
 
-		if (buf[i].data ^ u) {
-			u = buf[i].data;
-			buf[i].time = t;
+		if (dump->data ^ u) {
+			u = dump->data;
+			dump->time = t;
 			i++;
+			dump++;
 		}
 		t++;
 	}
@@ -109,42 +121,54 @@
  */
 
 	t = i;
+	dump = buf;
+	prev = dump;
 
-	printk(KERN_INFO "joydump: >------------------- DATA -------------------<\n");
-	printk(KERN_INFO "joydump: | index: %3d delta: %3d.%02d us data: ", 0, 0, 0);
+	printk(KERN_INFO "joydump: >------------------ DATA -----------------<\n");
+	printk(KERN_INFO "joydump: | index: %3d delta: %3d us data: ", 0, 0);
 	for (j = 7; j >= 0; j--)
-		printk("%d",(buf[0].data >> j) & 1);
+		printk("%d", (dump->data >> j) & 1);
 	printk(" |\n");
-	for (i = 1; i < t; i++) {
+	dump++;
+
+	for (i = 1; i < t; i++, dump++, prev++) {
 		printk(KERN_INFO "joydump: | index: %3d delta: %3d us data: ",
-			i, buf[i].time - buf[i-1].time);
+			i, dump->time - prev->time);
 		for (j = 7; j >= 0; j--)
-			printk("%d",(buf[i].data >> j) & 1);
-		printk("    |\n");
+			printk("%d", (dump->data >> j) & 1);
+		printk(" |\n");
 	}
+	kfree(buf);
+
+jd_end:
+	printk(KERN_INFO "joydump: `------------------- END -----------------'\n");
 
-	printk(KERN_INFO "joydump: `-------------------- END -------------------'\n");
+	return 0;
 }
 
-static void __devexit joydump_disconnect(struct gameport *gameport)
+static void joydump_disconnect(struct gameport *gameport)
 {
 	gameport_close(gameport);
 }
 
-static struct gameport_dev joydump_dev = {
-	.connect =	joydump_connect,
-	.disconnect =	joydump_disconnect,
+static struct gameport_driver joydump_drv = {
+	.driver		= {
+		.name	= "joydump",
+	},
+	.description	= DRIVER_DESC,
+	.connect	= joydump_connect,
+	.disconnect	= joydump_disconnect,
 };
 
 static int __init joydump_init(void)
 {
-	gameport_register_device(&joydump_dev);
+	gameport_register_driver(&joydump_drv);
 	return 0;
 }
 
 static void __exit joydump_exit(void)
 {
-	gameport_unregister_device(&joydump_dev);
+	gameport_unregister_driver(&joydump_drv);
 }
 
 module_init(joydump_init);
diff -Nru a/drivers/input/joystick/magellan.c b/drivers/input/joystick/magellan.c
--- a/drivers/input/joystick/magellan.c	2005-03-11 12:51:41 -08:00
+++ b/drivers/input/joystick/magellan.c	2005-03-11 12:51:41 -08:00
@@ -118,7 +118,7 @@
 static irqreturn_t magellan_interrupt(struct serio *serio,
 		unsigned char data, unsigned int flags, struct pt_regs *regs)
 {
-	struct magellan* magellan = serio->private;
+	struct magellan* magellan = serio_get_drvdata(serio);
 
 	if (data == '\r') {
 		magellan_process_packet(magellan, regs);
@@ -136,28 +136,28 @@
 
 static void magellan_disconnect(struct serio *serio)
 {
-	struct magellan* magellan = serio->private;
+	struct magellan* magellan = serio_get_drvdata(serio);
+
 	input_unregister_device(&magellan->dev);
 	serio_close(serio);
+	serio_set_drvdata(serio, NULL);
 	kfree(magellan);
 }
 
 /*
  * magellan_connect() is the routine that is called when someone adds a
- * new serio device. It looks for the Magellan, and if found, registers
- * it as an input device.
+ * new serio device that supports Magellan protocol and registers it as
+ * an input device.
  */
 
-static void magellan_connect(struct serio *serio, struct serio_driver *drv)
+static int magellan_connect(struct serio *serio, struct serio_driver *drv)
 {
 	struct magellan *magellan;
 	int i, t;
-
-	if (serio->type != (SERIO_RS232 | SERIO_MAGELLAN))
-		return;
+	int err;
 
 	if (!(magellan = kmalloc(sizeof(struct magellan), GFP_KERNEL)))
-		return;
+		return -ENOMEM;
 
 	memset(magellan, 0, sizeof(struct magellan));
 
@@ -185,28 +185,44 @@
 	magellan->dev.id.version = 0x0100;
 	magellan->dev.dev = &serio->dev;
 
-	serio->private = magellan;
+	serio_set_drvdata(serio, magellan);
 
-	if (serio_open(serio, drv)) {
+	err = serio_open(serio, drv);
+	if (err) {
+		serio_set_drvdata(serio, NULL);
 		kfree(magellan);
-		return;
+		return err;
 	}
 
 	input_register_device(&magellan->dev);
 
 	printk(KERN_INFO "input: %s on %s\n", magellan_name, serio->phys);
 
+	return 0;
 }
 
 /*
- * The serio device structure.
+ * The serio driver structure.
  */
 
+static struct serio_device_id magellan_serio_ids[] = {
+	{
+		.type	= SERIO_RS232,
+		.proto	= SERIO_MAGELLAN,
+		.id	= SERIO_ANY,
+		.extra	= SERIO_ANY,
+	},
+	{ 0 }
+};
+
+MODULE_DEVICE_TABLE(serio, magellan_serio_ids);
+
 static struct serio_driver magellan_drv = {
 	.driver		= {
 		.name	= "magellan",
 	},
 	.description	= DRIVER_DESC,
+	.id_table	= magellan_serio_ids,
 	.interrupt	= magellan_interrupt,
 	.connect	= magellan_connect,
 	.disconnect	= magellan_disconnect,
@@ -216,13 +232,13 @@
  * The functions for inserting/removing us as a module.
  */
 
-int __init magellan_init(void)
+static int __init magellan_init(void)
 {
 	serio_register_driver(&magellan_drv);
 	return 0;
 }
 
-void __exit magellan_exit(void)
+static void __exit magellan_exit(void)
 {
 	serio_unregister_driver(&magellan_drv);
 }
diff -Nru a/drivers/input/joystick/sidewinder.c b/drivers/input/joystick/sidewinder.c
--- a/drivers/input/joystick/sidewinder.c	2005-03-11 12:51:51 -08:00
+++ b/drivers/input/joystick/sidewinder.c	2005-03-11 12:51:51 -08:00
@@ -1,7 +1,5 @@
 /*
- * $Id: sidewinder.c,v 1.29 2002/01/22 20:28:51 vojtech Exp $
- *
- *  Copyright (c) 1998-2001 Vojtech Pavlik
+ *  Copyright (c) 1998-2005 Vojtech Pavlik
  */
 
 /*
@@ -36,8 +34,10 @@
 #include <linux/input.h>
 #include <linux/gameport.h>
 
+#define DRIVER_DESC	"Microsoft SideWinder joystick family driver"
+
 MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
-MODULE_DESCRIPTION("Microsoft SideWinder joystick family driver");
+MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
 
 /*
@@ -45,18 +45,18 @@
  * as well as break everything.
  */
 
-/* #define SW_DEBUG */
+#undef SW_DEBUG
+#undef SW_DEBUG_DATA
 
-#define SW_START	400	/* The time we wait for the first bit [400 us] */
-#define SW_STROBE	45	/* Max time per bit [45 us] */
-#define SW_TIMEOUT	4000	/* Wait for everything to settle [4 ms] */
+#define SW_START	600	/* The time we wait for the first bit [600 us] */
+#define SW_STROBE	60	/* Max time per bit [60 us] */
+#define SW_TIMEOUT	6	/* Wait for everything to settle [6 ms] */
 #define SW_KICK		45	/* Wait after A0 fall till kick [45 us] */
 #define SW_END		8	/* Number of bits before end of packet to kick */
 #define SW_FAIL		16	/* Number of packet read errors to fail and reinitialize */
 #define SW_BAD		2	/* Number of packet read errors to switch off 3d Pro optimization */
 #define SW_OK		64	/* Number of packet read successes to switch optimization back on */
 #define SW_LENGTH	512	/* Max number of bits in a packet */
-#define SW_REFRESH	HZ/50	/* Time to wait between updates of joystick data [20 ms] */
 
 #ifdef SW_DEBUG
 #define dbg(format, arg...) printk(KERN_DEBUG __FILE__ ": " format "\n" , ## arg)
@@ -113,7 +113,6 @@
 
 struct sw {
 	struct gameport *gameport;
-	struct timer_list timer;
 	struct input_dev dev[4];
 	char name[64];
 	char phys[4][32];
@@ -125,7 +124,6 @@
 	int ok;
 	int reads;
 	int bads;
-	int used;
 };
 
 /*
@@ -141,7 +139,7 @@
 	unsigned char pending, u, v;
 
 	i = -id;						/* Don't care about data, only want ID */
-	timeout = id ? gameport_time(gameport, SW_TIMEOUT) : 0;	/* Set up global timeout for ID packet */
+	timeout = id ? gameport_time(gameport, SW_TIMEOUT * 1000) : 0; /* Set up global timeout for ID packet */
 	kick = id ? gameport_time(gameport, SW_KICK) : 0;	/* Set up kick timeout for ID packet */
 	start = gameport_time(gameport, SW_START);
 	strobe = gameport_time(gameport, SW_STROBE);
@@ -160,7 +158,8 @@
 		v = gameport_read(gameport);
 	} while (!(~v & u & 0x10) && (bitout > 0));		/* Wait for first falling edge on clock */
 
-	if (bitout > 0) bitout = strobe;			/* Extend time if not timed out */
+	if (bitout > 0)
+		bitout = strobe;				/* Extend time if not timed out */
 
 	while ((timeout > 0 || bitout > 0) && (i < length)) {
 
@@ -194,7 +193,7 @@
 
 	local_irq_restore(flags);					/* Done - relax */
 
-#ifdef SW_DEBUG
+#ifdef SW_DEBUG_DATA
 	{
 		int j;
 		printk(KERN_DEBUG "sidewinder.c: Read %d triplets. [", i);
@@ -249,7 +248,7 @@
 	i = 0;
         do {
                 gameport_trigger(gameport);			/* Trigger */
-		t = gameport_time(gameport, SW_TIMEOUT);
+		t = gameport_time(gameport, SW_TIMEOUT * 1000);
 		while ((gameport_read(gameport) & 1) && t) t--;	/* Wait for axis to fall back to 0 */
                 udelay(seq[i]);					/* Delay magic time */
         } while (seq[++i]);
@@ -266,6 +265,7 @@
 static int sw_parity(__u64 t)
 {
 	int x = t ^ (t >> 32);
+
 	x ^= x >> 16;
 	x ^= x >> 8;
 	x ^= x >> 4;
@@ -307,7 +307,8 @@
 
 		case SW_ID_3DP:
 
-			if (sw_check(GB(0,64)) || (hat = (GB(6,1) << 3) | GB(60,3)) > 8) return -1;
+			if (sw_check(GB(0,64)) || (hat = (GB(6,1) << 3) | GB(60,3)) > 8)
+				return -1;
 
 			input_report_abs(dev, ABS_X,        (GB( 3,3) << 7) | GB(16,7));
 			input_report_abs(dev, ABS_Y,        (GB( 0,3) << 7) | GB(24,7));
@@ -331,7 +332,8 @@
 
 			for (i = 0; i < sw->number; i ++) {
 
-				if (sw_parity(GB(i*15,15))) return -1;
+				if (sw_parity(GB(i*15,15)))
+					return -1;
 
 				input_report_abs(dev + i, ABS_X, GB(i*15+3,1) - GB(i*15+2,1));
 				input_report_abs(dev + i, ABS_Y, GB(i*15+0,1) - GB(i*15+1,1));
@@ -347,7 +349,8 @@
 		case SW_ID_PP:
 		case SW_ID_FFP:
 
-			if (!sw_parity(GB(0,48)) || (hat = GB(42,4)) > 8) return -1;
+			if (!sw_parity(GB(0,48)) || (hat = GB(42,4)) > 8)
+				return -1;
 
 			input_report_abs(dev, ABS_X,        GB( 9,10));
 			input_report_abs(dev, ABS_Y,        GB(19,10));
@@ -366,7 +369,8 @@
 
 		case SW_ID_FSP:
 
-			if (!sw_parity(GB(0,43)) || (hat = GB(28,4)) > 8) return -1;
+			if (!sw_parity(GB(0,43)) || (hat = GB(28,4)) > 8)
+				return -1;
 
 			input_report_abs(dev, ABS_X,        GB( 0,10));
 			input_report_abs(dev, ABS_Y,        GB(16,10));
@@ -389,7 +393,8 @@
 
 		case SW_ID_FFW:
 
-			if (!sw_parity(GB(0,33))) return -1;
+			if (!sw_parity(GB(0,33)))
+				return -1;
 
 			input_report_abs(dev, ABS_RX,       GB( 0,10));
 			input_report_abs(dev, ABS_RUDDER,   GB(10, 6));
@@ -466,19 +471,20 @@
 		sw->length = 66;
 	}
 
-	if (sw->fail < SW_FAIL) return -1;					/* Not enough, don't reinitialize yet */
+	if (sw->fail < SW_FAIL)
+		return -1;							/* Not enough, don't reinitialize yet */
 
 	printk(KERN_WARNING "sidewinder.c: Too many bit errors on %s"
 		" - reinitializing joystick.\n", sw->gameport->phys);
 
 	if (!i && sw->type == SW_ID_3DP) {					/* 3D Pro can be in analog mode */
-		udelay(3 * SW_TIMEOUT);
+		mdelay(3 * SW_TIMEOUT);
 		sw_init_digital(sw->gameport);
 	}
 
-	udelay(SW_TIMEOUT);
+	mdelay(SW_TIMEOUT);
 	i = sw_read_packet(sw->gameport, buf, SW_LENGTH, 0);			/* Read normal data packet */
-	udelay(SW_TIMEOUT);
+	mdelay(SW_TIMEOUT);
 	sw_read_packet(sw->gameport, buf, SW_LENGTH, i);			/* Read ID packet, this initializes the stick */
 
 	sw->fail = SW_FAIL;
@@ -486,28 +492,28 @@
 	return -1;
 }
 
-static void sw_timer(unsigned long private)
+static void sw_poll(struct gameport *gameport)
 {
-	struct sw *sw = (void *) private;
+	struct sw *sw = gameport_get_drvdata(gameport);
 
 	sw->reads++;
-	if (sw_read(sw)) sw->bads++;
-	mod_timer(&sw->timer, jiffies + SW_REFRESH);
+	if (sw_read(sw))
+		sw->bads++;
 }
 
 static int sw_open(struct input_dev *dev)
 {
 	struct sw *sw = dev->private;
-	if (!sw->used++)
-		mod_timer(&sw->timer, jiffies + SW_REFRESH);
+
+	gameport_start_polling(sw->gameport);
 	return 0;
 }
 
 static void sw_close(struct input_dev *dev)
 {
 	struct sw *sw = dev->private;
-	if (!--sw->used)
-		del_timer(&sw->timer);
+
+	gameport_stop_polling(sw->gameport);
 }
 
 /*
@@ -561,7 +567,10 @@
 {
 	int i;
 	unsigned char xor = 0;
-	for (i = 1; i < len; i++) xor |= (buf[i - 1] ^ buf[i]) & 6;
+
+	for (i = 1; i < len; i++)
+		xor |= (buf[i - 1] ^ buf[i]) & 6;
+
 	return !!xor * 2 + 1;
 }
 
@@ -569,10 +578,11 @@
  * sw_connect() probes for SideWinder type joysticks.
  */
 
-static void sw_connect(struct gameport *gameport, struct gameport_dev *dev)
+static int sw_connect(struct gameport *gameport, struct gameport_driver *drv)
 {
 	struct sw *sw;
 	int i, j, k, l;
+	int err;
 	unsigned char *buf = NULL;	/* [SW_LENGTH] */
 	unsigned char *idbuf = NULL;	/* [SW_LENGTH] */
 	unsigned char m = 1;
@@ -580,50 +590,55 @@
 
 	comment[0] = 0;
 
-	if (!(sw = kmalloc(sizeof(struct sw), GFP_KERNEL))) return;
-	memset(sw, 0, sizeof(struct sw));
-
+	sw = kcalloc(1, sizeof(struct sw), GFP_KERNEL);
 	buf = kmalloc(SW_LENGTH, GFP_KERNEL);
 	idbuf = kmalloc(SW_LENGTH, GFP_KERNEL);
-	if (!buf || !idbuf)
+	if (!sw || !buf || !idbuf) {
+		err = -ENOMEM;
 		goto fail1;
-
-	gameport->private = sw;
+	}
 
 	sw->gameport = gameport;
-	init_timer(&sw->timer);
-	sw->timer.data = (long) sw;
-	sw->timer.function = sw_timer;
 
-	if (gameport_open(gameport, dev, GAMEPORT_MODE_RAW))
+	gameport_set_drvdata(gameport, sw);
+
+	err = gameport_open(gameport, drv, GAMEPORT_MODE_RAW);
+	if (err)
 		goto fail1;
 
 	dbg("Init 0: Opened %s, io %#x, speed %d",
 		gameport->phys, gameport->io, gameport->speed);
 
 	i = sw_read_packet(gameport, buf, SW_LENGTH, 0);		/* Read normal packet */
-	udelay(SW_TIMEOUT);
+	msleep(SW_TIMEOUT);
 	dbg("Init 1: Mode %d. Length %d.", m , i);
 
 	if (!i) {							/* No data. 3d Pro analog mode? */
 		sw_init_digital(gameport);				/* Switch to digital */
-		udelay(SW_TIMEOUT);
+		msleep(SW_TIMEOUT);
 		i = sw_read_packet(gameport, buf, SW_LENGTH, 0);	/* Retry reading packet */
-		udelay(SW_TIMEOUT);
+		msleep(SW_TIMEOUT);
 		dbg("Init 1b: Length %d.", i);
-		if (!i) goto fail2;					/* No data -> FAIL */
+		if (!i) {						/* No data -> FAIL */
+			err = -ENODEV;
+			goto fail2;
+		}
 	}
 
 	j = sw_read_packet(gameport, idbuf, SW_LENGTH, i);		/* Read ID. This initializes the stick */
 	m |= sw_guess_mode(idbuf, j);					/* ID packet should carry mode info [3DP] */
-	dbg("Init 2: Mode %d. ID Length %d.", m , j);
+	dbg("Init 2: Mode %d. ID Length %d.", m, j);
 
-	if (!j) {							/* Read ID failed. Happens in 1-bit mode on PP */
-		udelay(SW_TIMEOUT);
+	if (j <= 0) {							/* Read ID failed. Happens in 1-bit mode on PP */
+		msleep(SW_TIMEOUT);
 		i = sw_read_packet(gameport, buf, SW_LENGTH, 0);	/* Retry reading packet */
+		m |= sw_guess_mode(buf, i);
 		dbg("Init 2b: Mode %d. Length %d.", m, i);
-		if (!i) goto fail2;
-		udelay(SW_TIMEOUT);
+		if (!i) {
+			err = -ENODEV;
+			goto fail2;
+		}
+		msleep(SW_TIMEOUT);
 		j = sw_read_packet(gameport, idbuf, SW_LENGTH, i);	/* Retry reading ID */
 		dbg("Init 2c: ID Length %d.", j);
 	}
@@ -634,7 +649,7 @@
 
 	do {
 		k--;
-		udelay(SW_TIMEOUT);
+		msleep(SW_TIMEOUT);
 		i = sw_read_packet(gameport, buf, SW_LENGTH, 0);	/* Read data packet */
 		dbg("Init 3: Mode %d. Length %d. Last %d. Tries %d.", m, i, l, k);
 
@@ -686,13 +701,14 @@
 			}
 		}
 
-	} while (k && (sw->type == -1));
+	} while (k && sw->type == -1);
 
 	if (sw->type == -1) {
 		printk(KERN_WARNING "sidewinder.c: unknown joystick device detected "
 			"on %s, contact <vojtech@ucw.cz>\n", gameport->phys);
 		sw_print_packet("ID", j * 3, idbuf, 3);
 		sw_print_packet("Data", i * m, buf, m);
+		err = -ENODEV;
 		goto fail2;
 	}
 
@@ -701,6 +717,9 @@
 	sw_print_packet("Data", i * m, buf, m);
 #endif
 
+	gameport_set_poll_handler(gameport, sw_poll);
+	gameport_set_poll_interval(gameport, 20);
+
 	k = i;
 	l = j;
 
@@ -742,38 +761,46 @@
 			sw->name, comment, gameport->phys, m, l, k);
 	}
 
-	return;
+	return 0;
+
 fail2:	gameport_close(gameport);
-fail1:	kfree(sw);
+fail1:	gameport_set_drvdata(gameport, NULL);
+	kfree(sw);
 	kfree(buf);
 	kfree(idbuf);
+	return err;
 }
 
 static void sw_disconnect(struct gameport *gameport)
 {
+	struct sw *sw = gameport_get_drvdata(gameport);
 	int i;
 
-	struct sw *sw = gameport->private;
 	for (i = 0; i < sw->number; i++)
 		input_unregister_device(sw->dev + i);
 	gameport_close(gameport);
+	gameport_set_drvdata(gameport, NULL);
 	kfree(sw);
 }
 
-static struct gameport_dev sw_dev = {
-	.connect =	sw_connect,
-	.disconnect =	sw_disconnect,
+static struct gameport_driver sw_drv = {
+	.driver		= {
+		.name	= "sidewinder",
+	},
+	.description	= DRIVER_DESC,
+	.connect	= sw_connect,
+	.disconnect	= sw_disconnect,
 };
 
-int __init sw_init(void)
+static int __init sw_init(void)
 {
-	gameport_register_device(&sw_dev);
+	gameport_register_driver(&sw_drv);
 	return 0;
 }
 
-void __exit sw_exit(void)
+static void __exit sw_exit(void)
 {
-	gameport_unregister_device(&sw_dev);
+	gameport_unregister_driver(&sw_drv);
 }
 
 module_init(sw_init);
diff -Nru a/drivers/input/joystick/spaceball.c b/drivers/input/joystick/spaceball.c
--- a/drivers/input/joystick/spaceball.c	2005-03-11 12:51:41 -08:00
+++ b/drivers/input/joystick/spaceball.c	2005-03-11 12:51:41 -08:00
@@ -154,7 +154,7 @@
 static irqreturn_t spaceball_interrupt(struct serio *serio,
 		unsigned char data, unsigned int flags, struct pt_regs *regs)
 {
-	struct spaceball *spaceball = serio->private;
+	struct spaceball *spaceball = serio_get_drvdata(serio);
 
 	switch (data) {
 		case 0xd:
@@ -191,31 +191,32 @@
 
 static void spaceball_disconnect(struct serio *serio)
 {
-	struct spaceball* spaceball = serio->private;
+	struct spaceball* spaceball = serio_get_drvdata(serio);
+
 	input_unregister_device(&spaceball->dev);
 	serio_close(serio);
+	serio_set_drvdata(serio, NULL);
 	kfree(spaceball);
 }
 
 /*
  * spaceball_connect() is the routine that is called when someone adds a
- * new serio device. It looks for the Magellan, and if found, registers
- * it as an input device.
+ * new serio device that supports Spaceball protocol and registers it as
+ * an input device.
  */
 
-static void spaceball_connect(struct serio *serio, struct serio_driver *drv)
+static int spaceball_connect(struct serio *serio, struct serio_driver *drv)
 {
 	struct spaceball *spaceball;
 	int i, t, id;
+	int err;
 
-	if ((serio->type & ~SERIO_ID) != (SERIO_RS232 | SERIO_SPACEBALL))
-		return;
-
-	if ((id = (serio->type & SERIO_ID) >> 8) > SPACEBALL_MAX_ID)
-		return;
+	if ((id = serio->id.id) > SPACEBALL_MAX_ID)
+		return -ENODEV;
 
 	if (!(spaceball = kmalloc(sizeof(struct spaceball), GFP_KERNEL)))
-		return;
+		return - ENOMEM;
+
 	memset(spaceball, 0, sizeof(struct spaceball));
 
 	spaceball->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
@@ -255,28 +256,45 @@
 	spaceball->dev.id.version = 0x0100;
 	spaceball->dev.dev = &serio->dev;
 
-	serio->private = spaceball;
+	serio_set_drvdata(serio, spaceball);
 
-	if (serio_open(serio, drv)) {
+	err = serio_open(serio, drv);
+	if (err) {
+		serio_set_drvdata(serio, NULL);
 		kfree(spaceball);
-		return;
+		return err;
 	}
 
 	input_register_device(&spaceball->dev);
 
 	printk(KERN_INFO "input: %s on serio%s\n",
 		spaceball_names[id], serio->phys);
+
+	return 0;
 }
 
 /*
- * The serio device structure.
+ * The serio driver structure.
  */
 
+static struct serio_device_id spaceball_serio_ids[] = {
+	{
+		.type	= SERIO_RS232,
+		.proto	= SERIO_SPACEBALL,
+		.id	= SERIO_ANY,
+		.extra	= SERIO_ANY,
+	},
+	{ 0 }
+};
+
+MODULE_DEVICE_TABLE(serio, spaceball_serio_ids);
+
 static struct serio_driver spaceball_drv = {
 	.driver		= {
 		.name	= "spaceball",
 	},
 	.description	= DRIVER_DESC,
+	.id_table	= spaceball_serio_ids,
 	.interrupt	= spaceball_interrupt,
 	.connect	= spaceball_connect,
 	.disconnect	= spaceball_disconnect,
@@ -286,13 +304,13 @@
  * The functions for inserting/removing us as a module.
  */
 
-int __init spaceball_init(void)
+static int __init spaceball_init(void)
 {
 	serio_register_driver(&spaceball_drv);
 	return 0;
 }
 
-void __exit spaceball_exit(void)
+static void __exit spaceball_exit(void)
 {
 	serio_unregister_driver(&spaceball_drv);
 }
diff -Nru a/drivers/input/joystick/spaceorb.c b/drivers/input/joystick/spaceorb.c
--- a/drivers/input/joystick/spaceorb.c	2005-03-11 12:51:43 -08:00
+++ b/drivers/input/joystick/spaceorb.c	2005-03-11 12:51:43 -08:00
@@ -135,7 +135,7 @@
 static irqreturn_t spaceorb_interrupt(struct serio *serio,
 		unsigned char data, unsigned int flags, struct pt_regs *regs)
 {
-	struct spaceorb* spaceorb = serio->private;
+	struct spaceorb* spaceorb = serio_get_drvdata(serio);
 
 	if (~data & 0x80) {
 		if (spaceorb->idx) spaceorb_process_packet(spaceorb, regs);
@@ -152,28 +152,29 @@
 
 static void spaceorb_disconnect(struct serio *serio)
 {
-	struct spaceorb* spaceorb = serio->private;
+	struct spaceorb* spaceorb = serio_get_drvdata(serio);
+
 	input_unregister_device(&spaceorb->dev);
 	serio_close(serio);
+	serio_set_drvdata(serio, NULL);
 	kfree(spaceorb);
 }
 
 /*
  * spaceorb_connect() is the routine that is called when someone adds a
- * new serio device. It looks for the SpaceOrb/Avenger, and if found, registers
+ * new serio device that supports SpaceOrb/Avenger protocol and registers
  * it as an input device.
  */
 
-static void spaceorb_connect(struct serio *serio, struct serio_driver *drv)
+static int spaceorb_connect(struct serio *serio, struct serio_driver *drv)
 {
 	struct spaceorb *spaceorb;
 	int i, t;
-
-	if (serio->type != (SERIO_RS232 | SERIO_SPACEORB))
-		return;
+	int err;
 
 	if (!(spaceorb = kmalloc(sizeof(struct spaceorb), GFP_KERNEL)))
-		return;
+		return -ENOMEM;
+
 	memset(spaceorb, 0, sizeof(struct spaceorb));
 
 	spaceorb->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
@@ -202,25 +203,42 @@
 	spaceorb->dev.id.version = 0x0100;
 	spaceorb->dev.dev = &serio->dev;
 
-	serio->private = spaceorb;
+	serio_set_drvdata(serio, spaceorb);
 
-	if (serio_open(serio, drv)) {
+	err = serio_open(serio, drv);
+	if (err) {
+		serio_set_drvdata(serio, NULL);
 		kfree(spaceorb);
-		return;
+		return err;
 	}
 
 	input_register_device(&spaceorb->dev);
+
+	return 0;
 }
 
 /*
- * The serio device structure.
+ * The serio driver structure.
  */
 
+static struct serio_device_id spaceorb_serio_ids[] = {
+	{
+		.type	= SERIO_RS232,
+		.proto	= SERIO_SPACEORB,
+		.id	= SERIO_ANY,
+		.extra	= SERIO_ANY,
+	},
+	{ 0 }
+};
+
+MODULE_DEVICE_TABLE(serio, spaceorb_serio_ids);
+
 static struct serio_driver spaceorb_drv = {
 	.driver		= {
 		.name	= "spaceorb",
 	},
 	.description	= DRIVER_DESC,
+	.id_table	= spaceorb_serio_ids,
 	.interrupt	= spaceorb_interrupt,
 	.connect	= spaceorb_connect,
 	.disconnect	= spaceorb_disconnect,
@@ -230,13 +248,13 @@
  * The functions for inserting/removing us as a module.
  */
 
-int __init spaceorb_init(void)
+static int __init spaceorb_init(void)
 {
 	serio_register_driver(&spaceorb_drv);
 	return 0;
 }
 
-void __exit spaceorb_exit(void)
+static void __exit spaceorb_exit(void)
 {
 	serio_unregister_driver(&spaceorb_drv);
 }
diff -Nru a/drivers/input/joystick/stinger.c b/drivers/input/joystick/stinger.c
--- a/drivers/input/joystick/stinger.c	2005-03-11 12:51:40 -08:00
+++ b/drivers/input/joystick/stinger.c	2005-03-11 12:51:40 -08:00
@@ -103,7 +103,7 @@
 static irqreturn_t stinger_interrupt(struct serio *serio,
 	unsigned char data, unsigned int flags, struct pt_regs *regs)
 {
-	struct stinger* stinger = serio->private;
+	struct stinger *stinger = serio_get_drvdata(serio);
 
 	/* All Stinger packets are 4 bytes */
 
@@ -124,28 +124,28 @@
 
 static void stinger_disconnect(struct serio *serio)
 {
-	struct stinger* stinger = serio->private;
+	struct stinger *stinger = serio_get_drvdata(serio);
+
 	input_unregister_device(&stinger->dev);
 	serio_close(serio);
+	serio_set_drvdata(serio, NULL);
 	kfree(stinger);
 }
 
 /*
  * stinger_connect() is the routine that is called when someone adds a
- * new serio device. It looks for the Stinger, and if found, registers
- * it as an input device.
+ * new serio device that supports Stinger protocol and registers it as
+ * an input device.
  */
 
-static void stinger_connect(struct serio *serio, struct serio_driver *drv)
+static int stinger_connect(struct serio *serio, struct serio_driver *drv)
 {
 	struct stinger *stinger;
 	int i;
-
-	if (serio->type != (SERIO_RS232 | SERIO_STINGER))
-		return;
+	int err;
 
 	if (!(stinger = kmalloc(sizeof(struct stinger), GFP_KERNEL)))
-		return;
+		return -ENOMEM;
 
 	memset(stinger, 0, sizeof(struct stinger));
 
@@ -173,28 +173,45 @@
 	}
 
 	stinger->dev.private = stinger;
-	serio->private = stinger;
 
-	if (serio_open(serio, drv)) {
+	serio_set_drvdata(serio, stinger);
+
+	err = serio_open(serio, drv);
+	if (err) {
+		serio_set_drvdata(serio, NULL);
 		kfree(stinger);
-		return;
+		return err;
 	}
 
 	input_register_device(&stinger->dev);
 
 	printk(KERN_INFO "input: %s on %s\n",  stinger_name, serio->phys);
 
+	return 0;
 }
 
 /*
- * The serio device structure.
+ * The serio driver structure.
  */
 
+static struct serio_device_id stinger_serio_ids[] = {
+	{
+		.type	= SERIO_RS232,
+		.proto	= SERIO_STINGER,
+		.id	= SERIO_ANY,
+		.extra	= SERIO_ANY,
+	},
+	{ 0 }
+};
+
+MODULE_DEVICE_TABLE(serio, stinger_serio_ids);
+
 static struct serio_driver stinger_drv = {
 	.driver		= {
 		.name	= "stinger",
 	},
 	.description	= DRIVER_DESC,
+	.id_table	= stinger_serio_ids,
 	.interrupt	= stinger_interrupt,
 	.connect	= stinger_connect,
 	.disconnect	= stinger_disconnect,
@@ -204,13 +221,13 @@
  * The functions for inserting/removing us as a module.
  */
 
-int __init stinger_init(void)
+static int __init stinger_init(void)
 {
 	serio_register_driver(&stinger_drv);
 	return 0;
 }
 
-void __exit stinger_exit(void)
+static void __exit stinger_exit(void)
 {
 	serio_unregister_driver(&stinger_drv);
 }
diff -Nru a/drivers/input/joystick/tmdc.c b/drivers/input/joystick/tmdc.c
--- a/drivers/input/joystick/tmdc.c	2005-03-11 12:51:42 -08:00
+++ b/drivers/input/joystick/tmdc.c	2005-03-11 12:51:42 -08:00
@@ -39,14 +39,15 @@
 #include <linux/gameport.h>
 #include <linux/input.h>
 
+#define DRIVER_DESC	"ThrustMaster DirectConnect joystick driver"
+
 MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
-MODULE_DESCRIPTION("ThrustMaster DirectConnect joystick driver");
+MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
 
-#define TMDC_MAX_START		400	/* 400 us */
-#define TMDC_MAX_STROBE		45	/* 45 us */
+#define TMDC_MAX_START		600	/* 600 us */
+#define TMDC_MAX_STROBE		60	/* 60 us */
 #define TMDC_MAX_LENGTH		13
-#define TMDC_REFRESH_TIME	HZ/50	/* 20 ms */
 
 #define TMDC_MODE_M3DI		1
 #define TMDC_MODE_3DRP		3
@@ -92,7 +93,6 @@
 
 struct tmdc {
 	struct gameport *gameport;
-	struct timer_list timer;
 	struct input_dev dev[2];
 	char name[2][64];
 	char phys[2][32];
@@ -102,7 +102,6 @@
 	unsigned char absc[2];
 	unsigned char btnc[2][4];
 	unsigned char btno[2][4];
-	int used;
 	int reads;
 	int bads;
 	unsigned char exists;
@@ -158,13 +157,13 @@
 }
 
 /*
- * tmdc_read() reads and analyzes ThrustMaster joystick data.
+ * tmdc_poll() reads and analyzes ThrustMaster joystick data.
  */
 
-static void tmdc_timer(unsigned long private)
+static void tmdc_poll(struct gameport *gameport)
 {
 	unsigned char data[2][TMDC_MAX_LENGTH];
-	struct tmdc *tmdc = (void *) private;
+	struct tmdc *tmdc = gameport_get_drvdata(gameport);
 	struct input_dev *dev;
 	unsigned char r, bad = 0;
 	int i, j, k, l;
@@ -219,32 +218,30 @@
 	}
 
 	tmdc->bads += bad;
-
-	mod_timer(&tmdc->timer, jiffies + TMDC_REFRESH_TIME);
 }
 
 static int tmdc_open(struct input_dev *dev)
 {
 	struct tmdc *tmdc = dev->private;
-	if (!tmdc->used++)
-		mod_timer(&tmdc->timer, jiffies + TMDC_REFRESH_TIME);
+
+	gameport_start_polling(tmdc->gameport);
 	return 0;
 }
 
 static void tmdc_close(struct input_dev *dev)
 {
 	struct tmdc *tmdc = dev->private;
-	if (!--tmdc->used)
-		del_timer(&tmdc->timer);
+
+	gameport_stop_polling(tmdc->gameport);
 }
 
 /*
  * tmdc_probe() probes for ThrustMaster type joysticks.
  */
 
-static void tmdc_connect(struct gameport *gameport, struct gameport_dev *dev)
+static int tmdc_connect(struct gameport *gameport, struct gameport_driver *drv)
 {
-	struct models {
+	static struct models {
 		unsigned char id;
 		char *name;
 		char abs;
@@ -263,23 +260,26 @@
 	unsigned char data[2][TMDC_MAX_LENGTH];
 	struct tmdc *tmdc;
 	int i, j, k, l, m;
+	int err;
 
-	if (!(tmdc = kmalloc(sizeof(struct tmdc), GFP_KERNEL)))
-		return;
-	memset(tmdc, 0, sizeof(struct tmdc));
-
-	gameport->private = tmdc;
+	if (!(tmdc = kcalloc(1, sizeof(struct tmdc), GFP_KERNEL)))
+		return -ENOMEM;
 
 	tmdc->gameport = gameport;
-	init_timer(&tmdc->timer);
-	tmdc->timer.data = (long) tmdc;
-	tmdc->timer.function = tmdc_timer;
 
-	if (gameport_open(gameport, dev, GAMEPORT_MODE_RAW))
+	gameport_set_drvdata(gameport, tmdc);
+
+	err = gameport_open(gameport, drv, GAMEPORT_MODE_RAW);
+	if (err)
 		goto fail1;
 
-	if (!(tmdc->exists = tmdc_read_packet(gameport, data)))
+	if (!(tmdc->exists = tmdc_read_packet(gameport, data))) {
+		err = -ENODEV;
 		goto fail2;
+	}
+
+	gameport_set_poll_handler(gameport, tmdc_poll);
+	gameport_set_poll_interval(gameport, 20);
 
 	for (j = 0; j < 2; j++)
 		if (tmdc->exists & (1 << j)) {
@@ -321,20 +321,13 @@
 
 			tmdc->dev[j].evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
 
-			for (i = 0; i < models[m].abs && i < TMDC_ABS; i++) {
-				if (tmdc->abs[j][i] < 0) continue;
-				set_bit(tmdc->abs[j][i], tmdc->dev[j].absbit);
-				tmdc->dev[j].absmin[tmdc->abs[j][i]] = 8;
-				tmdc->dev[j].absmax[tmdc->abs[j][i]] = 248;
-				tmdc->dev[j].absfuzz[tmdc->abs[j][i]] = 2;
-				tmdc->dev[j].absflat[tmdc->abs[j][i]] = 4;
-			}
+			for (i = 0; i < models[m].abs && i < TMDC_ABS; i++)
+				if (tmdc->abs[j][i] >= 0)
+					input_set_abs_params(&tmdc->dev[j], tmdc->abs[j][i], 8, 248, 2, 4);
+
+			for (i = 0; i < models[m].hats && i < TMDC_ABS_HAT; i++)
+				input_set_abs_params(&tmdc->dev[j], tmdc_abs_hat[i], -1, 1, 0, 0);
 
-			for (i = 0; i < models[m].hats && i < TMDC_ABS_HAT; i++) {
-				set_bit(tmdc_abs_hat[i], tmdc->dev[j].absbit);
-				tmdc->dev[j].absmin[tmdc_abs_hat[i]] = -1;
-				tmdc->dev[j].absmax[tmdc_abs_hat[i]] = 1;
-			}
 
 			for (k = l = 0; k < 4; k++) {
 				for (i = 0; i < models[m].btnc[k] && i < TMDC_BTN; i++)
@@ -346,36 +339,45 @@
 			printk(KERN_INFO "input: %s on %s\n", tmdc->name[j], gameport->phys);
 		}
 
-	return;
+	return 0;
+
 fail2:	gameport_close(gameport);
-fail1:	kfree(tmdc);
+fail1:	gameport_set_drvdata(gameport, NULL);
+	kfree(tmdc);
+	return err;
 }
 
 static void tmdc_disconnect(struct gameport *gameport)
 {
-	struct tmdc *tmdc = gameport->private;
+	struct tmdc *tmdc = gameport_get_drvdata(gameport);
 	int i;
+
 	for (i = 0; i < 2; i++)
 		if (tmdc->exists & (1 << i))
 			input_unregister_device(tmdc->dev + i);
 	gameport_close(gameport);
+	gameport_set_drvdata(gameport, NULL);
 	kfree(tmdc);
 }
 
-static struct gameport_dev tmdc_dev = {
-	.connect =	tmdc_connect,
-	.disconnect =	tmdc_disconnect,
+static struct gameport_driver tmdc_drv = {
+	.driver		= {
+		.name	= "tmdc",
+	},
+	.description	= DRIVER_DESC,
+	.connect	= tmdc_connect,
+	.disconnect	= tmdc_disconnect,
 };
 
-int __init tmdc_init(void)
+static int __init tmdc_init(void)
 {
-	gameport_register_device(&tmdc_dev);
+	gameport_register_driver(&tmdc_drv);
 	return 0;
 }
 
-void __exit tmdc_exit(void)
+static void __exit tmdc_exit(void)
 {
-	gameport_unregister_device(&tmdc_dev);
+	gameport_unregister_driver(&tmdc_drv);
 }
 
 module_init(tmdc_init);
diff -Nru a/drivers/input/joystick/turbografx.c b/drivers/input/joystick/turbografx.c
--- a/drivers/input/joystick/turbografx.c	2005-03-11 12:51:48 -08:00
+++ b/drivers/input/joystick/turbografx.c	2005-03-11 12:51:48 -08:00
@@ -77,7 +77,7 @@
 static int tgfx_buttons[] = { BTN_TRIGGER, BTN_THUMB, BTN_THUMB2, BTN_TOP, BTN_TOP2 };
 static char *tgfx_name = "TurboGraFX Multisystem joystick";
 
-struct tgfx {
+static struct tgfx {
 	struct pardevice *pd;
 	struct timer_list timer;
 	struct input_dev dev[7];
@@ -229,7 +229,7 @@
 	return tgfx;
 }
 
-int __init tgfx_init(void)
+static int __init tgfx_init(void)
 {
 	tgfx_base[0] = tgfx_probe(tgfx, tgfx_nargs);
 	tgfx_base[1] = tgfx_probe(tgfx_2, tgfx_nargs_2);
@@ -241,7 +241,7 @@
 	return -ENODEV;
 }
 
-void __exit tgfx_exit(void)
+static void __exit tgfx_exit(void)
 {
 	int i, j;
 
diff -Nru a/drivers/input/joystick/twidjoy.c b/drivers/input/joystick/twidjoy.c
--- a/drivers/input/joystick/twidjoy.c	2005-03-11 12:51:41 -08:00
+++ b/drivers/input/joystick/twidjoy.c	2005-03-11 12:51:41 -08:00
@@ -58,7 +58,9 @@
 #include <linux/serio.h>
 #include <linux/init.h>
 
-MODULE_DESCRIPTION("Handykey Twiddler keyboard as a joystick driver");
+#define DRIVER_DESC	"Handykey Twiddler keyboard as a joystick driver"
+
+MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
 
 /*
@@ -147,7 +149,7 @@
 
 static irqreturn_t twidjoy_interrupt(struct serio *serio, unsigned char data, unsigned int flags, struct pt_regs *regs)
 {
-	struct twidjoy *twidjoy = serio->private;
+	struct twidjoy *twidjoy = serio_get_drvdata(serio);
 
 	/* All Twiddler packets are 5 bytes. The fact that the first byte
 	 * has a MSB of 0 and all other bytes have a MSB of 1 can be used
@@ -175,9 +177,11 @@
 
 static void twidjoy_disconnect(struct serio *serio)
 {
-	struct twidjoy *twidjoy = serio->private;
+	struct twidjoy *twidjoy = serio_get_drvdata(serio);
+
 	input_unregister_device(&twidjoy->dev);
 	serio_close(serio);
+	serio_set_drvdata(serio, NULL);
 	kfree(twidjoy);
 }
 
@@ -187,17 +191,15 @@
  * it as an input device.
  */
 
-static void twidjoy_connect(struct serio *serio, struct serio_driver *drv)
+static int twidjoy_connect(struct serio *serio, struct serio_driver *drv)
 {
 	struct twidjoy_button_spec *bp;
 	struct twidjoy *twidjoy;
 	int i;
-
-	if (serio->type != (SERIO_RS232 | SERIO_TWIDJOY))
-		return;
+	int err;
 
 	if (!(twidjoy = kmalloc(sizeof(struct twidjoy), GFP_KERNEL)))
-		return;
+		return -ENOMEM;
 
 	memset(twidjoy, 0, sizeof(struct twidjoy));
 
@@ -231,27 +233,45 @@
 	}
 
 	twidjoy->dev.private = twidjoy;
-	serio->private = twidjoy;
 
-	if (serio_open(serio, drv)) {
+	serio_set_drvdata(serio, twidjoy);
+
+	err = serio_open(serio, drv);
+	if (err) {
+		serio_set_drvdata(serio, NULL);
 		kfree(twidjoy);
-		return;
+		return err;
 	}
 
 	input_register_device(&twidjoy->dev);
 
 	printk(KERN_INFO "input: %s on %s\n", twidjoy_name, serio->phys);
+
+	return 0;
 }
 
 /*
- * The serio device structure.
+ * The serio driver structure.
  */
 
+static struct serio_device_id twidjoy_serio_ids[] = {
+	{
+		.type	= SERIO_RS232,
+		.proto	= SERIO_TWIDJOY,
+		.id	= SERIO_ANY,
+		.extra	= SERIO_ANY,
+	},
+	{ 0 }
+};
+
+MODULE_DEVICE_TABLE(serio, twidjoy_serio_ids);
+
 static struct serio_driver twidjoy_drv = {
 	.driver		= {
 		.name	= "twidjoy",
 	},
 	.description	= DRIVER_DESC,
+	.id_table	= twidjoy_serio_ids,
 	.interrupt	= twidjoy_interrupt,
 	.connect	= twidjoy_connect,
 	.disconnect	= twidjoy_disconnect,
diff -Nru a/drivers/input/joystick/warrior.c b/drivers/input/joystick/warrior.c
--- a/drivers/input/joystick/warrior.c	2005-03-11 12:51:47 -08:00
+++ b/drivers/input/joystick/warrior.c	2005-03-11 12:51:47 -08:00
@@ -104,7 +104,7 @@
 static irqreturn_t warrior_interrupt(struct serio *serio,
 		unsigned char data, unsigned int flags, struct pt_regs *regs)
 {
-	struct warrior* warrior = serio->private;
+	struct warrior *warrior = serio_get_drvdata(serio);
 
 	if (data & 0x80) {
 		if (warrior->idx) warrior_process_packet(warrior, regs);
@@ -129,9 +129,11 @@
 
 static void warrior_disconnect(struct serio *serio)
 {
-	struct warrior* warrior = serio->private;
+	struct warrior *warrior = serio_get_drvdata(serio);
+
 	input_unregister_device(&warrior->dev);
 	serio_close(serio);
+	serio_set_drvdata(serio, NULL);
 	kfree(warrior);
 }
 
@@ -141,16 +143,14 @@
  * it as an input device.
  */
 
-static void warrior_connect(struct serio *serio, struct serio_driver *drv)
+static int warrior_connect(struct serio *serio, struct serio_driver *drv)
 {
 	struct warrior *warrior;
 	int i;
-
-	if (serio->type != (SERIO_RS232 | SERIO_WARRIOR))
-		return;
+	int err;
 
 	if (!(warrior = kmalloc(sizeof(struct warrior), GFP_KERNEL)))
-		return;
+		return -ENOMEM;
 
 	memset(warrior, 0, sizeof(struct warrior));
 
@@ -186,27 +186,44 @@
 
 	warrior->dev.private = warrior;
 
-	serio->private = warrior;
+	serio_set_drvdata(serio, warrior);
 
-	if (serio_open(serio, drv)) {
+	err = serio_open(serio, drv);
+	if (err) {
+		serio_set_drvdata(serio, NULL);
 		kfree(warrior);
-		return;
+		return err;
 	}
 
 	input_register_device(&warrior->dev);
 
 	printk(KERN_INFO "input: Logitech WingMan Warrior on %s\n", serio->phys);
+
+	return 0;
 }
 
 /*
- * The serio device structure.
+ * The serio driver structure.
  */
 
+static struct serio_device_id warrior_serio_ids[] = {
+	{
+		.type	= SERIO_RS232,
+		.proto	= SERIO_WARRIOR,
+		.id	= SERIO_ANY,
+		.extra	= SERIO_ANY,
+	},
+	{ 0 }
+};
+
+MODULE_DEVICE_TABLE(serio, warrior_serio_ids);
+
 static struct serio_driver warrior_drv = {
 	.driver		= {
 		.name	= "warrior",
 	},
 	.description	= DRIVER_DESC,
+	.id_table	= warrior_serio_ids,
 	.interrupt	= warrior_interrupt,
 	.connect	= warrior_connect,
 	.disconnect	= warrior_disconnect,
@@ -216,13 +233,13 @@
  * The functions for inserting/removing us as a module.
  */
 
-int __init warrior_init(void)
+static int __init warrior_init(void)
 {
 	serio_register_driver(&warrior_drv);
 	return 0;
 }
 
-void __exit warrior_exit(void)
+static void __exit warrior_exit(void)
 {
 	serio_unregister_driver(&warrior_drv);
 }
diff -Nru a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig
--- a/drivers/input/keyboard/Kconfig	2005-03-11 12:51:51 -08:00
+++ b/drivers/input/keyboard/Kconfig	2005-03-11 12:51:51 -08:00
@@ -1,20 +1,20 @@
 #
 # Input core configuration
 #
-config INPUT_KEYBOARD
+menuconfig INPUT_KEYBOARD
 	bool "Keyboards" if EMBEDDED || !X86
 	default y
-	depends on INPUT
 	help
 	  Say Y here, and a list of supported keyboards will be displayed.
 	  This option doesn't affect the kernel.
 
 	  If unsure, say Y.
 
+if INPUT_KEYBOARD
+
 config KEYBOARD_ATKBD
-	tristate "AT keyboard support" if !PC
+	tristate "AT keyboard" if !PC
 	default y
-	depends on INPUT && INPUT_KEYBOARD
 	select SERIO
 	select SERIO_LIBPS2
 	select SERIO_I8042 if PC
@@ -30,9 +30,46 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called atkbd.
 
+config KEYBOARD_ATKBD_HP_KEYCODES
+	bool "Use HP keyboard scancodes"
+	depends on PARISC && KEYBOARD_ATKBD
+	default y
+	help
+	  Say Y here if you have a PA-RISC machine and want to use an AT or
+	  PS/2 keyboard, and your keyboard uses keycodes that are specific to
+	  PA-RISC keyboards.
+
+	  Say N if you use a standard keyboard.
+
+config KEYBOARD_ATKBD_RDI_KEYCODES
+	bool "Use PrecisionBook keyboard scancodes"
+	depends on KEYBOARD_ATKBD_HP_KEYCODES
+	default n
+	help
+	  If you have an RDI PrecisionBook, say Y here if you want to use its
+	  built-in keyboard (as opposed to an external keyboard).
+
+	  The PrecisionBook has five keys that conflict with those used by most
+	  AT and PS/2 keyboards. These are as follows:
+
+	    PrecisionBook    Standard AT or PS/2
+
+	    F1               F12
+	    Left Ctrl        Left Alt
+	    Caps Lock        Left Ctrl
+	    Right Ctrl       Caps Lock
+	    Left             102nd key (the key to the right of Left Shift)
+
+	  If you say N here, and use the PrecisionBook keyboard, then each key
+	  in the left-hand column will be interpreted as the corresponding key
+	  in the right-hand column.
+
+	  If you say Y here, and use an external keyboard, then each key in the
+	  right-hand column will be interpreted as the key shown in the
+	  left-hand column.
+
 config KEYBOARD_SUNKBD
-	tristate "Sun Type 4 and Type 5 keyboard support"
-	depends on INPUT && INPUT_KEYBOARD
+	tristate "Sun Type 4 and Type 5 keyboard"
 	select SERIO
 	help
 	  Say Y here if you want to use a Sun Type 4 or Type 5 keyboard,
@@ -43,8 +80,7 @@
 	  module will be called sunkbd.
 
 config KEYBOARD_LKKBD
-	tristate "DECstation/VAXstation LK201/LK401 keyboard support"
-	depends on INPUT && INPUT_KEYBOARD
+	tristate "DECstation/VAXstation LK201/LK401 keyboard"
 	select SERIO
 	help
 	  Say Y here if you want to use a LK201 or LK401 style serial
@@ -55,9 +91,17 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called lkkbd.
 
+config KEYBOARD_LOCOMO
+	tristate "LoCoMo Keyboard Support"
+	depends on SHARP_LOCOMO
+	help
+	  Say Y here if you are running Linux on a Sharp Zaurus Collie or Poodle based PDA
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called locomokbd.
+
 config KEYBOARD_XTKBD
-	tristate "XT Keyboard support"
-	depends on INPUT && INPUT_KEYBOARD
+	tristate "XT keyboard"
 	select SERIO
 	help
 	  Say Y here if you want to use the old IBM PC/XT keyboard (or
@@ -70,7 +114,6 @@
 
 config KEYBOARD_NEWTON
 	tristate "Newton keyboard"
-	depends on INPUT && INPUT_KEYBOARD
 	select SERIO
 	help
 	  Say Y here if you have a Newton keyboard on a serial port.
@@ -78,9 +121,20 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called newtonkbd.
 
+config KEYBOARD_CORGI
+	tristate "Corgi keyboard"
+	depends on PXA_SHARPSL
+	default y	
+	help
+	  Say Y here to enable the keyboard on the Sharp Zaurus SL-C7xx 
+	  series of PDAs.
+
+	  To compile this driver as a module, choose M here: the 
+	  module will be called corgikbd.
+
 config KEYBOARD_MAPLE
-	tristate "Maple bus keyboard support"
-	depends on SH_DREAMCAST && INPUT && INPUT_KEYBOARD && MAPLE
+	tristate "Maple bus keyboard"
+	depends on SH_DREAMCAST && MAPLE
 	help
 	  Say Y here if you have a DreamCast console running Linux and have
 	  a keyboard attached to its Maple bus.
@@ -90,10 +144,42 @@
 
 config KEYBOARD_AMIGA
 	tristate "Amiga keyboard"
-	depends on AMIGA && INPUT && INPUT_KEYBOARD
+	depends on AMIGA
 	help
 	  Say Y here if you are running Linux on any AMIGA and have a keyboard
 	  attached.
 
 	  To compile this driver as a module, choose M here: the
 	  module will be called amikbd.
+
+config KEYBOARD_HIL_OLD
+	tristate "HP HIL keyboard support (simple driver)"
+	depends on GSC
+	default y
+	help
+	  The "Human Interface Loop" is a older, 8-channel USB-like
+	  controller used in several Hewlett Packard models. This driver
+	  was adapted from the one written for m68k/hp300, and implements
+	  support for a keyboard attached to the HIL port, but not for
+	  any other types of HIL input devices like mice or tablets.
+	  However, it has been thoroughly tested and is stable.
+
+	  If you want full HIL support including support for multiple
+	  keyboards, mices and tablets, you have to enable the
+	  "HP System Device Controller i8042 Support" in the input/serio
+	  submenu.
+
+config KEYBOARD_HIL
+	tristate "HP HIL keyboard support"
+	depends on GSC
+	default y
+	select HP_SDC
+	select HIL_MLC
+	select SERIO
+	help
+	  The "Human Interface Loop" is a older, 8-channel USB-like
+	  controller used in several Hewlett Packard models.
+	  This driver implements support for HIL-keyboards attached
+	  to your machine, so normally you should say Y here.
+
+endif
diff -Nru a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile
--- a/drivers/input/keyboard/Makefile	2005-03-11 12:51:52 -08:00
+++ b/drivers/input/keyboard/Makefile	2005-03-11 12:51:52 -08:00
@@ -10,5 +10,10 @@
 obj-$(CONFIG_KEYBOARD_LKKBD)		+= lkkbd.o
 obj-$(CONFIG_KEYBOARD_XTKBD)		+= xtkbd.o
 obj-$(CONFIG_KEYBOARD_AMIGA)		+= amikbd.o
+obj-$(CONFIG_KEYBOARD_LOCOMO)		+= locomokbd.o
 obj-$(CONFIG_KEYBOARD_NEWTON)		+= newtonkbd.o
 obj-$(CONFIG_KEYBOARD_98KBD)		+= 98kbd.o
+obj-$(CONFIG_KEYBOARD_CORGI)		+= corgikbd.o
+obj-$(CONFIG_KEYBOARD_HIL)		+= hil_kbd.o
+obj-$(CONFIG_KEYBOARD_HIL_OLD)		+= hilkbd.o
+
diff -Nru a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c
--- a/drivers/input/keyboard/atkbd.c	2005-03-11 12:51:52 -08:00
+++ b/drivers/input/keyboard/atkbd.c	2005-03-11 12:51:52 -08:00
@@ -54,7 +54,7 @@
 module_param_named(softraw, atkbd_softraw, bool, 0);
 MODULE_PARM_DESC(softraw, "Use software generated rawmode");
 
-static int atkbd_scroll;
+static int atkbd_scroll = 1;
 module_param_named(scroll, atkbd_scroll, bool, 0);
 MODULE_PARM_DESC(scroll, "Enable scroll-wheel on MS Office and similar keyboards");
 
@@ -71,12 +71,15 @@
  * are loadable via an userland utility.
  */
 
-#if defined(__hppa__)
-#include "hpps2atkbd.h"
-#else
-
 static unsigned char atkbd_set2_keycode[512] = {
 
+#ifdef CONFIG_KEYBOARD_ATKBD_HP_KEYCODES
+
+/* XXX: need a more general approach */
+
+#include "hpps2atkbd.h"	/* include the keyboard scancodes */
+
+#else
 	  0, 67, 65, 63, 61, 59, 60, 88,  0, 68, 66, 64, 62, 15, 41,117,
 	  0, 56, 42, 93, 29, 16,  2,  0,  0,  0, 44, 31, 30, 17,  3,  0,
 	  0, 46, 45, 32, 18,  5,  4, 95,  0, 57, 47, 33, 20, 19,  6,183,
@@ -96,9 +99,8 @@
 	110,111,108,112,106,103,  0,119,  0,118,109,  0, 99,104,119,  0,
 
 	  0,  0,  0, 65, 99,
-};
-
 #endif
+};
 
 static unsigned char atkbd_set3_keycode[512] = {
 
@@ -141,7 +143,6 @@
 #define ATKBD_CMD_EX_SETLEDS	0x20eb
 #define ATKBD_CMD_OK_GETID	0x02e8
 
-
 #define ATKBD_RET_ACK		0xfa
 #define ATKBD_RET_NAK		0xfe
 #define ATKBD_RET_BAT		0xaa
@@ -160,15 +161,22 @@
 #define ATKBD_SCR_4		252
 #define ATKBD_SCR_8		251
 #define ATKBD_SCR_CLICK		250
+#define ATKBD_SCR_LEFT		249
+#define ATKBD_SCR_RIGHT		248
 
-#define ATKBD_SPECIAL		250
+#define ATKBD_SPECIAL		248
 
-static unsigned char atkbd_scroll_keys[5][2] = {
-	{ ATKBD_SCR_1,     0x45 },
-	{ ATKBD_SCR_2,     0x29 },
-	{ ATKBD_SCR_4,     0x36 },
-	{ ATKBD_SCR_8,     0x27 },
-	{ ATKBD_SCR_CLICK, 0x60 },
+static struct {
+	unsigned char keycode;
+	unsigned char set2;
+} atkbd_scroll_keys[] = {
+	{ ATKBD_SCR_1,     0xc5 },
+	{ ATKBD_SCR_2,     0xa9 },
+	{ ATKBD_SCR_4,     0xb6 },
+	{ ATKBD_SCR_8,     0xa7 },
+	{ ATKBD_SCR_CLICK, 0xe0 },
+	{ ATKBD_SCR_LEFT,  0xcb },
+	{ ATKBD_SCR_RIGHT, 0xd2 },
 };
 
 /*
@@ -249,9 +257,9 @@
 static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data,
 			unsigned int flags, struct pt_regs *regs)
 {
-	struct atkbd *atkbd = serio->private;
+	struct atkbd *atkbd = serio_get_drvdata(serio);
 	unsigned int code = data;
-	int scroll = 0, click = -1;
+	int scroll = 0, hscroll = 0, click = -1;
 	int value;
 
 #ifdef ATKBD_DEBUG
@@ -370,6 +378,12 @@
 		case ATKBD_SCR_CLICK:
 			click = !atkbd->release;
 			break;
+		case ATKBD_SCR_LEFT:
+			hscroll = -1;
+			break;
+		case ATKBD_SCR_RIGHT:
+			hscroll = 1;
+			break;
 		default:
 			value = atkbd->release ? 0 :
 				(1 + (!atkbd->softrepeat && test_bit(atkbd->keycode[code], atkbd->dev.key)));
@@ -380,7 +394,7 @@
 					break;
 				case 1:
 					atkbd->last = code;
-					atkbd->time = jiffies + (atkbd->dev.rep[REP_DELAY] * HZ + 500) / 1000 / 2;
+					atkbd->time = jiffies + msecs_to_jiffies(atkbd->dev.rep[REP_DELAY]) / 2;
 					break;
 				case 2:
 					if (!time_after(jiffies, atkbd->time) && atkbd->last == code)
@@ -391,10 +405,12 @@
 			atkbd_report_key(&atkbd->dev, regs, atkbd->keycode[code], value);
 	}
 
-	if (scroll || click != -1) {
+	if (atkbd->scroll) {
 		input_regs(&atkbd->dev, regs);
-		input_report_key(&atkbd->dev, BTN_MIDDLE, click);
+		if (click != -1)
+			input_report_key(&atkbd->dev, BTN_MIDDLE, click);
 		input_report_rel(&atkbd->dev, REL_WHEEL, scroll);
+		input_report_rel(&atkbd->dev, REL_HWHEEL, hscroll);
 		input_sync(&atkbd->dev);
 	}
 
@@ -403,7 +419,6 @@
 	return IRQ_HANDLED;
 }
 
-
 /*
  * Event callback from the input module. Events that change the state of
  * the hardware are processed here.
@@ -647,7 +662,7 @@
 
 static void atkbd_cleanup(struct serio *serio)
 {
-	struct atkbd *atkbd = serio->private;
+	struct atkbd *atkbd = serio_get_drvdata(serio);
 	ps2_command(&atkbd->ps2dev, NULL, ATKBD_CMD_RESET_BAT);
 }
 
@@ -658,7 +673,7 @@
 
 static void atkbd_disconnect(struct serio *serio)
 {
-	struct atkbd *atkbd = serio->private;
+	struct atkbd *atkbd = serio_get_drvdata(serio);
 
 	atkbd_disable(atkbd);
 
@@ -674,6 +689,7 @@
 
 	input_unregister_device(&atkbd->dev);
 	serio_close(serio);
+	serio_set_drvdata(serio, NULL);
 	kfree(atkbd);
 }
 
@@ -694,12 +710,9 @@
 			atkbd->keycode[i] = atkbd_set2_keycode[atkbd_unxlate_table[i]];
 			atkbd->keycode[i | 0x80] = atkbd_set2_keycode[atkbd_unxlate_table[i] | 0x80];
 			if (atkbd->scroll)
-				for (j = 0; i < 5; i++) {
-					if (atkbd_unxlate_table[i] == atkbd_scroll_keys[j][1])
-						atkbd->keycode[i] = atkbd_scroll_keys[j][0];
-					if ((atkbd_unxlate_table[i] | 0x80) == atkbd_scroll_keys[j][1])
-						atkbd->keycode[i | 0x80] = atkbd_scroll_keys[j][0];
-				}
+				for (j = 0; j < ARRAY_SIZE(atkbd_scroll_keys); j++)
+					if ((atkbd_unxlate_table[i] | 0x80) == atkbd_scroll_keys[j].set2)
+						atkbd->keycode[i | 0x80] = atkbd_scroll_keys[j].keycode;
 		}
 	} else if (atkbd->set == 3) {
 		memcpy(atkbd->keycode, atkbd_set3_keycode, sizeof(atkbd->keycode));
@@ -707,8 +720,8 @@
 		memcpy(atkbd->keycode, atkbd_set2_keycode, sizeof(atkbd->keycode));
 
 		if (atkbd->scroll)
-			for (i = 0; i < 5; i++)
-				atkbd->keycode[atkbd_scroll_keys[i][1]] = atkbd_scroll_keys[i][0];
+			for (i = 0; i < ARRAY_SIZE(atkbd_scroll_keys); i++)
+				atkbd->keycode[atkbd_scroll_keys[i].set2] = atkbd_scroll_keys[i].keycode;
 	}
 }
 
@@ -754,7 +767,7 @@
 
 	if (atkbd->scroll) {
 		atkbd->dev.evbit[0] |= BIT(EV_REL);
-		atkbd->dev.relbit[0] = BIT(REL_WHEEL);
+		atkbd->dev.relbit[0] = BIT(REL_WHEEL) | BIT(REL_HWHEEL);
 		set_bit(BTN_MIDDLE, atkbd->dev.keybit);
 	}
 
@@ -768,23 +781,25 @@
 }
 
 /*
- * atkbd_connect() is called when the serio module finds and interface
+ * atkbd_connect() is called when the serio module finds an interface
  * that isn't handled yet by an appropriate device driver. We check if
  * there is an AT keyboard out there and if yes, we register ourselves
  * to the input module.
  */
 
-static void atkbd_connect(struct serio *serio, struct serio_driver *drv)
+static int atkbd_connect(struct serio *serio, struct serio_driver *drv)
 {
 	struct atkbd *atkbd;
+	int err;
 
 	if (!(atkbd = kmalloc(sizeof(struct atkbd), GFP_KERNEL)))
-		return;
+		return - ENOMEM;
+
 	memset(atkbd, 0, sizeof(struct atkbd));
 
 	ps2_init(&atkbd->ps2dev, serio);
 
-	switch (serio->type & SERIO_TYPE) {
+	switch (serio->id.type) {
 
 		case SERIO_8042_XL:
 			atkbd->translated = 1;
@@ -792,12 +807,6 @@
 			if (serio->write)
 				atkbd->write = 1;
 			break;
-		case SERIO_RS232:
-			if ((serio->type & SERIO_PROTO) == SERIO_PS2SER)
-				break;
-		default:
-			kfree(atkbd);
-			return;
 	}
 
 	atkbd->softraw = atkbd_softraw;
@@ -810,20 +819,22 @@
 	if (atkbd->softrepeat)
 		atkbd->softraw = 1;
 
-	serio->private = atkbd;
+	serio_set_drvdata(serio, atkbd);
 
-	if (serio_open(serio, drv)) {
+	err = serio_open(serio, drv);
+	if (err) {
+		serio_set_drvdata(serio, NULL);
 		kfree(atkbd);
-		return;
+		return err;
 	}
 
 	if (atkbd->write) {
 
 		if (atkbd_probe(atkbd)) {
 			serio_close(serio);
-			serio->private = NULL;
+			serio_set_drvdata(serio, NULL);
 			kfree(atkbd);
-			return;
+			return -ENODEV;
 		}
 
 		atkbd->set = atkbd_select_set(atkbd, atkbd_set, atkbd_extra);
@@ -856,6 +867,8 @@
 	atkbd_enable(atkbd);
 
 	printk(KERN_INFO "input: %s on %s\n", atkbd->name, serio->phys);
+
+	return 0;
 }
 
 /*
@@ -865,7 +878,7 @@
 
 static int atkbd_reconnect(struct serio *serio)
 {
-	struct atkbd *atkbd = serio->private;
+	struct atkbd *atkbd = serio_get_drvdata(serio);
 	struct serio_driver *drv = serio->drv;
 	unsigned char param[1];
 
@@ -897,11 +910,36 @@
 	return 0;
 }
 
+static struct serio_device_id atkbd_serio_ids[] = {
+	{
+		.type	= SERIO_8042,
+		.proto	= SERIO_ANY,
+		.id	= SERIO_ANY,
+		.extra	= SERIO_ANY,
+	},
+	{
+		.type	= SERIO_8042_XL,
+		.proto	= SERIO_ANY,
+		.id	= SERIO_ANY,
+		.extra	= SERIO_ANY,
+	},
+	{
+		.type	= SERIO_RS232,
+		.proto	= SERIO_PS2SER,
+		.id	= SERIO_ANY,
+		.extra	= SERIO_ANY,
+	},
+	{ 0 }
+};
+
+MODULE_DEVICE_TABLE(serio, atkbd_serio_ids);
+
 static struct serio_driver atkbd_drv = {
 	.driver		= {
 		.name	= "atkbd",
 	},
 	.description	= DRIVER_DESC,
+	.id_table	= atkbd_serio_ids,
 	.interrupt	= atkbd_interrupt,
 	.connect	= atkbd_connect,
 	.reconnect	= atkbd_reconnect,
@@ -924,7 +962,7 @@
 		goto out;
 	}
 
-	retval = handler((struct atkbd *)serio->private, buf);
+	retval = handler((struct atkbd *)serio_get_drvdata(serio), buf);
 
 out:
 	serio_unpin_driver(serio);
@@ -947,7 +985,7 @@
 		goto out;
 	}
 
-	atkbd = serio->private;
+	atkbd = serio_get_drvdata(serio);
 	atkbd_disable(atkbd);
 	retval = handler(atkbd, buf, count);
 	atkbd_enable(atkbd);
@@ -1095,13 +1133,13 @@
 }
 
 
-int __init atkbd_init(void)
+static int __init atkbd_init(void)
 {
 	serio_register_driver(&atkbd_drv);
 	return 0;
 }
 
-void __exit atkbd_exit(void)
+static void __exit atkbd_exit(void)
 {
 	serio_unregister_driver(&atkbd_drv);
 }
diff -Nru a/drivers/input/keyboard/corgikbd.c b/drivers/input/keyboard/corgikbd.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/input/keyboard/corgikbd.c	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,361 @@
+/*
+ *  Keyboard driver for Sharp Corgi models (SL-C7xx)
+ *
+ *  Copyright (c) 2004-2005 Richard Purdie
+ *
+ *  Based on xtkbd.c/locomkbd.c
+ *
+ *  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/delay.h>
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <asm/irq.h>
+
+#include <asm/arch/corgi.h>
+#include <asm/arch/hardware.h>
+#include <asm/arch/pxa-regs.h>
+#include <asm/hardware/scoop.h>
+
+#define KB_ROWS				8
+#define KB_COLS				12
+#define KB_ROWMASK(r)		(1 << (r))
+#define SCANCODE(r,c)		( ((r)<<4) + (c) + 1 )
+/* zero code, 124 scancodes + 3 hinge combinations */
+#define	NR_SCANCODES		( SCANCODE(KB_ROWS-1,KB_COLS-1) +1 +1 +3 )
+#define SCAN_INTERVAL		(HZ/10)
+#define CORGIKBD_PRESSED	1
+
+#define HINGE_SCAN_INTERVAL		(HZ/4)
+
+#define CORGI_KEY_CALENDER	KEY_F1
+#define CORGI_KEY_ADDRESS	KEY_F2
+#define CORGI_KEY_FN		KEY_F3
+#define CORGI_KEY_OFF		KEY_SUSPEND
+#define CORGI_KEY_EXOK		KEY_F5
+#define CORGI_KEY_EXCANCEL	KEY_F6
+#define CORGI_KEY_EXJOGDOWN	KEY_F7
+#define CORGI_KEY_EXJOGUP	KEY_F8
+#define CORGI_KEY_JAP1		KEY_LEFTCTRL
+#define CORGI_KEY_JAP2		KEY_LEFTALT
+#define CORGI_KEY_OK		KEY_F11
+#define CORGI_KEY_MENU		KEY_F12
+#define CORGI_HINGE_0		KEY_KP0
+#define CORGI_HINGE_1		KEY_KP1
+#define CORGI_HINGE_2		KEY_KP2
+
+static unsigned char corgikbd_keycode[NR_SCANCODES] = {
+	0,                                                                                                                /* 0 */
+	0, KEY_1, KEY_3, KEY_5, KEY_6, KEY_7, KEY_9, KEY_0, KEY_BACKSPACE, 0, 0, 0, 0, 0, 0, 0, 	                      /* 1-16 */
+	0, KEY_2, KEY_4, KEY_R, KEY_Y, KEY_8, KEY_I, KEY_O, KEY_P, 0, 0, 0, 0, 0, 0, 0,                                   /* 17-32 */
+	KEY_TAB, KEY_Q, KEY_E, KEY_T, KEY_G, KEY_U, KEY_J, KEY_K, 0, 0, 0, 0, 0, 0, 0, 0,                                 /* 33-48 */
+	CORGI_KEY_CALENDER, KEY_W, KEY_S, KEY_F, KEY_V, KEY_H, KEY_M, KEY_L, 0, KEY_RIGHTSHIFT, 0, 0, 0, 0, 0, 0,         /* 49-64 */
+	CORGI_KEY_ADDRESS, KEY_A, KEY_D, KEY_C, KEY_B, KEY_N, KEY_DOT, 0, KEY_ENTER, 0, KEY_LEFTSHIFT, 0, 0, 0, 0, 0, 	  /* 65-80 */
+	KEY_MAIL, KEY_Z, KEY_X, KEY_MINUS, KEY_SPACE, KEY_COMMA, 0, KEY_UP, 0, 0, 0, CORGI_KEY_FN, 0, 0, 0, 0,            /* 81-96 */
+	KEY_SYSRQ, CORGI_KEY_JAP1, CORGI_KEY_JAP2, KEY_CANCEL, CORGI_KEY_OK, CORGI_KEY_MENU, KEY_LEFT, KEY_DOWN, KEY_RIGHT, 0, 0, 0, 0, 0, 0, 0,  /* 97-112 */
+	CORGI_KEY_OFF, CORGI_KEY_EXOK, CORGI_KEY_EXCANCEL, CORGI_KEY_EXJOGDOWN, CORGI_KEY_EXJOGUP, 0, 0, 0, 0, 0, 0, 0,   /* 113-124 */
+	CORGI_HINGE_0, CORGI_HINGE_1, CORGI_HINGE_2	  /* 125-127 */
+};
+
+
+struct corgikbd {
+	unsigned char keycode[ARRAY_SIZE(corgikbd_keycode)];
+	struct input_dev input;
+	char phys[32];
+
+	unsigned char state[ARRAY_SIZE(corgikbd_keycode)];
+	spinlock_t lock;
+
+	struct timer_list timer;
+	struct timer_list htimer;
+};
+
+static void handle_scancode(unsigned int pressed,unsigned int scancode, struct corgikbd *corgikbd_data)
+{
+	if (pressed && !(corgikbd_data->state[scancode] & CORGIKBD_PRESSED)) {
+		corgikbd_data->state[scancode] |= CORGIKBD_PRESSED;
+		input_report_key(&corgikbd_data->input, corgikbd_data->keycode[scancode], 1);
+		if (corgikbd_data->keycode[scancode] == CORGI_KEY_OFF)
+			input_event(&corgikbd_data->input, EV_PWR, CORGI_KEY_OFF, 1);
+	} else if (!pressed && corgikbd_data->state[scancode] & CORGIKBD_PRESSED) {
+		corgikbd_data->state[scancode] &= ~CORGIKBD_PRESSED;
+		input_report_key(&corgikbd_data->input, corgikbd_data->keycode[scancode], 0);
+	}
+}
+
+#define KB_DISCHARGE_DELAY	10
+#define KB_ACTIVATE_DELAY	10
+
+/* Helper functions for reading the keyboard matrix
+ * Note: We should really be using pxa_gpio_mode to alter GPDR but it
+ *       requires a function call per GPIO bit which is excessive
+ *       when we need to access 12 bits at once multiple times.
+ * These functions must be called within local_irq_save()/local_irq_restore()
+ * or similar.
+ */
+static inline void corgikbd_discharge_all(void)
+{
+	// STROBE All HiZ
+	GPCR2  = CORGI_GPIO_ALL_STROBE_BIT;
+	GPDR2 &= ~CORGI_GPIO_ALL_STROBE_BIT;
+}
+
+static inline void corgikbd_activate_all(void)
+{
+	// STROBE ALL -> High
+	GPSR2  = CORGI_GPIO_ALL_STROBE_BIT;
+	GPDR2 |= CORGI_GPIO_ALL_STROBE_BIT;
+
+	udelay(KB_DISCHARGE_DELAY);
+
+	// Clear any interrupts we may have triggered when altering the GPIO lines
+	GEDR1 = CORGI_GPIO_HIGH_SENSE_BIT;
+	GEDR2 = CORGI_GPIO_LOW_SENSE_BIT;
+}
+
+static inline void corgikbd_activate_col(int col)
+{
+	// STROBE col -> High, not col -> HiZ
+	GPSR2 = CORGI_GPIO_STROBE_BIT(col);
+	GPDR2 = (GPDR2 & ~CORGI_GPIO_ALL_STROBE_BIT) | CORGI_GPIO_STROBE_BIT(col);
+}
+
+static inline void corgikbd_reset_col(int col)
+{
+	// STROBE col -> Low
+	GPCR2 = CORGI_GPIO_STROBE_BIT(col);
+	// STROBE col -> out, not col -> HiZ
+	GPDR2 = (GPDR2 & ~CORGI_GPIO_ALL_STROBE_BIT) | CORGI_GPIO_STROBE_BIT(col);
+}
+
+#define GET_ROWS_STATUS(c)	(((GPLR1 & CORGI_GPIO_HIGH_SENSE_BIT) >> CORGI_GPIO_HIGH_SENSE_RSHIFT) | ((GPLR2 & CORGI_GPIO_LOW_SENSE_BIT) << CORGI_GPIO_LOW_SENSE_LSHIFT))
+
+/*
+ * The corgi keyboard only generates interrupts when a key is pressed.
+ * When a key is pressed, we enable a timer which then scans the
+ * keyboard to detect when the key is released.
+ */
+
+/* Scan the hardware keyboard and push any changes up through the input layer */
+static void corgikbd_scankeyboard(struct corgikbd *corgikbd_data, struct pt_regs *regs)
+{
+	unsigned int row, col, rowd, scancode;
+	unsigned long flags;
+	unsigned int num_pressed;
+
+	spin_lock_irqsave(&corgikbd_data->lock, flags);
+
+	if (regs)
+		input_regs(&corgikbd_data->input, regs);
+
+	num_pressed = 0;
+	for (col = 0; col < KB_COLS; col++) {
+		/*
+		 * Discharge the output driver capacitatance
+		 * in the keyboard matrix. (Yes it is significant..)
+		 */
+
+		corgikbd_discharge_all();
+		udelay(KB_DISCHARGE_DELAY);
+
+		corgikbd_activate_col(col);
+		udelay(KB_ACTIVATE_DELAY);
+
+		rowd = GET_ROWS_STATUS(col);
+		for (row = 0; row < KB_ROWS; row++) {
+			scancode = SCANCODE(row, col);
+			handle_scancode((rowd & KB_ROWMASK(row)), scancode, corgikbd_data);
+			if (rowd & KB_ROWMASK(row))
+				num_pressed++;
+		}
+		corgikbd_reset_col(col);
+	}
+
+	corgikbd_activate_all();
+
+	input_sync(&corgikbd_data->input);
+
+	/* if any keys are pressed, enable the timer */
+	if (num_pressed)
+		mod_timer(&corgikbd_data->timer, jiffies + SCAN_INTERVAL);
+
+	spin_unlock_irqrestore(&corgikbd_data->lock, flags);
+}
+
+/*
+ * corgi keyboard interrupt handler.
+ */
+static irqreturn_t corgikbd_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+	struct corgikbd *corgikbd_data = dev_id;
+
+	if (!timer_pending(&corgikbd_data->timer)) {
+		/** wait chattering delay **/
+		udelay(20);
+		corgikbd_scankeyboard(corgikbd_data, regs);
+	}
+
+	return IRQ_HANDLED;
+}
+
+/*
+ * corgi timer checking for released keys
+ */
+static void corgikbd_timer_callback(unsigned long data)
+{
+	struct corgikbd *corgikbd_data = (struct corgikbd *) data;
+	corgikbd_scankeyboard(corgikbd_data, NULL);
+}
+
+/*
+ * The hinge switches generate no interrupt so they need to be
+ * monitored by a timer.
+ *
+ * When we detect changes, we debounce it and then pass the three
+ * positions the system can take as keypresses to the input system.
+ */
+
+#define HINGE_STABLE_COUNT 2
+static int sharpsl_hinge_state;
+static int hinge_count;
+
+static void corgikbd_hinge_timer(unsigned long data)
+{
+	struct corgikbd *corgikbd_data = (struct corgikbd *) data;
+	unsigned long gprr;
+	unsigned long flags;
+
+	gprr = read_scoop_reg(SCOOP_GPRR) & (CORGI_SCP_SWA | CORGI_SCP_SWB);
+	if (gprr != sharpsl_hinge_state) {
+		hinge_count = 0;
+		sharpsl_hinge_state = gprr;
+	} else if (hinge_count < HINGE_STABLE_COUNT) {
+		hinge_count++;
+		if (hinge_count >= HINGE_STABLE_COUNT) {
+			spin_lock_irqsave(&corgikbd_data->lock, flags);
+
+			handle_scancode((sharpsl_hinge_state == 0x00), 125, corgikbd_data); /* Keyboard with Landscape Screen */
+			handle_scancode((sharpsl_hinge_state == 0x08), 126, corgikbd_data); /* No Keyboard with Portrait Screen */
+			handle_scancode((sharpsl_hinge_state == 0x0c), 127, corgikbd_data); /* Keyboard and Screen Closed  */
+			input_sync(&corgikbd_data->input);
+
+			spin_unlock_irqrestore(&corgikbd_data->lock, flags);
+		}
+	}
+	mod_timer(&corgikbd_data->htimer, jiffies + HINGE_SCAN_INTERVAL);
+}
+
+static int __init corgikbd_probe(struct device *dev)
+{
+	int i;
+	struct corgikbd *corgikbd;
+
+	corgikbd = kcalloc(1, sizeof(struct corgikbd), GFP_KERNEL);
+	if (!corgikbd)
+		return -ENOMEM;
+
+	dev_set_drvdata(dev,corgikbd);
+	strcpy(corgikbd->phys, "corgikbd/input0");
+
+	spin_lock_init(corgikbd->lock);
+
+	/* Init Keyboard rescan timer */
+	init_timer(&corgikbd->timer);
+	corgikbd->timer.function = corgikbd_timer_callback;
+	corgikbd->timer.data = (unsigned long) corgikbd;
+
+	/* Init Hinge Timer */
+	init_timer(&corgikbd->htimer);
+	corgikbd->htimer.function = corgikbd_hinge_timer;
+	corgikbd->htimer.data = (unsigned long) corgikbd;
+
+	init_input_dev(&corgikbd->input);
+	corgikbd->input.private = corgikbd;
+	corgikbd->input.name = "Corgi Keyboard";
+	corgikbd->input.dev = dev;
+	corgikbd->input.phys = corgikbd->phys;
+	corgikbd->input.id.bustype = BUS_HOST;
+	corgikbd->input.id.vendor = 0x0001;
+	corgikbd->input.id.product = 0x0001;
+	corgikbd->input.id.version = 0x0100;
+	corgikbd->input.evbit[0] = BIT(EV_KEY) | BIT(EV_REP) | BIT(EV_PWR);
+	corgikbd->input.keycode = corgikbd->keycode;
+	corgikbd->input.keycodesize = sizeof(unsigned char);
+	corgikbd->input.keycodemax = ARRAY_SIZE(corgikbd_keycode);
+
+	memcpy(corgikbd->keycode, corgikbd_keycode, sizeof(corgikbd->keycode));
+	for (i = 0; i < ARRAY_SIZE(corgikbd_keycode); i++)
+		set_bit(corgikbd->keycode[i], corgikbd->input.keybit);
+	clear_bit(0, corgikbd->input.keybit);
+
+	input_register_device(&corgikbd->input);
+	mod_timer(&corgikbd->htimer, jiffies + HINGE_SCAN_INTERVAL);
+
+	/* Setup sense interrupts - RisingEdge Detect, sense lines as inputs */
+	for (i = 0; i < CORGI_KEY_SENSE_NUM; i++) {
+		pxa_gpio_mode(CORGI_GPIO_KEY_SENSE(i) | GPIO_IN);
+		if (request_irq(CORGI_IRQ_GPIO_KEY_SENSE(i), corgikbd_interrupt,
+						SA_INTERRUPT, "corgikbd", corgikbd))
+			printk(KERN_WARNING "corgikbd: Can't get IRQ: %d!\n", i);
+		else
+			set_irq_type(CORGI_IRQ_GPIO_KEY_SENSE(i),IRQT_RISING);
+	}
+
+	/* Set Strobe lines as outputs - set high */
+	for (i = 0; i < CORGI_KEY_STROBE_NUM; i++)
+		pxa_gpio_mode(CORGI_GPIO_KEY_STROBE(i) | GPIO_OUT | GPIO_DFLT_HIGH);
+
+	printk(KERN_INFO "input: Corgi Keyboard Registered\n");
+
+	return 0;
+}
+
+static int corgikbd_remove(struct device *dev)
+{
+	int i;
+	struct corgikbd *corgikbd = dev_get_drvdata(dev);
+
+	for (i = 0; i < CORGI_KEY_SENSE_NUM; i++)
+		free_irq(CORGI_IRQ_GPIO_KEY_SENSE(i), corgikbd);
+
+	del_timer_sync(&corgikbd->htimer);
+	del_timer_sync(&corgikbd->timer);
+
+	input_unregister_device(&corgikbd->input);
+
+	kfree(corgikbd);
+
+	return 0;
+}
+
+static struct device_driver corgikbd_driver = {
+	.name		= "corgi-keyboard",
+	.bus		= &platform_bus_type,
+	.probe		= corgikbd_probe,
+	.remove		= corgikbd_remove,
+};
+
+static int __devinit corgikbd_init(void)
+{
+	return driver_register(&corgikbd_driver);
+}
+
+static void __exit corgikbd_exit(void)
+{
+	driver_unregister(&corgikbd_driver);
+}
+
+module_init(corgikbd_init);
+module_exit(corgikbd_exit);
+
+MODULE_AUTHOR("Richard Purdie <rpurdie@rpsys.net>");
+MODULE_DESCRIPTION("Corgi Keyboard Driver");
+MODULE_LICENSE("GPLv2");
diff -Nru a/drivers/input/keyboard/hil_kbd.c b/drivers/input/keyboard/hil_kbd.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/input/keyboard/hil_kbd.c	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,375 @@
+/*
+ * Generic linux-input device driver for keyboard devices
+ *
+ * Copyright (c) 2001 Brian S. Julin
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions, and the following disclaimer,
+ *    without modification.
+ * 2. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL").
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ *
+ * References:
+ * HP-HIL Technical Reference Manual.  Hewlett Packard Product No. 45918A
+ *
+ */
+
+#include <linux/hil.h>
+#include <linux/input.h>
+#include <linux/serio.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/pci_ids.h>
+
+#define PREFIX "HIL KEYB: "
+#define HIL_GENERIC_NAME "HIL keyboard"
+
+MODULE_AUTHOR("Brian S. Julin <bri@calyx.com>");
+MODULE_DESCRIPTION(HIL_GENERIC_NAME " driver");
+MODULE_LICENSE("Dual BSD/GPL");
+
+#define HIL_KBD_MAX_LENGTH 16
+
+#define HIL_KBD_SET1_UPBIT 0x01
+#define HIL_KBD_SET1_SHIFT 1
+static unsigned int hil_kbd_set1[HIL_KEYCODES_SET1_TBLSIZE] = 
+	{ HIL_KEYCODES_SET1 };
+
+#define HIL_KBD_SET2_UPBIT 0x01
+#define HIL_KBD_SET2_SHIFT 1
+/* Set2 is user defined */
+
+#define HIL_KBD_SET3_UPBIT 0x80
+#define HIL_KBD_SET3_SHIFT 0
+static unsigned int hil_kbd_set3[HIL_KEYCODES_SET3_TBLSIZE] =
+	{ HIL_KEYCODES_SET3 };
+
+static char hil_language[][16] = { HIL_LOCALE_MAP };
+
+struct hil_kbd {
+	struct input_dev dev;
+	struct serio *serio;
+
+	/* Input buffer and index for packets from HIL bus. */
+	hil_packet data[HIL_KBD_MAX_LENGTH];
+	int idx4; /* four counts per packet */
+
+	/* Raw device info records from HIL bus, see hil.h for fields. */
+	char	idd[HIL_KBD_MAX_LENGTH];	/* DID byte and IDD record */
+	char	rsc[HIL_KBD_MAX_LENGTH];	/* RSC record */
+	char	exd[HIL_KBD_MAX_LENGTH];	/* EXD record */
+	char	rnm[HIL_KBD_MAX_LENGTH + 1];	/* RNM record + NULL term. */
+
+	/* Something to sleep around with. */
+	struct semaphore sem;
+};
+
+/* Process a complete packet after transfer from the HIL */
+static void hil_kbd_process_record(struct hil_kbd *kbd)
+{
+	struct input_dev *dev = &kbd->dev;
+	hil_packet *data = kbd->data;
+	hil_packet p;
+	int idx, i, cnt;
+
+	idx = kbd->idx4/4;
+	p = data[idx - 1];
+
+	if ((p & ~HIL_CMDCT_POL) == 
+	    (HIL_ERR_INT | HIL_PKT_CMD | HIL_CMD_POL)) goto report;
+	if ((p & ~HIL_CMDCT_RPL) == 
+	    (HIL_ERR_INT | HIL_PKT_CMD | HIL_CMD_RPL)) goto report;
+
+	/* Not a poll response.  See if we are loading config records. */
+	switch (p & HIL_PKT_DATA_MASK) {
+	case HIL_CMD_IDD:
+		for (i = 0; i < idx; i++)
+			kbd->idd[i] = kbd->data[i] & HIL_PKT_DATA_MASK;
+		for (; i < HIL_KBD_MAX_LENGTH; i++)
+			kbd->idd[i] = 0;
+		break;
+	case HIL_CMD_RSC:
+		for (i = 0; i < idx; i++)
+			kbd->rsc[i] = kbd->data[i] & HIL_PKT_DATA_MASK;
+		for (; i < HIL_KBD_MAX_LENGTH; i++)
+			kbd->rsc[i] = 0;
+		break;
+	case HIL_CMD_EXD:
+		for (i = 0; i < idx; i++)
+			kbd->exd[i] = kbd->data[i] & HIL_PKT_DATA_MASK;
+		for (; i < HIL_KBD_MAX_LENGTH; i++)
+			kbd->exd[i] = 0;
+		break;
+	case HIL_CMD_RNM:
+		for (i = 0; i < idx; i++)
+			kbd->rnm[i] = kbd->data[i] & HIL_PKT_DATA_MASK;
+		for (; i < HIL_KBD_MAX_LENGTH + 1; i++)
+			kbd->rnm[i] = '\0';
+		break;
+	default:
+		/* These occur when device isn't present */
+		if (p == (HIL_ERR_INT | HIL_PKT_CMD)) break; 
+		/* Anything else we'd like to know about. */
+		printk(KERN_WARNING PREFIX "Device sent unknown record %x\n", p);
+		break;
+	}
+	goto out;
+
+ report:
+	cnt = 1;
+	switch (kbd->data[0] & HIL_POL_CHARTYPE_MASK) {
+	case HIL_POL_CHARTYPE_NONE:
+		break;
+	case HIL_POL_CHARTYPE_ASCII:
+		while (cnt < idx - 1)
+			input_report_key(dev, kbd->data[cnt++] & 0x7f, 1);
+		break;
+	case HIL_POL_CHARTYPE_RSVD1:
+	case HIL_POL_CHARTYPE_RSVD2:
+	case HIL_POL_CHARTYPE_BINARY:
+		while (cnt < idx - 1)
+			input_report_key(dev, kbd->data[cnt++], 1);
+		break;
+	case HIL_POL_CHARTYPE_SET1:
+		while (cnt < idx - 1) {
+			unsigned int key;
+			int up;
+			key = kbd->data[cnt++];
+			up = key & HIL_KBD_SET1_UPBIT;
+			key &= (~HIL_KBD_SET1_UPBIT & 0xff);
+			key = hil_kbd_set1[key >> HIL_KBD_SET1_SHIFT];
+			if (key != KEY_RESERVED)
+				input_report_key(dev, key, !up);
+		}
+		break;
+	case HIL_POL_CHARTYPE_SET2:
+		while (cnt < idx - 1) {
+			unsigned int key;
+			int up;
+			key = kbd->data[cnt++];
+			up = key & HIL_KBD_SET2_UPBIT;
+			key &= (~HIL_KBD_SET1_UPBIT & 0xff);
+			key = key >> HIL_KBD_SET2_SHIFT;
+			if (key != KEY_RESERVED)
+				input_report_key(dev, key, !up);
+		}
+		break;
+	case HIL_POL_CHARTYPE_SET3:
+		while (cnt < idx - 1) {
+			unsigned int key;
+			int up;
+			key = kbd->data[cnt++];
+			up = key & HIL_KBD_SET3_UPBIT;
+			key &= (~HIL_KBD_SET1_UPBIT & 0xff);
+			key = hil_kbd_set3[key >> HIL_KBD_SET3_SHIFT];
+			if (key != KEY_RESERVED)
+				input_report_key(dev, key, !up);
+		}
+		break;
+	}
+ out:
+	kbd->idx4 = 0;
+	up(&kbd->sem);
+}
+
+static void hil_kbd_process_err(struct hil_kbd *kbd) {
+	printk(KERN_WARNING PREFIX "errored HIL packet\n");
+	kbd->idx4 = 0;
+	up(&kbd->sem);
+}
+
+static irqreturn_t hil_kbd_interrupt(struct serio *serio, 
+	      unsigned char data, unsigned int flags, struct pt_regs *regs)
+{
+	struct hil_kbd *kbd;
+	hil_packet packet;
+	int idx;
+
+	kbd = (struct hil_kbd *)serio->private;
+	if (kbd == NULL) {
+		BUG();
+		return IRQ_HANDLED;
+	}
+
+	if (kbd->idx4 >= (HIL_KBD_MAX_LENGTH * sizeof(hil_packet))) {
+		hil_kbd_process_err(kbd);
+		return IRQ_HANDLED;
+	}
+	idx = kbd->idx4/4;
+	if (!(kbd->idx4 % 4)) kbd->data[idx] = 0;
+	packet = kbd->data[idx];
+	packet |= ((hil_packet)data) << ((3 - (kbd->idx4 % 4)) * 8);
+	kbd->data[idx] = packet;
+
+	/* Records of N 4-byte hil_packets must terminate with a command. */
+	if ((++(kbd->idx4)) % 4) return IRQ_HANDLED;
+	if ((packet & 0xffff0000) != HIL_ERR_INT) {
+		hil_kbd_process_err(kbd);
+		return IRQ_HANDLED;
+	}
+	if (packet & HIL_PKT_CMD) hil_kbd_process_record(kbd);
+	return IRQ_HANDLED;
+}
+
+static void hil_kbd_disconnect(struct serio *serio)
+{
+	struct hil_kbd *kbd;
+
+	kbd = (struct hil_kbd *)serio->private;
+	if (kbd == NULL) {
+		BUG();
+		return;
+	}
+
+	input_unregister_device(&kbd->dev);
+	serio_close(serio);
+	kfree(kbd);
+}
+
+static void hil_kbd_connect(struct serio *serio, struct serio_driver *drv)
+{
+	struct hil_kbd	*kbd;
+	uint8_t		did, *idd;
+	int		i;
+	
+	if (serio->type != (SERIO_HIL_MLC | SERIO_HIL)) return;
+
+	if (!(kbd = kmalloc(sizeof(struct hil_kbd), GFP_KERNEL))) return;
+	memset(kbd, 0, sizeof(struct hil_kbd));
+
+	if (serio_open(serio, drv)) goto bail0;
+
+	serio->private = kbd;
+	kbd->serio = serio;
+	kbd->dev.private = kbd;
+
+	init_MUTEX_LOCKED(&(kbd->sem));
+
+	/* Get device info.  MLC driver supplies devid/status/etc. */
+	serio->write(serio, 0);
+	serio->write(serio, 0);
+	serio->write(serio, HIL_PKT_CMD >> 8);
+	serio->write(serio, HIL_CMD_IDD);
+	down(&(kbd->sem));
+
+	serio->write(serio, 0);
+	serio->write(serio, 0);
+	serio->write(serio, HIL_PKT_CMD >> 8);
+	serio->write(serio, HIL_CMD_RSC);
+	down(&(kbd->sem));
+
+	serio->write(serio, 0);
+	serio->write(serio, 0);
+	serio->write(serio, HIL_PKT_CMD >> 8);
+	serio->write(serio, HIL_CMD_RNM);
+	down(&(kbd->sem));
+
+	serio->write(serio, 0);
+	serio->write(serio, 0);
+	serio->write(serio, HIL_PKT_CMD >> 8);
+	serio->write(serio, HIL_CMD_EXD);
+	down(&(kbd->sem));
+
+	up(&(kbd->sem));
+
+	did = kbd->idd[0];
+	idd = kbd->idd + 1;
+	switch (did & HIL_IDD_DID_TYPE_MASK) {
+	case HIL_IDD_DID_TYPE_KB_INTEGRAL:
+	case HIL_IDD_DID_TYPE_KB_ITF:
+	case HIL_IDD_DID_TYPE_KB_RSVD:
+	case HIL_IDD_DID_TYPE_CHAR:
+		printk(KERN_INFO PREFIX "HIL keyboard found (did = 0x%02x, lang = %s)\n",
+			did, hil_language[did & HIL_IDD_DID_TYPE_KB_LANG_MASK]);
+		break;
+	default:
+		goto bail1;
+	}
+
+	if(HIL_IDD_NUM_BUTTONS(idd) || HIL_IDD_NUM_AXES_PER_SET(*idd)) {
+		printk(KERN_INFO PREFIX "keyboards only, no combo devices supported.\n");
+		goto bail1;
+	}
+
+
+	kbd->dev.evbit[0]	= BIT(EV_KEY) | BIT(EV_REP);
+	kbd->dev.ledbit[0]	= BIT(LED_NUML) | BIT(LED_CAPSL) | BIT(LED_SCROLLL);
+	kbd->dev.keycodemax	= HIL_KEYCODES_SET1_TBLSIZE;
+	kbd->dev.keycodesize	= sizeof(hil_kbd_set1[0]);
+	kbd->dev.keycode	= hil_kbd_set1;
+	kbd->dev.name		= strlen(kbd->rnm) ? kbd->rnm : HIL_GENERIC_NAME;
+	kbd->dev.phys		= "hpkbd/input0";	/* XXX */
+
+	kbd->dev.id.bustype	= BUS_HIL;
+	kbd->dev.id.vendor	= PCI_VENDOR_ID_HP;
+	kbd->dev.id.product	= 0x0001; /* TODO: get from kbd->rsc */
+	kbd->dev.id.version	= 0x0100; /* TODO: get from kbd->rsc */
+	kbd->dev.dev		= &serio->dev;
+
+	for (i = 0; i < 128; i++) {
+		set_bit(hil_kbd_set1[i], kbd->dev.keybit);
+		set_bit(hil_kbd_set3[i], kbd->dev.keybit);
+	}
+	clear_bit(0, kbd->dev.keybit);
+
+	input_register_device(&kbd->dev);
+	printk(KERN_INFO "input: %s, ID: %d\n",
+		kbd->dev.name, did);
+
+	serio->write(serio, 0);
+	serio->write(serio, 0);
+	serio->write(serio, HIL_PKT_CMD >> 8);
+	serio->write(serio, HIL_CMD_EK1); /* Enable Keyswitch Autorepeat 1 */
+	down(&(kbd->sem));
+	up(&(kbd->sem));
+
+	return;
+ bail1:
+	serio_close(serio);
+ bail0:
+	kfree(kbd);
+}
+
+
+struct serio_driver hil_kbd_serio_drv = {
+	.driver		= {
+		.name	= "hil_kbd",
+	},
+	.description	= "HP HIL keyboard driver",
+	.connect 	= hil_kbd_connect,
+	.disconnect 	= hil_kbd_disconnect,
+	.interrupt 	= hil_kbd_interrupt
+};
+
+static int __init hil_kbd_init(void)
+{
+	serio_register_driver(&hil_kbd_serio_drv);
+        return 0;
+}
+                
+static void __exit hil_kbd_exit(void)
+{
+	serio_unregister_driver(&hil_kbd_serio_drv);
+}
+                        
+module_init(hil_kbd_init);
+module_exit(hil_kbd_exit);
diff -Nru a/drivers/input/keyboard/hilkbd.c b/drivers/input/keyboard/hilkbd.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/input/keyboard/hilkbd.c	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,343 @@
+/*
+ *  linux/drivers/hil/hilkbd.c
+ *
+ *  Copyright (C) 1998 Philip Blundell <philb@gnu.org>
+ *  Copyright (C) 1999 Matthew Wilcox <willy@bofh.ai>
+ *  Copyright (C) 1999-2003 Helge Deller <deller@gmx.de>
+ *
+ *  Very basic HP Human Interface Loop (HIL) driver.
+ *  This driver handles the keyboard on HP300 (m68k) and on some 
+ *  HP700 (parisc) series machines.
+ *
+ * 
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License version 2.  See the file COPYING in the main directory of this
+ * archive for more details.
+ */
+
+#include <linux/pci_ids.h>
+#include <linux/ioport.h>
+#include <linux/module.h>
+#include <linux/config.h>
+#include <linux/errno.h>
+#include <linux/input.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/hil.h>
+#include <linux/spinlock.h>
+
+
+MODULE_AUTHOR("Philip Blundell, Matthew Wilcox, Helge Deller");
+MODULE_DESCRIPTION("HIL keyboard driver (basic functionality)");
+MODULE_LICENSE("GPL v2");
+
+
+#if defined(CONFIG_PARISC)
+
+ #include <asm/io.h>
+ #include <asm/hardware.h>
+ #include <asm/parisc-device.h>
+ static unsigned long hil_base;	/* HPA for the HIL device */
+ static unsigned int hil_irq;
+ #define HILBASE		hil_base /* HPPA (parisc) port address */
+ #define HIL_DATA		0x800
+ #define HIL_CMD		0x801
+ #define HIL_IRQ		hil_irq
+ #define hil_readb(p)		gsc_readb(p)
+ #define hil_writeb(v,p)	gsc_writeb((v),(p))
+
+#elif defined(CONFIG_HP300)
+
+ #define HILBASE		0xf0428000 /* HP300 (m86k) port address */
+ #define HIL_DATA		0x1
+ #define HIL_CMD		0x3
+ #define HIL_IRQ		2
+ #define hil_readb(p)		readb(p)
+ #define hil_writeb(v,p)	writeb((v),(p))
+
+#else
+#error "HIL is not supported on this platform"
+#endif
+
+
+ 
+/* HIL helper functions */
+ 
+#define hil_busy()              (hil_readb(HILBASE + HIL_CMD) & HIL_BUSY)
+#define hil_data_available()    (hil_readb(HILBASE + HIL_CMD) & HIL_DATA_RDY)
+#define hil_status()            (hil_readb(HILBASE + HIL_CMD))
+#define hil_command(x)          do { hil_writeb((x), HILBASE + HIL_CMD); } while (0)
+#define hil_read_data()         (hil_readb(HILBASE + HIL_DATA))
+#define hil_write_data(x)       do { hil_writeb((x), HILBASE + HIL_DATA); } while (0)
+
+/* HIL constants */
+ 
+#define	HIL_BUSY		0x02
+#define	HIL_DATA_RDY		0x01
+
+#define	HIL_SETARD		0xA0		/* set auto-repeat delay */
+#define	HIL_SETARR		0xA2		/* set auto-repeat rate */
+#define	HIL_SETTONE		0xA3		/* set tone generator */
+#define	HIL_CNMT		0xB2		/* clear nmi */
+#define	HIL_INTON		0x5C		/* Turn on interrupts. */
+#define	HIL_INTOFF		0x5D		/* Turn off interrupts. */
+
+#define	HIL_READKBDSADR	 	0xF9
+#define	HIL_WRITEKBDSADR 	0xE9
+
+static unsigned int hphilkeyb_keycode[HIL_KEYCODES_SET1_TBLSIZE] = 
+	{ HIL_KEYCODES_SET1 };
+
+/* HIL structure */
+static struct {
+	struct input_dev dev;
+
+	unsigned int curdev;
+	
+	unsigned char s;
+	unsigned char c;
+	int valid;
+	
+	unsigned char data[16];
+	unsigned int ptr;
+	spinlock_t lock;
+
+	void *dev_id;	/* native bus device */
+} hil_dev;
+
+
+static void poll_finished(void)
+{
+	int down;
+	int key;
+	unsigned char scode;
+	
+	switch (hil_dev.data[0]) {
+	case 0x40:
+		down = (hil_dev.data[1] & 1) == 0;
+		scode = hil_dev.data[1] >> 1;
+		key = hphilkeyb_keycode[scode];
+		input_report_key(&hil_dev.dev, key, down);
+		break;
+	}
+	hil_dev.curdev = 0;
+}
+
+static inline void handle_status(unsigned char s, unsigned char c)
+{
+	if (c & 0x8) {
+		/* End of block */
+		if (c & 0x10)
+			poll_finished();
+	} else {
+		if (c & 0x10) {
+			if (hil_dev.curdev)
+				poll_finished();  /* just in case */
+			hil_dev.curdev = c & 7;
+			hil_dev.ptr = 0;
+		}
+	}
+}
+
+static inline void handle_data(unsigned char s, unsigned char c)
+{
+	if (hil_dev.curdev) {
+		hil_dev.data[hil_dev.ptr++] = c;
+		hil_dev.ptr &= 15;
+	}
+}
+
+
+/* 
+ * Handle HIL interrupts.
+ */
+static irqreturn_t hil_interrupt(int irq, void *handle, struct pt_regs *regs)
+{
+	unsigned char s, c;
+	
+	s = hil_status();
+	c = hil_read_data();
+
+	switch (s >> 4) {
+	case 0x5:
+		handle_status(s, c);
+		break;
+	case 0x6:
+		handle_data(s, c);
+		break;
+	case 0x4:
+		hil_dev.s = s;
+		hil_dev.c = c;
+		mb();
+		hil_dev.valid = 1;
+		break;
+	}
+	return IRQ_HANDLED;
+}
+
+/*
+ * Send a command to the HIL
+ */
+
+static void hil_do(unsigned char cmd, unsigned char *data, unsigned int len)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&hil_dev.lock, flags);
+	while (hil_busy())
+		/* wait */;
+	hil_command(cmd);
+	while (len--) {
+		while (hil_busy())
+			/* wait */;
+		hil_write_data(*(data++));
+	}
+	spin_unlock_irqrestore(&hil_dev.lock, flags);
+}
+
+
+/*
+ * Initialise HIL. 
+ */
+
+static int __init
+hil_keyb_init(void)
+{
+	unsigned char c;
+	unsigned int i, kbid;
+	wait_queue_head_t hil_wait;
+
+	if (hil_dev.dev.id.bustype) {
+		return -ENODEV; /* already initialized */
+	}
+	
+#if defined(CONFIG_HP300)
+	if (!hwreg_present((void *)(HILBASE + HIL_DATA)))
+		return -ENODEV;
+	
+	request_region(HILBASE+HIL_DATA, 2, "hil");
+#endif
+	
+	request_irq(HIL_IRQ, hil_interrupt, 0, "hil", hil_dev.dev_id);
+
+	/* Turn on interrupts */
+	hil_do(HIL_INTON, NULL, 0);
+
+	/* Look for keyboards */
+	hil_dev.valid = 0;	/* clear any pending data */
+	hil_do(HIL_READKBDSADR, NULL, 0);
+
+	init_waitqueue_head(&hil_wait);
+	wait_event_interruptible_timeout(hil_wait, hil_dev.valid, 3*HZ);
+	if (!hil_dev.valid) {
+		printk(KERN_WARNING "HIL: timed out, assuming no keyboard present.\n");
+	}
+
+	c = hil_dev.c; 
+	hil_dev.valid = 0;
+	if (c == 0) {
+		kbid = -1;
+		printk(KERN_WARNING "HIL: no keyboard present.\n");
+	} else {
+		kbid = ffz(~c);
+		/* printk(KERN_INFO "HIL: keyboard found at id %d\n", kbid); */
+	}
+
+	/* set it to raw mode */
+	c = 0;
+	hil_do(HIL_WRITEKBDSADR, &c, 1);
+	
+	init_input_dev(&hil_dev.dev);
+
+	for (i = 0; i < HIL_KEYCODES_SET1_TBLSIZE; i++)
+		if (hphilkeyb_keycode[i] != KEY_RESERVED)
+			set_bit(hphilkeyb_keycode[i], hil_dev.dev.keybit);
+
+	hil_dev.dev.evbit[0]    = BIT(EV_KEY) | BIT(EV_REP);
+	hil_dev.dev.ledbit[0]   = BIT(LED_NUML) | BIT(LED_CAPSL) | BIT(LED_SCROLLL);
+	hil_dev.dev.keycodemax  = HIL_KEYCODES_SET1_TBLSIZE;
+        hil_dev.dev.keycodesize = sizeof(hphilkeyb_keycode[0]);
+	hil_dev.dev.keycode     = hphilkeyb_keycode;
+	hil_dev.dev.name 	= "HIL keyboard";
+	hil_dev.dev.phys 	= "hpkbd/input0";
+
+	hil_dev.dev.id.bustype	= BUS_HIL;
+	hil_dev.dev.id.vendor	= PCI_VENDOR_ID_HP;
+	hil_dev.dev.id.product	= 0x0001;
+	hil_dev.dev.id.version	= 0x0010;
+
+	input_register_device(&hil_dev.dev);
+	printk(KERN_INFO "input: %s, ID %d at 0x%08lx (irq %d) found and attached\n",
+		hil_dev.dev.name, kbid, HILBASE, HIL_IRQ);
+
+	return 0;
+}
+
+#if defined(CONFIG_PARISC)
+static int __init
+hil_init_chip(struct parisc_device *dev)
+{
+	if (!dev->irq) {
+		printk(KERN_WARNING "HIL: IRQ not found for HIL bus at 0x%08lx\n", dev->hpa);
+		return -ENODEV;
+	}
+
+	hil_base = dev->hpa;
+	hil_irq  = dev->irq;
+	hil_dev.dev_id = dev;
+	
+	printk(KERN_INFO "Found HIL bus at 0x%08lx, IRQ %d\n", hil_base, hil_irq);
+
+	return hil_keyb_init();
+}
+
+static struct parisc_device_id hil_tbl[] = {
+	{ HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x00073 },
+	{ 0, }
+};
+
+MODULE_DEVICE_TABLE(parisc, hil_tbl);
+
+static struct parisc_driver hil_driver = {
+	.name =		"HIL",
+	.id_table =	hil_tbl,
+	.probe =	hil_init_chip,
+};
+#endif /* CONFIG_PARISC */
+
+
+
+
+
+static int __init hil_init(void)
+{
+#if defined(CONFIG_PARISC)
+	return register_parisc_driver(&hil_driver);
+#else
+	return hil_keyb_init();
+#endif
+}
+
+
+static void __exit hil_exit(void)
+{
+	if (HIL_IRQ) {
+		disable_irq(HIL_IRQ);
+		free_irq(HIL_IRQ, hil_dev.dev_id);
+	}
+
+	/* Turn off interrupts */
+	hil_do(HIL_INTOFF, NULL, 0);
+
+	input_unregister_device(&hil_dev.dev);
+
+#if defined(CONFIG_PARISC)
+	unregister_parisc_driver(&hil_driver);
+#else
+	release_region(HILBASE+HIL_DATA, 2);
+#endif
+}
+
+module_init(hil_init);
+module_exit(hil_exit);
+
diff -Nru a/drivers/input/keyboard/hpps2atkbd.h b/drivers/input/keyboard/hpps2atkbd.h
--- a/drivers/input/keyboard/hpps2atkbd.h	2005-03-11 12:51:41 -08:00
+++ b/drivers/input/keyboard/hpps2atkbd.h	2005-03-11 12:51:41 -08:00
@@ -14,10 +14,8 @@
  */
 
 
-/* undefine if you have a RDI PRECISIONBOOK */
-#define STANDARD_KEYBOARD
-
-#if defined(STANDARD_KEYBOARD)
+/* Is the keyboard an RDI PrecisionBook? */
+#ifndef CONFIG_KEYBOARD_ATKBD_RDI_KEYCODES
 # define CONFLICT(x,y) x
 #else
 # define CONFLICT(x,y) y
@@ -50,10 +48,10 @@
 /* 60 */  KEY_DOWN,     C_61,          KEY_PAUSE,     KEY_UP,        KEY_DELETE,    KEY_END,      KEY_BACKSPACE, KEY_INSERT,
 /* 68 */  KEY_RESERVED, KEY_KP1,       KEY_RIGHT,     KEY_KP4,       KEY_KP7,       KEY_PAGEDOWN, KEY_HOME,      KEY_PAGEUP,
 /* 70 */  KEY_KP0,      KEY_KPDOT,     KEY_KP2,       KEY_KP5,       KEY_KP6,       KEY_KP8,      KEY_ESC,       KEY_NUMLOCK,
-/* 78 */  KEY_F11,      KEY_KPPLUS,    KEY_KP3,       KEY_KPMINUS,   KEY_KPASTERISK,KEY_KP9,      KEY_SCROLLLOCK,KEY_103RD,
+/* 78 */  KEY_F11,      KEY_KPPLUS,    KEY_KP3,       KEY_KPMINUS,   KEY_KPASTERISK,KEY_KP9,      KEY_SCROLLLOCK,KEY_102ND,
 /* 80 */  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,
 /* 88 */  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,
-/* 90 */  KEY_RESERVED, KEY_RIGHTALT,  KEY_SYSRQ,     KEY_RESERVED,  KEY_RIGHTCTRL, KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,
+/* 90 */  KEY_RESERVED, KEY_RIGHTALT,  255,           KEY_RESERVED,  KEY_RIGHTCTRL, KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,
 /* 98 */  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_CAPSLOCK, KEY_RESERVED,  KEY_LEFTMETA,
 /* a0 */  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED, KEY_RESERVED,  KEY_RIGHTMETA,
 /* a8 */  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED, KEY_RESERVED,  KEY_COMPOSE,
@@ -103,7 +101,6 @@
 /* f0 */  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,
 /* f8 */  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED
 
-#undef STANDARD_KEYBOARD
 #undef CONFLICT
 #undef C_07
 #undef C_11
diff -Nru a/drivers/input/keyboard/lkkbd.c b/drivers/input/keyboard/lkkbd.c
--- a/drivers/input/keyboard/lkkbd.c	2005-03-11 12:51:41 -08:00
+++ b/drivers/input/keyboard/lkkbd.c	2005-03-11 12:51:41 -08:00
@@ -14,14 +14,14 @@
  * DISCLAIMER: This works for _me_. If you break anything by using the
  * information given below, I will _not_ be liable!
  *
- * RJ11 pinout:		To DE9:		Or DB25:
+ * RJ10 pinout:		To DE9:		Or DB25:
  * 	1 - RxD <---->	Pin 3 (TxD) <->	Pin 2 (TxD)
  * 	2 - GND <---->	Pin 5 (GND) <->	Pin 7 (GND)
  * 	4 - TxD <---->	Pin 2 (RxD) <->	Pin 3 (RxD)
  * 	3 - +12V (from HDD drive connector), DON'T connect to DE9 or DB25!!!
  *
  * Pin numbers for DE9 and DB25 are noted on the plug (quite small:). For
- * RJ11, it's like this:
+ * RJ10, it's like this:
  *
  *      __=__	Hold the plug in front of you, cable downwards,
  *     /___/|	nose is hidden behind the plug. Now, pin 1 is at
@@ -417,7 +417,7 @@
 lkkbd_interrupt (struct serio *serio, unsigned char data, unsigned int flags,
 		struct pt_regs *regs)
 {
-	struct lkkbd *lk = serio->private;
+	struct lkkbd *lk = serio_get_drvdata (serio);
 	int i;
 
 	DBG (KERN_INFO "Got byte 0x%02x\n", data);
@@ -623,19 +623,16 @@
 /*
  * lkkbd_connect() probes for a LK keyboard and fills the necessary structures.
  */
-static void
+static int
 lkkbd_connect (struct serio *serio, struct serio_driver *drv)
 {
 	struct lkkbd *lk;
 	int i;
-
-	if ((serio->type & SERIO_TYPE) != SERIO_RS232)
-		return;
-	if ((serio->type & SERIO_PROTO) != SERIO_LKKBD)
-		return;
+	int err;
 
 	if (!(lk = kmalloc (sizeof (struct lkkbd), GFP_KERNEL)))
-		return;
+		return -ENOMEM;
+
 	memset (lk, 0, sizeof (struct lkkbd));
 
 	init_input_dev (&lk->dev);
@@ -665,11 +662,13 @@
 	lk->dev.event = lkkbd_event;
 	lk->dev.private = lk;
 
-	serio->private = lk;
+	serio_set_drvdata (serio, lk);
 
-	if (serio_open (serio, drv)) {
+	err = serio_open (serio, drv);
+	if (err) {
+		serio_set_drvdata (serio, NULL);
 		kfree (lk);
-		return;
+		return err;
 	}
 
 	sprintf (lk->name, "DEC LK keyboard");
@@ -691,6 +690,8 @@
 
 	printk (KERN_INFO "input: %s on %s, initiating reset\n", lk->name, serio->phys);
 	lk->serio->write (lk->serio, LK_CMD_POWERCYCLE_RESET);
+
+	return 0;
 }
 
 /*
@@ -699,18 +700,32 @@
 static void
 lkkbd_disconnect (struct serio *serio)
 {
-	struct lkkbd *lk = serio->private;
+	struct lkkbd *lk = serio_get_drvdata (serio);
 
 	input_unregister_device (&lk->dev);
 	serio_close (serio);
+	serio_set_drvdata (serio, NULL);
 	kfree (lk);
 }
 
+static struct serio_device_id lkkbd_serio_ids[] = {
+	{
+		.type	= SERIO_RS232,
+		.proto	= SERIO_LKKBD,
+		.id	= SERIO_ANY,
+		.extra	= SERIO_ANY,
+	},
+	{ 0 }
+};
+
+MODULE_DEVICE_TABLE(serio, lkkbd_serio_ids);
+
 static struct serio_driver lkkbd_drv = {
 	.driver		= {
 		.name	= "lkkbd",
 	},
 	.description	= DRIVER_DESC,
+	.id_table	= lkkbd_serio_ids,
 	.connect	= lkkbd_connect,
 	.disconnect	= lkkbd_disconnect,
 	.interrupt	= lkkbd_interrupt,
@@ -719,14 +734,14 @@
 /*
  * The functions for insering/removing us as a module.
  */
-int __init
+static int __init
 lkkbd_init (void)
 {
 	serio_register_driver(&lkkbd_drv);
 	return 0;
 }
 
-void __exit
+static void __exit
 lkkbd_exit (void)
 {
 	serio_unregister_driver(&lkkbd_drv);
diff -Nru a/drivers/input/keyboard/locomokbd.c b/drivers/input/keyboard/locomokbd.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/input/keyboard/locomokbd.c	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,309 @@
+/*
+ *  Copyright (c) 2005 John Lenz
+ *
+ * Based on from xtkbd.c
+ */
+
+/*
+ * LoCoMo keyboard driver for Linux/ARM
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/input.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+
+#include <asm/hardware/locomo.h>
+#include <asm/irq.h>
+
+MODULE_AUTHOR("John Lenz <lenz@cs.wisc.edu>");
+MODULE_DESCRIPTION("LoCoMo keyboard driver");
+MODULE_LICENSE("GPL");
+
+#define LOCOMOKBD_NUMKEYS 	128
+
+#define KEY_ACTIVITY		KEY_F16
+#define KEY_CONTACT		KEY_F18
+#define KEY_CENTER		KEY_F15
+
+static unsigned char locomokbd_keycode[LOCOMOKBD_NUMKEYS] = {
+	0, KEY_ESC, KEY_ACTIVITY, 0, 0, 0, 0, 0, 0, 0,				/* 0 - 9 */
+	0, 0, 0, 0, 0, 0, 0, KEY_MENU, KEY_HOME, KEY_CONTACT,			/* 10 - 19 */
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0,						/* 20 - 29 */
+	0, 0, 0, KEY_CENTER, 0, KEY_MAIL, 0, 0, 0, 0,				/* 30 - 39 */
+	0, 0, 0, 0, 0, 0, 0, 0, 0, KEY_RIGHT,					/* 40 - 49 */
+	KEY_UP, KEY_LEFT, 0, 0, KEY_P, 0, KEY_O, KEY_I, KEY_Y, KEY_T,		/* 50 - 59 */
+	KEY_E, KEY_W, 0, 0, 0, 0, KEY_DOWN, KEY_ENTER, 0, 0,			/* 60 - 69 */
+	KEY_BACKSPACE, 0, KEY_L, KEY_U, KEY_H, KEY_R, KEY_D, KEY_Q, 0, 0,	/* 70 - 79 */
+	0, 0, 0, 0, 0, 0, KEY_ENTER, KEY_RIGHTSHIFT, KEY_K, KEY_J,		/* 80 - 89 */
+	KEY_G, KEY_F, KEY_X, KEY_S, 0, 0, 0, 0, 0, 0,				/* 90 - 99 */
+	0, 0, KEY_DOT, 0, KEY_COMMA, KEY_N, KEY_B, KEY_C, KEY_Z, KEY_A,		/* 100 - 109 */
+	KEY_LEFTSHIFT, KEY_TAB, KEY_LEFTCTRL, 0, 0, 0, 0, 0, 0, 0,		/* 110 - 119 */
+	KEY_M, KEY_SPACE, KEY_V, KEY_APOSTROPHE, KEY_SLASH, 0, 0, 0 		/* 120 - 128 */
+};
+
+#define KB_ROWS			16
+#define KB_COLS			8
+#define KB_ROWMASK(r)		(1 << (r))
+#define SCANCODE(c,r)		( ((c)<<4) + (r) + 1 )
+#define	NR_SCANCODES		128
+
+#define KB_DELAY		8
+#define SCAN_INTERVAL		(HZ/10)
+#define LOCOMOKBD_PRESSED	1
+
+struct locomokbd {
+	unsigned char keycode[LOCOMOKBD_NUMKEYS];
+	struct input_dev input;
+	char phys[32];
+
+	struct locomo_dev *ldev;
+	unsigned long base;
+	spinlock_t lock;
+	
+	struct timer_list timer;
+};
+
+/* helper functions for reading the keyboard matrix */
+static inline void locomokbd_charge_all(unsigned long membase)
+{
+	locomo_writel(0x00FF, membase + LOCOMO_KSC);
+}
+
+static inline void locomokbd_activate_all(unsigned long membase)
+{
+	unsigned long r;
+	
+	locomo_writel(0, membase + LOCOMO_KSC);
+	r = locomo_readl(membase + LOCOMO_KIC);
+	r &= 0xFEFF;
+	locomo_writel(r, membase + LOCOMO_KIC);
+}
+
+static inline void locomokbd_activate_col(unsigned long membase, int col)
+{
+	unsigned short nset;
+	unsigned short nbset;
+
+	nset = 0xFF & ~(1 << col);
+	nbset = (nset << 8) + nset;
+	locomo_writel(nbset, membase + LOCOMO_KSC);
+}
+
+static inline void locomokbd_reset_col(unsigned long membase, int col)
+{
+	unsigned short nbset;
+
+	nbset = ((0xFF & ~(1 << col)) << 8) + 0xFF;
+	locomo_writel(nbset, membase + LOCOMO_KSC);
+}
+
+/*
+ * The LoCoMo keyboard only generates interrupts when a key is pressed.
+ * So when a key is pressed, we enable a timer.  This timer scans the
+ * keyboard, and this is how we detect when the key is released.
+ */
+
+/* Scan the hardware keyboard and push any changes up through the input layer */
+static void locomokbd_scankeyboard(struct locomokbd *locomokbd, struct pt_regs *regs) 
+{
+	unsigned int row, col, rowd, scancode;
+	unsigned long flags;
+	unsigned int num_pressed;
+	unsigned long membase = locomokbd->base;
+
+	spin_lock_irqsave(&locomokbd->lock, flags);
+
+	if (regs)
+		input_regs(&locomokbd->input, regs);
+	
+	locomokbd_charge_all(membase);
+
+	num_pressed = 0;
+	for (col = 0; col < KB_COLS; col++) {
+
+		locomokbd_activate_col(membase, col);
+		udelay(KB_DELAY);
+		 
+		rowd = ~locomo_readl(membase + LOCOMO_KIB);
+		for (row = 0; row < KB_ROWS; row++ ) {
+			scancode = SCANCODE(col, row);
+			if (rowd & KB_ROWMASK(row)) {
+				num_pressed += 1;
+				input_report_key(&locomokbd->input, locomokbd->keycode[scancode], 1);
+			} else {
+				input_report_key(&locomokbd->input, locomokbd->keycode[scancode], 0);
+			}
+		}
+		locomokbd_reset_col(membase, col);
+	}
+	locomokbd_activate_all(membase);
+
+	input_sync(&locomokbd->input);
+
+	/* if any keys are pressed, enable the timer */
+	if (num_pressed)
+		mod_timer(&locomokbd->timer, jiffies + SCAN_INTERVAL);
+
+	spin_unlock_irqrestore(&locomokbd->lock, flags);
+}
+
+/* 
+ * LoCoMo keyboard interrupt handler.
+ */
+static irqreturn_t locomokbd_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+	struct locomokbd *locomokbd = dev_id;
+	/** wait chattering delay **/
+	udelay(100);
+
+	locomokbd_scankeyboard(locomokbd, regs);
+
+	return IRQ_HANDLED;
+}
+
+/*
+ * LoCoMo timer checking for released keys
+ */
+static void locomokbd_timer_callback(unsigned long data)
+{
+	struct locomokbd *locomokbd = (struct locomokbd *) data;
+	locomokbd_scankeyboard(locomokbd, NULL);
+}
+
+static int locomokbd_probe(struct locomo_dev *dev)
+{
+	struct locomokbd *locomokbd;
+	int i, ret;
+
+	locomokbd = kmalloc(sizeof(struct locomokbd), GFP_KERNEL);
+	if (!locomokbd)
+		return -ENOMEM;
+
+	memset(locomokbd, 0, sizeof(struct locomokbd));
+
+	/* try and claim memory region */
+	if (!request_mem_region((unsigned long) dev->mapbase, 
+				dev->length, 
+				LOCOMO_DRIVER_NAME(dev))) {
+		ret = -EBUSY;
+		printk(KERN_ERR "locomokbd: Can't acquire access to io memory for keyboard\n");
+		goto free;
+	}
+
+	locomokbd->ldev = dev;
+	locomo_set_drvdata(dev, locomokbd);
+
+	locomokbd->base = (unsigned long) dev->mapbase;
+
+	spin_lock_init(&locomokbd->lock);
+
+	init_timer(&locomokbd->timer);
+	locomokbd->timer.function = locomokbd_timer_callback;
+	locomokbd->timer.data = (unsigned long) locomokbd;
+
+	locomokbd->input.evbit[0] = BIT(EV_KEY) | BIT(EV_REP);
+	
+	init_input_dev(&locomokbd->input);
+	locomokbd->input.keycode = locomokbd->keycode;
+	locomokbd->input.keycodesize = sizeof(unsigned char);
+	locomokbd->input.keycodemax = ARRAY_SIZE(locomokbd_keycode);
+	locomokbd->input.private = locomokbd;
+
+	memcpy(locomokbd->keycode, locomokbd_keycode, sizeof(locomokbd->keycode));
+	for (i = 0; i < LOCOMOKBD_NUMKEYS; i++)
+		set_bit(locomokbd->keycode[i], locomokbd->input.keybit);
+	clear_bit(0, locomokbd->input.keybit);
+
+	strcpy(locomokbd->phys, "locomokbd/input0");
+
+	locomokbd->input.name = "LoCoMo keyboard";
+	locomokbd->input.phys = locomokbd->phys;
+	locomokbd->input.id.bustype = BUS_XTKBD;
+	locomokbd->input.id.vendor = 0x0001;
+	locomokbd->input.id.product = 0x0001;
+	locomokbd->input.id.version = 0x0100;
+
+	/* attempt to get the interrupt */
+	ret = request_irq(dev->irq[0], locomokbd_interrupt, 0, "locomokbd", locomokbd);
+	if (ret) {
+		printk(KERN_ERR "locomokbd: Can't get irq for keyboard\n");
+		goto out;
+	}
+
+	input_register_device(&locomokbd->input);
+
+	printk(KERN_INFO "input: LoCoMo keyboard on locomokbd\n");
+
+	return 0;
+
+out:
+	release_mem_region((unsigned long) dev->mapbase, dev->length);
+	locomo_set_drvdata(dev, NULL);
+free:
+	kfree(locomokbd);
+
+	return ret;
+}
+
+static int locomokbd_remove(struct locomo_dev *dev)
+{
+	struct locomokbd *locomokbd = locomo_get_drvdata(dev);
+	
+	free_irq(dev->irq[0], locomokbd);
+
+	del_timer_sync(&locomokbd->timer);
+	
+	input_unregister_device(&locomokbd->input);
+	locomo_set_drvdata(dev, NULL);
+
+	release_mem_region((unsigned long) dev->mapbase, dev->length);
+
+	kfree(locomokbd);
+
+	return 0;
+}
+
+static struct locomo_driver keyboard_driver = {
+	.drv = {
+		.name = "locomokbd"
+	},
+	.devid	= LOCOMO_DEVID_KEYBOARD,
+	.probe	= locomokbd_probe,
+	.remove	= locomokbd_remove,
+};
+
+static int __init locomokbd_init(void)
+{
+	return locomo_driver_register(&keyboard_driver);
+}
+
+static void __exit locomokbd_exit(void)
+{
+	locomo_driver_unregister(&keyboard_driver);
+}
+
+module_init(locomokbd_init);
+module_exit(locomokbd_exit);
diff -Nru a/drivers/input/keyboard/newtonkbd.c b/drivers/input/keyboard/newtonkbd.c
--- a/drivers/input/keyboard/newtonkbd.c	2005-03-11 12:51:52 -08:00
+++ b/drivers/input/keyboard/newtonkbd.c	2005-03-11 12:51:52 -08:00
@@ -66,10 +66,10 @@
 	char phys[32];
 };
 
-irqreturn_t nkbd_interrupt(struct serio *serio,
+static irqreturn_t nkbd_interrupt(struct serio *serio,
 		unsigned char data, unsigned int flags, struct pt_regs *regs)
 {
-	struct nkbd *nkbd = serio->private;
+	struct nkbd *nkbd = serio_get_drvdata(serio);
 
 	/* invalid scan codes are probably the init sequence, so we ignore them */
 	if (nkbd->keycode[data & NKBD_KEY]) {
@@ -84,16 +84,14 @@
 
 }
 
-void nkbd_connect(struct serio *serio, struct serio_driver *drv)
+static int nkbd_connect(struct serio *serio, struct serio_driver *drv)
 {
 	struct nkbd *nkbd;
 	int i;
-
-	if (serio->type != (SERIO_RS232 | SERIO_NEWTON))
-		return;
+	int err;
 
 	if (!(nkbd = kmalloc(sizeof(struct nkbd), GFP_KERNEL)))
-		return;
+		return -ENOMEM;
 
 	memset(nkbd, 0, sizeof(struct nkbd));
 
@@ -106,11 +104,14 @@
 	nkbd->dev.keycodesize = sizeof(unsigned char);
 	nkbd->dev.keycodemax = ARRAY_SIZE(nkbd_keycode);
 	nkbd->dev.private = nkbd;
-	serio->private = nkbd;
 
-	if (serio_open(serio, drv)) {
+	serio_set_drvdata(serio, nkbd);
+
+	err = serio_open(serio, drv);
+	if (err) {
+		serio_set_drvdata(serio, NULL);
 		kfree(nkbd);
-		return;
+		return err;
 	}
 
 	memcpy(nkbd->keycode, nkbd_keycode, sizeof(nkbd->keycode));
@@ -131,33 +132,50 @@
 	input_register_device(&nkbd->dev);
 
 	printk(KERN_INFO "input: %s on %s\n", nkbd_name, serio->phys);
+
+	return 0;
 }
 
-void nkbd_disconnect(struct serio *serio)
+static void nkbd_disconnect(struct serio *serio)
 {
-	struct nkbd *nkbd = serio->private;
+	struct nkbd *nkbd = serio_get_drvdata(serio);
+
 	input_unregister_device(&nkbd->dev);
 	serio_close(serio);
+	serio_set_drvdata(serio, NULL);
 	kfree(nkbd);
 }
 
-struct serio_driver nkbd_drv = {
+static struct serio_device_id nkbd_serio_ids[] = {
+	{
+		.type	= SERIO_RS232,
+		.proto	= SERIO_NEWTON,
+		.id	= SERIO_ANY,
+		.extra	= SERIO_ANY,
+	},
+	{ 0 }
+};
+
+MODULE_DEVICE_TABLE(serio, nkbd_serio_ids);
+
+static struct serio_driver nkbd_drv = {
 	.driver		= {
 		.name	= "newtonkbd",
 	},
 	.description	= DRIVER_DESC,
+	.id_table	= nkbd_serio_ids,
 	.interrupt	= nkbd_interrupt,
 	.connect	= nkbd_connect,
 	.disconnect	= nkbd_disconnect,
 };
 
-int __init nkbd_init(void)
+static int __init nkbd_init(void)
 {
 	serio_register_driver(&nkbd_drv);
 	return 0;
 }
 
-void __exit nkbd_exit(void)
+static void __exit nkbd_exit(void)
 {
 	serio_unregister_driver(&nkbd_drv);
 }
diff -Nru a/drivers/input/keyboard/sunkbd.c b/drivers/input/keyboard/sunkbd.c
--- a/drivers/input/keyboard/sunkbd.c	2005-03-11 12:51:52 -08:00
+++ b/drivers/input/keyboard/sunkbd.c	2005-03-11 12:51:52 -08:00
@@ -95,7 +95,7 @@
 static irqreturn_t sunkbd_interrupt(struct serio *serio,
 		unsigned char data, unsigned int flags, struct pt_regs *regs)
 {
-	struct sunkbd* sunkbd = serio->private;
+	struct sunkbd* sunkbd = serio_get_drvdata(serio);
 
 	if (sunkbd->reset <= -1) {		/* If cp[i] is 0xff, sunkbd->reset will stay -1. */
 		sunkbd->reset = data;		/* The keyboard sends 0xff 0xff 0xID on powerup */
@@ -223,19 +223,14 @@
  * sunkbd_connect() probes for a Sun keyboard and fills the necessary structures.
  */
 
-static void sunkbd_connect(struct serio *serio, struct serio_driver *drv)
+static int sunkbd_connect(struct serio *serio, struct serio_driver *drv)
 {
 	struct sunkbd *sunkbd;
 	int i;
-
-	if ((serio->type & SERIO_TYPE) != SERIO_RS232)
-		return;
-
-	if ((serio->type & SERIO_PROTO) && (serio->type & SERIO_PROTO) != SERIO_SUNKBD)
-		return;
+	int err;
 
 	if (!(sunkbd = kmalloc(sizeof(struct sunkbd), GFP_KERNEL)))
-		return;
+		return -ENOMEM;
 
 	memset(sunkbd, 0, sizeof(struct sunkbd));
 
@@ -257,17 +252,20 @@
 	sunkbd->dev.event = sunkbd_event;
 	sunkbd->dev.private = sunkbd;
 
-	serio->private = sunkbd;
+	serio_set_drvdata(serio, sunkbd);
 
-	if (serio_open(serio, drv)) {
+	err = serio_open(serio, drv);
+	if (err) {
+		serio_set_drvdata(serio, NULL);
 		kfree(sunkbd);
-		return;
+		return err;
 	}
 
 	if (sunkbd_initialize(sunkbd) < 0) {
 		serio_close(serio);
+		serio_set_drvdata(serio, NULL);
 		kfree(sunkbd);
-		return;
+		return -ENODEV;
 	}
 
 	sprintf(sunkbd->name, "Sun Type %d keyboard", sunkbd->type);
@@ -290,6 +288,8 @@
 	input_register_device(&sunkbd->dev);
 
 	printk(KERN_INFO "input: %s on %s\n", sunkbd->name, serio->phys);
+
+	return 0;
 }
 
 /*
@@ -298,17 +298,37 @@
 
 static void sunkbd_disconnect(struct serio *serio)
 {
-	struct sunkbd *sunkbd = serio->private;
+	struct sunkbd *sunkbd = serio_get_drvdata(serio);
 	input_unregister_device(&sunkbd->dev);
 	serio_close(serio);
+	serio_set_drvdata(serio, NULL);
 	kfree(sunkbd);
 }
 
+static struct serio_device_id sunkbd_serio_ids[] = {
+	{
+		.type	= SERIO_RS232,
+		.proto	= SERIO_SUNKBD,
+		.id	= SERIO_ANY,
+		.extra	= SERIO_ANY,
+	},
+	{
+		.type	= SERIO_RS232,
+		.proto	= SERIO_UNKNOWN, /* sunkbd does probe */
+		.id	= SERIO_ANY,
+		.extra	= SERIO_ANY,
+	},
+	{ 0 }
+};
+
+MODULE_DEVICE_TABLE(serio, sunkbd_serio_ids);
+
 static struct serio_driver sunkbd_drv = {
 	.driver		= {
 		.name	= "sunkbd",
 	},
 	.description	= DRIVER_DESC,
+	.id_table	= sunkbd_serio_ids,
 	.interrupt	= sunkbd_interrupt,
 	.connect	= sunkbd_connect,
 	.disconnect	= sunkbd_disconnect,
@@ -318,13 +338,13 @@
  * The functions for insering/removing us as a module.
  */
 
-int __init sunkbd_init(void)
+static int __init sunkbd_init(void)
 {
 	serio_register_driver(&sunkbd_drv);
 	return 0;
 }
 
-void __exit sunkbd_exit(void)
+static void __exit sunkbd_exit(void)
 {
 	serio_unregister_driver(&sunkbd_drv);
 }
diff -Nru a/drivers/input/keyboard/xtkbd.c b/drivers/input/keyboard/xtkbd.c
--- a/drivers/input/keyboard/xtkbd.c	2005-03-11 12:51:46 -08:00
+++ b/drivers/input/keyboard/xtkbd.c	2005-03-11 12:51:46 -08:00
@@ -65,10 +65,10 @@
 	char phys[32];
 };
 
-irqreturn_t xtkbd_interrupt(struct serio *serio,
+static irqreturn_t xtkbd_interrupt(struct serio *serio,
 	unsigned char data, unsigned int flags, struct pt_regs *regs)
 {
-	struct xtkbd *xtkbd = serio->private;
+	struct xtkbd *xtkbd = serio_get_drvdata(serio);
 
 	switch (data) {
 		case XTKBD_EMUL0:
@@ -88,16 +88,14 @@
 	return IRQ_HANDLED;
 }
 
-void xtkbd_connect(struct serio *serio, struct serio_driver *drv)
+static int xtkbd_connect(struct serio *serio, struct serio_driver *drv)
 {
 	struct xtkbd *xtkbd;
 	int i;
-
-	if ((serio->type & SERIO_TYPE) != SERIO_XT)
-		return;
+	int err;
 
 	if (!(xtkbd = kmalloc(sizeof(struct xtkbd), GFP_KERNEL)))
-		return;
+		return -ENOMEM;
 
 	memset(xtkbd, 0, sizeof(struct xtkbd));
 
@@ -111,11 +109,13 @@
 	xtkbd->dev.keycodemax = ARRAY_SIZE(xtkbd_keycode);
 	xtkbd->dev.private = xtkbd;
 
-	serio->private = xtkbd;
+	serio_set_drvdata(serio, xtkbd);
 
-	if (serio_open(serio, drv)) {
+	err = serio_open(serio, drv);
+	if (err) {
+		serio_set_drvdata(serio, NULL);
 		kfree(xtkbd);
-		return;
+		return err;
 	}
 
 	memcpy(xtkbd->keycode, xtkbd_keycode, sizeof(xtkbd->keycode));
@@ -136,33 +136,50 @@
 	input_register_device(&xtkbd->dev);
 
 	printk(KERN_INFO "input: %s on %s\n", xtkbd_name, serio->phys);
+
+	return 0;
 }
 
-void xtkbd_disconnect(struct serio *serio)
+static void xtkbd_disconnect(struct serio *serio)
 {
-	struct xtkbd *xtkbd = serio->private;
+	struct xtkbd *xtkbd = serio_get_drvdata(serio);
+
 	input_unregister_device(&xtkbd->dev);
 	serio_close(serio);
+	serio_set_drvdata(serio, NULL);
 	kfree(xtkbd);
 }
 
-struct serio_driver xtkbd_drv = {
+static struct serio_device_id xtkbd_serio_ids[] = {
+	{
+		.type	= SERIO_XT,
+		.proto	= SERIO_ANY,
+		.id	= SERIO_ANY,
+		.extra	= SERIO_ANY,
+	},
+	{ 0 }
+};
+
+MODULE_DEVICE_TABLE(serio, xtkbd_serio_ids);
+
+static struct serio_driver xtkbd_drv = {
 	.driver		= {
 		.name	= "xtkbd",
 	},
 	.description	= DRIVER_DESC,
+	.id_table	= xtkbd_serio_ids,
 	.interrupt	= xtkbd_interrupt,
 	.connect	= xtkbd_connect,
 	.disconnect	= xtkbd_disconnect,
 };
 
-int __init xtkbd_init(void)
+static int __init xtkbd_init(void)
 {
 	serio_register_driver(&xtkbd_drv);
 	return 0;
 }
 
-void __exit xtkbd_exit(void)
+static void __exit xtkbd_exit(void)
 {
 	serio_unregister_driver(&xtkbd_drv);
 }
diff -Nru a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
--- a/drivers/input/misc/Kconfig	2005-03-11 12:51:42 -08:00
+++ b/drivers/input/misc/Kconfig	2005-03-11 12:51:42 -08:00
@@ -1,9 +1,8 @@
 #
 # Input misc drivers configuration
 #
-config INPUT_MISC
-	bool "Misc"
-	depends on INPUT
+menuconfig INPUT_MISC
+	bool "Miscellaneous devices"
 	help
 	  Say Y here, and a list of miscellaneous input drivers will be displayed.
 	  Everything that didn't fit into the other categories is here. This option
@@ -11,9 +10,11 @@
 
 	  If unsure, say Y.
 
+if INPUT_MISC
+
 config INPUT_PCSPKR
 	tristate "PC Speaker support"
-	depends on (ALPHA || X86 || X86_64 || MIPS || PPC_PREP || PPC_CHRP || PPC_PSERIES) && INPUT && INPUT_MISC
+	depends on ALPHA || X86 || X86_64 || MIPS || PPC_PREP || PPC_CHRP || PPC_PSERIES
 	help
 	  Say Y here if you want the standard PC Speaker to be used for
 	  bells and whistles.
@@ -25,7 +26,7 @@
 
 config INPUT_SPARCSPKR
 	tristate "SPARC Speaker support"
-	depends on (SPARC32 || SPARC64) && INPUT && INPUT_MISC && PCI
+	depends on PCI && (SPARC32 || SPARC64)
 	help
 	  Say Y here if you want the standard Speaker on Sparc PCI systems
 	  to be used for bells and whistles.
@@ -37,11 +38,10 @@
 
 config INPUT_M68K_BEEP
 	tristate "M68k Beeper support"
-	depends on M68K && INPUT && INPUT_MISC
+	depends on M68K
 
 config INPUT_UINPUT
 	tristate "User level driver support"
-	depends on INPUT && INPUT_MISC
 	help
 	  Say Y here if you want to support user level drivers for input
 	  subsystem accessible under char device 10:223 - /dev/input/uinput.
@@ -49,3 +49,12 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called uinput.
 
+config HP_SDC_RTC
+	tristate "HP SDC Real Time Clock"       
+	depends on GSC
+	select HP_SDC
+	help
+	  Say Y here if you want to support the built-in real time clock
+	  of the HP SDC controller.
+
+endif
diff -Nru a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile
--- a/drivers/input/misc/Makefile	2005-03-11 12:51:47 -08:00
+++ b/drivers/input/misc/Makefile	2005-03-11 12:51:47 -08:00
@@ -9,3 +9,4 @@
 obj-$(CONFIG_INPUT_M68K_BEEP)		+= m68kspkr.o
 obj-$(CONFIG_INPUT_98SPKR)		+= 98spkr.o
 obj-$(CONFIG_INPUT_UINPUT)		+= uinput.o
+obj-$(CONFIG_HP_SDC_RTC)		+= hp_sdc_rtc.o
diff -Nru a/drivers/input/misc/hp_sdc_rtc.c b/drivers/input/misc/hp_sdc_rtc.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/input/misc/hp_sdc_rtc.c	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,724 @@
+/*
+ * HP i8042 SDC + MSM-58321 BBRTC driver.
+ *
+ * Copyright (c) 2001 Brian S. Julin
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions, and the following disclaimer,
+ *    without modification.
+ * 2. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL").
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ *
+ * References:
+ * System Device Controller Microprocessor Firmware Theory of Operation
+ *      for Part Number 1820-4784 Revision B.  Dwg No. A-1820-4784-2
+ * efirtc.c by Stephane Eranian/Hewlett Packard
+ *
+ */
+
+#include <linux/hp_sdc.h>
+#include <linux/errno.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/time.h>
+#include <linux/miscdevice.h>
+#include <linux/proc_fs.h>
+#include <linux/poll.h>
+#include <linux/rtc.h>
+
+MODULE_AUTHOR("Brian S. Julin <bri@calyx.com>");
+MODULE_DESCRIPTION("HP i8042 SDC + MSM-58321 RTC Driver");
+MODULE_LICENSE("Dual BSD/GPL");
+
+#define RTC_VERSION "1.10d"
+
+static unsigned long epoch = 2000;
+
+static struct semaphore i8042tregs;
+
+static hp_sdc_irqhook hp_sdc_rtc_isr;
+
+static struct fasync_struct *hp_sdc_rtc_async_queue;
+
+static DECLARE_WAIT_QUEUE_HEAD(hp_sdc_rtc_wait);
+
+static loff_t hp_sdc_rtc_llseek(struct file *file, loff_t offset, int origin);
+
+static ssize_t hp_sdc_rtc_read(struct file *file, char *buf,
+			       size_t count, loff_t *ppos);
+
+static int hp_sdc_rtc_ioctl(struct inode *inode, struct file *file,
+			    unsigned int cmd, unsigned long arg);
+
+static unsigned int hp_sdc_rtc_poll(struct file *file, poll_table *wait);
+
+static int hp_sdc_rtc_open(struct inode *inode, struct file *file);
+static int hp_sdc_rtc_release(struct inode *inode, struct file *file);
+static int hp_sdc_rtc_fasync (int fd, struct file *filp, int on);
+
+static int hp_sdc_rtc_read_proc(char *page, char **start, off_t off,
+				int count, int *eof, void *data);
+
+static void hp_sdc_rtc_isr (int irq, void *dev_id, 
+			    uint8_t status, uint8_t data) 
+{
+	return;
+}
+
+static int hp_sdc_rtc_do_read_bbrtc (struct rtc_time *rtctm)
+{
+	struct semaphore tsem;
+	hp_sdc_transaction t;
+	uint8_t tseq[91];
+	int i;
+	
+	i = 0;
+	while (i < 91) {
+		tseq[i++] = HP_SDC_ACT_DATAREG |
+			HP_SDC_ACT_POSTCMD | HP_SDC_ACT_DATAIN;
+		tseq[i++] = 0x01;			/* write i8042[0x70] */
+	  	tseq[i]   = i / 7;			/* BBRTC reg address */
+		i++;
+		tseq[i++] = HP_SDC_CMD_DO_RTCR;		/* Trigger command   */
+		tseq[i++] = 2;		/* expect 1 stat/dat pair back.   */
+		i++; i++;               /* buffer for stat/dat pair       */
+	}
+	tseq[84] |= HP_SDC_ACT_SEMAPHORE;
+	t.endidx =		91;
+	t.seq =			tseq;
+	t.act.semaphore =	&tsem;
+	init_MUTEX_LOCKED(&tsem);
+	
+	if (hp_sdc_enqueue_transaction(&t)) return -1;
+	
+	down_interruptible(&tsem);  /* Put ourselves to sleep for results. */
+	
+	/* Check for nonpresence of BBRTC */
+	if (!((tseq[83] | tseq[90] | tseq[69] | tseq[76] |
+	       tseq[55] | tseq[62] | tseq[34] | tseq[41] |
+	       tseq[20] | tseq[27] | tseq[6]  | tseq[13]) & 0x0f))
+		return -1;
+
+	memset(rtctm, 0, sizeof(struct rtc_time));
+	rtctm->tm_year = (tseq[83] & 0x0f) + (tseq[90] & 0x0f) * 10;
+	rtctm->tm_mon  = (tseq[69] & 0x0f) + (tseq[76] & 0x0f) * 10;
+	rtctm->tm_mday = (tseq[55] & 0x0f) + (tseq[62] & 0x0f) * 10;
+	rtctm->tm_wday = (tseq[48] & 0x0f);
+	rtctm->tm_hour = (tseq[34] & 0x0f) + (tseq[41] & 0x0f) * 10;
+	rtctm->tm_min  = (tseq[20] & 0x0f) + (tseq[27] & 0x0f) * 10;
+	rtctm->tm_sec  = (tseq[6]  & 0x0f) + (tseq[13] & 0x0f) * 10;
+	
+	return 0;
+}
+
+static int hp_sdc_rtc_read_bbrtc (struct rtc_time *rtctm)
+{
+	struct rtc_time tm, tm_last;
+	int i = 0;
+
+	/* MSM-58321 has no read latch, so must read twice and compare. */
+
+	if (hp_sdc_rtc_do_read_bbrtc(&tm_last)) return -1;
+	if (hp_sdc_rtc_do_read_bbrtc(&tm)) return -1;
+
+	while (memcmp(&tm, &tm_last, sizeof(struct rtc_time))) {
+		if (i++ > 4) return -1;
+		memcpy(&tm_last, &tm, sizeof(struct rtc_time));
+		if (hp_sdc_rtc_do_read_bbrtc(&tm)) return -1;
+	}
+
+	memcpy(rtctm, &tm, sizeof(struct rtc_time));
+
+	return 0;
+}
+
+
+static int64_t hp_sdc_rtc_read_i8042timer (uint8_t loadcmd, int numreg)
+{
+	hp_sdc_transaction t;
+	uint8_t tseq[26] = {
+		HP_SDC_ACT_PRECMD | HP_SDC_ACT_POSTCMD | HP_SDC_ACT_DATAIN,
+		0,
+		HP_SDC_CMD_READ_T1, 2, 0, 0,
+		HP_SDC_ACT_POSTCMD | HP_SDC_ACT_DATAIN, 
+		HP_SDC_CMD_READ_T2, 2, 0, 0,
+		HP_SDC_ACT_POSTCMD | HP_SDC_ACT_DATAIN, 
+		HP_SDC_CMD_READ_T3, 2, 0, 0,
+		HP_SDC_ACT_POSTCMD | HP_SDC_ACT_DATAIN, 
+		HP_SDC_CMD_READ_T4, 2, 0, 0,
+		HP_SDC_ACT_POSTCMD | HP_SDC_ACT_DATAIN, 
+		HP_SDC_CMD_READ_T5, 2, 0, 0
+	};
+
+	t.endidx = numreg * 5;
+
+	tseq[1] = loadcmd;
+	tseq[t.endidx - 4] |= HP_SDC_ACT_SEMAPHORE; /* numreg assumed > 1 */
+
+	t.seq =			tseq;
+	t.act.semaphore =	&i8042tregs;
+
+	down_interruptible(&i8042tregs);  /* Sleep if output regs in use. */
+
+	if (hp_sdc_enqueue_transaction(&t)) return -1;
+	
+	down_interruptible(&i8042tregs);  /* Sleep until results come back. */
+	up(&i8042tregs);
+
+	return (tseq[5] | 
+		((uint64_t)(tseq[10]) << 8)  | ((uint64_t)(tseq[15]) << 16) |
+		((uint64_t)(tseq[20]) << 24) | ((uint64_t)(tseq[25]) << 32));
+}
+
+
+/* Read the i8042 real-time clock */
+static inline int hp_sdc_rtc_read_rt(struct timeval *res) {
+	int64_t raw;
+	uint32_t tenms; 
+	unsigned int days;
+
+	raw = hp_sdc_rtc_read_i8042timer(HP_SDC_CMD_LOAD_RT, 5);
+	if (raw < 0) return -1;
+
+	tenms = (uint32_t)raw & 0xffffff;
+	days  = (unsigned int)(raw >> 24) & 0xffff;
+
+	res->tv_usec = (suseconds_t)(tenms % 100) * 10000;
+	res->tv_sec =  (time_t)(tenms / 100) + days * 86400;
+
+	return 0;
+}
+
+
+/* Read the i8042 fast handshake timer */
+static inline int hp_sdc_rtc_read_fhs(struct timeval *res) {
+	uint64_t raw;
+	unsigned int tenms;
+
+	raw = hp_sdc_rtc_read_i8042timer(HP_SDC_CMD_LOAD_FHS, 2);
+	if (raw < 0) return -1;
+
+	tenms = (unsigned int)raw & 0xffff;
+
+	res->tv_usec = (suseconds_t)(tenms % 100) * 10000;
+	res->tv_sec  = (time_t)(tenms / 100);
+
+	return 0;
+}
+
+
+/* Read the i8042 match timer (a.k.a. alarm) */
+static inline int hp_sdc_rtc_read_mt(struct timeval *res) {
+	int64_t raw;	
+	uint32_t tenms; 
+
+	raw = hp_sdc_rtc_read_i8042timer(HP_SDC_CMD_LOAD_MT, 3);
+	if (raw < 0) return -1;
+
+	tenms = (uint32_t)raw & 0xffffff;
+
+	res->tv_usec = (suseconds_t)(tenms % 100) * 10000;
+	res->tv_sec  = (time_t)(tenms / 100);
+
+	return 0;
+}
+
+
+/* Read the i8042 delay timer */
+static inline int hp_sdc_rtc_read_dt(struct timeval *res) {
+	int64_t raw;
+	uint32_t tenms;
+
+	raw = hp_sdc_rtc_read_i8042timer(HP_SDC_CMD_LOAD_DT, 3);
+	if (raw < 0) return -1;
+
+	tenms = (uint32_t)raw & 0xffffff;
+
+	res->tv_usec = (suseconds_t)(tenms % 100) * 10000;
+	res->tv_sec  = (time_t)(tenms / 100);
+
+	return 0;
+}
+
+
+/* Read the i8042 cycle timer (a.k.a. periodic) */
+static inline int hp_sdc_rtc_read_ct(struct timeval *res) {
+	int64_t raw;
+	uint32_t tenms;
+
+	raw = hp_sdc_rtc_read_i8042timer(HP_SDC_CMD_LOAD_CT, 3);
+	if (raw < 0) return -1;
+
+	tenms = (uint32_t)raw & 0xffffff;
+
+	res->tv_usec = (suseconds_t)(tenms % 100) * 10000;
+	res->tv_sec  = (time_t)(tenms / 100);
+
+	return 0;
+}
+
+
+/* Set the i8042 real-time clock */
+static int hp_sdc_rtc_set_rt (struct timeval *setto)
+{
+	uint32_t tenms;
+	unsigned int days;
+	hp_sdc_transaction t;
+	uint8_t tseq[11] = {
+		HP_SDC_ACT_PRECMD | HP_SDC_ACT_DATAOUT,
+		HP_SDC_CMD_SET_RTMS, 3, 0, 0, 0,
+		HP_SDC_ACT_PRECMD | HP_SDC_ACT_DATAOUT,
+		HP_SDC_CMD_SET_RTD, 2, 0, 0 
+	};
+
+	t.endidx = 10;
+
+	if (0xffff < setto->tv_sec / 86400) return -1;
+	days = setto->tv_sec / 86400;
+	if (0xffff < setto->tv_usec / 1000000 / 86400) return -1;
+	days += ((setto->tv_sec % 86400) + setto->tv_usec / 1000000) / 86400;
+	if (days > 0xffff) return -1;
+
+	if (0xffffff < setto->tv_sec) return -1;
+	tenms  = setto->tv_sec * 100;
+	if (0xffffff < setto->tv_usec / 10000) return -1;
+	tenms += setto->tv_usec / 10000;
+	if (tenms > 0xffffff) return -1;
+
+	tseq[3] = (uint8_t)(tenms & 0xff);
+	tseq[4] = (uint8_t)((tenms >> 8)  & 0xff);
+	tseq[5] = (uint8_t)((tenms >> 16) & 0xff);
+
+	tseq[9] = (uint8_t)(days & 0xff);
+	tseq[10] = (uint8_t)((days >> 8) & 0xff);
+
+	t.seq =	tseq;
+
+	if (hp_sdc_enqueue_transaction(&t)) return -1;
+	return 0;
+}
+
+/* Set the i8042 fast handshake timer */
+static int hp_sdc_rtc_set_fhs (struct timeval *setto)
+{
+	uint32_t tenms;
+	hp_sdc_transaction t;
+	uint8_t tseq[5] = {
+		HP_SDC_ACT_PRECMD | HP_SDC_ACT_DATAOUT,
+		HP_SDC_CMD_SET_FHS, 2, 0, 0
+	};
+
+	t.endidx = 4;
+
+	if (0xffff < setto->tv_sec) return -1;
+	tenms  = setto->tv_sec * 100;
+	if (0xffff < setto->tv_usec / 10000) return -1;
+	tenms += setto->tv_usec / 10000;
+	if (tenms > 0xffff) return -1;
+
+	tseq[3] = (uint8_t)(tenms & 0xff);
+	tseq[4] = (uint8_t)((tenms >> 8)  & 0xff);
+
+	t.seq =	tseq;
+
+	if (hp_sdc_enqueue_transaction(&t)) return -1;
+	return 0;
+}
+
+
+/* Set the i8042 match timer (a.k.a. alarm) */
+#define hp_sdc_rtc_set_mt (setto) \
+	hp_sdc_rtc_set_i8042timer(setto, HP_SDC_CMD_SET_MT)
+
+/* Set the i8042 delay timer */
+#define hp_sdc_rtc_set_dt (setto) \
+	hp_sdc_rtc_set_i8042timer(setto, HP_SDC_CMD_SET_DT)
+
+/* Set the i8042 cycle timer (a.k.a. periodic) */
+#define hp_sdc_rtc_set_ct (setto) \
+	hp_sdc_rtc_set_i8042timer(setto, HP_SDC_CMD_SET_CT)
+
+/* Set one of the i8042 3-byte wide timers */
+static int hp_sdc_rtc_set_i8042timer (struct timeval *setto, uint8_t setcmd)
+{
+	uint32_t tenms;
+	hp_sdc_transaction t;
+	uint8_t tseq[6] = {
+		HP_SDC_ACT_PRECMD | HP_SDC_ACT_DATAOUT,
+		0, 3, 0, 0, 0
+	};
+
+	t.endidx = 6;
+
+	if (0xffffff < setto->tv_sec) return -1;
+	tenms  = setto->tv_sec * 100;
+	if (0xffffff < setto->tv_usec / 10000) return -1;
+	tenms += setto->tv_usec / 10000;
+	if (tenms > 0xffffff) return -1;
+
+	tseq[1] = setcmd;
+	tseq[3] = (uint8_t)(tenms & 0xff);
+	tseq[4] = (uint8_t)((tenms >> 8)  & 0xff);
+	tseq[5] = (uint8_t)((tenms >> 16)  & 0xff);
+
+	t.seq =			tseq;
+
+	if (hp_sdc_enqueue_transaction(&t)) { 
+		return -1;
+	}
+	return 0;
+}
+
+static loff_t hp_sdc_rtc_llseek(struct file *file, loff_t offset, int origin)
+{
+        return -ESPIPE;
+}
+
+static ssize_t hp_sdc_rtc_read(struct file *file, char *buf,
+			       size_t count, loff_t *ppos) {
+	ssize_t retval;
+
+        if (count < sizeof(unsigned long))
+                return -EINVAL;
+
+	retval = put_user(68, (unsigned long *)buf);
+	return retval;
+}
+
+static unsigned int hp_sdc_rtc_poll(struct file *file, poll_table *wait)
+{
+        unsigned long l;
+
+	l = 0;
+        if (l != 0)
+                return POLLIN | POLLRDNORM;
+        return 0;
+}
+
+static int hp_sdc_rtc_open(struct inode *inode, struct file *file)
+{
+        return 0;
+}
+
+static int hp_sdc_rtc_release(struct inode *inode, struct file *file)
+{
+	/* Turn off interrupts? */
+
+        if (file->f_flags & FASYNC) {
+                hp_sdc_rtc_fasync (-1, file, 0);
+        }
+
+        return 0;
+}
+
+static int hp_sdc_rtc_fasync (int fd, struct file *filp, int on)
+{
+        return fasync_helper (fd, filp, on, &hp_sdc_rtc_async_queue);
+}
+
+static int hp_sdc_rtc_proc_output (char *buf)
+{
+#define YN(bit) ("no")
+#define NY(bit) ("yes")
+        char *p;
+        struct rtc_time tm;
+	struct timeval tv;
+
+	memset(&tm, 0, sizeof(struct rtc_time));
+
+	p = buf;
+
+	if (hp_sdc_rtc_read_bbrtc(&tm)) {
+		p += sprintf(p, "BBRTC\t\t: READ FAILED!\n");
+	} else {
+		p += sprintf(p,
+			     "rtc_time\t: %02d:%02d:%02d\n"
+			     "rtc_date\t: %04d-%02d-%02d\n"
+			     "rtc_epoch\t: %04lu\n",
+			     tm.tm_hour, tm.tm_min, tm.tm_sec,
+			     tm.tm_year + 1900, tm.tm_mon + 1, 
+			     tm.tm_mday, epoch);
+	}
+
+	if (hp_sdc_rtc_read_rt(&tv)) {
+		p += sprintf(p, "i8042 rtc\t: READ FAILED!\n");
+	} else {
+		p += sprintf(p, "i8042 rtc\t: %ld.%02d seconds\n", 
+			     tv.tv_sec, tv.tv_usec/1000);
+	}
+
+	if (hp_sdc_rtc_read_fhs(&tv)) {
+		p += sprintf(p, "handshake\t: READ FAILED!\n");
+	} else {
+        	p += sprintf(p, "handshake\t: %ld.%02d seconds\n", 
+			     tv.tv_sec, tv.tv_usec/1000);
+	}
+
+	if (hp_sdc_rtc_read_mt(&tv)) {
+		p += sprintf(p, "alarm\t\t: READ FAILED!\n");
+	} else {
+		p += sprintf(p, "alarm\t\t: %ld.%02d seconds\n", 
+			     tv.tv_sec, tv.tv_usec/1000);
+	}
+
+	if (hp_sdc_rtc_read_dt(&tv)) {
+		p += sprintf(p, "delay\t\t: READ FAILED!\n");
+	} else {
+		p += sprintf(p, "delay\t\t: %ld.%02d seconds\n", 
+			     tv.tv_sec, tv.tv_usec/1000);
+	}
+
+	if (hp_sdc_rtc_read_ct(&tv)) {
+		p += sprintf(p, "periodic\t: READ FAILED!\n");
+	} else {
+		p += sprintf(p, "periodic\t: %ld.%02d seconds\n", 
+			     tv.tv_sec, tv.tv_usec/1000);
+	}
+
+        p += sprintf(p,
+                     "DST_enable\t: %s\n"
+                     "BCD\t\t: %s\n"
+                     "24hr\t\t: %s\n"
+                     "square_wave\t: %s\n"
+                     "alarm_IRQ\t: %s\n"
+                     "update_IRQ\t: %s\n"
+                     "periodic_IRQ\t: %s\n"
+		     "periodic_freq\t: %ld\n"
+                     "batt_status\t: %s\n",
+                     YN(RTC_DST_EN),
+                     NY(RTC_DM_BINARY),
+                     YN(RTC_24H),
+                     YN(RTC_SQWE),
+                     YN(RTC_AIE),
+                     YN(RTC_UIE),
+                     YN(RTC_PIE),
+                     1UL,
+                     1 ? "okay" : "dead");
+
+        return  p - buf;
+#undef YN
+#undef NY
+}
+
+static int hp_sdc_rtc_read_proc(char *page, char **start, off_t off,
+                         int count, int *eof, void *data)
+{
+	int len = hp_sdc_rtc_proc_output (page);
+        if (len <= off+count) *eof = 1;
+        *start = page + off;
+        len -= off;
+        if (len>count) len = count;
+        if (len<0) len = 0;
+        return len;
+}
+
+static int hp_sdc_rtc_ioctl(struct inode *inode, struct file *file, 
+			    unsigned int cmd, unsigned long arg)
+{
+#if 1
+	return -EINVAL;
+#else
+	
+        struct rtc_time wtime; 
+	struct timeval ttime;
+	int use_wtime = 0;
+
+	/* This needs major work. */
+
+        switch (cmd) {
+
+        case RTC_AIE_OFF:       /* Mask alarm int. enab. bit    */
+        case RTC_AIE_ON:        /* Allow alarm interrupts.      */
+	case RTC_PIE_OFF:       /* Mask periodic int. enab. bit */
+        case RTC_PIE_ON:        /* Allow periodic ints          */
+        case RTC_UIE_ON:        /* Allow ints for RTC updates.  */
+        case RTC_UIE_OFF:       /* Allow ints for RTC updates.  */
+        {
+		/* We cannot mask individual user timers and we
+		   cannot tell them apart when they occur, so it 
+		   would be disingenuous to succeed these IOCTLs */
+		return -EINVAL;
+        }
+        case RTC_ALM_READ:      /* Read the present alarm time */
+        {
+		if (hp_sdc_rtc_read_mt(&ttime)) return -EFAULT;
+		if (hp_sdc_rtc_read_bbrtc(&wtime)) return -EFAULT;
+
+		wtime.tm_hour = ttime.tv_sec / 3600;  ttime.tv_sec %= 3600;
+		wtime.tm_min  = ttime.tv_sec / 60;    ttime.tv_sec %= 60;
+		wtime.tm_sec  = ttime.tv_sec;
+                
+		break;
+        }
+        case RTC_IRQP_READ:     /* Read the periodic IRQ rate.  */
+        {
+                return put_user(hp_sdc_rtc_freq, (unsigned long *)arg);
+        }
+        case RTC_IRQP_SET:      /* Set periodic IRQ rate.       */
+        {
+                /* 
+                 * The max we can do is 100Hz.
+		 */
+
+                if ((arg < 1) || (arg > 100)) return -EINVAL;
+		ttime.tv_sec = 0;
+		ttime.tv_usec = 1000000 / arg;
+		if (hp_sdc_rtc_set_ct(&ttime)) return -EFAULT;
+		hp_sdc_rtc_freq = arg;
+                return 0;
+        }
+        case RTC_ALM_SET:       /* Store a time into the alarm */
+        {
+                /*
+                 * This expects a struct hp_sdc_rtc_time. Writing 0xff means
+                 * "don't care" or "match all" for PC timers.  The HP SDC
+		 * does not support that perk, but it could be emulated fairly
+		 * easily.  Only the tm_hour, tm_min and tm_sec are used.
+		 * We could do it with 10ms accuracy with the HP SDC, if the 
+		 * rtc interface left us a way to do that.
+                 */
+                struct hp_sdc_rtc_time alm_tm;
+
+                if (copy_from_user(&alm_tm, (struct hp_sdc_rtc_time*)arg,
+                                   sizeof(struct hp_sdc_rtc_time)))
+                       return -EFAULT;
+
+                if (alm_tm.tm_hour > 23) return -EINVAL;
+		if (alm_tm.tm_min  > 59) return -EINVAL;
+		if (alm_tm.tm_sec  > 59) return -EINVAL;  
+
+		ttime.sec = alm_tm.tm_hour * 3600 + 
+		  alm_tm.tm_min * 60 + alm_tm.tm_sec;
+		ttime.usec = 0;
+		if (hp_sdc_rtc_set_mt(&ttime)) return -EFAULT;
+                return 0;
+        }
+        case RTC_RD_TIME:       /* Read the time/date from RTC  */
+        {
+		if (hp_sdc_rtc_read_bbrtc(&wtime)) return -EFAULT;
+                break;
+        }
+        case RTC_SET_TIME:      /* Set the RTC */
+        {
+                struct rtc_time hp_sdc_rtc_tm;
+                unsigned char mon, day, hrs, min, sec, leap_yr;
+                unsigned int yrs;
+
+                if (!capable(CAP_SYS_TIME))
+                        return -EACCES;
+		if (copy_from_user(&hp_sdc_rtc_tm, (struct rtc_time *)arg,
+                                   sizeof(struct rtc_time)))
+                        return -EFAULT;
+
+                yrs = hp_sdc_rtc_tm.tm_year + 1900;
+                mon = hp_sdc_rtc_tm.tm_mon + 1;   /* tm_mon starts at zero */
+                day = hp_sdc_rtc_tm.tm_mday;
+                hrs = hp_sdc_rtc_tm.tm_hour;
+                min = hp_sdc_rtc_tm.tm_min;
+                sec = hp_sdc_rtc_tm.tm_sec;
+
+                if (yrs < 1970)
+                        return -EINVAL;
+
+                leap_yr = ((!(yrs % 4) && (yrs % 100)) || !(yrs % 400));
+
+                if ((mon > 12) || (day == 0))
+                        return -EINVAL;
+                if (day > (days_in_mo[mon] + ((mon == 2) && leap_yr)))
+                        return -EINVAL;
+		if ((hrs >= 24) || (min >= 60) || (sec >= 60))
+                        return -EINVAL;
+
+                if ((yrs -= eH) > 255)    /* They are unsigned */
+                        return -EINVAL;
+
+
+                return 0;
+        }
+        case RTC_EPOCH_READ:    /* Read the epoch.      */
+        {
+                return put_user (epoch, (unsigned long *)arg);
+        }
+        case RTC_EPOCH_SET:     /* Set the epoch.       */
+        {
+                /* 
+                 * There were no RTC clocks before 1900.
+                 */
+                if (arg < 1900)
+		  return -EINVAL;
+		if (!capable(CAP_SYS_TIME))
+		  return -EACCES;
+		
+                epoch = arg;
+                return 0;
+        }
+        default:
+                return -EINVAL;
+        }
+        return copy_to_user((void *)arg, &wtime, sizeof wtime) ? -EFAULT : 0;
+#endif
+}
+
+static struct file_operations hp_sdc_rtc_fops = {
+        .owner =	THIS_MODULE,
+        .llseek =	hp_sdc_rtc_llseek,
+        .read =		hp_sdc_rtc_read,
+        .poll =		hp_sdc_rtc_poll,
+        .ioctl =	hp_sdc_rtc_ioctl,
+        .open =		hp_sdc_rtc_open,
+        .release =	hp_sdc_rtc_release,
+        .fasync =	hp_sdc_rtc_fasync,
+};
+
+static struct miscdevice hp_sdc_rtc_dev = {
+        .minor =	RTC_MINOR,
+        .name =		"rtc_HIL",
+        .fops =		&hp_sdc_rtc_fops
+};
+
+static int __init hp_sdc_rtc_init(void)
+{
+	int ret;
+
+	init_MUTEX(&i8042tregs);
+
+	if ((ret = hp_sdc_request_timer_irq(&hp_sdc_rtc_isr)))
+		return ret;
+	misc_register(&hp_sdc_rtc_dev);
+        create_proc_read_entry ("driver/rtc", 0, 0, 
+				hp_sdc_rtc_read_proc, NULL);
+
+	printk(KERN_INFO "HP i8042 SDC + MSM-58321 RTC support loaded "
+			 "(RTC v " RTC_VERSION ")\n");
+
+	return 0;
+}
+
+static void __exit hp_sdc_rtc_exit(void)
+{
+	remove_proc_entry ("driver/rtc", NULL);
+        misc_deregister(&hp_sdc_rtc_dev);
+	hp_sdc_release_timer_irq(hp_sdc_rtc_isr);
+        printk(KERN_INFO "HP i8042 SDC + MSM-58321 RTC support unloaded\n");
+}
+
+module_init(hp_sdc_rtc_init);
+module_exit(hp_sdc_rtc_exit);
diff -Nru a/drivers/input/misc/pcspkr.c b/drivers/input/misc/pcspkr.c
--- a/drivers/input/misc/pcspkr.c	2005-03-11 12:51:47 -08:00
+++ b/drivers/input/misc/pcspkr.c	2005-03-11 12:51:47 -08:00
@@ -27,7 +27,7 @@
 static char pcspkr_phys[] = "isa0061/input0";
 static struct input_dev pcspkr_dev;
 
-DEFINE_SPINLOCK(i8253_beep_lock);
+static DEFINE_SPINLOCK(i8253_beep_lock);
 
 static int pcspkr_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
 {
@@ -89,6 +89,8 @@
 static void __exit pcspkr_exit(void)
 {
         input_unregister_device(&pcspkr_dev);
+	/* turn off the speaker */
+	pcspkr_event(NULL, EV_SND, SND_BELL, 0);
 }
 
 module_init(pcspkr_init);
diff -Nru a/drivers/input/misc/uinput.c b/drivers/input/misc/uinput.c
--- a/drivers/input/misc/uinput.c	2005-03-11 12:51:52 -08:00
+++ b/drivers/input/misc/uinput.c	2005-03-11 12:51:52 -08:00
@@ -20,6 +20,9 @@
  * Author: Aristeu Sergio Rozanski Filho <aris@cathedrallabs.org>
  *
  * Changes/Revisions:
+ *	0.2	16/10/2004 (Micah Dowty <micah@navi.cx>)
+ *		- added force feedback support
+ *              - added UI_SET_PHYS
  *	0.1	20/06/2002
  *		- first public version
  */
@@ -47,7 +50,7 @@
 {
 	struct uinput_device	*udev;
 
-	udev = (struct uinput_device *)dev->private;
+	udev = dev->private;
 
 	udev->buff[udev->head].type = type;
 	udev->buff[udev->head].code = code;
@@ -60,14 +63,93 @@
 	return 0;
 }
 
+static int uinput_request_alloc_id(struct input_dev *dev, struct uinput_request *request)
+{
+	/* Atomically allocate an ID for the given request. Returns 0 on success. */
+	struct uinput_device *udev = dev->private;
+	int id;
+
+	down(&udev->requests_sem);
+	for (id=0; id<UINPUT_NUM_REQUESTS; id++)
+		if (!udev->requests[id]) {
+			udev->requests[id] = request;
+			request->id = id;
+			up(&udev->requests_sem);
+			return 0;
+		}
+	up(&udev->requests_sem);
+	return -1;
+}
+
+static struct uinput_request* uinput_request_find(struct uinput_device *udev, int id)
+{
+	/* Find an input request, by ID. Returns NULL if the ID isn't valid. */
+	if (id >= UINPUT_NUM_REQUESTS || id < 0)
+		return NULL;
+	if (udev->requests[id]->completed)
+		return NULL;
+	return udev->requests[id];
+}
+
+static void uinput_request_init(struct input_dev *dev, struct uinput_request *request, int code)
+{
+	struct uinput_device *udev = dev->private;
+
+	memset(request, 0, sizeof(struct uinput_request));
+	request->code = code;
+	init_waitqueue_head(&request->waitq);
+
+	/* Allocate an ID. If none are available right away, wait. */
+	request->retval = wait_event_interruptible(udev->requests_waitq,
+				       !uinput_request_alloc_id(dev, request));
+}
+
+static void uinput_request_submit(struct input_dev *dev, struct uinput_request *request)
+{
+	struct uinput_device *udev = dev->private;
+	int retval;
+
+	/* Tell our userspace app about this new request by queueing an input event */
+	uinput_dev_event(dev, EV_UINPUT, request->code, request->id);
+
+	/* Wait for the request to complete */
+	retval = wait_event_interruptible(request->waitq, request->completed);
+	if (retval)
+		request->retval = retval;
+
+	/* Release this request's ID, let others know it's available */
+	udev->requests[request->id] = NULL;
+	wake_up_interruptible(&udev->requests_waitq);
+}
+
 static int uinput_dev_upload_effect(struct input_dev *dev, struct ff_effect *effect)
 {
-	return 0;
+	struct uinput_request request;
+
+	if (!test_bit(EV_FF, dev->evbit))
+		return -ENOSYS;
+
+	uinput_request_init(dev, &request, UI_FF_UPLOAD);
+	if (request.retval)
+		return request.retval;
+	request.u.effect = effect;
+	uinput_request_submit(dev, &request);
+	return request.retval;
 }
 
 static int uinput_dev_erase_effect(struct input_dev *dev, int effect_id)
 {
-	return 0;
+	struct uinput_request request;
+
+	if (!test_bit(EV_FF, dev->evbit))
+		return -ENOSYS;
+
+	uinput_request_init(dev, &request, UI_FF_ERASE);
+	if (request.retval)
+		return request.retval;
+	request.u.effect_id = effect_id;
+	uinput_request_submit(dev, &request);
+	return request.retval;
 }
 
 static int uinput_create_device(struct uinput_device *udev)
@@ -116,6 +198,8 @@
 	if (!newdev)
 		goto error;
 	memset(newdev, 0, sizeof(struct uinput_device));
+	init_MUTEX(&newdev->requests_sem);
+	init_waitqueue_head(&newdev->requests_waitq);
 
 	newinput = kmalloc(sizeof(struct input_dev), GFP_KERNEL);
 	if (!newinput)
@@ -138,12 +222,11 @@
 	unsigned int cnt;
 	int retval = 0;
 
-	for (cnt = 0; cnt < ABS_MAX; cnt++) {
+	for (cnt = 0; cnt < ABS_MAX + 1; cnt++) {
 		if (!test_bit(cnt, dev->absbit))
 			continue;
 
-		if (/*!dev->absmin[cnt] || !dev->absmax[cnt] || */
-		    (dev->absmax[cnt] <= dev->absmin[cnt])) {
+		if ((dev->absmax[cnt] <= dev->absmin[cnt])) {
 			printk(KERN_DEBUG
 				"%s: invalid abs[%02x] min:%d max:%d\n",
 				UINPUT_NAME, cnt,
@@ -152,8 +235,7 @@
 			break;
 		}
 
-		if ((dev->absflat[cnt] < dev->absmin[cnt]) ||
-		    (dev->absflat[cnt] > dev->absmax[cnt])) {
+		if (dev->absflat[cnt] > (dev->absmax[cnt] - dev->absmin[cnt])) {
 			printk(KERN_DEBUG
 				"%s: absflat[%02x] out of range: %d "
 				"(min:%d/max:%d)\n",
@@ -176,7 +258,7 @@
 
 	retval = count;
 
-	udev = (struct uinput_device *)file->private_data;
+	udev = file->private_data;
 	dev = udev->dev;
 
 	user_dev = kmalloc(sizeof(*user_dev), GFP_KERNEL);
@@ -228,7 +310,7 @@
 
 static ssize_t uinput_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos)
 {
-	struct uinput_device	*udev = file->private_data;
+	struct uinput_device *udev = file->private_data;
 
 	if (test_bit(UIST_CREATED, &(udev->state))) {
 		struct input_event	ev;
@@ -279,9 +361,6 @@
 {
 	struct uinput_device *udev = file->private_data;
 
-	if (!test_bit(UIST_CREATED, &(udev->state)))
-		return 0;
-
 	poll_wait(file, &udev->waitq, wait);
 
 	if (udev->head != udev->tail)
@@ -295,6 +374,11 @@
 	if (test_bit(UIST_CREATED, &(udev->state)))
 		uinput_destroy_device(udev);
 
+	if (NULL != udev->dev->name)
+		kfree(udev->dev->name);
+	if (NULL != udev->dev->phys)
+		kfree(udev->dev->phys);
+
 	kfree(udev->dev);
 	kfree(udev);
 
@@ -303,19 +387,35 @@
 
 static int uinput_close(struct inode *inode, struct file *file)
 {
-	return uinput_burn_device((struct uinput_device *)file->private_data);
+	return uinput_burn_device(file->private_data);
 }
 
 static int uinput_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
 {
 	int			retval = 0;
 	struct uinput_device	*udev;
+	void __user             *p = (void __user *)arg;
+	struct uinput_ff_upload ff_up;
+	struct uinput_ff_erase  ff_erase;
+	struct uinput_request   *req;
+	int                     length;
 
-	udev = (struct uinput_device *)file->private_data;
+	udev = file->private_data;
 
 	/* device attributes can not be changed after the device is created */
-	if (cmd >= UI_SET_EVBIT && test_bit(UIST_CREATED, &(udev->state)))
-		return -EINVAL;
+	switch (cmd) {
+		case UI_SET_EVBIT:
+		case UI_SET_KEYBIT:
+		case UI_SET_RELBIT:
+		case UI_SET_ABSBIT:
+		case UI_SET_MSCBIT:
+		case UI_SET_LEDBIT:
+		case UI_SET_SNDBIT:
+		case UI_SET_FFBIT:
+		case UI_SET_PHYS:
+			if (test_bit(UIST_CREATED, &(udev->state)))
+				return -EINVAL;
+	}
 
 	switch (cmd) {
 		case UI_DEV_CREATE:
@@ -390,13 +490,102 @@
 			set_bit(arg, udev->dev->ffbit);
 			break;
 
+		case UI_SET_PHYS:
+			length = strnlen_user(p, 1024);
+			if (length <= 0) {
+				retval = -EFAULT;
+				break;
+			}
+			if (NULL != udev->dev->phys)
+				kfree(udev->dev->phys);
+			udev->dev->phys = kmalloc(length, GFP_KERNEL);
+			if (!udev->dev->phys) {
+				retval = -ENOMEM;
+				break;
+			}
+			if (copy_from_user(udev->dev->phys, p, length)) {
+				retval = -EFAULT;
+				kfree(udev->dev->phys);
+				udev->dev->phys = NULL;
+				break;
+			}
+			udev->dev->phys[length-1] = '\0';
+			break;
+
+		case UI_BEGIN_FF_UPLOAD:
+			if (copy_from_user(&ff_up, p, sizeof(ff_up))) {
+				retval = -EFAULT;
+				break;
+			}
+			req = uinput_request_find(udev, ff_up.request_id);
+			if (!(req && req->code==UI_FF_UPLOAD && req->u.effect)) {
+				retval = -EINVAL;
+				break;
+			}
+			ff_up.retval = 0;
+			memcpy(&ff_up.effect, req->u.effect, sizeof(struct ff_effect));
+			if (copy_to_user(p, &ff_up, sizeof(ff_up))) {
+				retval = -EFAULT;
+				break;
+			}
+			break;
+
+		case UI_BEGIN_FF_ERASE:
+			if (copy_from_user(&ff_erase, p, sizeof(ff_erase))) {
+				retval = -EFAULT;
+				break;
+			}
+			req = uinput_request_find(udev, ff_erase.request_id);
+			if (!(req && req->code==UI_FF_ERASE)) {
+				retval = -EINVAL;
+				break;
+			}
+			ff_erase.retval = 0;
+			ff_erase.effect_id = req->u.effect_id;
+			if (copy_to_user(p, &ff_erase, sizeof(ff_erase))) {
+				retval = -EFAULT;
+				break;
+			}
+			break;
+
+		case UI_END_FF_UPLOAD:
+			if (copy_from_user(&ff_up, p, sizeof(ff_up))) {
+				retval = -EFAULT;
+				break;
+			}
+			req = uinput_request_find(udev, ff_up.request_id);
+			if (!(req && req->code==UI_FF_UPLOAD && req->u.effect)) {
+				retval = -EINVAL;
+				break;
+			}
+			req->retval = ff_up.retval;
+			memcpy(req->u.effect, &ff_up.effect, sizeof(struct ff_effect));
+			req->completed = 1;
+			wake_up_interruptible(&req->waitq);
+			break;
+
+		case UI_END_FF_ERASE:
+			if (copy_from_user(&ff_erase, p, sizeof(ff_erase))) {
+				retval = -EFAULT;
+				break;
+			}
+			req = uinput_request_find(udev, ff_erase.request_id);
+			if (!(req && req->code==UI_FF_ERASE)) {
+				retval = -EINVAL;
+				break;
+			}
+			req->retval = ff_erase.retval;
+			req->completed = 1;
+			wake_up_interruptible(&req->waitq);
+			break;
+
 		default:
-			retval = -EFAULT;
+			retval = -EINVAL;
 	}
 	return retval;
 }
 
-struct file_operations uinput_fops = {
+static struct file_operations uinput_fops = {
 	.owner =	THIS_MODULE,
 	.open =		uinput_open,
 	.release =	uinput_close,
diff -Nru a/drivers/input/mouse/Kconfig b/drivers/input/mouse/Kconfig
--- a/drivers/input/mouse/Kconfig	2005-03-11 12:51:51 -08:00
+++ b/drivers/input/mouse/Kconfig	2005-03-11 12:51:51 -08:00
@@ -1,20 +1,20 @@
 #
 # Mouse driver configuration
 #
-config INPUT_MOUSE
-	bool "Mice"
+menuconfig INPUT_MOUSE
+	bool "Mouse"
 	default y
-	depends on INPUT
 	help
 	  Say Y here, and a list of supported mice will be displayed.
 	  This option doesn't affect the kernel.
 
 	  If unsure, say Y.
 
+if INPUT_MOUSE
+
 config MOUSE_PS2
 	tristate "PS/2 mouse"
 	default y
-	depends on INPUT && INPUT_MOUSE
 	select SERIO
 	select SERIO_LIBPS2
 	select SERIO_I8042 if PC
@@ -39,7 +39,6 @@
 
 config MOUSE_SERIAL
 	tristate "Serial mouse"
-	depends on INPUT && INPUT_MOUSE
 	select SERIO
 	---help---
 	  Say Y here if you have a serial (RS-232, COM port) mouse connected
@@ -53,7 +52,7 @@
 
 config MOUSE_INPORT
 	tristate "InPort/MS/ATIXL busmouse"
-	depends on INPUT && INPUT_MOUSE && ISA
+	depends on ISA
 	help
 	  Say Y here if you have an InPort, Microsoft or ATI XL busmouse.
 	  They are rather rare these days.
@@ -69,7 +68,7 @@
 
 config MOUSE_LOGIBM
 	tristate "Logitech busmouse"
-	depends on INPUT && INPUT_MOUSE && ISA
+	depends on ISA
 	help
 	  Say Y here if you have a Logitech busmouse.
 	  They are rather rare these days.
@@ -79,7 +78,7 @@
 
 config MOUSE_PC110PAD
 	tristate "IBM PC110 touchpad"
-	depends on INPUT && INPUT_MOUSE && ISA
+	depends on ISA
 	help
 	  Say Y if you have the IBM PC-110 micro-notebook and want its
 	  touchpad supported.
@@ -89,7 +88,7 @@
 
 config MOUSE_MAPLE
 	tristate "Maple bus mouse"
-	depends on SH_DREAMCAST && INPUT && INPUT_MOUSE && MAPLE
+	depends on SH_DREAMCAST && MAPLE
 	help
 	  Say Y if you have a DreamCast console and a mouse attached to
 	  its Maple bus.
@@ -99,7 +98,7 @@
 
 config MOUSE_AMIGA
 	tristate "Amiga mouse"
-	depends on AMIGA && INPUT && INPUT_MOUSE
+	depends on AMIGA
 	help
 	  Say Y here if you have an Amiga and want its native mouse
 	  supported by the kernel.
@@ -109,7 +108,7 @@
 
 config MOUSE_RISCPC
 	tristate "Acorn RiscPC mouse"
-	depends on ARCH_ACORN && INPUT && INPUT_MOUSE
+	depends on ARCH_ACORN
 	help
 	  Say Y here if you have the Acorn RiscPC computer and want its
 	  native mouse supported.
@@ -119,7 +118,6 @@
 
 config MOUSE_VSXXXAA
 	tristate "DEC VSXXX-AA/GA mouse and VSXXX-AB tablet"
-	depends on INPUT && INPUT_MOUSE
 	select SERIO
 	help
 	  Say Y (or M) if you want to use a DEC VSXXX-AA (hockey
@@ -129,3 +127,12 @@
 	  described in the source file). This driver also works with the
 	  digitizer (VSXXX-AB) DEC produced.
 
+config MOUSE_HIL
+	tristate "HIL pointers (mice etc)."     
+	depends on GSC
+	select HP_SDC
+	select HIL_MLC
+	help
+	  Say Y here to support HIL pointers.
+
+endif
diff -Nru a/drivers/input/mouse/Makefile b/drivers/input/mouse/Makefile
--- a/drivers/input/mouse/Makefile	2005-03-11 12:51:41 -08:00
+++ b/drivers/input/mouse/Makefile	2005-03-11 12:51:41 -08:00
@@ -12,6 +12,7 @@
 obj-$(CONFIG_MOUSE_PC110PAD)	+= pc110pad.o
 obj-$(CONFIG_MOUSE_PS2)		+= psmouse.o
 obj-$(CONFIG_MOUSE_SERIAL)	+= sermouse.o
+obj-$(CONFIG_MOUSE_HIL)		+= hil_ptr.o
 obj-$(CONFIG_MOUSE_VSXXXAA)	+= vsxxxaa.o
 
 psmouse-objs  := psmouse-base.o alps.o logips2pp.o synaptics.o
diff -Nru a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c
--- a/drivers/input/mouse/alps.c	2005-03-11 12:51:47 -08:00
+++ b/drivers/input/mouse/alps.c	2005-03-11 12:51:47 -08:00
@@ -4,6 +4,7 @@
  * Copyright (c) 2003 Neil Brown <neilb@cse.unsw.edu.au>
  * Copyright (c) 2003 Peter Osterlund <petero2@telia.com>
  * Copyright (c) 2004 Dmitry Torokhov <dtor@mail.ru>
+ * Copyright (c) 2005 Vojtech Pavlik <vojtech@suse.cz>
  *
  * ALPS detection, tap switching and status querying info is taken from
  * tpconfig utility (by C. Scott Ananian and Bruce Kall).
@@ -27,102 +28,122 @@
 #define dbg(format, arg...) do {} while (0)
 #endif
 
-#define ALPS_MODEL_GLIDEPOINT	1
-#define ALPS_MODEL_DUALPOINT	2
-
-struct alps_model_info {
-	unsigned char signature[3];
-	unsigned char model;
-} alps_model_data[] = {
-/*	{ { 0x33, 0x02, 0x0a },	ALPS_MODEL_GLIDEPOINT },	*/
-	{ { 0x53, 0x02, 0x0a },	ALPS_MODEL_GLIDEPOINT },
-	{ { 0x53, 0x02, 0x14 },	ALPS_MODEL_GLIDEPOINT },
-	{ { 0x63, 0x02, 0x0a },	ALPS_MODEL_GLIDEPOINT },
-	{ { 0x63, 0x02, 0x14 },	ALPS_MODEL_GLIDEPOINT },
-	{ { 0x73, 0x02, 0x0a },	ALPS_MODEL_GLIDEPOINT },
-	{ { 0x73, 0x02, 0x14 },	ALPS_MODEL_GLIDEPOINT },
-	{ { 0x63, 0x02, 0x28 },	ALPS_MODEL_GLIDEPOINT },
-/*	{ { 0x63, 0x02, 0x3c },	ALPS_MODEL_GLIDEPOINT },	*/
-/*	{ { 0x63, 0x02, 0x50 },	ALPS_MODEL_GLIDEPOINT },	*/
-	{ { 0x63, 0x02, 0x64 },	ALPS_MODEL_GLIDEPOINT },
-	{ { 0x20, 0x02, 0x0e },	ALPS_MODEL_DUALPOINT },
-	{ { 0x22, 0x02, 0x0a },	ALPS_MODEL_DUALPOINT },
-	{ { 0x22, 0x02, 0x14 }, ALPS_MODEL_DUALPOINT },
-	{ { 0x63, 0x03, 0xc8 },	ALPS_MODEL_DUALPOINT },
+#define ALPS_DUALPOINT	0x01
+#define ALPS_WHEEL	0x02
+#define ALPS_FW_BK	0x04
+#define ALPS_4BTN	0x08
+#define ALPS_OLDPROTO	0x10
+#define ALPS_PASS	0x20
+
+static struct alps_model_info alps_model_data[] = {
+	{ { 0x33, 0x02, 0x0a },	0x88, 0xf8, ALPS_OLDPROTO },		/* UMAX-530T */
+	{ { 0x53, 0x02, 0x0a },	0xf8, 0xf8, 0 },
+	{ { 0x53, 0x02, 0x14 },	0xf8, 0xf8, 0 },
+	{ { 0x63, 0x02, 0x0a },	0xf8, 0xf8, 0 },
+	{ { 0x63, 0x02, 0x14 },	0xf8, 0xf8, 0 },
+	{ { 0x63, 0x02, 0x28 },	0xf8, 0xf8, 0 },
+	{ { 0x63, 0x02, 0x3c },	0x8f, 0x8f, ALPS_WHEEL },		/* Toshiba Satellite S2400-103 */
+	{ { 0x63, 0x02, 0x50 },	0xef, 0xef, ALPS_FW_BK },		/* NEC Versa L320 */
+	{ { 0x63, 0x02, 0x64 },	0xf8, 0xf8, 0 },
+	{ { 0x63, 0x03, 0xc8 }, 0xf8, 0xf8, ALPS_PASS },		/* Dell Latitude D800 */
+	{ { 0x73, 0x02, 0x0a },	0xf8, 0xf8, 0 },
+	{ { 0x73, 0x02, 0x14 },	0xf8, 0xf8, 0 },
+	{ { 0x20, 0x02, 0x0e },	0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* XXX */
+	{ { 0x22, 0x02, 0x0a },	0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT },
+	{ { 0x22, 0x02, 0x14 }, 0xff, 0xff, ALPS_PASS | ALPS_DUALPOINT }, /* Dell Latitude D600 */
 };
 
 /*
- * ALPS abolute Mode
- * byte 0:  1    1    1    1    1  mid0 rig0 lef0
+ * XXX - this entry is suspicious. First byte has zero lower nibble,
+ * which is what a normal mouse would report. Also, the value 0x0e
+ * isn't valid per PS/2 spec.
+ */
+
+/*
+ * ALPS abolute Mode - new format
+ * 
+ * byte 0:  1    ?    ?    ?    1    ?    ?    ? 
  * byte 1:  0   x6   x5   x4   x3   x2   x1   x0
- * byte 2:  0   x10  x9   x8   x7  up1  fin  ges
- * byte 3:  0   y9   y8   y7    1  mid1 rig1 lef1
+ * byte 2:  0   x10  x9   x8   x7    ?  fin  ges
+ * byte 3:  0   y9   y8   y7    1    M    R    L 
  * byte 4:  0   y6   y5   y4   y3   y2   y1   y0
  * byte 5:  0   z6   z5   z4   z3   z2   z1   z0
  *
- * On a dualpoint, {mid,rig,lef}0 are the stick, 1 are the pad.
- * We just 'or' them together for now.
- *
- * We used to send 'ges'tures as BTN_TOUCH but this made it impossible
- * to disable tap events in the synaptics driver since the driver
- * was unable to distinguish a gesture tap from an actual button click.
- * A tap gesture now creates an emulated touch that the synaptics
- * driver can interpret as a tap event, if MaxTapTime=0 and
- * MaxTapMove=0 then the driver will ignore taps.
- *
- * The touchpad on an 'Acer Aspire' has 4 buttons:
- *   left,right,up,down.
- * This device always sets {mid,rig,lef}0 to 1 and
- * reflects left,right,down,up in lef1,rig1,mid1,up1.
+ * ?'s can have different meanings on different models,
+ * such as wheel rotation, extra buttons, stick buttons
+ * on a dualpoint, etc.
  */
 
 static void alps_process_packet(struct psmouse *psmouse, struct pt_regs *regs)
 {
+	struct alps_data *priv = psmouse->private;
 	unsigned char *packet = psmouse->packet;
 	struct input_dev *dev = &psmouse->dev;
-	int x, y, z;
-	int left = 0, right = 0, middle = 0;
+	struct input_dev *dev2 = &priv->dev2;
+	int x, y, z, ges, fin, left, right, middle;
 
 	input_regs(dev, regs);
 
 	if ((packet[0] & 0xc8) == 0x08) {   /* 3-byte PS/2 packet */
-		x = packet[1];
-		if (packet[0] & 0x10)
-			x = x - 256;
-		y = packet[2];
-		if (packet[0] & 0x20)
-			y = y - 256;
-		left  = (packet[0]     ) & 1;
-		right = (packet[0] >> 1) & 1;
-
-		input_report_rel(dev, REL_X, x);
-		input_report_rel(dev, REL_Y, -y);
-		input_report_key(dev, BTN_A, left);
-		input_report_key(dev, BTN_B, right);
-		input_sync(dev);
+		input_report_key(dev2, BTN_LEFT,   packet[0] & 1);    
+		input_report_key(dev2, BTN_RIGHT,  packet[0] & 2);
+		input_report_key(dev2, BTN_MIDDLE, packet[0] & 4);
+		input_report_rel(dev2, REL_X,
+			packet[1] ? packet[1] - ((packet[0] << 4) & 0x100) : 0);
+		input_report_rel(dev2, REL_Y,
+			packet[2] ? ((packet[0] << 3) & 0x100) - packet[2] : 0);
+		input_sync(dev2);
 		return;
 	}
 
-	x = (packet[1] & 0x7f) | ((packet[2] & 0x78)<<(7-3));
-	y = (packet[4] & 0x7f) | ((packet[3] & 0x70)<<(7-4));
-	z = packet[5];
-
-	if (z == 127) {	/* DualPoint stick is relative, not absolute */
-		if (x > 383)
-			x = x - 768;
-		if (y > 255)
-			y = y - 512;
-		left  = packet[3] & 1;
-		right = (packet[3] >> 1) & 1;
-
-		input_report_rel(dev, REL_X, x);
-		input_report_rel(dev, REL_Y, -y);
-		input_report_key(dev, BTN_LEFT, left);
-		input_report_key(dev, BTN_RIGHT, right);
+	if (priv->i->flags & ALPS_OLDPROTO) {
+		left = packet[2] & 0x08;
+		right = packet[2] & 0x10;
+		middle = 0;
+		x = packet[1] | ((packet[0] & 0x07) << 7);
+		y = packet[4] | ((packet[3] & 0x07) << 7);
+		z = packet[5];
+	} else {
+		left = packet[3] & 1;
+		right = packet[3] & 2;
+		middle = packet[3] & 4;
+		x = packet[1] | ((packet[2] & 0x78) << (7 - 3));
+		y = packet[4] | ((packet[3] & 0x70) << (7 - 4));
+		z = packet[5];
+	}
+
+	ges = packet[2] & 1;
+	fin = packet[2] & 2;
+
+	input_report_key(dev, BTN_LEFT, left);
+	input_report_key(dev, BTN_RIGHT, right);
+	input_report_key(dev, BTN_MIDDLE, middle);
+
+	if ((priv->i->flags & ALPS_DUALPOINT) && z == 127) {
+		input_report_rel(dev2, REL_X,  (x > 383 ? (x - 768) : x));
+		input_report_rel(dev2, REL_Y, -(y > 255 ? (y - 512) : y));
 		input_sync(dev);
+		input_sync(dev2);
 		return;
 	}
 
+	/* Convert hardware tap to a reasonable Z value */
+	if (ges && !fin) z = 40;
+
+	/*
+	 * A "tap and drag" operation is reported by the hardware as a transition
+	 * from (!fin && ges) to (fin && ges). This should be translated to the
+	 * sequence Z>0, Z==0, Z>0, so the Z==0 event has to be generated manually.
+	 */
+	if (ges && fin && !priv->prev_fin) {
+		input_report_abs(dev, ABS_X, x);
+		input_report_abs(dev, ABS_Y, y);
+		input_report_abs(dev, ABS_PRESSURE, 0);
+		input_report_key(dev, BTN_TOOL_FINGER, 0);
+		input_sync(dev);
+	}
+	priv->prev_fin = fin;
+
 	if (z > 30) input_report_key(dev, BTN_TOUCH, 1);
 	if (z < 25) input_report_key(dev, BTN_TOUCH, 0);
 
@@ -130,38 +151,26 @@
 		input_report_abs(dev, ABS_X, x);
 		input_report_abs(dev, ABS_Y, y);
 	}
+
 	input_report_abs(dev, ABS_PRESSURE, z);
 	input_report_key(dev, BTN_TOOL_FINGER, z > 0);
 
-	left  |= (packet[2]     ) & 1;
-	left  |= (packet[3]     ) & 1;
-	right |= (packet[3] >> 1) & 1;
-	if (packet[0] == 0xff) {
-		int back    = (packet[3] >> 2) & 1;
-		int forward = (packet[2] >> 2) & 1;
-		if (back && forward) {
-			middle = 1;
-			back = 0;
-			forward = 0;
-		}
-		input_report_key(dev, BTN_BACK,    back);
-		input_report_key(dev, BTN_FORWARD, forward);
-	} else {
-		left   |= (packet[0]     ) & 1;
-		right  |= (packet[0] >> 1) & 1;
-		middle |= (packet[0] >> 2) & 1;
-		middle |= (packet[3] >> 2) & 1;
-	}
 
-	input_report_key(dev, BTN_LEFT, left);
-	input_report_key(dev, BTN_RIGHT, right);
-	input_report_key(dev, BTN_MIDDLE, middle);
+	if (priv->i->flags & ALPS_WHEEL)
+		input_report_rel(dev, REL_WHEEL, ((packet[0] >> 4) & 0x07) | ((packet[2] >> 2) & 0x08));
+
+	if (priv->i->flags & ALPS_FW_BK) {
+		input_report_key(dev, BTN_FORWARD, packet[0] & 0x10);
+		input_report_key(dev, BTN_BACK, packet[2] & 0x04);
+	}
 
 	input_sync(dev);
 }
 
 static psmouse_ret_t alps_process_byte(struct psmouse *psmouse, struct pt_regs *regs)
 {
+	struct alps_data *priv = psmouse->private;
+
 	if ((psmouse->packet[0] & 0xc8) == 0x08) { /* PS/2 packet */
 		if (psmouse->pktcnt == 3) {
 			alps_process_packet(psmouse, regs);
@@ -170,13 +179,12 @@
 		return PSMOUSE_GOOD_DATA;
 	}
 
-	/* ALPS absolute mode packets start with 0b11111mrl */
-	if ((psmouse->packet[0] & 0xf8) != 0xf8)
+	if ((psmouse->packet[0] & priv->i->mask0) != priv->i->byte0)
 		return PSMOUSE_BAD_DATA;
 
 	/* Bytes 2 - 6 should have 0 in the highest bit */
 	if (psmouse->pktcnt >= 2 && psmouse->pktcnt <= 6 &&
-	    (psmouse->packet[psmouse->pktcnt-1] & 0x80))
+	    (psmouse->packet[psmouse->pktcnt - 1] & 0x80))
 		return PSMOUSE_BAD_DATA;
 
 	if (psmouse->pktcnt == 6) {
@@ -187,51 +195,58 @@
 	return PSMOUSE_GOOD_DATA;
 }
 
-int alps_get_model(struct psmouse *psmouse)
+static struct alps_model_info *alps_get_model(struct psmouse *psmouse, int *version)
 {
 	struct ps2dev *ps2dev = &psmouse->ps2dev;
+	unsigned char rates[] = { 0, 10, 20, 40, 60, 80, 100, 200 };
 	unsigned char param[4];
 	int i;
 
 	/*
 	 * First try "E6 report".
-	 * ALPS should return 0x00,0x00,0x0a or 0x00,0x00,0x64
+	 * ALPS should return 0,0,10 or 0,0,100
 	 */
 	param[0] = 0;
 	if (ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES) ||
 	    ps2_command(ps2dev,  NULL, PSMOUSE_CMD_SETSCALE11) ||
 	    ps2_command(ps2dev,  NULL, PSMOUSE_CMD_SETSCALE11) ||
 	    ps2_command(ps2dev,  NULL, PSMOUSE_CMD_SETSCALE11))
-		return -1;
+		return NULL;
 
 	param[0] = param[1] = param[2] = 0xff;
 	if (ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO))
-		return -1;
+		return NULL;
 
 	dbg("E6 report: %2.2x %2.2x %2.2x", param[0], param[1], param[2]);
 
-	if (param[0] != 0x00 || param[1] != 0x00 || (param[2] != 0x0a && param[2] != 0x64))
-		return -1;
+	if (param[0] != 0 || param[1] != 0 || (param[2] != 10 && param[2] != 100))
+		return NULL;
 
-	/* Now try "E7 report". ALPS should return 0x33 in byte 1 */
+	/*
+	 * Now try "E7 report". Allowed responses are in
+	 * alps_model_data[].signature
+	 */
 	param[0] = 0;
 	if (ps2_command(ps2dev, param, PSMOUSE_CMD_SETRES) ||
 	    ps2_command(ps2dev,  NULL, PSMOUSE_CMD_SETSCALE21) ||
 	    ps2_command(ps2dev,  NULL, PSMOUSE_CMD_SETSCALE21) ||
 	    ps2_command(ps2dev,  NULL, PSMOUSE_CMD_SETSCALE21))
-		return -1;
+		return NULL;
 
 	param[0] = param[1] = param[2] = 0xff;
 	if (ps2_command(ps2dev, param, PSMOUSE_CMD_GETINFO))
-		return -1;
+		return NULL;
 
 	dbg("E7 report: %2.2x %2.2x %2.2x", param[0], param[1], param[2]);
 
+	for (i = 0; i < ARRAY_SIZE(rates) && param[2] != rates[i]; i++);
+	*version = (param[0] << 8) | (param[1] << 4) | i;
+
 	for (i = 0; i < ARRAY_SIZE(alps_model_data); i++)
 		if (!memcmp(param, alps_model_data[i].signature, sizeof(alps_model_data[i].signature)))
-			return alps_model_data[i].model;
+			return alps_model_data + i;
 
-	return -1;
+	return NULL;
 }
 
 /*
@@ -322,27 +337,28 @@
 
 static int alps_reconnect(struct psmouse *psmouse)
 {
-	int model;
+	struct alps_data *priv = psmouse->private;
 	unsigned char param[4];
+	int version;
 
-	if ((model = alps_get_model(psmouse)) < 0)
+	if (!(priv->i = alps_get_model(psmouse, &version)))
 		return -1;
 
-	if (model == ALPS_MODEL_DUALPOINT && alps_passthrough_mode(psmouse, 1))
+	if (priv->i->flags & ALPS_PASS && alps_passthrough_mode(psmouse, 1))
 		return -1;
 
 	if (alps_get_status(psmouse, param))
 		return -1;
 
 	if (param[0] & 0x04)
-		alps_tap_mode(psmouse, 0);
+		alps_tap_mode(psmouse, 1);
 
 	if (alps_absolute_mode(psmouse)) {
 		printk(KERN_ERR "alps.c: Failed to enable absolute mode\n");
 		return -1;
 	}
 
-	if (model == ALPS_MODEL_DUALPOINT && alps_passthrough_mode(psmouse, 0))
+	if (priv->i->flags == ALPS_PASS && alps_passthrough_mode(psmouse, 0))
 		return -1;
 
 	return 0;
@@ -350,57 +366,83 @@
 
 static void alps_disconnect(struct psmouse *psmouse)
 {
+	struct alps_data *priv = psmouse->private;
 	psmouse_reset(psmouse);
+	input_unregister_device(&priv->dev2);
+	kfree(priv);
 }
 
 int alps_init(struct psmouse *psmouse)
 {
+	struct alps_data *priv;
 	unsigned char param[4];
-	int model;
+	int version;
 
-	if ((model = alps_get_model(psmouse)) < 0)
-		return -1;
+	psmouse->private = priv = kmalloc(sizeof(struct alps_data), GFP_KERNEL);
+	if (!priv)
+		goto init_fail;
+	memset(priv, 0, sizeof(struct alps_data));
 
-	printk(KERN_INFO "ALPS Touchpad (%s) detected\n",
-		model == ALPS_MODEL_GLIDEPOINT ? "Glidepoint" : "Dualpoint");
+	if (!(priv->i = alps_get_model(psmouse, &version)))
+		goto init_fail;
 
-	if (model == ALPS_MODEL_DUALPOINT && alps_passthrough_mode(psmouse, 1))
-		return -1;
+	if ((priv->i->flags & ALPS_PASS) && alps_passthrough_mode(psmouse, 1))
+		goto init_fail;
 
 	if (alps_get_status(psmouse, param)) {
 		printk(KERN_ERR "alps.c: touchpad status report request failed\n");
-		return -1;
+		goto init_fail;
 	}
 
 	if (param[0] & 0x04) {
-		printk(KERN_INFO "  Disabling hardware tapping\n");
-		if (alps_tap_mode(psmouse, 0))
-			printk(KERN_WARNING "alps.c: Failed to disable hardware tapping\n");
+		printk(KERN_INFO "  Enabling hardware tapping\n");
+		if (alps_tap_mode(psmouse, 1))
+			printk(KERN_WARNING "alps.c: Failed to enable hardware tapping\n");
 	}
 
 	if (alps_absolute_mode(psmouse)) {
 		printk(KERN_ERR "alps.c: Failed to enable absolute mode\n");
-		return -1;
+		goto init_fail;
 	}
 
-	if (model == ALPS_MODEL_DUALPOINT && alps_passthrough_mode(psmouse, 0))
-		return -1;
+	if ((priv->i->flags & ALPS_PASS) && alps_passthrough_mode(psmouse, 0))
+		goto init_fail;
 
-	psmouse->dev.evbit[LONG(EV_REL)] |= BIT(EV_REL);
-	psmouse->dev.relbit[LONG(REL_X)] |= BIT(REL_X);
-	psmouse->dev.relbit[LONG(REL_Y)] |= BIT(REL_Y);
-	psmouse->dev.keybit[LONG(BTN_A)] |= BIT(BTN_A);
-	psmouse->dev.keybit[LONG(BTN_B)] |= BIT(BTN_B);
+	psmouse->dev.evbit[LONG(EV_KEY)] |= BIT(EV_KEY);
+	psmouse->dev.keybit[LONG(BTN_TOUCH)] |= BIT(BTN_TOUCH);
+	psmouse->dev.keybit[LONG(BTN_TOOL_FINGER)] |= BIT(BTN_TOOL_FINGER);
+	psmouse->dev.keybit[LONG(BTN_LEFT)] |= BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
 
 	psmouse->dev.evbit[LONG(EV_ABS)] |= BIT(EV_ABS);
 	input_set_abs_params(&psmouse->dev, ABS_X, 0, 1023, 0, 0);
-	input_set_abs_params(&psmouse->dev, ABS_Y, 0, 1023, 0, 0);
+	input_set_abs_params(&psmouse->dev, ABS_Y, 0, 767, 0, 0);
 	input_set_abs_params(&psmouse->dev, ABS_PRESSURE, 0, 127, 0, 0);
 
-	psmouse->dev.keybit[LONG(BTN_TOUCH)] |= BIT(BTN_TOUCH);
-	psmouse->dev.keybit[LONG(BTN_TOOL_FINGER)] |= BIT(BTN_TOOL_FINGER);
-	psmouse->dev.keybit[LONG(BTN_FORWARD)] |= BIT(BTN_FORWARD);
-	psmouse->dev.keybit[LONG(BTN_BACK)] |= BIT(BTN_BACK);
+	if (priv->i->flags & ALPS_WHEEL) {
+		psmouse->dev.evbit[LONG(EV_REL)] |= BIT(EV_REL);
+		psmouse->dev.relbit[LONG(REL_WHEEL)] |= BIT(REL_WHEEL);
+	}
+
+	if (priv->i->flags & ALPS_FW_BK) {
+		psmouse->dev.keybit[LONG(BTN_FORWARD)] |= BIT(BTN_FORWARD);
+		psmouse->dev.keybit[LONG(BTN_BACK)] |= BIT(BTN_BACK);
+	}
+
+	sprintf(priv->phys, "%s/input1", psmouse->ps2dev.serio->phys);
+	priv->dev2.phys = priv->phys;
+	priv->dev2.name = (priv->i->flags & ALPS_DUALPOINT) ? "DualPoint Stick" : "PS/2 Mouse";
+	priv->dev2.id.bustype = BUS_I8042;
+	priv->dev2.id.vendor = 0x0002;
+	priv->dev2.id.product = PSMOUSE_ALPS;
+	priv->dev2.id.version = 0x0000; 
+	
+	priv->dev2.evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
+	priv->dev2.relbit[LONG(REL_X)] |= BIT(REL_X) | BIT(REL_Y);
+	priv->dev2.keybit[LONG(BTN_LEFT)] |= BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
+
+	input_register_device(&priv->dev2);
+
+	printk(KERN_INFO "input: %s on %s\n", priv->dev2.name, psmouse->ps2dev.serio->phys);
 
 	psmouse->protocol_handler = alps_process_byte;
 	psmouse->disconnect = alps_disconnect;
@@ -408,16 +450,27 @@
 	psmouse->pktsize = 6;
 
 	return 0;
+
+init_fail:
+	kfree(priv);
+	return -1;
 }
 
 int alps_detect(struct psmouse *psmouse, int set_properties)
 {
-	if (alps_get_model(psmouse) < 0)
+	int version;
+	struct alps_model_info *model; 
+
+	if (!(model = alps_get_model(psmouse, &version)))
 		return -1;
 
 	if (set_properties) {
 		psmouse->vendor = "ALPS";
-		psmouse->name = "TouchPad";
+		if (model->flags & ALPS_DUALPOINT) 
+			psmouse->name = "DualPoint TouchPad";
+		else
+			psmouse->name = "GlidePoint";
+		psmouse->model = version;
 	}
 	return 0;
 }
diff -Nru a/drivers/input/mouse/alps.h b/drivers/input/mouse/alps.h
--- a/drivers/input/mouse/alps.h	2005-03-11 12:51:51 -08:00
+++ b/drivers/input/mouse/alps.h	2005-03-11 12:51:51 -08:00
@@ -2,6 +2,7 @@
  * ALPS touchpad PS/2 mouse driver
  *
  * Copyright (c) 2003 Peter Osterlund <petero2@telia.com>
+ * Copyright (c) 2005 Vojtech Pavlik <vojtech@suse.cz>
  *
  * 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
@@ -13,5 +14,19 @@
 
 int alps_detect(struct psmouse *psmouse, int set_properties);
 int alps_init(struct psmouse *psmouse);
+
+struct alps_model_info {
+        unsigned char signature[3];
+        unsigned char byte0, mask0;
+        unsigned char flags;
+};
+
+struct alps_data {
+	struct input_dev dev2;		/* Relative device */
+	char name[32];			/* Name */
+	char phys[32];			/* Phys */
+	struct alps_model_info *i; 	/* Info */
+	int prev_fin;			/* Finger bit from previous packet */
+};
 
 #endif
diff -Nru a/drivers/input/mouse/hil_ptr.c b/drivers/input/mouse/hil_ptr.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/input/mouse/hil_ptr.c	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,414 @@
+/*
+ * Generic linux-input device driver for axis-bearing devices
+ *
+ * Copyright (c) 2001 Brian S. Julin
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions, and the following disclaimer,
+ *    without modification.
+ * 2. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL").
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ *
+ * References:
+ * HP-HIL Technical Reference Manual.  Hewlett Packard Product No. 45918A
+ *
+ */
+
+#include <linux/hil.h>
+#include <linux/input.h>
+#include <linux/serio.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/pci_ids.h>
+
+#define PREFIX "HIL PTR: "
+#define HIL_GENERIC_NAME "HIL pointer device"
+
+MODULE_AUTHOR("Brian S. Julin <bri@calyx.com>");
+MODULE_DESCRIPTION(HIL_GENERIC_NAME " driver");
+MODULE_LICENSE("Dual BSD/GPL");
+
+
+#define TABLET_SIMULATES_MOUSE	/* allow tablet to be used as mouse */
+#undef  TABLET_AUTOADJUST	/* auto-adjust valid tablet ranges */
+
+
+#define HIL_PTR_MAX_LENGTH 16
+
+struct hil_ptr {
+	struct input_dev dev;
+	struct serio *serio;
+
+	/* Input buffer and index for packets from HIL bus. */
+	hil_packet data[HIL_PTR_MAX_LENGTH];
+	int idx4; /* four counts per packet */
+
+	/* Raw device info records from HIL bus, see hil.h for fields. */
+	char	idd[HIL_PTR_MAX_LENGTH];	/* DID byte and IDD record */
+	char	rsc[HIL_PTR_MAX_LENGTH];	/* RSC record */
+	char	exd[HIL_PTR_MAX_LENGTH];	/* EXD record */
+	char	rnm[HIL_PTR_MAX_LENGTH + 1];	/* RNM record + NULL term. */
+
+	/* Extra device details not contained in struct input_dev. */
+	unsigned int nbtn, naxes;
+	unsigned int btnmap[7];
+
+	/* Something to sleep around with. */
+	struct semaphore sem;
+};
+
+/* Process a complete packet after transfer from the HIL */
+static void hil_ptr_process_record(struct hil_ptr *ptr)
+{
+	struct input_dev *dev = &ptr->dev;
+	hil_packet *data = ptr->data;
+	hil_packet p;
+	int idx, i, cnt, laxis;
+	int ax16, absdev;
+
+	idx = ptr->idx4/4;
+	p = data[idx - 1];
+
+	if ((p & ~HIL_CMDCT_POL) == 
+	    (HIL_ERR_INT | HIL_PKT_CMD | HIL_CMD_POL)) goto report;
+	if ((p & ~HIL_CMDCT_RPL) == 
+	    (HIL_ERR_INT | HIL_PKT_CMD | HIL_CMD_RPL)) goto report;
+
+	/* Not a poll response.  See if we are loading config records. */
+	switch (p & HIL_PKT_DATA_MASK) {
+	case HIL_CMD_IDD:
+		for (i = 0; i < idx; i++)
+			ptr->idd[i] = ptr->data[i] & HIL_PKT_DATA_MASK;
+		for (; i < HIL_PTR_MAX_LENGTH; i++)
+			ptr->idd[i] = 0;
+		break;
+	case HIL_CMD_RSC:
+		for (i = 0; i < idx; i++)
+			ptr->rsc[i] = ptr->data[i] & HIL_PKT_DATA_MASK;
+		for (; i < HIL_PTR_MAX_LENGTH; i++)
+			ptr->rsc[i] = 0;
+		break;
+	case HIL_CMD_EXD:
+		for (i = 0; i < idx; i++)
+			ptr->exd[i] = ptr->data[i] & HIL_PKT_DATA_MASK;
+		for (; i < HIL_PTR_MAX_LENGTH; i++)
+			ptr->exd[i] = 0;
+		break;
+	case HIL_CMD_RNM:
+		for (i = 0; i < idx; i++)
+			ptr->rnm[i] = ptr->data[i] & HIL_PKT_DATA_MASK;
+		for (; i < HIL_PTR_MAX_LENGTH + 1; i++)
+			ptr->rnm[i] = '\0';
+		break;
+	default:
+		/* These occur when device isn't present */
+		if (p == (HIL_ERR_INT | HIL_PKT_CMD)) break; 
+		/* Anything else we'd like to know about. */
+		printk(KERN_WARNING PREFIX "Device sent unknown record %x\n", p);
+		break;
+	}
+	goto out;
+
+ report:
+	if ((p & HIL_CMDCT_POL) != idx - 1) {
+		printk(KERN_WARNING PREFIX "Malformed poll packet %x (idx = %i)\n", p, idx);
+		goto out;
+	}
+
+	i = (ptr->data[0] & HIL_POL_AXIS_ALT) ? 3 : 0;
+	laxis = ptr->data[0] & HIL_POL_NUM_AXES_MASK;
+	laxis += i;
+
+	ax16 = ptr->idd[1] & HIL_IDD_HEADER_16BIT; /* 8 or 16bit resolution */
+	absdev = ptr->idd[1] & HIL_IDD_HEADER_ABS; 
+
+	for (cnt = 1; i < laxis; i++) {
+		unsigned int lo,hi,val;
+		lo = ptr->data[cnt++] & HIL_PKT_DATA_MASK;
+		hi = ax16 ? (ptr->data[cnt++] & HIL_PKT_DATA_MASK) : 0;
+		if (absdev) {
+			val = lo + (hi<<8);
+#ifdef TABLET_AUTOADJUST
+			if (val < ptr->dev.absmin[ABS_X + i])
+				ptr->dev.absmin[ABS_X + i] = val;
+			if (val > ptr->dev.absmax[ABS_X + i])
+				ptr->dev.absmax[ABS_X + i] = val;
+#endif
+			if (i%3) val = ptr->dev.absmax[ABS_X + i] - val;
+			input_report_abs(dev, ABS_X + i, val);
+		} else {
+			val = (int) (((int8_t)lo) | ((int8_t)hi<<8));
+			if (i%3) val *= -1;
+			input_report_rel(dev, REL_X + i, val);
+		}
+	}
+
+	while (cnt < idx - 1) {
+		unsigned int btn;
+		int up;
+		btn = ptr->data[cnt++];
+		up = btn & 1;
+		btn &= 0xfe;
+		if (btn == 0x8e) {
+			continue; /* TODO: proximity == touch? */
+		}
+		else if ((btn > 0x8c) || (btn < 0x80)) continue;
+		btn = (btn - 0x80) >> 1;
+		btn = ptr->btnmap[btn];
+		input_report_key(dev, btn, !up);
+	}
+	input_sync(dev);
+ out:
+	ptr->idx4 = 0;
+	up(&ptr->sem);
+}
+
+static void hil_ptr_process_err(struct hil_ptr *ptr) {
+	printk(KERN_WARNING PREFIX "errored HIL packet\n");
+	ptr->idx4 = 0;
+	up(&ptr->sem);
+	return;
+}
+
+static irqreturn_t hil_ptr_interrupt(struct serio *serio, 
+        unsigned char data, unsigned int flags, struct pt_regs *regs)
+{
+	struct hil_ptr *ptr;
+	hil_packet packet;
+	int idx;
+
+	ptr = (struct hil_ptr *)serio->private;
+	if (ptr == NULL) {
+		BUG();
+		return IRQ_HANDLED;
+	}
+
+	if (ptr->idx4 >= (HIL_PTR_MAX_LENGTH * sizeof(hil_packet))) {
+		hil_ptr_process_err(ptr);
+		return IRQ_HANDLED;
+	}
+	idx = ptr->idx4/4;
+	if (!(ptr->idx4 % 4)) ptr->data[idx] = 0;
+	packet = ptr->data[idx];
+	packet |= ((hil_packet)data) << ((3 - (ptr->idx4 % 4)) * 8);
+	ptr->data[idx] = packet;
+
+	/* Records of N 4-byte hil_packets must terminate with a command. */
+	if ((++(ptr->idx4)) % 4) return IRQ_HANDLED;
+	if ((packet & 0xffff0000) != HIL_ERR_INT) {
+		hil_ptr_process_err(ptr);
+		return IRQ_HANDLED;
+	}
+	if (packet & HIL_PKT_CMD) 
+		hil_ptr_process_record(ptr);
+	return IRQ_HANDLED;
+}
+
+static void hil_ptr_disconnect(struct serio *serio)
+{
+	struct hil_ptr *ptr;
+
+	ptr = (struct hil_ptr *)serio->private;
+	if (ptr == NULL) {
+		BUG();
+		return;
+	}
+
+	input_unregister_device(&ptr->dev);
+	serio_close(serio);
+	kfree(ptr);
+}
+
+static void hil_ptr_connect(struct serio *serio, struct serio_driver *driver)
+{
+	struct hil_ptr	*ptr;
+	char		*txt;
+	unsigned int	i, naxsets, btntype;
+	uint8_t		did, *idd;
+
+	if (serio->type != (SERIO_HIL_MLC | SERIO_HIL)) return;
+
+	if (!(ptr = kmalloc(sizeof(struct hil_ptr), GFP_KERNEL))) return;
+	memset(ptr, 0, sizeof(struct hil_ptr));
+
+	if (serio_open(serio, driver)) goto bail0;
+
+	serio->private = ptr;
+	ptr->serio = serio;
+	ptr->dev.private = ptr;
+
+	init_MUTEX_LOCKED(&(ptr->sem));
+
+	/* Get device info.  MLC driver supplies devid/status/etc. */
+	serio->write(serio, 0);
+	serio->write(serio, 0);
+	serio->write(serio, HIL_PKT_CMD >> 8);
+	serio->write(serio, HIL_CMD_IDD);
+	down(&(ptr->sem));
+
+	serio->write(serio, 0);
+	serio->write(serio, 0);
+	serio->write(serio, HIL_PKT_CMD >> 8);
+	serio->write(serio, HIL_CMD_RSC);
+	down(&(ptr->sem));
+
+	serio->write(serio, 0);
+	serio->write(serio, 0);
+	serio->write(serio, HIL_PKT_CMD >> 8);
+	serio->write(serio, HIL_CMD_RNM);
+	down(&(ptr->sem));
+
+	serio->write(serio, 0);
+	serio->write(serio, 0);
+	serio->write(serio, HIL_PKT_CMD >> 8);
+	serio->write(serio, HIL_CMD_EXD);
+	down(&(ptr->sem));
+
+	up(&(ptr->sem));
+
+	init_input_dev(&ptr->dev);
+	did = ptr->idd[0];
+	idd = ptr->idd + 1;
+	txt = "unknown";
+	if ((did & HIL_IDD_DID_TYPE_MASK) == HIL_IDD_DID_TYPE_REL) {
+		ptr->dev.evbit[0] = BIT(EV_REL);
+		txt = "relative";
+	}
+
+	if ((did & HIL_IDD_DID_TYPE_MASK) == HIL_IDD_DID_TYPE_ABS) {
+		ptr->dev.evbit[0] = BIT(EV_ABS);
+		txt = "absolute";
+	}
+	if (!ptr->dev.evbit[0]) {
+		goto bail1;
+	}
+
+	ptr->nbtn = HIL_IDD_NUM_BUTTONS(idd);
+	if (ptr->nbtn) ptr->dev.evbit[0] |= BIT(EV_KEY);
+
+	naxsets = HIL_IDD_NUM_AXSETS(*idd);
+	ptr->naxes = HIL_IDD_NUM_AXES_PER_SET(*idd);
+
+	printk(KERN_INFO PREFIX "HIL pointer device found (did: 0x%02x, axis: %s)\n",
+			did, txt);
+	printk(KERN_INFO PREFIX "HIL pointer has %i buttons and %i sets of %i axes\n",
+			ptr->nbtn, naxsets, ptr->naxes);
+	
+	btntype = BTN_MISC;
+	if ((did & HIL_IDD_DID_ABS_TABLET_MASK) == HIL_IDD_DID_ABS_TABLET)
+#ifdef TABLET_SIMULATES_MOUSE
+		btntype = BTN_TOUCH;
+#else
+		btntype = BTN_DIGI;
+#endif
+	if ((did & HIL_IDD_DID_ABS_TSCREEN_MASK) == HIL_IDD_DID_ABS_TSCREEN)
+		btntype = BTN_TOUCH;
+		
+	if ((did & HIL_IDD_DID_REL_MOUSE_MASK) == HIL_IDD_DID_REL_MOUSE)
+		btntype = BTN_MOUSE;
+
+	for (i = 0; i < ptr->nbtn; i++) {
+		set_bit(btntype | i, ptr->dev.keybit);
+		ptr->btnmap[i] = btntype | i;
+	}
+
+	if (btntype == BTN_MOUSE) {
+		/* Swap buttons 2 and 3 */
+		ptr->btnmap[1] = BTN_MIDDLE;
+		ptr->btnmap[2] = BTN_RIGHT;
+	}
+
+	if ((did & HIL_IDD_DID_TYPE_MASK) == HIL_IDD_DID_TYPE_REL) {
+		for (i = 0; i < ptr->naxes; i++) {
+			set_bit(REL_X + i, ptr->dev.relbit);
+		}
+		for (i = 3; (i < ptr->naxes + 3) && (naxsets > 1); i++) {
+			set_bit(REL_X + i, ptr->dev.relbit);
+		}
+	} else {
+		for (i = 0; i < ptr->naxes; i++) {
+	  		set_bit(ABS_X + i, ptr->dev.absbit);
+			ptr->dev.absmin[ABS_X + i] = 0;
+			ptr->dev.absmax[ABS_X + i] = 
+				HIL_IDD_AXIS_MAX((ptr->idd + 1), i);
+		}
+		for (i = 3; (i < ptr->naxes + 3) && (naxsets > 1); i++) {
+			set_bit(ABS_X + i, ptr->dev.absbit);
+			ptr->dev.absmin[ABS_X + i] = 0;
+			ptr->dev.absmax[ABS_X + i] = 
+				HIL_IDD_AXIS_MAX((ptr->idd + 1), (i - 3));
+		}
+#ifdef TABLET_AUTOADJUST
+		for (i = 0; i < ABS_MAX; i++) {
+			int diff = ptr->dev.absmax[ABS_X + i] / 10;
+			ptr->dev.absmin[ABS_X + i] += diff;
+			ptr->dev.absmax[ABS_X + i] -= diff;
+		}
+#endif
+	}
+
+	ptr->dev.name = strlen(ptr->rnm) ? ptr->rnm : HIL_GENERIC_NAME;
+
+	ptr->dev.id.bustype	= BUS_HIL;
+	ptr->dev.id.vendor	= PCI_VENDOR_ID_HP;
+	ptr->dev.id.product	= 0x0001; /* TODO: get from ptr->rsc */
+	ptr->dev.id.version	= 0x0100; /* TODO: get from ptr->rsc */
+	ptr->dev.dev		= &serio->dev;
+
+	input_register_device(&ptr->dev);
+	printk(KERN_INFO "input: %s (%s), ID: %d\n",
+                ptr->dev.name, 
+		(btntype == BTN_MOUSE) ? "HIL mouse":"HIL tablet or touchpad",
+		did);
+
+	return;
+ bail1:
+	serio_close(serio);
+ bail0:
+	kfree(ptr);
+	return;
+}
+
+
+static struct serio_driver hil_ptr_serio_driver = {
+	.driver		= {
+		.name	= "hil_ptr",
+	},
+	.description	= "HP HIL mouse/tablet driver",
+	.connect =	hil_ptr_connect,
+	.disconnect =	hil_ptr_disconnect,
+	.interrupt =	hil_ptr_interrupt
+};
+
+static int __init hil_ptr_init(void)
+{
+	serio_register_driver(&hil_ptr_serio_driver);
+        return 0;
+}
+                
+static void __exit hil_ptr_exit(void)
+{
+	serio_unregister_driver(&hil_ptr_serio_driver);
+}
+                        
+module_init(hil_ptr_init);
+module_exit(hil_ptr_exit);
diff -Nru a/drivers/input/mouse/logips2pp.c b/drivers/input/mouse/logips2pp.c
--- a/drivers/input/mouse/logips2pp.c	2005-03-11 12:51:47 -08:00
+++ b/drivers/input/mouse/logips2pp.c	2005-03-11 12:51:47 -08:00
@@ -202,6 +202,9 @@
 	static struct ps2pp_info ps2pp_list[] = {
 		{ 12,	0,			PS2PP_SIDE_BTN},
 		{ 13,	0,			0 },
+		{ 15,	PS2PP_KIND_MX,					/* MX1000 */
+				PS2PP_WHEEL | PS2PP_SIDE_BTN | PS2PP_TASK_BTN |
+				PS2PP_EXTRA_BTN | PS2PP_NAV_BTN | PS2PP_HWHEEL },
 		{ 40,	0,			PS2PP_SIDE_BTN },
 		{ 41,	0,			PS2PP_SIDE_BTN },
 		{ 42,	0,			PS2PP_SIDE_BTN },
@@ -210,9 +213,9 @@
 		{ 51,	0,			0 },
 		{ 52,	PS2PP_KIND_WHEEL,	PS2PP_SIDE_BTN | PS2PP_WHEEL },
 		{ 53,	PS2PP_KIND_WHEEL,	PS2PP_WHEEL },
-		{ 61,	PS2PP_KIND_MX,
+		{ 61,	PS2PP_KIND_MX,					/* MX700 */
 				PS2PP_WHEEL | PS2PP_SIDE_BTN | PS2PP_TASK_BTN |
-				PS2PP_EXTRA_BTN | PS2PP_NAV_BTN },	/* MX700 */
+				PS2PP_EXTRA_BTN | PS2PP_NAV_BTN },
 		{ 73,	0,			PS2PP_SIDE_BTN },
 		{ 75,	PS2PP_KIND_WHEEL,	PS2PP_WHEEL },
 		{ 76,	PS2PP_KIND_WHEEL,	PS2PP_WHEEL },
@@ -222,15 +225,17 @@
 		{ 88,	PS2PP_KIND_WHEEL,	PS2PP_WHEEL },
 		{ 96,	0,			0 },
 		{ 97,	PS2PP_KIND_TP3,		PS2PP_WHEEL | PS2PP_HWHEEL },
-		{ 100,	PS2PP_KIND_MX,
+		{ 100,	PS2PP_KIND_MX,					/* MX510 */
 				PS2PP_WHEEL | PS2PP_SIDE_BTN | PS2PP_TASK_BTN |
-				PS2PP_EXTRA_BTN | PS2PP_NAV_BTN },	/* MX510 */
-		{ 112,	PS2PP_KIND_MX,
+				PS2PP_EXTRA_BTN | PS2PP_NAV_BTN },
+		{ 111,  PS2PP_KIND_MX,					/* MX300 */
+				PS2PP_WHEEL | PS2PP_EXTRA_BTN | PS2PP_TASK_BTN },
+		{ 112,	PS2PP_KIND_MX,					/* MX500 */
 				PS2PP_WHEEL | PS2PP_SIDE_BTN | PS2PP_TASK_BTN |
-				PS2PP_EXTRA_BTN | PS2PP_NAV_BTN },	/* MX500 */
-		{ 114,	PS2PP_KIND_MX,
+				PS2PP_EXTRA_BTN | PS2PP_NAV_BTN },
+		{ 114,	PS2PP_KIND_MX,					/* MX310 */
 				PS2PP_WHEEL | PS2PP_SIDE_BTN |
-				PS2PP_TASK_BTN | PS2PP_EXTRA_BTN },	/* M310 */
+				PS2PP_TASK_BTN | PS2PP_EXTRA_BTN },
 		{ }
 	};
 	int i;
@@ -238,6 +243,8 @@
 	for (i = 0; ps2pp_list[i].model; i++)
 		if (model == ps2pp_list[i].model)
 			return &ps2pp_list[i];
+
+	printk(KERN_WARNING "logips2pp: Detected unknown logitech mouse model %d\n", model);
 	return NULL;
 }
 
diff -Nru a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c
--- a/drivers/input/mouse/psmouse-base.c	2005-03-11 12:51:41 -08:00
+++ b/drivers/input/mouse/psmouse-base.c	2005-03-11 12:51:41 -08:00
@@ -31,25 +31,30 @@
 MODULE_DESCRIPTION(DRIVER_DESC);
 MODULE_LICENSE("GPL");
 
-static char *psmouse_proto;
 static unsigned int psmouse_max_proto = -1U;
-module_param_named(proto, psmouse_proto, charp, 0);
-MODULE_PARM_DESC(proto, "Highest protocol extension to probe (bare, imps, exps). Useful for KVM switches.");
+static int psmouse_set_maxproto(const char *val, struct kernel_param *kp);
+static int psmouse_get_maxproto(char *buffer, struct kernel_param *kp);
+static char *psmouse_proto_abbrev[] = { NULL, "bare", NULL, NULL, NULL, "imps", "exps", NULL, NULL, NULL };
+#define param_check_proto_abbrev(name, p)	__param_check(name, p, unsigned int)
+#define param_set_proto_abbrev			psmouse_set_maxproto
+#define param_get_proto_abbrev			psmouse_get_maxproto
+module_param_named(proto, psmouse_max_proto, proto_abbrev, 0644);
+MODULE_PARM_DESC(proto, "Highest protocol extension to probe (bare, imps, exps, any). Useful for KVM switches.");
 
 static unsigned int psmouse_resolution = 200;
-module_param_named(resolution, psmouse_resolution, uint, 0);
+module_param_named(resolution, psmouse_resolution, uint, 0644);
 MODULE_PARM_DESC(resolution, "Resolution, in dpi.");
 
 static unsigned int psmouse_rate = 100;
-module_param_named(rate, psmouse_rate, uint, 0);
+module_param_named(rate, psmouse_rate, uint, 0644);
 MODULE_PARM_DESC(rate, "Report rate, in reports per second.");
 
 static unsigned int psmouse_smartscroll = 1;
-module_param_named(smartscroll, psmouse_smartscroll, bool, 0);
+module_param_named(smartscroll, psmouse_smartscroll, bool, 0644);
 MODULE_PARM_DESC(smartscroll, "Logitech Smartscroll autorepeat, 1 = enabled (default), 0 = disabled.");
 
 static unsigned int psmouse_resetafter;
-module_param_named(resetafter, psmouse_resetafter, uint, 0);
+module_param_named(resetafter, psmouse_resetafter, uint, 0644);
 MODULE_PARM_DESC(resetafter, "Reset device after so many bad packets (0 = never).");
 
 PSMOUSE_DEFINE_ATTR(rate);
@@ -142,7 +147,7 @@
 static irqreturn_t psmouse_interrupt(struct serio *serio,
 		unsigned char data, unsigned int flags, struct pt_regs *regs)
 {
-	struct psmouse *psmouse = serio->private;
+	struct psmouse *psmouse = serio_get_drvdata(serio);
 	psmouse_ret_t rc;
 
 	if (psmouse->state == PSMOUSE_IGNORE)
@@ -423,7 +428,7 @@
  * upsets the thinkingmouse).
  */
 
-	if (max_proto > PSMOUSE_PS2 && thinking_detect(psmouse, set_properties) == 0)
+	if (max_proto > PSMOUSE_IMEX && thinking_detect(psmouse, set_properties) == 0)
 		return PSMOUSE_THINKPS;
 
 /*
@@ -634,7 +639,7 @@
 
 static void psmouse_cleanup(struct serio *serio)
 {
-	struct psmouse *psmouse = serio->private;
+	struct psmouse *psmouse = serio_get_drvdata(serio);
 
 	psmouse_reset(psmouse);
 }
@@ -651,11 +656,11 @@
 	device_remove_file(&serio->dev, &psmouse_attr_resolution);
 	device_remove_file(&serio->dev, &psmouse_attr_resetafter);
 
-	psmouse = serio->private;
+	psmouse = serio_get_drvdata(serio);
 	psmouse_set_state(psmouse, PSMOUSE_CMD_MODE);
 
-	if (serio->parent && (serio->type & SERIO_TYPE) == SERIO_PS_PSTHRU) {
-		parent = serio->parent->private;
+	if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) {
+		parent = serio_get_drvdata(serio->parent);
 		if (parent->pt_deactivate)
 			parent->pt_deactivate(parent);
 	}
@@ -667,6 +672,7 @@
 
 	input_unregister_device(&psmouse->dev);
 	serio_close(serio);
+	serio_set_drvdata(serio, NULL);
 	kfree(psmouse);
 }
 
@@ -674,29 +680,29 @@
  * psmouse_connect() is a callback from the serio module when
  * an unhandled serio port is found.
  */
-static void psmouse_connect(struct serio *serio, struct serio_driver *drv)
+static int psmouse_connect(struct serio *serio, struct serio_driver *drv)
 {
 	struct psmouse *psmouse, *parent = NULL;
-
-	if ((serio->type & SERIO_TYPE) != SERIO_8042 &&
-	    (serio->type & SERIO_TYPE) != SERIO_PS_PSTHRU)
-		return;
+	int retval;
 
 	/*
 	 * If this is a pass-through port deactivate parent so the device
 	 * connected to this port can be successfully identified
 	 */
-	if (serio->parent && (serio->type & SERIO_TYPE) == SERIO_PS_PSTHRU) {
-		parent = serio->parent->private;
+	if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) {
+		parent = serio_get_drvdata(serio->parent);
 		psmouse_deactivate(parent);
 	}
 
-	if (!(psmouse = kmalloc(sizeof(struct psmouse), GFP_KERNEL)))
+	if (!(psmouse = kmalloc(sizeof(struct psmouse), GFP_KERNEL))) {
+		retval = -ENOMEM;
 		goto out;
+	}
 
 	memset(psmouse, 0, sizeof(struct psmouse));
 
 	ps2_init(&psmouse->ps2dev, serio);
+	sprintf(psmouse->phys, "%s/input0", serio->phys);
 	psmouse->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
 	psmouse->dev.keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
 	psmouse->dev.relbit[0] = BIT(REL_X) | BIT(REL_Y);
@@ -704,17 +710,20 @@
 	psmouse->dev.dev = &serio->dev;
 	psmouse_set_state(psmouse, PSMOUSE_INITIALIZING);
 
-	serio->private = psmouse;
-	if (serio_open(serio, drv)) {
+	serio_set_drvdata(serio, psmouse);
+
+	retval = serio_open(serio, drv);
+	if (retval) {
+		serio_set_drvdata(serio, NULL);
 		kfree(psmouse);
-		serio->private = NULL;
 		goto out;
 	}
 
 	if (psmouse_probe(psmouse) < 0) {
 		serio_close(serio);
+		serio_set_drvdata(serio, NULL);
 		kfree(psmouse);
-		serio->private = NULL;
+		retval = -ENODEV;
 		goto out;
 	}
 
@@ -731,8 +740,6 @@
 
 	sprintf(psmouse->devname, "%s %s %s",
 		psmouse_protocols[psmouse->type], psmouse->vendor, psmouse->name);
-	sprintf(psmouse->phys, "%s/input0",
-		serio->phys);
 
 	psmouse->dev.name = psmouse->devname;
 	psmouse->dev.phys = psmouse->phys;
@@ -756,26 +763,22 @@
 	device_create_file(&serio->dev, &psmouse_attr_resolution);
 	device_create_file(&serio->dev, &psmouse_attr_resetafter);
 
-	if (serio->child) {
-		/*
-		 * Nothing to be done here, serio core will detect that
-		 * the driver set serio->child and will register it for us.
-		 */
-		printk(KERN_INFO "serio: %s port at %s\n", serio->child->name, psmouse->phys);
-	}
-
 	psmouse_activate(psmouse);
 
+	retval = 0;
+
 out:
 	/* If this is a pass-through port the parent awaits to be activated */
 	if (parent)
 		psmouse_activate(parent);
+
+	return retval;
 }
 
 
 static int psmouse_reconnect(struct serio *serio)
 {
-	struct psmouse *psmouse = serio->private;
+	struct psmouse *psmouse = serio_get_drvdata(serio);
 	struct psmouse *parent = NULL;
 	struct serio_driver *drv = serio->drv;
 	int rc = -1;
@@ -785,8 +788,8 @@
 		return -1;
 	}
 
-	if (serio->parent && (serio->type & SERIO_TYPE) == SERIO_PS_PSTHRU) {
-		parent = serio->parent->private;
+	if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) {
+		parent = serio_get_drvdata(serio->parent);
 		psmouse_deactivate(parent);
 	}
 
@@ -820,12 +823,30 @@
 	return rc;
 }
 
+static struct serio_device_id psmouse_serio_ids[] = {
+	{
+		.type	= SERIO_8042,
+		.proto	= SERIO_ANY,
+		.id	= SERIO_ANY,
+		.extra	= SERIO_ANY,
+	},
+	{
+		.type	= SERIO_PS_PSTHRU,
+		.proto	= SERIO_ANY,
+		.id	= SERIO_ANY,
+		.extra	= SERIO_ANY,
+	},
+	{ 0 }
+};
+
+MODULE_DEVICE_TABLE(serio, psmouse_serio_ids);
 
 static struct serio_driver psmouse_drv = {
 	.driver		= {
 		.name	= "psmouse",
 	},
 	.description	= DRIVER_DESC,
+	.id_table	= psmouse_serio_ids,
 	.interrupt	= psmouse_interrupt,
 	.connect	= psmouse_connect,
 	.reconnect	= psmouse_reconnect,
@@ -848,7 +869,7 @@
 		goto out;
 	}
 
-	retval = handler(serio->private, buf);
+	retval = handler(serio_get_drvdata(serio), buf);
 
 out:
 	serio_unpin_driver(serio);
@@ -859,7 +880,8 @@
 				ssize_t (*handler)(struct psmouse *, const char *, size_t))
 {
 	struct serio *serio = to_serio_port(dev);
-	struct psmouse *psmouse = serio->private, *parent = NULL;
+	struct psmouse *psmouse = serio_get_drvdata(serio);
+	struct psmouse *parent = NULL;
 	int retval;
 
 	retval = serio_pin_driver(serio);
@@ -871,8 +893,8 @@
 		goto out;
 	}
 
-	if (serio->parent && (serio->type & SERIO_TYPE) == SERIO_PS_PSTHRU) {
-		parent = serio->parent->private;
+	if (serio->parent && serio->id.type == SERIO_PS_PSTHRU) {
+		parent = serio_get_drvdata(serio->parent);
 		psmouse_deactivate(parent);
 	}
 	psmouse_deactivate(psmouse);
@@ -942,28 +964,45 @@
 	return count;
 }
 
-static inline void psmouse_parse_proto(void)
+static int psmouse_set_maxproto(const char *val, struct kernel_param *kp)
 {
-	if (psmouse_proto) {
-		if (!strcmp(psmouse_proto, "bare"))
-			psmouse_max_proto = PSMOUSE_PS2;
-		else if (!strcmp(psmouse_proto, "imps"))
-			psmouse_max_proto = PSMOUSE_IMPS;
-		else if (!strcmp(psmouse_proto, "exps"))
-			psmouse_max_proto = PSMOUSE_IMEX;
-		else
-			printk(KERN_ERR "psmouse: unknown protocol type '%s'\n", psmouse_proto);
+	int i;
+
+	if (!val)
+		return -EINVAL;
+
+	if (!strncmp(val, "any", 3)) {
+		*((unsigned int *)kp->arg) = -1UL;
+		return 0;
 	}
+
+	for (i = 0; i < ARRAY_SIZE(psmouse_proto_abbrev); i++) {
+		if (!psmouse_proto_abbrev[i])
+			continue;
+
+		if (!strncmp(val, psmouse_proto_abbrev[i], strlen(psmouse_proto_abbrev[i]))) {
+			*((unsigned int *)kp->arg) = i;
+			return 0;
+		}
+	}
+
+	return -EINVAL;					\
+}
+
+static int psmouse_get_maxproto(char *buffer, struct kernel_param *kp)
+{
+	return sprintf(buffer, "%s\n",
+			psmouse_max_proto < ARRAY_SIZE(psmouse_proto_abbrev) ?
+				psmouse_proto_abbrev[psmouse_max_proto] : "any");
 }
 
-int __init psmouse_init(void)
+static int __init psmouse_init(void)
 {
-	psmouse_parse_proto();
 	serio_register_driver(&psmouse_drv);
 	return 0;
 }
 
-void __exit psmouse_exit(void)
+static void __exit psmouse_exit(void)
 {
 	serio_unregister_driver(&psmouse_drv);
 }
diff -Nru a/drivers/input/mouse/psmouse.h b/drivers/input/mouse/psmouse.h
--- a/drivers/input/mouse/psmouse.h	2005-03-11 12:51:51 -08:00
+++ b/drivers/input/mouse/psmouse.h	2005-03-11 12:51:51 -08:00
@@ -44,7 +44,7 @@
 	unsigned char pktcnt;
 	unsigned char pktsize;
 	unsigned char type;
-	unsigned char model;
+	unsigned int model;
 	unsigned long last;
 	unsigned long out_of_sync;
 	enum psmouse_state state;
diff -Nru a/drivers/input/mouse/sermouse.c b/drivers/input/mouse/sermouse.c
--- a/drivers/input/mouse/sermouse.c	2005-03-11 12:51:47 -08:00
+++ b/drivers/input/mouse/sermouse.c	2005-03-11 12:51:47 -08:00
@@ -209,7 +209,7 @@
 static irqreturn_t sermouse_interrupt(struct serio *serio,
 		unsigned char data, unsigned int flags, struct pt_regs *regs)
 {
-	struct sermouse *sermouse = serio->private;
+	struct sermouse *sermouse = serio_get_drvdata(serio);
 
 	if (time_after(jiffies, sermouse->last + HZ/10)) sermouse->count = 0;
 	sermouse->last = jiffies;
@@ -228,9 +228,11 @@
 
 static void sermouse_disconnect(struct serio *serio)
 {
-	struct sermouse *sermouse = serio->private;
+	struct sermouse *sermouse = serio_get_drvdata(serio);
+
 	input_unregister_device(&sermouse->dev);
 	serio_close(serio);
+	serio_set_drvdata(serio, NULL);
 	kfree(sermouse);
 }
 
@@ -239,19 +241,17 @@
  * an unhandled serio port is found.
  */
 
-static void sermouse_connect(struct serio *serio, struct serio_driver *drv)
+static int sermouse_connect(struct serio *serio, struct serio_driver *drv)
 {
 	struct sermouse *sermouse;
 	unsigned char c;
+	int err;
 
-	if ((serio->type & SERIO_TYPE) != SERIO_RS232)
-		return;
-
-	if (!(serio->type & SERIO_PROTO) || ((serio->type & SERIO_PROTO) > SERIO_MZPP))
-		return;
+	if (!serio->id.proto || serio->id.proto > SERIO_MZPP)
+		return -ENODEV;
 
 	if (!(sermouse = kmalloc(sizeof(struct sermouse), GFP_KERNEL)))
-		return;
+		return -ENOMEM;
 
 	memset(sermouse, 0, sizeof(struct sermouse));
 
@@ -261,10 +261,8 @@
 	sermouse->dev.relbit[0] = BIT(REL_X) | BIT(REL_Y);
 	sermouse->dev.private = sermouse;
 
-	serio->private = sermouse;
-
-	sermouse->type = serio->type & SERIO_PROTO;
-	c = (serio->type & SERIO_EXTRA) >> 16;
+	sermouse->type = serio->id.proto;
+	c = serio->id.extra;
 
 	if (c & 0x01) set_bit(BTN_MIDDLE, sermouse->dev.keybit);
 	if (c & 0x02) set_bit(BTN_SIDE, sermouse->dev.keybit);
@@ -282,33 +280,88 @@
 	sermouse->dev.id.version = 0x0100;
 	sermouse->dev.dev = &serio->dev;
 
-	if (serio_open(serio, drv)) {
+	serio_set_drvdata(serio, sermouse);
+
+	err = serio_open(serio, drv);
+	if (err) {
+		serio_set_drvdata(serio, NULL);
 		kfree(sermouse);
-		return;
+		return err;
 	}
 
 	input_register_device(&sermouse->dev);
 
 	printk(KERN_INFO "input: %s on %s\n", sermouse_protocols[sermouse->type], serio->phys);
+
+	return 0;
 }
 
+static struct serio_device_id sermouse_serio_ids[] = {
+	{
+		.type	= SERIO_RS232,
+		.proto	= SERIO_MSC,
+		.id	= SERIO_ANY,
+		.extra	= SERIO_ANY,
+	},
+	{
+		.type	= SERIO_RS232,
+		.proto	= SERIO_SUN,
+		.id	= SERIO_ANY,
+		.extra	= SERIO_ANY,
+	},
+	{
+		.type	= SERIO_RS232,
+		.proto	= SERIO_MS,
+		.id	= SERIO_ANY,
+		.extra	= SERIO_ANY,
+	},
+	{
+		.type	= SERIO_RS232,
+		.proto	= SERIO_MP,
+		.id	= SERIO_ANY,
+		.extra	= SERIO_ANY,
+	},
+	{
+		.type	= SERIO_RS232,
+		.proto	= SERIO_MZ,
+		.id	= SERIO_ANY,
+		.extra	= SERIO_ANY,
+	},
+	{
+		.type	= SERIO_RS232,
+		.proto	= SERIO_MZP,
+		.id	= SERIO_ANY,
+		.extra	= SERIO_ANY,
+	},
+	{
+		.type	= SERIO_RS232,
+		.proto	= SERIO_MZPP,
+		.id	= SERIO_ANY,
+		.extra	= SERIO_ANY,
+	},
+	{ 0 }
+};
+
+MODULE_DEVICE_TABLE(serio, sermouse_serio_ids);
+
 static struct serio_driver sermouse_drv = {
 	.driver		= {
 		.name	= "sermouse",
 	},
 	.description	= DRIVER_DESC,
+	.id_table	= sermouse_serio_ids,
 	.interrupt	= sermouse_interrupt,
 	.connect	= sermouse_connect,
 	.disconnect	= sermouse_disconnect,
 };
 
-int __init sermouse_init(void)
+static int __init sermouse_init(void)
 {
 	serio_register_driver(&sermouse_drv);
 	return 0;
 }
 
-void __exit sermouse_exit(void)
+static void __exit sermouse_exit(void)
 {
 	serio_unregister_driver(&sermouse_drv);
 }
diff -Nru a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c
--- a/drivers/input/mouse/synaptics.c	2005-03-11 12:51:42 -08:00
+++ b/drivers/input/mouse/synaptics.c	2005-03-11 12:51:42 -08:00
@@ -229,7 +229,7 @@
  ****************************************************************************/
 static int synaptics_pt_write(struct serio *serio, unsigned char c)
 {
-	struct psmouse *parent = serio->parent->private;
+	struct psmouse *parent = serio_get_drvdata(serio->parent);
 	char rate_param = SYN_PS_CLIENT_CMD; /* indicates that we want pass-through port */
 
 	if (psmouse_sliced_command(parent, c))
@@ -246,7 +246,7 @@
 
 static void synaptics_pass_pt_packet(struct serio *ptport, unsigned char *packet)
 {
-	struct psmouse *child = ptport->private;
+	struct psmouse *child = serio_get_drvdata(ptport);
 
 	if (child && child->state == PSMOUSE_ACTIVATED) {
 		serio_interrupt(ptport, packet[1], 0, NULL);
@@ -260,7 +260,8 @@
 
 static void synaptics_pt_activate(struct psmouse *psmouse)
 {
-	struct psmouse *child = psmouse->ps2dev.serio->child->private;
+	struct serio *ptport = psmouse->ps2dev.serio->child;
+	struct psmouse *child = serio_get_drvdata(ptport);
 	struct synaptics_data *priv = psmouse->private;
 
 	/* adjust the touchpad to child's choice of protocol */
@@ -287,7 +288,7 @@
 
 	memset(serio, 0, sizeof(struct serio));
 
-	serio->type = SERIO_PS_PSTHRU;
+	serio->id.type = SERIO_PS_PSTHRU;
 	strlcpy(serio->name, "Synaptics pass-through", sizeof(serio->name));
 	strlcpy(serio->phys, "synaptics-pt/serio0", sizeof(serio->name));
 	serio->write = synaptics_pt_write;
@@ -295,7 +296,8 @@
 
 	psmouse->pt_activate = synaptics_pt_activate;
 
-	psmouse->ps2dev.serio->child = serio;
+	printk(KERN_INFO "serio: %s port at %s\n", serio->name, psmouse->phys);
+	serio_register_port(serio);
 }
 
 /*****************************************************************************
@@ -322,8 +324,11 @@
 		hw->left  = (buf[0] & 0x01) ? 1 : 0;
 		hw->right = (buf[0] & 0x02) ? 1 : 0;
 
-		if (SYN_CAP_MIDDLE_BUTTON(priv->capabilities))
+		if (SYN_CAP_MIDDLE_BUTTON(priv->capabilities)) {
 			hw->middle = ((buf[0] ^ buf[3]) & 0x01) ? 1 : 0;
+			if (hw->w == 2)
+				hw->scroll = (signed char)(buf[1]);
+		}
 
 		if (SYN_CAP_FOUR_BUTTON(priv->capabilities)) {
 			hw->up   = ((buf[0] ^ buf[3]) & 0x01) ? 1 : 0;
@@ -379,6 +384,26 @@
 
 	synaptics_parse_hw_state(psmouse->packet, priv, &hw);
 
+	if (hw.scroll) {
+		priv->scroll += hw.scroll;
+
+		while (priv->scroll >= 4) {
+			input_report_key(dev, BTN_BACK, !hw.down);
+			input_sync(dev);
+			input_report_key(dev, BTN_BACK, hw.down);
+			input_sync(dev);
+			priv->scroll -= 4;
+		}
+		while (priv->scroll <= -4) {
+			input_report_key(dev, BTN_FORWARD, !hw.up);
+			input_sync(dev);
+			input_report_key(dev, BTN_FORWARD, hw.up);
+			input_sync(dev);
+			priv->scroll += 4;
+		}
+		return;
+	}
+
 	if (hw.z > 0) {
 		num_fingers = 1;
 		finger_width = 5;
@@ -528,7 +553,8 @@
 	if (SYN_CAP_MIDDLE_BUTTON(priv->capabilities))
 		set_bit(BTN_MIDDLE, dev->keybit);
 
-	if (SYN_CAP_FOUR_BUTTON(priv->capabilities)) {
+	if (SYN_CAP_FOUR_BUTTON(priv->capabilities) ||
+	    SYN_CAP_MIDDLE_BUTTON(priv->capabilities)) {
 		set_bit(BTN_FORWARD, dev->keybit);
 		set_bit(BTN_BACK, dev->keybit);
 	}
@@ -551,6 +577,7 @@
 {
 	synaptics_reset(psmouse);
 	kfree(psmouse->private);
+	psmouse->private = NULL;
 }
 
 static int synaptics_reconnect(struct psmouse *psmouse)
@@ -604,6 +631,20 @@
 	return 0;
 }
 
+#if defined(__i386__)
+#include <linux/dmi.h>
+static struct dmi_system_id toshiba_dmi_table[] = {
+	{
+		.ident = "Toshiba Satellite",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+			DMI_MATCH(DMI_PRODUCT_NAME , "Satellite"),
+		},
+	},
+	{ }
+};
+#endif
+
 int synaptics_init(struct psmouse *psmouse)
 {
 	struct synaptics_data *priv;
@@ -625,9 +666,6 @@
 
 	priv->pkt_type = SYN_MODEL_NEWABS(priv->model_id) ? SYN_NEWABS : SYN_OLDABS;
 
-	if (SYN_CAP_PASS_THROUGH(priv->capabilities))
-		synaptics_pt_create(psmouse);
-
 	print_ident(priv);
 	set_input_params(&psmouse->dev, priv);
 
@@ -636,6 +674,21 @@
 	psmouse->disconnect = synaptics_disconnect;
 	psmouse->reconnect = synaptics_reconnect;
 	psmouse->pktsize = 6;
+
+	if (SYN_CAP_PASS_THROUGH(priv->capabilities))
+		synaptics_pt_create(psmouse);
+
+#if defined(__i386__)
+	/*
+	 * Toshiba's KBC seems to have trouble handling data from
+	 * Synaptics as full rate, switch to lower rate which is roughly
+	 * thye same as rate of standard PS/2 mouse.
+	 */
+	if (psmouse->rate >= 80 && dmi_check_system(toshiba_dmi_table)) {
+		printk(KERN_INFO "synaptics: Toshiba Satellite detected, limiting rate to 40pps.\n");
+		psmouse->rate = 40;
+	}
+#endif
 
 	return 0;
 
diff -Nru a/drivers/input/mouse/synaptics.h b/drivers/input/mouse/synaptics.h
--- a/drivers/input/mouse/synaptics.h	2005-03-11 12:51:46 -08:00
+++ b/drivers/input/mouse/synaptics.h	2005-03-11 12:51:46 -08:00
@@ -92,6 +92,7 @@
 	unsigned int up:1;
 	unsigned int down:1;
 	unsigned char ext_buttons;
+	signed char scroll;
 };
 
 struct synaptics_data {
@@ -103,6 +104,7 @@
 
 	unsigned char pkt_type;			/* packet type - old, new, etc */
 	unsigned char mode;			/* current mode byte */
+	int scroll;
 };
 
 #endif /* _SYNAPTICS_H */
diff -Nru a/drivers/input/mouse/vsxxxaa.c b/drivers/input/mouse/vsxxxaa.c
--- a/drivers/input/mouse/vsxxxaa.c	2005-03-11 12:51:52 -08:00
+++ b/drivers/input/mouse/vsxxxaa.c	2005-03-11 12:51:52 -08:00
@@ -470,7 +470,7 @@
 vsxxxaa_interrupt (struct serio *serio, unsigned char data, unsigned int flags,
 		struct pt_regs *regs)
 {
-	struct vsxxxaa *mouse = serio->private;
+	struct vsxxxaa *mouse = serio_get_drvdata (serio);
 
 	vsxxxaa_queue_byte (mouse, data);
 	vsxxxaa_parse_buffer (mouse, regs);
@@ -481,25 +481,22 @@
 static void
 vsxxxaa_disconnect (struct serio *serio)
 {
-	struct vsxxxaa *mouse = serio->private;
+	struct vsxxxaa *mouse = serio_get_drvdata (serio);
 
 	input_unregister_device (&mouse->dev);
 	serio_close (serio);
+	serio_set_drvdata (serio, NULL);
 	kfree (mouse);
 }
 
-static void
+static int
 vsxxxaa_connect (struct serio *serio, struct serio_driver *drv)
 {
 	struct vsxxxaa *mouse;
-
-	if ((serio->type & SERIO_TYPE) != SERIO_RS232)
-		return;
-	if ((serio->type & SERIO_PROTO) != SERIO_VSXXXAA)
-		return;
+	int err;
 
 	if (!(mouse = kmalloc (sizeof (struct vsxxxaa), GFP_KERNEL)))
-		return;
+		return -ENOMEM;
 
 	memset (mouse, 0, sizeof (struct vsxxxaa));
 
@@ -522,7 +519,6 @@
 	mouse->dev.absmax[ABS_Y] = 1023;
 
 	mouse->dev.private = mouse;
-	serio->private = mouse;
 
 	sprintf (mouse->name, "DEC VSXXX-AA/-GA mouse or VSXXX-AB digitizer");
 	sprintf (mouse->phys, "%s/input0", serio->phys);
@@ -532,9 +528,13 @@
 	mouse->dev.dev = &serio->dev;
 	mouse->serio = serio;
 
-	if (serio_open (serio, drv)) {
+	serio_set_drvdata (serio, mouse);
+
+	err = serio_open (serio, drv);
+	if (err) {
+		serio_set_drvdata (serio, NULL);
 		kfree (mouse);
-		return;
+		return err;
 	}
 
 	/*
@@ -546,26 +546,41 @@
 	input_register_device (&mouse->dev);
 
 	printk (KERN_INFO "input: %s on %s\n", mouse->name, mouse->phys);
+
+	return 0;
 }
 
+static struct serio_device_id vsxxaa_serio_ids[] = {
+	{
+		.type	= SERIO_RS232,
+		.proto	= SERIO_VSXXXAA,
+		.id	= SERIO_ANY,
+		.extra	= SERIO_ANY,
+	},
+	{ 0 }
+};
+
+MODULE_DEVICE_TABLE(serio, vsxxaa_serio_ids);
+
 static struct serio_driver vsxxxaa_drv = {
 	.driver		= {
 		.name	= "vsxxxaa",
 	},
 	.description	= DRIVER_DESC,
+	.id_table	= vsxxaa_serio_ids,
 	.connect	= vsxxxaa_connect,
 	.interrupt	= vsxxxaa_interrupt,
 	.disconnect	= vsxxxaa_disconnect,
 };
 
-int __init
+static int __init
 vsxxxaa_init (void)
 {
 	serio_register_driver(&vsxxxaa_drv);
 	return 0;
 }
 
-void __exit
+static void __exit
 vsxxxaa_exit (void)
 {
 	serio_unregister_driver(&vsxxxaa_drv);
diff -Nru a/drivers/input/mousedev.c b/drivers/input/mousedev.c
--- a/drivers/input/mousedev.c	2005-03-11 12:51:51 -08:00
+++ b/drivers/input/mousedev.c	2005-03-11 12:51:51 -08:00
@@ -71,6 +71,7 @@
 	struct mousedev_hw_data packet;
 	unsigned int pkt_count;
 	int old_x[4], old_y[4];
+	int frac_dx, frac_dy;
 	unsigned long touch;
 };
 
@@ -117,24 +118,31 @@
 
 static void mousedev_touchpad_event(struct input_dev *dev, struct mousedev *mousedev, unsigned int code, int value)
 {
-	int size;
+	int size, tmp;
+	enum { FRACTION_DENOM = 128 };
 
 	if (mousedev->touch) {
+		size = dev->absmax[ABS_X] - dev->absmin[ABS_X];
+		if (size == 0) size = 256 * 2;
 		switch (code) {
 			case ABS_X:
-				size = dev->absmax[ABS_X] - dev->absmin[ABS_X];
-				if (size == 0) size = xres;
 				fx(0) = value;
-				if (mousedev->pkt_count >= 2)
-					mousedev->packet.dx = ((fx(0) - fx(1)) / 2 + (fx(1) - fx(2)) / 2) * xres / (size * 2);
+				if (mousedev->pkt_count >= 2) {
+					tmp = ((value - fx(2)) * (256 * FRACTION_DENOM)) / size;
+					tmp += mousedev->frac_dx;
+					mousedev->packet.dx = tmp / FRACTION_DENOM;
+					mousedev->frac_dx = tmp - mousedev->packet.dx * FRACTION_DENOM;
+				}
 				break;
 
 			case ABS_Y:
-				size = dev->absmax[ABS_Y] - dev->absmin[ABS_Y];
-				if (size == 0) size = yres;
 				fy(0) = value;
-				if (mousedev->pkt_count >= 2)
-					mousedev->packet.dy = -((fy(0) - fy(1)) / 2 + (fy(1) - fy(2)) / 2) * yres / (size * 2);
+				if (mousedev->pkt_count >= 2) {
+					tmp = -((value - fy(2)) * (256 * FRACTION_DENOM)) / size;
+					tmp += mousedev->frac_dy;
+					mousedev->packet.dy = tmp / FRACTION_DENOM;
+					mousedev->frac_dy = tmp - mousedev->packet.dy * FRACTION_DENOM;
+				}
 				break;
 		}
 	}
@@ -268,6 +276,8 @@
 			clear_bit(0, &mousedev_mix.packet.buttons);
 		}
 		mousedev->touch = mousedev->pkt_count = 0;
+		mousedev->frac_dx = 0;
+		mousedev->frac_dy = 0;
 	}
 	else
 		if (!mousedev->touch)
@@ -445,7 +455,7 @@
 
 	switch (list->mode) {
 		case MOUSEDEV_EMUL_EXPS:
-			ps2_data[3] = mousedev_limit_delta(p->dz, 127);
+			ps2_data[3] = mousedev_limit_delta(p->dz, 7);
 			p->dz -= ps2_data[3];
 			ps2_data[3] = (ps2_data[3] & 0x0f) | ((p->buttons & 0x18) << 1);
 			list->bufsiz = 4;
@@ -585,12 +595,11 @@
 {
 	struct mousedev_list *list = file->private_data;
 	poll_wait(file, &list->mousedev->wait, wait);
-	if (list->ready || list->buffer)
-		return POLLIN | POLLRDNORM;
-	return 0;
+	return ((list->ready || list->buffer) ? (POLLIN | POLLRDNORM) : 0) |
+		(list->mousedev->exist ? 0 : (POLLHUP | POLLERR));
 }
 
-struct file_operations mousedev_fops = {
+static struct file_operations mousedev_fops = {
 	.owner =	THIS_MODULE,
 	.read =		mousedev_read,
 	.write =	mousedev_write,
@@ -643,6 +652,7 @@
 static void mousedev_disconnect(struct input_handle *handle)
 {
 	struct mousedev *mousedev = handle->private;
+	struct mousedev_list *list;
 
 	class_simple_device_remove(MKDEV(INPUT_MAJOR, MOUSEDEV_MINOR_BASE + mousedev->minor));
 	devfs_remove("input/mouse%d", mousedev->minor);
@@ -650,6 +660,9 @@
 
 	if (mousedev->open) {
 		input_close_device(handle);
+		wake_up_interruptible(&mousedev->wait);
+		list_for_each_entry(list, &mousedev->list, node)
+			kill_fasync(&list->fasync, SIGIO, POLL_HUP);
 	} else {
 		if (mousedev_mix.open)
 			input_close_device(handle);
diff -Nru a/drivers/input/power.c b/drivers/input/power.c
--- a/drivers/input/power.c	2005-03-11 12:51:47 -08:00
+++ b/drivers/input/power.c	2005-03-11 12:51:47 -08:00
@@ -58,8 +58,6 @@
 
 	printk("Entering power_event\n");
 
-	if (type != EV_KEY || type != EV_PWR) return;
-
 	if (type == EV_PWR) {
 		switch (code) {
 			case KEY_SUSPEND:
@@ -76,7 +74,9 @@
 			default:
 				return;
 		}
-	} else {
+	}
+
+	if (type == EV_KEY) {
 		switch (code) {
 			case KEY_SUSPEND:
 				printk("Powering down input device\n");
@@ -102,12 +102,6 @@
 					  struct input_device_id *id)
 {
 	struct input_handle *handle;
-
-	if (!test_bit(EV_KEY, dev->evbit) || !test_bit(EV_PWR, dev->evbit))
-		return NULL;
-
-	if (!test_bit(KEY_SUSPEND, dev->keybit) || (!test_bit(KEY_POWER, dev->keybit)))
-		return NULL;
 
 	if (!(handle = kmalloc(sizeof(struct input_handle), GFP_KERNEL)))
 		return NULL;
diff -Nru a/drivers/input/serio/Kconfig b/drivers/input/serio/Kconfig
--- a/drivers/input/serio/Kconfig	2005-03-11 12:51:46 -08:00
+++ b/drivers/input/serio/Kconfig	2005-03-11 12:51:46 -08:00
@@ -2,11 +2,11 @@
 # Input core configuration
 #
 config SERIO
-	tristate "Serial i/o support" if EMBEDDED || !X86
+	tristate "Serial I/O support" if EMBEDDED || !X86
 	default y
 	---help---
 	  Say Yes here if you have any input device that uses serial I/O to
-	  communicate with the system. This includes the 
+	  communicate with the system. This includes the
 	  		* standard AT keyboard and PS/2 mouse *
 	  as well as serial mice, Sun keyboards, some joysticks and 6dof
 	  devices and more.
@@ -16,10 +16,11 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called serio.
 
+if SERIO
+
 config SERIO_I8042
 	tristate "i8042 PC Keyboard controller" if EMBEDDED || !X86
 	default y
-	select SERIO
 	depends on !PARISC && (!ARM || ARCH_SHARK || FOOTBRIDGE_HOST) && !M68K
 	---help---
 	  i8042 is the chip over which the standard AT keyboard and PS/2
@@ -34,7 +35,6 @@
 config SERIO_SERPORT
 	tristate "Serial port line discipline"
 	default y
-	depends on SERIO
 	---help---
 	  Say Y here if you plan to use an input device (mouse, joystick,
 	  tablet, 6dof) that communicates over the RS232 serial (COM) port.
@@ -48,8 +48,7 @@
 
 config SERIO_CT82C710
 	tristate "ct82c710 Aux port controller"
-	depends on SERIO
-	depends on !PARISC
+	depends on X86
 	---help---
 	  Say Y here if you have a Texas Instruments TravelMate notebook
 	  equipped with the ct82c710 chip and want to use a mouse connected
@@ -62,11 +61,11 @@
 
 config SERIO_Q40KBD
 	tristate "Q40 keyboard controller"
-	depends on Q40 && SERIO
+	depends on Q40
 
 config SERIO_PARKBD
 	tristate "Parallel port keyboard adapter"
-	depends on SERIO && PARPORT
+	depends on PARPORT
 	---help---
 	  Say Y here if you built a simple parallel port adapter to attach
 	  an additional AT keyboard, XT keyboard or PS/2 mouse.
@@ -80,7 +79,7 @@
 
 config SERIO_RPCKBD
 	tristate "Acorn RiscPC keyboard controller"
-	depends on (ARCH_ACORN || ARCH_CLPS7500) && SERIO
+	depends on ARCH_ACORN || ARCH_CLPS7500
 	default y
 	help
 	  Say Y here if you have the Acorn RiscPC and want to use an AT
@@ -91,15 +90,15 @@
 
 config SERIO_AMBAKMI
 	tristate "AMBA KMI keyboard controller"
-	depends on ARM_AMBA && SERIO
+	depends on ARM_AMBA
 
 config SERIO_SA1111
 	tristate "Intel SA1111 keyboard controller"
-	depends on SA1111 && SERIO
+	depends on SA1111
 
 config SERIO_GSCPS2
 	tristate "HP GSC PS/2 keyboard and PS/2 mouse controller"
-	depends on GSC && SERIO
+	depends on GSC
 	default y
 	help
 	  This driver provides support for the PS/2 ports on PA-RISC machines
@@ -111,9 +110,35 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called gscps2.
 
+config HP_SDC
+	tristate "HP System Device Controller i8042 Support"
+	depends on GSC && SERIO
+	default y
+	---help---
+	  This option enables supports for the the "System Device
+	  Controller", an i8042 carrying microcode to manage a
+	  few miscellanous devices on some Hewlett Packard systems.
+	  The SDC itself contains a 10ms resolution timer/clock capable
+	  of delivering interrupts on a periodic and one-shot basis.
+	  The SDC may also be connected to a battery-backed real-time
+	  clock, a basic audio waveform generator, and an HP-HIL Master
+	  Link Controller serving up to seven input devices.
+
+	  By itself this option is rather useless, but enabling it will
+	  enable selection of drivers for the abovementioned devices.
+	  It is, however, incompatible with the old, reliable HIL keyboard
+	  driver, and the new HIL driver is experimental, so if you plan
+	  to use a HIL keyboard as your primary keyboard, you may wish
+	  to keep using that driver until the new HIL drivers have had
+	  more testing.
+
+config HIL_MLC
+	tristate "HIL MLC Support (needed for HIL input devices)"
+	depends on HP_SDC
+
 config SERIO_PCIPS2
 	tristate "PCI PS/2 keyboard and PS/2 mouse controller"
-	depends on PCI && SERIO
+	depends on PCI
 	help
 	  Say Y here if you have a Mobility Docking station with PS/2
 	  keyboard and mice ports.
@@ -123,7 +148,7 @@
 
 config SERIO_MACEPS2
 	tristate "SGI O2 MACE PS/2 controller"
-	depends on SGI_IP32 && SERIO
+	depends on SGI_IP32
 	help
 	  Say Y here if you have SGI O2 workstation and want to use its
 	  PS/2 ports.
@@ -133,7 +158,6 @@
 
 config SERIO_LIBPS2
 	tristate "PS/2 driver library" if EMBEDDED
-	depends on SERIO
 	help
 	  Say Y here if you are using a driver for device connected
 	  to a PS/2 port, such as PS/2 mouse or standard AT keyboard.
@@ -143,7 +167,6 @@
 
 config SERIO_RAW
 	tristate "Raw access to serio ports"
-	depends on SERIO
 	help
 	  Say Y here if you want to have raw access to serio ports, such as
 	  AUX ports on i8042 keyboard controller. Each serio port that is
@@ -156,3 +179,5 @@
 
 	  To compile this driver as a module, choose M here: the
 	  module will be called serio_raw.
+
+endif
diff -Nru a/drivers/input/serio/Makefile b/drivers/input/serio/Makefile
--- a/drivers/input/serio/Makefile	2005-03-11 12:51:41 -08:00
+++ b/drivers/input/serio/Makefile	2005-03-11 12:51:41 -08:00
@@ -15,6 +15,8 @@
 obj-$(CONFIG_SERIO_Q40KBD)	+= q40kbd.o
 obj-$(CONFIG_SERIO_98KBD)	+= 98kbd-io.o
 obj-$(CONFIG_SERIO_GSCPS2)	+= gscps2.o
+obj-$(CONFIG_HP_SDC)		+= hp_sdc.o
+obj-$(CONFIG_HIL_MLC)		+= hp_sdc_mlc.o hil_mlc.o
 obj-$(CONFIG_SERIO_PCIPS2)	+= pcips2.o
 obj-$(CONFIG_SERIO_MACEPS2)	+= maceps2.o
 obj-$(CONFIG_SERIO_LIBPS2)	+= libps2.o
diff -Nru a/drivers/input/serio/ambakmi.c b/drivers/input/serio/ambakmi.c
--- a/drivers/input/serio/ambakmi.c	2005-03-11 12:51:47 -08:00
+++ b/drivers/input/serio/ambakmi.c	2005-03-11 12:51:47 -08:00
@@ -134,7 +134,7 @@
 	memset(kmi, 0, sizeof(struct amba_kmi_port));
 	memset(io, 0, sizeof(struct serio));
 
-	io->type	= SERIO_8042;
+	io->id.type	= SERIO_8042;
 	io->write	= amba_kmi_write;
 	io->open	= amba_kmi_open;
 	io->close	= amba_kmi_close;
diff -Nru a/drivers/input/serio/ct82c710.c b/drivers/input/serio/ct82c710.c
--- a/drivers/input/serio/ct82c710.c	2005-03-11 12:51:52 -08:00
+++ b/drivers/input/serio/ct82c710.c	2005-03-11 12:51:52 -08:00
@@ -181,7 +181,7 @@
 	serio = kmalloc(sizeof(struct serio), GFP_KERNEL);
 	if (serio) {
 		memset(serio, 0, sizeof(struct serio));
-		serio->type = SERIO_8042;
+		serio->id.type = SERIO_8042;
 		serio->open = ct82c710_open;
 		serio->close = ct82c710_close;
 		serio->write = ct82c710_write;
@@ -193,7 +193,7 @@
 	return serio;
 }
 
-int __init ct82c710_init(void)
+static int __init ct82c710_init(void)
 {
 	if (ct82c710_probe())
 		return -ENODEV;
@@ -215,7 +215,7 @@
 	return 0;
 }
 
-void __exit ct82c710_exit(void)
+static void __exit ct82c710_exit(void)
 {
 	serio_unregister_port(ct82c710_port);
 	platform_device_unregister(ct82c710_device);
diff -Nru a/drivers/input/serio/gscps2.c b/drivers/input/serio/gscps2.c
--- a/drivers/input/serio/gscps2.c	2005-03-11 12:51:51 -08:00
+++ b/drivers/input/serio/gscps2.c	2005-03-11 12:51:51 -08:00
@@ -38,7 +38,7 @@
 #include <asm/parisc-device.h>
 
 MODULE_AUTHOR("Laurent Canet <canetl@esiee.fr>, Thibaut Varene <varenet@esiee.fr>, Helge Deller <deller@gmx.de>");
-MODULE_DESCRIPTION("HP GSC PS/2 port driver");
+MODULE_DESCRIPTION("HP GSC PS2 port driver");
 MODULE_LICENSE("GPL");
 MODULE_DEVICE_TABLE(parisc, gscps2_device_tbl);
 
@@ -363,11 +363,7 @@
 	snprintf(serio->name, sizeof(serio->name), "GSC PS/2 %s",
 		 (ps2port->id == GSC_ID_KEYBOARD) ? "keyboard" : "mouse");
 	strlcpy(serio->phys, dev->dev.bus_id, sizeof(serio->phys));
-	serio->idbus		= BUS_GSC;
-	serio->idvendor		= PCI_VENDOR_ID_HP;
-	serio->idproduct	= 0x0001;
-	serio->idversion	= 0x0010;
-	serio->type		= SERIO_8042;
+	serio->id.type		= SERIO_8042;
 	serio->write		= gscps2_write;
 	serio->open		= gscps2_open;
 	serio->close		= gscps2_close;
@@ -448,7 +444,7 @@
 };
 
 static struct parisc_driver parisc_ps2_driver = {
-	.name		= "GSC PS/2",
+	.name		= "GSC PS2",
 	.id_table	= gscps2_device_tbl,
 	.probe		= gscps2_probe,
 	.remove		= gscps2_remove,
diff -Nru a/drivers/input/serio/hil_mlc.c b/drivers/input/serio/hil_mlc.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/input/serio/hil_mlc.c	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,949 @@
+/*
+ * HIL MLC state machine and serio interface driver
+ *
+ * Copyright (c) 2001 Brian S. Julin
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions, and the following disclaimer,
+ *    without modification.
+ * 2. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL").
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ *
+ * References:
+ * HP-HIL Technical Reference Manual.  Hewlett Packard Product No. 45918A
+ *
+ *
+ *	Driver theory of operation:
+ *
+ *	Some access methods and an ISR is defined by the sub-driver 
+ *	(e.g. hp_sdc_mlc.c).  These methods are expected to provide a 
+ *	few bits of logic in addition to raw access to the HIL MLC, 
+ *	specifically, the ISR, which is entirely registered by the 
+ *	sub-driver and invoked directly, must check for record 
+ *	termination or packet match, at which point a semaphore must
+ *	be cleared and then the hil_mlcs_tasklet must be scheduled.
+ *
+ *	The hil_mlcs_tasklet processes the state machine for all MLCs
+ *	each time it runs, checking each MLC's progress at the current
+ *	node in the state machine, and moving the MLC to subsequent nodes
+ *	in the state machine when appropriate.  It will reschedule
+ *	itself if output is pending.  (This rescheduling should be replaced
+ *	at some point with a sub-driver-specific mechanism.)
+ *
+ *	A timer task prods the tasklet once per second to prevent 
+ *	hangups when attached devices do not return expected data
+ *	and to initiate probes of the loop for new devices.
+ */
+
+#include <linux/hil_mlc.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/timer.h>
+#include <linux/sched.h>
+#include <linux/list.h>
+
+MODULE_AUTHOR("Brian S. Julin <bri@calyx.com>");
+MODULE_DESCRIPTION("HIL MLC serio");
+MODULE_LICENSE("Dual BSD/GPL");
+
+EXPORT_SYMBOL(hil_mlc_register);
+EXPORT_SYMBOL(hil_mlc_unregister);
+
+#define PREFIX "HIL MLC: "
+
+static LIST_HEAD(hil_mlcs);
+static rwlock_t			hil_mlcs_lock = RW_LOCK_UNLOCKED;
+static struct timer_list	hil_mlcs_kicker;
+static int			hil_mlcs_probe;
+
+static void hil_mlcs_process(unsigned long unused);
+DECLARE_TASKLET_DISABLED(hil_mlcs_tasklet, hil_mlcs_process, 0);
+
+
+/* #define HIL_MLC_DEBUG */
+
+/********************** Device info/instance management **********************/
+
+static void hil_mlc_clear_di_map (hil_mlc *mlc, int val) {
+	int j;
+	for (j = val; j < 7 ; j++) {
+		mlc->di_map[j] = -1;
+	}
+}
+
+static void hil_mlc_clear_di_scratch (hil_mlc *mlc) {
+	memset(&(mlc->di_scratch), 0, sizeof(mlc->di_scratch));
+}
+
+static void hil_mlc_copy_di_scratch (hil_mlc *mlc, int idx) {
+	memcpy(&(mlc->di[idx]), &(mlc->di_scratch), sizeof(mlc->di_scratch));
+}
+
+static int hil_mlc_match_di_scratch (hil_mlc *mlc) {
+	int idx;
+
+	for (idx = 0; idx < HIL_MLC_DEVMEM; idx++) {
+		int j, found;
+
+		/* In-use slots are not eligible. */
+		found = 0;
+		for (j = 0; j < 7 ; j++) {
+			if (mlc->di_map[j] == idx) found++;
+		}
+		if (found) continue;
+		if (!memcmp(mlc->di + idx, 
+			    &(mlc->di_scratch), 
+			    sizeof(mlc->di_scratch))) break;
+	}
+	return((idx >= HIL_MLC_DEVMEM) ? -1 : idx);
+}
+
+static int hil_mlc_find_free_di(hil_mlc *mlc) {
+	int idx;
+	/* TODO: Pick all-zero slots first, failing that, 
+	 * randomize the slot picked among those eligible. 
+	 */
+	for (idx = 0; idx < HIL_MLC_DEVMEM; idx++) {
+		int j, found;
+		found = 0;
+		for (j = 0; j < 7 ; j++) {
+			if (mlc->di_map[j] == idx) found++;
+		}
+		if (!found) break;
+	}
+	return(idx); /* Note: It is guaranteed at least one above will match */
+}
+
+static inline void hil_mlc_clean_serio_map(hil_mlc *mlc) {
+	int idx;
+	for (idx = 0; idx < HIL_MLC_DEVMEM; idx++) {
+		int j, found;
+		found = 0;
+		for (j = 0; j < 7 ; j++) {
+			if (mlc->di_map[j] == idx) found++;
+		}
+		if (!found) mlc->serio_map[idx].di_revmap = -1;
+	}
+}
+
+static void hil_mlc_send_polls(hil_mlc *mlc) {
+	int did, i, cnt;
+	struct serio *serio;
+	struct serio_driver *drv;
+
+	i = cnt = 0;
+	did = (mlc->ipacket[0] & HIL_PKT_ADDR_MASK) >> 8;
+	serio = did ? mlc->serio[mlc->di_map[did - 1]] : NULL;
+	drv = (serio != NULL) ? serio->drv : NULL;
+
+	while (mlc->icount < 15 - i) {
+		hil_packet p;
+		p = mlc->ipacket[i];
+		if (did != (p & HIL_PKT_ADDR_MASK) >> 8) {
+			if (drv == NULL || drv->interrupt == NULL) goto skip;
+
+			drv->interrupt(serio, 0, 0, NULL);
+			drv->interrupt(serio, HIL_ERR_INT >> 16, 0, NULL);
+			drv->interrupt(serio, HIL_PKT_CMD >> 8,  0, NULL);
+			drv->interrupt(serio, HIL_CMD_POL + cnt, 0, NULL);
+		skip:
+			did = (p & HIL_PKT_ADDR_MASK) >> 8;
+			serio = did ? mlc->serio[mlc->di_map[did-1]] : NULL;
+			drv = (serio != NULL) ? serio->drv : NULL;
+			cnt = 0;
+		}
+		cnt++; i++;
+		if (drv == NULL || drv->interrupt == NULL) continue;
+		drv->interrupt(serio, (p >> 24), 0, NULL);
+		drv->interrupt(serio, (p >> 16) & 0xff, 0, NULL);
+		drv->interrupt(serio, (p >> 8) & ~HIL_PKT_ADDR_MASK, 0, NULL);
+		drv->interrupt(serio, p & 0xff, 0, NULL);
+	}
+}
+
+/*************************** State engine *********************************/
+
+#define HILSEN_SCHED	0x000100	/* Schedule the tasklet		*/
+#define HILSEN_BREAK	0x000200	/* Wait until next pass		*/
+#define HILSEN_UP	0x000400	/* relative node#, decrement	*/
+#define HILSEN_DOWN	0x000800	/* relative node#, increment	*/
+#define HILSEN_FOLLOW	0x001000	/* use retval as next node#	*/
+
+#define HILSEN_MASK	0x0000ff
+#define HILSEN_START	0
+#define HILSEN_RESTART	1
+#define HILSEN_DHR	9
+#define HILSEN_DHR2	10
+#define HILSEN_IFC	14
+#define HILSEN_HEAL0	16
+#define HILSEN_HEAL	18
+#define HILSEN_ACF      21
+#define HILSEN_ACF2	22
+#define HILSEN_DISC0	25
+#define HILSEN_DISC	27
+#define HILSEN_MATCH	40
+#define HILSEN_OPERATE	41
+#define HILSEN_PROBE	44
+#define HILSEN_DSR	52
+#define HILSEN_REPOLL	55
+#define HILSEN_IFCACF	58
+#define HILSEN_END	60
+
+#define HILSEN_NEXT	(HILSEN_DOWN | 1)
+#define HILSEN_SAME	(HILSEN_DOWN | 0)
+#define HILSEN_LAST	(HILSEN_UP | 1)
+
+#define HILSEN_DOZE	(HILSEN_SAME | HILSEN_SCHED | HILSEN_BREAK)
+#define HILSEN_SLEEP	(HILSEN_SAME | HILSEN_BREAK)
+
+static int hilse_match(hil_mlc *mlc, int unused) {
+	int rc;
+	rc = hil_mlc_match_di_scratch(mlc);
+	if (rc == -1) {
+		rc = hil_mlc_find_free_di(mlc);
+		if (rc == -1) goto err;
+#ifdef HIL_MLC_DEBUG
+		printk(KERN_DEBUG PREFIX "new in slot %i\n", rc);
+#endif
+		hil_mlc_copy_di_scratch(mlc, rc);
+		mlc->di_map[mlc->ddi] = rc;
+		mlc->serio_map[rc].di_revmap = mlc->ddi;
+		hil_mlc_clean_serio_map(mlc);
+		serio_rescan(mlc->serio[rc]);
+		return -1;
+	}
+	mlc->di_map[mlc->ddi] = rc;
+#ifdef HIL_MLC_DEBUG
+	printk(KERN_DEBUG PREFIX "same in slot %i\n", rc);
+#endif
+	mlc->serio_map[rc].di_revmap = mlc->ddi;
+	hil_mlc_clean_serio_map(mlc);
+	return 0;
+ err:
+	printk(KERN_ERR PREFIX "Residual device slots exhausted, close some serios!\n");
+	return 1;
+}
+
+/* An LCV used to prevent runaway loops, forces 5 second sleep when reset. */
+static int hilse_init_lcv(hil_mlc *mlc, int unused) {
+	struct timeval tv;
+
+	do_gettimeofday(&tv);
+
+	if(mlc->lcv == 0) goto restart;  /* First init, no need to dally */
+	if(tv.tv_sec - mlc->lcv_tv.tv_sec < 5) return -1;
+ restart:
+	mlc->lcv_tv = tv;
+	mlc->lcv = 0;
+	return 0;
+}
+
+static int hilse_inc_lcv(hil_mlc *mlc, int lim) {
+	if (mlc->lcv++ >= lim) return -1;
+	return 0;
+}
+
+#if 0
+static int hilse_set_lcv(hil_mlc *mlc, int val) {
+	mlc->lcv = val;
+	return 0;
+}
+#endif
+
+/* Management of the discovered device index (zero based, -1 means no devs) */
+static int hilse_set_ddi(hil_mlc *mlc, int val) {
+	mlc->ddi = val;
+	hil_mlc_clear_di_map(mlc, val + 1);
+	return 0;
+}
+
+static int hilse_dec_ddi(hil_mlc *mlc, int unused) {
+	mlc->ddi--;
+	if (mlc->ddi <= -1) { 
+		mlc->ddi = -1;
+		hil_mlc_clear_di_map(mlc, 0);
+		return -1;
+	}
+	hil_mlc_clear_di_map(mlc, mlc->ddi + 1);
+	return 0;
+}
+
+static int hilse_inc_ddi(hil_mlc *mlc, int unused) {
+	if (mlc->ddi >= 6) {
+		BUG();
+		return -1;
+	}
+	mlc->ddi++;
+	return 0;
+}
+
+static int hilse_take_idd(hil_mlc *mlc, int unused) {
+	int i;
+
+	/* Help the state engine: 
+	 * Is this a real IDD response or just an echo? 
+	 *
+	 * Real IDD response does not start with a command. 
+	 */
+	if (mlc->ipacket[0] & HIL_PKT_CMD) goto bail;
+	/* Should have the command echoed further down. */
+	for (i = 1; i < 16; i++) {
+		if (((mlc->ipacket[i] & HIL_PKT_ADDR_MASK) == 
+		     (mlc->ipacket[0] & HIL_PKT_ADDR_MASK)) &&
+		    (mlc->ipacket[i] & HIL_PKT_CMD) && 
+		    ((mlc->ipacket[i] & HIL_PKT_DATA_MASK) == HIL_CMD_IDD))
+			break;
+	}
+	if (i > 15) goto bail;
+	/* And the rest of the packets should still be clear. */
+	while (++i < 16) {
+		if (mlc->ipacket[i]) break;
+	}
+	if (i < 16) goto bail;
+	for (i = 0; i < 16; i++) {
+		mlc->di_scratch.idd[i] = 
+			mlc->ipacket[i] & HIL_PKT_DATA_MASK;
+	}
+	/* Next step is to see if RSC supported */
+	if (mlc->di_scratch.idd[1] & HIL_IDD_HEADER_RSC) 
+		return HILSEN_NEXT;
+	if (mlc->di_scratch.idd[1] & HIL_IDD_HEADER_EXD) 
+		return HILSEN_DOWN | 4;
+	return 0;
+ bail:
+	mlc->ddi--;
+	return -1; /* This should send us off to ACF */
+}
+
+static int hilse_take_rsc(hil_mlc *mlc, int unused) {
+	int i;
+
+	for (i = 0; i < 16; i++) {
+		mlc->di_scratch.rsc[i] = 
+			mlc->ipacket[i] & HIL_PKT_DATA_MASK;
+	}
+	/* Next step is to see if EXD supported (IDD has already been read) */
+	if (mlc->di_scratch.idd[1] & HIL_IDD_HEADER_EXD) 
+		return HILSEN_NEXT;
+	return 0;
+}
+
+static int hilse_take_exd(hil_mlc *mlc, int unused) {
+	int i;
+
+	for (i = 0; i < 16; i++) {
+		mlc->di_scratch.exd[i] = 
+			mlc->ipacket[i] & HIL_PKT_DATA_MASK;
+	}
+	/* Next step is to see if RNM supported. */
+	if (mlc->di_scratch.exd[0] & HIL_EXD_HEADER_RNM) 
+		return HILSEN_NEXT;
+	return 0;
+}
+
+static int hilse_take_rnm(hil_mlc *mlc, int unused) {
+	int i;
+
+	for (i = 0; i < 16; i++) {
+		mlc->di_scratch.rnm[i] = 
+			mlc->ipacket[i] & HIL_PKT_DATA_MASK;
+	}
+	do {
+	  char nam[17];
+	  snprintf(nam, 16, "%s", mlc->di_scratch.rnm);
+	  nam[16] = '\0';
+	  printk(KERN_INFO PREFIX "Device name gotten: %s\n", nam);
+	} while (0);
+	return 0;
+}
+
+static int hilse_operate(hil_mlc *mlc, int repoll) { 
+
+	if (mlc->opercnt == 0) hil_mlcs_probe = 0;
+	mlc->opercnt = 1;
+
+	hil_mlc_send_polls(mlc);
+
+	if (!hil_mlcs_probe) return 0;
+	hil_mlcs_probe = 0;
+	mlc->opercnt = 0;
+	return 1;
+}
+
+#define FUNC(funct, funct_arg, zero_rc, neg_rc, pos_rc) \
+{ HILSE_FUNC,		{ func: &funct }, funct_arg, zero_rc, neg_rc, pos_rc },
+#define OUT(pack) \
+{ HILSE_OUT,		{ packet: pack }, 0, HILSEN_NEXT, HILSEN_DOZE, 0 },
+#define CTS \
+{ HILSE_CTS,		{ packet: 0    }, 0, HILSEN_NEXT | HILSEN_SCHED | HILSEN_BREAK, HILSEN_DOZE, 0 },
+#define EXPECT(comp, to, got, got_wrong, timed_out) \
+{ HILSE_EXPECT,		{ packet: comp }, to, got, got_wrong, timed_out },
+#define EXPECT_LAST(comp, to, got, got_wrong, timed_out) \
+{ HILSE_EXPECT_LAST,	{ packet: comp }, to, got, got_wrong, timed_out },
+#define EXPECT_DISC(comp, to, got, got_wrong, timed_out) \
+{ HILSE_EXPECT_DISC,	{ packet: comp }, to, got, got_wrong, timed_out },
+#define IN(to, got, got_error, timed_out) \
+{ HILSE_IN,		{ packet: 0    }, to, got, got_error, timed_out },
+#define OUT_DISC(pack) \
+{ HILSE_OUT_DISC,	{ packet: pack }, 0, 0, 0, 0 },
+#define OUT_LAST(pack) \
+{ HILSE_OUT_LAST,	{ packet: pack }, 0, 0, 0, 0 },
+
+struct hilse_node hil_mlc_se[HILSEN_END] = {
+
+	/* 0  HILSEN_START */
+	FUNC(hilse_init_lcv, 0,	HILSEN_NEXT,	HILSEN_SLEEP,	0)
+
+	/* 1  HILSEN_RESTART */
+	FUNC(hilse_inc_lcv, 10,	HILSEN_NEXT,	HILSEN_START,  0)
+	OUT(HIL_CTRL_ONLY)			/* Disable APE */
+	CTS
+
+#define TEST_PACKET(x) \
+(HIL_PKT_CMD | (x << HIL_PKT_ADDR_SHIFT) | x << 4 | x)
+
+	OUT(HIL_DO_ALTER_CTRL | HIL_CTRL_TEST | TEST_PACKET(0x5))
+	EXPECT(HIL_ERR_INT | TEST_PACKET(0x5),
+	       2000,		HILSEN_NEXT,	HILSEN_RESTART,	HILSEN_RESTART)
+	OUT(HIL_DO_ALTER_CTRL | HIL_CTRL_TEST | TEST_PACKET(0xa))
+	EXPECT(HIL_ERR_INT | TEST_PACKET(0xa),
+	       2000,		HILSEN_NEXT,	HILSEN_RESTART,	HILSEN_RESTART)
+	OUT(HIL_CTRL_ONLY | 0)			/* Disable test mode */
+	
+	/* 9  HILSEN_DHR */
+	FUNC(hilse_init_lcv, 0,	HILSEN_NEXT,	HILSEN_SLEEP,	0)
+
+	/* 10 HILSEN_DHR2 */
+	FUNC(hilse_inc_lcv, 10,	HILSEN_NEXT,	HILSEN_START,	0)
+	FUNC(hilse_set_ddi, -1,	HILSEN_NEXT,	0,		0)
+	OUT(HIL_PKT_CMD | HIL_CMD_DHR)
+	IN(300000,		HILSEN_DHR2,	HILSEN_DHR2,	HILSEN_NEXT)
+
+	/* 14 HILSEN_IFC */
+  	OUT(HIL_PKT_CMD | HIL_CMD_IFC)
+	EXPECT(HIL_PKT_CMD | HIL_CMD_IFC | HIL_ERR_INT,
+	       20000,		HILSEN_DISC,	HILSEN_DHR2,	HILSEN_NEXT )
+
+	/* If devices are there, they weren't in PUP or other loopback mode.
+	 * We're more concerned at this point with restoring operation
+	 * to devices than discovering new ones, so we try to salvage
+	 * the loop configuration by closing off the loop.
+	 */
+
+	/* 16 HILSEN_HEAL0 */
+	FUNC(hilse_dec_ddi, 0,	HILSEN_NEXT,	HILSEN_ACF,	0)
+	FUNC(hilse_inc_ddi, 0,	HILSEN_NEXT,	0,		0)
+
+	/* 18 HILSEN_HEAL */
+	OUT_LAST(HIL_CMD_ELB)
+	EXPECT_LAST(HIL_CMD_ELB | HIL_ERR_INT, 
+		    20000,	HILSEN_REPOLL,	HILSEN_DSR,	HILSEN_NEXT)
+	FUNC(hilse_dec_ddi, 0,	HILSEN_HEAL,	HILSEN_NEXT,	0)
+
+	/* 21 HILSEN_ACF */
+	FUNC(hilse_init_lcv, 0,	HILSEN_NEXT,	HILSEN_DOZE,	0)
+
+	/* 22 HILSEN_ACF2 */
+	FUNC(hilse_inc_lcv, 10,	HILSEN_NEXT,	HILSEN_START,	0)
+	OUT(HIL_PKT_CMD | HIL_CMD_ACF | 1)
+	IN(20000,		HILSEN_NEXT,	HILSEN_DSR,	HILSEN_NEXT)
+
+	/* 25 HILSEN_DISC0 */
+	OUT_DISC(HIL_PKT_CMD | HIL_CMD_ELB)
+	EXPECT_DISC(HIL_PKT_CMD | HIL_CMD_ELB | HIL_ERR_INT,
+	       20000,		HILSEN_NEXT,	HILSEN_DSR,	HILSEN_DSR)
+
+	/* Only enter here if response just received */
+	/* 27 HILSEN_DISC */
+	OUT_DISC(HIL_PKT_CMD | HIL_CMD_IDD)
+	EXPECT_DISC(HIL_PKT_CMD | HIL_CMD_IDD | HIL_ERR_INT,
+	       20000,		HILSEN_NEXT,	HILSEN_DSR,	HILSEN_START)
+	FUNC(hilse_inc_ddi,  0,	HILSEN_NEXT,	HILSEN_START,	0)
+	FUNC(hilse_take_idd, 0,	HILSEN_MATCH,	HILSEN_IFCACF,	HILSEN_FOLLOW)
+	OUT_LAST(HIL_PKT_CMD | HIL_CMD_RSC)
+	EXPECT_LAST(HIL_PKT_CMD | HIL_CMD_RSC | HIL_ERR_INT,
+	       30000,		HILSEN_NEXT,	HILSEN_DSR,	HILSEN_DSR)
+	FUNC(hilse_take_rsc, 0,	HILSEN_MATCH,	0,		HILSEN_FOLLOW)
+	OUT_LAST(HIL_PKT_CMD | HIL_CMD_EXD)
+	EXPECT_LAST(HIL_PKT_CMD | HIL_CMD_EXD | HIL_ERR_INT,
+	       30000,		HILSEN_NEXT,	HILSEN_DSR,	HILSEN_DSR)
+	FUNC(hilse_take_exd, 0,	HILSEN_MATCH,	0,		HILSEN_FOLLOW)
+	OUT_LAST(HIL_PKT_CMD | HIL_CMD_RNM)
+	EXPECT_LAST(HIL_PKT_CMD | HIL_CMD_RNM | HIL_ERR_INT,
+	       30000,		HILSEN_NEXT,	HILSEN_DSR,	HILSEN_DSR)
+	FUNC(hilse_take_rnm, 0, HILSEN_MATCH,	0,		0)
+
+	/* 40 HILSEN_MATCH */
+	FUNC(hilse_match, 0,	HILSEN_NEXT,	HILSEN_NEXT,	/* TODO */ 0)
+
+	/* 41 HILSEN_OPERATE */
+	OUT(HIL_PKT_CMD | HIL_CMD_POL)
+	EXPECT(HIL_PKT_CMD | HIL_CMD_POL | HIL_ERR_INT,
+	       20000,		HILSEN_NEXT,	HILSEN_DSR,	HILSEN_NEXT)
+	FUNC(hilse_operate, 0,	HILSEN_OPERATE,	HILSEN_IFC,	HILSEN_NEXT)
+
+	/* 44 HILSEN_PROBE */
+	OUT_LAST(HIL_PKT_CMD | HIL_CMD_EPT)
+	IN(10000, 		HILSEN_DISC,	HILSEN_DSR,	HILSEN_NEXT)
+	OUT_DISC(HIL_PKT_CMD | HIL_CMD_ELB)
+	IN(10000,		HILSEN_DISC,	HILSEN_DSR,	HILSEN_NEXT)
+	OUT(HIL_PKT_CMD | HIL_CMD_ACF | 1)
+	IN(10000,		HILSEN_DISC0,	HILSEN_DSR,	HILSEN_NEXT)
+	OUT_LAST(HIL_PKT_CMD | HIL_CMD_ELB)
+	IN(10000,		HILSEN_OPERATE,	HILSEN_DSR,	HILSEN_DSR)
+
+	/* 52 HILSEN_DSR */
+	FUNC(hilse_set_ddi, -1,	HILSEN_NEXT,	0,		0)
+	OUT(HIL_PKT_CMD | HIL_CMD_DSR)
+	IN(20000, 		HILSEN_DHR,	HILSEN_DHR,	HILSEN_IFC)
+
+	/* 55 HILSEN_REPOLL */
+	OUT(HIL_PKT_CMD | HIL_CMD_RPL)
+	EXPECT(HIL_PKT_CMD | HIL_CMD_RPL | HIL_ERR_INT,
+	       20000,		HILSEN_NEXT,	HILSEN_DSR,	HILSEN_NEXT)
+	FUNC(hilse_operate, 1,	HILSEN_OPERATE,	HILSEN_IFC,	HILSEN_PROBE)
+
+	/* 58 HILSEN_IFCACF */
+  	OUT(HIL_PKT_CMD | HIL_CMD_IFC)
+	EXPECT(HIL_PKT_CMD | HIL_CMD_IFC | HIL_ERR_INT,
+	       20000,		HILSEN_ACF2,	HILSEN_DHR2,	HILSEN_HEAL)
+
+	/* 60 HILSEN_END */
+};
+
+static inline void hilse_setup_input(hil_mlc *mlc, struct hilse_node *node) {
+
+	switch (node->act) {
+	case HILSE_EXPECT_DISC:
+		mlc->imatch = node->object.packet;
+		mlc->imatch |= ((mlc->ddi + 2) << HIL_PKT_ADDR_SHIFT);
+		break;
+	case HILSE_EXPECT_LAST:
+		mlc->imatch = node->object.packet;
+		mlc->imatch |= ((mlc->ddi + 1) << HIL_PKT_ADDR_SHIFT);
+		break;
+	case HILSE_EXPECT:
+		mlc->imatch = node->object.packet;
+		break;
+	case HILSE_IN:
+		mlc->imatch = 0;
+		break;
+	default:
+		BUG();
+	}
+	mlc->istarted = 1;
+	mlc->intimeout = node->arg;
+	do_gettimeofday(&(mlc->instart));
+	mlc->icount = 15;
+	memset(mlc->ipacket, 0, 16 * sizeof(hil_packet));
+	if (down_trylock(&(mlc->isem))) BUG();
+
+	return;
+}
+
+#ifdef HIL_MLC_DEBUG
+static int doze = 0;
+static int seidx; /* For debug */
+static int kick = 1;
+#endif
+
+static int hilse_donode (hil_mlc *mlc) {
+	struct hilse_node *node;
+	int nextidx = 0;
+	int sched_long = 0;
+	unsigned long flags;
+
+#ifdef HIL_MLC_DEBUG
+	if (mlc->seidx && (mlc->seidx != seidx)  && mlc->seidx != 41 && mlc->seidx != 42 && mlc->seidx != 43) {
+	  printk(KERN_DEBUG PREFIX "z%i \n%s {%i}", doze, kick ? "K" : "", mlc->seidx);
+		doze = 0;
+	}
+	kick = 0;
+
+	seidx = mlc->seidx;
+#endif
+	node = hil_mlc_se + mlc->seidx;
+
+	switch (node->act) {
+		int rc;
+		hil_packet pack;
+
+	case HILSE_FUNC:
+		if (node->object.func == NULL) break;
+		rc = node->object.func(mlc, node->arg);
+		nextidx = (rc > 0) ? node->ugly : 
+			((rc < 0) ? node->bad : node->good);
+		if (nextidx == HILSEN_FOLLOW) nextidx = rc;
+		break;
+	case HILSE_EXPECT_LAST:
+	case HILSE_EXPECT_DISC:
+	case HILSE_EXPECT:
+	case HILSE_IN:
+		/* Already set up from previous HILSE_OUT_* */
+		write_lock_irqsave(&(mlc->lock), flags);
+		rc = mlc->in(mlc, node->arg);
+		if (rc == 2)  {
+			nextidx = HILSEN_DOZE;
+			sched_long = 1;
+			write_unlock_irqrestore(&(mlc->lock), flags);
+			break;
+		}
+		if (rc == 1)		nextidx = node->ugly;
+		else if (rc == 0)	nextidx = node->good;
+		else			nextidx = node->bad;
+		mlc->istarted = 0;
+		write_unlock_irqrestore(&(mlc->lock), flags);
+		break;
+	case HILSE_OUT_LAST:
+		write_lock_irqsave(&(mlc->lock), flags);
+		pack = node->object.packet;
+		pack |= ((mlc->ddi + 1) << HIL_PKT_ADDR_SHIFT);
+		goto out;
+	case HILSE_OUT_DISC:
+		write_lock_irqsave(&(mlc->lock), flags);
+		pack = node->object.packet;
+		pack |= ((mlc->ddi + 2) << HIL_PKT_ADDR_SHIFT);
+		goto out;
+	case HILSE_OUT:
+		write_lock_irqsave(&(mlc->lock), flags);
+		pack = node->object.packet;
+	out:
+		if (mlc->istarted) goto out2;
+		/* Prepare to receive input */
+		if ((node + 1)->act & HILSE_IN)
+			hilse_setup_input(mlc, node + 1);
+
+	out2:
+		write_unlock_irqrestore(&(mlc->lock), flags);
+
+		if (down_trylock(&mlc->osem)) {
+			nextidx = HILSEN_DOZE;
+			break;
+		}
+		up(&mlc->osem);
+
+		write_lock_irqsave(&(mlc->lock), flags);
+		if (!(mlc->ostarted)) {
+			mlc->ostarted = 1;
+			mlc->opacket = pack;
+			mlc->out(mlc);
+			nextidx = HILSEN_DOZE;
+			write_unlock_irqrestore(&(mlc->lock), flags);
+			break;
+		}
+		mlc->ostarted = 0;
+		do_gettimeofday(&(mlc->instart));
+		write_unlock_irqrestore(&(mlc->lock), flags);
+		nextidx = HILSEN_NEXT;
+		break;
+	case HILSE_CTS:
+		nextidx = mlc->cts(mlc) ? node->bad : node->good;
+		break;
+	default:
+		BUG();
+		nextidx = 0;
+		break;
+	}
+
+#ifdef HIL_MLC_DEBUG
+	if (nextidx == HILSEN_DOZE) doze++;
+#endif
+
+	while (nextidx & HILSEN_SCHED) {
+		struct timeval tv;
+
+		if (!sched_long) goto sched;
+
+		do_gettimeofday(&tv);
+		tv.tv_usec += 1000000 * (tv.tv_sec - mlc->instart.tv_sec);
+		tv.tv_usec -= mlc->instart.tv_usec;
+		if (tv.tv_usec >= mlc->intimeout) goto sched;
+		tv.tv_usec = (mlc->intimeout - tv.tv_usec) * HZ / 1000000;
+		if (!tv.tv_usec) goto sched;
+		mod_timer(&hil_mlcs_kicker, jiffies + tv.tv_usec);
+		break;
+	sched:
+		tasklet_schedule(&hil_mlcs_tasklet);
+		break;
+	} 
+	if (nextidx & HILSEN_DOWN) mlc->seidx += nextidx & HILSEN_MASK;
+	else if (nextidx & HILSEN_UP) mlc->seidx -= nextidx & HILSEN_MASK;
+	else mlc->seidx = nextidx & HILSEN_MASK;
+
+	if (nextidx & HILSEN_BREAK)	return 1;
+	return 0;
+}
+
+/******************** tasklet context functions **************************/
+static void hil_mlcs_process(unsigned long unused) {
+	struct list_head *tmp;
+
+	read_lock(&hil_mlcs_lock);
+	list_for_each(tmp, &hil_mlcs) {
+		struct hil_mlc *mlc = list_entry(tmp, hil_mlc, list);
+		while (hilse_donode(mlc) == 0) {
+#ifdef HIL_MLC_DEBUG
+		  if (mlc->seidx != 41 && 
+		      mlc->seidx != 42 && 
+		      mlc->seidx != 43) 
+		    printk(KERN_DEBUG PREFIX " + ");
+#endif
+		};
+	}
+	read_unlock(&hil_mlcs_lock);
+}
+
+/************************* Keepalive timer task *********************/
+
+void hil_mlcs_timer (unsigned long data) {
+	hil_mlcs_probe = 1;
+	tasklet_schedule(&hil_mlcs_tasklet);
+	/* Re-insert the periodic task. */
+	if (!timer_pending(&hil_mlcs_kicker))
+		mod_timer(&hil_mlcs_kicker, jiffies + HZ);
+}
+
+/******************** user/kernel context functions **********************/
+
+static int hil_mlc_serio_write(struct serio *serio, unsigned char c) {
+	struct hil_mlc_serio_map *map;
+	struct hil_mlc *mlc;
+	struct serio_driver *drv;
+	uint8_t *idx, *last;
+
+	map = serio->port_data;
+	if (map == NULL) {
+		BUG();
+		return -EIO;
+	}
+	mlc = map->mlc;
+	if (mlc == NULL) {
+		BUG();
+		return -EIO;
+	}
+	mlc->serio_opacket[map->didx] |= 
+		((hil_packet)c) << (8 * (3 - mlc->serio_oidx[map->didx]));
+
+	if (mlc->serio_oidx[map->didx] >= 3) {
+		/* for now only commands */
+		if (!(mlc->serio_opacket[map->didx] & HIL_PKT_CMD)) 
+			return -EIO;
+		switch (mlc->serio_opacket[map->didx] & HIL_PKT_DATA_MASK) {
+		case HIL_CMD_IDD:
+			idx = mlc->di[map->didx].idd;
+			goto emu;
+		case HIL_CMD_RSC:
+			idx = mlc->di[map->didx].rsc;
+			goto emu;
+		case HIL_CMD_EXD:
+			idx = mlc->di[map->didx].exd;
+			goto emu;
+		case HIL_CMD_RNM:
+			idx = mlc->di[map->didx].rnm;
+			goto emu;
+		default:
+			break;
+		}
+		mlc->serio_oidx[map->didx] = 0;
+		mlc->serio_opacket[map->didx] = 0;
+	}
+
+	mlc->serio_oidx[map->didx]++;
+	return -EIO;
+ emu:
+	drv = serio->drv;
+	if (drv == NULL) {
+		BUG();
+		return -EIO;
+	}
+	last = idx + 15;
+	while ((last != idx) && (*last == 0)) last--;
+
+	while (idx != last) {
+		drv->interrupt(serio, 0, 0, NULL);
+		drv->interrupt(serio, HIL_ERR_INT >> 16, 0, NULL);
+		drv->interrupt(serio, 0, 0, NULL);
+		drv->interrupt(serio, *idx, 0, NULL);
+		idx++;
+	}
+	drv->interrupt(serio, 0, 0, NULL);
+	drv->interrupt(serio, HIL_ERR_INT >> 16, 0, NULL);
+	drv->interrupt(serio, HIL_PKT_CMD >> 8, 0, NULL);
+	drv->interrupt(serio, *idx, 0, NULL);
+	
+	mlc->serio_oidx[map->didx] = 0;
+	mlc->serio_opacket[map->didx] = 0;
+
+	return 0;
+}
+
+static int hil_mlc_serio_open(struct serio *serio) {
+	struct hil_mlc_serio_map *map;
+	struct hil_mlc *mlc;
+
+	if (serio->private != NULL) return -EBUSY;
+
+	map = serio->port_data;
+	if (map == NULL) {
+		BUG();
+		return -ENODEV;
+	}
+	mlc = map->mlc;
+	if (mlc == NULL) {
+		BUG();
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
+static void hil_mlc_serio_close(struct serio *serio) {
+	struct hil_mlc_serio_map *map;
+	struct hil_mlc *mlc;
+
+	map = serio->port_data;
+	if (map == NULL) {
+		BUG();
+		return;
+	}
+	mlc = map->mlc;
+	if (mlc == NULL) {
+		BUG();
+		return;
+	}
+
+	serio->private = NULL;
+	serio->drv = NULL;
+	/* TODO wake up interruptable */
+}
+
+int hil_mlc_register(hil_mlc *mlc) {
+	int i;
+        unsigned long flags;
+
+	if (mlc == NULL) {
+		return -EINVAL;
+	}
+
+	mlc->istarted = 0;
+        mlc->ostarted = 0;
+
+        mlc->lock = RW_LOCK_UNLOCKED;
+        init_MUTEX(&(mlc->osem));
+
+        init_MUTEX(&(mlc->isem));
+        mlc->icount = -1;
+        mlc->imatch = 0;
+
+	mlc->opercnt = 0;
+
+        init_MUTEX_LOCKED(&(mlc->csem));
+
+	hil_mlc_clear_di_scratch(mlc);
+	hil_mlc_clear_di_map(mlc, 0);
+	for (i = 0; i < HIL_MLC_DEVMEM; i++) {
+		struct serio *mlc_serio;
+		hil_mlc_copy_di_scratch(mlc, i);
+		mlc_serio = kmalloc(sizeof(*mlc_serio), GFP_KERNEL);
+		mlc->serio[i] = mlc_serio;
+		memset(mlc_serio, 0, sizeof(*mlc_serio));
+		mlc_serio->type			= SERIO_HIL | SERIO_HIL_MLC;
+		mlc_serio->write		= hil_mlc_serio_write;
+		mlc_serio->open			= hil_mlc_serio_open;
+		mlc_serio->close		= hil_mlc_serio_close;
+		mlc_serio->port_data		= &(mlc->serio_map[i]);
+		mlc->serio_map[i].mlc		= mlc;
+		mlc->serio_map[i].didx		= i;
+		mlc->serio_map[i].di_revmap	= -1;
+		mlc->serio_opacket[i]		= 0;
+		mlc->serio_oidx[i]		= 0;
+		serio_register_port(mlc_serio);
+	}
+
+	mlc->tasklet = &hil_mlcs_tasklet;
+
+	write_lock_irqsave(&hil_mlcs_lock, flags);
+	list_add_tail(&mlc->list, &hil_mlcs);
+	mlc->seidx = HILSEN_START;
+	write_unlock_irqrestore(&hil_mlcs_lock, flags);
+
+	tasklet_schedule(&hil_mlcs_tasklet);
+	return 0;
+}
+
+int hil_mlc_unregister(hil_mlc *mlc) {
+	struct list_head *tmp;
+        unsigned long flags;
+	int i;
+
+	if (mlc == NULL)
+		return -EINVAL;
+
+	write_lock_irqsave(&hil_mlcs_lock, flags);
+	list_for_each(tmp, &hil_mlcs) {
+		if (list_entry(tmp, hil_mlc, list) == mlc)
+			goto found;
+	}
+
+	/* not found in list */
+	write_unlock_irqrestore(&hil_mlcs_lock, flags);
+	tasklet_schedule(&hil_mlcs_tasklet);
+	return -ENODEV;
+
+ found:
+	list_del(tmp);
+        write_unlock_irqrestore(&hil_mlcs_lock, flags);
+
+	for (i = 0; i < HIL_MLC_DEVMEM; i++) {
+		serio_unregister_port(mlc->serio[i]);
+		mlc->serio[i] = NULL;
+	}
+
+	tasklet_schedule(&hil_mlcs_tasklet);
+	return 0;
+}
+
+/**************************** Module interface *************************/
+
+static int __init hil_mlc_init(void)
+{
+	init_timer(&hil_mlcs_kicker);
+	hil_mlcs_kicker.expires = jiffies + HZ;
+	hil_mlcs_kicker.function = &hil_mlcs_timer;
+	add_timer(&hil_mlcs_kicker);
+
+	tasklet_enable(&hil_mlcs_tasklet);
+
+	return 0;
+}
+                
+static void __exit hil_mlc_exit(void)
+{
+	del_timer(&hil_mlcs_kicker);
+
+	tasklet_disable(&hil_mlcs_tasklet);
+	tasklet_kill(&hil_mlcs_tasklet);
+}
+                        
+module_init(hil_mlc_init);
+module_exit(hil_mlc_exit);
diff -Nru a/drivers/input/serio/hp_sdc.c b/drivers/input/serio/hp_sdc.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/input/serio/hp_sdc.c	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,1055 @@
+/*
+ * HP i8042-based System Device Controller driver.
+ *
+ * Copyright (c) 2001 Brian S. Julin
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions, and the following disclaimer,
+ *    without modification.
+ * 2. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL").
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ *
+ * References:
+ * System Device Controller Microprocessor Firmware Theory of Operation
+ *      for Part Number 1820-4784 Revision B.  Dwg No. A-1820-4784-2
+ * Helge Deller's original hilkbd.c port for PA-RISC.
+ *
+ *
+ * Driver theory of operation:
+ *
+ * hp_sdc_put does all writing to the SDC.  ISR can run on a different 
+ * CPU than hp_sdc_put, but only one CPU runs hp_sdc_put at a time 
+ * (it cannot really benefit from SMP anyway.)  A tasket fit this perfectly.
+ *
+ * All data coming back from the SDC is sent via interrupt and can be read 
+ * fully in the ISR, so there are no latency/throughput problems there.  
+ * The problem is with output, due to the slow clock speed of the SDC 
+ * compared to the CPU.  This should not be too horrible most of the time, 
+ * but if used with HIL devices that support the multibyte transfer command, 
+ * keeping outbound throughput flowing at the 6500KBps that the HIL is 
+ * capable of is more than can be done at HZ=100.
+ *
+ * Busy polling for IBF clear wastes CPU cycles and bus cycles.  hp_sdc.ibf 
+ * is set to 0 when the IBF flag in the status register has cleared.  ISR 
+ * may do this, and may also access the parts of queued transactions related 
+ * to reading data back from the SDC, but otherwise will not touch the 
+ * hp_sdc state. Whenever a register is written hp_sdc.ibf is set to 1.
+ *
+ * The i8042 write index and the values in the 4-byte input buffer
+ * starting at 0x70 are kept track of in hp_sdc.wi, and .r7[], respectively,
+ * to minimize the amount of IO needed to the SDC.  However these values 
+ * do not need to be locked since they are only ever accessed by hp_sdc_put.
+ *
+ * A timer task schedules the tasklet once per second just to make
+ * sure it doesn't freeze up and to allow for bad reads to time out.
+ */
+
+#include <linux/hp_sdc.h>
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/ioport.h>
+#include <linux/time.h>
+#include <linux/slab.h>
+#include <linux/hil.h>
+#include <asm/io.h>
+#include <asm/system.h>
+
+/* Machine-specific abstraction */
+
+#if defined(__hppa__)
+# include <asm/parisc-device.h>
+# define sdc_readb(p)		gsc_readb(p)
+# define sdc_writeb(v,p)	gsc_writeb((v),(p))
+#elif defined(__mc68000__)
+# include <asm/uaccess.h>
+# define sdc_readb(p)		in_8(p)
+# define sdc_writeb(v,p)	out_8((p),(v))
+#else
+# error "HIL is not supported on this platform"
+#endif
+
+#define PREFIX "HP SDC: "
+
+MODULE_AUTHOR("Brian S. Julin <bri@calyx.com>");
+MODULE_DESCRIPTION("HP i8042-based SDC Driver");
+MODULE_LICENSE("Dual BSD/GPL");
+
+EXPORT_SYMBOL(hp_sdc_request_timer_irq);
+EXPORT_SYMBOL(hp_sdc_request_hil_irq);
+EXPORT_SYMBOL(hp_sdc_request_cooked_irq);
+
+EXPORT_SYMBOL(hp_sdc_release_timer_irq);
+EXPORT_SYMBOL(hp_sdc_release_hil_irq);
+EXPORT_SYMBOL(hp_sdc_release_cooked_irq);
+
+EXPORT_SYMBOL(hp_sdc_enqueue_transaction);
+EXPORT_SYMBOL(hp_sdc_dequeue_transaction);
+
+static hp_i8042_sdc	hp_sdc;	/* All driver state is kept in here. */
+
+/*************** primitives for use in any context *********************/
+static inline uint8_t hp_sdc_status_in8 (void) {
+	uint8_t status;
+	unsigned long flags;
+
+	write_lock_irqsave(&hp_sdc.ibf_lock, flags);
+	status = sdc_readb(hp_sdc.status_io);
+	if (!(status & HP_SDC_STATUS_IBF)) hp_sdc.ibf = 0;
+	write_unlock_irqrestore(&hp_sdc.ibf_lock, flags);
+
+	return status;
+}
+
+static inline uint8_t hp_sdc_data_in8 (void) {
+	return sdc_readb(hp_sdc.data_io); 
+}
+
+static inline void hp_sdc_status_out8 (uint8_t val) {
+	unsigned long flags;
+
+	write_lock_irqsave(&hp_sdc.ibf_lock, flags);
+	hp_sdc.ibf = 1;
+	if ((val & 0xf0) == 0xe0) hp_sdc.wi = 0xff;
+	sdc_writeb(val, hp_sdc.status_io);
+	write_unlock_irqrestore(&hp_sdc.ibf_lock, flags);
+}
+
+static inline void hp_sdc_data_out8 (uint8_t val) {
+	unsigned long flags;
+
+	write_lock_irqsave(&hp_sdc.ibf_lock, flags);
+	hp_sdc.ibf = 1;
+	sdc_writeb(val, hp_sdc.data_io);
+	write_unlock_irqrestore(&hp_sdc.ibf_lock, flags);
+}
+
+/*	Care must be taken to only invoke hp_sdc_spin_ibf when 
+ *	absolutely needed, or in rarely invoked subroutines.  
+ *	Not only does it waste CPU cycles, it also wastes bus cycles. 
+ */
+static inline void hp_sdc_spin_ibf(void) {
+	unsigned long flags;
+	rwlock_t *lock;
+
+	lock = &hp_sdc.ibf_lock;
+
+	read_lock_irqsave(lock, flags);
+	if (!hp_sdc.ibf) {
+		read_unlock_irqrestore(lock, flags);
+		return;
+	}
+	read_unlock(lock);
+	write_lock(lock);
+	while (sdc_readb(hp_sdc.status_io) & HP_SDC_STATUS_IBF) {};
+	hp_sdc.ibf = 0;
+	write_unlock_irqrestore(lock, flags);
+}
+
+
+/************************ Interrupt context functions ************************/
+static void hp_sdc_take (int irq, void *dev_id, uint8_t status, uint8_t data) {
+	hp_sdc_transaction *curr;
+
+	read_lock(&hp_sdc.rtq_lock);
+	if (hp_sdc.rcurr < 0) {
+	  	read_unlock(&hp_sdc.rtq_lock);
+		return;
+	}
+	curr = hp_sdc.tq[hp_sdc.rcurr];
+	read_unlock(&hp_sdc.rtq_lock);
+
+	curr->seq[curr->idx++] = status;
+	curr->seq[curr->idx++] = data;
+	hp_sdc.rqty -= 2;
+	do_gettimeofday(&hp_sdc.rtv);
+
+	if (hp_sdc.rqty <= 0) {
+		/* All data has been gathered. */
+		if(curr->seq[curr->actidx] & HP_SDC_ACT_SEMAPHORE) {
+			if (curr->act.semaphore) up(curr->act.semaphore);
+		}
+		if(curr->seq[curr->actidx] & HP_SDC_ACT_CALLBACK) {
+			if (curr->act.irqhook)
+				curr->act.irqhook(irq, dev_id, status, data);
+		}
+		curr->actidx = curr->idx;
+		curr->idx++;
+		/* Return control of this transaction */
+		write_lock(&hp_sdc.rtq_lock);
+		hp_sdc.rcurr = -1; 
+		hp_sdc.rqty = 0;
+		write_unlock(&hp_sdc.rtq_lock);
+		tasklet_schedule(&hp_sdc.task);
+	}
+}
+
+static irqreturn_t hp_sdc_isr(int irq, void *dev_id, struct pt_regs * regs) {
+	uint8_t status, data;
+
+	status = hp_sdc_status_in8();
+	/* Read data unconditionally to advance i8042. */
+	data =   hp_sdc_data_in8();
+
+	/* For now we are ignoring these until we get the SDC to behave. */
+	if (((status & 0xf1) == 0x51) && data == 0x82) {
+	  return IRQ_HANDLED;
+	}
+
+	switch(status & HP_SDC_STATUS_IRQMASK) {
+	      case 0: /* This case is not documented. */
+		break;
+	      case HP_SDC_STATUS_USERTIMER:
+	      case HP_SDC_STATUS_PERIODIC:
+	      case HP_SDC_STATUS_TIMER:
+		read_lock(&hp_sdc.hook_lock);
+	      	if (hp_sdc.timer != NULL)
+			hp_sdc.timer(irq, dev_id, status, data);
+		read_unlock(&hp_sdc.hook_lock);
+		break;
+	      case HP_SDC_STATUS_REG:
+		hp_sdc_take(irq, dev_id, status, data);
+		break;
+	      case HP_SDC_STATUS_HILCMD:
+	      case HP_SDC_STATUS_HILDATA:
+		read_lock(&hp_sdc.hook_lock);
+		if (hp_sdc.hil != NULL)
+			hp_sdc.hil(irq, dev_id, status, data);
+		read_unlock(&hp_sdc.hook_lock);
+		break;
+	      case HP_SDC_STATUS_PUP:
+		read_lock(&hp_sdc.hook_lock);
+		if (hp_sdc.pup != NULL)
+			hp_sdc.pup(irq, dev_id, status, data);
+		else printk(KERN_INFO PREFIX "HP SDC reports successful PUP.\n");
+		read_unlock(&hp_sdc.hook_lock);
+		break;
+	      default:
+		read_lock(&hp_sdc.hook_lock);
+		if (hp_sdc.cooked != NULL)
+			hp_sdc.cooked(irq, dev_id, status, data);
+		read_unlock(&hp_sdc.hook_lock);
+		break;
+	}
+	return IRQ_HANDLED;
+}
+
+
+static irqreturn_t hp_sdc_nmisr(int irq, void *dev_id, struct pt_regs * regs) {
+	int status;
+	
+	status = hp_sdc_status_in8();
+	printk(KERN_WARNING PREFIX "NMI !\n");
+
+#if 0	
+	if (status & HP_SDC_NMISTATUS_FHS) {
+		read_lock(&hp_sdc.hook_lock);
+	      	if (hp_sdc.timer != NULL)
+			hp_sdc.timer(irq, dev_id, status, 0);
+		read_unlock(&hp_sdc.hook_lock);
+	}
+	else {
+		/* TODO: pass this on to the HIL handler, or do SAK here? */
+		printk(KERN_WARNING PREFIX "HIL NMI\n");
+	}
+#endif
+	return IRQ_HANDLED;
+}
+
+
+/***************** Kernel (tasklet) context functions ****************/
+
+unsigned long hp_sdc_put(void);
+
+static void hp_sdc_tasklet(unsigned long foo) {
+
+	write_lock_irq(&hp_sdc.rtq_lock);
+	if (hp_sdc.rcurr >= 0) {
+		struct timeval tv;
+		do_gettimeofday(&tv);
+		if (tv.tv_sec > hp_sdc.rtv.tv_sec) tv.tv_usec += 1000000;
+		if (tv.tv_usec - hp_sdc.rtv.tv_usec > HP_SDC_MAX_REG_DELAY) {
+			hp_sdc_transaction *curr;
+			uint8_t tmp;
+
+			curr = hp_sdc.tq[hp_sdc.rcurr];
+			/* If this turns out to be a normal failure mode
+			 * we'll need to figure out a way to communicate
+			 * it back to the application. and be less verbose.
+			 */
+			printk(KERN_WARNING PREFIX "read timeout (%ius)!\n",
+			       tv.tv_usec - hp_sdc.rtv.tv_usec);
+			curr->idx += hp_sdc.rqty;
+			hp_sdc.rqty = 0;
+			tmp = curr->seq[curr->actidx];
+			curr->seq[curr->actidx] |= HP_SDC_ACT_DEAD;
+			if(tmp & HP_SDC_ACT_SEMAPHORE) {
+				if (curr->act.semaphore) 
+					up(curr->act.semaphore);
+			}
+			if(tmp & HP_SDC_ACT_CALLBACK) {
+				/* Note this means that irqhooks may be called
+				 * in tasklet/bh context.
+				 */
+				if (curr->act.irqhook) 
+					curr->act.irqhook(0, 0, 0, 0);
+			}
+			curr->actidx = curr->idx;
+			curr->idx++;
+			hp_sdc.rcurr = -1; 
+		}
+	}
+	write_unlock_irq(&hp_sdc.rtq_lock);
+	hp_sdc_put();
+}
+
+unsigned long hp_sdc_put(void) {
+	hp_sdc_transaction *curr;
+	uint8_t act;
+	int idx, curridx;
+
+	int limit = 0;
+
+	write_lock(&hp_sdc.lock);
+
+	/* If i8042 buffers are full, we cannot do anything that
+	   requires output, so we skip to the administrativa. */
+	if (hp_sdc.ibf) {
+		hp_sdc_status_in8();
+		if (hp_sdc.ibf) goto finish;
+	}
+
+ anew:
+	/* See if we are in the middle of a sequence. */
+	if (hp_sdc.wcurr < 0) hp_sdc.wcurr = 0;
+	read_lock_irq(&hp_sdc.rtq_lock);
+	if (hp_sdc.rcurr == hp_sdc.wcurr) hp_sdc.wcurr++;
+	read_unlock_irq(&hp_sdc.rtq_lock);
+	if (hp_sdc.wcurr >= HP_SDC_QUEUE_LEN) hp_sdc.wcurr = 0;
+	curridx = hp_sdc.wcurr;
+
+	if (hp_sdc.tq[curridx] != NULL) goto start;
+
+	while (++curridx != hp_sdc.wcurr) {
+		if (curridx >= HP_SDC_QUEUE_LEN) {
+			curridx = -1; /* Wrap to top */
+			continue;
+		}
+		read_lock_irq(&hp_sdc.rtq_lock);
+		if (hp_sdc.rcurr == curridx) {
+			read_unlock_irq(&hp_sdc.rtq_lock);
+			continue;
+		}
+		read_unlock_irq(&hp_sdc.rtq_lock);
+		if (hp_sdc.tq[curridx] != NULL) break; /* Found one. */
+	}
+	if (curridx == hp_sdc.wcurr) { /* There's nothing queued to do. */
+		curridx = -1;
+	}
+	hp_sdc.wcurr = curridx;
+
+ start:
+
+	/* Check to see if the interrupt mask needs to be set. */
+	if (hp_sdc.set_im) {
+		hp_sdc_status_out8(hp_sdc.im | HP_SDC_CMD_SET_IM);
+		hp_sdc.set_im = 0;
+		goto finish;
+	}
+
+	if (hp_sdc.wcurr == -1) goto done;
+
+	curr = hp_sdc.tq[curridx];
+	idx = curr->actidx;
+
+	if (curr->actidx >= curr->endidx) {
+		hp_sdc.tq[curridx] = NULL;
+		/* Interleave outbound data between the transactions. */
+		hp_sdc.wcurr++;
+		if (hp_sdc.wcurr >= HP_SDC_QUEUE_LEN) hp_sdc.wcurr = 0;
+		goto finish;	
+	}
+
+	act = curr->seq[idx];
+	idx++;
+
+	if (curr->idx >= curr->endidx) {
+		if (act & HP_SDC_ACT_DEALLOC) kfree(curr);
+		hp_sdc.tq[curridx] = NULL;
+		/* Interleave outbound data between the transactions. */
+		hp_sdc.wcurr++;
+		if (hp_sdc.wcurr >= HP_SDC_QUEUE_LEN) hp_sdc.wcurr = 0;
+		goto finish;	
+	}
+
+	while (act & HP_SDC_ACT_PRECMD) {
+		if (curr->idx != idx) {
+			idx++;
+			act &= ~HP_SDC_ACT_PRECMD;
+			break;
+		}
+		hp_sdc_status_out8(curr->seq[idx]);
+		curr->idx++;
+		/* act finished? */
+		if ((act & HP_SDC_ACT_DURING) == HP_SDC_ACT_PRECMD)
+		  goto actdone;
+		/* skip quantity field if data-out sequence follows. */
+		if (act & HP_SDC_ACT_DATAOUT) curr->idx++;
+		goto finish;
+	}
+	if (act & HP_SDC_ACT_DATAOUT) {
+		int qty;
+
+		qty = curr->seq[idx];
+		idx++;
+		if (curr->idx - idx < qty) {
+			hp_sdc_data_out8(curr->seq[curr->idx]);
+			curr->idx++;
+			/* act finished? */
+			if ((curr->idx - idx >= qty) && 
+			    ((act & HP_SDC_ACT_DURING) == HP_SDC_ACT_DATAOUT))
+				goto actdone;
+			goto finish;
+		}
+		idx += qty;
+		act &= ~HP_SDC_ACT_DATAOUT;
+	}
+	else while (act & HP_SDC_ACT_DATAREG) {
+		int mask;
+		uint8_t w7[4];
+
+		mask = curr->seq[idx];
+		if (idx != curr->idx) {
+			idx++;
+			idx += !!(mask & 1);
+			idx += !!(mask & 2);
+			idx += !!(mask & 4);
+			idx += !!(mask & 8);
+			act &= ~HP_SDC_ACT_DATAREG;
+			break;
+		}
+		
+		w7[0] = (mask & 1) ? curr->seq[++idx] : hp_sdc.r7[0];
+		w7[1] = (mask & 2) ? curr->seq[++idx] : hp_sdc.r7[1];
+		w7[2] = (mask & 4) ? curr->seq[++idx] : hp_sdc.r7[2];
+		w7[3] = (mask & 8) ? curr->seq[++idx] : hp_sdc.r7[3];
+		
+		if (hp_sdc.wi > 0x73 || hp_sdc.wi < 0x70 ||
+		        w7[hp_sdc.wi-0x70] == hp_sdc.r7[hp_sdc.wi-0x70]) {
+			int i = 0;
+
+			/* Need to point the write index register */	
+			while ((i < 4) && w7[i] == hp_sdc.r7[i]) i++;
+			if (i < 4) {
+				hp_sdc_status_out8(HP_SDC_CMD_SET_D0 + i);
+				hp_sdc.wi = 0x70 + i;
+				goto finish;
+			}
+			idx++;
+			if ((act & HP_SDC_ACT_DURING) == HP_SDC_ACT_DATAREG)
+				goto actdone;
+			curr->idx = idx;
+			act &= ~HP_SDC_ACT_DATAREG;
+			break;
+		}
+
+		hp_sdc_data_out8(w7[hp_sdc.wi - 0x70]);
+		hp_sdc.r7[hp_sdc.wi - 0x70] = w7[hp_sdc.wi - 0x70];
+		hp_sdc.wi++; /* write index register autoincrements */
+		{
+			int i = 0;
+
+			while ((i < 4) && w7[i] == hp_sdc.r7[i]) i++;
+			if (i >= 4) {
+				curr->idx = idx + 1;
+				if ((act & HP_SDC_ACT_DURING) == 
+				    HP_SDC_ACT_DATAREG)
+				        goto actdone;
+			}
+		}
+		goto finish;
+	}
+	/* We don't go any further in the command if there is a pending read,
+	   because we don't want interleaved results. */
+	read_lock_irq(&hp_sdc.rtq_lock);
+	if (hp_sdc.rcurr >= 0) {
+		read_unlock_irq(&hp_sdc.rtq_lock);
+		goto finish;
+	}
+	read_unlock_irq(&hp_sdc.rtq_lock);
+
+
+	if (act & HP_SDC_ACT_POSTCMD) {
+	  	uint8_t postcmd;
+
+		/* curr->idx should == idx at this point. */
+		postcmd = curr->seq[idx];
+		curr->idx++;
+		if (act & HP_SDC_ACT_DATAIN) {
+
+			/* Start a new read */
+	  		hp_sdc.rqty = curr->seq[curr->idx];
+			do_gettimeofday(&hp_sdc.rtv);
+			curr->idx++;
+			/* Still need to lock here in case of spurious irq. */
+			write_lock_irq(&hp_sdc.rtq_lock);
+			hp_sdc.rcurr = curridx; 
+			write_unlock_irq(&hp_sdc.rtq_lock);
+			hp_sdc_status_out8(postcmd);
+			goto finish;
+		}
+		hp_sdc_status_out8(postcmd);
+		goto actdone;
+	}
+
+actdone:
+	if (act & HP_SDC_ACT_SEMAPHORE) {
+		up(curr->act.semaphore);
+	}
+	else if (act & HP_SDC_ACT_CALLBACK) {
+		curr->act.irqhook(0,0,0,0);
+	}
+	if (curr->idx >= curr->endidx) { /* This transaction is over. */
+		if (act & HP_SDC_ACT_DEALLOC) kfree(curr);
+		hp_sdc.tq[curridx] = NULL;
+	}
+	else {
+		curr->actidx = idx + 1;
+		curr->idx = idx + 2;
+	}
+	/* Interleave outbound data between the transactions. */
+	hp_sdc.wcurr++;
+	if (hp_sdc.wcurr >= HP_SDC_QUEUE_LEN) hp_sdc.wcurr = 0;
+
+ finish:
+	/* If by some quirk IBF has cleared and our ISR has run to 
+	   see that that has happened, do it all again. */
+	if (!hp_sdc.ibf && limit++ < 20) goto anew;
+
+ done:
+	if (hp_sdc.wcurr >= 0) tasklet_schedule(&hp_sdc.task);
+	write_unlock(&hp_sdc.lock);
+	return 0;
+}
+
+/******* Functions called in either user or kernel context ****/
+int hp_sdc_enqueue_transaction(hp_sdc_transaction *this) {
+	unsigned long flags;
+	int i;
+
+	if (this == NULL) {
+		tasklet_schedule(&hp_sdc.task);
+		return -EINVAL;
+	};
+
+	write_lock_irqsave(&hp_sdc.lock, flags);
+
+	/* Can't have same transaction on queue twice */
+	for (i=0; i < HP_SDC_QUEUE_LEN; i++)
+		if (hp_sdc.tq[i] == this) goto fail;
+
+	this->actidx = 0;
+	this->idx = 1;
+
+	/* Search for empty slot */
+	for (i=0; i < HP_SDC_QUEUE_LEN; i++) {
+		if (hp_sdc.tq[i] == NULL) {
+			hp_sdc.tq[i] = this;
+			write_unlock_irqrestore(&hp_sdc.lock, flags);
+			tasklet_schedule(&hp_sdc.task);
+			return 0;
+		}
+	}
+	write_unlock_irqrestore(&hp_sdc.lock, flags);
+	printk(KERN_WARNING PREFIX "No free slot to add transaction.\n");
+	return -EBUSY;
+
+ fail:
+	write_unlock_irqrestore(&hp_sdc.lock,flags);
+	printk(KERN_WARNING PREFIX "Transaction add failed: transaction already queued?\n");
+	return -EINVAL;
+}
+
+int hp_sdc_dequeue_transaction(hp_sdc_transaction *this) {
+	unsigned long flags;
+	int i;
+
+	write_lock_irqsave(&hp_sdc.lock, flags);
+
+	/* TODO: don't remove it if it's not done. */
+
+	for (i=0; i < HP_SDC_QUEUE_LEN; i++)
+		if (hp_sdc.tq[i] == this) hp_sdc.tq[i] = NULL;
+
+	write_unlock_irqrestore(&hp_sdc.lock, flags);
+	return 0;
+}
+
+
+
+/********************** User context functions **************************/
+int hp_sdc_request_timer_irq(hp_sdc_irqhook *callback) {
+
+	if (callback == NULL || hp_sdc.dev == NULL) {
+		return -EINVAL;
+	}
+	write_lock_irq(&hp_sdc.hook_lock);
+	if (hp_sdc.timer != NULL) {
+		write_unlock_irq(&hp_sdc.hook_lock);
+		return -EBUSY;
+	}
+
+	hp_sdc.timer = callback;
+	/* Enable interrupts from the timers */
+	hp_sdc.im &= ~HP_SDC_IM_FH;
+        hp_sdc.im &= ~HP_SDC_IM_PT;
+	hp_sdc.im &= ~HP_SDC_IM_TIMERS;
+	hp_sdc.set_im = 1;
+	write_unlock_irq(&hp_sdc.hook_lock);
+
+	tasklet_schedule(&hp_sdc.task);
+
+	return 0;
+}
+
+int hp_sdc_request_hil_irq(hp_sdc_irqhook *callback) {
+
+	if (callback == NULL || hp_sdc.dev == NULL) {
+		return -EINVAL;
+	}
+	write_lock_irq(&hp_sdc.hook_lock);
+	if (hp_sdc.hil != NULL) {
+		write_unlock_irq(&hp_sdc.hook_lock);
+		return -EBUSY;
+	}
+
+	hp_sdc.hil = callback;
+	hp_sdc.im &= ~(HP_SDC_IM_HIL | HP_SDC_IM_RESET);
+	hp_sdc.set_im = 1;
+	write_unlock_irq(&hp_sdc.hook_lock);
+
+	tasklet_schedule(&hp_sdc.task);
+
+	return 0;
+}
+
+int hp_sdc_request_cooked_irq(hp_sdc_irqhook *callback) {
+
+	if (callback == NULL || hp_sdc.dev == NULL) {
+		return -EINVAL;
+	}
+	write_lock_irq(&hp_sdc.hook_lock);
+	if (hp_sdc.cooked != NULL) {
+		write_unlock_irq(&hp_sdc.hook_lock);
+		return -EBUSY;
+	}
+
+	/* Enable interrupts from the HIL MLC */
+	hp_sdc.cooked = callback;
+	hp_sdc.im &= ~(HP_SDC_IM_HIL | HP_SDC_IM_RESET);
+	hp_sdc.set_im = 1;
+	write_unlock_irq(&hp_sdc.hook_lock);
+
+	tasklet_schedule(&hp_sdc.task);
+
+	return 0;
+}
+
+int hp_sdc_release_timer_irq(hp_sdc_irqhook *callback) {
+
+
+	write_lock_irq(&hp_sdc.hook_lock);
+	if ((callback != hp_sdc.timer) ||
+	    (hp_sdc.timer == NULL)) {
+		write_unlock_irq(&hp_sdc.hook_lock);
+		return -EINVAL;
+	}
+
+	/* Disable interrupts from the timers */
+	hp_sdc.timer = NULL;
+	hp_sdc.im |= HP_SDC_IM_TIMERS;
+	hp_sdc.im |= HP_SDC_IM_FH;
+	hp_sdc.im |= HP_SDC_IM_PT;
+	hp_sdc.set_im = 1;
+	write_unlock_irq(&hp_sdc.hook_lock);
+	tasklet_schedule(&hp_sdc.task);
+
+	return 0;
+}
+
+int hp_sdc_release_hil_irq(hp_sdc_irqhook *callback) {
+
+	write_lock_irq(&hp_sdc.hook_lock);
+	if ((callback != hp_sdc.hil) ||
+	    (hp_sdc.hil == NULL)) {
+		write_unlock_irq(&hp_sdc.hook_lock);
+		return -EINVAL;
+	}
+
+	hp_sdc.hil = NULL;
+	/* Disable interrupts from HIL only if there is no cooked driver. */
+	if(hp_sdc.cooked == NULL) {
+		hp_sdc.im |= (HP_SDC_IM_HIL | HP_SDC_IM_RESET);
+		hp_sdc.set_im = 1;
+	}
+	write_unlock_irq(&hp_sdc.hook_lock);
+	tasklet_schedule(&hp_sdc.task);
+
+	return 0;
+}
+
+int hp_sdc_release_cooked_irq(hp_sdc_irqhook *callback) {
+
+	write_lock_irq(&hp_sdc.hook_lock);
+	if ((callback != hp_sdc.cooked) ||
+	    (hp_sdc.cooked == NULL)) {
+		write_unlock_irq(&hp_sdc.hook_lock);
+		return -EINVAL;
+	}
+
+	hp_sdc.cooked = NULL;
+	/* Disable interrupts from HIL only if there is no raw HIL driver. */
+	if(hp_sdc.hil == NULL) {
+		hp_sdc.im |= (HP_SDC_IM_HIL | HP_SDC_IM_RESET);
+		hp_sdc.set_im = 1;
+	}
+	write_unlock_irq(&hp_sdc.hook_lock);
+	tasklet_schedule(&hp_sdc.task);
+
+	return 0;
+}
+
+/************************* Keepalive timer task *********************/
+
+void hp_sdc_kicker (unsigned long data) {
+	tasklet_schedule(&hp_sdc.task);
+	/* Re-insert the periodic task. */
+	mod_timer(&hp_sdc.kicker, jiffies + HZ);
+}
+
+/************************** Module Initialization ***************************/
+
+#if defined(__hppa__)
+
+static struct parisc_device_id hp_sdc_tbl[] = {
+	{
+		.hw_type =	HPHW_FIO, 
+		.hversion_rev =	HVERSION_REV_ANY_ID,
+		.hversion =	HVERSION_ANY_ID,
+		.sversion =	0x73, 
+	 },
+	{ 0, }
+};
+
+MODULE_DEVICE_TABLE(parisc, hp_sdc_tbl);
+
+static int __init hp_sdc_init_hppa(struct parisc_device *d);
+
+static struct parisc_driver hp_sdc_driver = {
+	.name =		"HP SDC",
+	.id_table =	hp_sdc_tbl,
+	.probe =	hp_sdc_init_hppa,
+};
+
+#endif /* __hppa__ */
+
+static int __init hp_sdc_init(void)
+{
+	int i;
+	char *errstr;
+	hp_sdc_transaction t_sync;
+	uint8_t ts_sync[6];
+	struct semaphore s_sync;
+
+  	hp_sdc.lock		= RW_LOCK_UNLOCKED;
+  	hp_sdc.ibf_lock		= RW_LOCK_UNLOCKED;
+  	hp_sdc.rtq_lock		= RW_LOCK_UNLOCKED;
+  	hp_sdc.hook_lock	= RW_LOCK_UNLOCKED;
+
+	hp_sdc.timer		= NULL;
+	hp_sdc.hil		= NULL;
+	hp_sdc.pup		= NULL;
+	hp_sdc.cooked		= NULL;
+	hp_sdc.im		= HP_SDC_IM_MASK;  /* Mask maskable irqs */
+	hp_sdc.set_im		= 1;
+	hp_sdc.wi		= 0xff;
+	hp_sdc.r7[0]		= 0xff;
+	hp_sdc.r7[1]		= 0xff;
+	hp_sdc.r7[2]		= 0xff;
+	hp_sdc.r7[3]		= 0xff;
+	hp_sdc.ibf		= 1;
+
+	for (i = 0; i < HP_SDC_QUEUE_LEN; i++) hp_sdc.tq[i] = NULL;
+	hp_sdc.wcurr		= -1;
+        hp_sdc.rcurr		= -1;
+	hp_sdc.rqty		= 0;
+
+	hp_sdc.dev_err = -ENODEV;
+
+	errstr = "IO not found for";
+	if (!hp_sdc.base_io) goto err0;
+
+	errstr = "IRQ not found for";
+	if (!hp_sdc.irq) goto err0;
+
+	hp_sdc.dev_err = -EBUSY;
+
+#if defined(__hppa__)
+	errstr = "IO not available for";
+        if (request_region(hp_sdc.data_io, 2, hp_sdc_driver.name)) goto err0;
+#endif	
+
+	errstr = "IRQ not available for";
+        if(request_irq(hp_sdc.irq, &hp_sdc_isr, 0, "HP SDC",
+		       (void *) hp_sdc.base_io)) goto err1;
+
+	errstr = "NMI not available for";
+	if (request_irq(hp_sdc.nmi, &hp_sdc_nmisr, 0, "HP SDC NMI", 
+			(void *) hp_sdc.base_io)) goto err2;
+
+	printk(KERN_INFO PREFIX "HP SDC at 0x%p, IRQ %d (NMI IRQ %d)\n", 
+	       (void *)hp_sdc.base_io, hp_sdc.irq, hp_sdc.nmi);
+
+	hp_sdc_status_in8();
+	hp_sdc_data_in8();
+
+	tasklet_init(&hp_sdc.task, hp_sdc_tasklet, 0);
+
+	/* Sync the output buffer registers, thus scheduling hp_sdc_tasklet. */
+	t_sync.actidx	= 0;
+	t_sync.idx	= 1;
+	t_sync.endidx	= 6;
+	t_sync.seq	= ts_sync;
+	ts_sync[0]	= HP_SDC_ACT_DATAREG | HP_SDC_ACT_SEMAPHORE;
+	ts_sync[1]	= 0x0f;
+	ts_sync[2] = ts_sync[3]	= ts_sync[4] = ts_sync[5] = 0;
+	t_sync.act.semaphore = &s_sync;
+	init_MUTEX_LOCKED(&s_sync);
+	hp_sdc_enqueue_transaction(&t_sync);
+	down(&s_sync); /* Wait for t_sync to complete */
+
+	/* Create the keepalive task */
+	init_timer(&hp_sdc.kicker);
+	hp_sdc.kicker.expires = jiffies + HZ;
+	hp_sdc.kicker.function = &hp_sdc_kicker;
+	add_timer(&hp_sdc.kicker);
+
+	hp_sdc.dev_err = 0;
+	return 0;
+ err2:
+	free_irq(hp_sdc.irq, NULL);
+ err1:
+	release_region(hp_sdc.data_io, 2);
+ err0:
+	printk(KERN_WARNING PREFIX ": %s SDC IO=0x%p IRQ=0x%x NMI=0x%x\n", 
+		errstr, (void *)hp_sdc.base_io, hp_sdc.irq, hp_sdc.nmi);
+	hp_sdc.dev = NULL;
+	return hp_sdc.dev_err;
+}
+
+#if defined(__hppa__)
+
+static int __init hp_sdc_init_hppa(struct parisc_device *d)
+{
+	if (!d) return 1;
+	if (hp_sdc.dev != NULL) return 1;	/* We only expect one SDC */
+
+	hp_sdc.dev		= d;
+	hp_sdc.irq		= d->irq;
+	/* TODO: Is NMI == IRQ - 1 all cases, or is there a way to query? */
+	hp_sdc.nmi		= d->irq - 1;
+	hp_sdc.base_io		= (unsigned long) d->hpa;
+	hp_sdc.data_io		= (unsigned long) d->hpa + 0x800;
+	hp_sdc.status_io	= (unsigned long) d->hpa + 0x801;
+
+	return hp_sdc_init();
+}
+
+#endif /* __hppa__ */
+
+#if !defined(__mc68000__) /* Link error on m68k! */
+static void __exit hp_sdc_exit(void)
+#else
+static void hp_sdc_exit(void)
+#endif
+{
+	write_lock_irq(&hp_sdc.lock);
+
+	/* Turn off all maskable "sub-function" irq's. */
+	hp_sdc_spin_ibf();
+	sdc_writeb(HP_SDC_CMD_SET_IM | HP_SDC_IM_MASK, hp_sdc.status_io);
+
+	/* Wait until we know this has been processed by the i8042 */
+	hp_sdc_spin_ibf();
+
+	free_irq(hp_sdc.nmi, NULL);
+	free_irq(hp_sdc.irq, NULL);
+	write_unlock_irq(&hp_sdc.lock);
+
+	del_timer(&hp_sdc.kicker);
+
+	tasklet_kill(&hp_sdc.task);
+
+/*        release_region(hp_sdc.data_io, 2); */
+
+#if defined(__hppa__)
+	if (unregister_parisc_driver(&hp_sdc_driver)) 
+		printk(KERN_WARNING PREFIX "Error unregistering HP SDC");
+#endif
+}
+
+static int __init hp_sdc_register(void)
+{
+	hp_sdc_transaction tq_init;
+	uint8_t tq_init_seq[5];
+	struct semaphore tq_init_sem;
+#if defined(__mc68000__)
+	mm_segment_t fs;
+	unsigned char i;
+#endif
+	
+	hp_sdc.dev = NULL;
+	hp_sdc.dev_err = 0;
+#if defined(__hppa__)
+	if (register_parisc_driver(&hp_sdc_driver)) {
+		printk(KERN_WARNING PREFIX "Error registering SDC with system bus tree.\n");
+		return -ENODEV;
+	}
+#elif defined(__mc68000__)
+	if (!MACH_IS_HP300)
+	    return -ENODEV;
+
+	hp_sdc.irq	 = 1;
+	hp_sdc.nmi	 = 7;
+	hp_sdc.base_io	 = (unsigned long) 0xf0428000;
+	hp_sdc.data_io	 = (unsigned long) hp_sdc.base_io + 1;
+	hp_sdc.status_io = (unsigned long) hp_sdc.base_io + 3;
+	fs = get_fs();
+	set_fs(KERNEL_DS);
+	if (!get_user(i, (unsigned char *)hp_sdc.data_io))
+		hp_sdc.dev = (void *)1;
+	set_fs(fs);
+	hp_sdc.dev_err   = hp_sdc_init();
+#endif
+	if (hp_sdc.dev == NULL) {
+		printk(KERN_WARNING PREFIX "No SDC found.\n");
+		return hp_sdc.dev_err;
+	}
+
+	init_MUTEX_LOCKED(&tq_init_sem);
+
+	tq_init.actidx		= 0;
+	tq_init.idx		= 1;
+	tq_init.endidx		= 5;
+	tq_init.seq		= tq_init_seq;
+	tq_init.act.semaphore	= &tq_init_sem;
+
+	tq_init_seq[0] = 
+	  HP_SDC_ACT_POSTCMD | HP_SDC_ACT_DATAIN | HP_SDC_ACT_SEMAPHORE;
+	tq_init_seq[1] = HP_SDC_CMD_READ_KCC;
+	tq_init_seq[2] = 1;
+	tq_init_seq[3] = 0;
+	tq_init_seq[4] = 0;
+
+	hp_sdc_enqueue_transaction(&tq_init);
+
+	down(&tq_init_sem);
+	up(&tq_init_sem);
+
+	if ((tq_init_seq[0] & HP_SDC_ACT_DEAD) == HP_SDC_ACT_DEAD) {
+		printk(KERN_WARNING PREFIX "Error reading config byte.\n");
+		hp_sdc_exit();
+		return -ENODEV;
+	}
+	hp_sdc.r11 = tq_init_seq[4];
+	if (hp_sdc.r11 & HP_SDC_CFG_NEW) {
+		char *str;
+		printk(KERN_INFO PREFIX "New style SDC\n");
+		tq_init_seq[1] = HP_SDC_CMD_READ_XTD;
+		tq_init.actidx		= 0;
+		tq_init.idx		= 1;
+		down(&tq_init_sem);
+		hp_sdc_enqueue_transaction(&tq_init);		
+		down(&tq_init_sem);
+		up(&tq_init_sem);
+		if ((tq_init_seq[0] & HP_SDC_ACT_DEAD) == HP_SDC_ACT_DEAD) {
+			printk(KERN_WARNING PREFIX "Error reading extended config byte.\n");
+			return -ENODEV;
+		}
+		hp_sdc.r7e = tq_init_seq[4];
+		HP_SDC_XTD_REV_STRINGS(hp_sdc.r7e & HP_SDC_XTD_REV, str)
+		printk(KERN_INFO PREFIX "Revision: %s\n", str);
+		if (hp_sdc.r7e & HP_SDC_XTD_BEEPER) {
+			printk(KERN_INFO PREFIX "TI SN76494 beeper present\n");
+		}
+		if (hp_sdc.r7e & HP_SDC_XTD_BBRTC) {
+			printk(KERN_INFO PREFIX "OKI MSM-58321 BBRTC present\n");
+		}
+		printk(KERN_INFO PREFIX "Spunking the self test register to force PUP "
+		       "on next firmware reset.\n");
+		tq_init_seq[0] = HP_SDC_ACT_PRECMD | 
+			HP_SDC_ACT_DATAOUT | HP_SDC_ACT_SEMAPHORE;
+		tq_init_seq[1] = HP_SDC_CMD_SET_STR;
+		tq_init_seq[2] = 1;
+		tq_init_seq[3] = 0;
+		tq_init.actidx		= 0;
+		tq_init.idx		= 1;
+		tq_init.endidx		= 4;
+		down(&tq_init_sem);
+		hp_sdc_enqueue_transaction(&tq_init);		
+		down(&tq_init_sem);
+		up(&tq_init_sem);
+	}
+	else {
+		printk(KERN_INFO PREFIX "Old style SDC (1820-%s).\n", 
+		       (hp_sdc.r11 & HP_SDC_CFG_REV) ? "3300" : "2564/3087");
+	}
+
+        return 0;
+}
+
+module_init(hp_sdc_register);
+module_exit(hp_sdc_exit);
+
+/* Timing notes:  These measurements taken on my 64MHz 7100-LC (715/64) 
+ *                                              cycles cycles-adj    time
+ * between two consecutive mfctl(16)'s:              4        n/a    63ns
+ * hp_sdc_spin_ibf when idle:                      119        115   1.7us
+ * gsc_writeb status register:                      83         79   1.2us
+ * IBF to clear after sending SET_IM:             6204       6006    93us
+ * IBF to clear after sending LOAD_RT:            4467       4352    68us  
+ * IBF to clear after sending two LOAD_RTs:      18974      18859   295us
+ * READ_T1, read status/data, IRQ, call handler: 35564        n/a   556us
+ * cmd to ~IBF READ_T1 2nd time right after:   5158403        n/a    81ms
+ * between IRQ received and ~IBF for above:    2578877        n/a    40ms
+ *
+ * Performance stats after a run of this module configuring HIL and
+ * receiving a few mouse events:
+ *
+ * status in8  282508 cycles 7128 calls
+ * status out8   8404 cycles  341 calls
+ * data out8     1734 cycles   78 calls
+ * isr         174324 cycles  617 calls (includes take)
+ * take          1241 cycles    2 calls
+ * put        1411504 cycles 6937 calls
+ * task       1655209 cycles 6937 calls (includes put)
+ *
+ */
diff -Nru a/drivers/input/serio/hp_sdc_mlc.c b/drivers/input/serio/hp_sdc_mlc.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/input/serio/hp_sdc_mlc.c	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,358 @@
+/*
+ * Access to HP-HIL MLC through HP System Device Controller.
+ *
+ * Copyright (c) 2001 Brian S. Julin
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions, and the following disclaimer,
+ *    without modification.
+ * 2. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL").
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ *
+ * References:
+ * HP-HIL Technical Reference Manual.  Hewlett Packard Product No. 45918A
+ * System Device Controller Microprocessor Firmware Theory of Operation
+ *      for Part Number 1820-4784 Revision B.  Dwg No. A-1820-4784-2
+ *
+ */
+
+#include <linux/hil_mlc.h>
+#include <linux/hp_sdc.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/string.h>
+
+#define PREFIX "HP SDC MLC: "
+
+static hil_mlc hp_sdc_mlc;
+
+MODULE_AUTHOR("Brian S. Julin <bri@calyx.com>");
+MODULE_DESCRIPTION("Glue for onboard HIL MLC in HP-PARISC machines");
+MODULE_LICENSE("Dual BSD/GPL");
+
+struct hp_sdc_mlc_priv_s {
+	int emtestmode;
+	hp_sdc_transaction trans;
+	u8 tseq[16];
+	int got5x;
+} hp_sdc_mlc_priv;
+
+/************************* Interrupt context ******************************/
+static void hp_sdc_mlc_isr (int irq, void *dev_id, 
+			    uint8_t status, uint8_t data) {
+  	int idx;
+	hil_mlc *mlc = &hp_sdc_mlc;
+
+	write_lock(&(mlc->lock));
+	if (mlc->icount < 0) {
+		printk(KERN_WARNING PREFIX "HIL Overflow!\n");
+		up(&mlc->isem);
+		goto out;
+	}
+	idx = 15 - mlc->icount;
+	if ((status & HP_SDC_STATUS_IRQMASK) == HP_SDC_STATUS_HILDATA) {
+		mlc->ipacket[idx] |= data | HIL_ERR_INT;
+		mlc->icount--;
+		if (hp_sdc_mlc_priv.got5x) goto check;
+		if (!idx) goto check;
+		if ((mlc->ipacket[idx-1] & HIL_PKT_ADDR_MASK) !=
+		    (mlc->ipacket[idx] & HIL_PKT_ADDR_MASK)) {
+			mlc->ipacket[idx] &= ~HIL_PKT_ADDR_MASK;
+			mlc->ipacket[idx] |= (mlc->ipacket[idx-1] 
+						    & HIL_PKT_ADDR_MASK);
+		}
+		goto check;
+	}
+	/* We know status is 5X */
+	if (data & HP_SDC_HIL_ISERR) goto err;
+	mlc->ipacket[idx] = 
+		(data & HP_SDC_HIL_R1MASK) << HIL_PKT_ADDR_SHIFT;
+	hp_sdc_mlc_priv.got5x = 1;
+	goto out;
+
+ check:
+	hp_sdc_mlc_priv.got5x = 0;
+	if (mlc->imatch == 0) goto done;
+	if ((mlc->imatch == (HIL_ERR_INT | HIL_PKT_CMD | HIL_CMD_POL)) 
+	    && (mlc->ipacket[idx] == (mlc->imatch | idx))) goto done;
+	if (mlc->ipacket[idx] == mlc->imatch) goto done;
+	goto out;
+
+ err:				
+	printk(KERN_DEBUG PREFIX "err code %x\n", data);
+	switch (data) {
+	case HP_SDC_HIL_RC_DONE:
+		printk(KERN_WARNING PREFIX "Bastard SDC reconfigured loop!\n");
+		break;
+	case HP_SDC_HIL_ERR:
+		mlc->ipacket[idx] |= HIL_ERR_INT | HIL_ERR_PERR | 
+		  HIL_ERR_FERR | HIL_ERR_FOF;
+		break;
+	case HP_SDC_HIL_TO:
+		mlc->ipacket[idx] |= HIL_ERR_INT | HIL_ERR_LERR;
+		break;
+	case HP_SDC_HIL_RC:
+		printk(KERN_WARNING PREFIX "Bastard SDC decided to reconfigure loop!\n");
+		break;
+	default:
+		printk(KERN_WARNING PREFIX "Unkown HIL Error status (%x)!\n", data);
+		break;
+	}
+	/* No more data will be coming due to an error. */
+ done:
+	tasklet_schedule(mlc->tasklet);
+	up(&(mlc->isem));
+ out:
+	write_unlock(&(mlc->lock));
+}
+
+
+/******************** Tasklet or userspace context functions ****************/
+
+static int hp_sdc_mlc_in (hil_mlc *mlc, suseconds_t timeout) {
+	unsigned long flags;
+	struct hp_sdc_mlc_priv_s *priv;
+	int rc = 2;
+
+	priv = mlc->priv;
+
+	write_lock_irqsave(&(mlc->lock), flags);
+
+	/* Try to down the semaphore */
+	if (down_trylock(&(mlc->isem))) {
+		struct timeval tv;
+		if (priv->emtestmode) {
+			mlc->ipacket[0] = 
+				HIL_ERR_INT | (mlc->opacket & 
+					       (HIL_PKT_CMD | 
+						HIL_PKT_ADDR_MASK | 
+						HIL_PKT_DATA_MASK));
+			mlc->icount = 14;
+			/* printk(KERN_DEBUG PREFIX ">[%x]\n", mlc->ipacket[0]); */
+			goto wasup;
+		}
+		do_gettimeofday(&tv);
+		tv.tv_usec += 1000000 * (tv.tv_sec - mlc->instart.tv_sec);
+		if (tv.tv_usec - mlc->instart.tv_usec > mlc->intimeout) {
+		  /*		  printk("!%i %i", 
+				  tv.tv_usec - mlc->instart.tv_usec, 
+				  mlc->intimeout);
+		  */
+			rc = 1;
+			up(&(mlc->isem));
+		}
+		goto done;
+	}
+ wasup:
+	up(&(mlc->isem));
+	rc = 0;
+	goto done;
+ done:
+	write_unlock_irqrestore(&(mlc->lock), flags);
+	return rc;
+}
+
+static int hp_sdc_mlc_cts (hil_mlc *mlc) {
+	struct hp_sdc_mlc_priv_s *priv;
+	unsigned long flags;
+
+	priv = mlc->priv;	
+
+	write_lock_irqsave(&(mlc->lock), flags);
+
+	/* Try to down the semaphores -- they should be up. */
+	if (down_trylock(&(mlc->isem))) {
+		BUG();
+		goto busy;
+	}
+	if (down_trylock(&(mlc->osem))) {
+	 	BUG();
+		up(&(mlc->isem));
+		goto busy;
+	}
+	up(&(mlc->isem));
+	up(&(mlc->osem));
+
+	if (down_trylock(&(mlc->csem))) {
+		if (priv->trans.act.semaphore != &(mlc->csem)) goto poll;
+		goto busy;
+	}
+	if (!(priv->tseq[4] & HP_SDC_USE_LOOP)) goto done;
+
+ poll:
+	priv->trans.act.semaphore = &(mlc->csem);
+	priv->trans.actidx = 0;
+	priv->trans.idx = 1;
+	priv->trans.endidx = 5;
+	priv->tseq[0] = 
+		HP_SDC_ACT_POSTCMD | HP_SDC_ACT_DATAIN | HP_SDC_ACT_SEMAPHORE;
+	priv->tseq[1] = HP_SDC_CMD_READ_USE;
+	priv->tseq[2] = 1;
+	priv->tseq[3] = 0;
+	priv->tseq[4] = 0;
+	hp_sdc_enqueue_transaction(&(priv->trans));
+ busy:
+	write_unlock_irqrestore(&(mlc->lock), flags);
+	return 1;
+ done:
+	priv->trans.act.semaphore = &(mlc->osem);
+	up(&(mlc->csem));
+	write_unlock_irqrestore(&(mlc->lock), flags);
+	return 0;
+}
+
+static void hp_sdc_mlc_out (hil_mlc *mlc) {
+	struct hp_sdc_mlc_priv_s *priv;
+	unsigned long flags;
+
+	priv = mlc->priv;
+
+	write_lock_irqsave(&(mlc->lock), flags);
+	
+	/* Try to down the semaphore -- it should be up. */
+	if (down_trylock(&(mlc->osem))) {
+	 	BUG();
+		goto done;
+	}
+
+	if (mlc->opacket & HIL_DO_ALTER_CTRL) goto do_control;
+
+ do_data:
+	if (priv->emtestmode) {
+		up(&(mlc->osem));
+		goto done;
+	}
+	/* Shouldn't be sending commands when loop may be busy */
+	if (down_trylock(&(mlc->csem))) {
+	 	BUG();
+		goto done;
+	}
+	up(&(mlc->csem));
+
+	priv->trans.actidx = 0;
+	priv->trans.idx = 1;
+	priv->trans.act.semaphore = &(mlc->osem);
+	priv->trans.endidx = 6;
+	priv->tseq[0] = 
+		HP_SDC_ACT_DATAREG | HP_SDC_ACT_POSTCMD | HP_SDC_ACT_SEMAPHORE;
+	priv->tseq[1] = 0x7;
+	priv->tseq[2] = 
+		(mlc->opacket & 
+		 (HIL_PKT_ADDR_MASK | HIL_PKT_CMD))
+		   >> HIL_PKT_ADDR_SHIFT;
+	priv->tseq[3] = 
+		(mlc->opacket & HIL_PKT_DATA_MASK) 
+		  >> HIL_PKT_DATA_SHIFT;
+	priv->tseq[4] = 0;  /* No timeout */
+	if (priv->tseq[3] == HIL_CMD_DHR) priv->tseq[4] = 1;
+	priv->tseq[5] = HP_SDC_CMD_DO_HIL;
+	goto enqueue;
+
+ do_control:
+	priv->emtestmode = mlc->opacket & HIL_CTRL_TEST;
+	if ((mlc->opacket & (HIL_CTRL_APE | HIL_CTRL_IPF)) == HIL_CTRL_APE) {
+		BUG(); /* we cannot emulate this, it should not be used. */
+	}
+	if ((mlc->opacket & HIL_CTRL_ONLY) == HIL_CTRL_ONLY) goto control_only;
+	if (mlc->opacket & HIL_CTRL_APE) { 
+		BUG(); /* Should not send command/data after engaging APE */
+		goto done;
+	}
+	/* Disengaging APE this way would not be valid either since 
+	 * the loop must be allowed to idle.
+	 *
+	 * So, it works out that we really never actually send control 
+	 * and data when using SDC, we just send the data. 
+	 */
+	goto do_data;
+
+ control_only:
+	priv->trans.actidx = 0;
+	priv->trans.idx = 1;
+	priv->trans.act.semaphore = &(mlc->osem);
+	priv->trans.endidx = 4;
+	priv->tseq[0] = 
+	  HP_SDC_ACT_PRECMD | HP_SDC_ACT_DATAOUT | HP_SDC_ACT_SEMAPHORE;
+	priv->tseq[1] = HP_SDC_CMD_SET_LPC;
+	priv->tseq[2] = 1;
+	//	priv->tseq[3] = (mlc->ddc + 1) | HP_SDC_LPS_ACSUCC;
+	priv->tseq[3] = 0;
+	if (mlc->opacket & HIL_CTRL_APE) {
+		priv->tseq[3] |= HP_SDC_LPC_APE_IPF;
+		down_trylock(&(mlc->csem));
+	} 
+ enqueue:
+	hp_sdc_enqueue_transaction(&(priv->trans));
+ done:
+	write_unlock_irqrestore(&(mlc->lock), flags);
+}
+
+static int __init hp_sdc_mlc_init(void)
+{
+	hil_mlc *mlc = &hp_sdc_mlc;
+
+	printk(KERN_INFO PREFIX "Registering the System Domain Controller's HIL MLC.\n");
+
+	hp_sdc_mlc_priv.emtestmode = 0;
+	hp_sdc_mlc_priv.trans.seq = hp_sdc_mlc_priv.tseq;
+	hp_sdc_mlc_priv.trans.act.semaphore = &(mlc->osem);
+	hp_sdc_mlc_priv.got5x = 0;
+
+	mlc->cts		= &hp_sdc_mlc_cts;
+	mlc->in			= &hp_sdc_mlc_in;
+	mlc->out		= &hp_sdc_mlc_out;
+
+	if (hil_mlc_register(mlc)) {
+		printk(KERN_WARNING PREFIX "Failed to register MLC structure with hil_mlc\n");
+		goto err0;
+	}
+	mlc->priv		= &hp_sdc_mlc_priv;
+
+	if (hp_sdc_request_hil_irq(&hp_sdc_mlc_isr)) {
+		printk(KERN_WARNING PREFIX "Request for raw HIL ISR hook denied\n");
+		goto err1;
+	}
+	return 0;
+ err1:
+	if (hil_mlc_unregister(mlc)) {
+		printk(KERN_ERR PREFIX "Failed to unregister MLC structure with hil_mlc.\n"
+			"This is bad.  Could cause an oops.\n");
+	}
+ err0:
+	return -EBUSY;
+}
+
+static void __exit hp_sdc_mlc_exit(void)
+{
+	hil_mlc *mlc = &hp_sdc_mlc;
+	if (hp_sdc_release_hil_irq(&hp_sdc_mlc_isr)) {
+		printk(KERN_ERR PREFIX "Failed to release the raw HIL ISR hook.\n"
+			"This is bad.  Could cause an oops.\n");
+	}
+	if (hil_mlc_unregister(mlc)) {
+		printk(KERN_ERR PREFIX "Failed to unregister MLC structure with hil_mlc.\n"
+			"This is bad.  Could cause an oops.\n");
+	}
+}
+
+module_init(hp_sdc_mlc_init);
+module_exit(hp_sdc_mlc_exit);
diff -Nru a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h
--- a/drivers/input/serio/i8042-x86ia64io.h	2005-03-11 12:51:48 -08:00
+++ b/drivers/input/serio/i8042-x86ia64io.h	2005-03-11 12:51:48 -08:00
@@ -67,7 +67,7 @@
 
 #include <linux/dmi.h>
 
-static struct dmi_system_id __initdata i8042_dmi_table[] = {
+static struct dmi_system_id __initdata i8042_dmi_noloop_table[] = {
 	{
 		.ident = "Compaq Proliant 8500",
 		.matches = {
@@ -86,186 +86,208 @@
 	},
 	{ }
 };
+
+/*
+ * Some Fujitsu notebooks are ahving trouble with touhcpads if
+ * active multiplexing mode is activated. Luckily they don't have
+ * external PS/2 ports so we can safely disable it.
+ */
+static struct dmi_system_id __initdata i8042_dmi_nomux_table[] = {
+	{
+		.ident = "Fujitsu Lifebook P7010/P7010D",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "P7010"),
+		},
+	},
+	{
+		.ident = "Fujitsu Lifebook P5020D",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook P Series"),
+		},
+	},
+	{
+		.ident = "Fujitsu Lifebook S2000",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook S Series"),
+		},
+	},
+	{
+		.ident = "Fujitsu T70H",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
+			DMI_MATCH(DMI_PRODUCT_NAME, "FMVLT70H"),
+		},
+	},
+	{ }
+};
+
+
+
 #endif
 
-#ifdef CONFIG_ACPI
-#include <linux/acpi.h>
-#include <acpi/acpi_bus.h>
-
-struct i8042_acpi_resources {
-	unsigned int port1;
-	unsigned int port2;
-	unsigned int irq;
-};
-
-static int i8042_acpi_kbd_registered;
-static int i8042_acpi_aux_registered;
-
-static acpi_status i8042_acpi_parse_resource(struct acpi_resource *res, void *data)
-{
-	struct i8042_acpi_resources *i8042_res = data;
-	struct acpi_resource_io *io;
-	struct acpi_resource_fixed_io *fixed_io;
-	struct acpi_resource_irq *irq;
-	struct acpi_resource_ext_irq *ext_irq;
-
-	switch (res->id) {
-		case ACPI_RSTYPE_IO:
-			io = &res->data.io;
-			if (io->range_length) {
-				if (!i8042_res->port1)
-					i8042_res->port1 = io->min_base_address;
-				else
-					i8042_res->port2 = io->min_base_address;
-			}
-			break;
-
-		case ACPI_RSTYPE_FIXED_IO:
-			fixed_io = &res->data.fixed_io;
-			if (fixed_io->range_length) {
-				if (!i8042_res->port1)
-					i8042_res->port1 = fixed_io->base_address;
-				else
-					i8042_res->port2 = fixed_io->base_address;
-			}
-			break;
-
-		case ACPI_RSTYPE_IRQ:
-			irq = &res->data.irq;
-			if (irq->number_of_interrupts > 0)
-				i8042_res->irq =
-					acpi_register_gsi(irq->interrupts[0],
-							  irq->edge_level,
-							  irq->active_high_low);
-			break;
-
-		case ACPI_RSTYPE_EXT_IRQ:
-			ext_irq = &res->data.extended_irq;
-			if (ext_irq->number_of_interrupts > 0)
-				i8042_res->irq =
-					acpi_register_gsi(ext_irq->interrupts[0],
-							  ext_irq->edge_level,
-							  ext_irq->active_high_low);
-			break;
-	}
-	return AE_OK;
-}
 
-static int i8042_acpi_kbd_add(struct acpi_device *device)
+#ifdef CONFIG_PNP
+#include <linux/pnp.h>
+
+static int i8042_pnp_kbd_registered;
+static int i8042_pnp_aux_registered;
+
+static int i8042_pnp_command_reg;
+static int i8042_pnp_data_reg;
+static int i8042_pnp_kbd_irq;
+static int i8042_pnp_aux_irq;
+
+static char i8042_pnp_kbd_name[32];
+static char i8042_pnp_aux_name[32];
+
+static int i8042_pnp_kbd_probe(struct pnp_dev *dev, const struct pnp_device_id *did)
 {
-	struct i8042_acpi_resources kbd_res;
-	acpi_status status;
+	if (pnp_port_valid(dev, 0) && pnp_port_len(dev, 0) == 1)
+		i8042_pnp_data_reg = pnp_port_start(dev,0);
 
-	memset(&kbd_res, 0, sizeof(kbd_res));
-	status = acpi_walk_resources(device->handle, METHOD_NAME__CRS,
-				     i8042_acpi_parse_resource, &kbd_res);
-	if (ACPI_FAILURE(status))
-		return -ENODEV;
+	if (pnp_port_valid(dev, 1) && pnp_port_len(dev, 1) == 1)
+		i8042_pnp_command_reg = pnp_port_start(dev, 1);
+
+	if (pnp_irq_valid(dev,0))
+		i8042_pnp_kbd_irq = pnp_irq(dev, 0);
 
-	if (kbd_res.port1)
-		i8042_data_reg = kbd_res.port1;
-	else
-		printk(KERN_WARNING "ACPI: [%s] has no data port; default is 0x%x\n",
-			acpi_device_bid(device), i8042_data_reg);
-
-	if (kbd_res.port2)
-		i8042_command_reg = kbd_res.port2;
-	else
-		printk(KERN_WARNING "ACPI: [%s] has no command port; default is 0x%x\n",
-			acpi_device_bid(device), i8042_command_reg);
-
-	if (kbd_res.irq)
-		i8042_kbd_irq = kbd_res.irq;
-	else
-		printk(KERN_WARNING "ACPI: [%s] has no IRQ; default is %d\n",
-			acpi_device_bid(device), i8042_kbd_irq);
-
-	strncpy(acpi_device_name(device), "PS/2 Keyboard Controller",
-		sizeof(acpi_device_name(device)));
-	printk("ACPI: %s [%s] at I/O 0x%x, 0x%x, irq %d\n",
-		acpi_device_name(device), acpi_device_bid(device),
-		i8042_data_reg, i8042_command_reg, i8042_kbd_irq);
+	strncpy(i8042_pnp_kbd_name, did->id, sizeof(i8042_pnp_kbd_name));
+	if (strlen(pnp_dev_name(dev))) {
+		strncat(i8042_pnp_kbd_name, ":", sizeof(i8042_pnp_kbd_name));
+		strncat(i8042_pnp_kbd_name, pnp_dev_name(dev), sizeof(i8042_pnp_kbd_name));
+	}
 
 	return 0;
 }
 
-static int i8042_acpi_aux_add(struct acpi_device *device)
+static int i8042_pnp_aux_probe(struct pnp_dev *dev, const struct pnp_device_id *did)
 {
-	struct i8042_acpi_resources aux_res;
-	acpi_status status;
+	if (pnp_port_valid(dev, 0) && pnp_port_len(dev, 0) == 1)
+		i8042_pnp_data_reg = pnp_port_start(dev,0);
 
-	memset(&aux_res, 0, sizeof(aux_res));
-	status = acpi_walk_resources(device->handle, METHOD_NAME__CRS,
-				     i8042_acpi_parse_resource, &aux_res);
-	if (ACPI_FAILURE(status))
-		return -ENODEV;
+	if (pnp_port_valid(dev, 1) && pnp_port_len(dev, 1) == 1)
+		i8042_pnp_command_reg = pnp_port_start(dev, 1);
 
-	if (aux_res.irq)
-		i8042_aux_irq = aux_res.irq;
-	else
-		printk(KERN_WARNING "ACPI: [%s] has no IRQ; default is %d\n",
-			acpi_device_bid(device), i8042_aux_irq);
-
-	strncpy(acpi_device_name(device), "PS/2 Mouse Controller",
-		sizeof(acpi_device_name(device)));
-	printk("ACPI: %s [%s] at irq %d\n",
-		acpi_device_name(device), acpi_device_bid(device), i8042_aux_irq);
+	if (pnp_irq_valid(dev, 0))
+		i8042_pnp_aux_irq = pnp_irq(dev, 0);
+
+	strncpy(i8042_pnp_aux_name, did->id, sizeof(i8042_pnp_aux_name));
+	if (strlen(pnp_dev_name(dev))) {
+		strncat(i8042_pnp_aux_name, ":", sizeof(i8042_pnp_aux_name));
+		strncat(i8042_pnp_aux_name, pnp_dev_name(dev), sizeof(i8042_pnp_aux_name));
+	}
 
 	return 0;
 }
 
-static struct acpi_driver i8042_acpi_kbd_driver = {
-	.name		= "i8042",
-	.ids		= "PNP0303,PNP030B",
-	.ops		= {
-		.add		= i8042_acpi_kbd_add,
-	},
+static struct pnp_device_id pnp_kbd_devids[] = {
+	{ .id = "PNP0303", .driver_data = 0 },
+	{ .id = "PNP030b", .driver_data = 0 },
+	{ .id = "", },
 };
 
-static struct acpi_driver i8042_acpi_aux_driver = {
-	.name		= "i8042",
-	.ids		= "PNP0F03,PNP0F0B,PNP0F0E,PNP0F12,PNP0F13,SYN0801",
-	.ops		= {
-		.add		= i8042_acpi_aux_add,
-	},
+static struct pnp_driver i8042_pnp_kbd_driver = {
+	.name           = "i8042 kbd",
+	.id_table       = pnp_kbd_devids,
+	.probe          = i8042_pnp_kbd_probe,
+};
+
+static struct pnp_device_id pnp_aux_devids[] = {
+	{ .id = "PNP0f03", .driver_data = 0 },
+	{ .id = "PNP0f0b", .driver_data = 0 },
+	{ .id = "PNP0f0e", .driver_data = 0 },
+	{ .id = "PNP0f12", .driver_data = 0 },
+	{ .id = "PNP0f13", .driver_data = 0 },
+	{ .id = "PNP0f19", .driver_data = 0 },
+	{ .id = "PNP0f1c", .driver_data = 0 },
+	{ .id = "SYN0801", .driver_data = 0 },
+	{ .id = "", },
 };
 
-static int i8042_acpi_init(void)
+static struct pnp_driver i8042_pnp_aux_driver = {
+	.name           = "i8042 aux",
+	.id_table       = pnp_aux_devids,
+	.probe          = i8042_pnp_aux_probe,
+};
+
+static void i8042_pnp_exit(void)
+{
+	if (i8042_pnp_kbd_registered)
+		pnp_unregister_driver(&i8042_pnp_kbd_driver);
+
+	if (i8042_pnp_aux_registered)
+		pnp_unregister_driver(&i8042_pnp_aux_driver);
+}
+
+static int i8042_pnp_init(void)
 {
-	int result;
+	int result_kbd, result_aux;
 
-	if (acpi_disabled || i8042_noacpi) {
-		printk("i8042: ACPI detection disabled\n");
+	if (i8042_nopnp) {
+		printk("i8042: PNP detection disabled\n");
 		return 0;
 	}
 
-	result = acpi_bus_register_driver(&i8042_acpi_kbd_driver);
-	if (result < 0)
-		return result;
+	if ((result_kbd = pnp_register_driver(&i8042_pnp_kbd_driver)) >= 0)
+		i8042_pnp_kbd_registered = 1;
+	if ((result_aux = pnp_register_driver(&i8042_pnp_aux_driver)) >= 0)
+		i8042_pnp_aux_registered = 1;
 
-	if (result == 0) {
-		acpi_bus_unregister_driver(&i8042_acpi_kbd_driver);
+	if (result_kbd <= 0 && result_aux <= 0) {
+		i8042_pnp_exit();
+#if defined(__ia64__)
 		return -ENODEV;
+#else
+		printk(KERN_WARNING "PNP: No PS/2 controller found. Probing ports directly.\n");
+		return 0;
+#endif
+	}
+
+	if (((i8042_pnp_data_reg & ~0xf) == (i8042_data_reg & ~0xf) &&
+	      i8042_pnp_data_reg != i8042_data_reg) || !i8042_pnp_data_reg) {
+		printk(KERN_WARNING "PNP: PS/2 controller has invalid data port %#x; using default %#x\n",
+			i8042_pnp_data_reg, i8042_data_reg);
+		i8042_pnp_data_reg = i8042_data_reg;
+	}
+
+	if (((i8042_pnp_command_reg & ~0xf) == (i8042_command_reg & ~0xf) &&
+	      i8042_pnp_command_reg != i8042_command_reg) || !i8042_pnp_command_reg) {
+		printk(KERN_WARNING "PNP: PS/2 controller has invalid command port %#x; using default %#x\n",
+			i8042_pnp_command_reg, i8042_command_reg);
+		i8042_pnp_command_reg = i8042_command_reg;
+	}
+
+	if (!i8042_pnp_kbd_irq) {
+		printk(KERN_WARNING "PNP: PS/2 controller doesn't have KBD irq; using default %#x\n", i8042_kbd_irq);
+		i8042_pnp_kbd_irq = i8042_kbd_irq;
+	}
+
+	if (result_aux > 0 && !i8042_pnp_aux_irq) {
+		printk(KERN_WARNING "PNP: PS/2 controller doesn't have AUX irq; using default %#x\n", i8042_aux_irq);
+		i8042_pnp_aux_irq = i8042_aux_irq;
 	}
-	i8042_acpi_kbd_registered = 1;
 
-	result = acpi_bus_register_driver(&i8042_acpi_aux_driver);
-	if (result >= 0)
-		i8042_acpi_aux_registered = 1;
-	if (result == 0)
+#if defined(__ia64__)
+	if (result_aux <= 0)
 		i8042_noaux = 1;
+#endif
+
+	i8042_data_reg = i8042_pnp_data_reg;
+	i8042_command_reg = i8042_pnp_command_reg;
+	i8042_kbd_irq = i8042_pnp_kbd_irq;
+	i8042_aux_irq = i8042_pnp_aux_irq;
+
+	printk(KERN_INFO "PNP: PS/2 Controller [%s%s%s] at %#x,%#x irq %d%s%d\n",
+		i8042_pnp_kbd_name, (result_kbd > 0 && result_aux > 0) ? "," : "", i8042_pnp_aux_name,
+		i8042_data_reg, i8042_command_reg, i8042_kbd_irq,
+		(result_aux > 0) ? "," : "", i8042_aux_irq);
 
 	return 0;
 }
 
-static void i8042_acpi_exit(void)
-{
-	if (i8042_acpi_kbd_registered)
-		acpi_bus_unregister_driver(&i8042_acpi_kbd_driver);
-
-	if (i8042_acpi_aux_registered)
-		acpi_bus_unregister_driver(&i8042_acpi_aux_driver);
-}
 #endif
 
 static inline int i8042_platform_init(void)
@@ -281,8 +303,8 @@
 	i8042_kbd_irq = I8042_MAP_IRQ(1);
 	i8042_aux_irq = I8042_MAP_IRQ(12);
 
-#ifdef CONFIG_ACPI
-	if (i8042_acpi_init())
+#ifdef CONFIG_PNP
+	if (i8042_pnp_init())
 		return -1;
 #endif
 
@@ -291,8 +313,11 @@
 #endif
 
 #if defined(__i386__)
-	if (dmi_check_system(i8042_dmi_table))
+	if (dmi_check_system(i8042_dmi_noloop_table))
 		i8042_noloop = 1;
+
+	if (dmi_check_system(i8042_dmi_nomux_table))
+		i8042_nomux = 1;
 #endif
 
 	return 0;
@@ -300,8 +325,8 @@
 
 static inline void i8042_platform_exit(void)
 {
-#ifdef CONFIG_ACPI
-	i8042_acpi_exit();
+#ifdef CONFIG_PNP
+	i8042_pnp_exit();
 #endif
 }
 
diff -Nru a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c
--- a/drivers/input/serio/i8042.c	2005-03-11 12:51:41 -08:00
+++ b/drivers/input/serio/i8042.c	2005-03-11 12:51:41 -08:00
@@ -19,6 +19,7 @@
 #include <linux/init.h>
 #include <linux/serio.h>
 #include <linux/err.h>
+#include <linux/rcupdate.h>
 
 #include <asm/io.h>
 
@@ -52,12 +53,16 @@
 
 static unsigned int i8042_noloop;
 module_param_named(noloop, i8042_noloop, bool, 0);
-MODULE_PARM_DESC(dumbkbd, "Disable the AUX Loopback command while probing for the AUX port");
+MODULE_PARM_DESC(noloop, "Disable the AUX Loopback command while probing for the AUX port");
 
-#ifdef CONFIG_ACPI
-static int i8042_noacpi;
-module_param_named(noacpi, i8042_noacpi, bool, 0);
-MODULE_PARM_DESC(noacpi, "Do not use ACPI to detect controller settings");
+static unsigned int i8042_blink_frequency = 500;
+module_param_named(panicblink, i8042_blink_frequency, uint, 0600);
+MODULE_PARM_DESC(panicblink, "Frequency with which keyboard LEDs should blink when kernel panics");
+
+#ifdef CONFIG_PNP
+static int i8042_nopnp;
+module_param_named(nopnp, i8042_nopnp, bool, 0);
+MODULE_PARM_DESC(nopnp, "Do not use PNP to detect controller settings");
 #endif
 
 #define DEBUG
@@ -76,9 +81,10 @@
 
 #include "i8042.h"
 
-DEFINE_SPINLOCK(i8042_lock);
+static DEFINE_SPINLOCK(i8042_lock);
 
-struct i8042_values {
+struct i8042_port {
+	struct serio *serio;
 	int irq;
 	unsigned char disable;
 	unsigned char irqen;
@@ -87,25 +93,25 @@
 	char name[8];
 };
 
-static struct i8042_values i8042_kbd_values = {
-	.disable	= I8042_CTR_KBDDIS,
-	.irqen 		= I8042_CTR_KBDINT,
-	.mux		= -1,
-	.name		= "KBD",
-};
-
-static struct i8042_values i8042_aux_values = {
-	.disable	= I8042_CTR_AUXDIS,
-	.irqen		= I8042_CTR_AUXINT,
-	.mux		= -1,
-	.name		= "AUX",
+#define I8042_KBD_PORT_NO	0
+#define I8042_AUX_PORT_NO	1
+#define I8042_MUX_PORT_NO	2
+#define I8042_NUM_PORTS		(I8042_NUM_MUX_PORTS + 2)
+static struct i8042_port i8042_ports[I8042_NUM_PORTS] = {
+	{
+		.disable	= I8042_CTR_KBDDIS,
+		.irqen 		= I8042_CTR_KBDINT,
+		.mux		= -1,
+		.name		= "KBD",
+	},
+	{
+		.disable	= I8042_CTR_AUXDIS,
+		.irqen		= I8042_CTR_AUXINT,
+		.mux		= -1,
+		.name		= "AUX",
+	}
 };
 
-static struct i8042_values i8042_mux_values[I8042_NUM_MUX_PORTS];
-
-static struct serio *i8042_kbd_port;
-static struct serio *i8042_aux_port;
-static struct serio *i8042_mux_port[I8042_NUM_MUX_PORTS];
 static unsigned char i8042_initial_ctr;
 static unsigned char i8042_ctr;
 static unsigned char i8042_mux_open;
@@ -113,6 +119,7 @@
 static struct timer_list i8042_timer;
 static struct platform_device *i8042_platform_device;
 
+
 /*
  * Shared IRQ's require a device pointer, but this driver doesn't support
  * multiple devices
@@ -155,16 +162,17 @@
 static int i8042_flush(void)
 {
 	unsigned long flags;
-	unsigned char data;
+	unsigned char data, str;
 	int i = 0;
 
 	spin_lock_irqsave(&i8042_lock, flags);
 
-	while ((i8042_read_status() & I8042_STR_OBF) && (i++ < I8042_BUFFER_SIZE)) {
+	while (((str = i8042_read_status()) & I8042_STR_OBF) && (i < I8042_BUFFER_SIZE)) {
 		udelay(50);
 		data = i8042_read_data();
+		i++;
 		dbg("%02x <- i8042 (flush, %s)", data,
-			i8042_read_status() & I8042_STR_AUXDATA ? "aux" : "kbd");
+			str & I8042_STR_AUXDATA ? "aux" : "kbd");
 	}
 
 	spin_unlock_irqrestore(&i8042_lock, flags);
@@ -246,19 +254,19 @@
  * i8042_aux_write() sends a byte out through the aux interface.
  */
 
-static int i8042_aux_write(struct serio *port, unsigned char c)
+static int i8042_aux_write(struct serio *serio, unsigned char c)
 {
-	struct i8042_values *values = port->port_data;
+	struct i8042_port *port = serio->port_data;
 	int retval;
 
 /*
  * Send the byte out.
  */
 
-	if (values->mux == -1)
+	if (port->mux == -1)
 		retval = i8042_command(&c, I8042_CMD_AUX_SEND);
 	else
-		retval = i8042_command(&c, I8042_CMD_MUX_SEND + values->mux);
+		retval = i8042_command(&c, I8042_CMD_MUX_SEND + port->mux);
 
 /*
  * Make sure the interrupt happens and the character is received even
@@ -274,9 +282,10 @@
  * i8042_activate_port() enables port on a chip.
  */
 
-static int i8042_activate_port(struct serio *port)
+static int i8042_activate_port(struct i8042_port *port)
 {
-	struct i8042_values *values = port->port_data;
+	if (!port->serio)
+		return -1;
 
 	i8042_flush();
 
@@ -284,12 +293,12 @@
 	 * Enable port again here because it is disabled if we are
 	 * resuming (normally it is enabled already).
 	 */
-	i8042_ctr &= ~values->disable;
+	i8042_ctr &= ~port->disable;
 
-	i8042_ctr |= values->irqen;
+	i8042_ctr |= port->irqen;
 
 	if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) {
-		i8042_ctr &= ~values->irqen;
+		i8042_ctr &= ~port->irqen;
 		return -1;
 	}
 
@@ -302,22 +311,22 @@
  * It allocates the interrupt and calls i8042_enable_port.
  */
 
-static int i8042_open(struct serio *port)
+static int i8042_open(struct serio *serio)
 {
-	struct i8042_values *values = port->port_data;
+	struct i8042_port *port = serio->port_data;
 
-	if (values->mux != -1)
+	if (port->mux != -1)
 		if (i8042_mux_open++)
 			return 0;
 
-	if (request_irq(values->irq, i8042_interrupt,
+	if (request_irq(port->irq, i8042_interrupt,
 			SA_SHIRQ, "i8042", i8042_request_irq_cookie)) {
-		printk(KERN_ERR "i8042.c: Can't get irq %d for %s, unregistering the port.\n", values->irq, values->name);
+		printk(KERN_ERR "i8042.c: Can't get irq %d for %s, unregistering the port.\n", port->irq, port->name);
 		goto irq_fail;
 	}
 
 	if (i8042_activate_port(port)) {
-		printk(KERN_ERR "i8042.c: Can't activate %s, unregistering the port\n", values->name);
+		printk(KERN_ERR "i8042.c: Can't activate %s, unregistering the port\n", port->name);
 		goto activate_fail;
 	}
 
@@ -326,11 +335,10 @@
 	return 0;
 
 activate_fail:
-	free_irq(values->irq, i8042_request_irq_cookie);
+	free_irq(port->irq, i8042_request_irq_cookie);
 
 irq_fail:
-	values->exists = 0;
-	serio_unregister_port_delayed(port);
+	serio_unregister_port_delayed(serio);
 
 	return -1;
 }
@@ -341,27 +349,58 @@
  * the BIOS could have used the AUX interrupt for PCI.
  */
 
-static void i8042_close(struct serio *port)
+static void i8042_close(struct serio *serio)
 {
-	struct i8042_values *values = port->port_data;
+	struct i8042_port *port = serio->port_data;
 
-	if (values->mux != -1)
+	if (port->mux != -1)
 		if (--i8042_mux_open)
 			return;
 
-	i8042_ctr &= ~values->irqen;
+	i8042_ctr &= ~port->irqen;
 
 	if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) {
-		printk(KERN_ERR "i8042.c: Can't write CTR while closing %s.\n", values->name);
-		return;
+		printk(KERN_WARNING "i8042.c: Can't write CTR while closing %s.\n", port->name);
+/*
+ * We still want to continue and free IRQ so if more data keeps coming in
+ * kernel will just ignore the irq.
+ */
 	}
 
-	free_irq(values->irq, i8042_request_irq_cookie);
+	free_irq(port->irq, i8042_request_irq_cookie);
 
 	i8042_flush();
 }
 
 /*
+ * i8042_start() is called by serio core when port is about to finish
+ * registering. It will mark port as existing so i8042_interrupt can
+ * start sending data through it.
+ */
+static int i8042_start(struct serio *serio)
+{
+	struct i8042_port *port = serio->port_data;
+
+	port->exists = 1;
+	mb();
+	return 0;
+}
+
+/*
+ * i8042_stop() marks serio port as non-existing so i8042_interrupt
+ * will not try to send data to the port that is about to go away.
+ * The function is called by serio core as part of unregister procedure.
+ */
+static void i8042_stop(struct serio *serio)
+{
+	struct i8042_port *port = serio->port_data;
+
+	port->exists = 0;
+	synchronize_kernel();
+	port->serio = NULL;
+}
+
+/*
  * i8042_interrupt() is the most important function in this driver -
  * it handles the interrupts from the i8042, and sends incoming bytes
  * to the upper layers.
@@ -369,25 +408,25 @@
 
 static irqreturn_t i8042_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
+	struct i8042_port *port;
 	unsigned long flags;
-	unsigned char str, data = 0;
+	unsigned char str, data;
 	unsigned int dfl;
-	unsigned int aux_idx;
+	unsigned int port_no;
 	int ret;
 
 	mod_timer(&i8042_timer, jiffies + I8042_POLL_PERIOD);
 
 	spin_lock_irqsave(&i8042_lock, flags);
 	str = i8042_read_status();
-	if (str & I8042_STR_OBF)
-		data = i8042_read_data();
-	spin_unlock_irqrestore(&i8042_lock, flags);
-
-	if (~str & I8042_STR_OBF) {
+	if (unlikely(~str & I8042_STR_OBF)) {
+		spin_unlock_irqrestore(&i8042_lock, flags);
 		if (irq) dbg("Interrupt %d, without any data", irq);
 		ret = 0;
 		goto out;
 	}
+	data = i8042_read_data();
+	spin_unlock_irqrestore(&i8042_lock, flags);
 
 	if (i8042_mux_present && (str & I8042_STR_AUXDATA)) {
 		static unsigned long last_transmit;
@@ -419,39 +458,28 @@
 			}
 		}
 
-		aux_idx = (str >> 6) & 3;
-
-		dbg("%02x <- i8042 (interrupt, aux%d, %d%s%s)",
-			data, aux_idx, irq,
-			dfl & SERIO_PARITY ? ", bad parity" : "",
-			dfl & SERIO_TIMEOUT ? ", timeout" : "");
-
-		if (likely(i8042_mux_values[aux_idx].exists))
-			serio_interrupt(i8042_mux_port[aux_idx], data, dfl, regs);
-
+		port_no = I8042_MUX_PORT_NO + ((str >> 6) & 3);
 		last_str = str;
 		last_transmit = jiffies;
-		goto irq_ret;
+	} else {
+
+		dfl = ((str & I8042_STR_PARITY) ? SERIO_PARITY : 0) |
+		      ((str & I8042_STR_TIMEOUT) ? SERIO_TIMEOUT : 0);
+
+		port_no = (str & I8042_STR_AUXDATA) ?
+				I8042_AUX_PORT_NO : I8042_KBD_PORT_NO;
 	}
 
-	dfl = ((str & I8042_STR_PARITY) ? SERIO_PARITY : 0) |
-	      ((str & I8042_STR_TIMEOUT) ? SERIO_TIMEOUT : 0);
+	port = &i8042_ports[port_no];
 
 	dbg("%02x <- i8042 (interrupt, %s, %d%s%s)",
-		data, (str & I8042_STR_AUXDATA) ? "aux" : "kbd", irq,
-		dfl & SERIO_PARITY ? ", bad parity" : "",
-		dfl & SERIO_TIMEOUT ? ", timeout" : "");
+	    data, port->name, irq,
+	    dfl & SERIO_PARITY ? ", bad parity" : "",
+	    dfl & SERIO_TIMEOUT ? ", timeout" : "");
 
+	if (likely(port->exists))
+		serio_interrupt(port->serio, data, dfl, regs);
 
-	if (str & I8042_STR_AUXDATA) {
-		if (likely(i8042_aux_values.exists))
-			serio_interrupt(i8042_aux_port, data, dfl, regs);
-	} else {
-		if (likely(i8042_kbd_values.exists))
-			serio_interrupt(i8042_kbd_port, data, dfl, regs);
-	}
-
-irq_ret:
 	ret = 1;
 out:
 	return IRQ_RETVAL(ret);
@@ -500,7 +528,7 @@
  * the controller has been switched into Multiplexed mode
  */
 
-static int i8042_enable_mux_ports(struct i8042_values *values)
+static int i8042_enable_mux_ports(void)
 {
 	unsigned char param;
 	int i;
@@ -535,7 +563,7 @@
  * LCS/Telegraphics.
  */
 
-static int __init i8042_check_mux(struct i8042_values *values)
+static int __init i8042_check_mux(void)
 {
 	unsigned char mux_version;
 
@@ -550,7 +578,7 @@
 	printk(KERN_INFO "i8042.c: Detected active multiplexing controller, rev %d.%d.\n",
 		(mux_version >> 4) & 0xf, mux_version & 0xf);
 
-	if (i8042_enable_mux_ports(values))
+	if (i8042_enable_mux_ports())
 		return -1;
 
 	i8042_mux_present = 1;
@@ -563,7 +591,7 @@
  * the presence of an AUX interface.
  */
 
-static int __init i8042_check_aux(struct i8042_values *values)
+static int __init i8042_check_aux(void)
 {
 	unsigned char param;
 	static int i8042_check_aux_cookie;
@@ -573,10 +601,10 @@
  * in trying to detect AUX presence.
  */
 
-	if (request_irq(values->irq, i8042_interrupt, SA_SHIRQ,
-				"i8042", &i8042_check_aux_cookie))
+	if (request_irq(i8042_ports[I8042_AUX_PORT_NO].irq, i8042_interrupt,
+			SA_SHIRQ, "i8042", &i8042_check_aux_cookie))
                 return -1;
-	free_irq(values->irq, &i8042_check_aux_cookie);
+	free_irq(i8042_ports[I8042_AUX_PORT_NO].irq, &i8042_check_aux_cookie);
 
 /*
  * Get rid of bytes in the queue.
@@ -641,27 +669,25 @@
  * registers it, and reports to the user.
  */
 
-static int __init i8042_port_register(struct serio *port)
+static int __init i8042_port_register(struct i8042_port *port)
 {
-	struct i8042_values *values = port->port_data;
-
-	values->exists = 1;
-
-	i8042_ctr &= ~values->disable;
+	i8042_ctr &= ~port->disable;
 
 	if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR)) {
 		printk(KERN_WARNING "i8042.c: Can't write CTR while registering.\n");
-		values->exists = 0;
+		kfree(port->serio);
+		port->serio = NULL;
+		i8042_ctr |= port->disable;
 		return -1;
 	}
 
 	printk(KERN_INFO "serio: i8042 %s port at %#lx,%#lx irq %d\n",
-	       values->name,
+	       port->name,
 	       (unsigned long) I8042_DATA_REG,
 	       (unsigned long) I8042_COMMAND_REG,
-	       values->irq);
+	       port->irq);
 
-	serio_register_port(port);
+	serio_register_port(port->serio);
 
 	return 0;
 }
@@ -688,7 +714,10 @@
  * before doing anything else.
  */
 
-	i8042_flush();
+	if (i8042_flush() == I8042_BUFFER_SIZE) {
+		printk(KERN_ERR "i8042.c: No controller found.\n");
+		return -1;
+	}
 
 	if (i8042_reset) {
 
@@ -771,7 +800,7 @@
 /*
  * Reset the controller.
  */
-void i8042_controller_reset(void)
+static void i8042_controller_reset(void)
 {
 	unsigned char param;
 
@@ -806,7 +835,7 @@
  * able to talk to the hardware when rebooting.
  */
 
-void i8042_controller_cleanup(void)
+static void i8042_controller_cleanup(void)
 {
 	int i;
 
@@ -816,39 +845,41 @@
  * Reset anything that is connected to the ports.
  */
 
-	if (i8042_kbd_values.exists)
-		serio_cleanup(i8042_kbd_port);
-
-	if (i8042_aux_values.exists)
-		serio_cleanup(i8042_aux_port);
-
-	for (i = 0; i < I8042_NUM_MUX_PORTS; i++)
-		if (i8042_mux_values[i].exists)
-			serio_cleanup(i8042_mux_port[i]);
+	for (i = 0; i < I8042_NUM_PORTS; i++)
+		if (i8042_ports[i].exists)
+			serio_cleanup(i8042_ports[i].serio);
 
 	i8042_controller_reset();
 }
 
 
-static int blink_frequency = 500;
-module_param_named(panicblink, blink_frequency, int, 0600);
+/*
+ * i8042_panic_blink() will flash the keyboard LEDs and is called when
+ * kernel panics. Flashing LEDs is useful for users running X who may
+ * not see the console and will help distingushing panics from "real"
+ * lockups.
+ *
+ * Note that DELAY has a limit of 10ms so we will not get stuck here
+ * waiting for KBC to free up even if KBD interrupt is off
+ */
 
-/* Catch the case when the kbd interrupt is off */
 #define DELAY do { mdelay(1); if (++delay > 10) return delay; } while(0)
 
-/* Tell the user who may be running in X and not see the console that we have
-   panic'ed. This is to distingush panics from "real" lockups.  */
 static long i8042_panic_blink(long count)
 {
 	long delay = 0;
 	static long last_blink;
 	static char led;
-	/* Roughly 1/2s frequency. KDB uses about 1s. Make sure it is
-	   different. */
-	if (!blink_frequency)
+
+	/*
+	 * We expect frequency to be about 1/2s. KDB uses about 1s.
+	 * Make sure they are different.
+	 */
+	if (!i8042_blink_frequency)
 		return 0;
-	if (count - last_blink < blink_frequency)
+	if (count - last_blink < i8042_blink_frequency)
 		return 0;
+
 	led ^= 0x01 | 0x04;
 	while (i8042_read_status() & I8042_STR_IBF)
 		DELAY;
@@ -869,7 +900,7 @@
  * Here we try to restore the original BIOS settings
  */
 
-static int i8042_suspend(struct device *dev, u32 state, u32 level)
+static int i8042_suspend(struct device *dev, pm_message_t state, u32 level)
 {
 	if (level == SUSPEND_DISABLE) {
 		del_timer_sync(&i8042_timer);
@@ -897,24 +928,16 @@
 	}
 
 	if (i8042_mux_present)
-		if (i8042_set_mux_mode(1, NULL) ||
-		    i8042_enable_mux_ports(&i8042_aux_values)) {
+		if (i8042_set_mux_mode(1, NULL) || i8042_enable_mux_ports())
 			printk(KERN_WARNING "i8042: failed to resume active multiplexor, mouse won't work.\n");
-		}
 
 /*
- * Reconnect anything that was connected to the ports.
+ * Activate all ports.
  */
 
-	if (i8042_kbd_values.exists && i8042_activate_port(i8042_kbd_port) == 0)
-		serio_reconnect(i8042_kbd_port);
-
-	if (i8042_aux_values.exists && i8042_activate_port(i8042_aux_port) == 0)
-		serio_reconnect(i8042_aux_port);
+	for (i = 0; i < I8042_NUM_PORTS; i++)
+		i8042_activate_port(&i8042_ports[i]);
 
-	for (i = 0; i < I8042_NUM_MUX_PORTS; i++)
-		if (i8042_mux_values[i].exists && i8042_activate_port(i8042_mux_port[i]) == 0)
-			serio_reconnect(i8042_mux_port[i]);
 /*
  * Restart timer (for polling "stuck" data)
  */
@@ -944,72 +967,83 @@
 	.shutdown	= i8042_shutdown,
 };
 
-static struct serio * __init i8042_allocate_kbd_port(void)
+static void __init i8042_create_kbd_port(void)
 {
 	struct serio *serio;
+	struct i8042_port *port = &i8042_ports[I8042_KBD_PORT_NO];
 
 	serio = kmalloc(sizeof(struct serio), GFP_KERNEL);
 	if (serio) {
 		memset(serio, 0, sizeof(struct serio));
-		serio->type		= i8042_direct ? SERIO_8042 : SERIO_8042_XL,
-		serio->write		= i8042_dumbkbd ? NULL : i8042_kbd_write,
-		serio->open		= i8042_open,
-		serio->close		= i8042_close,
-		serio->port_data	= &i8042_kbd_values,
+		serio->id.type		= i8042_direct ? SERIO_8042 : SERIO_8042_XL;
+		serio->write		= i8042_dumbkbd ? NULL : i8042_kbd_write;
+		serio->open		= i8042_open;
+		serio->close		= i8042_close;
+		serio->start		= i8042_start;
+		serio->stop		= i8042_stop;
+		serio->port_data	= port;
 		serio->dev.parent	= &i8042_platform_device->dev;
 		strlcpy(serio->name, "i8042 Kbd Port", sizeof(serio->name));
 		strlcpy(serio->phys, I8042_KBD_PHYS_DESC, sizeof(serio->phys));
-	}
 
-	return serio;
+		port->serio = serio;
+		i8042_port_register(port);
+	}
 }
 
-static struct serio * __init i8042_allocate_aux_port(void)
+static void __init i8042_create_aux_port(void)
 {
 	struct serio *serio;
+	struct i8042_port *port = &i8042_ports[I8042_AUX_PORT_NO];
 
 	serio = kmalloc(sizeof(struct serio), GFP_KERNEL);
 	if (serio) {
 		memset(serio, 0, sizeof(struct serio));
-		serio->type		= SERIO_8042;
+		serio->id.type		= SERIO_8042;
 		serio->write		= i8042_aux_write;
 		serio->open		= i8042_open;
 		serio->close		= i8042_close;
-		serio->port_data	= &i8042_aux_values,
+		serio->start		= i8042_start;
+		serio->stop		= i8042_stop;
+		serio->port_data	= port;
 		serio->dev.parent	= &i8042_platform_device->dev;
 		strlcpy(serio->name, "i8042 Aux Port", sizeof(serio->name));
 		strlcpy(serio->phys, I8042_AUX_PHYS_DESC, sizeof(serio->phys));
-	}
 
-	return serio;
+		port->serio = serio;
+		i8042_port_register(port);
+	}
 }
 
-static struct serio * __init i8042_allocate_mux_port(int index)
+static void __init i8042_create_mux_port(int index)
 {
 	struct serio *serio;
-	struct i8042_values *values = &i8042_mux_values[index];
+	struct i8042_port *port = &i8042_ports[I8042_MUX_PORT_NO + index];
 
 	serio = kmalloc(sizeof(struct serio), GFP_KERNEL);
 	if (serio) {
-		*values = i8042_aux_values;
-		snprintf(values->name, sizeof(values->name), "AUX%d", index);
-		values->mux = index;
-
 		memset(serio, 0, sizeof(struct serio));
-		serio->type		= SERIO_8042;
+		serio->id.type		= SERIO_8042;
 		serio->write		= i8042_aux_write;
 		serio->open		= i8042_open;
 		serio->close		= i8042_close;
-		serio->port_data	= values;
+		serio->start		= i8042_start;
+		serio->stop		= i8042_stop;
+		serio->port_data	= port;
 		serio->dev.parent	= &i8042_platform_device->dev;
 		snprintf(serio->name, sizeof(serio->name), "i8042 Aux-%d Port", index);
 		snprintf(serio->phys, sizeof(serio->phys), I8042_MUX_PHYS_DESC, index + 1);
-	}
 
-	return serio;
+		*port = i8042_ports[I8042_AUX_PORT_NO];
+		port->exists = 0;
+		snprintf(port->name, sizeof(port->name), "AUX%d", index);
+		port->mux = index;
+		port->serio = serio;
+		i8042_port_register(port);
+	}
 }
 
-int __init i8042_init(void)
+static int __init i8042_init(void)
 {
 	int i;
 	int err;
@@ -1022,60 +1056,51 @@
 	if (i8042_platform_init())
 		return -EBUSY;
 
-	i8042_aux_values.irq = I8042_AUX_IRQ;
-	i8042_kbd_values.irq = I8042_KBD_IRQ;
+	i8042_ports[I8042_AUX_PORT_NO].irq = I8042_AUX_IRQ;
+	i8042_ports[I8042_KBD_PORT_NO].irq = I8042_KBD_IRQ;
 
-	if (i8042_controller_init())
+	if (i8042_controller_init()) {
+		i8042_platform_exit();
 		return -ENODEV;
+	}
 
 	err = driver_register(&i8042_driver);
-	if (err)
+	if (err) {
+		i8042_platform_exit();
 		return err;
+	}
 
 	i8042_platform_device = platform_device_register_simple("i8042", -1, NULL, 0);
 	if (IS_ERR(i8042_platform_device)) {
 		driver_unregister(&i8042_driver);
+		i8042_platform_exit();
 		return PTR_ERR(i8042_platform_device);
 	}
 
-	if (!i8042_noaux && !i8042_check_aux(&i8042_aux_values)) {
-		if (!i8042_nomux && !i8042_check_mux(&i8042_aux_values))
-			for (i = 0; i < I8042_NUM_MUX_PORTS; i++) {
-				i8042_mux_port[i] = i8042_allocate_mux_port(i);
-				if (i8042_mux_port[i])
-					i8042_port_register(i8042_mux_port[i]);
-			}
-		else {
-			i8042_aux_port = i8042_allocate_aux_port();
-			if (i8042_aux_port)
-				i8042_port_register(i8042_aux_port);
-		}
+	if (!i8042_noaux && !i8042_check_aux()) {
+		if (!i8042_nomux && !i8042_check_mux())
+			for (i = 0; i < I8042_NUM_MUX_PORTS; i++)
+				i8042_create_mux_port(i);
+		else
+			i8042_create_aux_port();
 	}
 
-	i8042_kbd_port = i8042_allocate_kbd_port();
-	if (i8042_kbd_port)
-		i8042_port_register(i8042_kbd_port);
+	i8042_create_kbd_port();
 
 	mod_timer(&i8042_timer, jiffies + I8042_POLL_PERIOD);
 
 	return 0;
 }
 
-void __exit i8042_exit(void)
+static void __exit i8042_exit(void)
 {
 	int i;
 
 	i8042_controller_cleanup();
 
-	if (i8042_kbd_values.exists)
-		serio_unregister_port(i8042_kbd_port);
-
-	if (i8042_aux_values.exists)
-		serio_unregister_port(i8042_aux_port);
-
-	for (i = 0; i < I8042_NUM_MUX_PORTS; i++)
-		if (i8042_mux_values[i].exists)
-			serio_unregister_port(i8042_mux_port[i]);
+	for (i = 0; i < I8042_NUM_PORTS; i++)
+		if (i8042_ports[i].exists)
+			serio_unregister_port(i8042_ports[i].serio);
 
 	del_timer_sync(&i8042_timer);
 
diff -Nru a/drivers/input/serio/i8042.h b/drivers/input/serio/i8042.h
--- a/drivers/input/serio/i8042.h	2005-03-11 12:51:50 -08:00
+++ b/drivers/input/serio/i8042.h	2005-03-11 12:51:50 -08:00
@@ -100,10 +100,10 @@
 
 /*
  * Expected maximum internal i8042 buffer size. This is used for flushing
- * the i8042 buffers. 32 should be more than enough.
+ * the i8042 buffers.
  */
 
-#define I8042_BUFFER_SIZE	32
+#define I8042_BUFFER_SIZE	16
 
 /*
  * Number of AUX ports on controllers supporting active multiplexing
@@ -117,13 +117,13 @@
  */
 
 #ifdef DEBUG
-static unsigned long i8042_start;
-#define dbg_init() do { i8042_start = jiffies; } while (0)
+static unsigned long i8042_start_time;
+#define dbg_init() do { i8042_start_time = jiffies; } while (0)
 #define dbg(format, arg...) 							\
 	do { 									\
 		if (i8042_debug)						\
 			printk(KERN_DEBUG __FILE__ ": " format " [%d]\n" ,	\
-	 			## arg, (int) (jiffies - i8042_start));		\
+	 			## arg, (int) (jiffies - i8042_start_time));	\
 	} while (0)
 #else
 #define dbg_init() do { } while (0)
diff -Nru a/drivers/input/serio/maceps2.c b/drivers/input/serio/maceps2.c
--- a/drivers/input/serio/maceps2.c	2005-03-11 12:51:42 -08:00
+++ b/drivers/input/serio/maceps2.c	2005-03-11 12:51:42 -08:00
@@ -125,7 +125,7 @@
 	serio = kmalloc(sizeof(struct serio), GFP_KERNEL);
 	if (serio) {
 		memset(serio, 0, sizeof(struct serio));
-		serio->type		= SERIO_8042;
+		serio->id.type		= SERIO_8042;
 		serio->write		= maceps2_write;
 		serio->open		= maceps2_open;
 		serio->close		= maceps2_close;
diff -Nru a/drivers/input/serio/parkbd.c b/drivers/input/serio/parkbd.c
--- a/drivers/input/serio/parkbd.c	2005-03-11 12:51:41 -08:00
+++ b/drivers/input/serio/parkbd.c	2005-03-11 12:51:41 -08:00
@@ -1,31 +1,47 @@
 /*
- * $Id: parkbd.c,v 1.10 2002/03/13 10:09:20 vojtech Exp $
+ *  Parallel port to Keyboard port adapter driver for Linux
  *
- *  Copyright (c) 1999-2001 Vojtech Pavlik
+ *  Copyright (c) 1999-2004 Vojtech Pavlik
  */
 
 /*
- *  Parallel port to Keyboard port adapter driver for Linux
+ * 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 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.
+ * To connect an AT or XT keyboard to the parallel port, a fairly simple adapter
+ * can be made:
+ * 
+ *  Parallel port            Keyboard port
  *
- * 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.
+ *     +5V --------------------- +5V (4)
+ *  
+ *                 ______
+ *     +5V -------|______|--.
+ *                          |
+ *     ACK (10) ------------|
+ *                          |--- KBD CLOCK (5)
+ *     STROBE (1) ---|<|----'
+ *     
+ *                 ______
+ *     +5V -------|______|--.
+ *                          |
+ *     BUSY (11) -----------|
+ *                          |--- KBD DATA (1)
+ *     AUTOFD (14) --|<|----'
  *
- * 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
+ *     GND (18-25) ------------- GND (3)
+ *     
+ * The diodes can be fairly any type, and the resistors should be somewhere
+ * around 5 kOhm, but the adapter will likely work without the resistors,
+ * too.
  *
- * Should you need to contact me, the author, you can do so either by
- * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail:
- * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
+ * The +5V source can be taken either from USB, from mouse or keyboard ports,
+ * or from a joystick port. Unfortunately, the parallel port of a PC doesn't
+ * have a +5V pin, and feeding the keyboard from signal pins is out of question
+ * with 300 mA power reqirement of a typical AT keyboard.
  */
 
 #include <linux/module.h>
@@ -158,7 +174,7 @@
 	serio = kmalloc(sizeof(struct serio), GFP_KERNEL);
 	if (serio) {
 		memset(serio, 0, sizeof(struct serio));
-		serio->type = parkbd_mode;
+		serio->id.type = parkbd_mode;
 		serio->write = parkbd_write,
 		strlcpy(serio->name, "PARKBD AT/XT keyboard adapter", sizeof(serio->name));
 		snprintf(serio->phys, sizeof(serio->phys), "%s/serio0", parkbd_dev->port->name);
@@ -167,7 +183,7 @@
 	return serio;
 }
 
-int __init parkbd_init(void)
+static int __init parkbd_init(void)
 {
 	int err;
 
@@ -191,7 +207,7 @@
 	return 0;
 }
 
-void __exit parkbd_exit(void)
+static void __exit parkbd_exit(void)
 {
 	parport_release(parkbd_dev);
 	serio_unregister_port(parkbd_port);
diff -Nru a/drivers/input/serio/pcips2.c b/drivers/input/serio/pcips2.c
--- a/drivers/input/serio/pcips2.c	2005-03-11 12:51:41 -08:00
+++ b/drivers/input/serio/pcips2.c	2005-03-11 12:51:41 -08:00
@@ -150,7 +150,7 @@
 	memset(ps2if, 0, sizeof(struct pcips2_data));
 	memset(serio, 0, sizeof(struct serio));
 
-	serio->type		= SERIO_8042;
+	serio->id.type		= SERIO_8042;
 	serio->write		= pcips2_write;
 	serio->open		= pcips2_open;
 	serio->close		= pcips2_close;
@@ -217,7 +217,7 @@
 
 static int __init pcips2_init(void)
 {
-	return pci_module_init(&pcips2_driver);
+	return pci_register_driver(&pcips2_driver);
 }
 
 static void __exit pcips2_exit(void)
diff -Nru a/drivers/input/serio/q40kbd.c b/drivers/input/serio/q40kbd.c
--- a/drivers/input/serio/q40kbd.c	2005-03-11 12:51:42 -08:00
+++ b/drivers/input/serio/q40kbd.c	2005-03-11 12:51:42 -08:00
@@ -122,7 +122,7 @@
 	serio = kmalloc(sizeof(struct serio), GFP_KERNEL);
 	if (serio) {
 		memset(serio, 0, sizeof(struct serio));
-		serio->type		= SERIO_8042;
+		serio->id.type		= SERIO_8042;
 		serio->open		= q40kbd_open;
 		serio->close		= q40kbd_close;
 		serio->dev.parent	= &q40kbd_device->dev;
diff -Nru a/drivers/input/serio/rpckbd.c b/drivers/input/serio/rpckbd.c
--- a/drivers/input/serio/rpckbd.c	2005-03-11 12:51:41 -08:00
+++ b/drivers/input/serio/rpckbd.c	2005-03-11 12:51:41 -08:00
@@ -115,7 +115,7 @@
 		return -ENOMEM;
 
 	memset(serio, 0, sizeof(struct serio));
-	serio->type		= SERIO_8042;
+	serio->id.type		= SERIO_8042;
 	serio->write		= rpckbd_write;
 	serio->open		= rpckbd_open;
 	serio->close		= rpckbd_close;
diff -Nru a/drivers/input/serio/sa1111ps2.c b/drivers/input/serio/sa1111ps2.c
--- a/drivers/input/serio/sa1111ps2.c	2005-03-11 12:51:52 -08:00
+++ b/drivers/input/serio/sa1111ps2.c	2005-03-11 12:51:52 -08:00
@@ -245,7 +245,7 @@
 	memset(ps2if, 0, sizeof(struct ps2if));
 	memset(serio, 0, sizeof(struct serio));
 
-	serio->type		= SERIO_8042;
+	serio->id.type		= SERIO_8042;
 	serio->write		= ps2_write;
 	serio->open		= ps2_open;
 	serio->close		= ps2_close;
diff -Nru a/drivers/input/serio/serio.c b/drivers/input/serio/serio.c
--- a/drivers/input/serio/serio.c	2005-03-11 12:51:41 -08:00
+++ b/drivers/input/serio/serio.c	2005-03-11 12:51:41 -08:00
@@ -41,76 +41,98 @@
 MODULE_LICENSE("GPL");
 
 EXPORT_SYMBOL(serio_interrupt);
-EXPORT_SYMBOL(serio_register_port);
-EXPORT_SYMBOL(serio_register_port_delayed);
+EXPORT_SYMBOL(__serio_register_port);
 EXPORT_SYMBOL(serio_unregister_port);
-EXPORT_SYMBOL(serio_unregister_port_delayed);
-EXPORT_SYMBOL(serio_register_driver);
+EXPORT_SYMBOL(__serio_unregister_port_delayed);
+EXPORT_SYMBOL(__serio_register_driver);
 EXPORT_SYMBOL(serio_unregister_driver);
 EXPORT_SYMBOL(serio_open);
 EXPORT_SYMBOL(serio_close);
 EXPORT_SYMBOL(serio_rescan);
 EXPORT_SYMBOL(serio_reconnect);
 
-static DECLARE_MUTEX(serio_sem);	/* protects serio_list and serio_diriver_list */
+/*
+ * serio_sem protects entire serio subsystem and is taken every time
+ * serio port or driver registrered or unregistered.
+ */
+static DECLARE_MUTEX(serio_sem);
+
 static LIST_HEAD(serio_list);
-static LIST_HEAD(serio_driver_list);
-static unsigned int serio_no;
 
-struct bus_type serio_bus = {
+static struct bus_type serio_bus = {
 	.name =	"serio",
 };
 
-static void serio_find_driver(struct serio *serio);
-static void serio_create_port(struct serio *serio);
+static void serio_add_port(struct serio *serio);
 static void serio_destroy_port(struct serio *serio);
-static void serio_connect_port(struct serio *serio, struct serio_driver *drv);
 static void serio_reconnect_port(struct serio *serio);
 static void serio_disconnect_port(struct serio *serio);
 
-static int serio_bind_driver(struct serio *serio, struct serio_driver *drv)
+static int serio_match_port(const struct serio_device_id *ids, struct serio *serio)
 {
-	get_driver(&drv->driver);
+	while (ids->type || ids->proto) {
+		if ((ids->type == SERIO_ANY || ids->type == serio->id.type) &&
+		    (ids->proto == SERIO_ANY || ids->proto == serio->id.proto) &&
+		    (ids->extra == SERIO_ANY || ids->extra == serio->id.extra) &&
+		    (ids->id == SERIO_ANY || ids->id == serio->id.id))
+			return 1;
+		ids++;
+	}
+	return 0;
+}
 
-	drv->connect(serio, drv);
-	if (serio->drv) {
-		down_write(&serio_bus.subsys.rwsem);
+/*
+ * Basic serio -> driver core mappings
+ */
+
+static void serio_bind_driver(struct serio *serio, struct serio_driver *drv)
+{
+	down_write(&serio_bus.subsys.rwsem);
+
+	if (serio_match_port(drv->id_table, serio)) {
 		serio->dev.driver = &drv->driver;
+		if (drv->connect(serio, drv)) {
+			serio->dev.driver = NULL;
+			goto out;
+		}
 		device_bind_driver(&serio->dev);
-		up_write(&serio_bus.subsys.rwsem);
-		return 1;
 	}
+out:
+	up_write(&serio_bus.subsys.rwsem);
+}
 
-	put_driver(&drv->driver);
-	return 0;
+static void serio_release_driver(struct serio *serio)
+{
+	down_write(&serio_bus.subsys.rwsem);
+	device_release_driver(&serio->dev);
+	up_write(&serio_bus.subsys.rwsem);
 }
 
-/* serio_find_driver() must be called with serio_sem down.  */
 static void serio_find_driver(struct serio *serio)
 {
-	struct serio_driver *drv;
-
-	list_for_each_entry(drv, &serio_driver_list, node)
-		if (!drv->manual_bind)
-			if (serio_bind_driver(serio, drv))
-				break;
+	down_write(&serio_bus.subsys.rwsem);
+	device_attach(&serio->dev);
+	up_write(&serio_bus.subsys.rwsem);
 }
 
+
 /*
  * Serio event processing.
  */
 
-struct serio_event {
-	int type;
-	struct serio *serio;
-	struct list_head node;
-};
-
 enum serio_event_type {
 	SERIO_RESCAN,
 	SERIO_RECONNECT,
 	SERIO_REGISTER_PORT,
 	SERIO_UNREGISTER_PORT,
+	SERIO_REGISTER_DRIVER,
+};
+
+struct serio_event {
+	enum serio_event_type type;
+	void *object;
+	struct module *owner;
+	struct list_head node;
 };
 
 static DEFINE_SPINLOCK(serio_event_lock);	/* protects serio_event_list */
@@ -119,24 +141,82 @@
 static DECLARE_COMPLETION(serio_exited);
 static int serio_pid;
 
-static void serio_queue_event(struct serio *serio, int event_type)
+static void serio_queue_event(void *object, struct module *owner,
+			      enum serio_event_type event_type)
 {
 	unsigned long flags;
 	struct serio_event *event;
 
 	spin_lock_irqsave(&serio_event_lock, flags);
 
+	/*
+ 	 * Scan event list for the other events for the same serio port,
+	 * starting with the most recent one. If event is the same we
+	 * do not need add new one. If event is of different type we
+	 * need to add this event and should not look further because
+	 * we need to preseve sequence of distinct events.
+ 	 */
+	list_for_each_entry_reverse(event, &serio_event_list, node) {
+		if (event->object == object) {
+			if (event->type == event_type)
+				goto out;
+			break;
+		}
+	}
+
 	if ((event = kmalloc(sizeof(struct serio_event), GFP_ATOMIC))) {
+		if (!try_module_get(owner)) {
+			printk(KERN_WARNING "serio: Can't get module reference, dropping event %d\n", event_type);
+			goto out;
+		}
+
 		event->type = event_type;
-		event->serio = serio;
+		event->object = object;
+		event->owner = owner;
 
 		list_add_tail(&event->node, &serio_event_list);
 		wake_up(&serio_wait);
+	} else {
+		printk(KERN_ERR "serio: Not enough memory to queue event %d\n", event_type);
+	}
+out:
+	spin_unlock_irqrestore(&serio_event_lock, flags);
+}
+
+static void serio_free_event(struct serio_event *event)
+{
+	module_put(event->owner);
+	kfree(event);
+}
+
+static void serio_remove_duplicate_events(struct serio_event *event)
+{
+	struct list_head *node, *next;
+	struct serio_event *e;
+	unsigned long flags;
+
+	spin_lock_irqsave(&serio_event_lock, flags);
+
+	list_for_each_safe(node, next, &serio_event_list) {
+		e = list_entry(node, struct serio_event, node);
+		if (event->object == e->object) {
+			/*
+			 * If this event is of different type we should not
+			 * look further - we only suppress duplicate events
+			 * that were sent back-to-back.
+			 */
+			if (event->type != e->type)
+				break;
+
+			list_del_init(node);
+			serio_free_event(e);
+		}
 	}
 
 	spin_unlock_irqrestore(&serio_event_lock, flags);
 }
 
+
 static struct serio_event *serio_get_event(void)
 {
 	struct serio_event *event;
@@ -151,7 +231,7 @@
 	}
 
 	node = serio_event_list.next;
-	event = container_of(node, struct serio_event, node);
+	event = list_entry(node, struct serio_event, node);
 	list_del_init(node);
 
 	spin_unlock_irqrestore(&serio_event_lock, flags);
@@ -162,39 +242,50 @@
 static void serio_handle_events(void)
 {
 	struct serio_event *event;
+	struct serio_driver *serio_drv;
 
-	while ((event = serio_get_event())) {
+	down(&serio_sem);
 
-		down(&serio_sem);
+	while ((event = serio_get_event())) {
 
 		switch (event->type) {
-			case SERIO_REGISTER_PORT :
-				serio_create_port(event->serio);
-				serio_connect_port(event->serio, NULL);
+			case SERIO_REGISTER_PORT:
+				serio_add_port(event->object);
 				break;
 
-			case SERIO_UNREGISTER_PORT :
-				serio_disconnect_port(event->serio);
-				serio_destroy_port(event->serio);
+			case SERIO_UNREGISTER_PORT:
+				serio_disconnect_port(event->object);
+				serio_destroy_port(event->object);
 				break;
 
-			case SERIO_RECONNECT :
-				serio_reconnect_port(event->serio);
+			case SERIO_RECONNECT:
+				serio_reconnect_port(event->object);
 				break;
 
-			case SERIO_RESCAN :
-				serio_disconnect_port(event->serio);
-				serio_connect_port(event->serio, NULL);
+			case SERIO_RESCAN:
+				serio_disconnect_port(event->object);
+				serio_find_driver(event->object);
 				break;
+
+			case SERIO_REGISTER_DRIVER:
+				serio_drv = event->object;
+				driver_register(&serio_drv->driver);
+				break;
+
 			default:
 				break;
 		}
 
-		up(&serio_sem);
-		kfree(event);
+		serio_remove_duplicate_events(event);
+		serio_free_event(event);
 	}
+
+	up(&serio_sem);
 }
 
+/*
+ * Remove all events that have been submitted for a given serio port.
+ */
 static void serio_remove_pending_events(struct serio *serio)
 {
 	struct list_head *node, *next;
@@ -204,16 +295,45 @@
 	spin_lock_irqsave(&serio_event_lock, flags);
 
 	list_for_each_safe(node, next, &serio_event_list) {
-		event = container_of(node, struct serio_event, node);
-		if (event->serio == serio) {
+		event = list_entry(node, struct serio_event, node);
+		if (event->object == serio) {
 			list_del_init(node);
-			kfree(event);
+			serio_free_event(event);
 		}
 	}
 
 	spin_unlock_irqrestore(&serio_event_lock, flags);
 }
 
+/*
+ * Destroy child serio port (if any) that has not been fully registered yet.
+ *
+ * Note that we rely on the fact that port can have only one child and therefore
+ * only one child registration request can be pending. Additionally, children
+ * are registered by driver's connect() handler so there can't be a grandchild
+ * pending registration together with a child.
+ */
+static struct serio *serio_get_pending_child(struct serio *parent)
+{
+	struct serio_event *event;
+	struct serio *serio, *child = NULL;
+	unsigned long flags;
+
+	spin_lock_irqsave(&serio_event_lock, flags);
+
+	list_for_each_entry(event, &serio_event_list, node) {
+		if (event->type == SERIO_REGISTER_PORT) {
+			serio = event->object;
+			if (serio->parent == parent) {
+				child = serio;
+				break;
+			}
+		}
+	}
+
+	spin_unlock_irqrestore(&serio_event_lock, flags);
+	return child;
+}
 
 static int serio_thread(void *nothing)
 {
@@ -244,6 +364,30 @@
 	return sprintf(buf, "%s\n", serio->name);
 }
 
+static ssize_t serio_show_id_type(struct device *dev, char *buf)
+{
+	struct serio *serio = to_serio_port(dev);
+	return sprintf(buf, "%02x\n", serio->id.type);
+}
+
+static ssize_t serio_show_id_proto(struct device *dev, char *buf)
+{
+	struct serio *serio = to_serio_port(dev);
+	return sprintf(buf, "%02x\n", serio->id.proto);
+}
+
+static ssize_t serio_show_id_id(struct device *dev, char *buf)
+{
+	struct serio *serio = to_serio_port(dev);
+	return sprintf(buf, "%02x\n", serio->id.id);
+}
+
+static ssize_t serio_show_id_extra(struct device *dev, char *buf)
+{
+	struct serio *serio = to_serio_port(dev);
+	return sprintf(buf, "%02x\n", serio->id.extra);
+}
+
 static ssize_t serio_rebind_driver(struct device *dev, const char *buf, size_t count)
 {
 	struct serio *serio = to_serio_port(dev);
@@ -261,10 +405,10 @@
 		serio_reconnect_port(serio);
 	} else if (!strncmp(buf, "rescan", count)) {
 		serio_disconnect_port(serio);
-		serio_connect_port(serio, NULL);
+		serio_find_driver(serio);
 	} else if ((drv = driver_find(buf, &serio_bus)) != NULL) {
 		serio_disconnect_port(serio);
-		serio_connect_port(serio, to_serio_driver(drv));
+		serio_bind_driver(serio, to_serio_driver(drv));
 		put_driver(drv);
 	} else {
 		retval = -EINVAL;
@@ -300,6 +444,10 @@
 
 static struct device_attribute serio_device_attrs[] = {
 	__ATTR(description, S_IRUGO, serio_show_description, NULL),
+	__ATTR(id_type, S_IRUGO, serio_show_id_type, NULL),
+	__ATTR(id_proto, S_IRUGO, serio_show_id_proto, NULL),
+	__ATTR(id_id, S_IRUGO, serio_show_id_id, NULL),
+	__ATTR(id_extra, S_IRUGO, serio_show_id_extra, NULL),
 	__ATTR(drvctl, S_IWUSR, NULL, serio_rebind_driver),
 	__ATTR(bind_mode, S_IWUSR | S_IRUGO, serio_show_bind_mode, serio_set_bind_mode),
 	__ATTR_NULL
@@ -314,95 +462,88 @@
 	module_put(THIS_MODULE);
 }
 
-static void serio_create_port(struct serio *serio)
+/*
+ * Prepare serio port for registration.
+ */
+static void serio_init_port(struct serio *serio)
 {
-	try_module_get(THIS_MODULE);
+	static atomic_t serio_no = ATOMIC_INIT(0);
+
+	__module_get(THIS_MODULE);
 
 	spin_lock_init(&serio->lock);
 	init_MUTEX(&serio->drv_sem);
-	list_add_tail(&serio->node, &serio_list);
-	snprintf(serio->dev.bus_id, sizeof(serio->dev.bus_id), "serio%d", serio_no++);
+	device_initialize(&serio->dev);
+	snprintf(serio->dev.bus_id, sizeof(serio->dev.bus_id),
+		 "serio%ld", (long)atomic_inc_return(&serio_no) - 1);
 	serio->dev.bus = &serio_bus;
 	serio->dev.release = serio_release_port;
 	if (serio->parent)
 		serio->dev.parent = &serio->parent->dev;
-	device_register(&serio->dev);
 }
 
 /*
- * serio_destroy_port() completes deregistration process and removes
- * port from the system
+ * Complete serio port registration.
+ * Driver core will attempt to find appropriate driver for the port.
  */
-static void serio_destroy_port(struct serio *serio)
+static void serio_add_port(struct serio *serio)
 {
-	struct serio_driver *drv = serio->drv;
-	unsigned long flags;
-
-	serio_remove_pending_events(serio);
-	list_del_init(&serio->node);
-
-	if (drv) {
-		drv->disconnect(serio);
-		down_write(&serio_bus.subsys.rwsem);
-		device_release_driver(&serio->dev);
-		up_write(&serio_bus.subsys.rwsem);
-		put_driver(&drv->driver);
-	}
-
 	if (serio->parent) {
-		spin_lock_irqsave(&serio->parent->lock, flags);
-		serio->parent->child = NULL;
-		spin_unlock_irqrestore(&serio->parent->lock, flags);
+		serio_pause_rx(serio->parent);
+		serio->parent->child = serio;
+		serio_continue_rx(serio->parent);
 	}
 
-	device_unregister(&serio->dev);
+	list_add_tail(&serio->node, &serio_list);
+	if (serio->start)
+		serio->start(serio);
+	device_add(&serio->dev);
+	serio->registered = 1;
 }
 
 /*
- * serio_connect_port() tries to bind the port and possible all its
- * children to appropriate drivers. If driver passed in the function will not
- * try otehr drivers when binding parent port.
+ * serio_destroy_port() completes deregistration process and removes
+ * port from the system
  */
-static void serio_connect_port(struct serio *serio, struct serio_driver *drv)
+static void serio_destroy_port(struct serio *serio)
 {
-	WARN_ON(serio->drv);
-	WARN_ON(serio->child);
+	struct serio *child;
 
-	if (drv)
-		serio_bind_driver(serio, drv);
-	else if (!serio->manual_bind)
-		serio_find_driver(serio);
-
-	/* Ok, now bind children, if any */
-	while (serio->child) {
-		serio = serio->child;
+	child = serio_get_pending_child(serio);
+	if (child) {
+		serio_remove_pending_events(child);
+		put_device(&child->dev);
+	}
 
-		WARN_ON(serio->drv);
-		WARN_ON(serio->child);
+	if (serio->stop)
+		serio->stop(serio);
 
-		serio_create_port(serio);
+	if (serio->parent) {
+		serio_pause_rx(serio->parent);
+		serio->parent->child = NULL;
+		serio_continue_rx(serio->parent);
+		serio->parent = NULL;
+	}
 
-		if (!serio->manual_bind) {
-			/*
-			 * With children we just _prefer_ passed in driver,
-			 * but we will try other options in case preferred
-			 * is not the one
-			 */
-			if (!drv || !serio_bind_driver(serio, drv))
-				serio_find_driver(serio);
-		}
+	if (serio->registered) {
+		device_del(&serio->dev);
+		list_del_init(&serio->node);
+		serio->registered = 0;
 	}
+
+	serio_remove_pending_events(serio);
+	put_device(&serio->dev);
 }
 
 /*
- *
+ * Reconnect serio port and all its children (re-initialize attached devices)
  */
 static void serio_reconnect_port(struct serio *serio)
 {
 	do {
 		if (!serio->drv || !serio->drv->reconnect || serio->drv->reconnect(serio)) {
 			serio_disconnect_port(serio);
-			serio_connect_port(serio, NULL);
+			serio_find_driver(serio);
 			/* Ok, old children are now gone, we are done */
 			break;
 		}
@@ -416,8 +557,7 @@
  */
 static void serio_disconnect_port(struct serio *serio)
 {
-	struct serio_driver *drv = serio->drv;
-	struct serio *s;
+	struct serio *s, *parent;
 
 	if (serio->child) {
 		/*
@@ -425,56 +565,46 @@
 		 * first, staring with the leaf one, since we don't want
 		 * to do recursion
 		 */
+		for (s = serio; s->child; s = s->child)
+			/* empty */;
+
 		do {
-			s = serio->child;
-		} while (s->child);
+			parent = s->parent;
 
-		while (s != serio) {
-			s = s->parent;
-			serio_destroy_port(s->child);
-		}
+			serio_release_driver(s);
+			serio_destroy_port(s);
+		} while ((s = parent) != serio);
 	}
 
 	/*
 	 * Ok, no children left, now disconnect this port
 	 */
-	if (drv) {
-		drv->disconnect(serio);
-		down_write(&serio_bus.subsys.rwsem);
-		device_release_driver(&serio->dev);
-		up_write(&serio_bus.subsys.rwsem);
-		put_driver(&drv->driver);
-	}
+	serio_release_driver(serio);
 }
 
 void serio_rescan(struct serio *serio)
 {
-	serio_queue_event(serio, SERIO_RESCAN);
+	serio_queue_event(serio, NULL, SERIO_RESCAN);
 }
 
 void serio_reconnect(struct serio *serio)
 {
-	serio_queue_event(serio, SERIO_RECONNECT);
-}
-
-void serio_register_port(struct serio *serio)
-{
-	down(&serio_sem);
-	serio_create_port(serio);
-	serio_connect_port(serio, NULL);
-	up(&serio_sem);
+	serio_queue_event(serio, NULL, SERIO_RECONNECT);
 }
 
 /*
  * Submits register request to kseriod for subsequent execution.
- * Can be used when it is not obvious whether the serio_sem is
- * taken or not and when delayed execution is feasible.
+ * Note that port registration is always asynchronous.
  */
-void serio_register_port_delayed(struct serio *serio)
+void __serio_register_port(struct serio *serio, struct module *owner)
 {
-	serio_queue_event(serio, SERIO_REGISTER_PORT);
+	serio_init_port(serio);
+	serio_queue_event(serio, owner, SERIO_REGISTER_PORT);
 }
 
+/*
+ * Synchronously unregisters serio port.
+ */
 void serio_unregister_port(struct serio *serio)
 {
 	down(&serio_sem);
@@ -484,13 +614,13 @@
 }
 
 /*
- * Submits unregister request to kseriod for subsequent execution.
+ * Submits register request to kseriod for subsequent execution.
  * Can be used when it is not obvious whether the serio_sem is
  * taken or not and when delayed execution is feasible.
  */
-void serio_unregister_port_delayed(struct serio *serio)
+void __serio_unregister_port_delayed(struct serio *serio, struct module *owner)
 {
-	serio_queue_event(serio, SERIO_UNREGISTER_PORT);
+	serio_queue_event(serio, owner, SERIO_UNREGISTER_PORT);
 }
 
 
@@ -535,35 +665,30 @@
 	__ATTR_NULL
 };
 
-void serio_register_driver(struct serio_driver *drv)
+static int serio_driver_probe(struct device *dev)
 {
-	struct serio *serio;
-
-	down(&serio_sem);
+	struct serio *serio = to_serio_port(dev);
+	struct serio_driver *drv = to_serio_driver(dev->driver);
 
-	list_add_tail(&drv->node, &serio_driver_list);
+	return drv->connect(serio, drv);
+}
 
-	drv->driver.bus = &serio_bus;
-	driver_register(&drv->driver);
+static int serio_driver_remove(struct device *dev)
+{
+	struct serio *serio = to_serio_port(dev);
+	struct serio_driver *drv = to_serio_driver(dev->driver);
 
-	if (drv->manual_bind)
-		goto out;
+	drv->disconnect(serio);
+	return 0;
+}
 
-start_over:
-	list_for_each_entry(serio, &serio_list, node) {
-		if (!serio->drv) {
-			serio_connect_port(serio, drv);
-			/*
-			 * if new child appeared then the list is changed,
-			 * we need to start over
-			 */
-			if (serio->child)
-				goto start_over;
-		}
-	}
+void __serio_register_driver(struct serio_driver *drv, struct module *owner)
+{
+	drv->driver.bus = &serio_bus;
+	drv->driver.probe = serio_driver_probe;
+	drv->driver.remove = serio_driver_remove;
 
-out:
-	up(&serio_sem);
+	serio_queue_event(drv, owner, SERIO_REGISTER_DRIVER);
 }
 
 void serio_unregister_driver(struct serio_driver *drv)
@@ -571,21 +696,19 @@
 	struct serio *serio;
 
 	down(&serio_sem);
-
-	list_del_init(&drv->node);
+	drv->manual_bind = 1;	/* so serio_find_driver ignores it */
 
 start_over:
 	list_for_each_entry(serio, &serio_list, node) {
 		if (serio->drv == drv) {
 			serio_disconnect_port(serio);
-			serio_connect_port(serio, NULL);
+			serio_find_driver(serio);
 			/* we could've deleted some ports, restart */
 			goto start_over;
 		}
 	}
 
 	driver_unregister(&drv->driver);
-
 	up(&serio_sem);
 }
 
@@ -598,6 +721,75 @@
 	up(&serio->drv_sem);
 }
 
+static int serio_bus_match(struct device *dev, struct device_driver *drv)
+{
+	struct serio *serio = to_serio_port(dev);
+	struct serio_driver *serio_drv = to_serio_driver(drv);
+
+	if (serio->manual_bind || serio_drv->manual_bind)
+		return 0;
+
+	return serio_match_port(serio_drv->id_table, serio);
+}
+
+#ifdef CONFIG_HOTPLUG
+
+#define PUT_ENVP(fmt, val) 						\
+do {									\
+	envp[i++] = buffer;						\
+	length += snprintf(buffer, buffer_size - length, fmt, val);	\
+	if (buffer_size - length <= 0 || i >= num_envp)			\
+		return -ENOMEM;						\
+	length++;							\
+	buffer += length;						\
+} while (0)
+static int serio_hotplug(struct device *dev, char **envp, int num_envp, char *buffer, int buffer_size)
+{
+	struct serio *serio;
+	int i = 0;
+	int length = 0;
+
+	if (!dev)
+		return -ENODEV;
+
+	serio = to_serio_port(dev);
+
+	PUT_ENVP("SERIO_TYPE=%02x", serio->id.type);
+	PUT_ENVP("SERIO_PROTO=%02x", serio->id.proto);
+	PUT_ENVP("SERIO_ID=%02x", serio->id.id);
+	PUT_ENVP("SERIO_EXTRA=%02x", serio->id.extra);
+
+	envp[i] = NULL;
+
+	return 0;
+}
+#undef PUT_ENVP
+
+#else
+
+static int serio_hotplug(struct device *dev, char **envp, int num_envp, char *buffer, int buffer_size)
+{
+	return -ENODEV;
+}
+
+#endif /* CONFIG_HOTPLUG */
+
+static int serio_resume(struct device *dev)
+{
+	struct serio *serio = to_serio_port(dev);
+
+	if (!serio->drv || !serio->drv->reconnect || serio->drv->reconnect(serio)) {
+		serio_disconnect_port(serio);
+		/*
+		 * Driver re-probing can take a while, so better let kseriod
+		 * deal with it.
+		 */
+		serio_rescan(serio);
+	}
+
+	return 0;
+}
+
 /* called from serio_driver->connect/disconnect methods under serio_sem */
 int serio_open(struct serio *serio, struct serio_driver *drv)
 {
@@ -629,14 +821,9 @@
 
         if (likely(serio->drv)) {
                 ret = serio->drv->interrupt(serio, data, dfl, regs);
-	} else {
-		if (!dfl) {
-			if ((serio->type != SERIO_8042 &&
-			     serio->type != SERIO_8042_XL) || (data == 0xaa)) {
-				serio_rescan(serio);
-				ret = IRQ_HANDLED;
-			}
-		}
+	} else if (!dfl && serio->registered) {
+		serio_rescan(serio);
+		ret = IRQ_HANDLED;
 	}
 
 	spin_unlock_irqrestore(&serio->lock, flags);
@@ -647,12 +834,15 @@
 static int __init serio_init(void)
 {
 	if (!(serio_pid = kernel_thread(serio_thread, NULL, CLONE_KERNEL))) {
-		printk(KERN_WARNING "serio: Failed to start kseriod\n");
+		printk(KERN_ERR "serio: Failed to start kseriod\n");
 		return -1;
 	}
 
 	serio_bus.dev_attrs = serio_device_attrs;
 	serio_bus.drv_attrs = serio_driver_attrs;
+	serio_bus.match = serio_bus_match;
+	serio_bus.hotplug = serio_hotplug;
+	serio_bus.resume = serio_resume;
 	bus_register(&serio_bus);
 
 	return 0;
diff -Nru a/drivers/input/serio/serio_raw.c b/drivers/input/serio/serio_raw.c
--- a/drivers/input/serio/serio_raw.c	2005-03-11 12:51:51 -08:00
+++ b/drivers/input/serio/serio_raw.c	2005-03-11 12:51:51 -08:00
@@ -235,7 +235,7 @@
 	return 0;
 }
 
-struct file_operations serio_raw_fops = {
+static struct file_operations serio_raw_fops = {
 	.owner =	THIS_MODULE,
 	.open =		serio_raw_open,
 	.release =	serio_raw_release,
@@ -253,7 +253,7 @@
 static irqreturn_t serio_raw_interrupt(struct serio *serio, unsigned char data,
 					unsigned int dfl, struct pt_regs *regs)
 {
-	struct serio_raw *serio_raw = serio->private;
+	struct serio_raw *serio_raw = serio_get_drvdata(serio);
 	struct serio_raw_list *list;
 	unsigned int head = serio_raw->head;
 
@@ -270,17 +270,14 @@
 	return IRQ_HANDLED;
 }
 
-static void serio_raw_connect(struct serio *serio, struct serio_driver *drv)
+static int serio_raw_connect(struct serio *serio, struct serio_driver *drv)
 {
 	struct serio_raw *serio_raw;
 	int err;
 
-	if ((serio->type & SERIO_TYPE) != SERIO_8042)
-		return;
-
 	if (!(serio_raw = kmalloc(sizeof(struct serio_raw), GFP_KERNEL))) {
 		printk(KERN_ERR "serio_raw.c: can't allocate memory for a device\n");
-		return;
+		return -ENOMEM;
 	}
 
 	down(&serio_raw_sem);
@@ -292,8 +289,10 @@
 	INIT_LIST_HEAD(&serio_raw->list);
 	init_waitqueue_head(&serio_raw->wait);
 
-	serio->private = serio_raw;
-	if (serio_open(serio, drv))
+	serio_set_drvdata(serio, serio_raw);
+
+	err = serio_open(serio, drv);
+	if (err)
 		goto out_free;
 
 	list_add_tail(&serio_raw->node, &serio_raw_list);
@@ -322,15 +321,16 @@
 	serio_close(serio);
 	list_del_init(&serio_raw->node);
 out_free:
-	serio->private = NULL;
+	serio_set_drvdata(serio, NULL);
 	kfree(serio_raw);
 out:
 	up(&serio_raw_sem);
+	return err;
 }
 
 static int serio_raw_reconnect(struct serio *serio)
 {
-	struct serio_raw *serio_raw = serio->private;
+	struct serio_raw *serio_raw = serio_get_drvdata(serio);
 	struct serio_driver *drv = serio->drv;
 
 	if (!drv || !serio_raw) {
@@ -351,10 +351,10 @@
 
 	down(&serio_raw_sem);
 
-	serio_raw = serio->private;
+	serio_raw = serio_get_drvdata(serio);
 
 	serio_close(serio);
-	serio->private = NULL;
+	serio_set_drvdata(serio, NULL);
 
 	serio_raw->serio = NULL;
 	if (!serio_raw_cleanup(serio_raw))
@@ -363,11 +363,24 @@
 	up(&serio_raw_sem);
 }
 
+static struct serio_device_id serio_raw_serio_ids[] = {
+	{
+		.type	= SERIO_8042,
+		.proto	= SERIO_ANY,
+		.id	= SERIO_ANY,
+		.extra	= SERIO_ANY,
+	},
+	{ 0 }
+};
+
+MODULE_DEVICE_TABLE(serio, serio_raw_serio_ids);
+
 static struct serio_driver serio_raw_drv = {
 	.driver		= {
 		.name	= "serio_raw",
 	},
 	.description	= DRIVER_DESC,
+	.id_table	= serio_raw_serio_ids,
 	.interrupt	= serio_raw_interrupt,
 	.connect	= serio_raw_connect,
 	.reconnect	= serio_raw_reconnect,
@@ -375,13 +388,13 @@
 	.manual_bind	= 1,
 };
 
-int __init serio_raw_init(void)
+static int __init serio_raw_init(void)
 {
 	serio_register_driver(&serio_raw_drv);
 	return 0;
 }
 
-void __exit serio_raw_exit(void)
+static void __exit serio_raw_exit(void)
 {
 	serio_unregister_driver(&serio_raw_drv);
 }
diff -Nru a/drivers/input/serio/serport.c b/drivers/input/serio/serport.c
--- a/drivers/input/serio/serport.c	2005-03-11 12:51:51 -08:00
+++ b/drivers/input/serio/serport.c	2005-03-11 12:51:51 -08:00
@@ -49,7 +49,7 @@
 {
 	struct serport *serport = serio->port_data;
 
-	serport->serio->type = 0;
+	serport->serio->id.type = 0;
 	wake_up_interruptible(&serport->wait);
 }
 
@@ -84,7 +84,7 @@
 	memset(serio, 0, sizeof(struct serio));
 	strlcpy(serio->name, "Serial port", sizeof(serio->name));
 	snprintf(serio->phys, sizeof(serio->phys), "%s/serio0", tty_name(tty, name));
-	serio->type = SERIO_RS232;
+	serio->id.type = SERIO_RS232;
 	serio->write = serport_serio_write;
 	serio->close = serport_serio_close;
 	serio->port_data = serport;
@@ -148,7 +148,7 @@
 
 	serio_register_port(serport->serio);
 	printk(KERN_INFO "serio: Serial port %s\n", tty_name(tty, name));
-	wait_event_interruptible(serport->wait, !serport->serio->type);
+	wait_event_interruptible(serport->wait, !serport->serio->id.type);
 	serio_unregister_port(serport->serio);
 
 	clear_bit(SERPORT_BUSY, &serport->flags);
@@ -163,9 +163,19 @@
 static int serport_ldisc_ioctl(struct tty_struct * tty, struct file * file, unsigned int cmd, unsigned long arg)
 {
 	struct serport *serport = (struct serport*) tty->disc_data;
+	struct serio *serio = serport->serio;
+	unsigned long type;
 
-	if (cmd == SPIOCSTYPE)
-		return get_user(serport->serio->type, (unsigned long __user *) arg);
+	if (cmd == SPIOCSTYPE) {
+		if (get_user(type, (unsigned long __user *) arg))
+			return -EFAULT;
+
+		serio->id.proto	= type & 0x000000ff;
+		serio->id.id	= (type & 0x0000ff00) >> 8;
+		serio->id.extra	= (type & 0x00ff0000) >> 16;
+
+		return 0;
+	}
 
 	return -EINVAL;
 }
diff -Nru a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
--- a/drivers/input/touchscreen/Kconfig	2005-03-11 12:51:46 -08:00
+++ b/drivers/input/touchscreen/Kconfig	2005-03-11 12:51:46 -08:00
@@ -1,18 +1,19 @@
 #
 # Mouse driver configuration
 #
-config INPUT_TOUCHSCREEN
+menuconfig INPUT_TOUCHSCREEN
 	bool "Touchscreens"
-	depends on INPUT
 	help
 	  Say Y here, and a list of supported touchscreens will be displayed.
 	  This option doesn't affect the kernel.
 
 	  If unsure, say Y.
 
+if INPUT_TOUCHSCREEN
+
 config TOUCHSCREEN_BITSY
-	tristate "Compaq iPAQ H3600 (Bitsy) touchscreen input driver"
-	depends on SA1100_BITSY && INPUT && INPUT_TOUCHSCREEN
+	tristate "Compaq iPAQ H3600 (Bitsy) touchscreen"
+	depends on SA1100_BITSY
 	select SERIO
 	help
 	  Say Y here if you have the h3600 (Bitsy) touchscreen.
@@ -22,9 +23,21 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called h3600_ts_input.
 
+config TOUCHSCREEN_CORGI
+	tristate "Corgi touchscreen (for Sharp SL-C7xx)"
+	depends on PXA_SHARPSL
+	default y	
+	help
+	  Say Y here to enable the driver for the touchscreen on the 
+	  Sharp SL-C7xx series of PDAs.
+
+	  If unsure, say N.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called ads7846_ts.
+
 config TOUCHSCREEN_GUNZE
 	tristate "Gunze AHL-51S touchscreen"
-	depends on INPUT && INPUT_TOUCHSCREEN
 	select SERIO
 	help
 	  Say Y here if you have the Gunze AHL-51 touchscreen connected to
@@ -35,3 +48,51 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called gunze.
 
+config TOUCHSCREEN_ELO
+	tristate "Elo serial touchscreens"
+	select SERIO
+	help
+	  Say Y here if you have an Elo serial touchscreen connected to
+	  your system.
+
+	  If unsure, say N.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called gunze.
+
+config TOUCHSCREEN_MTOUCH
+	tristate "MicroTouch serial touchscreens"
+	select SERIO
+	help
+	  Say Y here if you have a MicroTouch (3M) serial touchscreen connected to
+	  your system.
+
+	  If unsure, say N.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called mtouch.
+
+config TOUCHSCREEN_MK712
+	tristate "ICS MicroClock MK712 touchscreen"
+	help
+	  Say Y here if you have the ICS MicroClock MK712 touchscreen
+	  controller chip in your system.
+
+	  If unsure, say N.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called mk712.
+
+config TOUCHSCREEN_HP600
+	tristate "HP Jornada 680/690 touchscreen"
+	depends on SH_HP600 && SH_ADC
+	help
+	  Say Y here if you have a HP Jornada 680 or 690 and want to
+          support the built-in touchscreen.
+
+	  If unsure, say N.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called hp680_ts_input.
+
+endif
diff -Nru a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
--- a/drivers/input/touchscreen/Makefile	2005-03-11 12:51:51 -08:00
+++ b/drivers/input/touchscreen/Makefile	2005-03-11 12:51:51 -08:00
@@ -5,4 +5,9 @@
 # Each configuration option enables a list of files.
 
 obj-$(CONFIG_TOUCHSCREEN_BITSY)	+= h3600_ts_input.o
+obj-$(CONFIG_TOUCHSCREEN_CORGI)	+= corgi_ts.o
 obj-$(CONFIG_TOUCHSCREEN_GUNZE)	+= gunze.o
+obj-$(CONFIG_TOUCHSCREEN_ELO)	+= elo.o
+obj-$(CONFIG_TOUCHSCREEN_MTOUCH) += mtouch.o
+obj-$(CONFIG_TOUCHSCREEN_MK712)	+= mk712.o
+obj-$(CONFIG_TOUCHSCREEN_HP600)	+= hp680_ts_input.o
diff -Nru a/drivers/input/touchscreen/corgi_ts.c b/drivers/input/touchscreen/corgi_ts.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/input/touchscreen/corgi_ts.c	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,380 @@
+/*
+ *  Touchscreen driver for Sharp Corgi models (SL-C7xx)
+ *
+ *  Copyright (c) 2004-2005 Richard Purdie
+ *
+ *  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/delay.h>
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <asm/irq.h>
+
+#include <asm/arch/corgi.h>
+#include <asm/arch/hardware.h>
+#include <asm/arch/pxa-regs.h>
+
+
+#define PWR_MODE_ACTIVE		0
+#define PWR_MODE_SUSPEND	1
+
+#define X_AXIS_MAX		3830
+#define X_AXIS_MIN		150
+#define Y_AXIS_MAX		3830
+#define Y_AXIS_MIN		190
+#define PRESSURE_MIN		0
+#define PRESSURE_MAX		15000
+
+struct ts_event {
+	short pressure;
+	short x;
+	short y;
+};
+
+struct corgi_ts {
+	char phys[32];
+	struct input_dev input;
+	struct timer_list timer;
+	struct ts_event tc;
+	int pendown;
+	int power_mode;
+};
+
+#define STATUS_HSYNC		(GPLR(CORGI_GPIO_HSYNC) & GPIO_bit(CORGI_GPIO_HSYNC))
+
+#define SyncHS()	while((STATUS_HSYNC) == 0); while((STATUS_HSYNC) != 0);
+#define CCNT(a)		asm volatile ("mrc p14, 0, %0, C1, C0, 0" : "=r"(a))
+#define CCNT_ON()	{int pmnc = 1; asm volatile ("mcr p14, 0, %0, C0, C0, 0" : : "r"(pmnc));}
+#define CCNT_OFF()	{int pmnc = 0; asm volatile ("mcr p14, 0, %0, C0, C0, 0" : : "r"(pmnc));}
+
+#define WAIT_HS_400_VGA		7013U	// 17.615us
+#define WAIT_HS_400_QVGA	16622U	// 41.750us
+
+
+/* ADS7846 Touch Screen Controller bit definitions */
+#define ADSCTRL_PD0		(1u << 0)	/* PD0 */
+#define ADSCTRL_PD1		(1u << 1)	/* PD1 */
+#define ADSCTRL_DFR		(1u << 2)	/* SER/DFR */
+#define ADSCTRL_MOD		(1u << 3)	/* Mode */
+#define ADSCTRL_ADR_SH	4	/* Address setting */
+#define ADSCTRL_STS		(1u << 7)	/* Start Bit */
+
+/* External Functions */
+extern int w100fb_get_xres(void);
+extern int w100fb_get_blanking(void);
+extern int w100fb_get_fastsysclk(void);
+extern unsigned int get_clk_frequency_khz(int info);
+
+static unsigned long calc_waittime(void)
+{
+	int w100fb_xres = w100fb_get_xres();
+	unsigned int waittime = 0;
+
+	if (w100fb_xres == 480 || w100fb_xres == 640) {
+		waittime = WAIT_HS_400_VGA * get_clk_frequency_khz(0) / 398131U;
+
+		if (w100fb_get_fastsysclk() == 100)
+			waittime = waittime * 75 / 100;
+
+		if (w100fb_xres == 640)
+			waittime *= 3;
+
+		return waittime;
+	}
+
+	return WAIT_HS_400_QVGA * get_clk_frequency_khz(0) / 398131U;
+}
+
+static int sync_receive_data_send_cmd(int doRecive, int doSend, unsigned int address, unsigned long wait_time)
+{
+	int pos = 0;
+	unsigned long timer1 = 0, timer2;
+	int dosleep;
+
+	dosleep = !w100fb_get_blanking();
+
+	if (dosleep && doSend) {
+		CCNT_ON();
+		/* polling HSync */
+		SyncHS();
+		/* get CCNT */
+		CCNT(timer1);
+	}
+
+	if (doRecive)
+		pos = corgi_ssp_ads7846_get();
+
+	if (doSend) {
+		int cmd = ADSCTRL_PD0 | ADSCTRL_PD1 | (address << ADSCTRL_ADR_SH) | ADSCTRL_STS;
+		/* dummy command */
+		corgi_ssp_ads7846_put(cmd);
+		corgi_ssp_ads7846_get();
+
+		if (dosleep) {
+			/* Wait after HSync */
+			CCNT(timer2);
+			if (timer2-timer1 > wait_time) {
+				/* timeout */
+				SyncHS();
+				/* get OSCR */
+				CCNT(timer1);
+				/* Wait after HSync */
+				CCNT(timer2);
+			}
+			while (timer2 - timer1 < wait_time)
+				CCNT(timer2);
+		}
+		corgi_ssp_ads7846_put(cmd);
+		if (dosleep)
+			CCNT_OFF();
+	}
+	return pos;
+}
+
+static int read_xydata(struct corgi_ts *corgi_ts)
+{
+	unsigned int x, y, z1, z2;
+	unsigned long flags, wait_time;
+
+	/* critical section */
+	local_irq_save(flags);
+	corgi_ssp_ads7846_lock();
+	wait_time=calc_waittime();
+
+	/* Y-axis */
+	sync_receive_data_send_cmd(0, 1, 1u, wait_time);
+
+	/* Y-axis */
+	sync_receive_data_send_cmd(1, 1, 1u, wait_time);
+
+	/* X-axis */
+	y = sync_receive_data_send_cmd(1, 1, 5u, wait_time);
+
+	/* Z1 */
+	x = sync_receive_data_send_cmd(1, 1, 3u, wait_time);
+
+	/* Z2 */
+	z1 = sync_receive_data_send_cmd(1, 1, 4u, wait_time);
+	z2 = sync_receive_data_send_cmd(1, 0, 4u, wait_time);
+
+	/* Power-Down Enable */
+	corgi_ssp_ads7846_put((1u << ADSCTRL_ADR_SH) | ADSCTRL_STS);
+	corgi_ssp_ads7846_get();
+
+	corgi_ssp_ads7846_unlock();
+	local_irq_restore(flags);
+
+	if (x== 0 || y == 0 || z1 == 0 || (x * (z2 - z1) / z1) >= 15000) {
+		corgi_ts->tc.pressure = 0;
+		return 0;
+	}
+
+	corgi_ts->tc.x = x;
+	corgi_ts->tc.y = y;
+	corgi_ts->tc.pressure = (x * (z2 - z1)) / z1;
+	return 1;
+}
+
+static void new_data(struct corgi_ts *corgi_ts, struct pt_regs *regs)
+{
+	if (corgi_ts->power_mode != PWR_MODE_ACTIVE)
+		return;
+
+	if (!corgi_ts->tc.pressure && corgi_ts->pendown == 0)
+		return;
+
+	if (regs)
+		input_regs(&corgi_ts->input, regs);
+
+	input_report_abs(&corgi_ts->input, ABS_X, corgi_ts->tc.x);
+	input_report_abs(&corgi_ts->input, ABS_Y, corgi_ts->tc.y);
+	input_report_abs(&corgi_ts->input, ABS_PRESSURE, corgi_ts->tc.pressure);
+	input_report_key(&corgi_ts->input, BTN_TOUCH, (corgi_ts->pendown != 0));
+	input_sync(&corgi_ts->input);
+}
+
+static void ts_interrupt_main(struct corgi_ts *corgi_ts, int isTimer, struct pt_regs *regs)
+{
+	if ((GPLR(CORGI_GPIO_TP_INT) & GPIO_bit(CORGI_GPIO_TP_INT)) == 0) {
+		/* Disable Interrupt */
+		set_irq_type(CORGI_IRQ_GPIO_TP_INT, IRQT_NOEDGE);
+		if (read_xydata(corgi_ts)) {
+			corgi_ts->pendown = 1;
+			new_data(corgi_ts, regs);
+		}
+		mod_timer(&corgi_ts->timer, jiffies + HZ / 100);
+	} else {
+		if (corgi_ts->pendown == 1 || corgi_ts->pendown == 2) {
+			mod_timer(&corgi_ts->timer, jiffies + HZ / 100);
+			corgi_ts->pendown++;
+			return;
+		}
+
+		if (corgi_ts->pendown) {
+			corgi_ts->tc.pressure = 0;
+			new_data(corgi_ts, regs);
+		}
+
+		/* Enable Falling Edge */
+		set_irq_type(CORGI_IRQ_GPIO_TP_INT, IRQT_FALLING);
+		corgi_ts->pendown = 0;
+	}
+}
+
+static void corgi_ts_timer(unsigned long data)
+{
+	struct corgi_ts *corgits_data = (struct corgi_ts *) data;
+	ts_interrupt_main(corgits_data, 1, NULL);
+}
+
+static irqreturn_t ts_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+	struct corgi_ts *corgits_data = dev_id;
+	ts_interrupt_main(corgits_data, 0, regs);
+	return IRQ_HANDLED;
+}
+
+#ifdef CONFIG_PM
+static int corgits_suspend(struct device *dev, uint32_t state, uint32_t level)
+{
+	if (level == SUSPEND_POWER_DOWN) {
+		struct corgi_ts *corgi_ts = dev_get_drvdata(dev);
+
+		if (corgi_ts->pendown) {
+			del_timer_sync(&corgi_ts->timer);
+			corgi_ts->tc.pressure = 0;
+			new_data(corgi_ts, NULL);
+			corgi_ts->pendown = 0;
+		}
+		corgi_ts->power_mode = PWR_MODE_SUSPEND;
+
+		corgi_ssp_ads7846_putget((1u << ADSCTRL_ADR_SH) | ADSCTRL_STS);
+	}
+	return 0;
+}
+
+static int corgits_resume(struct device *dev, uint32_t level)
+{
+	if (level == RESUME_POWER_ON) {
+		struct corgi_ts *corgi_ts = dev_get_drvdata(dev);
+
+		corgi_ssp_ads7846_putget((4u << ADSCTRL_ADR_SH) | ADSCTRL_STS);
+		/* Enable Falling Edge */
+		set_irq_type(CORGI_IRQ_GPIO_TP_INT, IRQT_FALLING);
+		corgi_ts->power_mode = PWR_MODE_ACTIVE;
+	}
+	return 0;
+}
+#else
+#define corgits_suspend		NULL
+#define corgits_resume		NULL
+#endif
+
+static int __init corgits_probe(struct device *dev)
+{
+	struct corgi_ts *corgi_ts;
+
+	if (!(corgi_ts = kmalloc(sizeof(struct corgi_ts), GFP_KERNEL)))
+		return -ENOMEM;
+
+	dev_set_drvdata(dev, corgi_ts);
+
+	memset(corgi_ts, 0, sizeof(struct corgi_ts));
+
+	init_input_dev(&corgi_ts->input);
+	corgi_ts->input.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+	corgi_ts->input.keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
+	input_set_abs_params(&corgi_ts->input, ABS_X, X_AXIS_MIN, X_AXIS_MAX, 0, 0);
+	input_set_abs_params(&corgi_ts->input, ABS_Y, Y_AXIS_MIN, Y_AXIS_MAX, 0, 0);
+	input_set_abs_params(&corgi_ts->input, ABS_PRESSURE, PRESSURE_MIN, PRESSURE_MAX, 0, 0);
+
+	strcpy(corgi_ts->phys, "corgits/input0");
+
+	corgi_ts->input.private = corgi_ts;
+	corgi_ts->input.name = "Corgi Touchscreen";
+	corgi_ts->input.dev = dev;
+	corgi_ts->input.phys = corgi_ts->phys;
+	corgi_ts->input.id.bustype = BUS_HOST;
+	corgi_ts->input.id.vendor = 0x0001;
+	corgi_ts->input.id.product = 0x0002;
+	corgi_ts->input.id.version = 0x0100;
+
+	pxa_gpio_mode(CORGI_GPIO_TP_INT | GPIO_IN);
+	pxa_gpio_mode(CORGI_GPIO_HSYNC | GPIO_IN);
+
+	/* Initiaize ADS7846 Difference Reference mode */
+	corgi_ssp_ads7846_putget((1u << ADSCTRL_ADR_SH) | ADSCTRL_STS);
+	mdelay(5);
+	corgi_ssp_ads7846_putget((3u << ADSCTRL_ADR_SH) | ADSCTRL_STS);
+	mdelay(5);
+	corgi_ssp_ads7846_putget((4u << ADSCTRL_ADR_SH) | ADSCTRL_STS);
+	mdelay(5);
+	corgi_ssp_ads7846_putget((5u << ADSCTRL_ADR_SH) | ADSCTRL_STS);
+	mdelay(5);
+
+	init_timer(&corgi_ts->timer);
+	corgi_ts->timer.data = (unsigned long) corgi_ts;
+	corgi_ts->timer.function = corgi_ts_timer;
+
+	input_register_device(&corgi_ts->input);
+	corgi_ts->power_mode = PWR_MODE_ACTIVE;
+
+	if (request_irq(CORGI_IRQ_GPIO_TP_INT, ts_interrupt, SA_INTERRUPT, "ts", corgi_ts)) {
+		input_unregister_device(&corgi_ts->input);
+		kfree(corgi_ts);
+		return -EBUSY;
+	}
+
+	/* Enable Falling Edge */
+	set_irq_type(CORGI_IRQ_GPIO_TP_INT, IRQT_FALLING);
+
+	printk(KERN_INFO "input: Corgi Touchscreen Registered\n");
+
+	return 0;
+}
+
+static int corgits_remove(struct device *dev)
+{
+	struct corgi_ts *corgi_ts = dev_get_drvdata(dev);
+
+	free_irq(CORGI_IRQ_GPIO_TP_INT, NULL);
+	del_timer_sync(&corgi_ts->timer);
+	input_unregister_device(&corgi_ts->input);
+	kfree(corgi_ts);
+	return 0;
+}
+
+static struct device_driver corgits_driver = {
+	.name		= "corgi-ts",
+	.bus		= &platform_bus_type,
+	.probe		= corgits_probe,
+	.remove		= corgits_remove,
+	.suspend	= corgits_suspend,
+	.resume		= corgits_resume,
+};
+
+static int __devinit corgits_init(void)
+{
+	return driver_register(&corgits_driver);
+}
+
+static void __exit corgits_exit(void)
+{
+	driver_unregister(&corgits_driver);
+}
+
+module_init(corgits_init);
+module_exit(corgits_exit);
+
+MODULE_AUTHOR("Richard Purdie <rpurdie@rpsys.net>");
+MODULE_DESCRIPTION("Corgi TouchScreen Driver");
+MODULE_LICENSE("GPL");
diff -Nru a/drivers/input/touchscreen/elo.c b/drivers/input/touchscreen/elo.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/input/touchscreen/elo.c	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,315 @@
+/*
+ * Elo serial touchscreen driver
+ *
+ * Copyright (c) 2004 Vojtech Pavlik
+ */
+
+/*
+ * 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 driver can handle serial Elo touchscreens using either the Elo standard
+ * 'E271-2210' 10-byte protocol, Elo legacy 'E281A-4002' 6-byte protocol, Elo
+ * legacy 'E271-140' 4-byte protocol and Elo legacy 'E261-280' 3-byte protocol.
+ */
+
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/input.h>
+#include <linux/serio.h>
+#include <linux/init.h>
+
+#define DRIVER_DESC	"Elo serial touchscreen driver"
+
+MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
+
+/*
+ * Definitions & global arrays.
+ */
+
+#define	ELO_MAX_LENGTH	10
+
+static char *elo_name = "Elo Serial TouchScreen";
+
+/*
+ * Per-touchscreen data.
+ */
+
+struct elo {
+	struct input_dev dev;
+	struct serio *serio;
+	int id;
+	int idx;
+	unsigned char csum;
+	unsigned char data[ELO_MAX_LENGTH];
+	char phys[32];
+};
+
+static void elo_process_data_10(struct elo* elo, unsigned char data, struct pt_regs *regs)
+{
+	struct input_dev *dev = &elo->dev;
+
+	elo->csum += elo->data[elo->idx] = data;
+
+	switch (elo->idx++) {
+
+		case 0:
+			if (data != 'U') {
+				elo->idx = 0;
+				elo->csum = 0;
+			}
+			break;
+
+		case 1:
+			if (data != 'T') {
+				elo->idx = 0;
+				elo->csum = 0;
+			}
+			break;
+
+		case 9:
+			if (elo->csum) {
+				input_regs(dev, regs);
+				input_report_abs(dev, ABS_X, (elo->data[4] << 8) | elo->data[3]);
+				input_report_abs(dev, ABS_Y, (elo->data[6] << 8) | elo->data[5]);
+				input_report_abs(dev, ABS_PRESSURE, (elo->data[8] << 8) | elo->data[7]);
+				input_report_key(dev, BTN_TOUCH, elo->data[2] & 3);
+				input_sync(dev);
+			}
+			elo->idx = 0;
+			elo->csum = 0;
+			break;
+	}
+}
+
+static void elo_process_data_6(struct elo* elo, unsigned char data, struct pt_regs *regs)
+{
+	struct input_dev *dev = &elo->dev;
+
+	elo->data[elo->idx] = data;
+
+	switch (elo->idx++) {
+
+		case 0: if ((data & 0xc0) != 0xc0) elo->idx = 0; break;
+		case 1: if ((data & 0xc0) != 0x80) elo->idx = 0; break;
+		case 2: if ((data & 0xc0) != 0x40) elo->idx = 0; break;
+
+		case 3:
+			if (data & 0xc0) {
+				elo->idx = 0;
+				break;
+			}
+
+			input_regs(dev, regs);
+			input_report_abs(dev, ABS_X, ((elo->data[0] & 0x3f) << 6) | (elo->data[1] & 0x3f));
+			input_report_abs(dev, ABS_Y, ((elo->data[2] & 0x3f) << 6) | (elo->data[3] & 0x3f));
+
+			if (elo->id == 2) {
+				input_report_key(dev, BTN_TOUCH, 1);
+				input_sync(dev);
+				elo->idx = 0;
+			}
+
+			break;
+
+		case 4:
+			if (data) {
+				input_sync(dev);
+				elo->idx = 0;
+			}
+			break;
+
+		case 5:
+			if ((data & 0xf0) == 0) {
+				input_report_abs(dev, ABS_PRESSURE, elo->data[5]);
+				input_report_key(dev, BTN_TOUCH, elo->data[5]);
+			}
+			input_sync(dev);
+			elo->idx = 0;
+			break;
+	}
+}
+
+static void elo_process_data_3(struct elo* elo, unsigned char data, struct pt_regs *regs)
+{
+	struct input_dev *dev = &elo->dev;
+
+	elo->data[elo->idx] = data;
+
+	switch (elo->idx++) {
+
+		case 0:
+			if ((data & 0x7f) != 0x01)
+				elo->idx = 0;
+			break;
+		case 2:
+			input_regs(dev, regs);
+			input_report_key(dev, BTN_TOUCH, !(elo->data[1] & 0x80));
+			input_report_abs(dev, ABS_X, elo->data[1]);
+			input_report_abs(dev, ABS_Y, elo->data[2]);
+			input_sync(dev);
+			elo->idx = 0;
+			break;
+	}
+}
+
+static irqreturn_t elo_interrupt(struct serio *serio,
+		unsigned char data, unsigned int flags, struct pt_regs *regs)
+{
+	struct elo* elo = serio_get_drvdata(serio);
+
+	switch(elo->id) {
+		case 0:
+			elo_process_data_10(elo, data, regs);
+			break;
+
+		case 1:
+		case 2:
+			elo_process_data_6(elo, data, regs);
+			break;
+
+		case 3:
+			elo_process_data_3(elo, data, regs);
+			break;
+	}
+
+	return IRQ_HANDLED;
+}
+
+/*
+ * elo_disconnect() is the opposite of elo_connect()
+ */
+
+static void elo_disconnect(struct serio *serio)
+{
+	struct elo* elo = serio_get_drvdata(serio);
+
+	input_unregister_device(&elo->dev);
+	serio_close(serio);
+	serio_set_drvdata(serio, NULL);
+	kfree(elo);
+}
+
+/*
+ * elo_connect() is the routine that is called when someone adds a
+ * new serio device that supports Gunze protocol and registers it as
+ * an input device.
+ */
+
+static int elo_connect(struct serio *serio, struct serio_driver *drv)
+{
+	struct elo *elo;
+	int err;
+
+	if (!(elo = kmalloc(sizeof(struct elo), GFP_KERNEL)))
+		return -ENOMEM;
+
+	memset(elo, 0, sizeof(struct elo));
+
+	init_input_dev(&elo->dev);
+	elo->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+	elo->dev.keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
+
+	elo->id = serio->id.id;
+
+	switch (elo->id) {
+
+		case 0: /* 10-byte protocol */
+			input_set_abs_params(&elo->dev, ABS_X, 96, 4000, 0, 0);
+			input_set_abs_params(&elo->dev, ABS_Y, 96, 4000, 0, 0);
+			input_set_abs_params(&elo->dev, ABS_PRESSURE, 0, 255, 0, 0);
+			break;
+		
+		case 1: /* 6-byte protocol */
+			input_set_abs_params(&elo->dev, ABS_PRESSURE, 0, 15, 0, 0);
+
+		case 2: /* 4-byte protocol */
+			input_set_abs_params(&elo->dev, ABS_X, 96, 4000, 0, 0);
+			input_set_abs_params(&elo->dev, ABS_Y, 96, 4000, 0, 0);
+			break;
+
+		case 3: /* 3-byte protocol */
+			input_set_abs_params(&elo->dev, ABS_X, 0, 255, 0, 0);
+			input_set_abs_params(&elo->dev, ABS_Y, 0, 255, 0, 0);
+			break;
+	}
+
+	elo->serio = serio;
+
+	sprintf(elo->phys, "%s/input0", serio->phys);
+
+	elo->dev.private = elo;
+	elo->dev.name = elo_name;
+	elo->dev.phys = elo->phys;
+	elo->dev.id.bustype = BUS_RS232;
+	elo->dev.id.vendor = SERIO_ELO;
+	elo->dev.id.product = elo->id;
+	elo->dev.id.version = 0x0100;
+
+	serio_set_drvdata(serio, elo);
+
+	err = serio_open(serio, drv);
+	if (err) {
+		serio_set_drvdata(serio, NULL);
+		kfree(elo);
+		return err;
+	}
+
+	input_register_device(&elo->dev);
+
+	printk(KERN_INFO "input: %s on %s\n", elo_name, serio->phys);
+
+	return 0;
+}
+
+/*
+ * The serio driver structure.
+ */
+
+static struct serio_device_id elo_serio_ids[] = {
+	{
+		.type	= SERIO_RS232,
+		.proto	= SERIO_ELO,
+		.id	= SERIO_ANY,
+		.extra	= SERIO_ANY,
+	},
+	{ 0 }
+};
+
+MODULE_DEVICE_TABLE(serio, elo_serio_ids);
+
+static struct serio_driver elo_drv = {
+	.driver		= {
+		.name	= "elo",
+	},
+	.description	= DRIVER_DESC,
+	.id_table	= elo_serio_ids,
+	.interrupt	= elo_interrupt,
+	.connect	= elo_connect,
+	.disconnect	= elo_disconnect,
+};
+
+/*
+ * The functions for inserting/removing us as a module.
+ */
+
+static int __init elo_init(void)
+{
+	serio_register_driver(&elo_drv);
+	return 0;
+}
+
+static void __exit elo_exit(void)
+{
+	serio_unregister_driver(&elo_drv);
+}
+
+module_init(elo_init);
+module_exit(elo_exit);
diff -Nru a/drivers/input/touchscreen/gunze.c b/drivers/input/touchscreen/gunze.c
--- a/drivers/input/touchscreen/gunze.c	2005-03-11 12:51:42 -08:00
+++ b/drivers/input/touchscreen/gunze.c	2005-03-11 12:51:42 -08:00
@@ -74,8 +74,8 @@
 	}
 
 	input_regs(dev, regs);
-	input_report_abs(dev, ABS_X, simple_strtoul(gunze->data + 1, NULL, 10) * 4);
-	input_report_abs(dev, ABS_Y, 3072 - simple_strtoul(gunze->data + 6, NULL, 10) * 3);
+	input_report_abs(dev, ABS_X, simple_strtoul(gunze->data + 1, NULL, 10));
+	input_report_abs(dev, ABS_Y, 1024 - simple_strtoul(gunze->data + 6, NULL, 10));
 	input_report_key(dev, BTN_TOUCH, gunze->data[0] == 'T');
 	input_sync(dev);
 }
@@ -83,7 +83,7 @@
 static irqreturn_t gunze_interrupt(struct serio *serio,
 		unsigned char data, unsigned int flags, struct pt_regs *regs)
 {
-	struct gunze* gunze = serio->private;
+	struct gunze* gunze = serio_get_drvdata(serio);
 
 	if (data == '\r') {
 		gunze_process_packet(gunze, regs);
@@ -101,38 +101,37 @@
 
 static void gunze_disconnect(struct serio *serio)
 {
-	struct gunze* gunze = serio->private;
+	struct gunze* gunze = serio_get_drvdata(serio);
+
 	input_unregister_device(&gunze->dev);
 	serio_close(serio);
+	serio_set_drvdata(serio, NULL);
 	kfree(gunze);
 }
 
 /*
  * gunze_connect() is the routine that is called when someone adds a
- * new serio device. It looks whether it was registered as a Gunze touchscreen
- * and if yes, registers it as an input device.
+ * new serio device that supports Gunze protocol and registers it as
+ * an input device.
  */
 
-static void gunze_connect(struct serio *serio, struct serio_driver *drv)
+static int gunze_connect(struct serio *serio, struct serio_driver *drv)
 {
 	struct gunze *gunze;
-
-	if (serio->type != (SERIO_RS232 | SERIO_GUNZE))
-		return;
+	int err;
 
 	if (!(gunze = kmalloc(sizeof(struct gunze), GFP_KERNEL)))
-		return;
+		return -ENOMEM;
 
 	memset(gunze, 0, sizeof(struct gunze));
 
 	init_input_dev(&gunze->dev);
 	gunze->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
 	gunze->dev.keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
-	input_set_abs_params(&gunze->dev, ABS_X, 96, 4000, 0, 0);
-	input_set_abs_params(&gunze->dev, ABS_Y, 72, 3000, 0, 0);
+	input_set_abs_params(&gunze->dev, ABS_X, 24, 1000, 0, 0);
+	input_set_abs_params(&gunze->dev, ABS_Y, 24, 1000, 0, 0);
 
 	gunze->serio = serio;
-	serio->private = gunze;
 
 	sprintf(gunze->phys, "%s/input0", serio->phys);
 
@@ -144,25 +143,44 @@
 	gunze->dev.id.product = 0x0051;
 	gunze->dev.id.version = 0x0100;
 
-	if (serio_open(serio, drv)) {
+	serio_set_drvdata(serio, gunze);
+
+	err = serio_open(serio, drv);
+	if (err) {
+		serio_set_drvdata(serio, NULL);
 		kfree(gunze);
-		return;
+		return err;
 	}
 
 	input_register_device(&gunze->dev);
 
 	printk(KERN_INFO "input: %s on %s\n", gunze_name, serio->phys);
+
+	return 0;
 }
 
 /*
- * The serio device structure.
+ * The serio driver structure.
  */
 
+static struct serio_device_id gunze_serio_ids[] = {
+	{
+		.type	= SERIO_RS232,
+		.proto	= SERIO_GUNZE,
+		.id	= SERIO_ANY,
+		.extra	= SERIO_ANY,
+	},
+	{ 0 }
+};
+
+MODULE_DEVICE_TABLE(serio, gunze_serio_ids);
+
 static struct serio_driver gunze_drv = {
 	.driver		= {
 		.name	= "gunze",
 	},
 	.description	= DRIVER_DESC,
+	.id_table	= gunze_serio_ids,
 	.interrupt	= gunze_interrupt,
 	.connect	= gunze_connect,
 	.disconnect	= gunze_disconnect,
@@ -172,13 +190,13 @@
  * The functions for inserting/removing us as a module.
  */
 
-int __init gunze_init(void)
+static int __init gunze_init(void)
 {
 	serio_register_driver(&gunze_drv);
 	return 0;
 }
 
-void __exit gunze_exit(void)
+static void __exit gunze_exit(void)
 {
 	serio_unregister_driver(&gunze_drv);
 }
diff -Nru a/drivers/input/touchscreen/h3600_ts_input.c b/drivers/input/touchscreen/h3600_ts_input.c
--- a/drivers/input/touchscreen/h3600_ts_input.c	2005-03-11 12:51:51 -08:00
+++ b/drivers/input/touchscreen/h3600_ts_input.c	2005-03-11 12:51:51 -08:00
@@ -102,6 +102,7 @@
 	struct input_dev dev;
 	struct pm_dev *pm_dev;
 	struct serio *serio;
+	struct pm_dev *pm_dev;
 	unsigned char event;	/* event ID from packet */
 	unsigned char chksum;
 	unsigned char len;
@@ -331,7 +332,7 @@
 static irqreturn_t h3600ts_interrupt(struct serio *serio, unsigned char data,
                                      unsigned int flags, struct pt_regs *regs)
 {
-        struct h3600_dev *ts = serio->private;
+        struct h3600_dev *ts = serio_get_drvdata(serio);
 
 	/*
          * We have a new frame coming in.
@@ -373,18 +374,16 @@
 
 /*
  * h3600ts_connect() is the routine that is called when someone adds a
- * new serio device. It looks whether it was registered as a H3600 touchscreen
- * and if yes, registers it as an input device.
+ * new serio device that supports H3600 protocol and registers it as
+ * an input device.
  */
-static void h3600ts_connect(struct serio *serio, struct serio_driver *drv)
+static int h3600ts_connect(struct serio *serio, struct serio_driver *drv)
 {
 	struct h3600_dev *ts;
-
-	if (serio->type != (SERIO_RS232 | SERIO_H3600))
-		return;
+	int err;
 
 	if (!(ts = kmalloc(sizeof(struct h3600_dev), GFP_KERNEL)))
-		return;
+		return -ENOMEM;
 
 	memset(ts, 0, sizeof(struct h3600_dev));
 
@@ -399,7 +398,7 @@
 			"h3600_action", &ts->dev)) {
 		printk(KERN_ERR "h3600ts.c: Could not allocate Action Button IRQ!\n");
 		kfree(ts);
-		return;
+		return -EBUSY;
 	}
 
         if (request_irq(IRQ_GPIO_BITSY_NPOWER_BUTTON, npower_button_handler,
@@ -408,7 +407,7 @@
 		free_irq(IRQ_GPIO_BITSY_ACTION_BUTTON, &ts->dev);
 		printk(KERN_ERR "h3600ts.c: Could not allocate Power Button IRQ!\n");
 		kfree(ts);
-		return;
+		return -EBUSY;
 	}
 
 	/* Now we have things going we setup our input device */
@@ -431,7 +430,6 @@
 	ts->dev.keybit[LONG(KEY_SUSPEND)] |= BIT(KEY_SUSPEND);
 
 	ts->serio = serio;
-	serio->private = ts;
 
 	sprintf(ts->phys, "%s/input0", serio->phys);
 
@@ -444,11 +442,15 @@
 	ts->dev.id.product = 0x0666;  /* FIXME !!! We can ask the hardware */
 	ts->dev.id.version = 0x0100;
 
-	if (serio_open(serio, drv)) {
+	serio_set_drvdata(serio, ts);
+
+	err = serio_open(serio, drv);
+	if (err) {
         	free_irq(IRQ_GPIO_BITSY_ACTION_BUTTON, ts);
         	free_irq(IRQ_GPIO_BITSY_NPOWER_BUTTON, ts);
+		serio_set_drvdata(serio, NULL);
 		kfree(ts);
-		return;
+		return err;
 	}
 
 	//h3600_flite_control(1, 25);     /* default brightness */
@@ -460,6 +462,8 @@
 	input_register_device(&ts->dev);
 
 	printk(KERN_INFO "input: %s on %s\n", h3600_name, serio->phys);
+
+	return 0;
 }
 
 /*
@@ -468,24 +472,38 @@
 
 static void h3600ts_disconnect(struct serio *serio)
 {
-	struct h3600_dev *ts = serio->private;
+	struct h3600_dev *ts = serio_get_drvdata(serio);
 
-        free_irq(IRQ_GPIO_BITSY_ACTION_BUTTON, &ts->dev);
-        free_irq(IRQ_GPIO_BITSY_NPOWER_BUTTON, &ts->dev);
+	free_irq(IRQ_GPIO_BITSY_ACTION_BUTTON, &ts->dev);
+	free_irq(IRQ_GPIO_BITSY_NPOWER_BUTTON, &ts->dev);
 	input_unregister_device(&ts->dev);
 	serio_close(serio);
+	serio_set_drvdata(serio, NULL);
 	kfree(ts);
 }
 
 /*
- * The serio device structure.
+ * The serio driver structure.
  */
 
+static struct serio_device_id h3600ts_serio_ids[] = {
+	{
+		.type	= SERIO_RS232,
+		.proto	= SERIO_H3600,
+		.id	= SERIO_ANY,
+		.extra	= SERIO_ANY,
+	},
+	{ 0 }
+};
+
+MODULE_DEVICE_TABLE(serio, h3600ts_serio_ids);
+
 static struct serio_driver h3600ts_drv = {
 	.driver		= {
 		.name	= "h3600ts",
 	},
 	.description	= DRIVER_DESC,
+	.id_table	= h3600ts_serio_ids,
 	.interrupt	= h3600ts_interrupt,
 	.connect	= h3600ts_connect,
 	.disconnect	= h3600ts_disconnect,
diff -Nru a/drivers/input/touchscreen/hp680_ts_input.c b/drivers/input/touchscreen/hp680_ts_input.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/input/touchscreen/hp680_ts_input.c	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,135 @@
+#include <linux/input.h>
+#include <linux/module.h>
+#include <linux/init.h>
+
+#include <linux/interrupt.h>
+#include <asm/io.h>
+#include <asm/delay.h>
+#include <asm/adc.h>
+#include <asm/hp6xx/hp6xx.h>
+
+#define MODNAME "hp680_ts_input"
+
+#define HP680_TS_ABS_X_MIN	40
+#define HP680_TS_ABS_X_MAX	950
+#define HP680_TS_ABS_Y_MIN	80
+#define HP680_TS_ABS_Y_MAX	910
+
+#define	SCPCR	0xa4000116
+#define	PHDR	0xa400012e
+#define SCPDR	0xa4000136
+
+static void do_softint(void *data);
+
+static struct input_dev hp680_ts_dev;
+static DECLARE_WORK(work, do_softint, 0);
+static char *hp680_ts_name = "HP Jornada touchscreen";
+static char *hp680_ts_phys = "input0";
+
+static void do_softint(void *data)
+{
+	int absx = 0, absy = 0;
+	u8 scpdr;
+	int touched = 0;
+
+	if (ctrl_inb(PHDR) & PHDR_TS_PEN_DOWN) {
+		scpdr = ctrl_inb(SCPDR);
+		scpdr |= SCPDR_TS_SCAN_ENABLE;
+		scpdr &= ~SCPDR_TS_SCAN_Y;
+		ctrl_outb(scpdr, SCPDR);
+		udelay(30);
+
+		absy = adc_single(ADC_CHANNEL_TS_Y);
+
+		scpdr = ctrl_inb(SCPDR);
+		scpdr |= SCPDR_TS_SCAN_Y;
+		scpdr &= ~SCPDR_TS_SCAN_X;
+		ctrl_outb(scpdr, SCPDR);
+		udelay(30);
+
+		absx = adc_single(ADC_CHANNEL_TS_X);
+
+		scpdr = ctrl_inb(SCPDR);
+		scpdr |= SCPDR_TS_SCAN_X;
+		scpdr &= ~SCPDR_TS_SCAN_ENABLE;
+		ctrl_outb(scpdr, SCPDR);
+		udelay(100);
+		touched = ctrl_inb(PHDR) & PHDR_TS_PEN_DOWN;
+	}
+
+	if (touched) {
+		input_report_key(&hp680_ts_dev, BTN_TOUCH, 1);
+		input_report_abs(&hp680_ts_dev, ABS_X, absx);
+		input_report_abs(&hp680_ts_dev, ABS_Y, absy);
+	} else {
+		input_report_key(&hp680_ts_dev, BTN_TOUCH, 0);
+	}
+
+	input_sync(&hp680_ts_dev);
+	enable_irq(HP680_TS_IRQ);
+}
+
+static irqreturn_t hp680_ts_interrupt(int irq, void *dev, struct pt_regs *regs)
+{
+	disable_irq_nosync(irq);
+	schedule_delayed_work(&work, HZ / 20);
+
+	return IRQ_HANDLED;
+}
+
+static int __init hp680_ts_init(void)
+{
+	u8 scpdr;
+	u16 scpcr;
+
+	scpdr = ctrl_inb(SCPDR);
+	scpdr |= SCPDR_TS_SCAN_X | SCPDR_TS_SCAN_Y;
+	scpdr &= ~SCPDR_TS_SCAN_ENABLE;
+	ctrl_outb(scpdr, SCPDR);
+
+	scpcr = ctrl_inw(SCPCR);
+	scpcr &= ~SCPCR_TS_MASK;
+	scpcr |= SCPCR_TS_ENABLE;
+	ctrl_outw(scpcr, SCPCR);
+
+	memset(&hp680_ts_dev, 0, sizeof(hp680_ts_dev));
+	init_input_dev(&hp680_ts_dev);
+
+	hp680_ts_dev.evbit[0] = BIT(EV_ABS) | BIT(EV_KEY);
+	hp680_ts_dev.absbit[0] = BIT(ABS_X) | BIT(ABS_Y);
+	hp680_ts_dev.keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
+
+	hp680_ts_dev.absmin[ABS_X] = HP680_TS_ABS_X_MIN;
+	hp680_ts_dev.absmin[ABS_Y] = HP680_TS_ABS_Y_MIN;
+	hp680_ts_dev.absmax[ABS_X] = HP680_TS_ABS_X_MAX;
+	hp680_ts_dev.absmax[ABS_Y] = HP680_TS_ABS_Y_MAX;
+
+	hp680_ts_dev.name = hp680_ts_name;
+	hp680_ts_dev.phys = hp680_ts_phys;
+	input_register_device(&hp680_ts_dev);
+
+	if (request_irq
+	    (HP680_TS_IRQ, hp680_ts_interrupt, SA_INTERRUPT, MODNAME, 0) < 0) {
+		printk(KERN_ERR "hp680_touchscreen.c : Can't allocate irq %d\n",
+		       HP680_TS_IRQ);
+		input_unregister_device(&hp680_ts_dev);
+		return -EBUSY;
+	}
+
+	return 0;
+}
+
+static void __exit hp680_ts_exit(void)
+{
+	free_irq(HP680_TS_IRQ, 0);
+	cancel_delayed_work(&work);
+	flush_scheduled_work();
+	input_unregister_device(&hp680_ts_dev);
+}
+
+module_init(hp680_ts_init);
+module_exit(hp680_ts_exit);
+
+MODULE_AUTHOR("Andriy Skulysh, askulysh@image.kiev.ua");
+MODULE_DESCRIPTION("HP Jornada 680 touchscreen driver");
+MODULE_LICENSE("GPL");
diff -Nru a/drivers/input/touchscreen/mk712.c b/drivers/input/touchscreen/mk712.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/input/touchscreen/mk712.c	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,222 @@
+/*
+ * ICS MK712 touchscreen controller driver
+ *
+ * Copyright (c) 1999-2002 Transmeta Corporation
+ * Copyright (c) 2005 Rick Koch <n1gp@hotmail.com>
+ * Copyright (c) 2005 Vojtech Pavlik <vojtech@suse.cz>
+ */
+
+/*
+ * 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 driver supports the ICS MicroClock MK712 TouchScreen controller,
+ * found in Gateway AOL Connected Touchpad computers.
+ *
+ * Documentation for ICS MK712 can be found at:
+ * 	http://www.icst.com/pdf/mk712.pdf
+ */
+
+/*
+ * 1999-12-18: original version, Daniel Quinlan
+ * 1999-12-19: added anti-jitter code, report pen-up events, fixed mk712_poll
+ *             to use queue_empty, Nathan Laredo
+ * 1999-12-20: improved random point rejection, Nathan Laredo
+ * 2000-01-05: checked in new anti-jitter code, changed mouse protocol, fixed
+ *             queue code, added module options, other fixes, Daniel Quinlan
+ * 2002-03-15: Clean up for kernel merge <alan@redhat.com>
+ *             Fixed multi open race, fixed memory checks, fixed resource
+ *             allocation, fixed close/powerdown bug, switched to new init
+ * 2005-01-18: Ported to 2.6 from 2.4.28, Rick Koch
+ * 2005-02-05: Rewritten for the input layer, Vojtech Pavlik
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/delay.h>
+#include <linux/ioport.h>
+#include <linux/interrupt.h>
+#include <linux/input.h>
+#include <asm/io.h>
+
+MODULE_AUTHOR("Daniel Quinlan <quinlan@pathname.com>, Vojtech Pavlik <vojtech@suse.cz>");
+MODULE_DESCRIPTION("ICS MicroClock MK712 TouchScreen driver");
+MODULE_LICENSE("GPL");
+
+static unsigned int mk712_io = 0x260;	/* Also 0x200, 0x208, 0x300 */
+module_param_named(io, mk712_io, uint, 0);
+MODULE_PARM_DESC(io, "I/O base address of MK712 touchscreen controller");
+
+static unsigned int mk712_irq = 10;	/* Also 12, 14, 15 */
+module_param_named(irq, mk712_irq, uint, 0);
+MODULE_PARM_DESC(irq, "IRQ of MK712 touchscreen controller");
+
+/* eight 8-bit registers */
+#define MK712_STATUS		0
+#define MK712_X			2
+#define MK712_Y			4
+#define MK712_CONTROL		6
+#define MK712_RATE		7
+
+/* status */
+#define	MK712_STATUS_TOUCH			0x10
+#define	MK712_CONVERSION_COMPLETE		0x80
+
+/* control */
+#define MK712_ENABLE_INT			0x01
+#define MK712_INT_ON_CONVERSION_COMPLETE	0x02
+#define MK712_INT_ON_CHANGE_IN_TOUCH_STATUS	0x04
+#define MK712_ENABLE_PERIODIC_CONVERSIONS	0x10
+#define MK712_READ_ONE_POINT			0x20
+#define MK712_POWERUP				0x40
+
+static int mk712_used = 0;
+static struct input_dev mk712_dev;
+static DEFINE_SPINLOCK(mk712_lock);
+
+static irqreturn_t mk712_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+	unsigned char status;
+	static int debounce = 1;
+	static unsigned short last_x;
+	static unsigned short last_y;
+
+	spin_lock(&mk712_lock);
+	input_regs(&mk712_dev, regs);
+
+	status = inb(mk712_io + MK712_STATUS);
+
+	if (~status & MK712_CONVERSION_COMPLETE) {
+		debounce = 1;
+		goto end;
+	}
+
+	if (~status & MK712_STATUS_TOUCH)
+	{
+		debounce = 1;
+		input_report_key(&mk712_dev, BTN_TOUCH, 0);
+		goto end;
+	}
+
+	if (debounce)
+	{
+		debounce = 0;
+		goto end;
+	}
+
+	input_report_key(&mk712_dev, BTN_TOUCH, 1);
+	input_report_abs(&mk712_dev, ABS_X, last_x);
+	input_report_abs(&mk712_dev, ABS_Y, last_y);
+
+end:
+
+	last_x = inw(mk712_io + MK712_X) & 0x0fff;
+	last_y = inw(mk712_io + MK712_Y) & 0x0fff;
+	input_sync(&mk712_dev);
+	spin_unlock(&mk712_lock);
+	return IRQ_HANDLED;
+}
+
+static int mk712_open(struct input_dev *dev)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&mk712_lock, flags);
+
+	if (!mk712_used++) {
+
+		outb(0, mk712_io + MK712_CONTROL); /* Reset */
+
+		outb(MK712_ENABLE_INT | MK712_INT_ON_CONVERSION_COMPLETE |
+			MK712_INT_ON_CHANGE_IN_TOUCH_STATUS |
+			MK712_ENABLE_PERIODIC_CONVERSIONS |
+			MK712_POWERUP, mk712_io + MK712_CONTROL);
+
+		outb(10, mk712_io + MK712_RATE); /* 187 points per second */
+	}
+
+	spin_unlock_irqrestore(&mk712_lock, flags);
+
+	return 0;
+}
+
+static void mk712_close(struct input_dev *dev)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&mk712_lock, flags);
+
+	if (!--mk712_used)
+		outb(0, mk712_io + MK712_CONTROL);
+
+	spin_unlock_irqrestore(&mk712_lock, flags);
+}
+
+static struct input_dev mk712_dev = {
+	.evbit   = { BIT(EV_KEY) | BIT(EV_ABS) },
+	.keybit  = { [LONG(BTN_TOUCH)] = BIT(BTN_TOUCH) },
+	.absbit  = { BIT(ABS_X) | BIT(ABS_Y) },
+	.open    = mk712_open,
+	.close   = mk712_close,
+	.name    = "ICS MicroClock MK712 TouchScreen",
+	.phys    = "isa0260/input0",
+	.absmin  = { [ABS_X] = 0, [ABS_Y] = 0 },
+	.absmax  = { [ABS_X] = 0xfff, [ABS_Y] = 0xfff },
+	.absfuzz = { [ABS_X] = 88, [ABS_Y] = 88 },
+	.id      = {
+		.bustype = BUS_ISA,
+		.vendor  = 0x0005,
+		.product = 0x0001,
+		.version = 0x0100,
+	},
+};
+
+int __init mk712_init(void)
+{
+
+	if(!request_region(mk712_io, 8, "mk712"))
+	{
+		printk(KERN_WARNING "mk712: unable to get IO region\n");
+		return -ENODEV;
+	}
+
+	outb(0, mk712_io + MK712_CONTROL);
+
+	if ((inw(mk712_io + MK712_X) & 0xf000) ||	/* Sanity check */
+	    (inw(mk712_io + MK712_Y) & 0xf000) ||
+	    (inw(mk712_io + MK712_STATUS) & 0xf333)) {
+		printk(KERN_WARNING "mk712: device not present\n");
+		release_region(mk712_io, 8);
+		return -ENODEV;
+	}
+
+	if(request_irq(mk712_irq, mk712_interrupt, 0, "mk712", &mk712_dev))
+	{
+		printk(KERN_WARNING "mk712: unable to get IRQ\n");
+		release_region(mk712_io, 8);
+		return -EBUSY;
+	}
+
+	input_register_device(&mk712_dev);
+
+	printk(KERN_INFO "input: ICS MicroClock MK712 TouchScreen at %#x irq %d\n", mk712_io, mk712_irq);
+
+	return 0;
+}
+
+static void __exit mk712_exit(void)
+{
+	input_unregister_device(&mk712_dev);
+	free_irq(mk712_irq, &mk712_dev);
+	release_region(mk712_io, 8);
+}
+
+module_init(mk712_init);
+module_exit(mk712_exit);
diff -Nru a/drivers/input/touchscreen/mtouch.c b/drivers/input/touchscreen/mtouch.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/input/touchscreen/mtouch.c	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,219 @@
+/*
+ * MicroTouch (3M) serial touchscreen driver
+ *
+ * Copyright (c) 2004 Vojtech Pavlik
+ */
+
+/*
+ * 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.
+ */
+
+/*
+ * 2005/02/19 Dan Streetman <ddstreet@ieee.org>
+ *   Copied elo.c and edited for MicroTouch protocol
+ */
+
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/input.h>
+#include <linux/serio.h>
+#include <linux/init.h>
+
+#define DRIVER_DESC	"MicroTouch serial touchscreen driver"
+
+MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
+
+/*
+ * Definitions & global arrays.
+ */
+
+#define MTOUCH_FORMAT_TABLET_STATUS_BIT 0x80
+#define MTOUCH_FORMAT_TABLET_TOUCH_BIT 0x40
+#define MTOUCH_FORMAT_TABLET_LENGTH 5
+#define MTOUCH_RESPONSE_BEGIN_BYTE 0x01
+#define MTOUCH_RESPONSE_END_BYTE 0x0d
+
+/* todo: check specs for max length of all responses */
+#define MTOUCH_MAX_LENGTH 16
+
+#define MTOUCH_MIN_XC 0
+#define MTOUCH_MAX_XC 0x3fff
+#define MTOUCH_MIN_YC 0
+#define MTOUCH_MAX_YC 0x3fff
+
+#define MTOUCH_GET_XC(data) (((data[2])<<7) | data[1])
+#define MTOUCH_GET_YC(data) (((data[4])<<7) | data[3])
+#define MTOUCH_GET_TOUCHED(data) (MTOUCH_FORMAT_TABLET_TOUCH_BIT & data[0])
+
+static char *mtouch_name = "MicroTouch Serial TouchScreen";
+
+/*
+ * Per-touchscreen data.
+ */
+
+struct mtouch {
+	struct input_dev dev;
+	struct serio *serio;
+	int idx;
+	unsigned char data[MTOUCH_MAX_LENGTH];
+	char phys[32];
+};
+
+static void mtouch_process_format_tablet(struct mtouch *mtouch, struct pt_regs *regs)
+{
+	struct input_dev *dev = &mtouch->dev;
+
+	if (MTOUCH_FORMAT_TABLET_LENGTH == ++mtouch->idx) {
+		input_regs(dev, regs);
+		input_report_abs(dev, ABS_X, MTOUCH_GET_XC(mtouch->data));
+		input_report_abs(dev, ABS_Y, MTOUCH_MAX_YC - MTOUCH_GET_YC(mtouch->data));
+		input_report_key(dev, BTN_TOUCH, MTOUCH_GET_TOUCHED(mtouch->data));
+		input_sync(dev);
+
+		mtouch->idx = 0;
+	}
+}
+
+static void mtouch_process_response(struct mtouch *mtouch, struct pt_regs *regs)
+{
+	if (MTOUCH_RESPONSE_END_BYTE == mtouch->data[mtouch->idx++]) {
+		/* FIXME - process response */
+		mtouch->idx = 0;
+	} else if (MTOUCH_MAX_LENGTH == mtouch->idx) {
+		printk(KERN_ERR "mtouch.c: too many response bytes\n");
+		mtouch->idx = 0;
+	}
+}
+
+static irqreturn_t mtouch_interrupt(struct serio *serio,
+		unsigned char data, unsigned int flags, struct pt_regs *regs)
+{
+	struct mtouch* mtouch = serio_get_drvdata(serio);
+
+	mtouch->data[mtouch->idx] = data;
+
+	if (MTOUCH_FORMAT_TABLET_STATUS_BIT & mtouch->data[0])
+		mtouch_process_format_tablet(mtouch, regs);
+	else if (MTOUCH_RESPONSE_BEGIN_BYTE == mtouch->data[0])
+		mtouch_process_response(mtouch, regs);
+	else
+		printk(KERN_DEBUG "mtouch.c: unknown/unsynchronized data from device, byte %x\n",mtouch->data[0]);
+
+	return IRQ_HANDLED;
+}
+
+/*
+ * mtouch_disconnect() is the opposite of mtouch_connect()
+ */
+
+static void mtouch_disconnect(struct serio *serio)
+{
+	struct mtouch* mtouch = serio_get_drvdata(serio);
+
+	input_unregister_device(&mtouch->dev);
+	serio_close(serio);
+	serio_set_drvdata(serio, NULL);
+	kfree(mtouch);
+}
+
+/*
+ * mtouch_connect() is the routine that is called when someone adds a
+ * new serio device that supports MicroTouch (Format Tablet) protocol and registers it as
+ * an input device.
+ */
+
+static int mtouch_connect(struct serio *serio, struct serio_driver *drv)
+{
+	struct mtouch *mtouch;
+	int err;
+
+	if (!(mtouch = kmalloc(sizeof(*mtouch), GFP_KERNEL)))
+		return -ENOMEM;
+
+	memset(mtouch, 0, sizeof(*mtouch));
+
+	init_input_dev(&mtouch->dev);
+	mtouch->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
+	mtouch->dev.keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
+
+	input_set_abs_params(&mtouch->dev, ABS_X, MTOUCH_MIN_XC, MTOUCH_MAX_XC, 0, 0);
+	input_set_abs_params(&mtouch->dev, ABS_Y, MTOUCH_MIN_YC, MTOUCH_MAX_YC, 0, 0);
+
+	mtouch->serio = serio;
+
+	sprintf(mtouch->phys, "%s/input0", serio->phys);
+
+	mtouch->dev.private = mtouch;
+	mtouch->dev.name = mtouch_name;
+	mtouch->dev.phys = mtouch->phys;
+	mtouch->dev.id.bustype = BUS_RS232;
+	mtouch->dev.id.vendor = SERIO_MICROTOUCH;
+	mtouch->dev.id.product = 0;
+	mtouch->dev.id.version = 0x0100;
+
+	serio_set_drvdata(serio, mtouch);
+
+	err = serio_open(serio, drv);
+	if (err) {
+		serio_set_drvdata(serio, NULL);
+		kfree(mtouch);
+		return err;
+	}
+
+	input_register_device(&mtouch->dev);
+
+	printk(KERN_INFO "input: %s on %s\n", mtouch->dev.name, serio->phys);
+
+	return 0;
+}
+
+/*
+ * The serio driver structure.
+ */
+
+static struct serio_device_id mtouch_serio_ids[] = {
+	{
+		.type	= SERIO_RS232,
+		.proto	= SERIO_MICROTOUCH,
+		.id	= SERIO_ANY,
+		.extra	= SERIO_ANY,
+	},
+	{ 0 }
+};
+
+MODULE_DEVICE_TABLE(serio, mtouch_serio_ids);
+
+static struct serio_driver mtouch_drv = {
+	.driver		= {
+		.name	= "mtouch",
+	},
+	.description	= DRIVER_DESC,
+	.id_table	= mtouch_serio_ids,
+	.interrupt	= mtouch_interrupt,
+	.connect	= mtouch_connect,
+	.disconnect	= mtouch_disconnect,
+};
+
+/*
+ * The functions for inserting/removing us as a module.
+ */
+
+static int __init mtouch_init(void)
+{
+	serio_register_driver(&mtouch_drv);
+	return 0;
+}
+
+static void __exit mtouch_exit(void)
+{
+	serio_unregister_driver(&mtouch_drv);
+}
+
+module_init(mtouch_init);
+module_exit(mtouch_exit);
diff -Nru a/drivers/input/tsdev.c b/drivers/input/tsdev.c
--- a/drivers/input/tsdev.c	2005-03-11 12:51:51 -08:00
+++ b/drivers/input/tsdev.c	2005-03-11 12:51:51 -08:00
@@ -232,11 +232,9 @@
 static unsigned int tsdev_poll(struct file *file, poll_table * wait)
 {
 	struct tsdev_list *list = file->private_data;
-
 	poll_wait(file, &list->tsdev->wait, wait);
-	if (list->head != list->tail)
-		return POLLIN | POLLRDNORM;
-	return 0;
+	return ((list->head == list->tail) ? 0 : (POLLIN | POLLRDNORM)) |
+		(list->tsdev->exist ? 0 : (POLLHUP | POLLERR));
 }
 
 static int tsdev_ioctl(struct inode *inode, struct file *file,
@@ -265,7 +263,7 @@
 	return retval;
 }
 
-struct file_operations tsdev_fops = {
+static struct file_operations tsdev_fops = {
 	.owner =	THIS_MODULE,
 	.open =		tsdev_open,
 	.release =	tsdev_release,
@@ -426,6 +424,7 @@
 static void tsdev_disconnect(struct input_handle *handle)
 {
 	struct tsdev *tsdev = handle->private;
+	struct tsdev_list *list;
 
 	class_simple_device_remove(MKDEV(INPUT_MAJOR, TSDEV_MINOR_BASE + tsdev->minor));
 	devfs_remove("input/ts%d", tsdev->minor);
@@ -435,6 +434,8 @@
 	if (tsdev->open) {
 		input_close_device(handle);
 		wake_up_interruptible(&tsdev->wait);
+		list_for_each_entry(list, &tsdev->list, node)
+			kill_fasync(&list->fasync, SIGIO, POLL_HUP);
 	} else
 		tsdev_free(tsdev);
 }
diff -Nru a/drivers/isdn/Makefile b/drivers/isdn/Makefile
--- a/drivers/isdn/Makefile	2005-03-11 12:51:51 -08:00
+++ b/drivers/isdn/Makefile	2005-03-11 12:51:51 -08:00
@@ -13,4 +13,3 @@
 obj-$(CONFIG_ISDN_DRV_LOOP)		+= isdnloop/
 obj-$(CONFIG_ISDN_DRV_ACT2000)		+= act2000/
 obj-$(CONFIG_HYSDN)			+= hysdn/
-obj-$(CONFIG_ISDN_DRV_TPAM)		+= tpam/
diff -Nru a/drivers/isdn/hisax/Kconfig b/drivers/isdn/hisax/Kconfig
--- a/drivers/isdn/hisax/Kconfig	2005-03-11 12:51:50 -08:00
+++ b/drivers/isdn/hisax/Kconfig	2005-03-11 12:51:50 -08:00
@@ -411,6 +411,12 @@
 	help
 	  This enables the driver for HFC USB based ISDN modems.
 
+config HISAX_HFC4S8S
+	tristate "HFC-4S/8S based ISDN cards (EXPERIMENTAL)"
+	depends on EXPERIMENTAL
+	help
+	  This enables the driver for HFC-4S/8S based ISDN cards.
+
 config HISAX_FRITZ_PCIPNP
 	tristate "AVM Fritz!Card PCI/PCIv2/PnP support (EXPERIMENTAL)"
 	depends on PCI && EXPERIMENTAL
diff -Nru a/drivers/isdn/hisax/Makefile b/drivers/isdn/hisax/Makefile
--- a/drivers/isdn/hisax/Makefile	2005-03-11 12:51:42 -08:00
+++ b/drivers/isdn/hisax/Makefile	2005-03-11 12:51:42 -08:00
@@ -13,6 +13,7 @@
 obj-$(CONFIG_HISAX_TELES_CS)		+= teles_cs.o
 obj-$(CONFIG_HISAX_ST5481)		+= hisax_st5481.o
 obj-$(CONFIG_HISAX_HFCUSB)		+= hfc_usb.o
+obj-$(CONFIG_HISAX_HFC4S8S)		+= hfc4s8s_l1.o
 obj-$(CONFIG_HISAX_FRITZ_PCIPNP)        += hisax_isac.o hisax_fcpcipnp.o
 
 ifdef CONFIG_HISAX_HDLC
diff -Nru a/drivers/isdn/hisax/hfc4s8s_l1.c b/drivers/isdn/hisax/hfc4s8s_l1.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/isdn/hisax/hfc4s8s_l1.c	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,1714 @@
+/*************************************************************************/
+/* $Id: hfc4s8s_l1.c,v 1.10 2005/02/09 16:31:09 martinb1 Exp $           */
+/* HFC-4S/8S low layer interface for Cologne Chip HFC-4S/8S isdn chips   */
+/* The low layer (L1) is implemented as a loadable module for usage with */
+/* the HiSax isdn driver for passive cards.                              */
+/*                                                                       */
+/* Author: Werner Cornelius                                              */
+/* (C) 2003 Cornelius Consult (werner@cornelius-consult.de)              */
+/*                                                                       */
+/* Driver maintained by Cologne Chip                                     */
+/*   - Martin Bachem, support@colognechip.com                            */
+/*                                                                       */
+/* This driver only works with chip revisions >= 1, older revision 0     */
+/* engineering samples (only first manufacturer sample cards) will not   */
+/* work and are rejected by the driver.                                  */
+/*                                                                       */
+/* This file distributed under the GNU GPL.                              */
+/*                                                                       */
+/* See Version History at the end of this file                           */
+/*                                                                       */
+/*************************************************************************/
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/config.h>
+#include <linux/pci.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/timer.h>
+#include <linux/skbuff.h>
+#include <linux/wait.h>
+#include "hisax_if.h"
+#include "hfc4s8s_l1.h"
+
+static const char hfc4s8s_rev[] = "Revision: 1.10";
+
+/***************************************************************/
+/* adjustable transparent mode fifo threshold                  */
+/* The value defines the used fifo threshold with the equation */
+/*                                                             */
+/* notify number of bytes = 2 * 2 ^ TRANS_FIFO_THRES           */
+/*                                                             */
+/* The default value is 5 which results in a buffer size of 64 */
+/* and an interrupt rate of 8ms.                               */
+/* The maximum value is 7 due to fifo size restrictions.       */
+/* Values below 3-4 are not recommended due to high interrupt  */
+/* load of the processor. For non critical applications the    */
+/* value should be raised to 7 to reduce any interrupt overhead*/
+/***************************************************************/
+#define TRANS_FIFO_THRES 5
+
+/*************/
+/* constants */
+/*************/
+#define CLOCKMODE_0     0	/* ext. 24.576 MhZ clk freq, int. single clock mode */
+#define CLOCKMODE_1     1	/* ext. 49.576 MhZ clk freq, int. single clock mode */
+#define CHIP_ID_SHIFT   4
+#define HFC_MAX_ST 8
+#define MAX_D_FRAME_SIZE 270
+#define MAX_B_FRAME_SIZE 1536
+#define TRANS_TIMER_MODE (TRANS_FIFO_THRES & 0xf)
+#define TRANS_FIFO_BYTES (2 << TRANS_FIFO_THRES)
+#define MAX_F_CNT 0x0f
+
+#define CLKDEL_NT 0x6c
+#define CLKDEL_TE 0xf
+#define CTRL0_NT  4
+#define CTRL0_TE  0
+
+#define L1_TIMER_T4 2		/* minimum in jiffies */
+#define L1_TIMER_T3 (7 * HZ)	/* activation timeout */
+#define L1_TIMER_T1 ((120 * HZ) / 1000)	/* NT mode deactivation timeout */
+
+
+/******************/
+/* types and vars */
+/******************/
+static int card_cnt;
+
+/* private driver_data */
+typedef struct {
+	int chip_id;
+	int clock_mode;
+	int max_st_ports;
+	char *device_name;
+} hfc4s8s_param;
+
+static struct pci_device_id hfc4s8s_ids[] = {
+	{.vendor = PCI_VENDOR_ID_CCD,
+	 .device = PCI_DEVICE_ID_4S,
+	 .subvendor = 0x1397,
+	 .subdevice = 0x08b4,
+	 .driver_data =
+	 (unsigned long) &((hfc4s8s_param) {CHIP_ID_4S, CLOCKMODE_0, 4,
+					    "HFC-4S Evaluation Board"}),
+	 },
+	{.vendor = PCI_VENDOR_ID_CCD,
+	 .device = PCI_DEVICE_ID_8S,
+	 .subvendor = 0x1397,
+	 .subdevice = 0x16b8,
+	 .driver_data =
+	 (unsigned long) &((hfc4s8s_param) {CHIP_ID_8S, CLOCKMODE_0, 8,
+					    "HFC-8S Evaluation Board"}),
+	 },
+	{.vendor = PCI_VENDOR_ID_CCD,
+	 .device = PCI_DEVICE_ID_4S,
+	 .subvendor = 0x1397,
+	 .subdevice = 0xb520,
+	 .driver_data =
+	 (unsigned long) &((hfc4s8s_param) {CHIP_ID_4S, CLOCKMODE_1, 4,
+					    "IOB4ST"}),
+	 },
+	{.vendor = PCI_VENDOR_ID_CCD,
+	 .device = PCI_DEVICE_ID_8S,
+	 .subvendor = 0x1397,
+	 .subdevice = 0xb522,
+	 .driver_data =
+	 (unsigned long) &((hfc4s8s_param) {CHIP_ID_8S, CLOCKMODE_1, 8,
+					    "IOB8ST"}),
+	 },
+	{}
+};
+
+MODULE_DEVICE_TABLE(pci, hfc4s8s_ids);
+
+MODULE_AUTHOR("Werner Cornelius, werner@cornelius-consult.de");
+MODULE_DESCRIPTION("ISDN layer 1 for Cologne Chip HFC-4S/8S chips");
+MODULE_LICENSE("GPL");
+
+/***********/
+/* layer 1 */
+/***********/
+struct hfc4s8s_btype {
+	spinlock_t lock;
+	struct hisax_b_if b_if;
+	struct hfc4s8s_l1 *l1p;
+	struct sk_buff_head tx_queue;
+	struct sk_buff *tx_skb;
+	struct sk_buff *rx_skb;
+	__u8 *rx_ptr;
+	int tx_cnt;
+	int bchan;
+	int mode;
+};
+
+struct _hfc4s8s_hw;
+
+struct hfc4s8s_l1 {
+	spinlock_t lock;
+	struct _hfc4s8s_hw *hw;	/* pointer to hardware area */
+	int l1_state;		/* actual l1 state */
+	struct timer_list l1_timer;	/* layer 1 timer structure */
+	int nt_mode;		/* set to nt mode */
+	int st_num;		/* own index */
+	int enabled;		/* interface is enabled */
+	struct sk_buff_head d_tx_queue;	/* send queue */
+	int tx_cnt;		/* bytes to send */
+	struct hisax_d_if d_if;	/* D-channel interface */
+	struct hfc4s8s_btype b_ch[2];	/* B-channel data */
+	struct hisax_b_if *b_table[2];
+};
+
+/**********************/
+/* hardware structure */
+/**********************/
+typedef struct _hfc4s8s_hw {
+	spinlock_t lock;
+
+	int cardnum;
+	int ifnum;
+	int iobase;
+	int nt_mode;
+	u_char *membase;
+	u_char *hw_membase;
+	void *pdev;
+	int max_fifo;
+	hfc4s8s_param driver_data;
+	int irq;
+	int fifo_sched_cnt;
+	struct work_struct tqueue;
+	struct hfc4s8s_l1 l1[HFC_MAX_ST];
+	char card_name[60];
+	struct {
+		u_char r_irq_ctrl;
+		u_char r_ctrl0;
+		volatile u_char r_irq_statech;	/* active isdn l1 status */
+		u_char r_irqmsk_statchg;	/* enabled isdn status ints */
+		u_char r_irq_fifo_blx[8];	/* fifo status registers */
+		u_char fifo_rx_trans_enables[8];	/* mask for enabled transparent rx fifos */
+		u_char fifo_slow_timer_service[8];	/* mask for fifos needing slower timer service */
+		volatile u_char r_irq_oview;	/* contents of overview register */
+		volatile u_char timer_irq;
+		int timer_usg_cnt;	/* number of channels using timer */
+	} mr;
+} hfc4s8s_hw;
+
+
+
+/***************************/
+/* inline function defines */
+/***************************/
+#ifdef CONFIG_HISAX_HFC4S8S_PCIMEM	/* inline functions mempry mapped */
+
+/* memory write and dummy IO read to avoid PCI byte merge problems */
+#define Write_hfc8(a,b,c) {(*((volatile u_char *)(a->membase+b)) = c); inb(a->iobase+4);}
+/* memory write without dummy IO access for fifo data access */
+#define fWrite_hfc8(a,b,c) (*((volatile u_char *)(a->membase+b)) = c)
+#define Read_hfc8(a,b) (*((volatile u_char *)(a->membase+b)))
+#define Write_hfc16(a,b,c) (*((volatile unsigned short *)(a->membase+b)) = c)
+#define Read_hfc16(a,b) (*((volatile unsigned short *)(a->membase+b)))
+#define Write_hfc32(a,b,c) (*((volatile unsigned long *)(a->membase+b)) = c)
+#define Read_hfc32(a,b) (*((volatile unsigned long *)(a->membase+b)))
+#define wait_busy(a) {while ((Read_hfc8(a, R_STATUS) & M_BUSY));}
+#define PCI_ENA_MEMIO	0x03
+
+#else
+
+/* inline functions io mapped */
+static inline void
+SetRegAddr(hfc4s8s_hw * a, u_char b)
+{
+	outb(b, (a->iobase) + 4);
+}
+
+static inline u_char
+GetRegAddr(hfc4s8s_hw * a)
+{
+	return (inb((volatile u_int) (a->iobase + 4)));
+}
+
+
+static inline void
+Write_hfc8(hfc4s8s_hw * a, u_char b, u_char c)
+{
+	SetRegAddr(a, b);
+	outb(c, a->iobase);
+}
+
+static inline void
+fWrite_hfc8(hfc4s8s_hw * a, u_char c)
+{
+	outb(c, a->iobase);
+}
+
+static inline void
+Write_hfc16(hfc4s8s_hw * a, u_char b, u_short c)
+{
+	SetRegAddr(a, b);
+	outw(c, a->iobase);
+}
+
+static inline void
+Write_hfc32(hfc4s8s_hw * a, u_char b, u_long c)
+{
+	SetRegAddr(a, b);
+	outl(c, a->iobase);
+}
+
+static inline void
+fWrite_hfc32(hfc4s8s_hw * a, u_long c)
+{
+	outl(c, a->iobase);
+}
+
+static inline u_char
+Read_hfc8(hfc4s8s_hw * a, u_char b)
+{
+	SetRegAddr(a, b);
+	return (inb((volatile u_int) a->iobase));
+}
+
+static inline u_char
+fRead_hfc8(hfc4s8s_hw * a)
+{
+	return (inb((volatile u_int) a->iobase));
+}
+
+
+static inline u_short
+Read_hfc16(hfc4s8s_hw * a, u_char b)
+{
+	SetRegAddr(a, b);
+	return (inw((volatile u_int) a->iobase));
+}
+
+static inline u_long
+Read_hfc32(hfc4s8s_hw * a, u_char b)
+{
+	SetRegAddr(a, b);
+	return (inl((volatile u_int) a->iobase));
+}
+
+static inline u_long
+fRead_hfc32(hfc4s8s_hw * a)
+{
+	return (inl((volatile u_int) a->iobase));
+}
+
+static inline void
+wait_busy(hfc4s8s_hw * a)
+{
+	SetRegAddr(a, R_STATUS);
+	while (inb((volatile u_int) a->iobase) & M_BUSY);
+}
+
+#define PCI_ENA_REGIO	0x01
+
+#endif				/* CONFIG_HISAX_HFC4S8S_PCIMEM */
+
+/******************************************************/
+/* function to read critical counter registers that   */
+/* may be udpated by the chip during read             */
+/******************************************************/
+static volatile u_char
+Read_hfc8_stable(hfc4s8s_hw * hw, int reg)
+{
+	u_char ref8;
+	u_char in8;
+	ref8 = Read_hfc8(hw, reg);
+	while (((in8 = Read_hfc8(hw, reg)) != ref8)) {
+		ref8 = in8;
+	}
+	return in8;
+}
+
+static volatile int
+Read_hfc16_stable(hfc4s8s_hw * hw, int reg)
+{
+	int ref16;
+	int in16;
+
+	ref16 = Read_hfc16(hw, reg);
+	while (((in16 = Read_hfc16(hw, reg)) != ref16)) {
+		ref16 = in16;
+	}
+	return in16;
+}
+
+/*****************************/
+/* D-channel call from HiSax */
+/*****************************/
+static void
+dch_l2l1(struct hisax_d_if *iface, int pr, void *arg)
+{
+	struct hfc4s8s_l1 *l1 = iface->ifc.priv;
+	struct sk_buff *skb = (struct sk_buff *) arg;
+	u_long flags;
+
+	switch (pr) {
+
+		case (PH_DATA | REQUEST):
+			if (!l1->enabled) {
+				dev_kfree_skb(skb);
+				break;
+			}
+			spin_lock_irqsave(&l1->lock, flags);
+			skb_queue_tail(&l1->d_tx_queue, skb);
+			if ((skb_queue_len(&l1->d_tx_queue) == 1) &&
+			    (l1->tx_cnt <= 0)) {
+				l1->hw->mr.r_irq_fifo_blx[l1->st_num] |=
+				    0x10;
+				spin_unlock_irqrestore(&l1->lock, flags);
+				schedule_work(&l1->hw->tqueue);
+			} else
+				spin_unlock_irqrestore(&l1->lock, flags);
+			break;
+
+		case (PH_ACTIVATE | REQUEST):
+			if (!l1->enabled)
+				break;
+			if (!l1->nt_mode) {
+				if (l1->l1_state < 6) {
+					spin_lock_irqsave(&l1->lock,
+							  flags);
+
+					Write_hfc8(l1->hw, R_ST_SEL,
+						   l1->st_num);
+					Write_hfc8(l1->hw, A_ST_WR_STA,
+						   0x60);
+					mod_timer(&l1->l1_timer,
+						  jiffies + L1_TIMER_T3);
+					spin_unlock_irqrestore(&l1->lock,
+							       flags);
+				} else if (l1->l1_state == 7)
+					l1->d_if.ifc.l1l2(&l1->d_if.ifc,
+							  PH_ACTIVATE |
+							  INDICATION,
+							  NULL);
+			} else {
+				if (l1->l1_state != 3) {
+					spin_lock_irqsave(&l1->lock,
+							  flags);
+					Write_hfc8(l1->hw, R_ST_SEL,
+						   l1->st_num);
+					Write_hfc8(l1->hw, A_ST_WR_STA,
+						   0x60);
+					spin_unlock_irqrestore(&l1->lock,
+							       flags);
+				} else if (l1->l1_state == 3)
+					l1->d_if.ifc.l1l2(&l1->d_if.ifc,
+							  PH_ACTIVATE |
+							  INDICATION,
+							  NULL);
+			}
+			break;
+
+		default:
+			printk(KERN_INFO
+			       "HFC-4S/8S: Unknown D-chan cmd 0x%x received, ignored\n",
+			       pr);
+			break;
+	}
+	if (!l1->enabled)
+		l1->d_if.ifc.l1l2(&l1->d_if.ifc,
+				  PH_DEACTIVATE | INDICATION, NULL);
+}				/* dch_l2l1 */
+
+/*****************************/
+/* B-channel call from HiSax */
+/*****************************/
+static void
+bch_l2l1(struct hisax_if *ifc, int pr, void *arg)
+{
+	struct hfc4s8s_btype *bch = ifc->priv;
+	struct hfc4s8s_l1 *l1 = bch->l1p;
+	struct sk_buff *skb = (struct sk_buff *) arg;
+	int mode = (int) arg;
+	u_long flags;
+
+	switch (pr) {
+
+		case (PH_DATA | REQUEST):
+			if (!l1->enabled || (bch->mode == L1_MODE_NULL)) {
+				dev_kfree_skb(skb);
+				break;
+			}
+			spin_lock_irqsave(&l1->lock, flags);
+			skb_queue_tail(&bch->tx_queue, skb);
+			if (!bch->tx_skb && (bch->tx_cnt <= 0)) {
+				l1->hw->mr.r_irq_fifo_blx[l1->st_num] |=
+				    ((bch->bchan == 1) ? 1 : 4);
+				spin_unlock_irqrestore(&l1->lock, flags);
+				schedule_work(&l1->hw->tqueue);
+			} else
+				spin_unlock_irqrestore(&l1->lock, flags);
+			break;
+
+		case (PH_ACTIVATE | REQUEST):
+		case (PH_DEACTIVATE | REQUEST):
+			if (!l1->enabled)
+				break;
+			if (pr == (PH_DEACTIVATE | REQUEST))
+				mode = L1_MODE_NULL;
+
+			switch (mode) {
+				case L1_MODE_HDLC:
+					spin_lock_irqsave(&l1->lock,
+							  flags);
+					l1->hw->mr.timer_usg_cnt++;
+					l1->hw->mr.
+					    fifo_slow_timer_service[l1->
+								    st_num]
+					    |=
+					    ((bch->bchan ==
+					      1) ? 0x2 : 0x8);
+					Write_hfc8(l1->hw, R_FIFO,
+						   (l1->st_num * 8 +
+						    ((bch->bchan ==
+						      1) ? 0 : 2)));
+					wait_busy(l1->hw);
+					Write_hfc8(l1->hw, A_CON_HDLC, 0xc);	/* HDLC mode, flag fill, connect ST */
+					Write_hfc8(l1->hw, A_SUBCH_CFG, 0);	/* 8 bits */
+					Write_hfc8(l1->hw, A_IRQ_MSK, 1);	/* enable TX interrupts for hdlc */
+					Write_hfc8(l1->hw, A_INC_RES_FIFO, 2);	/* reset fifo */
+					wait_busy(l1->hw);
+
+					Write_hfc8(l1->hw, R_FIFO,
+						   (l1->st_num * 8 +
+						    ((bch->bchan ==
+						      1) ? 1 : 3)));
+					wait_busy(l1->hw);
+					Write_hfc8(l1->hw, A_CON_HDLC, 0xc);	/* HDLC mode, flag fill, connect ST */
+					Write_hfc8(l1->hw, A_SUBCH_CFG, 0);	/* 8 bits */
+					Write_hfc8(l1->hw, A_IRQ_MSK, 1);	/* enable RX interrupts for hdlc */
+					Write_hfc8(l1->hw, A_INC_RES_FIFO, 2);	/* reset fifo */
+
+					Write_hfc8(l1->hw, R_ST_SEL,
+						   l1->st_num);
+					l1->hw->mr.r_ctrl0 |=
+					    (bch->bchan & 3);
+					Write_hfc8(l1->hw, A_ST_CTRL0,
+						   l1->hw->mr.r_ctrl0);
+					bch->mode = L1_MODE_HDLC;
+					spin_unlock_irqrestore(&l1->lock,
+							       flags);
+
+					bch->b_if.ifc.l1l2(&bch->b_if.ifc,
+							   PH_ACTIVATE |
+							   INDICATION,
+							   NULL);
+					break;
+
+				case L1_MODE_TRANS:
+					spin_lock_irqsave(&l1->lock,
+							  flags);
+					l1->hw->mr.
+					    fifo_rx_trans_enables[l1->
+								  st_num]
+					    |=
+					    ((bch->bchan ==
+					      1) ? 0x2 : 0x8);
+					l1->hw->mr.timer_usg_cnt++;
+					Write_hfc8(l1->hw, R_FIFO,
+						   (l1->st_num * 8 +
+						    ((bch->bchan ==
+						      1) ? 0 : 2)));
+					wait_busy(l1->hw);
+					Write_hfc8(l1->hw, A_CON_HDLC, 0xf);	/* Transparent mode, 1 fill, connect ST */
+					Write_hfc8(l1->hw, A_SUBCH_CFG, 0);	/* 8 bits */
+					Write_hfc8(l1->hw, A_IRQ_MSK, 0);	/* disable TX interrupts */
+					Write_hfc8(l1->hw, A_INC_RES_FIFO, 2);	/* reset fifo */
+					wait_busy(l1->hw);
+
+					Write_hfc8(l1->hw, R_FIFO,
+						   (l1->st_num * 8 +
+						    ((bch->bchan ==
+						      1) ? 1 : 3)));
+					wait_busy(l1->hw);
+					Write_hfc8(l1->hw, A_CON_HDLC, 0xf);	/* Transparent mode, 1 fill, connect ST */
+					Write_hfc8(l1->hw, A_SUBCH_CFG, 0);	/* 8 bits */
+					Write_hfc8(l1->hw, A_IRQ_MSK, 0);	/* disable RX interrupts */
+					Write_hfc8(l1->hw, A_INC_RES_FIFO, 2);	/* reset fifo */
+
+					Write_hfc8(l1->hw, R_ST_SEL,
+						   l1->st_num);
+					l1->hw->mr.r_ctrl0 |=
+					    (bch->bchan & 3);
+					Write_hfc8(l1->hw, A_ST_CTRL0,
+						   l1->hw->mr.r_ctrl0);
+					bch->mode = L1_MODE_TRANS;
+					spin_unlock_irqrestore(&l1->lock,
+							       flags);
+
+					bch->b_if.ifc.l1l2(&bch->b_if.ifc,
+							   PH_ACTIVATE |
+							   INDICATION,
+							   NULL);
+					break;
+
+				default:
+					if (bch->mode == L1_MODE_NULL)
+						break;
+					spin_lock_irqsave(&l1->lock,
+							  flags);
+					l1->hw->mr.
+					    fifo_slow_timer_service[l1->
+								    st_num]
+					    &=
+					    ~((bch->bchan ==
+					       1) ? 0x3 : 0xc);
+					l1->hw->mr.
+					    fifo_rx_trans_enables[l1->
+								  st_num]
+					    &=
+					    ~((bch->bchan ==
+					       1) ? 0x3 : 0xc);
+					l1->hw->mr.timer_usg_cnt--;
+					Write_hfc8(l1->hw, R_FIFO,
+						   (l1->st_num * 8 +
+						    ((bch->bchan ==
+						      1) ? 0 : 2)));
+					wait_busy(l1->hw);
+					Write_hfc8(l1->hw, A_IRQ_MSK, 0);	/* disable TX interrupts */
+					wait_busy(l1->hw);
+					Write_hfc8(l1->hw, R_FIFO,
+						   (l1->st_num * 8 +
+						    ((bch->bchan ==
+						      1) ? 1 : 3)));
+					wait_busy(l1->hw);
+					Write_hfc8(l1->hw, A_IRQ_MSK, 0);	/* disable RX interrupts */
+					Write_hfc8(l1->hw, R_ST_SEL,
+						   l1->st_num);
+					l1->hw->mr.r_ctrl0 &=
+					    ~(bch->bchan & 3);
+					Write_hfc8(l1->hw, A_ST_CTRL0,
+						   l1->hw->mr.r_ctrl0);
+					spin_unlock_irqrestore(&l1->lock,
+							       flags);
+
+					bch->mode = L1_MODE_NULL;
+					bch->b_if.ifc.l1l2(&bch->b_if.ifc,
+							   PH_DEACTIVATE |
+							   INDICATION,
+							   NULL);
+					if (bch->tx_skb) {
+						dev_kfree_skb(bch->tx_skb);
+						bch->tx_skb = NULL;
+					}
+					if (bch->rx_skb) {
+						dev_kfree_skb(bch->rx_skb);
+						bch->rx_skb = NULL;
+					}
+					skb_queue_purge(&bch->tx_queue);
+					bch->tx_cnt = 0;
+					bch->rx_ptr = NULL;
+					break;
+			}
+
+			/* timer is only used when at least one b channel */
+			/* is set up to transparent mode */
+			if (l1->hw->mr.timer_usg_cnt) {
+				Write_hfc8(l1->hw, R_IRQMSK_MISC,
+					   M_TI_IRQMSK);
+			} else {
+				Write_hfc8(l1->hw, R_IRQMSK_MISC, 0);
+			}
+
+			break;
+
+		default:
+			printk(KERN_INFO
+			       "HFC-4S/8S: Unknown B-chan cmd 0x%x received, ignored\n",
+			       pr);
+			break;
+	}
+	if (!l1->enabled)
+		bch->b_if.ifc.l1l2(&bch->b_if.ifc,
+				   PH_DEACTIVATE | INDICATION, NULL);
+}				/* bch_l2l1 */
+
+/**************************/
+/* layer 1 timer function */
+/**************************/
+static void
+hfc_l1_timer(struct hfc4s8s_l1 *l1)
+{
+	u_long flags;
+
+	if (!l1->enabled)
+		return;
+
+	spin_lock_irqsave(&l1->lock, flags);
+	if (l1->nt_mode) {
+		l1->l1_state = 1;
+		Write_hfc8(l1->hw, R_ST_SEL, l1->st_num);
+		Write_hfc8(l1->hw, A_ST_WR_STA, 0x11);
+		spin_unlock_irqrestore(&l1->lock, flags);
+		l1->d_if.ifc.l1l2(&l1->d_if.ifc,
+				  PH_DEACTIVATE | INDICATION, NULL);
+		spin_lock_irqsave(&l1->lock, flags);
+		l1->l1_state = 1;
+		Write_hfc8(l1->hw, A_ST_WR_STA, 0x1);
+		spin_unlock_irqrestore(&l1->lock, flags);
+	} else {
+		/* activation timed out */
+		Write_hfc8(l1->hw, R_ST_SEL, l1->st_num);
+		Write_hfc8(l1->hw, A_ST_WR_STA, 0x13);
+		spin_unlock_irqrestore(&l1->lock, flags);
+		l1->d_if.ifc.l1l2(&l1->d_if.ifc,
+				  PH_DEACTIVATE | INDICATION, NULL);
+		spin_lock_irqsave(&l1->lock, flags);
+		Write_hfc8(l1->hw, R_ST_SEL, l1->st_num);
+		Write_hfc8(l1->hw, A_ST_WR_STA, 0x3);
+		spin_unlock_irqrestore(&l1->lock, flags);
+	}
+}				/* hfc_l1_timer */
+
+/****************************************/
+/* a complete D-frame has been received */
+/****************************************/
+static void
+rx_d_frame(struct hfc4s8s_l1 *l1p, int ech)
+{
+	int z1, z2;
+	u_char f1, f2, df;
+	struct sk_buff *skb;
+	u_char *cp;
+
+
+	if (!l1p->enabled)
+		return;
+	do {
+		/* E/D RX fifo */
+		Write_hfc8(l1p->hw, R_FIFO,
+			   (l1p->st_num * 8 + ((ech) ? 7 : 5)));
+		wait_busy(l1p->hw);
+
+		f1 = Read_hfc8_stable(l1p->hw, A_F1);
+		f2 = Read_hfc8(l1p->hw, A_F2);
+		df = f1 - f2;
+		if ((f1 - f2) < 0)
+			df = f1 - f2 + MAX_F_CNT + 1;
+
+
+		if (!df) {
+			return;	/* no complete frame in fifo */
+		}
+
+		z1 = Read_hfc16_stable(l1p->hw, A_Z1);
+		z2 = Read_hfc16(l1p->hw, A_Z2);
+
+		z1 = z1 - z2 + 1;
+		if (z1 < 0)
+			z1 += 384;
+
+		if (!(skb = dev_alloc_skb(MAX_D_FRAME_SIZE))) {
+			printk(KERN_INFO
+			       "HFC-4S/8S: Could not allocate D/E "
+			       "channel receive buffer");
+			Write_hfc8(l1p->hw, A_INC_RES_FIFO, 2);
+			wait_busy(l1p->hw);
+			return;
+		}
+
+		if (((z1 < 4) || (z1 > MAX_D_FRAME_SIZE))) {
+			if (skb)
+				dev_kfree_skb(skb);
+			/* remove errornous D frame */
+			if (df == 1) {
+				/* reset fifo */
+				Write_hfc8(l1p->hw, A_INC_RES_FIFO, 2);
+				wait_busy(l1p->hw);
+				return;
+			} else {
+				/* read errornous D frame */
+
+#ifndef CONFIG_HISAX_HFC4S8S_PCIMEM
+				SetRegAddr(l1p->hw, A_FIFO_DATA0);
+#endif
+
+				while (z1 >= 4) {
+#ifdef CONFIG_HISAX_HFC4S8S_PCIMEM
+					Read_hfc32(l1p->hw, A_FIFO_DATA0);
+#else
+					fRead_hfc32(l1p->hw);
+#endif
+					z1 -= 4;
+				}
+
+				while (z1--)
+#ifdef CONFIG_HISAX_HFC4S8S_PCIMEM
+					Read_hfc8(l1p->hw, A_FIFO_DATA0);
+#else
+					fRead_hfc8(l1p->hw);
+#endif
+
+				Write_hfc8(l1p->hw, A_INC_RES_FIFO, 1);
+				wait_busy(l1p->hw);
+				return;
+			}
+		}
+
+		cp = skb->data;
+
+#ifndef CONFIG_HISAX_HFC4S8S_PCIMEM
+		SetRegAddr(l1p->hw, A_FIFO_DATA0);
+#endif
+
+		while (z1 >= 4) {
+#ifdef CONFIG_HISAX_HFC4S8S_PCIMEM
+			*((unsigned long *) cp) =
+			    Read_hfc32(l1p->hw, A_FIFO_DATA0);
+#else
+			*((unsigned long *) cp) = fRead_hfc32(l1p->hw);
+#endif
+			cp += 4;
+			z1 -= 4;
+		}
+
+		while (z1--)
+#ifdef CONFIG_HISAX_HFC4S8S_PCIMEM
+			*cp++ = Read_hfc8(l1p->hw, A_FIFO_DATA0);
+#else
+			*cp++ = fRead_hfc8(l1p->hw);
+#endif
+
+		Write_hfc8(l1p->hw, A_INC_RES_FIFO, 1);	/* increment f counter */
+		wait_busy(l1p->hw);
+
+		if (*(--cp)) {
+			dev_kfree_skb(skb);
+		} else {
+			skb->len = (cp - skb->data) - 2;
+			if (ech)
+				l1p->d_if.ifc.l1l2(&l1p->d_if.ifc,
+						   PH_DATA_E | INDICATION,
+						   skb);
+			else
+				l1p->d_if.ifc.l1l2(&l1p->d_if.ifc,
+						   PH_DATA | INDICATION,
+						   skb);
+		}
+	} while (1);
+}				/* rx_d_frame */
+
+/*************************************************************/
+/* a B-frame has been received (perhaps not fully completed) */
+/*************************************************************/
+static void
+rx_b_frame(struct hfc4s8s_btype *bch)
+{
+	int z1, z2, hdlc_complete;
+	u_char f1, f2;
+	struct hfc4s8s_l1 *l1 = bch->l1p;
+	struct sk_buff *skb;
+
+	if (!l1->enabled || (bch->mode == L1_MODE_NULL))
+		return;
+
+	do {
+		/* RX Fifo */
+		Write_hfc8(l1->hw, R_FIFO,
+			   (l1->st_num * 8 + ((bch->bchan == 1) ? 1 : 3)));
+		wait_busy(l1->hw);
+
+		if (bch->mode == L1_MODE_HDLC) {
+			f1 = Read_hfc8_stable(l1->hw, A_F1);
+			f2 = Read_hfc8(l1->hw, A_F2);
+			hdlc_complete = ((f1 ^ f2) & MAX_F_CNT);
+		} else
+			hdlc_complete = 0;
+		z1 = Read_hfc16_stable(l1->hw, A_Z1);
+		z2 = Read_hfc16(l1->hw, A_Z2);
+		z1 = (z1 - z2);
+		if (hdlc_complete)
+			z1++;
+		if (z1 < 0)
+			z1 += 384;
+
+		if (!z1)
+			break;
+
+		if (!(skb = bch->rx_skb)) {
+			if (!
+			    (skb =
+			     dev_alloc_skb((bch->mode ==
+					    L1_MODE_TRANS) ? z1
+					   : (MAX_B_FRAME_SIZE + 3)))) {
+				printk(KERN_ERR
+				       "HFC-4S/8S: Could not allocate B "
+				       "channel receive buffer");
+				return;
+			}
+			bch->rx_ptr = skb->data;
+			bch->rx_skb = skb;
+		}
+
+		skb->len = (bch->rx_ptr - skb->data) + z1;
+
+		/* HDLC length check */
+		if ((bch->mode == L1_MODE_HDLC) &&
+		    ((hdlc_complete && (skb->len < 4)) ||
+		     (skb->len > (MAX_B_FRAME_SIZE + 3)))) {
+
+			skb->len = 0;
+			bch->rx_ptr = skb->data;
+			Write_hfc8(l1->hw, A_INC_RES_FIFO, 2);	/* reset fifo */
+			wait_busy(l1->hw);
+			return;
+		}
+#ifndef CONFIG_HISAX_HFC4S8S_PCIMEM
+		SetRegAddr(l1->hw, A_FIFO_DATA0);
+#endif
+
+		while (z1 >= 4) {
+#ifdef CONFIG_HISAX_HFC4S8S_PCIMEM
+			*((unsigned long *) bch->rx_ptr) =
+			    Read_hfc32(l1->hw, A_FIFO_DATA0);
+#else
+			*((unsigned long *) bch->rx_ptr) =
+			    fRead_hfc32(l1->hw);
+#endif
+			bch->rx_ptr += 4;
+			z1 -= 4;
+		}
+
+		while (z1--)
+#ifdef CONFIG_HISAX_HFC4S8S_PCIMEM
+			*(bch->rx_ptr++) = Read_hfc8(l1->hw, A_FIFO_DATA0);
+#else
+			*(bch->rx_ptr++) = fRead_hfc8(l1->hw);
+#endif
+
+		if (hdlc_complete) {
+			/* increment f counter */
+			Write_hfc8(l1->hw, A_INC_RES_FIFO, 1);
+			wait_busy(l1->hw);
+
+			/* hdlc crc check */
+			bch->rx_ptr--;
+			if (*bch->rx_ptr) {
+				skb->len = 0;
+				bch->rx_ptr = skb->data;
+				continue;
+			}
+			skb->len -= 3;
+		}
+		if (hdlc_complete || (bch->mode == L1_MODE_TRANS)) {
+			bch->rx_skb = NULL;
+			bch->rx_ptr = NULL;
+			bch->b_if.ifc.l1l2(&bch->b_if.ifc,
+					   PH_DATA | INDICATION, skb);
+		}
+
+	} while (1);
+}				/* rx_b_frame */
+
+/********************************************/
+/* a D-frame has been/should be transmitted */
+/********************************************/
+static void
+tx_d_frame(struct hfc4s8s_l1 *l1p)
+{
+	struct sk_buff *skb;
+	u_char f1, f2;
+	u_char *cp;
+	int cnt;
+
+	if (l1p->l1_state != 7)
+		return;
+
+	/* TX fifo */
+	Write_hfc8(l1p->hw, R_FIFO, (l1p->st_num * 8 + 4));
+	wait_busy(l1p->hw);
+
+	f1 = Read_hfc8(l1p->hw, A_F1);
+	f2 = Read_hfc8_stable(l1p->hw, A_F2);
+
+	if ((f1 ^ f2) & MAX_F_CNT)
+		return;		/* fifo is still filled */
+
+	if (l1p->tx_cnt > 0) {
+		cnt = l1p->tx_cnt;
+		l1p->tx_cnt = 0;
+		l1p->d_if.ifc.l1l2(&l1p->d_if.ifc, PH_DATA | CONFIRM,
+				   (void *) cnt);
+	}
+
+	if ((skb = skb_dequeue(&l1p->d_tx_queue))) {
+		cp = skb->data;
+		cnt = skb->len;
+#ifndef CONFIG_HISAX_HFC4S8S_PCIMEM
+		SetRegAddr(l1p->hw, A_FIFO_DATA0);
+#endif
+
+		while (cnt >= 4) {
+#ifdef CONFIG_HISAX_HFC4S8S_PCIMEM
+			fWrite_hfc32(l1p->hw, A_FIFO_DATA0,
+				     *(unsigned long *) cp);
+#else
+			SetRegAddr(l1p->hw, A_FIFO_DATA0);
+			fWrite_hfc32(l1p->hw, *(unsigned long *) cp);
+#endif
+			cp += 4;
+			cnt -= 4;
+		}
+
+#ifdef CONFIG_HISAX_HFC4S8S_PCIMEM
+		while (cnt--)
+			fWrite_hfc8(l1p->hw, A_FIFO_DATA0, *cp++);
+#else
+		while (cnt--)
+			fWrite_hfc8(l1p->hw, *cp++);
+#endif
+
+		l1p->tx_cnt = skb->truesize;
+		Write_hfc8(l1p->hw, A_INC_RES_FIFO, 1);	/* increment f counter */
+		wait_busy(l1p->hw);
+
+		dev_kfree_skb(skb);
+	}
+}				/* tx_d_frame */
+
+/******************************************************/
+/* a B-frame may be transmitted (or is not completed) */
+/******************************************************/
+static void
+tx_b_frame(struct hfc4s8s_btype *bch)
+{
+	struct sk_buff *skb;
+	struct hfc4s8s_l1 *l1 = bch->l1p;
+	u_char *cp;
+	int cnt, max, hdlc_num, ack_len = 0;
+
+	if (!l1->enabled || (bch->mode == L1_MODE_NULL))
+		return;
+
+	/* TX fifo */
+	Write_hfc8(l1->hw, R_FIFO,
+		   (l1->st_num * 8 + ((bch->bchan == 1) ? 0 : 2)));
+	wait_busy(l1->hw);
+	do {
+
+		if (bch->mode == L1_MODE_HDLC) {
+			hdlc_num = Read_hfc8(l1->hw, A_F1) & MAX_F_CNT;
+			hdlc_num -=
+			    (Read_hfc8_stable(l1->hw, A_F2) & MAX_F_CNT);
+			if (hdlc_num < 0)
+				hdlc_num += 16;
+			if (hdlc_num >= 15)
+				break;	/* fifo still filled up with hdlc frames */
+		} else
+			hdlc_num = 0;
+
+		if (!(skb = bch->tx_skb)) {
+			if (!(skb = skb_dequeue(&bch->tx_queue))) {
+				l1->hw->mr.fifo_slow_timer_service[l1->
+								   st_num]
+				    &= ~((bch->bchan == 1) ? 1 : 4);
+				break;	/* list empty */
+			}
+			bch->tx_skb = skb;
+			bch->tx_cnt = 0;
+		}
+
+		if (!hdlc_num)
+			l1->hw->mr.fifo_slow_timer_service[l1->st_num] |=
+			    ((bch->bchan == 1) ? 1 : 4);
+		else
+			l1->hw->mr.fifo_slow_timer_service[l1->st_num] &=
+			    ~((bch->bchan == 1) ? 1 : 4);
+
+		max = Read_hfc16_stable(l1->hw, A_Z2);
+		max -= Read_hfc16(l1->hw, A_Z1);
+		if (max <= 0)
+			max += 384;
+		max--;
+
+		if (max < 16)
+			break;	/* don't write to small amounts of bytes */
+
+		cnt = skb->len - bch->tx_cnt;
+		if (cnt > max)
+			cnt = max;
+		cp = skb->data + bch->tx_cnt;
+		bch->tx_cnt += cnt;
+
+#ifndef CONFIG_HISAX_HFC4S8S_PCIMEM
+		SetRegAddr(l1->hw, A_FIFO_DATA0);
+#endif
+		while (cnt >= 4) {
+#ifdef CONFIG_HISAX_HFC4S8S_PCIMEM
+			fWrite_hfc32(l1->hw, A_FIFO_DATA0,
+				     *(unsigned long *) cp);
+#else
+			fWrite_hfc32(l1->hw, *(unsigned long *) cp);
+#endif
+			cp += 4;
+			cnt -= 4;
+		}
+
+		while (cnt--)
+#ifdef CONFIG_HISAX_HFC4S8S_PCIMEM
+			fWrite_hfc8(l1->hw, A_FIFO_DATA0, *cp++);
+#else
+			fWrite_hfc8(l1->hw, *cp++);
+#endif
+
+		if (bch->tx_cnt >= skb->len) {
+			if (bch->mode == L1_MODE_HDLC) {
+				/* increment f counter */
+				Write_hfc8(l1->hw, A_INC_RES_FIFO, 1);
+			}
+			ack_len += skb->truesize;
+			bch->tx_skb = 0;
+			bch->tx_cnt = 0;
+			dev_kfree_skb(skb);
+		} else
+			/* Re-Select */
+			Write_hfc8(l1->hw, R_FIFO,
+				   (l1->st_num * 8 +
+				    ((bch->bchan == 1) ? 0 : 2)));
+		wait_busy(l1->hw);
+	} while (1);
+
+	if (ack_len)
+		bch->b_if.ifc.l1l2((struct hisax_if *) &bch->b_if,
+				   PH_DATA | CONFIRM, (void *) ack_len);
+}				/* tx_b_frame */
+
+/*************************************/
+/* bottom half handler for interrupt */
+/*************************************/
+static void
+hfc4s8s_bh(hfc4s8s_hw * hw)
+{
+	u_char b;
+	struct hfc4s8s_l1 *l1p;
+	volatile u_char *fifo_stat;
+	int idx;
+
+	/* handle layer 1 state changes */
+	b = 1;
+	l1p = hw->l1;
+	while (b) {
+		if ((b & hw->mr.r_irq_statech)) {
+			/* reset l1 event */
+			hw->mr.r_irq_statech &= ~b;
+			if (l1p->enabled) {
+				if (l1p->nt_mode) {
+					u_char oldstate = l1p->l1_state;
+
+					Write_hfc8(l1p->hw, R_ST_SEL,
+						   l1p->st_num);
+					l1p->l1_state =
+					    Read_hfc8(l1p->hw,
+						      A_ST_RD_STA) & 0xf;
+
+					if ((oldstate == 3)
+					    && (l1p->l1_state != 3))
+						l1p->d_if.ifc.l1l2(&l1p->
+								   d_if.
+								   ifc,
+								   PH_DEACTIVATE
+								   |
+								   INDICATION,
+								   NULL);
+
+					if (l1p->l1_state != 2) {
+						del_timer(&l1p->l1_timer);
+						if (l1p->l1_state == 3) {
+							l1p->d_if.ifc.
+							    l1l2(&l1p->
+								 d_if.ifc,
+								 PH_ACTIVATE
+								 |
+								 INDICATION,
+								 NULL);
+						}
+					} else {
+						/* allow transition */
+						Write_hfc8(hw, A_ST_WR_STA,
+							   M_SET_G2_G3);
+						mod_timer(&l1p->l1_timer,
+							  jiffies +
+							  L1_TIMER_T1);
+					}
+					printk(KERN_INFO
+					       "HFC-4S/8S: NT ch %d l1 state %d -> %d\n",
+					       l1p->st_num, oldstate,
+					       l1p->l1_state);
+				} else {
+					u_char oldstate = l1p->l1_state;
+
+					Write_hfc8(l1p->hw, R_ST_SEL,
+						   l1p->st_num);
+					l1p->l1_state =
+					    Read_hfc8(l1p->hw,
+						      A_ST_RD_STA) & 0xf;
+
+					if (((l1p->l1_state == 3) &&
+					     ((oldstate == 7) ||
+					      (oldstate == 8))) ||
+					    ((timer_pending
+					      (&l1p->l1_timer))
+					     && (l1p->l1_state == 8))) {
+						mod_timer(&l1p->l1_timer,
+							  L1_TIMER_T4 +
+							  jiffies);
+					} else {
+						if (l1p->l1_state == 7) {
+							del_timer(&l1p->
+								  l1_timer);
+							l1p->d_if.ifc.
+							    l1l2(&l1p->
+								 d_if.ifc,
+								 PH_ACTIVATE
+								 |
+								 INDICATION,
+								 NULL);
+							tx_d_frame(l1p);
+						}
+						if (l1p->l1_state == 3) {
+							if (oldstate != 3)
+								l1p->d_if.
+								    ifc.
+								    l1l2
+								    (&l1p->
+								     d_if.
+								     ifc,
+								     PH_DEACTIVATE
+								     |
+								     INDICATION,
+								     NULL);
+						}
+					}
+					printk(KERN_INFO
+					       "HFC-4S/8S: TE %d ch %d l1 state %d -> %d\n",
+					       l1p->hw->cardnum,
+					       l1p->st_num, oldstate,
+					       l1p->l1_state);
+				}
+			}
+		}
+		b <<= 1;
+		l1p++;
+	}
+
+	/* now handle the fifos */
+	idx = 0;
+	fifo_stat = hw->mr.r_irq_fifo_blx;
+	l1p = hw->l1;
+	while (idx < hw->driver_data.max_st_ports) {
+
+		if (hw->mr.timer_irq) {
+			*fifo_stat |= hw->mr.fifo_rx_trans_enables[idx];
+			if (hw->fifo_sched_cnt <= 0) {
+				*fifo_stat |=
+				    hw->mr.fifo_slow_timer_service[l1p->
+								   st_num];
+			}
+		}
+		/* ignore fifo 6 (TX E fifo) */
+		*fifo_stat &= 0xff - 0x40;
+
+		while (*fifo_stat) {
+
+			if (!l1p->nt_mode) {
+				/* RX Fifo has data to read */
+				if ((*fifo_stat & 0x20)) {
+					*fifo_stat &= ~0x20;
+					rx_d_frame(l1p, 0);
+				}
+				/* E Fifo has data to read */
+				if ((*fifo_stat & 0x80)) {
+					*fifo_stat &= ~0x80;
+					rx_d_frame(l1p, 1);
+				}
+				/* TX Fifo completed send */
+				if ((*fifo_stat & 0x10)) {
+					*fifo_stat &= ~0x10;
+					tx_d_frame(l1p);
+				}
+			}
+			/* B1 RX Fifo has data to read */
+			if ((*fifo_stat & 0x2)) {
+				*fifo_stat &= ~0x2;
+				rx_b_frame(l1p->b_ch);
+			}
+			/* B1 TX Fifo has send completed */
+			if ((*fifo_stat & 0x1)) {
+				*fifo_stat &= ~0x1;
+				tx_b_frame(l1p->b_ch);
+			}
+			/* B2 RX Fifo has data to read */
+			if ((*fifo_stat & 0x8)) {
+				*fifo_stat &= ~0x8;
+				rx_b_frame(l1p->b_ch + 1);
+			}
+			/* B2 TX Fifo has send completed */
+			if ((*fifo_stat & 0x4)) {
+				*fifo_stat &= ~0x4;
+				tx_b_frame(l1p->b_ch + 1);
+			}
+		}
+		fifo_stat++;
+		l1p++;
+		idx++;
+	}
+
+	if (hw->fifo_sched_cnt <= 0)
+		hw->fifo_sched_cnt += (1 << (7 - TRANS_TIMER_MODE));
+	hw->mr.timer_irq = 0;	/* clear requested timer irq */
+}				/* hfc4s8s_bh */
+
+/*********************/
+/* interrupt handler */
+/*********************/
+static irqreturn_t
+hfc4s8s_interrupt(int intno, void *dev_id, struct pt_regs *regs)
+{
+	hfc4s8s_hw *hw = dev_id;
+	u_char b, ovr;
+	volatile u_char *ovp;
+	int idx;
+	u_char old_ioreg;
+
+	if (!hw || !(hw->mr.r_irq_ctrl & M_GLOB_IRQ_EN))
+		return IRQ_NONE;
+
+#ifndef	CONFIG_HISAX_HFC4S8S_PCIMEM
+	/* read current selected regsister */
+	old_ioreg = GetRegAddr(hw);
+#endif
+
+	/* Layer 1 State change */
+	hw->mr.r_irq_statech |=
+	    (Read_hfc8(hw, R_SCI) & hw->mr.r_irqmsk_statchg);
+	if (!
+	    (b = (Read_hfc8(hw, R_STATUS) & (M_MISC_IRQSTA | M_FR_IRQSTA)))
+&& !hw->mr.r_irq_statech) {
+#ifndef	CONFIG_HISAX_HFC4S8S_PCIMEM
+		SetRegAddr(hw, old_ioreg);
+#endif
+		return IRQ_NONE;
+	}
+
+	/* timer event */
+	if (Read_hfc8(hw, R_IRQ_MISC) & M_TI_IRQ) {
+		hw->mr.timer_irq = 1;
+		hw->fifo_sched_cnt--;
+	}
+
+	/* FIFO event */
+	if ((ovr = Read_hfc8(hw, R_IRQ_OVIEW))) {
+		hw->mr.r_irq_oview |= ovr;
+		idx = R_IRQ_FIFO_BL0;
+		ovp = hw->mr.r_irq_fifo_blx;
+		while (ovr) {
+			if ((ovr & 1)) {
+				*ovp |= Read_hfc8(hw, idx);
+			}
+			ovp++;
+			idx++;
+			ovr >>= 1;
+		}
+	}
+
+	/* queue the request to allow other cards to interrupt */
+	schedule_work(&hw->tqueue);
+
+#ifndef	CONFIG_HISAX_HFC4S8S_PCIMEM
+	SetRegAddr(hw, old_ioreg);
+#endif
+	return IRQ_HANDLED;
+}				/* hfc4s8s_interrupt */
+
+/***********************************************************************/
+/* reset the complete chip, don't release the chips irq but disable it */
+/***********************************************************************/
+static void
+chipreset(hfc4s8s_hw * hw)
+{
+	u_long flags;
+
+	spin_lock_irqsave(&hw->lock, flags);
+	Write_hfc8(hw, R_CTRL, 0);	/* use internal RAM */
+	Write_hfc8(hw, R_RAM_MISC, 0);	/* 32k*8 RAM */
+	Write_hfc8(hw, R_FIFO_MD, 0);	/* fifo mode 386 byte/fifo simple mode */
+	Write_hfc8(hw, R_CIRM, M_SRES);	/* reset chip */
+	hw->mr.r_irq_ctrl = 0;	/* interrupt is inactive */
+	spin_unlock_irqrestore(&hw->lock, flags);
+
+	udelay(3);
+	Write_hfc8(hw, R_CIRM, 0);	/* disable reset */
+	wait_busy(hw);
+
+	Write_hfc8(hw, R_PCM_MD0, M_PCM_MD);	/* master mode */
+	Write_hfc8(hw, R_RAM_MISC, M_FZ_MD);	/* transmit fifo option */
+	if (hw->driver_data.clock_mode == 1)
+		Write_hfc8(hw, R_BRG_PCM_CFG, M_PCM_CLK);	/* PCM clk / 2 */
+	Write_hfc8(hw, R_TI_WD, TRANS_TIMER_MODE);	/* timer interval */
+
+	memset(&hw->mr, 0, sizeof(hw->mr));
+}				/* chipreset */
+
+/********************************************/
+/* disable/enable hardware in nt or te mode */
+/********************************************/
+void
+hfc_hardware_enable(hfc4s8s_hw * hw, int enable, int nt_mode)
+{
+	u_long flags;
+	char if_name[40];
+	int i;
+
+	if (enable) {
+		/* save system vars */
+		hw->nt_mode = nt_mode;
+
+		/* enable fifo and state irqs, but not global irq enable */
+		hw->mr.r_irq_ctrl = M_FIFO_IRQ;
+		Write_hfc8(hw, R_IRQ_CTRL, hw->mr.r_irq_ctrl);
+		hw->mr.r_irqmsk_statchg = 0;
+		Write_hfc8(hw, R_SCI_MSK, hw->mr.r_irqmsk_statchg);
+		Write_hfc8(hw, R_PWM_MD, 0x80);
+		Write_hfc8(hw, R_PWM1, 26);
+		if (!nt_mode)
+			Write_hfc8(hw, R_ST_SYNC, M_AUTO_SYNC);
+
+		/* enable the line interfaces and fifos */
+		for (i = 0; i < hw->driver_data.max_st_ports; i++) {
+			hw->mr.r_irqmsk_statchg |= (1 << i);
+			Write_hfc8(hw, R_SCI_MSK, hw->mr.r_irqmsk_statchg);
+			Write_hfc8(hw, R_ST_SEL, i);
+			Write_hfc8(hw, A_ST_CLK_DLY,
+				   ((nt_mode) ? CLKDEL_NT : CLKDEL_TE));
+			hw->mr.r_ctrl0 = ((nt_mode) ? CTRL0_NT : CTRL0_TE);
+			Write_hfc8(hw, A_ST_CTRL0, hw->mr.r_ctrl0);
+			Write_hfc8(hw, A_ST_CTRL2, 3);
+			Write_hfc8(hw, A_ST_WR_STA, 0);	/* enable state machine */
+
+			hw->l1[i].enabled = 1;
+			hw->l1[i].nt_mode = nt_mode;
+
+			if (!nt_mode) {
+				/* setup E-fifo */
+				Write_hfc8(hw, R_FIFO, i * 8 + 7);	/* E fifo */
+				wait_busy(hw);
+				Write_hfc8(hw, A_CON_HDLC, 0x11);	/* HDLC mode, 1 fill, connect ST */
+				Write_hfc8(hw, A_SUBCH_CFG, 2);	/* only 2 bits */
+				Write_hfc8(hw, A_IRQ_MSK, 1);	/* enable interrupt */
+				Write_hfc8(hw, A_INC_RES_FIFO, 2);	/* reset fifo */
+				wait_busy(hw);
+
+				/* setup D RX-fifo */
+				Write_hfc8(hw, R_FIFO, i * 8 + 5);	/* RX fifo */
+				wait_busy(hw);
+				Write_hfc8(hw, A_CON_HDLC, 0x11);	/* HDLC mode, 1 fill, connect ST */
+				Write_hfc8(hw, A_SUBCH_CFG, 2);	/* only 2 bits */
+				Write_hfc8(hw, A_IRQ_MSK, 1);	/* enable interrupt */
+				Write_hfc8(hw, A_INC_RES_FIFO, 2);	/* reset fifo */
+				wait_busy(hw);
+
+				/* setup D TX-fifo */
+				Write_hfc8(hw, R_FIFO, i * 8 + 4);	/* TX fifo */
+				wait_busy(hw);
+				Write_hfc8(hw, A_CON_HDLC, 0x11);	/* HDLC mode, 1 fill, connect ST */
+				Write_hfc8(hw, A_SUBCH_CFG, 2);	/* only 2 bits */
+				Write_hfc8(hw, A_IRQ_MSK, 1);	/* enable interrupt */
+				Write_hfc8(hw, A_INC_RES_FIFO, 2);	/* reset fifo */
+				wait_busy(hw);
+			}
+
+			sprintf(if_name, "hfc4s8s_%d%d_", hw->cardnum, i);
+
+			if (hisax_register
+			    (&hw->l1[i].d_if, hw->l1[i].b_table, if_name,
+			     ((nt_mode) ? 3 : 2))) {
+
+				hw->l1[i].enabled = 0;
+				hw->mr.r_irqmsk_statchg &= ~(1 << i);
+				Write_hfc8(hw, R_SCI_MSK,
+					   hw->mr.r_irqmsk_statchg);
+				printk(KERN_INFO
+				       "HFC-4S/8S: Unable to register S/T device %s, break\n",
+				       if_name);
+				break;
+			}
+		}
+		spin_lock_irqsave(&hw->lock, flags);
+		hw->mr.r_irq_ctrl |= M_GLOB_IRQ_EN;
+		Write_hfc8(hw, R_IRQ_CTRL, hw->mr.r_irq_ctrl);
+		spin_unlock_irqrestore(&hw->lock, flags);
+	} else {
+		/* disable hardware */
+		spin_lock_irqsave(&hw->lock, flags);
+		hw->mr.r_irq_ctrl &= ~M_GLOB_IRQ_EN;
+		Write_hfc8(hw, R_IRQ_CTRL, hw->mr.r_irq_ctrl);
+		spin_unlock_irqrestore(&hw->lock, flags);
+
+		for (i = hw->driver_data.max_st_ports - 1; i >= 0; i--) {
+			hw->l1[i].enabled = 0;
+			hisax_unregister(&hw->l1[i].d_if);
+			del_timer(&hw->l1[i].l1_timer);
+			skb_queue_purge(&hw->l1[i].d_tx_queue);
+			skb_queue_purge(&hw->l1[i].b_ch[0].tx_queue);
+			skb_queue_purge(&hw->l1[i].b_ch[1].tx_queue);
+		}
+		chipreset(hw);
+	}
+}				/* hfc_hardware_enable */
+
+/******************************************/
+/* disable memory mapped ports / io ports */
+/******************************************/
+void
+release_pci_ports(hfc4s8s_hw * hw)
+{
+	pci_write_config_word(hw->pdev, PCI_COMMAND, 0);
+#ifdef CONFIG_HISAX_HFC4S8S_PCIMEM
+	if (hw->membase)
+		iounmap((void *) hw->membase);
+#else
+	if (hw->iobase)
+		release_region(hw->iobase, 8);
+#endif
+}
+
+/*****************************************/
+/* enable memory mapped ports / io ports */
+/*****************************************/
+void
+enable_pci_ports(hfc4s8s_hw * hw)
+{
+#ifdef CONFIG_HISAX_HFC4S8S_PCIMEM
+	pci_write_config_word(hw->pdev, PCI_COMMAND, PCI_ENA_MEMIO);
+#else
+	pci_write_config_word(hw->pdev, PCI_COMMAND, PCI_ENA_REGIO);
+#endif
+}
+
+/*************************************/
+/* initialise the HFC-4s/8s hardware */
+/* return 0 on success.              */
+/*************************************/
+static int __devinit
+setup_instance(hfc4s8s_hw * hw)
+{
+	int err = -EIO;
+	int i;
+
+	for (i = 0; i < HFC_MAX_ST; i++) {
+		struct hfc4s8s_l1 *l1p;
+
+		l1p = hw->l1 + i;
+		spin_lock_init(&l1p->lock);
+		l1p->hw = hw;
+		l1p->l1_timer.function = (void *) hfc_l1_timer;
+		l1p->l1_timer.data = (long) (l1p);
+		init_timer(&l1p->l1_timer);
+		l1p->st_num = i;
+		skb_queue_head_init(&l1p->d_tx_queue);
+		l1p->d_if.ifc.priv = hw->l1 + i;
+		l1p->d_if.ifc.l2l1 = (void *) dch_l2l1;
+
+		spin_lock_init(&l1p->b_ch[0].lock);
+		l1p->b_ch[0].b_if.ifc.l2l1 = (void *) bch_l2l1;
+		l1p->b_ch[0].b_if.ifc.priv = (void *) &l1p->b_ch[0];
+		l1p->b_ch[0].l1p = hw->l1 + i;
+		l1p->b_ch[0].bchan = 1;
+		l1p->b_table[0] = &l1p->b_ch[0].b_if;
+		skb_queue_head_init(&l1p->b_ch[0].tx_queue);
+
+		spin_lock_init(&l1p->b_ch[1].lock);
+		l1p->b_ch[1].b_if.ifc.l2l1 = (void *) bch_l2l1;
+		l1p->b_ch[1].b_if.ifc.priv = (void *) &l1p->b_ch[1];
+		l1p->b_ch[1].l1p = hw->l1 + i;
+		l1p->b_ch[1].bchan = 2;
+		l1p->b_table[1] = &l1p->b_ch[1].b_if;
+		skb_queue_head_init(&l1p->b_ch[1].tx_queue);
+	}
+
+	enable_pci_ports(hw);
+	chipreset(hw);
+
+	i = Read_hfc8(hw, R_CHIP_ID) >> CHIP_ID_SHIFT;
+	if (i != hw->driver_data.chip_id) {
+		printk(KERN_INFO
+		       "HFC-4S/8S: invalid chip id 0x%x instead of 0x%x, card ignored\n",
+		       i, hw->driver_data.chip_id);
+		goto out;
+	}
+
+	i = Read_hfc8(hw, R_CHIP_RV) & 0xf;
+	if (!i) {
+		printk(KERN_INFO
+		       "HFC-4S/8S: chip revision 0 not supported, card ignored\n");
+		goto out;
+	}
+
+	INIT_WORK(&hw->tqueue, (void *) (void *) hfc4s8s_bh, hw);
+
+	if (request_irq
+	    (hw->irq, hfc4s8s_interrupt, SA_SHIRQ, hw->card_name, hw)) {
+		printk(KERN_INFO
+		       "HFC-4S/8S: unable to alloc irq %d, card ignored\n",
+		       hw->irq);
+		goto out;
+	}
+#ifdef CONFIG_HISAX_HFC4S8S_PCIMEM
+	printk(KERN_INFO
+	       "HFC-4S/8S: found PCI card at membase 0x%p, irq %d\n",
+	       hw->hw_membase, hw->irq);
+#else
+	printk(KERN_INFO
+	       "HFC-4S/8S: found PCI card at iobase 0x%x, irq %d\n",
+	       hw->iobase, hw->irq);
+#endif
+
+	hfc_hardware_enable(hw, 1, 0);
+
+	return (0);
+
+      out:
+	hw->irq = 0;
+	release_pci_ports(hw);
+	kfree(hw);
+	return (err);
+}
+
+/*****************************************/
+/* PCI hotplug interface: probe new card */
+/*****************************************/
+static int __devinit
+hfc4s8s_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+	int err = -ENOMEM;
+	hfc4s8s_param *driver_data = (hfc4s8s_param *) ent->driver_data;
+	hfc4s8s_hw *hw;
+
+	if (!(hw = kmalloc(sizeof(hfc4s8s_hw), GFP_ATOMIC))) {
+		printk(KERN_ERR "No kmem for HFC-4S/8S card\n");
+		return (err);
+	}
+	memset(hw, 0, sizeof(hfc4s8s_hw));
+
+	hw->pdev = pdev;
+	err = pci_enable_device(pdev);
+
+	if (err)
+		goto out;
+
+	hw->cardnum = card_cnt;
+	sprintf(hw->card_name, "hfc4s8s_%d", hw->cardnum);
+	printk(KERN_INFO "HFC-4S/8S: found adapter %s (%s) at %s\n",
+	       driver_data->device_name, hw->card_name, pci_name(pdev));
+
+	spin_lock_init(&hw->lock);
+
+	hw->driver_data = *driver_data;
+	hw->irq = pdev->irq;
+	hw->iobase = pci_resource_start(pdev, 0);
+
+#ifdef CONFIG_HISAX_HFC4S8S_PCIMEM
+	hw->hw_membase = (u_char *) pci_resource_start(pdev, 1);
+	hw->membase = ioremap((ulong) hw->hw_membase, 256);
+#else
+	if (!request_region(hw->iobase, 8, hw->card_name)) {
+		printk(KERN_INFO
+		       "HFC-4S/8S: failed to rquest address space at 0x%04x\n",
+		       hw->iobase);
+		goto out;
+	}
+#endif
+
+	pci_set_drvdata(pdev, hw);
+	err = setup_instance(hw);
+	if (!err)
+		card_cnt++;
+	return (err);
+
+      out:
+	kfree(hw);
+	return (err);
+}
+
+/**************************************/
+/* PCI hotplug interface: remove card */
+/**************************************/
+static void __devexit
+hfc4s8s_remove(struct pci_dev *pdev)
+{
+	hfc4s8s_hw *hw = pci_get_drvdata(pdev);
+
+	printk(KERN_INFO "HFC-4S/8S: removing card %d\n", hw->cardnum);
+	hfc_hardware_enable(hw, 0, 0);
+
+	if (hw->irq)
+		free_irq(hw->irq, hw);
+	hw->irq = 0;
+	release_pci_ports(hw);
+
+	card_cnt--;
+	pci_disable_device(pdev);
+	kfree(hw);
+	return;
+}
+
+static struct pci_driver hfc4s8s_driver = {
+      name:"hfc4s8s_l1",
+      probe:hfc4s8s_probe,
+      remove:__devexit_p(hfc4s8s_remove),
+      id_table:hfc4s8s_ids,
+};
+
+/**********************/
+/* driver Module init */
+/**********************/
+static int __init
+hfc4s8s_module_init(void)
+{
+	int err;
+
+	printk(KERN_INFO
+	       "HFC-4S/8S: Layer 1 driver module for HFC-4S/8S isdn chips, %s\n",
+	       hfc4s8s_rev);
+	printk(KERN_INFO
+	       "HFC-4S/8S: (C) 2003 Cornelius Consult, www.cornelius-consult.de\n");
+
+	card_cnt = 0;
+
+	err = pci_register_driver(&hfc4s8s_driver);
+	if (err < 0) {
+		goto out;
+	}
+	printk(KERN_INFO "HFC-4S/8S: found %d cards\n", card_cnt);
+
+#if !defined(CONFIG_HOTPLUG)
+	if (err == 0) {
+		err = -ENODEV;
+		pci_unregister_driver(&hfc4s8s_driver);
+		goto out;
+	}
+#endif
+
+	return 0;
+      out:
+	return (err);
+}				/* hfc4s8s_init_hw */
+
+/*************************************/
+/* driver module exit :              */
+/* release the HFC-4s/8s hardware    */
+/*************************************/
+static void
+hfc4s8s_module_exit(void)
+{
+	pci_unregister_driver(&hfc4s8s_driver);
+	printk(KERN_INFO "HFC-4S/8S: module removed\n");
+}				/* hfc4s8s_release_hw */
+
+module_init(hfc4s8s_module_init);
+module_exit(hfc4s8s_module_exit);
diff -Nru a/drivers/isdn/hisax/hfc4s8s_l1.h b/drivers/isdn/hisax/hfc4s8s_l1.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/isdn/hisax/hfc4s8s_l1.h	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,88 @@
+/***************************************************************/
+/*  $Id: hfc4s8s_l1.h,v 1.1 2005/02/02 17:28:55 martinb1 Exp $ */
+/*                                                             */
+/*  This file is a minimal required extraction of hfc48scu.h   */
+/*  (Genero 3.2, HFC XML 1.7a for HFC-E1, HFC-4S and HFC-8S)   */
+/*                                                             */
+/*  To get this complete register description contact          */
+/*  Cologne Chip AG :                                          */
+/*  Internet:  http://www.colognechip.com/                     */
+/*  E-Mail:    info@colognechip.com                            */
+/***************************************************************/
+
+#ifndef _HFC4S8S_L1_H_
+#define _HFC4S8S_L1_H_
+
+
+/*
+*  include Genero generated HFC-4S/8S header file hfc48scu.h
+*  for comlete register description. This will define _HFC48SCU_H_
+*  to prevent redefinitions
+*/
+
+// #include "hfc48scu.h"
+
+#ifndef _HFC48SCU_H_
+#define _HFC48SCU_H_
+
+#ifndef PCI_VENDOR_ID_CCD
+#define PCI_VENDOR_ID_CCD	0x1397
+#endif
+
+#define CHIP_ID_4S		0x0C
+#define CHIP_ID_8S		0x08
+#define PCI_DEVICE_ID_4S	0x08B4
+#define PCI_DEVICE_ID_8S	0x16B8
+
+#define R_IRQ_MISC	0x11
+#define M_TI_IRQ	0x02
+#define A_ST_RD_STA	0x30
+#define A_ST_WR_STA	0x30
+#define M_SET_G2_G3	0x80
+#define A_ST_CTRL0	0x31
+#define A_ST_CTRL2	0x33
+#define A_ST_CLK_DLY	0x37
+#define A_Z1		0x04
+#define A_Z2		0x06
+#define R_CIRM		0x00
+#define M_SRES		0x08
+#define R_CTRL		0x01
+#define R_BRG_PCM_CFG	0x02
+#define M_PCM_CLK	0x20
+#define R_RAM_MISC	0x0C
+#define M_FZ_MD		0x80
+#define R_FIFO_MD	0x0D
+#define A_INC_RES_FIFO	0x0E
+#define R_FIFO		0x0F
+#define A_F1		0x0C
+#define A_F2		0x0D
+#define R_IRQ_OVIEW	0x10
+#define R_CHIP_ID	0x16
+#define R_STATUS	0x1C
+#define M_BUSY		0x01
+#define M_MISC_IRQSTA	0x40
+#define M_FR_IRQSTA	0x80
+#define R_CHIP_RV	0x1F
+#define R_IRQ_CTRL	0x13
+#define M_FIFO_IRQ	0x01
+#define M_GLOB_IRQ_EN	0x08
+#define R_PCM_MD0	0x14
+#define M_PCM_MD	0x01
+#define A_FIFO_DATA0	0x80
+#define R_TI_WD		0x1A
+#define R_PWM1		0x39
+#define R_PWM_MD	0x46
+#define R_IRQ_FIFO_BL0	0xC8
+#define A_CON_HDLC	0xFA
+#define A_SUBCH_CFG	0xFB
+#define A_IRQ_MSK	0xFF
+#define R_SCI_MSK	0x12
+#define R_ST_SEL	0x16
+#define R_ST_SYNC	0x17
+#define M_AUTO_SYNC	0x08
+#define R_SCI		0x12
+#define R_IRQMSK_MISC	0x11
+#define M_TI_IRQMSK	0x02
+
+#endif	/* _HFC4S8S_L1_H_ */
+#endif	/* _HFC48SCU_H_ */
diff -Nru a/drivers/isdn/hisax/hfc_usb.c b/drivers/isdn/hisax/hfc_usb.c
--- a/drivers/isdn/hisax/hfc_usb.c	2005-03-11 12:51:42 -08:00
+++ b/drivers/isdn/hisax/hfc_usb.c	2005-03-11 12:51:42 -08:00
@@ -1,11 +1,15 @@
 /*
  * hfc_usb.c
  *
- * modular HiSax ISDN driver for Colognechip HFC-USB chip
+ * $Id: hfc_usb.c,v 4.34 2005/01/26 17:25:53 martinb1 Exp $
  *
- * Authors : Peter Sprenger  (sprenger@moving-byters.de)
+ * modular HiSax ISDN driver for Colognechip HFC-S USB chip
+ *
+ * Authors : Peter Sprenger  (sprenger@moving-bytes.de)
  *           Martin Bachem   (info@colognechip.com)
- *           based on the first hfc_usb driver of Werner Cornelius (werner@isdn-development.de)
+ *
+ *           based on the first hfc_usb driver of
+ *           Werner Cornelius (werner@isdn-development.de)
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -21,249 +25,229 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
+ * See Version Histroy at the bottom of this file
+ *
 */
 
-
 #include <linux/types.h>
 #include <linux/stddef.h>
 #include <linux/timer.h>
 #include <linux/config.h>
 #include <linux/init.h>
-#include "hisax.h"
 #include <linux/module.h>
 #include <linux/kernel_stat.h>
 #include <linux/usb.h>
 #include <linux/kernel.h>
 #include <linux/smp_lock.h>
 #include <linux/sched.h>
+#include "hisax.h"
 #include "hisax_if.h"
-
-static const char *hfcusb_revision = "4.0";
+#include "hfc_usb.h"
 
 /*
-	to enable much mire debug messages in this driver, define
-			VERBOSE_USB_DEBUG and VERBOSE_ISDN_DEBUG
-	below
+* Version Information
+* (do not modify the CVS Makros $Revision: 4.34 $ and $Date: 2005/01/26 17:25:53 $ !)
 */
+static const char *hfcusb_revision =
+    "Revision: 4.34 $ Date: 2005/01/26 17:25:53 $ ";
 
-#define VERBOSE_USB_DEBUG
-#define VERBOSE_ISDN_DEBUG
-
-#define INCLUDE_INLINE_FUNCS
-
-#define TRUE  1
-#define FALSE 0
-
-
-/***********/
-/* defines */
-/***********/
-#define HFC_CTRL_TIMEOUT	20  //(HZ * USB_CTRL_GET_TIMEOUT)
-/* 5ms timeout writing/reading regs */
-#define HFC_TIMER_T3     8000      /* timeout for l1 activation timer */
-#define HFC_TIMER_T4     500       /* time for state change interval */
-
-#define HFCUSB_L1_STATECHANGE   0  /* L1 state changed */
-#define HFCUSB_L1_DRX           1  /* D-frame received */
-#define HFCUSB_L1_ERX           2  /* E-frame received */
-#define HFCUSB_L1_DTX           4  /* D-frames completed */
-
-#define MAX_BCH_SIZE        2048   /* allowed B-channel packet size */
-
-#define HFCUSB_RX_THRESHOLD 64     /* threshold for fifo report bit rx */
-#define HFCUSB_TX_THRESHOLD 64     /* threshold for fifo report bit tx */
-
-#define HFCUSB_CHIP_ID    0x16     /* Chip ID register index */
-#define HFCUSB_CIRM       0x00     /* cirm register index */
-#define HFCUSB_USB_SIZE   0x07     /* int length register */
-#define HFCUSB_USB_SIZE_I 0x06     /* iso length register */
-#define HFCUSB_F_CROSS    0x0b     /* bit order register */
-#define HFCUSB_CLKDEL     0x37     /* bit delay register */
-#define HFCUSB_CON_HDLC   0xfa     /* channel connect register */
-#define HFCUSB_HDLC_PAR   0xfb
-#define HFCUSB_SCTRL      0x31     /* S-bus control register (tx) */
-#define HFCUSB_SCTRL_E    0x32     /* same for E and special funcs */
-#define HFCUSB_SCTRL_R    0x33     /* S-bus control register (rx) */
-#define HFCUSB_F_THRES    0x0c     /* threshold register */
-#define HFCUSB_FIFO       0x0f     /* fifo select register */
-#define HFCUSB_F_USAGE    0x1a     /* fifo usage register */
-#define HFCUSB_MST_MODE0  0x14
-#define HFCUSB_MST_MODE1  0x15
-#define HFCUSB_P_DATA     0x1f
-#define HFCUSB_INC_RES_F  0x0e
-#define HFCUSB_STATES     0x30
-
-#define HFCUSB_CHIPID 0x40         /* ID value of HFC-USB */
-
-/******************/
-/* fifo registers */
-/******************/
-#define HFCUSB_NUM_FIFOS   8       /* maximum number of fifos */
-#define HFCUSB_B1_TX       0       /* index for B1 transmit bulk/int */
-#define HFCUSB_B1_RX       1       /* index for B1 receive bulk/int */
-#define HFCUSB_B2_TX       2
-#define HFCUSB_B2_RX       3
-#define HFCUSB_D_TX        4
-#define HFCUSB_D_RX        5
-#define HFCUSB_PCM_TX      6
-#define HFCUSB_PCM_RX      7
-
-/*
-* used to switch snd_transfer_mode for different TA modes e.g. the Billion USB TA just
-* supports ISO out, while the Cologne Chip EVAL TA just supports BULK out
+/* Hisax debug support
+* use "modprobe debug=x" where x is bitfield of USB_DBG & ISDN_DBG
 */
-#define USB_INT		0
-#define USB_BULK	1
-#define USB_ISOC	2
-
-#define ISOC_PACKETS_D	8
-#define ISOC_PACKETS_B	8
-#define ISO_BUFFER_SIZE	128
-
-// ISO send definitions
-#define SINK_MAX	68
-#define SINK_MIN	48
-#define SINK_DMIN	12
-#define SINK_DMAX	18
-#define BITLINE_INF	(-64*8)
-
-
-
-
-/**********/
-/* macros */
-/**********/
-#define write_usb(a,b,c) usb_control_msg((a)->dev,(a)->ctrl_out_pipe,0,0x40,(c),(b),NULL,0,HFC_CTRL_TIMEOUT)
-#define read_usb(a,b,c) usb_control_msg((a)->dev,(a)->ctrl_in_pipe,1,0xC0,0,(b),(c),1,HFC_CTRL_TIMEOUT)
-
-/*************************************************/
-/* entry and size of output/input control buffer */
-/*************************************************/
-#define HFC_CTRL_BUFSIZE 32
-typedef struct
-{
-	__u8 hfc_reg;		/* register number */
-	__u8 reg_val;		/* value to be written (or read) */
-	int action;         /* data for action handler */
+#ifdef CONFIG_HISAX_DEBUG
+#include <linux/moduleparam.h>
+#define __debug_variable hfc_debug
+#include "hisax_debug.h"
+static u_int debug;
+module_param(debug, uint, 0);
+int hfc_debug;
+#endif
 
-} ctrl_buft;
 
-typedef struct
-{
-	int vendor;         // vendor id
-	int prod_id;	    // product id
-	char *vend_name;    // vendor string
-	__u8 led_scheme;    // led display scheme
-	__u8 led_invert;    // invert led aux port settings
-	__u8 led_bits[8];   // array of 8 possible LED bitmask settings
+/****************************************/
+/* data defining the devices to be used */
+/****************************************/
+static struct usb_device_id hfc_usb_idtab[] = {
+	{USB_DEVICE(0x0959, 0x2bd0)},	/* Colognechip USB eval TA */
+	{USB_DEVICE(0x0675, 0x1688)},	/* DrayTek miniVigor 128 USB ISDN TA */
+	{USB_DEVICE(0x07b0, 0x0007)},	/* Billion USB TA 2 */
+	{USB_DEVICE(0x0742, 0x2008)},	/* Stollmann USB TA */
+	{USB_DEVICE(0x0742, 0x2009)},	/* Aceex USB ISDN TA */
+	{USB_DEVICE(0x0742, 0x200A)},	/* OEM USB ISDN TA */
+	{USB_DEVICE(0x08e3, 0x0301)},	/* OliTec ISDN USB */
+	{USB_DEVICE(0x07fa, 0x0846)},	/* Bewan ISDN USB TA */
+	{USB_DEVICE(0x07fa, 0x0847)},	/* Djinn Numeris USB */
+	{USB_DEVICE(0x07b0, 0x0006)},	/* Twister ISDN USB TA */
+	{}			/* end with an all-zeroes entry */
+};
 
-} vendor_data;
+/* driver internal device specific data:
+*   VendorID, ProductID, Devicename, LED_SCHEME,
+*   LED's BitMask in HFCUSB_P_DATA Register : LED_USB, LED_S0, LED_B1, LED_B2
+*/
+vendor_data vdata[] = {
+	/* CologneChip Eval TA */
+	{0x0959, 0x2bd0, "ISDN USB TA (Cologne Chip HFC-S USB based)",
+	 LED_OFF, {4, 0, 2, 1}
+	 }
+	,
+	/* DrayTek miniVigor 128 USB ISDN TA */
+	{0x0675, 0x1688, "DrayTek miniVigor 128 USB ISDN TA",
+	 LED_SCHEME1, {1, 2, 0, 0}
+	 }
+	,
+	/* Billion TA */
+	{0x07b0, 0x0007, "Billion tiny USB ISDN TA 128",
+	 LED_SCHEME1, {0x80, -64, -32, -16}
+	 }
+	,
+	/* Stollmann TA */
+	{0x0742, 0x2008, "Stollmann USB TA",
+	 LED_SCHEME1, {4, 0, 2, 1}
+	 }
+	,
+	/* Aceex USB ISDN TA */
+	{0x0742, 0x2009, "Aceex USB ISDN TA",
+	 LED_SCHEME1, {4, 0, 2, 1}
+	 }
+	,
+	/* OEM USB ISDN TA */
+	{0x0742, 0x200A, "OEM USB ISDN TA",
+	 LED_SCHEME1, {4, 0, 2, 1}
+	 }
+	,
+	/* Olitec TA  */
+	{0x08e3, 0x0301, "Olitec USB RNIS",
+	 LED_SCHEME1, {2, 0, 1, 4}
+	 }
+	,
+	/* Bewan TA   */
+	{0x07fa, 0x0846, "Bewan Modem RNIS USB",
+	 LED_SCHEME1, {0x80, -64, -32, -16}
+	 }
+	,
+	/* Bewan TA   */
+	{0x07fa, 0x0847, "Djinn Numeris USB",
+	 LED_SCHEME1, {0x80, -64, -32, -16}
+	 }
+	,
+	/* Twister ISDN TA   */
+	{0x07b0, 0x0006, "Twister ISDN TA",
+	 LED_SCHEME1, {0x80, -64, -32, -16}
+	 }
+	,
+	{0, 0, 0}		/* EOL element */
+};
 
 /***************************************************************/
 /* structure defining input+output fifos (interrupt/bulk mode) */
 /***************************************************************/
-
-struct usb_fifo;			/* forward definition */
-typedef struct iso_urb_struct
-{
+struct usb_fifo;		/* forward definition */
+typedef struct iso_urb_struct {
 	struct urb *purb;
 	__u8 buffer[ISO_BUFFER_SIZE];	/* buffer incoming/outgoing data */
-	struct usb_fifo *owner_fifo;	// pointer to owner fifo
+	struct usb_fifo *owner_fifo;	/* pointer to owner fifo */
 } iso_urb_struct;
 
 
-struct hfcusb_data;			/* forward definition */
-typedef struct usb_fifo
-{
-	int fifonum;			/* fifo index attached to this structure */
-	int active;			/* fifo is currently active */
+struct hfcusb_data;		/* forward definition */
+typedef struct usb_fifo {
+	int fifonum;		/* fifo index attached to this structure */
+	int active;		/* fifo is currently active */
 	struct hfcusb_data *hfc;	/* pointer to main structure */
-	int pipe;			/* address of endpoint */
-	__u8 usb_packet_maxlen;		/* maximum length for usb transfer */
-	unsigned int max_size;		/* maximum size of receive/send packet */
-	__u8 intervall;			/* interrupt interval */
-	struct sk_buff *skbuff; 	/* actual used buffer */
-	struct urb *urb;		/* transfer structure for usb routines */
-	__u8 buffer[128];		/* buffer incoming/outgoing data */
-	int bit_line;			/* how much bits are in the fifo? */
-
-	volatile __u8 usb_transfer_mode;/* switched between ISO and INT */
-	iso_urb_struct iso[2];		/* need two urbs to have one always for pending */
-	struct hisax_if *hif;		/* hisax interface */
-	int delete_flg;			/* only delete skbuff once */
-	int last_urblen;		/* remember length of last packet */
+	int pipe;		/* address of endpoint */
+	__u8 usb_packet_maxlen;	/* maximum length for usb transfer */
+	unsigned int max_size;	/* maximum size of receive/send packet */
+	__u8 intervall;		/* interrupt interval */
+	struct sk_buff *skbuff;	/* actual used buffer */
+	struct urb *urb;	/* transfer structure for usb routines */
+	__u8 buffer[128];	/* buffer incoming/outgoing data */
+	int bit_line;		/* how much bits are in the fifo? */
+
+	volatile __u8 usb_transfer_mode;	/* switched between ISO and INT */
+	iso_urb_struct iso[2];	/* need two urbs to have one always for pending */
+	struct hisax_if *hif;	/* hisax interface */
+	int delete_flg;		/* only delete skbuff once */
+	int last_urblen;	/* remember length of last packet */
 
 } usb_fifo;
 
-
 /*********************************************/
 /* structure holding all data for one device */
 /*********************************************/
-typedef struct hfcusb_data
-{
-	// HiSax Interface for loadable Layer1 drivers
-	struct hisax_d_if d_if;			/* see hisax_if.h */
-	struct hisax_b_if b_if[2];		/* see hisax_if.h */
+typedef struct hfcusb_data {
+	/* HiSax Interface for loadable Layer1 drivers */
+	struct hisax_d_if d_if;	/* see hisax_if.h */
+	struct hisax_b_if b_if[2];	/* see hisax_if.h */
 	int protocol;
-	
-	struct usb_device *dev;			/* our device */
-	int if_used;				/* used interface number */
-	int alt_used;				/* used alternate config */
-	int ctrl_paksize;			/* control pipe packet size */
-	int ctrl_in_pipe, ctrl_out_pipe;	/* handles for control pipe */
-	int cfg_used;				/* configuration index used */
-	int vend_idx;				// vendor found
-
-	int b_mode[2];				// B-channel mode
-
-	int l1_activated;			// layer 1 activated
 
-	int packet_size,iso_packet_size;	
+	struct usb_device *dev;	/* our device */
+	int if_used;		/* used interface number */
+	int alt_used;		/* used alternate config */
+	int ctrl_paksize;	/* control pipe packet size */
+	int ctrl_in_pipe, ctrl_out_pipe;	/* handles for control pipe */
+	int cfg_used;		/* configuration index used */
+	int vend_idx;		/* vendor found */
+	int b_mode[2];		/* B-channel mode */
+	int l1_activated;	/* layer 1 activated */
+	int disc_flag;		/* TRUE if device was disonnected to avoid some USB actions */
+	int packet_size, iso_packet_size;
 
 	/* control pipe background handling */
 	ctrl_buft ctrl_buff[HFC_CTRL_BUFSIZE];	/* buffer holding queued data */
-	volatile int ctrl_in_idx, ctrl_out_idx,
-		ctrl_cnt;			/* input/output pointer + count */
-	struct urb *ctrl_urb;			/* transfer structure for control channel */
+	volatile int ctrl_in_idx, ctrl_out_idx, ctrl_cnt;	/* input/output pointer + count */
+	struct urb *ctrl_urb;	/* transfer structure for control channel */
 
 	struct usb_ctrlrequest ctrl_write;	/* buffer for control write request */
 	struct usb_ctrlrequest ctrl_read;	/* same for read request */
 
-	__u8 led_state,led_new_data,led_b_active;
+	__u8 old_led_state, led_state, led_new_data, led_b_active;
 
-	volatile __u8 threshold_mask;		/* threshold actually reported */
-	volatile __u8 bch_enables;		/* or mask for sctrl_r and sctrl register values */
+	volatile __u8 threshold_mask;	/* threshold actually reported */
+	volatile __u8 bch_enables;	/* or mask for sctrl_r and sctrl register values */
 
 	usb_fifo fifos[HFCUSB_NUM_FIFOS];	/* structure holding all fifo data */
 
-	volatile __u8 l1_state;			/* actual l1 state */
-	struct timer_list t3_timer;		/* timer 3 for activation/deactivation */
-	struct timer_list t4_timer;		/* timer 4 for activation/deactivation */
-	struct timer_list led_timer;		/* timer flashing leds */
+	volatile __u8 l1_state;	/* actual l1 state */
+	struct timer_list t3_timer;	/* timer 3 for activation/deactivation */
+	struct timer_list t4_timer;	/* timer 4 for activation/deactivation */
+	struct timer_list led_timer;	/* timer flashing leds */
 
 } hfcusb_data;
 
 
-static void collect_rx_frame(usb_fifo *fifo,__u8 *data,int len,int finish);
+static void collect_rx_frame(usb_fifo * fifo, __u8 * data, int len,
+			     int finish);
+
 
+static inline const char *
+symbolic(struct hfcusb_symbolic_list list[], const int num)
+{
+	int i;
+	for (i = 0; list[i].name != NULL; i++)
+		if (list[i].num == num)
+			return (list[i].name);
+	return "<unkown>";
+}
 
 
 /******************************************************/
 /* start next background transfer for control channel */
 /******************************************************/
-static void ctrl_start_transfer(hfcusb_data * hfc)
+static void
+ctrl_start_transfer(hfcusb_data * hfc)
 {
-	int err;
-	if(hfc->ctrl_cnt)
-	{
+	if (hfc->ctrl_cnt) {
 		hfc->ctrl_urb->pipe = hfc->ctrl_out_pipe;
 		hfc->ctrl_urb->setup_packet = (u_char *) & hfc->ctrl_write;
 		hfc->ctrl_urb->transfer_buffer = NULL;
 		hfc->ctrl_urb->transfer_buffer_length = 0;
-		hfc->ctrl_write.wIndex = hfc->ctrl_buff[hfc->ctrl_out_idx].hfc_reg;
-		hfc->ctrl_write.wValue = hfc->ctrl_buff[hfc->ctrl_out_idx].reg_val;
-		err = usb_submit_urb(hfc->ctrl_urb, GFP_ATOMIC);	/* start transfer */
-		printk(KERN_DEBUG "ctrl_start_transfer: submit %d\n", err);
+		hfc->ctrl_write.wIndex =
+		    hfc->ctrl_buff[hfc->ctrl_out_idx].hfc_reg;
+		hfc->ctrl_write.wValue =
+		    hfc->ctrl_buff[hfc->ctrl_out_idx].reg_val;
+
+		usb_submit_urb(hfc->ctrl_urb, GFP_ATOMIC);	/* start transfer */
 	}
 }				/* ctrl_start_transfer */
 
@@ -271,271 +255,284 @@
 /* queue a control transfer request */
 /* return 0 on success.             */
 /************************************/
-static int queue_control_request(hfcusb_data * hfc, __u8 reg, __u8 val,int action)
+static int
+queue_control_request(hfcusb_data * hfc, __u8 reg, __u8 val, int action)
 {
 	ctrl_buft *buf;
 
-#ifdef VERBOSE_USB_DEBUG
-	printk ("HFC_USB: queue_control_request reg: %x, val: %x\n", reg, val);
-#endif
-
-	if(hfc->ctrl_cnt >= HFC_CTRL_BUFSIZE)  return(1);	   /* no space left */
+	if (hfc->ctrl_cnt >= HFC_CTRL_BUFSIZE)
+		return (1);	/* no space left */
 	buf = &hfc->ctrl_buff[hfc->ctrl_in_idx];	/* pointer to new index */
 	buf->hfc_reg = reg;
 	buf->reg_val = val;
-	buf->action=action;
+	buf->action = action;
 	if (++hfc->ctrl_in_idx >= HFC_CTRL_BUFSIZE)
 		hfc->ctrl_in_idx = 0;	/* pointer wrap */
 	if (++hfc->ctrl_cnt == 1)
 		ctrl_start_transfer(hfc);
-	return(0);
-}		/* queue_control_request */
+	return (0);
+}				/* queue_control_request */
 
-
-static int control_action_handler(hfcusb_data *hfc,int reg,int val,int action)
+static int
+control_action_handler(hfcusb_data * hfc, int reg, int val, int action)
 {
-	if(!action) return(1);  // no action defined
-
-	return(0);
+	if (!action)
+		return (1);	/* no action defined */
+	return (0);
 }
 
-
 /***************************************************************/
 /* control completion routine handling background control cmds */
 /***************************************************************/
-static void ctrl_complete(struct urb *urb, struct pt_regs *regs)
+static void
+ctrl_complete(struct urb *urb, struct pt_regs *regs)
 {
 	hfcusb_data *hfc = (hfcusb_data *) urb->context;
 	ctrl_buft *buf;
 
-	printk(KERN_DEBUG "ctrl_complete cnt %d\n", hfc->ctrl_cnt);
 	urb->dev = hfc->dev;
-	if(hfc->ctrl_cnt)
-	{
-		buf=&hfc->ctrl_buff[hfc->ctrl_out_idx];
-		control_action_handler(hfc,buf->hfc_reg,buf->reg_val,buf->action);
+	if (hfc->ctrl_cnt) {
+		buf = &hfc->ctrl_buff[hfc->ctrl_out_idx];
+		control_action_handler(hfc, buf->hfc_reg, buf->reg_val,
+				       buf->action);
 
 		hfc->ctrl_cnt--;	/* decrement actual count */
-		if(++hfc->ctrl_out_idx >= HFC_CTRL_BUFSIZE) hfc->ctrl_out_idx = 0;	/* pointer wrap */
+		if (++hfc->ctrl_out_idx >= HFC_CTRL_BUFSIZE)
+			hfc->ctrl_out_idx = 0;	/* pointer wrap */
 
 		ctrl_start_transfer(hfc);	/* start next transfer */
 	}
 }				/* ctrl_complete */
 
-
-
-#define LED_OFF      0   // no LED support
-#define LED_SCHEME1  1	 // LED standard scheme
-#define LED_SCHEME2  2	 // not used yet...
-
-#define LED_POWER_ON	1
-#define LED_POWER_OFF	2
-#define LED_S0_ON		3
-#define LED_S0_OFF		4
-#define LED_B1_ON		5
-#define LED_B1_OFF		6
-#define LED_B1_DATA		7
-#define LED_B2_ON		8
-#define LED_B2_OFF		9
-#define LED_B2_DATA	   10
-
-#define LED_NORMAL   0	 // LEDs are normal
-#define LED_INVERTED 1   // LEDs are inverted
-
-// time for LED flashing
-#define LED_TIME      250
-
-vendor_data vdata[]=
-{
-    {0x959, 0x2bd0, "ISDN USB TA (Cologne Chip HFC-S USB based)", LED_OFF,LED_NORMAL,{4,0,2,1}},     /* CologneChip Eval TA */
-	{0x7b0, 0x0007, "Billion tiny USB ISDN TA 128", LED_SCHEME1,  LED_INVERTED, {8,0x40,0x20,0x10}},  /* Billion TA */
-	{0x742, 0x2008, "Stollmann USB TA",             LED_SCHEME1,  LED_NORMAL,   {4,0,2,1}},           /* Stollmann TA */
-	{0x8e3, 0x0301, "Olitec USB RNIS",              LED_SCHEME1,  LED_NORMAL,   {2,0,1,4}},           /* Olitec TA  */
-	{0x675, 0x1688, "DrayTec USB ISDN TA",          LED_SCHEME1,  LED_NORMAL,   {4,0,2,1}},           /* Draytec TA */
-	{0x7fa, 0x0846, "Bewan Modem RNIS USB",         LED_SCHEME1,  LED_INVERTED, {8,0x40,0x20,0x10}},  /* Bewan TA   */
-	{0}			   // EOL element
-};
-										
 /***************************************************/
 /* write led data to auxport & invert if necessary */
 /***************************************************/
-static void write_led(hfcusb_data * hfc,__u8 led_state)
+static void
+write_led(hfcusb_data * hfc, __u8 led_state)
 {
-	if(led_state!=hfc->led_state)
-	{
-		hfc->led_state=led_state;
-		queue_control_request(hfc, HFCUSB_P_DATA,(vdata[hfc->vend_idx].led_invert) ? ~led_state : led_state,1);
+	if (led_state != hfc->old_led_state) {
+		hfc->old_led_state = led_state;
+		queue_control_request(hfc, HFCUSB_P_DATA, led_state, 1);
+	}
+}
+
+/**************************/
+/* handle LED bits        */
+/**************************/
+static void
+set_led_bit(hfcusb_data * hfc, signed short led_bits, int unset)
+{
+	if (unset) {
+		if (led_bits < 0)
+			hfc->led_state |= abs(led_bits);
+		else
+			hfc->led_state &= ~led_bits;
+	} else {
+		if (led_bits < 0)
+			hfc->led_state &= ~abs(led_bits);
+		else
+			hfc->led_state |= led_bits;
 	}
 }
 
 /******************************************/
 /* invert B-channel LEDs if data is sent  */
 /******************************************/
-static void led_timer(hfcusb_data * hfc)
+static void
+led_timer(hfcusb_data * hfc)
 {
-   	static int cnt=0;
-	__u8 led_state=hfc->led_state;
+	static int cnt = 0;
 
-	if(cnt)
-	{
-		if(hfc->led_b_active&1) led_state|=vdata[hfc->vend_idx].led_bits[2];
-		if(hfc->led_b_active&2) led_state|=vdata[hfc->vend_idx].led_bits[3];
-	}
-	else
-	{
-		if(!(hfc->led_b_active&1) || hfc->led_new_data&1) led_state&=~vdata[hfc->vend_idx].led_bits[2];
-		if(!(hfc->led_b_active&2) || hfc->led_new_data&2) led_state&=~vdata[hfc->vend_idx].led_bits[3];
+	if (cnt) {
+		if (hfc->led_b_active & 1)
+			set_led_bit(hfc, vdata[hfc->vend_idx].led_bits[2],
+				    0);
+		if (hfc->led_b_active & 2)
+			set_led_bit(hfc, vdata[hfc->vend_idx].led_bits[3],
+				    0);
+	} else {
+		if (!(hfc->led_b_active & 1) || hfc->led_new_data & 1)
+			set_led_bit(hfc, vdata[hfc->vend_idx].led_bits[2],
+				    1);
+		if (!(hfc->led_b_active & 2) || hfc->led_new_data & 2)
+			set_led_bit(hfc, vdata[hfc->vend_idx].led_bits[3],
+				    1);
+	}
+
+	write_led(hfc, hfc->led_state);
+	hfc->led_new_data = 0;
+
+	cnt = !cnt;
+
+	/* restart 4 hz timer */
+	if (!timer_pending(&hfc->led_timer)) {
+		add_timer(&hfc->led_timer);
+		hfc->led_timer.expires = jiffies + (LED_TIME * HZ) / 1000;
 	}
-
-	write_led(hfc,led_state);
-	hfc->led_new_data=0;
-
-	cnt=!cnt;
-	// restart 4 hz timer
-	hfc->led_timer.expires = jiffies + (LED_TIME * HZ) / 1000;
-	if(!timer_pending(&hfc->led_timer)) add_timer(&hfc->led_timer);
 }
 
 /**************************/
 /* handle LED requests    */
 /**************************/
-static void handle_led(hfcusb_data * hfc,int event)
+static void
+handle_led(hfcusb_data * hfc, int event)
 {
-	__u8 led_state=hfc->led_state;
-
-	// if no scheme -> no LED action
-   	if(vdata[hfc->vend_idx].led_scheme==LED_OFF) return;
+	/* if no scheme -> no LED action */
+	if (vdata[hfc->vend_idx].led_scheme == LED_OFF)
+		return;
 
-	switch(event)
-	{
+	switch (event) {
 		case LED_POWER_ON:
-				   led_state|=vdata[hfc->vend_idx].led_bits[0];
-				break;
-		case LED_POWER_OFF: // no Power off handling
-				break;
+			set_led_bit(hfc, vdata[hfc->vend_idx].led_bits[0],
+				    0);
+			set_led_bit(hfc, vdata[hfc->vend_idx].led_bits[1],
+				    1);
+			set_led_bit(hfc, vdata[hfc->vend_idx].led_bits[2],
+				    1);
+			set_led_bit(hfc, vdata[hfc->vend_idx].led_bits[3],
+				    1);
+			break;
+		case LED_POWER_OFF:	/* no Power off handling */
+			break;
 		case LED_S0_ON:
-				   led_state|=vdata[hfc->vend_idx].led_bits[1];
-				break;
+			set_led_bit(hfc, vdata[hfc->vend_idx].led_bits[1],
+				    0);
+			break;
 		case LED_S0_OFF:
-				   led_state&=~vdata[hfc->vend_idx].led_bits[1];
-				break;
+			set_led_bit(hfc, vdata[hfc->vend_idx].led_bits[1],
+				    1);
+			break;
 		case LED_B1_ON:
-					hfc->led_b_active|=1;
-				break;
+			hfc->led_b_active |= 1;
+			break;
 		case LED_B1_OFF:
-					hfc->led_b_active&=~1;
-				break;
+			hfc->led_b_active &= ~1;
+			break;
 		case LED_B1_DATA:
-				   hfc->led_new_data|=1;
-				break;
+			hfc->led_new_data |= 1;
+			break;
 		case LED_B2_ON:
-				   hfc->led_b_active|=2;
-				break;
+			hfc->led_b_active |= 2;
+			break;
 		case LED_B2_OFF:
-					hfc->led_b_active&=~2;
-				break;
+			hfc->led_b_active &= ~2;
+			break;
 		case LED_B2_DATA:
-				   hfc->led_new_data|=2;
-				break;
+			hfc->led_new_data |= 2;
+			break;
 	}
-	
-	write_led(hfc,led_state);
+
+	write_led(hfc, hfc->led_state);
 }
 
 /********************************/
 /* called when timer t3 expires */
 /********************************/
-static void l1_timer_expire_t3(hfcusb_data * hfc)
+static void
+l1_timer_expire_t3(hfcusb_data * hfc)
 {
-    //printk (KERN_INFO "HFC-USB: l1_timer_expire_t3\n");
-
-	hfc->d_if.ifc.l1l2(&hfc->d_if.ifc,PH_DEACTIVATE | INDICATION,NULL);
-#ifdef VERBOSE_USB_DEBUG
-	printk(KERN_INFO "PH_DEACTIVATE | INDICATION sent\n");
-#endif
-	hfc->l1_activated=FALSE;
-	handle_led(hfc,LED_S0_OFF);
+	hfc->d_if.ifc.l1l2(&hfc->d_if.ifc, PH_DEACTIVATE | INDICATION,
+			   NULL);
+#ifdef CONFIG_HISAX_DEBUG
+	DBG(ISDN_DBG,
+	    "HFC-S USB: PH_DEACTIVATE | INDICATION sent (T3 expire)");
+#endif
+	hfc->l1_activated = FALSE;
+	handle_led(hfc, LED_S0_OFF);
+	/* deactivate : */
+	queue_control_request(hfc, HFCUSB_STATES, 0x10, 1);
+	queue_control_request(hfc, HFCUSB_STATES, 3, 1);
 }
 
 /********************************/
 /* called when timer t4 expires */
 /********************************/
-static void l1_timer_expire_t4(hfcusb_data * hfc)
+static void
+l1_timer_expire_t4(hfcusb_data * hfc)
 {
-    //printk (KERN_INFO "HFC-USB: l1_timer_expire_t4\n");
-
-	hfc->d_if.ifc.l1l2(&hfc->d_if.ifc,PH_DEACTIVATE | INDICATION,NULL);
-#ifdef VERBOSE_USB_DEBUG
-	printk(KERN_INFO "PH_DEACTIVATE | INDICATION sent\n");
+	hfc->d_if.ifc.l1l2(&hfc->d_if.ifc, PH_DEACTIVATE | INDICATION,
+			   NULL);
+#ifdef CONFIG_HISAX_DEBUG
+	DBG(ISDN_DBG,
+	    "HFC-S USB: PH_DEACTIVATE | INDICATION sent (T4 expire)");
 #endif
-	hfc->l1_activated=FALSE;
-	handle_led(hfc,LED_S0_OFF);
+	hfc->l1_activated = FALSE;
+	handle_led(hfc, LED_S0_OFF);
 }
 
 /*****************************/
 /* handle S0 state changes   */
 /*****************************/
-static void state_handler(hfcusb_data * hfc,__u8 state)
+static void
+state_handler(hfcusb_data * hfc, __u8 state)
 {
 	__u8 old_state;
 
-	old_state=hfc->l1_state;
-
-	// range check
-	if(state==old_state || state<1 || state>8) return;
+	old_state = hfc->l1_state;
+	if (state == old_state || state < 1 || state > 8)
+		return;
 
-#ifdef VERBOSE_ISDN_DEBUG
-	printk(KERN_INFO "HFC-USB: new S0 state:%d old_state:%d\n",state,old_state);
+#ifdef CONFIG_HISAX_DEBUG
+	DBG(ISDN_DBG, "HFC-S USB: new S0 state:%d old_state:%d", state,
+	    old_state);
+#endif
+	if (state < 4 || state == 7 || state == 8) {
+		if (timer_pending(&hfc->t3_timer))
+			del_timer(&hfc->t3_timer);
+#ifdef CONFIG_HISAX_DEBUG
+		DBG(ISDN_DBG, "HFC-S USB: T3 deactivated");
+#endif
+	}
+	if (state >= 7) {
+		if (timer_pending(&hfc->t4_timer))
+			del_timer(&hfc->t4_timer);
+#ifdef CONFIG_HISAX_DEBUG
+		DBG(ISDN_DBG, "HFC-S USB: T4 deactivated");
 #endif
+	}
 
-	if(state<4 || state==7 || state==8)
-	{
-        if(timer_pending(&hfc->t3_timer)) del_timer(&hfc->t3_timer);
-		//printk(KERN_INFO "HFC-USB: T3 deactivated\n");
-	}
-
-	if(state>=7)
-	{
-        if(timer_pending(&hfc->t4_timer)) del_timer(&hfc->t4_timer);
-		//printk(KERN_INFO "HFC-USB: T4 deactivated\n");
-	}
-
-	if(state==7 && !hfc->l1_activated)
-	{
-		hfc->d_if.ifc.l1l2(&hfc->d_if.ifc,PH_ACTIVATE | INDICATION,NULL);
-		//printk(KERN_INFO "HFC-USB: PH_ACTIVATE | INDICATION sent\n");
-		hfc->l1_activated=TRUE;
-		handle_led(hfc,LED_S0_ON);
-	}
-	else
-	if(state<=3 /* && activated*/)
-	{
-		if(old_state==7 || old_state==8)
-		{
-			//printk(KERN_INFO "HFC-USB: T4 activated\n");
-			hfc->t4_timer.expires = jiffies + (HFC_TIMER_T4 * HZ) / 1000;
-			if(!timer_pending(&hfc->t4_timer)) add_timer(&hfc->t4_timer);
-		}
-		else
-		{
-			hfc->d_if.ifc.l1l2(&hfc->d_if.ifc,PH_DEACTIVATE | INDICATION,NULL);
-			//printk(KERN_INFO "HFC-USB: PH_DEACTIVATE | INDICATION sent\n");
-			hfc->l1_activated=FALSE;
-			handle_led(hfc,LED_S0_OFF);
+	if (state == 7 && !hfc->l1_activated) {
+		hfc->d_if.ifc.l1l2(&hfc->d_if.ifc,
+				   PH_ACTIVATE | INDICATION, NULL);
+#ifdef CONFIG_HISAX_DEBUG
+		DBG(ISDN_DBG, "HFC-S USB: PH_ACTIVATE | INDICATION sent");
+#endif
+		hfc->l1_activated = TRUE;
+		handle_led(hfc, LED_S0_ON);
+	} else if (state <= 3 /* && activated */ ) {
+		if (old_state == 7 || old_state == 8) {
+#ifdef CONFIG_HISAX_DEBUG
+			DBG(ISDN_DBG, "HFC-S USB: T4 activated");
+#endif
+			if (!timer_pending(&hfc->t4_timer)) {
+				hfc->t4_timer.expires =
+				    jiffies + (HFC_TIMER_T4 * HZ) / 1000;
+				add_timer(&hfc->t4_timer);
+			}
+		} else {
+			hfc->d_if.ifc.l1l2(&hfc->d_if.ifc,
+					   PH_DEACTIVATE | INDICATION,
+					   NULL);
+#ifdef CONFIG_HISAX_DEBUG
+			DBG(ISDN_DBG,
+			    "HFC-S USB: PH_DEACTIVATE | INDICATION sent");
+#endif
+			hfc->l1_activated = FALSE;
+			handle_led(hfc, LED_S0_OFF);
 		}
 	}
-
-	hfc->l1_state=state;
+	hfc->l1_state = state;
 }
 
-
 /* prepare iso urb */
-static void fill_isoc_urb(struct urb *urb, struct usb_device *dev, unsigned int pipe, void *buf,
-	int num_packets, int packet_size, int interval, usb_complete_t complete, void *context)
+static void
+fill_isoc_urb(struct urb *urb, struct usb_device *dev, unsigned int pipe,
+	      void *buf, int num_packets, int packet_size, int interval,
+	      usb_complete_t complete, void *context)
 {
 	int k;
 
-	spin_lock_init(&urb->lock);	// do we really need spin_lock_init ?
+	spin_lock_init(&urb->lock);
 	urb->dev = dev;
 	urb->pipe = pipe;
 	urb->complete = complete;
@@ -543,7 +540,6 @@
 	urb->transfer_buffer_length = packet_size * num_packets;
 	urb->context = context;
 	urb->transfer_buffer = buf;
-	urb->transfer_flags = 0;
 	urb->transfer_flags = URB_ISO_ASAP;
 	urb->actual_length = 0;
 	urb->interval = interval;
@@ -554,67 +550,80 @@
 	}
 }
 
-/* allocs urbs and start isoc transfer with two pending urbs to avoid gaps in the transfer chain */
-static int start_isoc_chain(usb_fifo * fifo, int num_packets_per_urb,usb_complete_t complete,int packet_size)
+/* allocs urbs and start isoc transfer with two pending urbs to avoid
+   gaps in the transfer chain */
+static int
+start_isoc_chain(usb_fifo * fifo, int num_packets_per_urb,
+		 usb_complete_t complete, int packet_size)
 {
 	int i, k, errcode;
 
-#ifdef VERBOSE_USB_DEBUG
-	printk(KERN_INFO "HFC-USB: starting ISO-chain for Fifo %i\n",  fifo->fifonum);
-#endif
-
+	printk(KERN_INFO "HFC-S USB: starting ISO-chain for Fifo %i\n",
+	       fifo->fifonum);
 
-	// allocate Memory for Iso out Urbs
+	/* allocate Memory for Iso out Urbs */
 	for (i = 0; i < 2; i++) {
 		if (!(fifo->iso[i].purb)) {
-			fifo->iso[i].purb = usb_alloc_urb(num_packets_per_urb, GFP_KERNEL);
+			fifo->iso[i].purb =
+			    usb_alloc_urb(num_packets_per_urb, GFP_KERNEL);
+			if (!(fifo->iso[i].purb)) {
+				printk(KERN_INFO
+				       "alloc urb for fifo %i failed!!!",
+				       fifo->fifonum);
+			}
 			fifo->iso[i].owner_fifo = (struct usb_fifo *) fifo;
 
-			// Init the first iso
-			if (ISO_BUFFER_SIZE >= (fifo->usb_packet_maxlen * num_packets_per_urb))
-			{
-
-				fill_isoc_urb(fifo->iso[i].purb, fifo->hfc->dev, fifo->pipe, fifo->iso[i].buffer,
-					num_packets_per_urb, fifo->usb_packet_maxlen, fifo->intervall,
-					complete, &fifo->iso[i]);
-
-				memset(fifo->iso[i].buffer, 0, sizeof(fifo->iso[i].buffer));
-
-				// defining packet delimeters in fifo->buffer
-				for(k = 0; k < num_packets_per_urb; k++)
-				{
-					fifo->iso[i].purb->iso_frame_desc[k].offset = k*packet_size;
-					fifo->iso[i].purb->iso_frame_desc[k].length = packet_size;
+			/* Init the first iso */
+			if (ISO_BUFFER_SIZE >=
+			    (fifo->usb_packet_maxlen *
+			     num_packets_per_urb)) {
+				fill_isoc_urb(fifo->iso[i].purb,
+					      fifo->hfc->dev, fifo->pipe,
+					      fifo->iso[i].buffer,
+					      num_packets_per_urb,
+					      fifo->usb_packet_maxlen,
+					      fifo->intervall, complete,
+					      &fifo->iso[i]);
+				memset(fifo->iso[i].buffer, 0,
+				       sizeof(fifo->iso[i].buffer));
+				/* defining packet delimeters in fifo->buffer */
+				for (k = 0; k < num_packets_per_urb; k++) {
+					fifo->iso[i].purb->
+					    iso_frame_desc[k].offset =
+					    k * packet_size;
+					fifo->iso[i].purb->
+					    iso_frame_desc[k].length =
+					    packet_size;
 				}
+			} else {
+				printk(KERN_INFO
+				       "HFC-S USB: ISO Buffer size to small!\n");
 			}
 		}
-
 		fifo->bit_line = BITLINE_INF;
 
 		errcode = usb_submit_urb(fifo->iso[i].purb, GFP_KERNEL);
 		fifo->active = (errcode >= 0) ? 1 : 0;
-		if(errcode < 0)
-		{
-			printk(KERN_INFO "HFC-USB: error submitting ISO URB: %i.%i \n",  errcode, i);
+		if (errcode < 0) {
+			printk(KERN_INFO "HFC-S USB: %s  URB nr:%d\n",
+			       symbolic(urb_errlist, errcode), i);
 		};
-
 	}
-
-	// errcode = (usb_submit_urb(fifo->iso[0].purb, GFP_KERNEL));
-	return(fifo->active);
+	return (fifo->active);
 }
 
 /* stops running iso chain and frees their pending urbs */
-static void stop_isoc_chain(usb_fifo * fifo)
+static void
+stop_isoc_chain(usb_fifo * fifo)
 {
 	int i;
 
-	for(i = 0; i < 2; i++)
-	{
-		if(fifo->iso[i].purb)
-		{
-#ifdef VERBOSE_USB_DEBUG
-			printk(KERN_INFO "HFC-USB: Stopping iso chain for fifo %i.%i\n", fifo->fifonum, i);
+	for (i = 0; i < 2; i++) {
+		if (fifo->iso[i].purb) {
+#ifdef CONFIG_HISAX_DEBUG
+			DBG(USB_DBG,
+			    "HFC-S USB: Stopping iso chain for fifo %i.%i",
+			    fifo->fifonum, i);
 #endif
 			usb_unlink_urb(fifo->iso[i].purb);
 			usb_free_urb(fifo->iso[i].purb);
@@ -629,554 +638,653 @@
 	fifo->active = 0;
 }
 
-// defines how much ISO packets are handled in one URB
-static int iso_packets[8]={ISOC_PACKETS_B,ISOC_PACKETS_B,ISOC_PACKETS_B,ISOC_PACKETS_B,
-	                       ISOC_PACKETS_D,ISOC_PACKETS_D,ISOC_PACKETS_D,ISOC_PACKETS_D};
+/* defines how much ISO packets are handled in one URB */
+static int iso_packets[8] =
+    { ISOC_PACKETS_B, ISOC_PACKETS_B, ISOC_PACKETS_B, ISOC_PACKETS_B,
+	ISOC_PACKETS_D, ISOC_PACKETS_D, ISOC_PACKETS_D, ISOC_PACKETS_D
+};
 
 /*****************************************************/
 /* transmit completion routine for all ISO tx fifos */
 /*****************************************************/
-static void tx_iso_complete(struct urb *urb, struct pt_regs *regs)
+static void
+tx_iso_complete(struct urb *urb, struct pt_regs *regs)
 {
 	iso_urb_struct *context_iso_urb = (iso_urb_struct *) urb->context;
 	usb_fifo *fifo = context_iso_urb->owner_fifo;
 	hfcusb_data *hfc = fifo->hfc;
-	int k, tx_offset, num_isoc_packets, sink, len, current_len,errcode,frame_complete,transp_mode,fifon;
+	int k, tx_offset, num_isoc_packets, sink, len, current_len,
+	    errcode;
+	int frame_complete, transp_mode, fifon, status;
 	__u8 threshbit;
-	__u8 threshtable[8] = { 1, 2, 4, 8, 0x10, 0x20, 0x40, 0x80};
+	__u8 threshtable[8] = { 1, 2, 4, 8, 0x10, 0x20, 0x40, 0x80 };
 
-	fifon=fifo->fifonum;
-	tx_offset=0;
-	// very weird error code when using ohci drivers, for now : ignore this error ...  (MB)
-	if(urb->status == -EOVERFLOW)
-	{
-		urb->status = 0;
-#ifdef VERBOSE_USB_DEBUG
-		printk(KERN_INFO "HFC-USB: ignoring USB DATAOVERRUN  for fifo  %i \n",fifon);
-#endif
-	}
+	fifon = fifo->fifonum;
+	status = urb->status;
 
-	if(fifo->active && !urb->status)
-	{
-		transp_mode=0;
-		if(fifon<4 && hfc->b_mode[fifon/2]==L1_MODE_TRANS) transp_mode=TRUE;
-
-		threshbit = threshtable[fifon] & hfc->threshold_mask;	// is threshold set for our channel?
-		num_isoc_packets=iso_packets[fifon];
-
-		if(fifon >= HFCUSB_D_TX)
-		{
-			sink = (threshbit) ? SINK_DMIN : SINK_DMAX;	// how much bit go to the sink for D-channel?
-		}
-		else
-		{
-			sink = (threshbit) ? SINK_MIN : SINK_MAX;	// how much bit go to the sink for B-channel?
-		}
+	tx_offset = 0;
+
+	if (fifo->active && !status) {
+		transp_mode = 0;
+		if (fifon < 4 && hfc->b_mode[fifon / 2] == L1_MODE_TRANS)
+			transp_mode = TRUE;
 
-		// prepare ISO Urb
-		fill_isoc_urb(urb, fifo->hfc->dev, fifo->pipe,context_iso_urb->buffer, num_isoc_packets,
-			fifo->usb_packet_maxlen, fifo->intervall, tx_iso_complete, urb->context);
-		memset(context_iso_urb->buffer, 0, sizeof(context_iso_urb->buffer));
-
-		frame_complete=FALSE;
-
-		// Generate Iso Packets
-		for(k = 0; k < num_isoc_packets; ++k)
-		{
-			if(fifo->skbuff)
-			{
-				len = fifo->skbuff->len;	// remaining length
+		/* is FifoFull-threshold set for our channel? */
+		threshbit = threshtable[fifon] & hfc->threshold_mask;
+		num_isoc_packets = iso_packets[fifon];
 
-				fifo->bit_line -= sink;	// we lower data margin every msec
+		/* predict dataflow to avoid fifo overflow */
+		if (fifon >= HFCUSB_D_TX) {
+			sink = (threshbit) ? SINK_DMIN : SINK_DMAX;
+		} else {
+			sink = (threshbit) ? SINK_MIN : SINK_MAX;
+		}
+		fill_isoc_urb(urb, fifo->hfc->dev, fifo->pipe,
+			      context_iso_urb->buffer, num_isoc_packets,
+			      fifo->usb_packet_maxlen, fifo->intervall,
+			      tx_iso_complete, urb->context);
+		memset(context_iso_urb->buffer, 0,
+		       sizeof(context_iso_urb->buffer));
+		frame_complete = FALSE;
+		/* Generate next Iso Packets */
+		for (k = 0; k < num_isoc_packets; ++k) {
+			if (fifo->skbuff) {
+				len = fifo->skbuff->len;
+				/* we lower data margin every msec */
+				fifo->bit_line -= sink;
 				current_len = (0 - fifo->bit_line) / 8;
-				if(current_len > 14) current_len = 14;	// maximum 15 byte for every ISO packet makes our life easier
-				current_len = (len <= current_len) ? len : current_len;
-				fifo->bit_line += current_len * 8;	// how much bit do we put on the line?
+				/* maximum 15 byte for every ISO packet makes our life easier */
+				if (current_len > 14)
+					current_len = 14;
+				current_len =
+				    (len <=
+				     current_len) ? len : current_len;
+				/* how much bit do we put on the line? */
+				fifo->bit_line += current_len * 8;
 
 				context_iso_urb->buffer[tx_offset] = 0;
-				if(current_len == len)
-				{
-					if(!transp_mode)
-					{
-						context_iso_urb->buffer[tx_offset] = 1;	// here frame completion
-						fifo->bit_line += 32;	// add 2 byte flags and 16bit CRC at end of ISDN frame
+				if (current_len == len) {
+					if (!transp_mode) {
+						/* here frame completion */
+						context_iso_urb->
+						    buffer[tx_offset] = 1;
+						/* add 2 byte flags and 16bit CRC at end of ISDN frame */
+						fifo->bit_line += 32;
 					}
 					frame_complete = TRUE;
 				}
 
-				// copy bytes from buffer into ISO_URB
-				memcpy(context_iso_urb->buffer+tx_offset+1,fifo->skbuff->data,current_len);
-				skb_pull(fifo->skbuff,current_len);
+				memcpy(context_iso_urb->buffer +
+				       tx_offset + 1, fifo->skbuff->data,
+				       current_len);
+				skb_pull(fifo->skbuff, current_len);
 
-				// define packet delimeters within the URB buffer
+				/* define packet delimeters within the URB buffer */
 				urb->iso_frame_desc[k].offset = tx_offset;
-				urb->iso_frame_desc[k].length = current_len + 1;
+				urb->iso_frame_desc[k].length =
+				    current_len + 1;
 
 				tx_offset += (current_len + 1);
-				// printk(KERN_INFO "HFC-USB: fifonum:%d,%d bytes to send, %d bytes ISO packet,bitline:%d,sink:%d,threshbit:%d,threshmask:%x\n",fifon,len,current_len,fifo->bit_line,sink,threshbit,hfc->threshold_mask);
-				if(!transp_mode)
-				{
-					if(fifon==HFCUSB_B1_TX) handle_led(hfc,LED_B1_DATA);
-					if(fifon==HFCUSB_B2_TX) handle_led(hfc,LED_B2_DATA);
+				if (!transp_mode) {
+					if (fifon == HFCUSB_B1_TX)
+						handle_led(hfc,
+							   LED_B1_DATA);
+					if (fifon == HFCUSB_B2_TX)
+						handle_led(hfc,
+							   LED_B2_DATA);
 				}
-			}
-			else
-			{
-				// we have no more data - generate 1 byte ISO packets
-				urb->iso_frame_desc[k].offset = tx_offset++;
+			} else {
+				urb->iso_frame_desc[k].offset =
+				    tx_offset++;
 
 				urb->iso_frame_desc[k].length = 1;
-				fifo->bit_line -= sink;	// we lower data margin every msec
+				fifo->bit_line -= sink;	/* we lower data margin every msec */
 
-				if(fifo->bit_line < BITLINE_INF)
-				{
+				if (fifo->bit_line < BITLINE_INF) {
 					fifo->bit_line = BITLINE_INF;
-					//printk (KERN_INFO "HFC-USB: BITLINE_INF underrun\n");
 				}
 			}
 
-			if(frame_complete)
-			{
-				// delete the buffer only once, here or in hfc_usb_l2l1() in a PH_DATA|REQUEST
-				fifo->delete_flg=TRUE;
-
-				fifo->hif->l1l2(fifo->hif,PH_DATA|CONFIRM,(void*)fifo->skbuff->truesize);
-
-				if(fifo->skbuff && fifo->delete_flg)
-				{
+			if (frame_complete) {
+				fifo->delete_flg = TRUE;
+				fifo->hif->l1l2(fifo->hif,
+						PH_DATA | CONFIRM,
+						(void *) fifo->skbuff->
+						truesize);
+				if (fifo->skbuff && fifo->delete_flg) {
 					dev_kfree_skb_any(fifo->skbuff);
-					//printk(KERN_INFO "HFC-USB: skbuff=NULL on fifo:%d\n",fifo->fifonum);
 					fifo->skbuff = NULL;
-					fifo->delete_flg=FALSE;
+					fifo->delete_flg = FALSE;
 				}
-
-				frame_complete=FALSE;
+				frame_complete = FALSE;
 			}
-        }
-
+		}
 		errcode = usb_submit_urb(urb, GFP_ATOMIC);
-		if(errcode < 0)
-		{
-			printk(KERN_INFO "HFC-USB: error submitting ISO URB: %i \n",  errcode);
+		if (errcode < 0) {
+			printk(KERN_INFO
+			       "HFC-S USB: error submitting ISO URB: %d \n",
+			       errcode);
 		}
-	}
-	else
-	{
-		if(urb->status)
-		{
-			printk(KERN_INFO "HFC-USB: tx_iso_complete : urb->status %i, fifonum %i\n",  urb->status,fifon);
+	} else {
+		if (status && !hfc->disc_flag) {
+			printk(KERN_INFO
+			       "HFC-S USB: tx_iso_complete : urb->status %s (%i), fifonum=%d\n",
+			       symbolic(urb_errlist, status), status,
+			       fifon);
 		}
 	}
-
 }				/* tx_iso_complete */
 
 /*****************************************************/
 /* receive completion routine for all ISO tx fifos   */
 /*****************************************************/
-static void rx_iso_complete(struct urb *urb, struct pt_regs *regs)
+static void
+rx_iso_complete(struct urb *urb, struct pt_regs *regs)
 {
 	iso_urb_struct *context_iso_urb = (iso_urb_struct *) urb->context;
 	usb_fifo *fifo = context_iso_urb->owner_fifo;
 	hfcusb_data *hfc = fifo->hfc;
-	int k, len, errcode, offset, num_isoc_packets,fifon;
+	int k, len, errcode, offset, num_isoc_packets, fifon, maxlen,
+	    status;
+	unsigned int iso_status;
 	__u8 *buf;
-
-	fifon=fifo->fifonum;
-	// very weird error code when using ohci drivers, for now : ignore this error ...  (MB)
-	if(urb->status == -EOVERFLOW)
-	{
-		urb->status = 0;
-#ifdef VERBOSE_USB_DEBUG
-		printk(KERN_INFO "HFC-USB: ignoring USB DATAOVERRUN  for fifo  %i \n",fifon);
+	static __u8 eof[8];
+#ifdef CONFIG_HISAX_DEBUG
+	__u8 i;
+#endif
+
+	fifon = fifo->fifonum;
+	status = urb->status;
+
+	if (urb->status == -EOVERFLOW) {
+#ifdef CONFIG_HISAX_DEBUG
+		DBG(USB_DBG,
+		    "HFC-USB: ignoring USB DATAOVERRUN  for fifo  %i \n",
+		    fifon);
+#endif
+		status = 0;
+	}
+	if (fifo->active && !status) {
+		num_isoc_packets = iso_packets[fifon];
+		maxlen = fifo->usb_packet_maxlen;
+		for (k = 0; k < num_isoc_packets; ++k) {
+			len = urb->iso_frame_desc[k].actual_length;
+			offset = urb->iso_frame_desc[k].offset;
+			buf = context_iso_urb->buffer + offset;
+			iso_status = urb->iso_frame_desc[k].status;
+#ifdef CONFIG_HISAX_DEBUG
+			if (iso_status && !hfc->disc_flag)
+				DBG(USB_DBG,
+				    "HFC-S USB: ISO packet failure - status:%x",
+				    iso_status);
+
+			if ((fifon == 5) && (debug > 1)) {
+				printk(KERN_INFO
+				       "HFC-S USB: ISO-D-RX lst_urblen:%2d "
+				       "act_urblen:%2d max-urblen:%2d "
+				       "EOF:0x%0x DATA: ",
+				       fifo->last_urblen, len, maxlen,
+				       eof[5]);
+				for (i = 0; i < len; i++)
+					printk("%.2x ", buf[i]);
+				printk("\n");
+			}
 #endif
-	}
-
-	if(fifo->active && !urb->status)
-	{
-		num_isoc_packets=iso_packets[fifon];
-
-		// Generate D-Channel Iso Packets
-		for(k = 0; k < num_isoc_packets; ++k)
-		{
-			len=urb->iso_frame_desc[k].actual_length;
-			offset=urb->iso_frame_desc[k].offset;
-			buf=context_iso_urb->buffer+offset;
-
-			if(fifo->last_urblen!=fifo->usb_packet_maxlen)
-			{
-				// the threshold mask is in the 2nd status byte
-				hfc->threshold_mask=buf[1];
-				// the S0 state is in the upper half of the 1st status byte
-				state_handler(hfc,buf[0] >> 4);
-				// if we have more than the 2 status bytes -> collect data
-				if(len>2) collect_rx_frame(fifo,buf+2,len-2,buf[0]&1);
+			if (fifo->last_urblen != maxlen) {
+				/* the threshold mask is in the 2nd status byte */
+				hfc->threshold_mask = buf[1];
+				/* care for L1 state only for D-Channel
+				   to avoid overlapped iso completions */
+				if (fifon == 5) {
+					/* the S0 state is in the upper half
+					   of the 1st status byte */
+					state_handler(hfc, buf[0] >> 4);
+				}
+				eof[fifon] = buf[0] & 1;
+				if (len > 2)
+					collect_rx_frame(fifo, buf + 2,
+							 len - 2,
+							 (len <
+							  maxlen) ?
+							 eof[fifon] : 0);
+			} else {
+				collect_rx_frame(fifo, buf, len,
+						 (len <
+						  maxlen) ? eof[fifon] :
+						 0);
 			}
-			else collect_rx_frame(fifo,buf,len,0);
-
-			fifo->last_urblen=len;
-
-        }
-
-		// prepare ISO Urb
-		fill_isoc_urb(urb, fifo->hfc->dev, fifo->pipe,context_iso_urb->buffer, num_isoc_packets,
-			fifo->usb_packet_maxlen, fifo->intervall, rx_iso_complete, urb->context);
+			fifo->last_urblen = len;
+		}
 
+		fill_isoc_urb(urb, fifo->hfc->dev, fifo->pipe,
+			      context_iso_urb->buffer, num_isoc_packets,
+			      fifo->usb_packet_maxlen, fifo->intervall,
+			      rx_iso_complete, urb->context);
 		errcode = usb_submit_urb(urb, GFP_ATOMIC);
-		if(errcode < 0)
-		{
-			printk(KERN_INFO "HFC-USB: error submitting ISO URB: %i \n",  errcode);
+		if (errcode < 0) {
+			printk(KERN_INFO
+			       "HFC-S USB: error submitting ISO URB: %d \n",
+			       errcode);
 		}
-	}
-	else
-	{
-		if(urb->status)
-		{
-			printk(KERN_INFO "HFC-USB: rx_iso_complete : urb->status %i, fifonum %i\n",  urb->status,fifon);
+	} else {
+		if (status && !hfc->disc_flag) {
+			printk(KERN_INFO
+			       "HFC-S USB: rx_iso_complete : "
+			       "urb->status %d, fifonum %d\n",
+			       status, fifon);
 		}
 	}
 }				/* rx_iso_complete */
 
-
 /*****************************************************/
 /* collect data from interrupt or isochron in        */
 /*****************************************************/
-static void collect_rx_frame(usb_fifo *fifo,__u8 *data,int len,int finish)
+static void
+collect_rx_frame(usb_fifo * fifo, __u8 * data, int len, int finish)
 {
 	hfcusb_data *hfc = fifo->hfc;
-	int transp_mode,fifon;
-
-	fifon=fifo->fifonum;
-	transp_mode=0;
-	if(fifon<4 && hfc->b_mode[fifon/2]==L1_MODE_TRANS) transp_mode=TRUE;
-
-	//printk(KERN_INFO "HFC-USB: got %d bytes finish:%d max_size:%d fifo:%d\n",len,finish,fifo->max_size,fifon);
-	if(!fifo->skbuff)
-	{
-		// allocate sk buffer
-		fifo->skbuff=dev_alloc_skb(fifo->max_size + 3);
-		if(!fifo->skbuff)
-		{
-			printk(KERN_INFO "HFC-USB: cannot allocate buffer (dev_alloc_skb) fifo:%d\n",fifon);
+	int transp_mode, fifon;
+#ifdef CONFIG_HISAX_DEBUG
+	int i;
+#endif
+	fifon = fifo->fifonum;
+	transp_mode = 0;
+	if (fifon < 4 && hfc->b_mode[fifon / 2] == L1_MODE_TRANS)
+		transp_mode = TRUE;
+
+	if (!fifo->skbuff) {
+		fifo->skbuff = dev_alloc_skb(fifo->max_size + 3);
+		if (!fifo->skbuff) {
+			printk(KERN_INFO
+			       "HFC-S USB: cannot allocate buffer (dev_alloc_skb) fifo:%d\n",
+			       fifon);
 			return;
 		}
-		
 	}
-
-	if(len && fifo->skbuff->len+len<fifo->max_size)
-	{
-		memcpy(skb_put(fifo->skbuff,len),data,len);
+	if (len) {
+		if (fifo->skbuff->len + len < fifo->max_size) {
+			memcpy(skb_put(fifo->skbuff, len), data, len);
+		} else {
+#ifdef CONFIG_HISAX_DEBUG
+			printk(KERN_INFO "HFC-S USB: ");
+			for (i = 0; i < 15; i++)
+				printk("%.2x ",
+				       fifo->skbuff->data[fifo->skbuff->
+							  len - 15 + i]);
+			printk("\n");
+#endif
+			printk(KERN_INFO
+			       "HCF-USB: got frame exceeded fifo->max_size:%d on fifo:%d\n",
+			       fifo->max_size, fifon);
+		}
 	}
-	else printk(KERN_INFO "HCF-USB: got frame exceeded fifo->max_size:%d\n",fifo->max_size);
-
-	// give transparent data up, when 128 byte are available
-	if(transp_mode && fifo->skbuff->len>=128)
-	{
-		fifo->hif->l1l2(fifo->hif,PH_DATA | INDICATION,fifo->skbuff);
-		fifo->skbuff = NULL;  // buffer was freed from upper layer
+	if (transp_mode && fifo->skbuff->len >= 128) {
+		fifo->hif->l1l2(fifo->hif, PH_DATA | INDICATION,
+				fifo->skbuff);
+		fifo->skbuff = NULL;
 		return;
 	}
-
-	// we have a complete hdlc packet
-	if(finish)
-	{
-		if(!fifo->skbuff->data[fifo->skbuff->len-1])
-		{
-			skb_trim(fifo->skbuff,fifo->skbuff->len-3);  // remove CRC & status
-
-			//printk(KERN_INFO "HFC-USB: got frame %d bytes on fifo:%d\n",fifo->skbuff->len,fifon);
-
-			if(fifon==HFCUSB_PCM_RX) fifo->hif->l1l2(fifo->hif,PH_DATA_E | INDICATION,fifo->skbuff);
-			else fifo->hif->l1l2(fifo->hif,PH_DATA | INDICATION,fifo->skbuff);
-
-			fifo->skbuff = NULL;  // buffer was freed from upper layer
-		}
-		else
-		{
-			printk(KERN_INFO "HFC-USB: got frame %d bytes but CRC ERROR!!!\n",fifo->skbuff->len);
-
-			skb_trim(fifo->skbuff,0);  // clear whole buffer
+	/* we have a complete hdlc packet */
+	if (finish) {
+		if ((!fifo->skbuff->data[fifo->skbuff->len - 1])
+		    && (fifo->skbuff->len > 3)) {
+			/* remove CRC & status */
+			skb_trim(fifo->skbuff, fifo->skbuff->len - 3);
+			if (fifon == HFCUSB_PCM_RX) {
+				fifo->hif->l1l2(fifo->hif,
+						PH_DATA_E | INDICATION,
+						fifo->skbuff);
+			} else
+				fifo->hif->l1l2(fifo->hif,
+						PH_DATA | INDICATION,
+						fifo->skbuff);
+			fifo->skbuff = NULL;	/* buffer was freed from upper layer */
+		} else {
+			if (fifo->skbuff->len > 3) {
+				printk(KERN_INFO
+				       "HFC-S USB: got frame %d bytes but CRC ERROR on fifo:%d!!!\n",
+				       fifo->skbuff->len, fifon);
+#ifdef CONFIG_HISAX_DEBUG
+				if (debug > 1) {
+					printk(KERN_INFO "HFC-S USB: ");
+					for (i = 0; i < 15; i++)
+						printk("%.2x ",
+						       fifo->skbuff->
+						       data[fifo->skbuff->
+							    len - 15 + i]);
+					printk("\n");
+				}
+#endif
+			}
+#ifdef CONFIG_HISAX_DEBUG
+			else {
+				printk(KERN_INFO
+				       "HFC-S USB: frame to small (%d bytes)!!!\n",
+				       fifo->skbuff->len);
+			}
+#endif
+			skb_trim(fifo->skbuff, 0);
 		}
 	}
 
-	// LED flashing only in HDLC mode
-	if(!transp_mode)
-	{
-		if(fifon==HFCUSB_B1_RX) handle_led(hfc,LED_B1_DATA);
-		if(fifon==HFCUSB_B2_RX) handle_led(hfc,LED_B2_DATA);
+	/* LED flashing only in HDLC mode */
+	if (!transp_mode) {
+		if (fifon == HFCUSB_B1_RX)
+			handle_led(hfc, LED_B1_DATA);
+		if (fifon == HFCUSB_B2_RX)
+			handle_led(hfc, LED_B2_DATA);
 	}
 }
 
 /***********************************************/
 /* receive completion routine for all rx fifos */
 /***********************************************/
-static void rx_complete(struct urb *urb, struct pt_regs *regs)
+static void
+rx_complete(struct urb *urb, struct pt_regs *regs)
 {
 	int len;
-	__u8 *buf;
-	usb_fifo *fifo = (usb_fifo *) urb->context;	/* pointer to our fifo */
+	int status;
+	__u8 *buf, maxlen, fifon;
+	usb_fifo *fifo = (usb_fifo *) urb->context;
 	hfcusb_data *hfc = fifo->hfc;
+	static __u8 eof[8];
+#ifdef CONFIG_HISAX_DEBUG
+	__u8 i;
+#endif
 
 	urb->dev = hfc->dev;	/* security init */
 
-	if((!fifo->active) || (urb->status)) {
-#ifdef VERBOSE_USB_DEBUG
-		printk(KERN_INFO "HFC-USB: RX-Fifo %i is going down (%i)\n", fifo->fifonum, urb->status);
+	fifon = fifo->fifonum;
+	if ((!fifo->active) || (urb->status)) {
+#ifdef CONFIG_HISAX_DEBUG
+		DBG(USB_DBG, "HFC-S USB: RX-Fifo %i is going down (%i)",
+		    fifon, urb->status);
 #endif
 		fifo->urb->interval = 0;	/* cancel automatic rescheduling */
-		if(fifo->skbuff) {
+		if (fifo->skbuff) {
 			dev_kfree_skb_any(fifo->skbuff);
 			fifo->skbuff = NULL;
 		}
 		return;
 	}
+	len = urb->actual_length;
+	buf = fifo->buffer;
+	maxlen = fifo->usb_packet_maxlen;
+
+#ifdef CONFIG_HISAX_DEBUG
+	if ((fifon == 5) && (debug > 1)) {
+		printk(KERN_INFO
+		       "HFC-S USB: INT-D-RX lst_urblen:%2d act_urblen:%2d max-urblen:%2d EOF:0x%0x DATA: ",
+		       fifo->last_urblen, len, maxlen, eof[5]);
+		for (i = 0; i < len; i++)
+			printk("%.2x ", buf[i]);
+		printk("\n");
+	}
+#endif
 
-	len=urb->actual_length;
-	buf=fifo->buffer;
-
-	if(fifo->last_urblen!=fifo->usb_packet_maxlen) {
-		// the threshold mask is in the 2nd status byte
-		hfc->threshold_mask=buf[1];
-		// the S0 state is in the upper half of the 1st status byte
-		state_handler(hfc,buf[0] >> 4);
-		// if we have more than the 2 status bytes -> collect data
-		if(len>2) collect_rx_frame(fifo,buf+2,urb->actual_length-2,buf[0]&1);
-	} else
-		collect_rx_frame(fifo,buf,urb->actual_length,0);
-
-	fifo->last_urblen=urb->actual_length;
-
-
-}	/* rx_complete */
-
-
+	if (fifo->last_urblen != fifo->usb_packet_maxlen) {
+		/* the threshold mask is in the 2nd status byte */
+		hfc->threshold_mask = buf[1];
+		/* the S0 state is in the upper half of the 1st status byte */
+		state_handler(hfc, buf[0] >> 4);
+		eof[fifon] = buf[0] & 1;
+		/* if we have more than the 2 status bytes -> collect data */
+		if (len > 2)
+			collect_rx_frame(fifo, buf + 2,
+					 urb->actual_length - 2,
+					 (len < maxlen) ? eof[fifon] : 0);
+	} else {
+		collect_rx_frame(fifo, buf, urb->actual_length,
+				 (len < maxlen) ? eof[fifon] : 0);
+	}
+	fifo->last_urblen = urb->actual_length;
+	status = usb_submit_urb(urb, GFP_ATOMIC);
+	if (status) {
+		printk(KERN_INFO
+		       "HFC-S USB: error resubmitting URN at rx_complete...\n");
+	}
+}				/* rx_complete */
 
 /***************************************************/
 /* start the interrupt transfer for the given fifo */
 /***************************************************/
-static void start_int_fifo(usb_fifo * fifo)
+static void
+start_int_fifo(usb_fifo * fifo)
 {
 	int errcode;
 
-#ifdef VERBOSE_USB_DEBUG
-	printk(KERN_INFO "HFC-USB: starting intr IN fifo:%d\n", fifo->fifonum);
-#endif
+	printk(KERN_INFO "HFC-S USB: starting intr IN fifo:%d\n",
+	       fifo->fifonum);
+
 	if (!fifo->urb) {
 		fifo->urb = usb_alloc_urb(0, GFP_KERNEL);
 		if (!fifo->urb)
 			return;
 	}
-	usb_fill_int_urb(fifo->urb, fifo->hfc->dev, fifo->pipe, fifo->buffer,
-				 fifo->usb_packet_maxlen, rx_complete, fifo, fifo->intervall);
-	fifo->active = 1;		/* must be marked active */
+	usb_fill_int_urb(fifo->urb, fifo->hfc->dev, fifo->pipe,
+			 fifo->buffer, fifo->usb_packet_maxlen,
+			 rx_complete, fifo, fifo->intervall);
+	fifo->active = 1;	/* must be marked active */
 	errcode = usb_submit_urb(fifo->urb, GFP_KERNEL);
-
-	if(errcode)
-	{
-		printk(KERN_INFO "HFC-USB: submit URB error(start_int_info): status:%i\n",   errcode);
+	if (errcode) {
+		printk(KERN_INFO
+		       "HFC-S USB: submit URB error(start_int_info): status:%i\n",
+		       errcode);
 		fifo->active = 0;
 		fifo->skbuff = NULL;
 	}
-} /* start_int_fifo */
+}				/* start_int_fifo */
 
 /*****************************/
 /* set the B-channel mode    */
 /*****************************/
-static void set_hfcmode(hfcusb_data *hfc,int channel,int mode)
+static void
+set_hfcmode(hfcusb_data * hfc, int channel, int mode)
 {
-	__u8 val,idx_table[2]={0,2};
-
-#ifdef VERBOSE_ISDN_DEBUG
-  printk (KERN_INFO "HFC-USB: setting channel %d to mode %d\n",channel,mode);
-#endif
-
-	hfc->b_mode[channel]=mode;
-
-	// setup CON_HDLC
-	val=0;
-	if(mode!=L1_MODE_NULL) val=8;    // enable fifo?
-	if(mode==L1_MODE_TRANS) val|=2;  // set transparent bit
-
-	queue_control_request(hfc,HFCUSB_FIFO,idx_table[channel],1); // set FIFO to transmit register
-	queue_control_request(hfc,HFCUSB_CON_HDLC,val,1);
-	queue_control_request(hfc,HFCUSB_INC_RES_F,2,1); // reset fifo
-
-	queue_control_request(hfc,HFCUSB_FIFO,idx_table[channel]+1,1); // set FIFO to receive register
-	queue_control_request(hfc,HFCUSB_CON_HDLC,val,1);
-	queue_control_request(hfc,HFCUSB_INC_RES_F,2,1);  // reset fifo
+	__u8 val, idx_table[2] = { 0, 2 };
 
-	val=0x40;
-	if(hfc->b_mode[0]) val|=1;
-	if(hfc->b_mode[1]) val|=2;
-	queue_control_request(hfc,HFCUSB_SCTRL,val,1);
-
-	val=0;
-	if(hfc->b_mode[0]) val|=1;
-	if(hfc->b_mode[1]) val|=2;
-	queue_control_request(hfc,HFCUSB_SCTRL_R,val,1);
-
-	if(mode==L1_MODE_NULL)
-	{
-		if(channel) handle_led(hfc,LED_B2_OFF);
-		else handle_led(hfc,LED_B1_OFF);
+	if (hfc->disc_flag) {
+		return;
 	}
-	else
-	{
-		if(channel) handle_led(hfc,LED_B2_ON);
-		else handle_led(hfc,LED_B1_ON);
+#ifdef CONFIG_HISAX_DEBUG
+	DBG(ISDN_DBG, "HFC-S USB: setting channel %d to mode %d", channel,
+	    mode);
+#endif
+	hfc->b_mode[channel] = mode;
+
+	/* setup CON_HDLC */
+	val = 0;
+	if (mode != L1_MODE_NULL)
+		val = 8;	/* enable fifo? */
+	if (mode == L1_MODE_TRANS)
+		val |= 2;	/* set transparent bit */
+
+	/* set FIFO to transmit register */
+	queue_control_request(hfc, HFCUSB_FIFO, idx_table[channel], 1);
+	queue_control_request(hfc, HFCUSB_CON_HDLC, val, 1);
+	/* reset fifo */
+	queue_control_request(hfc, HFCUSB_INC_RES_F, 2, 1);
+	/* set FIFO to receive register */
+	queue_control_request(hfc, HFCUSB_FIFO, idx_table[channel] + 1, 1);
+	queue_control_request(hfc, HFCUSB_CON_HDLC, val, 1);
+	/* reset fifo */
+	queue_control_request(hfc, HFCUSB_INC_RES_F, 2, 1);
+
+	val = 0x40;
+	if (hfc->b_mode[0])
+		val |= 1;
+	if (hfc->b_mode[1])
+		val |= 2;
+	queue_control_request(hfc, HFCUSB_SCTRL, val, 1);
+
+	val = 0;
+	if (hfc->b_mode[0])
+		val |= 1;
+	if (hfc->b_mode[1])
+		val |= 2;
+	queue_control_request(hfc, HFCUSB_SCTRL_R, val, 1);
+
+	if (mode == L1_MODE_NULL) {
+		if (channel)
+			handle_led(hfc, LED_B2_OFF);
+		else
+			handle_led(hfc, LED_B1_OFF);
+	} else {
+		if (channel)
+			handle_led(hfc, LED_B2_ON);
+		else
+			handle_led(hfc, LED_B1_ON);
 	}
 }
 
-/*
-   --------------------------------------------------------------------------------------
-   from here : hisax_if callback routines :
-     - void hfc_usb_d_l2l1(struct hisax_if *hisax_d_if, int pr, void *arg) {
-
-   l1 to l2 routines :
-     - static void hfc_usb_l1l2(hfcusb_data * hfc)
-
-*/
-
-void hfc_usb_l2l1(struct hisax_if *my_hisax_if, int pr, void *arg)
+void
+hfc_usb_l2l1(struct hisax_if *my_hisax_if, int pr, void *arg)
 {
-    usb_fifo *fifo = my_hisax_if->priv;
+	usb_fifo *fifo = my_hisax_if->priv;
 	hfcusb_data *hfc = fifo->hfc;
 
-    switch (pr) {
+	switch (pr) {
 		case PH_ACTIVATE | REQUEST:
-				if(fifo->fifonum==HFCUSB_D_TX)
-				{
-#ifdef VERBOSE_ISDN_DEBUG
-					printk (KERN_INFO "HFC_USB: hfc_usb_d_l2l1 D-chan: PH_ACTIVATE | REQUEST\n");
-#endif
-					queue_control_request(hfc, HFCUSB_STATES,0x60,1);	/* make activation */
-					hfc->t3_timer.expires = jiffies + (HFC_TIMER_T3 * HZ) / 1000;
-					if(!timer_pending(&hfc->t3_timer)) add_timer(&hfc->t3_timer);
-				}
-				else
-				{
-#ifdef VERBOSE_ISDN_DEBUG
-					printk (KERN_INFO "HFC_USB: hfc_usb_d_l2l1 Bx-chan: PH_ACTIVATE | REQUEST\n");
-#endif
-					set_hfcmode(hfc,(fifo->fifonum==HFCUSB_B1_TX) ? 0 : 1 ,(int)arg);
-					fifo->hif->l1l2(fifo->hif,PH_ACTIVATE | INDICATION, NULL);
-				}
-                break;
-        case PH_DEACTIVATE | REQUEST:
-				if(fifo->fifonum==HFCUSB_D_TX)
-				{
-#ifdef VERBOSE_ISDN_DEBUG
-					printk (KERN_INFO "HFC_USB: hfc_usb_d_l2l1 D-chan: PH_DEACTIVATE | REQUEST\n");
-#endif
-					printk (KERN_INFO "HFC-USB: ISDN TE device should not deativate...\n");
-				}
-				else
-				{
-#ifdef VERBOSE_ISDN_DEBUG
-					printk (KERN_INFO "HFC_USB: hfc_usb_d_l2l1 Bx-chan: PH_DEACTIVATE | REQUEST\n");
-#endif
-					set_hfcmode(hfc,(fifo->fifonum==HFCUSB_B1_TX) ? 0 : 1 ,(int)L1_MODE_NULL);
-					fifo->hif->l1l2(fifo->hif,PH_DEACTIVATE | INDICATION, NULL);
+			if (fifo->fifonum == HFCUSB_D_TX) {
+#ifdef CONFIG_HISAX_DEBUG
+				DBG(ISDN_DBG,
+				    "HFC_USB: hfc_usb_d_l2l1 D-chan: PH_ACTIVATE | REQUEST");
+#endif
+				if (hfc->l1_state != 3
+				    && hfc->l1_state != 7) {
+					hfc->d_if.ifc.l1l2(&hfc->d_if.ifc,
+							   PH_DEACTIVATE |
+							   INDICATION,
+							   NULL);
+#ifdef CONFIG_HISAX_DEBUG
+					DBG(ISDN_DBG,
+					    "HFC-S USB: PH_DEACTIVATE | INDICATION sent (not state 3 or 7)");
+#endif
+				} else {
+					if (hfc->l1_state == 7) {	/* l1 already active */
+						hfc->d_if.ifc.l1l2(&hfc->
+								   d_if.
+								   ifc,
+								   PH_ACTIVATE
+								   |
+								   INDICATION,
+								   NULL);
+#ifdef CONFIG_HISAX_DEBUG
+						DBG(ISDN_DBG,
+						    "HFC-S USB: PH_ACTIVATE | INDICATION sent again ;)");
+#endif
+					} else {
+						/* force sending sending INFO1 */
+						queue_control_request(hfc,
+								      HFCUSB_STATES,
+								      0x14,
+								      1);
+						mdelay(1);
+						/* start l1 activation */
+						queue_control_request(hfc,
+								      HFCUSB_STATES,
+								      0x04,
+								      1);
+						if (!timer_pending
+						    (&hfc->t3_timer)) {
+							hfc->t3_timer.
+							    expires =
+							    jiffies +
+							    (HFC_TIMER_T3 *
+							     HZ) / 1000;
+							add_timer(&hfc->
+								  t3_timer);
+						}
+					}
 				}
-                break;
+			} else {
+#ifdef CONFIG_HISAX_DEBUG
+				DBG(ISDN_DBG,
+				    "HFC_USB: hfc_usb_d_l2l1 Bx-chan: PH_ACTIVATE | REQUEST");
+#endif
+				set_hfcmode(hfc,
+					    (fifo->fifonum ==
+					     HFCUSB_B1_TX) ? 0 : 1,
+					    (int) arg);
+				fifo->hif->l1l2(fifo->hif,
+						PH_ACTIVATE | INDICATION,
+						NULL);
+			}
+			break;
+		case PH_DEACTIVATE | REQUEST:
+			if (fifo->fifonum == HFCUSB_D_TX) {
+#ifdef CONFIG_HISAX_DEBUG
+				DBG(ISDN_DBG,
+				    "HFC_USB: hfc_usb_d_l2l1 D-chan: PH_DEACTIVATE | REQUEST");
+#endif
+				printk(KERN_INFO
+				       "HFC-S USB: ISDN TE device should not deativate...\n");
+			} else {
+#ifdef CONFIG_HISAX_DEBUG
+				DBG(ISDN_DBG,
+				    "HFC_USB: hfc_usb_d_l2l1 Bx-chan: PH_DEACTIVATE | REQUEST");
+#endif
+				set_hfcmode(hfc,
+					    (fifo->fifonum ==
+					     HFCUSB_B1_TX) ? 0 : 1,
+					    (int) L1_MODE_NULL);
+				fifo->hif->l1l2(fifo->hif,
+						PH_DEACTIVATE | INDICATION,
+						NULL);
+			}
+			break;
 		case PH_DATA | REQUEST:
-				if(fifo->skbuff && fifo->delete_flg)
-				{
-					dev_kfree_skb_any(fifo->skbuff);
-					//printk(KERN_INFO "skbuff=NULL on fifo:%d\n",fifo->fifonum);
-					fifo->skbuff = NULL;
-					fifo->delete_flg=FALSE;
-				}
-
-				fifo->skbuff=arg; // we have a new buffer
-
-				//if(fifo->fifonum==HFCUSB_D_TX) printk (KERN_INFO "HFC_USB: hfc_usb_d_l2l1 D-chan: PH_DATA | REQUEST\n");
-				//else printk (KERN_INFO "HFC_USB: hfc_usb_d_l2l1 Bx-chan: PH_DATA | REQUEST\n");
-                break;
-        default:
-                printk (KERN_INFO "HFC_USB: hfc_usb_d_l2l1: unkown state : %#x\n", pr);
-                break;
-    }
+			if (fifo->skbuff && fifo->delete_flg) {
+				dev_kfree_skb_any(fifo->skbuff);
+				fifo->skbuff = NULL;
+				fifo->delete_flg = FALSE;
+			}
+			fifo->skbuff = arg;	/* we have a new buffer */
+			break;
+		default:
+			printk(KERN_INFO
+			       "HFC_USB: hfc_usb_d_l2l1: unkown state : %#x\n",
+			       pr);
+			break;
+	}
 }
 
-// valid configurations
-#define CNF_4INT3ISO  1      // 4 INT IN, 3 ISO OUT
-#define CNF_3INT3ISO  2      // 3 INT IN, 3 ISO OUT
-#define CNF_4ISO3ISO  3      // 4 ISO IN, 3 ISO OUT
-#define CNF_3ISO3ISO  4 	 // 3 ISO IN, 3 ISO OUT
-
-
-/*
-   --------------------------------------------------------------------------------------
-   From here on USB initialization and deactivation related routines are implemented :
-
-   - hfc_usb_init :
-      is the main Entry Point for the USB Subsystem when the device get plugged
-      in. This function calls usb_register with usb_driver as parameter.
-      Here, further entry points for probing (hfc_usb_probe) and disconnecting
-      the device (hfc_usb_disconnect) are published, as the id_table
-
-   - hfc_usb_probe
-      this function is called by the usb subsystem, and steps through the alternate
-      settings of the currently plugged in device to detect all Endpoints needed to
-      run an ISDN TA.
-      Needed EndPoints are
-      3 (+1) IntIn EndPoints   (D-in,  E-in, B1-in, B2-in, (E-in)) or
-      3 (+1) Isochron In Endpoints (D-out, B1-out, B2-out) and 3 IsoOut Endpoints
-      The currently used transfer mode of on the Out-Endpoints will be stored in
-      hfc->usb_transfer_mode and is either USB_INT or USB_ISO
-      When a valid alternate setting could be found, the usb_init (see blow)
-      function is called
-
-   - usb_init
-      Here, the HFC_USB Chip itself gets initialized and the USB framework to send/receive
-      Data to/from the several EndPoints are initialized:
-       The E- and D-Channel Int-In chain gets started
-       The IsoChain for the Iso-Out traffic get started
-
-   - hfc_usb_disconnect
-      this function is called by the usb subsystem and has to free all resources
-      and stop all usb traffic to allow a proper hotplugging disconnect.
-
-*/
-
 /***************************************************************************/
 /* usb_init is called once when a new matching device is detected to setup */
-/* main parameters. It registers the driver at the main hisax module.       */
+/* main parameters. It registers the driver at the main hisax module.      */
 /* on success 0 is returned.                                               */
 /***************************************************************************/
-static int usb_init(hfcusb_data * hfc)
+static int
+usb_init(hfcusb_data * hfc)
 {
 	usb_fifo *fifo;
 	int i, err;
 	u_char b;
 	struct hisax_b_if *p_b_if[2];
-	
+
 	/* check the chip id */
-	printk(KERN_INFO "HFCUSB_CHIP_ID begin\n");
 	if (read_usb(hfc, HFCUSB_CHIP_ID, &b) != 1) {
 		printk(KERN_INFO "HFC-USB: cannot read chip id\n");
-		return(1); 
+		return (1);
 	}
-	printk(KERN_INFO "HFCUSB_CHIP_ID %x\n", b);
 	if (b != HFCUSB_CHIPID) {
-		printk(KERN_INFO "HFC-USB: Invalid chip id 0x%02x\n", b);
-		return(1);
+		printk(KERN_INFO "HFC-S USB: Invalid chip id 0x%02x\n", b);
+		return (1);
 	}
 
 	/* first set the needed config, interface and alternate */
-	printk(KERN_INFO "usb_init 1\n");
-//	usb_set_configuration(hfc->dev, 1);
-	printk(KERN_INFO "usb_init 2\n");
 	err = usb_set_interface(hfc->dev, hfc->if_used, hfc->alt_used);
-	printk(KERN_INFO "usb_init usb_set_interface return %d\n", err);
-	/* now we initialize the chip */
-	write_usb(hfc, HFCUSB_CIRM, 8);	    // do reset
-	write_usb(hfc, HFCUSB_CIRM, 0x10);	// aux = output, reset off
 
-	// set USB_SIZE to match the the wMaxPacketSize for INT or BULK transfers
-	write_usb(hfc, HFCUSB_USB_SIZE,(hfc->packet_size/8) | ((hfc->packet_size/8) << 4));
+	/* do Chip reset */
+	write_usb(hfc, HFCUSB_CIRM, 8);
+	/* aux = output, reset off */
+	write_usb(hfc, HFCUSB_CIRM, 0x10);
+
+	/* set USB_SIZE to match the the wMaxPacketSize for INT or BULK transfers */
+	write_usb(hfc, HFCUSB_USB_SIZE,
+		  (hfc->packet_size / 8) | ((hfc->packet_size / 8) << 4));
 
-	// set USB_SIZE_I to match the the wMaxPacketSize for ISO transfers
+	/* set USB_SIZE_I to match the the wMaxPacketSize for ISO transfers */
 	write_usb(hfc, HFCUSB_USB_SIZE_I, hfc->iso_packet_size);
 
 	/* enable PCM/GCI master mode */
@@ -1184,412 +1292,447 @@
 	write_usb(hfc, HFCUSB_MST_MODE0, 1);	/* enable master mode */
 
 	/* init the fifos */
-	write_usb(hfc, HFCUSB_F_THRES, (HFCUSB_TX_THRESHOLD/8) |((HFCUSB_RX_THRESHOLD/8) << 4));
+	write_usb(hfc, HFCUSB_F_THRES,
+		  (HFCUSB_TX_THRESHOLD /
+		   8) | ((HFCUSB_RX_THRESHOLD / 8) << 4));
 
 	fifo = hfc->fifos;
-	for(i = 0; i < HFCUSB_NUM_FIFOS; i++)
-	{
+	for (i = 0; i < HFCUSB_NUM_FIFOS; i++) {
 		write_usb(hfc, HFCUSB_FIFO, i);	/* select the desired fifo */
 		fifo[i].skbuff = NULL;	/* init buffer pointer */
-		fifo[i].max_size = (i <= HFCUSB_B2_RX) ? MAX_BCH_SIZE : MAX_DFRAME_LEN;
-		fifo[i].last_urblen=0;
-		write_usb(hfc, HFCUSB_HDLC_PAR, ((i <= HFCUSB_B2_RX) ? 0 : 2));	    // set 2 bit for D- & E-channel
-		write_usb(hfc, HFCUSB_CON_HDLC, ((i==HFCUSB_D_TX) ? 0x09 : 0x08));	// rx hdlc, enable IFF for D-channel
+		fifo[i].max_size =
+		    (i <= HFCUSB_B2_RX) ? MAX_BCH_SIZE : MAX_DFRAME_LEN;
+		fifo[i].last_urblen = 0;
+		/* set 2 bit for D- & E-channel */
+		write_usb(hfc, HFCUSB_HDLC_PAR,
+			  ((i <= HFCUSB_B2_RX) ? 0 : 2));
+		/* rx hdlc, enable IFF for D-channel */
+		write_usb(hfc, HFCUSB_CON_HDLC,
+			  ((i == HFCUSB_D_TX) ? 0x09 : 0x08));
 		write_usb(hfc, HFCUSB_INC_RES_F, 2);	/* reset the fifo */
 	}
 
-	write_usb(hfc, HFCUSB_CLKDEL, 0x0f);	 /* clock delay value */
-	write_usb(hfc, HFCUSB_STATES, 3 | 0x10); /* set deactivated mode */
-	write_usb(hfc, HFCUSB_STATES, 3);	     /* enable state machine */
-
-	write_usb(hfc, HFCUSB_SCTRL_R, 0);	     /* disable both B receivers */
-	write_usb(hfc, HFCUSB_SCTRL, 0x40);	     /* disable B transmitters + capacitive mode */
-
-	// set both B-channel to not connected
-	hfc->b_mode[0]=L1_MODE_NULL;
-	hfc->b_mode[1]=L1_MODE_NULL;
-
-	hfc->l1_activated=FALSE;
-	hfc->led_state=0;
-	hfc->led_new_data=0;
+	write_usb(hfc, HFCUSB_CLKDEL, 0x0f);	/* clock delay value */
+	write_usb(hfc, HFCUSB_STATES, 3 | 0x10);	/* set deactivated mode */
+	write_usb(hfc, HFCUSB_STATES, 3);	/* enable state machine */
+
+	write_usb(hfc, HFCUSB_SCTRL_R, 0);	/* disable both B receivers */
+	write_usb(hfc, HFCUSB_SCTRL, 0x40);	/* disable B transmitters + capacitive mode */
+
+	/* set both B-channel to not connected */
+	hfc->b_mode[0] = L1_MODE_NULL;
+	hfc->b_mode[1] = L1_MODE_NULL;
+
+	hfc->l1_activated = FALSE;
+	hfc->disc_flag = FALSE;
+	hfc->led_state = 0;
+	hfc->led_new_data = 0;
+	hfc->old_led_state = 0;
 
 	/* init the t3 timer */
 	init_timer(&hfc->t3_timer);
 	hfc->t3_timer.data = (long) hfc;
 	hfc->t3_timer.function = (void *) l1_timer_expire_t3;
+
 	/* init the t4 timer */
 	init_timer(&hfc->t4_timer);
 	hfc->t4_timer.data = (long) hfc;
 	hfc->t4_timer.function = (void *) l1_timer_expire_t4;
+
 	/* init the led timer */
 	init_timer(&hfc->led_timer);
 	hfc->led_timer.data = (long) hfc;
 	hfc->led_timer.function = (void *) led_timer;
-	// trigger 4 hz led timer
-	hfc->led_timer.expires = jiffies + (LED_TIME * HZ) / 1000;
-	if(!timer_pending(&hfc->led_timer)) add_timer(&hfc->led_timer);
 
-	// init the background machinery for control requests
+	/* trigger 4 hz led timer */
+	if (!timer_pending(&hfc->led_timer)) {
+		hfc->led_timer.expires = jiffies + (LED_TIME * HZ) / 1000;
+		add_timer(&hfc->led_timer);
+	}
+
+	/* init the background machinery for control requests */
 	hfc->ctrl_read.bRequestType = 0xc0;
 	hfc->ctrl_read.bRequest = 1;
 	hfc->ctrl_read.wLength = 1;
 	hfc->ctrl_write.bRequestType = 0x40;
 	hfc->ctrl_write.bRequest = 0;
 	hfc->ctrl_write.wLength = 0;
-	usb_fill_control_urb(hfc->ctrl_urb, hfc->dev, hfc->ctrl_out_pipe,(u_char *) & hfc->ctrl_write, NULL, 0, ctrl_complete, hfc);
-					
+	usb_fill_control_urb(hfc->ctrl_urb,
+			     hfc->dev,
+			     hfc->ctrl_out_pipe,
+			     (u_char *) & hfc->ctrl_write,
+			     NULL, 0, ctrl_complete, hfc);
 	/* Init All Fifos */
-	for(i = 0; i < HFCUSB_NUM_FIFOS; i++)
-	{
+	for (i = 0; i < HFCUSB_NUM_FIFOS; i++) {
 		hfc->fifos[i].iso[0].purb = NULL;
 		hfc->fifos[i].iso[1].purb = NULL;
 		hfc->fifos[i].active = 0;
 	}
-
-	// register like Germaschewski :
+	/* register Modul to upper Hisax Layers */
 	hfc->d_if.owner = THIS_MODULE;
 	hfc->d_if.ifc.priv = &hfc->fifos[HFCUSB_D_TX];
 	hfc->d_if.ifc.l2l1 = hfc_usb_l2l1;
-
-	for (i=0; i<2; i++)
-	{
-		hfc->b_if[i].ifc.priv = &hfc->fifos[HFCUSB_B1_TX+i*2];
+	for (i = 0; i < 2; i++) {
+		hfc->b_if[i].ifc.priv = &hfc->fifos[HFCUSB_B1_TX + i * 2];
 		hfc->b_if[i].ifc.l2l1 = hfc_usb_l2l1;
 		p_b_if[i] = &hfc->b_if[i];
 	}
-	
-	hfc->protocol = 2;  /* default EURO ISDN, should be a module_param */
+	/* default Prot: EURO ISDN, should be a module_param */
+	hfc->protocol = 2;
 	hisax_register(&hfc->d_if, p_b_if, "hfc_usb", hfc->protocol);
-	
-	for (i=0; i<4; i++)
-		hfc->fifos[i].hif=&p_b_if[i/2]->ifc;
-	for (i=4; i<8; i++)
-		hfc->fifos[i].hif=&hfc->d_if.ifc;
-
-	// 3 (+1) INT IN + 3 ISO OUT
-	if(hfc->cfg_used == CNF_3INT3ISO || hfc->cfg_used == CNF_4INT3ISO)
-	{
-		start_int_fifo(hfc->fifos + HFCUSB_D_RX);	// Int IN D-fifo
-		if(hfc->fifos[HFCUSB_PCM_RX].pipe) start_int_fifo(hfc->fifos + HFCUSB_PCM_RX);	// E-fifo
-		start_int_fifo(hfc->fifos + HFCUSB_B1_RX);	// Int IN B1-fifo
-		start_int_fifo(hfc->fifos + HFCUSB_B2_RX);	// Int IN B2-fifo
-	}
-
-	// 3 (+1) ISO IN + 3 ISO OUT
-	if(hfc->cfg_used==CNF_3ISO3ISO || hfc->cfg_used==CNF_4ISO3ISO)
-	{
-		start_isoc_chain(hfc->fifos + HFCUSB_D_RX, ISOC_PACKETS_D, rx_iso_complete,16);
-		if(hfc->fifos[HFCUSB_PCM_RX].pipe) start_isoc_chain(hfc->fifos + HFCUSB_PCM_RX, ISOC_PACKETS_D, rx_iso_complete,16);
-		start_isoc_chain(hfc->fifos + HFCUSB_B1_RX, ISOC_PACKETS_B, rx_iso_complete,16);
-		start_isoc_chain(hfc->fifos + HFCUSB_B2_RX, ISOC_PACKETS_B, rx_iso_complete,16);
-	}
-
-	start_isoc_chain(hfc->fifos + HFCUSB_D_TX, ISOC_PACKETS_D, tx_iso_complete,1);
-	start_isoc_chain(hfc->fifos + HFCUSB_B1_TX, ISOC_PACKETS_B, tx_iso_complete,1);
-	start_isoc_chain(hfc->fifos + HFCUSB_B2_TX, ISOC_PACKETS_B, tx_iso_complete,1);
-
-	handle_led(hfc,LED_POWER_ON);
-
-	return(0);
-}	/* usb_init */
-
-
-/****************************************/
-/* data defining the devices to be used */
-/****************************************/
-// static __devinitdata const struct usb_device_id hfc_usb_idtab[3] = {
-static struct usb_device_id hfc_usb_idtab[] = {
-	{USB_DEVICE(0x7b0, 0x0007)},	/* Billion USB TA 2 */
-	{USB_DEVICE(0x742, 0x2008)},	/* Stollmann USB TA */
-	{USB_DEVICE(0x959, 0x2bd0)},	/* Colognechip USB eval TA */
-	{USB_DEVICE(0x8e3, 0x0301)},	/* OliTec ISDN USB */
-	{USB_DEVICE(0x675, 0x1688)},	/* DrayTec ISDN USB */
-	{USB_DEVICE(0x7fa, 0x0846)},    /* Bewan ISDN USB TA */
-	{}				/* end with an all-zeroes entry */
-};
 
-MODULE_AUTHOR("Peter Sprenger (sprenger@moving-byters.de)/Martin Bachem (info@colognechip.com)");
-MODULE_DESCRIPTION("HFC I4L USB driver");
-MODULE_DEVICE_TABLE(usb, hfc_usb_idtab);
-MODULE_LICENSE("GPL");
+#ifdef CONFIG_HISAX_DEBUG
+	hfc_debug = debug;
+#endif
 
-#define EP_NUL 1    // Endpoint at this position not allowed
-#define EP_NOP 2	// all type of endpoints allowed at this position
-#define EP_ISO 3	// Isochron endpoint mandatory at this position
-#define EP_BLK 4	// Bulk endpoint mandatory at this position
-#define EP_INT 5	// Interrupt endpoint mandatory at this position
-
-// this array represents all endpoints possible in the HCF-USB
-// the last 2 entries are the configuration number and the minimum interval for Interrupt endpoints
-int validconf[][18]=
-{
-	// INT in, ISO out config
-	{EP_NUL,EP_INT,EP_NUL,EP_INT,EP_NUL,EP_INT,EP_NOP,EP_INT,EP_ISO,EP_NUL,EP_ISO,EP_NUL,EP_ISO,EP_NUL,EP_NUL,EP_NUL,CNF_4INT3ISO,2},
-	{EP_NUL,EP_INT,EP_NUL,EP_INT,EP_NUL,EP_INT,EP_NUL,EP_NUL,EP_ISO,EP_NUL,EP_ISO,EP_NUL,EP_ISO,EP_NUL,EP_NUL,EP_NUL,CNF_3INT3ISO,2},
-	// ISO in, ISO out config
-	{EP_NUL,EP_NUL,EP_NUL,EP_NUL,EP_NUL,EP_NUL,EP_NUL,EP_NUL,EP_ISO,EP_ISO,EP_ISO,EP_ISO,EP_ISO,EP_ISO,EP_NOP,EP_ISO,CNF_4ISO3ISO,2},
-	{EP_NUL,EP_NUL,EP_NUL,EP_NUL,EP_NUL,EP_NUL,EP_NUL,EP_NUL,EP_ISO,EP_ISO,EP_ISO,EP_ISO,EP_ISO,EP_ISO,EP_NUL,EP_NUL,CNF_3ISO3ISO,2},
-	{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}       // EOL element
-};
+	for (i = 0; i < 4; i++)
+		hfc->fifos[i].hif = &p_b_if[i / 2]->ifc;
+	for (i = 4; i < 8; i++)
+		hfc->fifos[i].hif = &hfc->d_if.ifc;
+
+	/* 3 (+1) INT IN + 3 ISO OUT */
+	if (hfc->cfg_used == CNF_3INT3ISO || hfc->cfg_used == CNF_4INT3ISO) {
+		start_int_fifo(hfc->fifos + HFCUSB_D_RX);
+		if (hfc->fifos[HFCUSB_PCM_RX].pipe)
+			start_int_fifo(hfc->fifos + HFCUSB_PCM_RX);
+		start_int_fifo(hfc->fifos + HFCUSB_B1_RX);
+		start_int_fifo(hfc->fifos + HFCUSB_B2_RX);
+	}
+	/* 3 (+1) ISO IN + 3 ISO OUT */
+	if (hfc->cfg_used == CNF_3ISO3ISO || hfc->cfg_used == CNF_4ISO3ISO) {
+		start_isoc_chain(hfc->fifos + HFCUSB_D_RX, ISOC_PACKETS_D,
+				 rx_iso_complete, 16);
+		if (hfc->fifos[HFCUSB_PCM_RX].pipe)
+			start_isoc_chain(hfc->fifos + HFCUSB_PCM_RX,
+					 ISOC_PACKETS_D, rx_iso_complete,
+					 16);
+		start_isoc_chain(hfc->fifos + HFCUSB_B1_RX, ISOC_PACKETS_B,
+				 rx_iso_complete, 16);
+		start_isoc_chain(hfc->fifos + HFCUSB_B2_RX, ISOC_PACKETS_B,
+				 rx_iso_complete, 16);
+	}
+
+	start_isoc_chain(hfc->fifos + HFCUSB_D_TX, ISOC_PACKETS_D,
+			 tx_iso_complete, 1);
+	start_isoc_chain(hfc->fifos + HFCUSB_B1_TX, ISOC_PACKETS_B,
+			 tx_iso_complete, 1);
+	start_isoc_chain(hfc->fifos + HFCUSB_B2_TX, ISOC_PACKETS_B,
+			 tx_iso_complete, 1);
 
-// string description of chosen config
-char *conf_str[]=
-{
-	"4 Interrupt IN + 3 Isochron OUT",
-	"3 Interrupt IN + 3 Isochron OUT",
-	"4 Isochron IN + 3 Isochron OUT",
-	"3 Isochron IN + 3 Isochron OUT"
-};
+	handle_led(hfc, LED_POWER_ON);
 
+	return (0);
+}				/* usb_init */
 
 /*************************************************/
 /* function called to probe a new plugged device */
 /*************************************************/
-static int hfc_usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
+static int
+hfc_usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
 {
-	struct usb_device *dev= interface_to_usbdev(intf);
+	struct usb_device *dev = interface_to_usbdev(intf);
 	hfcusb_data *context;
 	struct usb_host_interface *iface = intf->cur_altsetting;
 	struct usb_host_interface *iface_used = NULL;
 	struct usb_host_endpoint *ep;
 	int ifnum = iface->desc.bInterfaceNumber;
-	int i, idx, alt_idx, probe_alt_setting, vend_idx, cfg_used, *vcf, attr, cfg_found, cidx, ep_addr;
-	int cmptbl[16],small_match,iso_packet_size,packet_size,alt_used=0;
-
-//        usb_show_device(dev);
-//	usb_show_device_descriptor(&dev->descriptor);
-//	usb_show_interface_descriptor(&iface->desc);
-	vend_idx=0xffff;
-	for(i=0;vdata[i].vendor;i++) {
-		if (le16_to_cpu(dev->descriptor.idVendor) == vdata[i].vendor && 
-		    le16_to_cpu(dev->descriptor.idProduct) == vdata[i].prod_id)
+	int i, idx, alt_idx, probe_alt_setting, vend_idx, cfg_used, *vcf,
+	    attr, cfg_found, cidx, ep_addr;
+	int cmptbl[16], small_match, iso_packet_size, packet_size,
+	    alt_used = 0;
+
+	vend_idx = 0xffff;
+	for (i = 0; vdata[i].vendor; i++) {
+		if (dev->descriptor.idVendor == vdata[i].vendor
+		    && dev->descriptor.idProduct == vdata[i].prod_id)
 			vend_idx = i;
 	}
-	
-
-#ifdef VERBOSE_USB_DEBUG	
-	printk(KERN_INFO "HFC-USB: probing interface(%d) actalt(%d) minor(%d)\n",
-		ifnum, iface->desc.bAlternateSetting, intf->minor);
-#endif
+#ifdef CONFIG_HISAX_DEBUG
+	DBG(USB_DBG,
+	    "HFC-USB: probing interface(%d) actalt(%d) minor(%d)\n", ifnum,
+	    iface->desc.bAlternateSetting, intf->minor);
+#endif
+	printk(KERN_INFO
+	       "HFC-S USB: probing interface(%d) actalt(%d) minor(%d)\n",
+	       ifnum, iface->desc.bAlternateSetting, intf->minor);
 
 	if (vend_idx != 0xffff) {
-#ifdef VERBOSE_USB_DEBUG
-		printk(KERN_INFO "HFC-USB: found vendor idx:%d  name:%s\n",vend_idx,vdata[vend_idx].vend_name);
+#ifdef CONFIG_HISAX_DEBUG
+		DBG(USB_DBG, "HFC-S USB: found vendor idx:%d  name:%s",
+		    vend_idx, vdata[vend_idx].vend_name);
 #endif
-		/* if vendor and product ID is OK, start probing a matching alternate setting ... */
+		/* if vendor and product ID is OK, start probing alternate settings */
 		alt_idx = 0;
-		small_match=0xffff;
-		// default settings
-		iso_packet_size=16;
-		packet_size=64;
+		small_match = 0xffff;
+
+		/* default settings */
+		iso_packet_size = 16;
+		packet_size = 64;
 
 		while (alt_idx < intf->num_altsetting) {
 			iface = intf->altsetting + alt_idx;
 			probe_alt_setting = iface->desc.bAlternateSetting;
-			cfg_used=0;
+			cfg_used = 0;
 
-#ifdef VERBOSE_USB_DEBUG
-			printk(KERN_INFO "HFC-USB: test alt_setting %d\n", probe_alt_setting);
-#endif
-			// check for config EOL element
+			/* check for config EOL element */
 			while (validconf[cfg_used][0]) {
-				cfg_found=TRUE;
-				vcf=validconf[cfg_used];
-				ep = iface->endpoint;	/* first endpoint descriptor */
-
-#ifdef VERBOSE_USB_DEBUG
-				printk(KERN_INFO "HFC-USB: (if=%d alt=%d cfg_used=%d)\n",
-					ifnum, probe_alt_setting, cfg_used);
-#endif
-				// copy table
-				memcpy(cmptbl,vcf,16*sizeof(int));
-
-				// check for all endpoints in this alternate setting
-				for (i=0; i < iface->desc.bNumEndpoints; i++) {
-					ep_addr = ep->desc.bEndpointAddress;
-					idx = ((ep_addr & 0x7f)-1)*2;	/* get endpoint base */
+				cfg_found = TRUE;
+				vcf = validconf[cfg_used];
+				/* first endpoint descriptor */
+				ep = iface->endpoint;
+#ifdef CONFIG_HISAX_DEBUG
+				DBG(USB_DBG,
+				    "HFC-S USB: (if=%d alt=%d cfg_used=%d)\n",
+				    ifnum, probe_alt_setting, cfg_used);
+#endif
+				memcpy(cmptbl, vcf, 16 * sizeof(int));
+
+				/* check for all endpoints in this alternate setting */
+				for (i = 0; i < iface->desc.bNumEndpoints;
+				     i++) {
+					ep_addr =
+					    ep->desc.bEndpointAddress;
+					/* get endpoint base */
+					idx = ((ep_addr & 0x7f) - 1) * 2;
 					if (ep_addr & 0x80)
 						idx++;
 					attr = ep->desc.bmAttributes;
-
 					if (cmptbl[idx] == EP_NUL) {
-						printk(KERN_INFO "HFC-USB: cfg_found=FALSE in idx:%d  attr:%d  cmptbl[%d]:%d\n",
-							idx, attr, idx, cmptbl[idx]);
 						cfg_found = FALSE;
 					}
-
-					if (attr == USB_ENDPOINT_XFER_INT && cmptbl[idx] == EP_INT)
+					if (attr == USB_ENDPOINT_XFER_INT
+					    && cmptbl[idx] == EP_INT)
 						cmptbl[idx] = EP_NUL;
-					if (attr == USB_ENDPOINT_XFER_BULK && cmptbl[idx] == EP_BLK)
+					if (attr == USB_ENDPOINT_XFER_BULK
+					    && cmptbl[idx] == EP_BLK)
 						cmptbl[idx] = EP_NUL;
-					if (attr == USB_ENDPOINT_XFER_ISOC && cmptbl[idx] == EP_ISO)
+					if (attr == USB_ENDPOINT_XFER_ISOC
+					    && cmptbl[idx] == EP_ISO)
 						cmptbl[idx] = EP_NUL;
 
-					// check if all INT endpoints match minimum interval
-					if (attr == USB_ENDPOINT_XFER_INT && ep->desc.bInterval < vcf[17]) {
-#ifdef VERBOSE_USB_DEBUG
+					/* check if all INT endpoints match minimum interval */
+					if (attr == USB_ENDPOINT_XFER_INT
+					    && ep->desc.bInterval <
+					    vcf[17]) {
+#ifdef CONFIG_HISAX_DEBUG
 						if (cfg_found)
-							printk(KERN_INFO "HFC-USB: Interrupt Endpoint interval < %d found - skipping config\n",
-								vcf[17]);
+							DBG(USB_DBG,
+							    "HFC-S USB: Interrupt Endpoint interval < %d found - skipping config",
+							    vcf[17]);
 #endif
 						cfg_found = FALSE;
 					}
-
 					ep++;
 				}
-
 				for (i = 0; i < 16; i++) {
-					// printk(KERN_INFO "HFC-USB: cmptbl[%d]:%d\n", i, cmptbl[i]);
-
-					// all entries must be EP_NOP or EP_NUL for a valid config
-					if (cmptbl[i] != EP_NOP && cmptbl[i] != EP_NUL)
+					/* all entries must be EP_NOP or EP_NUL for a valid config */
+					if (cmptbl[i] != EP_NOP
+					    && cmptbl[i] != EP_NUL)
 						cfg_found = FALSE;
 				}
-
-				// we check for smallest match, to provide configuration priority
-				// configurations with smaller index have higher priority
 				if (cfg_found) {
 					if (cfg_used < small_match) {
 						small_match = cfg_used;
-						alt_used = probe_alt_setting;
+						alt_used =
+						    probe_alt_setting;
 						iface_used = iface;
 					}
-#ifdef VERBOSE_USB_DEBUG
-					printk(KERN_INFO "HFC-USB: small_match=%x %x\n", small_match, alt_used);
+#ifdef CONFIG_HISAX_DEBUG
+					DBG(USB_DBG,
+					    "HFC-USB: small_match=%x %x\n",
+					    small_match, alt_used);
 #endif
 				}
-
 				cfg_used++;
 			}
-
 			alt_idx++;
 		}		/* (alt_idx < intf->num_altsetting) */
-#ifdef VERBOSE_USB_DEBUG
-		printk(KERN_INFO "HFC-USB: final small_match=%x alt_used=%x\n",small_match, alt_used);
-#endif
-		// yiipiee, we found a valid config
+
+		/* found a valid USB Ta Endpint config */
 		if (small_match != 0xffff) {
 			iface = iface_used;
+			if (!
+			    (context =
+			     kmalloc(sizeof(hfcusb_data), GFP_KERNEL)))
+				return (-ENOMEM);	/* got no mem */
+			memset(context, 0, sizeof(hfcusb_data));
 
-			if (!(context = kmalloc(sizeof(hfcusb_data), GFP_KERNEL)))
-				return(-ENOMEM);  /* got no mem */
-			memset(context, 0, sizeof(hfcusb_data));	/* clear the structure */
-
-			ep = iface->endpoint;	/* first endpoint descriptor */
+			ep = iface->endpoint;
 			vcf = validconf[small_match];
 
 			for (i = 0; i < iface->desc.bNumEndpoints; i++) {
 				ep_addr = ep->desc.bEndpointAddress;
-				idx = ((ep_addr & 0x7f)-1)*2;	/* get endpoint base */
+				/* get endpoint base */
+				idx = ((ep_addr & 0x7f) - 1) * 2;
 				if (ep_addr & 0x80)
 					idx++;
 				cidx = idx & 7;
 				attr = ep->desc.bmAttributes;
 
-				// only initialize used endpoints
-				if (vcf[idx] != EP_NOP && vcf[idx] != EP_NUL) {
+				/* init Endpoints */
+				if (vcf[idx] != EP_NOP
+				    && vcf[idx] != EP_NUL) {
 					switch (attr) {
 						case USB_ENDPOINT_XFER_INT:
-							context->fifos[cidx].pipe = usb_rcvintpipe(dev, ep->desc.bEndpointAddress);
-							context->fifos[cidx].usb_transfer_mode = USB_INT;
-							packet_size = le16_to_cpu(ep->desc.wMaxPacketSize); // remember max packet size
-#ifdef VERBOSE_USB_DEBUG
-							printk (KERN_INFO "HFC-USB: Interrupt-In Endpoint found %d ms(idx:%d cidx:%d)!\n",
-								ep->desc.bInterval, idx, cidx);
-#endif
+							context->
+							    fifos[cidx].
+							    pipe =
+							    usb_rcvintpipe
+							    (dev,
+							     ep->desc.
+							     bEndpointAddress);
+							context->
+							    fifos[cidx].
+							    usb_transfer_mode
+							    = USB_INT;
+							packet_size =
+							    ep->desc.
+							    wMaxPacketSize;
 							break;
 						case USB_ENDPOINT_XFER_BULK:
 							if (ep_addr & 0x80)
-								context->fifos[cidx].pipe = usb_rcvbulkpipe(dev, ep->desc.bEndpointAddress);
+								context->
+								    fifos
+								    [cidx].
+								    pipe =
+								    usb_rcvbulkpipe
+								    (dev,
+								     ep->
+								     desc.
+								     bEndpointAddress);
 							else
-								context->fifos[cidx].pipe = usb_sndbulkpipe(dev, ep->desc.bEndpointAddress);
-							context->fifos[cidx].usb_transfer_mode = USB_BULK;
-							packet_size = le16_to_cpu(ep->desc.wMaxPacketSize); // remember max packet size
-#ifdef VERBOSE_USB_DEBUG
-							printk (KERN_INFO "HFC-USB: Bulk Endpoint found (idx:%d cidx:%d)!\n",
-								idx, cidx);
-#endif
+								context->
+								    fifos
+								    [cidx].
+								    pipe =
+								    usb_sndbulkpipe
+								    (dev,
+								     ep->
+								     desc.
+								     bEndpointAddress);
+							context->
+							    fifos[cidx].
+							    usb_transfer_mode
+							    = USB_BULK;
+							packet_size =
+							    ep->desc.
+							    wMaxPacketSize;
 							break;
 						case USB_ENDPOINT_XFER_ISOC:
 							if (ep_addr & 0x80)
-								context->fifos[cidx].pipe = usb_rcvisocpipe(dev, ep->desc.bEndpointAddress);
+								context->
+								    fifos
+								    [cidx].
+								    pipe =
+								    usb_rcvisocpipe
+								    (dev,
+								     ep->
+								     desc.
+								     bEndpointAddress);
 							else
-								context->fifos[cidx].pipe = usb_sndisocpipe(dev, ep->desc.bEndpointAddress);
-							context->fifos[cidx].usb_transfer_mode = USB_ISOC;
-							iso_packet_size = le16_to_cpu(ep->desc.wMaxPacketSize); // remember max packet size
-#ifdef VERBOSE_USB_DEBUG
-							printk (KERN_INFO "HFC-USB: ISO Endpoint found (idx:%d cidx:%d)!\n",
-								idx, cidx);
-#endif
+								context->
+								    fifos
+								    [cidx].
+								    pipe =
+								    usb_sndisocpipe
+								    (dev,
+								     ep->
+								     desc.
+								     bEndpointAddress);
+							context->
+							    fifos[cidx].
+							    usb_transfer_mode
+							    = USB_ISOC;
+							iso_packet_size =
+							    ep->desc.
+							    wMaxPacketSize;
 							break;
 						default:
-							context->fifos[cidx].pipe = 0;	/* reset data */
+							context->
+							    fifos[cidx].
+							    pipe = 0;
 					}	/* switch attribute */
 
 					if (context->fifos[cidx].pipe) {
-						context->fifos[cidx].fifonum = cidx;
-						context->fifos[cidx].hfc = context;
-						context->fifos[cidx].usb_packet_maxlen = le16_to_cpu(ep->desc.wMaxPacketSize);
-						context->fifos[cidx].intervall = ep->desc.bInterval;
-						context->fifos[cidx].skbuff = NULL;
-#ifdef VERBOSE_USB_DEBUG
-						printk (KERN_INFO "HFC-USB: fifo%d pktlen %d interval %d\n",
-							context->fifos[cidx].fifonum,
-							context->fifos[cidx].usb_packet_maxlen,
-							context->fifos[cidx].intervall);
-#endif
+						context->fifos[cidx].
+						    fifonum = cidx;
+						context->fifos[cidx].hfc =
+						    context;
+						context->fifos[cidx].
+						    usb_packet_maxlen =
+						    ep->desc.
+						    wMaxPacketSize;
+						context->fifos[cidx].
+						    intervall =
+						    ep->desc.bInterval;
+						context->fifos[cidx].
+						    skbuff = NULL;
 					}
 				}
-
 				ep++;
 			}
-
-			// now share our luck
-			context->dev = dev;						/* save device */
-			context->if_used = ifnum;					/* save used interface */
-			context->alt_used = alt_used;					/* and alternate config */
+			context->dev = dev;	/* save device */
+			context->if_used = ifnum;	/* save used interface */
+			context->alt_used = alt_used;	/* and alternate config */
 			context->ctrl_paksize = dev->descriptor.bMaxPacketSize0;	/* control size */
-			context->cfg_used=vcf[16];					// store used config
-			context->vend_idx=vend_idx;					// store found vendor
-			context->packet_size=packet_size;
-			context->iso_packet_size=iso_packet_size;
+			context->cfg_used = vcf[16];	/* store used config */
+			context->vend_idx = vend_idx;	/* store found vendor */
+			context->packet_size = packet_size;
+			context->iso_packet_size = iso_packet_size;
 
 			/* create the control pipes needed for register access */
-			context->ctrl_in_pipe = usb_rcvctrlpipe(context->dev, 0);
-			context->ctrl_out_pipe = usb_sndctrlpipe(context->dev, 0);
+			context->ctrl_in_pipe =
+			    usb_rcvctrlpipe(context->dev, 0);
+			context->ctrl_out_pipe =
+			    usb_sndctrlpipe(context->dev, 0);
 			context->ctrl_urb = usb_alloc_urb(0, GFP_KERNEL);
 
-			printk(KERN_INFO "HFC-USB: detected \"%s\" configuration: %s (if=%d alt=%d)\n",
-				vdata[vend_idx].vend_name, conf_str[small_match], context->if_used, context->alt_used);
-
+			printk(KERN_INFO
+			       "HFC-S USB: detected \"%s\"\n",
+			       vdata[vend_idx].vend_name);
+#ifdef CONFIG_HISAX_DEBUG
+			DBG(USB_DBG,
+			    "HFC-S USB: Endpoint-Config: %s (if=%d alt=%d)\n",
+			    conf_str[small_match], context->if_used,
+			    context->alt_used);
+			printk(KERN_INFO
+			       "HFC-S USB: E-channel (\"ECHO:\") logging ");
+			if (validconf[small_match][18])
+				printk(" possible\n");
+			else
+				printk("NOT possible\n");
+#endif
 			/* init the chip and register the driver */
-			if (usb_init(context))
-			{
+			if (usb_init(context)) {
 				if (context->ctrl_urb) {
 					usb_unlink_urb(context->ctrl_urb);
 					usb_free_urb(context->ctrl_urb);
 					context->ctrl_urb = NULL;
 				}
 				kfree(context);
-				return(-EIO);
+				return (-EIO);
 			}
 			usb_set_intfdata(intf, context);
-			return(0);
-		} 
+			return (0);
+		}
+	} else {
+		printk(KERN_INFO
+		       "HFC-S USB: no valid vendor found in USB descriptor\n");
 	}
-	return(-EIO);
+	return (-EIO);
 }
 
 /****************************************************/
 /* function called when an active device is removed */
 /****************************************************/
-static void hfc_usb_disconnect(struct usb_interface *intf)
+static void
+hfc_usb_disconnect(struct usb_interface
+		   *intf)
 {
 	hfcusb_data *context = usb_get_intfdata(intf);
 	int i;
-
-	printk(KERN_INFO "HFC-USB: device disconnect\n");
-	
+	printk(KERN_INFO "HFC-S USB: device disconnect\n");
+	context->disc_flag = TRUE;
 	usb_set_intfdata(intf, NULL);
 	if (!context)
 		return;
@@ -1599,23 +1742,24 @@
 		del_timer(&context->t4_timer);
 	if (timer_pending(&context->led_timer))
 		del_timer(&context->led_timer);
-
-	hisax_unregister(&context->d_if);
-
 	/* tell all fifos to terminate */
-	for(i = 0; i < HFCUSB_NUM_FIFOS; i++) {
-		if(context->fifos[i].usb_transfer_mode == USB_ISOC) {
-			if(context->fifos[i].active > 0) {
-	    			stop_isoc_chain(&context->fifos[i]);
-#ifdef VERBOSE_USB_DEBUG
-		    		printk (KERN_INFO "HFC-USB: hfc_usb_disconnect: stopping ISOC chain Fifo no %i\n", i);
+	for (i = 0; i < HFCUSB_NUM_FIFOS; i++) {
+		if (context->fifos[i].usb_transfer_mode == USB_ISOC) {
+			if (context->fifos[i].active > 0) {
+				stop_isoc_chain(&context->fifos[i]);
+#ifdef CONFIG_HISAX_DEBUG
+				DBG(USB_DBG,
+				    "HFC-S USB: hfc_usb_disconnect: stopping ISOC chain Fifo no %i",
+				    i);
 #endif
- 			}
+			}
 		} else {
-			if(context->fifos[i].active > 0) {
+			if (context->fifos[i].active > 0) {
 				context->fifos[i].active = 0;
-#ifdef VERBOSE_USB_DEBUG
-				printk (KERN_INFO "HFC-USB: hfc_usb_disconnect: unlinking URB for Fifo no %i\n", i);
+#ifdef CONFIG_HISAX_DEBUG
+				DBG(USB_DBG,
+				    "HFC-S USB: hfc_usb_disconnect: unlinking URB for Fifo no %i",
+				    i);
 #endif
 			}
 			if (context->fifos[i].urb) {
@@ -1626,46 +1770,59 @@
 		}
 		context->fifos[i].active = 0;
 	}
+	/* wait for all URBS to terminate */
+	mdelay(10);
 	if (context->ctrl_urb) {
 		usb_unlink_urb(context->ctrl_urb);
 		usb_free_urb(context->ctrl_urb);
 		context->ctrl_urb = NULL;
 	}
+	hisax_unregister(&context->d_if);
 	kfree(context);		/* free our structure again */
 }				/* hfc_usb_disconnect */
 
-
 /************************************/
 /* our driver information structure */
 /************************************/
 static struct usb_driver hfc_drv = {
-	.owner =	THIS_MODULE,
-	.name =		"hfc_usb",
-	.id_table = 	hfc_usb_idtab,
-	.probe =	hfc_usb_probe,
-	.disconnect =	hfc_usb_disconnect,
+	.owner = THIS_MODULE,.name =
+	    "hfc_usb",.id_table = hfc_usb_idtab,.probe =
+	    hfc_usb_probe,.disconnect = hfc_usb_disconnect,
 };
-
-static void __exit hfc_usb_exit(void)
+static void __exit
+hfc_usb_exit(void)
 {
-#ifdef VERBOSE_USB_DEBUG
-	printk ("HFC-USB: calling \"hfc_usb_exit\" ...\n");
+#ifdef CONFIG_HISAX_DEBUG
+	DBG(USB_DBG, "HFC-S USB: calling \"hfc_usb_exit\" ...");
 #endif
 	usb_deregister(&hfc_drv);	/* release our driver */
-	printk(KERN_INFO "HFC-USB module removed\n");
+	printk(KERN_INFO "HFC-S USB: module removed\n");
 }
 
-static int __init hfc_usb_init(void)
+static int __init
+hfc_usb_init(void)
 {
-	printk ("HFC-USB: driver module revision %s loaded\n", hfcusb_revision);
-
-	if(usb_register(&hfc_drv))
-	{
-		printk(KERN_INFO "HFC-USB: Unable to register HFC-USB module at usb stack\n");
-		return(-1);		   /* unable to register */
+#ifndef CONFIG_HISAX_DEBUG
+	unsigned int debug = -1;
+#endif
+	char revstr[30], datestr[30], dummy[30];
+	sscanf(hfcusb_revision,
+	       "%s %s $ %s %s %s $ ", dummy, revstr,
+	       dummy, datestr, dummy);
+	printk(KERN_INFO
+	       "HFC-S USB: driver module revision %s date %s loaded, (debug=%i)\n",
+	       revstr, datestr, debug);
+	if (usb_register(&hfc_drv)) {
+		printk(KERN_INFO
+		       "HFC-S USB: Unable to register HFC-S USB module at usb stack\n");
+		return (-1);	/* unable to register */
 	}
-	return(0);
+	return (0);
 }
 
 module_init(hfc_usb_init);
 module_exit(hfc_usb_exit);
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
+MODULE_DEVICE_TABLE(usb, hfc_usb_idtab);
diff -Nru a/drivers/isdn/hisax/hfc_usb.h b/drivers/isdn/hisax/hfc_usb.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/isdn/hisax/hfc_usb.h	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,228 @@
+/*
+* hfc_usb.h
+*
+* $Id: hfc_usb.h,v 4.1 2005/01/26 17:25:53 martinb1 Exp $
+*/
+
+#ifndef __HFC_USB_H__
+#define __HFC_USB_H__
+
+#define DRIVER_AUTHOR   "Peter Sprenger (sprenger@moving-byters.de)"
+#define DRIVER_DESC     "HFC-S USB based HiSAX ISDN driver"
+
+#define VERBOSE_USB_DEBUG
+
+#define TRUE  1
+#define FALSE 0
+
+
+/***********/
+/* defines */
+/***********/
+#define HFC_CTRL_TIMEOUT 20	/* 5ms timeout writing/reading regs */
+#define HFC_TIMER_T3 8000	/* timeout for l1 activation timer */
+#define HFC_TIMER_T4 500	/* time for state change interval */
+
+#define HFCUSB_L1_STATECHANGE 0	/* L1 state changed */
+#define HFCUSB_L1_DRX 1		/* D-frame received */
+#define HFCUSB_L1_ERX 2		/* E-frame received */
+#define HFCUSB_L1_DTX 4		/* D-frames completed */
+
+#define MAX_BCH_SIZE 2048	/* allowed B-channel packet size */
+
+#define HFCUSB_RX_THRESHOLD 64	/* threshold for fifo report bit rx */
+#define HFCUSB_TX_THRESHOLD 64	/* threshold for fifo report bit tx */
+
+#define HFCUSB_CHIP_ID		0x16	/* Chip ID register index */
+#define HFCUSB_CIRM		0x00	/* cirm register index */
+#define HFCUSB_USB_SIZE		0x07	/* int length register */
+#define HFCUSB_USB_SIZE_I	0x06	/* iso length register */
+#define HFCUSB_F_CROSS		0x0b	/* bit order register */
+#define HFCUSB_CLKDEL		0x37	/* bit delay register */
+#define HFCUSB_CON_HDLC		0xfa	/* channel connect register */
+#define HFCUSB_HDLC_PAR		0xfb
+#define HFCUSB_SCTRL		0x31	/* S-bus control register (tx) */
+#define HFCUSB_SCTRL_E		0x32	/* same for E and special funcs */
+#define HFCUSB_SCTRL_R		0x33	/* S-bus control register (rx) */
+#define HFCUSB_F_THRES		0x0c	/* threshold register */
+#define HFCUSB_FIFO		0x0f	/* fifo select register */
+#define HFCUSB_F_USAGE		0x1a	/* fifo usage register */
+#define HFCUSB_MST_MODE0	0x14
+#define HFCUSB_MST_MODE1	0x15
+#define HFCUSB_P_DATA		0x1f
+#define HFCUSB_INC_RES_F	0x0e
+#define HFCUSB_STATES		0x30
+
+#define HFCUSB_CHIPID		0x40	/* ID value of HFC-S USB */
+
+/******************/
+/* fifo registers */
+/******************/
+#define HFCUSB_NUM_FIFOS	8	/* maximum number of fifos */
+#define HFCUSB_B1_TX		0	/* index for B1 transmit bulk/int */
+#define HFCUSB_B1_RX		1	/* index for B1 receive bulk/int */
+#define HFCUSB_B2_TX		2
+#define HFCUSB_B2_RX		3
+#define HFCUSB_D_TX		4
+#define HFCUSB_D_RX		5
+#define HFCUSB_PCM_TX		6
+#define HFCUSB_PCM_RX		7
+
+/*
+* used to switch snd_transfer_mode for different TA modes e.g. the Billion USB TA just
+* supports ISO out, while the Cologne Chip EVAL TA just supports BULK out
+*/
+#define USB_INT		0
+#define USB_BULK	1
+#define USB_ISOC	2
+
+#define ISOC_PACKETS_D	8
+#define ISOC_PACKETS_B	8
+#define ISO_BUFFER_SIZE	128
+
+// ISO send definitions
+#define SINK_MAX	68
+#define SINK_MIN	48
+#define SINK_DMIN	12
+#define SINK_DMAX	18
+#define BITLINE_INF	(-64*8)
+
+
+/**********/
+/* macros */
+/**********/
+#define write_usb(a,b,c)usb_control_msg((a)->dev,(a)->ctrl_out_pipe,0,0x40,(c),(b),0,0,HFC_CTRL_TIMEOUT)
+#define read_usb(a,b,c) usb_control_msg((a)->dev,(a)->ctrl_in_pipe,1,0xC0,0,(b),(c),1,HFC_CTRL_TIMEOUT)
+
+
+/*******************/
+/* Debugging Flags */
+/*******************/
+#define USB_DBG   1
+#define ISDN_DBG  2
+
+
+/* *********************/
+/* USB related defines */
+/***********************/
+#define HFC_CTRL_BUFSIZE 32
+
+
+
+/*************************************************/
+/* entry and size of output/input control buffer */
+/*************************************************/
+typedef struct {
+	__u8 hfc_reg;		/* register number */
+	__u8 reg_val;		/* value to be written (or read) */
+	int action;		/* data for action handler */
+} ctrl_buft;
+
+
+/********************/
+/* URB error codes: */
+/********************/
+/* Used to represent a list of values and their respective symbolic names */
+struct hfcusb_symbolic_list {
+	const int num;
+	const char *name;
+};
+
+static struct hfcusb_symbolic_list urb_errlist[] = {
+	{-ENOMEM, "No memory for allocation of internal structures"},
+	{-ENOSPC, "The host controller's bandwidth is already consumed"},
+	{-ENOENT, "URB was canceled by unlink_urb"},
+	{-EXDEV, "ISO transfer only partially completed"},
+	{-EAGAIN, "Too match scheduled for the future"},
+	{-ENXIO, "URB already queued"},
+	{-EFBIG, "Too much ISO frames requested"},
+	{-ENOSR, "Buffer error (overrun)"},
+	{-EPIPE, "Specified endpoint is stalled (device not responding)"},
+	{-EOVERFLOW, "Babble (bad cable?)"},
+	{-EPROTO, "Bit-stuff error (bad cable?)"},
+	{-EILSEQ, "CRC/Timeout"},
+	{-ETIMEDOUT, "NAK (device does not respond)"},
+	{-ESHUTDOWN, "Device unplugged"},
+	{-1, NULL}
+};
+
+
+/*****************************************************/
+/* device dependant information to support different */
+/* ISDN Ta's using the HFC-S USB chip                */
+/*****************************************************/
+
+/* USB descriptor need to contain one of the following EndPoint combination: */
+#define CNF_4INT3ISO	1	// 4 INT IN, 3 ISO OUT
+#define CNF_3INT3ISO	2	// 3 INT IN, 3 ISO OUT
+#define CNF_4ISO3ISO	3	// 4 ISO IN, 3 ISO OUT
+#define CNF_3ISO3ISO	4	// 3 ISO IN, 3 ISO OUT
+
+#define EP_NUL 1		// Endpoint at this position not allowed
+#define EP_NOP 2		// all type of endpoints allowed at this position
+#define EP_ISO 3		// Isochron endpoint mandatory at this position
+#define EP_BLK 4		// Bulk endpoint mandatory at this position
+#define EP_INT 5		// Interrupt endpoint mandatory at this position
+
+/* this array represents all endpoints possible in the HCF-USB the last
+* 3 entries are the configuration number, the minimum interval for
+* Interrupt endpoints & boolean if E-channel logging possible
+*/
+int validconf[][19] = {
+	// INT in, ISO out config
+	{EP_NUL, EP_INT, EP_NUL, EP_INT, EP_NUL, EP_INT, EP_NOP, EP_INT,
+	 EP_ISO, EP_NUL, EP_ISO, EP_NUL, EP_ISO, EP_NUL, EP_NUL, EP_NUL,
+	 CNF_4INT3ISO, 2, 1},
+	{EP_NUL, EP_INT, EP_NUL, EP_INT, EP_NUL, EP_INT, EP_NUL, EP_NUL,
+	 EP_ISO, EP_NUL, EP_ISO, EP_NUL, EP_ISO, EP_NUL, EP_NUL, EP_NUL,
+	 CNF_3INT3ISO, 2, 0},
+	// ISO in, ISO out config
+	{EP_NUL, EP_NUL, EP_NUL, EP_NUL, EP_NUL, EP_NUL, EP_NUL, EP_NUL,
+	 EP_ISO, EP_ISO, EP_ISO, EP_ISO, EP_ISO, EP_ISO, EP_NOP, EP_ISO,
+	 CNF_4ISO3ISO, 2, 1},
+	{EP_NUL, EP_NUL, EP_NUL, EP_NUL, EP_NUL, EP_NUL, EP_NUL, EP_NUL,
+	 EP_ISO, EP_ISO, EP_ISO, EP_ISO, EP_ISO, EP_ISO, EP_NUL, EP_NUL,
+	 CNF_3ISO3ISO, 2, 0},
+	{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}	// EOL element
+};
+
+// string description of chosen config
+char *conf_str[] = {
+	"4 Interrupt IN + 3 Isochron OUT",
+	"3 Interrupt IN + 3 Isochron OUT",
+	"4 Isochron IN + 3 Isochron OUT",
+	"3 Isochron IN + 3 Isochron OUT"
+};
+
+
+typedef struct {
+	int vendor;		// vendor id
+	int prod_id;		// product id
+	char *vend_name;	// vendor string
+	__u8 led_scheme;	// led display scheme
+	signed short led_bits[8];	// array of 8 possible LED bitmask settings
+} vendor_data;
+
+#define LED_OFF      0		// no LED support
+#define LED_SCHEME1  1		// LED standard scheme
+#define LED_SCHEME2  2		// not used yet...
+
+#define LED_POWER_ON	1
+#define LED_POWER_OFF	2
+#define LED_S0_ON	3
+#define LED_S0_OFF	4
+#define LED_B1_ON	5
+#define LED_B1_OFF	6
+#define LED_B1_DATA	7
+#define LED_B2_ON	8
+#define LED_B2_OFF	9
+#define LED_B2_DATA	10
+
+#define LED_NORMAL   0		// LEDs are normal
+#define LED_INVERTED 1		// LEDs are inverted
+
+/* time in ms to perform a Flashing LED when B-Channel has traffic */
+#define LED_TIME      250
+
+
+#endif				// __HFC_USB_H__
diff -Nru a/drivers/isdn/hisax/hisax_fcpcipnp.c b/drivers/isdn/hisax/hisax_fcpcipnp.c
--- a/drivers/isdn/hisax/hisax_fcpcipnp.c	2005-03-11 12:51:48 -08:00
+++ b/drivers/isdn/hisax/hisax_fcpcipnp.c	2005-03-11 12:51:48 -08:00
@@ -902,7 +902,7 @@
 	adapter->irq = pdev->irq;
 
 	printk(KERN_INFO "hisax_fcpcipnp: found adapter %s at %s\n",
-	       (char *) ent->driver_data, pdev->slot_name);
+	       (char *) ent->driver_data, pci_name(pdev));
 
 	retval = fcpcipnp_setup(adapter);
 	if (retval)
diff -Nru a/drivers/isdn/i4l/Kconfig b/drivers/isdn/i4l/Kconfig
--- a/drivers/isdn/i4l/Kconfig	2005-03-11 12:51:42 -08:00
+++ b/drivers/isdn/i4l/Kconfig	2005-03-11 12:51:42 -08:00
@@ -135,8 +135,6 @@
 
 source "drivers/isdn/act2000/Kconfig"
 
-source "drivers/isdn/tpam/Kconfig"
-
 source "drivers/isdn/hysdn/Kconfig"
 
 endmenu
diff -Nru a/drivers/isdn/tpam/Kconfig b/drivers/isdn/tpam/Kconfig
--- a/drivers/isdn/tpam/Kconfig	2005-03-11 12:51:41 -08:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,15 +0,0 @@
-#
-# Config.in for Auvertech TurboPAM ISDN driver
-#
-config ISDN_DRV_TPAM
-	tristate "Auvertech TurboPAM support (EXPERIMENTAL)"
-	depends on EXPERIMENTAL && ISDN_I4L && PCI
-	select CRC_CCITT
-	help
-	  This enables support for the Auvertech TurboPAM ISDN-card.
-	  For running this card, additional firmware is necessary, which has
-	  to be downloaded into the card using a utility which is distributed
-	  separately from the Auvertech's web site: <http://www.auvertech.fr/>.
-
-	  Please redirect all support questions to <support@auvertech.fr>.
-
diff -Nru a/drivers/isdn/tpam/Makefile b/drivers/isdn/tpam/Makefile
--- a/drivers/isdn/tpam/Makefile	2005-03-11 12:51:41 -08:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,11 +0,0 @@
-# Makefile for the TurboPAM ISDN device driver
-
-# Each configuration option enables a list of files.
-
-obj-$(CONFIG_ISDN_DRV_TPAM)	+= tpam.o
-
-# Multipart objects.
-
-tpam-y				:= tpam_main.o tpam_nco.o tpam_memory.o \
-				   tpam_commands.o tpam_queues.o tpam_hdlc.o \
-				   tpam_crcpc.o
diff -Nru a/drivers/isdn/tpam/tpam.h b/drivers/isdn/tpam/tpam.h
--- a/drivers/isdn/tpam/tpam.h	2005-03-11 12:51:41 -08:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,229 +0,0 @@
-/* $Id: tpam.h,v 1.1.2.3 2001/11/06 20:58:30 kai Exp $
- *
- * Turbo PAM ISDN driver for Linux. (Kernel Driver)
- *
- * Copyright 2001 Stelian Pop <stelian.pop@fr.alcove.com>, Alcôve
- *
- * This software may be used and distributed according to the terms
- * of the GNU General Public License, incorporated herein by reference.
- *
- * For all support questions please contact: <support@auvertech.fr>
- *
- */
-
-#ifndef _TPAM_PRIV_H_
-#define _TPAM_PRIV_H_
-
-//#define DEBUG /* uncomment if you want debugging output */
-#include <linux/kernel.h>
-#include <linux/isdnif.h>
-#include <linux/init.h>
-#include <linux/workqueue.h>
-#include <linux/interrupt.h>
-
-/* Maximum number of channels for this board */
-#define TPAM_NBCHANNEL		30
-/* Maximum size of data */
-#define TPAM_MAXBUFSIZE		2032
-/* Size of a page of board memory */
-#define TPAM_PAGE_SIZE		0x003ffffc	/* 4 MB */
-/* Magic number present if the board was successfully started */
-#define TPAM_MAGICNUMBER	0x2a343242
-
-/* Registers in the PCI BAR0 */
-#define TPAM_PAGE_REGISTER	0x00400000	/* Select page */
-#define TPAM_DSPINT_REGISTER	0x00400004	/* Interrupt board */
-#define TPAM_RESETPAM_REGISTER	0x00400008	/* Reset board */
-#define TPAM_HINTACK_REGISTER	0x0040000c	/* Ack interrupt */
-#define TPAM_HPIC_REGISTER	0x00400014	/* Board ready */
-
-/* Registers in the board memory */
-#define TPAM_MAGICNUMBER_REGISTER	0x80008000 /* Magic number */
-#define TPAM_EXID_REGISTER		0x80008004 /* EXID - not used */
-#define TPAM_UPLOADPTR_REGISTER		0x80008008 /* Upload data ptr */
-#define TPAM_DOWNLOADPTR_REGISTER	0x8000800c /* Download data ptr */
-#define TPAM_ACKUPLOAD_REGISTER		0x80008010 /* Ack upload */
-#define TPAM_ACKDOWNLOAD_REGISTER	0x80008014 /* Ack download */
-#define TPAM_INTERRUPTACK_REGISTER	0x80008018 /* Ack interrupt */
-
-/* Reserved areas in the board memory */
-#define	TPAM_RESERVEDAREA1_START	0x00000000
-#define TPAM_RESERVEDAREA1_END		0x003FFFFF
-#define TPAM_RESERVEDAREA2_START	0x01C00000
-#define TPAM_RESERVEDAREA2_END		0x01FFFFFF
-#define TPAM_RESERVEDAREA3_START	0x04000000
-#define TPAM_RESERVEDAREA3_END		0x7FFFFFFF
-#define TPAM_RESERVEDAREA4_START	0x80010000
-#define TPAM_RESERVEDAREA4_END		0xFFFFFFFF
-
-/* NCO ID invalid */
-#define TPAM_NCOID_INVALID	0xffff
-/* channel number invalid */
-#define TPAM_CHANNEL_INVALID	0xffff
-
-/* Channel structure */
-typedef struct tpam_channel {
-	int num;			/* channel number */
-	struct tpam_card *card;		/* channel's card */
-	u32 ncoid;			/* ncoid */
-	u8  hdlc;			/* hdlc mode (set by user level) */
-	u8  realhdlc;			/* hdlc mode (negociated with peer) */
-	u32 hdlcshift;			/* hdlc shift */
-	u8  readytoreceive;		/* channel ready to receive data */
-	struct sk_buff_head sendq;	/* Send queue */
-} tpam_channel;
-
-/* Card structure */
-typedef struct tpam_card {
-	struct tpam_card *next;		/* next card in list */
-	unsigned int irq;		/* IRQ used by this board */
-	void __iomem *bar0;		/* ioremapped bar0 */
-	int id;				/* id of the board */
-	isdn_if interface;		/* isdn link-level pointer */
-	int channels_used;		/* number of channels actually used */
-	int channels_tested;		/* number of channels being tested */
-	u8 loopmode;			/* board in looptest mode */
-	tpam_channel channels[TPAM_NBCHANNEL];/* channels tab */
-	int running;			/* card is running */
-	int busy;			/* waiting for ack from card */
-	int roundrobin;			/* round robin between channels */
-	struct sk_buff_head sendq;	/* send queue */
-	struct sk_buff_head recvq;	/* receive queue */
-	struct work_struct send_tq;	/* send task queue */
-	struct work_struct recv_tq;	/* receive task queue */
-	spinlock_t lock;		/* lock for the card */
-} tpam_card;
-
-/* Timeout waiting for signature to become available */
-#define SIGNATURE_TIMEOUT	(5*HZ)
-/* Timeout waiting for receiving all the ACreateNCOCnf */
-#define NCOCREATE_TIMEOUT	(30*HZ)
-
-/* Maximum size of the TLV block */
-#define MPB_MAXIMUMBLOCKTLVSIZE	 128
-/* Maximum size of the data block */
-#define MPB_MAXIMUMDATASIZE	4904
-/* Maximum size of a phone number */
-#define PHONE_MAXIMUMSIZE	  32
-
-/* Header for a sk_buff structure */
-typedef struct skb_header {
-	u16 size;		/* size of pci_mpb block + size of tlv block */
-	u16 data_size;		/* size of the data block */
-	u16 ack;		/* packet needs to send ack upon send */
-	u16 ack_size;		/* size of data to be acknowledged upon send */
-} skb_header;
-
-/* PCI message header structure */
-typedef struct pci_mpb {
-	u16 exID;			/* exID - not used */
-	u16 flags;			/* flags - not used */
-	u32 errorCode;			/* errorCode - not used */
-	u16 messageID;			/* message ID - one of ID_XXX */
-	u16 maximumBlockTLVSize;	/* MPB_MAXIMUMBLOCKTLVSIZE */
-	u16 actualBlockTLVSize;		/* size of the tlv block */
-	u16 maximumDataSize;		/* MPB_MAXIMUMDATASIZE */
-	u16 actualDataSize;		/* size of the data block */
-	u16 dummy;			/* padding */
-} pci_mpb;
-
-/* Types of PCI messages */
-#define ID_ACreateNCOReq	101
-#define ID_ACreateNCOCnf	102
-#define ID_ADestroyNCOReq	103
-#define ID_ADestroyNCOCnf	104
-#define ID_CConnectReq		203
-#define ID_CConnectInd		204
-#define ID_CConnectRsp		205
-#define ID_CConnectCnf		206
-#define ID_CDisconnectReq	207
-#define ID_CDisconnectInd	208
-#define ID_CDisconnectRsp	209
-#define ID_CDisconnectCnf	210
-#define ID_U3DataReq		307
-#define ID_U3DataInd		308
-#define ID_U3ReadyToReceiveInd	318
-
-/* Parameters for the PCI message TLV block */
-#define PAR_BearerCap		3
-#define PAR_CalledNumber	7
-#define PAR_CallingNumber	11
-#define PAR_CauseToPUF		15
-#define PAR_Cdirection		16
-#define PAR_CompletionStatus	19
-#define PAR_Facility		30
-#define PAR_HLC			34
-#define PAR_NCOID		49
-#define PAR_NCOType		50
-#define PAR_ReadyFlag		55
-#define PAR_U3Protocol		62
-#define PAR_Udirection		64
-
-/* Delayed statcallb structure */
-typedef struct tpam_statcallb_data {
-	tpam_card *card;		/* card issuing the statcallb */
-	struct timer_list *timer;	/* timer launching the statcallb */
-	isdn_ctrl ctrl;			/* isdn command */
-} tpam_statcallb_data;
-
-/* Function prototypes from tpam_main.c */
-extern tpam_card *tpam_findcard(int);
-extern u32 tpam_findchannel(tpam_card *, u32);
-
-/* Function prototypes from tpam_memory.c */
-extern void copy_to_pam_dword(tpam_card *, u32, u32);
-extern void copy_to_pam(tpam_card *, u32, const void *, u32);
-extern u32 copy_from_pam_dword(tpam_card *, u32);
-extern void copy_from_pam(tpam_card *, void *, u32, u32);
-extern int copy_from_pam_to_user(tpam_card *, void __user *, u32, u32);
-extern int copy_from_user_to_pam(tpam_card *, u32, const void __user *, u32);
-extern int tpam_verify_area(u32, u32);
-
-/* Function prototypes from tpam_nco.c */
-extern struct sk_buff *build_ACreateNCOReq(const u8 *);
-extern struct sk_buff *build_ADestroyNCOReq(u32);
-extern struct sk_buff *build_CConnectReq(u32, const u8 *, u8);
-extern struct sk_buff *build_CConnectRsp(u32);
-extern struct sk_buff *build_CDisconnectReq(u32);
-extern struct sk_buff *build_CDisconnectRsp(u32);
-extern struct sk_buff *build_U3DataReq(u32, void *, u16, u16, u16);
-extern int parse_ACreateNCOCnf(struct sk_buff *, u8 *, u32 *);
-extern int parse_ADestroyNCOCnf(struct sk_buff *, u8 *, u32 *);
-extern int parse_CConnectCnf(struct sk_buff *, u32 *);
-extern int parse_CConnectInd(struct sk_buff *, u32 *, u8 *, u8 *, 
-			     u8 *, u8 *, u8 *);
-extern int parse_CDisconnectCnf(struct sk_buff *, u32 *, u32 *);
-extern int parse_CDisconnectInd(struct sk_buff *, u32 *, u32 *);
-extern int parse_U3ReadyToReceiveInd(struct sk_buff *, u32 *, u8 *);
-extern int parse_U3DataInd(struct sk_buff *, u32 *, u8 **, u16 *);
-
-/* Function prototypes from tpam_queues.c */
-extern void tpam_enqueue(tpam_card *, struct sk_buff *);
-extern void tpam_enqueue_data(tpam_channel *, struct sk_buff *);
-extern irqreturn_t tpam_irq(int, void *, struct pt_regs *);
-extern void tpam_recv_tq(tpam_card *);
-extern void tpam_send_tq(tpam_card *);
-
-/* Function prototypes from tpam_commands.c */
-extern int tpam_command(isdn_ctrl *);
-extern int tpam_writebuf_skb(int, int, int, struct sk_buff *);
-extern void tpam_recv_ACreateNCOCnf(tpam_card *, struct sk_buff *);
-extern void tpam_recv_ADestroyNCOCnf(tpam_card *, struct sk_buff *);
-extern void tpam_recv_CConnectCnf(tpam_card *, struct sk_buff *);
-extern void tpam_recv_CConnectInd(tpam_card *, struct sk_buff *);
-extern void tpam_recv_CDisconnectInd(tpam_card *, struct sk_buff *);
-extern void tpam_recv_CDisconnectCnf(tpam_card *, struct sk_buff *);
-extern void tpam_recv_U3DataInd(tpam_card *, struct sk_buff *);
-extern void tpam_recv_U3ReadyToReceiveInd(tpam_card *, struct sk_buff *);
-
-/* Function prototypes from tpam_hdlc.c */
-extern u32 tpam_hdlc_encode(u8 *, u8 *, u32 *, u32);
-extern u32 tpam_hdlc_decode(u8 *, u8 *, u32);
-
-/* Function prototypes from tpam_crcpc.c */
-extern void init_CRC(void);
-extern void hdlc_encode_modem(u8 *, u32, u8 *, u32 *);
-extern void hdlc_no_accm_encode(u8 *, u32, u8 *, u32 *);
-extern u32 hdlc_no_accm_decode(u8 *, u32);
-
-#endif /* _TPAM_H_ */
diff -Nru a/drivers/isdn/tpam/tpam_commands.c b/drivers/isdn/tpam/tpam_commands.c
--- a/drivers/isdn/tpam/tpam_commands.c	2005-03-11 12:51:41 -08:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,987 +0,0 @@
-/* $Id: tpam_commands.c,v 1.1.2.4 2001/11/06 20:58:30 kai Exp $
- *
- * Turbo PAM ISDN driver for Linux. (Kernel Driver - ISDN commands)
- *
- * Copyright 2001 Stelian Pop <stelian.pop@fr.alcove.com>, Alcôve
- *
- * This software may be used and distributed according to the terms
- * of the GNU General Public License, incorporated herein by reference.
- *
- * For all support questions please contact: <support@auvertech.fr>
- *
- */
-
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/sched.h>
-#include <linux/interrupt.h>
-#include <asm/io.h>
-
-#include <linux/isdn/tpam.h>
-#include "tpam.h"
-
-/* Local functions prototypes */
-static int tpam_command_ioctl_dspload(tpam_card *, unsigned long);
-static int tpam_command_ioctl_dspsave(tpam_card *, unsigned long);
-static int tpam_command_ioctl_dsprun(tpam_card *);
-static int tpam_command_ioctl_loopmode(tpam_card *, u8);
-static int tpam_command_dial(tpam_card *, u32, u8 *);
-static int tpam_command_setl2(tpam_card *, u32, u8);
-static int tpam_command_acceptd(tpam_card *, u32);
-static int tpam_command_acceptb(tpam_card *, u32);
-static int tpam_command_hangup(tpam_card *, u32);
-static int tpam_command_proceed(tpam_card *, u32);
-static void tpam_statcallb_run(unsigned long);
-static void tpam_statcallb(tpam_card *, isdn_ctrl);
-
-/*
- * Function called when the ISDN link level send a command to the driver.
- *
- * 	c: ISDN command.
- *
- * Return: 0 if OK, <0 on errors.
- */
-int tpam_command(isdn_ctrl *c) {
-	tpam_card *card;
-	unsigned long argp;
-
-	pr_debug("TurboPAM(tpam_command) card=%d, command=%d\n",
-		c->driver, c->command);	
-
-	/* search for the board */
-	if (!(card = tpam_findcard(c->driver))) {
-		printk(KERN_ERR "TurboPAM(tpam_command): invalid driverId %d\n",
-		       c->driver);	
-		return -ENODEV;
-	}
-
-	/* dispatch the command */
-	switch (c->command) {
-		case ISDN_CMD_IOCTL:
-			argp = c->parm.userdata;
-			switch (c->arg) {
-				case TPAM_CMD_DSPLOAD:
-					return tpam_command_ioctl_dspload(card,
-									  argp);
-				case TPAM_CMD_DSPSAVE:
-					return tpam_command_ioctl_dspsave(card,
-									  argp);
-				case TPAM_CMD_DSPRUN:
-					return tpam_command_ioctl_dsprun(card);
-				case TPAM_CMD_LOOPMODEON:
-					return tpam_command_ioctl_loopmode(card,
-									   1);
-				case TPAM_CMD_LOOPMODEOFF:
-					return tpam_command_ioctl_loopmode(card,
-									   0);
-				default:
-					pr_debug("TurboPAM(tpam_command): "
-						"invalid tpam ioctl %ld\n", 
-						c->arg);	
-					return -EINVAL;
-			}
-		case ISDN_CMD_DIAL:
-			return tpam_command_dial(card, c->arg, 
-						 c->parm.setup.phone);
-		case ISDN_CMD_ACCEPTD:
-			return tpam_command_acceptd(card, c->arg);
-		case ISDN_CMD_ACCEPTB:
-			return tpam_command_acceptb(card, c->arg);
-		case ISDN_CMD_HANGUP:
-			return tpam_command_hangup(card, c->arg);
-		case ISDN_CMD_SETL2:
-			return tpam_command_setl2(card, c->arg & 0xff, 
-						  c->arg >> 8);
-		case ISDN_CMD_PROCEED:
-			return tpam_command_proceed(card, c->arg);
-		default:
-			pr_debug("TurboPAM(tpam_command): "
-				"unknown or unused isdn ioctl %d\n", 
-				c->command);	
-			return -EINVAL;
-	}
-
-	/* not reached */
-	return -EINVAL;
-}
-
-/*
- * Load some data into the board's memory.
- *
- * 	card: the board
- * 	arg: IOCTL argument containing the user space address of 
- * 		the tpam_dsp_ioctl structure describing the IOCTL.
- *
- * Return: 0 if OK, <0 on errors.
- */
-static int tpam_command_ioctl_dspload(tpam_card *card, unsigned long arg) {
-	tpam_dsp_ioctl tdl;
-
-	pr_debug("TurboPAM(tpam_command_ioctl_dspload): card=%d\n", card->id);
-
-	/* get the IOCTL parameter from userspace */
-	if (copy_from_user(&tdl, (void __user *)arg, sizeof(tpam_dsp_ioctl)))
-		return -EFAULT;
-
-	/* if the board's firmware was started, protect against writes
-	 * to unallowed memory areas. If the board's firmware wasn't started,
-	 * all is allowed. */
-	if (card->running && tpam_verify_area(tdl.address, tdl.data_len)) 
-		return -EPERM;
-
-	/* write the data in the board's memory */
-	return copy_from_user_to_pam(card, tdl.address, 
-				     (void __user *)arg + sizeof(tpam_dsp_ioctl), 
-				     tdl.data_len);
-}
-
-/*
- * Extract some data from the board's memory.
- *
- * 	card: the board
- * 	arg: IOCTL argument containing the user space address of 
- * 		the tpam_dsp_ioctl structure describing the IOCTL.
- *
- * Return: 0 if OK, <0 on errors.
- */
-static int tpam_command_ioctl_dspsave(tpam_card *card, unsigned long arg) {
-	tpam_dsp_ioctl tdl;
-
-	pr_debug("TurboPAM(tpam_command_ioctl_dspsave): card=%d\n", card->id);
-
-	/* get the IOCTL parameter from userspace */
-	if (copy_from_user(&tdl, (void __user *)arg, sizeof(tpam_dsp_ioctl)))
-		return -EFAULT;
-
-	/* protect against read from unallowed memory areas */
-	if (tpam_verify_area(tdl.address, tdl.data_len)) 
-		return -EPERM;
-
-	/* read the data from the board's memory */
-	return copy_from_pam_to_user(card, (void __user *)arg + sizeof(tpam_dsp_ioctl),
-				     tdl.address, tdl.data_len);
-}
-
-/*
- * Launch the board's firmware. This function must be called after the 
- * firmware was loaded into the board's memory using TPAM_CMD_DSPLOAD 
- * IOCTL commands. After launching the firmware, this function creates
- * the NCOs and waits for their creation.
- *
- * 	card: the board
- *
- * Return: 0 if OK, <0 on errors.
- */
-static int tpam_command_ioctl_dsprun(tpam_card *card) {
-	u32 signature = 0, i;
-	unsigned long timeout;
-	isdn_ctrl ctrl;
-	struct sk_buff *skb;
-
-	pr_debug("TurboPAM(tpam_command_ioctl_dsprun): card=%d\n", card->id);
-
-	/* board must _not_ be running */
-	if (card->running)
-		return -EBUSY;
-
-	/* reset the board */
-	spin_lock_irq(&card->lock);
-	copy_to_pam_dword(card, TPAM_MAGICNUMBER_REGISTER, 0xdeadface);
-	readl(card->bar0 + TPAM_DSPINT_REGISTER);
-	readl(card->bar0 + TPAM_HINTACK_REGISTER);
-	spin_unlock_irq(&card->lock);
-	
-	/* wait for the board signature */
-	timeout = jiffies + SIGNATURE_TIMEOUT;
-	while (time_before(jiffies, timeout)) {
-		spin_lock_irq(&card->lock);
-		signature = copy_from_pam_dword(card, 
-						TPAM_MAGICNUMBER_REGISTER);
-		spin_unlock_irq(&card->lock);
-		if (signature == TPAM_MAGICNUMBER)
-			break;
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		schedule_timeout(2);
-	}
-
-	/* signature not present -> board not started */
-	if (signature != TPAM_MAGICNUMBER) {
-		printk(KERN_ERR "TurboPAM(tpam_command_ioctl_dsprun): "
-		       "card=%d, signature 0x%lx, expected 0x%lx\n", 
-		       card->id, (unsigned long)signature, 
-		       (unsigned long)TPAM_MAGICNUMBER);
-		printk(KERN_ERR "TurboPAM(tpam_command_ioctl_dsprun): "
-		       "card=%d, firmware not started\n", card->id);
-		return -EIO;
-	}
-
-	/* the firmware is started */
-	printk(KERN_INFO "TurboPAM: card=%d, firmware started\n", card->id);
-
-	/* init the CRC routines */
-	init_CRC();
-
-	/* create all the NCOs */
-	for (i = 0; i < TPAM_NBCHANNEL; ++i)
-		if ((skb = build_ACreateNCOReq("")))
-			tpam_enqueue(card, skb);
-
-	/* wait for NCO creation confirmation */
-	timeout = jiffies + NCOCREATE_TIMEOUT;
-	while (time_before(jiffies, timeout)) {
-		if (card->channels_tested == TPAM_NBCHANNEL)
-			break;
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		schedule_timeout(2);
-	}
-
-	card->running = 1;
-
-	if (card->channels_tested != TPAM_NBCHANNEL)
-		printk(KERN_ERR "TurboPAM(tpam_command_ioctl_dsprun): "
-		       "card=%d, tried to init %d channels, "
-		       "got reply from only %d channels\n", card->id, 
-		       TPAM_NBCHANNEL, card->channels_tested);
-
-	/* if all the channels were not initialized, signal to the ISDN
-	 * link layer that fact that some channels are not usable */
-	if (card->channels_used != TPAM_NBCHANNEL)
-		for (i = card->channels_used; i < TPAM_NBCHANNEL; ++i) {
-			ctrl.driver = card->id;
-			ctrl.command = ISDN_STAT_DISCH;
-			ctrl.arg = i;
-			ctrl.parm.num[0] = 0;
-			(* card->interface.statcallb)(&ctrl);
-		}
-
-	printk(KERN_INFO "TurboPAM: card=%d, ready, %d channels available\n", 
-	       card->id, card->channels_used);
-
-	/* let's rock ! */
-	ctrl.driver = card->id;
-	ctrl.command = ISDN_STAT_RUN;
-	ctrl.arg = 0;
-	tpam_statcallb(card, ctrl);
-
-	return 0;
-}
-
-/* 
- * Set/reset the board's looptest mode.
- *
- * 	card: the board
- * 	mode: if 1, sets the board's looptest mode, if 0 resets it.
- *
- * Return: 0 if OK, <0 if error.
- */
-static int tpam_command_ioctl_loopmode(tpam_card *card, u8 mode) {
-
-	/* board must be running */
-	if (!card->running)
-		return -ENODEV;
-
-	card->loopmode = mode;
-	return 0;
-}
-
-/*
- * Issue a dial command. This function builds and sends a CConnectReq.
- * 
- * 	card: the board
- * 	channel: the channel number
- * 	phone: the remote phone number (EAZ)
- *
- * Return: 0 if OK, <0 if error.
- */
-static int tpam_command_dial(tpam_card *card, u32 channel, u8 *phone) {
-	struct sk_buff *skb;
-	isdn_ctrl ctrl;
-
-	pr_debug("TurboPAM(tpam_command_dial): card=%d, channel=%lu, phone=%s\n",
-		card->id, (unsigned long)channel, phone);
-
-	/* board must be running */
-	if (!card->running)
-		return -ENODEV;
-
-	/* initialize channel parameters */
-	card->channels[channel].realhdlc = card->channels[channel].hdlc;
-	card->channels[channel].hdlcshift = 0;
-	card->channels[channel].readytoreceive = 0;
-
-	/* build and send a CConnectReq */
-	skb = build_CConnectReq(card->channels[channel].ncoid, phone, 
-				card->channels[channel].realhdlc);
-	if (!skb)
-		return -ENOMEM;
-	tpam_enqueue(card, skb);
-
-	/* making a connection in modem mode is slow and causes the ISDN
-	 * link layer to hangup the connection before even it gets a chance
-	 * to establish... All we can do is simulate a successful connection
-	 * for now, and send a DHUP later if the connection fails */
-	if (!card->channels[channel].realhdlc) {
-		ctrl.driver = card->id;
-		ctrl.command = ISDN_STAT_DCONN;
-		ctrl.arg = channel;
-		tpam_statcallb(card, ctrl);
-	}
-	
-	return 0;
-}
-
-/*
- * Set the level2 protocol (modem or HDLC).
- *
- * 	card: the board
- * 	channel: the channel number
- * 	proto: the level2 protocol (one of ISDN_PROTO_L2*)
- *
- * Return: 0 if OK, <0 if error.
- */
-static int tpam_command_setl2(tpam_card *card, u32 channel, u8 proto) {
-
-	pr_debug("TurboPAM(tpam_command_setl2): card=%d, channel=%lu, proto=%d\n",
-		card->id, (unsigned long)channel, proto);
-
-	/* board must be running */
-	if (!card->running)
-		return -ENODEV;
-
-	/* set the hdlc/modem mode */
-	switch (proto) {
-		case ISDN_PROTO_L2_HDLC:
-			card->channels[channel].hdlc = 1;
-			break;
-		case ISDN_PROTO_L2_MODEM:
-			card->channels[channel].hdlc = 0;
-			break;
-		default:
-			return -EINVAL;
-	}
-	return 0;
-}
-
-/*
- * Accept a D-channel connection (incoming connection). This function
- * builds and sends a CConnectRsp message and signals DCONN to the ISDN
- * link level.
- *
- * 	card: the board
- * 	channel: the channel number
- *
- * Return: 0 if OK, <0 if error.
- */
-static int tpam_command_acceptd(tpam_card *card, u32 channel) {
-	isdn_ctrl ctrl;
-	struct sk_buff *skb;
-
-	pr_debug("TurboPAM(tpam_command_acceptd): card=%d, channel=%lu\n",
-		card->id, (unsigned long)channel);
-
-	/* board must be running */
-	if (!card->running)
-		return -ENODEV;
-
-	/* build and send a CConnectRsp */
-	skb = build_CConnectRsp(card->channels[channel].ncoid);
-	if (!skb)
-		return -ENOMEM;
-	tpam_enqueue(card, skb);
-
-	/* issue DCONN to the ISDN link level */
-	ctrl.driver = card->id;
-	ctrl.command = ISDN_STAT_DCONN;
-	ctrl.arg = channel;
-	tpam_statcallb(card, ctrl);
-	return 0;
-}
-
-/*
- * Accepts a B-channel connection. This is not used by the driver, 
- * since the TurboPAM is an active card hiding its B-channels from
- * us. We just signal BCONN to the ISDN link layer.
- *
- * 	card: the board
- * 	channel: the channel number
- *
- * Return: 0 if OK, <0 if error.
- */
-static int tpam_command_acceptb(tpam_card *card, u32 channel) {
-	isdn_ctrl ctrl;
-
-	pr_debug("TurboPAM(tpam_command_acceptb): card=%d, channel=%lu\n",
-		card->id, (unsigned long)channel);
-
-	/* board must be running */
-	if (!card->running)
-		return -ENODEV;
-
-	/* issue BCONN to the ISDN link level */
-	ctrl.driver = card->id;
-	ctrl.command = ISDN_STAT_BCONN;
-	ctrl.arg = channel;
-	ctrl.parm.num[0] = '\0';
-	tpam_statcallb(card, ctrl);
-	return 0;
-}
-
-/*
- * Hang up a connection. This function builds and sends a CDisconnectReq.
- *
- * 	card: the board
- * 	channel: the channel number.
- *
- * Return: 0 if OK, <0 if error.
- */
-static int tpam_command_hangup(tpam_card *card, u32 channel) {
-	struct sk_buff *skb;
-
-	pr_debug("TurboPAM(tpam_command_hangup): card=%d, channel=%lu\n",
-		card->id, (unsigned long)channel);
-
-	/* board must be running */
-	if (!card->running)
-		return -ENODEV;
-
-	/* build and send a CDisconnectReq */
-	skb = build_CDisconnectReq(card->channels[channel].ncoid);
-	if (!skb)
-		return -ENOMEM;
-	tpam_enqueue(card, skb);
-	return 0;
-}
-
-/*
- * Proceed with an incoming connection. This function builds and sends a 
- * CConnectRsp.
- *
- * 	card: the board
- * 	channel: the channel number.
- *
- * Return: 0 if OK, <0 if error.
- */
-static int tpam_command_proceed(tpam_card *card, u32 channel) {
-	struct sk_buff *skb;
-
-	pr_debug("TurboPAM(tpam_command_proceed): card=%d, channel=%lu\n",
-		card->id, (unsigned long)channel);
-
-	/* board must be running */
-	if (!card->running)
-		return -ENODEV;
-
-	/* build and send a CConnectRsp */
-	skb = build_CConnectRsp(card->channels[channel].ncoid);
-	if (!skb)
-		return -ENOMEM;
-	tpam_enqueue(card, skb);
-	return 0;
-}
-
-/*
- * Send data through the board. This function encodes the data depending
- * on the connection type (modem or HDLC), then builds and sends a U3DataReq.
- *
- * 	driverId: the driver id (really meaning here the board)
- * 	channel: the channel number
- * 	ack: data needs to be acknowledged upon send
- * 	skb: sk_buff containing the data
- *
- * Return: size of data send if OK, <0 if error.
- */
-int tpam_writebuf_skb(int driverId, int channel, int ack, struct sk_buff *skb) {
-	tpam_card *card;
-	int orig_size = skb->len;
-	void *finaldata;
-	u32 finallen;
-
-	pr_debug("TurboPAM(tpam_writebuf_skb): "
-		"card=%d, channel=%ld, ack=%d, data size=%d\n", 
-		driverId, (unsigned long)channel, ack, skb->len);
-
-	/* find the board based on its driver ID */
-	if (!(card = tpam_findcard(driverId))) {
-		printk(KERN_ERR "TurboPAM(tpam_writebuf_skb): "
-		       "invalid driverId %d\n", driverId);	
-		return -ENODEV;
-	}
-
-	/* board must be running */
-	if (!card->running)
-		return -ENODEV;
-
-	/* allocate some temporary memory */
-	if (!(finaldata = (void *)__get_free_page(GFP_ATOMIC))) {
-		printk(KERN_ERR "TurboPAM(tpam_writebuf_skb): "
-		       "get_free_page failed\n");
-		return -ENOMEM;
-	}
-
-	/* encode the data */
-	if (!card->channels[channel].realhdlc) {
-		/* modem mode */
-		hdlc_encode_modem(skb->data, skb->len, finaldata, &finallen);
-	}
-	else {
-		/* HDLC mode */
-		void *tempdata;
-		u32 templen;
-
-		if (!(tempdata = (void *)__get_free_page(GFP_ATOMIC))) {
-			printk(KERN_ERR "TurboPAM(tpam_writebuf_skb): "
-			       "get_free_page failed\n");
-			free_page((unsigned long)finaldata);
-			return -ENOMEM;
-		}
-		hdlc_no_accm_encode(skb->data, skb->len, tempdata, &templen);
-		finallen = tpam_hdlc_encode(tempdata, finaldata, 
-				       &card->channels[channel].hdlcshift, 
-				       templen);
-		free_page((unsigned long)tempdata);
-	}
-
-	/* free the old sk_buff */
-	kfree_skb(skb);
-
-	/* build and send a U3DataReq */
-	skb = build_U3DataReq(card->channels[channel].ncoid, finaldata, 
-			      finallen, ack, orig_size);
-	if (!skb) {
-		free_page((unsigned long)finaldata);
-		return -ENOMEM;
-	}
-	tpam_enqueue_data(&card->channels[channel], skb);
-
-	/* free the temporary memory */
-	free_page((unsigned long)finaldata);
-	return orig_size;
-}
-
-/*
- * Treat a received ACreateNCOCnf message.
- *
- * 	card: the board
- * 	skb: the received message
- */
-void tpam_recv_ACreateNCOCnf(tpam_card *card, struct sk_buff *skb) {
-	u32 ncoid;
-	u8 status;
-	u32 channel;
-
-	pr_debug("TurboPAM(tpam_recv_ACreateNCOCnf): card=%d\n", card->id);
-
-	/* parse the message contents */
-	if (parse_ACreateNCOCnf(skb, &status, &ncoid))
-		return;
-
-	/* if the card is alreay running, it means that this message
-	 * arrives too late... */
-	if (card->running) {
-		printk(KERN_ERR "TurboPAM(tpam_recv_ACreateNCOCnf): "
-		       "ACreateNCOCnf received too late, status=%d\n", status);
-		return;
-	}
-
-	/* the NCO creation failed, the corresponding channel will
-	 * be unused */
-	if (status) {
-		printk(KERN_ERR "TurboPAM(tpam_recv_ACreateNCOCnf): "
-		       "ACreateNCO failed, status=%d\n", status);
-		card->channels_tested++;
-		return;
-	}
-
-	/* find the first free channel and assign the nco ID to it */
-	if ((channel = tpam_findchannel(card, TPAM_NCOID_INVALID)) == TPAM_CHANNEL_INVALID) {
-		printk(KERN_ERR "TurboPAM(tpam_recv_ACreateNCOCnf): "
-		       "All channels are assigned\n");
-		return;
-	}
-	card->channels[channel].ncoid = ncoid;
-	card->channels_tested++;
-	card->channels_used++;
-}
-
-/*
- * Treat a received ADestroyNCOCnf message. Not used by the driver.
- *
- * 	card: the board
- * 	skb: the received message
- */
-void tpam_recv_ADestroyNCOCnf(tpam_card *card, struct sk_buff *skb) {
-	u32 ncoid;
-	u8 status;
-	u32 channel;
-
-	pr_debug("TurboPAM(tpam_recv_ADestroyNCOCnf): card=%d\n", card->id);
-
-	/* parse the message contents */
-	if (parse_ADestroyNCOCnf(skb, &status, &ncoid))
-		return;
-	
-	if (status) {
-		printk(KERN_ERR "TurboPAM(tpam_recv_ADestroyNCOCnf): "
-		       "ADestroyNCO failed, status=%d\n", status);
-		return;
-	}
-
-	/* clears the channel's nco ID */
-	if ((channel = tpam_findchannel(card, ncoid)) == TPAM_CHANNEL_INVALID) {
-		printk(KERN_ERR "TurboPAM(tpam_recv_ADestroyNCOCnf): "
-		       "ncoid invalid %lu\n", (unsigned long)ncoid);
-		return;
-	}
-
-	card->channels[channel].ncoid = TPAM_NCOID_INVALID;
-}
-
-/*
- * Treat a received CConnectCnf message.
- *
- * 	card: the board
- * 	skb: the received message
- */
-void tpam_recv_CConnectCnf(tpam_card *card, struct sk_buff *skb) {
-	u32 ncoid;
-	u32 channel;
-	isdn_ctrl ctrl;
-
-	pr_debug("TurboPAM(tpam_recv_CConnectCnf): card=%d\n", card->id);
-
-	/* parse the message contents */
-	if (parse_CConnectCnf(skb, &ncoid))
-		return;
-
-	/* find the channel by its nco ID */
-	if ((channel = tpam_findchannel(card, ncoid)) == TPAM_CHANNEL_INVALID) {
-		printk(KERN_ERR "TurboPAM(tpam_recv_CConnectCnf): "
-		       "ncoid invalid %lu\n", (unsigned long)ncoid);
-		return;
-	}
-
-	/* issue a DCONN command to the ISDN link layer if we are in HDLC mode.
-	 * In modem mode, we alreay did it - the ISDN timer kludge */
-	if (card->channels[channel].realhdlc) {
-		ctrl.driver = card->id;
-		ctrl.command = ISDN_STAT_DCONN;
-		ctrl.arg = channel;
-		(* card->interface.statcallb)(&ctrl);
-	}
-}
-
-/*
- * Treat a received CConnectInd message. This function signals a ICALL
- * to the ISDN link layer.
- *
- * 	card: the board
- * 	skb: the received message
- */
-void tpam_recv_CConnectInd(tpam_card *card, struct sk_buff *skb) {
-	u32 ncoid;
-	u32 channel;
-	u8 hdlc, plan, screen;
-	u8 calling[PHONE_MAXIMUMSIZE], called[PHONE_MAXIMUMSIZE];
-	isdn_ctrl ctrl;
-	int status;
-
-	pr_debug("TurboPAM(tpam_recv_CConnectInd): card=%d\n", card->id);
-
-	/* parse the message contents */
-	if (parse_CConnectInd(skb, &ncoid, &hdlc, calling, called, &plan, &screen))
-		return;
-
-	/* find the channel by its nco ID */
-	if ((channel = tpam_findchannel(card, ncoid)) == TPAM_CHANNEL_INVALID) {
-		printk(KERN_ERR "TurboPAM(tpam_recv_CConnectInd): "
-		       "ncoid invalid %lu\n", (unsigned long)ncoid);
-		return;
-	}
-
-	/* initialize the channel parameters */
-	card->channels[channel].realhdlc = hdlc;
-	card->channels[channel].hdlcshift = 0;
-	card->channels[channel].readytoreceive = 0;
-
-	/* issue a ICALL command to the ISDN link layer */
-	ctrl.driver = card->id;
-	ctrl.command = ISDN_STAT_ICALL;
-	ctrl.arg = channel;
-	memcpy(ctrl.parm.setup.phone, calling, 32);
-	memcpy(ctrl.parm.setup.eazmsn, called, 32);
-	ctrl.parm.setup.si1 = 7;	/* data capability */
-	ctrl.parm.setup.si2 = 0;
-	ctrl.parm.setup.plan = plan;
-	ctrl.parm.setup.screen = screen;
-
-	status = (* card->interface.statcallb)(&ctrl);
-	switch (status) {
-		case 1:
-		case 4:
-			/* call accepted, link layer will send us a ACCEPTD 
-			 * command later */
-			pr_debug("TurboPAM(tpam_recv_CConnectInd): "
-				"card=%d, channel=%d, icall waiting, status=%d\n", 
-				card->id, channel, status);
-			break;
-		default:
-			/* call denied, we build and send a CDisconnectReq */
-			pr_debug("TurboPAM(tpam_recv_CConnectInd): "
-				"card=%d, channel=%d, icall denied, status=%d\n", 
-				card->id, channel, status);
-			skb = build_CDisconnectReq(ncoid);
-			if (!skb)
-				return;
-			tpam_enqueue(card, skb);
-	}
-}
-
-/*
- * Treat a received CDisconnectInd message. This function signals a DHUP and
- * a BHUP to the ISDN link layer.
- *
- * 	card: the board
- * 	skb: the received message
- */
-void tpam_recv_CDisconnectInd(tpam_card *card, struct sk_buff *skb) {
-	u32 ncoid;
-	u32 channel;
-	u32 cause;
-	isdn_ctrl ctrl;
-
-	pr_debug("TurboPAM(tpam_recv_CDisconnectInd): card=%d\n", card->id);
-
-	/* parse the message contents */
-	if (parse_CDisconnectInd(skb, &ncoid, &cause))
-		return;
-
-	/* find the channel by its nco ID */
-	if ((channel = tpam_findchannel(card, ncoid)) == TPAM_CHANNEL_INVALID) {
-		printk(KERN_ERR "TurboPAM(tpam_recv_CDisconnectInd): "
-		       "ncoid invalid %lu\n", (unsigned long)ncoid);
-		return;
-	}
-
-	/* build and send a CDisconnectRsp */
-	skb = build_CDisconnectRsp(ncoid);
-	if (!skb)
-		return;
-	tpam_enqueue(card, skb);
-
-	/* issue a DHUP to the ISDN link layer */
-	ctrl.driver = card->id;
-	ctrl.command = ISDN_STAT_DHUP;
-	ctrl.arg = channel;
-	(* card->interface.statcallb)(&ctrl);
-
-	/* issue a BHUP to the ISDN link layer */
-	ctrl.driver = card->id;
-	ctrl.command = ISDN_STAT_BHUP;
-	ctrl.arg = channel;
-	(* card->interface.statcallb)(&ctrl);
-}
-
-/*
- * Treat a received CDisconnectCnf message. This function signals a DHUP and
- * a BHUP to the ISDN link layer.
- *
- * 	card: the board
- * 	skb: the received message
- */
-void tpam_recv_CDisconnectCnf(tpam_card *card, struct sk_buff *skb) {
-	u32 ncoid;
-	u32 channel;
-	u32 cause;
-	isdn_ctrl ctrl;
-
-	pr_debug("TurboPAM(tpam_recv_CDisconnectCnf): card=%d\n", card->id);
-
-	/* parse the message contents */
-	if (parse_CDisconnectCnf(skb, &ncoid, &cause))
-		return;
-
-	/* find the channel by its nco ID */
-	if ((channel = tpam_findchannel(card, ncoid)) == TPAM_CHANNEL_INVALID) {
-		printk(KERN_ERR "TurboPAM(tpam_recv_CDisconnectCnf): "
-		       "ncoid invalid %lu\n", (unsigned long)ncoid);
-		return;
-	}
-
-	/* issue a DHUP to the ISDN link layer */
-	ctrl.driver = card->id;
-	ctrl.command = ISDN_STAT_DHUP;
-	ctrl.arg = channel;
-	(* card->interface.statcallb)(&ctrl);
-
-	/* issue a BHUP to the ISDN link layer */
-	ctrl.driver = card->id;
-	ctrl.command = ISDN_STAT_BHUP;
-	ctrl.arg = channel;
-	(* card->interface.statcallb)(&ctrl);
-}
-
-/*
- * Treat a received U3DataInd message. This function decodes the data
- * depending on the connection type (modem or HDLC) and passes it to the
- * ISDN link layer by using rcvcallb_skb.
- *
- * 	card: the board
- * 	skb: the received message + data
- */
-void tpam_recv_U3DataInd(tpam_card *card, struct sk_buff *skb) {
-	u32 ncoid;
-	u32 channel;
-	u8 *data;
-	u16 len;
-	struct sk_buff *result;
-
-	pr_debug("TurboPAM(tpam_recv_U3DataInd): card=%d, datalen=%d\n",
-		card->id, skb->len);
-
-	/* parse the message contents */
-	if (parse_U3DataInd(skb, &ncoid, &data, &len))
-		return;
-
-	/* find the channel by its nco ID */
-	if ((channel = tpam_findchannel(card, ncoid)) == TPAM_CHANNEL_INVALID) {
-		printk(KERN_ERR "TurboPAM(tpam_recv_U3DataInd): "
-		       "ncoid invalid %lu\n", (unsigned long)ncoid);
-		return;
-	}
-
-	/* decode the data */
-	if (card->channels[ncoid].realhdlc) {
-		/* HDLC mode */
-		u8 *tempdata;
-		u32 templen;
-
-		if (!(tempdata = (void *)__get_free_page(GFP_ATOMIC))) {
-			printk(KERN_ERR "TurboPAM(tpam_recv_U3DataInd): "
-			       "get_free_page failed\n");
-			return;
-		}
-		templen = tpam_hdlc_decode(data, tempdata, len);
-		templen = hdlc_no_accm_decode(tempdata, templen);
-		if (!(result = alloc_skb(templen, GFP_ATOMIC))) {
-			printk(KERN_ERR "TurboPAM(tpam_recv_U3DataInd): "
-			       "alloc_skb failed\n");
-			free_page((unsigned long)tempdata);
-			return;
-		}
-		memcpy(skb_put(result, templen), tempdata, templen);
-		free_page((unsigned long)tempdata);
-	}
-	else {
-		/* modem mode */
-		if (!(result = alloc_skb(len, GFP_ATOMIC))) {
-			printk(KERN_ERR "TurboPAM(tpam_recv_U3DataInd): "
-			       "alloc_skb failed\n");
-			return;
-		}
-		memcpy(skb_put(result, len), data, len);
-	}
-
-	/* In loop mode, resend the data immediately */
-	if (card->loopmode) {
-		struct sk_buff *loopskb;
-
-		if (!(loopskb = alloc_skb(skb->len, GFP_ATOMIC))) {
-			printk(KERN_ERR "TurboPAM(tpam_recv_U3DataInd): "
-			       "alloc_skb failed\n");
-			kfree_skb(result);
-			return;
-		}
-		memcpy(skb_put(loopskb, result->len), result->data, 
-		       result->len);
-		if (tpam_writebuf_skb(card->id, channel, 0, loopskb) < 0)
-			kfree_skb(loopskb);
-	}
-
-	/* pass the data to the ISDN link layer */
-	(* card->interface.rcvcallb_skb)(card->id, channel, result);
-}
-
-/*
- * Treat a received U3ReadyToReceiveInd message. This function sets the
- * channel ready flag and triggers the send of data if the channel becomed
- * ready.
- *
- * 	card: the board
- * 	skb: the received message + data
- */
-void tpam_recv_U3ReadyToReceiveInd(tpam_card *card, struct sk_buff *skb) {
-	u32 ncoid;
-	u32 channel;
-	u8 ready;
-
-	pr_debug("TurboPAM(tpam_recv_U3ReadyToReceiveInd): card=%d\n", card->id);
-
-	/* parse the message contents */
-	if (parse_U3ReadyToReceiveInd(skb, &ncoid, &ready))
-		return;
-
-	/* find the channel by its nco ID */
-	if ((channel = tpam_findchannel(card, ncoid)) == TPAM_CHANNEL_INVALID) {
-		printk(KERN_ERR "TurboPAM(tpam_recv_U3ReadyToReceiveInd): "
-		       "ncoid invalid %lu\n", (unsigned long)ncoid);
-		return;
-	}
-
-	/* set the readytoreceive flag */
-	card->channels[channel].readytoreceive = ready;
-
-	/* if the channel just becomed ready, trigger the send of queued data */
-	if (ready)
-		tpam_enqueue_data(&card->channels[channel], NULL);
-}
-
-/*
- * Runs the delayed statcallb when its timer expires.
- *
- * 	parm: pointer to the tpam_statcallb_data statcallb argument.
- */
-static void tpam_statcallb_run(unsigned long parm) {
-	tpam_statcallb_data *ds = (tpam_statcallb_data *)parm;
-
-	pr_debug("TurboPAM(tpam_statcallb_run)\n");
-
-	(* ds->card->interface.statcallb)(&ds->ctrl);
-
-	kfree(ds->timer);
-	kfree(ds);
-}
-
-/*
- * Queues a statcallb call for delayed invocation.
- *
- * 	card: the board
- * 	ctrl: the statcallb argument
- */
-static void tpam_statcallb(tpam_card *card, isdn_ctrl ctrl) {
-	struct timer_list *timer;
-	tpam_statcallb_data *ds;
-
-	pr_debug("TurboPAM(tpam_statcallb): card=%d\n", card->id);
-
-	if (!(timer = (struct timer_list *) kmalloc(sizeof(struct timer_list), 
-						    GFP_ATOMIC))) {
-		printk(KERN_ERR "TurboPAM: tpam_statcallb: kmalloc failed!\n");
-		return;
-	}
-
-	if (!(ds = (tpam_statcallb_data *) kmalloc(sizeof(tpam_statcallb_data),
-						   GFP_ATOMIC))) {
-		printk(KERN_ERR "TurboPAM: tpam_statcallb: kmalloc failed!\n");
-		kfree(timer);
-		return;
-	}
-	ds->card = card;
-	ds->timer = timer;
-	memcpy(&ds->ctrl, &ctrl, sizeof(isdn_ctrl));
-
-	init_timer(timer);
-	timer->function = tpam_statcallb_run;
-	timer->data = (unsigned long)ds;
-	timer->expires = jiffies + HZ / 10;   /* 0.1 second */
-	add_timer(timer);
-}
diff -Nru a/drivers/isdn/tpam/tpam_crcpc.c b/drivers/isdn/tpam/tpam_crcpc.c
--- a/drivers/isdn/tpam/tpam_crcpc.c	2005-03-11 12:51:42 -08:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,162 +0,0 @@
-/* $Id: tpam_crcpc.c,v 1.1.2.2 2001/09/23 22:25:03 kai Exp $
- *
- * Turbo PAM ISDN driver for Linux. (Kernel Driver - CRC encoding)
- *
- * Copyright 1998-2000 AUVERTECH Télécom
- * Copyright 2001 Stelian Pop <stelian.pop@fr.alcove.com>, Alcôve
- *
- * This software may be used and distributed according to the terms
- * of the GNU General Public License, incorporated herein by reference.
- *
- * For all support questions please contact: <support@auvertech.fr>
- *
- */
-
-/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-
-Module Name:
-
-    crcpc.c
-
-Abstract:
-
-    Modem HDLC coding
-    Software HDLC coding / decoding
-
-Revision History:
-
----------------------------------------------------------------------------*/
-
-#include <linux/crc-ccitt.h>
-#include "tpam.h"
-
-#define  HDLC_CTRL_CHAR_CMPL_MASK	0x20	/* HDLC control character complement mask */
-#define  HDLC_FLAG			0x7E	/* HDLC flag */
-#define  HDLC_CTRL_ESC			0x7D	/* HDLC control escapr character */
-#define  HDLC_LIKE_FCS_INIT_VAL		0xFFFF	/* FCS initial value (0xFFFF for new equipment or 0) */
-#define  HDLC_FCS_OK			0xF0B8	/* This value is the only valid value of FCS */
-
-#define TRUE	1
-#define FALSE	0
-
-static u8 ap_t_ctrl_char_complemented[256]; /* list of characters to complement */
-
-static void ap_hdlc_like_ctrl_char_list (u32 ctrl_char) {
-	int i;
-
-	for (i = 0; i < 256; ++i)
-		ap_t_ctrl_char_complemented[i] = FALSE;
-	for (i = 0; i < 32; ++i)
-		if ((ctrl_char >> i) & 0x0001)
-			ap_t_ctrl_char_complemented [i] = TRUE;
-	ap_t_ctrl_char_complemented[HDLC_FLAG] = TRUE;
-	ap_t_ctrl_char_complemented[HDLC_CTRL_ESC] = TRUE;
-		
-}
-
-void init_CRC(void) {
-	ap_hdlc_like_ctrl_char_list(0xffffffff);
-}
-
-void hdlc_encode_modem(u8 *buffer_in, u32 lng_in,
-		       u8 *buffer_out, u32 *lng_out) {
-	u16 fcs;
-	register u8 data;
-	register u8 *p_data_out = buffer_out;
-
-	fcs = HDLC_LIKE_FCS_INIT_VAL;
-
-	/*
-	 *   Insert HDLC flag at the beginning of the frame
-	 */
-	*p_data_out++ = HDLC_FLAG;
-
-#define ESCAPE_CHAR(data_out, data) \
-	if (ap_t_ctrl_char_complemented[data]) { \
-		*data_out++ = HDLC_CTRL_ESC; \
-		*data_out++ = data ^ 0x20; \
-	} \
-	else \
-		*data_out++ = data;
-
-	while (lng_in--) {
-		data = *buffer_in++;
-
-		/*
-		 *   FCS calculation
-		 */
-		fcs = crc_ccitt_byte(fcs, data);
-
-		ESCAPE_CHAR(p_data_out, data);
-	}
-
-	/*
-	 *  Add FCS and closing flag
-	 */
-	fcs ^= 0xFFFF;  // Complement
-
-	data = (u8)(fcs & 0xff);	/* LSB */
-	ESCAPE_CHAR(p_data_out, data);
-
-	data = (u8)((fcs >> 8));	/* MSB */
-	ESCAPE_CHAR(p_data_out, data);
-#undef ESCAPE_CHAR
-
-	*p_data_out++ = HDLC_FLAG;
-
-	*lng_out = (u32)(p_data_out - buffer_out);
-}
-
-void hdlc_no_accm_encode(u8 *buffer_in, u32 lng_in, 
-			 u8 *buffer_out, u32 *lng_out) {
-	u16 fcs;
-	register u8 data;
-	register u8 *p_data_out = buffer_out;
-
-	/*
-	 *   Insert HDLC flag at the beginning of the frame
-	 */
-	fcs = HDLC_LIKE_FCS_INIT_VAL;
-
-	while (lng_in--) {
-		data = *buffer_in++;
-		/* calculate FCS */
-		fcs = crc_ccitt_byte(fcs, data);
-		*p_data_out++ = data;
-	}
-
-	/*
-	 *  Add FCS and closing flag
-	 */
-	fcs ^= 0xFFFF;  // Complement
-	data = (u8)(fcs);    
-	*p_data_out++ = data;
-
-	data =(u8)((fcs >> 8));   // revense MSB / LSB
-	*p_data_out++ = data;
- 
-	*lng_out = (u32)(p_data_out - buffer_out);
-}
-
-u32 hdlc_no_accm_decode(u8 *buffer_in, u32 lng_in) {
-	u16 fcs;
-	u32 lng = lng_in;
-	register u8 data;
-
-	/*
-	 *   Insert HDLC flag at the beginning of the frame
-	 */
-	fcs = HDLC_LIKE_FCS_INIT_VAL;
-
-	while (lng_in--) {
-		data = *buffer_in++;
-		/* calculate FCS */
-		fcs = crc_ccitt_byte(fcs, data);
-	}
-
-	if (fcs == HDLC_FCS_OK) 
-		return (lng-2);
-	else 
-		return 0;
-}
-
diff -Nru a/drivers/isdn/tpam/tpam_hdlc.c b/drivers/isdn/tpam/tpam_hdlc.c
--- a/drivers/isdn/tpam/tpam_hdlc.c	2005-03-11 12:51:42 -08:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,923 +0,0 @@
-/* $Id: tpam_hdlc.c,v 1.1.2.3 2001/11/06 20:58:30 kai Exp $
- *
- * Turbo PAM ISDN driver for Linux. (Kernel Driver - HDLC encoding)
- *
- * Copyright 1998-2000 AUVERTECH Télécom
- * Copyright 2001 Stelian Pop <stelian.pop@fr.alcove.com>, Alcôve
- *
- * This software may be used and distributed according to the terms
- * of the GNU General Public License, incorporated herein by reference.
- *
- * For all support questions please contact: <support@auvertech.fr>
- *
- */
-
-/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-
-Module Name:
-
-    hdlc.c
-
-Abstract:
-
-    stuff0 : array necessary for the bit stuffing algorithm
-    stuff1 : array necessary for the bit stuffing algorithm
-    stuff2 : array necessary for the bit stuffing algorithm
-    stuff3 : array necessary for the bit stuffing algorithm
-    stuff4 : array necessary for the bit stuffing algorithm
-    stuff5 : array necessary for the bit stuffing algorithm
-    stuffs[] : array conaining the previous 6 arrays
-    destuff0 : array necessary for the bit destuffing algorithm
-    destuff1 : array necessary for the bit destuffing algorithm
-    destuff2 : array necessary for the bit destuffing algorithm
-    destuff3 : array necessary for the bit destuffing algorithm
-    destuff4 : array necessary for the bit destuffing algorithm
-    destuff5 : array necessary for the bit destuffing algorithm
-    destuffs[] : array conaining the previous 6 arrays
-
-    tpam_hdlc_encode : bit stuffing of a byte array, with the addition 
-                  of a start and end flag, using the bit shift given in 
-		  parameter (which is updated at the end of encoding).
-    tpam_hdlc_decode : bit de-stuffing of a byte array with detection of 
-                  possible ABORTs.
-
-Revision History:
-
----------------------------------------------------------------------------*/
-
-/* The arrays are used as follows:
-
-  For the bit stuffing :
-	
-  stuff0 = used if the previous byte ended with '0'
-  stuff1 = used if the previous byte ended with '10'
-  stuff2 = used if the previous byte ended with '110'
-  stuff3 = used if the previous byte ended with '1110'
-  stuff4 = used if the previous byte ended with '11110'
-  stuff5 = used if the previous byte ended with '111110'
-  
-  those arrays are indexed by the byte to stuff.
-  
-  the data of those arrays are of the form (in binary):
-  "bbbbaaaa cccccccc"
-  with "cccccccc" : byte stuffed
-       "aaaa" : "0000" --> no insertion of '0'
-	            "0100" --> 1 '0' inserted, carry = '0'
-                "0101" --> 1 '0' inserted, carry = '1'
-                "1000" --> 2 '0' inserted, carry = '00'
-                "1001" --> 2 '0' inserted, carry = '01'
-                "1010" --> 2 '0' inserted, carry = '10'
-                "1011" --> 2 '0' inserted, carry = '11'
-       "bbbb" : count of '1' at the end of "cccccccc"
-
-
-  
-  For the bit de-stuffing :
-
-  destuff0 = used if the previous byte ended with '0'
-  destuff1 = used if the previous byte ended with '10'
-  destuff2 = used if the previous byte ended with '110'
-  destuff3 = used if the previous byte ended with '1110'
-  destuff4 = used if the previous byte ended with '11110'
-  destuff5 = used if the previous byte ended with '111110'
-
-  those arrays are indexed by the byte to de-stuff.
-
-  the data of those arrays are of the form (in binary):
-  "dbbbaaaa cccccccc"
-  with "cccccccc" : byte destuffed
-       "aaaa" : count of '1' at the end of the byte non destuffed
-       "bbb" : count of bits to use in the destuffed byte (8 less the count
-               of '0' deleted) less 1 (can be only 7, 6 or 5)
-	   "d" : '1' if the byte non destuffed has more than 5 consecutive '1' 
-	         (flag or abort)
-*/
-
-#include <linux/types.h>
-#include "tpam.h"
-
-typedef u8	BYTE;
-typedef u16	WORD;
-typedef u32	DWORD;
-typedef u8	BOOL;
-
-#define	TRUE			1
-#define FALSE			0
-
-static WORD stuff0[] =
-{
-	0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 
-	0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F, 
-	0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 
-	0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x041F, 
-	0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 
-	0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x002F, 
-	0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 
-	0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x043E, 0x045F, 
-	0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 
-	0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F, 
-	0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 
-	0x0058, 0x0059, 0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x149F, 
-	0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 
-	0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F, 
-	0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 
-	0x0078, 0x0079, 0x007A, 0x007B, 0x047C, 0x047D, 0x14BE, 0x24DF, 
-	0x1080, 0x1081, 0x1082, 0x1083, 0x1084, 0x1085, 0x1086, 0x1087, 
-	0x1088, 0x1089, 0x108A, 0x108B, 0x108C, 0x108D, 0x108E, 0x108F, 
-	0x1090, 0x1091, 0x1092, 0x1093, 0x1094, 0x1095, 0x1096, 0x1097, 
-	0x1098, 0x1099, 0x109A, 0x109B, 0x109C, 0x109D, 0x109E, 0x051F, 
-	0x10A0, 0x10A1, 0x10A2, 0x10A3, 0x10A4, 0x10A5, 0x10A6, 0x10A7, 
-	0x10A8, 0x10A9, 0x10AA, 0x10AB, 0x10AC, 0x10AD, 0x10AE, 0x10AF, 
-	0x10B0, 0x10B1, 0x10B2, 0x10B3, 0x10B4, 0x10B5, 0x10B6, 0x10B7, 
-	0x10B8, 0x10B9, 0x10BA, 0x10BB, 0x10BC, 0x10BD, 0x053E, 0x055F, 
-	0x20C0, 0x20C1, 0x20C2, 0x20C3, 0x20C4, 0x20C5, 0x20C6, 0x20C7, 
-	0x20C8, 0x20C9, 0x20CA, 0x20CB, 0x20CC, 0x20CD, 0x20CE, 0x20CF, 
-	0x20D0, 0x20D1, 0x20D2, 0x20D3, 0x20D4, 0x20D5, 0x20D6, 0x20D7, 
-	0x20D8, 0x20D9, 0x20DA, 0x20DB, 0x20DC, 0x20DD, 0x20DE, 0x159F, 
-	0x30E0, 0x30E1, 0x30E2, 0x30E3, 0x30E4, 0x30E5, 0x30E6, 0x30E7, 
-	0x30E8, 0x30E9, 0x30EA, 0x30EB, 0x30EC, 0x30ED, 0x30EE, 0x30EF, 
-	0x40F0, 0x40F1, 0x40F2, 0x40F3, 0x40F4, 0x40F5, 0x40F6, 0x40F7, 
-	0x50F8, 0x50F9, 0x50FA, 0x50FB, 0x057C, 0x057D, 0x15BE, 0x25DF, 
-};
-
-
-static WORD stuff1[] =
-{
-	0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 
-	0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x040F, 
-	0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 
-	0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x042F, 
-	0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 
-	0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x044F, 
-	0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 
-	0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x043E, 0x046F, 
-	0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 
-	0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x148F, 
-	0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 
-	0x0058, 0x0059, 0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x14AF, 
-	0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 
-	0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x24CF, 
-	0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 
-	0x0078, 0x0079, 0x007A, 0x007B, 0x047C, 0x047D, 0x14BE, 0x34EF, 
-	0x1080, 0x1081, 0x1082, 0x1083, 0x1084, 0x1085, 0x1086, 0x1087, 
-	0x1088, 0x1089, 0x108A, 0x108B, 0x108C, 0x108D, 0x108E, 0x050F, 
-	0x1090, 0x1091, 0x1092, 0x1093, 0x1094, 0x1095, 0x1096, 0x1097, 
-	0x1098, 0x1099, 0x109A, 0x109B, 0x109C, 0x109D, 0x109E, 0x052F, 
-	0x10A0, 0x10A1, 0x10A2, 0x10A3, 0x10A4, 0x10A5, 0x10A6, 0x10A7, 
-	0x10A8, 0x10A9, 0x10AA, 0x10AB, 0x10AC, 0x10AD, 0x10AE, 0x054F, 
-	0x10B0, 0x10B1, 0x10B2, 0x10B3, 0x10B4, 0x10B5, 0x10B6, 0x10B7, 
-	0x10B8, 0x10B9, 0x10BA, 0x10BB, 0x10BC, 0x10BD, 0x053E, 0x056F, 
-	0x20C0, 0x20C1, 0x20C2, 0x20C3, 0x20C4, 0x20C5, 0x20C6, 0x20C7, 
-	0x20C8, 0x20C9, 0x20CA, 0x20CB, 0x20CC, 0x20CD, 0x20CE, 0x158F, 
-	0x20D0, 0x20D1, 0x20D2, 0x20D3, 0x20D4, 0x20D5, 0x20D6, 0x20D7, 
-	0x20D8, 0x20D9, 0x20DA, 0x20DB, 0x20DC, 0x20DD, 0x20DE, 0x15AF, 
-	0x30E0, 0x30E1, 0x30E2, 0x30E3, 0x30E4, 0x30E5, 0x30E6, 0x30E7, 
-	0x30E8, 0x30E9, 0x30EA, 0x30EB, 0x30EC, 0x30ED, 0x30EE, 0x25CF, 
-	0x40F0, 0x40F1, 0x40F2, 0x40F3, 0x40F4, 0x40F5, 0x40F6, 0x40F7, 
-	0x50F8, 0x50F9, 0x50FA, 0x50FB, 0x057C, 0x057D, 0x15BE, 0x35EF, 
-};
-
-
-static WORD stuff2[] =
-{
-	0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0407, 
-	0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x0417, 
-	0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0427, 
-	0x0018, 0x0019, 0x001A, 0x001B, 0x001C, 0x001D, 0x001E, 0x0437, 
-	0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0447, 
-	0x0028, 0x0029, 0x002A, 0x002B, 0x002C, 0x002D, 0x002E, 0x0457, 
-	0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0467, 
-	0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x043E, 0x0477, 
-	0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x1487, 
-	0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x1497, 
-	0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x14A7, 
-	0x0058, 0x0059, 0x005A, 0x005B, 0x005C, 0x005D, 0x005E, 0x14B7, 
-	0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x24C7, 
-	0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x24D7, 
-	0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x34E7, 
-	0x0078, 0x0079, 0x007A, 0x007B, 0x047C, 0x047D, 0x14BE, 0x44F7, 
-	0x1080, 0x1081, 0x1082, 0x1083, 0x1084, 0x1085, 0x1086, 0x0507, 
-	0x1088, 0x1089, 0x108A, 0x108B, 0x108C, 0x108D, 0x108E, 0x0517, 
-	0x1090, 0x1091, 0x1092, 0x1093, 0x1094, 0x1095, 0x1096, 0x0527, 
-	0x1098, 0x1099, 0x109A, 0x109B, 0x109C, 0x109D, 0x109E, 0x0537, 
-	0x10A0, 0x10A1, 0x10A2, 0x10A3, 0x10A4, 0x10A5, 0x10A6, 0x0547, 
-	0x10A8, 0x10A9, 0x10AA, 0x10AB, 0x10AC, 0x10AD, 0x10AE, 0x0557, 
-	0x10B0, 0x10B1, 0x10B2, 0x10B3, 0x10B4, 0x10B5, 0x10B6, 0x0567, 
-	0x10B8, 0x10B9, 0x10BA, 0x10BB, 0x10BC, 0x10BD, 0x053E, 0x0577, 
-	0x20C0, 0x20C1, 0x20C2, 0x20C3, 0x20C4, 0x20C5, 0x20C6, 0x1587, 
-	0x20C8, 0x20C9, 0x20CA, 0x20CB, 0x20CC, 0x20CD, 0x20CE, 0x1597, 
-	0x20D0, 0x20D1, 0x20D2, 0x20D3, 0x20D4, 0x20D5, 0x20D6, 0x15A7, 
-	0x20D8, 0x20D9, 0x20DA, 0x20DB, 0x20DC, 0x20DD, 0x20DE, 0x15B7, 
-	0x30E0, 0x30E1, 0x30E2, 0x30E3, 0x30E4, 0x30E5, 0x30E6, 0x25C7, 
-	0x30E8, 0x30E9, 0x30EA, 0x30EB, 0x30EC, 0x30ED, 0x30EE, 0x25D7, 
-	0x40F0, 0x40F1, 0x40F2, 0x40F3, 0x40F4, 0x40F5, 0x40F6, 0x35E7, 
-	0x50F8, 0x50F9, 0x50FA, 0x50FB, 0x057C, 0x057D, 0x15BE, 0x45F7, 
-};
-
-
-static WORD stuff3[] =
-{
-	0x0000, 0x0001, 0x0002, 0x0403, 0x0004, 0x0005, 0x0006, 0x040B, 
-	0x0008, 0x0009, 0x000A, 0x0413, 0x000C, 0x000D, 0x000E, 0x041B, 
-	0x0010, 0x0011, 0x0012, 0x0423, 0x0014, 0x0015, 0x0016, 0x042B, 
-	0x0018, 0x0019, 0x001A, 0x0433, 0x001C, 0x001D, 0x001E, 0x043B, 
-	0x0020, 0x0021, 0x0022, 0x0443, 0x0024, 0x0025, 0x0026, 0x044B, 
-	0x0028, 0x0029, 0x002A, 0x0453, 0x002C, 0x002D, 0x002E, 0x045B, 
-	0x0030, 0x0031, 0x0032, 0x0463, 0x0034, 0x0035, 0x0036, 0x046B, 
-	0x0038, 0x0039, 0x003A, 0x0473, 0x003C, 0x003D, 0x043E, 0x047B, 
-	0x0040, 0x0041, 0x0042, 0x1483, 0x0044, 0x0045, 0x0046, 0x148B, 
-	0x0048, 0x0049, 0x004A, 0x1493, 0x004C, 0x004D, 0x004E, 0x149B, 
-	0x0050, 0x0051, 0x0052, 0x14A3, 0x0054, 0x0055, 0x0056, 0x14AB, 
-	0x0058, 0x0059, 0x005A, 0x14B3, 0x005C, 0x005D, 0x005E, 0x14BB, 
-	0x0060, 0x0061, 0x0062, 0x24C3, 0x0064, 0x0065, 0x0066, 0x24CB, 
-	0x0068, 0x0069, 0x006A, 0x24D3, 0x006C, 0x006D, 0x006E, 0x24DB, 
-	0x0070, 0x0071, 0x0072, 0x34E3, 0x0074, 0x0075, 0x0076, 0x34EB, 
-	0x0078, 0x0079, 0x007A, 0x44F3, 0x047C, 0x047D, 0x14BE, 0x54FB, 
-	0x1080, 0x1081, 0x1082, 0x0503, 0x1084, 0x1085, 0x1086, 0x050B, 
-	0x1088, 0x1089, 0x108A, 0x0513, 0x108C, 0x108D, 0x108E, 0x051B, 
-	0x1090, 0x1091, 0x1092, 0x0523, 0x1094, 0x1095, 0x1096, 0x052B, 
-	0x1098, 0x1099, 0x109A, 0x0533, 0x109C, 0x109D, 0x109E, 0x053B, 
-	0x10A0, 0x10A1, 0x10A2, 0x0543, 0x10A4, 0x10A5, 0x10A6, 0x054B, 
-	0x10A8, 0x10A9, 0x10AA, 0x0553, 0x10AC, 0x10AD, 0x10AE, 0x055B, 
-	0x10B0, 0x10B1, 0x10B2, 0x0563, 0x10B4, 0x10B5, 0x10B6, 0x056B, 
-	0x10B8, 0x10B9, 0x10BA, 0x0573, 0x10BC, 0x10BD, 0x053E, 0x057B, 
-	0x20C0, 0x20C1, 0x20C2, 0x1583, 0x20C4, 0x20C5, 0x20C6, 0x158B, 
-	0x20C8, 0x20C9, 0x20CA, 0x1593, 0x20CC, 0x20CD, 0x20CE, 0x159B, 
-	0x20D0, 0x20D1, 0x20D2, 0x15A3, 0x20D4, 0x20D5, 0x20D6, 0x15AB, 
-	0x20D8, 0x20D9, 0x20DA, 0x15B3, 0x20DC, 0x20DD, 0x20DE, 0x15BB, 
-	0x30E0, 0x30E1, 0x30E2, 0x25C3, 0x30E4, 0x30E5, 0x30E6, 0x25CB, 
-	0x30E8, 0x30E9, 0x30EA, 0x25D3, 0x30EC, 0x30ED, 0x30EE, 0x25DB, 
-	0x40F0, 0x40F1, 0x40F2, 0x35E3, 0x40F4, 0x40F5, 0x40F6, 0x35EB, 
-	0x50F8, 0x50F9, 0x50FA, 0x45F3, 0x057C, 0x057D, 0x15BE, 0x55FB, 
-};
-
-
-static WORD stuff4[] =
-{
-	0x0000, 0x0401, 0x0002, 0x0405, 0x0004, 0x0409, 0x0006, 0x040D, 
-	0x0008, 0x0411, 0x000A, 0x0415, 0x000C, 0x0419, 0x000E, 0x041D, 
-	0x0010, 0x0421, 0x0012, 0x0425, 0x0014, 0x0429, 0x0016, 0x042D, 
-	0x0018, 0x0431, 0x001A, 0x0435, 0x001C, 0x0439, 0x001E, 0x043D, 
-	0x0020, 0x0441, 0x0022, 0x0445, 0x0024, 0x0449, 0x0026, 0x044D, 
-	0x0028, 0x0451, 0x002A, 0x0455, 0x002C, 0x0459, 0x002E, 0x045D, 
-	0x0030, 0x0461, 0x0032, 0x0465, 0x0034, 0x0469, 0x0036, 0x046D, 
-	0x0038, 0x0471, 0x003A, 0x0475, 0x003C, 0x0479, 0x043E, 0x087D, 
-	0x0040, 0x1481, 0x0042, 0x1485, 0x0044, 0x1489, 0x0046, 0x148D, 
-	0x0048, 0x1491, 0x004A, 0x1495, 0x004C, 0x1499, 0x004E, 0x149D, 
-	0x0050, 0x14A1, 0x0052, 0x14A5, 0x0054, 0x14A9, 0x0056, 0x14AD, 
-	0x0058, 0x14B1, 0x005A, 0x14B5, 0x005C, 0x14B9, 0x005E, 0x14BD, 
-	0x0060, 0x24C1, 0x0062, 0x24C5, 0x0064, 0x24C9, 0x0066, 0x24CD, 
-	0x0068, 0x24D1, 0x006A, 0x24D5, 0x006C, 0x24D9, 0x006E, 0x24DD, 
-	0x0070, 0x34E1, 0x0072, 0x34E5, 0x0074, 0x34E9, 0x0076, 0x34ED, 
-	0x0078, 0x44F1, 0x007A, 0x44F5, 0x047C, 0x54F9, 0x14BE, 0x097D, 
-	0x1080, 0x0501, 0x1082, 0x0505, 0x1084, 0x0509, 0x1086, 0x050D, 
-	0x1088, 0x0511, 0x108A, 0x0515, 0x108C, 0x0519, 0x108E, 0x051D, 
-	0x1090, 0x0521, 0x1092, 0x0525, 0x1094, 0x0529, 0x1096, 0x052D, 
-	0x1098, 0x0531, 0x109A, 0x0535, 0x109C, 0x0539, 0x109E, 0x053D, 
-	0x10A0, 0x0541, 0x10A2, 0x0545, 0x10A4, 0x0549, 0x10A6, 0x054D, 
-	0x10A8, 0x0551, 0x10AA, 0x0555, 0x10AC, 0x0559, 0x10AE, 0x055D, 
-	0x10B0, 0x0561, 0x10B2, 0x0565, 0x10B4, 0x0569, 0x10B6, 0x056D, 
-	0x10B8, 0x0571, 0x10BA, 0x0575, 0x10BC, 0x0579, 0x053E, 0x0A7D, 
-	0x20C0, 0x1581, 0x20C2, 0x1585, 0x20C4, 0x1589, 0x20C6, 0x158D, 
-	0x20C8, 0x1591, 0x20CA, 0x1595, 0x20CC, 0x1599, 0x20CE, 0x159D, 
-	0x20D0, 0x15A1, 0x20D2, 0x15A5, 0x20D4, 0x15A9, 0x20D6, 0x15AD, 
-	0x20D8, 0x15B1, 0x20DA, 0x15B5, 0x20DC, 0x15B9, 0x20DE, 0x15BD, 
-	0x30E0, 0x25C1, 0x30E2, 0x25C5, 0x30E4, 0x25C9, 0x30E6, 0x25CD, 
-	0x30E8, 0x25D1, 0x30EA, 0x25D5, 0x30EC, 0x25D9, 0x30EE, 0x25DD, 
-	0x40F0, 0x35E1, 0x40F2, 0x35E5, 0x40F4, 0x35E9, 0x40F6, 0x35ED, 
-	0x50F8, 0x45F1, 0x50FA, 0x45F5, 0x057C, 0x55F9, 0x15BE, 0x0B7D, 
-};
-
-
-static WORD stuff5[] =
-{
-	0x0400, 0x0402, 0x0404, 0x0406, 0x0408, 0x040A, 0x040C, 0x040E, 
-	0x0410, 0x0412, 0x0414, 0x0416, 0x0418, 0x041A, 0x041C, 0x041E, 
-	0x0420, 0x0422, 0x0424, 0x0426, 0x0428, 0x042A, 0x042C, 0x042E, 
-	0x0430, 0x0432, 0x0434, 0x0436, 0x0438, 0x043A, 0x043C, 0x083E, 
-	0x0440, 0x0442, 0x0444, 0x0446, 0x0448, 0x044A, 0x044C, 0x044E, 
-	0x0450, 0x0452, 0x0454, 0x0456, 0x0458, 0x045A, 0x045C, 0x045E, 
-	0x0460, 0x0462, 0x0464, 0x0466, 0x0468, 0x046A, 0x046C, 0x046E, 
-	0x0470, 0x0472, 0x0474, 0x0476, 0x0478, 0x047A, 0x087C, 0x18BE, 
-	0x1480, 0x1482, 0x1484, 0x1486, 0x1488, 0x148A, 0x148C, 0x148E, 
-	0x1490, 0x1492, 0x1494, 0x1496, 0x1498, 0x149A, 0x149C, 0x149E, 
-	0x14A0, 0x14A2, 0x14A4, 0x14A6, 0x14A8, 0x14AA, 0x14AC, 0x14AE, 
-	0x14B0, 0x14B2, 0x14B4, 0x14B6, 0x14B8, 0x14BA, 0x14BC, 0x093E, 
-	0x24C0, 0x24C2, 0x24C4, 0x24C6, 0x24C8, 0x24CA, 0x24CC, 0x24CE, 
-	0x24D0, 0x24D2, 0x24D4, 0x24D6, 0x24D8, 0x24DA, 0x24DC, 0x24DE, 
-	0x34E0, 0x34E2, 0x34E4, 0x34E6, 0x34E8, 0x34EA, 0x34EC, 0x34EE, 
-	0x44F0, 0x44F2, 0x44F4, 0x44F6, 0x54F8, 0x54FA, 0x097C, 0x19BE, 
-	0x0500, 0x0502, 0x0504, 0x0506, 0x0508, 0x050A, 0x050C, 0x050E, 
-	0x0510, 0x0512, 0x0514, 0x0516, 0x0518, 0x051A, 0x051C, 0x051E, 
-	0x0520, 0x0522, 0x0524, 0x0526, 0x0528, 0x052A, 0x052C, 0x052E, 
-	0x0530, 0x0532, 0x0534, 0x0536, 0x0538, 0x053A, 0x053C, 0x0A3E, 
-	0x0540, 0x0542, 0x0544, 0x0546, 0x0548, 0x054A, 0x054C, 0x054E, 
-	0x0550, 0x0552, 0x0554, 0x0556, 0x0558, 0x055A, 0x055C, 0x055E, 
-	0x0560, 0x0562, 0x0564, 0x0566, 0x0568, 0x056A, 0x056C, 0x056E, 
-	0x0570, 0x0572, 0x0574, 0x0576, 0x0578, 0x057A, 0x0A7C, 0x1ABE, 
-	0x1580, 0x1582, 0x1584, 0x1586, 0x1588, 0x158A, 0x158C, 0x158E, 
-	0x1590, 0x1592, 0x1594, 0x1596, 0x1598, 0x159A, 0x159C, 0x159E, 
-	0x15A0, 0x15A2, 0x15A4, 0x15A6, 0x15A8, 0x15AA, 0x15AC, 0x15AE, 
-	0x15B0, 0x15B2, 0x15B4, 0x15B6, 0x15B8, 0x15BA, 0x15BC, 0x0B3E, 
-	0x25C0, 0x25C2, 0x25C4, 0x25C6, 0x25C8, 0x25CA, 0x25CC, 0x25CE, 
-	0x25D0, 0x25D2, 0x25D4, 0x25D6, 0x25D8, 0x25DA, 0x25DC, 0x25DE, 
-	0x35E0, 0x35E2, 0x35E4, 0x35E6, 0x35E8, 0x35EA, 0x35EC, 0x35EE, 
-	0x45F0, 0x45F2, 0x45F4, 0x45F6, 0x55F8, 0x55FA, 0x0B7C, 0x1BBE, 
-};
-
-static WORD destuff0[] =
-{
-	0x7000, 0x7001, 0x7002, 0x7003, 0x7004, 0x7005, 0x7006, 0x7007, 
-	0x7008, 0x7009, 0x700A, 0x700B, 0x700C, 0x700D, 0x700E, 0x700F, 
-	0x7010, 0x7011, 0x7012, 0x7013, 0x7014, 0x7015, 0x7016, 0x7017, 
-	0x7018, 0x7019, 0x701A, 0x701B, 0x701C, 0x701D, 0x701E, 0x601F, 
-	0x7020, 0x7021, 0x7022, 0x7023, 0x7024, 0x7025, 0x7026, 0x7027, 
-	0x7028, 0x7029, 0x702A, 0x702B, 0x702C, 0x702D, 0x702E, 0x702F, 
-	0x7030, 0x7031, 0x7032, 0x7033, 0x7034, 0x7035, 0x7036, 0x7037, 
-	0x7038, 0x7039, 0x703A, 0x703B, 0x703C, 0x703D, 0x603E, 0xF03F, 
-	0x7040, 0x7041, 0x7042, 0x7043, 0x7044, 0x7045, 0x7046, 0x7047, 
-	0x7048, 0x7049, 0x704A, 0x704B, 0x704C, 0x704D, 0x704E, 0x704F, 
-	0x7050, 0x7051, 0x7052, 0x7053, 0x7054, 0x7055, 0x7056, 0x7057, 
-	0x7058, 0x7059, 0x705A, 0x705B, 0x705C, 0x705D, 0x705E, 0x603F, 
-	0x7060, 0x7061, 0x7062, 0x7063, 0x7064, 0x7065, 0x7066, 0x7067, 
-	0x7068, 0x7069, 0x706A, 0x706B, 0x706C, 0x706D, 0x706E, 0x706F, 
-	0x7070, 0x7071, 0x7072, 0x7073, 0x7074, 0x7075, 0x7076, 0x7077, 
-	0x7078, 0x7079, 0x707A, 0x707B, 0x607C, 0x607D, 0xF07E, 0xF07F, 
-	0x7180, 0x7181, 0x7182, 0x7183, 0x7184, 0x7185, 0x7186, 0x7187, 
-	0x7188, 0x7189, 0x718A, 0x718B, 0x718C, 0x718D, 0x718E, 0x718F, 
-	0x7190, 0x7191, 0x7192, 0x7193, 0x7194, 0x7195, 0x7196, 0x7197, 
-	0x7198, 0x7199, 0x719A, 0x719B, 0x719C, 0x719D, 0x719E, 0x615F, 
-	0x71A0, 0x71A1, 0x71A2, 0x71A3, 0x71A4, 0x71A5, 0x71A6, 0x71A7, 
-	0x71A8, 0x71A9, 0x71AA, 0x71AB, 0x71AC, 0x71AD, 0x71AE, 0x71AF, 
-	0x71B0, 0x71B1, 0x71B2, 0x71B3, 0x71B4, 0x71B5, 0x71B6, 0x71B7, 
-	0x71B8, 0x71B9, 0x71BA, 0x71BB, 0x71BC, 0x71BD, 0x617E, 0xF1BF, 
-	0x72C0, 0x72C1, 0x72C2, 0x72C3, 0x72C4, 0x72C5, 0x72C6, 0x72C7, 
-	0x72C8, 0x72C9, 0x72CA, 0x72CB, 0x72CC, 0x72CD, 0x72CE, 0x72CF, 
-	0x72D0, 0x72D1, 0x72D2, 0x72D3, 0x72D4, 0x72D5, 0x72D6, 0x72D7, 
-	0x72D8, 0x72D9, 0x72DA, 0x72DB, 0x72DC, 0x72DD, 0x72DE, 0x627F, 
-	0x73E0, 0x73E1, 0x73E2, 0x73E3, 0x73E4, 0x73E5, 0x73E6, 0x73E7, 
-	0x73E8, 0x73E9, 0x73EA, 0x73EB, 0x73EC, 0x73ED, 0x73EE, 0x73EF, 
-	0x74F0, 0x74F1, 0x74F2, 0x74F3, 0x74F4, 0x74F5, 0x74F6, 0x74F7, 
-	0x75F8, 0x75F9, 0x75FA, 0x75FB, 0xF6FC, 0xF6FD, 0xF7FE, 0xF8FF, 
-};
-
-
-static WORD destuff1[] =
-{
-	0x7000, 0x7001, 0x7002, 0x7003, 0x7004, 0x7005, 0x7006, 0x7007, 
-	0x7008, 0x7009, 0x700A, 0x700B, 0x700C, 0x700D, 0x700E, 0x600F, 
-	0x7010, 0x7011, 0x7012, 0x7013, 0x7014, 0x7015, 0x7016, 0x7017, 
-	0x7018, 0x7019, 0x701A, 0x701B, 0x701C, 0x701D, 0x701E, 0xF01F, 
-	0x7020, 0x7021, 0x7022, 0x7023, 0x7024, 0x7025, 0x7026, 0x7027, 
-	0x7028, 0x7029, 0x702A, 0x702B, 0x702C, 0x702D, 0x702E, 0x601F, 
-	0x7030, 0x7031, 0x7032, 0x7033, 0x7034, 0x7035, 0x7036, 0x7037, 
-	0x7038, 0x7039, 0x703A, 0x703B, 0x703C, 0x703D, 0x603E, 0xF03F, 
-	0x7040, 0x7041, 0x7042, 0x7043, 0x7044, 0x7045, 0x7046, 0x7047, 
-	0x7048, 0x7049, 0x704A, 0x704B, 0x704C, 0x704D, 0x704E, 0x602F, 
-	0x7050, 0x7051, 0x7052, 0x7053, 0x7054, 0x7055, 0x7056, 0x7057, 
-	0x7058, 0x7059, 0x705A, 0x705B, 0x705C, 0x705D, 0x705E, 0xF05F, 
-	0x7060, 0x7061, 0x7062, 0x7063, 0x7064, 0x7065, 0x7066, 0x7067, 
-	0x7068, 0x7069, 0x706A, 0x706B, 0x706C, 0x706D, 0x706E, 0x603F, 
-	0x7070, 0x7071, 0x7072, 0x7073, 0x7074, 0x7075, 0x7076, 0x7077, 
-	0x7078, 0x7079, 0x707A, 0x707B, 0x607C, 0x607D, 0xF07E, 0xF07F, 
-	0x7180, 0x7181, 0x7182, 0x7183, 0x7184, 0x7185, 0x7186, 0x7187, 
-	0x7188, 0x7189, 0x718A, 0x718B, 0x718C, 0x718D, 0x718E, 0x614F, 
-	0x7190, 0x7191, 0x7192, 0x7193, 0x7194, 0x7195, 0x7196, 0x7197, 
-	0x7198, 0x7199, 0x719A, 0x719B, 0x719C, 0x719D, 0x719E, 0xF19F, 
-	0x71A0, 0x71A1, 0x71A2, 0x71A3, 0x71A4, 0x71A5, 0x71A6, 0x71A7, 
-	0x71A8, 0x71A9, 0x71AA, 0x71AB, 0x71AC, 0x71AD, 0x71AE, 0x615F, 
-	0x71B0, 0x71B1, 0x71B2, 0x71B3, 0x71B4, 0x71B5, 0x71B6, 0x71B7, 
-	0x71B8, 0x71B9, 0x71BA, 0x71BB, 0x71BC, 0x71BD, 0x617E, 0xF1BF, 
-	0x72C0, 0x72C1, 0x72C2, 0x72C3, 0x72C4, 0x72C5, 0x72C6, 0x72C7, 
-	0x72C8, 0x72C9, 0x72CA, 0x72CB, 0x72CC, 0x72CD, 0x72CE, 0x626F, 
-	0x72D0, 0x72D1, 0x72D2, 0x72D3, 0x72D4, 0x72D5, 0x72D6, 0x72D7, 
-	0x72D8, 0x72D9, 0x72DA, 0x72DB, 0x72DC, 0x72DD, 0x72DE, 0xF2DF, 
-	0x73E0, 0x73E1, 0x73E2, 0x73E3, 0x73E4, 0x73E5, 0x73E6, 0x73E7, 
-	0x73E8, 0x73E9, 0x73EA, 0x73EB, 0x73EC, 0x73ED, 0x73EE, 0x637F, 
-	0x74F0, 0x74F1, 0x74F2, 0x74F3, 0x74F4, 0x74F5, 0x74F6, 0x74F7, 
-	0x75F8, 0x75F9, 0x75FA, 0x75FB, 0xF6FC, 0xF6FD, 0xF7FE, 0xF9FF, 
-};
-
-
-static WORD destuff2[] =
-{
-	0x7000, 0x7001, 0x7002, 0x7003, 0x7004, 0x7005, 0x7006, 0x6007, 
-	0x7008, 0x7009, 0x700A, 0x700B, 0x700C, 0x700D, 0x700E, 0xF00F, 
-	0x7010, 0x7011, 0x7012, 0x7013, 0x7014, 0x7015, 0x7016, 0x600F, 
-	0x7018, 0x7019, 0x701A, 0x701B, 0x701C, 0x701D, 0x701E, 0xF01F, 
-	0x7020, 0x7021, 0x7022, 0x7023, 0x7024, 0x7025, 0x7026, 0x6017, 
-	0x7028, 0x7029, 0x702A, 0x702B, 0x702C, 0x702D, 0x702E, 0xF02F, 
-	0x7030, 0x7031, 0x7032, 0x7033, 0x7034, 0x7035, 0x7036, 0x601F, 
-	0x7038, 0x7039, 0x703A, 0x703B, 0x703C, 0x703D, 0x603E, 0xF03F, 
-	0x7040, 0x7041, 0x7042, 0x7043, 0x7044, 0x7045, 0x7046, 0x6027, 
-	0x7048, 0x7049, 0x704A, 0x704B, 0x704C, 0x704D, 0x704E, 0xF04F, 
-	0x7050, 0x7051, 0x7052, 0x7053, 0x7054, 0x7055, 0x7056, 0x602F, 
-	0x7058, 0x7059, 0x705A, 0x705B, 0x705C, 0x705D, 0x705E, 0xF05F, 
-	0x7060, 0x7061, 0x7062, 0x7063, 0x7064, 0x7065, 0x7066, 0x6037, 
-	0x7068, 0x7069, 0x706A, 0x706B, 0x706C, 0x706D, 0x706E, 0xF06F, 
-	0x7070, 0x7071, 0x7072, 0x7073, 0x7074, 0x7075, 0x7076, 0x603F, 
-	0x7078, 0x7079, 0x707A, 0x707B, 0x607C, 0x607D, 0xF07E, 0xF07F, 
-	0x7180, 0x7181, 0x7182, 0x7183, 0x7184, 0x7185, 0x7186, 0x6147, 
-	0x7188, 0x7189, 0x718A, 0x718B, 0x718C, 0x718D, 0x718E, 0xF18F, 
-	0x7190, 0x7191, 0x7192, 0x7193, 0x7194, 0x7195, 0x7196, 0x614F, 
-	0x7198, 0x7199, 0x719A, 0x719B, 0x719C, 0x719D, 0x719E, 0xF19F, 
-	0x71A0, 0x71A1, 0x71A2, 0x71A3, 0x71A4, 0x71A5, 0x71A6, 0x6157, 
-	0x71A8, 0x71A9, 0x71AA, 0x71AB, 0x71AC, 0x71AD, 0x71AE, 0xF1AF, 
-	0x71B0, 0x71B1, 0x71B2, 0x71B3, 0x71B4, 0x71B5, 0x71B6, 0x615F, 
-	0x71B8, 0x71B9, 0x71BA, 0x71BB, 0x71BC, 0x71BD, 0x617E, 0xF1BF, 
-	0x72C0, 0x72C1, 0x72C2, 0x72C3, 0x72C4, 0x72C5, 0x72C6, 0x6267, 
-	0x72C8, 0x72C9, 0x72CA, 0x72CB, 0x72CC, 0x72CD, 0x72CE, 0xF2CF, 
-	0x72D0, 0x72D1, 0x72D2, 0x72D3, 0x72D4, 0x72D5, 0x72D6, 0x626F, 
-	0x72D8, 0x72D9, 0x72DA, 0x72DB, 0x72DC, 0x72DD, 0x72DE, 0xF2DF, 
-	0x73E0, 0x73E1, 0x73E2, 0x73E3, 0x73E4, 0x73E5, 0x73E6, 0x6377, 
-	0x73E8, 0x73E9, 0x73EA, 0x73EB, 0x73EC, 0x73ED, 0x73EE, 0xF3EF, 
-	0x74F0, 0x74F1, 0x74F2, 0x74F3, 0x74F4, 0x74F5, 0x74F6, 0x647F, 
-	0x75F8, 0x75F9, 0x75FA, 0x75FB, 0xF6FC, 0xF6FD, 0xF7FE, 0xFAFF, 
-};
-
-
-static WORD destuff3[] =
-{
-	0x7000, 0x7001, 0x7002, 0x6003, 0x7004, 0x7005, 0x7006, 0xF007, 
-	0x7008, 0x7009, 0x700A, 0x6007, 0x700C, 0x700D, 0x700E, 0xF00F, 
-	0x7010, 0x7011, 0x7012, 0x600B, 0x7014, 0x7015, 0x7016, 0xF017, 
-	0x7018, 0x7019, 0x701A, 0x600F, 0x701C, 0x701D, 0x701E, 0xF01F, 
-	0x7020, 0x7021, 0x7022, 0x6013, 0x7024, 0x7025, 0x7026, 0xF027, 
-	0x7028, 0x7029, 0x702A, 0x6017, 0x702C, 0x702D, 0x702E, 0xF02F, 
-	0x7030, 0x7031, 0x7032, 0x601B, 0x7034, 0x7035, 0x7036, 0xF037, 
-	0x7038, 0x7039, 0x703A, 0x601F, 0x703C, 0x703D, 0x603E, 0xF03F, 
-	0x7040, 0x7041, 0x7042, 0x6023, 0x7044, 0x7045, 0x7046, 0xF047, 
-	0x7048, 0x7049, 0x704A, 0x6027, 0x704C, 0x704D, 0x704E, 0xF04F, 
-	0x7050, 0x7051, 0x7052, 0x602B, 0x7054, 0x7055, 0x7056, 0xF057, 
-	0x7058, 0x7059, 0x705A, 0x602F, 0x705C, 0x705D, 0x705E, 0xF05F, 
-	0x7060, 0x7061, 0x7062, 0x6033, 0x7064, 0x7065, 0x7066, 0xF067, 
-	0x7068, 0x7069, 0x706A, 0x6037, 0x706C, 0x706D, 0x706E, 0xF06F, 
-	0x7070, 0x7071, 0x7072, 0x603B, 0x7074, 0x7075, 0x7076, 0xF077, 
-	0x7078, 0x7079, 0x707A, 0x603F, 0x607C, 0x607D, 0xF07E, 0xF07F, 
-	0x7180, 0x7181, 0x7182, 0x6143, 0x7184, 0x7185, 0x7186, 0xF187, 
-	0x7188, 0x7189, 0x718A, 0x6147, 0x718C, 0x718D, 0x718E, 0xF18F, 
-	0x7190, 0x7191, 0x7192, 0x614B, 0x7194, 0x7195, 0x7196, 0xF197, 
-	0x7198, 0x7199, 0x719A, 0x614F, 0x719C, 0x719D, 0x719E, 0xF19F, 
-	0x71A0, 0x71A1, 0x71A2, 0x6153, 0x71A4, 0x71A5, 0x71A6, 0xF1A7, 
-	0x71A8, 0x71A9, 0x71AA, 0x6157, 0x71AC, 0x71AD, 0x71AE, 0xF1AF, 
-	0x71B0, 0x71B1, 0x71B2, 0x615B, 0x71B4, 0x71B5, 0x71B6, 0xF1B7, 
-	0x71B8, 0x71B9, 0x71BA, 0x615F, 0x71BC, 0x71BD, 0x617E, 0xF1BF, 
-	0x72C0, 0x72C1, 0x72C2, 0x6263, 0x72C4, 0x72C5, 0x72C6, 0xF2C7, 
-	0x72C8, 0x72C9, 0x72CA, 0x6267, 0x72CC, 0x72CD, 0x72CE, 0xF2CF, 
-	0x72D0, 0x72D1, 0x72D2, 0x626B, 0x72D4, 0x72D5, 0x72D6, 0xF2D7, 
-	0x72D8, 0x72D9, 0x72DA, 0x626F, 0x72DC, 0x72DD, 0x72DE, 0xF2DF, 
-	0x73E0, 0x73E1, 0x73E2, 0x6373, 0x73E4, 0x73E5, 0x73E6, 0xF3E7, 
-	0x73E8, 0x73E9, 0x73EA, 0x6377, 0x73EC, 0x73ED, 0x73EE, 0xF3EF, 
-	0x74F0, 0x74F1, 0x74F2, 0x647B, 0x74F4, 0x74F5, 0x74F6, 0xF4F7, 
-	0x75F8, 0x75F9, 0x75FA, 0x657F, 0xF6FC, 0xF6FD, 0xF7FE, 0xFBFF, 
-};
-
-
-static WORD destuff4[] =
-{
-	0x7000, 0x6001, 0x7002, 0xF003, 0x7004, 0x6003, 0x7006, 0xF007, 
-	0x7008, 0x6005, 0x700A, 0xF00B, 0x700C, 0x6007, 0x700E, 0xF00F, 
-	0x7010, 0x6009, 0x7012, 0xF013, 0x7014, 0x600B, 0x7016, 0xF017, 
-	0x7018, 0x600D, 0x701A, 0xF01B, 0x701C, 0x600F, 0x701E, 0xF01F, 
-	0x7020, 0x6011, 0x7022, 0xF023, 0x7024, 0x6013, 0x7026, 0xF027, 
-	0x7028, 0x6015, 0x702A, 0xF02B, 0x702C, 0x6017, 0x702E, 0xF02F, 
-	0x7030, 0x6019, 0x7032, 0xF033, 0x7034, 0x601B, 0x7036, 0xF037, 
-	0x7038, 0x601D, 0x703A, 0xF03B, 0x703C, 0x601F, 0x603E, 0xF03F, 
-	0x7040, 0x6021, 0x7042, 0xF043, 0x7044, 0x6023, 0x7046, 0xF047, 
-	0x7048, 0x6025, 0x704A, 0xF04B, 0x704C, 0x6027, 0x704E, 0xF04F, 
-	0x7050, 0x6029, 0x7052, 0xF053, 0x7054, 0x602B, 0x7056, 0xF057, 
-	0x7058, 0x602D, 0x705A, 0xF05B, 0x705C, 0x602F, 0x705E, 0xF05F, 
-	0x7060, 0x6031, 0x7062, 0xF063, 0x7064, 0x6033, 0x7066, 0xF067, 
-	0x7068, 0x6035, 0x706A, 0xF06B, 0x706C, 0x6037, 0x706E, 0xF06F, 
-	0x7070, 0x6039, 0x7072, 0xF073, 0x7074, 0x603B, 0x7076, 0xF077, 
-	0x7078, 0x603D, 0x707A, 0xF07B, 0x607C, 0x503F, 0xF07E, 0xF07F, 
-	0x7180, 0x6141, 0x7182, 0xF183, 0x7184, 0x6143, 0x7186, 0xF187, 
-	0x7188, 0x6145, 0x718A, 0xF18B, 0x718C, 0x6147, 0x718E, 0xF18F, 
-	0x7190, 0x6149, 0x7192, 0xF193, 0x7194, 0x614B, 0x7196, 0xF197, 
-	0x7198, 0x614D, 0x719A, 0xF19B, 0x719C, 0x614F, 0x719E, 0xF19F, 
-	0x71A0, 0x6151, 0x71A2, 0xF1A3, 0x71A4, 0x6153, 0x71A6, 0xF1A7, 
-	0x71A8, 0x6155, 0x71AA, 0xF1AB, 0x71AC, 0x6157, 0x71AE, 0xF1AF, 
-	0x71B0, 0x6159, 0x71B2, 0xF1B3, 0x71B4, 0x615B, 0x71B6, 0xF1B7, 
-	0x71B8, 0x615D, 0x71BA, 0xF1BB, 0x71BC, 0x615F, 0x617E, 0xF1BF, 
-	0x72C0, 0x6261, 0x72C2, 0xF2C3, 0x72C4, 0x6263, 0x72C6, 0xF2C7, 
-	0x72C8, 0x6265, 0x72CA, 0xF2CB, 0x72CC, 0x6267, 0x72CE, 0xF2CF, 
-	0x72D0, 0x6269, 0x72D2, 0xF2D3, 0x72D4, 0x626B, 0x72D6, 0xF2D7, 
-	0x72D8, 0x626D, 0x72DA, 0xF2DB, 0x72DC, 0x626F, 0x72DE, 0xF2DF, 
-	0x73E0, 0x6371, 0x73E2, 0xF3E3, 0x73E4, 0x6373, 0x73E6, 0xF3E7, 
-	0x73E8, 0x6375, 0x73EA, 0xF3EB, 0x73EC, 0x6377, 0x73EE, 0xF3EF, 
-	0x74F0, 0x6479, 0x74F2, 0xF4F3, 0x74F4, 0x647B, 0x74F6, 0xF4F7, 
-	0x75F8, 0x657D, 0x75FA, 0xF5FB, 0xF6FC, 0xE67F, 0xF7FE, 0xFCFF, 
-};
-
-
-static WORD destuff5[] =
-{
-	0x6000, 0xF001, 0x6001, 0xF003, 0x6002, 0xF005, 0x6003, 0xF007, 
-	0x6004, 0xF009, 0x6005, 0xF00B, 0x6006, 0xF00D, 0x6007, 0xF00F, 
-	0x6008, 0xF011, 0x6009, 0xF013, 0x600A, 0xF015, 0x600B, 0xF017, 
-	0x600C, 0xF019, 0x600D, 0xF01B, 0x600E, 0xF01D, 0x600F, 0xF01F, 
-	0x6010, 0xF021, 0x6011, 0xF023, 0x6012, 0xF025, 0x6013, 0xF027, 
-	0x6014, 0xF029, 0x6015, 0xF02B, 0x6016, 0xF02D, 0x6017, 0xF02F, 
-	0x6018, 0xF031, 0x6019, 0xF033, 0x601A, 0xF035, 0x601B, 0xF037, 
-	0x601C, 0xF039, 0x601D, 0xF03B, 0x601E, 0xF03D, 0x501F, 0xF03F, 
-	0x6020, 0xF041, 0x6021, 0xF043, 0x6022, 0xF045, 0x6023, 0xF047, 
-	0x6024, 0xF049, 0x6025, 0xF04B, 0x6026, 0xF04D, 0x6027, 0xF04F, 
-	0x6028, 0xF051, 0x6029, 0xF053, 0x602A, 0xF055, 0x602B, 0xF057, 
-	0x602C, 0xF059, 0x602D, 0xF05B, 0x602E, 0xF05D, 0x602F, 0xF05F, 
-	0x6030, 0xF061, 0x6031, 0xF063, 0x6032, 0xF065, 0x6033, 0xF067, 
-	0x6034, 0xF069, 0x6035, 0xF06B, 0x6036, 0xF06D, 0x6037, 0xF06F, 
-	0x6038, 0xF071, 0x6039, 0xF073, 0x603A, 0xF075, 0x603B, 0xF077, 
-	0x603C, 0xF079, 0x603D, 0xF07B, 0x503E, 0xE07D, 0xE03F, 0xF07F, 
-	0x6140, 0xF181, 0x6141, 0xF183, 0x6142, 0xF185, 0x6143, 0xF187, 
-	0x6144, 0xF189, 0x6145, 0xF18B, 0x6146, 0xF18D, 0x6147, 0xF18F, 
-	0x6148, 0xF191, 0x6149, 0xF193, 0x614A, 0xF195, 0x614B, 0xF197, 
-	0x614C, 0xF199, 0x614D, 0xF19B, 0x614E, 0xF19D, 0x614F, 0xF19F, 
-	0x6150, 0xF1A1, 0x6151, 0xF1A3, 0x6152, 0xF1A5, 0x6153, 0xF1A7, 
-	0x6154, 0xF1A9, 0x6155, 0xF1AB, 0x6156, 0xF1AD, 0x6157, 0xF1AF, 
-	0x6158, 0xF1B1, 0x6159, 0xF1B3, 0x615A, 0xF1B5, 0x615B, 0xF1B7, 
-	0x615C, 0xF1B9, 0x615D, 0xF1BB, 0x615E, 0xF1BD, 0x513F, 0xF1BF, 
-	0x6260, 0xF2C1, 0x6261, 0xF2C3, 0x6262, 0xF2C5, 0x6263, 0xF2C7, 
-	0x6264, 0xF2C9, 0x6265, 0xF2CB, 0x6266, 0xF2CD, 0x6267, 0xF2CF, 
-	0x6268, 0xF2D1, 0x6269, 0xF2D3, 0x626A, 0xF2D5, 0x626B, 0xF2D7, 
-	0x626C, 0xF2D9, 0x626D, 0xF2DB, 0x626E, 0xF2DD, 0x626F, 0xF2DF, 
-	0x6370, 0xF3E1, 0x6371, 0xF3E3, 0x6372, 0xF3E5, 0x6373, 0xF3E7, 
-	0x6374, 0xF3E9, 0x6375, 0xF3EB, 0x6376, 0xF3ED, 0x6377, 0xF3EF, 
-	0x6478, 0xF4F1, 0x6479, 0xF4F3, 0x647A, 0xF4F5, 0x647B, 0xF4F7, 
-	0x657C, 0xF5F9, 0x657D, 0xF5FB, 0xE67E, 0xF6FD, 0xE77F, 0xFDFF, 
-};
-
-
-static WORD * stuffs[] = { stuff0, stuff1, stuff2, stuff3, stuff4, stuff5 };
-WORD * destuffs[] = { destuff0, destuff1, destuff2, destuff3, destuff4, destuff5 };
-
-
-/*- AuverTech Telecom -------------------------------------------------------+
- |                                                                           |
- | @Function  : tpam_hdlc_encode                                             |
- | @Author    : Cyrille Boudon                                               |
- |                                                                           |
- +---------------------------------------------------------------------------+
- |                                                                           |
- | @Param     : BYTE *pbyBuffIn        IN,    array of bytes to encode       |
- | @Param     : BYTE *pbyBuffOut       OUT,   array of bytes encoded         |
- | @Param     : DWORD *pdwInitialShift INOUT, initial shift                  |
- | @Param     : DWORD dwLength         IN,    count of bytes to encode       |
- |                                                                           |
- | @Return    : DWORD                  count of bytes encoded                |
- |                                                                           |
- +------------------------------- @Abstract ---------------------------------+
- |                                                                           |
- | Bit stuffing of thz array pbyBuffIn with the insertion of a flag at the   |
- | beginning and the end, using the initial shift (due to the emission of    |
- | previous frames). The last byte can be used to insert flags (by outputting|
- | the flag N times) before the next frame. The initial shift is updated at  |
- | the end of the algorithm for the next frame. Its signification is: for the|
- | flags shifted like  "1100111111001111" *pdwInitialShift = 3. At the       |
- | beginning (for the first frame), the shift must be initialized to 0.      |
- |                                                                           |
- +---------------------------------------------------------------------------*/
-DWORD tpam_hdlc_encode(BYTE *pbyBuffIn, BYTE *pbyBuffOut,
-		       DWORD *pdwInitialShift, DWORD dwLength)
-{
-	DWORD	dwShifter;     // temporary variable
-	DWORD	dwShiftNb;     // shift due to the insertion of '0'
-	DWORD	dwState;       // count of '1' at the end of the current byte
-	DWORD	dwNb;          // length of the encoded array
-	BYTE	byCarry;       // carry due to the shift
-	BYTE	byNewCarry;    // temporary variable
-	BYTE	byCharIn;      // byte being encoded
-	BYTE	byCarryMSB;    // lost bit of the carry if dwShiftNb=7 and 2 '0' inserted
-	WORD	woDecal;       // temporary variable
-	WORD	woInfo;        // data read in the arrays
-	BOOL	bContinue;     // true until the two last bytes
-	BOOL	bContinue2;    // true until the last byte
-
-	bContinue = TRUE;
-	bContinue2 = TRUE;
-	dwShiftNb = 0;
-	byCarry = 0;
-	dwState = 0;
-	woDecal = 0x7E;
-	byCarryMSB = 0xFF;
-	dwNb = 1; // length to 1 to account for the first flag
-	
-	/*-----------------------------
-	 | insert the flag using the
-	 | shift given by
-	 | *pdwInitialShift)
-	 +-----------------------------*/
-	* pbyBuffOut ++ = 0x7E7E >> *pdwInitialShift;
-
-	/*-----------------------------
-	 | main loop
-	 +-----------------------------*/
-	while (dwLength--)
-	{
-		byCharIn = *pbyBuffIn ++;
-		
-/*-----------------------------
- | go back here to treat the
- | carry when its length
- | is over 7 and for the first
- | byte (with flag)
- +-----------------------------*/
-carry:
-
-		dwNb ++;
-
-		/*-----------------------------
-		 | shift the byte to get the
-		 | byte to encode (without
-		 | taking into account the
-		 | initial shift)
-		 +-----------------------------*/
-		if (dwShiftNb)
-		{
-			dwShifter = byCharIn << dwShiftNb;
-			byNewCarry = dwShifter >> 8;
-			byCharIn = dwShifter | byCarry;
-			byCarry = byNewCarry;
-		}
-
-		/*-----------------------------
-		 | get the data from the arrays
-		 | and take into account the
-		 | initial shift for the byte
-		 | to encode
-		 +-----------------------------*/
-		woInfo = stuffs[dwState][byCharIn];
-		woDecal |= (woInfo & 0x00FF) << 8;
-		* pbyBuffOut ++ = woDecal >> *pdwInitialShift;
-		woDecal = woInfo & 0x00FF;
-		dwState = woInfo >> 12;
-
-		/*-----------------------------
-		 | treat the lost bit if we had
-		 | a carry overflow
-		 +-----------------------------*/
-		if (byCarryMSB != 0xFF)
-		{
-			if (!dwShiftNb)
-			{
-				if(byCarryMSB)
-					byCarry = 1;
-				dwShiftNb = 1;
-			}
-			byCarryMSB = 0xFF;
-		}
-
-		/*-----------------------------
-		 | if one '0' get inserted, we
-		 | have to calculate the new
-		 | carry and the new shift
-		 +-----------------------------*/
-		if (woInfo & 0x0F00)
-		{
-			byCarryMSB = byCarry & 0x40;
-			byCarry <<= (woInfo & 0x0C00) >> 10;
-			byCarry |= (woInfo & 0x0300) >> 8;
-			dwShiftNb += (woInfo & 0x0C00) >> 10;
-		}
-
-		/*-----------------------------
-		 | if the carry is a whole byte
-		 | we use it as a byte to encode
-		 +-----------------------------*/
-		if (dwShiftNb > 7)
-		{
-			if (dwShiftNb == 8)
-				byCarryMSB = 0xFF;
-			dwShiftNb = 0;
-			byCharIn = byCarry;
-			byCarry = 0;
-			goto carry;
-		}
-
-		/*-----------------------------
-		 | at the end of the array
-		 +-----------------------------*/
-		if (!dwLength)
-		{
-			/*-----------------------------
-			 | take into account the bits
-			 | set in the carry
-			 +-----------------------------*/
-			if (bContinue)
-			{
-				bContinue = FALSE;
-				byCharIn = 0;
-				goto carry;
-			}
-			
-			/*-----------------------------
-			 | treat the last byte if we
-			 | had a carry overflow
-			 +-----------------------------*/
-			if (bContinue2 && ((8 - *pdwInitialShift) + dwShiftNb) > 7)
-			{
-				bContinue2 = FALSE;
-				byCharIn = 0;
-				goto carry;
-			}
-
-			/*-----------------------------
-			 | Calculate the new shift
-			 +-----------------------------*/
-			*pdwInitialShift = ((8 - *pdwInitialShift) + dwShiftNb)%8;
-
-			/*-----------------------------
-			 | Add a flag at the end of the
-			 | carry and a full flag
-			 +-----------------------------*/
-			pbyBuffOut--;
-			*pbyBuffOut++ |= 0x7E << *pdwInitialShift;
-			byCarry = 0x7E7E >> (8 - *pdwInitialShift);
-			*pbyBuffOut++ = byCarry;
-			*pbyBuffOut++ = byCarry;
-			dwNb += 2;
-		}
-	}
-
-	/*-------------------------------
-	 | Pad the array to a multiple
-	 | of 64 bytes.
-	 +-------------------------------*/
-	for(;dwNb%64;dwNb++)
-		*pbyBuffOut ++ = byCarry;
-
-	*pdwInitialShift = (8 - *pdwInitialShift)%8;
-
-	return dwNb;
-}
-
-
-
-/*- AuverTech Telecom -------------------------------------------------------+
- |                                                                           |
- | @Function  : tpam_hdlc_decode                                             |
- | @Author    : Cyrille Boudon                                               |
- |                                                                           |
- +---------------------------------------------------------------------------+
- |                                                                           |
- | @Param     : BYTE * pbyBuffIn  IN,  array of bytes to decode              |
- | @Param     : BYTE * pbyBuffOut OUT, array of decoded bytes                |
- | @Param     : DWORD dwLength    IN,  count of bytes to decode              |
- |                                                                           |
- | @Return    : DWORD             count of decoded bytes                     |
- |                                                                           |
- +------------------------------- @Abstract ---------------------------------+
- |                                                                           |
- | Bit de-stuffing of the array pbyBuffIn. There has to be at least 1 full   |
- | flag at the beginning. At the end there has to be a flag or an abort (more|
- | than 6 consecutive '1').                                                  |
- | If an abort is encountered, the returned count is '0'.                    |
- |                                                                           |
- +---------------------------------------------------------------------------*/
-DWORD tpam_hdlc_decode(BYTE * pbyBuffIn, BYTE * pbyBuffOut, DWORD dwLength)
-{
-	BYTE	byCharIn;    // byte being decoded
-	BYTE	byCarry;     // current carry
-	WORD	woInfo;      // data read in the arrays
-	WORD	woNb1;       // count of '1' at the end of the previous byte
-	BYTE	byShift;     // shift of the first flag
-	DWORD	dwInit;      // temporary variable
-	DWORD	dwLengthOut; // count of the decoded bytes
-	BYTE	byLgCarry;   // count of used bits in the carry
-	BYTE	byLgByte;    // count of used bits in the decoded byte
-
-	/*-----------------------------
-	 | Find the 1st flag. At the end
-	 | of the loop dwShift is the count
-	 | of bits to reach the 1st bit
-	 | of the 1st flag.
-	 +-----------------------------*/
-	dwInit = *pbyBuffIn | (*(pbyBuffIn+1)<<8) | (*(pbyBuffIn+2)<<16);
-	for (byShift=0;byShift<17;byShift++)
-	{
-		if (!(((dwInit>>byShift)&0xFF)^0x7E))
-		{
-			break;
-		}
-	}
-
-	/*-----------------------------
-	 | If at the end of the previous
-	 | loop dwShift = 17, it means
-	 | that no flag was found in the
-	 | first 3 bytes (normally
-	 | impossible impossible with the
-	 | DSP algorithm)
-	 +-----------------------------*/
-	if (byShift == 17)
-		return 0;
-
-	/*-----------------------------
-	 | Plase the array pointer after
-	 | the first flag. Update the
-	 | shift.
-	 +-----------------------------*/
-	pbyBuffIn += byShift/8 + 1;
-	dwLength -= byShift/8 + 1;
-	byShift %= 8;
-	
-	/*-----------------------------
-	 | Walk through the frame to
-	 | find the first data byte
-	 +-----------------------------*/
-	dwInit = *pbyBuffIn | (*(pbyBuffIn+1)<<8);
-	while (!(((dwInit>>byShift)&0xFF)^0x7E))
-	{
-		pbyBuffIn ++;
-		dwLength --;
-		dwInit = *pbyBuffIn | (*(pbyBuffIn+1)<<8);
-	}
-
-	dwLengthOut = 0;
-	byCarry = 0;
-	byLgCarry = 0;
-	byLgByte = 0;
-
-	/*-------------------------------
-	 | Treat the first byte
-	 +-------------------------------*/	
-	byCharIn = (*pbyBuffIn >> byShift) << byShift;
-	woInfo = destuffs[0][byCharIn];
-	byLgByte = ((woInfo & 0x7000) >> 12) + 1;
-	woNb1 = (woInfo & 0x0F00) >> 8;
-	dwLength --;
-	pbyBuffIn++;
-
-	if (woNb1 > 5)
-		return 0;
-
-	if (byLgByte - byShift == 8)
-	{
-		*pbyBuffOut ++ = woInfo;
-		dwLengthOut ++;
-	}
-	else
-	{
-		byCarry = woInfo << (8 - byLgByte);
-		byLgCarry = byLgByte - byShift;
-	}
-
-	/*-------------------------------
-	 | main loop
-	 +-------------------------------*/
-	while(dwLength --)
-	{
-		byCharIn = *pbyBuffIn ++;
-
-		woInfo = destuffs[woNb1][byCharIn];
-		byLgByte = ((woInfo & 0x7000) >> 12) + 1;
-		
-		/*-------------------------------
-		 | if the used bits in the carry
-		 | and the current byte makes
-		 | possible to output a full byte
-		 +-------------------------------*/
-		if (byLgByte + byLgCarry >= 8)
-		{
-			*pbyBuffOut ++ = ( (woInfo << 8) | byCarry) >> (8 - byLgCarry);
-			dwLengthOut ++;
-			byLgCarry += byLgByte - 8;
-			byCarry = woInfo << (8-byLgByte);
-		}
-		/*-------------------------------
-		 | if the used bits in the carry
-		 | and the current byte doesn't
-		 | make possible to output a full 
-		 | byte
-		 +-------------------------------*/
-		else
-		{
-			dwInit = (woInfo << 8) | byCarry;
-			byLgCarry += byLgByte;
-			byCarry = dwInit >> byLgByte;
-		}
-
-		woNb1 = (woInfo & 0x0F00) >> 8;
-
-		/*-------------------------------
-		 | if the current byte contains
-		 | six or more consecutive '1'
-		 +-------------------------------*/
-		if (woInfo & 0x8000)
-		{
-			byCarry = ((byCharIn << 8) | *(pbyBuffIn-2)) >> (8 - byLgCarry);
-			if (byCarry == 0x7E)
-				return dwLengthOut-1;
-			else
-				if (woNb1 > 6)
-					return 0;
-				else
-					if ((!(*pbyBuffIn & 1)) && (byLgCarry == 7))
-						return dwLengthOut;
-					else
-						return 0;
-		}
-	}
-
-	return dwLengthOut;
-}
-
diff -Nru a/drivers/isdn/tpam/tpam_main.c b/drivers/isdn/tpam/tpam_main.c
--- a/drivers/isdn/tpam/tpam_main.c	2005-03-11 12:51:47 -08:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,297 +0,0 @@
-/* $Id: tpam_main.c,v 1.1.2.3 2001/09/23 22:25:03 kai Exp $
- *
- * Turbo PAM ISDN driver for Linux. (Kernel Driver - main routines)
- *
- * Copyright 2001 Stelian Pop <stelian.pop@fr.alcove.com>, Alcôve
- *
- * This software may be used and distributed according to the terms
- * of the GNU General Public License, incorporated herein by reference.
- *
- * For all support questions please contact: <support@auvertech.fr>
- *
- */
-
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/sched.h>
-#include <linux/interrupt.h>
-
-#include <linux/init.h>
-#include <asm/io.h>
-
-#include "tpam.h"
-
-/* Local functions prototypes */
-static int __devinit tpam_probe(struct pci_dev *, const struct pci_device_id *);
-static void __devexit tpam_unregister_card(struct pci_dev *, tpam_card *);
-static void __devexit tpam_remove(struct pci_dev *);
-static int __init tpam_init(void);
-static void __exit tpam_exit(void);
-
-/* List of boards */
-static tpam_card *cards; /* = NULL; */
-/* Number of cards */
-static int cards_num;
-/* Configurable id of the driver */
-static char *id = "tpam\0\0\0\0\0\0\0\0\0\0\0\0";
-
-MODULE_DESCRIPTION("ISDN4Linux: Driver for TurboPAM ISDN cards");
-MODULE_AUTHOR("Stelian Pop");
-MODULE_LICENSE("GPL");
-MODULE_PARM_DESC(id,"ID-String of the driver");
-module_param(id, charp, 0);
-
-/*
- * Finds a board by its driver ID.
- *
- * 	driverId: driver ID (as referenced by the IDSN link layer)
- *
- * Return: the tpam_card structure if found, NULL on error.
- */
-tpam_card *tpam_findcard(int driverid) {
-	tpam_card *p = cards;
-
-	while (p) {
-		if (p->id == driverid)
-			return p;
-		p = p->next;
-	}
-	return NULL;
-}
-
-/*
- * Finds a channel number by its ncoid.
- *
- * 	card: the board
- * 	ncoid: the NCO id
- *
- * Return: the channel number if found, TPAM_CHANNEL_INVALID if not.
- */
-u32 tpam_findchannel(tpam_card *card, u32 ncoid) {
-	int i;
-
-	for (i = 0; i < TPAM_NBCHANNEL; ++i)
-		if (card->channels[i].ncoid == ncoid)
-			return card->channels[i].num;
-	return TPAM_CHANNEL_INVALID;
-}
-
-/*
- * Initializes and registers a new TurboPAM card.
- *
- * 	dev: the PCI device
- * 	num: the board number
- *
- * Return: 0 if OK, <0 if error
- */
-static int __devinit tpam_probe(struct pci_dev *dev, const struct pci_device_id *pci_id) {
-	tpam_card *card, *c;
-	int i, err;
-
-	if ((err = pci_enable_device(dev))) {
-		printk(KERN_ERR "TurboPAM: can't enable PCI device at %s\n",
-			pci_name(dev));
-		return err;
-	}
-
-	/* allocate memory for the board structure */
-	if (!(card = (tpam_card *)kmalloc(sizeof(tpam_card), GFP_KERNEL))) {
-		printk(KERN_ERR "TurboPAM: tpam_register_card: "
-		       "kmalloc failed!\n");
-		err = -ENOMEM;
-		goto err_out_disable_dev;
-	}
-
-	memset((char *)card, 0, sizeof(tpam_card));
-
-	card->irq = dev->irq;
-	spin_lock_init(&card->lock);
-	sprintf(card->interface.id, "%s%d", id, cards_num);
-
-	/* request interrupt */
-	if (request_irq(card->irq, &tpam_irq, SA_INTERRUPT | SA_SHIRQ, 
-			card->interface.id, card)) {
-		printk(KERN_ERR "TurboPAM: tpam_register_card: "
-		       "could not request irq %d\n", card->irq);
-		err = -EIO;
-		goto err_out_free_card;
-	}
-
-	/* remap board memory */
-	if (!(card->bar0 = ioremap(pci_resource_start(dev, 0),
-						   0x800000))) {
-		printk(KERN_ERR "TurboPAM: tpam_register_card: "
-		       "unable to remap bar0\n");
-		err = -EIO;
-		goto err_out_free_irq;
-	}
-
-	/* reset the board */
-	readl(card->bar0 + TPAM_RESETPAM_REGISTER);
-
-	/* initialisation magic :-( */
-	copy_to_pam_dword(card, 0x01800008, 0x00000030);
-	copy_to_pam_dword(card, 0x01800010, 0x00000030);
-	copy_to_pam_dword(card, 0x01800014, 0x42240822);
-	copy_to_pam_dword(card, 0x01800018, 0x07114000);
-	copy_to_pam_dword(card, 0x0180001c, 0x00000400);
-	copy_to_pam_dword(card, 0x01840070, 0x00000010);
-
-	/* fill the ISDN link layer structure */
-	card->interface.owner = THIS_MODULE;
-	card->interface.channels = TPAM_NBCHANNEL;
-	card->interface.maxbufsize = TPAM_MAXBUFSIZE;
-	card->interface.features = 
-		ISDN_FEATURE_P_EURO |
-		ISDN_FEATURE_L2_HDLC |
-		ISDN_FEATURE_L2_MODEM |
-		ISDN_FEATURE_L3_TRANS;
-	card->interface.hl_hdrlen = 0;
-	card->interface.command = tpam_command;
-	card->interface.writebuf_skb = tpam_writebuf_skb;
-	card->interface.writecmd = NULL;
-	card->interface.readstat = NULL;
-
-	/* register wrt the ISDN link layer */
-	if (!register_isdn(&card->interface)) {
-		printk(KERN_ERR "TurboPAM: tpam_register_card: "
-		       "unable to register %s\n", card->interface.id);
-		err = -EIO;
-		goto err_out_iounmap;
-	}
-	card->id = card->interface.channels;
-
-	/* initialize all channels */
-	for (i = 0; i < TPAM_NBCHANNEL; ++i) {
-		card->channels[i].num = i;
-		card->channels[i].card = card;
-		card->channels[i].ncoid = TPAM_NCOID_INVALID;
-		card->channels[i].hdlc = 0;
-		card->channels[i].realhdlc = 0;
-		card->channels[i].hdlcshift = 0;
-		skb_queue_head_init(&card->channels[i].sendq);
-	}
-
-	/* initialize the rest of board structure */
-	card->channels_used = 0;
-	card->channels_tested = 0;
-	card->running = 0;
-	card->busy = 0;
-	card->roundrobin = 0;
-	card->loopmode = 0;
-	skb_queue_head_init(&card->sendq);
-	skb_queue_head_init(&card->recvq);
-	INIT_WORK(&card->recv_tq, (void *) (void *) tpam_recv_tq, card);
-	INIT_WORK(&card->send_tq, (void *) (void *) tpam_send_tq, card);
-
-	/* add the board at the end of the list of boards */
-	card->next = NULL;
-	if (cards) {
-		c = cards;
-		while (c->next)
-			c = c->next;
-		c->next = card;
-	}
-	else
-		cards = card;
-
-	++cards_num;
-	pci_set_drvdata(dev, card);
-
-	return 0;
-
-err_out_iounmap:
-	iounmap(card->bar0);
-
-err_out_free_irq:
-	free_irq(card->irq, card);
-
-err_out_free_card:
-	kfree(card);
-
-err_out_disable_dev:
-	pci_disable_device(dev);
-	return err;
-}
-
-/*
- * Unregisters a TurboPAM board by releasing all its ressources (irq, mem etc).
- *
- * 	card: the board.
- */
-static void __devexit tpam_unregister_card(struct pci_dev *pcidev, tpam_card *card) {
-	isdn_ctrl cmd;
-
-	/* prevent the ISDN link layer that the driver will be unloaded */
-	cmd.command = ISDN_STAT_UNLOAD;
-	cmd.driver = card->id;
-	(* card->interface.statcallb)(&cmd);
-
-	/* release interrupt */
-	free_irq(card->irq, card);
-
-	/* release mapped memory */
-	iounmap(card->bar0);
-
-	pci_disable_device(pcidev);
-}
-
-/*
- * Stops the driver.
- */
-static void __devexit tpam_remove(struct pci_dev *pcidev) {
-	tpam_card *card = pci_get_drvdata(pcidev);
-	tpam_card *c;
-
-	/* remove from the list of cards */
-	if (card == cards)
-		cards = cards->next;
-	else {
-		c = cards;
-		while (c->next != card) 
-			c = c->next;
-		c->next = c->next->next;
-	}
-	
-	/* unregister each board */
-	tpam_unregister_card(pcidev, card);
-	
-	/* and free the board structure itself */
-	kfree(card);
-}
-
-static struct pci_device_id tpam_pci_tbl[] = {
-	{ PCI_VENDOR_ID_XILINX, PCI_DEVICE_ID_TURBOPAM,
-	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
-	{ }
-};
-
-MODULE_DEVICE_TABLE(pci, tpam_pci_tbl);
-
-static struct pci_driver tpam_driver = {
-	.name		= "tpam",
-	.id_table	= tpam_pci_tbl,
-	.probe		= tpam_probe,
-	.remove		= __devexit_p(tpam_remove),
-};
-
-static int __init tpam_init(void) {
-	int ret;
-	
-	ret = pci_module_init(&tpam_driver);
-	if (ret)
-		return ret;
-	printk(KERN_INFO "TurboPAM: %d card%s found, driver loaded.\n", 
-	       cards_num, (cards_num > 1) ? "s" : "");
-	return 0;
-}
-
-static void __exit tpam_exit(void) {
-	pci_unregister_driver(&tpam_driver);
-	printk(KERN_INFO "TurboPAM: driver unloaded\n");
-}
-
-/* Module entry points */
-module_init(tpam_init);
-module_exit(tpam_exit);
-
diff -Nru a/drivers/isdn/tpam/tpam_memory.c b/drivers/isdn/tpam/tpam_memory.c
--- a/drivers/isdn/tpam/tpam_memory.c	2005-03-11 12:51:42 -08:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,247 +0,0 @@
-/* $Id: tpam_memory.c,v 1.1.2.2 2001/09/23 22:25:03 kai Exp $
- *
- * Turbo PAM ISDN driver for Linux. (Kernel Driver - Board Memory Access)
- *
- * Copyright 2001 Stelian Pop <stelian.pop@fr.alcove.com>, Alcôve
- *
- * This software may be used and distributed according to the terms
- * of the GNU General Public License, incorporated herein by reference.
- *
- * For all support questions please contact: <support@auvertech.fr>
- *
- */
-
-#include <linux/pci.h>
-#include <asm/io.h>
-
-#include "tpam.h"
-
-/*
- * Write a DWORD into the board memory.
- *
- * 	card: the board
- * 	addr: the address (in the board memory)
- * 	val: the value to put into the memory.
- */
-void copy_to_pam_dword(tpam_card *card, u32 addr, u32 val) {
-
-	/* set the page register */
-	writel(addr | TPAM_PAGE_SIZE, 
-	       card->bar0 + TPAM_PAGE_REGISTER);
-
-	/* write the value */
-	writel(val, card->bar0 + (addr & TPAM_PAGE_SIZE));
-}
-
-/*
- * Write n bytes into the board memory. The count of bytes will be rounded
- * up to a multiple of 4.
- *
- * 	card: the board
- * 	to: the destination address (in the board memory)
- * 	from: the source address (in the kernel memory)
- * 	n: number of bytes
- */
-void copy_to_pam(tpam_card *card, u32 to, const void *from, u32 n) {
-	u32 page, offset, count;
-
-	/* need to write in dword ! */
-	while (n & 3) n++;
-
-	while (n) {
-		page = to | TPAM_PAGE_SIZE;
-		offset = to & TPAM_PAGE_SIZE;
-		count = n < TPAM_PAGE_SIZE - offset
-				? n
-				: TPAM_PAGE_SIZE - offset;
-
-		/* set the page register */
-		writel(page, card->bar0 + TPAM_PAGE_REGISTER);
-
-		/* copy the data */
-		memcpy_toio(card->bar0 + offset, from, count);
-		
-		from += count;
-		to += count;
-		n -= count;
-	}
-}
-
-/*
- * Read a DWORD from the board memory.
- *
- * 	card: the board
- * 	addr: the address (in the board memory)
- *
- * Return: the value read into the memory.
- */
-u32 copy_from_pam_dword(tpam_card *card, u32 addr) {
-
-	/* set the page register */
-	writel(((u32)addr) | TPAM_PAGE_SIZE, 
-	       card->bar0 + TPAM_PAGE_REGISTER);
-
-	/* read the data */
-	return readl(card->bar0 + (addr & TPAM_PAGE_SIZE));
-}
-
-/*
- * Read n bytes from the board memory.
- *
- * 	card: the board
- * 	to: the destination address (in the kernel memory)
- * 	from: the source address (in the board memory)
- * 	n: number of bytes
- */
-void copy_from_pam(tpam_card *card, void *to, u32 from, u32 n) {
-	u32 page, offset, count;
-
-	while (n) {
-		page = from | TPAM_PAGE_SIZE;
-		offset = from & TPAM_PAGE_SIZE;
-		count = n < TPAM_PAGE_SIZE - offset 
-				? n 
-				: TPAM_PAGE_SIZE - offset;
-
-		/* set the page register */
-		writel(page, card->bar0 + TPAM_PAGE_REGISTER);
-
-		/* read the data */
-		memcpy_fromio(to, card->bar0 + offset, count);
-		
-		from += count;
-		to += count;
-		n -= count;
-	}
-}
-
-/*
- * Read n bytes from the board memory and writes them into the user memory.
- *
- * 	card: the board
- * 	to: the destination address (in the userspace memory)
- * 	from: the source address (in the board memory)
- * 	n: number of bytes
- *
- * Return: 0 if OK, <0 if error.
- */
-int copy_from_pam_to_user(tpam_card *card, void __user *to, u32 from, u32 n) {
-	void *page;
-	u32 count;
-
-	/* allocate a free page for the data transfer */
-	if (!(page = (void *)__get_free_page(GFP_KERNEL))) {
-		printk(KERN_ERR "TurboPAM(copy_from_pam_to_user): "
-		       "get_free_page failed\n");
-		return -ENOMEM;
-	}
-
-	while (n) {
-		count = n < PAGE_SIZE ? n : PAGE_SIZE;
-
-		/* copy data from the board into the kernel memory */
-		spin_lock_irq(&card->lock);
-		copy_from_pam(card, page, from, count);
-		spin_unlock_irq(&card->lock);
-
-		/* copy it from the kernel memory into the user memory */
-		if (copy_to_user(to, page, count)) {
-			
-			/* this can fail... */
-			free_page((unsigned long)page);
-			return -EFAULT;
-		}
-		from += count;
-		to += count;
-		n -= count;
-	}
-
-	/* release allocated memory */
-	free_page((unsigned long)page);
-	return 0;
-}
-
-/*
- * Read n bytes from the user memory and writes them into the board memory.
- *
- * 	card: the board
- * 	to: the destination address (in the board memory)
- * 	from: the source address (in the userspace memory)
- * 	n: number of bytes
- *
- * Return: 0 if OK, <0 if error.
- */
-int copy_from_user_to_pam(tpam_card *card, u32 to, const void __user *from, u32 n) {
-	void *page;
-	u32 count;
-
-	/* allocate a free page for the data transfer */
-	if (!(page = (void *)__get_free_page(GFP_KERNEL))) {
-		printk(KERN_ERR "TurboPAM(copy_from_user_to_pam): "
-		       "get_free_page failed\n");
-		return -ENOMEM;
-	}
-
-	while (n) {
-		count = n < PAGE_SIZE ? n : PAGE_SIZE;
-
-		/* copy data from the user memory into the kernel memory */
-		if (copy_from_user(page, from, count)) {
-			/* this can fail... */
-			free_page((unsigned long)page);
-			return -EFAULT;
-		}
-
-		/* copy it from the kernel memory into the board memory */
-		spin_lock_irq(&card->lock);
-		copy_to_pam(card, to, page, count);
-		spin_unlock_irq(&card->lock);
-
-		from += count;
-		to += count;
-		n -= count;
-	}
-
-	/* release allocated memory */
-	free_page((unsigned long)page);
-	return 0;
-}
-
-/*
- * Verify if we have the permission to read or writes len bytes at the
- * address address from/to the board memory.
- *
- * 	address: the start address (in the board memory)
- * 	len: number of bytes
- *
- * Return: 0 if OK, <0 if error.
- */
-int tpam_verify_area(u32 address, u32 len) {
-
-	if (address < TPAM_RESERVEDAREA1_START)
-		return (address + len <= TPAM_RESERVEDAREA1_START) ? 0 : -1;
-
-	if (address <= TPAM_RESERVEDAREA1_END)
-		return -1;
-
-	if (address < TPAM_RESERVEDAREA2_START)
-		return (address + len <= TPAM_RESERVEDAREA2_START) ? 0 : -1;
-
-	if (address <= TPAM_RESERVEDAREA2_END)
-		return -1;
-
-	if (address < TPAM_RESERVEDAREA3_START)
-		return (address + len <= TPAM_RESERVEDAREA3_START) ? 0 : -1;
-
-	if (address <= TPAM_RESERVEDAREA3_END)
-		return -1;
-
-	if (address < TPAM_RESERVEDAREA4_START)
-		return (address + len <= TPAM_RESERVEDAREA4_START) ? 0 : -1;
-
-	if (address <= TPAM_RESERVEDAREA4_END)
-		return -1;
-
-	return 0;
-}
-
diff -Nru a/drivers/isdn/tpam/tpam_nco.c b/drivers/isdn/tpam/tpam_nco.c
--- a/drivers/isdn/tpam/tpam_nco.c	2005-03-11 12:51:41 -08:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,651 +0,0 @@
-/* $Id: tpam_nco.c,v 1.1.2.2 2001/09/23 22:25:03 kai Exp $
- *
- * Turbo PAM ISDN driver for Linux. 
- * (Kernel Driver - Low Level NCO Manipulation)
- *
- * Copyright 2001 Stelian Pop <stelian.pop@fr.alcove.com>, Alcôve
- *
- * This software may be used and distributed according to the terms
- * of the GNU General Public License, incorporated herein by reference.
- *
- * For all support questions please contact: <support@auvertech.fr>
- *
- */
-
-#include <linux/pci.h>
-#include <linux/sched.h>
-#include <linux/interrupt.h>
-#include <asm/io.h>
-
-#include "tpam.h"
-
-/* Local function prototypes */
-static struct sk_buff *build_NCOpacket(u16, u16, u16, u16, u16);
-static int extract_NCOParameter(struct sk_buff *, u8, void *, u16);
-
-/*
- * Build a NCO packet (PCI message).
- *
- * 	messageID: the message type (ID_*)
- * 	size: size of the TLV block
- * 	data_size: size of the data block
- * 	ack: packet needs to send ack upon send
- * 	ack_size: size of data to be acknowledged upon send
- *
- * Return: the sk_buff filled with the NCO packet, or NULL if error.
- */
-static struct sk_buff *build_NCOpacket(u16 messageID, u16 size, 
-				       u16 data_size, u16 ack, 
-				       u16 ack_size) {
-	struct sk_buff *skb;
-	skb_header *h;
-	pci_mpb *p;
-	u16 finalsize;
-
-	/* reserve enough space for the sk_buff header, the pci * header, 
-	 * size bytes for the TLV block, size bytes for the data and 4 more
-	 * bytes in order to make sure we can write dwords to the board. */
-	finalsize = sizeof(skb_header) + sizeof(pci_mpb) + size + data_size + 4;
-
-	/* allocate the sk_buff */
-	if (!(skb = alloc_skb(finalsize, GFP_ATOMIC))) {
-		printk(KERN_ERR "TurboPAM(make_NCOpacket): alloc_skb failed\n");
-		return NULL;
-	}
-
-	/* construct the skb_header */
-	h = (skb_header *)skb_put(skb, sizeof(skb_header));
-	h->size = sizeof(pci_mpb) + size;
-	h->data_size = data_size;
-	h->ack = ack;
-	h->ack_size = ack_size;
-
-	/* construct the pci_mpb */
-	p = (pci_mpb *)skb_put(skb, sizeof(pci_mpb));
-	p->exID = 0;
-	p->flags = 0;
-	p->errorCode = 0;
-	p->messageID = messageID;
-	p->maximumBlockTLVSize = MPB_MAXIMUMBLOCKTLVSIZE;
-	p->actualBlockTLVSize = size;
-	p->maximumDataSize = MPB_MAXIMUMDATASIZE;
-	p->actualDataSize = data_size;
-	return skb;
-}
-
-/*
- * Build a ACreateNCOReq message.
- *
- * 	phone: the local phone number.
- *
- * Return: the sk_buff filled with the NCO packet, or NULL if error.
- */
-struct sk_buff *build_ACreateNCOReq(const u8 *phone) {
-	struct sk_buff *skb;
-	u8 *tlv;
-
-	pr_debug("TurboPAM(build_ACreateNCOReq): phone=%s\n", phone);
-
-	/* build the NCO packet */
-	if (!(skb = build_NCOpacket(ID_ACreateNCOReq, 23 + strlen(phone), 0, 0, 0))) 
-		return NULL;
-
-	/* add the parameters */
-	tlv = (u8 *)skb_put(skb, 3);
-	*tlv = PAR_NCOType; 
-	*(tlv+1) = 1;
-	*(tlv+2) = 5;	/* mistery value... */
-
-	tlv = (u8 *)skb_put(skb, 4);
-	*tlv = PAR_U3Protocol;
-	*(tlv+1) = 2;
-	*(tlv+2) = 4;	/* no level 3 protocol */
-	*(tlv+3) = 1;	/* HDLC in level 2 */
-
-	tlv = (u8 *)skb_put(skb, 3);
-	*tlv = PAR_Cdirection;
-	*(tlv+1) = 1;
-	*(tlv+2) = 3; /* PCI_DIRECTION_BOTH */
-
-	tlv = (u8 *)skb_put(skb, 3);
-	*tlv = PAR_Udirection;
-	*(tlv+1) = 1;
-	*(tlv+2) = 3; /* PCI_DIRECTION_BOTH */
-
-	tlv = (u8 *)skb_put(skb, 4);
-	*tlv = PAR_BearerCap;
-	*(tlv+1) = 2;
-	*(tlv+2) = 0x88;
-	*(tlv+3) = 0x90;
-
-	tlv = (u8 *)skb_put(skb, 6 + strlen(phone));
-	*tlv = PAR_CallingNumber;
-	*(tlv+1) = strlen(phone) + 4;
-	*(tlv+2) = 0x01; /* international */
-	*(tlv+3) = 0x01; /* isdn */
-	*(tlv+4) = 0x00;
-	*(tlv+5) = 0x00;
-	memcpy(tlv + 6, phone, strlen(phone));
-
-	return skb;
-}
-
-/*
- * Build a ADestroyNCOReq message.
- *
- * 	ncoid: the NCO id.
- *
- * Return: the sk_buff filled with the NCO packet, or NULL if error.
- */
-struct sk_buff *build_ADestroyNCOReq(u32 ncoid) {
-	struct sk_buff *skb;
-	u8 *tlv;
-
-	pr_debug("TurboPAM(build_ADestroyNCOReq): ncoid=%lu\n",
-		(unsigned long)ncoid);
-
-	/* build the NCO packet */
-	if (!(skb = build_NCOpacket(ID_ADestroyNCOReq, 6, 0, 0, 0)))
-		return NULL;
-	
-	/* add the parameters */
-	tlv = (u8 *)skb_put(skb, 6);
-	*tlv = PAR_NCOID;
-	*(tlv+1) = 4;
-	*((u32 *)(tlv+2)) = ncoid;
-
-	return skb;
-}
-
-/*
- * Build a CConnectReq message.
- *
- * 	ncoid: the NCO id.
- * 	called: the destination phone number
- * 	hdlc: type of connection: 1 (HDLC) or 0(modem)
- *
- * Return: the sk_buff filled with the NCO packet, or NULL if error.
- */
-struct sk_buff *build_CConnectReq(u32 ncoid, const u8 *called, u8 hdlc) {
-	struct sk_buff *skb;
-	u8 *tlv;
-
-	pr_debug("TurboPAM(build_CConnectReq): ncoid=%lu, called=%s, hdlc=%d\n",
-		(unsigned long)ncoid, called, hdlc);
-
-	/* build the NCO packet */
-	if (!(skb = build_NCOpacket(ID_CConnectReq, 20 + strlen(called), 0, 0, 0)))
-		return NULL;
-	
-	/* add the parameters */
-	tlv = (u8 *)skb_put(skb, 6);
-	*tlv = PAR_NCOID;
-	*(tlv+1) = 4;
-	*((u32 *)(tlv+2)) = ncoid;
-
-	tlv = (u8 *)skb_put(skb, 4 + strlen(called));
-	*tlv = PAR_CalledNumber;
-	*(tlv+1) = strlen(called) + 2;
-	*(tlv+2) = 0x01; /* international */
-	*(tlv+3) = 0x01; /* isdn */
-	memcpy(tlv + 4, called, strlen(called));
-
-	tlv = (u8 *)skb_put(skb, 3);
-	*tlv = PAR_BearerCap;
-	*(tlv+1) = 1;
-	*(tlv+2) = hdlc ? 0x88 /* HDLC */ : 0x80 /* MODEM */;
-
-	tlv = (u8 *)skb_put(skb, 4);
-	*tlv = PAR_HLC;
-	*(tlv+1) = 2;
-	*(tlv+2) = 0x2;
-	*(tlv+3) = 0x7f;
-
-	tlv = (u8 *)skb_put(skb, 3);
-	*tlv = PAR_Facility;
-	*(tlv+1) = 1;
-	*(tlv+2) = 2;
-
-	return skb;
-}
-
-/*
- * Build a CConnectRsp message.
- *
- * 	ncoid: the NCO id.
- *
- * Return: the sk_buff filled with the NCO packet, or NULL if error.
- */
-struct sk_buff *build_CConnectRsp(u32 ncoid) {
-	struct sk_buff *skb;
-	u8 *tlv;
-
-	pr_debug("TurboPAM(build_CConnectRsp): ncoid=%lu\n",
-		(unsigned long)ncoid);
-
-	/* build the NCO packet */
-	if (!(skb = build_NCOpacket(ID_CConnectRsp, 6, 0, 0, 0)))
-		return NULL;
-
-	/* add the parameters */
-	tlv = (u8 *)skb_put(skb, 6);
-	*tlv = PAR_NCOID;
-	*(tlv+1) = 4;
-	*((u32 *)(tlv+2)) = ncoid;
-
-	return skb;
-}
-
-/*
- * Build a CDisconnectReq message.
- *
- * 	ncoid: the NCO id.
- *
- * Return: the sk_buff filled with the NCO packet, or NULL if error.
- */
-struct sk_buff *build_CDisconnectReq(u32 ncoid) {
-	struct sk_buff *skb;
-	u8 *tlv;
-
-	pr_debug("TurboPAM(build_CDisconnectReq): ncoid=%lu\n",
-		(unsigned long)ncoid);
-
-	/* build the NCO packet */
-	if (!(skb = build_NCOpacket(ID_CDisconnectReq, 6, 0, 0, 0)))
-		return NULL;
-
-	/* add the parameters */
-	tlv = (u8 *)skb_put(skb, 6);
-	*tlv = PAR_NCOID;
-	*(tlv+1) = 4;
-	*((u32 *)(tlv+2)) = ncoid;
-
-	return skb;
-}
-
-/*
- * Build a CDisconnectRsp message.
- *
- * 	ncoid: the NCO id.
- *
- * Return: the sk_buff filled with the NCO packet, or NULL if error.
- */
-struct sk_buff *build_CDisconnectRsp(u32 ncoid) {
-	struct sk_buff *skb;
-	u8 *tlv;
-
-	pr_debug("TurboPAM(build_CDisconnectRsp): ncoid=%lu\n",
-		(unsigned long)ncoid);
-
-	/* build the NCO packet */
-	if (!(skb = build_NCOpacket(ID_CDisconnectRsp, 6, 0, 0, 0)))
-		return NULL;
-
-	/* add the parameters */
-	tlv = (u8 *)skb_put(skb, 6);
-	*tlv = PAR_NCOID;
-	*(tlv+1) = 4;
-	*((u32 *)(tlv+2)) = ncoid;
-
-	return skb;
-}
-
-/*
- * Build a U3DataReq message.
- *
- * 	ncoid: the NCO id.
- * 	data: the data to be send
- * 	len: length of the data
- * 	ack: send ack upon send
- * 	ack_size: size of data to be acknowledged upon send
- *
- * Return: the sk_buff filled with the NCO packet, or NULL if error.
- */
-struct sk_buff *build_U3DataReq(u32 ncoid, void *data, u16 len,
-				u16 ack, u16 ack_size) {
-	struct sk_buff *skb;
-	u8 *tlv;
-	void *p;
-
-	pr_debug("TurboPAM(build_U3DataReq): "
-		"ncoid=%lu, len=%d, ack=%d, ack_size=%d\n", 
-		(unsigned long)ncoid, len, ack, ack_size);
-
-	/* build the NCO packet */
-	if (!(skb = build_NCOpacket(ID_U3DataReq, 6, len, ack, ack_size)))
-		return NULL;
-
-	/* add the parameters */
-	tlv = (u8 *)skb_put(skb, 6);
-	*tlv = PAR_NCOID;
-	*(tlv+1) = 4;
-	*((u32 *)(tlv+2)) = ncoid;
-
-	p = skb_put(skb, len);
-	memcpy(p, data, len);
-
-	return skb;
-}
-
-/*
- * Extract a parameter from a TLV block.
- *
- * 	skb: sk_buff containing the PCI message
- * 	type: parameter to search for (PARAM_*)
- * 	value: to be filled with the value of the parameter
- * 	len: maximum length of the parameter value
- *
- * Return: 0 if OK, <0 if error.
- */
-static int extract_NCOParameter(struct sk_buff *skb, u8 type, 
-				void *value, u16 len) {
-	void *buffer = (void *)skb->data;
-	pci_mpb *p;
-	void * bufferend;
-	u8 valtype;
-	u16 vallen;
-
-	/* calculate the start and end of the TLV block */
-	buffer += sizeof(skb_header);
-	p = (pci_mpb *)buffer;
-	buffer += sizeof(pci_mpb);
-	bufferend = buffer + p->actualBlockTLVSize;
-
-	/* walk through the parameters */
-	while (buffer < bufferend) {
-
-		/* parameter type */
-		valtype = *((u8 *)buffer++);
-		/* parameter length */
-		vallen = *((u8 *)buffer++);
-		if (vallen == 0xff) {
-			/* parameter length is on 2 bytes */
-			vallen = *((u8 *)buffer++);
-			vallen <<= 8;
-			vallen |= *((u8 *)buffer++);
-		}
-		/* got the right parameter */
-		if (valtype == type) {
-			/* not enough space for returning the value */
-			if (vallen > len)
-				return -1;
-			/* OK, return it */
-			memcpy(value, buffer, vallen);
-			return 0;
-		}
-		buffer += vallen;
-	}
-	return -1;
-}
-
-/*
- * Parse a ACreateNCOCnf message.
- *
- * 	skb: the sk_buff containing the message
- * 	status: to be filled with the status field value
- * 	ncoid: to be filled with the ncoid field value
- *
- * Return: 0 if OK, <0 if error.
- */
-int parse_ACreateNCOCnf(struct sk_buff *skb, u8 *status, u32 *ncoid) {
-
-	/* extract the status */
-	if (extract_NCOParameter(skb, PAR_CompletionStatus, status, 1)) {
-		printk(KERN_ERR "TurboPAM(parse_ACreateNCOCnf): "
-		       "CompletionStatus not found\n");
-		return -1;
-	}
-
-	if (*status) {
-		pr_debug("TurboPAM(parse_ACreateNCOCnf): status=%d\n", *status);
-		return 0;
-	}
-
-	/* extract the ncoid */
-	if (extract_NCOParameter(skb, PAR_NCOID, ncoid, 4)) {
-		printk(KERN_ERR "TurboPAM(parse_ACreateNCOCnf): "
-		       "NCOID not found\n");
-		return -1;
-	}
-
-	pr_debug("TurboPAM(parse_ACreateNCOCnf): ncoid=%lu, status=%d\n",
-		(unsigned long)*ncoid, *status);
-	return 0;
-}
-
-/*
- * Parse a ADestroyNCOCnf message. Not used in the driver.
- *
- * 	skb: the sk_buff containing the message
- * 	status: to be filled with the status field value
- * 	ncoid: to be filled with the ncoid field value
- *
- * Return: 0 if OK, <0 if error.
- */
-int parse_ADestroyNCOCnf(struct sk_buff *skb, u8 *status, u32 *ncoid) {
-
-	/* extract the status */
-	if (extract_NCOParameter(skb, PAR_CompletionStatus, status, 1)) {
-		printk(KERN_ERR "TurboPAM(parse_ADestroyNCOCnf): "
-		       "CompletionStatus not found\n");
-		return -1;
-	}
-
-	if (*status) {
-		pr_debug("TurboPAM(parse_ADestroyNCOCnf): status=%d\n", *status);
-		return 0;
-	}
-
-	/* extract the ncoid */
-	if (extract_NCOParameter(skb, PAR_NCOID, ncoid, 4)) {
-		printk(KERN_ERR "TurboPAM(parse_ADestroyNCOCnf): "
-		       "NCOID not found\n");
-		return -1;
-	}
-
-	pr_debug("TurboPAM(parse_ADestroyNCOCnf): ncoid=%lu, status=%d\n",
-		(unsigned long)*ncoid, *status);
-	return 0;
-}
-
-/*
- * Parse a CConnectCnf message.
- *
- * 	skb: the sk_buff containing the message
- * 	ncoid: to be filled with the ncoid field value
- *
- * Return: 0 if OK, <0 if error.
- */
-int parse_CConnectCnf(struct sk_buff *skb, u32 *ncoid) {
-
-	/* extract the ncoid */
-	if (extract_NCOParameter(skb, PAR_NCOID, ncoid, 4)) {
-		printk(KERN_ERR "TurboPAM(parse_CConnectCnf): "
-		       "NCOID not found\n");
-		return -1;
-	}
-	pr_debug("TurboPAM(parse_CConnectCnf): ncoid=%lu\n",
-		(unsigned long)*ncoid);
-	return 0;
-}
-
-/*
- * Parse a CConnectInd message.
- *
- * 	skb: the sk_buff containing the message
- * 	ncoid: to be filled with the ncoid field value
- * 	hdlc: to be filled with 1 if the incoming connection is a HDLC one,
- * 		with 0 if the incoming connection is a modem one
- * 	calling: to be filled with the calling phone number value
- * 	called: to be filled with the called phone number value
- * 	plan: to be filled with the plan value
- * 	screen: to be filled with the screen value
- *
- * Return: 0 if OK, <0 if error.
- */
-int parse_CConnectInd(struct sk_buff *skb, u32 *ncoid, u8 *hdlc, 
-		      u8 *calling, u8 *called, u8 *plan, u8 *screen) {
-	u8 phone[PHONE_MAXIMUMSIZE + 4];
-
-	/* extract the ncoid */
-	if (extract_NCOParameter(skb, PAR_NCOID, ncoid, 4)) {
-		printk(KERN_ERR "TurboPAM(parse_CConnectInd): "
-		       "NCOID not found\n");
-		return -1;
-	}
-
-	/* extract the bearer capability field */
-	if (extract_NCOParameter(skb, PAR_BearerCap, hdlc, 1)) {
-		printk(KERN_ERR "TurboPAM(parse_CConnectInd): "
-		       "BearerCap not found\n");
-		return -1;
-	}
-	*hdlc = (*hdlc == 0x88) ? 1 : 0;
-
-	/* extract the calling number / plan / screen */
-	if (extract_NCOParameter(skb, PAR_CallingNumber, phone, 
-				 PHONE_MAXIMUMSIZE + 4)) {
-		printk(KERN_ERR "TurboPAM(parse_CConnectInd): "
-		       "CallingNumber not found\n");
-		return -1;
-	}
-	memcpy(calling, phone + 4, PHONE_MAXIMUMSIZE);
-	*plan = phone[1];
-	*screen = phone[3];
-
-	/* extract the called number */
-	if (extract_NCOParameter(skb, PAR_CalledNumber, phone, 
-				 PHONE_MAXIMUMSIZE + 2)) {
-		printk(KERN_ERR "TurboPAM(parse_CConnectInd): "
-		       "CalledNumber not found\n");
-		return -1;
-	}
-	memcpy(called, phone + 2, PHONE_MAXIMUMSIZE);
-
-	pr_debug("TurboPAM(parse_CConnectInd): "
-		"ncoid=%lu, hdlc=%d, plan=%d, scr=%d, calling=%s, called=%s\n",
-		(unsigned long)*ncoid, *hdlc, *plan, *screen, calling, called);
-	return 0;
-}
-
-/*
- * Parse a CDisconnectCnf message.
- *
- * 	skb: the sk_buff containing the message
- * 	ncoid: to be filled with the ncoid field value
- * 	causetopuf: to be filled with the cause field value
- *
- * Return: 0 if OK, <0 if error.
- */
-int parse_CDisconnectCnf(struct sk_buff *skb, u32 *ncoid, u32 *causetopuf) {
-
-	/* extract the ncoid */
-	if (extract_NCOParameter(skb, PAR_NCOID, ncoid, 4)) {
-		printk(KERN_ERR "TurboPAM(parse_CDisconnectCnf): "
-		       "NCOID not found\n");
-		return -1;
-	}
-
-	/* extract the cause of disconnection */
-	if (extract_NCOParameter(skb, PAR_CauseToPUF, causetopuf, 4)) {
-		printk(KERN_ERR "TurboPAM(parse_CDisconnectCnf): "
-		       "CauseToPUF not found\n");
-		return -1;
-	}
-
-	pr_debug("TurboPAM(parse_CDisconnectCnf): ncoid=%lu, causetopuf=%lu\n",
-		(unsigned long)*ncoid, (unsigned long)*causetopuf);
-	return 0;
-}
-
-/*
- * Parse a CDisconnectInd message.
- *
- * 	skb: the sk_buff containing the message
- * 	ncoid: to be filled with the ncoid field value
- * 	causetopuf: to be filled with the cause field value
- *
- * Return: 0 if OK, <0 if error.
- */
-int parse_CDisconnectInd(struct sk_buff *skb, u32 *ncoid, u32 *causetopuf) {
-
-	/* extract the ncoid */
-	if (extract_NCOParameter(skb, PAR_NCOID, ncoid, 4)) {
-		printk(KERN_ERR "TurboPAM(parse_CDisconnectInd): "
-		       "NCOID not found\n");
-		return -1;
-	}
-
-	/* extract the cause of disconnection */
-	if (extract_NCOParameter(skb, PAR_CauseToPUF, causetopuf, 4)) {
-		printk(KERN_ERR "TurboPAM(parse_CDisconnectInd): "
-		       "CauseToPUF not found\n");
-		return -1;
-	}
-
-	pr_debug("TurboPAM(parse_CDisconnectInd): ncoid=%lu, causetopuf=%lu\n",
-		(unsigned long)*ncoid, (unsigned long)*causetopuf);
-	return 0;
-}
-
-/*
- * Parse a U3ReadyToReceiveInd message.
- *
- * 	skb: the sk_buff containing the message
- * 	ncoid: to be filled with the ncoid field value
- * 	ready: to be filled with the ready field value
- *
- * Return: 0 if OK, <0 if error.
- */
-int parse_U3ReadyToReceiveInd(struct sk_buff *skb, u32 *ncoid, u8 *ready) {
-
-	/* extract the ncoid */
-	if (extract_NCOParameter(skb, PAR_NCOID, ncoid, 4)) {
-		printk(KERN_ERR "TurboPAM(parse_U3ReadyToReceiveInd): "
-		       "NCOID not found\n");
-		return -1;
-	}
-
-	/* extract the ready flag */
-	if (extract_NCOParameter(skb, PAR_ReadyFlag, ready, 1)) {
-		printk(KERN_ERR "TurboPAM(parse_U3ReadyToReceiveInd): "
-		       "ReadyFlag not found\n");
-		return -1;
-	}
-
-	pr_debug("TurboPAM(parse_U3ReadyToReceiveInd): ncoid=%lu, ready=%d\n",
-		(unsigned long)*ncoid, *ready);
-	return 0;
-}
-
-/*
- * Parse a U3DataInd message.
- *
- * 	skb: the sk_buff containing the message + data
- * 	ncoid: to be filled with the ncoid field value
- * 	data: to be filled with the data 
- * 	ready: to be filled with the data length
- *
- * Return: 0 if OK, <0 if error.
- */
-int parse_U3DataInd(struct sk_buff *skb, u32 *ncoid, u8 **data, u16 *len) {
-	pci_mpb *p;
-
-	/* extract the ncoid */
-	if (extract_NCOParameter(skb, PAR_NCOID, ncoid, 4) == -1) {
-		printk(KERN_ERR "TurboPAM(parse_U3DataInd): NCOID not found\n");
-		return -1;
-	}
-
-	/* get a pointer to the beginning of the data block and its length */
-	p = (pci_mpb *)(skb->data + sizeof(skb_header));
-	*len = p->actualDataSize;
-	skb_pull(skb, 
-		 sizeof(skb_header) + sizeof(pci_mpb) + p->actualBlockTLVSize);
-	*data = skb->data;
-
-	pr_debug("TurboPAM(parse_U3DataInd): ncoid=%lu, datalen=%d\n",
-		(unsigned long)*ncoid, *len);
-	return 0;
-}
-
diff -Nru a/drivers/isdn/tpam/tpam_queues.c b/drivers/isdn/tpam/tpam_queues.c
--- a/drivers/isdn/tpam/tpam_queues.c	2005-03-11 12:51:52 -08:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,401 +0,0 @@
-/* $Id: tpam_queues.c,v 1.1.2.2 2001/09/23 22:25:03 kai Exp $
- *
- * Turbo PAM ISDN driver for Linux. (Kernel Driver)
- *
- * Copyright 2001 Stelian Pop <stelian.pop@fr.alcove.com>, Alcôve
- *
- * This software may be used and distributed according to the terms
- * of the GNU General Public License, incorporated herein by reference.
- *
- * For all support questions please contact: <support@auvertech.fr>
- *
- */
-
-#include <linux/pci.h>
-#include <linux/sched.h>
-#include <linux/workqueue.h>
-#include <linux/interrupt.h>
-#include <asm/io.h>
-
-#include "tpam.h"
-
-/* Local function prototype */
-static int tpam_sendpacket(tpam_card *card, tpam_channel *channel);
-
-/*
- * Queue a message to be send to the card when possible.
- *
- * 	card: the board
- * 	skb: the sk_buff containing the message.
- */
-void tpam_enqueue(tpam_card *card, struct sk_buff *skb) {
-
-	pr_debug("TurboPAM(tpam_enqueue): card=%d\n", card->id);
-
-	/* queue the sk_buff on the board's send queue */
-	skb_queue_tail(&card->sendq, skb);
-
-	/* queue the board's send task struct for immediate treatment */
-	schedule_work(&card->send_tq);
-}
-
-/*
- * Queue a data message to be send to the card when possible.
- *
- * 	card: the board
- * 	skb: the sk_buff containing the message and the data. This parameter
- * 		can be NULL if we want just to trigger the send of queued 
- * 		messages.
- */
-void tpam_enqueue_data(tpam_channel *channel, struct sk_buff *skb) {
-	
-	pr_debug("TurboPAM(tpam_enqueue_data): card=%d, channel=%d\n",
-		channel->card->id, channel->num);
-
-	/* if existant, queue the sk_buff on the channel's send queue */
-	if (skb)
-		skb_queue_tail(&channel->sendq, skb);
-
-	/* queue the channel's send task struct for immediate treatment */
-	schedule_work(&channel->card->send_tq);
-}
-
-/*
- * IRQ handler.
- *
- * If a message comes from the board we read it, construct a sk_buff containing
- * the message and we queue the sk_buff on the board's receive queue, and we
- * trigger the execution of the board's receive task queue.
- *
- * If a message ack comes from the board we can go on and send a new message,
- * so we trigger the execution of the board's send task queue.
- *
- * 	irq: the irq number
- * 	dev_id: the registered board to the irq
- * 	regs: not used.
- */
-irqreturn_t tpam_irq(int irq, void *dev_id, struct pt_regs *regs)
-{
-	tpam_card *card = (tpam_card *)dev_id;
-	u32 ackupload, uploadptr;
-	u32 waiting_too_long;
-	u32 hpic;
-	struct sk_buff *skb;
-	pci_mpb mpb;
-	skb_header *skbh;
-
-	pr_debug("TurboPAM(tpam_irq): IRQ received, card=%d\n", card->id);
-
-	/* grab the board lock */
-	spin_lock(&card->lock);
-
-	/* get the message type */
-	ackupload = copy_from_pam_dword(card, TPAM_ACKUPLOAD_REGISTER);
-
-	/* acknowledge the interrupt */
-	copy_to_pam_dword(card, TPAM_INTERRUPTACK_REGISTER, 0);
-	readl(card->bar0 + TPAM_HINTACK_REGISTER);
-
-	if (!ackupload) {
-		/* it is a new message from the board */
-		
-		pr_debug("TurboPAM(tpam_irq): message received, card=%d\n",
-			card->id);
-
-		/* get the upload pointer */
-		uploadptr = copy_from_pam_dword(card, 
-					    TPAM_UPLOADPTR_REGISTER);
-		
-		/* get the beginning of the message (pci_mpb part) */
-		copy_from_pam(card, &mpb, uploadptr, sizeof(pci_mpb));
-
-		/* allocate the sk_buff */
-		if (!(skb = alloc_skb(sizeof(skb_header) + sizeof(pci_mpb) + 
-				      mpb.actualBlockTLVSize + 
-				      mpb.actualDataSize, GFP_ATOMIC))) {
-			printk(KERN_ERR "TurboPAM(tpam_irq): "
-			       "alloc_skb failed\n");
-			spin_unlock(&card->lock);
-			return IRQ_HANDLED;
-		}
-
-		/* build the skb_header */
-		skbh = (skb_header *)skb_put(skb, sizeof(skb_header));
-		skbh->size = sizeof(pci_mpb) + mpb.actualBlockTLVSize;
-		skbh->data_size = mpb.actualDataSize;
-		skbh->ack = 0;
-		skbh->ack_size = 0;
-
-		/* copy the pci_mpb into the sk_buff */
-		memcpy(skb_put(skb, sizeof(pci_mpb)), &mpb, sizeof(pci_mpb));
-
-		/* copy the TLV block into the sk_buff */
-		copy_from_pam(card, skb_put(skb, mpb.actualBlockTLVSize),
-			      uploadptr + sizeof(pci_mpb), 
-			      mpb.actualBlockTLVSize);
-
-		/* if existent, copy the data block into the sk_buff */
-		if (mpb.actualDataSize)
-			copy_from_pam(card, skb_put(skb, mpb.actualDataSize),
-				uploadptr + sizeof(pci_mpb) + 4096, 
-				mpb.actualDataSize);
-
-		/* wait for the board to become ready */
-		waiting_too_long = 0;
-		do {
-			hpic = readl(card->bar0 + TPAM_HPIC_REGISTER);
-			if (waiting_too_long++ > 0xfffffff) {
-				kfree_skb(skb); 
-				spin_unlock(&card->lock);
-				printk(KERN_ERR "TurboPAM(tpam_irq): "
-						"waiting too long...\n");
-				return IRQ_HANDLED;
-			}
-		} while (hpic & 0x00000002);
-
-		/* acknowledge the message */
-        	copy_to_pam_dword(card, TPAM_ACKDOWNLOAD_REGISTER, 
-				  0xffffffff);
-        	readl(card->bar0 + TPAM_DSPINT_REGISTER);
-
-		/* release the board lock */
-		spin_unlock(&card->lock);
-	
-		if (mpb.messageID == ID_U3ReadyToReceiveInd) {
-			/* this message needs immediate treatment */
-			tpam_recv_U3ReadyToReceiveInd(card, skb);
-			kfree_skb(skb);
-		}
-		else {
-			/* put the message in the receive queue */
-			skb_queue_tail(&card->recvq, skb);
-			schedule_work(&card->recv_tq);
-		}
-		return IRQ_HANDLED;
-	}
-	else {
-		/* it is a ack from the board */
-
-		pr_debug("TurboPAM(tpam_irq): message acknowledged, card=%d\n",
-			card->id);
-
-		/* board is not busy anymore */
-		card->busy = 0;
-		
-		/* release the lock */
-		spin_unlock(&card->lock);
-
-		/* schedule the send queue for execution */
-		schedule_work(&card->send_tq);
-	}
-	return IRQ_HANDLED;
-}
-
-/*
- * Run the board's receive task queue, dispatching each message on the queue,
- * to its treatment function.
- *
- * 	card: the board.
- */
-void tpam_recv_tq(tpam_card *card) {
-	pci_mpb *p;
-	struct sk_buff *skb;
-
-	/* for each message on the receive queue... */
-        while ((skb = skb_dequeue(&card->recvq))) {
-
-		/* point to the pci_mpb block */
-		p = (pci_mpb *)(skb->data + sizeof(skb_header));
-
-		/* dispatch the message */
-		switch (p->messageID) {
-			case ID_ACreateNCOCnf:
-				tpam_recv_ACreateNCOCnf(card, skb);
-				break;
-			case ID_ADestroyNCOCnf:
-				tpam_recv_ADestroyNCOCnf(card, skb);
-				break;
-			case ID_CConnectCnf:
-				tpam_recv_CConnectCnf(card, skb);
-				break;
-			case ID_CConnectInd:
-				tpam_recv_CConnectInd(card, skb);
-				break;
-			case ID_CDisconnectInd:
-				tpam_recv_CDisconnectInd(card, skb);
-				break;
-			case ID_CDisconnectCnf:
-				tpam_recv_CDisconnectCnf(card, skb);
-				break;
-			case ID_U3DataInd:
-				tpam_recv_U3DataInd(card, skb);
-				break;
-			default:
-				pr_debug("TurboPAM(tpam_recv_tq): "
-					"unknown messageID %d, card=%d\n", 
-					p->messageID, card->id);
-				break;
-		}
-		/* free the sk_buff */
-		kfree_skb(skb);
-	}
-}
-
-/*
- * Run the board's send task queue. If there is a message in the board's send
- * queue, it gets sended. If not, it examines each channel (one at the time,
- * using a round robin algorithm). For each channel, if there is a message
- * in the channel's send queue, it gets sended. This function sends only one
- * message, it does not consume all the queue.
- */
-void tpam_send_tq(tpam_card *card) {
-	int i;
-
-	/* first, try to send a packet from the board's send queue */
-	if (tpam_sendpacket(card, NULL))
-		return;
-
-	/* then, try each channel, in a round-robin manner */
-	for (i=card->roundrobin; i<card->roundrobin+card->channels_used; i++) {
-		if (tpam_sendpacket(card, 
-				    &card->channels[i % card->channels_used])) {
-			card->roundrobin = (i + 1) % card->channels_used;
-			return;
-		}
-	}
-}
-
-/*
- * Try to send a packet from the board's send queue or from the channel's
- * send queue.
- *
- * 	card: the board.
- * 	channel: the channel (if NULL, the packet will be taken from the 
- * 		board's send queue. If not, it will be taken from the 
- * 		channel's send queue.
- *
- * Return: 0 if tpam_send_tq must try another card/channel combination
- * 	(meaning that no packet has been send), 1 if no more packets
- * 	can be send at that time (a packet has been send or the card is
- * 	still busy from a previous send).
- */
-static int tpam_sendpacket(tpam_card *card, tpam_channel *channel) {
-        struct sk_buff *skb;
-	u32 hpic;
-        u32 downloadptr;
-	skb_header *skbh;
-	u32 waiting_too_long;
-
-	pr_debug("TurboPAM(tpam_sendpacket), card=%d, channel=%d\n",
-		card->id, channel ? channel->num : -1);
-
-	if (channel) {
-		/* dequeue a packet from the channel's send queue */
-		if (!(skb = skb_dequeue(&channel->sendq))) {
-			pr_debug("TurboPAM(tpam_sendpacket): "
-				"card=%d, channel=%d, no packet\n", 
-				card->id, channel->num);
-			return 0;
-		}
-
-		/* if the channel is not ready to receive, requeue the packet
-		 * and return 0 to give a chance to another channel */
-		if (!channel->readytoreceive) {
-			pr_debug("TurboPAM(tpam_sendpacket): "
-				"card=%d, channel=%d, channel not ready\n",
-				card->id, channel->num);
-			skb_queue_head(&channel->sendq, skb);
-			return 0;
-		}
-
-		/* grab the board lock */
-		spin_lock_irq(&card->lock);
-
-		/* if the board is busy, requeue the packet and return 1 since
-		 * there is no need to try another channel */
-		if (card->busy) {
-			pr_debug("TurboPAM(tpam_sendpacket): "
-				"card=%d, channel=%d, card busy\n",
-				card->id, channel->num);
-			skb_queue_head(&channel->sendq, skb);
-			spin_unlock_irq(&card->lock);
-			return 1;
-		}
-	}
-	else {
-		/* dequeue a packet from the board's send queue */
-		if (!(skb = skb_dequeue(&card->sendq))) {
-			pr_debug("TurboPAM(tpam_sendpacket): "
-				"card=%d, no packet\n", card->id);
-			return 0;
-		}
-
-		/* grab the board lock */
-		spin_lock_irq(&card->lock);
-
-		/* if the board is busy, requeue the packet and return 1 since
-		 * there is no need to try another channel */
-		if (card->busy) {
-			pr_debug("TurboPAM(tpam_sendpacket): "
-				"card=%d, card busy\n", card->id);
-			skb_queue_head(&card->sendq, skb);
-			spin_unlock_irq(&card->lock);
-			return 1;
-		}
-	}
-
-	/* wait for the board to become ready */
-	waiting_too_long = 0;
-	do {
-		hpic = readl(card->bar0 + TPAM_HPIC_REGISTER);
-		if (waiting_too_long++ > 0xfffffff) {
-			spin_unlock_irq(&card->lock);
-			printk(KERN_ERR "TurboPAM(tpam_sendpacket): "
-					"waiting too long...\n");
-			return 1;
-		}
-	} while (hpic & 0x00000002);
-
-	skbh = (skb_header *)skb->data;
-	pr_debug("TurboPAM(tpam_sendpacket): "
-		"card=%d, card ready, sending %d/%d bytes\n", 
-		card->id, skbh->size, skbh->data_size);
-
-	/* get the board's download pointer */
-       	downloadptr = copy_from_pam_dword(card, TPAM_DOWNLOADPTR_REGISTER);
-
-	/* copy the packet to the board at the downloadptr location */
-       	copy_to_pam(card, downloadptr, skb->data + sizeof(skb_header), 
-		    skbh->size);
-	if (skbh->data_size)
-		/* if there is some data in the packet, copy it too */
-		copy_to_pam(card, downloadptr + sizeof(pci_mpb) + 4096,
-			    skb->data + sizeof(skb_header) + skbh->size, 
-			    skbh->data_size);
-
-	/* card will become busy right now */
-	card->busy = 1;
-
-	/* interrupt the board */
-	copy_to_pam_dword(card, TPAM_ACKDOWNLOAD_REGISTER, 0);
-	readl(card->bar0 + TPAM_DSPINT_REGISTER);
-
-	/* release the lock */
-	spin_unlock_irq(&card->lock);
-
-	/* if a data ack was requested by the ISDN link layer, send it now */
-	if (skbh->ack) {
-		isdn_ctrl ctrl;
-		ctrl.driver = card->id;
-		ctrl.command = ISDN_STAT_BSENT;
-		ctrl.arg = channel->num;
-		ctrl.parm.length = skbh->ack_size;
-		(* card->interface.statcallb)(&ctrl);
-	}
-
-	/* free the sk_buff */
-	kfree_skb(skb);
-
-	return 1;
-}
-
diff -Nru a/drivers/macintosh/macserial.c b/drivers/macintosh/macserial.c
--- a/drivers/macintosh/macserial.c	2005-03-11 12:51:51 -08:00
+++ b/drivers/macintosh/macserial.c	2005-03-11 12:51:51 -08:00
@@ -155,7 +155,7 @@
 static irqreturn_t rs_txdma_irq(int irq, void *dev_id, struct pt_regs *regs);
 static irqreturn_t rs_rxdma_irq(int irq, void *dev_id, struct pt_regs *regs);
 static void dma_init(struct mac_serial * info);
-static void rxdma_start(struct mac_serial * info, int current);
+static void rxdma_start(struct mac_serial * info, int curr);
 static void rxdma_to_tty(struct mac_serial * info);
 
 /*
@@ -762,10 +762,10 @@
 	return 0;
 }
 
-static _INLINE_ void rxdma_start(struct mac_serial * info, int current)
+static _INLINE_ void rxdma_start(struct mac_serial * info, int curr)
 {
 	volatile struct dbdma_regs *rd = &info->rx->dma;
-	volatile struct dbdma_cmd *cd = info->rx_cmds[current];
+	volatile struct dbdma_cmd *cd = info->rx_cmds[curr];
 
 //printk(KERN_DEBUG "SCC: rxdma_start\n");
 
diff -Nru a/drivers/macintosh/therm_adt746x.c b/drivers/macintosh/therm_adt746x.c
--- a/drivers/macintosh/therm_adt746x.c	2005-03-11 12:51:50 -08:00
+++ b/drivers/macintosh/therm_adt746x.c	2005-03-11 12:51:50 -08:00
@@ -548,7 +548,15 @@
 	prop = (u32 *)get_property(np, "reg", NULL);
 	if (!prop)
 		return -ENODEV;
-	therm_bus = ((*prop) >> 8) & 0x0f;
+
+	/* look for bus either by path or using "reg" */
+	if (strstr(np->full_name, "/i2c-bus@") != NULL) {
+		const char *tmp_bus = (strstr(np->full_name, "/i2c-bus@") + 9);
+		therm_bus = tmp_bus[0]-'0';
+	} else {
+		therm_bus = ((*prop) >> 8) & 0x0f;
+	}
+
 	therm_address = ((*prop) & 0xff) >> 1;
 
 	printk(KERN_INFO "adt746x: Thermostat bus: %d, address: 0x%02x, "
diff -Nru a/drivers/macintosh/therm_windtunnel.c b/drivers/macintosh/therm_windtunnel.c
--- a/drivers/macintosh/therm_windtunnel.c	2005-03-11 12:51:47 -08:00
+++ b/drivers/macintosh/therm_windtunnel.c	2005-03-11 12:51:47 -08:00
@@ -47,8 +47,6 @@
 #define LOG_TEMP		0			/* continously log temperature */
 
 #define I2C_DRIVERID_G4FAN	0x9001			/* fixme */
-#define THERMOSTAT_CLIENT_ID	1
-#define FAN_CLIENT_ID		2
 
 static int 			do_probe( struct i2c_adapter *adapter, int addr, int kind);
 
@@ -372,7 +370,6 @@
 		goto out;
 	printk("ADM1030 fan controller [@%02x]\n", cl->addr );
 
-	cl->id = FAN_CLIENT_ID;
 	strlcpy( cl->name, "ADM1030 fan controller", sizeof(cl->name) );
 
 	if( !i2c_attach_client(cl) )
@@ -412,7 +409,6 @@
 	x.overheat_temp = os_temp;
 	x.overheat_hyst = hyst_temp;
 	
-	cl->id = THERMOSTAT_CLIENT_ID;
 	strlcpy( cl->name, "DS1775 thermostat", sizeof(cl->name) );
 
 	if( !i2c_attach_client(cl) )
diff -Nru a/drivers/macintosh/via-pmu.c b/drivers/macintosh/via-pmu.c
--- a/drivers/macintosh/via-pmu.c	2005-03-11 12:51:51 -08:00
+++ b/drivers/macintosh/via-pmu.c	2005-03-11 12:51:51 -08:00
@@ -2389,7 +2389,7 @@
 	enable_kernel_fp();
 
 #ifdef CONFIG_ALTIVEC
-	if (cur_cpu_spec[0]->cpu_features & CPU_FTR_ALTIVEC)
+	if (cpu_has_feature(CPU_FTR_ALTIVEC))
 		enable_kernel_altivec();
 #endif /* CONFIG_ALTIVEC */
 
diff -Nru a/drivers/md/Kconfig b/drivers/md/Kconfig
--- a/drivers/md/Kconfig	2005-03-11 12:51:41 -08:00
+++ b/drivers/md/Kconfig	2005-03-11 12:51:41 -08:00
@@ -227,5 +227,17 @@
 	  A target that discards writes, and returns all zeroes for
 	  reads.  Useful in some recovery situations.
 
+config DM_MULTIPATH
+	tristate "Multipath target (EXPERIMENTAL)"
+	depends on BLK_DEV_DM && EXPERIMENTAL
+	---help---
+	  Allow volume managers to support multipath hardware.
+
+config DM_MULTIPATH_EMC
+	tristate "EMC CX/AX multipath support (EXPERIMENTAL)"
+	depends on DM_MULTIPATH && BLK_DEV_DM && EXPERIMENTAL
+	---help---
+	  Multipath support for EMC CX/AX series hardware.
+
 endmenu
 
diff -Nru a/drivers/md/Makefile b/drivers/md/Makefile
--- a/drivers/md/Makefile	2005-03-11 12:51:46 -08:00
+++ b/drivers/md/Makefile	2005-03-11 12:51:46 -08:00
@@ -4,6 +4,7 @@
 
 dm-mod-objs	:= dm.o dm-table.o dm-target.o dm-linear.o dm-stripe.o \
 		   dm-ioctl.o dm-io.o kcopyd.o
+dm-multipath-objs := dm-hw-handler.o dm-path-selector.o dm-mpath.o
 dm-snapshot-objs := dm-snap.o dm-exception-store.o
 dm-mirror-objs	:= dm-log.o dm-raid1.o
 raid6-objs	:= raid6main.o raid6algos.o raid6recov.o raid6tables.o \
@@ -30,6 +31,8 @@
 obj-$(CONFIG_BLK_DEV_MD)	+= md.o
 obj-$(CONFIG_BLK_DEV_DM)	+= dm-mod.o
 obj-$(CONFIG_DM_CRYPT)		+= dm-crypt.o
+obj-$(CONFIG_DM_MULTIPATH)	+= dm-multipath.o dm-round-robin.o
+obj-$(CONFIG_DM_MULTIPATH_EMC)	+= dm-emc.o
 obj-$(CONFIG_DM_SNAPSHOT)	+= dm-snapshot.o
 obj-$(CONFIG_DM_MIRROR)		+= dm-mirror.o
 obj-$(CONFIG_DM_ZERO)		+= dm-zero.o
diff -Nru a/drivers/md/dm-bio-record.h b/drivers/md/dm-bio-record.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/md/dm-bio-record.h	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
+ *
+ * This file is released under the GPL.
+ */
+
+#ifndef DM_BIO_RECORD_H
+#define DM_BIO_RECORD_H
+
+#include <linux/bio.h>
+
+/*
+ * There are lots of mutable fields in the bio struct that get
+ * changed by the lower levels of the block layer.  Some targets,
+ * such as multipath, may wish to resubmit a bio on error.  The
+ * functions in this file help the target record and restore the
+ * original bio state.
+ */
+struct dm_bio_details {
+	sector_t bi_sector;
+	struct block_device *bi_bdev;
+	unsigned int bi_size;
+	unsigned short bi_idx;
+	unsigned long bi_flags;
+};
+
+static inline void dm_bio_record(struct dm_bio_details *bd, struct bio *bio)
+{
+	bd->bi_sector = bio->bi_sector;
+	bd->bi_bdev = bio->bi_bdev;
+	bd->bi_size = bio->bi_size;
+	bd->bi_idx = bio->bi_idx;
+	bd->bi_flags = bio->bi_flags;
+}
+
+static inline void dm_bio_restore(struct dm_bio_details *bd, struct bio *bio)
+{
+	bio->bi_sector = bd->bi_sector;
+	bio->bi_bdev = bd->bi_bdev;
+	bio->bi_size = bd->bi_size;
+	bio->bi_idx = bd->bi_idx;
+	bio->bi_flags = bd->bi_flags;
+}
+
+#endif
diff -Nru a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c
--- a/drivers/md/dm-crypt.c	2005-03-11 12:51:40 -08:00
+++ b/drivers/md/dm-crypt.c	2005-03-11 12:51:40 -08:00
@@ -869,7 +869,6 @@
 			char *result, unsigned int maxlen)
 {
 	struct crypt_config *cc = (struct crypt_config *) ti->private;
-	char buffer[32];
 	const char *cipher;
 	const char *chainmode = NULL;
 	unsigned int sz = 0;
@@ -910,9 +909,8 @@
 			result[sz++] = '-';
 		}
 
-		format_dev_t(buffer, cc->dev->bdev->bd_dev);
 		DMEMIT(" " SECTOR_FORMAT " %s " SECTOR_FORMAT,
-		       cc->iv_offset, buffer, cc->start);
+		       cc->iv_offset, cc->dev->name, cc->start);
 		break;
 	}
 	return 0;
diff -Nru a/drivers/md/dm-emc.c b/drivers/md/dm-emc.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/md/dm-emc.c	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,359 @@
+/*
+ * Copyright (C) 2004 SUSE LINUX Products GmbH. All rights reserved.
+ * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
+ *
+ * This file is released under the GPL.
+ *
+ * Multipath support for EMC CLARiiON AX/CX-series hardware.
+ */
+
+#include "dm.h"
+#include "dm-hw-handler.h"
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+
+struct emc_handler {
+	spinlock_t lock;
+
+	/* Whether we should send the short trespass command (FC-series)
+	 * or the long version (default for AX/CX CLARiiON arrays). */
+	unsigned short_trespass;
+	/* Whether or not to honor SCSI reservations when initiating a
+	 * switch-over. Default: Don't. */
+	unsigned hr;
+
+	unsigned char sense[SCSI_SENSE_BUFFERSIZE];
+};
+
+#define TRESPASS_PAGE 0x22
+#define EMC_FAILOVER_TIMEOUT (60 * HZ)
+
+/* Code borrowed from dm-lsi-rdac by Mike Christie */
+
+static inline void free_bio(struct bio *bio)
+{
+	__free_page(bio->bi_io_vec[0].bv_page);
+	bio_put(bio);
+}
+
+static int emc_endio(struct bio *bio, unsigned int bytes_done, int error)
+{
+	struct path *path = bio->bi_private;
+
+	if (bio->bi_size)
+		return 1;
+
+	/* We also need to look at the sense keys here whether or not to
+	 * switch to the next PG etc.
+	 *
+	 * For now simple logic: either it works or it doesn't.
+	 */
+	if (error)
+		dm_pg_init_complete(path, MP_FAIL_PATH);
+	else
+		dm_pg_init_complete(path, 0);
+
+	/* request is freed in block layer */
+	free_bio(bio);
+
+	return 0;
+}
+
+static struct bio *get_failover_bio(struct path *path, unsigned data_size)
+{
+	struct bio *bio;
+	struct page *page;
+
+	bio = bio_alloc(GFP_ATOMIC, 1);
+	if (!bio) {
+		DMERR("dm-emc: get_failover_bio: bio_alloc() failed.");
+		return NULL;
+	}
+
+	bio->bi_rw |= (1 << BIO_RW);
+	bio->bi_bdev = path->dev->bdev;
+	bio->bi_sector = 0;
+	bio->bi_private = path;
+	bio->bi_end_io = emc_endio;
+
+	page = alloc_page(GFP_ATOMIC);
+	if (!page) {
+		DMERR("dm-emc: get_failover_bio: alloc_page() failed.");
+		bio_put(bio);
+		return NULL;
+	}
+
+	if (bio_add_page(bio, page, data_size, 0) != data_size) {
+		DMERR("dm-emc: get_failover_bio: alloc_page() failed.");
+		__free_page(page);
+		bio_put(bio);
+		return NULL;
+	}
+
+	return bio;
+}
+
+static struct request *get_failover_req(struct emc_handler *h,
+					struct bio *bio, struct path *path)
+{
+	struct request *rq;
+	struct block_device *bdev = bio->bi_bdev;
+	struct request_queue *q = bdev_get_queue(bdev);
+
+	/* FIXME: Figure out why it fails with GFP_ATOMIC. */
+	rq = blk_get_request(q, WRITE, __GFP_WAIT);
+	if (!rq) {
+		DMERR("dm-emc: get_failover_req: blk_get_request failed");
+		return NULL;
+	}
+
+	rq->bio = rq->biotail = bio;
+	blk_rq_bio_prep(q, rq, bio);
+
+	rq->rq_disk = bdev->bd_contains->bd_disk;
+
+	/* bio backed don't set data */
+	rq->buffer = rq->data = NULL;
+	/* rq data_len used for pc cmd's request_bufflen */
+	rq->data_len = bio->bi_size;
+
+	rq->sense = h->sense;
+	memset(rq->sense, 0, SCSI_SENSE_BUFFERSIZE);
+	rq->sense_len = 0;
+
+	memset(&rq->cmd, 0, BLK_MAX_CDB);
+
+	rq->timeout = EMC_FAILOVER_TIMEOUT;
+	rq->flags |= (REQ_BLOCK_PC | REQ_FAILFAST | REQ_NOMERGE);
+
+	return rq;
+}
+
+static struct request *emc_trespass_get(struct emc_handler *h,
+					struct path *path)
+{
+	struct bio *bio;
+	struct request *rq;
+	unsigned char *page22;
+	unsigned char long_trespass_pg[] = {
+		0, 0, 0, 0,
+		TRESPASS_PAGE,        /* Page code */
+		0x09,                 /* Page length - 2 */
+		h->hr ? 0x01 : 0x81,  /* Trespass code + Honor reservation bit */
+		0xff, 0xff,           /* Trespass target */
+		0, 0, 0, 0, 0, 0      /* Reserved bytes / unknown */
+		};
+	unsigned char short_trespass_pg[] = {
+		0, 0, 0, 0,
+		TRESPASS_PAGE,        /* Page code */
+		0x02,                 /* Page length - 2 */
+		h->hr ? 0x01 : 0x81,  /* Trespass code + Honor reservation bit */
+		0xff,                 /* Trespass target */
+		};
+	unsigned data_size = h->short_trespass ? sizeof(short_trespass_pg) :
+				sizeof(long_trespass_pg);
+
+	/* get bio backing */
+	if (data_size > PAGE_SIZE)
+		/* this should never happen */
+		return NULL;
+
+	bio = get_failover_bio(path, data_size);
+	if (!bio) {
+		DMERR("dm-emc: emc_trespass_get: no bio");
+		return NULL;
+	}
+
+	page22 = (unsigned char *)bio_data(bio);
+	memset(page22, 0, data_size);
+
+	memcpy(page22, h->short_trespass ?
+		short_trespass_pg : long_trespass_pg, data_size);
+
+	/* get request for block layer packet command */
+	rq = get_failover_req(h, bio, path);
+	if (!rq) {
+		DMERR("dm-emc: emc_trespass_get: no rq");
+		free_bio(bio);
+		return NULL;
+	}
+
+	/* Prepare the command. */
+	rq->cmd[0] = MODE_SELECT;
+	rq->cmd[1] = 0x10;
+	rq->cmd[4] = data_size;
+	rq->cmd_len = COMMAND_SIZE(rq->cmd[0]);
+
+	return rq;
+}
+
+static void emc_pg_init(struct hw_handler *hwh, unsigned bypassed,
+			struct path *path)
+{
+	struct request *rq;
+	struct request_queue *q = bdev_get_queue(path->dev->bdev);
+
+	/*
+	 * We can either blindly init the pg (then look at the sense),
+	 * or we can send some commands to get the state here (then
+	 * possibly send the fo cmnd), or we can also have the
+	 * initial state passed into us and then get an update here.
+	 */
+	if (!q) {
+		DMINFO("dm-emc: emc_pg_init: no queue");
+		goto fail_path;
+	}
+
+	/* FIXME: The request should be pre-allocated. */
+	rq = emc_trespass_get(hwh->context, path);
+	if (!rq) {
+		DMERR("dm-emc: emc_pg_init: no rq");
+		goto fail_path;
+	}
+
+	DMINFO("dm-emc: emc_pg_init: sending switch-over command");
+	elv_add_request(q, rq, ELEVATOR_INSERT_FRONT, 1);
+	return;
+
+fail_path:
+	dm_pg_init_complete(path, MP_FAIL_PATH);
+}
+
+static struct emc_handler *alloc_emc_handler(void)
+{
+	struct emc_handler *h = kmalloc(sizeof(*h), GFP_KERNEL);
+
+	if (h)
+		spin_lock_init(&h->lock);
+
+	return h;
+}
+
+static int emc_create(struct hw_handler *hwh, unsigned argc, char **argv)
+{
+	struct emc_handler *h;
+	unsigned hr, short_trespass;
+
+	if (argc == 0) {
+		/* No arguments: use defaults */
+		hr = 0;
+		short_trespass = 0;
+	} else if (argc != 2) {
+		DMWARN("dm-emc hwhandler: incorrect number of arguments");
+		return -EINVAL;
+	} else {
+		if ((sscanf(argv[0], "%u", &short_trespass) != 1)
+			|| (short_trespass > 1)) {
+			DMWARN("dm-emc: invalid trespass mode selected");
+			return -EINVAL;
+		}
+
+		if ((sscanf(argv[1], "%u", &hr) != 1)
+			|| (hr > 1)) {
+			DMWARN("dm-emc: invalid honor reservation flag selected");
+			return -EINVAL;
+		}
+	}
+
+	h = alloc_emc_handler();
+	if (!h)
+		return -ENOMEM;
+
+	memset(h, 0, sizeof(*h));
+
+	hwh->context = h;
+
+	if ((h->short_trespass = short_trespass))
+		DMWARN("dm-emc: short trespass command will be send");
+	else
+		DMWARN("dm-emc: long trespass command will be send");
+
+	if ((h->hr = hr))
+		DMWARN("dm-emc: honor reservation bit will be set");
+	else
+		DMWARN("dm-emc: honor reservation bit will not be set (default)");
+
+	return 0;
+}
+
+static void emc_destroy(struct hw_handler *hwh)
+{
+	struct emc_handler *h = (struct emc_handler *) hwh->context;
+
+	kfree(h);
+	hwh->context = NULL;
+}
+
+static unsigned emc_error(struct hw_handler *hwh, struct bio *bio)
+{
+	/* FIXME: Patch from axboe still missing */
+#if 0
+	int sense;
+
+	if (bio->bi_error & BIO_SENSE) {
+		sense = bio->bi_error & 0xffffff; /* sense key / asc / ascq */
+
+		if (sense == 0x020403) {
+			/* LUN Not Ready - Manual Intervention Required
+			 * indicates this is a passive path.
+			 *
+			 * FIXME: However, if this is seen and EVPD C0
+			 * indicates that this is due to a NDU in
+			 * progress, we should set FAIL_PATH too.
+			 * This indicates we might have to do a SCSI
+			 * inquiry in the end_io path. Ugh. */
+			return MP_BYPASS_PG | MP_RETRY_IO;
+		} else if (sense == 0x052501) {
+			/* An array based copy is in progress. Do not
+			 * fail the path, do not bypass to another PG,
+			 * do not retry. Fail the IO immediately.
+			 * (Actually this is the same conclusion as in
+			 * the default handler, but lets make sure.) */
+			return 0;
+		} else if (sense == 0x062900) {
+			/* Unit Attention Code. This is the first IO
+			 * to the new path, so just retry. */
+			return MP_RETRY_IO;
+		}
+	}
+#endif
+
+	/* Try default handler */
+	return dm_scsi_err_handler(hwh, bio);
+}
+
+static struct hw_handler_type emc_hwh = {
+	.name = "emc",
+	.module = THIS_MODULE,
+	.create = emc_create,
+	.destroy = emc_destroy,
+	.pg_init = emc_pg_init,
+	.error = emc_error,
+};
+
+static int __init dm_emc_init(void)
+{
+	int r = dm_register_hw_handler(&emc_hwh);
+
+	if (r < 0)
+		DMERR("emc: register failed %d", r);
+
+	DMINFO("dm-emc version 0.0.3 loaded");
+
+	return r;
+}
+
+static void __exit dm_emc_exit(void)
+{
+	int r = dm_unregister_hw_handler(&emc_hwh);
+
+	if (r < 0)
+		DMERR("emc: unregister failed %d", r);
+}
+
+module_init(dm_emc_init);
+module_exit(dm_emc_exit);
+
+MODULE_DESCRIPTION(DM_NAME " EMC CX/AX/FC-family multipath");
+MODULE_AUTHOR("Lars Marowsky-Bree <lmb@suse.de>");
+MODULE_LICENSE("GPL");
diff -Nru a/drivers/md/dm-hw-handler.c b/drivers/md/dm-hw-handler.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/md/dm-hw-handler.c	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,216 @@
+/*
+ * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
+ *
+ * This file is released under the GPL.
+ *
+ * Multipath hardware handler registration.
+ */
+
+#include "dm.h"
+#include "dm-hw-handler.h"
+
+#include <linux/slab.h>
+
+struct hwh_internal {
+	struct hw_handler_type hwht;
+
+	struct list_head list;
+	long use;
+};
+
+#define hwht_to_hwhi(__hwht) container_of((__hwht), struct hwh_internal, hwht)
+
+static LIST_HEAD(_hw_handlers);
+static DECLARE_RWSEM(_hwh_lock);
+
+struct hwh_internal *__find_hw_handler_type(const char *name)
+{
+	struct hwh_internal *hwhi;
+
+	list_for_each_entry(hwhi, &_hw_handlers, list) {
+		if (!strcmp(name, hwhi->hwht.name))
+			return hwhi;
+	}
+
+	return NULL;
+}
+
+static struct hwh_internal *get_hw_handler(const char *name)
+{
+	struct hwh_internal *hwhi;
+
+	down_read(&_hwh_lock);
+	hwhi = __find_hw_handler_type(name);
+	if (hwhi) {
+		if ((hwhi->use == 0) && !try_module_get(hwhi->hwht.module))
+			hwhi = NULL;
+		else
+			hwhi->use++;
+	}
+	up_read(&_hwh_lock);
+
+	return hwhi;
+}
+
+struct hw_handler_type *dm_get_hw_handler(const char *name)
+{
+	struct hwh_internal *hwhi;
+
+	if (!name)
+		return NULL;
+
+	hwhi = get_hw_handler(name);
+	if (!hwhi) {
+		request_module("dm-%s", name);
+		hwhi = get_hw_handler(name);
+	}
+
+	return hwhi ? &hwhi->hwht : NULL;
+}
+
+void dm_put_hw_handler(struct hw_handler_type *hwht)
+{
+	struct hwh_internal *hwhi;
+
+	if (!hwht)
+		return;
+
+	down_read(&_hwh_lock);
+	hwhi = __find_hw_handler_type(hwht->name);
+	if (!hwhi)
+		goto out;
+
+	if (--hwhi->use == 0)
+		module_put(hwhi->hwht.module);
+
+	if (hwhi->use < 0)
+		BUG();
+
+      out:
+	up_read(&_hwh_lock);
+}
+
+static struct hwh_internal *_alloc_hw_handler(struct hw_handler_type *hwht)
+{
+	struct hwh_internal *hwhi = kmalloc(sizeof(*hwhi), GFP_KERNEL);
+
+	if (hwhi) {
+		memset(hwhi, 0, sizeof(*hwhi));
+		hwhi->hwht = *hwht;
+	}
+
+	return hwhi;
+}
+
+int dm_register_hw_handler(struct hw_handler_type *hwht)
+{
+	int r = 0;
+	struct hwh_internal *hwhi = _alloc_hw_handler(hwht);
+
+	if (!hwhi)
+		return -ENOMEM;
+
+	down_write(&_hwh_lock);
+
+	if (__find_hw_handler_type(hwht->name)) {
+		kfree(hwhi);
+		r = -EEXIST;
+	} else
+		list_add(&hwhi->list, &_hw_handlers);
+
+	up_write(&_hwh_lock);
+
+	return r;
+}
+
+int dm_unregister_hw_handler(struct hw_handler_type *hwht)
+{
+	struct hwh_internal *hwhi;
+
+	down_write(&_hwh_lock);
+
+	hwhi = __find_hw_handler_type(hwht->name);
+	if (!hwhi) {
+		up_write(&_hwh_lock);
+		return -EINVAL;
+	}
+
+	if (hwhi->use) {
+		up_write(&_hwh_lock);
+		return -ETXTBSY;
+	}
+
+	list_del(&hwhi->list);
+
+	up_write(&_hwh_lock);
+
+	kfree(hwhi);
+
+	return 0;
+}
+
+unsigned dm_scsi_err_handler(struct hw_handler *hwh, struct bio *bio)
+{
+#if 0
+	int sense_key, asc, ascq;
+
+	if (bio->bi_error & BIO_SENSE) {
+		/* FIXME: This is just an initial guess. */
+		/* key / asc / ascq */
+		sense_key = (bio->bi_error >> 16) & 0xff;
+		asc = (bio->bi_error >> 8) & 0xff;
+		ascq = bio->bi_error & 0xff;
+
+		switch (sense_key) {
+			/* This block as a whole comes from the device.
+			 * So no point retrying on another path. */
+		case 0x03:	/* Medium error */
+		case 0x05:	/* Illegal request */
+		case 0x07:	/* Data protect */
+		case 0x08:	/* Blank check */
+		case 0x0a:	/* copy aborted */
+		case 0x0c:	/* obsolete - no clue ;-) */
+		case 0x0d:	/* volume overflow */
+		case 0x0e:	/* data miscompare */
+		case 0x0f:	/* reserved - no idea either. */
+			return MP_ERROR_IO;
+
+			/* For these errors it's unclear whether they
+			 * come from the device or the controller.
+			 * So just lets try a different path, and if
+			 * it eventually succeeds, user-space will clear
+			 * the paths again... */
+		case 0x02:	/* Not ready */
+		case 0x04:	/* Hardware error */
+		case 0x09:	/* vendor specific */
+		case 0x0b:	/* Aborted command */
+			return MP_FAIL_PATH;
+
+		case 0x06:	/* Unit attention - might want to decode */
+			if (asc == 0x04 && ascq == 0x01)
+				/* "Unit in the process of
+				 * becoming ready" */
+				return 0;
+			return MP_FAIL_PATH;
+
+			/* FIXME: For Unit Not Ready we may want
+			 * to have a generic pg activation
+			 * feature (START_UNIT). */
+
+			/* Should these two ever end up in the
+			 * error path? I don't think so. */
+		case 0x00:	/* No sense */
+		case 0x01:	/* Recovered error */
+			return 0;
+		}
+	}
+#endif
+
+	/* We got no idea how to decode the other kinds of errors ->
+	 * assume generic error condition. */
+	return MP_FAIL_PATH;
+}
+
+EXPORT_SYMBOL_GPL(dm_register_hw_handler);
+EXPORT_SYMBOL_GPL(dm_unregister_hw_handler);
+EXPORT_SYMBOL_GPL(dm_scsi_err_handler);
diff -Nru a/drivers/md/dm-hw-handler.h b/drivers/md/dm-hw-handler.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/md/dm-hw-handler.h	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
+ *
+ * This file is released under the GPL.
+ *
+ * Multipath hardware handler registration.
+ */
+
+#ifndef	DM_HW_HANDLER_H
+#define	DM_HW_HANDLER_H
+
+#include <linux/device-mapper.h>
+
+#include "dm-mpath.h"
+
+struct hw_handler_type;
+struct hw_handler {
+	struct hw_handler_type *type;
+	void *context;
+};
+
+/*
+ * Constructs a hardware handler object, takes custom arguments
+ */
+/* Information about a hardware handler type */
+struct hw_handler_type {
+	char *name;
+	struct module *module;
+
+	int (*create) (struct hw_handler *handler, unsigned int argc,
+		       char **argv);
+	void (*destroy) (struct hw_handler *hwh);
+
+	void (*pg_init) (struct hw_handler *hwh, unsigned bypassed,
+			 struct path *path);
+	unsigned (*error) (struct hw_handler *hwh, struct bio *bio);
+	int (*status) (struct hw_handler *hwh, status_type_t type,
+		       char *result, unsigned int maxlen);
+};
+
+/* Register a hardware handler */
+int dm_register_hw_handler(struct hw_handler_type *type);
+
+/* Unregister a hardware handler */
+int dm_unregister_hw_handler(struct hw_handler_type *type);
+
+/* Returns a registered hardware handler type */
+struct hw_handler_type *dm_get_hw_handler(const char *name);
+
+/* Releases a hardware handler  */
+void dm_put_hw_handler(struct hw_handler_type *hwht);
+
+/* Default err function */
+unsigned dm_scsi_err_handler(struct hw_handler *hwh, struct bio *bio);
+
+/* Error flags for err and dm_pg_init_complete */
+#define MP_FAIL_PATH 1
+#define MP_BYPASS_PG 2
+#define MP_ERROR_IO  4	/* Don't retry this I/O */
+
+#endif
diff -Nru a/drivers/md/dm-io.c b/drivers/md/dm-io.c
--- a/drivers/md/dm-io.c	2005-03-11 12:51:51 -08:00
+++ b/drivers/md/dm-io.c	2005-03-11 12:51:51 -08:00
@@ -12,191 +12,7 @@
 #include <linux/sched.h>
 #include <linux/slab.h>
 
-#define BIO_POOL_SIZE 256
-
-
-/*-----------------------------------------------------------------
- * Bio set, move this to bio.c
- *---------------------------------------------------------------*/
-#define BV_NAME_SIZE 16
-struct biovec_pool {
-	int nr_vecs;
-	char name[BV_NAME_SIZE];
-	kmem_cache_t *slab;
-	mempool_t *pool;
-	atomic_t allocated;	/* FIXME: debug */
-};
-
-#define BIOVEC_NR_POOLS 6
-struct bio_set {
-	char name[BV_NAME_SIZE];
-	kmem_cache_t *bio_slab;
-	mempool_t *bio_pool;
-	struct biovec_pool pools[BIOVEC_NR_POOLS];
-};
-
-static void bio_set_exit(struct bio_set *bs)
-{
-	unsigned i;
-	struct biovec_pool *bp;
-
-	if (bs->bio_pool)
-		mempool_destroy(bs->bio_pool);
-
-	if (bs->bio_slab)
-		kmem_cache_destroy(bs->bio_slab);
-
-	for (i = 0; i < BIOVEC_NR_POOLS; i++) {
-		bp = bs->pools + i;
-		if (bp->pool)
-			mempool_destroy(bp->pool);
-
-		if (bp->slab)
-			kmem_cache_destroy(bp->slab);
-	}
-}
-
-static void mk_name(char *str, size_t len, const char *prefix, unsigned count)
-{
-	snprintf(str, len, "%s-%u", prefix, count);
-}
-
-static int bio_set_init(struct bio_set *bs, const char *slab_prefix,
-			 unsigned pool_entries, unsigned scale)
-{
-	/* FIXME: this must match bvec_index(), why not go the
-	 * whole hog and have a pool per power of 2 ? */
-	static unsigned _vec_lengths[BIOVEC_NR_POOLS] = {
-		1, 4, 16, 64, 128, BIO_MAX_PAGES
-	};
-
-
-	unsigned i, size;
-	struct biovec_pool *bp;
-
-	/* zero the bs so we can tear down properly on error */
-	memset(bs, 0, sizeof(*bs));
-
-	/*
-	 * Set up the bio pool.
-	 */
-	snprintf(bs->name, sizeof(bs->name), "%s-bio", slab_prefix);
-
-	bs->bio_slab = kmem_cache_create(bs->name, sizeof(struct bio), 0,
-					 SLAB_HWCACHE_ALIGN, NULL, NULL);
-	if (!bs->bio_slab) {
-		DMWARN("can't init bio slab");
-		goto bad;
-	}
-
-	bs->bio_pool = mempool_create(pool_entries, mempool_alloc_slab,
-				      mempool_free_slab, bs->bio_slab);
-	if (!bs->bio_pool) {
-		DMWARN("can't init bio pool");
-		goto bad;
-	}
-
-	/*
-	 * Set up the biovec pools.
-	 */
-	for (i = 0; i < BIOVEC_NR_POOLS; i++) {
-		bp = bs->pools + i;
-		bp->nr_vecs = _vec_lengths[i];
-		atomic_set(&bp->allocated, 1); /* FIXME: debug */
-
-
-		size = bp->nr_vecs * sizeof(struct bio_vec);
-
-		mk_name(bp->name, sizeof(bp->name), slab_prefix, i);
-		bp->slab = kmem_cache_create(bp->name, size, 0,
-					     SLAB_HWCACHE_ALIGN, NULL, NULL);
-		if (!bp->slab) {
-			DMWARN("can't init biovec slab cache");
-			goto bad;
-		}
-
-		if (i >= scale)
-			pool_entries >>= 1;
-
-		bp->pool = mempool_create(pool_entries, mempool_alloc_slab,
-					  mempool_free_slab, bp->slab);
-		if (!bp->pool) {
-			DMWARN("can't init biovec mempool");
-			goto bad;
-		}
-	}
-
-	return 0;
-
- bad:
-	bio_set_exit(bs);
-	return -ENOMEM;
-}
-
-/* FIXME: blech */
-static inline unsigned bvec_index(unsigned nr)
-{
-	switch (nr) {
-	case 1:		return 0;
-	case 2 ... 4: 	return 1;
-	case 5 ... 16:	return 2;
-	case 17 ... 64:	return 3;
-	case 65 ... 128:return 4;
-	case 129 ... BIO_MAX_PAGES: return 5;
-	}
-
-	BUG();
-	return 0;
-}
-
-static unsigned _bio_count = 0;
-struct bio *bio_set_alloc(struct bio_set *bs, int gfp_mask, int nr_iovecs)
-{
-	struct biovec_pool *bp;
-	struct bio_vec *bv = NULL;
-	unsigned long idx;
-	struct bio *bio;
-
-	bio = mempool_alloc(bs->bio_pool, gfp_mask);
-	if (unlikely(!bio))
-		return NULL;
-
-	bio_init(bio);
-
-	if (likely(nr_iovecs)) {
-		idx = bvec_index(nr_iovecs);
-		bp = bs->pools + idx;
-		bv = mempool_alloc(bp->pool, gfp_mask);
-		if (!bv) {
-			mempool_free(bio, bs->bio_pool);
-			return NULL;
-		}
-
-		memset(bv, 0, bp->nr_vecs * sizeof(*bv));
-		bio->bi_flags |= idx << BIO_POOL_OFFSET;
-		bio->bi_max_vecs = bp->nr_vecs;
-		atomic_inc(&bp->allocated);
-	}
-
-	bio->bi_io_vec = bv;
-	return bio;
-}
-
-static void bio_set_free(struct bio_set *bs, struct bio *bio)
-{
-	struct biovec_pool *bp = bs->pools + BIO_POOL_IDX(bio);
-
-	if (atomic_dec_and_test(&bp->allocated))
-		BUG();
-
-	mempool_free(bio->bi_io_vec, bp->pool);
-	mempool_free(bio, bs->bio_pool);
-}
-
-/*-----------------------------------------------------------------
- * dm-io proper
- *---------------------------------------------------------------*/
-static struct bio_set _bios;
+static struct bio_set *_bios;
 
 /* FIXME: can we shrink this ? */
 struct io {
@@ -240,7 +56,7 @@
 			/* free off the pool */
 			mempool_destroy(_io_pool);
 			_io_pool = NULL;
-			bio_set_exit(&_bios);
+			bioset_free(_bios);
 
 		} else {
 			/* resize the pool */
@@ -253,10 +69,11 @@
 		if (!_io_pool)
 			return -ENOMEM;
 
-		r = bio_set_init(&_bios, "dm-io", 512, 1);
-		if (r) {
+		_bios = bioset_create(16, 16, 4);
+		if (!_bios) {
 			mempool_destroy(_io_pool);
 			_io_pool = NULL;
+			return -ENOMEM;
 		}
 	}
 
@@ -280,6 +97,7 @@
  * We need to keep track of which region a bio is doing io for.
  * In order to save a memory allocation we store this the last
  * bvec which we know is unused (blech).
+ * XXX This is ugly and can OOPS with some configs... find another way.
  *---------------------------------------------------------------*/
 static inline void bio_set_region(struct bio *bio, unsigned region)
 {
@@ -315,21 +133,6 @@
 	}
 }
 
-/* FIXME Move this to bio.h? */
-static void zero_fill_bio(struct bio *bio)
-{
-	unsigned long flags;
-	struct bio_vec *bv;
-	int i;
-
-	bio_for_each_segment(bv, bio, i) {
-		char *data = bvec_kmap_irq(bv, &flags);
-		memset(data, 0, bv->bv_len);
-		flush_dcache_page(bv->bv_page);
-		bvec_kunmap_irq(data, &flags);
-	}
-}
-
 static int endio(struct bio *bio, unsigned int done, int error)
 {
 	struct io *io = (struct io *) bio->bi_private;
@@ -347,12 +150,6 @@
 	return 0;
 }
 
-static void bio_dtr(struct bio *bio)
-{
-	_bio_count--;
-	bio_set_free(&_bios, bio);
-}
-
 /*-----------------------------------------------------------------
  * These little objects provide an abstraction for getting a new
  * destination page for io.
@@ -461,13 +258,11 @@
 		 * bvec for bio_get/set_region().
 		 */
 		num_bvecs = (remaining / (PAGE_SIZE >> 9)) + 2;
-		_bio_count++;
-		bio = bio_set_alloc(&_bios, GFP_NOIO, num_bvecs);
+		bio = bio_alloc_bioset(GFP_NOIO, num_bvecs, _bios);
 		bio->bi_sector = where->sector + (where->count - remaining);
 		bio->bi_bdev = where->bdev;
 		bio->bi_end_io = endio;
 		bio->bi_private = io;
-		bio->bi_destructor = bio_dtr;
 		bio_set_region(bio, region);
 
 		/*
diff -Nru a/drivers/md/dm-linear.c b/drivers/md/dm-linear.c
--- a/drivers/md/dm-linear.c	2005-03-11 12:51:46 -08:00
+++ b/drivers/md/dm-linear.c	2005-03-11 12:51:46 -08:00
@@ -80,7 +80,6 @@
 			 char *result, unsigned int maxlen)
 {
 	struct linear_c *lc = (struct linear_c *) ti->private;
-	char buffer[32];
 
 	switch (type) {
 	case STATUSTYPE_INFO:
@@ -88,8 +87,8 @@
 		break;
 
 	case STATUSTYPE_TABLE:
-		format_dev_t(buffer, lc->dev->bdev->bd_dev);
-		snprintf(result, maxlen, "%s " SECTOR_FORMAT, buffer, lc->start);
+		snprintf(result, maxlen, "%s " SECTOR_FORMAT, lc->dev->name,
+			 lc->start);
 		break;
 	}
 	return 0;
diff -Nru a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/md/dm-mpath.c	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,1302 @@
+/*
+ * Copyright (C) 2003 Sistina Software Limited.
+ * Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
+ *
+ * This file is released under the GPL.
+ */
+
+#include "dm.h"
+#include "dm-path-selector.h"
+#include "dm-hw-handler.h"
+#include "dm-bio-list.h"
+#include "dm-bio-record.h"
+
+#include <linux/ctype.h>
+#include <linux/init.h>
+#include <linux/mempool.h>
+#include <linux/module.h>
+#include <linux/pagemap.h>
+#include <linux/slab.h>
+#include <linux/time.h>
+#include <linux/workqueue.h>
+#include <asm/atomic.h>
+
+#define MESG_STR(x) x, sizeof(x)
+
+/* Path properties */
+struct pgpath {
+	struct list_head list;
+
+	struct priority_group *pg;	/* Owning PG */
+	unsigned fail_count;		/* Cumulative failure count */
+
+	struct path path;
+};
+
+#define path_to_pgpath(__pgp) container_of((__pgp), struct pgpath, path)
+
+/*
+ * Paths are grouped into Priority Groups and numbered from 1 upwards.
+ * Each has a path selector which controls which path gets used.
+ */
+struct priority_group {
+	struct list_head list;
+
+	struct multipath *m;		/* Owning multipath instance */
+	struct path_selector ps;
+
+	unsigned pg_num;		/* Reference number */
+	unsigned bypassed;		/* Temporarily bypass this PG? */
+
+	unsigned nr_pgpaths;		/* Number of paths in PG */
+	struct list_head pgpaths;
+};
+
+/* Multipath context */
+struct multipath {
+	struct list_head list;
+	struct dm_target *ti;
+
+	spinlock_t lock;
+
+	struct hw_handler hw_handler;
+	unsigned nr_priority_groups;
+	struct list_head priority_groups;
+	unsigned pg_init_required;	/* pg_init needs calling? */
+
+	unsigned nr_valid_paths;	/* Total number of usable paths */
+	struct pgpath *current_pgpath;
+	struct priority_group *current_pg;
+	struct priority_group *next_pg;	/* Switch to this PG if set */
+	unsigned repeat_count;		/* I/Os left before calling PS again */
+
+	unsigned queue_io;		/* Must we queue all I/O? */
+	unsigned queue_if_no_path;	/* Queue I/O if last path fails? */
+	unsigned suspended;		/* Has dm core suspended our I/O? */
+
+	struct work_struct process_queued_ios;
+	struct bio_list queued_ios;
+	unsigned queue_size;
+
+	struct work_struct trigger_event;
+
+	/*
+	 * We must use a mempool of mpath_io structs so that we
+	 * can resubmit bios on error.
+	 */
+	mempool_t *mpio_pool;
+};
+
+/*
+ * Context information attached to each bio we process.
+ */
+struct mpath_io {
+	struct pgpath *pgpath;
+	struct dm_bio_details details;
+};
+
+typedef int (*action_fn) (struct pgpath *pgpath);
+
+#define MIN_IOS 256	/* Mempool size */
+
+static kmem_cache_t *_mpio_cache;
+
+static void process_queued_ios(void *data);
+static void trigger_event(void *data);
+
+
+/*-----------------------------------------------
+ * Allocation routines
+ *-----------------------------------------------*/
+
+static struct pgpath *alloc_pgpath(void)
+{
+	struct pgpath *pgpath = kmalloc(sizeof(*pgpath), GFP_KERNEL);
+
+	if (pgpath) {
+		memset(pgpath, 0, sizeof(*pgpath));
+		pgpath->path.is_active = 1;
+	}
+
+	return pgpath;
+}
+
+static inline void free_pgpath(struct pgpath *pgpath)
+{
+	kfree(pgpath);
+}
+
+static struct priority_group *alloc_priority_group(void)
+{
+	struct priority_group *pg;
+
+	pg = kmalloc(sizeof(*pg), GFP_KERNEL);
+	if (!pg)
+		return NULL;
+
+	memset(pg, 0, sizeof(*pg));
+	INIT_LIST_HEAD(&pg->pgpaths);
+
+	return pg;
+}
+
+static void free_pgpaths(struct list_head *pgpaths, struct dm_target *ti)
+{
+	struct pgpath *pgpath, *tmp;
+
+	list_for_each_entry_safe(pgpath, tmp, pgpaths, list) {
+		list_del(&pgpath->list);
+		dm_put_device(ti, pgpath->path.dev);
+		free_pgpath(pgpath);
+	}
+}
+
+static void free_priority_group(struct priority_group *pg,
+				struct dm_target *ti)
+{
+	struct path_selector *ps = &pg->ps;
+
+	if (ps->type) {
+		ps->type->destroy(ps);
+		dm_put_path_selector(ps->type);
+	}
+
+	free_pgpaths(&pg->pgpaths, ti);
+	kfree(pg);
+}
+
+static struct multipath *alloc_multipath(void)
+{
+	struct multipath *m;
+
+	m = kmalloc(sizeof(*m), GFP_KERNEL);
+	if (m) {
+		memset(m, 0, sizeof(*m));
+		INIT_LIST_HEAD(&m->priority_groups);
+		spin_lock_init(&m->lock);
+		m->queue_io = 1;
+		INIT_WORK(&m->process_queued_ios, process_queued_ios, m);
+		INIT_WORK(&m->trigger_event, trigger_event, m);
+		m->mpio_pool = mempool_create(MIN_IOS, mempool_alloc_slab,
+					      mempool_free_slab, _mpio_cache);
+		if (!m->mpio_pool) {
+			kfree(m);
+			return NULL;
+		}
+	}
+
+	return m;
+}
+
+static void free_multipath(struct multipath *m)
+{
+	struct priority_group *pg, *tmp;
+	struct hw_handler *hwh = &m->hw_handler;
+
+	list_for_each_entry_safe(pg, tmp, &m->priority_groups, list) {
+		list_del(&pg->list);
+		free_priority_group(pg, m->ti);
+	}
+
+	if (hwh->type) {
+		hwh->type->destroy(hwh);
+		dm_put_hw_handler(hwh->type);
+	}
+
+	mempool_destroy(m->mpio_pool);
+	kfree(m);
+}
+
+
+/*-----------------------------------------------
+ * Path selection
+ *-----------------------------------------------*/
+
+static void __switch_pg(struct multipath *m, struct pgpath *pgpath)
+{
+	struct hw_handler *hwh = &m->hw_handler;
+
+	m->current_pg = pgpath->pg;
+
+	/* Must we initialise the PG first, and queue I/O till it's ready? */
+	if (hwh->type && hwh->type->pg_init) {
+		m->pg_init_required = 1;
+		m->queue_io = 1;
+	} else {
+		m->pg_init_required = 0;
+		m->queue_io = 0;
+	}
+}
+
+static int __choose_path_in_pg(struct multipath *m, struct priority_group *pg)
+{
+	struct path *path;
+
+	path = pg->ps.type->select_path(&pg->ps, &m->repeat_count);
+	if (!path)
+		return -ENXIO;
+
+	m->current_pgpath = path_to_pgpath(path);
+
+	if (m->current_pg != pg)
+		__switch_pg(m, m->current_pgpath);
+
+	return 0;
+}
+
+static void __choose_pgpath(struct multipath *m)
+{
+	struct priority_group *pg;
+	unsigned bypassed = 1;
+
+	if (!m->nr_valid_paths)
+		goto failed;
+
+	/* Were we instructed to switch PG? */
+	if (m->next_pg) {
+		pg = m->next_pg;
+		m->next_pg = NULL;
+		if (!__choose_path_in_pg(m, pg))
+			return;
+	}
+
+	/* Don't change PG until it has no remaining paths */
+	if (m->current_pg && !__choose_path_in_pg(m, m->current_pg))
+		return;
+
+	/*
+	 * Loop through priority groups until we find a valid path.
+	 * First time we skip PGs marked 'bypassed'.
+	 * Second time we only try the ones we skipped.
+	 */
+	do {
+		list_for_each_entry(pg, &m->priority_groups, list) {
+			if (pg->bypassed == bypassed)
+				continue;
+			if (!__choose_path_in_pg(m, pg))
+				return;
+		}
+	} while (bypassed--);
+
+failed:
+	m->current_pgpath = NULL;
+	m->current_pg = NULL;
+}
+
+static int map_io(struct multipath *m, struct bio *bio, struct mpath_io *mpio,
+		  unsigned was_queued)
+{
+	int r = 1;
+	unsigned long flags;
+	struct pgpath *pgpath;
+
+	spin_lock_irqsave(&m->lock, flags);
+
+	/* Do we need to select a new pgpath? */
+	if (!m->current_pgpath ||
+	    (!m->queue_io && (m->repeat_count && --m->repeat_count == 0)))
+		__choose_pgpath(m);
+
+	pgpath = m->current_pgpath;
+
+	if (was_queued)
+		m->queue_size--;
+
+	if ((pgpath && m->queue_io) ||
+	    (!pgpath && m->queue_if_no_path && !m->suspended)) {
+		/* Queue for the daemon to resubmit */
+		bio_list_add(&m->queued_ios, bio);
+		m->queue_size++;
+		if (m->pg_init_required || !m->queue_io)
+			schedule_work(&m->process_queued_ios);
+		pgpath = NULL;
+		r = 0;
+	} else if (!pgpath)
+		r = -EIO;		/* Failed */
+	else
+		bio->bi_bdev = pgpath->path.dev->bdev;
+
+	mpio->pgpath = pgpath;
+
+	spin_unlock_irqrestore(&m->lock, flags);
+
+	return r;
+}
+
+/*
+ * If we run out of usable paths, should we queue I/O or error it?
+ */
+static int queue_if_no_path(struct multipath *m, unsigned queue_if_no_path)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&m->lock, flags);
+
+	m->queue_if_no_path = queue_if_no_path;
+	if (!m->queue_if_no_path)
+		schedule_work(&m->process_queued_ios);
+
+	spin_unlock_irqrestore(&m->lock, flags);
+
+	return 0;
+}
+
+/*-----------------------------------------------------------------
+ * The multipath daemon is responsible for resubmitting queued ios.
+ *---------------------------------------------------------------*/
+
+static void dispatch_queued_ios(struct multipath *m)
+{
+	int r;
+	unsigned long flags;
+	struct bio *bio = NULL, *next;
+	struct mpath_io *mpio;
+	union map_info *info;
+
+	spin_lock_irqsave(&m->lock, flags);
+	bio = bio_list_get(&m->queued_ios);
+	spin_unlock_irqrestore(&m->lock, flags);
+
+	while (bio) {
+		next = bio->bi_next;
+		bio->bi_next = NULL;
+
+		info = dm_get_mapinfo(bio);
+		mpio = info->ptr;
+
+		r = map_io(m, bio, mpio, 1);
+		if (r < 0)
+			bio_endio(bio, bio->bi_size, r);
+		else if (r == 1)
+			generic_make_request(bio);
+
+		bio = next;
+	}
+}
+
+static void process_queued_ios(void *data)
+{
+	struct multipath *m = (struct multipath *) data;
+	struct hw_handler *hwh = &m->hw_handler;
+	struct pgpath *pgpath;
+	unsigned init_required, must_queue = 0;
+	unsigned long flags;
+
+	spin_lock_irqsave(&m->lock, flags);
+
+	if (!m->current_pgpath)
+		__choose_pgpath(m);
+
+	pgpath = m->current_pgpath;
+
+	if ((pgpath && m->queue_io) ||
+	    (!pgpath && m->queue_if_no_path && !m->suspended))
+		must_queue = 1;
+
+	init_required = m->pg_init_required;
+	if (init_required)
+		m->pg_init_required = 0;
+
+	spin_unlock_irqrestore(&m->lock, flags);
+
+	if (init_required)
+		hwh->type->pg_init(hwh, pgpath->pg->bypassed, &pgpath->path);
+
+	if (!must_queue)
+		dispatch_queued_ios(m);
+}
+
+/*
+ * An event is triggered whenever a path is taken out of use.
+ * Includes path failure and PG bypass.
+ */
+static void trigger_event(void *data)
+{
+	struct multipath *m = (struct multipath *) data;
+
+	dm_table_event(m->ti->table);
+}
+
+/*-----------------------------------------------------------------
+ * Constructor/argument parsing:
+ * <#multipath feature args> [<arg>]*
+ * <#hw_handler args> [hw_handler [<arg>]*]
+ * <#priority groups>
+ * <initial priority group>
+ *     [<selector> <#selector args> [<arg>]*
+ *      <#paths> <#per-path selector args>
+ *         [<path> [<arg>]* ]+ ]+
+ *---------------------------------------------------------------*/
+struct param {
+	unsigned min;
+	unsigned max;
+	char *error;
+};
+
+#define ESTR(s) ("dm-multipath: " s)
+
+static int read_param(struct param *param, char *str, unsigned *v, char **error)
+{
+	if (!str ||
+	    (sscanf(str, "%u", v) != 1) ||
+	    (*v < param->min) ||
+	    (*v > param->max)) {
+		*error = param->error;
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+struct arg_set {
+	unsigned argc;
+	char **argv;
+};
+
+static char *shift(struct arg_set *as)
+{
+	char *r;
+
+	if (as->argc) {
+		as->argc--;
+		r = *as->argv;
+		as->argv++;
+		return r;
+	}
+
+	return NULL;
+}
+
+static void consume(struct arg_set *as, unsigned n)
+{
+	BUG_ON (as->argc < n);
+	as->argc -= n;
+	as->argv += n;
+}
+
+static int parse_path_selector(struct arg_set *as, struct priority_group *pg,
+			       struct dm_target *ti)
+{
+	int r;
+	struct path_selector_type *pst;
+	unsigned ps_argc;
+
+	static struct param _params[] = {
+		{0, 1024, ESTR("invalid number of path selector args")},
+	};
+
+	pst = dm_get_path_selector(shift(as));
+	if (!pst) {
+		ti->error = ESTR("unknown path selector type");
+		return -EINVAL;
+	}
+
+	r = read_param(_params, shift(as), &ps_argc, &ti->error);
+	if (r)
+		return -EINVAL;
+
+	r = pst->create(&pg->ps, ps_argc, as->argv);
+	if (r) {
+		dm_put_path_selector(pst);
+		ti->error = ESTR("path selector constructor failed");
+		return r;
+	}
+
+	pg->ps.type = pst;
+	consume(as, ps_argc);
+
+	return 0;
+}
+
+static struct pgpath *parse_path(struct arg_set *as, struct path_selector *ps,
+			       struct dm_target *ti)
+{
+	int r;
+	struct pgpath *p;
+
+	/* we need at least a path arg */
+	if (as->argc < 1) {
+		ti->error = ESTR("no device given");
+		return NULL;
+	}
+
+	p = alloc_pgpath();
+	if (!p)
+		return NULL;
+
+	r = dm_get_device(ti, shift(as), ti->begin, ti->len,
+			  dm_table_get_mode(ti->table), &p->path.dev);
+	if (r) {
+		ti->error = ESTR("error getting device");
+		goto bad;
+	}
+
+	r = ps->type->add_path(ps, &p->path, as->argc, as->argv, &ti->error);
+	if (r) {
+		dm_put_device(ti, p->path.dev);
+		goto bad;
+	}
+
+	return p;
+
+ bad:
+	free_pgpath(p);
+	return NULL;
+}
+
+static struct priority_group *parse_priority_group(struct arg_set *as,
+						   struct multipath *m,
+						   struct dm_target *ti)
+{
+	static struct param _params[] = {
+		{1, 1024, ESTR("invalid number of paths")},
+		{0, 1024, ESTR("invalid number of selector args")}
+	};
+
+	int r;
+	unsigned i, nr_selector_args, nr_params;
+	struct priority_group *pg;
+
+	if (as->argc < 2) {
+		as->argc = 0;
+		ti->error = ESTR("not enough priority group aruments");
+		return NULL;
+	}
+
+	pg = alloc_priority_group();
+	if (!pg) {
+		ti->error = ESTR("couldn't allocate priority group");
+		return NULL;
+	}
+	pg->m = m;
+
+	r = parse_path_selector(as, pg, ti);
+	if (r)
+		goto bad;
+
+	/*
+	 * read the paths
+	 */
+	r = read_param(_params, shift(as), &pg->nr_pgpaths, &ti->error);
+	if (r)
+		goto bad;
+
+	r = read_param(_params + 1, shift(as), &nr_selector_args, &ti->error);
+	if (r)
+		goto bad;
+
+	nr_params = 1 + nr_selector_args;
+	for (i = 0; i < pg->nr_pgpaths; i++) {
+		struct pgpath *pgpath;
+		struct arg_set path_args;
+
+		if (as->argc < nr_params)
+			goto bad;
+
+		path_args.argc = nr_params;
+		path_args.argv = as->argv;
+
+		pgpath = parse_path(&path_args, &pg->ps, ti);
+		if (!pgpath)
+			goto bad;
+
+		pgpath->pg = pg;
+		list_add_tail(&pgpath->list, &pg->pgpaths);
+		consume(as, nr_params);
+	}
+
+	return pg;
+
+ bad:
+	free_priority_group(pg, ti);
+	return NULL;
+}
+
+static int parse_hw_handler(struct arg_set *as, struct multipath *m,
+			    struct dm_target *ti)
+{
+	int r;
+	struct hw_handler_type *hwht;
+	unsigned hw_argc;
+
+	static struct param _params[] = {
+		{0, 1024, ESTR("invalid number of hardware handler args")},
+	};
+
+	r = read_param(_params, shift(as), &hw_argc, &ti->error);
+	if (r)
+		return -EINVAL;
+
+	if (!hw_argc)
+		return 0;
+
+	hwht = dm_get_hw_handler(shift(as));
+	if (!hwht) {
+		ti->error = ESTR("unknown hardware handler type");
+		return -EINVAL;
+	}
+
+	r = hwht->create(&m->hw_handler, hw_argc - 1, as->argv);
+	if (r) {
+		dm_put_hw_handler(hwht);
+		ti->error = ESTR("hardware handler constructor failed");
+		return r;
+	}
+
+	m->hw_handler.type = hwht;
+	consume(as, hw_argc - 1);
+
+	return 0;
+}
+
+static int parse_features(struct arg_set *as, struct multipath *m,
+			  struct dm_target *ti)
+{
+	int r;
+	unsigned argc;
+
+	static struct param _params[] = {
+		{0, 1, ESTR("invalid number of feature args")},
+	};
+
+	r = read_param(_params, shift(as), &argc, &ti->error);
+	if (r)
+		return -EINVAL;
+
+	if (!argc)
+		return 0;
+
+	if (!strnicmp(shift(as), MESG_STR("queue_if_no_path")))
+		return queue_if_no_path(m, 1);
+	else {
+		ti->error = "Unrecognised multipath feature request";
+		return -EINVAL;
+	}
+}
+
+static int multipath_ctr(struct dm_target *ti, unsigned int argc,
+			 char **argv)
+{
+	/* target parameters */
+	static struct param _params[] = {
+		{1, 1024, ESTR("invalid number of priority groups")},
+		{1, 1024, ESTR("invalid initial priority group number")},
+	};
+
+	int r;
+	struct multipath *m;
+	struct arg_set as;
+	unsigned pg_count = 0;
+	unsigned next_pg_num;
+
+	as.argc = argc;
+	as.argv = argv;
+
+	m = alloc_multipath();
+	if (!m) {
+		ti->error = ESTR("can't allocate multipath");
+		return -EINVAL;
+	}
+
+	r = parse_features(&as, m, ti);
+	if (r)
+		goto bad;
+
+	r = parse_hw_handler(&as, m, ti);
+	if (r)
+		goto bad;
+
+	r = read_param(_params, shift(&as), &m->nr_priority_groups, &ti->error);
+	if (r)
+		goto bad;
+
+	r = read_param(_params + 1, shift(&as), &next_pg_num, &ti->error);
+	if (r)
+		goto bad;
+
+	/* parse the priority groups */
+	while (as.argc) {
+		struct priority_group *pg;
+
+		pg = parse_priority_group(&as, m, ti);
+		if (!pg) {
+			r = -EINVAL;
+			goto bad;
+		}
+
+		m->nr_valid_paths += pg->nr_pgpaths;
+		list_add_tail(&pg->list, &m->priority_groups);
+		pg_count++;
+		pg->pg_num = pg_count;
+		if (!--next_pg_num)
+			m->next_pg = pg;
+	}
+
+	if (pg_count != m->nr_priority_groups) {
+		ti->error = ESTR("priority group count mismatch");
+		r = -EINVAL;
+		goto bad;
+	}
+
+	ti->private = m;
+	m->ti = ti;
+
+	return 0;
+
+ bad:
+	free_multipath(m);
+	return r;
+}
+
+static void multipath_dtr(struct dm_target *ti)
+{
+	struct multipath *m = (struct multipath *) ti->private;
+	free_multipath(m);
+}
+
+/*
+ * Map bios, recording original fields for later in case we have to resubmit
+ */
+static int multipath_map(struct dm_target *ti, struct bio *bio,
+			 union map_info *map_context)
+{
+	int r;
+	struct mpath_io *mpio;
+	struct multipath *m = (struct multipath *) ti->private;
+
+	mpio = mempool_alloc(m->mpio_pool, GFP_NOIO);
+	dm_bio_record(&mpio->details, bio);
+
+	map_context->ptr = mpio;
+	bio->bi_rw |= (1 << BIO_RW_FAILFAST);
+	r = map_io(m, bio, mpio, 0);
+	if (r < 0)
+		mempool_free(mpio, m->mpio_pool);
+
+	return r;
+}
+
+/*
+ * Take a path out of use.
+ */
+static int fail_path(struct pgpath *pgpath)
+{
+	unsigned long flags;
+	struct multipath *m = pgpath->pg->m;
+
+	spin_lock_irqsave(&m->lock, flags);
+
+	if (!pgpath->path.is_active)
+		goto out;
+
+	DMWARN("dm-multipath: Failing path %s.", pgpath->path.dev->name);
+
+	pgpath->pg->ps.type->fail_path(&pgpath->pg->ps, &pgpath->path);
+	pgpath->path.is_active = 0;
+	pgpath->fail_count++;
+
+	m->nr_valid_paths--;
+
+	if (pgpath == m->current_pgpath)
+		m->current_pgpath = NULL;
+
+	schedule_work(&m->trigger_event);
+
+out:
+	spin_unlock_irqrestore(&m->lock, flags);
+
+	return 0;
+}
+
+/*
+ * Reinstate a previously-failed path
+ */
+static int reinstate_path(struct pgpath *pgpath)
+{
+	int r = 0;
+	unsigned long flags;
+	struct multipath *m = pgpath->pg->m;
+
+	spin_lock_irqsave(&m->lock, flags);
+
+	if (pgpath->path.is_active)
+		goto out;
+
+	if (!pgpath->pg->ps.type) {
+		DMWARN("Reinstate path not supported by path selector %s",
+		       pgpath->pg->ps.type->name);
+		r = -EINVAL;
+		goto out;
+	}
+
+	r = pgpath->pg->ps.type->reinstate_path(&pgpath->pg->ps, &pgpath->path);
+	if (r)
+		goto out;
+
+	pgpath->path.is_active = 1;
+
+	m->current_pgpath = NULL;
+	if (!m->nr_valid_paths++)
+		schedule_work(&m->process_queued_ios);
+
+	schedule_work(&m->trigger_event);
+
+out:
+	spin_unlock_irqrestore(&m->lock, flags);
+
+	return r;
+}
+
+/*
+ * Fail or reinstate all paths that match the provided struct dm_dev.
+ */
+static int action_dev(struct multipath *m, struct dm_dev *dev,
+		      action_fn action)
+{
+	int r = 0;
+	struct pgpath *pgpath;
+	struct priority_group *pg;
+
+	list_for_each_entry(pg, &m->priority_groups, list) {
+		list_for_each_entry(pgpath, &pg->pgpaths, list) {
+			if (pgpath->path.dev == dev)
+				r = action(pgpath);
+		}
+	}
+
+	return r;
+}
+
+/*
+ * Temporarily try to avoid having to use the specified PG
+ */
+static void bypass_pg(struct multipath *m, struct priority_group *pg,
+		      int bypassed)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&m->lock, flags);
+
+	pg->bypassed = bypassed;
+	m->current_pgpath = NULL;
+	m->current_pg = NULL;
+
+	spin_unlock_irqrestore(&m->lock, flags);
+
+	schedule_work(&m->trigger_event);
+}
+
+/*
+ * Switch to using the specified PG from the next I/O that gets mapped
+ */
+static int switch_pg_num(struct multipath *m, const char *pgstr)
+{
+	struct priority_group *pg;
+	unsigned pgnum;
+	unsigned long flags;
+
+	if (!pgstr || (sscanf(pgstr, "%u", &pgnum) != 1) || !pgnum ||
+	    (pgnum > m->nr_priority_groups)) {
+		DMWARN("invalid PG number supplied to switch_pg_num");
+		return -EINVAL;
+	}
+
+	spin_lock_irqsave(&m->lock, flags);
+	list_for_each_entry(pg, &m->priority_groups, list) {
+		pg->bypassed = 0;
+		if (--pgnum)
+			continue;
+
+		m->current_pgpath = NULL;
+		m->current_pg = NULL;
+		m->next_pg = pg;
+	}
+	spin_unlock_irqrestore(&m->lock, flags);
+
+	schedule_work(&m->trigger_event);
+	return 0;
+}
+
+/*
+ * Set/clear bypassed status of a PG.
+ * PGs are numbered upwards from 1 in the order they were declared.
+ */
+static int bypass_pg_num(struct multipath *m, const char *pgstr, int bypassed)
+{
+	struct priority_group *pg;
+	unsigned pgnum;
+
+	if (!pgstr || (sscanf(pgstr, "%u", &pgnum) != 1) || !pgnum ||
+	    (pgnum > m->nr_priority_groups)) {
+		DMWARN("invalid PG number supplied to bypass_pg");
+		return -EINVAL;
+	}
+
+	list_for_each_entry(pg, &m->priority_groups, list) {
+		if (!--pgnum)
+			break;
+	}
+
+	bypass_pg(m, pg, bypassed);
+	return 0;
+}
+
+/*
+ * pg_init must call this when it has completed its initialisation
+ */
+void dm_pg_init_complete(struct path *path, unsigned err_flags)
+{
+	struct pgpath *pgpath = path_to_pgpath(path);
+	struct priority_group *pg = pgpath->pg;
+	struct multipath *m = pg->m;
+	unsigned long flags;
+
+	/* We insist on failing the path if the PG is already bypassed. */
+	if (err_flags && pg->bypassed)
+		err_flags |= MP_FAIL_PATH;
+
+	if (err_flags & MP_FAIL_PATH)
+		fail_path(pgpath);
+
+	if (err_flags & MP_BYPASS_PG)
+		bypass_pg(m, pg, 1);
+
+	spin_lock_irqsave(&m->lock, flags);
+	if (!err_flags)
+		m->queue_io = 0;
+	else {
+		m->current_pgpath = NULL;
+		m->current_pg = NULL;
+	}
+	schedule_work(&m->process_queued_ios);
+	spin_unlock_irqrestore(&m->lock, flags);
+}
+
+/*
+ * end_io handling
+ */
+static int do_end_io(struct multipath *m, struct bio *bio,
+		     int error, struct mpath_io *mpio)
+{
+	struct hw_handler *hwh = &m->hw_handler;
+	unsigned err_flags = MP_FAIL_PATH;	/* Default behavior */
+
+	if (!error)
+		return 0;	/* I/O complete */
+
+	spin_lock(&m->lock);
+	if (!m->nr_valid_paths) {
+		if (!m->queue_if_no_path || m->suspended) {
+			spin_unlock(&m->lock);
+			return -EIO;
+		} else {
+			spin_unlock(&m->lock);
+			goto requeue;
+		}
+	}
+	spin_unlock(&m->lock);
+
+	if (hwh->type && hwh->type->error)
+		err_flags = hwh->type->error(hwh, bio);
+
+	if (mpio->pgpath) {
+		if (err_flags & MP_FAIL_PATH)
+			fail_path(mpio->pgpath);
+
+		if (err_flags & MP_BYPASS_PG)
+			bypass_pg(m, mpio->pgpath->pg, 1);
+	}
+
+	if (err_flags & MP_ERROR_IO)
+		return -EIO;
+
+      requeue:
+	dm_bio_restore(&mpio->details, bio);
+
+	/* queue for the daemon to resubmit or fail */
+	spin_lock(&m->lock);
+	bio_list_add(&m->queued_ios, bio);
+	m->queue_size++;
+	if (!m->queue_io)
+		schedule_work(&m->process_queued_ios);
+	spin_unlock(&m->lock);
+
+	return 1;	/* io not complete */
+}
+
+static int multipath_end_io(struct dm_target *ti, struct bio *bio,
+			    int error, union map_info *map_context)
+{
+	struct multipath *m = (struct multipath *) ti->private;
+	struct mpath_io *mpio = (struct mpath_io *) map_context->ptr;
+	struct pgpath *pgpath = mpio->pgpath;
+	struct path_selector *ps;
+	int r;
+
+	r  = do_end_io(m, bio, error, mpio);
+	if (pgpath) {
+		ps = &pgpath->pg->ps;
+		if (ps->type->end_io)
+			ps->type->end_io(ps, &pgpath->path);
+	}
+	if (r <= 0)
+		mempool_free(mpio, m->mpio_pool);
+
+	return r;
+}
+
+/*
+ * Suspend can't complete until all the I/O is processed so if
+ * the last path failed we will now error any queued I/O.
+ */
+static void multipath_presuspend(struct dm_target *ti)
+{
+	struct multipath *m = (struct multipath *) ti->private;
+	unsigned long flags;
+
+	spin_lock_irqsave(&m->lock, flags);
+	m->suspended = 1;
+	if (m->queue_if_no_path)
+		schedule_work(&m->process_queued_ios);
+	spin_unlock_irqrestore(&m->lock, flags);
+}
+
+static void multipath_resume(struct dm_target *ti)
+{
+	struct multipath *m = (struct multipath *) ti->private;
+	unsigned long flags;
+
+	spin_lock_irqsave(&m->lock, flags);
+	m->suspended = 0;
+	spin_unlock_irqrestore(&m->lock, flags);
+}
+
+/*
+ * Info output has the following format:
+ * num_multipath_feature_args [multipath_feature_args]*
+ * num_handler_status_args [handler_status_args]*
+ * num_groups init_group_number
+ *            [A|D|E num_ps_status_args [ps_status_args]*
+ *             num_paths num_selector_args
+ *             [path_dev A|F fail_count [selector_args]* ]+ ]+
+ *
+ * Table output has the following format (identical to the constructor string):
+ * num_feature_args [features_args]*
+ * num_handler_args hw_handler [hw_handler_args]*
+ * num_groups init_group_number
+ *     [priority selector-name num_ps_args [ps_args]*
+ *      num_paths num_selector_args [path_dev [selector_args]* ]+ ]+
+ */
+static int multipath_status(struct dm_target *ti, status_type_t type,
+			    char *result, unsigned int maxlen)
+{
+	int sz = 0;
+	unsigned long flags;
+	struct multipath *m = (struct multipath *) ti->private;
+	struct hw_handler *hwh = &m->hw_handler;
+	struct priority_group *pg;
+	struct pgpath *p;
+	unsigned pg_num;
+	char state;
+
+	spin_lock_irqsave(&m->lock, flags);
+
+	/* Features */
+	if (type == STATUSTYPE_INFO)
+		DMEMIT("1 %u ", m->queue_size);
+	else if (m->queue_if_no_path)
+		DMEMIT("1 queue_if_no_path ");
+	else
+		DMEMIT("0 ");
+
+	if (hwh->type && hwh->type->status)
+		sz += hwh->type->status(hwh, type, result + sz, maxlen - sz);
+	else if (!hwh->type || type == STATUSTYPE_INFO)
+		DMEMIT("0 ");
+	else
+		DMEMIT("1 %s ", hwh->type->name);
+
+	DMEMIT("%u ", m->nr_priority_groups);
+
+	if (m->next_pg)
+		pg_num = m->next_pg->pg_num;
+	else if (m->current_pg)
+		pg_num = m->current_pg->pg_num;
+	else
+			pg_num = 1;
+
+	DMEMIT("%u ", pg_num);
+
+	switch (type) {
+	case STATUSTYPE_INFO:
+		list_for_each_entry(pg, &m->priority_groups, list) {
+			if (pg->bypassed)
+				state = 'D';	/* Disabled */
+			else if (pg == m->current_pg)
+				state = 'A';	/* Currently Active */
+			else
+				state = 'E';	/* Enabled */
+
+			DMEMIT("%c ", state);
+
+			if (pg->ps.type->status)
+				sz += pg->ps.type->status(&pg->ps, NULL, type,
+							  result + sz,
+							  maxlen - sz);
+			else
+				DMEMIT("0 ");
+
+			DMEMIT("%u %u ", pg->nr_pgpaths,
+			       pg->ps.type->info_args);
+
+			list_for_each_entry(p, &pg->pgpaths, list) {
+				DMEMIT("%s %s %u ", p->path.dev->name,
+				       p->path.is_active ? "A" : "F",
+				       p->fail_count);
+				if (pg->ps.type->status)
+					sz += pg->ps.type->status(&pg->ps,
+					      &p->path, type, result + sz,
+					      maxlen - sz);
+			}
+		}
+		break;
+
+	case STATUSTYPE_TABLE:
+		list_for_each_entry(pg, &m->priority_groups, list) {
+			DMEMIT("%s ", pg->ps.type->name);
+
+			if (pg->ps.type->status)
+				sz += pg->ps.type->status(&pg->ps, NULL, type,
+							  result + sz,
+							  maxlen - sz);
+			else
+				DMEMIT("0 ");
+
+			DMEMIT("%u %u ", pg->nr_pgpaths,
+			       pg->ps.type->table_args);
+
+			list_for_each_entry(p, &pg->pgpaths, list) {
+				DMEMIT("%s ", p->path.dev->name);
+				if (pg->ps.type->status)
+					sz += pg->ps.type->status(&pg->ps,
+					      &p->path, type, result + sz,
+					      maxlen - sz);
+			}
+		}
+		break;
+	}
+
+	spin_unlock_irqrestore(&m->lock, flags);
+
+	return 0;
+}
+
+static int multipath_message(struct dm_target *ti, unsigned argc, char **argv)
+{
+	int r;
+	struct dm_dev *dev;
+	struct multipath *m = (struct multipath *) ti->private;
+	action_fn action;
+
+	if (argc == 1) {
+		if (!strnicmp(argv[0], MESG_STR("queue_if_no_path")))
+			return queue_if_no_path(m, 1);
+		else if (!strnicmp(argv[0], MESG_STR("fail_if_no_path")))
+			return queue_if_no_path(m, 0);
+	}
+
+	if (argc != 2)
+		goto error;
+
+	if (!strnicmp(argv[0], MESG_STR("disable_group")))
+		return bypass_pg_num(m, argv[1], 1);
+	else if (!strnicmp(argv[0], MESG_STR("enable_group")))
+		return bypass_pg_num(m, argv[1], 0);
+	else if (!strnicmp(argv[0], MESG_STR("switch_group")))
+		return switch_pg_num(m, argv[1]);
+	else if (!strnicmp(argv[0], MESG_STR("reinstate_path")))
+		action = reinstate_path;
+	else if (!strnicmp(argv[0], MESG_STR("fail_path")))
+		action = fail_path;
+	else
+		goto error;
+
+	r = dm_get_device(ti, argv[1], ti->begin, ti->len,
+			  dm_table_get_mode(ti->table), &dev);
+	if (r) {
+		DMWARN("dm-multipath message: error getting device %s",
+		       argv[1]);
+		return -EINVAL;
+	}
+
+	r = action_dev(m, dev, action);
+
+	dm_put_device(ti, dev);
+
+	return r;
+
+error:
+	DMWARN("Unrecognised multipath message received.");
+	return -EINVAL;
+}
+
+/*-----------------------------------------------------------------
+ * Module setup
+ *---------------------------------------------------------------*/
+static struct target_type multipath_target = {
+	.name = "multipath",
+	.version = {1, 0, 4},
+	.module = THIS_MODULE,
+	.ctr = multipath_ctr,
+	.dtr = multipath_dtr,
+	.map = multipath_map,
+	.end_io = multipath_end_io,
+	.presuspend = multipath_presuspend,
+	.resume = multipath_resume,
+	.status = multipath_status,
+	.message = multipath_message,
+};
+
+static int __init dm_multipath_init(void)
+{
+	int r;
+
+	/* allocate a slab for the dm_ios */
+	_mpio_cache = kmem_cache_create("dm_mpath", sizeof(struct mpath_io),
+					0, 0, NULL, NULL);
+	if (!_mpio_cache)
+		return -ENOMEM;
+
+	r = dm_register_target(&multipath_target);
+	if (r < 0) {
+		DMERR("%s: register failed %d", multipath_target.name, r);
+		kmem_cache_destroy(_mpio_cache);
+		return -EINVAL;
+	}
+
+	DMINFO("dm-multipath version %u.%u.%u loaded",
+	       multipath_target.version[0], multipath_target.version[1],
+	       multipath_target.version[2]);
+
+	return r;
+}
+
+static void __exit dm_multipath_exit(void)
+{
+	int r;
+
+	r = dm_unregister_target(&multipath_target);
+	if (r < 0)
+		DMERR("%s: target unregister failed %d",
+		      multipath_target.name, r);
+	kmem_cache_destroy(_mpio_cache);
+}
+
+EXPORT_SYMBOL_GPL(dm_pg_init_complete);
+
+module_init(dm_multipath_init);
+module_exit(dm_multipath_exit);
+
+MODULE_DESCRIPTION(DM_NAME " multipath target");
+MODULE_AUTHOR("Sistina Software <dm-devel@redhat.com>");
+MODULE_LICENSE("GPL");
diff -Nru a/drivers/md/dm-mpath.h b/drivers/md/dm-mpath.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/md/dm-mpath.h	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
+ *
+ * This file is released under the GPL.
+ *
+ * Multipath.
+ */
+
+#ifndef	DM_MPATH_H
+#define	DM_MPATH_H
+
+struct dm_dev;
+
+struct path {
+	struct dm_dev *dev;	/* Read-only */
+	unsigned is_active;	/* Read-only */
+
+	void *pscontext;	/* For path-selector use */
+	void *hwhcontext;	/* For hw-handler use */
+};
+
+/* Callback for hwh_pg_init_fn to use when complete */
+void dm_pg_init_complete(struct path *path, unsigned err_flags);
+
+#endif
diff -Nru a/drivers/md/dm-path-selector.c b/drivers/md/dm-path-selector.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/md/dm-path-selector.c	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,156 @@
+/*
+ * Copyright (C) 2003 Sistina Software.
+ * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
+ *
+ * Module Author: Heinz Mauelshagen
+ *
+ * This file is released under the GPL.
+ *
+ * Path selector registration.
+ */
+
+#include "dm.h"
+#include "dm-path-selector.h"
+
+#include <linux/slab.h>
+
+struct ps_internal {
+	struct path_selector_type pst;
+
+	struct list_head list;
+	long use;
+};
+
+#define pst_to_psi(__pst) container_of((__pst), struct ps_internal, pst)
+
+static LIST_HEAD(_path_selectors);
+static DECLARE_RWSEM(_ps_lock);
+
+struct ps_internal *__find_path_selector_type(const char *name)
+{
+	struct ps_internal *psi;
+
+	list_for_each_entry(psi, &_path_selectors, list) {
+		if (!strcmp(name, psi->pst.name))
+			return psi;
+	}
+
+	return NULL;
+}
+
+static struct ps_internal *get_path_selector(const char *name)
+{
+	struct ps_internal *psi;
+
+	down_read(&_ps_lock);
+	psi = __find_path_selector_type(name);
+	if (psi) {
+		if ((psi->use == 0) && !try_module_get(psi->pst.module))
+			psi = NULL;
+		else
+			psi->use++;
+	}
+	up_read(&_ps_lock);
+
+	return psi;
+}
+
+struct path_selector_type *dm_get_path_selector(const char *name)
+{
+	struct ps_internal *psi;
+
+	if (!name)
+		return NULL;
+
+	psi = get_path_selector(name);
+	if (!psi) {
+		request_module("dm-%s", name);
+		psi = get_path_selector(name);
+	}
+
+	return psi ? &psi->pst : NULL;
+}
+
+void dm_put_path_selector(struct path_selector_type *pst)
+{
+	struct ps_internal *psi;
+
+	if (!pst)
+		return;
+
+	down_read(&_ps_lock);
+	psi = __find_path_selector_type(pst->name);
+	if (!psi)
+		goto out;
+
+	if (--psi->use == 0)
+		module_put(psi->pst.module);
+
+	if (psi->use < 0)
+		BUG();
+
+out:
+	up_read(&_ps_lock);
+}
+
+static struct ps_internal *_alloc_path_selector(struct path_selector_type *pst)
+{
+	struct ps_internal *psi = kmalloc(sizeof(*psi), GFP_KERNEL);
+
+	if (psi) {
+		memset(psi, 0, sizeof(*psi));
+		psi->pst = *pst;
+	}
+
+	return psi;
+}
+
+int dm_register_path_selector(struct path_selector_type *pst)
+{
+	int r = 0;
+	struct ps_internal *psi = _alloc_path_selector(pst);
+
+	if (!psi)
+		return -ENOMEM;
+
+	down_write(&_ps_lock);
+
+	if (__find_path_selector_type(pst->name)) {
+		kfree(psi);
+		r = -EEXIST;
+	} else
+		list_add(&psi->list, &_path_selectors);
+
+	up_write(&_ps_lock);
+
+	return r;
+}
+
+int dm_unregister_path_selector(struct path_selector_type *pst)
+{
+	struct ps_internal *psi;
+
+	down_write(&_ps_lock);
+
+	psi = __find_path_selector_type(pst->name);
+	if (!psi) {
+		up_write(&_ps_lock);
+		return -EINVAL;
+	}
+
+	if (psi->use) {
+		up_write(&_ps_lock);
+		return -ETXTBSY;
+	}
+
+	list_del(&psi->list);
+
+	up_write(&_ps_lock);
+
+	kfree(psi);
+
+	return 0;
+}
+
+EXPORT_SYMBOL_GPL(dm_register_path_selector);
+EXPORT_SYMBOL_GPL(dm_unregister_path_selector);
diff -Nru a/drivers/md/dm-path-selector.h b/drivers/md/dm-path-selector.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/md/dm-path-selector.h	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2003 Sistina Software.
+ * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
+ *
+ * Module Author: Heinz Mauelshagen
+ *
+ * This file is released under the GPL.
+ *
+ * Path-Selector registration.
+ */
+
+#ifndef	DM_PATH_SELECTOR_H
+#define	DM_PATH_SELECTOR_H
+
+#include <linux/device-mapper.h>
+
+#include "dm-mpath.h"
+
+/*
+ * We provide an abstraction for the code that chooses which path
+ * to send some io down.
+ */
+struct path_selector_type;
+struct path_selector {
+	struct path_selector_type *type;
+	void *context;
+};
+
+/* Information about a path selector type */
+struct path_selector_type {
+	char *name;
+	struct module *module;
+
+	unsigned int table_args;
+	unsigned int info_args;
+
+	/*
+	 * Constructs a path selector object, takes custom arguments
+	 */
+	int (*create) (struct path_selector *ps, unsigned argc, char **argv);
+	void (*destroy) (struct path_selector *ps);
+
+	/*
+	 * Add an opaque path object, along with some selector specific
+	 * path args (eg, path priority).
+	 */
+	int (*add_path) (struct path_selector *ps, struct path *path,
+			 int argc, char **argv, char **error);
+
+	/*
+	 * Chooses a path for this io, if no paths are available then
+	 * NULL will be returned.
+	 *
+	 * repeat_count is the number of times to use the path before
+	 * calling the function again.  0 means don't call it again unless
+	 * the path fails.
+	 */
+	struct path *(*select_path) (struct path_selector *ps,
+				     unsigned *repeat_count);
+
+	/*
+	 * Notify the selector that a path has failed.
+	 */
+	void (*fail_path) (struct path_selector *ps, struct path *p);
+
+	/*
+	 * Ask selector to reinstate a path.
+	 */
+	int (*reinstate_path) (struct path_selector *ps, struct path *p);
+
+	/*
+	 * Table content based on parameters added in ps_add_path_fn
+	 * or path selector status
+	 */
+	int (*status) (struct path_selector *ps, struct path *path,
+		       status_type_t type, char *result, unsigned int maxlen);
+
+	int (*end_io) (struct path_selector *ps, struct path *path);
+};
+
+/* Register a path selector */
+int dm_register_path_selector(struct path_selector_type *type);
+
+/* Unregister a path selector */
+int dm_unregister_path_selector(struct path_selector_type *type);
+
+/* Returns a registered path selector type */
+struct path_selector_type *dm_get_path_selector(const char *name);
+
+/* Releases a path selector  */
+void dm_put_path_selector(struct path_selector_type *pst);
+
+#endif
diff -Nru a/drivers/md/dm-raid1.c b/drivers/md/dm-raid1.c
--- a/drivers/md/dm-raid1.c	2005-03-11 12:51:52 -08:00
+++ b/drivers/md/dm-raid1.c	2005-03-11 12:51:52 -08:00
@@ -1182,7 +1182,6 @@
 static int mirror_status(struct dm_target *ti, status_type_t type,
 			 char *result, unsigned int maxlen)
 {
-	char buffer[32];
 	unsigned int m, sz;
 	struct mirror_set *ms = (struct mirror_set *) ti->private;
 
@@ -1191,10 +1190,8 @@
 	switch (type) {
 	case STATUSTYPE_INFO:
 		DMEMIT("%d ", ms->nr_mirrors);
-		for (m = 0; m < ms->nr_mirrors; m++) {
-			format_dev_t(buffer, ms->mirror[m].dev->bdev->bd_dev);
-			DMEMIT("%s ", buffer);
-		}
+		for (m = 0; m < ms->nr_mirrors; m++)
+			DMEMIT("%s ", ms->mirror[m].dev->name);
 
 		DMEMIT(SECTOR_FORMAT "/" SECTOR_FORMAT,
 		       ms->rh.log->type->get_sync_count(ms->rh.log),
@@ -1203,11 +1200,9 @@
 
 	case STATUSTYPE_TABLE:
 		DMEMIT("%d ", ms->nr_mirrors);
-		for (m = 0; m < ms->nr_mirrors; m++) {
-			format_dev_t(buffer, ms->mirror[m].dev->bdev->bd_dev);
+		for (m = 0; m < ms->nr_mirrors; m++)
 			DMEMIT("%s " SECTOR_FORMAT " ",
-			       buffer, ms->mirror[m].offset);
-		}
+			       ms->mirror[m].dev->name, ms->mirror[m].offset);
 	}
 
 	return 0;
diff -Nru a/drivers/md/dm-round-robin.c b/drivers/md/dm-round-robin.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/md/dm-round-robin.c	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,214 @@
+/*
+ * Copyright (C) 2003 Sistina Software.
+ * Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
+ *
+ * Module Author: Heinz Mauelshagen
+ *
+ * This file is released under the GPL.
+ *
+ * Round-robin path selector.
+ */
+
+#include "dm.h"
+#include "dm-path-selector.h"
+
+#include <linux/slab.h>
+
+/*-----------------------------------------------------------------
+ * Path-handling code, paths are held in lists
+ *---------------------------------------------------------------*/
+struct path_info {
+	struct list_head list;
+	struct path *path;
+	unsigned repeat_count;
+};
+
+static void free_paths(struct list_head *paths)
+{
+	struct path_info *pi, *next;
+
+	list_for_each_entry_safe(pi, next, paths, list) {
+		list_del(&pi->list);
+		kfree(pi);
+	}
+}
+
+/*-----------------------------------------------------------------
+ * Round-robin selector
+ *---------------------------------------------------------------*/
+
+#define RR_MIN_IO		1000
+
+struct selector {
+	struct list_head valid_paths;
+	struct list_head invalid_paths;
+};
+
+static struct selector *alloc_selector(void)
+{
+	struct selector *s = kmalloc(sizeof(*s), GFP_KERNEL);
+
+	if (s) {
+		INIT_LIST_HEAD(&s->valid_paths);
+		INIT_LIST_HEAD(&s->invalid_paths);
+	}
+
+	return s;
+}
+
+static int rr_create(struct path_selector *ps, unsigned argc, char **argv)
+{
+	struct selector *s;
+
+	s = alloc_selector();
+	if (!s)
+		return -ENOMEM;
+
+	ps->context = s;
+	return 0;
+}
+
+static void rr_destroy(struct path_selector *ps)
+{
+	struct selector *s = (struct selector *) ps->context;
+
+	free_paths(&s->valid_paths);
+	free_paths(&s->invalid_paths);
+	kfree(s);
+	ps->context = NULL;
+}
+
+static int rr_status(struct path_selector *ps, struct path *path,
+		     status_type_t type, char *result, unsigned int maxlen)
+{
+	struct path_info *pi;
+	int sz = 0;
+
+	if (!path)
+		DMEMIT("0 ");
+	else {
+		switch(type) {
+		case STATUSTYPE_INFO:
+			break;
+		case STATUSTYPE_TABLE:
+			pi = path->pscontext;
+			DMEMIT("%u ", pi->repeat_count);
+			break;
+		}
+	}
+
+	return sz;
+}
+
+/*
+ * Called during initialisation to register each path with an
+ * optional repeat_count.
+ */
+static int rr_add_path(struct path_selector *ps, struct path *path,
+		       int argc, char **argv, char **error)
+{
+	struct selector *s = (struct selector *) ps->context;
+	struct path_info *pi;
+	unsigned repeat_count = RR_MIN_IO;
+
+	if (argc > 1) {
+		*error = "round-robin ps: incorrect number of arguments";
+		return -EINVAL;
+	}
+
+	/* First path argument is number of I/Os before switching path */
+	if ((argc == 1) && (sscanf(argv[0], "%u", &repeat_count) != 1)) {
+		*error = "round-robin ps: invalid repeat count";
+		return -EINVAL;
+	}
+
+	/* allocate the path */
+	pi = kmalloc(sizeof(*pi), GFP_KERNEL);
+	if (!pi) {
+		*error = "round-robin ps: Error allocating path context";
+		return -ENOMEM;
+	}
+
+	pi->path = path;
+	pi->repeat_count = repeat_count;
+
+	path->pscontext = pi;
+
+	list_add(&pi->list, &s->valid_paths);
+
+	return 0;
+}
+
+static void rr_fail_path(struct path_selector *ps, struct path *p)
+{
+	struct selector *s = (struct selector *) ps->context;
+	struct path_info *pi = p->pscontext;
+
+	list_move(&pi->list, &s->invalid_paths);
+}
+
+static int rr_reinstate_path(struct path_selector *ps, struct path *p)
+{
+	struct selector *s = (struct selector *) ps->context;
+	struct path_info *pi = p->pscontext;
+
+	list_move(&pi->list, &s->valid_paths);
+
+	return 0;
+}
+
+static struct path *rr_select_path(struct path_selector *ps,
+				   unsigned *repeat_count)
+{
+	struct selector *s = (struct selector *) ps->context;
+	struct path_info *pi = NULL;
+
+	if (!list_empty(&s->valid_paths)) {
+		pi = list_entry(s->valid_paths.next, struct path_info, list);
+		list_move_tail(&pi->list, &s->valid_paths);
+		*repeat_count = pi->repeat_count;
+	}
+
+	return pi ? pi->path : NULL;
+}
+
+static struct path_selector_type rr_ps = {
+	.name = "round-robin",
+	.module = THIS_MODULE,
+	.table_args = 1,
+	.info_args = 0,
+	.create = rr_create,
+	.destroy = rr_destroy,
+	.status = rr_status,
+	.add_path = rr_add_path,
+	.fail_path = rr_fail_path,
+	.reinstate_path = rr_reinstate_path,
+	.select_path = rr_select_path,
+};
+
+static int __init dm_rr_init(void)
+{
+	int r = dm_register_path_selector(&rr_ps);
+
+	if (r < 0)
+		DMERR("round-robin: register failed %d", r);
+
+	DMINFO("dm-round-robin version 1.0.0 loaded");
+
+	return r;
+}
+
+static void __exit dm_rr_exit(void)
+{
+	int r = dm_unregister_path_selector(&rr_ps);
+
+	if (r < 0)
+		DMERR("round-robin: unregister failed %d", r);
+}
+
+module_init(dm_rr_init);
+module_exit(dm_rr_exit);
+
+MODULE_DESCRIPTION(DM_NAME " round-robin multipath path selector");
+MODULE_AUTHOR("Sistina Software <dm-devel@redhat.com>");
+MODULE_LICENSE("GPL");
diff -Nru a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c
--- a/drivers/md/dm-snap.c	2005-03-11 12:51:48 -08:00
+++ b/drivers/md/dm-snap.c	2005-03-11 12:51:48 -08:00
@@ -864,8 +864,6 @@
 			   char *result, unsigned int maxlen)
 {
 	struct dm_snapshot *snap = (struct dm_snapshot *) ti->private;
-	char cow[32];
-	char org[32];
 
 	switch (type) {
 	case STATUSTYPE_INFO:
@@ -892,9 +890,8 @@
 		 * to make private copies if the output is to
 		 * make sense.
 		 */
-		format_dev_t(cow, snap->cow->bdev->bd_dev);
-		format_dev_t(org, snap->origin->bdev->bd_dev);
-		snprintf(result, maxlen, "%s %s %c " SECTOR_FORMAT, org, cow,
+		snprintf(result, maxlen, "%s %s %c " SECTOR_FORMAT,
+			 snap->origin->name, snap->cow->name,
 			 snap->type, snap->chunk_size);
 		break;
 	}
@@ -1082,7 +1079,6 @@
 			 unsigned int maxlen)
 {
 	struct dm_dev *dev = (struct dm_dev *) ti->private;
-	char buffer[32];
 
 	switch (type) {
 	case STATUSTYPE_INFO:
@@ -1090,8 +1086,7 @@
 		break;
 
 	case STATUSTYPE_TABLE:
-		format_dev_t(buffer, dev->bdev->bd_dev);
-		snprintf(result, maxlen, "%s", buffer);
+		snprintf(result, maxlen, "%s", dev->name);
 		break;
 	}
 
diff -Nru a/drivers/md/dm-stripe.c b/drivers/md/dm-stripe.c
--- a/drivers/md/dm-stripe.c	2005-03-11 12:51:46 -08:00
+++ b/drivers/md/dm-stripe.c	2005-03-11 12:51:46 -08:00
@@ -188,7 +188,6 @@
 	struct stripe_c *sc = (struct stripe_c *) ti->private;
 	unsigned int sz = 0;
 	unsigned int i;
-	char buffer[32];
 
 	switch (type) {
 	case STATUSTYPE_INFO:
@@ -197,11 +196,9 @@
 
 	case STATUSTYPE_TABLE:
 		DMEMIT("%d " SECTOR_FORMAT, sc->stripes, sc->chunk_mask + 1);
-		for (i = 0; i < sc->stripes; i++) {
-			format_dev_t(buffer, sc->stripe[i].dev->bdev->bd_dev);
-			DMEMIT(" %s " SECTOR_FORMAT, buffer,
+		for (i = 0; i < sc->stripes; i++)
+			DMEMIT(" %s " SECTOR_FORMAT, sc->stripe[i].dev->name,
 			       sc->stripe[i].physical_start);
-		}
 		break;
 	}
 	return 0;
diff -Nru a/drivers/md/dm-table.c b/drivers/md/dm-table.c
--- a/drivers/md/dm-table.c	2005-03-11 12:51:51 -08:00
+++ b/drivers/md/dm-table.c	2005-03-11 12:51:51 -08:00
@@ -455,6 +455,8 @@
 			return r;
 		}
 
+		format_dev_t(dd->name, dev);
+
 		atomic_set(&dd->count, 0);
 		list_add(&dd->list, &t->devices);
 
diff -Nru a/drivers/md/dm-zero.c b/drivers/md/dm-zero.c
--- a/drivers/md/dm-zero.c	2005-03-11 12:51:47 -08:00
+++ b/drivers/md/dm-zero.c	2005-03-11 12:51:47 -08:00
@@ -24,23 +24,6 @@
 }
 
 /*
- * Fills the bio pages with zeros
- */
-static void zero_fill_bio(struct bio *bio)
-{
-	unsigned long flags;
-	struct bio_vec *bv;
-	int i;
-
-	bio_for_each_segment(bv, bio, i) {
-		char *data = bvec_kmap_irq(bv, &flags);
-		memset(data, 0, bv->bv_len);
-		flush_dcache_page(bv->bv_page);
-		bvec_kunmap_irq(data, &flags);
-	}
-}
-
-/*
  * Return zeros only on reads
  */
 static int zero_map(struct dm_target *ti, struct bio *bio,
diff -Nru a/drivers/md/dm.c b/drivers/md/dm.c
--- a/drivers/md/dm.c	2005-03-11 12:51:50 -08:00
+++ b/drivers/md/dm.c	2005-03-11 12:51:50 -08:00
@@ -43,6 +43,13 @@
 	union map_info info;
 };
 
+union map_info *dm_get_mapinfo(struct bio *bio)
+{
+        if (bio && bio->bi_private)
+                return &((struct target_io *)bio->bi_private)->info;
+        return NULL;
+}
+
 /*
  * Bits for the md->flags field.
  */
@@ -96,10 +103,16 @@
 static kmem_cache_t *_io_cache;
 static kmem_cache_t *_tio_cache;
 
+static struct bio_set *dm_set;
+
 static int __init local_init(void)
 {
 	int r;
 
+	dm_set = bioset_create(16, 16, 4);
+	if (!dm_set)
+		return -ENOMEM;
+
 	/* allocate a slab for the dm_ios */
 	_io_cache = kmem_cache_create("dm_io",
 				      sizeof(struct dm_io), 0, 0, NULL, NULL);
@@ -133,6 +146,8 @@
 	kmem_cache_destroy(_tio_cache);
 	kmem_cache_destroy(_io_cache);
 
+	bioset_free(dm_set);
+
 	if (unregister_blkdev(_major, _name) < 0)
 		DMERR("devfs_unregister_blkdev failed");
 
@@ -393,7 +408,7 @@
 	struct bio *clone;
 	struct bio_vec *bv = bio->bi_io_vec + idx;
 
-	clone = bio_alloc(GFP_NOIO, 1);
+	clone = bio_alloc_bioset(GFP_NOIO, 1, dm_set);
 	*clone->bi_io_vec = *bv;
 
 	clone->bi_sector = sector;
@@ -1163,6 +1178,8 @@
 	.release = dm_blk_close,
 	.owner = THIS_MODULE
 };
+
+EXPORT_SYMBOL(dm_get_mapinfo);
 
 /*
  * module hooks
diff -Nru a/drivers/md/dm.h b/drivers/md/dm.h
--- a/drivers/md/dm.h	2005-03-11 12:51:43 -08:00
+++ b/drivers/md/dm.h	2005-03-11 12:51:43 -08:00
@@ -44,6 +44,7 @@
 	atomic_t count;
 	int mode;
 	struct block_device *bdev;
+	char name[16];
 };
 
 struct dm_table;
@@ -189,5 +190,6 @@
 void dm_stripe_exit(void);
 
 void *dm_vcalloc(unsigned long nmemb, unsigned long elem_size);
+union map_info *dm_get_mapinfo(struct bio *bio);
 
 #endif
diff -Nru a/drivers/md/md.c b/drivers/md/md.c
--- a/drivers/md/md.c	2005-03-11 12:51:42 -08:00
+++ b/drivers/md/md.c	2005-03-11 12:51:42 -08:00
@@ -940,7 +940,7 @@
 	
 	sb->max_dev = cpu_to_le32(max_dev);
 	for (i=0; i<max_dev;i++)
-		sb->dev_roles[max_dev] = cpu_to_le16(0xfffe);
+		sb->dev_roles[i] = cpu_to_le16(0xfffe);
 	
 	ITERATE_RDEV(mddev,rdev2,tmp) {
 		i = rdev2->desc_nr;
diff -Nru a/drivers/md/raid6altivec.uc b/drivers/md/raid6altivec.uc
--- a/drivers/md/raid6altivec.uc	2005-03-11 12:51:51 -08:00
+++ b/drivers/md/raid6altivec.uc	2005-03-11 12:51:51 -08:00
@@ -108,7 +108,7 @@
 int raid6_have_altivec(void)
 {
 	/* This assumes either all CPUs have Altivec or none does */
-	return cur_cpu_spec->cpu_features & CPU_FTR_ALTIVEC;
+	return cpu_has_feature(CPU_FTR_ALTIVEC);
 }
 #endif
 
diff -Nru a/drivers/media/common/saa7146_i2c.c b/drivers/media/common/saa7146_i2c.c
--- a/drivers/media/common/saa7146_i2c.c	2005-03-11 12:51:51 -08:00
+++ b/drivers/media/common/saa7146_i2c.c	2005-03-11 12:51:51 -08:00
@@ -25,7 +25,7 @@
    sent through the saa7146. have a look at the specifications p. 122 ff 
    to understand this. it returns the number of u32s to send, or -1
    in case of an error. */
-static int saa7146_i2c_msg_prepare(const struct i2c_msg m[], int num, u32 *op)
+static int saa7146_i2c_msg_prepare(const struct i2c_msg *m, int num, u32 *op)
 {
 	int h1, h2;
 	int i, j, addr;
@@ -89,7 +89,7 @@
    which bytes were read through the adapter and write them back to the corresponding
    i2c-message. but instead, we simply write back all bytes.
    fixme: this could be improved. */
-static int saa7146_i2c_msg_cleanup(const struct i2c_msg m[], int num, u32 *op)
+static int saa7146_i2c_msg_cleanup(const struct i2c_msg *m, int num, u32 *op)
 {
 	int i, j;
 	int op_count = 0;
@@ -272,7 +272,7 @@
 	return 0;
 }
 
-int saa7146_i2c_transfer(struct saa7146_dev *dev, const struct i2c_msg msgs[], int num, int retries)
+int saa7146_i2c_transfer(struct saa7146_dev *dev, const struct i2c_msg *msgs, int num, int retries)
 {
 	int i = 0, count = 0;
 	u32* buffer = dev->d_i2c.cpu_addr;
@@ -372,7 +372,7 @@
 }
 
 /* utility functions */
-static int saa7146_i2c_xfer(struct i2c_adapter* adapter, struct i2c_msg msg[], int num)
+static int saa7146_i2c_xfer(struct i2c_adapter* adapter, struct i2c_msg *msg, int num)
 {
 	struct saa7146_dev* dev = i2c_get_adapdata(adapter);
 	
diff -Nru a/drivers/media/common/saa7146_video.c b/drivers/media/common/saa7146_video.c
--- a/drivers/media/common/saa7146_video.c	2005-03-11 12:51:47 -08:00
+++ b/drivers/media/common/saa7146_video.c	2005-03-11 12:51:47 -08:00
@@ -889,7 +889,7 @@
 		
                 strcpy(cap->driver, "saa7146 v4l2");
 		strlcpy(cap->card, dev->ext->name, sizeof(cap->card));
-		sprintf(cap->bus_info,"PCI:%s",dev->pci->slot_name);
+		sprintf(cap->bus_info,"PCI:%s", pci_name(dev->pci));
 		cap->version = SAA7146_VERSION_CODE;
 		cap->capabilities =
 			V4L2_CAP_VIDEO_CAPTURE |
diff -Nru a/drivers/media/dvb/b2c2/b2c2-usb-core.c b/drivers/media/dvb/b2c2/b2c2-usb-core.c
--- a/drivers/media/dvb/b2c2/b2c2-usb-core.c	2005-03-11 12:51:51 -08:00
+++ b/drivers/media/dvb/b2c2/b2c2-usb-core.c	2005-03-11 12:51:51 -08:00
@@ -194,7 +194,7 @@
 			0,
 			&val,
 			sizeof(u32),
-			B2C2_WAIT_FOR_OPERATION_RDW * HZ);
+			B2C2_WAIT_FOR_OPERATION_RDW * 1000);
 
 	if (len != sizeof(u32)) {
 		err("error while reading dword from %d (%d).",wAddress,wRegOffsPCI);
@@ -220,7 +220,7 @@
 			0,
 			&val,
 			sizeof(u32),
-			B2C2_WAIT_FOR_OPERATION_RDW * HZ);
+			B2C2_WAIT_FOR_OPERATION_RDW * 1000);
 
 	if (len != sizeof(u32)) {
 		err("error while reading dword from %d (%d).",wAddress,wRegOffsPCI);
@@ -270,7 +270,7 @@
 			wIndex,
 			pbBuffer,
 			buflen,
-			nWaitTime * HZ);
+			nWaitTime * 1000);
 	return len == buflen ? 0 : -EIO;
 }
 
@@ -312,7 +312,7 @@
 			wIndex,
 			buf,
 			buflen,
-			nWaitTime * HZ);
+			nWaitTime * 1000);
 	return len == buflen ? 0 : -EIO;
 }
 
@@ -334,7 +334,7 @@
 			wIndex,
 			pvBuffer,
 			buflen,
-			nWaitTime * HZ);
+			nWaitTime * 1000);
 	return len == buflen ? 0 : -EIO;
 }
 
diff -Nru a/drivers/media/dvb/b2c2/skystar2.c b/drivers/media/dvb/b2c2/skystar2.c
--- a/drivers/media/dvb/b2c2/skystar2.c	2005-03-11 12:51:52 -08:00
+++ b/drivers/media/dvb/b2c2/skystar2.c	2005-03-11 12:51:52 -08:00
@@ -293,7 +293,7 @@
 	return buf - start;
 }
 
-static int master_xfer(struct i2c_adapter* adapter, struct i2c_msg msgs[], int num)
+static int master_xfer(struct i2c_adapter* adapter, struct i2c_msg *msgs, int num)
 {
 	struct adapter *tmp = i2c_get_adapdata(adapter);
 	int i, ret = 0;
diff -Nru a/drivers/media/dvb/bt8xx/bt878.h b/drivers/media/dvb/bt8xx/bt878.h
--- a/drivers/media/dvb/bt8xx/bt878.h	2005-03-11 12:51:52 -08:00
+++ b/drivers/media/dvb/bt8xx/bt878.h	2005-03-11 12:51:52 -08:00
@@ -89,7 +89,6 @@
 #define BT878_RISC_SYNC_MASK	(1 << 15)
 
 extern int bt878_num;
-extern struct bt878 bt878[BT878_MAX];
 
 struct bt878 {
 	struct semaphore  gpio_lock;
@@ -123,6 +122,8 @@
 	struct tasklet_struct tasklet;
 	int shutdown;	
 };
+
+extern struct bt878 bt878[BT878_MAX];
 
 void bt878_start(struct bt878 *bt, u32 controlreg, u32 op_sync_orin,
 		u32 irq_err_ignore);
diff -Nru a/drivers/media/dvb/cinergyT2/cinergyT2.c b/drivers/media/dvb/cinergyT2/cinergyT2.c
--- a/drivers/media/dvb/cinergyT2/cinergyT2.c	2005-03-11 12:51:46 -08:00
+++ b/drivers/media/dvb/cinergyT2/cinergyT2.c	2005-03-11 12:51:46 -08:00
@@ -212,7 +212,7 @@
 	int ret;
 
 	ret = usb_bulk_msg(cinergyt2->udev, usb_sndbulkpipe(cinergyt2->udev, 1),
-			   send_buf, send_buf_len, &actual_len, HZ);
+			   send_buf, send_buf_len, &actual_len, 1000);
 
 	if (ret)
 		dprintk(1, "usb_bulk_msg (send) failed, err %i\n", ret);
@@ -221,7 +221,7 @@
 		recv_buf = &dummy;
 
 	ret = usb_bulk_msg(cinergyt2->udev, usb_rcvbulkpipe(cinergyt2->udev, 1),
-			   recv_buf, recv_buf_len, &actual_len, HZ);
+			   recv_buf, recv_buf_len, &actual_len, 1000);
 
 	if (ret)
 		dprintk(1, "usb_bulk_msg (read) failed, err %i\n", ret);
diff -Nru a/drivers/media/dvb/dibusb/dvb-dibusb-fe-i2c.c b/drivers/media/dvb/dibusb/dvb-dibusb-fe-i2c.c
--- a/drivers/media/dvb/dibusb/dvb-dibusb-fe-i2c.c	2005-03-11 12:51:47 -08:00
+++ b/drivers/media/dvb/dibusb/dvb-dibusb-fe-i2c.c	2005-03-11 12:51:47 -08:00
@@ -38,7 +38,7 @@
 /*
  * I2C master xfer function
  */
-static int dibusb_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num)
+static int dibusb_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg *msg,int num)
 {
 	struct usb_dibusb *dib = i2c_get_adapdata(adap);
 	int i;
diff -Nru a/drivers/media/dvb/dibusb/dvb-dibusb-firmware.c b/drivers/media/dvb/dibusb/dvb-dibusb-firmware.c
--- a/drivers/media/dvb/dibusb/dvb-dibusb-firmware.c	2005-03-11 12:51:51 -08:00
+++ b/drivers/media/dvb/dibusb/dvb-dibusb-firmware.c	2005-03-11 12:51:51 -08:00
@@ -19,7 +19,7 @@
 static int dibusb_writemem(struct usb_device *udev,u16 addr,u8 *data, u8 len)
 {
 	return usb_control_msg(udev, usb_sndctrlpipe(udev,0),
-			0xa0, USB_TYPE_VENDOR, addr, 0x00, data, len, 5*HZ);
+			0xa0, USB_TYPE_VENDOR, addr, 0x00, data, len, 5000);
 }
 
 int dibusb_loadfirmware(struct usb_device *udev, struct dibusb_usb_device *dibdev)
diff -Nru a/drivers/media/dvb/dibusb/dvb-dibusb.h b/drivers/media/dvb/dibusb/dvb-dibusb.h
--- a/drivers/media/dvb/dibusb/dvb-dibusb.h	2005-03-11 12:51:41 -08:00
+++ b/drivers/media/dvb/dibusb/dvb-dibusb.h	2005-03-11 12:51:41 -08:00
@@ -236,7 +236,7 @@
 int dibusb_ctrl_pid(struct usb_dibusb *dib, struct dvb_demux_feed *dvbdmxfeed , int onoff);
 
 /* i2c and transfer stuff */
-#define DIBUSB_I2C_TIMEOUT				HZ*5
+#define DIBUSB_I2C_TIMEOUT				5000
 
 /* 
  * protocol of all dibusb related devices
diff -Nru a/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c b/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c
--- a/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c	2005-03-11 12:51:51 -08:00
+++ b/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c	2005-03-11 12:51:51 -08:00
@@ -162,7 +162,7 @@
 		return -EAGAIN;
 
 	err = usb_bulk_msg(ttusb->dev, ttusb->bulk_out_pipe,
-			   (u8 *) data, len, &actual_len, HZ);
+			   (u8 *) data, len, &actual_len, 1000);
 	if (err != 0) {
 		dprintk("%s: usb_bulk_msg(send) failed, err == %i!\n",
 			__FUNCTION__, err);
@@ -177,7 +177,7 @@
 	}
 
 	err = usb_bulk_msg(ttusb->dev, ttusb->bulk_in_pipe,
-			   ttusb->last_result, 32, &actual_len, HZ);
+			   ttusb->last_result, 32, &actual_len, 1000);
 
 	if (err != 0) {
 		printk("%s: failed, receive error %d\n", __FUNCTION__,
@@ -252,7 +252,7 @@
 	return rcv_len;
 }
 
-static int master_xfer(struct i2c_adapter* adapter, struct i2c_msg msg[], int num)
+static int master_xfer(struct i2c_adapter* adapter, struct i2c_msg *msg, int num)
 {
 	struct ttusb *ttusb = i2c_get_adapdata(adapter);
 	int i = 0;
diff -Nru a/drivers/media/dvb/ttusb-dec/ttusb_dec.c b/drivers/media/dvb/ttusb-dec/ttusb_dec.c
--- a/drivers/media/dvb/ttusb-dec/ttusb_dec.c	2005-03-11 12:51:51 -08:00
+++ b/drivers/media/dvb/ttusb-dec/ttusb_dec.c	2005-03-11 12:51:51 -08:00
@@ -208,7 +208,7 @@
 	}
 
 	result = usb_bulk_msg(dec->udev, dec->command_pipe, b,
-			      COMMAND_PACKET_SIZE + 4, &actual_len, HZ);
+			      COMMAND_PACKET_SIZE + 4, &actual_len, 1000);
 
 	if (result) {
 		printk("%s: command bulk message failed: error %d\n",
@@ -219,7 +219,7 @@
 	}
 
 	result = usb_bulk_msg(dec->udev, dec->result_pipe, b,
-			      COMMAND_PACKET_SIZE + 4, &actual_len, HZ);
+			      COMMAND_PACKET_SIZE + 4, &actual_len, 1000);
 
 	if (result) {
 		printk("%s: result bulk message failed: error %d\n",
@@ -1205,12 +1205,12 @@
 		if (j >= ARM_PACKET_SIZE) {
 			result = usb_bulk_msg(dec->udev, dec->command_pipe, b,
 					      ARM_PACKET_SIZE, &actual_len,
-					      HZ / 10);
+					      100);
 			j = 0;
 		} else if (size < COMMAND_PACKET_SIZE) {
 			result = usb_bulk_msg(dec->udev, dec->command_pipe, b,
 					      j - COMMAND_PACKET_SIZE + size,
-					      &actual_len, HZ / 10);
+					      &actual_len, 100);
 		}
 	}
 
diff -Nru a/drivers/media/video/Makefile b/drivers/media/video/Makefile
--- a/drivers/media/video/Makefile	2005-03-11 12:51:42 -08:00
+++ b/drivers/media/video/Makefile	2005-03-11 12:51:42 -08:00
@@ -7,6 +7,7 @@
 zoran-objs      :=	zr36120.o zr36120_i2c.o zr36120_mem.o
 zr36067-objs	:=	zoran_procfs.o zoran_device.o \
 			zoran_driver.o zoran_card.o
+tuner-objs	:=	tuner-core.o tuner-simple.o mt20xx.o tda8290.o
 
 obj-$(CONFIG_VIDEO_DEV) += videodev.o v4l2-common.o v4l1-compat.o
 
diff -Nru a/drivers/media/video/adv7170.c b/drivers/media/video/adv7170.c
--- a/drivers/media/video/adv7170.c	2005-03-11 12:51:51 -08:00
+++ b/drivers/media/video/adv7170.c	2005-03-11 12:51:51 -08:00
@@ -402,7 +402,6 @@
 	.force			= force
 };
 
-static int adv7170_i2c_id = 0;
 static struct i2c_driver i2c_driver_adv7170;
 
 static int
@@ -432,7 +431,6 @@
 	client->adapter = adapter;
 	client->driver = &i2c_driver_adv7170;
 	client->flags = I2C_CLIENT_ALLOW_USE;
-	client->id = adv7170_i2c_id++;
 	if ((client->addr == I2C_ADV7170 >> 1) ||
 	    (client->addr == (I2C_ADV7170 >> 1) + 1)) {
 		dname = adv7170_name;
@@ -444,8 +442,7 @@
 		kfree(client);
 		return 0;
 	}
-	snprintf(I2C_NAME(client), sizeof(I2C_NAME(client)) - 1,
-		"%s[%d]", dname, client->id);
+	strlcpy(I2C_NAME(client), dname, sizeof(I2C_NAME(client)));
 
 	encoder = kmalloc(sizeof(struct adv7170), GFP_KERNEL);
 	if (encoder == NULL) {
diff -Nru a/drivers/media/video/adv7175.c b/drivers/media/video/adv7175.c
--- a/drivers/media/video/adv7175.c	2005-03-11 12:51:51 -08:00
+++ b/drivers/media/video/adv7175.c	2005-03-11 12:51:51 -08:00
@@ -452,7 +452,6 @@
 	.force			= force
 };
 
-static int adv7175_i2c_id = 0;
 static struct i2c_driver i2c_driver_adv7175;
 
 static int
@@ -482,7 +481,6 @@
 	client->adapter = adapter;
 	client->driver = &i2c_driver_adv7175;
 	client->flags = I2C_CLIENT_ALLOW_USE;
-	client->id = adv7175_i2c_id++;
 	if ((client->addr == I2C_ADV7175 >> 1) ||
 	    (client->addr == (I2C_ADV7175 >> 1) + 1)) {
 		dname = adv7175_name;
@@ -494,8 +492,7 @@
 		kfree(client);
 		return 0;
 	}
-	snprintf(I2C_NAME(client), sizeof(I2C_NAME(client)) - 1,
-		"%s[%d]", dname, client->id);
+	strlcpy(I2C_NAME(client), dname, sizeof(I2C_NAME(client)));
 
 	encoder = kmalloc(sizeof(struct adv7175), GFP_KERNEL);
 	if (encoder == NULL) {
diff -Nru a/drivers/media/video/bt819.c b/drivers/media/video/bt819.c
--- a/drivers/media/video/bt819.c	2005-03-11 12:51:41 -08:00
+++ b/drivers/media/video/bt819.c	2005-03-11 12:51:41 -08:00
@@ -517,7 +517,6 @@
 	.force			= force
 };
 
-static int bt819_i2c_id = 0;
 static struct i2c_driver i2c_driver_bt819;
 
 static int
@@ -546,7 +545,6 @@
 	client->adapter = adapter;
 	client->driver = &i2c_driver_bt819;
 	client->flags = I2C_CLIENT_ALLOW_USE;
-	client->id = bt819_i2c_id++;
 
 	decoder = kmalloc(sizeof(struct bt819), GFP_KERNEL);
 	if (decoder == NULL) {
@@ -568,16 +566,13 @@
 	id = bt819_read(client, 0x17);
 	switch (id & 0xf0) {
 	case 0x70:
-	        snprintf(I2C_NAME(client), sizeof(I2C_NAME(client)) - 1,
-			 "bt819a[%d]", client->id);
+		strlcpy(I2C_NAME(client), "bt819a", sizeof(I2C_NAME(client)));
 		break;
 	case 0x60:
-		snprintf(I2C_NAME(client), sizeof(I2C_NAME(client)) - 1,
-			 "bt817a[%d]", client->id);
+		strlcpy(I2C_NAME(client), "bt817a", sizeof(I2C_NAME(client)));
 		break;
 	case 0x20:
-		snprintf(I2C_NAME(client), sizeof(I2C_NAME(client)) - 1,
-			 "bt815a[%d]", client->id);
+		strlcpy(I2C_NAME(client), "bt815a", sizeof(I2C_NAME(client)));
 		break;
 	default:
 		dprintk(1,
diff -Nru a/drivers/media/video/bt856.c b/drivers/media/video/bt856.c
--- a/drivers/media/video/bt856.c	2005-03-11 12:51:40 -08:00
+++ b/drivers/media/video/bt856.c	2005-03-11 12:51:40 -08:00
@@ -306,7 +306,6 @@
 	.force			= force
 };
 
-static int bt856_i2c_id = 0;
 static struct i2c_driver i2c_driver_bt856;
 
 static int
@@ -335,9 +334,7 @@
 	client->adapter = adapter;
 	client->driver = &i2c_driver_bt856;
 	client->flags = I2C_CLIENT_ALLOW_USE;
-	client->id = bt856_i2c_id++;
-	snprintf(I2C_NAME(client), sizeof(I2C_NAME(client)) - 1,
-		"bt856[%d]", client->id);
+	strlcpy(I2C_NAME(client), "bt856", sizeof(I2C_NAME(client)));
 
 	encoder = kmalloc(sizeof(struct bt856), GFP_KERNEL);
 	if (encoder == NULL) {
diff -Nru a/drivers/media/video/bttv-cards.c b/drivers/media/video/bttv-cards.c
--- a/drivers/media/video/bttv-cards.c	2005-03-11 12:51:46 -08:00
+++ b/drivers/media/video/bttv-cards.c	2005-03-11 12:51:46 -08:00
@@ -1,5 +1,5 @@
 /*
-    $Id: bttv-cards.c,v 1.42 2005/01/13 17:22:33 kraxel Exp $
+    $Id: bttv-cards.c,v 1.44 2005/01/31 11:35:05 kraxel Exp $
 
     bttv-cards.c
 
@@ -170,6 +170,8 @@
 	// some cards ship with byteswapped IDs ...
 	{ 0x1200bd11, BTTV_PINNACLE,      "Pinnacle PCTV [bswap]" },
 	{ 0xff00bd11, BTTV_PINNACLE,      "Pinnacle PCTV [bswap]" },
+	// this seems to happen as well ...
+	{ 0xff1211bd, BTTV_PINNACLE,      "Pinnacle PCTV" },
 
 	{ 0x3000121a, BTTV_VOODOOTV_FM,   "3Dfx VoodooTV FM/ VoodooTV 200" },
 	{ 0x263710b4, BTTV_VOODOOTV_FM,   "3Dfx VoodooTV FM/ VoodooTV 200" },
diff -Nru a/drivers/media/video/bttv-driver.c b/drivers/media/video/bttv-driver.c
--- a/drivers/media/video/bttv-driver.c	2005-03-11 12:51:48 -08:00
+++ b/drivers/media/video/bttv-driver.c	2005-03-11 12:51:50 -08:00
@@ -1,5 +1,5 @@
 /*
-    $Id: bttv-driver.c,v 1.34 2005/01/07 13:11:19 kraxel Exp $
+    $Id: bttv-driver.c,v 1.36 2005/02/15 10:51:53 kraxel Exp $
 
     bttv - Bt848 frame grabber driver
 
@@ -3921,7 +3921,7 @@
         return;
 }
 
-static int bttv_suspend(struct pci_dev *pci_dev, u32 state)
+static int bttv_suspend(struct pci_dev *pci_dev, pm_message_t state)
 {
         struct bttv *btv = pci_get_drvdata(pci_dev);
 	struct bttv_buffer_set idle;
diff -Nru a/drivers/media/video/bttv-i2c.c b/drivers/media/video/bttv-i2c.c
--- a/drivers/media/video/bttv-i2c.c	2005-03-11 12:51:41 -08:00
+++ b/drivers/media/video/bttv-i2c.c	2005-03-11 12:51:41 -08:00
@@ -245,7 +245,7 @@
        	return retval;
 }
 
-static int bttv_i2c_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msgs[], int num)
+static int bttv_i2c_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, int num)
 {
 	struct bttv *btv = i2c_get_adapdata(i2c_adap);
 	int retval = 0;
@@ -330,7 +330,6 @@
 
 static struct i2c_client bttv_i2c_client_template = {
 	I2C_DEVNAME("bttv internal"),
-        .id       = -1,
 };
 
 
diff -Nru a/drivers/media/video/bttv.h b/drivers/media/video/bttv.h
--- a/drivers/media/video/bttv.h	2005-03-11 12:51:41 -08:00
+++ b/drivers/media/video/bttv.h	2005-03-11 12:51:41 -08:00
@@ -1,5 +1,5 @@
 /*
- * $Id: bttv.h,v 1.14 2005/01/07 13:11:19 kraxel Exp $
+ * $Id: bttv.h,v 1.15 2005/01/24 17:37:23 kraxel Exp $
  *
  *  bttv - Bt848 frame grabber driver
  *
diff -Nru a/drivers/media/video/bttvp.h b/drivers/media/video/bttvp.h
--- a/drivers/media/video/bttvp.h	2005-03-11 12:51:52 -08:00
+++ b/drivers/media/video/bttvp.h	2005-03-11 12:51:52 -08:00
@@ -1,5 +1,5 @@
 /*
-    $Id: bttvp.h,v 1.15 2004/12/14 15:33:30 kraxel Exp $
+    $Id: bttvp.h,v 1.16 2005/01/24 17:37:23 kraxel Exp $
 
     bttv - Bt848 frame grabber driver
 
@@ -230,7 +230,6 @@
 /* our devices */
 #define BTTV_MAX 16
 extern unsigned int bttv_num;
-extern struct bttv bttvs[BTTV_MAX];
 
 #define BTTV_MAX_FBUF   0x208000
 #define VBIBUF_SIZE     (2048*VBI_MAXLINES*2)
@@ -377,6 +376,7 @@
 	unsigned int users;
 	struct bttv_fh init;
 };
+extern struct bttv bttvs[BTTV_MAX];
 
 /* private ioctls */
 #define BTTV_VERSION            _IOR('v' , BASE_VIDIOCPRIVATE+6, int)
diff -Nru a/drivers/media/video/cpia_usb.c b/drivers/media/video/cpia_usb.c
--- a/drivers/media/video/cpia_usb.c	2005-03-11 12:51:40 -08:00
+++ b/drivers/media/video/cpia_usb.c	2005-03-11 12:51:40 -08:00
@@ -308,7 +308,7 @@
 			 packet[1] + (packet[0] << 8),
 			 USB_TYPE_VENDOR | USB_RECIP_DEVICE,
 			 packet[2] + (packet[3] << 8), 
-			 packet[4] + (packet[5] << 8), buf, size, HZ);
+			 packet[4] + (packet[5] << 8), buf, size, 1000);
 }
 
 /****************************************************************************
@@ -325,7 +325,7 @@
 			 packet[1] + (packet[0] << 8),
 			 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
 			 packet[2] + (packet[3] << 8), 
-			 packet[4] + (packet[5] << 8), buf, size, HZ);
+			 packet[4] + (packet[5] << 8), buf, size, 1000);
 }
 
 static int cpia_usb_transferCmd(void *privdata, u8 *command, u8 *data)
diff -Nru a/drivers/media/video/cx88/cx88-i2c.c b/drivers/media/video/cx88/cx88-i2c.c
--- a/drivers/media/video/cx88/cx88-i2c.c	2005-03-11 12:51:42 -08:00
+++ b/drivers/media/video/cx88/cx88-i2c.c	2005-03-11 12:51:42 -08:00
@@ -141,7 +141,6 @@
 
 static struct i2c_client cx8800_i2c_client_template = {
         I2C_DEVNAME("cx88xx internal"),
-        .id   = -1,
 };
 
 static char *i2c_devs[128] = {
diff -Nru a/drivers/media/video/meye.c b/drivers/media/video/meye.c
--- a/drivers/media/video/meye.c	2005-03-11 12:51:47 -08:00
+++ b/drivers/media/video/meye.c	2005-03-11 12:51:47 -08:00
@@ -1154,7 +1154,7 @@
 		memset(cap, 0, sizeof(*cap));
 		strcpy(cap->driver, "meye");
 		strcpy(cap->card, "meye");
-		sprintf(cap->bus_info, "PCI:%s", meye.mchip_dev->slot_name);
+		sprintf(cap->bus_info, "PCI:%s", pci_name(meye.mchip_dev));
 		cap->version = (MEYE_DRIVER_MAJORVERSION << 8) +
 			       MEYE_DRIVER_MINORVERSION;
 		cap->capabilities = V4L2_CAP_VIDEO_CAPTURE |
diff -Nru a/drivers/media/video/mt20xx.c b/drivers/media/video/mt20xx.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/media/video/mt20xx.c	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,557 @@
+/*
+ * $Id: mt20xx.c,v 1.3 2005/02/15 15:59:35 kraxel Exp $
+ *
+ * i2c tv tuner chip device driver
+ * controls microtune tuners, mt2032 + mt2050 at the moment.
+ */
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/videodev.h>
+#include <media/tuner.h>
+
+/* ---------------------------------------------------------------------- */
+
+static unsigned int optimize_vco  = 1;
+module_param(optimize_vco,      int, 0644);
+
+static unsigned int tv_antenna    = 1;
+module_param(tv_antenna,        int, 0644);
+
+static unsigned int radio_antenna = 0;
+module_param(radio_antenna,     int, 0644);
+
+/* ---------------------------------------------------------------------- */
+
+#define MT2032 0x04
+#define MT2030 0x06
+#define MT2040 0x07
+#define MT2050 0x42
+
+static char *microtune_part[] = {
+	[ MT2030 ] = "MT2030",
+	[ MT2032 ] = "MT2032",
+	[ MT2040 ] = "MT2040",
+	[ MT2050 ] = "MT2050",
+};
+
+// IsSpurInBand()?
+static int mt2032_spurcheck(struct i2c_client *c,
+			    int f1, int f2, int spectrum_from,int spectrum_to)
+{
+	struct tuner *t = i2c_get_clientdata(c);
+	int n1=1,n2,f;
+
+	f1=f1/1000; //scale to kHz to avoid 32bit overflows
+	f2=f2/1000;
+	spectrum_from/=1000;
+	spectrum_to/=1000;
+
+	tuner_dbg("spurcheck f1=%d f2=%d  from=%d to=%d\n",
+		  f1,f2,spectrum_from,spectrum_to);
+
+	do {
+	    n2=-n1;
+	    f=n1*(f1-f2);
+	    do {
+		n2--;
+		f=f-f2;
+		tuner_dbg("spurtest n1=%d n2=%d ftest=%d\n",n1,n2,f);
+
+		if( (f>spectrum_from) && (f<spectrum_to))
+			tuner_dbg("mt2032 spurcheck triggered: %d\n",n1);
+	    } while ( (f>(f2-spectrum_to)) || (n2>-5));
+	    n1++;
+	} while (n1<5);
+
+	return 1;
+}
+
+static int mt2032_compute_freq(struct i2c_client *c,
+			       unsigned int rfin,
+			       unsigned int if1, unsigned int if2,
+			       unsigned int spectrum_from,
+			       unsigned int spectrum_to,
+			       unsigned char *buf,
+			       int *ret_sel,
+			       unsigned int xogc) //all in Hz
+{
+	struct tuner *t = i2c_get_clientdata(c);
+        unsigned int fref,lo1,lo1n,lo1a,s,sel,lo1freq, desired_lo1,
+		desired_lo2,lo2,lo2n,lo2a,lo2num,lo2freq;
+
+        fref= 5250 *1000; //5.25MHz
+	desired_lo1=rfin+if1;
+
+	lo1=(2*(desired_lo1/1000)+(fref/1000)) / (2*fref/1000);
+        lo1n=lo1/8;
+        lo1a=lo1-(lo1n*8);
+
+        s=rfin/1000/1000+1090;
+
+	if(optimize_vco) {
+		if(s>1890) sel=0;
+		else if(s>1720) sel=1;
+		else if(s>1530) sel=2;
+		else if(s>1370) sel=3;
+		else sel=4; // >1090
+	}
+	else {
+        	if(s>1790) sel=0; // <1958
+        	else if(s>1617) sel=1;
+        	else if(s>1449) sel=2;
+        	else if(s>1291) sel=3;
+        	else sel=4; // >1090
+	}
+	*ret_sel=sel;
+
+        lo1freq=(lo1a+8*lo1n)*fref;
+
+	tuner_dbg("mt2032: rfin=%d lo1=%d lo1n=%d lo1a=%d sel=%d, lo1freq=%d\n",
+		  rfin,lo1,lo1n,lo1a,sel,lo1freq);
+
+        desired_lo2=lo1freq-rfin-if2;
+        lo2=(desired_lo2)/fref;
+        lo2n=lo2/8;
+        lo2a=lo2-(lo2n*8);
+        lo2num=((desired_lo2/1000)%(fref/1000))* 3780/(fref/1000); //scale to fit in 32bit arith
+        lo2freq=(lo2a+8*lo2n)*fref + lo2num*(fref/1000)/3780*1000;
+
+	tuner_dbg("mt2032: rfin=%d lo2=%d lo2n=%d lo2a=%d num=%d lo2freq=%d\n",
+		  rfin,lo2,lo2n,lo2a,lo2num,lo2freq);
+
+        if(lo1a<0 || lo1a>7 || lo1n<17 ||lo1n>48 || lo2a<0 ||lo2a >7 ||lo2n<17 || lo2n>30) {
+		tuner_info("mt2032: frequency parameters out of range: %d %d %d %d\n",
+			   lo1a, lo1n, lo2a,lo2n);
+                return(-1);
+        }
+
+	mt2032_spurcheck(c, lo1freq, desired_lo2,  spectrum_from, spectrum_to);
+	// should recalculate lo1 (one step up/down)
+
+	// set up MT2032 register map for transfer over i2c
+	buf[0]=lo1n-1;
+	buf[1]=lo1a | (sel<<4);
+	buf[2]=0x86; // LOGC
+	buf[3]=0x0f; //reserved
+	buf[4]=0x1f;
+	buf[5]=(lo2n-1) | (lo2a<<5);
+ 	if(rfin >400*1000*1000)
+                buf[6]=0xe4;
+        else
+                buf[6]=0xf4; // set PKEN per rev 1.2
+	buf[7]=8+xogc;
+	buf[8]=0xc3; //reserved
+	buf[9]=0x4e; //reserved
+	buf[10]=0xec; //reserved
+	buf[11]=(lo2num&0xff);
+	buf[12]=(lo2num>>8) |0x80; // Lo2RST
+
+	return 0;
+}
+
+static int mt2032_check_lo_lock(struct i2c_client *c)
+{
+	struct tuner *t = i2c_get_clientdata(c);
+	int try,lock=0;
+	unsigned char buf[2];
+
+	for(try=0;try<10;try++) {
+		buf[0]=0x0e;
+		i2c_master_send(c,buf,1);
+		i2c_master_recv(c,buf,1);
+		tuner_dbg("mt2032 Reg.E=0x%02x\n",buf[0]);
+		lock=buf[0] &0x06;
+
+		if (lock==6)
+			break;
+
+		tuner_dbg("mt2032: pll wait 1ms for lock (0x%2x)\n",buf[0]);
+		udelay(1000);
+	}
+        return lock;
+}
+
+static int mt2032_optimize_vco(struct i2c_client *c,int sel,int lock)
+{
+	struct tuner *t = i2c_get_clientdata(c);
+	unsigned char buf[2];
+	int tad1;
+
+	buf[0]=0x0f;
+	i2c_master_send(c,buf,1);
+	i2c_master_recv(c,buf,1);
+	tuner_dbg("mt2032 Reg.F=0x%02x\n",buf[0]);
+	tad1=buf[0]&0x07;
+
+	if(tad1 ==0) return lock;
+	if(tad1 ==1) return lock;
+
+	if(tad1==2) {
+		if(sel==0)
+			return lock;
+		else sel--;
+	}
+	else {
+		if(sel<4)
+			sel++;
+		else
+			return lock;
+	}
+
+	tuner_dbg("mt2032 optimize_vco: sel=%d\n",sel);
+
+	buf[0]=0x0f;
+	buf[1]=sel;
+        i2c_master_send(c,buf,2);
+	lock=mt2032_check_lo_lock(c);
+	return lock;
+}
+
+
+static void mt2032_set_if_freq(struct i2c_client *c, unsigned int rfin,
+			       unsigned int if1, unsigned int if2,
+			       unsigned int from, unsigned int to)
+{
+	unsigned char buf[21];
+	int lint_try,ret,sel,lock=0;
+	struct tuner *t = i2c_get_clientdata(c);
+
+	tuner_dbg("mt2032_set_if_freq rfin=%d if1=%d if2=%d from=%d to=%d\n",
+		  rfin,if1,if2,from,to);
+
+        buf[0]=0;
+        ret=i2c_master_send(c,buf,1);
+        i2c_master_recv(c,buf,21);
+
+	buf[0]=0;
+	ret=mt2032_compute_freq(c,rfin,if1,if2,from,to,&buf[1],&sel,t->xogc);
+	if (ret<0)
+		return;
+
+        // send only the relevant registers per Rev. 1.2
+        buf[0]=0;
+        ret=i2c_master_send(c,buf,4);
+        buf[5]=5;
+        ret=i2c_master_send(c,buf+5,4);
+        buf[11]=11;
+        ret=i2c_master_send(c,buf+11,3);
+        if(ret!=3)
+		tuner_warn("i2c i/o error: rc == %d (should be 3)\n",ret);
+
+	// wait for PLLs to lock (per manual), retry LINT if not.
+	for(lint_try=0; lint_try<2; lint_try++) {
+		lock=mt2032_check_lo_lock(c);
+
+		if(optimize_vco)
+			lock=mt2032_optimize_vco(c,sel,lock);
+		if(lock==6) break;
+
+		tuner_dbg("mt2032: re-init PLLs by LINT\n");
+		buf[0]=7;
+		buf[1]=0x80 +8+t->xogc; // set LINT to re-init PLLs
+		i2c_master_send(c,buf,2);
+		mdelay(10);
+		buf[1]=8+t->xogc;
+		i2c_master_send(c,buf,2);
+        }
+
+	if (lock!=6)
+		tuner_warn("MT2032 Fatal Error: PLLs didn't lock.\n");
+
+	buf[0]=2;
+	buf[1]=0x20; // LOGC for optimal phase noise
+	ret=i2c_master_send(c,buf,2);
+	if (ret!=2)
+		tuner_warn("i2c i/o error: rc == %d (should be 2)\n",ret);
+}
+
+
+static void mt2032_set_tv_freq(struct i2c_client *c, unsigned int freq)
+{
+	struct tuner *t = i2c_get_clientdata(c);
+	int if2,from,to;
+
+	// signal bandwidth and picture carrier
+	if (t->std & V4L2_STD_525_60) {
+		// NTSC
+		from = 40750*1000;
+		to   = 46750*1000;
+		if2  = 45750*1000;
+	} else {
+		// PAL
+		from = 32900*1000;
+		to   = 39900*1000;
+		if2  = 38900*1000;
+	}
+
+        mt2032_set_if_freq(c, freq*62500 /* freq*1000*1000/16 */,
+			   1090*1000*1000, if2, from, to);
+}
+
+static void mt2032_set_radio_freq(struct i2c_client *c, unsigned int freq)
+{
+	struct tuner *t = i2c_get_clientdata(c);
+	int if2 = t->radio_if2;
+
+	// per Manual for FM tuning: first if center freq. 1085 MHz
+        mt2032_set_if_freq(c, freq*62500 /* freq*1000*1000/16 */,
+			   1085*1000*1000,if2,if2,if2);
+}
+
+// Initalization as described in "MT203x Programming Procedures", Rev 1.2, Feb.2001
+static int mt2032_init(struct i2c_client *c)
+{
+	struct tuner *t = i2c_get_clientdata(c);
+        unsigned char buf[21];
+        int ret,xogc,xok=0;
+
+	// Initialize Registers per spec.
+        buf[1]=2; // Index to register 2
+        buf[2]=0xff;
+        buf[3]=0x0f;
+        buf[4]=0x1f;
+        ret=i2c_master_send(c,buf+1,4);
+
+        buf[5]=6; // Index register 6
+        buf[6]=0xe4;
+        buf[7]=0x8f;
+        buf[8]=0xc3;
+        buf[9]=0x4e;
+        buf[10]=0xec;
+        ret=i2c_master_send(c,buf+5,6);
+
+        buf[12]=13;  // Index register 13
+        buf[13]=0x32;
+        ret=i2c_master_send(c,buf+12,2);
+
+        // Adjust XOGC (register 7), wait for XOK
+        xogc=7;
+        do {
+		tuner_dbg("mt2032: xogc = 0x%02x\n",xogc&0x07);
+                mdelay(10);
+                buf[0]=0x0e;
+                i2c_master_send(c,buf,1);
+                i2c_master_recv(c,buf,1);
+                xok=buf[0]&0x01;
+                tuner_dbg("mt2032: xok = 0x%02x\n",xok);
+                if (xok == 1) break;
+
+                xogc--;
+                tuner_dbg("mt2032: xogc = 0x%02x\n",xogc&0x07);
+                if (xogc == 3) {
+                        xogc=4; // min. 4 per spec
+                        break;
+                }
+                buf[0]=0x07;
+                buf[1]=0x88 + xogc;
+                ret=i2c_master_send(c,buf,2);
+                if (ret!=2)
+			tuner_warn("i2c i/o error: rc == %d (should be 2)\n",ret);
+        } while (xok != 1 );
+	t->xogc=xogc;
+
+	t->tv_freq    = mt2032_set_tv_freq;
+	t->radio_freq = mt2032_set_radio_freq;
+        return(1);
+}
+
+static void mt2050_set_antenna(struct i2c_client *c, unsigned char antenna)
+{
+	struct tuner *t = i2c_get_clientdata(c);
+       unsigned char buf[2];
+       int ret;
+
+       buf[0] = 6;
+       buf[1] = antenna ? 0x11 : 0x10;
+       ret=i2c_master_send(c,buf,2);
+       tuner_dbg("mt2050: enabled antenna connector %d\n", antenna);
+}
+
+static void mt2050_set_if_freq(struct i2c_client *c,unsigned int freq, unsigned int if2)
+{
+	struct tuner *t = i2c_get_clientdata(c);
+	unsigned int if1=1218*1000*1000;
+	unsigned int f_lo1,f_lo2,lo1,lo2,f_lo1_modulo,f_lo2_modulo,num1,num2,div1a,div1b,div2a,div2b;
+	int ret;
+	unsigned char buf[6];
+
+	tuner_dbg("mt2050_set_if_freq freq=%d if1=%d if2=%d\n",
+		  freq,if1,if2);
+
+	f_lo1=freq+if1;
+	f_lo1=(f_lo1/1000000)*1000000;
+
+	f_lo2=f_lo1-freq-if2;
+	f_lo2=(f_lo2/50000)*50000;
+
+	lo1=f_lo1/4000000;
+	lo2=f_lo2/4000000;
+
+	f_lo1_modulo= f_lo1-(lo1*4000000);
+	f_lo2_modulo= f_lo2-(lo2*4000000);
+
+	num1=4*f_lo1_modulo/4000000;
+	num2=4096*(f_lo2_modulo/1000)/4000;
+
+	// todo spurchecks
+
+	div1a=(lo1/12)-1;
+	div1b=lo1-(div1a+1)*12;
+
+	div2a=(lo2/8)-1;
+	div2b=lo2-(div2a+1)*8;
+
+	if (tuner_debug > 1) {
+		tuner_dbg("lo1 lo2 = %d %d\n", lo1, lo2);
+		tuner_dbg("num1 num2 div1a div1b div2a div2b= %x %x %x %x %x %x\n",
+			  num1,num2,div1a,div1b,div2a,div2b);
+	}
+
+	buf[0]=1;
+	buf[1]= 4*div1b + num1;
+	if(freq<275*1000*1000) buf[1] = buf[1]|0x80;
+
+	buf[2]=div1a;
+	buf[3]=32*div2b + num2/256;
+	buf[4]=num2-(num2/256)*256;
+	buf[5]=div2a;
+	if(num2!=0) buf[5]=buf[5]|0x40;
+
+	if (tuner_debug > 1) {
+		int i;
+		tuner_dbg("bufs is: ");
+		for(i=0;i<6;i++)
+			printk("%x ",buf[i]);
+		printk("\n");
+	}
+
+	ret=i2c_master_send(c,buf,6);
+        if (ret!=6)
+		tuner_warn("i2c i/o error: rc == %d (should be 6)\n",ret);
+}
+
+static void mt2050_set_tv_freq(struct i2c_client *c, unsigned int freq)
+{
+	struct tuner *t = i2c_get_clientdata(c);
+	unsigned int if2;
+
+	if (t->std & V4L2_STD_525_60) {
+		// NTSC
+                if2 = 45750*1000;
+        } else {
+                // PAL
+                if2 = 38900*1000;
+        }
+	if (V4L2_TUNER_DIGITAL_TV == t->mode) {
+		// DVB (pinnacle 300i)
+		if2 = 36150*1000;
+	}
+	mt2050_set_if_freq(c, freq*62500, if2);
+	mt2050_set_antenna(c, tv_antenna);
+}
+
+static void mt2050_set_radio_freq(struct i2c_client *c, unsigned int freq)
+{
+	struct tuner *t = i2c_get_clientdata(c);
+	int if2 = t->radio_if2;
+
+	mt2050_set_if_freq(c, freq*62500, if2);
+	mt2050_set_antenna(c, radio_antenna);
+}
+
+static int mt2050_init(struct i2c_client *c)
+{
+	struct tuner *t = i2c_get_clientdata(c);
+	unsigned char buf[2];
+	int ret;
+
+	buf[0]=6;
+	buf[1]=0x10;
+	ret=i2c_master_send(c,buf,2); //  power
+
+	buf[0]=0x0f;
+	buf[1]=0x0f;
+	ret=i2c_master_send(c,buf,2); // m1lo
+
+	buf[0]=0x0d;
+	ret=i2c_master_send(c,buf,1);
+	i2c_master_recv(c,buf,1);
+
+	tuner_dbg("mt2050: sro is %x\n",buf[0]);
+	t->tv_freq    = mt2050_set_tv_freq;
+	t->radio_freq = mt2050_set_radio_freq;
+	return 0;
+}
+
+int microtune_init(struct i2c_client *c)
+{
+	struct tuner *t = i2c_get_clientdata(c);
+	char *name;
+        unsigned char buf[21];
+	int company_code;
+
+	memset(buf,0,sizeof(buf));
+	t->tv_freq    = NULL;
+	t->radio_freq = NULL;
+	name = "unknown";
+
+        i2c_master_send(c,buf,1);
+        i2c_master_recv(c,buf,21);
+        if (tuner_debug) {
+                int i;
+		tuner_dbg("MT20xx hexdump:");
+                for(i=0;i<21;i++) {
+                        printk(" %02x",buf[i]);
+                        if(((i+1)%8)==0) printk(" ");
+                }
+                printk("\n");
+        }
+	company_code = buf[0x11] << 8 | buf[0x12];
+	tuner_info("microtune: companycode=%04x part=%02x rev=%02x\n",
+		   company_code,buf[0x13],buf[0x14]);
+
+#if 0
+	/* seems to cause more problems than it solves ... */
+	switch (company_code) {
+	case 0x30bf:
+	case 0x3cbf:
+	case 0x3dbf:
+	case 0x4d54:
+	case 0x8e81:
+	case 0x8e91:
+		/* ok (?) */
+		break;
+	default:
+		tuner_warn("tuner: microtune: unknown companycode\n");
+		return 0;
+	}
+#endif
+
+	if (buf[0x13] < ARRAY_SIZE(microtune_part) &&
+	    NULL != microtune_part[buf[0x13]])
+		name = microtune_part[buf[0x13]];
+	switch (buf[0x13]) {
+	case MT2032:
+		mt2032_init(c);
+		break;
+	case MT2050:
+		mt2050_init(c);
+		break;
+	default:
+		tuner_info("microtune %s found, not (yet?) supported, sorry :-/\n",
+			   name);
+                return 0;
+        }
+
+	strlcpy(c->name, name, sizeof(c->name));
+	tuner_info("microtune %s found, OK\n",name);
+	return 0;
+}
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff -Nru a/drivers/media/video/ovcamchip/ovcamchip_core.c b/drivers/media/video/ovcamchip/ovcamchip_core.c
--- a/drivers/media/video/ovcamchip/ovcamchip_core.c	2005-03-11 12:51:51 -08:00
+++ b/drivers/media/video/ovcamchip/ovcamchip_core.c	2005-03-11 12:51:51 -08:00
@@ -422,7 +422,6 @@
 
 static struct i2c_client client_template = {
 	I2C_DEVNAME("(unset)"),
-	.id =		-1,
 	.driver =	&driver,
 };
 
diff -Nru a/drivers/media/video/saa5246a.c b/drivers/media/video/saa5246a.c
--- a/drivers/media/video/saa5246a.c	2005-03-11 12:51:43 -08:00
+++ b/drivers/media/video/saa5246a.c	2005-03-11 12:51:43 -08:00
@@ -185,7 +185,6 @@
 };
 
 static struct i2c_client client_template = {
-	.id 		= -1,
 	.driver		= &i2c_driver_videotext,
 	.name		= "(unset)",
 };
diff -Nru a/drivers/media/video/saa5249.c b/drivers/media/video/saa5249.c
--- a/drivers/media/video/saa5249.c	2005-03-11 12:51:48 -08:00
+++ b/drivers/media/video/saa5249.c	2005-03-11 12:51:48 -08:00
@@ -258,7 +258,6 @@
 };
 
 static struct i2c_client client_template = {
-	.id 		= -1,
 	.driver		= &i2c_driver_videotext,
 	.name		= "(unset)",
 };
diff -Nru a/drivers/media/video/saa7110.c b/drivers/media/video/saa7110.c
--- a/drivers/media/video/saa7110.c	2005-03-11 12:51:40 -08:00
+++ b/drivers/media/video/saa7110.c	2005-03-11 12:51:40 -08:00
@@ -476,7 +476,6 @@
 	.force			= force
 };
 
-static int saa7110_i2c_id = 0;
 static struct i2c_driver i2c_driver_saa7110;
 
 static int
@@ -507,9 +506,7 @@
 	client->adapter = adapter;
 	client->driver = &i2c_driver_saa7110;
 	client->flags = I2C_CLIENT_ALLOW_USE;
-	client->id = saa7110_i2c_id++;
-	snprintf(I2C_NAME(client), sizeof(I2C_NAME(client)) - 1,
-		"saa7110[%d]", client->id);
+	strlcpy(I2C_NAME(client), "saa7110", sizeof(I2C_NAME(client)));
 
 	decoder = kmalloc(sizeof(struct saa7110), GFP_KERNEL);
 	if (decoder == 0) {
diff -Nru a/drivers/media/video/saa7111.c b/drivers/media/video/saa7111.c
--- a/drivers/media/video/saa7111.c	2005-03-11 12:51:52 -08:00
+++ b/drivers/media/video/saa7111.c	2005-03-11 12:51:52 -08:00
@@ -500,7 +500,6 @@
 	.force			= force
 };
 
-static int saa7111_i2c_id = 0;
 static struct i2c_driver i2c_driver_saa7111;
 
 static int
@@ -530,9 +529,7 @@
 	client->adapter = adapter;
 	client->driver = &i2c_driver_saa7111;
 	client->flags = I2C_CLIENT_ALLOW_USE;
-	client->id = saa7111_i2c_id++;
-	snprintf(I2C_NAME(client), sizeof(I2C_NAME(client)) - 1,
-		"saa7111[%d]", client->id);
+	strlcpy(I2C_NAME(client), "saa7111", sizeof(I2C_NAME(client)));
 
 	decoder = kmalloc(sizeof(struct saa7111), GFP_KERNEL);
 	if (decoder == NULL) {
diff -Nru a/drivers/media/video/saa7114.c b/drivers/media/video/saa7114.c
--- a/drivers/media/video/saa7114.c	2005-03-11 12:51:51 -08:00
+++ b/drivers/media/video/saa7114.c	2005-03-11 12:51:51 -08:00
@@ -838,7 +838,6 @@
 	.force			= force
 };
 
-static int saa7114_i2c_id = 0;
 static struct i2c_driver i2c_driver_saa7114;
 
 static int
@@ -871,9 +870,7 @@
 	client->adapter = adapter;
 	client->driver = &i2c_driver_saa7114;
 	client->flags = I2C_CLIENT_ALLOW_USE;
-	client->id = saa7114_i2c_id++;
-	snprintf(I2C_NAME(client), sizeof(I2C_NAME(client)) - 1,
-		"saa7114[%d]", client->id);
+	strlcpy(I2C_NAME(client), "saa7114", sizeof(I2C_NAME(client)));
 
 	decoder = kmalloc(sizeof(struct saa7114), GFP_KERNEL);
 	if (decoder == NULL) {
diff -Nru a/drivers/media/video/saa7134/saa7134-i2c.c b/drivers/media/video/saa7134/saa7134-i2c.c
--- a/drivers/media/video/saa7134/saa7134-i2c.c	2005-03-11 12:51:41 -08:00
+++ b/drivers/media/video/saa7134/saa7134-i2c.c	2005-03-11 12:51:41 -08:00
@@ -236,7 +236,7 @@
 }
 
 static int saa7134_i2c_xfer(struct i2c_adapter *i2c_adap,
-			    struct i2c_msg msgs[], int num)
+			    struct i2c_msg *msgs, int num)
 {
 	struct saa7134_dev *dev = i2c_adap->algo_data;
 	enum i2c_status status;
@@ -362,7 +362,6 @@
 
 static struct i2c_client saa7134_client_template = {
 	I2C_DEVNAME("saa7134 internal"),
-        .id        = -1,
 };
 
 /* ----------------------------------------------------------- */
diff -Nru a/drivers/media/video/saa7185.c b/drivers/media/video/saa7185.c
--- a/drivers/media/video/saa7185.c	2005-03-11 12:51:52 -08:00
+++ b/drivers/media/video/saa7185.c	2005-03-11 12:51:52 -08:00
@@ -398,7 +398,6 @@
 	.force			= force
 };
 
-static int saa7185_i2c_id = 0;
 static struct i2c_driver i2c_driver_saa7185;
 
 static int
@@ -427,9 +426,7 @@
 	client->adapter = adapter;
 	client->driver = &i2c_driver_saa7185;
 	client->flags = I2C_CLIENT_ALLOW_USE;
-	client->id = saa7185_i2c_id++;
-	snprintf(I2C_NAME(client), sizeof(I2C_NAME(client)) - 1,
-		"saa7185[%d]", client->id);
+	strlcpy(I2C_NAME(client), "saa7185", sizeof(I2C_NAME(client)));
 
 	encoder = kmalloc(sizeof(struct saa7185), GFP_KERNEL);
 	if (encoder == NULL) {
diff -Nru a/drivers/media/video/tda7432.c b/drivers/media/video/tda7432.c
--- a/drivers/media/video/tda7432.c	2005-03-11 12:51:47 -08:00
+++ b/drivers/media/video/tda7432.c	2005-03-11 12:51:47 -08:00
@@ -528,7 +528,6 @@
 static struct i2c_client client_template =
 {
 	I2C_DEVNAME("tda7432"),
-        .id         = -1,
 	.driver     = &driver,
 };
 
diff -Nru a/drivers/media/video/tda8290.c b/drivers/media/video/tda8290.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/media/video/tda8290.c	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,224 @@
+/*
+ * $Id: tda8290.c,v 1.5 2005/02/15 15:59:35 kraxel Exp $
+ *
+ * i2c tv tuner chip device driver
+ * controls the philips tda8290+75 tuner chip combo.
+ */
+#include <linux/i2c.h>
+#include <linux/videodev.h>
+#include <linux/delay.h>
+#include <media/tuner.h>
+
+/* ---------------------------------------------------------------------- */
+
+struct freq_entry {
+	u16	freq;
+	u8	value;
+};
+
+static struct freq_entry band_table[] = {
+	{ 0x2DF4, 0x1C },
+	{ 0x2574, 0x14 },
+	{ 0x22B4, 0x0C },
+	{ 0x20D4, 0x0B },
+	{ 0x1E74, 0x3B },
+	{ 0x1C34, 0x33 },
+	{ 0x16F4, 0x5B },
+	{ 0x1454, 0x53 },
+	{ 0x12D4, 0x52 },
+	{ 0x1034, 0x4A },
+	{ 0x0EE4, 0x7A },
+	{ 0x0D34, 0x72 },
+	{ 0x0B54, 0x9A },
+	{ 0x0914, 0x91 },
+	{ 0x07F4, 0x89 },
+	{ 0x0774, 0xB9 },
+	{ 0x067B, 0xB1 },
+	{ 0x0634, 0xD9 },
+	{ 0x05A4, 0xD8 },	// FM radio
+	{ 0x0494, 0xD0 },
+	{ 0x03BC, 0xC8 },
+	{ 0x0394, 0xF8 },	// 57250000 Hz
+	{ 0x0000, 0xF0 },	// 0
+};
+
+static struct freq_entry div_table[] = {
+	{ 0x1C34, 3 },
+	{ 0x0D34, 2 },
+	{ 0x067B, 1 },
+        { 0x0000, 0 },
+};
+
+static struct freq_entry agc_table[] = {
+	{ 0x22B4, 0x8F },
+	{ 0x0B54, 0x9F },
+	{ 0x09A4, 0x8F },
+	{ 0x0554, 0x9F },
+	{ 0x0000, 0xBF },
+};
+
+static __u8 get_freq_entry( struct freq_entry* table, __u16 freq)
+{
+	while(table->freq && table->freq > freq)
+		table++;
+	return table->value;
+}
+
+/* ---------------------------------------------------------------------- */
+
+static unsigned char i2c_enable_bridge[2] = 	{ 0x21, 0xC0 };
+static unsigned char i2c_disable_bridge[2] = 	{ 0x21, 0x80 };
+static unsigned char i2c_init_tda8275[14] = 	{ 0x00, 0x00, 0x00, 0x00,
+						  0x7C, 0x04, 0xA3, 0x3F,
+						  0x2A, 0x04, 0xFF, 0x00,
+						  0x00, 0x40 };
+static unsigned char i2c_set_VS[2] = 		{ 0x30, 0x6F };
+static unsigned char i2c_set_GP01_CF[2] = 	{ 0x20, 0x0B };
+static unsigned char i2c_tda8290_reset[2] =	{ 0x00, 0x00 };
+static unsigned char i2c_gainset_off[2] =	{ 0x28, 0x14 };
+static unsigned char i2c_gainset_on[2] =	{ 0x28, 0x54 };
+static unsigned char i2c_agc3_00[2] =		{ 0x80, 0x00 };
+static unsigned char i2c_agc2_BF[2] =		{ 0x60, 0xBF };
+static unsigned char i2c_cb1_D2[2] =		{ 0x30, 0xD2 };
+static unsigned char i2c_cb1_56[2] =		{ 0x30, 0x56 };
+static unsigned char i2c_cb1_52[2] =		{ 0x30, 0x52 };
+static unsigned char i2c_cb1_50[2] =		{ 0x30, 0x50 };
+static unsigned char i2c_agc2_7F[2] =		{ 0x60, 0x7F };
+static unsigned char i2c_agc3_08[2] =		{ 0x80, 0x08 };
+
+static struct i2c_msg i2c_msg_init[] = {
+	{ I2C_ADDR_TDA8275, 0, ARRAY_SIZE(i2c_init_tda8275), i2c_init_tda8275 },
+	{ I2C_ADDR_TDA8290, 0, ARRAY_SIZE(i2c_disable_bridge), i2c_disable_bridge },
+	{ I2C_ADDR_TDA8290, 0, ARRAY_SIZE(i2c_set_VS), i2c_set_VS },
+	{ I2C_ADDR_TDA8290, 0, ARRAY_SIZE(i2c_set_GP01_CF), i2c_set_GP01_CF },
+};
+
+static struct i2c_msg i2c_msg_prolog[] = {
+//	{ I2C_ADDR_TDA8290, 0, ARRAY_SIZE(i2c_easy_mode), i2c_easy_mode },
+	{ I2C_ADDR_TDA8290, 0, ARRAY_SIZE(i2c_gainset_off), i2c_gainset_off },
+	{ I2C_ADDR_TDA8290, 0, ARRAY_SIZE(i2c_tda8290_reset), i2c_tda8290_reset },
+	{ I2C_ADDR_TDA8290, 0, ARRAY_SIZE(i2c_enable_bridge), i2c_enable_bridge },
+};
+
+static struct i2c_msg i2c_msg_config[] = {
+//	{ I2C_ADDR_TDA8275, 0, ARRAY_SIZE(i2c_set_freq), i2c_set_freq },
+	{ I2C_ADDR_TDA8275, 0, ARRAY_SIZE(i2c_agc3_00), i2c_agc3_00 },
+	{ I2C_ADDR_TDA8275, 0, ARRAY_SIZE(i2c_agc2_BF), i2c_agc2_BF },
+	{ I2C_ADDR_TDA8275, 0, ARRAY_SIZE(i2c_cb1_D2), i2c_cb1_D2 },
+	{ I2C_ADDR_TDA8275, 0, ARRAY_SIZE(i2c_cb1_56), i2c_cb1_56 },
+	{ I2C_ADDR_TDA8275, 0, ARRAY_SIZE(i2c_cb1_52), i2c_cb1_52 },
+};
+
+static struct i2c_msg i2c_msg_epilog[] = {
+	{ I2C_ADDR_TDA8275, 0, ARRAY_SIZE(i2c_cb1_50), i2c_cb1_50 },
+	{ I2C_ADDR_TDA8275, 0, ARRAY_SIZE(i2c_agc2_7F), i2c_agc2_7F },
+	{ I2C_ADDR_TDA8275, 0, ARRAY_SIZE(i2c_agc3_08), i2c_agc3_08 },
+	{ I2C_ADDR_TDA8290, 0, ARRAY_SIZE(i2c_disable_bridge), i2c_disable_bridge },
+	{ I2C_ADDR_TDA8290, 0, ARRAY_SIZE(i2c_gainset_on), i2c_gainset_on },
+};
+
+static int tda8290_tune(struct i2c_client *c)
+{
+	struct tuner *t = i2c_get_clientdata(c);
+	struct i2c_msg easy_mode =
+		{ I2C_ADDR_TDA8290, 0, 2, t->i2c_easy_mode };
+	struct i2c_msg set_freq =
+		{ I2C_ADDR_TDA8290, 0, 8, t->i2c_set_freq  };
+
+	i2c_transfer(c->adapter, &easy_mode,      1);
+	i2c_transfer(c->adapter, i2c_msg_prolog, ARRAY_SIZE(i2c_msg_prolog));
+
+	i2c_transfer(c->adapter, &set_freq,       1);
+	i2c_transfer(c->adapter, i2c_msg_config, ARRAY_SIZE(i2c_msg_config));
+
+	msleep(550);
+	i2c_transfer(c->adapter, i2c_msg_epilog, ARRAY_SIZE(i2c_msg_epilog));
+	return 0;
+}
+
+static void set_frequency(struct tuner *t, u16 ifc)
+{
+	u32 N = (((t->freq<<3)+ifc)&0x3fffc);
+
+	N = N >> get_freq_entry(div_table, t->freq);
+	t->i2c_set_freq[0] = 0;
+	t->i2c_set_freq[1] = (unsigned char)(N>>8);
+	t->i2c_set_freq[2] = (unsigned char) N;
+	t->i2c_set_freq[3] = 0x40;
+	t->i2c_set_freq[4] = 0x52;
+	t->i2c_set_freq[5] = get_freq_entry(band_table, t->freq);
+	t->i2c_set_freq[6] = get_freq_entry(agc_table,  t->freq);
+	t->i2c_set_freq[7] = 0x8f;
+}
+
+#define V4L2_STD_MN	(V4L2_STD_PAL_M|V4L2_STD_PAL_N|V4L2_STD_PAL_Nc|V4L2_STD_NTSC)
+#define V4L2_STD_B	(V4L2_STD_PAL_B|V4L2_STD_PAL_B1|V4L2_STD_SECAM_B)
+#define V4L2_STD_GH	(V4L2_STD_PAL_G|V4L2_STD_PAL_H|V4L2_STD_SECAM_G|V4L2_STD_SECAM_H)
+#define V4L2_STD_DK	(V4L2_STD_PAL_DK|V4L2_STD_SECAM_DK)
+
+static void set_audio(struct tuner *t)
+{
+	t->i2c_easy_mode[0] = 0x01;
+
+	if (t->std & V4L2_STD_MN)
+		t->i2c_easy_mode[1] = 0x01;
+	else if (t->std & V4L2_STD_B)
+		t->i2c_easy_mode[1] = 0x02;
+	else if (t->std & V4L2_STD_GH)
+		t->i2c_easy_mode[1] = 0x04;
+	else if (t->std & V4L2_STD_PAL_I)
+		t->i2c_easy_mode[1] = 0x08;
+	else if (t->std & V4L2_STD_DK)
+		t->i2c_easy_mode[1] = 0x10;
+	else if (t->std & V4L2_STD_SECAM_L)
+		t->i2c_easy_mode[1] = 0x20;
+}
+
+static void set_tv_freq(struct i2c_client *c, unsigned int freq)
+{
+	struct tuner *t = i2c_get_clientdata(c);
+
+	set_audio(t);
+	set_frequency(t, 864);
+	tda8290_tune(c);
+}
+
+static void set_radio_freq(struct i2c_client *c, unsigned int freq)
+{
+	struct tuner *t = i2c_get_clientdata(c);
+	set_frequency(t, 704);
+	tda8290_tune(c);
+}
+
+static int has_signal(struct i2c_client *c)
+{
+	unsigned char i2c_get_afc[1] = { 0x1B };
+	unsigned char afc = 0;
+
+	i2c_master_send(c, i2c_get_afc, ARRAY_SIZE(i2c_get_afc));
+	i2c_master_recv(c, &afc, 1);
+	return (afc & 0x80)? 65535:0;
+}
+
+int tda8290_init(struct i2c_client *c)
+{
+	struct tuner *t = i2c_get_clientdata(c);
+
+	strlcpy(c->name, "tda8290+75", sizeof(c->name));
+	tuner_info("tuner: type set to %s\n", c->name);
+	t->tv_freq    = set_tv_freq;
+	t->radio_freq = set_radio_freq;
+	t->has_signal = has_signal;
+
+	i2c_master_send(c, i2c_enable_bridge, ARRAY_SIZE(i2c_enable_bridge));
+	i2c_transfer(c->adapter, i2c_msg_init, ARRAY_SIZE(i2c_msg_init));
+	return 0;
+}
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff -Nru a/drivers/media/video/tda9840.c b/drivers/media/video/tda9840.c
--- a/drivers/media/video/tda9840.c	2005-03-11 12:51:47 -08:00
+++ b/drivers/media/video/tda9840.c	2005-03-11 12:51:47 -08:00
@@ -51,9 +51,6 @@
 static struct i2c_driver driver;
 static struct i2c_client client_template;
 
-/* unique ID allocation */
-static int tda9840_id = 0;
-
 static int command(struct i2c_client *client, unsigned int cmd, void *arg)
 {
 	int result;
@@ -179,7 +176,6 @@
 
 	/* fill client structure */
 	memcpy(client, &client_template, sizeof(struct i2c_client));
-	client->id = tda9840_id++;
 	client->addr = address;
 	client->adapter = adapter;
 
diff -Nru a/drivers/media/video/tda9875.c b/drivers/media/video/tda9875.c
--- a/drivers/media/video/tda9875.c	2005-03-11 12:51:42 -08:00
+++ b/drivers/media/video/tda9875.c	2005-03-11 12:51:42 -08:00
@@ -399,7 +399,6 @@
 static struct i2c_client client_template =
 {
         I2C_DEVNAME("tda9875"),
-        .id        = -1,
         .driver    = &driver,
 };
 
diff -Nru a/drivers/media/video/tda9887.c b/drivers/media/video/tda9887.c
--- a/drivers/media/video/tda9887.c	2005-03-11 12:51:52 -08:00
+++ b/drivers/media/video/tda9887.c	2005-03-11 12:51:52 -08:00
@@ -557,7 +557,7 @@
 #if 0
 	/* This as-is breaks some cards, must be fixed in a
 	 * card-specific way, probably using TDA9887_SET_CONFIG to
-	  * turn on/off port2 */
+	 * turn on/off port2 */
 	if (t->std & V4L2_STD_SECAM_L) {
 		/* secam fixup (FIXME: move this to tvnorms array?) */
 		buf[1] &= ~cOutputPort2Inactive;
diff -Nru a/drivers/media/video/tea6415c.c b/drivers/media/video/tea6415c.c
--- a/drivers/media/video/tea6415c.c	2005-03-11 12:51:47 -08:00
+++ b/drivers/media/video/tea6415c.c	2005-03-11 12:51:47 -08:00
@@ -51,9 +51,6 @@
 static struct i2c_driver driver;
 static struct i2c_client client_template;
 
-/* unique ID allocation */
-static int tea6415c_id = 0;
-
 /* this function is called by i2c_probe */
 static int detect(struct i2c_adapter *adapter, int address, int kind)
 {
@@ -73,7 +70,6 @@
 
 	/* fill client structure */
 	memcpy(client, &client_template, sizeof(struct i2c_client));
-	client->id = tea6415c_id++;
 	client->addr = address;
 	client->adapter = adapter;
 
diff -Nru a/drivers/media/video/tea6420.c b/drivers/media/video/tea6420.c
--- a/drivers/media/video/tea6420.c	2005-03-11 12:51:46 -08:00
+++ b/drivers/media/video/tea6420.c	2005-03-11 12:51:46 -08:00
@@ -48,9 +48,6 @@
 static struct i2c_driver driver;
 static struct i2c_client client_template;
 
-/* unique ID allocation */
-static int tea6420_id = 0;
-
 /* make a connection between the input 'i' and the output 'o'
    with gain 'g' for the tea6420-client 'client' (note: i = 6 means 'mute') */
 static int tea6420_switch(struct i2c_client *client, int i, int o, int g)
@@ -111,7 +108,6 @@
 
 	/* fill client structure */
 	memcpy(client, &client_template, sizeof(struct i2c_client));
-	client->id = tea6420_id++;
 	client->addr = address;
 	client->adapter = adapter;
 
diff -Nru a/drivers/media/video/tuner-3036.c b/drivers/media/video/tuner-3036.c
--- a/drivers/media/video/tuner-3036.c	2005-03-11 12:51:42 -08:00
+++ b/drivers/media/video/tuner-3036.c	2005-03-11 12:51:42 -08:00
@@ -192,7 +192,6 @@
 
 static struct i2c_client client_template =
 {
-        .id 		= -1,
         .driver		= &i2c_driver_tuner,
 	.name		= "SAB3036",
 };
diff -Nru a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/media/video/tuner-core.c	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,443 @@
+/*
+ * $Id: tuner-core.c,v 1.5 2005/02/15 15:59:35 kraxel Exp $
+ *
+ * i2c tv tuner chip device driver
+ * core core, i.e. kernel interfaces, registering and so on
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/timer.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/poll.h>
+#include <linux/i2c.h>
+#include <linux/types.h>
+#include <linux/videodev.h>
+#include <linux/init.h>
+
+#include <media/tuner.h>
+#include <media/audiochip.h>
+
+#define UNSET (-1U)
+
+/* standard i2c insmod options */
+static unsigned short normal_i2c[] = {
+	0x4b, /* tda8290 */
+	I2C_CLIENT_END
+};
+static unsigned short normal_i2c_range[] = {
+	0x60, 0x6f,
+	I2C_CLIENT_END
+};
+I2C_CLIENT_INSMOD;
+
+/* insmod options used at init time => read/only */
+static unsigned int addr  =  0;
+module_param(addr, int, 0444);
+
+/* insmod options used at runtime => read/write */
+unsigned int tuner_debug   = 0;
+module_param(tuner_debug,       int, 0644);
+
+static unsigned int tv_range[2]    = { 44, 958 };
+static unsigned int radio_range[2] = { 65, 108 };
+
+module_param_array(tv_range,    int, NULL, 0644);
+module_param_array(radio_range, int, NULL, 0644);
+
+MODULE_DESCRIPTION("device driver for various TV and TV+FM radio tuners");
+MODULE_AUTHOR("Ralph Metzler, Gerd Knorr, Gunther Mayer");
+MODULE_LICENSE("GPL");
+
+static int this_adap;
+
+static struct i2c_driver driver;
+static struct i2c_client client_template;
+
+/* ---------------------------------------------------------------------- */
+
+// Set tuner frequency,  freq in Units of 62.5kHz = 1/16MHz
+static void set_tv_freq(struct i2c_client *c, unsigned int freq)
+{
+	struct tuner *t = i2c_get_clientdata(c);
+
+	if (t->type == UNSET) {
+		tuner_info("tuner type not set\n");
+		return;
+	}
+	if (NULL == t->tv_freq) {
+		tuner_info("Huh? tv_set is NULL?\n");
+		return;
+	}
+	if (freq < tv_range[0]*16 || freq > tv_range[1]*16) {
+		/* FIXME: better do that chip-specific, but
+		   right now we don't have that in the config
+		   struct and this way is still better than no
+		   check at all */
+		tuner_info("TV freq (%d.%02d) out of range (%d-%d)\n",
+			   freq/16,freq%16*100/16,tv_range[0],tv_range[1]);
+		return;
+	}
+	t->tv_freq(c,freq);
+}
+
+static void set_radio_freq(struct i2c_client *c, unsigned int freq)
+{
+	struct tuner *t = i2c_get_clientdata(c);
+
+	if (t->type == UNSET) {
+		tuner_info("tuner type not set\n");
+		return;
+	}
+	if (NULL == t->radio_freq) {
+		tuner_info("no radio tuning for this one, sorry.\n");
+		return;
+	}
+	if (freq < radio_range[0]*16 || freq > radio_range[1]*16) {
+		tuner_info("radio freq (%d.%02d) out of range (%d-%d)\n",
+			   freq/16,freq%16*100/16,
+			   radio_range[0],radio_range[1]);
+		return;
+	}
+	t->radio_freq(c,freq);
+}
+
+static void set_freq(struct i2c_client *c, unsigned long freq)
+{
+	struct tuner *t = i2c_get_clientdata(c);
+
+	switch (t->mode) {
+	case V4L2_TUNER_RADIO:
+		tuner_dbg("radio freq set to %lu.%02lu\n",
+			  freq/16,freq%16*100/16);
+		set_radio_freq(c,freq);
+		break;
+	case V4L2_TUNER_ANALOG_TV:
+	case V4L2_TUNER_DIGITAL_TV:
+		tuner_dbg("tv freq set to %lu.%02lu\n",
+			  freq/16,freq%16*100/16);
+		set_tv_freq(c, freq);
+		break;
+	}
+	t->freq = freq;
+}
+
+static void set_type(struct i2c_client *c, unsigned int type)
+{
+	struct tuner *t = i2c_get_clientdata(c);
+
+	/* sanity check */
+	if (type == UNSET  ||  type == TUNER_ABSENT)
+		return;
+	if (type >= tuner_count)
+		return;
+
+	if (NULL == t->i2c.dev.driver) {
+		/* not registered yet */
+		t->type = type;
+		return;
+	}
+	if (t->initialized)
+		/* run only once */
+		return;
+
+	t->initialized = 1;
+	t->type = type;
+	switch (t->type) {
+	case TUNER_MT2032:
+		microtune_init(c);
+		break;
+	case TUNER_PHILIPS_TDA8290:
+		tda8290_init(c);
+		break;
+	default:
+		default_tuner_init(c);
+		break;
+	}
+}
+
+static char pal[] = "-";
+module_param_string(pal, pal, 0644, sizeof(pal));
+
+static int tuner_fixup_std(struct tuner *t)
+{
+	if ((t->std & V4L2_STD_PAL) == V4L2_STD_PAL) {
+		/* get more precise norm info from insmod option */
+		switch (pal[0]) {
+		case 'b':
+		case 'B':
+		case 'g':
+		case 'G':
+			tuner_dbg("insmod fixup: PAL => PAL-BG\n");
+			t->std = V4L2_STD_PAL_BG;
+			break;
+		case 'i':
+		case 'I':
+			tuner_dbg("insmod fixup: PAL => PAL-I\n");
+			t->std = V4L2_STD_PAL_I;
+			break;
+		case 'd':
+		case 'D':
+		case 'k':
+		case 'K':
+			tuner_dbg("insmod fixup: PAL => PAL-DK\n");
+			t->std = V4L2_STD_PAL_DK;
+			break;
+		}
+	}
+	return 0;
+}
+
+/* ---------------------------------------------------------------------- */
+
+static int tuner_attach(struct i2c_adapter *adap, int addr, int kind)
+{
+	struct tuner *t;
+
+	if (this_adap > 0)
+		return -1;
+	this_adap++;
+
+        client_template.adapter = adap;
+        client_template.addr = addr;
+
+        t = kmalloc(sizeof(struct tuner),GFP_KERNEL);
+        if (NULL == t)
+                return -ENOMEM;
+        memset(t,0,sizeof(struct tuner));
+        memcpy(&t->i2c,&client_template,sizeof(struct i2c_client));
+	i2c_set_clientdata(&t->i2c, t);
+	t->type       = UNSET;
+	t->radio_if2  = 10700*1000; // 10.7MHz - FM radio
+
+        i2c_attach_client(&t->i2c);
+	tuner_info("chip found @ 0x%x (%s)\n",
+		   addr << 1, adap->name);
+	set_type(&t->i2c, t->type);
+	return 0;
+}
+
+static int tuner_probe(struct i2c_adapter *adap)
+{
+	if (0 != addr) {
+		normal_i2c[0]       = addr;
+		normal_i2c_range[0] = addr;
+		normal_i2c_range[1] = addr;
+	}
+	this_adap = 0;
+
+	if (adap->class & I2C_CLASS_TV_ANALOG)
+		return i2c_probe(adap, &addr_data, tuner_attach);
+	return 0;
+}
+
+static int tuner_detach(struct i2c_client *client)
+{
+	struct tuner *t = i2c_get_clientdata(client);
+
+	i2c_detach_client(&t->i2c);
+	kfree(t);
+	return 0;
+}
+
+#define SWITCH_V4L2	if (!t->using_v4l2 && tuner_debug) \
+		          tuner_info("switching to v4l2\n"); \
+	                  t->using_v4l2 = 1;
+#define CHECK_V4L2	if (t->using_v4l2) { if (tuner_debug) \
+			  tuner_info("ignore v4l1 call\n"); \
+		          return 0; }
+
+static int
+tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
+{
+	struct tuner *t = i2c_get_clientdata(client);
+        unsigned int *iarg = (int*)arg;
+
+        switch (cmd) {
+
+	/* --- configuration --- */
+	case TUNER_SET_TYPE:
+		set_type(client,*iarg);
+		break;
+	case AUDC_SET_RADIO:
+		if (V4L2_TUNER_RADIO != t->mode) {
+			set_tv_freq(client,400 * 16);
+			t->mode = V4L2_TUNER_RADIO;
+		}
+		break;
+	case AUDC_CONFIG_PINNACLE:
+		switch (*iarg) {
+		case 2:
+			tuner_dbg("pinnacle pal\n");
+			t->radio_if2 = 33300 * 1000;
+			break;
+		case 3:
+			tuner_dbg("pinnacle ntsc\n");
+			t->radio_if2 = 41300 * 1000;
+			break;
+		}
+                break;
+
+	/* --- v4l ioctls --- */
+	/* take care: bttv does userspace copying, we'll get a
+	   kernel pointer here... */
+	case VIDIOCSCHAN:
+	{
+		static const v4l2_std_id map[] = {
+			[ VIDEO_MODE_PAL   ] = V4L2_STD_PAL,
+			[ VIDEO_MODE_NTSC  ] = V4L2_STD_NTSC_M,
+			[ VIDEO_MODE_SECAM ] = V4L2_STD_SECAM,
+			[ 4 /* bttv */     ] = V4L2_STD_PAL_M,
+			[ 5 /* bttv */     ] = V4L2_STD_PAL_N,
+			[ 6 /* bttv */     ] = V4L2_STD_NTSC_M_JP,
+		};
+		struct video_channel *vc = arg;
+
+		CHECK_V4L2;
+		t->mode = V4L2_TUNER_ANALOG_TV;
+		if (vc->norm < ARRAY_SIZE(map))
+			t->std = map[vc->norm];
+		tuner_fixup_std(t);
+		if (t->freq)
+			set_tv_freq(client,t->freq);
+		return 0;
+	}
+	case VIDIOCSFREQ:
+	{
+		unsigned long *v = arg;
+
+		CHECK_V4L2;
+		set_freq(client,*v);
+		return 0;
+	}
+	case VIDIOCGTUNER:
+	{
+		struct video_tuner *vt = arg;
+
+		CHECK_V4L2;
+		if (V4L2_TUNER_RADIO == t->mode  &&  t->has_signal)
+			vt->signal = t->has_signal(client);
+		return 0;
+	}
+	case VIDIOCGAUDIO:
+	{
+		struct video_audio *va = arg;
+
+		CHECK_V4L2;
+		if (V4L2_TUNER_RADIO == t->mode  &&  t->is_stereo)
+			va->mode = t->is_stereo(client)
+				? VIDEO_SOUND_STEREO
+				: VIDEO_SOUND_MONO;
+		return 0;
+	}
+
+	case VIDIOC_S_STD:
+	{
+		v4l2_std_id *id = arg;
+
+		SWITCH_V4L2;
+		t->mode = V4L2_TUNER_ANALOG_TV;
+		t->std = *id;
+		tuner_fixup_std(t);
+		if (t->freq)
+			set_freq(client,t->freq);
+		break;
+	}
+	case VIDIOC_S_FREQUENCY:
+	{
+		struct v4l2_frequency *f = arg;
+
+		SWITCH_V4L2;
+		if (V4L2_TUNER_RADIO == f->type &&
+		    V4L2_TUNER_RADIO != t->mode)
+			set_tv_freq(client,400*16);
+		t->mode  = f->type;
+		t->freq  = f->frequency;
+		set_freq(client,t->freq);
+		break;
+	}
+	case VIDIOC_G_TUNER:
+	{
+		struct v4l2_tuner *tuner = arg;
+
+		SWITCH_V4L2;
+		if (V4L2_TUNER_RADIO == t->mode  &&  t->has_signal)
+			tuner->signal = t->has_signal(client);
+		break;
+	}
+	default:
+		/* nothing */
+		break;
+	}
+
+	return 0;
+}
+
+static int tuner_suspend(struct device * dev, u32 state, u32 level)
+{
+	struct i2c_client *c = container_of(dev, struct i2c_client, dev);
+	struct tuner *t = i2c_get_clientdata(c);
+
+	tuner_dbg("suspend\n");
+	/* FIXME: power down ??? */
+	return 0;
+}
+
+static int tuner_resume(struct device * dev, u32 level)
+{
+	struct i2c_client *c = container_of(dev, struct i2c_client, dev);
+	struct tuner *t = i2c_get_clientdata(c);
+
+	tuner_dbg("resume\n");
+	if (t->freq)
+		set_freq(c,t->freq);
+	return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+static struct i2c_driver driver = {
+	.owner          = THIS_MODULE,
+        .name           = "tuner",
+        .id             = I2C_DRIVERID_TUNER,
+        .flags          = I2C_DF_NOTIFY,
+        .attach_adapter = tuner_probe,
+        .detach_client  = tuner_detach,
+        .command        = tuner_command,
+	.driver = {
+		.suspend = tuner_suspend,
+		.resume  = tuner_resume,
+	},
+};
+static struct i2c_client client_template =
+{
+	I2C_DEVNAME("(tuner unset)"),
+	.flags      = I2C_CLIENT_ALLOW_USE,
+        .driver     = &driver,
+};
+
+static int __init tuner_init_module(void)
+{
+	return i2c_add_driver(&driver);
+}
+
+static void __exit tuner_cleanup_module(void)
+{
+	i2c_del_driver(&driver);
+}
+
+module_init(tuner_init_module);
+module_exit(tuner_cleanup_module);
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff -Nru a/drivers/media/video/tuner-simple.c b/drivers/media/video/tuner-simple.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/media/video/tuner-simple.c	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,467 @@
+/*
+ * $Id: tuner-simple.c,v 1.4 2005/02/15 15:59:35 kraxel Exp $
+ *
+ * i2c tv tuner chip device driver
+ * controls all those simple 4-control-bytes style tuners.
+ */
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/videodev.h>
+#include <media/tuner.h>
+
+/* ---------------------------------------------------------------------- */
+
+/* tv standard selection for Temic 4046 FM5
+   this value takes the low bits of control byte 2
+   from datasheet Rev.01, Feb.00
+     standard     BG      I       L       L2      D
+     picture IF   38.9    38.9    38.9    33.95   38.9
+     sound 1      33.4    32.9    32.4    40.45   32.4
+     sound 2      33.16
+     NICAM        33.05   32.348  33.05           33.05
+ */
+#define TEMIC_SET_PAL_I         0x05
+#define TEMIC_SET_PAL_DK        0x09
+#define TEMIC_SET_PAL_L         0x0a // SECAM ?
+#define TEMIC_SET_PAL_L2        0x0b // change IF !
+#define TEMIC_SET_PAL_BG        0x0c
+
+/* tv tuner system standard selection for Philips FQ1216ME
+   this value takes the low bits of control byte 2
+   from datasheet "1999 Nov 16" (supersedes "1999 Mar 23")
+     standard 		BG	DK	I	L	L`
+     picture carrier	38.90	38.90	38.90	38.90	33.95
+     colour		34.47	34.47	34.47	34.47	38.38
+     sound 1		33.40	32.40	32.90	32.40	40.45
+     sound 2		33.16	-	-	-	-
+     NICAM		33.05	33.05	32.35	33.05	39.80
+ */
+#define PHILIPS_SET_PAL_I	0x01 /* Bit 2 always zero !*/
+#define PHILIPS_SET_PAL_BGDK	0x09
+#define PHILIPS_SET_PAL_L2	0x0a
+#define PHILIPS_SET_PAL_L	0x0b
+
+/* system switching for Philips FI1216MF MK2
+   from datasheet "1996 Jul 09",
+    standard         BG     L      L'
+    picture carrier  38.90  38.90  33.95
+    colour	     34.47  34.37  38.38
+    sound 1          33.40  32.40  40.45
+    sound 2          33.16  -      -
+    NICAM            33.05  33.05  39.80
+ */
+#define PHILIPS_MF_SET_BG	0x01 /* Bit 2 must be zero, Bit 3 is system output */
+#define PHILIPS_MF_SET_PAL_L	0x03 // France
+#define PHILIPS_MF_SET_PAL_L2	0x02 // L'
+
+
+/* ---------------------------------------------------------------------- */
+
+struct tunertype
+{
+	char *name;
+	unsigned char Vendor;
+	unsigned char Type;
+
+	unsigned short thresh1;  /*  band switch VHF_LO <=> VHF_HI  */
+	unsigned short thresh2;  /*  band switch VHF_HI <=> UHF     */
+	unsigned char VHF_L;
+	unsigned char VHF_H;
+	unsigned char UHF;
+	unsigned char config;
+	unsigned short IFPCoff; /* 622.4=16*38.90 MHz PAL,
+				   732  =16*45.75 NTSCi,
+				   940  =16*58.75 NTSC-Japan
+				   704  =16*44    ATSC */
+};
+
+/*
+ *	The floats in the tuner struct are computed at compile time
+ *	by gcc and cast back to integers. Thus we don't violate the
+ *	"no float in kernel" rule.
+ */
+static struct tunertype tuners[] = {
+        { "Temic PAL (4002 FH5)", TEMIC, PAL,
+	  16*140.25,16*463.25,0x02,0x04,0x01,0x8e,623},
+	{ "Philips PAL_I (FI1246 and compatibles)", Philips, PAL_I,
+	  16*140.25,16*463.25,0xa0,0x90,0x30,0x8e,623},
+	{ "Philips NTSC (FI1236,FM1236 and compatibles)", Philips, NTSC,
+	  16*157.25,16*451.25,0xA0,0x90,0x30,0x8e,732},
+	{ "Philips (SECAM+PAL_BG) (FI1216MF, FM1216MF, FR1216MF)", Philips, SECAM,
+	  16*168.25,16*447.25,0xA7,0x97,0x37,0x8e,623},
+
+	{ "NoTuner", NoTuner, NOTUNER,
+	  0,0,0x00,0x00,0x00,0x00,0x00},
+	{ "Philips PAL_BG (FI1216 and compatibles)", Philips, PAL,
+	  16*168.25,16*447.25,0xA0,0x90,0x30,0x8e,623},
+	{ "Temic NTSC (4032 FY5)", TEMIC, NTSC,
+	  16*157.25,16*463.25,0x02,0x04,0x01,0x8e,732},
+	{ "Temic PAL_I (4062 FY5)", TEMIC, PAL_I,
+	  16*170.00,16*450.00,0x02,0x04,0x01,0x8e,623},
+
+ 	{ "Temic NTSC (4036 FY5)", TEMIC, NTSC,
+	  16*157.25,16*463.25,0xa0,0x90,0x30,0x8e,732},
+        { "Alps HSBH1", TEMIC, NTSC,
+	  16*137.25,16*385.25,0x01,0x02,0x08,0x8e,732},
+        { "Alps TSBE1",TEMIC,PAL,
+	  16*137.25,16*385.25,0x01,0x02,0x08,0x8e,732},
+        { "Alps TSBB5", Alps, PAL_I, /* tested (UK UHF) with Modulartech MM205 */
+	  16*133.25,16*351.25,0x01,0x02,0x08,0x8e,632},
+
+        { "Alps TSBE5", Alps, PAL, /* untested - data sheet guess. Only IF differs. */
+	  16*133.25,16*351.25,0x01,0x02,0x08,0x8e,622},
+        { "Alps TSBC5", Alps, PAL, /* untested - data sheet guess. Only IF differs. */
+	  16*133.25,16*351.25,0x01,0x02,0x08,0x8e,608},
+	{ "Temic PAL_BG (4006FH5)", TEMIC, PAL,
+	  16*170.00,16*450.00,0xa0,0x90,0x30,0x8e,623},
+  	{ "Alps TSCH6",Alps,NTSC,
+  	  16*137.25,16*385.25,0x14,0x12,0x11,0x8e,732},
+
+  	{ "Temic PAL_DK (4016 FY5)",TEMIC,PAL,
+  	  16*168.25,16*456.25,0xa0,0x90,0x30,0x8e,623},
+  	{ "Philips NTSC_M (MK2)",Philips,NTSC,
+  	  16*160.00,16*454.00,0xa0,0x90,0x30,0x8e,732},
+        { "Temic PAL_I (4066 FY5)", TEMIC, PAL_I,
+          16*169.00, 16*454.00, 0xa0,0x90,0x30,0x8e,623},
+        { "Temic PAL* auto (4006 FN5)", TEMIC, PAL,
+          16*169.00, 16*454.00, 0xa0,0x90,0x30,0x8e,623},
+
+        { "Temic PAL_BG (4009 FR5) or PAL_I (4069 FR5)", TEMIC, PAL,
+          16*141.00, 16*464.00, 0xa0,0x90,0x30,0x8e,623},
+        { "Temic NTSC (4039 FR5)", TEMIC, NTSC,
+          16*158.00, 16*453.00, 0xa0,0x90,0x30,0x8e,732},
+        { "Temic PAL/SECAM multi (4046 FM5)", TEMIC, PAL,
+          16*169.00, 16*454.00, 0xa0,0x90,0x30,0x8e,623},
+        { "Philips PAL_DK (FI1256 and compatibles)", Philips, PAL,
+	  16*170.00,16*450.00,0xa0,0x90,0x30,0x8e,623},
+
+	{ "Philips PAL/SECAM multi (FQ1216ME)", Philips, PAL,
+	  16*170.00,16*450.00,0xa0,0x90,0x30,0x8e,623},
+	{ "LG PAL_I+FM (TAPC-I001D)", LGINNOTEK, PAL_I,
+	  16*170.00,16*450.00,0xa0,0x90,0x30,0x8e,623},
+	{ "LG PAL_I (TAPC-I701D)", LGINNOTEK, PAL_I,
+	  16*170.00,16*450.00,0xa0,0x90,0x30,0x8e,623},
+	{ "LG NTSC+FM (TPI8NSR01F)", LGINNOTEK, NTSC,
+	  16*210.00,16*497.00,0xa0,0x90,0x30,0x8e,732},
+
+	{ "LG PAL_BG+FM (TPI8PSB01D)", LGINNOTEK, PAL,
+	  16*170.00,16*450.00,0xa0,0x90,0x30,0x8e,623},
+	{ "LG PAL_BG (TPI8PSB11D)", LGINNOTEK, PAL,
+	  16*170.00,16*450.00,0xa0,0x90,0x30,0x8e,623},
+	{ "Temic PAL* auto + FM (4009 FN5)", TEMIC, PAL,
+	  16*141.00, 16*464.00, 0xa0,0x90,0x30,0x8e,623},
+	{ "SHARP NTSC_JP (2U5JF5540)", SHARP, NTSC, /* 940=16*58.75 NTSC@Japan */
+	  16*137.25,16*317.25,0x01,0x02,0x08,0x8e,940 },
+
+	{ "Samsung PAL TCPM9091PD27", Samsung, PAL,  /* from sourceforge v3tv */
+          16*169,16*464,0xA0,0x90,0x30,0x8e,623},
+	{ "MT20xx universal", Microtune,PAL|NTSC,
+	  /* see mt20xx.c for details */ },
+	{ "Temic PAL_BG (4106 FH5)", TEMIC, PAL,
+          16*141.00, 16*464.00, 0xa0,0x90,0x30,0x8e,623},
+	{ "Temic PAL_DK/SECAM_L (4012 FY5)", TEMIC, PAL,
+          16*140.25, 16*463.25, 0x02,0x04,0x01,0x8e,623},
+
+	{ "Temic NTSC (4136 FY5)", TEMIC, NTSC,
+          16*158.00, 16*453.00, 0xa0,0x90,0x30,0x8e,732},
+        { "LG PAL (newer TAPC series)", LGINNOTEK, PAL,
+          16*170.00, 16*450.00, 0x01,0x02,0x08,0x8e,623},
+	{ "Philips PAL/SECAM multi (FM1216ME MK3)", Philips, PAL,
+	  16*160.00,16*442.00,0x01,0x02,0x04,0x8e,623 },
+	{ "LG NTSC (newer TAPC series)", LGINNOTEK, NTSC,
+          16*170.00, 16*450.00, 0x01,0x02,0x08,0x8e,732},
+
+	{ "HITACHI V7-J180AT", HITACHI, NTSC,
+	  16*170.00, 16*450.00, 0x01,0x02,0x08,0x8e,940 },
+	{ "Philips PAL_MK (FI1216 MK)", Philips, PAL,
+	  16*140.25,16*463.25,0x01,0xc2,0xcf,0x8e,623},
+	{ "Philips 1236D ATSC/NTSC daul in",Philips,ATSC,
+	  16*157.25,16*454.00,0xa0,0x90,0x30,0x8e,732},
+        { "Philips NTSC MK3 (FM1236MK3 or FM1236/F)", Philips, NTSC,
+          16*160.00,16*442.00,0x01,0x02,0x04,0x8e,732},
+
+        { "Philips 4 in 1 (ATI TV Wonder Pro/Conexant)", Philips, NTSC,
+          16*160.00,16*442.00,0x01,0x02,0x04,0x8e,732},
+	{ "Microtune 4049 FM5",Microtune,PAL,
+	  16*141.00,16*464.00,0xa0,0x90,0x30,0x8e,623},
+	{ "Panasonic VP27s/ENGE4324D", Panasonic, NTSC,
+	  16*160.00,16*454.00,0x01,0x02,0x08,0xce,940},
+        { "LG NTSC (TAPE series)", LGINNOTEK, NTSC,
+          16*160.00,16*442.00,0x01,0x02,0x04,0x8e,732 },
+
+        { "Tenna TNF 8831 BGFF)", Philips, PAL,
+          16*161.25,16*463.25,0xa0,0x90,0x30,0x8e,623},
+	{ "Microtune 4042 FI5 ATSC/NTSC dual in", Microtune, NTSC,
+	  16*162.00,16*457.00,0xa2,0x94,0x31,0x8e,732},
+        { "TCL 2002N", TCL, NTSC,
+          16*172.00,16*448.00,0x01,0x02,0x08,0x8e,732},
+	{ "Philips PAL/SECAM_D (FM 1256 I-H3)", Philips, PAL,
+	  16*160.00,16*442.00,0x01,0x02,0x04,0x8e,623 },
+
+	{ "Thomson DDT 7610 (ATSC/NTSC)", THOMSON, ATSC,
+	  16*157.25,16*454.00,0x39,0x3a,0x3c,0x8e,732},
+	{ "Philips FQ1286", Philips, NTSC,
+	  16*160.00,16*454.00,0x41,0x42,0x04,0x8e,940}, // UHF band untested
+	{ "tda8290+75", Philips,PAL|NTSC,
+	  /* see tda8290.c for details */ },
+
+};
+unsigned const int tuner_count = ARRAY_SIZE(tuners);
+
+/* ---------------------------------------------------------------------- */
+
+static int tuner_getstatus(struct i2c_client *c)
+{
+	unsigned char byte;
+
+	if (1 != i2c_master_recv(c,&byte,1))
+		return 0;
+	return byte;
+}
+
+#define TUNER_POR       0x80
+#define TUNER_FL        0x40
+#define TUNER_MODE      0x38
+#define TUNER_AFC       0x07
+
+#define TUNER_STEREO    0x10 /* radio mode */
+#define TUNER_SIGNAL    0x07 /* radio mode */
+
+static int tuner_signal(struct i2c_client *c)
+{
+	return (tuner_getstatus(c) & TUNER_SIGNAL)<<13;
+}
+
+static int tuner_stereo(struct i2c_client *c)
+{
+	return (tuner_getstatus (c) & TUNER_STEREO);
+}
+
+#if 0 /* unused */
+static int tuner_islocked (struct i2c_client *c)
+{
+        return (tuner_getstatus (c) & TUNER_FL);
+}
+
+static int tuner_afcstatus (struct i2c_client *c)
+{
+        return (tuner_getstatus (c) & TUNER_AFC) - 2;
+}
+
+static int tuner_mode (struct i2c_client *c)
+{
+        return (tuner_getstatus (c) & TUNER_MODE) >> 3;
+}
+#endif
+
+/* ---------------------------------------------------------------------- */
+
+static void default_set_tv_freq(struct i2c_client *c, unsigned int freq)
+{
+	struct tuner *t = i2c_get_clientdata(c);
+	u8 config;
+	u16 div;
+	struct tunertype *tun;
+        unsigned char buffer[4];
+	int rc;
+
+	tun = &tuners[t->type];
+	if (freq < tun->thresh1) {
+		config = tun->VHF_L;
+		tuner_dbg("tv: VHF lowrange\n");
+	} else if (freq < tun->thresh2) {
+		config = tun->VHF_H;
+		tuner_dbg("tv: VHF high range\n");
+	} else {
+		config = tun->UHF;
+		tuner_dbg("tv: UHF range\n");
+	}
+
+
+	/* tv norm specific stuff for multi-norm tuners */
+	switch (t->type) {
+	case TUNER_PHILIPS_SECAM: // FI1216MF
+		/* 0x01 -> ??? no change ??? */
+		/* 0x02 -> PAL BDGHI / SECAM L */
+		/* 0x04 -> ??? PAL others / SECAM others ??? */
+		config &= ~0x02;
+		if (t->std & V4L2_STD_SECAM)
+			config |= 0x02;
+		break;
+
+	case TUNER_TEMIC_4046FM5:
+		config &= ~0x0f;
+
+		if (t->std & V4L2_STD_PAL_BG) {
+			config |= TEMIC_SET_PAL_BG;
+
+		} else if (t->std & V4L2_STD_PAL_I) {
+			config |= TEMIC_SET_PAL_I;
+
+		} else if (t->std & V4L2_STD_PAL_DK) {
+			config |= TEMIC_SET_PAL_DK;
+
+		} else if (t->std & V4L2_STD_SECAM_L) {
+			config |= TEMIC_SET_PAL_L;
+
+		}
+		break;
+
+	case TUNER_PHILIPS_FQ1216ME:
+		config &= ~0x0f;
+
+		if (t->std & (V4L2_STD_PAL_BG|V4L2_STD_PAL_DK)) {
+			config |= PHILIPS_SET_PAL_BGDK;
+
+		} else if (t->std & V4L2_STD_PAL_I) {
+			config |= PHILIPS_SET_PAL_I;
+
+		} else if (t->std & V4L2_STD_SECAM_L) {
+			config |= PHILIPS_SET_PAL_L;
+
+		}
+		break;
+
+	case TUNER_PHILIPS_ATSC:
+		/* 0x00 -> ATSC antenna input 1 */
+		/* 0x01 -> ATSC antenna input 2 */
+		/* 0x02 -> NTSC antenna input 1 */
+		/* 0x03 -> NTSC antenna input 2 */
+		config &= ~0x03;
+		if (!(t->std & V4L2_STD_ATSC))
+			config |= 2;
+		/* FIXME: input */
+		break;
+
+	case TUNER_MICROTUNE_4042FI5:
+		/* Set the charge pump for fast tuning */
+		tun->config |= 0x40;
+		break;
+	}
+
+	/*
+	 * Philips FI1216MK2 remark from specification :
+	 * for channel selection involving band switching, and to ensure
+	 * smooth tuning to the desired channel without causing
+	 * unnecessary charge pump action, it is recommended to consider
+	 * the difference between wanted channel frequency and the
+	 * current channel frequency.  Unnecessary charge pump action
+	 * will result in very low tuning voltage which may drive the
+	 * oscillator to extreme conditions.
+	 *
+	 * Progfou: specification says to send config data before
+	 * frequency in case (wanted frequency < current frequency).
+	 */
+
+	div=freq + tun->IFPCoff;
+	if (t->type == TUNER_PHILIPS_SECAM && freq < t->freq) {
+		buffer[0] = tun->config;
+		buffer[1] = config;
+		buffer[2] = (div>>8) & 0x7f;
+		buffer[3] = div      & 0xff;
+	} else {
+		buffer[0] = (div>>8) & 0x7f;
+		buffer[1] = div      & 0xff;
+		buffer[2] = tun->config;
+		buffer[3] = config;
+	}
+	tuner_dbg("tv 0x%02x 0x%02x 0x%02x 0x%02x\n",
+		  buffer[0],buffer[1],buffer[2],buffer[3]);
+
+        if (4 != (rc = i2c_master_send(c,buffer,4)))
+		tuner_warn("i2c i/o error: rc == %d (should be 4)\n",rc);
+
+	if (t->type == TUNER_MICROTUNE_4042FI5) {
+		// FIXME - this may also work for other tuners
+		unsigned long timeout = jiffies + msecs_to_jiffies(1);
+		u8 status_byte = 0;
+
+		/* Wait until the PLL locks */
+		for (;;) {
+			if (time_after(jiffies,timeout))
+				return;
+			if (1 != (rc = i2c_master_recv(c,&status_byte,1))) {
+				tuner_warn("i2c i/o read error: rc == %d (should be 1)\n",rc);
+				break;
+			}
+			/* bit 6 is PLL locked indicator */
+			if (status_byte & 0x40)
+				break;
+			udelay(10);
+		}
+
+		/* Set the charge pump for optimized phase noise figure */
+		tun->config &= ~0x40;
+		buffer[0] = (div>>8) & 0x7f;
+		buffer[1] = div      & 0xff;
+		buffer[2] = tun->config;
+		buffer[3] = config;
+		tuner_dbg("tv 0x%02x 0x%02x 0x%02x 0x%02x\n",
+		       buffer[0],buffer[1],buffer[2],buffer[3]);
+
+		if (4 != (rc = i2c_master_send(c,buffer,4)))
+			tuner_warn("i2c i/o error: rc == %d (should be 4)\n",rc);
+	}
+}
+
+static void default_set_radio_freq(struct i2c_client *c, unsigned int freq)
+{
+	struct tunertype *tun;
+	struct tuner *t = i2c_get_clientdata(c);
+        unsigned char buffer[4];
+	unsigned div;
+	int rc;
+
+	tun=&tuners[t->type];
+	div = freq + (int)(16*10.7);
+	buffer[2] = tun->config;
+
+	switch (t->type) {
+	case TUNER_PHILIPS_FM1216ME_MK3:
+	case TUNER_PHILIPS_FM1236_MK3:
+		buffer[3] = 0x19;
+		break;
+	case TUNER_PHILIPS_FM1256_IH3:
+		div = (20 * freq)/16 + 333 * 2;
+	        buffer[2] = 0x80;
+		buffer[3] = 0x19;
+		break;
+	case TUNER_LG_PAL_FM:
+		buffer[3] = 0xa5;
+		break;
+	default:
+		buffer[3] = 0xa4;
+		break;
+	}
+        buffer[0] = (div>>8) & 0x7f;
+        buffer[1] = div      & 0xff;
+
+	tuner_dbg("radio 0x%02x 0x%02x 0x%02x 0x%02x\n",
+	       buffer[0],buffer[1],buffer[2],buffer[3]);
+
+        if (4 != (rc = i2c_master_send(c,buffer,4)))
+		tuner_warn("i2c i/o error: rc == %d (should be 4)\n",rc);
+}
+
+int default_tuner_init(struct i2c_client *c)
+{
+	struct tuner *t = i2c_get_clientdata(c);
+
+	tuner_info("type set to %d (%s)\n",
+		   t->type, tuners[t->type].name);
+	strlcpy(c->name, tuners[t->type].name, sizeof(c->name));
+
+	t->tv_freq    = default_set_tv_freq;
+	t->radio_freq = default_set_radio_freq;
+	t->has_signal = tuner_signal;
+	t->is_stereo  = tuner_stereo;
+	return 0;
+}
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff -Nru a/drivers/media/video/tuner.c b/drivers/media/video/tuner.c
--- a/drivers/media/video/tuner.c	2005-03-11 12:51:52 -08:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,1425 +0,0 @@
-/*
- * $Id: tuner.c,v 1.36 2005/01/14 13:29:40 kraxel Exp $
- */
-
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/string.h>
-#include <linux/timer.h>
-#include <linux/delay.h>
-#include <linux/errno.h>
-#include <linux/slab.h>
-#include <linux/poll.h>
-#include <linux/i2c.h>
-#include <linux/types.h>
-#include <linux/videodev.h>
-#include <linux/init.h>
-
-#include <media/tuner.h>
-#include <media/audiochip.h>
-
-#define UNSET (-1U)
-
-/* standard i2c insmod options */
-static unsigned short normal_i2c[] = {I2C_CLIENT_END};
-static unsigned short normal_i2c_range[] = {0x60,0x6f,I2C_CLIENT_END};
-I2C_CLIENT_INSMOD;
-
-/* insmod options used at init time => read/only */
-static unsigned int type  =  UNSET;
-static unsigned int addr  =  0;
-module_param(type, int, 0444);
-module_param(addr, int, 0444);
-
-/* insmod options used at runtime => read/write */
-static unsigned int debug         = 0;
-static unsigned int tv_antenna    = 1;
-static unsigned int radio_antenna = 0;
-static unsigned int optimize_vco  = 1;
-module_param(debug,             int, 0644);
-module_param(tv_antenna,        int, 0644);
-module_param(radio_antenna,     int, 0644);
-module_param(optimize_vco,      int, 0644);
-
-static unsigned int tv_range[2]    = { 44, 958 };
-static unsigned int radio_range[2] = { 65, 108 };
-
-module_param_array(tv_range,    int, NULL, 0644);
-module_param_array(radio_range, int, NULL, 0644);
-
-MODULE_DESCRIPTION("device driver for various TV and TV+FM radio tuners");
-MODULE_AUTHOR("Ralph Metzler, Gerd Knorr, Gunther Mayer");
-MODULE_LICENSE("GPL");
-
-static int this_adap;
-#define dprintk     if (debug) printk
-
-struct tuner {
-	unsigned int type;            /* chip type */
-	unsigned int freq;            /* keep track of the current settings */
-	v4l2_std_id  std;
-	int          using_v4l2;
-
-	enum v4l2_tuner_type mode;
-	unsigned int input;
-
-	// only for MT2032
-	unsigned int xogc;
-	unsigned int radio_if2;
-
-	void (*tv_freq)(struct i2c_client *c, unsigned int freq);
-	void (*radio_freq)(struct i2c_client *c, unsigned int freq);
-};
-
-static struct i2c_driver driver;
-static struct i2c_client client_template;
-
-/* ---------------------------------------------------------------------- */
-
-/* tv standard selection for Temic 4046 FM5
-   this value takes the low bits of control byte 2
-   from datasheet Rev.01, Feb.00
-     standard     BG      I       L       L2      D
-     picture IF   38.9    38.9    38.9    33.95   38.9
-     sound 1      33.4    32.9    32.4    40.45   32.4
-     sound 2      33.16
-     NICAM        33.05   32.348  33.05           33.05
- */
-#define TEMIC_SET_PAL_I         0x05
-#define TEMIC_SET_PAL_DK        0x09
-#define TEMIC_SET_PAL_L         0x0a // SECAM ?
-#define TEMIC_SET_PAL_L2        0x0b // change IF !
-#define TEMIC_SET_PAL_BG        0x0c
-
-/* tv tuner system standard selection for Philips FQ1216ME
-   this value takes the low bits of control byte 2
-   from datasheet "1999 Nov 16" (supersedes "1999 Mar 23")
-     standard 		BG	DK	I	L	L`
-     picture carrier	38.90	38.90	38.90	38.90	33.95
-     colour		34.47	34.47	34.47	34.47	38.38
-     sound 1		33.40	32.40	32.90	32.40	40.45
-     sound 2		33.16	-	-	-	-
-     NICAM		33.05	33.05	32.35	33.05	39.80
- */
-#define PHILIPS_SET_PAL_I	0x01 /* Bit 2 always zero !*/
-#define PHILIPS_SET_PAL_BGDK	0x09
-#define PHILIPS_SET_PAL_L2	0x0a
-#define PHILIPS_SET_PAL_L	0x0b
-
-/* system switching for Philips FI1216MF MK2
-   from datasheet "1996 Jul 09",
-    standard         BG     L      L'
-    picture carrier  38.90  38.90  33.95
-    colour	     34.47  34.37  38.38
-    sound 1          33.40  32.40  40.45
-    sound 2          33.16  -      -
-    NICAM            33.05  33.05  39.80
- */
-#define PHILIPS_MF_SET_BG	0x01 /* Bit 2 must be zero, Bit 3 is system output */
-#define PHILIPS_MF_SET_PAL_L	0x03 // France
-#define PHILIPS_MF_SET_PAL_L2	0x02 // L'
-
-
-/* ---------------------------------------------------------------------- */
-
-struct tunertype
-{
-	char *name;
-	unsigned char Vendor;
-	unsigned char Type;
-
-	unsigned short thresh1;  /*  band switch VHF_LO <=> VHF_HI  */
-	unsigned short thresh2;  /*  band switch VHF_HI <=> UHF     */
-	unsigned char VHF_L;
-	unsigned char VHF_H;
-	unsigned char UHF;
-	unsigned char config;
-	unsigned short IFPCoff; /* 622.4=16*38.90 MHz PAL,
-				   732  =16*45.75 NTSCi,
-				   940  =16*58.75 NTSC-Japan
-				   704  =16*44    ATSC */
-};
-
-/*
- *	The floats in the tuner struct are computed at compile time
- *	by gcc and cast back to integers. Thus we don't violate the
- *	"no float in kernel" rule.
- */
-static struct tunertype tuners[] = {
-        { "Temic PAL (4002 FH5)", TEMIC, PAL,
-	  16*140.25,16*463.25,0x02,0x04,0x01,0x8e,623},
-	{ "Philips PAL_I (FI1246 and compatibles)", Philips, PAL_I,
-	  16*140.25,16*463.25,0xa0,0x90,0x30,0x8e,623},
-	{ "Philips NTSC (FI1236,FM1236 and compatibles)", Philips, NTSC,
-	  16*157.25,16*451.25,0xA0,0x90,0x30,0x8e,732},
-	{ "Philips (SECAM+PAL_BG) (FI1216MF, FM1216MF, FR1216MF)", Philips, SECAM,
-	  16*168.25,16*447.25,0xA7,0x97,0x37,0x8e,623},
-
-	{ "NoTuner", NoTuner, NOTUNER,
-	  0,0,0x00,0x00,0x00,0x00,0x00},
-	{ "Philips PAL_BG (FI1216 and compatibles)", Philips, PAL,
-	  16*168.25,16*447.25,0xA0,0x90,0x30,0x8e,623},
-	{ "Temic NTSC (4032 FY5)", TEMIC, NTSC,
-	  16*157.25,16*463.25,0x02,0x04,0x01,0x8e,732},
-	{ "Temic PAL_I (4062 FY5)", TEMIC, PAL_I,
-	  16*170.00,16*450.00,0x02,0x04,0x01,0x8e,623},
-
- 	{ "Temic NTSC (4036 FY5)", TEMIC, NTSC,
-	  16*157.25,16*463.25,0xa0,0x90,0x30,0x8e,732},
-        { "Alps HSBH1", TEMIC, NTSC,
-	  16*137.25,16*385.25,0x01,0x02,0x08,0x8e,732},
-        { "Alps TSBE1",TEMIC,PAL,
-	  16*137.25,16*385.25,0x01,0x02,0x08,0x8e,732},
-        { "Alps TSBB5", Alps, PAL_I, /* tested (UK UHF) with Modulartech MM205 */
-	  16*133.25,16*351.25,0x01,0x02,0x08,0x8e,632},
-
-        { "Alps TSBE5", Alps, PAL, /* untested - data sheet guess. Only IF differs. */
-	  16*133.25,16*351.25,0x01,0x02,0x08,0x8e,622},
-        { "Alps TSBC5", Alps, PAL, /* untested - data sheet guess. Only IF differs. */
-	  16*133.25,16*351.25,0x01,0x02,0x08,0x8e,608},
-	{ "Temic PAL_BG (4006FH5)", TEMIC, PAL,
-	  16*170.00,16*450.00,0xa0,0x90,0x30,0x8e,623},
-  	{ "Alps TSCH6",Alps,NTSC,
-  	  16*137.25,16*385.25,0x14,0x12,0x11,0x8e,732},
-
-  	{ "Temic PAL_DK (4016 FY5)",TEMIC,PAL,
-  	  16*168.25,16*456.25,0xa0,0x90,0x30,0x8e,623},
-  	{ "Philips NTSC_M (MK2)",Philips,NTSC,
-  	  16*160.00,16*454.00,0xa0,0x90,0x30,0x8e,732},
-        { "Temic PAL_I (4066 FY5)", TEMIC, PAL_I,
-          16*169.00, 16*454.00, 0xa0,0x90,0x30,0x8e,623},
-        { "Temic PAL* auto (4006 FN5)", TEMIC, PAL,
-          16*169.00, 16*454.00, 0xa0,0x90,0x30,0x8e,623},
-
-        { "Temic PAL_BG (4009 FR5) or PAL_I (4069 FR5)", TEMIC, PAL,
-          16*141.00, 16*464.00, 0xa0,0x90,0x30,0x8e,623},
-        { "Temic NTSC (4039 FR5)", TEMIC, NTSC,
-          16*158.00, 16*453.00, 0xa0,0x90,0x30,0x8e,732},
-        { "Temic PAL/SECAM multi (4046 FM5)", TEMIC, PAL,
-          16*169.00, 16*454.00, 0xa0,0x90,0x30,0x8e,623},
-        { "Philips PAL_DK (FI1256 and compatibles)", Philips, PAL,
-	  16*170.00,16*450.00,0xa0,0x90,0x30,0x8e,623},
-
-	{ "Philips PAL/SECAM multi (FQ1216ME)", Philips, PAL,
-	  16*170.00,16*450.00,0xa0,0x90,0x30,0x8e,623},
-	{ "LG PAL_I+FM (TAPC-I001D)", LGINNOTEK, PAL_I,
-	  16*170.00,16*450.00,0xa0,0x90,0x30,0x8e,623},
-	{ "LG PAL_I (TAPC-I701D)", LGINNOTEK, PAL_I,
-	  16*170.00,16*450.00,0xa0,0x90,0x30,0x8e,623},
-	{ "LG NTSC+FM (TPI8NSR01F)", LGINNOTEK, NTSC,
-	  16*210.00,16*497.00,0xa0,0x90,0x30,0x8e,732},
-
-	{ "LG PAL_BG+FM (TPI8PSB01D)", LGINNOTEK, PAL,
-	  16*170.00,16*450.00,0xa0,0x90,0x30,0x8e,623},
-	{ "LG PAL_BG (TPI8PSB11D)", LGINNOTEK, PAL,
-	  16*170.00,16*450.00,0xa0,0x90,0x30,0x8e,623},
-	{ "Temic PAL* auto + FM (4009 FN5)", TEMIC, PAL,
-	  16*141.00, 16*464.00, 0xa0,0x90,0x30,0x8e,623},
-	{ "SHARP NTSC_JP (2U5JF5540)", SHARP, NTSC, /* 940=16*58.75 NTSC@Japan */
-	  16*137.25,16*317.25,0x01,0x02,0x08,0x8e,940 },
-
-	{ "Samsung PAL TCPM9091PD27", Samsung, PAL,  /* from sourceforge v3tv */
-          16*169,16*464,0xA0,0x90,0x30,0x8e,623},
-	{ "MT20xx universal", Microtune,PAL|NTSC,
-               0,0,0,0,0,0,0},
-	{ "Temic PAL_BG (4106 FH5)", TEMIC, PAL,
-          16*141.00, 16*464.00, 0xa0,0x90,0x30,0x8e,623},
-	{ "Temic PAL_DK/SECAM_L (4012 FY5)", TEMIC, PAL,
-          16*140.25, 16*463.25, 0x02,0x04,0x01,0x8e,623},
-
-	{ "Temic NTSC (4136 FY5)", TEMIC, NTSC,
-          16*158.00, 16*453.00, 0xa0,0x90,0x30,0x8e,732},
-        { "LG PAL (newer TAPC series)", LGINNOTEK, PAL,
-          16*170.00, 16*450.00, 0x01,0x02,0x08,0x8e,623},
-	{ "Philips PAL/SECAM multi (FM1216ME MK3)", Philips, PAL,
-	  16*160.00,16*442.00,0x01,0x02,0x04,0x8e,623 },
-	{ "LG NTSC (newer TAPC series)", LGINNOTEK, NTSC,
-          16*170.00, 16*450.00, 0x01,0x02,0x08,0x8e,732},
-
-	{ "HITACHI V7-J180AT", HITACHI, NTSC,
-	  16*170.00, 16*450.00, 0x01,0x02,0x08,0x8e,940 },
-	{ "Philips PAL_MK (FI1216 MK)", Philips, PAL,
-	  16*140.25,16*463.25,0x01,0xc2,0xcf,0x8e,623},
-	{ "Philips 1236D ATSC/NTSC daul in",Philips,ATSC,
-	  16*157.25,16*454.00,0xa0,0x90,0x30,0x8e,732},
-        { "Philips NTSC MK3 (FM1236MK3 or FM1236/F)", Philips, NTSC,
-          16*160.00,16*442.00,0x01,0x02,0x04,0x8e,732},
-
-        { "Philips 4 in 1 (ATI TV Wonder Pro/Conexant)", Philips, NTSC,
-          16*160.00,16*442.00,0x01,0x02,0x04,0x8e,732},
-	{ "Microtune 4049 FM5",Microtune,PAL,
-	  16*141.00,16*464.00,0xa0,0x90,0x30,0x8e,623},
-	{ "Panasonic VP27s/ENGE4324D", Panasonic, NTSC,
-	  16*160.00,16*454.00,0x01,0x02,0x08,0xce,940},
-        { "LG NTSC (TAPE series)", LGINNOTEK, NTSC,
-          16*160.00,16*442.00,0x01,0x02,0x04,0x8e,732 },
-
-        { "Tenna TNF 8831 BGFF)", Philips, PAL,
-          16*161.25,16*463.25,0xa0,0x90,0x30,0x8e,623},
-	{ "Microtune 4042 FI5 ATSC/NTSC dual in", Microtune, NTSC,
-	  16*162.00,16*457.00,0xa2,0x94,0x31,0x8e,732},
-        { "TCL 2002N", TCL, NTSC,
-          16*172.00,16*448.00,0x01,0x02,0x08,0x8e,732},
-	{ "Philips PAL/SECAM_D (FM 1256 I-H3)", Philips, PAL,
-	  16*160.00,16*442.00,0x01,0x02,0x04,0x8e,623 },
-
-	{ "Thomson DDT 7610 ATSC/NTSC)", THOMSON, ATSC,
-	  16*157.25,16*454.00,0x39,0x3a,0x3c,0x8e,732},
-	{ "Philips FQ1286", Philips, NTSC,
-	  16*160.00,16*454.00,0x41,0x42,0x04,0x8e,940}, // UHF band untested
-
-};
-#define TUNERS ARRAY_SIZE(tuners)
-
-/* ---------------------------------------------------------------------- */
-
-static int tuner_getstatus(struct i2c_client *c)
-{
-	unsigned char byte;
-
-	struct tuner *t = i2c_get_clientdata(c);
-
-        if (t->type == TUNER_MT2032)
-		return 0;
-
-	if (1 != i2c_master_recv(c,&byte,1))
-		return 0;
-	return byte;
-}
-
-#define TUNER_POR       0x80
-#define TUNER_FL        0x40
-#define TUNER_MODE      0x38
-#define TUNER_AFC       0x07
-
-#define TUNER_STEREO    0x10 /* radio mode */
-#define TUNER_SIGNAL    0x07 /* radio mode */
-
-static int tuner_signal(struct i2c_client *c)
-{
-	return (tuner_getstatus(c) & TUNER_SIGNAL)<<13;
-}
-
-static int tuner_stereo(struct i2c_client *c)
-{
-	return (tuner_getstatus (c) & TUNER_STEREO);
-}
-
-#if 0 /* unused */
-static int tuner_islocked (struct i2c_client *c)
-{
-        return (tuner_getstatus (c) & TUNER_FL);
-}
-
-static int tuner_afcstatus (struct i2c_client *c)
-{
-        return (tuner_getstatus (c) & TUNER_AFC) - 2;
-}
-
-static int tuner_mode (struct i2c_client *c)
-{
-        return (tuner_getstatus (c) & TUNER_MODE) >> 3;
-}
-#endif
-
-/* ---------------------------------------------------------------------- */
-
-#define MT2032 0x04
-#define MT2030 0x06
-#define MT2040 0x07
-#define MT2050 0x42
-
-static char *microtune_part[] = {
-	[ MT2030 ] = "MT2030",
-	[ MT2032 ] = "MT2032",
-	[ MT2040 ] = "MT2040",
-	[ MT2050 ] = "MT2050",
-};
-
-// IsSpurInBand()?
-static int mt2032_spurcheck(int f1, int f2, int spectrum_from,int spectrum_to)
-{
-	int n1=1,n2,f;
-
-	f1=f1/1000; //scale to kHz to avoid 32bit overflows
-	f2=f2/1000;
-	spectrum_from/=1000;
-	spectrum_to/=1000;
-
-	dprintk("spurcheck f1=%d f2=%d  from=%d to=%d\n",f1,f2,spectrum_from,spectrum_to);
-
-	do {
-	    n2=-n1;
-	    f=n1*(f1-f2);
-	    do {
-		n2--;
-		f=f-f2;
-		dprintk(" spurtest n1=%d n2=%d ftest=%d\n",n1,n2,f);
-
-		if( (f>spectrum_from) && (f<spectrum_to))
-			printk("mt2032 spurcheck triggered: %d\n",n1);
-	    } while ( (f>(f2-spectrum_to)) || (n2>-5));
-	    n1++;
-	} while (n1<5);
-
-	return 1;
-}
-
-static int mt2032_compute_freq(unsigned int rfin,
-			       unsigned int if1, unsigned int if2,
-			       unsigned int spectrum_from,
-			       unsigned int spectrum_to,
-			       unsigned char *buf,
-			       int *ret_sel,
-			       unsigned int xogc) //all in Hz
-{
-        unsigned int fref,lo1,lo1n,lo1a,s,sel,lo1freq, desired_lo1,
-		desired_lo2,lo2,lo2n,lo2a,lo2num,lo2freq;
-
-        fref= 5250 *1000; //5.25MHz
-	desired_lo1=rfin+if1;
-
-	lo1=(2*(desired_lo1/1000)+(fref/1000)) / (2*fref/1000);
-        lo1n=lo1/8;
-        lo1a=lo1-(lo1n*8);
-
-        s=rfin/1000/1000+1090;
-
-	if(optimize_vco) {
-		if(s>1890) sel=0;
-		else if(s>1720) sel=1;
-		else if(s>1530) sel=2;
-		else if(s>1370) sel=3;
-		else sel=4; // >1090
-	}
-	else {
-        	if(s>1790) sel=0; // <1958
-        	else if(s>1617) sel=1;
-        	else if(s>1449) sel=2;
-        	else if(s>1291) sel=3;
-        	else sel=4; // >1090
-	}
-	*ret_sel=sel;
-
-        lo1freq=(lo1a+8*lo1n)*fref;
-
-        dprintk("mt2032: rfin=%d lo1=%d lo1n=%d lo1a=%d sel=%d, lo1freq=%d\n",
-		rfin,lo1,lo1n,lo1a,sel,lo1freq);
-
-        desired_lo2=lo1freq-rfin-if2;
-        lo2=(desired_lo2)/fref;
-        lo2n=lo2/8;
-        lo2a=lo2-(lo2n*8);
-        lo2num=((desired_lo2/1000)%(fref/1000))* 3780/(fref/1000); //scale to fit in 32bit arith
-        lo2freq=(lo2a+8*lo2n)*fref + lo2num*(fref/1000)/3780*1000;
-
-        dprintk("mt2032: rfin=%d lo2=%d lo2n=%d lo2a=%d num=%d lo2freq=%d\n",
-		rfin,lo2,lo2n,lo2a,lo2num,lo2freq);
-
-        if(lo1a<0 || lo1a>7 || lo1n<17 ||lo1n>48 || lo2a<0 ||lo2a >7 ||lo2n<17 || lo2n>30) {
-                printk("mt2032: frequency parameters out of range: %d %d %d %d\n",
-		       lo1a, lo1n, lo2a,lo2n);
-                return(-1);
-        }
-
-	mt2032_spurcheck(lo1freq, desired_lo2,  spectrum_from, spectrum_to);
-	// should recalculate lo1 (one step up/down)
-
-	// set up MT2032 register map for transfer over i2c
-	buf[0]=lo1n-1;
-	buf[1]=lo1a | (sel<<4);
-	buf[2]=0x86; // LOGC
-	buf[3]=0x0f; //reserved
-	buf[4]=0x1f;
-	buf[5]=(lo2n-1) | (lo2a<<5);
- 	if(rfin >400*1000*1000)
-                buf[6]=0xe4;
-        else
-                buf[6]=0xf4; // set PKEN per rev 1.2
-	buf[7]=8+xogc;
-	buf[8]=0xc3; //reserved
-	buf[9]=0x4e; //reserved
-	buf[10]=0xec; //reserved
-	buf[11]=(lo2num&0xff);
-	buf[12]=(lo2num>>8) |0x80; // Lo2RST
-
-	return 0;
-}
-
-static int mt2032_check_lo_lock(struct i2c_client *c)
-{
-	int try,lock=0;
-	unsigned char buf[2];
-	for(try=0;try<10;try++) {
-		buf[0]=0x0e;
-		i2c_master_send(c,buf,1);
-		i2c_master_recv(c,buf,1);
-		dprintk("mt2032 Reg.E=0x%02x\n",buf[0]);
-		lock=buf[0] &0x06;
-
-		if (lock==6)
-			break;
-
-		dprintk("mt2032: pll wait 1ms for lock (0x%2x)\n",buf[0]);
-		udelay(1000);
-	}
-        return lock;
-}
-
-static int mt2032_optimize_vco(struct i2c_client *c,int sel,int lock)
-{
-	unsigned char buf[2];
-	int tad1;
-
-	buf[0]=0x0f;
-	i2c_master_send(c,buf,1);
-	i2c_master_recv(c,buf,1);
-	dprintk("mt2032 Reg.F=0x%02x\n",buf[0]);
-	tad1=buf[0]&0x07;
-
-	if(tad1 ==0) return lock;
-	if(tad1 ==1) return lock;
-
-	if(tad1==2) {
-		if(sel==0)
-			return lock;
-		else sel--;
-	}
-	else {
-		if(sel<4)
-			sel++;
-		else
-			return lock;
-	}
-
-	dprintk("mt2032 optimize_vco: sel=%d\n",sel);
-
-	buf[0]=0x0f;
-	buf[1]=sel;
-        i2c_master_send(c,buf,2);
-	lock=mt2032_check_lo_lock(c);
-	return lock;
-}
-
-
-static void mt2032_set_if_freq(struct i2c_client *c, unsigned int rfin,
-			       unsigned int if1, unsigned int if2,
-			       unsigned int from, unsigned int to)
-{
-	unsigned char buf[21];
-	int lint_try,ret,sel,lock=0;
-	struct tuner *t = i2c_get_clientdata(c);
-
-	dprintk("mt2032_set_if_freq rfin=%d if1=%d if2=%d from=%d to=%d\n",rfin,if1,if2,from,to);
-
-        buf[0]=0;
-        ret=i2c_master_send(c,buf,1);
-        i2c_master_recv(c,buf,21);
-
-	buf[0]=0;
-	ret=mt2032_compute_freq(rfin,if1,if2,from,to,&buf[1],&sel,t->xogc);
-	if (ret<0)
-		return;
-
-        // send only the relevant registers per Rev. 1.2
-        buf[0]=0;
-        ret=i2c_master_send(c,buf,4);
-        buf[5]=5;
-        ret=i2c_master_send(c,buf+5,4);
-        buf[11]=11;
-        ret=i2c_master_send(c,buf+11,3);
-        if(ret!=3)
-                printk("mt2032_set_if_freq failed with %d\n",ret);
-
-	// wait for PLLs to lock (per manual), retry LINT if not.
-	for(lint_try=0; lint_try<2; lint_try++) {
-		lock=mt2032_check_lo_lock(c);
-
-		if(optimize_vco)
-			lock=mt2032_optimize_vco(c,sel,lock);
-		if(lock==6) break;
-
-		printk("mt2032: re-init PLLs by LINT\n");
-		buf[0]=7;
-		buf[1]=0x80 +8+t->xogc; // set LINT to re-init PLLs
-		i2c_master_send(c,buf,2);
-		mdelay(10);
-		buf[1]=8+t->xogc;
-		i2c_master_send(c,buf,2);
-        }
-
-	if (lock!=6)
-		printk("MT2032 Fatal Error: PLLs didn't lock.\n");
-
-	buf[0]=2;
-	buf[1]=0x20; // LOGC for optimal phase noise
-	ret=i2c_master_send(c,buf,2);
-	if (ret!=2)
-		printk("mt2032_set_if_freq2 failed with %d\n",ret);
-}
-
-
-static void mt2032_set_tv_freq(struct i2c_client *c, unsigned int freq)
-{
-	struct tuner *t = i2c_get_clientdata(c);
-	int if2,from,to;
-
-	// signal bandwidth and picture carrier
-	if (t->std & V4L2_STD_525_60) {
-		// NTSC
-		from = 40750*1000;
-		to   = 46750*1000;
-		if2  = 45750*1000;
-	} else {
-		// PAL
-		from = 32900*1000;
-		to   = 39900*1000;
-		if2  = 38900*1000;
-	}
-
-        mt2032_set_if_freq(c, freq*62500 /* freq*1000*1000/16 */,
-			   1090*1000*1000, if2, from, to);
-}
-
-static void mt2032_set_radio_freq(struct i2c_client *c, unsigned int freq)
-{
-	struct tuner *t = i2c_get_clientdata(c);
-	int if2 = t->radio_if2;
-
-	// per Manual for FM tuning: first if center freq. 1085 MHz
-        mt2032_set_if_freq(c, freq*62500 /* freq*1000*1000/16 */,
-			   1085*1000*1000,if2,if2,if2);
-}
-
-// Initalization as described in "MT203x Programming Procedures", Rev 1.2, Feb.2001
-static int mt2032_init(struct i2c_client *c)
-{
-	struct tuner *t = i2c_get_clientdata(c);
-        unsigned char buf[21];
-        int ret,xogc,xok=0;
-
-	// Initialize Registers per spec.
-        buf[1]=2; // Index to register 2
-        buf[2]=0xff;
-        buf[3]=0x0f;
-        buf[4]=0x1f;
-        ret=i2c_master_send(c,buf+1,4);
-
-        buf[5]=6; // Index register 6
-        buf[6]=0xe4;
-        buf[7]=0x8f;
-        buf[8]=0xc3;
-        buf[9]=0x4e;
-        buf[10]=0xec;
-        ret=i2c_master_send(c,buf+5,6);
-
-        buf[12]=13;  // Index register 13
-        buf[13]=0x32;
-        ret=i2c_master_send(c,buf+12,2);
-
-        // Adjust XOGC (register 7), wait for XOK
-        xogc=7;
-        do {
-		dprintk("mt2032: xogc = 0x%02x\n",xogc&0x07);
-                mdelay(10);
-                buf[0]=0x0e;
-                i2c_master_send(c,buf,1);
-                i2c_master_recv(c,buf,1);
-                xok=buf[0]&0x01;
-                dprintk("mt2032: xok = 0x%02x\n",xok);
-                if (xok == 1) break;
-
-                xogc--;
-                dprintk("mt2032: xogc = 0x%02x\n",xogc&0x07);
-                if (xogc == 3) {
-                        xogc=4; // min. 4 per spec
-                        break;
-                }
-                buf[0]=0x07;
-                buf[1]=0x88 + xogc;
-                ret=i2c_master_send(c,buf,2);
-                if (ret!=2)
-                        printk("mt2032_init failed with %d\n",ret);
-        } while (xok != 1 );
-	t->xogc=xogc;
-
-	t->tv_freq    = mt2032_set_tv_freq;
-	t->radio_freq = mt2032_set_radio_freq;
-        return(1);
-}
-
-static void mt2050_set_antenna(struct i2c_client *c, unsigned char antenna)
-{
-       unsigned char buf[2];
-       int ret;
-
-       buf[0] = 6;
-       buf[1] = antenna ? 0x11 : 0x10;
-       ret=i2c_master_send(c,buf,2);
-       dprintk("mt2050: enabled antenna connector %d\n", antenna);
-}
-
-static void mt2050_set_if_freq(struct i2c_client *c,unsigned int freq, unsigned int if2)
-{
-	unsigned int if1=1218*1000*1000;
-	unsigned int f_lo1,f_lo2,lo1,lo2,f_lo1_modulo,f_lo2_modulo,num1,num2,div1a,div1b,div2a,div2b;
-	int ret;
-	unsigned char buf[6];
-
-	dprintk("mt2050_set_if_freq freq=%d if1=%d if2=%d\n",
-		freq,if1,if2);
-
-	f_lo1=freq+if1;
-	f_lo1=(f_lo1/1000000)*1000000;
-
-	f_lo2=f_lo1-freq-if2;
-	f_lo2=(f_lo2/50000)*50000;
-
-	lo1=f_lo1/4000000;
-	lo2=f_lo2/4000000;
-
-	f_lo1_modulo= f_lo1-(lo1*4000000);
-	f_lo2_modulo= f_lo2-(lo2*4000000);
-
-	num1=4*f_lo1_modulo/4000000;
-	num2=4096*(f_lo2_modulo/1000)/4000;
-
-	// todo spurchecks
-
-	div1a=(lo1/12)-1;
-	div1b=lo1-(div1a+1)*12;
-
-	div2a=(lo2/8)-1;
-	div2b=lo2-(div2a+1)*8;
-
-	if (debug > 1) {
-		printk("lo1 lo2 = %d %d\n", lo1, lo2);
-		printk("num1 num2 div1a div1b div2a div2b= %x %x %x %x %x %x\n",num1,num2,div1a,div1b,div2a,div2b);
-	}
-
-	buf[0]=1;
-	buf[1]= 4*div1b + num1;
-	if(freq<275*1000*1000) buf[1] = buf[1]|0x80;
-
-	buf[2]=div1a;
-	buf[3]=32*div2b + num2/256;
-	buf[4]=num2-(num2/256)*256;
-	buf[5]=div2a;
-	if(num2!=0) buf[5]=buf[5]|0x40;
-
-	if (debug > 1) {
-		int i;
-		printk("bufs is: ");
-		for(i=0;i<6;i++)
-			printk("%x ",buf[i]);
-		printk("\n");
-	}
-
-	ret=i2c_master_send(c,buf,6);
-        if (ret!=6)
-                printk("mt2050_set_if_freq failed with %d\n",ret);
-}
-
-static void mt2050_set_tv_freq(struct i2c_client *c, unsigned int freq)
-{
-	struct tuner *t = i2c_get_clientdata(c);
-	unsigned int if2;
-
-	if (t->std & V4L2_STD_525_60) {
-		// NTSC
-                if2 = 45750*1000;
-        } else {
-                // PAL
-                if2 = 38900*1000;
-        }
-	if (V4L2_TUNER_DIGITAL_TV == t->mode) {
-		// testing for DVB ...
-		if2 = 36150*1000;
-	}
-	mt2050_set_if_freq(c, freq*62500, if2);
-	mt2050_set_antenna(c, tv_antenna);
-}
-
-static void mt2050_set_radio_freq(struct i2c_client *c, unsigned int freq)
-{
-	struct tuner *t = i2c_get_clientdata(c);
-	int if2 = t->radio_if2;
-
-	mt2050_set_if_freq(c, freq*62500, if2);
-	mt2050_set_antenna(c, radio_antenna);
-}
-
-static int mt2050_init(struct i2c_client *c)
-{
-	struct tuner *t = i2c_get_clientdata(c);
-	unsigned char buf[2];
-	int ret;
-
-	buf[0]=6;
-	buf[1]=0x10;
-	ret=i2c_master_send(c,buf,2); //  power
-
-	buf[0]=0x0f;
-	buf[1]=0x0f;
-	ret=i2c_master_send(c,buf,2); // m1lo
-
-	buf[0]=0x0d;
-	ret=i2c_master_send(c,buf,1);
-	i2c_master_recv(c,buf,1);
-
-	dprintk("mt2050: sro is %x\n",buf[0]);
-	t->tv_freq    = mt2050_set_tv_freq;
-	t->radio_freq = mt2050_set_radio_freq;
-	return 0;
-}
-
-static int microtune_init(struct i2c_client *c)
-{
-	struct tuner *t = i2c_get_clientdata(c);
-	char *name;
-        unsigned char buf[21];
-	int company_code;
-
-	memset(buf,0,sizeof(buf));
-	t->tv_freq    = NULL;
-	t->radio_freq = NULL;
-	name = "unknown";
-
-        i2c_master_send(c,buf,1);
-        i2c_master_recv(c,buf,21);
-        if(debug) {
-                int i;
-                printk(KERN_DEBUG "tuner: MT2032 hexdump:\n");
-                for(i=0;i<21;i++) {
-                        printk(" %02x",buf[i]);
-                        if(((i+1)%8)==0) printk(" ");
-                        if(((i+1)%16)==0) printk("\n ");
-                }
-                printk("\n ");
-        }
-	company_code = buf[0x11] << 8 | buf[0x12];
-        printk("tuner: microtune: companycode=%04x part=%02x rev=%02x\n",
-	       company_code,buf[0x13],buf[0x14]);
-
-#if 0
-	/* seems to cause more problems than it solves ... */
-	switch (company_code) {
-	case 0x30bf:
-	case 0x3cbf:
-	case 0x3dbf:
-	case 0x4d54:
-	case 0x8e81:
-	case 0x8e91:
-		/* ok (?) */
-		break;
-	default:
-		printk("tuner: microtune: unknown companycode\n");
-		return 0;
-	}
-#endif
-
-	if (buf[0x13] < ARRAY_SIZE(microtune_part) &&
-	    NULL != microtune_part[buf[0x13]])
-		name = microtune_part[buf[0x13]];
-	switch (buf[0x13]) {
-	case MT2032:
-		mt2032_init(c);
-		break;
-	case MT2050:
-		mt2050_init(c);
-		break;
-	default:
-		printk("tuner: microtune %s found, not (yet?) supported, sorry :-/\n",
-		       name);
-                return 0;
-        }
-	printk("tuner: microtune %s found, OK\n",name);
-	return 0;
-}
-
-/* ---------------------------------------------------------------------- */
-
-static void default_set_tv_freq(struct i2c_client *c, unsigned int freq)
-{
-	struct tuner *t = i2c_get_clientdata(c);
-	u8 config;
-	u16 div;
-	struct tunertype *tun;
-        unsigned char buffer[4];
-	int rc;
-
-	tun = &tuners[t->type];
-	if (freq < tun->thresh1) {
-		config = tun->VHF_L;
-		dprintk("tv: VHF lowrange\n");
-	} else if (freq < tun->thresh2) {
-		config = tun->VHF_H;
-		dprintk("tv: VHF high range\n");
-	} else {
-		config = tun->UHF;
-		dprintk("tv: UHF range\n");
-	}
-
-
-	/* tv norm specific stuff for multi-norm tuners */
-	switch (t->type) {
-	case TUNER_PHILIPS_SECAM: // FI1216MF
-		/* 0x01 -> ??? no change ??? */
-		/* 0x02 -> PAL BDGHI / SECAM L */
-		/* 0x04 -> ??? PAL others / SECAM others ??? */
-		config &= ~0x02;
-		if (t->std & V4L2_STD_SECAM)
-			config |= 0x02;
-		break;
-
-	case TUNER_TEMIC_4046FM5:
-		config &= ~0x0f;
-
-		if (t->std & V4L2_STD_PAL_BG) {
-			config |= TEMIC_SET_PAL_BG;
-
-		} else if (t->std & V4L2_STD_PAL_I) {
-			config |= TEMIC_SET_PAL_I;
-
-		} else if (t->std & V4L2_STD_PAL_DK) {
-			config |= TEMIC_SET_PAL_DK;
-
-		} else if (t->std & V4L2_STD_SECAM_L) {
-			config |= TEMIC_SET_PAL_L;
-
-		}
-		break;
-
-	case TUNER_PHILIPS_FQ1216ME:
-		config &= ~0x0f;
-
-		if (t->std & (V4L2_STD_PAL_BG|V4L2_STD_PAL_DK)) {
-			config |= PHILIPS_SET_PAL_BGDK;
-
-		} else if (t->std & V4L2_STD_PAL_I) {
-			config |= PHILIPS_SET_PAL_I;
-
-		} else if (t->std & V4L2_STD_SECAM_L) {
-			config |= PHILIPS_SET_PAL_L;
-
-		}
-		break;
-
-	case TUNER_PHILIPS_ATSC:
-		/* 0x00 -> ATSC antenna input 1 */
-		/* 0x01 -> ATSC antenna input 2 */
-		/* 0x02 -> NTSC antenna input 1 */
-		/* 0x03 -> NTSC antenna input 2 */
-		config &= ~0x03;
-		if (!(t->std & V4L2_STD_ATSC))
-			config |= 2;
-		/* FIXME: input */
-		break;
-
-	case TUNER_MICROTUNE_4042FI5:
-		/* Set the charge pump for fast tuning */
-		tun->config |= 0x40;
-		break;
-	}
-
-	/*
-	 * Philips FI1216MK2 remark from specification :
-	 * for channel selection involving band switching, and to ensure
-	 * smooth tuning to the desired channel without causing
-	 * unnecessary charge pump action, it is recommended to consider
-	 * the difference between wanted channel frequency and the
-	 * current channel frequency.  Unnecessary charge pump action
-	 * will result in very low tuning voltage which may drive the
-	 * oscillator to extreme conditions.
-	 *
-	 * Progfou: specification says to send config data before
-	 * frequency in case (wanted frequency < current frequency).
-	 */
-
-	div=freq + tun->IFPCoff;
-	if (t->type == TUNER_PHILIPS_SECAM && freq < t->freq) {
-		buffer[0] = tun->config;
-		buffer[1] = config;
-		buffer[2] = (div>>8) & 0x7f;
-		buffer[3] = div      & 0xff;
-	} else {
-		buffer[0] = (div>>8) & 0x7f;
-		buffer[1] = div      & 0xff;
-		buffer[2] = tun->config;
-		buffer[3] = config;
-	}
-	dprintk("tuner: tv 0x%02x 0x%02x 0x%02x 0x%02x\n",
-		buffer[0],buffer[1],buffer[2],buffer[3]);
-
-        if (4 != (rc = i2c_master_send(c,buffer,4)))
-                printk("tuner: i2c i/o error: rc == %d (should be 4)\n",rc);
-
-	if (t->type == TUNER_MICROTUNE_4042FI5) {
-		// FIXME - this may also work for other tuners
-		unsigned long timeout = jiffies + msecs_to_jiffies(1);
-		u8 status_byte = 0;
-
-		/* Wait until the PLL locks */
-		for (;;) {
-			if (time_after(jiffies,timeout))
-				return;
-			if (1 != (rc = i2c_master_recv(c,&status_byte,1))) {
-				dprintk("tuner: i2c i/o read error: rc == %d (should be 1)\n",rc);
-				break;
-			}
-			/* bit 6 is PLL locked indicator */
-			if (status_byte & 0x40)
-				break;
-			udelay(10);
-		}
-
-		/* Set the charge pump for optimized phase noise figure */
-		tun->config &= ~0x40;
-		buffer[0] = (div>>8) & 0x7f;
-		buffer[1] = div      & 0xff;
-		buffer[2] = tun->config;
-		buffer[3] = config;
-		dprintk("tuner: tv 0x%02x 0x%02x 0x%02x 0x%02x\n",
-			buffer[0],buffer[1],buffer[2],buffer[3]);
-
-		if (4 != (rc = i2c_master_send(c,buffer,4)))
-			dprintk("tuner: i2c i/o error: rc == %d (should be 4)\n",rc);
-	}
-}
-
-static void default_set_radio_freq(struct i2c_client *c, unsigned int freq)
-{
-	struct tunertype *tun;
-	struct tuner *t = i2c_get_clientdata(c);
-        unsigned char buffer[4];
-	unsigned div;
-	int rc;
-
-	tun=&tuners[t->type];
-	div = freq + (int)(16*10.7);
-	buffer[2] = tun->config;
-
-	switch (t->type) {
-	case TUNER_PHILIPS_FM1216ME_MK3:
-	case TUNER_PHILIPS_FM1236_MK3:
-		buffer[3] = 0x19;
-		break;
-	case TUNER_PHILIPS_FM1256_IH3:
-		div = (20 * freq)/16 + 333 * 2;
-	        buffer[2] = 0x80;
-		buffer[3] = 0x19;
-		break;
-	case TUNER_LG_PAL_FM:
-		buffer[3] = 0xa5;
-		break;
-	default:
-		buffer[3] = 0xa4;
-		break;
-	}
-        buffer[0] = (div>>8) & 0x7f;
-        buffer[1] = div      & 0xff;
-
-	dprintk("tuner: radio 0x%02x 0x%02x 0x%02x 0x%02x\n",
-		buffer[0],buffer[1],buffer[2],buffer[3]);
-
-        if (4 != (rc = i2c_master_send(c,buffer,4)))
-                printk("tuner: i2c i/o error: rc == %d (should be 4)\n",rc);
-}
-
-/* ---------------------------------------------------------------------- */
-
-// Set tuner frequency,  freq in Units of 62.5kHz = 1/16MHz
-static void set_tv_freq(struct i2c_client *c, unsigned int freq)
-{
-	struct tuner *t = i2c_get_clientdata(c);
-
-	if (t->type == UNSET) {
-		printk("tuner: tuner type not set\n");
-		return;
-	}
-	if (NULL == t->tv_freq) {
-		printk("tuner: Huh? tv_set is NULL?\n");
-		return;
-	}
-	if (freq < tv_range[0]*16 || freq > tv_range[1]*16) {
-		/* FIXME: better do that chip-specific, but
-		   right now we don't have that in the config
-		   struct and this way is still better than no
-		   check at all */
-		printk("tuner: TV freq (%d.%02d) out of range (%d-%d)\n",
-		       freq/16,freq%16*100/16,tv_range[0],tv_range[1]);
-		return;
-	}
-	t->tv_freq(c,freq);
-}
-
-static void set_radio_freq(struct i2c_client *c, unsigned int freq)
-{
-	struct tuner *t = i2c_get_clientdata(c);
-
-	if (t->type == UNSET) {
-		printk("tuner: tuner type not set\n");
-		return;
-	}
-	if (NULL == t->radio_freq) {
-		printk("tuner: no radio tuning for this one, sorry.\n");
-		return;
-	}
-	if (freq < radio_range[0]*16 || freq > radio_range[1]*16) {
-		printk("tuner: radio freq (%d.%02d) out of range (%d-%d)\n",
-		       freq/16,freq%16*100/16,
-		       radio_range[0],radio_range[1]);
-		return;
-	}
-	t->radio_freq(c,freq);
-}
-
-static void set_freq(struct i2c_client *c, unsigned long freq)
-{
-	struct tuner *t = i2c_get_clientdata(c);
-
-	switch (t->mode) {
-	case V4L2_TUNER_RADIO:
-		dprintk("tuner: radio freq set to %lu.%02lu\n",
-			freq/16,freq%16*100/16);
-		set_radio_freq(c,freq);
-		break;
-	case V4L2_TUNER_ANALOG_TV:
-	case V4L2_TUNER_DIGITAL_TV:
-		dprintk("tuner: tv freq set to %lu.%02lu\n",
-			freq/16,freq%16*100/16);
-		set_tv_freq(c, freq);
-		break;
-	}
-	t->freq = freq;
-}
-
-static void set_type(struct i2c_client *c, unsigned int type, char *source)
-{
-	struct tuner *t = i2c_get_clientdata(c);
-
-	if (t->type != UNSET && t->type != TUNER_ABSENT) {
-		if (t->type != type)
-			printk("tuner: type already set to %d, "
-			       "ignoring request for %d\n", t->type, type);
-		return;
-	}
-	if (type >= TUNERS)
-		return;
-
-	t->type = type;
-	printk("tuner: type set to %d (%s) by %s\n",
-	       t->type,tuners[t->type].name, source);
-	strlcpy(c->name, tuners[t->type].name, sizeof(c->name));
-
-	switch (t->type) {
-	case TUNER_MT2032:
-		microtune_init(c);
-		break;
-	default:
-		t->tv_freq    = default_set_tv_freq;
-		t->radio_freq = default_set_radio_freq;
-		break;
-	}
-}
-
-static char pal[] = "-";
-module_param_string(pal, pal, 0644, sizeof(pal));
-
-static int tuner_fixup_std(struct tuner *t)
-{
-	if ((t->std & V4L2_STD_PAL) == V4L2_STD_PAL) {
-		/* get more precise norm info from insmod option */
-		switch (pal[0]) {
-		case 'b':
-		case 'B':
-		case 'g':
-		case 'G':
-			dprintk("insmod fixup: PAL => PAL-BG\n");
-			t->std = V4L2_STD_PAL_BG;
-			break;
-		case 'i':
-		case 'I':
-			dprintk("insmod fixup: PAL => PAL-I\n");
-			t->std = V4L2_STD_PAL_I;
-			break;
-		case 'd':
-		case 'D':
-		case 'k':
-		case 'K':
-			dprintk("insmod fixup: PAL => PAL-DK\n");
-			t->std = V4L2_STD_PAL_DK;
-			break;
-		}
-	}
-	return 0;
-}
-
-/* ---------------------------------------------------------------------- */
-
-static int tuner_attach(struct i2c_adapter *adap, int addr, int kind)
-{
-	struct tuner *t;
-	struct i2c_client *client;
-
-	if (this_adap > 0)
-		return -1;
-	this_adap++;
-
-        client_template.adapter = adap;
-        client_template.addr = addr;
-
-        printk("tuner: chip found at addr 0x%x i2c-bus %s\n",
-	       addr<<1, adap->name);
-
-        if (NULL == (client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL)))
-                return -ENOMEM;
-        memcpy(client,&client_template,sizeof(struct i2c_client));
-        t = kmalloc(sizeof(struct tuner),GFP_KERNEL);
-        if (NULL == t) {
-                kfree(client);
-                return -ENOMEM;
-        }
-        memset(t,0,sizeof(struct tuner));
-	i2c_set_clientdata(client, t);
-	t->type       = UNSET;
-	t->radio_if2  = 10700*1000; // 10.7MHz - FM radio
-
-        i2c_attach_client(client);
-	if (type < TUNERS) {
-		set_type(client, type, "insmod option");
-		printk("tuner: The type=<n> insmod option will go away soon.\n");
-		printk("tuner: Please use the tuner=<n> option provided by\n");
-		printk("tuner: tv aard core driver (bttv, saa7134, ...) instead.\n");
-	}
-	return 0;
-}
-
-static int tuner_probe(struct i2c_adapter *adap)
-{
-	if (0 != addr) {
-		normal_i2c_range[0] = addr;
-		normal_i2c_range[1] = addr;
-	}
-	this_adap = 0;
-
-#ifdef I2C_CLASS_TV_ANALOG
-	if (adap->class & I2C_CLASS_TV_ANALOG)
-		return i2c_probe(adap, &addr_data, tuner_attach);
-#else
-	switch (adap->id) {
-	case I2C_ALGO_BIT | I2C_HW_SMBUS_VOODOO3:
-	case I2C_ALGO_BIT | I2C_HW_B_BT848:
-	case I2C_ALGO_BIT | I2C_HW_B_RIVA:
-	case I2C_ALGO_SAA7134:
-	case I2C_ALGO_SAA7146:
-		return i2c_probe(adap, &addr_data, tuner_attach);
-		break;
-	}
-#endif
-	return 0;
-}
-
-static int tuner_detach(struct i2c_client *client)
-{
-	struct tuner *t = i2c_get_clientdata(client);
-
-	i2c_detach_client(client);
-	kfree(t);
-	kfree(client);
-	return 0;
-}
-
-#define SWITCH_V4L2	if (!t->using_v4l2 && debug) \
-		          printk("tuner: switching to v4l2\n"); \
-	                  t->using_v4l2 = 1;
-#define CHECK_V4L2	if (t->using_v4l2) { if (debug) \
-			  printk("tuner: ignore v4l1 call\n"); \
-		          return 0; }
-
-static int
-tuner_command(struct i2c_client *client, unsigned int cmd, void *arg)
-{
-	struct tuner *t = i2c_get_clientdata(client);
-        unsigned int *iarg = (int*)arg;
-
-        switch (cmd) {
-
-	/* --- configuration --- */
-	case TUNER_SET_TYPE:
-		set_type(client,*iarg,client->adapter->name);
-		break;
-	case AUDC_SET_RADIO:
-		if (V4L2_TUNER_RADIO != t->mode) {
-			set_tv_freq(client,400 * 16);
-			t->mode = V4L2_TUNER_RADIO;
-		}
-		break;
-	case AUDC_CONFIG_PINNACLE:
-		switch (*iarg) {
-		case 2:
-			dprintk("tuner: pinnacle pal\n");
-			t->radio_if2 = 33300 * 1000;
-			break;
-		case 3:
-			dprintk("tuner: pinnacle ntsc\n");
-			t->radio_if2 = 41300 * 1000;
-			break;
-		}
-                break;
-
-	/* --- v4l ioctls --- */
-	/* take care: bttv does userspace copying, we'll get a
-	   kernel pointer here... */
-	case VIDIOCSCHAN:
-	{
-		static const v4l2_std_id map[] = {
-			[ VIDEO_MODE_PAL   ] = V4L2_STD_PAL,
-			[ VIDEO_MODE_NTSC  ] = V4L2_STD_NTSC_M,
-			[ VIDEO_MODE_SECAM ] = V4L2_STD_SECAM,
-			[ 4 /* bttv */     ] = V4L2_STD_PAL_M,
-			[ 5 /* bttv */     ] = V4L2_STD_PAL_N,
-			[ 6 /* bttv */     ] = V4L2_STD_NTSC_M_JP,
-		};
-		struct video_channel *vc = arg;
-
-		CHECK_V4L2;
-		t->mode = V4L2_TUNER_ANALOG_TV;
-		if (vc->norm < ARRAY_SIZE(map))
-			t->std = map[vc->norm];
-		tuner_fixup_std(t);
-		if (t->freq)
-			set_tv_freq(client,t->freq);
-		return 0;
-	}
-	case VIDIOCSFREQ:
-	{
-		unsigned long *v = arg;
-
-		CHECK_V4L2;
-		set_freq(client,*v);
-		return 0;
-	}
-	case VIDIOCGTUNER:
-	{
-		struct video_tuner *vt = arg;
-
-		CHECK_V4L2;
-		if (V4L2_TUNER_RADIO == t->mode)
-			vt->signal = tuner_signal(client);
-		return 0;
-	}
-	case VIDIOCGAUDIO:
-	{
-		struct video_audio *va = arg;
-
-		CHECK_V4L2;
-		if (V4L2_TUNER_RADIO == t->mode)
-			va->mode = (tuner_stereo(client) ? VIDEO_SOUND_STEREO : VIDEO_SOUND_MONO);
-		return 0;
-	}
-
-	case VIDIOC_S_STD:
-	{
-		v4l2_std_id *id = arg;
-
-		SWITCH_V4L2;
-		t->mode = V4L2_TUNER_ANALOG_TV;
-		t->std = *id;
-		tuner_fixup_std(t);
-		if (t->freq)
-			set_freq(client,t->freq);
-		break;
-	}
-	case VIDIOC_S_FREQUENCY:
-	{
-		struct v4l2_frequency *f = arg;
-
-		SWITCH_V4L2;
-		if (V4L2_TUNER_RADIO == f->type &&
-		    V4L2_TUNER_RADIO != t->mode)
-			set_tv_freq(client,400*16);
-		t->mode  = f->type;
-		t->freq  = f->frequency;
-		set_freq(client,t->freq);
-		break;
-	}
-	case VIDIOC_G_TUNER:
-	{
-		struct v4l2_tuner *tuner = arg;
-
-		SWITCH_V4L2;
-		if (V4L2_TUNER_RADIO == t->mode)
-			tuner->signal = tuner_signal(client);
-		break;
-	}
-	default:
-		/* nothing */
-		break;
-	}
-
-	return 0;
-}
-
-static int tuner_suspend(struct device * dev, u32 state, u32 level)
-{
-	dprintk("tuner: suspend\n");
-	/* FIXME: power down ??? */
-	return 0;
-}
-
-static int tuner_resume(struct device * dev, u32 level)
-{
-	struct i2c_client *c = container_of(dev, struct i2c_client, dev);
-	struct tuner *t = i2c_get_clientdata(c);
-
-	dprintk("tuner: resume\n");
-	if (t->freq)
-		set_freq(c,t->freq);
-	return 0;
-}
-
-/* ----------------------------------------------------------------------- */
-
-static struct i2c_driver driver = {
-	.owner          = THIS_MODULE,
-        .name           = "i2c TV tuner driver",
-        .id             = I2C_DRIVERID_TUNER,
-        .flags          = I2C_DF_NOTIFY,
-        .attach_adapter = tuner_probe,
-        .detach_client  = tuner_detach,
-        .command        = tuner_command,
-	.driver = {
-		.suspend = tuner_suspend,
-		.resume  = tuner_resume,
-	},
-};
-static struct i2c_client client_template =
-{
-	I2C_DEVNAME("(tuner unset)"),
-	.flags      = I2C_CLIENT_ALLOW_USE,
-        .driver     = &driver,
-};
-
-static int __init tuner_init_module(void)
-{
-	return i2c_add_driver(&driver);
-}
-
-static void __exit tuner_cleanup_module(void)
-{
-	i2c_del_driver(&driver);
-}
-
-module_init(tuner_init_module);
-module_exit(tuner_cleanup_module);
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff -Nru a/drivers/media/video/tveeprom.c b/drivers/media/video/tveeprom.c
--- a/drivers/media/video/tveeprom.c	2005-03-11 12:51:51 -08:00
+++ b/drivers/media/video/tveeprom.c	2005-03-11 12:51:51 -08:00
@@ -34,6 +34,7 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/types.h>
+#include <linux/videodev.h>
 #include <linux/i2c.h>
 
 #include <media/tuner.h>
diff -Nru a/drivers/media/video/videodev.c b/drivers/media/video/videodev.c
--- a/drivers/media/video/videodev.c	2005-03-11 12:51:41 -08:00
+++ b/drivers/media/video/videodev.c	2005-03-11 12:51:41 -08:00
@@ -46,15 +46,7 @@
 	return sprintf(buf,"%.*s\n",(int)sizeof(vfd->name),vfd->name);
 }
 
-static ssize_t show_dev(struct class_device *cd, char *buf)
-{
-	struct video_device *vfd = container_of(cd, struct video_device, class_dev);
-	dev_t dev = MKDEV(VIDEO_MAJOR, vfd->minor);
-	return print_dev_t(buf,dev);
-}
-
 static CLASS_DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
-static CLASS_DEVICE_ATTR(dev,  S_IRUGO, show_dev, NULL);
 
 struct video_device *video_device_alloc(void)
 {
@@ -347,12 +339,11 @@
 	if (vfd->dev)
 		vfd->class_dev.dev = vfd->dev;
 	vfd->class_dev.class       = &video_class;
+	vfd->class_dev.devt       = MKDEV(VIDEO_MAJOR, vfd->minor);
 	strlcpy(vfd->class_dev.class_id, vfd->devfs_name + 4, BUS_ID_SIZE);
 	class_device_register(&vfd->class_dev);
 	class_device_create_file(&vfd->class_dev,
 				 &class_device_attr_name);
-	class_device_create_file(&vfd->class_dev,
-				 &class_device_attr_dev);
 
 #if 1 /* needed until all drivers are fixed */
 	if (!vfd->release)
diff -Nru a/drivers/media/video/vpx3220.c b/drivers/media/video/vpx3220.c
--- a/drivers/media/video/vpx3220.c	2005-03-11 12:51:47 -08:00
+++ b/drivers/media/video/vpx3220.c	2005-03-11 12:51:47 -08:00
@@ -587,7 +587,6 @@
 	.force			= force
 };
 
-static int vpx3220_i2c_id = 0;
 static struct i2c_driver vpx3220_i2c_driver;
 
 static int
@@ -634,7 +633,6 @@
 	client->adapter = adapter;
 	client->driver = &vpx3220_i2c_driver;
 	client->flags = I2C_CLIENT_ALLOW_USE;
-	client->id = vpx3220_i2c_id++;
 
 	/* Check for manufacture ID and part number */
 	if (kind < 0) {
@@ -655,16 +653,16 @@
 		    vpx3220_read(client, 0x01);
 		switch (pn) {
 		case 0x4680:
-			snprintf(I2C_NAME(client), sizeof(I2C_NAME(client)) - 1,
-				 "vpx3220a[%d]", client->id);
+			strlcpy(I2C_NAME(client), "vpx3220a",
+				sizeof(I2C_NAME(client)));
 			break;
 		case 0x4260:
-			snprintf(I2C_NAME(client), sizeof(I2C_NAME(client)) - 1,
-				 "vpx3216b[%d]", client->id);
+			strlcpy(I2C_NAME(client), "vpx3216b",
+				sizeof(I2C_NAME(client)));
 			break;
 		case 0x4280:
-			snprintf(I2C_NAME(client), sizeof(I2C_NAME(client)) - 1,
-				 "vpx3214c[%d]", client->id);
+			strlcpy(I2C_NAME(client), "vpx3214c",
+				sizeof(I2C_NAME(client)));
 			break;
 		default:
 			dprintk(1,
@@ -675,9 +673,8 @@
 			return 0;
 		}
 	} else {
-		snprintf(I2C_NAME(client), sizeof(I2C_NAME(client)) - 1,
-			 "forced vpx32xx[%d]",
-		client->id);
+		strlcpy(I2C_NAME(client), "forced vpx32xx",
+			sizeof(I2C_NAME(client)));
 	}
 
 	decoder = kmalloc(sizeof(struct vpx3220), GFP_KERNEL);
diff -Nru a/drivers/media/video/zoran_driver.c b/drivers/media/video/zoran_driver.c
--- a/drivers/media/video/zoran_driver.c	2005-03-11 12:51:48 -08:00
+++ b/drivers/media/video/zoran_driver.c	2005-03-11 12:51:48 -08:00
@@ -2694,7 +2694,7 @@
 		strncpy(cap->card, ZR_DEVNAME(zr), sizeof(cap->card));
 		strncpy(cap->driver, "zoran", sizeof(cap->driver));
 		snprintf(cap->bus_info, sizeof(cap->bus_info), "PCI:%s",
-			 zr->pci_dev->slot_name);
+			 pci_name(zr->pci_dev));
 		cap->version =
 		    KERNEL_VERSION(MAJOR_VERSION, MINOR_VERSION,
 				   RELEASE_VERSION);
diff -Nru a/drivers/mmc/mmc_sysfs.c b/drivers/mmc/mmc_sysfs.c
--- a/drivers/mmc/mmc_sysfs.c	2005-03-11 12:51:47 -08:00
+++ b/drivers/mmc/mmc_sysfs.c	2005-03-11 12:51:47 -08:00
@@ -21,6 +21,41 @@
 #define dev_to_mmc_card(d)	container_of(d, struct mmc_card, dev)
 #define to_mmc_driver(d)	container_of(d, struct mmc_driver, drv)
 
+#define MMC_ATTR(name, fmt, args...)					\
+static ssize_t mmc_##name##_show (struct device *dev, char *buf)	\
+{									\
+	struct mmc_card *card = dev_to_mmc_card(dev);			\
+	return sprintf(buf, fmt, args);					\
+}
+
+MMC_ATTR(cid, "%08x%08x%08x%08x\n", card->raw_cid[0], card->raw_cid[1],
+	card->raw_cid[2], card->raw_cid[3]);
+MMC_ATTR(csd, "%08x%08x%08x%08x\n", card->raw_csd[0], card->raw_csd[1],
+	card->raw_csd[2], card->raw_csd[3]);
+MMC_ATTR(date, "%02d/%04d\n", card->cid.month, card->cid.year);
+MMC_ATTR(fwrev, "0x%x\n", card->cid.fwrev);
+MMC_ATTR(hwrev, "0x%x\n", card->cid.hwrev);
+MMC_ATTR(manfid, "0x%06x\n", card->cid.manfid);
+MMC_ATTR(name, "%s\n", card->cid.prod_name);
+MMC_ATTR(oemid, "0x%04x\n", card->cid.oemid);
+MMC_ATTR(serial, "0x%08x\n", card->cid.serial);
+
+#define MMC_ATTR_RO(name) __ATTR(name, S_IRUGO, mmc_##name##_show, NULL)
+
+static struct device_attribute mmc_dev_attrs[] = {
+	MMC_ATTR_RO(cid),
+	MMC_ATTR_RO(csd),
+	MMC_ATTR_RO(date),
+	MMC_ATTR_RO(fwrev),
+	MMC_ATTR_RO(hwrev),
+	MMC_ATTR_RO(manfid),
+	MMC_ATTR_RO(name),
+	MMC_ATTR_RO(oemid),
+	MMC_ATTR_RO(serial),
+	__ATTR_NULL
+};
+
+
 static void mmc_release_card(struct device *dev)
 {
 	struct mmc_card *card = dev_to_mmc_card(dev);
@@ -98,6 +133,7 @@
 
 static struct bus_type mmc_bus_type = {
 	.name		= "mmc",
+	.dev_attrs	= mmc_dev_attrs,
 	.match		= mmc_bus_match,
 	.hotplug	= mmc_bus_hotplug,
 	.suspend	= mmc_bus_suspend,
@@ -151,38 +187,6 @@
 EXPORT_SYMBOL(mmc_unregister_driver);
 
 
-#define MMC_ATTR(name, fmt, args...)					\
-static ssize_t mmc_dev_show_##name (struct device *dev, char *buf)	\
-{									\
-	struct mmc_card *card = dev_to_mmc_card(dev);			\
-	return sprintf(buf, fmt, args);					\
-}									\
-static DEVICE_ATTR(name, S_IRUGO, mmc_dev_show_##name, NULL)
-
-MMC_ATTR(cid, "%08x%08x%08x%08x\n", card->raw_cid[0], card->raw_cid[1],
-	card->raw_cid[2], card->raw_cid[3]);
-MMC_ATTR(csd, "%08x%08x%08x%08x\n", card->raw_csd[0], card->raw_csd[1],
-	card->raw_csd[2], card->raw_csd[3]);
-MMC_ATTR(date, "%02d/%04d\n", card->cid.month, card->cid.year);
-MMC_ATTR(fwrev, "0x%x\n", card->cid.fwrev);
-MMC_ATTR(hwrev, "0x%x\n", card->cid.hwrev);
-MMC_ATTR(manfid, "0x%06x\n", card->cid.manfid);
-MMC_ATTR(name, "%s\n", card->cid.prod_name);
-MMC_ATTR(oemid, "0x%04x\n", card->cid.oemid);
-MMC_ATTR(serial, "0x%08x\n", card->cid.serial);
-
-static struct device_attribute *mmc_dev_attributes[] = {
-	&dev_attr_cid,
-	&dev_attr_csd,
-	&dev_attr_date,
-	&dev_attr_fwrev,
-	&dev_attr_hwrev,
-	&dev_attr_manfid,
-	&dev_attr_name,
-	&dev_attr_oemid,
-	&dev_attr_serial,
-};
-
 /*
  * Internal function.  Initialise a MMC card structure.
  */
@@ -201,17 +205,10 @@
  */
 int mmc_register_card(struct mmc_card *card)
 {
-	int ret, i;
-
 	snprintf(card->dev.bus_id, sizeof(card->dev.bus_id),
 		 "%s:%04x", card->host->host_name, card->rca);
 
-	ret = device_add(&card->dev);
-	if (ret == 0)
-		for (i = 0; i < ARRAY_SIZE(mmc_dev_attributes); i++)
-			device_create_file(&card->dev, mmc_dev_attributes[i]);
-
-	return ret;
+	return device_add(&card->dev);
 }
 
 /*
diff -Nru a/drivers/mtd/devices/block2mtd.c b/drivers/mtd/devices/block2mtd.c
--- a/drivers/mtd/devices/block2mtd.c	2005-03-11 12:51:40 -08:00
+++ b/drivers/mtd/devices/block2mtd.c	2005-03-11 12:51:40 -08:00
@@ -59,7 +59,7 @@
 
 	end_index = ((isize - 1) >> PAGE_CACHE_SHIFT);
 
-	spin_lock_irq(&mapping->tree_lock);
+	read_lock_irq(&mapping->tree_lock);
 	for (i = 0; i < PAGE_READAHEAD; i++) {
 		pagei = index + i;
 		if (pagei > end_index) {
@@ -71,16 +71,16 @@
 			break;
 		if (page)
 			continue;
-		spin_unlock_irq(&mapping->tree_lock);
+		read_unlock_irq(&mapping->tree_lock);
 		page = page_cache_alloc_cold(mapping);
-		spin_lock_irq(&mapping->tree_lock);
+		read_lock_irq(&mapping->tree_lock);
 		if (!page)
 			break;
 		page->index = pagei;
 		list_add(&page->lru, &page_pool);
 		ret++;
 	}
-	spin_unlock_irq(&mapping->tree_lock);
+	read_unlock_irq(&mapping->tree_lock);
 	if (ret)
 		read_cache_pages(mapping, &page_pool, filler, NULL);
 }
diff -Nru a/drivers/mtd/maps/Kconfig b/drivers/mtd/maps/Kconfig
--- a/drivers/mtd/maps/Kconfig	2005-03-11 12:51:51 -08:00
+++ b/drivers/mtd/maps/Kconfig	2005-03-11 12:51:51 -08:00
@@ -159,7 +159,7 @@
 
 config MTD_SCx200_DOCFLASH
 	tristate "Flash device mapped with DOCCS on NatSemi SCx200"
-	depends on X86 && MTD_CFI && MTD_PARTITIONS
+	depends on SCx200 && MTD_CFI && MTD_PARTITIONS
 	help
 	  Enable support for a flash chip mapped using the DOCCS signal on a
 	  National Semiconductor SCx200 processor.
diff -Nru a/drivers/mtd/maps/scx200_docflash.c b/drivers/mtd/maps/scx200_docflash.c
--- a/drivers/mtd/maps/scx200_docflash.c	2005-03-11 12:51:47 -08:00
+++ b/drivers/mtd/maps/scx200_docflash.c	2005-03-11 12:51:47 -08:00
@@ -92,17 +92,16 @@
 				      PCI_DEVICE_ID_NS_SCx200_BRIDGE,
 				      NULL)) == NULL)
 		return -ENODEV;
-	
-	if (!scx200_cb_probe(SCx200_CB_BASE)) {
-		printk(KERN_WARNING NAME ": no configuration block found\n");
+
+	/* check that we have found the configuration block */
+	if (!scx200_cb_present())
 		return -ENODEV;
-	}
 
 	if (probe) {
 		/* Try to use the present flash mapping if any */
 		pci_read_config_dword(bridge, SCx200_DOCCS_BASE, &base);
 		pci_read_config_dword(bridge, SCx200_DOCCS_CTRL, &ctrl);
-		pmr = inl(SCx200_CB_BASE + SCx200_PMR);
+		pmr = inl(scx200_cb_base + SCx200_PMR);
 
 		if (base == 0
 		    || (ctrl & 0x07000000) != 0x07000000
@@ -155,14 +154,14 @@
 		
 		pci_write_config_dword(bridge, SCx200_DOCCS_BASE, docmem.start);
 		pci_write_config_dword(bridge, SCx200_DOCCS_CTRL, ctrl);
-		pmr = inl(SCx200_CB_BASE + SCx200_PMR);
+		pmr = inl(scx200_cb_base + SCx200_PMR);
 		
 		if (width == 8) {
 			pmr &= ~(1<<6);
 		} else {
 			pmr |= (1<<6);
 		}
-		outl(pmr, SCx200_CB_BASE + SCx200_PMR);
+		outl(pmr, scx200_cb_base + SCx200_PMR);
 	}
 	
        	printk(KERN_INFO NAME ": DOCCS mapped at 0x%lx-0x%lx, width %d\n", 
diff -Nru a/drivers/net/3c503.c b/drivers/net/3c503.c
--- a/drivers/net/3c503.c	2005-03-11 12:51:47 -08:00
+++ b/drivers/net/3c503.c	2005-03-11 12:51:47 -08:00
@@ -103,8 +103,15 @@
 	return -ENXIO;
 
     for (addr = addrs; *addr; addr++) {
-	unsigned base_bits = isa_readb(*addr);
-	int i = ffs(base_bits) - 1;
+	void __iomem *p = ioremap(*addr, 1);
+	unsigned base_bits;
+	int i;
+
+	if (!p)
+		continue;
+	base_bits = readb(p);
+	iounmap(p);
+	i = ffs(base_bits) - 1;
 	if (i == -1 || base_bits != (1 << i))
 	    continue;
 	if (el2_probe1(dev, netcard_portlist[i]) == 0)
@@ -145,6 +152,8 @@
 {
 	/* NB: el2_close() handles free_irq */
 	release_region(dev->base_addr, EL2_IO_EXTENT);
+	if (ei_status.mem)
+		iounmap(ei_status.mem);
 }
 
 #ifndef MODULE
@@ -262,42 +271,46 @@
     if ((membase_reg & 0xf0) == 0) {
 	dev->mem_start = 0;
 	ei_status.name = "3c503-PIO";
+	ei_status.mem = NULL;
     } else {
 	dev->mem_start = ((membase_reg & 0xc0) ? 0xD8000 : 0xC8000) +
 	    ((membase_reg & 0xA0) ? 0x4000 : 0);
-
 #define EL2_MEMSIZE (EL2_MB1_STOP_PG - EL2_MB1_START_PG)*256
+	ei_status.mem = ioremap(dev->mem_start, EL2_MEMSIZE);
+
 #ifdef EL2MEMTEST
 	/* This has never found an error, but someone might care.
 	   Note that it only tests the 2nd 8kB on 16kB 3c503/16
 	   cards between card addr. 0x2000 and 0x3fff. */
 	{			/* Check the card's memory. */
-	    unsigned long mem_base = dev->mem_start;
+	    void __iomem *mem_base = ei_status.mem;
 	    unsigned int test_val = 0xbbadf00d;
-	    isa_writel(0xba5eba5e, mem_base);
+	    writel(0xba5eba5e, mem_base);
 	    for (i = sizeof(test_val); i < EL2_MEMSIZE; i+=sizeof(test_val)) {
-		isa_writel(test_val, mem_base + i);
-		if (isa_readl(mem_base) != 0xba5eba5e
-		    || isa_readl(mem_base + i) != test_val) {
+		writel(test_val, mem_base + i);
+		if (readl(mem_base) != 0xba5eba5e
+		    || readl(mem_base + i) != test_val) {
 		    printk("3c503: memory failure or memory address conflict.\n");
 		    dev->mem_start = 0;
 		    ei_status.name = "3c503-PIO";
+		    iounmap(mem_base);
+		    ei_status.mem = NULL;
 		    break;
 		}
 		test_val += 0x55555555;
-		isa_writel(0, mem_base + i);
+		writel(0, mem_base + i);
 	    }
 	}
 #endif  /* EL2MEMTEST */
 
 	if (dev->mem_start)
-		dev->mem_end = ei_status.rmem_end = dev->mem_start + EL2_MEMSIZE;
+		dev->mem_end = dev->mem_start + EL2_MEMSIZE;
 
 	if (wordlength) {	/* No Tx pages to skip over to get to Rx */
-		ei_status.rmem_start = dev->mem_start;
+		ei_status.priv = 0;
 		ei_status.name = "3c503/16";
 	} else {
-		ei_status.rmem_start = TX_PAGES*256 + dev->mem_start;
+		ei_status.priv = TX_PAGES * 256;
 		ei_status.name = "3c503";
 	}
     }
@@ -471,16 +484,16 @@
     unsigned short int *wrd;
     int boguscount;		/* timeout counter */
     unsigned short word;	/* temporary for better machine code */
+    void __iomem *base = ei_status.mem;
 
     if (ei_status.word16)      /* Tx packets go into bank 0 on EL2/16 card */
 	outb(EGACFR_RSEL|EGACFR_TCM, E33G_GACFR);
     else
 	outb(EGACFR_NORM, E33G_GACFR);
 
-    if (dev->mem_start) {	/* Shared memory transfer */
-	unsigned long dest_addr = dev->mem_start +
-	    ((start_page - ei_status.tx_start_page) << 8);
-	isa_memcpy_toio(dest_addr, buf, count);
+    if (base) {	/* Shared memory transfer */
+	memcpy_toio(base + ((start_page - ei_status.tx_start_page) << 8),
+			buf, count);
 	outb(EGACFR_NORM, E33G_GACFR);	/* Back to bank1 in case on bank0 */
 	return;
     }
@@ -541,11 +554,12 @@
 el2_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
 {
     int boguscount;
-    unsigned long hdr_start = dev->mem_start + ((ring_page - EL2_MB1_START_PG)<<8);
+    void __iomem *base = ei_status.mem;
     unsigned short word;
 
-    if (dev->mem_start) {       /* Use the shared memory. */
-	isa_memcpy_fromio(hdr, hdr_start, sizeof(struct e8390_pkt_hdr));
+    if (base) {       /* Use the shared memory. */
+	void __iomem *hdr_start = base + ((ring_page - EL2_MB1_START_PG)<<8);
+	memcpy_fromio(hdr, hdr_start, sizeof(struct e8390_pkt_hdr));
 	hdr->count = le16_to_cpu(hdr->count);
 	return;
     }
@@ -581,23 +595,22 @@
 el2_block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset)
 {
     int boguscount = 0;
+    void __iomem *base = ei_status.mem;
     unsigned short int *buf;
     unsigned short word;
 
-    int end_of_ring = ei_status.rmem_end;
-
     /* Maybe enable shared memory just be to be safe... nahh.*/
-    if (dev->mem_start) {	/* Use the shared memory. */
+    if (base) {	/* Use the shared memory. */
 	ring_offset -= (EL2_MB1_START_PG<<8);
-	if (dev->mem_start + ring_offset + count > end_of_ring) {
+	if (ring_offset + count > EL2_MEMSIZE) {
 	    /* We must wrap the input move. */
-	    int semi_count = end_of_ring - (dev->mem_start + ring_offset);
-	    isa_memcpy_fromio(skb->data, dev->mem_start + ring_offset, semi_count);
+	    int semi_count = EL2_MEMSIZE - ring_offset;
+	    memcpy_fromio(skb->data, base + ring_offset, semi_count);
 	    count -= semi_count;
-	    isa_memcpy_fromio(skb->data + semi_count, ei_status.rmem_start, count);
+	    memcpy_fromio(skb->data + semi_count, base + ei_status.priv, count);
 	} else {
 		/* Packet is in one chunk -- we can copy + cksum. */
-		isa_eth_io_copy_and_sum(skb, dev->mem_start + ring_offset, count, 0);
+		eth_io_copy_and_sum(skb, base + ring_offset, count, 0);
 	}
 	return;
     }
diff -Nru a/drivers/net/3c509.c b/drivers/net/3c509.c
--- a/drivers/net/3c509.c	2005-03-11 12:51:52 -08:00
+++ b/drivers/net/3c509.c	2005-03-11 12:51:52 -08:00
@@ -214,7 +214,7 @@
 #endif
 
 #ifdef CONFIG_EISA
-struct eisa_device_id el3_eisa_ids[] = {
+static struct eisa_device_id el3_eisa_ids[] = {
 		{ "TCM5092" },
 		{ "TCM5093" },
 		{ "" }
@@ -222,7 +222,7 @@
 
 static int el3_eisa_probe (struct device *device);
 
-struct eisa_driver el3_eisa_driver = {
+static struct eisa_driver el3_eisa_driver = {
 		.id_table = el3_eisa_ids,
 		.driver   = {
 				.name    = "3c509",
diff -Nru a/drivers/net/3c515.c b/drivers/net/3c515.c
--- a/drivers/net/3c515.c	2005-03-11 12:51:41 -08:00
+++ b/drivers/net/3c515.c	2005-03-11 12:51:41 -08:00
@@ -86,6 +86,7 @@
 MODULE_AUTHOR("Donald Becker <becker@scyld.com>");
 MODULE_DESCRIPTION("3Com 3c515 Corkscrew driver");
 MODULE_LICENSE("GPL");
+MODULE_VERSION(DRV_VERSION);
 
 /* "Knobs" for adjusting internal parameters. */
 /* Put out somewhat more debugging messages. (0 - no msg, 1 minimal msgs). */
@@ -472,7 +473,7 @@
 
 static void cleanup_card(struct net_device *dev)
 {
-	struct corkscrew_private *vp = (struct corkscrew_private *) dev->priv;
+	struct corkscrew_private *vp = netdev_priv(dev);
 	list_del_init(&vp->list);
 	if (dev->dma)
 		free_dma(dev->dma);
@@ -570,7 +571,7 @@
 static void corkscrew_setup(struct net_device *dev, int ioaddr,
 			    struct pnp_dev *idev, int card_number)
 {
-	struct corkscrew_private *vp = (struct corkscrew_private *) dev->priv;
+	struct corkscrew_private *vp = netdev_priv(dev);
 	unsigned int eeprom[0x40], checksum = 0;	/* EEPROM contents */
 	int i;
 	int irq;
@@ -696,8 +697,7 @@
 static int corkscrew_open(struct net_device *dev)
 {
 	int ioaddr = dev->base_addr;
-	struct corkscrew_private *vp =
-	    (struct corkscrew_private *) dev->priv;
+	struct corkscrew_private *vp = netdev_priv(dev);
 	union wn3_config config;
 	int i;
 
@@ -862,7 +862,7 @@
 {
 #ifdef AUTOMEDIA
 	struct net_device *dev = (struct net_device *) data;
-	struct corkscrew_private *vp = (struct corkscrew_private *) dev->priv;
+	struct corkscrew_private *vp = netdev_priv(dev);
 	int ioaddr = dev->base_addr;
 	unsigned long flags;
 	int ok = 0;
@@ -954,8 +954,7 @@
 static void corkscrew_timeout(struct net_device *dev)
 {
 	int i;
-	struct corkscrew_private *vp =
-	    (struct corkscrew_private *) dev->priv;
+	struct corkscrew_private *vp = netdev_priv(dev);
 	int ioaddr = dev->base_addr;
 
 	printk(KERN_WARNING
@@ -994,8 +993,7 @@
 static int corkscrew_start_xmit(struct sk_buff *skb,
 				struct net_device *dev)
 {
-	struct corkscrew_private *vp =
-	    (struct corkscrew_private *) dev->priv;
+	struct corkscrew_private *vp = netdev_priv(dev);
 	int ioaddr = dev->base_addr;
 
 	/* Block a timer-based transmit from overlapping. */
@@ -1123,14 +1121,13 @@
 {
 	/* Use the now-standard shared IRQ implementation. */
 	struct net_device *dev = dev_id;
-	struct corkscrew_private *lp;
+	struct corkscrew_private *lp = netdev_priv(dev);
 	int ioaddr, status;
 	int latency;
 	int i = max_interrupt_work;
 
 	ioaddr = dev->base_addr;
 	latency = inb(ioaddr + Timer);
-	lp = (struct corkscrew_private *) dev->priv;
 
 	spin_lock(&lp->lock);
 	
@@ -1262,7 +1259,7 @@
 
 static int corkscrew_rx(struct net_device *dev)
 {
-	struct corkscrew_private *vp = (struct corkscrew_private *) dev->priv;
+	struct corkscrew_private *vp = netdev_priv(dev);
 	int ioaddr = dev->base_addr;
 	int i;
 	short rx_status;
@@ -1329,8 +1326,7 @@
 
 static int boomerang_rx(struct net_device *dev)
 {
-	struct corkscrew_private *vp =
-	    (struct corkscrew_private *) dev->priv;
+	struct corkscrew_private *vp = netdev_priv(dev);
 	int entry = vp->cur_rx % RX_RING_SIZE;
 	int ioaddr = dev->base_addr;
 	int rx_status;
@@ -1420,8 +1416,7 @@
 
 static int corkscrew_close(struct net_device *dev)
 {
-	struct corkscrew_private *vp =
-	    (struct corkscrew_private *) dev->priv;
+	struct corkscrew_private *vp = netdev_priv(dev);
 	int ioaddr = dev->base_addr;
 	int i;
 
@@ -1476,7 +1471,7 @@
 
 static struct net_device_stats *corkscrew_get_stats(struct net_device *dev)
 {
-	struct corkscrew_private *vp = (struct corkscrew_private *) dev->priv;
+	struct corkscrew_private *vp = netdev_priv(dev);
 	unsigned long flags;
 
 	if (netif_running(dev)) {
@@ -1496,8 +1491,7 @@
 	*/
 static void update_stats(int ioaddr, struct net_device *dev)
 {
-	struct corkscrew_private *vp =
-	    (struct corkscrew_private *) dev->priv;
+	struct corkscrew_private *vp = netdev_priv(dev);
 
 	/* Unlike the 3c5x9 we need not turn off stats updates while reading. */
 	/* Switch to the stats window, and read everything. */
diff -Nru a/drivers/net/3c527.c b/drivers/net/3c527.c
--- a/drivers/net/3c527.c	2005-03-11 12:51:47 -08:00
+++ b/drivers/net/3c527.c	2005-03-11 12:51:47 -08:00
@@ -197,7 +197,7 @@
 	char		*name;
 };
 
-const struct mca_adapters_t mc32_adapters[] = {
+static const struct mca_adapters_t mc32_adapters[] = {
 	{ 0x0041, "3COM EtherLink MC/32" },
 	{ 0x8EF5, "IBM High Performance Lan Adapter" },
 	{ 0x0000, NULL }
diff -Nru a/drivers/net/3c59x.c b/drivers/net/3c59x.c
--- a/drivers/net/3c59x.c	2005-03-11 12:51:40 -08:00
+++ b/drivers/net/3c59x.c	2005-03-11 12:51:40 -08:00
@@ -964,7 +964,7 @@
 
 #ifdef CONFIG_PM
 
-static int vortex_suspend (struct pci_dev *pdev, u32 state)
+static int vortex_suspend (struct pci_dev *pdev, pm_message_t state)
 {
 	struct net_device *dev = pci_get_drvdata(pdev);
 
diff -Nru a/drivers/net/8139too.c b/drivers/net/8139too.c
--- a/drivers/net/8139too.c	2005-03-11 12:51:40 -08:00
+++ b/drivers/net/8139too.c	2005-03-11 12:51:40 -08:00
@@ -389,8 +389,14 @@
 
 /* Bits in TxConfig. */
 enum tx_config_bits {
-	TxIFG1 = (1 << 25),	/* Interframe Gap Time */
-	TxIFG0 = (1 << 24),	/* Enabling these bits violates IEEE 802.3 */
+
+        /* Interframe Gap Time. Only TxIFG96 doesn't violate IEEE 802.3 */
+        TxIFGShift = 24,
+        TxIFG84 = (0 << TxIFGShift),    /* 8.4us / 840ns (10 / 100Mbps) */
+        TxIFG88 = (1 << TxIFGShift),    /* 8.8us / 880ns (10 / 100Mbps) */
+        TxIFG92 = (2 << TxIFGShift),    /* 9.2us / 920ns (10 / 100Mbps) */
+        TxIFG96 = (3 << TxIFGShift),    /* 9.6us / 960ns (10 / 100Mbps) */
+
 	TxLoopBack = (1 << 18) | (1 << 17), /* enable loopback test mode */
 	TxCRC = (1 << 16),	/* DISABLE appending CRC to end of Tx packets */
 	TxClearAbt = (1 << 0),	/* Clear abort (WO) */
@@ -723,17 +729,14 @@
 #endif
 
 static const unsigned int rtl8139_tx_config =
-	(TX_DMA_BURST << TxDMAShift) | (TX_RETRY << TxRetryShift);
+	TxIFG96 | (TX_DMA_BURST << TxDMAShift) | (TX_RETRY << TxRetryShift);
 
 static void __rtl8139_cleanup_dev (struct net_device *dev)
 {
-	struct rtl8139_private *tp;
+	struct rtl8139_private *tp = netdev_priv(dev);
 	struct pci_dev *pdev;
 
 	assert (dev != NULL);
-	assert (dev->priv != NULL);
-
-	tp = dev->priv;
 	assert (tp->pci_dev != NULL);
 	pdev = tp->pci_dev;
 
@@ -746,7 +749,7 @@
 	pci_release_regions (pdev);
 
 	free_netdev(dev);
-
+	pci_disable_device(pdev);
 	pci_set_drvdata (pdev, NULL);
 }
 
@@ -785,7 +788,7 @@
 
 	*dev_out = NULL;
 
-	/* dev and dev->priv zeroed in alloc_etherdev */
+	/* dev and priv zeroed in alloc_etherdev */
 	dev = alloc_etherdev (sizeof (*tp));
 	if (dev == NULL) {
 		printk (KERN_ERR PFX "%s: Unable to alloc new net device\n", pci_name(pdev));
@@ -794,7 +797,7 @@
 	SET_MODULE_OWNER(dev);
 	SET_NETDEV_DEV(dev, &pdev->dev);
 
-	tp = dev->priv;
+	tp = netdev_priv(dev);
 	tp->pci_dev = pdev;
 
 	/* enable device (incl. PCI PM wakeup and hotplug setup) */
@@ -976,8 +979,8 @@
 		return i;
 
 	assert (dev != NULL);
-	tp = dev->priv;
-	assert (tp != NULL);
+	tp = netdev_priv(dev);
+
 	ioaddr = tp->mmio_addr;
 	assert (ioaddr != NULL);
 
@@ -1010,8 +1013,8 @@
 
 	dev->irq = pdev->irq;
 
-	/* dev->priv/tp zeroed and aligned in alloc_etherdev */
-	tp = dev->priv;
+	/* tp zeroed and aligned in alloc_etherdev */
+	tp = netdev_priv(dev);
 
 	/* note: tp->chipset set in rtl8139_init_board */
 	tp->drv_flags = board_info[ent->driver_data].hw_flags;
@@ -1116,11 +1119,8 @@
 static void __devexit rtl8139_remove_one (struct pci_dev *pdev)
 {
 	struct net_device *dev = pci_get_drvdata (pdev);
-	struct rtl8139_private *np;
 
 	assert (dev != NULL);
-	np = dev->priv;
-	assert (np != NULL);
 
 	unregister_netdev (dev);
 
@@ -1234,7 +1234,7 @@
 
 static int mdio_read (struct net_device *dev, int phy_id, int location)
 {
-	struct rtl8139_private *tp = dev->priv;
+	struct rtl8139_private *tp = netdev_priv(dev);
 	int retval = 0;
 #ifdef CONFIG_8139TOO_8129
 	void *mdio_addr = tp->mmio_addr + Config4;
@@ -1276,7 +1276,7 @@
 static void mdio_write (struct net_device *dev, int phy_id, int location,
 			int value)
 {
-	struct rtl8139_private *tp = dev->priv;
+	struct rtl8139_private *tp = netdev_priv(dev);
 #ifdef CONFIG_8139TOO_8129
 	void *mdio_addr = tp->mmio_addr + Config4;
 	int mii_cmd = (0x5002 << 16) | (phy_id << 23) | (location << 18) | value;
@@ -1319,7 +1319,7 @@
 
 static int rtl8139_open (struct net_device *dev)
 {
-	struct rtl8139_private *tp = dev->priv;
+	struct rtl8139_private *tp = netdev_priv(dev);
 	int retval;
 	void *ioaddr = tp->mmio_addr;
 
@@ -1367,7 +1367,7 @@
 
 static void rtl_check_media (struct net_device *dev, unsigned int init_media)
 {
-	struct rtl8139_private *tp = dev->priv;
+	struct rtl8139_private *tp = netdev_priv(dev);
 
 	if (tp->phys[0] >= 0) {
 		mii_check_media(&tp->mii, netif_msg_link(tp), init_media);
@@ -1377,7 +1377,7 @@
 /* Start the hardware at open or resume. */
 static void rtl8139_hw_start (struct net_device *dev)
 {
-	struct rtl8139_private *tp = dev->priv;
+	struct rtl8139_private *tp = netdev_priv(dev);
 	void *ioaddr = tp->mmio_addr;
 	u32 i;
 	u8 tmp;
@@ -1399,8 +1399,6 @@
 
 	tp->rx_config = rtl8139_rx_config | AcceptBroadcast | AcceptMyPhys;
 	RTL_W32 (RxConfig, tp->rx_config);
-
-	/* Check this value: the documentation for IFG contradicts ifself. */
 	RTL_W32 (TxConfig, rtl8139_tx_config);
 
 	tp->cur_rx = 0;
@@ -1446,7 +1444,7 @@
 /* Initialize the Rx and Tx rings, along with various 'dev' bits. */
 static void rtl8139_init_ring (struct net_device *dev)
 {
-	struct rtl8139_private *tp = dev->priv;
+	struct rtl8139_private *tp = netdev_priv(dev);
 	int i;
 
 	tp->cur_rx = 0;
@@ -1613,7 +1611,7 @@
 static int rtl8139_thread (void *data)
 {
 	struct net_device *dev = data;
-	struct rtl8139_private *tp = dev->priv;
+	struct rtl8139_private *tp = netdev_priv(dev);
 	unsigned long timeout;
 
 	daemonize("%s", dev->name);
@@ -1645,7 +1643,7 @@
 
 static void rtl8139_start_thread(struct net_device *dev)
 {
-	struct rtl8139_private *tp = dev->priv;
+	struct rtl8139_private *tp = netdev_priv(dev);
 
 	tp->thr_pid = -1;
 	tp->twistie = 0;
@@ -1673,7 +1671,7 @@
 
 static void rtl8139_tx_timeout (struct net_device *dev)
 {
-	struct rtl8139_private *tp = dev->priv;
+	struct rtl8139_private *tp = netdev_priv(dev);
 	void *ioaddr = tp->mmio_addr;
 	int i;
 	u8 tmp8;
@@ -1718,7 +1716,7 @@
 
 static int rtl8139_start_xmit (struct sk_buff *skb, struct net_device *dev)
 {
-	struct rtl8139_private *tp = dev->priv;
+	struct rtl8139_private *tp = netdev_priv(dev);
 	void *ioaddr = tp->mmio_addr;
 	unsigned int entry;
 	unsigned int len = skb->len;
@@ -1766,7 +1764,6 @@
 	unsigned long dirty_tx, tx_left;
 
 	assert (dev != NULL);
-	assert (tp != NULL);
 	assert (ioaddr != NULL);
 
 	dirty_tx = tp->dirty_tx;
@@ -2125,7 +2122,7 @@
 
 static int rtl8139_poll(struct net_device *dev, int *budget)
 {
-	struct rtl8139_private *tp = dev->priv;
+	struct rtl8139_private *tp = netdev_priv(dev);
 	void *ioaddr = tp->mmio_addr;
 	int orig_budget = min(*budget, dev->quota);
 	int done = 1;
@@ -2163,7 +2160,7 @@
 			       struct pt_regs *regs)
 {
 	struct net_device *dev = (struct net_device *) dev_instance;
-	struct rtl8139_private *tp = dev->priv;
+	struct rtl8139_private *tp = netdev_priv(dev);
 	void *ioaddr = tp->mmio_addr;
 	u16 status, ackstat;
 	int link_changed = 0; /* avoid bogus "uninit" warning */
@@ -2239,7 +2236,7 @@
 
 static int rtl8139_close (struct net_device *dev)
 {
-	struct rtl8139_private *tp = dev->priv;
+	struct rtl8139_private *tp = netdev_priv(dev);
 	void *ioaddr = tp->mmio_addr;
 	int ret = 0;
 	unsigned long flags;
@@ -2302,7 +2299,7 @@
    other threads or interrupts aren't messing with the 8139.  */
 static void rtl8139_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
 {
-	struct rtl8139_private *np = dev->priv;
+	struct rtl8139_private *np = netdev_priv(dev);
 	void *ioaddr = np->mmio_addr;
 
 	spin_lock_irq(&np->lock);
@@ -2336,7 +2333,7 @@
    aren't messing with the 8139.  */
 static int rtl8139_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
 {
-	struct rtl8139_private *np = dev->priv;
+	struct rtl8139_private *np = netdev_priv(dev);
 	void *ioaddr = np->mmio_addr;
 	u32 support;
 	u8 cfg3, cfg5;
@@ -2376,7 +2373,7 @@
 
 static void rtl8139_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
 {
-	struct rtl8139_private *np = dev->priv;
+	struct rtl8139_private *np = netdev_priv(dev);
 	strcpy(info->driver, DRV_NAME);
 	strcpy(info->version, DRV_VERSION);
 	strcpy(info->bus_info, pci_name(np->pci_dev));
@@ -2385,7 +2382,7 @@
 
 static int rtl8139_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
 {
-	struct rtl8139_private *np = dev->priv;
+	struct rtl8139_private *np = netdev_priv(dev);
 	spin_lock_irq(&np->lock);
 	mii_ethtool_gset(&np->mii, cmd);
 	spin_unlock_irq(&np->lock);
@@ -2394,7 +2391,7 @@
 
 static int rtl8139_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
 {
-	struct rtl8139_private *np = dev->priv;
+	struct rtl8139_private *np = netdev_priv(dev);
 	int rc;
 	spin_lock_irq(&np->lock);
 	rc = mii_ethtool_sset(&np->mii, cmd);
@@ -2404,25 +2401,25 @@
 
 static int rtl8139_nway_reset(struct net_device *dev)
 {
-	struct rtl8139_private *np = dev->priv;
+	struct rtl8139_private *np = netdev_priv(dev);
 	return mii_nway_restart(&np->mii);
 }
 
 static u32 rtl8139_get_link(struct net_device *dev)
 {
-	struct rtl8139_private *np = dev->priv;
+	struct rtl8139_private *np = netdev_priv(dev);
 	return mii_link_ok(&np->mii);
 }
 
 static u32 rtl8139_get_msglevel(struct net_device *dev)
 {
-	struct rtl8139_private *np = dev->priv;
+	struct rtl8139_private *np = netdev_priv(dev);
 	return np->msg_enable;
 }
 
 static void rtl8139_set_msglevel(struct net_device *dev, u32 datum)
 {
-	struct rtl8139_private *np = dev->priv;
+	struct rtl8139_private *np = netdev_priv(dev);
 	np->msg_enable = datum;
 }
 
@@ -2433,13 +2430,13 @@
 #else
 static int rtl8139_get_regs_len(struct net_device *dev)
 {
-	struct rtl8139_private *np = dev->priv;
+	struct rtl8139_private *np = netdev_priv(dev);
 	return np->regs_len;
 }
 
 static void rtl8139_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *regbuf)
 {
-	struct rtl8139_private *np = dev->priv;
+	struct rtl8139_private *np = netdev_priv(dev);
 
 	regs->version = RTL_REGS_VER;
 
@@ -2456,7 +2453,7 @@
 
 static void rtl8139_get_ethtool_stats(struct net_device *dev, struct ethtool_stats *stats, u64 *data)
 {
-	struct rtl8139_private *np = dev->priv;
+	struct rtl8139_private *np = netdev_priv(dev);
 
 	data[0] = np->xstats.early_rx;
 	data[1] = np->xstats.tx_buf_mapped;
@@ -2488,7 +2485,7 @@
 
 static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 {
-	struct rtl8139_private *np = dev->priv;
+	struct rtl8139_private *np = netdev_priv(dev);
 	int rc;
 
 	if (!netif_running(dev))
@@ -2504,7 +2501,7 @@
 
 static struct net_device_stats *rtl8139_get_stats (struct net_device *dev)
 {
-	struct rtl8139_private *tp = dev->priv;
+	struct rtl8139_private *tp = netdev_priv(dev);
 	void *ioaddr = tp->mmio_addr;
 	unsigned long flags;
 
@@ -2523,7 +2520,7 @@
 
 static void __set_rx_mode (struct net_device *dev)
 {
-	struct rtl8139_private *tp = dev->priv;
+	struct rtl8139_private *tp = netdev_priv(dev);
 	void *ioaddr = tp->mmio_addr;
 	u32 mc_filter[2];	/* Multicast hash filter */
 	int i, rx_mode;
@@ -2572,7 +2569,7 @@
 static void rtl8139_set_rx_mode (struct net_device *dev)
 {
 	unsigned long flags;
-	struct rtl8139_private *tp = dev->priv;
+	struct rtl8139_private *tp = netdev_priv(dev);
 
 	spin_lock_irqsave (&tp->lock, flags);
 	__set_rx_mode(dev);
@@ -2581,10 +2578,10 @@
 
 #ifdef CONFIG_PM
 
-static int rtl8139_suspend (struct pci_dev *pdev, u32 state)
+static int rtl8139_suspend (struct pci_dev *pdev, pm_message_t state)
 {
 	struct net_device *dev = pci_get_drvdata (pdev);
-	struct rtl8139_private *tp = dev->priv;
+	struct rtl8139_private *tp = netdev_priv(dev);
 	void *ioaddr = tp->mmio_addr;
 	unsigned long flags;
 
diff -Nru a/drivers/net/Kconfig b/drivers/net/Kconfig
--- a/drivers/net/Kconfig	2005-03-11 12:51:51 -08:00
+++ b/drivers/net/Kconfig	2005-03-11 12:51:51 -08:00
@@ -47,16 +47,13 @@
 	---help---
 	  Say 'Y' or 'M' if you wish to be able to 'bond' multiple Ethernet
 	  Channels together. This is called 'Etherchannel' by Cisco,
-	  'Trunking' by Sun, and 'Bonding' in Linux.
+	  'Trunking' by Sun, 802.3ad by the IEEE, and 'Bonding' in Linux.
 
-	  If you have two Ethernet connections to some other computer, you can
-	  make them behave like one double speed connection using this driver.
-	  Naturally, this has to be supported at the other end as well, either
-	  with a similar Bonding Linux driver, a Cisco 5500 switch or a
-	  SunTrunking SunSoft driver.
+	  The driver supports multiple bonding modes to allow for both high
+	  perfomance and high availability operation.
 
-	  This is similar to the EQL driver, but it merges Ethernet segments
-	  instead of serial lines.
+	  Refer to <file:Documentation/networking/bonding.txt> for more
+	  information.
 
 	  To compile this driver as a module, choose M here: the module
 	  will be called bonding.
@@ -445,7 +442,7 @@
 
 config MIPS_JAZZ_SONIC
 	tristate "MIPS JAZZ onboard SONIC Ethernet support"
-	depends on NET_ETHERNET && MIPS_JAZZ
+	depends on NET_ETHERNET && MACH_JAZZ
 	help
 	  This is the driver for the onboard card of MIPS Magnum 4000,
 	  Acer PICA, Olivetti M700-10 and a few other identical OEM systems.
@@ -470,7 +467,7 @@
 
 config SGI_IOC3_ETH
 	bool "SGI IOC3 Ethernet"
-	depends on NET_ETHERNET && SGI_IP27
+	depends on NET_ETHERNET && PCI && SGI_IP27
 	select CRC32
 	select MII
 	help
@@ -819,7 +816,7 @@
 	tristate "SMC 91C9x/91C1xxx support"
 	select CRC32
 	select MII
-	depends on NET_ETHERNET && (ARM || REDWOOD_5 || REDWOOD_6 || M32R)
+	depends on NET_ETHERNET && (ARM || REDWOOD_5 || REDWOOD_6 || M32R || SUPERH)
 	help
 	  This is a driver for SMC's 91x series of Ethernet chipsets,
 	  including the SMC91C94 and the SMC91C111. Say Y if you want it
@@ -1428,23 +1425,6 @@
 	  <file:Documentation/networking/net-modules.txt>.  The module
 	  will be called e100.
 
-config E100_NAPI
-	bool "Use Rx Polling (NAPI)"
-	depends on E100
-	help
-	  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.
-
 config LNE390
 	tristate "Mylex EISA LNE390A/B support (EXPERIMENTAL)"
 	depends on NET_PCI && EISA && EXPERIMENTAL
@@ -1780,14 +1760,6 @@
 	  DEC (now Compaq) based on the AMD Lance chipset, including the
 	  DEPCA series.  (This chipset is better known via the NE2100 cards.)
 
-config BAGETLANCE
-	tristate "Baget AMD LANCE support"
-	depends on NET_ETHERNET && BAGET_MIPS
-	help
-	  Say Y to enable kernel support for AMD Lance Ethernet cards on the
-	  MIPS-32-based Baget embedded system.  This chipset is better known
-	  via the NE2100 cards.
-
 config 68360_ENET
 	bool "Motorola 68360 ethernet controller"
 	depends on M68360
@@ -2083,7 +2055,7 @@
 
 config GIANFAR
 	tristate "Gianfar Ethernet"
-	depends on 85xx
+	depends on 85xx || 83xx
 	help
 	  This driver supports the Gigabit TSEC on the MPC85xx 
 	  family of chips, and the FEC on the 8540
@@ -2094,10 +2066,11 @@
 
 config MV643XX_ETH
 	tristate "MV-643XX Ethernet support"
-	depends on MOMENCO_OCELOT_C || MOMENCO_JAGUAR_ATX
+	depends on MOMENCO_OCELOT_C || MOMENCO_JAGUAR_ATX || MV64360 || MOMENCO_OCELOT_3
 	help
 	  This driver supports the gigabit Ethernet on the Marvell MV643XX
-	  chipset which is used in the Momenco Ocelot C and Jaguar ATX.
+	  chipset which is used in the Momenco Ocelot C and Jaguar ATX and
+	  Pegasos II, amongst other PPC and MIPS boards.
 
 config MV643XX_ETH_0
 	bool "MV-643XX Port 0"
diff -Nru a/drivers/net/Makefile b/drivers/net/Makefile
--- a/drivers/net/Makefile	2005-03-11 12:51:42 -08:00
+++ b/drivers/net/Makefile	2005-03-11 12:51:42 -08:00
@@ -162,7 +162,6 @@
 obj-$(CONFIG_MIPS_GT96100ETH) += gt96100eth.o
 obj-$(CONFIG_MIPS_AU1X00_ENET) += au1000_eth.o
 obj-$(CONFIG_SGI_IOC3_ETH) += ioc3-eth.o
-obj-$(CONFIG_BAGETLANCE) += bagetlance.o
 obj-$(CONFIG_DECLANCE) += declance.o
 obj-$(CONFIG_ATARILANCE) += atarilance.o
 obj-$(CONFIG_ATARI_BIONET) += atari_bionet.o
diff -Nru a/drivers/net/Space.c b/drivers/net/Space.c
--- a/drivers/net/Space.c	2005-03-11 12:51:41 -08:00
+++ b/drivers/net/Space.c	2005-03-11 12:51:41 -08:00
@@ -302,16 +302,6 @@
 	{NULL, 0},
 };
 
-static struct devprobe2 mips_probes[] __initdata = {
-#ifdef CONFIG_MIPS_JAZZ_SONIC
-	{sonic_probe, 0},
-#endif
-#ifdef CONFIG_BAGETLANCE        /* Lance-based Baget ethernet boards */
-        {bagetlance_probe, 0},
-#endif
-	{NULL, 0},
-};
-
 /*
  * Unified ethernet device probe, segmented per architecture and
  * per bus interface. This drives the legacy devices only for now.
@@ -325,7 +315,6 @@
 		return;
 
 	(void)(	probe_list2(unit, m68k_probes, base_addr == 0) &&
-		probe_list2(unit, mips_probes, base_addr == 0) &&
 		probe_list2(unit, eisa_probes, base_addr == 0) &&
 		probe_list2(unit, mca_probes, base_addr == 0) &&
 		probe_list2(unit, isa_probes, base_addr == 0) &&
diff -Nru a/drivers/net/amd8111e.c b/drivers/net/amd8111e.c
--- a/drivers/net/amd8111e.c	2005-03-11 12:51:52 -08:00
+++ b/drivers/net/amd8111e.c	2005-03-11 12:51:52 -08:00
@@ -1381,6 +1381,8 @@
 
 	if(amd8111e_restart(dev)){
 		spin_unlock_irq(&lp->lock);
+		if (dev->irq)
+			free_irq(dev->irq, dev);
 		return -ENOMEM;
 	}
 	/* Start ipg timer */
@@ -1487,7 +1489,7 @@
 amd8111e crc generator implementation is different from the kernel
 ether_crc() function.
 */
-int amd8111e_ether_crc(int len, char* mac_addr)
+static int amd8111e_ether_crc(int len, char* mac_addr)
 {
 	int i,byte;
 	unsigned char octet;
@@ -1715,7 +1717,7 @@
 /* 
 This function changes the mtu of the device. It restarts the device  to initialize the descriptor with new receive buffers.
 */  
-int amd8111e_change_mtu(struct net_device *dev, int new_mtu)
+static int amd8111e_change_mtu(struct net_device *dev, int new_mtu)
 {
 	struct amd8111e_priv *lp = netdev_priv(dev);
 	int err;
@@ -1797,7 +1799,7 @@
 	if(!err)
 		netif_wake_queue(dev);
 }
-static int amd8111e_suspend(struct pci_dev *pci_dev, u32 state)
+static int amd8111e_suspend(struct pci_dev *pci_dev, pm_message_t state)
 {	
 	struct net_device *dev = pci_get_drvdata(pci_dev);
 	struct amd8111e_priv *lp = netdev_priv(dev);
diff -Nru a/drivers/net/arcnet/arc-rawmode.c b/drivers/net/arcnet/arc-rawmode.c
--- a/drivers/net/arcnet/arc-rawmode.c	2005-03-11 12:51:51 -08:00
+++ b/drivers/net/arcnet/arc-rawmode.c	2005-03-11 12:51:51 -08:00
@@ -87,7 +87,7 @@
 static void rx(struct net_device *dev, int bufnum,
 	       struct archdr *pkthdr, int length)
 {
-	struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
+	struct arcnet_local *lp = dev->priv;
 	struct sk_buff *skb;
 	struct archdr *pkt = pkthdr;
 	int ofs;
@@ -168,7 +168,7 @@
 static int prepare_tx(struct net_device *dev, struct archdr *pkt, int length,
 		      int bufnum)
 {
-	struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
+	struct arcnet_local *lp = dev->priv;
 	struct arc_hardware *hard = &pkt->hard;
 	int ofs;
 
diff -Nru a/drivers/net/arcnet/arc-rimi.c b/drivers/net/arcnet/arc-rimi.c
--- a/drivers/net/arcnet/arc-rimi.c	2005-03-11 12:51:41 -08:00
+++ b/drivers/net/arcnet/arc-rimi.c	2005-03-11 12:51:41 -08:00
@@ -230,7 +230,7 @@
  */
 static int arcrimi_reset(struct net_device *dev, int really_reset)
 {
-	struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
+	struct arcnet_local *lp = dev->priv;
 	void __iomem *ioaddr = lp->mem_start + 0x800;
 
 	BUGMSG(D_INIT, "Resetting %s (status=%02Xh)\n", dev->name, ASTATUS());
@@ -251,7 +251,7 @@
 
 static void arcrimi_setmask(struct net_device *dev, int mask)
 {
-	struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
+	struct arcnet_local *lp = dev->priv;
 	void __iomem *ioaddr = lp->mem_start + 0x800;
 
 	AINTMASK(mask);
@@ -259,7 +259,7 @@
 
 static int arcrimi_status(struct net_device *dev)
 {
-	struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
+	struct arcnet_local *lp = dev->priv;
 	void __iomem *ioaddr = lp->mem_start + 0x800;
 
 	return ASTATUS();
@@ -267,7 +267,7 @@
 
 static void arcrimi_command(struct net_device *dev, int cmd)
 {
-	struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
+	struct arcnet_local *lp = dev->priv;
 	void __iomem *ioaddr = lp->mem_start + 0x800;
 
 	ACOMMAND(cmd);
@@ -276,7 +276,7 @@
 static void arcrimi_copy_to_card(struct net_device *dev, int bufnum, int offset,
 				 void *buf, int count)
 {
-	struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
+	struct arcnet_local *lp = dev->priv;
 	void __iomem *memaddr = lp->mem_start + 0x800 + bufnum * 512 + offset;
 	TIME("memcpy_toio", count, memcpy_toio(memaddr, buf, count));
 }
@@ -285,7 +285,7 @@
 static void arcrimi_copy_from_card(struct net_device *dev, int bufnum, int offset,
 				   void *buf, int count)
 {
-	struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
+	struct arcnet_local *lp = dev->priv;
 	void __iomem *memaddr = lp->mem_start + 0x800 + bufnum * 512 + offset;
 	TIME("memcpy_fromio", count, memcpy_fromio(buf, memaddr, count));
 }
@@ -331,7 +331,7 @@
 static void __exit arc_rimi_exit(void)
 {
 	struct net_device *dev = my_dev;
-	struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
+	struct arcnet_local *lp = dev->priv;
 
 	unregister_netdev(dev);
 	iounmap(lp->mem_start);
diff -Nru a/drivers/net/arcnet/arcnet.c b/drivers/net/arcnet/arcnet.c
--- a/drivers/net/arcnet/arcnet.c	2005-03-11 12:51:47 -08:00
+++ b/drivers/net/arcnet/arcnet.c	2005-03-11 12:51:47 -08:00
@@ -181,7 +181,7 @@
 void arcnet_dump_packet(struct net_device *dev, int bufnum, char *desc,
 			int take_arcnet_lock)
 {
-	struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
+	struct arcnet_local *lp = dev->priv;
 	int i, length;
 	unsigned long flags = 0;
 	static uint8_t buf[512];
@@ -244,7 +244,7 @@
  */
 static void release_arcbuf(struct net_device *dev, int bufnum)
 {
-	struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
+	struct arcnet_local *lp = dev->priv;
 	int i;
 
 	lp->buf_queue[lp->first_free_buf++] = bufnum;
@@ -266,7 +266,7 @@
  */
 static int get_arcbuf(struct net_device *dev)
 {
-	struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
+	struct arcnet_local *lp = dev->priv;
 	int buf = -1, i;
 
 	if (!atomic_dec_and_test(&lp->buf_lock)) {
@@ -367,7 +367,7 @@
  */
 static int arcnet_open(struct net_device *dev)
 {
-	struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
+	struct arcnet_local *lp = dev->priv;
 	int count, newmtu, error;
 
 	BUGMSG(D_INIT,"opened.");
@@ -467,7 +467,7 @@
 /* The inverse routine to arcnet_open - shuts down the card. */
 static int arcnet_close(struct net_device *dev)
 {
-	struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
+	struct arcnet_local *lp = dev->priv;
 
 	netif_stop_queue(dev);
 
@@ -488,7 +488,7 @@
 			 unsigned short type, void *daddr, void *saddr,
 			 unsigned len)
 {
-	struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
+	struct arcnet_local *lp = dev->priv;
 	uint8_t _daddr, proto_num;
 	struct ArcProto *proto;
 
@@ -546,7 +546,7 @@
 static int arcnet_rebuild_header(struct sk_buff *skb)
 {
 	struct net_device *dev = skb->dev;
-	struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
+	struct arcnet_local *lp = dev->priv;
 	int status = 0;		/* default is failure */
 	unsigned short type;
 	uint8_t daddr=0;
@@ -591,7 +591,7 @@
 /* Called by the kernel in order to transmit a packet. */
 static int arcnet_send_packet(struct sk_buff *skb, struct net_device *dev)
 {
-	struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
+	struct arcnet_local *lp = dev->priv;
 	struct archdr *pkt;
 	struct arc_rfc1201 *soft;
 	struct ArcProto *proto;
@@ -674,7 +674,7 @@
  */
 static int go_tx(struct net_device *dev)
 {
-	struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
+	struct arcnet_local *lp = dev->priv;
 
 	BUGMSG(D_DURING, "go_tx: status=%Xh, intmask=%Xh, next_tx=%d, cur_tx=%d\n",
 	       ASTATUS(), lp->intmask, lp->next_tx, lp->cur_tx);
@@ -705,7 +705,7 @@
 static void arcnet_timeout(struct net_device *dev)
 {
 	unsigned long flags;
-	struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
+	struct arcnet_local *lp = dev->priv;
 	int status = ASTATUS();
 	char *msg;
 
@@ -754,7 +754,7 @@
 
 	BUGMSG(D_DURING, "in arcnet_interrupt\n");
 	
-	lp = (struct arcnet_local *) dev->priv;
+	lp = dev->priv;
 	if (!lp)
 		BUG();
 		
@@ -989,7 +989,7 @@
  */
 void arcnet_rx(struct net_device *dev, int bufnum)
 {
-	struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
+	struct arcnet_local *lp = dev->priv;
 	struct archdr pkt;
 	struct arc_rfc1201 *soft;
 	int length, ofs;
@@ -1053,7 +1053,7 @@
  */
 static struct net_device_stats *arcnet_get_stats(struct net_device *dev)
 {
-	struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
+	struct arcnet_local *lp = dev->priv;
 	return &lp->stats;
 }
 
@@ -1070,7 +1070,7 @@
 static int null_build_header(struct sk_buff *skb, struct net_device *dev,
 			     unsigned short type, uint8_t daddr)
 {
-	struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
+	struct arcnet_local *lp = dev->priv;
 
 	BUGMSG(D_PROTO,
 	       "tx: can't build header for encap %02Xh; load a protocol driver.\n",
@@ -1085,7 +1085,7 @@
 static int null_prepare_tx(struct net_device *dev, struct archdr *pkt,
 			   int length, int bufnum)
 {
-	struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
+	struct arcnet_local *lp = dev->priv;
 	struct arc_hardware newpkt;
 
 	BUGMSG(D_PROTO, "tx: no encap for this host; load a protocol driver.\n");
diff -Nru a/drivers/net/arcnet/com20020.c b/drivers/net/arcnet/com20020.c
--- a/drivers/net/arcnet/com20020.c	2005-03-11 12:51:42 -08:00
+++ b/drivers/net/arcnet/com20020.c	2005-03-11 12:51:42 -08:00
@@ -159,7 +159,7 @@
 
 	/* Initialize the rest of the device structure. */
 
-	lp = (struct arcnet_local *) dev->priv;
+	lp = dev->priv;
 
 	lp->hw.owner = THIS_MODULE;
 	lp->hw.command = com20020_command;
@@ -233,7 +233,7 @@
  */
 static int com20020_reset(struct net_device *dev, int really_reset)
 {
-	struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
+	struct arcnet_local *lp = dev->priv;
 	u_int ioaddr = dev->base_addr;
 	u_char inbyte;
 
@@ -300,7 +300,7 @@
 
 static void com20020_close(struct net_device *dev)
 {
-	struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
+	struct arcnet_local *lp = dev->priv;
 	int ioaddr = dev->base_addr;
 
 	/* disable transmitter */
diff -Nru a/drivers/net/arcnet/com90io.c b/drivers/net/arcnet/com90io.c
--- a/drivers/net/arcnet/com90io.c	2005-03-11 12:51:42 -08:00
+++ b/drivers/net/arcnet/com90io.c	2005-03-11 12:51:42 -08:00
@@ -248,7 +248,7 @@
 		return -EBUSY;
 	}
 
-	lp = (struct arcnet_local *) (dev->priv);
+	lp = dev->priv;
 	lp->card_name = "COM90xx I/O";
 	lp->hw.command = com90io_command;
 	lp->hw.status = com90io_status;
@@ -290,7 +290,7 @@
  */
 static int com90io_reset(struct net_device *dev, int really_reset)
 {
-	struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
+	struct arcnet_local *lp = dev->priv;
 	short ioaddr = dev->base_addr;
 
 	BUGMSG(D_INIT, "Resetting %s (status=%02Xh)\n", dev->name, ASTATUS());
diff -Nru a/drivers/net/arcnet/com90xx.c b/drivers/net/arcnet/com90xx.c
--- a/drivers/net/arcnet/com90xx.c	2005-03-11 12:51:47 -08:00
+++ b/drivers/net/arcnet/com90xx.c	2005-03-11 12:51:47 -08:00
@@ -529,7 +529,7 @@
  */
 int com90xx_reset(struct net_device *dev, int really_reset)
 {
-	struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
+	struct arcnet_local *lp = dev->priv;
 	short ioaddr = dev->base_addr;
 
 	BUGMSG(D_INIT, "Resetting (status=%02Xh)\n", ASTATUS());
@@ -565,7 +565,7 @@
 static void com90xx_copy_to_card(struct net_device *dev, int bufnum, int offset,
 				 void *buf, int count)
 {
-	struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
+	struct arcnet_local *lp = dev->priv;
 	void __iomem *memaddr = lp->mem_start + bufnum * 512 + offset;
 	TIME("memcpy_toio", count, memcpy_toio(memaddr, buf, count));
 }
@@ -574,7 +574,7 @@
 static void com90xx_copy_from_card(struct net_device *dev, int bufnum, int offset,
 				   void *buf, int count)
 {
-	struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
+	struct arcnet_local *lp = dev->priv;
 	void __iomem *memaddr = lp->mem_start + bufnum * 512 + offset;
 	TIME("memcpy_fromio", count, memcpy_fromio(buf, memaddr, count));
 }
@@ -600,7 +600,7 @@
 
 	for (count = 0; count < numcards; count++) {
 		dev = cards[count];
-		lp = (struct arcnet_local *) dev->priv;
+		lp = dev->priv;
 
 		unregister_netdev(dev);
 		free_irq(dev->irq, dev);
diff -Nru a/drivers/net/arcnet/rfc1051.c b/drivers/net/arcnet/rfc1051.c
--- a/drivers/net/arcnet/rfc1051.c	2005-03-11 12:51:47 -08:00
+++ b/drivers/net/arcnet/rfc1051.c	2005-03-11 12:51:47 -08:00
@@ -88,7 +88,7 @@
  */
 static unsigned short type_trans(struct sk_buff *skb, struct net_device *dev)
 {
-	struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
+	struct arcnet_local *lp = dev->priv;
 	struct archdr *pkt = (struct archdr *) skb->data;
 	struct arc_rfc1051 *soft = &pkt->soft.rfc1051;
 	int hdr_size = ARC_HDR_SIZE + RFC1051_HDR_SIZE;
@@ -125,7 +125,7 @@
 static void rx(struct net_device *dev, int bufnum,
 	       struct archdr *pkthdr, int length)
 {
-	struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
+	struct arcnet_local *lp = dev->priv;
 	struct sk_buff *skb;
 	struct archdr *pkt = pkthdr;
 	int ofs;
@@ -169,7 +169,7 @@
 static int build_header(struct sk_buff *skb, struct net_device *dev,
 			unsigned short type, uint8_t daddr)
 {
-	struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
+	struct arcnet_local *lp = dev->priv;
 	int hdr_size = ARC_HDR_SIZE + RFC1051_HDR_SIZE;
 	struct archdr *pkt = (struct archdr *) skb_push(skb, hdr_size);
 	struct arc_rfc1051 *soft = &pkt->soft.rfc1051;
@@ -220,7 +220,7 @@
 static int prepare_tx(struct net_device *dev, struct archdr *pkt, int length,
 		      int bufnum)
 {
-	struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
+	struct arcnet_local *lp = dev->priv;
 	struct arc_hardware *hard = &pkt->hard;
 	int ofs;
 
diff -Nru a/drivers/net/arcnet/rfc1201.c b/drivers/net/arcnet/rfc1201.c
--- a/drivers/net/arcnet/rfc1201.c	2005-03-11 12:51:46 -08:00
+++ b/drivers/net/arcnet/rfc1201.c	2005-03-11 12:51:46 -08:00
@@ -92,7 +92,7 @@
 {
 	struct archdr *pkt = (struct archdr *) skb->data;
 	struct arc_rfc1201 *soft = &pkt->soft.rfc1201;
-	struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
+	struct arcnet_local *lp = dev->priv;
 	int hdr_size = ARC_HDR_SIZE + RFC1201_HDR_SIZE;
 
 	/* Pull off the arcnet header. */
@@ -134,7 +134,7 @@
 static void rx(struct net_device *dev, int bufnum,
 	       struct archdr *pkthdr, int length)
 {
-	struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
+	struct arcnet_local *lp = dev->priv;
 	struct sk_buff *skb;
 	struct archdr *pkt = pkthdr;
 	struct arc_rfc1201 *soft = &pkthdr->soft.rfc1201;
@@ -376,7 +376,7 @@
 static int build_header(struct sk_buff *skb, struct net_device *dev,
 			unsigned short type, uint8_t daddr)
 {
-	struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
+	struct arcnet_local *lp = dev->priv;
 	int hdr_size = ARC_HDR_SIZE + RFC1201_HDR_SIZE;
 	struct archdr *pkt = (struct archdr *) skb_push(skb, hdr_size);
 	struct arc_rfc1201 *soft = &pkt->soft.rfc1201;
@@ -443,7 +443,7 @@
 static void load_pkt(struct net_device *dev, struct arc_hardware *hard,
 		     struct arc_rfc1201 *soft, int softlen, int bufnum)
 {
-	struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
+	struct arcnet_local *lp = dev->priv;
 	int ofs;
 
 	/* assume length <= XMTU: someone should have handled that by now. */
@@ -476,7 +476,7 @@
 static int prepare_tx(struct net_device *dev, struct archdr *pkt, int length,
 		      int bufnum)
 {
-	struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
+	struct arcnet_local *lp = dev->priv;
 	const int maxsegsize = XMTU - RFC1201_HDR_SIZE;
 	struct Outgoing *out;
 
@@ -511,7 +511,7 @@
 
 static int continue_tx(struct net_device *dev, int bufnum)
 {
-	struct arcnet_local *lp = (struct arcnet_local *) dev->priv;
+	struct arcnet_local *lp = dev->priv;
 	struct Outgoing *out = &lp->outgoing;
 	struct arc_hardware *hard = &out->pkt->hard;
 	struct arc_rfc1201 *soft = &out->pkt->soft.rfc1201, *newsoft;
diff -Nru a/drivers/net/arm/ether1.c b/drivers/net/arm/ether1.c
--- a/drivers/net/arm/ether1.c	2005-03-11 12:51:52 -08:00
+++ b/drivers/net/arm/ether1.c	2005-03-11 12:51:52 -08:00
@@ -86,8 +86,8 @@
 #define DISABLEIRQS 1
 #define NORMALIRQS  0
 
-#define ether1_inw(dev, addr, type, offset, svflgs) ether1_inw_p (dev, addr + (int)(&((type *)0)->offset), svflgs)
-#define ether1_outw(dev, val, addr, type, offset, svflgs) ether1_outw_p (dev, val, addr + (int)(&((type *)0)->offset), svflgs)
+#define ether1_readw(dev, addr, type, offset, svflgs) ether1_inw_p (dev, addr + (int)(&((type *)0)->offset), svflgs)
+#define ether1_writew(dev, val, addr, type, offset, svflgs) ether1_outw_p (dev, val, addr + (int)(&((type *)0)->offset), svflgs)
 
 static inline unsigned short
 ether1_inw_p (struct net_device *dev, int addr, int svflgs)
@@ -98,8 +98,8 @@
 	if (svflgs)
 		local_irq_save (flags);
 
-	outb (addr >> 12, REG_PAGE);
-	ret = inw (ETHER1_RAM + ((addr & 4095) >> 1));
+	writeb(addr >> 12, REG_PAGE);
+	ret = readw(ETHER1_RAM + ((addr & 4095) << 1));
 	if (svflgs)
 		local_irq_restore (flags);
 	return ret;
@@ -113,8 +113,8 @@
 	if (svflgs)
 		local_irq_save (flags);
 
-	outb (addr >> 12, REG_PAGE);
-	outw (val, ETHER1_RAM + ((addr & 4095) >> 1));
+	writeb(addr >> 12, REG_PAGE);
+	writew(val, ETHER1_RAM + ((addr & 4095) << 1));
 	if (svflgs)
 		local_irq_restore (flags);
 }
@@ -131,11 +131,12 @@
 static void
 ether1_writebuffer (struct net_device *dev, void *data, unsigned int start, unsigned int length)
 {
-	unsigned int page, thislen, offset, addr;
+	unsigned int page, thislen, offset;
+	void __iomem *addr;
 
 	offset = start & 4095;
 	page = start >> 12;
-	addr = ioaddr(ETHER1_RAM + (offset >> 1));
+	addr = ETHER1_RAM + (offset << 1);
 
 	if (offset + length > 4096)
 		thislen = 4096 - offset;
@@ -145,7 +146,7 @@
 	do {
 		int used;
 
-		outb(page, REG_PAGE);
+		writeb(page, REG_PAGE);
 		length -= thislen;
 
 		__asm__ __volatile__(
@@ -181,7 +182,7 @@
 		: "=&r" (used), "=&r" (data)
 		: "r"  (addr), "r" (thislen), "1" (data));
 
-		addr = ioaddr(ETHER1_RAM);
+		addr = ETHER1_RAM;
 
 		thislen = length;
 		if (thislen > 4096)
@@ -193,11 +194,12 @@
 static void
 ether1_readbuffer (struct net_device *dev, void *data, unsigned int start, unsigned int length)
 {
-	unsigned int page, thislen, offset, addr;
+	unsigned int page, thislen, offset;
+	void __iomem *addr;
 
 	offset = start & 4095;
 	page = start >> 12;
-	addr = ioaddr(ETHER1_RAM + (offset >> 1));
+	addr = ETHER1_RAM + (offset << 1);
 
 	if (offset + length > 4096)
 		thislen = 4096 - offset;
@@ -207,7 +209,7 @@
 	do {
 		int used;
 
-		outb(page, REG_PAGE);
+		writeb(page, REG_PAGE);
 		length -= thislen;
 
 		__asm__ __volatile__(
@@ -243,7 +245,7 @@
 		: "=&r" (used), "=&r" (data)
 		: "r"  (addr), "r" (thislen), "1" (data));
 
-		addr = ioaddr(ETHER1_RAM);
+		addr = ETHER1_RAM;
 
 		thislen = length;
 		if (thislen > 4096)
@@ -302,7 +304,7 @@
 static int
 ether1_reset (struct net_device *dev)
 {
-	outb (CTRL_RST|CTRL_ACK, REG_CONTROL);
+	writeb(CTRL_RST|CTRL_ACK, REG_CONTROL);
 	return BUS_16;
 }
 
@@ -447,12 +449,11 @@
 static int
 ether1_init_for_open (struct net_device *dev)
 {
-	struct ether1_priv *priv = netdev_priv(dev);
 	int i, status, addr, next, next2;
 	int failures = 0;
 	unsigned long timeout;
 
-	outb (CTRL_RST|CTRL_ACK, REG_CONTROL);
+	writeb(CTRL_RST|CTRL_ACK, REG_CONTROL);
 
 	for (i = 0; i < 6; i++)
 		init_sa.sa_addr[i] = dev->dev_addr[i];
@@ -467,7 +468,7 @@
 	ether1_writebuffer (dev, &init_tdr,  TDR_ADDR,  TDR_SIZE);
 	ether1_writebuffer (dev, &init_nop,  NOP_ADDR,  NOP_SIZE);
 
-	if (ether1_inw (dev, CFG_ADDR, cfg_t, cfg_command, NORMALIRQS) != CMD_CONFIG) {
+	if (ether1_readw(dev, CFG_ADDR, cfg_t, cfg_command, NORMALIRQS) != CMD_CONFIG) {
 		printk (KERN_ERR "%s: detected either RAM fault or compiler bug\n",
 			dev->name);
 		return 1;
@@ -487,7 +488,7 @@
 		if (next2 >= RX_AREA_END) {
 			next = RX_AREA_START;
 			init_rfd.rfd_command = RFD_CMDEL | RFD_CMDSUSPEND;
-			priv->rx_tail = addr;
+			priv(dev)->rx_tail = addr;
 		} else
 			init_rfd.rfd_command = 0;
 		if (addr == RX_AREA_START)
@@ -503,21 +504,21 @@
 		addr = next;
 	} while (next2 < RX_AREA_END);
 
-	priv->tx_link = NOP_ADDR;
-	priv->tx_head = NOP_ADDR + NOP_SIZE;
-	priv->tx_tail = TDR_ADDR;
-	priv->rx_head = RX_AREA_START;
+	priv(dev)->tx_link = NOP_ADDR;
+	priv(dev)->tx_head = NOP_ADDR + NOP_SIZE;
+	priv(dev)->tx_tail = TDR_ADDR;
+	priv(dev)->rx_head = RX_AREA_START;
 
 	/* release reset & give 586 a prod */
-	priv->resetting = 1;
-	priv->initialising = 1;
-	outb (CTRL_RST, REG_CONTROL);
-	outb (0, REG_CONTROL);
-	outb (CTRL_CA, REG_CONTROL);
+	priv(dev)->resetting = 1;
+	priv(dev)->initialising = 1;
+	writeb(CTRL_RST, REG_CONTROL);
+	writeb(0, REG_CONTROL);
+	writeb(CTRL_CA, REG_CONTROL);
 
 	/* 586 should now unset iscp.busy */
 	timeout = jiffies + HZ/2;
-	while (ether1_inw (dev, ISCP_ADDR, iscp_t, iscp_busy, DISABLEIRQS) == 1) {
+	while (ether1_readw(dev, ISCP_ADDR, iscp_t, iscp_busy, DISABLEIRQS) == 1) {
 		if (time_after(jiffies, timeout)) {
 			printk (KERN_WARNING "%s: can't initialise 82586: iscp is busy\n", dev->name);
 			return 1;
@@ -526,7 +527,7 @@
 
 	/* check status of commands that we issued */
 	timeout += HZ/10;
-	while (((status = ether1_inw (dev, CFG_ADDR, cfg_t, cfg_status, DISABLEIRQS))
+	while (((status = ether1_readw(dev, CFG_ADDR, cfg_t, cfg_status, DISABLEIRQS))
 			& STAT_COMPLETE) == 0) {
 		if (time_after(jiffies, timeout))
 			break;
@@ -535,15 +536,15 @@
 	if ((status & (STAT_COMPLETE | STAT_OK)) != (STAT_COMPLETE | STAT_OK)) {
 		printk (KERN_WARNING "%s: can't initialise 82586: config status %04X\n", dev->name, status);
 		printk (KERN_DEBUG "%s: SCB=[STS=%04X CMD=%04X CBL=%04X RFA=%04X]\n", dev->name,
-			ether1_inw (dev, SCB_ADDR, scb_t, scb_status, NORMALIRQS),
-			ether1_inw (dev, SCB_ADDR, scb_t, scb_command, NORMALIRQS),
-			ether1_inw (dev, SCB_ADDR, scb_t, scb_cbl_offset, NORMALIRQS),
-			ether1_inw (dev, SCB_ADDR, scb_t, scb_rfa_offset, NORMALIRQS));
+			ether1_readw(dev, SCB_ADDR, scb_t, scb_status, NORMALIRQS),
+			ether1_readw(dev, SCB_ADDR, scb_t, scb_command, NORMALIRQS),
+			ether1_readw(dev, SCB_ADDR, scb_t, scb_cbl_offset, NORMALIRQS),
+			ether1_readw(dev, SCB_ADDR, scb_t, scb_rfa_offset, NORMALIRQS));
 		failures += 1;
 	}
 
 	timeout += HZ/10;
-	while (((status = ether1_inw (dev, SA_ADDR, sa_t, sa_status, DISABLEIRQS))
+	while (((status = ether1_readw(dev, SA_ADDR, sa_t, sa_status, DISABLEIRQS))
 			& STAT_COMPLETE) == 0) {
 		if (time_after(jiffies, timeout))
 			break;
@@ -552,15 +553,15 @@
 	if ((status & (STAT_COMPLETE | STAT_OK)) != (STAT_COMPLETE | STAT_OK)) {
 		printk (KERN_WARNING "%s: can't initialise 82586: set address status %04X\n", dev->name, status);
 		printk (KERN_DEBUG "%s: SCB=[STS=%04X CMD=%04X CBL=%04X RFA=%04X]\n", dev->name,
-			ether1_inw (dev, SCB_ADDR, scb_t, scb_status, NORMALIRQS),
-			ether1_inw (dev, SCB_ADDR, scb_t, scb_command, NORMALIRQS),
-			ether1_inw (dev, SCB_ADDR, scb_t, scb_cbl_offset, NORMALIRQS),
-			ether1_inw (dev, SCB_ADDR, scb_t, scb_rfa_offset, NORMALIRQS));
+			ether1_readw(dev, SCB_ADDR, scb_t, scb_status, NORMALIRQS),
+			ether1_readw(dev, SCB_ADDR, scb_t, scb_command, NORMALIRQS),
+			ether1_readw(dev, SCB_ADDR, scb_t, scb_cbl_offset, NORMALIRQS),
+			ether1_readw(dev, SCB_ADDR, scb_t, scb_rfa_offset, NORMALIRQS));
 		failures += 1;
 	}
 
 	timeout += HZ/10;
-	while (((status = ether1_inw (dev, MC_ADDR, mc_t, mc_status, DISABLEIRQS))
+	while (((status = ether1_readw(dev, MC_ADDR, mc_t, mc_status, DISABLEIRQS))
 			& STAT_COMPLETE) == 0) {
 		if (time_after(jiffies, timeout))
 			break;
@@ -569,15 +570,15 @@
 	if ((status & (STAT_COMPLETE | STAT_OK)) != (STAT_COMPLETE | STAT_OK)) {
 		printk (KERN_WARNING "%s: can't initialise 82586: set multicast status %04X\n", dev->name, status);
 		printk (KERN_DEBUG "%s: SCB=[STS=%04X CMD=%04X CBL=%04X RFA=%04X]\n", dev->name,
-			ether1_inw (dev, SCB_ADDR, scb_t, scb_status, NORMALIRQS),
-			ether1_inw (dev, SCB_ADDR, scb_t, scb_command, NORMALIRQS),
-			ether1_inw (dev, SCB_ADDR, scb_t, scb_cbl_offset, NORMALIRQS),
-			ether1_inw (dev, SCB_ADDR, scb_t, scb_rfa_offset, NORMALIRQS));
+			ether1_readw(dev, SCB_ADDR, scb_t, scb_status, NORMALIRQS),
+			ether1_readw(dev, SCB_ADDR, scb_t, scb_command, NORMALIRQS),
+			ether1_readw(dev, SCB_ADDR, scb_t, scb_cbl_offset, NORMALIRQS),
+			ether1_readw(dev, SCB_ADDR, scb_t, scb_rfa_offset, NORMALIRQS));
 		failures += 1;
 	}
 
 	timeout += HZ;
-	while (((status = ether1_inw (dev, TDR_ADDR, tdr_t, tdr_status, DISABLEIRQS))
+	while (((status = ether1_readw(dev, TDR_ADDR, tdr_t, tdr_status, DISABLEIRQS))
 			& STAT_COMPLETE) == 0) {
 		if (time_after(jiffies, timeout))
 			break;
@@ -586,12 +587,12 @@
 	if ((status & (STAT_COMPLETE | STAT_OK)) != (STAT_COMPLETE | STAT_OK)) {
 		printk (KERN_WARNING "%s: can't tdr (ignored)\n", dev->name);
 		printk (KERN_DEBUG "%s: SCB=[STS=%04X CMD=%04X CBL=%04X RFA=%04X]\n", dev->name,
-			ether1_inw (dev, SCB_ADDR, scb_t, scb_status, NORMALIRQS),
-			ether1_inw (dev, SCB_ADDR, scb_t, scb_command, NORMALIRQS),
-			ether1_inw (dev, SCB_ADDR, scb_t, scb_cbl_offset, NORMALIRQS),
-			ether1_inw (dev, SCB_ADDR, scb_t, scb_rfa_offset, NORMALIRQS));
+			ether1_readw(dev, SCB_ADDR, scb_t, scb_status, NORMALIRQS),
+			ether1_readw(dev, SCB_ADDR, scb_t, scb_command, NORMALIRQS),
+			ether1_readw(dev, SCB_ADDR, scb_t, scb_cbl_offset, NORMALIRQS),
+			ether1_readw(dev, SCB_ADDR, scb_t, scb_rfa_offset, NORMALIRQS));
 	} else {
-		status = ether1_inw (dev, TDR_ADDR, tdr_t, tdr_result, DISABLEIRQS);
+		status = ether1_readw(dev, TDR_ADDR, tdr_t, tdr_result, DISABLEIRQS);
 		if (status & TDR_XCVRPROB)
 			printk (KERN_WARNING "%s: i/f failed tdr: transceiver problem\n", dev->name);
 		else if ((status & (TDR_SHORT|TDR_OPEN)) && (status & TDR_TIME)) {
@@ -616,24 +617,23 @@
 static int
 ether1_txalloc (struct net_device *dev, int size)
 {
-	struct ether1_priv *priv = netdev_priv(dev);
 	int start, tail;
 
 	size = (size + 1) & ~1;
-	tail = priv->tx_tail;
+	tail = priv(dev)->tx_tail;
 
-	if (priv->tx_head + size > TX_AREA_END) {
-		if (tail > priv->tx_head)
+	if (priv(dev)->tx_head + size > TX_AREA_END) {
+		if (tail > priv(dev)->tx_head)
 			return -1;
 		start = TX_AREA_START;
 		if (start + size > tail)
 			return -1;
-		priv->tx_head = start + size;
+		priv(dev)->tx_head = start + size;
 	} else {
-		if (priv->tx_head < tail && (priv->tx_head + size) > tail)
+		if (priv(dev)->tx_head < tail && (priv(dev)->tx_head + size) > tail)
 			return -1;
-		start = priv->tx_head;
-		priv->tx_head += size;
+		start = priv(dev)->tx_head;
+		priv(dev)->tx_head += size;
 	}
 
 	return start;
@@ -642,8 +642,6 @@
 static int
 ether1_open (struct net_device *dev)
 {
-	struct ether1_priv *priv = netdev_priv(dev);
-
 	if (!is_valid_ether_addr(dev->dev_addr)) {
 		printk(KERN_WARNING "%s: invalid ethernet MAC address\n",
 			dev->name);
@@ -653,7 +651,7 @@
 	if (request_irq(dev->irq, ether1_interrupt, 0, "ether1", dev))
 		return -EAGAIN;
 
-	memset (&priv->stats, 0, sizeof (struct net_device_stats));
+	memset (&priv(dev)->stats, 0, sizeof (struct net_device_stats));
 
 	if (ether1_init_for_open (dev)) {
 		free_irq (dev->irq, dev);
@@ -668,8 +666,6 @@
 static void
 ether1_timeout(struct net_device *dev)
 {
-	struct ether1_priv *priv = netdev_priv(dev);
-
 	printk(KERN_WARNING "%s: transmit timeout, network cable problem?\n",
 		dev->name);
 	printk(KERN_WARNING "%s: resetting device\n", dev->name);
@@ -679,21 +675,20 @@
 	if (ether1_init_for_open (dev))
 		printk (KERN_ERR "%s: unable to restart interface\n", dev->name);
 
-	priv->stats.tx_errors++;
+	priv(dev)->stats.tx_errors++;
 	netif_wake_queue(dev);
 }
 
 static int
 ether1_sendpacket (struct sk_buff *skb, struct net_device *dev)
 {
-	struct ether1_priv *priv = netdev_priv(dev);
 	int tmp, tst, nopaddr, txaddr, tbdaddr, dataddr;
 	unsigned long flags;
 	tx_t tx;
 	tbd_t tbd;
 	nop_t nop;
 
-	if (priv->restart) {
+	if (priv(dev)->restart) {
 		printk(KERN_WARNING "%s: resetting device\n", dev->name);
 
 		ether1_reset(dev);
@@ -701,7 +696,7 @@
 		if (ether1_init_for_open(dev))
 			printk(KERN_ERR "%s: unable to restart interface\n", dev->name);
 		else
-			priv->restart = 0;
+			priv(dev)->restart = 0;
 	}
 
 	if (skb->len < ETH_ZLEN) {
@@ -735,11 +730,11 @@
 	ether1_writebuffer (dev, &tbd, tbdaddr, TBD_SIZE);
 	ether1_writebuffer (dev, skb->data, dataddr, skb->len);
 	ether1_writebuffer (dev, &nop, nopaddr, NOP_SIZE);
-	tmp = priv->tx_link;
-	priv->tx_link = nopaddr;
+	tmp = priv(dev)->tx_link;
+	priv(dev)->tx_link = nopaddr;
 
 	/* now reset the previous nop pointer */
-	ether1_outw (dev, txaddr, tmp, nop_t, nop_link, NORMALIRQS);
+	ether1_writew(dev, txaddr, tmp, nop_t, nop_link, NORMALIRQS);
 
 	local_irq_restore(flags);
 
@@ -747,9 +742,9 @@
 	dev->trans_start = jiffies;
 
 	/* check to see if we have room for a full sized ether frame */
-	tmp = priv->tx_head;
+	tmp = priv(dev)->tx_head;
 	tst = ether1_txalloc (dev, TX_SIZE + TBD_SIZE + NOP_SIZE + ETH_FRAME_LEN);
-	priv->tx_head = tmp;
+	priv(dev)->tx_head = tmp;
 	dev_kfree_skb (skb);
 
 	if (tst == -1)
@@ -762,11 +757,10 @@
 static void
 ether1_xmit_done (struct net_device *dev)
 {
-	struct ether1_priv *priv = netdev_priv(dev);
 	nop_t nop;
 	int caddr, tst;
 
-	caddr = priv->tx_tail;
+	caddr = priv(dev)->tx_tail;
 
 again:
 	ether1_readbuffer (dev, &nop, caddr, NOP_SIZE);
@@ -774,21 +768,21 @@
 	switch (nop.nop_command & CMD_MASK) {
 	case CMD_TDR:
 		/* special case */
-		if (ether1_inw (dev, SCB_ADDR, scb_t, scb_cbl_offset, NORMALIRQS)
+		if (ether1_readw(dev, SCB_ADDR, scb_t, scb_cbl_offset, NORMALIRQS)
 				!= (unsigned short)I82586_NULL) {
-			ether1_outw(dev, SCB_CMDCUCSTART | SCB_CMDRXSTART, SCB_ADDR, scb_t,
+			ether1_writew(dev, SCB_CMDCUCSTART | SCB_CMDRXSTART, SCB_ADDR, scb_t,
 				    scb_command, NORMALIRQS);
-			outb (CTRL_CA, REG_CONTROL);
+			writeb(CTRL_CA, REG_CONTROL);
 		}
-		priv->tx_tail = NOP_ADDR;
+		priv(dev)->tx_tail = NOP_ADDR;
 		return;
 
 	case CMD_NOP:
 		if (nop.nop_link == caddr) {
-			if (priv->initialising == 0)
+			if (priv(dev)->initialising == 0)
 				printk (KERN_WARNING "%s: strange command complete with no tx command!\n", dev->name);
 			else
-			        priv->initialising = 0;
+			        priv(dev)->initialising = 0;
 			return;
 		}
 		if (caddr == nop.nop_link)
@@ -800,33 +794,33 @@
 		if (nop.nop_status & STAT_COMPLETE)
 			break;
 		printk (KERN_ERR "%s: strange command complete without completed command\n", dev->name);
-		priv->restart = 1;
+		priv(dev)->restart = 1;
 		return;
 
 	default:
 		printk (KERN_WARNING "%s: strange command %d complete! (offset %04X)", dev->name,
 			nop.nop_command & CMD_MASK, caddr);
-		priv->restart = 1;
+		priv(dev)->restart = 1;
 		return;
 	}
 
 	while (nop.nop_status & STAT_COMPLETE) {
 		if (nop.nop_status & STAT_OK) {
-			priv->stats.tx_packets ++;
-			priv->stats.collisions += (nop.nop_status & STAT_COLLISIONS);
+			priv(dev)->stats.tx_packets ++;
+			priv(dev)->stats.collisions += (nop.nop_status & STAT_COLLISIONS);
 		} else {
-			priv->stats.tx_errors ++;
+			priv(dev)->stats.tx_errors ++;
 
 			if (nop.nop_status & STAT_COLLAFTERTX)
-				priv->stats.collisions ++;
+				priv(dev)->stats.collisions ++;
 			if (nop.nop_status & STAT_NOCARRIER)
-				priv->stats.tx_carrier_errors ++;
+				priv(dev)->stats.tx_carrier_errors ++;
 			if (nop.nop_status & STAT_TXLOSTCTS)
 				printk (KERN_WARNING "%s: cts lost\n", dev->name);
 			if (nop.nop_status & STAT_TXSLOWDMA)
-				priv->stats.tx_fifo_errors ++;
+				priv(dev)->stats.tx_fifo_errors ++;
 			if (nop.nop_status & STAT_COLLEXCESSIVE)
-				priv->stats.collisions += 16;
+				priv(dev)->stats.collisions += 16;
 		}
 
 		if (nop.nop_link == caddr) {
@@ -851,11 +845,11 @@
 			break;
 		}
 	}
-	priv->tx_tail = caddr;
+	priv(dev)->tx_tail = caddr;
 
-	caddr = priv->tx_head;
+	caddr = priv(dev)->tx_head;
 	tst = ether1_txalloc (dev, TX_SIZE + TBD_SIZE + NOP_SIZE + ETH_FRAME_LEN);
-	priv->tx_head = caddr;
+	priv(dev)->tx_head = caddr;
 	if (tst != -1)
 		netif_wake_queue(dev);
 }
@@ -863,17 +857,16 @@
 static void
 ether1_recv_done (struct net_device *dev)
 {
-	struct ether1_priv *priv = netdev_priv(dev);
 	int status;
 	int nexttail, rbdaddr;
 	rbd_t rbd;
 
 	do {
-		status = ether1_inw (dev, priv->rx_head, rfd_t, rfd_status, NORMALIRQS);
+		status = ether1_readw(dev, priv(dev)->rx_head, rfd_t, rfd_status, NORMALIRQS);
 		if ((status & RFD_COMPLETE) == 0)
 			break;
 
-		rbdaddr = ether1_inw (dev, priv->rx_head, rfd_t, rfd_rbdoffset, NORMALIRQS);
+		rbdaddr = ether1_readw(dev, priv(dev)->rx_head, rfd_t, rfd_rbdoffset, NORMALIRQS);
 		ether1_readbuffer (dev, &rbd, rbdaddr, RBD_SIZE);
 
 		if ((rbd.rbd_status & (RBD_EOF | RBD_ACNTVALID)) == (RBD_EOF | RBD_ACNTVALID)) {
@@ -891,27 +884,27 @@
 
 				skb->protocol = eth_type_trans (skb, dev);
 				netif_rx (skb);
-				priv->stats.rx_packets ++;
+				priv(dev)->stats.rx_packets ++;
 			} else
-				priv->stats.rx_dropped ++;
+				priv(dev)->stats.rx_dropped ++;
 		} else {
 			printk(KERN_WARNING "%s: %s\n", dev->name,
 				(rbd.rbd_status & RBD_EOF) ? "oversized packet" : "acnt not valid");
-			priv->stats.rx_dropped ++;
+			priv(dev)->stats.rx_dropped ++;
 		}
 
-		nexttail = ether1_inw (dev, priv->rx_tail, rfd_t, rfd_link, NORMALIRQS);
+		nexttail = ether1_readw(dev, priv(dev)->rx_tail, rfd_t, rfd_link, NORMALIRQS);
 		/* nexttail should be rx_head */
-		if (nexttail != priv->rx_head)
+		if (nexttail != priv(dev)->rx_head)
 			printk(KERN_ERR "%s: receiver buffer chaining error (%04X != %04X)\n",
-				dev->name, nexttail, priv->rx_head);
-		ether1_outw (dev, RFD_CMDEL | RFD_CMDSUSPEND, nexttail, rfd_t, rfd_command, NORMALIRQS);
-		ether1_outw (dev, 0, priv->rx_tail, rfd_t, rfd_command, NORMALIRQS);
-		ether1_outw (dev, 0, priv->rx_tail, rfd_t, rfd_status, NORMALIRQS);
-		ether1_outw (dev, 0, priv->rx_tail, rfd_t, rfd_rbdoffset, NORMALIRQS);
+				dev->name, nexttail, priv(dev)->rx_head);
+		ether1_writew(dev, RFD_CMDEL | RFD_CMDSUSPEND, nexttail, rfd_t, rfd_command, NORMALIRQS);
+		ether1_writew(dev, 0, priv(dev)->rx_tail, rfd_t, rfd_command, NORMALIRQS);
+		ether1_writew(dev, 0, priv(dev)->rx_tail, rfd_t, rfd_status, NORMALIRQS);
+		ether1_writew(dev, 0, priv(dev)->rx_tail, rfd_t, rfd_rbdoffset, NORMALIRQS);
 	
-		priv->rx_tail = nexttail;
-		priv->rx_head = ether1_inw (dev, priv->rx_head, rfd_t, rfd_link, NORMALIRQS);
+		priv(dev)->rx_tail = nexttail;
+		priv(dev)->rx_head = ether1_readw(dev, priv(dev)->rx_head, rfd_t, rfd_link, NORMALIRQS);
 	} while (1);
 }
 
@@ -919,48 +912,47 @@
 ether1_interrupt (int irq, void *dev_id, struct pt_regs *regs)
 {
 	struct net_device *dev = (struct net_device *)dev_id;
-	struct ether1_priv *priv = netdev_priv(dev);
 	int status;
 
-	status = ether1_inw (dev, SCB_ADDR, scb_t, scb_status, NORMALIRQS);
+	status = ether1_readw(dev, SCB_ADDR, scb_t, scb_status, NORMALIRQS);
 
 	if (status) {
-		ether1_outw(dev, status & (SCB_STRNR | SCB_STCNA | SCB_STFR | SCB_STCX),
+		ether1_writew(dev, status & (SCB_STRNR | SCB_STCNA | SCB_STFR | SCB_STCX),
 			    SCB_ADDR, scb_t, scb_command, NORMALIRQS);
-		outb (CTRL_CA | CTRL_ACK, REG_CONTROL);
+		writeb(CTRL_CA | CTRL_ACK, REG_CONTROL);
 		if (status & SCB_STCX) {
 			ether1_xmit_done (dev);
 		}
 		if (status & SCB_STCNA) {
-			if (priv->resetting == 0)
+			if (priv(dev)->resetting == 0)
 				printk (KERN_WARNING "%s: CU went not ready ???\n", dev->name);
 			else
-				priv->resetting += 1;
-			if (ether1_inw (dev, SCB_ADDR, scb_t, scb_cbl_offset, NORMALIRQS)
+				priv(dev)->resetting += 1;
+			if (ether1_readw(dev, SCB_ADDR, scb_t, scb_cbl_offset, NORMALIRQS)
 					!= (unsigned short)I82586_NULL) {
-				ether1_outw (dev, SCB_CMDCUCSTART, SCB_ADDR, scb_t, scb_command, NORMALIRQS);
-				outb (CTRL_CA, REG_CONTROL);
+				ether1_writew(dev, SCB_CMDCUCSTART, SCB_ADDR, scb_t, scb_command, NORMALIRQS);
+				writeb(CTRL_CA, REG_CONTROL);
 			}
-			if (priv->resetting == 2)
-				priv->resetting = 0;
+			if (priv(dev)->resetting == 2)
+				priv(dev)->resetting = 0;
 		}
 		if (status & SCB_STFR) {
 			ether1_recv_done (dev);
 		}
 		if (status & SCB_STRNR) {
-			if (ether1_inw (dev, SCB_ADDR, scb_t, scb_status, NORMALIRQS) & SCB_STRXSUSP) {
+			if (ether1_readw(dev, SCB_ADDR, scb_t, scb_status, NORMALIRQS) & SCB_STRXSUSP) {
 				printk (KERN_WARNING "%s: RU went not ready: RU suspended\n", dev->name);
-				ether1_outw (dev, SCB_CMDRXRESUME, SCB_ADDR, scb_t, scb_command, NORMALIRQS);
-				outb (CTRL_CA, REG_CONTROL);
-				priv->stats.rx_dropped ++;	/* we suspended due to lack of buffer space */
+				ether1_writew(dev, SCB_CMDRXRESUME, SCB_ADDR, scb_t, scb_command, NORMALIRQS);
+				writeb(CTRL_CA, REG_CONTROL);
+				priv(dev)->stats.rx_dropped ++;	/* we suspended due to lack of buffer space */
 			} else
 				printk(KERN_WARNING "%s: RU went not ready: %04X\n", dev->name,
-					ether1_inw (dev, SCB_ADDR, scb_t, scb_status, NORMALIRQS));
-			printk (KERN_WARNING "RU ptr = %04X\n", ether1_inw (dev, SCB_ADDR, scb_t, scb_rfa_offset,
+					ether1_readw(dev, SCB_ADDR, scb_t, scb_status, NORMALIRQS));
+			printk (KERN_WARNING "RU ptr = %04X\n", ether1_readw(dev, SCB_ADDR, scb_t, scb_rfa_offset,
 						NORMALIRQS));
 		}
 	} else
-		outb (CTRL_ACK, REG_CONTROL);
+		writeb(CTRL_ACK, REG_CONTROL);
 
 	return IRQ_HANDLED;
 }
@@ -978,8 +970,7 @@
 static struct net_device_stats *
 ether1_getstats (struct net_device *dev)
 {
-	struct ether1_priv *priv = netdev_priv(dev);
-	return &priv->stats;
+	return &priv(dev)->stats;
 }
 
 /*
@@ -1008,40 +999,42 @@
 ether1_probe(struct expansion_card *ec, const struct ecard_id *id)
 {
 	struct net_device *dev;
-	struct ether1_priv *priv;
 	int i, ret = 0;
 
 	ether1_banner();
 
+	ret = ecard_request_resources(ec);
+	if (ret)
+		goto out;
+
 	dev = alloc_etherdev(sizeof(struct ether1_priv));
 	if (!dev) {
 		ret = -ENOMEM;
-		goto out;
+		goto release;
 	}
 
 	SET_MODULE_OWNER(dev);
+	SET_NETDEV_DEV(dev, &ec->dev);
 
-	dev->base_addr	= ecard_address(ec, ECARD_IOC, ECARD_FAST);
-	dev->irq	= ec->irq;
-
-	/*
-	 * these will not fail - the nature of the bus ensures this
-	 */
-	request_region(dev->base_addr, 16, dev->name);
-	request_region(dev->base_addr + 0x800, 4096, dev->name);
+	dev->irq = ec->irq;
+	priv(dev)->base = ioremap(ecard_resource_start(ec, ECARD_RES_IOCFAST),
+				  ecard_resource_len(ec, ECARD_RES_IOCFAST));
+	if (!priv(dev)->base) {
+		ret = -ENOMEM;
+		goto free;
+	}
 
-	priv = netdev_priv(dev);
-	if ((priv->bus_type = ether1_reset(dev)) == 0) {
+	if ((priv(dev)->bus_type = ether1_reset(dev)) == 0) {
 		ret = -ENODEV;
-		goto release;
+		goto free;
 	}
 
 	for (i = 0; i < 6; i++)
-		dev->dev_addr[i] = inb(IDPROM_ADDRESS + i);
+		dev->dev_addr[i] = readb(IDPROM_ADDRESS + (i << 2));
 
 	if (ether1_init_2(dev)) {
 		ret = -ENODEV;
-		goto release;
+		goto free;
 	}
 
 	dev->open		= ether1_open;
@@ -1054,7 +1047,7 @@
 
 	ret = register_netdev(dev);
 	if (ret)
-		goto release;
+		goto free;
 
 	printk(KERN_INFO "%s: ether1 in slot %d, ",
 		dev->name, ec->slot_no);
@@ -1065,11 +1058,13 @@
 	ecard_set_drvdata(ec, dev);
 	return 0;
 
-release:
-	release_region(dev->base_addr, 16);
-	release_region(dev->base_addr + 0x800, 4096);
+ free:
+	if (priv(dev)->base)
+		iounmap(priv(dev)->base);
 	free_netdev(dev);
-out:
+ release:
+	ecard_release_resources(ec);
+ out:
 	return ret;
 }
 
@@ -1080,10 +1075,9 @@
 	ecard_set_drvdata(ec, NULL);	
 
 	unregister_netdev(dev);
-
-	release_region(dev->base_addr, 16);
-	release_region(dev->base_addr + 0x800, 4096);
+	iounmap(priv(dev)->base);
 	free_netdev(dev);
+	ecard_release_resources(ec);
 }
 
 static const struct ecard_id ether1_ids[] = {
diff -Nru a/drivers/net/arm/ether1.h b/drivers/net/arm/ether1.h
--- a/drivers/net/arm/ether1.h	2005-03-11 12:51:52 -08:00
+++ b/drivers/net/arm/ether1.h	2005-03-11 12:51:52 -08:00
@@ -19,22 +19,25 @@
 #define NET_DEBUG 0
 #endif
 
+#define priv(dev)	((struct ether1_priv *)netdev_priv(dev))
+
 /* Page register */
-#define REG_PAGE	(dev->base_addr + 0x00)
+#define REG_PAGE	(priv(dev)->base + 0x0000)
 
 /* Control register */
-#define REG_CONTROL	(dev->base_addr + 0x01)
+#define REG_CONTROL	(priv(dev)->base + 0x0004)
 #define CTRL_RST	0x01
 #define CTRL_LOOPBACK	0x02
 #define CTRL_CA		0x04
 #define CTRL_ACK	0x08
 
-#define ETHER1_RAM	(dev->base_addr + 0x800)
+#define ETHER1_RAM	(priv(dev)->base + 0x2000)
 
 /* HW address */
-#define IDPROM_ADDRESS	(dev->base_addr + 0x09)
+#define IDPROM_ADDRESS	(priv(dev)->base + 0x0024)
 
 struct ether1_priv {
+	void __iomem *base;
 	struct net_device_stats stats;
 	unsigned int tx_link;
 	unsigned int tx_head;
diff -Nru a/drivers/net/arm/ether3.c b/drivers/net/arm/ether3.c
--- a/drivers/net/arm/ether3.c	2005-03-11 12:51:51 -08:00
+++ b/drivers/net/arm/ether3.c	2005-03-11 12:51:51 -08:00
@@ -78,8 +78,8 @@
 static unsigned int net_debug = NET_DEBUG;
 
 static void	ether3_setmulticastlist(struct net_device *dev);
-static int	ether3_rx(struct net_device *dev, struct dev_priv *priv, unsigned int maxcnt);
-static void	ether3_tx(struct net_device *dev, struct dev_priv *priv);
+static int	ether3_rx(struct net_device *dev, unsigned int maxcnt);
+static void	ether3_tx(struct net_device *dev);
 static int	ether3_open (struct net_device *dev);
 static int	ether3_sendpacket (struct sk_buff *skb, struct net_device *dev);
 static irqreturn_t ether3_interrupt (int irq, void *dev_id, struct pt_regs *regs);
@@ -104,33 +104,32 @@
  * The SEEQ8005 doesn't like us writing to its registers
  * too quickly.
  */
-static inline void ether3_outb(int v, const int r)
+static inline void ether3_outb(int v, const void __iomem *r)
 {
-	outb(v, r);
+	writeb(v, r);
 	udelay(1);
 }
 
-static inline void ether3_outw(int v, const int r)
+static inline void ether3_outw(int v, const void __iomem *r)
 {
-	outw(v, r);
+	writew(v, r);
 	udelay(1);
 }
-#define ether3_inb(r)		({ unsigned int __v = inb((r)); udelay(1); __v; })
-#define ether3_inw(r)		({ unsigned int __v = inw((r)); udelay(1); __v; })
+#define ether3_inb(r)		({ unsigned int __v = readb((r)); udelay(1); __v; })
+#define ether3_inw(r)		({ unsigned int __v = readw((r)); udelay(1); __v; })
 
 static int
 ether3_setbuffer(struct net_device *dev, buffer_rw_t read, int start)
 {
-	struct dev_priv *priv = netdev_priv(dev);
 	int timeout = 1000;
 
-	ether3_outw(priv->regs.config1 | CFG1_LOCBUFMEM, REG_CONFIG1);
-	ether3_outw(priv->regs.command | CMD_FIFOWRITE, REG_COMMAND);
+	ether3_outw(priv(dev)->regs.config1 | CFG1_LOCBUFMEM, REG_CONFIG1);
+	ether3_outw(priv(dev)->regs.command | CMD_FIFOWRITE, REG_COMMAND);
 
 	while ((ether3_inw(REG_STATUS) & STAT_FIFOEMPTY) == 0) {
 		if (!timeout--) {
 			printk("%s: setbuffer broken\n", dev->name);
-			priv->broken = 1;
+			priv(dev)->broken = 1;
 			return 1;
 		}
 		udelay(1);
@@ -138,9 +137,9 @@
 
 	if (read == buffer_read) {
 		ether3_outw(start, REG_DMAADDR);
-		ether3_outw(priv->regs.command | CMD_FIFOREAD, REG_COMMAND);
+		ether3_outw(priv(dev)->regs.command | CMD_FIFOREAD, REG_COMMAND);
 	} else {
-		ether3_outw(priv->regs.command | CMD_FIFOWRITE, REG_COMMAND);
+		ether3_outw(priv(dev)->regs.command | CMD_FIFOWRITE, REG_COMMAND);
 		ether3_outw(start, REG_DMAADDR);
 	}
 	return 0;
@@ -150,53 +149,50 @@
  * write data to the buffer memory
  */
 #define ether3_writebuffer(dev,data,length)			\
-	outsw(REG_BUFWIN, (data), (length) >> 1)
+	writesw(REG_BUFWIN, (data), (length) >> 1)
 
 #define ether3_writeword(dev,data)				\
-	outw((data), REG_BUFWIN)
+	writew((data), REG_BUFWIN)
 
 #define ether3_writelong(dev,data)	{			\
-	unsigned long reg_bufwin = REG_BUFWIN;			\
-	outw((data), reg_bufwin);				\
-	outw((data) >> 16, reg_bufwin);				\
+	void __iomem *reg_bufwin = REG_BUFWIN;			\
+	writew((data), reg_bufwin);				\
+	writew((data) >> 16, reg_bufwin);			\
 }
 
 /*
  * read data from the buffer memory
  */
 #define ether3_readbuffer(dev,data,length)			\
-	insw(REG_BUFWIN, (data), (length) >> 1)
+	readsw(REG_BUFWIN, (data), (length) >> 1)
 
 #define ether3_readword(dev)					\
-	inw(REG_BUFWIN)
+	readw(REG_BUFWIN)
 
 #define ether3_readlong(dev)	 				\
-	inw(REG_BUFWIN) | (inw(REG_BUFWIN) << 16)
+	readw(REG_BUFWIN) | (readw(REG_BUFWIN) << 16)
 
 /*
  * Switch LED off...
  */
-static void
-ether3_ledoff(unsigned long data)
+static void ether3_ledoff(unsigned long data)
 {
 	struct net_device *dev = (struct net_device *)data;
-	struct dev_priv *priv = netdev_priv(dev);
-	ether3_outw(priv->regs.config2 |= CFG2_CTRLO, REG_CONFIG2);
+	ether3_outw(priv(dev)->regs.config2 |= CFG2_CTRLO, REG_CONFIG2);
 }
 
 /*
  * switch LED on...
  */
-static inline void
-ether3_ledon(struct net_device *dev, struct dev_priv *priv)
+static inline void ether3_ledon(struct net_device *dev)
 {
-	del_timer(&priv->timer);
-	priv->timer.expires = jiffies + HZ / 50; /* leave on for 1/50th second */
-	priv->timer.data = (unsigned long)dev;
-	priv->timer.function = ether3_ledoff;
-	add_timer(&priv->timer);
-	if (priv->regs.config2 & CFG2_CTRLO)
-		ether3_outw(priv->regs.config2 &= ~CFG2_CTRLO, REG_CONFIG2);
+	del_timer(&priv(dev)->timer);
+	priv(dev)->timer.expires = jiffies + HZ / 50; /* leave on for 1/50th second */
+	priv(dev)->timer.data = (unsigned long)dev;
+	priv(dev)->timer.function = ether3_ledoff;
+	add_timer(&priv(dev)->timer);
+	if (priv(dev)->regs.config2 & CFG2_CTRLO)
+		ether3_outw(priv(dev)->regs.config2 &= ~CFG2_CTRLO, REG_CONFIG2);
 }
 
 /*
@@ -277,43 +273,41 @@
 
 /* ------------------------------------------------------------------------------- */
 
-static int __init
-ether3_init_2(struct net_device *dev)
+static int __init ether3_init_2(struct net_device *dev)
 {
-	struct dev_priv *priv = netdev_priv(dev);
 	int i;
 
-	priv->regs.config1 = CFG1_RECVCOMPSTAT0|CFG1_DMABURST8;
-	priv->regs.config2 = CFG2_CTRLO|CFG2_RECVCRC|CFG2_ERRENCRC;
-	priv->regs.command = 0;
+	priv(dev)->regs.config1 = CFG1_RECVCOMPSTAT0|CFG1_DMABURST8;
+	priv(dev)->regs.config2 = CFG2_CTRLO|CFG2_RECVCRC|CFG2_ERRENCRC;
+	priv(dev)->regs.command = 0;
 
 	/*
 	 * Set up our hardware address
 	 */
-	ether3_outw(priv->regs.config1 | CFG1_BUFSELSTAT0, REG_CONFIG1);
+	ether3_outw(priv(dev)->regs.config1 | CFG1_BUFSELSTAT0, REG_CONFIG1);
 	for (i = 0; i < 6; i++)
 		ether3_outb(dev->dev_addr[i], REG_BUFWIN);
 
 	if (dev->flags & IFF_PROMISC)
-		priv->regs.config1 |= CFG1_RECVPROMISC;
+		priv(dev)->regs.config1 |= CFG1_RECVPROMISC;
 	else if (dev->flags & IFF_MULTICAST)
-		priv->regs.config1 |= CFG1_RECVSPECBRMULTI;
+		priv(dev)->regs.config1 |= CFG1_RECVSPECBRMULTI;
 	else
-		priv->regs.config1 |= CFG1_RECVSPECBROAD;
+		priv(dev)->regs.config1 |= CFG1_RECVSPECBROAD;
 
 	/*
 	 * There is a problem with the NQ8005 in that it occasionally loses the
 	 * last two bytes.  To get round this problem, we receive the CRC as
 	 * well.  That way, if we do lose the last two, then it doesn't matter.
 	 */
-	ether3_outw(priv->regs.config1 | CFG1_TRANSEND, REG_CONFIG1);
+	ether3_outw(priv(dev)->regs.config1 | CFG1_TRANSEND, REG_CONFIG1);
 	ether3_outw((TX_END>>8) - 1, REG_BUFWIN);
-	ether3_outw(priv->rx_head, REG_RECVPTR);
+	ether3_outw(priv(dev)->rx_head, REG_RECVPTR);
 	ether3_outw(0, REG_TRANSMITPTR);
-	ether3_outw(priv->rx_head >> 8, REG_RECVEND);
-	ether3_outw(priv->regs.config2, REG_CONFIG2);
-	ether3_outw(priv->regs.config1 | CFG1_LOCBUFMEM, REG_CONFIG1);
-	ether3_outw(priv->regs.command, REG_COMMAND);
+	ether3_outw(priv(dev)->rx_head >> 8, REG_RECVEND);
+	ether3_outw(priv(dev)->regs.config2, REG_CONFIG2);
+	ether3_outw(priv(dev)->regs.config1 | CFG1_LOCBUFMEM, REG_CONFIG1);
+	ether3_outw(priv(dev)->regs.command, REG_COMMAND);
 
 	i = ether3_ramtest(dev, 0x5A);
 	if(i)
@@ -330,41 +324,41 @@
 static void
 ether3_init_for_open(struct net_device *dev)
 {
-	struct dev_priv *priv = netdev_priv(dev);
 	int i;
 
-	memset(&priv->stats, 0, sizeof(struct net_device_stats));
+	memset(&priv(dev)->stats, 0, sizeof(struct net_device_stats));
 
 	/* Reset the chip */
 	ether3_outw(CFG2_RESET, REG_CONFIG2);
 	udelay(4);
 
-	priv->regs.command = 0;
+	priv(dev)->regs.command = 0;
 	ether3_outw(CMD_RXOFF|CMD_TXOFF, REG_COMMAND);
-	while (ether3_inw(REG_STATUS) & (STAT_RXON|STAT_TXON));
+	while (ether3_inw(REG_STATUS) & (STAT_RXON|STAT_TXON))
+		barrier();
 
-	ether3_outw(priv->regs.config1 | CFG1_BUFSELSTAT0, REG_CONFIG1);
+	ether3_outw(priv(dev)->regs.config1 | CFG1_BUFSELSTAT0, REG_CONFIG1);
 	for (i = 0; i < 6; i++)
 		ether3_outb(dev->dev_addr[i], REG_BUFWIN);
 
-	priv->tx_head	= 0;
-	priv->tx_tail	= 0;
-	priv->regs.config2 |= CFG2_CTRLO;
-	priv->rx_head	= RX_START;
+	priv(dev)->tx_head	= 0;
+	priv(dev)->tx_tail	= 0;
+	priv(dev)->regs.config2 |= CFG2_CTRLO;
+	priv(dev)->rx_head	= RX_START;
 
-	ether3_outw(priv->regs.config1 | CFG1_TRANSEND, REG_CONFIG1);
+	ether3_outw(priv(dev)->regs.config1 | CFG1_TRANSEND, REG_CONFIG1);
 	ether3_outw((TX_END>>8) - 1, REG_BUFWIN);
-	ether3_outw(priv->rx_head, REG_RECVPTR);
-	ether3_outw(priv->rx_head >> 8, REG_RECVEND);
+	ether3_outw(priv(dev)->rx_head, REG_RECVPTR);
+	ether3_outw(priv(dev)->rx_head >> 8, REG_RECVEND);
 	ether3_outw(0, REG_TRANSMITPTR);
-	ether3_outw(priv->regs.config2, REG_CONFIG2);
-	ether3_outw(priv->regs.config1 | CFG1_LOCBUFMEM, REG_CONFIG1);
+	ether3_outw(priv(dev)->regs.config2, REG_CONFIG2);
+	ether3_outw(priv(dev)->regs.config1 | CFG1_LOCBUFMEM, REG_CONFIG1);
 
 	ether3_setbuffer(dev, buffer_write, 0);
 	ether3_writelong(dev, 0);
 
-	priv->regs.command = CMD_ENINTRX | CMD_ENINTTX;
-	ether3_outw(priv->regs.command | CMD_RXON, REG_COMMAND);
+	priv(dev)->regs.command = CMD_ENINTRX | CMD_ENINTTX;
+	ether3_outw(priv(dev)->regs.command | CMD_RXON, REG_COMMAND);
 }
 
 static inline int
@@ -378,10 +372,10 @@
 	printk(KERN_DEBUG "ether3_probe: write8 [%02X:%02X]", write_high, write_low);
 
 	ether3_outb(write_low, REG_RECVPTR);
-	ether3_outb(write_high, REG_RECVPTR + 1);
+	ether3_outb(write_high, REG_RECVPTR + 4);
 
 	read_low = ether3_inb(REG_RECVPTR);
-	read_high = ether3_inb(REG_RECVPTR + 1);
+	read_high = ether3_inb(REG_RECVPTR + 4);
 
 	printk(", read8 [%02X:%02X]\n", read_high, read_low);
 
@@ -434,16 +428,15 @@
 static int
 ether3_close(struct net_device *dev)
 {
-	struct dev_priv *priv = netdev_priv(dev);
-
 	netif_stop_queue(dev);
 
 	disable_irq(dev->irq);
 
 	ether3_outw(CMD_RXOFF|CMD_TXOFF, REG_COMMAND);
-	priv->regs.command = 0;
-	while (ether3_inw(REG_STATUS) & (STAT_RXON|STAT_TXON));
-	ether3_outb(0x80, REG_CONFIG2 + 1);
+	priv(dev)->regs.command = 0;
+	while (ether3_inw(REG_STATUS) & (STAT_RXON|STAT_TXON))
+		barrier();
+	ether3_outb(0x80, REG_CONFIG2 + 4);
 	ether3_outw(0, REG_COMMAND);
 
 	free_irq(dev->irq, dev);
@@ -457,8 +450,7 @@
  */
 static struct net_device_stats *ether3_getstats(struct net_device *dev)
 {
-	struct dev_priv *priv = netdev_priv(dev);
-	return &priv->stats;
+	return &priv(dev)->stats;
 }
 
 /*
@@ -469,28 +461,24 @@
  */
 static void ether3_setmulticastlist(struct net_device *dev)
 {
-	struct dev_priv *priv = netdev_priv(dev);
-
-	priv->regs.config1 &= ~CFG1_RECVPROMISC;
+	priv(dev)->regs.config1 &= ~CFG1_RECVPROMISC;
 
 	if (dev->flags & IFF_PROMISC) {
 		/* promiscuous mode */
-		priv->regs.config1 |= CFG1_RECVPROMISC;
+		priv(dev)->regs.config1 |= CFG1_RECVPROMISC;
 	} else if (dev->flags & IFF_ALLMULTI) {
-		priv->regs.config1 |= CFG1_RECVSPECBRMULTI;
+		priv(dev)->regs.config1 |= CFG1_RECVSPECBRMULTI;
 	} else
-		priv->regs.config1 |= CFG1_RECVSPECBROAD;
+		priv(dev)->regs.config1 |= CFG1_RECVSPECBROAD;
 
-	ether3_outw(priv->regs.config1 | CFG1_LOCBUFMEM, REG_CONFIG1);
+	ether3_outw(priv(dev)->regs.config1 | CFG1_LOCBUFMEM, REG_CONFIG1);
 }
 
-static void
-ether3_timeout(struct net_device *dev)
+static void ether3_timeout(struct net_device *dev)
 {
-	struct dev_priv *priv = netdev_priv(dev);
 	unsigned long flags;
 
-	del_timer(&priv->timer);
+	del_timer(&priv(dev)->timer);
 
 	local_irq_save(flags);
 	printk(KERN_ERR "%s: transmit timed out, network cable problem?\n", dev->name);
@@ -499,15 +487,15 @@
 	printk(KERN_ERR "%s: { rpr=%04X rea=%04X tpr=%04X }\n", dev->name,
 		ether3_inw(REG_RECVPTR), ether3_inw(REG_RECVEND), ether3_inw(REG_TRANSMITPTR));
 	printk(KERN_ERR "%s: tx head=%X tx tail=%X\n", dev->name,
-		priv->tx_head, priv->tx_tail);
-	ether3_setbuffer(dev, buffer_read, priv->tx_tail);
+		priv(dev)->tx_head, priv(dev)->tx_tail);
+	ether3_setbuffer(dev, buffer_read, priv(dev)->tx_tail);
 	printk(KERN_ERR "%s: packet status = %08X\n", dev->name, ether3_readlong(dev));
 	local_irq_restore(flags);
 
-	priv->regs.config2 |= CFG2_CTRLO;
-	priv->stats.tx_errors += 1;
-	ether3_outw(priv->regs.config2, REG_CONFIG2);
-	priv->tx_head = priv->tx_tail = 0;
+	priv(dev)->regs.config2 |= CFG2_CTRLO;
+	priv(dev)->stats.tx_errors += 1;
+	ether3_outw(priv(dev)->regs.config2, REG_CONFIG2);
+	priv(dev)->tx_head = priv(dev)->tx_tail = 0;
 
 	netif_wake_queue(dev);
 }
@@ -518,14 +506,13 @@
 static int
 ether3_sendpacket(struct sk_buff *skb, struct net_device *dev)
 {
-	struct dev_priv *priv = netdev_priv(dev);
 	unsigned long flags;
 	unsigned int length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
 	unsigned int ptr, next_ptr;
 
-	if (priv->broken) {
+	if (priv(dev)->broken) {
 		dev_kfree_skb(skb);
-		priv->stats.tx_dropped ++;
+		priv(dev)->stats.tx_dropped ++;
 		netif_start_queue(dev);
 		return 0;
 	}
@@ -537,18 +524,18 @@
 			goto out;
 	}
 
-	next_ptr = (priv->tx_head + 1) & 15;
+	next_ptr = (priv(dev)->tx_head + 1) & 15;
 
 	local_irq_save(flags);
 
-	if (priv->tx_tail == next_ptr) {
+	if (priv(dev)->tx_tail == next_ptr) {
 		local_irq_restore(flags);
 		return 1;	/* unable to queue */
 	}
 
 	dev->trans_start = jiffies;
-	ptr		 = 0x600 * priv->tx_head;
-	priv->tx_head	 = next_ptr;
+	ptr		 = 0x600 * priv(dev)->tx_head;
+	priv(dev)->tx_head = next_ptr;
 	next_ptr	*= 0x600;
 
 #define TXHDR_FLAGS (TXHDR_TRANSMIT|TXHDR_CHAINCONTINUE|TXHDR_DATAFOLLOWS|TXHDR_ENSUCCESS)
@@ -563,19 +550,19 @@
 	ether3_setbuffer(dev, buffer_write, ptr);
 	ether3_writeword(dev, htons((ptr + length + 4)));
 	ether3_writeword(dev, TXHDR_FLAGS >> 16);
-	ether3_ledon(dev, priv);
+	ether3_ledon(dev);
 
 	if (!(ether3_inw(REG_STATUS) & STAT_TXON)) {
 		ether3_outw(ptr, REG_TRANSMITPTR);
-		ether3_outw(priv->regs.command | CMD_TXON, REG_COMMAND);
+		ether3_outw(priv(dev)->regs.command | CMD_TXON, REG_COMMAND);
 	}
 
-	next_ptr = (priv->tx_head + 1) & 15;
+	next_ptr = (priv(dev)->tx_head + 1) & 15;
 	local_irq_restore(flags);
 
 	dev_kfree_skb(skb);
 
-	if (priv->tx_tail == next_ptr)
+	if (priv(dev)->tx_tail == next_ptr)
 		netif_stop_queue(dev);
 
  out:
@@ -586,7 +573,6 @@
 ether3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
 	struct net_device *dev = (struct net_device *)dev_id;
-	struct dev_priv *priv;
 	unsigned int status, handled = IRQ_NONE;
 
 #if NET_DEBUG > 1
@@ -594,19 +580,17 @@
 		printk("eth3irq: %d ", irq);
 #endif
 
-	priv = netdev_priv(dev);
-
 	status = ether3_inw(REG_STATUS);
 
 	if (status & STAT_INTRX) {
-		ether3_outw(CMD_ACKINTRX | priv->regs.command, REG_COMMAND);
-		ether3_rx(dev, priv, 12);
+		ether3_outw(CMD_ACKINTRX | priv(dev)->regs.command, REG_COMMAND);
+		ether3_rx(dev, 12);
 		handled = IRQ_HANDLED;
 	}
 
 	if (status & STAT_INTTX) {
-		ether3_outw(CMD_ACKINTTX | priv->regs.command, REG_COMMAND);
-		ether3_tx(dev, priv);
+		ether3_outw(CMD_ACKINTTX | priv(dev)->regs.command, REG_COMMAND);
+		ether3_tx(dev);
 		handled = IRQ_HANDLED;
 	}
 
@@ -620,11 +604,11 @@
 /*
  * If we have a good packet(s), get it/them out of the buffers.
  */
-static int
-ether3_rx(struct net_device *dev, struct dev_priv *priv, unsigned int maxcnt)
+static int ether3_rx(struct net_device *dev, unsigned int maxcnt)
 {
-	unsigned int next_ptr = priv->rx_head, received = 0;
-	ether3_ledon(dev, priv);
+	unsigned int next_ptr = priv(dev)->rx_head, received = 0;
+
+	ether3_ledon(dev);
 
 	do {
 		unsigned int this_ptr, status;
@@ -653,12 +637,12 @@
 
 if (next_ptr < RX_START || next_ptr >= RX_END) {
  int i;
- printk("%s: bad next pointer @%04X: ", dev->name, priv->rx_head);
+ printk("%s: bad next pointer @%04X: ", dev->name, priv(dev)->rx_head);
  printk("%02X %02X %02X %02X ", next_ptr >> 8, next_ptr & 255, status & 255, status >> 8);
  for (i = 2; i < 14; i++)
    printk("%02X ", addrs[i]);
  printk("\n");
- next_ptr = priv->rx_head;
+ next_ptr = priv(dev)->rx_head;
  break;
 }
 		/*
@@ -695,7 +679,7 @@
 			} else
 				goto dropping;
 		} else {
-			struct net_device_stats *stats = &priv->stats;
+			struct net_device_stats *stats = &priv(dev)->stats;
 			ether3_outw(next_ptr >> 8, REG_RECVEND);
 			if (status & RXSTAT_OVERSIZE)	  stats->rx_over_errors ++;
 			if (status & RXSTAT_CRCERROR)	  stats->rx_crc_errors ++;
@@ -707,16 +691,16 @@
 	while (-- maxcnt);
 
 done:
-	priv->stats.rx_packets += received;
-	priv->rx_head = next_ptr;
+	priv(dev)->stats.rx_packets += received;
+	priv(dev)->rx_head = next_ptr;
 	/*
 	 * If rx went off line, then that means that the buffer may be full.  We
 	 * have dropped at least one packet.
 	 */
 	if (!(ether3_inw(REG_STATUS) & STAT_RXON)) {
-		priv->stats.rx_dropped ++;
+		priv(dev)->stats.rx_dropped ++;
     		ether3_outw(next_ptr, REG_RECVPTR);
-		ether3_outw(priv->regs.command | CMD_RXON, REG_COMMAND);
+		ether3_outw(priv(dev)->regs.command | CMD_RXON, REG_COMMAND);
 	}
 
 	return maxcnt;
@@ -732,7 +716,7 @@
 		last_warned = jiffies;
 		printk("%s: memory squeeze, dropping packet.\n", dev->name);
 	}
-	priv->stats.rx_dropped ++;
+	priv(dev)->stats.rx_dropped ++;
 	goto done;
 	}
 }
@@ -740,10 +724,9 @@
 /*
  * Update stats for the transmitted packet(s)
  */
-static void
-ether3_tx(struct net_device *dev, struct dev_priv *priv)
+static void ether3_tx(struct net_device *dev)
 {
-	unsigned int tx_tail = priv->tx_tail;
+	unsigned int tx_tail = priv(dev)->tx_tail;
 	int max_work = 14;
 
 	do {
@@ -766,18 +749,20 @@
 		 * Update errors
 		 */
 		if (!(status & (TXSTAT_BABBLED | TXSTAT_16COLLISIONS)))
-			priv->stats.tx_packets++;
+			priv(dev)->stats.tx_packets++;
 		else {
-			priv->stats.tx_errors ++;
-			if (status & TXSTAT_16COLLISIONS) priv->stats.collisions += 16;
-			if (status & TXSTAT_BABBLED) priv->stats.tx_fifo_errors ++;
+			priv(dev)->stats.tx_errors ++;
+			if (status & TXSTAT_16COLLISIONS)
+				priv(dev)->stats.collisions += 16;
+			if (status & TXSTAT_BABBLED)
+				priv(dev)->stats.tx_fifo_errors ++;
 		}
 
 		tx_tail = (tx_tail + 1) & 15;
 	} while (--max_work);
 
-	if (priv->tx_tail != tx_tail) {
-		priv->tx_tail = tx_tail;
+	if (priv(dev)->tx_tail != tx_tail) {
+		priv(dev)->tx_tail = tx_tail;
 		netif_wake_queue(dev);
 	}
 }
@@ -790,66 +775,48 @@
 		printk(KERN_INFO "%s", version);
 }
 
-static const char * __init
-ether3_get_dev(struct net_device *dev, struct expansion_card *ec)
-{
-	const char *name = "ether3";
-
-	dev->base_addr = ecard_address(ec, ECARD_MEMC, 0);
-	dev->irq = ec->irq;
-
-	if (ec->cid.manufacturer == MANU_ANT &&
-	    ec->cid.product == PROD_ANT_ETHERB) {
-		dev->base_addr += 0x200;
-		name = "etherb";
-	}
-
-	ec->irqaddr = (volatile unsigned char *)ioaddr(dev->base_addr);
-	ec->irqmask = 0xf0;
-
-	ether3_addr(dev->dev_addr, ec);
-
-	return name;
-}
-
 static int __devinit
 ether3_probe(struct expansion_card *ec, const struct ecard_id *id)
 {
+	const struct ether3_data *data = id->data;
 	struct net_device *dev;
-	struct dev_priv *priv;
-	const char *name;
 	int i, bus_type, ret;
 
 	ether3_banner();
 
+	ret = ecard_request_resources(ec);
+	if (ret)
+		goto out;
+
 	dev = alloc_etherdev(sizeof(struct dev_priv));
 	if (!dev) {
 		ret = -ENOMEM;
-		goto out;
+		goto release;
 	}
 
 	SET_MODULE_OWNER(dev);
+	SET_NETDEV_DEV(dev, &ec->dev);
 
-	name = ether3_get_dev(dev, ec);
-	if (!name) {
-		ret = -ENODEV;
+	priv(dev)->base = ioremap(ecard_resource_start(ec, ECARD_RES_MEMC),
+				  ecard_resource_len(ec, ECARD_RES_MEMC));
+	if (!priv(dev)->base) {
+		ret = -ENOMEM;
 		goto free;
 	}
 
-	/*
-	 * this will not fail - the nature of the bus ensures this
-	 */
-	if (!request_region(dev->base_addr, 128, dev->name)) {
-		ret = -EBUSY;
-		goto free;
-	}
+	ec->irqaddr = priv(dev)->base + data->base_offset;
+	ec->irqmask = 0xf0;
 
-	priv = netdev_priv(dev);
-	init_timer(&priv->timer);
+	priv(dev)->seeq = priv(dev)->base + data->base_offset;
+	dev->irq = ec->irq;
+
+	ether3_addr(dev->dev_addr, ec);
+
+	init_timer(&priv(dev)->timer);
 
 	/* Reset card...
 	 */
-	ether3_outb(0x80, REG_CONFIG2 + 1);
+	ether3_outb(0x80, REG_CONFIG2 + 4);
 	bus_type = BUS_UNKNOWN;
 	udelay(4);
 
@@ -869,13 +836,13 @@
 	case BUS_UNKNOWN:
 		printk(KERN_ERR "%s: unable to identify bus width\n", dev->name);
 		ret = -ENODEV;
-		goto failed;
+		goto free;
 
 	case BUS_8:
 		printk(KERN_ERR "%s: %s found, but is an unsupported "
-			"8-bit card\n", dev->name, name);
+			"8-bit card\n", dev->name, data->name);
 		ret = -ENODEV;
-		goto failed;
+		goto free;
 
 	default:
 		break;
@@ -883,7 +850,7 @@
 
 	if (ether3_init_2(dev)) {
 		ret = -ENODEV;
-		goto failed;
+		goto free;
 	}
 
 	dev->open		= ether3_open;
@@ -896,20 +863,22 @@
 
 	ret = register_netdev(dev);
 	if (ret)
-		goto failed;
+		goto free;
 
-	printk("%s: %s in slot %d, ", dev->name, name, ec->slot_no);
+	printk("%s: %s in slot %d, ", dev->name, data->name, ec->slot_no);
 	for (i = 0; i < 6; i++)
 		printk("%2.2x%c", dev->dev_addr[i], i == 5 ? '\n' : ':');
 
 	ecard_set_drvdata(ec, dev);
 	return 0;
 
-failed:
-	release_region(dev->base_addr, 128);
-free:
+ free:
+	if (priv(dev)->base)
+		iounmap(priv(dev)->base);
 	free_netdev(dev);
-out:
+ release:
+	ecard_release_resources(ec);
+ out:
 	return ret;
 }
 
@@ -920,14 +889,25 @@
 	ecard_set_drvdata(ec, NULL);
 
 	unregister_netdev(dev);
-	release_region(dev->base_addr, 128);
+	iounmap(priv(dev)->base);
 	free_netdev(dev);
+	ecard_release_resources(ec);
 }
 
+static struct ether3_data ether3 = {
+	.name		= "ether3",
+	.base_offset	= 0,
+};
+
+static struct ether3_data etherb = {
+	.name		= "etherb",
+	.base_offset	= 0x800,
+};
+
 static const struct ecard_id ether3_ids[] = {
-	{ MANU_ANT2, PROD_ANT_ETHER3 },
-	{ MANU_ANT,  PROD_ANT_ETHER3 },
-	{ MANU_ANT,  PROD_ANT_ETHERB },
+	{ MANU_ANT2, PROD_ANT_ETHER3, &ether3 },
+	{ MANU_ANT,  PROD_ANT_ETHER3, &ether3 },
+	{ MANU_ANT,  PROD_ANT_ETHERB, &etherb },
 	{ 0xffff, 0xffff }
 };
 
diff -Nru a/drivers/net/arm/ether3.h b/drivers/net/arm/ether3.h
--- a/drivers/net/arm/ether3.h	2005-03-11 12:51:51 -08:00
+++ b/drivers/net/arm/ether3.h	2005-03-11 12:51:51 -08:00
@@ -22,8 +22,10 @@
 #define NET_DEBUG 	0
 #endif
 
+#define priv(dev)	((struct dev_priv *)netdev_priv(dev))
+
 /* Command register definitions & bits */
-#define REG_COMMAND		(dev->base_addr + 0x00)
+#define REG_COMMAND		(priv(dev)->seeq + 0x0000)
 #define CMD_ENINTDMA		0x0001
 #define CMD_ENINTRX		0x0002
 #define CMD_ENINTTX		0x0004
@@ -42,7 +44,7 @@
 #define CMD_FIFOWRITE		0x8000
 
 /* status register */
-#define REG_STATUS		(dev->base_addr + 0x00)
+#define REG_STATUS		(priv(dev)->seeq + 0x0000)
 #define STAT_ENINTSTAT		0x0001
 #define STAT_ENINTRX		0x0002
 #define STAT_ENINTTX		0x0004
@@ -59,7 +61,7 @@
 #define STAT_FIFODIR		0x8000
 
 /* configuration register 1 */
-#define REG_CONFIG1		(dev->base_addr + 0x10)
+#define REG_CONFIG1		(priv(dev)->seeq + 0x0040)
 #define CFG1_BUFSELSTAT0	0x0000
 #define CFG1_BUFSELSTAT1	0x0001
 #define CFG1_BUFSELSTAT2	0x0002
@@ -92,7 +94,7 @@
 #define CFG1_RECVCOMPSTAT5	0x2000
 
 /* configuration register 2 */
-#define REG_CONFIG2		(dev->base_addr + 0x20)
+#define REG_CONFIG2		(priv(dev)->seeq + 0x0080)
 #define CFG2_BYTESWAP		0x0001
 #define CFG2_ERRENCRC		0x0008
 #define CFG2_ERRENDRIBBLE	0x0010
@@ -106,15 +108,15 @@
 #define CFG2_CTRLO		0x1000
 #define CFG2_RESET		0x8000
 
-#define REG_RECVEND		(dev->base_addr + 0x30)
+#define REG_RECVEND		(priv(dev)->seeq + 0x00c0)
 
-#define REG_BUFWIN		(dev->base_addr + 0x40)
+#define REG_BUFWIN		(priv(dev)->seeq + 0x0100)
 
-#define REG_RECVPTR		(dev->base_addr + 0x50)
+#define REG_RECVPTR		(priv(dev)->seeq + 0x0140)
 
-#define REG_TRANSMITPTR		(dev->base_addr + 0x60)
+#define REG_TRANSMITPTR		(priv(dev)->seeq + 0x0180)
 
-#define REG_DMAADDR		(dev->base_addr + 0x70)
+#define REG_DMAADDR		(priv(dev)->seeq + 0x01c0)
 
 /*
  * Cards transmit/receive headers
@@ -152,6 +154,8 @@
 #define MAX_TX_BUFFERED	10
 
 struct dev_priv {
+    void __iomem *base;
+    void __iomem *seeq;
     struct {
 	unsigned int command;
 	unsigned int config1;
@@ -163,6 +167,11 @@
     struct net_device_stats stats;
     struct timer_list timer;
     int broken;				/* 0 = ok, 1 = something went wrong	 */
+};
+
+struct ether3_data {
+	const char name[8];
+	unsigned long base_offset;
 };
 
 #endif
diff -Nru a/drivers/net/au1000_eth.c b/drivers/net/au1000_eth.c
--- a/drivers/net/au1000_eth.c	2005-03-11 12:51:46 -08:00
+++ b/drivers/net/au1000_eth.c	2005-03-11 12:51:46 -08:00
@@ -1,10 +1,19 @@
 /*
- * Alchemy Semi Au1000 ethernet driver
  *
- * Copyright 2001 MontaVista Software Inc.
+ * Alchemy Au1x00 ethernet driver
+ *
+ * Copyright 2001,2002,2003 MontaVista Software Inc.
+ * Copyright 2002 TimeSys Corp.
+ * Added ethtool/mii-tool support,
+ * Copyright 2004 Matt Porter <mporter@kernel.crashing.org>
+ * Update: 2004 Bjoern Riemer, riemer@fokus.fraunhofer.de 
+ * or riemer@riemer-nt.de: fixed the link beat detection with 
+ * ioctls (SIOCGMIIPHY)
  * Author: MontaVista Software, Inc.
  *         	ppopov@mvista.com or source@mvista.com
  *
+ * ########################################################################
+ *
  *  This program is free software; you can distribute it and/or modify it
  *  under the terms of the GNU General Public License (Version 2) as
  *  published by the Free Software Foundation.
@@ -17,46 +26,59 @@
  *  You should have received a copy of the GNU General Public License along
  *  with this program; if not, write to the Free Software Foundation, Inc.,
  *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ *
+ * 
  */
-#include <linux/config.h>
 
 #include <linux/module.h>
 #include <linux/kernel.h>
+#include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/timer.h>
 #include <linux/errno.h>
 #include <linux/in.h>
 #include <linux/ioport.h>
+#include <linux/bitops.h>
 #include <linux/slab.h>
 #include <linux/interrupt.h>
 #include <linux/pci.h>
 #include <linux/init.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
+#include <linux/ethtool.h>
+#include <linux/mii.h>
 #include <linux/skbuff.h>
 #include <linux/delay.h>
-#include <linux/crc32.h>
-#include <linux/bitops.h>
-
 #include <asm/mipsregs.h>
 #include <asm/irq.h>
 #include <asm/io.h>
-#include <asm/au1000.h>
+#include <asm/processor.h>
 
+#include <asm/mach-au1x00/au1000.h>
+#include <asm/cpu.h>
 #include "au1000_eth.h"
 
 #ifdef AU1000_ETH_DEBUG
-static int au1000_debug = 10;
+static int au1000_debug = 5;
 #else
 static int au1000_debug = 3;
 #endif
 
+#define DRV_NAME	"au1000eth"
+#define DRV_VERSION	"1.5"
+#define DRV_AUTHOR	"Pete Popov <ppopov@embeddedalley.com>"
+#define DRV_DESC	"Au1xxx on-chip Ethernet driver"
+
+MODULE_AUTHOR(DRV_AUTHOR);
+MODULE_DESCRIPTION(DRV_DESC);
+MODULE_LICENSE("GPL");
+
 // prototypes
-static void *dma_alloc(size_t, dma_addr_t *);
-static void dma_free(void *, size_t);
 static void hard_stop(struct net_device *);
 static void enable_rx_tx(struct net_device *dev);
-static int __init au1000_probe1(long, int, int);
+static struct net_device * au1000_probe(u32 ioaddr, int irq, int port_num);
 static int au1000_init(struct net_device *);
 static int au1000_open(struct net_device *);
 static int au1000_close(struct net_device *);
@@ -78,8 +100,7 @@
 // externs
 extern  void ack_rise_edge_irq(unsigned int);
 extern int get_ethernet_addr(char *ethernet_addr);
-extern inline void str2eaddr(unsigned char *ea, unsigned char *str);
-extern inline unsigned char str2hexnum(unsigned char c);
+extern void str2eaddr(unsigned char *ea, unsigned char *str);
 extern char * __init prom_getcmdline(void);
 
 /*
@@ -97,29 +118,6 @@
  * complete immediately.
  */
 
-
-/*
- * Base address and interrupt of the Au1xxx ethernet macs
- */
-static struct {
-	unsigned int port;
-	int irq;
-} au1000_iflist[NUM_INTERFACES] = {
-		{AU1000_ETH0_BASE, AU1000_ETH0_IRQ}, 
-		{AU1000_ETH1_BASE, AU1000_ETH1_IRQ}
-	},
-  au1500_iflist[NUM_INTERFACES] = {
-		{AU1500_ETH0_BASE, AU1000_ETH0_IRQ}, 
-		{AU1500_ETH1_BASE, AU1000_ETH1_IRQ}
-	},
-  au1100_iflist[NUM_INTERFACES] = {
-		{AU1000_ETH0_BASE, AU1000_ETH0_IRQ}, 
-		{0, 0}
-	};
-
-static char version[] __devinitdata =
-    "au1000eth.c:1.0 ppopov@mvista.com\n";
-
 /* These addresses are only used if yamon doesn't tell us what
  * the mac address is, and the mac address is not passed on the
  * command line.
@@ -135,18 +133,36 @@
 #define cpu_to_dma32 cpu_to_be32
 #define dma32_to_cpu be32_to_cpu
 
+struct au1000_private *au_macs[NUM_ETH_INTERFACES];
 
 /* FIXME 
  * All of the PHY code really should be detached from the MAC 
  * code.
  */
 
+/* Default advertise */
+#define GENMII_DEFAULT_ADVERTISE \
+	ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full | \
+	ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full | \
+	ADVERTISED_Autoneg
+
+#define GENMII_DEFAULT_FEATURES \
+	SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full | \
+	SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full | \
+	SUPPORTED_Autoneg
+
+static char *phy_link[] = 
+{	"unknown", 
+	"10Base2", "10BaseT", 
+	"AUI",
+	"100BaseT", "100BaseTX", "100BaseFX"
+};
+
 int bcm_5201_init(struct net_device *dev, int phy_addr)
 {
 	s16 data;
 	
 	/* Stop auto-negotiation */
-	//printk("bcm_5201_init\n");
 	data = mdio_read(dev, phy_addr, MII_CONTROL);
 	mdio_write(dev, phy_addr, MII_CONTROL, data & ~MII_CNTL_AUTO);
 
@@ -161,17 +177,8 @@
 	data |= MII_CNTL_RST_AUTO | MII_CNTL_AUTO;
 	mdio_write(dev, phy_addr, MII_CONTROL, data);
 
-	/* Enable TX LED instead of FDX */
-	data = mdio_read(dev, phy_addr, MII_INT);
-	data &= ~MII_FDX_LED;
-	mdio_write(dev, phy_addr, MII_INT, data);
-
-	/* Enable TX LED instead of FDX */
-	data = mdio_read(dev, phy_addr, MII_INT);
-	data &= ~MII_FDX_LED;
-	mdio_write(dev, phy_addr, MII_INT, data);
-
-	if (au1000_debug > 4) dump_mii(dev, phy_addr);
+	if (au1000_debug > 4) 
+		dump_mii(dev, phy_addr);
 	return 0;
 }
 
@@ -179,7 +186,6 @@
 {
 	s16 mii_control, timeout;
 	
-	//printk("bcm_5201_reset\n");
 	mii_control = mdio_read(dev, phy_addr, MII_CONTROL);
 	mdio_write(dev, phy_addr, MII_CONTROL, mii_control | MII_CNTL_RESET);
 	mdelay(1);
@@ -242,12 +248,16 @@
 		printk("lsi_80227_init\n");
 
 	/* restart auto-negotiation */
-	mdio_write(dev, phy_addr, 0, 0x3200);
-
+	mdio_write(dev, phy_addr, MII_CONTROL,
+		   MII_CNTL_F100 | MII_CNTL_AUTO | MII_CNTL_RST_AUTO); // | MII_CNTL_FDX);
 	mdelay(1);
 
 	/* set up LEDs to correct display */
+#ifdef CONFIG_MIPS_MTX1
+	mdio_write(dev, phy_addr, 17, 0xff80);
+#else
 	mdio_write(dev, phy_addr, 17, 0xffc0);
+#endif
 
 	if (au1000_debug > 4)
 		dump_mii(dev, phy_addr);
@@ -294,9 +304,9 @@
 	mii_data = mdio_read(dev, aup->phy_addr, MII_STATUS);
 	if (mii_data & MII_STAT_LINK) {
 		*link = 1;
-		mii_data = mdio_read(dev, aup->phy_addr, MII_LSI_STAT);
-		if (mii_data & MII_LSI_STAT_SPD) {
-			if (mii_data & MII_LSI_STAT_FDX) {
+		mii_data = mdio_read(dev, aup->phy_addr, MII_LSI_PHY_STAT);
+		if (mii_data & MII_LSI_PHY_STAT_SPD) {
+			if (mii_data & MII_LSI_PHY_STAT_FDX) {
 				*speed = IF_PORT_100BASEFX;
 				dev->if_port = IF_PORT_100BASEFX;
 			}
@@ -337,12 +347,396 @@
 	return 0;
 }
 
+int am79c874_init(struct net_device *dev, int phy_addr)
+{
+	s16 data;
+
+	/* 79c874 has quit resembled bit assignments to BCM5201 */
+	if (au1000_debug > 4)
+		printk("am79c847_init\n");
+
+	/* Stop auto-negotiation */
+	data = mdio_read(dev, phy_addr, MII_CONTROL);
+	mdio_write(dev, phy_addr, MII_CONTROL, data & ~MII_CNTL_AUTO);
+
+	/* Set advertisement to 10/100 and Half/Full duplex
+	 * (full capabilities) */
+	data = mdio_read(dev, phy_addr, MII_ANADV);
+	data |= MII_NWAY_TX | MII_NWAY_TX_FDX | MII_NWAY_T_FDX | MII_NWAY_T;
+	mdio_write(dev, phy_addr, MII_ANADV, data);
+	
+	/* Restart auto-negotiation */
+	data = mdio_read(dev, phy_addr, MII_CONTROL);
+	data |= MII_CNTL_RST_AUTO | MII_CNTL_AUTO;
+
+	mdio_write(dev, phy_addr, MII_CONTROL, data);
+
+	if (au1000_debug > 4) dump_mii(dev, phy_addr);
+	return 0;
+}
+
+int am79c874_reset(struct net_device *dev, int phy_addr)
+{
+	s16 mii_control, timeout;
+	
+	if (au1000_debug > 4)
+		printk("am79c874_reset\n");
+
+	mii_control = mdio_read(dev, phy_addr, MII_CONTROL);
+	mdio_write(dev, phy_addr, MII_CONTROL, mii_control | MII_CNTL_RESET);
+	mdelay(1);
+	for (timeout = 100; timeout > 0; --timeout) {
+		mii_control = mdio_read(dev, phy_addr, MII_CONTROL);
+		if ((mii_control & MII_CNTL_RESET) == 0)
+			break;
+		mdelay(1);
+	}
+	if (mii_control & MII_CNTL_RESET) {
+		printk(KERN_ERR "%s PHY reset timeout !\n", dev->name);
+		return -1;
+	}
+	return 0;
+}
+
+int 
+am79c874_status(struct net_device *dev, int phy_addr, u16 *link, u16 *speed)
+{
+	u16 mii_data;
+	struct au1000_private *aup;
+
+	// printk("am79c874_status\n");
+	if (!dev) {
+		printk(KERN_ERR "am79c874_status error: NULL dev\n");
+		return -1;
+	}
+
+	aup = (struct au1000_private *) dev->priv;
+	mii_data = mdio_read(dev, aup->phy_addr, MII_STATUS);
+
+	if (mii_data & MII_STAT_LINK) {
+		*link = 1;
+		mii_data = mdio_read(dev, aup->phy_addr, MII_AMD_PHY_STAT);
+		if (mii_data & MII_AMD_PHY_STAT_SPD) {
+			if (mii_data & MII_AMD_PHY_STAT_FDX) {
+				*speed = IF_PORT_100BASEFX;
+				dev->if_port = IF_PORT_100BASEFX;
+			}
+			else {
+				*speed = IF_PORT_100BASETX;
+				dev->if_port = IF_PORT_100BASETX;
+			}
+		}
+		else {
+			*speed = IF_PORT_10BASET;
+			dev->if_port = IF_PORT_10BASET;
+		}
+
+	}
+	else {
+		*link = 0;
+		*speed = 0;
+		dev->if_port = IF_PORT_UNKNOWN;
+	}
+	return 0;
+}
+
+int lxt971a_init(struct net_device *dev, int phy_addr)
+{
+	if (au1000_debug > 4)
+		printk("lxt971a_init\n");
+
+	/* restart auto-negotiation */
+	mdio_write(dev, phy_addr, MII_CONTROL,
+		   MII_CNTL_F100 | MII_CNTL_AUTO | MII_CNTL_RST_AUTO | MII_CNTL_FDX);
+
+	/* set up LEDs to correct display */
+	mdio_write(dev, phy_addr, 20, 0x0422);
+
+	if (au1000_debug > 4)
+		dump_mii(dev, phy_addr);
+	return 0;
+}
+
+int lxt971a_reset(struct net_device *dev, int phy_addr)
+{
+	s16 mii_control, timeout;
+	
+	if (au1000_debug > 4) {
+		printk("lxt971a_reset\n");
+		dump_mii(dev, phy_addr);
+	}
+
+	mii_control = mdio_read(dev, phy_addr, MII_CONTROL);
+	mdio_write(dev, phy_addr, MII_CONTROL, mii_control | MII_CNTL_RESET);
+	mdelay(1);
+	for (timeout = 100; timeout > 0; --timeout) {
+		mii_control = mdio_read(dev, phy_addr, MII_CONTROL);
+		if ((mii_control & MII_CNTL_RESET) == 0)
+			break;
+		mdelay(1);
+	}
+	if (mii_control & MII_CNTL_RESET) {
+		printk(KERN_ERR "%s PHY reset timeout !\n", dev->name);
+		return -1;
+	}
+	return 0;
+}
+
+int
+lxt971a_status(struct net_device *dev, int phy_addr, u16 *link, u16 *speed)
+{
+	u16 mii_data;
+	struct au1000_private *aup;
+
+	if (!dev) {
+		printk(KERN_ERR "lxt971a_status error: NULL dev\n");
+		return -1;
+	}
+	aup = (struct au1000_private *) dev->priv;
+
+	mii_data = mdio_read(dev, aup->phy_addr, MII_STATUS);
+	if (mii_data & MII_STAT_LINK) {
+		*link = 1;
+		mii_data = mdio_read(dev, aup->phy_addr, MII_INTEL_PHY_STAT);
+		if (mii_data & MII_INTEL_PHY_STAT_SPD) {
+			if (mii_data & MII_INTEL_PHY_STAT_FDX) {
+				*speed = IF_PORT_100BASEFX;
+				dev->if_port = IF_PORT_100BASEFX;
+			}
+			else {
+				*speed = IF_PORT_100BASETX;
+				dev->if_port = IF_PORT_100BASETX;
+			}
+		}
+		else  {
+			*speed = IF_PORT_10BASET;
+			dev->if_port = IF_PORT_10BASET;
+		}
+
+	}
+	else {
+		*link = 0;
+		*speed = 0;
+		dev->if_port = IF_PORT_UNKNOWN;
+	}
+	return 0;
+}
+
+int ks8995m_init(struct net_device *dev, int phy_addr)
+{
+	s16 data;
+	
+//	printk("ks8995m_init\n");
+	/* Stop auto-negotiation */
+	data = mdio_read(dev, phy_addr, MII_CONTROL);
+	mdio_write(dev, phy_addr, MII_CONTROL, data & ~MII_CNTL_AUTO);
+
+	/* Set advertisement to 10/100 and Half/Full duplex
+	 * (full capabilities) */
+	data = mdio_read(dev, phy_addr, MII_ANADV);
+	data |= MII_NWAY_TX | MII_NWAY_TX_FDX | MII_NWAY_T_FDX | MII_NWAY_T;
+	mdio_write(dev, phy_addr, MII_ANADV, data);
+	
+	/* Restart auto-negotiation */
+	data = mdio_read(dev, phy_addr, MII_CONTROL);
+	data |= MII_CNTL_RST_AUTO | MII_CNTL_AUTO;
+	mdio_write(dev, phy_addr, MII_CONTROL, data);
+
+	if (au1000_debug > 4) dump_mii(dev, phy_addr);
+
+	return 0;
+}
+
+int ks8995m_reset(struct net_device *dev, int phy_addr)
+{
+	s16 mii_control, timeout;
+	
+//	printk("ks8995m_reset\n");
+	mii_control = mdio_read(dev, phy_addr, MII_CONTROL);
+	mdio_write(dev, phy_addr, MII_CONTROL, mii_control | MII_CNTL_RESET);
+	mdelay(1);
+	for (timeout = 100; timeout > 0; --timeout) {
+		mii_control = mdio_read(dev, phy_addr, MII_CONTROL);
+		if ((mii_control & MII_CNTL_RESET) == 0)
+			break;
+		mdelay(1);
+	}
+	if (mii_control & MII_CNTL_RESET) {
+		printk(KERN_ERR "%s PHY reset timeout !\n", dev->name);
+		return -1;
+	}
+	return 0;
+}
+
+int ks8995m_status(struct net_device *dev, int phy_addr, u16 *link, u16 *speed)
+{
+	u16 mii_data;
+	struct au1000_private *aup;
+
+	if (!dev) {
+		printk(KERN_ERR "ks8995m_status error: NULL dev\n");
+		return -1;
+	}
+	aup = (struct au1000_private *) dev->priv;
+
+	mii_data = mdio_read(dev, aup->phy_addr, MII_STATUS);
+	if (mii_data & MII_STAT_LINK) {
+		*link = 1;
+		mii_data = mdio_read(dev, aup->phy_addr, MII_AUX_CNTRL);
+		if (mii_data & MII_AUX_100) {
+			if (mii_data & MII_AUX_FDX) {
+				*speed = IF_PORT_100BASEFX;
+				dev->if_port = IF_PORT_100BASEFX;
+			}
+			else {
+				*speed = IF_PORT_100BASETX;
+				dev->if_port = IF_PORT_100BASETX;
+			}
+		}
+		else  {											
+			*speed = IF_PORT_10BASET;
+			dev->if_port = IF_PORT_10BASET;
+		}
+
+	}
+	else {
+		*link = 0;
+		*speed = 0;
+		dev->if_port = IF_PORT_UNKNOWN;
+	}
+	return 0;
+}
+
+int
+smsc_83C185_init (struct net_device *dev, int phy_addr)
+{
+	s16 data;
+
+	if (au1000_debug > 4)
+		printk("smsc_83C185_init\n");
+
+	/* Stop auto-negotiation */
+	data = mdio_read(dev, phy_addr, MII_CONTROL);
+	mdio_write(dev, phy_addr, MII_CONTROL, data & ~MII_CNTL_AUTO);
+
+	/* Set advertisement to 10/100 and Half/Full duplex
+	 * (full capabilities) */
+	data = mdio_read(dev, phy_addr, MII_ANADV);
+	data |= MII_NWAY_TX | MII_NWAY_TX_FDX | MII_NWAY_T_FDX | MII_NWAY_T;
+	mdio_write(dev, phy_addr, MII_ANADV, data);
+	
+	/* Restart auto-negotiation */
+	data = mdio_read(dev, phy_addr, MII_CONTROL);
+	data |= MII_CNTL_RST_AUTO | MII_CNTL_AUTO;
+
+	mdio_write(dev, phy_addr, MII_CONTROL, data);
+
+	if (au1000_debug > 4) dump_mii(dev, phy_addr);
+	return 0;
+}
+
+int
+smsc_83C185_reset (struct net_device *dev, int phy_addr)
+{
+	s16 mii_control, timeout;
+	
+	if (au1000_debug > 4)
+		printk("smsc_83C185_reset\n");
+
+	mii_control = mdio_read(dev, phy_addr, MII_CONTROL);
+	mdio_write(dev, phy_addr, MII_CONTROL, mii_control | MII_CNTL_RESET);
+	mdelay(1);
+	for (timeout = 100; timeout > 0; --timeout) {
+		mii_control = mdio_read(dev, phy_addr, MII_CONTROL);
+		if ((mii_control & MII_CNTL_RESET) == 0)
+			break;
+		mdelay(1);
+	}
+	if (mii_control & MII_CNTL_RESET) {
+		printk(KERN_ERR "%s PHY reset timeout !\n", dev->name);
+		return -1;
+	}
+	return 0;
+}
+
+int 
+smsc_83C185_status (struct net_device *dev, int phy_addr, u16 *link, u16 *speed)
+{
+	u16 mii_data;
+	struct au1000_private *aup;
+
+	if (!dev) {
+		printk(KERN_ERR "smsc_83C185_status error: NULL dev\n");
+		return -1;
+	}
+
+	aup = (struct au1000_private *) dev->priv;
+	mii_data = mdio_read(dev, aup->phy_addr, MII_STATUS);
+
+	if (mii_data & MII_STAT_LINK) {
+		*link = 1;
+		mii_data = mdio_read(dev, aup->phy_addr, 0x1f);
+		if (mii_data & (1<<3)) {
+			if (mii_data & (1<<4)) {
+				*speed = IF_PORT_100BASEFX;
+				dev->if_port = IF_PORT_100BASEFX;
+			}
+			else {
+				*speed = IF_PORT_100BASETX;
+				dev->if_port = IF_PORT_100BASETX;
+			}
+		}
+		else {
+			*speed = IF_PORT_10BASET;
+			dev->if_port = IF_PORT_10BASET;
+		}
+	}
+	else {
+		*link = 0;
+		*speed = 0;
+		dev->if_port = IF_PORT_UNKNOWN;
+	}
+	return 0;
+}
+
+
+#ifdef CONFIG_MIPS_BOSPORUS
+int stub_init(struct net_device *dev, int phy_addr)
+{
+	//printk("PHY stub_init\n");
+	return 0;
+}
+
+int stub_reset(struct net_device *dev, int phy_addr)
+{
+	//printk("PHY stub_reset\n");
+	return 0;
+}
+
+int 
+stub_status(struct net_device *dev, int phy_addr, u16 *link, u16 *speed)
+{
+	//printk("PHY stub_status\n");
+	*link = 1;
+	/* hmmm, revisit */
+	*speed = IF_PORT_100BASEFX;
+	dev->if_port = IF_PORT_100BASEFX;
+	return 0;
+}
+#endif
+
 struct phy_ops bcm_5201_ops = {
 	bcm_5201_init,
 	bcm_5201_reset,
 	bcm_5201_status,
 };
 
+struct phy_ops am79c874_ops = {
+	am79c874_init,
+	am79c874_reset,
+	am79c874_status,
+};
+
 struct phy_ops am79c901_ops = {
 	am79c901_init,
 	am79c901_reset,
@@ -355,26 +749,89 @@
 	lsi_80227_status,
 };
 
+struct phy_ops lxt971a_ops = { 
+	lxt971a_init,
+	lxt971a_reset,
+	lxt971a_status,
+};
+
+struct phy_ops ks8995m_ops = {
+	ks8995m_init,
+	ks8995m_reset,
+	ks8995m_status,
+};
+
+struct phy_ops smsc_83C185_ops = {
+	smsc_83C185_init,
+	smsc_83C185_reset,
+	smsc_83C185_status,
+};
+
+#ifdef CONFIG_MIPS_BOSPORUS
+struct phy_ops stub_ops = {
+	stub_init,
+	stub_reset,
+	stub_status,
+};
+#endif
+
 static struct mii_chip_info {
 	const char * name;
 	u16 phy_id0;
 	u16 phy_id1;
 	struct phy_ops *phy_ops;	
+	int dual_phy;
 } mii_chip_table[] = {
-	{"Broadcom BCM5201 10/100 BaseT PHY",  0x0040, 0x6212, &bcm_5201_ops },
-	{"AMD 79C901 HomePNA PHY",  0x0000, 0x35c8, &am79c901_ops },
-	{"LSI 80227 10/100 BaseT PHY", 0x0016, 0xf840, &lsi_80227_ops },
-	{"Broadcom BCM5221 10/100 BaseT PHY",  0x0040, 0x61e4, &bcm_5201_ops },
+	{"Broadcom BCM5201 10/100 BaseT PHY",0x0040,0x6212, &bcm_5201_ops,0},
+	{"Broadcom BCM5221 10/100 BaseT PHY",0x0040,0x61e4, &bcm_5201_ops,0},
+	{"Broadcom BCM5222 10/100 BaseT PHY",0x0040,0x6322, &bcm_5201_ops,1},
+	{"AMD 79C901 HomePNA PHY",0x0000,0x35c8, &am79c901_ops,0},
+	{"AMD 79C874 10/100 BaseT PHY",0x0022,0x561b, &am79c874_ops,0},
+	{"LSI 80227 10/100 BaseT PHY",0x0016,0xf840, &lsi_80227_ops,0},
+	{"Intel LXT971A Dual Speed PHY",0x0013,0x78e2, &lxt971a_ops,0},
+	{"Kendin KS8995M 10/100 BaseT PHY",0x0022,0x1450, &ks8995m_ops,0},
+	{"SMSC LAN83C185 10/100 BaseT PHY",0x0007,0xc0a3, &smsc_83C185_ops,0},
+#ifdef CONFIG_MIPS_BOSPORUS
+	{"Stub", 0x1234, 0x5678, &stub_ops },
+#endif
 	{0,},
 };
 
 static int mdio_read(struct net_device *dev, int phy_id, int reg)
 {
 	struct au1000_private *aup = (struct au1000_private *) dev->priv;
+	volatile u32 *mii_control_reg;
+	volatile u32 *mii_data_reg;
 	u32 timedout = 20;
 	u32 mii_control;
 
-	while (aup->mac->mii_control & MAC_MII_BUSY) {
+	#ifdef CONFIG_BCM5222_DUAL_PHY
+	/* First time we probe, it's for the mac0 phy.
+	 * Since we haven't determined yet that we have a dual phy,
+	 * aup->mii->mii_control_reg won't be setup and we'll
+	 * default to the else statement.
+	 * By the time we probe for the mac1 phy, the mii_control_reg
+	 * will be setup to be the address of the mac0 phy control since
+	 * both phys are controlled through mac0.
+	 */
+	if (aup->mii && aup->mii->mii_control_reg) {
+		mii_control_reg = aup->mii->mii_control_reg;
+		mii_data_reg = aup->mii->mii_data_reg;
+	}
+	else if (au_macs[0]->mii && au_macs[0]->mii->mii_control_reg) {
+		/* assume both phys are controlled through mac0 */
+		mii_control_reg = au_macs[0]->mii->mii_control_reg;
+		mii_data_reg = au_macs[0]->mii->mii_data_reg;
+	}
+	else 
+	#endif
+	{
+		/* default control and data reg addresses */
+		mii_control_reg = &aup->mac->mii_control;
+		mii_data_reg = &aup->mac->mii_data;
+	}
+
+	while (*mii_control_reg & MAC_MII_BUSY) {
 		mdelay(1);
 		if (--timedout == 0) {
 			printk(KERN_ERR "%s: read_MII busy timeout!!\n", 
@@ -386,10 +843,10 @@
 	mii_control = MAC_SET_MII_SELECT_REG(reg) | 
 		MAC_SET_MII_SELECT_PHY(phy_id) | MAC_MII_READ;
 
-	aup->mac->mii_control = mii_control;
+	*mii_control_reg = mii_control;
 
 	timedout = 20;
-	while (aup->mac->mii_control & MAC_MII_BUSY) {
+	while (*mii_control_reg & MAC_MII_BUSY) {
 		mdelay(1);
 		if (--timedout == 0) {
 			printk(KERN_ERR "%s: mdio_read busy timeout!!\n", 
@@ -397,16 +854,36 @@
 			return -1;
 		}
 	}
-	return (int)aup->mac->mii_data;
+	return (int)*mii_data_reg;
 }
 
 static void mdio_write(struct net_device *dev, int phy_id, int reg, u16 value)
 {
 	struct au1000_private *aup = (struct au1000_private *) dev->priv;
+	volatile u32 *mii_control_reg;
+	volatile u32 *mii_data_reg;
 	u32 timedout = 20;
 	u32 mii_control;
 
-	while (aup->mac->mii_control & MAC_MII_BUSY) {
+	#ifdef CONFIG_BCM5222_DUAL_PHY
+	if (aup->mii && aup->mii->mii_control_reg) {
+		mii_control_reg = aup->mii->mii_control_reg;
+		mii_data_reg = aup->mii->mii_data_reg;
+	}
+	else if (au_macs[0]->mii && au_macs[0]->mii->mii_control_reg) {
+		/* assume both phys are controlled through mac0 */
+		mii_control_reg = au_macs[0]->mii->mii_control_reg;
+		mii_data_reg = au_macs[0]->mii->mii_data_reg;
+	}
+	else 
+	#endif
+	{
+		/* default control and data reg addresses */
+		mii_control_reg = &aup->mac->mii_control;
+		mii_data_reg = &aup->mac->mii_data;
+	}
+
+	while (*mii_control_reg & MAC_MII_BUSY) {
 		mdelay(1);
 		if (--timedout == 0) {
 			printk(KERN_ERR "%s: mdio_write busy timeout!!\n", 
@@ -418,8 +895,8 @@
 	mii_control = MAC_SET_MII_SELECT_REG(reg) | 
 		MAC_SET_MII_SELECT_PHY(phy_id) | MAC_MII_WRITE;
 
-	aup->mac->mii_data = value;
-	aup->mac->mii_control = mii_control;
+	*mii_data_reg = value;
+	*mii_control_reg = mii_control;
 }
 
 
@@ -437,12 +914,13 @@
 	}
 }
 
-static int __init mii_probe (struct net_device * dev)
+static int mii_probe (struct net_device * dev)
 {
 	struct au1000_private *aup = (struct au1000_private *) dev->priv;
 	int phy_addr;
-
-	aup->mii = NULL;
+#ifdef CONFIG_MIPS_BOSPORUS
+	int phy_found=0;
+#endif
 
 	/* search for total of 32 possible mii phy addresses */
 	for (phy_addr = 0; phy_addr < 32; phy_addr++) {
@@ -450,9 +928,17 @@
 		u16 phy_id0, phy_id1;
 		int i;
 
+		#ifdef CONFIG_BCM5222_DUAL_PHY
+		/* Mask the already found phy, try next one */
+		if (au_macs[0]->mii && au_macs[0]->mii->mii_control_reg) {
+			if (au_macs[0]->phy_addr == phy_addr)
+				continue;
+		}
+		#endif
+
 		mii_status = mdio_read(dev, phy_addr, MII_STATUS);
 		if (mii_status == 0xffff || mii_status == 0x0000)
-			/* the mii is not accessible, try next one */
+			/* the mii is not accessable, try next one */
 			continue;
 
 		phy_id0 = mdio_read(dev, phy_addr, MII_PHY_ID0);
@@ -462,6 +948,66 @@
 		for (i = 0; mii_chip_table[i].phy_id1; i++) {
 			if (phy_id0 == mii_chip_table[i].phy_id0 &&
 			    phy_id1 == mii_chip_table[i].phy_id1) {
+				struct mii_phy * mii_phy = aup->mii;
+
+				printk(KERN_INFO "%s: %s at phy address %d\n",
+				       dev->name, mii_chip_table[i].name, 
+				       phy_addr);
+#ifdef CONFIG_MIPS_BOSPORUS
+				phy_found = 1;
+#endif
+				mii_phy->chip_info = mii_chip_table+i;
+				aup->phy_addr = phy_addr;
+				aup->want_autoneg = 1;
+				aup->phy_ops = mii_chip_table[i].phy_ops;
+				aup->phy_ops->phy_init(dev,phy_addr);
+
+				// Check for dual-phy and then store required 
+				// values and set indicators. We need to do 
+				// this now since mdio_{read,write} need the 
+				// control and data register addresses.
+				#ifdef CONFIG_BCM5222_DUAL_PHY
+				if ( mii_chip_table[i].dual_phy) {
+
+					/* assume both phys are controlled 
+					 * through MAC0. Board specific? */
+					
+					/* sanity check */
+					if (!au_macs[0] || !au_macs[0]->mii)
+						return -1;
+					aup->mii->mii_control_reg = (u32 *)
+						&au_macs[0]->mac->mii_control;
+					aup->mii->mii_data_reg = (u32 *)
+						&au_macs[0]->mac->mii_data;
+				}
+				#endif
+				goto found;
+			}
+		}
+	}
+found:
+
+#ifdef CONFIG_MIPS_BOSPORUS
+	/* This is a workaround for the Micrel/Kendin 5 port switch
+	   The second MAC doesn't see a PHY connected... so we need to
+	   trick it into thinking we have one.
+		
+	   If this kernel is run on another Au1500 development board
+	   the stub will be found as well as the actual PHY. However,
+	   the last found PHY will be used... usually at Addr 31 (Db1500).	
+	*/
+	if ( (!phy_found) )
+	{
+		u16 phy_id0, phy_id1;
+		int i;
+
+		phy_id0 = 0x1234;
+		phy_id1 = 0x5678;
+
+		/* search our mii table for the current mii */ 
+		for (i = 0; mii_chip_table[i].phy_id1; i++) {
+			if (phy_id0 == mii_chip_table[i].phy_id0 &&
+			    phy_id1 == mii_chip_table[i].phy_id1) {
 				struct mii_phy * mii_phy;
 
 				printk(KERN_INFO "%s: %s at phy address %d\n",
@@ -471,31 +1017,39 @@
 						GFP_KERNEL);
 				if (mii_phy) {
 					mii_phy->chip_info = mii_chip_table+i;
-					mii_phy->phy_addr = phy_addr;
+					aup->phy_addr = phy_addr;
 					mii_phy->next = aup->mii;
 					aup->phy_ops = 
 						mii_chip_table[i].phy_ops;
 					aup->mii = mii_phy;
 					aup->phy_ops->phy_init(dev,phy_addr);
 				} else {
-					printk(KERN_ERR "%s: out of memory\n",
+					printk(KERN_ERR "%s: out of memory\n", 
 							dev->name);
 					return -1;
 				}
-				/* the current mii is on our mii_info_table,
-				   try next address */
+				mii_phy->chip_info = mii_chip_table+i;
+				aup->phy_addr = phy_addr;
+				aup->phy_ops = mii_chip_table[i].phy_ops;
+				aup->phy_ops->phy_init(dev,phy_addr);
 				break;
 			}
 		}
 	}
+	if (aup->mac_id == 0) {
+		/* the Bosporus phy responds to addresses 0-5 but 
+		 * 5 is the correct one.
+		 */
+		aup->phy_addr = 5;
+	}
+#endif
 
-	if (aup->mii == NULL) {
-		printk(KERN_ERR "%s: No MII transceivers found!\n", dev->name);
+	if (aup->mii->chip_info == NULL) {
+		printk(KERN_ERR "%s: Au1x No MII transceivers found!\n",
+				dev->name);
 		return -1;
 	}
 
-	/* use last PHY */
-	aup->phy_addr = aup->mii->phy_addr;
 	printk(KERN_INFO "%s: Using %s as default\n", 
 			dev->name, aup->mii->chip_info->name);
 
@@ -516,7 +1070,6 @@
 	if (pDB) {
 		aup->pDBfree = pDB->pnext;
 	}
-	//printk("GetFreeDB: %x\n", pDB);
 	return pDB;
 }
 
@@ -528,35 +1081,6 @@
 	aup->pDBfree = pDB;
 }
 
-
-/*
-  DMA memory allocation, derived from pci_alloc_consistent.
-  However, the Au1000 data cache is coherent (when programmed
-  so), therefore we return KSEG0 address, not KSEG1.
-*/
-static void *dma_alloc(size_t size, dma_addr_t * dma_handle)
-{
-	void *ret;
-	int gfp = GFP_ATOMIC | GFP_DMA;
-
-	ret = (void *) __get_free_pages(gfp, get_order(size));
-
-	if (ret != NULL) {
-		memset(ret, 0, size);
-		*dma_handle = virt_to_bus(ret);
-		ret = (void *)KSEG0ADDR(ret);
-	}
-	return ret;
-}
-
-
-static void dma_free(void *vaddr, size_t size)
-{
-	vaddr = (void *)KSEG0ADDR(vaddr);
-	free_pages((unsigned long) vaddr, get_order(size));
-}
-
-
 static void enable_rx_tx(struct net_device *dev)
 {
 	struct au1000_private *aup = (struct au1000_private *) dev->priv;
@@ -582,6 +1106,7 @@
 
 static void reset_mac(struct net_device *dev)
 {
+	int i;
 	u32 flags;
 	struct au1000_private *aup = (struct au1000_private *) dev->priv;
 
@@ -590,13 +1115,32 @@
 				dev->name, (unsigned)aup);
 
 	spin_lock_irqsave(&aup->lock, flags);
-	del_timer(&aup->timer);
+	if (aup->timer.function == &au1000_timer) {/* check if timer initted */
+		del_timer(&aup->timer);
+	}
+
 	hard_stop(dev);
-	*aup->enable = MAC_EN_CLOCK_ENABLE;
-	au_sync_delay(2);
-       	*aup->enable = 0;
-	au_sync_delay(2);
+	#ifdef CONFIG_BCM5222_DUAL_PHY
+	if (aup->mac_id != 0) {
+	#endif
+		/* If BCM5222, we can't leave MAC0 in reset because then 
+		 * we can't access the dual phy for ETH1 */
+		*aup->enable = MAC_EN_CLOCK_ENABLE;
+		au_sync_delay(2);
+		*aup->enable = 0;
+		au_sync_delay(2);
+	#ifdef CONFIG_BCM5222_DUAL_PHY
+	}
+	#endif
 	aup->tx_full = 0;
+	for (i = 0; i < NUM_RX_DMA; i++) {
+		/* reset control bits */
+		aup->rx_dma_ring[i]->buff_stat &= ~0xf;
+	}
+	for (i = 0; i < NUM_TX_DMA; i++) {
+		/* reset control bits */
+		aup->tx_dma_ring[i]->buff_stat &= ~0xf;
+	}
 	spin_unlock_irqrestore(&aup->lock, flags);
 }
 
@@ -611,93 +1155,348 @@
 {
 	int i;
 
-	for (i=0; i<NUM_RX_DMA; i++) {
+	for (i = 0; i < NUM_RX_DMA; i++) {
 		aup->rx_dma_ring[i] = 
 			(volatile rx_dma_t *) (rx_base + sizeof(rx_dma_t)*i);
 	}
-	for (i=0; i<NUM_TX_DMA; i++) {
+	for (i = 0; i < NUM_TX_DMA; i++) {
 		aup->tx_dma_ring[i] = 
 			(volatile tx_dma_t *) (tx_base + sizeof(tx_dma_t)*i);
 	}
 }
 
+static struct {
+	int port;
+	u32 base_addr;
+	u32 macen_addr;
+	int irq;
+	struct net_device *dev;
+} iflist[2];
+
+static int num_ifs;
+
+/*
+ * Setup the base address and interupt of the Au1xxx ethernet macs
+ * based on cpu type and whether the interface is enabled in sys_pinfunc
+ * register. The last interface is enabled if SYS_PF_NI2 (bit 4) is 0.
+ */
 static int __init au1000_init_module(void)
 {
-	int i;
-	int prid;
-	int base_addr, irq;
+	struct cpuinfo_mips *c = &current_cpu_data;
+	int ni = (int)((au_readl(SYS_PINFUNC) & (u32)(SYS_PF_NI2)) >> 4);
+	struct net_device *dev;
+	int i, found_one = 0;
 
-	prid = read_c0_prid();
-	for (i=0; i<NUM_INTERFACES; i++) {
-		if ( (prid & 0xffff0000) == 0x00030000 ) {
-			base_addr = au1000_iflist[i].port;
-			irq = au1000_iflist[i].irq;
-		} else if ( (prid & 0xffff0000) == 0x01030000 ) {
-			base_addr = au1500_iflist[i].port;
-			irq = au1500_iflist[i].irq;
-		} else if ( (prid & 0xffff0000) == 0x02030000 ) {
-			base_addr = au1100_iflist[i].port;
-			irq = au1100_iflist[i].irq;
+	switch (c->cputype) {
+#ifdef CONFIG_SOC_AU1000
+	case CPU_AU1000:
+		num_ifs = 2 - ni;
+		iflist[0].base_addr = AU1000_ETH0_BASE;
+		iflist[1].base_addr = AU1000_ETH1_BASE;
+		iflist[0].macen_addr = AU1000_MAC0_ENABLE;
+		iflist[1].macen_addr = AU1000_MAC1_ENABLE;
+		iflist[0].irq = AU1000_MAC0_DMA_INT;
+		iflist[1].irq = AU1000_MAC1_DMA_INT;
+		break;
+#endif
+#ifdef CONFIG_SOC_AU1100
+	case CPU_AU1100:
+		num_ifs = 1 - ni;
+		iflist[0].base_addr = AU1100_ETH0_BASE;
+		iflist[0].macen_addr = AU1100_MAC0_ENABLE;
+		iflist[0].irq = AU1100_MAC0_DMA_INT;
+		break;
+#endif
+#ifdef CONFIG_SOC_AU1500
+	case CPU_AU1500:
+		num_ifs = 2 - ni;
+		iflist[0].base_addr = AU1500_ETH0_BASE;
+		iflist[1].base_addr = AU1500_ETH1_BASE;
+		iflist[0].macen_addr = AU1500_MAC0_ENABLE;
+		iflist[1].macen_addr = AU1500_MAC1_ENABLE;
+		iflist[0].irq = AU1500_MAC0_DMA_INT;
+		iflist[1].irq = AU1500_MAC1_DMA_INT;
+		break;
+#endif
+#ifdef CONFIG_SOC_AU1550
+	case CPU_AU1550:
+		num_ifs = 2 - ni;
+		iflist[0].base_addr = AU1550_ETH0_BASE;
+		iflist[1].base_addr = AU1550_ETH1_BASE;
+		iflist[0].macen_addr = AU1550_MAC0_ENABLE;
+		iflist[1].macen_addr = AU1550_MAC1_ENABLE;
+		iflist[0].irq = AU1550_MAC0_DMA_INT;
+		iflist[1].irq = AU1550_MAC1_DMA_INT;
+		break;
+#endif
+	default:
+		num_ifs = 0;
+	}
+	for(i = 0; i < num_ifs; i++) {
+		dev = au1000_probe(iflist[i].base_addr, iflist[i].irq, i);
+		iflist[i].dev = dev;
+		if (dev)
+			found_one++;
+	}
+	if (!found_one)
+		return -ENODEV;
+	return 0;
+}
+
+static int au1000_setup_aneg(struct net_device *dev, u32 advertise)
+{
+	struct au1000_private *aup = (struct au1000_private *)dev->priv;
+	u16 ctl, adv;
+
+	/* Setup standard advertise */
+	adv = mdio_read(dev, aup->phy_addr, MII_ADVERTISE);
+	adv &= ~(ADVERTISE_ALL | ADVERTISE_100BASE4);
+	if (advertise & ADVERTISED_10baseT_Half)
+		adv |= ADVERTISE_10HALF;
+	if (advertise & ADVERTISED_10baseT_Full)
+		adv |= ADVERTISE_10FULL;
+	if (advertise & ADVERTISED_100baseT_Half)
+		adv |= ADVERTISE_100HALF;
+	if (advertise & ADVERTISED_100baseT_Full)
+		adv |= ADVERTISE_100FULL;
+	mdio_write(dev, aup->phy_addr, MII_ADVERTISE, adv);
+
+	/* Start/Restart aneg */
+	ctl = mdio_read(dev, aup->phy_addr, MII_BMCR);
+	ctl |= (BMCR_ANENABLE | BMCR_ANRESTART);
+	mdio_write(dev, aup->phy_addr, MII_BMCR, ctl);
+
+	return 0;
+}
+
+static int au1000_setup_forced(struct net_device *dev, int speed, int fd)
+{
+	struct au1000_private *aup = (struct au1000_private *)dev->priv;
+	u16 ctl;
+
+	ctl = mdio_read(dev, aup->phy_addr, MII_BMCR);
+	ctl &= ~(BMCR_FULLDPLX | BMCR_SPEED100 | BMCR_ANENABLE);
+
+	/* First reset the PHY */
+	mdio_write(dev, aup->phy_addr, MII_BMCR, ctl | BMCR_RESET);
+
+	/* Select speed & duplex */
+	switch (speed) {
+		case SPEED_10:
+			break;
+		case SPEED_100:
+			ctl |= BMCR_SPEED100;
+			break;
+		case SPEED_1000:
+		default:
+			return -EINVAL;
+	}
+	if (fd == DUPLEX_FULL)
+		ctl |= BMCR_FULLDPLX;
+	mdio_write(dev, aup->phy_addr, MII_BMCR, ctl);
+
+	return 0;
+}
+
+
+static void
+au1000_start_link(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+	struct au1000_private *aup = (struct au1000_private *)dev->priv;
+	u32 advertise;
+	int autoneg;
+	int forced_speed;
+	int forced_duplex;
+
+	/* Default advertise */
+	advertise = GENMII_DEFAULT_ADVERTISE;
+	autoneg = aup->want_autoneg;
+	forced_speed = SPEED_100;
+	forced_duplex = DUPLEX_FULL;
+
+	/* Setup link parameters */
+	if (cmd) {
+		if (cmd->autoneg == AUTONEG_ENABLE) {
+			advertise = cmd->advertising;
+			autoneg = 1;
 		} else {
-			printk(KERN_ERR "au1000 eth: unknown Processor ID\n");
-			return -ENODEV;
-		}
-		// check for valid entries, au1100 only has one entry
-		if (base_addr && irq) {
-			if (au1000_probe1(base_addr, irq, i) != 0)
-				return -ENODEV;
+			autoneg = 0;
+
+			forced_speed = cmd->speed;
+			forced_duplex = cmd->duplex;
 		}
 	}
+
+	/* Configure PHY & start aneg */
+	aup->want_autoneg = autoneg;
+	if (autoneg)
+		au1000_setup_aneg(dev, advertise);
+	else
+		au1000_setup_forced(dev, forced_speed, forced_duplex);
+	mod_timer(&aup->timer, jiffies + HZ);
+}
+
+static int au1000_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+	struct au1000_private *aup = (struct au1000_private *)dev->priv;
+	u16 link, speed;
+
+	cmd->supported = GENMII_DEFAULT_FEATURES;
+	cmd->advertising = GENMII_DEFAULT_ADVERTISE;
+	cmd->port = PORT_MII;
+	cmd->transceiver = XCVR_EXTERNAL;
+	cmd->phy_address = aup->phy_addr;
+	spin_lock_irq(&aup->lock);
+	cmd->autoneg = aup->want_autoneg;
+	aup->phy_ops->phy_status(dev, aup->phy_addr, &link, &speed);
+	if ((speed == IF_PORT_100BASETX) || (speed == IF_PORT_100BASEFX))
+		cmd->speed = SPEED_100;
+	else if (speed == IF_PORT_10BASET)
+		cmd->speed = SPEED_10;
+	if (link && (dev->if_port == IF_PORT_100BASEFX))
+		cmd->duplex = DUPLEX_FULL;
+	else
+		cmd->duplex = DUPLEX_HALF;
+	spin_unlock_irq(&aup->lock);
 	return 0;
 }
 
-static int __init
-au1000_probe1(long ioaddr, int irq, int port_num)
+static int au1000_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+	 struct au1000_private *aup = (struct au1000_private *)dev->priv;
+	  unsigned long features = GENMII_DEFAULT_FEATURES;
+
+	 if (!capable(CAP_NET_ADMIN))
+		 return -EPERM;
+
+	 if (cmd->autoneg != AUTONEG_ENABLE && cmd->autoneg != AUTONEG_DISABLE)
+		 return -EINVAL;
+	 if (cmd->autoneg == AUTONEG_ENABLE && cmd->advertising == 0)
+		 return -EINVAL;
+	 if (cmd->duplex != DUPLEX_HALF && cmd->duplex != DUPLEX_FULL)
+		 return -EINVAL;
+	 if (cmd->autoneg == AUTONEG_DISABLE)
+		 switch (cmd->speed) {
+		 case SPEED_10:
+			 if (cmd->duplex == DUPLEX_HALF &&
+				 (features & SUPPORTED_10baseT_Half) == 0)
+				 return -EINVAL;
+			 if (cmd->duplex == DUPLEX_FULL &&
+				 (features & SUPPORTED_10baseT_Full) == 0)
+				 return -EINVAL;
+			 break;
+		 case SPEED_100:
+			 if (cmd->duplex == DUPLEX_HALF &&
+				 (features & SUPPORTED_100baseT_Half) == 0)
+				 return -EINVAL;
+			 if (cmd->duplex == DUPLEX_FULL &&
+				 (features & SUPPORTED_100baseT_Full) == 0)
+				 return -EINVAL;
+			 break;
+		 default:
+			 return -EINVAL;
+		 }
+	 else if ((features & SUPPORTED_Autoneg) == 0)
+		 return -EINVAL;
+
+	 spin_lock_irq(&aup->lock);
+	 au1000_start_link(dev, cmd);
+	 spin_unlock_irq(&aup->lock);
+	 return 0;
+}
+
+static int au1000_nway_reset(struct net_device *dev)
+{
+	struct au1000_private *aup = (struct au1000_private *)dev->priv;
+
+	if (!aup->want_autoneg)
+		return -EINVAL;
+	spin_lock_irq(&aup->lock);
+	au1000_start_link(dev, NULL);
+	spin_unlock_irq(&aup->lock);
+	return 0;
+}
+
+static void
+au1000_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
+{
+	struct au1000_private *aup = (struct au1000_private *)dev->priv;
+
+	strcpy(info->driver, DRV_NAME);
+	strcpy(info->version, DRV_VERSION);
+	info->fw_version[0] = '\0';
+	sprintf(info->bus_info, "%s %d", DRV_NAME, aup->mac_id);
+	info->regdump_len = 0;
+}
+
+static u32 au1000_get_link(struct net_device *dev)
+{
+	return netif_carrier_ok(dev);
+}
+
+static struct ethtool_ops au1000_ethtool_ops = {
+	.get_settings = au1000_get_settings,
+	.set_settings = au1000_set_settings,
+	.get_drvinfo = au1000_get_drvinfo,
+	.nway_reset = au1000_nway_reset,
+	.get_link = au1000_get_link
+};
+
+static struct net_device *
+au1000_probe(u32 ioaddr, int irq, int port_num)
 {
-	struct net_device *dev;
 	static unsigned version_printed = 0;
 	struct au1000_private *aup = NULL;
-	int i, retval = 0;
+	struct net_device *dev = NULL;
 	db_dest_t *pDB, *pDBfree;
 	char *pmac, *argptr;
 	char ethaddr[6];
+	int i, err;
 
-	if (!request_region(PHYSADDR(ioaddr), MAC_IOSIZE, "Au1000 ENET"))
-		 return -ENODEV;
+	if (!request_mem_region(CPHYSADDR(ioaddr), MAC_IOSIZE, "Au1x00 ENET"))
+		return NULL;
 
-	if (version_printed++ == 0)
-		printk(version);
-
-	retval = -ENOMEM;
+	if (version_printed++ == 0) 
+		printk("%s version %s %s\n", DRV_NAME, DRV_VERSION, DRV_AUTHOR);
 
 	dev = alloc_etherdev(sizeof(struct au1000_private));
 	if (!dev) {
 		printk (KERN_ERR "au1000 eth: alloc_etherdev failed\n");  
-		goto out;
+		return NULL;
 	}
 
-	SET_MODULE_OWNER(dev);
+	if ((err = register_netdev(dev))) {
+		printk(KERN_ERR "Au1x_eth Cannot register net device err %d\n",
+				err);
+		free_netdev(dev);
+		return NULL;
+	}
 
-	printk("%s: Au1xxx ethernet found at 0x%lx, irq %d\n", 
-	       dev->name, ioaddr, irq);
+	printk("%s: Au1x Ethernet found at 0x%x, irq %d\n", 
+			dev->name, ioaddr, irq);
 
 	aup = dev->priv;
 
 	/* Allocate the data buffers */
-	aup->vaddr = (u32)dma_alloc(MAX_BUF_SIZE * 
-			(NUM_TX_BUFFS+NUM_RX_BUFFS), &aup->dma_addr);
-	if (!aup->vaddr)
-		goto out1;
+	/* Snooping works fine with eth on all au1xxx */
+	aup->vaddr = (u32)dma_alloc_noncoherent(NULL,
+			MAX_BUF_SIZE * (NUM_TX_BUFFS+NUM_RX_BUFFS),
+			&aup->dma_addr,
+			0);
+	if (!aup->vaddr) {
+		free_netdev(dev);
+		release_mem_region(CPHYSADDR(ioaddr), MAC_IOSIZE);
+		return NULL;
+	}
 
 	/* aup->mac is the base address of the MAC's registers */
 	aup->mac = (volatile mac_reg_t *)((unsigned long)ioaddr);
 	/* Setup some variables for quick register address access */
-	switch (ioaddr) {
-	case AU1000_ETH0_BASE:
-	case AU1500_ETH0_BASE:
+	if (ioaddr == iflist[0].base_addr)
+	{
 		/* check env variables first */
 		if (!get_ethernet_addr(ethaddr)) { 
-			memcpy(au1000_mac_addr, ethaddr, sizeof(dev->dev_addr));
+			memcpy(au1000_mac_addr, ethaddr, sizeof(au1000_mac_addr));
 		} else {
 			/* Check command line */
 			argptr = prom_getcmdline();
@@ -708,38 +1507,32 @@
 			} else {
 				str2eaddr(ethaddr, pmac + strlen("ethaddr="));
 				memcpy(au1000_mac_addr, ethaddr, 
-						sizeof(dev->dev_addr));
+						sizeof(au1000_mac_addr));
 			}
 		}
-		if (ioaddr == AU1000_ETH0_BASE)
-			aup->enable = (volatile u32 *) 
-				((unsigned long)AU1000_MAC0_ENABLE);
-		else
 			aup->enable = (volatile u32 *) 
-				((unsigned long)AU1500_MAC0_ENABLE);
-		memcpy(dev->dev_addr, au1000_mac_addr, sizeof(dev->dev_addr));
+				((unsigned long)iflist[0].macen_addr);
+		memcpy(dev->dev_addr, au1000_mac_addr, sizeof(au1000_mac_addr));
 		setup_hw_rings(aup, MAC0_RX_DMA_ADDR, MAC0_TX_DMA_ADDR);
-			break;
-	case AU1000_ETH1_BASE:
-	case AU1500_ETH1_BASE:
-		if (ioaddr == AU1000_ETH1_BASE)
-			aup->enable = (volatile u32 *) 
-				((unsigned long)AU1000_MAC1_ENABLE);
+		aup->mac_id = 0;
+		au_macs[0] = aup;
+	}
 		else
+	if (ioaddr == iflist[1].base_addr)
+	{
 			aup->enable = (volatile u32 *) 
-				((unsigned long)AU1500_MAC1_ENABLE);
-		memcpy(dev->dev_addr, au1000_mac_addr, sizeof(dev->dev_addr));
+				((unsigned long)iflist[1].macen_addr);
+		memcpy(dev->dev_addr, au1000_mac_addr, sizeof(au1000_mac_addr));
 		dev->dev_addr[4] += 0x10;
 		setup_hw_rings(aup, MAC1_RX_DMA_ADDR, MAC1_TX_DMA_ADDR);
-			break;
-	default:
+		aup->mac_id = 1;
+		au_macs[1] = aup;
+	}
+	else
+	{
 		printk(KERN_ERR "%s: bad ioaddr\n", dev->name);
-		break;
-
 	}
 
-	aup->phy_addr = PHY_ADDRESS;
-
 	/* bring the device out of reset, otherwise probing the mii
 	 * will hang */
 	*aup->enable = MAC_EN_CLOCK_ENABLE;
@@ -748,15 +1541,22 @@
 		MAC_EN_RESET2 | MAC_EN_CLOCK_ENABLE;
 	au_sync_delay(2);
 
-	retval = mii_probe(dev);
-	if (retval)
-		 goto out2;
+	aup->mii = kmalloc(sizeof(struct mii_phy), GFP_KERNEL);
+	if (!aup->mii) {
+		printk(KERN_ERR "%s: out of memory\n", dev->name);
+		goto err_out;
+	}
+	aup->mii->mii_control_reg = 0;
+	aup->mii->mii_data_reg = 0;
+
+	if (mii_probe(dev) != 0) {
+		goto err_out;
+	}
 
-	retval = -EINVAL;
 	pDBfree = NULL;
 	/* setup the data buffer descriptors and attach a buffer to each one */
 	pDB = aup->db;
-	for (i=0; i<(NUM_TX_BUFFS+NUM_RX_BUFFS); i++) {
+	for (i = 0; i < (NUM_TX_BUFFS+NUM_RX_BUFFS); i++) {
 		pDB->pnext = pDBfree;
 		pDBfree = pDB;
 		pDB->vaddr = (u32 *)((unsigned)aup->vaddr + MAX_BUF_SIZE*i);
@@ -765,15 +1565,19 @@
 	}
 	aup->pDBfree = pDBfree;
 
-	for (i=0; i<NUM_RX_DMA; i++) {
+	for (i = 0; i < NUM_RX_DMA; i++) {
 		pDB = GetFreeDB(aup);
-		if (!pDB) goto out2;
+		if (!pDB) {
+			goto err_out;
+		}
 		aup->rx_dma_ring[i]->buff_stat = (unsigned)pDB->dma_addr;
 		aup->rx_db_inuse[i] = pDB;
 	}
-	for (i=0; i<NUM_TX_DMA; i++) {
+	for (i = 0; i < NUM_TX_DMA; i++) {
 		pDB = GetFreeDB(aup);
-		if (!pDB) goto out2;
+		if (!pDB) {
+			goto err_out;
+		}
 		aup->tx_dma_ring[i]->buff_stat = (unsigned)pDB->dma_addr;
 		aup->tx_dma_ring[i]->len = 0;
 		aup->tx_db_inuse[i] = pDB;
@@ -788,6 +1592,7 @@
 	dev->get_stats = au1000_get_stats;
 	dev->set_multicast_list = &set_rx_mode;
 	dev->do_ioctl = &au1000_ioctl;
+	SET_ETHTOOL_OPS(dev, &au1000_ethtool_ops);
 	dev->set_config = &au1000_set_config;
 	dev->tx_timeout = au1000_tx_timeout;
 	dev->watchdog_timeo = ETH_TX_TIMEOUT;
@@ -798,23 +1603,32 @@
 	 */
 	reset_mac(dev);
 
-	retval = register_netdev(dev);
-	if (retval)
-		goto out2;
-	return 0;
+	return dev;
 
-out2:
-	dma_free(aup->vaddr, MAX_BUF_SIZE * (NUM_TX_BUFFS+NUM_RX_BUFFS));
-out1:
+err_out:
+	/* here we should have a valid dev plus aup-> register addresses
+	 * so we can reset the mac properly.*/
+	reset_mac(dev);
+	if (aup->mii)
+		kfree(aup->mii);
+	for (i = 0; i < NUM_RX_DMA; i++) {
+		if (aup->rx_db_inuse[i])
+			ReleaseDB(aup, aup->rx_db_inuse[i]);
+	}
+	for (i = 0; i < NUM_TX_DMA; i++) {
+		if (aup->tx_db_inuse[i])
+			ReleaseDB(aup, aup->tx_db_inuse[i]);
+	}
+	dma_free_noncoherent(NULL,
+			MAX_BUF_SIZE * (NUM_TX_BUFFS+NUM_RX_BUFFS),
+			(void *)aup->vaddr,
+			aup->dma_addr);
+	unregister_netdev(dev);
 	free_netdev(dev);
-out:
-	release_region(PHYSADDR(ioaddr), MAC_IOSIZE);
-	printk(KERN_ERR "%s: au1000_probe1 failed.  Returns %d\n",
-	       dev->name, retval);
-	return retval;
+	release_mem_region(CPHYSADDR(ioaddr), MAC_IOSIZE);
+	return NULL;
 }
 
-
 /* 
  * Initialize the interface.
  *
@@ -832,7 +1646,8 @@
 	u32 control;
 	u16 link, speed;
 
-	if (au1000_debug > 4) printk("%s: au1000_init\n", dev->name);
+	if (au1000_debug > 4) 
+		printk("%s: au1000_init\n", dev->name);
 
 	spin_lock_irqsave(&aup->lock, flags);
 
@@ -852,7 +1667,7 @@
 	aup->mac->mac_addr_low = dev->dev_addr[3]<<24 | dev->dev_addr[2]<<16 |
 		dev->dev_addr[1]<<8 | dev->dev_addr[0];
 
-	for (i=0; i<NUM_RX_DMA; i++) {
+	for (i = 0; i < NUM_RX_DMA; i++) {
 		aup->rx_dma_ring[i]->buff_stat |= RX_DMA_ENABLE;
 	}
 	au_sync();
@@ -865,7 +1680,13 @@
 	if (link && (dev->if_port == IF_PORT_100BASEFX)) {
 		control |= MAC_FULL_DUPLEX;
 	}
+
+	/* fix for startup without cable */
+	if (!link) 
+		dev->flags &= ~IFF_RUNNING;
+
 	aup->mac->control = control;
+	aup->mac->vlan1_tag = 0x8100; /* activate vlan support */
 	au_sync();
 
 	spin_unlock_irqrestore(&aup->lock, flags);
@@ -949,6 +1770,7 @@
 		return retval;
 	}
 
+	init_timer(&aup->timer); /* used in ioctl() */
 	aup->timer.expires = RUN_AT((3*HZ)); 
 	aup->timer.data = (unsigned long)dev;
 	aup->timer.function = &au1000_timer; /* timer handler */
@@ -968,22 +1790,49 @@
 	if (au1000_debug > 4)
 		printk("%s: close: dev=%p\n", dev->name, dev);
 
+	reset_mac(dev);
+
 	spin_lock_irqsave(&aup->lock, flags);
 	
 	/* stop the device */
-	if (netif_device_present(dev))
-		netif_stop_queue(dev);
+	netif_stop_queue(dev);
 
 	/* disable the interrupt */
 	free_irq(dev->irq, dev);
 	spin_unlock_irqrestore(&aup->lock, flags);
 
-	reset_mac(dev);
 	return 0;
 }
 
 static void __exit au1000_cleanup_module(void)
 {
+	int i, j;
+	struct net_device *dev;
+	struct au1000_private *aup;
+
+	for (i = 0; i < num_ifs; i++) {
+		dev = iflist[i].dev;
+		if (dev) {
+			aup = (struct au1000_private *) dev->priv;
+			unregister_netdev(dev);
+			if (aup->mii)
+				kfree(aup->mii);
+			for (j = 0; j < NUM_RX_DMA; j++) {
+				if (aup->rx_db_inuse[j])
+					ReleaseDB(aup, aup->rx_db_inuse[j]);
+			}
+			for (j = 0; j < NUM_TX_DMA; j++) {
+				if (aup->tx_db_inuse[j])
+					ReleaseDB(aup, aup->tx_db_inuse[j]);
+			}
+			dma_free_noncoherent(NULL,
+					MAX_BUF_SIZE * (NUM_TX_BUFFS+NUM_RX_BUFFS),
+					(void *)aup->vaddr,
+					aup->dma_addr);
+			free_netdev(dev);
+			release_mem_region(CPHYSADDR(iflist[i].base_addr), MAC_IOSIZE);
+		}
+	}
 }
 
 
@@ -1028,9 +1877,8 @@
 	ptxd = aup->tx_dma_ring[aup->tx_tail];
 
 	while (ptxd->buff_stat & TX_T_DONE) {
- 		update_tx_stats(dev, ptxd->status, aup->tx_len[aup->tx_tail]  & 0x3ff);
+		update_tx_stats(dev, ptxd->status, ptxd->len & 0x3ff);
 		ptxd->buff_stat &= ~TX_T_DONE;
- 		aup->tx_len[aup->tx_tail] = 0;
 		ptxd->len = 0;
 		au_sync();
 
@@ -1056,7 +1904,7 @@
 	db_dest_t *pDB;
 	int i;
 
-	if (au1000_debug > 4)
+	if (au1000_debug > 5)
 		printk("%s: tx: aup %x len=%d, data=%p, head %d\n", 
 				dev->name, (unsigned)aup, skb->len, 
 				skb->data, aup->tx_head);
@@ -1070,8 +1918,7 @@
 		return 1;
 	}
 	else if (buff_stat & TX_T_DONE) {
- 		update_tx_stats(dev, ptxd->status, aup->tx_len[aup->tx_head] & 0x3ff);
- 		aup->tx_len[aup->tx_head] = 0;
+		update_tx_stats(dev, ptxd->status, ptxd->len & 0x3ff);
 		ptxd->len = 0;
 	}
 
@@ -1082,17 +1929,15 @@
 
 	pDB = aup->tx_db_inuse[aup->tx_head];
 	memcpy((void *)pDB->vaddr, skb->data, skb->len);
-	if (skb->len < MAC_MIN_PKT_SIZE) {
-		for (i=skb->len; i<MAC_MIN_PKT_SIZE; i++) { 
+	if (skb->len < ETH_ZLEN) {
+		for (i=skb->len; i<ETH_ZLEN; i++) { 
 			((char *)pDB->vaddr)[i] = 0;
 		}
- 		aup->tx_len[aup->tx_head] = MAC_MIN_PKT_SIZE;
-		ptxd->len = MAC_MIN_PKT_SIZE;
+		ptxd->len = ETH_ZLEN;
 	}
-	else {
- 		aup->tx_len[aup->tx_head] = skb->len;
+	else
 		ptxd->len = skb->len;
-	}
+
 	ptxd->buff_stat = pDB->dma_addr | TX_DMA_ENABLE;
 	au_sync();
 	dev_kfree_skb(skb);
@@ -1137,8 +1982,9 @@
 	volatile rx_dma_t *prxd;
 	u32 buff_stat, status;
 	db_dest_t *pDB;
+	u32	frmlen;
 
-	if (au1000_debug > 4)
+	if (au1000_debug > 5)
 		printk("%s: au1000_rx head %d\n", dev->name, aup->rx_head);
 
 	prxd = aup->rx_dma_ring[aup->rx_head];
@@ -1150,7 +1996,9 @@
 		if (!(status & RX_ERROR))  {
 
 			/* good frame */
-			skb = dev_alloc_skb((status & RX_FRAME_LEN_MASK) + 2);
+			frmlen = (status & RX_FRAME_LEN_MASK);
+			frmlen -= 4; /* Remove FCS */
+			skb = dev_alloc_skb(frmlen + 2);
 			if (skb == NULL) {
 				printk(KERN_ERR
 				       "%s: Memory squeeze, dropping packet.\n",
@@ -1160,9 +2008,9 @@
 			}
 			skb->dev = dev;
 			skb_reserve(skb, 2);	/* 16 byte IP header align */
-			eth_copy_and_sum(skb, (unsigned char *)pDB->vaddr, 
-					status & RX_FRAME_LEN_MASK, 0);
-			skb_put(skb, status & RX_FRAME_LEN_MASK);
+			eth_copy_and_sum(skb,
+				(unsigned char *)pDB->vaddr, frmlen, 0);
+			skb_put(skb, frmlen);
 			skb->protocol = eth_type_trans(skb, dev);
 			netif_rx(skb);	/* pass the packet to upper layers */
 		}
@@ -1206,17 +2054,20 @@
 /*
  * Au1000 interrupt service routine.
  */
-irqreturn_t au1000_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t au1000_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
 	struct net_device *dev = (struct net_device *) dev_id;
 
 	if (dev == NULL) {
 		printk(KERN_ERR "%s: isr: null dev ptr\n", dev->name);
-		return IRQ_NONE;
+		return IRQ_RETVAL(1);
 	}
-	au1000_tx_ack(dev);
+
+	/* Handle RX interrupts first to minimize chance of overrun */
+
 	au1000_rx(dev);
-	return IRQ_HANDLED;
+	au1000_tx_ack(dev);
+	return IRQ_RETVAL(1);
 }
 
 
@@ -1233,6 +2084,23 @@
 	netif_wake_queue(dev);
 }
 
+
+static unsigned const ethernet_polynomial = 0x04c11db7U;
+static inline u32 ether_crc(int length, unsigned char *data)
+{
+    int crc = -1;
+
+    while(--length >= 0) {
+		unsigned char current_octet = *data++;
+		int bit;
+		for (bit = 0; bit < 8; bit++, current_octet >>= 1)
+			crc = (crc << 1) ^
+				((crc < 0) ^ (current_octet & 1) ? 
+				 ethernet_polynomial : 0);
+    }
+    return crc;
+}
+
 static void set_rx_mode(struct net_device *dev)
 {
 	struct au1000_private *aup = (struct au1000_private *) dev->priv;
@@ -1256,8 +2124,8 @@
 		mc_filter[1] = mc_filter[0] = 0;
 		for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count;
 			 i++, mclist = mclist->next) {
-			set_bit(ether_crc_le(ETH_ALEN, mclist->dmi_addr)>>26, 
-					mc_filter);
+			set_bit(ether_crc(ETH_ALEN, mclist->dmi_addr)>>26, 
+					(long *)mc_filter);
 		}
 		aup->mac->multi_hash_high = mc_filter[1];
 		aup->mac->multi_hash_low = mc_filter[0];
@@ -1269,28 +2137,28 @@
 
 static int au1000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 {
+	struct au1000_private *aup = (struct au1000_private *)dev->priv;
 	u16 *data = (u16 *)&rq->ifr_ifru;
 
-	/* fixme */
 	switch(cmd) { 
-	case SIOCGMIIPHY:	/* Get the address of the PHY in use. */
-		data[0] = PHY_ADDRESS;
-		return 0;
-
-	case SIOCGMIIREG:	/* Read the specified MII register. */
-		//data[3] = mdio_read(ioaddr, data[0], data[1]); 
-		return 0;
-
-	case SIOCSMIIREG:	/* Write the specified MII register */
-		if (!capable(CAP_NET_ADMIN))
-			return -EPERM;
-
-		//mdio_write(ioaddr, data[0], data[1], data[2]);
-		return 0;
-
-	default:
-		return -EOPNOTSUPP;
+		case SIOCDEVPRIVATE:	/* Get the address of the PHY in use. */
+		case SIOCGMIIPHY:
+		        if (!netif_running(dev)) return -EINVAL;
+			data[0] = aup->phy_addr;
+		case SIOCDEVPRIVATE+1:	/* Read the specified MII register. */
+		case SIOCGMIIREG:
+			data[3] =  mdio_read(dev, data[0], data[1]); 
+			return 0;
+		case SIOCDEVPRIVATE+2:	/* Write the specified MII register */
+		case SIOCSMIIREG: 
+			if (!capable(CAP_NET_ADMIN))
+				return -EPERM;
+			mdio_write(dev, data[0], data[1],data[2]);
+			return 0;
+		default:
+			return -EOPNOTSUPP;
 	}
+
 }
 
 
@@ -1352,7 +2220,6 @@
 			/* set Speed to 100Mbps, Half Duplex */
 			/* disable auto negotiation and enable 100MBit Mode */
 			control = mdio_read(dev, aup->phy_addr, MII_CONTROL);
-			printk("read control %x\n", control);
 			control &= ~(MII_CNTL_AUTO | MII_CNTL_FDX);
 			control |= MII_CNTL_F100;
 			mdio_write(dev, aup->phy_addr, MII_CONTROL, control);
diff -Nru a/drivers/net/au1000_eth.h b/drivers/net/au1000_eth.h
--- a/drivers/net/au1000_eth.h	2005-03-11 12:51:42 -08:00
+++ b/drivers/net/au1000_eth.h	2005-03-11 12:51:42 -08:00
@@ -1,10 +1,13 @@
 /*
- * Alchemy Semi Au1000 ethernet driver include file
+ *
+ * Alchemy Au1x00 ethernet driver include file
  *
  * Author: Pete Popov <ppopov@mvista.com>
  *
  * Copyright 2001 MontaVista Software Inc.
  *
+ * ########################################################################
+ *
  *  This program is free software; you can distribute it and/or modify it
  *  under the terms of the GNU General Public License (Version 2) as
  *  published by the Free Software Foundation.
@@ -17,14 +20,16 @@
  *  You should have received a copy of the GNU General Public License along
  *  with this program; if not, write to the Free Software Foundation, Inc.,
  *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ *
+ * 
  */
-#include <linux/config.h>
 
 
-#define NUM_INTERFACES 2
 #define MAC_IOSIZE 0x10000
-#define NUM_RX_DMA 4       /* Au1000 has 4 rx hardware descriptors */
-#define NUM_TX_DMA 4       /* Au1000 has 4 tx hardware descriptors */
+#define NUM_RX_DMA 4       /* Au1x00 has 4 rx hardware descriptors */
+#define NUM_TX_DMA 4       /* Au1x00 has 4 tx hardware descriptors */
 
 #define NUM_RX_BUFFS 4
 #define NUM_TX_BUFFS 4
@@ -33,12 +38,6 @@
 #define ETH_TX_TIMEOUT HZ/4
 #define MAC_MIN_PKT_SIZE 64
 
-#if defined(CONFIG_MIPS_PB1000) || defined(CONFIG_MIPS_PB1500) || defined(CONFIG_MIPS_PB1100)
-#define PHY_ADDRESS              0
-#define PHY_CONTROL_DEFAULT 0x3000
-#define PHY_CONTROL_REG_ADDR     0
-#endif
-
 #define MULTICAST_FILTER_LIMIT 64
 
 /* FIXME 
@@ -54,11 +53,13 @@
 #define MII_ANLPAR  0x0005
 #define MII_AEXP    0x0006
 #define MII_ANEXT   0x0007
-#define MII_LSI_CONFIG 0x0011
-#define MII_LSI_STAT   0x0012
-#define MII_AUX_CNTRL  0x0018
-#define MII_INT        0x001A
+#define MII_LSI_PHY_CONFIG 0x0011
+/* Status register */
+#define MII_LSI_PHY_STAT   0x0012
+#define MII_AMD_PHY_STAT   MII_LSI_PHY_STAT
+#define MII_INTEL_PHY_STAT 0x0011
 
+#define MII_AUX_CNTRL  0x0018
 /* mii registers specific to AMD 79C901 */
 #define	MII_STATUS_SUMMARY = 0x0018
 
@@ -121,23 +122,30 @@
 #define	MII_STSSUM_AUTO  0x0002
 #define MII_STSSUM_SPD   0x0001
 
-/* lsi status register */
-
-#define MII_LSI_STAT_FDX	0x0040
-#define MII_LSI_STAT_SPD	0x0080
+/* lsi phy status register */
+#define MII_LSI_PHY_STAT_FDX	0x0040
+#define MII_LSI_PHY_STAT_SPD	0x0080
+
+/* amd phy status register */
+#define MII_AMD_PHY_STAT_FDX	0x0800
+#define MII_AMD_PHY_STAT_SPD	0x0400
+
+/* intel phy status register */
+#define MII_INTEL_PHY_STAT_FDX	0x0200
+#define MII_INTEL_PHY_STAT_SPD	0x4000
 
 /* Auxilliary Control/Status Register */
 #define MII_AUX_FDX      0x0001
 #define MII_AUX_100      0x0002
 #define MII_AUX_F100     0x0004
 #define MII_AUX_ANEG     0x0008
-#define MII_FDX_LED	 0x8000
 
 typedef struct mii_phy {
 	struct mii_phy * next;
 	struct mii_chip_info * chip_info;
-	int phy_addr;
 	u16 status;
+	u32 *mii_control_reg;
+	u32 *mii_data_reg;
 } mii_phy_t;
 
 struct phy_ops {
@@ -197,7 +205,6 @@
 	db_dest_t db[NUM_RX_BUFFS+NUM_TX_BUFFS];
 	volatile rx_dma_t *rx_dma_ring[NUM_RX_DMA];
 	volatile tx_dma_t *tx_dma_ring[NUM_TX_DMA];
-	int tx_len[NUM_TX_DMA];
 	db_dest_t *rx_db_inuse[NUM_RX_DMA];
 	db_dest_t *tx_db_inuse[NUM_TX_DMA];
 	u32 rx_head;
@@ -205,6 +212,7 @@
 	u32 tx_tail;
 	u32 tx_full;
 
+	int mac_id;
 	mii_phy_t *mii;
 	struct phy_ops *phy_ops;
 	
@@ -218,9 +226,10 @@
 	u8 *hash_table;
 	u32 hash_mode;
 	u32 intr_work_done; /* number of Rx and Tx pkts processed in the isr */
-	u32 phy_addr;          /* PHY address */
+	int phy_addr;          /* phy address */
 	u32 options;           /* User-settable misc. driver options. */
 	u32 drv_flags;
+	int want_autoneg;
 	struct net_device_stats stats;
 	struct timer_list timer;
 	spinlock_t lock;       /* Serialise access to device */
diff -Nru a/drivers/net/b44.c b/drivers/net/b44.c
--- a/drivers/net/b44.c	2005-03-11 12:51:42 -08:00
+++ b/drivers/net/b44.c	2005-03-11 12:51:42 -08:00
@@ -1903,7 +1903,7 @@
 	}
 }
 
-static int b44_suspend(struct pci_dev *pdev, u32 state)
+static int b44_suspend(struct pci_dev *pdev, pm_message_t state)
 {
 	struct net_device *dev = pci_get_drvdata(pdev);
 	struct b44 *bp = netdev_priv(dev);
diff -Nru a/drivers/net/b44.h b/drivers/net/b44.h
--- a/drivers/net/b44.h	2005-03-11 12:51:47 -08:00
+++ b/drivers/net/b44.h	2005-03-11 12:51:47 -08:00
@@ -302,20 +302,6 @@
 #define B44_MII_TLEDCTRL	27	/* Traffic Meter LED */
 #define  MII_TLEDCTRL_ENABLE	0x0040
 
-/* XXX Add this to mii.h */
-#ifndef ADVERTISE_PAUSE
-#define ADVERTISE_PAUSE_CAP		0x0400
-#endif
-#ifndef ADVERTISE_PAUSE_ASYM
-#define ADVERTISE_PAUSE_ASYM		0x0800
-#endif
-#ifndef LPA_PAUSE
-#define LPA_PAUSE_CAP			0x0400
-#endif
-#ifndef LPA_PAUSE_ASYM
-#define LPA_PAUSE_ASYM			0x0800
-#endif
-
 struct dma_desc {
 	u32	ctrl;
 	u32	addr;
diff -Nru a/drivers/net/bagetlance.c b/drivers/net/bagetlance.c
--- a/drivers/net/bagetlance.c	2005-03-11 12:51:41 -08:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,1368 +0,0 @@
-/*
- * bagetlance.c: Ethernet driver for VME Lance cards on Baget/MIPS
- *      This code stealed and adopted from linux/drivers/net/atarilance.c
- *      See that for author info
- *
- * Copyright (C) 1998 Gleb Raiko & Vladimir Roganov
- */
-
-/* 
- * Driver code for Baget/Lance taken from atarilance.c, which also
- * works well in case of Besta. Most significant changes made here
- * related with 16BIT-only access to A24 space.
- */
-
-static char *version = "bagetlance.c: v1.1 11/10/98\n";
-
-#include <linux/module.h>
-#include <linux/stddef.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/errno.h>
-#include <linux/slab.h>
-#include <linux/interrupt.h>
-#include <linux/init.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/skbuff.h>
-#include <linux/bitops.h>
-
-#include <asm/irq.h>
-#include <asm/io.h>
-#include <asm/baget/baget.h>
-
-#define BAGET_LANCE_IRQ  BAGET_IRQ_MASK(0xdf)
-
-/*
- *  Define following if you don't need 16BIT-only access to Lance memory
- *  (Normally BAGET needs it)
- */
-#undef NORMAL_MEM_ACCESS 
-
-/* Debug level:
- *  0 = silent, print only serious errors
- *  1 = normal, print error messages
- *  2 = debug, print debug infos
- *  3 = debug, print even more debug infos (packet data)
- */
-
-#define	LANCE_DEBUG	1  
-
-#ifdef LANCE_DEBUG
-static int lance_debug = LANCE_DEBUG;
-#else
-static int lance_debug = 1;
-#endif
-MODULE_PARM(lance_debug, "i");
-MODULE_PARM_DESC(lance_debug, "Lance debug level (0-3)");
-MODULE_LICENSE("GPL");
-
-/* Print debug messages on probing? */
-#undef LANCE_DEBUG_PROBE
-
-#define	DPRINTK(n,a)							\
-	do {										\
-		if (lance_debug >= n)					\
-			printk a;							\
-	} while( 0 )
-
-#ifdef LANCE_DEBUG_PROBE
-# define PROBE_PRINT(a)	printk a
-#else
-# define PROBE_PRINT(a)
-#endif
-
-/* These define the number of Rx and Tx buffers as log2. (Only powers
- * of two are valid)
- * Much more rx buffers (32) are reserved than tx buffers (8), since receiving
- * is more time critical then sending and packets may have to remain in the
- * board's memory when main memory is low.
- */
-
-/* Baget Lance has 64K on-board memory, so it looks we can't increase
-   buffer quantity (40*1.5K is about 64K) */
-
-#define TX_LOG_RING_SIZE			3
-#define RX_LOG_RING_SIZE			5
-
-/* These are the derived values */
-
-#define TX_RING_SIZE			(1 << TX_LOG_RING_SIZE)
-#define TX_RING_LEN_BITS		(TX_LOG_RING_SIZE << 5)
-#define	TX_RING_MOD_MASK		(TX_RING_SIZE - 1)
-
-#define RX_RING_SIZE			(1 << RX_LOG_RING_SIZE)
-#define RX_RING_LEN_BITS		(RX_LOG_RING_SIZE << 5)
-#define	RX_RING_MOD_MASK		(RX_RING_SIZE - 1)
-
-/* The LANCE Rx and Tx ring descriptors. */
-struct lance_rx_head {
-	volatile unsigned short	base;		/* Low word of base addr */
-#ifdef NORMAL_MEM_ACCESS
-       /* Following two fields are joined into one short to guarantee
-		  16BIT access to Baget lance registers */
-	volatile unsigned char	flag;
-	unsigned char			base_hi;	/* High word of base addr (unused) */
-#else
-/* Following macros are used as replecements to 8BIT fields */
-#define GET_FLAG(h)    (((h)->flag_base_hi >> 8) & 0xff)
-#define SET_FLAG(h,f)  (h)->flag_base_hi = ((h)->flag_base_hi & 0xff) | \
-		                                                (((unsigned)(f)) << 8)
-	volatile unsigned short flag_base_hi; 
-#endif
-	volatile short			buf_length;	/* This length is 2s complement! */
-	volatile short			msg_length;	/* This length is "normal". */
-};
-
-
-struct lance_tx_head {
-	volatile unsigned short	base;		/* Low word of base addr */
-#ifdef NORMAL_MEM_ACCESS 
-/* See comments above about 8BIT-access Baget A24-space problems */
-	volatile unsigned char	flag;
-	unsigned char			base_hi;	/* High word of base addr (unused) */
-#else
-	volatile unsigned short  flag_base_hi;
-#endif
-	volatile short			length;		/* Length is 2s complement! */
-	volatile short			misc;
-};
-
-struct ringdesc {
-	volatile unsigned short	adr_lo;		/* Low 16 bits of address */
-#ifdef NORMAL_MEM_ACCESS 
-/* See comments above about 8BIT-access Bage A24-space problems */
-	unsigned char	len;		/* Length bits */
-	unsigned char	adr_hi;		/* High 8 bits of address (unused) */
-#else
-	volatile unsigned short  len_adr_hi;
-#endif
-};
-
-/* The LANCE initialization block, described in databook. */
-struct lance_init_block {
-	unsigned short	mode;		/* Pre-set mode */
-	unsigned char	hwaddr[6];	/* Physical ethernet address */
-	unsigned		filter[2];	/* Multicast filter (unused). */
-	/* Receive and transmit ring base, along with length bits. */
-	struct ringdesc	rx_ring;
-	struct ringdesc	tx_ring;
-};
-
-/* The whole layout of the Lance shared memory */
-struct lance_memory {
-	struct lance_init_block	init;
-	struct lance_tx_head	tx_head[TX_RING_SIZE];
-	struct lance_rx_head	rx_head[RX_RING_SIZE];
-	char					packet_area[0];	/* packet data follow after the
-											 * init block and the ring
-											 * descriptors and are located
-											 * at runtime */
-};
-
-/* RieblCard specifics:
- * The original TOS driver for these cards reserves the area from offset
- * 0xee70 to 0xeebb for storing configuration data. Of interest to us is the
- * Ethernet address there, and the magic for verifying the data's validity.
- * The reserved area isn't touch by packet buffers. Furthermore, offset 0xfffe
- * is reserved for the interrupt vector number.
- */
-#define	RIEBL_RSVD_START	0xee70
-#define	RIEBL_RSVD_END		0xeec0
-#define RIEBL_MAGIC			0x09051990
-#define RIEBL_MAGIC_ADDR	((unsigned long *)(((char *)MEM) + 0xee8a))
-#define RIEBL_HWADDR_ADDR	((unsigned char *)(((char *)MEM) + 0xee8e))
-#define RIEBL_IVEC_ADDR		((unsigned short *)(((char *)MEM) + 0xfffe))
-
-/* This is a default address for the old RieblCards without a battery
- * that have no ethernet address at boot time. 00:00:36:04 is the
- * prefix for Riebl cards, the 00:00 at the end is arbitrary.
- */
-
-static unsigned char OldRieblDefHwaddr[6] = {
-	0x00, 0x00, 0x36, 0x04, 0x00, 0x00
-};
-
-/* I/O registers of the Lance chip */
-
-struct lance_ioreg {
-/* base+0x0 */	volatile unsigned short	data;
-/* base+0x2 */	volatile unsigned short	addr;
-				unsigned char			_dummy1[3];
-/* base+0x7 */	volatile unsigned char	ivec;
-				unsigned char			_dummy2[5];
-/* base+0xd */	volatile unsigned char	eeprom;
-				unsigned char			_dummy3;
-/* base+0xf */	volatile unsigned char	mem;
-};
-
-/* Types of boards this driver supports */
-
-enum lance_type {
-	OLD_RIEBL,		/* old Riebl card without battery */
-	NEW_RIEBL,		/* new Riebl card with battery */
-	PAM_CARD		/* PAM card with EEPROM */
-};
-
-static char *lance_names[] = {
-	"Riebl-Card (without battery)",
-	"Riebl-Card (with battery)",
-	"PAM intern card"
-};
-
-/* The driver's private device structure */
-
-struct lance_private {
-	enum lance_type		cardtype;
-	struct lance_ioreg	*iobase;
-	struct lance_memory	*mem;
-	int					cur_rx, cur_tx;	/* The next free ring entry */
-	int					dirty_tx;		/* Ring entries to be freed. */
-						/* copy function */
-	void				*(*memcpy_f)( void *, const void *, size_t );
-	struct net_device_stats stats;
-/* These two must be longs for set_bit() */
-	long				tx_full;
-	long				lock;
-};
-
-/* I/O register access macros */
-
-#define	MEM		lp->mem
-#define	DREG	IO->data
-#define	AREG	IO->addr
-#define	REGA(a)	( AREG = (a), DREG )
-
-/* Definitions for packet buffer access: */
-#define PKT_BUF_SZ		1544
-/* Get the address of a packet buffer corresponding to a given buffer head */
-#define	PKTBUF_ADDR(head)	(((unsigned char *)(MEM)) + (head)->base)
-
-/* Possible memory/IO addresses for probing */
-
-struct lance_addr {
-	unsigned long	memaddr;
-	unsigned long	ioaddr;
-	int				slow_flag;
-} lance_addr_list[] = {
-	{ BAGET_LANCE_MEM_BASE, BAGET_LANCE_IO_BASE, 1 }	/* Baget Lance */
-};
-
-#define	N_LANCE_ADDR	(sizeof(lance_addr_list)/sizeof(*lance_addr_list))
-
-
-#define LANCE_HI_BASE (0xff & (BAGET_LANCE_MEM_BASE >> 16))
-
-/* Definitions for the Lance */
-
-/* tx_head flags */
-#define TMD1_ENP		0x01	/* end of packet */
-#define TMD1_STP		0x02	/* start of packet */
-#define TMD1_DEF		0x04	/* deferred */
-#define TMD1_ONE		0x08	/* one retry needed */
-#define TMD1_MORE		0x10	/* more than one retry needed */
-#define TMD1_ERR		0x40	/* error summary */
-#define TMD1_OWN 		0x80	/* ownership (set: chip owns) */
-
-#define TMD1_OWN_CHIP	TMD1_OWN
-#define TMD1_OWN_HOST	0
-
-/* tx_head misc field */
-#define TMD3_TDR		0x03FF	/* Time Domain Reflectometry counter */
-#define TMD3_RTRY		0x0400	/* failed after 16 retries */
-#define TMD3_LCAR		0x0800	/* carrier lost */
-#define TMD3_LCOL		0x1000	/* late collision */
-#define TMD3_UFLO		0x4000	/* underflow (late memory) */
-#define TMD3_BUFF		0x8000	/* buffering error (no ENP) */
-
-/* rx_head flags */
-#define RMD1_ENP		0x01	/* end of packet */
-#define RMD1_STP		0x02	/* start of packet */
-#define RMD1_BUFF		0x04	/* buffer error */
-#define RMD1_CRC		0x08	/* CRC error */
-#define RMD1_OFLO		0x10	/* overflow */
-#define RMD1_FRAM		0x20	/* framing error */
-#define RMD1_ERR		0x40	/* error summary */
-#define RMD1_OWN 		0x80	/* ownership (set: ship owns) */
-
-#define RMD1_OWN_CHIP	RMD1_OWN
-#define RMD1_OWN_HOST	0
-
-/* register names */
-#define CSR0	0		/* mode/status */
-#define CSR1	1		/* init block addr (low) */
-#define CSR2	2		/* init block addr (high) */
-#define CSR3	3		/* misc */
-#define CSR8	8	  	/* address filter */
-#define CSR15	15		/* promiscuous mode */
-
-/* CSR0 */
-/* (R=readable, W=writeable, S=set on write, C=clear on write) */
-#define CSR0_INIT	0x0001		/* initialize (RS) */
-#define CSR0_STRT	0x0002		/* start (RS) */
-#define CSR0_STOP	0x0004		/* stop (RS) */
-#define CSR0_TDMD	0x0008		/* transmit demand (RS) */
-#define CSR0_TXON	0x0010		/* transmitter on (R) */
-#define CSR0_RXON	0x0020		/* receiver on (R) */
-#define CSR0_INEA	0x0040		/* interrupt enable (RW) */
-#define CSR0_INTR	0x0080		/* interrupt active (R) */
-#define CSR0_IDON	0x0100		/* initialization done (RC) */
-#define CSR0_TINT	0x0200		/* transmitter interrupt (RC) */
-#define CSR0_RINT	0x0400		/* receiver interrupt (RC) */
-#define CSR0_MERR	0x0800		/* memory error (RC) */
-#define CSR0_MISS	0x1000		/* missed frame (RC) */
-#define CSR0_CERR	0x2000		/* carrier error (no heartbeat :-) (RC) */
-#define CSR0_BABL	0x4000		/* babble: tx-ed too many bits (RC) */
-#define CSR0_ERR	0x8000		/* error (RC) */
-
-/* CSR3 */
-#define CSR3_BCON	0x0001		/* byte control */
-#define CSR3_ACON	0 // fixme: 0x0002		/* ALE control */
-#define CSR3_BSWP	0x0004		/* byte swap (1=big endian) */
-
-
-
-/***************************** Prototypes *****************************/
-
-static int addr_accessible( volatile void *regp, int wordflag, int
-                            writeflag );
-static int lance_probe1( struct net_device *dev, struct lance_addr *init_rec );
-static int lance_open( struct net_device *dev );
-static void lance_init_ring( struct net_device *dev );
-static int lance_start_xmit( struct sk_buff *skb, struct net_device *dev );
-static irqreturn_t lance_interrupt( int irq, void *dev_id, struct pt_regs *fp );
-static int lance_rx( struct net_device *dev );
-static int lance_close( struct net_device *dev );
-static struct net_device_stats *lance_get_stats( struct net_device *dev );
-static void set_multicast_list( struct net_device *dev );
-static int lance_set_mac_address( struct net_device *dev, void *addr );
-
-/************************* End of Prototypes **************************/
-
-/* Network traffic statistic (bytes) */
-
-int lance_stat = 0;
-
-static void update_lance_stat (int len) {
-		lance_stat += len;
-}
-
-/* 
-   This function is used to access Baget/Lance memory to avoid 
-   8/32BIT access to VAC A24 space 
-   ALL memcpy calls was chenged to this function to avoid dbe problems
-   Don't confuse with function name -- it stays from original code
-*/
-
-void *slow_memcpy( void *dst, const void *src, size_t len )
-
-{	
-	unsigned long to     = (unsigned long)dst;
-	unsigned long from   = (unsigned long)src;
-	unsigned long to_end = to +len;
-	
-	/* Unaligned flags */
-
-	int odd_from   = from   & 1;
-	int odd_to     = to     & 1;
-	int odd_to_end = to_end & 1;
-
-	/* Align for 16BIT-access first */
-
-	register unsigned short *from_a   = (unsigned short*) (from   & ~1);
-	register unsigned short *to_a     = (unsigned short*) (to     & ~1); 
-	register unsigned short *to_end_a = (unsigned short*) (to_end & ~1);
-
-	/* Caching values -- not in loop invariant */
-
-	register unsigned short from_v; 
-	register unsigned short to_v;
-
-	/* Invariant is: from_a and to_a are pointers before or exactly to
-	   currently copying byte */
-
-	if (odd_to) { 
-			/* First byte unaligned case */
-			from_v = *from_a;
-			to_v   = *to_a;
-
-			to_v &= ~0xff;
-			to_v |=  0xff & (from_v >> (odd_from ? 0 : 8));
-			*to_a++ = to_v;
-
-			if (odd_from) from_a++;
-	}
-    if (odd_from == odd_to) {
-			/* Same parity */
-			while (to_a + 7 < to_end_a) {
-					unsigned long dummy1, dummy2;
-					unsigned long reg1, reg2, reg3, reg4;
-
-					__asm__ __volatile__(
-					".set\tnoreorder\n\t"
-					".set\tnoat\n\t"
-					"lh\t%2,0(%1)\n\t"
-					"nop\n\t"
-					 "lh\t%3,2(%1)\n\t"
-					"sh\t%2,0(%0)\n\t"
-					   "lh\t%4,4(%1)\n\t"
-					 "sh\t%3,2(%0)\n\t"
-					    "lh\t%5,6(%1)\n\t"
-					   "sh\t%4,4(%0)\n\t"
-					"lh\t%2,8(%1)\n\t"
-					    "sh\t%5,6(%0)\n\t"
-					 "lh\t%3,10(%1)\n\t"
-					"sh\t%2,8(%0)\n\t"
-					  "lh\t%4,12(%1)\n\t"
-					 "sh\t%3,10(%0)\n\t"
-					    "lh\t%5,14(%1)\n\t"
-					  "sh\t%4,12(%0)\n\t"
-					 "nop\n\t"
-					    "sh\t%5,14(%0)\n\t"
-					".set\tat\n\t"
-					".set\treorder"
-					:"=r" (dummy1), "=r" (dummy2),
-					"=&r" (reg1), "=&r" (reg2), "=&r" (reg3), "=&r" (reg4)
-					:"0" (to_a), "1" (from_a)
-					:"memory");
-
-					to_a   += 8;
-					from_a += 8;
-
-			}
-			while (to_a < to_end_a) {
-					*to_a++ = *from_a++;
-			}
-	} else {
-			/* Different parity */
-			from_v = *from_a;
-			while (to_a < to_end_a) {
-					unsigned short from_v_next;
-					from_v_next = *++from_a;
-					*to_a++ = ((from_v & 0xff)<<8) | ((from_v_next>>8) & 0xff);
-					from_v = from_v_next; 
-			}
-
-	}
-	if (odd_to_end) {
-			/* Last byte unaligned case */
-			to_v = *to_a;
-			from_v = *from_a;
-
-			to_v &= ~0xff00;
-			if (odd_from == odd_to) {
-					to_v |= from_v & 0xff00;
-			} else {
-					to_v |= (from_v<<8) & 0xff00;
-			}
-
-			*to_a = to_v;
-	}
-
-	update_lance_stat( len );
-
-	return( dst );
-}
-
-
-struct net_device * __init bagetlance_probe(int unit)
-{
-	struct net_device *dev;
-	int i;
-	static int found;
-	int err = -ENODEV;
-
-	if (found)
-		/* Assume there's only one board possible... That seems true, since
-		 * the Riebl/PAM board's address cannot be changed. */
-		return ERR_PTR(-ENODEV);
-
-	dev = alloc_etherdev(sizeof(struct lance_private));
-	if (!dev)
-		return ERR_PTR(-ENOMEM);
-
-	SET_MODULE_OWNER(dev);
-
-	for( i = 0; i < N_LANCE_ADDR; ++i ) {
-		if (lance_probe1( dev, &lance_addr_list[i] )) {
-			found = 1;
-			break;
-		}
-	}
-	if (!found)
-		goto out;
-	err = register_netdev(dev);
-	if (err)
-		goto out1;
-	return dev;
-out1:
-	free_irq(dev->irq, dev);
-out:
-	free_netdev(dev);
-	return ERR_PTR(err);
-}
-
-/* Derived from hwreg_present() in vme/config.c: */
-
-static int __init addr_accessible( volatile void *regp, 
-				   int wordflag, 
-				   int writeflag )
-{	
-		/* We have a fine function to do it */
-		extern int try_read(unsigned long, int);
-		return try_read((unsigned long)regp, sizeof(short)) != -1;   
-}
-
-
-
-/* Original atari driver uses it */
-#define IRQ_TYPE_PRIO SA_INTERRUPT
-#define IRQ_SOURCE_TO_VECTOR(x) (x)
-
-static int __init lance_probe1( struct net_device *dev,
-				struct lance_addr *init_rec )
-
-{	volatile unsigned short *memaddr =
-		(volatile unsigned short *)init_rec->memaddr;
-	volatile unsigned short *ioaddr =
-		(volatile unsigned short *)init_rec->ioaddr;
-	struct lance_private	*lp;
-	struct lance_ioreg		*IO;
-	int 					i;
-	static int 				did_version;
-	unsigned short			save1, save2;
-
-	PROBE_PRINT(( "Probing for Lance card at mem %#lx io %#lx\n",
-				  (long)memaddr, (long)ioaddr ));
-
-	/* Test whether memory readable and writable */
-	PROBE_PRINT(( "lance_probe1: testing memory to be accessible\n" ));
-	if (!addr_accessible( memaddr, 1, 1 )) goto probe_fail;
-
-	if ((unsigned long)memaddr >= KSEG2) {
-			/* FIXME: do we need to undo that on cleanup paths? */
-			extern int kseg2_alloc_io (unsigned long addr, unsigned long size);
-			if (kseg2_alloc_io((unsigned long)memaddr, BAGET_LANCE_MEM_SIZE)) {
-					printk("bagetlance: unable map lance memory\n");
-					goto probe_fail;
-			}
-	}
-
-	/* Written values should come back... */
-	PROBE_PRINT(( "lance_probe1: testing memory to be writable (1)\n" ));
-	save1 = *memaddr;
-	*memaddr = 0x0001;
-	if (*memaddr != 0x0001) goto probe_fail;
-	PROBE_PRINT(( "lance_probe1: testing memory to be writable (2)\n" ));
-	*memaddr = 0x0000;
-	if (*memaddr != 0x0000) goto probe_fail;
-	*memaddr = save1;
-
-	/* First port should be readable and writable */
-	PROBE_PRINT(( "lance_probe1: testing ioport to be accessible\n" ));
-	if (!addr_accessible( ioaddr, 1, 1 )) goto probe_fail;
-
-	/* and written values should be readable */
-	PROBE_PRINT(( "lance_probe1: testing ioport to be writeable\n" ));
-	save2 = ioaddr[1];
-	ioaddr[1] = 0x0001;
-	if (ioaddr[1] != 0x0001) goto probe_fail;
-
-	/* The CSR0_INIT bit should not be readable */
-	PROBE_PRINT(( "lance_probe1: testing CSR0 register function (1)\n" ));
-	save1 = ioaddr[0];
-	ioaddr[1] = CSR0;
-	ioaddr[0] = CSR0_INIT | CSR0_STOP;
-	if (ioaddr[0] != CSR0_STOP) {
-		ioaddr[0] = save1;
-		ioaddr[1] = save2;
-		goto probe_fail;
-	}
-	PROBE_PRINT(( "lance_probe1: testing CSR0 register function (2)\n" ));
-	ioaddr[0] = CSR0_STOP;
-	if (ioaddr[0] != CSR0_STOP) {
-		ioaddr[0] = save1;
-		ioaddr[1] = save2;
-		goto probe_fail;
-	}
-
-	/* Now ok... */
-	PROBE_PRINT(( "lance_probe1: Lance card detected\n" ));
-	goto probe_ok;
-
-  probe_fail:
-	return( 0 );
-
-  probe_ok:
-	lp = netdev_priv(dev);
-	MEM = (struct lance_memory *)memaddr;
-	IO = lp->iobase = (struct lance_ioreg *)ioaddr;
-	dev->base_addr = (unsigned long)ioaddr; /* informational only */
-	lp->memcpy_f = init_rec->slow_flag ? slow_memcpy : memcpy;
-
-	REGA( CSR0 ) = CSR0_STOP;
-
-	/* Now test for type: If the eeprom I/O port is readable, it is a
-	 * PAM card */
-	if (addr_accessible( &(IO->eeprom), 0, 0 )) {
-		/* Switch back to Ram */
-		i = IO->mem;
-		lp->cardtype = PAM_CARD;
-	}
-#ifdef NORMAL_MEM_ACCESS
-	else if (*RIEBL_MAGIC_ADDR == RIEBL_MAGIC) {
-#else
-	else if (({
-			unsigned short *a = (unsigned short*)RIEBL_MAGIC_ADDR;
-		    (((int)a[0]) << 16) + ((int)a[1]) == RIEBL_MAGIC;
-	})) {
-#endif
-		lp->cardtype = NEW_RIEBL;
-	}
-	else
-		lp->cardtype = OLD_RIEBL;
-
-	if (lp->cardtype == PAM_CARD ||
-		memaddr == (unsigned short *)0xffe00000) {
-		/* PAMs card and Riebl on ST use level 5 autovector */
-		if (request_irq(BAGET_LANCE_IRQ, lance_interrupt, IRQ_TYPE_PRIO,
-		            "PAM/Riebl-ST Ethernet", dev))
-			goto probe_fail;
-		dev->irq = (unsigned short)BAGET_LANCE_IRQ;
-	}
-	else {
-		/* For VME-RieblCards, request a free VME int;
-		 * (This must be unsigned long, since dev->irq is short and the
-		 * IRQ_MACHSPEC bit would be cut off...)
-		 */
-		unsigned long irq = BAGET_LANCE_IRQ; 
-		if (!irq) {
-			printk( "Lance: request for VME interrupt failed\n" );
-			goto probe_fail;
-		}
-		if (request_irq(irq, lance_interrupt, IRQ_TYPE_PRIO,
-		            "Riebl-VME Ethernet", dev))
-			goto probe_fail;
-		dev->irq = irq;
-	}
-
-	printk("%s: %s at io %#lx, mem %#lx, irq %d%s, hwaddr ",
-		   dev->name, lance_names[lp->cardtype],
-		   (unsigned long)ioaddr,
-		   (unsigned long)memaddr,
-		   dev->irq,
-		   init_rec->slow_flag ? " (slow memcpy)" : "" );
-
-	/* Get the ethernet address */
-	switch( lp->cardtype ) {
-	  case OLD_RIEBL:
-		/* No ethernet address! (Set some default address) */
-		slow_memcpy( dev->dev_addr, OldRieblDefHwaddr, 6 );
-		break;
-	  case NEW_RIEBL:
-		lp->memcpy_f( dev->dev_addr, RIEBL_HWADDR_ADDR, 6 );
-		break;
-	  case PAM_CARD:
-		i = IO->eeprom;
-		for( i = 0; i < 6; ++i )
-			dev->dev_addr[i] =
-				((((unsigned short *)MEM)[i*2] & 0x0f) << 4) |
-				((((unsigned short *)MEM)[i*2+1] & 0x0f));
-		i = IO->mem;
-		break;
-	}
-	for( i = 0; i < 6; ++i )
-		printk( "%02x%s", dev->dev_addr[i], (i < 5) ? ":" : "\n" );
-	if (lp->cardtype == OLD_RIEBL) {
-		printk( "%s: Warning: This is a default ethernet address!\n",
-				dev->name );
-		printk( "      Use \"ifconfig hw ether ...\" to set the address.\n" );
-	}
-
-	MEM->init.mode = 0x0000;		/* Disable Rx and Tx. */
-
-	{
-			unsigned char hwaddr[6];
-			for( i = 0; i < 6; i++ ) 
-					hwaddr[i] = dev->dev_addr[i^1]; /* <- 16 bit swap! */
-			slow_memcpy(MEM->init.hwaddr, hwaddr, sizeof(hwaddr));
-	}
-
-	MEM->init.filter[0] = 0x00000000;
-	MEM->init.filter[1] = 0x00000000;
-	MEM->init.rx_ring.adr_lo = offsetof( struct lance_memory, rx_head );
-
-#ifdef NORMAL_MEM_ACCESS
-	MEM->init.rx_ring.adr_hi = LANCE_HI_BASE; 
-	MEM->init.rx_ring.len    = RX_RING_LEN_BITS;
-#else
-	MEM->init.rx_ring.len_adr_hi = 
-			((unsigned)RX_RING_LEN_BITS << 8) | LANCE_HI_BASE;
-#endif
-
-
-	MEM->init.tx_ring.adr_lo = offsetof( struct lance_memory, tx_head );
-
-#ifdef NORMAL_MEM_ACCESS
-	MEM->init.tx_ring.adr_hi = LANCE_HI_BASE; 
-	MEM->init.tx_ring.len    = TX_RING_LEN_BITS;
-#else
-	MEM->init.tx_ring.len_adr_hi = 
-			((unsigned)TX_RING_LEN_BITS<<8) | LANCE_HI_BASE;
-#endif
-
-	if (lp->cardtype == PAM_CARD)
-		IO->ivec = IRQ_SOURCE_TO_VECTOR(dev->irq);
-	else
-		*RIEBL_IVEC_ADDR = IRQ_SOURCE_TO_VECTOR(dev->irq);
-
-	if (did_version++ == 0)
-		DPRINTK( 1, ( version ));
-
-	/* The LANCE-specific entries in the device structure. */
-	dev->open = &lance_open;
-	dev->hard_start_xmit = &lance_start_xmit;
-	dev->stop = &lance_close;
-	dev->get_stats = &lance_get_stats;
-	dev->set_multicast_list = &set_multicast_list;
-	dev->set_mac_address = &lance_set_mac_address;
-	dev->start = 0;
-
-	memset( &lp->stats, 0, sizeof(lp->stats) );
-
-	return( 1 );
-}
-
-
-static int lance_open( struct net_device *dev )
-
-{	struct lance_private *lp = netdev_priv(dev);
-	struct lance_ioreg	 *IO = lp->iobase;
-	int i;
-
-	DPRINTK( 2, ( "%s: lance_open()\n", dev->name ));
-
-	lance_init_ring(dev);
-	/* Re-initialize the LANCE, and start it when done. */
-
-	REGA( CSR3 ) = CSR3_BSWP | (lp->cardtype == PAM_CARD ? CSR3_ACON : 0);
-	REGA( CSR2 ) = 0;
-	REGA( CSR1 ) = 0;
-	REGA( CSR0 ) = CSR0_INIT;
-	/* From now on, AREG is kept to point to CSR0 */
-
-	i = 1000000;
-	while (--i > 0)
-		if (DREG & CSR0_IDON)
-			break;
-	if (i < 0 || (DREG & CSR0_ERR)) {
-		DPRINTK( 2, ( "lance_open(): opening %s failed, i=%d, csr0=%04x\n",
-					  dev->name, i, DREG ));
-		DREG = CSR0_STOP;
-		return( -EIO );
-	}
-	DREG = CSR0_IDON;
-	DREG = CSR0_STRT;
-	DREG = CSR0_INEA;
-
-	dev->tbusy = 0;
-	dev->interrupt = 0;
-	dev->start = 1;
-
-	DPRINTK( 2, ( "%s: LANCE is open, csr0 %04x\n", dev->name, DREG ));
-	return( 0 );
-}
-
-
-/* Initialize the LANCE Rx and Tx rings. */
-
-static void lance_init_ring( struct net_device *dev )
-
-{	struct lance_private *lp = netdev_priv(dev);
-	int i;
-	unsigned offset;
-
-	lp->lock = 0;
-	lp->tx_full = 0;
-	lp->cur_rx = lp->cur_tx = 0;
-	lp->dirty_tx = 0;
-
-	offset = offsetof( struct lance_memory, packet_area );
-
-/* If the packet buffer at offset 'o' would conflict with the reserved area
- * of RieblCards, advance it */
-#define	CHECK_OFFSET(o)														 \
-	do {																	 \
-		if (lp->cardtype == OLD_RIEBL || lp->cardtype == NEW_RIEBL) {		 \
-			if (((o) < RIEBL_RSVD_START) ? (o)+PKT_BUF_SZ > RIEBL_RSVD_START \
-										 : (o) < RIEBL_RSVD_END)			 \
-				(o) = RIEBL_RSVD_END;										 \
-		}																	 \
-	} while(0)
-
-	for( i = 0; i < TX_RING_SIZE; i++ ) {
-		CHECK_OFFSET(offset);
-		MEM->tx_head[i].base = offset;
-#ifdef NORMAL_MEM_ACCESS
-		MEM->tx_head[i].flag = TMD1_OWN_HOST;
- 		MEM->tx_head[i].base_hi = LANCE_HI_BASE;
-#else
-		MEM->tx_head[i].flag_base_hi = 
-				(TMD1_OWN_HOST<<8) | LANCE_HI_BASE;
-#endif
-		MEM->tx_head[i].length = 0;
-		MEM->tx_head[i].misc = 0;
-		offset += PKT_BUF_SZ;
-	}
-
-	for( i = 0; i < RX_RING_SIZE; i++ ) {
-		CHECK_OFFSET(offset);
-		MEM->rx_head[i].base = offset;
-#ifdef NORMAL_MEM_ACCESS
-		MEM->rx_head[i].flag = TMD1_OWN_CHIP;
-		MEM->rx_head[i].base_hi = LANCE_HI_BASE; 
-#else
-		MEM->rx_head[i].flag_base_hi = 
-				(TMD1_OWN_CHIP<<8) | LANCE_HI_BASE;
-#endif
-		MEM->rx_head[i].buf_length = -PKT_BUF_SZ;
-		MEM->rx_head[i].msg_length = 0;
-		offset += PKT_BUF_SZ;
-	}
-}
-
-
-static int lance_start_xmit( struct sk_buff *skb, struct net_device *dev )
-
-{	struct lance_private *lp = netdev_priv(dev);
-	struct lance_ioreg	 *IO = lp->iobase;
-	int entry, len;
-	struct lance_tx_head *head;
-	unsigned long flags;
-
-	/* The old LANCE chips doesn't automatically pad buffers to min. size. */
-	len = (ETH_ZLEN < skb->len) ? skb->len : ETH_ZLEN;
-	/* PAM-Card has a bug: Can only send packets with even number of bytes! */
-	if (lp->cardtype == PAM_CARD && (len & 1))
-		++len;
-
-	if (len > skb->len) {
-		skb = skb_padto(skb, len);
-		if (skb == NULL)
-			return 0;
-	}	
-
-	/* Transmitter timeout, serious problems. */
-	if (dev->tbusy) {
-		int tickssofar = jiffies - dev->trans_start;
-		if (tickssofar < 20)
-			return( 1 );
-		AREG = CSR0;
-		DPRINTK( 1, ( "%s: transmit timed out, status %04x, resetting.\n",
-					  dev->name, DREG ));
-		DREG = CSR0_STOP;
-		/*
-		 * Always set BSWP after a STOP as STOP puts it back into
-		 * little endian mode.
-		 */
-		REGA( CSR3 ) = CSR3_BSWP | (lp->cardtype == PAM_CARD ? CSR3_ACON : 0);
-		lp->stats.tx_errors++;
-#ifndef final_version
-		{	int i;
-			DPRINTK( 2, ( "Ring data: dirty_tx %d cur_tx %d%s cur_rx %d\n",
-						  lp->dirty_tx, lp->cur_tx,
-						  lp->tx_full ? " (full)" : "",
-						  lp->cur_rx ));
-			for( i = 0 ; i < RX_RING_SIZE; i++ )
-				DPRINTK( 2, ( "rx #%d: base=%04x blen=%04x mlen=%04x\n",
-							  i, MEM->rx_head[i].base,
-							  -MEM->rx_head[i].buf_length,
-							  MEM->rx_head[i].msg_length ));
-			for( i = 0 ; i < TX_RING_SIZE; i++ )
-				DPRINTK( 2, ( "tx #%d: base=%04x len=%04x misc=%04x\n",
-							  i, MEM->tx_head[i].base,
-							  -MEM->tx_head[i].length,
-							  MEM->tx_head[i].misc ));
-		}
-#endif
-		lance_init_ring(dev);
-		REGA( CSR0 ) = CSR0_INEA | CSR0_INIT | CSR0_STRT;
-
-		dev->tbusy = 0;
-		dev->trans_start = jiffies;
-
-		return( 0 );
-	}
-
-	DPRINTK( 2, ( "%s: lance_start_xmit() called, csr0 %4.4x.\n",
-				  dev->name, DREG ));
-
-	/* Block a timer-based transmit from overlapping.  This could better be
-	   done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */
-	if (test_and_set_bit( 0, (void*)&dev->tbusy ) != 0) {
-		DPRINTK( 0, ( "%s: Transmitter access conflict.\n", dev->name ));
-		return 1;
-	}
-
-	if (test_and_set_bit( 0, (void*)&lp->lock ) != 0) {
-		DPRINTK( 0, ( "%s: tx queue lock!.\n", dev->name ));
-		/* don't clear dev->tbusy flag. */
-		return 1;
-	}
-
-	/* Fill in a Tx ring entry */
-	if (lance_debug >= 3) {
-		u_char *p;
-		int i;
-		printk( "%s: TX pkt type 0x%04x from ", dev->name,
-				((u_short *)skb->data)[6]);
-		for( p = &((u_char *)skb->data)[6], i = 0; i < 6; i++ )
-			printk("%02x%s", *p++, i != 5 ? ":" : "" );
-		printk(" to ");
-		for( p = (u_char *)skb->data, i = 0; i < 6; i++ )
-			printk("%02x%s", *p++, i != 5 ? ":" : "" );
-		printk(" data at 0x%08x len %d\n", (int)skb->data,
-			   (int)skb->len );
-	}
-
-	/* We're not prepared for the int until the last flags are set/reset. And
-	 * the int may happen already after setting the OWN_CHIP... */
-	save_flags(flags);
-	cli();
-
-	/* Mask to ring buffer boundary. */
-	entry = lp->cur_tx & TX_RING_MOD_MASK;
-	head  = &(MEM->tx_head[entry]);
-
-	/* Caution: the write order is important here, set the "ownership" bits
-	 * last.
-	 */
-
-	head->length = -len;
-	head->misc = 0;
-	lp->memcpy_f( PKTBUF_ADDR(head), (void *)skb->data, skb->len );
-#ifdef NORMAL_MEM_ACCESS
-	head->flag = TMD1_OWN_CHIP | TMD1_ENP | TMD1_STP;
-#else
-    SET_FLAG(head,(TMD1_OWN_CHIP | TMD1_ENP | TMD1_STP));
-#endif
-	lp->stats.tx_bytes += skb->len;
-	dev_kfree_skb( skb );
-	lp->cur_tx++;
-	while( lp->cur_tx >= TX_RING_SIZE && lp->dirty_tx >= TX_RING_SIZE ) {
-		lp->cur_tx -= TX_RING_SIZE;
-		lp->dirty_tx -= TX_RING_SIZE;
-	}
-
-	/* Trigger an immediate send poll. */
-	DREG = CSR0_INEA | CSR0_TDMD;
-	dev->trans_start = jiffies;
-
-	lp->lock = 0;
-#ifdef NORMAL_MEM_ACCESS
-	if ((MEM->tx_head[(entry+1) & TX_RING_MOD_MASK].flag & TMD1_OWN) ==
-#else
-	if ((GET_FLAG(&MEM->tx_head[(entry+1) & TX_RING_MOD_MASK]) & TMD1_OWN) ==
-#endif
-		TMD1_OWN_HOST)
-		dev->tbusy = 0;
-	else
-		lp->tx_full = 1;
-	restore_flags(flags);
-
-	return 0;
-}
-
-/* The LANCE interrupt handler. */
-
-static irqreturn_t lance_interrupt( int irq, void *dev_id, struct pt_regs *fp)
-{
-	struct net_device *dev = dev_id;
-	struct lance_private *lp;
-	struct lance_ioreg	 *IO;
-	int csr0, boguscnt = 10;
-	int handled = 0;
-
-	if (dev == NULL) {
-		DPRINTK( 1, ( "lance_interrupt(): interrupt for unknown device.\n" ));
-		return IRQ_NONE;
-	}
-
-	lp = netdev_priv(dev);
-	IO = lp->iobase;
-	AREG = CSR0;
-
-	if (dev->interrupt) {
-			DPRINTK( 1, ( "Re-entering CAUSE=%08x STATUS=%08x\n",  
-						  read_32bit_cp0_register(CP0_CAUSE),  
-						  read_32bit_cp0_register(CP0_STATUS) ));
-			panic("lance: interrupt handler reentered !");
-	}
-
-	dev->interrupt = 1;
-
-	while( ((csr0 = DREG) & (CSR0_ERR | CSR0_TINT | CSR0_RINT)) &&
-		   --boguscnt >= 0) {
-		handled = 1;
-		/* Acknowledge all of the current interrupt sources ASAP. */
-		DREG = csr0 & ~(CSR0_INIT | CSR0_STRT | CSR0_STOP |
-									CSR0_TDMD | CSR0_INEA);
-
-		DPRINTK( 2, ( "%s: interrupt  csr0=%04x new csr=%04x.\n",
-					  dev->name, csr0, DREG ));
-
-		if (csr0 & CSR0_RINT)			/* Rx interrupt */
-			lance_rx( dev );
-
-		if (csr0 & CSR0_TINT) {			/* Tx-done interrupt */
-			int dirty_tx = lp->dirty_tx;
-
-			while( dirty_tx < lp->cur_tx) {
-				int entry = dirty_tx & TX_RING_MOD_MASK;
-#ifdef NORMAL_MEM_ACCESS
-				int status = MEM->tx_head[entry].flag;
-#else
-				int status = GET_FLAG(&MEM->tx_head[entry]);
-#endif
-				if (status & TMD1_OWN_CHIP)
-					break;			/* It still hasn't been Txed */
-
-#ifdef NORMAL_MEM_ACCESS
-				MEM->tx_head[entry].flag = 0;
-#else
-				SET_FLAG(&MEM->tx_head[entry],0);
-#endif
-
-				if (status & TMD1_ERR) {
-					/* There was an major error, log it. */
-					int err_status = MEM->tx_head[entry].misc;
-					lp->stats.tx_errors++;
-					if (err_status & TMD3_RTRY) lp->stats.tx_aborted_errors++;
-					if (err_status & TMD3_LCAR) lp->stats.tx_carrier_errors++;
-					if (err_status & TMD3_LCOL) lp->stats.tx_window_errors++;
-					if (err_status & TMD3_UFLO) {
-						/* Ackk!  On FIFO errors the Tx unit is turned off! */
-						lp->stats.tx_fifo_errors++;
-						/* Remove this verbosity later! */
-						DPRINTK( 1, ( "%s: Tx FIFO error! Status %04x\n",
-									  dev->name, csr0 ));
-						/* Restart the chip. */
-						DREG = CSR0_STRT;
-					}
-				} else {
-					if (status & (TMD1_MORE | TMD1_ONE | TMD1_DEF))
-						lp->stats.collisions++;
-					lp->stats.tx_packets++;
-				}
-				dirty_tx++;
-			}
-
-#ifndef final_version
-			if (lp->cur_tx - dirty_tx >= TX_RING_SIZE) {
-				DPRINTK( 0, ( "out-of-sync dirty pointer,"
-							  " %d vs. %d, full=%d.\n",
-							  dirty_tx, lp->cur_tx, lp->tx_full ));
-				dirty_tx += TX_RING_SIZE;
-			}
-#endif
-
-			if (lp->tx_full && dev->tbusy
-				&& dirty_tx > lp->cur_tx - TX_RING_SIZE + 2) {
-				/* The ring is no longer full, clear tbusy. */
-				lp->tx_full = 0;
-				dev->tbusy = 0;
-				mark_bh( NET_BH );
-			}
-
-			lp->dirty_tx = dirty_tx;
-		}
-
-		/* Log misc errors. */
-		if (csr0 & CSR0_BABL) lp->stats.tx_errors++; /* Tx babble. */
-		if (csr0 & CSR0_MISS) lp->stats.rx_errors++; /* Missed a Rx frame. */
-		if (csr0 & CSR0_MERR) {
-			DPRINTK( 1, ( "%s: Bus master arbitration failure (?!?), "
-						  "status %04x.\n", dev->name, csr0 ));
-			/* Restart the chip. */
-			DREG = CSR0_STRT;
-		}
-	}
-
-    /* Clear any other interrupt, and set interrupt enable. */
-	DREG = CSR0_BABL | CSR0_CERR | CSR0_MISS | CSR0_MERR |
-		   CSR0_IDON | CSR0_INEA;
-
-	DPRINTK( 2, ( "%s: exiting interrupt, csr0=%#04x.\n",
-				  dev->name, DREG ));
-	dev->interrupt = 0;
-	return IRQ_RETVAL(handled);
-}
-
-
-static int lance_rx( struct net_device *dev )
-
-{	struct lance_private *lp = netdev_priv(dev);
-	int entry = lp->cur_rx & RX_RING_MOD_MASK;
-	int i;
-
-#ifdef NORMAL_MEM_ACCESS
-	DPRINTK( 2, ( "%s: rx int, flag=%04x\n", dev->name,
-				  MEM->rx_head[entry].flag ));
-#else
-	DPRINTK( 2, ( "%s: rx int, flag=%04x\n", dev->name,
-				  GET_FLAG(&MEM->rx_head[entry]) ));
-#endif
-
-	/* If we own the next entry, it's a new packet. Send it up. */
-#ifdef NORMAL_MEM_ACCESS
-	while( (MEM->rx_head[entry].flag & RMD1_OWN) == RMD1_OWN_HOST ) {
-#else
-	while( (GET_FLAG(&MEM->rx_head[entry]) & RMD1_OWN) == RMD1_OWN_HOST ) {
-#endif
-		struct lance_rx_head *head = &(MEM->rx_head[entry]);
-#ifdef NORMAL_MEM_ACCESS
-		int status = head->flag;
-#else
-		int status = GET_FLAG(head);
-#endif
-
-		if (status != (RMD1_ENP|RMD1_STP)) {		/* 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
-			   buffers, with only the last correctly noting the error. */
-			if (status & RMD1_ENP)	/* Only count a general error at the */
-				lp->stats.rx_errors++; /* end of a packet.*/
-			if (status & RMD1_FRAM) lp->stats.rx_frame_errors++;
-			if (status & RMD1_OFLO) lp->stats.rx_over_errors++;
-			if (status & RMD1_CRC) lp->stats.rx_crc_errors++;
-			if (status & RMD1_BUFF) lp->stats.rx_fifo_errors++;
-#ifdef NORMAL_MEM_ACCESS
-			head->flag &= (RMD1_ENP|RMD1_STP);
-#else
-			SET_FLAG(head,GET_FLAG(head) & (RMD1_ENP|RMD1_STP));
-#endif
-		} else {
-			/* Malloc up new buffer, compatible with net-3. */
-			short pkt_len = head->msg_length & 0xfff;
-			struct sk_buff *skb;
-
-			if (pkt_len < 60) {
-				printk( "%s: Runt packet!\n", dev->name );
-				lp->stats.rx_errors++;
-			}
-			else {
-				skb = dev_alloc_skb( pkt_len+2 );
-				if (skb == NULL) {
-					DPRINTK( 1, ( "%s: Memory squeeze, deferring packet.\n",
-								  dev->name ));
-                          for( i = 0; i < RX_RING_SIZE; i++ )
-#ifdef NORMAL_MEM_ACCESS
-                        if (MEM->rx_head[(entry+i) & RX_RING_MOD_MASK].flag &
-#else
-						if (GET_FLAG(&MEM->rx_head[(entry+i) & \
-												  RX_RING_MOD_MASK]) &
-#endif
-							RMD1_OWN_CHIP)
-							break;
-
-					if (i > RX_RING_SIZE - 2) {
-						lp->stats.rx_dropped++;
-#ifdef NORMAL_MEM_ACCESS
-                        head->flag |= RMD1_OWN_CHIP;
-#else
-                        SET_FLAG(head,GET_FLAG(head) | RMD1_OWN_CHIP);
-#endif
-						lp->cur_rx++;
-					}
-					break;
-				}
-
-				if (lance_debug >= 3) {
-					u_char *data = PKTBUF_ADDR(head), *p;
-					printk( "%s: RX pkt type 0x%04x from ", dev->name,
-							((u_short *)data)[6]);
-					for( p = &data[6], i = 0; i < 6; i++ )
-						printk("%02x%s", *p++, i != 5 ? ":" : "" );
-					printk(" to ");
-					for( p = data, i = 0; i < 6; i++ )
-						printk("%02x%s", *p++, i != 5 ? ":" : "" );
-					printk(" data %02x %02x %02x %02x %02x %02x %02x %02x "
-						   "len %d\n",
-						   data[15], data[16], data[17], data[18],
-						   data[19], data[20], data[21], data[22],
-						   pkt_len );
-				}
-
-				skb->dev = dev;
-				skb_reserve( skb, 2 );	/* 16 byte align */
-				skb_put( skb, pkt_len );	/* Make room */
-				lp->memcpy_f( skb->data, PKTBUF_ADDR(head), pkt_len );
-				skb->protocol = eth_type_trans( skb, dev );
-				netif_rx( skb );
-				dev->last_rx = jiffies;
-				lp->stats.rx_packets++;
-				lp->stats.rx_bytes += pkt_len;
-			}
-		}
-
-#ifdef NORMAL_MEM_ACCESS
-		head->flag |= RMD1_OWN_CHIP;
-#else
-		SET_FLAG(head,GET_FLAG(head) | RMD1_OWN_CHIP);
-#endif
-		entry = (++lp->cur_rx) & RX_RING_MOD_MASK;
-	}
-	lp->cur_rx &= RX_RING_MOD_MASK;
-
-	/* From lance.c (Donald Becker): */
-	/* We should check that at least two ring entries are free.	 If not,
-	   we should free one and mark stats->rx_dropped++. */
-
-	return 0;
-}
-
-
-static int lance_close( struct net_device *dev )
-
-{	struct lance_private *lp = netdev_priv(dev);
-	struct lance_ioreg	 *IO = lp->iobase;
-
-	dev->start = 0;
-	dev->tbusy = 1;
-
-	AREG = CSR0;
-
-	DPRINTK( 2, ( "%s: Shutting down ethercard, status was %2.2x.\n",
-				  dev->name, DREG ));
-
-	/* We stop the LANCE here -- it occasionally polls
-	   memory if we don't. */
-	DREG = CSR0_STOP;
-
-	return 0;
-}
-
-
-static struct net_device_stats *lance_get_stats( struct net_device *dev )
-
-{	
-	struct lance_private *lp = netdev_priv(dev);
-	return &lp->stats;
-}
-
-
-/* Set or clear the multicast filter for this adaptor.
-   num_addrs == -1		Promiscuous mode, receive all packets
-   num_addrs == 0		Normal mode, clear multicast list
-   num_addrs > 0		Multicast mode, receive normal and MC packets, and do
-						best-effort filtering.
- */
-
-static void set_multicast_list( struct net_device *dev )
-
-{	struct lance_private *lp = netdev_priv(dev);
-	struct lance_ioreg	 *IO = lp->iobase;
-
-	if (!dev->start)
-		/* Only possible if board is already started */
-		return;
-
-	/* We take the simple way out and always enable promiscuous mode. */
-	DREG = CSR0_STOP; /* Temporarily stop the lance. */
-
-	if (dev->flags & IFF_PROMISC) {
-		/* Log any net taps. */
-		DPRINTK( 1, ( "%s: Promiscuous mode enabled.\n", dev->name ));
-		REGA( CSR15 ) = 0x8000; /* Set promiscuous mode */
-	} else {
-		short multicast_table[4];
-		int num_addrs = dev->mc_count;
-		int i;
-		/* We don't use the multicast table, but rely on upper-layer
-		 * filtering. */
-		memset( multicast_table, (num_addrs == 0) ? 0 : -1,
-				sizeof(multicast_table) );
-		for( i = 0; i < 4; i++ )
-			REGA( CSR8+i ) = multicast_table[i];
-		REGA( CSR15 ) = 0; /* Unset promiscuous mode */
-	}
-
-	/*
-	 * Always set BSWP after a STOP as STOP puts it back into
-	 * little endian mode.
-	 */
-	REGA( CSR3 ) = CSR3_BSWP | (lp->cardtype == PAM_CARD ? CSR3_ACON : 0);
-
-	/* Resume normal operation and reset AREG to CSR0 */
-	REGA( CSR0 ) = CSR0_IDON | CSR0_INEA | CSR0_STRT;
-}
-
-
-/* This is needed for old RieblCards and possible for new RieblCards */
-
-static int lance_set_mac_address( struct net_device *dev, void *addr )
-
-{	struct lance_private *lp = netdev_priv(dev);
-	struct sockaddr *saddr = addr;
-	int i;
-
-	if (lp->cardtype != OLD_RIEBL && lp->cardtype != NEW_RIEBL)
-		return( -EOPNOTSUPP );
-
-	if (dev->start) {
-		/* Only possible while card isn't started */
-		DPRINTK( 1, ( "%s: hwaddr can be set only while card isn't open.\n",
-					  dev->name ));
-		return( -EIO );
-	}
-
-	slow_memcpy( dev->dev_addr, saddr->sa_data, dev->addr_len );
-
-	{
-			unsigned char hwaddr[6];
-			for( i = 0; i < 6; i++ ) 
-					hwaddr[i] = dev->dev_addr[i^1]; /* <- 16 bit swap! */
-			slow_memcpy(MEM->init.hwaddr, hwaddr, sizeof(hwaddr));
-	}
-
-	lp->memcpy_f( RIEBL_HWADDR_ADDR, dev->dev_addr, 6 );
-	/* set also the magic for future sessions */
-#ifdef NORMAL_MEM_ACCESS
-	*RIEBL_MAGIC_ADDR = RIEBL_MAGIC;
-#else
-	{
-			unsigned long magic = RIEBL_MAGIC;
-			slow_memcpy(RIEBL_MAGIC_ADDR, &magic, sizeof(*RIEBL_MAGIC_ADDR));
-	}
-#endif
-	return( 0 );
-}
-
-
-#ifdef MODULE
-static struct net_device *bagetlance_dev;
-
-int init_module(void)
-{
-	bagetlance_dev = bagetlance_probe(-1);
-	if (IS_ERR(bagetlance_dev))
-		return PTR_ERR(bagetlance_dev);
-	return 0;
-}
-
-void cleanup_module(void)
-{
-	unregister_netdev(bagetlance_dev);
-	free_irq(bagetlance_dev->irq, bagetlance_dev);
-	free_netdev(bagetlance_dev);
-}
-
-#endif /* MODULE */
-
-/*
- * Local variables:
- *  c-indent-level: 4
- *  tab-width: 4
- * End:
- */
diff -Nru a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c
--- a/drivers/net/bonding/bond_3ad.c	2005-03-11 12:51:50 -08:00
+++ b/drivers/net/bonding/bond_3ad.c	2005-03-11 12:51:50 -08:00
@@ -2175,7 +2175,7 @@
  * received frames (loopback). Since only the payload is given to this
  * function, it check for loopback.
  */
-void bond_3ad_rx_indication(struct lacpdu *lacpdu, struct slave *slave, u16 length)
+static void bond_3ad_rx_indication(struct lacpdu *lacpdu, struct slave *slave, u16 length)
 {
 	struct port *port;
 
diff -Nru a/drivers/net/bonding/bond_3ad.h b/drivers/net/bonding/bond_3ad.h
--- a/drivers/net/bonding/bond_3ad.h	2005-03-11 12:51:52 -08:00
+++ b/drivers/net/bonding/bond_3ad.h	2005-03-11 12:51:52 -08:00
@@ -290,7 +290,6 @@
 int  bond_3ad_bind_slave(struct slave *slave);
 void bond_3ad_unbind_slave(struct slave *slave);
 void bond_3ad_state_machine_handler(struct bonding *bond);
-void bond_3ad_rx_indication(struct lacpdu *lacpdu, struct slave *slave, u16 length);
 void bond_3ad_adapter_speed_changed(struct slave *slave);
 void bond_3ad_adapter_duplex_changed(struct slave *slave);
 void bond_3ad_handle_link_change(struct slave *slave, char link);
diff -Nru a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c
--- a/drivers/net/bonding/bond_alb.c	2005-03-11 12:51:47 -08:00
+++ b/drivers/net/bonding/bond_alb.c	2005-03-11 12:51:47 -08:00
@@ -275,7 +275,7 @@
 }
 
 /* Caller must hold bond lock for read */
-struct slave *tlb_choose_channel(struct bonding *bond, u32 hash_index, u32 skb_len)
+static struct slave *tlb_choose_channel(struct bonding *bond, u32 hash_index, u32 skb_len)
 {
 	struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
 	struct tlb_client_info *hash_table;
@@ -627,7 +627,7 @@
 }
 
 /* Caller must hold both bond and ptr locks for read */
-struct slave *rlb_choose_channel(struct sk_buff *skb, struct bonding *bond)
+static struct slave *rlb_choose_channel(struct sk_buff *skb, struct bonding *bond)
 {
 	struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
 	struct arp_pkt *arp = (struct arp_pkt *)skb->nh.raw;
@@ -954,9 +954,9 @@
 	/* each slave will receive packets destined to a different mac */
 	memcpy(s_addr.sa_data, addr, dev->addr_len);
 	s_addr.sa_family = dev->type;
-	if (dev->set_mac_address(dev, &s_addr)) {
+	if (dev_set_mac_address(dev, &s_addr)) {
 		printk(KERN_ERR DRV_NAME
-		       ": Error: dev->set_mac_address of dev %s failed! ALB "
+		       ": Error: dev_set_mac_address of dev %s failed! ALB "
 		       "mode requires that the base driver support setting "
 		       "the hw address also when the network device's "
 		       "interface is open\n",
@@ -1209,7 +1209,7 @@
 		/* save net_device's current hw address */
 		memcpy(tmp_addr, slave->dev->dev_addr, ETH_ALEN);
 
-		res = slave->dev->set_mac_address(slave->dev, addr);
+		res = dev_set_mac_address(slave->dev, addr);
 
 		/* restore net_device's hw address */
 		memcpy(slave->dev->dev_addr, tmp_addr, ETH_ALEN);
@@ -1229,7 +1229,7 @@
 	stop_at = slave;
 	bond_for_each_slave_from_to(bond, slave, i, bond->first_slave, stop_at) {
 		memcpy(tmp_addr, slave->dev->dev_addr, ETH_ALEN);
-		slave->dev->set_mac_address(slave->dev, &sa);
+		dev_set_mac_address(slave->dev, &sa);
 		memcpy(slave->dev->dev_addr, tmp_addr, ETH_ALEN);
 	}
 
diff -Nru a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
--- a/drivers/net/bonding/bond_main.c	2005-03-11 12:51:51 -08:00
+++ b/drivers/net/bonding/bond_main.c	2005-03-11 12:51:51 -08:00
@@ -1719,7 +1719,7 @@
 		 */
 		memcpy(addr.sa_data, bond_dev->dev_addr, bond_dev->addr_len);
 		addr.sa_family = slave_dev->type;
-		res = slave_dev->set_mac_address(slave_dev, &addr);
+		res = dev_set_mac_address(slave_dev, &addr);
 		if (res) {
 			dprintk("Error %d calling set_mac_address\n", res);
 			goto err_free;
@@ -1849,8 +1849,8 @@
 	if (bond_update_speed_duplex(new_slave) &&
 	    (new_slave->link != BOND_LINK_DOWN)) {
 		printk(KERN_WARNING DRV_NAME
-		       ": Warning: failed to get speed/duplex from %s, speed "
-		       "forced to 100Mbps, duplex forced to Full.\n",
+		       ": Warning: failed to get speed and duplex from %s, "
+		       "assumed to be 100Mb/sec and Full.\n",
 		       new_slave->dev->name);
 
 		if (bond->params.mode == BOND_MODE_8023AD) {
@@ -1991,7 +1991,7 @@
 err_restore_mac:
 	memcpy(addr.sa_data, new_slave->perm_hwaddr, ETH_ALEN);
 	addr.sa_family = slave_dev->type;
-	slave_dev->set_mac_address(slave_dev, &addr);
+	dev_set_mac_address(slave_dev, &addr);
 
 err_free:
 	kfree(new_slave);
@@ -2171,7 +2171,7 @@
 		/* restore original ("permanent") mac address */
 		memcpy(addr.sa_data, slave->perm_hwaddr, ETH_ALEN);
 		addr.sa_family = slave_dev->type;
-		slave_dev->set_mac_address(slave_dev, &addr);
+		dev_set_mac_address(slave_dev, &addr);
 	}
 
 	/* restore the original state of the
@@ -2262,7 +2262,7 @@
 			/* restore original ("permanent") mac address*/
 			memcpy(addr.sa_data, slave->perm_hwaddr, ETH_ALEN);
 			addr.sa_family = slave_dev->type;
-			slave_dev->set_mac_address(slave_dev, &addr);
+			dev_set_mac_address(slave_dev, &addr);
 		}
 
 		/* restore the original state of the IFF_NOARP flag that might have
@@ -3898,12 +3898,7 @@
 	bond_for_each_slave(bond, slave, i) {
 		dprintk("s %p s->p %p c_m %p\n", slave,
 			slave->prev, slave->dev->change_mtu);
-		if (slave->dev->change_mtu) {
-			res = slave->dev->change_mtu(slave->dev, new_mtu);
-		} else {
-			slave->dev->mtu = new_mtu;
-			res = 0;
-		}
+		res = dev_set_mtu(slave->dev, new_mtu);
 
 		if (res) {
 			/* If we failed to set the slave's mtu to the new value
@@ -3929,14 +3924,10 @@
 	bond_for_each_slave_from_to(bond, slave, i, bond->first_slave, stop_at) {
 		int tmp_res;
 
-		if (slave->dev->change_mtu) {
-			tmp_res = slave->dev->change_mtu(slave->dev, bond_dev->mtu);
-			if (tmp_res) {
-				dprintk("unwind err %d dev %s\n", tmp_res,
-					slave->dev->name);
-			}
-		} else {
-			slave->dev->mtu = bond_dev->mtu;
+		tmp_res = dev_set_mtu(slave->dev, bond_dev->mtu);
+		if (tmp_res) {
+			dprintk("unwind err %d dev %s\n", tmp_res,
+				slave->dev->name);
 		}
 	}
 
@@ -3988,7 +3979,7 @@
 			goto unwind;
 		}
 
-		res = slave->dev->set_mac_address(slave->dev, addr);
+		res = dev_set_mac_address(slave->dev, addr);
 		if (res) {
 			/* TODO: consider downing the slave
 			 * and retry ?
@@ -4014,7 +4005,7 @@
 	bond_for_each_slave_from_to(bond, slave, i, bond->first_slave, stop_at) {
 		int tmp_res;
 
-		tmp_res = slave->dev->set_mac_address(slave->dev, &tmp_sa);
+		tmp_res = dev_set_mac_address(slave->dev, &tmp_sa);
 		if (tmp_res) {
 			dprintk("unwind err %d dev %s\n", tmp_res,
 				slave->dev->name);
diff -Nru a/drivers/net/cs89x0.c b/drivers/net/cs89x0.c
--- a/drivers/net/cs89x0.c	2005-03-11 12:51:52 -08:00
+++ b/drivers/net/cs89x0.c	2005-03-11 12:51:52 -08:00
@@ -136,6 +136,7 @@
 #include <linux/string.h>
 #include <linux/init.h>
 #include <linux/bitops.h>
+#include <linux/delay.h>
 
 #include <asm/system.h>
 #include <asm/io.h>
@@ -909,8 +910,7 @@
 	writereg(dev, PP_SelfCTL, readreg(dev, PP_SelfCTL) | POWER_ON_RESET);
 
 	/* wait 30 ms */
-	current->state = TASK_INTERRUPTIBLE;
-	schedule_timeout(30*HZ/1000);
+	msleep(30);
 
 #ifndef CONFIG_ARCH_IXDP2X01
 	if (lp->chip_type != CS8900) {
diff -Nru a/drivers/net/defxx.c b/drivers/net/defxx.c
--- a/drivers/net/defxx.c	2005-03-11 12:51:40 -08:00
+++ b/drivers/net/defxx.c	2005-03-11 12:51:40 -08:00
@@ -420,7 +420,7 @@
 	}
 
 	if (pdev != NULL)
-		print_name = pdev->slot_name;
+		print_name = pci_name(pdev);
 
 	dev = alloc_fddidev(sizeof(*bp));
 	if (!dev) {
diff -Nru a/drivers/net/depca.c b/drivers/net/depca.c
--- a/drivers/net/depca.c	2005-03-11 12:51:46 -08:00
+++ b/drivers/net/depca.c	2005-03-11 12:51:46 -08:00
@@ -342,14 +342,14 @@
 static int depca_device_remove (struct device *device);
 
 #ifdef CONFIG_EISA
-struct eisa_device_id depca_eisa_ids[] = {
+static struct eisa_device_id depca_eisa_ids[] = {
 	{ "DEC4220", de422 },
 	{ "" }
 };
 
 static int depca_eisa_probe  (struct device *device);
 
-struct eisa_driver depca_eisa_driver = {
+static struct eisa_driver depca_eisa_driver = {
 	.id_table = depca_eisa_ids,
 	.driver   = {
 		.name    = depca_string,
diff -Nru a/drivers/net/dgrs.c b/drivers/net/dgrs.c
--- a/drivers/net/dgrs.c	2005-03-11 12:51:41 -08:00
+++ b/drivers/net/dgrs.c	2005-03-11 12:51:41 -08:00
@@ -454,7 +454,7 @@
  *	up some state variables to let the host CPU continue doing
  *	other things until a DMA completion interrupt comes along.
  */
-void
+static void
 dgrs_rcv_frame(
 	struct net_device	*dev0,
 	DGRS_PRIV	*priv0,
@@ -1150,7 +1150,7 @@
 /*
  *	Probe (init) a board
  */
-int __init 
+static int __init 
 dgrs_probe1(struct net_device *dev)
 {
 	DGRS_PRIV	*priv = (DGRS_PRIV *) dev->priv;
@@ -1228,7 +1228,7 @@
        	return rc;
 }
 
-int __init 
+static int __init 
 dgrs_initclone(struct net_device *dev)
 {
 	DGRS_PRIV	*priv = (DGRS_PRIV *) dev->priv;
diff -Nru a/drivers/net/dl2k.c b/drivers/net/dl2k.c
--- a/drivers/net/dl2k.c	2005-03-11 12:51:42 -08:00
+++ b/drivers/net/dl2k.c	2005-03-11 12:51:42 -08:00
@@ -1199,7 +1199,7 @@
 static void rio_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
 {
 	struct netdev_private *np = netdev_priv(dev);
-	strcpy(info->driver, "DL2K");
+	strcpy(info->driver, "dl2k");
 	strcpy(info->version, DRV_VERSION);
 	strcpy(info->bus_info, pci_name(np->pdev));
 }	
diff -Nru a/drivers/net/e100.c b/drivers/net/e100.c
--- a/drivers/net/e100.c	2005-03-11 12:51:52 -08:00
+++ b/drivers/net/e100.c	2005-03-11 12:51:52 -08:00
@@ -2310,7 +2310,7 @@
 }
 
 #ifdef CONFIG_PM
-static int e100_suspend(struct pci_dev *pdev, u32 state)
+static int e100_suspend(struct pci_dev *pdev, pm_message_t state)
 {
 	struct net_device *netdev = pci_get_drvdata(pdev);
 	struct nic *nic = netdev_priv(netdev);
@@ -2321,7 +2321,7 @@
 	netif_device_detach(netdev);
 
 	pci_save_state(pdev);
-	pci_enable_wake(pdev, state, nic->flags & (wol_magic | e100_asf(nic)));
+	pci_enable_wake(pdev, pci_choose_state(pdev, state), nic->flags & (wol_magic | e100_asf(nic)));
 	pci_disable_device(pdev);
 	pci_set_power_state(pdev, pci_choose_state(pdev, state));
 
diff -Nru a/drivers/net/e1000/e1000.h b/drivers/net/e1000/e1000.h
--- a/drivers/net/e1000/e1000.h	2005-03-11 12:51:40 -08:00
+++ b/drivers/net/e1000/e1000.h	2005-03-11 12:51:40 -08:00
@@ -138,6 +138,7 @@
 #define E1000_RX_BUFFER_WRITE	16	/* Must be power of 2 */
 
 #define AUTO_ALL_MODES       0
+#define E1000_EEPROM_82544_APM 0x0004
 #define E1000_EEPROM_APME    0x0400
 
 #ifndef E1000_MASTER_SLAVE
@@ -209,6 +210,7 @@
 
 	/* TX */
 	struct e1000_desc_ring tx_ring;
+	struct e1000_buffer previous_buffer_info;
 	spinlock_t tx_lock;
 	uint32_t txd_cmd;
 	uint32_t tx_int_delay;
@@ -222,6 +224,7 @@
 	uint32_t tx_fifo_size;
 	atomic_t tx_fifo_stall;
 	boolean_t pcix_82544;
+	boolean_t detect_tx_hung;
 
 	/* RX */
 	struct e1000_desc_ring rx_ring;
diff -Nru a/drivers/net/e1000/e1000_ethtool.c b/drivers/net/e1000/e1000_ethtool.c
--- a/drivers/net/e1000/e1000_ethtool.c	2005-03-11 12:51:43 -08:00
+++ b/drivers/net/e1000/e1000_ethtool.c	2005-03-11 12:51:43 -08:00
@@ -1310,7 +1310,7 @@
 	struct e1000_desc_ring *txdr = &adapter->test_tx_ring;
 	struct e1000_desc_ring *rxdr = &adapter->test_rx_ring;
 	struct pci_dev *pdev = adapter->pdev;
-	int i;
+	int i, ret_val;
 
 	E1000_WRITE_REG(&adapter->hw, RDT, rxdr->count - 1);
 
@@ -1330,11 +1330,12 @@
 					    rxdr->buffer_info[i].length,
 					    PCI_DMA_FROMDEVICE);
 
-		if (!e1000_check_lbtest_frame(rxdr->buffer_info[i++].skb, 1024))
-			return 0;
-	} while (i < 64);
+		ret_val = e1000_check_lbtest_frame(rxdr->buffer_info[i].skb,
+						   1024);
+		i++;
+	} while (ret_val != 0 && i < 64);
 
-	return 13;
+	return ret_val;
 }
 
 static int
diff -Nru a/drivers/net/e1000/e1000_hw.c b/drivers/net/e1000/e1000_hw.c
--- a/drivers/net/e1000/e1000_hw.c	2005-03-11 12:51:51 -08:00
+++ b/drivers/net/e1000/e1000_hw.c	2005-03-11 12:51:51 -08:00
@@ -1572,7 +1572,8 @@
             if(mii_status_reg & MII_SR_LINK_STATUS) break;
             msec_delay(100);
         }
-        if((i == 0) && (hw->phy_type == e1000_phy_m88)) {
+        if((i == 0) &&
+           (hw->phy_type == e1000_phy_m88)) {
             /* We didn't get link.  Reset the DSP and wait again for link. */
             ret_val = e1000_phy_reset_dsp(hw);
             if(ret_val) {
@@ -2503,7 +2504,7 @@
         }
     }
 
-    ret_val = e1000_read_phy_reg_ex(hw, IGP01E1000_PHY_PAGE_SELECT & reg_addr,
+    ret_val = e1000_read_phy_reg_ex(hw, MAX_PHY_REG_ADDRESS & reg_addr,
                                     phy_data);
 
     return ret_val;
@@ -2609,7 +2610,7 @@
         }
     }
 
-    ret_val = e1000_write_phy_reg_ex(hw, IGP01E1000_PHY_PAGE_SELECT & reg_addr,
+    ret_val = e1000_write_phy_reg_ex(hw, MAX_PHY_REG_ADDRESS & reg_addr,
                                      phy_data);
 
     return ret_val;
@@ -2955,8 +2956,7 @@
     /* Check polarity status */
     ret_val = e1000_check_polarity(hw, &polarity);
     if(ret_val)
-        return ret_val;
-
+        return ret_val; 
     phy_info->cable_polarity = polarity;
 
     ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data);
@@ -2966,9 +2966,9 @@
     phy_info->mdix_mode = (phy_data & M88E1000_PSSR_MDIX) >>
                           M88E1000_PSSR_MDIX_SHIFT;
 
-    if(phy_data & M88E1000_PSSR_1000MBS) {
-        /* Cable Length Estimation and Local/Remote Receiver Informatoion
-         * are only valid at 1000 Mbps
+    if ((phy_data & M88E1000_PSSR_SPEED) == M88E1000_PSSR_1000MBS) {
+        /* Cable Length Estimation and Local/Remote Receiver Information
+         * are only valid at 1000 Mbps.
          */
         phy_info->cable_length = ((phy_data & M88E1000_PSSR_CABLE_LENGTH) >>
                                   M88E1000_PSSR_CABLE_LENGTH_SHIFT);
@@ -4639,41 +4639,44 @@
 {
     uint32_t status;
 
-    if(hw->mac_type < e1000_82543) {
+    switch (hw->mac_type) {
+    case e1000_82542_rev2_0:
+    case e1000_82542_rev2_1:
         hw->bus_type = e1000_bus_type_unknown;
         hw->bus_speed = e1000_bus_speed_unknown;
         hw->bus_width = e1000_bus_width_unknown;
-        return;
-    }
-
-    status = E1000_READ_REG(hw, STATUS);
-    hw->bus_type = (status & E1000_STATUS_PCIX_MODE) ?
-                   e1000_bus_type_pcix : e1000_bus_type_pci;
+        break;
+    default:
+        status = E1000_READ_REG(hw, STATUS);
+        hw->bus_type = (status & E1000_STATUS_PCIX_MODE) ?
+                       e1000_bus_type_pcix : e1000_bus_type_pci;
 
-    if(hw->device_id == E1000_DEV_ID_82546EB_QUAD_COPPER) {
-        hw->bus_speed = (hw->bus_type == e1000_bus_type_pci) ?
-                        e1000_bus_speed_66 : e1000_bus_speed_120;
-    } else if(hw->bus_type == e1000_bus_type_pci) {
-        hw->bus_speed = (status & E1000_STATUS_PCI66) ?
-                        e1000_bus_speed_66 : e1000_bus_speed_33;
-    } else {
-        switch (status & E1000_STATUS_PCIX_SPEED) {
-        case E1000_STATUS_PCIX_SPEED_66:
-            hw->bus_speed = e1000_bus_speed_66;
-            break;
-        case E1000_STATUS_PCIX_SPEED_100:
-            hw->bus_speed = e1000_bus_speed_100;
-            break;
-        case E1000_STATUS_PCIX_SPEED_133:
-            hw->bus_speed = e1000_bus_speed_133;
-            break;
-        default:
-            hw->bus_speed = e1000_bus_speed_reserved;
-            break;
+        if(hw->device_id == E1000_DEV_ID_82546EB_QUAD_COPPER) {
+            hw->bus_speed = (hw->bus_type == e1000_bus_type_pci) ?
+                            e1000_bus_speed_66 : e1000_bus_speed_120;
+        } else if(hw->bus_type == e1000_bus_type_pci) {
+            hw->bus_speed = (status & E1000_STATUS_PCI66) ?
+                            e1000_bus_speed_66 : e1000_bus_speed_33;
+        } else {
+            switch (status & E1000_STATUS_PCIX_SPEED) {
+            case E1000_STATUS_PCIX_SPEED_66:
+                hw->bus_speed = e1000_bus_speed_66;
+                break;
+            case E1000_STATUS_PCIX_SPEED_100:
+                hw->bus_speed = e1000_bus_speed_100;
+                break;
+            case E1000_STATUS_PCIX_SPEED_133:
+                hw->bus_speed = e1000_bus_speed_133;
+                break;
+            default:
+                hw->bus_speed = e1000_bus_speed_reserved;
+                break;
+            }
         }
+        hw->bus_width = (status & E1000_STATUS_BUS64) ?
+                        e1000_bus_width_64 : e1000_bus_width_32;
+        break;
     }
-    hw->bus_width = (status & E1000_STATUS_BUS64) ?
-                    e1000_bus_width_64 : e1000_bus_width_32;
 }
 /******************************************************************************
  * Reads a value from one of the devices registers using port I/O (as opposed
@@ -4738,6 +4741,7 @@
     uint16_t agc_value = 0;
     uint16_t cur_agc, min_agc = IGP01E1000_AGC_LENGTH_TABLE_SIZE;
     uint16_t i, phy_data;
+    uint16_t cable_length;
 
     DEBUGFUNC("e1000_get_cable_length");
 
@@ -4749,10 +4753,11 @@
                                      &phy_data);
         if(ret_val)
             return ret_val;
+        cable_length = (phy_data & M88E1000_PSSR_CABLE_LENGTH) >>
+                       M88E1000_PSSR_CABLE_LENGTH_SHIFT;
 
         /* Convert the enum value to ranged values */
-        switch((phy_data & M88E1000_PSSR_CABLE_LENGTH) >>
-               M88E1000_PSSR_CABLE_LENGTH_SHIFT) {
+        switch (cable_length) {
         case e1000_cable_length_50:
             *min_length = 0;
             *max_length = e1000_igp_cable_length_50;
@@ -4919,8 +4924,7 @@
             return ret_val;
 
         hw->speed_downgraded = (phy_data & IGP01E1000_PLHR_SS_DOWNGRADE) ? 1 : 0;
-    }
-    else if(hw->phy_type == e1000_phy_m88) {
+    } else if(hw->phy_type == e1000_phy_m88) {
         ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS,
                                      &phy_data);
         if(ret_val)
diff -Nru a/drivers/net/e1000/e1000_hw.h b/drivers/net/e1000/e1000_hw.h
--- a/drivers/net/e1000/e1000_hw.h	2005-03-11 12:51:51 -08:00
+++ b/drivers/net/e1000/e1000_hw.h	2005-03-11 12:51:51 -08:00
@@ -369,6 +369,7 @@
 #define E1000_DEV_ID_82546GB_SERDES      0x107B
 #define E1000_DEV_ID_82546GB_PCIE        0x108A
 #define E1000_DEV_ID_82547EI             0x1019
+
 #define NODE_ADDRESS_SIZE 6
 #define ETH_LENGTH_OF_ADDRESS 6
 
@@ -1734,6 +1735,9 @@
 #define PHY_1000T_STATUS 0x0A /* 1000Base-T Status Reg */
 #define PHY_EXT_STATUS   0x0F /* Extended Status Reg */
 
+#define MAX_PHY_REG_ADDRESS        0x1F  /* 5 bit address bus (0-0x1F) */
+#define MAX_PHY_MULTI_PAGE_REG     0xF   /* Registers equal on all pages */
+
 /* M88E1000 Specific Registers */
 #define M88E1000_PHY_SPEC_CTRL     0x10  /* PHY Specific Control Register */
 #define M88E1000_PHY_SPEC_STATUS   0x11  /* PHY Specific Status Register */
@@ -1794,8 +1798,7 @@
 
 #define IGP01E1000_ANALOG_REGS_PAGE  0x20C0
 
-#define MAX_PHY_REG_ADDRESS 0x1F        /* 5 bit address bus (0-0x1F) */
-#define MAX_PHY_MULTI_PAGE_REG  0xF     /*Registers that are equal on all pages*/
+
 /* PHY Control Register */
 #define MII_CR_SPEED_SELECT_MSB 0x0040  /* bits 6,13: 10=1000, 01=100, 00=10 */
 #define MII_CR_COLL_TEST_ENABLE 0x0080  /* Collision test enable */
@@ -2098,7 +2101,11 @@
 #define IGP01E1000_ANALOG_FUSE_FINE_1               0x0080
 #define IGP01E1000_ANALOG_FUSE_FINE_10              0x0500
 
+
 /* Bit definitions for valid PHY IDs. */
+/* I = Integrated
+ * E = External
+ */
 #define M88E1000_E_PHY_ID  0x01410C50
 #define M88E1000_I_PHY_ID  0x01410C30
 #define M88E1011_I_PHY_ID  0x01410C20
diff -Nru a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c
--- a/drivers/net/e1000/e1000_main.c	2005-03-11 12:51:52 -08:00
+++ b/drivers/net/e1000/e1000_main.c	2005-03-11 12:51:52 -08:00
@@ -35,6 +35,14 @@
  * - More errlogging support from Jon Mason <jonmason@us.ibm.com>
  * - Fix TSO issues on PPC64 machines -- Jon Mason <jonmason@us.ibm.com>
  *
+ * 5.7.1	12/16/04
+ * - Resurrect 82547EI/GI related fix in e1000_intr to avoid deadlocks. This
+ *   fix was removed as it caused system instability. The suspected cause of 
+ *   this is the called to e1000_irq_disable in e1000_intr. Inlined the 
+ *   required piece of e1000_irq_disable into e1000_intr - Anton Blanchard
+ * 5.7.0	12/10/04
+ * - include fix to the condition that determines when to quit NAPI - Robert Olsson
+ * - use netif_poll_{disable/enable} to synchronize between NAPI and i/f up/down
  * 5.6.5 	11/01/04
  * - Enabling NETIF_F_SG without checksum offload is illegal - 
      John Mason <jdmason@us.ibm.com>
@@ -57,7 +65,7 @@
 #else
 #define DRIVERNAPI "-NAPI"
 #endif
-char e1000_driver_version[] = "5.6.10.1-k2"DRIVERNAPI;
+char e1000_driver_version[] = "5.7.6-k2"DRIVERNAPI;
 char e1000_copyright[] = "Copyright (c) 1999-2004 Intel Corporation.";
 
 /* e1000_pci_tbl - PCI Device ID Table
@@ -81,6 +89,7 @@
 	INTEL_E1000_ETHERNET_DEVICE(0x1011),
 	INTEL_E1000_ETHERNET_DEVICE(0x1012),
 	INTEL_E1000_ETHERNET_DEVICE(0x1013),
+	INTEL_E1000_ETHERNET_DEVICE(0x1014),
 	INTEL_E1000_ETHERNET_DEVICE(0x1015),
 	INTEL_E1000_ETHERNET_DEVICE(0x1016),
 	INTEL_E1000_ETHERNET_DEVICE(0x1017),
@@ -308,6 +317,9 @@
 	mod_timer(&adapter->watchdog_timer, jiffies);
 	e1000_irq_enable(adapter);
 
+#ifdef CONFIG_E1000_NAPI
+	netif_poll_enable(netdev);
+#endif
 	return 0;
 }
 
@@ -321,6 +333,10 @@
 	del_timer_sync(&adapter->tx_fifo_stall_timer);
 	del_timer_sync(&adapter->watchdog_timer);
 	del_timer_sync(&adapter->phy_info_timer);
+
+#ifdef CONFIG_E1000_NAPI
+	netif_poll_disable(netdev);
+#endif
 	adapter->link_speed = 0;
 	adapter->link_duplex = 0;
 	netif_carrier_off(netdev);
@@ -414,6 +430,7 @@
 	int i;
 	int err;
 	uint16_t eeprom_data;
+	uint16_t eeprom_apme_mask = E1000_EEPROM_APME;
 
 	if((err = pci_enable_device(pdev)))
 		return err;
@@ -510,9 +527,6 @@
 	}
 
 #ifdef NETIF_F_TSO
-	/* 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;
@@ -584,6 +598,11 @@
 	case e1000_82542_rev2_1:
 	case e1000_82543:
 		break;
+	case e1000_82544:
+		e1000_read_eeprom(&adapter->hw,
+			EEPROM_INIT_CONTROL2_REG, 1, &eeprom_data);
+		eeprom_apme_mask = E1000_EEPROM_82544_APM;
+		break;
 	case e1000_82546:
 	case e1000_82546_rev_3:
 		if((E1000_READ_REG(&adapter->hw, STATUS) & E1000_STATUS_FUNC_1)
@@ -598,7 +617,7 @@
 			EEPROM_INIT_CONTROL3_PORT_A, 1, &eeprom_data);
 		break;
 	}
-	if(eeprom_data & E1000_EEPROM_APME)
+	if(eeprom_data & eeprom_apme_mask)
 		adapter->wol |= E1000_WUFC_MAG;
 
 	/* reset the hardware with the new settings */
@@ -807,6 +826,31 @@
 }
 
 /**
+ * e1000_check_64k_bound - check that memory doesn't cross 64kB boundary
+ * @adapter: address of board private structure
+ * @begin: address of beginning of memory
+ * @end: address of end of memory
+ **/
+static inline boolean_t
+e1000_check_64k_bound(struct e1000_adapter *adapter,
+		      void *start, unsigned long len)
+{
+	unsigned long begin = (unsigned long) start;
+	unsigned long end = begin + len;
+
+	/* first rev 82545 and 82546 need to not allow any memory
+	 * write location to cross a 64k boundary due to errata 23 */
+	if (adapter->hw.mac_type == e1000_82545 ||
+	    adapter->hw.mac_type == e1000_82546 ) {
+
+		/* check buffer doesn't cross 64kB */
+		return ((begin ^ (end - 1)) >> 16) != 0 ? FALSE : TRUE;
+	}
+
+	return TRUE;
+}
+
+/**
  * e1000_setup_tx_resources - allocate Tx resources (Descriptors)
  * @adapter: board private structure
  *
@@ -824,7 +868,7 @@
 	txdr->buffer_info = vmalloc(size);
 	if(!txdr->buffer_info) {
 		DPRINTK(PROBE, ERR, 
-		"Unble to Allocate Memory for the Transmit descriptor ring\n");
+		"Unable to Allocate Memory for the Transmit descriptor ring\n");
 		return -ENOMEM;
 	}
 	memset(txdr->buffer_info, 0, size);
@@ -836,11 +880,42 @@
 
 	txdr->desc = pci_alloc_consistent(pdev, txdr->size, &txdr->dma);
 	if(!txdr->desc) {
+setup_tx_desc_die:
 		DPRINTK(PROBE, ERR, 
-		"Unble to Allocate Memory for the Transmit descriptor ring\n");
+		"Unable to Allocate Memory for the Transmit descriptor ring\n");
 		vfree(txdr->buffer_info);
 		return -ENOMEM;
 	}
+
+	/* fix for errata 23, cant cross 64kB boundary */
+	if (!e1000_check_64k_bound(adapter, txdr->desc, txdr->size)) {
+		void *olddesc = txdr->desc;
+		dma_addr_t olddma = txdr->dma;
+		DPRINTK(TX_ERR,ERR,"txdr align check failed: %u bytes at %p\n",
+		        txdr->size, txdr->desc);
+		/* try again, without freeing the previous */
+		txdr->desc = pci_alloc_consistent(pdev, txdr->size, &txdr->dma);
+		/* failed allocation, critial failure */
+		if(!txdr->desc) {
+			pci_free_consistent(pdev, txdr->size, olddesc, olddma);
+			goto setup_tx_desc_die;
+		}
+
+		if (!e1000_check_64k_bound(adapter, txdr->desc, txdr->size)) {
+			/* give up */
+			pci_free_consistent(pdev, txdr->size,
+			     txdr->desc, txdr->dma);
+			pci_free_consistent(pdev, txdr->size, olddesc, olddma);
+			DPRINTK(PROBE, ERR,
+			 "Unable to Allocate aligned Memory for the Transmit"
+		         " descriptor ring\n");
+			vfree(txdr->buffer_info);
+			return -ENOMEM;
+		} else {
+			/* free old, move on with the new one since its okay */
+			pci_free_consistent(pdev, txdr->size, olddesc, olddma);
+		}
+	}
 	memset(txdr->desc, 0, txdr->size);
 
 	txdr->next_to_use = 0;
@@ -945,7 +1020,7 @@
 	rxdr->buffer_info = vmalloc(size);
 	if(!rxdr->buffer_info) {
 		DPRINTK(PROBE, ERR, 
-		"Unble to Allocate Memory for the Recieve descriptor ring\n");
+		"Unable to Allocate Memory for the Recieve descriptor ring\n");
 		return -ENOMEM;
 	}
 	memset(rxdr->buffer_info, 0, size);
@@ -958,11 +1033,43 @@
 	rxdr->desc = pci_alloc_consistent(pdev, rxdr->size, &rxdr->dma);
 
 	if(!rxdr->desc) {
+setup_rx_desc_die:
 		DPRINTK(PROBE, ERR, 
 		"Unble to Allocate Memory for the Recieve descriptor ring\n");
 		vfree(rxdr->buffer_info);
 		return -ENOMEM;
 	}
+
+	/* fix for errata 23, cant cross 64kB boundary */
+	if (!e1000_check_64k_bound(adapter, rxdr->desc, rxdr->size)) {
+		void *olddesc = rxdr->desc;
+		dma_addr_t olddma = rxdr->dma;
+		DPRINTK(RX_ERR,ERR,
+			"rxdr align check failed: %u bytes at %p\n",
+			rxdr->size, rxdr->desc);
+		/* try again, without freeing the previous */
+		rxdr->desc = pci_alloc_consistent(pdev, rxdr->size, &rxdr->dma);
+		/* failed allocation, critial failure */
+		if(!rxdr->desc) {
+			pci_free_consistent(pdev, rxdr->size, olddesc, olddma);
+			goto setup_rx_desc_die;
+		}
+
+		if (!e1000_check_64k_bound(adapter, rxdr->desc, rxdr->size)) {
+			/* give up */
+			pci_free_consistent(pdev, rxdr->size,
+			     rxdr->desc, rxdr->dma);
+			pci_free_consistent(pdev, rxdr->size, olddesc, olddma);
+			DPRINTK(PROBE, ERR, 
+				"Unable to Allocate aligned Memory for the"
+				" Receive descriptor ring\n");
+			vfree(rxdr->buffer_info);
+			return -ENOMEM;
+		} else {
+			/* free old, move on with the new one since its okay */
+			pci_free_consistent(pdev, rxdr->size, olddesc, olddma);
+		}
+	}
 	memset(rxdr->desc, 0, rxdr->size);
 
 	rxdr->next_to_clean = 0;
@@ -1096,6 +1203,7 @@
 			struct e1000_buffer *buffer_info)
 {
 	struct pci_dev *pdev = adapter->pdev;
+
 	if(buffer_info->dma) {
 		pci_unmap_page(pdev,
 			       buffer_info->dma,
@@ -1124,6 +1232,11 @@
 
 	/* Free all the Tx ring sk_buffs */
 
+	if (likely(adapter->previous_buffer_info.skb != NULL)) {
+		e1000_unmap_and_free_tx_resource(adapter, 
+				&adapter->previous_buffer_info);
+	}
+
 	for(i = 0; i < tx_ring->count; i++) {
 		buffer_info = &tx_ring->buffer_info[i];
 		e1000_unmap_and_free_tx_resource(adapter, buffer_info);
@@ -1425,7 +1538,6 @@
 	struct e1000_adapter *adapter = (struct e1000_adapter *) data;
 	struct net_device *netdev = adapter->netdev;
 	struct e1000_desc_ring *txdr = &adapter->tx_ring;
-	unsigned int i;
 	uint32_t link;
 
 	e1000_check_for_link(&adapter->hw);
@@ -1505,12 +1617,8 @@
 	/* Cause software interrupt to ensure rx ring is cleaned */
 	E1000_WRITE_REG(&adapter->hw, ICS, E1000_ICS_RXDMT0);
 
-	/* Early detection of hung controller */
-	i = txdr->next_to_clean;
-	if(txdr->buffer_info[i].dma &&
-	   time_after(jiffies, txdr->buffer_info[i].time_stamp + HZ) &&
-	   !(E1000_READ_REG(&adapter->hw, STATUS) & E1000_STATUS_TXOFF))
-		netif_stop_queue(netdev);
+	/* Force detection of hung controller every watchdog period*/
+	adapter->detect_tx_hung = TRUE;
 
 	/* Reset the timer */
 	mod_timer(&adapter->watchdog_timer, jiffies + 2 * HZ);
@@ -1522,7 +1630,7 @@
 #define E1000_TX_FLAGS_VLAN_MASK	0xffff0000
 #define E1000_TX_FLAGS_VLAN_SHIFT	16
 
-static inline boolean_t
+static inline int
 e1000_tso(struct e1000_adapter *adapter, struct sk_buff *skb)
 {
 #ifdef NETIF_F_TSO
@@ -1531,8 +1639,15 @@
 	uint32_t cmd_length = 0;
 	uint16_t ipcse, tucse, mss;
 	uint8_t ipcss, ipcso, tucss, tucso, hdr_len;
+	int err;
 
 	if(skb_shinfo(skb)->tso_size) {
+		if (skb_header_cloned(skb)) {
+			err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC);
+			if (err)
+				return err;
+		}
+
 		hdr_len = ((skb->h.raw - skb->data) + (skb->h.th->doff << 2));
 		mss = skb_shinfo(skb)->tso_size;
 		skb->nh.iph->tot_len = 0;
@@ -1569,11 +1684,11 @@
 		if(++i == adapter->tx_ring.count) i = 0;
 		adapter->tx_ring.next_to_use = i;
 
-		return TRUE;
+		return 1;
 	}
 #endif
 
-	return FALSE;
+	return 0;
 }
 
 static inline boolean_t
@@ -1798,6 +1913,7 @@
 	unsigned int nr_frags = 0;
 	unsigned int mss = 0;
 	int count = 0;
+	int tso;
 	unsigned int f;
 	len -= skb->data_len;
 
@@ -1869,7 +1985,13 @@
 
 	first = adapter->tx_ring.next_to_use;
 	
-	if(likely(e1000_tso(adapter, skb)))
+	tso = e1000_tso(adapter, skb);
+	if (tso < 0) {
+		dev_kfree_skb_any(skb);
+		return NETDEV_TX_OK;
+	}
+
+	if (likely(tso))
 		tx_flags |= E1000_TX_FLAGS_TSO;
 	else if(likely(e1000_tx_csum(adapter, skb)))
 		tx_flags |= E1000_TX_FLAGS_CSUM;
@@ -2151,10 +2273,28 @@
 		__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){
+		atomic_inc(&adapter->irq_sem);
+		E1000_WRITE_REG(&adapter->hw, IMC, ~0);
+	}
+
 	for(i = 0; i < E1000_MAX_INTR; i++)
 		if(unlikely(!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;
@@ -2174,24 +2314,21 @@
 	int tx_cleaned;
 	int work_done = 0;
 	
-	if (!netif_carrier_ok(netdev))
-		goto quit_polling;
-
 	tx_cleaned = e1000_clean_tx_irq(adapter);
 	e1000_clean_rx_irq(adapter, &work_done, work_to_do);
 
 	*budget -= work_done;
 	netdev->quota -= work_done;
 	
-	/* if no Rx and Tx cleanup work was done, exit the polling mode */
-	if(!tx_cleaned || (work_done < work_to_do) || 
+	/* if no Tx and not enough Rx work done, exit the polling mode */
+	if((!tx_cleaned && (work_done < work_to_do)) || 
 				!netif_running(netdev)) {
-quit_polling:	netif_rx_complete(netdev);
+		netif_rx_complete(netdev);
 		e1000_irq_enable(adapter);
 		return 0;
 	}
 
-	return (work_done >= work_to_do);
+	return 1;
 }
 
 #endif
@@ -2215,11 +2352,34 @@
 	eop_desc = E1000_TX_DESC(*tx_ring, eop);
 
 	while(eop_desc->upper.data & cpu_to_le32(E1000_TXD_STAT_DD)) {
+		/* pre-mature writeback of Tx descriptors     */
+		/* clear (free buffers and unmap pci_mapping) */
+		/* previous_buffer_info                       */
+		if (likely(adapter->previous_buffer_info.skb != NULL)) {
+			e1000_unmap_and_free_tx_resource(adapter, 
+					&adapter->previous_buffer_info);
+		}
+
 		for(cleaned = FALSE; !cleaned; ) {
 			tx_desc = E1000_TX_DESC(*tx_ring, i);
 			buffer_info = &tx_ring->buffer_info[i];
+			cleaned = (i == eop);
+
+			/* pre-mature writeback of Tx descriptors */
+			/* save the cleaning of the this for the  */
+			/* next iteration                         */
+			if (cleaned) {
+				memcpy(&adapter->previous_buffer_info,
+					buffer_info,
+					sizeof(struct e1000_buffer));
+				memset(buffer_info,
+					0,
+					sizeof(struct e1000_buffer));
+			} else {
+				e1000_unmap_and_free_tx_resource(adapter, 
+							buffer_info);
+			}
 
-			e1000_unmap_and_free_tx_resource(adapter, buffer_info);
 			tx_desc->buffer_addr = 0;
 			tx_desc->lower.data = 0;
 			tx_desc->upper.data = 0;
@@ -2241,6 +2401,16 @@
 		netif_wake_queue(netdev);
 
 	spin_unlock(&adapter->tx_lock);
+ 
+	if(adapter->detect_tx_hung) {
+		/* detect a transmit hang in hardware, this serializes the
+		 * check with the clearing of time_stamp and movement of i */
+		adapter->detect_tx_hung = FALSE;
+		if(tx_ring->buffer_info[i].dma &&
+		   time_after(jiffies, tx_ring->buffer_info[i].time_stamp + HZ) &&
+		   !(E1000_READ_REG(&adapter->hw, STATUS) & E1000_STATUS_TXOFF))
+			netif_stop_queue(netdev);
+	}
 
 	return cleaned;
 }
@@ -2407,19 +2577,43 @@
 	struct e1000_rx_desc *rx_desc;
 	struct e1000_buffer *buffer_info;
 	struct sk_buff *skb;
-	unsigned int i;
+	unsigned int i, bufsz;
 
 	i = rx_ring->next_to_use;
 	buffer_info = &rx_ring->buffer_info[i];
 
 	while(!buffer_info->skb) {
-		skb = dev_alloc_skb(adapter->rx_buffer_len + NET_IP_ALIGN);
+		bufsz = adapter->rx_buffer_len + NET_IP_ALIGN;
 
+		skb = dev_alloc_skb(bufsz);
 		if(unlikely(!skb)) {
 			/* Better luck next round */
 			break;
 		}
 
+		/* fix for errata 23, cant cross 64kB boundary */
+		if (!e1000_check_64k_bound(adapter, skb->data, bufsz)) {
+			struct sk_buff *oldskb = skb;
+			DPRINTK(RX_ERR,ERR,
+				"skb align check failed: %u bytes at %p\n",
+				bufsz, skb->data);
+			/* try again, without freeing the previous */
+			skb = dev_alloc_skb(bufsz);
+			if (!skb) {
+				dev_kfree_skb(oldskb);
+				break;
+			}
+			if (!e1000_check_64k_bound(adapter, skb->data, bufsz)) {
+				/* give up */
+				dev_kfree_skb(skb);
+				dev_kfree_skb(oldskb);
+				break; /* while !buffer_info->skb */
+			} else {
+				/* move on with the new one */
+				dev_kfree_skb(oldskb);
+			}
+		}
+
 		/* Make buffer alignment 2 beyond a 16 byte boundary
 		 * this will result in a 16 byte aligned IP header after
 		 * the 14 byte MAC header is removed
@@ -2434,6 +2628,25 @@
 						  skb->data,
 						  adapter->rx_buffer_len,
 						  PCI_DMA_FROMDEVICE);
+
+		/* fix for errata 23, cant cross 64kB boundary */
+		if(!e1000_check_64k_bound(adapter,
+			                       (void *)(unsigned long)buffer_info->dma,
+			                       adapter->rx_buffer_len)) {
+			DPRINTK(RX_ERR,ERR,
+				"dma align check failed: %u bytes at %ld\n",
+				adapter->rx_buffer_len, (unsigned long)buffer_info->dma);
+
+			dev_kfree_skb(skb);
+			buffer_info->skb = NULL;
+
+			pci_unmap_single(pdev,
+					 buffer_info->dma,
+					 adapter->rx_buffer_len,
+					 PCI_DMA_FROMDEVICE);
+
+			break; /* while !buffer_info->skb */
+		}
 
 		rx_desc = E1000_RX_DESC(*rx_ring, i);
 		rx_desc->buffer_addr = cpu_to_le64(buffer_info->dma);
diff -Nru a/drivers/net/eepro100.c b/drivers/net/eepro100.c
--- a/drivers/net/eepro100.c	2005-03-11 12:51:47 -08:00
+++ b/drivers/net/eepro100.c	2005-03-11 12:51:47 -08:00
@@ -152,16 +152,6 @@
 
 #define RUN_AT(x) (jiffies + (x))
 
-/* ACPI power states don't universally work (yet) */
-#ifndef CONFIG_PM
-#undef pci_set_power_state
-#define pci_set_power_state null_set_power_state
-static inline int null_set_power_state(struct pci_dev *dev, int state)
-{
-	return 0;
-}
-#endif /* CONFIG_PM */
-
 #define netdevice_start(dev)
 #define netdevice_stop(dev)
 #define netif_set_tx_timeout(dev, tf, tm) \
@@ -2281,7 +2271,7 @@
 }
 
 #ifdef CONFIG_PM
-static int eepro100_suspend(struct pci_dev *pdev, u32 state)
+static int eepro100_suspend(struct pci_dev *pdev, pm_message_t state)
 {
 	struct net_device *dev = pci_get_drvdata (pdev);
 	struct speedo_private *sp = netdev_priv(dev);
@@ -2299,7 +2289,7 @@
 	
 	/* XXX call pci_set_power_state ()? */
 	pci_disable_device(pdev);
-	pci_set_power_state (pdev, 3);
+	pci_set_power_state (pdev, PCI_D3hot);
 	return 0;
 }
 
@@ -2309,7 +2299,7 @@
 	struct speedo_private *sp = netdev_priv(dev);
 	void __iomem *ioaddr = sp->regs;
 
-	pci_set_power_state(pdev, 0);
+	pci_set_power_state(pdev, PCI_D0);
 	pci_restore_state(pdev);
 	pci_enable_device(pdev);
 	pci_set_master(pdev);
@@ -2355,12 +2345,8 @@
 }
 
 static struct pci_device_id eepro100_pci_tbl[] = {
-	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82557,
-		PCI_ANY_ID, PCI_ANY_ID, },
-	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82559ER,
-		PCI_ANY_ID, PCI_ANY_ID, },
-	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_7,
-		PCI_ANY_ID, PCI_ANY_ID, },
+	{ PCI_VENDOR_ID_INTEL, 0x1229, PCI_ANY_ID, PCI_ANY_ID, },
+	{ PCI_VENDOR_ID_INTEL, 0x1209, PCI_ANY_ID, PCI_ANY_ID, },
 	{ PCI_VENDOR_ID_INTEL, 0x1029, PCI_ANY_ID, PCI_ANY_ID, },
 	{ PCI_VENDOR_ID_INTEL, 0x1030, PCI_ANY_ID, PCI_ANY_ID, },
 	{ PCI_VENDOR_ID_INTEL, 0x1031, PCI_ANY_ID, PCI_ANY_ID, },
@@ -2380,7 +2366,6 @@
 	{ PCI_VENDOR_ID_INTEL, 0x1050, PCI_ANY_ID, PCI_ANY_ID, },
 	{ PCI_VENDOR_ID_INTEL, 0x1059, PCI_ANY_ID, PCI_ANY_ID, },
 	{ PCI_VENDOR_ID_INTEL, 0x1227, PCI_ANY_ID, PCI_ANY_ID, },
-	{ PCI_VENDOR_ID_INTEL, 0x1228, PCI_ANY_ID, PCI_ANY_ID, },
 	{ PCI_VENDOR_ID_INTEL, 0x2449, PCI_ANY_ID, PCI_ANY_ID, },
 	{ PCI_VENDOR_ID_INTEL, 0x2459, PCI_ANY_ID, PCI_ANY_ID, },
 	{ PCI_VENDOR_ID_INTEL, 0x245D, PCI_ANY_ID, PCI_ANY_ID, },
diff -Nru a/drivers/net/epic100.c b/drivers/net/epic100.c
--- a/drivers/net/epic100.c	2005-03-11 12:51:43 -08:00
+++ b/drivers/net/epic100.c	2005-03-11 12:51:46 -08:00
@@ -1624,7 +1624,7 @@
 
 #ifdef CONFIG_PM
 
-static int epic_suspend (struct pci_dev *pdev, u32 state)
+static int epic_suspend (struct pci_dev *pdev, pm_message_t state)
 {
 	struct net_device *dev = pci_get_drvdata(pdev);
 	long ioaddr = dev->base_addr;
diff -Nru a/drivers/net/es3210.c b/drivers/net/es3210.c
--- a/drivers/net/es3210.c	2005-03-11 12:51:50 -08:00
+++ b/drivers/net/es3210.c	2005-03-11 12:51:50 -08:00
@@ -159,6 +159,7 @@
 {
 	free_irq(dev->irq, dev);
 	release_region(dev->base_addr, ES_IO_EXTENT);
+	iounmap(ei_status.mem);
 }
 
 #ifndef MODULE
@@ -271,9 +272,14 @@
 		printk(" assigning ");
 	}
 
-	dev->mem_end = ei_status.rmem_end = dev->mem_start
-		+ (ES_STOP_PG - ES_START_PG)*256;
-	ei_status.rmem_start = dev->mem_start + TX_PAGES*256;
+	ei_status.mem = ioremap(dev->mem_start, (ES_STOP_PG - ES_START_PG)*256);
+	if (!ei_status.mem) {
+		printk("ioremap failed - giving up\n");
+		retval = -ENXIO;
+		goto out1;
+	}
+
+	dev->mem_end = dev->mem_start + (ES_STOP_PG - ES_START_PG)*256;
 
 	printk("mem %#lx-%#lx\n", dev->mem_start, dev->mem_end-1);
 
@@ -353,8 +359,8 @@
 static void
 es_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
 {
-	unsigned long hdr_start = dev->mem_start + ((ring_page - ES_START_PG)<<8);
-	isa_memcpy_fromio(hdr, hdr_start, sizeof(struct e8390_pkt_hdr));
+	void __iomem *hdr_start = ei_status.mem + ((ring_page - ES_START_PG)<<8);
+	memcpy_fromio(hdr, hdr_start, sizeof(struct e8390_pkt_hdr));
 	hdr->count = (hdr->count + 3) & ~3;     /* Round up allocation. */
 }
 
@@ -367,27 +373,27 @@
 static void es_block_input(struct net_device *dev, int count, struct sk_buff *skb,
 						  int ring_offset)
 {
-	unsigned long xfer_start = dev->mem_start + ring_offset - (ES_START_PG<<8);
+	void __iomem *xfer_start = ei_status.mem + ring_offset - ES_START_PG*256;
 
-	if (xfer_start + count > ei_status.rmem_end) {
+	if (ring_offset + count > ES_STOP_PG*256) {
 		/* Packet wraps over end of ring buffer. */
-		int semi_count = ei_status.rmem_end - xfer_start;
-		isa_memcpy_fromio(skb->data, xfer_start, semi_count);
+		int semi_count = ES_STOP_PG*256 - ring_offset;
+		memcpy_fromio(skb->data, xfer_start, semi_count);
 		count -= semi_count;
-		isa_memcpy_fromio(skb->data + semi_count, ei_status.rmem_start, count);
+		memcpy_fromio(skb->data + semi_count, ei_status.mem, count);
 	} else {
 		/* Packet is in one chunk. */
-		isa_eth_io_copy_and_sum(skb, xfer_start, count, 0);
+		eth_io_copy_and_sum(skb, xfer_start, count, 0);
 	}
 }
 
 static void es_block_output(struct net_device *dev, int count,
 				const unsigned char *buf, int start_page)
 {
-	unsigned long shmem = dev->mem_start + ((start_page - ES_START_PG)<<8);
+	void __iomem *shmem = ei_status.mem + ((start_page - ES_START_PG)<<8);
 
 	count = (count + 3) & ~3;     /* Round up to doubleword */
-	isa_memcpy_toio(shmem, buf, count);
+	memcpy_toio(shmem, buf, count);
 }
 
 static int es_open(struct net_device *dev)
diff -Nru a/drivers/net/ethertap.c b/drivers/net/ethertap.c
--- a/drivers/net/ethertap.c	2005-03-11 12:51:42 -08:00
+++ b/drivers/net/ethertap.c	2005-03-11 12:51:42 -08:00
@@ -343,7 +343,7 @@
 }
 
 
-int __init ethertap_init(void)
+static int __init ethertap_init(void)
 {
 	int i, err = 0;
 
@@ -371,7 +371,7 @@
 }
 module_init(ethertap_init);
 
-void __exit ethertap_cleanup(void)
+static void __exit ethertap_cleanup(void)
 {
 	int i;
 
diff -Nru a/drivers/net/ewrk3.c b/drivers/net/ewrk3.c
--- a/drivers/net/ewrk3.c	2005-03-11 12:51:51 -08:00
+++ b/drivers/net/ewrk3.c	2005-03-11 12:51:51 -08:00
@@ -273,6 +273,7 @@
 struct ewrk3_private {
 	char adapter_name[80];	/* Name exported to /proc/ioports */
 	u_long shmem_base;	/* Shared memory start address */
+	void __iomem *shmem;
 	u_long shmem_length;	/* Shared memory window length */
 	struct net_device_stats stats;	/* Public stats */
 	struct ewrk3_stats pktStats; /* Private stats counters */
@@ -281,7 +282,7 @@
 	u_char lemac;		/* Chip rev. level */
 	u_char hard_strapped;	/* Don't allow a full open */
 	u_char txc;		/* Transmit cut through */
-	u_char *mctbl;		/* Pointer to the multicast table */
+	void __iomem *mctbl;	/* Pointer to the multicast table */
 	u_char led_mask;	/* Used to reserve LED access for ethtool */
 	spinlock_t hw_lock;
 };
@@ -535,6 +536,9 @@
 
 	lp = netdev_priv(dev);
 	lp->shmem_base = mem_start;
+	lp->shmem = ioremap(mem_start, shmem_length);
+	if (!lp->shmem)
+		return -ENOMEM;
 	lp->shmem_length = shmem_length;
 	lp->lemac = lemac;
 	lp->hard_strapped = hard_strapped;
@@ -590,6 +594,7 @@
 				} else {
 					printk(", but incorrect IRQ line detected.\n");
 				}
+				iounmap(lp->shmem);
 				return -ENXIO;
 			}
 
@@ -768,7 +773,7 @@
 {
 	struct ewrk3_private *lp = netdev_priv(dev);
 	u_long iobase = dev->base_addr;
-	u_long buf = 0;
+	void __iomem *buf = NULL;
 	u_char icr;
 	u_char page;
 
@@ -801,13 +806,13 @@
 	if (lp->shmem_length == IO_ONLY) {
 		outb (page, EWRK3_IOPR);
 	} else if (lp->shmem_length == SHMEM_2K) {
-		buf = lp->shmem_base;
+		buf = lp->shmem;
 		outb (page, EWRK3_MPR);
 	} else if (lp->shmem_length == SHMEM_32K) {
-		buf = ((((short) page << 11) & 0x7800) + lp->shmem_base);
+		buf = (((short) page << 11) & 0x7800) + lp->shmem;
 		outb ((page >> 4), EWRK3_MPR);
 	} else if (lp->shmem_length == SHMEM_64K) {
-		buf = ((((short) page << 11) & 0xf800) + lp->shmem_base);
+		buf = (((short) page << 11) & 0xf800) + lp->shmem;
 		outb ((page >> 5), EWRK3_MPR);
 	} else {
 		printk (KERN_ERR "%s: Oops - your private data area is hosed!\n",
@@ -831,30 +836,28 @@
 		}
 		outb (page, EWRK3_TQ);	/* Start sending pkt */
 	} else {
-		isa_writeb ((char) (TCR_QMODE | TCR_PAD | TCR_IFC), buf);	/* ctrl byte */
+		writeb ((char) (TCR_QMODE | TCR_PAD | TCR_IFC), buf);	/* ctrl byte */
 		buf += 1;
-		isa_writeb ((char) (skb->len & 0xff), buf);	/* length (16 bit xfer) */
+		writeb ((char) (skb->len & 0xff), buf);	/* length (16 bit xfer) */
 		buf += 1;
 		if (lp->txc) {
-			isa_writeb ((char)
-				    (((skb->len >> 8) & 0xff) | XCT), buf);
+			writeb(((skb->len >> 8) & 0xff) | XCT, buf);
 			buf += 1;
-			isa_writeb (0x04, buf);	/* index byte */
+			writeb (0x04, buf);	/* index byte */
 			buf += 1;
-			isa_writeb (0x00, (buf + skb->len));	/* Write the XCT flag */
-			isa_memcpy_toio (buf, skb->data, PRELOAD);	/* Write PRELOAD bytes */
+			writeb (0x00, (buf + skb->len));	/* Write the XCT flag */
+			memcpy_toio (buf, skb->data, PRELOAD);	/* Write PRELOAD bytes */
 			outb (page, EWRK3_TQ);	/* Start sending pkt */
-			isa_memcpy_toio (buf + PRELOAD,
+			memcpy_toio (buf + PRELOAD,
 					 skb->data + PRELOAD,
 					 skb->len - PRELOAD);
-			isa_writeb (0xff, (buf + skb->len));	/* Write the XCT flag */
+			writeb (0xff, (buf + skb->len));	/* Write the XCT flag */
 		} else {
-			isa_writeb ((char)
-				    ((skb->len >> 8) & 0xff), buf);
+			writeb ((skb->len >> 8) & 0xff, buf);
 			buf += 1;
-			isa_writeb (0x04, buf);	/* index byte */
+			writeb (0x04, buf);	/* index byte */
 			buf += 1;
-			isa_memcpy_toio (buf, skb->data, skb->len);	/* Write data bytes */
+			memcpy_toio (buf, skb->data, skb->len);	/* Write data bytes */
 			outb (page, EWRK3_TQ);	/* Start sending pkt */
 		}
 	}
@@ -940,7 +943,7 @@
 	u_long iobase = dev->base_addr;
 	int i, status = 0;
 	u_char page;
-	u_long buf = 0;
+	void __iomem *buf = NULL;
 
 	while (inb(EWRK3_RQC) && !status) {	/* Whilst there's incoming data */
 		if ((page = inb(EWRK3_RQ)) < lp->mPage) {	/* Get next entry's buffer page */
@@ -950,13 +953,13 @@
 			if (lp->shmem_length == IO_ONLY) {
 				outb(page, EWRK3_IOPR);
 			} else if (lp->shmem_length == SHMEM_2K) {
-				buf = lp->shmem_base;
+				buf = lp->shmem;
 				outb(page, EWRK3_MPR);
 			} else if (lp->shmem_length == SHMEM_32K) {
-				buf = ((((short) page << 11) & 0x7800) + lp->shmem_base);
+				buf = (((short) page << 11) & 0x7800) + lp->shmem;
 				outb((page >> 4), EWRK3_MPR);
 			} else if (lp->shmem_length == SHMEM_64K) {
-				buf = ((((short) page << 11) & 0xf800) + lp->shmem_base);
+				buf = (((short) page << 11) & 0xf800) + lp->shmem;
 				outb((page >> 5), EWRK3_MPR);
 			} else {
 				status = -1;
@@ -972,9 +975,9 @@
 					pkt_len = inb(EWRK3_DATA);
 					pkt_len |= ((u_short) inb(EWRK3_DATA) << 8);
 				} else {
-					rx_status = isa_readb(buf);
+					rx_status = readb(buf);
 					buf += 1;
-					pkt_len = isa_readw(buf);
+					pkt_len = readw(buf);
 					buf += 3;
 				}
 
@@ -1001,7 +1004,7 @@
 								*p++ = inb(EWRK3_DATA);
 							}
 						} else {
-							isa_memcpy_fromio(p, buf, pkt_len);
+							memcpy_fromio(p, buf, pkt_len);
 						}
 
 						for (i = 1; i < EWRK3_PKT_STAT_SZ - 1; i++) {
@@ -1153,9 +1156,9 @@
 	csr = inb(EWRK3_CSR);
 
 	if (lp->shmem_length == IO_ONLY) {
-		lp->mctbl = (char *) PAGE0_HTE;
+		lp->mctbl = NULL;
 	} else {
-		lp->mctbl = (char *) (lp->shmem_base + PAGE0_HTE);
+		lp->mctbl = lp->shmem + PAGE0_HTE;
 	}
 
 	csr &= ~(CSR_PME | CSR_MCE);
@@ -1184,7 +1187,7 @@
 	u_long iobase = dev->base_addr;
 	int i;
 	char *addrs, bit, byte;
-	short *p = (short *) lp->mctbl;
+	short __iomem *p = lp->mctbl;
 	u16 hashcode;
 	u32 crc;
 
@@ -1192,7 +1195,7 @@
 
 	if (lp->shmem_length == IO_ONLY) {
 		outb(0, EWRK3_IOPR);
-		outw(EEPROM_OFFSET(lp->mctbl), EWRK3_PIR1);
+		outw(PAGE0_HTE, EWRK3_PIR1);
 	} else {
 		outb(0, EWRK3_MPR);
 	}
@@ -1202,7 +1205,7 @@
 			if (lp->shmem_length == IO_ONLY) {
 				outb(0xff, EWRK3_DATA);
 			} else {	/* memset didn't work here */
-				isa_writew(0xffff, (int) p);
+				writew(0xffff, p);
 				p++;
 				i++;
 			}
@@ -1219,8 +1222,8 @@
 				outb(0x00, EWRK3_DATA);
 			}
 		} else {
-			isa_memset_io((int) lp->mctbl, 0, (HASH_TABLE_LEN >> 3));
-			isa_writeb(0x80, (int) (lp->mctbl + (HASH_TABLE_LEN >> 4) - 1));
+			memset_io(lp->mctbl, 0, HASH_TABLE_LEN >> 3);
+			writeb(0x80, lp->mctbl + (HASH_TABLE_LEN >> 4) - 1);
 		}
 
 		/* Update table */
@@ -1237,13 +1240,13 @@
 				if (lp->shmem_length == IO_ONLY) {
 					u_char tmp;
 
-					outw((short) ((long) lp->mctbl) + byte, EWRK3_PIR1);
+					outw(PAGE0_HTE + byte, EWRK3_PIR1);
 					tmp = inb(EWRK3_DATA);
 					tmp |= bit;
-					outw((short) ((long) lp->mctbl) + byte, EWRK3_PIR1);
+					outw(PAGE0_HTE + byte, EWRK3_PIR1);
 					outb(tmp, EWRK3_DATA);
 				} else {
-					isa_writeb(isa_readb((int)(lp->mctbl + byte)) | bit, (int)(lp->mctbl + byte));
+					writeb(readb(lp->mctbl + byte) | bit, lp->mctbl + byte);
 				}
 			}
 		}
@@ -1654,8 +1657,7 @@
 
 		/* Wait a little while */
 		spin_unlock_irqrestore(&lp->hw_lock, flags);
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		schedule_timeout(HZ>>2);
+		msleep(250);
 		spin_lock_irqsave(&lp->hw_lock, flags);
 
 		/* Exit if we got a signal */
@@ -1784,7 +1786,7 @@
 			}
 		} else {
 			outb(0, EWRK3_MPR);
-			isa_memcpy_fromio(tmp->addr, lp->shmem_base + PAGE0_HTE, (HASH_TABLE_LEN >> 3));
+			memcpy_fromio(tmp->addr, lp->shmem + PAGE0_HTE, (HASH_TABLE_LEN >> 3));
 		}
 		spin_unlock_irqrestore(&lp->hw_lock, flags);
 
@@ -1954,10 +1956,13 @@
 	int i;
 
 	for( i=0; i<ndevs; i++ ) {
-		unregister_netdev(ewrk3_devs[i]);
-		release_region(ewrk3_devs[i]->base_addr, EWRK3_TOTAL_SIZE);
-		free_netdev(ewrk3_devs[i]);
+		struct net_device *dev = ewrk3_devs[i];
+		struct ewrk3_private *lp = netdev_priv(dev);
 		ewrk3_devs[i] = NULL;
+		unregister_netdev(dev);
+		release_region(dev->base_addr, EWRK3_TOTAL_SIZE);
+		iounmap(lp->shmem);
+		free_netdev(dev);
 	}
 }
 
diff -Nru a/drivers/net/fealnx.c b/drivers/net/fealnx.c
--- a/drivers/net/fealnx.c	2005-03-11 12:51:52 -08:00
+++ b/drivers/net/fealnx.c	2005-03-11 12:51:52 -08:00
@@ -102,21 +102,6 @@
 #define USE_IO_OPS
 #endif
 
-#ifdef USE_IO_OPS
-#undef readb
-#undef readw
-#undef readl
-#undef writeb
-#undef writew
-#undef writel
-#define readb inb
-#define readw inw
-#define readl inl
-#define writeb outb
-#define writew outw
-#define writel outl
-#endif
-
 /* Kernel compatibility defines, some common to David Hinds' PCMCIA package. */
 /* This is only in the support-all-kernels source code. */
 
@@ -444,6 +429,7 @@
 	int mii_cnt;		/* MII device addresses. */
 	unsigned char phys[2];	/* MII device addresses. */
 	struct mii_if_info mii;
+	void __iomem *mem;
 };
 
 
@@ -468,23 +454,23 @@
 static void reset_rx_descriptors(struct net_device *dev);
 static void reset_tx_descriptors(struct net_device *dev);
 
-static void stop_nic_rx(long ioaddr, long crvalue)
+static void stop_nic_rx(void __iomem *ioaddr, long crvalue)
 {
 	int delay = 0x1000;
-	writel(crvalue & ~(CR_W_RXEN), ioaddr + TCRRCR);
+	iowrite32(crvalue & ~(CR_W_RXEN), ioaddr + TCRRCR);
 	while (--delay) {
-		if ( (readl(ioaddr + TCRRCR) & CR_R_RXSTOP) == CR_R_RXSTOP)
+		if ( (ioread32(ioaddr + TCRRCR) & CR_R_RXSTOP) == CR_R_RXSTOP)
 			break;
 	}
 }
 
 
-static void stop_nic_rxtx(long ioaddr, long crvalue)
+static void stop_nic_rxtx(void __iomem *ioaddr, long crvalue)
 {
 	int delay = 0x1000;
-	writel(crvalue & ~(CR_W_RXEN+CR_W_TXEN), ioaddr + TCRRCR);
+	iowrite32(crvalue & ~(CR_W_RXEN+CR_W_TXEN), ioaddr + TCRRCR);
 	while (--delay) {
-		if ( (readl(ioaddr + TCRRCR) & (CR_R_RXSTOP+CR_R_TXSTOP))
+		if ( (ioread32(ioaddr + TCRRCR) & (CR_R_RXSTOP+CR_R_TXSTOP))
 					    == (CR_R_RXSTOP+CR_R_TXSTOP) )
 			break;
 	}
@@ -498,11 +484,17 @@
 	int i, option, err, irq;
 	static int card_idx = -1;
 	char boardname[12];
-	long ioaddr;
+	void __iomem *ioaddr;
+	unsigned long len;
 	unsigned int chip_id = ent->driver_data;
 	struct net_device *dev;
 	void *ring_space;
 	dma_addr_t ring_dma;
+#ifdef USE_IO_OPS
+	int bar = 0;
+#else
+	int bar = 1;
+#endif
 	
 /* when built into the kernel, we only print version if device is found */
 #ifndef MODULE
@@ -520,14 +512,10 @@
 	if (i) return i;
 	pci_set_master(pdev);
 	
-#ifdef USE_IO_OPS
-	ioaddr = pci_resource_len(pdev, 0);
-#else
-	ioaddr = pci_resource_len(pdev, 1);
-#endif
-	if (ioaddr < MIN_REGION_SIZE) {
+	len = pci_resource_len(pdev, bar);
+	if (len < MIN_REGION_SIZE) {
 		printk(KERN_ERR "%s: region size %ld too small, aborting\n",
-		       boardname, ioaddr);
+		       boardname, len);
 		return -ENODEV;
 	}
 
@@ -536,17 +524,12 @@
 	
 	irq = pdev->irq;
 
-#ifdef USE_IO_OPS
-	ioaddr = pci_resource_start(pdev, 0);
-#else
-	ioaddr = (long) ioremap(pci_resource_start(pdev, 1),
-				pci_resource_len(pdev, 1));
+	ioaddr = pci_iomap(pdev, bar, len);
 	if (!ioaddr) {
 		err = -ENOMEM;
 		goto err_out_res;
 	}
-#endif
-	
+
 	dev = alloc_etherdev(sizeof(struct netdev_private));
 	if (!dev) {
 		err = -ENOMEM;
@@ -557,16 +540,17 @@
 
 	/* read ethernet id */
 	for (i = 0; i < 6; ++i)
-		dev->dev_addr[i] = readb(ioaddr + PAR0 + i);
+		dev->dev_addr[i] = ioread8(ioaddr + PAR0 + i);
 
 	/* Reset the chip to erase previous misconfiguration. */
-	writel(0x00000001, ioaddr + BCR);
+	iowrite32(0x00000001, ioaddr + BCR);
 
-	dev->base_addr = ioaddr;
+	dev->base_addr = (unsigned long)ioaddr;
 	dev->irq = irq;
 
 	/* Make certain the descriptor lists are aligned. */
-	np = dev->priv;
+	np = netdev_priv(dev);
+	np->mem = ioaddr;
 	spin_lock_init(&np->lock);
 	np->pci_dev = pdev;
 	np->flags = skel_netdrv_tbl[chip_id].flags;
@@ -635,7 +619,7 @@
 		np->phys[0] = 32;
 /* 89/6/23 add, (begin) */
 		/* get phy type */
-		if (readl(ioaddr + PHYIDENTIFIER) == MysonPHYID)
+		if (ioread32(ioaddr + PHYIDENTIFIER) == MysonPHYID)
 			np->PHYType = MysonPHY;
 		else
 			np->PHYType = OtherPHY;
@@ -670,7 +654,7 @@
 		if (np->flags == HAS_MII_XCVR)
 			mdio_write(dev, np->phys[0], MII_ADVERTISE, ADVERTISE_FULL);
 		else
-			writel(ADVERTISE_FULL, ioaddr + ANARANLPAR);
+			iowrite32(ADVERTISE_FULL, ioaddr + ANARANLPAR);
 		np->mii.force_media = 1;
 	}
 
@@ -689,7 +673,7 @@
 	if (err)
 		goto err_out_free_tx;
 
-	printk(KERN_INFO "%s: %s at 0x%lx, ",
+	printk(KERN_INFO "%s: %s at %p, ",
 	       dev->name, skel_netdrv_tbl[chip_id].chip_name, ioaddr);
 	for (i = 0; i < 5; i++)
 		printk("%2.2x:", dev->dev_addr[i]);
@@ -704,10 +688,8 @@
 err_out_free_dev:
 	free_netdev(dev);
 err_out_unmap:
-#ifndef USE_IO_OPS
-	iounmap((void *)ioaddr);
+	pci_iounmap(pdev, ioaddr);
 err_out_res:
-#endif
 	pci_release_regions(pdev);
 	return err;
 }
@@ -718,16 +700,14 @@
 	struct net_device *dev = pci_get_drvdata(pdev);
 
 	if (dev) {
-		struct netdev_private *np = dev->priv;
+		struct netdev_private *np = netdev_priv(dev);
 
 		pci_free_consistent(pdev, TX_TOTAL_SIZE, np->tx_ring,
 			np->tx_ring_dma);
 		pci_free_consistent(pdev, RX_TOTAL_SIZE, np->rx_ring,
 			np->rx_ring_dma);
 		unregister_netdev(dev);
-#ifndef USE_IO_OPS
-		iounmap((void *)dev->base_addr);
-#endif
+		pci_iounmap(pdev, np->mem);
 		free_netdev(dev);
 		pci_release_regions(pdev);
 		pci_set_drvdata(pdev, NULL);
@@ -736,14 +716,14 @@
 }
 
 
-static ulong m80x_send_cmd_to_phy(long miiport, int opcode, int phyad, int regad)
+static ulong m80x_send_cmd_to_phy(void __iomem *miiport, int opcode, int phyad, int regad)
 {
 	ulong miir;
 	int i;
 	unsigned int mask, data;
 
 	/* enable MII output */
-	miir = (ulong) readl(miiport);
+	miir = (ulong) ioread32(miiport);
 	miir &= 0xfffffff0;
 
 	miir |= MASK_MIIR_MII_WRITE + MASK_MIIR_MII_MDO;
@@ -752,11 +732,11 @@
 	for (i = 0; i < 32; i++) {
 		/* low MDC; MDO is already high (miir) */
 		miir &= ~MASK_MIIR_MII_MDC;
-		writel(miir, miiport);
+		iowrite32(miir, miiport);
 
 		/* high MDC */
 		miir |= MASK_MIIR_MII_MDC;
-		writel(miir, miiport);
+		iowrite32(miir, miiport);
 	}
 
 	/* calculate ST+OP+PHYAD+REGAD+TA */
@@ -770,10 +750,10 @@
 		if (mask & data)
 			miir |= MASK_MIIR_MII_MDO;
 
-		writel(miir, miiport);
+		iowrite32(miir, miiport);
 		/* high MDC */
 		miir |= MASK_MIIR_MII_MDC;
-		writel(miir, miiport);
+		iowrite32(miir, miiport);
 		udelay(30);
 
 		/* next */
@@ -787,7 +767,8 @@
 
 static int mdio_read(struct net_device *dev, int phyad, int regad)
 {
-	long miiport = dev->base_addr + MANAGEMENT;
+	struct netdev_private *np = netdev_priv(dev);
+	void __iomem *miiport = np->mem + MANAGEMENT;
 	ulong miir;
 	unsigned int mask, data;
 
@@ -799,16 +780,16 @@
 	while (mask) {
 		/* low MDC */
 		miir &= ~MASK_MIIR_MII_MDC;
-		writel(miir, miiport);
+		iowrite32(miir, miiport);
 
 		/* read MDI */
-		miir = readl(miiport);
+		miir = ioread32(miiport);
 		if (miir & MASK_MIIR_MII_MDI)
 			data |= mask;
 
 		/* high MDC, and wait */
 		miir |= MASK_MIIR_MII_MDC;
-		writel(miir, miiport);
+		iowrite32(miir, miiport);
 		udelay(30);
 
 		/* next */
@@ -817,7 +798,7 @@
 
 	/* low MDC */
 	miir &= ~MASK_MIIR_MII_MDC;
-	writel(miir, miiport);
+	iowrite32(miir, miiport);
 
 	return data & 0xffff;
 }
@@ -825,7 +806,8 @@
 
 static void mdio_write(struct net_device *dev, int phyad, int regad, int data)
 {
-	long miiport = dev->base_addr + MANAGEMENT;
+	struct netdev_private *np = netdev_priv(dev);
+	void __iomem *miiport = np->mem + MANAGEMENT;
 	ulong miir;
 	unsigned int mask;
 
@@ -838,11 +820,11 @@
 		miir &= ~(MASK_MIIR_MII_MDC + MASK_MIIR_MII_MDO);
 		if (mask & data)
 			miir |= MASK_MIIR_MII_MDO;
-		writel(miir, miiport);
+		iowrite32(miir, miiport);
 
 		/* high MDC */
 		miir |= MASK_MIIR_MII_MDC;
-		writel(miir, miiport);
+		iowrite32(miir, miiport);
 
 		/* next */
 		mask >>= 1;
@@ -850,29 +832,29 @@
 
 	/* low MDC */
 	miir &= ~MASK_MIIR_MII_MDC;
-	writel(miir, miiport);
+	iowrite32(miir, miiport);
 }
 
 
 static int netdev_open(struct net_device *dev)
 {
-	struct netdev_private *np = dev->priv;
-	long ioaddr = dev->base_addr;
+	struct netdev_private *np = netdev_priv(dev);
+	void __iomem *ioaddr = np->mem;
 	int i;
 
-	writel(0x00000001, ioaddr + BCR);	/* Reset */
+	iowrite32(0x00000001, ioaddr + BCR);	/* Reset */
 
 	if (request_irq(dev->irq, &intr_handler, SA_SHIRQ, dev->name, dev))
 		return -EAGAIN;
 
 	for (i = 0; i < 3; i++)
-		writew(((unsigned short*)dev->dev_addr)[i],
+		iowrite16(((unsigned short*)dev->dev_addr)[i],
 				ioaddr + PAR0 + i*2);
 
 	init_ring(dev);
 
-	writel(np->rx_ring_dma, ioaddr + RXLBA);
-	writel(np->tx_ring_dma, ioaddr + TXLBA);
+	iowrite32(np->rx_ring_dma, ioaddr + RXLBA);
+	iowrite32(np->tx_ring_dma, ioaddr + TXLBA);
 
 	/* Initialize other registers. */
 	/* Configure the PCI bus bursts and FIFO thresholds.
@@ -933,12 +915,12 @@
 		np->crvalue |= CR_W_ENH;	/* set enhanced bit */
 		np->imrvalue |= ETI;
 	}
-	writel(np->bcrvalue, ioaddr + BCR);
+	iowrite32(np->bcrvalue, ioaddr + BCR);
 
 	if (dev->if_port == 0)
 		dev->if_port = np->default_port;
 
-	writel(0, ioaddr + RXPDR);
+	iowrite32(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 */
@@ -951,8 +933,8 @@
 	netif_start_queue(dev);
 
 	/* Clear and Enable interrupts by setting the interrupt mask. */
-	writel(FBE | TUNF | CNTOVF | RBU | TI | RI, ioaddr + ISR);
-	writel(np->imrvalue, ioaddr + IMR);
+	iowrite32(FBE | TUNF | CNTOVF | RBU | TI | RI, ioaddr + ISR);
+	iowrite32(np->imrvalue, ioaddr + IMR);
 
 	if (debug)
 		printk(KERN_DEBUG "%s: Done netdev_open().\n", dev->name);
@@ -980,14 +962,14 @@
 /* input   : dev... pointer to the adapter block.                            */
 /* output  : none.                                                           */
 {
-	struct netdev_private *np = dev->priv;
+	struct netdev_private *np = netdev_priv(dev);
 	unsigned int i, DelayTime = 0x1000;
 
 	np->linkok = 0;
 
 	if (np->PHYType == MysonPHY) {
 		for (i = 0; i < DelayTime; ++i) {
-			if (readl(dev->base_addr + BMCRSR) & LinkIsUp2) {
+			if (ioread32(np->mem + BMCRSR) & LinkIsUp2) {
 				np->linkok = 1;
 				return;
 			}
@@ -1007,14 +989,14 @@
 
 static void getlinktype(struct net_device *dev)
 {
-	struct netdev_private *np = dev->priv;
+	struct netdev_private *np = netdev_priv(dev);
 
 	if (np->PHYType == MysonPHY) {	/* 3-in-1 case */
-		if (readl(dev->base_addr + TCRRCR) & CR_R_FD)
+		if (ioread32(np->mem + TCRRCR) & CR_R_FD)
 			np->duplexmode = 2;	/* full duplex */
 		else
 			np->duplexmode = 1;	/* half duplex */
-		if (readl(dev->base_addr + TCRRCR) & CR_R_PS10)
+		if (ioread32(np->mem + TCRRCR) & CR_R_PS10)
 			np->line_speed = 1;	/* 10M */
 		else
 			np->line_speed = 2;	/* 100M */
@@ -1110,7 +1092,7 @@
 /* Take lock before calling this */
 static void allocate_rx_buffers(struct net_device *dev)
 {
-	struct netdev_private *np = dev->priv;
+	struct netdev_private *np = netdev_priv(dev);
 
 	/*  allocate skb for rx buffers */
 	while (np->really_rx_count != RX_RING_SIZE) {
@@ -1136,16 +1118,16 @@
 static void netdev_timer(unsigned long data)
 {
 	struct net_device *dev = (struct net_device *) data;
-	struct netdev_private *np = dev->priv;
-	long ioaddr = dev->base_addr;
+	struct netdev_private *np = netdev_priv(dev);
+	void __iomem *ioaddr = np->mem;
 	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));
+		       "config %8.8x.\n", dev->name, ioread32(ioaddr + ISR),
+		       ioread32(ioaddr + TCRRCR));
 
 	spin_lock_irqsave(&np->lock, flags);
 
@@ -1155,7 +1137,7 @@
 			getlinktype(dev);
 			if (np->crvalue != old_crvalue) {
 				stop_nic_rxtx(ioaddr, np->crvalue);
-				writel(np->crvalue, ioaddr + TCRRCR);
+				iowrite32(np->crvalue, ioaddr + TCRRCR);
 			}
 		}
 	}
@@ -1173,22 +1155,23 @@
 /* Reset chip and disable rx, tx and interrupts */
 static void reset_and_disable_rxtx(struct net_device *dev)
 {
-	long ioaddr = dev->base_addr;
+	struct netdev_private *np = netdev_priv(dev);
+	void __iomem *ioaddr = np->mem;
 	int delay=51;
 
 	/* Reset the chip's Tx and Rx processes. */
 	stop_nic_rxtx(ioaddr, 0);
 
 	/* Disable interrupts by clearing the interrupt mask. */
-	writel(0, ioaddr + IMR);
+	iowrite32(0, ioaddr + IMR);
 
 	/* Reset the chip to erase previous misconfiguration. */
-	writel(0x00000001, ioaddr + BCR);
+	iowrite32(0x00000001, ioaddr + BCR);
 
 	/* Ueimor: wait for 50 PCI cycles (and flush posted writes btw). 
 	   We surely wait too long (address+data phase). Who cares? */
 	while (--delay) {
-		readl(ioaddr + BCR);
+		ioread32(ioaddr + BCR);
 		rmb();
 	}
 }
@@ -1198,33 +1181,33 @@
 /* Restore chip after reset */
 static void enable_rxtx(struct net_device *dev)
 {
-	struct netdev_private *np = dev->priv;
-	long ioaddr = dev->base_addr;
+	struct netdev_private *np = netdev_priv(dev);
+	void __iomem *ioaddr = np->mem;
 
 	reset_rx_descriptors(dev);
 
-	writel(np->tx_ring_dma + ((char*)np->cur_tx - (char*)np->tx_ring),
+	iowrite32(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),
+	iowrite32(np->rx_ring_dma + ((char*)np->cur_rx - (char*)np->rx_ring),
 		ioaddr + RXLBA);
 
-	writel(np->bcrvalue, ioaddr + BCR);
+	iowrite32(np->bcrvalue, ioaddr + BCR);
 
-	writel(0, ioaddr + RXPDR);
+	iowrite32(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);
+	iowrite32(FBE | TUNF | CNTOVF | RBU | TI | RI, ioaddr + ISR);
+	iowrite32(np->imrvalue, ioaddr + IMR);
 
-	writel(0, ioaddr + TXPDR);
+	iowrite32(0, ioaddr + TXPDR);
 }
 
 
 static void reset_timer(unsigned long data)
 {
 	struct net_device *dev = (struct net_device *) data;
-	struct netdev_private *np = dev->priv;
+	struct netdev_private *np = netdev_priv(dev);
 	unsigned long flags;
 
 	printk(KERN_WARNING "%s: resetting tx and rx machinery\n", dev->name);
@@ -1247,13 +1230,13 @@
 
 static void tx_timeout(struct net_device *dev)
 {
-	struct netdev_private *np = dev->priv;
-	long ioaddr = dev->base_addr;
+	struct netdev_private *np = netdev_priv(dev);
+	void __iomem *ioaddr = np->mem;
 	unsigned long flags;
 	int i;
 
 	printk(KERN_WARNING "%s: Transmit timed out, status %8.8x,"
-	       " resetting...\n", dev->name, readl(ioaddr + ISR));
+	       " resetting...\n", dev->name, ioread32(ioaddr + ISR));
 
 	{
 		printk(KERN_DEBUG "  Rx ring %p: ", np->rx_ring);
@@ -1282,7 +1265,7 @@
 /* Initialize the Rx and Tx rings, along with various 'dev' bits. */
 static void init_ring(struct net_device *dev)
 {
-	struct netdev_private *np = dev->priv;
+	struct netdev_private *np = netdev_priv(dev);
 	int i;
 
 	/* initialize rx variables */
@@ -1346,7 +1329,7 @@
 
 static int start_tx(struct sk_buff *skb, struct net_device *dev)
 {
-	struct netdev_private *np = dev->priv;
+	struct netdev_private *np = netdev_priv(dev);
 	unsigned long flags;
 
 	spin_lock_irqsave(&np->lock, flags);
@@ -1413,7 +1396,7 @@
 	if (np->free_tx_count < 2)
 		netif_stop_queue(dev);
 	++np->really_tx_count;
-	writel(0, dev->base_addr + TXPDR);
+	iowrite32(0, np->mem + TXPDR);
 	dev->trans_start = jiffies;
 
 	spin_unlock_irqrestore(&np->lock, flags);
@@ -1425,7 +1408,7 @@
 /* Chip probably hosed tx ring. Clean up. */
 static void reset_tx_descriptors(struct net_device *dev)
 {
-	struct netdev_private *np = dev->priv;
+	struct netdev_private *np = netdev_priv(dev);
 	struct fealnx_desc *cur;
 	int i;
 
@@ -1460,7 +1443,7 @@
 /* Take lock and stop rx before calling this */
 static void reset_rx_descriptors(struct net_device *dev)
 {
-	struct netdev_private *np = dev->priv;
+	struct netdev_private *np = netdev_priv(dev);
 	struct fealnx_desc *cur = np->cur_rx;
 	int i;
 
@@ -1472,8 +1455,8 @@
 		cur = cur->next_desc_logical;
 	}
 
-	writel(np->rx_ring_dma + ((char*)np->cur_rx - (char*)np->rx_ring),
-		dev->base_addr + RXLBA);
+	iowrite32(np->rx_ring_dma + ((char*)np->cur_rx - (char*)np->rx_ring),
+		np->mem + RXLBA);
 }
 
 
@@ -1482,21 +1465,21 @@
 static irqreturn_t intr_handler(int irq, void *dev_instance, struct pt_regs *rgs)
 {
 	struct net_device *dev = (struct net_device *) dev_instance;
-	struct netdev_private *np = dev->priv;
-	long ioaddr = dev->base_addr;
+	struct netdev_private *np = netdev_priv(dev);
+	void __iomem *ioaddr = np->mem;
 	long boguscnt = max_interrupt_work;
 	unsigned int num_tx = 0;
 	int handled = 0;
 
 	spin_lock(&np->lock);
 
-	writel(0, ioaddr + IMR);
+	iowrite32(0, ioaddr + IMR);
 
 	do {
-		u32 intr_status = readl(ioaddr + ISR);
+		u32 intr_status = ioread32(ioaddr + ISR);
 
 		/* Acknowledge all of the current interrupt sources ASAP. */
-		writel(intr_status, ioaddr + ISR);
+		iowrite32(intr_status, ioaddr + ISR);
 
 		if (debug)
 			printk(KERN_DEBUG "%s: Interrupt, status %4.4x.\n", dev->name,
@@ -1517,15 +1500,15 @@
 //      };
 
 		if (intr_status & TUNF)
-			writel(0, ioaddr + TXPDR);
+			iowrite32(0, ioaddr + TXPDR);
 
 		if (intr_status & CNTOVF) {
 			/* missed pkts */
-			np->stats.rx_missed_errors += readl(ioaddr + TALLY) & 0x7fff;
+			np->stats.rx_missed_errors += ioread32(ioaddr + TALLY) & 0x7fff;
 
 			/* crc error */
 			np->stats.rx_crc_errors +=
-			    (readl(ioaddr + TALLY) & 0x7fff0000) >> 16;
+			    (ioread32(ioaddr + TALLY) & 0x7fff0000) >> 16;
 		}
 
 		if (intr_status & (RI | RBU)) {
@@ -1534,7 +1517,7 @@
 			else {
 				stop_nic_rx(ioaddr, np->crvalue);
 				reset_rx_descriptors(dev);
-				writel(np->crvalue, ioaddr + TCRRCR);
+				iowrite32(np->crvalue, ioaddr + TCRRCR);
 			}				
 		}
 
@@ -1605,7 +1588,7 @@
 		if (np->crvalue & CR_W_ENH) {
 			long data;
 
-			data = readl(ioaddr + TSR);
+			data = ioread32(ioaddr + TSR);
 			np->stats.tx_errors += (data & 0xff000000) >> 24;
 			np->stats.tx_aborted_errors += (data & 0xff000000) >> 24;
 			np->stats.tx_window_errors += (data & 0x00ff0000) >> 16;
@@ -1635,16 +1618,16 @@
 
 	/* read the tally counters */
 	/* missed pkts */
-	np->stats.rx_missed_errors += readl(ioaddr + TALLY) & 0x7fff;
+	np->stats.rx_missed_errors += ioread32(ioaddr + TALLY) & 0x7fff;
 
 	/* crc error */
-	np->stats.rx_crc_errors += (readl(ioaddr + TALLY) & 0x7fff0000) >> 16;
+	np->stats.rx_crc_errors += (ioread32(ioaddr + TALLY) & 0x7fff0000) >> 16;
 
 	if (debug)
 		printk(KERN_DEBUG "%s: exiting interrupt, status=%#4.4x.\n",
-		       dev->name, readl(ioaddr + ISR));
+		       dev->name, ioread32(ioaddr + ISR));
 
-	writel(np->imrvalue, ioaddr + IMR);
+	iowrite32(np->imrvalue, ioaddr + IMR);
 
 	spin_unlock(&np->lock);
 
@@ -1656,8 +1639,8 @@
    for clarity and better register allocation. */
 static int netdev_rx(struct net_device *dev)
 {
-	struct netdev_private *np = dev->priv;
-	long ioaddr = dev->base_addr;
+	struct netdev_private *np = netdev_priv(dev);
+	void __iomem *ioaddr = np->mem;
 
 	/* If EOP is set on the next entry, it's a new packet. Send it up. */
 	while (!(np->cur_rx->status & RXOWN) && np->cur_rx->skbuff) {
@@ -1725,7 +1708,7 @@
 				} else {        /* rx error, need to reset this chip */
 					stop_nic_rx(ioaddr, np->crvalue);
 					reset_rx_descriptors(dev);
-					writel(np->crvalue, ioaddr + TCRRCR);
+					iowrite32(np->crvalue, ioaddr + TCRRCR);
 				}
 				break;	/* exit the while loop */
 			}
@@ -1793,13 +1776,13 @@
 
 static struct net_device_stats *get_stats(struct net_device *dev)
 {
-	long ioaddr = dev->base_addr;
-	struct netdev_private *np = dev->priv;
+	struct netdev_private *np = netdev_priv(dev);
+	void __iomem *ioaddr = np->mem;
 
 	/* The chip only need report frame silently dropped. */
 	if (netif_running(dev)) {
-		np->stats.rx_missed_errors += readl(ioaddr + TALLY) & 0x7fff;
-		np->stats.rx_crc_errors += (readl(ioaddr + TALLY) & 0x7fff0000) >> 16;
+		np->stats.rx_missed_errors += ioread32(ioaddr + TALLY) & 0x7fff;
+		np->stats.rx_crc_errors += (ioread32(ioaddr + TALLY) & 0x7fff0000) >> 16;
 	}
 
 	return &np->stats;
@@ -1809,7 +1792,7 @@
 /* for dev->set_multicast_list */
 static void set_rx_mode(struct net_device *dev)
 {
-	spinlock_t *lp = &((struct netdev_private *)dev->priv)->lock;
+	spinlock_t *lp = &((struct netdev_private *)netdev_priv(dev))->lock;
 	unsigned long flags;
 	spin_lock_irqsave(lp, flags);
 	__set_rx_mode(dev);
@@ -1820,8 +1803,8 @@
 /* Take lock before calling */
 static void __set_rx_mode(struct net_device *dev)
 {
-	struct netdev_private *np = dev->priv;
-	long ioaddr = dev->base_addr;
+	struct netdev_private *np = netdev_priv(dev);
+	void __iomem *ioaddr = np->mem;
 	u32 mc_filter[2];	/* Multicast hash filter */
 	u32 rx_mode;
 
@@ -1851,16 +1834,16 @@
 
 	stop_nic_rxtx(ioaddr, np->crvalue);
 
-	writel(mc_filter[0], ioaddr + MAR0);
-	writel(mc_filter[1], ioaddr + MAR1);
+	iowrite32(mc_filter[0], ioaddr + MAR0);
+	iowrite32(mc_filter[1], ioaddr + MAR1);
 	np->crvalue &= ~CR_W_RXMODEMASK;
 	np->crvalue |= rx_mode;
-	writel(np->crvalue, ioaddr + TCRRCR);
+	iowrite32(np->crvalue, ioaddr + TCRRCR);
 }
 
 static void netdev_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
 {
-	struct netdev_private *np = dev->priv;
+	struct netdev_private *np = netdev_priv(dev);
 
 	strcpy(info->driver, DRV_NAME);
 	strcpy(info->version, DRV_VERSION);
@@ -1869,7 +1852,7 @@
 
 static int netdev_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
 {
-	struct netdev_private *np = dev->priv;
+	struct netdev_private *np = netdev_priv(dev);
 	int rc;
 
 	spin_lock_irq(&np->lock);
@@ -1881,7 +1864,7 @@
 
 static int netdev_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
 {
-	struct netdev_private *np = dev->priv;
+	struct netdev_private *np = netdev_priv(dev);
 	int rc;
 
 	spin_lock_irq(&np->lock);
@@ -1893,13 +1876,13 @@
 
 static int netdev_nway_reset(struct net_device *dev)
 {
-	struct netdev_private *np = dev->priv;
+	struct netdev_private *np = netdev_priv(dev);
 	return mii_nway_restart(&np->mii);
 }
 
 static u32 netdev_get_link(struct net_device *dev)
 {
-	struct netdev_private *np = dev->priv;
+	struct netdev_private *np = netdev_priv(dev);
 	return mii_link_ok(&np->mii);
 }
 
@@ -1927,7 +1910,7 @@
 
 static int mii_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 {
-	struct netdev_private *np = dev->priv;
+	struct netdev_private *np = netdev_priv(dev);
 	int rc;
 
 	if (!netif_running(dev))
@@ -1943,14 +1926,14 @@
 
 static int netdev_close(struct net_device *dev)
 {
-	long ioaddr = dev->base_addr;
-	struct netdev_private *np = dev->priv;
+	struct netdev_private *np = netdev_priv(dev);
+	void __iomem *ioaddr = np->mem;
 	int i;
 
 	netif_stop_queue(dev);
 
 	/* Disable interrupts by clearing the interrupt mask. */
-	writel(0x0000, ioaddr + IMR);
+	iowrite32(0x0000, ioaddr + IMR);
 
 	/* Stop the chip's Tx and Rx processes. */
 	stop_nic_rxtx(ioaddr, 0);
diff -Nru a/drivers/net/gianfar.c b/drivers/net/gianfar.c
--- a/drivers/net/gianfar.c	2005-03-11 12:51:40 -08:00
+++ b/drivers/net/gianfar.c	2005-03-11 12:51:40 -08:00
@@ -377,6 +377,8 @@
 			ADVERTISED_1000baseT_Full);
 	mii_info->autoneg = 1;
 
+	spin_lock_init(&mii_info->mdio_lock);
+
 	mii_info->mii_id = priv->einfo->phyid;
 
 	mii_info->dev = dev;
diff -Nru a/drivers/net/hamradio/6pack.c b/drivers/net/hamradio/6pack.c
--- a/drivers/net/hamradio/6pack.c	2005-03-11 12:51:41 -08:00
+++ b/drivers/net/hamradio/6pack.c	2005-03-11 12:51:41 -08:00
@@ -756,12 +756,12 @@
 
 	switch(cmd) {
 	case SIOCGIFNAME:
-		err = copy_to_user((void *) arg, dev->name,
+		err = copy_to_user((void __user *) arg, dev->name,
 		                   strlen(dev->name) + 1) ? -EFAULT : 0;
 		break;
 
 	case SIOCGIFENCAP:
-		err = put_user(0, (int __user *)arg);
+		err = put_user(0, (int __user *) arg);
 		break;
 
 	case SIOCSIFENCAP:
diff -Nru a/drivers/net/hamradio/baycom_epp.c b/drivers/net/hamradio/baycom_epp.c
--- a/drivers/net/hamradio/baycom_epp.c	2005-03-11 12:51:52 -08:00
+++ b/drivers/net/hamradio/baycom_epp.c	2005-03-11 12:51:52 -08:00
@@ -68,25 +68,7 @@
 /* --------------------------------------------------------------------- */
 
 static const char paranoia_str[] = KERN_ERR 
-"baycom_epp: bad magic number for hdlcdrv_state struct in routine %s\n";
-
-#define baycom_paranoia_check(dev,routine,retval)                                              \
-({                                                                                             \
-	if (!dev || !dev->priv || ((struct baycom_state *)dev->priv)->magic != BAYCOM_MAGIC) { \
-		printk(paranoia_str, routine);                                                 \
-		return retval;                                                                 \
-	}                                                                                      \
-})
-
-#define baycom_paranoia_check_void(dev,routine)                                                \
-({                                                                                             \
-	if (!dev || !dev->priv || ((struct baycom_state *)dev->priv)->magic != BAYCOM_MAGIC) { \
-		printk(paranoia_str, routine);                                                 \
-		return;                                                                        \
-	}                                                                                      \
-})
-
-/* --------------------------------------------------------------------- */
+	"baycom_epp: bad magic number for hdlcdrv_state struct in routine %s\n";
 
 static const char bc_drvname[] = "baycom_epp";
 static const char bc_drvinfo[] = KERN_INFO "baycom_epp: (C) 1998-2000 Thomas Sailer, HB9JNX/AE4WA\n"
@@ -747,7 +729,6 @@
 	unsigned int time1 = 0, time2 = 0, time3 = 0;
 	int cnt, cnt2;
 	
-	baycom_paranoia_check_void(dev, "epp_bh");
 	bc = netdev_priv(dev);
 	if (!bc->work_running)
 		return;
@@ -863,10 +844,8 @@
 
 static int baycom_send_packet(struct sk_buff *skb, struct net_device *dev)
 {
-	struct baycom_state *bc;
+	struct baycom_state *bc = netdev_priv(dev);
 
-	baycom_paranoia_check(dev, "baycom_send_packet", 0);
-	bc = netdev_priv(dev);
 	if (skb->data[0] != 0) {
 		do_kiss_params(bc, skb->data, skb->len);
 		dev_kfree_skb(skb);
@@ -899,10 +878,8 @@
 
 static struct net_device_stats *baycom_get_stats(struct net_device *dev)
 {
-	struct baycom_state *bc;
+	struct baycom_state *bc = netdev_priv(dev);
 
-	baycom_paranoia_check(dev, "baycom_get_stats", NULL);
-	bc = netdev_priv(dev);
 	/* 
 	 * Get the current statistics.  This may be called with the
 	 * card open or closed. 
@@ -915,10 +892,8 @@
 static void epp_wakeup(void *handle)
 {
         struct net_device *dev = (struct net_device *)handle;
-        struct baycom_state *bc;
+        struct baycom_state *bc = netdev_priv(dev);
 
-	baycom_paranoia_check_void(dev, "epp_wakeup");
-        bc = netdev_priv(dev);
         printk(KERN_DEBUG "baycom_epp: %s: why am I being woken up?\n", dev->name);
         if (!parport_claim(bc->pdev))
                 printk(KERN_DEBUG "baycom_epp: %s: I'm broken.\n", dev->name);
@@ -937,16 +912,13 @@
 
 static int epp_open(struct net_device *dev)
 {
-	struct baycom_state *bc;
-        struct parport *pp;
+	struct baycom_state *bc = netdev_priv(dev);
+        struct parport *pp = parport_find_base(dev->base_addr);
 	unsigned int i, j;
 	unsigned char tmp[128];
 	unsigned char stat;
 	unsigned long tstart;
 	
-	baycom_paranoia_check(dev, "epp_open", -ENXIO);
-	bc = netdev_priv(dev);
-        pp = parport_find_base(dev->base_addr);
         if (!pp) {
                 printk(KERN_ERR "%s: parport at 0x%lx unknown\n", bc_drvname, dev->base_addr);
                 return -ENXIO;
@@ -1055,13 +1027,10 @@
 
 static int epp_close(struct net_device *dev)
 {
-	struct baycom_state *bc;
-	struct parport *pp;
+	struct baycom_state *bc = netdev_priv(dev);
+	struct parport *pp = bc->pdev->port;
 	unsigned char tmp[1];
 
-	baycom_paranoia_check(dev, "epp_close", -EINVAL);
-	bc = netdev_priv(dev);
-	pp = bc->pdev->port;
 	bc->work_running = 0;
 	flush_scheduled_work();
 	bc->stat = EPP_DCDBIT;
@@ -1117,11 +1086,9 @@
 
 static int baycom_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 {
-	struct baycom_state *bc;
+	struct baycom_state *bc = netdev_priv(dev);
 	struct hdlcdrv_ioctl hi;
 
-	baycom_paranoia_check(dev, "baycom_ioctl", -EINVAL);
-	bc = netdev_priv(dev);
 	if (cmd != SIOCDEVPRIVATE)
 		return -ENOIOCTLCMD;
 
@@ -1354,7 +1321,7 @@
 			free_netdev(dev);
 			break;
 		}
-		if (set_hw && baycom_setmode(dev->priv, mode[i]))
+		if (set_hw && baycom_setmode(netdev_priv(dev), mode[i]))
 			set_hw = 0;
 		baycom_device[i] = dev;
 		found++;
diff -Nru a/drivers/net/hamradio/baycom_par.c b/drivers/net/hamradio/baycom_par.c
--- a/drivers/net/hamradio/baycom_par.c	2005-03-11 12:51:52 -08:00
+++ b/drivers/net/hamradio/baycom_par.c	2005-03-11 12:51:52 -08:00
@@ -85,6 +85,7 @@
 #include <linux/parport.h>
 #include <linux/bitops.h>
 
+#include <asm/bug.h>
 #include <asm/system.h>
 #include <asm/uaccess.h>
 
@@ -415,12 +416,11 @@
 	struct baycom_state *bc;
 	struct baycom_ioctl bi;
 
-	if (!dev || !dev->priv ||
-	    ((struct baycom_state *)dev->priv)->hdrv.magic != HDLCDRV_MAGIC) {
-		printk(KERN_ERR "bc_ioctl: invalid device struct\n");
+	if (!dev)
 		return -EINVAL;
-	}
+
 	bc = netdev_priv(dev);
+	BUG_ON(bc->hdrv.magic != HDLCDRV_MAGIC);
 
 	if (cmd != SIOCDEVPRIVATE)
 		return -ENOIOCTLCMD;
diff -Nru a/drivers/net/hamradio/baycom_ser_fdx.c b/drivers/net/hamradio/baycom_ser_fdx.c
--- a/drivers/net/hamradio/baycom_ser_fdx.c	2005-03-11 12:51:47 -08:00
+++ b/drivers/net/hamradio/baycom_ser_fdx.c	2005-03-11 12:51:47 -08:00
@@ -530,12 +530,11 @@
 	struct baycom_state *bc;
 	struct baycom_ioctl bi;
 
-	if (!dev || !dev->priv ||
-	    ((struct baycom_state *)dev->priv)->hdrv.magic != HDLCDRV_MAGIC) {
-		printk(KERN_ERR "bc_ioctl: invalid device struct\n");
+	if (!dev)
 		return -EINVAL;
-	}
+
 	bc = netdev_priv(dev);
+	BUG_ON(bc->hdrv.magic != HDLCDRV_MAGIC);
 
 	if (cmd != SIOCDEVPRIVATE)
 		return -ENOIOCTLCMD;
diff -Nru a/drivers/net/hamradio/baycom_ser_hdx.c b/drivers/net/hamradio/baycom_ser_hdx.c
--- a/drivers/net/hamradio/baycom_ser_hdx.c	2005-03-11 12:51:41 -08:00
+++ b/drivers/net/hamradio/baycom_ser_hdx.c	2005-03-11 12:51:41 -08:00
@@ -570,12 +570,11 @@
 	struct baycom_state *bc;
 	struct baycom_ioctl bi;
 
-	if (!dev || !dev->priv ||
-	    ((struct baycom_state *)dev->priv)->hdrv.magic != HDLCDRV_MAGIC) {
-		printk(KERN_ERR "bc_ioctl: invalid device struct\n");
+	if (!dev)
 		return -EINVAL;
-	}
+
 	bc = netdev_priv(dev);
+	BUG_ON(bc->hdrv.magic != HDLCDRV_MAGIC);
 
 	if (cmd != SIOCDEVPRIVATE)
 		return -ENOIOCTLCMD;
diff -Nru a/drivers/net/hamradio/bpqether.c b/drivers/net/hamradio/bpqether.c
--- a/drivers/net/hamradio/bpqether.c	2005-03-11 12:51:43 -08:00
+++ b/drivers/net/hamradio/bpqether.c	2005-03-11 12:51:43 -08:00
@@ -112,8 +112,6 @@
 };
 
 
-#define MAXBPQDEV 100
-
 struct bpqdev {
 	struct list_head bpq_list;	/* list of bpq devices chain */
 	struct net_device *ethdev;	/* link to ethernet device */
@@ -134,7 +132,7 @@
  */
 static inline struct net_device *bpq_get_ether_dev(struct net_device *dev)
 {
-	struct bpqdev *bpq = (struct bpqdev *) dev->priv;
+	struct bpqdev *bpq = netdev_priv(dev);
 
 	return bpq ? bpq->ethdev : NULL;
 }
@@ -191,7 +189,7 @@
 	 * we check the source address of the sender.
 	 */
 
-	bpq = (struct bpqdev *)dev->priv;
+	bpq = netdev_priv(dev);
 
 	eth = eth_hdr(skb);
 
@@ -281,7 +279,7 @@
 	*ptr++ = (size + 5) % 256;
 	*ptr++ = (size + 5) / 256;
 
-	bpq = (struct bpqdev *)dev->priv;
+	bpq = netdev_priv(dev);
 
 	if ((dev = bpq_get_ether_dev(dev)) == NULL) {
 		bpq->stats.tx_dropped++;
@@ -305,7 +303,7 @@
  */
 static struct net_device_stats *bpq_get_stats(struct net_device *dev)
 {
-	struct bpqdev *bpq = (struct bpqdev *) dev->priv;
+	struct bpqdev *bpq = netdev_priv(dev);
 
 	return &bpq->stats;
 }
@@ -332,15 +330,12 @@
 static int bpq_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 {
 	struct bpq_ethaddr __user *ethaddr = ifr->ifr_data;
-	struct bpqdev *bpq = dev->priv;
+	struct bpqdev *bpq = netdev_priv(dev);
 	struct bpq_req req;
 
 	if (!capable(CAP_NET_ADMIN))
 		return -EPERM;
 
-	if (bpq == NULL)		/* woops! */
-		return -ENODEV;
-
 	switch (cmd) {
 		case SIOCSBPQETHOPT:
 			if (copy_from_user(&req, ifr->ifr_data, sizeof(struct bpq_req)))
@@ -525,7 +520,7 @@
 		return -ENOMEM;
 
 		
-	bpq = ndev->priv;
+	bpq = netdev_priv(ndev);
 	dev_hold(edev);
 	bpq->ethdev = edev;
 	bpq->axdev = ndev;
@@ -554,7 +549,7 @@
 
 static void bpq_free_device(struct net_device *ndev)
 {
-	struct bpqdev *bpq = ndev->priv;
+	struct bpqdev *bpq = netdev_priv(ndev);
 
 	dev_put(bpq->ethdev);
 	list_del_rcu(&bpq->bpq_list);
diff -Nru a/drivers/net/hamradio/dmascc.c b/drivers/net/hamradio/dmascc.c
--- a/drivers/net/hamradio/dmascc.c	2005-03-11 12:51:42 -08:00
+++ b/drivers/net/hamradio/dmascc.c	2005-03-11 12:51:42 -08:00
@@ -1,6 +1,4 @@
 /*
- * $Id: dmascc.c,v 1.27 2000/06/01 14:46:23 oe1kib Exp $
- *
  * Driver for high-speed SCC boards (those with DMA support)
  * Copyright (C) 1997-2000 Klaus Kudielka
  *
@@ -19,7 +17,6 @@
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
  */
 
 
@@ -49,9 +46,9 @@
 
 /* Number of buffers per channel */
 
-#define NUM_TX_BUF      2          /* NUM_TX_BUF >= 1 (min. 2 recommended) */
-#define NUM_RX_BUF      6          /* NUM_RX_BUF >= 1 (min. 2 recommended) */
-#define BUF_SIZE        1576       /* BUF_SIZE >= mtu + hard_header_len */
+#define NUM_TX_BUF      2	/* NUM_TX_BUF >= 1 (min. 2 recommended) */
+#define NUM_RX_BUF      6	/* NUM_RX_BUF >= 1 (min. 2 recommended) */
+#define BUF_SIZE        1576	/* BUF_SIZE >= mtu + hard_header_len */
 
 
 /* Cards supported */
@@ -67,7 +64,7 @@
 
 #define HARDWARE        { HW_PI, HW_PI2, HW_TWIN, HW_S5 }
 
-#define TMR_0_HZ        25600      /* Frequency of timer 0 */
+#define TMR_0_HZ        25600	/* Frequency of timer 0 */
 
 #define TYPE_PI         0
 #define TYPE_PI2        1
@@ -164,69 +161,69 @@
 /* Data types */
 
 struct scc_param {
-  int pclk_hz;    /* frequency of BRG input (don't change) */
-  int brg_tc;     /* BRG terminal count; BRG disabled if < 0 */
-  int nrzi;       /* 0 (nrz), 1 (nrzi) */
-  int clocks;     /* see dmascc_cfg documentation */
-  int txdelay;    /* [1/TMR_0_HZ] */
-  int txtimeout;  /* [1/HZ] */
-  int txtail;     /* [1/TMR_0_HZ] */
-  int waittime;   /* [1/TMR_0_HZ] */
-  int slottime;   /* [1/TMR_0_HZ] */
-  int persist;    /* 1 ... 256 */
-  int dma;        /* -1 (disable), 0, 1, 3 */
-  int txpause;    /* [1/TMR_0_HZ] */
-  int rtsoff;     /* [1/TMR_0_HZ] */
-  int dcdon;      /* [1/TMR_0_HZ] */
-  int dcdoff;     /* [1/TMR_0_HZ] */
+	int pclk_hz;		/* frequency of BRG input (don't change) */
+	int brg_tc;		/* BRG terminal count; BRG disabled if < 0 */
+	int nrzi;		/* 0 (nrz), 1 (nrzi) */
+	int clocks;		/* see dmascc_cfg documentation */
+	int txdelay;		/* [1/TMR_0_HZ] */
+	int txtimeout;		/* [1/HZ] */
+	int txtail;		/* [1/TMR_0_HZ] */
+	int waittime;		/* [1/TMR_0_HZ] */
+	int slottime;		/* [1/TMR_0_HZ] */
+	int persist;		/* 1 ... 256 */
+	int dma;		/* -1 (disable), 0, 1, 3 */
+	int txpause;		/* [1/TMR_0_HZ] */
+	int rtsoff;		/* [1/TMR_0_HZ] */
+	int dcdon;		/* [1/TMR_0_HZ] */
+	int dcdoff;		/* [1/TMR_0_HZ] */
 };
 
 struct scc_hardware {
-  char *name;
-  int io_region;
-  int io_delta;
-  int io_size;
-  int num_devs;
-  int scc_offset;
-  int tmr_offset;
-  int tmr_hz;
-  int pclk_hz;
+	char *name;
+	int io_region;
+	int io_delta;
+	int io_size;
+	int num_devs;
+	int scc_offset;
+	int tmr_offset;
+	int tmr_hz;
+	int pclk_hz;
 };
 
 struct scc_priv {
-  int type;
-  int chip;
-  struct net_device *dev;
-  struct scc_info *info;
-  struct net_device_stats stats;
-  int channel;
-  int card_base, scc_cmd, scc_data;
-  int tmr_cnt, tmr_ctrl, tmr_mode;
-  struct scc_param param;
-  char rx_buf[NUM_RX_BUF][BUF_SIZE];
-  int rx_len[NUM_RX_BUF];
-  int rx_ptr;
-  struct work_struct rx_work;
-  int rx_head, rx_tail, rx_count;
-  int rx_over;
-  char tx_buf[NUM_TX_BUF][BUF_SIZE];
-  int tx_len[NUM_TX_BUF];
-  int tx_ptr;
-  int tx_head, tx_tail, tx_count;
-  int state;
-  unsigned long tx_start;
-  int rr0;
-  spinlock_t *register_lock;	/* Per scc_info */
-  spinlock_t ring_lock;
+	int type;
+	int chip;
+	struct net_device *dev;
+	struct scc_info *info;
+	struct net_device_stats stats;
+	int channel;
+	int card_base, scc_cmd, scc_data;
+	int tmr_cnt, tmr_ctrl, tmr_mode;
+	struct scc_param param;
+	char rx_buf[NUM_RX_BUF][BUF_SIZE];
+	int rx_len[NUM_RX_BUF];
+	int rx_ptr;
+	struct work_struct rx_work;
+	int rx_head, rx_tail, rx_count;
+	int rx_over;
+	char tx_buf[NUM_TX_BUF][BUF_SIZE];
+	int tx_len[NUM_TX_BUF];
+	int tx_ptr;
+	int tx_head, tx_tail, tx_count;
+	int state;
+	unsigned long tx_start;
+	int rr0;
+	spinlock_t *register_lock;	/* Per scc_info */
+	spinlock_t ring_lock;
 };
 
 struct scc_info {
-  int irq_used;
-  int twin_serial_cfg;
-  struct net_device *dev[2];
-  struct scc_priv priv[2];
-  struct scc_info *next;
-  spinlock_t register_lock;	/* Per device register lock */
+	int irq_used;
+	int twin_serial_cfg;
+	struct net_device *dev[2];
+	struct scc_priv priv[2];
+	struct scc_info *next;
+	spinlock_t register_lock;	/* Per device register lock */
 };
 
 
@@ -252,7 +249,7 @@
 static inline unsigned char random(void);
 
 static inline void z8530_isr(struct scc_info *info);
-static irqreturn_t scc_isr(int irq, void *dev_id, struct pt_regs * regs);
+static irqreturn_t scc_isr(int irq, void *dev_id, struct pt_regs *regs);
 static void rx_isr(struct scc_priv *priv);
 static void special_condition(struct scc_priv *priv, int rc);
 static void rx_bh(void *arg);
@@ -264,12 +261,15 @@
 /* Initialization variables */
 
 static int io[MAX_NUM_DEVS] __initdata = { 0, };
+
 /* Beware! hw[] is also used in cleanup_module(). */
 static struct scc_hardware hw[NUM_TYPES] __initdata_or_module = HARDWARE;
 static char ax25_broadcast[7] __initdata =
-  { 'Q'<<1, 'S'<<1, 'T'<<1, ' '<<1, ' '<<1, ' '<<1, '0'<<1 };
+    { 'Q' << 1, 'S' << 1, 'T' << 1, ' ' << 1, ' ' << 1, ' ' << 1,
+'0' << 1 };
 static char ax25_test[7] __initdata =
-  { 'L'<<1, 'I'<<1, 'N'<<1, 'U'<<1, 'X'<<1, ' '<<1, '1'<<1 };
+    { 'L' << 1, 'I' << 1, 'N' << 1, 'U' << 1, 'X' << 1, ' ' << 1,
+'1' << 1 };
 
 
 /* Global variables */
@@ -283,143 +283,164 @@
 MODULE_PARM(io, "1-" __MODULE_STRING(MAX_NUM_DEVS) "i");
 MODULE_LICENSE("GPL");
 
-static void __exit dmascc_exit(void) {
-  int i;
-  struct scc_info *info;
-
-  while (first) {
-    info = first;
-
-    /* Unregister devices */
-    for (i = 0; i < 2; i++)
-	unregister_netdev(info->dev[i]);
-
-    /* Reset board */
-    if (info->priv[0].type == TYPE_TWIN)
-      outb(0, info->dev[0]->base_addr + TWIN_SERIAL_CFG);
-    write_scc(&info->priv[0], R9, FHWRES);
-    release_region(info->dev[0]->base_addr,
-		   hw[info->priv[0].type].io_size);
-
-    for (i = 0; i < 2; i++)
-	free_netdev(info->dev[i]);
-
-    /* Free memory */
-    first = info->next;
-    kfree(info);
-  }
+static void __exit dmascc_exit(void)
+{
+	int i;
+	struct scc_info *info;
+
+	while (first) {
+		info = first;
+
+		/* Unregister devices */
+		for (i = 0; i < 2; i++)
+			unregister_netdev(info->dev[i]);
+
+		/* Reset board */
+		if (info->priv[0].type == TYPE_TWIN)
+			outb(0, info->dev[0]->base_addr + TWIN_SERIAL_CFG);
+		write_scc(&info->priv[0], R9, FHWRES);
+		release_region(info->dev[0]->base_addr,
+			       hw[info->priv[0].type].io_size);
+
+		for (i = 0; i < 2; i++)
+			free_netdev(info->dev[i]);
+
+		/* Free memory */
+		first = info->next;
+		kfree(info);
+	}
 }
 
 #ifndef MODULE
-void __init dmascc_setup(char *str, int *ints) {
-   int i;
+void __init dmascc_setup(char *str, int *ints)
+{
+	int i;
 
-   for (i = 0; i < MAX_NUM_DEVS && i < ints[0]; i++)
-      io[i] = ints[i+1];
+	for (i = 0; i < MAX_NUM_DEVS && i < ints[0]; i++)
+		io[i] = ints[i + 1];
 }
 #endif
 
-static int __init dmascc_init(void) {
-  int h, i, j, n;
-  int base[MAX_NUM_DEVS], tcmd[MAX_NUM_DEVS], t0[MAX_NUM_DEVS],
-    t1[MAX_NUM_DEVS];
-  unsigned t_val;
-  unsigned long time, start[MAX_NUM_DEVS], delay[MAX_NUM_DEVS],
-    counting[MAX_NUM_DEVS];
-
-  /* Initialize random number generator */
-  rand = jiffies;
-  /* Cards found = 0 */
-  n = 0;
-  /* Warning message */
-  if (!io[0]) printk(KERN_INFO "dmascc: autoprobing (dangerous)\n");
-
-  /* Run autodetection for each card type */
-  for (h = 0; h < NUM_TYPES; h++) {
-
-    if (io[0]) {
-      /* User-specified I/O address regions */
-      for (i = 0; i < hw[h].num_devs; i++) base[i] = 0;
-      for (i = 0; i < MAX_NUM_DEVS && io[i]; i++) {
-	j = (io[i] - hw[h].io_region) / hw[h].io_delta;
-	if (j >= 0 &&
-	    j < hw[h].num_devs && 
-	    hw[h].io_region + j * hw[h].io_delta == io[i]) {
-	  base[j] = io[i];
-	}
-      }
-    } else {
-      /* Default I/O address regions */
-      for (i = 0; i < hw[h].num_devs; i++) {
-	base[i] = hw[h].io_region + i * hw[h].io_delta;
-      }
-    }
-
-    /* Check valid I/O address regions */
-    for (i = 0; i < hw[h].num_devs; i++)
-      if (base[i]) {
-	if (!request_region(base[i], hw[h].io_size, "dmascc"))
-	  base[i] = 0;
-	else {
-	  tcmd[i] = base[i] + hw[h].tmr_offset + TMR_CTRL;
-	  t0[i]   = base[i] + hw[h].tmr_offset + TMR_CNT0;
-	  t1[i]   = base[i] + hw[h].tmr_offset + TMR_CNT1;
-	}
-      }
-
-    /* Start timers */
-    for (i = 0; i < hw[h].num_devs; i++)
-      if (base[i]) {
-	/* Timer 0: LSB+MSB, Mode 3, TMR_0_HZ */
-	outb(0x36, tcmd[i]);
-	outb((hw[h].tmr_hz/TMR_0_HZ) & 0xFF, t0[i]);
-	outb((hw[h].tmr_hz/TMR_0_HZ) >> 8, t0[i]);
-	/* Timer 1: LSB+MSB, Mode 0, HZ/10 */
-	outb(0x70, tcmd[i]);
-	outb((TMR_0_HZ/HZ*10) & 0xFF, t1[i]);
-	outb((TMR_0_HZ/HZ*10) >> 8, t1[i]);
-	start[i] = jiffies;
-	delay[i] = 0;
-	counting[i] = 1;
-	/* Timer 2: LSB+MSB, Mode 0 */
-	outb(0xb0, tcmd[i]);
-      }
-    time = jiffies;
-    /* Wait until counter registers are loaded */
-    udelay(2000000/TMR_0_HZ);
-
-    /* Timing loop */
-    while (jiffies - time < 13) {
-      for (i = 0; i < hw[h].num_devs; i++)
-	if (base[i] && counting[i]) {
-	  /* Read back Timer 1: latch; read LSB; read MSB */
-	  outb(0x40, tcmd[i]);
-	  t_val = inb(t1[i]) + (inb(t1[i]) << 8);
-	  /* Also check whether counter did wrap */
-	  if (t_val == 0 || t_val > TMR_0_HZ/HZ*10) counting[i] = 0;
-	  delay[i] = jiffies - start[i];
-	}
-    }
-
-    /* Evaluate measurements */
-    for (i = 0; i < hw[h].num_devs; i++)
-      if (base[i]) {
-	if ((delay[i] >= 9 && delay[i] <= 11)&& 
-	    /* Ok, we have found an adapter */
-	    (setup_adapter(base[i], h, n) == 0))
-	  n++;
-	else
-	  release_region(base[i], hw[h].io_size);
-      }
-
-  } /* NUM_TYPES */
+static int __init dmascc_init(void)
+{
+	int h, i, j, n;
+	int base[MAX_NUM_DEVS], tcmd[MAX_NUM_DEVS], t0[MAX_NUM_DEVS],
+	    t1[MAX_NUM_DEVS];
+	unsigned t_val;
+	unsigned long time, start[MAX_NUM_DEVS], delay[MAX_NUM_DEVS],
+	    counting[MAX_NUM_DEVS];
+
+	/* Initialize random number generator */
+	rand = jiffies;
+	/* Cards found = 0 */
+	n = 0;
+	/* Warning message */
+	if (!io[0])
+		printk(KERN_INFO "dmascc: autoprobing (dangerous)\n");
+
+	/* Run autodetection for each card type */
+	for (h = 0; h < NUM_TYPES; h++) {
+
+		if (io[0]) {
+			/* User-specified I/O address regions */
+			for (i = 0; i < hw[h].num_devs; i++)
+				base[i] = 0;
+			for (i = 0; i < MAX_NUM_DEVS && io[i]; i++) {
+				j = (io[i] -
+				     hw[h].io_region) / hw[h].io_delta;
+				if (j >= 0 && j < hw[h].num_devs
+				    && hw[h].io_region +
+				    j * hw[h].io_delta == io[i]) {
+					base[j] = io[i];
+				}
+			}
+		} else {
+			/* Default I/O address regions */
+			for (i = 0; i < hw[h].num_devs; i++) {
+				base[i] =
+				    hw[h].io_region + i * hw[h].io_delta;
+			}
+		}
 
-  /* If any adapter was successfully initialized, return ok */
-  if (n) return 0;
+		/* Check valid I/O address regions */
+		for (i = 0; i < hw[h].num_devs; i++)
+			if (base[i]) {
+				if (!request_region
+				    (base[i], hw[h].io_size, "dmascc"))
+					base[i] = 0;
+				else {
+					tcmd[i] =
+					    base[i] + hw[h].tmr_offset +
+					    TMR_CTRL;
+					t0[i] =
+					    base[i] + hw[h].tmr_offset +
+					    TMR_CNT0;
+					t1[i] =
+					    base[i] + hw[h].tmr_offset +
+					    TMR_CNT1;
+				}
+			}
+
+		/* Start timers */
+		for (i = 0; i < hw[h].num_devs; i++)
+			if (base[i]) {
+				/* Timer 0: LSB+MSB, Mode 3, TMR_0_HZ */
+				outb(0x36, tcmd[i]);
+				outb((hw[h].tmr_hz / TMR_0_HZ) & 0xFF,
+				     t0[i]);
+				outb((hw[h].tmr_hz / TMR_0_HZ) >> 8,
+				     t0[i]);
+				/* Timer 1: LSB+MSB, Mode 0, HZ/10 */
+				outb(0x70, tcmd[i]);
+				outb((TMR_0_HZ / HZ * 10) & 0xFF, t1[i]);
+				outb((TMR_0_HZ / HZ * 10) >> 8, t1[i]);
+				start[i] = jiffies;
+				delay[i] = 0;
+				counting[i] = 1;
+				/* Timer 2: LSB+MSB, Mode 0 */
+				outb(0xb0, tcmd[i]);
+			}
+		time = jiffies;
+		/* Wait until counter registers are loaded */
+		udelay(2000000 / TMR_0_HZ);
+
+		/* Timing loop */
+		while (jiffies - time < 13) {
+			for (i = 0; i < hw[h].num_devs; i++)
+				if (base[i] && counting[i]) {
+					/* Read back Timer 1: latch; read LSB; read MSB */
+					outb(0x40, tcmd[i]);
+					t_val =
+					    inb(t1[i]) + (inb(t1[i]) << 8);
+					/* Also check whether counter did wrap */
+					if (t_val == 0
+					    || t_val > TMR_0_HZ / HZ * 10)
+						counting[i] = 0;
+					delay[i] = jiffies - start[i];
+				}
+		}
 
-  /* If no adapter found, return error */
-  printk(KERN_INFO "dmascc: no adapters found\n");
-  return -EIO;
+		/* Evaluate measurements */
+		for (i = 0; i < hw[h].num_devs; i++)
+			if (base[i]) {
+				if ((delay[i] >= 9 && delay[i] <= 11) &&
+				    /* Ok, we have found an adapter */
+				    (setup_adapter(base[i], h, n) == 0))
+					n++;
+				else
+					release_region(base[i],
+						       hw[h].io_size);
+			}
+
+	}			/* NUM_TYPES */
+
+	/* If any adapter was successfully initialized, return ok */
+	if (n)
+		return 0;
+
+	/* If no adapter found, return error */
+	printk(KERN_INFO "dmascc: no adapters found\n");
+	return -EIO;
 }
 
 module_init(dmascc_init);
@@ -452,8 +473,8 @@
 	info = kmalloc(sizeof(struct scc_info), GFP_KERNEL | GFP_DMA);
 	if (!info) {
 		printk(KERN_ERR "dmascc: "
-			"could not allocate memory for %s at %#3x\n",
-			hw[type].name, card_base);
+		       "could not allocate memory for %s at %#3x\n",
+		       hw[type].name, card_base);
 		goto out;
 	}
 
@@ -463,16 +484,16 @@
 	info->dev[0] = alloc_netdev(0, "", dev_setup);
 	if (!info->dev[0]) {
 		printk(KERN_ERR "dmascc: "
-			"could not allocate memory for %s at %#3x\n",
-			hw[type].name, card_base);
+		       "could not allocate memory for %s at %#3x\n",
+		       hw[type].name, card_base);
 		goto out1;
 	}
 
 	info->dev[1] = alloc_netdev(0, "", dev_setup);
 	if (!info->dev[1]) {
 		printk(KERN_ERR "dmascc: "
-			"could not allocate memory for %s at %#3x\n",
-			hw[type].name, card_base);
+		       "could not allocate memory for %s at %#3x\n",
+		       hw[type].name, card_base);
 		goto out2;
 	}
 	spin_lock_init(&info->register_lock);
@@ -526,7 +547,8 @@
 	outb(0, tmr_base + TMR_CNT1);
 
 	/* Wait and detect IRQ */
-	time = jiffies; while (jiffies - time < 2 + HZ / TMR_0_HZ);
+	time = jiffies;
+	while (jiffies - time < 2 + HZ / TMR_0_HZ);
 	irq = probe_irq_off(irqs);
 
 	/* Clear pending interrupt, disable interrupts */
@@ -539,8 +561,9 @@
 	}
 
 	if (irq <= 0) {
-		printk(KERN_ERR "dmascc: could not find irq of %s at %#3x (irq=%d)\n",
-			hw[type].name, card_base, irq);
+		printk(KERN_ERR
+		       "dmascc: could not find irq of %s at %#3x (irq=%d)\n",
+		       hw[type].name, card_base, irq);
 		goto out3;
 	}
 
@@ -568,7 +591,7 @@
 		priv->param.dma = -1;
 		INIT_WORK(&priv->rx_work, rx_bh, priv);
 		dev->priv = priv;
-		sprintf(dev->name, "dmascc%i", 2*n+i);
+		sprintf(dev->name, "dmascc%i", 2 * n + i);
 		SET_MODULE_OWNER(dev);
 		dev->base_addr = card_base;
 		dev->irq = irq;
@@ -583,820 +606,888 @@
 	}
 	if (register_netdev(info->dev[0])) {
 		printk(KERN_ERR "dmascc: could not register %s\n",
-				info->dev[0]->name);
+		       info->dev[0]->name);
 		goto out3;
 	}
 	if (register_netdev(info->dev[1])) {
 		printk(KERN_ERR "dmascc: could not register %s\n",
-				info->dev[1]->name);
+		       info->dev[1]->name);
 		goto out4;
 	}
 
 
 	info->next = first;
 	first = info;
-	printk(KERN_INFO "dmascc: found %s (%s) at %#3x, irq %d\n", hw[type].name,
-	chipnames[chip], card_base, irq);
+	printk(KERN_INFO "dmascc: found %s (%s) at %#3x, irq %d\n",
+	       hw[type].name, chipnames[chip], card_base, irq);
 	return 0;
 
-out4:
+      out4:
 	unregister_netdev(info->dev[0]);
-out3:
+      out3:
 	if (info->priv[0].type == TYPE_TWIN)
 		outb(0, info->dev[0]->base_addr + TWIN_SERIAL_CFG);
 	write_scc(&info->priv[0], R9, FHWRES);
 	free_netdev(info->dev[1]);
-out2:
+      out2:
 	free_netdev(info->dev[0]);
-out1:
+      out1:
 	kfree(info);
-out:
+      out:
 	return -1;
 }
 
 
 /* Driver functions */
 
-static void write_scc(struct scc_priv *priv, int reg, int val) {
-  unsigned long flags;
-  switch (priv->type) {
-  case TYPE_S5:
-    if (reg) outb(reg, priv->scc_cmd);
-    outb(val, priv->scc_cmd);
-    return;
-  case TYPE_TWIN:
-    if (reg) outb_p(reg, priv->scc_cmd);
-    outb_p(val, priv->scc_cmd);
-    return;
-  default:
-    spin_lock_irqsave(priv->register_lock, flags);
-    outb_p(0, priv->card_base + PI_DREQ_MASK);
-    if (reg) outb_p(reg, priv->scc_cmd);
-    outb_p(val, priv->scc_cmd);
-    outb(1, priv->card_base + PI_DREQ_MASK);
-    spin_unlock_irqrestore(priv->register_lock, flags);
-    return;
-  }
-}
-
-
-static void write_scc_data(struct scc_priv *priv, int val, int fast) {
-  unsigned long flags;
-  switch (priv->type) {
-  case TYPE_S5:
-    outb(val, priv->scc_data);
-    return;
-  case TYPE_TWIN:
-    outb_p(val, priv->scc_data);
-    return;
-  default:
-    if (fast) outb_p(val, priv->scc_data);
-    else {
-      spin_lock_irqsave(priv->register_lock, flags);
-      outb_p(0, priv->card_base + PI_DREQ_MASK);
-      outb_p(val, priv->scc_data);
-      outb(1, priv->card_base + PI_DREQ_MASK);
-      spin_unlock_irqrestore(priv->register_lock, flags);
-    }
-    return;
-  }
-}
-
-
-static int read_scc(struct scc_priv *priv, int reg) {
-  int rc;
-  unsigned long flags;
-  switch (priv->type) {
-  case TYPE_S5:
-    if (reg) outb(reg, priv->scc_cmd);
-    return inb(priv->scc_cmd);
-  case TYPE_TWIN:
-    if (reg) outb_p(reg, priv->scc_cmd);
-    return inb_p(priv->scc_cmd);
-  default:
-    spin_lock_irqsave(priv->register_lock, flags);
-    outb_p(0, priv->card_base + PI_DREQ_MASK);
-    if (reg) outb_p(reg, priv->scc_cmd);
-    rc = inb_p(priv->scc_cmd);
-    outb(1, priv->card_base + PI_DREQ_MASK);
-    spin_unlock_irqrestore(priv->register_lock, flags);
-    return rc;
-  }
-}
-
-
-static int read_scc_data(struct scc_priv *priv) {
-  int rc;
-  unsigned long flags;
-  switch (priv->type) {
-  case TYPE_S5:
-    return inb(priv->scc_data);
-  case TYPE_TWIN:
-    return inb_p(priv->scc_data);
-  default:
-    spin_lock_irqsave(priv->register_lock, flags);
-    outb_p(0, priv->card_base + PI_DREQ_MASK);
-    rc = inb_p(priv->scc_data);
-    outb(1, priv->card_base + PI_DREQ_MASK);
-    spin_unlock_irqrestore(priv->register_lock, flags);
-    return rc;
-  }
-}
-
-
-static int scc_open(struct net_device *dev) {
-  struct scc_priv *priv = dev->priv;
-  struct scc_info *info = priv->info;
-  int card_base = priv->card_base;
-
-  /* Request IRQ if not already used by other channel */
-  if (!info->irq_used) {
-    if (request_irq(dev->irq, scc_isr, 0, "dmascc", info)) {
-      return -EAGAIN;
-    }
-  }
-  info->irq_used++;
-
-  /* Request DMA if required */
-  if (priv->param.dma >= 0) {
-    if (request_dma(priv->param.dma, "dmascc")) {
-      if (--info->irq_used == 0) free_irq(dev->irq, info);
-      return -EAGAIN;
-    } else {
-      unsigned long flags = claim_dma_lock();
-      clear_dma_ff(priv->param.dma);
-      release_dma_lock(flags);
-    }
-  }
-
-  /* Initialize local variables */
-  priv->rx_ptr = 0;
-  priv->rx_over = 0;
-  priv->rx_head = priv->rx_tail = priv->rx_count = 0;
-  priv->state = IDLE;
-  priv->tx_head = priv->tx_tail = priv->tx_count = 0;
-  priv->tx_ptr = 0;
-
-  /* Reset channel */
-  write_scc(priv, R9, (priv->channel ? CHRB : CHRA) | MIE | NV);
-  /* X1 clock, SDLC mode */
-  write_scc(priv, R4, SDLC | X1CLK);
-  /* DMA */
-  write_scc(priv, R1, EXT_INT_ENAB | WT_FN_RDYFN);
-  /* 8 bit RX char, RX disable */
-  write_scc(priv, R3, Rx8);
-  /* 8 bit TX char, TX disable */
-  write_scc(priv, R5, Tx8);
-  /* SDLC address field */
-  write_scc(priv, R6, 0);
-  /* SDLC flag */
-  write_scc(priv, R7, FLAG);
-  switch (priv->chip) {
-  case Z85C30:
-    /* Select WR7' */
-    write_scc(priv, R15, SHDLCE);
-    /* Auto EOM reset */
-    write_scc(priv, R7, AUTOEOM);
-    write_scc(priv, R15, 0);
-    break;
-  case Z85230:
-    /* Select WR7' */
-    write_scc(priv, R15, SHDLCE);
-    /* The following bits are set (see 2.5.2.1):
-       - Automatic EOM reset
-       - Interrupt request if RX FIFO is half full
-         This bit should be ignored in DMA mode (according to the
-         documentation), but actually isn't. The receiver doesn't work if
-         it is set. Thus, we have to clear it in DMA mode.
-       - Interrupt/DMA request if TX FIFO is completely empty
-         a) If set, the ESCC behaves as if it had no TX FIFO (Z85C30
-            compatibility).
-         b) If cleared, DMA requests may follow each other very quickly,
-            filling up the TX FIFO.
-            Advantage: TX works even in case of high bus latency.
-            Disadvantage: Edge-triggered DMA request circuitry may miss
-                          a request. No more data is delivered, resulting
-                          in a TX FIFO underrun.
-         Both PI2 and S5SCC/DMA seem to work fine with TXFIFOE cleared.
-         The PackeTwin doesn't. I don't know about the PI, but let's
-	 assume it behaves like the PI2.
-    */
-    if (priv->param.dma >= 0) {
-      if (priv->type == TYPE_TWIN) write_scc(priv, R7, AUTOEOM | TXFIFOE);
-      else write_scc(priv, R7, AUTOEOM);
-    } else {
-      write_scc(priv, R7, AUTOEOM | RXFIFOH);
-    }
-    write_scc(priv, R15, 0);
-    break;
-  }
-  /* Preset CRC, NRZ(I) encoding */
-  write_scc(priv, R10, CRCPS | (priv->param.nrzi ? NRZI : NRZ));
-
-  /* Configure baud rate generator */
-  if (priv->param.brg_tc >= 0) {
-    /* Program BR generator */
-    write_scc(priv, R12, priv->param.brg_tc & 0xFF);
-    write_scc(priv, R13, (priv->param.brg_tc>>8) & 0xFF);
-    /* BRG source = SYS CLK; enable BRG; DTR REQ function (required by
-       PackeTwin, not connected on the PI2); set DPLL source to BRG */
-    write_scc(priv, R14, SSBR | DTRREQ | BRSRC | BRENABL);
-    /* Enable DPLL */
-    write_scc(priv, R14, SEARCH | DTRREQ | BRSRC | BRENABL);
-  } else {
-    /* Disable BR generator */
-    write_scc(priv, R14, DTRREQ | BRSRC);
-  }
-
-  /* Configure clocks */
-  if (priv->type == TYPE_TWIN) {
-    /* Disable external TX clock receiver */
-    outb((info->twin_serial_cfg &=
-	    ~(priv->channel ? TWIN_EXTCLKB : TWIN_EXTCLKA)), 
-	   card_base + TWIN_SERIAL_CFG);
-  }
-  write_scc(priv, R11, priv->param.clocks);
-  if ((priv->type == TYPE_TWIN) && !(priv->param.clocks & TRxCOI)) {
-    /* Enable external TX clock receiver */
-    outb((info->twin_serial_cfg |=
-	    (priv->channel ? TWIN_EXTCLKB : TWIN_EXTCLKA)),
-	   card_base + TWIN_SERIAL_CFG);
-  }
-
-  /* Configure PackeTwin */
-  if (priv->type == TYPE_TWIN) {
-    /* Assert DTR, enable interrupts */
-    outb((info->twin_serial_cfg |= TWIN_EI |
-	    (priv->channel ? TWIN_DTRB_ON : TWIN_DTRA_ON)),
-	   card_base + TWIN_SERIAL_CFG);
-  }
-
-  /* Read current status */
-  priv->rr0 = read_scc(priv, R0);
-  /* Enable DCD interrupt */
-  write_scc(priv, R15, DCDIE);
-
-  netif_start_queue(dev);
-
-  return 0;
-}
-
-
-static int scc_close(struct net_device *dev) {
-  struct scc_priv *priv = dev->priv;
-  struct scc_info *info = priv->info;
-  int card_base = priv->card_base;
-
-  netif_stop_queue(dev);
-
-  if (priv->type == TYPE_TWIN) {
-    /* Drop DTR */
-    outb((info->twin_serial_cfg &=
-	    (priv->channel ? ~TWIN_DTRB_ON : ~TWIN_DTRA_ON)),
-	   card_base + TWIN_SERIAL_CFG);
-  }
-
-  /* Reset channel, free DMA and IRQ */
-  write_scc(priv, R9, (priv->channel ? CHRB : CHRA) | MIE | NV);
-  if (priv->param.dma >= 0) {
-    if (priv->type == TYPE_TWIN) outb(0, card_base + TWIN_DMA_CFG);
-    free_dma(priv->param.dma);
-  }
-  if (--info->irq_used == 0) free_irq(dev->irq, info);
-
-  return 0;
-}
-
-
-static int scc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) {
-  struct scc_priv *priv = dev->priv;
-  
-  switch (cmd) {
-  case SIOCGSCCPARAM:
-    if (copy_to_user(ifr->ifr_data, &priv->param, sizeof(struct scc_param)))
-      return -EFAULT;
-    return 0;
-  case SIOCSSCCPARAM:
-    if (!capable(CAP_NET_ADMIN)) return -EPERM;
-    if (netif_running(dev)) return -EAGAIN;
-    if (copy_from_user(&priv->param, ifr->ifr_data, sizeof(struct scc_param)))
-      return -EFAULT;
-    return 0;
-  default:
-    return -EINVAL;
-  }
-}
-
-
-static int scc_send_packet(struct sk_buff *skb, struct net_device *dev) {
-  struct scc_priv *priv = dev->priv;
-  unsigned long flags;
-  int i;
-
-  /* Temporarily stop the scheduler feeding us packets */
-  netif_stop_queue(dev);
-
-  /* Transfer data to DMA buffer */
-  i = priv->tx_head;
-  memcpy(priv->tx_buf[i], skb->data+1, skb->len-1);
-  priv->tx_len[i] = skb->len-1;
-
-  /* Clear interrupts while we touch our circular buffers */
-
-  spin_lock_irqsave(&priv->ring_lock, flags);
-  /* Move the ring buffer's head */
-  priv->tx_head = (i + 1) % NUM_TX_BUF;
-  priv->tx_count++;
-
-  /* If we just filled up the last buffer, leave queue stopped.
-     The higher layers must wait until we have a DMA buffer
-     to accept the data. */
-  if (priv->tx_count < NUM_TX_BUF) netif_wake_queue(dev);
-
-  /* Set new TX state */
-  if (priv->state == IDLE) {
-    /* Assert RTS, start timer */
-    priv->state = TX_HEAD;
-    priv->tx_start = jiffies;
-    write_scc(priv, R5, TxCRC_ENAB | RTS | TxENAB | Tx8);
-    write_scc(priv, R15, 0);
-    start_timer(priv, priv->param.txdelay, 0);
-  }
-
-  /* Turn interrupts back on and free buffer */
-  spin_unlock_irqrestore(&priv->ring_lock, flags);
-  dev_kfree_skb(skb);
-
-  return 0;
-}
-
-
-static struct net_device_stats *scc_get_stats(struct net_device *dev) {
-  struct scc_priv *priv = dev->priv;
-
-  return &priv->stats;
-}
-
-
-static int scc_set_mac_address(struct net_device *dev, void *sa) {
-  memcpy(dev->dev_addr, ((struct sockaddr *)sa)->sa_data, dev->addr_len);
-  return 0;
-}
-
-
-static inline void tx_on(struct scc_priv *priv) {
-  int i, n;
-  unsigned long flags;
-
-  if (priv->param.dma >= 0) {
-    n = (priv->chip == Z85230) ? 3 : 1;
-    /* Program DMA controller */
-    flags = claim_dma_lock();
-    set_dma_mode(priv->param.dma, DMA_MODE_WRITE);
-    set_dma_addr(priv->param.dma, (int) priv->tx_buf[priv->tx_tail]+n);
-    set_dma_count(priv->param.dma, priv->tx_len[priv->tx_tail]-n);
-    release_dma_lock(flags);
-    /* Enable TX underrun interrupt */
-    write_scc(priv, R15, TxUIE);
-    /* Configure DREQ */
-    if (priv->type == TYPE_TWIN)
-      outb((priv->param.dma == 1) ? TWIN_DMA_HDX_T1 : TWIN_DMA_HDX_T3,
-	   priv->card_base + TWIN_DMA_CFG);
-    else
-      write_scc(priv, R1, EXT_INT_ENAB | WT_FN_RDYFN | WT_RDY_ENAB);
-    /* Write first byte(s) */
-    spin_lock_irqsave(priv->register_lock, flags);
-    for (i = 0; i < n; i++)
-      write_scc_data(priv, priv->tx_buf[priv->tx_tail][i], 1);
-    enable_dma(priv->param.dma);
-    spin_unlock_irqrestore(priv->register_lock, flags);
-  } else {
-    write_scc(priv, R15, TxUIE);
-    write_scc(priv, R1, EXT_INT_ENAB | WT_FN_RDYFN | TxINT_ENAB);
-    tx_isr(priv);
-  }
-  /* Reset EOM latch if we do not have the AUTOEOM feature */
-  if (priv->chip == Z8530) write_scc(priv, R0, RES_EOM_L);
-}
-
-
-static inline void rx_on(struct scc_priv *priv) {
-  unsigned long flags;
-
-  /* Clear RX FIFO */
-  while (read_scc(priv, R0) & Rx_CH_AV) read_scc_data(priv);
-  priv->rx_over = 0;
-  if (priv->param.dma >= 0) {
-    /* Program DMA controller */
-    flags = claim_dma_lock();
-    set_dma_mode(priv->param.dma, DMA_MODE_READ);
-    set_dma_addr(priv->param.dma, (int) priv->rx_buf[priv->rx_head]);
-    set_dma_count(priv->param.dma, BUF_SIZE);
-    release_dma_lock(flags);
-    enable_dma(priv->param.dma);
-    /* Configure PackeTwin DMA */
-    if (priv->type == TYPE_TWIN) {
-      outb((priv->param.dma == 1) ? TWIN_DMA_HDX_R1 : TWIN_DMA_HDX_R3,
-	   priv->card_base + TWIN_DMA_CFG);
-    }
-    /* Sp. cond. intr. only, ext int enable, RX DMA enable */
-    write_scc(priv, R1, EXT_INT_ENAB | INT_ERR_Rx |
-	      WT_RDY_RT | WT_FN_RDYFN | WT_RDY_ENAB);
-  } else {
-    /* Reset current frame */
-    priv->rx_ptr = 0;
-    /* Intr. on all Rx characters and Sp. cond., ext int enable */
-    write_scc(priv, R1, EXT_INT_ENAB | INT_ALL_Rx | WT_RDY_RT |
-	      WT_FN_RDYFN);
-  }
-  write_scc(priv, R0, ERR_RES);
-  write_scc(priv, R3, RxENABLE | Rx8 | RxCRC_ENAB);
-}
-
-
-static inline void rx_off(struct scc_priv *priv) {
-  /* Disable receiver */
-  write_scc(priv, R3, Rx8);
-  /* Disable DREQ / RX interrupt */
-  if (priv->param.dma >= 0 && priv->type == TYPE_TWIN)
-    outb(0, priv->card_base + TWIN_DMA_CFG);
-  else
-    write_scc(priv, R1, EXT_INT_ENAB | WT_FN_RDYFN);
-  /* Disable DMA */
-  if (priv->param.dma >= 0) disable_dma(priv->param.dma);
-}
-
-
-static void start_timer(struct scc_priv *priv, int t, int r15) {
-  unsigned long flags;
-
-  outb(priv->tmr_mode, priv->tmr_ctrl);
-  if (t == 0) {
-    tm_isr(priv);
-  } else if (t > 0) {
-    save_flags(flags);
-    cli();
-    outb(t & 0xFF, priv->tmr_cnt);
-    outb((t >> 8) & 0xFF, priv->tmr_cnt);
-    if (priv->type != TYPE_TWIN) {
-      write_scc(priv, R15, r15 | CTSIE);
-      priv->rr0 |= CTS;
-    }
-    restore_flags(flags);
-  }
-}
-
-
-static inline unsigned char random(void) {
-  /* See "Numerical Recipes in C", second edition, p. 284 */
-  rand = rand * 1664525L + 1013904223L;
-  return (unsigned char) (rand >> 24);
-}
-
-static inline void z8530_isr(struct scc_info *info) {
-  int is, i = 100;
-
-  while ((is = read_scc(&info->priv[0], R3)) && i--) {
-    if (is & CHARxIP) {
-      rx_isr(&info->priv[0]);
-    } else if (is & CHATxIP) {
-      tx_isr(&info->priv[0]);
-    } else if (is & CHAEXT) {
-      es_isr(&info->priv[0]);
-    } else if (is & CHBRxIP) {
-      rx_isr(&info->priv[1]);
-    } else if (is & CHBTxIP) {
-      tx_isr(&info->priv[1]);
-    } else {
-      es_isr(&info->priv[1]);
-    }
-    write_scc(&info->priv[0], R0, RES_H_IUS);
-    i++;
-  }
-  if (i < 0) {
-    printk(KERN_ERR "dmascc: stuck in ISR with RR3=0x%02x.\n", is);
-  }
-  /* Ok, no interrupts pending from this 8530. The INT line should
-     be inactive now. */
-}
-
-
-static irqreturn_t scc_isr(int irq, void *dev_id, struct pt_regs * regs) {
-  struct scc_info *info = dev_id;
-
-  spin_lock(info->priv[0].register_lock);
-  /* At this point interrupts are enabled, and the interrupt under service
-     is already acknowledged, but masked off.
-
-     Interrupt processing: We loop until we know that the IRQ line is
-     low. If another positive edge occurs afterwards during the ISR,
-     another interrupt will be triggered by the interrupt controller
-     as soon as the IRQ level is enabled again (see asm/irq.h).
-
-     Bottom-half handlers will be processed after scc_isr(). This is
-     important, since we only have small ringbuffers and want new data
-     to be fetched/delivered immediately. */
-
-  if (info->priv[0].type == TYPE_TWIN) {
-    int is, card_base = info->priv[0].card_base;
-    while ((is = ~inb(card_base + TWIN_INT_REG)) &
-	   TWIN_INT_MSK) {
-      if (is & TWIN_SCC_MSK) {
-	z8530_isr(info);
-      } else if (is & TWIN_TMR1_MSK) {
-	inb(card_base + TWIN_CLR_TMR1);
-	tm_isr(&info->priv[0]);
-      } else {
-	inb(card_base + TWIN_CLR_TMR2);
-	tm_isr(&info->priv[1]);
-      }
-    }
-  } else z8530_isr(info);
-  spin_unlock(info->priv[0].register_lock);
-  return IRQ_HANDLED;
-}
-
-
-static void rx_isr(struct scc_priv *priv) {
-  if (priv->param.dma >= 0) {
-    /* Check special condition and perform error reset. See 2.4.7.5. */
-    special_condition(priv, read_scc(priv, R1));
-    write_scc(priv, R0, ERR_RES);
-  } else {
-    /* Check special condition for each character. Error reset not necessary.
-       Same algorithm for SCC and ESCC. See 2.4.7.1 and 2.4.7.4. */
-    int rc;
-    while (read_scc(priv, R0) & Rx_CH_AV) {
-      rc = read_scc(priv, R1);
-      if (priv->rx_ptr < BUF_SIZE)
-	priv->rx_buf[priv->rx_head][priv->rx_ptr++] =
-	  read_scc_data(priv);
-      else {
-	priv->rx_over = 2;
-	read_scc_data(priv);
-      }
-      special_condition(priv, rc);
-    }
-  }
-}
-
-
-static void special_condition(struct scc_priv *priv, int rc) {
-  int cb;
-  unsigned long flags;
-
-  /* See Figure 2-15. Only overrun and EOF need to be checked. */
-  
-  if (rc & Rx_OVR) {
-    /* Receiver overrun */
-    priv->rx_over = 1;
-    if (priv->param.dma < 0) write_scc(priv, R0, ERR_RES);
-  } else if (rc & END_FR) {
-    /* End of frame. Get byte count */
-    if (priv->param.dma >= 0) {
-      flags = claim_dma_lock();
-      cb = BUF_SIZE - get_dma_residue(priv->param.dma) - 2;
-      release_dma_lock(flags);
-    } else {
-      cb = priv->rx_ptr - 2;
-    }
-    if (priv->rx_over) {
-      /* We had an overrun */
-      priv->stats.rx_errors++;
-      if (priv->rx_over == 2) priv->stats.rx_length_errors++;
-      else priv->stats.rx_fifo_errors++;
-      priv->rx_over = 0;
-    } else if (rc & CRC_ERR) {
-      /* Count invalid CRC only if packet length >= minimum */
-      if (cb >= 15) {
-	priv->stats.rx_errors++;
-	priv->stats.rx_crc_errors++;
-      }
-    } else {
-      if (cb >= 15) {
-	if (priv->rx_count < NUM_RX_BUF - 1) {
-	  /* Put good frame in FIFO */
-	  priv->rx_len[priv->rx_head] = cb;
-	  priv->rx_head = (priv->rx_head + 1) % NUM_RX_BUF;
-	  priv->rx_count++;
-	  schedule_work(&priv->rx_work);
+static void write_scc(struct scc_priv *priv, int reg, int val)
+{
+	unsigned long flags;
+	switch (priv->type) {
+	case TYPE_S5:
+		if (reg)
+			outb(reg, priv->scc_cmd);
+		outb(val, priv->scc_cmd);
+		return;
+	case TYPE_TWIN:
+		if (reg)
+			outb_p(reg, priv->scc_cmd);
+		outb_p(val, priv->scc_cmd);
+		return;
+	default:
+		spin_lock_irqsave(priv->register_lock, flags);
+		outb_p(0, priv->card_base + PI_DREQ_MASK);
+		if (reg)
+			outb_p(reg, priv->scc_cmd);
+		outb_p(val, priv->scc_cmd);
+		outb(1, priv->card_base + PI_DREQ_MASK);
+		spin_unlock_irqrestore(priv->register_lock, flags);
+		return;
+	}
+}
+
+
+static void write_scc_data(struct scc_priv *priv, int val, int fast)
+{
+	unsigned long flags;
+	switch (priv->type) {
+	case TYPE_S5:
+		outb(val, priv->scc_data);
+		return;
+	case TYPE_TWIN:
+		outb_p(val, priv->scc_data);
+		return;
+	default:
+		if (fast)
+			outb_p(val, priv->scc_data);
+		else {
+			spin_lock_irqsave(priv->register_lock, flags);
+			outb_p(0, priv->card_base + PI_DREQ_MASK);
+			outb_p(val, priv->scc_data);
+			outb(1, priv->card_base + PI_DREQ_MASK);
+			spin_unlock_irqrestore(priv->register_lock, flags);
+		}
+		return;
+	}
+}
+
+
+static int read_scc(struct scc_priv *priv, int reg)
+{
+	int rc;
+	unsigned long flags;
+	switch (priv->type) {
+	case TYPE_S5:
+		if (reg)
+			outb(reg, priv->scc_cmd);
+		return inb(priv->scc_cmd);
+	case TYPE_TWIN:
+		if (reg)
+			outb_p(reg, priv->scc_cmd);
+		return inb_p(priv->scc_cmd);
+	default:
+		spin_lock_irqsave(priv->register_lock, flags);
+		outb_p(0, priv->card_base + PI_DREQ_MASK);
+		if (reg)
+			outb_p(reg, priv->scc_cmd);
+		rc = inb_p(priv->scc_cmd);
+		outb(1, priv->card_base + PI_DREQ_MASK);
+		spin_unlock_irqrestore(priv->register_lock, flags);
+		return rc;
+	}
+}
+
+
+static int read_scc_data(struct scc_priv *priv)
+{
+	int rc;
+	unsigned long flags;
+	switch (priv->type) {
+	case TYPE_S5:
+		return inb(priv->scc_data);
+	case TYPE_TWIN:
+		return inb_p(priv->scc_data);
+	default:
+		spin_lock_irqsave(priv->register_lock, flags);
+		outb_p(0, priv->card_base + PI_DREQ_MASK);
+		rc = inb_p(priv->scc_data);
+		outb(1, priv->card_base + PI_DREQ_MASK);
+		spin_unlock_irqrestore(priv->register_lock, flags);
+		return rc;
+	}
+}
+
+
+static int scc_open(struct net_device *dev)
+{
+	struct scc_priv *priv = dev->priv;
+	struct scc_info *info = priv->info;
+	int card_base = priv->card_base;
+
+	/* Request IRQ if not already used by other channel */
+	if (!info->irq_used) {
+		if (request_irq(dev->irq, scc_isr, 0, "dmascc", info)) {
+			return -EAGAIN;
+		}
+	}
+	info->irq_used++;
+
+	/* Request DMA if required */
+	if (priv->param.dma >= 0) {
+		if (request_dma(priv->param.dma, "dmascc")) {
+			if (--info->irq_used == 0)
+				free_irq(dev->irq, info);
+			return -EAGAIN;
+		} else {
+			unsigned long flags = claim_dma_lock();
+			clear_dma_ff(priv->param.dma);
+			release_dma_lock(flags);
+		}
+	}
+
+	/* Initialize local variables */
+	priv->rx_ptr = 0;
+	priv->rx_over = 0;
+	priv->rx_head = priv->rx_tail = priv->rx_count = 0;
+	priv->state = IDLE;
+	priv->tx_head = priv->tx_tail = priv->tx_count = 0;
+	priv->tx_ptr = 0;
+
+	/* Reset channel */
+	write_scc(priv, R9, (priv->channel ? CHRB : CHRA) | MIE | NV);
+	/* X1 clock, SDLC mode */
+	write_scc(priv, R4, SDLC | X1CLK);
+	/* DMA */
+	write_scc(priv, R1, EXT_INT_ENAB | WT_FN_RDYFN);
+	/* 8 bit RX char, RX disable */
+	write_scc(priv, R3, Rx8);
+	/* 8 bit TX char, TX disable */
+	write_scc(priv, R5, Tx8);
+	/* SDLC address field */
+	write_scc(priv, R6, 0);
+	/* SDLC flag */
+	write_scc(priv, R7, FLAG);
+	switch (priv->chip) {
+	case Z85C30:
+		/* Select WR7' */
+		write_scc(priv, R15, SHDLCE);
+		/* Auto EOM reset */
+		write_scc(priv, R7, AUTOEOM);
+		write_scc(priv, R15, 0);
+		break;
+	case Z85230:
+		/* Select WR7' */
+		write_scc(priv, R15, SHDLCE);
+		/* The following bits are set (see 2.5.2.1):
+		   - Automatic EOM reset
+		   - Interrupt request if RX FIFO is half full
+		   This bit should be ignored in DMA mode (according to the
+		   documentation), but actually isn't. The receiver doesn't work if
+		   it is set. Thus, we have to clear it in DMA mode.
+		   - Interrupt/DMA request if TX FIFO is completely empty
+		   a) If set, the ESCC behaves as if it had no TX FIFO (Z85C30
+		   compatibility).
+		   b) If cleared, DMA requests may follow each other very quickly,
+		   filling up the TX FIFO.
+		   Advantage: TX works even in case of high bus latency.
+		   Disadvantage: Edge-triggered DMA request circuitry may miss
+		   a request. No more data is delivered, resulting
+		   in a TX FIFO underrun.
+		   Both PI2 and S5SCC/DMA seem to work fine with TXFIFOE cleared.
+		   The PackeTwin doesn't. I don't know about the PI, but let's
+		   assume it behaves like the PI2.
+		 */
+		if (priv->param.dma >= 0) {
+			if (priv->type == TYPE_TWIN)
+				write_scc(priv, R7, AUTOEOM | TXFIFOE);
+			else
+				write_scc(priv, R7, AUTOEOM);
+		} else {
+			write_scc(priv, R7, AUTOEOM | RXFIFOH);
+		}
+		write_scc(priv, R15, 0);
+		break;
+	}
+	/* Preset CRC, NRZ(I) encoding */
+	write_scc(priv, R10, CRCPS | (priv->param.nrzi ? NRZI : NRZ));
+
+	/* Configure baud rate generator */
+	if (priv->param.brg_tc >= 0) {
+		/* Program BR generator */
+		write_scc(priv, R12, priv->param.brg_tc & 0xFF);
+		write_scc(priv, R13, (priv->param.brg_tc >> 8) & 0xFF);
+		/* BRG source = SYS CLK; enable BRG; DTR REQ function (required by
+		   PackeTwin, not connected on the PI2); set DPLL source to BRG */
+		write_scc(priv, R14, SSBR | DTRREQ | BRSRC | BRENABL);
+		/* Enable DPLL */
+		write_scc(priv, R14, SEARCH | DTRREQ | BRSRC | BRENABL);
 	} else {
-	  priv->stats.rx_errors++;
-	  priv->stats.rx_over_errors++;
+		/* Disable BR generator */
+		write_scc(priv, R14, DTRREQ | BRSRC);
+	}
+
+	/* Configure clocks */
+	if (priv->type == TYPE_TWIN) {
+		/* Disable external TX clock receiver */
+		outb((info->twin_serial_cfg &=
+		      ~(priv->channel ? TWIN_EXTCLKB : TWIN_EXTCLKA)),
+		     card_base + TWIN_SERIAL_CFG);
+	}
+	write_scc(priv, R11, priv->param.clocks);
+	if ((priv->type == TYPE_TWIN) && !(priv->param.clocks & TRxCOI)) {
+		/* Enable external TX clock receiver */
+		outb((info->twin_serial_cfg |=
+		      (priv->channel ? TWIN_EXTCLKB : TWIN_EXTCLKA)),
+		     card_base + TWIN_SERIAL_CFG);
+	}
+
+	/* Configure PackeTwin */
+	if (priv->type == TYPE_TWIN) {
+		/* Assert DTR, enable interrupts */
+		outb((info->twin_serial_cfg |= TWIN_EI |
+		      (priv->channel ? TWIN_DTRB_ON : TWIN_DTRA_ON)),
+		     card_base + TWIN_SERIAL_CFG);
+	}
+
+	/* Read current status */
+	priv->rr0 = read_scc(priv, R0);
+	/* Enable DCD interrupt */
+	write_scc(priv, R15, DCDIE);
+
+	netif_start_queue(dev);
+
+	return 0;
+}
+
+
+static int scc_close(struct net_device *dev)
+{
+	struct scc_priv *priv = dev->priv;
+	struct scc_info *info = priv->info;
+	int card_base = priv->card_base;
+
+	netif_stop_queue(dev);
+
+	if (priv->type == TYPE_TWIN) {
+		/* Drop DTR */
+		outb((info->twin_serial_cfg &=
+		      (priv->channel ? ~TWIN_DTRB_ON : ~TWIN_DTRA_ON)),
+		     card_base + TWIN_SERIAL_CFG);
+	}
+
+	/* Reset channel, free DMA and IRQ */
+	write_scc(priv, R9, (priv->channel ? CHRB : CHRA) | MIE | NV);
+	if (priv->param.dma >= 0) {
+		if (priv->type == TYPE_TWIN)
+			outb(0, card_base + TWIN_DMA_CFG);
+		free_dma(priv->param.dma);
+	}
+	if (--info->irq_used == 0)
+		free_irq(dev->irq, info);
+
+	return 0;
+}
+
+
+static int scc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
+{
+	struct scc_priv *priv = dev->priv;
+
+	switch (cmd) {
+	case SIOCGSCCPARAM:
+		if (copy_to_user
+		    (ifr->ifr_data, &priv->param,
+		     sizeof(struct scc_param)))
+			return -EFAULT;
+		return 0;
+	case SIOCSSCCPARAM:
+		if (!capable(CAP_NET_ADMIN))
+			return -EPERM;
+		if (netif_running(dev))
+			return -EAGAIN;
+		if (copy_from_user
+		    (&priv->param, ifr->ifr_data,
+		     sizeof(struct scc_param)))
+			return -EFAULT;
+		return 0;
+	default:
+		return -EINVAL;
+	}
+}
+
+
+static int scc_send_packet(struct sk_buff *skb, struct net_device *dev)
+{
+	struct scc_priv *priv = dev->priv;
+	unsigned long flags;
+	int i;
+
+	/* Temporarily stop the scheduler feeding us packets */
+	netif_stop_queue(dev);
+
+	/* Transfer data to DMA buffer */
+	i = priv->tx_head;
+	memcpy(priv->tx_buf[i], skb->data + 1, skb->len - 1);
+	priv->tx_len[i] = skb->len - 1;
+
+	/* Clear interrupts while we touch our circular buffers */
+
+	spin_lock_irqsave(&priv->ring_lock, flags);
+	/* Move the ring buffer's head */
+	priv->tx_head = (i + 1) % NUM_TX_BUF;
+	priv->tx_count++;
+
+	/* If we just filled up the last buffer, leave queue stopped.
+	   The higher layers must wait until we have a DMA buffer
+	   to accept the data. */
+	if (priv->tx_count < NUM_TX_BUF)
+		netif_wake_queue(dev);
+
+	/* Set new TX state */
+	if (priv->state == IDLE) {
+		/* Assert RTS, start timer */
+		priv->state = TX_HEAD;
+		priv->tx_start = jiffies;
+		write_scc(priv, R5, TxCRC_ENAB | RTS | TxENAB | Tx8);
+		write_scc(priv, R15, 0);
+		start_timer(priv, priv->param.txdelay, 0);
+	}
+
+	/* Turn interrupts back on and free buffer */
+	spin_unlock_irqrestore(&priv->ring_lock, flags);
+	dev_kfree_skb(skb);
+
+	return 0;
+}
+
+
+static struct net_device_stats *scc_get_stats(struct net_device *dev)
+{
+	struct scc_priv *priv = dev->priv;
+
+	return &priv->stats;
+}
+
+
+static int scc_set_mac_address(struct net_device *dev, void *sa)
+{
+	memcpy(dev->dev_addr, ((struct sockaddr *) sa)->sa_data,
+	       dev->addr_len);
+	return 0;
+}
+
+
+static inline void tx_on(struct scc_priv *priv)
+{
+	int i, n;
+	unsigned long flags;
+
+	if (priv->param.dma >= 0) {
+		n = (priv->chip == Z85230) ? 3 : 1;
+		/* Program DMA controller */
+		flags = claim_dma_lock();
+		set_dma_mode(priv->param.dma, DMA_MODE_WRITE);
+		set_dma_addr(priv->param.dma,
+			     (int) priv->tx_buf[priv->tx_tail] + n);
+		set_dma_count(priv->param.dma,
+			      priv->tx_len[priv->tx_tail] - n);
+		release_dma_lock(flags);
+		/* Enable TX underrun interrupt */
+		write_scc(priv, R15, TxUIE);
+		/* Configure DREQ */
+		if (priv->type == TYPE_TWIN)
+			outb((priv->param.dma ==
+			      1) ? TWIN_DMA_HDX_T1 : TWIN_DMA_HDX_T3,
+			     priv->card_base + TWIN_DMA_CFG);
+		else
+			write_scc(priv, R1,
+				  EXT_INT_ENAB | WT_FN_RDYFN |
+				  WT_RDY_ENAB);
+		/* Write first byte(s) */
+		spin_lock_irqsave(priv->register_lock, flags);
+		for (i = 0; i < n; i++)
+			write_scc_data(priv,
+				       priv->tx_buf[priv->tx_tail][i], 1);
+		enable_dma(priv->param.dma);
+		spin_unlock_irqrestore(priv->register_lock, flags);
+	} else {
+		write_scc(priv, R15, TxUIE);
+		write_scc(priv, R1,
+			  EXT_INT_ENAB | WT_FN_RDYFN | TxINT_ENAB);
+		tx_isr(priv);
+	}
+	/* Reset EOM latch if we do not have the AUTOEOM feature */
+	if (priv->chip == Z8530)
+		write_scc(priv, R0, RES_EOM_L);
+}
+
+
+static inline void rx_on(struct scc_priv *priv)
+{
+	unsigned long flags;
+
+	/* Clear RX FIFO */
+	while (read_scc(priv, R0) & Rx_CH_AV)
+		read_scc_data(priv);
+	priv->rx_over = 0;
+	if (priv->param.dma >= 0) {
+		/* Program DMA controller */
+		flags = claim_dma_lock();
+		set_dma_mode(priv->param.dma, DMA_MODE_READ);
+		set_dma_addr(priv->param.dma,
+			     (int) priv->rx_buf[priv->rx_head]);
+		set_dma_count(priv->param.dma, BUF_SIZE);
+		release_dma_lock(flags);
+		enable_dma(priv->param.dma);
+		/* Configure PackeTwin DMA */
+		if (priv->type == TYPE_TWIN) {
+			outb((priv->param.dma ==
+			      1) ? TWIN_DMA_HDX_R1 : TWIN_DMA_HDX_R3,
+			     priv->card_base + TWIN_DMA_CFG);
+		}
+		/* Sp. cond. intr. only, ext int enable, RX DMA enable */
+		write_scc(priv, R1, EXT_INT_ENAB | INT_ERR_Rx |
+			  WT_RDY_RT | WT_FN_RDYFN | WT_RDY_ENAB);
+	} else {
+		/* Reset current frame */
+		priv->rx_ptr = 0;
+		/* Intr. on all Rx characters and Sp. cond., ext int enable */
+		write_scc(priv, R1, EXT_INT_ENAB | INT_ALL_Rx | WT_RDY_RT |
+			  WT_FN_RDYFN);
+	}
+	write_scc(priv, R0, ERR_RES);
+	write_scc(priv, R3, RxENABLE | Rx8 | RxCRC_ENAB);
+}
+
+
+static inline void rx_off(struct scc_priv *priv)
+{
+	/* Disable receiver */
+	write_scc(priv, R3, Rx8);
+	/* Disable DREQ / RX interrupt */
+	if (priv->param.dma >= 0 && priv->type == TYPE_TWIN)
+		outb(0, priv->card_base + TWIN_DMA_CFG);
+	else
+		write_scc(priv, R1, EXT_INT_ENAB | WT_FN_RDYFN);
+	/* Disable DMA */
+	if (priv->param.dma >= 0)
+		disable_dma(priv->param.dma);
+}
+
+
+static void start_timer(struct scc_priv *priv, int t, int r15)
+{
+	unsigned long flags;
+
+	outb(priv->tmr_mode, priv->tmr_ctrl);
+	if (t == 0) {
+		tm_isr(priv);
+	} else if (t > 0) {
+		save_flags(flags);
+		cli();
+		outb(t & 0xFF, priv->tmr_cnt);
+		outb((t >> 8) & 0xFF, priv->tmr_cnt);
+		if (priv->type != TYPE_TWIN) {
+			write_scc(priv, R15, r15 | CTSIE);
+			priv->rr0 |= CTS;
+		}
+		restore_flags(flags);
+	}
+}
+
+
+static inline unsigned char random(void)
+{
+	/* See "Numerical Recipes in C", second edition, p. 284 */
+	rand = rand * 1664525L + 1013904223L;
+	return (unsigned char) (rand >> 24);
+}
+
+static inline void z8530_isr(struct scc_info *info)
+{
+	int is, i = 100;
+
+	while ((is = read_scc(&info->priv[0], R3)) && i--) {
+		if (is & CHARxIP) {
+			rx_isr(&info->priv[0]);
+		} else if (is & CHATxIP) {
+			tx_isr(&info->priv[0]);
+		} else if (is & CHAEXT) {
+			es_isr(&info->priv[0]);
+		} else if (is & CHBRxIP) {
+			rx_isr(&info->priv[1]);
+		} else if (is & CHBTxIP) {
+			tx_isr(&info->priv[1]);
+		} else {
+			es_isr(&info->priv[1]);
+		}
+		write_scc(&info->priv[0], R0, RES_H_IUS);
+		i++;
+	}
+	if (i < 0) {
+		printk(KERN_ERR "dmascc: stuck in ISR with RR3=0x%02x.\n",
+		       is);
+	}
+	/* Ok, no interrupts pending from this 8530. The INT line should
+	   be inactive now. */
+}
+
+
+static irqreturn_t scc_isr(int irq, void *dev_id, struct pt_regs *regs)
+{
+	struct scc_info *info = dev_id;
+
+	spin_lock(info->priv[0].register_lock);
+	/* At this point interrupts are enabled, and the interrupt under service
+	   is already acknowledged, but masked off.
+
+	   Interrupt processing: We loop until we know that the IRQ line is
+	   low. If another positive edge occurs afterwards during the ISR,
+	   another interrupt will be triggered by the interrupt controller
+	   as soon as the IRQ level is enabled again (see asm/irq.h).
+
+	   Bottom-half handlers will be processed after scc_isr(). This is
+	   important, since we only have small ringbuffers and want new data
+	   to be fetched/delivered immediately. */
+
+	if (info->priv[0].type == TYPE_TWIN) {
+		int is, card_base = info->priv[0].card_base;
+		while ((is = ~inb(card_base + TWIN_INT_REG)) &
+		       TWIN_INT_MSK) {
+			if (is & TWIN_SCC_MSK) {
+				z8530_isr(info);
+			} else if (is & TWIN_TMR1_MSK) {
+				inb(card_base + TWIN_CLR_TMR1);
+				tm_isr(&info->priv[0]);
+			} else {
+				inb(card_base + TWIN_CLR_TMR2);
+				tm_isr(&info->priv[1]);
+			}
+		}
+	} else
+		z8530_isr(info);
+	spin_unlock(info->priv[0].register_lock);
+	return IRQ_HANDLED;
+}
+
+
+static void rx_isr(struct scc_priv *priv)
+{
+	if (priv->param.dma >= 0) {
+		/* Check special condition and perform error reset. See 2.4.7.5. */
+		special_condition(priv, read_scc(priv, R1));
+		write_scc(priv, R0, ERR_RES);
+	} else {
+		/* Check special condition for each character. Error reset not necessary.
+		   Same algorithm for SCC and ESCC. See 2.4.7.1 and 2.4.7.4. */
+		int rc;
+		while (read_scc(priv, R0) & Rx_CH_AV) {
+			rc = read_scc(priv, R1);
+			if (priv->rx_ptr < BUF_SIZE)
+				priv->rx_buf[priv->rx_head][priv->
+							    rx_ptr++] =
+				    read_scc_data(priv);
+			else {
+				priv->rx_over = 2;
+				read_scc_data(priv);
+			}
+			special_condition(priv, rc);
+		}
+	}
+}
+
+
+static void special_condition(struct scc_priv *priv, int rc)
+{
+	int cb;
+	unsigned long flags;
+
+	/* See Figure 2-15. Only overrun and EOF need to be checked. */
+
+	if (rc & Rx_OVR) {
+		/* Receiver overrun */
+		priv->rx_over = 1;
+		if (priv->param.dma < 0)
+			write_scc(priv, R0, ERR_RES);
+	} else if (rc & END_FR) {
+		/* End of frame. Get byte count */
+		if (priv->param.dma >= 0) {
+			flags = claim_dma_lock();
+			cb = BUF_SIZE - get_dma_residue(priv->param.dma) -
+			    2;
+			release_dma_lock(flags);
+		} else {
+			cb = priv->rx_ptr - 2;
+		}
+		if (priv->rx_over) {
+			/* We had an overrun */
+			priv->stats.rx_errors++;
+			if (priv->rx_over == 2)
+				priv->stats.rx_length_errors++;
+			else
+				priv->stats.rx_fifo_errors++;
+			priv->rx_over = 0;
+		} else if (rc & CRC_ERR) {
+			/* Count invalid CRC only if packet length >= minimum */
+			if (cb >= 15) {
+				priv->stats.rx_errors++;
+				priv->stats.rx_crc_errors++;
+			}
+		} else {
+			if (cb >= 15) {
+				if (priv->rx_count < NUM_RX_BUF - 1) {
+					/* Put good frame in FIFO */
+					priv->rx_len[priv->rx_head] = cb;
+					priv->rx_head =
+					    (priv->rx_head +
+					     1) % NUM_RX_BUF;
+					priv->rx_count++;
+					schedule_work(&priv->rx_work);
+				} else {
+					priv->stats.rx_errors++;
+					priv->stats.rx_over_errors++;
+				}
+			}
+		}
+		/* Get ready for new frame */
+		if (priv->param.dma >= 0) {
+			flags = claim_dma_lock();
+			set_dma_addr(priv->param.dma,
+				     (int) priv->rx_buf[priv->rx_head]);
+			set_dma_count(priv->param.dma, BUF_SIZE);
+			release_dma_lock(flags);
+		} else {
+			priv->rx_ptr = 0;
+		}
+	}
+}
+
+
+static void rx_bh(void *arg)
+{
+	struct scc_priv *priv = arg;
+	int i = priv->rx_tail;
+	int cb;
+	unsigned long flags;
+	struct sk_buff *skb;
+	unsigned char *data;
+
+	spin_lock_irqsave(&priv->ring_lock, flags);
+	while (priv->rx_count) {
+		spin_unlock_irqrestore(&priv->ring_lock, flags);
+		cb = priv->rx_len[i];
+		/* Allocate buffer */
+		skb = dev_alloc_skb(cb + 1);
+		if (skb == NULL) {
+			/* Drop packet */
+			priv->stats.rx_dropped++;
+		} else {
+			/* Fill buffer */
+			data = skb_put(skb, cb + 1);
+			data[0] = 0;
+			memcpy(&data[1], priv->rx_buf[i], cb);
+			skb->dev = priv->dev;
+			skb->protocol = ntohs(ETH_P_AX25);
+			skb->mac.raw = skb->data;
+			netif_rx(skb);
+			priv->dev->last_rx = jiffies;
+			priv->stats.rx_packets++;
+			priv->stats.rx_bytes += cb;
+		}
+		spin_lock_irqsave(&priv->ring_lock, flags);
+		/* Move tail */
+		priv->rx_tail = i = (i + 1) % NUM_RX_BUF;
+		priv->rx_count--;
+	}
+	spin_unlock_irqrestore(&priv->ring_lock, flags);
+}
+
+
+static void tx_isr(struct scc_priv *priv)
+{
+	int i = priv->tx_tail, p = priv->tx_ptr;
+
+	/* Suspend TX interrupts if we don't want to send anything.
+	   See Figure 2-22. */
+	if (p == priv->tx_len[i]) {
+		write_scc(priv, R0, RES_Tx_P);
+		return;
+	}
+
+	/* Write characters */
+	while ((read_scc(priv, R0) & Tx_BUF_EMP) && p < priv->tx_len[i]) {
+		write_scc_data(priv, priv->tx_buf[i][p++], 0);
+	}
+
+	/* Reset EOM latch of Z8530 */
+	if (!priv->tx_ptr && p && priv->chip == Z8530)
+		write_scc(priv, R0, RES_EOM_L);
+
+	priv->tx_ptr = p;
+}
+
+
+static void es_isr(struct scc_priv *priv)
+{
+	int i, rr0, drr0, res;
+	unsigned long flags;
+
+	/* Read status, reset interrupt bit (open latches) */
+	rr0 = read_scc(priv, R0);
+	write_scc(priv, R0, RES_EXT_INT);
+	drr0 = priv->rr0 ^ rr0;
+	priv->rr0 = rr0;
+
+	/* Transmit underrun (2.4.9.6). We can't check the TxEOM flag, since
+	   it might have already been cleared again by AUTOEOM. */
+	if (priv->state == TX_DATA) {
+		/* Get remaining bytes */
+		i = priv->tx_tail;
+		if (priv->param.dma >= 0) {
+			disable_dma(priv->param.dma);
+			flags = claim_dma_lock();
+			res = get_dma_residue(priv->param.dma);
+			release_dma_lock(flags);
+		} else {
+			res = priv->tx_len[i] - priv->tx_ptr;
+			priv->tx_ptr = 0;
+		}
+		/* Disable DREQ / TX interrupt */
+		if (priv->param.dma >= 0 && priv->type == TYPE_TWIN)
+			outb(0, priv->card_base + TWIN_DMA_CFG);
+		else
+			write_scc(priv, R1, EXT_INT_ENAB | WT_FN_RDYFN);
+		if (res) {
+			/* Update packet statistics */
+			priv->stats.tx_errors++;
+			priv->stats.tx_fifo_errors++;
+			/* Other underrun interrupts may already be waiting */
+			write_scc(priv, R0, RES_EXT_INT);
+			write_scc(priv, R0, RES_EXT_INT);
+		} else {
+			/* Update packet statistics */
+			priv->stats.tx_packets++;
+			priv->stats.tx_bytes += priv->tx_len[i];
+			/* Remove frame from FIFO */
+			priv->tx_tail = (i + 1) % NUM_TX_BUF;
+			priv->tx_count--;
+			/* Inform upper layers */
+			netif_wake_queue(priv->dev);
+		}
+		/* Switch state */
+		write_scc(priv, R15, 0);
+		if (priv->tx_count &&
+		    (jiffies - priv->tx_start) < priv->param.txtimeout) {
+			priv->state = TX_PAUSE;
+			start_timer(priv, priv->param.txpause, 0);
+		} else {
+			priv->state = TX_TAIL;
+			start_timer(priv, priv->param.txtail, 0);
+		}
+	}
+
+	/* DCD transition */
+	if (drr0 & DCD) {
+		if (rr0 & DCD) {
+			switch (priv->state) {
+			case IDLE:
+			case WAIT:
+				priv->state = DCD_ON;
+				write_scc(priv, R15, 0);
+				start_timer(priv, priv->param.dcdon, 0);
+			}
+		} else {
+			switch (priv->state) {
+			case RX_ON:
+				rx_off(priv);
+				priv->state = DCD_OFF;
+				write_scc(priv, R15, 0);
+				start_timer(priv, priv->param.dcdoff, 0);
+			}
+		}
+	}
+
+	/* CTS transition */
+	if ((drr0 & CTS) && (~rr0 & CTS) && priv->type != TYPE_TWIN)
+		tm_isr(priv);
+
+}
+
+
+static void tm_isr(struct scc_priv *priv)
+{
+	switch (priv->state) {
+	case TX_HEAD:
+	case TX_PAUSE:
+		tx_on(priv);
+		priv->state = TX_DATA;
+		break;
+	case TX_TAIL:
+		write_scc(priv, R5, TxCRC_ENAB | Tx8);
+		priv->state = RTS_OFF;
+		if (priv->type != TYPE_TWIN)
+			write_scc(priv, R15, 0);
+		start_timer(priv, priv->param.rtsoff, 0);
+		break;
+	case RTS_OFF:
+		write_scc(priv, R15, DCDIE);
+		priv->rr0 = read_scc(priv, R0);
+		if (priv->rr0 & DCD) {
+			priv->stats.collisions++;
+			rx_on(priv);
+			priv->state = RX_ON;
+		} else {
+			priv->state = WAIT;
+			start_timer(priv, priv->param.waittime, DCDIE);
+		}
+		break;
+	case WAIT:
+		if (priv->tx_count) {
+			priv->state = TX_HEAD;
+			priv->tx_start = jiffies;
+			write_scc(priv, R5,
+				  TxCRC_ENAB | RTS | TxENAB | Tx8);
+			write_scc(priv, R15, 0);
+			start_timer(priv, priv->param.txdelay, 0);
+		} else {
+			priv->state = IDLE;
+			if (priv->type != TYPE_TWIN)
+				write_scc(priv, R15, DCDIE);
+		}
+		break;
+	case DCD_ON:
+	case DCD_OFF:
+		write_scc(priv, R15, DCDIE);
+		priv->rr0 = read_scc(priv, R0);
+		if (priv->rr0 & DCD) {
+			rx_on(priv);
+			priv->state = RX_ON;
+		} else {
+			priv->state = WAIT;
+			start_timer(priv,
+				    random() / priv->param.persist *
+				    priv->param.slottime, DCDIE);
+		}
+		break;
 	}
-      }
-    }
-    /* Get ready for new frame */
-    if (priv->param.dma >= 0) {
-      flags = claim_dma_lock();
-      set_dma_addr(priv->param.dma, (int) priv->rx_buf[priv->rx_head]);
-      set_dma_count(priv->param.dma, BUF_SIZE);
-      release_dma_lock(flags);
-    } else {
-      priv->rx_ptr = 0;
-    }
-  }
-}
-
-
-static void rx_bh(void *arg) {
-  struct scc_priv *priv = arg;
-  int i = priv->rx_tail;
-  int cb;
-  unsigned long flags;
-  struct sk_buff *skb;
-  unsigned char *data;
-
-  spin_lock_irqsave(&priv->ring_lock, flags);
-  while (priv->rx_count) {
-    spin_unlock_irqrestore(&priv->ring_lock, flags);
-    cb = priv->rx_len[i];
-    /* Allocate buffer */
-    skb = dev_alloc_skb(cb+1);
-    if (skb == NULL) {
-      /* Drop packet */
-      priv->stats.rx_dropped++;
-    } else {
-      /* Fill buffer */
-      data = skb_put(skb, cb+1);
-      data[0] = 0;
-      memcpy(&data[1], priv->rx_buf[i], cb);
-      skb->dev = priv->dev;
-      skb->protocol = ntohs(ETH_P_AX25);
-      skb->mac.raw = skb->data;
-      netif_rx(skb);
-      priv->dev->last_rx = jiffies;
-      priv->stats.rx_packets++;
-      priv->stats.rx_bytes += cb;
-    }
-    spin_lock_irqsave(&priv->ring_lock, flags);
-    /* Move tail */
-    priv->rx_tail = i = (i + 1) % NUM_RX_BUF;
-    priv->rx_count--;
-  }
-  spin_unlock_irqrestore(&priv->ring_lock, flags);
-}
-
-
-static void tx_isr(struct scc_priv *priv) {
-  int i = priv->tx_tail, p = priv->tx_ptr;
-
-  /* Suspend TX interrupts if we don't want to send anything.
-     See Figure 2-22. */
-  if (p ==  priv->tx_len[i]) {
-    write_scc(priv, R0, RES_Tx_P);
-    return;
-  }
-
-  /* Write characters */
-  while ((read_scc(priv, R0) & Tx_BUF_EMP) && p < priv->tx_len[i]) {
-    write_scc_data(priv, priv->tx_buf[i][p++], 0);
-  }
-
-  /* Reset EOM latch of Z8530 */
-  if (!priv->tx_ptr && p && priv->chip == Z8530)
-    write_scc(priv, R0, RES_EOM_L);
-
-  priv->tx_ptr = p;
-}
-
-
-static void es_isr(struct scc_priv *priv) {
-  int i, rr0, drr0, res;
-  unsigned long flags;
-
-  /* Read status, reset interrupt bit (open latches) */
-  rr0 = read_scc(priv, R0);
-  write_scc(priv, R0, RES_EXT_INT);
-  drr0 = priv->rr0 ^ rr0;
-  priv->rr0 = rr0;
-
-  /* Transmit underrun (2.4.9.6). We can't check the TxEOM flag, since
-     it might have already been cleared again by AUTOEOM. */
-  if (priv->state == TX_DATA) {
-    /* Get remaining bytes */
-    i = priv->tx_tail;
-    if (priv->param.dma >= 0) {
-      disable_dma(priv->param.dma);
-      flags = claim_dma_lock();
-      res = get_dma_residue(priv->param.dma);
-      release_dma_lock(flags);
-    } else {
-      res = priv->tx_len[i] - priv->tx_ptr;
-      priv->tx_ptr = 0;
-    }
-    /* Disable DREQ / TX interrupt */
-    if (priv->param.dma >= 0 && priv->type == TYPE_TWIN)
-      outb(0, priv->card_base + TWIN_DMA_CFG);
-    else
-      write_scc(priv, R1, EXT_INT_ENAB | WT_FN_RDYFN);
-    if (res) {
-      /* Update packet statistics */
-      priv->stats.tx_errors++;
-      priv->stats.tx_fifo_errors++;
-      /* Other underrun interrupts may already be waiting */
-      write_scc(priv, R0, RES_EXT_INT);
-      write_scc(priv, R0, RES_EXT_INT);
-    } else {
-      /* Update packet statistics */
-      priv->stats.tx_packets++;
-      priv->stats.tx_bytes += priv->tx_len[i];
-      /* Remove frame from FIFO */
-      priv->tx_tail = (i + 1) % NUM_TX_BUF;
-      priv->tx_count--;
-      /* Inform upper layers */
-      netif_wake_queue(priv->dev);
-    }
-    /* Switch state */
-    write_scc(priv, R15, 0);
-    if (priv->tx_count &&
-	(jiffies - priv->tx_start) < priv->param.txtimeout) {
-      priv->state = TX_PAUSE;
-      start_timer(priv, priv->param.txpause, 0);
-    } else {
-      priv->state = TX_TAIL;
-      start_timer(priv, priv->param.txtail, 0);
-    }
-  }
-
-  /* DCD transition */
-  if (drr0 & DCD) {
-    if (rr0 & DCD) {
-      switch (priv->state) {
-      case IDLE:
-      case WAIT:
-	priv->state = DCD_ON;
-	write_scc(priv, R15, 0);
-	start_timer(priv, priv->param.dcdon, 0);
-      }
-    } else {
-      switch (priv->state) {
-      case RX_ON:
-	rx_off(priv);
-	priv->state = DCD_OFF;
-	write_scc(priv, R15, 0);
-	start_timer(priv, priv->param.dcdoff, 0);
-      }
-    }
-  }
-
-  /* CTS transition */
-  if ((drr0 & CTS) && (~rr0 & CTS) && priv->type != TYPE_TWIN)
-    tm_isr(priv);
-
-}
-
-
-static void tm_isr(struct scc_priv *priv) {
-  switch (priv->state) {
-  case TX_HEAD:
-  case TX_PAUSE:
-    tx_on(priv);
-    priv->state = TX_DATA;
-    break;
-  case TX_TAIL:
-    write_scc(priv, R5, TxCRC_ENAB | Tx8);
-    priv->state = RTS_OFF;
-    if (priv->type != TYPE_TWIN) write_scc(priv, R15, 0);
-    start_timer(priv, priv->param.rtsoff, 0);
-    break;
-  case RTS_OFF:
-    write_scc(priv, R15, DCDIE);
-    priv->rr0 = read_scc(priv, R0);
-    if (priv->rr0 & DCD) {
-      priv->stats.collisions++;
-      rx_on(priv);
-      priv->state = RX_ON;
-    } else {
-      priv->state = WAIT;
-      start_timer(priv, priv->param.waittime, DCDIE);
-    }
-    break;
-  case WAIT:
-    if (priv->tx_count) {
-      priv->state = TX_HEAD;
-      priv->tx_start = jiffies;
-      write_scc(priv, R5, TxCRC_ENAB | RTS | TxENAB | Tx8);
-      write_scc(priv, R15, 0);
-      start_timer(priv, priv->param.txdelay, 0);
-    } else {
-      priv->state = IDLE;
-      if (priv->type != TYPE_TWIN) write_scc(priv, R15, DCDIE);
-    }
-    break;
-  case DCD_ON:
-  case DCD_OFF:
-    write_scc(priv, R15, DCDIE);
-    priv->rr0 = read_scc(priv, R0);
-    if (priv->rr0 & DCD) {
-      rx_on(priv);
-      priv->state = RX_ON;
-    } else {
-      priv->state = WAIT;
-      start_timer(priv,
-		  random()/priv->param.persist*priv->param.slottime,
-		  DCDIE);
-    }
-    break;
-  }
 }
diff -Nru a/drivers/net/hamradio/hdlcdrv.c b/drivers/net/hamradio/hdlcdrv.c
--- a/drivers/net/hamradio/hdlcdrv.c	2005-03-11 12:51:52 -08:00
+++ b/drivers/net/hamradio/hdlcdrv.c	2005-03-11 12:51:52 -08:00
@@ -427,27 +427,10 @@
  * ===================== network driver interface =========================
  */
 
-static inline int hdlcdrv_paranoia_check(struct net_device *dev,
-					const char *routine)
-{
-	if (!dev || !dev->priv || 
-	    ((struct hdlcdrv_state *)dev->priv)->magic != HDLCDRV_MAGIC) {
-		printk(KERN_ERR "hdlcdrv: bad magic number for hdlcdrv_state "
-		       "struct in routine %s\n", routine);
-		return 1;
-	}
-	return 0;
-}
-
-/* --------------------------------------------------------------------- */
-
 static int hdlcdrv_send_packet(struct sk_buff *skb, struct net_device *dev)
 {
-	struct hdlcdrv_state *sm;
+	struct hdlcdrv_state *sm = netdev_priv(dev);
 
-	if (hdlcdrv_paranoia_check(dev, "hdlcdrv_send_packet"))
-		return 0;
-	sm = (struct hdlcdrv_state *)dev->priv;
 	if (skb->data[0] != 0) {
 		do_kiss_params(sm, skb->data, skb->len);
 		dev_kfree_skb(skb);
@@ -475,11 +458,8 @@
 
 static struct net_device_stats *hdlcdrv_get_stats(struct net_device *dev)
 {
-	struct hdlcdrv_state *sm;
+	struct hdlcdrv_state *sm = netdev_priv(dev);
 
-	if (hdlcdrv_paranoia_check(dev, "hdlcdrv_get_stats"))
-		return NULL;
-	sm = (struct hdlcdrv_state *)dev->priv;
 	/* 
 	 * Get the current statistics.  This may be called with the
 	 * card open or closed. 
@@ -499,13 +479,9 @@
 
 static int hdlcdrv_open(struct net_device *dev)
 {
-	struct hdlcdrv_state *s;
+	struct hdlcdrv_state *s = netdev_priv(dev);
 	int i;
 
-	if (hdlcdrv_paranoia_check(dev, "hdlcdrv_open"))
-		return -EINVAL;
-	s = (struct hdlcdrv_state *)dev->priv;
-
 	if (!s->ops || !s->ops->open)
 		return -ENODEV;
 
@@ -540,13 +516,9 @@
 
 static int hdlcdrv_close(struct net_device *dev)
 {
-	struct hdlcdrv_state *s;
+	struct hdlcdrv_state *s = netdev_priv(dev);
 	int i = 0;
 
-	if (hdlcdrv_paranoia_check(dev, "hdlcdrv_close"))
-		return -EINVAL;
-	s = (struct hdlcdrv_state *)dev->priv;
-
 	netif_stop_queue(dev);
 
 	if (s->ops && s->ops->close)
@@ -562,12 +534,8 @@
 
 static int hdlcdrv_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 {
-	struct hdlcdrv_state *s;
+	struct hdlcdrv_state *s = netdev_priv(dev);
 	struct hdlcdrv_ioctl bi;
-		
-	if (hdlcdrv_paranoia_check(dev, "hdlcdrv_ioctl"))
-		return -EINVAL;
-	s = (struct hdlcdrv_state *)dev->priv;
 
 	if (cmd != SIOCDEVPRIVATE) {
 		if (s->ops && s->ops->ioctl)
@@ -698,7 +666,7 @@
 	static const struct hdlcdrv_channel_params dflt_ch_params = { 
 		20, 2, 10, 40, 0 
 	};
-	struct hdlcdrv_state *s = dev->priv;
+	struct hdlcdrv_state *s = netdev_priv(dev);
 
 	/*
 	 * initialize the hdlcdrv_state struct
@@ -782,7 +750,7 @@
 	/*
 	 * initialize part of the hdlcdrv_state struct
 	 */
-	s = dev->priv;
+	s = netdev_priv(dev);
 	s->magic = HDLCDRV_MAGIC;
 	s->ops = ops;
 	dev->base_addr = baseaddr;
@@ -803,7 +771,7 @@
 
 void hdlcdrv_unregister(struct net_device *dev) 
 {
-	struct hdlcdrv_state *s = dev->priv;
+	struct hdlcdrv_state *s = netdev_priv(dev);
 
 	BUG_ON(s->magic != HDLCDRV_MAGIC);
 
diff -Nru a/drivers/net/hamradio/mkiss.c b/drivers/net/hamradio/mkiss.c
--- a/drivers/net/hamradio/mkiss.c	2005-03-11 12:51:51 -08:00
+++ b/drivers/net/hamradio/mkiss.c	2005-03-11 12:51:51 -08:00
@@ -419,7 +419,7 @@
 /* Encapsulate an AX.25 packet and kick it into a TTY queue. */
 static int ax_xmit(struct sk_buff *skb, struct net_device *dev)
 {
-	struct ax_disp *ax = (struct ax_disp *) dev->priv;
+	struct ax_disp *ax = netdev_priv(dev);
 
 	if (!netif_running(dev))  {
 		printk(KERN_ERR "mkiss: %s: xmit call when iface is down\n", dev->name);
@@ -483,7 +483,7 @@
 /* Open the low-level part of the AX25 channel. Easy! */
 static int ax_open(struct net_device *dev)
 {
-	struct ax_disp *ax = (struct ax_disp *) dev->priv;
+	struct ax_disp *ax = netdev_priv(dev);
 	unsigned long len;
 
 	if (ax->tty == NULL)
@@ -534,7 +534,7 @@
 /* Close the low-level part of the AX25 channel. Easy! */
 static int ax_close(struct net_device *dev)
 {
-	struct ax_disp *ax = (struct ax_disp *) dev->priv;
+	struct ax_disp *ax = netdev_priv(dev);
 
 	if (ax->tty == NULL)
 		return -EBUSY;
@@ -634,7 +634,7 @@
 static struct net_device_stats *ax_get_stats(struct net_device *dev)
 {
 	static struct net_device_stats stats;
-	struct ax_disp *ax = (struct ax_disp *) dev->priv;
+	struct ax_disp *ax = netdev_priv(dev);
 
 	memset(&stats, 0, sizeof(struct net_device_stats));
 
@@ -827,7 +827,7 @@
 
 static int ax_open_dev(struct net_device *dev)
 {
-	struct ax_disp *ax = (struct ax_disp *) dev->priv;
+	struct ax_disp *ax = netdev_priv(dev);
 
 	if (ax->tty == NULL)
 		return -ENODEV;
@@ -839,7 +839,7 @@
 /* Initialize the driver.  Called by network startup. */
 static int ax25_init(struct net_device *dev)
 {
-	struct ax_disp *ax = (struct ax_disp *) dev->priv;
+	struct ax_disp *ax = netdev_priv(dev);
 
 	static char ax25_bcast[AX25_ADDR_LEN] =
 		{'Q'<<1,'S'<<1,'T'<<1,' '<<1,' '<<1,' '<<1,'0'<<1};
diff -Nru a/drivers/net/hamradio/yam.c b/drivers/net/hamradio/yam.c
--- a/drivers/net/hamradio/yam.c	2005-03-11 12:51:47 -08:00
+++ b/drivers/net/hamradio/yam.c	2005-03-11 12:51:47 -08:00
@@ -442,7 +442,7 @@
 
 static void yam_set_uart(struct net_device *dev)
 {
-	struct yam_port *yp = (struct yam_port *) dev->priv;
+	struct yam_port *yp = netdev_priv(dev);
 	int divisor = 115200 / yp->baudrate;
 
 	outb(0, IER(dev->base_addr));
@@ -565,7 +565,7 @@
 
 static int yam_send_packet(struct sk_buff *skb, struct net_device *dev)
 {
-	struct yam_port *yp = dev->priv;
+	struct yam_port *yp = netdev_priv(dev);
 
 	skb_queue_tail(&yp->send_queue, skb);
 	dev->trans_start = jiffies;
@@ -592,12 +592,11 @@
 
 static void yam_arbitrate(struct net_device *dev)
 {
-	struct yam_port *yp = dev->priv;
+	struct yam_port *yp = netdev_priv(dev);
 
-	if (!yp || yp->magic != YAM_MAGIC
-		|| yp->tx_state != TX_OFF || skb_queue_empty(&yp->send_queue)) {
+	if (yp->magic != YAM_MAGIC || yp->tx_state != TX_OFF ||
+	    skb_queue_empty(&yp->send_queue))
 		return;
-	}
 	/* tx_state is TX_OFF and there is data to send */
 
 	if (yp->dupmode) {
@@ -725,7 +724,7 @@
 
 	for (i = 0; i < NR_PORTS; i++) {
 		dev = yam_devs[i];
-		yp = dev->priv;
+		yp = netdev_priv(dev);
 
 		if (!netif_running(dev))
 			continue;
@@ -784,8 +783,8 @@
 
 static int yam_seq_show(struct seq_file *seq, void *v)
 {
-	const struct net_device *dev = v;
-	const struct yam_port *yp = dev->priv;
+	struct net_device *dev = v;
+	const struct yam_port *yp = netdev_priv(dev);
 
 	seq_printf(seq, "Device %s\n", dev->name);
 	seq_printf(seq, "  Up       %d\n", netif_running(dev));
@@ -838,10 +837,10 @@
 {
 	struct yam_port *yp;
 
-	if (!dev || !dev->priv)
+	if (!dev)
 		return NULL;
 
-	yp = (struct yam_port *) dev->priv;
+	yp = netdev_priv(dev);
 	if (yp->magic != YAM_MAGIC)
 		return NULL;
 
@@ -856,14 +855,14 @@
 
 static int yam_open(struct net_device *dev)
 {
-	struct yam_port *yp = (struct yam_port *) dev->priv;
+	struct yam_port *yp = netdev_priv(dev);
 	enum uart u;
 	int i;
 	int ret=0;
 
 	printk(KERN_INFO "Trying %s at iobase 0x%lx irq %u\n", dev->name, dev->base_addr, dev->irq);
 
-	if (!dev || !yp || !yp->bitrate)
+	if (!dev || !yp->bitrate)
 		return -ENXIO;
 	if (!dev->base_addr || dev->base_addr > 0x1000 - YAM_EXTENT ||
 		dev->irq < 2 || dev->irq > 15) {
@@ -900,7 +899,7 @@
 	/* Reset overruns for all ports - FPGA programming makes overruns */
 	for (i = 0; i < NR_PORTS; i++) {
 		struct net_device *dev = yam_devs[i];
-		struct yam_port *yp = dev->priv;
+		struct yam_port *yp = netdev_priv(dev);
 		inb(LSR(dev->base_addr));
 		yp->stats.rx_fifo_errors = 0;
 	}
@@ -919,10 +918,11 @@
 static int yam_close(struct net_device *dev)
 {
 	struct sk_buff *skb;
-	struct yam_port *yp = (struct yam_port *) dev->priv;
+	struct yam_port *yp = netdev_priv(dev);
 
-	if (!dev || !yp)
+	if (!dev)
 		return -EINVAL;
+
 	/*
 	 * disable interrupts
 	 */
@@ -944,7 +944,7 @@
 
 static int yam_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 {
-	struct yam_port *yp = (struct yam_port *) dev->priv;
+	struct yam_port *yp = netdev_priv(dev);
 	struct yamdrv_ioctl_cfg yi;
 	struct yamdrv_ioctl_mcs *ym;
 	int ioctl_cmd;
@@ -952,7 +952,7 @@
 	if (copy_from_user(&ioctl_cmd, ifr->ifr_data, sizeof(int)))
 		 return -EFAULT;
 
-	if (yp == NULL || yp->magic != YAM_MAGIC)
+	if (yp->magic != YAM_MAGIC)
 		return -EINVAL;
 
 	if (!capable(CAP_NET_ADMIN))
@@ -1091,7 +1091,7 @@
 
 static void yam_setup(struct net_device *dev)
 {
-	struct yam_port *yp = dev->priv;
+	struct yam_port *yp = netdev_priv(dev);
 
 	yp->magic = YAM_MAGIC;
 	yp->bitrate = DEFAULT_BITRATE;
diff -Nru a/drivers/net/ibm_emac/ibm_emac.h b/drivers/net/ibm_emac/ibm_emac.h
--- a/drivers/net/ibm_emac/ibm_emac.h	2005-03-11 12:51:52 -08:00
+++ b/drivers/net/ibm_emac/ibm_emac.h	2005-03-11 12:51:52 -08:00
@@ -237,6 +237,10 @@
 #define EMAC_RWMR_DEFAULT		0x1000a200
 #define EMAC_TMR0_DEFAULT		EMAC_TMR0_TFAE_2_32
 #define EMAC_TMR1_DEFAULT		0xa00f0000
+#elif defined(CONFIG_440SP)
+#define EMAC_RWMR_DEFAULT		0x08002000
+#define EMAC_TMR0_DEFAULT		EMAC_TMR0_TFAE_128_2048
+#define EMAC_TMR1_DEFAULT		0xf8200000
 #else
 #define EMAC_RWMR_DEFAULT		0x0f002000
 #define EMAC_TMR0_DEFAULT		0x00000000
diff -Nru a/drivers/net/ibm_emac/ibm_emac_core.c b/drivers/net/ibm_emac/ibm_emac_core.c
--- a/drivers/net/ibm_emac/ibm_emac_core.c	2005-03-11 12:51:41 -08:00
+++ b/drivers/net/ibm_emac/ibm_emac_core.c	2005-03-11 12:51:41 -08:00
@@ -1041,7 +1041,7 @@
 	/* set speed (default is 10Mb) */
 	switch (speed) {
 	case SPEED_1000:
-		mode_reg |= EMAC_M1_JUMBO_ENABLE | EMAC_M1_RFS_16K;
+		mode_reg |= EMAC_M1_RFS_16K;
 		if (fep->rgmii_dev) {
 			struct ibm_ocp_rgmii *rgmii = RGMII_PRIV(fep->rgmii_dev);
 
@@ -1118,6 +1118,7 @@
 {
 	struct ocp_enet_private *fep = dev->priv;
 	int old_mtu = dev->mtu;
+	unsigned long mode_reg;
 	emac_t *emacp = fep->emacp;
 	u32 em0mr0;
 	int i, full;
@@ -1160,10 +1161,17 @@
 			fep->rx_skb[i] = NULL;
 		}
 
-		/* Set new rx_buffer_size and advertise new mtu */
-		fep->rx_buffer_size =
-		    new_mtu + ENET_HEADER_SIZE + ENET_FCS_SIZE;
+		/* Set new rx_buffer_size, jumbo cap, and advertise new mtu */
+		mode_reg = in_be32(&emacp->em0mr1);
+		if (new_mtu > ENET_DEF_MTU_SIZE) {
+			mode_reg |= EMAC_M1_JUMBO_ENABLE;
+			fep->rx_buffer_size = EMAC_MAX_FRAME;
+		} else {
+			mode_reg &= ~EMAC_M1_JUMBO_ENABLE;
+			fep->rx_buffer_size = ENET_DEF_BUF_SIZE;
+		}
 		dev->mtu = new_mtu;
+		out_be32(&emacp->em0mr1, mode_reg);
 
 		/* Re-init rx skbs */
 		fep->rx_slot = 0;
diff -Nru a/drivers/net/ibm_emac/ibm_emac_core.h b/drivers/net/ibm_emac/ibm_emac_core.h
--- a/drivers/net/ibm_emac/ibm_emac_core.h	2005-03-11 12:51:41 -08:00
+++ b/drivers/net/ibm_emac/ibm_emac_core.h	2005-03-11 12:51:41 -08:00
@@ -77,6 +77,8 @@
 
 #define ENET_HEADER_SIZE	14
 #define ENET_FCS_SIZE		4
+#define ENET_DEF_MTU_SIZE	1500
+#define ENET_DEF_BUF_SIZE	(ENET_DEF_MTU_SIZE + ENET_HEADER_SIZE + ENET_FCS_SIZE)
 #define EMAC_MIN_FRAME		64
 #define EMAC_MAX_FRAME		9018
 #define EMAC_MIN_MTU		(EMAC_MIN_FRAME - ENET_HEADER_SIZE - ENET_FCS_SIZE)
diff -Nru a/drivers/net/ibmlana.c b/drivers/net/ibmlana.c
--- a/drivers/net/ibmlana.c	2005-03-11 12:51:41 -08:00
+++ b/drivers/net/ibmlana.c	2005-03-11 12:51:41 -08:00
@@ -133,13 +133,14 @@
 
 static void dumpmem(struct net_device *dev, u32 start, u32 len)
 {
+	ibmlana_priv *priv = netdev_priv(dev);
 	int z;
 
 	printk("Address %04x:\n", start);
 	for (z = 0; z < len; z++) {
 		if ((z & 15) == 0)
 			printk("%04x:", z);
-		printk(" %02x", isa_readb(dev->mem_start + start + z));
+		printk(" %02x", readb(priv->base + start + z));
 		if ((z & 15) == 15)
 			printk("\n");
 	}
@@ -231,7 +232,7 @@
 
 static void InitDscrs(struct net_device *dev)
 {
-	ibmlana_priv *priv = (ibmlana_priv *) dev->priv;
+	ibmlana_priv *priv = netdev_priv(dev);
 	u32 addr, baddr, raddr;
 	int z;
 	tda_t tda;
@@ -240,8 +241,8 @@
 
 	/* initialize RAM */
 
-	isa_memset_io(dev->mem_start, 0xaa,
-		      dev->mem_start - dev->mem_start);
+	memset_io(priv->base, 0xaa,
+		      dev->mem_start - dev->mem_start);	/* XXX: typo? */
 
 	/* setup n TX descriptors - independent of RAM size */
 
@@ -260,7 +261,7 @@
 		else
 			tda.link = addr + sizeof(tda_t);
 		tda.link |= 1;
-		isa_memcpy_toio(dev->mem_start + addr, &tda, sizeof(tda_t));
+		memcpy_toio(priv->base + addr, &tda, sizeof(tda_t));
 		addr += sizeof(tda_t);
 		baddr += PKTSIZE;
 	}
@@ -280,7 +281,7 @@
 		rra.starthi = 0;
 		rra.cntlo = PKTSIZE >> 1;
 		rra.cnthi = 0;
-		isa_memcpy_toio(dev->mem_start + raddr, &rra, sizeof(rra_t));
+		memcpy_toio(priv->base + raddr, &rra, sizeof(rra_t));
 
 		rda.status = 0;
 		rda.length = 0;
@@ -292,7 +293,7 @@
 		else
 			rda.link = 1;
 		rda.inuse = 1;
-		isa_memcpy_toio(dev->mem_start + addr, &rda, sizeof(rda_t));
+		memcpy_toio(priv->base + addr, &rda, sizeof(rda_t));
 
 		baddr += PKTSIZE;
 		raddr += sizeof(rra_t);
@@ -313,7 +314,7 @@
 
 static int InitSONIC(struct net_device *dev)
 {
-	ibmlana_priv *priv = (ibmlana_priv *) dev->priv;
+	ibmlana_priv *priv = netdev_priv(dev);
 
 	/* set up start & end of resource area */
 
@@ -379,6 +380,7 @@
 
 static void InitBoard(struct net_device *dev)
 {
+	ibmlana_priv *priv = netdev_priv(dev);
 	int camcnt;
 	camentry_t cams[16];
 	u32 cammask;
@@ -429,8 +431,8 @@
 
 	/* feed CDA into SONIC, initialize RCR value (always get broadcasts) */
 
-	isa_memcpy_toio(dev->mem_start, cams, sizeof(camentry_t) * camcnt);
-	isa_memcpy_toio(dev->mem_start + (sizeof(camentry_t) * camcnt), &cammask, sizeof(cammask));
+	memcpy_toio(priv->base, cams, sizeof(camentry_t) * camcnt);
+	memcpy_toio(priv->base + (sizeof(camentry_t) * camcnt), &cammask, sizeof(cammask));
 
 #ifdef DEBUG
 	printk("CAM setup:\n");
@@ -520,7 +522,7 @@
 
 static void StartTx(struct net_device *dev, int descr)
 {
-	ibmlana_priv *priv = (ibmlana_priv *) dev->priv;
+	ibmlana_priv *priv = netdev_priv(dev);
 	int addr;
 
 	addr = priv->tdastart + (descr * sizeof(tda_t));
@@ -543,7 +545,7 @@
 
 static void irqrbe_handler(struct net_device *dev)
 {
-	ibmlana_priv *priv = (ibmlana_priv *) dev->priv;
+	ibmlana_priv *priv = netdev_priv(dev);
 
 	/* point the SONIC back to the RRA start */
 
@@ -555,7 +557,7 @@
 
 static void irqrx_handler(struct net_device *dev)
 {
-	ibmlana_priv *priv = (ibmlana_priv *) dev->priv;
+	ibmlana_priv *priv = netdev_priv(dev);
 	rda_t rda;
 	u32 rdaaddr, lrdaaddr;
 
@@ -566,7 +568,7 @@
 
 		rdaaddr = priv->rdastart + (priv->nextrxdescr * sizeof(rda_t));
 		lrdaaddr = priv->rdastart + (priv->lastrxdescr * sizeof(rda_t));
-		isa_memcpy_fromio(&rda, dev->mem_start + rdaaddr, sizeof(rda_t));
+		memcpy_fromio(&rda, priv->base + rdaaddr, sizeof(rda_t));
 
 		/* iron out upper word halves of fields we use - SONIC will duplicate 
 		   bits 0..15 to 16..31 */
@@ -593,8 +595,8 @@
 			else {
 				/* copy out data */
 
-				isa_memcpy_fromio(skb_put(skb, rda.length),
-					       dev->mem_start +
+				memcpy_fromio(skb_put(skb, rda.length),
+					       priv->base +
 					       rda.startlo, rda.length);
 
 				/* set up skb fields */
@@ -627,14 +629,14 @@
 
 		rda.link = 1;
 		rda.inuse = 1;
-		isa_memcpy_toio(dev->mem_start + rdaaddr, &rda,
+		memcpy_toio(priv->base + rdaaddr, &rda,
 			     sizeof(rda_t));
 
 		/* set up link and EOL = 0 in currently last descriptor. Only write
 		   the link field since the SONIC may currently already access the
 		   other fields. */
 
-		isa_memcpy_toio(dev->mem_start + lrdaaddr + 20, &rdaaddr, 4);
+		memcpy_toio(priv->base + lrdaaddr + 20, &rdaaddr, 4);
 
 		/* advance indices */
 
@@ -648,11 +650,11 @@
 
 static void irqtx_handler(struct net_device *dev)
 {
-	ibmlana_priv *priv = (ibmlana_priv *) dev->priv;
+	ibmlana_priv *priv = netdev_priv(dev);
 	tda_t tda;
 
 	/* fetch descriptor (we forgot the size ;-) */
-	isa_memcpy_fromio(&tda, dev->mem_start + priv->tdastart + (priv->currtxdescr * sizeof(tda_t)), sizeof(tda_t));
+	memcpy_fromio(&tda, priv->base + priv->tdastart + (priv->currtxdescr * sizeof(tda_t)), sizeof(tda_t));
 
 	/* update statistics */
 	priv->stat.tx_packets++;
@@ -672,11 +674,11 @@
 
 static void irqtxerr_handler(struct net_device *dev)
 {
-	ibmlana_priv *priv = (ibmlana_priv *) dev->priv;
+	ibmlana_priv *priv = netdev_priv(dev);
 	tda_t tda;
 
 	/* fetch descriptor to check status */
-	isa_memcpy_fromio(&tda, dev->mem_start + priv->tdastart + (priv->currtxdescr * sizeof(tda_t)), sizeof(tda_t));
+	memcpy_fromio(&tda, priv->base + priv->tdastart + (priv->currtxdescr * sizeof(tda_t)), sizeof(tda_t));
 
 	/* update statistics */
 	priv->stat.tx_errors++;
@@ -753,9 +755,7 @@
 
 	if (dev == NULL)
 		return len;
-	if (dev->priv == NULL)
-		return len;
-	priv = (ibmlana_priv *) dev->priv;
+	priv = netdev_priv(dev);
 
 	/* print info */
 
@@ -778,7 +778,7 @@
 static int ibmlana_open(struct net_device *dev)
 {
 	int result;
-	ibmlana_priv *priv = (ibmlana_priv *) dev->priv;
+	ibmlana_priv *priv = netdev_priv(dev);
 
 	/* register resources - only necessary for IRQ */
 
@@ -814,7 +814,7 @@
 
 static int ibmlana_tx(struct sk_buff *skb, struct net_device *dev)
 {
-	ibmlana_priv *priv = (ibmlana_priv *) dev->priv;
+	ibmlana_priv *priv = netdev_priv(dev);
 	int retval = 0, tmplen, addr;
 	unsigned long flags;
 	tda_t tda;
@@ -834,7 +834,7 @@
 	if (tmplen < 60)
 		tmplen = 60;
 	baddr = priv->txbufstart + (priv->nexttxdescr * PKTSIZE);
-	isa_memcpy_toio(dev->mem_start + baddr, skb->data, skb->len);
+	memcpy_toio(priv->base + baddr, skb->data, skb->len);
 
 	/* copy filler into RAM - in case we're filling up... 
 	   we're filling a bit more than necessary, but that doesn't harm
@@ -846,16 +846,16 @@
 		unsigned int destoffs = skb->len, l = strlen(fill);
 
 		while (destoffs < tmplen) {
-			isa_memcpy_toio(dev->mem_start + baddr + destoffs, fill, l);
+			memcpy_toio(priv->base + baddr + destoffs, fill, l);
 			destoffs += l;
 		}
 	}
 
 	/* set up the new frame descriptor */
 	addr = priv->tdastart + (priv->nexttxdescr * sizeof(tda_t));
-	isa_memcpy_fromio(&tda, dev->mem_start + addr, sizeof(tda_t));
+	memcpy_fromio(&tda, priv->base + addr, sizeof(tda_t));
 	tda.length = tda.fraglength = tmplen;
-	isa_memcpy_toio(dev->mem_start + addr, &tda, sizeof(tda_t));
+	memcpy_toio(priv->base + addr, &tda, sizeof(tda_t));
 
 	/* if there were no active descriptors, trigger the SONIC */
 	spin_lock_irqsave(&priv->lock, flags);
@@ -881,7 +881,7 @@
 
 static struct net_device_stats *ibmlana_stats(struct net_device *dev)
 {
-	ibmlana_priv *priv = (ibmlana_priv *) dev->priv;
+	ibmlana_priv *priv = netdev_priv(dev);
 	return &priv->stat;
 }
 
@@ -903,7 +903,6 @@
 
 static int ibmlana_probe(struct net_device *dev)
 {
-	int force_detect = 0;
 	int slot, z;
 	int base = 0, irq = 0, iobase = 0, memlen = 0;
 	ibmlana_priv *priv;
@@ -915,10 +914,6 @@
 	if (MCA_bus == 0)
 		return -ENODEV;
 
-	/* start address of 1 --> forced detection */
-	if (dev->mem_start == 1)
-		force_detect = 1;
-
 	base = dev->mem_start;
 	irq = dev->irq;
 
@@ -952,18 +947,12 @@
 		return -EBUSY;
 	}
 
-	/* make procfs entries */
-	mca_set_adapter_name(slot, "IBM LAN Adapter/A");
-	mca_set_adapter_procfn(slot, (MCA_ProcFn) ibmlana_getinfo, dev);
-
-	mca_mark_as_used(slot);
-
-	/* allocate structure */
-	priv = dev->priv;
+	priv = netdev_priv(dev);
 	priv->slot = slot;
 	priv->realirq = irq;
 	priv->medium = medium;
 	spin_lock_init(&priv->lock);
+		
 
 	/* set base + irq for this device (irq not allocated so far) */
 
@@ -972,6 +961,20 @@
 	dev->mem_end = base + memlen;
 	dev->base_addr = iobase;
 
+	priv->base = ioremap(base, memlen);
+	if (!priv->base) {
+		printk(KERN_ERR "%s: cannot remap memory!\n", DRV_NAME);
+		startslot = slot + 1;
+		release_region(iobase, IBM_LANA_IORANGE);
+		return -EBUSY;
+	}
+
+	/* make procfs entries */
+	mca_set_adapter_name(slot, "IBM LAN Adapter/A");
+	mca_set_adapter_procfn(slot, (MCA_ProcFn) ibmlana_getinfo, dev);
+
+	mca_mark_as_used(slot);
+
 	/* set methods */
 
 	dev->open = ibmlana_open;
@@ -1042,11 +1045,12 @@
 			break;
 		}
 		if (register_netdev(dev)) {
-			ibmlana_priv *priv = dev->priv;
+			ibmlana_priv *priv = netdev_priv(dev);
 			release_region(dev->base_addr, IBM_LANA_IORANGE);
 			mca_mark_as_unused(priv->slot);
 			mca_set_adapter_name(priv->slot, "");
 			mca_set_adapter_procfn(priv->slot, NULL, NULL);
+			iounmap(priv->base);
 			free_netdev(dev);
 			break;
 		}
@@ -1061,13 +1065,14 @@
 	for (z = 0; z < DEVMAX; z++) {
 		struct net_device *dev = moddevs[z];
 		if (dev) {
-			ibmlana_priv *priv = (ibmlana_priv *) dev->priv;
+			ibmlana_priv *priv = netdev_priv(dev);
 			unregister_netdev(dev);
 			/*DeinitBoard(dev); */
 			release_region(dev->base_addr, IBM_LANA_IORANGE);
 			mca_mark_as_unused(priv->slot);
 			mca_set_adapter_name(priv->slot, "");
 			mca_set_adapter_procfn(priv->slot, NULL, NULL);
+			iounmap(priv->base);
 			free_netdev(dev);
 		}
 	}
diff -Nru a/drivers/net/ibmlana.h b/drivers/net/ibmlana.h
--- a/drivers/net/ibmlana.h	2005-03-11 12:51:51 -08:00
+++ b/drivers/net/ibmlana.h	2005-03-11 12:51:51 -08:00
@@ -37,6 +37,7 @@
 		nexttxdescr,		/* last tx descriptor to be used    */
 		currtxdescr,		/* tx descriptor currently tx'ed    */
 		txused[TXBUFCNT];	/* busy flags                       */
+	void __iomem *base;
 	spinlock_t lock;
 } ibmlana_priv;
 
diff -Nru a/drivers/net/ioc3-eth.c b/drivers/net/ioc3-eth.c
--- a/drivers/net/ioc3-eth.c	2005-03-11 12:51:41 -08:00
+++ b/drivers/net/ioc3-eth.c	2005-03-11 12:51:41 -08:00
@@ -56,7 +56,6 @@
 #include <linux/etherdevice.h>
 #include <linux/ethtool.h>
 #include <linux/skbuff.h>
-#include <linux/dp83840.h>
 #include <net/ip.h>
 
 #include <asm/byteorder.h>
@@ -463,6 +462,29 @@
 	printk(".\n");
 }
 
+static void __ioc3_set_mac_address(struct net_device *dev)
+{
+	struct ioc3_private *ip = netdev_priv(dev);
+	struct ioc3 *ioc3 = ip->regs;
+
+	ioc3_w_emar_h((dev->dev_addr[5] <<  8) | dev->dev_addr[4]);
+	ioc3_w_emar_l((dev->dev_addr[3] << 24) | (dev->dev_addr[2] << 16) |
+	              (dev->dev_addr[1] <<  8) | dev->dev_addr[0]);
+}
+
+static int ioc3_set_mac_address(struct net_device *dev, void *addr)
+{
+	struct ioc3_private *ip = netdev_priv(dev);
+	struct sockaddr *sa = addr;
+
+	memcpy(dev->dev_addr, sa->sa_data, dev->addr_len);
+
+	spin_lock_irq(&ip->ioc3_lock);
+	__ioc3_set_mac_address(dev);
+	spin_unlock_irq(&ip->ioc3_lock);
+
+	return 0;
+}
 
 /*
  * Caller must hold the ioc3_lock ever for MII readers.  This is also
@@ -1014,9 +1036,7 @@
 	(void) ioc3_r_etcdc();			/* Clear on read */
 	ioc3_w_ercsr(15);			/* RX low watermark  */
 	ioc3_w_ertr(0);				/* Interrupt immediately */
-	ioc3_w_emar_h((dev->dev_addr[5] <<  8) | dev->dev_addr[4]);
-	ioc3_w_emar_l((dev->dev_addr[3] << 24) | (dev->dev_addr[2] << 16) |
-	              (dev->dev_addr[1] <<  8) | dev->dev_addr[0]);
+	__ioc3_set_mac_address(dev);
 	ioc3_w_ehar_h(ip->ehar_h);
 	ioc3_w_ehar_l(ip->ehar_l);
 	ioc3_w_ersr(42);			/* XXX should be random */
@@ -1100,6 +1120,7 @@
 	       && dev->device == PCI_DEVICE_ID_SGI_IOC3;
 }
 
+#ifdef CONFIG_SERIAL_8250
 /*
  * Note about serial ports and consoles:
  * For console output, everyone uses the IOC3 UARTA (offset 0x178)
@@ -1121,15 +1142,14 @@
  * "device" routine referred to in this console structure
  * (ip27prom_console_dev).
  *
- * Also look in ip27-pci.c:pci_fixuop_ioc3() for some comments on working
+ * Also look in ip27-pci.c:pci_fixup_ioc3() for some comments on working
  * around ioc3 oddities in this respect.
  *
  * The IOC3 serials use a 22MHz clock rate with an additional divider by 3.
  * (IOC3_BAUD = (22000000 / (3*16)))
  */
 
-static inline void ioc3_serial_probe(struct pci_dev *pdev,
-				struct ioc3 *ioc3)
+static void __devinit ioc3_serial_probe(struct pci_dev *pdev, struct ioc3 *ioc3)
 {
 	struct serial_struct req;
 
@@ -1160,9 +1180,9 @@
 	req.iomem_base      = (unsigned char *) &ioc3->sregs.uartb;
 	register_serial(&req);
 }
+#endif
 
-static int __devinit ioc3_probe(struct pci_dev *pdev,
-	                        const struct pci_device_id *ent)
+static int ioc3_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
 	unsigned int sw_physid1, sw_physid2;
 	struct net_device *dev = NULL;
@@ -1170,11 +1190,39 @@
 	struct ioc3 *ioc3;
 	unsigned long ioc3_base, ioc3_size;
 	u32 vendor, model, rev;
-	int err;
+	int err, pci_using_dac;
+
+	/* Configure DMA attributes. */
+	err = pci_set_dma_mask(pdev, 0xffffffffffffffffULL);
+	if (!err) {
+		pci_using_dac = 1;
+		err = pci_set_consistent_dma_mask(pdev, 0xffffffffffffffffULL);
+		if (err < 0) {
+			printk(KERN_ERR "%s: Unable to obtain 64 bit DMA "
+			       "for consistent allocations\n", pci_name(pdev));
+			goto out;
+		}
+	} else {
+		err = pci_set_dma_mask(pdev, 0xffffffffULL);
+		if (err) {
+			printk(KERN_ERR "%s: No usable DMA configuration, "
+			       "aborting.\n", pci_name(pdev));
+			goto out;
+		}
+		pci_using_dac = 0;
+	}
+
+	if (pci_enable_device(pdev))
+		return -ENODEV;
 
 	dev = alloc_etherdev(sizeof(struct ioc3_private));
-	if (!dev)
-		return -ENOMEM;
+	if (!dev) {
+		err = -ENOMEM;
+		goto out_disable;
+	}
+
+	if (pci_using_dac)
+		dev->features |= NETIF_F_HIGHDMA;
 
 	err = pci_request_regions(pdev, "ioc3");
 	if (err)
@@ -1237,6 +1285,7 @@
 	dev->get_stats		= ioc3_get_stats;
 	dev->do_ioctl		= ioc3_ioctl;
 	dev->set_multicast_list	= ioc3_set_multicast_list;
+	dev->set_mac_address	= ioc3_set_mac_address;
 	dev->ethtool_ops	= &ioc3_ethtool_ops;
 #ifdef CONFIG_SGI_IOC3_ETH_HW_TX_CSUM
 	dev->features		= NETIF_F_IP_CSUM;
@@ -1269,6 +1318,12 @@
 	pci_release_regions(pdev);
 out_free:
 	free_netdev(dev);
+out_disable:
+	/*
+	 * We should call pci_disable_device(pdev); here if the IOC3 wasn't
+	 * such a weird device ...
+	 */
+out:
 	return err;
 }
 
@@ -1282,6 +1337,10 @@
 	iounmap(ioc3);
 	pci_release_regions(pdev);
 	free_netdev(dev);
+	/*
+	 * We should call pci_disable_device(pdev); here if the IOC3 wasn't
+	 * such a weird device ...
+	 */
 }
 
 static struct pci_device_id ioc3_pci_tbl[] = {
diff -Nru a/drivers/net/irda/act200l-sir.c b/drivers/net/irda/act200l-sir.c
--- a/drivers/net/irda/act200l-sir.c	2005-03-11 12:51:42 -08:00
+++ b/drivers/net/irda/act200l-sir.c	2005-03-11 12:51:42 -08:00
@@ -177,8 +177,7 @@
 
 	/* Write control bytes */
 	sirdev_raw_write(dev, control, 3);
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	schedule_timeout(msecs_to_jiffies(5));
+	msleep(5);
 
 	/* Go back to normal mode */
 	sirdev_set_dtr_rts(dev, TRUE, TRUE);
diff -Nru a/drivers/net/irda/donauboe.c b/drivers/net/irda/donauboe.c
--- a/drivers/net/irda/donauboe.c	2005-03-11 12:51:43 -08:00
+++ b/drivers/net/irda/donauboe.c	2005-03-11 12:51:43 -08:00
@@ -1712,7 +1712,7 @@
 }
 
 static int
-toshoboe_gotosleep (struct pci_dev *pci_dev, u32 crap)
+toshoboe_gotosleep (struct pci_dev *pci_dev, pm_message_t crap)
 {
   struct toshoboe_cb *self = (struct toshoboe_cb*)pci_get_drvdata(pci_dev);
   unsigned long flags;
diff -Nru a/drivers/net/irda/irda-usb.c b/drivers/net/irda/irda-usb.c
--- a/drivers/net/irda/irda-usb.c	2005-03-11 12:51:46 -08:00
+++ b/drivers/net/irda/irda-usb.c	2005-03-11 12:51:46 -08:00
@@ -998,7 +998,7 @@
 		struct urb *urb = self->rx_urb[i];
 		struct sk_buff *skb = (struct sk_buff *) urb->context;
 		/* Cancel the receive command */
-		usb_unlink_urb(urb);
+		usb_kill_urb(urb);
 		/* The skb is ours, free it */
 		if(skb) {
 			dev_kfree_skb(skb);
@@ -1308,7 +1308,7 @@
 		IU_REQ_GET_CLASS_DESC,
 		USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
 		0, intf->altsetting->desc.bInterfaceNumber, desc,
-		sizeof(*desc), msecs_to_jiffies(500));
+		sizeof(*desc), 500);
 	
 	IRDA_DEBUG(1, "%s(), ret=%d\n", __FUNCTION__, ret);
 	if (ret < sizeof(*desc)) {
@@ -1367,12 +1367,12 @@
 	if (!net) 
 		goto err_out;
 
+	SET_MODULE_OWNER(net);
+	SET_NETDEV_DEV(net, &intf->dev);
 	self = net->priv;
 	self->netdev = net;
 	spin_lock_init(&self->lock);
 
-	SET_MODULE_OWNER(net);
-
 	/* Create all of the needed urbs */
 	for (i = 0; i < IU_MAX_RX_URBS; i++) {
 		self->rx_urb[i] = usb_alloc_urb(0, GFP_KERNEL);
@@ -1516,7 +1516,7 @@
 		netif_stop_queue(self->netdev);
 		/* Stop all the receive URBs */
 		for (i = 0; i < IU_MAX_RX_URBS; i++)
-			usb_unlink_urb(self->rx_urb[i]);
+			usb_kill_urb(self->rx_urb[i]);
 		/* Cancel Tx and speed URB.
 		 * Toggle flags to make sure it's synchronous. */
 		self->tx_urb->transfer_flags &= ~URB_ASYNC_UNLINK;
diff -Nru a/drivers/net/irda/irport.c b/drivers/net/irda/irport.c
--- a/drivers/net/irda/irport.c	2005-03-11 12:51:47 -08:00
+++ b/drivers/net/irda/irport.c	2005-03-11 12:51:47 -08:00
@@ -87,50 +87,14 @@
 static int irport_change_speed_complete(struct irda_task *task);
 static void irport_timeout(struct net_device *dev);
 
-EXPORT_SYMBOL(irport_open);
-EXPORT_SYMBOL(irport_close);
-EXPORT_SYMBOL(irport_start);
-EXPORT_SYMBOL(irport_stop);
-EXPORT_SYMBOL(irport_interrupt);
-EXPORT_SYMBOL(irport_hard_xmit);
-EXPORT_SYMBOL(irport_timeout);
-EXPORT_SYMBOL(irport_change_speed);
-EXPORT_SYMBOL(irport_net_open);
-EXPORT_SYMBOL(irport_net_close);
+static irqreturn_t irport_interrupt(int irq, void *dev_id,
+				    struct pt_regs *regs);
+static int irport_hard_xmit(struct sk_buff *skb, struct net_device *dev);
+static void irport_change_speed(void *priv, __u32 speed);
+static int irport_net_open(struct net_device *dev);
+static int irport_net_close(struct net_device *dev);
 
-static int __init irport_init(void)
-{
- 	int i;
-
- 	for (i=0; (io[i] < 2000) && (i < 4); i++) {
- 		if (irport_open(i, io[i], irq[i]) != NULL)
- 			return 0;
- 	}
-	/* 
-	 * Maybe something failed, but we can still be usable for FIR drivers 
-	 */
- 	return 0;
-}
-
-/*
- * Function irport_cleanup ()
- *
- *    Close all configured ports
- *
- */
-static void __exit irport_cleanup(void)
-{
- 	int i;
-
-        IRDA_DEBUG( 4, "%s()\n", __FUNCTION__);
-
-	for (i=0; i < 4; i++) {
- 		if (dev_self[i])
- 			irport_close(dev_self[i]);
- 	}
-}
-
-struct irport_cb *
+static struct irport_cb *
 irport_open(int i, unsigned int iobase, unsigned int irq)
 {
 	struct net_device *dev;
@@ -254,7 +218,7 @@
 	return NULL;
 }
 
-int irport_close(struct irport_cb *self)
+static int irport_close(struct irport_cb *self)
 {
 	ASSERT(self != NULL, return -1;);
 
@@ -285,40 +249,40 @@
 	return 0;
 }
 
-void irport_start(struct irport_cb *self)
+static void irport_stop(struct irport_cb *self)
 {
 	int iobase;
 
 	iobase = self->io.sir_base;
 
-	irport_stop(self);
-	
 	/* We can't lock, we may be called from a FIR driver - Jean II */
 
-	/* Initialize UART */
-	outb(UART_LCR_WLEN8, iobase+UART_LCR);  /* Reset DLAB */
-	outb((UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2), iobase+UART_MCR);
+	/* We are not transmitting any more */
+	self->transmitting = 0;
+
+	/* Reset UART */
+	outb(0, iobase+UART_MCR);
 	
-	/* Turn on interrups */
-	outb(UART_IER_RLSI | UART_IER_RDI |UART_IER_THRI, iobase+UART_IER);
+	/* Turn off interrupts */
+	outb(0, iobase+UART_IER);
 }
 
-void irport_stop(struct irport_cb *self)
+static void irport_start(struct irport_cb *self)
 {
 	int iobase;
 
 	iobase = self->io.sir_base;
 
+	irport_stop(self);
+	
 	/* We can't lock, we may be called from a FIR driver - Jean II */
 
-	/* We are not transmitting any more */
-	self->transmitting = 0;
-
-	/* Reset UART */
-	outb(0, iobase+UART_MCR);
+	/* Initialize UART */
+	outb(UART_LCR_WLEN8, iobase+UART_LCR);  /* Reset DLAB */
+	outb((UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2), iobase+UART_MCR);
 	
-	/* Turn off interrupts */
-	outb(0, iobase+UART_IER);
+	/* Turn on interrups */
+	outb(UART_IER_RLSI | UART_IER_RDI |UART_IER_THRI, iobase+UART_IER);
 }
 
 /*
@@ -368,7 +332,7 @@
  *
  * This function should be called with irq off and spin-lock.
  */
-void irport_change_speed(void *priv, __u32 speed)
+static void irport_change_speed(void *priv, __u32 speed)
 {
 	struct irport_cb *self = (struct irport_cb *) priv;
 	int iobase; 
@@ -619,7 +583,7 @@
  *    waits until the next transmitt interrupt, and continues until the
  *    frame is transmitted.
  */
-int irport_hard_xmit(struct sk_buff *skb, struct net_device *dev)
+static int irport_hard_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct irport_cb *self;
 	unsigned long flags;
@@ -814,7 +778,8 @@
  *
  *    Interrupt handler
  */
-irqreturn_t irport_interrupt(int irq, void *dev_id, struct pt_regs *regs) 
+static irqreturn_t irport_interrupt(int irq, void *dev_id,
+				    struct pt_regs *regs) 
 {
 	struct net_device *dev = (struct net_device *) dev_id;
 	struct irport_cb *self;
@@ -888,7 +853,7 @@
  *    Network device is taken up. Usually this is done by "ifconfig irda0 up" 
  *   
  */
-int irport_net_open(struct net_device *dev)
+static int irport_net_open(struct net_device *dev)
 {
 	struct irport_cb *self;
 	int iobase;
@@ -941,7 +906,7 @@
  *    Network device is taken down. Usually this is done by 
  *    "ifconfig irda0 down" 
  */
-int irport_net_close(struct net_device *dev)
+static int irport_net_close(struct net_device *dev)
 {
 	struct irport_cb *self;
 	int iobase;
@@ -1132,6 +1097,38 @@
 	struct irport_cb *self = (struct irport_cb *) dev->priv;
 	
 	return &self->stats;
+}
+
+static int __init irport_init(void)
+{
+ 	int i;
+
+ 	for (i=0; (io[i] < 2000) && (i < 4); i++) {
+ 		if (irport_open(i, io[i], irq[i]) != NULL)
+ 			return 0;
+ 	}
+	/* 
+	 * Maybe something failed, but we can still be usable for FIR drivers 
+	 */
+ 	return 0;
+}
+
+/*
+ * Function irport_cleanup ()
+ *
+ *    Close all configured ports
+ *
+ */
+static void __exit irport_cleanup(void)
+{
+ 	int i;
+
+        IRDA_DEBUG( 4, "%s()\n", __FUNCTION__);
+
+	for (i=0; i < 4; i++) {
+ 		if (dev_self[i])
+ 			irport_close(dev_self[i]);
+ 	}
 }
 
 MODULE_PARM(io, "1-4i");
diff -Nru a/drivers/net/irda/irport.h b/drivers/net/irda/irport.h
--- a/drivers/net/irda/irport.h	2005-03-11 12:51:47 -08:00
+++ b/drivers/net/irda/irport.h	2005-03-11 12:51:47 -08:00
@@ -77,14 +77,4 @@
 	int (*interrupt)(int irq, void *dev_id, struct pt_regs *regs);
 };
 
-struct irport_cb *irport_open(int i, unsigned int iobase, unsigned int irq);
-int  irport_close(struct irport_cb *self);
-void irport_start(struct irport_cb *self);
-void irport_stop(struct irport_cb *self);
-void irport_change_speed(void *priv, __u32 speed);
-irqreturn_t irport_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-int  irport_hard_xmit(struct sk_buff *skb, struct net_device *dev);
-int  irport_net_open(struct net_device *dev);
-int  irport_net_close(struct net_device *dev);
-
 #endif /* IRPORT_H */
diff -Nru a/drivers/net/irda/irtty-sir.c b/drivers/net/irda/irtty-sir.c
--- a/drivers/net/irda/irtty-sir.c	2005-03-11 12:51:40 -08:00
+++ b/drivers/net/irda/irtty-sir.c	2005-03-11 12:51:40 -08:00
@@ -32,6 +32,7 @@
 #include <linux/init.h>
 #include <asm/uaccess.h>
 #include <linux/smp_lock.h>
+#include <linux/delay.h>
 
 #include <net/irda/irda.h>
 #include <net/irda/irda_device.h>
@@ -97,8 +98,7 @@
 		unlock_kernel();
 	}
 	else {
-		set_task_state(current, TASK_UNINTERRUPTIBLE);
-		schedule_timeout(msecs_to_jiffies(USBSERIAL_TX_DONE_DELAY));
+		msleep(USBSERIAL_TX_DONE_DELAY);
 	}
 }
 
@@ -413,7 +413,7 @@
 
 /* ------------------------------------------------------- */
 
-struct sir_driver sir_tty_drv = {
+static struct sir_driver sir_tty_drv = {
 	.owner			= THIS_MODULE,
 	.driver_name		= "sir_tty",
 	.start_dev		= irtty_start_dev,
diff -Nru a/drivers/net/irda/ma600-sir.c b/drivers/net/irda/ma600-sir.c
--- a/drivers/net/irda/ma600-sir.c	2005-03-11 12:51:47 -08:00
+++ b/drivers/net/irda/ma600-sir.c	2005-03-11 12:51:47 -08:00
@@ -191,8 +191,7 @@
 	sirdev_raw_write(dev, &byte, sizeof(byte));
 
 	/* Wait at least 10ms: fake wait_until_sent - 10 bits at 9600 baud*/
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	schedule_timeout(msecs_to_jiffies(15));		/* old ma600 uses 15ms */
+	msleep(15);					/* old ma600 uses 15ms */
 
 #if 1
 	/* read-back of the control byte. ma600 is the first dongle driver
@@ -215,8 +214,7 @@
 	sirdev_set_dtr_rts(dev, TRUE, TRUE);
 
 	/* Wait at least 10ms */
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	schedule_timeout(msecs_to_jiffies(10));
+	msleep(10);
 
 	/* dongle is now switched to the new speed */
 	dev->speed = speed;
@@ -245,13 +243,11 @@
 
 	/* Reset the dongle : set DTR low for 10 ms */
 	sirdev_set_dtr_rts(dev, FALSE, TRUE);
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	schedule_timeout(msecs_to_jiffies(10));
+	msleep(10);
 
 	/* Go back to normal mode */
 	sirdev_set_dtr_rts(dev, TRUE, TRUE);
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	schedule_timeout(msecs_to_jiffies(10));
+	msleep(10);
 
 	dev->speed = 9600;      /* That's the dongle-default */
 
diff -Nru a/drivers/net/irda/nsc-ircc.c b/drivers/net/irda/nsc-ircc.c
--- a/drivers/net/irda/nsc-ircc.c	2005-03-11 12:51:52 -08:00
+++ b/drivers/net/irda/nsc-ircc.c	2005-03-11 12:51:52 -08:00
@@ -94,16 +94,13 @@
 	  nsc_ircc_probe_108, nsc_ircc_init_108 },
 	{ "PC87338", { 0x398, 0x15c, 0x2e }, 0x08, 0xb0, 0xf8, 
 	  nsc_ircc_probe_338, nsc_ircc_init_338 },
+	/* Contributed by Steffen Pingel - IBM X40 */
+	{ "PC8738x", { 0x164e, 0x4e, 0x0 }, 0x20, 0xf4, 0xff,
+	  nsc_ircc_probe_39x, nsc_ircc_init_39x },
 	/* Contributed by Jan Frey - IBM A30/A31 */
 	{ "PC8739x", { 0x2e, 0x4e, 0x0 }, 0x20, 0xea, 0xff, 
 	  nsc_ircc_probe_39x, nsc_ircc_init_39x },
 	{ NULL }
-#if 0
-	/* Probably bogus, "PC8739x" should be the real thing. Jean II */
-	/* Contributed by Kevin Thayer - OmniBook 6100 */
-	{ "PC87338?", { 0x2e, 0x15c, 0x398 }, 0x08, 0x00, 0xf8, 
-	  nsc_ircc_probe_338, nsc_ircc_init_338 },
-#endif
 };
 
 /* Max 4 instances for now */
diff -Nru a/drivers/net/irda/sir_dev.c b/drivers/net/irda/sir_dev.c
--- a/drivers/net/irda/sir_dev.c	2005-03-11 12:51:47 -08:00
+++ b/drivers/net/irda/sir_dev.c	2005-03-11 12:51:47 -08:00
@@ -15,6 +15,7 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/smp_lock.h>
+#include <linux/delay.h>
 
 #include <net/irda/irda.h>
 #include <net/irda/wrapper.h>
@@ -73,8 +74,7 @@
 	spin_lock_irqsave(&dev->tx_lock, flags);	/* serialize with other tx operations */
 	while (dev->tx_buff.len > 0) {			/* wait until tx idle */
 		spin_unlock_irqrestore(&dev->tx_lock, flags);
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		schedule_timeout(msecs_to_jiffies(10));
+		msleep(10);
 		spin_lock_irqsave(&dev->tx_lock, flags);
 	}
 
diff -Nru a/drivers/net/irda/smsc-ircc2.c b/drivers/net/irda/smsc-ircc2.c
--- a/drivers/net/irda/smsc-ircc2.c	2005-03-11 12:51:47 -08:00
+++ b/drivers/net/irda/smsc-ircc2.c	2005-03-11 12:51:47 -08:00
@@ -203,7 +203,7 @@
 
 /* Transceivers for SMSC-ircc */
 
-smsc_transceiver_t smsc_transceivers[]=
+static smsc_transceiver_t smsc_transceivers[]=
 {
 	{ "Toshiba Satellite 1800 (GP data pin select)", smsc_ircc_set_transceiver_toshiba_sat1800, smsc_ircc_probe_transceiver_toshiba_sat1800},
 	{ "Fast pin select", smsc_ircc_set_transceiver_smsc_ircc_fast_pin_select, smsc_ircc_probe_transceiver_smsc_ircc_fast_pin_select},
diff -Nru a/drivers/net/irda/stir4200.c b/drivers/net/irda/stir4200.c
--- a/drivers/net/irda/stir4200.c	2005-03-11 12:51:42 -08:00
+++ b/drivers/net/irda/stir4200.c	2005-03-11 12:51:42 -08:00
@@ -208,7 +208,7 @@
 			       REQ_WRITE_SINGLE,
 			       USB_DIR_OUT|USB_TYPE_VENDOR|USB_RECIP_DEVICE,
 			       value, reg, NULL, 0,
-			       msecs_to_jiffies(CTRL_TIMEOUT));
+			       CTRL_TIMEOUT);
 }
 
 /* Send control message to read multiple registers */
@@ -221,7 +221,7 @@
 			       REQ_READ_REG,
 			       USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
 			       0, reg, data, count,
-			       msecs_to_jiffies(CTRL_TIMEOUT));
+			       CTRL_TIMEOUT);
 }
 
 static inline int isfir(u32 speed)
@@ -671,7 +671,8 @@
 		return;
 
 	do_gettimeofday(&now);
-	us -= (now.tv_sec - stir->rx_time.tv_sec) * USEC_PER_SEC;
+	if (now.tv_sec - stir->rx_time.tv_sec > 0)
+		us -= USEC_PER_SEC;
 	us -= now.tv_usec - stir->rx_time.tv_usec;
 	if (us < 10)
 		return;
@@ -740,7 +741,7 @@
 
 	if (usb_bulk_msg(stir->usbdev, usb_sndbulkpipe(stir->usbdev, 1),
 			 stir->io_buf, wraplen,
-			 NULL, msecs_to_jiffies(TRANSMIT_TIMEOUT)))
+			 NULL, TRANSMIT_TIMEOUT))
 		stir->stats.tx_errors++;
 }
 
@@ -787,7 +788,7 @@
 				stir_send(stir, skb);
 			dev_kfree_skb(skb);
 
-			if (stir->speed != new_speed) {
+			if ((new_speed != -1) && (stir->speed != new_speed)) {
 				if (fifo_txwait(stir, -1) ||
 				    change_speed(stir, new_speed))
 					break;
diff -Nru a/drivers/net/irda/tekram-sir.c b/drivers/net/irda/tekram-sir.c
--- a/drivers/net/irda/tekram-sir.c	2005-03-11 12:51:42 -08:00
+++ b/drivers/net/irda/tekram-sir.c	2005-03-11 12:51:42 -08:00
@@ -210,8 +210,7 @@
 	sirdev_set_dtr_rts(dev, FALSE, TRUE); 
 
 	/* Should sleep 1 ms */
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	schedule_timeout(msecs_to_jiffies(1));
+	msleep(1);
 
 	/* Set DTR, Set RTS */
 	sirdev_set_dtr_rts(dev, TRUE, TRUE);
diff -Nru a/drivers/net/irda/via-ircc.c b/drivers/net/irda/via-ircc.c
--- a/drivers/net/irda/via-ircc.c	2005-03-11 12:51:40 -08:00
+++ b/drivers/net/irda/via-ircc.c	2005-03-11 12:51:40 -08:00
@@ -83,7 +83,7 @@
 
 /* Some prototypes */
 static int via_ircc_open(int i, chipio_t * info, unsigned int id);
-static int __exit via_ircc_close(struct via_ircc_cb *self);
+static int via_ircc_close(struct via_ircc_cb *self);
 static int via_ircc_dma_receive(struct via_ircc_cb *self);
 static int via_ircc_dma_receive_complete(struct via_ircc_cb *self,
 					 int iobase);
@@ -111,7 +111,7 @@
 static int via_ircc_dma_xmit(struct via_ircc_cb *self, u16 iobase);
 static int upload_rxdata(struct via_ircc_cb *self, int iobase);
 static int __devinit via_init_one (struct pci_dev *pcidev, const struct pci_device_id *id);
-static void __exit via_remove_one (struct pci_dev *pdev);
+static void __devexit via_remove_one (struct pci_dev *pdev);
 
 /* FIXME : Should use udelay() instead, even if we are x86 only - Jean II */
 static void iodelay(int udelay)
@@ -140,7 +140,7 @@
 	.name		= VIA_MODULE_NAME,
 	.id_table	= via_pci_tbl,
 	.probe		= via_init_one,
-	.remove		= via_remove_one,
+	.remove		= __devexit_p(via_remove_one),
 };
 
 
@@ -273,7 +273,7 @@
  *    Close all configured chips
  *
  */
-static void __exit via_ircc_clean(void)
+static void via_ircc_clean(void)
 {
 	int i;
 
@@ -285,7 +285,7 @@
 	}
 }
 
-static void __exit via_remove_one (struct pci_dev *pdev)
+static void __devexit via_remove_one (struct pci_dev *pdev)
 {
 	IRDA_DEBUG(3, "%s()\n", __FUNCTION__);
 
@@ -468,7 +468,7 @@
  *    Close driver instance
  *
  */
-static int __exit via_ircc_close(struct via_ircc_cb *self)
+static int via_ircc_close(struct via_ircc_cb *self)
 {
 	int iobase;
 
diff -Nru a/drivers/net/ixgb/ixgb.h b/drivers/net/ixgb/ixgb.h
--- a/drivers/net/ixgb/ixgb.h	2005-03-11 12:51:42 -08:00
+++ b/drivers/net/ixgb/ixgb.h	2005-03-11 12:51:42 -08:00
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   
-  Copyright(c) 1999 - 2004 Intel Corporation. All rights reserved.
+  Copyright(c) 1999 - 2005 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 
@@ -176,6 +176,7 @@
 	uint64_t hw_csum_tx_error;
 	uint32_t tx_int_delay;
 	boolean_t tx_int_delay_enable;
+	boolean_t detect_tx_hung;
 
 	/* RX */
 	struct ixgb_desc_ring rx_ring;
diff -Nru a/drivers/net/ixgb/ixgb_ee.c b/drivers/net/ixgb/ixgb_ee.c
--- a/drivers/net/ixgb/ixgb_ee.c	2005-03-11 12:51:52 -08:00
+++ b/drivers/net/ixgb/ixgb_ee.c	2005-03-11 12:51:52 -08:00
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   
-  Copyright(c) 1999 - 2004 Intel Corporation. All rights reserved.
+  Copyright(c) 1999 - 2005 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 
@@ -372,11 +372,11 @@
  *
  *****************************************************************************/
 void
-ixgb_write_eeprom(struct ixgb_hw *hw,
-		   uint16_t offset,
-		   uint16_t data)
+ixgb_write_eeprom(struct ixgb_hw *hw, uint16_t offset, uint16_t data)
 {
-	/*  Prepare the EEPROM for writing  */
+	struct ixgb_ee_map_type *ee_map = (struct ixgb_ee_map_type *)hw->eeprom;
+
+	/* Prepare the EEPROM for writing */
 	ixgb_setup_eeprom(hw);
 
 	/*  Send the 9-bit EWEN (write enable) command to the EEPROM (5-bit opcode
@@ -410,6 +410,9 @@
 	/*  Done with writing  */
 	ixgb_cleanup_eeprom(hw);
 
+	/* clear the init_ctrl_reg_1 to signify that the cache is invalidated */
+	ee_map->init_ctrl_reg_1 = EEPROM_ICW1_SIGNATURE_CLEAR;
+
 	return;
 }
 
@@ -478,6 +481,9 @@
 
 	if (checksum != (uint16_t) EEPROM_SUM) {
 		DEBUGOUT("ixgb_ee: Checksum invalid.\n");
+		/* clear the init_ctrl_reg_1 to signify that the cache is
+		 * invalidated */
+		ee_map->init_ctrl_reg_1 = EEPROM_ICW1_SIGNATURE_CLEAR;
 		return (FALSE);
 	}
 
diff -Nru a/drivers/net/ixgb/ixgb_ee.h b/drivers/net/ixgb/ixgb_ee.h
--- a/drivers/net/ixgb/ixgb_ee.h	2005-03-11 12:51:46 -08:00
+++ b/drivers/net/ixgb/ixgb_ee.h	2005-03-11 12:51:46 -08:00
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   
-  Copyright(c) 1999 - 2004 Intel Corporation. All rights reserved.
+  Copyright(c) 1999 - 2005 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 
@@ -63,6 +63,7 @@
 
 #define EEPROM_ICW1_SIGNATURE_MASK  0xC000
 #define EEPROM_ICW1_SIGNATURE_VALID 0x4000
+#define EEPROM_ICW1_SIGNATURE_CLEAR 0x0000
 
 /* For checksumming, the sum of all words in the EEPROM should equal 0xBABA. */
 #define EEPROM_SUM 0xBABA
diff -Nru a/drivers/net/ixgb/ixgb_ethtool.c b/drivers/net/ixgb/ixgb_ethtool.c
--- a/drivers/net/ixgb/ixgb_ethtool.c	2005-03-11 12:51:51 -08:00
+++ b/drivers/net/ixgb/ixgb_ethtool.c	2005-03-11 12:51:51 -08:00
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   
-  Copyright(c) 1999 - 2004 Intel Corporation. All rights reserved.
+  Copyright(c) 1999 - 2005 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 
@@ -63,6 +63,7 @@
 	{"tx_dropped", IXGB_STAT(net_stats.tx_dropped)},
 	{"multicast", IXGB_STAT(net_stats.multicast)},
 	{"collisions", IXGB_STAT(net_stats.collisions)},
+
 /*	{ "rx_length_errors", IXGB_STAT(net_stats.rx_length_errors) },	*/
 	{"rx_over_errors", IXGB_STAT(net_stats.rx_over_errors)},
 	{"rx_crc_errors", IXGB_STAT(net_stats.rx_crc_errors)},
@@ -98,6 +99,7 @@
 ixgb_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
 {
 	struct ixgb_adapter *adapter = netdev->priv;
+
 	ecmd->supported = (SUPPORTED_10000baseT_Full | SUPPORTED_FIBRE);
 	ecmd->advertising = (SUPPORTED_10000baseT_Full | SUPPORTED_FIBRE);
 	ecmd->port = PORT_FIBRE;
@@ -119,6 +121,7 @@
 ixgb_set_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
 {
 	struct ixgb_adapter *adapter = netdev->priv;
+
 	if(ecmd->autoneg == AUTONEG_ENABLE ||
 	   ecmd->speed + ecmd->duplex != SPEED_10000 + DUPLEX_FULL)
 		return -EINVAL;
diff -Nru a/drivers/net/ixgb/ixgb_hw.c b/drivers/net/ixgb/ixgb_hw.c
--- a/drivers/net/ixgb/ixgb_hw.c	2005-03-11 12:51:47 -08:00
+++ b/drivers/net/ixgb/ixgb_hw.c	2005-03-11 12:51:47 -08:00
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   
-  Copyright(c) 1999 - 2004 Intel Corporation. All rights reserved.
+  Copyright(c) 1999 - 2005 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 
diff -Nru a/drivers/net/ixgb/ixgb_hw.h b/drivers/net/ixgb/ixgb_hw.h
--- a/drivers/net/ixgb/ixgb_hw.h	2005-03-11 12:51:40 -08:00
+++ b/drivers/net/ixgb/ixgb_hw.h	2005-03-11 12:51:40 -08:00
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   
-  Copyright(c) 1999 - 2004 Intel Corporation. All rights reserved.
+  Copyright(c) 1999 - 2005 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 
diff -Nru a/drivers/net/ixgb/ixgb_ids.h b/drivers/net/ixgb/ixgb_ids.h
--- a/drivers/net/ixgb/ixgb_ids.h	2005-03-11 12:51:46 -08:00
+++ b/drivers/net/ixgb/ixgb_ids.h	2005-03-11 12:51:46 -08:00
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   
-  Copyright(c) 1999 - 2004 Intel Corporation. All rights reserved.
+  Copyright(c) 1999 - 2005 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 
diff -Nru a/drivers/net/ixgb/ixgb_main.c b/drivers/net/ixgb/ixgb_main.c
--- a/drivers/net/ixgb/ixgb_main.c	2005-03-11 12:51:52 -08:00
+++ b/drivers/net/ixgb/ixgb_main.c	2005-03-11 12:51:52 -08:00
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   
-  Copyright(c) 1999 - 2004 Intel Corporation. All rights reserved.
+  Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
   
   This program is free software; you can redistribute it and/or modify it 
   under the terms of the GNU General Public License as published by the Free 
@@ -29,6 +29,9 @@
 #include "ixgb.h"
 
 /* Change Log
+ * 1.0.88 01/05/05
+ * - include fix to the condition that determines when to quit NAPI - Robert Olsson
+ * - use netif_poll_{disable/enable} to synchronize between NAPI and i/f up/down
  * 1.0.84 10/26/04
  * - reset buffer_info->dma in Tx resource cleanup logic
  * 1.0.83 10/12/04
@@ -38,13 +41,14 @@
 
 char ixgb_driver_name[] = "ixgb";
 char ixgb_driver_string[] = "Intel(R) PRO/10GbE Network Driver";
+
 #ifndef CONFIG_IXGB_NAPI
 #define DRIVERNAPI
 #else
 #define DRIVERNAPI "-NAPI"
 #endif
-char ixgb_driver_version[] = "1.0.87-k2"DRIVERNAPI;
-char ixgb_copyright[] = "Copyright (c) 1999-2004 Intel Corporation.";
+char ixgb_driver_version[] = "1.0.90-k2"DRIVERNAPI;
+char ixgb_copyright[] = "Copyright (c) 1999-2005 Intel Corporation.";
 
 /* ixgb_pci_tbl - PCI Device ID Table
  *
@@ -292,6 +296,9 @@
 	mod_timer(&adapter->watchdog_timer, jiffies);
 	ixgb_irq_enable(adapter);
 
+#ifdef CONFIG_IXGB_NAPI
+	netif_poll_enable(netdev);
+#endif
 	return 0;
 }
 
@@ -309,6 +316,9 @@
 #endif
 	if(kill_watchdog)
 		del_timer_sync(&adapter->watchdog_timer);
+#ifdef CONFIG_IXGB_NAPI
+	netif_poll_disable(netdev);
+#endif
 	adapter->link_speed = 0;
 	adapter->link_duplex = 0;
 	netif_carrier_off(netdev);
@@ -709,14 +719,8 @@
 	IXGB_WRITE_REG(hw, TDH, 0);
 	IXGB_WRITE_REG(hw, TDT, 0);
 
-	/* don't set up txdctl, it induces performance problems if
-	 * configured incorrectly
-	 txdctl  = TXDCTL_PTHRESH_DEFAULT; // prefetch txds below this threshold
-	 txdctl |= (TXDCTL_HTHRESH_DEFAULT // only prefetch if there are this many ready
-	 << IXGB_TXDCTL_HTHRESH_SHIFT);
-	 IXGB_WRITE_REG (hw, TXDCTL, txdctl);
-	 */
-
+	/* don't set up txdctl, it induces performance problems if configured
+	 * incorrectly */
 	/* Set the Tx Interrupt Delay register */
 
 	IXGB_WRITE_REG(hw, TIDV, adapter->tx_int_delay);
@@ -849,10 +853,17 @@
 	IXGB_WRITE_REG(hw, RDH, 0);
 	IXGB_WRITE_REG(hw, RDT, 0);
 
-						/* burst 16 or burst when RXT0*/
-	rxdctl =  RXDCTL_WTHRESH_DEFAULT << IXGB_RXDCTL_WTHRESH_SHIFT 
-			| RXDCTL_HTHRESH_DEFAULT << IXGB_RXDCTL_HTHRESH_SHIFT 
-			| RXDCTL_PTHRESH_DEFAULT << IXGB_RXDCTL_PTHRESH_SHIFT;
+	/* set up pre-fetching of receive buffers so we get some before we
+	 * run out (default hardware behavior is to run out before fetching
+	 * more).  This sets up to fetch if HTHRESH rx descriptors are avail
+	 * and the descriptors in hw cache are below PTHRESH.  This avoids
+	 * the hardware behavior of fetching <=512 descriptors in a single
+	 * burst that pre-empts all other activity, usually causing fifo
+	 * overflows. */
+	/* use WTHRESH to burst write 16 descriptors or burst when RXT0 */
+	rxdctl = RXDCTL_WTHRESH_DEFAULT << IXGB_RXDCTL_WTHRESH_SHIFT |
+	         RXDCTL_HTHRESH_DEFAULT << IXGB_RXDCTL_HTHRESH_SHIFT |
+	         RXDCTL_PTHRESH_DEFAULT << IXGB_RXDCTL_PTHRESH_SHIFT;
 	IXGB_WRITE_REG(hw, RXDCTL, rxdctl);
 
 	/* Enable Receive Checksum Offload for TCP and UDP */
@@ -1094,7 +1105,6 @@
 	struct ixgb_adapter *adapter = (struct ixgb_adapter *)data;
 	struct net_device *netdev = adapter->netdev;
 	struct ixgb_desc_ring *txdr = &adapter->tx_ring;
-	unsigned int i;
 
 	ixgb_check_for_link(&adapter->hw);
 
@@ -1137,12 +1147,8 @@
 		}
 	}
 
-	/* Early detection of hung controller */
-	i = txdr->next_to_clean;
-	if(txdr->buffer_info[i].dma &&
-	   time_after(jiffies, txdr->buffer_info[i].time_stamp + HZ) &&
-	   !(IXGB_READ_REG(&adapter->hw, STATUS) & IXGB_STATUS_TXOFF))
-		netif_stop_queue(netdev);
+	/* Force detection of hung controller every watchdog period */
+	adapter->detect_tx_hung = TRUE;
 
 	/* generate an interrupt to force clean up of any stragglers */
 	IXGB_WRITE_REG(&adapter->hw, ICS, IXGB_INT_TXDW);
@@ -1155,7 +1161,7 @@
 #define IXGB_TX_FLAGS_VLAN		0x00000002
 #define IXGB_TX_FLAGS_TSO		0x00000004
 
-static inline boolean_t
+static inline int
 ixgb_tso(struct ixgb_adapter *adapter, struct sk_buff *skb)
 {
 #ifdef NETIF_F_TSO
@@ -1163,8 +1169,15 @@
 	unsigned int i;
 	uint8_t ipcss, ipcso, tucss, tucso, hdr_len;
 	uint16_t ipcse, tucse, mss;
+	int err;
 
 	if(likely(skb_shinfo(skb)->tso_size)) {
+		if (skb_header_cloned(skb)) {
+			err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC);
+			if (err)
+				return err;
+		}
+
 		hdr_len = ((skb->h.raw - skb->data) + (skb->h.th->doff << 2));
 		mss = skb_shinfo(skb)->tso_size;
 		skb->nh.iph->tot_len = 0;
@@ -1203,11 +1216,11 @@
 		if(++i == adapter->tx_ring.count) i = 0;
 		adapter->tx_ring.next_to_use = i;
 
-		return TRUE;
+		return 1;
 	}
 #endif
 
-	return FALSE;
+	return 0;
 }
 
 static inline boolean_t
@@ -1378,6 +1391,7 @@
 	unsigned int tx_flags = 0;
 	unsigned long flags;
 	int vlan_id = 0;
+	int tso;
 
 	if(skb->len <= 0) {
 		dev_kfree_skb_any(skb);
@@ -1399,7 +1413,13 @@
 
 	first = adapter->tx_ring.next_to_use;
 	
-	if(ixgb_tso(adapter, skb))
+	tso = ixgb_tso(adapter, skb);
+	if (tso < 0) {
+		dev_kfree_skb_any(skb);
+		return NETDEV_TX_OK;
+	}
+
+	if (tso)
 		tx_flags |= IXGB_TX_FLAGS_TSO;
 	else if(ixgb_tx_csum(adapter, skb))
 		tx_flags |= IXGB_TX_FLAGS_CSUM;
@@ -1668,20 +1688,16 @@
 	int work_to_do = min(*budget, netdev->quota);
 	int tx_cleaned;
 	int work_done = 0;
-	
-	if (!netif_carrier_ok(netdev))
-		goto quit_polling;
 
 	tx_cleaned = ixgb_clean_tx_irq(adapter);
 	ixgb_clean_rx_irq(adapter, &work_done, work_to_do);
 
 	*budget -= work_done;
 	netdev->quota -= work_done;
-	
-	/* if no Tx cleanup and not enough Rx work done, exit the polling mode */
-	if((!tx_cleaned && (work_done < work_to_do)) || 
-				!netif_running(netdev)) {
-quit_polling:	netif_rx_complete(netdev);
+
+	/* if no Tx and not enough Rx work done, exit the polling mode */
+	if((!tx_cleaned && (work_done == 0)) || !netif_running(netdev)) {
+		netif_rx_complete(netdev);
 		ixgb_irq_enable(adapter);
 		return 0;
 	}
@@ -1741,6 +1757,17 @@
 		netif_wake_queue(netdev);
 	}
 	spin_unlock(&adapter->tx_lock);
+
+	if(adapter->detect_tx_hung) {
+		/* detect a transmit hang in hardware, this serializes the
+		 * check with the clearing of time_stamp and movement of i */
+		adapter->detect_tx_hung = FALSE;
+		if(tx_ring->buffer_info[i].dma &&
+		   time_after(jiffies, tx_ring->buffer_info[i].time_stamp + HZ)
+		   && !(IXGB_READ_REG(&adapter->hw, STATUS) &
+			IXGB_STATUS_TXOFF))
+			netif_stop_queue(netdev);
+	}
 
 	return cleaned;
 }
diff -Nru a/drivers/net/ixgb/ixgb_osdep.h b/drivers/net/ixgb/ixgb_osdep.h
--- a/drivers/net/ixgb/ixgb_osdep.h	2005-03-11 12:51:47 -08:00
+++ b/drivers/net/ixgb/ixgb_osdep.h	2005-03-11 12:51:47 -08:00
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   
-  Copyright(c) 1999 - 2004 Intel Corporation. All rights reserved.
+  Copyright(c) 1999 - 2005 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 
diff -Nru a/drivers/net/ixgb/ixgb_param.c b/drivers/net/ixgb/ixgb_param.c
--- a/drivers/net/ixgb/ixgb_param.c	2005-03-11 12:51:52 -08:00
+++ b/drivers/net/ixgb/ixgb_param.c	2005-03-11 12:51:52 -08:00
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   
-  Copyright(c) 1999 - 2004 Intel Corporation. All rights reserved.
+  Copyright(c) 1999 - 2005 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 
diff -Nru a/drivers/net/jazzsonic.c b/drivers/net/jazzsonic.c
--- a/drivers/net/jazzsonic.c	2005-03-11 12:51:42 -08:00
+++ b/drivers/net/jazzsonic.c	2005-03-11 12:51:42 -08:00
@@ -14,6 +14,7 @@
  */
 
 #include <linux/kernel.h>
+#include <linux/module.h>
 #include <linux/types.h>
 #include <linux/fcntl.h>
 #include <linux/interrupt.h>
@@ -28,6 +29,7 @@
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
 #include <linux/bitops.h>
+#include <linux/device.h>
 
 #include <asm/bootinfo.h>
 #include <asm/system.h>
@@ -37,7 +39,10 @@
 #include <asm/jazz.h>
 #include <asm/jazzdma.h>
 
-#define DRV_NAME "jazzsonic"
+static char jazz_sonic_string[] = "jazzsonic";
+static struct platform_device *jazz_sonic_device;
+
+#define SONIC_MEM_SIZE	0x100
 
 #define SREGS_PAD(n)    u16 n;
 
@@ -50,8 +55,8 @@
 
 #define SONIC_WRITE(reg,val)						\
 do {									\
-	*((volatile unsigned int *)base_addr+reg) = val;		\
-}
+	*((volatile unsigned int *)base_addr+(reg)) = (val);		\
+} while (0)
 
 
 /* use 0 for production, 1 for verification, >2 for debug */
@@ -80,70 +85,7 @@
 	0xffff			/* end of list */
 };
 
-/* Index to functions, as function prototypes. */
-
-static int sonic_probe1(struct net_device *dev, unsigned int base_addr,
-                        unsigned int irq);
-
-
-/*
- * Probe for a SONIC ethernet controller on a Mips Jazz board.
- * Actually probing is superfluous but we're paranoid.
- */
-struct net_device * __init sonic_probe(int unit)
-{
-	struct net_device *dev;
-	struct sonic_local *lp;
-	unsigned int base_addr;
-	int err = 0;
-	int i;
-
-	/*
-	 * Don't probe if we're not running on a Jazz board.
-	 */
-	if (mips_machgroup != MACH_GROUP_JAZZ)
-		return ERR_PTR(-ENODEV);
-
-	dev = alloc_etherdev(0);
-	if (!dev)
-		return ERR_PTR(-ENOMEM);
-
-	sprintf(dev->name, "eth%d", unit);
-	netdev_boot_setup_check(dev);
-	base_addr = dev->base_addr;
-
-	if (base_addr >= KSEG0)	{ /* Check a single specified location. */
-		err = sonic_probe1(dev, base_addr, dev->irq);
-	} else if (base_addr != 0) { /* Don't probe at all. */
-		err = -ENXIO;
-	} else {
-		for (i = 0; sonic_portlist[i].port; i++) {
-			int io = sonic_portlist[i].port;
-			if (sonic_probe1(dev, io, sonic_portlist[i].irq) == 0)
-				break;
-		}
-		if (!sonic_portlist[i].port)
-			err = -ENODEV;
-	}
-	if (err)
-		goto out;
-	err = register_netdev(dev);
-	if (err)
-		goto out1;
-	return dev;
-out1:
-	lp = dev->priv;
-	vdma_free(lp->rba_laddr);
-	kfree(lp->rba);
-	vdma_free(lp->cda_laddr);
-	kfree(lp);
-	release_region(dev->base_addr, 0x100);
-out:
-	free_netdev(dev);
-	return ERR_PTR(err);
-}
-
-static int __init sonic_probe1(struct net_device *dev, unsigned int base_addr,
+static int __init sonic_probe1(struct net_device *dev, unsigned long base_addr,
                                unsigned int irq)
 {
 	static unsigned version_printed;
@@ -153,7 +95,7 @@
 	int err = -ENODEV;
 	int i;
 
-	if (!request_region(base_addr, 0x100, DRV_NAME))
+	if (!request_mem_region(base_addr, SONIC_MEM_SIZE, jazz_sonic_string))
 		return -EBUSY;
 	/*
 	 * get the Silicon Revision ID. If this is one of the known
@@ -233,7 +175,7 @@
 		memset(lp, 0, sizeof(struct sonic_local));
 
 		/* get the virtual dma address */
-		lp->cda_laddr = vdma_alloc(PHYSADDR(lp),sizeof(*lp));
+		lp->cda_laddr = vdma_alloc(CPHYSADDR(lp),sizeof(*lp));
 		if (lp->cda_laddr == ~0UL) {
 			printk("%s: couldn't get DMA page entry for "
 			       "descriptors\n", dev->name);
@@ -254,7 +196,7 @@
 		}
 
 		/* get virtual dma address */
-		lp->rba_laddr = vdma_alloc(PHYSADDR(lp->rba),
+		lp->rba_laddr = vdma_alloc(CPHYSADDR(lp->rba),
 		                           SONIC_NUM_RRS * SONIC_RBSIZE);
 		if (lp->rba_laddr == ~0UL) {
 			printk("%s: couldn't get DMA page entry for receive "
@@ -291,7 +233,66 @@
 out1:
 	kfree(lp);
 out:
-	release_region(base_addr, 0x100);
+	release_region(base_addr, SONIC_MEM_SIZE);
+	return err;
+}
+
+/*
+ * Probe for a SONIC ethernet controller on a Mips Jazz board.
+ * Actually probing is superfluous but we're paranoid.
+ */
+static int __init jazz_sonic_probe(struct device *device)
+{
+	struct net_device *dev;
+	struct sonic_local *lp;
+	unsigned long base_addr;
+	int err = 0;
+	int i;
+
+	/*
+	 * Don't probe if we're not running on a Jazz board.
+	 */
+	if (mips_machgroup != MACH_GROUP_JAZZ)
+		return -ENODEV;
+
+	dev = alloc_etherdev(0);
+	if (!dev)
+		return -ENOMEM;
+
+	netdev_boot_setup_check(dev);
+	base_addr = dev->base_addr;
+
+	if (base_addr >= KSEG0)	{ /* Check a single specified location. */
+		err = sonic_probe1(dev, base_addr, dev->irq);
+	} else if (base_addr != 0) { /* Don't probe at all. */
+		err = -ENXIO;
+	} else {
+		for (i = 0; sonic_portlist[i].port; i++) {
+			int io = sonic_portlist[i].port;
+			if (sonic_probe1(dev, io, sonic_portlist[i].irq) == 0)
+				break;
+		}
+		if (!sonic_portlist[i].port)
+			err = -ENODEV;
+	}
+	if (err)
+		goto out;
+	err = register_netdev(dev);
+	if (err)
+		goto out1;
+
+	return 0;
+
+out1:
+	lp = dev->priv;
+	vdma_free(lp->rba_laddr);
+	kfree(lp->rba);
+	vdma_free(lp->cda_laddr);
+	kfree(lp);
+	release_region(dev->base_addr, SONIC_MEM_SIZE);
+out:
+	free_netdev(dev);
+
 	return err;
 }
 
@@ -304,3 +305,77 @@
 #define sonic_chiptomem(x)      KSEG1ADDR(vdma_log2phys(x))
 
 #include "sonic.c"
+
+static int __devexit jazz_sonic_device_remove (struct device *device)
+{
+	struct net_device *dev = device->driver_data;
+
+	unregister_netdev (dev);
+	release_region (dev->base_addr, SONIC_MEM_SIZE);
+	free_netdev (dev);
+
+	return 0;
+}
+
+static struct device_driver jazz_sonic_driver = {
+	.name	= jazz_sonic_string,
+	.bus	= &platform_bus_type,
+	.probe	= jazz_sonic_probe,
+	.remove	= __devexit_p(jazz_sonic_device_remove),
+};
+                                                                                
+static void jazz_sonic_platform_release (struct device *device)
+{
+	struct platform_device *pldev;
+
+	/* free device */
+	pldev = to_platform_device (device);
+	kfree (pldev);
+}
+
+static int __init jazz_sonic_init_module(void)
+{
+	struct platform_device *pldev;
+
+	if (driver_register(&jazz_sonic_driver)) {
+		printk(KERN_ERR "Driver registration failed\n");
+		return -ENOMEM;
+	}
+
+	jazz_sonic_device = NULL;
+
+	if (!(pldev = kmalloc (sizeof (*pldev), GFP_KERNEL))) {
+		goto out_unregister;
+	}
+
+	memset(pldev, 0, sizeof (*pldev));
+	pldev->name		= jazz_sonic_string;
+	pldev->id		= 0;
+	pldev->dev.release	= jazz_sonic_platform_release;
+	jazz_sonic_device	= pldev;
+
+	if (platform_device_register (pldev)) {
+		kfree(pldev);
+		jazz_sonic_device = NULL;
+	}
+
+	return 0;
+
+out_unregister:
+	platform_device_unregister(pldev);
+
+	return -ENOMEM;
+}
+
+static void __exit jazz_sonic_cleanup_module(void)
+{
+	driver_unregister(&jazz_sonic_driver);
+
+	if (jazz_sonic_device) {
+		platform_device_unregister(jazz_sonic_device);
+		jazz_sonic_device = NULL;
+	}
+}
+
+module_init(jazz_sonic_init_module);
+module_exit(jazz_sonic_cleanup_module);
diff -Nru a/drivers/net/loopback.c b/drivers/net/loopback.c
--- a/drivers/net/loopback.c	2005-03-11 12:51:41 -08:00
+++ b/drivers/net/loopback.c	2005-03-11 12:51:41 -08:00
@@ -184,7 +184,7 @@
 	return stats;
 }
 
-u32 loopback_get_link(struct net_device *dev)
+static u32 loopback_get_link(struct net_device *dev)
 {
 	return 1;
 }
diff -Nru a/drivers/net/lp486e.c b/drivers/net/lp486e.c
--- a/drivers/net/lp486e.c	2005-03-11 12:51:42 -08:00
+++ b/drivers/net/lp486e.c	2005-03-11 12:51:42 -08:00
@@ -112,8 +112,10 @@
 	CmdDiagnose = 7
 };
 
-char *CUcmdnames[8] = { "NOP", "IASetup", "Configure", "MulticastList",
-			"Tx", "TDR", "Dump", "Diagnose" };
+#if 0
+static const char *CUcmdnames[8] = { "NOP", "IASetup", "Configure", "MulticastList",
+				     "Tx", "TDR", "Dump", "Diagnose" };
+#endif
 
 /* Status word bits */
 #define	STAT_CX		0x8000	/* The CU finished executing a command
@@ -960,7 +962,7 @@
 		(unsigned char) add[12], (unsigned char) add[13]);
 }
 
-int __init lp486e_probe(struct net_device *dev) {
+static int __init lp486e_probe(struct net_device *dev) {
 	struct i596_private *lp;
 	unsigned char eth_addr[6] = { 0, 0xaa, 0, 0, 0, 0 };
 	unsigned char *bios;
diff -Nru a/drivers/net/meth.c b/drivers/net/meth.c
--- a/drivers/net/meth.c	2005-03-11 12:51:52 -08:00
+++ b/drivers/net/meth.c	2005-03-11 12:51:52 -08:00
@@ -27,7 +27,7 @@
 #include <linux/ip.h>          /* struct iphdr */
 #include <linux/tcp.h>         /* struct tcphdr */
 #include <linux/skbuff.h>
-#include <linux/mii.h> /*MII definitions */
+#include <linux/mii.h>         /* MII definitions */
 
 #include <asm/ip32/mace.h>
 #include <asm/ip32/ip32_ints.h>
@@ -105,27 +105,27 @@
 		(int)o2meth_eaddr[3]&0xFF,(int)o2meth_eaddr[4]&0xFF,(int)o2meth_eaddr[5]&0xFF);
 	for (i = 0; i < 6; i++)
 		dev->dev_addr[i] = o2meth_eaddr[i];
-	mace_eth_write((*(u64*)o2meth_eaddr)>>16, mac_addr);
+	mace->eth.mac_addr = (*(unsigned long*)o2meth_eaddr) >> 16;
 }
 
 /*
  * Waits for BUSY status of mdio bus to clear
  */
-#define WAIT_FOR_PHY(___rval)						\
-	while ((___rval = mace_eth_read(phy_data)) & MDIO_BUSY) {	\
-		udelay(25);						\
+#define WAIT_FOR_PHY(___rval)					\
+	while ((___rval = mace->eth.phy_data) & MDIO_BUSY) {	\
+		udelay(25);					\
 	}
 /*read phy register, return value read */
 static unsigned long mdio_read(struct meth_private *priv, unsigned long phyreg)
 {
 	unsigned long rval;
 	WAIT_FOR_PHY(rval);
-	mace_eth_write((priv->phy_addr << 5) | (phyreg & 0x1f), phy_regs);
+	mace->eth.phy_regs = (priv->phy_addr << 5) | (phyreg & 0x1f);
 	udelay(25);
-	mace_eth_write(1, phy_trans_go);
+	mace->eth.phy_trans_go = 1;
 	udelay(25);
 	WAIT_FOR_PHY(rval);
-	return rval&MDIO_DATA_MASK;
+	return rval & MDIO_DATA_MASK;
 }
 
 static int mdio_probe(struct meth_private *priv)
@@ -191,7 +191,7 @@
 			priv->mac_ctrl |= METH_PHY_FDX;
 		else
 			priv->mac_ctrl &= ~METH_PHY_FDX;
-		mace_eth_write(priv->mac_ctrl, mac_ctrl);
+		mace->eth.mac_ctrl = priv->mac_ctrl;
 	}
 
 	if ((priv->mac_ctrl & METH_100MBIT) ^ speed) {
@@ -200,7 +200,7 @@
 			priv->mac_ctrl |= METH_100MBIT;
 		else
 			priv->mac_ctrl &= ~METH_100MBIT;
-		mace_eth_write(priv->mac_ctrl, mac_ctrl);
+		mace->eth.mac_ctrl = priv->mac_ctrl;
 	}
 }
 
@@ -214,26 +214,28 @@
 		return -ENOMEM;
 	memset(priv->tx_ring, 0, TX_RING_BUFFER_SIZE);
 	priv->tx_count = priv->tx_read = priv->tx_write = 0;
-	mace_eth_write(priv->tx_ring_dma, tx_ring_base);
+	mace->eth.tx_ring_base = priv->tx_ring_dma;
 	/* Now init skb save area */
-	memset(priv->tx_skbs,0,sizeof(priv->tx_skbs));
-	memset(priv->tx_skb_dmas,0,sizeof(priv->tx_skb_dmas));
+	memset(priv->tx_skbs, 0, sizeof(priv->tx_skbs));
+	memset(priv->tx_skb_dmas, 0, sizeof(priv->tx_skb_dmas));
 	return 0;
 }
 
 static int meth_init_rx_ring(struct meth_private *priv)
 {
 	int i;
-	for(i=0;i<RX_RING_ENTRIES;i++){
-		priv->rx_skbs[i]=alloc_skb(METH_RX_BUFF_SIZE,0);
-		/* 8byte status vector+3quad padding + 2byte padding,
-		   to put data on 64bit aligned boundary */
+
+	for (i = 0; i < RX_RING_ENTRIES; i++) {
+		priv->rx_skbs[i] = alloc_skb(METH_RX_BUFF_SIZE, 0);
+		/* 8byte status vector + 3quad padding + 2byte padding,
+		 * to put data on 64bit aligned boundary */
 		skb_reserve(priv->rx_skbs[i],METH_RX_HEAD);
 		priv->rx_ring[i]=(rx_packet*)(priv->rx_skbs[i]->head);
 		/* I'll need to re-sync it after each RX */
-		priv->rx_ring_dmas[i]=dma_map_single(NULL,priv->rx_ring[i],
-						     METH_RX_BUFF_SIZE,DMA_FROM_DEVICE);
-		mace_eth_write(priv->rx_ring_dmas[i], rx_fifo);
+		priv->rx_ring_dmas[i] = 
+			dma_map_single(NULL, priv->rx_ring[i],
+				       METH_RX_BUFF_SIZE, DMA_FROM_DEVICE);
+		mace->eth.rx_fifo = priv->rx_ring_dmas[i];
 	}
         priv->rx_write = 0;
 	return 0;
@@ -257,10 +259,11 @@
 {
 	int i;
 
-	for(i=0;i<RX_RING_ENTRIES;i++) {
-		dma_unmap_single(NULL,priv->rx_ring_dmas[i],METH_RX_BUFF_SIZE,DMA_FROM_DEVICE);
-		priv->rx_ring[i]=0;
-		priv->rx_ring_dmas[i]=0;
+	for (i = 0; i < RX_RING_ENTRIES; i++) {
+		dma_unmap_single(NULL, priv->rx_ring_dmas[i],
+				 METH_RX_BUFF_SIZE, DMA_FROM_DEVICE);
+		priv->rx_ring[i] = 0;
+		priv->rx_ring_dmas[i] = 0;
 		kfree_skb(priv->rx_skbs[i]);
 	}
 }
@@ -270,8 +273,9 @@
 	struct meth_private *priv = (struct meth_private *) dev->priv;
 
 	/* Reset card */
-	mace_eth_write(SGI_MAC_RESET, mac_ctrl);
-	mace_eth_write(0, mac_ctrl);
+	mace->eth.mac_ctrl = SGI_MAC_RESET;
+	udelay(1);
+	mace->eth.mac_ctrl = 0;
 	udelay(25);
 
 	/* Load ethernet address */
@@ -279,24 +283,24 @@
 	/* Should load some "errata", but later */
 	
 	/* Check for device */
-	if(mdio_probe(priv) < 0) {
+	if (mdio_probe(priv) < 0) {
 		DPRINTK("Unable to find PHY\n");
 		return -ENODEV;
 	}
 
 	/* Initial mode: 10 | Half-duplex | Accept normal packets */
 	priv->mac_ctrl = METH_ACCEPT_MCAST | METH_DEFAULT_IPG;
-	if(dev->flags | IFF_PROMISC)
+	if (dev->flags | IFF_PROMISC)
 		priv->mac_ctrl |= METH_PROMISC;
-	mace_eth_write(priv->mac_ctrl, mac_ctrl);
+	mace->eth.mac_ctrl = priv->mac_ctrl;
 
 	/* Autonegotiate speed and duplex mode */
 	meth_check_link(dev);
 
 	/* Now set dma control, but don't enable DMA, yet */
-	priv->dma_ctrl= (4 << METH_RX_OFFSET_SHIFT) |
-		(RX_RING_ENTRIES << METH_RX_DEPTH_SHIFT);
-	mace_eth_write(priv->dma_ctrl, dma_ctrl);
+	priv->dma_ctrl = (4 << METH_RX_OFFSET_SHIFT) |
+			 (RX_RING_ENTRIES << METH_RX_DEPTH_SHIFT);
+	mace->eth.dma_ctrl = priv->dma_ctrl;
 
 	return 0;
 }
@@ -335,7 +339,7 @@
 	/* Start DMA */
 	priv->dma_ctrl |= METH_DMA_TX_EN | /*METH_DMA_TX_INT_EN |*/
 			  METH_DMA_RX_EN | METH_DMA_RX_INT_EN;
-	mace_eth_write(priv->dma_ctrl, dma_ctrl);
+	mace->eth.dma_ctrl = priv->dma_ctrl;
 
 	DPRINTK("About to start queue\n");
 	netif_start_queue(dev);
@@ -359,7 +363,7 @@
 	/* shut down DMA */
 	priv->dma_ctrl &= ~(METH_DMA_TX_EN | METH_DMA_TX_INT_EN |
 			    METH_DMA_RX_EN | METH_DMA_RX_INT_EN);
-	mace_eth_write(priv->dma_ctrl, dma_ctrl);
+	mace->eth.dma_ctrl = priv->dma_ctrl;
 	free_irq(dev->irq, dev);
 	meth_free_tx_ring(priv);
 	meth_free_rx_ring(priv);
@@ -373,56 +377,57 @@
 static void meth_rx(struct net_device* dev, unsigned long int_status)
 {
 	struct sk_buff *skb;
+	unsigned long status;
 	struct meth_private *priv = (struct meth_private *) dev->priv;
-	unsigned long fifo_rptr=(int_status&METH_INT_RX_RPTR_MASK)>>8;
+	unsigned long fifo_rptr = (int_status & METH_INT_RX_RPTR_MASK) >> 8;
+
 	spin_lock(&priv->meth_lock);
-	priv->dma_ctrl&=~METH_DMA_RX_INT_EN;
-	mace_eth_write(priv->dma_ctrl, dma_ctrl);
+	priv->dma_ctrl &= ~METH_DMA_RX_INT_EN;
+	mace->eth.dma_ctrl = priv->dma_ctrl;
 	spin_unlock(&priv->meth_lock);
 
-	if (int_status & METH_INT_RX_UNDERFLOW){
-		fifo_rptr=(fifo_rptr-1)&(0xF);
+	if (int_status & METH_INT_RX_UNDERFLOW) {
+		fifo_rptr = (fifo_rptr - 1) & 0x0f;
 	}
-	while(priv->rx_write != fifo_rptr) {
-		u64 status;
-		dma_unmap_single(NULL,priv->rx_ring_dmas[priv->rx_write],
-				 METH_RX_BUFF_SIZE,DMA_FROM_DEVICE);
-		status=priv->rx_ring[priv->rx_write]->status.raw;
+	while (priv->rx_write != fifo_rptr) {
+		dma_unmap_single(NULL, priv->rx_ring_dmas[priv->rx_write],
+				 METH_RX_BUFF_SIZE, DMA_FROM_DEVICE);
+		status = priv->rx_ring[priv->rx_write]->status.raw;
 #if MFE_DEBUG
-		if(!(status&METH_RX_ST_VALID)) {
+		if (!(status & METH_RX_ST_VALID)) {
 			DPRINTK("Not received? status=%016lx\n",status);
 		}
 #endif
-		if((!(status&METH_RX_STATUS_ERRORS))&&(status&METH_RX_ST_VALID)){
-			int len=(status&0xFFFF) - 4; /* omit CRC */
+		if ((!(status & METH_RX_STATUS_ERRORS)) && (status & METH_RX_ST_VALID)) {
+			int len = (status & 0xffff) - 4; /* omit CRC */
 			/* length sanity check */
-			if(len < 60 || len > 1518) {
-				printk(KERN_DEBUG "%s: bogus packet size: %d, status=%#2lx.\n",
+			if (len < 60 || len > 1518) {
+				printk(KERN_DEBUG "%s: bogus packet size: %ld, status=%#2lx.\n",
 				       dev->name, priv->rx_write,
 				       priv->rx_ring[priv->rx_write]->status.raw);
 				priv->stats.rx_errors++;
 				priv->stats.rx_length_errors++;
-				skb=priv->rx_skbs[priv->rx_write];
+				skb = priv->rx_skbs[priv->rx_write];
 			} else {
-				skb=alloc_skb(METH_RX_BUFF_SIZE,GFP_ATOMIC|GFP_DMA);
-				if(!skb){
+				skb = alloc_skb(METH_RX_BUFF_SIZE, GFP_ATOMIC | GFP_DMA);
+				if (!skb) {
 					/* Ouch! No memory! Drop packet on the floor */
 					DPRINTK("No mem: dropping packet\n");
 					priv->stats.rx_dropped++;
-					skb=priv->rx_skbs[priv->rx_write];
+					skb = priv->rx_skbs[priv->rx_write];
 				} else {
-					struct sk_buff *skb_c=priv->rx_skbs[priv->rx_write];
-					/* 8byte status vector+3quad padding + 2byte padding,
-					   to put data on 64bit aligned boundary */
-					skb_reserve(skb,METH_RX_HEAD);
+					struct sk_buff *skb_c = priv->rx_skbs[priv->rx_write];
+					/* 8byte status vector + 3quad padding + 2byte padding,
+					 * to put data on 64bit aligned boundary */
+					skb_reserve(skb, METH_RX_HEAD);
 					/* Write metadata, and then pass to the receive level */
-					skb_put(skb_c,len);
-					priv->rx_skbs[priv->rx_write]=skb;
+					skb_put(skb_c, len);
+					priv->rx_skbs[priv->rx_write] = skb;
 					skb_c->dev = dev;
 					skb_c->protocol = eth_type_trans(skb_c, dev);
 					dev->last_rx = jiffies;
 					priv->stats.rx_packets++;
-					priv->stats.rx_bytes+=len;
+					priv->stats.rx_bytes += len;
 					netif_rx(skb_c);
 				}
 			}
@@ -445,18 +450,19 @@
 				printk(KERN_WARNING "Carrier Event Seen\n");
 #endif
 		}
-		priv->rx_ring[priv->rx_write]=(rx_packet*)skb->head;
-		priv->rx_ring[priv->rx_write]->status.raw=0;
-		priv->rx_ring_dmas[priv->rx_write]=dma_map_single(NULL,priv->rx_ring[priv->rx_write],
-								  METH_RX_BUFF_SIZE,DMA_FROM_DEVICE);
-		mace_eth_write(priv->rx_ring_dmas[priv->rx_write], rx_fifo);
+		priv->rx_ring[priv->rx_write] = (rx_packet*)skb->head;
+		priv->rx_ring[priv->rx_write]->status.raw = 0;
+		priv->rx_ring_dmas[priv->rx_write] = 
+			dma_map_single(NULL, priv->rx_ring[priv->rx_write],
+				       METH_RX_BUFF_SIZE, DMA_FROM_DEVICE);
+		mace->eth.rx_fifo = priv->rx_ring_dmas[priv->rx_write];
 		ADVANCE_RX_PTR(priv->rx_write);
 	}
 	spin_lock(&priv->meth_lock);
 	/* In case there was underflow, and Rx DMA was disabled */
-	priv->dma_ctrl|=METH_DMA_RX_INT_EN|METH_DMA_RX_EN;
-	mace_eth_write(priv->dma_ctrl, dma_ctrl);
-	mace_eth_write(METH_INT_RX_THRESHOLD, int_stat);
+	priv->dma_ctrl |= METH_DMA_RX_INT_EN | METH_DMA_RX_EN;
+	mace->eth.dma_ctrl = priv->dma_ctrl;
+	mace->eth.int_stat = METH_INT_RX_THRESHOLD;
 	spin_unlock(&priv->meth_lock);
 }
 
@@ -464,31 +470,31 @@
 {
 	struct meth_private *priv = (struct meth_private *) dev->priv;
 
-	return(priv->tx_count >= TX_RING_ENTRIES-1);
+	return (priv->tx_count >= TX_RING_ENTRIES - 1);
 }
 
 static void meth_tx_cleanup(struct net_device* dev, unsigned long int_status)
 {
 	struct meth_private *priv = dev->priv;
-	u64 status;
+	unsigned long status;
 	struct sk_buff *skb;
-	unsigned long rptr=(int_status&TX_INFO_RPTR)>>16;
+	unsigned long rptr = (int_status&TX_INFO_RPTR) >> 16;
 
 	spin_lock(&priv->meth_lock);
 
 	/* Stop DMA notification */
 	priv->dma_ctrl &= ~(METH_DMA_TX_INT_EN);
-	mace_eth_write(priv->dma_ctrl, dma_ctrl);
+	mace->eth.dma_ctrl = priv->dma_ctrl;
 
-	while(priv->tx_read != rptr){
+	while (priv->tx_read != rptr) {
 		skb = priv->tx_skbs[priv->tx_read];
 		status = priv->tx_ring[priv->tx_read].header.raw;
 #if MFE_DEBUG>=1
-		if(priv->tx_read==priv->tx_write)
-			DPRINTK("Auchi! tx_read=%d,tx_write=%d,rptr=%d?\n",priv->tx_read,priv->tx_write,rptr);
+		if (priv->tx_read == priv->tx_write)
+			DPRINTK("Auchi! tx_read=%d,tx_write=%d,rptr=%d?\n", priv->tx_read, priv->tx_write,rptr);
 #endif
-		if(status & METH_TX_ST_DONE) {
-			if(status & METH_TX_ST_SUCCESS){
+		if (status & METH_TX_ST_DONE) {
+			if (status & METH_TX_ST_SUCCESS){
 				priv->stats.tx_packets++;
 				priv->stats.tx_bytes += skb->len;
 			} else {
@@ -518,19 +524,19 @@
 		priv->tx_skbs[priv->tx_read] = NULL;
 		priv->tx_ring[priv->tx_read].header.raw = 0;
 		priv->tx_read = (priv->tx_read+1)&(TX_RING_ENTRIES-1);
-		priv->tx_count --;
+		priv->tx_count--;
 	}
 
 	/* wake up queue if it was stopped */
-	if (netif_queue_stopped(dev) && ! meth_tx_full(dev)) {
+	if (netif_queue_stopped(dev) && !meth_tx_full(dev)) {
 		netif_wake_queue(dev);
 	}
 
-	mace_eth_write(METH_INT_TX_EMPTY | METH_INT_TX_PKT, int_stat);
+	mace->eth.int_stat = METH_INT_TX_EMPTY | METH_INT_TX_PKT;
 	spin_unlock(&priv->meth_lock);
 }
 
-static void meth_error(struct net_device* dev, u32 status)
+static void meth_error(struct net_device* dev, unsigned status)
 {
 	struct meth_private *priv = (struct meth_private *) dev->priv;
 
@@ -548,17 +554,16 @@
 	if (status & (METH_INT_RX_UNDERFLOW)) {
 		printk(KERN_WARNING "meth: Rx underflow\n");
 		spin_lock(&priv->meth_lock);
-		mace_eth_write(METH_INT_RX_UNDERFLOW, int_stat);
+		mace->eth.int_stat = METH_INT_RX_UNDERFLOW;
 		/* more underflow interrupts will be delivered, 
-		   effectively throwing us into an infinite loop.
-		   Thus I stop processing Rx in this case.
-		*/
-		priv->dma_ctrl&=~METH_DMA_RX_EN;
-		mace_eth_write(priv->dma_ctrl, dma_ctrl);
+		 * effectively throwing us into an infinite loop.
+		 *  Thus I stop processing Rx in this case. */
+		priv->dma_ctrl &= ~METH_DMA_RX_EN;
+		mace->eth.dma_ctrl = priv->dma_ctrl;
 		DPRINTK("Disabled meth Rx DMA temporarily\n");
 		spin_unlock(&priv->meth_lock);
 	}
-	mace_eth_write(METH_INT_ERROR, int_stat);
+	mace->eth.int_stat = METH_INT_ERROR;
 }
 
 /*
@@ -570,12 +575,12 @@
 	struct meth_private *priv = (struct meth_private *) dev->priv;
 	unsigned long status;
 
-	status = mace_eth_read(int_stat);
-	while (status & 0xFF) {
+	status = mace->eth.int_stat;
+	while (status & 0xff) {
 		/* First handle errors - if we get Rx underflow,
-		   Rx DMA will be disabled, and Rx handler will reenable
-		   it. I don't think it's possible to get Rx underflow,
-		   without getting Rx interrupt */
+		 * Rx DMA will be disabled, and Rx handler will reenable
+		 * it. I don't think it's possible to get Rx underflow,
+		 * without getting Rx interrupt */
 		if (status & METH_INT_ERROR) {
 			meth_error(dev, status);
 		}
@@ -589,7 +594,7 @@
 			/* send it to meth_rx for handling */
 			meth_rx(dev, status);
 		}
-		status = mace_eth_read(int_stat);
+		status = mace->eth.int_stat;
 	}
 
 	return IRQ_HANDLED;
@@ -601,45 +606,45 @@
 static void meth_tx_short_prepare(struct meth_private *priv,
 				  struct sk_buff *skb)
 {
-	tx_packet *desc=&priv->tx_ring[priv->tx_write];
-	int len = (skb->len<ETH_ZLEN)?ETH_ZLEN:skb->len;
+	tx_packet *desc = &priv->tx_ring[priv->tx_write];
+	int len = (skb->len < ETH_ZLEN) ? ETH_ZLEN : skb->len;
 
-	desc->header.raw=METH_TX_CMD_INT_EN|(len-1)|((128-len)<<16);
+	desc->header.raw = METH_TX_CMD_INT_EN | (len-1) | ((128-len) << 16);
 	/* maybe I should set whole thing to 0 first... */
-	memcpy(desc->data.dt+(120-len),skb->data,skb->len);
-	if(skb->len < len)
-		memset(desc->data.dt+120-len+skb->len,0,len-skb->len);
+	memcpy(desc->data.dt + (120 - len), skb->data, skb->len);
+	if (skb->len < len)
+		memset(desc->data.dt + 120 - len + skb->len, 0, len-skb->len);
 }
 #define TX_CATBUF1 BIT(25)
 static void meth_tx_1page_prepare(struct meth_private *priv,
 				  struct sk_buff *skb)
 {
-	tx_packet *desc=&priv->tx_ring[priv->tx_write];
+	tx_packet *desc = &priv->tx_ring[priv->tx_write];
 	void *buffer_data = (void *)(((unsigned long)skb->data + 7) & ~7);
 	int unaligned_len = (int)((unsigned long)buffer_data - (unsigned long)skb->data);
 	int buffer_len = skb->len - unaligned_len;
 	dma_addr_t catbuf;
 
-	desc->header.raw=METH_TX_CMD_INT_EN|TX_CATBUF1|(skb->len-1);
+	desc->header.raw = METH_TX_CMD_INT_EN | TX_CATBUF1 | (skb->len - 1);
 
 	/* unaligned part */
-	if(unaligned_len){
-		memcpy(desc->data.dt+(120-unaligned_len),
+	if (unaligned_len) {
+		memcpy(desc->data.dt + (120 - unaligned_len),
 		       skb->data, unaligned_len);
-		desc->header.raw |= (128-unaligned_len) << 16;
+		desc->header.raw |= (128 - unaligned_len) << 16;
 	}
 
 	/* first page */
 	catbuf = dma_map_single(NULL, buffer_data, buffer_len,
 				DMA_TO_DEVICE);
 	desc->data.cat_buf[0].form.start_addr = catbuf >> 3;
-	desc->data.cat_buf[0].form.len = buffer_len-1;
+	desc->data.cat_buf[0].form.len = buffer_len - 1;
 }
 #define TX_CATBUF2 BIT(26)
 static void meth_tx_2page_prepare(struct meth_private *priv,
 				  struct sk_buff *skb)
 {
-	tx_packet *desc=&priv->tx_ring[priv->tx_write];
+	tx_packet *desc = &priv->tx_ring[priv->tx_write];
 	void *buffer1_data = (void *)(((unsigned long)skb->data + 7) & ~7);
 	void *buffer2_data = (void *)PAGE_ALIGN((unsigned long)skb->data);
 	int unaligned_len = (int)((unsigned long)buffer1_data - (unsigned long)skb->data);
@@ -647,44 +652,44 @@
 	int buffer2_len = skb->len - buffer1_len - unaligned_len;
 	dma_addr_t catbuf1, catbuf2;
 
-	desc->header.raw=METH_TX_CMD_INT_EN|TX_CATBUF1|TX_CATBUF2|(skb->len-1);
+	desc->header.raw = METH_TX_CMD_INT_EN | TX_CATBUF1 | TX_CATBUF2| (skb->len - 1);
 	/* unaligned part */
-	if(unaligned_len){
-		memcpy(desc->data.dt+(120-unaligned_len),
+	if (unaligned_len){
+		memcpy(desc->data.dt + (120 - unaligned_len),
 		       skb->data, unaligned_len);
-		desc->header.raw |= (128-unaligned_len) << 16;
+		desc->header.raw |= (128 - unaligned_len) << 16;
 	}
 
 	/* first page */
 	catbuf1 = dma_map_single(NULL, buffer1_data, buffer1_len,
 				 DMA_TO_DEVICE);
 	desc->data.cat_buf[0].form.start_addr = catbuf1 >> 3;
-	desc->data.cat_buf[0].form.len = buffer1_len-1;
+	desc->data.cat_buf[0].form.len = buffer1_len - 1;
 	/* second page */
 	catbuf2 = dma_map_single(NULL, buffer2_data, buffer2_len,
 				 DMA_TO_DEVICE);
 	desc->data.cat_buf[1].form.start_addr = catbuf2 >> 3;
-	desc->data.cat_buf[1].form.len = buffer2_len-1;
+	desc->data.cat_buf[1].form.len = buffer2_len - 1;
 }
 
 static void meth_add_to_tx_ring(struct meth_private *priv, struct sk_buff *skb)
 {
 	/* Remember the skb, so we can free it at interrupt time */
 	priv->tx_skbs[priv->tx_write] = skb;
-	if(skb->len <= 120) {
+	if (skb->len <= 120) {
 		/* Whole packet fits into descriptor */
-		meth_tx_short_prepare(priv,skb);
-	} else if(PAGE_ALIGN((unsigned long)skb->data) !=
-		  PAGE_ALIGN((unsigned long)skb->data+skb->len-1)) {
+		meth_tx_short_prepare(priv, skb);
+	} else if (PAGE_ALIGN((unsigned long)skb->data) !=
+		   PAGE_ALIGN((unsigned long)skb->data + skb->len - 1)) {
 		/* Packet crosses page boundary */
-		meth_tx_2page_prepare(priv,skb);
+		meth_tx_2page_prepare(priv, skb);
 	} else {
 		/* Packet is in one page */
-		meth_tx_1page_prepare(priv,skb);
+		meth_tx_1page_prepare(priv, skb);
 	}
-	priv->tx_write = (priv->tx_write+1) & (TX_RING_ENTRIES-1);
-	mace_eth_write(priv->tx_write, tx_info);
-	priv->tx_count ++;
+	priv->tx_write = (priv->tx_write + 1) & (TX_RING_ENTRIES - 1);
+	mace->eth.tx_info = priv->tx_write;
+	priv->tx_count++;
 }
 
 /*
@@ -695,10 +700,10 @@
 	struct meth_private *priv = (struct meth_private *) dev->priv;
 	unsigned long flags;
 
-	spin_lock_irqsave(&priv->meth_lock,flags);
+	spin_lock_irqsave(&priv->meth_lock, flags);
 	/* Stop DMA notification */
 	priv->dma_ctrl &= ~(METH_DMA_TX_INT_EN);
-	mace_eth_write(priv->dma_ctrl, dma_ctrl);
+	mace->eth.dma_ctrl = priv->dma_ctrl;
 
 	meth_add_to_tx_ring(priv, skb);
 	dev->trans_start = jiffies; /* save the timestamp */
@@ -711,9 +716,9 @@
 
 	/* Restart DMA notification */
 	priv->dma_ctrl |= METH_DMA_TX_INT_EN;
-	mace_eth_write(priv->dma_ctrl, dma_ctrl);
+	mace->eth.dma_ctrl = priv->dma_ctrl;
 
-	spin_unlock_irqrestore(&priv->meth_lock,flags);
+	spin_unlock_irqrestore(&priv->meth_lock, flags);
 
 	return 0;
 }
@@ -743,11 +748,11 @@
 	meth_init_rx_ring(priv);
 
 	/* Restart dma */
-	priv->dma_ctrl|=METH_DMA_TX_EN|METH_DMA_RX_EN|METH_DMA_RX_INT_EN;
-	mace_eth_write(priv->dma_ctrl, dma_ctrl);
+	priv->dma_ctrl |= METH_DMA_TX_EN | METH_DMA_RX_EN | METH_DMA_RX_INT_EN;
+	mace->eth.dma_ctrl = priv->dma_ctrl;
 
 	/* Enable interrupt */
-	spin_unlock_irqrestore(&priv->meth_lock,flags);
+	spin_unlock_irqrestore(&priv->meth_lock, flags);
 
 	dev->trans_start = jiffies;
 	netif_wake_queue(dev);
@@ -760,8 +765,14 @@
  */
 static int meth_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 {
-	DPRINTK("ioctl\n");
-	return 0;
+	/* XXX Not yet implemented */
+	switch(cmd) { 
+	case SIOCGMIIPHY:
+	case SIOCGMIIREG:
+	case SIOCSMIIREG:
+	default:
+		return -EOPNOTSUPP;
+	}
 }
 
 /*
@@ -808,7 +819,7 @@
 	}
 
 	printk(KERN_INFO "%s: SGI MACE Ethernet rev. %d\n",
-	       dev->name, (unsigned int)mace_eth_read(mac_ctrl) >> 29);
+	       dev->name, (unsigned int)(mace->eth.mac_ctrl >> 29));
 	return 0;
 }
 
diff -Nru a/drivers/net/meth.h b/drivers/net/meth.h
--- a/drivers/net/meth.h	2005-03-11 12:51:42 -08:00
+++ b/drivers/net/meth.h	2005-03-11 12:51:42 -08:00
@@ -29,7 +29,7 @@
 #define RX_BUCKET_SIZE 256
 
 #undef BIT
-#define BIT(x)	(1 << (x))
+#define BIT(x)	(1UL << (x))
 
 /* For more detailed explanations of what each field menas,
    see Nick's great comments to #defines below (or docs, if
diff -Nru a/drivers/net/mii.c b/drivers/net/mii.c
--- a/drivers/net/mii.c	2005-03-11 12:51:42 -08:00
+++ b/drivers/net/mii.c	2005-03-11 12:51:42 -08:00
@@ -37,6 +37,7 @@
 {
 	struct net_device *dev = mii->dev;
 	u32 advert, bmcr, lpa, nego;
+	u32 advert2 = 0, bmcr2 = 0, lpa2 = 0;
 
 	ecmd->supported =
 	    (SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full |
@@ -54,6 +55,9 @@
 
 	ecmd->advertising = ADVERTISED_TP | ADVERTISED_MII;
 	advert = mii->mdio_read(dev, mii->phy_id, MII_ADVERTISE);
+	if (mii->supports_gmii)
+		advert2 = mii->mdio_read(dev, mii->phy_id, MII_CTRL1000);
+
 	if (advert & ADVERTISE_10HALF)
 		ecmd->advertising |= ADVERTISED_10baseT_Half;
 	if (advert & ADVERTISE_10FULL)
@@ -62,19 +66,31 @@
 		ecmd->advertising |= ADVERTISED_100baseT_Half;
 	if (advert & ADVERTISE_100FULL)
 		ecmd->advertising |= ADVERTISED_100baseT_Full;
+	if (advert2 & ADVERTISE_1000HALF)
+		ecmd->advertising |= ADVERTISED_1000baseT_Half;
+	if (advert2 & ADVERTISE_1000FULL)
+		ecmd->advertising |= ADVERTISED_1000baseT_Full;
 
 	bmcr = mii->mdio_read(dev, mii->phy_id, MII_BMCR);
 	lpa = mii->mdio_read(dev, mii->phy_id, MII_LPA);
+	if (mii->supports_gmii) {
+		bmcr2 = mii->mdio_read(dev, mii->phy_id, MII_CTRL1000);
+		lpa2 = mii->mdio_read(dev, mii->phy_id, MII_STAT1000);
+	}
 	if (bmcr & BMCR_ANENABLE) {
 		ecmd->advertising |= ADVERTISED_Autoneg;
 		ecmd->autoneg = AUTONEG_ENABLE;
 		
 		nego = mii_nway_result(advert & lpa);
-		if (nego == LPA_100FULL || nego == LPA_100HALF)
+		if ((bmcr2 & (ADVERTISE_1000HALF | ADVERTISE_1000FULL)) & 
+		    (lpa2 >> 2))
+			ecmd->speed = SPEED_1000;
+		else if (nego == LPA_100FULL || nego == LPA_100HALF)
 			ecmd->speed = SPEED_100;
 		else
 			ecmd->speed = SPEED_10;
-		if (nego == LPA_100FULL || nego == LPA_10FULL) {
+		if ((lpa2 & LPA_1000FULL) || nego == LPA_100FULL ||
+		    nego == LPA_10FULL) {
 			ecmd->duplex = DUPLEX_FULL;
 			mii->full_duplex = 1;
 		} else {
@@ -84,7 +100,9 @@
 	} else {
 		ecmd->autoneg = AUTONEG_DISABLE;
 
-		ecmd->speed = (bmcr & BMCR_SPEED100) ? SPEED_100 : SPEED_10;
+		ecmd->speed = ((bmcr2 & BMCR_SPEED1000 && 
+				(bmcr & BMCR_SPEED100) == 0) ? SPEED_1000 :
+			       (bmcr & BMCR_SPEED100) ? SPEED_100 : SPEED_10);
 		ecmd->duplex = (bmcr & BMCR_FULLDPLX) ? DUPLEX_FULL : DUPLEX_HALF;
 	}
 
@@ -97,7 +115,9 @@
 {
 	struct net_device *dev = mii->dev;
 
-	if (ecmd->speed != SPEED_10 && ecmd->speed != SPEED_100)
+	if (ecmd->speed != SPEED_10 && 
+	    ecmd->speed != SPEED_100 && 
+	    ecmd->speed != SPEED_1000)
 		return -EINVAL;
 	if (ecmd->duplex != DUPLEX_HALF && ecmd->duplex != DUPLEX_FULL)
 		return -EINVAL;
@@ -109,21 +129,30 @@
 		return -EINVAL;
 	if (ecmd->autoneg != AUTONEG_DISABLE && ecmd->autoneg != AUTONEG_ENABLE)
 		return -EINVAL;
+	if ((ecmd->speed == SPEED_1000) && (!mii->supports_gmii))
+		return -EINVAL;
 				  
 	/* ignore supported, maxtxpkt, maxrxpkt */
 	
 	if (ecmd->autoneg == AUTONEG_ENABLE) {
 		u32 bmcr, advert, tmp;
+		u32 advert2 = 0, tmp2 = 0;
 
 		if ((ecmd->advertising & (ADVERTISED_10baseT_Half |
 					  ADVERTISED_10baseT_Full |
 					  ADVERTISED_100baseT_Half |
-					  ADVERTISED_100baseT_Full)) == 0)
+					  ADVERTISED_100baseT_Full |
+					  ADVERTISED_1000baseT_Half |
+					  ADVERTISED_1000baseT_Full)) == 0)
 			return -EINVAL;
 
 		/* advertise only what has been requested */
 		advert = mii->mdio_read(dev, mii->phy_id, MII_ADVERTISE);
 		tmp = advert & ~(ADVERTISE_ALL | ADVERTISE_100BASE4);
+		if (mii->supports_gmii) {
+			advert2 = mii->mdio_read(dev, mii->phy_id, MII_CTRL1000);
+			tmp2 = advert2 & ~(ADVERTISE_1000HALF | ADVERTISE_1000FULL);
+		}
 		if (ecmd->advertising & ADVERTISED_10baseT_Half)
 			tmp |= ADVERTISE_10HALF;
 		if (ecmd->advertising & ADVERTISED_10baseT_Full)
@@ -132,10 +161,18 @@
 			tmp |= ADVERTISE_100HALF;
 		if (ecmd->advertising & ADVERTISED_100baseT_Full)
 			tmp |= ADVERTISE_100FULL;
+		if (mii->supports_gmii) {
+			if (ecmd->advertising & ADVERTISED_1000baseT_Half)
+				advert2 |= ADVERTISE_1000HALF;
+			if (ecmd->advertising & ADVERTISED_1000baseT_Full)
+				advert2 |= ADVERTISE_1000FULL;
+		}
 		if (advert != tmp) {
 			mii->mdio_write(dev, mii->phy_id, MII_ADVERTISE, tmp);
 			mii->advertising = tmp;
 		}
+		if ((mii->supports_gmii) && (advert2 != tmp2))
+			mii->mdio_write(dev, mii->phy_id, MII_CTRL1000, tmp2);
 		
 		/* turn on autonegotiation, and force a renegotiate */
 		bmcr = mii->mdio_read(dev, mii->phy_id, MII_BMCR);
@@ -148,8 +185,11 @@
 
 		/* turn off auto negotiation, set speed and duplexity */
 		bmcr = mii->mdio_read(dev, mii->phy_id, MII_BMCR);
-		tmp = bmcr & ~(BMCR_ANENABLE | BMCR_SPEED100 | BMCR_FULLDPLX);
-		if (ecmd->speed == SPEED_100)
+		tmp = bmcr & ~(BMCR_ANENABLE | BMCR_SPEED100 | 
+			       BMCR_SPEED1000 | BMCR_FULLDPLX);
+		if (ecmd->speed == SPEED_1000)
+			tmp |= BMCR_SPEED1000;
+		else if (ecmd->speed == SPEED_100)
 			tmp |= BMCR_SPEED100;
 		if (ecmd->duplex == DUPLEX_FULL) {
 			tmp |= BMCR_FULLDPLX;
@@ -207,6 +247,7 @@
 {
 	unsigned int old_carrier, new_carrier;
 	int advertise, lpa, media, duplex;
+	int lpa2 = 0;
 
 	/* if forced media, go no further */
 	if (mii->force_media)
@@ -243,16 +284,20 @@
 		mii->advertising = advertise;
 	}
 	lpa = mii->mdio_read(mii->dev, mii->phy_id, MII_LPA);
+	if (mii->supports_gmii)
+		lpa2 = mii->mdio_read(mii->dev, mii->phy_id, MII_STAT1000);
 
 	/* figure out media and duplex from advertise and LPA values */
 	media = mii_nway_result(lpa & advertise);
 	duplex = (media & ADVERTISE_FULL) ? 1 : 0;
+	if (lpa2 & LPA_1000FULL)
+		duplex = 1;
 
 	if (ok_to_print)
 		printk(KERN_INFO "%s: link up, %sMbps, %s-duplex, lpa 0x%04X\n",
 		       mii->dev->name,
-		       media & (ADVERTISE_100FULL | ADVERTISE_100HALF) ?
-		       		"100" : "10",
+		       lpa2 & (LPA_1000FULL | LPA_1000HALF) ? "1000" :
+		       media & (ADVERTISE_100FULL | ADVERTISE_100HALF) ? "100" : "10",
 		       duplex ? "full" : "half",
 		       lpa);
 
diff -Nru a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c
--- a/drivers/net/mv643xx_eth.c	2005-03-11 12:51:42 -08:00
+++ b/drivers/net/mv643xx_eth.c	2005-03-11 12:51:42 -08:00
@@ -1,5 +1,5 @@
 /*
- * drivers/net/mv64340_eth.c - Driver for MV64340X ethernet ports
+ * drivers/net/mv643xx_eth.c - Driver for MV643XX ethernet ports
  * Copyright (C) 2002 Matthew Dharm <mdharm@momenco.com>
  *
  * Based on the 64360 driver from:
@@ -10,6 +10,12 @@
  *
  * Copyright (C) 2003 Ralf Baechle <ralf@linux-mips.org>
  *
+ * Copyright (C) 2004-2005 MontaVista Software, Inc.
+ *			   Dale Farnsworth <dale@farnsworth.org>
+ *
+ * Copyright (C) 2004 Steven J. Hill <sjhill1@rockwellcollins.com>
+ *				     <sjhill@realitydiluted.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
@@ -24,80 +30,100 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
-#include <linux/config.h>
-#include <linux/version.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/config.h>
-#include <linux/sched.h>
-#include <linux/ptrace.h>
-#include <linux/fcntl.h>
-#include <linux/ioport.h>
-#include <linux/interrupt.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/errno.h>
-#include <linux/ip.h>
 #include <linux/init.h>
-#include <linux/in.h>
-#include <linux/pci.h>
-#include <linux/workqueue.h>
-#include <asm/smp.h>
-#include <linux/skbuff.h>
+#include <linux/dma-mapping.h>
 #include <linux/tcp.h>
-#include <linux/netdevice.h>
+#include <linux/udp.h>
 #include <linux/etherdevice.h>
-#include <net/ip.h>
 
 #include <linux/bitops.h>
+#include <linux/delay.h>
+#include <linux/ethtool.h>
 #include <asm/io.h>
 #include <asm/types.h>
 #include <asm/pgtable.h>
 #include <asm/system.h>
+#include <asm/delay.h>
 #include "mv643xx_eth.h"
 
 /*
- * The first part is the high level driver of the gigE ethernet ports. 
+ * The first part is the high level driver of the gigE ethernet ports.
  */
 
-/* Definition for configuring driver */
-#undef MV64340_RX_QUEUE_FILL_ON_TASK
-
 /* Constants */
-#define EXTRA_BYTES 32
-#define WRAP       ETH_HLEN + 2 + 4 + 16
-#define BUFFER_MTU dev->mtu + WRAP
+#define VLAN_HLEN		4
+#define FCS_LEN			4
+#define WRAP			NET_IP_ALIGN + ETH_HLEN + VLAN_HLEN + FCS_LEN
+#define RX_SKB_SIZE		((dev->mtu + WRAP + 7) & ~0x7)
+
 #define INT_CAUSE_UNMASK_ALL		0x0007ffff
 #define INT_CAUSE_UNMASK_ALL_EXT	0x0011ffff
-#ifdef MV64340_RX_FILL_ON_TASK
+#ifdef MV643XX_RX_QUEUE_FILL_ON_TASK
 #define INT_CAUSE_MASK_ALL		0x00000000
 #define INT_CAUSE_CHECK_BITS		INT_CAUSE_UNMASK_ALL
 #define INT_CAUSE_CHECK_BITS_EXT	INT_CAUSE_UNMASK_ALL_EXT
 #endif
 
+#ifdef MV643XX_CHECKSUM_OFFLOAD_TX
+#define MAX_DESCS_PER_SKB	(MAX_SKB_FRAGS + 1)
+#else
+#define MAX_DESCS_PER_SKB	1
+#endif
+
+#define PHY_WAIT_ITERATIONS	1000	/* 1000 iterations * 10uS = 10mS max */
+#define PHY_WAIT_MICRO_SECONDS	10
+
 /* Static function declarations */
-static int mv64340_eth_real_open(struct net_device *);
-static int mv64340_eth_real_stop(struct net_device *);
-static int mv64340_eth_change_mtu(struct net_device *, int);
-static struct net_device_stats *mv64340_eth_get_stats(struct net_device *);
+static int eth_port_link_is_up(unsigned int eth_port_num);
+static void eth_port_uc_addr_get(struct net_device *dev,
+						unsigned char *MacAddr);
+static int mv643xx_eth_real_open(struct net_device *);
+static int mv643xx_eth_real_stop(struct net_device *);
+static int mv643xx_eth_change_mtu(struct net_device *, int);
+static struct net_device_stats *mv643xx_eth_get_stats(struct net_device *);
 static void eth_port_init_mac_tables(unsigned int eth_port_num);
-#ifdef MV64340_NAPI
-static int mv64340_poll(struct net_device *dev, int *budget);
+#ifdef MV643XX_NAPI
+static int mv643xx_poll(struct net_device *dev, int *budget);
 #endif
+static void ethernet_phy_set(unsigned int eth_port_num, int phy_addr);
+static int ethernet_phy_detect(unsigned int eth_port_num);
+static struct ethtool_ops mv643xx_ethtool_ops;
+
+static char mv643xx_driver_name[] = "mv643xx_eth";
+static char mv643xx_driver_version[] = "1.0";
+
+static void __iomem *mv643xx_eth_shared_base;
+
+/* used to protect MV643XX_ETH_SMI_REG, which is shared across ports */
+static spinlock_t mv643xx_eth_phy_lock = SPIN_LOCK_UNLOCKED;
+
+static inline u32 mv_read(int offset)
+{
+	void *__iomem reg_base;
+
+	reg_base = mv643xx_eth_shared_base - MV643XX_ETH_SHARED_REGS;
+
+	return readl(reg_base + offset);
+}
+
+static inline void mv_write(int offset, u32 data)
+{
+	void * __iomem reg_base;
 
-unsigned char prom_mac_addr_base[6];
-unsigned long mv64340_sram_base;
+	reg_base = mv643xx_eth_shared_base - MV643XX_ETH_SHARED_REGS;
+	writel(data, reg_base + offset);
+}
 
 /*
  * Changes MTU (maximum transfer unit) of the gigabit ethenret port
  *
- * Input : pointer to ethernet interface network device structure
- *         new mtu size 
- * Output : 0 upon success, -EINVAL upon failure
+ * Input :	pointer to ethernet interface network device structure
+ *		new mtu size
+ * Output :	0 upon success, -EINVAL upon failure
  */
-static int mv64340_eth_change_mtu(struct net_device *dev, int new_mtu)
+static int mv643xx_eth_change_mtu(struct net_device *dev, int new_mtu)
 {
-	struct mv64340_private *mp = netdev_priv(dev);
+	struct mv643xx_private *mp = netdev_priv(dev);
 	unsigned long flags;
 
 	spin_lock_irqsave(&mp->lock, flags);
@@ -108,21 +134,21 @@
 	}
 
 	dev->mtu = new_mtu;
-	/* 
+	/*
 	 * Stop then re-open the interface. This will allocate RX skb's with
 	 * the new MTU.
 	 * There is a possible danger that the open will not successed, due
 	 * to memory is full, which might fail the open function.
 	 */
 	if (netif_running(dev)) {
-		if (mv64340_eth_real_stop(dev))
+		if (mv643xx_eth_real_stop(dev))
 			printk(KERN_ERR
-			       "%s: Fatal error on stopping device\n",
-			       dev->name);
-		if (mv64340_eth_real_open(dev))
+				"%s: Fatal error on stopping device\n",
+				dev->name);
+		if (mv643xx_eth_real_open(dev))
 			printk(KERN_ERR
-			       "%s: Fatal error on opening device\n",
-			       dev->name);
+				"%s: Fatal error on opening device\n",
+				dev->name);
 	}
 
 	spin_unlock_irqrestore(&mp->lock, flags);
@@ -130,17 +156,17 @@
 }
 
 /*
- * mv64340_eth_rx_task
- *								       
+ * mv643xx_eth_rx_task
+ *
  * Fills / refills RX queue on a certain gigabit ethernet port
  *
- * Input : pointer to ethernet interface network device structure
- * Output : N/A
+ * Input :	pointer to ethernet interface network device structure
+ * Output :	N/A
  */
-static void mv64340_eth_rx_task(void *data)
+static void mv643xx_eth_rx_task(void *data)
 {
-	struct net_device *dev = (struct net_device *) data;
-	struct mv64340_private *mp = netdev_priv(dev);
+	struct net_device *dev = (struct net_device *)data;
+	struct mv643xx_private *mp = netdev_priv(dev);
 	struct pkt_info pkt_info;
 	struct sk_buff *skb;
 
@@ -148,28 +174,18 @@
 		panic("%s: Error in test_set_bit / clear_bit", dev->name);
 
 	while (mp->rx_ring_skbs < (mp->rx_ring_size - 5)) {
-		/* The +8 for buffer allignment and another 32 byte extra */
-
-		skb = dev_alloc_skb(BUFFER_MTU + 8 + EXTRA_BYTES);
+		skb = dev_alloc_skb(RX_SKB_SIZE);
 		if (!skb)
-			/* Better luck next time */
 			break;
 		mp->rx_ring_skbs++;
 		pkt_info.cmd_sts = ETH_RX_ENABLE_INTERRUPT;
-		pkt_info.byte_cnt = dev->mtu + ETH_HLEN + 4 + 2 + EXTRA_BYTES;
-		/* Allign buffer to 8 bytes */
-		if (pkt_info.byte_cnt & ~0x7) {
-			pkt_info.byte_cnt &= ~0x7;
-			pkt_info.byte_cnt += 8;
-		}
-		pkt_info.buf_ptr =
-		    pci_map_single(0, skb->data,
-				   dev->mtu + ETH_HLEN + 4 + 2 + EXTRA_BYTES,
-				   PCI_DMA_FROMDEVICE);
+		pkt_info.byte_cnt = RX_SKB_SIZE;
+		pkt_info.buf_ptr = dma_map_single(NULL, skb->data, RX_SKB_SIZE,
+							DMA_FROM_DEVICE);
 		pkt_info.return_info = skb;
 		if (eth_rx_return_buff(mp, &pkt_info) != ETH_OK) {
 			printk(KERN_ERR
-			       "%s: Error allocating RX Ring\n", dev->name);
+				"%s: Error allocating RX Ring\n", dev->name);
 			break;
 		}
 		skb_reserve(skb, 2);
@@ -186,46 +202,45 @@
 		add_timer(&mp->timeout);
 		mp->rx_timer_flag = 1;
 	}
-#if MV64340_RX_QUEUE_FILL_ON_TASK
+#ifdef MV643XX_RX_QUEUE_FILL_ON_TASK
 	else {
 		/* Return interrupts */
-		MV_WRITE(MV64340_ETH_INTERRUPT_MASK_REG(mp->port_num),
-			 INT_CAUSE_UNMASK_ALL);
+		mv_write(MV643XX_ETH_INTERRUPT_MASK_REG(mp->port_num),
+							INT_CAUSE_UNMASK_ALL);
 	}
 #endif
 }
 
 /*
- * mv64340_eth_rx_task_timer_wrapper
- *								       
+ * mv643xx_eth_rx_task_timer_wrapper
+ *
  * Timer routine to wake up RX queue filling task. This function is
  * used only in case the RX queue is empty, and all alloc_skb has
  * failed (due to out of memory event).
  *
- * Input : pointer to ethernet interface network device structure
- * Output : N/A
+ * Input :	pointer to ethernet interface network device structure
+ * Output :	N/A
  */
-static void mv64340_eth_rx_task_timer_wrapper(unsigned long data)
+static void mv643xx_eth_rx_task_timer_wrapper(unsigned long data)
 {
-	struct net_device *dev = (struct net_device *) data;
-	struct mv64340_private *mp = netdev_priv(dev);
+	struct net_device *dev = (struct net_device *)data;
+	struct mv643xx_private *mp = netdev_priv(dev);
 
 	mp->rx_timer_flag = 0;
-	mv64340_eth_rx_task((void *) data);
+	mv643xx_eth_rx_task((void *)data);
 }
 
-
 /*
- * mv64340_eth_update_mac_address
- *								       
+ * mv643xx_eth_update_mac_address
+ *
  * Update the MAC address of the port in the address table
  *
- * Input : pointer to ethernet interface network device structure
- * Output : N/A
+ * Input :	pointer to ethernet interface network device structure
+ * Output :	N/A
  */
-static void mv64340_eth_update_mac_address(struct net_device *dev)
+static void mv643xx_eth_update_mac_address(struct net_device *dev)
 {
-	struct mv64340_private *mp = netdev_priv(dev);
+	struct mv643xx_private *mp = netdev_priv(dev);
 	unsigned int port_num = mp->port_num;
 
 	eth_port_init_mac_tables(port_num);
@@ -234,64 +249,59 @@
 }
 
 /*
- * mv64340_eth_set_rx_mode
- *								       
+ * mv643xx_eth_set_rx_mode
+ *
  * Change from promiscuos to regular rx mode
  *
- * Input : pointer to ethernet interface network device structure
- * Output : N/A
+ * Input :	pointer to ethernet interface network device structure
+ * Output :	N/A
  */
-static void mv64340_eth_set_rx_mode(struct net_device *dev)
+static void mv643xx_eth_set_rx_mode(struct net_device *dev)
 {
-	struct mv64340_private *mp = netdev_priv(dev);
+	struct mv643xx_private *mp = netdev_priv(dev);
+	u32 config_reg;
 
-	if (dev->flags & IFF_PROMISC) {
-		ethernet_set_config_reg
-		    (mp->port_num,
-		     ethernet_get_config_reg(mp->port_num) |
-		     ETH_UNICAST_PROMISCUOUS_MODE);
-	} else {
-		ethernet_set_config_reg
-		    (mp->port_num,
-		     ethernet_get_config_reg(mp->port_num) &
-		     ~(unsigned int) ETH_UNICAST_PROMISCUOUS_MODE);
-	}
+	config_reg = ethernet_get_config_reg(mp->port_num);
+	if (dev->flags & IFF_PROMISC)
+		config_reg |= (u32) MV643XX_ETH_UNICAST_PROMISCUOUS_MODE;
+	else
+		config_reg &= ~(u32) MV643XX_ETH_UNICAST_PROMISCUOUS_MODE;
+	ethernet_set_config_reg(mp->port_num, config_reg);
 }
 
-
 /*
- * mv64340_eth_set_mac_address
- *								       
+ * mv643xx_eth_set_mac_address
+ *
  * Change the interface's mac address.
  * No special hardware thing should be done because interface is always
  * put in promiscuous mode.
  *
- * Input : pointer to ethernet interface network device structure and
- *         a pointer to the designated entry to be added to the cache.
- * Output : zero upon success, negative upon failure
+ * Input :	pointer to ethernet interface network device structure and
+ *		a pointer to the designated entry to be added to the cache.
+ * Output :	zero upon success, negative upon failure
  */
-static int mv64340_eth_set_mac_address(struct net_device *dev, void *addr)
+static int mv643xx_eth_set_mac_address(struct net_device *dev, void *addr)
 {
 	int i;
 
 	for (i = 0; i < 6; i++)
 		/* +2 is for the offset of the HW addr type */
-		dev->dev_addr[i] = ((unsigned char *) addr)[i + 2];
-	mv64340_eth_update_mac_address(dev);
+		dev->dev_addr[i] = ((unsigned char *)addr)[i + 2];
+	mv643xx_eth_update_mac_address(dev);
 	return 0;
 }
 
 /*
- * mv64340_eth_tx_timeout
- *								       
+ * mv643xx_eth_tx_timeout
+ *
  * Called upon a timeout on transmitting a packet
  *
- * Input : pointer to ethernet interface network device structure.
- * Output : N/A
+ * Input :	pointer to ethernet interface network device structure.
+ * Output :	N/A
  */
-static void mv64340_eth_tx_timeout(struct net_device *dev)
+static void mv643xx_eth_tx_timeout(struct net_device *dev)
 {
-	struct mv64340_private *mp = netdev_priv(dev);
+	struct mv643xx_private *mp = netdev_priv(dev);
 
 	printk(KERN_INFO "%s: TX timeout  ", dev->name);
 
@@ -300,31 +310,31 @@
 }
 
 /*
- * mv64340_eth_tx_timeout_task
+ * mv643xx_eth_tx_timeout_task
  *
  * Actual routine to reset the adapter when a timeout on Tx has occurred
  */
-static void mv64340_eth_tx_timeout_task(struct net_device *dev)
+static void mv643xx_eth_tx_timeout_task(struct net_device *dev)
 {
-        struct mv64340_private *mp = netdev_priv(dev);
+	struct mv643xx_private *mp = netdev_priv(dev);
 
-        netif_device_detach(dev);
-        eth_port_reset(mp->port_num);
-        eth_port_start(mp);
-        netif_device_attach(dev);
+	netif_device_detach(dev);
+	eth_port_reset(mp->port_num);
+	eth_port_start(mp);
+	netif_device_attach(dev);
 }
 
 /*
- * mv64340_eth_free_tx_queue
+ * mv643xx_eth_free_tx_queue
  *
- * Input : dev - a pointer to the required interface
+ * Input :	dev - a pointer to the required interface
  *
- * Output : 0 if was able to release skb , nonzero otherwise
+ * Output :	0 if was able to release skb , nonzero otherwise
  */
-static int mv64340_eth_free_tx_queue(struct net_device *dev,
-			      unsigned int eth_int_cause_ext)
+static int mv643xx_eth_free_tx_queue(struct net_device *dev,
+					unsigned int eth_int_cause_ext)
 {
-	struct mv64340_private *mp = netdev_priv(dev);
+	struct mv643xx_private *mp = netdev_priv(dev);
 	struct net_device_stats *stats = &mp->stats;
 	struct pkt_info pkt_info;
 	int released = 1;
@@ -341,33 +351,36 @@
 			stats->tx_errors++;
 		}
 
-		/* 
+		/*
 		 * If return_info is different than 0, release the skb.
 		 * The case where return_info is not 0 is only in case
 		 * when transmitted a scatter/gather packet, where only
 		 * last skb releases the whole chain.
 		 */
 		if (pkt_info.return_info) {
-			dev_kfree_skb_irq((struct sk_buff *)
-					  pkt_info.return_info);
-			released = 0;
 			if (skb_shinfo(pkt_info.return_info)->nr_frags)
-				pci_unmap_page(NULL, pkt_info.buf_ptr,
-					pkt_info.byte_cnt, PCI_DMA_TODEVICE);
+				dma_unmap_page(NULL, pkt_info.buf_ptr,
+						pkt_info.byte_cnt,
+						DMA_TO_DEVICE);
+			else
+				dma_unmap_single(NULL, pkt_info.buf_ptr,
+						pkt_info.byte_cnt,
+						DMA_TO_DEVICE);
 
-			if (mp->tx_ring_skbs != 1)
-				mp->tx_ring_skbs--;
-		} else 
-			pci_unmap_page(NULL, pkt_info.buf_ptr,
-					pkt_info.byte_cnt, PCI_DMA_TODEVICE);
-
-		/* 
-		 * Decrement the number of outstanding skbs counter on
-		 * the TX queue.
-		 */
-		if (mp->tx_ring_skbs == 0)
-			panic("ERROR - TX outstanding SKBs counter is corrupted");
+			dev_kfree_skb_irq(pkt_info.return_info);
+			released = 0;
 
+			/*
+			 * Decrement the number of outstanding skbs counter on
+			 * the TX queue.
+			 */
+			if (mp->tx_ring_skbs == 0)
+				panic("ERROR - TX outstanding SKBs"
+						" counter is corrupted");
+			mp->tx_ring_skbs--;
+		} else
+			dma_unmap_page(NULL, pkt_info.buf_ptr,
+					pkt_info.byte_cnt, DMA_TO_DEVICE);
 	}
 
 	spin_unlock(&mp->lock);
@@ -376,60 +389,59 @@
 }
 
 /*
- * mv64340_eth_receive
+ * mv643xx_eth_receive
  *
  * This function is forward packets that are received from the port's
  * queues toward kernel core or FastRoute them to another interface.
  *
- * Input : dev - a pointer to the required interface
- *         max - maximum number to receive (0 means unlimted)
+ * Input :	dev - a pointer to the required interface
+ *		max - maximum number to receive (0 means unlimted)
  *
- * Output : number of served packets
+ * Output :	number of served packets
  */
-#ifdef MV64340_NAPI
-static int mv64340_eth_receive_queue(struct net_device *dev, unsigned int max,
-								int budget)
+#ifdef MV643XX_NAPI
+static int mv643xx_eth_receive_queue(struct net_device *dev, int budget)
 #else
-static int mv64340_eth_receive_queue(struct net_device *dev, unsigned int max)
+static int mv643xx_eth_receive_queue(struct net_device *dev)
 #endif
 {
-	struct mv64340_private *mp = netdev_priv(dev);
+	struct mv643xx_private *mp = netdev_priv(dev);
 	struct net_device_stats *stats = &mp->stats;
 	unsigned int received_packets = 0;
 	struct sk_buff *skb;
 	struct pkt_info pkt_info;
 
-#ifdef MV64340_NAPI
+#ifdef MV643XX_NAPI
 	while (eth_port_receive(mp, &pkt_info) == ETH_OK && budget > 0) {
 #else
-	while ((--max) && eth_port_receive(mp, &pkt_info) == ETH_OK) {
+	while (eth_port_receive(mp, &pkt_info) == ETH_OK) {
 #endif
 		mp->rx_ring_skbs--;
 		received_packets++;
-#ifdef MV64340_NAPI
+#ifdef MV643XX_NAPI
 		budget--;
 #endif
 		/* Update statistics. Note byte count includes 4 byte CRC count */
 		stats->rx_packets++;
 		stats->rx_bytes += pkt_info.byte_cnt;
-		skb = (struct sk_buff *) pkt_info.return_info;
+		skb = pkt_info.return_info;
 		/*
 		 * In case received a packet without first / last bits on OR
 		 * the error summary bit is on, the packets needs to be dropeed.
 		 */
 		if (((pkt_info.cmd_sts
-		      & (ETH_RX_FIRST_DESC | ETH_RX_LAST_DESC)) !=
-		     (ETH_RX_FIRST_DESC | ETH_RX_LAST_DESC))
-		    || (pkt_info.cmd_sts & ETH_ERROR_SUMMARY)) {
+				& (ETH_RX_FIRST_DESC | ETH_RX_LAST_DESC)) !=
+					(ETH_RX_FIRST_DESC | ETH_RX_LAST_DESC))
+				|| (pkt_info.cmd_sts & ETH_ERROR_SUMMARY)) {
 			stats->rx_dropped++;
 			if ((pkt_info.cmd_sts & (ETH_RX_FIRST_DESC |
-						 ETH_RX_LAST_DESC)) !=
-			    (ETH_RX_FIRST_DESC | ETH_RX_LAST_DESC)) {
+							ETH_RX_LAST_DESC)) !=
+				(ETH_RX_FIRST_DESC | ETH_RX_LAST_DESC)) {
 				if (net_ratelimit())
 					printk(KERN_ERR
-					       "%s: Received packet spread on multiple"
-					       " descriptors\n",
-					       dev->name);
+						"%s: Received packet spread "
+						"on multiple descriptors\n",
+						dev->name);
 			}
 			if (pkt_info.cmd_sts & ETH_ERROR_SUMMARY)
 				stats->rx_errors++;
@@ -445,11 +457,11 @@
 
 			if (pkt_info.cmd_sts & ETH_LAYER_4_CHECKSUM_OK) {
 				skb->ip_summed = CHECKSUM_UNNECESSARY;
-				skb->csum = htons((pkt_info.cmd_sts
-							& 0x0007fff8) >> 3);
+				skb->csum = htons(
+					(pkt_info.cmd_sts & 0x0007fff8) >> 3);
 			}
 			skb->protocol = eth_type_trans(skb, dev);
-#ifdef MV64340_NAPI
+#ifdef MV643XX_NAPI
 			netif_receive_skb(skb);
 #else
 			netif_rx(skb);
@@ -461,74 +473,74 @@
 }
 
 /*
- * mv64340_eth_int_handler
+ * mv643xx_eth_int_handler
  *
  * Main interrupt handler for the gigbit ethernet ports
  *
- * Input : irq - irq number (not used)
- *         dev_id - a pointer to the required interface's data structure
- *         regs   - not used
- * Output : N/A
+ * Input :	irq	- irq number (not used)
+ *		dev_id	- a pointer to the required interface's data structure
+ *		regs	- not used
+ * Output :	N/A
  */
 
-static irqreturn_t mv64340_eth_int_handler(int irq, void *dev_id,
-	struct pt_regs *regs)
+static irqreturn_t mv643xx_eth_int_handler(int irq, void *dev_id,
+							struct pt_regs *regs)
 {
-	struct net_device *dev = (struct net_device *) dev_id;
-	struct mv64340_private *mp = netdev_priv(dev);
+	struct net_device *dev = (struct net_device *)dev_id;
+	struct mv643xx_private *mp = netdev_priv(dev);
 	u32 eth_int_cause, eth_int_cause_ext = 0;
 	unsigned int port_num = mp->port_num;
 
 	/* Read interrupt cause registers */
-	eth_int_cause = MV_READ(MV64340_ETH_INTERRUPT_CAUSE_REG(port_num)) &
-			INT_CAUSE_UNMASK_ALL;
+	eth_int_cause = mv_read(MV643XX_ETH_INTERRUPT_CAUSE_REG(port_num)) &
+						INT_CAUSE_UNMASK_ALL;
 
 	if (eth_int_cause & BIT1)
-		eth_int_cause_ext =
-		MV_READ(MV64340_ETH_INTERRUPT_CAUSE_EXTEND_REG(port_num)) &
-		INT_CAUSE_UNMASK_ALL_EXT;
+		eth_int_cause_ext = mv_read(
+			MV643XX_ETH_INTERRUPT_CAUSE_EXTEND_REG(port_num)) &
+						INT_CAUSE_UNMASK_ALL_EXT;
 
-#ifdef MV64340_NAPI
+#ifdef MV643XX_NAPI
 	if (!(eth_int_cause & 0x0007fffd)) {
-	/* Dont ack the Rx interrupt */
+		/* Dont ack the Rx interrupt */
 #endif
 		/*
-	 	 * Clear specific ethernet port intrerrupt registers by
+		 * Clear specific ethernet port intrerrupt registers by
 		 * acknowleding relevant bits.
 		 */
-		MV_WRITE(MV64340_ETH_INTERRUPT_CAUSE_REG(port_num),
-			 ~eth_int_cause);
+		mv_write(MV643XX_ETH_INTERRUPT_CAUSE_REG(port_num),
+							~eth_int_cause);
 		if (eth_int_cause_ext != 0x0)
-			MV_WRITE(MV64340_ETH_INTERRUPT_CAUSE_EXTEND_REG(port_num),
-				 ~eth_int_cause_ext);
+			mv_write(MV643XX_ETH_INTERRUPT_CAUSE_EXTEND_REG
+					(port_num), ~eth_int_cause_ext);
 
 		/* UDP change : We may need this */
 		if ((eth_int_cause_ext & 0x0000ffff) &&
-		    (mv64340_eth_free_tx_queue(dev, eth_int_cause_ext) == 0) &&
-		    (MV64340_TX_QUEUE_SIZE > mp->tx_ring_skbs + 1))
-                                         netif_wake_queue(dev);
-#ifdef MV64340_NAPI
+		    (mv643xx_eth_free_tx_queue(dev, eth_int_cause_ext) == 0) &&
+		    (mp->tx_ring_size > mp->tx_ring_skbs + MAX_DESCS_PER_SKB))
+			netif_wake_queue(dev);
+#ifdef MV643XX_NAPI
 	} else {
 		if (netif_rx_schedule_prep(dev)) {
 			/* Mask all the interrupts */
-			MV_WRITE(MV64340_ETH_INTERRUPT_MASK_REG(port_num),0);
-			MV_WRITE(MV64340_ETH_INTERRUPT_EXTEND_MASK_REG(port_num), 0);
+			mv_write(MV643XX_ETH_INTERRUPT_MASK_REG(port_num), 0);
+			mv_write(MV643XX_ETH_INTERRUPT_EXTEND_MASK_REG
+								(port_num), 0);
 			__netif_rx_schedule(dev);
 		}
 #else
-		{
 		if (eth_int_cause & (BIT2 | BIT11))
-			mv64340_eth_receive_queue(dev, 0);
+			mv643xx_eth_receive_queue(dev, 0);
 
 		/*
-		 * After forwarded received packets to upper layer,  add a task
+		 * After forwarded received packets to upper layer, add a task
 		 * in an interrupts enabled context that refills the RX ring
 		 * with skb's.
 		 */
-#if MV64340_RX_QUEUE_FILL_ON_TASK
+#ifdef MV643XX_RX_QUEUE_FILL_ON_TASK
 		/* Unmask all interrupts on ethernet port */
-		MV_WRITE(MV64340_ETH_INTERRUPT_MASK_REG(port_num),
-		         INT_CAUSE_MASK_ALL);
+		mv_write(MV643XX_ETH_INTERRUPT_MASK_REG(port_num),
+							INT_CAUSE_MASK_ALL);
 		queue_task(&mp->rx_task, &tq_immediate);
 		mark_bh(IMMEDIATE_BH);
 #else
@@ -538,25 +550,15 @@
 	}
 	/* PHY status changed */
 	if (eth_int_cause_ext & (BIT16 | BIT20)) {
-		unsigned int phy_reg_data;
-
-		/* Check Link status on ethernet port */
-		eth_port_read_smi_reg(port_num, 1, &phy_reg_data);
-		if (!(phy_reg_data & 0x20)) {
-			netif_stop_queue(dev);
-		} else {
+		if (eth_port_link_is_up(port_num)) {
+			netif_carrier_on(dev);
 			netif_wake_queue(dev);
-
-			/*
-			 * Start all TX queues on ethernet port. This is good in
-			 * case of previous packets where not transmitted, due
-			 * to link down and this command re-enables all TX
-			 * queues.
-			 * Note that it is possible to get a TX resource error
-			 * interrupt after issuing this, since not all TX queues
-			 * are enabled, or has anything to send.
-			 */
-			MV_WRITE(MV64340_ETH_TRANSMIT_QUEUE_COMMAND_REG(port_num), 1);
+			/* Start TX queue */
+			mv_write(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG
+								(port_num), 1);
+		} else {
+			netif_carrier_off(dev);
+			netif_stop_queue(dev);
 		}
 	}
 
@@ -570,7 +572,7 @@
 	return IRQ_HANDLED;
 }
 
-#ifdef MV64340_COAL
+#ifdef MV643XX_COAL
 
 /*
  * eth_port_set_rx_coal - Sets coalescing interrupt mechanism on RX path
@@ -584,9 +586,9 @@
  *	, and the required delay of the interrupt in usec.
  *
  * INPUT:
- *	unsigned int eth_port_num      Ethernet port number
- *	unsigned int t_clk        t_clk of the MV-643xx chip in HZ units
- *	unsigned int delay       Delay in usec
+ *	unsigned int eth_port_num	Ethernet port number
+ *	unsigned int t_clk		t_clk of the MV-643xx chip in HZ units
+ *	unsigned int delay		Delay in usec
  *
  * OUTPUT:
  *	Interrupt coalescing mechanism value is set in MV-643xx chip.
@@ -596,15 +598,15 @@
  *
  */
 static unsigned int eth_port_set_rx_coal(unsigned int eth_port_num,
-	unsigned int t_clk, unsigned int delay)
+					unsigned int t_clk, unsigned int delay)
 {
 	unsigned int coal = ((t_clk / 1000000) * delay) / 64;
 
 	/* Set RX Coalescing mechanism */
-	MV_WRITE(MV64340_ETH_SDMA_CONFIG_REG(eth_port_num),
-		 ((coal & 0x3fff) << 8) |
-		 (MV_READ(MV64340_ETH_SDMA_CONFIG_REG(eth_port_num))
-		  & 0xffc000ff));
+	mv_write(MV643XX_ETH_SDMA_CONFIG_REG(eth_port_num),
+		((coal & 0x3fff) << 8) |
+		(mv_read(MV643XX_ETH_SDMA_CONFIG_REG(eth_port_num))
+			& 0xffc000ff));
 
 	return coal;
 }
@@ -618,13 +620,13 @@
  *	This parameter is a timeout counter, that counts in 64 t_clk
  *	chunks ; that when timeout event occurs a maskable interrupt
  *	occurs.
- *	The parameter is calculated using the t_cLK frequency of the 
+ *	The parameter is calculated using the t_cLK frequency of the
  *	MV-643xx chip and the required delay in the interrupt in uSec
  *
  * INPUT:
- *	unsigned int eth_port_num      Ethernet port number
- *	unsigned int t_clk        t_clk of the MV-643xx chip in HZ units
- *	unsigned int delay       Delay in uSeconds
+ *	unsigned int eth_port_num	Ethernet port number
+ *	unsigned int t_clk		t_clk of the MV-643xx chip in HZ units
+ *	unsigned int delay		Delay in uSeconds
  *
  * OUTPUT:
  *	Interrupt coalescing mechanism value is set in MV-643xx chip.
@@ -634,48 +636,48 @@
  *
  */
 static unsigned int eth_port_set_tx_coal(unsigned int eth_port_num,
-	unsigned int t_clk, unsigned int delay)
+					unsigned int t_clk, unsigned int delay)
 {
 	unsigned int coal;
 	coal = ((t_clk / 1000000) * delay) / 64;
 	/* Set TX Coalescing mechanism */
-	MV_WRITE(MV64340_ETH_TX_FIFO_URGENT_THRESHOLD_REG(eth_port_num),
-		 coal << 4);
+	mv_write(MV643XX_ETH_TX_FIFO_URGENT_THRESHOLD_REG(eth_port_num),
+								coal << 4);
 	return coal;
 }
 
 /*
- * mv64340_eth_open
+ * mv643xx_eth_open
  *
  * This function is called when openning the network device. The function
  * should initialize all the hardware, initialize cyclic Rx/Tx
  * descriptors chain and buffers and allocate an IRQ to the network
  * device.
  *
- * Input : a pointer to the network device structure
+ * Input :	a pointer to the network device structure
  *
- * Output : zero of success , nonzero if fails.
+ * Output :	zero of success , nonzero if fails.
  */
 
-static int mv64340_eth_open(struct net_device *dev)
+static int mv643xx_eth_open(struct net_device *dev)
 {
-	struct mv64340_private *mp = netdev_priv(dev);
+	struct mv643xx_private *mp = netdev_priv(dev);
 	unsigned int port_num = mp->port_num;
-	int err = err;
+	int err;
 
 	spin_lock_irq(&mp->lock);
 
-	err = request_irq(dev->irq, mv64340_eth_int_handler,
-	                  SA_INTERRUPT | SA_SAMPLE_RANDOM, dev->name, dev);
+	err = request_irq(dev->irq, mv643xx_eth_int_handler,
+			SA_INTERRUPT | SA_SAMPLE_RANDOM, dev->name, dev);
 
 	if (err) {
-		printk(KERN_ERR "Can not assign IRQ number to MV64340_eth%d\n",
-		       port_num);
+		printk(KERN_ERR "Can not assign IRQ number to MV643XX_eth%d\n",
+								port_num);
 		err = -EAGAIN;
 		goto out;
 	}
 
-	if (mv64340_eth_real_open(dev)) {
+	if (mv643xx_eth_real_open(dev)) {
 		printk("%s: Error opening interface\n", dev->name);
 		err = -EBUSY;
 		goto out_free;
@@ -698,66 +700,35 @@
  * ether_init_rx_desc_ring - Curve a Rx chain desc list and buffer in memory.
  *
  * DESCRIPTION:
- *       This function prepares a Rx chained list of descriptors and packet 
- *       buffers in a form of a ring. The routine must be called after port 
- *       initialization routine and before port start routine. 
- *       The Ethernet SDMA engine uses CPU bus addresses to access the various 
- *       devices in the system (i.e. DRAM). This function uses the ethernet 
- *       struct 'virtual to physical' routine (set by the user) to set the ring 
- *       with physical addresses.
+ *	This function prepares a Rx chained list of descriptors and packet
+ *	buffers in a form of a ring. The routine must be called after port
+ *	initialization routine and before port start routine.
+ *	The Ethernet SDMA engine uses CPU bus addresses to access the various
+ *	devices in the system (i.e. DRAM). This function uses the ethernet
+ *	struct 'virtual to physical' routine (set by the user) to set the ring
+ *	with physical addresses.
  *
  * INPUT:
- *	struct mv64340_private   *mp   Ethernet Port Control srtuct. 
- *      int 			rx_desc_num       Number of Rx descriptors
- *      int 			rx_buff_size      Size of Rx buffer
- *      unsigned int    rx_desc_base_addr  Rx descriptors memory area base addr.
- *      unsigned int    rx_buff_base_addr  Rx buffer memory area base addr.
+ *	struct mv643xx_private *mp	Ethernet Port Control srtuct.
  *
  * OUTPUT:
- *      The routine updates the Ethernet port control struct with information 
- *      regarding the Rx descriptors and buffers.
+ *	The routine updates the Ethernet port control struct with information
+ *	regarding the Rx descriptors and buffers.
  *
  * RETURN:
- *      false if the given descriptors memory area is not aligned according to
- *      Ethernet SDMA specifications.
- *      true otherwise.
+ *	None.
  */
-static int ether_init_rx_desc_ring(struct mv64340_private * mp,
-	unsigned long rx_buff_base_addr)
+static void ether_init_rx_desc_ring(struct mv643xx_private *mp)
 {
-	unsigned long buffer_addr = rx_buff_base_addr;
 	volatile struct eth_rx_desc *p_rx_desc;
 	int rx_desc_num = mp->rx_ring_size;
-	unsigned long rx_desc_base_addr = (unsigned long) mp->p_rx_desc_area;
-	int rx_buff_size = 1536;	/* Dummy, will be replaced later */
 	int i;
 
-	p_rx_desc = (struct eth_rx_desc *) rx_desc_base_addr;
-
-	/* Rx desc Must be 4LW aligned (i.e. Descriptor_Address[3:0]=0000). */
-	if (rx_buff_base_addr & 0xf)
-		return 0;
-
-	/* Rx buffers are limited to 64K bytes and Minimum size is 8 bytes  */
-	if ((rx_buff_size < 8) || (rx_buff_size > RX_BUFFER_MAX_SIZE))
-		return 0;
-
-	/* Rx buffers must be 64-bit aligned.       */
-	if ((rx_buff_base_addr + rx_buff_size) & 0x7)
-		return 0;
-
-	/* initialize the Rx descriptors ring */
+	/* initialize the next_desc_ptr links in the Rx descriptors ring */
+	p_rx_desc = (struct eth_rx_desc *)mp->p_rx_desc_area;
 	for (i = 0; i < rx_desc_num; i++) {
-		p_rx_desc[i].buf_size = rx_buff_size;
-		p_rx_desc[i].byte_cnt = 0x0000;
-		p_rx_desc[i].cmd_sts =
-			ETH_BUFFER_OWNED_BY_DMA | ETH_RX_ENABLE_INTERRUPT;
 		p_rx_desc[i].next_desc_ptr = mp->rx_desc_dma +
 			((i + 1) % rx_desc_num) * sizeof(struct eth_rx_desc);
-		p_rx_desc[i].buf_ptr = buffer_addr;
-
-		mp->rx_skb[i] = NULL;
-		buffer_addr += rx_buff_size;
 	}
 
 	/* Save Rx desc pointer to driver struct. */
@@ -766,293 +737,288 @@
 
 	mp->rx_desc_area_size = rx_desc_num * sizeof(struct eth_rx_desc);
 
+	/* Add the queue to the list of RX queues of this port */
 	mp->port_rx_queue_command |= 1;
-
-	return 1;
 }
 
 /*
  * ether_init_tx_desc_ring - Curve a Tx chain desc list and buffer in memory.
  *
  * DESCRIPTION:
- *       This function prepares a Tx chained list of descriptors and packet 
- *       buffers in a form of a ring. The routine must be called after port 
- *       initialization routine and before port start routine. 
- *       The Ethernet SDMA engine uses CPU bus addresses to access the various 
- *       devices in the system (i.e. DRAM). This function uses the ethernet 
- *       struct 'virtual to physical' routine (set by the user) to set the ring 
- *       with physical addresses.
+ *	This function prepares a Tx chained list of descriptors and packet
+ *	buffers in a form of a ring. The routine must be called after port
+ *	initialization routine and before port start routine.
+ *	The Ethernet SDMA engine uses CPU bus addresses to access the various
+ *	devices in the system (i.e. DRAM). This function uses the ethernet
+ *	struct 'virtual to physical' routine (set by the user) to set the ring
+ *	with physical addresses.
  *
  * INPUT:
- *	struct mv64340_private   *mp   Ethernet Port Control srtuct. 
- *      int 		tx_desc_num        Number of Tx descriptors
- *      int 		tx_buff_size	   Size of Tx buffer
- *      unsigned int    tx_desc_base_addr  Tx descriptors memory area base addr.
+ *	struct mv643xx_private *mp	Ethernet Port Control srtuct.
  *
  * OUTPUT:
- *      The routine updates the Ethernet port control struct with information 
- *      regarding the Tx descriptors and buffers.
+ *	The routine updates the Ethernet port control struct with information
+ *	regarding the Tx descriptors and buffers.
  *
  * RETURN:
- *      false if the given descriptors memory area is not aligned according to
- *      Ethernet SDMA specifications.
- *      true otherwise.
+ *	None.
  */
-static int ether_init_tx_desc_ring(struct mv64340_private *mp)
+static void ether_init_tx_desc_ring(struct mv643xx_private *mp)
 {
-	unsigned long tx_desc_base_addr = (unsigned long) mp->p_tx_desc_area;
 	int tx_desc_num = mp->tx_ring_size;
 	struct eth_tx_desc *p_tx_desc;
 	int i;
 
-	/* Tx desc Must be 4LW aligned (i.e. Descriptor_Address[3:0]=0000). */
-	if (tx_desc_base_addr & 0xf)
-		return 0;
-
-	/* save the first desc pointer to link with the last descriptor */
-	p_tx_desc = (struct eth_tx_desc *) tx_desc_base_addr;
-
-	/* Initialize the Tx descriptors ring */
+	/* Initialize the next_desc_ptr links in the Tx descriptors ring */
+	p_tx_desc = (struct eth_tx_desc *)mp->p_tx_desc_area;
 	for (i = 0; i < tx_desc_num; i++) {
-		p_tx_desc[i].byte_cnt	= 0x0000;
-		p_tx_desc[i].l4i_chk	= 0x0000;
-		p_tx_desc[i].cmd_sts	= 0x00000000;
 		p_tx_desc[i].next_desc_ptr = mp->tx_desc_dma +
 			((i + 1) % tx_desc_num) * sizeof(struct eth_tx_desc);
-		p_tx_desc[i].buf_ptr	= 0x00000000;
-		mp->tx_skb[i]		= NULL;
 	}
 
-	/* Set Tx desc pointer in driver struct. */
 	mp->tx_curr_desc_q = 0;
 	mp->tx_used_desc_q = 0;
-#ifdef MV64340_CHECKSUM_OFFLOAD_TX
-        mp->tx_first_desc_q = 0;
+#ifdef MV643XX_CHECKSUM_OFFLOAD_TX
+	mp->tx_first_desc_q = 0;
 #endif
-	/* Init Tx ring base and size parameters */
-	mp->tx_desc_area_size	= tx_desc_num * sizeof(struct eth_tx_desc);
+
+	mp->tx_desc_area_size = tx_desc_num * sizeof(struct eth_tx_desc);
 
 	/* Add the queue to the list of Tx queues of this port */
 	mp->port_tx_queue_command |= 1;
-
-	return 1;
 }
 
-/* Helper function for mv64340_eth_open */
-static int mv64340_eth_real_open(struct net_device *dev)
+/* Helper function for mv643xx_eth_open */
+static int mv643xx_eth_real_open(struct net_device *dev)
 {
-	struct mv64340_private *mp = netdev_priv(dev);
+	struct mv643xx_private *mp = netdev_priv(dev);
 	unsigned int port_num = mp->port_num;
-	u32 phy_reg_data;
 	unsigned int size;
 
 	/* Stop RX Queues */
-	MV_WRITE(MV64340_ETH_RECEIVE_QUEUE_COMMAND_REG(port_num),
-		 0x0000ff00);
+	mv_write(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(port_num), 0x0000ff00);
 
 	/* Clear the ethernet port interrupts */
-	MV_WRITE(MV64340_ETH_INTERRUPT_CAUSE_REG(port_num), 0);
-	MV_WRITE(MV64340_ETH_INTERRUPT_CAUSE_EXTEND_REG(port_num), 0);
+	mv_write(MV643XX_ETH_INTERRUPT_CAUSE_REG(port_num), 0);
+	mv_write(MV643XX_ETH_INTERRUPT_CAUSE_EXTEND_REG(port_num), 0);
 
 	/* Unmask RX buffer and TX end interrupt */
-	MV_WRITE(MV64340_ETH_INTERRUPT_MASK_REG(port_num),
-		 INT_CAUSE_UNMASK_ALL);
+	mv_write(MV643XX_ETH_INTERRUPT_MASK_REG(port_num),
+						INT_CAUSE_UNMASK_ALL);
 
 	/* Unmask phy and link status changes interrupts */
-	MV_WRITE(MV64340_ETH_INTERRUPT_EXTEND_MASK_REG(port_num),
-		 INT_CAUSE_UNMASK_ALL_EXT);
+	mv_write(MV643XX_ETH_INTERRUPT_EXTEND_MASK_REG(port_num),
+						INT_CAUSE_UNMASK_ALL_EXT);
 
 	/* Set the MAC Address */
 	memcpy(mp->port_mac_addr, dev->dev_addr, 6);
 
 	eth_port_init(mp);
 
-	INIT_WORK(&mp->rx_task, (void (*)(void *)) mv64340_eth_rx_task, dev);
+	INIT_WORK(&mp->rx_task, (void (*)(void *))mv643xx_eth_rx_task, dev);
 
 	memset(&mp->timeout, 0, sizeof(struct timer_list));
-	mp->timeout.function = mv64340_eth_rx_task_timer_wrapper;
-	mp->timeout.data = (unsigned long) dev;
+	mp->timeout.function = mv643xx_eth_rx_task_timer_wrapper;
+	mp->timeout.data = (unsigned long)dev;
 
 	mp->rx_task_busy = 0;
 	mp->rx_timer_flag = 0;
 
+	/* Allocate RX and TX skb rings */
+	mp->rx_skb = kmalloc(sizeof(*mp->rx_skb) * mp->rx_ring_size,
+								GFP_KERNEL);
+	if (!mp->rx_skb) {
+		printk(KERN_ERR "%s: Cannot allocate Rx skb ring\n", dev->name);
+		return -ENOMEM;
+	}
+	mp->tx_skb = kmalloc(sizeof(*mp->tx_skb) * mp->tx_ring_size,
+								GFP_KERNEL);
+	if (!mp->tx_skb) {
+		printk(KERN_ERR "%s: Cannot allocate Tx skb ring\n", dev->name);
+		kfree(mp->rx_skb);
+		return -ENOMEM;
+	}
+
 	/* Allocate TX ring */
 	mp->tx_ring_skbs = 0;
-	mp->tx_ring_size = MV64340_TX_QUEUE_SIZE;
 	size = mp->tx_ring_size * sizeof(struct eth_tx_desc);
 	mp->tx_desc_area_size = size;
 
-	/* Assumes allocated ring is 16 bytes alligned */
-	mp->p_tx_desc_area = pci_alloc_consistent(NULL, size, &mp->tx_desc_dma);
+	if (mp->tx_sram_size) {
+		mp->p_tx_desc_area = ioremap(mp->tx_sram_addr,
+							mp->tx_sram_size);
+		mp->tx_desc_dma = mp->tx_sram_addr;
+	} else
+		mp->p_tx_desc_area = dma_alloc_coherent(NULL, size,
+							&mp->tx_desc_dma,
+							GFP_KERNEL);
+
 	if (!mp->p_tx_desc_area) {
 		printk(KERN_ERR "%s: Cannot allocate Tx Ring (size %d bytes)\n",
-		       dev->name, size);
+							dev->name, size);
+		kfree(mp->rx_skb);
+		kfree(mp->tx_skb);
 		return -ENOMEM;
 	}
-	memset((void *) mp->p_tx_desc_area, 0, mp->tx_desc_area_size);
+	BUG_ON((u32) mp->p_tx_desc_area & 0xf);	/* check 16-byte alignment */
+	memset((void *)mp->p_tx_desc_area, 0, mp->tx_desc_area_size);
 
-	/* Dummy will be replaced upon real tx */
 	ether_init_tx_desc_ring(mp);
 
 	/* Allocate RX ring */
-	/* Meantime RX Ring are fixed - but must be configurable by user */
-	mp->rx_ring_size = MV64340_RX_QUEUE_SIZE;
 	mp->rx_ring_skbs = 0;
 	size = mp->rx_ring_size * sizeof(struct eth_rx_desc);
 	mp->rx_desc_area_size = size;
 
-	/* Assumes allocated ring is 16 bytes aligned */
-
-	mp->p_rx_desc_area = pci_alloc_consistent(NULL, size, &mp->rx_desc_dma);
+	if (mp->rx_sram_size) {
+		mp->p_rx_desc_area = ioremap(mp->rx_sram_addr,
+							mp->rx_sram_size);
+		mp->rx_desc_dma = mp->rx_sram_addr;
+	} else
+		mp->p_rx_desc_area = dma_alloc_coherent(NULL, size,
+							&mp->rx_desc_dma,
+							GFP_KERNEL);
 
 	if (!mp->p_rx_desc_area) {
 		printk(KERN_ERR "%s: Cannot allocate Rx ring (size %d bytes)\n",
-		       dev->name, size);
+							dev->name, size);
 		printk(KERN_ERR "%s: Freeing previously allocated TX queues...",
-		       dev->name);
-		pci_free_consistent(0, mp->tx_desc_area_size,
-				    (void *) mp->p_tx_desc_area,
-				    mp->tx_desc_dma);
+							dev->name);
+		if (mp->rx_sram_size)
+			iounmap(mp->p_rx_desc_area);
+		else
+			dma_free_coherent(NULL, mp->tx_desc_area_size,
+					mp->p_tx_desc_area, mp->tx_desc_dma);
+		kfree(mp->rx_skb);
+		kfree(mp->tx_skb);
 		return -ENOMEM;
 	}
-	memset(mp->p_rx_desc_area, 0, size);
+	memset((void *)mp->p_rx_desc_area, 0, size);
 
-	if (!(ether_init_rx_desc_ring(mp, 0)))
-		panic("%s: Error initializing RX Ring", dev->name);
+	ether_init_rx_desc_ring(mp);
 
-	mv64340_eth_rx_task(dev);	/* Fill RX ring with skb's */
+	mv643xx_eth_rx_task(dev);	/* Fill RX ring with skb's */
 
 	eth_port_start(mp);
 
 	/* Interrupt Coalescing */
 
-#ifdef MV64340_COAL
+#ifdef MV643XX_COAL
 	mp->rx_int_coal =
-		eth_port_set_rx_coal(port_num, 133000000, MV64340_RX_COAL);
+		eth_port_set_rx_coal(port_num, 133000000, MV643XX_RX_COAL);
 #endif
 
 	mp->tx_int_coal =
-		eth_port_set_tx_coal (port_num, 133000000, MV64340_TX_COAL);  
+		eth_port_set_tx_coal(port_num, 133000000, MV643XX_TX_COAL);
 
-	/* Increase the Rx side buffer size */
-
-	MV_WRITE (MV64340_ETH_PORT_SERIAL_CONTROL_REG(port_num), (0x5 << 17) |
-			(MV_READ(MV64340_ETH_PORT_SERIAL_CONTROL_REG(port_num))
-					& 0xfff1ffff));
-
-	/* Check Link status on phy */
-	eth_port_read_smi_reg(port_num, 1, &phy_reg_data);
-	if (!(phy_reg_data & 0x20))
-		netif_stop_queue(dev);
-	else
-		netif_start_queue(dev);
+	netif_start_queue(dev);
 
 	return 0;
 }
 
-static void mv64340_eth_free_tx_rings(struct net_device *dev)
+static void mv643xx_eth_free_tx_rings(struct net_device *dev)
 {
-	struct mv64340_private *mp = netdev_priv(dev);
+	struct mv643xx_private *mp = netdev_priv(dev);
 	unsigned int port_num = mp->port_num;
 	unsigned int curr;
 
 	/* Stop Tx Queues */
-	MV_WRITE(MV64340_ETH_TRANSMIT_QUEUE_COMMAND_REG(port_num),
-		 0x0000ff00);
+	mv_write(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(port_num), 0x0000ff00);
 
-	/* Free TX rings */
 	/* Free outstanding skb's on TX rings */
-	for (curr = 0;
-	     (mp->tx_ring_skbs) && (curr < MV64340_TX_QUEUE_SIZE);
-	     curr++) {
+	for (curr = 0; mp->tx_ring_skbs && curr < mp->tx_ring_size; curr++) {
 		if (mp->tx_skb[curr]) {
 			dev_kfree_skb(mp->tx_skb[curr]);
 			mp->tx_ring_skbs--;
 		}
 	}
-	if (mp->tx_ring_skbs != 0)
+	if (mp->tx_ring_skbs)
 		printk("%s: Error on Tx descriptor free - could not free %d"
-		     " descriptors\n", dev->name,
-		     mp->tx_ring_skbs);
-	pci_free_consistent(0, mp->tx_desc_area_size,
-			    (void *) mp->p_tx_desc_area, mp->tx_desc_dma);
+				" descriptors\n", dev->name, mp->tx_ring_skbs);
+
+	/* Free TX ring */
+	if (mp->tx_sram_size)
+		iounmap(mp->p_tx_desc_area);
+	else
+		dma_free_coherent(NULL, mp->tx_desc_area_size,
+				mp->p_tx_desc_area, mp->tx_desc_dma);
 }
 
-static void mv64340_eth_free_rx_rings(struct net_device *dev)
+static void mv643xx_eth_free_rx_rings(struct net_device *dev)
 {
-	struct mv64340_private *mp = netdev_priv(dev);
+	struct mv643xx_private *mp = netdev_priv(dev);
 	unsigned int port_num = mp->port_num;
 	int curr;
 
 	/* Stop RX Queues */
-	MV_WRITE(MV64340_ETH_RECEIVE_QUEUE_COMMAND_REG(port_num),
-		 0x0000ff00);
+	mv_write(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(port_num), 0x0000ff00);
 
-	/* Free RX rings */
 	/* Free preallocated skb's on RX rings */
-	for (curr = 0;
-		mp->rx_ring_skbs && (curr < MV64340_RX_QUEUE_SIZE);
-		curr++) {
+	for (curr = 0; mp->rx_ring_skbs && curr < mp->rx_ring_size; curr++) {
 		if (mp->rx_skb[curr]) {
 			dev_kfree_skb(mp->rx_skb[curr]);
 			mp->rx_ring_skbs--;
 		}
 	}
 
-	if (mp->rx_ring_skbs != 0)
+	if (mp->rx_ring_skbs)
 		printk(KERN_ERR
-		       "%s: Error in freeing Rx Ring. %d skb's still"
-		       " stuck in RX Ring - ignoring them\n", dev->name,
-		       mp->rx_ring_skbs);
-	pci_free_consistent(0, mp->rx_desc_area_size,
-			    (void *) mp->p_rx_desc_area,
-			    mp->rx_desc_dma);
+			"%s: Error in freeing Rx Ring. %d skb's still"
+			" stuck in RX Ring - ignoring them\n", dev->name,
+			mp->rx_ring_skbs);
+	/* Free RX ring */
+	if (mp->rx_sram_size)
+		iounmap(mp->p_rx_desc_area);
+	else
+		dma_free_coherent(NULL, mp->rx_desc_area_size,
+				mp->p_rx_desc_area, mp->rx_desc_dma);
 }
 
 /*
- * mv64340_eth_stop
+ * mv643xx_eth_stop
  *
- * This function is used when closing the network device. 
- * It updates the hardware, 
+ * This function is used when closing the network device.
+ * It updates the hardware,
  * release all memory that holds buffers and descriptors and release the IRQ.
- * Input : a pointer to the device structure
- * Output : zero if success , nonzero if fails
+ * Input :	a pointer to the device structure
+ * Output :	zero if success , nonzero if fails
  */
 
-/* Helper function for mv64340_eth_stop */
+/* Helper function for mv643xx_eth_stop */
 
-static int mv64340_eth_real_stop(struct net_device *dev)
+static int mv643xx_eth_real_stop(struct net_device *dev)
 {
-	struct mv64340_private *mp = netdev_priv(dev);
+	struct mv643xx_private *mp = netdev_priv(dev);
 	unsigned int port_num = mp->port_num;
 
+	netif_carrier_off(dev);
 	netif_stop_queue(dev);
 
-	mv64340_eth_free_tx_rings(dev);
-	mv64340_eth_free_rx_rings(dev);
+	mv643xx_eth_free_tx_rings(dev);
+	mv643xx_eth_free_rx_rings(dev);
 
 	eth_port_reset(mp->port_num);
 
 	/* Disable ethernet port interrupts */
-	MV_WRITE(MV64340_ETH_INTERRUPT_CAUSE_REG(port_num), 0);
-	MV_WRITE(MV64340_ETH_INTERRUPT_CAUSE_EXTEND_REG(port_num), 0);
+	mv_write(MV643XX_ETH_INTERRUPT_CAUSE_REG(port_num), 0);
+	mv_write(MV643XX_ETH_INTERRUPT_CAUSE_EXTEND_REG(port_num), 0);
 
 	/* Mask RX buffer and TX end interrupt */
-	MV_WRITE(MV64340_ETH_INTERRUPT_MASK_REG(port_num), 0);
+	mv_write(MV643XX_ETH_INTERRUPT_MASK_REG(port_num), 0);
 
 	/* Mask phy and link status changes interrupts */
-	MV_WRITE(MV64340_ETH_INTERRUPT_EXTEND_MASK_REG(port_num), 0);
+	mv_write(MV643XX_ETH_INTERRUPT_EXTEND_MASK_REG(port_num), 0);
 
 	return 0;
 }
 
-static int mv64340_eth_stop(struct net_device *dev)
+static int mv643xx_eth_stop(struct net_device *dev)
 {
-	struct mv64340_private *mp = netdev_priv(dev);
+	struct mv643xx_private *mp = netdev_priv(dev);
 
 	spin_lock_irq(&mp->lock);
 
-	mv64340_eth_real_stop(dev);
+	mv643xx_eth_real_stop(dev);
 
 	free_irq(dev->irq, dev);
 	spin_unlock_irq(&mp->lock);
@@ -1060,59 +1026,64 @@
 	return 0;
 }
 
-#ifdef MV64340_NAPI
-static void mv64340_tx(struct net_device *dev)
+#ifdef MV643XX_NAPI
+static void mv643xx_tx(struct net_device *dev)
 {
-	struct mv64340_private *mp = netdev_priv(dev);
-        struct pkt_info pkt_info;
+	struct mv643xx_private *mp = netdev_priv(dev);
+	struct pkt_info pkt_info;
 
 	while (eth_tx_return_desc(mp, &pkt_info) == ETH_OK) {
 		if (pkt_info.return_info) {
-			dev_kfree_skb_irq((struct sk_buff *)
-                                                  pkt_info.return_info);
-			if (skb_shinfo(pkt_info.return_info)->nr_frags) 
-                                 pci_unmap_page(NULL, pkt_info.buf_ptr,
-                                             pkt_info.byte_cnt,
-                                             PCI_DMA_TODEVICE);
-
-                         if (mp->tx_ring_skbs != 1)
-                                  mp->tx_ring_skbs--;
-                } else 
-                       pci_unmap_page(NULL, pkt_info.buf_ptr, pkt_info.byte_cnt,
-                                      PCI_DMA_TODEVICE);
+			if (skb_shinfo(pkt_info.return_info)->nr_frags)
+				dma_unmap_page(NULL, pkt_info.buf_ptr,
+						pkt_info.byte_cnt,
+						DMA_TO_DEVICE);
+			else
+				dma_unmap_single(NULL, pkt_info.buf_ptr,
+						pkt_info.byte_cnt,
+						DMA_TO_DEVICE);
+
+			dev_kfree_skb_irq(pkt_info.return_info);
+
+			if (mp->tx_ring_skbs)
+				mp->tx_ring_skbs--;
+		} else
+			dma_unmap_page(NULL, pkt_info.buf_ptr,
+					pkt_info.byte_cnt, DMA_TO_DEVICE);
 	}
 
 	if (netif_queue_stopped(dev) &&
-            MV64340_TX_QUEUE_SIZE > mp->tx_ring_skbs + 1)
-                       netif_wake_queue(dev);
+			mp->tx_ring_size > mp->tx_ring_skbs + MAX_DESCS_PER_SKB)
+		netif_wake_queue(dev);
 }
 
 /*
- * mv64340_poll
+ * mv643xx_poll
  *
  * This function is used in case of NAPI
  */
-static int mv64340_poll(struct net_device *dev, int *budget)
+static int mv643xx_poll(struct net_device *dev, int *budget)
 {
-	struct mv64340_private *mp = netdev_priv(dev);
-	int	done = 1, orig_budget, work_done;
+	struct mv643xx_private *mp = netdev_priv(dev);
+	int done = 1, orig_budget, work_done;
 	unsigned int port_num = mp->port_num;
 	unsigned long flags;
 
-#ifdef MV64340_TX_FAST_REFILL
+#ifdef MV643XX_TX_FAST_REFILL
 	if (++mp->tx_clean_threshold > 5) {
 		spin_lock_irqsave(&mp->lock, flags);
-		mv64340_tx(dev);
+		mv643xx_tx(dev);
 		mp->tx_clean_threshold = 0;
 		spin_unlock_irqrestore(&mp->lock, flags);
 	}
 #endif
 
-	if ((u32)(MV_READ(MV64340_ETH_RX_CURRENT_QUEUE_DESC_PTR_0(port_num)))                                      != (u32)mp->rx_used_desc_q) {
+	if ((mv_read(MV643XX_ETH_RX_CURRENT_QUEUE_DESC_PTR_0(port_num)))
+						!= (u32) mp->rx_used_desc_q) {
 		orig_budget = *budget;
 		if (orig_budget > dev->quota)
 			orig_budget = dev->quota;
-		work_done = mv64340_eth_receive_queue(dev, 0, orig_budget);
+		work_done = mv643xx_eth_receive_queue(dev, orig_budget);
 		mp->rx_task.func(dev);
 		*budget -= work_done;
 		dev->quota -= work_done;
@@ -1123,12 +1094,12 @@
 	if (done) {
 		spin_lock_irqsave(&mp->lock, flags);
 		__netif_rx_complete(dev);
-		MV_WRITE(MV64340_ETH_INTERRUPT_CAUSE_REG(port_num),0);
-                MV_WRITE(MV64340_ETH_INTERRUPT_CAUSE_EXTEND_REG(port_num),0);
-		MV_WRITE(MV64340_ETH_INTERRUPT_MASK_REG(port_num), 
+		mv_write(MV643XX_ETH_INTERRUPT_CAUSE_REG(port_num), 0);
+		mv_write(MV643XX_ETH_INTERRUPT_CAUSE_EXTEND_REG(port_num), 0);
+		mv_write(MV643XX_ETH_INTERRUPT_MASK_REG(port_num),
 						INT_CAUSE_UNMASK_ALL);
-		MV_WRITE(MV64340_ETH_INTERRUPT_EXTEND_MASK_REG(port_num),
-				                 INT_CAUSE_UNMASK_ALL_EXT);
+		mv_write(MV643XX_ETH_INTERRUPT_EXTEND_MASK_REG(port_num),
+						INT_CAUSE_UNMASK_ALL_EXT);
 		spin_unlock_irqrestore(&mp->lock, flags);
 	}
 
@@ -1137,19 +1108,19 @@
 #endif
 
 /*
- * mv64340_eth_start_xmit
+ * mv643xx_eth_start_xmit
  *
- * This function is queues a packet in the Tx descriptor for 
+ * This function is queues a packet in the Tx descriptor for
  * required port.
  *
- * Input : skb - a pointer to socket buffer
- *         dev - a pointer to the required port
+ * Input :	skb - a pointer to socket buffer
+ *		dev - a pointer to the required port
  *
- * Output : zero upon success
+ * Output :	zero upon success
  */
-static int mv64340_eth_start_xmit(struct sk_buff *skb, struct net_device *dev)
+static int mv643xx_eth_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
-	struct mv64340_private *mp = netdev_priv(dev);
+	struct mv643xx_private *mp = netdev_priv(dev);
 	struct net_device_stats *stats = &mp->stats;
 	ETH_FUNC_RET_STATUS status;
 	unsigned long flags;
@@ -1157,119 +1128,195 @@
 
 	if (netif_queue_stopped(dev)) {
 		printk(KERN_ERR
-		       "%s: Tried sending packet when interface is stopped\n",
-		       dev->name);
+			"%s: Tried sending packet when interface is stopped\n",
+			dev->name);
 		return 1;
 	}
 
 	/* This is a hard error, log it. */
-	if ((MV64340_TX_QUEUE_SIZE - mp->tx_ring_skbs) <=
-	    (skb_shinfo(skb)->nr_frags + 1)) {
+	if ((mp->tx_ring_size - mp->tx_ring_skbs) <=
+					(skb_shinfo(skb)->nr_frags + 1)) {
 		netif_stop_queue(dev);
 		printk(KERN_ERR
-		       "%s: Bug in mv64340_eth - Trying to transmit when"
-		       " queue full !\n", dev->name);
+			"%s: Bug in mv643xx_eth - Trying to transmit when"
+			" queue full !\n", dev->name);
 		return 1;
 	}
 
 	/* Paranoid check - this shouldn't happen */
 	if (skb == NULL) {
 		stats->tx_dropped++;
+		printk(KERN_ERR "mv64320_eth paranoid check failed\n");
 		return 1;
 	}
 
 	spin_lock_irqsave(&mp->lock, flags);
 
 	/* Update packet info data structure -- DMA owned, first last */
-#ifdef MV64340_CHECKSUM_OFFLOAD_TX
-	if (!skb_shinfo(skb)->nr_frags || (skb_shinfo(skb)->nr_frags > 3)) {
-#endif
-		pkt_info.cmd_sts = ETH_TX_ENABLE_INTERRUPT |
-	    	                   ETH_TX_FIRST_DESC | ETH_TX_LAST_DESC;
+#ifdef MV643XX_CHECKSUM_OFFLOAD_TX
+	if (!skb_shinfo(skb)->nr_frags) {
+linear:
+		if (skb->ip_summed != CHECKSUM_HW) {
+			pkt_info.cmd_sts = ETH_TX_ENABLE_INTERRUPT |
+					ETH_TX_FIRST_DESC | ETH_TX_LAST_DESC;
+			pkt_info.l4i_chk = 0;
+		} else {
+			u32 ipheader = skb->nh.iph->ihl << 11;
 
+			pkt_info.cmd_sts = ETH_TX_ENABLE_INTERRUPT |
+					ETH_TX_FIRST_DESC | ETH_TX_LAST_DESC |
+					ETH_GEN_TCP_UDP_CHECKSUM |
+					ETH_GEN_IP_V_4_CHECKSUM | ipheader;
+			/* CPU already calculated pseudo header checksum. */
+			if (skb->nh.iph->protocol == IPPROTO_UDP) {
+				pkt_info.cmd_sts |= ETH_UDP_FRAME;
+				pkt_info.l4i_chk = skb->h.uh->check;
+			} else if (skb->nh.iph->protocol == IPPROTO_TCP)
+				pkt_info.l4i_chk = skb->h.th->check;
+			else {
+				printk(KERN_ERR
+					"%s: chksum proto != TCP or UDP\n",
+					dev->name);
+				spin_unlock_irqrestore(&mp->lock, flags);
+				return 1;
+			}
+		}
 		pkt_info.byte_cnt = skb->len;
-		pkt_info.buf_ptr = pci_map_single(0, skb->data, skb->len,
-		                                  PCI_DMA_TODEVICE);
-
-
+		pkt_info.buf_ptr = dma_map_single(NULL, skb->data, skb->len,
+							DMA_TO_DEVICE);
 		pkt_info.return_info = skb;
+		mp->tx_ring_skbs++;
 		status = eth_port_send(mp, &pkt_info);
 		if ((status == ETH_ERROR) || (status == ETH_QUEUE_FULL))
 			printk(KERN_ERR "%s: Error on transmitting packet\n",
-				       dev->name);
-		mp->tx_ring_skbs++;
-#ifdef MV64340_CHECKSUM_OFFLOAD_TX
+								dev->name);
+		stats->tx_bytes += pkt_info.byte_cnt;
 	} else {
-		unsigned int    frag;
-		u32		ipheader;
+		unsigned int frag;
+		u32 ipheader;
 
-                /* first frag which is skb header */
-                pkt_info.byte_cnt = skb_headlen(skb);
-                pkt_info.buf_ptr = pci_map_single(0, skb->data,
-                                        skb_headlen(skb), PCI_DMA_TODEVICE);
-                pkt_info.return_info = 0;
-                ipheader = skb->nh.iph->ihl << 11;
-                pkt_info.cmd_sts = ETH_TX_FIRST_DESC | 
-					ETH_GEN_TCP_UDP_CHECKSUM |
-					ETH_GEN_IP_V_4_CHECKSUM |
-                                        ipheader;
-		/* CPU already calculated pseudo header checksum. So, use it */
-                pkt_info.l4i_chk = skb->h.th->check;
-                status = eth_port_send(mp, &pkt_info);
+		/* Since hardware can't handle unaligned fragments smaller
+		 * than 9 bytes, if we find any, we linearize the skb
+		 * and start again.  When I've seen it, it's always been
+		 * the first frag (probably near the end of the page),
+		 * but we check all frags to be safe.
+		 */
+		for (frag = 0; frag < skb_shinfo(skb)->nr_frags; frag++) {
+			skb_frag_t *fragp;
+
+			fragp = &skb_shinfo(skb)->frags[frag];
+			if (fragp->size <= 8 && fragp->page_offset & 0x7) {
+				skb_linearize(skb, GFP_ATOMIC);
+				printk(KERN_DEBUG "%s: unaligned tiny fragment"
+						"%d of %d, fixed\n",
+						dev->name, frag,
+						skb_shinfo(skb)->nr_frags);
+				goto linear;
+			}
+		}
+
+		/* first frag which is skb header */
+		pkt_info.byte_cnt = skb_headlen(skb);
+		pkt_info.buf_ptr = dma_map_single(NULL, skb->data,
+							skb_headlen(skb),
+							DMA_TO_DEVICE);
+		pkt_info.l4i_chk = 0;
+		pkt_info.return_info = 0;
+		pkt_info.cmd_sts = ETH_TX_FIRST_DESC;
+
+		if (skb->ip_summed == CHECKSUM_HW) {
+			ipheader = skb->nh.iph->ihl << 11;
+			pkt_info.cmd_sts |= ETH_GEN_TCP_UDP_CHECKSUM |
+					ETH_GEN_IP_V_4_CHECKSUM | ipheader;
+			/* CPU already calculated pseudo header checksum. */
+			if (skb->nh.iph->protocol == IPPROTO_UDP) {
+				pkt_info.cmd_sts |= ETH_UDP_FRAME;
+				pkt_info.l4i_chk = skb->h.uh->check;
+			} else if (skb->nh.iph->protocol == IPPROTO_TCP)
+				pkt_info.l4i_chk = skb->h.th->check;
+			else {
+				printk(KERN_ERR
+					"%s: chksum proto != TCP or UDP\n",
+					dev->name);
+				spin_unlock_irqrestore(&mp->lock, flags);
+				return 1;
+			}
+		}
+
+		status = eth_port_send(mp, &pkt_info);
 		if (status != ETH_OK) {
-	                if ((status == ETH_ERROR))
-        	                printk(KERN_ERR "%s: Error on transmitting packet\n", dev->name);
-	                if (status == ETH_QUEUE_FULL)
-        	                printk("Error on Queue Full \n");
-                	if (status == ETH_QUEUE_LAST_RESOURCE)
-                        	printk("Tx resource error \n");
+			if ((status == ETH_ERROR))
+				printk(KERN_ERR
+					"%s: Error on transmitting packet\n",
+					dev->name);
+			if (status == ETH_QUEUE_FULL)
+				printk("Error on Queue Full \n");
+			if (status == ETH_QUEUE_LAST_RESOURCE)
+				printk("Tx resource error \n");
 		}
+		stats->tx_bytes += pkt_info.byte_cnt;
+
+		/* Check for the remaining frags */
+		for (frag = 0; frag < skb_shinfo(skb)->nr_frags; frag++) {
+			skb_frag_t *this_frag = &skb_shinfo(skb)->frags[frag];
+			pkt_info.l4i_chk = 0x0000;
+			pkt_info.cmd_sts = 0x00000000;
+
+			/* Last Frag enables interrupt and frees the skb */
+			if (frag == (skb_shinfo(skb)->nr_frags - 1)) {
+				pkt_info.cmd_sts |= ETH_TX_ENABLE_INTERRUPT |
+							ETH_TX_LAST_DESC;
+				pkt_info.return_info = skb;
+				mp->tx_ring_skbs++;
+			} else {
+				pkt_info.return_info = 0;
+			}
+			pkt_info.l4i_chk = 0;
+			pkt_info.byte_cnt = this_frag->size;
 
-                /* Check for the remaining frags */
-                for (frag = 0; frag < skb_shinfo(skb)->nr_frags; frag++) {
-                        skb_frag_t *this_frag = &skb_shinfo(skb)->frags[frag];
-                        pkt_info.l4i_chk = 0x0000;
-                        pkt_info.cmd_sts = 0x00000000;
-
-                        /* Last Frag enables interrupt and frees the skb */
-                        if (frag == (skb_shinfo(skb)->nr_frags - 1)) {
-                                pkt_info.cmd_sts |= ETH_TX_ENABLE_INTERRUPT |
-                                                        ETH_TX_LAST_DESC;
-                                pkt_info.return_info = skb;
-                                mp->tx_ring_skbs++;
-                        }
-                        else {
-                                pkt_info.return_info = 0;
-                        }
-                        pkt_info.byte_cnt = this_frag->size;
-                        if (this_frag->size < 8)
-                                printk("%d : \n", skb_shinfo(skb)->nr_frags);
-
-                        pkt_info.buf_ptr = pci_map_page(NULL, this_frag->page,
-                                        this_frag->page_offset,
-                                        this_frag->size, PCI_DMA_TODEVICE);
+			pkt_info.buf_ptr = dma_map_page(NULL, this_frag->page,
+							this_frag->page_offset,
+							this_frag->size,
+							DMA_TO_DEVICE);
 
-                        status = eth_port_send(mp, &pkt_info);
+			status = eth_port_send(mp, &pkt_info);
 
 			if (status != ETH_OK) {
-	                        if ((status == ETH_ERROR))
-        	                        printk(KERN_ERR "%s: Error on transmitting packet\n", dev->name);
+				if ((status == ETH_ERROR))
+					printk(KERN_ERR "%s: Error on "
+							"transmitting packet\n",
+							dev->name);
 
-       		                 if (status == ETH_QUEUE_LAST_RESOURCE)
-                	                printk("Tx resource error \n");
+				if (status == ETH_QUEUE_LAST_RESOURCE)
+					printk("Tx resource error \n");
 
-                        	if (status == ETH_QUEUE_FULL)
-                                	printk("Queue is full \n");
+				if (status == ETH_QUEUE_FULL)
+					printk("Queue is full \n");
 			}
-                }
-        }
+			stats->tx_bytes += pkt_info.byte_cnt;
+		}
+	}
+#else
+	pkt_info.cmd_sts = ETH_TX_ENABLE_INTERRUPT | ETH_TX_FIRST_DESC |
+							ETH_TX_LAST_DESC;
+	pkt_info.l4i_chk = 0;
+	pkt_info.byte_cnt = skb->len;
+	pkt_info.buf_ptr = dma_map_single(NULL, skb->data, skb->len,
+								DMA_TO_DEVICE);
+	pkt_info.return_info = skb;
+	mp->tx_ring_skbs++;
+	status = eth_port_send(mp, &pkt_info);
+	if ((status == ETH_ERROR) || (status == ETH_QUEUE_FULL))
+		printk(KERN_ERR "%s: Error on transmitting packet\n",
+								dev->name);
+	stats->tx_bytes += pkt_info.byte_cnt;
 #endif
 
 	/* Check if TX queue can handle another skb. If not, then
 	 * signal higher layers to stop requesting TX
 	 */
-	if (MV64340_TX_QUEUE_SIZE <= (mp->tx_ring_skbs + 1))
-		/* 
+	if (mp->tx_ring_size <= (mp->tx_ring_skbs + MAX_DESCS_PER_SKB))
+		/*
 		 * Stop getting skb's from upper layers.
 		 * Getting skb's from upper layers will be enabled again after
 		 * packets are released.
@@ -1277,7 +1324,6 @@
 		netif_stop_queue(dev);
 
 	/* Update statistics and start of transmittion time */
-	stats->tx_bytes += skb->len;
 	stats->tx_packets++;
 	dev->trans_start = jiffies;
 
@@ -1287,214 +1333,302 @@
 }
 
 /*
- * mv64340_eth_get_stats
+ * mv643xx_eth_get_stats
  *
  * Returns a pointer to the interface statistics.
  *
- * Input : dev - a pointer to the required interface
+ * Input :	dev - a pointer to the required interface
  *
- * Output : a pointer to the interface's statistics
+ * Output :	a pointer to the interface's statistics
  */
 
-static struct net_device_stats *mv64340_eth_get_stats(struct net_device *dev)
+static struct net_device_stats *mv643xx_eth_get_stats(struct net_device *dev)
 {
-	struct mv64340_private *mp = netdev_priv(dev);
+	struct mv643xx_private *mp = netdev_priv(dev);
 
 	return &mp->stats;
 }
 
 /*/
- * mv64340_eth_init
- *								       
- * First function called after registering the network device. 
- * It's purpose is to initialize the device as an ethernet device, 
- * fill the structure that was given in registration with pointers
- * to functions, and setting the MAC address of the interface
+ * mv643xx_eth_probe
  *
- * Input : number of port to initialize
- * Output : -ENONMEM if failed , 0 if success
- */
-static struct net_device *mv64340_eth_init(int port_num)
-{
-	struct mv64340_private *mp;
+ * First function called after registering the network device.
+ * It's purpose is to initialize the device as an ethernet device,
+ * fill the ethernet device structure with pointers * to functions,
+ * and set the MAC address of the interface
+ *
+ * Input :	struct device *
+ * Output :	-ENOMEM if failed , 0 if success
+ */
+static int mv643xx_eth_probe(struct device *ddev)
+{
+	struct platform_device *pdev = to_platform_device(ddev);
+	struct mv643xx_eth_platform_data *pd;
+	int port_num = pdev->id;
+	struct mv643xx_private *mp;
 	struct net_device *dev;
+	u8 *p;
+	struct resource *res;
 	int err;
 
-	dev = alloc_etherdev(sizeof(struct mv64340_private));
+	dev = alloc_etherdev(sizeof(struct mv643xx_private));
 	if (!dev)
-		return NULL;
+		return -ENOMEM;
+
+	dev_set_drvdata(ddev, dev);
 
 	mp = netdev_priv(dev);
 
-	dev->irq = ETH_PORT0_IRQ_NUM + port_num;
+	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	BUG_ON(!res);
+	dev->irq = res->start;
 
-	dev->open = mv64340_eth_open;
-	dev->stop = mv64340_eth_stop;
-	dev->hard_start_xmit = mv64340_eth_start_xmit;
-	dev->get_stats = mv64340_eth_get_stats;
-	dev->set_mac_address = mv64340_eth_set_mac_address;
-	dev->set_multicast_list = mv64340_eth_set_rx_mode;
+	mp->port_num = port_num;
+
+	dev->open = mv643xx_eth_open;
+	dev->stop = mv643xx_eth_stop;
+	dev->hard_start_xmit = mv643xx_eth_start_xmit;
+	dev->get_stats = mv643xx_eth_get_stats;
+	dev->set_mac_address = mv643xx_eth_set_mac_address;
+	dev->set_multicast_list = mv643xx_eth_set_rx_mode;
 
 	/* No need to Tx Timeout */
-	dev->tx_timeout = mv64340_eth_tx_timeout;
-#ifdef MV64340_NAPI
-        dev->poll = mv64340_poll;
-        dev->weight = 64;
+	dev->tx_timeout = mv643xx_eth_tx_timeout;
+#ifdef MV643XX_NAPI
+	dev->poll = mv643xx_poll;
+	dev->weight = 64;
 #endif
 
 	dev->watchdog_timeo = 2 * HZ;
-	dev->tx_queue_len = MV64340_TX_QUEUE_SIZE;
+	dev->tx_queue_len = mp->tx_ring_size;
 	dev->base_addr = 0;
-	dev->change_mtu = mv64340_eth_change_mtu;
+	dev->change_mtu = mv643xx_eth_change_mtu;
+	SET_ETHTOOL_OPS(dev, &mv643xx_ethtool_ops);
 
-#ifdef MV64340_CHECKSUM_OFFLOAD_TX
+#ifdef MV643XX_CHECKSUM_OFFLOAD_TX
 #ifdef MAX_SKB_FRAGS
-#ifndef CONFIG_JAGUAR_DMALOW
-        /*
-         * Zero copy can only work if we use Discovery II memory. Else, we will
-         * have to map the buffers to ISA memory which is only 16 MB
-         */
-        dev->features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_HW_CSUM;
-#endif
+	/*
+	 * Zero copy can only work if we use Discovery II memory. Else, we will
+	 * have to map the buffers to ISA memory which is only 16 MB
+	 */
+	dev->features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_HW_CSUM;
 #endif
 #endif
 
-	mp->port_num = port_num;
-
 	/* Configure the timeout task */
-        INIT_WORK(&mp->tx_timeout_task,
-                  (void (*)(void *))mv64340_eth_tx_timeout_task, dev);
+	INIT_WORK(&mp->tx_timeout_task,
+			(void (*)(void *))mv643xx_eth_tx_timeout_task, dev);
 
 	spin_lock_init(&mp->lock);
 
-	/* set MAC addresses */
-	memcpy(dev->dev_addr, prom_mac_addr_base, 6);
-	dev->dev_addr[5] += port_num;
+	/* set default config values */
+	eth_port_uc_addr_get(dev, dev->dev_addr);
+	mp->port_config = MV643XX_ETH_PORT_CONFIG_DEFAULT_VALUE;
+	mp->port_config_extend = MV643XX_ETH_PORT_CONFIG_EXTEND_DEFAULT_VALUE;
+	mp->port_sdma_config = MV643XX_ETH_PORT_SDMA_CONFIG_DEFAULT_VALUE;
+	mp->port_serial_control = MV643XX_ETH_PORT_SERIAL_CONTROL_DEFAULT_VALUE;
+	mp->rx_ring_size = MV643XX_ETH_PORT_DEFAULT_RECEIVE_QUEUE_SIZE;
+	mp->tx_ring_size = MV643XX_ETH_PORT_DEFAULT_TRANSMIT_QUEUE_SIZE;
+
+	pd = pdev->dev.platform_data;
+	if (pd) {
+		if (pd->mac_addr != NULL)
+			memcpy(dev->dev_addr, pd->mac_addr, 6);
+
+		if (pd->phy_addr || pd->force_phy_addr)
+			ethernet_phy_set(port_num, pd->phy_addr);
+
+		if (pd->port_config || pd->force_port_config)
+			mp->port_config = pd->port_config;
+
+		if (pd->port_config_extend || pd->force_port_config_extend)
+			mp->port_config_extend = pd->port_config_extend;
+
+		if (pd->port_sdma_config || pd->force_port_sdma_config)
+			mp->port_sdma_config = pd->port_sdma_config;
+
+		if (pd->port_serial_control || pd->force_port_serial_control)
+			mp->port_serial_control = pd->port_serial_control;
+
+		if (pd->rx_queue_size)
+			mp->rx_ring_size = pd->rx_queue_size;
+
+		if (pd->tx_queue_size)
+			mp->tx_ring_size = pd->tx_queue_size;
+
+		if (pd->tx_sram_size) {
+			mp->tx_sram_size = pd->tx_sram_size;
+			mp->tx_sram_addr = pd->tx_sram_addr;
+		}
+
+		if (pd->rx_sram_size) {
+			mp->rx_sram_size = pd->rx_sram_size;
+			mp->rx_sram_addr = pd->rx_sram_addr;
+		}
+	}
+
+	err = ethernet_phy_detect(port_num);
+	if (err) {
+		pr_debug("MV643xx ethernet port %d: "
+					"No PHY detected at addr %d\n",
+					port_num, ethernet_phy_get(port_num));
+		return err;
+	}
 
 	err = register_netdev(dev);
 	if (err)
-		goto out_free_dev;
+		goto out;
 
-	printk(KERN_NOTICE "%s: port %d with MAC address %02x:%02x:%02x:%02x:%02x:%02x\n",
-		dev->name, port_num,
-		dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2],
-		dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]);
+	p = dev->dev_addr;
+	printk(KERN_NOTICE
+		"%s: port %d with MAC address %02x:%02x:%02x:%02x:%02x:%02x\n",
+		dev->name, port_num, p[0], p[1], p[2], p[3], p[4], p[5]);
 
 	if (dev->features & NETIF_F_SG)
-		printk("Scatter Gather Enabled  ");
+		printk(KERN_NOTICE "%s: Scatter Gather Enabled\n", dev->name);
 
 	if (dev->features & NETIF_F_IP_CSUM)
-		printk("TX TCP/IP Checksumming Supported  \n");
+		printk(KERN_NOTICE "%s: TX TCP/IP Checksumming Supported\n",
+								dev->name);
 
-	printk("RX TCP/UDP Checksum Offload ON, \n");
-	printk("TX and RX Interrupt Coalescing ON \n");
+#ifdef MV643XX_CHECKSUM_OFFLOAD_TX
+	printk(KERN_NOTICE "%s: RX TCP/UDP Checksum Offload ON \n", dev->name);
+#endif
 
-#ifdef MV64340_NAPI
-	printk("RX NAPI Enabled \n");
+#ifdef MV643XX_COAL
+	printk(KERN_NOTICE "%s: TX and RX Interrupt Coalescing ON \n",
+								dev->name);
 #endif
 
-	return dev;
+#ifdef MV643XX_NAPI
+	printk(KERN_NOTICE "%s: RX NAPI Enabled \n", dev->name);
+#endif
 
-out_free_dev:
+	return 0;
+
+out:
 	free_netdev(dev);
 
-	return NULL;
+	return err;
 }
 
-static void mv64340_eth_remove(struct net_device *dev)
+static int mv643xx_eth_remove(struct device *ddev)
 {
-	struct mv64340_private *mp = netdev_priv(dev);
+	struct net_device *dev = dev_get_drvdata(ddev);
 
 	unregister_netdev(dev);
 	flush_scheduled_work();
+
 	free_netdev(dev);
+	dev_set_drvdata(ddev, NULL);
+	return 0;
 }
 
-static struct net_device *mv64340_dev0;
-static struct net_device *mv64340_dev1;
-static struct net_device *mv64340_dev2;
+static int mv643xx_eth_shared_probe(struct device *ddev)
+{
+	struct platform_device *pdev = to_platform_device(ddev);
+	struct resource *res;
+
+	printk(KERN_NOTICE "MV-643xx 10/100/1000 Ethernet Driver\n");
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (res == NULL)
+		return -ENODEV;
+
+	mv643xx_eth_shared_base = ioremap(res->start,
+						MV643XX_ETH_SHARED_REGS_SIZE);
+	if (mv643xx_eth_shared_base == NULL)
+		return -ENOMEM;
+
+	return 0;
+
+}
+
+static int mv643xx_eth_shared_remove(struct device *ddev)
+{
+	iounmap(mv643xx_eth_shared_base);
+	mv643xx_eth_shared_base = NULL;
+
+	return 0;
+}
+
+static struct device_driver mv643xx_eth_driver = {
+	.name = MV643XX_ETH_NAME,
+	.bus = &platform_bus_type,
+	.probe = mv643xx_eth_probe,
+	.remove = mv643xx_eth_remove,
+};
+
+static struct device_driver mv643xx_eth_shared_driver = {
+	.name = MV643XX_ETH_SHARED_NAME,
+	.bus = &platform_bus_type,
+	.probe = mv643xx_eth_shared_probe,
+	.remove = mv643xx_eth_shared_remove,
+};
 
 /*
- * mv64340_init_module
+ * mv643xx_init_module
  *
  * Registers the network drivers into the Linux kernel
  *
- * Input : N/A
+ * Input :	N/A
  *
- * Output : N/A
+ * Output :	N/A
  */
-static int __init mv64340_init_module(void)
+static int __init mv643xx_init_module(void)
 {
-	printk(KERN_NOTICE "MV-643xx 10/100/1000 Ethernet Driver\n");
+	int rc;
 
-#ifdef CONFIG_MV643XX_ETH_0
-	mv64340_dev0 = mv64340_eth_init(0);
-	if (!mv64340_dev0) {
-		printk(KERN_ERR
-		       "Error registering MV-64360 ethernet port 0\n");
-	}
-#endif
-#ifdef CONFIG_MV643XX_ETH_1
-	mv64340_dev1 = mv64340_eth_init(1);
-	if (!mv64340_dev1) {
-		printk(KERN_ERR
-		       "Error registering MV-64360 ethernet port 1\n");
-	}
-#endif
-#ifdef CONFIG_MV643XX_ETH_2
-	mv64340_dev2 = mv64340_eth_init(2);
-	if (!mv64340_dev2) {
-		printk(KERN_ERR
-		       "Error registering MV-64360 ethernet port 2\n");
+	rc = driver_register(&mv643xx_eth_shared_driver);
+	if (!rc) {
+		rc = driver_register(&mv643xx_eth_driver);
+		if (rc)
+			driver_unregister(&mv643xx_eth_shared_driver);
 	}
-#endif
-	return 0;
+	return rc;
 }
 
 /*
- * mv64340_cleanup_module
+ * mv643xx_cleanup_module
  *
  * Registers the network drivers into the Linux kernel
  *
- * Input : N/A
+ * Input :	N/A
  *
- * Output : N/A
+ * Output :	N/A
  */
-static void __exit mv64340_cleanup_module(void)
+static void __exit mv643xx_cleanup_module(void)
 {
-	if (mv64340_dev2)
-		mv64340_eth_remove(mv64340_dev2);
-	if (mv64340_dev1)
-		mv64340_eth_remove(mv64340_dev1);
-	if (mv64340_dev0)
-		mv64340_eth_remove(mv64340_dev0);
+	driver_unregister(&mv643xx_eth_driver);
+	driver_unregister(&mv643xx_eth_shared_driver);
 }
 
-module_init(mv64340_init_module);
-module_exit(mv64340_cleanup_module);
+module_init(mv643xx_init_module);
+module_exit(mv643xx_cleanup_module);
 
 MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Rabeeh Khoury, Assaf Hoffman, Matthew Dharm and Manish Lachwani");
-MODULE_DESCRIPTION("Ethernet driver for Marvell MV64340");
+MODULE_AUTHOR(	"Rabeeh Khoury, Assaf Hoffman, Matthew Dharm, Manish Lachwani"
+		" and Dale Farnsworth");
+MODULE_DESCRIPTION("Ethernet driver for Marvell MV643XX");
 
 /*
- *  The second part is the low level driver of the gigE ethernet ports.
+ * The second part is the low level driver of the gigE ethernet ports.
  */
 
 /*
  * Marvell's Gigabit Ethernet controller low level driver
  *
  * DESCRIPTION:
- *       This file introduce low level API to Marvell's Gigabit Ethernet
+ *	This file introduce low level API to Marvell's Gigabit Ethernet
  *		controller. This Gigabit Ethernet Controller driver API controls
  *		1) Operations (i.e. port init, start, reset etc').
  *		2) Data flow (i.e. port send, receive etc').
  *		Each Gigabit Ethernet port is controlled via
- *              struct mv64340_private.
+ *		struct mv643xx_private.
  *		This struct includes user configuration information as well as
  *		driver internal data needed for its operations.
  *
- *		Supported Features:  
+ *		Supported Features:
  *		- This low level driver is OS independent. Allocating memory for
  *		  the descriptor rings and buffers are not within the scope of
  *		  this driver.
@@ -1511,12 +1645,12 @@
  *		- PHY access and control API.
  *		- Port control register configuration API.
  *		- Full control over Unicast and Multicast MAC configurations.
- *								   
+ *
  *		Operation flow:
  *
  *		Initialization phase
- *		This phase complete the initialization of the the mv64340_private
- *		struct. 
+ *		This phase complete the initialization of the the
+ *		mv643xx_private struct.
  *		User information regarding port configuration has to be set
  *		prior to calling the port initialization routine.
  *
@@ -1525,7 +1659,7 @@
  *		access to DRAM and internal SRAM memory spaces.
  *
  *		Driver ring initialization
- *		Allocating memory for the descriptor rings and buffers is not 
+ *		Allocating memory for the descriptor rings and buffers is not
  *		within the scope of this driver. Thus, the user is required to
  *		allocate memory for the descriptors ring and buffers. Those
  *		memory parameters are used by the Rx and Tx ring initialization
@@ -1533,49 +1667,50 @@
  *		of a ring.
  *		Note: Pay special attention to alignment issues when using
  *		cached descriptors/buffers. In this phase the driver store
- *		information in the mv64340_private struct regarding each queue
+ *		information in the mv643xx_private struct regarding each queue
  *		ring.
  *
- *		Driver start 
+ *		Driver start
  *		This phase prepares the Ethernet port for Rx and Tx activity.
- *		It uses the information stored in the mv64340_private struct to 
+ *		It uses the information stored in the mv643xx_private struct to
  *		initialize the various port registers.
  *
  *		Data flow:
  *		All packet references to/from the driver are done using
- *              struct pkt_info.
- *		This struct is a unified struct used with Rx and Tx operations. 
+ *		struct pkt_info.
+ *		This struct is a unified struct used with Rx and Tx operations.
  *		This way the user is not required to be familiar with neither
  *		Tx nor Rx descriptors structures.
  *		The driver's descriptors rings are management by indexes.
  *		Those indexes controls the ring resources and used to indicate
  *		a SW resource error:
- *		'current' 
- *		This index points to the current available resource for use. For 
- *		example in Rx process this index will point to the descriptor  
- *		that will be passed to the user upon calling the receive routine.
- *		In Tx process, this index will point to the descriptor
+ *		'current'
+ *		This index points to the current available resource for use. For
+ *		example in Rx process this index will point to the descriptor
+ *		that will be passed to the user upon calling the receive
+ *		routine.  In Tx process, this index will point to the descriptor
  *		that will be assigned with the user packet info and transmitted.
- *		'used'    
- *		This index points to the descriptor that need to restore its 
+ *		'used'
+ *		This index points to the descriptor that need to restore its
  *		resources. For example in Rx process, using the Rx buffer return
  *		API will attach the buffer returned in packet info to the
  *		descriptor pointed by 'used'. In Tx process, using the Tx
  *		descriptor return will merely return the user packet info with
- *		the command status of  the transmitted buffer pointed by the
+ *		the command status of the transmitted buffer pointed by the
  *		'used' index. Nevertheless, it is essential to use this routine
  *		to update the 'used' index.
  *		'first'
- *		This index supports Tx Scatter-Gather. It points to the first 
- *		descriptor of a packet assembled of multiple buffers. For example
- *		when in middle of Such packet we have a Tx resource error the 
- *		'curr' index get the value of 'first' to indicate that the ring 
- *		returned to its state before trying to transmit this packet.
+ *		This index supports Tx Scatter-Gather. It points to the first
+ *		descriptor of a packet assembled of multiple buffers. For
+ *		example when in middle of Such packet we have a Tx resource
+ *		error the 'curr' index get the value of 'first' to indicate
+ *		that the ring returned to its state before trying to transmit
+ *		this packet.
  *
  *		Receive operation:
  *		The eth_port_receive API set the packet information struct,
- *		passed by the caller, with received information from the 
- *		'current' SDMA descriptor. 
+ *		passed by the caller, with received information from the
+ *		'current' SDMA descriptor.
  *		It is the user responsibility to return this resource back
  *		to the Rx descriptor ring to enable the reuse of this source.
  *		Return Rx resource is done using the eth_rx_return_buff API.
@@ -1596,27 +1731,21 @@
  *
  *		EXTERNAL INTERFACE
  *
- *       Prior to calling the initialization routine eth_port_init() the user
- *	 must set the following fields under mv64340_private struct:
- *       port_num             User Ethernet port number.
- *       port_mac_addr[6]	    User defined port MAC address.
- *       port_config          User port configuration value.
- *       port_config_extend    User port config extend value.
- *       port_sdma_config      User port SDMA config value.
- *       port_serial_control   User port serial control value.
- *
- *       This driver introduce a set of default values:
- *       PORT_CONFIG_VALUE           Default port configuration value
- *       PORT_CONFIG_EXTEND_VALUE    Default port extend configuration value
- *       PORT_SDMA_CONFIG_VALUE      Default sdma control value
- *       PORT_SERIAL_CONTROL_VALUE   Default port serial control value
+ *	Prior to calling the initialization routine eth_port_init() the user
+ *	must set the following fields under mv643xx_private struct:
+ *	port_num		User Ethernet port number.
+ *	port_mac_addr[6]	User defined port MAC address.
+ *	port_config		User port configuration value.
+ *	port_config_extend	User port config extend value.
+ *	port_sdma_config	User port SDMA config value.
+ *	port_serial_control	User port serial control value.
  *
  *		This driver data flow is done using the struct pkt_info which
- *              is a unified struct for Rx and Tx operations:
+ *		is a unified struct for Rx and Tx operations:
  *
  *		byte_cnt	Tx/Rx descriptor buffer byte count.
  *		l4i_chk		CPU provided TCP Checksum. For Tx operation
- *                              only.
+ *				only.
  *		cmd_sts		Tx/Rx descriptor command status.
  *		buf_ptr		Tx/Rx descriptor buffer pointer.
  *		return_info	Tx/Rx user resource return information.
@@ -1625,70 +1754,44 @@
 /* defines */
 /* SDMA command macros */
 #define ETH_ENABLE_TX_QUEUE(eth_port) \
-	MV_WRITE(MV64340_ETH_TRANSMIT_QUEUE_COMMAND_REG(eth_port), 1)
-
-#define ETH_DISABLE_TX_QUEUE(eth_port) \
-	MV_WRITE(MV64340_ETH_TRANSMIT_QUEUE_COMMAND_REG(eth_port),	\
-	         (1 << 8))
-
-#define ETH_ENABLE_RX_QUEUE(rx_queue, eth_port) \
-	MV_WRITE(MV64340_ETH_RECEIVE_QUEUE_COMMAND_REG(eth_port),	\
-	         (1 << rx_queue))
-
-#define ETH_DISABLE_RX_QUEUE(rx_queue, eth_port) \
-	MV_WRITE(MV64340_ETH_RECEIVE_QUEUE_COMMAND_REG(eth_port),	\
-	         (1 << (8 + rx_queue)))
-
-#define LINK_UP_TIMEOUT		100000
-#define PHY_BUSY_TIMEOUT	10000000
+	mv_write(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(eth_port), 1)
 
 /* locals */
 
 /* PHY routines */
 static int ethernet_phy_get(unsigned int eth_port_num);
+static void ethernet_phy_set(unsigned int eth_port_num, int phy_addr);
 
 /* Ethernet Port routines */
 static int eth_port_uc_addr(unsigned int eth_port_num, unsigned char uc_nibble,
-	int option);
+								int option);
 
 /*
  * eth_port_init - Initialize the Ethernet port driver
  *
  * DESCRIPTION:
- *       This function prepares the ethernet port to start its activity:
- *       1) Completes the ethernet port driver struct initialization toward port
- *           start routine.
- *       2) Resets the device to a quiescent state in case of warm reboot.
- *       3) Enable SDMA access to all four DRAM banks as well as internal SRAM.
- *       4) Clean MAC tables. The reset status of those tables is unknown.
- *       5) Set PHY address. 
- *       Note: Call this routine prior to eth_port_start routine and after
- *       setting user values in the user fields of Ethernet port control
- *       struct.
+ *	This function prepares the ethernet port to start its activity:
+ *	1) Completes the ethernet port driver struct initialization toward port
+ *		start routine.
+ *	2) Resets the device to a quiescent state in case of warm reboot.
+ *	3) Enable SDMA access to all four DRAM banks as well as internal SRAM.
+ *	4) Clean MAC tables. The reset status of those tables is unknown.
+ *	5) Set PHY address.
+ *	Note: Call this routine prior to eth_port_start routine and after
+ *	setting user values in the user fields of Ethernet port control
+ *	struct.
  *
  * INPUT:
- *       struct mv64340_private *mp   Ethernet port control struct
+ *	struct mv643xx_private *mp	Ethernet port control struct
  *
  * OUTPUT:
- *       See description.
+ *	See description.
  *
  * RETURN:
- *       None.
+ *	None.
  */
-static void eth_port_init(struct mv64340_private * mp)
+static void eth_port_init(struct mv643xx_private *mp)
 {
-	mp->port_config = PORT_CONFIG_VALUE;
-	mp->port_config_extend = PORT_CONFIG_EXTEND_VALUE;
-#if defined(__BIG_ENDIAN)
-	mp->port_sdma_config = PORT_SDMA_CONFIG_VALUE;
-#elif defined(__LITTLE_ENDIAN)
-	mp->port_sdma_config = PORT_SDMA_CONFIG_VALUE |
-		ETH_BLM_RX_NO_SWAP | ETH_BLM_TX_NO_SWAP;
-#else
-#error One of __LITTLE_ENDIAN or __BIG_ENDIAN must be defined!
-#endif
-	mp->port_serial_control = PORT_SERIAL_CONTROL_VALUE;
-
 	mp->port_rx_queue_command = 0;
 	mp->port_tx_queue_command = 0;
 
@@ -1706,77 +1809,73 @@
  * eth_port_start - Start the Ethernet port activity.
  *
  * DESCRIPTION:
- *       This routine prepares the Ethernet port for Rx and Tx activity:
- *       1. Initialize Tx and Rx Current Descriptor Pointer for each queue that
- *          has been initialized a descriptor's ring (using
- *          ether_init_tx_desc_ring for Tx and ether_init_rx_desc_ring for Rx)
- *       2. Initialize and enable the Ethernet configuration port by writing to
- *          the port's configuration and command registers.
- *       3. Initialize and enable the SDMA by writing to the SDMA's 
- *          configuration and command registers.  After completing these steps,
- *          the ethernet port SDMA can starts to perform Rx and Tx activities.
+ *	This routine prepares the Ethernet port for Rx and Tx activity:
+ *	 1. Initialize Tx and Rx Current Descriptor Pointer for each queue that
+ *	    has been initialized a descriptor's ring (using
+ *	    ether_init_tx_desc_ring for Tx and ether_init_rx_desc_ring for Rx)
+ *	 2. Initialize and enable the Ethernet configuration port by writing to
+ *	    the port's configuration and command registers.
+ *	 3. Initialize and enable the SDMA by writing to the SDMA's
+ *	    configuration and command registers.  After completing these steps,
+ *	    the ethernet port SDMA can starts to perform Rx and Tx activities.
  *
- *       Note: Each Rx and Tx queue descriptor's list must be initialized prior
- *       to calling this function (use ether_init_tx_desc_ring for Tx queues
- *       and ether_init_rx_desc_ring for Rx queues).
+ *	Note: Each Rx and Tx queue descriptor's list must be initialized prior
+ *	to calling this function (use ether_init_tx_desc_ring for Tx queues
+ *	and ether_init_rx_desc_ring for Rx queues).
  *
  * INPUT:
- *       struct mv64340_private 	*mp   Ethernet port control struct
+ *	struct mv643xx_private *mp	Ethernet port control struct
  *
  * OUTPUT:
- *       Ethernet port is ready to receive and transmit.
+ *	Ethernet port is ready to receive and transmit.
  *
  * RETURN:
- *       false if the port PHY is not up.
- *       true otherwise.
+ *	None.
  */
-static int eth_port_start(struct mv64340_private *mp)
+static void eth_port_start(struct mv643xx_private *mp)
 {
-	unsigned int eth_port_num = mp->port_num;
+	unsigned int port_num = mp->port_num;
 	int tx_curr_desc, rx_curr_desc;
-	unsigned int phy_reg_data;
 
 	/* Assignment of Tx CTRP of given queue */
 	tx_curr_desc = mp->tx_curr_desc_q;
-	MV_WRITE(MV64340_ETH_TX_CURRENT_QUEUE_DESC_PTR_0(eth_port_num),
-	         (struct eth_tx_desc *) mp->tx_desc_dma + tx_curr_desc);
+	mv_write(MV643XX_ETH_TX_CURRENT_QUEUE_DESC_PTR_0(port_num),
+		(u32)((struct eth_tx_desc *)mp->tx_desc_dma + tx_curr_desc));
 
 	/* Assignment of Rx CRDP of given queue */
 	rx_curr_desc = mp->rx_curr_desc_q;
-	MV_WRITE(MV64340_ETH_RX_CURRENT_QUEUE_DESC_PTR_0(eth_port_num),
-		 (struct eth_rx_desc *) mp->rx_desc_dma + rx_curr_desc);
+	mv_write(MV643XX_ETH_RX_CURRENT_QUEUE_DESC_PTR_0(port_num),
+		(u32)((struct eth_rx_desc *)mp->rx_desc_dma + rx_curr_desc));
 
 	/* Add the assigned Ethernet address to the port's address table */
-	eth_port_uc_addr_set(mp->port_num, mp->port_mac_addr);
+	eth_port_uc_addr_set(port_num, mp->port_mac_addr);
 
 	/* Assign port configuration and command. */
-	MV_WRITE(MV64340_ETH_PORT_CONFIG_REG(eth_port_num),
-		 mp->port_config);
+	mv_write(MV643XX_ETH_PORT_CONFIG_REG(port_num), mp->port_config);
+
+	mv_write(MV643XX_ETH_PORT_CONFIG_EXTEND_REG(port_num),
+						mp->port_config_extend);
 
-	MV_WRITE(MV64340_ETH_PORT_CONFIG_EXTEND_REG(eth_port_num),
-		 mp->port_config_extend);
 
-	MV_WRITE(MV64340_ETH_PORT_SERIAL_CONTROL_REG(eth_port_num),
-		 mp->port_serial_control);
+	/* Increase the Rx side buffer size if supporting GigE */
+	if (mp->port_serial_control & MV643XX_ETH_SET_GMII_SPEED_TO_1000)
+		mv_write(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(port_num),
+			(mp->port_serial_control & 0xfff1ffff) | (0x5 << 17));
+	else
+		mv_write(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(port_num),
+						mp->port_serial_control);
 
-	MV_SET_REG_BITS(MV64340_ETH_PORT_SERIAL_CONTROL_REG(eth_port_num),
-			ETH_SERIAL_PORT_ENABLE);
+	mv_write(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(port_num),
+		mv_read(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(port_num)) |
+						MV643XX_ETH_SERIAL_PORT_ENABLE);
 
 	/* Assign port SDMA configuration */
-	MV_WRITE(MV64340_ETH_SDMA_CONFIG_REG(eth_port_num),
-		 mp->port_sdma_config);
+	mv_write(MV643XX_ETH_SDMA_CONFIG_REG(port_num),
+							mp->port_sdma_config);
 
 	/* Enable port Rx. */
-	MV_WRITE(MV64340_ETH_RECEIVE_QUEUE_COMMAND_REG(eth_port_num),
-		 mp->port_rx_queue_command);
-
-	/* Check if link is up */
-	eth_port_read_smi_reg(eth_port_num, 1, &phy_reg_data);
-
-	if (!(phy_reg_data & 0x20))
-		return 0;
-
-	return 1;
+	mv_write(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(port_num),
+						mp->port_rx_queue_command);
 }
 
 /*
@@ -1786,29 +1885,29 @@
  *		This function Set the port Ethernet MAC address.
  *
  * INPUT:
- *	unsigned int eth_port_num     Port number.
- *	char *        p_addr		Address to be set 
+ *	unsigned int	eth_port_num	Port number.
+ *	char *		p_addr		Address to be set
  *
  * OUTPUT:
- *	Set MAC address low and high registers. also calls eth_port_uc_addr() 
- *       To set the unicast table with the proper information.
+ *	Set MAC address low and high registers. also calls eth_port_uc_addr()
+ *	To set the unicast table with the proper information.
  *
  * RETURN:
  *	N/A.
  *
  */
 static void eth_port_uc_addr_set(unsigned int eth_port_num,
-				 unsigned char *p_addr)
+							unsigned char *p_addr)
 {
 	unsigned int mac_h;
 	unsigned int mac_l;
 
 	mac_l = (p_addr[4] << 8) | (p_addr[5]);
-	mac_h = (p_addr[0] << 24) | (p_addr[1] << 16) |
-	    (p_addr[2] << 8) | (p_addr[3] << 0);
+	mac_h = (p_addr[0] << 24) | (p_addr[1] << 16) | (p_addr[2] << 8) |
+							(p_addr[3] << 0);
 
-	MV_WRITE(MV64340_ETH_MAC_ADDR_LOW(eth_port_num), mac_l);
-	MV_WRITE(MV64340_ETH_MAC_ADDR_HIGH(eth_port_num), mac_h);
+	mv_write(MV643XX_ETH_MAC_ADDR_LOW(eth_port_num), mac_l);
+	mv_write(MV643XX_ETH_MAC_ADDR_HIGH(eth_port_num), mac_h);
 
 	/* Accept frames of this address */
 	eth_port_uc_addr(eth_port_num, p_addr[5], ACCEPT_MAC_ADDR);
@@ -1817,29 +1916,64 @@
 }
 
 /*
+ * eth_port_uc_addr_get - This function retrieves the port Unicast address
+ * (MAC address) from the ethernet hw registers.
+ *
+ * DESCRIPTION:
+ *		This function retrieves the port Ethernet MAC address.
+ *
+ * INPUT:
+ *	unsigned int	eth_port_num	Port number.
+ *	char		*MacAddr	pointer where the MAC address is stored
+ *
+ * OUTPUT:
+ *	Copy the MAC address to the location pointed to by MacAddr
+ *
+ * RETURN:
+ *	N/A.
+ *
+ */
+static void eth_port_uc_addr_get(struct net_device *dev, unsigned char *p_addr)
+{
+	struct mv643xx_private *mp = netdev_priv(dev);
+	unsigned int mac_h;
+	unsigned int mac_l;
+
+	mac_h = mv_read(MV643XX_ETH_MAC_ADDR_HIGH(mp->port_num));
+	mac_l = mv_read(MV643XX_ETH_MAC_ADDR_LOW(mp->port_num));
+
+	p_addr[0] = (mac_h >> 24) & 0xff;
+	p_addr[1] = (mac_h >> 16) & 0xff;
+	p_addr[2] = (mac_h >> 8) & 0xff;
+	p_addr[3] = mac_h & 0xff;
+	p_addr[4] = (mac_l >> 8) & 0xff;
+	p_addr[5] = mac_l & 0xff;
+}
+
+/*
  * eth_port_uc_addr - This function Set the port unicast address table
  *
  * DESCRIPTION:
- *	This function locates the proper entry in the Unicast table for the 
- *	specified MAC nibble and sets its properties according to function 
+ *	This function locates the proper entry in the Unicast table for the
+ *	specified MAC nibble and sets its properties according to function
  *	parameters.
  *
  * INPUT:
- *	unsigned int 	eth_port_num      Port number.
- *	unsigned char uc_nibble		Unicast MAC Address last nibble. 
- *	int 			option      0 = Add, 1 = remove address.
+ *	unsigned int	eth_port_num	Port number.
+ *	unsigned char	uc_nibble	Unicast MAC Address last nibble.
+ *	int 		option		0 = Add, 1 = remove address.
  *
  * OUTPUT:
  *	This function add/removes MAC addresses from the port unicast address
- *	table. 
+ *	table.
  *
  * RETURN:
  *	true is output succeeded.
  *	false if option parameter is invalid.
  *
  */
-static int eth_port_uc_addr(unsigned int eth_port_num,
-	unsigned char uc_nibble, int option)
+static int eth_port_uc_addr(unsigned int eth_port_num, unsigned char uc_nibble,
+								int option)
 {
 	unsigned int unicast_reg;
 	unsigned int tbl_offset;
@@ -1852,29 +1986,26 @@
 
 	switch (option) {
 	case REJECT_MAC_ADDR:
-		/* Clear accepts frame bit at specified unicast DA table entry */
-		unicast_reg = MV_READ((MV64340_ETH_DA_FILTER_UNICAST_TABLE_BASE
-				  (eth_port_num) + tbl_offset));
+		/* Clear accepts frame bit at given unicast DA table entry */
+		unicast_reg = mv_read((MV643XX_ETH_DA_FILTER_UNICAST_TABLE_BASE
+						(eth_port_num) + tbl_offset));
 
 		unicast_reg &= (0x0E << (8 * reg_offset));
 
-		MV_WRITE(
-			 (MV64340_ETH_DA_FILTER_UNICAST_TABLE_BASE
-			  (eth_port_num) + tbl_offset), unicast_reg);
+		mv_write((MV643XX_ETH_DA_FILTER_UNICAST_TABLE_BASE
+				(eth_port_num) + tbl_offset), unicast_reg);
 		break;
 
 	case ACCEPT_MAC_ADDR:
 		/* Set accepts frame bit at unicast DA filter table entry */
 		unicast_reg =
-		    MV_READ(
-				 (MV64340_ETH_DA_FILTER_UNICAST_TABLE_BASE
-				  (eth_port_num) + tbl_offset));
+			mv_read((MV643XX_ETH_DA_FILTER_UNICAST_TABLE_BASE
+						(eth_port_num) + tbl_offset));
 
 		unicast_reg |= (0x01 << (8 * reg_offset));
 
-		MV_WRITE(
-			 (MV64340_ETH_DA_FILTER_UNICAST_TABLE_BASE
-			  (eth_port_num) + tbl_offset), unicast_reg);
+		mv_write((MV643XX_ETH_DA_FILTER_UNICAST_TABLE_BASE
+				(eth_port_num) + tbl_offset), unicast_reg);
 
 		break;
 
@@ -1889,17 +2020,17 @@
  * eth_port_init_mac_tables - Clear all entrance in the UC, SMC and OMC tables
  *
  * DESCRIPTION:
- *       Go through all the DA filter tables (Unicast, Special Multicast &
- *       Other Multicast) and set each entry to 0.
+ *	Go through all the DA filter tables (Unicast, Special Multicast &
+ *	Other Multicast) and set each entry to 0.
  *
  * INPUT:
- *	unsigned int    eth_port_num   Ethernet Port number.
+ *	unsigned int	eth_port_num	Ethernet Port number.
  *
  * OUTPUT:
- *       Multicast and Unicast packets are rejected.
+ *	Multicast and Unicast packets are rejected.
  *
  * RETURN:
- *       None.
+ *	None.
  */
 static void eth_port_init_mac_tables(unsigned int eth_port_num)
 {
@@ -1907,18 +2038,16 @@
 
 	/* Clear DA filter unicast table (Ex_dFUT) */
 	for (table_index = 0; table_index <= 0xC; table_index += 4)
-		MV_WRITE(
-			 (MV64340_ETH_DA_FILTER_UNICAST_TABLE_BASE
-			  (eth_port_num) + table_index), 0);
+		mv_write((MV643XX_ETH_DA_FILTER_UNICAST_TABLE_BASE
+					(eth_port_num) + table_index), 0);
 
 	for (table_index = 0; table_index <= 0xFC; table_index += 4) {
 		/* Clear DA filter special multicast table (Ex_dFSMT) */
-		MV_WRITE(
-			 (MV64340_ETH_DA_FILTER_SPECIAL_MULTICAST_TABLE_BASE
-			  (eth_port_num) + table_index), 0);
+		mv_write((MV643XX_ETH_DA_FILTER_SPECIAL_MULTICAST_TABLE_BASE
+					(eth_port_num) + table_index), 0);
 		/* Clear DA filter other multicast table (Ex_dFOMT) */
-		MV_WRITE((MV64340_ETH_DA_FILTER_OTHER_MULTICAST_TABLE_BASE
-			  (eth_port_num) + table_index), 0);
+		mv_write((MV643XX_ETH_DA_FILTER_OTHER_MULTICAST_TABLE_BASE
+					(eth_port_num) + table_index), 0);
 	}
 }
 
@@ -1926,17 +2055,17 @@
  * eth_clear_mib_counters - Clear all MIB counters
  *
  * DESCRIPTION:
- *       This function clears all MIB counters of a specific ethernet port.
- *       A read from the MIB counter will reset the counter.
+ *	This function clears all MIB counters of a specific ethernet port.
+ *	A read from the MIB counter will reset the counter.
  *
  * INPUT:
- *	unsigned int    eth_port_num   Ethernet Port number.
+ *	unsigned int	eth_port_num	Ethernet Port number.
  *
  * OUTPUT:
- *       After reading all MIB counters, the counters resets.
+ *	After reading all MIB counters, the counters resets.
  *
  * RETURN:
- *       MIB counter value.
+ *	MIB counter value.
  *
  */
 static void eth_clear_mib_counters(unsigned int eth_port_num)
@@ -1944,72 +2073,155 @@
 	int i;
 
 	/* Perform dummy reads from MIB counters */
-	for (i = ETH_MIB_GOOD_OCTETS_RECEIVED_LOW; i < ETH_MIB_LATE_COLLISION; i += 4)
-		MV_READ(MV64340_ETH_MIB_COUNTERS_BASE(eth_port_num) + i);
+	for (i = ETH_MIB_GOOD_OCTETS_RECEIVED_LOW; i < ETH_MIB_LATE_COLLISION;
+									i += 4)
+		mv_read(MV643XX_ETH_MIB_COUNTERS_BASE(eth_port_num) + i);
+}
+
+static inline u32 read_mib(struct mv643xx_private *mp, int offset)
+{
+	return mv_read(MV643XX_ETH_MIB_COUNTERS_BASE(mp->port_num) + offset);
+}
+
+static void eth_update_mib_counters(struct mv643xx_private *mp)
+{
+	struct mv643xx_mib_counters *p = &mp->mib_counters;
+	int offset;
+
+	p->good_octets_received +=
+		read_mib(mp, ETH_MIB_GOOD_OCTETS_RECEIVED_LOW);
+	p->good_octets_received +=
+		(u64)read_mib(mp, ETH_MIB_GOOD_OCTETS_RECEIVED_HIGH) << 32;
+
+	for (offset = ETH_MIB_BAD_OCTETS_RECEIVED;
+			offset <= ETH_MIB_FRAMES_1024_TO_MAX_OCTETS;
+			offset += 4)
+		*(u32 *)((char *)p + offset) = read_mib(mp, offset);
+
+	p->good_octets_sent += read_mib(mp, ETH_MIB_GOOD_OCTETS_SENT_LOW);
+	p->good_octets_sent +=
+		(u64)read_mib(mp, ETH_MIB_GOOD_OCTETS_SENT_HIGH) << 32;
+
+	for (offset = ETH_MIB_GOOD_FRAMES_SENT;
+			offset <= ETH_MIB_LATE_COLLISION;
+			offset += 4)
+		*(u32 *)((char *)p + offset) = read_mib(mp, offset);
 }
 
+/*
+ * ethernet_phy_detect - Detect whether a phy is present
+ *
+ * DESCRIPTION:
+ *	This function tests whether there is a PHY present on
+ *	the specified port.
+ *
+ * INPUT:
+ *	unsigned int	eth_port_num	Ethernet Port number.
+ *
+ * OUTPUT:
+ *	None
+ *
+ * RETURN:
+ *	0 on success
+ *	-ENODEV on failure
+ *
+ */
+static int ethernet_phy_detect(unsigned int port_num)
+{
+	unsigned int phy_reg_data0;
+	int auto_neg;
+
+	eth_port_read_smi_reg(port_num, 0, &phy_reg_data0);
+	auto_neg = phy_reg_data0 & 0x1000;
+	phy_reg_data0 ^= 0x1000;	/* invert auto_neg */
+	eth_port_write_smi_reg(port_num, 0, phy_reg_data0);
+
+	eth_port_read_smi_reg(port_num, 0, &phy_reg_data0);
+	if ((phy_reg_data0 & 0x1000) == auto_neg)
+		return -ENODEV;				/* change didn't take */
+
+	phy_reg_data0 ^= 0x1000;
+	eth_port_write_smi_reg(port_num, 0, phy_reg_data0);
+	return 0;
+}
 
 /*
  * ethernet_phy_get - Get the ethernet port PHY address.
  *
  * DESCRIPTION:
- *       This routine returns the given ethernet port PHY address.
+ *	This routine returns the given ethernet port PHY address.
  *
  * INPUT:
- *		unsigned int   eth_port_num   Ethernet Port number.
+ *	unsigned int	eth_port_num	Ethernet Port number.
  *
  * OUTPUT:
- *       None.
+ *	None.
  *
  * RETURN:
- *       PHY address.
+ *	PHY address.
  *
  */
 static int ethernet_phy_get(unsigned int eth_port_num)
 {
 	unsigned int reg_data;
 
-	reg_data = MV_READ(MV64340_ETH_PHY_ADDR_REG);
+	reg_data = mv_read(MV643XX_ETH_PHY_ADDR_REG);
 
 	return ((reg_data >> (5 * eth_port_num)) & 0x1f);
 }
 
 /*
+ * ethernet_phy_set - Set the ethernet port PHY address.
+ *
+ * DESCRIPTION:
+ *	This routine sets the given ethernet port PHY address.
+ *
+ * INPUT:
+ *	unsigned int	eth_port_num	Ethernet Port number.
+ *	int		phy_addr	PHY address.
+ *
+ * OUTPUT:
+ *	None.
+ *
+ * RETURN:
+ *	None.
+ *
+ */
+static void ethernet_phy_set(unsigned int eth_port_num, int phy_addr)
+{
+	u32 reg_data;
+	int addr_shift = 5 * eth_port_num;
+
+	reg_data = mv_read(MV643XX_ETH_PHY_ADDR_REG);
+	reg_data &= ~(0x1f << addr_shift);
+	reg_data |= (phy_addr & 0x1f) << addr_shift;
+	mv_write(MV643XX_ETH_PHY_ADDR_REG, reg_data);
+}
+
+/*
  * ethernet_phy_reset - Reset Ethernet port PHY.
  *
  * DESCRIPTION:
- *       This routine utilize the SMI interface to reset the ethernet port PHY.
- *       The routine waits until the link is up again or link up is timeout.
+ *	This routine utilizes the SMI interface to reset the ethernet port PHY.
  *
  * INPUT:
- *	unsigned int   eth_port_num   Ethernet Port number.
+ *	unsigned int	eth_port_num	Ethernet Port number.
  *
  * OUTPUT:
- *       The ethernet port PHY renew its link.
+ *	The PHY is reset.
  *
  * RETURN:
- *       None.
+ *	None.
  *
  */
-static int ethernet_phy_reset(unsigned int eth_port_num)
+static void ethernet_phy_reset(unsigned int eth_port_num)
 {
-	unsigned int time_out = 50;
 	unsigned int phy_reg_data;
 
 	/* Reset the PHY */
 	eth_port_read_smi_reg(eth_port_num, 0, &phy_reg_data);
 	phy_reg_data |= 0x8000;	/* Set bit 15 to reset the PHY */
 	eth_port_write_smi_reg(eth_port_num, 0, phy_reg_data);
-
-	/* Poll on the PHY LINK */
-	do {
-		eth_port_read_smi_reg(eth_port_num, 1, &phy_reg_data);
-
-		if (time_out-- == 0)
-			return 0;
-	} while (!(phy_reg_data & 0x20));
-
-	return 1;
 }
 
 /*
@@ -2017,381 +2229,358 @@
  *
  * DESCRIPTION:
  * 	This routine resets the chip by aborting any SDMA engine activity and
- *      clearing the MIB counters. The Receiver and the Transmit unit are in 
- *      idle state after this command is performed and the port is disabled.
+ *	clearing the MIB counters. The Receiver and the Transmit unit are in
+ *	idle state after this command is performed and the port is disabled.
  *
  * INPUT:
- *	unsigned int   eth_port_num   Ethernet Port number.
+ *	unsigned int	eth_port_num	Ethernet Port number.
  *
  * OUTPUT:
- *       Channel activity is halted.
+ *	Channel activity is halted.
  *
  * RETURN:
- *       None.
+ *	None.
  *
  */
-static void eth_port_reset(unsigned int eth_port_num)
+static void eth_port_reset(unsigned int port_num)
 {
 	unsigned int reg_data;
 
 	/* Stop Tx port activity. Check port Tx activity. */
-	reg_data =
-	    MV_READ(MV64340_ETH_TRANSMIT_QUEUE_COMMAND_REG(eth_port_num));
+	reg_data = mv_read(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(port_num));
 
 	if (reg_data & 0xFF) {
 		/* Issue stop command for active channels only */
-		MV_WRITE(MV64340_ETH_TRANSMIT_QUEUE_COMMAND_REG
-			 (eth_port_num), (reg_data << 8));
+		mv_write(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(port_num),
+							(reg_data << 8));
 
 		/* Wait for all Tx activity to terminate. */
-		do {
-			/* Check port cause register that all Tx queues are stopped */
-			reg_data =
-			    MV_READ
-			    (MV64340_ETH_TRANSMIT_QUEUE_COMMAND_REG
-			     (eth_port_num));
-		}
-		while (reg_data & 0xFF);
+		/* Check port cause register that all Tx queues are stopped */
+		while (mv_read(MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(port_num))
+									& 0xFF)
+			udelay(10);
 	}
 
 	/* Stop Rx port activity. Check port Rx activity. */
-	reg_data =
-	    MV_READ(MV64340_ETH_RECEIVE_QUEUE_COMMAND_REG
-			 (eth_port_num));
+	reg_data = mv_read(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(port_num));
 
 	if (reg_data & 0xFF) {
 		/* Issue stop command for active channels only */
-		MV_WRITE(MV64340_ETH_RECEIVE_QUEUE_COMMAND_REG
-			 (eth_port_num), (reg_data << 8));
+		mv_write(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(port_num),
+							(reg_data << 8));
 
 		/* Wait for all Rx activity to terminate. */
-		do {
-			/* Check port cause register that all Rx queues are stopped */
-			reg_data =
-			    MV_READ
-			    (MV64340_ETH_RECEIVE_QUEUE_COMMAND_REG
-			     (eth_port_num));
-		}
-		while (reg_data & 0xFF);
+		/* Check port cause register that all Rx queues are stopped */
+		while (mv_read(MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(port_num))
+									& 0xFF)
+			udelay(10);
 	}
 
-
 	/* Clear all MIB counters */
-	eth_clear_mib_counters(eth_port_num);
+	eth_clear_mib_counters(port_num);
 
 	/* Reset the Enable bit in the Configuration Register */
-	reg_data =
-	    MV_READ(MV64340_ETH_PORT_SERIAL_CONTROL_REG (eth_port_num));
-	reg_data &= ~ETH_SERIAL_PORT_ENABLE;
-	MV_WRITE(MV64340_ETH_PORT_SERIAL_CONTROL_REG(eth_port_num), reg_data);
-
-	return;
+	reg_data = mv_read(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(port_num));
+	reg_data &= ~MV643XX_ETH_SERIAL_PORT_ENABLE;
+	mv_write(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(port_num), reg_data);
 }
 
 /*
  * ethernet_set_config_reg - Set specified bits in configuration register.
  *
  * DESCRIPTION:
- *       This function sets specified bits in the given ethernet 
- *       configuration register. 
+ *	This function sets specified bits in the given ethernet
+ *	configuration register.
  *
  * INPUT:
- *	unsigned int   eth_port_num   Ethernet Port number.
- *      unsigned int    value   32 bit value.
+ *	unsigned int	eth_port_num	Ethernet Port number.
+ *	unsigned int	value		32 bit value.
  *
  * OUTPUT:
- *      The set bits in the value parameter are set in the configuration 
- *      register.
+ *	The set bits in the value parameter are set in the configuration
+ *	register.
  *
  * RETURN:
- *      None.
+ *	None.
  *
  */
 static void ethernet_set_config_reg(unsigned int eth_port_num,
-				    unsigned int value)
+							unsigned int value)
 {
 	unsigned int eth_config_reg;
 
-	eth_config_reg =
-	    MV_READ(MV64340_ETH_PORT_CONFIG_REG(eth_port_num));
+	eth_config_reg = mv_read(MV643XX_ETH_PORT_CONFIG_REG(eth_port_num));
 	eth_config_reg |= value;
-	MV_WRITE(MV64340_ETH_PORT_CONFIG_REG(eth_port_num),
-		 eth_config_reg);
+	mv_write(MV643XX_ETH_PORT_CONFIG_REG(eth_port_num), eth_config_reg);
+}
+
+static int eth_port_autoneg_supported(unsigned int eth_port_num)
+{
+	unsigned int phy_reg_data0;
+
+	eth_port_read_smi_reg(eth_port_num, 0, &phy_reg_data0);
+
+	return phy_reg_data0 & 0x1000;
+}
+
+static int eth_port_link_is_up(unsigned int eth_port_num)
+{
+	unsigned int phy_reg_data1;
+
+	eth_port_read_smi_reg(eth_port_num, 1, &phy_reg_data1);
+
+	if (eth_port_autoneg_supported(eth_port_num)) {
+		if (phy_reg_data1 & 0x20)	/* auto-neg complete */
+			return 1;
+	} else if (phy_reg_data1 & 0x4)		/* link up */
+		return 1;
+
+	return 0;
 }
 
 /*
  * ethernet_get_config_reg - Get the port configuration register
  *
  * DESCRIPTION:
- *       This function returns the configuration register value of the given 
- *       ethernet port.
+ *	This function returns the configuration register value of the given
+ *	ethernet port.
  *
  * INPUT:
- *	unsigned int   eth_port_num   Ethernet Port number.
+ *	unsigned int	eth_port_num	Ethernet Port number.
  *
  * OUTPUT:
- *       None.
+ *	None.
  *
  * RETURN:
- *       Port configuration register value.
+ *	Port configuration register value.
  */
 static unsigned int ethernet_get_config_reg(unsigned int eth_port_num)
 {
 	unsigned int eth_config_reg;
 
-	eth_config_reg = MV_READ(MV64340_ETH_PORT_CONFIG_EXTEND_REG
-				      (eth_port_num));
+	eth_config_reg = mv_read(MV643XX_ETH_PORT_CONFIG_EXTEND_REG
+								(eth_port_num));
 	return eth_config_reg;
 }
 
-
 /*
  * eth_port_read_smi_reg - Read PHY registers
  *
  * DESCRIPTION:
- *       This routine utilize the SMI interface to interact with the PHY in 
- *       order to perform PHY register read.
+ *	This routine utilize the SMI interface to interact with the PHY in
+ *	order to perform PHY register read.
  *
  * INPUT:
- *	unsigned int   eth_port_num   Ethernet Port number.
- *       unsigned int   phy_reg   PHY register address offset.
- *       unsigned int   *value   Register value buffer.
+ *	unsigned int	port_num	Ethernet Port number.
+ *	unsigned int	phy_reg		PHY register address offset.
+ *	unsigned int	*value		Register value buffer.
  *
  * OUTPUT:
- *       Write the value of a specified PHY register into given buffer.
+ *	Write the value of a specified PHY register into given buffer.
  *
  * RETURN:
- *       false if the PHY is busy or read data is not in valid state.
- *       true otherwise.
+ *	false if the PHY is busy or read data is not in valid state.
+ *	true otherwise.
  *
  */
-static int eth_port_read_smi_reg(unsigned int eth_port_num,
-	unsigned int phy_reg, unsigned int *value)
+static void eth_port_read_smi_reg(unsigned int port_num,
+				unsigned int phy_reg, unsigned int *value)
 {
-	int phy_addr = ethernet_phy_get(eth_port_num);
-	unsigned int time_out = PHY_BUSY_TIMEOUT;
-	unsigned int reg_value;
-
-	/* first check that it is not busy */
-	do {
-		reg_value = MV_READ(MV64340_ETH_SMI_REG);
-		if (time_out-- == 0)
-			return 0;
-	} while (reg_value & ETH_SMI_BUSY);
-
-	/* not busy */
-
-	MV_WRITE(MV64340_ETH_SMI_REG,
-		 (phy_addr << 16) | (phy_reg << 21) | ETH_SMI_OPCODE_READ);
-
-	time_out = PHY_BUSY_TIMEOUT;	/* initialize the time out var again */
+	int phy_addr = ethernet_phy_get(port_num);
+	unsigned long flags;
+	int i;
 
-	do {
-		reg_value = MV_READ(MV64340_ETH_SMI_REG);
-		if (time_out-- == 0)
-			return 0;
-	} while (reg_value & ETH_SMI_READ_VALID);
+	/* the SMI register is a shared resource */
+	spin_lock_irqsave(&mv643xx_eth_phy_lock, flags);
 
-	/* Wait for the data to update in the SMI register */
-	for (time_out = 0; time_out < PHY_BUSY_TIMEOUT; time_out++);
+	/* wait for the SMI register to become available */
+	for (i = 0; mv_read(MV643XX_ETH_SMI_REG) & ETH_SMI_BUSY; i++) {
+		if (i == PHY_WAIT_ITERATIONS) {
+			printk("mv643xx PHY busy timeout, port %d\n", port_num);
+			goto out;
+		}
+		udelay(PHY_WAIT_MICRO_SECONDS);
+	}
 
-	reg_value = MV_READ(MV64340_ETH_SMI_REG);
+	mv_write(MV643XX_ETH_SMI_REG,
+		(phy_addr << 16) | (phy_reg << 21) | ETH_SMI_OPCODE_READ);
 
-	*value = reg_value & 0xffff;
+	/* now wait for the data to be valid */
+	for (i = 0; !(mv_read(MV643XX_ETH_SMI_REG) & ETH_SMI_READ_VALID); i++) {
+		if (i == PHY_WAIT_ITERATIONS) {
+			printk("mv643xx PHY read timeout, port %d\n", port_num);
+			goto out;
+		}
+		udelay(PHY_WAIT_MICRO_SECONDS);
+	}
 
-	return 1;
+	*value = mv_read(MV643XX_ETH_SMI_REG) & 0xffff;
+out:
+	spin_unlock_irqrestore(&mv643xx_eth_phy_lock, flags);
 }
 
 /*
  * eth_port_write_smi_reg - Write to PHY registers
  *
  * DESCRIPTION:
- *       This routine utilize the SMI interface to interact with the PHY in 
- *       order to perform writes to PHY registers.
+ *	This routine utilize the SMI interface to interact with the PHY in
+ *	order to perform writes to PHY registers.
  *
  * INPUT:
- *	unsigned int   eth_port_num   Ethernet Port number.
- *      unsigned int   phy_reg   PHY register address offset.
- *      unsigned int    value   Register value.
+ *	unsigned int	eth_port_num	Ethernet Port number.
+ *	unsigned int	phy_reg		PHY register address offset.
+ *	unsigned int	value		Register value.
  *
  * OUTPUT:
- *      Write the given value to the specified PHY register.
+ *	Write the given value to the specified PHY register.
  *
  * RETURN:
- *      false if the PHY is busy.
- *      true otherwise.
+ *	false if the PHY is busy.
+ *	true otherwise.
  *
  */
-static int eth_port_write_smi_reg(unsigned int eth_port_num,
-	unsigned int phy_reg, unsigned int value)
+static void eth_port_write_smi_reg(unsigned int eth_port_num,
+				   unsigned int phy_reg, unsigned int value)
 {
-	unsigned int time_out = PHY_BUSY_TIMEOUT;
-	unsigned int reg_value;
 	int phy_addr;
+	int i;
+	unsigned long flags;
 
 	phy_addr = ethernet_phy_get(eth_port_num);
 
-	/* first check that it is not busy */
-	do {
-		reg_value = MV_READ(MV64340_ETH_SMI_REG);
-		if (time_out-- == 0)
-			return 0;
-	} while (reg_value & ETH_SMI_BUSY);
-
-	/* not busy */
-	MV_WRITE(MV64340_ETH_SMI_REG, (phy_addr << 16) | (phy_reg << 21) |
-		 ETH_SMI_OPCODE_WRITE | (value & 0xffff));
+	/* the SMI register is a shared resource */
+	spin_lock_irqsave(&mv643xx_eth_phy_lock, flags);
 
-	return 1;
+	/* wait for the SMI register to become available */
+	for (i = 0; mv_read(MV643XX_ETH_SMI_REG) & ETH_SMI_BUSY; i++) {
+		if (i == PHY_WAIT_ITERATIONS) {
+			printk("mv643xx PHY busy timeout, port %d\n",
+								eth_port_num);
+			goto out;
+		}
+		udelay(PHY_WAIT_MICRO_SECONDS);
+	}
+
+	mv_write(MV643XX_ETH_SMI_REG, (phy_addr << 16) | (phy_reg << 21) |
+				ETH_SMI_OPCODE_WRITE | (value & 0xffff));
+out:
+	spin_unlock_irqrestore(&mv643xx_eth_phy_lock, flags);
 }
 
 /*
  * eth_port_send - Send an Ethernet packet
  *
  * DESCRIPTION:
- *	This routine send a given packet described by p_pktinfo parameter. It 
- *      supports transmitting of a packet spaned over multiple buffers. The 
- *      routine updates 'curr' and 'first' indexes according to the packet 
- *      segment passed to the routine. In case the packet segment is first, 
- *      the 'first' index is update. In any case, the 'curr' index is updated. 
- *      If the routine get into Tx resource error it assigns 'curr' index as 
- *      'first'. This way the function can abort Tx process of multiple 
- *      descriptors per packet.
+ *	This routine send a given packet described by p_pktinfo parameter. It
+ *	supports transmitting of a packet spaned over multiple buffers. The
+ *	routine updates 'curr' and 'first' indexes according to the packet
+ *	segment passed to the routine. In case the packet segment is first,
+ *	the 'first' index is update. In any case, the 'curr' index is updated.
+ *	If the routine get into Tx resource error it assigns 'curr' index as
+ *	'first'. This way the function can abort Tx process of multiple
+ *	descriptors per packet.
  *
  * INPUT:
- *	struct mv64340_private   *mp   Ethernet Port Control srtuct. 
- *	struct pkt_info        *p_pkt_info       User packet buffer.
+ *	struct mv643xx_private	*mp		Ethernet Port Control srtuct.
+ *	struct pkt_info		*p_pkt_info	User packet buffer.
  *
  * OUTPUT:
- *	Tx ring 'curr' and 'first' indexes are updated. 
+ *	Tx ring 'curr' and 'first' indexes are updated.
  *
  * RETURN:
- *      ETH_QUEUE_FULL in case of Tx resource error.
+ *	ETH_QUEUE_FULL in case of Tx resource error.
  *	ETH_ERROR in case the routine can not access Tx desc ring.
  *	ETH_QUEUE_LAST_RESOURCE if the routine uses the last Tx resource.
- *      ETH_OK otherwise.
+ *	ETH_OK otherwise.
  *
  */
-#ifdef  MV64340_CHECKSUM_OFFLOAD_TX
+#ifdef MV643XX_CHECKSUM_OFFLOAD_TX
 /*
  * Modified to include the first descriptor pointer in case of SG
  */
-static ETH_FUNC_RET_STATUS eth_port_send(struct mv64340_private * mp,
-                                         struct pkt_info * p_pkt_info)
+static ETH_FUNC_RET_STATUS eth_port_send(struct mv643xx_private *mp,
+					 struct pkt_info *p_pkt_info)
 {
 	int tx_desc_curr, tx_desc_used, tx_first_desc, tx_next_desc;
-	volatile struct eth_tx_desc *current_descriptor;
-	volatile struct eth_tx_desc *first_descriptor;
-	u32 command_status, first_chip_ptr;
+	struct eth_tx_desc *current_descriptor;
+	struct eth_tx_desc *first_descriptor;
+	u32 command;
 
 	/* Do not process Tx ring in case of Tx ring resource error */
 	if (mp->tx_resource_err)
 		return ETH_QUEUE_FULL;
 
+	/*
+	 * The hardware requires that each buffer that is <= 8 bytes
+	 * in length must be aligned on an 8 byte boundary.
+	 */
+	if (p_pkt_info->byte_cnt <= 8 && p_pkt_info->buf_ptr & 0x7) {
+		printk(KERN_ERR
+			"mv643xx_eth port %d: packet size <= 8 problem\n",
+			mp->port_num);
+		return ETH_ERROR;
+	}
+
 	/* Get the Tx Desc ring indexes */
 	tx_desc_curr = mp->tx_curr_desc_q;
 	tx_desc_used = mp->tx_used_desc_q;
 
 	current_descriptor = &mp->p_tx_desc_area[tx_desc_curr];
-	if (current_descriptor == NULL)
-		return ETH_ERROR;
 
-	tx_next_desc = (tx_desc_curr + 1) % MV64340_TX_QUEUE_SIZE;
-	command_status = p_pkt_info->cmd_sts | ETH_ZERO_PADDING | ETH_GEN_CRC;
+	tx_next_desc = (tx_desc_curr + 1) % mp->tx_ring_size;
+
+	current_descriptor->buf_ptr = p_pkt_info->buf_ptr;
+	current_descriptor->byte_cnt = p_pkt_info->byte_cnt;
+	current_descriptor->l4i_chk = p_pkt_info->l4i_chk;
+	mp->tx_skb[tx_desc_curr] = p_pkt_info->return_info;
 
-	if (command_status & ETH_TX_FIRST_DESC) {
+	command = p_pkt_info->cmd_sts | ETH_ZERO_PADDING | ETH_GEN_CRC |
+							ETH_BUFFER_OWNED_BY_DMA;
+	if (command & ETH_TX_FIRST_DESC) {
 		tx_first_desc = tx_desc_curr;
 		mp->tx_first_desc_q = tx_first_desc;
+		first_descriptor = current_descriptor;
+		mp->tx_first_command = command;
+	} else {
+		tx_first_desc = mp->tx_first_desc_q;
+		first_descriptor = &mp->p_tx_desc_area[tx_first_desc];
+		BUG_ON(first_descriptor == NULL);
+		current_descriptor->cmd_sts = command;
+	}
 
-                /* fill first descriptor */
-                first_descriptor = &mp->p_tx_desc_area[tx_desc_curr];
-                first_descriptor->l4i_chk = p_pkt_info->l4i_chk;
-                first_descriptor->cmd_sts = command_status;
-                first_descriptor->byte_cnt = p_pkt_info->byte_cnt;
-                first_descriptor->buf_ptr = p_pkt_info->buf_ptr;
-                first_descriptor->next_desc_ptr = mp->tx_desc_dma +
-			tx_next_desc * sizeof(struct eth_tx_desc);
+	if (command & ETH_TX_LAST_DESC) {
 		wmb();
-        } else {
-                tx_first_desc = mp->tx_first_desc_q;
-                first_descriptor = &mp->p_tx_desc_area[tx_first_desc];
-                if (first_descriptor == NULL) {
-                        printk("First desc is NULL !!\n");
-                        return ETH_ERROR;
-                }
-                if (command_status & ETH_TX_LAST_DESC)
-                        current_descriptor->next_desc_ptr = 0x00000000;
-                else {
-                        command_status |= ETH_BUFFER_OWNED_BY_DMA;
-                        current_descriptor->next_desc_ptr = mp->tx_desc_dma +
-				tx_next_desc * sizeof(struct eth_tx_desc);
-                }
-        }
-
-        if (p_pkt_info->byte_cnt < 8) {
-                printk(" < 8 problem \n");
-                return ETH_ERROR;
-        }
-
-        current_descriptor->buf_ptr = p_pkt_info->buf_ptr;
-        current_descriptor->byte_cnt = p_pkt_info->byte_cnt;
-        current_descriptor->l4i_chk = p_pkt_info->l4i_chk;
-        current_descriptor->cmd_sts = command_status;
-
-        mp->tx_skb[tx_desc_curr] = (struct sk_buff*) p_pkt_info->return_info;
-
-        wmb();
-
-        /* Set last desc with DMA ownership and interrupt enable. */
-        if (command_status & ETH_TX_LAST_DESC) {
-                current_descriptor->cmd_sts = command_status |
-                                        ETH_TX_ENABLE_INTERRUPT |
-                                        ETH_BUFFER_OWNED_BY_DMA;
+		first_descriptor->cmd_sts = mp->tx_first_command;
 
-		if (!(command_status & ETH_TX_FIRST_DESC))
-			first_descriptor->cmd_sts |= ETH_BUFFER_OWNED_BY_DMA;
 		wmb();
-
-		first_chip_ptr = MV_READ(MV64340_ETH_CURRENT_SERVED_TX_DESC_PTR(mp->port_num));
-
-		/* Apply send command */
-		if (first_chip_ptr == 0x00000000)
-			MV_WRITE(MV64340_ETH_TX_CURRENT_QUEUE_DESC_PTR_0(mp->port_num), (struct eth_tx_desc *) mp->tx_desc_dma + tx_first_desc);
-
-                ETH_ENABLE_TX_QUEUE(mp->port_num);
+		ETH_ENABLE_TX_QUEUE(mp->port_num);
 
 		/*
 		 * Finish Tx packet. Update first desc in case of Tx resource
 		 * error */
-                tx_first_desc = tx_next_desc;
-                mp->tx_first_desc_q = tx_first_desc;
-	} else {
-		if (! (command_status & ETH_TX_FIRST_DESC) ) {
-			current_descriptor->cmd_sts = command_status;
-			wmb();
-		}
+		tx_first_desc = tx_next_desc;
+		mp->tx_first_desc_q = tx_first_desc;
 	}
 
-        /* Check for ring index overlap in the Tx desc ring */
-        if (tx_next_desc == tx_desc_used) {
-                mp->tx_resource_err = 1;
-                mp->tx_curr_desc_q = tx_first_desc;
+	/* Check for ring index overlap in the Tx desc ring */
+	if (tx_next_desc == tx_desc_used) {
+		mp->tx_resource_err = 1;
+		mp->tx_curr_desc_q = tx_first_desc;
 
-                return ETH_QUEUE_LAST_RESOURCE;
+		return ETH_QUEUE_LAST_RESOURCE;
 	}
 
-        mp->tx_curr_desc_q = tx_next_desc;
-        wmb();
+	mp->tx_curr_desc_q = tx_next_desc;
 
-        return ETH_OK;
+	return ETH_OK;
 }
 #else
-static ETH_FUNC_RET_STATUS eth_port_send(struct mv64340_private * mp,
-					 struct pkt_info * p_pkt_info)
+static ETH_FUNC_RET_STATUS eth_port_send(struct mv643xx_private *mp,
+					 struct pkt_info *p_pkt_info)
 {
 	int tx_desc_curr;
 	int tx_desc_used;
-	volatile struct eth_tx_desc* current_descriptor;
+	struct eth_tx_desc *current_descriptor;
 	unsigned int command_status;
 
 	/* Do not process Tx ring in case of Tx ring resource error */
@@ -2403,39 +2592,24 @@
 	tx_desc_used = mp->tx_used_desc_q;
 	current_descriptor = &mp->p_tx_desc_area[tx_desc_curr];
 
-	if (current_descriptor == NULL)
-		return ETH_ERROR;
-
 	command_status = p_pkt_info->cmd_sts | ETH_ZERO_PADDING | ETH_GEN_CRC;
-
-/* XXX Is this for real ?!?!? */
-	/* Buffers with a payload smaller than 8 bytes must be aligned to a
-	 * 64-bit boundary. We use the memory allocated for Tx descriptor.
-	 * This memory is located in TX_BUF_OFFSET_IN_DESC offset within the
-	 * Tx descriptor. */
-	if (p_pkt_info->byte_cnt <= 8) {
-		printk(KERN_ERR
-		       "You have failed in the < 8 bytes errata - fixme\n");
-		return ETH_ERROR;
-	}
 	current_descriptor->buf_ptr = p_pkt_info->buf_ptr;
 	current_descriptor->byte_cnt = p_pkt_info->byte_cnt;
-	mp->tx_skb[tx_desc_curr] = (struct sk_buff *) p_pkt_info->return_info;
-
-	mb();
+	mp->tx_skb[tx_desc_curr] = p_pkt_info->return_info;
 
 	/* Set last desc with DMA ownership and interrupt enable. */
+	wmb();
 	current_descriptor->cmd_sts = command_status |
 			ETH_BUFFER_OWNED_BY_DMA | ETH_TX_ENABLE_INTERRUPT;
 
-	/* Apply send command */
+	wmb();
 	ETH_ENABLE_TX_QUEUE(mp->port_num);
 
 	/* Finish Tx packet. Update first desc in case of Tx resource error */
-	tx_desc_curr = (tx_desc_curr + 1) % MV64340_TX_QUEUE_SIZE;
+	tx_desc_curr = (tx_desc_curr + 1) % mp->tx_ring_size;
 
 	/* Update the current descriptor */
- 	mp->tx_curr_desc_q = tx_desc_curr;
+	mp->tx_curr_desc_q = tx_desc_curr;
 
 	/* Check for ring index overlap in the Tx desc ring */
 	if (tx_desc_curr == tx_desc_used) {
@@ -2452,62 +2626,55 @@
  *
  * DESCRIPTION:
  *	This routine returns the transmitted packet information to the caller.
- *      It uses the 'first' index to support Tx desc return in case a transmit 
- *      of a packet spanned over multiple buffer still in process.
- *      In case the Tx queue was in "resource error" condition, where there are 
- *      no available Tx resources, the function resets the resource error flag.
+ *	It uses the 'first' index to support Tx desc return in case a transmit
+ *	of a packet spanned over multiple buffer still in process.
+ *	In case the Tx queue was in "resource error" condition, where there are
+ *	no available Tx resources, the function resets the resource error flag.
  *
  * INPUT:
- *	struct mv64340_private   *mp   Ethernet Port Control srtuct. 
- *	struct pkt_info        *p_pkt_info       User packet buffer.
+ *	struct mv643xx_private	*mp		Ethernet Port Control srtuct.
+ *	struct pkt_info		*p_pkt_info	User packet buffer.
  *
  * OUTPUT:
- *	Tx ring 'first' and 'used' indexes are updated. 
+ *	Tx ring 'first' and 'used' indexes are updated.
  *
  * RETURN:
  *	ETH_ERROR in case the routine can not access Tx desc ring.
- *      ETH_RETRY in case there is transmission in process.
+ *	ETH_RETRY in case there is transmission in process.
  *	ETH_END_OF_JOB if the routine has nothing to release.
- *      ETH_OK otherwise.
+ *	ETH_OK otherwise.
  *
  */
-static ETH_FUNC_RET_STATUS eth_tx_return_desc(struct mv64340_private * mp,
-					      struct pkt_info * p_pkt_info)
+static ETH_FUNC_RET_STATUS eth_tx_return_desc(struct mv643xx_private *mp,
+						struct pkt_info *p_pkt_info)
 {
-	int tx_desc_used, tx_desc_curr;
-#ifdef MV64340_CHECKSUM_OFFLOAD_TX
-        int tx_first_desc;
+	int tx_desc_used;
+#ifdef MV643XX_CHECKSUM_OFFLOAD_TX
+	int tx_busy_desc = mp->tx_first_desc_q;
+#else
+	int tx_busy_desc = mp->tx_curr_desc_q;
 #endif
-	volatile struct eth_tx_desc *p_tx_desc_used;
+	struct eth_tx_desc *p_tx_desc_used;
 	unsigned int command_status;
 
 	/* Get the Tx Desc ring indexes */
-	tx_desc_curr = mp->tx_curr_desc_q;
 	tx_desc_used = mp->tx_used_desc_q;
-#ifdef MV64340_CHECKSUM_OFFLOAD_TX
-        tx_first_desc = mp->tx_first_desc_q;
-#endif
+
 	p_tx_desc_used = &mp->p_tx_desc_area[tx_desc_used];
 
-	/* XXX Sanity check */
+	/* Sanity check */
 	if (p_tx_desc_used == NULL)
 		return ETH_ERROR;
 
+	/* Stop release. About to overlap the current available Tx descriptor */
+	if (tx_desc_used == tx_busy_desc && !mp->tx_resource_err)
+		return ETH_END_OF_JOB;
+
 	command_status = p_tx_desc_used->cmd_sts;
 
 	/* Still transmitting... */
-#ifndef MV64340_CHECKSUM_OFFLOAD_TX
 	if (command_status & (ETH_BUFFER_OWNED_BY_DMA))
 		return ETH_RETRY;
-#endif
-	/* Stop release. About to overlap the current available Tx descriptor */
-#ifdef MV64340_CHECKSUM_OFFLOAD_TX
-	if (tx_desc_used == tx_first_desc && !mp->tx_resource_err)
-		return ETH_END_OF_JOB;
-#else
-	if (tx_desc_used == tx_desc_curr && !mp->tx_resource_err)
-		return ETH_END_OF_JOB;
-#endif
 
 	/* Pass the packet information to the caller */
 	p_pkt_info->cmd_sts = command_status;
@@ -2515,7 +2682,7 @@
 	mp->tx_skb[tx_desc_used] = NULL;
 
 	/* Update the next descriptor to release. */
-	mp->tx_used_desc_q = (tx_desc_used + 1) % MV64340_TX_QUEUE_SIZE;
+	mp->tx_used_desc_q = (tx_desc_used + 1) % mp->tx_ring_size;
 
 	/* Any Tx return cancels the Tx resource error status */
 	mp->tx_resource_err = 0;
@@ -2527,30 +2694,30 @@
  * eth_port_receive - Get received information from Rx ring.
  *
  * DESCRIPTION:
- * 	This routine returns the received data to the caller. There is no 
- *	data copying during routine operation. All information is returned 
- *	using pointer to packet information struct passed from the caller. 
- *      If the routine exhausts	Rx ring resources then the resource error flag 
- *      is set.  
+ * 	This routine returns the received data to the caller. There is no
+ *	data copying during routine operation. All information is returned
+ *	using pointer to packet information struct passed from the caller.
+ *	If the routine exhausts Rx ring resources then the resource error flag
+ *	is set.
  *
  * INPUT:
- *	struct mv64340_private   *mp   Ethernet Port Control srtuct. 
- *	struct pkt_info        *p_pkt_info       User packet buffer.
+ *	struct mv643xx_private	*mp		Ethernet Port Control srtuct.
+ *	struct pkt_info		*p_pkt_info	User packet buffer.
  *
  * OUTPUT:
- *	Rx ring current and used indexes are updated. 
+ *	Rx ring current and used indexes are updated.
  *
  * RETURN:
  *	ETH_ERROR in case the routine can not access Rx desc ring.
  *	ETH_QUEUE_FULL if Rx ring resources are exhausted.
  *	ETH_END_OF_JOB if there is no received data.
- *      ETH_OK otherwise.
+ *	ETH_OK otherwise.
  */
-static ETH_FUNC_RET_STATUS eth_port_receive(struct mv64340_private * mp,
-					    struct pkt_info * p_pkt_info)
+static ETH_FUNC_RET_STATUS eth_port_receive(struct mv643xx_private *mp,
+						struct pkt_info *p_pkt_info)
 {
 	int rx_next_curr_desc, rx_curr_desc, rx_used_desc;
-	volatile struct eth_rx_desc * p_rx_desc;
+	volatile struct eth_rx_desc *p_rx_desc;
 	unsigned int command_status;
 
 	/* Do not process Rx ring in case of Rx ring resource error */
@@ -2565,6 +2732,7 @@
 
 	/* The following parameters are used to save readings from memory */
 	command_status = p_rx_desc->cmd_sts;
+	rmb();
 
 	/* Nothing to receive... */
 	if (command_status & (ETH_BUFFER_OWNED_BY_DMA))
@@ -2577,18 +2745,17 @@
 	p_pkt_info->l4i_chk = p_rx_desc->buf_size;
 
 	/* Clean the return info field to indicate that the packet has been */
-	/* moved to the upper layers                                        */
+	/* moved to the upper layers					    */
 	mp->rx_skb[rx_curr_desc] = NULL;
 
 	/* Update current index in data structure */
-	rx_next_curr_desc = (rx_curr_desc + 1) % MV64340_RX_QUEUE_SIZE;
+	rx_next_curr_desc = (rx_curr_desc + 1) % mp->rx_ring_size;
 	mp->rx_curr_desc_q = rx_next_curr_desc;
 
 	/* Rx descriptors exhausted. Set the Rx ring resource error flag */
 	if (rx_next_curr_desc == rx_used_desc)
 		mp->rx_resource_err = 1;
 
-	mb();
 	return ETH_OK;
 }
 
@@ -2596,27 +2763,27 @@
  * eth_rx_return_buff - Returns a Rx buffer back to the Rx ring.
  *
  * DESCRIPTION:
- *	This routine returns a Rx buffer back to the Rx ring. It retrieves the 
- *      next 'used' descriptor and attached the returned buffer to it.
- *      In case the Rx ring was in "resource error" condition, where there are 
- *      no available Rx resources, the function resets the resource error flag.
+ *	This routine returns a Rx buffer back to the Rx ring. It retrieves the
+ *	next 'used' descriptor and attached the returned buffer to it.
+ *	In case the Rx ring was in "resource error" condition, where there are
+ *	no available Rx resources, the function resets the resource error flag.
  *
  * INPUT:
- *	struct mv64340_private *mp   Ethernet Port Control srtuct. 
- *      struct pkt_info        *p_pkt_info   Information on the returned buffer.
+ *	struct mv643xx_private	*mp		Ethernet Port Control srtuct.
+ *	struct pkt_info		*p_pkt_info	Information on returned buffer.
  *
  * OUTPUT:
  *	New available Rx resource in Rx descriptor ring.
  *
  * RETURN:
  *	ETH_ERROR in case the routine can not access Rx desc ring.
- *      ETH_OK otherwise.
+ *	ETH_OK otherwise.
  */
-static ETH_FUNC_RET_STATUS eth_rx_return_buff(struct mv64340_private * mp,
-	struct pkt_info * p_pkt_info)
+static ETH_FUNC_RET_STATUS eth_rx_return_buff(struct mv643xx_private *mp,
+						struct pkt_info *p_pkt_info)
 {
 	int used_rx_desc;	/* Where to return Rx resource */
-	volatile struct eth_rx_desc* p_used_rx_desc;
+	volatile struct eth_rx_desc *p_used_rx_desc;
 
 	/* Get 'used' Rx descriptor */
 	used_rx_desc = mp->rx_used_desc_q;
@@ -2627,20 +2794,240 @@
 	mp->rx_skb[used_rx_desc] = p_pkt_info->return_info;
 
 	/* Flush the write pipe */
-	mb();
 
 	/* Return the descriptor to DMA ownership */
+	wmb();
 	p_used_rx_desc->cmd_sts =
-		ETH_BUFFER_OWNED_BY_DMA | ETH_RX_ENABLE_INTERRUPT;
-
-	/* Flush descriptor and CPU pipe */
-	mb();
+			ETH_BUFFER_OWNED_BY_DMA | ETH_RX_ENABLE_INTERRUPT;
+	wmb();
 
 	/* Move the used descriptor pointer to the next descriptor */
-	mp->rx_used_desc_q = (used_rx_desc + 1) % MV64340_RX_QUEUE_SIZE;
+	mp->rx_used_desc_q = (used_rx_desc + 1) % mp->rx_ring_size;
 
 	/* Any Rx return cancels the Rx resource error status */
 	mp->rx_resource_err = 0;
 
 	return ETH_OK;
 }
+
+/************* Begin ethtool support *************************/
+
+struct mv643xx_stats {
+	char stat_string[ETH_GSTRING_LEN];
+	int sizeof_stat;
+	int stat_offset;
+};
+
+#define MV643XX_STAT(m) sizeof(((struct mv643xx_private *)0)->m), \
+		      offsetof(struct mv643xx_private, m)
+
+static const struct mv643xx_stats mv643xx_gstrings_stats[] = {
+	{ "rx_packets", MV643XX_STAT(stats.rx_packets) },
+	{ "tx_packets", MV643XX_STAT(stats.tx_packets) },
+	{ "rx_bytes", MV643XX_STAT(stats.rx_bytes) },
+	{ "tx_bytes", MV643XX_STAT(stats.tx_bytes) },
+	{ "rx_errors", MV643XX_STAT(stats.rx_errors) },
+	{ "tx_errors", MV643XX_STAT(stats.tx_errors) },
+	{ "rx_dropped", MV643XX_STAT(stats.rx_dropped) },
+	{ "tx_dropped", MV643XX_STAT(stats.tx_dropped) },
+	{ "good_octets_received", MV643XX_STAT(mib_counters.good_octets_received) },
+	{ "bad_octets_received", MV643XX_STAT(mib_counters.bad_octets_received) },
+	{ "internal_mac_transmit_err", MV643XX_STAT(mib_counters.internal_mac_transmit_err) },
+	{ "good_frames_received", MV643XX_STAT(mib_counters.good_frames_received) },
+	{ "bad_frames_received", MV643XX_STAT(mib_counters.bad_frames_received) },
+	{ "broadcast_frames_received", MV643XX_STAT(mib_counters.broadcast_frames_received) },
+	{ "multicast_frames_received", MV643XX_STAT(mib_counters.multicast_frames_received) },
+	{ "frames_64_octets", MV643XX_STAT(mib_counters.frames_64_octets) },
+	{ "frames_65_to_127_octets", MV643XX_STAT(mib_counters.frames_65_to_127_octets) },
+	{ "frames_128_to_255_octets", MV643XX_STAT(mib_counters.frames_128_to_255_octets) },
+	{ "frames_256_to_511_octets", MV643XX_STAT(mib_counters.frames_256_to_511_octets) },
+	{ "frames_512_to_1023_octets", MV643XX_STAT(mib_counters.frames_512_to_1023_octets) },
+	{ "frames_1024_to_max_octets", MV643XX_STAT(mib_counters.frames_1024_to_max_octets) },
+	{ "good_octets_sent", MV643XX_STAT(mib_counters.good_octets_sent) },
+	{ "good_frames_sent", MV643XX_STAT(mib_counters.good_frames_sent) },
+	{ "excessive_collision", MV643XX_STAT(mib_counters.excessive_collision) },
+	{ "multicast_frames_sent", MV643XX_STAT(mib_counters.multicast_frames_sent) },
+	{ "broadcast_frames_sent", MV643XX_STAT(mib_counters.broadcast_frames_sent) },
+	{ "unrec_mac_control_received", MV643XX_STAT(mib_counters.unrec_mac_control_received) },
+	{ "fc_sent", MV643XX_STAT(mib_counters.fc_sent) },
+	{ "good_fc_received", MV643XX_STAT(mib_counters.good_fc_received) },
+	{ "bad_fc_received", MV643XX_STAT(mib_counters.bad_fc_received) },
+	{ "undersize_received", MV643XX_STAT(mib_counters.undersize_received) },
+	{ "fragments_received", MV643XX_STAT(mib_counters.fragments_received) },
+	{ "oversize_received", MV643XX_STAT(mib_counters.oversize_received) },
+	{ "jabber_received", MV643XX_STAT(mib_counters.jabber_received) },
+	{ "mac_receive_error", MV643XX_STAT(mib_counters.mac_receive_error) },
+	{ "bad_crc_event", MV643XX_STAT(mib_counters.bad_crc_event) },
+	{ "collision", MV643XX_STAT(mib_counters.collision) },
+	{ "late_collision", MV643XX_STAT(mib_counters.late_collision) },
+};
+
+#define MV643XX_STATS_LEN	\
+	sizeof(mv643xx_gstrings_stats) / sizeof(struct mv643xx_stats)
+
+static int
+mv643xx_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd)
+{
+	struct mv643xx_private *mp = netdev->priv;
+	int port_num = mp->port_num;
+	int autoneg = eth_port_autoneg_supported(port_num);
+	int mode_10_bit;
+	int auto_duplex;
+	int half_duplex = 0;
+	int full_duplex = 0;
+	int auto_speed;
+	int speed_10 = 0;
+	int speed_100 = 0;
+	int speed_1000 = 0;
+
+	u32 pcs = mv_read(MV643XX_ETH_PORT_SERIAL_CONTROL_REG(port_num));
+	u32 psr = mv_read(MV643XX_ETH_PORT_STATUS_REG(port_num));
+
+	mode_10_bit = psr & MV643XX_ETH_PORT_STATUS_MODE_10_BIT;
+
+	if (mode_10_bit) {
+		ecmd->supported = SUPPORTED_10baseT_Half;
+	} else {
+		ecmd->supported = (SUPPORTED_10baseT_Half		|
+				   SUPPORTED_10baseT_Full		|
+				   SUPPORTED_100baseT_Half		|
+				   SUPPORTED_100baseT_Full		|
+				   SUPPORTED_1000baseT_Full		|
+				   (autoneg ? SUPPORTED_Autoneg : 0)	|
+				   SUPPORTED_TP);
+
+		auto_duplex = !(pcs & MV643XX_ETH_DISABLE_AUTO_NEG_FOR_DUPLX);
+		auto_speed = !(pcs & MV643XX_ETH_DISABLE_AUTO_NEG_SPEED_GMII);
+
+		ecmd->advertising = ADVERTISED_TP;
+
+		if (autoneg) {
+			ecmd->advertising |= ADVERTISED_Autoneg;
+
+			if (auto_duplex) {
+				half_duplex = 1;
+				full_duplex = 1;
+			} else {
+				if (pcs & MV643XX_ETH_SET_FULL_DUPLEX_MODE)
+					full_duplex = 1;
+				else
+					half_duplex = 1;
+			}
+
+			if (auto_speed) {
+				speed_10 = 1;
+				speed_100 = 1;
+				speed_1000 = 1;
+			} else {
+				if (pcs & MV643XX_ETH_SET_GMII_SPEED_TO_1000)
+					speed_1000 = 1;
+				else if (pcs & MV643XX_ETH_SET_MII_SPEED_TO_100)
+					speed_100 = 1;
+				else
+					speed_10 = 1;
+			}
+
+			if (speed_10 & half_duplex)
+				ecmd->advertising |= ADVERTISED_10baseT_Half;
+			if (speed_10 & full_duplex)
+				ecmd->advertising |= ADVERTISED_10baseT_Full;
+			if (speed_100 & half_duplex)
+				ecmd->advertising |= ADVERTISED_100baseT_Half;
+			if (speed_100 & full_duplex)
+				ecmd->advertising |= ADVERTISED_100baseT_Full;
+			if (speed_1000)
+				ecmd->advertising |= ADVERTISED_1000baseT_Full;
+		}
+	}
+
+	ecmd->port = PORT_TP;
+	ecmd->phy_address = ethernet_phy_get(port_num);
+
+	ecmd->transceiver = XCVR_EXTERNAL;
+
+	if (netif_carrier_ok(netdev)) {
+		if (mode_10_bit)
+			ecmd->speed = SPEED_10;
+		else {
+			if (psr & MV643XX_ETH_PORT_STATUS_GMII_1000)
+				ecmd->speed = SPEED_1000;
+			else if (psr & MV643XX_ETH_PORT_STATUS_MII_100)
+				ecmd->speed = SPEED_100;
+			else
+				ecmd->speed = SPEED_10;
+		}
+
+		if (psr & MV643XX_ETH_PORT_STATUS_FULL_DUPLEX)
+			ecmd->duplex = DUPLEX_FULL;
+		else
+			ecmd->duplex = DUPLEX_HALF;
+	} else {
+		ecmd->speed = -1;
+		ecmd->duplex = -1;
+	}
+
+	ecmd->autoneg = autoneg ? AUTONEG_ENABLE : AUTONEG_DISABLE;
+	return 0;
+}
+
+static void
+mv643xx_get_drvinfo(struct net_device *netdev,
+                       struct ethtool_drvinfo *drvinfo)
+{
+	strncpy(drvinfo->driver,  mv643xx_driver_name, 32);
+	strncpy(drvinfo->version, mv643xx_driver_version, 32);
+	strncpy(drvinfo->fw_version, "N/A", 32);
+	strncpy(drvinfo->bus_info, "mv643xx", 32);
+	drvinfo->n_stats = MV643XX_STATS_LEN;
+}
+
+static int 
+mv643xx_get_stats_count(struct net_device *netdev)
+{
+	return MV643XX_STATS_LEN;
+}
+
+static void 
+mv643xx_get_ethtool_stats(struct net_device *netdev, 
+		struct ethtool_stats *stats, uint64_t *data)
+{
+	struct mv643xx_private *mp = netdev->priv;
+	int i;
+
+	eth_update_mib_counters(mp);
+
+	for(i = 0; i < MV643XX_STATS_LEN; i++) {
+		char *p = (char *)mp+mv643xx_gstrings_stats[i].stat_offset;	
+		data[i] = (mv643xx_gstrings_stats[i].sizeof_stat == 
+			sizeof(uint64_t)) ? *(uint64_t *)p : *(uint32_t *)p;
+	}
+}
+
+static void 
+mv643xx_get_strings(struct net_device *netdev, uint32_t stringset, uint8_t *data)
+{
+	int i;
+
+	switch(stringset) {
+	case ETH_SS_STATS:
+		for (i=0; i < MV643XX_STATS_LEN; i++) {
+			memcpy(data + i * ETH_GSTRING_LEN, 
+			mv643xx_gstrings_stats[i].stat_string,
+			ETH_GSTRING_LEN);
+		}
+		break;
+	}
+}
+
+static struct ethtool_ops mv643xx_ethtool_ops = {
+	.get_settings           = mv643xx_get_settings,
+	.get_drvinfo            = mv643xx_get_drvinfo,
+	.get_link               = ethtool_op_get_link,
+	.get_sg			= ethtool_op_get_sg,
+	.set_sg			= ethtool_op_set_sg,
+	.get_strings            = mv643xx_get_strings,
+	.get_stats_count        = mv643xx_get_stats_count,
+	.get_ethtool_stats      = mv643xx_get_ethtool_stats,
+};
+
+/************* End ethtool support *************************/
diff -Nru a/drivers/net/mv643xx_eth.h b/drivers/net/mv643xx_eth.h
--- a/drivers/net/mv643xx_eth.h	2005-03-11 12:51:46 -08:00
+++ b/drivers/net/mv643xx_eth.h	2005-03-11 12:51:46 -08:00
@@ -1,5 +1,5 @@
-#ifndef __MV64340_ETH_H__
-#define __MV64340_ETH_H__
+#ifndef __MV643XX_ETH_H__
+#define __MV643XX_ETH_H__
 
 #include <linux/version.h>
 #include <linux/module.h>
@@ -46,17 +46,16 @@
  *  The first part is the high level driver of the gigE ethernet ports.
  */
 
-#define ETH_PORT0_IRQ_NUM 48			/* main high register, bit0 */
-#define ETH_PORT1_IRQ_NUM ETH_PORT0_IRQ_NUM+1	/* main high register, bit1 */
-#define ETH_PORT2_IRQ_NUM ETH_PORT0_IRQ_NUM+2	/* main high register, bit1 */
-
-/* Checksum offload for Tx works */
-#define  MV64340_CHECKSUM_OFFLOAD_TX
-#define	 MV64340_NAPI
-#define	 MV64340_TX_FAST_REFILL
-#undef	 MV64340_COAL
+/* Checksum offload for Tx works for most packets, but
+ * fails if previous packet sent did not use hw csum
+ */
+#undef	MV643XX_CHECKSUM_OFFLOAD_TX
+#define	MV643XX_NAPI
+#define	MV643XX_TX_FAST_REFILL
+#undef	MV643XX_RX_QUEUE_FILL_ON_TASK	/* Does not work, yet */
+#undef	MV643XX_COAL
 
-/* 
+/*
  * Number of RX / TX descriptors on RX / TX rings.
  * Note that allocating RX descriptors is done by allocating the RX
  * ring AND a preallocated RX buffers (skb's) for each descriptor.
@@ -65,89 +64,35 @@
  */
 
 /* Default TX ring size is 1000 descriptors */
-#define MV64340_TX_QUEUE_SIZE 1000
+#define MV643XX_DEFAULT_TX_QUEUE_SIZE 1000
 
 /* Default RX ring size is 400 descriptors */
-#define MV64340_RX_QUEUE_SIZE 400
+#define MV643XX_DEFAULT_RX_QUEUE_SIZE 400
 
-#define MV64340_TX_COAL 100
-#ifdef MV64340_COAL
-#define MV64340_RX_COAL 100
+#define MV643XX_TX_COAL 100
+#ifdef MV643XX_COAL
+#define MV643XX_RX_COAL 100
 #endif
 
-
 /*
- * The second part is the low level driver of the gigE ethernet ports.   *
+ * The second part is the low level driver of the gigE ethernet ports.
  */
 
-
 /*
- * Header File for : MV-643xx network interface header 
+ * Header File for : MV-643xx network interface header
  *
  * DESCRIPTION:
- *       This header file contains macros typedefs and function declaration for
- *       the Marvell Gig Bit Ethernet Controller. 
+ *	This header file contains macros typedefs and function declaration for
+ *	the Marvell Gig Bit Ethernet Controller.
  *
  * DEPENDENCIES:
- *       None.
+ *	None.
  *
  */
 
-/* Default port configuration value */
-#define PORT_CONFIG_VALUE                       \
-             ETH_UNICAST_NORMAL_MODE		|   \
-             ETH_DEFAULT_RX_QUEUE_0		|   \
-             ETH_DEFAULT_RX_ARP_QUEUE_0		|   \
-             ETH_RECEIVE_BC_IF_NOT_IP_OR_ARP	|   \
-             ETH_RECEIVE_BC_IF_IP		|   \
-             ETH_RECEIVE_BC_IF_ARP 		|   \
-             ETH_CAPTURE_TCP_FRAMES_DIS		|   \
-             ETH_CAPTURE_UDP_FRAMES_DIS		|   \
-             ETH_DEFAULT_RX_TCP_QUEUE_0		|   \
-             ETH_DEFAULT_RX_UDP_QUEUE_0		|   \
-             ETH_DEFAULT_RX_BPDU_QUEUE_0
-
-/* Default port extend configuration value */
-#define PORT_CONFIG_EXTEND_VALUE		\
-             ETH_SPAN_BPDU_PACKETS_AS_NORMAL	|   \
-             ETH_PARTITION_DISABLE
-
-
-/* Default sdma control value */
-#define PORT_SDMA_CONFIG_VALUE			\
-			 ETH_RX_BURST_SIZE_16_64BIT 	|	\
-			 GT_ETH_IPG_INT_RX(0) 		|	\
-			 ETH_TX_BURST_SIZE_16_64BIT;
-
-#define GT_ETH_IPG_INT_RX(value)                \
-            ((value & 0x3fff) << 8)
-
-/* Default port serial control value */
-#define PORT_SERIAL_CONTROL_VALUE		\
-			ETH_FORCE_LINK_PASS 			|	\
-			ETH_ENABLE_AUTO_NEG_FOR_DUPLX		|	\
-			ETH_DISABLE_AUTO_NEG_FOR_FLOW_CTRL 	|	\
-			ETH_ADV_SYMMETRIC_FLOW_CTRL 		|	\
-			ETH_FORCE_FC_MODE_NO_PAUSE_DIS_TX 	|	\
-			ETH_FORCE_BP_MODE_NO_JAM 		|	\
-			BIT9 					|	\
-			ETH_DO_NOT_FORCE_LINK_FAIL 		|	\
-			ETH_RETRANSMIT_16_ATTEMPTS 		|	\
-			ETH_ENABLE_AUTO_NEG_SPEED_GMII	 	|	\
-			ETH_DTE_ADV_0 				|	\
-			ETH_DISABLE_AUTO_NEG_BYPASS		|	\
-			ETH_AUTO_NEG_NO_CHANGE 			|	\
-			ETH_MAX_RX_PACKET_9700BYTE 		|	\
-			ETH_CLR_EXT_LOOPBACK 			|	\
-			ETH_SET_FULL_DUPLEX_MODE 		|	\
-			ETH_ENABLE_FLOW_CTRL_TX_RX_IN_FULL_DUPLEX
-
-#define RX_BUFFER_MAX_SIZE  0x4000000
-#define TX_BUFFER_MAX_SIZE  0x4000000
-
 /* MAC accepet/reject macros */
-#define ACCEPT_MAC_ADDR	    0
-#define REJECT_MAC_ADDR	    1
+#define ACCEPT_MAC_ADDR				0
+#define REJECT_MAC_ADDR				1
 
 /* Buffer offset from buffer pointer */
 #define RX_BUF_OFFSET				0x2
@@ -155,277 +100,132 @@
 /* Gigabit Ethernet Unit Global Registers */
 
 /* MIB Counters register definitions */
-#define ETH_MIB_GOOD_OCTETS_RECEIVED_LOW   0x0
-#define ETH_MIB_GOOD_OCTETS_RECEIVED_HIGH  0x4
-#define ETH_MIB_BAD_OCTETS_RECEIVED        0x8
-#define ETH_MIB_INTERNAL_MAC_TRANSMIT_ERR  0xc
-#define ETH_MIB_GOOD_FRAMES_RECEIVED       0x10
-#define ETH_MIB_BAD_FRAMES_RECEIVED        0x14
-#define ETH_MIB_BROADCAST_FRAMES_RECEIVED  0x18
-#define ETH_MIB_MULTICAST_FRAMES_RECEIVED  0x1c
-#define ETH_MIB_FRAMES_64_OCTETS           0x20
-#define ETH_MIB_FRAMES_65_TO_127_OCTETS    0x24
-#define ETH_MIB_FRAMES_128_TO_255_OCTETS   0x28
-#define ETH_MIB_FRAMES_256_TO_511_OCTETS   0x2c
-#define ETH_MIB_FRAMES_512_TO_1023_OCTETS  0x30
-#define ETH_MIB_FRAMES_1024_TO_MAX_OCTETS  0x34
-#define ETH_MIB_GOOD_OCTETS_SENT_LOW       0x38
-#define ETH_MIB_GOOD_OCTETS_SENT_HIGH      0x3c
-#define ETH_MIB_GOOD_FRAMES_SENT           0x40
-#define ETH_MIB_EXCESSIVE_COLLISION        0x44
-#define ETH_MIB_MULTICAST_FRAMES_SENT      0x48
-#define ETH_MIB_BROADCAST_FRAMES_SENT      0x4c
-#define ETH_MIB_UNREC_MAC_CONTROL_RECEIVED 0x50
-#define ETH_MIB_FC_SENT                    0x54
-#define ETH_MIB_GOOD_FC_RECEIVED           0x58
-#define ETH_MIB_BAD_FC_RECEIVED            0x5c
-#define ETH_MIB_UNDERSIZE_RECEIVED         0x60
-#define ETH_MIB_FRAGMENTS_RECEIVED         0x64
-#define ETH_MIB_OVERSIZE_RECEIVED          0x68
-#define ETH_MIB_JABBER_RECEIVED            0x6c
-#define ETH_MIB_MAC_RECEIVE_ERROR          0x70
-#define ETH_MIB_BAD_CRC_EVENT              0x74
-#define ETH_MIB_COLLISION                  0x78
-#define ETH_MIB_LATE_COLLISION             0x7c
+#define ETH_MIB_GOOD_OCTETS_RECEIVED_LOW	0x0
+#define ETH_MIB_GOOD_OCTETS_RECEIVED_HIGH	0x4
+#define ETH_MIB_BAD_OCTETS_RECEIVED		0x8
+#define ETH_MIB_INTERNAL_MAC_TRANSMIT_ERR	0xc
+#define ETH_MIB_GOOD_FRAMES_RECEIVED		0x10
+#define ETH_MIB_BAD_FRAMES_RECEIVED		0x14
+#define ETH_MIB_BROADCAST_FRAMES_RECEIVED	0x18
+#define ETH_MIB_MULTICAST_FRAMES_RECEIVED	0x1c
+#define ETH_MIB_FRAMES_64_OCTETS		0x20
+#define ETH_MIB_FRAMES_65_TO_127_OCTETS		0x24
+#define ETH_MIB_FRAMES_128_TO_255_OCTETS	0x28
+#define ETH_MIB_FRAMES_256_TO_511_OCTETS	0x2c
+#define ETH_MIB_FRAMES_512_TO_1023_OCTETS	0x30
+#define ETH_MIB_FRAMES_1024_TO_MAX_OCTETS	0x34
+#define ETH_MIB_GOOD_OCTETS_SENT_LOW		0x38
+#define ETH_MIB_GOOD_OCTETS_SENT_HIGH		0x3c
+#define ETH_MIB_GOOD_FRAMES_SENT		0x40
+#define ETH_MIB_EXCESSIVE_COLLISION		0x44
+#define ETH_MIB_MULTICAST_FRAMES_SENT		0x48
+#define ETH_MIB_BROADCAST_FRAMES_SENT		0x4c
+#define ETH_MIB_UNREC_MAC_CONTROL_RECEIVED	0x50
+#define ETH_MIB_FC_SENT				0x54
+#define ETH_MIB_GOOD_FC_RECEIVED		0x58
+#define ETH_MIB_BAD_FC_RECEIVED			0x5c
+#define ETH_MIB_UNDERSIZE_RECEIVED		0x60
+#define ETH_MIB_FRAGMENTS_RECEIVED		0x64
+#define ETH_MIB_OVERSIZE_RECEIVED		0x68
+#define ETH_MIB_JABBER_RECEIVED			0x6c
+#define ETH_MIB_MAC_RECEIVE_ERROR		0x70
+#define ETH_MIB_BAD_CRC_EVENT			0x74
+#define ETH_MIB_COLLISION			0x78
+#define ETH_MIB_LATE_COLLISION			0x7c
 
 /* Port serial status reg (PSR) */
-#define ETH_INTERFACE_GMII_MII                          0
-#define ETH_INTERFACE_PCM                               BIT0
-#define ETH_LINK_IS_DOWN                                0
-#define ETH_LINK_IS_UP                                  BIT1
-#define ETH_PORT_AT_HALF_DUPLEX                         0
-#define ETH_PORT_AT_FULL_DUPLEX                         BIT2
-#define ETH_RX_FLOW_CTRL_DISABLED                       0
-#define ETH_RX_FLOW_CTRL_ENBALED                        BIT3
-#define ETH_GMII_SPEED_100_10                           0
-#define ETH_GMII_SPEED_1000                             BIT4
-#define ETH_MII_SPEED_10                                0
-#define ETH_MII_SPEED_100                               BIT5
-#define ETH_NO_TX                                       0
-#define ETH_TX_IN_PROGRESS                              BIT7
-#define ETH_BYPASS_NO_ACTIVE                            0
-#define ETH_BYPASS_ACTIVE                               BIT8
-#define ETH_PORT_NOT_AT_PARTITION_STATE                 0
-#define ETH_PORT_AT_PARTITION_STATE                     BIT9
-#define ETH_PORT_TX_FIFO_NOT_EMPTY                      0
-#define ETH_PORT_TX_FIFO_EMPTY                          BIT10
-
-
-/* These macros describes the Port configuration reg (Px_cR) bits */
-#define ETH_UNICAST_NORMAL_MODE                         0
-#define ETH_UNICAST_PROMISCUOUS_MODE                    BIT0
-#define ETH_DEFAULT_RX_QUEUE_0                          0
-#define ETH_DEFAULT_RX_QUEUE_1                          BIT1
-#define ETH_DEFAULT_RX_QUEUE_2                          BIT2
-#define ETH_DEFAULT_RX_QUEUE_3                          (BIT2 | BIT1)
-#define ETH_DEFAULT_RX_QUEUE_4                          BIT3
-#define ETH_DEFAULT_RX_QUEUE_5                          (BIT3 | BIT1)
-#define ETH_DEFAULT_RX_QUEUE_6                          (BIT3 | BIT2)
-#define ETH_DEFAULT_RX_QUEUE_7                          (BIT3 | BIT2 | BIT1)
-#define ETH_DEFAULT_RX_ARP_QUEUE_0                      0
-#define ETH_DEFAULT_RX_ARP_QUEUE_1                      BIT4
-#define ETH_DEFAULT_RX_ARP_QUEUE_2                      BIT5
-#define ETH_DEFAULT_RX_ARP_QUEUE_3                      (BIT5 | BIT4)
-#define ETH_DEFAULT_RX_ARP_QUEUE_4                      BIT6
-#define ETH_DEFAULT_RX_ARP_QUEUE_5                      (BIT6 | BIT4)
-#define ETH_DEFAULT_RX_ARP_QUEUE_6                      (BIT6 | BIT5)
-#define ETH_DEFAULT_RX_ARP_QUEUE_7                      (BIT6 | BIT5 | BIT4)
-#define ETH_RECEIVE_BC_IF_NOT_IP_OR_ARP                 0
-#define ETH_REJECT_BC_IF_NOT_IP_OR_ARP                  BIT7
-#define ETH_RECEIVE_BC_IF_IP                            0
-#define ETH_REJECT_BC_IF_IP                             BIT8
-#define ETH_RECEIVE_BC_IF_ARP                           0
-#define ETH_REJECT_BC_IF_ARP                            BIT9
-#define ETH_TX_AM_NO_UPDATE_ERROR_SUMMARY               BIT12
-#define ETH_CAPTURE_TCP_FRAMES_DIS                      0
-#define ETH_CAPTURE_TCP_FRAMES_EN                       BIT14
-#define ETH_CAPTURE_UDP_FRAMES_DIS                      0
-#define ETH_CAPTURE_UDP_FRAMES_EN                       BIT15
-#define ETH_DEFAULT_RX_TCP_QUEUE_0                      0
-#define ETH_DEFAULT_RX_TCP_QUEUE_1                      BIT16
-#define ETH_DEFAULT_RX_TCP_QUEUE_2                      BIT17
-#define ETH_DEFAULT_RX_TCP_QUEUE_3                      (BIT17 | BIT16)
-#define ETH_DEFAULT_RX_TCP_QUEUE_4                      BIT18
-#define ETH_DEFAULT_RX_TCP_QUEUE_5                      (BIT18 | BIT16)
-#define ETH_DEFAULT_RX_TCP_QUEUE_6                      (BIT18 | BIT17)
-#define ETH_DEFAULT_RX_TCP_QUEUE_7                      (BIT18 | BIT17 | BIT16)
-#define ETH_DEFAULT_RX_UDP_QUEUE_0                      0
-#define ETH_DEFAULT_RX_UDP_QUEUE_1                      BIT19
-#define ETH_DEFAULT_RX_UDP_QUEUE_2                      BIT20
-#define ETH_DEFAULT_RX_UDP_QUEUE_3                      (BIT20 | BIT19)
-#define ETH_DEFAULT_RX_UDP_QUEUE_4                      (BIT21
-#define ETH_DEFAULT_RX_UDP_QUEUE_5                      (BIT21 | BIT19)
-#define ETH_DEFAULT_RX_UDP_QUEUE_6                      (BIT21 | BIT20)
-#define ETH_DEFAULT_RX_UDP_QUEUE_7                      (BIT21 | BIT20 | BIT19)
-#define ETH_DEFAULT_RX_BPDU_QUEUE_0                      0
-#define ETH_DEFAULT_RX_BPDU_QUEUE_1                     BIT22
-#define ETH_DEFAULT_RX_BPDU_QUEUE_2                     BIT23
-#define ETH_DEFAULT_RX_BPDU_QUEUE_3                     (BIT23 | BIT22)
-#define ETH_DEFAULT_RX_BPDU_QUEUE_4                     BIT24
-#define ETH_DEFAULT_RX_BPDU_QUEUE_5                     (BIT24 | BIT22)
-#define ETH_DEFAULT_RX_BPDU_QUEUE_6                     (BIT24 | BIT23)
-#define ETH_DEFAULT_RX_BPDU_QUEUE_7                     (BIT24 | BIT23 | BIT22)
-
-
-/* These macros describes the Port configuration extend reg (Px_cXR) bits*/
-#define ETH_CLASSIFY_EN                                 BIT0
-#define ETH_SPAN_BPDU_PACKETS_AS_NORMAL                 0
-#define ETH_SPAN_BPDU_PACKETS_TO_RX_QUEUE_7             BIT1
-#define ETH_PARTITION_DISABLE                           0
-#define ETH_PARTITION_ENABLE                            BIT2
-
-
-/* Tx/Rx queue command reg (RQCR/TQCR)*/
-#define ETH_QUEUE_0_ENABLE                              BIT0
-#define ETH_QUEUE_1_ENABLE                              BIT1
-#define ETH_QUEUE_2_ENABLE                              BIT2
-#define ETH_QUEUE_3_ENABLE                              BIT3
-#define ETH_QUEUE_4_ENABLE                              BIT4
-#define ETH_QUEUE_5_ENABLE                              BIT5
-#define ETH_QUEUE_6_ENABLE                              BIT6
-#define ETH_QUEUE_7_ENABLE                              BIT7
-#define ETH_QUEUE_0_DISABLE                             BIT8
-#define ETH_QUEUE_1_DISABLE                             BIT9
-#define ETH_QUEUE_2_DISABLE                             BIT10
-#define ETH_QUEUE_3_DISABLE                             BIT11
-#define ETH_QUEUE_4_DISABLE                             BIT12
-#define ETH_QUEUE_5_DISABLE                             BIT13
-#define ETH_QUEUE_6_DISABLE                             BIT14
-#define ETH_QUEUE_7_DISABLE                             BIT15
-
-
-/* These macros describes the Port Sdma configuration reg (SDCR) bits */
-#define ETH_RIFB                                        BIT0
-#define ETH_RX_BURST_SIZE_1_64BIT                       0
-#define ETH_RX_BURST_SIZE_2_64BIT                       BIT1
-#define ETH_RX_BURST_SIZE_4_64BIT                       BIT2
-#define ETH_RX_BURST_SIZE_8_64BIT                       (BIT2 | BIT1)
-#define ETH_RX_BURST_SIZE_16_64BIT                      BIT3
-#define ETH_BLM_RX_NO_SWAP                              BIT4
-#define ETH_BLM_RX_BYTE_SWAP                            0
-#define ETH_BLM_TX_NO_SWAP                              BIT5
-#define ETH_BLM_TX_BYTE_SWAP                            0
-#define ETH_DESCRIPTORS_BYTE_SWAP                       BIT6
-#define ETH_DESCRIPTORS_NO_SWAP                         0
-#define ETH_TX_BURST_SIZE_1_64BIT                       0
-#define ETH_TX_BURST_SIZE_2_64BIT                       BIT22
-#define ETH_TX_BURST_SIZE_4_64BIT                       BIT23
-#define ETH_TX_BURST_SIZE_8_64BIT                       (BIT23 | BIT22)
-#define ETH_TX_BURST_SIZE_16_64BIT                      BIT24
-
-
-
-/* These macros describes the Port serial control reg (PSCR) bits */
-#define ETH_SERIAL_PORT_DISABLE                         0
-#define ETH_SERIAL_PORT_ENABLE                          BIT0
-#define ETH_FORCE_LINK_PASS                             BIT1
-#define ETH_DO_NOT_FORCE_LINK_PASS                      0
-#define ETH_ENABLE_AUTO_NEG_FOR_DUPLX                   0
-#define ETH_DISABLE_AUTO_NEG_FOR_DUPLX                  BIT2
-#define ETH_ENABLE_AUTO_NEG_FOR_FLOW_CTRL               0
-#define ETH_DISABLE_AUTO_NEG_FOR_FLOW_CTRL              BIT3
-#define ETH_ADV_NO_FLOW_CTRL                            0
-#define ETH_ADV_SYMMETRIC_FLOW_CTRL                     BIT4
-#define ETH_FORCE_FC_MODE_NO_PAUSE_DIS_TX               0
-#define ETH_FORCE_FC_MODE_TX_PAUSE_DIS                  BIT5
-#define ETH_FORCE_BP_MODE_NO_JAM                        0
-#define ETH_FORCE_BP_MODE_JAM_TX                        BIT7
-#define ETH_FORCE_BP_MODE_JAM_TX_ON_RX_ERR              BIT8
-#define ETH_FORCE_LINK_FAIL                             0
-#define ETH_DO_NOT_FORCE_LINK_FAIL                      BIT10
-#define ETH_RETRANSMIT_16_ATTEMPTS                      0
-#define ETH_RETRANSMIT_FOREVER                          BIT11
-#define ETH_DISABLE_AUTO_NEG_SPEED_GMII                 BIT13
-#define ETH_ENABLE_AUTO_NEG_SPEED_GMII                  0
-#define ETH_DTE_ADV_0                                   0
-#define ETH_DTE_ADV_1                                   BIT14
-#define ETH_DISABLE_AUTO_NEG_BYPASS                     0
-#define ETH_ENABLE_AUTO_NEG_BYPASS                      BIT15
-#define ETH_AUTO_NEG_NO_CHANGE                          0
-#define ETH_RESTART_AUTO_NEG                            BIT16
-#define ETH_MAX_RX_PACKET_1518BYTE                      0
-#define ETH_MAX_RX_PACKET_1522BYTE                      BIT17
-#define ETH_MAX_RX_PACKET_1552BYTE                      BIT18
-#define ETH_MAX_RX_PACKET_9022BYTE                      (BIT18 | BIT17)
-#define ETH_MAX_RX_PACKET_9192BYTE                      BIT19
-#define ETH_MAX_RX_PACKET_9700BYTE                      (BIT19 | BIT17)
-#define ETH_SET_EXT_LOOPBACK                            BIT20
-#define ETH_CLR_EXT_LOOPBACK                            0
-#define ETH_SET_FULL_DUPLEX_MODE                        BIT21
-#define ETH_SET_HALF_DUPLEX_MODE                        0
-#define ETH_ENABLE_FLOW_CTRL_TX_RX_IN_FULL_DUPLEX       BIT22
-#define ETH_DISABLE_FLOW_CTRL_TX_RX_IN_FULL_DUPLEX      0
-#define ETH_SET_GMII_SPEED_TO_10_100                    0
-#define ETH_SET_GMII_SPEED_TO_1000                      BIT23
-#define ETH_SET_MII_SPEED_TO_10                         0
-#define ETH_SET_MII_SPEED_TO_100                        BIT24
-
+#define ETH_INTERFACE_GMII_MII			0
+#define ETH_INTERFACE_PCM			BIT0
+#define ETH_LINK_IS_DOWN			0
+#define ETH_LINK_IS_UP				BIT1
+#define ETH_PORT_AT_HALF_DUPLEX			0
+#define ETH_PORT_AT_FULL_DUPLEX			BIT2
+#define ETH_RX_FLOW_CTRL_DISABLED		0
+#define ETH_RX_FLOW_CTRL_ENBALED		BIT3
+#define ETH_GMII_SPEED_100_10			0
+#define ETH_GMII_SPEED_1000			BIT4
+#define ETH_MII_SPEED_10			0
+#define ETH_MII_SPEED_100			BIT5
+#define ETH_NO_TX				0
+#define ETH_TX_IN_PROGRESS			BIT7
+#define ETH_BYPASS_NO_ACTIVE			0
+#define ETH_BYPASS_ACTIVE			BIT8
+#define ETH_PORT_NOT_AT_PARTITION_STATE		0
+#define ETH_PORT_AT_PARTITION_STATE		BIT9
+#define ETH_PORT_TX_FIFO_NOT_EMPTY		0
+#define ETH_PORT_TX_FIFO_EMPTY			BIT10
+
+#define ETH_DEFAULT_RX_BPDU_QUEUE_3		(BIT23 | BIT22)
+#define ETH_DEFAULT_RX_BPDU_QUEUE_4		BIT24
+#define ETH_DEFAULT_RX_BPDU_QUEUE_5		(BIT24 | BIT22)
+#define ETH_DEFAULT_RX_BPDU_QUEUE_6		(BIT24 | BIT23)
+#define ETH_DEFAULT_RX_BPDU_QUEUE_7		(BIT24 | BIT23 | BIT22)
 
 /* SMI reg */
-#define ETH_SMI_BUSY        	BIT28	/* 0 - Write, 1 - Read          */
-#define ETH_SMI_READ_VALID  	BIT27	/* 0 - Write, 1 - Read          */
+#define ETH_SMI_BUSY		BIT28	/* 0 - Write, 1 - Read		*/
+#define ETH_SMI_READ_VALID	BIT27	/* 0 - Write, 1 - Read		*/
 #define ETH_SMI_OPCODE_WRITE	0	/* Completion of Read operation */
-#define ETH_SMI_OPCODE_READ 	BIT26	/* Operation is in progress             */
+#define ETH_SMI_OPCODE_READ 	BIT26	/* Operation is in progress	*/
 
 /* SDMA command status fields macros */
 
 /* Tx & Rx descriptors status */
-#define ETH_ERROR_SUMMARY                   (BIT0)
+#define ETH_ERROR_SUMMARY			(BIT0)
 
 /* Tx & Rx descriptors command */
-#define ETH_BUFFER_OWNED_BY_DMA             (BIT31)
+#define ETH_BUFFER_OWNED_BY_DMA			(BIT31)
 
 /* Tx descriptors status */
-#define ETH_LC_ERROR                        (0	  )
-#define ETH_UR_ERROR                        (BIT1 )
-#define ETH_RL_ERROR                        (BIT2 )
-#define ETH_LLC_SNAP_FORMAT                 (BIT9 )
+#define ETH_LC_ERROR				(0    )
+#define ETH_UR_ERROR				(BIT1 )
+#define ETH_RL_ERROR				(BIT2 )
+#define ETH_LLC_SNAP_FORMAT			(BIT9 )
 
 /* Rx descriptors status */
-#define ETH_CRC_ERROR                       (0	  )
-#define ETH_OVERRUN_ERROR                   (BIT1 )
-#define ETH_MAX_FRAME_LENGTH_ERROR          (BIT2 )
-#define ETH_RESOURCE_ERROR                  ((BIT2 | BIT1))
-#define ETH_VLAN_TAGGED                     (BIT19)
-#define ETH_BPDU_FRAME                      (BIT20)
-#define ETH_TCP_FRAME_OVER_IP_V_4           (0    )
-#define ETH_UDP_FRAME_OVER_IP_V_4           (BIT21)
-#define ETH_OTHER_FRAME_TYPE                (BIT22)
-#define ETH_LAYER_2_IS_ETH_V_2              (BIT23)
-#define ETH_FRAME_TYPE_IP_V_4               (BIT24)
-#define ETH_FRAME_HEADER_OK                 (BIT25)
-#define ETH_RX_LAST_DESC                    (BIT26)
-#define ETH_RX_FIRST_DESC                   (BIT27)
-#define ETH_UNKNOWN_DESTINATION_ADDR        (BIT28)
-#define ETH_RX_ENABLE_INTERRUPT             (BIT29)
-#define ETH_LAYER_4_CHECKSUM_OK             (BIT30)
+#define ETH_CRC_ERROR				(0    )
+#define ETH_OVERRUN_ERROR			(BIT1 )
+#define ETH_MAX_FRAME_LENGTH_ERROR		(BIT2 )
+#define ETH_RESOURCE_ERROR			((BIT2 | BIT1))
+#define ETH_VLAN_TAGGED				(BIT19)
+#define ETH_BPDU_FRAME				(BIT20)
+#define ETH_TCP_FRAME_OVER_IP_V_4		(0    )
+#define ETH_UDP_FRAME_OVER_IP_V_4		(BIT21)
+#define ETH_OTHER_FRAME_TYPE			(BIT22)
+#define ETH_LAYER_2_IS_ETH_V_2			(BIT23)
+#define ETH_FRAME_TYPE_IP_V_4			(BIT24)
+#define ETH_FRAME_HEADER_OK			(BIT25)
+#define ETH_RX_LAST_DESC			(BIT26)
+#define ETH_RX_FIRST_DESC			(BIT27)
+#define ETH_UNKNOWN_DESTINATION_ADDR		(BIT28)
+#define ETH_RX_ENABLE_INTERRUPT			(BIT29)
+#define ETH_LAYER_4_CHECKSUM_OK			(BIT30)
 
 /* Rx descriptors byte count */
-#define ETH_FRAME_FRAGMENTED                (BIT2)
+#define ETH_FRAME_FRAGMENTED			(BIT2)
 
 /* Tx descriptors command */
 #define ETH_LAYER_4_CHECKSUM_FIRST_DESC		(BIT10)
-#define ETH_FRAME_SET_TO_VLAN               (BIT15)
-#define ETH_TCP_FRAME                       (0	  )
-#define ETH_UDP_FRAME                       (BIT16)
-#define ETH_GEN_TCP_UDP_CHECKSUM            (BIT17)
-#define ETH_GEN_IP_V_4_CHECKSUM             (BIT18)
-#define ETH_ZERO_PADDING                    (BIT19)
-#define ETH_TX_LAST_DESC                    (BIT20)
-#define ETH_TX_FIRST_DESC                   (BIT21)
-#define ETH_GEN_CRC                         (BIT22)
-#define ETH_TX_ENABLE_INTERRUPT             (BIT23)
-#define ETH_AUTO_MODE                       (BIT30)
+#define ETH_FRAME_SET_TO_VLAN			(BIT15)
+#define ETH_TCP_FRAME				(0    )
+#define ETH_UDP_FRAME				(BIT16)
+#define ETH_GEN_TCP_UDP_CHECKSUM		(BIT17)
+#define ETH_GEN_IP_V_4_CHECKSUM			(BIT18)
+#define ETH_ZERO_PADDING			(BIT19)
+#define ETH_TX_LAST_DESC			(BIT20)
+#define ETH_TX_FIRST_DESC			(BIT21)
+#define ETH_GEN_CRC				(BIT22)
+#define ETH_TX_ENABLE_INTERRUPT			(BIT23)
+#define ETH_AUTO_MODE				(BIT30)
 
 /* typedefs */
 
 typedef enum _eth_func_ret_status {
-	ETH_OK,			/* Returned as expected.                    */
-	ETH_ERROR,		/* Fundamental error.                       */
-	ETH_RETRY,		/* Could not process request. Try later.    */
-	ETH_END_OF_JOB,		/* Ring has nothing to process.             */
-	ETH_QUEUE_FULL,		/* Ring resource error.                     */
-	ETH_QUEUE_LAST_RESOURCE	/* Ring resources about to exhaust.         */
+	ETH_OK,			/* Returned as expected.		*/
+	ETH_ERROR,		/* Fundamental error.			*/
+	ETH_RETRY,		/* Could not process request. Try later.*/
+	ETH_END_OF_JOB,		/* Ring has nothing to process.		*/
+	ETH_QUEUE_FULL,		/* Ring resource error.			*/
+	ETH_QUEUE_LAST_RESOURCE	/* Ring resources about to exhaust.	*/
 } ETH_FUNC_RET_STATUS;
 
 typedef enum _eth_target {
@@ -441,66 +241,103 @@
  */
 #if defined(__BIG_ENDIAN)
 struct eth_rx_desc {
-	u16	byte_cnt;	/* Descriptor buffer byte count     */
-	u16	buf_size;	/* Buffer size                      */
-	u32	cmd_sts;	/* Descriptor command status        */
-	u32	next_desc_ptr;	/* Next descriptor pointer          */
-	u32	buf_ptr;	/* Descriptor buffer pointer        */
+	u16 byte_cnt;		/* Descriptor buffer byte count		*/
+	u16 buf_size;		/* Buffer size				*/
+	u32 cmd_sts;		/* Descriptor command status		*/
+	u32 next_desc_ptr;	/* Next descriptor pointer		*/
+	u32 buf_ptr;		/* Descriptor buffer pointer		*/
 };
 
 struct eth_tx_desc {
-	u16	byte_cnt;	/* buffer byte count */
-	u16	l4i_chk;	/* CPU provided TCP checksum */
-	u32	cmd_sts;	/* Command/status field */
-	u32	next_desc_ptr;	/* Pointer to next descriptor */
-	u32	buf_ptr;	/* pointer to buffer for this descriptor */
+	u16 byte_cnt;		/* buffer byte count			*/
+	u16 l4i_chk;		/* CPU provided TCP checksum		*/
+	u32 cmd_sts;		/* Command/status field			*/
+	u32 next_desc_ptr;	/* Pointer to next descriptor		*/
+	u32 buf_ptr;		/* pointer to buffer for this descriptor*/
 };
 
 #elif defined(__LITTLE_ENDIAN)
 struct eth_rx_desc {
-	u32	cmd_sts;	/* Descriptor command status        */
-	u16	buf_size;	/* Buffer size                      */
-	u16	byte_cnt;	/* Descriptor buffer byte count     */
-	u32	buf_ptr;	/* Descriptor buffer pointer        */
-	u32	next_desc_ptr;	/* Next descriptor pointer          */
+	u32 cmd_sts;		/* Descriptor command status		*/
+	u16 buf_size;		/* Buffer size				*/
+	u16 byte_cnt;		/* Descriptor buffer byte count		*/
+	u32 buf_ptr;		/* Descriptor buffer pointer		*/
+	u32 next_desc_ptr;	/* Next descriptor pointer		*/
 };
 
 struct eth_tx_desc {
-	u32	cmd_sts;	/* Command/status field */
-	u16	l4i_chk;	/* CPU provided TCP checksum */
-	u16	byte_cnt;	/* buffer byte count */
-	u32	buf_ptr;	/* pointer to buffer for this descriptor */
-	u32	next_desc_ptr;	/* Pointer to next descriptor */
+	u32 cmd_sts;		/* Command/status field			*/
+	u16 l4i_chk;		/* CPU provided TCP checksum		*/
+	u16 byte_cnt;		/* buffer byte count			*/
+	u32 buf_ptr;		/* pointer to buffer for this descriptor*/
+	u32 next_desc_ptr;	/* Pointer to next descriptor		*/
 };
 #else
 #error One of __BIG_ENDIAN or __LITTLE_ENDIAN must be defined
 #endif
 
-/* Unified struct for Rx and Tx operations. The user is not required to */
-/* be familier with neither Tx nor Rx descriptors.                       */
+/* Unified struct for Rx and Tx operations. The user is not required to	*/
+/* be familier with neither Tx nor Rx descriptors.			*/
 struct pkt_info {
-	unsigned short	byte_cnt;	/* Descriptor buffer byte count     */
-	unsigned short	l4i_chk;	/* Tx CPU provided TCP Checksum     */
-	unsigned int	cmd_sts;	/* Descriptor command status        */
-	dma_addr_t	buf_ptr;	/* Descriptor buffer pointer        */
-	struct sk_buff	* return_info;	/* User resource return information */
+	unsigned short byte_cnt;	/* Descriptor buffer byte count	*/
+	unsigned short l4i_chk;		/* Tx CPU provided TCP Checksum	*/
+	unsigned int cmd_sts;		/* Descriptor command status	*/
+	dma_addr_t buf_ptr;		/* Descriptor buffer pointer	*/
+	struct sk_buff *return_info;	/* User resource return information */
 };
 
-
 /* Ethernet port specific infomation */
 
-struct mv64340_private {
-	int	port_num;		/* User Ethernet port number */
-	u8	port_mac_addr[6];	/* User defined port MAC address. */
-	u32	port_config;		/* User port configuration value */
-	u32	port_config_extend;	/* User port config extend value */
-	u32	port_sdma_config;	/* User port SDMA config value */
-	u32	port_serial_control;	/* User port serial control value */
-	u32	port_tx_queue_command;	/* Port active Tx queues summary */
-	u32	port_rx_queue_command;	/* Port active Rx queues summary */
+struct mv643xx_mib_counters {
+	u64 good_octets_received;
+	u32 bad_octets_received;
+	u32 internal_mac_transmit_err;
+	u32 good_frames_received;
+	u32 bad_frames_received;
+	u32 broadcast_frames_received;
+	u32 multicast_frames_received;
+	u32 frames_64_octets;
+	u32 frames_65_to_127_octets;
+	u32 frames_128_to_255_octets;
+	u32 frames_256_to_511_octets;
+	u32 frames_512_to_1023_octets;
+	u32 frames_1024_to_max_octets;
+	u64 good_octets_sent;
+	u32 good_frames_sent;
+	u32 excessive_collision;
+	u32 multicast_frames_sent;
+	u32 broadcast_frames_sent;
+	u32 unrec_mac_control_received;
+	u32 fc_sent;
+	u32 good_fc_received;
+	u32 bad_fc_received;
+	u32 undersize_received;
+	u32 fragments_received;
+	u32 oversize_received;
+	u32 jabber_received;
+	u32 mac_receive_error;
+	u32 bad_crc_event;
+	u32 collision;
+	u32 late_collision;
+};
+
+struct mv643xx_private {
+	int port_num;			/* User Ethernet port number	*/
+	u8 port_mac_addr[6];		/* User defined port MAC address.*/
+	u32 port_config;		/* User port configuration value*/
+	u32 port_config_extend;		/* User port config extend value*/
+	u32 port_sdma_config;		/* User port SDMA config value	*/
+	u32 port_serial_control;	/* User port serial control value */
+	u32 port_tx_queue_command;	/* Port active Tx queues summary*/
+	u32 port_rx_queue_command;	/* Port active Rx queues summary*/
+
+	u32 rx_sram_addr;		/* Base address of rx sram area */
+	u32 rx_sram_size;		/* Size of rx sram area		*/
+	u32 tx_sram_addr;		/* Base address of tx sram area */
+	u32 tx_sram_size;		/* Size of tx sram area		*/
 
-	int	rx_resource_err;	/* Rx ring resource error flag */
-	int	tx_resource_err;	/* Tx ring resource error flag */
+	int rx_resource_err;		/* Rx ring resource error flag */
+	int tx_resource_err;		/* Tx ring resource error flag */
 
 	/* Tx/Rx rings managment indexes fields. For driver use */
 
@@ -509,30 +346,32 @@
 
 	/* Next available and first returning Tx resource */
 	int tx_curr_desc_q, tx_used_desc_q;
-#ifdef MV64340_CHECKSUM_OFFLOAD_TX
-        int tx_first_desc_q;
+#ifdef MV643XX_CHECKSUM_OFFLOAD_TX
+	int tx_first_desc_q;
+	u32 tx_first_command;
 #endif
 
-#ifdef MV64340_TX_FAST_REFILL
-	u32	tx_clean_threshold;
+#ifdef MV643XX_TX_FAST_REFILL
+	u32 tx_clean_threshold;
 #endif
 
-	volatile struct eth_rx_desc	* p_rx_desc_area;
-	dma_addr_t			rx_desc_dma;
-	unsigned int			rx_desc_area_size;
-	struct sk_buff			* rx_skb[MV64340_RX_QUEUE_SIZE];
-
-	volatile struct eth_tx_desc	* p_tx_desc_area;
-	dma_addr_t			tx_desc_dma;
-	unsigned int			tx_desc_area_size;
-	struct sk_buff			* tx_skb[MV64340_TX_QUEUE_SIZE];
+	struct eth_rx_desc *p_rx_desc_area;
+	dma_addr_t rx_desc_dma;
+	unsigned int rx_desc_area_size;
+	struct sk_buff **rx_skb;
+
+	struct eth_tx_desc *p_tx_desc_area;
+	dma_addr_t tx_desc_dma;
+	unsigned int tx_desc_area_size;
+	struct sk_buff **tx_skb;
 
-	struct work_struct		tx_timeout_task;
+	struct work_struct tx_timeout_task;
 
 	/*
-	 * Former struct mv64340_eth_priv members start here
+	 * Former struct mv643xx_eth_priv members start here
 	 */
 	struct net_device_stats stats;
+	struct mv643xx_mib_counters mib_counters;
 	spinlock_t lock;
 	/* Size of Tx Ring per queue */
 	unsigned int tx_ring_size;
@@ -544,13 +383,13 @@
 	unsigned int rx_ring_skbs;
 
 	/*
-	 * rx_task used to fill RX ring out of bottom half context 
+	 * rx_task used to fill RX ring out of bottom half context
 	 */
 	struct work_struct rx_task;
 
-	/* 
-	 * Used in case RX Ring is empty, which can be caused when 
-	 * system does not have resources (skb's) 
+	/*
+	 * Used in case RX Ring is empty, which can be caused when
+	 * system does not have resources (skb's)
 	 */
 	struct timer_list timeout;
 	long rx_task_busy __attribute__ ((aligned(SMP_CACHE_BYTES)));
@@ -563,9 +402,9 @@
 /* ethernet.h API list */
 
 /* Port operation control routines */
-static void eth_port_init(struct mv64340_private *mp);
+static void eth_port_init(struct mv643xx_private *mp);
 static void eth_port_reset(unsigned int eth_port_num);
-static int eth_port_start(struct mv64340_private *mp);
+static void eth_port_start(struct mv643xx_private *mp);
 
 static void ethernet_set_config_reg(unsigned int eth_port_num,
 				    unsigned int value);
@@ -576,26 +415,24 @@
 				 unsigned char *p_addr);
 
 /* PHY and MIB routines */
-static int ethernet_phy_reset(unsigned int eth_port_num);
+static void ethernet_phy_reset(unsigned int eth_port_num);
+
+static void eth_port_write_smi_reg(unsigned int eth_port_num,
+				   unsigned int phy_reg, unsigned int value);
 
-static int eth_port_write_smi_reg(unsigned int eth_port_num,
-				   unsigned int phy_reg,
-				   unsigned int value);
-
-static int eth_port_read_smi_reg(unsigned int eth_port_num,
-				  unsigned int phy_reg,
-				  unsigned int *value);
+static void eth_port_read_smi_reg(unsigned int eth_port_num,
+				  unsigned int phy_reg, unsigned int *value);
 
 static void eth_clear_mib_counters(unsigned int eth_port_num);
 
 /* Port data flow control routines */
-static ETH_FUNC_RET_STATUS eth_port_send(struct mv64340_private *mp,
-					 struct pkt_info * p_pkt_info);
-static ETH_FUNC_RET_STATUS eth_tx_return_desc(struct mv64340_private *mp,
-					      struct pkt_info * p_pkt_info);
-static ETH_FUNC_RET_STATUS eth_port_receive(struct mv64340_private *mp,
-					    struct pkt_info * p_pkt_info);
-static ETH_FUNC_RET_STATUS eth_rx_return_buff(struct mv64340_private *mp,
-					      struct pkt_info * p_pkt_info);
+static ETH_FUNC_RET_STATUS eth_port_send(struct mv643xx_private *mp,
+					 struct pkt_info *p_pkt_info);
+static ETH_FUNC_RET_STATUS eth_tx_return_desc(struct mv643xx_private *mp,
+					      struct pkt_info *p_pkt_info);
+static ETH_FUNC_RET_STATUS eth_port_receive(struct mv643xx_private *mp,
+					    struct pkt_info *p_pkt_info);
+static ETH_FUNC_RET_STATUS eth_rx_return_buff(struct mv643xx_private *mp,
+					      struct pkt_info *p_pkt_info);
 
-#endif  /* __MV64340_ETH_H__ */
+#endif				/* __MV643XX_ETH_H__ */
diff -Nru a/drivers/net/natsemi.c b/drivers/net/natsemi.c
--- a/drivers/net/natsemi.c	2005-03-11 12:51:41 -08:00
+++ b/drivers/net/natsemi.c	2005-03-11 12:51:41 -08:00
@@ -3162,7 +3162,7 @@
  * Interrupts must be disabled, otherwise hands_off can cause irq storms.
  */
 
-static int natsemi_suspend (struct pci_dev *pdev, u32 state)
+static int natsemi_suspend (struct pci_dev *pdev, pm_message_t state)
 {
 	struct net_device *dev = pci_get_drvdata (pdev);
 	struct netdev_private *np = netdev_priv(dev);
diff -Nru a/drivers/net/ne2k-pci.c b/drivers/net/ne2k-pci.c
--- a/drivers/net/ne2k-pci.c	2005-03-11 12:51:41 -08:00
+++ b/drivers/net/ne2k-pci.c	2005-03-11 12:51:41 -08:00
@@ -654,13 +654,13 @@
 }
 
 #ifdef CONFIG_PM
-static int ne2k_pci_suspend (struct pci_dev *pdev, u32 state)
+static int ne2k_pci_suspend (struct pci_dev *pdev, pm_message_t state)
 {
 	struct net_device *dev = pci_get_drvdata (pdev);
 
 	netif_device_detach(dev);
 	pci_save_state(pdev);
-	pci_set_power_state(pdev, state);
+	pci_set_power_state(pdev, pci_choose_state(pdev, state));
 
 	return 0;
 }
diff -Nru a/drivers/net/ni65.c b/drivers/net/ni65.c
--- a/drivers/net/ni65.c	2005-03-11 12:51:42 -08:00
+++ b/drivers/net/ni65.c	2005-03-11 12:51:42 -08:00
@@ -526,8 +526,7 @@
 			ni65_init_lance(p,dev->dev_addr,0,0);
 			irq_mask = probe_irq_on();
 			writereg(CSR0_INIT|CSR0_INEA,CSR0); /* trigger interrupt */
-			set_current_state(TASK_UNINTERRUPTIBLE);
-			schedule_timeout(HZ/50);
+			msleep(20);
 			dev->irq = probe_irq_off(irq_mask);
 			if(!dev->irq)
 			{
diff -Nru a/drivers/net/ns83820.c b/drivers/net/ns83820.c
--- a/drivers/net/ns83820.c	2005-03-11 12:51:51 -08:00
+++ b/drivers/net/ns83820.c	2005-03-11 12:51:51 -08:00
@@ -2007,8 +2007,7 @@
 	if (reset_phy) {
 		printk(KERN_INFO "%s: resetting phy\n", ndev->name);
 		writel(dev->CFG_cache | CFG_PHY_RST, dev->base + CFG);
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		schedule_timeout((HZ+99)/100);
+		msleep(10);
 		writel(dev->CFG_cache, dev->base + CFG);
 	}
 
diff -Nru a/drivers/net/pcmcia/ibmtr_cs.c b/drivers/net/pcmcia/ibmtr_cs.c
--- a/drivers/net/pcmcia/ibmtr_cs.c	2005-03-11 12:51:46 -08:00
+++ b/drivers/net/pcmcia/ibmtr_cs.c	2005-03-11 12:51:46 -08:00
@@ -343,7 +343,8 @@
     CS_CHECK(MapMemPage, pcmcia_map_mem_page(info->sram_win_handle, &mem));
 
     ti->sram_base = mem.CardOffset >> 12;
-    ti->sram_virt = (u_long)ioremap(req.Base, req.Size);
+    ti->sram_virt = ioremap(req.Base, req.Size);
+    ti->sram_phys = req.Base;
 
     CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link->handle, &link->conf));
 
@@ -401,7 +402,7 @@
     pcmcia_release_irq(link->handle, &link->irq);
     if (link->win) {
 	struct tok_info *ti = netdev_priv(dev);
-	iounmap((void *)ti->mmio);
+	iounmap(ti->mmio);
 	pcmcia_release_window(link->win);
 	pcmcia_release_window(info->sram_win_handle);
     }
@@ -433,7 +434,7 @@
         if (link->state & DEV_CONFIG) {
 	    /* set flag to bypass normal interrupt code */
 	    struct tok_info *priv = netdev_priv(dev);
-	    priv->sram_virt |= 1;
+	    priv->sram_phys |= 1;
 	    netif_device_detach(dev);
         }
         break;
diff -Nru a/drivers/net/pcmcia/xirc2ps_cs.c b/drivers/net/pcmcia/xirc2ps_cs.c
--- a/drivers/net/pcmcia/xirc2ps_cs.c	2005-03-11 12:51:42 -08:00
+++ b/drivers/net/pcmcia/xirc2ps_cs.c	2005-03-11 12:51:42 -08:00
@@ -415,11 +415,6 @@
 #define PutByte(reg,value) outb((value), ioaddr+(reg))
 #define PutWord(reg,value) outw((value), ioaddr+(reg))
 
-#define Wait(n) do { \
-	set_current_state(TASK_UNINTERRUPTIBLE); \
-	schedule_timeout(n); \
-} while (0)
-
 /*====== Functions used for debugging =================================*/
 #if defined(PCMCIA_DEBUG) && 0 /* reading regs may change system status */
 static void
@@ -1707,12 +1702,12 @@
     SelectPage(4);
     udelay(1);
     PutByte(XIRCREG4_GPR1, 0);	     /* clear bit 0: power down */
-    Wait(HZ/25);		     /* wait 40 msec */
+    msleep(40);				     /* wait 40 msec */
     if (local->mohawk)
 	PutByte(XIRCREG4_GPR1, 1);	 /* set bit 0: power up */
     else
 	PutByte(XIRCREG4_GPR1, 1 | 4);	 /* set bit 0: power up, bit 2: AIC */
-    Wait(HZ/50);		     /* wait 20 msec */
+    msleep(20);			     /* wait 20 msec */
 }
 
 static void
@@ -1726,9 +1721,9 @@
 
     hardreset(dev);
     PutByte(XIRCREG_CR, SoftReset); /* set */
-    Wait(HZ/50);		     /* wait 20 msec */
+    msleep(20);			     /* wait 20 msec */
     PutByte(XIRCREG_CR, 0);	     /* clear */
-    Wait(HZ/25);		     /* wait 40 msec */
+    msleep(40);			     /* wait 40 msec */
     if (local->mohawk) {
 	SelectPage(4);
 	/* set pin GP1 and GP2 to output  (0x0c)
@@ -1739,7 +1734,7 @@
     }
 
     /* give the circuits some time to power up */
-    Wait(HZ/2);		/* about 500ms */
+    msleep(500);			/* about 500ms */
 
     local->last_ptr_value = 0;
     local->silicon = local->mohawk ? (GetByte(XIRCREG4_BOV) & 0x70) >> 4
@@ -1758,7 +1753,7 @@
 	SelectPage(0x42);
 	PutByte(XIRCREG42_SWC1, 0x80);
     }
-    Wait(HZ/25);		     /* wait 40 msec to let it complete */
+    msleep(40);			     /* wait 40 msec to let it complete */
 
   #ifdef PCMCIA_DEBUG
     if (pc_debug) {
@@ -1817,7 +1812,7 @@
 	    printk(KERN_INFO "%s: MII selected\n", dev->name);
 	    SelectPage(2);
 	    PutByte(XIRCREG2_MSR, GetByte(XIRCREG2_MSR) | 0x08);
-	    Wait(HZ/50);
+	    msleep(20);
 	} else {
 	    printk(KERN_INFO "%s: MII detected; using 10mbs\n",
 		   dev->name);
@@ -1826,7 +1821,7 @@
 		PutByte(XIRCREG42_SWC1, 0xC0);
 	    else  /* enable 10BaseT */
 		PutByte(XIRCREG42_SWC1, 0x80);
-	    Wait(HZ/25);	/* wait 40 msec to let it complete */
+	    msleep(40);			/* wait 40 msec to let it complete */
 	}
 	if (full_duplex)
 	    PutByte(XIRCREG1_ECR, GetByte(XIRCREG1_ECR | FullDuplex));
@@ -1919,7 +1914,7 @@
 	 * Fixme: Better to use a timer here!
 	 */
 	for (i=0; i < 35; i++) {
-	    Wait(HZ/10);	 /* wait 100 msec */
+	    msleep(100);	 /* wait 100 msec */
 	    status = mii_rd(ioaddr,  0, 1);
 	    if ((status & 0x0020) && (status & 0x0004))
 		break;
diff -Nru a/drivers/net/pcnet32.c b/drivers/net/pcnet32.c
--- a/drivers/net/pcnet32.c	2005-03-11 12:51:42 -08:00
+++ b/drivers/net/pcnet32.c	2005-03-11 12:51:42 -08:00
@@ -1429,25 +1429,36 @@
 	val |= 0x10;
     lp->a.write_csr (ioaddr, 124, val);
 
-    /* 24 Jun 2004 according AMD, in order to change the PHY,
-     * DANAS (or DISPM for 79C976) must be set; then select the speed,
-     * duplex, and/or enable auto negotiation, and clear DANAS */
-    if (lp->mii && !(lp->options & PCNET32_PORT_ASEL)) {
-	lp->a.write_bcr(ioaddr, 32, lp->a.read_bcr(ioaddr, 32) | 0x0080);
-	/* disable Auto Negotiation, set 10Mpbs, HD */
-	val = lp->a.read_bcr(ioaddr, 32) & ~0xb8;
-	if (lp->options & PCNET32_PORT_FD)
-	    val |= 0x10;
-	if (lp->options & PCNET32_PORT_100)
-	    val |= 0x08;
-	lp->a.write_bcr (ioaddr, 32, val);
+    /* Allied Telesyn AT 2700/2701 FX looses the link, so skip that */
+    if (lp->pci_dev->subsystem_vendor == PCI_VENDOR_ID_AT &&
+        (lp->pci_dev->subsystem_device == PCI_SUBDEVICE_ID_AT_2700FX ||
+	 lp->pci_dev->subsystem_device == PCI_SUBDEVICE_ID_AT_2701FX)) {
+	printk(KERN_DEBUG "%s: Skipping PHY selection.\n", dev->name);
     } else {
-	if (lp->options & PCNET32_PORT_ASEL) {
-	    lp->a.write_bcr(ioaddr, 32, lp->a.read_bcr(ioaddr, 32) | 0x0080);
-	    /* enable auto negotiate, setup, disable fd */
-	    val = lp->a.read_bcr(ioaddr, 32) & ~0x98;
-	    val |= 0x20;
-	    lp->a.write_bcr(ioaddr, 32, val);
+	/*
+	 * 24 Jun 2004 according AMD, in order to change the PHY,
+	 * DANAS (or DISPM for 79C976) must be set; then select the speed,
+	 * duplex, and/or enable auto negotiation, and clear DANAS
+	 */
+	if (lp->mii && !(lp->options & PCNET32_PORT_ASEL)) {
+	    lp->a.write_bcr(ioaddr, 32,
+				lp->a.read_bcr(ioaddr, 32) | 0x0080);
+	    /* disable Auto Negotiation, set 10Mpbs, HD */
+	    val = lp->a.read_bcr(ioaddr, 32) & ~0xb8;
+	    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) {
+		lp->a.write_bcr(ioaddr, 32,
+			lp->a.read_bcr(ioaddr, 32) | 0x0080);
+		/* enable auto negotiate, setup, disable fd */
+		val = lp->a.read_bcr(ioaddr, 32) & ~0x98;
+		val |= 0x20;
+		lp->a.write_bcr(ioaddr, 32, val);
+	    }
 	}
     }
 
diff -Nru a/drivers/net/ppp_deflate.c b/drivers/net/ppp_deflate.c
--- a/drivers/net/ppp_deflate.c	2005-03-11 12:51:51 -08:00
+++ b/drivers/net/ppp_deflate.c	2005-03-11 12:51:51 -08:00
@@ -600,7 +600,7 @@
 /*
  * Procedures exported to if_ppp.c.
  */
-struct compressor ppp_deflate = {
+static struct compressor ppp_deflate = {
 	.compress_proto =	CI_DEFLATE,
 	.comp_alloc =		z_comp_alloc,
 	.comp_free =		z_comp_free,
@@ -618,7 +618,7 @@
 	.owner =		THIS_MODULE
 };
 
-struct compressor ppp_deflate_draft = {
+static struct compressor ppp_deflate_draft = {
 	.compress_proto =	CI_DEFLATE_DRAFT,
 	.comp_alloc =		z_comp_alloc,
 	.comp_free =		z_comp_free,
diff -Nru a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c
--- a/drivers/net/ppp_generic.c	2005-03-11 12:51:51 -08:00
+++ b/drivers/net/ppp_generic.c	2005-03-11 12:51:51 -08:00
@@ -2741,8 +2741,6 @@
 EXPORT_SYMBOL(ppp_output_wakeup);
 EXPORT_SYMBOL(ppp_register_compressor);
 EXPORT_SYMBOL(ppp_unregister_compressor);
-EXPORT_SYMBOL(all_ppp_units); /* for debugging */
-EXPORT_SYMBOL(all_channels); /* for debugging */
 MODULE_LICENSE("GPL");
 MODULE_ALIAS_CHARDEV_MAJOR(PPP_MAJOR);
 MODULE_ALIAS("/dev/ppp");
diff -Nru a/drivers/net/pppoe.c b/drivers/net/pppoe.c
--- a/drivers/net/pppoe.c	2005-03-11 12:51:47 -08:00
+++ b/drivers/net/pppoe.c	2005-03-11 12:51:47 -08:00
@@ -120,17 +120,17 @@
 }
 
 /* zeroed because its in .bss */
-static struct pppox_opt *item_hash_table[PPPOE_HASH_SIZE];
+static struct pppox_sock *item_hash_table[PPPOE_HASH_SIZE];
 
 /**********************************************************************
  *
  *  Set/get/delete/rehash items  (internal versions)
  *
  **********************************************************************/
-static struct pppox_opt *__get_item(unsigned long sid, unsigned char *addr)
+static struct pppox_sock *__get_item(unsigned long sid, unsigned char *addr)
 {
 	int hash = hash_item(sid, addr);
-	struct pppox_opt *ret;
+	struct pppox_sock *ret;
 
 	ret = item_hash_table[hash];
 
@@ -140,10 +140,10 @@
 	return ret;
 }
 
-static int __set_item(struct pppox_opt *po)
+static int __set_item(struct pppox_sock *po)
 {
 	int hash = hash_item(po->pppoe_pa.sid, po->pppoe_pa.remote);
-	struct pppox_opt *ret;
+	struct pppox_sock *ret;
 
 	ret = item_hash_table[hash];
 	while (ret) {
@@ -161,10 +161,10 @@
 	return 0;
 }
 
-static struct pppox_opt *__delete_item(unsigned long sid, char *addr)
+static struct pppox_sock *__delete_item(unsigned long sid, char *addr)
 {
 	int hash = hash_item(sid, addr);
-	struct pppox_opt *ret, **src;
+	struct pppox_sock *ret, **src;
 
 	ret = item_hash_table[hash];
 	src = &item_hash_table[hash];
@@ -187,26 +187,26 @@
  *  Set/get/delete/rehash items
  *
  **********************************************************************/
-static inline struct pppox_opt *get_item(unsigned long sid,
+static inline struct pppox_sock *get_item(unsigned long sid,
 					 unsigned char *addr)
 {
-	struct pppox_opt *po;
+	struct pppox_sock *po;
 
 	read_lock_bh(&pppoe_hash_lock);
 	po = __get_item(sid, addr);
 	if (po)
-		sock_hold(po->sk);
+		sock_hold(sk_pppox(po));
 	read_unlock_bh(&pppoe_hash_lock);
 
 	return po;
 }
 
-static inline struct pppox_opt *get_item_by_addr(struct sockaddr_pppox *sp)
+static inline struct pppox_sock *get_item_by_addr(struct sockaddr_pppox *sp)
 {
 	return get_item(sp->sa_addr.pppoe.sid, sp->sa_addr.pppoe.remote);
 }
 
-static inline int set_item(struct pppox_opt *po)
+static inline int set_item(struct pppox_sock *po)
 {
 	int i;
 
@@ -220,9 +220,9 @@
 	return i;
 }
 
-static inline struct pppox_opt *delete_item(unsigned long sid, char *addr)
+static inline struct pppox_sock *delete_item(unsigned long sid, char *addr)
 {
-	struct pppox_opt *ret;
+	struct pppox_sock *ret;
 
 	write_lock_bh(&pppoe_hash_lock);
 	ret = __delete_item(sid, addr);
@@ -248,11 +248,11 @@
 
 	read_lock_bh(&pppoe_hash_lock);
 	for (hash = 0; hash < PPPOE_HASH_SIZE; hash++) {
-		struct pppox_opt *po = item_hash_table[hash];
+		struct pppox_sock *po = item_hash_table[hash];
 
 		while (po != NULL) {
 			if (po->pppoe_dev == dev) {
-				struct sock *sk = po->sk;
+				struct sock *sk = sk_pppox(po);
 
 				sock_hold(sk);
 				po->pppoe_dev = NULL;
@@ -331,14 +331,16 @@
  ***********************************************************************/
 static int pppoe_rcv_core(struct sock *sk, struct sk_buff *skb)
 {
-	struct pppox_opt *po = pppox_sk(sk);
-	struct pppox_opt *relay_po = NULL;
+	struct pppox_sock *po = pppox_sk(sk);
+	struct pppox_sock *relay_po = NULL;
 
 	if (sk->sk_state & PPPOX_BOUND) {
 		struct pppoe_hdr *ph = (struct pppoe_hdr *) skb->nh.raw;
 		int len = ntohs(ph->length);
 		skb_pull(skb, sizeof(struct pppoe_hdr));
-		skb_trim(skb, len);
+		skb_postpull_rcsum(skb, ph, sizeof(*ph));
+		if (pskb_trim_rcsum(skb, len))
+			goto abort_kfree;
 
 		ppp_input(&po->chan, skb);
 	} else if (sk->sk_state & PPPOX_RELAY) {
@@ -347,11 +349,11 @@
 		if (relay_po == NULL)
 			goto abort_kfree;
 
-		if ((relay_po->sk->sk_state & PPPOX_CONNECTED) == 0)
+		if ((sk_pppox(relay_po)->sk_state & PPPOX_CONNECTED) == 0)
 			goto abort_put;
 
 		skb_pull(skb, sizeof(struct pppoe_hdr));
-		if (!__pppoe_xmit( relay_po->sk, skb))
+		if (!__pppoe_xmit(sk_pppox(relay_po), skb))
 			goto abort_put;
 	} else {
 		if (sock_queue_rcv_skb(sk, skb))
@@ -361,7 +363,7 @@
 	return NET_RX_SUCCESS;
 
 abort_put:
-	sock_put(relay_po->sk);
+	sock_put(sk_pppox(relay_po));
 
 abort_kfree:
 	kfree_skb(skb);
@@ -379,7 +381,7 @@
 
 {
 	struct pppoe_hdr *ph;
-	struct pppox_opt *po;
+	struct pppox_sock *po;
 	struct sock *sk;
 	int ret;
 
@@ -395,7 +397,7 @@
 	if (!po) 
 		goto drop;
 
-	sk = po->sk;
+	sk = sk_pppox(po);
 	bh_lock_sock(sk);
 
 	/* Socket state is unknown, must put skb into backlog. */
@@ -428,7 +430,7 @@
 
 {
 	struct pppoe_hdr *ph;
-	struct pppox_opt *po;
+	struct pppox_sock *po;
 
 	if (!pskb_may_pull(skb, sizeof(struct pppoe_hdr)))
 		goto abort;
@@ -442,7 +444,7 @@
 
 	po = get_item((unsigned long) ph->sid, eth_hdr(skb)->h_source);
 	if (po) {
-		struct sock *sk = po->sk;
+		struct sock *sk = sk_pppox(po);
 
 		bh_lock_sock(sk);
 
@@ -480,20 +482,6 @@
 
 /***********************************************************************
  *
- * Really kill the socket. (Called from pppox_sk_free if refcnt == 0.)
- *
- **********************************************************************/
-static void pppoe_sk_free(struct sock *sk)
-{
-	struct pppox_opt *po = pppox_sk(sk);
-
-	if (po)
-		kfree(po);
-}
-
-
-/***********************************************************************
- *
  * Initialize a new struct sock.
  *
  **********************************************************************/
@@ -501,9 +489,8 @@
 {
 	int error = -ENOMEM;
 	struct sock *sk;
-	struct pppox_opt *po;
 
-	sk = sk_alloc(PF_PPPOX, GFP_KERNEL, 1, NULL);
+	sk = sk_alloc(PF_PPPOX, GFP_KERNEL, sizeof(struct pppox_sock), NULL);
 	if (!sk)
 		goto out;
 
@@ -517,23 +504,15 @@
 	sk->sk_type	   = SOCK_STREAM;
 	sk->sk_family	   = PF_PPPOX;
 	sk->sk_protocol	   = PX_PROTO_OE;
-	sk->sk_destruct	   = pppoe_sk_free;
 
-	po = sk->sk_protinfo = kmalloc(sizeof(*po), GFP_KERNEL);
-	if (!po)
-		goto frees;
-	memset(po, 0, sizeof(*po));
-	po->sk = sk;
 	error = 0;
 out:	return error;
-frees:	sk_free(sk);
-	goto out;
 }
 
 static int pppoe_release(struct socket *sock)
 {
 	struct sock *sk = sock->sk;
-	struct pppox_opt *po;
+	struct pppox_sock *po;
 	int error = 0;
 
 	if (!sk)
@@ -573,7 +552,7 @@
 	struct sock *sk = sock->sk;
 	struct net_device *dev = NULL;
 	struct sockaddr_pppox *sp = (struct sockaddr_pppox *) uservaddr;
-	struct pppox_opt *po = pppox_sk(sk);
+	struct pppox_sock *po = pppox_sk(sk);
 	int error;
 
 	lock_sock(sk);
@@ -602,8 +581,8 @@
 		if(po->pppoe_dev)
 			dev_put(po->pppoe_dev);
 
-		memset(po, 0, sizeof(struct pppox_opt));
-		po->sk = sk;
+		memset(sk_pppox(po) + 1, 0,
+		       sizeof(struct pppox_sock) - sizeof(struct sock));
 
 		sk->sk_state = PPPOX_NONE;
 	}
@@ -679,7 +658,7 @@
 		unsigned long arg)
 {
 	struct sock *sk = sock->sk;
-	struct pppox_opt *po = pppox_sk(sk);
+	struct pppox_sock *po = pppox_sk(sk);
 	int val = 0;
 	int err = 0;
 
@@ -725,7 +704,7 @@
 
 	case PPPOEIOCSFWD:
 	{
-		struct pppox_opt *relay_po;
+		struct pppox_sock *relay_po;
 
 		err = -EBUSY;
 		if (sk->sk_state & (PPPOX_BOUND | PPPOX_ZOMBIE | PPPOX_DEAD))
@@ -755,7 +734,7 @@
 		if (!relay_po)
 			break;
 
-		sock_put(relay_po->sk);
+		sock_put(sk_pppox(relay_po));
 		sk->sk_state |= PPPOX_RELAY;
 		err = 0;
 		break;
@@ -782,7 +761,7 @@
 {
 	struct sk_buff *skb = NULL;
 	struct sock *sk = sock->sk;
-	struct pppox_opt *po = pppox_sk(sk);
+	struct pppox_sock *po = pppox_sk(sk);
 	int error = 0;
 	struct pppoe_hdr hdr;
 	struct pppoe_hdr *ph;
@@ -857,7 +836,7 @@
  ***********************************************************************/
 static int __pppoe_xmit(struct sock *sk, struct sk_buff *skb)
 {
-	struct pppox_opt *po = pppox_sk(sk);
+	struct pppox_sock *po = pppox_sk(sk);
 	struct net_device *dev = po->pppoe_dev;
 	struct pppoe_hdr hdr;
 	struct pppoe_hdr *ph;
@@ -984,7 +963,7 @@
 #ifdef CONFIG_PROC_FS
 static int pppoe_seq_show(struct seq_file *seq, void *v)
 {
-	struct pppox_opt *po;
+	struct pppox_sock *po;
 	char *dev_name;
 
 	if (v == SEQ_START_TOKEN) {
@@ -1004,9 +983,9 @@
 	return 0;
 }
 
-static __inline__ struct pppox_opt *pppoe_get_idx(loff_t pos)
+static __inline__ struct pppox_sock *pppoe_get_idx(loff_t pos)
 {
-	struct pppox_opt *po = NULL;
+	struct pppox_sock *po = NULL;
 	int i = 0;
 
 	for (; i < PPPOE_HASH_SIZE; i++) {
@@ -1031,7 +1010,7 @@
 
 static void *pppoe_seq_next(struct seq_file *seq, void *v, loff_t *pos)
 {
-	struct pppox_opt *po;
+	struct pppox_sock *po;
 
 	++*pos;
 	if (v == SEQ_START_TOKEN) {
@@ -1059,7 +1038,7 @@
 	read_unlock_bh(&pppoe_hash_lock);
 }
 
-struct seq_operations pppoe_seq_ops = {
+static struct seq_operations pppoe_seq_ops = {
 	.start		= pppoe_seq_start,
 	.next		= pppoe_seq_next,
 	.stop		= pppoe_seq_stop,
diff -Nru a/drivers/net/pppox.c b/drivers/net/pppox.c
--- a/drivers/net/pppox.c	2005-03-11 12:51:51 -08:00
+++ b/drivers/net/pppox.c	2005-03-11 12:51:51 -08:00
@@ -72,7 +72,7 @@
 		       unsigned long arg)
 {
 	struct sock *sk = sock->sk;
-	struct pppox_opt *po = pppox_sk(sk);
+	struct pppox_sock *po = pppox_sk(sk);
 	int rc = 0;
 
 	lock_sock(sk);
diff -Nru a/drivers/net/r8169.c b/drivers/net/r8169.c
--- a/drivers/net/r8169.c	2005-03-11 12:51:46 -08:00
+++ b/drivers/net/r8169.c	2005-03-11 12:51:46 -08:00
@@ -1180,7 +1180,7 @@
 	/* enable device (incl. PCI PM wakeup and hotplug setup) */
 	rc = pci_enable_device(pdev);
 	if (rc) {
-		printk(KERN_ERR PFX "%s: enable failure\n", pdev->slot_name);
+		printk(KERN_ERR PFX "%s: enable failure\n", pci_name(pdev));
 		goto err_out_free_dev;
 	}
 
@@ -1218,7 +1218,7 @@
 	rc = pci_request_regions(pdev, MODULENAME);
 	if (rc) {
 		printk(KERN_ERR PFX "%s: could not request regions.\n",
-		       pdev->slot_name);
+		       pci_name(pdev));
 		goto err_out_mwi;
 	}
 
diff -Nru a/drivers/net/s2io.c b/drivers/net/s2io.c
--- a/drivers/net/s2io.c	2005-03-11 12:51:47 -08:00
+++ b/drivers/net/s2io.c	2005-03-11 12:51:47 -08:00
@@ -36,28 +36,29 @@
  * in PCI Configuration space.
  ************************************************************************/
 
-#include<linux/config.h>
-#include<linux/module.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/stddef.h>
-#include<linux/ioctl.h>
-#include<linux/timex.h>
-#include<linux/sched.h>
-#include<linux/ethtool.h>
-#include<asm/system.h>
-#include<asm/uaccess.h>
-#include<linux/version.h>
-#include<asm/io.h>
-#include<linux/workqueue.h>
+#include <linux/config.h>
+#include <linux/module.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/stddef.h>
+#include <linux/ioctl.h>
+#include <linux/timex.h>
+#include <linux/sched.h>
+#include <linux/ethtool.h>
+#include <linux/version.h>
+#include <linux/workqueue.h>
+
+#include <asm/io.h>
+#include <asm/system.h>
+#include <asm/uaccess.h>
 
 /* local include */
 #include "s2io.h"
@@ -698,8 +699,7 @@
 	val64 = 0;
 	writeq(val64, &bar0->sw_reset);
 	val64 = readq(&bar0->sw_reset);
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	schedule_timeout(HZ / 2);
+	msleep(500);
 
 	/*  Enable Receiving broadcasts */
 	add = &bar0->mac_cfg;
@@ -952,8 +952,7 @@
 				  dev->name);
 			return -1;
 		}
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		schedule_timeout(HZ / 20);
+		msleep(50);
 		time++;
 	}
 
@@ -991,8 +990,7 @@
 			return -1;
 		}
 		time++;
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		schedule_timeout(HZ / 20);
+		msleep(50);
 	}
 
 	/* 
@@ -1352,7 +1350,7 @@
  *
  */
 
-void fix_mac_address(nic_t * sp)
+static void fix_mac_address(nic_t * sp)
 {
 	XENA_dev_config_t __iomem *bar0 = sp->bar0;
 	u64 val64;
@@ -1421,8 +1419,7 @@
 	SPECIAL_REG_WRITE(val64, &bar0->mc_rldram_mrs, UF);
 	val64 = readq(&bar0->mc_rldram_mrs);
 
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	schedule_timeout(HZ / 10);	/* Delay by around 100 ms. */
+	msleep(100);			/* Delay by around 100 ms. */
 
 	/* Enabling ECC Protection. */
 	val64 = readq(&bar0->adapter_control);
@@ -1509,7 +1506,7 @@
  *  Return Value: void 
 */
 
-void free_tx_buffers(struct s2io_nic *nic)
+static void free_tx_buffers(struct s2io_nic *nic)
 {
 	struct net_device *dev = nic->dev;
 	struct sk_buff *skb;
@@ -1600,7 +1597,7 @@
  *  SUCCESS on success or an appropriate -ve value on failure.
  */
 
-int fill_rx_buffers(struct s2io_nic *nic, int ring_no)
+static int fill_rx_buffers(struct s2io_nic *nic, int ring_no)
 {
 	struct net_device *dev = nic->dev;
 	struct sk_buff *skb;
@@ -2425,7 +2422,7 @@
  *   SUCCESS on success and FAILURE on failure.
  */
 
-int wait_for_cmd_complete(nic_t * sp)
+static int wait_for_cmd_complete(nic_t * sp)
 {
 	XENA_dev_config_t __iomem *bar0 = sp->bar0;
 	int ret = FAILURE, cnt = 0;
@@ -2437,8 +2434,7 @@
 			ret = SUCCESS;
 			break;
 		}
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		schedule_timeout(HZ / 20);
+		msleep(50);
 		if (cnt++ > 10)
 			break;
 	}
@@ -2456,7 +2452,7 @@
  *  void.
  */
 
-void s2io_reset(nic_t * sp)
+static void s2io_reset(nic_t * sp)
 {
 	XENA_dev_config_t __iomem *bar0 = sp->bar0;
 	u64 val64;
@@ -2477,15 +2473,13 @@
 	 * As of now I'am just giving a 250ms delay and hoping that the
 	 * PCI write to sw_reset register is done by this time.
 	 */
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	schedule_timeout(HZ / 4);
+	msleep(250);
 
 	/* Restore the PCI state saved during initializarion. */
 	pci_restore_state(sp->pdev);
 	s2io_init_pci(sp);
 
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	schedule_timeout(HZ / 4);
+	msleep(250);
 
 	/* SXE-002: Configure link and activity LED to turn it off */
 	subid = sp->pdev->subsystem_device;
@@ -2510,7 +2504,7 @@
  *  SUCCESS on success and FAILURE on failure.
  */
 
-int s2io_set_swapper(nic_t * sp)
+static int s2io_set_swapper(nic_t * sp)
 {
 	struct net_device *dev = sp->dev;
 	XENA_dev_config_t __iomem *bar0 = sp->bar0;
@@ -2604,7 +2598,7 @@
  *   file on failure.
  */
 
-int s2io_open(struct net_device *dev)
+static int s2io_open(struct net_device *dev)
 {
 	nic_t *sp = dev->priv;
 	int err = 0;
@@ -2656,7 +2650,7 @@
  *  file on failure.
  */
 
-int s2io_close(struct net_device *dev)
+static int s2io_close(struct net_device *dev)
 {
 	nic_t *sp = dev->priv;
 
@@ -2683,7 +2677,7 @@
  *  0 on success & 1 on failure.
  */
 
-int s2io_xmit(struct sk_buff *skb, struct net_device *dev)
+static int s2io_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	nic_t *sp = dev->priv;
 	u16 frg_cnt, frg_len, i, queue, queue_len, put_off, get_off;
@@ -2903,7 +2897,7 @@
  *  pointer to the updated net_device_stats structure.
  */
 
-struct net_device_stats *s2io_get_stats(struct net_device *dev)
+static struct net_device_stats *s2io_get_stats(struct net_device *dev)
 {
 	nic_t *sp = dev->priv;
 	mac_info_t *mac_control;
@@ -3156,7 +3150,7 @@
  * return 0 on success.
  */
 
-int s2io_ethtool_gset(struct net_device *dev, struct ethtool_cmd *info)
+static int s2io_ethtool_gset(struct net_device *dev, struct ethtool_cmd *info)
 {
 	nic_t *sp = dev->priv;
 	info->supported = (SUPPORTED_10000baseT_Full | SUPPORTED_FIBRE);
@@ -3197,7 +3191,7 @@
 	strncpy(info->version, s2io_driver_version,
 		sizeof(s2io_driver_version));
 	strncpy(info->fw_version, "", 32);
-	strncpy(info->bus_info, sp->pdev->slot_name, 32);
+	strncpy(info->bus_info, pci_name(sp->pdev), 32);
 	info->regdump_len = XENA_REG_SPACE;
 	info->eedump_len = XENA_EEPROM_SPACE;
 	info->testinfo_len = S2IO_TEST_LEN;
@@ -3303,11 +3297,10 @@
 		sp->id_timer.data = (unsigned long) sp;
 	}
 	mod_timer(&sp->id_timer, jiffies);
-	set_current_state(TASK_INTERRUPTIBLE);
 	if (data)
-		schedule_timeout(data * HZ);
+		msleep(data * 1000);
 	else
-		schedule_timeout(MAX_SCHEDULE_TIMEOUT);
+		msleep(0xFFFFFFFF);
 	del_timer_sync(&sp->id_timer);
 
 	if (CARDS_WITH_FAULTY_LINK_INDICATORS(subid)) {
@@ -3354,8 +3347,8 @@
  * int, returns 0 on Success
  */
 
-int s2io_ethtool_setpause_data(struct net_device *dev,
-			       struct ethtool_pauseparam *ep)
+static int s2io_ethtool_setpause_data(struct net_device *dev,
+				      struct ethtool_pauseparam *ep)
 {
 	u64 val64;
 	nic_t *sp = dev->priv;
@@ -3410,8 +3403,7 @@
 			ret = 0;
 			break;
 		}
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		schedule_timeout(HZ / 20);
+		msleep(50);
 		exit_cnt++;
 	}
 
@@ -3451,8 +3443,7 @@
 				ret = 0;
 			break;
 		}
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		schedule_timeout(HZ / 20);
+		msleep(50);
 		exit_cnt++;
 	}
 
@@ -3472,8 +3463,8 @@
  *  int  0 on success
  */
 
-int s2io_ethtool_geeprom(struct net_device *dev,
-			 struct ethtool_eeprom *eeprom, u8 * data_buf)
+static int s2io_ethtool_geeprom(struct net_device *dev,
+				struct ethtool_eeprom *eeprom, u8 * data_buf)
 {
 	u32 data, i, valid;
 	nic_t *sp = dev->priv;
@@ -3708,8 +3699,7 @@
 			ret = 0;
 			break;
 		}
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		schedule_timeout(HZ / 10);
+		msleep(100);
 		cnt++;
 	}
 
@@ -3810,8 +3800,7 @@
 			val64 = readq(&bar0->mc_rldram_test_ctrl);
 			if (val64 & MC_RLDRAM_TEST_DONE)
 				break;
-			set_current_state(TASK_UNINTERRUPTIBLE);
-			schedule_timeout(HZ / 5);
+			msleep(200);
 		}
 
 		if (cnt == 5)
@@ -3827,8 +3816,7 @@
 			val64 = readq(&bar0->mc_rldram_test_ctrl);
 			if (val64 & MC_RLDRAM_TEST_DONE)
 				break;
-			set_current_state(TASK_UNINTERRUPTIBLE);
-			schedule_timeout(HZ / 2);
+			msleep(500);
 		}
 
 		if (cnt == 5)
@@ -3973,19 +3961,20 @@
 	tmp_stats[i++] = stat_info->rmac_err_tcp;
 }
 
-int s2io_ethtool_get_regs_len(struct net_device *dev)
+static int s2io_ethtool_get_regs_len(struct net_device *dev)
 {
 	return (XENA_REG_SPACE);
 }
 
 
-u32 s2io_ethtool_get_rx_csum(struct net_device * dev)
+static u32 s2io_ethtool_get_rx_csum(struct net_device * dev)
 {
 	nic_t *sp = dev->priv;
 
 	return (sp->rx_csum);
 }
-int s2io_ethtool_set_rx_csum(struct net_device *dev, u32 data)
+
+static int s2io_ethtool_set_rx_csum(struct net_device *dev, u32 data)
 {
 	nic_t *sp = dev->priv;
 
@@ -3996,17 +3985,19 @@
 
 	return 0;
 }
-int s2io_get_eeprom_len(struct net_device *dev)
+
+static int s2io_get_eeprom_len(struct net_device *dev)
 {
 	return (XENA_EEPROM_SPACE);
 }
 
-int s2io_ethtool_self_test_count(struct net_device *dev)
+static int s2io_ethtool_self_test_count(struct net_device *dev)
 {
 	return (S2IO_TEST_LEN);
 }
-void s2io_ethtool_get_strings(struct net_device *dev,
-			      u32 stringset, u8 * data)
+
+static void s2io_ethtool_get_strings(struct net_device *dev,
+				     u32 stringset, u8 * data)
 {
 	switch (stringset) {
 	case ETH_SS_TEST:
@@ -4017,12 +4008,13 @@
 		       sizeof(ethtool_stats_keys));
 	}
 }
+
 static int s2io_ethtool_get_stats_count(struct net_device *dev)
 {
 	return (S2IO_STAT_LEN);
 }
 
-int s2io_ethtool_op_set_tx_csum(struct net_device *dev, u32 data)
+static int s2io_ethtool_op_set_tx_csum(struct net_device *dev, u32 data)
 {
 	if (data)
 		dev->features |= NETIF_F_IP_CSUM;
@@ -4078,7 +4070,7 @@
  *  function returns OP NOT SUPPORTED value.
  */
 
-int s2io_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+static int s2io_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 {
 	return -EOPNOTSUPP;
 }
@@ -4094,7 +4086,7 @@
  *   file on failure.
  */
 
-int s2io_change_mtu(struct net_device *dev, int new_mtu)
+static int s2io_change_mtu(struct net_device *dev, int new_mtu)
 {
 	nic_t *sp = dev->priv;
 	XENA_dev_config_t __iomem *bar0 = sp->bar0;
@@ -4188,8 +4180,7 @@
 	 * Allow a small delay for the NICs self initiated 
 	 * cleanup to complete.
 	 */
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	schedule_timeout(HZ / 10);
+	msleep(100);
 
 	val64 = readq(&bar0->adapter_status);
 	if (verify_xena_quiescence(val64, nic->device_enabled_once)) {
@@ -4243,10 +4234,8 @@
 	register u64 val64 = 0;
 
 	/* If s2io_set_link task is executing, wait till it completes. */
-	while (test_and_set_bit(0, &(sp->link_state))) {
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		schedule_timeout(HZ / 20);
-	}
+	while (test_and_set_bit(0, &(sp->link_state)))
+		msleep(50);
 	atomic_set(&sp->card_state, CARD_DOWN);
 
 	/* disable Tx and Rx traffic on the NIC */
@@ -4262,8 +4251,7 @@
 			break;
 		}
 
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		schedule_timeout(HZ / 20);
+		msleep(50);
 		cnt++;
 		if (cnt == 10) {
 			DBG_PRINT(ERR_DBG,
@@ -4492,7 +4480,7 @@
  *  void.
  */
 
-void s2io_link(nic_t * sp, int link)
+static void s2io_link(nic_t * sp, int link)
 {
 	struct net_device *dev = (struct net_device *) sp->dev;
 
@@ -4509,23 +4497,6 @@
 }
 
 /**
- *  get_xena_rev_id - to identify revision ID of xena. 
- *  @pdev : PCI Dev structure
- *  Description:
- *  Function to identify the Revision ID of xena.
- *  Return value:
- *  returns the revision ID of the device.
- */
-
-int get_xena_rev_id(struct pci_dev *pdev)
-{
-	u8 id = 0;
-	int ret;
-	ret = pci_read_config_byte(pdev, PCI_REVISION_ID, (u8 *) & id);
-	return id;
-}
-
-/**
  *  s2io_init_pci -Initialization of PCI and PCI-X configuration registers . 
  *  @sp : private member of the device structure, which is a pointer to the 
  *  s2io_nic structure.
@@ -4978,7 +4949,7 @@
  * Description: This function is the cleanup routine for the driver. It unregist * ers the driver.
  */
 
-void s2io_closer(void)
+static void s2io_closer(void)
 {
 	pci_unregister_driver(&s2io_driver);
 	DBG_PRINT(INIT_DBG, "cleanup done\n");
diff -Nru a/drivers/net/s2io.h b/drivers/net/s2io.h
--- a/drivers/net/s2io.h	2005-03-11 12:51:42 -08:00
+++ b/drivers/net/s2io.h	2005-03-11 12:51:42 -08:00
@@ -848,7 +848,7 @@
 static void alarm_intr_handler(struct s2io_nic *sp);
 
 static int s2io_starter(void);
-void s2io_closer(void);
+static void s2io_closer(void);
 static void s2io_tx_watchdog(struct net_device *dev);
 static void s2io_tasklet(unsigned long dev_addr);
 static void s2io_set_multicast(struct net_device *dev);
@@ -858,13 +858,13 @@
 static int rx_osm_handler(nic_t * sp, RxD_t * rxdp, int ring_no,
 			  buffAdd_t * ba);
 #endif
-void s2io_link(nic_t * sp, int link);
-void s2io_reset(nic_t * sp);
+static void s2io_link(nic_t * sp, int link);
+static void s2io_reset(nic_t * sp);
 #ifdef CONFIG_S2IO_NAPI
 static int s2io_poll(struct net_device *dev, int *budget);
 #endif
 static void s2io_init_pci(nic_t * sp);
-int s2io_set_mac_addr(struct net_device *dev, u8 * addr);
+static int s2io_set_mac_addr(struct net_device *dev, u8 * addr);
 static irqreturn_t s2io_isr(int irq, void *dev_id, struct pt_regs *regs);
 static int verify_xena_quiescence(u64 val64, int flag);
 static struct ethtool_ops netdev_ethtool_ops;
diff -Nru a/drivers/net/sb1000.c b/drivers/net/sb1000.c
--- a/drivers/net/sb1000.c	2005-03-11 12:51:41 -08:00
+++ b/drivers/net/sb1000.c	2005-03-11 12:51:41 -08:00
@@ -57,9 +57,9 @@
 #include <asm/uaccess.h>
 
 #ifdef SB1000_DEBUG
-int sb1000_debug = SB1000_DEBUG;
+static int sb1000_debug = SB1000_DEBUG;
 #else
-int sb1000_debug = 1;
+static int sb1000_debug = 1;
 #endif
 
 static const int SB1000_IO_EXTENT = 8;
@@ -116,15 +116,15 @@
 static inline int sb1000_end_get_set_command(const int ioaddr[],
 	const char* name);
 static inline int sb1000_activate(const int ioaddr[], const char* name);
-static inline int sb1000_get_firmware_version(const int ioaddr[],
+static int sb1000_get_firmware_version(const int ioaddr[],
 	const char* name, unsigned char version[], int do_end);
-static inline int sb1000_get_frequency(const int ioaddr[], const char* name,
+static int sb1000_get_frequency(const int ioaddr[], const char* name,
 	int* frequency);
-static inline int sb1000_set_frequency(const int ioaddr[], const char* name,
+static int sb1000_set_frequency(const int ioaddr[], const char* name,
 	int frequency);
-static inline int sb1000_get_PIDs(const int ioaddr[], const char* name,
+static int sb1000_get_PIDs(const int ioaddr[], const char* name,
 	short PID[]);
-static inline int sb1000_set_PIDs(const int ioaddr[], const char* name,
+static int sb1000_set_PIDs(const int ioaddr[], const char* name,
 	const short PID[]);
 
 /* SB1000 commands for frame rx interrupt */
@@ -252,7 +252,7 @@
  * SB1000 hardware routines to be used during open/configuration phases
  */
 
-const int TimeOutJiffies = (875 * HZ) / 100;
+static const int TimeOutJiffies = (875 * HZ) / 100;
 
 static inline void nicedelay(unsigned long usecs)
 {
@@ -363,7 +363,7 @@
 /*
  * SB1000 hardware routines to be used during frame rx interrupt
  */
-const int Sb1000TimeOutJiffies = 7 * HZ;
+static const int Sb1000TimeOutJiffies = 7 * HZ;
 
 /* Card Wait For Ready (to be used during frame rx) */
 static inline int
@@ -552,7 +552,7 @@
 }
 
 /* get SB1000 firmware version */
-static inline int
+static int
 sb1000_get_firmware_version(const int ioaddr[], const char* name,
 	unsigned char version[], int do_end)
 {
@@ -575,7 +575,7 @@
 }
 
 /* get SB1000 frequency */
-static inline int
+static int
 sb1000_get_frequency(const int ioaddr[], const char* name, int* frequency)
 {
 	unsigned char st[7];
@@ -592,7 +592,7 @@
 }
 
 /* set SB1000 frequency */
-static inline int
+static int
 sb1000_set_frequency(const int ioaddr[], const char* name, int frequency)
 {
 	unsigned char st[7];
@@ -622,7 +622,7 @@
 }
 
 /* get SB1000 PIDs */
-static inline int
+static int
 sb1000_get_PIDs(const int ioaddr[], const char* name, short PID[])
 {
 	unsigned char st[7];
@@ -656,7 +656,7 @@
 }
 
 /* set SB1000 PIDs */
-static inline int
+static int
 sb1000_set_PIDs(const int ioaddr[], const char* name, const short PID[])
 {
 	unsigned char st[7];
diff -Nru a/drivers/net/sb1250-mac.c b/drivers/net/sb1250-mac.c
--- a/drivers/net/sb1250-mac.c	2005-03-11 12:51:51 -08:00
+++ b/drivers/net/sb1250-mac.c	2005-03-11 12:51:51 -08:00
@@ -14,47 +14,11 @@
  * 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 driver is designed for the Broadcom SiByte SOC built-in
+ * Ethernet controllers. Written by Mitch Lichtenberg at Broadcom Corp.
  */
-
-/*
-  This driver is designed for the Broadcom SiByte SOC built-in
-  Ethernet controllers.
-  
-  Written by Mitch Lichtenberg at Broadcom Corp.
-*/
-
-
-
-#define CONFIG_SBMAC_COALESCE
-
-/* A few user-configurable values.
-   These may be modified when a driver module is loaded. */
-
-static int debug = 1;			/* 1 normal messages, 0 quiet .. 7 verbose. */
-static int noisy_mii = 1;		/* mii status msgs */
-
-/* Used to pass the media type, etc.
-   Both 'options[]' and 'full_duplex[]' should exist for driver
-   interoperability.
-   The media type is usually passed in 'options[]'.
-*/
-
-#define MAX_UNITS 3		/* More are supported, limit only on options */
-#ifdef MODULE
-static int options[MAX_UNITS] = {-1, -1, -1};
-static int full_duplex[MAX_UNITS] = {-1, -1, -1};
-#endif
-
-#ifdef CONFIG_SBMAC_COALESCE
-static int int_pktcnt = 0;
-static int int_timeout = 0;
-#endif
-
-/* Operational parameters that usually are not changed. */
-
-/* Time in jiffies before concluding the transmitter is hung. */
-#define TX_TIMEOUT  (2*HZ)
-
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
@@ -89,16 +53,56 @@
 #endif
 
 
+/* Operational parameters that usually are not changed. */
+
+#define CONFIG_SBMAC_COALESCE
+
+#define MAX_UNITS 3		/* More are supported, limit only on options */
+
+/* Time in jiffies before concluding the transmitter is hung. */
+#define TX_TIMEOUT  (2*HZ)
+
 
 MODULE_AUTHOR("Mitch Lichtenberg (Broadcom Corp.)");
 MODULE_DESCRIPTION("Broadcom SiByte SOC GB Ethernet driver");
-MODULE_PARM(debug, "i");
-MODULE_PARM(noisy_mii, "i");
-MODULE_PARM(options, "1-" __MODULE_STRING(MAX_UNITS) "i");
-MODULE_PARM(full_duplex, "1-" __MODULE_STRING(MAX_UNITS) "i");
 
-MODULE_PARM(int_pktcnt, "i");
-MODULE_PARM(int_timeout, "i");
+/* A few user-configurable values which may be modified when a driver
+   module is loaded. */
+
+/* 1 normal messages, 0 quiet .. 7 verbose. */
+static int debug = 1;
+module_param(debug, int, S_IRUGO);
+MODULE_PARM_DESC(debug, "Debug messages");
+
+/* mii status msgs */
+static int noisy_mii = 1;
+module_param(noisy_mii, int, S_IRUGO);
+MODULE_PARM_DESC(noisy_mii, "MII status messages");
+
+/* Used to pass the media type, etc.
+   Both 'options[]' and 'full_duplex[]' should exist for driver
+   interoperability.
+   The media type is usually passed in 'options[]'.
+*/
+#ifdef MODULE
+static int options[MAX_UNITS] = {-1, -1, -1};
+module_param_array(options, int, NULL, S_IRUGO);
+MODULE_PARM_DESC(options, "1-" __MODULE_STRING(MAX_UNITS));
+
+static int full_duplex[MAX_UNITS] = {-1, -1, -1};
+module_param_array(full_duplex, int, NULL, S_IRUGO);
+MODULE_PARM_DESC(full_duplex, "1-" __MODULE_STRING(MAX_UNITS));
+#endif
+
+#ifdef CONFIG_SBMAC_COALESCE
+static int int_pktcnt = 0;
+module_param(int_pktcnt, int, S_IRUGO);
+MODULE_PARM_DESC(int_pktcnt, "Packet count");
+
+static int int_timeout = 0;
+module_param(int_timeout, int, S_IRUGO);
+MODULE_PARM_DESC(int_timeout, "Timeout value");
+#endif
 
 #include <asm/sibyte/sb1250.h>
 #include <asm/sibyte/sb1250_defs.h>
@@ -1811,8 +1815,6 @@
 	
 	/* read system identification to determine revision */
 	if (periph_rev >= 2) {
-		printk(KERN_INFO "%s: enabling TCP rcv checksum\n",
-		       sc->sbm_dev->name);
 		sc->rx_hw_checksum = ENABLE;
 	} else {
 		sc->rx_hw_checksum = DISABLE;
@@ -2417,6 +2419,11 @@
 	if (err)
 		goto out_uninit;
 
+	if (periph_rev >= 2) {
+		printk(KERN_INFO "%s: enabling TCP rcv checksum\n",
+			sc->sbm_dev->name);
+	}
+
 	/*
 	 * Display Ethernet address (this is called during the config
 	 * process so we need to finish off the config message that
@@ -2879,12 +2886,12 @@
 		dev->mem_end = 0;
 		if (sbmac_init(dev, idx)) {
 			port = A_MAC_CHANNEL_BASE(idx);
-			SBMAC_WRITECSR(KSEG1ADDR(port+R_MAC_ETHERNET_ADDR),
-					sbmac_orig_hwaddr[idx] );
+			SBMAC_WRITECSR(IOADDR(port+R_MAC_ETHERNET_ADDR),
+				       sbmac_orig_hwaddr[idx]);
 			free_netdev(dev);
 			continue;
 		}
-		dev_sbmac[idx++] = dev;
+		dev_sbmac[idx] = dev;
 	}
 	return 0;
 }
diff -Nru a/drivers/net/sgiseeq.c b/drivers/net/sgiseeq.c
--- a/drivers/net/sgiseeq.c	2005-03-11 12:51:51 -08:00
+++ b/drivers/net/sgiseeq.c	2005-03-11 12:51:51 -08:00
@@ -136,9 +136,10 @@
 	hregs->rx_ctrl = HPC3_ERXCTRL_ACTIVE;
 }
 
-static inline void seeq_load_eaddr(struct net_device *dev,
-				   struct sgiseeq_regs *sregs)
+static inline void __sgiseeq_set_mac_address(struct net_device *dev)
 {
+	struct sgiseeq_private *sp = netdev_priv(dev);
+	struct sgiseeq_regs *sregs = sp->sregs;
 	int i;
 
 	sregs->tstat = SEEQ_TCMD_RB0;
@@ -146,6 +147,20 @@
 		sregs->rw.eth_addr[i] = dev->dev_addr[i];
 }
 
+static int sgiseeq_set_mac_address(struct net_device *dev, void *addr)
+{
+	struct sgiseeq_private *sp = netdev_priv(dev);
+	struct sockaddr *sa = addr;
+
+	memcpy(dev->dev_addr, sa->sa_data, dev->addr_len);
+
+	spin_lock_irq(&sp->tx_lock);
+	__sgiseeq_set_mac_address(dev);
+	spin_unlock_irq(&sp->tx_lock);
+
+	return 0;
+}
+
 #define TCNTINFO_INIT (HPCDMA_EOX | HPCDMA_ETXD)
 #define RCNTCFG_INIT  (HPCDMA_OWN | HPCDMA_EORP | HPCDMA_XIE)
 #define RCNTINFO_INIT (RCNTCFG_INIT | (PKT_BUF_SZ & HPCDMA_BCNT))
@@ -159,13 +174,7 @@
 	sp->rx_new = sp->tx_new = 0;
 	sp->rx_old = sp->tx_old = 0;
 
-	seeq_load_eaddr(dev, sp->sregs);
-
-	/* XXX for now just accept packets directly to us
-	 * XXX and ether-broadcast.  Will do multicast and
-	 * XXX promiscuous mode later. -davem
-	 */
-	sp->mode = SEEQ_RCMD_RBCAST;
+	__sgiseeq_set_mac_address(dev);
 
 	/* Setup tx ring. */
 	for(i = 0; i < SEEQ_TX_BUFFERS; i++) {
@@ -175,7 +184,7 @@
 			buffer = (unsigned long) kmalloc(PKT_BUF_SZ, GFP_KERNEL);
 			if (!buffer)
 				return -ENOMEM;
-			sp->tx_desc[i].buf_vaddr = KSEG1ADDR(buffer);
+			sp->tx_desc[i].buf_vaddr = CKSEG1ADDR(buffer);
 			sp->tx_desc[i].tdma.pbuf = CPHYSADDR(buffer);
 		}
 		sp->tx_desc[i].tdma.cntinfo = TCNTINFO_INIT;
@@ -189,7 +198,7 @@
 			buffer = (unsigned long) kmalloc(PKT_BUF_SZ, GFP_KERNEL);
 			if (!buffer)
 				return -ENOMEM;
-			sp->rx_desc[i].buf_vaddr = KSEG1ADDR(buffer);
+			sp->rx_desc[i].buf_vaddr = CKSEG1ADDR(buffer);
 			sp->rx_desc[i].rdma.pbuf = CPHYSADDR(buffer);
 		}
 		sp->rx_desc[i].rdma.cntinfo = RCNTINFO_INIT;
@@ -331,10 +340,17 @@
 				/* Copy out of kseg1 to avoid silly cache flush. */
 				eth_copy_and_sum(skb, pkt_pointer + 2, len, 0);
 				skb->protocol = eth_type_trans(skb, dev);
-				netif_rx(skb);
-				dev->last_rx = jiffies;
-				sp->stats.rx_packets++;
-				sp->stats.rx_bytes += len;
+
+				/* We don't want to receive our own packets */
+				if (memcmp(eth_hdr(skb)->h_source, dev->dev_addr, ETH_ALEN)) {
+					netif_rx(skb);
+					dev->last_rx = jiffies;
+					sp->stats.rx_packets++;
+					sp->stats.rx_bytes += len;
+				} else {
+					/* Silently drop my own packets */
+					dev_kfree_skb_irq(skb);
+				}
 			} else {
 				printk (KERN_NOTICE "%s: Memory squeeze, deferring packet.\n",
 					dev->name);
@@ -373,7 +389,7 @@
 	 */
 	while ((td->tdma.cntinfo & (HPCDMA_XIU | HPCDMA_ETXD)) ==
 	      (HPCDMA_XIU | HPCDMA_ETXD))
-		td = (struct sgiseeq_tx_desc *)(long) KSEG1ADDR(td->tdma.pnext);
+		td = (struct sgiseeq_tx_desc *)(long) CKSEG1ADDR(td->tdma.pnext);
 	if (td->tdma.cntinfo & HPCDMA_XIU) {
 		hregs->tx_ndptr = CPHYSADDR(td);
 		hregs->tx_ctrl = HPC3_ETXCTRL_ACTIVE;
@@ -583,6 +599,22 @@
 
 static void sgiseeq_set_multicast(struct net_device *dev)
 {
+	struct sgiseeq_private *sp = (struct sgiseeq_private *) dev->priv;
+	unsigned char oldmode = sp->mode;
+
+	if(dev->flags & IFF_PROMISC)
+		sp->mode = SEEQ_RCMD_RANY;
+	else if ((dev->flags & IFF_ALLMULTI) || dev->mc_count)
+		sp->mode = SEEQ_RCMD_RBMCAST;
+	else
+		sp->mode = SEEQ_RCMD_RBCAST;
+
+	/* XXX I know this sucks, but is there a better way to reprogram
+	 * XXX the receiver? At least, this shouldn't happen too often.
+	 */
+
+	if (oldmode != sp->mode)
+		sgiseeq_reset(dev);
 }
 
 static inline void setup_tx_ring(struct sgiseeq_tx_desc *buf, int nbufs)
@@ -651,13 +683,14 @@
 	sp->sregs = (struct sgiseeq_regs *) &hpc3c0->eth_ext[0];
 	sp->hregs = &hpc3c0->ethregs;
 	sp->name = sgiseeqstr;
+	sp->mode = SEEQ_RCMD_RBCAST;
 
 	sp->rx_desc = (struct sgiseeq_rx_desc *)
-	              KSEG1ADDR(ALIGNED(&sp->srings->rxvector[0]));
+	              CKSEG1ADDR(ALIGNED(&sp->srings->rxvector[0]));
 	dma_cache_wback_inv((unsigned long)&sp->srings->rxvector,
 	                    sizeof(sp->srings->rxvector));
 	sp->tx_desc = (struct sgiseeq_tx_desc *)
-	              KSEG1ADDR(ALIGNED(&sp->srings->txvector[0]));
+	              CKSEG1ADDR(ALIGNED(&sp->srings->txvector[0]));
 	dma_cache_wback_inv((unsigned long)&sp->srings->txvector,
 	                    sizeof(sp->srings->txvector));
 
@@ -681,6 +714,7 @@
 	dev->watchdog_timeo	= (200 * HZ) / 1000;
 	dev->get_stats		= sgiseeq_get_stats;
 	dev->set_multicast_list	= sgiseeq_set_multicast;
+	dev->set_mac_address	= sgiseeq_set_mac_address;
 	dev->irq		= irq;
 
 	if (register_netdev(dev)) {
diff -Nru a/drivers/net/shaper.c b/drivers/net/shaper.c
--- a/drivers/net/shaper.c	2005-03-11 12:51:47 -08:00
+++ b/drivers/net/shaper.c	2005-03-11 12:51:47 -08:00
@@ -96,7 +96,7 @@
 }; 
 #define SHAPERCB(skb) ((struct shaper_cb *) ((skb)->cb))
 
-int sh_debug;		/* Debug flag */
+static int sh_debug;		/* Debug flag */
 
 #define SHAPER_BANNER	"CymruNet Traffic Shaper BETA 0.04 for Linux 2.1\n"
 
diff -Nru a/drivers/net/sis900.c b/drivers/net/sis900.c
--- a/drivers/net/sis900.c	2005-03-11 12:51:42 -08:00
+++ b/drivers/net/sis900.c	2005-03-11 12:51:42 -08:00
@@ -1,6 +1,6 @@
 /* sis900.c: A SiS 900/7016 PCI Fast Ethernet driver for Linux.
    Copyright 1999 Silicon Integrated System Corporation 
-   Revision:	1.08.06 Sep. 24 2002
+   Revision:	1.08.08 Jan. 22 2005
    
    Modified from the driver which is originally written by Donald Becker.
    
@@ -16,8 +16,8 @@
    preliminary Rev. 1.0 Nov. 10, 1998
    SiS 7014 Single Chip 100BASE-TX/10BASE-T Physical Layer Solution,
    preliminary Rev. 1.0 Jan. 18, 1998
-   http://www.sis.com.tw/support/databook.htm
 
+   Rev 1.08.08 Jan. 22 2005 Daniele Venzano use netif_msg for debugging messages
    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
@@ -69,12 +69,13 @@
 
 #include <asm/processor.h>      /* Processor type for cache alignment. */
 #include <asm/io.h>
+#include <asm/irq.h>
 #include <asm/uaccess.h>	/* User space memory access functions */
 
 #include "sis900.h"
 
 #define SIS900_MODULE_NAME "sis900"
-#define SIS900_DRV_VERSION "v1.08.07 11/02/2003"
+#define SIS900_DRV_VERSION "v1.08.08 Jan. 22 2005"
 
 static char version[] __devinitdata =
 KERN_INFO "sis900.c: " SIS900_DRV_VERSION "\n";
@@ -82,8 +83,13 @@
 static int max_interrupt_work = 40;
 static int multicast_filter_limit = 128;
 
-#define sis900_debug debug
-static int sis900_debug;
+static int sis900_debug = -1; /* Use SIS900_DEF_MSG as value */
+
+#define SIS900_DEF_MSG \
+	(NETIF_MSG_DRV		| \
+	 NETIF_MSG_LINK		| \
+	 NETIF_MSG_RX_ERR	| \
+	 NETIF_MSG_TX_ERR)
 
 /* Time in jiffies before concluding the transmitter is hung. */
 #define TX_TIMEOUT  (4*HZ)
@@ -160,6 +166,8 @@
 	struct timer_list timer; /* Link status detection timer. */
 	u8 autong_complete; /* 1: auto-negotiate complete  */
 
+	u32 msg_enable;
+
 	unsigned int cur_rx, dirty_rx; /* producer/comsumer pointers for Tx/Rx ring */
 	unsigned int cur_tx, dirty_tx;
 
@@ -174,6 +182,7 @@
 
 	unsigned int tx_full; /* The Tx queue is full. */
 	u8 host_bridge_rev;
+	u8 chipset_rev;
 };
 
 MODULE_AUTHOR("Jim Huang <cmhuang@sis.com.tw>, Ollie Lho <ollie@sis.com.tw>");
@@ -182,11 +191,12 @@
 
 module_param(multicast_filter_limit, int, 0444);
 module_param(max_interrupt_work, int, 0444);
-module_param(debug, int, 0444);
+module_param(sis900_debug, int, 0444);
 MODULE_PARM_DESC(multicast_filter_limit, "SiS 900/7016 maximum number of filtered multicast addresses");
 MODULE_PARM_DESC(max_interrupt_work, "SiS 900/7016 maximum events handled per interrupt");
-MODULE_PARM_DESC(debug, "SiS 900/7016 debug level (2-4)");
+MODULE_PARM_DESC(sis900_debug, "SiS 900/7016 bitmapped debugging message level");
 
+static void sis900_poll(struct net_device *dev);
 static int sis900_open(struct net_device *net_dev);
 static int sis900_mii_probe (struct net_device * net_dev);
 static void sis900_init_rxfilter (struct net_device * net_dev);
@@ -235,8 +245,8 @@
 	/* check to see if we have sane EEPROM */
 	signature = (u16) read_eeprom(ioaddr, EEPROMSignature);    
 	if (signature == 0xffff || signature == 0x0000) {
-		printk (KERN_INFO "%s: Error EERPOM read %x\n", 
-			net_dev->name, signature);
+		printk (KERN_WARNING "%s: Error EERPOM read %x\n", 
+			pci_name(pci_dev), signature);
 		return 0;
 	}
 
@@ -268,7 +278,8 @@
 	if (!isa_bridge)
 		isa_bridge = pci_get_device(PCI_VENDOR_ID_SI, 0x0018, isa_bridge);
 	if (!isa_bridge) {
-		printk("%s: Can not find ISA bridge\n", net_dev->name);
+		printk(KERN_WARNING "%s: Can not find ISA bridge\n",
+		       pci_name(pci_dev));
 		return 0;
 	}
 	pci_read_config_byte(isa_bridge, 0x48, &reg);
@@ -386,8 +397,8 @@
 	void *ring_space;
 	long ioaddr;
 	int i, ret;
-	u8 revision;
 	char *card_name = card_names[pci_id->driver_data];
+	const char *dev_name = pci_name(pci_dev);
 
 /* when built into the kernel, we only print version if device is found */
 #ifndef MODULE
@@ -456,37 +467,49 @@
 	net_dev->tx_timeout = sis900_tx_timeout;
 	net_dev->watchdog_timeo = TX_TIMEOUT;
 	net_dev->ethtool_ops = &sis900_ethtool_ops;
-	
-	ret = register_netdev(net_dev);
-	if (ret)
-		goto err_unmap_rx;
+
+#ifdef CONFIG_NET_POLL_CONTROLLER
+        net_dev->poll_controller = &sis900_poll;
+#endif
+
+	if (sis900_debug > 0)
+		sis_priv->msg_enable = sis900_debug;
+	else
+		sis_priv->msg_enable = SIS900_DEF_MSG;
 		
 	/* Get Mac address according to the chip revision */
-	pci_read_config_byte(pci_dev, PCI_CLASS_REVISION, &revision);
+	pci_read_config_byte(pci_dev, PCI_CLASS_REVISION, &(sis_priv->chipset_rev));
+	if(netif_msg_probe(sis_priv))
+		printk(KERN_DEBUG "%s: detected revision %2.2x, "
+				"trying to get MAC address...\n",
+				dev_name, sis_priv->chipset_rev);
+	
 	ret = 0;
-
-	if (revision == SIS630E_900_REV)
+	if (sis_priv->chipset_rev == SIS630E_900_REV)
 		ret = sis630e_get_mac_addr(pci_dev, net_dev);
-	else if ((revision > 0x81) && (revision <= 0x90) )
+	else if ((sis_priv->chipset_rev > 0x81) && (sis_priv->chipset_rev <= 0x90) )
 		ret = sis635_get_mac_addr(pci_dev, net_dev);
-	else if (revision == SIS96x_900_REV)
+	else if (sis_priv->chipset_rev == SIS96x_900_REV)
 		ret = sis96x_get_mac_addr(pci_dev, net_dev);
 	else
 		ret = sis900_get_mac_addr(pci_dev, net_dev);
 
 	if (ret == 0) {
+		printk(KERN_WARNING "%s: Cannot read MAC address.\n", dev_name);
 		ret = -ENODEV;
-		goto err_out_unregister;
+		goto err_unmap_rx;
 	}
 	
 	/* 630ET : set the mii access mode as software-mode */
-	if (revision == SIS630ET_900_REV)
+	if (sis_priv->chipset_rev == SIS630ET_900_REV)
 		outl(ACCESSMODE | inl(ioaddr + cr), ioaddr + cr);
 
 	/* probe for mii transceiver */
 	if (sis900_mii_probe(net_dev) == 0) {
+		printk(KERN_WARNING "%s: Error probing MII device.\n",
+		       dev_name);
 		ret = -ENODEV;
-		goto err_out_unregister;
+		goto err_unmap_rx;
 	}
 
 	/* save our host bridge revision */
@@ -496,6 +519,10 @@
 		pci_dev_put(dev);
 	}
 
+	ret = register_netdev(net_dev);
+	if (ret)
+		goto err_unmap_rx;
+
 	/* print some information about our NIC */
 	printk(KERN_INFO "%s: %s at %#lx, IRQ %d, ", net_dev->name,
 	       card_name, ioaddr, net_dev->irq);
@@ -505,8 +532,6 @@
 
 	return 0;
 
- err_out_unregister:
- 	unregister_netdev(net_dev);
  err_unmap_rx:
 	pci_free_consistent(pci_dev, RX_TOTAL_SIZE, sis_priv->rx_ring,
 		sis_priv->rx_ring_dma);
@@ -533,10 +558,10 @@
 static int __init sis900_mii_probe(struct net_device * net_dev)
 {
 	struct sis900_private * sis_priv = net_dev->priv;
+	const char *dev_name = pci_name(sis_priv->pci_dev);
 	u16 poll_bit = MII_STAT_LINK, status = 0;
 	unsigned long timeout = jiffies + 5 * HZ;
 	int phy_addr;
-	u8 revision;
 
 	sis_priv->mii = NULL;
 
@@ -550,12 +575,16 @@
 		for(i = 0; i < 2; i++)
 			mii_status = mdio_read(net_dev, phy_addr, MII_STATUS);
 
-		if (mii_status == 0xffff || mii_status == 0x0000)
-			/* the mii is not accessible, try next one */
+		if (mii_status == 0xffff || mii_status == 0x0000) {
+			if (netif_msg_probe(sis_priv))
+				printk(KERN_DEBUG "%s: MII at address %d"
+						" not accessible\n",
+						dev_name, phy_addr);
 			continue;
+		}
 		
 		if ((mii_phy = kmalloc(sizeof(struct mii_phy), GFP_KERNEL)) == NULL) {
-			printk(KERN_INFO "Cannot allocate mem for struct mii_phy\n");
+			printk(KERN_WARNING "Cannot allocate mem for struct mii_phy\n");
 			mii_phy = sis_priv->first_mii;
 			while (mii_phy) {
 				struct mii_phy *phy;
@@ -581,22 +610,23 @@
 				if (mii_chip_table[i].phy_types == MIX)
 					mii_phy->phy_types =
 					    (mii_status & (MII_STAT_CAN_TX_FDX | MII_STAT_CAN_TX)) ? LAN : HOME;
-				printk(KERN_INFO "%s: %s transceiver found at address %d.\n",
-				       net_dev->name, mii_chip_table[i].name,
-				       phy_addr);
+				printk(KERN_INFO "%s: %s transceiver found "
+							"at address %d.\n",
+							dev_name,
+							mii_chip_table[i].name,
+							phy_addr);
 				break;
 			}
 			
 		if( !mii_chip_table[i].phy_id1 ) {
 			printk(KERN_INFO "%s: Unknown PHY transceiver found at address %d.\n",
-			       net_dev->name, phy_addr);
+			       dev_name, phy_addr);
 			mii_phy->phy_types = UNKNOWN;
 		}
 	}
 	
 	if (sis_priv->mii == NULL) {
-		printk(KERN_INFO "%s: No MII transceivers found!\n",
-			net_dev->name);
+		printk(KERN_INFO "%s: No MII transceivers found!\n", dev_name);
 		return 0;
 	}
 
@@ -621,14 +651,13 @@
 			poll_bit ^= (mdio_read(net_dev, sis_priv->cur_phy, MII_STATUS) & poll_bit);
 			if (time_after_eq(jiffies, timeout)) {
 				printk(KERN_WARNING "%s: reset phy and link down now\n",
-					net_dev->name);
+				       dev_name);
 				return -ETIME;
 			}
 		}
 	}
 
-	pci_read_config_byte(sis_priv->pci_dev, PCI_CLASS_REVISION, &revision);
-	if (revision == SIS630E_900_REV) {
+	if (sis_priv->chipset_rev == SIS630E_900_REV) {
 		/* SiS 630E has some bugs on default value of PHY registers */
 		mdio_write(net_dev, sis_priv->cur_phy, MII_ANADV, 0x05e1);
 		mdio_write(net_dev, sis_priv->cur_phy, MII_CONFIG1, 0x22);
@@ -691,7 +720,7 @@
 		sis_priv->mii = default_phy;
 		sis_priv->cur_phy = default_phy->phy_addr;
 		printk(KERN_INFO "%s: Using transceiver found at address %d as default\n",
-					net_dev->name,sis_priv->cur_phy);
+		       pci_name(sis_priv->pci_dev), sis_priv->cur_phy);
 	}
 	
 	status = mdio_read(net_dev, sis_priv->cur_phy, MII_CONTROL);
@@ -930,6 +959,20 @@
 	return status;
 }
 
+#ifdef CONFIG_NET_POLL_CONTROLLER
+/*
+ * Polling 'interrupt' - used by things like netconsole to send skbs
+ * without having to re-enable interrupts. It's not called while
+ * the interrupt routine is executing.
+*/
+static void sis900_poll(struct net_device *dev)
+{
+	disable_irq(dev->irq);
+	sis900_interrupt(dev->irq, dev, NULL);
+	enable_irq(dev->irq);
+}
+#endif
+
 /**
  *	sis900_open - open sis900 device
  *	@net_dev: the net device to open
@@ -943,15 +986,13 @@
 {
 	struct sis900_private *sis_priv = net_dev->priv;
 	long ioaddr = net_dev->base_addr;
-	u8 revision;
 	int ret;
 
 	/* Soft reset the chip. */
 	sis900_reset(net_dev);
 
 	/* Equalizer workaround Rule */
-	pci_read_config_byte(sis_priv->pci_dev, PCI_CLASS_REVISION, &revision);
-	sis630_set_eq(net_dev, revision);
+	sis630_set_eq(net_dev, sis_priv->chipset_rev);
 
 	ret = request_irq(net_dev->irq, &sis900_interrupt, SA_SHIRQ,
 						net_dev->name, net_dev);
@@ -999,6 +1040,7 @@
 static void
 sis900_init_rxfilter (struct net_device * net_dev)
 {
+	struct sis900_private *sis_priv = net_dev->priv;
 	long ioaddr = net_dev->base_addr;
 	u32 rfcrSave;
 	u32 i;
@@ -1016,8 +1058,8 @@
 		outl((i << RFADDR_shift), ioaddr + rfcr);
 		outl(w, ioaddr + rfdr);
 
-		if (sis900_debug > 2) {
-			printk(KERN_INFO "%s: Receive Filter Addrss[%d]=%x\n",
+		if (netif_msg_hw(sis_priv)) {
+			printk(KERN_DEBUG "%s: Receive Filter Addrss[%d]=%x\n",
 			       net_dev->name, i, inl(ioaddr + rfdr));
 		}
 	}
@@ -1054,8 +1096,8 @@
 
 	/* load Transmit Descriptor Register */
 	outl(sis_priv->tx_ring_dma, ioaddr + txdp);
-	if (sis900_debug > 2)
-		printk(KERN_INFO "%s: TX descriptor register loaded with: %8.8x\n",
+	if (netif_msg_hw(sis_priv))
+		printk(KERN_DEBUG "%s: TX descriptor register loaded with: %8.8x\n",
 		       net_dev->name, inl(ioaddr + txdp));
 }
 
@@ -1108,8 +1150,8 @@
 
 	/* load Receive Descriptor Register */
 	outl(sis_priv->rx_ring_dma, ioaddr + rxdp);
-	if (sis900_debug > 2)
-		printk(KERN_INFO "%s: RX descriptor register loaded with: %8.8x\n",
+	if (netif_msg_hw(sis_priv))
+		printk(KERN_DEBUG "%s: RX descriptor register loaded with: %8.8x\n",
 		       net_dev->name, inl(ioaddr + rxdp));
 }
 
@@ -1219,7 +1261,6 @@
 	struct mii_phy *mii_phy = sis_priv->mii;
 	static int next_tick = 5*HZ;
 	u16 status;
-	u8 revision;
 
 	if (!sis_priv->autong_complete){
 		int speed, duplex = 0;
@@ -1227,9 +1268,7 @@
 		sis900_read_mode(net_dev, &speed, &duplex);
 		if (duplex){
 			sis900_set_mode(net_dev->base_addr, speed, duplex);
-			pci_read_config_byte(sis_priv->pci_dev,
-						PCI_CLASS_REVISION, &revision);
-			sis630_set_eq(net_dev, revision);
+			sis630_set_eq(net_dev, sis_priv->chipset_rev);
 			netif_start_queue(net_dev);
 		}
 
@@ -1256,16 +1295,15 @@
 	/* Link ON -> OFF */
                 if (!(status & MII_STAT_LINK)){
                 	netif_carrier_off(net_dev);
-                	printk(KERN_INFO "%s: Media Link Off\n", net_dev->name);
+			if(netif_msg_link(sis_priv))
+                		printk(KERN_INFO "%s: Media Link Off\n", net_dev->name);
 
                 	/* Change mode issue */
                 	if ((mii_phy->phy_id0 == 0x001D) && 
 			    ((mii_phy->phy_id1 & 0xFFF0) == 0x8000))
                			sis900_reset_phy(net_dev,  sis_priv->cur_phy);
   
-                	pci_read_config_byte(sis_priv->pci_dev,
-					PCI_CLASS_REVISION, &revision);
-			sis630_set_eq(net_dev, revision);
+			sis630_set_eq(net_dev, sis_priv->chipset_rev);
   
                 	goto LookForLink;
                 }
@@ -1371,7 +1409,8 @@
 		status = mdio_read(net_dev, phy_addr, MII_STATUS);
 
 	if (!(status & MII_STAT_LINK)){
-		printk(KERN_INFO "%s: Media Link Off\n", net_dev->name);
+		if(netif_msg_link(sis_priv))
+			printk(KERN_INFO "%s: Media Link Off\n", net_dev->name);
 		sis_priv->autong_complete = 1;
 		netif_carrier_off(net_dev);
 		return;
@@ -1433,7 +1472,8 @@
 			*speed = HW_SPEED_100_MBPS;
 	}
 
-	printk(KERN_INFO "%s: Media Link On %s %s-duplex \n",
+	if(netif_msg_link(sis_priv))
+		printk(KERN_INFO "%s: Media Link On %s %s-duplex \n",
 	       				net_dev->name,
 	       				*speed == HW_SPEED_100_MBPS ?
 	       					"100mbps" : "10mbps",
@@ -1456,8 +1496,9 @@
 	unsigned long flags;
 	int i;
 
-	printk(KERN_INFO "%s: Transmit timeout, status %8.8x %8.8x \n",
-	       net_dev->name, inl(ioaddr + cr), inl(ioaddr + isr));
+	if(netif_msg_tx_err(sis_priv))
+		printk(KERN_INFO "%s: Transmit timeout, status %8.8x %8.8x \n",
+	       		net_dev->name, inl(ioaddr + cr), inl(ioaddr + isr));
 
 	/* Disable interrupts by clearing the interrupt mask. */
 	outl(0x0000, ioaddr + imr);
@@ -1558,8 +1599,8 @@
 
 	net_dev->trans_start = jiffies;
 
-	if (sis900_debug > 3)
-		printk(KERN_INFO "%s: Queued Tx packet at %p size %d "
+	if (netif_msg_tx_queued(sis_priv))
+		printk(KERN_DEBUG "%s: Queued Tx packet at %p size %d "
 		       "to slot %d.\n",
 		       net_dev->name, skb->data, (int)skb->len, entry);
 
@@ -1606,20 +1647,22 @@
 
 		/* something strange happened !!! */
 		if (status & HIBERR) {
-			printk(KERN_INFO "%s: Abnormal interrupt,"
-			       "status %#8.8x.\n", net_dev->name, status);
+			if(netif_msg_intr(sis_priv))
+				printk(KERN_INFO "%s: Abnormal interrupt,"
+					"status %#8.8x.\n", net_dev->name, status);
 			break;
 		}
 		if (--boguscnt < 0) {
-			printk(KERN_INFO "%s: Too much work at interrupt, "
-			       "interrupt status = %#8.8x.\n",
-			       net_dev->name, status);
+			if(netif_msg_intr(sis_priv))
+				printk(KERN_INFO "%s: Too much work at interrupt, "
+					"interrupt status = %#8.8x.\n",
+					net_dev->name, status);
 			break;
 		}
 	} while (1);
 
-	if (sis900_debug > 3)
-		printk(KERN_INFO "%s: exiting interrupt, "
+	if(netif_msg_intr(sis_priv))
+		printk(KERN_DEBUG "%s: exiting interrupt, "
 		       "interrupt status = 0x%#8.8x.\n",
 		       net_dev->name, inl(ioaddr + isr));
 	
@@ -1644,8 +1687,8 @@
 	unsigned int entry = sis_priv->cur_rx % NUM_RX_DESC;
 	u32 rx_status = sis_priv->rx_ring[entry].cmdsts;
 
-	if (sis900_debug > 3)
-		printk(KERN_INFO "sis900_rx, cur_rx:%4.4d, dirty_rx:%4.4d "
+	if (netif_msg_rx_status(sis_priv))
+		printk(KERN_DEBUG "sis900_rx, cur_rx:%4.4d, dirty_rx:%4.4d "
 		       "status:0x%8.8x\n",
 		       sis_priv->cur_rx, sis_priv->dirty_rx, rx_status);
 
@@ -1656,8 +1699,8 @@
 
 		if (rx_status & (ABORT|OVERRUN|TOOLONG|RUNT|RXISERR|CRCERR|FAERR)) {
 			/* corrupted packet received */
-			if (sis900_debug > 3)
-				printk(KERN_INFO "%s: Corrupted packet "
+			if (netif_msg_rx_err(sis_priv))
+				printk(KERN_DEBUG "%s: Corrupted packet "
 				       "received, buffer status = 0x%8.8x.\n",
 				       net_dev->name, rx_status);
 			sis_priv->stats.rx_errors++;
@@ -1678,9 +1721,10 @@
 			   some unknow bugs, it is possible that
 			   we are working on NULL sk_buff :-( */
 			if (sis_priv->rx_skbuff[entry] == NULL) {
-				printk(KERN_INFO "%s: NULL pointer " 
-				       "encountered in Rx ring, skipping\n",
-				       net_dev->name);
+				if (netif_msg_rx_err(sis_priv))
+					printk(KERN_INFO "%s: NULL pointer " 
+						"encountered in Rx ring, skipping\n",
+						net_dev->name);
 				break;
 			}
 
@@ -1707,9 +1751,10 @@
 				 * "hole" on the buffer ring, it is not clear
 				 * how the hardware will react to this kind
 				 * of degenerated buffer */
-				printk(KERN_INFO "%s: Memory squeeze,"
-				       "deferring packet.\n",
-				       net_dev->name);
+				if (netif_msg_rx_status(sis_priv))
+					printk(KERN_INFO "%s: Memory squeeze,"
+						"deferring packet.\n",
+						net_dev->name);
 				sis_priv->rx_skbuff[entry] = NULL;
 				/* reset buffer descriptor state */
 				sis_priv->rx_ring[entry].cmdsts = 0;
@@ -1743,9 +1788,10 @@
 				 * "hole" on the buffer ring, it is not clear
 				 * how the hardware will react to this kind
 				 * of degenerated buffer */
-				printk(KERN_INFO "%s: Memory squeeze,"
-				       "deferring packet.\n",
-				       net_dev->name);
+				if (netif_msg_rx_err(sis_priv))
+					printk(KERN_INFO "%s: Memory squeeze,"
+						"deferring packet.\n",
+						net_dev->name);
 				sis_priv->stats.rx_dropped++;
 				break;
 			}
@@ -1794,8 +1840,8 @@
 
 		if (tx_status & (ABORT | UNDERRUN | OWCOLL)) {
 			/* packet unsuccessfully transmitted */
-			if (sis900_debug > 3)
-				printk(KERN_INFO "%s: Transmit "
+			if (netif_msg_tx_err(sis_priv))
+				printk(KERN_DEBUG "%s: Transmit "
 				       "error, Tx status %8.8x.\n",
 				       net_dev->name, tx_status);
 			sis_priv->stats.tx_errors++;
@@ -1906,8 +1952,22 @@
 	strcpy (info->bus_info, pci_name(sis_priv->pci_dev));
 }
 
+static u32 sis900_get_msglevel(struct net_device *net_dev)
+{
+	struct sis900_private *sis_priv = net_dev->priv;
+	return sis_priv->msg_enable;
+}
+  
+static void sis900_set_msglevel(struct net_device *net_dev, u32 value)
+{
+	struct sis900_private *sis_priv = net_dev->priv;
+	sis_priv->msg_enable = value;
+}
+
 static struct ethtool_ops sis900_ethtool_ops = {
-	.get_drvinfo =		sis900_get_drvinfo,
+	.get_drvinfo 	= sis900_get_drvinfo,
+	.get_msglevel	= sis900_get_msglevel,
+	.set_msglevel	= sis900_set_msglevel,
 };
 
 /**
@@ -2048,12 +2108,10 @@
 		case IF_PORT_AUI: /* AUI */
 		case IF_PORT_100BASEFX: /* 100BaseFx */
                 	/* These Modes are not supported (are they?)*/
-			printk(KERN_INFO "Not supported");
 			return -EOPNOTSUPP;
 			break;
             
 		default:
-			printk(KERN_INFO "Invalid");
 			return -EINVAL;
 		}
 	}
@@ -2099,11 +2157,10 @@
 	u16 mc_filter[16] = {0};	/* 256/128 bits multicast hash table */
 	int i, table_entries;
 	u32 rx_mode;
-	u8 revision;
 
 	/* 635 Hash Table entires = 256(2^16) */
-	pci_read_config_byte(sis_priv->pci_dev, PCI_CLASS_REVISION, &revision);
-	if((revision >= SIS635A_900_REV) || (revision == SIS900B_900_REV))
+	if((sis_priv->chipset_rev >= SIS635A_900_REV) ||
+			(sis_priv->chipset_rev == SIS900B_900_REV))
 		table_entries = 16;
 	else
 		table_entries = 8;
@@ -2129,7 +2186,7 @@
 			mclist && i < net_dev->mc_count;
 			i++, mclist = mclist->next) {
 			unsigned int bit_nr =
-				sis900_mcast_bitnr(mclist->dmi_addr, revision);
+				sis900_mcast_bitnr(mclist->dmi_addr, sis_priv->chipset_rev);
 			mc_filter[bit_nr >> 4] |= (1 << (bit_nr & 0xf));
 		}
 	}
@@ -2175,7 +2232,6 @@
 	long ioaddr = net_dev->base_addr;
 	int i = 0;
 	u32 status = TxRCMP | RxRCMP;
-	u8  revision;
 
 	outl(0, ioaddr + ier);
 	outl(0, ioaddr + imr);
@@ -2188,8 +2244,8 @@
 		status ^= (inl(isr + ioaddr) & status);
 	}
 
-	pci_read_config_byte(sis_priv->pci_dev, PCI_CLASS_REVISION, &revision);
-	if( (revision >= SIS635A_900_REV) || (revision == SIS900B_900_REV) )
+	if( (sis_priv->chipset_rev >= SIS635A_900_REV) ||
+			(sis_priv->chipset_rev == SIS900B_900_REV) )
 		outl(PESEL | RND_CNT, ioaddr + cfg);
 	else
 		outl(PESEL, ioaddr + cfg);
@@ -2226,7 +2282,7 @@
 
 #ifdef CONFIG_PM
 
-static int sis900_suspend(struct pci_dev *pci_dev, u32 state)
+static int sis900_suspend(struct pci_dev *pci_dev, pm_message_t state)
 {
 	struct net_device *net_dev = pci_get_drvdata(pci_dev);
 	long ioaddr = net_dev->base_addr;
diff -Nru a/drivers/net/sk98lin/h/skdrv1st.h b/drivers/net/sk98lin/h/skdrv1st.h
--- a/drivers/net/sk98lin/h/skdrv1st.h	2005-03-11 12:51:41 -08:00
+++ b/drivers/net/sk98lin/h/skdrv1st.h	2005-03-11 12:51:41 -08:00
@@ -69,6 +69,7 @@
 #include <linux/bitops.h>
 #include <asm/byteorder.h>
 #include <asm/io.h>
+#include <asm/irq.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
diff -Nru a/drivers/net/sk98lin/skethtool.c b/drivers/net/sk98lin/skethtool.c
--- a/drivers/net/sk98lin/skethtool.c	2005-03-11 12:51:52 -08:00
+++ b/drivers/net/sk98lin/skethtool.c	2005-03-11 12:51:52 -08:00
@@ -257,7 +257,7 @@
 	strlcpy(info->driver, DRIVER_FILE_NAME, sizeof(info->driver));
 	strcpy(info->version, vers);
 	strcpy(info->fw_version, "N/A");
-	strlcpy(info->bus_info, pAC->PciDev->slot_name, ETHTOOL_BUSINFO_LEN);
+	strlcpy(info->bus_info, pci_name(pAC->PciDev), ETHTOOL_BUSINFO_LEN);
 }
 
 /*
diff -Nru a/drivers/net/sk98lin/skge.c b/drivers/net/sk98lin/skge.c
--- a/drivers/net/sk98lin/skge.c	2005-03-11 12:51:41 -08:00
+++ b/drivers/net/sk98lin/skge.c	2005-03-11 12:51:41 -08:00
@@ -3058,7 +3058,7 @@
 		*/
 		* ((SK_U32 *)pMemBuf) = 0;
 		* ((SK_U32 *)pMemBuf + 1) = pdev->bus->number;
-		* ((SK_U32 *)pMemBuf + 2) = ParseDeviceNbrFromSlotName(pdev->slot_name);
+		* ((SK_U32 *)pMemBuf + 2) = ParseDeviceNbrFromSlotName(pci_name(pdev));
 		if(copy_to_user(Ioctl.pData, pMemBuf, Length) ) {
 			Err = -EFAULT;
 			goto fault_diag;
@@ -5151,6 +5151,8 @@
 	{ PCI_VENDOR_ID_LINKSYS, 0x1064, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
 	{ 0, }
 };
+
+MODULE_DEVICE_TABLE(pci, skge_pci_tbl);
 
 static struct pci_driver skge_driver = {
 	.name		= "skge",
diff -Nru a/drivers/net/sk_mca.c b/drivers/net/sk_mca.c
--- a/drivers/net/sk_mca.c	2005-03-11 12:51:52 -08:00
+++ b/drivers/net/sk_mca.c	2005-03-11 12:51:52 -08:00
@@ -127,12 +127,13 @@
 #ifdef DEBUG
 static void dumpmem(struct net_device *dev, u32 start, u32 len)
 {
+	skmca_priv *priv = netdev_priv(dev);
 	int z;
 
 	for (z = 0; z < len; z++) {
 		if ((z & 15) == 0)
 			printk("%04x:", z);
-		printk(" %02x", SKMCA_READB(dev->mem_start + start + z));
+		printk(" %02x", readb(priv->base + start + z));
 		if ((z & 15) == 15)
 			printk("\n");
 	}
@@ -220,21 +221,21 @@
 
 static void ResetBoard(struct net_device *dev)
 {
-	skmca_priv *priv = (skmca_priv *) dev->priv;
+	skmca_priv *priv = netdev_priv(dev);
 
-	SKMCA_WRITEB(CTRL_RESET_ON, priv->ctrladdr);
+	writeb(CTRL_RESET_ON, priv->ctrladdr);
 	udelay(10);
-	SKMCA_WRITEB(CTRL_RESET_OFF, priv->ctrladdr);
+	writeb(CTRL_RESET_OFF, priv->ctrladdr);
 }
 
 /* wait for LANCE interface to become not busy */
 
 static int WaitLANCE(struct net_device *dev)
 {
-	skmca_priv *priv = (skmca_priv *) dev->priv;
+	skmca_priv *priv = netdev_priv(dev);
 	int t = 0;
 
-	while ((SKMCA_READB(priv->ctrladdr) & STAT_IO_BUSY) ==
+	while ((readb(priv->ctrladdr) & STAT_IO_BUSY) ==
 	       STAT_IO_BUSY) {
 		udelay(1);
 		if (++t > 1000) {
@@ -250,7 +251,7 @@
 
 static void SetLANCE(struct net_device *dev, u16 addr, u16 value)
 {
-	skmca_priv *priv = (skmca_priv *) dev->priv;
+	skmca_priv *priv = netdev_priv(dev);
 	unsigned long flags;
 
 	/* disable interrupts */
@@ -263,19 +264,17 @@
 
 	/* transfer register address to RAP */
 
-	SKMCA_WRITEB(CTRL_RESET_OFF | CTRL_RW_WRITE | CTRL_ADR_RAP,
-		     priv->ctrladdr);
-	SKMCA_WRITEW(addr, priv->ioregaddr);
-	SKMCA_WRITEB(IOCMD_GO, priv->cmdaddr);
+	writeb(CTRL_RESET_OFF | CTRL_RW_WRITE | CTRL_ADR_RAP, priv->ctrladdr);
+	writew(addr, priv->ioregaddr);
+	writeb(IOCMD_GO, priv->cmdaddr);
 	udelay(1);
 	WaitLANCE(dev);
 
 	/* transfer data to register */
 
-	SKMCA_WRITEB(CTRL_RESET_OFF | CTRL_RW_WRITE | CTRL_ADR_DATA,
-		     priv->ctrladdr);
-	SKMCA_WRITEW(value, priv->ioregaddr);
-	SKMCA_WRITEB(IOCMD_GO, priv->cmdaddr);
+	writeb(CTRL_RESET_OFF | CTRL_RW_WRITE | CTRL_ADR_DATA, priv->ctrladdr);
+	writew(value, priv->ioregaddr);
+	writeb(IOCMD_GO, priv->cmdaddr);
 	udelay(1);
 	WaitLANCE(dev);
 
@@ -288,7 +287,7 @@
 
 static u16 GetLANCE(struct net_device *dev, u16 addr)
 {
-	skmca_priv *priv = (skmca_priv *) dev->priv;
+	skmca_priv *priv = netdev_priv(dev);
 	unsigned long flags;
 	unsigned int res;
 
@@ -302,21 +301,19 @@
 
 	/* transfer register address to RAP */
 
-	SKMCA_WRITEB(CTRL_RESET_OFF | CTRL_RW_WRITE | CTRL_ADR_RAP,
-		     priv->ctrladdr);
-	SKMCA_WRITEW(addr, priv->ioregaddr);
-	SKMCA_WRITEB(IOCMD_GO, priv->cmdaddr);
+	writeb(CTRL_RESET_OFF | CTRL_RW_WRITE | CTRL_ADR_RAP, priv->ctrladdr);
+	writew(addr, priv->ioregaddr);
+	writeb(IOCMD_GO, priv->cmdaddr);
 	udelay(1);
 	WaitLANCE(dev);
 
 	/* transfer data from register */
 
-	SKMCA_WRITEB(CTRL_RESET_OFF | CTRL_RW_READ | CTRL_ADR_DATA,
-		     priv->ctrladdr);
-	SKMCA_WRITEB(IOCMD_GO, priv->cmdaddr);
+	writeb(CTRL_RESET_OFF | CTRL_RW_READ | CTRL_ADR_DATA, priv->ctrladdr);
+	writeb(IOCMD_GO, priv->cmdaddr);
 	udelay(1);
 	WaitLANCE(dev);
-	res = SKMCA_READW(priv->ioregaddr);
+	res = readw(priv->ioregaddr);
 
 	/* reenable interrupts */
 
@@ -329,6 +326,7 @@
 
 static void InitDscrs(struct net_device *dev)
 {
+	skmca_priv *priv = netdev_priv(dev);
 	u32 bufaddr;
 
 	/* Set up Tx descriptors. The board has only 16K RAM so bits 16..23
@@ -344,11 +342,10 @@
 			descr.Flags = 0;
 			descr.Len = 0xf000;
 			descr.Status = 0;
-			SKMCA_TOIO(dev->mem_start + RAM_TXBASE +
+			memcpy_toio(priv->base + RAM_TXBASE +
 				   (z * sizeof(LANCE_TxDescr)), &descr,
 				   sizeof(LANCE_TxDescr));
-			SKMCA_SETIO(dev->mem_start + bufaddr, 0,
-				    RAM_BUFSIZE);
+			memset_io(priv->base + bufaddr, 0, RAM_BUFSIZE);
 			bufaddr += RAM_BUFSIZE;
 		}
 	}
@@ -364,11 +361,10 @@
 			descr.Flags = RXDSCR_FLAGS_OWN;
 			descr.MaxLen = -RAM_BUFSIZE;
 			descr.Len = 0;
-			SKMCA_TOIO(dev->mem_start + RAM_RXBASE +
+			memcpy_toio(priv->base + RAM_RXBASE +
 				   (z * sizeof(LANCE_RxDescr)), &descr,
 				   sizeof(LANCE_RxDescr));
-			SKMCA_SETIO(dev->mem_start + bufaddr, 0,
-				    RAM_BUFSIZE);
+			memset_io(priv->base + bufaddr, 0, RAM_BUFSIZE);
 			bufaddr += RAM_BUFSIZE;
 		}
 	}
@@ -425,7 +421,7 @@
 
 static void InitLANCE(struct net_device *dev)
 {
-	skmca_priv *priv = (skmca_priv *) dev->priv;
+	skmca_priv *priv = netdev_priv(dev);
 
 	/* build up descriptors. */
 
@@ -478,6 +474,7 @@
 
 static void InitBoard(struct net_device *dev)
 {
+	skmca_priv *priv = netdev_priv(dev);
 	LANCE_InitBlock block;
 
 	/* Lay out the shared RAM - first we create the init block for the LANCE.
@@ -492,7 +489,7 @@
 	block.RdrP = (RAM_RXBASE & 0xffffff) | (LRXCOUNT << 29);
 	block.TdrP = (RAM_TXBASE & 0xffffff) | (LTXCOUNT << 29);
 
-	SKMCA_TOIO(dev->mem_start + RAM_INITBASE, &block, sizeof(block));
+	memcpy_toio(priv->base + RAM_INITBASE, &block, sizeof(block));
 
 	/* initialize LANCE. Implicitly sets up other structures in RAM. */
 
@@ -572,7 +569,7 @@
 
 static u16 irqmiss_handler(struct net_device *dev, u16 oldcsr0)
 {
-	skmca_priv *priv = (skmca_priv *) dev->priv;
+	skmca_priv *priv = netdev_priv(dev);
 
 	/* update statistics */
 
@@ -588,7 +585,7 @@
 
 static u16 irqrx_handler(struct net_device *dev, u16 oldcsr0)
 {
-	skmca_priv *priv = (skmca_priv *) dev->priv;
+	skmca_priv *priv = netdev_priv(dev);
 	LANCE_RxDescr descr;
 	unsigned int descraddr;
 
@@ -597,7 +594,7 @@
 	descraddr = RAM_RXBASE + (priv->nextrx * sizeof(LANCE_RxDescr));
 	while (1) {
 		/* read descriptor */
-		SKMCA_FROMIO(&descr, dev->mem_start + descraddr,
+		memcpy_fromio(&descr, priv->base + descraddr,
 			     sizeof(LANCE_RxDescr));
 
 		/* if we reach a descriptor we do not own, we're done */
@@ -629,8 +626,8 @@
 			if (skb == NULL)
 				priv->stat.rx_dropped++;
 			else {
-				SKMCA_FROMIO(skb_put(skb, descr.Len),
-					     dev->mem_start +
+				memcpy_fromio(skb_put(skb, descr.Len),
+					     priv->base +
 					     descr.LowAddr, descr.Len);
 				skb->dev = dev;
 				skb->protocol = eth_type_trans(skb, dev);
@@ -647,7 +644,7 @@
 		descr.Flags |= RXDSCR_FLAGS_OWN;
 
 		/* update descriptor in shared RAM */
-		SKMCA_TOIO(dev->mem_start + descraddr, &descr,
+		memcpy_toio(priv->base + descraddr, &descr,
 			   sizeof(LANCE_RxDescr));
 
 		/* go to next descriptor */
@@ -669,7 +666,7 @@
 
 static u16 irqtx_handler(struct net_device *dev, u16 oldcsr0)
 {
-	skmca_priv *priv = (skmca_priv *) dev->priv;
+	skmca_priv *priv = netdev_priv(dev);
 	LANCE_TxDescr descr;
 	unsigned int descraddr;
 
@@ -679,7 +676,7 @@
 	    RAM_TXBASE + (priv->nexttxdone * sizeof(LANCE_TxDescr));
 	while (priv->txbusy > 0) {
 		/* read descriptor */
-		SKMCA_FROMIO(&descr, dev->mem_start + descraddr,
+		memcpy_fromio(&descr, priv->base + descraddr,
 			     sizeof(LANCE_TxDescr));
 
 		/* if the LANCE still owns this one, we've worked out all sent packets */
@@ -798,9 +795,7 @@
 
 	if (dev == NULL)
 		return len;
-	if (dev->priv == NULL)
-		return len;
-	priv = (skmca_priv *) dev->priv;
+	priv = netdev_priv(dev);
 
 	/* print info */
 
@@ -825,7 +820,7 @@
 static int skmca_open(struct net_device *dev)
 {
 	int result;
-	skmca_priv *priv = (skmca_priv *) dev->priv;
+	skmca_priv *priv = netdev_priv(dev);
 
 	/* register resources - only necessary for IRQ */
 	result =
@@ -868,7 +863,7 @@
 
 static int skmca_tx(struct sk_buff *skb, struct net_device *dev)
 {
-	skmca_priv *priv = (skmca_priv *) dev->priv;
+	skmca_priv *priv = netdev_priv(dev);
 	LANCE_TxDescr descr;
 	unsigned int address;
 	int tmplen, retval = 0;
@@ -894,8 +889,7 @@
 
 	/* get TX descriptor */
 	address = RAM_TXBASE + (priv->nexttxput * sizeof(LANCE_TxDescr));
-	SKMCA_FROMIO(&descr, dev->mem_start + address,
-		     sizeof(LANCE_TxDescr));
+	memcpy_fromio(&descr, priv->base + address, sizeof(LANCE_TxDescr));
 
 	/* enter packet length as 2s complement - assure minimum length */
 	tmplen = skb->len;
@@ -911,14 +905,14 @@
 		unsigned int destoffs = 0, l = strlen(fill);
 
 		while (destoffs < tmplen) {
-			SKMCA_TOIO(dev->mem_start + descr.LowAddr +
+			memcpy_toio(priv->base + descr.LowAddr +
 				   destoffs, fill, l);
 			destoffs += l;
 		}
 	}
 
 	/* do the real data copying */
-	SKMCA_TOIO(dev->mem_start + descr.LowAddr, skb->data, skb->len);
+	memcpy_toio(priv->base + descr.LowAddr, skb->data, skb->len);
 
 	/* hand descriptor over to LANCE - this is the first and last chunk */
 	descr.Flags =
@@ -945,8 +939,7 @@
 		netif_stop_queue(dev);
 
 	/* write descriptor back to RAM */
-	SKMCA_TOIO(dev->mem_start + address, &descr,
-		   sizeof(LANCE_TxDescr));
+	memcpy_toio(priv->base + address, &descr, sizeof(LANCE_TxDescr));
 
 	/* if no descriptors were active, give the LANCE a hint to read it
 	   immediately */
@@ -967,7 +960,7 @@
 
 static struct net_device_stats *skmca_stats(struct net_device *dev)
 {
-	skmca_priv *priv = (skmca_priv *) dev->priv;
+	skmca_priv *priv = netdev_priv(dev);
 
 	return &(priv->stat);
 }
@@ -977,13 +970,14 @@
 
 static void skmca_set_multicast_list(struct net_device *dev)
 {
+	skmca_priv *priv = netdev_priv(dev);
 	LANCE_InitBlock block;
 
 	/* first stop the LANCE... */
 	StopLANCE(dev);
 
 	/* ...then modify the initialization block... */
-	SKMCA_FROMIO(&block, dev->mem_start + RAM_INITBASE, sizeof(block));
+	memcpy_fromio(&block, priv->base + RAM_INITBASE, sizeof(block));
 	if (dev->flags & IFF_PROMISC)
 		block.Mode |= LANCE_INIT_PROM;
 	else
@@ -1003,7 +997,7 @@
 		}
 	}
 
-	SKMCA_TOIO(dev->mem_start + RAM_INITBASE, &block, sizeof(block));
+	memcpy_toio(priv->base + RAM_INITBASE, &block, sizeof(block));
 
 	/* ...then reinit LANCE with the correct flags */
 	InitLANCE(dev);
@@ -1017,10 +1011,11 @@
 
 static void cleanup_card(struct net_device *dev)
 {
-	skmca_priv *priv = dev->priv;
+	skmca_priv *priv = netdev_priv(dev);
 	DeinitBoard(dev);
 	if (dev->irq != 0)
 		free_irq(dev->irq, dev);
+	iounmap(priv->base);
 	mca_mark_as_unused(priv->slot);
 	mca_set_adapter_procfn(priv->slot, NULL, NULL);
 }
@@ -1104,13 +1099,20 @@
 	printk("%s: SKNet %s adapter found in slot %d\n", dev->name,
 	       junior ? "Junior MC2" : "MC2+", slot + 1);
 
-	/* allocate structure */
-	priv = dev->priv;
+	priv = netdev_priv(dev);
+	priv->base = ioremap(base, 0x4000);
+	if (!priv->base) {
+		mca_set_adapter_procfn(slot, NULL, NULL);
+		mca_mark_as_unused(slot);
+		free_netdev(dev);
+		return ERR_PTR(-ENOMEM);
+	}
+
 	priv->slot = slot;
-	priv->macbase = base + 0x3fc0;
-	priv->ioregaddr = base + 0x3ff0;
-	priv->ctrladdr = base + 0x3ff2;
-	priv->cmdaddr = base + 0x3ff3;
+	priv->macbase = priv->base + 0x3fc0;
+	priv->ioregaddr = priv->base + 0x3ff0;
+	priv->ctrladdr = priv->base + 0x3ff2;
+	priv->cmdaddr = priv->base + 0x3ff3;
 	priv->medium = medium;
 	memset(&priv->stat, 0, sizeof(struct net_device_stats));
 	spin_lock_init(&priv->lock);
@@ -1147,7 +1149,7 @@
 
 	/* copy out MAC address */
 	for (i = 0; i < 6; i++)
-		dev->dev_addr[i] = SKMCA_READB(priv->macbase + (i << 1));
+		dev->dev_addr[i] = readb(priv->macbase + (i << 1));
 
 	/* print config */
 	printk("%s: IRQ %d, memory %#lx-%#lx, "
diff -Nru a/drivers/net/sk_mca.h b/drivers/net/sk_mca.h
--- a/drivers/net/sk_mca.h	2005-03-11 12:51:46 -08:00
+++ b/drivers/net/sk_mca.h	2005-03-11 12:51:46 -08:00
@@ -5,16 +5,6 @@
 
 #ifdef _SK_MCA_DRIVER_
 
-/* version-dependent functions/structures */
-
-#define SKMCA_READB(addr) isa_readb(addr)
-#define SKMCA_READW(addr) isa_readw(addr)
-#define SKMCA_WRITEB(data, addr) isa_writeb(data, addr)
-#define SKMCA_WRITEW(data, addr) isa_writew(data, addr)
-#define SKMCA_TOIO(dest, src, len) isa_memcpy_toio(dest, src, len)
-#define SKMCA_FROMIO(dest, src, len) isa_memcpy_fromio(dest, src, len)
-#define SKMCA_SETIO(dest, val, len) isa_memset_io(dest, val, len)
-
 /* Adapter ID's */
 #define SKNET_MCA_ID 0x6afd
 #define SKNET_JUNIOR_MCA_ID 0x6be9
@@ -29,10 +19,11 @@
 /* private structure */
 typedef struct {
 	unsigned int slot;	/* MCA-Slot-#                       */
-	unsigned int macbase;	/* base address of MAC address PROM */
-	unsigned int ioregaddr;	/* address of I/O-register (Lo)     */
-	unsigned int ctrladdr;	/* address of control/stat register */
-	unsigned int cmdaddr;	/* address of I/O-command register  */
+	void __iomem *base;
+	void __iomem *macbase;	/* base address of MAC address PROM */
+	void __iomem *ioregaddr;/* address of I/O-register (Lo)     */
+	void __iomem *ctrladdr;	/* address of control/stat register */
+	void __iomem *cmdaddr;	/* address of I/O-command register  */
 	int nextrx;		/* index of next RX descriptor to
 				   be read                          */
 	int nexttxput;		/* index of next free TX descriptor */
diff -Nru a/drivers/net/slhc.c b/drivers/net/slhc.c
--- a/drivers/net/slhc.c	2005-03-11 12:51:41 -08:00
+++ b/drivers/net/slhc.c	2005-03-11 12:51:41 -08:00
@@ -693,33 +693,6 @@
 }
 
 
-void slhc_i_status(struct slcompress *comp)
-{
-	if (comp != NULLSLCOMPR) {
-		printk("\t%d Cmp, %d Uncmp, %d Bad, %d Tossed\n",
-			comp->sls_i_compressed,
-			comp->sls_i_uncompressed,
-			comp->sls_i_error,
-			comp->sls_i_tossed);
-	}
-}
-
-
-void slhc_o_status(struct slcompress *comp)
-{
-	if (comp != NULLSLCOMPR) {
-		printk("\t%d Cmp, %d Uncmp, %d AsIs, %d NotTCP\n",
-			comp->sls_o_compressed,
-			comp->sls_o_uncompressed,
-			comp->sls_o_tcp,
-			comp->sls_o_nontcp);
-		printk("\t%10d Searches, %10d Misses\n",
-			comp->sls_o_searches,
-			comp->sls_o_misses);
-	}
-}
-
-/* Should this be surrounded with "#ifdef CONFIG_MODULES" ? */
 /* VJ header compression */
 EXPORT_SYMBOL(slhc_init);
 EXPORT_SYMBOL(slhc_free);
diff -Nru a/drivers/net/smc-mca.c b/drivers/net/smc-mca.c
--- a/drivers/net/smc-mca.c	2005-03-11 12:51:41 -08:00
+++ b/drivers/net/smc-mca.c	2005-03-11 12:51:41 -08:00
@@ -310,9 +310,13 @@
 	ei_status.rx_start_page = START_PG + TX_PAGES;
 	ei_status.stop_page = num_pages;
 
-	ei_status.rmem_start = dev->mem_start + TX_PAGES * 256;
-	dev->mem_end = ei_status.rmem_end =
-	dev->mem_start + (ei_status.stop_page - START_PG) * 256;
+	ei_status.mem = ioremap(dev->mem_start, (ei_status.stop_page - START_PG) * 256);
+	if (!ei_status.mem) {
+		rc = -ENOMEM;
+		goto err_release_region;
+	}
+
+	dev->mem_end = dev->mem_start + (ei_status.stop_page - START_PG) * 256;
 
 	printk(", IRQ %d memory %#lx-%#lx.\n",
 	dev->irq, dev->mem_start, dev->mem_end - 1);
@@ -334,10 +338,12 @@
 
 	rc = register_netdev(dev);
 	if (rc)
-		goto err_release_region;
+		goto err_unmap;
 
 	return 0;
 
+err_unmap:
+	iounmap(ei_status.mem);
 err_release_region:
 	release_region(ioaddr, ULTRA_IO_EXTENT);
 err_unclaim:
@@ -395,13 +401,13 @@
 
 static void ultramca_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
 {
-	unsigned long hdr_start = dev->mem_start + ((ring_page - START_PG) << 8);
+	void __iomem *hdr_start = ei_status.mem + ((ring_page - START_PG) << 8);
 
 #ifdef notdef
 	/* Officially this is what we are doing, but the readl() is faster */
-	isa_memcpy_fromio(hdr, hdr_start, sizeof(struct e8390_pkt_hdr));
+	memcpy_fromio(hdr, hdr_start, sizeof(struct e8390_pkt_hdr));
 #else
-	((unsigned int*)hdr)[0] = isa_readl(hdr_start);
+	((unsigned int*)hdr)[0] = readl(hdr_start);
 #endif
 }
 
@@ -411,17 +417,17 @@
 
 static void ultramca_block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset)
 {
-	unsigned long xfer_start = dev->mem_start + ring_offset - (START_PG << 8);
+	void __iomem *xfer_start = ei_status.mem + ring_offset - START_PG * 256;
 
-	if (xfer_start + count > ei_status.rmem_end) {
+	if (ring_offset + count > ei_status.stop_page * 256) {
 		/* We must wrap the input move. */
-		int semi_count = ei_status.rmem_end - xfer_start;
-		isa_memcpy_fromio(skb->data, xfer_start, semi_count);
+		int semi_count = ei_status.stop_page * 256 - ring_offset;
+		memcpy_fromio(skb->data, xfer_start, semi_count);
 		count -= semi_count;
-		isa_memcpy_fromio(skb->data + semi_count, ei_status.rmem_start, count);
+		memcpy_fromio(skb->data + semi_count, ei_status.mem + TX_PAGES * 256, count);
 	} else {
 		/* Packet is in one chunk -- we can copy + cksum. */
-		isa_eth_io_copy_and_sum(skb, xfer_start, count, 0);
+		eth_io_copy_and_sum(skb, xfer_start, count, 0);
 	}
 
 }
@@ -429,9 +435,9 @@
 static void ultramca_block_output(struct net_device *dev, int count, const unsigned char *buf,
                 int start_page)
 {
-	unsigned long shmem = dev->mem_start + ((start_page - START_PG) << 8);
+	void __iomem *shmem = ei_status.mem + ((start_page - START_PG) << 8);
 
-	isa_memcpy_toio(shmem, buf, count);
+	memcpy_toio(shmem, buf, count);
 }
 
 static int ultramca_close_card(struct net_device *dev)
@@ -466,6 +472,7 @@
 		unregister_netdev(dev);
 		mca_device_set_claim(mca_dev, 0);
 		release_region(ioaddr, ULTRA_IO_EXTENT);
+		iounmap(ei_status.mem);
 		free_netdev(dev);
 	}
 	return 0;
diff -Nru a/drivers/net/smc-ultra.c b/drivers/net/smc-ultra.c
--- a/drivers/net/smc-ultra.c	2005-03-11 12:51:41 -08:00
+++ b/drivers/net/smc-ultra.c	2005-03-11 12:51:41 -08:00
@@ -176,6 +176,7 @@
 		pnp_device_detach(idev);
 #endif
 	release_region(dev->base_addr - ULTRA_NIC_OFFSET, ULTRA_IO_EXTENT);
+	iounmap(ei_status.mem);
 }
 
 #ifndef MODULE
@@ -294,9 +295,14 @@
 	ei_status.rx_start_page = START_PG + TX_PAGES;
 	ei_status.stop_page = num_pages;
 
-	ei_status.rmem_start = dev->mem_start + TX_PAGES*256;
-	dev->mem_end = ei_status.rmem_end
-		= dev->mem_start + (ei_status.stop_page - START_PG)*256;
+	ei_status.mem = ioremap(dev->mem_start, (ei_status.stop_page - START_PG)*256);
+	if (!ei_status.mem) {
+		printk(", failed to ioremap.\n");
+		retval =  -ENOMEM;
+		goto out;
+	}
+
+	dev->mem_end = dev->mem_start + (ei_status.stop_page - START_PG)*256;
 
 	if (piomode) {
 		printk(",%s IRQ %d programmed-I/O mode.\n",
@@ -430,16 +436,16 @@
 static void
 ultra_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
 {
-	unsigned long hdr_start = dev->mem_start + ((ring_page - START_PG)<<8);
+	void __iomem *hdr_start = ei_status.mem + ((ring_page - START_PG)<<8);
 
 	outb(ULTRA_MEMENB, dev->base_addr - ULTRA_NIC_OFFSET);	/* shmem on */
 #ifdef __BIG_ENDIAN
 	/* Officially this is what we are doing, but the readl() is faster */
 	/* unfortunately it isn't endian aware of the struct               */
-	isa_memcpy_fromio(hdr, hdr_start, sizeof(struct e8390_pkt_hdr));
+	memcpy_fromio(hdr, hdr_start, sizeof(struct e8390_pkt_hdr));
 	hdr->count = le16_to_cpu(hdr->count);
 #else
-	((unsigned int*)hdr)[0] = isa_readl(hdr_start);
+	((unsigned int*)hdr)[0] = readl(hdr_start);
 #endif
 	outb(0x00, dev->base_addr - ULTRA_NIC_OFFSET); /* shmem off */
 }
@@ -450,20 +456,20 @@
 static void
 ultra_block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset)
 {
-	unsigned long xfer_start = dev->mem_start + ring_offset - (START_PG<<8);
+	void __iomem *xfer_start = ei_status.mem + ring_offset - (START_PG<<8);
 
 	/* Enable shared memory. */
 	outb(ULTRA_MEMENB, dev->base_addr - ULTRA_NIC_OFFSET);
 
-	if (xfer_start + count > ei_status.rmem_end) {
+	if (ring_offset + count > ei_status.stop_page*256) {
 		/* We must wrap the input move. */
-		int semi_count = ei_status.rmem_end - xfer_start;
-		isa_memcpy_fromio(skb->data, xfer_start, semi_count);
+		int semi_count = ei_status.stop_page*256 - ring_offset;
+		memcpy_fromio(skb->data, xfer_start, semi_count);
 		count -= semi_count;
-		isa_memcpy_fromio(skb->data + semi_count, ei_status.rmem_start, count);
+		memcpy_fromio(skb->data + semi_count, ei_status.mem + TX_PAGES * 256, count);
 	} else {
 		/* Packet is in one chunk -- we can copy + cksum. */
-		isa_eth_io_copy_and_sum(skb, xfer_start, count, 0);
+		eth_io_copy_and_sum(skb, xfer_start, count, 0);
 	}
 
 	outb(0x00, dev->base_addr - ULTRA_NIC_OFFSET);	/* Disable memory. */
@@ -473,12 +479,12 @@
 ultra_block_output(struct net_device *dev, int count, const unsigned char *buf,
 				int start_page)
 {
-	unsigned long shmem = dev->mem_start + ((start_page - START_PG)<<8);
+	void __iomem *shmem = ei_status.mem + ((start_page - START_PG)<<8);
 
 	/* Enable shared memory. */
 	outb(ULTRA_MEMENB, dev->base_addr - ULTRA_NIC_OFFSET);
 
-	isa_memcpy_toio(shmem, buf, count);
+	memcpy_toio(shmem, buf, count);
 
 	outb(0x00, dev->base_addr - ULTRA_NIC_OFFSET); /* Disable memory. */
 }
diff -Nru a/drivers/net/smc-ultra32.c b/drivers/net/smc-ultra32.c
--- a/drivers/net/smc-ultra32.c	2005-03-11 12:51:51 -08:00
+++ b/drivers/net/smc-ultra32.c	2005-03-11 12:51:51 -08:00
@@ -104,6 +104,7 @@
 	int ioaddr = dev->base_addr - ULTRA32_NIC_OFFSET;
 	/* NB: ultra32_close_card() does free_irq */
 	release_region(ioaddr, ULTRA32_IO_EXTENT);
+	iounmap(ei_status.mem);
 }
 
 /*	Probe for the Ultra32.  This looks like a 8013 with the station
@@ -259,8 +260,13 @@
 	/* All Ultra32 cards have 32KB memory with an 8KB window. */
 	ei_status.stop_page = 128;
 
-	ei_status.rmem_start = dev->mem_start + TX_PAGES*256;
-	dev->mem_end = ei_status.rmem_end = dev->mem_start + 0x1fff;
+	ei_status.mem = ioremap(dev->mem_start, 0x2000);
+	if (!ei_status.mem) {
+		printk(", failed to ioremap.\n");
+		retval = -ENOMEM;
+		goto out;
+	}
+	dev->mem_end = dev->mem_start + 0x1fff;
 
 	printk(", IRQ %d, 32KB memory, 8KB window at 0x%lx-0x%lx.\n",
 	       dev->irq, dev->mem_start, dev->mem_end);
@@ -345,7 +351,7 @@
 				 struct e8390_pkt_hdr *hdr,
 				 int ring_page)
 {
-	unsigned long hdr_start = dev->mem_start + ((ring_page & 0x1f) << 8);
+	void __iomem *hdr_start = ei_status.mem + ((ring_page & 0x1f) << 8);
 	unsigned int RamReg = dev->base_addr - ULTRA32_NIC_OFFSET + ULTRA32_CFG3;
 
 	/* Select correct 8KB Window. */
@@ -354,10 +360,10 @@
 #ifdef __BIG_ENDIAN
 	/* Officially this is what we are doing, but the readl() is faster */
 	/* unfortunately it isn't endian aware of the struct               */
-	isa_memcpy_fromio(hdr, hdr_start, sizeof(struct e8390_pkt_hdr));
+	memcpy_fromio(hdr, hdr_start, sizeof(struct e8390_pkt_hdr));
 	hdr->count = le16_to_cpu(hdr->count);
 #else
-	((unsigned int*)hdr)[0] = isa_readl(hdr_start);
+	((unsigned int*)hdr)[0] = readl(hdr_start);
 #endif
 }
 
@@ -371,26 +377,26 @@
 				struct sk_buff *skb,
 				int ring_offset)
 {
-	unsigned long xfer_start = dev->mem_start + (ring_offset & 0x1fff);
+	void __iomem *xfer_start = ei_status.mem + (ring_offset & 0x1fff);
 	unsigned int RamReg = dev->base_addr - ULTRA32_NIC_OFFSET + ULTRA32_CFG3;
 
 	if ((ring_offset & ~0x1fff) != ((ring_offset + count - 1) & ~0x1fff)) {
 		int semi_count = 8192 - (ring_offset & 0x1FFF);
-		isa_memcpy_fromio(skb->data, xfer_start, semi_count);
+		memcpy_fromio(skb->data, xfer_start, semi_count);
 		count -= semi_count;
 		if (ring_offset < 96*256) {
 			/* Select next 8KB Window. */
 			ring_offset += semi_count;
 			outb(ei_status.reg0 | ((ring_offset & 0x6000) >> 13), RamReg);
-			isa_memcpy_fromio(skb->data + semi_count, dev->mem_start, count);
+			memcpy_fromio(skb->data + semi_count, ei_status.mem, count);
 		} else {
 			/* Select first 8KB Window. */
 			outb(ei_status.reg0, RamReg);
-			isa_memcpy_fromio(skb->data + semi_count, ei_status.rmem_start, count);
+			memcpy_fromio(skb->data + semi_count, ei_status.mem + TX_PAGES * 256, count);
 		}
 	} else {
 		/* Packet is in one chunk -- we can copy + cksum. */
-		isa_eth_io_copy_and_sum(skb, xfer_start, count, 0);
+		eth_io_copy_and_sum(skb, xfer_start, count, 0);
 	}
 }
 
@@ -399,13 +405,13 @@
 				 const unsigned char *buf,
 				 int start_page)
 {
-	unsigned long xfer_start = dev->mem_start + (start_page<<8);
+	void __iomem *xfer_start = ei_status.mem + (start_page<<8);
 	unsigned int RamReg = dev->base_addr - ULTRA32_NIC_OFFSET + ULTRA32_CFG3;
 
 	/* Select first 8KB Window. */
 	outb(ei_status.reg0, RamReg);
 
-	isa_memcpy_toio(xfer_start, buf, count);
+	memcpy_toio(xfer_start, buf, count);
 }
 
 #ifdef MODULE
diff -Nru a/drivers/net/smc91x.c b/drivers/net/smc91x.c
--- a/drivers/net/smc91x.c	2005-03-11 12:51:51 -08:00
+++ b/drivers/net/smc91x.c	2005-03-11 12:51:51 -08:00
@@ -210,10 +210,15 @@
 
 	spinlock_t lock;
 
+#ifdef SMC_CAN_USE_DATACS
+	u32	__iomem *datacs;
+#endif
+
 #ifdef SMC_USE_PXA_DMA
 	/* DMA needs the physical address of the chip */
 	u_long physaddr;
 #endif
+	void __iomem *base;
 };
 
 #if SMC_DEBUG > 0
@@ -307,8 +312,8 @@
  */
 static void smc_reset(struct net_device *dev)
 {
-	unsigned long ioaddr = dev->base_addr;
 	struct smc_local *lp = netdev_priv(dev);
+	void __iomem *ioaddr = lp->base;
 	unsigned int ctl, cfg;
 
 	DBG(2, "%s: %s\n", dev->name, __FUNCTION__);
@@ -399,8 +404,8 @@
  */
 static void smc_enable(struct net_device *dev)
 {
-	unsigned long ioaddr = dev->base_addr;
 	struct smc_local *lp = netdev_priv(dev);
+	void __iomem *ioaddr = lp->base;
 	int mask;
 
 	DBG(2, "%s: %s\n", dev->name, __FUNCTION__);
@@ -433,8 +438,8 @@
  */
 static void smc_shutdown(struct net_device *dev)
 {
-	unsigned long ioaddr = dev->base_addr;
 	struct smc_local *lp = netdev_priv(dev);
+	void __iomem *ioaddr = lp->base;
 
 	DBG(2, "%s: %s\n", CARDNAME, __FUNCTION__);
 
@@ -462,7 +467,7 @@
 static inline void  smc_rcv(struct net_device *dev)
 {
 	struct smc_local *lp = netdev_priv(dev);
-	unsigned long ioaddr = dev->base_addr;
+	void __iomem *ioaddr = lp->base;
 	unsigned int packet_number, status, packet_len;
 
 	DBG(3, "%s: %s\n", dev->name, __FUNCTION__);
@@ -483,7 +488,19 @@
 		dev->name, packet_number, status,
 		packet_len, packet_len);
 
-	if (unlikely(status & RS_ERRORS)) {
+	back:
+	if (unlikely(packet_len < 6 || status & RS_ERRORS)) {
+		if (status & RS_TOOLONG && packet_len <= (1514 + 4 + 6)) {
+			/* accept VLAN packets */
+			status &= ~RS_TOOLONG;
+			goto back;
+		}
+		if (packet_len < 6) {
+			/* bloody hardware */
+			printk(KERN_ERR "%s: fubar (rxlen %u status %x\n",
+					dev->name, packet_len, status);
+			status |= RS_TOOSHORT;
+		}
 		SMC_WAIT_MMU_BUSY();
 		SMC_SET_MMU_CMD(MC_RELEASE);
 		lp->stats.rx_errors++;
@@ -508,7 +525,7 @@
 		 * (2 bytes, possibly containing the payload odd byte).
 		 * Furthermore, we add 2 bytes to allow rounding up to
 		 * multiple of 4 bytes on 32 bit buses.
-		 * Ence packet_len - 6 + 2 + 2 + 2.
+		 * Hence packet_len - 6 + 2 + 2 + 2.
 		 */
 		skb = dev_alloc_skb(packet_len);
 		if (unlikely(skb == NULL)) {
@@ -596,7 +613,7 @@
 {
 	struct net_device *dev = (struct net_device *)data;
 	struct smc_local *lp = netdev_priv(dev);
-	unsigned long ioaddr = dev->base_addr;
+	void __iomem *ioaddr = lp->base;
 	struct sk_buff *skb;
 	unsigned int packet_no, len;
 	unsigned char *buf;
@@ -680,7 +697,7 @@
 static int smc_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct smc_local *lp = netdev_priv(dev);
-	unsigned long ioaddr = dev->base_addr;
+	void __iomem *ioaddr = lp->base;
 	unsigned int numPages, poll_count, status;
 
 	DBG(3, "%s: %s\n", dev->name, __FUNCTION__);
@@ -752,8 +769,8 @@
  */
 static void smc_tx(struct net_device *dev)
 {
-	unsigned long ioaddr = dev->base_addr;
 	struct smc_local *lp = netdev_priv(dev);
+	void __iomem *ioaddr = lp->base;
 	unsigned int saved_packet, packet_no, tx_status, pkt_len;
 
 	DBG(3, "%s: %s\n", dev->name, __FUNCTION__);
@@ -809,7 +826,8 @@
 
 static void smc_mii_out(struct net_device *dev, unsigned int val, int bits)
 {
-	unsigned long ioaddr = dev->base_addr;
+	struct smc_local *lp = netdev_priv(dev);
+	void __iomem *ioaddr = lp->base;
 	unsigned int mii_reg, mask;
 
 	mii_reg = SMC_GET_MII() & ~(MII_MCLK | MII_MDOE | MII_MDO);
@@ -830,7 +848,8 @@
 
 static unsigned int smc_mii_in(struct net_device *dev, int bits)
 {
-	unsigned long ioaddr = dev->base_addr;
+	struct smc_local *lp = netdev_priv(dev);
+	void __iomem *ioaddr = lp->base;
 	unsigned int mii_reg, mask, val;
 
 	mii_reg = SMC_GET_MII() & ~(MII_MCLK | MII_MDOE | MII_MDO);
@@ -854,7 +873,8 @@
  */
 static int smc_phy_read(struct net_device *dev, int phyaddr, int phyreg)
 {
-	unsigned long ioaddr = dev->base_addr;
+	struct smc_local *lp = netdev_priv(dev);
+	void __iomem *ioaddr = lp->base;
 	unsigned int phydata;
 
 	SMC_SELECT_BANK(3);
@@ -884,7 +904,8 @@
 static void smc_phy_write(struct net_device *dev, int phyaddr, int phyreg,
 			  int phydata)
 {
-	unsigned long ioaddr = dev->base_addr;
+	struct smc_local *lp = netdev_priv(dev);
+	void __iomem *ioaddr = lp->base;
 
 	SMC_SELECT_BANK(3);
 
@@ -946,7 +967,7 @@
 static int smc_phy_fixed(struct net_device *dev)
 {
 	struct smc_local *lp = netdev_priv(dev);
-	unsigned long ioaddr = dev->base_addr;
+	void __iomem *ioaddr = lp->base;
 	int phyaddr = lp->mii.phy_id;
 	int bmcr, cfg1;
 
@@ -1017,13 +1038,29 @@
 /*
  * smc_phy_powerdown - powerdown phy
  * @dev: net device
- * @phy: phy address
  *
  * Power down the specified PHY
  */
-static void smc_phy_powerdown(struct net_device *dev, int phy)
+static void smc_phy_powerdown(struct net_device *dev)
 {
+	struct smc_local *lp = netdev_priv(dev);
 	unsigned int bmcr;
+	int phy = lp->mii.phy_id;
+
+	if (lp->phy_type == 0)
+		return;
+
+	/* We need to ensure that no calls to smc_phy_configure are
+	   pending.
+
+	   flush_scheduled_work() cannot be called because we are
+	   running with the netlink semaphore held (from
+	   devinet_ioctl()) and the pending work queue contains
+	   linkwatch_event() (scheduled by netif_carrier_off()
+	   above). linkwatch_event() also wants the netlink semaphore.
+	*/
+	while(lp->work_pending)
+		schedule();
 
 	bmcr = smc_phy_read(dev, phy, MII_BMCR);
 	smc_phy_write(dev, phy, MII_BMCR, bmcr | BMCR_PDOWN);
@@ -1040,7 +1077,7 @@
 static void smc_phy_check_media(struct net_device *dev, int init)
 {
 	struct smc_local *lp = netdev_priv(dev);
-	unsigned long ioaddr = dev->base_addr;
+	void __iomem *ioaddr = lp->base;
 
 	if (mii_check_media(&lp->mii, netif_msg_link(lp), init)) {
 		/* duplex state has changed */
@@ -1068,7 +1105,7 @@
 {
 	struct net_device *dev = data;
 	struct smc_local *lp = netdev_priv(dev);
-	unsigned long ioaddr = dev->base_addr;
+	void __iomem *ioaddr = lp->base;
 	int phyaddr = lp->mii.phy_id;
 	int my_phy_caps; /* My PHY capabilities */
 	int my_ad_caps; /* My Advertised capabilities */
@@ -1193,7 +1230,7 @@
 static void smc_10bt_check_media(struct net_device *dev, int init)
 {
 	struct smc_local *lp = netdev_priv(dev);
-	unsigned long ioaddr = dev->base_addr;
+	void __iomem *ioaddr = lp->base;
 	unsigned int old_carrier, new_carrier;
 
 	old_carrier = netif_carrier_ok(dev) ? 1 : 0;
@@ -1216,7 +1253,8 @@
 
 static void smc_eph_interrupt(struct net_device *dev)
 {
-	unsigned long ioaddr = dev->base_addr;
+	struct smc_local *lp = netdev_priv(dev);
+	void __iomem *ioaddr = lp->base;
 	unsigned int ctl;
 
 	smc_10bt_check_media(dev, 0);
@@ -1235,8 +1273,8 @@
 static irqreturn_t smc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
 	struct net_device *dev = dev_id;
-	unsigned long ioaddr = dev->base_addr;
 	struct smc_local *lp = netdev_priv(dev);
+	void __iomem *ioaddr = lp->base;
 	int status, mask, timeout, card_stats;
 	int saved_pointer;
 
@@ -1350,7 +1388,7 @@
 static void smc_timeout(struct net_device *dev)
 {
 	struct smc_local *lp = netdev_priv(dev);
-	unsigned long ioaddr = dev->base_addr;
+	void __iomem *ioaddr = lp->base;
 	int status, mask, meminfo, fifo;
 
 	DBG(2, "%s: %s\n", dev->name, __FUNCTION__);
@@ -1394,7 +1432,7 @@
 static void smc_set_multicast_list(struct net_device *dev)
 {
 	struct smc_local *lp = netdev_priv(dev);
-	unsigned long ioaddr = dev->base_addr;
+	void __iomem *ioaddr = lp->base;
 	unsigned char multicast_table[8];
 	int update_multicast = 0;
 
@@ -1561,21 +1599,7 @@
 	/* clear everything */
 	smc_shutdown(dev);
 
-	if (lp->phy_type != 0) {
-		/* We need to ensure that no calls to
-		   smc_phy_configure are pending.
-
-		   flush_scheduled_work() cannot be called because we
-		   are running with the netlink semaphore held (from
-		   devinet_ioctl()) and the pending work queue
-		   contains linkwatch_event() (scheduled by
-		   netif_carrier_off() above). linkwatch_event() also
-		   wants the netlink semaphore.
-		*/
-		while(lp->work_pending)
-			schedule();
-		smc_phy_powerdown(dev, lp->mii.phy_id);
-	}
+	smc_phy_powerdown(dev);
 
 	if (lp->pending_tx_skb) {
 		dev_kfree_skb(lp->pending_tx_skb);
@@ -1723,7 +1747,7 @@
  * I just deleted auto_irq.c, since it was never built...
  *   --jgarzik
  */
-static int __init smc_findirq(unsigned long ioaddr)
+static int __init smc_findirq(void __iomem *ioaddr)
 {
 	int timeout = 20;
 	unsigned long cookie;
@@ -1796,7 +1820,7 @@
  * o  actually GRAB the irq.
  * o  GRAB the region
  */
-static int __init smc_probe(struct net_device *dev, unsigned long ioaddr)
+static int __init smc_probe(struct net_device *dev, void __iomem *ioaddr)
 {
 	struct smc_local *lp = netdev_priv(dev);
 	static int version_printed = 0;
@@ -1813,7 +1837,7 @@
 		if ((val & 0xFF) == 0x33) {
 			printk(KERN_WARNING
 				"%s: Detected possible byte-swapped interface"
-				" at IOADDR 0x%lx\n", CARDNAME, ioaddr);
+				" at IOADDR %p\n", CARDNAME, ioaddr);
 		}
 		retval = -ENODEV;
 		goto err_out;
@@ -1839,8 +1863,8 @@
 	SMC_SELECT_BANK(1);
 	val = SMC_GET_BASE();
 	val = ((val & 0x1F00) >> 3) << SMC_IO_SHIFT;
-	if ((ioaddr & ((PAGE_SIZE-1)<<SMC_IO_SHIFT)) != val) {
-		printk("%s: IOADDR %lx doesn't match configuration (%x).\n",
+	if (((unsigned long)ioaddr & ((PAGE_SIZE-1)<<SMC_IO_SHIFT)) != val) { /*XXX: WTF? */
+		printk("%s: IOADDR %p doesn't match configuration (%x).\n",
 			CARDNAME, ioaddr, val);
 	}
 
@@ -1855,7 +1879,7 @@
 	version_string = chip_ids[ (revision_register >> 4) & 0xF];
 	if (!version_string || (revision_register & 0xff00) != 0x3300) {
 		/* I don't recognize this chip, so... */
-		printk("%s: IO 0x%lx: Unrecognized revision register 0x%04x"
+		printk("%s: IO %p: Unrecognized revision register 0x%04x"
 			", Contact author.\n", CARDNAME,
 			ioaddr, revision_register);
 
@@ -1868,7 +1892,8 @@
 		printk("%s", version);
 
 	/* fill in some of the fields */
-	dev->base_addr = ioaddr;
+	dev->base_addr = (unsigned long)ioaddr;
+	lp->base = ioaddr;
 	lp->version = revision_register & 0xff;
 	spin_lock_init(&lp->lock);
 
@@ -1974,9 +1999,9 @@
 	retval = register_netdev(dev);
 	if (retval == 0) {
 		/* now, print out the card info, in a short format.. */
-		printk("%s: %s (rev %d) at %#lx IRQ %d",
+		printk("%s: %s (rev %d) at %p IRQ %d",
 			dev->name, version_string, revision_register & 0x0f,
-			dev->base_addr, dev->irq);
+			lp->base, dev->irq);
 
 		if (dev->dma != (unsigned char)-1)
 			printk(" DMA %d", dev->dma);
@@ -2012,16 +2037,21 @@
 	return retval;
 }
 
-static int smc_enable_device(unsigned long attrib_phys)
+static int smc_enable_device(struct platform_device *pdev)
 {
 	unsigned long flags;
 	unsigned char ecor, ecsr;
-	void *addr;
+	void __iomem *addr;
+	struct resource * res;
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "smc91x-attrib");
+	if (!res)
+		return 0;
 
 	/*
 	 * Map the attribute space.  This is overkill, but clean.
 	 */
-	addr = ioremap(attrib_phys, ATTRIB_SIZE);
+	addr = ioremap(res->start, ATTRIB_SIZE);
 	if (!addr)
 		return -ENOMEM;
 
@@ -2069,6 +2099,62 @@
 	return 0;
 }
 
+static int smc_request_attrib(struct platform_device *pdev)
+{
+	struct resource * res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "smc91x-attrib");
+
+	if (!res)
+		return 0;
+
+	if (!request_mem_region(res->start, ATTRIB_SIZE, CARDNAME))
+		return -EBUSY;
+
+	return 0;
+}
+
+static void smc_release_attrib(struct platform_device *pdev)
+{
+	struct resource * res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "smc91x-attrib");
+
+	if (res)
+		release_mem_region(res->start, ATTRIB_SIZE);
+}
+
+#ifdef SMC_CAN_USE_DATACS
+static void smc_request_datacs(struct platform_device *pdev, struct net_device *ndev)
+{
+	struct resource * res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "smc91x-data32");
+	struct smc_local *lp = netdev_priv(ndev);
+
+	if (!res)
+		return;
+
+	if(!request_mem_region(res->start, SMC_DATA_EXTENT, CARDNAME)) {
+		printk(KERN_INFO "%s: failed to request datacs memory region.\n", CARDNAME);
+		return;
+	}
+
+	lp->datacs = ioremap(res->start, SMC_DATA_EXTENT);
+}
+
+static void smc_release_datacs(struct platform_device *pdev, struct net_device *ndev)
+{
+	struct smc_local *lp = netdev_priv(ndev);
+	struct resource * res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "smc91x-data32");
+
+	if (lp->datacs)
+		iounmap(lp->datacs);
+
+	lp->datacs = NULL;
+
+	if (res)
+		release_mem_region(res->start, SMC_DATA_EXTENT);
+}
+#else
+static void smc_request_datacs(struct platform_device *pdev, struct net_device *ndev) {}
+static void smc_release_datacs(struct platform_device *pdev, struct net_device *ndev) {}
+#endif
+
 /*
  * smc_init(void)
  *   Input parameters:
@@ -2084,20 +2170,20 @@
 {
 	struct platform_device *pdev = to_platform_device(dev);
 	struct net_device *ndev;
-	struct resource *res, *ext = NULL;
-	unsigned int *addr;
+	struct resource *res;
+	unsigned int __iomem *addr;
 	int ret;
 
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "smc91x-regs");
+	if (!res)
+		res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!res) {
 		ret = -ENODEV;
 		goto out;
 	}
 
-	/*
-	 * Request the regions.
-	 */
-	if (!request_mem_region(res->start, SMC_IO_EXTENT, "smc91x")) {
+
+	if (!request_mem_region(res->start, SMC_IO_EXTENT, CARDNAME)) {
 		ret = -EBUSY;
 		goto out;
 	}
@@ -2106,7 +2192,7 @@
 	if (!ndev) {
 		printk("%s: could not allocate device.\n", CARDNAME);
 		ret = -ENOMEM;
-		goto release_1;
+		goto out_release_io;
 	}
 	SET_MODULE_OWNER(ndev);
 	SET_NETDEV_DEV(ndev, dev);
@@ -2114,42 +2200,26 @@
 	ndev->dma = (unsigned char)-1;
 	ndev->irq = platform_get_irq(pdev, 0);
 
-	ext = platform_get_resource(pdev, IORESOURCE_MEM, 1);
-	if (ext) {
-		if (!request_mem_region(ext->start, ATTRIB_SIZE, ndev->name)) {
-			ret = -EBUSY;
-			goto release_1;
-		}
-
+	ret = smc_request_attrib(pdev);
+	if (ret)
+		goto out_free_netdev;
 #if defined(CONFIG_SA1100_ASSABET)
-		NCR_0 |= NCR_ENET_OSC_EN;
+	NCR_0 |= NCR_ENET_OSC_EN;
 #endif
-
-		ret = smc_enable_device(ext->start);
-		if (ret)
-			goto release_both;
-	}
+	ret = smc_enable_device(pdev);
+	if (ret)
+		goto out_release_attrib;
 
 	addr = ioremap(res->start, SMC_IO_EXTENT);
 	if (!addr) {
 		ret = -ENOMEM;
-		goto release_both;
+		goto out_release_attrib;
 	}
 
 	dev_set_drvdata(dev, ndev);
-	ret = smc_probe(ndev, (unsigned long)addr);
-	if (ret != 0) {
-		dev_set_drvdata(dev, NULL);
-		iounmap(addr);
- release_both:
-		if (ext)
-			release_mem_region(ext->start, ATTRIB_SIZE);
-		free_netdev(ndev);
- release_1:
-		release_mem_region(res->start, SMC_IO_EXTENT);
- out:
-		printk("%s: not found (%d).\n", CARDNAME, ret);
-	}
+	ret = smc_probe(ndev, addr);
+	if (ret != 0)
+		goto out_iounmap;
 #ifdef SMC_USE_PXA_DMA
 	else {
 		struct smc_local *lp = netdev_priv(ndev);
@@ -2157,6 +2227,22 @@
 	}
 #endif
 
+	smc_request_datacs(pdev, ndev);
+
+	return 0;
+
+ out_iounmap:
+	dev_set_drvdata(dev, NULL);
+	iounmap(addr);
+ out_release_attrib:
+	smc_release_attrib(pdev);
+ out_free_netdev:
+	free_netdev(ndev);
+ out_release_io:
+	release_mem_region(res->start, SMC_IO_EXTENT);
+ out:
+	printk("%s: not found (%d).\n", CARDNAME, ret);
+
 	return ret;
 }
 
@@ -2164,6 +2250,7 @@
 {
 	struct platform_device *pdev = to_platform_device(dev);
 	struct net_device *ndev = dev_get_drvdata(dev);
+	struct smc_local *lp = netdev_priv(ndev);
 	struct resource *res;
 
 	dev_set_drvdata(dev, NULL);
@@ -2176,11 +2263,14 @@
 	if (ndev->dma != (unsigned char)-1)
 		pxa_free_dma(ndev->dma);
 #endif
-	iounmap((void *)ndev->base_addr);
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
-	if (res)
-		release_mem_region(res->start, ATTRIB_SIZE);
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	iounmap(lp->base);
+
+	smc_release_datacs(pdev,ndev);
+	smc_release_attrib(pdev);
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "smc91x-regs");
+	if (!res)
+		platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	release_mem_region(res->start, SMC_IO_EXTENT);
 
 	free_netdev(ndev);
@@ -2196,6 +2286,7 @@
 		if (netif_running(ndev)) {
 			netif_device_detach(ndev);
 			smc_shutdown(ndev);
+			smc_phy_powerdown(ndev);
 		}
 	}
 	return 0;
@@ -2208,9 +2299,7 @@
 
 	if (ndev && level == RESUME_ENABLE) {
 		struct smc_local *lp = netdev_priv(ndev);
-
-		if (pdev->num_resources == 3)
-			smc_enable_device(pdev->resource[2].start);
+		smc_enable_device(pdev);
 		if (netif_running(ndev)) {
 			smc_reset(ndev);
 			smc_enable(ndev);
diff -Nru a/drivers/net/smc91x.h b/drivers/net/smc91x.h
--- a/drivers/net/smc91x.h	2005-03-11 12:51:48 -08:00
+++ b/drivers/net/smc91x.h	2005-03-11 12:51:48 -08:00
@@ -162,6 +162,45 @@
 	}
 }
 
+#elif	defined(CONFIG_ARCH_OMAP)
+
+/* We can only do 16-bit reads and writes in the static memory space. */
+#define SMC_CAN_USE_8BIT	0
+#define SMC_CAN_USE_16BIT	1
+#define SMC_CAN_USE_32BIT	0
+#define SMC_IO_SHIFT		0
+#define SMC_NOWAIT		1
+
+#define SMC_inb(a, r)		readb((a) + (r))
+#define SMC_outb(v, a, r)	writeb(v, (a) + (r))
+#define SMC_inw(a, r)		readw((a) + (r))
+#define SMC_outw(v, a, r)	writew(v, (a) + (r))
+#define SMC_insw(a, r, p, l)	readsw((a) + (r), p, l)
+#define SMC_outsw(a, r, p, l)	writesw((a) + (r), p, l)
+#define SMC_inl(a, r)		readl((a) + (r))
+#define SMC_outl(v, a, r)	writel(v, (a) + (r))
+#define SMC_insl(a, r, p, l)	readsl((a) + (r), p, l)
+#define SMC_outsl(a, r, p, l)	writesl((a) + (r), p, l)
+
+#elif	defined(CONFIG_SH_SH4202_MICRODEV)
+
+#define SMC_CAN_USE_8BIT	0
+#define SMC_CAN_USE_16BIT	1
+#define SMC_CAN_USE_32BIT	0
+
+#define SMC_inb(a, r)		inb((a) + (r) - 0xa0000000)
+#define SMC_inw(a, r)		inw((a) + (r) - 0xa0000000)
+#define SMC_inl(a, r)		inl((a) + (r) - 0xa0000000)
+#define SMC_outb(v, a, r)	outb(v, (a) + (r) - 0xa0000000)
+#define SMC_outw(v, a, r)	outw(v, (a) + (r) - 0xa0000000)
+#define SMC_outl(v, a, r)	outl(v, (a) + (r) - 0xa0000000)
+#define SMC_insl(a, r, p, l)	insl((a) + (r) - 0xa0000000, p, l)
+#define SMC_outsl(a, r, p, l)	outsl((a) + (r) - 0xa0000000, p, l)
+#define SMC_insw(a, r, p, l)	insw((a) + (r) - 0xa0000000, p, l)
+#define SMC_outsw(a, r, p, l)	outsw((a) + (r) - 0xa0000000, p, l)
+
+#define set_irq_type(irq, type)	do {} while(0)
+
 #elif	defined(CONFIG_ISA)
 
 #define SMC_CAN_USE_8BIT	1
@@ -362,7 +401,7 @@
 #define SMC_IO_SHIFT	0
 #endif
 #define SMC_IO_EXTENT	(16 << SMC_IO_SHIFT)
-
+#define SMC_DATA_EXTENT (4)
 
 /*
  . Bank Select Register:
@@ -883,7 +922,7 @@
 #endif
 
 #if SMC_CAN_USE_32BIT
-#define SMC_PUSH_DATA(p, l)						\
+#define _SMC_PUSH_DATA(p, l)						\
 	do {								\
 		char *__ptr = (p);					\
 		int __len = (l);					\
@@ -898,7 +937,7 @@
 			SMC_outw( *((u16 *)__ptr), ioaddr, DATA_REG );	\
 		}							\
 	} while (0)
-#define SMC_PULL_DATA(p, l)						\
+#define _SMC_PULL_DATA(p, l)						\
 	do {								\
 		char *__ptr = (p);					\
 		int __len = (l);					\
@@ -918,11 +957,11 @@
 		SMC_insl( ioaddr, DATA_REG, __ptr, __len >> 2);		\
 	} while (0)
 #elif SMC_CAN_USE_16BIT
-#define SMC_PUSH_DATA(p, l)	SMC_outsw( ioaddr, DATA_REG, p, (l) >> 1 )
-#define SMC_PULL_DATA(p, l)	SMC_insw ( ioaddr, DATA_REG, p, (l) >> 1 )
+#define _SMC_PUSH_DATA(p, l)	SMC_outsw( ioaddr, DATA_REG, p, (l) >> 1 )
+#define _SMC_PULL_DATA(p, l)	SMC_insw ( ioaddr, DATA_REG, p, (l) >> 1 )
 #elif SMC_CAN_USE_8BIT
-#define SMC_PUSH_DATA(p, l)	SMC_outsb( ioaddr, DATA_REG, p, l )
-#define SMC_PULL_DATA(p, l)	SMC_insb ( ioaddr, DATA_REG, p, l )
+#define _SMC_PUSH_DATA(p, l)	SMC_outsb( ioaddr, DATA_REG, p, l )
+#define _SMC_PULL_DATA(p, l)	SMC_insb ( ioaddr, DATA_REG, p, l )
 #endif
 
 #if ! SMC_CAN_USE_16BIT
@@ -939,6 +978,51 @@
 		__val16 |= SMC_inb( ioaddr, reg + (1 << SMC_IO_SHIFT)) << 8; \
 		__val16;						\
 	})
+#endif
+
+#if SMC_CAN_USE_DATACS
+#define SMC_PUSH_DATA(p, l)						\
+	if ( lp->datacs ) {						\
+		unsigned char *__ptr = (p);				\
+		int __len = (l);					\
+ 		if (__len >= 2 && (unsigned long)__ptr & 2) {		\
+ 			__len -= 2;					\
+ 			SMC_outw( *((u16 *)__ptr), ioaddr, DATA_REG );	\
+ 			__ptr += 2;					\
+ 		}							\
+		outsl(lp->datacs, __ptr, __len >> 2);			\
+ 		if (__len & 2) {					\
+ 			__ptr += (__len & ~3);				\
+ 			SMC_outw( *((u16 *)__ptr), ioaddr, DATA_REG );	\
+ 		}							\
+	} else {							\
+		_SMC_PUSH_DATA(p, l);					\
+	}
+
+#define SMC_PULL_DATA(p, l)						\
+	if ( lp->datacs ) { 						\
+		unsigned char *__ptr = (p);				\
+		int __len = (l);					\
+		if ((unsigned long)__ptr & 2) {			 	\
+			/*						\
+			 * We want 32bit alignment here.		\
+			 * Since some buses perform a full 32bit	\
+			 * fetch even for 16bit data we can't use	\
+			 * SMC_inw() here.  Back both source (on chip	\
+			 * and destination) pointers of 2 bytes.	\
+			 */						\
+			__ptr -= 2;					\
+			__len += 2;					\
+			SMC_SET_PTR( 2|PTR_READ|PTR_RCV|PTR_AUTOINC ); 	\
+		}							\
+		__len += 2;						\
+		insl( lp->datacs, __ptr, __len >> 2);			\
+	} else {							\
+		_SMC_PULL_DATA(p, l);					\
+	}
+#else
+#define SMC_PUSH_DATA(p, l) _SMC_PUSH_DATA(p, l)
+#define SMC_PULL_DATA(p, l) _SMC_PULL_DATA(p, l)
 #endif
 
 #if !defined (SMC_INTERRUPT_PREAMBLE)
diff -Nru a/drivers/net/sonic.c b/drivers/net/sonic.c
--- a/drivers/net/sonic.c	2005-03-11 12:51:51 -08:00
+++ b/drivers/net/sonic.c	2005-03-11 12:51:51 -08:00
@@ -116,7 +116,7 @@
 	/*
 	 * Map the packet data into the logical DMA address space
 	 */
-	if ((laddr = vdma_alloc(PHYSADDR(skb->data), skb->len)) == ~0UL) {
+	if ((laddr = vdma_alloc(CPHYSADDR(skb->data), skb->len)) == ~0UL) {
 		printk("%s: no VDMA entry for transmit available.\n",
 		       dev->name);
 		dev_kfree_skb(skb);
@@ -223,7 +223,7 @@
 
 			/* We must free the original skb */
 			if (lp->tx_skb[entry]) {
-				dev_kfree_skb(lp->tx_skb[entry]);
+				dev_kfree_skb_irq(lp->tx_skb[entry]);
 				lp->tx_skb[entry] = 0;
 			}
 			/* and the VDMA address */
diff -Nru a/drivers/net/sundance.c b/drivers/net/sundance.c
--- a/drivers/net/sundance.c	2005-03-11 12:51:47 -08:00
+++ b/drivers/net/sundance.c	2005-03-11 12:51:47 -08:00
@@ -1210,9 +1210,11 @@
 				}
 				/* Yup, this is a documentation bug.  It cost me *hours*. */
 				iowrite16 (0, ioaddr + TxStatus);
-				tx_status = ioread16 (ioaddr + TxStatus);
-				if (tx_cnt < 0)
+				if (tx_cnt < 0) {
+					iowrite32(5000, ioaddr + DownCounter);
 					break;
+				}
+				tx_status = ioread16 (ioaddr + TxStatus);
 			}
 			hw_frame_id = (tx_status >> 8) & 0xff;
 		} else 	{
@@ -1278,7 +1280,6 @@
 	if (netif_msg_intr(np))
 		printk(KERN_DEBUG "%s: exiting interrupt, status=%#4.4x.\n",
 			   dev->name, ioread16(ioaddr + IntrStatus));
-	iowrite32(5000, ioaddr + DownCounter);
 	return IRQ_RETVAL(handled);
 }
 
diff -Nru a/drivers/net/sungem.c b/drivers/net/sungem.c
--- a/drivers/net/sungem.c	2005-03-11 12:51:51 -08:00
+++ b/drivers/net/sungem.c	2005-03-11 12:51:51 -08:00
@@ -3,16 +3,32 @@
  *
  * Copyright (C) 2000, 2001, 2002, 2003 David S. Miller (davem@redhat.com)
  * 
- * Support for Apple GMAC and assorted PHYs by
- * Benjamin Herrenscmidt (benh@kernel.crashing.org)
+ * Support for Apple GMAC and assorted PHYs, WOL, Power Management
+ * (C) 2001,2002,2003 Benjamin Herrenscmidt (benh@kernel.crashing.org)
+ * (C) 2004,2005 Benjamin Herrenscmidt, IBM Corp.
  *
  * NAPI and NETPOLL support
  * (C) 2004 by Eric Lemoine (eric.lemoine@gmail.com)
  * 
  * TODO: 
- *  - Get rid of all those nasty mdelay's and replace them
- * with schedule_timeout.
- *  - Implement WOL
+ *  - Now that the driver was significantly simplified, I need to rework
+ *    the locking. I'm sure we don't need _2_ spinlocks, and we probably
+ *    can avoid taking most of them for so long period of time (and schedule
+ *    instead). The main issues at this point are caused by the netdev layer
+ *    though:
+ *    
+ *    gem_change_mtu() and gem_set_multicast() are called with a read_lock()
+ *    help by net/core/dev.c, thus they can't schedule. That means they can't
+ *    call netif_poll_disable() neither, thus force gem_poll() to keep a spinlock
+ *    where it could have been dropped. change_mtu especially would love also to
+ *    be able to msleep instead of horrid locked delays when resetting the HW,
+ *    but that read_lock() makes it impossible, unless I defer it's action to
+ *    the reset task, which means it'll be asynchronous (won't take effect until
+ *    the system schedules a bit).
+ *
+ *    Also, it would probably be possible to also remove most of the long-life
+ *    locking in open/resume code path (gem_reinit_chip) by beeing more careful
+ *    about when we can start taking interrupts or get xmit() called...
  */
 
 #include <linux/module.h>
@@ -109,6 +125,8 @@
 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
 	{ PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_K2_GMAC,
 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
+	{ PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_SH_SUNGEM,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
 	{0, }
 };
 
@@ -196,6 +214,33 @@
 	writel(GREG_STAT_NAPI | GREG_STAT_TXDONE, gp->regs + GREG_IMASK);
 }
 
+static void gem_get_cell(struct gem *gp)
+{
+	BUG_ON(gp->cell_enabled < 0);
+	gp->cell_enabled++;
+#ifdef CONFIG_PPC_PMAC
+	if (gp->cell_enabled == 1) {
+		mb();
+		pmac_call_feature(PMAC_FTR_GMAC_ENABLE, gp->of_node, 0, 1);
+		udelay(10);
+	}
+#endif /* CONFIG_PPC_PMAC */
+}
+
+/* Turn off the chip's clock */
+static void gem_put_cell(struct gem *gp)
+{
+	BUG_ON(gp->cell_enabled <= 0);
+	gp->cell_enabled--;
+#ifdef CONFIG_PPC_PMAC
+	if (gp->cell_enabled == 0) {
+		mb();
+		pmac_call_feature(PMAC_FTR_GMAC_ENABLE, gp->of_node, 0, 0);
+		udelay(10);
+	}
+#endif /* CONFIG_PPC_PMAC */
+}
+
 static void gem_handle_mif_event(struct gem *gp, u32 reg_val, u32 changed_bits)
 {
 	if (netif_msg_intr(gp))
@@ -319,7 +364,19 @@
 	u64 desc_dma;
 	u32 val;
 
-	/* First, reset MAC RX. */
+	/* First, reset & disable MAC RX. */
+	writel(MAC_RXRST_CMD, gp->regs + MAC_RXRST);
+	for (limit = 0; limit < 5000; limit++) {
+		if (!(readl(gp->regs + MAC_RXRST) & MAC_RXRST_CMD))
+			break;
+		udelay(10);
+	}
+	if (limit == 5000) {
+		printk(KERN_ERR "%s: RX MAC will not reset, resetting whole "
+                       "chip.\n", dev->name);
+		return 1;
+	}
+
 	writel(gp->mac_rx_cfg & ~MAC_RXCFG_ENAB,
 	       gp->regs + MAC_RXCFG);
 	for (limit = 0; limit < 5000; limit++) {
@@ -597,7 +654,7 @@
 	return 0;
 
 do_reset:
-	gp->reset_task_pending = 2;
+	gp->reset_task_pending = 1;
 	schedule_work(&gp->reset_task);
 
 	return 1;
@@ -823,6 +880,9 @@
 	struct gem *gp = dev->priv;
 	unsigned long flags;
 
+	/*
+	 * NAPI locking nightmare: See comment at head of driver 
+	 */
 	spin_lock_irqsave(&gp->lock, flags);
 
 	do {
@@ -874,8 +934,11 @@
 	struct gem *gp = dev->priv;
 	unsigned long flags;
 
-	/* Swallow interrupts when shutting the chip down */
-	if (!gp->hw_running)
+	/* Swallow interrupts when shutting the chip down, though
+	 * that shouldn't happen, we should have done free_irq() at
+	 * this point...
+	 */
+	if (!gp->running)
 		return IRQ_HANDLED;
 
 	spin_lock_irqsave(&gp->lock, flags);
@@ -916,7 +979,7 @@
 	struct gem *gp = dev->priv;
 
 	printk(KERN_ERR "%s: transmit timed out, resetting\n", dev->name);
-	if (!gp->hw_running) {
+	if (!gp->running) {
 		printk("%s: hrm.. hw not running !\n", dev->name);
 		return;
 	}
@@ -934,7 +997,7 @@
 	spin_lock_irq(&gp->lock);
 	spin_lock(&gp->tx_lock);
 
-	gp->reset_task_pending = 2;
+	gp->reset_task_pending = 1;
 	schedule_work(&gp->reset_task);
 
 	spin_unlock(&gp->tx_lock);
@@ -975,6 +1038,11 @@
 		local_irq_restore(flags);
 		return NETDEV_TX_LOCKED;
 	}
+	/* We raced with gem_do_stop() */
+	if (!gp->running) {
+		spin_unlock_irqrestore(&gp->tx_lock, flags);
+		return NETDEV_TX_BUSY;
+	}
 
 	/* This is a hard error, log it. */
 	if (TX_BUFFS_AVAIL(gp) <= (skb_shinfo(skb)->nr_frags + 1)) {
@@ -1073,46 +1141,10 @@
 	return NETDEV_TX_OK;
 }
 
-/* Jumbo-grams don't seem to work :-( */
-#define GEM_MIN_MTU	68
-#if 1
-#define GEM_MAX_MTU	1500
-#else
-#define GEM_MAX_MTU	9000
-#endif
-
-static int gem_change_mtu(struct net_device *dev, int new_mtu)
-{
-	struct gem *gp = dev->priv;
-
-	if (new_mtu < GEM_MIN_MTU || new_mtu > GEM_MAX_MTU)
-		return -EINVAL;
-
-	if (!netif_running(dev) || !netif_device_present(dev)) {
-		/* We'll just catch it later when the
-		 * device is up'd or resumed.
-		 */
-		dev->mtu = new_mtu;
-		return 0;
-	}
-
-	spin_lock_irq(&gp->lock);
-	spin_lock(&gp->tx_lock);
-	dev->mtu = new_mtu;
-	gp->reset_task_pending = 1;
-	schedule_work(&gp->reset_task);
-	spin_unlock(&gp->tx_lock);
-	spin_unlock_irq(&gp->lock);
-
-	flush_scheduled_work();
-
-	return 0;
-}
-
 #define STOP_TRIES 32
 
 /* Must be invoked under gp->lock and gp->tx_lock. */
-static void gem_stop(struct gem *gp)
+static void gem_reset(struct gem *gp)
 {
 	int limit;
 	u32 val;
@@ -1140,7 +1172,7 @@
 /* Must be invoked under gp->lock and gp->tx_lock. */
 static void gem_start_dma(struct gem *gp)
 {
-	unsigned long val;
+	u32 val;
 	
 	/* We are ready to rock, turn everything on. */
 	val = readl(gp->regs + TXDMA_CFG);
@@ -1155,10 +1187,31 @@
 	(void) readl(gp->regs + MAC_RXCFG);
 	udelay(100);
 
-	writel(GREG_STAT_TXDONE, gp->regs + GREG_IMASK);
+	gem_enable_ints(gp);
 
 	writel(RX_RING_SIZE - 4, gp->regs + RXDMA_KICK);
+}
+
+/* Must be invoked under gp->lock and gp->tx_lock. DMA won't be
+ * actually stopped before about 4ms tho ...
+ */
+static void gem_stop_dma(struct gem *gp)
+{
+	u32 val;
+
+	/* We are done rocking, turn everything off. */
+	val = readl(gp->regs + TXDMA_CFG);
+	writel(val & ~TXDMA_CFG_ENABLE, gp->regs + TXDMA_CFG);
+	val = readl(gp->regs + RXDMA_CFG);
+	writel(val & ~RXDMA_CFG_ENABLE, gp->regs + RXDMA_CFG);
+	val = readl(gp->regs + MAC_TXCFG);
+	writel(val & ~MAC_TXCFG_ENAB, gp->regs + MAC_TXCFG);
+	val = readl(gp->regs + MAC_RXCFG);
+	writel(val & ~MAC_RXCFG_ENAB, gp->regs + MAC_RXCFG);
+
+	(void) readl(gp->regs + MAC_RXCFG);
 
+	/* Need to wait a bit ... done by the caller */
 }
 
 
@@ -1219,10 +1272,10 @@
 	if (speed == 0)
 		speed = SPEED_10;
 	
-	/* If HW is down, we don't try to actually setup the PHY, we
+	/* If we are asleep, we don't try to actually setup the PHY, we
 	 * just store the settings
 	 */
-	if (!gp->hw_running) {
+	if (gp->asleep) {
 		gp->phy_mii.autoneg = gp->want_autoneg = autoneg;
 		gp->phy_mii.speed = speed;
 		gp->phy_mii.duplex = duplex;
@@ -1279,6 +1332,9 @@
 		printk(KERN_INFO "%s: Link is up at %d Mbps, %s-duplex.\n",
 			gp->dev->name, speed, (full_duplex ? "full" : "half"));
 
+	if (!gp->running)
+		return 0;
+
 	val = (MAC_TXCFG_EIPG0 | MAC_TXCFG_NGU);
 	if (full_duplex) {
 		val |= (MAC_TXCFG_ICS | MAC_TXCFG_ICOLL);
@@ -1405,48 +1461,19 @@
 	}
 }
 
-static void gem_init_rings(struct gem *);
-static void gem_init_hw(struct gem *, int);
-
-static void gem_reset_task(void *data)
-{
-	struct gem *gp = (struct gem *) data;
-
-	netif_poll_disable(gp->dev);
-	spin_lock_irq(&gp->lock);
-	spin_lock(&gp->tx_lock);
-
-	if (gp->hw_running && gp->opened) {
-		netif_stop_queue(gp->dev);
-
-		/* Reset the chip & rings */
-		gem_stop(gp);
-		gem_init_rings(gp);
-
-		gem_init_hw(gp,
-			    (gp->reset_task_pending == 2));
-
-		netif_wake_queue(gp->dev);
-	}
-	gp->reset_task_pending = 0;
-
-	spin_unlock(&gp->tx_lock);
-	spin_unlock_irq(&gp->lock);
-	netif_poll_enable(gp->dev);
-}
-
 static void gem_link_timer(unsigned long data)
 {
 	struct gem *gp = (struct gem *) data;
 	int restart_aneg = 0;
 		
-	if (!gp->hw_running)
+	if (gp->asleep)
 		return;
 
 	spin_lock_irq(&gp->lock);
 	spin_lock(&gp->tx_lock);
+	gem_get_cell(gp);
 
-	/* If the link of task is still pending, we just
+	/* If the reset task is still pending, we just
 	 * reschedule the link timer
 	 */
 	if (gp->reset_task_pending)
@@ -1462,8 +1489,7 @@
 		if ((val & PCS_MIISTAT_LS) != 0) {
 			gp->lstate = link_up;
 			netif_carrier_on(gp->dev);
-			if (gp->opened)
-				(void)gem_set_link_modes(gp);
+			(void)gem_set_link_modes(gp);
 		}
 		goto restart;
 	}
@@ -1484,7 +1510,7 @@
 		} else if (gp->lstate != link_up) {
 			gp->lstate = link_up;
 			netif_carrier_on(gp->dev);
-			if (gp->opened && gem_set_link_modes(gp))
+			if (gem_set_link_modes(gp))
 				restart_aneg = 1;
 		}
 	} else {
@@ -1497,7 +1523,7 @@
 				printk(KERN_INFO "%s: Link down\n",
 					gp->dev->name);
 			netif_carrier_off(gp->dev);
-			gp->reset_task_pending = 2;
+			gp->reset_task_pending = 1;
 			schedule_work(&gp->reset_task);
 			restart_aneg = 1;
 		} else if (++gp->timer_ticks > 10) {
@@ -1514,6 +1540,7 @@
 restart:
 	mod_timer(&gp->link_timer, jiffies + ((12 * HZ) / 10));
 out_unlock:
+	gem_put_cell(gp);
 	spin_unlock(&gp->tx_lock);
 	spin_unlock_irq(&gp->lock);
 }
@@ -1619,59 +1646,40 @@
 	wmb();
 }
 
-/* Must be invoked under gp->lock and gp->tx_lock. */
+/* Init PHY interface and start link poll state machine */
 static void gem_init_phy(struct gem *gp)
 {
 	u32 mifcfg;
-	
+
 	/* Revert MIF CFG setting done on stop_phy */
 	mifcfg = readl(gp->regs + MIF_CFG);
 	mifcfg &= ~MIF_CFG_BBMODE;
 	writel(mifcfg, gp->regs + MIF_CFG);
 	
-#ifdef CONFIG_PPC_PMAC
 	if (gp->pdev->vendor == PCI_VENDOR_ID_APPLE) {
-		int i, j;
+		int i;
 
 		/* Those delay sucks, the HW seem to love them though, I'll
 		 * serisouly consider breaking some locks here to be able
 		 * to schedule instead
 		 */
-		pmac_call_feature(PMAC_FTR_GMAC_PHY_RESET, gp->of_node, 0, 0);
-		for (j = 0; j < 3; j++) {
+		for (i = 0; i < 3; i++) {
+#ifdef CONFIG_PPC_PMAC
+			pmac_call_feature(PMAC_FTR_GMAC_PHY_RESET, gp->of_node, 0, 0);
+			msleep(20);
+#endif
 			/* Some PHYs used by apple have problem getting back to us,
-			 * we _know_ it's actually at addr 0 or 1, that's a hack, but
-			 * it helps to do that reset now. I suspect some motherboards
-			 * don't wire the PHY reset line properly, thus the PHY doesn't
-			 * come back with the above pmac_call_feature.
+			 * we do an additional reset here
 			 */
-			gp->mii_phy_addr = 0;
-			phy_write(gp, MII_BMCR, BMCR_RESET);
-			gp->mii_phy_addr = 1;
 			phy_write(gp, MII_BMCR, BMCR_RESET);
-			/* We should probably break some locks here and schedule... */
-			mdelay(10);
-			
-			/* On K2, we only probe the internal PHY at address 1, other
-			 * addresses tend to return garbage.
-			 */
-			if (gp->pdev->device == PCI_DEVICE_ID_APPLE_K2_GMAC)
+			msleep(20);
+			if (phy_read(gp, MII_BMCR) != 0xffff)
 				break;
-
-			for (i = 0; i < 32; i++) {
-				gp->mii_phy_addr = i;
-				if (phy_read(gp, MII_BMCR) != 0xffff)
-					break;
-			}
-			if (i == 32) {
+			if (i == 2)
 				printk(KERN_WARNING "%s: GMAC PHY not responding !\n",
 				       gp->dev->name);
-				gp->mii_phy_addr = 0;
-			} else
-				break;
 		}
 	}
-#endif /* CONFIG_PPC_PMAC */
 
 	if (gp->pdev->vendor == PCI_VENDOR_ID_SUN &&
 	    gp->pdev->device == PCI_DEVICE_ID_SUN_GEM) {
@@ -1755,6 +1763,16 @@
 			val |= PCS_SCTRL_LOOP;
 		writel(val, gp->regs + PCS_SCTRL);
 	}
+
+	/* Default aneg parameters */
+	gp->timer_ticks = 0;
+	gp->lstate = link_down;
+	netif_carrier_off(gp->dev);
+
+	/* Can I advertise gigabit here ? I'd need BCM PHY docs... */
+	spin_lock_irq(&gp->lock);
+	gem_begin_auto_negotiation(gp, NULL);
+	spin_unlock_irq(&gp->lock);
 }
 
 /* Must be invoked under gp->lock and gp->tx_lock. */
@@ -1796,8 +1814,7 @@
 }
 
 /* Must be invoked under gp->lock and gp->tx_lock. */
-static u32
-gem_setup_multicast(struct gem *gp)
+static u32 gem_setup_multicast(struct gem *gp)
 {
 	u32 rxcfg = 0;
 	int i;
@@ -1914,6 +1931,11 @@
 	 * make no use of those events other than to record them.
 	 */
 	writel(0xffffffff, gp->regs + MAC_MCMASK);
+
+	/* Don't enable GEM's WOL in normal operations
+	 */
+	if (gp->has_wol)
+		writel(0, gp->regs + WOL_WAKECSR);
 }
 
 /* Must be invoked under gp->lock and gp->tx_lock. */
@@ -1975,6 +1997,23 @@
 		gp->tx_fifo_sz = readl(gp->regs + TXDMA_FSZ) * 64;
 		gp->rx_fifo_sz = readl(gp->regs + RXDMA_FSZ) * 64;
 		gp->swrst_base = 0;
+
+		mif_cfg = readl(gp->regs + MIF_CFG);
+		mif_cfg &= ~(MIF_CFG_PSELECT|MIF_CFG_POLL|MIF_CFG_BBMODE|MIF_CFG_MDI1);
+		mif_cfg |= MIF_CFG_MDI0;
+		writel(mif_cfg, gp->regs + MIF_CFG);
+		writel(PCS_DMODE_MGM, gp->regs + PCS_DMODE);
+		writel(MAC_XIFCFG_OE, gp->regs + MAC_XIFCFG);
+
+		/* We hard-code the PHY address so we can properly bring it out of
+		 * reset later on, we can't really probe it at this point, though
+		 * that isn't an issue.
+		 */
+		if (gp->pdev->device == PCI_DEVICE_ID_APPLE_K2_GMAC)
+			gp->mii_phy_addr = 1;
+		else
+			gp->mii_phy_addr = 0;
+
 		return 0;
 	}
 
@@ -2053,68 +2092,28 @@
 }
 
 /* Must be invoked under gp->lock and gp->tx_lock. */
-static void gem_init_hw(struct gem *gp, int restart_link)
+static void gem_reinit_chip(struct gem *gp)
 {
-	/* On Apple's gmac, I initialize the PHY only after
-	 * setting up the chip. It appears the gigabit PHYs
-	 * don't quite like beeing talked to on the GII when
-	 * the chip is not running, I suspect it might not
-	 * be clocked at that point. --BenH
-	 */
-	if (restart_link)
-		gem_init_phy(gp);
-	gem_init_pause_thresholds(gp);
-	gem_init_dma(gp);
-	gem_init_mac(gp);
-
-	if (restart_link) {
-		/* Default aneg parameters */
-		gp->timer_ticks = 0;
-		gp->lstate = link_down;
-		netif_carrier_off(gp->dev);
-
-		/* Can I advertise gigabit here ? I'd need BCM PHY docs... */
-		gem_begin_auto_negotiation(gp, NULL);
-	} else {
-		if (gp->lstate == link_up) {
-			netif_carrier_on(gp->dev);
-			gem_set_link_modes(gp);
-		}
-	}
-}
+	/* Reset the chip */
+	gem_reset(gp);
 
-#ifdef CONFIG_PPC_PMAC
-/* Enable the chip's clock and make sure it's config space is
- * setup properly. There appear to be no need to restore the
- * base addresses.
- */
-static void gem_apple_powerup(struct gem *gp)
-{
-	u32 mif_cfg;
+	/* Make sure ints are disabled */
+	gem_disable_ints(gp);
 
-	mb();
-	pmac_call_feature(PMAC_FTR_GMAC_ENABLE, gp->of_node, 0, 1);
+	/* Allocate & setup ring buffers */
+	gem_init_rings(gp);
 
-	udelay(3);
-	
-	mif_cfg = readl(gp->regs + MIF_CFG);
-	mif_cfg &= ~(MIF_CFG_PSELECT|MIF_CFG_POLL|MIF_CFG_BBMODE|MIF_CFG_MDI1);
-	mif_cfg |= MIF_CFG_MDI0;
-	writel(mif_cfg, gp->regs + MIF_CFG);
-	writel(PCS_DMODE_MGM, gp->regs + PCS_DMODE);
-	writel(MAC_XIFCFG_OE, gp->regs + MAC_XIFCFG);
-}
+	/* Configure pause thresholds */
+	gem_init_pause_thresholds(gp);
 
-/* Turn off the chip's clock */
-static void gem_apple_powerdown(struct gem *gp)
-{
-	pmac_call_feature(PMAC_FTR_GMAC_ENABLE, gp->of_node, 0, 0);
+	/* Init DMA & MAC engines */
+	gem_init_dma(gp);
+	gem_init_mac(gp);
 }
 
-#endif /* CONFIG_PPC_PMAC */
 
 /* Must be invoked with no lock held. */
-static void gem_stop_phy(struct gem *gp)
+static void gem_stop_phy(struct gem *gp, int wol)
 {
 	u32 mifcfg;
 	unsigned long flags;
@@ -2131,8 +2130,22 @@
 	mifcfg &= ~MIF_CFG_POLL;
 	writel(mifcfg, gp->regs + MIF_CFG);
 
-	if (gp->wake_on_lan) {
-		/* Setup wake-on-lan */
+	if (wol && gp->has_wol) {
+		unsigned char *e = &gp->dev->dev_addr[0];
+		u32 csr;
+
+		/* Setup wake-on-lan for MAGIC packet */
+		writel(MAC_RXCFG_HFE | MAC_RXCFG_SFCS | MAC_RXCFG_ENAB,
+		       gp->regs + MAC_RXCFG);	
+		writel((e[4] << 8) | e[5], gp->regs + WOL_MATCH0);
+		writel((e[2] << 8) | e[3], gp->regs + WOL_MATCH1);
+		writel((e[0] << 8) | e[1], gp->regs + WOL_MATCH2);
+
+		writel(WOL_MCOUNT_N | WOL_MCOUNT_M, gp->regs + WOL_MCOUNT);
+		csr = WOL_WAKECSR_ENABLE;
+		if ((readl(gp->regs + MAC_XIFCFG) & MAC_XIFCFG_GMII) == 0)
+			csr |= WOL_WAKECSR_MII;
+		writel(csr, gp->regs + WOL_WAKECSR);
 	} else {
 		writel(0, gp->regs + MAC_RXCFG);
 		(void)readl(gp->regs + MAC_RXCFG);
@@ -2148,20 +2161,20 @@
 	writel(0, gp->regs + TXDMA_CFG);
 	writel(0, gp->regs + RXDMA_CFG);
 
-	if (!gp->wake_on_lan) {
+	if (!wol) {
 		spin_lock_irqsave(&gp->lock, flags);
 		spin_lock(&gp->tx_lock);
-		gem_stop(gp);
+		gem_reset(gp);
 		writel(MAC_TXRST_CMD, gp->regs + MAC_TXRST);
 		writel(MAC_RXRST_CMD, gp->regs + MAC_RXRST);
 		spin_unlock(&gp->tx_lock);
 		spin_unlock_irqrestore(&gp->lock, flags);
-	}
 
-	if (found_mii_phy(gp) && gp->phy_mii.def->ops->suspend)
-		gp->phy_mii.def->ops->suspend(&gp->phy_mii, 0 /* wake on lan options */);
+		/* No need to take the lock here */
+
+		if (found_mii_phy(gp) && gp->phy_mii.def->ops->suspend)
+			gp->phy_mii.def->ops->suspend(&gp->phy_mii);
 
-	if (!gp->wake_on_lan) {
 		/* According to Apple, we must set the MDIO pins to this begnign
 		 * state or we may 1) eat more current, 2) damage some PHYs
 		 */
@@ -2174,181 +2187,160 @@
 	}
 }
 
-/* Shut down the chip, must be called with pm_sem held.  */
-static void gem_shutdown(struct gem *gp)
+
+static int gem_do_start(struct net_device *dev)
 {
-	/* Make us not-running to avoid timers respawning
-	 * and swallow irqs 
-	 */
-	gp->hw_running = 0;
-	wmb();
+	struct gem *gp = dev->priv;
+	unsigned long flags;
 
-	/* Stop the link timer */
-	del_timer_sync(&gp->link_timer);
+	spin_lock_irqsave(&gp->lock, flags);
+	spin_lock(&gp->tx_lock);
 
-	/* Stop the reset task */
-	while (gp->reset_task_pending)
-		yield();
-	
-	/* Actually stop the chip */
-	if (gp->pdev->vendor == PCI_VENDOR_ID_APPLE) {
-		gem_stop_phy(gp);
+	/* Enable the cell */
+	gem_get_cell(gp);
 
-#ifdef CONFIG_PPC_PMAC
-		/* Power down the chip */
-		gem_apple_powerdown(gp);
-#endif /* CONFIG_PPC_PMAC */
-	} else{
-		unsigned long flags;
+	/* Init & setup chip hardware */
+	gem_reinit_chip(gp);
+
+	gp->running = 1;
+
+	if (gp->lstate == link_up) {
+		netif_carrier_on(gp->dev);
+		gem_set_link_modes(gp);
+	}
+
+	netif_wake_queue(gp->dev);
+
+	spin_unlock(&gp->tx_lock);
+	spin_unlock_irqrestore(&gp->lock, flags);
+
+	if (request_irq(gp->pdev->irq, gem_interrupt,
+				   SA_SHIRQ, dev->name, (void *)dev)) {
+		printk(KERN_ERR "%s: failed to request irq !\n", gp->dev->name);
 
 		spin_lock_irqsave(&gp->lock, flags);
 		spin_lock(&gp->tx_lock);
-		gem_stop(gp);
+
+		gp->running =  0;
+		gem_reset(gp);
+		gem_clean_rings(gp);
+		gem_put_cell(gp);
+		
 		spin_unlock(&gp->tx_lock);
 		spin_unlock_irqrestore(&gp->lock, flags);
+
+		return -EAGAIN;
 	}
+
+	return 0;
 }
 
-static void gem_pm_task(void *data)
+static void gem_do_stop(struct net_device *dev, int wol)
 {
-	struct gem *gp = (struct gem *) data;
+	struct gem *gp = dev->priv;
+	unsigned long flags;
 
-	/* We assume if we can't lock the pm_sem, then open() was
-	 * called again (or suspend()), and we can safely ignore
-	 * the PM request
-	 */
-	if (down_trylock(&gp->pm_sem))
-		return;
+	spin_lock_irqsave(&gp->lock, flags);
+	spin_lock(&gp->tx_lock);
 
-	/* Driver was re-opened or already shut down */
-	if (gp->opened || !gp->hw_running) {
-		up(&gp->pm_sem);
-		return;
-	}
+	gp->running = 0;
 
-	gem_shutdown(gp);
+	/* Stop netif queue */
+	netif_stop_queue(dev);
 
-	up(&gp->pm_sem);
-}
+	/* Make sure ints are disabled */
+	gem_disable_ints(gp);
 
-static void gem_pm_timer(unsigned long data)
-{
-	struct gem *gp = (struct gem *) data;
+	/* We can drop the lock now */
+	spin_unlock(&gp->tx_lock);
+	spin_unlock_irqrestore(&gp->lock, flags);
+
+	/* If we are going to sleep with WOL */
+	gem_stop_dma(gp);
+	msleep(10);
+	if (!wol)
+		gem_reset(gp);
+	msleep(10);
+
+	/* Get rid of rings */
+	gem_clean_rings(gp);
+
+	/* No irq needed anymore */
+	free_irq(gp->pdev->irq, (void *) dev);
 
-	schedule_work(&gp->pm_task);
+	/* Cell not needed neither if no WOL */
+	if (!wol) {
+		spin_lock_irqsave(&gp->lock, flags);
+		gem_put_cell(gp);
+		spin_unlock_irqrestore(&gp->lock, flags);
+	}
 }
 
-static int gem_open(struct net_device *dev)
+static void gem_reset_task(void *data)
 {
-	struct gem *gp = dev->priv;
-	int hw_was_up;
+	struct gem *gp = (struct gem *) data;
 
 	down(&gp->pm_sem);
 
-	hw_was_up = gp->hw_running;
+	netif_poll_disable(gp->dev);
 
-	/* Stop the PM timer/task */
-	del_timer(&gp->pm_timer);
-	flush_scheduled_work();
+	spin_lock_irq(&gp->lock);
+	spin_lock(&gp->tx_lock);
 
-	/* The power-management semaphore protects the hw_running
-	 * etc. state so it is safe to do this bit without gp->lock
-	 */
-	if (!gp->hw_running) {
-#ifdef CONFIG_PPC_PMAC
-		/* First, we need to bring up the chip */
-		if (gp->pdev->vendor == PCI_VENDOR_ID_APPLE) {
-			gem_apple_powerup(gp);
-			gem_check_invariants(gp);
-		}
-#endif /* CONFIG_PPC_PMAC */
+	if (gp->running == 0)
+		goto not_running;
 
-		/* Reset the chip */
-		spin_lock_irq(&gp->lock);
-		spin_lock(&gp->tx_lock);
-		gem_stop(gp);
-		spin_unlock(&gp->tx_lock);
-		spin_unlock_irq(&gp->lock);
+	if (gp->running) {
+		netif_stop_queue(gp->dev);
 
-		gp->hw_running = 1;
+		/* Reset the chip & rings */
+		gem_reinit_chip(gp);
+		if (gp->lstate == link_up)
+			gem_set_link_modes(gp);
+		netif_wake_queue(gp->dev);
 	}
+ not_running:
+	gp->reset_task_pending = 0;
 
-	/* We can now request the interrupt as we know it's masked
-	 * on the controller
-	 */
-	if (request_irq(gp->pdev->irq, gem_interrupt,
-			SA_SHIRQ, dev->name, (void *)dev)) {
-		printk(KERN_ERR "%s: failed to request irq !\n", gp->dev->name);
-
-		spin_lock_irq(&gp->lock);
-		spin_lock(&gp->tx_lock);
-#ifdef CONFIG_PPC_PMAC
-		if (!hw_was_up && gp->pdev->vendor == PCI_VENDOR_ID_APPLE)
-			gem_apple_powerdown(gp);
-#endif /* CONFIG_PPC_PMAC */
-		/* Fire the PM timer that will shut us down in about 10 seconds */
-		gp->pm_timer.expires = jiffies + 10*HZ;
-		add_timer(&gp->pm_timer);
-		up(&gp->pm_sem);
-		spin_unlock(&gp->tx_lock);
-		spin_unlock_irq(&gp->lock);
+	spin_unlock(&gp->tx_lock);
+	spin_unlock_irq(&gp->lock);
 
-		return -EAGAIN;
-	}
+	netif_poll_enable(gp->dev);
 
-       	spin_lock_irq(&gp->lock);
-	spin_lock(&gp->tx_lock);
+	up(&gp->pm_sem);
+}
 
-	/* Allocate & setup ring buffers */
-	gem_init_rings(gp);
 
-	/* Init & setup chip hardware */
-	gem_init_hw(gp, !hw_was_up);
+static int gem_open(struct net_device *dev)
+{
+	struct gem *gp = dev->priv;
+	int rc = 0;
 
-	gp->opened = 1;
+	down(&gp->pm_sem);
 
-	spin_unlock(&gp->tx_lock);
-	spin_unlock_irq(&gp->lock);
+	/* We need the cell enabled */
+	if (!gp->asleep)
+		rc = gem_do_start(dev);
+	gp->opened = (rc == 0);
 
 	up(&gp->pm_sem);
 
-	return 0;
+	return rc;
 }
 
 static int gem_close(struct net_device *dev)
 {
 	struct gem *gp = dev->priv;
 
-	/* Make sure we don't get distracted by suspend/resume */
-	down(&gp->pm_sem);
-
 	/* Note: we don't need to call netif_poll_disable() here because
 	 * our caller (dev_close) already did it for us
 	 */
 
-	/* Stop traffic, mark us closed */
-	spin_lock_irq(&gp->lock);
-	spin_lock(&gp->tx_lock);
+	down(&gp->pm_sem);
 
 	gp->opened = 0;	
-
-	netif_stop_queue(dev);
-
-	/* Stop chip */
-	gem_stop(gp);
-
-	/* Get rid of rings */
-	gem_clean_rings(gp);
-
-	/* Bye, the pm timer will finish the job */
-	free_irq(gp->pdev->irq, (void *) dev);
-
-	spin_unlock(&gp->tx_lock);
-	spin_unlock_irq(&gp->lock);
-
-	/* Fire the PM timer that will shut us down in about 10 seconds */
-	gp->pm_timer.expires = jiffies + 10*HZ;
-	add_timer(&gp->pm_timer);
+	if (!gp->asleep)
+		gem_do_stop(dev, 0);
 
 	up(&gp->pm_sem);
 	
@@ -2356,49 +2348,66 @@
 }
 
 #ifdef CONFIG_PM
-static int gem_suspend(struct pci_dev *pdev, u32 state)
+static int gem_suspend(struct pci_dev *pdev, pm_message_t state)
 {
 	struct net_device *dev = pci_get_drvdata(pdev);
 	struct gem *gp = dev->priv;
+	unsigned long flags;
 
-	netif_poll_disable(dev);
-
-	/* We hold the PM semaphore during entire driver
-	 * sleep time
-	 */
 	down(&gp->pm_sem);
 
+	netif_poll_disable(dev);
+
 	printk(KERN_INFO "%s: suspending, WakeOnLan %s\n",
-	       dev->name, gp->wake_on_lan ? "enabled" : "disabled");
+	       dev->name,
+	       (gp->wake_on_lan && gp->opened) ? "enabled" : "disabled");
 	
-	/* If the driver is opened, we stop the DMA */
-	if (gp->opened) {
-		spin_lock_irq(&gp->lock);
-		spin_lock(&gp->tx_lock);
+	/* Keep the cell enabled during the entire operation */
+	spin_lock_irqsave(&gp->lock, flags);
+	spin_lock(&gp->tx_lock);
+	gem_get_cell(gp);
+	spin_unlock(&gp->tx_lock);
+	spin_unlock_irqrestore(&gp->lock, flags);
 
+	/* If the driver is opened, we stop the MAC */
+	if (gp->opened) {
 		/* Stop traffic, mark us closed */
 		netif_device_detach(dev);
 
-		/* Stop chip */
-		gem_stop(gp);
+		/* Switch off MAC, remember WOL setting */
+		gp->asleep_wol = gp->wake_on_lan;
+		gem_do_stop(dev, gp->asleep_wol);
+	} else
+		gp->asleep_wol = 0;
 
-		/* Get rid of ring buffers */
-		gem_clean_rings(gp);
+	/* Mark us asleep */
+	gp->asleep = 1;
+	wmb();
 
-		spin_unlock(&gp->tx_lock);
-		spin_unlock_irq(&gp->lock);
+	/* Stop the link timer */
+	del_timer_sync(&gp->link_timer);
 
-		if (gp->pdev->vendor == PCI_VENDOR_ID_APPLE)
-			disable_irq(gp->pdev->irq);
-	}
+	/* Now we release the semaphore to not block the reset task who
+	 * can take it too. We are marked asleep, so there will be no
+	 * conflict here
+	 */
+	up(&gp->pm_sem);
 
-	if (gp->hw_running) {
-		/* Kill PM timer if any */
-		del_timer_sync(&gp->pm_timer);
-		flush_scheduled_work();
+	/* Wait for a pending reset task to complete */
+	while (gp->reset_task_pending)
+		yield();
+	flush_scheduled_work();
 
-		gem_shutdown(gp);
-	}
+	/* Shut the PHY down eventually and setup WOL */
+	gem_stop_phy(gp, gp->asleep_wol);
+
+	/* Make sure bus master is disabled */
+	pci_disable_device(gp->pdev);
+
+	/* Release the cell, no need to take a lock at this point since
+	 * nothing else can happen now
+	 */
+	gem_put_cell(gp);
 
 	return 0;
 }
@@ -2407,36 +2416,74 @@
 {
 	struct net_device *dev = pci_get_drvdata(pdev);
 	struct gem *gp = dev->priv;
+	unsigned long flags;
 
 	printk(KERN_INFO "%s: resuming\n", dev->name);
 
-	if (gp->opened) {
-#ifdef CONFIG_PPC_PMAC
-		/* First, we need to bring up the chip */
-		if (gp->pdev->vendor == PCI_VENDOR_ID_APPLE) {
-			gem_apple_powerup(gp);
-			gem_check_invariants(gp);
-		}
-#endif /* CONFIG_PPC_PMAC */
-		spin_lock_irq(&gp->lock);
-		spin_lock(&gp->tx_lock);
+	down(&gp->pm_sem);
 
-		gem_stop(gp);
-		gp->hw_running = 1;
-		gem_init_rings(gp);
-		gem_init_hw(gp, 1);
+	/* Keep the cell enabled during the entire operation, no need to
+	 * take a lock here tho since nothing else can happen while we are
+	 * marked asleep
+	 */
+	gem_get_cell(gp);
+
+	/* Make sure PCI access and bus master are enabled */
+	if (pci_enable_device(gp->pdev)) {
+		printk(KERN_ERR "%s: Can't re-enable chip !\n",
+		       dev->name);
+		/* Put cell and forget it for now, it will be considered as
+		 * still asleep, a new sleep cycle may bring it back
+		 */
+		gem_put_cell(gp);
+		up(&gp->pm_sem);
+		return 0;
+	}
+	pci_set_master(gp->pdev);
 
-		spin_unlock(&gp->tx_lock);
-		spin_unlock_irq(&gp->lock);
+	/* Reset everything */
+	gem_reset(gp);
 
+	/* Mark us woken up */
+	gp->asleep = 0;
+	wmb();
+
+	/* Bring the PHY back. Again, lock is useless at this point as
+	 * nothing can be happening until we restart the whole thing
+	 */
+	gem_init_phy(gp);
+
+	/* If we were opened, bring everything back */
+	if (gp->opened) {
+		/* Restart MAC */
+		gem_do_start(dev);
+
+		/* Re-attach net device */
 		netif_device_attach(dev);
-		if (gp->pdev->vendor == PCI_VENDOR_ID_APPLE)
-			enable_irq(gp->pdev->irq);
+
 	}
-	up(&gp->pm_sem);
+
+	spin_lock_irqsave(&gp->lock, flags);
+	spin_lock(&gp->tx_lock);
+
+	/* If we had WOL enabled, the cell clock was never turned off during
+	 * sleep, so we end up beeing unbalanced. Fix that here
+	 */
+	if (gp->asleep_wol)
+		gem_put_cell(gp);
+
+	/* This function doesn't need to hold the cell, it will be held if the
+	 * driver is open by gem_do_start().
+	 */
+	gem_put_cell(gp);
+
+	spin_unlock(&gp->tx_lock);
+	spin_unlock_irqrestore(&gp->lock, flags);
 
 	netif_poll_enable(dev);
 	
+	up(&gp->pm_sem);
+
 	return 0;
 }
 #endif /* CONFIG_PM */
@@ -2449,7 +2496,10 @@
 	spin_lock_irq(&gp->lock);
 	spin_lock(&gp->tx_lock);
 
-	if (gp->hw_running) {
+	/* I have seen this being called while the PM was in progress,
+	 * so we shield against this
+	 */
+	if (gp->running) {
 		stats->rx_crc_errors += readl(gp->regs + MAC_FCSERR);
 		writel(0, gp->regs + MAC_FCSERR);
 
@@ -2479,12 +2529,13 @@
 	u32 rxcfg, rxcfg_new;
 	int limit = 10000;
 	
-	if (!gp->hw_running)
-		return;
-		
+
 	spin_lock_irq(&gp->lock);
 	spin_lock(&gp->tx_lock);
 
+	if (!gp->running)
+		goto bail;
+
 	netif_stop_queue(dev);
 
 	rxcfg = readl(gp->regs + MAC_RXCFG);
@@ -2508,8 +2559,48 @@
 
 	netif_wake_queue(dev);
 
+ bail:
+	spin_unlock(&gp->tx_lock);
+	spin_unlock_irq(&gp->lock);
+}
+
+/* Jumbo-grams don't seem to work :-( */
+#define GEM_MIN_MTU	68
+#if 1
+#define GEM_MAX_MTU	1500
+#else
+#define GEM_MAX_MTU	9000
+#endif
+
+static int gem_change_mtu(struct net_device *dev, int new_mtu)
+{
+	struct gem *gp = dev->priv;
+
+	if (new_mtu < GEM_MIN_MTU || new_mtu > GEM_MAX_MTU)
+		return -EINVAL;
+
+	if (!netif_running(dev) || !netif_device_present(dev)) {
+		/* We'll just catch it later when the
+		 * device is up'd or resumed.
+		 */
+		dev->mtu = new_mtu;
+		return 0;
+	}
+
+	down(&gp->pm_sem);
+	spin_lock_irq(&gp->lock);
+	spin_lock(&gp->tx_lock);
+	dev->mtu = new_mtu;
+	if (gp->running) {
+		gem_reinit_chip(gp);
+		if (gp->lstate == link_up)
+			gem_set_link_modes(gp);
+	}
 	spin_unlock(&gp->tx_lock);
 	spin_unlock_irq(&gp->lock);
+	up(&gp->pm_sem);
+
+	return 0;
 }
 
 static void gem_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
@@ -2540,7 +2631,6 @@
 
 		/* Return current PHY settings */
 		spin_lock_irq(&gp->lock);
-		spin_lock(&gp->tx_lock);
 		cmd->autoneg = gp->want_autoneg;
 		cmd->speed = gp->phy_mii.speed;
 		cmd->duplex = gp->phy_mii.duplex;			
@@ -2552,7 +2642,6 @@
 		 */
 		if (cmd->advertising == 0)
 			cmd->advertising = cmd->supported;
-		spin_unlock(&gp->tx_lock);
 		spin_unlock_irq(&gp->lock);
 	} else { // XXX PCS ?
 		cmd->supported =
@@ -2592,9 +2681,9 @@
 	      
 	/* Apply settings and restart link process. */
 	spin_lock_irq(&gp->lock);
-	spin_lock(&gp->tx_lock);
+	gem_get_cell(gp);
 	gem_begin_auto_negotiation(gp, cmd);
-	spin_unlock(&gp->tx_lock);
+	gem_put_cell(gp);
 	spin_unlock_irq(&gp->lock);
 
 	return 0;
@@ -2609,9 +2698,9 @@
 
 	/* Restart link process. */
 	spin_lock_irq(&gp->lock);
-	spin_lock(&gp->tx_lock);
+	gem_get_cell(gp);
 	gem_begin_auto_negotiation(gp, NULL);
-	spin_unlock(&gp->tx_lock);
+	gem_put_cell(gp);
 	spin_unlock_irq(&gp->lock);
 
 	return 0;
@@ -2628,7 +2717,37 @@
 	struct gem *gp = dev->priv;
 	gp->msg_enable = value;
 }
-  
+
+
+/* Add more when I understand how to program the chip */
+/* like WAKE_UCAST | WAKE_MCAST | WAKE_BCAST */
+
+#define WOL_SUPPORTED_MASK	(WAKE_MAGIC)
+
+static void gem_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
+{
+	struct gem *gp = dev->priv;
+
+	/* Add more when I understand how to program the chip */
+	if (gp->has_wol) {
+		wol->supported = WOL_SUPPORTED_MASK;
+		wol->wolopts = gp->wake_on_lan;
+	} else {
+		wol->supported = 0;
+		wol->wolopts = 0;
+	}
+}
+
+static int gem_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
+{
+	struct gem *gp = dev->priv;
+
+	if (!gp->has_wol)
+		return -EOPNOTSUPP;
+	gp->wake_on_lan = wol->wolopts & WOL_SUPPORTED_MASK;
+	return 0;
+}
+
 static struct ethtool_ops gem_ethtool_ops = {
 	.get_drvinfo		= gem_get_drvinfo,
 	.get_link		= ethtool_op_get_link,
@@ -2637,6 +2756,8 @@
 	.nway_reset		= gem_nway_reset,
 	.get_msglevel		= gem_get_msglevel,
 	.set_msglevel		= gem_set_msglevel,
+	.get_wol		= gem_get_wol,
+	.set_wol		= gem_set_wol,
 };
 
 static int gem_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
@@ -2644,22 +2765,28 @@
 	struct gem *gp = dev->priv;
 	struct mii_ioctl_data *data = if_mii(ifr);
 	int rc = -EOPNOTSUPP;
-	
+	unsigned long flags;
+
 	/* Hold the PM semaphore while doing ioctl's or we may collide
-	 * with open/close and power management and oops.
+	 * with power management.
 	 */
 	down(&gp->pm_sem);
-	
+		
+	spin_lock_irqsave(&gp->lock, flags);
+	gem_get_cell(gp);
+	spin_unlock_irqrestore(&gp->lock, flags);
+
 	switch (cmd) {
 	case SIOCGMIIPHY:		/* Get address of MII PHY in use. */
 		data->phy_id = gp->mii_phy_addr;
 		/* Fallthrough... */
 
 	case SIOCGMIIREG:		/* Read MII PHY register. */
-		if (!gp->hw_running)
-			rc = -EIO;
+		if (!gp->running)
+			rc = -EAGAIN;
 		else {
-			data->val_out = __phy_read(gp, data->phy_id & 0x1f, data->reg_num & 0x1f);
+			data->val_out = __phy_read(gp, data->phy_id & 0x1f,
+						   data->reg_num & 0x1f);
 			rc = 0;
 		}
 		break;
@@ -2667,14 +2794,19 @@
 	case SIOCSMIIREG:		/* Write MII PHY register. */
 		if (!capable(CAP_NET_ADMIN))
 			rc = -EPERM;
-		else if (!gp->hw_running)
-			rc = -EIO;
+		else if (!gp->running)
+			rc = -EAGAIN;
 		else {
-			__phy_write(gp, data->phy_id & 0x1f, data->reg_num & 0x1f, data->val_in);
+			__phy_write(gp, data->phy_id & 0x1f, data->reg_num & 0x1f,
+				    data->val_in);
 			rc = 0;
 		}
 		break;
 	};
+	
+	spin_lock_irqsave(&gp->lock, flags);
+	gem_put_cell(gp);
+	spin_unlock_irqrestore(&gp->lock, flags);
 
 	up(&gp->pm_sem);
 	
@@ -2779,6 +2911,47 @@
 	return 0;
 }
 
+static void __devexit gem_remove_one(struct pci_dev *pdev)
+{
+	struct net_device *dev = pci_get_drvdata(pdev);
+
+	if (dev) {
+		struct gem *gp = dev->priv;
+
+		unregister_netdev(dev);
+
+		/* Stop the link timer */
+		del_timer_sync(&gp->link_timer);
+
+		/* We shouldn't need any locking here */
+		gem_get_cell(gp);
+
+		/* Wait for a pending reset task to complete */
+		while (gp->reset_task_pending)
+			yield();
+		flush_scheduled_work();
+
+		/* Shut the PHY down */
+		gem_stop_phy(gp, 0);
+
+		gem_put_cell(gp);
+
+		/* Make sure bus master is disabled */
+		pci_disable_device(gp->pdev);
+
+		/* Free resources */
+		pci_free_consistent(pdev,
+				    sizeof(struct gem_init_block),
+				    gp->init_block,
+				    gp->gblock_dvma);
+		iounmap(gp->regs);
+		pci_release_regions(pdev);
+		free_netdev(dev);
+
+		pci_set_drvdata(pdev, NULL);
+	}
+}
+
 static int __devinit gem_init_one(struct pci_dev *pdev,
 				  const struct pci_device_id *ent)
 {
@@ -2827,7 +3000,7 @@
 		}
 		pci_using_dac = 0;
 	}
-
+	
 	gemreg_base = pci_resource_start(pdev, 0);
 	gemreg_len = pci_resource_len(pdev, 0);
 
@@ -2870,11 +3043,6 @@
 	gp->link_timer.function = gem_link_timer;
 	gp->link_timer.data = (unsigned long) gp;
 
-	init_timer(&gp->pm_timer);
-	gp->pm_timer.function = gem_pm_timer;
-	gp->pm_timer.data = (unsigned long) gp;
-
-	INIT_WORK(&gp->pm_task, gem_pm_task, gp);
 	INIT_WORK(&gp->reset_task, gem_reset_task, gp);
 	
 	gp->lstate = link_down;
@@ -2889,20 +3057,22 @@
 		goto err_out_free_res;
 	}
 
-	/* On Apple, we power the chip up now in order for check
-	 * invariants to work, but also because the firmware might
-	 * not have properly shut down the PHY.
+	/* On Apple, we want a reference to the Open Firmware device-tree
+	 * node. We use it for clock control.
 	 */
 #ifdef CONFIG_PPC_PMAC
 	gp->of_node = pci_device_to_OF_node(pdev);
-	if (pdev->vendor == PCI_VENDOR_ID_APPLE)
-		gem_apple_powerup(gp);
 #endif
-	spin_lock_irq(&gp->lock);
-	spin_lock(&gp->tx_lock);
-	gem_stop(gp);
-	spin_unlock(&gp->tx_lock);
-	spin_unlock_irq(&gp->lock);
+
+	/* Only Apple version supports WOL afaik */
+	if (pdev->vendor == PCI_VENDOR_ID_APPLE)
+		gp->has_wol = 1;
+
+	/* Make sure cell is enabled */
+	gem_get_cell(gp);
+
+	/* Make sure everything is stopped and in init state */
+	gem_reset(gp);
 
 	/* Fill up the mii_phy structure (even if we won't use it) */
 	gp->phy_mii.dev = dev;
@@ -2911,7 +3081,8 @@
 
 	/* By default, we start with autoneg */
 	gp->want_autoneg = 1;
-	
+
+	/* Check fifo sizes, PHY type, etc... */
 	if (gem_check_invariants(gp)) {
 		err = -ENODEV;
 		goto err_out_iounmap;
@@ -2951,6 +3122,19 @@
 	dev->poll_controller = gem_poll_controller;
 #endif
 
+	/* Set that now, in case PM kicks in now */
+	pci_set_drvdata(pdev, dev);
+
+	/* Detect & init PHY, start autoneg, we release the cell now
+	 * too, it will be managed by whoever needs it
+	 */
+	gem_init_phy(gp);
+
+	spin_lock_irq(&gp->lock);
+	gem_put_cell(gp);
+	spin_unlock_irq(&gp->lock);
+
+	/* Register with kernel */
 	if (register_netdev(dev)) {
 		printk(KERN_ERR PFX "Cannot register net device, "
 		       "aborting.\n");
@@ -2965,48 +3149,22 @@
 		       i == 5 ? ' ' : ':');
 	printk("\n");
 
-	/* Detect & init PHY, start autoneg */
-	spin_lock_irq(&gp->lock);
-	spin_lock(&gp->tx_lock);
-	gp->hw_running = 1;
-	gem_init_phy(gp);
-	gem_begin_auto_negotiation(gp, NULL);
-	spin_unlock(&gp->tx_lock);
-	spin_unlock_irq(&gp->lock);
-
 	if (gp->phy_type == phy_mii_mdio0 ||
      	    gp->phy_type == phy_mii_mdio1)
 		printk(KERN_INFO "%s: Found %s PHY\n", dev->name, 
 			gp->phy_mii.def ? gp->phy_mii.def->name : "no");
 
-	pci_set_drvdata(pdev, dev);
-
 	/* GEM can do it all... */
 	dev->features |= NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_LLTX;
 	if (pci_using_dac)
 		dev->features |= NETIF_F_HIGHDMA;
 
-	/* Fire the PM timer that will shut us down in about 10 seconds */
-	gp->pm_timer.expires = jiffies + 10*HZ;
-	add_timer(&gp->pm_timer);
-
 	return 0;
 
 err_out_free_consistent:
-	pci_free_consistent(pdev,
-			    sizeof(struct gem_init_block),
-			    gp->init_block,
-			    gp->gblock_dvma);
-
+	gem_remove_one(pdev);
 err_out_iounmap:
-	down(&gp->pm_sem);
-	/* Stop the PM timer & task */
-	del_timer_sync(&gp->pm_timer);
-	flush_scheduled_work();
-	if (gp->hw_running)
-		gem_shutdown(gp);
-	up(&gp->pm_sem);
-
+	gem_put_cell(gp);
 	iounmap(gp->regs);
 
 err_out_free_res:
@@ -3020,34 +3178,6 @@
 
 }
 
-static void __devexit gem_remove_one(struct pci_dev *pdev)
-{
-	struct net_device *dev = pci_get_drvdata(pdev);
-
-	if (dev) {
-		struct gem *gp = dev->priv;
-
-		unregister_netdev(dev);
-
-		down(&gp->pm_sem);
-		/* Stop the PM timer & task */
-		del_timer_sync(&gp->pm_timer);
-		flush_scheduled_work();
-		if (gp->hw_running)
-			gem_shutdown(gp);
-		up(&gp->pm_sem);
-
-		pci_free_consistent(pdev,
-				    sizeof(struct gem_init_block),
-				    gp->init_block,
-				    gp->gblock_dvma);
-		iounmap(gp->regs);
-		pci_release_regions(pdev);
-		free_netdev(dev);
-
-		pci_set_drvdata(pdev, NULL);
-	}
-}
 
 static struct pci_driver gem_driver = {
 	.name		= GEM_MODULE_NAME,
diff -Nru a/drivers/net/sungem.h b/drivers/net/sungem.h
--- a/drivers/net/sungem.h	2005-03-11 12:51:46 -08:00
+++ b/drivers/net/sungem.h	2005-03-11 12:51:46 -08:00
@@ -170,6 +170,27 @@
  * them later. -DaveM
  */
 
+/* WakeOnLan Registers	*/
+#define WOL_MATCH0	0x3000UL
+#define WOL_MATCH1	0x3004UL
+#define WOL_MATCH2	0x3008UL
+#define WOL_MCOUNT	0x300CUL
+#define WOL_WAKECSR	0x3010UL
+
+/* WOL Match count register
+ */
+#define WOL_MCOUNT_N		0x00000010
+#define WOL_MCOUNT_M		0x00000000 /* 0 << 8 */
+
+#define WOL_WAKECSR_ENABLE	0x00000001
+#define WOL_WAKECSR_MII		0x00000002
+#define WOL_WAKECSR_SEEN	0x00000004
+#define WOL_WAKECSR_FILT_UCAST	0x00000008
+#define WOL_WAKECSR_FILT_MCAST	0x00000010
+#define WOL_WAKECSR_FILT_BCAST	0x00000020
+#define WOL_WAKECSR_FILT_SEEN	0x00000040
+
+
 /* Receive DMA Registers */
 #define RXDMA_CFG	0x4000UL	/* RX Configuration Register	*/
 #define RXDMA_DBLOW	0x4004UL	/* RX Descriptor Base Low	*/
@@ -952,45 +973,38 @@
 };
 
 struct gem {
-	spinlock_t lock;
-	spinlock_t tx_lock;
-	void __iomem *regs;
-	int rx_new, rx_old;
-	int tx_new, tx_old;
-
-	/* Set when chip is actually in operational state
-	 * (ie. not power managed)
-	 */
-	int hw_running;
-	int opened;
-	struct semaphore pm_sem;
-	struct work_struct pm_task;
-	struct timer_list pm_timer;
-
-	struct gem_init_block *init_block;
-
-	struct sk_buff *rx_skbs[RX_RING_SIZE];
-	struct sk_buff *tx_skbs[RX_RING_SIZE];
+	spinlock_t		lock;
+	spinlock_t		tx_lock;
+	void __iomem		*regs;
+	int			rx_new, rx_old;
+	int			tx_new, tx_old;
+
+	unsigned int has_wol : 1;	/* chip supports wake-on-lan */
+	unsigned int asleep : 1;	/* chip asleep, protected by pm_sem */
+	unsigned int asleep_wol : 1;	/* was asleep with WOL enabled */
+	unsigned int opened : 1;	/* driver opened, protected by pm_sem */
+	unsigned int running : 1;	/* chip running, protected by lock */
+	
+	/* cell enable count, protected by lock */
+	int			cell_enabled;  
+	
+	struct semaphore	pm_sem;
 
 	u32			msg_enable;
 	u32			status;
 
 	struct net_device_stats net_stats;
 
-	enum gem_phy_type	phy_type;
-	struct mii_phy		phy_mii;
-	
 	int			tx_fifo_sz;
 	int			rx_fifo_sz;
 	int			rx_pause_off;
 	int			rx_pause_on;
 	int			rx_buf_sz;
-	int			mii_phy_addr;
-
+	u64			pause_entered;
+	u16			pause_last_time_recvd;
 	u32			mac_rx_cfg;
 	u32			swrst_base;
 
-	/* Autoneg & PHY control */
 	int			want_autoneg;
 	int			last_forced_speed;
 	enum link_state		lstate;
@@ -999,14 +1013,18 @@
 	int			wake_on_lan;
 	struct work_struct	reset_task;
 	volatile int		reset_task_pending;
-	
-	/* Diagnostic counters and state. */
-	u64			pause_entered;
-	u16			pause_last_time_recvd;
 
-	dma_addr_t gblock_dvma;
-	struct pci_dev *pdev;
-	struct net_device *dev;
+	enum gem_phy_type	phy_type;
+	struct mii_phy		phy_mii;
+	int			mii_phy_addr;
+		
+	struct gem_init_block	*init_block;
+	struct sk_buff		*rx_skbs[RX_RING_SIZE];
+	struct sk_buff		*tx_skbs[RX_RING_SIZE];
+	dma_addr_t		gblock_dvma;
+
+	struct pci_dev		*pdev;
+	struct net_device	*dev;
 #ifdef CONFIG_PPC_PMAC
 	struct device_node	*of_node;
 #endif
diff -Nru a/drivers/net/sungem_phy.c b/drivers/net/sungem_phy.c
--- a/drivers/net/sungem_phy.c	2005-03-11 12:51:42 -08:00
+++ b/drivers/net/sungem_phy.c	2005-03-11 12:51:42 -08:00
@@ -98,25 +98,15 @@
 	data &= ~MII_BCM5201_MULTIPHY_SUPERISOLATE;
 	phy_write(phy, MII_BCM5201_MULTIPHY, data);
 
+	phy_write(phy, MII_BCM5201_INTERRUPT, 0);
+
 	return 0;
 }
 
-static int bcm5201_suspend(struct mii_phy* phy, int wol_options)
+static int bcm5201_suspend(struct mii_phy* phy)
 {
-	if (!wol_options)
-		phy_write(phy, MII_BCM5201_INTERRUPT, 0);
-
-	/* Here's a strange hack used by both MacOS 9 and X */
-	phy_write(phy, MII_LPA, phy_read(phy, MII_LPA));
-	
-	if (!wol_options) {
-#if 0 /* Commented out in Darwin... someone has those dawn docs ? */
-		u16 val = phy_read(phy, MII_BCM5201_AUXMODE2)
-		phy_write(phy, MII_BCM5201_AUXMODE2,
-			  val & ~MII_BCM5201_AUXMODE2_LOWPOWER);
-#endif			
-		phy_write(phy, MII_BCM5201_MULTIPHY, MII_BCM5201_MULTIPHY_SUPERISOLATE);
-	}
+	phy_write(phy, MII_BCM5201_INTERRUPT, 0);
+	phy_write(phy, MII_BCM5201_MULTIPHY, MII_BCM5201_MULTIPHY_SUPERISOLATE);
 
 	return 0;
 }
@@ -144,6 +134,21 @@
 	return 0;
 }
 
+static int bcm5221_suspend(struct mii_phy* phy)
+{
+	u16 data;
+
+	data = phy_read(phy, MII_BCM5221_TEST);
+	phy_write(phy, MII_BCM5221_TEST,
+		data | MII_BCM5221_TEST_ENABLE_SHADOWS);
+
+	data = phy_read(phy, MII_BCM5221_SHDOW_AUX_MODE4);
+	phy_write(phy, MII_BCM5221_SHDOW_AUX_MODE4,
+		  data | MII_BCM5221_SHDOW_AUX_MODE4_IDDQMODE);
+
+	return 0;
+}
+
 static int bcm5400_init(struct mii_phy* phy)
 {
 	u16 data;
@@ -173,7 +178,7 @@
 	return 0;
 }
 
-static int bcm5400_suspend(struct mii_phy* phy, int wol_options)
+static int bcm5400_suspend(struct mii_phy* phy)
 {
 #if 0 /* Commented out in Darwin... someone has those dawn docs ? */
 	phy_write(phy, MII_BMCR, BMCR_PDOWN);
@@ -229,7 +234,7 @@
 	return 0;
 }
 
-static int bcm5401_suspend(struct mii_phy* phy, int wol_options)
+static int bcm5401_suspend(struct mii_phy* phy)
 {
 #if 0 /* Commented out in Darwin... someone has those dawn docs ? */
 	phy_write(phy, MII_BMCR, BMCR_PDOWN);
@@ -266,7 +271,7 @@
 	return 0;
 }
 
-static int bcm5411_suspend(struct mii_phy* phy, int wol_options)
+static int bcm5411_suspend(struct mii_phy* phy)
 {
 	phy_write(phy, MII_BMCR, BMCR_PDOWN);
 
@@ -662,7 +667,7 @@
 
 /* Broadcom BCM 5221 */
 static struct mii_phy_ops bcm5221_phy_ops = {
-	.suspend	= bcm5201_suspend,
+	.suspend	= bcm5221_suspend,
 	.init		= bcm5221_init,
 	.setup_aneg	= genmii_setup_aneg,
 	.setup_forced	= genmii_setup_forced,
diff -Nru a/drivers/net/sungem_phy.h b/drivers/net/sungem_phy.h
--- a/drivers/net/sungem_phy.h	2005-03-11 12:51:47 -08:00
+++ b/drivers/net/sungem_phy.h	2005-03-11 12:51:47 -08:00
@@ -7,7 +7,7 @@
 struct mii_phy_ops
 {
 	int		(*init)(struct mii_phy *phy);
-	int		(*suspend)(struct mii_phy *phy, int wol_options);
+	int		(*suspend)(struct mii_phy *phy);
 	int		(*setup_aneg)(struct mii_phy *phy, u32 advertise);
 	int		(*setup_forced)(struct mii_phy *phy, int speed, int fd);
 	int		(*poll_link)(struct mii_phy *phy);
@@ -80,6 +80,7 @@
 #define MII_BCM5221_SHDOW_AUX_STAT2		0x1b
 #define MII_BCM5221_SHDOW_AUX_STAT2_APD		0x0020
 #define MII_BCM5221_SHDOW_AUX_MODE4		0x1a
+#define MII_BCM5221_SHDOW_AUX_MODE4_IDDQMODE	0x0001
 #define MII_BCM5221_SHDOW_AUX_MODE4_CLKLOPWR	0x0004
 
 /* MII BCM5400 1000-BASET Control register */
diff -Nru a/drivers/net/sunhme.c b/drivers/net/sunhme.c
--- a/drivers/net/sunhme.c	2005-03-11 12:51:42 -08:00
+++ b/drivers/net/sunhme.c	2005-03-11 12:51:42 -08:00
@@ -175,13 +175,13 @@
 #define DEFAULT_IPG2       4 /* For all modes */
 #define DEFAULT_JAMSIZE    4 /* Toe jam */
 
-#ifdef CONFIG_PCI
+#if defined(CONFIG_PCI) && defined(MODULE)
 /* This happy_pci_ids is declared __initdata because it is only used
    as an advisory to depmod.  If this is ported to the new PCI interface
    where it could be referenced at any time due to hot plugging,
    the __initdata reference should be removed. */
 
-struct pci_device_id happymeal_pci_ids[] = {
+static struct pci_device_id happymeal_pci_ids[] = {
 	{
 	  .vendor	= PCI_VENDOR_ID_SUN,
 	  .device	= PCI_DEVICE_ID_SUN_HAPPYMEAL,
diff -Nru a/drivers/net/tg3.c b/drivers/net/tg3.c
--- a/drivers/net/tg3.c	2005-03-11 12:51:46 -08:00
+++ b/drivers/net/tg3.c	2005-03-11 12:51:46 -08:00
@@ -60,8 +60,8 @@
 
 #define DRV_MODULE_NAME		"tg3"
 #define PFX DRV_MODULE_NAME	": "
-#define DRV_MODULE_VERSION	"3.23"
-#define DRV_MODULE_RELDATE	"February 15, 2005"
+#define DRV_MODULE_VERSION	"3.24"
+#define DRV_MODULE_RELDATE	"March 4, 2005"
 
 #define TG3_DEF_MAC_MODE	0
 #define TG3_DEF_RX_MODE		0
@@ -3110,6 +3110,12 @@
 	    (mss = skb_shinfo(skb)->tso_size) != 0) {
 		int tcp_opt_len, ip_tcp_len;
 
+		if (skb_header_cloned(skb) &&
+		    pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) {
+			dev_kfree_skb(skb);
+			goto out_unlock;
+		}
+
 		tcp_opt_len = ((skb->h.th->doff - 5) * 4);
 		ip_tcp_len = (skb->nh.iph->ihl * 4) + sizeof(struct tcphdr);
 
@@ -3697,8 +3703,9 @@
 /* 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_SUN_570X))
+		tg3_write_mem(tp, NIC_SRAM_FIRMWARE_MBOX,
+			      NIC_SRAM_FIRMWARE_MBOX_MAGIC1);
 
 	if (tp->tg3_flags2 & TG3_FLG2_ASF_NEW_HANDSHAKE) {
 		switch (kind) {
@@ -3902,19 +3909,20 @@
 		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_570X)) {
-		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_SUN_570X)) {
+		/* 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) {
+			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) &&
@@ -7829,6 +7837,19 @@
 
 static int __devinit tg3_get_invariants(struct tg3 *tp)
 {
+	static struct pci_device_id write_reorder_chipsets[] = {
+		{ PCI_DEVICE(PCI_VENDOR_ID_INTEL,
+		             PCI_DEVICE_ID_INTEL_82801AA_8) },
+		{ PCI_DEVICE(PCI_VENDOR_ID_INTEL,
+		             PCI_DEVICE_ID_INTEL_82801AB_8) },
+		{ PCI_DEVICE(PCI_VENDOR_ID_INTEL,
+		             PCI_DEVICE_ID_INTEL_82801BA_11) },
+		{ PCI_DEVICE(PCI_VENDOR_ID_INTEL,
+		             PCI_DEVICE_ID_INTEL_82801BA_6) },
+		{ PCI_DEVICE(PCI_VENDOR_ID_AMD,
+		             PCI_DEVICE_ID_AMD_FE_GATE_700C) },
+		{ },
+	};
 	u32 misc_ctrl_reg;
 	u32 cacheline_sz_reg;
 	u32 pci_state_reg, grc_misc_cfg;
@@ -7847,16 +7868,7 @@
 	 * every mailbox register write to force the writes to be
 	 * posted to the chip in order.
 	 */
-	if (pci_find_device(PCI_VENDOR_ID_INTEL,
-			    PCI_DEVICE_ID_INTEL_82801AA_8, NULL) ||
-	    pci_find_device(PCI_VENDOR_ID_INTEL,
-			    PCI_DEVICE_ID_INTEL_82801AB_8, NULL) ||
-	    pci_find_device(PCI_VENDOR_ID_INTEL,
-			    PCI_DEVICE_ID_INTEL_82801BA_11, NULL) ||
-	    pci_find_device(PCI_VENDOR_ID_INTEL,
-			    PCI_DEVICE_ID_INTEL_82801BA_6, NULL) ||
-	    pci_find_device(PCI_VENDOR_ID_AMD,
-			    PCI_DEVICE_ID_AMD_FE_GATE_700C, NULL))
+	if (pci_dev_present(write_reorder_chipsets))
 		tp->tg3_flags |= TG3_FLAG_MBOX_WRITE_REORDER;
 
 	/* Force memory write invalidate off.  If we leave it on,
@@ -8940,7 +8952,7 @@
 	}
 }
 
-static int tg3_suspend(struct pci_dev *pdev, u32 state)
+static int tg3_suspend(struct pci_dev *pdev, pm_message_t state)
 {
 	struct net_device *dev = pci_get_drvdata(pdev);
 	struct tg3 *tp = netdev_priv(dev);
@@ -8967,7 +8979,7 @@
 	spin_unlock(&tp->tx_lock);
 	spin_unlock_irq(&tp->lock);
 
-	err = tg3_set_power_state(tp, state);
+	err = tg3_set_power_state(tp, pci_choose_state(pdev, state));
 	if (err) {
 		spin_lock_irq(&tp->lock);
 		spin_lock(&tp->tx_lock);
diff -Nru a/drivers/net/tg3.h b/drivers/net/tg3.h
--- a/drivers/net/tg3.h	2005-03-11 12:51:41 -08:00
+++ b/drivers/net/tg3.h	2005-03-11 12:51:41 -08:00
@@ -1548,20 +1548,6 @@
 #define MII_TG3_INT_DUPLEXCHG		0x0008
 #define MII_TG3_INT_ANEG_PAGE_RX	0x0400
 
-/* XXX Add this to mii.h */
-#ifndef ADVERTISE_PAUSE
-#define ADVERTISE_PAUSE_CAP		0x0400
-#endif
-#ifndef ADVERTISE_PAUSE_ASYM
-#define ADVERTISE_PAUSE_ASYM		0x0800
-#endif
-#ifndef LPA_PAUSE
-#define LPA_PAUSE_CAP			0x0400
-#endif
-#ifndef LPA_PAUSE_ASYM
-#define LPA_PAUSE_ASYM			0x0800
-#endif
-
 /* There are two ways to manage the TX descriptors on the tigon3.
  * Either the descriptors are in host DMA'able memory, or they
  * exist only in the cards on-chip SRAM.  All 16 send bds are under
diff -Nru a/drivers/net/tokenring/ibmtr.c b/drivers/net/tokenring/ibmtr.c
--- a/drivers/net/tokenring/ibmtr.c	2005-03-11 12:51:47 -08:00
+++ b/drivers/net/tokenring/ibmtr.c	2005-03-11 12:51:47 -08:00
@@ -227,7 +227,7 @@
 	printk("\n");
 }
 
-static void __devinit HWPrtChanID(void * pcid, short stride)
+static void __devinit HWPrtChanID(void __iomem *pcid, short stride)
 {
 	short i, j;
 	for (i = 0, j = 0; i < 24; i++, j += stride)
@@ -239,15 +239,16 @@
  * going away. 
  */
 
-static void __devinit find_turbo_adapters(int *iolist) {
+static void __devinit find_turbo_adapters(int *iolist)
+{
 	int ram_addr;
 	int index=0;
-	void *chanid;
+	void __iomem *chanid;
 	int found_turbo=0;
 	unsigned char *tchanid, ctemp;
 	int i, j;
 	unsigned long jif;
-	void *ram_mapped ;   
+	void __iomem *ram_mapped ;   
 
 	if (turbo_searched == 1) return;
 	turbo_searched=1;
@@ -328,8 +329,8 @@
 
 	{ 
 		struct tok_info *ti = (struct tok_info *) dev->priv;
-		iounmap((u32 *)ti->mmio);
-		iounmap((u32 *)ti->sram_virt);
+		iounmap(ti->mmio);
+		iounmap(ti->sram_virt);
 	}
 #endif		
 }
@@ -383,9 +384,9 @@
 {
 
 	unsigned char segment, intr=0, irq=0, i, j, cardpresent=NOTOK, temp=0;
-	void * t_mmio = NULL;
+	void __iomem * t_mmio = NULL;
 	struct tok_info *ti = dev->priv;
-	void *cd_chanid;
+	void __iomem *cd_chanid;
 	unsigned char *tchanid, ctemp;
 #ifndef PCMCIA
 	unsigned char t_irq=0;
@@ -428,7 +429,7 @@
 	 */
 #ifdef PCMCIA
 	iounmap(t_mmio);
-	t_mmio = (void *)ti->mmio;	/*BMS to get virtual address */
+	t_mmio = ti->mmio;	/*BMS to get virtual address */
 	irq = ti->irq;		/*BMS to display the irq!   */
 #endif
 	cd_chanid = (CHANNEL_ID + t_mmio);	/* for efficiency */
@@ -515,7 +516,7 @@
 		if (intr == 3) irq = 11;
 		ti->global_int_enable = 0;
 		ti->adapter_int_enable = 0;
-		ti->sram_virt=(__u32)(inb(PIOaddr+ADAPTRESETREL) & 0xfe) << 12;
+		ti->sram_phys=(__u32)(inb(PIOaddr+ADAPTRESETREL) & 0xfe) << 12;
 		break;
 	case TR_ISAPNP:
 		if (!t_irq) {
@@ -533,7 +534,7 @@
 			kfree(ti);
 			return -ENODEV;
 		}
-		ti->sram_virt =
+		ti->sram_phys =
 		     ((__u32)readb(ti->mmio+ACA_OFFSET+ACA_RW+RRR_EVEN)<<12);
 		ti->adapter_int_enable = PIOaddr + ADAPTINTREL;
 		break;
@@ -542,7 +543,7 @@
 
 	if (ibmtr_debug_trace & TRC_INIT) {	/* just report int */
 		DPRINTK("irq=%d", irq);
-		printk(", sram_virt=0x%x", ti->sram_virt);
+		printk(", sram_phys=0x%x", ti->sram_phys);
 		if(ibmtr_debug_trace&TRC_INITV){ /* full chat in verbose only */
 			DPRINTK(", ti->mmio=%p", ti->mmio);
 			printk(", segment=%02X", segment);
@@ -681,7 +682,7 @@
 			ibmtr_mem_base = chk_base;
 		}
 	}
-	else  ti->sram_base = ti->sram_virt >> 12;
+	else  ti->sram_base = ti->sram_phys >> 12;
 
 	/* The PCMCIA has already got the interrupt line and the io port, 
 	   so no chance of anybody else getting it - MLP */
@@ -893,7 +894,7 @@
 	*/
 	dev->flags &= ~IFF_RUNNING;
 
-	ti->sram_virt &= ~1; /* to reverse what we do in tok_close */
+	ti->sram_phys &= ~1; /* to reverse what we do in tok_close */
 	/* init the spinlock */
 	spin_lock_init(&ti->lock);
 	init_timer(&ti->tr_timer);
@@ -1068,7 +1069,7 @@
 	/* unloading the module from memory, and then if a timer pops, ouch */
 	del_timer_sync(&ti->tr_timer);
 	outb(0, dev->base_addr + ADAPTRESET);
-	ti->sram_virt |= 1;
+	ti->sram_phys |= 1;
 	ti->open_status = CLOSED;
 
 	netif_stop_queue(dev);
@@ -1094,30 +1095,33 @@
 		"IMPL force received","Duplicate modifier",
 		"No monitor detected","Monitor contention failed for RPL"};
 
-void dir_open_adapter (struct net_device *dev) {
+static void __iomem *map_address(struct tok_info *ti, unsigned index, __u8 *page)
+{
+	if (ti->page_mask) {
+		*page = (index >> 8) & ti->page_mask;
+		index &= ~(ti->page_mask << 8);
+	}
+	return ti->sram_virt + index;
+}
 
+void dir_open_adapter (struct net_device *dev)
+{
         struct tok_info *ti = (struct tok_info *) dev->priv;
         unsigned char ret_code;
         __u16 err;
 
-        ti->srb = ntohs(readw(ti->init_srb + SRB_ADDRESS_OFST));
-        ti->ssb = ntohs(readw(ti->init_srb + SSB_ADDRESS_OFST));
-        ti->arb = ntohs(readw(ti->init_srb + ARB_ADDRESS_OFST));
-        ti->asb = ntohs(readw(ti->init_srb + ASB_ADDRESS_OFST));
-        if (ti->page_mask) {
-                ti->srb_page = (ti->srb >> 8) & ti->page_mask;
-                ti->srb &= ~(ti->page_mask << 8);
-                ti->ssb_page = (ti->ssb >> 8) & ti->page_mask;
-                ti->ssb &= ~(ti->page_mask << 8);
-                ti->arb_page = (ti->arb >> 8) & ti->page_mask;
-                ti->arb &= ~(ti->page_mask << 8);
-                ti->asb_page = (ti->asb >> 8) & ti->page_mask;
-                ti->asb &= ~(ti->page_mask << 8);
-        }
-        ti->srb += ti->sram_virt;
-        ti->ssb += ti->sram_virt;
-        ti->arb += ti->sram_virt;
-        ti->asb += ti->sram_virt;
+        ti->srb = map_address(ti,
+		ntohs(readw(ti->init_srb + SRB_ADDRESS_OFST)),
+		&ti->srb_page);
+        ti->ssb = map_address(ti,
+		ntohs(readw(ti->init_srb + SSB_ADDRESS_OFST)),
+		&ti->ssb_page);
+        ti->arb = map_address(ti,
+		ntohs(readw(ti->init_srb + ARB_ADDRESS_OFST)),
+		&ti->arb_page);
+        ti->asb = map_address(ti,
+		ntohs(readw(ti->init_srb + ASB_ADDRESS_OFST)),
+		&ti->asb_page);
         ti->current_skb = NULL;
         ret_code = readb(ti->init_srb + RETCODE_OFST);
         err = ntohs(readw(ti->init_srb + OPEN_ERROR_CODE_OFST));
@@ -1188,7 +1192,7 @@
 	DPRINTK("Int from tok_driver, dev : %p irq%d regs=%p\n", dev,irq,regs);
 #endif
 	ti = (struct tok_info *) dev->priv;
-	if (ti->sram_virt & 1)
+	if (ti->sram_phys & 1)
 		return IRQ_NONE;         /* PCMCIA card extraction flag */
 	spin_lock(&(ti->lock));
 #ifdef ENABLE_PAGING
@@ -1220,15 +1224,11 @@
 
 	if (status & ADAP_CHK_INT) {
 		int i;
-		__u32 check_reason;
+		void __iomem *check_reason;
 		__u8 check_reason_page = 0;
-		check_reason =
-			ntohs(readw(ti->mmio+ ACA_OFFSET+ACA_RW + WWCR_EVEN));
-		if (ti->page_mask) {
-			check_reason_page = (check_reason >> 8) & ti->page_mask;
-			check_reason &= ~(ti->page_mask << 8);
-		}
-		check_reason += ti->sram_virt;
+		check_reason = map_address(ti,
+			ntohs(readw(ti->mmio+ ACA_OFFSET+ACA_RW + WWCR_EVEN)),
+			&check_reason_page);
 		SET_PAGE(check_reason_page);
 
 		DPRINTK("Adapter check interrupt\n");
@@ -1517,23 +1517,20 @@
 	/* we assign the shared-ram address for ISA devices */
 	writeb(ti->sram_base, ti->mmio + ACA_OFFSET + ACA_RW + RRR_EVEN);
 #ifndef PCMCIA
-        ti->sram_virt = (u32)ioremap(((__u32)ti->sram_base << 12), ti->avail_shared_ram);
+        ti->sram_virt = ioremap(((__u32)ti->sram_base << 12), ti->avail_shared_ram);
 #endif
-	ti->init_srb = ntohs(readw(ti->mmio + ACA_OFFSET + WRBR_EVEN));
-	if (ti->page_mask) {
-		ti->init_srb_page = (ti->init_srb >> 8) & ti->page_mask;
-		ti->init_srb &= ~(ti->page_mask << 8);
-	}
-	ti->init_srb += ti->sram_virt;
+	ti->init_srb = map_address(ti,
+		ntohs(readw(ti->mmio + ACA_OFFSET + WRBR_EVEN)),
+		&ti->init_srb_page);
 	if (ti->page_mask && ti->avail_shared_ram == 127) {
-		int last_512 = 0xfe00, i;
-		int last_512_page=0;
-		last_512_page=(last_512>>8)&ti->page_mask;
-		last_512 &= ~(ti->page_mask << 8);
+		void __iomem *last_512;
+		__u8 last_512_page=0;
+		int i;
+		last_512 = map_address(ti, 0xfe00, &last_512_page);
 		/* initialize high section of ram (if necessary) */
 		SET_PAGE(last_512_page);
 		for (i = 0; i < 512; i++)
-			writeb(0, ti->sram_virt + last_512 + i);
+			writeb(0, last_512 + i);
 	}
 	SET_PAGE(ti->init_srb_page);
 
@@ -1542,7 +1539,7 @@
 	int i;
 
 	DPRINTK("ti->init_srb_page=0x%x\n", ti->init_srb_page);
-	DPRINTK("init_srb(%x):", (ti->init_srb) );
+	DPRINTK("init_srb(%p):", ti->init_srb );
 	for (i = 0; i < 20; i++)
 		printk("%02X ", (int) readb(ti->init_srb + i));
 	printk("\n");
@@ -1579,6 +1576,7 @@
 	struct trh_hdr *trhdr = (struct trh_hdr *) ti->current_skb->data;
 	unsigned int hdr_len;
 	__u32 dhb=0,dhb_base;
+	void __iomem *dhbuf = NULL;
 	unsigned char xmit_command;
 	int i,dhb_len=0x4000,src_len,src_offset;
 	struct trllc *llc;
@@ -1600,7 +1598,7 @@
 		dhb_page = (dhb_base >> 8) & ti->page_mask;
 		dhb=dhb_base & ~(ti->page_mask << 8);
 	}
-	dhb += ti->sram_virt;
+	dhbuf = ti->sram_virt + dhb;
 
 	/* Figure out the size of the 802.5 header */
 	if (!(trhdr->saddr[0] & 0x80))	/* RIF present? */
@@ -1626,12 +1624,12 @@
 		writew(htons(0x11), ti->asb + FRAME_LENGTH_OFST);
 		writeb(0x0e, ti->asb + HEADER_LENGTH_OFST);
 		SET_PAGE(dhb_page);
-		writeb(AC, dhb);
-		writeb(LLC_FRAME, dhb + 1);
+		writeb(AC, dhbuf);
+		writeb(LLC_FRAME, dhbuf + 1);
 		for (i = 0; i < TR_ALEN; i++)
-			writeb((int) 0x0FF, dhb + i + 2);
+			writeb((int) 0x0FF, dhbuf + i + 2);
 		for (i = 0; i < TR_ALEN; i++)
-			writeb(0, dhb + i + TR_ALEN + 2);
+			writeb(0, dhbuf + i + TR_ALEN + 2);
 		writeb(RESP_IN_ASB, ti->mmio + ACA_OFFSET + ACA_SET + ISRA_ODD);
 		return;
 	}
@@ -1650,10 +1648,10 @@
 			dhb=dhb & ~(ti->page_mask << 8);
 			dhb_len=0x4000-dhb; /* remaining size of this page */
 		}
-		dhb+=ti->sram_virt;
+		dhbuf = ti->sram_virt + dhb;
 		SET_PAGE(dhb_page);
 		if (src_len > dhb_len) {
-			memcpy_toio(dhb,&ti->current_skb->data[src_offset],
+			memcpy_toio(dhbuf,&ti->current_skb->data[src_offset],
 					dhb_len);
 			src_len -= dhb_len;
 			src_offset += dhb_len;
@@ -1661,7 +1659,7 @@
 			dhb=dhb_base;
 			continue;
 		}
-		memcpy_toio(dhb, &ti->current_skb->data[src_offset], src_len);
+		memcpy_toio(dhbuf, &ti->current_skb->data[src_offset], src_len);
 		break;
 	}
 	writeb(RESP_IN_ASB, ti->mmio + ACA_OFFSET + ACA_SET + ISRA_ODD);
@@ -1689,9 +1687,9 @@
 static void tr_rx(struct net_device *dev)
 {
 	struct tok_info *ti = (struct tok_info *) dev->priv;
-	__u32 rbuffer, rbufdata;
+	__u32 rbuffer;
+	void __iomem *rbuf, *rbufdata, *llc;
 	__u8 rbuffer_page = 0;
-	__u32 llc;
 	unsigned char *data;
 	unsigned int rbuffer_len, lan_hdr_len, hdr_len, ip_len, length;
 	unsigned char dlc_hdr_len;
@@ -1705,11 +1703,7 @@
 	SET_PAGE(ti->arb_page);
 	memcpy_fromio(&rarb, ti->arb, sizeof(rarb));
 	rbuffer = ntohs(rarb.rec_buf_addr) ;
-	if (ti->page_mask) {
-		rbuffer_page = (rbuffer >> 8) & ti->page_mask;
-		rbuffer &= ~(ti->page_mask << 8);
-	}
-	rbuffer += ti->sram_virt;
+	rbuf = map_address(ti, rbuffer, &rbuffer_page);
 
 	SET_PAGE(ti->asb_page);
 
@@ -1728,7 +1722,7 @@
 	hdr_len = lan_hdr_len + sizeof(struct trllc) + sizeof(struct iphdr);
 
 	SET_PAGE(rbuffer_page);
-	llc = (rbuffer + offsetof(struct rec_buf, data) + lan_hdr_len);
+	llc = rbuf + offsetof(struct rec_buf, data) + lan_hdr_len;
 
 #if TR_VERBOSE
 	DPRINTK("offsetof data: %02X lan_hdr_len: %02X\n",
@@ -1759,9 +1753,7 @@
 
 	if (!IPv4_p) {
 
-		__u32 trhhdr;
-
-		trhhdr = (rbuffer + offsetof(struct rec_buf, data));
+		void __iomem *trhhdr = rbuf + offsetof(struct rec_buf, data);
 
 		DPRINTK("Probably non-IP frame received.\n");
 		DPRINTK("ssap: %02X dsap: %02X "
@@ -1793,8 +1785,8 @@
 	skb_put(skb, length);
 	skb->dev = dev;
 	data = skb->data;
-	rbuffer_len = ntohs(readw(rbuffer + offsetof(struct rec_buf, buf_len)));
-	rbufdata = rbuffer + offsetof(struct rec_buf, data);
+	rbuffer_len = ntohs(readw(rbuf + offsetof(struct rec_buf, buf_len)));
+	rbufdata = rbuf + offsetof(struct rec_buf, data);
 
 	if (IPv4_p) {
 		/* Copy the headers without checksumming */
@@ -1822,20 +1814,16 @@
 			    data,length<rbuffer_len?length:rbuffer_len,chksum);
 		else
 			memcpy_fromio(data, rbufdata, rbuffer_len);
-		rbuffer = ntohs(readw(rbuffer+BUFFER_POINTER_OFST)) ;
+		rbuffer = ntohs(readw(rbuf+BUFFER_POINTER_OFST)) ;
 		if (!rbuffer)
 			break;
 		rbuffer -= 2;
 		length -= rbuffer_len;
 		data += rbuffer_len;
-		if (ti->page_mask) {
-			rbuffer_page = (rbuffer >> 8) & ti->page_mask;
-			rbuffer &= ~(ti->page_mask << 8);
-		}
-		rbuffer += ti->sram_virt;
+		rbuf = map_address(ti, rbuffer, &rbuffer_page);
 		SET_PAGE(rbuffer_page);
-		rbuffer_len = ntohs(readw(rbuffer + BUFFER_LENGTH_OFST));
-		rbufdata = rbuffer + offsetof(struct rec_buf, data);
+		rbuffer_len = ntohs(readw(rbuf + BUFFER_LENGTH_OFST));
+		rbufdata = rbuf + offsetof(struct rec_buf, data);
 	}
 
 	SET_PAGE(ti->asb_page);
diff -Nru a/drivers/net/tulip/de2104x.c b/drivers/net/tulip/de2104x.c
--- a/drivers/net/tulip/de2104x.c	2005-03-11 12:51:50 -08:00
+++ b/drivers/net/tulip/de2104x.c	2005-03-11 12:51:50 -08:00
@@ -1927,7 +1927,7 @@
 	goto fill_defaults;
 }
 
-static int __devinit de_init_one (struct pci_dev *pdev,
+static int __init de_init_one (struct pci_dev *pdev,
 				  const struct pci_device_id *ent)
 {
 	struct net_device *dev;
diff -Nru a/drivers/net/tulip/interrupt.c b/drivers/net/tulip/interrupt.c
--- a/drivers/net/tulip/interrupt.c	2005-03-11 12:51:52 -08:00
+++ b/drivers/net/tulip/interrupt.c	2005-03-11 12:51:52 -08:00
@@ -26,7 +26,7 @@
 #define MIT_SIZE 15
 #define MIT_TABLE 15 /* We use 0 or max */
 
-unsigned int mit_table[MIT_SIZE+1] =
+static unsigned int mit_table[MIT_SIZE+1] =
 {
         /*  CRS11 21143 hardware Mitigation Control Interrupt
             We use only RX mitigation we other techniques for
diff -Nru a/drivers/net/tulip/tulip.h b/drivers/net/tulip/tulip.h
--- a/drivers/net/tulip/tulip.h	2005-03-11 12:51:51 -08:00
+++ b/drivers/net/tulip/tulip.h	2005-03-11 12:51:51 -08:00
@@ -476,7 +476,7 @@
 
 		if (!i)
 			printk(KERN_DEBUG "%s: tulip_stop_rxtx() failed\n",
-					tp->pdev->slot_name);
+					pci_name(tp->pdev));
 	}
 }
 
diff -Nru a/drivers/net/tulip/tulip_core.c b/drivers/net/tulip/tulip_core.c
--- a/drivers/net/tulip/tulip_core.c	2005-03-11 12:51:47 -08:00
+++ b/drivers/net/tulip/tulip_core.c	2005-03-11 12:51:47 -08:00
@@ -1749,7 +1749,7 @@
 
 #ifdef CONFIG_PM
 
-static int tulip_suspend (struct pci_dev *pdev, u32 state)
+static int tulip_suspend (struct pci_dev *pdev, pm_message_t state)
 {
 	struct net_device *dev = pci_get_drvdata(pdev);
 
diff -Nru a/drivers/net/tun.c b/drivers/net/tun.c
--- a/drivers/net/tun.c	2005-03-11 12:51:43 -08:00
+++ b/drivers/net/tun.c	2005-03-11 12:51:43 -08:00
@@ -229,7 +229,7 @@
 	size_t len = count;
 
 	if (!(tun->flags & TUN_NO_PI)) {
-		if ((len -= sizeof(pi)) > len)
+		if ((len -= sizeof(pi)) > count)
 			return -EINVAL;
 
 		if(memcpy_fromiovec((void *)&pi, iv, sizeof(pi)))
@@ -843,7 +843,7 @@
 	.set_rx_csum	= tun_set_rx_csum
 };
 
-int __init tun_init(void)
+static int __init tun_init(void)
 {
 	int ret = 0;
 
@@ -856,7 +856,7 @@
 	return ret;
 }
 
-void tun_cleanup(void)
+static void tun_cleanup(void)
 {
 	struct tun_struct *tun, *nxt;
 
diff -Nru a/drivers/net/typhoon-firmware.h b/drivers/net/typhoon-firmware.h
--- a/drivers/net/typhoon-firmware.h	2005-03-11 12:51:41 -08:00
+++ b/drivers/net/typhoon-firmware.h	2005-03-11 12:51:41 -08:00
@@ -1,5 +1,5 @@
 /*
- * Copyright 1999-2003 3Com Corporation.  All Rights Reserved.    
+ * Copyright 1999-2004 3Com Corporation.  All Rights Reserved.    
  *
  * Redistribution and use in source and binary forms of the 3c990img.h
  * microcode software are permitted provided that the following conditions
@@ -31,14 +31,15 @@
  * COMBINATION WITH THE 3c990img.h MICROCODE SOFTWARE
  */ 
 
+ /* ver 03.001.008 */
 const u8 typhoon_firmware_image[] = {
 0x54, 0x59, 0x50, 0x48, 0x4f, 0x4f, 0x4e, 0x00, 0x02, 0x00, 0x00, 0x00, 
-0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xbf, 0xcd, 0x57, 0xc3, 
-0xba, 0x01, 0x2c, 0xe8, 0xcd, 0xef, 0xa9, 0xd9, 0x6f, 0xbb, 0x76, 0x2f, 
-0x86, 0x49, 0xac, 0x1b, 0x40, 0x01, 0x00, 0x00, 0x8a, 0xe4, 0x00, 0x00, 
+0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xcb, 0x99, 0xb1, 0xd4, 
+0x4c, 0xb8, 0xd0, 0x4b, 0x32, 0x02, 0xd4, 0xee, 0x73, 0x7e, 0x0b, 0x13, 
+0x9b, 0xc0, 0xae, 0xf4, 0x40, 0x01, 0x00, 0x00, 0xe8, 0xfc, 0x00, 0x00, 
 0x00, 0x00, 0xff, 0xff, 0x39, 0x00, 0x00, 0xea, 0x05, 0x00, 0x00, 0xea, 
 0x04, 0x00, 0x00, 0xea, 0x03, 0x00, 0x00, 0xea, 0x02, 0x00, 0x00, 0xea, 
-0x01, 0x00, 0x00, 0xea, 0x32, 0x02, 0x00, 0xea, 0xc0, 0x14, 0x00, 0xea, 
+0x01, 0x00, 0x00, 0xea, 0x32, 0x02, 0x00, 0xea, 0xc5, 0x14, 0x00, 0xea, 
 0x07, 0x00, 0x2d, 0xe9, 0x0e, 0x00, 0xa0, 0xe1, 0x00, 0x10, 0x0f, 0xe1, 
 0xd0, 0x20, 0x9f, 0xe5, 0x12, 0xff, 0x2f, 0xe1, 0xfe, 0xff, 0xff, 0xea, 
 0x01, 0x00, 0x80, 0xe0, 0x04, 0x20, 0x81, 0xe4, 0x01, 0x00, 0x50, 0xe1, 
@@ -50,7 +51,7 @@
 0x88, 0xd0, 0x9f, 0xe5, 0xdb, 0x00, 0xa0, 0xe3, 0x00, 0xf0, 0x21, 0xe1, 
 0x7c, 0xd0, 0x9f, 0xe5, 0xd2, 0x00, 0xa0, 0xe3, 0x00, 0xf0, 0x21, 0xe1, 
 0x74, 0xd0, 0x9f, 0xe5, 0xd1, 0x00, 0xa0, 0xe3, 0x00, 0xf0, 0x21, 0xe1, 
-0x6c, 0xd0, 0x9f, 0xe5, 0x96, 0x14, 0x00, 0xeb, 0xd3, 0x00, 0xa0, 0xe3, 
+0x6c, 0xd0, 0x9f, 0xe5, 0x9b, 0x14, 0x00, 0xeb, 0xd3, 0x00, 0xa0, 0xe3, 
 0x00, 0xf0, 0x21, 0xe1, 0x60, 0xd0, 0x9f, 0xe5, 0x60, 0x00, 0x9f, 0xe5, 
 0x60, 0x10, 0x9f, 0xe5, 0x60, 0x20, 0x9f, 0xe5, 0xdb, 0xff, 0xff, 0xeb, 
 0x5c, 0x00, 0x9f, 0xe5, 0x5c, 0x10, 0x9f, 0xe5, 0x00, 0x20, 0xa0, 0xe3, 
@@ -58,21 +59,21 @@
 0xd4, 0xff, 0xff, 0xeb, 0x0a, 0x00, 0xa0, 0xe1, 0x0b, 0xf0, 0xa0, 0xe1, 
 0xd3, 0x10, 0xa0, 0xe3, 0x01, 0xf0, 0x21, 0xe1, 0xd4, 0xff, 0xff, 0xeb, 
 0x3c, 0xa0, 0x9f, 0xe5, 0x1a, 0xff, 0x2f, 0xe1, 0xc6, 0xff, 0xff, 0xea, 
-0x01, 0x21, 0xff, 0xff, 0x0c, 0x00, 0x10, 0x00, 0x1c, 0x00, 0x10, 0x00, 
+0x15, 0x21, 0xff, 0xff, 0x0c, 0x00, 0x10, 0x00, 0x1c, 0x00, 0x10, 0x00, 
 0x3c, 0x38, 0x00, 0x80, 0xfc, 0x37, 0x00, 0x80, 0xfc, 0x3f, 0x00, 0x80, 
 0x7c, 0x34, 0x00, 0x80, 0x80, 0x0f, 0x00, 0x00, 0x80, 0x30, 0x00, 0x80, 
-0xad, 0xde, 0xad, 0xde, 0x5c, 0xbc, 0x00, 0x00, 0x24, 0xab, 0x20, 0x40, 
-0x48, 0x29, 0x00, 0x00, 0x28, 0x05, 0x00, 0x80, 0x8d, 0xd2, 0x21, 0x40, 
+0xad, 0xde, 0xad, 0xde, 0xb0, 0xbb, 0x00, 0x00, 0x24, 0xab, 0x20, 0x40, 
+0x48, 0x29, 0x00, 0x00, 0x28, 0x05, 0x00, 0x80, 0xbd, 0xba, 0x21, 0x40, 
 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-0x44, 0x57, 0x00, 0x00, 0x71, 0xaf, 0x00, 0x00, 0x60, 0x01, 0xff, 0xff, 
-0xb0, 0xb5, 0x07, 0x1c, 0x12, 0x4c, 0x00, 0x25, 0x20, 0x68, 0x00, 0x28, 
-0x1d, 0xd0, 0x38, 0x1c, 0x10, 0x49, 0x04, 0xf0, 0x71, 0xfd, 0x21, 0x68, 
-0xc0, 0x46, 0x08, 0x60, 0x00, 0x28, 0x14, 0xd0, 0x38, 0x01, 0x0d, 0x49, 
+0x58, 0x57, 0x00, 0x00, 0x86, 0x4b, 0x00, 0x00, 0x60, 0x01, 0xff, 0xff, 
+0xb0, 0xb5, 0x07, 0x1c, 0x12, 0x4d, 0x00, 0x24, 0x28, 0x68, 0x00, 0x28, 
+0x1e, 0xd0, 0x38, 0x1c, 0x10, 0x49, 0x04, 0xf0, 0x7b, 0xfd, 0x29, 0x68, 
+0xc0, 0x46, 0x08, 0x60, 0x00, 0x28, 0x15, 0xd0, 0x38, 0x01, 0x0d, 0x49, 
 0x40, 0x18, 0x19, 0x23, 0xdb, 0x01, 0xc0, 0x18, 0x41, 0x6b, 0x80, 0x29, 
-0x0b, 0xd2, 0x01, 0x31, 0x41, 0x63, 0x20, 0x68, 0xc1, 0x69, 0xc0, 0x46, 
-0x21, 0x60, 0x39, 0x07, 0x41, 0x60, 0xc7, 0x62, 0xb0, 0xbc, 0x08, 0xbc, 
-0x18, 0x47, 0x28, 0x1c, 0xfa, 0xe7, 0x00, 0x00, 0xe8, 0x17, 0x00, 0x80, 
+0x0c, 0xd2, 0x01, 0x31, 0x41, 0x63, 0x28, 0x68, 0xc1, 0x69, 0xc0, 0x46, 
+0x29, 0x60, 0x39, 0x07, 0x41, 0x60, 0x04, 0x62, 0xc7, 0x62, 0xb0, 0xbc, 
+0x08, 0xbc, 0x18, 0x47, 0x20, 0x1c, 0xfa, 0xe7, 0xe8, 0x17, 0x00, 0x80, 
 0xee, 0x05, 0x00, 0x00, 0xa0, 0x1c, 0x00, 0x80, 0x02, 0x49, 0x0a, 0x68, 
 0xc0, 0x46, 0xc2, 0x61, 0x08, 0x60, 0x70, 0x47, 
 0xe8, 0x17, 0x00, 0x80, 0x70, 0x47, 0x00, 0x00, 0x70, 0x47, 0x00, 0x00, 
@@ -91,7 +92,7 @@
 0x1e, 0xff, 0x2f, 0xe1, 0x01, 0x20, 0x80, 0xe0, 0x01, 0x00, 0x80, 0xe0, 
 0x1e, 0xff, 0x2f, 0xe1, 0x80, 0xb5, 0x08, 0x4f, 0x64, 0x28, 0x04, 0xd3, 
 0x64, 0x20, 0x38, 0x63, 0x00, 0x20, 0xc0, 0x43, 0x03, 0xe0, 0x38, 0x63, 
-0x04, 0x49, 0x05, 0xf0, 0xf7, 0xfa, 0x78, 0x63, 0xb8, 0x63, 0x80, 0xbc, 
+0x04, 0x49, 0x05, 0xf0, 0x01, 0xfb, 0x78, 0x63, 0xb8, 0x63, 0x80, 0xbc, 
 0x08, 0xbc, 0x18, 0x47, 0x68, 0x0e, 0x00, 0x80, 0x88, 0x13, 0x00, 0x00, 
 0x80, 0xb4, 0x10, 0x4b, 0x00, 0x22, 0x1f, 0x6b, 0x64, 0x2f, 0x03, 0xd2, 
 0x09, 0x68, 0x09, 0x68, 0x49, 0x08, 0x02, 0xd2, 0x10, 0x1c, 0x80, 0xbc, 
@@ -104,7 +105,7 @@
 0x49, 0x08, 0x08, 0xd3, 0x21, 0x6c, 0xa2, 0x6b, 0x91, 0x42, 0x07, 0xd2, 
 0xfa, 0x1d, 0x39, 0x32, 0x52, 0x8b, 0x89, 0x18, 0x21, 0x64, 0x90, 0xbc, 
 0x08, 0xbc, 0x18, 0x47, 0x78, 0x6a, 0x39, 0x6b, 0xc0, 0x46, 0x48, 0x62, 
-0x38, 0x6b, 0x02, 0xf0, 0x23, 0xfe, 0x38, 0x1c, 0x02, 0xf0, 0xde, 0xfa, 
+0x38, 0x6b, 0x02, 0xf0, 0x2d, 0xfe, 0x38, 0x1c, 0x02, 0xf0, 0xe8, 0xfa, 
 0x01, 0x20, 0xbb, 0x23, 0x1b, 0x01, 0xe1, 0x18, 0xc8, 0x73, 0x05, 0x49, 
 0x0a, 0x6c, 0x12, 0x18, 0x0a, 0x64, 0x04, 0x49, 0x8a, 0x6d, 0x12, 0x18, 
 0x8a, 0x65, 0xe4, 0xe7, 0x68, 0x0e, 0x00, 0x80, 0x0c, 0x2b, 0x00, 0x80, 
@@ -333,8 +334,8 @@
 0xc9, 0x68, 0x40, 0x18, 0x01, 0x23, 0x9b, 0x07, 0x02, 0x30, 0x18, 0x43, 
 0x00, 0x68, 0x00, 0x04, 0x00, 0x0c, 0x11, 0x23, 0x9b, 0x02, 0x98, 0x42, 
 0x18, 0xd1, 0x78, 0x6a, 0x39, 0x6b, 0xc0, 0x46, 
-0x48, 0x62, 0x38, 0x6b, 0x02, 0xf0, 0xd0, 0xf8, 0x38, 0x1c, 0x01, 0xf0, 
-0x8b, 0xfd, 0x01, 0x20, 0x07, 0x49, 0xc0, 0x46, 0xc8, 0x73, 0x07, 0x49, 
+0x48, 0x62, 0x38, 0x6b, 0x02, 0xf0, 0xda, 0xf8, 0x38, 0x1c, 0x01, 0xf0, 
+0x95, 0xfd, 0x01, 0x20, 0x07, 0x49, 0xc0, 0x46, 0xc8, 0x73, 0x07, 0x49, 
 0x4a, 0x6c, 0x12, 0x18, 0x4a, 0x64, 0x06, 0x49, 0x8a, 0x6d, 0x12, 0x18, 
 0x8a, 0x65, 0x80, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x20, 0xfa, 0xe7, 
 0x18, 0x1a, 0x00, 0x80, 0x0c, 0x2b, 0x00, 0x80, 0xa4, 0x2a, 0x00, 0x80, 
@@ -370,7 +371,7 @@
 0xc2, 0x60, 0x38, 0x1c, 0x00, 0xf0, 0xce, 0xfa, 0x38, 0x6a, 0x01, 0x30, 
 0x38, 0x62, 0x38, 0x1c, 0x00, 0xf0, 0x0a, 0xf8, 0x80, 0xbc, 0x08, 0xbc, 
 0x18, 0x47, 0x10, 0x1c, 0xfa, 0xe7, 0x00, 0x00, 0x6c, 0x06, 0x00, 0x80, 
-0x1c, 0xad, 0x20, 0x40, 0xf0, 0xb5, 0x07, 0x1c, 0xf9, 0x1d, 0xf9, 0x31, 
+0xac, 0xab, 0x20, 0x40, 0xf0, 0xb5, 0x07, 0x1c, 0xf9, 0x1d, 0xf9, 0x31, 
 0x88, 0x6a, 0xc2, 0x1d, 0x2d, 0x32, 0x01, 0x23, 0x9b, 0x07, 0x08, 0x32, 
 0x1a, 0x43, 0xc8, 0x6a, 0x12, 0x68, 0x12, 0x04, 0x12, 0x0c, 0x80, 0x18, 
 0x82, 0x79, 0xc3, 0x79, 0x1b, 0x02, 0x1a, 0x43, 0x13, 0x02, 0x12, 0x0a, 
@@ -381,7 +382,7 @@
 0xc2, 0x1d, 0x0d, 0x32, 0x1a, 0x43, 0x12, 0x68, 0x12, 0x04, 0x12, 0x30, 
 0x18, 0x43, 0x00, 0x68, 0x00, 0x04, 0x00, 0x0c, 0x10, 0x43, 0x03, 0x1c, 
 0xf8, 0x1d, 0xff, 0x30, 0x4a, 0x30, 0x82, 0x78, 0xc8, 0x6b, 0x19, 0x1c, 
-0x01, 0xf0, 0xf8, 0xff, 0x00, 0x28, 0x04, 0xda, 0x20, 0x8a, 0xff, 0x23, 
+0x02, 0xf0, 0x02, 0xf8, 0x00, 0x28, 0x04, 0xda, 0x20, 0x8a, 0xff, 0x23, 
 0x01, 0x33, 0x18, 0x43, 0x0e, 0xe0, 0xf9, 0x1d, 0xff, 0x31, 0x3a, 0x31, 
 0x08, 0x60, 0x01, 0x04, 0x09, 0x0c, 0x38, 0x1c, 0x00, 0xf0, 0x1c, 0xf8, 
 0x00, 0x28, 0x14, 0xd1, 0x20, 0x8a, 0x01, 0x23, 0x5b, 0x02, 0x18, 0x43, 
@@ -398,7 +399,7 @@
 0x60, 0x6b, 0x81, 0x42, 0xf8, 0xd8, 0x69, 0x89, 0xea, 0x88, 0x89, 0x18, 
 0x81, 0x42, 0xf3, 0xd8, 0x00, 0x98, 0x01, 0x28, 0x25, 0xd1, 0xe0, 0x6a, 
 0xf1, 0x6b, 0x40, 0x18, 0x71, 0x6c, 0xfa, 0x1d, 0xcd, 0x32, 0x01, 0xf0, 
-0x29, 0xf9, 0xfa, 0x1d, 0xff, 0x32, 0x3a, 0x32, 0xe0, 0x6a, 0x51, 0x69, 
+0x33, 0xf9, 0xfa, 0x1d, 0xff, 0x32, 0x3a, 0x32, 0xe0, 0x6a, 0x51, 0x69, 
 0x40, 0x18, 0xc3, 0x1d, 0x03, 0x33, 0x00, 0x20, 0x81, 0x00, 0x5e, 0x58, 
 0xc9, 0x19, 0xff, 0x31, 0x01, 0x31, 0x4e, 0x61, 0x01, 0x30, 0x04, 0x28, 
 0xf6, 0xd3, 0xe0, 0x6a, 0x51, 0x69, 0x40, 0x18, 0xc1, 0x1d, 0x05, 0x31, 
@@ -419,7 +420,7 @@
 0xc0, 0x46, 0x09, 0x90, 0xff, 0x23, 0x1b, 0x02, 0x18, 0x40, 0x00, 0x0a, 
 0x0a, 0x90, 0x0a, 0x98, 0xa4, 0x4e, 0x01, 0x28, 0x59, 0xd1, 0x28, 0x6b, 
 0xa2, 0x68, 0x80, 0x18, 0xa2, 0x4a, 0x21, 0x69, 
-0x09, 0x04, 0x09, 0x0c, 0x01, 0xf0, 0x1c, 0xf9, 0x28, 0x6b, 0x79, 0x69, 
+0x09, 0x04, 0x09, 0x0c, 0x01, 0xf0, 0x26, 0xf9, 0x28, 0x6b, 0x79, 0x69, 
 0x40, 0x18, 0xc1, 0x1d, 0x05, 0x31, 0x00, 0x20, 0x82, 0x00, 0x98, 0x4b, 
 0xd3, 0x18, 0xff, 0x33, 0x01, 0x33, 0x5b, 0x69, 0xc0, 0x46, 0x8b, 0x50, 
 0x01, 0x30, 0x04, 0x28, 0xf4, 0xd3, 0x00, 0x20, 0x31, 0x1c, 0x82, 0x00, 
@@ -429,7 +430,7 @@
 0x8e, 0x48, 0xc1, 0x89, 0x01, 0x31, 0xc1, 0x81, 0xb8, 0x68, 0x00, 0x28, 
 0x03, 0xd1, 0x38, 0x8a, 0x10, 0x23, 0x18, 0x43, 0x71, 0xe0, 0x38, 0x8a, 
 0x40, 0x23, 0x18, 0x43, 0x6d, 0xe0, 0x00, 0xf0, 0x11, 0xf9, 0x01, 0xf0, 
-0x5d, 0xff, 0xf5, 0xe0, 0x01, 0x30, 0x06, 0x28, 0xe3, 0xd3, 0x08, 0x98, 
+0x67, 0xff, 0xf5, 0xe0, 0x01, 0x30, 0x06, 0x28, 0xe3, 0xd3, 0x08, 0x98, 
 0x00, 0x28, 0x0c, 0xd1, 0xb8, 0x68, 0x41, 0x1c, 0xb9, 0x60, 0x00, 0x28, 
 0x03, 0xd1, 0x38, 0x8a, 0x01, 0x23, 0x18, 0x43, 0x02, 0xe0, 0x38, 0x8a, 
 0x04, 0x23, 0x18, 0x43, 0x38, 0x82, 0x78, 0x68, 0x01, 0x30, 0x78, 0x60, 
@@ -470,10 +471,10 @@
 0xff, 0xf7, 0xc0, 0xfd, 0x00, 0x28, 0x11, 0xd1, 0x0e, 0xe0, 0x00, 0x20, 
 0x30, 0x72, 0x11, 0xe0, 0x33, 0x29, 0x01, 0xd0, 0x32, 0x29, 0x0d, 0xd1, 
 0x07, 0x1c, 0x00, 0xf0, 0x71, 0xf8, 0x38, 0x1c, 0xff, 0xf7, 0xb0, 0xfd, 
-0x00, 0x28, 0x01, 0xd1, 0x01, 0xf0, 0x66, 0xfe, 0x0d, 0xb0, 0xf0, 0xbc, 
+0x00, 0x28, 0x01, 0xd1, 0x01, 0xf0, 0x70, 0xfe, 0x0d, 0xb0, 0xf0, 0xbc, 
 0x08, 0xbc, 0x18, 0x47, 0x00, 0xf0, 0x12, 0xf8, 0xf6, 0xe7, 0x00, 0x00, 
 0x6c, 0x06, 0x00, 0x80, 0x00, 0x00, 0x00, 0xb0, 0x4c, 0x2a, 0x00, 0x80, 
-0x1c, 0xad, 0x20, 0x40, 0x40, 0x07, 0x00, 0x80, 0x82, 0x07, 0x00, 0x80, 
+0xac, 0xab, 0x20, 0x40, 0x40, 0x07, 0x00, 0x80, 0x82, 0x07, 0x00, 0x80, 
 0x0c, 0x2b, 0x00, 0x80, 0x6c, 0x07, 0x00, 0x80, 0xf0, 0xb5, 0x25, 0x48, 
 0x41, 0x68, 0x01, 0x31, 0x41, 0x60, 0x24, 0x4f, 0xf9, 0x1d, 0xf9, 0x31, 
 0x00, 0x24, 0x88, 0x6a, 0xfa, 0x68, 0xc0, 0x46, 0x94, 0x61, 0x04, 0x22, 
@@ -485,7 +486,7 @@
 0x4a, 0x6b, 0xfb, 0x68, 0xc0, 0x46, 0xda, 0x81, 0x0a, 0x6b, 0xc0, 0x46, 
 0x82, 0x62, 0xc4, 0x62, 0xc3, 0x1d, 0x39, 0x33, 0x4a, 0x6b, 0xc0, 0x46, 
 0x5a, 0x83, 0x04, 0x23, 0x02, 0x68, 0x1a, 0x43, 0x02, 0x60, 0x88, 0x6a, 
-0x01, 0xf0, 0x28, 0xfa, 0xf8, 0x68, 0x01, 0x23, 0x9b, 0x07, 0x54, 0x30, 
+0x01, 0xf0, 0x32, 0xfa, 0xf8, 0x68, 0x01, 0x23, 0x9b, 0x07, 0x54, 0x30, 
 0x18, 0x43, 0x00, 0x68, 0xc0, 0x46, 0xf8, 0x60, 0xf0, 0xbc, 0x08, 0xbc, 
 0x18, 0x47, 0x00, 0x00, 0x0c, 0x2b, 0x00, 0x80, 0x6c, 0x06, 0x00, 0x80, 
 0xac, 0x07, 0x00, 0x80, 0x80, 0xb5, 0xc1, 0x1d, 0xf9, 0x31, 0x8a, 0x6a, 
@@ -546,7 +547,7 @@
 0x04, 0x23, 0x90, 0x6a, 0xc0, 0x46, 0xc3, 0x60, 0x10, 0x23, 0x83, 0x61, 
 0xcb, 0x0a, 0x01, 0xd3, 0x18, 0x23, 0x83, 0x61, 0xc1, 0x83, 0x51, 0x6b, 
 0xc0, 0x46, 0xc1, 0x81, 0x51, 0x6b, 0xc2, 0x1d, 0x39, 0x32, 0x51, 0x83, 
-0x04, 0x23, 0x01, 0x68, 0x19, 0x43, 0x01, 0x60, 0x01, 0xf0, 0xb8, 0xf8, 
+0x04, 0x23, 0x01, 0x68, 0x19, 0x43, 0x01, 0x60, 0x01, 0xf0, 0xc2, 0xf8, 
 0x08, 0xbc, 0x18, 0x47, 0x0c, 0x2b, 0x00, 0x80, 
 0xb0, 0xb5, 0x1b, 0x4c, 0x20, 0x6a, 0x02, 0x28, 0x1b, 0xd2, 0x00, 0x20, 
 0xe7, 0x1d, 0x19, 0x37, 0x38, 0x71, 0xe1, 0x68, 0xe0, 0x1d, 0xf9, 0x30, 
@@ -555,1331 +556,1331 @@
 0x02, 0x28, 0x00, 0xd3, 0x3d, 0x71, 0xe0, 0x68, 0x00, 0x28, 0x02, 0xd0, 
 0x38, 0x79, 0x00, 0x28, 0xf1, 0xd0, 0xb0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 
 0x40, 0x6a, 0x00, 0x28, 0xf9, 0xd1, 0x00, 0x29, 0xf7, 0xd1, 0x60, 0x69, 
-0x00, 0x28, 0x04, 0xd0, 0x06, 0x48, 0x00, 0x68, 0x03, 0xf0, 0x9e, 0xfc, 
-0xef, 0xe7, 0x60, 0x68, 0x00, 0x28, 0xec, 0xd0, 0x00, 0xf0, 0x50, 0xf8, 
+0x00, 0x28, 0x04, 0xd0, 0x06, 0x48, 0x00, 0x68, 0x03, 0xf0, 0xa8, 0xfc, 
+0xef, 0xe7, 0x60, 0x68, 0x00, 0x28, 0xec, 0xd0, 0x00, 0xf0, 0x5a, 0xf8, 
 0xe9, 0xe7, 0x00, 0x00, 0x6c, 0x06, 0x00, 0x80, 0x34, 0x04, 0x00, 0x80, 
-0xb0, 0xb5, 0x07, 0x1c, 0x20, 0x23, 0xb8, 0x68, 0x18, 0x40, 0x00, 0x25, 
-0x00, 0x28, 0x03, 0xd1, 0x28, 0x1c, 0xb0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 
-0xc4, 0x23, 0x48, 0x68, 0x18, 0x40, 0x01, 0x24, 0x00, 0x28, 0x03, 0xd1, 
-0x38, 0x6a, 0x00, 0xf0, 0x09, 0xfc, 0x2f, 0xe0, 0x38, 0x1c, 0x00, 0xf0, 
-0x19, 0xfc, 0x38, 0x1c, 0x00, 0xf0, 0x78, 0xfa, 0xb8, 0x68, 0xc0, 0x08, 
-0x02, 0xd3, 0x38, 0x6a, 0x00, 0xf0, 0xce, 0xfb, 0xb8, 0x68, 0x39, 0x6a, 
-0xc0, 0x46, 0x88, 0x60, 0x38, 0x6a, 0xc0, 0x46, 0xc5, 0x60, 0x0f, 0x48, 
-0x41, 0x68, 0x00, 0x29, 0x11, 0xd1, 0xc1, 0x68, 0x00, 0x29, 0x09, 0xd1, 
-0x41, 0x69, 0x00, 0x29, 0x06, 0xd1, 0x39, 0x6a, 0xc0, 0x46, 0x81, 0x60, 
-0x41, 0x60, 0x00, 0xf0, 0x11, 0xf8, 0x0b, 0xe0, 0x39, 0x6a, 0xc0, 0x46, 
-0x81, 0x60, 0x41, 0x60, 0x06, 0xe0, 0x39, 0x6a, 0x82, 0x68, 0xc0, 0x46, 
-0xd1, 0x60, 0x39, 0x6a, 0xc0, 0x46, 0x81, 0x60, 0x20, 0x1c, 0xc0, 0xe7, 
-0x6c, 0x06, 0x00, 0x80, 0x90, 0xb5, 0x0b, 0x4c, 0x67, 0x68, 0x00, 0x2f, 
-0x0f, 0xd0, 0x38, 0x1c, 0x00, 0xf0, 0x12, 0xf8, 0x00, 0x28, 0x0a, 0xd1, 
-0x60, 0x68, 0xc0, 0x68, 0xc0, 0x46, 0x60, 0x60, 0x38, 0x1c, 0x00, 0xf0, 
-0xc3, 0xfb, 0x00, 0x20, 0x90, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x01, 0x20, 
-0xfa, 0xe7, 0x00, 0x00, 0x6c, 0x06, 0x00, 0x80, 0xf0, 0xb5, 0x07, 0x1c, 
-0xfe, 0x1d, 0x49, 0x36, 0x30, 0x78, 0x40, 0x00, 0xc0, 0x19, 0x85, 0x8b, 
-0x33, 0x4c, 0x34, 0x4b, 0x9d, 0x42, 0x3c, 0xd0, 0x38, 0x1c, 0x21, 0x1c, 
-0x2a, 0x1c, 0x00, 0xf0, 0x1d, 0xf9, 0x31, 0x48, 0x80, 0x6a, 0x58, 0x21, 
-0x69, 0x43, 0x40, 0x18, 0x01, 0x23, 0x9b, 0x07, 0x18, 0x43, 0x00, 0x68, 
-0x00, 0x04, 0x00, 0x0c, 0x2c, 0x4d, 0x01, 0x28, 0x1a, 0xd1, 0x30, 0x78, 
-0xc0, 0x19, 0xc1, 0x1d, 0x19, 0x31, 0x08, 0x7a, 0x3a, 0x68, 0x80, 0x18, 
-0x09, 0x7b, 0xea, 0x1d, 0x21, 0x32, 0x00, 0xf0, 0xe3, 0xfc, 0x30, 0x78, 
-0xc0, 0x19, 0x20, 0x30, 0x00, 0x79, 0x39, 0x68, 0x40, 0x18, 0xc1, 0x1d, 
-0x05, 0x31, 0x00, 0x20, 0x00, 0x23, 0x42, 0x00, 0x8b, 0x52, 0x01, 0x30, 
-0x06, 0x28, 0xfa, 0xd3, 0xa0, 0x88, 0x41, 0x07, 0x0b, 0xd1, 0x21, 0x89, 
-0x09, 0x18, 0x78, 0x68, 0x00, 0x04, 0x00, 0x0c, 0x81, 0x42, 0x04, 0xd8, 
-0x61, 0x89, 0xe2, 0x88, 0x89, 0x18, 0x81, 0x42, 0x03, 0xd9, 0x00, 0x20, 
-0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x21, 0x1c, 0x14, 0x4a, 0x00, 0x20, 
-0xfe, 0xf7, 0x64, 0xff, 0x01, 0x22, 0x52, 0x04, 0x78, 0x68, 0x02, 0x43, 
-0x01, 0x20, 0x39, 0x68, 0xfe, 0xf7, 0x5c, 0xff, 0x01, 0x22, 0x52, 0x04, 
-0x78, 0x68, 0x02, 0x43, 0x00, 0x20, 0x39, 0x68, 
-0xfe, 0xf7, 0x54, 0xff, 0x0b, 0x49, 0x0c, 0x4a, 0x01, 0x20, 0xfe, 0xf7, 
-0x4f, 0xff, 0x01, 0x20, 0xe9, 0x1d, 0x19, 0x31, 0x48, 0x71, 0x02, 0x21, 
-0xea, 0x1d, 0xf9, 0x32, 0x51, 0x62, 0xd9, 0xe7, 0x98, 0xad, 0x20, 0x40, 
-0xff, 0xff, 0x00, 0x00, 0x4c, 0x2a, 0x00, 0x80, 0x6c, 0x06, 0x00, 0x80, 
-0x54, 0x00, 0x03, 0x00, 0x84, 0xad, 0x20, 0x40, 0x14, 0x00, 0x07, 0x00, 
-0xf0, 0xb5, 0x83, 0xb0, 0x00, 0x21, 0x4f, 0x48, 0xc2, 0x1d, 0xf9, 0x32, 
-0x51, 0x62, 0x01, 0x21, 0xc9, 0x04, 0x4d, 0x4a, 0xc0, 0x46, 0x11, 0x60, 
-0xc1, 0x1d, 0x19, 0x31, 0x49, 0x79, 0x00, 0x29, 0x04, 0xd1, 0x4a, 0x48, 
-0x00, 0x68, 0x03, 0xf0, 0x9b, 0xfb, 0x87, 0xe0, 0x45, 0x48, 0x47, 0x68, 
-0xfc, 0x1d, 0x49, 0x34, 0x21, 0x78, 0x48, 0x00, 0xc0, 0x19, 0x80, 0x8b, 
-0x44, 0x4a, 0x92, 0x6a, 0x58, 0x23, 0x58, 0x43, 0x15, 0x18, 0x01, 0x23, 
-0x9b, 0x07, 0xea, 0x1d, 0x05, 0x32, 0x1a, 0x43, 0x12, 0x68, 0x08, 0x35, 
-0x2b, 0x43, 0x1d, 0x68, 0xff, 0x23, 0x1b, 0x02, 0x2b, 0x40, 0x1b, 0x0a, 
-0x3c, 0x4d, 0x01, 0x2b, 0x24, 0xd1, 0xc8, 0x19, 0xc1, 0x1d, 0x19, 0x31, 
-0x08, 0x7a, 0x3a, 0x68, 0x80, 0x18, 0x39, 0x4a, 0x09, 0x7b, 0x00, 0xf0, 
-0xc5, 0xfc, 0x20, 0x78, 0xc0, 0x19, 0x20, 0x30, 0x00, 0x79, 0x39, 0x68, 
-0x41, 0x18, 0x00, 0x20, 0x82, 0x00, 0x53, 0x19, 0x9b, 0x6e, 0x6e, 0x46, 
-0xb3, 0x50, 0x01, 0x30, 0x03, 0x28, 0xf7, 0xd3, 0xca, 0x1d, 0x05, 0x32, 
-0x69, 0x46, 0x00, 0x20, 0x43, 0x00, 0xcd, 0x5a, 0xc0, 0x46, 0xd5, 0x52, 
-0x01, 0x30, 0x06, 0x28, 0xf8, 0xd3, 0x2d, 0xe0, 0x02, 0x2b, 0x2b, 0xd1, 
-0x11, 0x0a, 0x29, 0xd3, 0x00, 0x21, 0x8a, 0x00, 0x53, 0x19, 0x9b, 0x6e, 
-0x6e, 0x46, 0xb3, 0x50, 0x01, 0x31, 0x03, 0x29, 0xf7, 0xd3, 0x21, 0x78, 
-0x49, 0x00, 0xc9, 0x19, 0x09, 0x8f, 0x3a, 0x68, 0x8b, 0x18, 0x6a, 0x46, 
-0x00, 0x21, 0x4d, 0x00, 0x56, 0x5b, 0xc0, 0x46, 0x5e, 0x53, 0x01, 0x31, 
-0x06, 0x29, 0xf8, 0xd3, 0x19, 0x49, 0x8a, 0x6a, 0x13, 0x18, 0x1a, 0x6d, 
-0x00, 0x9d, 0x55, 0x40, 0x19, 0x4a, 0xd6, 0x68, 0x75, 0x40, 0x1d, 0x65, 
-0x89, 0x6a, 0x08, 0x18, 0x41, 0x6d, 0x02, 0x9b, 0x59, 0x40, 0x92, 0x69, 
-0x51, 0x40, 0x41, 0x65, 0x20, 0x78, 0x41, 0x1e, 0x21, 0x70, 0x00, 0x28, 
-0x0d, 0xd0, 0x38, 0x1c, 0xff, 0xf7, 0xf4, 0xfe, 0x00, 0x28, 0x0d, 0xd1, 
-0x08, 0x4a, 0x50, 0x68, 0xc0, 0x68, 0xc0, 0x46, 0x50, 0x60, 0x38, 0x1c, 
-0x00, 0xf0, 0xa4, 0xfa, 0x02, 0xe0, 0x38, 0x1c, 0x00, 0xf0, 0x73, 0xfa, 
-0x01, 0xf0, 0xde, 0xfa, 0x03, 0xb0, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 
-0x6c, 0x06, 0x00, 0x80, 0x00, 0x00, 0x00, 0xb0, 0x38, 0x04, 0x00, 0x80, 
-0x4c, 0x2a, 0x00, 0x80, 0x1c, 0xad, 0x20, 0x40, 0x94, 0x06, 0x00, 0x80, 
-0x08, 0x83, 0x20, 0x40, 0xf0, 0xb5, 0x82, 0xb0, 0x69, 0x4b, 0x9f, 0x6a, 
-0x58, 0x23, 0x5a, 0x43, 0xba, 0x18, 0xc3, 0x1d, 0x49, 0x33, 0x1f, 0x78, 
-0x01, 0x23, 0x9b, 0x07, 0xd4, 0x1d, 0x01, 0x34, 0x23, 0x43, 0x1d, 0x68, 
-0x43, 0x68, 0x1c, 0x04, 0x01, 0x23, 0x9b, 0x07, 0xd6, 0x1d, 0x05, 0x36, 
-0x33, 0x43, 0x1b, 0x68, 0x1c, 0x43, 0x42, 0x23, 0x1c, 0x43, 0x0c, 0x60, 
-0xff, 0x26, 0x36, 0x02, 0x2e, 0x40, 0x01, 0x23, 0x5b, 0x02, 0x9e, 0x42, 
-0x74, 0xd1, 0x6b, 0x0c, 0x2b, 0xd3, 0xc3, 0x19, 0x20, 0x33, 0x1b, 0x79, 
+0xb0, 0xb5, 0x07, 0x1c, 0x20, 0x23, 0xb8, 0x68, 0x18, 0x40, 0x01, 0x24, 
+0x00, 0x25, 0x00, 0x28, 0x0b, 0xd1, 0x38, 0x6a, 0x00, 0x28, 0x03, 0xd1, 
+0x28, 0x1c, 0xb0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x1f, 0x48, 0x01, 0x6e, 
+0x01, 0x31, 0x01, 0x66, 0x03, 0xe0, 0x48, 0x68, 0xc4, 0x23, 0x18, 0x40, 
+0x03, 0xd1, 0x38, 0x6a, 0x00, 0xf0, 0x0c, 0xfc, 0x2f, 0xe0, 0x38, 0x1c, 
+0x00, 0xf0, 0x1c, 0xfc, 0x38, 0x1c, 0x00, 0xf0, 0x7b, 0xfa, 0xb8, 0x68, 
+0xc0, 0x08, 0x02, 0xd3, 0x38, 0x6a, 0x00, 0xf0, 0xd1, 0xfb, 0xb8, 0x68, 
+0x39, 0x6a, 0xc0, 0x46, 0x88, 0x60, 0x38, 0x6a, 0xc0, 0x46, 0xc5, 0x60, 
+0x10, 0x48, 0x41, 0x68, 0x00, 0x29, 0x11, 0xd1, 0xc1, 0x68, 0x00, 0x29, 
+0x09, 0xd1, 0x41, 0x69, 0x00, 0x29, 0x06, 0xd1, 0x39, 0x6a, 0xc0, 0x46, 
+0x81, 0x60, 0x41, 0x60, 0x00, 0xf0, 0x14, 0xf8, 0x0b, 0xe0, 0x39, 0x6a, 
+0xc0, 0x46, 0x81, 0x60, 0x41, 0x60, 0x06, 0xe0, 0x39, 0x6a, 0x82, 0x68, 
+0xc0, 0x46, 0xd1, 0x60, 0x39, 0x6a, 0xc0, 0x46, 0x81, 0x60, 0x20, 0x1c, 
+0xbd, 0xe7, 0x00, 0x00, 0xa4, 0x2a, 0x00, 0x80, 0x6c, 0x06, 0x00, 0x80, 
+0x90, 0xb5, 0x0b, 0x4c, 0x67, 0x68, 0x00, 0x2f, 0x0f, 0xd0, 0x38, 0x1c, 
+0x00, 0xf0, 0x12, 0xf8, 0x00, 0x28, 0x0a, 0xd1, 0x60, 0x68, 0xc0, 0x68, 
+0xc0, 0x46, 0x60, 0x60, 0x38, 0x1c, 0x00, 0xf0, 0xc3, 0xfb, 0x00, 0x20, 
+0x90, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x01, 0x20, 0xfa, 0xe7, 0x00, 0x00, 
+0x6c, 0x06, 0x00, 0x80, 0xf0, 0xb5, 0x07, 0x1c, 0xfe, 0x1d, 0x49, 0x36, 
+0x30, 0x78, 0x40, 0x00, 0xc0, 0x19, 0x85, 0x8b, 0x33, 0x4c, 0x34, 0x4b, 
+0x9d, 0x42, 0x3c, 0xd0, 0x38, 0x1c, 0x21, 0x1c, 0x2a, 0x1c, 0x00, 0xf0, 
+0x1d, 0xf9, 0x31, 0x48, 0x80, 0x6a, 0x58, 0x21, 0x69, 0x43, 0x40, 0x18, 
+0x01, 0x23, 0x9b, 0x07, 0x18, 0x43, 0x00, 0x68, 0x00, 0x04, 0x00, 0x0c, 
+0x2c, 0x4d, 0x01, 0x28, 0x1a, 0xd1, 0x30, 0x78, 0xc0, 0x19, 0xc1, 0x1d, 
+0x19, 0x31, 0x08, 0x7a, 0x3a, 0x68, 0x80, 0x18, 0x09, 0x7b, 0xea, 0x1d, 
+0x21, 0x32, 0x00, 0xf0, 0xe3, 0xfc, 0x30, 0x78, 0xc0, 0x19, 0x20, 0x30, 
+0x00, 0x79, 0x39, 0x68, 0x40, 0x18, 0xc1, 0x1d, 0x05, 0x31, 0x00, 0x20, 
+0x00, 0x23, 0x42, 0x00, 0x8b, 0x52, 0x01, 0x30, 0x06, 0x28, 0xfa, 0xd3, 
+0xa0, 0x88, 0x41, 0x07, 0x0b, 0xd1, 0x21, 0x89, 0x09, 0x18, 0x78, 0x68, 
+0x00, 0x04, 0x00, 0x0c, 0x81, 0x42, 0x04, 0xd8, 0x61, 0x89, 0xe2, 0x88, 
+0x89, 0x18, 0x81, 0x42, 0x03, 0xd9, 0x00, 0x20, 0xf0, 0xbc, 0x08, 0xbc, 
+0x18, 0x47, 0x21, 0x1c, 0x14, 0x4a, 0x00, 0x20, 0xfe, 0xf7, 0x5a, 0xff, 
+0x01, 0x22, 0x52, 0x04, 0x78, 0x68, 0x02, 0x43, 
+0x01, 0x20, 0x39, 0x68, 0xfe, 0xf7, 0x52, 0xff, 0x01, 0x22, 0x52, 0x04, 
+0x78, 0x68, 0x02, 0x43, 0x00, 0x20, 0x39, 0x68, 0xfe, 0xf7, 0x4a, 0xff, 
+0x0b, 0x49, 0x0c, 0x4a, 0x01, 0x20, 0xfe, 0xf7, 0x45, 0xff, 0x01, 0x20, 
+0xe9, 0x1d, 0x19, 0x31, 0x48, 0x71, 0x02, 0x21, 0xea, 0x1d, 0xf9, 0x32, 
+0x51, 0x62, 0xd9, 0xe7, 0x28, 0xac, 0x20, 0x40, 0xff, 0xff, 0x00, 0x00, 
+0x4c, 0x2a, 0x00, 0x80, 0x6c, 0x06, 0x00, 0x80, 0x54, 0x00, 0x03, 0x00, 
+0x14, 0xac, 0x20, 0x40, 0x14, 0x00, 0x07, 0x00, 0xf0, 0xb5, 0x83, 0xb0, 
+0x00, 0x21, 0x4f, 0x48, 0xc2, 0x1d, 0xf9, 0x32, 0x51, 0x62, 0x01, 0x21, 
+0xc9, 0x04, 0x4d, 0x4a, 0xc0, 0x46, 0x11, 0x60, 0xc1, 0x1d, 0x19, 0x31, 
+0x49, 0x79, 0x00, 0x29, 0x04, 0xd1, 0x4a, 0x48, 0x00, 0x68, 0x03, 0xf0, 
+0x9b, 0xfb, 0x87, 0xe0, 0x45, 0x48, 0x47, 0x68, 0xfc, 0x1d, 0x49, 0x34, 
+0x21, 0x78, 0x48, 0x00, 0xc0, 0x19, 0x80, 0x8b, 0x44, 0x4a, 0x92, 0x6a, 
+0x58, 0x23, 0x58, 0x43, 0x15, 0x18, 0x01, 0x23, 0x9b, 0x07, 0xea, 0x1d, 
+0x05, 0x32, 0x1a, 0x43, 0x12, 0x68, 0x08, 0x35, 0x2b, 0x43, 0x1d, 0x68, 
+0xff, 0x23, 0x1b, 0x02, 0x2b, 0x40, 0x1b, 0x0a, 0x3c, 0x4d, 0x01, 0x2b, 
+0x24, 0xd1, 0xc8, 0x19, 0xc1, 0x1d, 0x19, 0x31, 0x08, 0x7a, 0x3a, 0x68, 
+0x80, 0x18, 0x39, 0x4a, 0x09, 0x7b, 0x00, 0xf0, 0xc5, 0xfc, 0x20, 0x78, 
+0xc0, 0x19, 0x20, 0x30, 0x00, 0x79, 0x39, 0x68, 0x41, 0x18, 0x00, 0x20, 
+0x82, 0x00, 0x53, 0x19, 0x9b, 0x6e, 0x6e, 0x46, 0xb3, 0x50, 0x01, 0x30, 
+0x03, 0x28, 0xf7, 0xd3, 0xca, 0x1d, 0x05, 0x32, 0x69, 0x46, 0x00, 0x20, 
+0x43, 0x00, 0xcd, 0x5a, 0xc0, 0x46, 0xd5, 0x52, 0x01, 0x30, 0x06, 0x28, 
+0xf8, 0xd3, 0x2d, 0xe0, 0x02, 0x2b, 0x2b, 0xd1, 0x11, 0x0a, 0x29, 0xd3, 
+0x00, 0x21, 0x8a, 0x00, 0x53, 0x19, 0x9b, 0x6e, 0x6e, 0x46, 0xb3, 0x50, 
+0x01, 0x31, 0x03, 0x29, 0xf7, 0xd3, 0x21, 0x78, 0x49, 0x00, 0xc9, 0x19, 
+0x09, 0x8f, 0x3a, 0x68, 0x8b, 0x18, 0x6a, 0x46, 0x00, 0x21, 0x4d, 0x00, 
+0x56, 0x5b, 0xc0, 0x46, 0x5e, 0x53, 0x01, 0x31, 0x06, 0x29, 0xf8, 0xd3, 
+0x19, 0x49, 0x8a, 0x6a, 0x13, 0x18, 0x1a, 0x6d, 0x00, 0x9d, 0x55, 0x40, 
+0x19, 0x4a, 0xd6, 0x68, 0x75, 0x40, 0x1d, 0x65, 0x89, 0x6a, 0x08, 0x18, 
+0x41, 0x6d, 0x02, 0x9b, 0x59, 0x40, 0x92, 0x69, 0x51, 0x40, 0x41, 0x65, 
+0x20, 0x78, 0x41, 0x1e, 0x21, 0x70, 0x00, 0x28, 0x0d, 0xd0, 0x38, 0x1c, 
+0xff, 0xf7, 0xf4, 0xfe, 0x00, 0x28, 0x0d, 0xd1, 0x08, 0x4a, 0x50, 0x68, 
+0xc0, 0x68, 0xc0, 0x46, 0x50, 0x60, 0x38, 0x1c, 0x00, 0xf0, 0xa4, 0xfa, 
+0x02, 0xe0, 0x38, 0x1c, 0x00, 0xf0, 0x73, 0xfa, 0x01, 0xf0, 0xde, 0xfa, 
+0x03, 0xb0, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x6c, 0x06, 0x00, 0x80, 
+0x00, 0x00, 0x00, 0xb0, 0x38, 0x04, 0x00, 0x80, 0x4c, 0x2a, 0x00, 0x80, 
+0xac, 0xab, 0x20, 0x40, 0x94, 0x06, 0x00, 0x80, 0x08, 0x83, 0x20, 0x40, 
+0xf0, 0xb5, 0x82, 0xb0, 0x69, 0x4b, 0x9f, 0x6a, 0x58, 0x23, 0x5a, 0x43, 
+0xba, 0x18, 0xc3, 0x1d, 0x49, 0x33, 0x1f, 0x78, 0x01, 0x23, 0x9b, 0x07, 
+0xd4, 0x1d, 0x01, 0x34, 0x23, 0x43, 0x1d, 0x68, 0x43, 0x68, 0x1c, 0x04, 
+0x01, 0x23, 0x9b, 0x07, 0xd6, 0x1d, 0x05, 0x36, 0x33, 0x43, 0x1b, 0x68, 
+0x1c, 0x43, 0x42, 0x23, 0x1c, 0x43, 0x0c, 0x60, 0xff, 0x26, 0x36, 0x02, 
+0x2e, 0x40, 0x01, 0x23, 0x5b, 0x02, 0x9e, 0x42, 0x74, 0xd1, 0x6b, 0x0c, 
+0x2b, 0xd3, 0xc3, 0x19, 0x20, 0x33, 0x1b, 0x79, 
 0xc0, 0x46, 0x4b, 0x81, 0x7b, 0x00, 0x1b, 0x18, 0x1b, 0x8f, 0x4c, 0x89, 
-0x1b, 0x1b, 0xcb, 0x80, 0x00, 0x24, 0xa6, 0x00, 
-0x01, 0x96, 0xb3, 0x18, 0xde, 0x1d, 0x09, 0x36, 0x01, 0x23, 0x9b, 0x07, 
-0x33, 0x43, 0x1b, 0x68, 0x01, 0x9e, 0x76, 0x18, 0x73, 0x61, 0x01, 0x34, 
-0x05, 0x2c, 0xf0, 0xd3, 0x00, 0x24, 0xa6, 0x00, 0x00, 0x96, 0xb3, 0x18, 
-0xde, 0x1d, 0x1d, 0x36, 0x01, 0x23, 0x9b, 0x07, 0x33, 0x43, 0x1b, 0x68, 
-0x00, 0x9e, 0x76, 0x18, 0xb3, 0x62, 0x01, 0x34, 0x05, 0x2c, 0xf0, 0xd3, 
-0x06, 0xe0, 0x00, 0x23, 0x4b, 0x81, 0xcb, 0x80, 0x40, 0x23, 0x9c, 0x43, 
-0x0c, 0x60, 0x23, 0x1c, 0x6b, 0x0e, 0x4a, 0xd3, 0xc3, 0x19, 0x20, 0x33, 
-0x1b, 0x79, 0x10, 0x33, 0x0b, 0x81, 0x7b, 0x00, 0x1b, 0x18, 0x1b, 0x8f, 
-0x0f, 0x89, 0xdb, 0x1b, 0x8b, 0x80, 0x01, 0x23, 0x9b, 0x07, 0xd4, 0x1d, 
-0x35, 0x34, 0x23, 0x43, 0x1b, 0x68, 0xc0, 0x46, 0xcb, 0x63, 0x01, 0x23, 
-0x9b, 0x07, 0xd4, 0x1d, 0x31, 0x34, 0x23, 0x43, 0x1b, 0x68, 0xc0, 0x46, 
-0x0b, 0x64, 0xab, 0x0e, 0x21, 0xd2, 0x01, 0x23, 0x9b, 0x07, 0xd4, 0x1d, 
-0x3d, 0x34, 0x23, 0x43, 0x1b, 0x68, 0xc0, 0x46, 0x4b, 0x64, 0x01, 0x23, 
-0x9b, 0x07, 0xd4, 0x1d, 0x39, 0x34, 0x23, 0x43, 0x1b, 0x68, 0xc0, 0x46, 
-0x8b, 0x64, 0x01, 0x23, 0x9b, 0x07, 0xd4, 0x1d, 0x45, 0x34, 0x23, 0x43, 
-0x1b, 0x68, 0xc0, 0x46, 0xcb, 0x64, 0x01, 0x23, 0x9b, 0x07, 0xd4, 0x1d, 
-0x41, 0x34, 0x23, 0x43, 0x1b, 0x68, 0xc0, 0x46, 0x0b, 0x65, 0x00, 0xe0, 
-0x0f, 0xe0, 0xfb, 0x1f, 0x01, 0x3b, 0x1b, 0x04, 0x1b, 0x0c, 0x07, 0x68, 
-0xff, 0x18, 0x03, 0x69, 0x08, 0x1c, 0x39, 0x1c, 0x00, 0xf0, 0x34, 0xf8, 
-0x2c, 0xe0, 0x00, 0x23, 0x0b, 0x81, 0x8b, 0x80, 0x28, 0xe0, 0x00, 0x23, 
-0x8b, 0x80, 0x0b, 0x81, 0xc3, 0x19, 0x20, 0x33, 0x1b, 0x7a, 0xc0, 0x46, 
-0x4b, 0x81, 0x7b, 0x00, 0x18, 0x18, 0x00, 0x8e, 0xc0, 0x46, 0xc8, 0x80, 
-0x00, 0x20, 0x87, 0x00, 0xbb, 0x18, 0xdc, 0x1d, 0x09, 0x34, 0x01, 0x23, 
-0x9b, 0x07, 0x23, 0x43, 0x1b, 0x68, 0x7f, 0x18, 0x7b, 0x61, 0x01, 0x30, 
-0x05, 0x28, 0xf2, 0xd3, 0x00, 0x20, 0x87, 0x00, 0xbb, 0x18, 0xdc, 0x1d, 
-0x1d, 0x34, 0x01, 0x23, 0x9b, 0x07, 0x23, 0x43, 0x1b, 0x68, 0x7f, 0x18, 
-0xbb, 0x62, 0x01, 0x30, 0x05, 0x28, 0xf2, 0xd3, 0x02, 0xb0, 0xf0, 0xbc, 
-0x08, 0xbc, 0x18, 0x47, 0x4c, 0x2a, 0x00, 0x80, 0x80, 0xb4, 0x1f, 0x1c, 
-0x3b, 0x0c, 0x18, 0xd2, 0x17, 0x6d, 0x11, 0x4b, 0xc0, 0x46, 0xdf, 0x60, 
-0x52, 0x6d, 0xc0, 0x46, 0x1a, 0x61, 0xc7, 0x60, 0x1a, 0x69, 0xc0, 0x46, 
-0x02, 0x61, 0xd8, 0x68, 0xc0, 0x46, 0x08, 0x80, 0xd8, 0x68, 0x00, 0x0c, 
-0x48, 0x80, 0x18, 0x69, 0xc0, 0x46, 0x88, 0x80, 0x18, 0x69, 0x00, 0x0c, 
-0xc8, 0x80, 0x80, 0xbc, 0x70, 0x47, 0x4a, 0x88, 0x12, 0x04, 0x0b, 0x88, 
-0x1a, 0x43, 0xc2, 0x60, 0x8a, 0x88, 0xc9, 0x88, 0x09, 0x04, 0x11, 0x43, 
-0x01, 0x61, 0xf2, 0xe7, 0x2c, 0x07, 0x00, 0x80, 0xf1, 0xb5, 0x88, 0xb0, 
-0x00, 0x22, 0x08, 0x98, 0x00, 0x6a, 0x08, 0x9b, 0x99, 0x68, 0x49, 0x0a, 
-0x02, 0xd3, 0x01, 0x27, 0xff, 0x03, 0x00, 0xe0, 0x00, 0x27, 0x03, 0x8b, 
-0x00, 0x2b, 0x19, 0xd0, 0xa3, 0x49, 0x89, 0x6a, 0x1c, 0x1c, 0x58, 0x23, 
-0x63, 0x43, 0xc9, 0x18, 0x01, 0x23, 0x9b, 0x07, 0x58, 0x39, 0x19, 0x43, 
-0x09, 0x68, 0x09, 0x04, 0x09, 0x0c, 0x02, 0x29, 0x02, 0xd1, 0x08, 0x23, 
-0x1f, 0x43, 0x07, 0xe0, 0x41, 0x8b, 0x00, 0x29, 0x02, 0xd0, 0x0c, 0x23, 
+0x1b, 0x1b, 0xcb, 0x80, 0x00, 0x24, 0xa6, 0x00, 0x01, 0x96, 0xb3, 0x18, 
+0xde, 0x1d, 0x09, 0x36, 0x01, 0x23, 0x9b, 0x07, 0x33, 0x43, 0x1b, 0x68, 
+0x01, 0x9e, 0x76, 0x18, 0x73, 0x61, 0x01, 0x34, 0x05, 0x2c, 0xf0, 0xd3, 
+0x00, 0x24, 0xa6, 0x00, 0x00, 0x96, 0xb3, 0x18, 0xde, 0x1d, 0x1d, 0x36, 
+0x01, 0x23, 0x9b, 0x07, 0x33, 0x43, 0x1b, 0x68, 0x00, 0x9e, 0x76, 0x18, 
+0xb3, 0x62, 0x01, 0x34, 0x05, 0x2c, 0xf0, 0xd3, 0x06, 0xe0, 0x00, 0x23, 
+0x4b, 0x81, 0xcb, 0x80, 0x40, 0x23, 0x9c, 0x43, 0x0c, 0x60, 0x23, 0x1c, 
+0x6b, 0x0e, 0x4a, 0xd3, 0xc3, 0x19, 0x20, 0x33, 0x1b, 0x79, 0x10, 0x33, 
+0x0b, 0x81, 0x7b, 0x00, 0x1b, 0x18, 0x1b, 0x8f, 0x0f, 0x89, 0xdb, 0x1b, 
+0x8b, 0x80, 0x01, 0x23, 0x9b, 0x07, 0xd4, 0x1d, 0x35, 0x34, 0x23, 0x43, 
+0x1b, 0x68, 0xc0, 0x46, 0xcb, 0x63, 0x01, 0x23, 0x9b, 0x07, 0xd4, 0x1d, 
+0x31, 0x34, 0x23, 0x43, 0x1b, 0x68, 0xc0, 0x46, 0x0b, 0x64, 0xab, 0x0e, 
+0x21, 0xd2, 0x01, 0x23, 0x9b, 0x07, 0xd4, 0x1d, 0x3d, 0x34, 0x23, 0x43, 
+0x1b, 0x68, 0xc0, 0x46, 0x4b, 0x64, 0x01, 0x23, 0x9b, 0x07, 0xd4, 0x1d, 
+0x39, 0x34, 0x23, 0x43, 0x1b, 0x68, 0xc0, 0x46, 0x8b, 0x64, 0x01, 0x23, 
+0x9b, 0x07, 0xd4, 0x1d, 0x45, 0x34, 0x23, 0x43, 0x1b, 0x68, 0xc0, 0x46, 
+0xcb, 0x64, 0x01, 0x23, 0x9b, 0x07, 0xd4, 0x1d, 0x41, 0x34, 0x23, 0x43, 
+0x1b, 0x68, 0xc0, 0x46, 0x0b, 0x65, 0x00, 0xe0, 0x0f, 0xe0, 0xfb, 0x1f, 
+0x01, 0x3b, 0x1b, 0x04, 0x1b, 0x0c, 0x07, 0x68, 0xff, 0x18, 0x03, 0x69, 
+0x08, 0x1c, 0x39, 0x1c, 0x00, 0xf0, 0x34, 0xf8, 0x2c, 0xe0, 0x00, 0x23, 
+0x0b, 0x81, 0x8b, 0x80, 0x28, 0xe0, 0x00, 0x23, 0x8b, 0x80, 0x0b, 0x81, 
+0xc3, 0x19, 0x20, 0x33, 0x1b, 0x7a, 0xc0, 0x46, 0x4b, 0x81, 0x7b, 0x00, 
+0x18, 0x18, 0x00, 0x8e, 0xc0, 0x46, 0xc8, 0x80, 0x00, 0x20, 0x87, 0x00, 
+0xbb, 0x18, 0xdc, 0x1d, 0x09, 0x34, 0x01, 0x23, 0x9b, 0x07, 0x23, 0x43, 
+0x1b, 0x68, 0x7f, 0x18, 0x7b, 0x61, 0x01, 0x30, 0x05, 0x28, 0xf2, 0xd3, 
+0x00, 0x20, 0x87, 0x00, 0xbb, 0x18, 0xdc, 0x1d, 0x1d, 0x34, 0x01, 0x23, 
+0x9b, 0x07, 0x23, 0x43, 0x1b, 0x68, 0x7f, 0x18, 0xbb, 0x62, 0x01, 0x30, 
+0x05, 0x28, 0xf2, 0xd3, 0x02, 0xb0, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 
+0x4c, 0x2a, 0x00, 0x80, 0x80, 0xb4, 0x1f, 0x1c, 0x3b, 0x0c, 0x18, 0xd2, 
+0x17, 0x6d, 0x11, 0x4b, 0xc0, 0x46, 0xdf, 0x60, 0x52, 0x6d, 0xc0, 0x46, 
+0x1a, 0x61, 0xc7, 0x60, 0x1a, 0x69, 0xc0, 0x46, 0x02, 0x61, 0xd8, 0x68, 
+0xc0, 0x46, 0x08, 0x80, 0xd8, 0x68, 0x00, 0x0c, 0x48, 0x80, 0x18, 0x69, 
+0xc0, 0x46, 0x88, 0x80, 0x18, 0x69, 0x00, 0x0c, 0xc8, 0x80, 0x80, 0xbc, 
+0x70, 0x47, 0x4a, 0x88, 0x12, 0x04, 0x0b, 0x88, 0x1a, 0x43, 0xc2, 0x60, 
+0x8a, 0x88, 0xc9, 0x88, 0x09, 0x04, 0x11, 0x43, 0x01, 0x61, 0xf2, 0xe7, 
+0x2c, 0x07, 0x00, 0x80, 0xf1, 0xb5, 0x88, 0xb0, 0x00, 0x22, 0x08, 0x98, 
+0x00, 0x6a, 0x08, 0x9b, 0x99, 0x68, 0x49, 0x0a, 0x02, 0xd3, 0x01, 0x27, 
+0xff, 0x03, 0x00, 0xe0, 0x00, 0x27, 0x03, 0x8b, 0x00, 0x2b, 0x19, 0xd0, 
+0xa3, 0x49, 0x89, 0x6a, 0x1c, 0x1c, 0x58, 0x23, 0x63, 0x43, 0xc9, 0x18, 
+0x01, 0x23, 0x9b, 0x07, 0x58, 0x39, 0x19, 0x43, 0x09, 0x68, 0x09, 0x04, 
+0x09, 0x0c, 0x02, 0x29, 0x02, 0xd1, 0x08, 0x23, 0x1f, 0x43, 0x07, 0xe0, 
+0x41, 0x8b, 0x00, 0x29, 0x02, 0xd0, 0x0c, 0x23, 
 0x1f, 0x43, 0x01, 0xe0, 0x04, 0x23, 0x1f, 0x43, 0x83, 0x8a, 0x00, 0x2b, 
-0x18, 0xd0, 0x95, 0x49, 0x89, 0x6a, 0x1c, 0x1c, 
-0x58, 0x23, 0x63, 0x43, 0xc9, 0x18, 0x01, 0x23, 0x9b, 0x07, 0x58, 0x39, 
-0x19, 0x43, 0x09, 0x68, 0x09, 0x04, 0x09, 0x0c, 0x02, 0x29, 0x01, 0xd1, 
-0x0f, 0x43, 0x07, 0xe0, 0xc1, 0x8a, 0x00, 0x29, 0x02, 0xd0, 0x03, 0x23, 
-0x1f, 0x43, 0x01, 0xe0, 0x01, 0x23, 0x1f, 0x43, 0xc1, 0x1d, 0x39, 0x31, 
-0x07, 0x91, 0x4b, 0x89, 0x0c, 0x89, 0x1c, 0x19, 0x24, 0x04, 0x24, 0x0c, 
-0x08, 0x9d, 0x2d, 0x68, 0xc0, 0x46, 0x01, 0x95, 0xc9, 0x88, 0x7d, 0x08, 
-0x1a, 0xd3, 0x1a, 0x1c, 0xc3, 0x1d, 0x19, 0x33, 0x1a, 0x72, 0x07, 0x9a, 
-0x92, 0x89, 0xc0, 0x46, 0x1a, 0x73, 0x07, 0x9a, 0x12, 0x89, 0xc0, 0x46, 
-0x02, 0x86, 0x04, 0x87, 0x82, 0x8a, 0x01, 0x3a, 0x82, 0x83, 0x01, 0x22, 
-0x19, 0x71, 0x08, 0x9b, 0x1b, 0x68, 0x5b, 0x18, 0x5b, 0x78, 0x9b, 0x00, 
-0x1b, 0x04, 0x1b, 0x0c, 0x08, 0x33, 0x59, 0x18, 0xbb, 0x08, 0x47, 0xd3, 
-0x07, 0x9b, 0x5b, 0x89, 0x85, 0x18, 0x06, 0x95, 0x20, 0x35, 0x2b, 0x72, 
-0x07, 0x9b, 0x9b, 0x89, 0xc0, 0x46, 0x2b, 0x73, 0x07, 0x9b, 0x1b, 0x89, 
-0x2e, 0x1c, 0x55, 0x00, 0x2d, 0x18, 0x05, 0x95, 0x2b, 0x86, 0x00, 0x2a, 
-0x01, 0xd0, 0xc3, 0x8a, 0x00, 0xe0, 0x83, 0x8a, 0x01, 0x3b, 0x05, 0x9d, 
-0xc0, 0x46, 0xab, 0x83, 0x31, 0x71, 0x65, 0x4b, 0x9d, 0x6a, 0x05, 0x9b, 
+0x18, 0xd0, 0x95, 0x49, 0x89, 0x6a, 0x1c, 0x1c, 0x58, 0x23, 0x63, 0x43, 
+0xc9, 0x18, 0x01, 0x23, 0x9b, 0x07, 0x58, 0x39, 0x19, 0x43, 0x09, 0x68, 
+0x09, 0x04, 0x09, 0x0c, 0x02, 0x29, 0x01, 0xd1, 0x0f, 0x43, 0x07, 0xe0, 
+0xc1, 0x8a, 0x00, 0x29, 0x02, 0xd0, 0x03, 0x23, 0x1f, 0x43, 0x01, 0xe0, 
+0x01, 0x23, 0x1f, 0x43, 0xc1, 0x1d, 0x39, 0x31, 0x07, 0x91, 0x4b, 0x89, 
+0x0c, 0x89, 0x1c, 0x19, 0x24, 0x04, 0x24, 0x0c, 0x08, 0x9d, 0x2d, 0x68, 
+0xc0, 0x46, 0x01, 0x95, 0xc9, 0x88, 0x7d, 0x08, 0x1a, 0xd3, 0x1a, 0x1c, 
+0xc3, 0x1d, 0x19, 0x33, 0x1a, 0x72, 0x07, 0x9a, 0x92, 0x89, 0xc0, 0x46, 
+0x1a, 0x73, 0x07, 0x9a, 0x12, 0x89, 0xc0, 0x46, 0x02, 0x86, 0x04, 0x87, 
+0x82, 0x8a, 0x01, 0x3a, 0x82, 0x83, 0x01, 0x22, 0x19, 0x71, 0x08, 0x9b, 
+0x1b, 0x68, 0x5b, 0x18, 0x5b, 0x78, 0x9b, 0x00, 0x1b, 0x04, 0x1b, 0x0c, 
+0x08, 0x33, 0x59, 0x18, 0xbb, 0x08, 0x47, 0xd3, 0x07, 0x9b, 0x5b, 0x89, 
+0x85, 0x18, 0x06, 0x95, 0x20, 0x35, 0x2b, 0x72, 0x07, 0x9b, 0x9b, 0x89, 
+0xc0, 0x46, 0x2b, 0x73, 0x07, 0x9b, 0x1b, 0x89, 0x2e, 0x1c, 0x55, 0x00, 
+0x2d, 0x18, 0x05, 0x95, 0x2b, 0x86, 0x00, 0x2a, 0x01, 0xd0, 0xc3, 0x8a, 
+0x00, 0xe0, 0x83, 0x8a, 0x01, 0x3b, 0x05, 0x9d, 0xc0, 0x46, 0xab, 0x83, 
+0x31, 0x71, 0x65, 0x4b, 0x9d, 0x6a, 0x05, 0x9b, 0x9e, 0x8b, 0x58, 0x23, 
+0x73, 0x43, 0xeb, 0x18, 0xdd, 0x1d, 0x01, 0x35, 0x01, 0x23, 0x9b, 0x07, 
+0x2b, 0x43, 0x1d, 0x68, 0x2b, 0x0e, 0x5b, 0x06, 0x01, 0xd1, 0x08, 0x31, 
+0x00, 0xe0, 0x10, 0x31, 0x81, 0x23, 0x5b, 0x02, 0x1d, 0x40, 0x9d, 0x42, 
+0x03, 0xd1, 0xe3, 0x1f, 0x05, 0x3b, 0x1c, 0x04, 0x24, 0x0c, 0x05, 0x9b, 
+0xc0, 0x46, 0x1c, 0x87, 0x08, 0x9b, 0x1b, 0x68, 0x1b, 0x19, 0x10, 0x3b, 
+0x9b, 0x7b, 0x06, 0x9d, 0x40, 0x35, 0x2b, 0x70, 0x2b, 0x78, 0x02, 0x33, 
+0xe3, 0x1a, 0x1c, 0x04, 0x24, 0x0c, 0x01, 0x32, 0xbb, 0x08, 0x9b, 0x07, 
+0x6d, 0xd0, 0x83, 0x18, 0x20, 0x33, 0x04, 0x93, 0x19, 0x72, 0x01, 0x9b, 
+0x5d, 0x18, 0x01, 0x23, 0x9b, 0x07, 0x2b, 0x43, 0x1b, 0x68, 0x1b, 0x07, 
+0x1b, 0x0f, 0x9b, 0x00, 0x04, 0x9e, 0xc0, 0x46, 0x33, 0x73, 0x00, 0x95, 
+0x2b, 0x78, 0x1b, 0x07, 0x1b, 0x0f, 0x9b, 0x00, 0x04, 0x9d, 0xc0, 0x46, 
+0x2b, 0x73, 0x00, 0x9d, 0xeb, 0x78, 0xad, 0x78, 0x1b, 0x02, 0x1d, 0x43, 
+0x2b, 0x02, 0x2d, 0x0a, 0x2d, 0x06, 0x2d, 0x0e, 0x2b, 0x43, 0x55, 0x00, 
+0x2d, 0x18, 0x2b, 0x86, 0x04, 0x9b, 0xc0, 0x46, 0x59, 0x72, 0x04, 0x9b, 
+0x1b, 0x7b, 0x2e, 0x1c, 0x04, 0x9d, 0xc0, 0x46, 0x6b, 0x73, 0x33, 0x8e, 
+0xc0, 0x46, 0x73, 0x86, 0x00, 0x9d, 0x2b, 0x78, 0x1b, 0x07, 0x1b, 0x0f, 
+0x9b, 0x00, 0x1b, 0x04, 0x1b, 0x0c, 0x59, 0x18, 0x04, 0x25, 0x3d, 0x40, 
+0x0e, 0xd0, 0x34, 0x87, 0x03, 0x8b, 0x01, 0x3b, 0xb3, 0x83, 0x13, 0x1c, 
+0x1b, 0x18, 0x20, 0x33, 0x19, 0x71, 0x01, 0x9b, 0x5b, 0x18, 0x5b, 0x78, 
+0x9b, 0x00, 0x59, 0x18, 0x08, 0x31, 0x01, 0x32, 0x3b, 0x09, 0x37, 0xd3, 
+0x00, 0x2d, 0x01, 0xd0, 0x43, 0x8b, 0x00, 0xe0, 0x03, 0x8b, 0x55, 0x00, 
+0x2d, 0x18, 0x01, 0x3b, 0xab, 0x83, 0x83, 0x18, 0x03, 0x93, 0x20, 0x33, 
+0x19, 0x71, 0x20, 0x4b, 0x9d, 0x6a, 0x53, 0x00, 0x1b, 0x18, 0x02, 0x93, 
 0x9e, 0x8b, 0x58, 0x23, 0x73, 0x43, 0xeb, 0x18, 0xdd, 0x1d, 0x01, 0x35, 
-0x01, 0x23, 0x9b, 0x07, 0x2b, 0x43, 0x1d, 0x68, 0x2b, 0x0e, 0x5b, 0x06, 
-0x01, 0xd1, 0x08, 0x31, 0x00, 0xe0, 0x10, 0x31, 0x81, 0x23, 0x5b, 0x02, 
-0x1d, 0x40, 0x9d, 0x42, 0x03, 0xd1, 0xe3, 0x1f, 0x05, 0x3b, 0x1c, 0x04, 
-0x24, 0x0c, 0x05, 0x9b, 0xc0, 0x46, 0x1c, 0x87, 0x08, 0x9b, 0x1b, 0x68, 
-0x1b, 0x19, 0x10, 0x3b, 0x9b, 0x7b, 0x06, 0x9d, 0x40, 0x35, 0x2b, 0x70, 
-0x2b, 0x78, 0x02, 0x33, 0xe3, 0x1a, 0x1c, 0x04, 0x24, 0x0c, 0x01, 0x32, 
-0xbb, 0x08, 0x9b, 0x07, 0x6d, 0xd0, 0x83, 0x18, 0x20, 0x33, 0x04, 0x93, 
-0x19, 0x72, 0x01, 0x9b, 0x5d, 0x18, 0x01, 0x23, 0x9b, 0x07, 0x2b, 0x43, 
-0x1b, 0x68, 0x1b, 0x07, 0x1b, 0x0f, 0x9b, 0x00, 0x04, 0x9e, 0xc0, 0x46, 
-0x33, 0x73, 0x00, 0x95, 0x2b, 0x78, 0x1b, 0x07, 0x1b, 0x0f, 0x9b, 0x00, 
-0x04, 0x9d, 0xc0, 0x46, 0x2b, 0x73, 0x00, 0x9d, 0xeb, 0x78, 0xad, 0x78, 
-0x1b, 0x02, 0x1d, 0x43, 0x2b, 0x02, 0x2d, 0x0a, 0x2d, 0x06, 0x2d, 0x0e, 
-0x2b, 0x43, 0x55, 0x00, 0x2d, 0x18, 0x2b, 0x86, 0x04, 0x9b, 0xc0, 0x46, 
-0x59, 0x72, 0x04, 0x9b, 0x1b, 0x7b, 0x2e, 0x1c, 0x04, 0x9d, 0xc0, 0x46, 
-0x6b, 0x73, 0x33, 0x8e, 0xc0, 0x46, 0x73, 0x86, 0x00, 0x9d, 0x2b, 0x78, 
-0x1b, 0x07, 0x1b, 0x0f, 0x9b, 0x00, 0x1b, 0x04, 0x1b, 0x0c, 0x59, 0x18, 
-0x04, 0x25, 0x3d, 0x40, 0x0e, 0xd0, 0x34, 0x87, 0x03, 0x8b, 0x01, 0x3b, 
-0xb3, 0x83, 0x13, 0x1c, 0x1b, 0x18, 0x20, 0x33, 0x19, 0x71, 0x01, 0x9b, 
-0x5b, 0x18, 0x5b, 0x78, 0x9b, 0x00, 0x59, 0x18, 0x08, 0x31, 0x01, 0x32, 
-0x3b, 0x09, 0x37, 0xd3, 0x00, 0x2d, 0x01, 0xd0, 0x43, 0x8b, 0x00, 0xe0, 
-0x03, 0x8b, 0x55, 0x00, 0x2d, 0x18, 0x01, 0x3b, 0xab, 0x83, 0x83, 0x18, 
-0x03, 0x93, 0x20, 0x33, 0x19, 0x71, 0x20, 0x4b, 0x9d, 0x6a, 0x53, 0x00, 
-0x1b, 0x18, 0x02, 0x93, 0x9e, 0x8b, 0x58, 0x23, 0x73, 0x43, 0xeb, 0x18, 
-0xdd, 0x1d, 0x01, 0x35, 0x01, 0x23, 0x9b, 0x07, 0x2b, 0x43, 0x1d, 0x68, 
+0x01, 0x23, 0x9b, 0x07, 0x2b, 0x43, 0x1d, 0x68, 
 0x2b, 0x0e, 0x5b, 0x06, 0x02, 0xd1, 0x08, 0x31, 0x01, 0xe0, 0x15, 0xe0, 
-0x10, 0x31, 0x81, 0x23, 0x5b, 0x02, 0x1d, 0x40, 
-0x9d, 0x42, 0x03, 0xd1, 0xe3, 0x1f, 0x05, 0x3b, 0x1c, 0x04, 0x24, 0x0c, 
-0x02, 0x9b, 0xc0, 0x46, 0x1c, 0x87, 0x08, 0x9b, 0x1b, 0x68, 0x1b, 0x19, 
-0x10, 0x3b, 0x9b, 0x7b, 0x03, 0x9c, 0x40, 0x34, 0x23, 0x70, 0x01, 0x32, 
-0x07, 0x9b, 0xc0, 0x46, 0xd9, 0x80, 0x51, 0x1e, 0xc3, 0x1d, 0x49, 0x33, 
-0x19, 0x70, 0x07, 0x61, 0x04, 0x2a, 0x06, 0xd2, 0x06, 0x49, 0x53, 0x00, 
-0x1b, 0x18, 0x99, 0x83, 0x01, 0x32, 0x04, 0x2a, 0xf9, 0xd3, 0x09, 0xb0, 
-0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0x4c, 0x2a, 0x00, 0x80, 
-0xff, 0xff, 0x00, 0x00, 0x70, 0x47, 0x80, 0xb5, 0x8c, 0xb0, 0x07, 0x1c, 
-0x12, 0x48, 0x01, 0x68, 0x01, 0x31, 0x01, 0x60, 0x38, 0x68, 0xc0, 0x46, 
-0x00, 0x90, 0x78, 0x68, 0xc0, 0x46, 0x01, 0x90, 0xb8, 0x68, 0xc0, 0x46, 
-0x02, 0x90, 0x0d, 0x48, 0x41, 0x68, 0xc9, 0x68, 0xc0, 0x46, 0x41, 0x60, 
-0x38, 0x1c, 0x00, 0xf0, 0x4f, 0xf8, 0xb8, 0x68, 0x40, 0x09, 0x06, 0xd3, 
-0x10, 0x23, 0x02, 0x98, 0x18, 0x43, 0x02, 0x90, 0x68, 0x46, 0x02, 0xf0, 
-0xe1, 0xff, 0x68, 0x46, 0x02, 0xf0, 0x9a, 0xfe, 0x0c, 0xb0, 0x80, 0xbc, 
-0x08, 0xbc, 0x18, 0x47, 0x0c, 0x2b, 0x00, 0x80, 0x6c, 0x06, 0x00, 0x80, 
-0x00, 0xb5, 0x8c, 0xb0, 0x01, 0x68, 0xc0, 0x46, 0x00, 0x91, 0x41, 0x68, 
-0x05, 0x4b, 0x19, 0x43, 0x01, 0x91, 0x00, 0xf0, 0x2f, 0xf8, 0x68, 0x46, 
-0x02, 0xf0, 0x84, 0xfe, 0x0c, 0xb0, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 
-0x00, 0x00, 0x00, 0xa0, 0x02, 0x6a, 0x03, 0x68, 0xc0, 0x46, 0x13, 0x60, 
-0x40, 0x68, 0xc0, 0x46, 0x50, 0x60, 0x40, 0x32, 0x48, 0x68, 0xc0, 0x46, 
-0x90, 0x80, 0xc8, 0x68, 0xc0, 0x46, 0xd0, 0x80, 0x48, 0x69, 0xc0, 0x46, 
-0x10, 0x81, 0x88, 0x68, 0xc0, 0x46, 0x50, 0x81, 0x08, 0x7e, 0xc0, 0x46, 
-0x90, 0x73, 0x08, 0x69, 0xc0, 0x46, 0x90, 0x81, 0x70, 0x47, 0x04, 0x49, 
-0x08, 0x68, 0x00, 0x28, 0x00, 0xd1, 0x70, 0x47, 0xc2, 0x68, 0xc0, 0x46, 
-0x0a, 0x60, 0xfa, 0xe7, 0x6c, 0x06, 0x00, 0x80, 0x02, 0x49, 0x0a, 0x68, 
-0xc0, 0x46, 0xc2, 0x60, 0x08, 0x60, 0x70, 0x47, 0x6c, 0x06, 0x00, 0x80, 
-0xb0, 0xb4, 0x00, 0x22, 0x12, 0x4f, 0x7c, 0x7f, 0x01, 0x34, 0x7c, 0x77, 
-0x03, 0x23, 0xfc, 0x1d, 0x19, 0x34, 0x38, 0x62, 0x79, 0x62, 0x23, 0x72, 
-0x0e, 0x4c, 0x25, 0x68, 0x6b, 0x0c, 0x05, 0xd2, 0x23, 0x68, 0x1b, 0x0c, 
-0x10, 0xd1, 0x24, 0x68, 0xa3, 0x0a, 0x0d, 0xd3, 0x01, 0x23, 0x0a, 0x4f, 
-0xc0, 0x46, 0xfb, 0x62, 0x09, 0x4f, 0x0a, 0x4b, 0xc0, 0x46, 0xdf, 0x60, 
-0x99, 0x60, 0x58, 0x60, 0x10, 0x1c, 0x18, 0x60, 0x01, 0x32, 0xfb, 0xe7, 
-0x10, 0x1c, 0x38, 0x64, 0x01, 0x32, 0xfb, 0xe7, 0x00, 0x00, 0x00, 0x80, 
-0x00, 0x00, 0x10, 0x40, 0xc0, 0x00, 0x18, 0x00, 0x02, 0x81, 0x00, 0x00, 
-0x40, 0x01, 0x18, 0x00, 0xf0, 0xb5, 0x47, 0x4f, 0x38, 0x68, 0x47, 0x4e, 
-0x47, 0x4d, 0x07, 0x23, 0x5b, 0x02, 0xec, 0x18, 0x00, 0x28, 0x1d, 0xd1, 
-0x20, 0x6b, 0x01, 0x30, 0x20, 0x63, 0x44, 0x49, 0xc0, 0x46, 0x08, 0x60, 
-0x43, 0x48, 0x41, 0x69, 0x00, 0x29, 0x13, 0xd0, 0xc1, 0x1d, 0x69, 0x31, 
-0x09, 0x7b, 0x00, 0x29, 0x0e, 0xd0, 0x01, 0x23, 0x9b, 0x07, 0x01, 0x6d, 
-0x19, 0x43, 0x09, 0x68, 0xc0, 0x46, 0x81, 0x61, 0xc2, 0x69, 0x91, 0x42, 
-0x04, 0xd0, 0xf1, 0x6c, 0x01, 0x31, 0xf1, 0x64, 0x01, 0xf0, 0x50, 0xfe, 
+0x10, 0x31, 0x81, 0x23, 0x5b, 0x02, 0x1d, 0x40, 0x9d, 0x42, 0x03, 0xd1, 
+0xe3, 0x1f, 0x05, 0x3b, 0x1c, 0x04, 0x24, 0x0c, 0x02, 0x9b, 0xc0, 0x46, 
+0x1c, 0x87, 0x08, 0x9b, 0x1b, 0x68, 0x1b, 0x19, 0x10, 0x3b, 0x9b, 0x7b, 
+0x03, 0x9c, 0x40, 0x34, 0x23, 0x70, 0x01, 0x32, 0x07, 0x9b, 0xc0, 0x46, 
+0xd9, 0x80, 0x51, 0x1e, 0xc3, 0x1d, 0x49, 0x33, 0x19, 0x70, 0x07, 0x61, 
+0x04, 0x2a, 0x06, 0xd2, 0x06, 0x49, 0x53, 0x00, 0x1b, 0x18, 0x99, 0x83, 
+0x01, 0x32, 0x04, 0x2a, 0xf9, 0xd3, 0x09, 0xb0, 0xf0, 0xbc, 0x08, 0xbc, 
+0x18, 0x47, 0x00, 0x00, 0x4c, 0x2a, 0x00, 0x80, 0xff, 0xff, 0x00, 0x00, 
+0x70, 0x47, 0x80, 0xb5, 0x8c, 0xb0, 0x07, 0x1c, 0x12, 0x48, 0x01, 0x68, 
+0x01, 0x31, 0x01, 0x60, 0x38, 0x68, 0xc0, 0x46, 0x00, 0x90, 0x78, 0x68, 
+0xc0, 0x46, 0x01, 0x90, 0xb8, 0x68, 0xc0, 0x46, 0x02, 0x90, 0x0d, 0x48, 
+0x41, 0x68, 0xc9, 0x68, 0xc0, 0x46, 0x41, 0x60, 0x38, 0x1c, 0x00, 0xf0, 
+0x4f, 0xf8, 0xb8, 0x68, 0x40, 0x09, 0x06, 0xd3, 0x10, 0x23, 0x02, 0x98, 
+0x18, 0x43, 0x02, 0x90, 0x68, 0x46, 0x02, 0xf0, 0xe1, 0xff, 0x68, 0x46, 
+0x02, 0xf0, 0x9a, 0xfe, 0x0c, 0xb0, 0x80, 0xbc, 0x08, 0xbc, 0x18, 0x47, 
+0x0c, 0x2b, 0x00, 0x80, 0x6c, 0x06, 0x00, 0x80, 0x00, 0xb5, 0x8c, 0xb0, 
+0x01, 0x68, 0xc0, 0x46, 0x00, 0x91, 0x41, 0x68, 0x05, 0x4b, 0x19, 0x43, 
+0x01, 0x91, 0x00, 0xf0, 0x2f, 0xf8, 0x68, 0x46, 0x02, 0xf0, 0x84, 0xfe, 
+0x0c, 0xb0, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 
+0x02, 0x6a, 0x03, 0x68, 0xc0, 0x46, 0x13, 0x60, 0x40, 0x68, 0xc0, 0x46, 
+0x50, 0x60, 0x40, 0x32, 0x48, 0x68, 0xc0, 0x46, 0x90, 0x80, 0xc8, 0x68, 
+0xc0, 0x46, 0xd0, 0x80, 0x48, 0x69, 0xc0, 0x46, 0x10, 0x81, 0x88, 0x68, 
+0xc0, 0x46, 0x50, 0x81, 0x08, 0x7e, 0xc0, 0x46, 0x90, 0x73, 0x08, 0x69, 
+0xc0, 0x46, 0x90, 0x81, 0x70, 0x47, 0x04, 0x49, 0x08, 0x68, 0x00, 0x28, 
+0x00, 0xd1, 0x70, 0x47, 0xc2, 0x68, 0xc0, 0x46, 0x0a, 0x60, 0xfa, 0xe7, 
+0x6c, 0x06, 0x00, 0x80, 0x02, 0x49, 0x0a, 0x68, 0xc0, 0x46, 0xc2, 0x60, 
+0x08, 0x60, 0x70, 0x47, 0x6c, 0x06, 0x00, 0x80, 0xb0, 0xb4, 0x00, 0x22, 
+0x12, 0x4f, 0x7c, 0x7f, 0x01, 0x34, 0x7c, 0x77, 0x03, 0x23, 0xfc, 0x1d, 
+0x19, 0x34, 0x38, 0x62, 0x79, 0x62, 0x23, 0x72, 0x0e, 0x4c, 0x25, 0x68, 
+0x6b, 0x0c, 0x05, 0xd2, 0x23, 0x68, 0x1b, 0x0c, 0x10, 0xd1, 0x24, 0x68, 
+0xa3, 0x0a, 0x0d, 0xd3, 0x01, 0x23, 0x0a, 0x4f, 0xc0, 0x46, 0xfb, 0x62, 
+0x09, 0x4f, 0x0a, 0x4b, 0xc0, 0x46, 0xdf, 0x60, 0x99, 0x60, 0x58, 0x60, 
+0x10, 0x1c, 0x18, 0x60, 0x01, 0x32, 0xfb, 0xe7, 0x10, 0x1c, 0x38, 0x64, 
+0x01, 0x32, 0xfb, 0xe7, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x10, 0x40, 
+0xc0, 0x00, 0x18, 0x00, 0x02, 0x81, 0x00, 0x00, 0x40, 0x01, 0x18, 0x00, 
+0xf0, 0xb5, 0x47, 0x4f, 0x38, 0x68, 0x47, 0x4e, 0x47, 0x4d, 0x07, 0x23, 
+0x5b, 0x02, 0xec, 0x18, 0x00, 0x28, 0x1d, 0xd1, 0x20, 0x6b, 0x01, 0x30, 
+0x20, 0x63, 0x44, 0x49, 0xc0, 0x46, 0x08, 0x60, 0x43, 0x48, 0x41, 0x69, 
+0x00, 0x29, 0x13, 0xd0, 0xc1, 0x1d, 0x69, 0x31, 0x09, 0x7b, 0x00, 0x29, 
+0x0e, 0xd0, 0x01, 0x23, 0x9b, 0x07, 0x01, 0x6d, 0x19, 0x43, 0x09, 0x68, 
+0xc0, 0x46, 0x81, 0x61, 0xc2, 0x69, 0x91, 0x42, 0x04, 0xd0, 0xf1, 0x6c, 
+0x01, 0x31, 0xf1, 0x64, 0x01, 0xf0, 0x50, 0xfe, 
 0x38, 0x68, 0x01, 0x28, 0x17, 0xd1, 0x37, 0x48, 0x41, 0x69, 0x00, 0x29, 
-0x13, 0xd0, 0xc1, 0x1d, 0x69, 0x31, 0x09, 0x7b, 
-0x00, 0x29, 0x0e, 0xd0, 0x01, 0x23, 0x9b, 0x07, 0x01, 0x6d, 0x19, 0x43, 
-0x09, 0x68, 0xc0, 0x46, 0x81, 0x61, 0xc2, 0x69, 0x91, 0x42, 0x04, 0xd0, 
-0xf1, 0x6c, 0x01, 0x31, 0xf1, 0x64, 0x01, 0xf0, 0x35, 0xfe, 0x38, 0x68, 
-0x02, 0x28, 0x2f, 0xd1, 0xbb, 0x23, 0x1b, 0x01, 0xee, 0x18, 0x70, 0x7b, 
-0x00, 0x28, 0x03, 0xd0, 0x00, 0x20, 0x70, 0x73, 0x00, 0xf0, 0x4a, 0xfd, 
-0x30, 0x7b, 0x00, 0x28, 0x02, 0xd0, 0x78, 0x68, 0x02, 0xf0, 0xaa, 0xff, 
-0x1b, 0x23, 0xdb, 0x01, 0xe8, 0x18, 0xc0, 0x8b, 0x04, 0x26, 0x06, 0x40, 
-0xe0, 0x6a, 0xb0, 0x42, 0x14, 0xd0, 0xf8, 0x68, 0x01, 0x30, 0xf8, 0x60, 
-0x19, 0x28, 0x11, 0xd3, 0x1b, 0x48, 0x01, 0x7b, 0x00, 0x29, 0x0d, 0xd1, 
-0xff, 0x30, 0x41, 0x30, 0x40, 0x78, 0x00, 0x28, 0x08, 0xd1, 0xb8, 0x68, 
-0x02, 0xf0, 0x90, 0xff, 0x00, 0x20, 0xf8, 0x60, 0xe6, 0x62, 0x01, 0xe0, 
-0x00, 0x20, 0xf8, 0x60, 0x38, 0x68, 0x03, 0x28, 0x0b, 0xd1, 0xec, 0x1d, 
-0x79, 0x34, 0xe0, 0x6b, 0x80, 0x08, 0x02, 0xd3, 0x02, 0x20, 0x02, 0xf0, 
-0x07, 0xfc, 0x02, 0x23, 0xe0, 0x6b, 0x98, 0x43, 0xe0, 0x63, 0x38, 0x68, 
-0x01, 0x30, 0x38, 0x60, 0x03, 0x28, 0x01, 0xd9, 0x00, 0x20, 0x38, 0x60, 
-0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0x3c, 0x04, 0x00, 0x80, 
-0xa0, 0x82, 0x20, 0x40, 0x68, 0x0e, 0x00, 0x80, 0x40, 0x01, 0x18, 0x00, 
-0x64, 0x2d, 0x00, 0x80, 0xe4, 0x2c, 0x00, 0x80, 0x28, 0x05, 0x00, 0x80, 
-0xb0, 0xb4, 0x1d, 0x48, 0x84, 0x8a, 0x1d, 0x4a, 0x13, 0x8a, 0xc1, 0x1d, 
-0x09, 0x31, 0x01, 0x27, 0x9c, 0x42, 0x03, 0xd1, 0x43, 0x8a, 0x54, 0x8a, 
-0xa3, 0x42, 0x10, 0xd0, 0x0b, 0x78, 0x00, 0x2b, 0x0d, 0xd0, 0x4b, 0x78, 
-0x00, 0x2b, 0x0a, 0xd0, 0x44, 0x8b, 0x93, 0x8a, 0x9c, 0x42, 0x04, 0xdc, 
-0x13, 0x4b, 0xc0, 0x46, 0x5f, 0x60, 0x97, 0x82, 0x01, 0xe0, 0x01, 0x33, 
-0x93, 0x82, 0xc3, 0x8b, 0x5c, 0x1c, 0xc4, 0x83, 0x84, 0x8b, 0xa3, 0x42, 
-0x0e, 0xdb, 0x84, 0x8a, 0x05, 0x8b, 0x00, 0x23, 0xac, 0x42, 0x05, 0xda, 
-0x44, 0x8a, 0xc5, 0x8a, 0xac, 0x42, 0x01, 0xda, 0x4b, 0x70, 0x00, 0xe0, 
-0x4f, 0x70, 0x43, 0x82, 0x83, 0x82, 0xc3, 0x83, 0x41, 0x8a, 0xc0, 0x46, 
-0x51, 0x82, 0x80, 0x8a, 0xc0, 0x46, 0x10, 0x82, 0xb0, 0xbc, 0x70, 0x47, 
-0xe8, 0x0e, 0x00, 0x80, 0x3c, 0x04, 0x00, 0x80, 0x40, 0x01, 0x18, 0x00, 
-0xf7, 0xb5, 0x91, 0xb0, 0x6b, 0x46, 0x84, 0x1e, 0x12, 0x99, 0x14, 0x29, 
-0x1a, 0xd9, 0x00, 0x20, 0x81, 0x00, 0x67, 0x58, 0xc0, 0x46, 0x57, 0x50, 
-0x01, 0x30, 0x00, 0x06, 0x00, 0x0e, 0x10, 0x28, 0xf6, 0xd3, 0x00, 0x21, 
-0x05, 0x20, 0x87, 0x00, 0xd6, 0x59, 0x4f, 0x1c, 0x3d, 0x06, 0x2d, 0x0e, 
-0x0f, 0x1c, 0xbf, 0x00, 0xde, 0x51, 0x29, 0x1c, 0x01, 0x30, 0x00, 0x06, 
-0x00, 0x0e, 0x10, 0x28, 0xf1, 0xd3, 0x09, 0xe0, 0x00, 0x20, 0x81, 0x00, 
-0x63, 0x58, 0xc0, 0x46, 0x53, 0x50, 0x01, 0x30, 0x00, 0x06, 0x00, 0x0e, 
-0x06, 0x28, 0xf6, 0xd3, 0x00, 0x20, 0xe0, 0x70, 0x20, 0x72, 0x60, 0x72, 
-0xa0, 0x72, 0x20, 0x73, 0x60, 0x73, 0x12, 0x99, 0x14, 0x29, 0x37, 0xd9, 
-0x69, 0x46, 0x8e, 0x1c, 0x91, 0x78, 0x09, 0x07, 0x09, 0x0f, 0x89, 0x00, 
-0x14, 0x39, 0x0d, 0x06, 0x2d, 0x16, 0x00, 0x27, 0x00, 0x2d, 0x1b, 0xdd, 
-0xf0, 0x19, 0x10, 0xa9, 0x00, 0xf0, 0x3d, 0xf8, 0x00, 0x28, 0x0e, 0xd0, 
+0x13, 0xd0, 0xc1, 0x1d, 0x69, 0x31, 0x09, 0x7b, 0x00, 0x29, 0x0e, 0xd0, 
+0x01, 0x23, 0x9b, 0x07, 0x01, 0x6d, 0x19, 0x43, 0x09, 0x68, 0xc0, 0x46, 
+0x81, 0x61, 0xc2, 0x69, 0x91, 0x42, 0x04, 0xd0, 0xf1, 0x6c, 0x01, 0x31, 
+0xf1, 0x64, 0x01, 0xf0, 0x35, 0xfe, 0x38, 0x68, 0x02, 0x28, 0x2f, 0xd1, 
+0xbb, 0x23, 0x1b, 0x01, 0xee, 0x18, 0x70, 0x7b, 0x00, 0x28, 0x03, 0xd0, 
+0x00, 0x20, 0x70, 0x73, 0x00, 0xf0, 0x4a, 0xfd, 0x30, 0x7b, 0x00, 0x28, 
+0x02, 0xd0, 0x78, 0x68, 0x02, 0xf0, 0xaa, 0xff, 0x1b, 0x23, 0xdb, 0x01, 
+0xe8, 0x18, 0xc0, 0x8b, 0x04, 0x26, 0x06, 0x40, 0xe0, 0x6a, 0xb0, 0x42, 
+0x14, 0xd0, 0xf8, 0x68, 0x01, 0x30, 0xf8, 0x60, 0x19, 0x28, 0x11, 0xd3, 
+0x1b, 0x48, 0x01, 0x7b, 0x00, 0x29, 0x0d, 0xd1, 0xff, 0x30, 0x41, 0x30, 
+0x40, 0x78, 0x00, 0x28, 0x08, 0xd1, 0xb8, 0x68, 0x02, 0xf0, 0x90, 0xff, 
+0x00, 0x20, 0xf8, 0x60, 0xe6, 0x62, 0x01, 0xe0, 0x00, 0x20, 0xf8, 0x60, 
+0x38, 0x68, 0x03, 0x28, 0x0b, 0xd1, 0xec, 0x1d, 0x79, 0x34, 0xe0, 0x6b, 
+0x80, 0x08, 0x02, 0xd3, 0x02, 0x20, 0x02, 0xf0, 0x07, 0xfc, 0x02, 0x23, 
+0xe0, 0x6b, 0x98, 0x43, 0xe0, 0x63, 0x38, 0x68, 0x01, 0x30, 0x38, 0x60, 
+0x03, 0x28, 0x01, 0xd9, 0x00, 0x20, 0x38, 0x60, 0xf0, 0xbc, 0x08, 0xbc, 
+0x18, 0x47, 0x00, 0x00, 0x3c, 0x04, 0x00, 0x80, 0xa0, 0x82, 0x20, 0x40, 
+0x68, 0x0e, 0x00, 0x80, 0x40, 0x01, 0x18, 0x00, 0x64, 0x2d, 0x00, 0x80, 
+0xe4, 0x2c, 0x00, 0x80, 0x28, 0x05, 0x00, 0x80, 0xb0, 0xb4, 0x1d, 0x48, 
+0x84, 0x8a, 0x1d, 0x4a, 0x13, 0x8a, 0xc1, 0x1d, 0x09, 0x31, 0x01, 0x27, 
+0x9c, 0x42, 0x03, 0xd1, 0x43, 0x8a, 0x54, 0x8a, 0xa3, 0x42, 0x10, 0xd0, 
+0x0b, 0x78, 0x00, 0x2b, 0x0d, 0xd0, 0x4b, 0x78, 0x00, 0x2b, 0x0a, 0xd0, 
+0x44, 0x8b, 0x93, 0x8a, 0x9c, 0x42, 0x04, 0xdc, 0x13, 0x4b, 0xc0, 0x46, 
+0x5f, 0x60, 0x97, 0x82, 0x01, 0xe0, 0x01, 0x33, 0x93, 0x82, 0xc3, 0x8b, 
+0x5c, 0x1c, 0xc4, 0x83, 0x84, 0x8b, 0xa3, 0x42, 0x0e, 0xdb, 0x84, 0x8a, 
+0x05, 0x8b, 0x00, 0x23, 0xac, 0x42, 0x05, 0xda, 0x44, 0x8a, 0xc5, 0x8a, 
+0xac, 0x42, 0x01, 0xda, 0x4b, 0x70, 0x00, 0xe0, 0x4f, 0x70, 0x43, 0x82, 
+0x83, 0x82, 0xc3, 0x83, 0x41, 0x8a, 0xc0, 0x46, 0x51, 0x82, 0x80, 0x8a, 
+0xc0, 0x46, 0x10, 0x82, 0xb0, 0xbc, 0x70, 0x47, 0xe8, 0x0e, 0x00, 0x80, 
+0x3c, 0x04, 0x00, 0x80, 0x40, 0x01, 0x18, 0x00, 0xf7, 0xb5, 0x91, 0xb0, 
+0x6b, 0x46, 0x84, 0x1e, 0x12, 0x99, 0x14, 0x29, 0x1a, 0xd9, 0x00, 0x20, 
+0x81, 0x00, 0x67, 0x58, 0xc0, 0x46, 0x57, 0x50, 0x01, 0x30, 0x00, 0x06, 
+0x00, 0x0e, 0x10, 0x28, 0xf6, 0xd3, 0x00, 0x21, 0x05, 0x20, 0x87, 0x00, 
+0xd6, 0x59, 0x4f, 0x1c, 0x3d, 0x06, 0x2d, 0x0e, 0x0f, 0x1c, 0xbf, 0x00, 
+0xde, 0x51, 0x29, 0x1c, 0x01, 0x30, 0x00, 0x06, 0x00, 0x0e, 0x10, 0x28, 
+0xf1, 0xd3, 0x09, 0xe0, 0x00, 0x20, 0x81, 0x00, 0x63, 0x58, 0xc0, 0x46, 
+0x53, 0x50, 0x01, 0x30, 0x00, 0x06, 0x00, 0x0e, 0x06, 0x28, 0xf6, 0xd3, 
+0x00, 0x20, 0xe0, 0x70, 0x20, 0x72, 0x60, 0x72, 0xa0, 0x72, 0x20, 0x73, 
+0x60, 0x73, 0x12, 0x99, 0x14, 0x29, 0x37, 0xd9, 0x69, 0x46, 0x8e, 0x1c, 
+0x91, 0x78, 0x09, 0x07, 0x09, 0x0f, 0x89, 0x00, 0x14, 0x39, 0x0d, 0x06, 
+0x2d, 0x16, 0x00, 0x27, 0x00, 0x2d, 0x1b, 0xdd, 0xf0, 0x19, 0x10, 0xa9, 
+0x00, 0xf0, 0x3d, 0xf8, 0x00, 0x28, 0x0e, 0xd0, 
 0x00, 0x20, 0x10, 0xa9, 0x09, 0x78, 0x00, 0x29, 0x09, 0xdd, 0x00, 0x22, 
-0x39, 0x18, 0x72, 0x54, 0x01, 0x30, 0x00, 0x06, 
-0x00, 0x0e, 0x10, 0xa9, 0x09, 0x78, 0x88, 0x42, 0xf6, 0xdb, 0x10, 0xa8, 
-0x00, 0x78, 0x38, 0x18, 0x07, 0x06, 0x3f, 0x0e, 0xaf, 0x42, 0xe3, 0xdb, 
-0x68, 0x46, 0xe2, 0x1d, 0x0d, 0x32, 0x00, 0x21, 0xab, 0x08, 0x5f, 0x1c, 
-0x08, 0xd0, 0x8b, 0x00, 0xc4, 0x58, 0xc0, 0x46, 0xd4, 0x50, 0x01, 0x31, 
-0x09, 0x06, 0x09, 0x0e, 0x8f, 0x42, 0xf6, 0xd8, 0x14, 0xb0, 0xf0, 0xbc, 
-0x08, 0xbc, 0x18, 0x47, 0x90, 0xb4, 0x87, 0x1e, 0x00, 0x20, 0x89, 0x08, 
-0x4b, 0x1c, 0x08, 0xd0, 0x81, 0x00, 0x54, 0x58, 0xc0, 0x46, 0x7c, 0x50, 
-0x01, 0x30, 0x00, 0x06, 0x00, 0x0e, 0x83, 0x42, 0xf6, 0xd8, 0x90, 0xbc, 
-0x70, 0x47, 0x80, 0xb4, 0x02, 0x78, 0xd2, 0x06, 0xd2, 0x0e, 0x00, 0x23, 
-0x01, 0x27, 0x01, 0x2a, 0x01, 0xdc, 0x0f, 0x70, 0x11, 0xe0, 0x40, 0x78, 
-0xc0, 0x46, 0x08, 0x70, 0x14, 0x2a, 0x04, 0xd1, 0x08, 0x48, 0x01, 0x7a, 
-0x01, 0x31, 0x01, 0x72, 0x07, 0xe0, 0x02, 0x2a, 0x05, 0xd0, 0x05, 0x2a, 
-0x03, 0xd0, 0x06, 0x2a, 0x01, 0xd0, 0x15, 0x2a, 0x02, 0xd1, 0x18, 0x1c, 
-0x80, 0xbc, 0x70, 0x47, 0x38, 0x1c, 0xfb, 0xe7, 0xe0, 0x82, 0x20, 0x40, 
-0x00, 0xb5, 0x0f, 0x48, 0x01, 0x23, 0x1b, 0x06, 0x41, 0x69, 0x99, 0x43, 
-0x1a, 0x09, 0x41, 0x61, 0xd1, 0x60, 0x00, 0x21, 0xa1, 0x22, 0x52, 0x03, 
-0x91, 0x61, 0x19, 0x1c, 0x09, 0x4a, 0xc0, 0x46, 0x11, 0x60, 0x1b, 0x23, 
-0xdb, 0x01, 0xc0, 0x18, 0x80, 0x69, 0x00, 0x28, 0x03, 0xd0, 0x02, 0xf0, 
-0x61, 0xfe, 0x08, 0xbc, 0x18, 0x47, 0x04, 0x48, 0x41, 0x88, 0x01, 0x31, 
-0x41, 0x80, 0xf8, 0xe7, 0x68, 0x0e, 0x00, 0x80, 0x00, 0x00, 0x00, 0xb0, 
-0xe0, 0x82, 0x20, 0x40, 0x70, 0x47, 0x00, 0x00, 0xf0, 0xb5, 0x86, 0xb0, 
-0x95, 0x4a, 0xd0, 0x68, 0xd7, 0x1d, 0x79, 0x37, 0x01, 0x28, 0x09, 0xd1, 
-0x38, 0x89, 0x00, 0x28, 0x06, 0xd1, 0xd0, 0x6f, 0x02, 0x23, 0x01, 0x68, 
-0x99, 0x43, 0x01, 0x60, 0x14, 0x20, 0x38, 0x81, 0x8e, 0x4c, 0x61, 0x6a, 
-0x8e, 0x48, 0xc3, 0x6b, 0x59, 0x18, 0xc1, 0x63, 0xa0, 0x6a, 0x19, 0x23, 
-0xdb, 0x01, 0xd4, 0x18, 0xa0, 0x62, 0x21, 0x6a, 0x09, 0x03, 0x09, 0x0b, 
-0x81, 0x42, 0x05, 0xd1, 0x01, 0x20, 0x40, 0x04, 0x87, 0x49, 0xc0, 0x46, 
-0x08, 0x60, 0xf3, 0xe0, 0xbb, 0x8a, 0x58, 0x1c, 0xb8, 0x82, 0x3d, 0x8b, 
-0x01, 0x20, 0x00, 0x21, 0xab, 0x42, 0x04, 0xdb, 0xd3, 0x1d, 0x89, 0x33, 
-0x58, 0x70, 0xb9, 0x82, 0xf9, 0x83, 0x33, 0x23, 0x9b, 0x01, 0xd3, 0x18, 
-0x05, 0x93, 0x5b, 0x69, 0x0f, 0x2b, 0x73, 0xd2, 0x00, 0x21, 0x7c, 0x4f, 
-0xc0, 0x46, 0x39, 0x61, 0x21, 0x6a, 0x8a, 0x68, 0x12, 0x04, 0x12, 0x0c, 
-0x4b, 0x68, 0x1e, 0x0c, 0x36, 0x04, 0xfd, 0x1f, 0x09, 0x3d, 0x00, 0x2e, 
-0x05, 0xd1, 0x3b, 0x2a, 0x03, 0xd3, 0x01, 0x23, 0xdb, 0x02, 0x9a, 0x42, 
-0x01, 0xd9, 0xa8, 0x73, 0xc8, 0xe0, 0x01, 0x23, 0x9b, 0x07, 0x08, 0x31, 
-0x19, 0x43, 0x09, 0x68, 0xc0, 0x46, 0x03, 0x91, 0x03, 0xa9, 0x09, 0x88, 
-0x01, 0x31, 0x09, 0x04, 0x09, 0x0c, 0x79, 0x82, 0x49, 0x09, 0x05, 0x31, 
-0x09, 0x06, 0x09, 0x0e, 0x69, 0x4e, 0xc0, 0x46, 0x02, 0x96, 0x69, 0x48, 
-0x43, 0x6a, 0xc0, 0x46, 0x01, 0x93, 0x83, 0x6a, 0xc0, 0x46, 0x00, 0x93, 
-0xc2, 0x1d, 0x11, 0x32, 0x80, 0x69, 0x00, 0x03, 0x00, 0x0b, 0x92, 0x68, 
-0xb3, 0x07, 0x1a, 0x43, 0x12, 0x68, 0x90, 0x42, 0x01, 0xd1, 0x01, 0x20, 
+0x39, 0x18, 0x72, 0x54, 0x01, 0x30, 0x00, 0x06, 0x00, 0x0e, 0x10, 0xa9, 
+0x09, 0x78, 0x88, 0x42, 0xf6, 0xdb, 0x10, 0xa8, 0x00, 0x78, 0x38, 0x18, 
+0x07, 0x06, 0x3f, 0x0e, 0xaf, 0x42, 0xe3, 0xdb, 0x68, 0x46, 0xe2, 0x1d, 
+0x0d, 0x32, 0x00, 0x21, 0xab, 0x08, 0x5f, 0x1c, 0x08, 0xd0, 0x8b, 0x00, 
+0xc4, 0x58, 0xc0, 0x46, 0xd4, 0x50, 0x01, 0x31, 0x09, 0x06, 0x09, 0x0e, 
+0x8f, 0x42, 0xf6, 0xd8, 0x14, 0xb0, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 
+0x90, 0xb4, 0x87, 0x1e, 0x00, 0x20, 0x89, 0x08, 0x4b, 0x1c, 0x08, 0xd0, 
+0x81, 0x00, 0x54, 0x58, 0xc0, 0x46, 0x7c, 0x50, 0x01, 0x30, 0x00, 0x06, 
+0x00, 0x0e, 0x83, 0x42, 0xf6, 0xd8, 0x90, 0xbc, 0x70, 0x47, 0x80, 0xb4, 
+0x02, 0x78, 0xd2, 0x06, 0xd2, 0x0e, 0x00, 0x23, 0x01, 0x27, 0x01, 0x2a, 
+0x01, 0xdc, 0x0f, 0x70, 0x11, 0xe0, 0x40, 0x78, 0xc0, 0x46, 0x08, 0x70, 
+0x14, 0x2a, 0x04, 0xd1, 0x08, 0x48, 0x01, 0x7a, 0x01, 0x31, 0x01, 0x72, 
+0x07, 0xe0, 0x02, 0x2a, 0x05, 0xd0, 0x05, 0x2a, 0x03, 0xd0, 0x06, 0x2a, 
+0x01, 0xd0, 0x15, 0x2a, 0x02, 0xd1, 0x18, 0x1c, 0x80, 0xbc, 0x70, 0x47, 
+0x38, 0x1c, 0xfb, 0xe7, 0xe0, 0x82, 0x20, 0x40, 0x00, 0xb5, 0x0f, 0x48, 
+0x01, 0x23, 0x1b, 0x06, 0x41, 0x69, 0x99, 0x43, 0x1a, 0x09, 0x41, 0x61, 
+0xd1, 0x60, 0x00, 0x21, 0xa1, 0x22, 0x52, 0x03, 0x91, 0x61, 0x19, 0x1c, 
+0x09, 0x4a, 0xc0, 0x46, 0x11, 0x60, 0x1b, 0x23, 0xdb, 0x01, 0xc0, 0x18, 
+0x80, 0x69, 0x00, 0x28, 0x03, 0xd0, 0x02, 0xf0, 0x61, 0xfe, 0x08, 0xbc, 
+0x18, 0x47, 0x04, 0x48, 0x41, 0x88, 0x01, 0x31, 0x41, 0x80, 0xf8, 0xe7, 
+0x68, 0x0e, 0x00, 0x80, 0x00, 0x00, 0x00, 0xb0, 0xe0, 0x82, 0x20, 0x40, 
+0x70, 0x47, 0x00, 0x00, 0xf0, 0xb5, 0x86, 0xb0, 0x95, 0x4a, 0xd0, 0x68, 
+0xd7, 0x1d, 0x79, 0x37, 0x01, 0x28, 0x09, 0xd1, 0x38, 0x89, 0x00, 0x28, 
+0x06, 0xd1, 0xd0, 0x6f, 0x02, 0x23, 0x01, 0x68, 0x99, 0x43, 0x01, 0x60, 
+0x14, 0x20, 0x38, 0x81, 0x8e, 0x4c, 0x61, 0x6a, 0x8e, 0x48, 0xc3, 0x6b, 
+0x59, 0x18, 0xc1, 0x63, 0xa0, 0x6a, 0x19, 0x23, 0xdb, 0x01, 0xd4, 0x18, 
+0xa0, 0x62, 0x21, 0x6a, 0x09, 0x03, 0x09, 0x0b, 0x81, 0x42, 0x05, 0xd1, 
+0x01, 0x20, 0x40, 0x04, 0x87, 0x49, 0xc0, 0x46, 0x08, 0x60, 0xf3, 0xe0, 
+0xbb, 0x8a, 0x58, 0x1c, 0xb8, 0x82, 0x3d, 0x8b, 0x01, 0x20, 0x00, 0x21, 
+0xab, 0x42, 0x04, 0xdb, 0xd3, 0x1d, 0x89, 0x33, 0x58, 0x70, 0xb9, 0x82, 
+0xf9, 0x83, 0x33, 0x23, 0x9b, 0x01, 0xd3, 0x18, 0x05, 0x93, 0x5b, 0x69, 
+0x0f, 0x2b, 0x73, 0xd2, 0x00, 0x21, 0x7c, 0x4f, 0xc0, 0x46, 0x39, 0x61, 
+0x21, 0x6a, 0x8a, 0x68, 0x12, 0x04, 0x12, 0x0c, 0x4b, 0x68, 0x1e, 0x0c, 
+0x36, 0x04, 0xfd, 0x1f, 0x09, 0x3d, 0x00, 0x2e, 0x05, 0xd1, 0x3b, 0x2a, 
+0x03, 0xd3, 0x01, 0x23, 0xdb, 0x02, 0x9a, 0x42, 0x01, 0xd9, 0xa8, 0x73, 
+0xc8, 0xe0, 0x01, 0x23, 0x9b, 0x07, 0x08, 0x31, 0x19, 0x43, 0x09, 0x68, 
+0xc0, 0x46, 0x03, 0x91, 0x03, 0xa9, 0x09, 0x88, 0x01, 0x31, 0x09, 0x04, 
+0x09, 0x0c, 0x79, 0x82, 0x49, 0x09, 0x05, 0x31, 0x09, 0x06, 0x09, 0x0e, 
+0x69, 0x4e, 0xc0, 0x46, 0x02, 0x96, 0x69, 0x48, 0x43, 0x6a, 0xc0, 0x46, 
+0x01, 0x93, 0x83, 0x6a, 0xc0, 0x46, 0x00, 0x93, 0xc2, 0x1d, 0x11, 0x32, 
+0x80, 0x69, 0x00, 0x03, 0x00, 0x0b, 0x92, 0x68, 0xb3, 0x07, 0x1a, 0x43, 
+0x12, 0x68, 0x90, 0x42, 0x01, 0xd1, 0x01, 0x20, 
 0x0d, 0xe0, 0x90, 0x42, 0x05, 0xd9, 0x00, 0x9b, 0x18, 0x1a, 0x01, 0x9b, 
-0xd2, 0x1a, 0x82, 0x18, 0x00, 0xe0, 0x12, 0x1a, 
-0x01, 0x20, 0x09, 0x01, 0x91, 0x42, 0x00, 0xd3, 0x00, 0x20, 0x01, 0x28, 
-0x65, 0xd1, 0x51, 0x49, 0x20, 0x69, 0x00, 0x28, 0x62, 0xd0, 0x05, 0x99, 
-0x48, 0x69, 0x01, 0x30, 0x48, 0x61, 0x02, 0x20, 0x21, 0x6a, 0xc0, 0x46, 
-0x08, 0x60, 0x00, 0xf0, 0xa7, 0xfc, 0x78, 0x63, 0xbe, 0x60, 0x49, 0x49, 
-0x22, 0x6a, 0xa3, 0x6b, 0xd3, 0x18, 0x66, 0x6b, 0xb3, 0x42, 0x00, 0xd9, 
-0x22, 0x6b, 0xc0, 0x46, 0xba, 0x62, 0xba, 0x6a, 0x0c, 0x32, 0xfa, 0x62, 
-0x00, 0x22, 0xfa, 0x61, 0x03, 0xaa, 0x52, 0x88, 0xd2, 0x09, 0x03, 0xd3, 
-0x01, 0x22, 0x00, 0xe0, 0x7b, 0xe0, 0x00, 0xe0, 0x00, 0x22, 0x7a, 0x60, 
-0x7a, 0x68, 0xc0, 0x46, 0x02, 0x60, 0x78, 0x8a, 0x41, 0x4e, 0x60, 0x28, 
-0x04, 0xdc, 0xb0, 0x83, 0x78, 0x8a, 0xc0, 0x46, 0xf0, 0x83, 0x08, 0xe0, 
-0x60, 0x20, 0xb0, 0x83, 0x79, 0x8a, 0xf8, 0x6a, 0x42, 0x18, 0x63, 0x6b, 
-0x9a, 0x42, 0x03, 0xd8, 0xf1, 0x83, 0x00, 0x22, 0x3a, 0x63, 0x05, 0xe0, 
-0x21, 0x6b, 0xc0, 0x46, 0x39, 0x63, 0x61, 0x6b, 0x08, 0x1a, 0xf0, 0x83, 
-0x2d, 0x49, 0x78, 0x6b, 0x42, 0x68, 0xc0, 0x46, 0xba, 0x60, 0x82, 0x68, 
-0xc0, 0x46, 0xfa, 0x60, 0x02, 0x69, 0xc0, 0x46, 0x7a, 0x61, 0x40, 0x69, 
-0xc0, 0x46, 0xb8, 0x61, 0x2e, 0x4b, 0xc8, 0x18, 0x04, 0x90, 0x00, 0xf0, 
-0x37, 0xf9, 0x04, 0x98, 0x00, 0xf0, 0x88, 0xf8, 0x00, 0xf0, 0xf6, 0xfa, 
-0x78, 0x8a, 0xf1, 0x8b, 0x88, 0x42, 0x04, 0xd1, 0xf9, 0x6a, 0x08, 0x18, 
-0x04, 0xe0, 0x38, 0xe0, 0x32, 0xe0, 0x3a, 0x6b, 0x10, 0x18, 0x40, 0x1a, 
-0x81, 0x07, 0x02, 0xd0, 0x80, 0x08, 0x80, 0x00, 0x04, 0x30, 0x61, 0x6b, 
-0x09, 0x1a, 0xa2, 0x6b, 0x91, 0x42, 0x00, 0xd2, 0x20, 0x6b, 0xc0, 0x46, 
-0x20, 0x62, 0xe8, 0x7b, 0x00, 0x28, 0x08, 0xd0, 0x00, 0x22, 0xea, 0x73, 
-0x05, 0x99, 0x48, 0x69, 0x01, 0x38, 0x48, 0x61, 0x78, 0x6b, 0x00, 0xf0, 
-0x73, 0xfa, 0x18, 0x48, 0x80, 0x6a, 0x80, 0x06, 0x80, 0x0e, 0x01, 0x28, 
-0x0a, 0xd1, 0x20, 0x6a, 0x00, 0x03, 0x00, 0x0b, 0x0b, 0x4c, 0xa1, 0x6a, 
-0x88, 0x42, 0x03, 0xd0, 0x06, 0xb0, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 
-0x01, 0x20, 0x40, 0x04, 0x08, 0x49, 0xc0, 0x46, 0x08, 0x60, 0x06, 0xe0, 
-0xe0, 0x68, 0x00, 0x28, 0x01, 0xd0, 0x00, 0xf0, 0xb5, 0xfa, 0x01, 0x20, 
-0xa8, 0x73, 0xed, 0xe7, 0x68, 0x0e, 0x00, 0x80, 0x00, 0x40, 0x14, 0x40, 
-0xa4, 0x2a, 0x00, 0x80, 0x00, 0x00, 0x00, 0xb0, 0x28, 0x1a, 0x00, 0x80, 
-0x55, 0x55, 0x55, 0x55, 0xa8, 0x03, 0x00, 0x80, 0x68, 0x1a, 0x00, 0x80, 
-0xc4, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x10, 0x40, 0x80, 0xb5, 0x07, 0x1c, 
-0x78, 0x6a, 0x40, 0x89, 0xff, 0x21, 0x01, 0x31, 0x01, 0x40, 0x10, 0x48, 
-0x02, 0xd1, 0x81, 0x6c, 0x01, 0x31, 0x81, 0x64, 0x79, 0x6a, 0x49, 0x89, 
-0x49, 0x0b, 0x02, 0xd2, 0x41, 0x6c, 0x01, 0x31, 0x41, 0x64, 0x0b, 0x48, 
-0x41, 0x6a, 0x01, 0x31, 0x41, 0x62, 0x78, 0x6a, 0x39, 0x6b, 0xc0, 0x46, 
-0x48, 0x62, 0x38, 0x6b, 0x00, 0xf0, 0xf8, 0xfb, 0x38, 0x1c, 0x00, 0xf0, 
-0xb3, 0xf8, 0x01, 0x20, 0x04, 0x49, 0xc0, 0x46, 0xc8, 0x73, 0x80, 0xbc, 
-0x08, 0xbc, 0x18, 0x47, 0xa4, 0x2a, 0x00, 0x80, 0xa0, 0x82, 0x20, 0x40, 
-0x18, 0x1a, 0x00, 0x80, 0xf8, 0xb5, 0x07, 0x1c, 0x00, 0x22, 0xf9, 0x1d, 
-0x61, 0x31, 0x0d, 0x1c, 0x78, 0x6a, 0xc0, 0x46, 0x00, 0x90, 0x40, 0x89, 
+0xd2, 0x1a, 0x82, 0x18, 0x00, 0xe0, 0x12, 0x1a, 0x01, 0x20, 0x09, 0x01, 
+0x91, 0x42, 0x00, 0xd3, 0x00, 0x20, 0x01, 0x28, 0x65, 0xd1, 0x51, 0x49, 
+0x20, 0x69, 0x00, 0x28, 0x62, 0xd0, 0x05, 0x99, 0x48, 0x69, 0x01, 0x30, 
+0x48, 0x61, 0x02, 0x20, 0x21, 0x6a, 0xc0, 0x46, 0x08, 0x60, 0x00, 0xf0, 
+0xa7, 0xfc, 0x78, 0x63, 0xbe, 0x60, 0x49, 0x49, 0x22, 0x6a, 0xa3, 0x6b, 
+0xd3, 0x18, 0x66, 0x6b, 0xb3, 0x42, 0x00, 0xd9, 0x22, 0x6b, 0xc0, 0x46, 
+0xba, 0x62, 0xba, 0x6a, 0x0c, 0x32, 0xfa, 0x62, 0x00, 0x22, 0xfa, 0x61, 
+0x03, 0xaa, 0x52, 0x88, 0xd2, 0x09, 0x03, 0xd3, 0x01, 0x22, 0x00, 0xe0, 
+0x7b, 0xe0, 0x00, 0xe0, 0x00, 0x22, 0x7a, 0x60, 0x7a, 0x68, 0xc0, 0x46, 
+0x02, 0x60, 0x78, 0x8a, 0x41, 0x4e, 0x60, 0x28, 0x04, 0xdc, 0xb0, 0x83, 
+0x78, 0x8a, 0xc0, 0x46, 0xf0, 0x83, 0x08, 0xe0, 0x60, 0x20, 0xb0, 0x83, 
+0x79, 0x8a, 0xf8, 0x6a, 0x42, 0x18, 0x63, 0x6b, 0x9a, 0x42, 0x03, 0xd8, 
+0xf1, 0x83, 0x00, 0x22, 0x3a, 0x63, 0x05, 0xe0, 0x21, 0x6b, 0xc0, 0x46, 
+0x39, 0x63, 0x61, 0x6b, 0x08, 0x1a, 0xf0, 0x83, 0x2d, 0x49, 0x78, 0x6b, 
+0x42, 0x68, 0xc0, 0x46, 0xba, 0x60, 0x82, 0x68, 0xc0, 0x46, 0xfa, 0x60, 
+0x02, 0x69, 0xc0, 0x46, 0x7a, 0x61, 0x40, 0x69, 0xc0, 0x46, 0xb8, 0x61, 
+0x2e, 0x4b, 0xc8, 0x18, 0x04, 0x90, 0x00, 0xf0, 0x37, 0xf9, 0x04, 0x98, 
+0x00, 0xf0, 0x88, 0xf8, 0x00, 0xf0, 0xf6, 0xfa, 0x78, 0x8a, 0xf1, 0x8b, 
+0x88, 0x42, 0x04, 0xd1, 0xf9, 0x6a, 0x08, 0x18, 0x04, 0xe0, 0x38, 0xe0, 
+0x32, 0xe0, 0x3a, 0x6b, 0x10, 0x18, 0x40, 0x1a, 0x81, 0x07, 0x02, 0xd0, 
+0x80, 0x08, 0x80, 0x00, 0x04, 0x30, 0x61, 0x6b, 0x09, 0x1a, 0xa2, 0x6b, 
+0x91, 0x42, 0x00, 0xd2, 0x20, 0x6b, 0xc0, 0x46, 0x20, 0x62, 0xe8, 0x7b, 
+0x00, 0x28, 0x08, 0xd0, 0x00, 0x22, 0xea, 0x73, 0x05, 0x99, 0x48, 0x69, 
+0x01, 0x38, 0x48, 0x61, 0x78, 0x6b, 0x00, 0xf0, 0x73, 0xfa, 0x18, 0x48, 
+0x80, 0x6a, 0x80, 0x06, 0x80, 0x0e, 0x01, 0x28, 0x0a, 0xd1, 0x20, 0x6a, 
+0x00, 0x03, 0x00, 0x0b, 0x0b, 0x4c, 0xa1, 0x6a, 0x88, 0x42, 0x03, 0xd0, 
+0x06, 0xb0, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x01, 0x20, 0x40, 0x04, 
+0x08, 0x49, 0xc0, 0x46, 0x08, 0x60, 0x06, 0xe0, 0xe0, 0x68, 0x00, 0x28, 
+0x01, 0xd0, 0x00, 0xf0, 0xb5, 0xfa, 0x01, 0x20, 0xa8, 0x73, 0xed, 0xe7, 
+0x68, 0x0e, 0x00, 0x80, 0x00, 0x40, 0x14, 0x40, 0xa4, 0x2a, 0x00, 0x80, 
+0x00, 0x00, 0x00, 0xb0, 0x28, 0x1a, 0x00, 0x80, 0x55, 0x55, 0x55, 0x55, 
+0xa8, 0x03, 0x00, 0x80, 0x68, 0x1a, 0x00, 0x80, 0xc4, 0x0b, 0x00, 0x00, 
+0x00, 0x00, 0x10, 0x40, 0x80, 0xb5, 0x07, 0x1c, 0x78, 0x6a, 0x40, 0x89, 
+0xff, 0x21, 0x01, 0x31, 0x01, 0x40, 0x10, 0x48, 0x02, 0xd1, 0x81, 0x6c, 
+0x01, 0x31, 0x81, 0x64, 0x79, 0x6a, 0x49, 0x89, 0x49, 0x0b, 0x02, 0xd2, 
+0x41, 0x6c, 0x01, 0x31, 0x41, 0x64, 0x0b, 0x48, 0x41, 0x6a, 0x01, 0x31, 
+0x41, 0x62, 0x78, 0x6a, 0x39, 0x6b, 0xc0, 0x46, 0x48, 0x62, 0x38, 0x6b, 
+0x00, 0xf0, 0xf8, 0xfb, 0x38, 0x1c, 0x00, 0xf0, 0xb3, 0xf8, 0x01, 0x20, 
+0x04, 0x49, 0xc0, 0x46, 0xc8, 0x73, 0x80, 0xbc, 0x08, 0xbc, 0x18, 0x47, 
+0xa4, 0x2a, 0x00, 0x80, 0xa0, 0x82, 0x20, 0x40, 0x18, 0x1a, 0x00, 0x80, 
+0xf8, 0xb5, 0x07, 0x1c, 0x00, 0x22, 0xf9, 0x1d, 0x61, 0x31, 0x0d, 0x1c, 
+0x78, 0x6a, 0xc0, 0x46, 0x00, 0x90, 0x40, 0x89, 
 0x03, 0x0c, 0x01, 0xd2, 0x40, 0x0a, 0x03, 0xd2, 0x38, 0x1c, 0xff, 0xf7, 
-0xc1, 0xff, 0x67, 0xe0, 0x35, 0x48, 0xc0, 0x6b, 
-0x00, 0x09, 0x1f, 0xd3, 0x08, 0x78, 0x40, 0x08, 0x1c, 0xd2, 0x00, 0x20, 
-0x43, 0x00, 0xcc, 0x5a, 0x31, 0x4e, 0x9e, 0x19, 0x33, 0x23, 0x9b, 0x01, 
-0xf3, 0x18, 0x1b, 0x88, 0x9c, 0x42, 0x0e, 0xd0, 0xb8, 0x69, 0x39, 0x6b, 
-0xc0, 0x46, 0x88, 0x61, 0xf8, 0x68, 0x39, 0x6b, 0xc0, 0x46, 0xc8, 0x60, 
-0x38, 0x1c, 0x00, 0xf0, 0x27, 0xf9, 0x38, 0x1c, 0x00, 0xf0, 0x74, 0xf8, 
-0x46, 0xe0, 0x01, 0x30, 0x03, 0x28, 0xe3, 0xdb, 0x02, 0x20, 0x43, 0x00, 
-0x5c, 0x18, 0xe4, 0x88, 0x22, 0x4e, 0x9e, 0x19, 0x33, 0x23, 0x9b, 0x01, 
-0xf3, 0x18, 0x1b, 0x88, 0x9c, 0x42, 0x03, 0xd1, 0x01, 0x23, 0x01, 0x38, 
-0xd8, 0x42, 0xf0, 0xdc, 0x01, 0x23, 0xd8, 0x42, 0xc4, 0xd0, 0x1b, 0x4e, 
-0x0b, 0x23, 0x1b, 0x02, 0xf0, 0x18, 0x40, 0x69, 0x00, 0x28, 0x24, 0xd0, 
-0x7d, 0x63, 0x00, 0x98, 0x40, 0x89, 0x00, 0x0c, 0x1f, 0xd2, 0x00, 0x24, 
-0x2d, 0x23, 0x9b, 0x01, 0xf0, 0x18, 0xc0, 0x6b, 0x35, 0x1c, 0x00, 0x28, 
-0x17, 0xd0, 0xfe, 0x1d, 0x2d, 0x36, 0xa2, 0x00, 0x52, 0x19, 0x2d, 0x23, 
-0x9b, 0x01, 0xd2, 0x18, 0xd2, 0x6b, 0x38, 0x1c, 0x31, 0x1c, 0x02, 0xf0, 
-0x7b, 0xfc, 0x01, 0x28, 0x0e, 0xd0, 0x01, 0x34, 0xa0, 0x00, 0x40, 0x19, 
-0x2d, 0x23, 0x9b, 0x01, 0xc0, 0x18, 0xc0, 0x6b, 0x00, 0x28, 0xea, 0xd1, 
-0x01, 0xe0, 0x01, 0x2a, 0x02, 0xd0, 0x38, 0x1c, 0x00, 0xf0, 0x08, 0xf8, 
-0xf8, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0xe8, 0x1a, 0x00, 0x80, 
-0x68, 0x0e, 0x00, 0x80, 0x80, 0xb5, 0x07, 0x1c, 0xb8, 0x69, 0x39, 0x6b, 
-0xc0, 0x46, 0x88, 0x61, 0xf8, 0x68, 0x39, 0x6b, 0xc0, 0x46, 0xc8, 0x60, 
-0x78, 0x6a, 0x40, 0x89, 0x01, 0x0c, 0x0e, 0xd2, 0x40, 0x0a, 0x0c, 0xd3, 
-0x38, 0x68, 0x40, 0x08, 0x02, 0xd3, 0x38, 0x1c, 0x02, 0xf0, 0x0c, 0xfc, 
-0x38, 0x1c, 0x00, 0xf0, 0xbb, 0xf8, 0x38, 0x1c, 0x00, 0xf0, 0x08, 0xf8, 
-0x02, 0xe0, 0x38, 0x1c, 0xff, 0xf7, 0x30, 0xff, 0x01, 0x20, 0x80, 0xbc, 
-0x08, 0xbc, 0x18, 0x47, 0x01, 0x21, 0x00, 0x6b, 0x40, 0x6a, 0xc0, 0x46, 
-0x01, 0x60, 0x70, 0x47, 0xb0, 0xb4, 0xc1, 0x1d, 0x39, 0x31, 0x09, 0x8b, 
-0x89, 0x08, 0x09, 0x04, 0x09, 0x0c, 0x84, 0x6a, 0xc2, 0x1d, 0x61, 0x32, 
-0x00, 0x20, 0x00, 0x29, 0x0c, 0xdd, 0x87, 0x00, 0x3d, 0x19, 0x01, 0x23, 
-0x9b, 0x07, 0x2b, 0x43, 0x1b, 0x68, 0xc0, 0x46, 0xd3, 0x51, 0x01, 0x30, 
-0x00, 0x04, 0x00, 0x0c, 0x88, 0x42, 0xf2, 0xdb, 0xb0, 0xbc, 0x70, 0x47, 
-0xf0, 0xb5, 0xa0, 0xb0, 0x01, 0x23, 0x9b, 0x07, 0xc1, 0x1d, 0x21, 0x31, 
-0x19, 0x43, 0x09, 0x68, 0xc0, 0x46, 0x0b, 0x91, 0xc1, 0x1d, 0x53, 0x31, 
-0x19, 0x43, 0x1f, 0x91, 0x09, 0x68, 0x01, 0xaf, 0xfa, 0x1d, 0x39, 0x32, 
-0x1e, 0x92, 0x17, 0xab, 0x59, 0x80, 0x3a, 0x49, 0x01, 0x23, 0x9b, 0x07, 
-0x0a, 0x6a, 0x13, 0x43, 0xcc, 0x1d, 0x11, 0x34, 0x89, 0x69, 0x09, 0x03, 
-0x09, 0x0b, 0x22, 0x69, 0xe5, 0x68, 0xc0, 0x46, 0x1d, 0x95, 0xfc, 0x1d, 
-0x39, 0x34, 0x64, 0x8b, 0x64, 0x09, 0x05, 0x34, 0x24, 0x06, 0x24, 0x0e, 
-0x1c, 0x94, 0x56, 0x1a, 0x1b, 0x96, 0x1c, 0x9c, 0x2e, 0x4a, 0xc0, 0x46, 
-0x00, 0x92, 0x01, 0x26, 0x1d, 0x9d, 0x1a, 0x68, 0x91, 0x42, 0x01, 0xd1, 
-0x32, 0x1c, 0x0b, 0xe0, 0x91, 0x42, 0x03, 0xd9, 0x52, 0x1b, 0x1b, 0x9e, 
-0xb5, 0x18, 0x00, 0xe0, 0x55, 0x1a, 0x01, 0x22, 0x24, 0x01, 0xac, 0x42, 
+0xc1, 0xff, 0x67, 0xe0, 0x35, 0x48, 0xc0, 0x6b, 0x00, 0x09, 0x1f, 0xd3, 
+0x08, 0x78, 0x40, 0x08, 0x1c, 0xd2, 0x00, 0x20, 0x43, 0x00, 0xcc, 0x5a, 
+0x31, 0x4e, 0x9e, 0x19, 0x33, 0x23, 0x9b, 0x01, 0xf3, 0x18, 0x1b, 0x88, 
+0x9c, 0x42, 0x0e, 0xd0, 0xb8, 0x69, 0x39, 0x6b, 0xc0, 0x46, 0x88, 0x61, 
+0xf8, 0x68, 0x39, 0x6b, 0xc0, 0x46, 0xc8, 0x60, 0x38, 0x1c, 0x00, 0xf0, 
+0x27, 0xf9, 0x38, 0x1c, 0x00, 0xf0, 0x74, 0xf8, 0x46, 0xe0, 0x01, 0x30, 
+0x03, 0x28, 0xe3, 0xdb, 0x02, 0x20, 0x43, 0x00, 0x5c, 0x18, 0xe4, 0x88, 
+0x22, 0x4e, 0x9e, 0x19, 0x33, 0x23, 0x9b, 0x01, 0xf3, 0x18, 0x1b, 0x88, 
+0x9c, 0x42, 0x03, 0xd1, 0x01, 0x23, 0x01, 0x38, 0xd8, 0x42, 0xf0, 0xdc, 
+0x01, 0x23, 0xd8, 0x42, 0xc4, 0xd0, 0x1b, 0x4e, 0x0b, 0x23, 0x1b, 0x02, 
+0xf0, 0x18, 0x40, 0x69, 0x00, 0x28, 0x24, 0xd0, 0x7d, 0x63, 0x00, 0x98, 
+0x40, 0x89, 0x00, 0x0c, 0x1f, 0xd2, 0x00, 0x24, 0x2d, 0x23, 0x9b, 0x01, 
+0xf0, 0x18, 0xc0, 0x6b, 0x35, 0x1c, 0x00, 0x28, 0x17, 0xd0, 0xfe, 0x1d, 
+0x2d, 0x36, 0xa2, 0x00, 0x52, 0x19, 0x2d, 0x23, 0x9b, 0x01, 0xd2, 0x18, 
+0xd2, 0x6b, 0x38, 0x1c, 0x31, 0x1c, 0x02, 0xf0, 0x7b, 0xfc, 0x01, 0x28, 
+0x0e, 0xd0, 0x01, 0x34, 0xa0, 0x00, 0x40, 0x19, 0x2d, 0x23, 0x9b, 0x01, 
+0xc0, 0x18, 0xc0, 0x6b, 0x00, 0x28, 0xea, 0xd1, 0x01, 0xe0, 0x01, 0x2a, 
+0x02, 0xd0, 0x38, 0x1c, 0x00, 0xf0, 0x08, 0xf8, 0xf8, 0xbc, 0x08, 0xbc, 
+0x18, 0x47, 0x00, 0x00, 0xe8, 0x1a, 0x00, 0x80, 0x68, 0x0e, 0x00, 0x80, 
+0x80, 0xb5, 0x07, 0x1c, 0xb8, 0x69, 0x39, 0x6b, 0xc0, 0x46, 0x88, 0x61, 
+0xf8, 0x68, 0x39, 0x6b, 0xc0, 0x46, 0xc8, 0x60, 0x78, 0x6a, 0x40, 0x89, 
+0x01, 0x0c, 0x0e, 0xd2, 0x40, 0x0a, 0x0c, 0xd3, 0x38, 0x68, 0x40, 0x08, 
+0x02, 0xd3, 0x38, 0x1c, 0x02, 0xf0, 0x0c, 0xfc, 0x38, 0x1c, 0x00, 0xf0, 
+0xbb, 0xf8, 0x38, 0x1c, 0x00, 0xf0, 0x08, 0xf8, 0x02, 0xe0, 0x38, 0x1c, 
+0xff, 0xf7, 0x30, 0xff, 0x01, 0x20, 0x80, 0xbc, 0x08, 0xbc, 0x18, 0x47, 
+0x01, 0x21, 0x00, 0x6b, 0x40, 0x6a, 0xc0, 0x46, 0x01, 0x60, 0x70, 0x47, 
+0xb0, 0xb4, 0xc1, 0x1d, 0x39, 0x31, 0x09, 0x8b, 0x89, 0x08, 0x09, 0x04, 
+0x09, 0x0c, 0x84, 0x6a, 0xc2, 0x1d, 0x61, 0x32, 0x00, 0x20, 0x00, 0x29, 
+0x0c, 0xdd, 0x87, 0x00, 0x3d, 0x19, 0x01, 0x23, 0x9b, 0x07, 0x2b, 0x43, 
+0x1b, 0x68, 0xc0, 0x46, 0xd3, 0x51, 0x01, 0x30, 0x00, 0x04, 0x00, 0x0c, 
+0x88, 0x42, 0xf2, 0xdb, 0xb0, 0xbc, 0x70, 0x47, 0xf0, 0xb5, 0xa0, 0xb0, 
+0x01, 0x23, 0x9b, 0x07, 0xc1, 0x1d, 0x21, 0x31, 0x19, 0x43, 0x09, 0x68, 
+0xc0, 0x46, 0x0b, 0x91, 0xc1, 0x1d, 0x53, 0x31, 0x19, 0x43, 0x1f, 0x91, 
+0x09, 0x68, 0x01, 0xaf, 0xfa, 0x1d, 0x39, 0x32, 0x1e, 0x92, 0x17, 0xab, 
+0x59, 0x80, 0x3a, 0x49, 0x01, 0x23, 0x9b, 0x07, 0x0a, 0x6a, 0x13, 0x43, 
+0xcc, 0x1d, 0x11, 0x34, 0x89, 0x69, 0x09, 0x03, 0x09, 0x0b, 0x22, 0x69, 
+0xe5, 0x68, 0xc0, 0x46, 0x1d, 0x95, 0xfc, 0x1d, 0x39, 0x34, 0x64, 0x8b, 
+0x64, 0x09, 0x05, 0x34, 0x24, 0x06, 0x24, 0x0e, 0x1c, 0x94, 0x56, 0x1a, 
+0x1b, 0x96, 0x1c, 0x9c, 0x2e, 0x4a, 0xc0, 0x46, 0x00, 0x92, 0x01, 0x26, 
+0x1d, 0x9d, 0x1a, 0x68, 0x91, 0x42, 0x01, 0xd1, 0x32, 0x1c, 0x0b, 0xe0, 
+0x91, 0x42, 0x03, 0xd9, 0x52, 0x1b, 0x1b, 0x9e, 0xb5, 0x18, 0x00, 0xe0, 
+0x55, 0x1a, 0x01, 0x22, 0x24, 0x01, 0xac, 0x42, 
 0x00, 0xd3, 0x00, 0x22, 0x01, 0x2a, 0xe6, 0xd1, 0x91, 0x07, 0x01, 0x43, 
-0x09, 0x68, 0xc0, 0x46, 0x39, 0x60, 0x93, 0x07, 
-0x01, 0x1d, 0x19, 0x43, 0x09, 0x68, 0xc0, 0x46, 0x79, 0x60, 0xc1, 0x1d, 
-0x01, 0x31, 0x19, 0x43, 0x09, 0x68, 0xc0, 0x46, 0xb9, 0x60, 0x1f, 0x99, 
-0x09, 0x68, 0x1e, 0x9a, 0xc0, 0x46, 0x51, 0x83, 0xc1, 0x1d, 0x1d, 0x31, 
-0x19, 0x43, 0x09, 0x68, 0xc0, 0x46, 0x38, 0x63, 0x79, 0x62, 0xc1, 0x1d, 
-0x11, 0x31, 0x19, 0x43, 0x09, 0x68, 0xc0, 0x46, 0xb9, 0x61, 0xc1, 0x1d, 
-0x05, 0x31, 0x19, 0x43, 0x09, 0x68, 0xc0, 0x46, 0xf9, 0x60, 0xc1, 0x1d, 
-0x17, 0x31, 0x19, 0x43, 0x09, 0x68, 0xc0, 0x46, 0xf9, 0x83, 0x0e, 0x30, 
-0x18, 0x43, 0x00, 0x68, 0xc0, 0x46, 0xf8, 0x81, 0x38, 0x68, 0x40, 0x08, 
-0x02, 0xd3, 0x38, 0x1c, 0x02, 0xf0, 0x5c, 0xfb, 0x38, 0x1c, 0x00, 0xf0, 
-0x0b, 0xf8, 0x38, 0x1c, 0xff, 0xf7, 0x58, 0xff, 0x20, 0xb0, 0xf0, 0xbc, 
-0x08, 0xbc, 0x18, 0x47, 0xa8, 0x03, 0x00, 0x80, 0x55, 0x55, 0x55, 0x55, 
-0xf8, 0xb5, 0x07, 0x1c, 0xf8, 0x1d, 0x39, 0x30, 0x41, 0x8b, 0x39, 0x4a, 
-0x91, 0x42, 0x00, 0xdd, 0x42, 0x83, 0x42, 0x8b, 0xc0, 0x46, 0x00, 0x92, 
-0x01, 0x20, 0x3a, 0x1d, 0x06, 0xca, 0xbb, 0x6a, 0x02, 0xf0, 0x0e, 0xff, 
-0x33, 0x4a, 0xc0, 0x46, 0x00, 0x92, 0x33, 0x4e, 0x30, 0x6a, 0x33, 0x4c, 
-0xe1, 0x6d, 0x41, 0x18, 0x38, 0x6b, 0xc3, 0x1d, 0x05, 0x33, 0x01, 0x20, 
-0x72, 0x6a, 0x02, 0xf0, 0xfb, 0xfe, 0xe0, 0x6d, 0x18, 0x30, 0x00, 0x25, 
-0xb1, 0x6a, 0x81, 0x42, 0x01, 0xd8, 0xe5, 0x65, 0x00, 0xe0, 0xe0, 0x65, 
-0x2f, 0x23, 0x9b, 0x01, 0x20, 0x1c, 0xe1, 0x6d, 0xe4, 0x18, 0x22, 0x68, 
-0x92, 0x00, 0x27, 0x4b, 0xc0, 0x46, 0x99, 0x50, 0x26, 0x48, 0xc1, 0x6b, 
-0x4a, 0x08, 0x05, 0xd3, 0x49, 0x08, 0x49, 0x00, 0xc1, 0x63, 0x01, 0x20, 
-0x01, 0xf0, 0xd6, 0xff, 0x22, 0x4a, 0x1f, 0x48, 0xc1, 0x1d, 0x89, 0x31, 
-0x0b, 0x78, 0x00, 0x2b, 0x02, 0xd0, 0x49, 0x78, 0x00, 0x29, 0x00, 0xd1, 
-0x1e, 0x4a, 0xc0, 0x46, 0x00, 0x92, 0x20, 0x68, 0x80, 0x00, 0x19, 0x4b, 
-0xc3, 0x18, 0x05, 0xce, 0xc1, 0x1d, 0x11, 0x31, 0x01, 0x20, 0x02, 0xf0, 
-0xc7, 0xfe, 0x14, 0x48, 0x21, 0x68, 0x01, 0x31, 0x21, 0x60, 0x17, 0x29, 
-0x00, 0xd3, 0x25, 0x60, 0x39, 0x6b, 0xc0, 0x46, 0x0d, 0x65, 0x79, 0x6a, 
-0x3a, 0x6b, 0xc0, 0x46, 0x51, 0x62, 0x33, 0x23, 0x9b, 0x01, 0xc0, 0x18, 
-0x81, 0x68, 0x00, 0x29, 0x03, 0xd1, 0x39, 0x6b, 0xc0, 0x46, 0x81, 0x60, 
-0x04, 0xe0, 0x39, 0x6b, 0xc2, 0x68, 0xc0, 0x46, 0x11, 0x65, 0x39, 0x6b, 
-0xc0, 0x46, 0xc1, 0x60, 0xf8, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 
-0xea, 0x05, 0x00, 0x00, 0x18, 0x00, 0x14, 0x02, 0x7c, 0x29, 0x00, 0x80, 
-0x68, 0x0e, 0x00, 0x80, 0x44, 0x82, 0x20, 0x40, 0xe8, 0x0e, 0x00, 0x80, 
-0x04, 0x00, 0x00, 0x02, 0x04, 0x00, 0x00, 0x03, 0xf0, 0xb5, 0x11, 0x4e, 
-0xff, 0x25, 0x01, 0x35, 0x10, 0x4f, 0xc0, 0x46, 0x35, 0x60, 0x78, 0x69, 
-0x01, 0x38, 0x78, 0x61, 0xbc, 0x68, 0x00, 0x2c, 0x10, 0xd0, 0x20, 0x6d, 
-0xc0, 0x46, 0xb8, 0x60, 0x20, 0x1c, 0x00, 0xf0, 0x21, 0xf8, 0x20, 0x1c, 
-0x00, 0xf0, 0x04, 0xfa, 0x08, 0x48, 0x80, 0x6a, 0x00, 0x0c, 0x00, 0x07, 
-0xe9, 0xd1, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x05, 0x48, 0xc1, 0x79, 
-0x01, 0x31, 0xc1, 0x71, 0xf7, 0xe7, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 
-0x28, 0x1b, 0x00, 0x80, 0x00, 0x00, 0x10, 0x40, 0xa0, 0x82, 0x20, 0x40, 
+0x09, 0x68, 0xc0, 0x46, 0x39, 0x60, 0x93, 0x07, 0x01, 0x1d, 0x19, 0x43, 
+0x09, 0x68, 0xc0, 0x46, 0x79, 0x60, 0xc1, 0x1d, 0x01, 0x31, 0x19, 0x43, 
+0x09, 0x68, 0xc0, 0x46, 0xb9, 0x60, 0x1f, 0x99, 0x09, 0x68, 0x1e, 0x9a, 
+0xc0, 0x46, 0x51, 0x83, 0xc1, 0x1d, 0x1d, 0x31, 0x19, 0x43, 0x09, 0x68, 
+0xc0, 0x46, 0x38, 0x63, 0x79, 0x62, 0xc1, 0x1d, 0x11, 0x31, 0x19, 0x43, 
+0x09, 0x68, 0xc0, 0x46, 0xb9, 0x61, 0xc1, 0x1d, 0x05, 0x31, 0x19, 0x43, 
+0x09, 0x68, 0xc0, 0x46, 0xf9, 0x60, 0xc1, 0x1d, 0x17, 0x31, 0x19, 0x43, 
+0x09, 0x68, 0xc0, 0x46, 0xf9, 0x83, 0x0e, 0x30, 0x18, 0x43, 0x00, 0x68, 
+0xc0, 0x46, 0xf8, 0x81, 0x38, 0x68, 0x40, 0x08, 0x02, 0xd3, 0x38, 0x1c, 
+0x02, 0xf0, 0x5c, 0xfb, 0x38, 0x1c, 0x00, 0xf0, 0x0b, 0xf8, 0x38, 0x1c, 
+0xff, 0xf7, 0x58, 0xff, 0x20, 0xb0, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 
+0xa8, 0x03, 0x00, 0x80, 0x55, 0x55, 0x55, 0x55, 0xf8, 0xb5, 0x07, 0x1c, 
+0xf8, 0x1d, 0x39, 0x30, 0x41, 0x8b, 0x39, 0x4a, 0x91, 0x42, 0x00, 0xdd, 
+0x42, 0x83, 0x42, 0x8b, 0xc0, 0x46, 0x00, 0x92, 0x01, 0x20, 0x3a, 0x1d, 
+0x06, 0xca, 0xbb, 0x6a, 0x02, 0xf0, 0x0e, 0xff, 0x33, 0x4a, 0xc0, 0x46, 
+0x00, 0x92, 0x33, 0x4e, 0x30, 0x6a, 0x33, 0x4c, 0xe1, 0x6d, 0x41, 0x18, 
+0x38, 0x6b, 0xc3, 0x1d, 0x05, 0x33, 0x01, 0x20, 0x72, 0x6a, 0x02, 0xf0, 
+0xfb, 0xfe, 0xe0, 0x6d, 0x18, 0x30, 0x00, 0x25, 0xb1, 0x6a, 0x81, 0x42, 
+0x01, 0xd8, 0xe5, 0x65, 0x00, 0xe0, 0xe0, 0x65, 0x2f, 0x23, 0x9b, 0x01, 
+0x20, 0x1c, 0xe1, 0x6d, 0xe4, 0x18, 0x22, 0x68, 0x92, 0x00, 0x27, 0x4b, 
+0xc0, 0x46, 0x99, 0x50, 0x26, 0x48, 0xc1, 0x6b, 0x4a, 0x08, 0x05, 0xd3, 
+0x49, 0x08, 0x49, 0x00, 0xc1, 0x63, 0x01, 0x20, 0x01, 0xf0, 0xd6, 0xff, 
+0x22, 0x4a, 0x1f, 0x48, 0xc1, 0x1d, 0x89, 0x31, 0x0b, 0x78, 0x00, 0x2b, 
+0x02, 0xd0, 0x49, 0x78, 0x00, 0x29, 0x00, 0xd1, 0x1e, 0x4a, 0xc0, 0x46, 
+0x00, 0x92, 0x20, 0x68, 0x80, 0x00, 0x19, 0x4b, 0xc3, 0x18, 0x05, 0xce, 
+0xc1, 0x1d, 0x11, 0x31, 0x01, 0x20, 0x02, 0xf0, 0xc7, 0xfe, 0x14, 0x48, 
+0x21, 0x68, 0x01, 0x31, 0x21, 0x60, 0x17, 0x29, 0x00, 0xd3, 0x25, 0x60, 
+0x39, 0x6b, 0xc0, 0x46, 0x0d, 0x65, 0x79, 0x6a, 0x3a, 0x6b, 0xc0, 0x46, 
+0x51, 0x62, 0x33, 0x23, 0x9b, 0x01, 0xc0, 0x18, 0x81, 0x68, 0x00, 0x29, 
+0x03, 0xd1, 0x39, 0x6b, 0xc0, 0x46, 0x81, 0x60, 0x04, 0xe0, 0x39, 0x6b, 
+0xc2, 0x68, 0xc0, 0x46, 0x11, 0x65, 0x39, 0x6b, 0xc0, 0x46, 0xc1, 0x60, 
+0xf8, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0xea, 0x05, 0x00, 0x00, 
+0x18, 0x00, 0x14, 0x02, 0x7c, 0x29, 0x00, 0x80, 0x68, 0x0e, 0x00, 0x80, 
+0x44, 0x82, 0x20, 0x40, 0xe8, 0x0e, 0x00, 0x80, 0x04, 0x00, 0x00, 0x02, 
+0x04, 0x00, 0x00, 0x03, 0xf0, 0xb5, 0x11, 0x4e, 0xff, 0x25, 0x01, 0x35, 
+0x10, 0x4f, 0xc0, 0x46, 0x35, 0x60, 0x78, 0x69, 0x01, 0x38, 0x78, 0x61, 
+0xbc, 0x68, 0x00, 0x2c, 0x10, 0xd0, 0x20, 0x6d, 0xc0, 0x46, 0xb8, 0x60, 
+0x20, 0x1c, 0x00, 0xf0, 0x21, 0xf8, 0x20, 0x1c, 0x00, 0xf0, 0x04, 0xfa, 
+0x08, 0x48, 0x80, 0x6a, 0x00, 0x0c, 0x00, 0x07, 0xe9, 0xd1, 0xf0, 0xbc, 
+0x08, 0xbc, 0x18, 0x47, 0x05, 0x48, 0xc1, 0x79, 0x01, 0x31, 0xc1, 0x71, 
+0xf7, 0xe7, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0x28, 0x1b, 0x00, 0x80, 
+0x00, 0x00, 0x10, 0x40, 0xa0, 0x82, 0x20, 0x40, 
 0x01, 0x20, 0x80, 0x03, 0x01, 0x49, 0xc0, 0x46, 0x08, 0x60, 0x70, 0x47, 
-0x00, 0x00, 0x00, 0xb0, 0x90, 0xb5, 0x07, 0x1c, 
-0x38, 0x68, 0xc0, 0x08, 0x09, 0xd3, 0x1d, 0x48, 0x01, 0x6a, 0x01, 0x39, 
-0x01, 0x62, 0x20, 0x30, 0x00, 0x79, 0x00, 0x28, 0x01, 0xd0, 0xfe, 0xf7, 
-0xf3, 0xfd, 0x01, 0x23, 0x9b, 0x07, 0xf8, 0x1d, 0x1d, 0x30, 0x18, 0x43, 
-0x00, 0x68, 0x16, 0x4c, 0x61, 0x6a, 0x81, 0x42, 0x21, 0xd1, 0x01, 0x1c, 
-0x19, 0x43, 0x09, 0x68, 0x09, 0x04, 0x09, 0x0c, 0x01, 0x29, 0x1a, 0xd1, 
-0x00, 0xf0, 0x22, 0xf8, 0x60, 0x62, 0x60, 0x6a, 0x21, 0x6a, 0x88, 0x42, 
-0x05, 0xd0, 0x01, 0x21, 0x89, 0x07, 0x01, 0x43, 0x09, 0x68, 0x09, 0x04, 
-0xf2, 0xd0, 0x51, 0x21, 0x89, 0x03, 0x62, 0x6a, 0x23, 0x6b, 0x9a, 0x42, 
-0x02, 0xd1, 0x60, 0x6b, 0xa2, 0x6b, 0x80, 0x1a, 0x04, 0x38, 0xc8, 0x60, 
-0x90, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x20, 0x79, 0x6a, 0xc0, 0x46, 
-0x08, 0x60, 0xf7, 0xe7, 0x6c, 0x06, 0x00, 0x80, 0xe8, 0x1a, 0x00, 0x80, 
-0x01, 0x23, 0x9b, 0x07, 0xc1, 0x1d, 0x01, 0x31, 0x19, 0x43, 0x09, 0x68, 
-0x09, 0x04, 0x09, 0x0c, 0x08, 0x18, 0x0d, 0x30, 0x81, 0x07, 0x02, 0xd0, 
-0x80, 0x08, 0x80, 0x00, 0x04, 0x30, 0x04, 0x49, 0x8a, 0x6b, 0x12, 0x18, 
-0x4b, 0x6b, 0x9a, 0x42, 0x00, 0xd9, 0x08, 0x6b, 0x70, 0x47, 0x00, 0x00, 
-0xe8, 0x1a, 0x00, 0x80, 0x00, 0xb5, 0x04, 0x48, 0xc0, 0x68, 0x10, 0x28, 
-0x01, 0xd3, 0x00, 0xf0, 0x05, 0xf8, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 
-0xe8, 0x1a, 0x00, 0x80, 0x88, 0xb5, 0x0c, 0x4f, 0x38, 0x79, 0x00, 0x28, 
-0x11, 0xd1, 0x0b, 0x49, 0x10, 0x20, 0x02, 0xf0, 0xf5, 0xfd, 0x00, 0x28, 
-0x0b, 0xd0, 0x01, 0x20, 0x38, 0x71, 0x08, 0x4a, 0xc0, 0x46, 0x00, 0x92, 
-0x07, 0x48, 0x42, 0x68, 0x07, 0x4b, 0x01, 0x68, 0x00, 0x20, 0x02, 0xf0, 
-0xdf, 0xfd, 0x88, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0xf8, 0x1a, 0x00, 0x80, 
-0xe1, 0x2c, 0xff, 0xff, 0x10, 0x00, 0x35, 0x02, 0x7c, 0x29, 0x00, 0x80, 
-0x44, 0x80, 0x20, 0x40, 0x90, 0xb5, 0x01, 0x20, 0x40, 0x02, 0x10, 0x49, 
-0xc0, 0x46, 0x08, 0x60, 0x0f, 0x4f, 0x10, 0x21, 0xf8, 0x1d, 0x3d, 0x30, 
-0x02, 0xf0, 0x4c, 0xfc, 0x19, 0x23, 0xdb, 0x01, 0xfc, 0x18, 0xe0, 0x68, 
-0x00, 0x28, 0x01, 0xd0, 0x00, 0xf0, 0x14, 0xf8, 0x00, 0x20, 0xc9, 0x23, 
-0x1b, 0x01, 0xf9, 0x18, 0x08, 0x71, 0xe0, 0x68, 0x10, 0x28, 0x04, 0xd3, 
-0x01, 0x20, 0xbb, 0x23, 0x1b, 0x01, 0xf9, 0x18, 0x48, 0x73, 0x90, 0xbc, 
-0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0x00, 0xb0, 0x68, 0x0e, 0x00, 0x80, 
-0xf8, 0xb5, 0x37, 0x48, 0x19, 0x23, 0xdb, 0x01, 0xc1, 0x18, 0xc9, 0x68, 
-0x35, 0x4d, 0x10, 0x29, 0x00, 0xd9, 0x10, 0x21, 0x69, 0x62, 0x32, 0x48, 
-0xc1, 0x6c, 0x00, 0x6e, 0x81, 0x42, 0x07, 0xd9, 0x08, 0x1a, 0x07, 0x09, 
-0x00, 0x24, 0x68, 0x6a, 0xb8, 0x42, 0x12, 0xd2, 0x07, 0x1c, 0x10, 0xe0, 
-0x81, 0x42, 0x2a, 0xd2, 0x2c, 0x4a, 0x52, 0x6b, 0x10, 0x1a, 0x07, 0x09, 
-0x68, 0x6a, 0xb8, 0x42, 0x05, 0xd9, 0x0c, 0x09, 0x39, 0x19, 0x88, 0x42, 
-0x03, 0xd2, 0xc4, 0x1b, 0x01, 0xe0, 0x00, 0x24, 0x07, 0x1c, 0x3e, 0x19, 
-0x30, 0x01, 0x25, 0x49, 0x02, 0xf0, 0x84, 0xfd, 0x00, 0x28, 0x3d, 0xd0, 
-0x23, 0x48, 0x00, 0x2c, 0x1a, 0xd1, 0x1e, 0x49, 0x3a, 0x01, 0x6f, 0x62, 
-0x09, 0x6e, 0x8c, 0x18, 0x1d, 0x4d, 0x6b, 0x6b, 0xa3, 0x42, 0x00, 0xd8, 
-0xe4, 0x1a, 0x1e, 0x4b, 0x1a, 0x43, 0x00, 0x92, 0xea, 0x6a, 0x51, 0x18, 
+0x00, 0x00, 0x00, 0xb0, 0x90, 0xb5, 0x07, 0x1c, 0x38, 0x68, 0xc0, 0x08, 
+0x09, 0xd3, 0x1d, 0x48, 0x01, 0x6a, 0x01, 0x39, 0x01, 0x62, 0x20, 0x30, 
+0x00, 0x79, 0x00, 0x28, 0x01, 0xd0, 0xfe, 0xf7, 0xe9, 0xfd, 0x01, 0x23, 
+0x9b, 0x07, 0xf8, 0x1d, 0x1d, 0x30, 0x18, 0x43, 0x00, 0x68, 0x16, 0x4c, 
+0x61, 0x6a, 0x81, 0x42, 0x21, 0xd1, 0x01, 0x1c, 0x19, 0x43, 0x09, 0x68, 
+0x09, 0x04, 0x09, 0x0c, 0x01, 0x29, 0x1a, 0xd1, 0x00, 0xf0, 0x22, 0xf8, 
+0x60, 0x62, 0x60, 0x6a, 0x21, 0x6a, 0x88, 0x42, 0x05, 0xd0, 0x01, 0x21, 
+0x89, 0x07, 0x01, 0x43, 0x09, 0x68, 0x09, 0x04, 0xf2, 0xd0, 0x51, 0x21, 
+0x89, 0x03, 0x62, 0x6a, 0x23, 0x6b, 0x9a, 0x42, 0x02, 0xd1, 0x60, 0x6b, 
+0xa2, 0x6b, 0x80, 0x1a, 0x04, 0x38, 0xc8, 0x60, 0x90, 0xbc, 0x08, 0xbc, 
+0x18, 0x47, 0x00, 0x20, 0x79, 0x6a, 0xc0, 0x46, 0x08, 0x60, 0xf7, 0xe7, 
+0x6c, 0x06, 0x00, 0x80, 0xe8, 0x1a, 0x00, 0x80, 0x01, 0x23, 0x9b, 0x07, 
+0xc1, 0x1d, 0x01, 0x31, 0x19, 0x43, 0x09, 0x68, 0x09, 0x04, 0x09, 0x0c, 
+0x08, 0x18, 0x0d, 0x30, 0x81, 0x07, 0x02, 0xd0, 0x80, 0x08, 0x80, 0x00, 
+0x04, 0x30, 0x04, 0x49, 0x8a, 0x6b, 0x12, 0x18, 0x4b, 0x6b, 0x9a, 0x42, 
+0x00, 0xd9, 0x08, 0x6b, 0x70, 0x47, 0x00, 0x00, 0xe8, 0x1a, 0x00, 0x80, 
+0x00, 0xb5, 0x04, 0x48, 0xc0, 0x68, 0x10, 0x28, 0x01, 0xd3, 0x00, 0xf0, 
+0x05, 0xf8, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0xe8, 0x1a, 0x00, 0x80, 
+0x88, 0xb5, 0x0c, 0x4f, 0x38, 0x79, 0x00, 0x28, 0x11, 0xd1, 0x0b, 0x49, 
+0x10, 0x20, 0x02, 0xf0, 0xf5, 0xfd, 0x00, 0x28, 0x0b, 0xd0, 0x01, 0x20, 
+0x38, 0x71, 0x08, 0x4a, 0xc0, 0x46, 0x00, 0x92, 0x07, 0x48, 0x42, 0x68, 
+0x07, 0x4b, 0x01, 0x68, 0x00, 0x20, 0x02, 0xf0, 0xdf, 0xfd, 0x88, 0xbc, 
+0x08, 0xbc, 0x18, 0x47, 0xf8, 0x1a, 0x00, 0x80, 0xf5, 0x2c, 0xff, 0xff, 
+0x10, 0x00, 0x35, 0x02, 0x7c, 0x29, 0x00, 0x80, 0x44, 0x80, 0x20, 0x40, 
+0x90, 0xb5, 0x01, 0x20, 0x40, 0x02, 0x10, 0x49, 0xc0, 0x46, 0x08, 0x60, 
+0x0f, 0x4f, 0x10, 0x21, 0xf8, 0x1d, 0x3d, 0x30, 0x02, 0xf0, 0x4c, 0xfc, 
+0x19, 0x23, 0xdb, 0x01, 0xfc, 0x18, 0xe0, 0x68, 0x00, 0x28, 0x01, 0xd0, 
+0x00, 0xf0, 0x14, 0xf8, 0x00, 0x20, 0xc9, 0x23, 0x1b, 0x01, 0xf9, 0x18, 
+0x08, 0x71, 0xe0, 0x68, 0x10, 0x28, 0x04, 0xd3, 0x01, 0x20, 0xbb, 0x23, 
+0x1b, 0x01, 0xf9, 0x18, 0x48, 0x73, 0x90, 0xbc, 0x08, 0xbc, 0x18, 0x47, 
+0x00, 0x00, 0x00, 0xb0, 0x68, 0x0e, 0x00, 0x80, 0xf8, 0xb5, 0x37, 0x48, 
+0x19, 0x23, 0xdb, 0x01, 0xc1, 0x18, 0xc9, 0x68, 0x35, 0x4d, 0x10, 0x29, 
+0x00, 0xd9, 0x10, 0x21, 0x69, 0x62, 0x32, 0x48, 0xc1, 0x6c, 0x00, 0x6e, 
+0x81, 0x42, 0x07, 0xd9, 0x08, 0x1a, 0x07, 0x09, 0x00, 0x24, 0x68, 0x6a, 
+0xb8, 0x42, 0x12, 0xd2, 0x07, 0x1c, 0x10, 0xe0, 0x81, 0x42, 0x2a, 0xd2, 
+0x2c, 0x4a, 0x52, 0x6b, 0x10, 0x1a, 0x07, 0x09, 0x68, 0x6a, 0xb8, 0x42, 
+0x05, 0xd9, 0x0c, 0x09, 0x39, 0x19, 0x88, 0x42, 0x03, 0xd2, 0xc4, 0x1b, 
+0x01, 0xe0, 0x00, 0x24, 0x07, 0x1c, 0x3e, 0x19, 0x30, 0x01, 0x25, 0x49, 
+0x02, 0xf0, 0x84, 0xfd, 0x00, 0x28, 0x3d, 0xd0, 0x23, 0x48, 0x00, 0x2c, 
+0x1a, 0xd1, 0x1e, 0x49, 0x3a, 0x01, 0x6f, 0x62, 0x09, 0x6e, 0x8c, 0x18, 
+0x1d, 0x4d, 0x6b, 0x6b, 0xa3, 0x42, 0x00, 0xd8, 0xe4, 0x1a, 0x1e, 0x4b, 
+0x1a, 0x43, 0x00, 0x92, 0xea, 0x6a, 0x51, 0x18, 
 0x2a, 0x6b, 0x03, 0x1c, 0x20, 0xe0, 0x1b, 0x48, 0x01, 0x6b, 0x01, 0x31, 
-0x01, 0x63, 0x00, 0x20, 0x68, 0x62, 0xf8, 0xbc, 
-0x08, 0xbc, 0x18, 0x47, 0x10, 0x49, 0x24, 0x01, 0x3f, 0x01, 0x11, 0x22, 
-0x52, 0x05, 0x3a, 0x43, 0x6e, 0x62, 0x00, 0x92, 0x0e, 0x4d, 0xea, 0x6a, 
-0x09, 0x6e, 0x51, 0x18, 0x03, 0x1c, 0x06, 0x1c, 0x00, 0x20, 0x2a, 0x6b, 
-0x02, 0xf0, 0x4a, 0xfd, 0x0c, 0x4a, 0x22, 0x43, 0x00, 0x92, 0xbb, 0x19, 
-0xe9, 0x6a, 0x2a, 0x6b, 0x00, 0x20, 0x02, 0xf0, 0x41, 0xfd, 0x03, 0x48, 
-0xc0, 0x46, 0x04, 0x66, 0x00, 0xf0, 0x10, 0xf8, 0x01, 0x20, 0xda, 0xe7, 
-0x68, 0x0e, 0x00, 0x80, 0x28, 0x1b, 0x00, 0x80, 0x7c, 0x29, 0x00, 0x80, 
-0x49, 0x2e, 0xff, 0xff, 0x44, 0x80, 0x20, 0x40, 0x00, 0x00, 0x36, 0x02, 
-0xa0, 0x82, 0x20, 0x40, 0x04, 0x48, 0x01, 0x6e, 0x04, 0x4a, 0x80, 0x30, 
-0xd1, 0x60, 0x02, 0x23, 0xc1, 0x6b, 0x19, 0x43, 0xc1, 0x63, 0x70, 0x47, 
-0x68, 0x0e, 0x00, 0x80, 0x3c, 0xef, 0x20, 0x40, 0xf0, 0xb5, 0x84, 0xb0, 
-0x01, 0x20, 0x80, 0x02, 0x1c, 0x49, 0xc0, 0x46, 0x08, 0x60, 0x00, 0x27, 
-0x1b, 0x4e, 0x33, 0x23, 0x9b, 0x01, 0xf5, 0x18, 0x68, 0x6a, 0x00, 0x28, 
-0x1d, 0xd9, 0x19, 0x4c, 0x68, 0x46, 0x10, 0x21, 0x02, 0xf0, 0x90, 0xfb, 
-0x68, 0x46, 0x00, 0xf0, 0x33, 0xf8, 0x00, 0x28, 0x04, 0xd0, 0x15, 0x49, 
-0x48, 0x69, 0x01, 0x30, 0x48, 0x61, 0x0a, 0xe0, 0x13, 0x49, 0x60, 0x7b, 
-0x01, 0x30, 0x60, 0x73, 0x88, 0x79, 0x01, 0x30, 0x88, 0x71, 0x11, 0x48, 
-0x00, 0x68, 0x02, 0xf0, 0x65, 0xf9, 0x68, 0x6a, 0x01, 0x37, 0xb8, 0x42, 
-0xe2, 0xd8, 0xbb, 0x23, 0x1b, 0x01, 0xf0, 0x18, 0x81, 0x7b, 0x00, 0x29, 
-0x03, 0xd0, 0x00, 0x21, 0x81, 0x73, 0xff, 0xf7, 0x05, 0xfb, 0xff, 0xf7, 
-0xe3, 0xfe, 0x04, 0xb0, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 
-0x00, 0x00, 0x00, 0xb0, 0x68, 0x0e, 0x00, 0x80, 0xb0, 0x82, 0x20, 0x40, 
-0x08, 0x83, 0x20, 0x40, 0xa0, 0x82, 0x20, 0x40, 0x58, 0x04, 0x00, 0x80, 
-0x90, 0xb4, 0x17, 0x4f, 0x19, 0x23, 0xdb, 0x01, 0xf9, 0x18, 0x00, 0x22, 
-0xcb, 0x68, 0x00, 0x2b, 0x23, 0xd0, 0x01, 0x3b, 0xcb, 0x60, 0x33, 0x23, 
-0x9b, 0x01, 0xff, 0x18, 0xbb, 0x69, 0x1c, 0x6d, 0xc0, 0x46, 0xbc, 0x61, 
-0x04, 0x68, 0xc0, 0x46, 0x5c, 0x60, 0x44, 0x68, 0xc0, 0x46, 0x9c, 0x60, 
-0x84, 0x68, 0xc0, 0x46, 0x1c, 0x61, 0xc0, 0x68, 0xc0, 0x46, 0x58, 0x61, 
-0x1a, 0x65, 0x08, 0x69, 0x42, 0x1c, 0x0a, 0x61, 0x00, 0x28, 0x03, 0xd0, 
-0x38, 0x6a, 0xc0, 0x46, 0x03, 0x65, 0x00, 0xe0, 0xfb, 0x61, 0x3b, 0x62, 
-0x18, 0x1c, 0x90, 0xbc, 0x70, 0x47, 0x10, 0x1c, 0xfb, 0xe7, 0x00, 0x00, 
-0x68, 0x0e, 0x00, 0x80, 0x0a, 0x4a, 0x33, 0x23, 0x9b, 0x01, 0xd1, 0x18, 
-0xc8, 0x69, 0x19, 0x23, 0xdb, 0x01, 0xd2, 0x18, 0x13, 0x69, 0x00, 0x2b, 
-0x06, 0xd0, 0x01, 0x3b, 0x13, 0x61, 0xca, 0x69, 0x12, 0x6d, 0xc0, 0x46, 
-0xca, 0x61, 0x70, 0x47, 0x00, 0x21, 0x11, 0x61, 0xfb, 0xe7, 0x00, 0x00, 
-0x68, 0x0e, 0x00, 0x80, 0x06, 0x4a, 0x11, 0x69, 0x4b, 0x1c, 0x13, 0x61, 
-0x40, 0x32, 0x00, 0x29, 0x01, 0xd0, 0xd1, 0x69, 0x00, 0xe0, 0x00, 0x21, 
-0x01, 0x65, 0xd0, 0x61, 0x70, 0x47, 0x00, 0x00, 0xe8, 0x1a, 0x00, 0x80, 
-0x06, 0x4a, 0xd1, 0x68, 0x4b, 0x1c, 0xd3, 0x60, 0x40, 0x32, 0x00, 0x29, 
-0x01, 0xd0, 0x91, 0x69, 0x00, 0xe0, 0x00, 0x21, 0x01, 0x65, 0x90, 0x61, 
-0x70, 0x47, 0x00, 0x00, 0xe8, 0x1a, 0x00, 0x80, 0x90, 0xb4, 0x00, 0x21, 
+0x01, 0x63, 0x00, 0x20, 0x68, 0x62, 0xf8, 0xbc, 0x08, 0xbc, 0x18, 0x47, 
+0x10, 0x49, 0x24, 0x01, 0x3f, 0x01, 0x11, 0x22, 0x52, 0x05, 0x3a, 0x43, 
+0x6e, 0x62, 0x00, 0x92, 0x0e, 0x4d, 0xea, 0x6a, 0x09, 0x6e, 0x51, 0x18, 
+0x03, 0x1c, 0x06, 0x1c, 0x00, 0x20, 0x2a, 0x6b, 0x02, 0xf0, 0x4a, 0xfd, 
+0x0c, 0x4a, 0x22, 0x43, 0x00, 0x92, 0xbb, 0x19, 0xe9, 0x6a, 0x2a, 0x6b, 
+0x00, 0x20, 0x02, 0xf0, 0x41, 0xfd, 0x03, 0x48, 0xc0, 0x46, 0x04, 0x66, 
+0x00, 0xf0, 0x10, 0xf8, 0x01, 0x20, 0xda, 0xe7, 0x68, 0x0e, 0x00, 0x80, 
+0x28, 0x1b, 0x00, 0x80, 0x7c, 0x29, 0x00, 0x80, 0x5d, 0x2e, 0xff, 0xff, 
+0x44, 0x80, 0x20, 0x40, 0x00, 0x00, 0x36, 0x02, 0xa0, 0x82, 0x20, 0x40, 
+0x04, 0x48, 0x01, 0x6e, 0x04, 0x4a, 0x80, 0x30, 0xd1, 0x60, 0x02, 0x23, 
+0xc1, 0x6b, 0x19, 0x43, 0xc1, 0x63, 0x70, 0x47, 0x68, 0x0e, 0x00, 0x80, 
+0x90, 0xee, 0x20, 0x40, 0xf0, 0xb5, 0x84, 0xb0, 0x01, 0x20, 0x80, 0x02, 
+0x1c, 0x49, 0xc0, 0x46, 0x08, 0x60, 0x00, 0x27, 0x1b, 0x4e, 0x33, 0x23, 
+0x9b, 0x01, 0xf5, 0x18, 0x68, 0x6a, 0x00, 0x28, 0x1d, 0xd9, 0x19, 0x4c, 
+0x68, 0x46, 0x10, 0x21, 0x02, 0xf0, 0x90, 0xfb, 0x68, 0x46, 0x00, 0xf0, 
+0x33, 0xf8, 0x00, 0x28, 0x04, 0xd0, 0x15, 0x49, 0x48, 0x69, 0x01, 0x30, 
+0x48, 0x61, 0x0a, 0xe0, 0x13, 0x49, 0x60, 0x7b, 0x01, 0x30, 0x60, 0x73, 
+0x88, 0x79, 0x01, 0x30, 0x88, 0x71, 0x11, 0x48, 0x00, 0x68, 0x02, 0xf0, 
+0x65, 0xf9, 0x68, 0x6a, 0x01, 0x37, 0xb8, 0x42, 0xe2, 0xd8, 0xbb, 0x23, 
+0x1b, 0x01, 0xf0, 0x18, 0x81, 0x7b, 0x00, 0x29, 0x03, 0xd0, 0x00, 0x21, 
+0x81, 0x73, 0xff, 0xf7, 0x05, 0xfb, 0xff, 0xf7, 0xe3, 0xfe, 0x04, 0xb0, 
+0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 
+0x68, 0x0e, 0x00, 0x80, 0xb0, 0x82, 0x20, 0x40, 0x08, 0x83, 0x20, 0x40, 
+0xa0, 0x82, 0x20, 0x40, 0x58, 0x04, 0x00, 0x80, 0x90, 0xb4, 0x17, 0x4f, 
+0x19, 0x23, 0xdb, 0x01, 0xf9, 0x18, 0x00, 0x22, 0xcb, 0x68, 0x00, 0x2b, 
+0x23, 0xd0, 0x01, 0x3b, 0xcb, 0x60, 0x33, 0x23, 0x9b, 0x01, 0xff, 0x18, 
+0xbb, 0x69, 0x1c, 0x6d, 0xc0, 0x46, 0xbc, 0x61, 0x04, 0x68, 0xc0, 0x46, 
+0x5c, 0x60, 0x44, 0x68, 0xc0, 0x46, 0x9c, 0x60, 0x84, 0x68, 0xc0, 0x46, 
+0x1c, 0x61, 0xc0, 0x68, 0xc0, 0x46, 0x58, 0x61, 0x1a, 0x65, 0x08, 0x69, 
+0x42, 0x1c, 0x0a, 0x61, 0x00, 0x28, 0x03, 0xd0, 0x38, 0x6a, 0xc0, 0x46, 
+0x03, 0x65, 0x00, 0xe0, 0xfb, 0x61, 0x3b, 0x62, 0x18, 0x1c, 0x90, 0xbc, 
+0x70, 0x47, 0x10, 0x1c, 0xfb, 0xe7, 0x00, 0x00, 0x68, 0x0e, 0x00, 0x80, 
+0x0a, 0x4a, 0x33, 0x23, 0x9b, 0x01, 0xd1, 0x18, 0xc8, 0x69, 0x19, 0x23, 
+0xdb, 0x01, 0xd2, 0x18, 0x13, 0x69, 0x00, 0x2b, 0x06, 0xd0, 0x01, 0x3b, 
+0x13, 0x61, 0xca, 0x69, 0x12, 0x6d, 0xc0, 0x46, 0xca, 0x61, 0x70, 0x47, 
+0x00, 0x21, 0x11, 0x61, 0xfb, 0xe7, 0x00, 0x00, 0x68, 0x0e, 0x00, 0x80, 
+0x06, 0x4a, 0x11, 0x69, 0x4b, 0x1c, 0x13, 0x61, 0x40, 0x32, 0x00, 0x29, 
+0x01, 0xd0, 0xd1, 0x69, 0x00, 0xe0, 0x00, 0x21, 0x01, 0x65, 0xd0, 0x61, 
+0x70, 0x47, 0x00, 0x00, 0xe8, 0x1a, 0x00, 0x80, 0x06, 0x4a, 0xd1, 0x68, 
+0x4b, 0x1c, 0xd3, 0x60, 0x40, 0x32, 0x00, 0x29, 0x01, 0xd0, 0x91, 0x69, 
+0x00, 0xe0, 0x00, 0x21, 0x01, 0x65, 0x90, 0x61, 0x70, 0x47, 0x00, 0x00, 
+0xe8, 0x1a, 0x00, 0x80, 0x90, 0xb4, 0x00, 0x21, 
 0x0f, 0x4a, 0x97, 0x89, 0x92, 0x6a, 0x4b, 0x00, 0x1b, 0x18, 0x9b, 0x8a, 
-0x00, 0x2b, 0x12, 0xd0, 0xbb, 0x42, 0x10, 0xdc, 
-0x1c, 0x1c, 0x58, 0x23, 0x63, 0x43, 0xd3, 0x18, 0xdc, 0x1f, 0x49, 0x3c, 
-0x01, 0x23, 0x9b, 0x07, 0x23, 0x43, 0x1b, 0x68, 0x1b, 0x06, 0x1b, 0x0e, 
-0x03, 0x2b, 0x02, 0xd0, 0x00, 0x20, 0x90, 0xbc, 0x70, 0x47, 0x01, 0x31, 
-0x04, 0x29, 0xe4, 0xd3, 0x01, 0x20, 0xf8, 0xe7, 0x4c, 0x2a, 0x00, 0x80, 
-0xf7, 0xb5, 0x86, 0xb0, 0x3d, 0x4a, 0x07, 0x1c, 0xd1, 0x69, 0x8f, 0x40, 
-0x03, 0x1c, 0x14, 0x6a, 0xe3, 0x40, 0x5f, 0x40, 0x07, 0x9e, 0x8e, 0x40, 
-0x77, 0x40, 0xcf, 0x40, 0x94, 0x69, 0xc0, 0x46, 0x05, 0x94, 0x03, 0x1c, 
-0xa3, 0x40, 0x00, 0x25, 0x14, 0x69, 0xc0, 0x46, 0x04, 0x94, 0x00, 0x2c, 
-0x5d, 0xd9, 0x1c, 0x1c, 0x32, 0x4e, 0x26, 0x43, 0x94, 0x69, 0xe6, 0x40, 
-0x33, 0x1c, 0x03, 0x96, 0x53, 0x6a, 0xc0, 0x46, 0x02, 0x93, 0xd2, 0x6a, 
-0xc0, 0x46, 0x01, 0x92, 0xbb, 0x00, 0x02, 0x9a, 0xd2, 0x58, 0x13, 0x1c, 
-0x05, 0x9c, 0xe3, 0x40, 0x03, 0x9c, 0xa3, 0x42, 0x3e, 0xd1, 0x8a, 0x40, 
-0xca, 0x40, 0x14, 0x1c, 0x63, 0x00, 0x1b, 0x19, 0x5b, 0x01, 0x01, 0x9a, 
-0xd2, 0x18, 0x01, 0x23, 0x9b, 0x07, 0xd6, 0x1d, 0x01, 0x36, 0x33, 0x43, 
-0x1b, 0x68, 0x1b, 0x06, 0x1b, 0x0e, 0x03, 0x2b, 0x2c, 0xd1, 0x01, 0x23, 
-0x9b, 0x07, 0xd6, 0x1d, 0x51, 0x36, 0x33, 0x43, 0x1b, 0x68, 0x07, 0x9e, 
-0x1e, 0x40, 0x00, 0x96, 0x01, 0x23, 0x9b, 0x07, 0xd6, 0x1d, 0x49, 0x36, 
-0x33, 0x43, 0x1b, 0x68, 0x83, 0x42, 0x1b, 0xd1, 0x01, 0x23, 0x9b, 0x07, 
-0xd6, 0x1d, 0x4d, 0x36, 0x33, 0x43, 0x1b, 0x68, 0x00, 0x9e, 0xb3, 0x42, 
-0x12, 0xd1, 0x01, 0x23, 0x9b, 0x07, 0x1a, 0x43, 0x12, 0x68, 0x12, 0x04, 
-0x12, 0x0c, 0x08, 0x9b, 0x32, 0x2b, 0x04, 0xd1, 0x02, 0x2a, 0x07, 0xd1, 
-0x20, 0x04, 0x00, 0x14, 0x0f, 0xe0, 0x08, 0x9b, 0x33, 0x2b, 0x01, 0xd1, 
-0x01, 0x2a, 0xf7, 0xd0, 0x04, 0x9a, 0x01, 0x37, 0x97, 0x42, 0x00, 0xd3, 
-0x00, 0x27, 0x04, 0x9a, 0x01, 0x35, 0xaa, 0x42, 0xae, 0xd8, 0x00, 0x20, 
-0xc0, 0x43, 0x09, 0xb0, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 
-0x4c, 0x2a, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0xf0, 0xb5, 0x27, 0x4d, 
-0x68, 0x69, 0x00, 0x28, 0x06, 0xd0, 0x26, 0x48, 0x00, 0x68, 0x02, 0xf0, 
-0x2b, 0xf8, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x23, 0x4c, 0x00, 0x26, 
-0xa0, 0x68, 0x23, 0x4f, 0x00, 0x28, 0x16, 0xd0, 0x0f, 0xe0, 0x28, 0x6a, 
-0x02, 0x28, 0x02, 0xd3, 0x01, 0x20, 0x38, 0x71, 0x0f, 0xe0, 0xa6, 0x60, 
-0xfd, 0xf7, 0xe8, 0xfe, 0x00, 0x28, 0xea, 0xd1, 0x28, 0x6a, 0x02, 0x28, 
-0x01, 0xd3, 0x01, 0x20, 0x38, 0x71, 0xe8, 0x68, 0x00, 0x28, 0x02, 0xd0, 
-0x38, 0x79, 0x00, 0x28, 0xe9, 0xd0, 0x68, 0x68, 0x00, 0x28, 0x1b, 0xd0, 
-0x01, 0x20, 0xa0, 0x60, 0xfe, 0xf7, 0xbc, 0xfb, 0x00, 0x28, 0xd6, 0xd1, 
-0x68, 0x68, 0x00, 0x28, 0xf6, 0xd1, 0x11, 0xe0, 0x00, 0x28, 0xd0, 0xd1, 
-0x28, 0x6a, 0x02, 0x28, 0x02, 0xd3, 0x01, 0x20, 0x38, 0x71, 0xca, 0xe7, 
-0xa6, 0x60, 0xfd, 0xf7, 0xc3, 0xfe, 0x00, 0x28, 0xc5, 0xd1, 0x28, 0x6a, 
-0x02, 0x28, 0x01, 0xd3, 0x01, 0x20, 0x38, 0x71, 0xe8, 0x68, 0x00, 0x28, 
-0xbd, 0xd0, 0x38, 0x79, 0x00, 0x28, 0xe7, 0xd0, 0xb9, 0xe7, 0x00, 0x00, 
-0x6c, 0x06, 0x00, 0x80, 0x5c, 0x04, 0x00, 0x80, 0x4c, 0x2a, 0x00, 0x80, 
-0x8c, 0x06, 0x00, 0x80, 0x70, 0x47, 0x00, 0x00, 0x70, 0x47, 0x00, 0x00, 
+0x00, 0x2b, 0x12, 0xd0, 0xbb, 0x42, 0x10, 0xdc, 0x1c, 0x1c, 0x58, 0x23, 
+0x63, 0x43, 0xd3, 0x18, 0xdc, 0x1f, 0x49, 0x3c, 0x01, 0x23, 0x9b, 0x07, 
+0x23, 0x43, 0x1b, 0x68, 0x1b, 0x06, 0x1b, 0x0e, 0x03, 0x2b, 0x02, 0xd0, 
+0x00, 0x20, 0x90, 0xbc, 0x70, 0x47, 0x01, 0x31, 0x04, 0x29, 0xe4, 0xd3, 
+0x01, 0x20, 0xf8, 0xe7, 0x4c, 0x2a, 0x00, 0x80, 0xf7, 0xb5, 0x86, 0xb0, 
+0x3d, 0x4a, 0x07, 0x1c, 0xd1, 0x69, 0x8f, 0x40, 0x03, 0x1c, 0x14, 0x6a, 
+0xe3, 0x40, 0x5f, 0x40, 0x07, 0x9e, 0x8e, 0x40, 0x77, 0x40, 0xcf, 0x40, 
+0x94, 0x69, 0xc0, 0x46, 0x05, 0x94, 0x03, 0x1c, 0xa3, 0x40, 0x00, 0x25, 
+0x14, 0x69, 0xc0, 0x46, 0x04, 0x94, 0x00, 0x2c, 0x5d, 0xd9, 0x1c, 0x1c, 
+0x32, 0x4e, 0x26, 0x43, 0x94, 0x69, 0xe6, 0x40, 0x33, 0x1c, 0x03, 0x96, 
+0x53, 0x6a, 0xc0, 0x46, 0x02, 0x93, 0xd2, 0x6a, 0xc0, 0x46, 0x01, 0x92, 
+0xbb, 0x00, 0x02, 0x9a, 0xd2, 0x58, 0x13, 0x1c, 0x05, 0x9c, 0xe3, 0x40, 
+0x03, 0x9c, 0xa3, 0x42, 0x3e, 0xd1, 0x8a, 0x40, 0xca, 0x40, 0x14, 0x1c, 
+0x63, 0x00, 0x1b, 0x19, 0x5b, 0x01, 0x01, 0x9a, 0xd2, 0x18, 0x01, 0x23, 
+0x9b, 0x07, 0xd6, 0x1d, 0x01, 0x36, 0x33, 0x43, 0x1b, 0x68, 0x1b, 0x06, 
+0x1b, 0x0e, 0x03, 0x2b, 0x2c, 0xd1, 0x01, 0x23, 0x9b, 0x07, 0xd6, 0x1d, 
+0x51, 0x36, 0x33, 0x43, 0x1b, 0x68, 0x07, 0x9e, 0x1e, 0x40, 0x00, 0x96, 
+0x01, 0x23, 0x9b, 0x07, 0xd6, 0x1d, 0x49, 0x36, 0x33, 0x43, 0x1b, 0x68, 
+0x83, 0x42, 0x1b, 0xd1, 0x01, 0x23, 0x9b, 0x07, 0xd6, 0x1d, 0x4d, 0x36, 
+0x33, 0x43, 0x1b, 0x68, 0x00, 0x9e, 0xb3, 0x42, 0x12, 0xd1, 0x01, 0x23, 
+0x9b, 0x07, 0x1a, 0x43, 0x12, 0x68, 0x12, 0x04, 0x12, 0x0c, 0x08, 0x9b, 
+0x32, 0x2b, 0x04, 0xd1, 0x02, 0x2a, 0x07, 0xd1, 0x20, 0x04, 0x00, 0x14, 
+0x0f, 0xe0, 0x08, 0x9b, 0x33, 0x2b, 0x01, 0xd1, 0x01, 0x2a, 0xf7, 0xd0, 
+0x04, 0x9a, 0x01, 0x37, 0x97, 0x42, 0x00, 0xd3, 0x00, 0x27, 0x04, 0x9a, 
+0x01, 0x35, 0xaa, 0x42, 0xae, 0xd8, 0x00, 0x20, 0xc0, 0x43, 0x09, 0xb0, 
+0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0x4c, 0x2a, 0x00, 0x80, 
+0x00, 0x00, 0x00, 0x80, 0xf0, 0xb5, 0x27, 0x4d, 0x68, 0x69, 0x00, 0x28, 
+0x06, 0xd0, 0x26, 0x48, 0x00, 0x68, 0x02, 0xf0, 0x2b, 0xf8, 0xf0, 0xbc, 
+0x08, 0xbc, 0x18, 0x47, 0x23, 0x4c, 0x00, 0x26, 0xa0, 0x68, 0x23, 0x4f, 
+0x00, 0x28, 0x16, 0xd0, 0x0f, 0xe0, 0x28, 0x6a, 0x02, 0x28, 0x02, 0xd3, 
+0x01, 0x20, 0x38, 0x71, 0x0f, 0xe0, 0xa6, 0x60, 0xfd, 0xf7, 0xde, 0xfe, 
+0x00, 0x28, 0xea, 0xd1, 0x28, 0x6a, 0x02, 0x28, 0x01, 0xd3, 0x01, 0x20, 
+0x38, 0x71, 0xe8, 0x68, 0x00, 0x28, 0x02, 0xd0, 0x38, 0x79, 0x00, 0x28, 
+0xe9, 0xd0, 0x68, 0x68, 0x00, 0x28, 0x1b, 0xd0, 0x01, 0x20, 0xa0, 0x60, 
+0xfe, 0xf7, 0xbc, 0xfb, 0x00, 0x28, 0xd6, 0xd1, 0x68, 0x68, 0x00, 0x28, 
+0xf6, 0xd1, 0x11, 0xe0, 0x00, 0x28, 0xd0, 0xd1, 0x28, 0x6a, 0x02, 0x28, 
+0x02, 0xd3, 0x01, 0x20, 0x38, 0x71, 0xca, 0xe7, 0xa6, 0x60, 0xfd, 0xf7, 
+0xb9, 0xfe, 0x00, 0x28, 0xc5, 0xd1, 0x28, 0x6a, 0x02, 0x28, 0x01, 0xd3, 
+0x01, 0x20, 0x38, 0x71, 0xe8, 0x68, 0x00, 0x28, 0xbd, 0xd0, 0x38, 0x79, 
+0x00, 0x28, 0xe7, 0xd0, 0xb9, 0xe7, 0x00, 0x00, 0x6c, 0x06, 0x00, 0x80, 
+0x5c, 0x04, 0x00, 0x80, 0x4c, 0x2a, 0x00, 0x80, 0x8c, 0x06, 0x00, 0x80, 
+0x70, 0x47, 0x00, 0x00, 0x70, 0x47, 0x00, 0x00, 
 0x70, 0x47, 0x00, 0x00, 0x90, 0xb5, 0x40, 0x20, 0x1d, 0x49, 0xc0, 0x46, 
-0x08, 0x60, 0x01, 0xf0, 0x9d, 0xfc, 0x03, 0x23, 
-0x1b, 0x07, 0x41, 0x68, 0x19, 0x40, 0x0c, 0x0f, 0x61, 0x01, 0x09, 0x1b, 
-0x89, 0x00, 0x18, 0x4a, 0x8f, 0x18, 0x01, 0x21, 0x39, 0x80, 0x81, 0x6a, 
-0xc0, 0x46, 0x79, 0x65, 0x41, 0x6a, 0xc0, 0x46, 0x79, 0x67, 0xb9, 0x6c, 
-0xfa, 0x6c, 0x89, 0x18, 0xb9, 0x64, 0x00, 0x21, 0xf9, 0x64, 0xba, 0x6b, 
-0x3b, 0x6d, 0xd2, 0x18, 0xba, 0x63, 0x39, 0x65, 0x42, 0x6a, 0x20, 0x32, 
-0x51, 0x71, 0x79, 0x6d, 0x7a, 0x6f, 0xd2, 0x6d, 0xc0, 0x46, 0x11, 0x60, 
-0xfc, 0xf7, 0xd4, 0xff, 0x20, 0x01, 0x09, 0x49, 0x40, 0x18, 0x19, 0x23, 
-0xdb, 0x01, 0xc0, 0x18, 0x41, 0x6b, 0x01, 0x39, 0x41, 0x63, 0x78, 0x6f, 
-0x01, 0xf0, 0xc6, 0xfb, 0x90, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 
-0x00, 0x00, 0x00, 0xb0, 0x5c, 0x2b, 0x00, 0x80, 0xa0, 0x1c, 0x00, 0x80, 
-0xf0, 0xb5, 0x40, 0x20, 0x12, 0x49, 0xc0, 0x46, 0x08, 0x60, 0x01, 0xf0, 
-0x59, 0xfc, 0x07, 0x1c, 0x40, 0x68, 0x03, 0x23, 0x1b, 0x07, 0x18, 0x40, 
-0x06, 0x0f, 0x70, 0x01, 0x80, 0x1b, 0x80, 0x00, 0x0c, 0x49, 0x44, 0x18, 
-0xb8, 0x6a, 0xc0, 0x46, 0x60, 0x65, 0x78, 0x6a, 0xc0, 0x46, 0x60, 0x67, 
-0x80, 0x6f, 0x05, 0x1d, 0xe5, 0x63, 0xb9, 0x69, 0x28, 0x1c, 0x02, 0xf0, 
-0x89, 0xf9, 0x38, 0x1c, 0x21, 0x1c, 0x32, 0x1c, 0x2b, 0x1c, 0x00, 0xf0, 
-0x20, 0xf8, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0x00, 0xb0, 
-0x5c, 0x2b, 0x00, 0x80, 0xf0, 0xb5, 0x4b, 0x6f, 0x9b, 0x6f, 0x1f, 0x1d, 
-0xcf, 0x63, 0x05, 0x68, 0x00, 0x23, 0x84, 0x69, 0xa4, 0x08, 0x08, 0xd0, 
-0x9c, 0x00, 0x2e, 0x59, 0xc0, 0x46, 0x3e, 0x51, 0x84, 0x69, 0xa4, 0x08, 
-0x01, 0x33, 0x9c, 0x42, 0xf6, 0xd8, 0x3b, 0x1c, 0x00, 0xf0, 0x03, 0xf8, 
-0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0xff, 0xb5, 0x81, 0xb0, 0x04, 0x1c, 
-0x1d, 0x1c, 0x0f, 0x1c, 0x46, 0x48, 0x01, 0x69, 0x01, 0x31, 0x01, 0x61, 
-0xf9, 0x1d, 0x51, 0x31, 0xbd, 0x65, 0x00, 0x91, 0x20, 0x1c, 0xfd, 0xf7, 
-0x67, 0xfc, 0xf8, 0x6d, 0x40, 0x09, 0x36, 0xd2, 0xb8, 0x6d, 0x06, 0x7b, 
-0x43, 0x7b, 0x1b, 0x02, 0x1e, 0x43, 0x17, 0x21, 0x49, 0x02, 0x01, 0x73, 
-0x0b, 0x0a, 0x43, 0x73, 0x00, 0x99, 0x20, 0x1c, 0xfd, 0xf7, 0x56, 0xfc, 
-0xb8, 0x6d, 0xc0, 0x46, 0x06, 0x73, 0x33, 0x0a, 0x43, 0x73, 0xf8, 0x6d, 
-0x40, 0x09, 0x20, 0xd2, 0x60, 0x68, 0x01, 0x04, 0x09, 0x0c, 0x03, 0x98, 
-0x01, 0xf0, 0xcc, 0xfc, 0x60, 0x68, 0x32, 0x4b, 0x18, 0x43, 0x60, 0x60, 
-0x20, 0x1c, 0x01, 0xf0, 0x35, 0xfd, 0x00, 0x25, 0x7d, 0x60, 0xbd, 0x60, 
-0x3d, 0x64, 0x7d, 0x64, 0x20, 0x1c, 0xfc, 0xf7, 0x3b, 0xff, 0x38, 0x88, 
-0x40, 0x23, 0x18, 0x43, 0x38, 0x80, 0x7d, 0x62, 0x29, 0x48, 0xc0, 0x46, 
-0xb8, 0x62, 0x38, 0x1c, 0x00, 0xf0, 0xa0, 0xfb, 0x44, 0xe0, 0x20, 0x68, 
-0x01, 0x23, 0x9b, 0x07, 0x08, 0x38, 0x18, 0x43, 0x00, 0x68, 0xc0, 0x46, 
-0x78, 0x64, 0x60, 0x68, 0x02, 0x04, 0x12, 0x0c, 0x78, 0x6e, 0x01, 0x26, 
-0xc1, 0x1d, 0x0d, 0x31, 0x8a, 0x42, 0x02, 0xd2, 0x3a, 0x64, 0x08, 0x1c, 
-0x0e, 0xe0, 0x41, 0x19, 0x89, 0x89, 0xf0, 0x23, 0x19, 0x40, 0x09, 0x09, 
-0x89, 0x00, 0x40, 0x18, 0xf8, 0x60, 0xf9, 0x61, 0x61, 0x68, 0x09, 0x04, 
-0x09, 0x0c, 0x81, 0x42, 0x16, 0xd2, 0x39, 0x64, 0x63, 0x68, 0x19, 0x04, 
+0x08, 0x60, 0x01, 0xf0, 0x9d, 0xfc, 0x03, 0x23, 0x1b, 0x07, 0x41, 0x68, 
+0x19, 0x40, 0x0c, 0x0f, 0x61, 0x01, 0x09, 0x1b, 0x89, 0x00, 0x18, 0x4a, 
+0x8f, 0x18, 0x01, 0x21, 0x39, 0x80, 0x81, 0x6a, 0xc0, 0x46, 0x79, 0x65, 
+0x41, 0x6a, 0xc0, 0x46, 0x79, 0x67, 0xb9, 0x6c, 0xfa, 0x6c, 0x89, 0x18, 
+0xb9, 0x64, 0x00, 0x21, 0xf9, 0x64, 0xba, 0x6b, 0x3b, 0x6d, 0xd2, 0x18, 
+0xba, 0x63, 0x39, 0x65, 0x42, 0x6a, 0x20, 0x32, 0x51, 0x71, 0x79, 0x6d, 
+0x7a, 0x6f, 0xd2, 0x6d, 0xc0, 0x46, 0x11, 0x60, 0xfc, 0xf7, 0xca, 0xff, 
+0x20, 0x01, 0x09, 0x49, 0x40, 0x18, 0x19, 0x23, 0xdb, 0x01, 0xc0, 0x18, 
+0x41, 0x6b, 0x01, 0x39, 0x41, 0x63, 0x78, 0x6f, 0x01, 0xf0, 0xc6, 0xfb, 
+0x90, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 
+0x5c, 0x2b, 0x00, 0x80, 0xa0, 0x1c, 0x00, 0x80, 0xf0, 0xb5, 0x40, 0x20, 
+0x12, 0x49, 0xc0, 0x46, 0x08, 0x60, 0x01, 0xf0, 0x59, 0xfc, 0x07, 0x1c, 
+0x40, 0x68, 0x03, 0x23, 0x1b, 0x07, 0x18, 0x40, 0x06, 0x0f, 0x70, 0x01, 
+0x80, 0x1b, 0x80, 0x00, 0x0c, 0x49, 0x44, 0x18, 0xb8, 0x6a, 0xc0, 0x46, 
+0x60, 0x65, 0x78, 0x6a, 0xc0, 0x46, 0x60, 0x67, 0x80, 0x6f, 0x05, 0x1d, 
+0xe5, 0x63, 0xb9, 0x69, 0x28, 0x1c, 0x02, 0xf0, 0x89, 0xf9, 0x38, 0x1c, 
+0x21, 0x1c, 0x32, 0x1c, 0x2b, 0x1c, 0x00, 0xf0, 0x20, 0xf8, 0xf0, 0xbc, 
+0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0x00, 0xb0, 0x5c, 0x2b, 0x00, 0x80, 
+0xf0, 0xb5, 0x4b, 0x6f, 0x9b, 0x6f, 0x1f, 0x1d, 0xcf, 0x63, 0x05, 0x68, 
+0x00, 0x23, 0x84, 0x69, 0xa4, 0x08, 0x08, 0xd0, 0x9c, 0x00, 0x2e, 0x59, 
+0xc0, 0x46, 0x3e, 0x51, 0x84, 0x69, 0xa4, 0x08, 0x01, 0x33, 0x9c, 0x42, 
+0xf6, 0xd8, 0x3b, 0x1c, 0x00, 0xf0, 0x03, 0xf8, 0xf0, 0xbc, 0x08, 0xbc, 
+0x18, 0x47, 0xff, 0xb5, 0x81, 0xb0, 0x04, 0x1c, 0x1d, 0x1c, 0x0f, 0x1c, 
+0x46, 0x48, 0x01, 0x69, 0x01, 0x31, 0x01, 0x61, 0xf9, 0x1d, 0x51, 0x31, 
+0xbd, 0x65, 0x00, 0x91, 0x20, 0x1c, 0xfd, 0xf7, 0x5d, 0xfc, 0xf8, 0x6d, 
+0x40, 0x09, 0x36, 0xd2, 0xb8, 0x6d, 0x06, 0x7b, 0x43, 0x7b, 0x1b, 0x02, 
+0x1e, 0x43, 0x17, 0x21, 0x49, 0x02, 0x01, 0x73, 0x0b, 0x0a, 0x43, 0x73, 
+0x00, 0x99, 0x20, 0x1c, 0xfd, 0xf7, 0x4c, 0xfc, 0xb8, 0x6d, 0xc0, 0x46, 
+0x06, 0x73, 0x33, 0x0a, 0x43, 0x73, 0xf8, 0x6d, 0x40, 0x09, 0x20, 0xd2, 
+0x60, 0x68, 0x01, 0x04, 0x09, 0x0c, 0x03, 0x98, 0x01, 0xf0, 0xcc, 0xfc, 
+0x60, 0x68, 0x32, 0x4b, 0x18, 0x43, 0x60, 0x60, 0x20, 0x1c, 0x01, 0xf0, 
+0x35, 0xfd, 0x00, 0x25, 0x7d, 0x60, 0xbd, 0x60, 0x3d, 0x64, 0x7d, 0x64, 
+0x20, 0x1c, 0xfc, 0xf7, 0x31, 0xff, 0x38, 0x88, 0x40, 0x23, 0x18, 0x43, 
+0x38, 0x80, 0x7d, 0x62, 0x29, 0x48, 0xc0, 0x46, 0xb8, 0x62, 0x38, 0x1c, 
+0x00, 0xf0, 0xa0, 0xfb, 0x44, 0xe0, 0x20, 0x68, 0x01, 0x23, 0x9b, 0x07, 
+0x08, 0x38, 0x18, 0x43, 0x00, 0x68, 0xc0, 0x46, 0x78, 0x64, 0x60, 0x68, 
+0x02, 0x04, 0x12, 0x0c, 0x78, 0x6e, 0x01, 0x26, 0xc1, 0x1d, 0x0d, 0x31, 
+0x8a, 0x42, 0x02, 0xd2, 0x3a, 0x64, 0x08, 0x1c, 0x0e, 0xe0, 0x41, 0x19, 
+0x89, 0x89, 0xf0, 0x23, 0x19, 0x40, 0x09, 0x09, 0x89, 0x00, 0x40, 0x18, 
+0xf8, 0x60, 0xf9, 0x61, 0x61, 0x68, 0x09, 0x04, 0x09, 0x0c, 0x81, 0x42, 
+0x16, 0xd2, 0x39, 0x64, 0x63, 0x68, 0x19, 0x04, 0x09, 0x0c, 0x40, 0x1a, 
+0x03, 0x30, 0x80, 0x08, 0x82, 0x00, 0xa0, 0x61, 
+0x20, 0x68, 0x09, 0x18, 0x9b, 0x18, 0x63, 0x60, 0xc3, 0x1f, 0x05, 0x3b, 
+0x38, 0x1c, 0x00, 0xf0, 0xb6, 0xfa, 0x7e, 0x80, 0x20, 0x1c, 0x00, 0xf0, 
+0xbf, 0xfb, 0x0b, 0xe0, 0xb9, 0x68, 0x08, 0x1a, 0x00, 0x25, 0x78, 0x62, 
+0xbd, 0x62, 0x38, 0x1c, 0x00, 0xf0, 0x3c, 0xfc, 0x20, 0x1c, 0x39, 0x1c, 
+0x00, 0xf0, 0x64, 0xf8, 0x05, 0xb0, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 
+0x0c, 0x2b, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0xc0, 
+0xf0, 0xb5, 0x04, 0x1c, 0x0f, 0x1c, 0x38, 0x6c, 0xf9, 0x6b, 0x0d, 0x18, 
+0x21, 0x68, 0x41, 0x18, 0x00, 0x20, 0xa2, 0x69, 0x00, 0x2a, 0x0b, 0xd9, 
+0x82, 0x00, 0x56, 0x18, 0x01, 0x23, 0x9b, 0x07, 0x33, 0x43, 0x1b, 0x68, 
+0xc0, 0x46, 0xab, 0x50, 0xa2, 0x69, 0x01, 0x30, 0x82, 0x42, 0xf3, 0xd8, 
+0x78, 0x6e, 0xf9, 0x6b, 0x09, 0x18, 0x89, 0x89, 0xf0, 0x23, 0x19, 0x40, 
+0x09, 0x09, 0x89, 0x00, 0x40, 0x18, 0xf8, 0x60, 0xf9, 0x61, 0x20, 0x68, 
+0x01, 0x23, 0x9b, 0x07, 0x08, 0x38, 0x18, 0x43, 0x01, 0x68, 0x78, 0x6c, 
+0xfc, 0xf7, 0x95, 0xff, 0x78, 0x64, 0x60, 0x68, 0x01, 0x04, 0x09, 0x0c, 
+0xf8, 0x68, 0x81, 0x42, 0x19, 0xd2, 0x39, 0x64, 0x63, 0x68, 0x19, 0x04, 
 0x09, 0x0c, 0x40, 0x1a, 0x03, 0x30, 0x80, 0x08, 0x82, 0x00, 0xa0, 0x61, 
 0x20, 0x68, 0x09, 0x18, 0x9b, 0x18, 0x63, 0x60, 0xc3, 0x1f, 0x05, 0x3b, 
-0x38, 0x1c, 0x00, 0xf0, 0xb6, 0xfa, 0x7e, 0x80, 
-0x20, 0x1c, 0x00, 0xf0, 0xbf, 0xfb, 0x0b, 0xe0, 0xb9, 0x68, 0x08, 0x1a, 
-0x00, 0x25, 0x78, 0x62, 0xbd, 0x62, 0x38, 0x1c, 0x00, 0xf0, 0x3c, 0xfc, 
-0x20, 0x1c, 0x39, 0x1c, 0x00, 0xf0, 0x64, 0xf8, 0x05, 0xb0, 0xf0, 0xbc, 
-0x08, 0xbc, 0x18, 0x47, 0x0c, 0x2b, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 
-0x01, 0x00, 0x00, 0xc0, 0xf0, 0xb5, 0x04, 0x1c, 0x0f, 0x1c, 0x38, 0x6c, 
-0xf9, 0x6b, 0x0d, 0x18, 0x21, 0x68, 0x41, 0x18, 0x00, 0x20, 0xa2, 0x69, 
-0x00, 0x2a, 0x0b, 0xd9, 0x82, 0x00, 0x56, 0x18, 0x01, 0x23, 0x9b, 0x07, 
-0x33, 0x43, 0x1b, 0x68, 0xc0, 0x46, 0xab, 0x50, 0xa2, 0x69, 0x01, 0x30, 
-0x82, 0x42, 0xf3, 0xd8, 0x78, 0x6e, 0xf9, 0x6b, 0x09, 0x18, 0x89, 0x89, 
-0xf0, 0x23, 0x19, 0x40, 0x09, 0x09, 0x89, 0x00, 0x40, 0x18, 0xf8, 0x60, 
-0xf9, 0x61, 0x20, 0x68, 0x01, 0x23, 0x9b, 0x07, 0x08, 0x38, 0x18, 0x43, 
-0x01, 0x68, 0x78, 0x6c, 0xfc, 0xf7, 0x9f, 0xff, 0x78, 0x64, 0x60, 0x68, 
-0x01, 0x04, 0x09, 0x0c, 0xf8, 0x68, 0x81, 0x42, 0x19, 0xd2, 0x39, 0x64, 
-0x63, 0x68, 0x19, 0x04, 0x09, 0x0c, 0x40, 0x1a, 0x03, 0x30, 0x80, 0x08, 
-0x82, 0x00, 0xa0, 0x61, 0x20, 0x68, 0x09, 0x18, 0x9b, 0x18, 0x63, 0x60, 
-0xc3, 0x1f, 0x05, 0x3b, 0x38, 0x1c, 0x00, 0xf0, 0x56, 0xfa, 0x01, 0x20, 
-0x78, 0x80, 0x20, 0x1c, 0x00, 0xf0, 0x5e, 0xfb, 0xf0, 0xbc, 0x08, 0xbc, 
-0x18, 0x47, 0xb9, 0x68, 0x08, 0x1a, 0x78, 0x62, 0x00, 0x20, 0xb8, 0x62, 
-0x38, 0x1c, 0x00, 0xf0, 0xd9, 0xfb, 0x20, 0x1c, 0x39, 0x1c, 0x00, 0xf0, 
-0x01, 0xf8, 0xef, 0xe7, 0xf0, 0xb5, 0x84, 0xb0, 0x04, 0x1c, 0x0f, 0x1c, 
-0x8e, 0x48, 0x41, 0x69, 0x01, 0x31, 0x41, 0x61, 0x03, 0x20, 0x00, 0x07, 
-0x61, 0x68, 0x08, 0x40, 0x06, 0x0f, 0x0a, 0x04, 0x12, 0x0c, 0x20, 0x68, 
-0x11, 0x18, 0xfb, 0x68, 0xd2, 0x1a, 0x7b, 0x68, 0x9d, 0x1a, 0xc3, 0x1f, 
-0x05, 0x3b, 0x38, 0x1c, 0x2a, 0x1c, 0x00, 0xf0, 0x26, 0xfa, 0x00, 0x20, 
-0x78, 0x80, 0x20, 0x1c, 0x00, 0xf0, 0x2e, 0xfb, 0x60, 0x68, 0x40, 0x19, 
-0x01, 0x04, 0x09, 0x0c, 0x60, 0x60, 0x30, 0x1c, 0x01, 0xf0, 0xe0, 0xfb, 
-0x7d, 0x4e, 0x0b, 0x23, 0x1b, 0x02, 0xf0, 0x18, 0x00, 0x69, 0x00, 0x28, 
-0x19, 0xd0, 0x00, 0x25, 0x2d, 0x23, 0x9b, 0x01, 0xf0, 0x18, 0xc0, 0x68, 
-0x00, 0x28, 0x12, 0xd0, 0xaa, 0x00, 0x92, 0x19, 0x2d, 0x23, 0x9b, 0x01, 
-0xd2, 0x18, 0xd2, 0x68, 0x20, 0x1c, 0x39, 0x1c, 0x01, 0xf0, 0x1c, 0xfe, 
-0x01, 0x35, 0xa8, 0x00, 0x80, 0x19, 0x2d, 0x23, 0x9b, 0x01, 0xc0, 0x18, 
-0xc0, 0x68, 0x00, 0x28, 0xec, 0xd1, 0xf8, 0x6b, 0x01, 0x1f, 0x8a, 0x1c, 
-0xfa, 0x63, 0xfa, 0x68, 0x7d, 0x6c, 0x00, 0xf0, 0xbb, 0xf9, 0xc0, 0x43, 
-0x01, 0x04, 0x09, 0x0c, 0x28, 0x1c, 0xfc, 0xf7, 0x1a, 0xff, 0x03, 0x90, 
-0xf9, 0x6b, 0x3a, 0x6e, 0x8e, 0x18, 0x20, 0x68, 0x12, 0x18, 0x01, 0x92, 
-0x7a, 0x6e, 0x8d, 0x18, 0x11, 0x18, 0x02, 0x91, 0xc8, 0x1d, 0x09, 0x30, 
-0xe0, 0x60, 0xb1, 0x88, 0x08, 0x02, 0x09, 0x0a, 0x09, 0x06, 0x09, 0x0e, 
-0x08, 0x43, 0x00, 0x04, 0x00, 0x0c, 0x78, 0x61, 0x68, 0x68, 0x01, 0x0e, 
-0xff, 0x22, 0x12, 0x04, 0x02, 0x40, 0x12, 0x0a, 0x11, 0x43, 0xff, 0x22, 
-0x12, 0x02, 0x02, 0x40, 0x12, 0x02, 0x11, 0x43, 0x00, 0x06, 0x08, 0x43, 
-0x38, 0x61, 0xa8, 0x89, 0x09, 0x23, 0x1b, 0x02, 0x18, 0x40, 0xb8, 0x61, 
+0x38, 0x1c, 0x00, 0xf0, 0x56, 0xfa, 0x01, 0x20, 0x78, 0x80, 0x20, 0x1c, 
+0x00, 0xf0, 0x5e, 0xfb, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0xb9, 0x68, 
+0x08, 0x1a, 0x78, 0x62, 0x00, 0x20, 0xb8, 0x62, 0x38, 0x1c, 0x00, 0xf0, 
+0xd9, 0xfb, 0x20, 0x1c, 0x39, 0x1c, 0x00, 0xf0, 0x01, 0xf8, 0xef, 0xe7, 
+0xf0, 0xb5, 0x84, 0xb0, 0x04, 0x1c, 0x0f, 0x1c, 0x8e, 0x48, 0x41, 0x69, 
+0x01, 0x31, 0x41, 0x61, 0x03, 0x20, 0x00, 0x07, 0x61, 0x68, 0x08, 0x40, 
+0x06, 0x0f, 0x0a, 0x04, 0x12, 0x0c, 0x20, 0x68, 0x11, 0x18, 0xfb, 0x68, 
+0xd2, 0x1a, 0x7b, 0x68, 0x9d, 0x1a, 0xc3, 0x1f, 0x05, 0x3b, 0x38, 0x1c, 
+0x2a, 0x1c, 0x00, 0xf0, 0x26, 0xfa, 0x00, 0x20, 0x78, 0x80, 0x20, 0x1c, 
+0x00, 0xf0, 0x2e, 0xfb, 0x60, 0x68, 0x40, 0x19, 0x01, 0x04, 0x09, 0x0c, 
+0x60, 0x60, 0x30, 0x1c, 0x01, 0xf0, 0xe0, 0xfb, 0x7d, 0x4e, 0x0b, 0x23, 
+0x1b, 0x02, 0xf0, 0x18, 0x00, 0x69, 0x00, 0x28, 0x19, 0xd0, 0x00, 0x25, 
+0x2d, 0x23, 0x9b, 0x01, 0xf0, 0x18, 0xc0, 0x68, 0x00, 0x28, 0x12, 0xd0, 
+0xaa, 0x00, 0x92, 0x19, 0x2d, 0x23, 0x9b, 0x01, 0xd2, 0x18, 0xd2, 0x68, 
+0x20, 0x1c, 0x39, 0x1c, 0x01, 0xf0, 0x1c, 0xfe, 0x01, 0x35, 0xa8, 0x00, 
+0x80, 0x19, 0x2d, 0x23, 0x9b, 0x01, 0xc0, 0x18, 0xc0, 0x68, 0x00, 0x28, 
+0xec, 0xd1, 0xf8, 0x6b, 0x01, 0x1f, 0x8a, 0x1c, 0xfa, 0x63, 0xfa, 0x68, 
+0x7d, 0x6c, 0x00, 0xf0, 0xbb, 0xf9, 0xc0, 0x43, 0x01, 0x04, 0x09, 0x0c, 
+0x28, 0x1c, 0xfc, 0xf7, 0x10, 0xff, 0x03, 0x90, 0xf9, 0x6b, 0x3a, 0x6e, 
+0x8e, 0x18, 0x20, 0x68, 0x12, 0x18, 0x01, 0x92, 0x7a, 0x6e, 0x8d, 0x18, 
+0x11, 0x18, 0x02, 0x91, 0xc8, 0x1d, 0x09, 0x30, 0xe0, 0x60, 0xb1, 0x88, 
+0x08, 0x02, 0x09, 0x0a, 0x09, 0x06, 0x09, 0x0e, 0x08, 0x43, 0x00, 0x04, 
+0x00, 0x0c, 0x78, 0x61, 0x68, 0x68, 0x01, 0x0e, 0xff, 0x22, 0x12, 0x04, 
+0x02, 0x40, 0x12, 0x0a, 0x11, 0x43, 0xff, 0x22, 0x12, 0x02, 0x02, 0x40, 
+0x12, 0x02, 0x11, 0x43, 0x00, 0x06, 0x08, 0x43, 0x38, 0x61, 0xa8, 0x89, 
+0x09, 0x23, 0x1b, 0x02, 0x18, 0x40, 0xb8, 0x61, 
 0xa8, 0x89, 0x98, 0x43, 0xa8, 0x81, 0xa8, 0x89, 0x02, 0x99, 0xc0, 0x46, 
-0x88, 0x81, 0x00, 0x20, 0x70, 0x80, 0xb0, 0x80, 
-0x70, 0x81, 0x68, 0x60, 0x28, 0x82, 0xb9, 0x6e, 0x30, 0x1c, 0xfc, 0xf7, 
-0xf2, 0xfe, 0x38, 0x86, 0xfa, 0x69, 0x30, 0x1c, 0x29, 0x1c, 0xfc, 0xf7, 
-0x0d, 0xff, 0x78, 0x86, 0x3d, 0x8e, 0x78, 0x8e, 0x03, 0x99, 0xfc, 0xf7, 
-0xd2, 0xfe, 0x00, 0x90, 0x60, 0x68, 0x00, 0x04, 0x00, 0x0c, 0x39, 0x6e, 
-0x41, 0x1a, 0x09, 0x04, 0x09, 0x0c, 0x7a, 0x6e, 0x82, 0x1a, 0x13, 0x04, 
-0x1b, 0x0c, 0x1a, 0x02, 0x1b, 0x0a, 0x1a, 0x43, 0x16, 0x04, 0x36, 0x0c, 
-0xba, 0x68, 0x82, 0x42, 0x01, 0xd2, 0x00, 0x20, 0x00, 0xe0, 0x10, 0x1a, 
-0xb8, 0x60, 0x08, 0x02, 0x09, 0x12, 0x09, 0x06, 0x09, 0x0e, 0x08, 0x43, 
-0x01, 0x04, 0x09, 0x0c, 0x01, 0x98, 0xc0, 0x46, 0x41, 0x80, 0x28, 0x1c, 
-0xfc, 0xf7, 0xad, 0xfe, 0x05, 0x1c, 0x00, 0x98, 0x31, 0x1c, 0xfc, 0xf7, 
-0xa8, 0xfe, 0x06, 0x1c, 0x78, 0x69, 0x00, 0x04, 0x00, 0x0c, 0x01, 0x02, 
-0x00, 0x0a, 0x08, 0x43, 0x01, 0x04, 0x09, 0x0c, 0x01, 0x98, 0xc0, 0x46, 
-0x81, 0x80, 0x28, 0x1c, 0xfc, 0xf7, 0x99, 0xfe, 0x79, 0x69, 0x01, 0x31, 
-0xc0, 0x43, 0x79, 0x61, 0x01, 0x9a, 0xc0, 0x46, 0x50, 0x81, 0x38, 0x69, 
-0x01, 0x0e, 0xff, 0x22, 0x12, 0x04, 0x02, 0x40, 0x12, 0x0a, 0x11, 0x43, 
-0xff, 0x22, 0x12, 0x02, 0x02, 0x40, 0x12, 0x02, 0x11, 0x43, 0x00, 0x06, 
-0x01, 0x43, 0x30, 0x1c, 0xfc, 0xf7, 0x81, 0xfe, 0x39, 0x69, 0x7a, 0x68, 
-0x89, 0x18, 0x39, 0x61, 0xb9, 0x68, 0x00, 0x29, 0x09, 0xd1, 0x02, 0x99, 
-0x89, 0x89, 0xba, 0x69, 0x11, 0x43, 0x02, 0x9a, 0xc0, 0x46, 0x91, 0x81, 
-0xb9, 0x69, 0xfc, 0xf7, 0x70, 0xfe, 0x20, 0x82, 0x00, 0x20, 0x60, 0x82, 
-0xf8, 0x6d, 0x41, 0x08, 0x16, 0xd3, 0x80, 0x0a, 0x0a, 0xd3, 0x60, 0x68, 
-0x10, 0x38, 0x01, 0x04, 0x09, 0x0c, 0x08, 0x02, 0x09, 0x0a, 0x08, 0x43, 
-0x21, 0x68, 0xc0, 0x46, 0x08, 0x82, 0x09, 0xe0, 0x60, 0x68, 0x0c, 0x38, 
-0x01, 0x04, 0x09, 0x0c, 0x08, 0x02, 0x09, 0x0a, 0x08, 0x43, 0x21, 0x68, 
-0xc0, 0x46, 0x88, 0x81, 0x04, 0xb0, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 
-0x0c, 0x2b, 0x00, 0x80, 0x68, 0x0e, 0x00, 0x80, 0xf1, 0xb5, 0x84, 0xb0, 
-0x6e, 0x4d, 0x28, 0x69, 0x01, 0x22, 0x04, 0x99, 0x8a, 0x40, 0x90, 0x43, 
-0x28, 0x61, 0x04, 0x98, 0x43, 0x01, 0x18, 0x1a, 0x80, 0x00, 0x16, 0x1c, 
-0x69, 0x49, 0x44, 0x18, 0xe0, 0x6b, 0xc0, 0x46, 0x00, 0x90, 0xa0, 0x68, 
-0x00, 0x28, 0x01, 0xd1, 0x00, 0x26, 0x26, 0xe0, 0x65, 0x48, 0x41, 0x69, 
-0x01, 0x31, 0x41, 0x61, 0x04, 0x98, 0xfc, 0xf7, 0x13, 0xfd, 0x07, 0x1c, 
-0x03, 0xd1, 0x28, 0x69, 0x30, 0x43, 0x28, 0x61, 0xb5, 0xe0, 0xa0, 0x68, 
-0x65, 0x68, 0xa8, 0x42, 0x00, 0xd2, 0x05, 0x1c, 0xa1, 0x6c, 0xa9, 0x42, 
-0x16, 0xd2, 0x40, 0x1a, 0x62, 0x6a, 0x10, 0x1a, 0x00, 0x26, 0x60, 0x62, 
-0xa6, 0x60, 0xa6, 0x62, 0x20, 0x88, 0x48, 0x23, 0x18, 0x43, 0x20, 0x80, 
-0x0d, 0x1c, 0x09, 0xd1, 0x38, 0x1c, 0xfc, 0xf7, 0x23, 0xfd, 0x03, 0x20, 
-0x60, 0x80, 0x66, 0x60, 0x20, 0x1c, 0x00, 0xf0, 0x8d, 0xf9, 0x96, 0xe0, 
-0xe1, 0x68, 0x38, 0x68, 0x09, 0x18, 0xc3, 0x1f, 0x05, 0x3b, 0x20, 0x1c, 
-0x02, 0x39, 0x2a, 0x1c, 0x00, 0xf0, 0xcd, 0xf8, 0x38, 0x1c, 0x00, 0xf0, 
-0xd7, 0xf9, 0xe0, 0x68, 0x46, 0x19, 0x78, 0x68, 0x30, 0x43, 0x78, 0x60, 
-0x04, 0x98, 0x31, 0x1c, 0x01, 0xf0, 0x88, 0xfa, 0x21, 0x6e, 0x00, 0x98, 
+0x88, 0x81, 0x00, 0x20, 0x70, 0x80, 0xb0, 0x80, 0x70, 0x81, 0x68, 0x60, 
+0x28, 0x82, 0xb9, 0x6e, 0x30, 0x1c, 0xfc, 0xf7, 0xe8, 0xfe, 0x38, 0x86, 
+0xfa, 0x69, 0x30, 0x1c, 0x29, 0x1c, 0xfc, 0xf7, 0x03, 0xff, 0x78, 0x86, 
+0x3d, 0x8e, 0x78, 0x8e, 0x03, 0x99, 0xfc, 0xf7, 0xc8, 0xfe, 0x00, 0x90, 
+0x60, 0x68, 0x00, 0x04, 0x00, 0x0c, 0x39, 0x6e, 0x41, 0x1a, 0x09, 0x04, 
+0x09, 0x0c, 0x7a, 0x6e, 0x82, 0x1a, 0x13, 0x04, 0x1b, 0x0c, 0x1a, 0x02, 
+0x1b, 0x0a, 0x1a, 0x43, 0x16, 0x04, 0x36, 0x0c, 0xba, 0x68, 0x82, 0x42, 
+0x01, 0xd2, 0x00, 0x20, 0x00, 0xe0, 0x10, 0x1a, 0xb8, 0x60, 0x08, 0x02, 
+0x09, 0x12, 0x09, 0x06, 0x09, 0x0e, 0x08, 0x43, 0x01, 0x04, 0x09, 0x0c, 
+0x01, 0x98, 0xc0, 0x46, 0x41, 0x80, 0x28, 0x1c, 0xfc, 0xf7, 0xa3, 0xfe, 
+0x05, 0x1c, 0x00, 0x98, 0x31, 0x1c, 0xfc, 0xf7, 0x9e, 0xfe, 0x06, 0x1c, 
+0x78, 0x69, 0x00, 0x04, 0x00, 0x0c, 0x01, 0x02, 0x00, 0x0a, 0x08, 0x43, 
+0x01, 0x04, 0x09, 0x0c, 0x01, 0x98, 0xc0, 0x46, 0x81, 0x80, 0x28, 0x1c, 
+0xfc, 0xf7, 0x8f, 0xfe, 0x79, 0x69, 0x01, 0x31, 0xc0, 0x43, 0x79, 0x61, 
+0x01, 0x9a, 0xc0, 0x46, 0x50, 0x81, 0x38, 0x69, 0x01, 0x0e, 0xff, 0x22, 
+0x12, 0x04, 0x02, 0x40, 0x12, 0x0a, 0x11, 0x43, 0xff, 0x22, 0x12, 0x02, 
+0x02, 0x40, 0x12, 0x02, 0x11, 0x43, 0x00, 0x06, 0x01, 0x43, 0x30, 0x1c, 
+0xfc, 0xf7, 0x77, 0xfe, 0x39, 0x69, 0x7a, 0x68, 0x89, 0x18, 0x39, 0x61, 
+0xb9, 0x68, 0x00, 0x29, 0x09, 0xd1, 0x02, 0x99, 0x89, 0x89, 0xba, 0x69, 
+0x11, 0x43, 0x02, 0x9a, 0xc0, 0x46, 0x91, 0x81, 0xb9, 0x69, 0xfc, 0xf7, 
+0x66, 0xfe, 0x20, 0x82, 0x00, 0x20, 0x60, 0x82, 0xf8, 0x6d, 0x41, 0x08, 
+0x16, 0xd3, 0x80, 0x0a, 0x0a, 0xd3, 0x60, 0x68, 0x10, 0x38, 0x01, 0x04, 
+0x09, 0x0c, 0x08, 0x02, 0x09, 0x0a, 0x08, 0x43, 0x21, 0x68, 0xc0, 0x46, 
+0x08, 0x82, 0x09, 0xe0, 0x60, 0x68, 0x0c, 0x38, 0x01, 0x04, 0x09, 0x0c, 
+0x08, 0x02, 0x09, 0x0a, 0x08, 0x43, 0x21, 0x68, 0xc0, 0x46, 0x88, 0x81, 
+0x04, 0xb0, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x0c, 0x2b, 0x00, 0x80, 
+0x68, 0x0e, 0x00, 0x80, 0xf1, 0xb5, 0x84, 0xb0, 0x6e, 0x4d, 0x28, 0x69, 
+0x01, 0x22, 0x04, 0x99, 0x8a, 0x40, 0x90, 0x43, 0x28, 0x61, 0x04, 0x98, 
+0x43, 0x01, 0x18, 0x1a, 0x80, 0x00, 0x16, 0x1c, 0x69, 0x49, 0x44, 0x18, 
+0xe0, 0x6b, 0xc0, 0x46, 0x00, 0x90, 0xa0, 0x68, 0x00, 0x28, 0x01, 0xd1, 
+0x00, 0x26, 0x26, 0xe0, 0x65, 0x48, 0x41, 0x69, 0x01, 0x31, 0x41, 0x61, 
+0x04, 0x98, 0xfc, 0xf7, 0x09, 0xfd, 0x07, 0x1c, 0x03, 0xd1, 0x28, 0x69, 
+0x30, 0x43, 0x28, 0x61, 0xb5, 0xe0, 0xa0, 0x68, 0x65, 0x68, 0xa8, 0x42, 
+0x00, 0xd2, 0x05, 0x1c, 0xa1, 0x6c, 0xa9, 0x42, 0x16, 0xd2, 0x40, 0x1a, 
+0x62, 0x6a, 0x10, 0x1a, 0x00, 0x26, 0x60, 0x62, 0xa6, 0x60, 0xa6, 0x62, 
+0x20, 0x88, 0x48, 0x23, 0x18, 0x43, 0x20, 0x80, 0x0d, 0x1c, 0x09, 0xd1, 
+0x38, 0x1c, 0xfc, 0xf7, 0x19, 0xfd, 0x03, 0x20, 0x60, 0x80, 0x66, 0x60, 
+0x20, 0x1c, 0x00, 0xf0, 0x8d, 0xf9, 0x96, 0xe0, 0xe1, 0x68, 0x38, 0x68, 
+0x09, 0x18, 0xc3, 0x1f, 0x05, 0x3b, 0x20, 0x1c, 0x02, 0x39, 0x2a, 0x1c, 
+0x00, 0xf0, 0xcd, 0xf8, 0x38, 0x1c, 0x00, 0xf0, 0xd7, 0xf9, 0xe0, 0x68, 
+0x46, 0x19, 0x78, 0x68, 0x30, 0x43, 0x78, 0x60, 0x04, 0x98, 0x31, 0x1c, 
+0x01, 0xf0, 0x88, 0xfa, 0x21, 0x6e, 0x00, 0x98, 
 0x08, 0x18, 0x01, 0x90, 0x70, 0x1a, 0x00, 0x04, 0x00, 0x0c, 0x61, 0x6e, 
-0x71, 0x1a, 0x0a, 0x04, 0x12, 0x0c, 0x11, 0x02, 
-0x12, 0x0a, 0x11, 0x43, 0x09, 0x04, 0x09, 0x0c, 0x02, 0x91, 0x01, 0x02, 
-0x00, 0x0a, 0x08, 0x43, 0x01, 0x04, 0x09, 0x0c, 0x01, 0x98, 0xc0, 0x46, 
-0x41, 0x80, 0x20, 0x8e, 0xfc, 0xf7, 0xd5, 0xfd, 0x06, 0x1c, 0x60, 0x8e, 
-0x02, 0x99, 0xfc, 0xf7, 0xd0, 0xfd, 0x03, 0x90, 0x60, 0x69, 0x01, 0x04, 
-0x09, 0x0c, 0x08, 0x02, 0x09, 0x0a, 0x08, 0x43, 0x01, 0x04, 0x09, 0x0c, 
-0x01, 0x98, 0xc0, 0x46, 0x81, 0x80, 0x30, 0x1c, 0xfc, 0xf7, 0xc1, 0xfd, 
-0x61, 0x69, 0x01, 0x31, 0xc0, 0x43, 0x61, 0x61, 0x01, 0x99, 0xc0, 0x46, 
-0x48, 0x81, 0x60, 0x6e, 0x00, 0x99, 0x46, 0x18, 0x20, 0x69, 0x01, 0x0e, 
-0xff, 0x22, 0x12, 0x04, 0x02, 0x40, 0x12, 0x0a, 0x11, 0x43, 0xff, 0x22, 
-0x12, 0x02, 0x02, 0x40, 0x12, 0x02, 0x11, 0x43, 0x00, 0x06, 0x01, 0x43, 
-0x71, 0x60, 0x03, 0x98, 0xfc, 0xf7, 0xa5, 0xfd, 0x21, 0x69, 0x49, 0x19, 
-0x21, 0x61, 0xa1, 0x68, 0x49, 0x1b, 0xa1, 0x60, 0x06, 0xd1, 0xb1, 0x89, 
-0xa2, 0x69, 0x11, 0x43, 0xb1, 0x81, 0xa1, 0x69, 0xfc, 0xf7, 0x97, 0xfd, 
-0x38, 0x82, 0x61, 0x6e, 0x38, 0x68, 0x09, 0x18, 0x0e, 0x31, 0xf9, 0x60, 
-0xe2, 0x68, 0x00, 0x99, 0x04, 0x38, 0x00, 0xf0, 0x4c, 0xf8, 0x02, 0x20, 
-0x78, 0x82, 0xe0, 0x6d, 0x41, 0x08, 0x16, 0xd3, 0x80, 0x0a, 0x0a, 0xd3, 
-0x78, 0x68, 0x10, 0x38, 0x01, 0x04, 0x09, 0x0c, 0x08, 0x02, 0x09, 0x0a, 
-0x08, 0x43, 0x39, 0x68, 0xc0, 0x46, 0xc8, 0x81, 0x09, 0xe0, 0x78, 0x68, 
-0x0c, 0x38, 0x01, 0x04, 0x09, 0x0c, 0x08, 0x02, 0x09, 0x0a, 0x08, 0x43, 
-0x39, 0x68, 0xc0, 0x46, 0x48, 0x81, 0x05, 0xb0, 0xf0, 0xbc, 0x08, 0xbc, 
-0x18, 0x47, 0x00, 0x00, 0xd0, 0x2c, 0x00, 0x80, 0x5c, 0x2b, 0x00, 0x80, 
-0x0c, 0x2b, 0x00, 0x80, 0xf7, 0xb5, 0x03, 0x1c, 0x0f, 0x1c, 0x00, 0x20, 
-0x1c, 0x68, 0x26, 0x04, 0x31, 0x1c, 0x1d, 0x1d, 0xfc, 0xf7, 0x5b, 0xfd, 
-0x40, 0xc7, 0x02, 0x9a, 0xd1, 0x1c, 0x89, 0x08, 0x01, 0x39, 0x4a, 0x1e, 
-0x02, 0x92, 0x00, 0x29, 0x0d, 0xd0, 0x21, 0x0c, 0x10, 0xcd, 0x22, 0x04, 
-0x0a, 0x43, 0x11, 0x1c, 0x16, 0x1c, 0xfc, 0xf7, 0x4a, 0xfd, 0x40, 0xc7, 
-0x02, 0x99, 0x4a, 0x1e, 0x02, 0x92, 0x00, 0x29, 0xf1, 0xd1, 0x03, 0xb0, 
-0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x80, 0x08, 0x80, 0x00, 0x89, 0x08, 
-0x89, 0x00, 0x03, 0x32, 0x93, 0x08, 0x5a, 0x1e, 0x00, 0x2b, 0x05, 0xd0, 
-0x08, 0xc9, 0x08, 0xc0, 0x13, 0x1c, 0x01, 0x3a, 0x00, 0x2b, 0xf9, 0xd1, 
-0x70, 0x47, 0xff, 0xb5, 0x86, 0xb0, 0x17, 0x1c, 0x00, 0x26, 0x06, 0x98, 
-0x80, 0x6c, 0xc0, 0x1b, 0x06, 0x99, 0xc0, 0x46, 0x88, 0x64, 0x01, 0x20, 
-0xc0, 0x05, 0x06, 0x99, 0x89, 0x6b, 0xc0, 0x46, 0x01, 0x91, 0x06, 0x99, 
-0x4c, 0x6b, 0x67, 0xe0, 0x21, 0x68, 0xc0, 0x46, 0x02, 0x91, 0x61, 0x68, 
-0xc0, 0x46, 0x03, 0x91, 0xa1, 0x68, 0xc0, 0x46, 0x04, 0x91, 0x02, 0xa9, 
-0x49, 0x88, 0xb9, 0x42, 0x08, 0xd2, 0x02, 0xad, 0x6d, 0x88, 0x02, 0xa9, 
-0x49, 0x88, 0x7f, 0x1a, 0x00, 0x21, 0x02, 0xab, 0x59, 0x80, 0x19, 0xe0, 
-0x02, 0xa9, 0x49, 0x88, 0xc9, 0x1b, 0x02, 0xab, 0x59, 0x80, 0x3d, 0x1c, 
-0x00, 0x27, 0x01, 0x21, 0x49, 0x06, 0x07, 0x9b, 0x9a, 0x07, 0x92, 0x0f, 
-0x0d, 0xd0, 0xeb, 0x06, 0xdb, 0x0e, 0x08, 0xd0, 0x1e, 0x2b, 0x08, 0xd3, 
-0x1e, 0x2b, 0x02, 0xd1, 0x03, 0x2a, 0x04, 0xd1, 0x01, 0xe0, 0x02, 0x2a, 
+0x71, 0x1a, 0x0a, 0x04, 0x12, 0x0c, 0x11, 0x02, 0x12, 0x0a, 0x11, 0x43, 
+0x09, 0x04, 0x09, 0x0c, 0x02, 0x91, 0x01, 0x02, 0x00, 0x0a, 0x08, 0x43, 
+0x01, 0x04, 0x09, 0x0c, 0x01, 0x98, 0xc0, 0x46, 0x41, 0x80, 0x20, 0x8e, 
+0xfc, 0xf7, 0xcb, 0xfd, 0x06, 0x1c, 0x60, 0x8e, 0x02, 0x99, 0xfc, 0xf7, 
+0xc6, 0xfd, 0x03, 0x90, 0x60, 0x69, 0x01, 0x04, 0x09, 0x0c, 0x08, 0x02, 
+0x09, 0x0a, 0x08, 0x43, 0x01, 0x04, 0x09, 0x0c, 0x01, 0x98, 0xc0, 0x46, 
+0x81, 0x80, 0x30, 0x1c, 0xfc, 0xf7, 0xb7, 0xfd, 0x61, 0x69, 0x01, 0x31, 
+0xc0, 0x43, 0x61, 0x61, 0x01, 0x99, 0xc0, 0x46, 0x48, 0x81, 0x60, 0x6e, 
+0x00, 0x99, 0x46, 0x18, 0x20, 0x69, 0x01, 0x0e, 0xff, 0x22, 0x12, 0x04, 
+0x02, 0x40, 0x12, 0x0a, 0x11, 0x43, 0xff, 0x22, 0x12, 0x02, 0x02, 0x40, 
+0x12, 0x02, 0x11, 0x43, 0x00, 0x06, 0x01, 0x43, 0x71, 0x60, 0x03, 0x98, 
+0xfc, 0xf7, 0x9b, 0xfd, 0x21, 0x69, 0x49, 0x19, 0x21, 0x61, 0xa1, 0x68, 
+0x49, 0x1b, 0xa1, 0x60, 0x06, 0xd1, 0xb1, 0x89, 0xa2, 0x69, 0x11, 0x43, 
+0xb1, 0x81, 0xa1, 0x69, 0xfc, 0xf7, 0x8d, 0xfd, 0x38, 0x82, 0x61, 0x6e, 
+0x38, 0x68, 0x09, 0x18, 0x0e, 0x31, 0xf9, 0x60, 0xe2, 0x68, 0x00, 0x99, 
+0x04, 0x38, 0x00, 0xf0, 0x4c, 0xf8, 0x02, 0x20, 0x78, 0x82, 0xe0, 0x6d, 
+0x41, 0x08, 0x16, 0xd3, 0x80, 0x0a, 0x0a, 0xd3, 0x78, 0x68, 0x10, 0x38, 
+0x01, 0x04, 0x09, 0x0c, 0x08, 0x02, 0x09, 0x0a, 0x08, 0x43, 0x39, 0x68, 
+0xc0, 0x46, 0xc8, 0x81, 0x09, 0xe0, 0x78, 0x68, 0x0c, 0x38, 0x01, 0x04, 
+0x09, 0x0c, 0x08, 0x02, 0x09, 0x0a, 0x08, 0x43, 0x39, 0x68, 0xc0, 0x46, 
+0x48, 0x81, 0x05, 0xb0, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 
+0xd0, 0x2c, 0x00, 0x80, 0x5c, 0x2b, 0x00, 0x80, 0x0c, 0x2b, 0x00, 0x80, 
+0xf7, 0xb5, 0x03, 0x1c, 0x0f, 0x1c, 0x00, 0x20, 0x1c, 0x68, 0x26, 0x04, 
+0x31, 0x1c, 0x1d, 0x1d, 0xfc, 0xf7, 0x51, 0xfd, 0x40, 0xc7, 0x02, 0x9a, 
+0xd1, 0x1c, 0x89, 0x08, 0x01, 0x39, 0x4a, 0x1e, 0x02, 0x92, 0x00, 0x29, 
+0x0d, 0xd0, 0x21, 0x0c, 0x10, 0xcd, 0x22, 0x04, 0x0a, 0x43, 0x11, 0x1c, 
+0x16, 0x1c, 0xfc, 0xf7, 0x40, 0xfd, 0x40, 0xc7, 0x02, 0x99, 0x4a, 0x1e, 
+0x02, 0x92, 0x00, 0x29, 0xf1, 0xd1, 0x03, 0xb0, 0xf0, 0xbc, 0x08, 0xbc, 
+0x18, 0x47, 0x80, 0x08, 0x80, 0x00, 0x89, 0x08, 0x89, 0x00, 0x03, 0x32, 
+0x93, 0x08, 0x5a, 0x1e, 0x00, 0x2b, 0x05, 0xd0, 0x08, 0xc9, 0x08, 0xc0, 
+0x13, 0x1c, 0x01, 0x3a, 0x00, 0x2b, 0xf9, 0xd1, 0x70, 0x47, 0xff, 0xb5, 
+0x86, 0xb0, 0x17, 0x1c, 0x00, 0x26, 0x06, 0x98, 0x80, 0x6c, 0xc0, 0x1b, 
+0x06, 0x99, 0xc0, 0x46, 0x88, 0x64, 0x01, 0x20, 0xc0, 0x05, 0x06, 0x99, 
+0x89, 0x6b, 0xc0, 0x46, 0x01, 0x91, 0x06, 0x99, 0x4c, 0x6b, 0x67, 0xe0, 
+0x21, 0x68, 0xc0, 0x46, 0x02, 0x91, 0x61, 0x68, 0xc0, 0x46, 0x03, 0x91, 
+0xa1, 0x68, 0xc0, 0x46, 0x04, 0x91, 0x02, 0xa9, 0x49, 0x88, 0xb9, 0x42, 
+0x08, 0xd2, 0x02, 0xad, 0x6d, 0x88, 0x02, 0xa9, 0x49, 0x88, 0x7f, 0x1a, 
+0x00, 0x21, 0x02, 0xab, 0x59, 0x80, 0x19, 0xe0, 0x02, 0xa9, 0x49, 0x88, 
+0xc9, 0x1b, 0x02, 0xab, 0x59, 0x80, 0x3d, 0x1c, 0x00, 0x27, 0x01, 0x21, 
+0x49, 0x06, 0x07, 0x9b, 0x9a, 0x07, 0x92, 0x0f, 0x0d, 0xd0, 0xeb, 0x06, 
+0xdb, 0x0e, 0x08, 0xd0, 0x1e, 0x2b, 0x08, 0xd3, 0x1e, 0x2b, 0x02, 0xd1, 
+0x03, 0x2a, 0x04, 0xd1, 0x01, 0xe0, 0x02, 0x2a, 
 0x01, 0xd3, 0x01, 0x26, 0x00, 0x21, 0x29, 0x43, 0x01, 0x43, 0x0a, 0x1c, 
-0x00, 0x91, 0x00, 0x20, 0x03, 0x99, 0x04, 0x9a, 
-0x07, 0x9b, 0x01, 0xf0, 0x5b, 0xff, 0x07, 0x99, 0x49, 0x19, 0x07, 0x91, 
-0x00, 0x2e, 0x0a, 0xd0, 0x1d, 0x4a, 0xc0, 0x46, 0x00, 0x92, 0x1d, 0x48, 
-0x01, 0x6d, 0x42, 0x6d, 0x00, 0x20, 0x07, 0x9b, 0x01, 0xf0, 0x4c, 0xff, 
-0x00, 0x26, 0x02, 0xa8, 0x40, 0x88, 0x00, 0x28, 0x0c, 0xd0, 0x03, 0x98, 
-0x40, 0x19, 0x03, 0x90, 0x02, 0x98, 0xc0, 0x46, 0x20, 0x60, 0x03, 0x98, 
-0xc0, 0x46, 0x60, 0x60, 0x04, 0x98, 0xc0, 0x46, 0xa0, 0x60, 0x03, 0xe0, 
-0x01, 0x98, 0x01, 0x38, 0x01, 0x90, 0x10, 0x34, 0x06, 0x98, 0xc0, 0x46, 
-0x44, 0x63, 0x01, 0x98, 0x06, 0x99, 0xc0, 0x46, 0x88, 0x63, 0x00, 0x20, 
-0x00, 0x2f, 0x02, 0xd0, 0x01, 0x99, 0x00, 0x29, 0x92, 0xd1, 0x09, 0x4a, 
-0xc0, 0x46, 0x00, 0x92, 0x06, 0x48, 0x01, 0x6d, 0x42, 0x6d, 0x00, 0x20, 
-0x09, 0x9b, 0x01, 0xf0, 0x1f, 0xff, 0x0a, 0xb0, 0xf0, 0xbc, 0x08, 0xbc, 
-0x18, 0x47, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x7c, 0x29, 0x00, 0x80, 
-0x04, 0x00, 0x53, 0x02, 0x90, 0xb5, 0x0c, 0x1c, 0x07, 0x1c, 0x38, 0x68, 
-0x01, 0x23, 0x9b, 0x07, 0x08, 0x38, 0x18, 0x43, 0x01, 0x68, 0x38, 0x8a, 
-0xfc, 0xf7, 0x8f, 0xfc, 0xc0, 0x43, 0xf9, 0x68, 0xc0, 0x46, 0x08, 0x80, 
-0x78, 0x8a, 0x39, 0x68, 0x08, 0x1a, 0x38, 0x60, 0x38, 0x1c, 0x01, 0xf0, 
-0x8b, 0xf9, 0x38, 0x1c, 0xfc, 0xf7, 0x96, 0xfb, 0x20, 0x1c, 0xff, 0xf7, 
-0x33, 0xfe, 0x90, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x80, 0xb5, 0x01, 0x88, 
-0x8a, 0x09, 0x21, 0xd3, 0xca, 0x09, 0x1f, 0xd2, 0x8a, 0x08, 0x1d, 0xd3, 
-0x00, 0x21, 0x01, 0x80, 0x41, 0x80, 0x47, 0x6f, 0x40, 0x6d, 0xfa, 0x1d, 
-0x19, 0x32, 0x51, 0x71, 0xfa, 0x6d, 0xc0, 0x46, 0x10, 0x60, 0x3a, 0x6e, 
-0xc0, 0x46, 0x10, 0x60, 0x0c, 0x48, 0xc0, 0x46, 0x81, 0x63, 0xc1, 0x6b, 
-0x49, 0x08, 0x49, 0x00, 0xc1, 0x63, 0x01, 0x20, 0x00, 0xf0, 0xcc, 0xff, 
-0x38, 0x1c, 0x00, 0xf0, 0x6b, 0xff, 0x80, 0xbc, 0x08, 0xbc, 0x18, 0x47, 
-0x80, 0x23, 0x19, 0x43, 0x01, 0x80, 0x01, 0x88, 0x49, 0x09, 0xf6, 0xd2, 
-0x00, 0xf0, 0xb0, 0xf8, 0xf3, 0xe7, 0x00, 0x00, 0xe8, 0x0e, 0x00, 0x80, 
-0xf0, 0xb5, 0x07, 0x1c, 0x10, 0x1c, 0x0d, 0x1c, 0x00, 0x24, 0x5e, 0x1e, 
-0x00, 0x2b, 0x19, 0xd0, 0x01, 0x68, 0xc0, 0x46, 0x39, 0x60, 0x41, 0x88, 
-0x0c, 0x19, 0x41, 0x68, 0xc0, 0x46, 0x79, 0x60, 0x81, 0x68, 0xc0, 0x46, 
-0xb9, 0x60, 0xc1, 0x68, 0xc0, 0x46, 0xf9, 0x60, 0x10, 0x30, 0x10, 0x37, 
-0xe9, 0x6a, 0x81, 0x42, 0x02, 0xd8, 0x28, 0x1c, 0x00, 0xf0, 0xec, 0xff, 
-0x31, 0x1c, 0x01, 0x3e, 0x00, 0x29, 0xe5, 0xd1, 0x20, 0x1c, 0xf0, 0xbc, 
-0x08, 0xbc, 0x18, 0x47, 0x00, 0x21, 0xc1, 0x61, 0x05, 0x49, 0x0a, 0x68, 
-0x00, 0x2a, 0x01, 0xd1, 0x08, 0x60, 0x02, 0xe0, 0x4a, 0x68, 0xc0, 0x46, 
-0xd0, 0x61, 0x48, 0x60, 0x70, 0x47, 0x00, 0x00, 0xd0, 0x2c, 0x00, 0x80, 
-0x03, 0x49, 0x08, 0x68, 0x00, 0x28, 0x02, 0xd0, 0xc2, 0x69, 0xc0, 0x46, 
-0x0a, 0x60, 0x70, 0x47, 0xd0, 0x2c, 0x00, 0x80, 0x00, 0x21, 0x81, 0x67, 
-0x05, 0x49, 0x8a, 0x68, 0x00, 0x2a, 0x01, 0xd1, 0x88, 0x60, 0x02, 0xe0, 
-0xca, 0x68, 0xc0, 0x46, 0x90, 0x67, 0xc8, 0x60, 0x70, 0x47, 0x00, 0x00, 
-0xd0, 0x2c, 0x00, 0x80, 0x03, 0x49, 0x88, 0x68, 0x00, 0x28, 0x02, 0xd0, 
-0x82, 0x6f, 0xc0, 0x46, 0x8a, 0x60, 0x70, 0x47, 0xd0, 0x2c, 0x00, 0x80, 
+0x00, 0x91, 0x00, 0x20, 0x03, 0x99, 0x04, 0x9a, 0x07, 0x9b, 0x01, 0xf0, 
+0x5b, 0xff, 0x07, 0x99, 0x49, 0x19, 0x07, 0x91, 0x00, 0x2e, 0x0a, 0xd0, 
+0x1d, 0x4a, 0xc0, 0x46, 0x00, 0x92, 0x1d, 0x48, 0x01, 0x6d, 0x42, 0x6d, 
+0x00, 0x20, 0x07, 0x9b, 0x01, 0xf0, 0x4c, 0xff, 0x00, 0x26, 0x02, 0xa8, 
+0x40, 0x88, 0x00, 0x28, 0x0c, 0xd0, 0x03, 0x98, 0x40, 0x19, 0x03, 0x90, 
+0x02, 0x98, 0xc0, 0x46, 0x20, 0x60, 0x03, 0x98, 0xc0, 0x46, 0x60, 0x60, 
+0x04, 0x98, 0xc0, 0x46, 0xa0, 0x60, 0x03, 0xe0, 0x01, 0x98, 0x01, 0x38, 
+0x01, 0x90, 0x10, 0x34, 0x06, 0x98, 0xc0, 0x46, 0x44, 0x63, 0x01, 0x98, 
+0x06, 0x99, 0xc0, 0x46, 0x88, 0x63, 0x00, 0x20, 0x00, 0x2f, 0x02, 0xd0, 
+0x01, 0x99, 0x00, 0x29, 0x92, 0xd1, 0x09, 0x4a, 0xc0, 0x46, 0x00, 0x92, 
+0x06, 0x48, 0x01, 0x6d, 0x42, 0x6d, 0x00, 0x20, 0x09, 0x9b, 0x01, 0xf0, 
+0x1f, 0xff, 0x0a, 0xb0, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 
+0x01, 0x00, 0x00, 0x02, 0x7c, 0x29, 0x00, 0x80, 0x04, 0x00, 0x53, 0x02, 
+0x90, 0xb5, 0x0c, 0x1c, 0x07, 0x1c, 0x38, 0x68, 0x01, 0x23, 0x9b, 0x07, 
+0x08, 0x38, 0x18, 0x43, 0x01, 0x68, 0x38, 0x8a, 0xfc, 0xf7, 0x85, 0xfc, 
+0xc0, 0x43, 0xf9, 0x68, 0xc0, 0x46, 0x08, 0x80, 0x78, 0x8a, 0x39, 0x68, 
+0x08, 0x1a, 0x38, 0x60, 0x38, 0x1c, 0x01, 0xf0, 0x8b, 0xf9, 0x38, 0x1c, 
+0xfc, 0xf7, 0x8c, 0xfb, 0x20, 0x1c, 0xff, 0xf7, 0x33, 0xfe, 0x90, 0xbc, 
+0x08, 0xbc, 0x18, 0x47, 0x80, 0xb5, 0x01, 0x88, 0x8a, 0x09, 0x21, 0xd3, 
+0xca, 0x09, 0x1f, 0xd2, 0x8a, 0x08, 0x1d, 0xd3, 0x00, 0x21, 0x01, 0x80, 
+0x41, 0x80, 0x47, 0x6f, 0x40, 0x6d, 0xfa, 0x1d, 0x19, 0x32, 0x51, 0x71, 
+0xfa, 0x6d, 0xc0, 0x46, 0x10, 0x60, 0x3a, 0x6e, 0xc0, 0x46, 0x10, 0x60, 
+0x0c, 0x48, 0xc0, 0x46, 0x81, 0x63, 0xc1, 0x6b, 0x49, 0x08, 0x49, 0x00, 
+0xc1, 0x63, 0x01, 0x20, 0x00, 0xf0, 0xcc, 0xff, 0x38, 0x1c, 0x00, 0xf0, 
+0x6b, 0xff, 0x80, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x80, 0x23, 0x19, 0x43, 
+0x01, 0x80, 0x01, 0x88, 0x49, 0x09, 0xf6, 0xd2, 0x00, 0xf0, 0xb0, 0xf8, 
+0xf3, 0xe7, 0x00, 0x00, 0xe8, 0x0e, 0x00, 0x80, 0xf0, 0xb5, 0x07, 0x1c, 
+0x10, 0x1c, 0x0d, 0x1c, 0x00, 0x24, 0x5e, 0x1e, 0x00, 0x2b, 0x19, 0xd0, 
+0x01, 0x68, 0xc0, 0x46, 0x39, 0x60, 0x41, 0x88, 0x0c, 0x19, 0x41, 0x68, 
+0xc0, 0x46, 0x79, 0x60, 0x81, 0x68, 0xc0, 0x46, 0xb9, 0x60, 0xc1, 0x68, 
+0xc0, 0x46, 0xf9, 0x60, 0x10, 0x30, 0x10, 0x37, 0xe9, 0x6a, 0x81, 0x42, 
+0x02, 0xd8, 0x28, 0x1c, 0x00, 0xf0, 0xec, 0xff, 0x31, 0x1c, 0x01, 0x3e, 
+0x00, 0x29, 0xe5, 0xd1, 0x20, 0x1c, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 
+0x00, 0x21, 0xc1, 0x61, 0x05, 0x49, 0x0a, 0x68, 0x00, 0x2a, 0x01, 0xd1, 
+0x08, 0x60, 0x02, 0xe0, 0x4a, 0x68, 0xc0, 0x46, 0xd0, 0x61, 0x48, 0x60, 
+0x70, 0x47, 0x00, 0x00, 0xd0, 0x2c, 0x00, 0x80, 0x03, 0x49, 0x08, 0x68, 
+0x00, 0x28, 0x02, 0xd0, 0xc2, 0x69, 0xc0, 0x46, 0x0a, 0x60, 0x70, 0x47, 
+0xd0, 0x2c, 0x00, 0x80, 0x00, 0x21, 0x81, 0x67, 0x05, 0x49, 0x8a, 0x68, 
+0x00, 0x2a, 0x01, 0xd1, 0x88, 0x60, 0x02, 0xe0, 0xca, 0x68, 0xc0, 0x46, 
+0x90, 0x67, 0xc8, 0x60, 0x70, 0x47, 0x00, 0x00, 0xd0, 0x2c, 0x00, 0x80, 
+0x03, 0x49, 0x88, 0x68, 0x00, 0x28, 0x02, 0xd0, 0x82, 0x6f, 0xc0, 0x46, 
+0x8a, 0x60, 0x70, 0x47, 0xd0, 0x2c, 0x00, 0x80, 
 0x00, 0xb5, 0x80, 0x20, 0x13, 0x49, 0xc0, 0x46, 0x08, 0x60, 0xff, 0xf7, 
-0xd5, 0xff, 0x00, 0x28, 0x1b, 0xd0, 0x03, 0x23, 
-0x1b, 0x07, 0x41, 0x68, 0x19, 0x40, 0x0a, 0x0f, 0x51, 0x01, 0x89, 0x1a, 
-0x89, 0x00, 0x0d, 0x4b, 0xc9, 0x18, 0x4b, 0x88, 0x00, 0x2b, 0x04, 0xd1, 
-0x11, 0x1c, 0xff, 0xf7, 0x3b, 0xff, 0x08, 0xbc, 0x18, 0x47, 0x01, 0x2b, 
-0x02, 0xd1, 0xff, 0xf7, 0x05, 0xfc, 0xf8, 0xe7, 0x02, 0x2b, 0xf6, 0xd1, 
-0xff, 0xf7, 0x4e, 0xfb, 0xf3, 0xe7, 0x04, 0x48, 0x01, 0x6d, 0x01, 0x31, 
-0x01, 0x65, 0xee, 0xe7, 0x00, 0x00, 0x00, 0xb0, 0x5c, 0x2b, 0x00, 0x80, 
-0xa0, 0x82, 0x20, 0x40, 0x00, 0xb5, 0x20, 0x20, 0x0d, 0x49, 0xc0, 0x46, 
-0x08, 0x60, 0xff, 0xf7, 0xbf, 0xff, 0x00, 0x28, 0x0e, 0xd0, 0x01, 0x88, 
-0x20, 0x23, 0x19, 0x43, 0x01, 0x80, 0x01, 0x88, 0x10, 0x23, 0x99, 0x43, 
-0x01, 0x80, 0x01, 0x88, 0x09, 0x0a, 0x01, 0xd3, 0xff, 0xf7, 0x2e, 0xff, 
-0x08, 0xbc, 0x18, 0x47, 0x03, 0x48, 0x01, 0x6d, 0x01, 0x31, 0x01, 0x65, 
-0xf8, 0xe7, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0xa0, 0x82, 0x20, 0x40, 
-0x98, 0xb5, 0x07, 0x1c, 0x22, 0x48, 0xc0, 0x46, 0x00, 0x90, 0x22, 0x48, 
-0xc3, 0x1d, 0x41, 0x33, 0x41, 0x6d, 0x82, 0x6d, 0x80, 0x6c, 0x00, 0x03, 
-0x00, 0x0b, 0x9c, 0x68, 0x01, 0x23, 0x9b, 0x07, 0x23, 0x43, 0x1b, 0x68, 
-0x98, 0x42, 0x00, 0xd1, 0x0c, 0xe0, 0x98, 0x42, 0x03, 0xd9, 0x10, 0x1a, 
-0x59, 0x1a, 0x41, 0x18, 0x00, 0xe0, 0x19, 0x1a, 0x01, 0x20, 0x10, 0x29, 
-0x00, 0xd8, 0x00, 0x20, 0x00, 0x28, 0x1f, 0xd0, 0x78, 0x6a, 0xf9, 0x6a, 
-0xc0, 0x46, 0x08, 0x60, 0xb8, 0x6a, 0xf9, 0x6a, 0xc0, 0x46, 0x48, 0x60, 
-0x10, 0x4a, 0xc0, 0x46, 0x00, 0x92, 0xfb, 0x6a, 0x0f, 0x48, 0x42, 0x6d, 
-0x03, 0x20, 0x39, 0x6a, 0x01, 0xf0, 0xe2, 0xfd, 0x38, 0x88, 0x10, 0x23, 
-0x18, 0x43, 0x38, 0x80, 0x38, 0x88, 0x40, 0x23, 0x98, 0x43, 0x38, 0x80, 
-0x38, 0x1c, 0xff, 0xf7, 0x55, 0xff, 0x98, 0xbc, 0x08, 0xbc, 0x18, 0x47, 
-0x38, 0x88, 0x40, 0x23, 0x18, 0x43, 0x38, 0x80, 0xf7, 0xe7, 0x00, 0x00, 
-0x55, 0x55, 0x55, 0x55, 0xa8, 0x03, 0x00, 0x80, 0x08, 0x00, 0x11, 0x02, 
-0x7c, 0x29, 0x00, 0x80, 0xb0, 0xb5, 0x40, 0x20, 0x2c, 0x49, 0xc0, 0x46, 
-0x08, 0x60, 0x00, 0xf0, 0xfd, 0xfe, 0x07, 0x1c, 0x40, 0x68, 0x03, 0x23, 
-0x1b, 0x07, 0x18, 0x40, 0x05, 0x0f, 0x68, 0x01, 0x40, 0x1b, 0x80, 0x00, 
-0x26, 0x49, 0x44, 0x18, 0x20, 0x88, 0x02, 0x23, 0x18, 0x43, 0x20, 0x80, 
-0x20, 0x88, 0x41, 0x08, 0x34, 0xd3, 0x40, 0x08, 0x40, 0x00, 0x20, 0x80, 
-0xa0, 0x6c, 0xe1, 0x6c, 0x40, 0x18, 0xa0, 0x64, 0x00, 0x20, 0xe0, 0x64, 
-0xa1, 0x6b, 0x22, 0x6d, 0x89, 0x18, 0xa1, 0x63, 0x20, 0x65, 0xb8, 0x6a, 
-0xc0, 0x46, 0x60, 0x65, 0x03, 0x23, 0x1b, 0x07, 0x78, 0x68, 0x18, 0x40, 
-0x78, 0x60, 0x61, 0x68, 0x36, 0x31, 0x94, 0x29, 0x04, 0xd8, 0x38, 0x23, 
-0x18, 0x43, 0x78, 0x60, 0x38, 0x20, 0x03, 0xe0, 0x94, 0x23, 0x18, 0x43, 
-0x78, 0x60, 0x94, 0x20, 0xb8, 0x61, 0x39, 0x68, 0x78, 0x68, 0x02, 0x04, 
-0x12, 0x0c, 0x20, 0x1c, 0xcb, 0x1f, 0x05, 0x3b, 0xff, 0xf7, 0xd7, 0xfd, 
-0x02, 0x20, 0x60, 0x80, 0x38, 0x1c, 0xff, 0xf7, 0xdf, 0xfe, 0xb0, 0xbc, 
-0x08, 0xbc, 0x18, 0x47, 0x38, 0x1c, 0xfc, 0xf7, 0x11, 0xfa, 0x28, 0x01, 
-0x06, 0x49, 0x40, 0x18, 0x19, 0x23, 0xdb, 0x01, 0xc0, 0x18, 0x41, 0x6b, 
-0x01, 0x39, 0x41, 0x63, 0xef, 0xe7, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 
+0xd5, 0xff, 0x00, 0x28, 0x1b, 0xd0, 0x03, 0x23, 0x1b, 0x07, 0x41, 0x68, 
+0x19, 0x40, 0x0a, 0x0f, 0x51, 0x01, 0x89, 0x1a, 0x89, 0x00, 0x0d, 0x4b, 
+0xc9, 0x18, 0x4b, 0x88, 0x00, 0x2b, 0x04, 0xd1, 0x11, 0x1c, 0xff, 0xf7, 
+0x3b, 0xff, 0x08, 0xbc, 0x18, 0x47, 0x01, 0x2b, 0x02, 0xd1, 0xff, 0xf7, 
+0x05, 0xfc, 0xf8, 0xe7, 0x02, 0x2b, 0xf6, 0xd1, 0xff, 0xf7, 0x4e, 0xfb, 
+0xf3, 0xe7, 0x04, 0x48, 0x01, 0x6d, 0x01, 0x31, 0x01, 0x65, 0xee, 0xe7, 
+0x00, 0x00, 0x00, 0xb0, 0x5c, 0x2b, 0x00, 0x80, 0xa0, 0x82, 0x20, 0x40, 
+0x00, 0xb5, 0x20, 0x20, 0x0d, 0x49, 0xc0, 0x46, 0x08, 0x60, 0xff, 0xf7, 
+0xbf, 0xff, 0x00, 0x28, 0x0e, 0xd0, 0x01, 0x88, 0x20, 0x23, 0x19, 0x43, 
+0x01, 0x80, 0x01, 0x88, 0x10, 0x23, 0x99, 0x43, 0x01, 0x80, 0x01, 0x88, 
+0x09, 0x0a, 0x01, 0xd3, 0xff, 0xf7, 0x2e, 0xff, 0x08, 0xbc, 0x18, 0x47, 
+0x03, 0x48, 0x01, 0x6d, 0x01, 0x31, 0x01, 0x65, 0xf8, 0xe7, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0xb0, 0xa0, 0x82, 0x20, 0x40, 0x98, 0xb5, 0x07, 0x1c, 
+0x22, 0x48, 0xc0, 0x46, 0x00, 0x90, 0x22, 0x48, 0xc3, 0x1d, 0x41, 0x33, 
+0x41, 0x6d, 0x82, 0x6d, 0x80, 0x6c, 0x00, 0x03, 0x00, 0x0b, 0x9c, 0x68, 
+0x01, 0x23, 0x9b, 0x07, 0x23, 0x43, 0x1b, 0x68, 0x98, 0x42, 0x00, 0xd1, 
+0x0c, 0xe0, 0x98, 0x42, 0x03, 0xd9, 0x10, 0x1a, 0x59, 0x1a, 0x41, 0x18, 
+0x00, 0xe0, 0x19, 0x1a, 0x01, 0x20, 0x10, 0x29, 0x00, 0xd8, 0x00, 0x20, 
+0x00, 0x28, 0x1f, 0xd0, 0x78, 0x6a, 0xf9, 0x6a, 0xc0, 0x46, 0x08, 0x60, 
+0xb8, 0x6a, 0xf9, 0x6a, 0xc0, 0x46, 0x48, 0x60, 0x10, 0x4a, 0xc0, 0x46, 
+0x00, 0x92, 0xfb, 0x6a, 0x0f, 0x48, 0x42, 0x6d, 0x03, 0x20, 0x39, 0x6a, 
+0x01, 0xf0, 0xe2, 0xfd, 0x38, 0x88, 0x10, 0x23, 0x18, 0x43, 0x38, 0x80, 
+0x38, 0x88, 0x40, 0x23, 0x98, 0x43, 0x38, 0x80, 0x38, 0x1c, 0xff, 0xf7, 
+0x55, 0xff, 0x98, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x38, 0x88, 0x40, 0x23, 
+0x18, 0x43, 0x38, 0x80, 0xf7, 0xe7, 0x00, 0x00, 0x55, 0x55, 0x55, 0x55, 
+0xa8, 0x03, 0x00, 0x80, 0x08, 0x00, 0x11, 0x02, 0x7c, 0x29, 0x00, 0x80, 
+0xb0, 0xb5, 0x40, 0x20, 0x2c, 0x49, 0xc0, 0x46, 0x08, 0x60, 0x00, 0xf0, 
+0xfd, 0xfe, 0x07, 0x1c, 0x40, 0x68, 0x03, 0x23, 0x1b, 0x07, 0x18, 0x40, 
+0x05, 0x0f, 0x68, 0x01, 0x40, 0x1b, 0x80, 0x00, 0x26, 0x49, 0x44, 0x18, 
+0x20, 0x88, 0x02, 0x23, 0x18, 0x43, 0x20, 0x80, 0x20, 0x88, 0x41, 0x08, 
+0x34, 0xd3, 0x40, 0x08, 0x40, 0x00, 0x20, 0x80, 0xa0, 0x6c, 0xe1, 0x6c, 
+0x40, 0x18, 0xa0, 0x64, 0x00, 0x20, 0xe0, 0x64, 0xa1, 0x6b, 0x22, 0x6d, 
+0x89, 0x18, 0xa1, 0x63, 0x20, 0x65, 0xb8, 0x6a, 0xc0, 0x46, 0x60, 0x65, 
+0x03, 0x23, 0x1b, 0x07, 0x78, 0x68, 0x18, 0x40, 0x78, 0x60, 0x61, 0x68, 
+0x36, 0x31, 0x94, 0x29, 0x04, 0xd8, 0x38, 0x23, 0x18, 0x43, 0x78, 0x60, 
+0x38, 0x20, 0x03, 0xe0, 0x94, 0x23, 0x18, 0x43, 0x78, 0x60, 0x94, 0x20, 
+0xb8, 0x61, 0x39, 0x68, 0x78, 0x68, 0x02, 0x04, 0x12, 0x0c, 0x20, 0x1c, 
+0xcb, 0x1f, 0x05, 0x3b, 0xff, 0xf7, 0xd7, 0xfd, 0x02, 0x20, 0x60, 0x80, 
+0x38, 0x1c, 0xff, 0xf7, 0xdf, 0xfe, 0xb0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 
+0x38, 0x1c, 0xfc, 0xf7, 0x07, 0xfa, 0x28, 0x01, 0x06, 0x49, 0x40, 0x18, 
+0x19, 0x23, 0xdb, 0x01, 0xc0, 0x18, 0x41, 0x6b, 0x01, 0x39, 0x41, 0x63, 
+0xef, 0xe7, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 
 0x5c, 0x2b, 0x00, 0x80, 0xa0, 0x1c, 0x00, 0x80, 0x90, 0xb5, 0x00, 0x27, 
-0x0f, 0x4c, 0x0d, 0xe0, 0x42, 0x6b, 0x01, 0x3a, 
-0x42, 0x63, 0x00, 0x2a, 0x05, 0xdc, 0x02, 0x6b, 0xc0, 0x46, 0x42, 0x63, 
-0xc0, 0x6a, 0x01, 0xf0, 0xc6, 0xf9, 0x01, 0x37, 0x0b, 0x2f, 0x07, 0xd2, 
-0x38, 0x01, 0x00, 0x19, 0x33, 0x23, 0x9b, 0x01, 0xc0, 0x18, 0x81, 0x6a, 
-0x00, 0x29, 0xe9, 0xd1, 0x01, 0x20, 0x40, 0x06, 0x03, 0x49, 0xc0, 0x46, 
-0x08, 0x60, 0x90, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x68, 0x0e, 0x00, 0x80, 
-0x00, 0x00, 0x00, 0xb0, 0x10, 0x48, 0xc1, 0x68, 0x01, 0x31, 0xc1, 0x60, 
-0x0f, 0x49, 0xc8, 0x68, 0x01, 0x28, 0x17, 0xd1, 0xc8, 0x1d, 0x79, 0x30, 
-0x02, 0x89, 0x00, 0x2a, 0x12, 0xd0, 0x01, 0x3a, 0x02, 0x81, 0x02, 0x89, 
-0x00, 0x2a, 0x0d, 0xd1, 0x42, 0x89, 0x00, 0x2a, 0x08, 0xd1, 0xc9, 0x6f, 
-0x02, 0x23, 0x0a, 0x68, 0x1a, 0x43, 0x0a, 0x60, 0x04, 0x21, 0x01, 0x81, 
-0x01, 0x21, 0x00, 0xe0, 0x00, 0x21, 0x41, 0x81, 0x70, 0x47, 0x00, 0x00, 
-0x08, 0x83, 0x20, 0x40, 0x68, 0x0e, 0x00, 0x80, 0xb0, 0xb5, 0x07, 0x1c, 
-0x01, 0x23, 0xf8, 0x1d, 0x69, 0x30, 0x03, 0x73, 0x1e, 0x48, 0xc2, 0x1d, 
-0x79, 0x32, 0x54, 0x8a, 0x61, 0x1c, 0x51, 0x82, 0xd5, 0x8a, 0x00, 0x21, 
-0xac, 0x42, 0x04, 0xdb, 0xc4, 0x1d, 0x89, 0x34, 0x63, 0x70, 0x51, 0x82, 
-0xd1, 0x83, 0x01, 0x23, 0x9b, 0x07, 0x3a, 0x6d, 0x1a, 0x43, 0x12, 0x68, 
-0xc0, 0x46, 0xba, 0x61, 0xfb, 0x69, 0x9a, 0x42, 0x06, 0xd1, 0xf8, 0x6c, 
-0x12, 0x49, 0xc0, 0x46, 0x08, 0x60, 0xb0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 
-0x79, 0x61, 0x41, 0x69, 0xfa, 0x6c, 0x91, 0x43, 0x41, 0x61, 0x01, 0x20, 
-0x00, 0x05, 0xc1, 0x60, 0x38, 0x69, 0x02, 0x28, 0xf1, 0xd0, 0xb8, 0x69, 
-0xf9, 0x69, 0x41, 0x1a, 0x01, 0xd5, 0x78, 0x6d, 0x41, 0x18, 0x38, 0x1c, 
-0x00, 0xf0, 0x0e, 0xf8, 0xf9, 0x69, 0x09, 0x18, 0xf9, 0x61, 0x78, 0x6d, 
-0x81, 0x42, 0xe2, 0xd3, 0x08, 0x1a, 0xf8, 0x61, 0xdf, 0xe7, 0x00, 0x00, 
-0x68, 0x0e, 0x00, 0x80, 0x00, 0x00, 0x00, 0xb0, 0xf8, 0xb5, 0x04, 0x1c, 
-0x0f, 0x1c, 0xff, 0x23, 0x21, 0x33, 0x9f, 0x42, 0x01, 0xd9, 0xff, 0x27, 
-0x21, 0x37, 0xe1, 0x6e, 0x38, 0x1c, 0x01, 0xf0, 0xcb, 0xfc, 0x2d, 0x4d, 
-0x00, 0x28, 0x13, 0xd1, 0xe0, 0x1d, 0x49, 0x30, 0x01, 0x7a, 0x01, 0x23, 
-0x19, 0x43, 0x01, 0x72, 0x29, 0x4a, 0xc0, 0x46, 0x00, 0x92, 0x29, 0x48, 
-0x01, 0x6d, 0x42, 0x6d, 0x00, 0x20, 0x2b, 0x1c, 0x01, 0xf0, 0xb0, 0xfc, 
-0x00, 0x20, 0xf8, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x20, 0x69, 0x01, 0x30, 
-0x20, 0x61, 0x23, 0x49, 0xc8, 0x1d, 0xb9, 0x30, 0x02, 0x6b, 0x92, 0x00, 
-0x51, 0x18, 0xc0, 0x31, 0x0f, 0x61, 0x01, 0x6b, 0x01, 0x31, 0x89, 0x07, 
-0x89, 0x0f, 0x01, 0x63, 0x20, 0x6b, 0xc2, 0x19, 0x61, 0x6d, 0x8a, 0x42, 
-0x03, 0xd8, 0x23, 0x22, 0x12, 0x05, 0x3a, 0x43, 0x05, 0xe0, 0x09, 0x1a, 
-0x7e, 0x1a, 0x07, 0xd1, 0x23, 0x22, 0x12, 0x05, 0x0a, 0x43, 0x00, 0x92, 
-0x61, 0x6e, 0x09, 0x18, 0xa2, 0x6e, 0x10, 0xe0, 0x11, 0x22, 0x52, 0x05, 
-0x0a, 0x43, 0x00, 0x92, 0x61, 0x6e, 0x09, 0x18, 0x00, 0x20, 0xa2, 0x6e, 
-0x2b, 0x1c, 0x01, 0xf0, 0x7d, 0xfc, 0x23, 0x22, 0x12, 0x05, 0x32, 0x43, 
-0x00, 0x92, 0x61, 0x6e, 0xa2, 0x6e, 0x00, 0x20, 0x2b, 0x1c, 0x01, 0xf0, 
-0x73, 0xfc, 0x20, 0x6b, 0xc0, 0x19, 0x00, 0x09, 0x00, 0x01, 0x61, 0x6d, 
-0x81, 0x42, 0x00, 0xd8, 0x40, 0x1a, 0x20, 0x63, 0x38, 0x1c, 0xb8, 0xe7, 
+0x0f, 0x4c, 0x0d, 0xe0, 0x42, 0x6b, 0x01, 0x3a, 0x42, 0x63, 0x00, 0x2a, 
+0x05, 0xdc, 0x02, 0x6b, 0xc0, 0x46, 0x42, 0x63, 0xc0, 0x6a, 0x01, 0xf0, 
+0xc6, 0xf9, 0x01, 0x37, 0x0b, 0x2f, 0x07, 0xd2, 0x38, 0x01, 0x00, 0x19, 
+0x33, 0x23, 0x9b, 0x01, 0xc0, 0x18, 0x81, 0x6a, 0x00, 0x29, 0xe9, 0xd1, 
+0x01, 0x20, 0x40, 0x06, 0x03, 0x49, 0xc0, 0x46, 0x08, 0x60, 0x90, 0xbc, 
+0x08, 0xbc, 0x18, 0x47, 0x68, 0x0e, 0x00, 0x80, 0x00, 0x00, 0x00, 0xb0, 
+0x10, 0x48, 0xc1, 0x68, 0x01, 0x31, 0xc1, 0x60, 0x0f, 0x49, 0xc8, 0x68, 
+0x01, 0x28, 0x17, 0xd1, 0xc8, 0x1d, 0x79, 0x30, 0x02, 0x89, 0x00, 0x2a, 
+0x12, 0xd0, 0x01, 0x3a, 0x02, 0x81, 0x02, 0x89, 0x00, 0x2a, 0x0d, 0xd1, 
+0x42, 0x89, 0x00, 0x2a, 0x08, 0xd1, 0xc9, 0x6f, 0x02, 0x23, 0x0a, 0x68, 
+0x1a, 0x43, 0x0a, 0x60, 0x04, 0x21, 0x01, 0x81, 0x01, 0x21, 0x00, 0xe0, 
+0x00, 0x21, 0x41, 0x81, 0x70, 0x47, 0x00, 0x00, 0x08, 0x83, 0x20, 0x40, 
+0x68, 0x0e, 0x00, 0x80, 0xb0, 0xb5, 0x07, 0x1c, 0x01, 0x23, 0xf8, 0x1d, 
+0x69, 0x30, 0x03, 0x73, 0x1e, 0x48, 0xc2, 0x1d, 0x79, 0x32, 0x54, 0x8a, 
+0x61, 0x1c, 0x51, 0x82, 0xd5, 0x8a, 0x00, 0x21, 0xac, 0x42, 0x04, 0xdb, 
+0xc4, 0x1d, 0x89, 0x34, 0x63, 0x70, 0x51, 0x82, 0xd1, 0x83, 0x01, 0x23, 
+0x9b, 0x07, 0x3a, 0x6d, 0x1a, 0x43, 0x12, 0x68, 0xc0, 0x46, 0xba, 0x61, 
+0xfb, 0x69, 0x9a, 0x42, 0x06, 0xd1, 0xf8, 0x6c, 0x12, 0x49, 0xc0, 0x46, 
+0x08, 0x60, 0xb0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x79, 0x61, 0x41, 0x69, 
+0xfa, 0x6c, 0x91, 0x43, 0x41, 0x61, 0x01, 0x20, 0x00, 0x05, 0xc1, 0x60, 
+0x38, 0x69, 0x02, 0x28, 0xf1, 0xd0, 0xb8, 0x69, 0xf9, 0x69, 0x41, 0x1a, 
+0x01, 0xd5, 0x78, 0x6d, 0x41, 0x18, 0x38, 0x1c, 0x00, 0xf0, 0x0e, 0xf8, 
+0xf9, 0x69, 0x09, 0x18, 0xf9, 0x61, 0x78, 0x6d, 0x81, 0x42, 0xe2, 0xd3, 
+0x08, 0x1a, 0xf8, 0x61, 0xdf, 0xe7, 0x00, 0x00, 0x68, 0x0e, 0x00, 0x80, 
+0x00, 0x00, 0x00, 0xb0, 0xf8, 0xb5, 0x04, 0x1c, 0x0f, 0x1c, 0xff, 0x23, 
+0x21, 0x33, 0x9f, 0x42, 0x01, 0xd9, 0xff, 0x27, 0x21, 0x37, 0xe1, 0x6e, 
+0x38, 0x1c, 0x01, 0xf0, 0xcb, 0xfc, 0x2d, 0x4d, 0x00, 0x28, 0x13, 0xd1, 
+0xe0, 0x1d, 0x49, 0x30, 0x01, 0x7a, 0x01, 0x23, 0x19, 0x43, 0x01, 0x72, 
+0x29, 0x4a, 0xc0, 0x46, 0x00, 0x92, 0x29, 0x48, 0x01, 0x6d, 0x42, 0x6d, 
+0x00, 0x20, 0x2b, 0x1c, 0x01, 0xf0, 0xb0, 0xfc, 0x00, 0x20, 0xf8, 0xbc, 
+0x08, 0xbc, 0x18, 0x47, 0x20, 0x69, 0x01, 0x30, 0x20, 0x61, 0x23, 0x49, 
+0xc8, 0x1d, 0xb9, 0x30, 0x02, 0x6b, 0x92, 0x00, 0x51, 0x18, 0xc0, 0x31, 
+0x0f, 0x61, 0x01, 0x6b, 0x01, 0x31, 0x89, 0x07, 0x89, 0x0f, 0x01, 0x63, 
+0x20, 0x6b, 0xc2, 0x19, 0x61, 0x6d, 0x8a, 0x42, 0x03, 0xd8, 0x23, 0x22, 
+0x12, 0x05, 0x3a, 0x43, 0x05, 0xe0, 0x09, 0x1a, 0x7e, 0x1a, 0x07, 0xd1, 
+0x23, 0x22, 0x12, 0x05, 0x0a, 0x43, 0x00, 0x92, 0x61, 0x6e, 0x09, 0x18, 
+0xa2, 0x6e, 0x10, 0xe0, 0x11, 0x22, 0x52, 0x05, 0x0a, 0x43, 0x00, 0x92, 
+0x61, 0x6e, 0x09, 0x18, 0x00, 0x20, 0xa2, 0x6e, 0x2b, 0x1c, 0x01, 0xf0, 
+0x7d, 0xfc, 0x23, 0x22, 0x12, 0x05, 0x32, 0x43, 0x00, 0x92, 0x61, 0x6e, 
+0xa2, 0x6e, 0x00, 0x20, 0x2b, 0x1c, 0x01, 0xf0, 0x73, 0xfc, 0x20, 0x6b, 
+0xc0, 0x19, 0x00, 0x09, 0x00, 0x01, 0x61, 0x6d, 0x81, 0x42, 0x00, 0xd8, 
+0x40, 0x1a, 0x20, 0x63, 0x38, 0x1c, 0xb8, 0xe7, 
 0x44, 0x80, 0x20, 0x40, 0x04, 0x00, 0x1b, 0x02, 0x7c, 0x29, 0x00, 0x80, 
-0x68, 0x0e, 0x00, 0x80, 0x80, 0xb5, 0x01, 0x20, 
-0xc0, 0x03, 0x0d, 0x49, 0xc0, 0x46, 0x08, 0x60, 0x0c, 0x49, 0xc8, 0x1d, 
-0x49, 0x30, 0x02, 0x7a, 0x00, 0x27, 0x00, 0x2a, 0x03, 0xd0, 0x07, 0x72, 
-0x08, 0x1c, 0xff, 0xf7, 0x37, 0xff, 0x08, 0x49, 0xc8, 0x1d, 0x49, 0x30, 
-0x02, 0x7a, 0x00, 0x2a, 0x03, 0xd0, 0x07, 0x72, 0x08, 0x1c, 0xff, 0xf7, 
-0x2d, 0xff, 0x80, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0x00, 0xb0, 
-0x64, 0x2d, 0x00, 0x80, 0xe4, 0x2c, 0x00, 0x80, 0x90, 0xb5, 0x07, 0x1c, 
-0x10, 0x20, 0x18, 0x49, 0xc0, 0x46, 0x08, 0x60, 0xf8, 0x68, 0x01, 0x30, 
-0xf8, 0x60, 0x16, 0x48, 0xc4, 0x1d, 0xb9, 0x34, 0x61, 0x6b, 0x89, 0x00, 
-0x09, 0x18, 0xc0, 0x31, 0x09, 0x69, 0x7a, 0x68, 0x92, 0x00, 0xd2, 0x19, 
-0x51, 0x64, 0x61, 0x6b, 0x89, 0x00, 0x08, 0x18, 0xc0, 0x30, 0x01, 0x69, 
-0x78, 0x68, 0x80, 0x00, 0xc0, 0x19, 0xc0, 0x6b, 0x01, 0xf0, 0xa2, 0xfa, 
-0x01, 0x23, 0x78, 0x68, 0x58, 0x40, 0x78, 0x60, 0x60, 0x6b, 0x01, 0x30, 
-0x80, 0x07, 0x80, 0x0f, 0x60, 0x63, 0xf8, 0x1d, 0x19, 0x30, 0x40, 0x79, 
-0x00, 0x28, 0x02, 0xd1, 0x38, 0x1c, 0x00, 0xf0, 0x07, 0xf8, 0x90, 0xbc, 
-0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0x00, 0xb0, 0x68, 0x0e, 0x00, 0x80, 
-0x90, 0xb5, 0x07, 0x1c, 0x39, 0x48, 0xc0, 0x68, 0x00, 0x28, 0x05, 0xd0, 
-0xb8, 0x6a, 0xc0, 0x68, 0x80, 0x09, 0x01, 0xd3, 0x02, 0x20, 0x00, 0xe0, 
-0x78, 0x6f, 0xfc, 0xf7, 0x63, 0xf8, 0x04, 0x1c, 0x06, 0xd1, 0x01, 0x20, 
-0xf9, 0x1d, 0x19, 0x31, 0x08, 0x71, 0x90, 0xbc, 0x08, 0xbc, 0x18, 0x47, 
-0xf8, 0x6c, 0x2f, 0x49, 0xc0, 0x46, 0x08, 0x60, 0xba, 0x6a, 0x38, 0x1c, 
-0x21, 0x1c, 0x00, 0xf0, 0x59, 0xf8, 0x67, 0x62, 0x00, 0x28, 0x03, 0xd1, 
-0x20, 0x1c, 0x00, 0xf0, 0x0b, 0xfd, 0xec, 0xe7, 0xf9, 0x6d, 0x09, 0x68, 
-0x09, 0x18, 0x09, 0x09, 0x09, 0x01, 0x7a, 0x6d, 0x8a, 0x42, 0x00, 0xd8, 
-0x89, 0x1a, 0xa1, 0x62, 0xb9, 0x68, 0x89, 0x00, 0xc9, 0x19, 0x4a, 0x6c, 
-0x00, 0x2a, 0x07, 0xd0, 0x4a, 0x6c, 0x12, 0x1a, 0x4a, 0x64, 0x80, 0x08, 
-0x80, 0x00, 0xb9, 0x6a, 0x08, 0x18, 0xb8, 0x62, 0x38, 0x68, 0xb9, 0x6a, 
-0x80, 0x00, 0xc0, 0x19, 0x42, 0x6b, 0x91, 0x42, 0x0e, 0xd3, 0x00, 0x21, 
-0x41, 0x64, 0xb8, 0x6a, 0x39, 0x68, 0x89, 0x00, 0xc9, 0x19, 0x49, 0x6b, 
-0x40, 0x1a, 0xb8, 0x62, 0xb9, 0x68, 0x89, 0x00, 0xc9, 0x19, 0xc9, 0x6b, 
-0x40, 0x18, 0xb8, 0x62, 0xb8, 0x68, 0x81, 0x00, 0xc9, 0x19, 0x49, 0x6c, 
-0x00, 0x29, 0xb8, 0xd1, 0xb9, 0x6a, 0xfa, 0x6b, 0x91, 0x42, 0xb4, 0xd0, 
-0x3a, 0x6c, 0x91, 0x42, 0xb1, 0xd0, 0x01, 0x23, 0x58, 0x40, 0xb8, 0x60, 
-0x80, 0x00, 0xc0, 0x19, 0xc0, 0x6b, 0xc0, 0x46, 0xb8, 0x62, 0xf8, 0x68, 
-0x00, 0x28, 0x01, 0xd0, 0x01, 0x38, 0xf8, 0x60, 0x38, 0x69, 0x00, 0x28, 
-0xa1, 0xd0, 0x01, 0x38, 0x38, 0x61, 0x9e, 0xe7, 0x68, 0x19, 0x00, 0x80, 
-0x00, 0x00, 0x00, 0xb0, 0xf7, 0xb5, 0x90, 0xb0, 0x04, 0x1c, 0x0d, 0x1c, 
-0x00, 0x20, 0x05, 0x90, 0x02, 0x90, 0x00, 0x22, 0x01, 0x92, 0xf9, 0x48, 
-0xc0, 0x6a, 0xc0, 0x46, 0xa8, 0x61, 0xa0, 0x68, 0x81, 0x00, 0x09, 0x19, 
-0x49, 0x6b, 0xc0, 0x46, 0x20, 0x60, 0xe1, 0x62, 0x12, 0x9a, 0xd0, 0x68, 
-0xc0, 0x46, 0xa8, 0x60, 0x12, 0x9a, 0x51, 0x78, 0xc0, 0x46, 0x0c, 0x91, 
-0xf0, 0x48, 0xc0, 0x46, 0x03, 0x90, 0xd7, 0x1d, 0x09, 0x37, 0xe0, 0x6a, 
+0x68, 0x0e, 0x00, 0x80, 0x80, 0xb5, 0x01, 0x20, 0xc0, 0x03, 0x0d, 0x49, 
+0xc0, 0x46, 0x08, 0x60, 0x0c, 0x49, 0xc8, 0x1d, 0x49, 0x30, 0x02, 0x7a, 
+0x00, 0x27, 0x00, 0x2a, 0x03, 0xd0, 0x07, 0x72, 0x08, 0x1c, 0xff, 0xf7, 
+0x37, 0xff, 0x08, 0x49, 0xc8, 0x1d, 0x49, 0x30, 0x02, 0x7a, 0x00, 0x2a, 
+0x03, 0xd0, 0x07, 0x72, 0x08, 0x1c, 0xff, 0xf7, 0x2d, 0xff, 0x80, 0xbc, 
+0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0x00, 0xb0, 0x64, 0x2d, 0x00, 0x80, 
+0xe4, 0x2c, 0x00, 0x80, 0x90, 0xb5, 0x07, 0x1c, 0x10, 0x20, 0x18, 0x49, 
+0xc0, 0x46, 0x08, 0x60, 0xf8, 0x68, 0x01, 0x30, 0xf8, 0x60, 0x16, 0x48, 
+0xc4, 0x1d, 0xb9, 0x34, 0x61, 0x6b, 0x89, 0x00, 0x09, 0x18, 0xc0, 0x31, 
+0x09, 0x69, 0x7a, 0x68, 0x92, 0x00, 0xd2, 0x19, 0x51, 0x64, 0x61, 0x6b, 
+0x89, 0x00, 0x08, 0x18, 0xc0, 0x30, 0x01, 0x69, 0x78, 0x68, 0x80, 0x00, 
+0xc0, 0x19, 0xc0, 0x6b, 0x01, 0xf0, 0xa2, 0xfa, 0x01, 0x23, 0x78, 0x68, 
+0x58, 0x40, 0x78, 0x60, 0x60, 0x6b, 0x01, 0x30, 0x80, 0x07, 0x80, 0x0f, 
+0x60, 0x63, 0xf8, 0x1d, 0x19, 0x30, 0x40, 0x79, 0x00, 0x28, 0x02, 0xd1, 
+0x38, 0x1c, 0x00, 0xf0, 0x07, 0xf8, 0x90, 0xbc, 0x08, 0xbc, 0x18, 0x47, 
+0x00, 0x00, 0x00, 0xb0, 0x68, 0x0e, 0x00, 0x80, 0x90, 0xb5, 0x07, 0x1c, 
+0x39, 0x48, 0xc0, 0x68, 0x00, 0x28, 0x05, 0xd0, 0xb8, 0x6a, 0xc0, 0x68, 
+0x80, 0x09, 0x01, 0xd3, 0x02, 0x20, 0x00, 0xe0, 0x78, 0x6f, 0xfc, 0xf7, 
+0x59, 0xf8, 0x04, 0x1c, 0x06, 0xd1, 0x01, 0x20, 0xf9, 0x1d, 0x19, 0x31, 
+0x08, 0x71, 0x90, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0xf8, 0x6c, 0x2f, 0x49, 
+0xc0, 0x46, 0x08, 0x60, 0xba, 0x6a, 0x38, 0x1c, 0x21, 0x1c, 0x00, 0xf0, 
+0x59, 0xf8, 0x67, 0x62, 0x00, 0x28, 0x03, 0xd1, 0x20, 0x1c, 0x00, 0xf0, 
+0x0b, 0xfd, 0xec, 0xe7, 0xf9, 0x6d, 0x09, 0x68, 0x09, 0x18, 0x09, 0x09, 
+0x09, 0x01, 0x7a, 0x6d, 0x8a, 0x42, 0x00, 0xd8, 0x89, 0x1a, 0xa1, 0x62, 
+0xb9, 0x68, 0x89, 0x00, 0xc9, 0x19, 0x4a, 0x6c, 0x00, 0x2a, 0x07, 0xd0, 
+0x4a, 0x6c, 0x12, 0x1a, 0x4a, 0x64, 0x80, 0x08, 0x80, 0x00, 0xb9, 0x6a, 
+0x08, 0x18, 0xb8, 0x62, 0x38, 0x68, 0xb9, 0x6a, 0x80, 0x00, 0xc0, 0x19, 
+0x42, 0x6b, 0x91, 0x42, 0x0e, 0xd3, 0x00, 0x21, 0x41, 0x64, 0xb8, 0x6a, 
+0x39, 0x68, 0x89, 0x00, 0xc9, 0x19, 0x49, 0x6b, 0x40, 0x1a, 0xb8, 0x62, 
+0xb9, 0x68, 0x89, 0x00, 0xc9, 0x19, 0xc9, 0x6b, 0x40, 0x18, 0xb8, 0x62, 
+0xb8, 0x68, 0x81, 0x00, 0xc9, 0x19, 0x49, 0x6c, 0x00, 0x29, 0xb8, 0xd1, 
+0xb9, 0x6a, 0xfa, 0x6b, 0x91, 0x42, 0xb4, 0xd0, 0x3a, 0x6c, 0x91, 0x42, 
+0xb1, 0xd0, 0x01, 0x23, 0x58, 0x40, 0xb8, 0x60, 0x80, 0x00, 0xc0, 0x19, 
+0xc0, 0x6b, 0xc0, 0x46, 0xb8, 0x62, 0xf8, 0x68, 0x00, 0x28, 0x01, 0xd0, 
+0x01, 0x38, 0xf8, 0x60, 0x38, 0x69, 0x00, 0x28, 0xa1, 0xd0, 0x01, 0x38, 
+0x38, 0x61, 0x9e, 0xe7, 0x68, 0x19, 0x00, 0x80, 0x00, 0x00, 0x00, 0xb0, 
+0xf7, 0xb5, 0x90, 0xb0, 0x04, 0x1c, 0x0d, 0x1c, 0x00, 0x20, 0x05, 0x90, 
+0x02, 0x90, 0x00, 0x22, 0x01, 0x92, 0xf9, 0x48, 0xc0, 0x6a, 0xc0, 0x46, 
+0xa8, 0x61, 0xa0, 0x68, 0x81, 0x00, 0x09, 0x19, 0x49, 0x6b, 0xc0, 0x46, 
+0x20, 0x60, 0xe1, 0x62, 0x12, 0x9a, 0xd0, 0x68, 0xc0, 0x46, 0xa8, 0x60, 
+0x12, 0x9a, 0x51, 0x78, 0xc0, 0x46, 0x0c, 0x91, 0xf0, 0x48, 0xc0, 0x46, 
+0x03, 0x90, 0xd7, 0x1d, 0x09, 0x37, 0xe0, 0x6a, 
 0xc1, 0x1b, 0x09, 0x09, 0xe3, 0x1d, 0x19, 0x33, 0x0c, 0x9a, 0xc0, 0x46, 
-0x0f, 0x93, 0xeb, 0x4b, 0xc0, 0x46, 0x0e, 0x93, 
-0x91, 0x42, 0x01, 0xd3, 0xb8, 0x42, 0x21, 0xd8, 0xe1, 0x68, 0x02, 0x29, 
-0x1e, 0xd2, 0x01, 0x20, 0x0f, 0x99, 0xc0, 0x46, 0x48, 0x71, 0x00, 0x20, 
-0x03, 0x99, 0x01, 0xf0, 0x57, 0xfb, 0x00, 0x28, 0x03, 0xd1, 0x0e, 0x9b, 
-0xd8, 0x6b, 0x01, 0x30, 0xd8, 0x63, 0x01, 0x20, 0x80, 0x06, 0x00, 0x27, 
-0x68, 0x60, 0xaf, 0x61, 0xdd, 0x4a, 0xc0, 0x46, 0x00, 0x92, 0xdd, 0x48, 
-0x01, 0x6d, 0x42, 0x6d, 0xdc, 0x4b, 0x00, 0x20, 0x01, 0xf0, 0x3a, 0xfb, 
-0x38, 0x1c, 0x5c, 0xe3, 0xb8, 0x42, 0x03, 0xd8, 0x20, 0x1c, 0x00, 0xf0, 
-0x7b, 0xfc, 0x07, 0x1c, 0xd7, 0x48, 0xc0, 0x68, 0x00, 0x28, 0x64, 0xd0, 
-0x38, 0x78, 0x40, 0x07, 0x40, 0x0f, 0x03, 0x28, 0x60, 0xd1, 0x05, 0x98, 
-0x01, 0x30, 0x00, 0x06, 0x00, 0x0e, 0x05, 0x90, 0x38, 0x78, 0xf0, 0x23, 
-0x18, 0x40, 0x58, 0xd1, 0xe0, 0x6a, 0xc0, 0x1b, 0x00, 0x09, 0x0c, 0x99, 
-0x88, 0x42, 0x02, 0xd2, 0xe0, 0x68, 0x02, 0x28, 0x05, 0xd3, 0xcb, 0x49, 
-0x88, 0x68, 0x00, 0xf0, 0x83, 0xff, 0x06, 0x1c, 0x06, 0xd1, 0x03, 0x9b, 
-0x28, 0x1c, 0x39, 0x1c, 0x22, 0x1c, 0x00, 0xf0, 0x8b, 0xfc, 0x16, 0xe1, 
-0x2e, 0x62, 0xf8, 0x68, 0x00, 0x28, 0x0d, 0xd0, 0xb8, 0x89, 0x00, 0x28, 
-0x03, 0xd0, 0xc1, 0x49, 0xc9, 0x68, 0x00, 0xf0, 0x70, 0xff, 0xf8, 0x89, 
-0x00, 0x28, 0x03, 0xd0, 0xbd, 0x49, 0xc9, 0x68, 0x00, 0xf0, 0x69, 0xff, 
-0x7a, 0x68, 0xc0, 0x46, 0x72, 0x61, 0xb9, 0x68, 0xc0, 0x46, 0xb1, 0x61, 
-0x30, 0x1c, 0xb8, 0x49, 0x09, 0x68, 0x00, 0xf0, 0x5e, 0xff, 0x00, 0x28, 
-0x17, 0xd1, 0x30, 0x1c, 0xb4, 0x49, 0x49, 0x68, 0x00, 0xf0, 0x57, 0xff, 
-0x10, 0x37, 0xe0, 0x6a, 0xb8, 0x42, 0x03, 0xd8, 0x20, 0x1c, 0x00, 0xf0, 
-0x27, 0xfc, 0x07, 0x1c, 0x68, 0x68, 0xaf, 0x4b, 0x18, 0x43, 0x68, 0x60, 
-0x00, 0x20, 0xa8, 0x61, 0xac, 0x23, 0xa8, 0x68, 0x98, 0x43, 0xa8, 0x60, 
-0xb0, 0xe0, 0xa8, 0x69, 0xa8, 0x28, 0x01, 0xd2, 0xa8, 0x20, 0xa8, 0x61, 
-0x10, 0x37, 0xe0, 0x6a, 0xb8, 0x42, 0x6c, 0xd8, 0x9c, 0xe0, 0xa5, 0xe0, 
-0xa4, 0xe0, 0x10, 0x28, 0x68, 0xd1, 0x03, 0x23, 0x1b, 0x07, 0x68, 0x68, 
-0x18, 0x40, 0x01, 0x0f, 0x48, 0x01, 0x40, 0x1a, 0x80, 0x00, 0xa0, 0x4a, 
-0x82, 0x18, 0x01, 0x92, 0x78, 0x88, 0x42, 0x0b, 0x31, 0xd3, 0x82, 0x0b, 
-0x2f, 0xd3, 0x9d, 0x48, 0xc0, 0x46, 0x03, 0x90, 0x02, 0x20, 0x01, 0x9a, 
-0xc0, 0x46, 0x10, 0x80, 0x78, 0x88, 0x00, 0x05, 0x00, 0x0d, 0x01, 0x9a, 
-0xc0, 0x46, 0x50, 0x60, 0xb8, 0x68, 0x01, 0x9a, 0xc0, 0x46, 0x90, 0x60, 
-0x78, 0x68, 0x01, 0x9a, 0xc0, 0x46, 0x10, 0x62, 0x00, 0x20, 0x01, 0x9a, 
-0xc0, 0x46, 0x90, 0x64, 0x01, 0x9a, 0xc0, 0x46, 0x90, 0x63, 0x88, 0x02, 
-0x8f, 0x49, 0x40, 0x18, 0x01, 0x9a, 0xc0, 0x46, 0x50, 0x63, 0x01, 0x9a, 
-0x50, 0x68, 0x36, 0x30, 0x94, 0x28, 0x01, 0xd8, 0x38, 0x20, 0x00, 0xe0, 
-0x94, 0x20, 0xa8, 0x61, 0x10, 0x37, 0xe0, 0x6a, 0xb8, 0x42, 0x28, 0xd8, 
-0x58, 0xe0, 0x7a, 0x88, 0x92, 0x0b, 0x03, 0xd3, 0x85, 0x48, 0xc0, 0x46, 
-0x03, 0x90, 0x23, 0xe0, 0x01, 0x22, 0x12, 0x03, 0x02, 0x40, 0x83, 0x4b, 
-0x1d, 0xd0, 0x03, 0x93, 0x00, 0x05, 0x00, 0x0d, 0x01, 0x9a, 0xc0, 0x46, 
-0x50, 0x60, 0xb8, 0x68, 0x01, 0x9a, 0xc0, 0x46, 0x90, 0x60, 0x78, 0x68, 
-0x01, 0x9a, 0xc0, 0x46, 0x10, 0x62, 0x00, 0x20, 0x01, 0x9a, 0xc0, 0x46, 
+0x0f, 0x93, 0xeb, 0x4b, 0xc0, 0x46, 0x0e, 0x93, 0x91, 0x42, 0x01, 0xd3, 
+0xb8, 0x42, 0x21, 0xd8, 0xe1, 0x68, 0x02, 0x29, 0x1e, 0xd2, 0x01, 0x20, 
+0x0f, 0x99, 0xc0, 0x46, 0x48, 0x71, 0x00, 0x20, 0x03, 0x99, 0x01, 0xf0, 
+0x57, 0xfb, 0x00, 0x28, 0x03, 0xd1, 0x0e, 0x9b, 0xd8, 0x6b, 0x01, 0x30, 
+0xd8, 0x63, 0x01, 0x20, 0x80, 0x06, 0x00, 0x27, 0x68, 0x60, 0xaf, 0x61, 
+0xdd, 0x4a, 0xc0, 0x46, 0x00, 0x92, 0xdd, 0x48, 0x01, 0x6d, 0x42, 0x6d, 
+0xdc, 0x4b, 0x00, 0x20, 0x01, 0xf0, 0x3a, 0xfb, 0x38, 0x1c, 0x5c, 0xe3, 
+0xb8, 0x42, 0x03, 0xd8, 0x20, 0x1c, 0x00, 0xf0, 0x7b, 0xfc, 0x07, 0x1c, 
+0xd7, 0x48, 0xc0, 0x68, 0x00, 0x28, 0x64, 0xd0, 0x38, 0x78, 0x40, 0x07, 
+0x40, 0x0f, 0x03, 0x28, 0x60, 0xd1, 0x05, 0x98, 0x01, 0x30, 0x00, 0x06, 
+0x00, 0x0e, 0x05, 0x90, 0x38, 0x78, 0xf0, 0x23, 0x18, 0x40, 0x58, 0xd1, 
+0xe0, 0x6a, 0xc0, 0x1b, 0x00, 0x09, 0x0c, 0x99, 0x88, 0x42, 0x02, 0xd2, 
+0xe0, 0x68, 0x02, 0x28, 0x05, 0xd3, 0xcb, 0x49, 0x88, 0x68, 0x00, 0xf0, 
+0x83, 0xff, 0x06, 0x1c, 0x06, 0xd1, 0x03, 0x9b, 0x28, 0x1c, 0x39, 0x1c, 
+0x22, 0x1c, 0x00, 0xf0, 0x8b, 0xfc, 0x16, 0xe1, 0x2e, 0x62, 0xf8, 0x68, 
+0x00, 0x28, 0x0d, 0xd0, 0xb8, 0x89, 0x00, 0x28, 0x03, 0xd0, 0xc1, 0x49, 
+0xc9, 0x68, 0x00, 0xf0, 0x70, 0xff, 0xf8, 0x89, 0x00, 0x28, 0x03, 0xd0, 
+0xbd, 0x49, 0xc9, 0x68, 0x00, 0xf0, 0x69, 0xff, 0x7a, 0x68, 0xc0, 0x46, 
+0x72, 0x61, 0xb9, 0x68, 0xc0, 0x46, 0xb1, 0x61, 0x30, 0x1c, 0xb8, 0x49, 
+0x09, 0x68, 0x00, 0xf0, 0x5e, 0xff, 0x00, 0x28, 0x17, 0xd1, 0x30, 0x1c, 
+0xb4, 0x49, 0x49, 0x68, 0x00, 0xf0, 0x57, 0xff, 0x10, 0x37, 0xe0, 0x6a, 
+0xb8, 0x42, 0x03, 0xd8, 0x20, 0x1c, 0x00, 0xf0, 0x27, 0xfc, 0x07, 0x1c, 
+0x68, 0x68, 0xaf, 0x4b, 0x18, 0x43, 0x68, 0x60, 0x00, 0x20, 0xa8, 0x61, 
+0xac, 0x23, 0xa8, 0x68, 0x98, 0x43, 0xa8, 0x60, 0xb0, 0xe0, 0xa8, 0x69, 
+0xa8, 0x28, 0x01, 0xd2, 0xa8, 0x20, 0xa8, 0x61, 0x10, 0x37, 0xe0, 0x6a, 
+0xb8, 0x42, 0x6c, 0xd8, 0x9c, 0xe0, 0xa5, 0xe0, 0xa4, 0xe0, 0x10, 0x28, 
+0x68, 0xd1, 0x03, 0x23, 0x1b, 0x07, 0x68, 0x68, 0x18, 0x40, 0x01, 0x0f, 
+0x48, 0x01, 0x40, 0x1a, 0x80, 0x00, 0xa0, 0x4a, 0x82, 0x18, 0x01, 0x92, 
+0x78, 0x88, 0x42, 0x0b, 0x31, 0xd3, 0x82, 0x0b, 0x2f, 0xd3, 0x9d, 0x48, 
+0xc0, 0x46, 0x03, 0x90, 0x02, 0x20, 0x01, 0x9a, 0xc0, 0x46, 0x10, 0x80, 
+0x78, 0x88, 0x00, 0x05, 0x00, 0x0d, 0x01, 0x9a, 0xc0, 0x46, 0x50, 0x60, 
+0xb8, 0x68, 0x01, 0x9a, 0xc0, 0x46, 0x90, 0x60, 0x78, 0x68, 0x01, 0x9a, 
+0xc0, 0x46, 0x10, 0x62, 0x00, 0x20, 0x01, 0x9a, 0xc0, 0x46, 0x90, 0x64, 
+0x01, 0x9a, 0xc0, 0x46, 0x90, 0x63, 0x88, 0x02, 0x8f, 0x49, 0x40, 0x18, 
+0x01, 0x9a, 0xc0, 0x46, 0x50, 0x63, 0x01, 0x9a, 0x50, 0x68, 0x36, 0x30, 
+0x94, 0x28, 0x01, 0xd8, 0x38, 0x20, 0x00, 0xe0, 0x94, 0x20, 0xa8, 0x61, 
+0x10, 0x37, 0xe0, 0x6a, 0xb8, 0x42, 0x28, 0xd8, 0x58, 0xe0, 0x7a, 0x88, 
+0x92, 0x0b, 0x03, 0xd3, 0x85, 0x48, 0xc0, 0x46, 0x03, 0x90, 0x23, 0xe0, 
+0x01, 0x22, 0x12, 0x03, 0x02, 0x40, 0x83, 0x4b, 0x1d, 0xd0, 0x03, 0x93, 
+0x00, 0x05, 0x00, 0x0d, 0x01, 0x9a, 0xc0, 0x46, 0x50, 0x60, 0xb8, 0x68, 
+0x01, 0x9a, 0xc0, 0x46, 0x90, 0x60, 0x78, 0x68, 0x01, 0x9a, 0xc0, 0x46, 
+0x10, 0x62, 0x00, 0x20, 0x01, 0x9a, 0xc0, 0x46, 
 0x90, 0x64, 0x01, 0x9a, 0xc0, 0x46, 0x90, 0x63, 0x88, 0x02, 0x75, 0x49, 
-0x40, 0x18, 0x01, 0x9a, 0xc0, 0x46, 0x50, 0x63, 
-0x02, 0xe0, 0x33, 0xe0, 0x2a, 0xe0, 0x03, 0x93, 0x01, 0x20, 0x0f, 0x99, 
-0xc0, 0x46, 0x48, 0x71, 0x12, 0x9a, 0x50, 0x78, 0x05, 0x99, 0x43, 0x1a, 
-0x0b, 0x93, 0x10, 0x37, 0xe0, 0x6a, 0xb8, 0x42, 0x03, 0xd8, 0x20, 0x1c, 
-0x00, 0xf0, 0x92, 0xfb, 0x07, 0x1c, 0x01, 0x9a, 0x50, 0x6b, 0x91, 0x6b, 
-0x09, 0x01, 0x40, 0x18, 0x0b, 0x9b, 0x21, 0x1c, 0x3a, 0x1c, 0xff, 0xf7, 
-0x7d, 0xfb, 0x01, 0x9a, 0xc0, 0x46, 0xd0, 0x64, 0x01, 0x9a, 0x0b, 0x9b, 
-0xc0, 0x46, 0x13, 0x65, 0x01, 0x23, 0x5b, 0x06, 0x68, 0x68, 0x18, 0x43, 
-0x68, 0x60, 0x00, 0x20, 0xa8, 0x61, 0x0d, 0xe0, 0x10, 0x37, 0xe0, 0x6a, 
-0xb8, 0x42, 0x03, 0xd8, 0x20, 0x1c, 0x00, 0xf0, 0x71, 0xfb, 0x07, 0x1c, 
-0x38, 0x78, 0x40, 0x07, 0x40, 0x0f, 0x03, 0x28, 0x00, 0xd1, 0xf8, 0xe6, 
-0xa8, 0x69, 0x03, 0x99, 0x01, 0xf0, 0x26, 0xfa, 0x00, 0x28, 0x2a, 0xd1, 
-0x38, 0x1c, 0x21, 0x1c, 0x00, 0xf0, 0x79, 0xfb, 0xa8, 0x68, 0x80, 0x09, 
-0x04, 0xd3, 0x30, 0x1c, 0x49, 0x49, 0x49, 0x68, 0x00, 0xf0, 0x81, 0xfe, 
-0x41, 0x49, 0x00, 0x20, 0x01, 0xf0, 0x14, 0xfa, 0x00, 0x28, 0x04, 0xd1, 
-0x0e, 0x9b, 0xd8, 0x6b, 0x01, 0x30, 0xd8, 0x63, 0x11, 0xe0, 0x01, 0x20, 
-0x0f, 0x99, 0xc0, 0x46, 0x48, 0x71, 0x80, 0x06, 0x00, 0x27, 0x68, 0x60, 
-0xaf, 0x61, 0x3a, 0x4a, 0xc0, 0x46, 0x00, 0x92, 0x39, 0x48, 0x01, 0x6d, 
-0x42, 0x6d, 0x39, 0x4b, 0x00, 0x20, 0x01, 0xf0, 0xf3, 0xf9, 0x00, 0x20, 
-0x15, 0xe2, 0x05, 0x98, 0x0c, 0x99, 0x08, 0x1a, 0x00, 0x04, 0x00, 0x0c, 
-0x0c, 0x90, 0x0b, 0x90, 0x0c, 0x98, 0x00, 0x28, 0x03, 0xd0, 0x01, 0x20, 
-0x0f, 0x99, 0xc0, 0x46, 0x48, 0x71, 0x28, 0x68, 0xc0, 0x46, 0x04, 0x90, 
-0x00, 0x26, 0x00, 0x20, 0x08, 0x90, 0x00, 0x22, 0x0a, 0x92, 0x0c, 0x98, 
-0x01, 0x38, 0x0d, 0x90, 0xa3, 0xe0, 0x78, 0x88, 0x8a, 0x1b, 0x12, 0x04, 
-0x12, 0x0c, 0x90, 0x42, 0x05, 0xdd, 0x07, 0x92, 0x80, 0x1a, 0x00, 0x04, 
-0x00, 0x0c, 0x08, 0x90, 0x00, 0xe0, 0x07, 0x90, 0x08, 0x98, 0x00, 0x28, 
-0x07, 0xd1, 0x0d, 0x98, 0x0a, 0x9a, 0x90, 0x42, 0x07, 0xdd, 0x07, 0x98, 
-0x30, 0x18, 0x88, 0x42, 0x03, 0xd8, 0x01, 0x20, 0x40, 0x05, 0x06, 0x90, 
-0x1c, 0xe0, 0x11, 0x20, 0x40, 0x05, 0x06, 0x90, 0xa8, 0x68, 0x8c, 0x23, 
-0x18, 0x40, 0x02, 0xd1, 0x20, 0x48, 0xc0, 0x46, 0x06, 0x90, 0xb1, 0x07, 
-0x89, 0x0f, 0x0f, 0xd0, 0x07, 0x98, 0xc0, 0x06, 0xc0, 0x0e, 0x08, 0xd0, 
-0x1e, 0x28, 0x09, 0xdb, 0x1e, 0x28, 0x02, 0xd1, 0x03, 0x29, 0x05, 0xd1, 
-0x01, 0xe0, 0x02, 0x29, 0x02, 0xd3, 0x01, 0x20, 0x02, 0x90, 0xde, 0xe7, 
-0x0a, 0x9a, 0x00, 0x2a, 0x04, 0xd1, 0x01, 0x23, 0xdb, 0x05, 0x06, 0x98, 
-0x18, 0x43, 0x06, 0x90, 0x07, 0x98, 0x06, 0x99, 0x08, 0x43, 0x02, 0x1c, 
-0x00, 0x90, 0x04, 0x98, 0x83, 0x19, 0x1d, 0xe0, 0xe8, 0x0e, 0x00, 0x80, 
-0xed, 0x48, 0xff, 0xff, 0x28, 0x0f, 0x00, 0x80, 0x04, 0x00, 0x12, 0x02, 
-0x7c, 0x29, 0x00, 0x80, 0x44, 0x80, 0x20, 0x40, 0x68, 0x19, 0x00, 0x80, 
-0x60, 0x04, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x5c, 0x2b, 0x00, 0x80, 
-0x41, 0x32, 0xff, 0xff, 0x58, 0x5f, 0x21, 0x40, 0xf9, 0x3c, 0xff, 0xff, 
-0xb9, 0x31, 0xff, 0xff, 0x00, 0x00, 0x32, 0x02, 0x00, 0x20, 0x3a, 0x1d, 
-0x06, 0xca, 0x01, 0xf0, 0x6b, 0xf9, 0x07, 0x98, 0x36, 0x18, 0x02, 0x98, 
+0x40, 0x18, 0x01, 0x9a, 0xc0, 0x46, 0x50, 0x63, 0x02, 0xe0, 0x33, 0xe0, 
+0x2a, 0xe0, 0x03, 0x93, 0x01, 0x20, 0x0f, 0x99, 0xc0, 0x46, 0x48, 0x71, 
+0x12, 0x9a, 0x50, 0x78, 0x05, 0x99, 0x43, 0x1a, 0x0b, 0x93, 0x10, 0x37, 
+0xe0, 0x6a, 0xb8, 0x42, 0x03, 0xd8, 0x20, 0x1c, 0x00, 0xf0, 0x92, 0xfb, 
+0x07, 0x1c, 0x01, 0x9a, 0x50, 0x6b, 0x91, 0x6b, 0x09, 0x01, 0x40, 0x18, 
+0x0b, 0x9b, 0x21, 0x1c, 0x3a, 0x1c, 0xff, 0xf7, 0x7d, 0xfb, 0x01, 0x9a, 
+0xc0, 0x46, 0xd0, 0x64, 0x01, 0x9a, 0x0b, 0x9b, 0xc0, 0x46, 0x13, 0x65, 
+0x01, 0x23, 0x5b, 0x06, 0x68, 0x68, 0x18, 0x43, 0x68, 0x60, 0x00, 0x20, 
+0xa8, 0x61, 0x0d, 0xe0, 0x10, 0x37, 0xe0, 0x6a, 0xb8, 0x42, 0x03, 0xd8, 
+0x20, 0x1c, 0x00, 0xf0, 0x71, 0xfb, 0x07, 0x1c, 0x38, 0x78, 0x40, 0x07, 
+0x40, 0x0f, 0x03, 0x28, 0x00, 0xd1, 0xf8, 0xe6, 0xa8, 0x69, 0x03, 0x99, 
+0x01, 0xf0, 0x26, 0xfa, 0x00, 0x28, 0x2a, 0xd1, 0x38, 0x1c, 0x21, 0x1c, 
+0x00, 0xf0, 0x79, 0xfb, 0xa8, 0x68, 0x80, 0x09, 0x04, 0xd3, 0x30, 0x1c, 
+0x49, 0x49, 0x49, 0x68, 0x00, 0xf0, 0x81, 0xfe, 0x41, 0x49, 0x00, 0x20, 
+0x01, 0xf0, 0x14, 0xfa, 0x00, 0x28, 0x04, 0xd1, 0x0e, 0x9b, 0xd8, 0x6b, 
+0x01, 0x30, 0xd8, 0x63, 0x11, 0xe0, 0x01, 0x20, 0x0f, 0x99, 0xc0, 0x46, 
+0x48, 0x71, 0x80, 0x06, 0x00, 0x27, 0x68, 0x60, 0xaf, 0x61, 0x3a, 0x4a, 
+0xc0, 0x46, 0x00, 0x92, 0x39, 0x48, 0x01, 0x6d, 0x42, 0x6d, 0x39, 0x4b, 
+0x00, 0x20, 0x01, 0xf0, 0xf3, 0xf9, 0x00, 0x20, 0x15, 0xe2, 0x05, 0x98, 
+0x0c, 0x99, 0x08, 0x1a, 0x00, 0x04, 0x00, 0x0c, 0x0c, 0x90, 0x0b, 0x90, 
+0x0c, 0x98, 0x00, 0x28, 0x03, 0xd0, 0x01, 0x20, 0x0f, 0x99, 0xc0, 0x46, 
+0x48, 0x71, 0x28, 0x68, 0xc0, 0x46, 0x04, 0x90, 0x00, 0x26, 0x00, 0x20, 
+0x08, 0x90, 0x00, 0x22, 0x0a, 0x92, 0x0c, 0x98, 0x01, 0x38, 0x0d, 0x90, 
+0xa3, 0xe0, 0x78, 0x88, 0x8a, 0x1b, 0x12, 0x04, 0x12, 0x0c, 0x90, 0x42, 
+0x05, 0xdd, 0x07, 0x92, 0x80, 0x1a, 0x00, 0x04, 0x00, 0x0c, 0x08, 0x90, 
+0x00, 0xe0, 0x07, 0x90, 0x08, 0x98, 0x00, 0x28, 0x07, 0xd1, 0x0d, 0x98, 
+0x0a, 0x9a, 0x90, 0x42, 0x07, 0xdd, 0x07, 0x98, 0x30, 0x18, 0x88, 0x42, 
+0x03, 0xd8, 0x01, 0x20, 0x40, 0x05, 0x06, 0x90, 0x1c, 0xe0, 0x11, 0x20, 
+0x40, 0x05, 0x06, 0x90, 0xa8, 0x68, 0x8c, 0x23, 0x18, 0x40, 0x02, 0xd1, 
+0x20, 0x48, 0xc0, 0x46, 0x06, 0x90, 0xb1, 0x07, 0x89, 0x0f, 0x0f, 0xd0, 
+0x07, 0x98, 0xc0, 0x06, 0xc0, 0x0e, 0x08, 0xd0, 0x1e, 0x28, 0x09, 0xdb, 
+0x1e, 0x28, 0x02, 0xd1, 0x03, 0x29, 0x05, 0xd1, 0x01, 0xe0, 0x02, 0x29, 
+0x02, 0xd3, 0x01, 0x20, 0x02, 0x90, 0xde, 0xe7, 0x0a, 0x9a, 0x00, 0x2a, 
+0x04, 0xd1, 0x01, 0x23, 0xdb, 0x05, 0x06, 0x98, 0x18, 0x43, 0x06, 0x90, 
+0x07, 0x98, 0x06, 0x99, 0x08, 0x43, 0x02, 0x1c, 0x00, 0x90, 0x04, 0x98, 
+0x83, 0x19, 0x1d, 0xe0, 0xe8, 0x0e, 0x00, 0x80, 0x01, 0x49, 0xff, 0xff, 
+0x28, 0x0f, 0x00, 0x80, 0x04, 0x00, 0x12, 0x02, 0x7c, 0x29, 0x00, 0x80, 
+0x44, 0x80, 0x20, 0x40, 0x68, 0x19, 0x00, 0x80, 0x60, 0x04, 0x00, 0x80, 
+0x00, 0x00, 0x00, 0x80, 0x5c, 0x2b, 0x00, 0x80, 0x55, 0x32, 0xff, 0xff, 
+0xac, 0x5e, 0x21, 0x40, 0x0d, 0x3d, 0xff, 0xff, 0xcd, 0x31, 0xff, 0xff, 
+0x00, 0x00, 0x32, 0x02, 0x00, 0x20, 0x3a, 0x1d, 0x06, 0xca, 0x01, 0xf0, 
+0x6b, 0xf9, 0x07, 0x98, 0x36, 0x18, 0x02, 0x98, 
 0x00, 0x28, 0x16, 0xd0, 0xa8, 0x68, 0x8c, 0x23, 0x18, 0x40, 0x04, 0xd1, 
-0x09, 0x23, 0x5b, 0x04, 0x06, 0x98, 0x18, 0x43, 
-0x06, 0x90, 0x06, 0x98, 0xc2, 0x4a, 0x02, 0x43, 0x00, 0x92, 0x04, 0x98, 
-0x83, 0x19, 0xc1, 0x48, 0x01, 0x6d, 0x42, 0x6d, 0x00, 0x20, 0x01, 0xf0, 
-0x51, 0xf9, 0x00, 0x20, 0x02, 0x90, 0x08, 0x98, 0x00, 0x28, 0x0b, 0xd1, 
-0x0b, 0x9b, 0x01, 0x3b, 0x0b, 0x93, 0x10, 0x37, 0xe0, 0x6a, 0xb8, 0x42, 
-0x0c, 0xd8, 0x20, 0x1c, 0x00, 0xf0, 0x8a, 0xfa, 0x07, 0x1c, 0x07, 0xe0, 
-0x78, 0x68, 0x07, 0x9a, 0x80, 0x18, 0x78, 0x60, 0x78, 0x88, 0x07, 0x9a, 
-0x80, 0x1a, 0x78, 0x80, 0x0a, 0x9a, 0x50, 0x1c, 0x02, 0x04, 0x12, 0x0c, 
-0x0a, 0x92, 0x0c, 0x98, 0x0a, 0x9a, 0x82, 0x42, 0x03, 0xda, 0xa9, 0x69, 
-0xb1, 0x42, 0x00, 0xd9, 0x53, 0xe7, 0xa8, 0x69, 0xb0, 0x42, 0x6b, 0xd1, 
-0xa8, 0x68, 0x01, 0x09, 0x69, 0xd2, 0x08, 0x9a, 0x00, 0x2a, 0x56, 0xd0, 
-0x0c, 0x99, 0x0a, 0x9a, 0x8a, 0x42, 0x3e, 0xdb, 0xb1, 0x07, 0x89, 0x0f, 
-0x0c, 0xd0, 0x08, 0x9a, 0xd2, 0x06, 0xd2, 0x0e, 0x0b, 0xd0, 0x1e, 0x2a, 
-0x06, 0xdb, 0x1e, 0x2a, 0x02, 0xd1, 0x03, 0x29, 0x05, 0xd0, 0x01, 0xe0, 
-0x02, 0x29, 0x02, 0xd2, 0x02, 0x99, 0x00, 0x29, 0x21, 0xd0, 0x08, 0x9a, 
+0x09, 0x23, 0x5b, 0x04, 0x06, 0x98, 0x18, 0x43, 0x06, 0x90, 0x06, 0x98, 
+0xc2, 0x4a, 0x02, 0x43, 0x00, 0x92, 0x04, 0x98, 0x83, 0x19, 0xc1, 0x48, 
+0x01, 0x6d, 0x42, 0x6d, 0x00, 0x20, 0x01, 0xf0, 0x51, 0xf9, 0x00, 0x20, 
+0x02, 0x90, 0x08, 0x98, 0x00, 0x28, 0x0b, 0xd1, 0x0b, 0x9b, 0x01, 0x3b, 
+0x0b, 0x93, 0x10, 0x37, 0xe0, 0x6a, 0xb8, 0x42, 0x0c, 0xd8, 0x20, 0x1c, 
+0x00, 0xf0, 0x8a, 0xfa, 0x07, 0x1c, 0x07, 0xe0, 0x78, 0x68, 0x07, 0x9a, 
+0x80, 0x18, 0x78, 0x60, 0x78, 0x88, 0x07, 0x9a, 0x80, 0x1a, 0x78, 0x80, 
+0x0a, 0x9a, 0x50, 0x1c, 0x02, 0x04, 0x12, 0x0c, 0x0a, 0x92, 0x0c, 0x98, 
+0x0a, 0x9a, 0x82, 0x42, 0x03, 0xda, 0xa9, 0x69, 0xb1, 0x42, 0x00, 0xd9, 
+0x53, 0xe7, 0xa8, 0x69, 0xb0, 0x42, 0x6b, 0xd1, 0xa8, 0x68, 0x01, 0x09, 
+0x69, 0xd2, 0x08, 0x9a, 0x00, 0x2a, 0x56, 0xd0, 0x0c, 0x99, 0x0a, 0x9a, 
+0x8a, 0x42, 0x3e, 0xdb, 0xb1, 0x07, 0x89, 0x0f, 0x0c, 0xd0, 0x08, 0x9a, 
+0xd2, 0x06, 0xd2, 0x0e, 0x0b, 0xd0, 0x1e, 0x2a, 0x06, 0xdb, 0x1e, 0x2a, 
+0x02, 0xd1, 0x03, 0x29, 0x05, 0xd0, 0x01, 0xe0, 0x02, 0x29, 0x02, 0xd2, 
+0x02, 0x99, 0x00, 0x29, 0x21, 0xd0, 0x08, 0x9a, 0xc0, 0x46, 0x00, 0x92, 
+0x04, 0x98, 0x83, 0x19, 0x00, 0x20, 0x3a, 0x1d, 0x06, 0xca, 0x01, 0xf0, 
+0x01, 0xf9, 0x08, 0x98, 0x36, 0x18, 0xa8, 0x68, 0x8c, 0x23, 0x18, 0x40, 
+0x02, 0xd0, 0x01, 0x20, 0x40, 0x06, 0x00, 0xe0, 0x92, 0x48, 0x01, 0x22, 
+0x02, 0x43, 0x00, 0x92, 0x04, 0x98, 0x83, 0x19, 0x8e, 0x48, 0x01, 0x6d, 
+0x42, 0x6d, 0x00, 0x20, 0x01, 0xf0, 0xec, 0xf8, 0x00, 0x20, 0x02, 0x90, 
+0x15, 0xe0, 0x8c, 0x23, 0x18, 0x40, 0x02, 0xd0, 0x01, 0x20, 0x40, 0x06, 
+0x00, 0xe0, 0x88, 0x48, 0x08, 0x9a, 0x02, 0x43, 0x00, 0xe0, 0x08, 0x9a, 
 0xc0, 0x46, 0x00, 0x92, 0x04, 0x98, 0x83, 0x19, 0x00, 0x20, 0x3a, 0x1d, 
-0x06, 0xca, 0x01, 0xf0, 0x01, 0xf9, 0x08, 0x98, 0x36, 0x18, 0xa8, 0x68, 
-0x8c, 0x23, 0x18, 0x40, 0x02, 0xd0, 0x01, 0x20, 0x40, 0x06, 0x00, 0xe0, 
-0x92, 0x48, 0x01, 0x22, 0x02, 0x43, 0x00, 0x92, 0x04, 0x98, 0x83, 0x19, 
-0x8e, 0x48, 0x01, 0x6d, 0x42, 0x6d, 0x00, 0x20, 0x01, 0xf0, 0xec, 0xf8, 
-0x00, 0x20, 0x02, 0x90, 0x15, 0xe0, 0x8c, 0x23, 0x18, 0x40, 0x02, 0xd0, 
-0x01, 0x20, 0x40, 0x06, 0x00, 0xe0, 0x88, 0x48, 0x08, 0x9a, 0x02, 0x43, 
-0x00, 0xe0, 0x08, 0x9a, 0xc0, 0x46, 0x00, 0x92, 0x04, 0x98, 0x83, 0x19, 
-0x00, 0x20, 0x3a, 0x1d, 0x06, 0xca, 0x01, 0xf0, 0xd5, 0xf8, 0x08, 0x98, 
-0x36, 0x18, 0x10, 0x37, 0xe0, 0x6a, 0xb8, 0x42, 0x03, 0xd8, 0x20, 0x1c, 
-0x00, 0xf0, 0x14, 0xfa, 0x07, 0x1c, 0x68, 0x68, 0x80, 0x0e, 0x6b, 0xd2, 
-0x0a, 0x98, 0xc0, 0x46, 0x09, 0x90, 0x0c, 0x99, 0x88, 0x42, 0x5c, 0xda, 
-0x0d, 0x98, 0x09, 0x99, 0x88, 0x42, 0x03, 0xd0, 0x7a, 0x88, 0x1e, 0xe0, 
-0x5f, 0xe0, 0x5e, 0xe0, 0x78, 0x88, 0x01, 0x22, 0x52, 0x06, 0x02, 0x43, 
-0xa9, 0x68, 0x8c, 0x23, 0x19, 0x40, 0x02, 0xd1, 0x09, 0x23, 0x5b, 0x04, 
-0x1a, 0x43, 0xb1, 0x07, 0x89, 0x0f, 0x0e, 0xd0, 0xc3, 0x06, 0xdb, 0x0e, 
-0x08, 0xd0, 0x1e, 0x2b, 0x09, 0xdb, 0x1e, 0x2b, 0x02, 0xd1, 0x03, 0x29, 
-0x05, 0xd1, 0x01, 0xe0, 0x02, 0x29, 0x02, 0xd3, 0x01, 0x21, 0x02, 0x91, 
-0x02, 0x1c, 0x09, 0x98, 0x00, 0x28, 0x02, 0xd1, 0x01, 0x23, 0xdb, 0x05, 
-0x1a, 0x43, 0x00, 0x92, 0x04, 0x98, 0x83, 0x19, 0x00, 0x20, 0x3a, 0x1d, 
-0x06, 0xca, 0x01, 0xf0, 0x8f, 0xf8, 0x78, 0x88, 0x86, 0x19, 0x10, 0x37, 
-0x02, 0x98, 0x00, 0x28, 0x14, 0xd0, 0xa8, 0x68, 0x8c, 0x23, 0x18, 0x40, 
-0x02, 0xd0, 0x01, 0x20, 0x40, 0x06, 0x00, 0xe0, 0x57, 0x48, 0x01, 0x22, 
-0x02, 0x43, 0x00, 0x92, 0x04, 0x98, 0x83, 0x19, 0x53, 0x48, 0x01, 0x6d, 
-0x42, 0x6d, 0x00, 0x20, 0x01, 0xf0, 0x76, 0xf8, 0x00, 0x20, 0x02, 0x90, 
-0xe0, 0x6a, 0xb8, 0x42, 0x03, 0xd8, 0x20, 0x1c, 0x00, 0xf0, 0xb6, 0xf9, 
-0x07, 0x1c, 0x09, 0x98, 0x01, 0x30, 0x00, 0x04, 0x00, 0x0c, 0x09, 0x90, 
+0x06, 0xca, 0x01, 0xf0, 0xd5, 0xf8, 0x08, 0x98, 0x36, 0x18, 0x10, 0x37, 
+0xe0, 0x6a, 0xb8, 0x42, 0x03, 0xd8, 0x20, 0x1c, 0x00, 0xf0, 0x14, 0xfa, 
+0x07, 0x1c, 0x68, 0x68, 0x80, 0x0e, 0x6b, 0xd2, 0x0a, 0x98, 0xc0, 0x46, 
+0x09, 0x90, 0x0c, 0x99, 0x88, 0x42, 0x5c, 0xda, 0x0d, 0x98, 0x09, 0x99, 
+0x88, 0x42, 0x03, 0xd0, 0x7a, 0x88, 0x1e, 0xe0, 0x5f, 0xe0, 0x5e, 0xe0, 
+0x78, 0x88, 0x01, 0x22, 0x52, 0x06, 0x02, 0x43, 0xa9, 0x68, 0x8c, 0x23, 
+0x19, 0x40, 0x02, 0xd1, 0x09, 0x23, 0x5b, 0x04, 0x1a, 0x43, 0xb1, 0x07, 
+0x89, 0x0f, 0x0e, 0xd0, 0xc3, 0x06, 0xdb, 0x0e, 0x08, 0xd0, 0x1e, 0x2b, 
+0x09, 0xdb, 0x1e, 0x2b, 0x02, 0xd1, 0x03, 0x29, 0x05, 0xd1, 0x01, 0xe0, 
+0x02, 0x29, 0x02, 0xd3, 0x01, 0x21, 0x02, 0x91, 0x02, 0x1c, 0x09, 0x98, 
+0x00, 0x28, 0x02, 0xd1, 0x01, 0x23, 0xdb, 0x05, 0x1a, 0x43, 0x00, 0x92, 
+0x04, 0x98, 0x83, 0x19, 0x00, 0x20, 0x3a, 0x1d, 0x06, 0xca, 0x01, 0xf0, 
+0x8f, 0xf8, 0x78, 0x88, 0x86, 0x19, 0x10, 0x37, 0x02, 0x98, 0x00, 0x28, 
+0x14, 0xd0, 0xa8, 0x68, 0x8c, 0x23, 0x18, 0x40, 0x02, 0xd0, 0x01, 0x20, 
+0x40, 0x06, 0x00, 0xe0, 0x57, 0x48, 0x01, 0x22, 0x02, 0x43, 0x00, 0x92, 
+0x04, 0x98, 0x83, 0x19, 0x53, 0x48, 0x01, 0x6d, 0x42, 0x6d, 0x00, 0x20, 
+0x01, 0xf0, 0x76, 0xf8, 0x00, 0x20, 0x02, 0x90, 0xe0, 0x6a, 0xb8, 0x42, 
+0x03, 0xd8, 0x20, 0x1c, 0x00, 0xf0, 0xb6, 0xf9, 0x07, 0x1c, 0x09, 0x98, 
+0x01, 0x30, 0x00, 0x04, 0x00, 0x0c, 0x09, 0x90, 
 0x0c, 0x99, 0x88, 0x42, 0xa2, 0xdb, 0x68, 0x68, 0x30, 0x43, 0x01, 0x04, 
-0x09, 0x0c, 0x68, 0x60, 0xe8, 0x6a, 0x00, 0xf0, 
-0x7b, 0xfa, 0x28, 0xe0, 0x27, 0xe0, 0xa8, 0x68, 0x00, 0x09, 0x14, 0xd3, 
-0x68, 0x68, 0x80, 0x0e, 0x15, 0xd2, 0x01, 0x9a, 0x00, 0x2a, 0x12, 0xd0, 
-0x01, 0x9a, 0x50, 0x6b, 0x0b, 0x9b, 0x21, 0x1c, 0x3a, 0x1c, 0xff, 0xf7, 
-0x89, 0xf9, 0x01, 0x9a, 0xc0, 0x46, 0x90, 0x64, 0x01, 0x9a, 0x0b, 0x9b, 
-0xc0, 0x46, 0x93, 0x63, 0x03, 0xe0, 0xe8, 0x6a, 0x31, 0x1c, 0x00, 0xf0, 
-0x5d, 0xfa, 0x68, 0x68, 0x30, 0x43, 0x68, 0x60, 0xa8, 0x69, 0xb0, 0x42, 
-0x05, 0xd9, 0x00, 0x04, 0x00, 0x0c, 0x80, 0x1b, 0x00, 0xf0, 0xee, 0xf9, 
-0xae, 0x61, 0xa8, 0x68, 0x8c, 0x23, 0x18, 0x40, 0x0b, 0xd0, 0x2f, 0x4a, 
-0xc0, 0x46, 0x00, 0x92, 0x04, 0x98, 0xc3, 0x1f, 0x05, 0x3b, 0x2a, 0x48, 
-0x01, 0x6d, 0x42, 0x6d, 0x00, 0x20, 0x01, 0xf0, 0x23, 0xf8, 0x01, 0x23, 
-0x9b, 0x07, 0x20, 0x6d, 0x18, 0x43, 0x00, 0x68, 0xc0, 0x46, 0xa0, 0x61, 
-0xe1, 0x69, 0x81, 0x42, 0x12, 0xd0, 0x22, 0x69, 0x02, 0x2a, 0x0f, 0xd2, 
-0x41, 0x1a, 0x01, 0xd5, 0x60, 0x6d, 0x41, 0x18, 0x20, 0x1c, 0xff, 0xf7, 
-0x3f, 0xfb, 0xe1, 0x69, 0x40, 0x18, 0xe0, 0x61, 0x61, 0x6d, 0x88, 0x42, 
-0x24, 0xd3, 0x40, 0x1a, 0xe0, 0x61, 0x21, 0xe0, 0x81, 0x42, 0x1f, 0xd1, 
-0x20, 0x69, 0x02, 0x28, 0x1c, 0xd2, 0x01, 0x20, 0x60, 0x61, 0x18, 0x48, 
-0x41, 0x69, 0xe2, 0x6c, 0x0a, 0x43, 0x42, 0x61, 0x81, 0x69, 0xe3, 0x6c, 
-0x99, 0x43, 0x81, 0x61, 0x01, 0x21, 0x09, 0x05, 0xca, 0x60, 0x80, 0x69, 
-0xc0, 0x46, 0x08, 0x61, 0x8b, 0x02, 0x20, 0x6d, 0x18, 0x43, 0x00, 0x68, 
-0xc0, 0x46, 0xa0, 0x61, 0xe1, 0x69, 0x81, 0x42, 0x02, 0xd0, 0x20, 0x1c, 
-0xff, 0xf7, 0xcc, 0xfa, 0x28, 0x1c, 0x00, 0xf0, 0x0f, 0xf9, 0x0c, 0x98, 
-0x05, 0x99, 0x40, 0x18, 0x00, 0x01, 0x10, 0x30, 0x68, 0x61, 0x13, 0xb0, 
-0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 
-0x7c, 0x29, 0x00, 0x80, 0x00, 0x00, 0x12, 0x02, 0x04, 0x00, 0x52, 0x02, 
-0x68, 0x0e, 0x00, 0x80, 0xf0, 0xb5, 0x40, 0x20, 0x2d, 0x49, 0xc0, 0x46, 
-0x08, 0x60, 0x00, 0xf0, 0x03, 0xf9, 0x07, 0x1c, 0x81, 0x69, 0x44, 0x6a, 
-0xa0, 0x6f, 0x00, 0xf0, 0x45, 0xfe, 0x00, 0x20, 0xe1, 0x1d, 0x19, 0x31, 
-0x48, 0x71, 0x79, 0x68, 0xc9, 0x0e, 0x09, 0xd3, 0xf8, 0x6a, 0x00, 0x01, 
-0x24, 0x49, 0x40, 0x18, 0x24, 0x4b, 0xc0, 0x18, 0x01, 0x68, 0x01, 0x39, 
-0x01, 0x60, 0x36, 0xe0, 0xe1, 0x6d, 0x09, 0x68, 0x22, 0x6e, 0xc0, 0x46, 
-0x11, 0x60, 0x20, 0x4e, 0xf5, 0x1d, 0x79, 0x35, 0x01, 0x23, 0xe9, 0x6b, 
-0x19, 0x43, 0xe9, 0x63, 0xb9, 0x6a, 0xe2, 0x6d, 0xc0, 0x46, 0x11, 0x60, 
-0xb9, 0x6a, 0x22, 0x6e, 0xc0, 0x46, 0x11, 0x60, 0x61, 0x69, 0x00, 0x29, 
-0x04, 0xd1, 0xa9, 0x6b, 0x01, 0x31, 0xa9, 0x63, 0x08, 0x29, 0x07, 0xd3, 
-0xa8, 0x63, 0x01, 0x20, 0x00, 0xf0, 0x86, 0xf8, 0xe8, 0x6b, 0x40, 0x08, 
-0x40, 0x00, 0xe8, 0x63, 0x78, 0x68, 0x81, 0x0e, 0x0f, 0xd2, 0x0b, 0x23, 
-0x1b, 0x02, 0xf1, 0x18, 0xc9, 0x68, 0x00, 0x29, 0x06, 0xd0, 0x00, 0x08, 
-0x04, 0xd2, 0x20, 0x1c, 0x39, 0x1c, 0x00, 0xf0, 0x43, 0xf8, 0x02, 0xe0, 
-0x38, 0x1c, 0x00, 0xf0, 0x05, 0xfa, 0x38, 0x1c, 0xfb, 0xf7, 0x10, 0xfc, 
-0x20, 0x1c, 0x00, 0xf0, 0x0b, 0xf8, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 
-0x00, 0x00, 0x00, 0xb0, 0xa0, 0x1c, 0x00, 0x80, 0xb4, 0x0c, 0x00, 0x00, 
+0x09, 0x0c, 0x68, 0x60, 0xe8, 0x6a, 0x00, 0xf0, 0x7b, 0xfa, 0x28, 0xe0, 
+0x27, 0xe0, 0xa8, 0x68, 0x00, 0x09, 0x14, 0xd3, 0x68, 0x68, 0x80, 0x0e, 
+0x15, 0xd2, 0x01, 0x9a, 0x00, 0x2a, 0x12, 0xd0, 0x01, 0x9a, 0x50, 0x6b, 
+0x0b, 0x9b, 0x21, 0x1c, 0x3a, 0x1c, 0xff, 0xf7, 0x89, 0xf9, 0x01, 0x9a, 
+0xc0, 0x46, 0x90, 0x64, 0x01, 0x9a, 0x0b, 0x9b, 0xc0, 0x46, 0x93, 0x63, 
+0x03, 0xe0, 0xe8, 0x6a, 0x31, 0x1c, 0x00, 0xf0, 0x5d, 0xfa, 0x68, 0x68, 
+0x30, 0x43, 0x68, 0x60, 0xa8, 0x69, 0xb0, 0x42, 0x05, 0xd9, 0x00, 0x04, 
+0x00, 0x0c, 0x80, 0x1b, 0x00, 0xf0, 0xee, 0xf9, 0xae, 0x61, 0xa8, 0x68, 
+0x8c, 0x23, 0x18, 0x40, 0x0b, 0xd0, 0x2f, 0x4a, 0xc0, 0x46, 0x00, 0x92, 
+0x04, 0x98, 0xc3, 0x1f, 0x05, 0x3b, 0x2a, 0x48, 0x01, 0x6d, 0x42, 0x6d, 
+0x00, 0x20, 0x01, 0xf0, 0x23, 0xf8, 0x01, 0x23, 0x9b, 0x07, 0x20, 0x6d, 
+0x18, 0x43, 0x00, 0x68, 0xc0, 0x46, 0xa0, 0x61, 0xe1, 0x69, 0x81, 0x42, 
+0x12, 0xd0, 0x22, 0x69, 0x02, 0x2a, 0x0f, 0xd2, 0x41, 0x1a, 0x01, 0xd5, 
+0x60, 0x6d, 0x41, 0x18, 0x20, 0x1c, 0xff, 0xf7, 0x3f, 0xfb, 0xe1, 0x69, 
+0x40, 0x18, 0xe0, 0x61, 0x61, 0x6d, 0x88, 0x42, 0x24, 0xd3, 0x40, 0x1a, 
+0xe0, 0x61, 0x21, 0xe0, 0x81, 0x42, 0x1f, 0xd1, 0x20, 0x69, 0x02, 0x28, 
+0x1c, 0xd2, 0x01, 0x20, 0x60, 0x61, 0x18, 0x48, 0x41, 0x69, 0xe2, 0x6c, 
+0x0a, 0x43, 0x42, 0x61, 0x81, 0x69, 0xe3, 0x6c, 0x99, 0x43, 0x81, 0x61, 
+0x01, 0x21, 0x09, 0x05, 0xca, 0x60, 0x80, 0x69, 0xc0, 0x46, 0x08, 0x61, 
+0x8b, 0x02, 0x20, 0x6d, 0x18, 0x43, 0x00, 0x68, 0xc0, 0x46, 0xa0, 0x61, 
+0xe1, 0x69, 0x81, 0x42, 0x02, 0xd0, 0x20, 0x1c, 0xff, 0xf7, 0xcc, 0xfa, 
+0x28, 0x1c, 0x00, 0xf0, 0x0f, 0xf9, 0x0c, 0x98, 0x05, 0x99, 0x40, 0x18, 
+0x00, 0x01, 0x10, 0x30, 0x68, 0x61, 0x13, 0xb0, 0xf0, 0xbc, 0x08, 0xbc, 
+0x18, 0x47, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x7c, 0x29, 0x00, 0x80, 
+0x00, 0x00, 0x12, 0x02, 0x04, 0x00, 0x52, 0x02, 0x68, 0x0e, 0x00, 0x80, 
+0xf0, 0xb5, 0x40, 0x20, 0x2d, 0x49, 0xc0, 0x46, 0x08, 0x60, 0x00, 0xf0, 
+0x03, 0xf9, 0x07, 0x1c, 0x81, 0x69, 0x44, 0x6a, 0xa0, 0x6f, 0x00, 0xf0, 
+0x45, 0xfe, 0x00, 0x20, 0xe1, 0x1d, 0x19, 0x31, 0x48, 0x71, 0x79, 0x68, 
+0xc9, 0x0e, 0x09, 0xd3, 0xf8, 0x6a, 0x00, 0x01, 0x24, 0x49, 0x40, 0x18, 
+0x24, 0x4b, 0xc0, 0x18, 0x01, 0x68, 0x01, 0x39, 0x01, 0x60, 0x36, 0xe0, 
+0xe1, 0x6d, 0x09, 0x68, 0x22, 0x6e, 0xc0, 0x46, 0x11, 0x60, 0x20, 0x4e, 
+0xf5, 0x1d, 0x79, 0x35, 0x01, 0x23, 0xe9, 0x6b, 0x19, 0x43, 0xe9, 0x63, 
+0xb9, 0x6a, 0xe2, 0x6d, 0xc0, 0x46, 0x11, 0x60, 0xb9, 0x6a, 0x22, 0x6e, 
+0xc0, 0x46, 0x11, 0x60, 0x61, 0x69, 0x00, 0x29, 0x04, 0xd1, 0xa9, 0x6b, 
+0x01, 0x31, 0xa9, 0x63, 0x08, 0x29, 0x07, 0xd3, 0xa8, 0x63, 0x01, 0x20, 
+0x00, 0xf0, 0x86, 0xf8, 0xe8, 0x6b, 0x40, 0x08, 0x40, 0x00, 0xe8, 0x63, 
+0x78, 0x68, 0x81, 0x0e, 0x0f, 0xd2, 0x0b, 0x23, 0x1b, 0x02, 0xf1, 0x18, 
+0xc9, 0x68, 0x00, 0x29, 0x06, 0xd0, 0x00, 0x08, 0x04, 0xd2, 0x20, 0x1c, 
+0x39, 0x1c, 0x00, 0xf0, 0x43, 0xf8, 0x02, 0xe0, 0x38, 0x1c, 0x00, 0xf0, 
+0x05, 0xfa, 0x38, 0x1c, 0xfb, 0xf7, 0x06, 0xfc, 0x20, 0x1c, 0x00, 0xf0, 
+0x0b, 0xf8, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0x00, 0xb0, 
+0xa0, 0x1c, 0x00, 0x80, 0xb4, 0x0c, 0x00, 0x00, 
 0x68, 0x0e, 0x00, 0x80, 0x80, 0xb5, 0x07, 0x1c, 0xf8, 0x1d, 0x19, 0x30, 
-0x01, 0x79, 0x00, 0x29, 0x04, 0xd0, 0x00, 0x21, 
-0x01, 0x71, 0x38, 0x1c, 0xff, 0xf7, 0x56, 0xfb, 0xf8, 0x68, 0x02, 0x28, 
-0x0d, 0xd0, 0xb8, 0x68, 0x80, 0x00, 0xc2, 0x19, 0x50, 0x6c, 0x00, 0x28, 
-0x11, 0xd0, 0xb8, 0x6a, 0x41, 0x78, 0x09, 0x01, 0x10, 0x31, 0x52, 0x6b, 
-0x10, 0x1a, 0x88, 0x42, 0x05, 0xd3, 0x38, 0x1c, 0xff, 0xf7, 0x42, 0xfb, 
-0x80, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x38, 0x1c, 0xff, 0xf7, 0x28, 0xfa, 
-0xf8, 0xe7, 0x78, 0x68, 0x80, 0x00, 0xc0, 0x19, 0xc0, 0x6b, 0xc0, 0x46, 
-0xb8, 0x62, 0xf1, 0xe7, 0xb0, 0xb5, 0x87, 0xb0, 0x0f, 0x1c, 0x80, 0x6f, 
-0xc0, 0x46, 0x00, 0x90, 0x00, 0x24, 0x13, 0x4d, 0x0b, 0x23, 0x1b, 0x02, 
-0xe8, 0x18, 0x80, 0x69, 0x00, 0x28, 0x17, 0xd0, 0x69, 0x46, 0xa2, 0x00, 
-0x52, 0x19, 0x0b, 0x23, 0x1b, 0x02, 0xd2, 0x18, 0x92, 0x69, 0x38, 0x1c, 
-0x00, 0xf0, 0x92, 0xfb, 0x00, 0x28, 0x09, 0xd1, 0x01, 0x34, 0xa0, 0x00, 
-0x40, 0x19, 0x0b, 0x23, 0x1b, 0x02, 0xc0, 0x18, 0x80, 0x69, 0x00, 0x28, 
-0xea, 0xd1, 0x01, 0xe0, 0x01, 0x28, 0x02, 0xd0, 0x38, 0x1c, 0x00, 0xf0, 
-0x9d, 0xf9, 0x07, 0xb0, 0xb0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 
-0x68, 0x0e, 0x00, 0x80, 0xb8, 0xb5, 0xc2, 0x07, 0xd2, 0x0f, 0x16, 0x4c, 
-0x16, 0x49, 0x01, 0xd0, 0x08, 0x22, 0x08, 0xe0, 0x82, 0x08, 0x05, 0xd3, 
-0x0c, 0x22, 0xa4, 0x18, 0x0b, 0x68, 0xdf, 0x1d, 0x15, 0x37, 0x03, 0xe0, 
-0x1c, 0x22, 0x0b, 0x68, 0xdf, 0x1d, 0x09, 0x37, 0x0f, 0x4b, 0x1d, 0x78, 
-0x00, 0x2d, 0x13, 0xd0, 0x5b, 0x78, 0x00, 0x2b, 0x10, 0xd0, 0x01, 0x23, 
-0x5b, 0x06, 0x1a, 0x43, 0x00, 0x28, 0x01, 0xd1, 0x5b, 0x08, 0x1a, 0x43, 
-0x00, 0x92, 0x4a, 0x68, 0x01, 0x20, 0x39, 0x1c, 0x23, 0x1c, 0x00, 0xf0, 
-0xdf, 0xfe, 0xb8, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x03, 0x23, 0x1b, 0x06, 
-0x1a, 0x43, 0xf1, 0xe7, 0x3c, 0xef, 0x20, 0x40, 0x7c, 0x29, 0x00, 0x80, 
-0xf8, 0x0e, 0x00, 0x80, 0x00, 0x21, 0xc1, 0x61, 0x05, 0x49, 0x8a, 0x68, 
-0x00, 0x2a, 0x01, 0xd1, 0x88, 0x60, 0x02, 0xe0, 0xca, 0x68, 0xc0, 0x46, 
-0xd0, 0x61, 0xc8, 0x60, 0x70, 0x47, 0x00, 0x00, 0x28, 0x0f, 0x00, 0x80, 
-0x03, 0x49, 0x88, 0x68, 0x00, 0x28, 0x02, 0xd0, 0xc2, 0x69, 0xc0, 0x46, 
-0x8a, 0x60, 0x70, 0x47, 0x28, 0x0f, 0x00, 0x80, 0x01, 0x1c, 0x01, 0x23, 
-0x88, 0x68, 0x58, 0x40, 0x88, 0x60, 0xca, 0x68, 0x01, 0x3a, 0xca, 0x60, 
-0x0a, 0x69, 0x01, 0x3a, 0x80, 0x00, 0x0a, 0x61, 0x42, 0x18, 0xd0, 0x6b, 
-0x53, 0x6b, 0xc0, 0x46, 0xcb, 0x62, 0x0b, 0x68, 0x9b, 0x00, 0x59, 0x18, 
-0x49, 0x6c, 0x53, 0x6c, 0xc9, 0x18, 0x51, 0x64, 0x70, 0x47, 0x8a, 0x68, 
-0x92, 0x00, 0x52, 0x18, 0xd3, 0x6b, 0x83, 0x42, 0x17, 0xd1, 0xd0, 0x1d, 
-0x3d, 0x30, 0x0a, 0x68, 0x92, 0x00, 0x52, 0x18, 0x52, 0x6c, 0x03, 0x68, 
-0x9a, 0x1a, 0x02, 0x60, 0x01, 0x23, 0x88, 0x68, 0x58, 0x40, 0x88, 0x60, 
-0xca, 0x68, 0x01, 0x32, 0xca, 0x60, 0x0a, 0x69, 0x01, 0x32, 0x80, 0x00, 
-0x40, 0x18, 0x0a, 0x61, 0x40, 0x6b, 0xc0, 0x46, 0xc8, 0x62, 0x70, 0x47, 
-0xb8, 0xb5, 0x04, 0x1c, 0x1d, 0x1c, 0x17, 0x1c, 0x08, 0x1c, 0x39, 0x1c, 
-0xff, 0xf7, 0xd9, 0xff, 0x00, 0x20, 0x29, 0x1c, 0x00, 0xf0, 0x7c, 0xfe, 
-0x01, 0x20, 0xf9, 0x1d, 0x19, 0x31, 0x48, 0x71, 0x80, 0x06, 0x60, 0x60, 
-0x00, 0x20, 0xa0, 0x61, 0x06, 0x4a, 0xc0, 0x46, 0x00, 0x92, 0x06, 0x48, 
+0x01, 0x79, 0x00, 0x29, 0x04, 0xd0, 0x00, 0x21, 0x01, 0x71, 0x38, 0x1c, 
+0xff, 0xf7, 0x56, 0xfb, 0xf8, 0x68, 0x02, 0x28, 0x0d, 0xd0, 0xb8, 0x68, 
+0x80, 0x00, 0xc2, 0x19, 0x50, 0x6c, 0x00, 0x28, 0x11, 0xd0, 0xb8, 0x6a, 
+0x41, 0x78, 0x09, 0x01, 0x10, 0x31, 0x52, 0x6b, 0x10, 0x1a, 0x88, 0x42, 
+0x05, 0xd3, 0x38, 0x1c, 0xff, 0xf7, 0x42, 0xfb, 0x80, 0xbc, 0x08, 0xbc, 
+0x18, 0x47, 0x38, 0x1c, 0xff, 0xf7, 0x28, 0xfa, 0xf8, 0xe7, 0x78, 0x68, 
+0x80, 0x00, 0xc0, 0x19, 0xc0, 0x6b, 0xc0, 0x46, 0xb8, 0x62, 0xf1, 0xe7, 
+0xb0, 0xb5, 0x87, 0xb0, 0x0f, 0x1c, 0x80, 0x6f, 0xc0, 0x46, 0x00, 0x90, 
+0x00, 0x24, 0x13, 0x4d, 0x0b, 0x23, 0x1b, 0x02, 0xe8, 0x18, 0x80, 0x69, 
+0x00, 0x28, 0x17, 0xd0, 0x69, 0x46, 0xa2, 0x00, 0x52, 0x19, 0x0b, 0x23, 
+0x1b, 0x02, 0xd2, 0x18, 0x92, 0x69, 0x38, 0x1c, 0x00, 0xf0, 0x92, 0xfb, 
+0x00, 0x28, 0x09, 0xd1, 0x01, 0x34, 0xa0, 0x00, 0x40, 0x19, 0x0b, 0x23, 
+0x1b, 0x02, 0xc0, 0x18, 0x80, 0x69, 0x00, 0x28, 0xea, 0xd1, 0x01, 0xe0, 
+0x01, 0x28, 0x02, 0xd0, 0x38, 0x1c, 0x00, 0xf0, 0x9d, 0xf9, 0x07, 0xb0, 
+0xb0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0x68, 0x0e, 0x00, 0x80, 
+0xb8, 0xb5, 0xc2, 0x07, 0xd2, 0x0f, 0x16, 0x4c, 0x16, 0x49, 0x01, 0xd0, 
+0x08, 0x22, 0x08, 0xe0, 0x82, 0x08, 0x05, 0xd3, 0x0c, 0x22, 0xa4, 0x18, 
+0x0b, 0x68, 0xdf, 0x1d, 0x15, 0x37, 0x03, 0xe0, 0x1c, 0x22, 0x0b, 0x68, 
+0xdf, 0x1d, 0x09, 0x37, 0x0f, 0x4b, 0x1d, 0x78, 0x00, 0x2d, 0x13, 0xd0, 
+0x5b, 0x78, 0x00, 0x2b, 0x10, 0xd0, 0x01, 0x23, 0x5b, 0x06, 0x1a, 0x43, 
+0x00, 0x28, 0x01, 0xd1, 0x5b, 0x08, 0x1a, 0x43, 0x00, 0x92, 0x4a, 0x68, 
+0x01, 0x20, 0x39, 0x1c, 0x23, 0x1c, 0x00, 0xf0, 0xdf, 0xfe, 0xb8, 0xbc, 
+0x08, 0xbc, 0x18, 0x47, 0x03, 0x23, 0x1b, 0x06, 0x1a, 0x43, 0xf1, 0xe7, 
+0x90, 0xee, 0x20, 0x40, 0x7c, 0x29, 0x00, 0x80, 0xf8, 0x0e, 0x00, 0x80, 
+0x00, 0x21, 0xc1, 0x61, 0x05, 0x49, 0x8a, 0x68, 0x00, 0x2a, 0x01, 0xd1, 
+0x88, 0x60, 0x02, 0xe0, 0xca, 0x68, 0xc0, 0x46, 0xd0, 0x61, 0xc8, 0x60, 
+0x70, 0x47, 0x00, 0x00, 0x28, 0x0f, 0x00, 0x80, 0x03, 0x49, 0x88, 0x68, 
+0x00, 0x28, 0x02, 0xd0, 0xc2, 0x69, 0xc0, 0x46, 0x8a, 0x60, 0x70, 0x47, 
+0x28, 0x0f, 0x00, 0x80, 0x01, 0x1c, 0x01, 0x23, 0x88, 0x68, 0x58, 0x40, 
+0x88, 0x60, 0xca, 0x68, 0x01, 0x3a, 0xca, 0x60, 0x0a, 0x69, 0x01, 0x3a, 
+0x80, 0x00, 0x0a, 0x61, 0x42, 0x18, 0xd0, 0x6b, 0x53, 0x6b, 0xc0, 0x46, 
+0xcb, 0x62, 0x0b, 0x68, 0x9b, 0x00, 0x59, 0x18, 0x49, 0x6c, 0x53, 0x6c, 
+0xc9, 0x18, 0x51, 0x64, 0x70, 0x47, 0x8a, 0x68, 0x92, 0x00, 0x52, 0x18, 
+0xd3, 0x6b, 0x83, 0x42, 0x17, 0xd1, 0xd0, 0x1d, 0x3d, 0x30, 0x0a, 0x68, 
+0x92, 0x00, 0x52, 0x18, 0x52, 0x6c, 0x03, 0x68, 0x9a, 0x1a, 0x02, 0x60, 
+0x01, 0x23, 0x88, 0x68, 0x58, 0x40, 0x88, 0x60, 0xca, 0x68, 0x01, 0x32, 
+0xca, 0x60, 0x0a, 0x69, 0x01, 0x32, 0x80, 0x00, 0x40, 0x18, 0x0a, 0x61, 
+0x40, 0x6b, 0xc0, 0x46, 0xc8, 0x62, 0x70, 0x47, 0xb8, 0xb5, 0x04, 0x1c, 
+0x1d, 0x1c, 0x17, 0x1c, 0x08, 0x1c, 0x39, 0x1c, 0xff, 0xf7, 0xd9, 0xff, 
+0x00, 0x20, 0x29, 0x1c, 0x00, 0xf0, 0x7c, 0xfe, 0x01, 0x20, 0xf9, 0x1d, 
+0x19, 0x31, 0x48, 0x71, 0x80, 0x06, 0x60, 0x60, 0x00, 0x20, 0xa0, 0x61, 
+0x06, 0x4a, 0xc0, 0x46, 0x00, 0x92, 0x06, 0x48, 
 0x01, 0x6d, 0x42, 0x6d, 0x05, 0x4b, 0x00, 0x20, 0x00, 0xf0, 0x62, 0xfe, 
-0xb8, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 
-0x04, 0x00, 0x12, 0x02, 0x7c, 0x29, 0x00, 0x80, 0x44, 0x80, 0x20, 0x40, 
+0xb8, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0x04, 0x00, 0x12, 0x02, 
+0x7c, 0x29, 0x00, 0x80, 0x44, 0x80, 0x20, 0x40, 0x06, 0x49, 0x0a, 0x68, 
+0x10, 0x18, 0x08, 0x60, 0x01, 0x23, 0x5b, 0x02, 0x98, 0x42, 0x03, 0xd9, 
+0x03, 0x49, 0x0a, 0x79, 0x01, 0x32, 0x0a, 0x71, 0x70, 0x47, 0x00, 0x00, 
+0xe4, 0x2d, 0x00, 0x80, 0xa0, 0x82, 0x20, 0x40, 0x80, 0x08, 0x80, 0x00, 
 0x06, 0x49, 0x0a, 0x68, 0x10, 0x18, 0x08, 0x60, 0x01, 0x23, 0x5b, 0x02, 
 0x98, 0x42, 0x03, 0xd9, 0x03, 0x49, 0x0a, 0x79, 0x01, 0x32, 0x0a, 0x71, 
 0x70, 0x47, 0x00, 0x00, 0xe4, 0x2d, 0x00, 0x80, 0xa0, 0x82, 0x20, 0x40, 
-0x80, 0x08, 0x80, 0x00, 0x06, 0x49, 0x0a, 0x68, 0x10, 0x18, 0x08, 0x60, 
-0x01, 0x23, 0x5b, 0x02, 0x98, 0x42, 0x03, 0xd9, 0x03, 0x49, 0x0a, 0x79, 
-0x01, 0x32, 0x0a, 0x71, 0x70, 0x47, 0x00, 0x00, 0xe4, 0x2d, 0x00, 0x80, 
-0xa0, 0x82, 0x20, 0x40, 0x03, 0x30, 0x80, 0x08, 0x80, 0x00, 0x06, 0x49, 
-0x0a, 0x68, 0x10, 0x18, 0x08, 0x60, 0x01, 0x23, 0x5b, 0x02, 0x98, 0x42, 
-0x03, 0xd9, 0x03, 0x49, 0x0a, 0x79, 0x01, 0x32, 0x0a, 0x71, 0x70, 0x47, 
-0xe4, 0x2d, 0x00, 0x80, 0xa0, 0x82, 0x20, 0x40, 0x02, 0x48, 0x41, 0x79, 
-0x01, 0x31, 0x41, 0x71, 0x70, 0x47, 0x00, 0x00, 0xa0, 0x82, 0x20, 0x40, 
-0x90, 0xb4, 0x82, 0x00, 0x17, 0x4b, 0x9a, 0x58, 0x8b, 0x07, 0x02, 0xd0, 
-0x89, 0x08, 0x0b, 0x1d, 0x01, 0xe0, 0x89, 0x08, 0xcb, 0x1c, 0x11, 0x69, 
-0xd7, 0x68, 0x12, 0x4c, 0x80, 0x00, 0x20, 0x58, 0x40, 0x68, 0xb9, 0x42, 
-0x03, 0xd1, 0x81, 0x42, 0x19, 0xd9, 0x11, 0x68, 0x17, 0xe0, 0x00, 0x24, 
-0xb9, 0x42, 0x09, 0xd9, 0x81, 0x42, 0x12, 0xd9, 0x11, 0x68, 0x78, 0x1a, 
-0x00, 0xd5, 0x03, 0x30, 0x80, 0x10, 0x98, 0x42, 0x0b, 0xd8, 0x07, 0xe0, 
-0x81, 0x42, 0x05, 0xd8, 0x78, 0x1a, 0x00, 0xd5, 0x03, 0x30, 0x80, 0x10, 
-0x98, 0x42, 0x02, 0xd8, 0x20, 0x1c, 0x90, 0xbc, 0x70, 0x47, 0xc8, 0x1d, 
-0x05, 0x30, 0xfa, 0xe7, 0x70, 0x04, 0x00, 0x80, 0x80, 0xb5, 0x80, 0x00, 
-0x0f, 0x4a, 0x17, 0x58, 0x88, 0x07, 0x02, 0xd0, 0x88, 0x08, 0x04, 0x30, 
-0x01, 0xe0, 0x88, 0x08, 0x03, 0x30, 0x39, 0x69, 0x7a, 0x68, 0x91, 0x42, 
-0x09, 0xd9, 0x39, 0x68, 0xc0, 0x46, 0x39, 0x61, 0xf9, 0x68, 0x7a, 0x68, 
+0x03, 0x30, 0x80, 0x08, 0x80, 0x00, 0x06, 0x49, 0x0a, 0x68, 0x10, 0x18, 
+0x08, 0x60, 0x01, 0x23, 0x5b, 0x02, 0x98, 0x42, 0x03, 0xd9, 0x03, 0x49, 
+0x0a, 0x79, 0x01, 0x32, 0x0a, 0x71, 0x70, 0x47, 0xe4, 0x2d, 0x00, 0x80, 
+0xa0, 0x82, 0x20, 0x40, 0x02, 0x48, 0x41, 0x79, 0x01, 0x31, 0x41, 0x71, 
+0x70, 0x47, 0x00, 0x00, 0xa0, 0x82, 0x20, 0x40, 0x90, 0xb4, 0x82, 0x00, 
+0x17, 0x4b, 0x9a, 0x58, 0x8b, 0x07, 0x02, 0xd0, 0x89, 0x08, 0x0b, 0x1d, 
+0x01, 0xe0, 0x89, 0x08, 0xcb, 0x1c, 0x11, 0x69, 0xd7, 0x68, 0x12, 0x4c, 
+0x80, 0x00, 0x20, 0x58, 0x40, 0x68, 0xb9, 0x42, 0x03, 0xd1, 0x81, 0x42, 
+0x19, 0xd9, 0x11, 0x68, 0x17, 0xe0, 0x00, 0x24, 0xb9, 0x42, 0x09, 0xd9, 
+0x81, 0x42, 0x12, 0xd9, 0x11, 0x68, 0x78, 0x1a, 0x00, 0xd5, 0x03, 0x30, 
+0x80, 0x10, 0x98, 0x42, 0x0b, 0xd8, 0x07, 0xe0, 0x81, 0x42, 0x05, 0xd8, 
+0x78, 0x1a, 0x00, 0xd5, 0x03, 0x30, 0x80, 0x10, 0x98, 0x42, 0x02, 0xd8, 
+0x20, 0x1c, 0x90, 0xbc, 0x70, 0x47, 0xc8, 0x1d, 0x05, 0x30, 0xfa, 0xe7, 
+0x70, 0x04, 0x00, 0x80, 0x80, 0xb5, 0x80, 0x00, 0x0f, 0x4a, 0x17, 0x58, 
+0x88, 0x07, 0x02, 0xd0, 0x88, 0x08, 0x04, 0x30, 0x01, 0xe0, 0x88, 0x08, 
+0x03, 0x30, 0x39, 0x69, 0x7a, 0x68, 0x91, 0x42, 0x09, 0xd9, 0x39, 0x68, 
+0xc0, 0x46, 0x39, 0x61, 0xf9, 0x68, 0x7a, 0x68, 0x91, 0x42, 0x02, 0xd9, 
+0x39, 0x68, 0xc0, 0x46, 0xf9, 0x60, 0x81, 0x00, 0x38, 0x69, 0x00, 0xf0, 
+0xd1, 0xfd, 0x38, 0x61, 0x80, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 
+0x70, 0x04, 0x00, 0x80, 0x90, 0xb5, 0x03, 0x21, 0x09, 0x07, 0x01, 0x40, 
+0x0c, 0x0f, 0x01, 0x04, 0x09, 0x0c, 0x01, 0x22, 0x92, 0x07, 0x02, 0x40, 
+0xa3, 0x00, 0x1c, 0x4f, 0xff, 0x58, 0x89, 0x07, 0x89, 0x0f, 0x00, 0x04, 
+0x00, 0x0c, 0x80, 0x08, 0x00, 0x29, 0x00, 0xd0, 0x01, 0x30, 0x00, 0x2a, 
+0x01, 0xd0, 0x02, 0x30, 0x00, 0xe0, 0x03, 0x30, 0xf9, 0x68, 0x7a, 0x68, 
 0x91, 0x42, 0x02, 0xd9, 0x39, 0x68, 0xc0, 0x46, 0xf9, 0x60, 0x81, 0x00, 
-0x38, 0x69, 0x00, 0xf0, 0xd1, 0xfd, 0x38, 0x61, 0x80, 0xbc, 0x08, 0xbc, 
-0x18, 0x47, 0x00, 0x00, 0x70, 0x04, 0x00, 0x80, 0x90, 0xb5, 0x03, 0x21, 
-0x09, 0x07, 0x01, 0x40, 0x0c, 0x0f, 0x01, 0x04, 0x09, 0x0c, 0x01, 0x22, 
-0x92, 0x07, 0x02, 0x40, 0xa3, 0x00, 0x1c, 0x4f, 0xff, 0x58, 0x89, 0x07, 
-0x89, 0x0f, 0x00, 0x04, 0x00, 0x0c, 0x80, 0x08, 0x00, 0x29, 0x00, 0xd0, 
-0x01, 0x30, 0x00, 0x2a, 0x01, 0xd0, 0x02, 0x30, 0x00, 0xe0, 0x03, 0x30, 
-0xf9, 0x68, 0x7a, 0x68, 0x91, 0x42, 0x02, 0xd9, 0x39, 0x68, 0xc0, 0x46, 
-0xf9, 0x60, 0x81, 0x00, 0xf8, 0x68, 0x00, 0xf0, 0xa5, 0xfd, 0xf8, 0x60, 
-0x0f, 0x48, 0x00, 0x69, 0x00, 0x28, 0x05, 0xd0, 0x01, 0x20, 0xa0, 0x40, 
-0x02, 0xd0, 0x20, 0x1c, 0xfe, 0xf7, 0xca, 0xfc, 0x0b, 0x49, 0xc8, 0x1d, 
-0x19, 0x30, 0x03, 0x79, 0x00, 0x22, 0x00, 0x2b, 0x05, 0xd1, 0x09, 0x49, 
-0xc8, 0x1d, 0x19, 0x30, 0x03, 0x79, 0x00, 0x2b, 0x03, 0xd0, 0x02, 0x71, 
-0x08, 0x1c, 0xff, 0xf7, 0x79, 0xf9, 0x90, 0xbc, 0x08, 0xbc, 0x18, 0x47, 
-0x70, 0x04, 0x00, 0x80, 0xd0, 0x2c, 0x00, 0x80, 0x64, 0x2d, 0x00, 0x80, 
-0xe4, 0x2c, 0x00, 0x80, 0xb0, 0xb5, 0x2b, 0x49, 0x09, 0x79, 0x00, 0x29, 
-0x03, 0xd1, 0x41, 0x68, 0x29, 0x4b, 0x19, 0x43, 0x41, 0x60, 0x81, 0x68, 
+0xf8, 0x68, 0x00, 0xf0, 0xa5, 0xfd, 0xf8, 0x60, 0x0f, 0x48, 0x00, 0x69, 
+0x00, 0x28, 0x05, 0xd0, 0x01, 0x20, 0xa0, 0x40, 0x02, 0xd0, 0x20, 0x1c, 
+0xfe, 0xf7, 0xca, 0xfc, 0x0b, 0x49, 0xc8, 0x1d, 0x19, 0x30, 0x03, 0x79, 
+0x00, 0x22, 0x00, 0x2b, 0x05, 0xd1, 0x09, 0x49, 0xc8, 0x1d, 0x19, 0x30, 
+0x03, 0x79, 0x00, 0x2b, 0x03, 0xd0, 0x02, 0x71, 0x08, 0x1c, 0xff, 0xf7, 
+0x79, 0xf9, 0x90, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x70, 0x04, 0x00, 0x80, 
+0xd0, 0x2c, 0x00, 0x80, 0x64, 0x2d, 0x00, 0x80, 0xe4, 0x2c, 0x00, 0x80, 
+0xb0, 0xb5, 0x2b, 0x49, 0x09, 0x79, 0x00, 0x29, 0x03, 0xd1, 0x41, 0x68, 
+0x29, 0x4b, 0x19, 0x43, 0x41, 0x60, 0x81, 0x68, 
 0x49, 0x08, 0x02, 0xd3, 0x09, 0x21, 0x09, 0x04, 0x01, 0xe0, 0x0d, 0x21, 
-0x09, 0x04, 0x0c, 0xc8, 0x08, 0x38, 0x19, 0x43, 
-0x87, 0x68, 0xbb, 0x0a, 0x03, 0xd3, 0x43, 0x68, 0x5b, 0x08, 0x00, 0xd3, 
-0x01, 0x31, 0x40, 0x68, 0x03, 0x23, 0x1b, 0x07, 0x18, 0x40, 0x07, 0x0f, 
-0xf8, 0x00, 0x1d, 0x4c, 0x00, 0x19, 0x23, 0x68, 0xc0, 0x18, 0x50, 0x30, 
-0x00, 0x79, 0x01, 0x28, 0x10, 0xd1, 0x60, 0x68, 0x01, 0x28, 0x0d, 0xd0, 
-0x10, 0x1c, 0x00, 0xf0, 0x71, 0xf8, 0x38, 0x01, 0x00, 0x19, 0x19, 0x23, 
-0xdb, 0x01, 0xc0, 0x18, 0x41, 0x6b, 0x01, 0x39, 0x41, 0x63, 0xb0, 0xbc, 
-0x08, 0xbc, 0x18, 0x47, 0x38, 0x01, 0x00, 0x19, 0x19, 0x23, 0xdb, 0x01, 
-0xc0, 0x18, 0x03, 0x6b, 0x5d, 0x1c, 0x05, 0x63, 0xbd, 0x02, 0x2d, 0x19, 
-0xdb, 0x00, 0xeb, 0x18, 0x80, 0x33, 0x19, 0x63, 0xda, 0x62, 0x81, 0x6b, 
-0x01, 0x31, 0x81, 0x63, 0x01, 0x21, 0xb9, 0x40, 0x22, 0x68, 0x11, 0x43, 
-0x21, 0x60, 0x01, 0x6b, 0x80, 0x29, 0xe2, 0xd3, 0x00, 0x21, 0x01, 0x63, 
-0xdf, 0xe7, 0x00, 0x00, 0x28, 0x0f, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 
-0xa0, 0x1c, 0x00, 0x80, 0xf0, 0xb5, 0x1f, 0x4e, 0x70, 0x68, 0x00, 0x28, 
-0x36, 0xd1, 0x00, 0x24, 0xb1, 0x68, 0x48, 0x1c, 0xc9, 0x00, 0x89, 0x19, 
-0xb0, 0x60, 0x32, 0x68, 0x89, 0x18, 0x60, 0x31, 0x0d, 0x7b, 0x08, 0x28, 
-0x00, 0xd3, 0xb4, 0x60, 0x28, 0x01, 0x80, 0x19, 0x19, 0x23, 0xdb, 0x01, 
-0xc0, 0x18, 0x87, 0x6b, 0x00, 0x2f, 0x21, 0xd0, 0xc1, 0x6a, 0x4b, 0x1c, 
-0xaa, 0x02, 0x92, 0x19, 0xc9, 0x00, 0x51, 0x18, 0x80, 0x31, 0xc3, 0x62, 
-0xca, 0x6a, 0x09, 0x6b, 0x01, 0x3f, 0x87, 0x63, 0x80, 0x2b, 0x00, 0xd3, 
-0xc4, 0x62, 0x00, 0x2f, 0x06, 0xd1, 0x01, 0x27, 0xaf, 0x40, 0x3b, 0x1c, 
-0xdb, 0x43, 0x37, 0x68, 0x3b, 0x40, 0x33, 0x60, 0x43, 0x6b, 0x01, 0x3b, 
-0x43, 0x63, 0x10, 0x1c, 0x37, 0x1c, 0x00, 0xf0, 0x09, 0xf8, 0x78, 0x68, 
-0x00, 0x28, 0xc9, 0xd0, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 
-0xa0, 0x1c, 0x00, 0x80, 0xf0, 0xb5, 0xcd, 0x0f, 0xed, 0x07, 0x01, 0x24, 
-0x00, 0x27, 0x2e, 0x4b, 0x2e, 0x4a, 0x00, 0x2d, 0x1d, 0xd0, 0xd8, 0x6a, 
-0x01, 0x30, 0xd8, 0x62, 0x10, 0x1c, 0x52, 0x69, 0x00, 0x2a, 0x12, 0xd0, 
-0x02, 0x69, 0x53, 0x1c, 0x92, 0x00, 0x12, 0x18, 0x03, 0x61, 0x91, 0x61, 
-0x41, 0x69, 0x01, 0x31, 0x41, 0x61, 0x02, 0x69, 0x0f, 0x2a, 0x00, 0xd3, 
-0x07, 0x61, 0x0f, 0x29, 0x00, 0xd3, 0x44, 0x60, 0xf0, 0xbc, 0x08, 0xbc, 
-0x18, 0x47, 0x08, 0x1c, 0xff, 0xf7, 0xee, 0xfe, 0xf8, 0xe7, 0x15, 0x69, 
-0x6e, 0x1c, 0xad, 0x00, 0xad, 0x18, 0x16, 0x61, 0xa9, 0x61, 0x55, 0x69, 
-0x01, 0x35, 0x55, 0x61, 0x16, 0x69, 0x0f, 0x2e, 0x00, 0xd3, 0x17, 0x61, 
-0x0f, 0x2d, 0x00, 0xd3, 0x54, 0x60, 0x8c, 0x02, 0xa4, 0x0a, 0x16, 0x4f, 
-0x3a, 0x6f, 0xfd, 0x68, 0xf9, 0x1d, 0x79, 0x31, 0x01, 0x2d, 0x0c, 0xd1, 
-0xdb, 0x6d, 0x5b, 0x08, 0x09, 0xd3, 0x0b, 0x89, 0x00, 0x2b, 0x06, 0xd1, 
-0xfd, 0x6f, 0x03, 0x3b, 0x2e, 0x68, 0x33, 0x40, 0x2b, 0x60, 0x14, 0x23, 
-0x0b, 0x81, 0x10, 0x60, 0x80, 0x07, 0x80, 0x0a, 0x20, 0x43, 0x03, 0x04, 
-0x00, 0xd0, 0x01, 0x38, 0x50, 0x60, 0x09, 0x6a, 0x08, 0x32, 0x91, 0x42, 
-0x00, 0xd8, 0x07, 0x4a, 0x00, 0x0d, 0x02, 0xd3, 0x51, 0x20, 0x80, 0x03, 
-0x82, 0x61, 0x3a, 0x67, 0xbe, 0xe7, 0x00, 0x00, 0xa4, 0x2a, 0x00, 0x80, 
-0xa0, 0x1c, 0x00, 0x80, 0x68, 0x0e, 0x00, 0x80, 0x24, 0xa7, 0x20, 0x40, 
+0x09, 0x04, 0x0c, 0xc8, 0x08, 0x38, 0x19, 0x43, 0x87, 0x68, 0xbb, 0x0a, 
+0x03, 0xd3, 0x43, 0x68, 0x5b, 0x08, 0x00, 0xd3, 0x01, 0x31, 0x40, 0x68, 
+0x03, 0x23, 0x1b, 0x07, 0x18, 0x40, 0x07, 0x0f, 0xf8, 0x00, 0x1d, 0x4c, 
+0x00, 0x19, 0x23, 0x68, 0xc0, 0x18, 0x50, 0x30, 0x00, 0x79, 0x01, 0x28, 
+0x10, 0xd1, 0x60, 0x68, 0x01, 0x28, 0x0d, 0xd0, 0x10, 0x1c, 0x00, 0xf0, 
+0x71, 0xf8, 0x38, 0x01, 0x00, 0x19, 0x19, 0x23, 0xdb, 0x01, 0xc0, 0x18, 
+0x41, 0x6b, 0x01, 0x39, 0x41, 0x63, 0xb0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 
+0x38, 0x01, 0x00, 0x19, 0x19, 0x23, 0xdb, 0x01, 0xc0, 0x18, 0x03, 0x6b, 
+0x5d, 0x1c, 0x05, 0x63, 0xbd, 0x02, 0x2d, 0x19, 0xdb, 0x00, 0xeb, 0x18, 
+0x80, 0x33, 0x19, 0x63, 0xda, 0x62, 0x81, 0x6b, 0x01, 0x31, 0x81, 0x63, 
+0x01, 0x21, 0xb9, 0x40, 0x22, 0x68, 0x11, 0x43, 0x21, 0x60, 0x01, 0x6b, 
+0x80, 0x29, 0xe2, 0xd3, 0x00, 0x21, 0x01, 0x63, 0xdf, 0xe7, 0x00, 0x00, 
+0x28, 0x0f, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0xa0, 0x1c, 0x00, 0x80, 
+0xf0, 0xb5, 0x1f, 0x4e, 0x70, 0x68, 0x00, 0x28, 0x36, 0xd1, 0x00, 0x24, 
+0xb1, 0x68, 0x48, 0x1c, 0xc9, 0x00, 0x89, 0x19, 0xb0, 0x60, 0x32, 0x68, 
+0x89, 0x18, 0x60, 0x31, 0x0d, 0x7b, 0x08, 0x28, 0x00, 0xd3, 0xb4, 0x60, 
+0x28, 0x01, 0x80, 0x19, 0x19, 0x23, 0xdb, 0x01, 0xc0, 0x18, 0x87, 0x6b, 
+0x00, 0x2f, 0x21, 0xd0, 0xc1, 0x6a, 0x4b, 0x1c, 0xaa, 0x02, 0x92, 0x19, 
+0xc9, 0x00, 0x51, 0x18, 0x80, 0x31, 0xc3, 0x62, 0xca, 0x6a, 0x09, 0x6b, 
+0x01, 0x3f, 0x87, 0x63, 0x80, 0x2b, 0x00, 0xd3, 0xc4, 0x62, 0x00, 0x2f, 
+0x06, 0xd1, 0x01, 0x27, 0xaf, 0x40, 0x3b, 0x1c, 0xdb, 0x43, 0x37, 0x68, 
+0x3b, 0x40, 0x33, 0x60, 0x43, 0x6b, 0x01, 0x3b, 0x43, 0x63, 0x10, 0x1c, 
+0x37, 0x1c, 0x00, 0xf0, 0x09, 0xf8, 0x78, 0x68, 0x00, 0x28, 0xc9, 0xd0, 
+0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0xa0, 0x1c, 0x00, 0x80, 
+0xf0, 0xb5, 0xcd, 0x0f, 0xed, 0x07, 0x01, 0x24, 0x00, 0x27, 0x2e, 0x4b, 
+0x2e, 0x4a, 0x00, 0x2d, 0x1d, 0xd0, 0xd8, 0x6a, 0x01, 0x30, 0xd8, 0x62, 
+0x10, 0x1c, 0x52, 0x69, 0x00, 0x2a, 0x12, 0xd0, 0x02, 0x69, 0x53, 0x1c, 
+0x92, 0x00, 0x12, 0x18, 0x03, 0x61, 0x91, 0x61, 0x41, 0x69, 0x01, 0x31, 
+0x41, 0x61, 0x02, 0x69, 0x0f, 0x2a, 0x00, 0xd3, 0x07, 0x61, 0x0f, 0x29, 
+0x00, 0xd3, 0x44, 0x60, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x08, 0x1c, 
+0xff, 0xf7, 0xee, 0xfe, 0xf8, 0xe7, 0x15, 0x69, 0x6e, 0x1c, 0xad, 0x00, 
+0xad, 0x18, 0x16, 0x61, 0xa9, 0x61, 0x55, 0x69, 0x01, 0x35, 0x55, 0x61, 
+0x16, 0x69, 0x0f, 0x2e, 0x00, 0xd3, 0x17, 0x61, 0x0f, 0x2d, 0x00, 0xd3, 
+0x54, 0x60, 0x8c, 0x02, 0xa4, 0x0a, 0x16, 0x4f, 0x3a, 0x6f, 0xfd, 0x68, 
+0xf9, 0x1d, 0x79, 0x31, 0x01, 0x2d, 0x0c, 0xd1, 0xdb, 0x6d, 0x5b, 0x08, 
+0x09, 0xd3, 0x0b, 0x89, 0x00, 0x2b, 0x06, 0xd1, 0xfd, 0x6f, 0x03, 0x3b, 
+0x2e, 0x68, 0x33, 0x40, 0x2b, 0x60, 0x14, 0x23, 0x0b, 0x81, 0x10, 0x60, 
+0x80, 0x07, 0x80, 0x0a, 0x20, 0x43, 0x03, 0x04, 0x00, 0xd0, 0x01, 0x38, 
+0x50, 0x60, 0x09, 0x6a, 0x08, 0x32, 0x91, 0x42, 0x00, 0xd8, 0x07, 0x4a, 
+0x00, 0x0d, 0x02, 0xd3, 0x51, 0x20, 0x80, 0x03, 0x82, 0x61, 0x3a, 0x67, 
+0xbe, 0xe7, 0x00, 0x00, 0xa4, 0x2a, 0x00, 0x80, 0xa0, 0x1c, 0x00, 0x80, 
+0x68, 0x0e, 0x00, 0x80, 0x24, 0xa7, 0x20, 0x40, 
 0xb0, 0xb5, 0x00, 0x28, 0x04, 0xd1, 0x01, 0x20, 0xc0, 0x05, 0x16, 0x49, 
-0xc0, 0x46, 0x08, 0x60, 0x15, 0x4c, 0x00, 0x25, 
-0x67, 0x69, 0x00, 0x2f, 0x16, 0xd0, 0xe0, 0x68, 0x41, 0x1c, 0x80, 0x00, 
-0x00, 0x19, 0xe1, 0x60, 0x80, 0x69, 0x01, 0x3f, 0xff, 0xf7, 0x94, 0xfe, 
-0xe0, 0x68, 0x0f, 0x28, 0x00, 0xd3, 0xe5, 0x60, 0xe0, 0x68, 0x80, 0x00, 
-0x00, 0x19, 0x80, 0x69, 0x00, 0x08, 0x01, 0xd3, 0x00, 0x2f, 0xea, 0xd1, 
-0x67, 0x61, 0x03, 0xe0, 0x08, 0x48, 0x01, 0x6d, 0x01, 0x31, 0x01, 0x65, 
-0x65, 0x60, 0x20, 0x68, 0x00, 0x28, 0x01, 0xd0, 0xff, 0xf7, 0x26, 0xff, 
-0xb0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 
-0xa0, 0x1c, 0x00, 0x80, 0xa0, 0x82, 0x20, 0x40, 0x00, 0x20, 0x70, 0x47, 
-0xb0, 0xb4, 0x10, 0x23, 0x82, 0x68, 0x13, 0x40, 0x00, 0x21, 0x00, 0x2b, 
-0x15, 0xd0, 0x0c, 0x4b, 0x1a, 0x40, 0x12, 0x01, 0x81, 0x24, 0x14, 0x43, 
-0x02, 0x68, 0x15, 0x68, 0x13, 0x1d, 0x80, 0xcb, 0x1b, 0x68, 0x04, 0x3a, 
-0x02, 0x60, 0x20, 0xc2, 0x80, 0xc2, 0x08, 0xc2, 0x14, 0x60, 0x42, 0x68, 
-0x01, 0x23, 0x9b, 0x07, 0x04, 0x32, 0x1a, 0x43, 0x42, 0x60, 0x08, 0x1c, 
-0xb0, 0xbc, 0x70, 0x47, 0x00, 0xf0, 0xff, 0x0f, 0xf0, 0xb4, 0x82, 0x68, 
-0x53, 0x09, 0x34, 0xd3, 0x1b, 0x4b, 0x1a, 0x40, 0x12, 0x01, 0x81, 0x26, 
-0x16, 0x43, 0x03, 0x68, 0x1d, 0x68, 0x1f, 0x1d, 0x10, 0xcf, 0x3f, 0x68, 
-0x04, 0x3b, 0x03, 0x60, 0x20, 0xc3, 0x10, 0xc3, 0x80, 0xc3, 0x1e, 0x60, 
-0x43, 0x68, 0x1f, 0x1d, 0x01, 0x23, 0x9b, 0x07, 0x3b, 0x43, 0x43, 0x60, 
-0xcb, 0x6b, 0x18, 0x1f, 0xc8, 0x63, 0x80, 0xcb, 0x80, 0xc0, 0x1c, 0x68, 
-0x1f, 0x1d, 0x03, 0x1d, 0x04, 0x60, 0x38, 0x1c, 0x3f, 0x68, 0xc0, 0x46, 
-0x1f, 0x60, 0x1f, 0x1d, 0x43, 0x68, 0x1c, 0x04, 0x24, 0x0c, 0x81, 0x23, 
-0x23, 0x43, 0x3b, 0x60, 0x40, 0x68, 0x00, 0x0c, 0x00, 0x04, 0x10, 0x43, 
-0x78, 0x60, 0x08, 0x6e, 0x04, 0x30, 0x08, 0x66, 0x48, 0x6e, 0x04, 0x30, 
-0x48, 0x66, 0x00, 0x20, 0xf0, 0xbc, 0x70, 0x47, 0x00, 0xf0, 0xff, 0x0f, 
-0x80, 0xb4, 0x81, 0x6a, 0x01, 0x23, 0x9b, 0x07, 0xca, 0x1d, 0x05, 0x32, 
-0x1a, 0x43, 0x12, 0x68, 0xcf, 0x1d, 0x01, 0x37, 0x3b, 0x43, 0x1b, 0x68, 
-0xc0, 0x46, 0xcb, 0x60, 0x01, 0x23, 0x9b, 0x07, 0x0f, 0x1d, 0x3b, 0x43, 
-0x1b, 0x68, 0xc0, 0x46, 0x8b, 0x60, 0x01, 0x23, 0x9b, 0x07, 0x0b, 0x43, 
-0x1b, 0x68, 0x0c, 0xc1, 0x02, 0x62, 0x01, 0x6b, 0xc0, 0x46, 0x0a, 0x62, 
-0x04, 0x23, 0x81, 0x69, 0x19, 0x43, 0x81, 0x61, 0x02, 0x6b, 0xc0, 0x46, 
-0x91, 0x61, 0x81, 0x6a, 0x04, 0x31, 0x81, 0x62, 0x02, 0x6b, 0xc0, 0x46, 
-0x91, 0x62, 0xc1, 0x1d, 0x39, 0x31, 0x4a, 0x8b, 0x04, 0x3a, 0x4a, 0x83, 
-0x49, 0x8b, 0x02, 0x6b, 0x40, 0x32, 0x51, 0x83, 0xc1, 0x89, 0x04, 0x39, 
-0xc1, 0x81, 0xc1, 0x68, 0x00, 0x6b, 0xc0, 0x46, 0xc1, 0x60, 0x00, 0x20, 
-0x80, 0xbc, 0x70, 0x47, 0x00, 0x47, 0x08, 0x47, 0x10, 0x47, 0x18, 0x47, 
-0x20, 0x47, 0x28, 0x47, 0x30, 0x47, 0x38, 0x47, 0x30, 0x40, 0x2d, 0xe9, 
-0x0c, 0xc0, 0x9d, 0xe5, 0x0c, 0x48, 0xa0, 0xe1, 0x24, 0x48, 0xb0, 0xe1, 
-0x1e, 0x00, 0x00, 0x0a, 0x01, 0xc0, 0x4c, 0xe2, 0x18, 0x40, 0xa0, 0xe3, 
-0x64, 0x51, 0x9f, 0xe5, 0x94, 0x50, 0x20, 0xe0, 0x00, 0x50, 0x90, 0xe5, 
-0x14, 0x40, 0x90, 0xe5, 0x00, 0x30, 0x85, 0xe5, 0x04, 0xc0, 0x85, 0xe5, 
-0x08, 0x10, 0x85, 0xe5, 0x0c, 0x20, 0x85, 0xe5, 0x10, 0x10, 0x90, 0xe5, 
+0xc0, 0x46, 0x08, 0x60, 0x15, 0x4c, 0x00, 0x25, 0x67, 0x69, 0x00, 0x2f, 
+0x16, 0xd0, 0xe0, 0x68, 0x41, 0x1c, 0x80, 0x00, 0x00, 0x19, 0xe1, 0x60, 
+0x80, 0x69, 0x01, 0x3f, 0xff, 0xf7, 0x94, 0xfe, 0xe0, 0x68, 0x0f, 0x28, 
+0x00, 0xd3, 0xe5, 0x60, 0xe0, 0x68, 0x80, 0x00, 0x00, 0x19, 0x80, 0x69, 
+0x00, 0x08, 0x01, 0xd3, 0x00, 0x2f, 0xea, 0xd1, 0x67, 0x61, 0x03, 0xe0, 
+0x08, 0x48, 0x01, 0x6d, 0x01, 0x31, 0x01, 0x65, 0x65, 0x60, 0x20, 0x68, 
+0x00, 0x28, 0x01, 0xd0, 0xff, 0xf7, 0x26, 0xff, 0xb0, 0xbc, 0x08, 0xbc, 
+0x18, 0x47, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0xa0, 0x1c, 0x00, 0x80, 
+0xa0, 0x82, 0x20, 0x40, 0x00, 0x20, 0x70, 0x47, 0xb0, 0xb4, 0x10, 0x23, 
+0x82, 0x68, 0x13, 0x40, 0x00, 0x21, 0x00, 0x2b, 0x15, 0xd0, 0x0c, 0x4b, 
+0x1a, 0x40, 0x12, 0x01, 0x81, 0x24, 0x14, 0x43, 0x02, 0x68, 0x15, 0x68, 
+0x13, 0x1d, 0x80, 0xcb, 0x1b, 0x68, 0x04, 0x3a, 0x02, 0x60, 0x20, 0xc2, 
+0x80, 0xc2, 0x08, 0xc2, 0x14, 0x60, 0x42, 0x68, 0x01, 0x23, 0x9b, 0x07, 
+0x04, 0x32, 0x1a, 0x43, 0x42, 0x60, 0x08, 0x1c, 0xb0, 0xbc, 0x70, 0x47, 
+0x00, 0xf0, 0xff, 0x0f, 0xf0, 0xb4, 0x82, 0x68, 0x53, 0x09, 0x34, 0xd3, 
+0x1b, 0x4b, 0x1a, 0x40, 0x12, 0x01, 0x81, 0x26, 0x16, 0x43, 0x03, 0x68, 
+0x1d, 0x68, 0x1f, 0x1d, 0x10, 0xcf, 0x3f, 0x68, 0x04, 0x3b, 0x03, 0x60, 
+0x20, 0xc3, 0x10, 0xc3, 0x80, 0xc3, 0x1e, 0x60, 0x43, 0x68, 0x1f, 0x1d, 
+0x01, 0x23, 0x9b, 0x07, 0x3b, 0x43, 0x43, 0x60, 0xcb, 0x6b, 0x18, 0x1f, 
+0xc8, 0x63, 0x80, 0xcb, 0x80, 0xc0, 0x1c, 0x68, 0x1f, 0x1d, 0x03, 0x1d, 
+0x04, 0x60, 0x38, 0x1c, 0x3f, 0x68, 0xc0, 0x46, 0x1f, 0x60, 0x1f, 0x1d, 
+0x43, 0x68, 0x1c, 0x04, 0x24, 0x0c, 0x81, 0x23, 0x23, 0x43, 0x3b, 0x60, 
+0x40, 0x68, 0x00, 0x0c, 0x00, 0x04, 0x10, 0x43, 0x78, 0x60, 0x08, 0x6e, 
+0x04, 0x30, 0x08, 0x66, 0x48, 0x6e, 0x04, 0x30, 0x48, 0x66, 0x00, 0x20, 
+0xf0, 0xbc, 0x70, 0x47, 0x00, 0xf0, 0xff, 0x0f, 0x80, 0xb4, 0x81, 0x6a, 
+0x01, 0x23, 0x9b, 0x07, 0xca, 0x1d, 0x05, 0x32, 0x1a, 0x43, 0x12, 0x68, 
+0xcf, 0x1d, 0x01, 0x37, 0x3b, 0x43, 0x1b, 0x68, 0xc0, 0x46, 0xcb, 0x60, 
+0x01, 0x23, 0x9b, 0x07, 0x0f, 0x1d, 0x3b, 0x43, 0x1b, 0x68, 0xc0, 0x46, 
+0x8b, 0x60, 0x01, 0x23, 0x9b, 0x07, 0x0b, 0x43, 0x1b, 0x68, 0x0c, 0xc1, 
+0x02, 0x62, 0x01, 0x6b, 0xc0, 0x46, 0x0a, 0x62, 0x04, 0x23, 0x81, 0x69, 
+0x19, 0x43, 0x81, 0x61, 0x02, 0x6b, 0xc0, 0x46, 0x91, 0x61, 0x81, 0x6a, 
+0x04, 0x31, 0x81, 0x62, 0x02, 0x6b, 0xc0, 0x46, 0x91, 0x62, 0xc1, 0x1d, 
+0x39, 0x31, 0x4a, 0x8b, 0x04, 0x3a, 0x4a, 0x83, 0x49, 0x8b, 0x02, 0x6b, 
+0x40, 0x32, 0x51, 0x83, 0xc1, 0x89, 0x04, 0x39, 0xc1, 0x81, 0xc1, 0x68, 
+0x00, 0x6b, 0xc0, 0x46, 0xc1, 0x60, 0x00, 0x20, 0x80, 0xbc, 0x70, 0x47, 
+0x00, 0x47, 0x08, 0x47, 0x10, 0x47, 0x18, 0x47, 0x20, 0x47, 0x28, 0x47, 
+0x30, 0x47, 0x38, 0x47, 0x30, 0x40, 0x2d, 0xe9, 0x0c, 0xc0, 0x9d, 0xe5, 
+0x0c, 0x48, 0xa0, 0xe1, 0x24, 0x48, 0xb0, 0xe1, 0x1e, 0x00, 0x00, 0x0a, 
+0x01, 0xc0, 0x4c, 0xe2, 0x18, 0x40, 0xa0, 0xe3, 0x64, 0x51, 0x9f, 0xe5, 
+0x94, 0x50, 0x20, 0xe0, 0x00, 0x50, 0x90, 0xe5, 0x14, 0x40, 0x90, 0xe5, 
+0x00, 0x30, 0x85, 0xe5, 0x04, 0xc0, 0x85, 0xe5, 0x08, 0x10, 0x85, 0xe5, 
+0x0c, 0x20, 0x85, 0xe5, 0x10, 0x10, 0x90, 0xe5, 
 0x10, 0x50, 0x85, 0xe2, 0x01, 0x00, 0x55, 0xe1, 0x0c, 0x50, 0x90, 0x55, 
-0x04, 0x00, 0x55, 0xe1, 0x05, 0x00, 0x00, 0x0a, 
-0x04, 0x10, 0x90, 0xe5, 0x00, 0x50, 0x80, 0xe5, 0x00, 0x50, 0x81, 0xe5, 
-0x00, 0x00, 0xa0, 0xe3, 0x30, 0x40, 0xbd, 0xe8, 0x1e, 0xff, 0x2f, 0xe1, 
-0x00, 0x30, 0x93, 0xe5, 0x08, 0x20, 0x90, 0xe5, 0x01, 0x31, 0x83, 0xe3, 
-0x02, 0x36, 0x83, 0xe3, 0x03, 0x00, 0x55, 0xe1, 0x14, 0x30, 0x80, 0xe5, 
-0xf2, 0xff, 0xff, 0x1a, 0x01, 0x00, 0xa0, 0xe3, 0xf4, 0xff, 0xff, 0xea, 
-0x01, 0x06, 0x1c, 0xe3, 0xf1, 0xff, 0xff, 0x0a, 0xec, 0x10, 0x9f, 0xe5, 
-0x02, 0xc6, 0xcc, 0xe3, 0x54, 0x20, 0x91, 0xe5, 0xe4, 0x30, 0x9f, 0xe5, 
-0x50, 0x10, 0x91, 0xe5, 0xd9, 0xff, 0xff, 0xea, 0xf0, 0x47, 0x2d, 0xe9, 
-0x20, 0xc0, 0x9d, 0xe5, 0x0c, 0x68, 0xa0, 0xe1, 0x26, 0x68, 0xb0, 0xe1, 
-0x25, 0x00, 0x00, 0x0a, 0x18, 0x40, 0xa0, 0xe3, 0xb8, 0x50, 0x9f, 0xe5, 
-0x94, 0x00, 0x00, 0xe0, 0x05, 0x00, 0x80, 0xe0, 0x08, 0x40, 0x90, 0xe5, 
-0x04, 0x80, 0x90, 0xe5, 0x00, 0x70, 0xa0, 0xe3, 0x1f, 0xc0, 0xa0, 0xe3, 
-0x02, 0xc4, 0x8c, 0xe3, 0x00, 0x50, 0x90, 0xe5, 0x10, 0x90, 0x90, 0xe5, 
-0x14, 0xa0, 0x90, 0xe5, 0x00, 0x30, 0x85, 0xe5, 0x04, 0xc0, 0x85, 0xe5, 
-0x08, 0x10, 0x85, 0xe5, 0x0c, 0x20, 0x85, 0xe5, 0x10, 0x50, 0x85, 0xe2, 
-0x09, 0x00, 0x55, 0xe1, 0x0c, 0x50, 0x90, 0x55, 0x0a, 0x00, 0x55, 0xe1, 
-0x15, 0x00, 0x00, 0x0a, 0x03, 0x70, 0x17, 0xe2, 0x20, 0x10, 0x81, 0xe2, 
-0x20, 0x30, 0x83, 0xe2, 0x0a, 0x00, 0x00, 0x0a, 0x00, 0x60, 0x96, 0xe2, 
-0x01, 0x70, 0x87, 0xe2, 0x09, 0x00, 0x00, 0x0a, 0x20, 0x60, 0x46, 0xe2, 
-0x20, 0x00, 0x56, 0xe3, 0xec, 0xff, 0xff, 0xca, 0x00, 0x70, 0xa0, 0xe3, 
-0x01, 0xc0, 0x46, 0xe2, 0x02, 0xc4, 0x8c, 0xe3, 0x00, 0x60, 0xa0, 0xe3, 
-0xe7, 0xff, 0xff, 0xea, 0x00, 0x50, 0x88, 0xe5, 0xf2, 0xff, 0xff, 0xea, 
-0x00, 0x10, 0xa0, 0xe3, 0x00, 0x50, 0x80, 0xe5, 0x01, 0x00, 0xa0, 0xe1, 
-0xf0, 0x47, 0xbd, 0xe8, 0x1e, 0xff, 0x2f, 0xe1, 0x00, 0xa0, 0x94, 0xe5, 
-0x0a, 0x00, 0x55, 0xe1, 0x14, 0xa0, 0x80, 0xe5, 0xe5, 0xff, 0xff, 0x1a, 
-0x01, 0x10, 0xa0, 0xe3, 0xf5, 0xff, 0xff, 0xea, 0xa8, 0x03, 0x00, 0x80, 
-0x7c, 0x29, 0x00, 0x80, 0x00, 0x80, 0x20, 0x40, 0x68, 0x82, 0x9f, 0xe5, 
-0x0b, 0x92, 0xa0, 0xe3, 0x64, 0xa2, 0x9f, 0xe5, 0x58, 0xb0, 0x9a, 0xe5, 
-0x0e, 0xf0, 0xa0, 0xe1, 0x54, 0xb0, 0x9a, 0xe5, 0x1e, 0xff, 0x2f, 0xe1, 
-0x3f, 0x40, 0x2d, 0xe9, 0x00, 0x00, 0x4f, 0xe1, 0x1f, 0x00, 0x00, 0xe2, 
-0x12, 0x00, 0x50, 0xe3, 0x54, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0f, 0xe1, 
-0x80, 0x00, 0xc0, 0xe3, 0x00, 0xf0, 0x21, 0xe1, 0x04, 0x50, 0xa0, 0xe3, 
-0x00, 0x40, 0x99, 0xe5, 0x09, 0x00, 0x00, 0xea, 0x02, 0x00, 0x14, 0xe3, 
-0x53, 0x00, 0x00, 0x1b, 0x80, 0x00, 0x14, 0xe3, 0x59, 0x00, 0x00, 0x1b, 
-0x20, 0x00, 0x14, 0xe3, 0x59, 0x00, 0x00, 0x1b, 0x02, 0x07, 0x14, 0xe3, 
-0x59, 0x00, 0x00, 0x1b, 0x01, 0x06, 0x14, 0xe3, 0x59, 0x00, 0x00, 0x1b, 
-0x08, 0x00, 0x14, 0xe3, 0x45, 0x00, 0x00, 0x1b, 0x02, 0x05, 0x14, 0xe3, 
-0x4a, 0x00, 0x00, 0x1b, 0x02, 0x08, 0x14, 0xe3, 0x4b, 0x00, 0x00, 0x1b, 
-0xe5, 0x0e, 0x14, 0xe3, 0x07, 0x00, 0x00, 0x0a, 0x04, 0x20, 0x98, 0xe5, 
-0x0c, 0x10, 0x98, 0xe5, 0x04, 0x30, 0x52, 0xe2, 0x3c, 0x30, 0xa0, 0xb3, 
-0x04, 0x30, 0x88, 0xe5, 0x02, 0x00, 0x91, 0xe7, 0x0f, 0xe0, 0xa0, 0xe1, 
+0x04, 0x00, 0x55, 0xe1, 0x05, 0x00, 0x00, 0x0a, 0x04, 0x10, 0x90, 0xe5, 
+0x00, 0x50, 0x80, 0xe5, 0x00, 0x50, 0x81, 0xe5, 0x00, 0x00, 0xa0, 0xe3, 
+0x30, 0x40, 0xbd, 0xe8, 0x1e, 0xff, 0x2f, 0xe1, 0x00, 0x30, 0x93, 0xe5, 
+0x08, 0x20, 0x90, 0xe5, 0x01, 0x31, 0x83, 0xe3, 0x02, 0x36, 0x83, 0xe3, 
+0x03, 0x00, 0x55, 0xe1, 0x14, 0x30, 0x80, 0xe5, 0xf2, 0xff, 0xff, 0x1a, 
+0x01, 0x00, 0xa0, 0xe3, 0xf4, 0xff, 0xff, 0xea, 0x01, 0x06, 0x1c, 0xe3, 
+0xf1, 0xff, 0xff, 0x0a, 0xec, 0x10, 0x9f, 0xe5, 0x02, 0xc6, 0xcc, 0xe3, 
+0x54, 0x20, 0x91, 0xe5, 0xe4, 0x30, 0x9f, 0xe5, 0x50, 0x10, 0x91, 0xe5, 
+0xd9, 0xff, 0xff, 0xea, 0xf0, 0x47, 0x2d, 0xe9, 0x20, 0xc0, 0x9d, 0xe5, 
+0x0c, 0x68, 0xa0, 0xe1, 0x26, 0x68, 0xb0, 0xe1, 0x25, 0x00, 0x00, 0x0a, 
+0x18, 0x40, 0xa0, 0xe3, 0xb8, 0x50, 0x9f, 0xe5, 0x94, 0x00, 0x00, 0xe0, 
+0x05, 0x00, 0x80, 0xe0, 0x08, 0x40, 0x90, 0xe5, 0x04, 0x80, 0x90, 0xe5, 
+0x00, 0x70, 0xa0, 0xe3, 0x1f, 0xc0, 0xa0, 0xe3, 0x02, 0xc4, 0x8c, 0xe3, 
+0x00, 0x50, 0x90, 0xe5, 0x10, 0x90, 0x90, 0xe5, 0x14, 0xa0, 0x90, 0xe5, 
+0x00, 0x30, 0x85, 0xe5, 0x04, 0xc0, 0x85, 0xe5, 0x08, 0x10, 0x85, 0xe5, 
+0x0c, 0x20, 0x85, 0xe5, 0x10, 0x50, 0x85, 0xe2, 0x09, 0x00, 0x55, 0xe1, 
+0x0c, 0x50, 0x90, 0x55, 0x0a, 0x00, 0x55, 0xe1, 0x15, 0x00, 0x00, 0x0a, 
+0x03, 0x70, 0x17, 0xe2, 0x20, 0x10, 0x81, 0xe2, 0x20, 0x30, 0x83, 0xe2, 
+0x0a, 0x00, 0x00, 0x0a, 0x00, 0x60, 0x96, 0xe2, 0x01, 0x70, 0x87, 0xe2, 
+0x09, 0x00, 0x00, 0x0a, 0x20, 0x60, 0x46, 0xe2, 0x20, 0x00, 0x56, 0xe3, 
+0xec, 0xff, 0xff, 0xca, 0x00, 0x70, 0xa0, 0xe3, 0x01, 0xc0, 0x46, 0xe2, 
+0x02, 0xc4, 0x8c, 0xe3, 0x00, 0x60, 0xa0, 0xe3, 0xe7, 0xff, 0xff, 0xea, 
+0x00, 0x50, 0x88, 0xe5, 0xf2, 0xff, 0xff, 0xea, 0x00, 0x10, 0xa0, 0xe3, 
+0x00, 0x50, 0x80, 0xe5, 0x01, 0x00, 0xa0, 0xe1, 0xf0, 0x47, 0xbd, 0xe8, 
+0x1e, 0xff, 0x2f, 0xe1, 0x00, 0xa0, 0x94, 0xe5, 0x0a, 0x00, 0x55, 0xe1, 
+0x14, 0xa0, 0x80, 0xe5, 0xe5, 0xff, 0xff, 0x1a, 0x01, 0x10, 0xa0, 0xe3, 
+0xf5, 0xff, 0xff, 0xea, 0xa8, 0x03, 0x00, 0x80, 0x7c, 0x29, 0x00, 0x80, 
+0x00, 0x80, 0x20, 0x40, 0x68, 0x82, 0x9f, 0xe5, 0x0b, 0x92, 0xa0, 0xe3, 
+0x64, 0xa2, 0x9f, 0xe5, 0x58, 0xb0, 0x9a, 0xe5, 0x0e, 0xf0, 0xa0, 0xe1, 
+0x54, 0xb0, 0x9a, 0xe5, 0x1e, 0xff, 0x2f, 0xe1, 0x3f, 0x40, 0x2d, 0xe9, 
+0x00, 0x00, 0x4f, 0xe1, 0x1f, 0x00, 0x00, 0xe2, 0x12, 0x00, 0x50, 0xe3, 
+0x54, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0f, 0xe1, 0x80, 0x00, 0xc0, 0xe3, 
+0x00, 0xf0, 0x21, 0xe1, 0x04, 0x50, 0xa0, 0xe3, 0x00, 0x40, 0x99, 0xe5, 
+0x09, 0x00, 0x00, 0xea, 0x02, 0x00, 0x14, 0xe3, 0x53, 0x00, 0x00, 0x1b, 
+0x80, 0x00, 0x14, 0xe3, 0x59, 0x00, 0x00, 0x1b, 0x20, 0x00, 0x14, 0xe3, 
+0x59, 0x00, 0x00, 0x1b, 0x02, 0x07, 0x14, 0xe3, 0x59, 0x00, 0x00, 0x1b, 
+0x01, 0x06, 0x14, 0xe3, 0x59, 0x00, 0x00, 0x1b, 0x08, 0x00, 0x14, 0xe3, 
+0x45, 0x00, 0x00, 0x1b, 0x02, 0x05, 0x14, 0xe3, 0x4a, 0x00, 0x00, 0x1b, 
+0x02, 0x08, 0x14, 0xe3, 0x4b, 0x00, 0x00, 0x1b, 0xe5, 0x0e, 0x14, 0xe3, 
+0x07, 0x00, 0x00, 0x0a, 0x04, 0x20, 0x98, 0xe5, 0x0c, 0x10, 0x98, 0xe5, 
+0x04, 0x30, 0x52, 0xe2, 0x3c, 0x30, 0xa0, 0xb3, 0x04, 0x30, 0x88, 0xe5, 
+0x02, 0x00, 0x91, 0xe7, 0x0f, 0xe0, 0xa0, 0xe1, 
 0x10, 0xff, 0x2f, 0xe1, 0x01, 0x50, 0x55, 0xe2, 0x03, 0x00, 0x00, 0x0a, 
-0x00, 0x40, 0x99, 0xe5, 0x0c, 0x00, 0x9a, 0xe5, 
-0x00, 0x00, 0x14, 0xe1, 0x1b, 0xff, 0x2f, 0x11, 0x08, 0x00, 0x9a, 0xe5, 
-0x00, 0x00, 0x14, 0xe1, 0x0b, 0x00, 0x00, 0x0a, 0x01, 0x0c, 0x14, 0xe3, 
-0x98, 0x01, 0x9f, 0x15, 0x0f, 0xe0, 0xa0, 0x11, 0x10, 0xff, 0x2f, 0x11, 
-0x02, 0x04, 0x14, 0xe3, 0x8c, 0x01, 0x9f, 0x15, 0x0f, 0xe0, 0xa0, 0x11, 
-0x10, 0xff, 0x2f, 0x11, 0x01, 0x09, 0x14, 0xe3, 0x80, 0x01, 0x9f, 0x15, 
-0x0f, 0xe0, 0xa0, 0x11, 0x10, 0xff, 0x2f, 0x11, 0x04, 0x00, 0x9a, 0xe5, 
-0x00, 0x00, 0x14, 0xe1, 0x16, 0x00, 0x00, 0x0a, 0x54, 0xe0, 0x8f, 0xe2, 
-0x04, 0x00, 0x14, 0xe3, 0x40, 0x00, 0x9a, 0x15, 0x10, 0xff, 0x2f, 0x11, 
-0x02, 0x0a, 0x14, 0xe3, 0x44, 0x00, 0x9a, 0x15, 0x10, 0xff, 0x2f, 0x11, 
-0x02, 0x09, 0x14, 0xe3, 0x48, 0x00, 0x9a, 0x15, 0x10, 0xff, 0x2f, 0x11, 
-0x01, 0x02, 0x14, 0xe3, 0x4c, 0x00, 0x9a, 0x15, 0x10, 0xff, 0x2f, 0x11, 
-0x01, 0x04, 0x14, 0xe3, 0x50, 0x00, 0x9a, 0x15, 0x10, 0xff, 0x2f, 0x11, 
-0x01, 0x0a, 0x14, 0xe3, 0x21, 0x00, 0x00, 0x1b, 0x02, 0x00, 0x14, 0xe3, 
-0x0e, 0x00, 0x00, 0x1b, 0x10, 0x00, 0x9a, 0xe5, 0x00, 0x00, 0x14, 0xe1, 
-0x1c, 0x00, 0x00, 0x1b, 0x00, 0x40, 0x99, 0xe5, 0x04, 0x50, 0xa0, 0xe3, 
-0x00, 0x40, 0x94, 0xe2, 0x1b, 0xff, 0x2f, 0x11, 0x3f, 0x40, 0xbd, 0xe8, 
-0x04, 0xf0, 0x5e, 0xe2, 0xc0, 0x00, 0x80, 0xe3, 0x00, 0xf0, 0x61, 0xe1, 
-0xfa, 0xff, 0xff, 0xea, 0x18, 0x00, 0x9a, 0xe5, 0x1c, 0x10, 0x9a, 0xe5, 
-0x11, 0xff, 0x2f, 0xe1, 0x54, 0xb0, 0x9a, 0xe5, 0x1c, 0x10, 0x9a, 0xe5, 
-0x14, 0x00, 0x9a, 0xe5, 0x11, 0xff, 0x2f, 0xe1, 0x20, 0x10, 0x9a, 0xe5, 
-0x00, 0x00, 0xa0, 0xe3, 0x11, 0xff, 0x2f, 0xe1, 0x24, 0x10, 0x9a, 0xe5, 
-0x11, 0xff, 0x2f, 0xe1, 0x28, 0x10, 0x9a, 0xe5, 0x11, 0xff, 0x2f, 0xe1, 
-0x2c, 0x10, 0x9a, 0xe5, 0x11, 0xff, 0x2f, 0xe1, 0x30, 0x10, 0x9a, 0xe5, 
-0x11, 0xff, 0x2f, 0xe1, 0x34, 0x10, 0x9a, 0xe5, 0x11, 0xff, 0x2f, 0xe1, 
-0xfe, 0xff, 0xff, 0xea, 0x38, 0xe0, 0x9a, 0xe5, 0x3c, 0x10, 0x9a, 0xe5, 
-0x18, 0x00, 0x9a, 0xe5, 0x11, 0xff, 0x2f, 0xe1, 0x38, 0xe0, 0x9a, 0xe5, 
-0x3c, 0x10, 0x9a, 0xe5, 0x14, 0x00, 0x9a, 0xe5, 0x11, 0xff, 0x2f, 0xe1, 
-0x64, 0x20, 0x9f, 0xe5, 0x00, 0x30, 0x92, 0xe5, 0x00, 0x30, 0x53, 0xe0, 
-0x0a, 0x00, 0x00, 0xba, 0x00, 0x30, 0x82, 0xe5, 0x0c, 0x00, 0x92, 0xe5, 
-0x08, 0x30, 0x92, 0xe5, 0x00, 0x10, 0x91, 0xe2, 0x03, 0x00, 0x00, 0x0a, 
-0x03, 0x10, 0x80, 0xe7, 0x04, 0x30, 0x53, 0xe2, 0x3c, 0x30, 0xa0, 0xb3, 
-0x08, 0x30, 0x82, 0xe5, 0x01, 0x00, 0xa0, 0xe3, 0x1e, 0xff, 0x2f, 0xe1, 
-0x3c, 0x10, 0x9f, 0xe5, 0x00, 0x00, 0x91, 0xe5, 0x01, 0x00, 0x80, 0xe2, 
-0x00, 0x00, 0x81, 0xe5, 0x00, 0x00, 0xa0, 0xe3, 0xf8, 0xff, 0xff, 0xea, 
-0x10, 0x00, 0x9f, 0xe5, 0x08, 0x10, 0x90, 0xe5, 0x04, 0x10, 0x51, 0xe2, 
-0x3c, 0x10, 0xa0, 0xb3, 0x08, 0x10, 0x80, 0xe5, 0x1e, 0xff, 0x2f, 0xe1, 
-0xe4, 0x2d, 0x00, 0x80, 0xcc, 0x04, 0x00, 0x80, 0x5d, 0x2b, 0xff, 0xff, 
-0xbd, 0x3d, 0xff, 0xff, 0xb5, 0x2b, 0xff, 0xff, 0xa0, 0x82, 0x20, 0x40, 
-0xc9, 0x1c, 0x89, 0x08, 0x89, 0x00, 0x01, 0x23, 0x85, 0x4a, 0x5b, 0x07, 
-0x18, 0x43, 0x13, 0x68, 0x5b, 0x18, 0x13, 0x60, 0x00, 0x1f, 0x81, 0xa3, 
-0x5b, 0x1a, 0x18, 0x47, 0x04, 0x20, 0xa0, 0xe5, 0x04, 0x20, 0xa0, 0xe5, 
-0x04, 0x20, 0xa0, 0xe5, 0x04, 0x20, 0xa0, 0xe5, 0x04, 0x20, 0xa0, 0xe5, 
+0x00, 0x40, 0x99, 0xe5, 0x0c, 0x00, 0x9a, 0xe5, 0x00, 0x00, 0x14, 0xe1, 
+0x1b, 0xff, 0x2f, 0x11, 0x08, 0x00, 0x9a, 0xe5, 0x00, 0x00, 0x14, 0xe1, 
+0x0b, 0x00, 0x00, 0x0a, 0x01, 0x0c, 0x14, 0xe3, 0x98, 0x01, 0x9f, 0x15, 
+0x0f, 0xe0, 0xa0, 0x11, 0x10, 0xff, 0x2f, 0x11, 0x02, 0x04, 0x14, 0xe3, 
+0x8c, 0x01, 0x9f, 0x15, 0x0f, 0xe0, 0xa0, 0x11, 0x10, 0xff, 0x2f, 0x11, 
+0x01, 0x09, 0x14, 0xe3, 0x80, 0x01, 0x9f, 0x15, 0x0f, 0xe0, 0xa0, 0x11, 
+0x10, 0xff, 0x2f, 0x11, 0x04, 0x00, 0x9a, 0xe5, 0x00, 0x00, 0x14, 0xe1, 
+0x16, 0x00, 0x00, 0x0a, 0x54, 0xe0, 0x8f, 0xe2, 0x04, 0x00, 0x14, 0xe3, 
+0x40, 0x00, 0x9a, 0x15, 0x10, 0xff, 0x2f, 0x11, 0x02, 0x0a, 0x14, 0xe3, 
+0x44, 0x00, 0x9a, 0x15, 0x10, 0xff, 0x2f, 0x11, 0x02, 0x09, 0x14, 0xe3, 
+0x48, 0x00, 0x9a, 0x15, 0x10, 0xff, 0x2f, 0x11, 0x01, 0x02, 0x14, 0xe3, 
+0x4c, 0x00, 0x9a, 0x15, 0x10, 0xff, 0x2f, 0x11, 0x01, 0x04, 0x14, 0xe3, 
+0x50, 0x00, 0x9a, 0x15, 0x10, 0xff, 0x2f, 0x11, 0x01, 0x0a, 0x14, 0xe3, 
+0x21, 0x00, 0x00, 0x1b, 0x02, 0x00, 0x14, 0xe3, 0x0e, 0x00, 0x00, 0x1b, 
+0x10, 0x00, 0x9a, 0xe5, 0x00, 0x00, 0x14, 0xe1, 0x1c, 0x00, 0x00, 0x1b, 
+0x00, 0x40, 0x99, 0xe5, 0x04, 0x50, 0xa0, 0xe3, 0x00, 0x40, 0x94, 0xe2, 
+0x1b, 0xff, 0x2f, 0x11, 0x3f, 0x40, 0xbd, 0xe8, 0x04, 0xf0, 0x5e, 0xe2, 
+0xc0, 0x00, 0x80, 0xe3, 0x00, 0xf0, 0x61, 0xe1, 0xfa, 0xff, 0xff, 0xea, 
+0x18, 0x00, 0x9a, 0xe5, 0x1c, 0x10, 0x9a, 0xe5, 0x11, 0xff, 0x2f, 0xe1, 
+0x54, 0xb0, 0x9a, 0xe5, 0x1c, 0x10, 0x9a, 0xe5, 0x14, 0x00, 0x9a, 0xe5, 
+0x11, 0xff, 0x2f, 0xe1, 0x20, 0x10, 0x9a, 0xe5, 0x00, 0x00, 0xa0, 0xe3, 
+0x11, 0xff, 0x2f, 0xe1, 0x24, 0x10, 0x9a, 0xe5, 0x11, 0xff, 0x2f, 0xe1, 
+0x28, 0x10, 0x9a, 0xe5, 0x11, 0xff, 0x2f, 0xe1, 0x2c, 0x10, 0x9a, 0xe5, 
+0x11, 0xff, 0x2f, 0xe1, 0x30, 0x10, 0x9a, 0xe5, 0x11, 0xff, 0x2f, 0xe1, 
+0x34, 0x10, 0x9a, 0xe5, 0x11, 0xff, 0x2f, 0xe1, 0xfe, 0xff, 0xff, 0xea, 
+0x38, 0xe0, 0x9a, 0xe5, 0x3c, 0x10, 0x9a, 0xe5, 0x18, 0x00, 0x9a, 0xe5, 
+0x11, 0xff, 0x2f, 0xe1, 0x38, 0xe0, 0x9a, 0xe5, 0x3c, 0x10, 0x9a, 0xe5, 
+0x14, 0x00, 0x9a, 0xe5, 0x11, 0xff, 0x2f, 0xe1, 0x64, 0x20, 0x9f, 0xe5, 
+0x00, 0x30, 0x92, 0xe5, 0x00, 0x30, 0x53, 0xe0, 0x0a, 0x00, 0x00, 0xba, 
+0x00, 0x30, 0x82, 0xe5, 0x0c, 0x00, 0x92, 0xe5, 0x08, 0x30, 0x92, 0xe5, 
+0x00, 0x10, 0x91, 0xe2, 0x03, 0x00, 0x00, 0x0a, 0x03, 0x10, 0x80, 0xe7, 
+0x04, 0x30, 0x53, 0xe2, 0x3c, 0x30, 0xa0, 0xb3, 0x08, 0x30, 0x82, 0xe5, 
+0x01, 0x00, 0xa0, 0xe3, 0x1e, 0xff, 0x2f, 0xe1, 0x3c, 0x10, 0x9f, 0xe5, 
+0x00, 0x00, 0x91, 0xe5, 0x01, 0x00, 0x80, 0xe2, 0x00, 0x00, 0x81, 0xe5, 
+0x00, 0x00, 0xa0, 0xe3, 0xf8, 0xff, 0xff, 0xea, 0x10, 0x00, 0x9f, 0xe5, 
+0x08, 0x10, 0x90, 0xe5, 0x04, 0x10, 0x51, 0xe2, 0x3c, 0x10, 0xa0, 0xb3, 
+0x08, 0x10, 0x80, 0xe5, 0x1e, 0xff, 0x2f, 0xe1, 0xe4, 0x2d, 0x00, 0x80, 
+0xcc, 0x04, 0x00, 0x80, 0x71, 0x2b, 0xff, 0xff, 0xd1, 0x3d, 0xff, 0xff, 
+0xc9, 0x2b, 0xff, 0xff, 0xa0, 0x82, 0x20, 0x40, 0xc9, 0x1c, 0x89, 0x08, 
+0x89, 0x00, 0x01, 0x23, 0x85, 0x4a, 0x5b, 0x07, 0x18, 0x43, 0x13, 0x68, 
+0x5b, 0x18, 0x13, 0x60, 0x00, 0x1f, 0x81, 0xa3, 0x5b, 0x1a, 0x18, 0x47, 
 0x04, 0x20, 0xa0, 0xe5, 0x04, 0x20, 0xa0, 0xe5, 
 0x04, 0x20, 0xa0, 0xe5, 0x04, 0x20, 0xa0, 0xe5, 0x04, 0x20, 0xa0, 0xe5, 
 0x04, 0x20, 0xa0, 0xe5, 0x04, 0x20, 0xa0, 0xe5, 0x04, 0x20, 0xa0, 0xe5, 
@@ -1921,204 +1922,143 @@
 0x04, 0x20, 0xa0, 0xe5, 0x04, 0x20, 0xa0, 0xe5, 0x04, 0x20, 0xa0, 0xe5, 
 0x04, 0x20, 0xa0, 0xe5, 0x04, 0x20, 0xa0, 0xe5, 0x04, 0x20, 0xa0, 0xe5, 
 0x04, 0x20, 0xa0, 0xe5, 0x04, 0x20, 0xa0, 0xe5, 0x04, 0x20, 0xa0, 0xe5, 
-0x04, 0x20, 0xa0, 0xe5, 0x1e, 0xff, 0x2f, 0xe1, 0xe4, 0x2d, 0x00, 0x80, 
+0x04, 0x20, 0xa0, 0xe5, 0x04, 0x20, 0xa0, 0xe5, 0x04, 0x20, 0xa0, 0xe5, 
+0x04, 0x20, 0xa0, 0xe5, 0x04, 0x20, 0xa0, 0xe5, 0x04, 0x20, 0xa0, 0xe5, 
+0x1e, 0xff, 0x2f, 0xe1, 0xe4, 0x2d, 0x00, 0x80, 
 0x98, 0x00, 0x9f, 0xe5, 0x98, 0x10, 0x9f, 0xe5, 0x01, 0x20, 0x40, 0xe0, 
-0x94, 0x30, 0x9f, 0xe5, 0x00, 0x00, 0x91, 0xe5, 
+0x94, 0x30, 0x9f, 0xe5, 0x00, 0x00, 0x91, 0xe5, 0x03, 0x00, 0x50, 0xe1, 
+0x03, 0x00, 0x00, 0x1a, 0x04, 0x10, 0x81, 0xe2, 0x04, 0x20, 0x52, 0xe2, 
+0x00, 0x00, 0x00, 0x0a, 0xf8, 0xff, 0xff, 0xea, 0x78, 0x00, 0x9f, 0xe5, 
+0x00, 0x20, 0x80, 0xe5, 0x74, 0x00, 0x9f, 0xe5, 0x74, 0x10, 0x9f, 0xe5, 
+0x01, 0x20, 0x40, 0xe0, 0x60, 0x30, 0x9f, 0xe5, 0x00, 0x00, 0x91, 0xe5, 
 0x03, 0x00, 0x50, 0xe1, 0x03, 0x00, 0x00, 0x1a, 0x04, 0x10, 0x81, 0xe2, 
 0x04, 0x20, 0x52, 0xe2, 0x00, 0x00, 0x00, 0x0a, 0xf8, 0xff, 0xff, 0xea, 
-0x78, 0x00, 0x9f, 0xe5, 0x00, 0x20, 0x80, 0xe5, 0x74, 0x00, 0x9f, 0xe5, 
-0x74, 0x10, 0x9f, 0xe5, 0x01, 0x20, 0x40, 0xe0, 0x60, 0x30, 0x9f, 0xe5, 
+0x50, 0x00, 0x9f, 0xe5, 0x00, 0x20, 0x80, 0xe5, 0x4c, 0x00, 0x9f, 0xe5, 
+0x4c, 0x10, 0x9f, 0xe5, 0x01, 0x20, 0x40, 0xe0, 0x2c, 0x30, 0x9f, 0xe5, 
 0x00, 0x00, 0x91, 0xe5, 0x03, 0x00, 0x50, 0xe1, 0x03, 0x00, 0x00, 0x1a, 
 0x04, 0x10, 0x81, 0xe2, 0x04, 0x20, 0x52, 0xe2, 0x00, 0x00, 0x00, 0x0a, 
-0xf8, 0xff, 0xff, 0xea, 0x50, 0x00, 0x9f, 0xe5, 0x00, 0x20, 0x80, 0xe5, 
-0x4c, 0x00, 0x9f, 0xe5, 0x4c, 0x10, 0x9f, 0xe5, 0x01, 0x20, 0x40, 0xe0, 
-0x2c, 0x30, 0x9f, 0xe5, 0x00, 0x00, 0x91, 0xe5, 0x03, 0x00, 0x50, 0xe1, 
-0x03, 0x00, 0x00, 0x1a, 0x04, 0x10, 0x81, 0xe2, 0x04, 0x20, 0x52, 0xe2, 
-0x00, 0x00, 0x00, 0x0a, 0xf8, 0xff, 0xff, 0xea, 0x28, 0x00, 0x9f, 0xe5, 
-0x00, 0x20, 0x80, 0xe5, 0x1e, 0xff, 0x2f, 0xe1, 0x7c, 0x34, 0x00, 0x80, 
-0x80, 0x30, 0x00, 0x80, 0xad, 0xde, 0xad, 0xde, 0xc0, 0x04, 0x00, 0x80, 
-0xfc, 0x37, 0x00, 0x80, 0x80, 0x34, 0x00, 0x80, 0xc4, 0x04, 0x00, 0x80, 
-0xfc, 0x3f, 0x00, 0x80, 0x40, 0x38, 0x00, 0x80, 0xc8, 0x04, 0x00, 0x80, 
-0x78, 0x47, 0x00, 0x00, 0x76, 0xea, 0xff, 0xea, 0x78, 0x47, 0x00, 0x00, 
-0x39, 0xfe, 0xff, 0xea, 0x78, 0x47, 0x00, 0x00, 0x63, 0xfe, 0xff, 0xea, 
-0x78, 0x47, 0x00, 0x00, 0x1b, 0xff, 0xff, 0xea, 0x78, 0x47, 0x00, 0x00, 
-0x70, 0xea, 0xff, 0xea, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 
-0x00, 0x00, 0x00, 0x80, 0x28, 0x04, 0x00, 0x00, 0x95, 0x22, 0x00, 0x00, 
-0x00, 0x01, 0x00, 0x80, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-0xb9, 0x0b, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xd5, 0x0b, 0xff, 0xff, 
-0x03, 0xff, 0x06, 0x54, 0x03, 0x00, 0x00, 0x00, 0x75, 0x04, 0xff, 0xff, 
-0x00, 0x00, 0x00, 0x00, 0xa1, 0x05, 0xff, 0xff, 0x04, 0xff, 0x07, 0x54, 
-0x03, 0x00, 0x00, 0x00, 0xb5, 0x04, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 
-0xf1, 0x05, 0xff, 0xff, 0x05, 0xff, 0x05, 0x54, 0x03, 0x00, 0x00, 0x00, 
-0x39, 0x04, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x55, 0x05, 0xff, 0xff, 
-0x01, 0xff, 0x04, 0x00, 0x03, 0x00, 0x00, 0x00, 0x41, 0x18, 0xff, 0xff, 
-0x00, 0x00, 0x00, 0x00, 0x61, 0x0e, 0xff, 0xff, 0x02, 0xff, 0x02, 0x08, 
-0x00, 0x00, 0x00, 0x00, 0xa1, 0x02, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 
-0xf1, 0x02, 0xff, 0xff, 0xff, 0xff, 0x01, 0x44, 0x03, 0x00, 0x00, 0x00, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9d, 0x0d, 0xff, 0xff, 
-0x06, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29, 0x50, 0xff, 0xff, 
-0x6d, 0x50, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0xf8, 0xff, 0xff, 0xea, 0x28, 0x00, 0x9f, 0xe5, 0x00, 0x20, 0x80, 0xe5, 
+0x1e, 0xff, 0x2f, 0xe1, 0x7c, 0x34, 0x00, 0x80, 0x80, 0x30, 0x00, 0x80, 
+0xad, 0xde, 0xad, 0xde, 0xc0, 0x04, 0x00, 0x80, 0xfc, 0x37, 0x00, 0x80, 
+0x80, 0x34, 0x00, 0x80, 0xc4, 0x04, 0x00, 0x80, 0xfc, 0x3f, 0x00, 0x80, 
+0x40, 0x38, 0x00, 0x80, 0xc8, 0x04, 0x00, 0x80, 0x78, 0x47, 0x00, 0x00, 
+0x71, 0xea, 0xff, 0xea, 0x78, 0x47, 0x00, 0x00, 0x39, 0xfe, 0xff, 0xea, 
+0x78, 0x47, 0x00, 0x00, 0x63, 0xfe, 0xff, 0xea, 0x78, 0x47, 0x00, 0x00, 
+0x1b, 0xff, 0xff, 0xea, 0x78, 0x47, 0x00, 0x00, 0x6b, 0xea, 0xff, 0xea, 
+0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 
+0x28, 0x04, 0x00, 0x00, 0xf8, 0x3d, 0x00, 0x00, 0x00, 0x01, 0x00, 0x80, 
+0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb9, 0x0b, 0xff, 0xff, 
+0x00, 0x00, 0x00, 0x00, 0xd5, 0x0b, 0xff, 0xff, 0x03, 0xff, 0x06, 0x54, 
+0x03, 0x00, 0x00, 0x00, 0x75, 0x04, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 
+0xa1, 0x05, 0xff, 0xff, 0x04, 0xff, 0x07, 0x54, 0x03, 0x00, 0x00, 0x00, 
+0xb5, 0x04, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xf1, 0x05, 0xff, 0xff, 
+0x05, 0xff, 0x05, 0x54, 0x03, 0x00, 0x00, 0x00, 0x39, 0x04, 0xff, 0xff, 
+0x00, 0x00, 0x00, 0x00, 0x55, 0x05, 0xff, 0xff, 0x01, 0xff, 0x04, 0x00, 
+0x03, 0x00, 0x00, 0x00, 0x41, 0x18, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 
+0x61, 0x0e, 0xff, 0xff, 0x02, 0xff, 0x02, 0x08, 0x00, 0x00, 0x00, 0x00, 
+0xa1, 0x02, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xf1, 0x02, 0xff, 0xff, 
+0xff, 0xff, 0x01, 0x44, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x9d, 0x0d, 0xff, 0xff, 0x06, 0x00, 0xff, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x3d, 0x50, 0xff, 0xff, 0x81, 0x50, 0xff, 0xff, 
 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 
 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0x00, 0x00, 0x00, 0x48, 0x05, 0x00, 0x80, 0x19, 0x78, 0x21, 0x40, 
-0x23, 0x78, 0x21, 0x40, 0x39, 0x78, 0x21, 0x40, 0x51, 0x78, 0x21, 0x40, 
-0x5d, 0x78, 0x21, 0x40, 0x6b, 0x78, 0x21, 0x40, 0x85, 0x78, 0x21, 0x40, 
-0xb1, 0x78, 0x21, 0x40, 0x75, 0x79, 0x21, 0x40, 
-0xcd, 0x79, 0x21, 0x40, 0xdb, 0x79, 0x21, 0x40, 0xe5, 0x79, 0x21, 0x40, 
-0xef, 0x79, 0x21, 0x40, 0x8d, 0x7a, 0x21, 0x40, 0x9b, 0x7a, 0x21, 0x40, 
-0xa9, 0x7a, 0x21, 0x40, 0x51, 0x7b, 0x21, 0x40, 0x4f, 0x7f, 0x21, 0x40, 
-0xc9, 0x7f, 0x21, 0x40, 0x69, 0x80, 0x21, 0x40, 0x9d, 0x81, 0x21, 0x40, 
-0xa9, 0x81, 0x21, 0x40, 0x09, 0x82, 0x21, 0x40, 0x6d, 0x82, 0x21, 0x40, 
-0x99, 0x82, 0x21, 0x40, 0xbd, 0x82, 0x21, 0x40, 0xfd, 0x82, 0x21, 0x40, 
-0x25, 0x83, 0x21, 0x40, 0x6d, 0x83, 0x21, 0x40, 0x7d, 0x83, 0x21, 0x40, 
-0xa5, 0x83, 0x21, 0x40, 0xb5, 0x83, 0x21, 0x40, 0xfd, 0x83, 0x21, 0x40, 
-0x3b, 0x84, 0x21, 0x40, 0x91, 0x84, 0x21, 0x40, 0xf1, 0x84, 0x21, 0x40, 
-0xfb, 0x84, 0x21, 0x40, 0xff, 0x84, 0x21, 0x40, 0x6d, 0x85, 0x21, 0x40, 
-0xb9, 0x85, 0x21, 0x40, 0x11, 0x86, 0x21, 0x40, 0x4d, 0x86, 0x21, 0x40, 
-0xb1, 0x86, 0x21, 0x40, 0xe9, 0x86, 0x21, 0x40, 0xf9, 0x86, 0x21, 0x40, 
-0x31, 0x87, 0x21, 0x40, 0x41, 0x87, 0x21, 0x40, 0x55, 0x87, 0x21, 0x40, 
-0x7d, 0x87, 0x21, 0x40, 0x87, 0x87, 0x21, 0x40, 0x91, 0x87, 0x21, 0x40, 
-0xf5, 0x87, 0x21, 0x40, 0x25, 0x88, 0x21, 0x40, 0x31, 0x88, 0x21, 0x40, 
-0xa5, 0x88, 0x21, 0x40, 0xaf, 0x88, 0x21, 0x40, 0xb9, 0x88, 0x21, 0x40, 
-0xc3, 0x88, 0x21, 0x40, 0xcd, 0x88, 0x21, 0x40, 0xd7, 0x88, 0x21, 0x40, 
-0xe1, 0x88, 0x21, 0x40, 0xeb, 0x88, 0x21, 0x40, 0xf5, 0x88, 0x21, 0x40, 
-0xe9, 0x8b, 0x21, 0x40, 0xff, 0x88, 0x21, 0x40, 0x09, 0x89, 0x21, 0x40, 
-0x13, 0x89, 0x21, 0x40, 0x1d, 0x89, 0x21, 0x40, 0x45, 0x89, 0x21, 0x40, 
-0x4f, 0x89, 0x21, 0x40, 0xb1, 0x89, 0x21, 0x40, 0xbb, 0x89, 0x21, 0x40, 
-0xc5, 0x89, 0x21, 0x40, 0xcf, 0x89, 0x21, 0x40, 0xd9, 0x89, 0x21, 0x40, 
-0xa5, 0x77, 0x21, 0x40, 0xe3, 0x89, 0x21, 0x40, 0x49, 0x8a, 0x21, 0x40, 
-0x95, 0x8a, 0x21, 0x40, 0xe1, 0x8a, 0x21, 0x40, 0xf1, 0x8a, 0x21, 0x40, 
-0xa5, 0x77, 0x21, 0x40, 0x3d, 0x8b, 0x21, 0x40, 0x41, 0x8b, 0x21, 0x40, 
-0x45, 0x8b, 0x21, 0x40, 0x9d, 0x8b, 0x21, 0x40, 0xc5, 0x8b, 0x21, 0x40, 
-0xd1, 0x8b, 0x21, 0x40, 0xd5, 0x8b, 0x21, 0x40, 0xd9, 0x8b, 0x21, 0x40, 
-0xdd, 0x8b, 0x21, 0x40, 0xe1, 0x8b, 0x21, 0x40, 0xe5, 0x8b, 0x21, 0x40, 
-0x0d, 0x88, 0x21, 0x40, 0x69, 0x88, 0x21, 0x40, 0xa5, 0x77, 0x21, 0x40, 
-0xa5, 0x77, 0x21, 0x40, 0xf5, 0x8b, 0x21, 0x40, 0xe1, 0xc9, 0x21, 0x40, 
-0xe9, 0x77, 0x21, 0x40, 0xa5, 0x77, 0x21, 0x40, 0xa5, 0x77, 0x21, 0x40, 
-0xdd, 0xca, 0x21, 0x40, 0x13, 0xcb, 0x21, 0x40, 0x45, 0xcb, 0x21, 0x40, 
-0x4d, 0x8c, 0x21, 0x40, 0x5b, 0x7b, 0x21, 0x40, 0xe5, 0x7e, 0x21, 0x40, 
-0x21, 0x7f, 0x21, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x01, 0x18, 0x40, 
-0x58, 0x01, 0x18, 0x40, 0x24, 0xa3, 0x20, 0x40, 0x24, 0xa7, 0x20, 0x40, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0x01, 0x18, 0x40, 
-0x68, 0x01, 0x18, 0x40, 0x24, 0x83, 0x20, 0x40, 0x24, 0xa3, 0x20, 0x40, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x01, 0x18, 0x40, 
-0x78, 0x01, 0x18, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8c, 0x01, 0x18, 0x40, 
-0x88, 0x01, 0x18, 0x40, 0x24, 0xa9, 0x20, 0x40, 0x24, 0xab, 0x20, 0x40, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x12, 0x00, 0x18, 0x00, 0x12, 0x00, 
-0x0c, 0x00, 0x12, 0x00, 0x1c, 0x00, 0x12, 0x00, 0x24, 0xa8, 0x20, 0x40, 
-0xa4, 0xa8, 0x20, 0x40, 0xa4, 0xa8, 0x20, 0x40, 0x24, 0xa9, 0x20, 0x40, 
-0x00, 0x00, 0x00, 0x00, 0xa5, 0xb9, 0x21, 0x40, 0x01, 0xbb, 0x21, 0x40, 
-0x00, 0x00, 0x00, 0x00, 0x91, 0x73, 0x21, 0x40, 0x19, 0xb2, 0x21, 0x40, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 
-0x00, 0x00, 0x00, 0x00, 0xa7, 0x99, 0x21, 0x40, 0xa5, 0xb9, 0x21, 0x40, 
-0xb1, 0x2f, 0xff, 0xff, 0xf1, 0x20, 0xff, 0xff, 0xdb, 0x20, 0xff, 0xff, 
-0x2d, 0xb8, 0x21, 0x40, 0x34, 0x2e, 0x00, 0x80, 0x48, 0x2e, 0x00, 0x80, 
-0x5c, 0x2e, 0x00, 0x80, 0x30, 0x33, 0x3a, 0x31, 0x31, 0x3a, 0x31, 0x31, 
-0x00, 0x30, 0x37, 0x2f, 0x32, 0x33, 0x2f, 0x30, 0x31, 0x00, 0x30, 0x30, 
-0x30, 0x30, 0x31, 0x35, 0x36, 0x39, 0x00, 0x43, 0x6f, 0x70, 0x79, 0x72, 
-0x69, 0x67, 0x68, 0x74, 0x20, 0x28, 0x63, 0x29, 0x20, 0x32, 0x30, 0x30, 
-0x31, 0x20, 0x33, 0x43, 0x6f, 0x6d, 0x20, 0x43, 0x6f, 0x72, 0x70, 0x6f, 
-0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x0a, 0x00, 0x02, 0x10, 0x00, 0x03, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-0x78, 0x53, 0xff, 0xff, 0x27, 0xf0, 0x7d, 0xfd, 0x00, 0x01, 0x00, 0x02, 
-0xda, 0x0e, 0x82, 0x00, 0x01, 0x40, 0x64, 0x04, 0x64, 0x2d, 0x00, 0x80, 
-0xe4, 0x2c, 0x00, 0x80, 0x55, 0x3e, 0xff, 0xff, 0xb5, 0x4f, 0xff, 0xff, 
-0xc1, 0x24, 0xff, 0xff, 0xb5, 0x3b, 0xff, 0xff, 0x15, 0x3c, 0xff, 0xff, 
-0x05, 0x1a, 0xff, 0xff, 0x65, 0x11, 0xff, 0xff, 0xb8, 0x53, 0xff, 0xff, 
-0x0d, 0x40, 0xff, 0xff, 0x91, 0x73, 0x21, 0x40, 0x51, 0x75, 0x21, 0x40, 
-0xc5, 0x3f, 0xff, 0xff, 0x71, 0xaa, 0x21, 0x40, 0x71, 0x24, 0xff, 0xff, 
-0x50, 0x53, 0xff, 0xff, 0x78, 0x53, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 
-0xff, 0xff, 0x00, 0x00, 0x80, 0x30, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 
-0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x20, 0x40, 0xec, 0x68, 0x00, 0x00, 
-0x10, 0x5c, 0x00, 0x00, 0x00, 0x6e, 0x21, 0x40, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 
-0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 
-0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 
-0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 
-0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 
-0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 
-0x08, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 
-0x0b, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, 
-0x0e, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x3d, 0x9a, 0x21, 0x40, 
-0xdb, 0x99, 0x21, 0x40, 0xf5, 0x9c, 0x21, 0x40, 0x55, 0x9d, 0x21, 0x40, 
-0x1d, 0x9e, 0x21, 0x40, 0xdb, 0x9b, 0x21, 0x40, 0xf9, 0x9e, 0x21, 0x40, 
-0x65, 0x9f, 0x21, 0x40, 0xb9, 0x9b, 0x21, 0x40, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 
 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x48, 0x05, 0x00, 0x80, 0x11, 0x75, 0x21, 0x40, 0x1b, 0x75, 0x21, 0x40, 
+0x31, 0x75, 0x21, 0x40, 0x49, 0x75, 0x21, 0x40, 
+0x55, 0x75, 0x21, 0x40, 0x63, 0x75, 0x21, 0x40, 0x7d, 0x75, 0x21, 0x40, 
+0xa9, 0x75, 0x21, 0x40, 0x6d, 0x76, 0x21, 0x40, 0xc5, 0x76, 0x21, 0x40, 
+0xd3, 0x76, 0x21, 0x40, 0xdd, 0x76, 0x21, 0x40, 0xe7, 0x76, 0x21, 0x40, 
+0x99, 0x77, 0x21, 0x40, 0xa7, 0x77, 0x21, 0x40, 0xb5, 0x77, 0x21, 0x40, 
+0x61, 0x78, 0x21, 0x40, 0x5f, 0x7c, 0x21, 0x40, 0xe9, 0x7c, 0x21, 0x40, 
+0x89, 0x7d, 0x21, 0x40, 0xbd, 0x7e, 0x21, 0x40, 0xc9, 0x7e, 0x21, 0x40, 
+0x29, 0x7f, 0x21, 0x40, 0x8d, 0x7f, 0x21, 0x40, 0xb9, 0x7f, 0x21, 0x40, 
+0xdd, 0x7f, 0x21, 0x40, 0x1d, 0x80, 0x21, 0x40, 0x45, 0x80, 0x21, 0x40, 
+0x8d, 0x80, 0x21, 0x40, 0x9d, 0x80, 0x21, 0x40, 0xc5, 0x80, 0x21, 0x40, 
+0xd5, 0x80, 0x21, 0x40, 0x1d, 0x81, 0x21, 0x40, 0x5b, 0x81, 0x21, 0x40, 
+0xb1, 0x81, 0x21, 0x40, 0x11, 0x82, 0x21, 0x40, 0x1b, 0x82, 0x21, 0x40, 
+0x1f, 0x82, 0x21, 0x40, 0x8d, 0x82, 0x21, 0x40, 0xd9, 0x82, 0x21, 0x40, 
+0x31, 0x83, 0x21, 0x40, 0x6d, 0x83, 0x21, 0x40, 0xd1, 0x83, 0x21, 0x40, 
+0x09, 0x84, 0x21, 0x40, 0x19, 0x84, 0x21, 0x40, 0x51, 0x84, 0x21, 0x40, 
+0x61, 0x84, 0x21, 0x40, 0x75, 0x84, 0x21, 0x40, 0x9d, 0x84, 0x21, 0x40, 
+0xa7, 0x84, 0x21, 0x40, 0xb1, 0x84, 0x21, 0x40, 0x15, 0x85, 0x21, 0x40, 
+0x45, 0x85, 0x21, 0x40, 0x51, 0x85, 0x21, 0x40, 0xc5, 0x85, 0x21, 0x40, 
+0xcf, 0x85, 0x21, 0x40, 0xd9, 0x85, 0x21, 0x40, 0xe3, 0x85, 0x21, 0x40, 
+0xed, 0x85, 0x21, 0x40, 0xf7, 0x85, 0x21, 0x40, 0x01, 0x86, 0x21, 0x40, 
+0x0b, 0x86, 0x21, 0x40, 0x15, 0x86, 0x21, 0x40, 0x01, 0x89, 0x21, 0x40, 
+0x1f, 0x86, 0x21, 0x40, 0x29, 0x86, 0x21, 0x40, 0x33, 0x86, 0x21, 0x40, 
+0x3d, 0x86, 0x21, 0x40, 0x65, 0x86, 0x21, 0x40, 0x6f, 0x86, 0x21, 0x40, 
+0xd1, 0x86, 0x21, 0x40, 0xdb, 0x86, 0x21, 0x40, 0xe5, 0x86, 0x21, 0x40, 
+0xef, 0x86, 0x21, 0x40, 0xf9, 0x86, 0x21, 0x40, 0x9d, 0x74, 0x21, 0x40, 
+0x03, 0x87, 0x21, 0x40, 0x69, 0x87, 0x21, 0x40, 0xb5, 0x87, 0x21, 0x40, 
+0xf9, 0x87, 0x21, 0x40, 0x09, 0x88, 0x21, 0x40, 0x9d, 0x74, 0x21, 0x40, 
+0x55, 0x88, 0x21, 0x40, 0x59, 0x88, 0x21, 0x40, 0x5d, 0x88, 0x21, 0x40, 
+0xb5, 0x88, 0x21, 0x40, 0xdd, 0x88, 0x21, 0x40, 0xe9, 0x88, 0x21, 0x40, 
+0xed, 0x88, 0x21, 0x40, 0xf1, 0x88, 0x21, 0x40, 0xf5, 0x88, 0x21, 0x40, 
+0xf9, 0x88, 0x21, 0x40, 0xfd, 0x88, 0x21, 0x40, 0x2d, 0x85, 0x21, 0x40, 
+0x89, 0x85, 0x21, 0x40, 0x9d, 0x74, 0x21, 0x40, 0x9d, 0x74, 0x21, 0x40, 
+0x0d, 0x89, 0x21, 0x40, 0x9d, 0x74, 0x21, 0x40, 0xe1, 0x74, 0x21, 0x40, 
+0x9d, 0x74, 0x21, 0x40, 0x9d, 0x74, 0x21, 0x40, 0x9d, 0x74, 0x21, 0x40, 
+0x9d, 0x74, 0x21, 0x40, 0x9d, 0x74, 0x21, 0x40, 0x9d, 0x74, 0x21, 0x40, 
+0x6b, 0x78, 0x21, 0x40, 0xf5, 0x7b, 0x21, 0x40, 0x31, 0x7c, 0x21, 0x40, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x5c, 0x01, 0x18, 0x40, 0x58, 0x01, 0x18, 0x40, 
+0x24, 0xa3, 0x20, 0x40, 0x24, 0xa7, 0x20, 0x40, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x6c, 0x01, 0x18, 0x40, 0x68, 0x01, 0x18, 0x40, 
+0x24, 0x83, 0x20, 0x40, 0x24, 0xa3, 0x20, 0x40, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x7c, 0x01, 0x18, 0x40, 0x78, 0x01, 0x18, 0x40, 
 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x8c, 0x01, 0x18, 0x40, 
+0x88, 0x01, 0x18, 0x40, 0x24, 0xa9, 0x20, 0x40, 0x24, 0xab, 0x20, 0x40, 
 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x08, 0x00, 0x12, 0x00, 0x18, 0x00, 0x12, 0x00, 0x0c, 0x00, 0x12, 0x00, 
+0x1c, 0x00, 0x12, 0x00, 0x24, 0xa8, 0x20, 0x40, 0xa4, 0xa8, 0x20, 0x40, 
+0xa4, 0xa8, 0x20, 0x40, 0x24, 0xa9, 0x20, 0x40, 0x00, 0x00, 0x00, 0x00, 
+0xd1, 0xa8, 0x21, 0x40, 0x2d, 0xaa, 0x21, 0x40, 0x00, 0x00, 0x00, 0x00, 
+0x89, 0x70, 0x21, 0x40, 0xc9, 0xa1, 0x21, 0x40, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x57, 0x89, 0x21, 0x40, 0xd1, 0xa8, 0x21, 0x40, 0xc5, 0x2f, 0xff, 0xff, 
+0x05, 0x21, 0xff, 0xff, 0xef, 0x20, 0xff, 0xff, 0x59, 0xa7, 0x21, 0x40, 
+0x34, 0x2e, 0x00, 0x80, 0x48, 0x2e, 0x00, 0x80, 0x5c, 0x2e, 0x00, 0x80, 
+0x30, 0x33, 0x3a, 0x31, 0x31, 0x3a, 0x31, 0x31, 0x00, 0x30, 0x37, 0x2f, 
+0x32, 0x33, 0x2f, 0x30, 0x31, 0x00, 0x30, 0x30, 0x30, 0x30, 0x31, 0x35, 
+0x36, 0x39, 0x00, 0x43, 0x6f, 0x70, 0x79, 0x72, 0x69, 0x67, 0x68, 0x74, 
+0x20, 0x28, 0x63, 0x29, 0x20, 0x32, 0x30, 0x30, 0x31, 0x20, 0x33, 0x43, 
+0x6f, 0x6d, 0x20, 0x43, 0x6f, 0x72, 0x70, 0x6f, 0x72, 0x61, 0x74, 0x69, 
+0x6f, 0x6e, 0x0a, 0x00, 0x08, 0x10, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8c, 0x53, 0xff, 0xff, 
+0x27, 0xf0, 0x7d, 0xfd, 0x00, 0x01, 0x00, 0x02, 0xda, 0x0e, 0x82, 0x00, 
+0x01, 0x40, 0x64, 0x04, 0x64, 0x2d, 0x00, 0x80, 0xe4, 0x2c, 0x00, 0x80, 
+0x69, 0x3e, 0xff, 0xff, 0xc9, 0x4f, 0xff, 0xff, 0xd5, 0x24, 0xff, 0xff, 
+0xc9, 0x3b, 0xff, 0xff, 0x29, 0x3c, 0xff, 0xff, 0x19, 0x1a, 0xff, 0xff, 
+0x65, 0x11, 0xff, 0xff, 0xcc, 0x53, 0xff, 0xff, 0x21, 0x40, 0xff, 0xff, 
+0x89, 0x70, 0x21, 0x40, 0x49, 0x72, 0x21, 0x40, 0xd9, 0x3f, 0xff, 0xff, 
+0x21, 0x9a, 0x21, 0x40, 0x85, 0x24, 0xff, 0xff, 0x64, 0x53, 0xff, 0xff, 
+0x8c, 0x53, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 
+0x80, 0x30, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 
+0x00, 0x00, 0x20, 0x40, 0xb0, 0x50, 0x00, 0x00, 0x7b, 0x0e, 0x00, 0x00, 
+0x00, 0x6e, 0x21, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0xed, 0x89, 0x21, 0x40, 0x8b, 0x89, 0x21, 0x40, 0xa5, 0x8c, 0x21, 0x40, 
+0x05, 0x8d, 0x21, 0x40, 0xcd, 0x8d, 0x21, 0x40, 0x8b, 0x8b, 0x21, 0x40, 
+0xa9, 0x8e, 0x21, 0x40, 0x15, 0x8f, 0x21, 0x40, 0x69, 0x8b, 0x21, 0x40, 
 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 
-0xe9, 0xd6, 0x21, 0x40, 0x00, 0x00, 0x00, 0x00, 0xb9, 0xcb, 0x21, 0x40, 
-0x55, 0xcd, 0x21, 0x40, 0x00, 0x00, 0x00, 0x00, 0x25, 0xd5, 0x21, 0x40, 
-0x8d, 0xd5, 0x21, 0x40, 0xf9, 0xd5, 0x21, 0x40, 0x09, 0x29, 0x09, 0xd1, 
-0x20, 0x28, 0x07, 0xd2, 0x04, 0x48, 0x01, 0x78, 0x00, 0x29, 0x03, 0xd1, 
-0x01, 0x21, 0x01, 0x70, 0x02, 0x48, 0x70, 0x47, 0x00, 0x20, 0xfc, 0xe7, 
-0x00, 0x6e, 0x21, 0x40, 0x24, 0xab, 0x20, 0x40, 0x03, 0x49, 0x88, 0x42, 
-0x03, 0xd1, 0x00, 0x20, 0x02, 0x49, 0xc0, 0x46, 0x08, 0x70, 0x70, 0x47, 
-0x24, 0xab, 0x20, 0x40, 0x00, 0x6e, 0x21, 0x40, 0x00, 0xb5, 0x00, 0x20, 
-0x0b, 0x4a, 0x0b, 0x23, 0x1b, 0x02, 0xd1, 0x18, 0x2d, 0x23, 0x9b, 0x01, 
-0xd3, 0x18, 0x88, 0x61, 0xd8, 0x60, 0xd8, 0x63, 0x80, 0x32, 0xc8, 0x60, 
-0x08, 0x61, 0x48, 0x61, 0xd0, 0x62, 0x05, 0x48, 0xc0, 0x46, 0x48, 0x60, 
-0x88, 0x60, 0x05, 0xf0, 0xcb, 0xfd, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 
-0x68, 0x0e, 0x00, 0x80, 0xfe, 0x03, 0x00, 0x00, 0xf0, 0xb5, 0x84, 0xb0, 
-0x0c, 0x1c, 0x05, 0x1c, 0x00, 0x23, 0x00, 0x93, 0xff, 0xf7, 0xda, 0xff, 
-0x68, 0x49, 0x0b, 0x23, 0x1b, 0x02, 0xcf, 0x18, 0x78, 0x68, 0x28, 0x40, 
+0x59, 0xbd, 0x21, 0x40, 0xc1, 0xbd, 0x21, 0x40, 0x2d, 0xbe, 0x21, 0x40, 
+0x00, 0x20, 0x0a, 0x4a, 0x0b, 0x23, 0x1b, 0x02, 0xd1, 0x18, 0x2d, 0x23, 
+0x9b, 0x01, 0xd3, 0x18, 0x88, 0x61, 0xd8, 0x60, 0xd8, 0x63, 0x80, 0x32, 
+0xc8, 0x60, 0x08, 0x61, 0x48, 0x61, 0xd0, 0x62, 0x03, 0x48, 0xc0, 0x46, 
+0x48, 0x60, 0x88, 0x60, 0x70, 0x47, 0x00, 0x00, 0x68, 0x0e, 0x00, 0x80, 
+0xfe, 0x03, 0x00, 0x00, 0xf0, 0xb5, 0x84, 0xb0, 0x0c, 0x1c, 0x05, 0x1c, 
+0x00, 0x23, 0x00, 0x93, 0xff, 0xf7, 0xde, 0xff, 0x68, 0x49, 0x0b, 0x23, 
+0x1b, 0x02, 0xcf, 0x18, 0x78, 0x68, 0x28, 0x40, 
 0x00, 0x22, 0xf8, 0x60, 0x3a, 0x61, 0xba, 0x68, 0x22, 0x40, 0x7a, 0x61, 
 0x0c, 0x1c, 0x41, 0x09, 0x03, 0xd2, 0x51, 0x09, 0x01, 0xd2, 0x80, 0x0a, 
 0x02, 0xd3, 0x60, 0x48, 0x00, 0xf0, 0xc2, 0xf8, 0x01, 0x20, 0xf9, 0x68, 
 0x49, 0x09, 0x03, 0xd2, 0x79, 0x69, 0x49, 0x09, 0x00, 0xd2, 0x00, 0x20, 
-0x00, 0x06, 0x00, 0x0e, 0x04, 0xf0, 0xc8, 0xf9, 0xf8, 0x68, 0x00, 0x28, 
+0x00, 0x06, 0x00, 0x0e, 0x03, 0xf0, 0xd4, 0xfa, 0xf8, 0x68, 0x00, 0x28, 
 0x70, 0xd0, 0x00, 0x23, 0x02, 0x93, 0x01, 0x93, 0x54, 0x4a, 0x01, 0x23, 
 0x18, 0x43, 0xf8, 0x60, 0x00, 0x20, 0xd5, 0x1d, 0x79, 0x35, 0x03, 0x95, 
 0x01, 0x24, 0x00, 0x21, 0x4f, 0x4d, 0xfa, 0x68, 0x22, 0x40, 0x39, 0xd0, 
@@ -2138,300 +2078,301 @@
 0x9b, 0x01, 0xc9, 0x18, 0xc8, 0x60, 0x00, 0x9b, 0x00, 0x2b, 0x0c, 0xd1, 
 0x81, 0x00, 0x89, 0x18, 0x0b, 0x23, 0x1b, 0x02, 0xc9, 0x18, 0xcb, 0x69, 
 0xc0, 0x46, 0x8b, 0x61, 0x01, 0x30, 0x0b, 0x28, 0xf4, 0xd3, 0x08, 0xe0, 
-0x07, 0xe0, 0x03, 0x9d, 0xe8, 0x6a, 0x30, 0x28, 
-0x03, 0xd2, 0x30, 0x20, 0x03, 0x9d, 0xc0, 0x46, 0xe8, 0x62, 0x19, 0x4a, 
-0x78, 0x69, 0x00, 0x28, 0x2a, 0xd0, 0x00, 0x21, 0x01, 0x23, 0x18, 0x43, 
-0x78, 0x61, 0x00, 0x20, 0x01, 0x24, 0x00, 0x22, 0x13, 0x4e, 0x7b, 0x69, 
-0x23, 0x40, 0x10, 0xd0, 0x93, 0x00, 0x9b, 0x18, 0x9b, 0x00, 0x12, 0x4d, 
-0x5b, 0x19, 0x9d, 0x78, 0x85, 0x42, 0x08, 0xd1, 0x1d, 0x69, 0x0b, 0x1c, 
-0x9b, 0x00, 0x9e, 0x19, 0x2d, 0x23, 0x9b, 0x01, 0xf3, 0x18, 0xdd, 0x63, 
-0x01, 0x31, 0x64, 0x00, 0x01, 0x32, 0x0b, 0x2a, 0xe6, 0xd3, 0x01, 0x30, 
-0x09, 0x28, 0xe1, 0xd3, 0x00, 0x20, 0x89, 0x00, 0x04, 0x4a, 0x89, 0x18, 
-0x2d, 0x23, 0x9b, 0x01, 0xc9, 0x18, 0xc8, 0x63, 0x04, 0xb0, 0xf0, 0xbc, 
-0x08, 0xbc, 0x18, 0x47, 0x68, 0x0e, 0x00, 0x80, 0x1c, 0x53, 0xff, 0xff, 
-0x00, 0x01, 0x00, 0x80, 0x00, 0x47, 0x08, 0x47, 0x10, 0x47, 0x18, 0x47, 
-0x78, 0x47, 0xc0, 0x46, 0x34, 0xc0, 0x9f, 0xe5, 0x1c, 0xff, 0x2f, 0xe1, 
-0x78, 0x47, 0xc0, 0x46, 0x2c, 0xc0, 0x9f, 0xe5, 0x1c, 0xff, 0x2f, 0xe1, 
-0x78, 0x47, 0xc0, 0x46, 0x24, 0xc0, 0x9f, 0xe5, 0x1c, 0xff, 0x2f, 0xe1, 
-0xc0, 0x46, 0xff, 0xb4, 0x75, 0x46, 0x20, 0xb4, 0x01, 0x21, 0x08, 0x43, 
-0x01, 0xa4, 0xa6, 0x46, 0x00, 0x47, 0xc0, 0x46, 0x20, 0xbc, 0xae, 0x46, 
-0xff, 0xbc, 0xf7, 0x46, 0x24, 0x52, 0xff, 0xff, 0x74, 0x51, 0xff, 0xff, 
-0x51, 0xc0, 0x21, 0x40, 0xf0, 0xb5, 0x04, 0x20, 0x1a, 0x49, 0x01, 0x25, 
-0x08, 0x60, 0x1a, 0x4f, 0xbb, 0x23, 0x1b, 0x01, 0xf8, 0x18, 0x05, 0x73, 
-0x18, 0x48, 0x41, 0x6b, 0x2c, 0x05, 0x00, 0x20, 0x7a, 0x6e, 0x17, 0x4b, 
-0x8a, 0x42, 0x1d, 0xd0, 0x19, 0x7b, 0x00, 0x29, 0x17, 0xd1, 0xd9, 0x1d, 
-0xff, 0x31, 0x3a, 0x31, 0x49, 0x78, 0x1e, 0x1c, 0x00, 0x29, 0x10, 0xd1, 
-0xb0, 0x60, 0x10, 0x20, 0x70, 0x60, 0x10, 0x4a, 0x10, 0x49, 0xff, 0xf7, 
-0xb5, 0xff, 0x00, 0x28, 0x07, 0xd0, 0x35, 0x73, 0x04, 0x23, 0xb8, 0x69, 
-0x18, 0x43, 0xb8, 0x61, 0x20, 0x61, 0x00, 0xf0, 0x17, 0xf8, 0xf0, 0xbc, 
-0x08, 0xbc, 0x18, 0x47, 0x18, 0x73, 0x04, 0x23, 0xb8, 0x69, 0x98, 0x43, 
-0xb8, 0x61, 0x20, 0x61, 0xf5, 0xe7, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 
-0x68, 0x0e, 0x00, 0x80, 0x00, 0x01, 0x18, 0x40, 0x28, 0x05, 0x00, 0x80, 
-0x0c, 0x55, 0xff, 0xff, 0x85, 0x74, 0x21, 0x40, 0xf8, 0xb5, 0x15, 0x4f, 
-0x39, 0x6c, 0x15, 0x48, 0x40, 0x6e, 0x0c, 0x1a, 0x14, 0x4e, 0x71, 0x68, 
-0x14, 0x4d, 0xa1, 0x42, 0x06, 0xd8, 0x14, 0x4a, 0x0a, 0x43, 0x00, 0x92, 
-0xb9, 0x6b, 0x09, 0x18, 0xfa, 0x6b, 0x11, 0xe0, 0x11, 0x22, 0x52, 0x05, 
-0x22, 0x43, 0x00, 0x92, 0xb9, 0x6b, 0x09, 0x18, 0x00, 0x20, 0xfa, 0x6b, 
-0x2b, 0x1c, 0xff, 0xf7, 0x7f, 0xff, 0x70, 0x68, 0x00, 0x1b, 0x0a, 0x4a, 
-0x02, 0x43, 0x00, 0x92, 0xb9, 0x6b, 0xfa, 0x6b, 0x00, 0x20, 0x2b, 0x1c, 
-0xff, 0xf7, 0x74, 0xff, 0xf8, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 
-0x7c, 0x29, 0x00, 0x80, 0x68, 0x0e, 0x00, 0x80, 0x28, 0x05, 0x00, 0x80, 
-0x44, 0x80, 0x20, 0x40, 0x00, 0x00, 0x37, 0x02, 0xf0, 0xb5, 0x2b, 0x4f, 
-0xb8, 0x68, 0x79, 0x68, 0xc0, 0x19, 0x20, 0x30, 0x29, 0x4a, 0xff, 0xf7, 
-0x55, 0xff, 0x01, 0x20, 0xc0, 0x02, 0x28, 0x49, 0xc0, 0x46, 0x08, 0x60, 
-0xb9, 0x68, 0x38, 0x1c, 0x26, 0x4d, 0x00, 0x24, 0x26, 0x4e, 0xef, 0x1d, 
-0x79, 0x37, 0x00, 0x29, 0x31, 0xd1, 0x31, 0x68, 0x0a, 0x78, 0x12, 0x0a, 
-0x03, 0xd2, 0x04, 0x73, 0xf0, 0xbc, 0x08, 0xbc, 
-0x18, 0x47, 0x49, 0x78, 0x00, 0x29, 0x0c, 0xd1, 0x05, 0x1c, 0x40, 0x68, 
-0x00, 0xf0, 0x3e, 0xf9, 0x30, 0x68, 0x00, 0xf0, 0x67, 0xf8, 0x00, 0x28, 
-0x26, 0xd1, 0x2c, 0x73, 0xff, 0xf7, 0x58, 0xff, 0x22, 0xe0, 0x09, 0x01, 
-0x07, 0x1c, 0x41, 0x60, 0x08, 0x1c, 0x17, 0x4a, 0x17, 0x49, 0xff, 0xf7, 
-0x27, 0xff, 0x00, 0x28, 0x07, 0xd1, 0x3c, 0x73, 0x04, 0x23, 0xa8, 0x69, 
-0x98, 0x43, 0x99, 0x04, 0xa8, 0x61, 0x08, 0x61, 0xda, 0xe7, 0x10, 0x20, 
-0x00, 0xf0, 0x20, 0xf9, 0x10, 0x20, 0xb8, 0x60, 0xff, 0xf7, 0x82, 0xff, 
-0xd2, 0xe7, 0x05, 0x1c, 0x40, 0x68, 0x00, 0xf0, 0x17, 0xf9, 0x30, 0x68, 
-0x00, 0xf0, 0x40, 0xf8, 0x00, 0x28, 0xd8, 0xd0, 0x02, 0x23, 0xf8, 0x6b, 
-0x18, 0x43, 0xf8, 0x63, 0xc4, 0xe7, 0x00, 0x00, 0x28, 0x05, 0x00, 0x80, 
-0x91, 0x55, 0xff, 0xff, 0x00, 0x00, 0x00, 0xb0, 0x68, 0x0e, 0x00, 0x80, 
-0xe4, 0x01, 0x00, 0x80, 0x0c, 0x55, 0xff, 0xff, 0x85, 0x74, 0x21, 0x40, 
-0x90, 0xb5, 0x01, 0x20, 0x40, 0x03, 0x10, 0x49, 0x00, 0x27, 0x08, 0x60, 
-0x0f, 0x4c, 0xe0, 0x1d, 0xff, 0x30, 0x3a, 0x30, 0x47, 0x70, 0xe0, 0x69, 
-0x80, 0x00, 0x00, 0x19, 0x00, 0x69, 0x00, 0xf0, 0xd7, 0xf8, 0xe0, 0x69, 
-0x00, 0x28, 0x01, 0xd0, 0xe7, 0x61, 0x01, 0xe0, 0x01, 0x20, 0xe0, 0x61, 
-0x07, 0x48, 0x02, 0x23, 0xc1, 0x6b, 0x19, 0x43, 0xc1, 0x63, 0x27, 0x73, 
-0xff, 0xf7, 0x00, 0xff, 0x90, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 
-0x00, 0x00, 0x00, 0xb0, 0x28, 0x05, 0x00, 0x80, 0xe8, 0x0e, 0x00, 0x80, 
-0x80, 0xb5, 0x84, 0xb0, 0x07, 0x1c, 0x78, 0x88, 0x6d, 0x28, 0x03, 0xdb, 
-0x38, 0x1c, 0x00, 0xf0, 0xf7, 0xf8, 0x17, 0xe0, 0x80, 0x00, 0x0d, 0x49, 
-0x09, 0x58, 0x38, 0x1c, 0xff, 0xf7, 0xbd, 0xfe, 0x00, 0x28, 0x0f, 0xd1, 
-0x39, 0x78, 0xc9, 0x09, 0x0c, 0xd3, 0x69, 0x46, 0x38, 0x1c, 0x00, 0xf0, 
-0xcf, 0xf8, 0x68, 0x46, 0x00, 0x21, 0x00, 0xf0, 0x0b, 0xf8, 0x00, 0x28, 
-0x01, 0xd1, 0x01, 0x20, 0x00, 0xe0, 0x00, 0x20, 0x04, 0xb0, 0x80, 0xbc, 
-0x08, 0xbc, 0x18, 0x47, 0xe8, 0x01, 0x00, 0x80, 0xf0, 0xb5, 0x82, 0xb0, 
-0x02, 0x1c, 0x41, 0x4b, 0xdd, 0x1d, 0xff, 0x35, 0x3a, 0x35, 0x2f, 0x78, 
-0x00, 0x2f, 0x01, 0xd0, 0x00, 0x27, 0x00, 0xe0, 0x01, 0x27, 0x2f, 0x70, 
-0x2f, 0x78, 0xfb, 0x00, 0xdb, 0x19, 0x5b, 0x01, 0x3a, 0x4f, 0xdc, 0x19, 
-0x40, 0x78, 0x00, 0x01, 0xc7, 0x1d, 0x09, 0x37, 0x00, 0x20, 0x83, 0x00, 
-0xd6, 0x58, 0xc0, 0x46, 0xe6, 0x50, 0x01, 0x30, 0x04, 0x28, 0xf8, 0xd3, 
-0x00, 0x29, 0x0f, 0xd0, 0x00, 0x22, 0xbb, 0x08, 0x01, 0x93, 0x83, 0x42, 
-0x0b, 0xd9, 0x13, 0x1c, 0x9b, 0x00, 0xcb, 0x58, 0x86, 0x00, 0xa3, 0x51, 
-0x01, 0x9b, 0x01, 0x30, 0x01, 0x32, 0x83, 0x42, 0xf5, 0xd8, 0x00, 0xe0, 
-0x10, 0x27, 0x2b, 0x48, 0x02, 0x6d, 0x80, 0x6e, 0x2a, 0x49, 0x82, 0x42, 
-0x03, 0xd8, 0x82, 0x1a, 0xcb, 0x6c, 0x9a, 0x1a, 0x00, 0xe0, 0x12, 0x1a, 
-0xba, 0x42, 0x05, 0xd8, 0x26, 0x48, 0x81, 0x6b, 0x01, 0x31, 0x81, 0x63, 
-0x01, 0x20, 0x37, 0xe0, 0xc3, 0x19, 0xca, 0x6c, 0x93, 0x42, 0x08, 0xd8, 
-0x22, 0x4a, 0x3a, 0x43, 0x00, 0x92, 0x0a, 0x1c, 0x49, 0x6c, 0x09, 0x18, 
-0x92, 0x6c, 0x23, 0x1c, 0x12, 0xe0, 0x16, 0x1a, 0x00, 0x96, 0x1b, 0x49, 
-0x49, 0x6c, 0x09, 0x18, 0x19, 0x48, 0x82, 0x6c, 0x03, 0x20, 0x23, 0x1c, 
-0xff, 0xf7, 0x50, 0xfe, 0xb8, 0x1b, 0x18, 0x4a, 0x02, 0x43, 0x00, 0x92, 
-0xa3, 0x19, 0x14, 0x48, 0x82, 0x6c, 0x41, 0x6c, 
-0x03, 0x20, 0xff, 0xf7, 0x45, 0xfe, 0x01, 0x20, 0x0d, 0x49, 0xc0, 0x46, 
-0x68, 0x70, 0x8a, 0x69, 0x92, 0x00, 0x52, 0x18, 0x17, 0x61, 0x8a, 0x69, 
-0x00, 0x2a, 0x02, 0xd0, 0x00, 0x27, 0x8f, 0x61, 0x00, 0xe0, 0x88, 0x61, 
-0x0c, 0x48, 0x02, 0x23, 0xc1, 0x6b, 0x19, 0x43, 0xc1, 0x63, 0x00, 0x20, 
-0x01, 0x27, 0x0a, 0x49, 0xc0, 0x46, 0x4f, 0x73, 0x02, 0xb0, 0xf0, 0xbc, 
-0x08, 0xbc, 0x18, 0x47, 0x28, 0x05, 0x00, 0x80, 0xfc, 0xba, 0x20, 0x40, 
-0x68, 0x0e, 0x00, 0x80, 0x7c, 0x29, 0x00, 0x80, 0xa0, 0x82, 0x20, 0x40, 
-0x00, 0x00, 0x19, 0x02, 0xe8, 0x0e, 0x00, 0x80, 0x18, 0x1a, 0x00, 0x80, 
-0x07, 0x49, 0x8a, 0x6e, 0x10, 0x18, 0x07, 0x4a, 0xd2, 0x6c, 0x13, 0x04, 
-0x1b, 0x0c, 0x83, 0x42, 0x00, 0xd8, 0x80, 0x1a, 0x88, 0x66, 0x88, 0x6e, 
-0x03, 0x49, 0xc0, 0x46, 0x48, 0x61, 0x70, 0x47, 0x68, 0x0e, 0x00, 0x80, 
-0x7c, 0x29, 0x00, 0x80, 0x3c, 0xef, 0x20, 0x40, 0x06, 0x49, 0x4a, 0x6e, 
-0x10, 0x18, 0x06, 0x4a, 0x12, 0x6c, 0x82, 0x42, 0x00, 0xd8, 0x80, 0x1a, 
-0x48, 0x66, 0x48, 0x6e, 0x03, 0x49, 0xc0, 0x46, 0x08, 0x61, 0x70, 0x47, 
-0x68, 0x0e, 0x00, 0x80, 0x7c, 0x29, 0x00, 0x80, 0x3c, 0xef, 0x20, 0x40, 
-0x05, 0x22, 0x0a, 0x60, 0x82, 0x88, 0xc0, 0x46, 0x8a, 0x80, 0x00, 0x22, 
-0x4a, 0x70, 0x40, 0x88, 0xc0, 0x46, 0x48, 0x80, 0xca, 0x80, 0x8a, 0x60, 
-0xca, 0x60, 0x70, 0x47, 0x05, 0x22, 0x02, 0x60, 0x00, 0x22, 0x82, 0x80, 
-0x42, 0x70, 0x41, 0x80, 0xc2, 0x80, 0x82, 0x60, 0xc2, 0x60, 0x70, 0x47, 
-0x80, 0xb5, 0x84, 0xb0, 0x07, 0x1c, 0x0e, 0x48, 0x41, 0x6b, 0x01, 0x31, 
-0x41, 0x63, 0x69, 0x46, 0x38, 0x1c, 0xff, 0xf7, 0xdd, 0xff, 0x38, 0x68, 
-0xc0, 0x46, 0x00, 0x90, 0x45, 0x20, 0x00, 0xab, 0x18, 0x70, 0x01, 0x27, 
-0xdf, 0x80, 0x68, 0x46, 0x00, 0x21, 0xff, 0xf7, 0x11, 0xff, 0x00, 0x28, 
-0x01, 0xd1, 0x38, 0x1c, 0x00, 0xe0, 0x00, 0x20, 0x04, 0xb0, 0x80, 0xbc, 
-0x08, 0xbc, 0x18, 0x47, 0xa0, 0x82, 0x20, 0x40, 0x00, 0xb5, 0x84, 0xb0, 
-0xc1, 0x88, 0x09, 0x4a, 0xc0, 0x46, 0x91, 0x81, 0x69, 0x46, 0xff, 0xf7, 
-0xbd, 0xff, 0x01, 0x20, 0x40, 0x02, 0x01, 0xab, 0x58, 0x80, 0x68, 0x46, 
-0x00, 0x21, 0xff, 0xf7, 0xf5, 0xfe, 0x01, 0x20, 0x04, 0xb0, 0x08, 0xbc, 
-0x18, 0x47, 0x00, 0x00, 0xe8, 0x0e, 0x00, 0x80, 0x00, 0xb5, 0xff, 0xf7, 
-0xc3, 0xff, 0x08, 0xbc, 0x18, 0x47, 0x01, 0x20, 0x03, 0x49, 0xc0, 0x46, 
-0x08, 0x71, 0xa1, 0x21, 0x49, 0x03, 0x88, 0x60, 0x00, 0x20, 0x70, 0x47, 
-0x28, 0x0f, 0x00, 0x80, 0x00, 0x20, 0x04, 0x49, 0xc0, 0x46, 0x08, 0x71, 
-0xff, 0x21, 0xa1, 0x22, 0x52, 0x03, 0x01, 0x31, 0x91, 0x60, 0x70, 0x47, 
-0x28, 0x0f, 0x00, 0x80, 0x02, 0x20, 0xa1, 0x21, 0x49, 0x03, 0x88, 0x60, 
-0x00, 0x20, 0x70, 0x47, 0x01, 0x20, 0x40, 0x02, 0xa1, 0x21, 0x49, 0x03, 
-0x88, 0x60, 0x00, 0x20, 0x70, 0x47, 0xc0, 0x88, 0xc0, 0x06, 0xc0, 0x0e, 
-0xa1, 0x21, 0x49, 0x03, 0x48, 0x61, 0x02, 0x49, 0xc0, 0x46, 0xc8, 0x63, 
-0x00, 0x20, 0x70, 0x47, 0xe8, 0x1a, 0x00, 0x80, 0x80, 0xb5, 0x84, 0xb0, 
-0x08, 0x49, 0x0f, 0x6b, 0x69, 0x46, 0xff, 0xf7, 0x71, 0xff, 0xf8, 0x06, 
-0xc0, 0x0e, 0x01, 0xab, 0x58, 0x80, 0x68, 0x46, 0x00, 0x21, 0xff, 0xf7, 
-0xa9, 0xfe, 0x01, 0x20, 0x04, 0xb0, 0x80, 0xbc, 0x08, 0xbc, 0x18, 0x47, 
-0x80, 0x00, 0x14, 0x40, 0x80, 0xb5, 0x85, 0xb0, 0x07, 0x1c, 0x69, 0x46, 
-0x38, 0x1c, 0xff, 0xf7, 0x5b, 0xff, 0xf8, 0x88, 
-0x04, 0xa9, 0x05, 0xf0, 0xf7, 0xf9, 0x01, 0xab, 0x58, 0x80, 0x01, 0xa8, 
-0x40, 0x88, 0x00, 0x28, 0x0f, 0xd0, 0x01, 0xa8, 0x40, 0x88, 0x80, 0x08, 
-0x03, 0x38, 0x80, 0x08, 0x01, 0x30, 0x04, 0x3b, 0x58, 0x70, 0x04, 0x98, 
-0x01, 0x68, 0xc0, 0x46, 0x02, 0x91, 0x40, 0x68, 0xc0, 0x46, 0x03, 0x90, 
-0x05, 0xe0, 0x00, 0xa8, 0x00, 0x78, 0x40, 0x23, 0x18, 0x43, 0x00, 0xab, 
-0x18, 0x70, 0x04, 0x98, 0xc1, 0x1d, 0x01, 0x31, 0x68, 0x46, 0xff, 0xf7, 
-0x75, 0xfe, 0x01, 0x20, 0x05, 0xb0, 0x80, 0xbc, 0x08, 0xbc, 0x18, 0x47, 
-0x90, 0xb5, 0x84, 0xb0, 0x14, 0x4f, 0x39, 0x7b, 0x00, 0x29, 0x20, 0xd1, 
-0xf9, 0x1d, 0xff, 0x31, 0x3a, 0x31, 0x49, 0x78, 0x00, 0x29, 0x1a, 0xd1, 
-0x10, 0x49, 0x05, 0x22, 0x00, 0x92, 0x08, 0x22, 0x00, 0xab, 0x5a, 0x80, 
-0x98, 0x80, 0x06, 0x20, 0x00, 0xab, 0x58, 0x70, 0x00, 0x24, 0xdc, 0x80, 
-0x08, 0x68, 0xc0, 0x46, 0x02, 0x90, 0x48, 0x68, 0xc0, 0x46, 0x03, 0x90, 
-0x01, 0x20, 0x38, 0x73, 0x68, 0x46, 0x08, 0x31, 0xff, 0xf7, 0x4c, 0xfe, 
-0x00, 0x28, 0x00, 0xd0, 0x3c, 0x73, 0x04, 0xb0, 0x90, 0xbc, 0x08, 0xbc, 
-0x18, 0x47, 0x00, 0x00, 0x28, 0x05, 0x00, 0x80, 0xa4, 0x2a, 0x00, 0x80, 
-0x90, 0xb5, 0x84, 0xb0, 0x07, 0x1c, 0x69, 0x46, 0x38, 0x1c, 0xff, 0xf7, 
-0xf9, 0xfe, 0xba, 0x68, 0x0d, 0x4c, 0x0e, 0x48, 0x00, 0x2a, 0x05, 0xd1, 
-0x0d, 0x49, 0xff, 0xf7, 0xd6, 0xfc, 0x00, 0x28, 0x0c, 0xda, 0x05, 0xe0, 
-0xb9, 0x88, 0x0b, 0x4b, 0xff, 0xf7, 0xd1, 0xfc, 0x00, 0x28, 0x05, 0xda, 
-0x01, 0xab, 0x5c, 0x80, 0x68, 0x46, 0x00, 0x21, 0xff, 0xf7, 0x22, 0xfe, 
-0x00, 0x20, 0x04, 0xb0, 0x90, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 
-0xff, 0xff, 0x00, 0x00, 0x15, 0x79, 0x21, 0x40, 0x8d, 0xd5, 0x21, 0x40, 
-0x25, 0xd5, 0x21, 0x40, 0x00, 0xb5, 0xc0, 0x88, 0x05, 0xf0, 0x5c, 0xf9, 
-0x00, 0x20, 0x08, 0xbc, 0x18, 0x47, 0x00, 0xb5, 0xff, 0xf7, 0xe2, 0xfe, 
-0x08, 0xbc, 0x18, 0x47, 0x00, 0xb5, 0xff, 0xf7, 0xdd, 0xfe, 0x08, 0xbc, 
-0x18, 0x47, 0x00, 0xb5, 0x01, 0x1c, 0x02, 0x20, 0x00, 0xf0, 0x02, 0xf8, 
-0x08, 0xbc, 0x18, 0x47, 0xb0, 0xb5, 0xc6, 0xb0, 0x04, 0x1c, 0x08, 0x1c, 
-0x69, 0x46, 0xff, 0xf7, 0xb5, 0xfe, 0x1c, 0x48, 0xff, 0xf7, 0x96, 0xfc, 
-0x07, 0x1c, 0x1b, 0x4a, 0x00, 0x21, 0x20, 0x1c, 0xff, 0xf7, 0x92, 0xfc, 
-0x00, 0x28, 0x1d, 0xd0, 0x04, 0xa9, 0x18, 0x4a, 0x20, 0x1c, 0xff, 0xf7, 
-0x8b, 0xfc, 0x04, 0x98, 0x04, 0x28, 0x05, 0xd9, 0x04, 0x98, 0x80, 0x08, 
-0x03, 0x38, 0x80, 0x08, 0x01, 0x30, 0x00, 0xe0, 0x00, 0x20, 0x00, 0xab, 
-0x58, 0x70, 0x06, 0xa8, 0x00, 0x78, 0xc0, 0x46, 0xd8, 0x80, 0x04, 0x98, 
-0xc0, 0x46, 0x02, 0x90, 0x07, 0x98, 0xc0, 0x46, 0x03, 0x90, 0x04, 0x33, 
-0x08, 0xad, 0x02, 0xe0, 0x45, 0x20, 0x00, 0xab, 0x18, 0x70, 0x09, 0x49, 
-0x38, 0x1c, 0xff, 0xf7, 0x6a, 0xfc, 0x68, 0x46, 0x29, 0x1c, 0xff, 0xf7, 
-0xc1, 0xfd, 0x01, 0x20, 0x46, 0xb0, 0xb0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 
-0x24, 0x02, 0xff, 0xff, 0xcd, 0xc0, 0x21, 0x40, 0x29, 0xbf, 0x21, 0x40, 
-0x3c, 0x02, 0xff, 0xff, 0x00, 0xb5, 0x01, 0x1c, 0x02, 0x20, 0x00, 0xf0, 
-0x10, 0xf8, 0x08, 0xbc, 0x18, 0x47, 0x00, 0xb5, 0x01, 0x1c, 0x01, 0x20, 
-0xff, 0xf7, 0xac, 0xff, 0x08, 0xbc, 0x18, 0x47, 0x00, 0xb5, 0x01, 0x1c, 
-0x01, 0x20, 0x00, 0xf0, 0x02, 0xf8, 0x08, 0xbc, 0x18, 0x47, 0xf3, 0xb5, 
-0xc6, 0xb0, 0x0f, 0x1c, 0x69, 0x46, 0x38, 0x1c, 
-0xff, 0xf7, 0x58, 0xfe, 0x20, 0x48, 0xff, 0xf7, 0x39, 0xfc, 0x04, 0x1c, 
-0x78, 0x78, 0x00, 0x01, 0xba, 0x68, 0x04, 0x30, 0xfc, 0x2a, 0x23, 0xd8, 
-0xff, 0x23, 0x09, 0x33, 0x98, 0x42, 0x1f, 0xd8, 0xfd, 0x88, 0xf8, 0x68, 
-0xc0, 0x46, 0x04, 0x90, 0x05, 0xa9, 0xfb, 0x1d, 0x09, 0x33, 0x00, 0x20, 
-0x7e, 0x78, 0x00, 0x2e, 0x0d, 0xdd, 0x40, 0xcb, 0x40, 0xc1, 0x40, 0xcb, 
-0x40, 0xc1, 0x40, 0xcb, 0x40, 0xc1, 0x40, 0xcb, 0x40, 0xc1, 0x01, 0x30, 
-0x00, 0x04, 0x00, 0x0c, 0x7e, 0x78, 0x86, 0x42, 0xf1, 0xdc, 0x46, 0x98, 
-0x04, 0xa9, 0x2b, 0x1c, 0xff, 0xf7, 0x20, 0xfc, 0x00, 0x28, 0x05, 0xd0, 
-0x00, 0xa8, 0x00, 0x78, 0x40, 0x23, 0x18, 0x43, 0x00, 0xab, 0x18, 0x70, 
-0x07, 0x49, 0x20, 0x1c, 0xff, 0xf7, 0x05, 0xfc, 0x68, 0x46, 0x00, 0x21, 
-0xff, 0xf7, 0x5c, 0xfd, 0x01, 0x20, 0x48, 0xb0, 0xf0, 0xbc, 0x08, 0xbc, 
-0x18, 0x47, 0x00, 0x00, 0x24, 0x02, 0xff, 0xff, 0x3c, 0x02, 0xff, 0xff, 
-0x00, 0xb5, 0xff, 0xf7, 0x27, 0xfe, 0x08, 0xbc, 0x18, 0x47, 0xf0, 0xb5, 
-0xc6, 0xb0, 0x07, 0x1c, 0xfc, 0x88, 0x25, 0x4d, 0x68, 0x68, 0x01, 0x30, 
-0x69, 0x46, 0x68, 0x60, 0x38, 0x1c, 0xff, 0xf7, 0x01, 0xfe, 0x10, 0x2c, 
-0x08, 0xd3, 0x00, 0xa8, 0x00, 0x78, 0x40, 0x23, 0x18, 0x43, 0x00, 0xab, 
-0x18, 0x70, 0x02, 0x20, 0xd8, 0x80, 0x17, 0xe0, 0x78, 0x78, 0x82, 0x00, 
-0xfb, 0x1d, 0x09, 0x33, 0x00, 0x20, 0xb9, 0x68, 0x00, 0x2a, 0x15, 0xd9, 
-0x40, 0xcb, 0x0f, 0x1c, 0x01, 0x31, 0xbe, 0x42, 0x0d, 0xd0, 0x00, 0xaa, 
-0x12, 0x78, 0x40, 0x23, 0x1a, 0x43, 0x00, 0xab, 0x1a, 0x70, 0x04, 0x22, 
-0xda, 0x80, 0x02, 0x90, 0x03, 0x91, 0x04, 0x33, 0x68, 0x46, 0x00, 0x21, 
-0x15, 0xe0, 0x01, 0x30, 0x90, 0x42, 0xe9, 0xd3, 0x00, 0xab, 0x5c, 0x70, 
-0x02, 0x94, 0x69, 0x68, 0xc0, 0x46, 0x03, 0x91, 0xa2, 0x00, 0x00, 0x20, 
-0x10, 0x33, 0x00, 0x2a, 0x05, 0xd9, 0x0f, 0x1c, 0x80, 0xc3, 0x01, 0x30, 
-0x01, 0x31, 0x90, 0x42, 0xf9, 0xd3, 0x68, 0x46, 0x04, 0xa9, 0xff, 0xf7, 
-0x03, 0xfd, 0x01, 0x20, 0x46, 0xb0, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 
-0x9c, 0x03, 0x00, 0x80, 0x90, 0xb4, 0x23, 0x48, 0x00, 0x68, 0x01, 0x21, 
-0x42, 0x09, 0x00, 0xd3, 0x00, 0x21, 0x00, 0x27, 0x3a, 0x1c, 0x43, 0x0b, 
-0x00, 0xd2, 0x02, 0x22, 0x11, 0x43, 0x1e, 0x4a, 0x20, 0x24, 0xd3, 0x68, 
-0x01, 0x2b, 0x2e, 0xd1, 0x80, 0x0a, 0x00, 0xd2, 0x00, 0x24, 0x0c, 0x43, 
-0x20, 0x1c, 0x1b, 0x23, 0xdb, 0x01, 0xd1, 0x18, 0x89, 0x8b, 0x09, 0x0b, 
-0x00, 0xd2, 0x04, 0x27, 0x38, 0x43, 0xd1, 0x6f, 0x09, 0x68, 0x09, 0x0a, 
-0x07, 0xd2, 0xd1, 0x1d, 0x79, 0x31, 0x09, 0x68, 0x09, 0x68, 0x09, 0x0a, 
-0x01, 0xd3, 0x08, 0x23, 0x18, 0x43, 0xe3, 0x23, 0x1b, 0x01, 0xd1, 0x18, 
-0x89, 0x79, 0x03, 0x29, 0x02, 0xd1, 0xff, 0x23, 0x01, 0x33, 0x18, 0x43, 
-0x0b, 0x49, 0x09, 0x6a, 0x10, 0x22, 0x4b, 0x0a, 0x00, 0xd2, 0x00, 0x22, 
-0x10, 0x43, 0x89, 0x07, 0x89, 0x0f, 0x89, 0x01, 0x08, 0x43, 0x90, 0xbc, 
-0x70, 0x47, 0x40, 0x0c, 0x00, 0xd2, 0x00, 0x24, 0x0c, 0x43, 0x20, 0x1c, 
-0xec, 0xe7, 0x00, 0x00, 0x00, 0x00, 0x10, 0x40, 0x68, 0x0e, 0x00, 0x80, 
-0xc0, 0x00, 0x18, 0x40, 0xf0, 0xb5, 0x3a, 0x4c, 0x20, 0x1c, 0x05, 0xf0, 
-0x75, 0xfc, 0x39, 0x48, 0xe3, 0x23, 0x1b, 0x01, 0xc7, 0x18, 0xb9, 0x79, 
-0x37, 0x4e, 0xc5, 0x1d, 0x79, 0x35, 0x06, 0x29, 0x62, 0xd2, 0x02, 0xa3, 
-0x5b, 0x5c, 0x5b, 0x00, 0x9f, 0x44, 0x00, 0x1c, 
-0x03, 0x0e, 0x1e, 0x37, 0x4e, 0x55, 0x01, 0x20, 0xb8, 0x71, 0x00, 0x20, 
-0xb0, 0x60, 0xff, 0xf7, 0x95, 0xff, 0x05, 0x23, 0x98, 0x43, 0x00, 0xf0, 
-0x6f, 0xf8, 0x0c, 0xe0, 0xff, 0xf7, 0x8e, 0xff, 0xc0, 0x08, 0x06, 0xd3, 
-0xb0, 0x68, 0x41, 0x1c, 0xb1, 0x60, 0x0a, 0x28, 0x03, 0xd9, 0x04, 0x20, 
-0x00, 0xe0, 0x02, 0x20, 0xb8, 0x71, 0x64, 0x22, 0x20, 0x1c, 0x2b, 0xe0, 
-0x06, 0x1c, 0xc0, 0x6f, 0x80, 0x23, 0x01, 0x68, 0x19, 0x43, 0x01, 0x60, 
-0x03, 0x20, 0xb8, 0x71, 0x20, 0x1c, 0x20, 0x4a, 0x00, 0x21, 0x05, 0xf0, 
-0x07, 0xfc, 0xf0, 0x6f, 0x04, 0x23, 0x01, 0x68, 0x99, 0x43, 0x01, 0x60, 
-0x28, 0x68, 0x01, 0x68, 0x19, 0x43, 0x01, 0x60, 0xf0, 0xbc, 0x08, 0xbc, 
-0x18, 0x47, 0x05, 0x21, 0xb9, 0x71, 0x29, 0x68, 0x04, 0x23, 0x0a, 0x68, 
-0x9a, 0x43, 0x0a, 0x60, 0xc0, 0x6f, 0x01, 0x68, 0x19, 0x43, 0x01, 0x60, 
-0xff, 0xf7, 0x5a, 0xff, 0x08, 0x23, 0x18, 0x43, 0x00, 0xf0, 0x34, 0xf8, 
-0x20, 0x1c, 0x10, 0x4a, 0x00, 0x21, 0x05, 0xf0, 0xe5, 0xfb, 0xe5, 0xe7, 
-0xff, 0xf7, 0x4e, 0xff, 0x04, 0x23, 0x18, 0x43, 0x00, 0xf0, 0x28, 0xf8, 
-0xde, 0xe7, 0x00, 0x20, 0x29, 0x68, 0x60, 0x23, 0x0a, 0x68, 0x9a, 0x43, 
-0x0a, 0x60, 0xff, 0xf7, 0xe1, 0xfa, 0xd5, 0xe7, 0x06, 0x20, 0xb8, 0x71, 
-0xd2, 0xe7, 0x00, 0x00, 0x99, 0x7c, 0x21, 0x40, 0x68, 0x0e, 0x00, 0x80, 
-0x9c, 0x03, 0x00, 0x80, 0x30, 0x75, 0x00, 0x00, 0x10, 0x27, 0x00, 0x00, 
-0x00, 0xb5, 0x00, 0x20, 0x04, 0x49, 0xc0, 0x46, 0x88, 0x71, 0x04, 0x48, 
-0x01, 0x22, 0x00, 0x21, 0x05, 0xf0, 0xbc, 0xfb, 0x08, 0xbc, 0x18, 0x47, 
-0x98, 0x1c, 0x00, 0x80, 0x99, 0x7c, 0x21, 0x40, 0x90, 0xb5, 0x07, 0x1c, 
-0x31, 0x48, 0x00, 0x68, 0x79, 0x08, 0x03, 0xd3, 0x10, 0x23, 0x01, 0x1c, 
-0x99, 0x43, 0x01, 0xe0, 0x10, 0x21, 0x01, 0x43, 0x2d, 0x4c, 0xe2, 0x68, 
-0x01, 0x2a, 0x05, 0xd1, 0x22, 0x79, 0x00, 0x2a, 0x02, 0xd0, 0x01, 0x23, 
-0x9b, 0x02, 0x19, 0x43, 0x81, 0x42, 0x02, 0xd0, 0x01, 0x20, 0x00, 0x05, 
-0x01, 0x60, 0xe0, 0x68, 0x01, 0x28, 0x20, 0xd1, 0x1b, 0x23, 0xdb, 0x01, 
-0xe0, 0x18, 0x80, 0x8b, 0xf9, 0x08, 0x04, 0xd3, 0x01, 0x23, 0xdb, 0x02, 
-0x01, 0x1c, 0x99, 0x43, 0x01, 0xe0, 0x01, 0x21, 0xc9, 0x02, 0x81, 0x42, 
-0x02, 0xd0, 0x00, 0x20, 0x03, 0xf0, 0xca, 0xf9, 0x38, 0x09, 0x07, 0xd3, 
-0xe0, 0x6f, 0x80, 0x23, 0x01, 0x68, 0x99, 0x43, 0x01, 0x60, 0xe0, 0x18, 
-0x00, 0x68, 0x00, 0xe0, 0xe0, 0x6f, 0x80, 0x23, 0x01, 0x68, 0x19, 0x43, 
-0x01, 0x60, 0x15, 0x48, 0x01, 0x6a, 0x78, 0x09, 0x03, 0xd3, 0xff, 0x20, 
-0x01, 0x30, 0x08, 0x43, 0x03, 0xe0, 0xff, 0x23, 0x08, 0x1c, 0x01, 0x33, 
-0x98, 0x43, 0x80, 0x08, 0x80, 0x00, 0xba, 0x09, 0x92, 0x07, 0x92, 0x0f, 
-0x10, 0x43, 0x88, 0x42, 0x02, 0xd0, 0x0c, 0x49, 0xc0, 0x46, 0x08, 0x62, 
-0xe1, 0x68, 0x01, 0x29, 0x08, 0xd1, 0x79, 0x0a, 0x06, 0xd3, 0xff, 0x23, 
-0x04, 0x33, 0x18, 0x40, 0x03, 0x28, 0x01, 0xd1, 0xff, 0xf7, 0x8e, 0xff, 
-0x90, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0x00, 0x00, 0x10, 0x40, 
-0x68, 0x0e, 0x00, 0x80, 0xc0, 0x00, 0x18, 0x40, 0xc0, 0x00, 0x18, 0x00, 
-0x80, 0xb5, 0xff, 0xf7, 0xb1, 0xfe, 0x80, 0x09, 0x1b, 0xd2, 0x0f, 0x48, 
-0xe3, 0x23, 0x1b, 0x01, 0xc1, 0x18, 0x4a, 0x79, 0x00, 0x2a, 0x14, 0xd1, 
-0x01, 0x22, 0x4a, 0x71, 0x00, 0x27, 0x80, 0x30, 0x00, 0x68, 0x60, 0x23, 
-0x01, 0x68, 0x99, 0x43, 0x01, 0x60, 0x08, 0x48, 
-0x06, 0xe0, 0x02, 0x20, 0x03, 0xf0, 0x7e, 0xfb, 0x07, 0x20, 0x03, 0xf0, 
-0x4d, 0xfb, 0x38, 0x1c, 0xff, 0xf7, 0x34, 0xfa, 0xf5, 0xe7, 0x80, 0xbc, 
-0x08, 0xbc, 0x18, 0x47, 0x68, 0x0e, 0x00, 0x80, 0xf4, 0x01, 0xff, 0xff, 
-0x00, 0xb5, 0x84, 0xb0, 0x69, 0x46, 0xff, 0xf7, 0x43, 0xfc, 0xff, 0xf7, 
-0x85, 0xfe, 0x01, 0xab, 0x58, 0x80, 0x08, 0x48, 0x00, 0x68, 0xc0, 0x46, 
-0x02, 0x90, 0x07, 0x48, 0x00, 0x6a, 0xc0, 0x46, 0x03, 0x90, 0x68, 0x46, 
-0x00, 0x21, 0xff, 0xf7, 0x73, 0xfb, 0x01, 0x20, 0x04, 0xb0, 0x08, 0xbc, 
-0x18, 0x47, 0x00, 0x00, 0x00, 0x00, 0x10, 0x40, 0xc0, 0x00, 0x18, 0x40, 
-0x80, 0xb5, 0x84, 0xb0, 0x07, 0x1c, 0x69, 0x46, 0x38, 0x1c, 0xff, 0xf7, 
-0x23, 0xfc, 0xf8, 0x88, 0xff, 0xf7, 0x42, 0xff, 0xff, 0xf7, 0x62, 0xfe, 
-0x01, 0xab, 0x58, 0x80, 0x68, 0x46, 0x00, 0x21, 0xff, 0xf7, 0x58, 0xfb, 
-0x01, 0x20, 0x04, 0xb0, 0x80, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0xb0, 0xb5, 
-0xc6, 0xb0, 0xc7, 0x88, 0x69, 0x46, 0xff, 0xf7, 0x0d, 0xfc, 0x01, 0x24, 
-0x16, 0x4b, 0x9f, 0x42, 0x0a, 0xd9, 0x00, 0xa8, 0x00, 0x78, 0x40, 0x23, 
-0x18, 0x43, 0x00, 0xab, 0x18, 0x70, 0x02, 0x20, 0xd8, 0x80, 0x68, 0x46, 
-0x00, 0x21, 0x17, 0xe0, 0x10, 0x48, 0xff, 0xf7, 0xdf, 0xf9, 0x05, 0x1c, 
-0x0f, 0x4a, 0x38, 0x1c, 0x04, 0xa9, 0xff, 0xf7, 0xdb, 0xf9, 0x0e, 0x49, 
-0x28, 0x1c, 0xff, 0xf7, 0xd6, 0xf9, 0x10, 0x20, 0x00, 0xab, 0x58, 0x70, 
-0x04, 0x98, 0xc0, 0x46, 0x02, 0x90, 0x05, 0x98, 0xc0, 0x46, 0x03, 0x90, 
-0x68, 0x46, 0x06, 0xa9, 0xff, 0xf7, 0x24, 0xfb, 0x20, 0x1c, 0x46, 0xb0, 
-0xb0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 
-0x24, 0x02, 0xff, 0xff, 0x29, 0xbf, 0x21, 0x40, 0x3c, 0x02, 0xff, 0xff, 
+0x07, 0xe0, 0x03, 0x9d, 0xe8, 0x6a, 0x30, 0x28, 0x03, 0xd2, 0x30, 0x20, 
+0x03, 0x9d, 0xc0, 0x46, 0xe8, 0x62, 0x19, 0x4a, 0x78, 0x69, 0x00, 0x28, 
+0x2a, 0xd0, 0x00, 0x21, 0x01, 0x23, 0x18, 0x43, 0x78, 0x61, 0x00, 0x20, 
+0x01, 0x24, 0x00, 0x22, 0x13, 0x4e, 0x7b, 0x69, 0x23, 0x40, 0x10, 0xd0, 
+0x93, 0x00, 0x9b, 0x18, 0x9b, 0x00, 0x12, 0x4d, 0x5b, 0x19, 0x9d, 0x78, 
+0x85, 0x42, 0x08, 0xd1, 0x1d, 0x69, 0x0b, 0x1c, 0x9b, 0x00, 0x9e, 0x19, 
+0x2d, 0x23, 0x9b, 0x01, 0xf3, 0x18, 0xdd, 0x63, 0x01, 0x31, 0x64, 0x00, 
+0x01, 0x32, 0x0b, 0x2a, 0xe6, 0xd3, 0x01, 0x30, 0x09, 0x28, 0xe1, 0xd3, 
+0x00, 0x20, 0x89, 0x00, 0x04, 0x4a, 0x89, 0x18, 0x2d, 0x23, 0x9b, 0x01, 
+0xc9, 0x18, 0xc8, 0x63, 0x04, 0xb0, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 
+0x68, 0x0e, 0x00, 0x80, 0x30, 0x53, 0xff, 0xff, 0x00, 0x01, 0x00, 0x80, 
+0x00, 0x47, 0x08, 0x47, 0x10, 0x47, 0x18, 0x47, 0x78, 0x47, 0xc0, 0x46, 
+0x18, 0xc0, 0x9f, 0xe5, 0x1c, 0xff, 0x2f, 0xe1, 0x78, 0x47, 0xc0, 0x46, 
+0x10, 0xc0, 0x9f, 0xe5, 0x1c, 0xff, 0x2f, 0xe1, 0x78, 0x47, 0xc0, 0x46, 
+0x08, 0xc0, 0x9f, 0xe5, 0x1c, 0xff, 0x2f, 0xe1, 0x38, 0x52, 0xff, 0xff, 
+0x88, 0x51, 0xff, 0xff, 0xd5, 0xb0, 0x21, 0x40, 0xf0, 0xb5, 0x04, 0x20, 
+0x1a, 0x49, 0x01, 0x25, 0x08, 0x60, 0x1a, 0x4f, 0xbb, 0x23, 0x1b, 0x01, 
+0xf8, 0x18, 0x05, 0x73, 0x18, 0x48, 0x41, 0x6b, 0x2c, 0x05, 0x00, 0x20, 
+0x7a, 0x6e, 0x17, 0x4b, 0x8a, 0x42, 0x1d, 0xd0, 
+0x19, 0x7b, 0x00, 0x29, 0x17, 0xd1, 0xd9, 0x1d, 0xff, 0x31, 0x3a, 0x31, 
+0x49, 0x78, 0x1e, 0x1c, 0x00, 0x29, 0x10, 0xd1, 0xb0, 0x60, 0x10, 0x20, 
+0x70, 0x60, 0x10, 0x4a, 0x10, 0x49, 0xff, 0xf7, 0xc3, 0xff, 0x00, 0x28, 
+0x07, 0xd0, 0x35, 0x73, 0x04, 0x23, 0xb8, 0x69, 0x18, 0x43, 0xb8, 0x61, 
+0x20, 0x61, 0x00, 0xf0, 0x17, 0xf8, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 
+0x18, 0x73, 0x04, 0x23, 0xb8, 0x69, 0x98, 0x43, 0xb8, 0x61, 0x20, 0x61, 
+0xf5, 0xe7, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0x68, 0x0e, 0x00, 0x80, 
+0x00, 0x01, 0x18, 0x40, 0x28, 0x05, 0x00, 0x80, 0x20, 0x55, 0xff, 0xff, 
+0x7d, 0x71, 0x21, 0x40, 0xf8, 0xb5, 0x15, 0x4f, 0x39, 0x6c, 0x15, 0x48, 
+0x40, 0x6e, 0x0c, 0x1a, 0x14, 0x4e, 0x71, 0x68, 0x14, 0x4d, 0xa1, 0x42, 
+0x06, 0xd8, 0x14, 0x4a, 0x0a, 0x43, 0x00, 0x92, 0xb9, 0x6b, 0x09, 0x18, 
+0xfa, 0x6b, 0x11, 0xe0, 0x11, 0x22, 0x52, 0x05, 0x22, 0x43, 0x00, 0x92, 
+0xb9, 0x6b, 0x09, 0x18, 0x00, 0x20, 0xfa, 0x6b, 0x2b, 0x1c, 0xff, 0xf7, 
+0x8d, 0xff, 0x70, 0x68, 0x00, 0x1b, 0x0a, 0x4a, 0x02, 0x43, 0x00, 0x92, 
+0xb9, 0x6b, 0xfa, 0x6b, 0x00, 0x20, 0x2b, 0x1c, 0xff, 0xf7, 0x82, 0xff, 
+0xf8, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0x7c, 0x29, 0x00, 0x80, 
+0x68, 0x0e, 0x00, 0x80, 0x28, 0x05, 0x00, 0x80, 0x44, 0x80, 0x20, 0x40, 
+0x00, 0x00, 0x37, 0x02, 0xf0, 0xb5, 0x2b, 0x4f, 0xb8, 0x68, 0x79, 0x68, 
+0xc0, 0x19, 0x20, 0x30, 0x29, 0x4a, 0xff, 0xf7, 0x63, 0xff, 0x01, 0x20, 
+0xc0, 0x02, 0x28, 0x49, 0xc0, 0x46, 0x08, 0x60, 0xb9, 0x68, 0x38, 0x1c, 
+0x26, 0x4d, 0x00, 0x24, 0x26, 0x4e, 0xef, 0x1d, 0x79, 0x37, 0x00, 0x29, 
+0x31, 0xd1, 0x31, 0x68, 0x0a, 0x78, 0x12, 0x0a, 0x03, 0xd2, 0x04, 0x73, 
+0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x49, 0x78, 0x00, 0x29, 0x0c, 0xd1, 
+0x05, 0x1c, 0x40, 0x68, 0x00, 0xf0, 0x3e, 0xf9, 0x30, 0x68, 0x00, 0xf0, 
+0x67, 0xf8, 0x00, 0x28, 0x26, 0xd1, 0x2c, 0x73, 0xff, 0xf7, 0x58, 0xff, 
+0x22, 0xe0, 0x09, 0x01, 0x07, 0x1c, 0x41, 0x60, 0x08, 0x1c, 0x17, 0x4a, 
+0x17, 0x49, 0xff, 0xf7, 0x35, 0xff, 0x00, 0x28, 0x07, 0xd1, 0x3c, 0x73, 
+0x04, 0x23, 0xa8, 0x69, 0x98, 0x43, 0x99, 0x04, 0xa8, 0x61, 0x08, 0x61, 
+0xda, 0xe7, 0x10, 0x20, 0x00, 0xf0, 0x20, 0xf9, 0x10, 0x20, 0xb8, 0x60, 
+0xff, 0xf7, 0x82, 0xff, 0xd2, 0xe7, 0x05, 0x1c, 0x40, 0x68, 0x00, 0xf0, 
+0x17, 0xf9, 0x30, 0x68, 0x00, 0xf0, 0x40, 0xf8, 0x00, 0x28, 0xd8, 0xd0, 
+0x02, 0x23, 0xf8, 0x6b, 0x18, 0x43, 0xf8, 0x63, 0xc4, 0xe7, 0x00, 0x00, 
+0x28, 0x05, 0x00, 0x80, 0xa5, 0x55, 0xff, 0xff, 0x00, 0x00, 0x00, 0xb0, 
+0x68, 0x0e, 0x00, 0x80, 0xe4, 0x01, 0x00, 0x80, 0x20, 0x55, 0xff, 0xff, 
+0x7d, 0x71, 0x21, 0x40, 0x90, 0xb5, 0x01, 0x20, 0x40, 0x03, 0x10, 0x49, 
+0x00, 0x27, 0x08, 0x60, 0x0f, 0x4c, 0xe0, 0x1d, 0xff, 0x30, 0x3a, 0x30, 
+0x47, 0x70, 0xe0, 0x69, 0x80, 0x00, 0x00, 0x19, 0x00, 0x69, 0x00, 0xf0, 
+0xd7, 0xf8, 0xe0, 0x69, 0x00, 0x28, 0x01, 0xd0, 0xe7, 0x61, 0x01, 0xe0, 
+0x01, 0x20, 0xe0, 0x61, 0x07, 0x48, 0x02, 0x23, 0xc1, 0x6b, 0x19, 0x43, 
+0xc1, 0x63, 0x27, 0x73, 0xff, 0xf7, 0x00, 0xff, 0x90, 0xbc, 0x08, 0xbc, 
+0x18, 0x47, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0x28, 0x05, 0x00, 0x80, 
+0xe8, 0x0e, 0x00, 0x80, 0x80, 0xb5, 0x84, 0xb0, 0x07, 0x1c, 0x78, 0x88, 
+0x6d, 0x28, 0x03, 0xdb, 0x38, 0x1c, 0x00, 0xf0, 
+0xf7, 0xf8, 0x17, 0xe0, 0x80, 0x00, 0x0d, 0x49, 0x09, 0x58, 0x38, 0x1c, 
+0xff, 0xf7, 0xcb, 0xfe, 0x00, 0x28, 0x0f, 0xd1, 0x39, 0x78, 0xc9, 0x09, 
+0x0c, 0xd3, 0x69, 0x46, 0x38, 0x1c, 0x00, 0xf0, 0xcf, 0xf8, 0x68, 0x46, 
+0x00, 0x21, 0x00, 0xf0, 0x0b, 0xf8, 0x00, 0x28, 0x01, 0xd1, 0x01, 0x20, 
+0x00, 0xe0, 0x00, 0x20, 0x04, 0xb0, 0x80, 0xbc, 0x08, 0xbc, 0x18, 0x47, 
+0xe8, 0x01, 0x00, 0x80, 0xf0, 0xb5, 0x82, 0xb0, 0x02, 0x1c, 0x41, 0x4b, 
+0xdd, 0x1d, 0xff, 0x35, 0x3a, 0x35, 0x2f, 0x78, 0x00, 0x2f, 0x01, 0xd0, 
+0x00, 0x27, 0x00, 0xe0, 0x01, 0x27, 0x2f, 0x70, 0x2f, 0x78, 0xfb, 0x00, 
+0xdb, 0x19, 0x5b, 0x01, 0x3a, 0x4f, 0xdc, 0x19, 0x40, 0x78, 0x00, 0x01, 
+0xc7, 0x1d, 0x09, 0x37, 0x00, 0x20, 0x83, 0x00, 0xd6, 0x58, 0xc0, 0x46, 
+0xe6, 0x50, 0x01, 0x30, 0x04, 0x28, 0xf8, 0xd3, 0x00, 0x29, 0x0f, 0xd0, 
+0x00, 0x22, 0xbb, 0x08, 0x01, 0x93, 0x83, 0x42, 0x0b, 0xd9, 0x13, 0x1c, 
+0x9b, 0x00, 0xcb, 0x58, 0x86, 0x00, 0xa3, 0x51, 0x01, 0x9b, 0x01, 0x30, 
+0x01, 0x32, 0x83, 0x42, 0xf5, 0xd8, 0x00, 0xe0, 0x10, 0x27, 0x2b, 0x48, 
+0x02, 0x6d, 0x80, 0x6e, 0x2a, 0x49, 0x82, 0x42, 0x03, 0xd8, 0x82, 0x1a, 
+0xcb, 0x6c, 0x9a, 0x1a, 0x00, 0xe0, 0x12, 0x1a, 0xba, 0x42, 0x05, 0xd8, 
+0x26, 0x48, 0x81, 0x6b, 0x01, 0x31, 0x81, 0x63, 0x01, 0x20, 0x37, 0xe0, 
+0xc3, 0x19, 0xca, 0x6c, 0x93, 0x42, 0x08, 0xd8, 0x22, 0x4a, 0x3a, 0x43, 
+0x00, 0x92, 0x0a, 0x1c, 0x49, 0x6c, 0x09, 0x18, 0x92, 0x6c, 0x23, 0x1c, 
+0x12, 0xe0, 0x16, 0x1a, 0x00, 0x96, 0x1b, 0x49, 0x49, 0x6c, 0x09, 0x18, 
+0x19, 0x48, 0x82, 0x6c, 0x03, 0x20, 0x23, 0x1c, 0xff, 0xf7, 0x5e, 0xfe, 
+0xb8, 0x1b, 0x18, 0x4a, 0x02, 0x43, 0x00, 0x92, 0xa3, 0x19, 0x14, 0x48, 
+0x82, 0x6c, 0x41, 0x6c, 0x03, 0x20, 0xff, 0xf7, 0x53, 0xfe, 0x01, 0x20, 
+0x0d, 0x49, 0xc0, 0x46, 0x68, 0x70, 0x8a, 0x69, 0x92, 0x00, 0x52, 0x18, 
+0x17, 0x61, 0x8a, 0x69, 0x00, 0x2a, 0x02, 0xd0, 0x00, 0x27, 0x8f, 0x61, 
+0x00, 0xe0, 0x88, 0x61, 0x0c, 0x48, 0x02, 0x23, 0xc1, 0x6b, 0x19, 0x43, 
+0xc1, 0x63, 0x00, 0x20, 0x01, 0x27, 0x0a, 0x49, 0xc0, 0x46, 0x4f, 0x73, 
+0x02, 0xb0, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x28, 0x05, 0x00, 0x80, 
+0x50, 0xba, 0x20, 0x40, 0x68, 0x0e, 0x00, 0x80, 0x7c, 0x29, 0x00, 0x80, 
+0xa0, 0x82, 0x20, 0x40, 0x00, 0x00, 0x19, 0x02, 0xe8, 0x0e, 0x00, 0x80, 
+0x18, 0x1a, 0x00, 0x80, 0x07, 0x49, 0x8a, 0x6e, 0x10, 0x18, 0x07, 0x4a, 
+0xd2, 0x6c, 0x13, 0x04, 0x1b, 0x0c, 0x83, 0x42, 0x00, 0xd8, 0x80, 0x1a, 
+0x88, 0x66, 0x88, 0x6e, 0x03, 0x49, 0xc0, 0x46, 0x48, 0x61, 0x70, 0x47, 
+0x68, 0x0e, 0x00, 0x80, 0x7c, 0x29, 0x00, 0x80, 0x90, 0xee, 0x20, 0x40, 
+0x06, 0x49, 0x4a, 0x6e, 0x10, 0x18, 0x06, 0x4a, 0x12, 0x6c, 0x82, 0x42, 
+0x00, 0xd8, 0x80, 0x1a, 0x48, 0x66, 0x48, 0x6e, 0x03, 0x49, 0xc0, 0x46, 
+0x08, 0x61, 0x70, 0x47, 0x68, 0x0e, 0x00, 0x80, 0x7c, 0x29, 0x00, 0x80, 
+0x90, 0xee, 0x20, 0x40, 0x05, 0x22, 0x0a, 0x60, 0x82, 0x88, 0xc0, 0x46, 
+0x8a, 0x80, 0x00, 0x22, 0x4a, 0x70, 0x40, 0x88, 0xc0, 0x46, 0x48, 0x80, 
+0xca, 0x80, 0x8a, 0x60, 0xca, 0x60, 0x70, 0x47, 0x05, 0x22, 0x02, 0x60, 
+0x00, 0x22, 0x82, 0x80, 0x42, 0x70, 0x41, 0x80, 0xc2, 0x80, 0x82, 0x60, 
+0xc2, 0x60, 0x70, 0x47, 0x80, 0xb5, 0x84, 0xb0, 0x07, 0x1c, 0x0e, 0x48, 
+0x41, 0x6b, 0x01, 0x31, 0x41, 0x63, 0x69, 0x46, 
+0x38, 0x1c, 0xff, 0xf7, 0xdd, 0xff, 0x38, 0x68, 0xc0, 0x46, 0x00, 0x90, 
+0x45, 0x20, 0x00, 0xab, 0x18, 0x70, 0x01, 0x27, 0xdf, 0x80, 0x68, 0x46, 
+0x00, 0x21, 0xff, 0xf7, 0x11, 0xff, 0x00, 0x28, 0x01, 0xd1, 0x38, 0x1c, 
+0x00, 0xe0, 0x00, 0x20, 0x04, 0xb0, 0x80, 0xbc, 0x08, 0xbc, 0x18, 0x47, 
+0xa0, 0x82, 0x20, 0x40, 0x00, 0xb5, 0x84, 0xb0, 0xc1, 0x88, 0x09, 0x4a, 
+0xc0, 0x46, 0x91, 0x81, 0x69, 0x46, 0xff, 0xf7, 0xbd, 0xff, 0x01, 0x20, 
+0x40, 0x02, 0x01, 0xab, 0x58, 0x80, 0x68, 0x46, 0x00, 0x21, 0xff, 0xf7, 
+0xf5, 0xfe, 0x01, 0x20, 0x04, 0xb0, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 
+0xe8, 0x0e, 0x00, 0x80, 0x00, 0xb5, 0xff, 0xf7, 0xc3, 0xff, 0x08, 0xbc, 
+0x18, 0x47, 0x01, 0x20, 0x03, 0x49, 0xc0, 0x46, 0x08, 0x71, 0xa1, 0x21, 
+0x49, 0x03, 0x88, 0x60, 0x00, 0x20, 0x70, 0x47, 0x28, 0x0f, 0x00, 0x80, 
+0x00, 0x20, 0x04, 0x49, 0xc0, 0x46, 0x08, 0x71, 0xff, 0x21, 0xa1, 0x22, 
+0x52, 0x03, 0x01, 0x31, 0x91, 0x60, 0x70, 0x47, 0x28, 0x0f, 0x00, 0x80, 
+0x02, 0x20, 0xa1, 0x21, 0x49, 0x03, 0x88, 0x60, 0x00, 0x20, 0x70, 0x47, 
+0x01, 0x20, 0x40, 0x02, 0xa1, 0x21, 0x49, 0x03, 0x88, 0x60, 0x00, 0x20, 
+0x70, 0x47, 0xc0, 0x88, 0xc0, 0x06, 0xc0, 0x0e, 0xa1, 0x21, 0x49, 0x03, 
+0x48, 0x61, 0x02, 0x49, 0xc0, 0x46, 0xc8, 0x63, 0x00, 0x20, 0x70, 0x47, 
+0xe8, 0x1a, 0x00, 0x80, 0x80, 0xb5, 0x84, 0xb0, 0x08, 0x49, 0x0f, 0x6b, 
+0x69, 0x46, 0xff, 0xf7, 0x71, 0xff, 0xf8, 0x06, 0xc0, 0x0e, 0x01, 0xab, 
+0x58, 0x80, 0x68, 0x46, 0x00, 0x21, 0xff, 0xf7, 0xa9, 0xfe, 0x01, 0x20, 
+0x04, 0xb0, 0x80, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x80, 0x00, 0x14, 0x40, 
+0x80, 0xb5, 0x85, 0xb0, 0x07, 0x1c, 0x69, 0x46, 0x38, 0x1c, 0xff, 0xf7, 
+0x5b, 0xff, 0xf8, 0x88, 0x04, 0xa9, 0x03, 0xf0, 0xc9, 0xff, 0x01, 0xab, 
+0x58, 0x80, 0x01, 0xa8, 0x40, 0x88, 0x00, 0x28, 0x0f, 0xd0, 0x01, 0xa8, 
+0x40, 0x88, 0x80, 0x08, 0x03, 0x38, 0x80, 0x08, 0x01, 0x30, 0x04, 0x3b, 
+0x58, 0x70, 0x04, 0x98, 0x01, 0x68, 0xc0, 0x46, 0x02, 0x91, 0x40, 0x68, 
+0xc0, 0x46, 0x03, 0x90, 0x05, 0xe0, 0x00, 0xa8, 0x00, 0x78, 0x40, 0x23, 
+0x18, 0x43, 0x00, 0xab, 0x18, 0x70, 0x04, 0x98, 0xc1, 0x1d, 0x01, 0x31, 
+0x68, 0x46, 0xff, 0xf7, 0x75, 0xfe, 0x01, 0x20, 0x05, 0xb0, 0x80, 0xbc, 
+0x08, 0xbc, 0x18, 0x47, 0x90, 0xb5, 0x84, 0xb0, 0x14, 0x4f, 0x39, 0x7b, 
+0x00, 0x29, 0x20, 0xd1, 0xf9, 0x1d, 0xff, 0x31, 0x3a, 0x31, 0x49, 0x78, 
+0x00, 0x29, 0x1a, 0xd1, 0x10, 0x49, 0x05, 0x22, 0x00, 0x92, 0x08, 0x22, 
+0x00, 0xab, 0x5a, 0x80, 0x98, 0x80, 0x06, 0x20, 0x00, 0xab, 0x58, 0x70, 
+0x00, 0x24, 0xdc, 0x80, 0x08, 0x68, 0xc0, 0x46, 0x02, 0x90, 0x48, 0x68, 
+0xc0, 0x46, 0x03, 0x90, 0x01, 0x20, 0x38, 0x73, 0x68, 0x46, 0x08, 0x31, 
+0xff, 0xf7, 0x4c, 0xfe, 0x00, 0x28, 0x00, 0xd0, 0x3c, 0x73, 0x04, 0xb0, 
+0x90, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0x28, 0x05, 0x00, 0x80, 
+0xa4, 0x2a, 0x00, 0x80, 0x90, 0xb5, 0x84, 0xb0, 0x07, 0x1c, 0x69, 0x46, 
+0x38, 0x1c, 0xff, 0xf7, 0xf9, 0xfe, 0xba, 0x68, 0x0d, 0x4c, 0x0e, 0x48, 
+0x00, 0x2a, 0x05, 0xd1, 0x0d, 0x49, 0xff, 0xf7, 0xe4, 0xfc, 0x00, 0x28, 
+0x0c, 0xda, 0x05, 0xe0, 0xb9, 0x88, 0x0b, 0x4b, 0xff, 0xf7, 0xdf, 0xfc, 
+0x00, 0x28, 0x05, 0xda, 0x01, 0xab, 0x5c, 0x80, 0x68, 0x46, 0x00, 0x21, 
+0xff, 0xf7, 0x22, 0xfe, 0x00, 0x20, 0x04, 0xb0, 
+0x90, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 
+0x0d, 0x76, 0x21, 0x40, 0xc1, 0xbd, 0x21, 0x40, 0x59, 0xbd, 0x21, 0x40, 
+0x00, 0xb5, 0xc0, 0x88, 0x03, 0xf0, 0x2e, 0xff, 0x00, 0x20, 0x08, 0xbc, 
+0x18, 0x47, 0x00, 0xb5, 0xff, 0xf7, 0xe2, 0xfe, 0x08, 0xbc, 0x18, 0x47, 
+0x00, 0xb5, 0xff, 0xf7, 0xdd, 0xfe, 0x08, 0xbc, 0x18, 0x47, 0x00, 0xb5, 
+0x01, 0x1c, 0x02, 0x20, 0x00, 0xf0, 0x02, 0xf8, 0x08, 0xbc, 0x18, 0x47, 
+0xb0, 0xb5, 0xc6, 0xb0, 0x07, 0x1c, 0x08, 0x1c, 0x69, 0x46, 0xff, 0xf7, 
+0xb5, 0xfe, 0x21, 0x48, 0xff, 0xf7, 0xa4, 0xfc, 0x04, 0x1c, 0x20, 0x4a, 
+0x00, 0x21, 0x38, 0x1c, 0xff, 0xf7, 0xa0, 0xfc, 0x00, 0x28, 0x27, 0xd0, 
+0x04, 0xa9, 0x1d, 0x4a, 0x38, 0x1c, 0xff, 0xf7, 0x99, 0xfc, 0x04, 0xa8, 
+0x00, 0x23, 0x01, 0x2f, 0x06, 0xd1, 0x0c, 0xaa, 0x02, 0x32, 0x00, 0x21, 
+0x13, 0x60, 0x01, 0x31, 0x10, 0x29, 0xfb, 0xd3, 0x01, 0x68, 0x04, 0x29, 
+0x04, 0xd9, 0x89, 0x08, 0x03, 0x39, 0x89, 0x08, 0x01, 0x31, 0x00, 0xe0, 
+0x19, 0x1c, 0x00, 0xab, 0x59, 0x70, 0x06, 0xa9, 0x09, 0x78, 0xc0, 0x46, 
+0xd9, 0x80, 0x00, 0x68, 0xc0, 0x46, 0x02, 0x90, 0x07, 0x98, 0xc0, 0x46, 
+0x03, 0x90, 0x04, 0x33, 0x08, 0xad, 0x02, 0xe0, 0x45, 0x20, 0x00, 0xab, 
+0x18, 0x70, 0x09, 0x49, 0x20, 0x1c, 0xff, 0xf7, 0x6e, 0xfc, 0x68, 0x46, 
+0x29, 0x1c, 0xff, 0xf7, 0xb7, 0xfd, 0x01, 0x20, 0x46, 0xb0, 0xb0, 0xbc, 
+0x08, 0xbc, 0x18, 0x47, 0x24, 0x02, 0xff, 0xff, 0x59, 0xb1, 0x21, 0x40, 
+0x9d, 0xaf, 0x21, 0x40, 0x3c, 0x02, 0xff, 0xff, 0x00, 0xb5, 0x01, 0x1c, 
+0x02, 0x20, 0x00, 0xf0, 0x10, 0xf8, 0x08, 0xbc, 0x18, 0x47, 0x00, 0xb5, 
+0x01, 0x1c, 0x01, 0x20, 0xff, 0xf7, 0xa2, 0xff, 0x08, 0xbc, 0x18, 0x47, 
+0x00, 0xb5, 0x01, 0x1c, 0x01, 0x20, 0x00, 0xf0, 0x02, 0xf8, 0x08, 0xbc, 
+0x18, 0x47, 0xf0, 0xb5, 0xc7, 0xb0, 0x04, 0x1c, 0x0f, 0x1c, 0x38, 0x1c, 
+0x01, 0xa9, 0xff, 0xf7, 0x4d, 0xfe, 0x21, 0x48, 0xff, 0xf7, 0x3c, 0xfc, 
+0x00, 0x90, 0x78, 0x78, 0x00, 0x01, 0xba, 0x68, 0x04, 0x30, 0xfc, 0x2a, 
+0x25, 0xd8, 0xff, 0x23, 0x09, 0x33, 0x98, 0x42, 0x21, 0xd8, 0x19, 0x2c, 
+0x1f, 0xd8, 0xfd, 0x88, 0xf8, 0x68, 0xc0, 0x46, 0x05, 0x90, 0xf9, 0x1d, 
+0x09, 0x31, 0x06, 0xab, 0x00, 0x20, 0x7e, 0x78, 0x00, 0x2e, 0x0d, 0xdd, 
+0x40, 0xc9, 0x40, 0xc3, 0x40, 0xc9, 0x40, 0xc3, 0x40, 0xc9, 0x40, 0xc3, 
+0x40, 0xc9, 0x40, 0xc3, 0x01, 0x30, 0x00, 0x04, 0x00, 0x0c, 0x7e, 0x78, 
+0x86, 0x42, 0xf1, 0xdc, 0x20, 0x1c, 0x05, 0xa9, 0x2b, 0x1c, 0xff, 0xf7, 
+0x21, 0xfc, 0x00, 0x28, 0x05, 0xd0, 0x01, 0xa8, 0x00, 0x78, 0x40, 0x23, 
+0x18, 0x43, 0x01, 0xab, 0x18, 0x70, 0x07, 0x49, 0x00, 0x98, 0xff, 0xf7, 
+0x06, 0xfc, 0x00, 0x21, 0x01, 0xa8, 0xff, 0xf7, 0x4f, 0xfd, 0x01, 0x20, 
+0x47, 0xb0, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x24, 0x02, 0xff, 0xff, 
+0x3c, 0x02, 0xff, 0xff, 0x00, 0xb5, 0xff, 0xf7, 0x1b, 0xfe, 0x08, 0xbc, 
+0x18, 0x47, 0xf0, 0xb5, 0xc6, 0xb0, 0x07, 0x1c, 0xfc, 0x88, 0x25, 0x4d, 
+0x68, 0x68, 0x01, 0x30, 0x69, 0x46, 0x68, 0x60, 0x38, 0x1c, 0xff, 0xf7, 
+0xf5, 0xfd, 0x10, 0x2c, 0x08, 0xd3, 0x00, 0xa8, 0x00, 0x78, 0x40, 0x23, 
+0x18, 0x43, 0x00, 0xab, 0x18, 0x70, 0x02, 0x20, 0xd8, 0x80, 0x17, 0xe0, 
+0x78, 0x78, 0x82, 0x00, 0xfb, 0x1d, 0x09, 0x33, 0x00, 0x20, 0xb9, 0x68, 
+0x00, 0x2a, 0x15, 0xd9, 0x40, 0xcb, 0x0f, 0x1c, 
+0x01, 0x31, 0xbe, 0x42, 0x0d, 0xd0, 0x00, 0xaa, 0x12, 0x78, 0x40, 0x23, 
+0x1a, 0x43, 0x00, 0xab, 0x1a, 0x70, 0x04, 0x22, 0xda, 0x80, 0x02, 0x90, 
+0x03, 0x91, 0x04, 0x33, 0x68, 0x46, 0x00, 0x21, 0x15, 0xe0, 0x01, 0x30, 
+0x90, 0x42, 0xe9, 0xd3, 0x00, 0xab, 0x5c, 0x70, 0x02, 0x94, 0x69, 0x68, 
+0xc0, 0x46, 0x03, 0x91, 0xa2, 0x00, 0x00, 0x20, 0x10, 0x33, 0x00, 0x2a, 
+0x05, 0xd9, 0x0f, 0x1c, 0x80, 0xc3, 0x01, 0x30, 0x01, 0x31, 0x90, 0x42, 
+0xf9, 0xd3, 0x68, 0x46, 0x04, 0xa9, 0xff, 0xf7, 0xf7, 0xfc, 0x01, 0x20, 
+0x46, 0xb0, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x9c, 0x03, 0x00, 0x80, 
+0x90, 0xb4, 0x23, 0x48, 0x00, 0x68, 0x01, 0x21, 0x42, 0x09, 0x00, 0xd3, 
+0x00, 0x21, 0x00, 0x27, 0x3a, 0x1c, 0x43, 0x0b, 0x00, 0xd2, 0x02, 0x22, 
+0x11, 0x43, 0x1e, 0x4a, 0x20, 0x24, 0xd3, 0x68, 0x01, 0x2b, 0x2e, 0xd1, 
+0x80, 0x0a, 0x00, 0xd2, 0x00, 0x24, 0x0c, 0x43, 0x20, 0x1c, 0x1b, 0x23, 
+0xdb, 0x01, 0xd1, 0x18, 0x89, 0x8b, 0x09, 0x0b, 0x00, 0xd2, 0x04, 0x27, 
+0x38, 0x43, 0xd1, 0x6f, 0x09, 0x68, 0x09, 0x0a, 0x07, 0xd2, 0xd1, 0x1d, 
+0x79, 0x31, 0x09, 0x68, 0x09, 0x68, 0x09, 0x0a, 0x01, 0xd3, 0x08, 0x23, 
+0x18, 0x43, 0xe3, 0x23, 0x1b, 0x01, 0xd1, 0x18, 0x89, 0x79, 0x03, 0x29, 
+0x02, 0xd1, 0xff, 0x23, 0x01, 0x33, 0x18, 0x43, 0x0b, 0x49, 0x09, 0x6a, 
+0x10, 0x22, 0x4b, 0x0a, 0x00, 0xd2, 0x00, 0x22, 0x10, 0x43, 0x89, 0x07, 
+0x89, 0x0f, 0x89, 0x01, 0x08, 0x43, 0x90, 0xbc, 0x70, 0x47, 0x40, 0x0c, 
+0x00, 0xd2, 0x00, 0x24, 0x0c, 0x43, 0x20, 0x1c, 0xec, 0xe7, 0x00, 0x00, 
+0x00, 0x00, 0x10, 0x40, 0x68, 0x0e, 0x00, 0x80, 0xc0, 0x00, 0x18, 0x40, 
+0xf0, 0xb5, 0x3a, 0x4c, 0x20, 0x1c, 0x04, 0xf0, 0x07, 0xfa, 0x39, 0x48, 
+0xe3, 0x23, 0x1b, 0x01, 0xc7, 0x18, 0xb9, 0x79, 0x37, 0x4e, 0xc5, 0x1d, 
+0x79, 0x35, 0x06, 0x29, 0x62, 0xd2, 0x02, 0xa3, 0x5b, 0x5c, 0x5b, 0x00, 
+0x9f, 0x44, 0x00, 0x1c, 0x03, 0x0e, 0x1e, 0x37, 0x4e, 0x55, 0x01, 0x20, 
+0xb8, 0x71, 0x00, 0x20, 0xb0, 0x60, 0xff, 0xf7, 0x95, 0xff, 0x05, 0x23, 
+0x98, 0x43, 0x00, 0xf0, 0x6f, 0xf8, 0x0c, 0xe0, 0xff, 0xf7, 0x8e, 0xff, 
+0xc0, 0x08, 0x06, 0xd3, 0xb0, 0x68, 0x41, 0x1c, 0xb1, 0x60, 0x0a, 0x28, 
+0x03, 0xd9, 0x04, 0x20, 0x00, 0xe0, 0x02, 0x20, 0xb8, 0x71, 0x64, 0x22, 
+0x20, 0x1c, 0x2b, 0xe0, 0x06, 0x1c, 0xc0, 0x6f, 0x80, 0x23, 0x01, 0x68, 
+0x19, 0x43, 0x01, 0x60, 0x03, 0x20, 0xb8, 0x71, 0x20, 0x1c, 0x20, 0x4a, 
+0x00, 0x21, 0x04, 0xf0, 0x99, 0xf9, 0xf0, 0x6f, 0x04, 0x23, 0x01, 0x68, 
+0x99, 0x43, 0x01, 0x60, 0x28, 0x68, 0x01, 0x68, 0x19, 0x43, 0x01, 0x60, 
+0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x05, 0x21, 0xb9, 0x71, 0x29, 0x68, 
+0x04, 0x23, 0x0a, 0x68, 0x9a, 0x43, 0x0a, 0x60, 0xc0, 0x6f, 0x01, 0x68, 
+0x19, 0x43, 0x01, 0x60, 0xff, 0xf7, 0x5a, 0xff, 0x08, 0x23, 0x18, 0x43, 
+0x00, 0xf0, 0x34, 0xf8, 0x20, 0x1c, 0x10, 0x4a, 0x00, 0x21, 0x04, 0xf0, 
+0x77, 0xf9, 0xe5, 0xe7, 0xff, 0xf7, 0x4e, 0xff, 0x04, 0x23, 0x18, 0x43, 
+0x00, 0xf0, 0x28, 0xf8, 0xde, 0xe7, 0x00, 0x20, 0x29, 0x68, 0x60, 0x23, 
+0x0a, 0x68, 0x9a, 0x43, 0x0a, 0x60, 0xff, 0xf7, 0xe3, 0xfa, 0xd5, 0xe7, 
+0x06, 0x20, 0xb8, 0x71, 0xd2, 0xe7, 0x00, 0x00, 0xa9, 0x79, 0x21, 0x40, 
+0x68, 0x0e, 0x00, 0x80, 0x9c, 0x03, 0x00, 0x80, 0x30, 0x75, 0x00, 0x00, 
+0x10, 0x27, 0x00, 0x00, 0x00, 0xb5, 0x00, 0x20, 
+0x04, 0x49, 0xc0, 0x46, 0x88, 0x71, 0x04, 0x48, 0x01, 0x22, 0x00, 0x21, 
+0x04, 0xf0, 0x4e, 0xf9, 0x08, 0xbc, 0x18, 0x47, 0x98, 0x1c, 0x00, 0x80, 
+0xa9, 0x79, 0x21, 0x40, 0x90, 0xb5, 0x07, 0x1c, 0x31, 0x48, 0x00, 0x68, 
+0x79, 0x08, 0x03, 0xd3, 0x10, 0x23, 0x01, 0x1c, 0x99, 0x43, 0x01, 0xe0, 
+0x10, 0x21, 0x01, 0x43, 0x2d, 0x4c, 0xe2, 0x68, 0x01, 0x2a, 0x05, 0xd1, 
+0x22, 0x79, 0x00, 0x2a, 0x02, 0xd0, 0x01, 0x23, 0x9b, 0x02, 0x19, 0x43, 
+0x81, 0x42, 0x02, 0xd0, 0x01, 0x20, 0x00, 0x05, 0x01, 0x60, 0xe0, 0x68, 
+0x01, 0x28, 0x20, 0xd1, 0x1b, 0x23, 0xdb, 0x01, 0xe0, 0x18, 0x80, 0x8b, 
+0xf9, 0x08, 0x04, 0xd3, 0x01, 0x23, 0xdb, 0x02, 0x01, 0x1c, 0x99, 0x43, 
+0x01, 0xe0, 0x01, 0x21, 0xc9, 0x02, 0x81, 0x42, 0x02, 0xd0, 0x00, 0x20, 
+0x02, 0xf0, 0x1a, 0xfb, 0x38, 0x09, 0x07, 0xd3, 0xe0, 0x6f, 0x80, 0x23, 
+0x01, 0x68, 0x99, 0x43, 0x01, 0x60, 0xe0, 0x18, 0x00, 0x68, 0x00, 0xe0, 
+0xe0, 0x6f, 0x80, 0x23, 0x01, 0x68, 0x19, 0x43, 0x01, 0x60, 0x15, 0x48, 
+0x01, 0x6a, 0x78, 0x09, 0x03, 0xd3, 0xff, 0x20, 0x01, 0x30, 0x08, 0x43, 
+0x03, 0xe0, 0xff, 0x23, 0x08, 0x1c, 0x01, 0x33, 0x98, 0x43, 0x80, 0x08, 
+0x80, 0x00, 0xba, 0x09, 0x92, 0x07, 0x92, 0x0f, 0x10, 0x43, 0x88, 0x42, 
+0x02, 0xd0, 0x0c, 0x49, 0xc0, 0x46, 0x08, 0x62, 0xe1, 0x68, 0x01, 0x29, 
+0x08, 0xd1, 0x79, 0x0a, 0x06, 0xd3, 0xff, 0x23, 0x04, 0x33, 0x18, 0x40, 
+0x03, 0x28, 0x01, 0xd1, 0xff, 0xf7, 0x8e, 0xff, 0x90, 0xbc, 0x08, 0xbc, 
+0x18, 0x47, 0x00, 0x00, 0x00, 0x00, 0x10, 0x40, 0x68, 0x0e, 0x00, 0x80, 
+0xc0, 0x00, 0x18, 0x40, 0xc0, 0x00, 0x18, 0x00, 0x80, 0xb5, 0xff, 0xf7, 
+0xb1, 0xfe, 0x80, 0x09, 0x1b, 0xd2, 0x0f, 0x48, 0xe3, 0x23, 0x1b, 0x01, 
+0xc1, 0x18, 0x4a, 0x79, 0x00, 0x2a, 0x14, 0xd1, 0x01, 0x22, 0x4a, 0x71, 
+0x00, 0x27, 0x80, 0x30, 0x00, 0x68, 0x60, 0x23, 0x01, 0x68, 0x99, 0x43, 
+0x01, 0x60, 0x08, 0x48, 0x06, 0xe0, 0x02, 0x20, 0x02, 0xf0, 0x8c, 0xfc, 
+0x07, 0x20, 0x02, 0xf0, 0x5b, 0xfc, 0x38, 0x1c, 0xff, 0xf7, 0x36, 0xfa, 
+0xf5, 0xe7, 0x80, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x68, 0x0e, 0x00, 0x80, 
+0xf4, 0x01, 0xff, 0xff, 0x00, 0xb5, 0x84, 0xb0, 0x69, 0x46, 0xff, 0xf7, 
+0x37, 0xfc, 0xff, 0xf7, 0x85, 0xfe, 0x01, 0xab, 0x58, 0x80, 0x08, 0x48, 
+0x00, 0x68, 0xc0, 0x46, 0x02, 0x90, 0x07, 0x48, 0x00, 0x6a, 0xc0, 0x46, 
+0x03, 0x90, 0x68, 0x46, 0x00, 0x21, 0xff, 0xf7, 0x67, 0xfb, 0x01, 0x20, 
+0x04, 0xb0, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0x00, 0x00, 0x10, 0x40, 
+0xc0, 0x00, 0x18, 0x40, 0x80, 0xb5, 0x84, 0xb0, 0x07, 0x1c, 0x69, 0x46, 
+0x38, 0x1c, 0xff, 0xf7, 0x17, 0xfc, 0xf8, 0x88, 0xff, 0xf7, 0x42, 0xff, 
+0xff, 0xf7, 0x62, 0xfe, 0x01, 0xab, 0x58, 0x80, 0x68, 0x46, 0x00, 0x21, 
+0xff, 0xf7, 0x4c, 0xfb, 0x01, 0x20, 0x04, 0xb0, 0x80, 0xbc, 0x08, 0xbc, 
+0x18, 0x47, 0xb0, 0xb5, 0xc6, 0xb0, 0xc7, 0x88, 0x69, 0x46, 0xff, 0xf7, 
+0x01, 0xfc, 0x01, 0x24, 0x1a, 0x4b, 0x9f, 0x42, 0x0a, 0xd9, 0x00, 0xa8, 
+0x00, 0x78, 0x40, 0x23, 0x18, 0x43, 0x00, 0xab, 0x18, 0x70, 0x02, 0x20, 
+0xd8, 0x80, 0x68, 0x46, 0x00, 0x21, 0x20, 0xe0, 0x14, 0x48, 0xff, 0xf7, 
+0xe1, 0xf9, 0x05, 0x1c, 0x13, 0x4a, 0x38, 0x1c, 0x04, 0xa9, 0xff, 0xf7, 
+0xdd, 0xf9, 0x12, 0x49, 0x28, 0x1c, 0xff, 0xf7, 0xd8, 0xf9, 0x01, 0x2f, 
+0x06, 0xd1, 0x0c, 0xa9, 0x00, 0x20, 0x00, 0x22, 
+0x0a, 0x60, 0x01, 0x30, 0x10, 0x28, 0xfb, 0xd3, 0x10, 0x20, 0x00, 0xab, 
+0x58, 0x70, 0x04, 0x98, 0xc0, 0x46, 0x02, 0x90, 0x05, 0x98, 0xc0, 0x46, 
+0x03, 0x90, 0x68, 0x46, 0x06, 0xa9, 0xff, 0xf7, 0x0f, 0xfb, 0x20, 0x1c, 
+0x46, 0xb0, 0xb0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0xff, 0x01, 0x00, 0x00, 
+0x24, 0x02, 0xff, 0xff, 0x9d, 0xaf, 0x21, 0x40, 0x3c, 0x02, 0xff, 0xff, 
 0xf0, 0xb5, 0xc6, 0xb0, 0x07, 0x1c, 0x69, 0x46, 0x38, 0x1c, 0xff, 0xf7, 
-0xcf, 0xfb, 0xfc, 0x88, 0x78, 0x78, 0x01, 0x25, 0x10, 0x28, 0x02, 0xd1, 
-0x43, 0x01, 0x9c, 0x42, 0x09, 0xd3, 0x00, 0xa8, 0x00, 0x78, 0x40, 0x23, 
-0x18, 0x43, 0x00, 0xab, 0x18, 0x70, 0x02, 0x20, 0xd8, 0x80, 0x04, 0x33, 
-0x27, 0xe0, 0xb8, 0x68, 0xc0, 0x46, 0x04, 0x90, 0xf8, 0x68, 0xc0, 0x46, 
-0x05, 0x90, 0x06, 0xaa, 0xfb, 0x1d, 0x09, 0x33, 0x00, 0x21, 0x78, 0x78, 
-0x00, 0x28, 0x0d, 0xdd, 0x00, 0x20, 0x40, 0xcb, 0x40, 0xc2, 0x01, 0x30, 
-0x00, 0x04, 0x00, 0x0c, 0x04, 0x28, 0xf8, 0xdb, 0x48, 0x1c, 0x01, 0x04, 
-0x09, 0x0c, 0x78, 0x78, 0x88, 0x42, 0xf1, 0xdc, 0x0a, 0x48, 0xff, 0xf7, 
-0x83, 0xf9, 0x07, 0x1c, 0x09, 0x4a, 0x20, 0x1c, 0x04, 0xa9, 0xff, 0xf7, 
-0x7f, 0xf9, 0x08, 0x49, 0x38, 0x1c, 0xff, 0xf7, 0x7a, 0xf9, 0x68, 0x46, 
-0x00, 0x21, 0xff, 0xf7, 0xd1, 0xfa, 0x28, 0x1c, 0x46, 0xb0, 0xf0, 0xbc, 
-0x08, 0xbc, 0x18, 0x47, 0x24, 0x02, 0xff, 0xff, 0x51, 0xbf, 0x21, 0x40, 
+0xbb, 0xfb, 0xfc, 0x88, 0x78, 0x78, 0x01, 0x25, 0x10, 0x28, 0x01, 0xd1, 
+0x19, 0x2c, 0x09, 0xd9, 0x00, 0xa8, 0x00, 0x78, 0x40, 0x23, 0x18, 0x43, 
+0x00, 0xab, 0x18, 0x70, 0x02, 0x20, 0xd8, 0x80, 0x04, 0x33, 0x27, 0xe0, 
+0xb8, 0x68, 0xc0, 0x46, 0x04, 0x90, 0xf8, 0x68, 0xc0, 0x46, 0x05, 0x90, 
+0x06, 0xaa, 0xfb, 0x1d, 0x09, 0x33, 0x00, 0x21, 0x78, 0x78, 0x00, 0x28, 
+0x0d, 0xdd, 0x00, 0x20, 0x40, 0xcb, 0x40, 0xc2, 0x01, 0x30, 0x00, 0x04, 
+0x00, 0x0c, 0x04, 0x28, 0xf8, 0xdb, 0x48, 0x1c, 0x01, 0x04, 0x09, 0x0c, 
+0x78, 0x78, 0x88, 0x42, 0xf1, 0xdc, 0x0b, 0x48, 0xff, 0xf7, 0x7e, 0xf9, 
+0x07, 0x1c, 0x0a, 0x4a, 0x20, 0x1c, 0x04, 0xa9, 0xff, 0xf7, 0x7a, 0xf9, 
+0x08, 0x49, 0x38, 0x1c, 0xff, 0xf7, 0x75, 0xf9, 0x68, 0x46, 0x00, 0x21, 
+0xff, 0xf7, 0xbe, 0xfa, 0x28, 0x1c, 0x46, 0xb0, 0xf0, 0xbc, 0x08, 0xbc, 
+0x18, 0x47, 0x00, 0x00, 0x24, 0x02, 0xff, 0xff, 0xc5, 0xaf, 0x21, 0x40, 
 0x3c, 0x02, 0xff, 0xff, 0xf0, 0xb5, 0x84, 0xb0, 0x04, 0x1c, 0x00, 0x27, 
 0xe6, 0x88, 0xa2, 0x68, 0x47, 0x49, 0x08, 0x79, 0x00, 0x28, 0x08, 0xd0, 
 0x00, 0x2e, 0x01, 0xd0, 0x01, 0x2e, 0x01, 0xd1, 0x01, 0x27, 0x01, 0xe0, 
@@ -2439,110 +2380,110 @@
 0x66, 0xd2, 0x02, 0xa3, 0x9b, 0x5d, 0x5b, 0x00, 0x9f, 0x44, 0x00, 0x1c, 
 0x03, 0x06, 0x08, 0x0c, 0x10, 0x00, 0x05, 0x80, 0x00, 0x23, 0x03, 0xe0, 
 0x05, 0x80, 0x05, 0xe0, 0x00, 0x23, 0x03, 0x80, 0x43, 0x80, 0x06, 0xe0, 
-0x00, 0x23, 0x03, 0x80, 0x45, 0x80, 0x02, 0xe0, 
-0xff, 0x23, 0x01, 0x33, 0x03, 0x80, 0xcb, 0x1d, 0x79, 0x33, 0x9e, 0x89, 
-0x01, 0x23, 0x5b, 0x02, 0x9e, 0x42, 0x02, 0xdb, 0xd2, 0x07, 0xd2, 0x0f, 
-0x00, 0xe0, 0x01, 0x22, 0x6d, 0x23, 0x5b, 0x01, 0xc9, 0x18, 0x89, 0x88, 
-0xff, 0x23, 0xe1, 0x33, 0x99, 0x43, 0x01, 0x23, 0x19, 0x43, 0x06, 0x88, 
-0xff, 0x33, 0x9e, 0x42, 0x0d, 0xd1, 0xff, 0x20, 0xe1, 0x30, 0x08, 0x43, 
-0x00, 0x2a, 0x04, 0xd1, 0x01, 0x23, 0x9b, 0x02, 0x98, 0x43, 0x01, 0x1c, 
-0x20, 0xe0, 0x01, 0x21, 0x89, 0x02, 0x01, 0x43, 0x1c, 0xe0, 0x01, 0x2e, 
-0x0a, 0xd1, 0x40, 0x88, 0x01, 0x28, 0x04, 0xd1, 0x60, 0x23, 0x19, 0x43, 
-0x00, 0x2a, 0x13, 0xd0, 0x0c, 0xe0, 0x20, 0x23, 0x19, 0x43, 0x0f, 0xe0, 
-0x00, 0x2e, 0x0d, 0xd1, 0x40, 0x88, 0x01, 0x28, 0x08, 0xd1, 0xff, 0x23, 
-0x81, 0x33, 0x19, 0x43, 0x00, 0x2a, 0x05, 0xd0, 0x01, 0x23, 0x9b, 0x02, 
-0x19, 0x43, 0x01, 0xe0, 0x80, 0x23, 0x19, 0x43, 0x04, 0x20, 0x03, 0xf0, 
-0x2d, 0xf8, 0x09, 0x21, 0x49, 0x02, 0x00, 0x20, 0x03, 0xf0, 0x28, 0xf8, 
-0x00, 0x2f, 0x02, 0xd1, 0x00, 0x20, 0x12, 0xe0, 0xff, 0xe7, 0x69, 0x46, 
-0x20, 0x1c, 0xff, 0xf7, 0x03, 0xfb, 0x00, 0xa8, 0x00, 0x78, 0x40, 0x23, 
-0x18, 0x43, 0x00, 0xab, 0x18, 0x70, 0x02, 0x20, 0xd8, 0x80, 0x68, 0x46, 
-0x00, 0x21, 0x04, 0x33, 0xff, 0xf7, 0x36, 0xfa, 0x28, 0x1c, 0x04, 0xb0, 
+0x00, 0x23, 0x03, 0x80, 0x45, 0x80, 0x02, 0xe0, 0xff, 0x23, 0x01, 0x33, 
+0x03, 0x80, 0xcb, 0x1d, 0x79, 0x33, 0x9e, 0x89, 0x01, 0x23, 0x5b, 0x02, 
+0x9e, 0x42, 0x02, 0xdb, 0xd2, 0x07, 0xd2, 0x0f, 0x00, 0xe0, 0x01, 0x22, 
+0x6d, 0x23, 0x5b, 0x01, 0xc9, 0x18, 0x89, 0x88, 0xff, 0x23, 0xe1, 0x33, 
+0x99, 0x43, 0x01, 0x23, 0x19, 0x43, 0x06, 0x88, 0xff, 0x33, 0x9e, 0x42, 
+0x0d, 0xd1, 0xff, 0x20, 0xe1, 0x30, 0x08, 0x43, 0x00, 0x2a, 0x04, 0xd1, 
+0x01, 0x23, 0x9b, 0x02, 0x98, 0x43, 0x01, 0x1c, 0x20, 0xe0, 0x01, 0x21, 
+0x89, 0x02, 0x01, 0x43, 0x1c, 0xe0, 0x01, 0x2e, 0x0a, 0xd1, 0x40, 0x88, 
+0x01, 0x28, 0x04, 0xd1, 0x60, 0x23, 0x19, 0x43, 0x00, 0x2a, 0x13, 0xd0, 
+0x0c, 0xe0, 0x20, 0x23, 0x19, 0x43, 0x0f, 0xe0, 0x00, 0x2e, 0x0d, 0xd1, 
+0x40, 0x88, 0x01, 0x28, 0x08, 0xd1, 0xff, 0x23, 0x81, 0x33, 0x19, 0x43, 
+0x00, 0x2a, 0x05, 0xd0, 0x01, 0x23, 0x9b, 0x02, 0x19, 0x43, 0x01, 0xe0, 
+0x80, 0x23, 0x19, 0x43, 0x04, 0x20, 0x02, 0xf0, 0x75, 0xf9, 0x09, 0x21, 
+0x49, 0x02, 0x00, 0x20, 0x02, 0xf0, 0x70, 0xf9, 0x00, 0x2f, 0x02, 0xd1, 
+0x00, 0x20, 0x12, 0xe0, 0xff, 0xe7, 0x69, 0x46, 0x20, 0x1c, 0xff, 0xf7, 
+0xef, 0xfa, 0x00, 0xa8, 0x00, 0x78, 0x40, 0x23, 0x18, 0x43, 0x00, 0xab, 
+0x18, 0x70, 0x02, 0x20, 0xd8, 0x80, 0x68, 0x46, 0x00, 0x21, 0x04, 0x33, 
+0xff, 0xf7, 0x22, 0xfa, 0x28, 0x1c, 0x04, 0xb0, 
 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0x68, 0x0e, 0x00, 0x80, 
 0x88, 0x1c, 0x00, 0x80, 0xc0, 0x88, 0x51, 0x21, 0x89, 0x03, 0x08, 0x62, 
 0x00, 0x20, 0x70, 0x47, 0x80, 0xb5, 0x16, 0x4f, 0xf8, 0x68, 0x01, 0x28, 
 0x07, 0xd1, 0x37, 0x23, 0x9b, 0x01, 0xf8, 0x18, 0x40, 0x8a, 0x80, 0x21, 
 0x01, 0x43, 0x1b, 0x20, 0x07, 0xe0, 0x6d, 0x23, 0x5b, 0x01, 0xf8, 0x18, 
 0x80, 0x8b, 0x01, 0x21, 0x49, 0x03, 0x01, 0x43, 0x10, 0x20, 0x02, 0xf0, 
-0xeb, 0xff, 0x01, 0x20, 0x71, 0x23, 0x5b, 0x01, 0xf9, 0x18, 0x08, 0x80, 
+0x33, 0xf9, 0x01, 0x20, 0x71, 0x23, 0x5b, 0x01, 0xf9, 0x18, 0x08, 0x80, 
 0x48, 0x80, 0x1b, 0x23, 0xdb, 0x01, 0xf8, 0x18, 0x80, 0x8b, 0x01, 0x23, 
 0x1b, 0x03, 0x98, 0x43, 0x41, 0x21, 0x09, 0x02, 0x01, 0x43, 0x00, 0x20, 
-0x02, 0xf0, 0xd8, 0xff, 0x00, 0x20, 0x80, 0xbc, 0x08, 0xbc, 0x18, 0x47, 
+0x02, 0xf0, 0x20, 0xf9, 0x00, 0x20, 0x80, 0xbc, 0x08, 0xbc, 0x18, 0x47, 
 0x68, 0x0e, 0x00, 0x80, 0x80, 0xb5, 0x17, 0x4f, 0xf8, 0x68, 0x01, 0x28, 
 0x08, 0xd1, 0x37, 0x23, 0x9b, 0x01, 0xf8, 0x18, 0x40, 0x8a, 0x80, 0x23, 
 0x98, 0x43, 0x01, 0x1c, 0x1b, 0x20, 0x08, 0xe0, 0x6d, 0x23, 0x5b, 0x01, 
 0xf8, 0x18, 0x80, 0x8b, 0x01, 0x23, 0x5b, 0x03, 0x98, 0x43, 0x01, 0x1c, 
-0x10, 0x20, 0x02, 0xf0, 0xb9, 0xff, 0xff, 0x20, 0x71, 0x23, 0x5b, 0x01, 
+0x10, 0x20, 0x02, 0xf0, 0x01, 0xf9, 0xff, 0x20, 0x71, 0x23, 0x5b, 0x01, 
 0xf9, 0x18, 0x01, 0x30, 0x08, 0x80, 0x1b, 0x23, 0xdb, 0x01, 0xf8, 0x18, 
 0x80, 0x8b, 0x41, 0x23, 0x1b, 0x02, 0x98, 0x43, 0x09, 0x21, 0x49, 0x02, 
-0x01, 0x43, 0x00, 0x20, 0x02, 0xf0, 0xa6, 0xff, 0x00, 0x20, 0x80, 0xbc, 
+0x01, 0x43, 0x00, 0x20, 0x02, 0xf0, 0xee, 0xf8, 0x00, 0x20, 0x80, 0xbc, 
 0x08, 0xbc, 0x18, 0x47, 0x68, 0x0e, 0x00, 0x80, 0x80, 0xb5, 0x84, 0xb0, 
-0x08, 0x49, 0xcf, 0x6a, 0x69, 0x46, 0xff, 0xf7, 0x7d, 0xfa, 0xb8, 0x05, 
+0x08, 0x49, 0xcf, 0x6a, 0x69, 0x46, 0xff, 0xf7, 0x69, 0xfa, 0xb8, 0x05, 
 0x80, 0x0d, 0x01, 0xab, 0x58, 0x80, 0x68, 0x46, 0x00, 0x21, 0xff, 0xf7, 
-0xb5, 0xf9, 0x01, 0x20, 0x04, 0xb0, 0x80, 0xbc, 0x08, 0xbc, 0x18, 0x47, 
+0xa1, 0xf9, 0x01, 0x20, 0x04, 0xb0, 0x80, 0xbc, 0x08, 0xbc, 0x18, 0x47, 
 0x40, 0x00, 0x14, 0x40, 0xc0, 0x88, 0x9f, 0x23, 0x18, 0x40, 0x05, 0x49, 
 0xc9, 0x6a, 0x1b, 0x23, 0x5b, 0x01, 0x19, 0x40, 0x08, 0x43, 0x03, 0x49, 
 0xc0, 0x46, 0xc8, 0x62, 0x00, 0x20, 0x70, 0x47, 0x40, 0x00, 0x14, 0x40, 
-0x40, 0x00, 0x14, 0x00, 0x80, 0xb5, 0x84, 0xb0, 
-0x0d, 0x49, 0x0f, 0x6a, 0x01, 0x2f, 0x01, 0xd1, 0xff, 0x03, 0x07, 0xe0, 
-0x02, 0x2f, 0x01, 0xd1, 0x3f, 0x03, 0x03, 0xe0, 0x00, 0x2f, 0x01, 0xd1, 
-0x01, 0x27, 0xff, 0x02, 0x69, 0x46, 0xff, 0xf7, 0x49, 0xfa, 0x01, 0xab, 
-0x5f, 0x80, 0x68, 0x46, 0x00, 0x21, 0xff, 0xf7, 0x83, 0xf9, 0x01, 0x20, 
-0x04, 0xb0, 0x80, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x20, 0x14, 0x40, 
-0xc2, 0x88, 0xa1, 0x20, 0x40, 0x03, 0x00, 0x21, 0x01, 0x23, 0x5b, 0x03, 
-0x9a, 0x42, 0x01, 0xd1, 0x02, 0x22, 0x04, 0xe0, 0x01, 0x23, 0xdb, 0x03, 
-0x9a, 0x42, 0x02, 0xd1, 0x01, 0x22, 0x02, 0x62, 0x00, 0xe0, 0x01, 0x62, 
-0x08, 0x1c, 0x70, 0x47, 0x90, 0xb5, 0x84, 0xb0, 0x07, 0x1c, 0x02, 0xf0, 
-0x57, 0xff, 0x69, 0x46, 0x04, 0x1c, 0x38, 0x1c, 0xff, 0xf7, 0x1e, 0xfa, 
-0x01, 0xab, 0x5c, 0x80, 0x09, 0x4f, 0xf8, 0x6d, 0xc0, 0x46, 0x02, 0x90, 
-0x68, 0x46, 0x00, 0x21, 0xff, 0xf7, 0x54, 0xf9, 0xf8, 0x6d, 0xc0, 0x07, 
-0xc0, 0x0f, 0x05, 0x49, 0xc0, 0x46, 0xc8, 0x62, 0x01, 0x20, 0x04, 0xb0, 
-0x90, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0xa4, 0x2a, 0x00, 0x80, 
-0x68, 0x1c, 0x00, 0x80, 0xc0, 0x88, 0x02, 0x49, 0xc0, 0x46, 0x48, 0x61, 
-0x00, 0x20, 0x70, 0x47, 0x80, 0x00, 0x14, 0x00, 0x00, 0xb5, 0x84, 0xb0, 
-0x69, 0x46, 0xff, 0xf7, 0xf7, 0xf9, 0x06, 0x48, 0xc0, 0x68, 0x01, 0xab, 
-0x58, 0x80, 0x68, 0x46, 0x00, 0x21, 0xff, 0xf7, 0x2f, 0xf9, 0x01, 0x20, 
+0x40, 0x00, 0x14, 0x00, 0x80, 0xb5, 0x84, 0xb0, 0x0d, 0x49, 0x0f, 0x6a, 
+0x01, 0x2f, 0x01, 0xd1, 0xff, 0x03, 0x07, 0xe0, 0x02, 0x2f, 0x01, 0xd1, 
+0x3f, 0x03, 0x03, 0xe0, 0x00, 0x2f, 0x01, 0xd1, 0x01, 0x27, 0xff, 0x02, 
+0x69, 0x46, 0xff, 0xf7, 0x35, 0xfa, 0x01, 0xab, 0x5f, 0x80, 0x68, 0x46, 
+0x00, 0x21, 0xff, 0xf7, 0x6f, 0xf9, 0x01, 0x20, 0x04, 0xb0, 0x80, 0xbc, 
+0x08, 0xbc, 0x18, 0x47, 0x00, 0x20, 0x14, 0x40, 0xc2, 0x88, 0xa1, 0x20, 
+0x40, 0x03, 0x00, 0x21, 0x01, 0x23, 0x5b, 0x03, 0x9a, 0x42, 0x01, 0xd1, 
+0x02, 0x22, 0x04, 0xe0, 0x01, 0x23, 0xdb, 0x03, 0x9a, 0x42, 0x02, 0xd1, 
+0x01, 0x22, 0x02, 0x62, 0x00, 0xe0, 0x01, 0x62, 0x08, 0x1c, 0x70, 0x47, 
+0x90, 0xb5, 0x84, 0xb0, 0x07, 0x1c, 0x02, 0xf0, 0x9f, 0xf8, 0x69, 0x46, 
+0x04, 0x1c, 0x38, 0x1c, 0xff, 0xf7, 0x0a, 0xfa, 0x01, 0xab, 0x5c, 0x80, 
+0x09, 0x4f, 0xf8, 0x6d, 0xc0, 0x46, 0x02, 0x90, 0x68, 0x46, 0x00, 0x21, 
+0xff, 0xf7, 0x40, 0xf9, 0xf8, 0x6d, 0xc0, 0x07, 0xc0, 0x0f, 0x05, 0x49, 
+0xc0, 0x46, 0xc8, 0x62, 0x01, 0x20, 0x04, 0xb0, 0x90, 0xbc, 0x08, 0xbc, 
+0x18, 0x47, 0x00, 0x00, 0xa4, 0x2a, 0x00, 0x80, 0x68, 0x1c, 0x00, 0x80, 
+0xc0, 0x88, 0x02, 0x49, 0xc0, 0x46, 0x48, 0x61, 0x00, 0x20, 0x70, 0x47, 
+0x80, 0x00, 0x14, 0x00, 0x00, 0xb5, 0x84, 0xb0, 0x69, 0x46, 0xff, 0xf7, 
+0xe3, 0xf9, 0x06, 0x48, 0xc0, 0x68, 0x01, 0xab, 
+0x58, 0x80, 0x68, 0x46, 0x00, 0x21, 0xff, 0xf7, 0x1b, 0xf9, 0x01, 0x20, 
 0x04, 0xb0, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0x80, 0x00, 0x14, 0x40, 
 0xc0, 0x88, 0x02, 0x49, 0xc0, 0x46, 0xc8, 0x60, 0x00, 0x20, 0x70, 0x47, 
 0x80, 0x00, 0x14, 0x00, 0x80, 0xb5, 0x84, 0xb0, 0x69, 0x46, 0x87, 0x68, 
-0xff, 0xf7, 0xda, 0xf9, 0x20, 0x2f, 0x07, 0xd2, 0x78, 0x00, 0x0c, 0x49, 
+0xff, 0xf7, 0xc6, 0xf9, 0x20, 0x2f, 0x07, 0xd2, 0x78, 0x00, 0x0c, 0x49, 
 0x40, 0x18, 0x1b, 0x23, 0xdb, 0x01, 0xc0, 0x18, 0x80, 0x8b, 0x06, 0xe0, 
 0x00, 0xa8, 0x00, 0x78, 0x40, 0x23, 0x18, 0x43, 0x00, 0xab, 0x18, 0x70, 
 0x02, 0x20, 0x01, 0xab, 0x58, 0x80, 0x68, 0x46, 0x00, 0x21, 0xff, 0xf7, 
-0x03, 0xf9, 0x01, 0x20, 0x04, 0xb0, 0x80, 0xbc, 0x08, 0xbc, 0x18, 0x47, 
+0xef, 0xf8, 0x01, 0x20, 0x04, 0xb0, 0x80, 0xbc, 0x08, 0xbc, 0x18, 0x47, 
 0x68, 0x0e, 0x00, 0x80, 0x00, 0xb5, 0x84, 0xb0, 0xc1, 0x88, 0x82, 0x68, 
-0x20, 0x2a, 0x04, 0xd2, 0x10, 0x1c, 0x02, 0xf0, 0xcf, 0xfe, 0x00, 0x20, 
-0x10, 0xe0, 0x69, 0x46, 0xff, 0xf7, 0xae, 0xf9, 0x00, 0xa8, 0x00, 0x78, 
+0x20, 0x2a, 0x04, 0xd2, 0x10, 0x1c, 0x02, 0xf0, 0x17, 0xf8, 0x00, 0x20, 
+0x10, 0xe0, 0x69, 0x46, 0xff, 0xf7, 0x9a, 0xf9, 0x00, 0xa8, 0x00, 0x78, 
 0x40, 0x23, 0x18, 0x43, 0x00, 0xab, 0x18, 0x70, 0x02, 0x20, 0xd8, 0x80, 
-0x68, 0x46, 0x00, 0x21, 0x04, 0x33, 0xff, 0xf7, 0xe1, 0xf8, 0x01, 0x20, 
+0x68, 0x46, 0x00, 0x21, 0x04, 0x33, 0xff, 0xf7, 0xcd, 0xf8, 0x01, 0x20, 
 0x04, 0xb0, 0x08, 0xbc, 0x18, 0x47, 0x90, 0xb5, 0x84, 0xb0, 0xc7, 0x88, 
-0x69, 0x46, 0xff, 0xf7, 0x97, 0xf9, 0x10, 0x48, 0xfe, 0xf7, 0x78, 0xff, 
-0x02, 0x20, 0x39, 0x1c, 0x03, 0xf0, 0x3c, 0xfe, 0x00, 0x28, 0x06, 0xd0, 
-0x02, 0x20, 0x39, 0x1c, 0x03, 0xf0, 0x8c, 0xfd, 0x01, 0xab, 0x58, 0x80, 
+0x69, 0x46, 0xff, 0xf7, 0x83, 0xf9, 0x10, 0x48, 0xfe, 0xf7, 0x72, 0xff, 
+0x02, 0x20, 0x39, 0x1c, 0x02, 0xf0, 0xf2, 0xff, 0x00, 0x28, 0x06, 0xd0, 
+0x02, 0x20, 0x39, 0x1c, 0x02, 0xf0, 0x36, 0xff, 0x01, 0xab, 0x58, 0x80, 
 0x02, 0xe0, 0x45, 0x20, 0x00, 0xab, 0x18, 0x70, 0x07, 0x49, 0x20, 0x1c, 
-0xfe, 0xf7, 0x65, 0xff, 0x68, 0x46, 0x00, 0x21, 0xff, 0xf7, 0xbc, 0xf8, 
+0xfe, 0xf7, 0x5f, 0xff, 0x68, 0x46, 0x00, 0x21, 0xff, 0xf7, 0xa8, 0xf8, 
 0x01, 0x20, 0x04, 0xb0, 0x90, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 
 0x24, 0x02, 0xff, 0xff, 0x3c, 0x02, 0xff, 0xff, 0xb0, 0xb5, 0x84, 0xb0, 
-0xc7, 0x88, 0x69, 0x46, 0x84, 0x68, 0xff, 0xf7, 0x6b, 0xf9, 0x10, 0x48, 
-0xfe, 0xf7, 0x4c, 0xff, 0x0f, 0x4a, 0x02, 0x20, 0x39, 0x1c, 0xfe, 0xf7, 
-0x49, 0xff, 0x00, 0x28, 0x06, 0xd0, 0x0d, 0x4b, 0x02, 0x20, 0x39, 0x1c, 
-0x22, 0x1c, 0xfe, 0xf7, 0x42, 0xff, 0x02, 0xe0, 
-0x45, 0x20, 0x00, 0xab, 0x18, 0x70, 0x09, 0x49, 0x28, 0x1c, 0xfe, 0xf7, 
-0x38, 0xff, 0x68, 0x46, 0x00, 0x21, 0xff, 0xf7, 0x8f, 0xf8, 0x01, 0x20, 
-0x04, 0xb0, 0xb0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x24, 0x02, 0xff, 0xff, 
-0xcd, 0xc0, 0x21, 0x40, 0xd9, 0xbf, 0x21, 0x40, 0x3c, 0x02, 0xff, 0xff, 
-0x00, 0xb5, 0xff, 0xf7, 0x57, 0xf9, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x20, 
-0x70, 0x47, 0x80, 0xb4, 0xc2, 0x88, 0x19, 0x4b, 0xa1, 0x21, 0x49, 0x03, 
-0x00, 0x2a, 0x03, 0xd1, 0x18, 0x6b, 0x10, 0x23, 0x98, 0x43, 0x04, 0xe0, 
-0x01, 0x2a, 0x04, 0xd1, 0x18, 0x6b, 0x10, 0x23, 0x18, 0x43, 0x48, 0x61, 
-0x1f, 0xe0, 0x02, 0x2a, 0x1d, 0xd1, 0xc2, 0x68, 0x87, 0x68, 0x00, 0x20, 
-0x3b, 0x1c, 0xc3, 0x40, 0xdb, 0x07, 0xdb, 0x0f, 0x9b, 0x02, 0x03, 0x43, 
-0x0b, 0x61, 0x01, 0x30, 0x00, 0x04, 0x00, 0x0c, 0x20, 0x28, 0xf3, 0xdb, 
-0x00, 0x20, 0x13, 0x1c, 0xc3, 0x40, 0xdb, 0x07, 0xdb, 0x0f, 0x9b, 0x02, 
-0xc7, 0x1d, 0x19, 0x37, 0x3b, 0x43, 0x0b, 0x61, 0x01, 0x30, 0x00, 0x04, 
-0x00, 0x0c, 0x20, 0x28, 0xf1, 0xdb, 0x00, 0x20, 0x80, 0xbc, 0x70, 0x47, 
-0x80, 0x00, 0x14, 0x40, 0x80, 0xb4, 0xc2, 0x88, 0x81, 0x68, 0x10, 0x02, 
-0x12, 0x0a, 0x10, 0x43, 0x02, 0x04, 0x12, 0x0c, 0x0c, 0x48, 0xc0, 0x46, 
-0x02, 0x60, 0x0c, 0x4b, 0xc0, 0x46, 0x1a, 0x80, 0x0a, 0x0c, 0x17, 0x02, 
+0xc7, 0x88, 0x69, 0x46, 0x84, 0x68, 0xff, 0xf7, 0x57, 0xf9, 0x10, 0x48, 
+0xfe, 0xf7, 0x46, 0xff, 0x0f, 0x4a, 0x02, 0x20, 0x39, 0x1c, 0xfe, 0xf7, 
+0x43, 0xff, 0x00, 0x28, 0x06, 0xd0, 0x0d, 0x4b, 0x02, 0x20, 0x39, 0x1c, 
+0x22, 0x1c, 0xfe, 0xf7, 0x3c, 0xff, 0x02, 0xe0, 0x45, 0x20, 0x00, 0xab, 
+0x18, 0x70, 0x09, 0x49, 0x28, 0x1c, 0xfe, 0xf7, 0x32, 0xff, 0x68, 0x46, 
+0x00, 0x21, 0xff, 0xf7, 0x7b, 0xf8, 0x01, 0x20, 0x04, 0xb0, 0xb0, 0xbc, 
+0x08, 0xbc, 0x18, 0x47, 0x24, 0x02, 0xff, 0xff, 0x59, 0xb1, 0x21, 0x40, 
+0x59, 0xb0, 0x21, 0x40, 0x3c, 0x02, 0xff, 0xff, 0x00, 0xb5, 0xff, 0xf7, 
+0x43, 0xf9, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x20, 0x70, 0x47, 0x80, 0xb4, 
+0xc2, 0x88, 0x19, 0x4b, 0xa1, 0x21, 0x49, 0x03, 0x00, 0x2a, 0x03, 0xd1, 
+0x18, 0x6b, 0x10, 0x23, 0x98, 0x43, 0x04, 0xe0, 0x01, 0x2a, 0x04, 0xd1, 
+0x18, 0x6b, 0x10, 0x23, 0x18, 0x43, 0x48, 0x61, 0x1f, 0xe0, 0x02, 0x2a, 
+0x1d, 0xd1, 0xc2, 0x68, 0x87, 0x68, 0x00, 0x20, 0x3b, 0x1c, 0xc3, 0x40, 
+0xdb, 0x07, 0xdb, 0x0f, 0x9b, 0x02, 0x03, 0x43, 0x0b, 0x61, 0x01, 0x30, 
+0x00, 0x04, 0x00, 0x0c, 0x20, 0x28, 0xf3, 0xdb, 0x00, 0x20, 0x13, 0x1c, 
+0xc3, 0x40, 0xdb, 0x07, 0xdb, 0x0f, 0x9b, 0x02, 0xc7, 0x1d, 0x19, 0x37, 
+0x3b, 0x43, 0x0b, 0x61, 0x01, 0x30, 0x00, 0x04, 0x00, 0x0c, 0x20, 0x28, 
+0xf1, 0xdb, 0x00, 0x20, 0x80, 0xbc, 0x70, 0x47, 0x80, 0x00, 0x14, 0x40, 
+0x80, 0xb4, 0xc2, 0x88, 0x81, 0x68, 0x10, 0x02, 0x12, 0x0a, 0x10, 0x43, 
+0x02, 0x04, 0x12, 0x0c, 0x0c, 0x48, 0xc0, 0x46, 0x02, 0x60, 0x0c, 0x4b, 
+0xc0, 0x46, 0x1a, 0x80, 0x0a, 0x0c, 0x17, 0x02, 
 0x12, 0x12, 0x3a, 0x43, 0x12, 0x04, 0x12, 0x0c, 0x42, 0x60, 0x5a, 0x80, 
 0x09, 0x04, 0x09, 0x0c, 0x0a, 0x02, 0x09, 0x0a, 0x11, 0x43, 0x09, 0x04, 
 0x09, 0x0c, 0x81, 0x60, 0x99, 0x80, 0x00, 0x20, 0x80, 0xbc, 0x70, 0x47, 
@@ -2551,8 +2492,8 @@
 0x13, 0x43, 0x4a, 0x68, 0x12, 0x04, 0x12, 0x0c, 0x1f, 0x1c, 0x13, 0x02, 
 0x12, 0x12, 0x13, 0x43, 0x89, 0x68, 0x09, 0x04, 0x09, 0x0c, 0x0a, 0x02, 
 0x09, 0x12, 0x11, 0x43, 0x0c, 0x04, 0x24, 0x0c, 0x69, 0x46, 0x1d, 0x1c, 
-0xff, 0xf7, 0xc2, 0xf8, 0x01, 0xab, 0x5f, 0x80, 0x28, 0x04, 0x20, 0x43, 
-0x02, 0x90, 0x68, 0x46, 0x00, 0x21, 0xfe, 0xf7, 0xf9, 0xff, 0x01, 0x20, 
+0xff, 0xf7, 0xae, 0xf8, 0x01, 0xab, 0x5f, 0x80, 0x28, 0x04, 0x20, 0x43, 
+0x02, 0x90, 0x68, 0x46, 0x00, 0x21, 0xfe, 0xf7, 0xe5, 0xff, 0x01, 0x20, 
 0x04, 0xb0, 0xb0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x40, 0x00, 0x14, 0x40, 
 0xc1, 0x88, 0x82, 0x68, 0x08, 0x02, 0x09, 0x0a, 0x08, 0x43, 0x00, 0x04, 
 0x00, 0x0c, 0x0a, 0x49, 0xc0, 0x46, 0xc8, 0x60, 0x10, 0x0c, 0x03, 0x02, 
@@ -2566,415 +2507,126 @@
 0x00, 0x93, 0x84, 0x88, 0x01, 0xab, 0x1c, 0x80, 0x00, 0x24, 0x04, 0x3b, 
 0x5c, 0x70, 0x40, 0x88, 0x00, 0xab, 0x58, 0x80, 0xd9, 0x80, 0x10, 0x04, 
 0x38, 0x43, 0x02, 0x90, 0x03, 0x94, 0x68, 0x46, 0x00, 0x21, 0xfe, 0xf7, 
-0xa9, 0xff, 0x01, 0x20, 0x04, 0xb0, 0x90, 0xbc, 0x08, 0xbc, 0x18, 0x47, 
+0x95, 0xff, 0x01, 0x20, 0x04, 0xb0, 0x90, 0xbc, 0x08, 0xbc, 0x18, 0x47, 
 0x40, 0x00, 0x14, 0x40, 0x00, 0xb5, 0x84, 0xb0, 0x0b, 0x49, 0x8a, 0x6a, 
-0x05, 0x21, 0x00, 0x91, 0x81, 0x88, 0x01, 0xab, 
-0x19, 0x80, 0x00, 0x21, 0x04, 0x3b, 0x59, 0x70, 0x40, 0x88, 0x00, 0xab, 
-0x58, 0x80, 0xda, 0x80, 0x02, 0x91, 0x03, 0x91, 0x68, 0x46, 0xfe, 0xf7, 
-0x8d, 0xff, 0x01, 0x20, 0x04, 0xb0, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 
-0xc0, 0x00, 0x14, 0x40, 0xc0, 0x88, 0x02, 0x49, 0xc0, 0x46, 0x88, 0x62, 
-0x00, 0x20, 0x70, 0x47, 0xc0, 0x00, 0x14, 0x00, 0x00, 0xb5, 0x84, 0xb0, 
-0x0b, 0x49, 0x0a, 0x6a, 0x05, 0x21, 0x00, 0x91, 0x81, 0x88, 0x01, 0xab, 
-0x19, 0x80, 0x00, 0x21, 0x04, 0x3b, 0x59, 0x70, 0x40, 0x88, 0x00, 0xab, 
-0x58, 0x80, 0xda, 0x80, 0x02, 0x91, 0x03, 0x91, 0x68, 0x46, 0xfe, 0xf7, 
-0x69, 0xff, 0x01, 0x20, 0x04, 0xb0, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 
-0xc0, 0x00, 0x14, 0x40, 0xc0, 0x88, 0x02, 0x49, 0xc0, 0x46, 0x08, 0x62, 
-0x00, 0x20, 0x70, 0x47, 0xc0, 0x00, 0x14, 0x00, 0x00, 0xb5, 0xc0, 0x88, 
-0x02, 0x49, 0xfe, 0xf7, 0xfa, 0xfd, 0x00, 0x20, 0x08, 0xbc, 0x18, 0x47, 
-0x75, 0x02, 0xff, 0xff, 0x00, 0xb5, 0x84, 0xb0, 0x69, 0x46, 0xff, 0xf7, 
-0x0b, 0xf8, 0x06, 0x48, 0x00, 0x6b, 0x01, 0xab, 0x58, 0x80, 0x68, 0x46, 
-0x00, 0x21, 0xfe, 0xf7, 0x43, 0xff, 0x01, 0x20, 0x04, 0xb0, 0x08, 0xbc, 
-0x18, 0x47, 0x00, 0x00, 0x68, 0x0e, 0x00, 0x80, 0x00, 0xb5, 0xff, 0xf7, 
-0x11, 0xf8, 0x08, 0xbc, 0x18, 0x47, 0x00, 0xb5, 0xff, 0xf7, 0x0c, 0xf8, 
-0x08, 0xbc, 0x18, 0x47, 0x00, 0xb5, 0xff, 0xf7, 0x07, 0xf8, 0x08, 0xbc, 
-0x18, 0x47, 0x80, 0xb5, 0x07, 0x1c, 0x10, 0x48, 0xfe, 0xf7, 0xcc, 0xfd, 
+0x05, 0x21, 0x00, 0x91, 0x81, 0x88, 0x01, 0xab, 0x19, 0x80, 0x00, 0x21, 
+0x04, 0x3b, 0x59, 0x70, 0x40, 0x88, 0x00, 0xab, 0x58, 0x80, 0xda, 0x80, 
+0x02, 0x91, 0x03, 0x91, 0x68, 0x46, 0xfe, 0xf7, 0x79, 0xff, 0x01, 0x20, 
+0x04, 0xb0, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0xc0, 0x00, 0x14, 0x40, 
+0xc0, 0x88, 0x02, 0x49, 0xc0, 0x46, 0x88, 0x62, 0x00, 0x20, 0x70, 0x47, 
+0xc0, 0x00, 0x14, 0x00, 0x00, 0xb5, 0x84, 0xb0, 0x0b, 0x49, 0x0a, 0x6a, 
+0x05, 0x21, 0x00, 0x91, 0x81, 0x88, 0x01, 0xab, 0x19, 0x80, 0x00, 0x21, 
+0x04, 0x3b, 0x59, 0x70, 0x40, 0x88, 0x00, 0xab, 0x58, 0x80, 0xda, 0x80, 
+0x02, 0x91, 0x03, 0x91, 0x68, 0x46, 0xfe, 0xf7, 0x55, 0xff, 0x01, 0x20, 
+0x04, 0xb0, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0xc0, 0x00, 0x14, 0x40, 
+0xc0, 0x88, 0x02, 0x49, 0xc0, 0x46, 0x08, 0x62, 0x00, 0x20, 0x70, 0x47, 
+0xc0, 0x00, 0x14, 0x00, 0x00, 0xb5, 0xc0, 0x88, 0x02, 0x49, 0xfe, 0xf7, 
+0xf4, 0xfd, 0x00, 0x20, 0x08, 0xbc, 0x18, 0x47, 0x75, 0x02, 0xff, 0xff, 
+0x00, 0xb5, 0x84, 0xb0, 0x69, 0x46, 0xfe, 0xf7, 0xf7, 0xff, 0x06, 0x48, 
+0x00, 0x6b, 0x01, 0xab, 0x58, 0x80, 0x68, 0x46, 0x00, 0x21, 0xfe, 0xf7, 
+0x2f, 0xff, 0x01, 0x20, 0x04, 0xb0, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 
+0x68, 0x0e, 0x00, 0x80, 0x00, 0xb5, 0xfe, 0xf7, 0xfd, 0xff, 0x08, 0xbc, 
+0x18, 0x47, 0x00, 0xb5, 0xfe, 0xf7, 0xf8, 0xff, 
+0x08, 0xbc, 0x18, 0x47, 0x00, 0xb5, 0xfe, 0xf7, 0xf3, 0xff, 0x08, 0xbc, 
+0x18, 0x47, 0x80, 0xb5, 0x07, 0x1c, 0x10, 0x48, 0xfe, 0xf7, 0xc6, 0xfd, 
 0x01, 0x20, 0x40, 0x02, 0xa1, 0x21, 0x49, 0x03, 0x88, 0x60, 0x00, 0x21, 
 0x0c, 0x48, 0xc0, 0x46, 0x01, 0x71, 0x0c, 0x48, 0x02, 0x68, 0x52, 0x0c, 
 0x05, 0xd2, 0x02, 0x68, 0x12, 0x0c, 0x06, 0xd1, 0x00, 0x68, 0x80, 0x0a, 
 0x03, 0xd3, 0x08, 0x48, 0xc0, 0x46, 0xc7, 0x60, 0x02, 0xe0, 0x07, 0x48, 
 0xc0, 0x46, 0x07, 0x64, 0x08, 0x1c, 0x80, 0xbc, 0x08, 0xbc, 0x18, 0x47, 
-0x21, 0xa5, 0x21, 0x40, 0x28, 0x0f, 0x00, 0x80, 0x00, 0x00, 0x10, 0x40, 
+0xd5, 0x94, 0x21, 0x40, 0x28, 0x0f, 0x00, 0x80, 0x00, 0x00, 0x10, 0x40, 
 0x40, 0x01, 0x18, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0xb5, 0x01, 0x20, 
 0x03, 0x49, 0xc0, 0x46, 0x08, 0x72, 0x12, 0x20, 0xff, 0xf7, 0xcb, 0xff, 
 0x08, 0xbc, 0x18, 0x47, 0x88, 0x1c, 0x00, 0x80, 0x00, 0xb5, 0x01, 0x20, 
 0x03, 0x49, 0xc0, 0x46, 0x48, 0x72, 0x15, 0x20, 0xff, 0xf7, 0xbf, 0xff, 
-0x08, 0xbc, 0x18, 0x47, 0x88, 0x1c, 0x00, 0x80, 0x00, 0xb5, 0x02, 0xf0, 
-0xf3, 0xfe, 0x01, 0x20, 0x08, 0xbc, 0x18, 0x47, 0x80, 0xb5, 0x84, 0xb0, 
-0x07, 0x1c, 0xf8, 0x88, 0x02, 0xf0, 0xf8, 0xff, 0x00, 0x28, 0x0c, 0xd1, 
-0x69, 0x46, 0x38, 0x1c, 0xfe, 0xf7, 0x96, 0xff, 0x06, 0x48, 0x01, 0xab, 
-0x58, 0x80, 0x68, 0x46, 0x00, 0x21, 0xfe, 0xf7, 0xcf, 0xfe, 0x01, 0x20, 
+0x08, 0xbc, 0x18, 0x47, 0x88, 0x1c, 0x00, 0x80, 0x00, 0xb5, 0x01, 0xf0, 
+0xf9, 0xff, 0x01, 0x20, 0x08, 0xbc, 0x18, 0x47, 0x80, 0xb5, 0x84, 0xb0, 
+0x07, 0x1c, 0xf8, 0x88, 0x02, 0xf0, 0xfe, 0xf8, 0x00, 0x28, 0x0c, 0xd1, 
+0x69, 0x46, 0x38, 0x1c, 0xfe, 0xf7, 0x82, 0xff, 0x06, 0x48, 0x01, 0xab, 
+0x58, 0x80, 0x68, 0x46, 0x00, 0x21, 0xfe, 0xf7, 0xbb, 0xfe, 0x01, 0x20, 
 0x00, 0xe0, 0x00, 0x20, 0x04, 0xb0, 0x80, 0xbc, 0x08, 0xbc, 0x18, 0x47, 
-0xff, 0xff, 0x00, 0x00, 0x00, 0xb5, 0x84, 0xb0, 0x69, 0x46, 0xfe, 0xf7, 
-0x81, 0xff, 0x04, 0xf0, 0x47, 0xfa, 0x01, 0xab, 0x58, 0x80, 0x09, 0x48, 
-0x81, 0x89, 0x09, 0x04, 0xc2, 0x89, 0x11, 0x43, 0x02, 0x91, 0x81, 0x88, 
-0x09, 0x04, 0xc0, 0x88, 0x08, 0x43, 0x03, 0x90, 0x68, 0x46, 0x00, 0x21, 
-0xfe, 0xf7, 0xae, 0xfe, 0x01, 0x20, 0x04, 0xb0, 0x08, 0xbc, 0x18, 0x47, 
-0x4c, 0x2a, 0x00, 0x80, 0x00, 0xb5, 0xfe, 0xf7, 0x7d, 0xff, 0x08, 0xbc, 
-0x18, 0x47, 0x00, 0xb5, 0xfe, 0xf7, 0x78, 0xff, 0x08, 0xbc, 0x18, 0x47, 
-0x00, 0xb5, 0xfe, 0xf7, 0x73, 0xff, 0x08, 0xbc, 
-0x18, 0x47, 0x00, 0xb5, 0xfe, 0xf7, 0x6e, 0xff, 0x08, 0xbc, 0x18, 0x47, 
-0x00, 0xb5, 0xfe, 0xf7, 0x69, 0xff, 0x08, 0xbc, 0x18, 0x47, 0x00, 0xb5, 
-0xfe, 0xf7, 0x64, 0xff, 0x08, 0xbc, 0x18, 0x47, 0x00, 0xb5, 0xfe, 0xf7, 
-0x5f, 0xff, 0x08, 0xbc, 0x18, 0x47, 0x00, 0xb5, 0xfe, 0xf7, 0x5a, 0xff, 
-0x08, 0xbc, 0x18, 0x47, 0x00, 0xb5, 0xfe, 0xf7, 0x55, 0xff, 0x08, 0xbc, 
-0x18, 0x47, 0x00, 0xb5, 0xfe, 0xf7, 0x50, 0xff, 0x08, 0xbc, 0x18, 0x47, 
-0x00, 0xb5, 0xfe, 0xf7, 0x4b, 0xff, 0x08, 0xbc, 0x18, 0x47, 0x00, 0xb5, 
-0xfe, 0xf7, 0x46, 0xff, 0x08, 0xbc, 0x18, 0x47, 0x00, 0xb5, 0x8c, 0xb0, 
-0x08, 0xa9, 0xfe, 0xf7, 0x27, 0xff, 0x69, 0x46, 0x08, 0xa8, 0x04, 0xf0, 
-0x75, 0xfa, 0x02, 0x20, 0x08, 0xab, 0x58, 0x70, 0x69, 0x46, 0x08, 0xa8, 
-0xfe, 0xf7, 0x5c, 0xfe, 0x01, 0x20, 0x0c, 0xb0, 0x08, 0xbc, 0x18, 0x47, 
-0x00, 0xb5, 0xfe, 0xf7, 0x2d, 0xff, 0x08, 0xbc, 0x18, 0x47, 0x90, 0xb5, 
-0x84, 0xb0, 0x07, 0x1c, 0x69, 0x46, 0x38, 0x1c, 0xfe, 0xf7, 0x0c, 0xff, 
-0xfa, 0x88, 0x12, 0x49, 0x01, 0x24, 0xc8, 0x1d, 0x89, 0x30, 0x00, 0x2a, 
-0x0f, 0xd0, 0x04, 0x70, 0x44, 0x70, 0xb8, 0x68, 0x00, 0x0c, 0x80, 0x31, 
-0xc8, 0x82, 0xb8, 0x68, 0xc0, 0x46, 0x08, 0x83, 0xf8, 0x68, 0x00, 0x0c, 
-0x48, 0x83, 0xf8, 0x68, 0xc0, 0x46, 0x88, 0x83, 0x02, 0xe0, 0x00, 0x21, 
+0xff, 0xff, 0x00, 0x00, 0x80, 0xb5, 0x84, 0xb0, 0x69, 0x46, 0xfe, 0xf7, 
+0x6d, 0xff, 0x01, 0x27, 0x01, 0xab, 0x5f, 0x80, 0x09, 0x48, 0x81, 0x89, 
+0x09, 0x04, 0xc2, 0x89, 0x11, 0x43, 0x02, 0x91, 0x81, 0x88, 0x09, 0x04, 
+0xc0, 0x88, 0x08, 0x43, 0x03, 0x90, 0x68, 0x46, 0x00, 0x21, 0xfe, 0xf7, 
+0x9b, 0xfe, 0x38, 0x1c, 0x04, 0xb0, 0x80, 0xbc, 0x08, 0xbc, 0x18, 0x47, 
+0x4c, 0x2a, 0x00, 0x80, 0x00, 0xb5, 0xfe, 0xf7, 0x69, 0xff, 0x08, 0xbc, 
+0x18, 0x47, 0x00, 0xb5, 0xfe, 0xf7, 0x64, 0xff, 0x08, 0xbc, 0x18, 0x47, 
+0x00, 0xb5, 0xfe, 0xf7, 0x5f, 0xff, 0x08, 0xbc, 0x18, 0x47, 0x00, 0xb5, 
+0xfe, 0xf7, 0x5a, 0xff, 0x08, 0xbc, 0x18, 0x47, 0x00, 0xb5, 0xfe, 0xf7, 
+0x55, 0xff, 0x08, 0xbc, 0x18, 0x47, 0x00, 0xb5, 0xfe, 0xf7, 0x50, 0xff, 
+0x08, 0xbc, 0x18, 0x47, 0x00, 0xb5, 0xfe, 0xf7, 0x4b, 0xff, 0x08, 0xbc, 
+0x18, 0x47, 0x00, 0xb5, 0xfe, 0xf7, 0x46, 0xff, 0x08, 0xbc, 0x18, 0x47, 
+0x00, 0xb5, 0xfe, 0xf7, 0x41, 0xff, 0x08, 0xbc, 0x18, 0x47, 0x00, 0xb5, 
+0xfe, 0xf7, 0x3c, 0xff, 0x08, 0xbc, 0x18, 0x47, 0x00, 0xb5, 0xfe, 0xf7, 
+0x37, 0xff, 0x08, 0xbc, 0x18, 0x47, 0x00, 0xb5, 0xfe, 0xf7, 0x32, 0xff, 
+0x08, 0xbc, 0x18, 0x47, 0x00, 0xb5, 0x8c, 0xb0, 0x08, 0xa9, 0xfe, 0xf7, 
+0x13, 0xff, 0x69, 0x46, 0x08, 0xa8, 0x02, 0xf0, 0xa9, 0xff, 0x02, 0x20, 
+0x08, 0xab, 0x58, 0x70, 0x69, 0x46, 0x08, 0xa8, 0xfe, 0xf7, 0x48, 0xfe, 
+0x01, 0x20, 0x0c, 0xb0, 0x08, 0xbc, 0x18, 0x47, 0x00, 0xb5, 0xfe, 0xf7, 
+0x19, 0xff, 0x08, 0xbc, 0x18, 0x47, 0x90, 0xb5, 0x84, 0xb0, 0x07, 0x1c, 
+0x69, 0x46, 0x38, 0x1c, 0xfe, 0xf7, 0xf8, 0xfe, 0xfa, 0x88, 0x12, 0x49, 
+0x01, 0x24, 0xc8, 0x1d, 0x89, 0x30, 0x00, 0x2a, 0x0f, 0xd0, 0x04, 0x70, 
+0x44, 0x70, 0xb8, 0x68, 0x00, 0x0c, 0x80, 0x31, 0xc8, 0x82, 0xb8, 0x68, 
+0xc0, 0x46, 0x08, 0x83, 0xf8, 0x68, 0x00, 0x0c, 0x48, 0x83, 0xf8, 0x68, 
+0xc0, 0x46, 0x88, 0x83, 0x02, 0xe0, 0x00, 0x21, 
 0x01, 0x70, 0x41, 0x70, 0x06, 0x48, 0x01, 0xab, 0x58, 0x80, 0x68, 0x46, 
-0x00, 0x21, 0xfe, 0xf7, 0x2b, 0xfe, 0x20, 0x1c, 0x04, 0xb0, 0x90, 0xbc, 
+0x00, 0x21, 0xfe, 0xf7, 0x17, 0xfe, 0x20, 0x1c, 0x04, 0xb0, 0x90, 0xbc, 
 0x08, 0xbc, 0x18, 0x47, 0x68, 0x0e, 0x00, 0x80, 0xff, 0xff, 0x00, 0x00, 
-0x00, 0xb5, 0xfe, 0xf7, 0xf7, 0xfe, 0x08, 0xbc, 0x18, 0x47, 0x00, 0xb5, 
-0xfe, 0xf7, 0xf2, 0xfe, 0x08, 0xbc, 0x18, 0x47, 0x00, 0xb5, 0xfe, 0xf7, 
-0xed, 0xfe, 0x08, 0xbc, 0x18, 0x47, 0x00, 0xb5, 0xfe, 0xf7, 0xe8, 0xfe, 
-0x08, 0xbc, 0x18, 0x47, 0x00, 0xb5, 0xfe, 0xf7, 0xe3, 0xfe, 0x08, 0xbc, 
+0x00, 0xb5, 0xfe, 0xf7, 0xe3, 0xfe, 0x08, 0xbc, 0x18, 0x47, 0x00, 0xb5, 
+0xfe, 0xf7, 0xde, 0xfe, 0x08, 0xbc, 0x18, 0x47, 0x00, 0xb5, 0xfe, 0xf7, 
+0xd9, 0xfe, 0x08, 0xbc, 0x18, 0x47, 0x00, 0xb5, 0xfe, 0xf7, 0xd4, 0xfe, 
+0x08, 0xbc, 0x18, 0x47, 0x00, 0xb5, 0xfe, 0xf7, 0xcf, 0xfe, 0x08, 0xbc, 
 0x18, 0x47, 0x90, 0xb5, 0x84, 0xb0, 0x07, 0x1c, 0x69, 0x46, 0x38, 0x1c, 
-0xfe, 0xf7, 0xc2, 0xfe, 0xf8, 0x88, 0x03, 0x24, 0xe4, 0x04, 0x04, 0x43, 
+0xfe, 0xf7, 0xae, 0xfe, 0xf8, 0x88, 0x03, 0x24, 0xe4, 0x04, 0x04, 0x43, 
 0x03, 0x23, 0xdb, 0x04, 0x9c, 0x42, 0x02, 0xd3, 0x0f, 0x4b, 0x9c, 0x42, 
 0x06, 0xd9, 0x0f, 0x48, 0x01, 0xab, 0x58, 0x80, 0x68, 0x46, 0x00, 0x21, 
-0xfe, 0xf7, 0xf0, 0xfd, 0x01, 0x20, 0x80, 0x07, 0x20, 0x43, 0x00, 0x68, 
+0xfe, 0xf7, 0xdc, 0xfd, 0x01, 0x20, 0x80, 0x07, 0x20, 0x43, 0x00, 0x68, 
 0x00, 0x21, 0x00, 0xab, 0x59, 0x70, 0xfa, 0x88, 0xc0, 0x46, 0xda, 0x80, 
-0x02, 0x90, 0x03, 0x91, 0x68, 0x46, 0x04, 0x33, 0xfe, 0xf7, 0xe0, 0xfd, 
+0x02, 0x90, 0x03, 0x91, 0x68, 0x46, 0x04, 0x33, 0xfe, 0xf7, 0xcc, 0xfd, 
 0x01, 0x20, 0x04, 0xb0, 0x90, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 
 0xe0, 0x00, 0x18, 0x00, 0xff, 0xff, 0x00, 0x00, 0x80, 0xb5, 0x84, 0xb0, 
-0x07, 0x1c, 0x69, 0x46, 0x38, 0x1c, 0xfe, 0xf7, 0x8f, 0xfe, 0xf8, 0x88, 
+0x07, 0x1c, 0x69, 0x46, 0x38, 0x1c, 0xfe, 0xf7, 0x7b, 0xfe, 0xf8, 0x88, 
 0x03, 0x23, 0xdb, 0x04, 0x18, 0x43, 0x98, 0x42, 0x02, 0xd3, 0x0a, 0x4b, 
 0x98, 0x42, 0x08, 0xd9, 0x09, 0x48, 0x01, 0xab, 0x58, 0x80, 0x68, 0x46, 
-0x00, 0x21, 0xfe, 0xf7, 0xbf, 0xfd, 0x01, 0x20, 0x03, 0xe0, 0xb9, 0x68, 
+0x00, 0x21, 0xfe, 0xf7, 0xab, 0xfd, 0x01, 0x20, 0x03, 0xe0, 0xb9, 0x68, 
 0xc0, 0x46, 0x01, 0x60, 0x00, 0x20, 0x04, 0xb0, 0x80, 0xbc, 0x08, 0xbc, 
 0x18, 0x47, 0x00, 0x00, 0xe0, 0x00, 0x18, 0x00, 0xff, 0xff, 0x00, 0x00, 
-0x80, 0xb5, 0x86, 0xb0, 0x07, 0x1c, 0x04, 0xf0, 0x33, 0xf9, 0x38, 0x1c, 
-0x02, 0xa9, 0xfe, 0xf7, 0x67, 0xfe, 0x01, 0x27, 0x02, 0xab, 0x5f, 0x70, 
-0x00, 0x20, 0xd8, 0x80, 0x0a, 0x48, 0x41, 0x68, 0xc0, 0x46, 0x04, 0x91, 
-0x81, 0x68, 0xc0, 0x46, 0x05, 0x91, 0xc1, 0x68, 
+0x80, 0xb5, 0x86, 0xb0, 0x02, 0xa9, 0xfe, 0xf7, 0x57, 0xfe, 0x01, 0x27, 
+0x02, 0xab, 0x5f, 0x70, 0x00, 0x20, 0xd8, 0x80, 0x0a, 0x48, 0x41, 0x68, 
+0xc0, 0x46, 0x04, 0x91, 0x81, 0x68, 0xc0, 0x46, 0x05, 0x91, 0xc1, 0x68, 
 0xc0, 0x46, 0x00, 0x91, 0x40, 0x69, 0xc0, 0x46, 0x01, 0x90, 0x69, 0x46, 
-0x02, 0xa8, 0xfe, 0xf7, 0x91, 0xfd, 0x38, 0x1c, 0x06, 0xb0, 0x80, 0xbc, 
+0x02, 0xa8, 0xfe, 0xf7, 0x81, 0xfd, 0x38, 0x1c, 0x06, 0xb0, 0x80, 0xbc, 
 0x08, 0xbc, 0x18, 0x47, 0x68, 0x19, 0x00, 0x80, 0x00, 0xb5, 0xc1, 0x68, 
-0x80, 0x68, 0xfe, 0xf7, 0x49, 0xfb, 0x00, 0x20, 0x08, 0xbc, 0x18, 0x47, 
+0x80, 0x68, 0xfe, 0xf7, 0x47, 0xfb, 0x00, 0x20, 0x08, 0xbc, 0x18, 0x47, 
 0x00, 0x20, 0x70, 0x47, 0x90, 0xb5, 0x84, 0xb0, 0x04, 0x1c, 0x0f, 0x1c, 
-0x68, 0x46, 0x50, 0x21, 0xfe, 0xf7, 0x46, 0xfe, 0x01, 0xab, 0x5c, 0x80, 
-0x02, 0x97, 0x68, 0x46, 0x00, 0x21, 0xfe, 0xf7, 0x71, 0xfd, 0x04, 0xb0, 
+0x68, 0x46, 0x50, 0x21, 0xfe, 0xf7, 0x36, 0xfe, 0x01, 0xab, 0x5c, 0x80, 
+0x02, 0x97, 0x68, 0x46, 0x00, 0x21, 0xfe, 0xf7, 0x61, 0xfd, 0x04, 0xb0, 
 0x90, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x80, 0xb5, 0x84, 0xb0, 0x07, 0x1c, 
-0x68, 0x46, 0x51, 0x21, 0xfe, 0xf7, 0x34, 0xfe, 0x01, 0xab, 0x5f, 0x80, 
-0x68, 0x46, 0x00, 0x21, 0xfe, 0xf7, 0x60, 0xfd, 0x04, 0xb0, 0x80, 0xbc, 
+0x68, 0x46, 0x51, 0x21, 0xfe, 0xf7, 0x24, 0xfe, 0x01, 0xab, 0x5f, 0x80, 
+0x68, 0x46, 0x00, 0x21, 0xfe, 0xf7, 0x50, 0xfd, 0x04, 0xb0, 0x80, 0xbc, 
 0x08, 0xbc, 0x18, 0x47, 0x00, 0x20, 0x70, 0x47, 0x00, 0x20, 0x70, 0x47, 
 0x90, 0xb5, 0x84, 0xb0, 0x00, 0x27, 0x12, 0x49, 0x09, 0x68, 0x12, 0x4a, 
 0x12, 0x6b, 0x10, 0x23, 0x1a, 0x40, 0x01, 0x24, 0x00, 0x2a, 0x00, 0xd0, 
 0x01, 0x27, 0x8a, 0x0c, 0x03, 0xd3, 0x3a, 0x04, 0x12, 0x0c, 0x02, 0x27, 
 0x17, 0x43, 0xc9, 0x0c, 0x03, 0xd3, 0x39, 0x04, 0x09, 0x0c, 0x04, 0x27, 
-0x0f, 0x43, 0x69, 0x46, 0xfe, 0xf7, 0xfc, 0xfd, 0x01, 0xab, 0x5f, 0x80, 
-0x68, 0x46, 0x00, 0x21, 0xfe, 0xf7, 0x36, 0xfd, 0x20, 0x1c, 0x04, 0xb0, 
-0x90, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0x00, 0x00, 0x10, 0x40, 
-0xc0, 0x00, 0x18, 0x40, 0x00, 0xb5, 0x84, 0xb0, 0x69, 0x46, 0xfe, 0xf7, 
-0xe7, 0xfd, 0x06, 0x48, 0xc0, 0x6d, 0x01, 0xab, 0x58, 0x80, 0x68, 0x46, 
-0x00, 0x21, 0xfe, 0xf7, 0x1f, 0xfd, 0x01, 0x20, 0x04, 0xb0, 0x08, 0xbc, 
-0x18, 0x47, 0x00, 0x00, 0xa4, 0x2a, 0x00, 0x80, 0x00, 0xb5, 0xfe, 0xf7, 
-0xed, 0xfd, 0x08, 0xbc, 0x18, 0x47, 0x70, 0x47, 0x00, 0x20, 0x70, 0x47, 
+0x0f, 0x43, 0x69, 0x46, 0xfe, 0xf7, 0xec, 0xfd, 0x01, 0xab, 0x5f, 0x80, 
+0x68, 0x46, 0x00, 0x21, 0xfe, 0xf7, 0x26, 0xfd, 0x20, 0x1c, 0x04, 0xb0, 
+0x90, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 
+0x00, 0x00, 0x10, 0x40, 0xc0, 0x00, 0x18, 0x40, 0x00, 0xb5, 0x84, 0xb0, 
+0x69, 0x46, 0xfe, 0xf7, 0xd7, 0xfd, 0x06, 0x48, 0xc0, 0x6d, 0x01, 0xab, 
+0x58, 0x80, 0x68, 0x46, 0x00, 0x21, 0xfe, 0xf7, 0x0f, 0xfd, 0x01, 0x20, 
+0x04, 0xb0, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0xa4, 0x2a, 0x00, 0x80, 
+0x00, 0xb5, 0xfe, 0xf7, 0xdd, 0xfd, 0x08, 0xbc, 0x18, 0x47, 0x70, 0x47, 
+0x00, 0x20, 0x70, 0x47, 0x00, 0x20, 0x70, 0x47, 0x00, 0x20, 0x70, 0x47, 
 0x00, 0x20, 0x70, 0x47, 0x00, 0x20, 0x70, 0x47, 0x00, 0x20, 0x70, 0x47, 
-0x00, 0x20, 0x70, 0x47, 0x00, 0x20, 0x70, 0x47, 0x00, 0xb5, 0xfe, 0xf7, 
-0xdb, 0xfd, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0x80, 0xb5, 0x85, 0xb0, 
-0x01, 0xa9, 0xfe, 0xf7, 0xbb, 0xfd, 0x00, 0x20, 0x01, 0xab, 0x58, 0x70, 
-0x10, 0x49, 0xc9, 0x68, 0x01, 0x27, 0x01, 0x29, 0x0a, 0xd1, 0x04, 0xf0, 
-0xc7, 0xf8, 0x03, 0x90, 0x04, 0x97, 0x03, 0x98, 0x00, 0x28, 0x06, 0xd0, 
-0x68, 0x46, 0x02, 0xf0, 0xe5, 0xfb, 0x04, 0xe0, 0x03, 0x97, 0x04, 0x90, 
-0xf8, 0xe7, 0x00, 0x20, 0x00, 0x90, 0x02, 0xab, 0x00, 0x98, 0xc0, 0x46, 
-0x58, 0x80, 0x00, 0x21, 0x01, 0xa8, 0xfe, 0xf7, 0xdb, 0xfc, 0x38, 0x1c, 
+0x00, 0xb5, 0xfe, 0xf7, 0xcb, 0xfd, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 
+0x80, 0xb5, 0x85, 0xb0, 0x01, 0xa9, 0xfe, 0xf7, 0xab, 0xfd, 0x00, 0x20, 
+0x01, 0xab, 0x58, 0x70, 0x0c, 0x49, 0xc9, 0x68, 0x01, 0x27, 0x01, 0x29, 
+0x02, 0xd1, 0x03, 0x97, 0x04, 0x97, 0x01, 0xe0, 0x03, 0x97, 0x04, 0x90, 
+0x68, 0x46, 0x01, 0xf0, 0x33, 0xfd, 0x02, 0xab, 0x00, 0x98, 0xc0, 0x46, 
+0x58, 0x80, 0x00, 0x21, 0x01, 0xa8, 0xfe, 0xf7, 0xd3, 0xfc, 0x38, 0x1c, 
 0x05, 0xb0, 0x80, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x68, 0x0e, 0x00, 0x80, 
-0x90, 0xb5, 0x84, 0xb0, 0x07, 0x1c, 0x69, 0x46, 0x38, 0x1c, 0xfe, 0xf7, 
-0x8d, 0xfd, 0x00, 0x20, 0x00, 0xab, 0x58, 0x70, 0x01, 0x24, 0x20, 0x1c, 
-0x12, 0x49, 0xc9, 0x68, 0x01, 0x29, 0x00, 0xd0, 0x00, 0x20, 0x00, 0x06, 
-0x00, 0x0e, 0x13, 0xd0, 0xf8, 0x88, 0x0f, 0x4a, 0x90, 0x42, 0x02, 0xd0, 
-0x0e, 0x4b, 0x98, 0x42, 0x08, 0xd1, 0xb9, 0x68, 0x27, 0x1c, 0x90, 0x42, 
-0x00, 0xd0, 0x00, 0x27, 0x38, 0x06, 0x00, 0x0e, 0x04, 0xf0, 0x88, 0xf8, 
-0x04, 0xf0, 0x84, 0xf8, 0x02, 0x90, 0x00, 0xe0, 0x02, 0x94, 0x68, 0x46, 
-0x00, 0x21, 0xfe, 0xf7, 0xa7, 0xfc, 0x20, 0x1c, 0x04, 0xb0, 0x90, 0xbc, 
-0x08, 0xbc, 0x18, 0x47, 0x68, 0x0e, 0x00, 0x80, 0xed, 0xfe, 0x00, 0x00, 
-0xfe, 0xca, 0x00, 0x00, 0xf1, 0xb5, 0xd6, 0xb0, 
-0x00, 0x20, 0x81, 0x00, 0x56, 0x9c, 0x0a, 0x19, 0x12, 0x6a, 0x6b, 0x46, 
-0x5a, 0x50, 0x01, 0x30, 0x10, 0x28, 0xf6, 0xdb, 0x10, 0x20, 0x82, 0x00, 
-0x11, 0x1c, 0x69, 0x44, 0x40, 0x39, 0x4b, 0x6b, 0x0f, 0x6a, 0x7b, 0x40, 
-0x8f, 0x68, 0x7b, 0x40, 0x09, 0x68, 0x59, 0x40, 0x4b, 0x00, 0xc9, 0x0f, 
-0x19, 0x43, 0x6b, 0x46, 0x99, 0x50, 0x01, 0x30, 0x50, 0x28, 0xec, 0xdb, 
-0x56, 0x98, 0x01, 0x68, 0xc0, 0x46, 0x55, 0x91, 0x42, 0x68, 0xc0, 0x46, 
-0x54, 0x92, 0x86, 0x68, 0xc0, 0x46, 0x53, 0x96, 0xc5, 0x68, 0xc0, 0x46, 
-0x52, 0x95, 0x04, 0x69, 0xc0, 0x46, 0x51, 0x94, 0x48, 0x01, 0xcb, 0x0e, 
-0x18, 0x43, 0x13, 0x1c, 0x33, 0x40, 0x07, 0x1c, 0x28, 0x1c, 0x90, 0x43, 
-0x18, 0x43, 0x38, 0x18, 0x00, 0x19, 0x00, 0x9b, 0xc0, 0x18, 0xcf, 0x4b, 
-0xc0, 0x18, 0x93, 0x07, 0x92, 0x08, 0x13, 0x43, 0x42, 0x01, 0x1f, 0x1c, 
-0xc3, 0x0e, 0x1a, 0x43, 0x0b, 0x1c, 0x3b, 0x40, 0x14, 0x1c, 0x32, 0x1c, 
-0x8a, 0x43, 0x1a, 0x43, 0xa2, 0x18, 0x52, 0x19, 0x01, 0x9b, 0xd2, 0x18, 
-0xc5, 0x4b, 0xd4, 0x18, 0x8a, 0x07, 0x89, 0x08, 0x11, 0x43, 0x62, 0x01, 
-0xe3, 0x0e, 0x1a, 0x43, 0x03, 0x1c, 0x0b, 0x40, 0x15, 0x1c, 0x3a, 0x1c, 
-0x82, 0x43, 0x1a, 0x43, 0xaa, 0x18, 0x92, 0x19, 0x02, 0x9b, 0xd2, 0x18, 
-0xbc, 0x4b, 0xd2, 0x18, 0x3b, 0x1c, 0x87, 0x07, 0x80, 0x08, 0x38, 0x43, 
-0x57, 0x01, 0xd5, 0x0e, 0x3d, 0x43, 0x27, 0x1c, 0x07, 0x40, 0x0e, 0x1c, 
-0xa6, 0x43, 0x37, 0x43, 0xed, 0x19, 0xeb, 0x18, 0x03, 0x9f, 0xdf, 0x19, 
-0xb3, 0x4b, 0xff, 0x18, 0xa3, 0x07, 0xa4, 0x08, 0x1c, 0x43, 0x7b, 0x01, 
-0xfd, 0x0e, 0x2b, 0x43, 0x15, 0x1c, 0x25, 0x40, 0x1e, 0x1c, 0x03, 0x1c, 
-0x93, 0x43, 0x2b, 0x43, 0xf3, 0x18, 0x59, 0x18, 0x04, 0x9b, 0xc9, 0x18, 
-0xaa, 0x4b, 0xc9, 0x18, 0x93, 0x07, 0x92, 0x08, 0x1a, 0x43, 0x4b, 0x01, 
-0xcd, 0x0e, 0x1d, 0x43, 0x3e, 0x1c, 0x16, 0x40, 0x23, 0x1c, 0xbb, 0x43, 
-0x33, 0x43, 0xeb, 0x18, 0x18, 0x18, 0x05, 0x9b, 0xc0, 0x18, 0xa2, 0x4b, 
-0xc0, 0x18, 0xbb, 0x07, 0xbf, 0x08, 0x1f, 0x43, 0x43, 0x01, 0xc5, 0x0e, 
-0x2b, 0x43, 0x0d, 0x1c, 0x3d, 0x40, 0x1e, 0x1c, 0x13, 0x1c, 0x8b, 0x43, 
-0x2b, 0x43, 0xf3, 0x18, 0x1b, 0x19, 0x06, 0x9c, 0x1c, 0x19, 0x99, 0x4b, 
-0xe4, 0x18, 0x8b, 0x07, 0x89, 0x08, 0x19, 0x43, 0x63, 0x01, 0xe5, 0x0e, 
-0x1d, 0x43, 0x03, 0x1c, 0x0b, 0x40, 0x3e, 0x1c, 0x86, 0x43, 0x33, 0x43, 
-0xeb, 0x18, 0x9a, 0x18, 0x07, 0x9b, 0xd2, 0x18, 0x90, 0x4b, 0xd2, 0x18, 
-0x3b, 0x1c, 0x87, 0x07, 0x80, 0x08, 0x38, 0x43, 0x57, 0x01, 0xd5, 0x0e, 
-0x2f, 0x43, 0x25, 0x1c, 0x05, 0x40, 0x3e, 0x1c, 0x0f, 0x1c, 0xa7, 0x43, 
-0x2f, 0x43, 0xf5, 0x19, 0xeb, 0x18, 0x08, 0x9f, 0xdf, 0x19, 0x87, 0x4b, 
-0xff, 0x18, 0xa3, 0x07, 0xa4, 0x08, 0x1c, 0x43, 0x7b, 0x01, 0xfd, 0x0e, 
-0x1d, 0x43, 0x16, 0x1c, 0x26, 0x40, 0x03, 0x1c, 0x93, 0x43, 0x33, 0x43, 
-0xeb, 0x18, 0x59, 0x18, 0x09, 0x9b, 0xc9, 0x18, 0x7e, 0x4b, 0xc9, 0x18, 
-0x93, 0x07, 0x92, 0x08, 0x1a, 0x43, 0x4b, 0x01, 0xcd, 0x0e, 0x1d, 0x43, 
-0x3b, 0x1c, 0x13, 0x40, 0x26, 0x1c, 0xbe, 0x43, 0x33, 0x43, 0xeb, 0x18, 
-0x18, 0x18, 0x0a, 0x9b, 0xc0, 0x18, 0x76, 0x4b, 0xc0, 0x18, 0x23, 0x1c, 
-0xbc, 0x07, 0xbf, 0x08, 0x27, 0x43, 0x44, 0x01, 0xc5, 0x0e, 0x2c, 0x43, 
-0x0d, 0x1c, 0x3d, 0x40, 0x26, 0x1c, 0x14, 0x1c, 0x8c, 0x43, 0x2c, 0x43, 
-0x35, 0x19, 0xeb, 0x18, 0x0b, 0x9c, 0x1c, 0x19, 
-0x6c, 0x4b, 0xe4, 0x18, 0x8b, 0x07, 0x89, 0x08, 0x19, 0x43, 0x63, 0x01, 
-0xe5, 0x0e, 0x1d, 0x43, 0x03, 0x1c, 0x0b, 0x40, 0x3e, 0x1c, 0x86, 0x43, 
-0x33, 0x43, 0xeb, 0x18, 0x9a, 0x18, 0x0c, 0x9b, 0xd2, 0x18, 0x64, 0x4b, 
-0xd2, 0x18, 0x3b, 0x1c, 0x87, 0x07, 0x80, 0x08, 0x38, 0x43, 0x57, 0x01, 
-0xd5, 0x0e, 0x3d, 0x43, 0x27, 0x1c, 0x07, 0x40, 0x0e, 0x1c, 0xa6, 0x43, 
-0x37, 0x43, 0xed, 0x19, 0xeb, 0x18, 0x0d, 0x9f, 0xdf, 0x19, 0x5b, 0x4b, 
-0xff, 0x18, 0xa3, 0x07, 0xa4, 0x08, 0x1c, 0x43, 0x7b, 0x01, 0xfd, 0x0e, 
-0x1d, 0x43, 0x13, 0x1c, 0x23, 0x40, 0x06, 0x1c, 0x96, 0x43, 0x33, 0x43, 
-0xeb, 0x18, 0x59, 0x18, 0x0e, 0x9b, 0xc9, 0x18, 0x52, 0x4b, 0xc9, 0x18, 
-0x93, 0x07, 0x92, 0x08, 0x1a, 0x43, 0x4b, 0x01, 0xcd, 0x0e, 0x2b, 0x43, 
-0x3d, 0x1c, 0x15, 0x40, 0x1e, 0x1c, 0x23, 0x1c, 0xbb, 0x43, 0x2b, 0x43, 
-0xf3, 0x18, 0x18, 0x18, 0x0f, 0x9b, 0xc0, 0x18, 0x49, 0x4b, 0xc0, 0x18, 
-0x23, 0x1c, 0xbc, 0x07, 0xbf, 0x08, 0x27, 0x43, 0x10, 0x24, 0x50, 0x94, 
-0x44, 0x01, 0xc5, 0x0e, 0x25, 0x43, 0x0e, 0x1c, 0x3e, 0x40, 0x14, 0x1c, 
-0x8c, 0x43, 0x34, 0x43, 0x2c, 0x19, 0xe3, 0x18, 0x50, 0x9c, 0xa5, 0x00, 
-0x6c, 0x46, 0x64, 0x59, 0x1c, 0x19, 0x3e, 0x4b, 0xe4, 0x18, 0x13, 0x1c, 
-0x3a, 0x1c, 0x8f, 0x07, 0x89, 0x08, 0x0f, 0x43, 0x01, 0x1c, 0x20, 0x1c, 
-0x50, 0x9c, 0x01, 0x34, 0x50, 0x94, 0x14, 0x2c, 0xe2, 0xdb, 0x14, 0x24, 
-0x45, 0x01, 0xc6, 0x0e, 0x2e, 0x43, 0x0d, 0x1c, 0x7d, 0x40, 0x55, 0x40, 
-0x75, 0x19, 0xeb, 0x18, 0xa5, 0x00, 0x6e, 0x46, 0x75, 0x59, 0x5d, 0x19, 
-0x31, 0x4b, 0xed, 0x18, 0x13, 0x1c, 0x3a, 0x1c, 0x8f, 0x07, 0x89, 0x08, 
-0x0f, 0x43, 0x01, 0x1c, 0x28, 0x1c, 0x01, 0x34, 0x28, 0x2c, 0xe7, 0xdb, 
-0x28, 0x24, 0x50, 0x94, 0x44, 0x01, 0xc5, 0x0e, 0x25, 0x43, 0x3c, 0x1c, 
-0x14, 0x43, 0x0c, 0x40, 0x3e, 0x1c, 0x16, 0x40, 0x34, 0x43, 0x2c, 0x19, 
-0xe3, 0x18, 0x50, 0x9c, 0xa5, 0x00, 0x6c, 0x46, 0x64, 0x59, 0x1c, 0x19, 
-0x23, 0x4b, 0xe4, 0x18, 0x13, 0x1c, 0x3a, 0x1c, 0x8f, 0x07, 0x89, 0x08, 
-0x0f, 0x43, 0x01, 0x1c, 0x20, 0x1c, 0x50, 0x9c, 0x01, 0x34, 0x50, 0x94, 
-0x3c, 0x2c, 0xe1, 0xdb, 0x3c, 0x24, 0x45, 0x01, 0xc6, 0x0e, 0x2e, 0x43, 
-0x0d, 0x1c, 0x7d, 0x40, 0x55, 0x40, 0x75, 0x19, 0xeb, 0x18, 0xa6, 0x00, 
-0x6d, 0x46, 0xad, 0x59, 0x5d, 0x19, 0x17, 0x4b, 0xed, 0x18, 0x13, 0x1c, 
-0x3a, 0x1c, 0x8f, 0x07, 0x89, 0x08, 0x0f, 0x43, 0x01, 0x1c, 0x28, 0x1c, 
-0x01, 0x34, 0x50, 0x2c, 0xe7, 0xdb, 0x55, 0x9c, 0x20, 0x18, 0x56, 0x9c, 
-0xc0, 0x46, 0x20, 0x60, 0x54, 0x98, 0x40, 0x18, 0x56, 0x9c, 0xc0, 0x46, 
-0x60, 0x60, 0x53, 0x9e, 0xf0, 0x19, 0x56, 0x9c, 0xc0, 0x46, 0xa0, 0x60, 
-0x52, 0x9d, 0xa8, 0x18, 0x56, 0x9c, 0xc0, 0x46, 0xe0, 0x60, 0x51, 0x9c, 
-0xe0, 0x18, 0x56, 0x9c, 0xc0, 0x46, 0x20, 0x61, 0x57, 0xb0, 0xf0, 0xbc, 
-0x08, 0xbc, 0x18, 0x47, 0x99, 0x79, 0x82, 0x5a, 0xa1, 0xeb, 0xd9, 0x6e, 
-0xdc, 0xbc, 0x1b, 0x8f, 0xd6, 0xc1, 0x62, 0xca, 0x88, 0xb4, 0x8a, 0x08, 
-0x89, 0x07, 0x00, 0xd0, 0x01, 0x32, 0x00, 0x21, 0x00, 0x2a, 0x1e, 0xdd, 
-0x07, 0x78, 0x00, 0xab, 0x1f, 0x70, 0x47, 0x78, 0xc0, 0x46, 0x5f, 0x70, 
-0x87, 0x78, 0xc0, 0x46, 0x9f, 0x70, 0xc7, 0x78, 0xc0, 0x46, 0xdf, 0x70, 
-0xdb, 0x78, 0xc0, 0x46, 0x03, 0x70, 0x00, 0xab, 0x9b, 0x78, 0xc0, 0x46, 
-0x43, 0x70, 0x00, 0xab, 0x5b, 0x78, 0xc0, 0x46, 
-0x83, 0x70, 0x00, 0xab, 0x1b, 0x78, 0xc0, 0x46, 0xc3, 0x70, 0x04, 0x30, 
-0x01, 0x31, 0x91, 0x42, 0xe0, 0xdb, 0x88, 0xbc, 0x70, 0x47, 0x00, 0x21, 
-0xc1, 0x61, 0x09, 0x4a, 0xc0, 0x46, 0x02, 0x60, 0x08, 0x4a, 0xc0, 0x46, 
-0x42, 0x60, 0x08, 0x4a, 0xc0, 0x46, 0x82, 0x60, 0x07, 0x4a, 0xc0, 0x46, 
-0xc2, 0x60, 0x07, 0x4a, 0xc0, 0x46, 0x02, 0x61, 0x41, 0x61, 0x81, 0x61, 
-0x70, 0x47, 0x00, 0x00, 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 
-0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, 0xf0, 0xe1, 0xd2, 0xc3, 
-0xf0, 0xb5, 0x14, 0x1c, 0x0d, 0x1c, 0x07, 0x1c, 0xe1, 0x00, 0x78, 0x69, 
-0x41, 0x18, 0x81, 0x42, 0x02, 0xd2, 0xb8, 0x69, 0x01, 0x30, 0xb8, 0x61, 
-0x79, 0x61, 0x61, 0x0f, 0xb8, 0x69, 0x40, 0x18, 0xb8, 0x61, 0x40, 0x2c, 
-0x14, 0xdb, 0xfe, 0x1d, 0x19, 0x36, 0x00, 0x20, 0x29, 0x78, 0x3a, 0x18, 
-0x20, 0x32, 0x11, 0x70, 0x01, 0x35, 0x01, 0x30, 0x40, 0x28, 0xf7, 0xd3, 
-0x40, 0x21, 0x30, 0x1c, 0xff, 0xf7, 0x96, 0xff, 0x38, 0x1c, 0xff, 0xf7, 
-0xaf, 0xfd, 0x40, 0x3c, 0x40, 0x2c, 0xec, 0xda, 0x00, 0x20, 0x00, 0x2c, 
-0x07, 0xd9, 0x29, 0x78, 0x3a, 0x18, 0x20, 0x32, 0x11, 0x70, 0x01, 0x35, 
-0x01, 0x30, 0xa0, 0x42, 0xf7, 0xd3, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 
-0xf8, 0xb5, 0x07, 0x1c, 0xd3, 0x00, 0x78, 0x69, 0xc6, 0x18, 0x86, 0x42, 
-0x02, 0xd2, 0xb8, 0x69, 0x01, 0x30, 0xb8, 0x61, 0x7e, 0x61, 0x53, 0x0f, 
-0xb8, 0x69, 0xc0, 0x18, 0xb8, 0x61, 0x00, 0x90, 0x00, 0x20, 0x00, 0x2a, 
-0x07, 0xdd, 0x0b, 0x78, 0x3c, 0x18, 0x20, 0x34, 0x23, 0x70, 0x01, 0x31, 
-0x01, 0x30, 0x90, 0x42, 0xf7, 0xdb, 0x80, 0x20, 0xd1, 0x19, 0x20, 0x31, 
-0x08, 0x70, 0x54, 0x1c, 0xfd, 0x1d, 0x19, 0x35, 0x38, 0x2c, 0x1c, 0xdd, 
-0x38, 0x19, 0x20, 0x30, 0x00, 0x21, 0x40, 0x22, 0x12, 0x1b, 0x00, 0x2a, 
-0x05, 0xdd, 0x00, 0x23, 0x03, 0x70, 0x01, 0x30, 0x01, 0x31, 0x8a, 0x42, 
-0xfa, 0xdc, 0x28, 0x1c, 0x21, 0x1c, 0xff, 0xf7, 0x4d, 0xff, 0x38, 0x1c, 
-0xff, 0xf7, 0x66, 0xfd, 0x28, 0x1c, 0x00, 0x21, 0x00, 0x23, 0x03, 0x70, 
-0x01, 0x30, 0x01, 0x31, 0x38, 0x29, 0xfa, 0xdb, 0x0c, 0xe0, 0x38, 0x19, 
-0x20, 0x30, 0x00, 0x21, 0x38, 0x22, 0x12, 0x1b, 0x00, 0x2a, 0x05, 0xdd, 
-0x00, 0x23, 0x03, 0x70, 0x01, 0x30, 0x01, 0x31, 0x8a, 0x42, 0xfa, 0xdc, 
-0x28, 0x1c, 0x21, 0x1c, 0xff, 0xf7, 0x30, 0xff, 0x00, 0x98, 0xc0, 0x46, 
-0xb8, 0x65, 0xfe, 0x65, 0x38, 0x1c, 0xff, 0xf7, 0x45, 0xfd, 0x01, 0x20, 
-0xf8, 0x61, 0xf8, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0xf0, 0xb5, 0x0c, 0x1c, 
-0x05, 0x1c, 0x17, 0x1c, 0x38, 0x1c, 0x00, 0x2f, 0x04, 0xda, 0x40, 0x42, 
-0x80, 0x06, 0x80, 0x0e, 0x40, 0x42, 0x01, 0xe0, 0x80, 0x06, 0x80, 0x0e, 
-0x00, 0x28, 0x07, 0xd1, 0x28, 0x1c, 0x21, 0x1c, 0x3a, 0x1c, 0xff, 0xf7, 
-0x57, 0xff, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x38, 0x1c, 0x00, 0x2f, 
-0x00, 0xda, 0x3f, 0x30, 0x80, 0x11, 0x00, 0x28, 0x07, 0xdd, 0x86, 0x01, 
-0x28, 0x1c, 0x21, 0x1c, 0x32, 0x1c, 0xff, 0xf7, 0x47, 0xff, 0xa4, 0x19, 
-0xbf, 0x1b, 0x00, 0x2f, 0xeb, 0xd0, 0x28, 0x1c, 0x21, 0x1c, 0x3a, 0x1c, 
-0xff, 0xf7, 0x74, 0xff, 0xe5, 0xe7, 0x98, 0xb5, 0x04, 0x1c, 0x0f, 0x1c, 
-0x30, 0x20, 0x00, 0xab, 0x18, 0x70, 0xf8, 0x69, 0x00, 0x28, 0x04, 0xd1, 
-0x69, 0x46, 0x00, 0x22, 0x38, 0x1c, 0xff, 0xf7, 0x65, 0xff, 0x14, 0x21, 
-0x38, 0x1c, 0xff, 0xf7, 0xe3, 0xfe, 0x00, 0x20, 
-0x81, 0x00, 0x79, 0x58, 0x02, 0xc4, 0x01, 0x30, 0x05, 0x28, 0xf9, 0xdb, 
-0x98, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0xb0, 0xb5, 0x98, 0xb0, 0x07, 0x1c, 
-0x78, 0x68, 0x40, 0x28, 0x10, 0xd9, 0x68, 0x46, 0xff, 0xf7, 0xf9, 0xfe, 
-0x68, 0x46, 0x06, 0xcf, 0x08, 0x3f, 0xff, 0xf7, 0xa7, 0xff, 0xf8, 0x1d, 
-0xc5, 0x30, 0x69, 0x46, 0x04, 0x1c, 0xff, 0xf7, 0xd0, 0xff, 0x14, 0x20, 
-0x78, 0x60, 0x3c, 0x60, 0x00, 0x20, 0x00, 0x24, 0x39, 0x18, 0xca, 0x1d, 
-0x39, 0x32, 0x14, 0x72, 0x80, 0x31, 0x4c, 0x72, 0x7b, 0x68, 0x83, 0x42, 
-0x06, 0xd9, 0x3b, 0x68, 0x5d, 0x1c, 0x3d, 0x60, 0x1b, 0x78, 0xc0, 0x46, 
-0x13, 0x72, 0x4b, 0x72, 0x15, 0x7a, 0x36, 0x23, 0x6b, 0x40, 0x13, 0x72, 
-0x4a, 0x7a, 0x5c, 0x23, 0x5a, 0x40, 0x4a, 0x72, 0x01, 0x30, 0x40, 0x28, 
-0xe4, 0xd3, 0x18, 0xb0, 0xb0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0xf7, 0xb5, 
-0xe0, 0xb0, 0x14, 0x1c, 0x0f, 0x1c, 0x00, 0x25, 0xae, 0x00, 0x01, 0x20, 
-0xf1, 0x1d, 0x1d, 0x31, 0x02, 0xf0, 0x10, 0xfe, 0x01, 0x04, 0x00, 0x91, 
-0x01, 0x20, 0xf1, 0x1d, 0x1b, 0x31, 0x02, 0xf0, 0x09, 0xfe, 0x00, 0x99, 
-0x08, 0x43, 0x19, 0xa9, 0x71, 0x18, 0x88, 0x60, 0x01, 0x35, 0x10, 0x2d, 
-0xea, 0xd3, 0x1b, 0xa8, 0x19, 0x90, 0x40, 0x20, 0x1a, 0x90, 0x19, 0xa8, 
-0xff, 0xf7, 0xa7, 0xff, 0x01, 0xa8, 0xff, 0xf7, 0xa6, 0xfe, 0x40, 0x22, 
-0x01, 0xa8, 0x2b, 0xa9, 0xff, 0xf7, 0x54, 0xff, 0x00, 0x2f, 0x0b, 0xd0, 
-0x40, 0x2f, 0x01, 0xd9, 0x40, 0x25, 0x00, 0xe0, 0x3d, 0x1c, 0x60, 0x99, 
-0x01, 0xa8, 0x2a, 0x1c, 0xff, 0xf7, 0x48, 0xff, 0x7f, 0x1b, 0xf3, 0xd1, 
-0x51, 0xa8, 0x01, 0xa9, 0x07, 0x1c, 0xff, 0xf7, 0x70, 0xff, 0x01, 0xa8, 
-0xff, 0xf7, 0x8b, 0xfe, 0x40, 0x22, 0x01, 0xa8, 0x3b, 0xa9, 0x01, 0x31, 
-0xff, 0xf7, 0x38, 0xff, 0x14, 0x22, 0x01, 0xa8, 0x39, 0x1c, 0xff, 0xf7, 
-0x33, 0xff, 0x56, 0xa8, 0x01, 0xa9, 0xff, 0xf7, 0x5e, 0xff, 0x00, 0x20, 
-0x82, 0x00, 0x19, 0xa9, 0x51, 0x18, 0xc0, 0x31, 0x49, 0x6b, 0x02, 0xc4, 
-0x01, 0x30, 0x05, 0x28, 0xf6, 0xd3, 0x63, 0xb0, 0xf0, 0xbc, 0x08, 0xbc, 
-0x18, 0x47, 0x00, 0x00, 0x90, 0xb5, 0x07, 0x1c, 0x00, 0x24, 0x00, 0x2f, 
-0x04, 0xd3, 0x04, 0xf0, 0x15, 0xf9, 0x01, 0x34, 0xbc, 0x42, 0xfa, 0xd9, 
-0x90, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0xf0, 0xb5, 0x14, 0x1c, 0x0d, 0x1c, 
-0x06, 0x1c, 0x1f, 0x1c, 0x1b, 0x4b, 0x32, 0x04, 0x12, 0x0c, 0x3c, 0x21, 
-0x02, 0x20, 0xfd, 0xf7, 0x8a, 0xff, 0x32, 0x0c, 0x17, 0x4b, 0x3e, 0x21, 
-0x02, 0x20, 0xfd, 0xf7, 0x84, 0xff, 0x15, 0x4b, 0x2a, 0x04, 0x12, 0x0c, 
-0x40, 0x21, 0x02, 0x20, 0xfd, 0xf7, 0x7d, 0xff, 0x2a, 0x0c, 0x11, 0x4b, 
-0x42, 0x21, 0x02, 0x20, 0xfd, 0xf7, 0x77, 0xff, 0x0e, 0x4b, 0x22, 0x04, 
-0x12, 0x0c, 0x44, 0x21, 0x02, 0x20, 0xfd, 0xf7, 0x70, 0xff, 0x22, 0x0c, 
-0x0a, 0x4b, 0x46, 0x21, 0x02, 0x20, 0xfd, 0xf7, 0x6a, 0xff, 0x08, 0x4b, 
-0x3a, 0x04, 0x12, 0x0c, 0x48, 0x21, 0x02, 0x20, 0xfd, 0xf7, 0x63, 0xff, 
-0x3a, 0x0c, 0x04, 0x4b, 0x4a, 0x21, 0x02, 0x20, 0xfd, 0xf7, 0x5d, 0xff, 
-0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0xd9, 0xbf, 0x21, 0x40, 
-0x88, 0xb5, 0x11, 0x27, 0x3f, 0x04, 0x38, 0x62, 0x79, 0x62, 0xba, 0x62, 
-0xfb, 0x62, 0x04, 0x20, 0xff, 0xf7, 0xaa, 0xff, 0x07, 0x48, 0x40, 0x6b, 
-0xc0, 0x46, 0x00, 0x90, 0x00, 0x98, 0x80, 0x07, 0x80, 0x0f, 0x03, 0x28, 
-0x01, 0xd1, 0x01, 0x20, 0x00, 0xe0, 0x00, 0x20, 
-0x88, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0x00, 0x00, 0x11, 0x40, 
-0xf0, 0xb5, 0x8a, 0xb0, 0x00, 0x24, 0x05, 0x94, 0x69, 0x49, 0xc9, 0x68, 
-0xc0, 0x46, 0x00, 0x91, 0x68, 0x4a, 0x11, 0x68, 0x01, 0x22, 0x12, 0x04, 
-0x0a, 0x40, 0x17, 0x21, 0x66, 0x4e, 0x00, 0x2a, 0x06, 0xd1, 0x64, 0x4a, 
-0x13, 0x68, 0x1b, 0x0c, 0x04, 0xd1, 0x12, 0x68, 0x92, 0x0a, 0x01, 0xd3, 
-0xf1, 0x60, 0x02, 0xe0, 0x61, 0x4a, 0xc0, 0x46, 0x11, 0x64, 0x61, 0x49, 
-0x89, 0x68, 0x09, 0x04, 0x09, 0x0c, 0x03, 0x29, 0x54, 0xd1, 0xe9, 0x21, 
-0x01, 0x91, 0x02, 0x99, 0xc0, 0x46, 0xb1, 0x60, 0x06, 0x94, 0x06, 0x99, 
-0x8a, 0x00, 0x5b, 0x49, 0x8a, 0x58, 0x00, 0x2a, 0x73, 0xd0, 0x80, 0x20, 
-0x02, 0x90, 0x06, 0x98, 0x81, 0x00, 0x57, 0x48, 0x41, 0x58, 0x02, 0x9a, 
-0x11, 0x43, 0x02, 0x91, 0x00, 0x24, 0x00, 0x27, 0x25, 0x02, 0x28, 0x1c, 
-0x38, 0x43, 0x09, 0x90, 0x09, 0x98, 0x00, 0x04, 0x51, 0x4b, 0x18, 0x43, 
-0x04, 0x90, 0x09, 0x98, 0xef, 0x23, 0xdb, 0x05, 0x18, 0x43, 0x03, 0x90, 
-0x06, 0x98, 0x80, 0x00, 0x4b, 0x49, 0x08, 0x58, 0x00, 0x04, 0x03, 0x99, 
-0x08, 0x43, 0x03, 0x90, 0x00, 0x2f, 0x02, 0xd1, 0x03, 0x98, 0xc0, 0x46, 
-0x70, 0x60, 0x01, 0x9b, 0x03, 0x9a, 0x02, 0x99, 0x04, 0x98, 0xff, 0xf7, 
-0x89, 0xff, 0x00, 0x28, 0x06, 0xd0, 0x02, 0x99, 0xc0, 0x46, 0xb1, 0x60, 
-0x03, 0x99, 0xc0, 0x46, 0x71, 0x60, 0x5c, 0xe0, 0x79, 0x1c, 0x0f, 0x04, 
-0x3f, 0x0c, 0x17, 0x2f, 0xd1, 0xdd, 0x61, 0x1c, 0x0c, 0x04, 0x24, 0x0c, 
-0x16, 0x2c, 0xca, 0xdd, 0x06, 0x99, 0x01, 0x31, 0x06, 0x91, 0x06, 0x99, 
-0x89, 0x00, 0x37, 0x4a, 0x51, 0x58, 0x00, 0x29, 0xb7, 0xd1, 0x48, 0xe0, 
-0xbf, 0x21, 0xc9, 0x43, 0x04, 0x91, 0xff, 0x21, 0x02, 0x91, 0x97, 0x21, 
-0x01, 0x91, 0x06, 0x94, 0x06, 0x99, 0x89, 0x00, 0x31, 0x4f, 0x79, 0x58, 
-0x00, 0x29, 0x1c, 0xd0, 0x09, 0x94, 0x08, 0x94, 0x06, 0x98, 0x80, 0x00, 
-0x38, 0x58, 0xc0, 0x46, 0x07, 0x90, 0x07, 0x98, 0x00, 0x04, 0x26, 0xe0, 
-0x05, 0x98, 0x15, 0x23, 0x1b, 0x06, 0x18, 0x43, 0x03, 0x90, 0x01, 0x9b, 
-0x03, 0x9a, 0x02, 0x99, 0x04, 0x98, 0xff, 0xf7, 0x49, 0xff, 0x00, 0x28, 
-0x23, 0xd1, 0x09, 0x99, 0x01, 0x31, 0x09, 0x91, 0x17, 0x29, 0x06, 0xd8, 
-0x00, 0xe0, 0x1c, 0xe0, 0x08, 0x98, 0x00, 0x02, 0x09, 0x99, 0x08, 0x43, 
-0x07, 0xe0, 0x08, 0x99, 0x01, 0x31, 0x08, 0x91, 0x17, 0x29, 0x0a, 0xd8, 
-0x09, 0x94, 0x08, 0x98, 0x00, 0x02, 0x07, 0x99, 0x09, 0x04, 0x08, 0x43, 
-0x15, 0x23, 0x1b, 0x06, 0x18, 0x43, 0x05, 0x90, 0xd6, 0xe7, 0x06, 0x99, 
-0x01, 0x31, 0x06, 0x91, 0x06, 0x99, 0x89, 0x00, 0x79, 0x58, 0x00, 0x29, 
-0xc4, 0xd1, 0x0c, 0x4a, 0x11, 0x68, 0x49, 0x0c, 0x05, 0xd2, 0x11, 0x68, 
-0x09, 0x0c, 0x06, 0xd1, 0x11, 0x68, 0x89, 0x0a, 0x03, 0xd3, 0x00, 0x99, 
-0xc0, 0x46, 0xf1, 0x60, 0x03, 0xe0, 0x00, 0x99, 0x06, 0x4a, 0xc0, 0x46, 
-0x11, 0x64, 0x0a, 0xb0, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 
-0x40, 0x01, 0x18, 0x40, 0x00, 0x00, 0x10, 0x40, 0x40, 0x01, 0x18, 0x00, 
-0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x18, 0x40, 0x30, 0x6e, 0x21, 0x40, 
-0x43, 0xff, 0x00, 0x00, 0x0c, 0x6e, 0x21, 0x40, 0x80, 0xb5, 0x82, 0xb0, 
-0x00, 0x20, 0x01, 0x90, 0x1e, 0x48, 0xc1, 0x68, 0x01, 0x29, 0x1b, 0xd1, 
-0x40, 0x88, 0x00, 0x28, 0x18, 0xd1, 0x68, 0x46, 0x01, 0xf0, 0x9a, 0xfe, 
-0x00, 0x28, 0x13, 0xd1, 0xa8, 0x20, 0x01, 0xf0, 
-0xdb, 0xfe, 0x18, 0x4f, 0x00, 0x28, 0x11, 0xd0, 0x04, 0x20, 0xff, 0xf7, 
-0x97, 0xfe, 0x78, 0x6b, 0xc0, 0x46, 0x01, 0x90, 0x01, 0x98, 0x80, 0x07, 
-0x80, 0x0f, 0x03, 0x28, 0x06, 0xd1, 0x00, 0x20, 0x01, 0xf0, 0xca, 0xfe, 
-0x02, 0xb0, 0x80, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x23, 0x00, 0x22, 
-0x00, 0x21, 0x00, 0x20, 0xff, 0xf7, 0x8f, 0xfe, 0x00, 0x23, 0xdb, 0x43, 
-0x18, 0x1c, 0x19, 0x1c, 0x1a, 0x1c, 0xff, 0xf7, 0xc7, 0xfe, 0x00, 0x28, 
-0x03, 0xd1, 0xff, 0xf7, 0xdf, 0xfe, 0x00, 0x28, 0xe5, 0xd0, 0x38, 0x6a, 
-0x79, 0x6a, 0xba, 0x6a, 0xfb, 0x6a, 0xff, 0xf7, 0x7c, 0xfe, 0xde, 0xe7, 
-0x68, 0x0e, 0x00, 0x80, 0x00, 0x00, 0x11, 0x40, 0xff, 0xb5, 0x85, 0xb0, 
-0x14, 0x1c, 0x1f, 0x1c, 0x00, 0x20, 0x01, 0x90, 0x01, 0x23, 0x5b, 0x04, 
-0x9f, 0x42, 0x01, 0xd9, 0x0f, 0x20, 0x82, 0xe0, 0x26, 0x1c, 0x43, 0x4d, 
-0xaf, 0x42, 0x00, 0xd2, 0x3d, 0x1c, 0x21, 0x0d, 0x09, 0x05, 0x41, 0x48, 
-0x41, 0x4b, 0x99, 0x42, 0x04, 0xd0, 0x80, 0x25, 0x06, 0x1c, 0x80, 0x2f, 
-0x00, 0xd8, 0x3d, 0x1c, 0x3e, 0x4a, 0x51, 0x69, 0xc0, 0x46, 0x03, 0x91, 
-0x92, 0x69, 0xc0, 0x46, 0x02, 0x92, 0xff, 0x23, 0x01, 0x33, 0x19, 0x43, 
-0x39, 0x4b, 0xc0, 0x46, 0x59, 0x61, 0xff, 0x23, 0x01, 0x33, 0x9a, 0x43, 
-0x36, 0x4b, 0xc0, 0x46, 0x9a, 0x61, 0x01, 0x22, 0x12, 0x05, 0xd1, 0x60, 
-0x33, 0x4a, 0x91, 0x69, 0x01, 0x22, 0x12, 0x05, 0x11, 0x61, 0x31, 0x4a, 
-0xff, 0x23, 0x01, 0x33, 0x91, 0x69, 0x19, 0x43, 0x91, 0x61, 0x01, 0x22, 
-0x12, 0x05, 0x11, 0x61, 0x85, 0x21, 0x89, 0x04, 0x04, 0x91, 0x00, 0x2f, 
-0x34, 0xd0, 0x28, 0x48, 0x86, 0x42, 0x04, 0xd1, 0x30, 0x1c, 0x21, 0x1c, 
-0x2a, 0x1c, 0x03, 0xf0, 0x4f, 0xff, 0x2a, 0x1c, 0x04, 0x98, 0x02, 0x43, 
-0x00, 0x92, 0x01, 0x20, 0x06, 0x99, 0x05, 0x9a, 0x33, 0x1c, 0xfd, 0xf7, 
-0xbd, 0xfd, 0x22, 0x48, 0x22, 0x49, 0x4a, 0x68, 0x52, 0x0a, 0x09, 0xd3, 
-0xff, 0x21, 0x01, 0x31, 0x20, 0x4a, 0xc0, 0x46, 0x11, 0x60, 0x00, 0x28, 
-0x05, 0xd1, 0x11, 0x20, 0x01, 0x90, 0x13, 0xe0, 0x01, 0x38, 0xf0, 0xd1, 
-0xf9, 0xe7, 0x7f, 0x1b, 0x0e, 0xd0, 0x15, 0x48, 0x86, 0x42, 0x01, 0xd1, 
-0x64, 0x19, 0x00, 0xe0, 0x76, 0x19, 0x06, 0x99, 0x49, 0x19, 0x06, 0x91, 
-0x38, 0x1c, 0xaf, 0x42, 0x00, 0xd3, 0x28, 0x1c, 0x05, 0x1c, 0xca, 0xe7, 
-0x0f, 0x48, 0x41, 0x69, 0x03, 0x9b, 0x19, 0x43, 0x41, 0x61, 0x82, 0x69, 
-0x03, 0x9b, 0x9a, 0x43, 0x82, 0x61, 0x01, 0x22, 0x12, 0x05, 0xd1, 0x60, 
-0x81, 0x69, 0xc0, 0x46, 0x11, 0x61, 0x81, 0x69, 0x02, 0x9b, 0x19, 0x43, 
-0x81, 0x61, 0x11, 0x61, 0x01, 0x98, 0x09, 0xb0, 0xf0, 0xbc, 0x08, 0xbc, 
-0x18, 0x47, 0x00, 0x00, 0xf0, 0xff, 0x00, 0x00, 0x50, 0xab, 0x20, 0x40, 
-0x00, 0x00, 0x20, 0x40, 0x68, 0x0e, 0x00, 0x80, 0xff, 0xff, 0x00, 0x00, 
-0x00, 0x00, 0x10, 0x40, 0x00, 0x00, 0x00, 0xb0, 0xff, 0xb5, 0x85, 0xb0, 
-0x04, 0x1c, 0x1f, 0x1c, 0x00, 0x20, 0x01, 0x90, 0x01, 0x23, 0x5b, 0x04, 
-0x9f, 0x42, 0x01, 0xd9, 0x0f, 0x20, 0x7d, 0xe0, 0x26, 0x1c, 0x40, 0x4d, 
-0xaf, 0x42, 0x00, 0xd2, 0x3d, 0x1c, 0x21, 0x0d, 0x09, 0x05, 0x3e, 0x48, 
-0x3e, 0x4b, 0x99, 0x42, 0x04, 0xd0, 0x80, 0x25, 0x06, 0x1c, 0x80, 0x2f, 
-0x00, 0xd8, 0x3d, 0x1c, 0x3b, 0x4a, 0x51, 0x69, 0xc0, 0x46, 0x03, 0x91, 
-0x92, 0x69, 0xc0, 0x46, 0x02, 0x92, 0x10, 0x23, 0x19, 0x43, 0x37, 0x4b, 
-0xc0, 0x46, 0x59, 0x61, 0x10, 0x23, 0x9a, 0x43, 
-0x34, 0x4b, 0xc0, 0x46, 0x9a, 0x61, 0x01, 0x22, 0x12, 0x05, 0xd1, 0x60, 
-0x31, 0x4a, 0x91, 0x69, 0x01, 0x22, 0x12, 0x05, 0x11, 0x61, 0x2f, 0x4a, 
-0x10, 0x23, 0x91, 0x69, 0x19, 0x43, 0x91, 0x61, 0x1a, 0x04, 0x11, 0x61, 
-0x21, 0x21, 0x09, 0x05, 0x04, 0x91, 0x00, 0x2f, 0x33, 0xd0, 0x2a, 0x1c, 
-0x04, 0x98, 0x02, 0x43, 0x00, 0x92, 0x00, 0x20, 0x06, 0x99, 0x07, 0x9a, 
-0x33, 0x1c, 0xfd, 0xf7, 0x27, 0xfd, 0x25, 0x48, 0x25, 0x49, 0x4a, 0x68, 
-0x52, 0x09, 0x08, 0xd3, 0x10, 0x21, 0x24, 0x4a, 0xc0, 0x46, 0x11, 0x60, 
-0x00, 0x28, 0x05, 0xd1, 0x11, 0x20, 0x01, 0x90, 0x1b, 0xe0, 0x01, 0x38, 
-0xf1, 0xd1, 0xf9, 0xe7, 0x19, 0x48, 0x86, 0x42, 0x04, 0xd1, 0x20, 0x1c, 
-0x31, 0x1c, 0x2a, 0x1c, 0x03, 0xf0, 0x96, 0xfe, 0x7f, 0x1b, 0x0e, 0xd0, 
-0x14, 0x48, 0x86, 0x42, 0x01, 0xd0, 0x76, 0x19, 0x00, 0xe0, 0x64, 0x19, 
-0x06, 0x99, 0x49, 0x19, 0x06, 0x91, 0x38, 0x1c, 0xaf, 0x42, 0x00, 0xd3, 
-0x28, 0x1c, 0x05, 0x1c, 0xcb, 0xe7, 0x0f, 0x48, 0x41, 0x69, 0x03, 0x9b, 
-0x19, 0x43, 0x41, 0x61, 0x82, 0x69, 0x03, 0x9b, 0x9a, 0x43, 0x82, 0x61, 
-0x01, 0x22, 0x12, 0x05, 0xd1, 0x60, 0x81, 0x69, 0xc0, 0x46, 0x11, 0x61, 
-0x81, 0x69, 0x02, 0x9b, 0x19, 0x43, 0x81, 0x61, 0x11, 0x61, 0x01, 0x98, 
-0x09, 0xb0, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0xf0, 0xff, 0x00, 0x00, 
-0x50, 0xab, 0x20, 0x40, 0x00, 0x00, 0x20, 0x40, 0x68, 0x0e, 0x00, 0x80, 
-0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x10, 0x40, 0x00, 0x00, 0x00, 0xb0, 
 0x70, 0x47, 0x04, 0x49, 0x00, 0x20, 0x00, 0x22, 0x0a, 0x70, 0x01, 0x30, 
 0x01, 0x31, 0x68, 0x28, 0xfa, 0xd3, 0x70, 0x47, 0xa0, 0x82, 0x20, 0x40, 
 0x00, 0x22, 0x88, 0x42, 0x03, 0xd3, 0x40, 0x1a, 0x01, 0x32, 0x88, 0x42, 
@@ -2987,7 +2639,7 @@
 0xc0, 0x46, 0x93, 0x60, 0x0b, 0x69, 0xc0, 0x46, 0x13, 0x61, 0x4b, 0x69, 
 0xc0, 0x46, 0x53, 0x61, 0xc9, 0x68, 0xc0, 0x46, 0xd1, 0x60, 0x90, 0xbc, 
 0x70, 0x47, 0x01, 0x30, 0x00, 0x06, 0x00, 0x0e, 0x04, 0x28, 0xd9, 0xdb, 
-0x38, 0x1c, 0xf6, 0xe7, 0xd0, 0xab, 0x20, 0x40, 0xf7, 0xb5, 0xc4, 0xb0, 
+0x38, 0x1c, 0xf6, 0xe7, 0x40, 0xab, 0x20, 0x40, 0xf7, 0xb5, 0xc4, 0xb0, 
 0x04, 0x1c, 0x00, 0x20, 0x46, 0x9a, 0x11, 0x21, 0x11, 0x40, 0x6e, 0xd0, 
 0x00, 0x27, 0x79, 0x00, 0xc9, 0x19, 0xc9, 0x00, 0x57, 0x4a, 0x51, 0x58, 
 0x49, 0x0c, 0x03, 0xd2, 0x01, 0x30, 0x00, 0x06, 0x00, 0x0e, 0x04, 0xe0, 
@@ -2998,12 +2650,12 @@
 0x72, 0x1c, 0x16, 0x06, 0x36, 0x0e, 0x04, 0xe0, 0x01, 0x30, 0x00, 0x06, 
 0x00, 0x0e, 0x10, 0x28, 0xf0, 0xdb, 0x00, 0x2e, 0x3d, 0xd0, 0x04, 0x2c, 
 0x3e, 0xd1, 0x80, 0x00, 0x08, 0x58, 0x40, 0x01, 0x80, 0x0d, 0x00, 0x22, 
-0x00, 0x92, 0x10, 0x23, 0x00, 0x21, 0x02, 0xaa, 
-0x00, 0xf0, 0x68, 0xfa, 0x00, 0x21, 0x01, 0x91, 0x02, 0xa8, 0x05, 0x99, 
-0x49, 0x0c, 0x89, 0x05, 0x29, 0xd0, 0xc1, 0x68, 0x0a, 0x06, 0x12, 0x0e, 
-0x45, 0x9b, 0x9a, 0x42, 0x11, 0xd1, 0xc0, 0x68, 0x40, 0x01, 0x86, 0x0d, 
-0x00, 0x22, 0x00, 0x92, 0x0c, 0x23, 0x00, 0x21, 0x30, 0x1c, 0x02, 0xaa, 
-0x00, 0xf0, 0x50, 0xfa, 0x01, 0x99, 0x02, 0x9d, 0x48, 0x1c, 0x01, 0x06, 
+0x00, 0x92, 0x10, 0x23, 0x00, 0x21, 0x02, 0xaa, 0x00, 0xf0, 0x68, 0xfa, 
+0x00, 0x21, 0x01, 0x91, 0x02, 0xa8, 0x05, 0x99, 0x49, 0x0c, 0x89, 0x05, 
+0x29, 0xd0, 0xc1, 0x68, 0x0a, 0x06, 0x12, 0x0e, 0x45, 0x9b, 0x9a, 0x42, 
+0x11, 0xd1, 0xc0, 0x68, 0x40, 0x01, 0x86, 0x0d, 0x00, 0x22, 0x00, 0x92, 
+0x0c, 0x23, 0x00, 0x21, 0x30, 0x1c, 0x02, 0xaa, 0x00, 0xf0, 0x50, 0xfa, 
+0x01, 0x99, 0x02, 0x9d, 0x48, 0x1c, 0x01, 0x06, 
 0x09, 0x0e, 0x01, 0x91, 0x0e, 0xe0, 0x48, 0x01, 0x86, 0x0d, 0x00, 0x22, 
 0x00, 0x92, 0x10, 0x23, 0x00, 0x21, 0x30, 0x1c, 0x02, 0xaa, 0x00, 0xf0, 
 0x3f, 0xfa, 0x02, 0xa8, 0x05, 0x99, 0x49, 0x0c, 0x89, 0x05, 0xd8, 0xd1, 
@@ -3019,7 +2671,7 @@
 0x18, 0x18, 0xc0, 0x00, 0x00, 0x1b, 0x70, 0x61, 0x00, 0x20, 0x50, 0x21, 
 0x46, 0x9a, 0x11, 0x40, 0x50, 0x29, 0x00, 0xd1, 0x28, 0x1c, 0xf0, 0x60, 
 0x38, 0x1c, 0x47, 0xb0, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0xff, 0x20, 
-0xf9, 0xe7, 0x00, 0x00, 0xd0, 0xab, 0x20, 0x40, 0x80, 0xb4, 0x00, 0x23, 
+0xf9, 0xe7, 0x00, 0x00, 0x40, 0xab, 0x20, 0x40, 0x80, 0xb4, 0x00, 0x23, 
 0x00, 0x22, 0x00, 0x29, 0x06, 0xd9, 0x87, 0x5c, 0x7b, 0x40, 0x1b, 0x06, 
 0x1b, 0x0e, 0x01, 0x32, 0x8a, 0x42, 0xf8, 0xd3, 0xd8, 0x43, 0x00, 0x06, 
 0x00, 0x0e, 0x80, 0xbc, 0x70, 0x47, 0xf0, 0xb5, 0xc6, 0xb0, 0x04, 0x28, 
@@ -3041,12 +2693,12 @@
 0x05, 0x98, 0x00, 0x0a, 0x00, 0x02, 0x39, 0x06, 0x09, 0x0e, 0x08, 0x43, 
 0x05, 0x90, 0xff, 0x23, 0x1b, 0x02, 0x98, 0x43, 0x05, 0x90, 0x0c, 0x21, 
 0x03, 0xa8, 0xff, 0xf7, 0x83, 0xff, 0xff, 0x23, 0x1b, 0x02, 0x05, 0x99, 
-0x99, 0x43, 0x00, 0x06, 0x00, 0x0e, 0x00, 0x02, 
-0x08, 0x43, 0x05, 0x90, 0x0c, 0x23, 0x00, 0x21, 0x60, 0x68, 0x03, 0xaa, 
-0x00, 0xf0, 0xca, 0xf9, 0x00, 0x20, 0x45, 0x99, 0x06, 0x4a, 0xc0, 0x46, 
-0x50, 0x50, 0xc1, 0x43, 0x61, 0x60, 0xa1, 0x60, 0xe1, 0x60, 0x21, 0x61, 
-0x61, 0x61, 0x46, 0xb0, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 
-0xd0, 0xab, 0x20, 0x40, 0xb0, 0xb4, 0x4c, 0x42, 0x00, 0x29, 0x00, 0xdb, 
+0x99, 0x43, 0x00, 0x06, 0x00, 0x0e, 0x00, 0x02, 0x08, 0x43, 0x05, 0x90, 
+0x0c, 0x23, 0x00, 0x21, 0x60, 0x68, 0x03, 0xaa, 0x00, 0xf0, 0xca, 0xf9, 
+0x00, 0x20, 0x45, 0x99, 0x06, 0x4a, 0xc0, 0x46, 0x50, 0x50, 0xc1, 0x43, 
+0x61, 0x60, 0xa1, 0x60, 0xe1, 0x60, 0x21, 0x61, 0x61, 0x61, 0x46, 0xb0, 
+0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0x40, 0xab, 0x20, 0x40, 
+0xb0, 0xb4, 0x4c, 0x42, 0x00, 0x29, 0x00, 0xdb, 
 0x0c, 0x1c, 0x00, 0x27, 0xff, 0x43, 0x04, 0x28, 0x21, 0xda, 0x12, 0x4d, 
 0x43, 0x00, 0x18, 0x18, 0xc0, 0x00, 0x40, 0x19, 0x01, 0x2a, 0x05, 0xd0, 
 0x02, 0x2a, 0x09, 0xd0, 0x03, 0x2a, 0x16, 0xd1, 0x01, 0x69, 0x0b, 0xe0, 
@@ -3054,7 +2706,7 @@
 0x00, 0x29, 0x07, 0xda, 0xc1, 0x68, 0xa1, 0x42, 0x09, 0xd3, 0x09, 0x1b, 
 0xc1, 0x60, 0xc0, 0x68, 0xb0, 0xbc, 0x70, 0x47, 0xc1, 0x68, 0x09, 0x19, 
 0x02, 0x69, 0x91, 0x42, 0xf6, 0xd9, 0x38, 0x1c, 0xf6, 0xe7, 0x00, 0x00, 
-0xd0, 0xab, 0x20, 0x40, 0xf0, 0xb5, 0x84, 0xb0, 0x17, 0x1c, 0x0d, 0x1c, 
+0x40, 0xab, 0x20, 0x40, 0xf0, 0xb5, 0x84, 0xb0, 0x17, 0x1c, 0x0d, 0x1c, 
 0x00, 0x21, 0x02, 0x91, 0x42, 0x00, 0x12, 0x18, 0xd2, 0x00, 0x2c, 0x49, 
 0x8b, 0x58, 0x1b, 0x06, 0x1b, 0x0e, 0x01, 0x93, 0x00, 0x23, 0xdb, 0x43, 
 0x04, 0x28, 0x02, 0xda, 0x01, 0x98, 0x40, 0x08, 0x01, 0xd2, 0x18, 0x1c, 
@@ -3070,7 +2722,7 @@
 0x00, 0x92, 0x01, 0x1c, 0x30, 0x1c, 0x2a, 0x1c, 0x3b, 0x1c, 0x00, 0xf0, 
 0xcd, 0xf8, 0xe0, 0x68, 0xc0, 0x19, 0xed, 0x19, 0xe0, 0x60, 0x02, 0x98, 
 0xc0, 0x19, 0x02, 0x90, 0x00, 0x27, 0x00, 0x2f, 0xc2, 0xd8, 0x02, 0x98, 
-0x04, 0xb0, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0xd0, 0xab, 0x20, 0x40, 
+0x04, 0xb0, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x40, 0xab, 0x20, 0x40, 
 0xf0, 0xb5, 0x83, 0xb0, 0x17, 0x1c, 0x0d, 0x1c, 0x00, 0x21, 0x01, 0x91, 
 0x42, 0x00, 0x12, 0x18, 0xd2, 0x00, 0x02, 0x92, 0x30, 0x49, 0x8a, 0x58, 
 0x12, 0x06, 0x12, 0x0e, 0x00, 0x24, 0xe4, 0x43, 0x04, 0x28, 0x01, 0xda, 
@@ -3084,12 +2736,12 @@
 0x91, 0x42, 0x13, 0xd9, 0x13, 0x1a, 0x01, 0x1c, 0x00, 0x98, 0x2a, 0x1c, 
 0x1e, 0x1c, 0x00, 0xf0, 0xdf, 0xf8, 0xe0, 0x68, 0x80, 0x19, 0x75, 0x19, 
 0xe0, 0x60, 0x21, 0x69, 0x88, 0x42, 0x00, 0xd9, 0x20, 0x61, 0xbf, 0x1b, 
-0x01, 0x98, 0x30, 0x18, 0x01, 0x90, 0x12, 0xe0, 
-0x01, 0x1c, 0x00, 0x9e, 0x30, 0x1c, 0x2a, 0x1c, 0x3b, 0x1c, 0x00, 0xf0, 
-0xcb, 0xf8, 0xe0, 0x68, 0xc0, 0x19, 0xed, 0x19, 0xe0, 0x60, 0x21, 0x69, 
-0x88, 0x42, 0x00, 0xd9, 0x20, 0x61, 0x01, 0x98, 0xc0, 0x19, 0x01, 0x90, 
-0x00, 0x27, 0x00, 0x2f, 0xb9, 0xd8, 0x01, 0x98, 0x03, 0xb0, 0xf0, 0xbc, 
-0x08, 0xbc, 0x18, 0x47, 0xd0, 0xab, 0x20, 0x40, 0xb0, 0xb5, 0xc3, 0xb0, 
+0x01, 0x98, 0x30, 0x18, 0x01, 0x90, 0x12, 0xe0, 0x01, 0x1c, 0x00, 0x9e, 
+0x30, 0x1c, 0x2a, 0x1c, 0x3b, 0x1c, 0x00, 0xf0, 0xcb, 0xf8, 0xe0, 0x68, 
+0xc0, 0x19, 0xed, 0x19, 0xe0, 0x60, 0x21, 0x69, 0x88, 0x42, 0x00, 0xd9, 
+0x20, 0x61, 0x01, 0x98, 0xc0, 0x19, 0x01, 0x90, 0x00, 0x27, 0x00, 0x2f, 
+0xb9, 0xd8, 0x01, 0x98, 0x03, 0xb0, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 
+0x40, 0xab, 0x20, 0x40, 0xb0, 0xb5, 0xc3, 0xb0, 
 0x0c, 0x1c, 0x00, 0x27, 0xfa, 0x43, 0x04, 0x28, 0x06, 0xda, 0x41, 0x00, 
 0x09, 0x18, 0xc9, 0x00, 0x14, 0x48, 0x45, 0x58, 0x6b, 0x0c, 0x04, 0xd2, 
 0x10, 0x1c, 0x43, 0xb0, 0xb0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x62, 0x09, 
@@ -3098,222 +2750,222 @@
 0x12, 0x2c, 0x0d, 0xd0, 0x13, 0x2c, 0x05, 0xd0, 0x14, 0x2c, 0x0a, 0xd1, 
 0x03, 0x98, 0x00, 0x04, 0x07, 0x0e, 0x06, 0xe0, 0x03, 0x98, 0x07, 0x06, 
 0x3f, 0x0e, 0x02, 0xe0, 0x01, 0x9f, 0x00, 0xe0, 0x02, 0x9f, 0x38, 0x1c, 
-0xdb, 0xe7, 0x00, 0x00, 0xd0, 0xab, 0x20, 0x40, 0x03, 0x49, 0x00, 0x20, 
+0xdb, 0xe7, 0x00, 0x00, 0x40, 0xab, 0x20, 0x40, 0x03, 0x49, 0x00, 0x20, 
 0x00, 0x22, 0x0a, 0x54, 0x01, 0x30, 0x60, 0x28, 0xfb, 0xd3, 0x70, 0x47, 
-0xd0, 0xab, 0x20, 0x40, 0x00, 0xb5, 0x02, 0xf0, 0x01, 0xfa, 0x57, 0x20, 
-0x02, 0xf0, 0x5e, 0xf9, 0x02, 0xf0, 0xd2, 0xf8, 0x00, 0x0a, 0xfb, 0xd3, 
-0x02, 0xf0, 0xe0, 0xf9, 0x08, 0xbc, 0x18, 0x47, 0xf0, 0xb5, 0x82, 0xb0, 
+0x40, 0xab, 0x20, 0x40, 0x00, 0xb5, 0x02, 0xf0, 0x6f, 0xfa, 0x57, 0x20, 
+0x02, 0xf0, 0xcc, 0xf9, 0x02, 0xf0, 0x40, 0xf9, 0x00, 0x0a, 0xfb, 0xd3, 
+0x02, 0xf0, 0x4e, 0xfa, 0x08, 0xbc, 0x18, 0x47, 0xf0, 0xb5, 0x82, 0xb0, 
 0x07, 0x9d, 0x14, 0x1c, 0x1f, 0x1c, 0x30, 0x4a, 0xd2, 0x6f, 0x20, 0x23, 
 0x16, 0x68, 0x9e, 0x43, 0x16, 0x60, 0x33, 0x1c, 0xff, 0x22, 0x01, 0x32, 
 0x2a, 0x40, 0x40, 0x02, 0x08, 0x43, 0x05, 0x0a, 0x06, 0x1c, 0x00, 0x0c, 
-0x01, 0x90, 0x00, 0x2a, 0x20, 0xd0, 0x02, 0xf0, 0xdd, 0xf9, 0x53, 0x20, 
-0x02, 0xf0, 0x3a, 0xf9, 0x01, 0x98, 0xc0, 0x46, 0x00, 0x90, 0x02, 0xf0, 
-0x35, 0xf9, 0x28, 0x1c, 0x02, 0xf0, 0x32, 0xf9, 0x30, 0x1c, 0x02, 0xf0, 
-0x2f, 0xf9, 0x02, 0xf0, 0xb5, 0xf9, 0xff, 0xf7, 0xc7, 0xff, 0x02, 0xf0, 
-0xc9, 0xf9, 0x54, 0x20, 0x02, 0xf0, 0x26, 0xf9, 0x00, 0x98, 0x02, 0xf0, 
-0x23, 0xf9, 0x28, 0x1c, 0x02, 0xf0, 0x20, 0xf9, 0x30, 0x1c, 0x14, 0xe0, 
-0x02, 0xf0, 0xbc, 0xf9, 0x52, 0x20, 0x02, 0xf0, 0x19, 0xf9, 0x01, 0x98, 
-0x02, 0xf0, 0x16, 0xf9, 0x28, 0x1c, 0x02, 0xf0, 0x13, 0xf9, 0x30, 0x1c, 
-0x02, 0xf0, 0x10, 0xf9, 0x00, 0x20, 0x02, 0xf0, 0x0d, 0xf9, 0x00, 0x20, 
-0x02, 0xf0, 0x0a, 0xf9, 0x00, 0x20, 0x02, 0xf0, 0x07, 0xf9, 0x00, 0x20, 
-0x02, 0xf0, 0x04, 0xf9, 0x00, 0x2f, 0x05, 0xd9, 0x02, 0xf0, 0x76, 0xf8, 
-0x20, 0x70, 0x01, 0x34, 0x01, 0x3f, 0xf9, 0xd1, 0x02, 0xf0, 0x82, 0xf9, 
+0x01, 0x90, 0x00, 0x2a, 0x20, 0xd0, 0x02, 0xf0, 0x4b, 0xfa, 0x53, 0x20, 
+0x02, 0xf0, 0xa8, 0xf9, 0x01, 0x98, 0xc0, 0x46, 0x00, 0x90, 0x02, 0xf0, 
+0xa3, 0xf9, 0x28, 0x1c, 0x02, 0xf0, 0xa0, 0xf9, 0x30, 0x1c, 0x02, 0xf0, 
+0x9d, 0xf9, 0x02, 0xf0, 0x23, 0xfa, 0xff, 0xf7, 0xc7, 0xff, 0x02, 0xf0, 
+0x37, 0xfa, 0x54, 0x20, 0x02, 0xf0, 0x94, 0xf9, 0x00, 0x98, 0x02, 0xf0, 
+0x91, 0xf9, 0x28, 0x1c, 0x02, 0xf0, 0x8e, 0xf9, 0x30, 0x1c, 0x14, 0xe0, 
+0x02, 0xf0, 0x2a, 0xfa, 0x52, 0x20, 0x02, 0xf0, 0x87, 0xf9, 0x01, 0x98, 
+0x02, 0xf0, 0x84, 0xf9, 0x28, 0x1c, 0x02, 0xf0, 0x81, 0xf9, 0x30, 0x1c, 
+0x02, 0xf0, 0x7e, 0xf9, 0x00, 0x20, 0x02, 0xf0, 0x7b, 0xf9, 0x00, 0x20, 
+0x02, 0xf0, 0x78, 0xf9, 0x00, 0x20, 0x02, 0xf0, 0x75, 0xf9, 0x00, 0x20, 
+0x02, 0xf0, 0x72, 0xf9, 0x00, 0x2f, 0x05, 0xd9, 0x02, 0xf0, 0xe4, 0xf8, 
+0x20, 0x70, 0x01, 0x34, 0x01, 0x3f, 0xf9, 0xd1, 0x02, 0xf0, 0xf0, 0xf9, 
 0x04, 0x4a, 0xd0, 0x6f, 0x20, 0x23, 0x01, 0x68, 0x19, 0x43, 0x01, 0x60, 
 0x02, 0xb0, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x68, 0x0e, 0x00, 0x80, 
-0xf0, 0xb5, 0x82, 0xb0, 0x14, 0x1c, 0x1f, 0x1c, 0x40, 0x02, 0x08, 0x43, 
-0x05, 0x1c, 0x2c, 0x49, 0xc8, 0x6f, 0x20, 0x23, 0x02, 0x68, 0x9a, 0x43, 
-0x02, 0x60, 0xc8, 0x6f, 0x40, 0x23, 0x01, 0x68, 0x19, 0x43, 0x01, 0x60, 
-0x02, 0xf0, 0x7a, 0xf9, 0x53, 0x20, 0x02, 0xf0, 0xd7, 0xf8, 0x28, 0x0c, 
-0x06, 0x1c, 0x02, 0xf0, 0xd3, 0xf8, 0x28, 0x0a, 0x01, 0x90, 0x00, 0x90, 
-0x02, 0xf0, 0xce, 0xf8, 0x28, 0x1c, 0x02, 0xf0, 0xcb, 0xf8, 0x02, 0xf0, 
-0x51, 0xf9, 0xff, 0xf7, 0x63, 0xff, 0x02, 0xf0, 0x65, 0xf9, 0x84, 0x20, 
-0x02, 0xf0, 0xc2, 0xf8, 0x30, 0x1c, 0x02, 0xf0, 
-0xbf, 0xf8, 0x00, 0x98, 0x02, 0xf0, 0xbc, 0xf8, 0x28, 0x1c, 0x02, 0xf0, 
-0xb9, 0xf8, 0x00, 0x2f, 0x05, 0xd9, 0x20, 0x78, 0x01, 0x34, 0x02, 0xf0, 
-0xb3, 0xf8, 0x01, 0x3f, 0xf9, 0xd1, 0x02, 0xf0, 0x37, 0xf9, 0x02, 0xf0, 
-0x4d, 0xf9, 0x83, 0x20, 0x02, 0xf0, 0xaa, 0xf8, 0x30, 0x1c, 0x02, 0xf0, 
-0xa7, 0xf8, 0x01, 0x98, 0x02, 0xf0, 0xa4, 0xf8, 0x28, 0x1c, 0x02, 0xf0, 
-0xa1, 0xf8, 0x02, 0xf0, 0x27, 0xf9, 0xff, 0xf7, 0x39, 0xff, 0x07, 0x49, 
-0xc8, 0x6f, 0x40, 0x23, 0x02, 0x68, 0x9a, 0x43, 0x02, 0x60, 0xc8, 0x6f, 
-0x20, 0x23, 0x01, 0x68, 0x19, 0x43, 0x01, 0x60, 0x02, 0xb0, 0xf0, 0xbc, 
-0x08, 0xbc, 0x18, 0x47, 0x68, 0x0e, 0x00, 0x80, 0x70, 0x47, 0x00, 0x00, 
-0x80, 0xb5, 0x01, 0xf0, 0x91, 0xf8, 0x06, 0x4f, 0xc0, 0x46, 0xf8, 0x60, 
-0x01, 0xf0, 0xf4, 0xf8, 0x78, 0x80, 0x01, 0xf0, 0xb3, 0xf8, 0x38, 0x71, 
-0x80, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0x68, 0x0e, 0x00, 0x80, 
-0x00, 0xb5, 0x01, 0xf0, 0x07, 0xf9, 0x02, 0x49, 0xc0, 0x46, 0x08, 0x80, 
-0x08, 0xbc, 0x18, 0x47, 0x68, 0x0e, 0x00, 0x80, 0x0b, 0x48, 0xc1, 0x68, 
-0x01, 0x29, 0x11, 0xd1, 0xc1, 0x6f, 0x02, 0x23, 0x0a, 0x68, 0x1a, 0x43, 
-0x0a, 0x60, 0xc1, 0x6f, 0x80, 0x23, 0x0a, 0x68, 0x1a, 0x43, 0x0a, 0x60, 
-0xc1, 0x18, 0x08, 0x68, 0x82, 0x23, 0x02, 0x68, 0x1a, 0x43, 0x02, 0x60, 
-0x00, 0x20, 0x08, 0x81, 0x70, 0x47, 0x00, 0x00, 0x68, 0x0e, 0x00, 0x80, 
-0xf0, 0xb4, 0x4a, 0x49, 0xca, 0x1d, 0x9d, 0x32, 0x00, 0x20, 0x00, 0x27, 
-0x83, 0x00, 0xd7, 0x50, 0x01, 0x30, 0x17, 0x28, 0xfa, 0xd3, 0x46, 0x4c, 
-0x00, 0x20, 0x82, 0x00, 0xa7, 0x50, 0x01, 0x30, 0x20, 0x28, 0xfa, 0xd3, 
-0x43, 0x4a, 0x00, 0x20, 0x83, 0x00, 0xd7, 0x50, 0x01, 0x30, 0x20, 0x28, 
-0xfa, 0xd3, 0xa7, 0x61, 0x97, 0x61, 0x4f, 0x65, 0x8f, 0x65, 0x3f, 0x4d, 
-0xc0, 0x46, 0x2f, 0x60, 0x6f, 0x60, 0xaf, 0x60, 0xaf, 0x61, 0xef, 0x60, 
-0x2f, 0x61, 0x6f, 0x61, 0x00, 0x20, 0xc1, 0x00, 0x09, 0x18, 0x49, 0x01, 
-0x35, 0x4b, 0xc9, 0x18, 0x86, 0x00, 0xcb, 0x1d, 0xf9, 0x33, 0x34, 0x4c, 
-0x34, 0x19, 0xe3, 0x63, 0x11, 0x23, 0x5b, 0x01, 0xcb, 0x18, 0x63, 0x63, 
-0x0d, 0x23, 0x9b, 0x01, 0xcb, 0x18, 0xb4, 0x18, 0xe3, 0x63, 0x23, 0x23, 
-0x5b, 0x01, 0xc9, 0x18, 0x61, 0x63, 0x01, 0x30, 0x02, 0x28, 0xe4, 0xdb, 
-0x29, 0x48, 0xc1, 0x1d, 0xf9, 0x31, 0x29, 0x4c, 0xc0, 0x46, 0xa1, 0x62, 
-0x61, 0x6b, 0x0d, 0x23, 0x9b, 0x01, 0xe1, 0x62, 0xc1, 0x18, 0x91, 0x62, 
-0x51, 0x6b, 0xc0, 0x46, 0xd1, 0x62, 0x08, 0x21, 0xe1, 0x64, 0x25, 0x49, 
-0xc0, 0x46, 0x21, 0x65, 0x24, 0x49, 0x0b, 0x69, 0xc0, 0x46, 0x63, 0x65, 
-0xc3, 0x1d, 0x4d, 0x33, 0xe3, 0x65, 0x25, 0x66, 0x8b, 0x68, 0xc0, 0x46, 
-0x63, 0x66, 0xcb, 0x68, 0xc0, 0x46, 0xa3, 0x66, 0x1e, 0x4b, 0xc0, 0x46, 
-0xe3, 0x66, 0x27, 0x67, 0x0b, 0x23, 0xdb, 0x01, 0xc3, 0x18, 0xa3, 0x67, 
-0x67, 0x67, 0x01, 0x26, 0xe3, 0x1d, 0x69, 0x33, 0x66, 0x61, 0xe7, 0x61, 
-0x1f, 0x73, 0x02, 0x23, 0xd3, 0x64, 0x17, 0x4b, 0xc0, 0x46, 0x13, 0x65, 
-0xcb, 0x69, 0xc0, 0x46, 0x53, 0x65, 0xc3, 0x1d, 0x51, 0x33, 0xd3, 0x65, 
-0x2b, 0x1d, 0x13, 0x66, 0x4b, 0x69, 0xc0, 0x46, 0x53, 0x66, 0x89, 0x69, 
-0xc0, 0x46, 0x91, 0x66, 0x0f, 0x49, 0xc0, 0x46, 0xd1, 0x66, 0x16, 0x67, 
-0x0f, 0x23, 0xdb, 0x01, 0xc0, 0x18, 0x90, 0x67, 0x56, 0x67, 0xd7, 0x61, 
-0xd0, 0x1d, 0x69, 0x30, 0x56, 0x61, 0x07, 0x73, 
+0xf0, 0xb5, 0x82, 0xb0, 0x14, 0x1c, 0x1f, 0x1c, 0x42, 0x02, 0x0a, 0x43, 
+0x15, 0x1c, 0x01, 0x28, 0x54, 0xd0, 0x2c, 0x49, 0xc8, 0x6f, 0x20, 0x23, 
+0x02, 0x68, 0x9a, 0x43, 0x02, 0x60, 0xc8, 0x6f, 0x40, 0x23, 0x01, 0x68, 
+0x19, 0x43, 0x01, 0x60, 0x02, 0xf0, 0xe6, 0xf9, 0x53, 0x20, 0x02, 0xf0, 
+0x43, 0xf9, 0x28, 0x0c, 0x06, 0x1c, 0x02, 0xf0, 0x3f, 0xf9, 0x28, 0x0a, 
+0x01, 0x90, 0x00, 0x90, 0x02, 0xf0, 0x3a, 0xf9, 0x28, 0x1c, 0x02, 0xf0, 
+0x37, 0xf9, 0x02, 0xf0, 0xbd, 0xf9, 0xff, 0xf7, 0x61, 0xff, 0x02, 0xf0, 
+0xd1, 0xf9, 0x84, 0x20, 0x02, 0xf0, 0x2e, 0xf9, 0x30, 0x1c, 0x02, 0xf0, 
+0x2b, 0xf9, 0x00, 0x98, 0x02, 0xf0, 0x28, 0xf9, 0x28, 0x1c, 0x02, 0xf0, 
+0x25, 0xf9, 0x00, 0x2f, 0x05, 0xd9, 0x20, 0x78, 0x01, 0x34, 0x02, 0xf0, 
+0x1f, 0xf9, 0x01, 0x3f, 0xf9, 0xd1, 0x02, 0xf0, 0xa3, 0xf9, 0x02, 0xf0, 
+0xb9, 0xf9, 0x83, 0x20, 0x02, 0xf0, 0x16, 0xf9, 0x30, 0x1c, 0x02, 0xf0, 
+0x13, 0xf9, 0x01, 0x98, 0x02, 0xf0, 0x10, 0xf9, 
+0x28, 0x1c, 0x02, 0xf0, 0x0d, 0xf9, 0x02, 0xf0, 0x93, 0xf9, 0xff, 0xf7, 
+0x37, 0xff, 0x07, 0x49, 0xc8, 0x6f, 0x40, 0x23, 0x02, 0x68, 0x9a, 0x43, 
+0x02, 0x60, 0xc8, 0x6f, 0x20, 0x23, 0x01, 0x68, 0x19, 0x43, 0x01, 0x60, 
+0x02, 0xb0, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x68, 0x0e, 0x00, 0x80, 
+0x70, 0x47, 0x00, 0x00, 0x80, 0xb5, 0x01, 0xf0, 0x8f, 0xf8, 0x06, 0x4f, 
+0xc0, 0x46, 0xf8, 0x60, 0x01, 0xf0, 0xf2, 0xf8, 0x78, 0x80, 0x01, 0xf0, 
+0xb1, 0xf8, 0x38, 0x71, 0x80, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 
+0x68, 0x0e, 0x00, 0x80, 0x00, 0xb5, 0x01, 0xf0, 0x05, 0xf9, 0x02, 0x49, 
+0xc0, 0x46, 0x08, 0x80, 0x08, 0xbc, 0x18, 0x47, 0x68, 0x0e, 0x00, 0x80, 
+0x0b, 0x48, 0xc1, 0x68, 0x01, 0x29, 0x11, 0xd1, 0xc1, 0x6f, 0x02, 0x23, 
+0x0a, 0x68, 0x1a, 0x43, 0x0a, 0x60, 0xc1, 0x6f, 0x80, 0x23, 0x0a, 0x68, 
+0x1a, 0x43, 0x0a, 0x60, 0xc1, 0x18, 0x08, 0x68, 0x82, 0x23, 0x02, 0x68, 
+0x1a, 0x43, 0x02, 0x60, 0x00, 0x20, 0x08, 0x81, 0x70, 0x47, 0x00, 0x00, 
+0x68, 0x0e, 0x00, 0x80, 0xf0, 0xb4, 0x4a, 0x49, 0xca, 0x1d, 0x9d, 0x32, 
+0x00, 0x20, 0x00, 0x27, 0x83, 0x00, 0xd7, 0x50, 0x01, 0x30, 0x17, 0x28, 
+0xfa, 0xd3, 0x46, 0x4c, 0x00, 0x20, 0x82, 0x00, 0xa7, 0x50, 0x01, 0x30, 
+0x20, 0x28, 0xfa, 0xd3, 0x43, 0x4a, 0x00, 0x20, 0x83, 0x00, 0xd7, 0x50, 
+0x01, 0x30, 0x20, 0x28, 0xfa, 0xd3, 0xa7, 0x61, 0x97, 0x61, 0x4f, 0x65, 
+0x8f, 0x65, 0x3f, 0x4d, 0xc0, 0x46, 0x2f, 0x60, 0x6f, 0x60, 0xaf, 0x60, 
+0xaf, 0x61, 0xef, 0x60, 0x2f, 0x61, 0x6f, 0x61, 0x00, 0x20, 0xc1, 0x00, 
+0x09, 0x18, 0x49, 0x01, 0x35, 0x4b, 0xc9, 0x18, 0x86, 0x00, 0xcb, 0x1d, 
+0xf9, 0x33, 0x34, 0x4c, 0x34, 0x19, 0xe3, 0x63, 0x11, 0x23, 0x5b, 0x01, 
+0xcb, 0x18, 0x63, 0x63, 0x0d, 0x23, 0x9b, 0x01, 0xcb, 0x18, 0xb4, 0x18, 
+0xe3, 0x63, 0x23, 0x23, 0x5b, 0x01, 0xc9, 0x18, 0x61, 0x63, 0x01, 0x30, 
+0x02, 0x28, 0xe4, 0xdb, 0x29, 0x48, 0xc1, 0x1d, 0xf9, 0x31, 0x29, 0x4c, 
+0xc0, 0x46, 0xa1, 0x62, 0x61, 0x6b, 0x0d, 0x23, 0x9b, 0x01, 0xe1, 0x62, 
+0xc1, 0x18, 0x91, 0x62, 0x51, 0x6b, 0xc0, 0x46, 0xd1, 0x62, 0x08, 0x21, 
+0xe1, 0x64, 0x25, 0x49, 0xc0, 0x46, 0x21, 0x65, 0x24, 0x49, 0x0b, 0x69, 
+0xc0, 0x46, 0x63, 0x65, 0xc3, 0x1d, 0x4d, 0x33, 0xe3, 0x65, 0x25, 0x66, 
+0x8b, 0x68, 0xc0, 0x46, 0x63, 0x66, 0xcb, 0x68, 0xc0, 0x46, 0xa3, 0x66, 
+0x1e, 0x4b, 0xc0, 0x46, 0xe3, 0x66, 0x27, 0x67, 0x0b, 0x23, 0xdb, 0x01, 
+0xc3, 0x18, 0xa3, 0x67, 0x67, 0x67, 0x01, 0x26, 0xe3, 0x1d, 0x69, 0x33, 
+0x66, 0x61, 0xe7, 0x61, 0x1f, 0x73, 0x02, 0x23, 0xd3, 0x64, 0x17, 0x4b, 
+0xc0, 0x46, 0x13, 0x65, 0xcb, 0x69, 0xc0, 0x46, 0x53, 0x65, 0xc3, 0x1d, 
+0x51, 0x33, 0xd3, 0x65, 0x2b, 0x1d, 0x13, 0x66, 0x4b, 0x69, 0xc0, 0x46, 
+0x53, 0x66, 0x89, 0x69, 0xc0, 0x46, 0x91, 0x66, 0x0f, 0x49, 0xc0, 0x46, 
+0xd1, 0x66, 0x16, 0x67, 0x0f, 0x23, 0xdb, 0x01, 0xc0, 0x18, 0x90, 0x67, 
+0x56, 0x67, 0xd7, 0x61, 0xd0, 0x1d, 0x69, 0x30, 0x56, 0x61, 0x07, 0x73, 
 0xf0, 0xbc, 0x70, 0x47, 0x68, 0x0e, 0x00, 0x80, 0xe4, 0x2c, 0x00, 0x80, 
-0x64, 0x2d, 0x00, 0x80, 0x3c, 0xef, 0x20, 0x40, 0x30, 0x01, 0x18, 0x00, 
-0x7c, 0x29, 0x00, 0x80, 0xec, 0x54, 0xff, 0xff, 0x38, 0x01, 0x18, 0x00, 
-0xfc, 0x54, 0xff, 0xff, 0x90, 0xb4, 0x00, 0x21, 0x1e, 0x4a, 0xbb, 0x23, 
-0x1b, 0x01, 0xd7, 0x18, 0xf9, 0x73, 0x19, 0x23, 0xdb, 0x01, 0xd0, 0x18, 
-0x01, 0x24, 0xcd, 0x23, 0x1b, 0x01, 0xd3, 0x18, 0xc1, 0x61, 0x1c, 0x70, 
-0x33, 0x23, 0x9b, 0x01, 0xd3, 0x18, 0x99, 0x60, 0xb9, 0x73, 0x59, 0x61, 
-0x2f, 0x23, 0x9b, 0x01, 0xd3, 0x18, 0x19, 0x60, 0x13, 0x4b, 0x51, 0x27, 
-0xbf, 0x03, 0x03, 0x63, 0x3b, 0x60, 0x84, 0x69, 0xe4, 0x18, 0x44, 0x63, 
-0x04, 0x3c, 0x7c, 0x60, 0x01, 0x24, 0xe4, 0x02, 0x84, 0x63, 0x0e, 0x4c, 
-0xc0, 0x46, 0xbc, 0x60, 0x04, 0x6b, 0xc0, 0x46, 0x44, 0x62, 0x84, 0x69, 
-0xe4, 0x18, 0x0b, 0x4b, 0xe3, 0x18, 0xfb, 0x60, 0x03, 0x6b, 0xc0, 0x46, 
-0x83, 0x62, 0x43, 0x6a, 0xc0, 0x46, 0x03, 0x62, 0xc1, 0x63, 0x51, 0x64, 
-0x91, 0x64, 0xd1, 0x65, 0xd1, 0x66, 0x90, 0xbc, 0x70, 0x47, 0x00, 0x00, 
-0x68, 0x0e, 0x00, 0x80, 0x00, 0x00, 0x20, 0x40, 0xfc, 0x07, 0x00, 0x00, 
-0xfc, 0xf7, 0xff, 0xff, 0x90, 0xb4, 0x00, 0x22, 0x1b, 0x49, 0xc9, 0x23, 
-0x1b, 0x01, 0xc8, 0x18, 0x02, 0x71, 0x01, 0x20, 0xbb, 0x23, 0x1b, 0x01, 
-0xcb, 0x18, 0x58, 0x73, 0x17, 0x48, 0x03, 0x1c, 0x00, 0x27, 0xdc, 0x1d, 
-0xc1, 0x34, 0x1c, 0x65, 0x23, 0x1c, 0x01, 0x37, 0x3f, 0x2f, 0xf8, 0xd3, 
-0x1a, 0x65, 0x19, 0x23, 0xdb, 0x01, 0xcf, 0x18, 0x33, 0x23, 0x9b, 0x01, 
-0xcb, 0x18, 0x3a, 0x61, 0x98, 0x61, 0x40, 0x20, 0xf8, 0x60, 0xda, 0x61, 
-0x1a, 0x62, 0xca, 0x64, 0x0a, 0x66, 0x0c, 0x48, 0xc0, 0x46, 0xc2, 0x60, 
-0x0b, 0x48, 0x00, 0x6b, 0xc0, 0x06, 0xc0, 0x0e, 0xf8, 0x63, 0x0a, 0x48, 
-0x01, 0x68, 0xc0, 0x46, 0x19, 0x80, 0x41, 0x68, 0xc0, 0x46, 0x59, 0x80, 
-0x80, 0x68, 0xc0, 0x46, 0x98, 0x80, 0x90, 0xbc, 0x70, 0x47, 0x00, 0x00, 
-0x68, 0x0e, 0x00, 0x80, 0x3c, 0xbd, 0x20, 0x40, 0x3c, 0xef, 0x20, 0x40, 
-0x80, 0x00, 0x14, 0x40, 0x40, 0x00, 0x14, 0x40, 0x00, 0x20, 0x0a, 0x49, 
-0xc0, 0x46, 0x08, 0x73, 0xcb, 0x1d, 0xff, 0x33, 0x3a, 0x33, 0x88, 0x61, 
-0xc8, 0x61, 0x18, 0x70, 0x06, 0x4a, 0xc0, 0x46, 0x10, 0x65, 0x50, 0x66, 
-0x90, 0x66, 0x08, 0x70, 0x58, 0x70, 0xbb, 0x23, 0x1b, 0x01, 0xd1, 0x18, 
-0x08, 0x73, 0x70, 0x47, 0x28, 0x05, 0x00, 0x80, 0x68, 0x0e, 0x00, 0x80, 
-0xf0, 0xb4, 0x2f, 0x49, 0x2f, 0x4a, 0xc0, 0x46, 0x11, 0x61, 0x01, 0x23, 
-0x9b, 0x02, 0xc8, 0x18, 0x50, 0x61, 0x2d, 0x48, 0xc0, 0x46, 0x10, 0x62, 
-0xdb, 0x00, 0xc3, 0x18, 0x53, 0x62, 0x00, 0x23, 0x13, 0x63, 0x53, 0x63, 
-0x29, 0x4a, 0x2a, 0x4f, 0xd4, 0x1d, 0xff, 0x34, 0xfa, 0x34, 0x14, 0xc7, 
-0x08, 0x3f, 0x3b, 0x61, 0x1c, 0x1f, 0x7c, 0x61, 0x26, 0x4f, 0xc0, 0x46, 
-0x39, 0x60, 0xb8, 0x61, 0x79, 0x61, 0xf8, 0x62, 0x3b, 0x63, 0x7b, 0x64, 
-0xba, 0x64, 0xfa, 0x65, 0x22, 0x4f, 0xfe, 0x1d, 0xf9, 0x36, 0x22, 0x4d, 
-0xec, 0x1d, 0x79, 0x34, 0x26, 0x62, 0x51, 0x26, 0xb6, 0x03, 0x37, 0x61, 
-0x24, 0x6a, 0xc0, 0x46, 0x74, 0x61, 0x2f, 0x67, 0x1d, 0x4d, 0x09, 0x27, 
-0x7f, 0x04, 0xec, 0x1d, 0x75, 0x34, 0x7c, 0x60, 0x3d, 0x60, 0x1b, 0x4c, 
-0xc0, 0x46, 0x3c, 0x61, 0xe6, 0x1d, 0x75, 0x36, 0x7e, 0x61, 0x19, 0x4f, 
-0xc0, 0x46, 0x7c, 0x60, 0x3d, 0x60, 0x0f, 0x1c, 
+0x64, 0x2d, 0x00, 0x80, 0x90, 0xee, 0x20, 0x40, 0x30, 0x01, 0x18, 0x00, 
+0x7c, 0x29, 0x00, 0x80, 0x00, 0x55, 0xff, 0xff, 0x38, 0x01, 0x18, 0x00, 
+0x10, 0x55, 0xff, 0xff, 0x90, 0xb4, 0x00, 0x21, 0x1e, 0x4a, 0xbb, 0x23, 
+0x1b, 0x01, 0xd7, 0x18, 0xf9, 0x73, 0x19, 0x23, 
+0xdb, 0x01, 0xd0, 0x18, 0x01, 0x24, 0xcd, 0x23, 0x1b, 0x01, 0xd3, 0x18, 
+0xc1, 0x61, 0x1c, 0x70, 0x33, 0x23, 0x9b, 0x01, 0xd3, 0x18, 0x99, 0x60, 
+0xb9, 0x73, 0x59, 0x61, 0x2f, 0x23, 0x9b, 0x01, 0xd3, 0x18, 0x19, 0x60, 
+0x13, 0x4b, 0x51, 0x27, 0xbf, 0x03, 0x03, 0x63, 0x3b, 0x60, 0x84, 0x69, 
+0xe4, 0x18, 0x44, 0x63, 0x04, 0x3c, 0x7c, 0x60, 0x01, 0x24, 0xe4, 0x02, 
+0x84, 0x63, 0x0e, 0x4c, 0xc0, 0x46, 0xbc, 0x60, 0x04, 0x6b, 0xc0, 0x46, 
+0x44, 0x62, 0x84, 0x69, 0xe4, 0x18, 0x0b, 0x4b, 0xe3, 0x18, 0xfb, 0x60, 
+0x03, 0x6b, 0xc0, 0x46, 0x83, 0x62, 0x43, 0x6a, 0xc0, 0x46, 0x03, 0x62, 
+0xc1, 0x63, 0x51, 0x64, 0x91, 0x64, 0xd1, 0x65, 0xd1, 0x66, 0x90, 0xbc, 
+0x70, 0x47, 0x00, 0x00, 0x68, 0x0e, 0x00, 0x80, 0x00, 0x00, 0x20, 0x40, 
+0xfc, 0x07, 0x00, 0x00, 0xfc, 0xf7, 0xff, 0xff, 0x90, 0xb4, 0x00, 0x22, 
+0x1b, 0x49, 0xc9, 0x23, 0x1b, 0x01, 0xc8, 0x18, 0x02, 0x71, 0x01, 0x20, 
+0xbb, 0x23, 0x1b, 0x01, 0xcb, 0x18, 0x58, 0x73, 0x17, 0x48, 0x03, 0x1c, 
+0x00, 0x27, 0xdc, 0x1d, 0xc1, 0x34, 0x1c, 0x65, 0x23, 0x1c, 0x01, 0x37, 
+0x3f, 0x2f, 0xf8, 0xd3, 0x1a, 0x65, 0x19, 0x23, 0xdb, 0x01, 0xcf, 0x18, 
+0x33, 0x23, 0x9b, 0x01, 0xcb, 0x18, 0x3a, 0x61, 0x98, 0x61, 0x40, 0x20, 
+0xf8, 0x60, 0xda, 0x61, 0x1a, 0x62, 0xca, 0x64, 0x0a, 0x66, 0x0c, 0x48, 
+0xc0, 0x46, 0xc2, 0x60, 0x0b, 0x48, 0x00, 0x6b, 0xc0, 0x06, 0xc0, 0x0e, 
+0xf8, 0x63, 0x0a, 0x48, 0x01, 0x68, 0xc0, 0x46, 0x19, 0x80, 0x41, 0x68, 
+0xc0, 0x46, 0x59, 0x80, 0x80, 0x68, 0xc0, 0x46, 0x98, 0x80, 0x90, 0xbc, 
+0x70, 0x47, 0x00, 0x00, 0x68, 0x0e, 0x00, 0x80, 0x90, 0xbc, 0x20, 0x40, 
+0x90, 0xee, 0x20, 0x40, 0x80, 0x00, 0x14, 0x40, 0x40, 0x00, 0x14, 0x40, 
+0x00, 0x20, 0x0a, 0x49, 0xc0, 0x46, 0x08, 0x73, 0xcb, 0x1d, 0xff, 0x33, 
+0x3a, 0x33, 0x88, 0x61, 0xc8, 0x61, 0x18, 0x70, 0x06, 0x4a, 0xc0, 0x46, 
+0x10, 0x65, 0x50, 0x66, 0x90, 0x66, 0x08, 0x70, 0x58, 0x70, 0xbb, 0x23, 
+0x1b, 0x01, 0xd1, 0x18, 0x08, 0x73, 0x70, 0x47, 0x28, 0x05, 0x00, 0x80, 
+0x68, 0x0e, 0x00, 0x80, 0xf0, 0xb4, 0x2f, 0x49, 0x2f, 0x4a, 0xc0, 0x46, 
+0x11, 0x61, 0x01, 0x23, 0x9b, 0x02, 0xc8, 0x18, 0x50, 0x61, 0x2d, 0x48, 
+0xc0, 0x46, 0x10, 0x62, 0xdb, 0x00, 0xc3, 0x18, 0x53, 0x62, 0x00, 0x23, 
+0x13, 0x63, 0x53, 0x63, 0x29, 0x4a, 0x2a, 0x4f, 0xd4, 0x1d, 0xff, 0x34, 
+0xfa, 0x34, 0x14, 0xc7, 0x08, 0x3f, 0x3b, 0x61, 0x1c, 0x1f, 0x7c, 0x61, 
+0x26, 0x4f, 0xc0, 0x46, 0x39, 0x60, 0xb8, 0x61, 0x79, 0x61, 0xf8, 0x62, 
+0x3b, 0x63, 0x7b, 0x64, 0xba, 0x64, 0xfa, 0x65, 0x22, 0x4f, 0xfe, 0x1d, 
+0xf9, 0x36, 0x22, 0x4d, 0xec, 0x1d, 0x79, 0x34, 0x26, 0x62, 0x51, 0x26, 
+0xb6, 0x03, 0x37, 0x61, 0x24, 0x6a, 0xc0, 0x46, 0x74, 0x61, 0x2f, 0x67, 
+0x1d, 0x4d, 0x09, 0x27, 0x7f, 0x04, 0xec, 0x1d, 0x75, 0x34, 0x7c, 0x60, 
+0x3d, 0x60, 0x1b, 0x4c, 0xc0, 0x46, 0x3c, 0x61, 0xe6, 0x1d, 0x75, 0x36, 
+0x7e, 0x61, 0x19, 0x4f, 0xc0, 0x46, 0x7c, 0x60, 0x3d, 0x60, 0x0f, 0x1c, 
 0x00, 0x21, 0xff, 0x24, 0x01, 0x34, 0x1d, 0x1c, 0x8b, 0x00, 0xfd, 0x50, 
 0x01, 0x31, 0xa1, 0x42, 0xfa, 0xd3, 0x01, 0x1c, 0x00, 0x20, 0x01, 0x27, 
 0xff, 0x02, 0x83, 0x00, 0xcd, 0x50, 0x01, 0x30, 0xb8, 0x42, 0xfa, 0xd3, 
 0x00, 0x20, 0x81, 0x00, 0x55, 0x50, 0x01, 0x30, 0x80, 0x28, 0xfa, 0xd3, 
-0xf0, 0xbc, 0x70, 0x47, 0x24, 0xa3, 0x20, 0x40, 0x40, 0x01, 0x18, 0x00, 
-0x24, 0x83, 0x20, 0x40, 0x24, 0xa9, 0x20, 0x40, 0x80, 0x01, 0x18, 0x00, 
-0xa8, 0x03, 0x00, 0x80, 0x24, 0xa7, 0x20, 0x40, 0x68, 0x0e, 0x00, 0x80, 
-0x24, 0xa8, 0x20, 0x40, 0xa4, 0xa8, 0x20, 0x40, 0x08, 0x04, 0x00, 0x80, 
-0xb8, 0xb5, 0x2c, 0x48, 0xfc, 0xf7, 0x0a, 0xff, 0x01, 0x20, 0x2b, 0x49, 
-0x0a, 0x68, 0x52, 0x0c, 0x06, 0xd2, 0x0a, 0x68, 0x12, 0x0c, 0x02, 0xd1, 
-0x0a, 0x68, 0x92, 0x0a, 0x00, 0xd2, 0x00, 0x20, 0x04, 0x06, 0x24, 0x0e, 
-0x25, 0x4a, 0xd7, 0x1d, 0x0d, 0x37, 0x00, 0x23, 0x00, 0x20, 0x9d, 0x00, 
-0x78, 0x51, 0x01, 0x33, 0x04, 0x2b, 0xfa, 0xd3, 0x01, 0x27, 0x3f, 0x05, 
-0x50, 0x61, 0xf8, 0x60, 0xd0, 0x61, 0xf8, 0x61, 0x00, 0x23, 0xdb, 0x43, 
-0x93, 0x61, 0x3b, 0x61, 0x13, 0x62, 0x3b, 0x62, 0x00, 0x27, 0x1b, 0x4b, 
-0x8d, 0x68, 0xc0, 0x46, 0x00, 0x95, 0x8d, 0x69, 0xc0, 0x46, 0x00, 0x95, 
-0x00, 0x2c, 0x0b, 0xd0, 0xdd, 0x6b, 0xc0, 0x46, 0x00, 0x95, 0x9d, 0x6b, 
-0xc0, 0x46, 0x00, 0x95, 0x5d, 0x6b, 0xc0, 0x46, 0x00, 0x95, 0x1d, 0x6b, 
-0xc0, 0x46, 0x00, 0x95, 0x01, 0x37, 0x40, 0x2f, 0xe8, 0xd3, 0x00, 0x27, 
-0x6c, 0x46, 0x01, 0x23, 0x5b, 0x07, 0x1c, 0x43, 0x01, 0xe0, 0x20, 0x60, 
-0x01, 0x37, 0x0d, 0x68, 0x2b, 0x09, 0x02, 0xd2, 0x80, 0x2f, 0xf8, 0xd3, 
-0x01, 0xe0, 0x80, 0x2f, 0x03, 0xd3, 0x08, 0x49, 0x4b, 0x6e, 0x01, 0x33, 
-0x4b, 0x66, 0xd0, 0x62, 0xb8, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 
-0xf4, 0x01, 0xff, 0xff, 0x00, 0x00, 0x10, 0x40, 0x68, 0x0e, 0x00, 0x80, 
-0x00, 0x01, 0x18, 0x40, 0xa0, 0x82, 0x20, 0x40, 0x90, 0xb4, 0x00, 0x21, 
-0x0e, 0x4f, 0x0f, 0x4a, 0x00, 0x20, 0x4c, 0x01, 0x64, 0x1a, 0xa4, 0x00, 
-0xa3, 0x18, 0x58, 0x60, 0x98, 0x60, 0x18, 0x64, 0x58, 0x64, 0x10, 0x53, 
-0x58, 0x80, 0xcc, 0x00, 0xe4, 0x19, 0x98, 0x67, 0xdc, 0x62, 0x01, 0x31, 
-0x03, 0x29, 0xee, 0xd3, 0x06, 0x49, 0xc0, 0x46, 0x08, 0x60, 0x48, 0x60, 
-0x88, 0x60, 0xc8, 0x60, 0x08, 0x61, 0x90, 0xbc, 0x70, 0x47, 0x00, 0x00, 
-0x58, 0x67, 0x21, 0x40, 0x5c, 0x2b, 0x00, 0x80, 0xd0, 0x2c, 0x00, 0x80, 
-0x64, 0x21, 0x05, 0x48, 0xc0, 0x46, 0x01, 0x63, 0x00, 0x21, 0xc9, 0x43, 
-0x41, 0x63, 0x81, 0x63, 0x00, 0x21, 0xc1, 0x63, 0x01, 0x64, 0x70, 0x47, 
-0x68, 0x0e, 0x00, 0x80, 0x80, 0xb4, 0x01, 0x20, 0x40, 0x02, 0x0a, 0x49, 
-0xc0, 0x46, 0x08, 0x60, 0x3c, 0x20, 0x48, 0x60, 0x88, 0x60, 0x08, 0x48, 
-0xc0, 0x46, 0xc8, 0x60, 0x00, 0x20, 0x07, 0x4a, 0x87, 0x00, 0xcb, 0x68, 
-0xc0, 0x46, 0xda, 0x51, 0x01, 0x30, 0x10, 0x28, 0xf8, 0xd3, 0x80, 0xbc, 
-0x70, 0x47, 0x00, 0x00, 0xe4, 0x2d, 0x00, 0x80, 0xf4, 0x2d, 0x00, 0x80, 
-0x49, 0x4c, 0xff, 0xff, 0x12, 0x49, 0x13, 0x48, 0x67, 0x23, 0x9b, 0x01, 
-0xca, 0x18, 0x06, 0xc0, 0x08, 0x38, 0x11, 0x4b, 0xca, 0x18, 0xc1, 0x60, 
-0x82, 0x60, 0x01, 0x61, 0x0f, 0x49, 0x10, 0x48, 0xa7, 0x23, 0x9b, 0x01, 
-0xca, 0x18, 0x06, 0xc0, 0x08, 0x38, 0x0e, 0x4b, 0xca, 0x18, 0xc1, 0x60, 
-0x82, 0x60, 0x01, 0x61, 0x0c, 0x48, 0x0d, 0x49, 
+0xf0, 0xbc, 0x70, 0x47, 0x24, 0xa3, 0x20, 0x40, 
+0x40, 0x01, 0x18, 0x00, 0x24, 0x83, 0x20, 0x40, 0x24, 0xa9, 0x20, 0x40, 
+0x80, 0x01, 0x18, 0x00, 0xa8, 0x03, 0x00, 0x80, 0x24, 0xa7, 0x20, 0x40, 
+0x68, 0x0e, 0x00, 0x80, 0x24, 0xa8, 0x20, 0x40, 0xa4, 0xa8, 0x20, 0x40, 
+0x08, 0x04, 0x00, 0x80, 0xb8, 0xb5, 0x2c, 0x48, 0xfd, 0xf7, 0xba, 0xfd, 
+0x01, 0x20, 0x2b, 0x49, 0x0a, 0x68, 0x52, 0x0c, 0x06, 0xd2, 0x0a, 0x68, 
+0x12, 0x0c, 0x02, 0xd1, 0x0a, 0x68, 0x92, 0x0a, 0x00, 0xd2, 0x00, 0x20, 
+0x04, 0x06, 0x24, 0x0e, 0x25, 0x4a, 0xd7, 0x1d, 0x0d, 0x37, 0x00, 0x23, 
+0x00, 0x20, 0x9d, 0x00, 0x78, 0x51, 0x01, 0x33, 0x04, 0x2b, 0xfa, 0xd3, 
+0x01, 0x27, 0x3f, 0x05, 0x50, 0x61, 0xf8, 0x60, 0xd0, 0x61, 0xf8, 0x61, 
+0x00, 0x23, 0xdb, 0x43, 0x93, 0x61, 0x3b, 0x61, 0x13, 0x62, 0x3b, 0x62, 
+0x00, 0x27, 0x1b, 0x4b, 0x8d, 0x68, 0xc0, 0x46, 0x00, 0x95, 0x8d, 0x69, 
+0xc0, 0x46, 0x00, 0x95, 0x00, 0x2c, 0x0b, 0xd0, 0xdd, 0x6b, 0xc0, 0x46, 
+0x00, 0x95, 0x9d, 0x6b, 0xc0, 0x46, 0x00, 0x95, 0x5d, 0x6b, 0xc0, 0x46, 
+0x00, 0x95, 0x1d, 0x6b, 0xc0, 0x46, 0x00, 0x95, 0x01, 0x37, 0x40, 0x2f, 
+0xe8, 0xd3, 0x00, 0x27, 0x6c, 0x46, 0x01, 0x23, 0x5b, 0x07, 0x1c, 0x43, 
+0x01, 0xe0, 0x20, 0x60, 0x01, 0x37, 0x0d, 0x68, 0x2b, 0x09, 0x02, 0xd2, 
+0x80, 0x2f, 0xf8, 0xd3, 0x01, 0xe0, 0x80, 0x2f, 0x03, 0xd3, 0x08, 0x49, 
+0x4b, 0x6e, 0x01, 0x33, 0x4b, 0x66, 0xd0, 0x62, 0xb8, 0xbc, 0x08, 0xbc, 
+0x18, 0x47, 0x00, 0x00, 0xf4, 0x01, 0xff, 0xff, 0x00, 0x00, 0x10, 0x40, 
+0x68, 0x0e, 0x00, 0x80, 0x00, 0x01, 0x18, 0x40, 0xa0, 0x82, 0x20, 0x40, 
+0x90, 0xb4, 0x00, 0x21, 0x0e, 0x4f, 0x0f, 0x4a, 0x00, 0x20, 0x4c, 0x01, 
+0x64, 0x1a, 0xa4, 0x00, 0xa3, 0x18, 0x58, 0x60, 0x98, 0x60, 0x18, 0x64, 
+0x58, 0x64, 0x10, 0x53, 0x58, 0x80, 0xcc, 0x00, 0xe4, 0x19, 0x98, 0x67, 
+0xdc, 0x62, 0x01, 0x31, 0x03, 0x29, 0xee, 0xd3, 0x06, 0x49, 0xc0, 0x46, 
+0x08, 0x60, 0x48, 0x60, 0x88, 0x60, 0xc8, 0x60, 0x08, 0x61, 0x90, 0xbc, 
+0x70, 0x47, 0x00, 0x00, 0xac, 0x66, 0x21, 0x40, 0x5c, 0x2b, 0x00, 0x80, 
+0xd0, 0x2c, 0x00, 0x80, 0x64, 0x21, 0x05, 0x48, 0xc0, 0x46, 0x01, 0x63, 
+0x00, 0x21, 0xc9, 0x43, 0x41, 0x63, 0x81, 0x63, 0x00, 0x21, 0xc1, 0x63, 
+0x01, 0x64, 0x70, 0x47, 0x68, 0x0e, 0x00, 0x80, 0x80, 0xb4, 0x01, 0x20, 
+0x40, 0x02, 0x0a, 0x49, 0xc0, 0x46, 0x08, 0x60, 0x3c, 0x20, 0x48, 0x60, 
+0x88, 0x60, 0x08, 0x48, 0xc0, 0x46, 0xc8, 0x60, 0x00, 0x20, 0x07, 0x4a, 
+0x87, 0x00, 0xcb, 0x68, 0xc0, 0x46, 0xda, 0x51, 0x01, 0x30, 0x10, 0x28, 
+0xf8, 0xd3, 0x80, 0xbc, 0x70, 0x47, 0x00, 0x00, 0xe4, 0x2d, 0x00, 0x80, 
+0xf4, 0x2d, 0x00, 0x80, 0x5d, 0x4c, 0xff, 0xff, 0x12, 0x49, 0x13, 0x48, 
+0x67, 0x23, 0x9b, 0x01, 0xca, 0x18, 0x06, 0xc0, 0x08, 0x38, 0x11, 0x4b, 
+0xca, 0x18, 0xc1, 0x60, 0x82, 0x60, 0x01, 0x61, 0x0f, 0x49, 0x10, 0x48, 
+0xa7, 0x23, 0x9b, 0x01, 0xca, 0x18, 0x06, 0xc0, 0x08, 0x38, 0x0e, 0x4b, 
+0xca, 0x18, 0xc1, 0x60, 0x82, 0x60, 0x01, 0x61, 0x0c, 0x48, 0x0d, 0x49, 
 0x67, 0x23, 0x9b, 0x01, 0xc2, 0x18, 0x05, 0xc1, 0x08, 0x39, 0x05, 0x4b, 
 0xc2, 0x18, 0xc8, 0x60, 0x8a, 0x60, 0x08, 0x61, 0x70, 0x47, 0x00, 0x00, 
-0x58, 0x1f, 0x21, 0x40, 0x48, 0x2e, 0x00, 0x80, 0xfc, 0x1f, 0x00, 0x00, 
-0x58, 0xef, 0x20, 0x40, 0x34, 0x2e, 0x00, 0x80, 0xfc, 0x2f, 0x00, 0x00, 
-0x58, 0x3f, 0x21, 0x40, 0x5c, 0x2e, 0x00, 0x80, 0x90, 0xb4, 0x00, 0x21, 
-0x40, 0x4c, 0x00, 0x20, 0x0a, 0x01, 0x12, 0x19, 0x19, 0x23, 0xdb, 0x01, 
-0xd2, 0x18, 0xd0, 0x62, 0x10, 0x63, 0x50, 0x63, 0x90, 0x63, 0x01, 0x31, 
-0x03, 0x29, 0xf3, 0xd3, 0x3a, 0x49, 0xc0, 0x46, 0x08, 0x63, 0x48, 0x63, 
-0x88, 0x63, 0x20, 0x60, 0x01, 0x21, 0xe3, 0x1d, 0x59, 0x33, 0x60, 0x60, 
-0x19, 0x71, 0x18, 0x72, 0x98, 0x71, 0x98, 0x72, 0x59, 0x71, 0x58, 0x72, 
-0xd8, 0x71, 0xd8, 0x72, 0xe2, 0x1d, 0x49, 0x32, 0x11, 0x73, 0x19, 0x70, 
-0x90, 0x73, 0x98, 0x70, 0x51, 0x73, 0x59, 0x70, 0xd0, 0x73, 0xd8, 0x70, 
-0x11, 0x71, 0x11, 0x72, 0x90, 0x71, 0x90, 0x72, 0x50, 0x71, 0x50, 0x72, 
-0xd0, 0x71, 0xd0, 0x72, 0x18, 0x73, 0x02, 0x22, 0xe7, 0x1d, 0x69, 0x37, 
-0x3a, 0x70, 0x99, 0x73, 0xba, 0x70, 0x58, 0x73, 0x78, 0x70, 0xd8, 0x73, 
-0xf8, 0x70, 0x39, 0x71, 0x3a, 0x72, 0xb9, 0x71, 0xb9, 0x72, 0x78, 0x71, 
-0x7a, 0x72, 0xf9, 0x71, 0xf9, 0x72, 0x39, 0x73, 0xe3, 0x1d, 0x79, 0x33, 
-0x1a, 0x70, 0xb9, 0x73, 0x99, 0x70, 0x78, 0x73, 0x5a, 0x70, 0xf9, 0x73, 
-0xd9, 0x70, 0x1a, 0x71, 0x1a, 0x72, 0x99, 0x71, 0x9a, 0x72, 0x58, 0x71, 
-0x5a, 0x72, 0xd9, 0x71, 0xda, 0x72, 0x19, 0x73, 0xe7, 0x1d, 0x89, 0x37, 
-0x3a, 0x70, 0x99, 0x73, 0xb9, 0x70, 0x58, 0x73, 0x7a, 0x70, 0xd9, 0x73, 
-0xf9, 0x70, 0x39, 0x71, 0x3a, 0x72, 0xb9, 0x71, 0xb9, 0x72, 0x78, 0x71, 
-0x7a, 0x72, 0xf9, 0x71, 0xf9, 0x72, 0x3a, 0x73, 0xe3, 0x1d, 0x99, 0x33, 
-0x1a, 0x70, 0xb9, 0x73, 0x9a, 0x70, 0x78, 0x73, 0x5a, 0x70, 0xf9, 0x73, 
-0xda, 0x70, 0x19, 0x71, 0x1a, 0x72, 0x99, 0x71, 0x99, 0x72, 0x58, 0x71, 
-0x5a, 0x72, 0xd9, 0x71, 0xd9, 0x72, 0x20, 0x61, 0xe0, 0x60, 0x60, 0x61, 
-0xa0, 0x60, 0x90, 0xbc, 0x70, 0x47, 0x00, 0x00, 0xa0, 0x1c, 0x00, 0x80, 
-0xe8, 0x19, 0x00, 0x80, 0x81, 0x20, 0x00, 0x02, 0x01, 0x49, 0xc0, 0x46, 
-0x88, 0x62, 0x70, 0x47, 0xc0, 0x00, 0x14, 0x00, 0x09, 0x49, 0x0a, 0x4b, 
-0xc8, 0x18, 0x04, 0x3b, 0xc9, 0x18, 0x08, 0x60, 0x00, 0x21, 0xc2, 0x1d, 
-0x29, 0x32, 0xc2, 0x61, 0x10, 0x1c, 0x01, 0x31, 0x08, 0x29, 0xf8, 0xd3, 
-0xc1, 0x1f, 0x29, 0x39, 0x00, 0x20, 0xc8, 0x61, 0x70, 0x47, 0x00, 0x00, 
-0x68, 0x0e, 0x00, 0x80, 0x84, 0x09, 0x00, 0x00, 0x06, 0x48, 0x07, 0x49, 
-0xc0, 0x46, 0x08, 0x80, 0x48, 0x80, 0x00, 0x20, 0x88, 0x80, 0xc8, 0x80, 
-0x88, 0x60, 0x04, 0x49, 0xc0, 0x46, 0x48, 0x61, 0x88, 0x61, 0x70, 0x47, 
-0xff, 0xff, 0x00, 0x00, 0x4c, 0x2a, 0x00, 0x80, 0x6c, 0x06, 0x00, 0x80, 
-0x00, 0x21, 0x06, 0x48, 0xc2, 0x1d, 0x19, 0x32, 0xc1, 0x60, 0x01, 0x61, 
-0xc1, 0x61, 0x01, 0x62, 0x11, 0x71, 0xff, 0x30, 0x01, 0x30, 0x41, 0x62, 
-0x70, 0x47, 0x00, 0x00, 0x6c, 0x06, 0x00, 0x80, 0x09, 0x48, 0x0a, 0x4b, 
-0xc0, 0x46, 0x18, 0x60, 0x00, 0x21, 0xc2, 0x1d, 0x4d, 0x32, 0xc2, 0x60, 
-0x10, 0x1c, 0x01, 0x31, 0x14, 0x29, 0xf8, 0xd3, 0xc1, 0x1f, 0x4d, 0x39, 
-0x00, 0x20, 0xc8, 0x60, 0x58, 0x60, 0x98, 0x60, 0x70, 0x47, 0x00, 0x00, 
-0xd8, 0x07, 0x00, 0x80, 0x6c, 0x06, 0x00, 0x80, 
-0x00, 0xb5, 0x0b, 0x49, 0x0b, 0x48, 0xfc, 0xf7, 0x3a, 0xfd, 0x0b, 0x48, 
+0xac, 0x1e, 0x21, 0x40, 0x48, 0x2e, 0x00, 0x80, 0xfc, 0x1f, 0x00, 0x00, 
+0xac, 0xee, 0x20, 0x40, 0x34, 0x2e, 0x00, 0x80, 0xfc, 0x2f, 0x00, 0x00, 
+0xac, 0x3e, 0x21, 0x40, 0x5c, 0x2e, 0x00, 0x80, 
+0x90, 0xb4, 0x00, 0x21, 0x40, 0x4c, 0x00, 0x20, 0x0a, 0x01, 0x12, 0x19, 
+0x19, 0x23, 0xdb, 0x01, 0xd2, 0x18, 0xd0, 0x62, 0x10, 0x63, 0x50, 0x63, 
+0x90, 0x63, 0x01, 0x31, 0x03, 0x29, 0xf3, 0xd3, 0x3a, 0x49, 0xc0, 0x46, 
+0x08, 0x63, 0x48, 0x63, 0x88, 0x63, 0x20, 0x60, 0x01, 0x21, 0xe3, 0x1d, 
+0x59, 0x33, 0x60, 0x60, 0x19, 0x71, 0x18, 0x72, 0x98, 0x71, 0x98, 0x72, 
+0x59, 0x71, 0x58, 0x72, 0xd8, 0x71, 0xd8, 0x72, 0xe2, 0x1d, 0x49, 0x32, 
+0x11, 0x73, 0x19, 0x70, 0x90, 0x73, 0x98, 0x70, 0x51, 0x73, 0x59, 0x70, 
+0xd0, 0x73, 0xd8, 0x70, 0x11, 0x71, 0x11, 0x72, 0x90, 0x71, 0x90, 0x72, 
+0x50, 0x71, 0x50, 0x72, 0xd0, 0x71, 0xd0, 0x72, 0x18, 0x73, 0x02, 0x22, 
+0xe7, 0x1d, 0x69, 0x37, 0x3a, 0x70, 0x99, 0x73, 0xba, 0x70, 0x58, 0x73, 
+0x78, 0x70, 0xd8, 0x73, 0xf8, 0x70, 0x39, 0x71, 0x3a, 0x72, 0xb9, 0x71, 
+0xb9, 0x72, 0x78, 0x71, 0x7a, 0x72, 0xf9, 0x71, 0xf9, 0x72, 0x39, 0x73, 
+0xe3, 0x1d, 0x79, 0x33, 0x1a, 0x70, 0xb9, 0x73, 0x99, 0x70, 0x78, 0x73, 
+0x5a, 0x70, 0xf9, 0x73, 0xd9, 0x70, 0x1a, 0x71, 0x1a, 0x72, 0x99, 0x71, 
+0x9a, 0x72, 0x58, 0x71, 0x5a, 0x72, 0xd9, 0x71, 0xda, 0x72, 0x19, 0x73, 
+0xe7, 0x1d, 0x89, 0x37, 0x3a, 0x70, 0x99, 0x73, 0xb9, 0x70, 0x58, 0x73, 
+0x7a, 0x70, 0xd9, 0x73, 0xf9, 0x70, 0x39, 0x71, 0x3a, 0x72, 0xb9, 0x71, 
+0xb9, 0x72, 0x78, 0x71, 0x7a, 0x72, 0xf9, 0x71, 0xf9, 0x72, 0x3a, 0x73, 
+0xe3, 0x1d, 0x99, 0x33, 0x1a, 0x70, 0xb9, 0x73, 0x9a, 0x70, 0x78, 0x73, 
+0x5a, 0x70, 0xf9, 0x73, 0xda, 0x70, 0x19, 0x71, 0x1a, 0x72, 0x99, 0x71, 
+0x99, 0x72, 0x58, 0x71, 0x5a, 0x72, 0xd9, 0x71, 0xd9, 0x72, 0x20, 0x61, 
+0xe0, 0x60, 0x60, 0x61, 0xa0, 0x60, 0x90, 0xbc, 0x70, 0x47, 0x00, 0x00, 
+0xa0, 0x1c, 0x00, 0x80, 0xe8, 0x19, 0x00, 0x80, 0x81, 0x20, 0x00, 0x02, 
+0x01, 0x49, 0xc0, 0x46, 0x88, 0x62, 0x70, 0x47, 0xc0, 0x00, 0x14, 0x00, 
+0x09, 0x49, 0x0a, 0x4b, 0xc8, 0x18, 0x04, 0x3b, 0xc9, 0x18, 0x08, 0x60, 
+0x00, 0x21, 0xc2, 0x1d, 0x29, 0x32, 0xc2, 0x61, 0x10, 0x1c, 0x01, 0x31, 
+0x08, 0x29, 0xf8, 0xd3, 0xc1, 0x1f, 0x29, 0x39, 0x00, 0x20, 0xc8, 0x61, 
+0x70, 0x47, 0x00, 0x00, 0x68, 0x0e, 0x00, 0x80, 0x84, 0x09, 0x00, 0x00, 
+0x06, 0x48, 0x07, 0x49, 0xc0, 0x46, 0x08, 0x80, 0x48, 0x80, 0x00, 0x20, 
+0x88, 0x80, 0xc8, 0x80, 0x88, 0x60, 0x04, 0x49, 0xc0, 0x46, 0x48, 0x61, 
+0x88, 0x61, 0x70, 0x47, 0xff, 0xff, 0x00, 0x00, 0x4c, 0x2a, 0x00, 0x80, 
+0x6c, 0x06, 0x00, 0x80, 0x00, 0x21, 0x06, 0x48, 0xc2, 0x1d, 0x19, 0x32, 
+0xc1, 0x60, 0x01, 0x61, 0xc1, 0x61, 0x01, 0x62, 0x11, 0x71, 0xff, 0x30, 
+0x01, 0x30, 0x41, 0x62, 0x70, 0x47, 0x00, 0x00, 0x6c, 0x06, 0x00, 0x80, 
+0x09, 0x48, 0x0a, 0x4b, 0xc0, 0x46, 0x18, 0x60, 0x00, 0x21, 0xc2, 0x1d, 
+0x4d, 0x32, 0xc2, 0x60, 0x10, 0x1c, 0x01, 0x31, 0x14, 0x29, 0xf8, 0xd3, 
+0xc1, 0x1f, 0x4d, 0x39, 0x00, 0x20, 0xc8, 0x60, 0x58, 0x60, 0x98, 0x60, 
+0x70, 0x47, 0x00, 0x00, 0xd8, 0x07, 0x00, 0x80, 0x6c, 0x06, 0x00, 0x80, 
+0x00, 0xb5, 0x0b, 0x49, 0x0b, 0x48, 0xfd, 0xf7, 0xea, 0xfb, 0x0b, 0x48, 
 0x00, 0x6a, 0x01, 0x23, 0xdb, 0x03, 0x98, 0x43, 0x09, 0x49, 0xc0, 0x46, 
 0x08, 0x62, 0x09, 0x48, 0xc1, 0x68, 0x01, 0x29, 0x04, 0xd1, 0xc0, 0x6f, 
 0x80, 0x23, 0x01, 0x68, 0x19, 0x43, 0x01, 0x60, 0x08, 0xbc, 0x18, 0x47, 
-0x8d, 0xd5, 0x21, 0x40, 0xc1, 0xa8, 0x21, 0x40, 0xc0, 0x00, 0x18, 0x40, 
-0xc0, 0x00, 0x18, 0x00, 0x68, 0x0e, 0x00, 0x80, 0x00, 0xb5, 0x0f, 0x48, 
-0xc1, 0x68, 0x01, 0x29, 0x04, 0xd1, 0xc0, 0x6f, 0x80, 0x23, 0x01, 0x68, 
-0x99, 0x43, 0x01, 0x60, 0x0b, 0x4b, 0x0c, 0x48, 0x0c, 0x4a, 0x00, 0x21, 
-0xfc, 0xf7, 0x0f, 0xfd, 0x0b, 0x48, 0x41, 0x8d, 0x01, 0x31, 0x41, 0x85, 
-0x00, 0x21, 0xc1, 0x85, 0x09, 0x48, 0x00, 0x6a, 0x01, 0x23, 0xdb, 0x03, 
-0x18, 0x43, 0x08, 0x49, 0xc0, 0x46, 0x08, 0x62, 0x08, 0xbc, 0x18, 0x47, 
-0x68, 0x0e, 0x00, 0x80, 0x25, 0xd5, 0x21, 0x40, 0xc1, 0xa8, 0x21, 0x40, 
-0xb8, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xc0, 0x00, 0x18, 0x40, 
-0xc0, 0x00, 0x18, 0x00, 0xf0, 0xb5, 0xfe, 0xf7, 0x9b, 0xfe, 0x1b, 0x4c, 
+0xc1, 0xbd, 0x21, 0x40, 0x75, 0x98, 0x21, 0x40, 
+0xc0, 0x00, 0x18, 0x40, 0xc0, 0x00, 0x18, 0x00, 0x68, 0x0e, 0x00, 0x80, 
+0x00, 0xb5, 0x0f, 0x48, 0xc1, 0x68, 0x01, 0x29, 0x04, 0xd1, 0xc0, 0x6f, 
+0x80, 0x23, 0x01, 0x68, 0x99, 0x43, 0x01, 0x60, 0x0b, 0x4b, 0x0c, 0x48, 
+0x0c, 0x4a, 0x00, 0x21, 0xfd, 0xf7, 0xbf, 0xfb, 0x0b, 0x48, 0x41, 0x8d, 
+0x01, 0x31, 0x41, 0x85, 0x00, 0x21, 0xc1, 0x85, 0x09, 0x48, 0x00, 0x6a, 
+0x01, 0x23, 0xdb, 0x03, 0x18, 0x43, 0x08, 0x49, 0xc0, 0x46, 0x08, 0x62, 
+0x08, 0xbc, 0x18, 0x47, 0x68, 0x0e, 0x00, 0x80, 0x59, 0xbd, 0x21, 0x40, 
+0x75, 0x98, 0x21, 0x40, 0xb8, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 
+0xc0, 0x00, 0x18, 0x40, 0xc0, 0x00, 0x18, 0x00, 0xf0, 0xb5, 0x1b, 0x4c, 
 0x10, 0x26, 0xe0, 0x68, 0x01, 0x28, 0x08, 0xd1, 0x60, 0x88, 0x00, 0x28, 
 0x05, 0xd1, 0x20, 0x79, 0x00, 0x28, 0x02, 0xd1, 0x19, 0x20, 0xa0, 0x67, 
 0x00, 0xe0, 0xa6, 0x67, 0x00, 0x20, 0x07, 0x23, 0x5b, 0x02, 0xe5, 0x18, 
@@ -3342,12 +2994,12 @@
 0x03, 0x03, 0x1b, 0x0b, 0x4e, 0x4c, 0x27, 0x6f, 0x3d, 0x03, 0x2d, 0x0b, 
 0xe7, 0x1d, 0x79, 0x37, 0xab, 0x42, 0x1c, 0xd0, 0xe3, 0x1d, 0x79, 0x33, 
 0x1b, 0x6a, 0xc0, 0x46, 0x40, 0x93, 0x01, 0x23, 0x9b, 0x07, 0x03, 0x43, 
-0x1b, 0x68, 0xcc, 0x00, 0x6e, 0x46, 0x33, 0x51, 
-0x01, 0x23, 0x9b, 0x07, 0x06, 0x1d, 0x33, 0x43, 0x1b, 0x68, 0x6c, 0x44, 
-0x63, 0x60, 0x08, 0x30, 0x01, 0x31, 0x40, 0x9b, 0x83, 0x42, 0x00, 0xd8, 
-0x3f, 0x48, 0x03, 0x03, 0x1b, 0x0b, 0xab, 0x42, 0xe7, 0xd1, 0x00, 0x20, 
-0x01, 0x23, 0x1b, 0x03, 0x13, 0x40, 0x3c, 0x4c, 0x03, 0xd0, 0x63, 0x6a, 
-0x01, 0x33, 0x63, 0x62, 0x09, 0xe0, 0x13, 0x0b, 0x03, 0xd3, 0x23, 0x6a, 
+0x1b, 0x68, 0xcc, 0x00, 0x6e, 0x46, 0x33, 0x51, 0x01, 0x23, 0x9b, 0x07, 
+0x06, 0x1d, 0x33, 0x43, 0x1b, 0x68, 0x6c, 0x44, 0x63, 0x60, 0x08, 0x30, 
+0x01, 0x31, 0x40, 0x9b, 0x83, 0x42, 0x00, 0xd8, 0x3f, 0x48, 0x03, 0x03, 
+0x1b, 0x0b, 0xab, 0x42, 0xe7, 0xd1, 0x00, 0x20, 0x01, 0x23, 0x1b, 0x03, 
+0x13, 0x40, 0x3c, 0x4c, 0x03, 0xd0, 0x63, 0x6a, 0x01, 0x33, 0x63, 0x62, 
+0x09, 0xe0, 0x13, 0x0b, 0x03, 0xd3, 0x23, 0x6a, 
 0x01, 0x33, 0x23, 0x62, 0x03, 0xe0, 0x37, 0x4b, 0x5c, 0x6d, 0x01, 0x34, 
 0x5c, 0x65, 0x00, 0x29, 0x09, 0xd0, 0x03, 0x1c, 0xdc, 0x00, 0x23, 0x1c, 
 0x6b, 0x44, 0x5c, 0x68, 0x01, 0x30, 0x23, 0x0d, 0x01, 0xd2, 0x88, 0x42, 
@@ -3363,12 +3015,12 @@
 0x12, 0x4b, 0xc0, 0x46, 0x2b, 0x67, 0x03, 0x1c, 0xdb, 0x00, 0x6b, 0x44, 
 0x5c, 0x68, 0x01, 0x30, 0x23, 0x0d, 0x04, 0xd3, 0x51, 0x24, 0xa4, 0x03, 
 0x2b, 0x6f, 0xc0, 0x46, 0xa3, 0x61, 0x88, 0x42, 0xde, 0xd1, 0x10, 0x0b, 
-0x03, 0xd3, 0x0e, 0x49, 0x01, 0x20, 0xfc, 0xf7, 0xc2, 0xfb, 0x41, 0xb0, 
+0x03, 0xd3, 0x0e, 0x49, 0x01, 0x20, 0xfd, 0xf7, 0x74, 0xfa, 0x41, 0xb0, 
 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 
 0x00, 0x01, 0x14, 0x40, 0x00, 0x40, 0x14, 0x40, 0x00, 0x00, 0x20, 0x40, 
 0x68, 0x0e, 0x00, 0x80, 0x24, 0xa7, 0x20, 0x40, 0xa4, 0x2a, 0x00, 0x80, 
 0xa0, 0x82, 0x20, 0x40, 0x00, 0x00, 0x10, 0x40, 0xc0, 0x00, 0x18, 0x00, 
-0xb5, 0x4f, 0xff, 0xff, 0xf0, 0xb4, 0x00, 0x21, 0x00, 0x23, 0x07, 0x22, 
+0xc9, 0x4f, 0xff, 0xff, 0xf0, 0xb4, 0x00, 0x21, 0x00, 0x23, 0x07, 0x22, 
 0x06, 0x24, 0x47, 0x4f, 0xc0, 0x46, 0x3c, 0x61, 0x3a, 0x61, 0x01, 0x33, 
 0x20, 0x2b, 0xf9, 0xd3, 0x04, 0x25, 0x3d, 0x61, 0x05, 0x23, 0x3b, 0x61, 
 0x3c, 0x61, 0x3a, 0x61, 0x3c, 0x61, 0x3a, 0x61, 0x3d, 0x61, 0x3b, 0x61, 
@@ -3385,12 +3037,12 @@
 0x02, 0x23, 0x1d, 0x40, 0x04, 0x23, 0x2b, 0x43, 0x3b, 0x61, 0x05, 0x23, 
 0x2b, 0x43, 0x3b, 0x61, 0x45, 0x08, 0x02, 0x23, 0x1d, 0x40, 0x04, 0x23, 
 0x2b, 0x43, 0x3b, 0x61, 0x05, 0x23, 0x2b, 0x43, 0x3b, 0x61, 0x02, 0x25, 
-0x05, 0x40, 0x04, 0x23, 0x2b, 0x43, 0x3b, 0x61, 
-0x05, 0x23, 0x2b, 0x43, 0x3b, 0x61, 0x40, 0x00, 0x02, 0x23, 0x18, 0x40, 
-0x04, 0x23, 0x03, 0x43, 0x3b, 0x61, 0x05, 0x23, 0x18, 0x43, 0x38, 0x61, 
-0x00, 0x25, 0x3d, 0x61, 0x01, 0x23, 0x3b, 0x61, 0x3d, 0x61, 0x3b, 0x61, 
-0x00, 0x20, 0x3d, 0x61, 0x0d, 0x4b, 0x1b, 0x69, 0x49, 0x00, 0x1e, 0x1c, 
-0x02, 0x23, 0x33, 0x40, 0x19, 0x43, 0x01, 0x23, 0x3b, 0x61, 0x01, 0x30, 
+0x05, 0x40, 0x04, 0x23, 0x2b, 0x43, 0x3b, 0x61, 0x05, 0x23, 0x2b, 0x43, 
+0x3b, 0x61, 0x40, 0x00, 0x02, 0x23, 0x18, 0x40, 0x04, 0x23, 0x03, 0x43, 
+0x3b, 0x61, 0x05, 0x23, 0x18, 0x43, 0x38, 0x61, 0x00, 0x25, 0x3d, 0x61, 
+0x01, 0x23, 0x3b, 0x61, 0x3d, 0x61, 0x3b, 0x61, 0x00, 0x20, 0x3d, 0x61, 
+0x0d, 0x4b, 0x1b, 0x69, 0x49, 0x00, 0x1e, 0x1c, 0x02, 0x23, 0x33, 0x40, 
+0x19, 0x43, 0x01, 0x23, 0x3b, 0x61, 0x01, 0x30, 
 0x10, 0x28, 0xf2, 0xd3, 0x02, 0x20, 0x38, 0x61, 0x03, 0x20, 0x38, 0x61, 
 0x3c, 0x61, 0x3a, 0x61, 0x3c, 0x61, 0x3a, 0x61, 0x38, 0x61, 0x48, 0x08, 
 0xf0, 0xbc, 0x70, 0x47, 0x80, 0x00, 0x14, 0x00, 0x68, 0x0e, 0x00, 0x80, 
@@ -3419,21 +3071,21 @@
 0x10, 0x28, 0xf1, 0xd3, 0x17, 0x61, 0x07, 0x23, 0x13, 0x61, 0x17, 0x61, 
 0x13, 0x61, 0x03, 0x20, 0x10, 0x61, 0xf0, 0xbc, 0x70, 0x47, 0x00, 0x00, 
 0x80, 0x00, 0x14, 0x00, 0x68, 0x0e, 0x00, 0x80, 0xf0, 0xb5, 0x4f, 0x4d, 
-0x08, 0x21, 0x02, 0x20, 0x2a, 0x1c, 0xfc, 0xf7, 0x75, 0xfa, 0x4d, 0x4c, 
+0x08, 0x21, 0x02, 0x20, 0x2a, 0x1c, 0xfd, 0xf7, 0x27, 0xf9, 0x4d, 0x4c, 
 0x71, 0x23, 0x5b, 0x01, 0xe7, 0x18, 0x38, 0x80, 0x1a, 0x21, 0x02, 0x20, 
-0x2a, 0x1c, 0xfc, 0xf7, 0x6b, 0xfa, 0x78, 0x80, 0x20, 0x79, 0x00, 0x28, 
+0x2a, 0x1c, 0xfd, 0xf7, 0x1d, 0xf9, 0x78, 0x80, 0x20, 0x79, 0x00, 0x28, 
 0x0b, 0xd0, 0x00, 0x20, 0x38, 0x80, 0xe0, 0x68, 0x01, 0x28, 0x10, 0xd1, 
 0x44, 0x48, 0x00, 0x68, 0x01, 0x23, 0x9b, 0x02, 0x18, 0x43, 0x99, 0x02, 
 0x08, 0x60, 0xe0, 0x68, 0x01, 0x28, 0x06, 0xd1, 0x60, 0x88, 0x00, 0x28, 
 0x03, 0xd1, 0xf9, 0x21, 0x12, 0x20, 0xff, 0xf7, 0x43, 0xff, 0x01, 0x21, 
 0xc9, 0x03, 0x00, 0x20, 0xff, 0xf7, 0x3e, 0xff, 0x00, 0x25, 0x7d, 0x26, 
 0xf6, 0x00, 0x00, 0xe0, 0x01, 0x35, 0x00, 0x20, 0xff, 0xf7, 0x9c, 0xfe, 
-0x00, 0x0c, 0x01, 0xd3, 0xb5, 0x42, 0xf7, 0xd3, 
-0x00, 0x25, 0x05, 0xe0, 0x03, 0x21, 0x09, 0x03, 0x00, 0x20, 0xff, 0xf7, 
-0x2b, 0xff, 0x01, 0x35, 0x00, 0x20, 0xff, 0xf7, 0x8d, 0xfe, 0x40, 0x0b, 
-0x01, 0xd2, 0xb5, 0x42, 0xf2, 0xd3, 0x04, 0x20, 0xff, 0xf7, 0x86, 0xfe, 
-0xff, 0x23, 0xe1, 0x33, 0x98, 0x43, 0x01, 0x21, 0x01, 0x43, 0x38, 0x88, 
-0xff, 0x23, 0x01, 0x33, 0x98, 0x42, 0x03, 0xd1, 0x2f, 0x23, 0x5b, 0x01, 
+0x00, 0x0c, 0x01, 0xd3, 0xb5, 0x42, 0xf7, 0xd3, 0x00, 0x25, 0x05, 0xe0, 
+0x03, 0x21, 0x09, 0x03, 0x00, 0x20, 0xff, 0xf7, 0x2b, 0xff, 0x01, 0x35, 
+0x00, 0x20, 0xff, 0xf7, 0x8d, 0xfe, 0x40, 0x0b, 0x01, 0xd2, 0xb5, 0x42, 
+0xf2, 0xd3, 0x04, 0x20, 0xff, 0xf7, 0x86, 0xfe, 0xff, 0x23, 0xe1, 0x33, 
+0x98, 0x43, 0x01, 0x21, 0x01, 0x43, 0x38, 0x88, 0xff, 0x23, 0x01, 0x33, 
+0x98, 0x42, 0x03, 0xd1, 0x2f, 0x23, 0x5b, 0x01, 
 0x19, 0x43, 0x16, 0xe0, 0x01, 0x28, 0x09, 0xd1, 0x78, 0x88, 0x01, 0x28, 
 0x03, 0xd1, 0x23, 0x23, 0x5b, 0x01, 0x19, 0x43, 0x0d, 0xe0, 0x20, 0x23, 
 0x19, 0x43, 0x0a, 0xe0, 0x00, 0x28, 0x08, 0xd1, 0x78, 0x88, 0x01, 0x28, 
@@ -3445,7 +3097,7 @@
 0xe3, 0xfe, 0x00, 0x27, 0x03, 0xe0, 0x08, 0x2f, 0x01, 0xd3, 0x0f, 0x2f, 
 0x08, 0xd9, 0x38, 0x1c, 0xff, 0xf7, 0x40, 0xfe, 0x79, 0x00, 0x09, 0x19, 
 0x1b, 0x23, 0xdb, 0x01, 0xc9, 0x18, 0x88, 0x83, 0x01, 0x37, 0x20, 0x2f, 
-0xef, 0xd3, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x79, 0xbf, 0x21, 0x40, 
+0xef, 0xd3, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0xed, 0xaf, 0x21, 0x40, 
 0x68, 0x0e, 0x00, 0x80, 0x00, 0x00, 0x10, 0x40, 0x81, 0xb0, 0x13, 0x48, 
 0x01, 0x68, 0xc0, 0x46, 0x00, 0x91, 0x41, 0x68, 0xc0, 0x46, 0x00, 0x91, 
 0x81, 0x68, 0xc0, 0x46, 0x00, 0x91, 0xc1, 0x68, 0xc0, 0x46, 0x00, 0x91, 
@@ -3471,12 +3123,12 @@
 0x16, 0xd1, 0x51, 0x8b, 0xc9, 0x08, 0x13, 0xd2, 0x0f, 0xe0, 0x51, 0x8b, 
 0x09, 0x09, 0x0f, 0xd2, 0x0b, 0xe0, 0x0a, 0x79, 0x00, 0x2a, 0x0b, 0xd1, 
 0x6d, 0x23, 0x5b, 0x01, 0xc9, 0x18, 0x8a, 0x88, 0xc9, 0x88, 0x11, 0x40, 
-0x49, 0x09, 0x09, 0x07, 0x02, 0xd1, 0x04, 0x23, 
-0x98, 0x43, 0xf8, 0x83, 0xf8, 0x8b, 0x04, 0x21, 0x01, 0x40, 0x02, 0x9a, 
-0x1f, 0xd0, 0xb9, 0x8b, 0x4a, 0x0b, 0x27, 0xd3, 0x80, 0x09, 0x25, 0xd3, 
-0xff, 0x23, 0x01, 0x98, 0x01, 0x33, 0x98, 0x42, 0x20, 0xd0, 0x00, 0x25, 
-0x00, 0x98, 0x01, 0x28, 0x00, 0xd1, 0x05, 0x02, 0x01, 0x98, 0x00, 0x28, 
-0x02, 0xd1, 0x01, 0x23, 0x5b, 0x03, 0x1d, 0x43, 0xa9, 0x42, 0x13, 0xd0, 
+0x49, 0x09, 0x09, 0x07, 0x02, 0xd1, 0x04, 0x23, 0x98, 0x43, 0xf8, 0x83, 
+0xf8, 0x8b, 0x04, 0x21, 0x01, 0x40, 0x02, 0x9a, 0x1f, 0xd0, 0xb9, 0x8b, 
+0x4a, 0x0b, 0x27, 0xd3, 0x80, 0x09, 0x25, 0xd3, 0xff, 0x23, 0x01, 0x98, 
+0x01, 0x33, 0x98, 0x42, 0x20, 0xd0, 0x00, 0x25, 0x00, 0x98, 0x01, 0x28, 
+0x00, 0xd1, 0x05, 0x02, 0x01, 0x98, 0x00, 0x28, 0x02, 0xd1, 0x01, 0x23, 
+0x5b, 0x03, 0x1d, 0x43, 0xa9, 0x42, 0x13, 0xd0, 
 0x00, 0x20, 0x29, 0x1c, 0xff, 0xf7, 0x10, 0xfe, 0xbd, 0x83, 0x00, 0x20, 
 0xc0, 0x43, 0x60, 0x62, 0x0a, 0xe0, 0xb8, 0x8b, 0x40, 0x0b, 0x07, 0xd2, 
 0x09, 0x21, 0x49, 0x02, 0x00, 0x20, 0xff, 0xf7, 0x03, 0xfe, 0x09, 0x20, 
@@ -3504,7 +3156,7 @@
 0xff, 0xf7, 0xde, 0xff, 0x01, 0x1c, 0x05, 0x20, 0x00, 0x90, 0x00, 0x20, 
 0x01, 0xab, 0x18, 0x80, 0x04, 0x3b, 0x58, 0x70, 0x1b, 0x22, 0x00, 0xab, 
 0x5a, 0x80, 0xd9, 0x80, 0x05, 0x49, 0xc9, 0x6d, 0xc0, 0x46, 0x02, 0x91, 
-0x03, 0x90, 0x68, 0x46, 0x00, 0x21, 0xfc, 0xf7, 0xd5, 0xf9, 0x04, 0xb0, 
+0x03, 0x90, 0x68, 0x46, 0x00, 0x21, 0xfd, 0xf7, 0x79, 0xf8, 0x04, 0xb0, 
 0x08, 0xbc, 0x18, 0x47, 0xa4, 0x2a, 0x00, 0x80, 0x0f, 0x48, 0x01, 0x68, 
 0x49, 0x0c, 0x05, 0xd2, 0x01, 0x68, 0x09, 0x0c, 0x06, 0xd1, 0x00, 0x68, 
 0x80, 0x0a, 0x03, 0xd3, 0x0b, 0x48, 0x00, 0x68, 0x00, 0x0c, 0x01, 0xe0, 
@@ -3514,12 +3166,12 @@
 0x00, 0x00, 0x10, 0x40, 0x00, 0x00, 0x18, 0x40, 0x00, 0x00, 0x00, 0x80, 
 0x04, 0x99, 0x00, 0x00, 0x07, 0x99, 0x00, 0x00, 0x90, 0xb4, 0x01, 0x24, 
 0x21, 0x1c, 0x18, 0x48, 0x02, 0x68, 0x52, 0x0c, 0x06, 0xd2, 0x02, 0x68, 
-0x12, 0x0c, 0x02, 0xd1, 0x00, 0x68, 0x80, 0x0a, 
-0x00, 0xd2, 0x00, 0x21, 0x09, 0x06, 0x09, 0x0e, 0x12, 0x4f, 0x13, 0x4a, 
-0x02, 0xd0, 0x38, 0x68, 0x00, 0x0c, 0x00, 0xe0, 0x90, 0x6c, 0x00, 0x04, 
-0x00, 0x0c, 0x10, 0x4b, 0x98, 0x42, 0x08, 0xd0, 0x02, 0x33, 0x98, 0x42, 
-0x05, 0xd0, 0x0e, 0x4b, 0x98, 0x42, 0x02, 0xd0, 0x02, 0x3b, 0x98, 0x42, 
-0x0c, 0xd1, 0x00, 0x29, 0x02, 0xd0, 0xf8, 0x6a, 0x00, 0x0c, 0x00, 0xe0, 
+0x12, 0x0c, 0x02, 0xd1, 0x00, 0x68, 0x80, 0x0a, 0x00, 0xd2, 0x00, 0x21, 
+0x09, 0x06, 0x09, 0x0e, 0x12, 0x4f, 0x13, 0x4a, 0x02, 0xd0, 0x38, 0x68, 
+0x00, 0x0c, 0x00, 0xe0, 0x90, 0x6c, 0x00, 0x04, 0x00, 0x0c, 0x10, 0x4b, 
+0x98, 0x42, 0x08, 0xd0, 0x02, 0x33, 0x98, 0x42, 0x05, 0xd0, 0x0e, 0x4b, 
+0x98, 0x42, 0x02, 0xd0, 0x02, 0x3b, 0x98, 0x42, 0x0c, 0xd1, 0x00, 0x29, 
+0x02, 0xd0, 0xf8, 0x6a, 0x00, 0x0c, 0x00, 0xe0, 
 0xd0, 0x6c, 0x40, 0x0a, 0x00, 0xd2, 0x00, 0x24, 0x20, 0x06, 0x00, 0x0e, 
 0x90, 0xbc, 0x70, 0x47, 0x00, 0x20, 0xfb, 0xe7, 0x00, 0x00, 0x10, 0x40, 
 0x00, 0x00, 0x18, 0x40, 0x00, 0x00, 0x00, 0x80, 0x04, 0x99, 0x00, 0x00, 
@@ -3549,47 +3201,36 @@
 0x5b, 0x00, 0x9f, 0x44, 0x05, 0x03, 0x07, 0x03, 0x07, 0x07, 0x05, 0x03, 
 0x03, 0x20, 0x02, 0xe0, 0x01, 0x20, 0x00, 0xe0, 0x00, 0x20, 0x01, 0x21, 
 0x38, 0x60, 0x80, 0x07, 0x00, 0xd1, 0x00, 0x21, 0x08, 0x06, 0x00, 0x0e, 
-0x80, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0x98, 0x6e, 0x21, 0x40, 
+0x80, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0x34, 0x6e, 0x21, 0x40, 
 0x00, 0x00, 0x11, 0x40, 0x00, 0x00, 0x10, 0x40, 0x00, 0x00, 0x18, 0x40, 
-0x00, 0x00, 0x00, 0x80, 0xfe, 0x66, 0xff, 0xff, 0xf0, 0xb5, 0x83, 0xb0, 
-0x07, 0x1c, 0x01, 0x20, 0x02, 0x90, 0x01, 0x25, 0x02, 0x24, 0x10, 0x26, 
-0x20, 0x21, 0x00, 0x91, 0xff, 0xf7, 0xe2, 0xfe, 0x01, 0x28, 0x4d, 0xd1, 
-0x38, 0x2f, 0x01, 0xd0, 0xa8, 0x2f, 0x3a, 0xd1, 0x2e, 0x4e, 0x3c, 0x21, 
-0x02, 0x20, 0x32, 0x1c, 0xfb, 0xf7, 0x4c, 0xff, 0x3e, 0x21, 0x05, 0x1c, 
-0x02, 0x20, 0x32, 0x1c, 0xfb, 0xf7, 0x46, 0xff, 0x00, 0x04, 0x05, 0x43, 
-0x40, 0x21, 0x02, 0x20, 0x32, 0x1c, 0xfb, 0xf7, 
-0x3f, 0xff, 0x01, 0x90, 0x42, 0x21, 0x02, 0x20, 0x32, 0x1c, 0xfb, 0xf7, 
-0x39, 0xff, 0x00, 0x04, 0x01, 0x99, 0x08, 0x43, 0x06, 0x1c, 0xa8, 0x2f, 
-0x1b, 0xd1, 0x1f, 0x4a, 0x44, 0x21, 0x02, 0x20, 0xfb, 0xf7, 0x2e, 0xff, 
-0x04, 0x1c, 0x1c, 0x4a, 0x46, 0x21, 0x02, 0x20, 0xfb, 0xf7, 0x28, 0xff, 
-0x00, 0x04, 0x04, 0x43, 0x18, 0x4a, 0x48, 0x21, 0x02, 0x20, 0xfb, 0xf7, 
-0x21, 0xff, 0x00, 0x90, 0x15, 0x4a, 0x4a, 0x21, 0x02, 0x20, 0xfb, 0xf7, 
-0x1b, 0xff, 0x00, 0x04, 0x00, 0x99, 0x01, 0x43, 0x00, 0x91, 0x28, 0x1c, 
-0x30, 0x43, 0x20, 0x43, 0x00, 0x99, 0x08, 0x43, 0x00, 0xd1, 0x16, 0xe0, 
-0x11, 0x20, 0x00, 0x04, 0x05, 0x62, 0x46, 0x62, 0x84, 0x62, 0x00, 0x99, 
-0xc0, 0x46, 0xc1, 0x62, 0x00, 0x21, 0x0a, 0x48, 0xc0, 0x46, 0x01, 0x60, 
-0x38, 0x2f, 0x01, 0xd0, 0xa8, 0x2f, 0x05, 0xd1, 0x01, 0x21, 0x01, 0x60, 
-0xa8, 0x2f, 0x01, 0xd1, 0x03, 0x21, 0x01, 0x60, 0x02, 0x98, 0x03, 0xb0, 
-0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0x79, 0xbf, 0x21, 0x40, 
-0x98, 0x6e, 0x21, 0x40, 0x70, 0x47, 0x00, 0x00, 0x70, 0x47, 0x00, 0x00, 
-0x90, 0xb5, 0x07, 0x1c, 0x12, 0x4c, 0x21, 0x68, 0x12, 0x48, 0x81, 0x42, 
-0x0b, 0xd0, 0x00, 0x23, 0x21, 0x1c, 0xe2, 0x1d, 0xc5, 0x32, 0x00, 0xe0, 
-0x08, 0xc1, 0x91, 0x42, 0xfc, 0xd3, 0x20, 0x60, 0xcc, 0x20, 0xa0, 0x80, 
+0x00, 0x00, 0x00, 0x80, 0xfe, 0x66, 0xff, 0xff, 0xf0, 0xb5, 0x82, 0xb0, 
+0x07, 0x1c, 0x01, 0x20, 0x01, 0x90, 0xff, 0xf7, 0xe7, 0xfe, 0x01, 0x28, 
+0x13, 0xd1, 0x38, 0x2f, 0x01, 0xd0, 0xa8, 0x2f, 0x07, 0xd1, 0x00, 0x26, 
+0xf6, 0x43, 0x34, 0x1c, 0xa8, 0x2f, 0x02, 0xd1, 0x30, 0x1c, 0x00, 0x96, 
+0x35, 0x1c, 0x11, 0x20, 0x00, 0x04, 0x06, 0x62, 0x44, 0x62, 0x85, 0x62, 
+0x00, 0x99, 0xc0, 0x46, 0xc1, 0x62, 0x00, 0x21, 0x08, 0x48, 0xc0, 0x46, 
+0x01, 0x60, 0x38, 0x2f, 0x01, 0xd0, 0xa8, 0x2f, 0x05, 0xd1, 0x01, 0x21, 
+0x01, 0x60, 0xa8, 0x2f, 0x01, 0xd1, 0x03, 0x21, 0x01, 0x60, 0x01, 0x98, 
+0x02, 0xb0, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x34, 0x6e, 0x21, 0x40, 
+0x70, 0x47, 0x00, 0x00, 0x70, 0x47, 0x00, 0x00, 0x90, 0xb5, 0x07, 0x1c, 
+0x12, 0x4c, 0x21, 0x68, 0x12, 0x48, 0x81, 0x42, 0x0b, 0xd0, 0x00, 0x23, 
+0x21, 0x1c, 0xe2, 0x1d, 0xc1, 0x32, 0x00, 0xe0, 
+0x08, 0xc1, 0x91, 0x42, 0xfc, 0xd3, 0x20, 0x60, 0xc8, 0x20, 0xa0, 0x80, 
 0x67, 0x72, 0x38, 0x01, 0x00, 0xf0, 0x18, 0xf8, 0x27, 0x72, 0x0a, 0x48, 
 0xc0, 0x46, 0xe0, 0x60, 0x09, 0x2f, 0x00, 0xdb, 0x00, 0x27, 0xe0, 0x19, 
 0x01, 0x7d, 0x01, 0x31, 0x01, 0x75, 0xe0, 0x88, 0x01, 0x30, 0xe0, 0x80, 
 0x01, 0x20, 0x90, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0x00, 0x80, 
-0xee, 0xff, 0xc0, 0xd0, 0x02, 0x10, 0x00, 0x03, 0x80, 0xb4, 0x08, 0x4a, 
-0xd1, 0x1d, 0x89, 0x31, 0x0b, 0x7b, 0x20, 0x2b, 0x01, 0xd3, 0x00, 0x23, 
-0x0b, 0x73, 0x07, 0x1c, 0x08, 0x7b, 0x43, 0x1c, 0x0b, 0x73, 0x80, 0x18, 
-0x90, 0x30, 0x47, 0x73, 0x80, 0xbc, 0x70, 0x47, 0x00, 0x00, 0x00, 0x80, 
+0xee, 0xff, 0xc0, 0xd0, 0x08, 0x10, 0x00, 0x03, 0x80, 0xb4, 0x08, 0x4a, 
+0xd1, 0x1d, 0x89, 0x31, 0x0b, 0x7a, 0x20, 0x2b, 0x01, 0xd3, 0x00, 0x23, 
+0x0b, 0x72, 0x07, 0x1c, 0x08, 0x7a, 0x43, 0x1c, 0x0b, 0x72, 0x80, 0x18, 
+0x90, 0x30, 0x47, 0x72, 0x80, 0xbc, 0x70, 0x47, 0x00, 0x00, 0x00, 0x80, 
 0x07, 0x49, 0x01, 0x22, 0x12, 0x04, 0x08, 0x68, 0x02, 0x40, 0x01, 0x20, 
 0x00, 0x2a, 0x06, 0xd1, 0x0a, 0x68, 0x12, 0x0c, 0x02, 0xd1, 0x09, 0x68, 
 0x89, 0x0a, 0x00, 0xd2, 0x00, 0x20, 0x70, 0x47, 0x00, 0x00, 0x10, 0x40, 
 0x90, 0xb5, 0x07, 0x1c, 0x09, 0x4c, 0x38, 0x1c, 0x21, 0x1c, 0xfc, 0xf7, 
-0xab, 0xf8, 0x38, 0x1c, 0x00, 0xf0, 0x0e, 0xf8, 0x01, 0x23, 0xd8, 0x42, 
-0x01, 0xd1, 0x00, 0x0c, 0xe0, 0x80, 0x00, 0x21, 0x20, 0x1c, 0xfb, 0xf7, 
-0xdf, 0xff, 0x90, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x70, 0x67, 0x21, 0x40, 
+0x91, 0xff, 0x38, 0x1c, 0x00, 0xf0, 0x0e, 0xf8, 0x01, 0x23, 0xd8, 0x42, 
+0x01, 0xd1, 0x00, 0x0c, 0xe0, 0x80, 0x00, 0x21, 0x20, 0x1c, 0xfc, 0xf7, 
+0xc5, 0xfe, 0x90, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0xc4, 0x66, 0x21, 0x40, 
 0xf8, 0xb5, 0x07, 0x1c, 0x79, 0x7a, 0x76, 0x48, 0x00, 0x23, 0x76, 0x4c, 
 0x01, 0x29, 0x5d, 0xd1, 0xa2, 0x88, 0xc0, 0x46, 0x00, 0x92, 0xa1, 0x89, 
 0x8a, 0x42, 0x74, 0xda, 0xfa, 0x7a, 0x00, 0x2a, 0x15, 0xd0, 0x7a, 0x6c, 
@@ -3600,23 +3241,23 @@
 0x12, 0x0c, 0x22, 0x80, 0x8a, 0x42, 0x00, 0xdb, 0x23, 0x80, 0x00, 0x22, 
 0x00, 0x29, 0x69, 0xdd, 0x5f, 0x4c, 0xa4, 0x6a, 0x5e, 0x4b, 0x1d, 0x88, 
 0x58, 0x23, 0x6b, 0x43, 0xe3, 0x18, 0xde, 0x1d, 0x01, 0x36, 0x01, 0x23, 
-0x9b, 0x07, 0x33, 0x43, 0x1b, 0x68, 0x1b, 0x06, 
-0x15, 0xd1, 0x58, 0x49, 0x00, 0x9a, 0x01, 0x32, 0x8a, 0x80, 0x8a, 0x88, 
-0xc0, 0x46, 0x42, 0x81, 0x08, 0x88, 0x01, 0x30, 0x54, 0x4e, 0xc0, 0x46, 
-0xf0, 0x80, 0x58, 0x20, 0x68, 0x43, 0x21, 0x18, 0x38, 0x1c, 0x00, 0xf0, 
-0x8d, 0xfa, 0xf0, 0x88, 0x00, 0x04, 0x00, 0x14, 0x95, 0xe0, 0x4d, 0x4b, 
-0x01, 0x35, 0x2d, 0x04, 0x2d, 0x0c, 0x1d, 0x80, 0x8d, 0x42, 0x01, 0xdb, 
-0x00, 0x25, 0x1d, 0x80, 0x01, 0x32, 0x12, 0x04, 0x12, 0x14, 0x91, 0x42, 
-0xce, 0xdc, 0x81, 0xe0, 0xe1, 0x88, 0xe2, 0x89, 0x91, 0x42, 0x18, 0xda, 
-0xf9, 0x7a, 0x00, 0x29, 0x2f, 0xd0, 0x79, 0x6c, 0x49, 0x04, 0x49, 0x0c, 
-0x79, 0x64, 0x2a, 0xd0, 0xe2, 0x89, 0x91, 0x42, 0x27, 0xd8, 0xe1, 0x88, 
-0x01, 0x31, 0xe1, 0x80, 0xe1, 0x88, 0xc0, 0x46, 0x81, 0x81, 0x01, 0x23, 
-0xdb, 0x03, 0x78, 0x6c, 0x18, 0x43, 0x3a, 0x4e, 0xc0, 0x46, 0xf0, 0x80, 
-0x00, 0xe0, 0x63, 0xe0, 0xe0, 0x6a, 0x79, 0x6c, 0x4b, 0x00, 0x59, 0x18, 
-0x49, 0x01, 0x40, 0x18, 0xc1, 0x1f, 0x59, 0x39, 0x38, 0x1c, 0x00, 0xf0, 
-0x79, 0xfa, 0xe0, 0x6a, 0x79, 0x6c, 0x4a, 0x00, 0x52, 0x18, 0x52, 0x01, 
-0x80, 0x18, 0x01, 0x39, 0x09, 0x04, 0x09, 0x0c, 0x60, 0x38, 0x00, 0xf0, 
-0xf3, 0xfa, 0xb6, 0xe7, 0x4a, 0xe0, 0x61, 0x88, 0x01, 0x31, 0x09, 0x04, 
+0x9b, 0x07, 0x33, 0x43, 0x1b, 0x68, 0x1b, 0x06, 0x15, 0xd1, 0x58, 0x49, 
+0x00, 0x9a, 0x01, 0x32, 0x8a, 0x80, 0x8a, 0x88, 0xc0, 0x46, 0x42, 0x81, 
+0x08, 0x88, 0x01, 0x30, 0x54, 0x4e, 0xc0, 0x46, 0xf0, 0x80, 0x58, 0x20, 
+0x68, 0x43, 0x21, 0x18, 0x38, 0x1c, 0x00, 0xf0, 0x39, 0xfb, 0xf0, 0x88, 
+0x00, 0x04, 0x00, 0x14, 0x95, 0xe0, 0x4d, 0x4b, 0x01, 0x35, 0x2d, 0x04, 
+0x2d, 0x0c, 0x1d, 0x80, 0x8d, 0x42, 0x01, 0xdb, 0x00, 0x25, 0x1d, 0x80, 
+0x01, 0x32, 0x12, 0x04, 0x12, 0x14, 0x91, 0x42, 0xce, 0xdc, 0x81, 0xe0, 
+0xe1, 0x88, 0xe2, 0x89, 0x91, 0x42, 0x18, 0xda, 0xf9, 0x7a, 0x00, 0x29, 
+0x2f, 0xd0, 0x79, 0x6c, 0x49, 0x04, 0x49, 0x0c, 0x79, 0x64, 0x2a, 0xd0, 
+0xe2, 0x89, 0x91, 0x42, 0x27, 0xd8, 0xe1, 0x88, 0x01, 0x31, 0xe1, 0x80, 
+0xe1, 0x88, 0xc0, 0x46, 0x81, 0x81, 0x01, 0x23, 0xdb, 0x03, 0x78, 0x6c, 
+0x18, 0x43, 0x3a, 0x4e, 0xc0, 0x46, 0xf0, 0x80, 0x00, 0xe0, 0x63, 0xe0, 
+0xe0, 0x6a, 0x79, 0x6c, 0x4b, 0x00, 0x59, 0x18, 0x49, 0x01, 0x40, 0x18, 
+0xc1, 0x1f, 0x59, 0x39, 0x38, 0x1c, 0x00, 0xf0, 0x0f, 0xfb, 0xe0, 0x6a, 
+0x79, 0x6c, 0x4a, 0x00, 0x52, 0x18, 0x52, 0x01, 0x80, 0x18, 0x01, 0x39, 
+0x09, 0x04, 0x09, 0x0c, 0x60, 0x38, 0x00, 0xf0, 0x89, 0xfb, 0xb6, 0xe7, 
+0x4a, 0xe0, 0x61, 0x88, 0x01, 0x31, 0x09, 0x04, 
 0x09, 0x0c, 0x61, 0x80, 0xe2, 0x89, 0x91, 0x42, 0x00, 0xdb, 0x63, 0x80, 
 0x00, 0x21, 0x00, 0x2a, 0x3e, 0xdd, 0x24, 0x4c, 0xe4, 0x6a, 0x23, 0x4b, 
 0x5d, 0x88, 0x6b, 0x00, 0x5b, 0x19, 0x5b, 0x01, 0xe3, 0x18, 0xde, 0x1d, 
@@ -3624,14 +3265,14 @@
 0x20, 0xd1, 0x1c, 0x4e, 0xf1, 0x88, 0x01, 0x31, 0xf1, 0x80, 0xf1, 0x88, 
 0xc0, 0x46, 0x81, 0x81, 0x70, 0x88, 0x01, 0x23, 0xdb, 0x03, 0x01, 0x30, 
 0x18, 0x43, 0x17, 0x49, 0xc0, 0x46, 0xc8, 0x80, 0x68, 0x00, 0x40, 0x19, 
-0x40, 0x01, 0x21, 0x18, 0x38, 0x1c, 0x00, 0xf0, 0x39, 0xfa, 0x71, 0x88, 
+0x40, 0x01, 0x21, 0x18, 0x38, 0x1c, 0x00, 0xf0, 0xcf, 0xfa, 0x71, 0x88, 
 0x4a, 0x00, 0x52, 0x18, 0x52, 0x01, 0xf0, 0x6a, 0x80, 0x18, 0x00, 0xf0, 
-0xb7, 0xfa, 0x0e, 0x49, 0xc8, 0x88, 0x79, 0xe7, 0x0b, 0x4b, 0x01, 0x35, 
+0x4d, 0xfb, 0x0e, 0x49, 0xc8, 0x88, 0x79, 0xe7, 0x0b, 0x4b, 0x01, 0x35, 
 0x2d, 0x04, 0x2d, 0x0c, 0x5d, 0x80, 0x95, 0x42, 0x01, 0xdb, 0x00, 0x25, 
 0x5d, 0x80, 0x01, 0x31, 0x09, 0x04, 0x09, 0x14, 0x8a, 0x42, 0xc2, 0xdc, 
 0x01, 0x89, 0x01, 0x31, 0x01, 0x81, 0x00, 0x20, 0xc0, 0x43, 0xf8, 0xbc, 
 0x08, 0xbc, 0x18, 0x47, 0x4c, 0x2b, 0x00, 0x80, 0x4c, 0x2a, 0x00, 0x80, 
-0x70, 0x67, 0x21, 0x40, 0xf0, 0xb4, 0x06, 0x1c, 0x01, 0x23, 0xdb, 0x03, 
+0xc4, 0x66, 0x21, 0x40, 0xf0, 0xb4, 0x06, 0x1c, 0x01, 0x23, 0xdb, 0x03, 
 0x33, 0x40, 0x01, 0x24, 0x44, 0x4f, 0x00, 0x20, 0x44, 0x4a, 0x45, 0x4d, 
 0xd1, 0x1d, 0x39, 0x31, 0x00, 0x2b, 0x41, 0xd0, 0xe3, 0x03, 0xf3, 0x1a, 
 0x73, 0xd0, 0xee, 0x89, 0x9e, 0x42, 0x71, 0xd3, 0xee, 0x88, 0x00, 0x2e, 
@@ -3643,23 +3284,23 @@
 0xd2, 0x18, 0x90, 0x63, 0xf2, 0x6a, 0xd2, 0x18, 0xd0, 0x63, 0xf2, 0x6a, 
 0xd2, 0x18, 0x10, 0x64, 0xf2, 0x6a, 0xd2, 0x18, 0x50, 0x64, 0xf2, 0x6a, 
 0xd2, 0x18, 0x90, 0x64, 0xf2, 0x6a, 0xd2, 0x18, 0xd0, 0x64, 0xf0, 0x88, 
-0x01, 0x38, 0xf0, 0x80, 0xf0, 0x88, 0xc0, 0x46, 
-0x88, 0x81, 0x24, 0x49, 0x00, 0x28, 0x39, 0xd1, 0x4f, 0x80, 0x37, 0xe0, 
-0x00, 0x2e, 0x38, 0xd9, 0xab, 0x89, 0xb3, 0x42, 0x30, 0xd3, 0xab, 0x88, 
-0x00, 0x2b, 0x2c, 0xd0, 0x53, 0x89, 0x01, 0x33, 0x53, 0x81, 0x2a, 0x1c, 
-0xad, 0x6a, 0x58, 0x23, 0x01, 0x3e, 0x73, 0x43, 0xed, 0x18, 0xae, 0x68, 
-0x36, 0x06, 0x36, 0x0e, 0x03, 0x2e, 0x02, 0xd0, 0xce, 0x89, 0x01, 0x36, 
-0xce, 0x81, 0xa8, 0x60, 0x95, 0x6a, 0xed, 0x18, 0xa8, 0x63, 0x95, 0x6a, 
-0xed, 0x18, 0xe8, 0x63, 0x95, 0x6a, 0xed, 0x18, 0x28, 0x64, 0x95, 0x6a, 
-0xed, 0x18, 0x68, 0x64, 0x95, 0x6a, 0xed, 0x18, 0xa8, 0x64, 0x95, 0x6a, 
-0xeb, 0x18, 0xd8, 0x64, 0x90, 0x88, 0x01, 0x38, 0x90, 0x80, 0x90, 0x88, 
-0xc0, 0x46, 0x48, 0x81, 0x00, 0x28, 0x03, 0xd1, 0x01, 0xe0, 0x04, 0xe0, 
-0x03, 0xe0, 0x17, 0x80, 0x20, 0x1c, 0xf0, 0xbc, 0x70, 0x47, 0xca, 0x89, 
-0x01, 0x32, 0xca, 0x81, 0xf9, 0xe7, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 
-0x0c, 0x2b, 0x00, 0x80, 0x4c, 0x2a, 0x00, 0x80, 0x00, 0xb5, 0x00, 0x21, 
-0x41, 0x60, 0x10, 0x49, 0x4a, 0x68, 0x00, 0x2a, 0x10, 0xd1, 0xca, 0x68, 
-0x00, 0x2a, 0x04, 0xd0, 0xca, 0x1d, 0x19, 0x32, 0x12, 0x79, 0x00, 0x2a, 
-0x08, 0xd0, 0x4a, 0x69, 0x00, 0x2a, 0x0b, 0xd1, 0x88, 0x61, 0x48, 0x61, 
+0x01, 0x38, 0xf0, 0x80, 0xf0, 0x88, 0xc0, 0x46, 0x88, 0x81, 0x24, 0x49, 
+0x00, 0x28, 0x39, 0xd1, 0x4f, 0x80, 0x37, 0xe0, 0x00, 0x2e, 0x38, 0xd9, 
+0xab, 0x89, 0xb3, 0x42, 0x30, 0xd3, 0xab, 0x88, 0x00, 0x2b, 0x2c, 0xd0, 
+0x53, 0x89, 0x01, 0x33, 0x53, 0x81, 0x2a, 0x1c, 0xad, 0x6a, 0x58, 0x23, 
+0x01, 0x3e, 0x73, 0x43, 0xed, 0x18, 0xae, 0x68, 0x36, 0x06, 0x36, 0x0e, 
+0x03, 0x2e, 0x02, 0xd0, 0xce, 0x89, 0x01, 0x36, 0xce, 0x81, 0xa8, 0x60, 
+0x95, 0x6a, 0xed, 0x18, 0xa8, 0x63, 0x95, 0x6a, 0xed, 0x18, 0xe8, 0x63, 
+0x95, 0x6a, 0xed, 0x18, 0x28, 0x64, 0x95, 0x6a, 0xed, 0x18, 0x68, 0x64, 
+0x95, 0x6a, 0xed, 0x18, 0xa8, 0x64, 0x95, 0x6a, 0xeb, 0x18, 0xd8, 0x64, 
+0x90, 0x88, 0x01, 0x38, 0x90, 0x80, 0x90, 0x88, 0xc0, 0x46, 0x48, 0x81, 
+0x00, 0x28, 0x03, 0xd1, 0x01, 0xe0, 0x04, 0xe0, 0x03, 0xe0, 0x17, 0x80, 
+0x20, 0x1c, 0xf0, 0xbc, 0x70, 0x47, 0xca, 0x89, 0x01, 0x32, 0xca, 0x81, 
+0xf9, 0xe7, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x0c, 0x2b, 0x00, 0x80, 
+0x4c, 0x2a, 0x00, 0x80, 0x00, 0xb5, 0x00, 0x21, 0x41, 0x60, 0x10, 0x49, 
+0x4a, 0x68, 0x00, 0x2a, 0x10, 0xd1, 0xca, 0x68, 0x00, 0x2a, 0x04, 0xd0, 
+0xca, 0x1d, 0x19, 0x32, 0x12, 0x79, 0x00, 0x2a, 0x08, 0xd0, 0x4a, 0x69, 
+0x00, 0x2a, 0x0b, 0xd1, 0x88, 0x61, 0x48, 0x61, 
 0x00, 0xf0, 0x10, 0xf8, 0x08, 0xbc, 0x18, 0x47, 0x4a, 0x69, 0x00, 0x2a, 
 0x02, 0xd1, 0x88, 0x61, 0x48, 0x61, 0xf7, 0xe7, 0x8a, 0x69, 0xc0, 0x46, 
 0x50, 0x60, 0x88, 0x61, 0xf2, 0xe7, 0x00, 0x00, 0x6c, 0x06, 0x00, 0x80, 
@@ -3677,32 +3318,32 @@
 0x01, 0x31, 0x91, 0x42, 0xf4, 0xd3, 0x10, 0x29, 0x07, 0xd2, 0x8a, 0x00, 
 0xd2, 0x18, 0xff, 0x32, 0x01, 0x32, 0x57, 0x62, 0x01, 0x31, 0x10, 0x29, 
 0xf7, 0xd3, 0x11, 0x49, 0x00, 0xf0, 0x22, 0xf8, 0xb0, 0xbc, 0x08, 0xbc, 
-0x18, 0x47, 0x00, 0x00, 0x6c, 0x06, 0x00, 0x80, 0x1c, 0xad, 0x20, 0x40, 
+0x18, 0x47, 0x00, 0x00, 0x6c, 0x06, 0x00, 0x80, 0xac, 0xab, 0x20, 0x40, 
 0x28, 0x01, 0x40, 0x00, 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 
 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, 0x20, 0x01, 0x40, 0x00, 
 0x67, 0x45, 0x23, 0x01, 0xef, 0xcd, 0xab, 0x89, 0x98, 0xba, 0xdc, 0xfe, 
 0x10, 0x32, 0x54, 0x76, 0xc3, 0xd2, 0xe1, 0xf0, 0x36, 0x36, 0x36, 0x36, 
 0x30, 0x80, 0x20, 0x40, 0xb0, 0xb5, 0x0f, 0x1c, 0x15, 0x4d, 0xe9, 0x1d, 
-0xc9, 0x31, 0x15, 0x4c, 0x23, 0x1c, 0x15, 0x4a, 0x00, 0x20, 0xfb, 0xf7, 
-0x50, 0xfc, 0xe9, 0x1d, 0xff, 0x31, 0x1e, 0x31, 0x23, 0x1c, 0x0d, 0x1c, 
-0x11, 0x4a, 0x01, 0x20, 0xfb, 0xf7, 0x47, 0xfc, 0x29, 0x1c, 0x23, 0x1c, 
-0x0e, 0x4a, 0x00, 0x20, 0xfb, 0xf7, 0x41, 0xfc, 
-0x39, 0x1c, 0x23, 0x1c, 0x0c, 0x4a, 0x01, 0x20, 0xfb, 0xf7, 0x3b, 0xfc, 
-0x00, 0x21, 0x0b, 0x48, 0xc2, 0x1d, 0x19, 0x32, 0x51, 0x71, 0x01, 0x21, 
-0xff, 0x30, 0x01, 0x30, 0x41, 0x62, 0x08, 0x1c, 0xb0, 0xbc, 0x08, 0xbc, 
-0x18, 0x47, 0x00, 0x00, 0x1c, 0xad, 0x20, 0x40, 0x75, 0x08, 0xff, 0xff, 
-0x28, 0x00, 0x03, 0x00, 0x40, 0x00, 0x02, 0x00, 0x14, 0x00, 0x07, 0x00, 
-0x6c, 0x06, 0x00, 0x80, 0xf0, 0xb5, 0x37, 0x4a, 0x50, 0x69, 0x01, 0x23, 
-0x9b, 0x07, 0x08, 0x30, 0x18, 0x43, 0x00, 0x68, 0x01, 0x06, 0x09, 0x0e, 
-0x33, 0x4b, 0x01, 0x29, 0x49, 0xd1, 0x1f, 0x68, 0x19, 0x1c, 0x32, 0x4b, 
-0x9f, 0x42, 0x04, 0xd1, 0xff, 0xf7, 0x3e, 0xff, 0xf0, 0xbc, 0x08, 0xbc, 
-0x18, 0x47, 0x00, 0x23, 0x9f, 0x00, 0xcc, 0x59, 0x55, 0x69, 0xef, 0x19, 
-0x3c, 0x61, 0x01, 0x33, 0x05, 0x2b, 0xf7, 0xd3, 0x00, 0x0a, 0x00, 0x02, 
-0x02, 0x23, 0x18, 0x43, 0x53, 0x69, 0xc0, 0x46, 0x98, 0x60, 0x50, 0x69, 
-0x08, 0x23, 0xc2, 0x68, 0x13, 0x40, 0x25, 0x4f, 0xfa, 0x1d, 0xb9, 0x32, 
-0x00, 0x2b, 0x02, 0xd0, 0x04, 0x23, 0x23, 0x4c, 0x01, 0xe0, 0x05, 0x23, 
-0x22, 0x4c, 0xc0, 0x46, 0x14, 0x61, 0x40, 0x24, 0xd4, 0x82, 0x00, 0x24, 
-0x54, 0x83, 0x20, 0x4c, 0x00, 0x22, 0x00, 0x2b, 0x0c, 0xd9, 0x95, 0x00, 
+0xc9, 0x31, 0x15, 0x4c, 0x23, 0x1c, 0x15, 0x4a, 0x00, 0x20, 0xfc, 0xf7, 
+0x44, 0xfb, 0xe9, 0x1d, 0xff, 0x31, 0x1e, 0x31, 0x23, 0x1c, 0x0d, 0x1c, 
+0x11, 0x4a, 0x01, 0x20, 0xfc, 0xf7, 0x3b, 0xfb, 0x29, 0x1c, 0x23, 0x1c, 
+0x0e, 0x4a, 0x00, 0x20, 0xfc, 0xf7, 0x35, 0xfb, 0x39, 0x1c, 0x23, 0x1c, 
+0x0c, 0x4a, 0x01, 0x20, 0xfc, 0xf7, 0x2f, 0xfb, 0x00, 0x21, 0x0b, 0x48, 
+0xc2, 0x1d, 0x19, 0x32, 0x51, 0x71, 0x01, 0x21, 0xff, 0x30, 0x01, 0x30, 
+0x41, 0x62, 0x08, 0x1c, 0xb0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 
+0xac, 0xab, 0x20, 0x40, 0x75, 0x08, 0xff, 0xff, 0x28, 0x00, 0x03, 0x00, 
+0x40, 0x00, 0x02, 0x00, 0x14, 0x00, 0x07, 0x00, 0x6c, 0x06, 0x00, 0x80, 
+0xf0, 0xb5, 0x37, 0x4a, 0x50, 0x69, 0x01, 0x23, 0x9b, 0x07, 0x08, 0x30, 
+0x18, 0x43, 0x00, 0x68, 0x01, 0x06, 0x09, 0x0e, 0x33, 0x4b, 0x01, 0x29, 
+0x49, 0xd1, 0x1f, 0x68, 0x19, 0x1c, 0x32, 0x4b, 0x9f, 0x42, 0x04, 0xd1, 
+0xff, 0xf7, 0x3e, 0xff, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x23, 
+0x9f, 0x00, 0xcc, 0x59, 0x55, 0x69, 0xef, 0x19, 0x3c, 0x61, 0x01, 0x33, 
+0x05, 0x2b, 0xf7, 0xd3, 0x00, 0x0a, 0x00, 0x02, 0x02, 0x23, 0x18, 0x43, 
+0x53, 0x69, 0xc0, 0x46, 0x98, 0x60, 0x50, 0x69, 0x08, 0x23, 0xc2, 0x68, 
+0x13, 0x40, 0x25, 0x4f, 0xfa, 0x1d, 0xb9, 0x32, 0x00, 0x2b, 0x02, 0xd0, 
+0x04, 0x23, 0x23, 0x4c, 0x01, 0xe0, 0x05, 0x23, 0x22, 0x4c, 0xc0, 0x46, 
+0x14, 0x61, 0x40, 0x24, 0xd4, 0x82, 0x00, 0x24, 0x54, 0x83, 0x20, 0x4c, 
+0x00, 0x22, 0x00, 0x2b, 0x0c, 0xd9, 0x95, 0x00, 
 0x46, 0x19, 0x76, 0x6a, 0x66, 0x40, 0xed, 0x19, 0xff, 0x35, 0x01, 0x35, 
 0x6e, 0x62, 0x01, 0x32, 0x9a, 0x42, 0xf4, 0xd3, 0x10, 0x2a, 0x07, 0xd2, 
 0x93, 0x00, 0xdb, 0x19, 0xff, 0x33, 0x01, 0x33, 0x5c, 0x62, 0x01, 0x32, 
@@ -3710,26 +3351,51 @@
 0x8f, 0x00, 0xdc, 0x59, 0x55, 0x69, 0xef, 0x19, 0x7c, 0x62, 0x01, 0x31, 
 0x05, 0x29, 0xf7, 0xd3, 0x00, 0x0a, 0x00, 0x02, 0x03, 0x23, 0x18, 0x43, 
 0x51, 0x69, 0xc0, 0x46, 0x88, 0x60, 0x50, 0x69, 0x40, 0x68, 0xc0, 0x46, 
-0x50, 0x61, 0x09, 0x48, 0xfb, 0xf7, 0xb0, 0xfb, 0xa4, 0xe7, 0x00, 0x00, 
+0x50, 0x61, 0x09, 0x48, 0xfc, 0xf7, 0xa4, 0xfa, 0xa4, 0xe7, 0x00, 0x00, 
 0x6c, 0x06, 0x00, 0x80, 0x30, 0x80, 0x20, 0x40, 0x67, 0x45, 0x23, 0x01, 
-0x1c, 0xad, 0x20, 0x40, 0x28, 0x01, 0x40, 0x00, 0x20, 0x01, 0x40, 0x00, 
-0x5c, 0x5c, 0x5c, 0x5c, 0xfd, 0x30, 0xff, 0xff, 0x80, 0xb5, 0x87, 0xb0, 
-0x0f, 0x1c, 0x39, 0x1c, 0x00, 0xf0, 0x48, 0xf8, 0x0e, 0x49, 0xc8, 0x68, 
-0x02, 0x04, 0x89, 0x69, 0x4a, 0x40, 0x05, 0x92, 0x09, 0x04, 0xc9, 0x43, 
-0xc0, 0x43, 0x48, 0x40, 0x06, 0x90, 0x08, 0x21, 0x6a, 0x46, 0x05, 0xa8, 
-0xfd, 0xf7, 0x8b, 0xfb, 0x00, 0x98, 0xc0, 0x46, 0x38, 0x65, 0x03, 0x98, 
-0xc0, 0x46, 0x78, 0x65, 0x04, 0x48, 0x01, 0x89, 0x01, 0x31, 0x01, 0x81, 
-0x07, 0xb0, 0x80, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x08, 0x83, 0x20, 0x40, 
-0x0c, 0x2b, 0x00, 0x80, 0x90, 0xb5, 0x04, 0x1c, 0x0f, 0x1c, 0x20, 0x1c, 
-0x39, 0x1c, 0x00, 0xf0, 0x1f, 0xf8, 0xe0, 0x68, 0x01, 0x0e, 0xff, 0x22, 
-0x12, 0x04, 0x02, 0x40, 0x12, 0x0a, 0x11, 0x43, 0xff, 0x22, 0x12, 0x02, 
-0x02, 0x40, 0x12, 0x02, 0x11, 0x43, 0x00, 0x06, 0x08, 0x43, 0x38, 0x65, 
-0x20, 0x69, 0xc0, 0x46, 0x78, 0x65, 0x60, 0x69, 0xc0, 0x46, 0xb8, 0x65, 
-0x03, 0x48, 0x01, 0x89, 0x01, 0x31, 0x01, 0x81, 0x90, 0xbc, 0x08, 0xbc, 
-0x18, 0x47, 0x00, 0x00, 0x0c, 0x2b, 0x00, 0x80, 0x90, 0xb5, 0x00, 0x22, 
-0x93, 0x00, 0x1f, 0x18, 0xbf, 0x69, 0x5b, 0x18, 0x5f, 0x62, 0x01, 0x32, 
-0x05, 0x2a, 0xf7, 0xd3, 0x07, 0x7a, 0xfb, 0x08, 0x03, 0xd3, 0x00, 0x23, 
-0x92, 0x00, 0x52, 0x18, 0x13, 0x62, 0x07, 0x6b, 
+0xac, 0xab, 0x20, 0x40, 0x28, 0x01, 0x40, 0x00, 0x20, 0x01, 0x40, 0x00, 
+0x5c, 0x5c, 0x5c, 0x5c, 0x11, 0x31, 0xff, 0xff, 0xf0, 0xb5, 0x07, 0x1c, 
+0x3b, 0x48, 0x3c, 0x4c, 0x08, 0x21, 0x20, 0x60, 0xa1, 0x80, 0x00, 0x20, 
+0x20, 0x81, 0xe1, 0x80, 0x60, 0x81, 0x39, 0x48, 0xc0, 0x46, 0xe0, 0x60, 
+0x38, 0x48, 0xc0, 0x46, 0x20, 0x61, 0x38, 0x48, 0xc0, 0x46, 0x60, 0x61, 
+0x37, 0x48, 0xc0, 0x46, 0xa0, 0x61, 0x37, 0x48, 0xc0, 0x46, 0xe0, 0x61, 
+0x36, 0x48, 0xc0, 0x46, 0x20, 0x62, 0x36, 0x48, 0xc0, 0x46, 0x60, 0x62, 
+0x35, 0x48, 0xc0, 0x46, 0xa0, 0x62, 0x35, 0x48, 0xc0, 0x46, 0xe0, 0x62, 
+0x34, 0x48, 0xc0, 0x46, 0x20, 0x63, 0x34, 0x48, 0xc0, 0x46, 0x60, 0x63, 
+0x33, 0x48, 0xc0, 0x46, 0xa0, 0x63, 0x33, 0x48, 0xc0, 0x46, 0xe0, 0x63, 
+0x32, 0x48, 0xc0, 0x46, 0x20, 0x64, 0x32, 0x48, 0xc0, 0x46, 0x60, 0x64, 
+0x31, 0x48, 0xc0, 0x46, 0xa0, 0x64, 0x31, 0x48, 0xc0, 0x46, 0xe0, 0x64, 
+0x30, 0x48, 0xc0, 0x46, 0x20, 0x65, 0x30, 0x49, 0xc8, 0x68, 0x02, 0x04, 
+0x89, 0x69, 0x4a, 0x40, 0xe3, 0x1d, 0x79, 0x33, 0x09, 0x04, 0xc9, 0x43, 
+0xc0, 0x43, 0x48, 0x40, 0xe1, 0x1d, 0xb9, 0x31, 0xda, 0x63, 0x08, 0x60, 
+0x29, 0x4d, 0x21, 0x1c, 0x2b, 0x1c, 0x29, 0x4a, 0x00, 0x20, 0xfc, 0xf7, 
+0x3e, 0xfa, 0x28, 0x4a, 0xe1, 0x1d, 0xb5, 0x31, 0x01, 0x20, 0x2b, 0x1c, 
+0x0e, 0x1c, 0xfc, 0xf7, 0x36, 0xfa, 0x24, 0x4a, 0x00, 0x20, 0x31, 0x1c, 
+0x2b, 0x1c, 0xfc, 0xf7, 0x30, 0xfa, 0xe1, 0x1d, 0x4d, 0x31, 0x2b, 0x1c, 
+0x20, 0x4a, 0x01, 0x20, 0xfc, 0xf7, 0x29, 0xfa, 0xe0, 0x1d, 0x5d, 0x30, 
+0x01, 0x68, 0x00, 0x29, 0xfc, 0xd0, 0x60, 0x6d, 0xc0, 0x46, 0x38, 0x65, 
+0x20, 0x6e, 0xc0, 0x46, 0x78, 0x65, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 
+0x80, 0x00, 0x08, 0x00, 0x8c, 0xb9, 0x20, 0x40, 0x81, 0x81, 0x48, 0xbd, 
+0x79, 0x56, 0x23, 0x8c, 0x93, 0x0c, 0x82, 0x95, 0x1d, 0x0e, 0x12, 0xcf, 
+0x9b, 0x3b, 0xc0, 0xe9, 0xe6, 0x55, 0x7c, 0x82, 0x99, 0xf6, 0x78, 0x02, 
+0xd1, 0xd7, 0x25, 0x73, 0x72, 0x8c, 0x33, 0x10, 0xf7, 0x03, 0xf1, 0x42, 
+0x6c, 0x9b, 0x4a, 0xa7, 0x82, 0x8e, 0x23, 0xa9, 0x90, 0xb1, 0x82, 0x8e, 
+0xdc, 0x3f, 0xfb, 0x29, 0x00, 0x62, 0x22, 0x45, 0x88, 0x2b, 0xf1, 0x85, 
+0x12, 0x61, 0xd1, 0x73, 0x6e, 0xb1, 0x11, 0x16, 0x08, 0x83, 0x20, 0x40, 
+0x75, 0x08, 0xff, 0xff, 0x54, 0x00, 0x03, 0x00, 0x08, 0x00, 0x02, 0x00, 
+0x14, 0x00, 0x03, 0x00, 0x80, 0xb5, 0x0f, 0x1c, 0x39, 0x1c, 0x00, 0xf0, 
+0x33, 0xf8, 0x38, 0x1c, 0xff, 0xf7, 0x4c, 0xff, 0x03, 0x48, 0x01, 0x89, 
+0x01, 0x31, 0x01, 0x81, 0x80, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 
+0x0c, 0x2b, 0x00, 0x80, 0x90, 0xb5, 0x04, 0x1c, 
+0x0f, 0x1c, 0x20, 0x1c, 0x39, 0x1c, 0x00, 0xf0, 0x1f, 0xf8, 0xe0, 0x68, 
+0x01, 0x0e, 0xff, 0x22, 0x12, 0x04, 0x02, 0x40, 0x12, 0x0a, 0x11, 0x43, 
+0xff, 0x22, 0x12, 0x02, 0x02, 0x40, 0x12, 0x02, 0x11, 0x43, 0x00, 0x06, 
+0x08, 0x43, 0x38, 0x65, 0x20, 0x69, 0xc0, 0x46, 0x78, 0x65, 0x60, 0x69, 
+0xc0, 0x46, 0xb8, 0x65, 0x03, 0x48, 0x01, 0x89, 0x01, 0x31, 0x01, 0x81, 
+0x90, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0x0c, 0x2b, 0x00, 0x80, 
+0x90, 0xb5, 0x00, 0x22, 0x93, 0x00, 0x1f, 0x18, 0xbf, 0x69, 0x5b, 0x18, 
+0x5f, 0x62, 0x01, 0x32, 0x05, 0x2a, 0xf7, 0xd3, 0x07, 0x7a, 0xfb, 0x08, 
+0x03, 0xd3, 0x00, 0x23, 0x92, 0x00, 0x52, 0x18, 0x13, 0x62, 0x07, 0x6b, 
 0xc0, 0x46, 0x8f, 0x63, 0xc7, 0x6a, 0xc0, 0x46, 0xcf, 0x63, 0x87, 0x6b, 
 0xc0, 0x46, 0x0f, 0x64, 0x47, 0x6b, 0xc0, 0x46, 0x4f, 0x64, 0x07, 0x6c, 
 0xc0, 0x46, 0x8f, 0x64, 0xc2, 0x6b, 0xc0, 0x46, 0xca, 0x64, 0xc2, 0x88, 
@@ -3740,7 +3406,7 @@
 0x00, 0x22, 0x00, 0x7a, 0x43, 0x08, 0x10, 0xd3, 0xc0, 0x08, 0x02, 0xd3, 
 0x88, 0x20, 0x10, 0x43, 0x01, 0xe0, 0x80, 0x20, 0x10, 0x43, 0x3a, 0x0a, 
 0x12, 0x02, 0x01, 0x23, 0x1a, 0x43, 0xc8, 0x60, 0x8a, 0x60, 0x08, 0x1c, 
-0xff, 0xf7, 0x0e, 0xfe, 0x05, 0xe0, 0x38, 0x0a, 0x00, 0x02, 0x03, 0x23, 
+0xff, 0xf7, 0x78, 0xfd, 0x05, 0xe0, 0x38, 0x0a, 0x00, 0x02, 0x03, 0x23, 
 0x18, 0x43, 0x88, 0x60, 0xca, 0x60, 0x03, 0x48, 0x01, 0x89, 0x01, 0x31, 
 0x01, 0x81, 0x90, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x0c, 0x2b, 0x00, 0x80, 
 0xf0, 0xb4, 0x02, 0x6d, 0x14, 0x4c, 0x15, 0x1c, 0xe7, 0x69, 0xbd, 0x40, 
@@ -3754,458 +3420,283 @@
 0x80, 0xb4, 0x00, 0x22, 0x00, 0x23, 0x00, 0x29, 0x05, 0xd9, 0x07, 0x78, 
 0x7a, 0x40, 0x01, 0x30, 0x01, 0x33, 0x8b, 0x42, 0xf9, 0xd3, 0xd0, 0x43, 
 0x00, 0x06, 0x00, 0x0e, 0x80, 0xbc, 0x70, 0x47, 0xf0, 0xb5, 0x07, 0x1c, 
-0x00, 0x24, 0xff, 0x26, 0x09, 0x36, 0x20, 0x1c, 0x00, 0xf0, 0x8c, 0xf8, 
-0x00, 0xf0, 0x9e, 0xf9, 0x05, 0x1c, 0x00, 0xf0, 0xad, 0xfa, 0x3d, 0x70, 
+0x00, 0x24, 0xff, 0x26, 0x09, 0x36, 0x20, 0x1c, 0x00, 0xf0, 0x9a, 0xf8, 
+0x00, 0xf0, 0xb8, 0xf9, 0x05, 0x1c, 0x00, 0xf0, 0xc7, 0xfa, 0x3d, 0x70, 
 0x28, 0x1c, 0x01, 0x37, 0x01, 0x34, 0xb4, 0x42, 0xf1, 0xd3, 0xf0, 0xbc, 
-0x08, 0xbc, 0x18, 0x47, 0x80, 0xb5, 0x00, 0xf0, 0x85, 0xf8, 0x00, 0xf0, 
-0x8d, 0xf9, 0x07, 0x1c, 0x00, 0xf0, 0x9c, 0xfa, 0x38, 0x0a, 0xf6, 0xd3, 
-0x80, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0xf3, 0xb5, 0x81, 0xb0, 0x41, 0x02, 
-0x53, 0x20, 0x00, 0xf0, 0x57, 0xf8, 0x00, 0xf0, 0x8f, 0xfa, 0xff, 0xf7, 
-0xe9, 0xff, 0x00, 0x24, 0x00, 0x26, 0x00, 0x25, 0x00, 0x27, 0x30, 0x1c, 
-0x01, 0x36, 0x00, 0xf0, 0x5f, 0xf8, 0x00, 0xf0, 0x71, 0xf9, 0x00, 0x90, 
-0x00, 0xf0, 0x80, 0xfa, 0xf8, 0x00, 0x00, 0x99, 0x81, 0x40, 0x0d, 0x43, 
-0x01, 0x34, 0x01, 0x37, 0x04, 0x2f, 0xee, 0xd3, 0x02, 0x99, 0x20, 0xc1, 
-0x02, 0x91, 0xff, 0x23, 0x09, 0x33, 0x9c, 0x42, 0xe5, 0xd3, 0x03, 0xb0, 
-0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0xf0, 0xb5, 0x04, 0x1c, 0x0f, 0x1c, 
-0x16, 0x48, 0xc0, 0x6f, 0x40, 0x23, 0x01, 0x68, 0x19, 0x43, 0x01, 0x60, 
-0x00, 0x26, 0x20, 0xcf, 0xb1, 0x00, 0x84, 0x20, 0x00, 0xf0, 0x24, 0xf8, 
-0x28, 0x1c, 0x00, 0xf0, 0xd3, 0xf9, 0x28, 0x0a, 0x00, 0xf0, 0xd0, 0xf9, 
-0x28, 0x0c, 0x00, 0xf0, 0xcd, 0xf9, 0x28, 0x0e, 0x00, 0xf0, 0xca, 0xf9, 
-0x00, 0xf0, 0x50, 0xfa, 0x01, 0x36, 0x42, 0x2e, 0xe9, 0xd3, 0x61, 0x02, 
-0x83, 0x20, 0x00, 0xf0, 0x0f, 0xf8, 0x00, 0xf0, 
-0x47, 0xfa, 0xff, 0xf7, 0xa1, 0xff, 0x04, 0x48, 0xc0, 0x6f, 0x40, 0x23, 
-0x01, 0x68, 0x99, 0x43, 0x01, 0x60, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 
-0x68, 0x0e, 0x00, 0x80, 0x90, 0xb5, 0x04, 0x1c, 0x0f, 0x1c, 0x00, 0xf0, 
-0x4d, 0xfa, 0x20, 0x1c, 0x00, 0xf0, 0xaa, 0xf9, 0x38, 0x0c, 0x00, 0xf0, 
-0xa7, 0xf9, 0x38, 0x0a, 0x00, 0xf0, 0xa4, 0xf9, 0x38, 0x1c, 0x00, 0xf0, 
-0xa1, 0xf9, 0x90, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0xb5, 0x01, 0x1c, 
-0x54, 0x20, 0xff, 0xf7, 0xe7, 0xff, 0x00, 0x20, 0x00, 0xf0, 0x96, 0xf9, 
-0x08, 0xbc, 0x18, 0x47, 0x00, 0xb5, 0x00, 0xf0, 0x31, 0xfa, 0x57, 0x20, 
-0x00, 0xf0, 0x8e, 0xf9, 0x08, 0xbc, 0x18, 0x47, 0x90, 0xb5, 0x08, 0x4f, 
-0xfa, 0x6f, 0x20, 0x23, 0x14, 0x68, 0x9c, 0x43, 0x14, 0x60, 0x23, 0x1c, 
-0xff, 0xf7, 0x73, 0xff, 0xf8, 0x6f, 0x20, 0x23, 0x01, 0x68, 0x19, 0x43, 
-0x01, 0x60, 0x90, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x68, 0x0e, 0x00, 0x80, 
+0x08, 0xbc, 0x18, 0x47, 0x80, 0xb5, 0x00, 0xf0, 0x93, 0xf8, 0x00, 0xf0, 
+0xa7, 0xf9, 0x07, 0x1c, 0x00, 0xf0, 0xb6, 0xfa, 0x38, 0x0a, 0xf6, 0xd3, 
+0x80, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0xf3, 0xb5, 0x82, 0xb0, 0x02, 0x98, 
+0x41, 0x02, 0x53, 0x20, 0x00, 0xf0, 0x64, 0xf8, 0x00, 0xf0, 0xa8, 0xfa, 
+0xff, 0xf7, 0xe8, 0xff, 0x00, 0x24, 0x00, 0x20, 0x01, 0x90, 0x2e, 0x20, 
+0x00, 0x90, 0x00, 0x25, 0x00, 0x27, 0x02, 0x98, 0x01, 0x28, 0x04, 0xd1, 
+0x00, 0x98, 0x84, 0x42, 0x01, 0xd3, 0x00, 0x26, 
+0x09, 0xe0, 0x01, 0x98, 0x41, 0x1c, 0x01, 0x91, 0x00, 0xf0, 0x60, 0xf8, 
+0x00, 0xf0, 0x7e, 0xf9, 0x06, 0x1c, 0x00, 0xf0, 0x8d, 0xfa, 0xf8, 0x00, 
+0x86, 0x40, 0x35, 0x43, 0x01, 0x34, 0x01, 0x37, 0x04, 0x2f, 0xe6, 0xd3, 
+0x03, 0x99, 0x20, 0xc1, 0x03, 0x91, 0xff, 0x23, 0x09, 0x33, 0x9c, 0x42, 
+0xdd, 0xd3, 0x04, 0xb0, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0xf0, 0xb5, 
+0x04, 0x1c, 0x0f, 0x1c, 0x01, 0x2c, 0x2a, 0xd0, 0x16, 0x48, 0xc0, 0x6f, 
+0x40, 0x23, 0x01, 0x68, 0x19, 0x43, 0x01, 0x60, 0x00, 0x26, 0x20, 0xcf, 
+0xb1, 0x00, 0x84, 0x20, 0x00, 0xf0, 0x24, 0xf8, 0x28, 0x1c, 0x00, 0xf0, 
+0xdf, 0xf9, 0x28, 0x0a, 0x00, 0xf0, 0xdc, 0xf9, 0x28, 0x0c, 0x00, 0xf0, 
+0xd9, 0xf9, 0x28, 0x0e, 0x00, 0xf0, 0xd6, 0xf9, 0x00, 0xf0, 0x5c, 0xfa, 
+0x01, 0x36, 0x42, 0x2e, 0xe9, 0xd3, 0x61, 0x02, 0x83, 0x20, 0x00, 0xf0, 
+0x0f, 0xf8, 0x00, 0xf0, 0x53, 0xfa, 0xff, 0xf7, 0x93, 0xff, 0x04, 0x48, 
+0xc0, 0x6f, 0x40, 0x23, 0x01, 0x68, 0x99, 0x43, 0x01, 0x60, 0xf0, 0xbc, 
+0x08, 0xbc, 0x18, 0x47, 0x68, 0x0e, 0x00, 0x80, 0x90, 0xb5, 0x04, 0x1c, 
+0x0f, 0x1c, 0x00, 0xf0, 0x59, 0xfa, 0x20, 0x1c, 0x00, 0xf0, 0xb6, 0xf9, 
+0x38, 0x0c, 0x00, 0xf0, 0xb3, 0xf9, 0x38, 0x0a, 0x00, 0xf0, 0xb0, 0xf9, 
+0x38, 0x1c, 0x00, 0xf0, 0xad, 0xf9, 0x90, 0xbc, 0x08, 0xbc, 0x18, 0x47, 
+0x00, 0xb5, 0x01, 0x1c, 0x54, 0x20, 0xff, 0xf7, 0xe7, 0xff, 0x00, 0x20, 
+0x00, 0xf0, 0xa2, 0xf9, 0x08, 0xbc, 0x18, 0x47, 0x00, 0xb5, 0x00, 0xf0, 
+0x3d, 0xfa, 0x57, 0x20, 0x00, 0xf0, 0x9a, 0xf9, 0x08, 0xbc, 0x18, 0x47, 
 0x90, 0xb5, 0x08, 0x4f, 0xfa, 0x6f, 0x20, 0x23, 0x14, 0x68, 0x9c, 0x43, 
-0x14, 0x60, 0x23, 0x1c, 0xff, 0xf7, 0x89, 0xff, 0xf8, 0x6f, 0x20, 0x23, 
+0x14, 0x60, 0x23, 0x1c, 0xff, 0xf7, 0x65, 0xff, 0xf8, 0x6f, 0x20, 0x23, 
 0x01, 0x68, 0x19, 0x43, 0x01, 0x60, 0x90, 0xbc, 0x08, 0xbc, 0x18, 0x47, 
-0x68, 0x0e, 0x00, 0x80, 0xb0, 0xb5, 0x0f, 0x1c, 0x15, 0x4d, 0xe9, 0x6f, 
-0x20, 0x23, 0x0a, 0x68, 0x9a, 0x43, 0x0a, 0x60, 0x41, 0x02, 0x53, 0x20, 
-0xff, 0xf7, 0xa6, 0xff, 0x00, 0xf0, 0xde, 0xf9, 0xff, 0xf7, 0x38, 0xff, 
-0xf8, 0x1d, 0x05, 0x30, 0x44, 0x1c, 0xff, 0xf7, 0xb1, 0xff, 0x00, 0xf0, 
-0xc3, 0xf8, 0x07, 0x1c, 0x00, 0xf0, 0xd2, 0xf9, 0x20, 0x1c, 0xff, 0xf7, 
-0xa9, 0xff, 0x00, 0xf0, 0xbb, 0xf8, 0x04, 0x1c, 0x00, 0xf0, 0xca, 0xf9, 
-0xe8, 0x6f, 0x20, 0x23, 0x01, 0x68, 0x19, 0x43, 0x01, 0x60, 0x21, 0x02, 
-0x39, 0x43, 0x08, 0x1c, 0xb0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 
-0x68, 0x0e, 0x00, 0x80, 0xf0, 0xb5, 0xc2, 0xb0, 0x04, 0x1c, 0x0d, 0x1c, 
-0x17, 0x1c, 0x61, 0x02, 0x19, 0x4e, 0xf0, 0x6f, 0x20, 0x23, 0x02, 0x68, 
-0x9a, 0x43, 0x02, 0x60, 0x53, 0x20, 0xff, 0xf7, 0x73, 0xff, 0x00, 0xf0, 
-0xab, 0xf9, 0xff, 0xf7, 0x05, 0xff, 0x68, 0x46, 0xff, 0xf7, 0xec, 0xfe, 
-0x6a, 0x46, 0xe8, 0x1d, 0x05, 0x30, 0x17, 0x54, 0x39, 0x0a, 0x68, 0x44, 
-0x41, 0x70, 0x68, 0x46, 0x00, 0x99, 0x0c, 0x30, 0xff, 0xf7, 0xd0, 0xfe, 
-0x02, 0xab, 0x18, 0x70, 0x00, 0x20, 0x58, 0x70, 0x68, 0x46, 0x0c, 0x21, 
-0xff, 0xf7, 0xc8, 0xfe, 0x02, 0xab, 0x58, 0x70, 0x69, 0x46, 0x20, 0x1c, 
-0xff, 0xf7, 0x1f, 0xff, 0xf0, 0x6f, 0x20, 0x23, 0x01, 0x68, 0x19, 0x43, 
+0x68, 0x0e, 0x00, 0x80, 0x90, 0xb5, 0x08, 0x4f, 0xfa, 0x6f, 0x20, 0x23, 
+0x14, 0x68, 0x9c, 0x43, 0x14, 0x60, 0x23, 0x1c, 0xff, 0xf7, 0x87, 0xff, 
+0xf8, 0x6f, 0x20, 0x23, 0x01, 0x68, 0x19, 0x43, 0x01, 0x60, 0x90, 0xbc, 
+0x08, 0xbc, 0x18, 0x47, 0x68, 0x0e, 0x00, 0x80, 0xf0, 0xb5, 0x04, 0x1c, 
+0x0f, 0x1c, 0x18, 0x4e, 0xf0, 0x6f, 0x20, 0x23, 0x01, 0x68, 0x99, 0x43, 
+0x01, 0x60, 0x61, 0x02, 0x53, 0x20, 0xff, 0xf7, 0xa5, 0xff, 0x00, 0xf0, 
+0xe9, 0xf9, 0xff, 0xf7, 0x29, 0xff, 0xf8, 0x1d, 0x05, 0x30, 0x01, 0x2c, 
+0x03, 0xd1, 0x22, 0x2f, 0x01, 0xd3, 0x00, 0x27, 0x0f, 0xe0, 0x44, 0x1c, 
+0xff, 0xf7, 0xaa, 0xff, 0x00, 0xf0, 0xc8, 0xf8, 0x07, 0x1c, 0x00, 0xf0, 
+0xd7, 0xf9, 0x20, 0x1c, 0xff, 0xf7, 0xa2, 0xff, 0x00, 0xf0, 0xc0, 0xf8, 
+0x05, 0x1c, 0x00, 0xf0, 0xcf, 0xf9, 0xf0, 0x6f, 0x20, 0x23, 0x01, 0x68, 
+0x19, 0x43, 0x01, 0x60, 0x28, 0x02, 0x38, 0x43, 0xf0, 0xbc, 0x08, 0xbc, 
+0x18, 0x47, 0x00, 0x00, 0x68, 0x0e, 0x00, 0x80, 0xf0, 0xb5, 0xc2, 0xb0, 
+0x14, 0x1c, 0x0d, 0x1c, 0x07, 0x1c, 0x01, 0x2f, 0x2f, 0xd0, 0x79, 0x02, 
+0x19, 0x4e, 0xf0, 0x6f, 0x20, 0x23, 0x02, 0x68, 0x9a, 0x43, 0x02, 0x60, 
+0x53, 0x20, 0xff, 0xf7, 0x6b, 0xff, 0x00, 0xf0, 0xaf, 0xf9, 0xff, 0xf7, 
+0xef, 0xfe, 0x68, 0x46, 0xff, 0xf7, 0xd6, 0xfe, 0x6a, 0x46, 0xe8, 0x1d, 
+0x05, 0x30, 0x14, 0x54, 0x21, 0x0a, 0x68, 0x44, 0x41, 0x70, 0x68, 0x46, 
+0x00, 0x99, 0x0c, 0x30, 0xff, 0xf7, 0xba, 0xfe, 0x02, 0xab, 0x18, 0x70, 
+0x00, 0x20, 0x58, 0x70, 0x68, 0x46, 0x0c, 0x21, 
+0xff, 0xf7, 0xb2, 0xfe, 0x02, 0xab, 0x58, 0x70, 0x69, 0x46, 0x38, 0x1c, 
+0xff, 0xf7, 0x15, 0xff, 0xf0, 0x6f, 0x20, 0x23, 0x01, 0x68, 0x19, 0x43, 
 0x01, 0x60, 0x42, 0xb0, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 
-0x68, 0x0e, 0x00, 0x80, 0xff, 0xb5, 0xc2, 0xb0, 0x07, 0x1c, 0x6b, 0x46, 
-0x00, 0x20, 0xc4, 0x43, 0x10, 0xc3, 0x01, 0x30, 0x42, 0x28, 0xfb, 0xd3, 
-0x68, 0x46, 0x0c, 0x30, 0x03, 0x1c, 0x00, 0x24, 0x00, 0x2a, 0x0a, 0xd9, 
-0x0e, 0x88, 0xc0, 0x46, 0x06, 0x70, 0x0e, 0x88, 0x36, 0x12, 0x46, 0x70, 
-0x02, 0x30, 0x02, 0x31, 0x02, 0x34, 0x94, 0x42, 0xf4, 0xd3, 0x00, 0x92, 
-0x18, 0x1c, 0x11, 0x1c, 0xff, 0xf7, 0x96, 0xfe, 0x04, 0x1c, 0x00, 0x20, 
-0x01, 0x90, 0x02, 0xab, 0x1c, 0x70, 0x58, 0x70, 0x9d, 0x70, 0x68, 0x46, 
-0x0c, 0x21, 0xff, 0xf7, 0x8b, 0xfe, 0x02, 0xab, 0x58, 0x70, 0x45, 0x9b, 
-0x1d, 0x06, 0x2d, 0x0e, 0xac, 0x42, 0x03, 0xd1, 0x69, 0x46, 0x38, 0x1c, 
-0xff, 0xf7, 0x4a, 0xff, 0x01, 0x20, 0xac, 0x42, 
-0x00, 0xd1, 0x00, 0x20, 0x46, 0xb0, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 
-0xb0, 0xb5, 0xc2, 0xb0, 0x0f, 0x1c, 0x41, 0x02, 0x14, 0x4c, 0xe0, 0x6f, 
-0x20, 0x23, 0x02, 0x68, 0x9a, 0x43, 0x02, 0x60, 0x53, 0x20, 0xff, 0xf7, 
-0xfb, 0xfe, 0x00, 0xf0, 0x33, 0xf9, 0xff, 0xf7, 0x8d, 0xfe, 0x68, 0x46, 
-0xff, 0xf7, 0x74, 0xfe, 0xe0, 0x6f, 0x20, 0x23, 0x01, 0x68, 0x19, 0x43, 
-0x02, 0xad, 0x01, 0x60, 0x6d, 0x78, 0x00, 0x24, 0x02, 0xab, 0x5c, 0x70, 
-0x68, 0x46, 0x0c, 0x21, 0xff, 0xf7, 0x56, 0xfe, 0xa8, 0x42, 0x02, 0xd1, 
-0x00, 0x98, 0x87, 0x42, 0x01, 0xd3, 0x20, 0x1c, 0x00, 0xe0, 0x01, 0x20, 
-0x42, 0xb0, 0xb0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x68, 0x0e, 0x00, 0x80, 
-0xfc, 0x46, 0x60, 0x47, 0x00, 0x00, 0xa0, 0xe3, 0xb4, 0x22, 0x9f, 0xe5, 
-0xb4, 0x32, 0x9f, 0xe5, 0x01, 0x10, 0xa0, 0xe3, 0x00, 0x10, 0x82, 0xe5, 
+0x68, 0x0e, 0x00, 0x80, 0xff, 0xb5, 0xc2, 0xb0, 0x07, 0x1c, 0x01, 0x2f, 
+0x01, 0xd1, 0x01, 0x20, 0x36, 0xe0, 0x6b, 0x46, 0x00, 0x20, 0xc4, 0x43, 
+0x10, 0xc3, 0x01, 0x30, 0x42, 0x28, 0xfb, 0xd3, 0x68, 0x46, 0x0c, 0x30, 
+0x03, 0x1c, 0x00, 0x24, 0x00, 0x2a, 0x0a, 0xd9, 0x0e, 0x88, 0xc0, 0x46, 
+0x06, 0x70, 0x0e, 0x88, 0x36, 0x12, 0x46, 0x70, 0x02, 0x30, 0x02, 0x31, 
+0x02, 0x34, 0x94, 0x42, 0xf4, 0xd3, 0x00, 0x92, 0x18, 0x1c, 0x11, 0x1c, 
+0xff, 0xf7, 0x7c, 0xfe, 0x04, 0x1c, 0x00, 0x20, 0x01, 0x90, 0x02, 0xab, 
+0x1c, 0x70, 0x58, 0x70, 0x9d, 0x70, 0x68, 0x46, 0x0c, 0x21, 0xff, 0xf7, 
+0x71, 0xfe, 0x02, 0xab, 0x58, 0x70, 0x45, 0x9b, 0x1d, 0x06, 0x2d, 0x0e, 
+0xac, 0x42, 0x03, 0xd1, 0x69, 0x46, 0x38, 0x1c, 0xff, 0xf7, 0x3e, 0xff, 
+0x01, 0x20, 0xac, 0x42, 0x00, 0xd1, 0x00, 0x20, 0x46, 0xb0, 0xf0, 0xbc, 
+0x08, 0xbc, 0x18, 0x47, 0xb0, 0xb5, 0xc2, 0xb0, 0x0f, 0x1c, 0x41, 0x02, 
+0x14, 0x4c, 0xe0, 0x6f, 0x20, 0x23, 0x02, 0x68, 0x9a, 0x43, 0x02, 0x60, 
+0x53, 0x20, 0xff, 0xf7, 0xef, 0xfe, 0x00, 0xf0, 0x33, 0xf9, 0xff, 0xf7, 
+0x73, 0xfe, 0x68, 0x46, 0xff, 0xf7, 0x5a, 0xfe, 0xe0, 0x6f, 0x20, 0x23, 
+0x01, 0x68, 0x19, 0x43, 0x02, 0xad, 0x01, 0x60, 0x6d, 0x78, 0x00, 0x24, 
+0x02, 0xab, 0x5c, 0x70, 0x68, 0x46, 0x0c, 0x21, 0xff, 0xf7, 0x3c, 0xfe, 
+0xa8, 0x42, 0x02, 0xd1, 0x00, 0x98, 0x87, 0x42, 0x01, 0xd3, 0x20, 0x1c, 
+0x00, 0xe0, 0x01, 0x20, 0x42, 0xb0, 0xb0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 
+0x68, 0x0e, 0x00, 0x80, 0xfc, 0x46, 0x60, 0x47, 0x00, 0x00, 0xa0, 0xe3, 
+0xb4, 0x22, 0x9f, 0xe5, 0xb4, 0x32, 0x9f, 0xe5, 0x01, 0x10, 0xa0, 0xe3, 
+0x00, 0x10, 0x82, 0xe5, 0x00, 0x10, 0x82, 0xe5, 0x00, 0x10, 0xa0, 0xe3, 
+0x00, 0x10, 0x82, 0xe5, 0x00, 0x10, 0x82, 0xe5, 0x00, 0x10, 0x93, 0xe5, 
+0x81, 0x03, 0x80, 0xe1, 0x01, 0x10, 0xa0, 0xe3, 0x00, 0x10, 0x82, 0xe5, 
 0x00, 0x10, 0x82, 0xe5, 0x00, 0x10, 0xa0, 0xe3, 0x00, 0x10, 0x82, 0xe5, 
-0x00, 0x10, 0x82, 0xe5, 0x00, 0x10, 0x93, 0xe5, 0x81, 0x03, 0x80, 0xe1, 
+0x00, 0x10, 0x82, 0xe5, 0x00, 0x10, 0x93, 0xe5, 0x01, 0x03, 0x80, 0xe1, 
 0x01, 0x10, 0xa0, 0xe3, 0x00, 0x10, 0x82, 0xe5, 0x00, 0x10, 0x82, 0xe5, 
 0x00, 0x10, 0xa0, 0xe3, 0x00, 0x10, 0x82, 0xe5, 0x00, 0x10, 0x82, 0xe5, 
-0x00, 0x10, 0x93, 0xe5, 0x01, 0x03, 0x80, 0xe1, 0x01, 0x10, 0xa0, 0xe3, 
+0x00, 0x10, 0x93, 0xe5, 0x81, 0x02, 0x80, 0xe1, 0x01, 0x10, 0xa0, 0xe3, 
 0x00, 0x10, 0x82, 0xe5, 0x00, 0x10, 0x82, 0xe5, 0x00, 0x10, 0xa0, 0xe3, 
 0x00, 0x10, 0x82, 0xe5, 0x00, 0x10, 0x82, 0xe5, 0x00, 0x10, 0x93, 0xe5, 
-0x81, 0x02, 0x80, 0xe1, 0x01, 0x10, 0xa0, 0xe3, 0x00, 0x10, 0x82, 0xe5, 
+0x01, 0x02, 0x80, 0xe1, 0x01, 0x10, 0xa0, 0xe3, 0x00, 0x10, 0x82, 0xe5, 
 0x00, 0x10, 0x82, 0xe5, 0x00, 0x10, 0xa0, 0xe3, 0x00, 0x10, 0x82, 0xe5, 
-0x00, 0x10, 0x82, 0xe5, 0x00, 0x10, 0x93, 0xe5, 0x01, 0x02, 0x80, 0xe1, 
+0x00, 0x10, 0x82, 0xe5, 0x00, 0x10, 0x93, 0xe5, 0x81, 0x01, 0x80, 0xe1, 
 0x01, 0x10, 0xa0, 0xe3, 0x00, 0x10, 0x82, 0xe5, 0x00, 0x10, 0x82, 0xe5, 
 0x00, 0x10, 0xa0, 0xe3, 0x00, 0x10, 0x82, 0xe5, 0x00, 0x10, 0x82, 0xe5, 
-0x00, 0x10, 0x93, 0xe5, 0x81, 0x01, 0x80, 0xe1, 0x01, 0x10, 0xa0, 0xe3, 
+0x00, 0x10, 0x93, 0xe5, 0x01, 0x01, 0x80, 0xe1, 0x01, 0x10, 0xa0, 0xe3, 
+0x00, 0x10, 0x82, 0xe5, 0x00, 0x10, 0x82, 0xe5, 0x00, 0x10, 0xa0, 0xe3, 
+0x00, 0x10, 0x82, 0xe5, 0x00, 0x10, 0x82, 0xe5, 0x00, 0x10, 0x93, 0xe5, 
+0x81, 0x00, 0x80, 0xe1, 0x01, 0x10, 0xa0, 0xe3, 
 0x00, 0x10, 0x82, 0xe5, 0x00, 0x10, 0x82, 0xe5, 0x00, 0x10, 0xa0, 0xe3, 
 0x00, 0x10, 0x82, 0xe5, 0x00, 0x10, 0x82, 0xe5, 0x00, 0x10, 0x93, 0xe5, 
-0x01, 0x01, 0x80, 0xe1, 0x01, 0x10, 0xa0, 0xe3, 0x00, 0x10, 0x82, 0xe5, 
+0x01, 0x00, 0x80, 0xe1, 0x1e, 0xff, 0x2f, 0xe1, 0xfc, 0x46, 0x60, 0x47, 
+0xa4, 0x21, 0x9f, 0xe5, 0xa8, 0x31, 0x9f, 0xe5, 0xa0, 0x13, 0xa0, 0xe1, 
+0x00, 0x10, 0x83, 0xe5, 0x01, 0x10, 0xa0, 0xe3, 0x00, 0x10, 0x82, 0xe5, 
 0x00, 0x10, 0x82, 0xe5, 0x00, 0x10, 0xa0, 0xe3, 0x00, 0x10, 0x82, 0xe5, 
-0x00, 0x10, 0x82, 0xe5, 0x00, 0x10, 0x93, 0xe5, 0x81, 0x00, 0x80, 0xe1, 
+0x00, 0x10, 0x82, 0xe5, 0x20, 0x13, 0xa0, 0xe1, 0x00, 0x10, 0x83, 0xe5, 
 0x01, 0x10, 0xa0, 0xe3, 0x00, 0x10, 0x82, 0xe5, 0x00, 0x10, 0x82, 0xe5, 
 0x00, 0x10, 0xa0, 0xe3, 0x00, 0x10, 0x82, 0xe5, 0x00, 0x10, 0x82, 0xe5, 
-0x00, 0x10, 0x93, 0xe5, 0x01, 0x00, 0x80, 0xe1, 0x1e, 0xff, 0x2f, 0xe1, 
-0xfc, 0x46, 0x60, 0x47, 0xa4, 0x21, 0x9f, 0xe5, 0xa8, 0x31, 0x9f, 0xe5, 
-0xa0, 0x13, 0xa0, 0xe1, 0x00, 0x10, 0x83, 0xe5, 0x01, 0x10, 0xa0, 0xe3, 
+0xa0, 0x12, 0xa0, 0xe1, 0x00, 0x10, 0x83, 0xe5, 0x01, 0x10, 0xa0, 0xe3, 
 0x00, 0x10, 0x82, 0xe5, 0x00, 0x10, 0x82, 0xe5, 0x00, 0x10, 0xa0, 0xe3, 
-0x00, 0x10, 0x82, 0xe5, 0x00, 0x10, 0x82, 0xe5, 0x20, 0x13, 0xa0, 0xe1, 
+0x00, 0x10, 0x82, 0xe5, 0x00, 0x10, 0x82, 0xe5, 0x20, 0x12, 0xa0, 0xe1, 
 0x00, 0x10, 0x83, 0xe5, 0x01, 0x10, 0xa0, 0xe3, 0x00, 0x10, 0x82, 0xe5, 
 0x00, 0x10, 0x82, 0xe5, 0x00, 0x10, 0xa0, 0xe3, 0x00, 0x10, 0x82, 0xe5, 
-0x00, 0x10, 0x82, 0xe5, 0xa0, 0x12, 0xa0, 0xe1, 0x00, 0x10, 0x83, 0xe5, 
+0x00, 0x10, 0x82, 0xe5, 0xa0, 0x11, 0xa0, 0xe1, 0x00, 0x10, 0x83, 0xe5, 
 0x01, 0x10, 0xa0, 0xe3, 0x00, 0x10, 0x82, 0xe5, 0x00, 0x10, 0x82, 0xe5, 
 0x00, 0x10, 0xa0, 0xe3, 0x00, 0x10, 0x82, 0xe5, 0x00, 0x10, 0x82, 0xe5, 
-0x20, 0x12, 0xa0, 0xe1, 0x00, 0x10, 0x83, 0xe5, 0x01, 0x10, 0xa0, 0xe3, 
-0x00, 0x10, 0x82, 0xe5, 0x00, 0x10, 0x82, 0xe5, 
-0x00, 0x10, 0xa0, 0xe3, 0x00, 0x10, 0x82, 0xe5, 0x00, 0x10, 0x82, 0xe5, 
-0xa0, 0x11, 0xa0, 0xe1, 0x00, 0x10, 0x83, 0xe5, 0x01, 0x10, 0xa0, 0xe3, 
+0x20, 0x11, 0xa0, 0xe1, 0x00, 0x10, 0x83, 0xe5, 0x01, 0x10, 0xa0, 0xe3, 
 0x00, 0x10, 0x82, 0xe5, 0x00, 0x10, 0x82, 0xe5, 0x00, 0x10, 0xa0, 0xe3, 
-0x00, 0x10, 0x82, 0xe5, 0x00, 0x10, 0x82, 0xe5, 0x20, 0x11, 0xa0, 0xe1, 
+0x00, 0x10, 0x82, 0xe5, 0x00, 0x10, 0x82, 0xe5, 0xa0, 0x10, 0xa0, 0xe1, 
 0x00, 0x10, 0x83, 0xe5, 0x01, 0x10, 0xa0, 0xe3, 0x00, 0x10, 0x82, 0xe5, 
 0x00, 0x10, 0x82, 0xe5, 0x00, 0x10, 0xa0, 0xe3, 0x00, 0x10, 0x82, 0xe5, 
-0x00, 0x10, 0x82, 0xe5, 0xa0, 0x10, 0xa0, 0xe1, 0x00, 0x10, 0x83, 0xe5, 
+0x00, 0x10, 0x82, 0xe5, 0x00, 0x10, 0xa0, 0xe1, 0x00, 0x10, 0x83, 0xe5, 
 0x01, 0x10, 0xa0, 0xe3, 0x00, 0x10, 0x82, 0xe5, 0x00, 0x10, 0x82, 0xe5, 
 0x00, 0x10, 0xa0, 0xe3, 0x00, 0x10, 0x82, 0xe5, 0x00, 0x10, 0x82, 0xe5, 
-0x00, 0x10, 0xa0, 0xe1, 0x00, 0x10, 0x83, 0xe5, 0x01, 0x10, 0xa0, 0xe3, 
-0x00, 0x10, 0x82, 0xe5, 0x00, 0x10, 0x82, 0xe5, 0x00, 0x10, 0xa0, 0xe3, 
-0x00, 0x10, 0x82, 0xe5, 0x00, 0x10, 0x82, 0xe5, 0x1e, 0xff, 0x2f, 0xe1, 
-0xfc, 0x46, 0x60, 0x47, 0xa0, 0x30, 0x9f, 0xe5, 0x01, 0x10, 0xa0, 0xe3, 
+0x1e, 0xff, 0x2f, 0xe1, 0xfc, 0x46, 0x60, 0x47, 0xa0, 0x30, 0x9f, 0xe5, 
+0x01, 0x10, 0xa0, 0xe3, 0x00, 0x10, 0x83, 0xe5, 0x00, 0x10, 0x83, 0xe5, 
 0x00, 0x10, 0x83, 0xe5, 0x00, 0x10, 0x83, 0xe5, 0x00, 0x10, 0x83, 0xe5, 
 0x00, 0x10, 0x83, 0xe5, 0x00, 0x10, 0x83, 0xe5, 0x00, 0x10, 0x83, 0xe5, 
-0x00, 0x10, 0x83, 0xe5, 0x00, 0x10, 0x83, 0xe5, 0x1e, 0xff, 0x2f, 0xe1, 
-0xfc, 0x46, 0x60, 0x47, 0x70, 0x30, 0x9f, 0xe5, 0x00, 0x10, 0xa0, 0xe3, 
+0x1e, 0xff, 0x2f, 0xe1, 0xfc, 0x46, 0x60, 0x47, 0x70, 0x30, 0x9f, 0xe5, 
+0x00, 0x10, 0xa0, 0xe3, 0x00, 0x10, 0x83, 0xe5, 0x00, 0x10, 0x83, 0xe5, 
 0x00, 0x10, 0x83, 0xe5, 0x00, 0x10, 0x83, 0xe5, 0x00, 0x10, 0x83, 0xe5, 
 0x00, 0x10, 0x83, 0xe5, 0x00, 0x10, 0x83, 0xe5, 0x00, 0x10, 0x83, 0xe5, 
-0x00, 0x10, 0x83, 0xe5, 0x00, 0x10, 0x83, 0xe5, 0x1e, 0xff, 0x2f, 0xe1, 
-0xfc, 0x46, 0x60, 0x47, 0x34, 0x20, 0x9f, 0xe5, 0x3c, 0x30, 0x9f, 0xe5, 
-0x00, 0x10, 0xa0, 0xe3, 0x00, 0x10, 0x82, 0xe5, 0x00, 0x10, 0x82, 0xe5, 
-0x01, 0x10, 0xa0, 0xe3, 0x00, 0x10, 0x83, 0xe5, 0x00, 0x10, 0x83, 0xe5, 
+0x1e, 0xff, 0x2f, 0xe1, 0xfc, 0x46, 0x60, 0x47, 0x34, 0x20, 0x9f, 0xe5, 
+0x3c, 0x30, 0x9f, 0xe5, 0x00, 0x10, 0xa0, 0xe3, 0x00, 0x10, 0x82, 0xe5, 
+0x00, 0x10, 0x82, 0xe5, 0x01, 0x10, 0xa0, 0xe3, 0x00, 0x10, 0x83, 0xe5, 
 0x00, 0x10, 0x83, 0xe5, 0x00, 0x10, 0x83, 0xe5, 0x00, 0x10, 0x83, 0xe5, 
 0x00, 0x10, 0x83, 0xe5, 0x00, 0x10, 0x83, 0xe5, 0x00, 0x10, 0x83, 0xe5, 
-0x1e, 0xff, 0x2f, 0xe1, 0xf8, 0x00, 0x18, 0x40, 0x04, 0x01, 0x18, 0x40, 
-0x00, 0x01, 0x18, 0x40, 0xfc, 0x00, 0x18, 0x40, 0x02, 0x1c, 0x00, 0x20, 
-0x00, 0x29, 0x07, 0xdd, 0x13, 0x78, 0xc0, 0x18, 0x00, 0x06, 0x00, 0x0e, 
-0x01, 0x32, 0x01, 0x39, 0x00, 0x29, 0xf7, 0xdc, 0x70, 0x47, 0x09, 0x4b, 
-0xc9, 0x18, 0x04, 0x29, 0x08, 0xd8, 0x8c, 0x22, 0x4a, 0x43, 0x07, 0x4b, 
-0xd2, 0x18, 0x13, 0x7a, 0x09, 0x06, 0x09, 0x0e, 0x8b, 0x42, 0x01, 0xd0, 
-0x14, 0x20, 0x70, 0x47, 0x02, 0x60, 0x00, 0x20, 0xfb, 0xe7, 0x00, 0x00, 
-0xf3, 0x0f, 0x01, 0x35, 0xb0, 0x6e, 0x21, 0x40, 0x01, 0x1c, 0x00, 0x22, 
-0x06, 0x48, 0x03, 0x7a, 0xff, 0x2b, 0x04, 0xd0, 0x8c, 0x30, 0x01, 0x32, 
-0x04, 0x2a, 0xf8, 0xd3, 0x01, 0xe0, 0x04, 0x2a, 0x00, 0xd3, 0x00, 0x20, 
-0x0a, 0x60, 0x70, 0x47, 0xb0, 0x6e, 0x21, 0x40, 0xf0, 0xb5, 0x07, 0x1c, 
-0x00, 0x24, 0x00, 0x2f, 0x21, 0xd0, 0x00, 0x26, 0xf8, 0x79, 0x00, 0x28, 
-0x1b, 0xdd, 0x30, 0x01, 0xc0, 0x19, 0xc5, 0x1d, 0x05, 0x35, 0x00, 0x7b, 
-0x00, 0x06, 0x00, 0x16, 0x00, 0xf0, 0x9e, 0xfb, 0x01, 0x1c, 0x8b, 0x68, 
-0x00, 0x2b, 0x08, 0xd0, 0x68, 0x68, 0x00, 0x28, 0x05, 0xd0, 0xca, 0x68, 
-0xa9, 0x68, 0xfa, 0xf7, 0x4e, 0xff, 0x00, 0x20, 0x68, 0x60, 0x70, 0x1c, 
-0x06, 0x06, 0x36, 0x0e, 0xf8, 0x79, 0xb0, 0x42, 0xe3, 0xdc, 0xff, 0x20, 
-0x38, 0x72, 0x20, 0x1c, 0xf0, 0xbc, 0x08, 0xbc, 
-0x18, 0x47, 0xf3, 0xb5, 0x81, 0xb0, 0x0f, 0x1c, 0x68, 0x46, 0xff, 0xf7, 
-0xbd, 0xff, 0x00, 0x28, 0x01, 0xd1, 0x0d, 0x20, 0x37, 0xe0, 0xb9, 0x88, 
-0xc0, 0x46, 0x01, 0x80, 0xf9, 0x88, 0xc0, 0x46, 0x41, 0x80, 0xb9, 0x7a, 
-0xc0, 0x46, 0x41, 0x71, 0xf9, 0x7a, 0xc0, 0x46, 0x81, 0x71, 0x8c, 0x21, 
-0x01, 0x71, 0x3d, 0x7e, 0x00, 0x21, 0x00, 0x23, 0x00, 0x2d, 0x1f, 0xdd, 
-0x1a, 0x01, 0xd2, 0x19, 0x1c, 0x32, 0x16, 0x78, 0x05, 0x2e, 0x0d, 0xdc, 
-0x0c, 0x01, 0x24, 0x18, 0x26, 0x73, 0x96, 0x68, 0xc0, 0x46, 0x66, 0x61, 
-0xd6, 0x68, 0xc0, 0x46, 0x26, 0x61, 0x00, 0x24, 0x01, 0x31, 0x09, 0x06, 
-0x09, 0x0e, 0xd4, 0x60, 0x5a, 0x1c, 0x13, 0x06, 0x1b, 0x0e, 0xab, 0x42, 
-0xe6, 0xdb, 0x00, 0x29, 0x04, 0xd0, 0xc1, 0x71, 0x00, 0x99, 0xc0, 0x46, 
-0x01, 0x72, 0x00, 0xe0, 0x00, 0x20, 0x01, 0x99, 0xc0, 0x46, 0x08, 0x60, 
-0x00, 0x20, 0x03, 0xb0, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0xf0, 0xb5, 
-0x07, 0x1c, 0x38, 0x7e, 0x00, 0x28, 0x28, 0xd0, 0x01, 0x38, 0x05, 0x06, 
-0x2d, 0x0e, 0x00, 0x26, 0xff, 0x2d, 0x21, 0xd0, 0x28, 0x01, 0xc0, 0x19, 
-0xc4, 0x1d, 0x15, 0x34, 0x00, 0x7f, 0x00, 0x06, 0x00, 0x16, 0x00, 0xf0, 
-0x2b, 0xfb, 0x01, 0x1c, 0x11, 0xd0, 0x8a, 0x68, 0x00, 0x2a, 0x0c, 0xd0, 
-0xe0, 0x68, 0x00, 0x28, 0x09, 0xd0, 0x00, 0x23, 0xcb, 0x56, 0x05, 0x2b, 
-0x05, 0xdc, 0x13, 0x1c, 0xca, 0x68, 0xa1, 0x68, 0xfa, 0xf7, 0xd5, 0xfe, 
-0xe6, 0x60, 0xff, 0x20, 0x20, 0x70, 0x68, 0x1e, 0x05, 0x06, 0x2d, 0x0e, 
-0xff, 0x2d, 0xdd, 0xd1, 0x3e, 0x76, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 
-0x13, 0x20, 0x70, 0x47, 0xf0, 0xb5, 0x82, 0xb0, 0x07, 0x1c, 0xf8, 0x1d, 
-0xd5, 0x30, 0x39, 0x1c, 0xff, 0xf7, 0x7f, 0xff, 0x00, 0x90, 0x00, 0x98, 
-0x00, 0x28, 0x3b, 0xd1, 0x38, 0x7e, 0xc0, 0x46, 0x01, 0x90, 0x00, 0x26, 
-0x01, 0x98, 0x00, 0x28, 0x2d, 0xdd, 0x30, 0x01, 0xc0, 0x19, 0xc5, 0x1d, 
-0x15, 0x35, 0x00, 0x7f, 0x00, 0x06, 0x00, 0x16, 0x00, 0xf0, 0xf0, 0xfa, 
-0x04, 0x1c, 0x20, 0x69, 0x00, 0x28, 0x17, 0xd0, 0x28, 0x78, 0x05, 0x28, 
-0x0d, 0xdd, 0xe9, 0x68, 0xaa, 0x68, 0x60, 0x68, 0x40, 0x08, 0x40, 0x00, 
-0x01, 0xf0, 0x2c, 0xf8, 0x09, 0x22, 0xe8, 0x68, 0xa9, 0x68, 0xfa, 0xf7, 
-0x8b, 0xfd, 0x00, 0x20, 0xe8, 0x60, 0x21, 0x69, 0x28, 0x1c, 0xfa, 0xf7, 
-0x90, 0xfe, 0x00, 0x06, 0x00, 0x0e, 0x00, 0x90, 0x00, 0x98, 0x00, 0x28, 
-0x0c, 0xd1, 0x70, 0x1c, 0x06, 0x06, 0x36, 0x0e, 0x01, 0x98, 0x86, 0x42, 
-0xd1, 0xdb, 0x00, 0x20, 0x38, 0x76, 0x00, 0x98, 0x02, 0xb0, 0xf0, 0xbc, 
-0x08, 0xbc, 0x18, 0x47, 0x38, 0x1c, 0xff, 0xf7, 0x82, 0xff, 0xf6, 0xe7, 
-0xc1, 0x1d, 0x79, 0x31, 0x4a, 0x6b, 0xc0, 0x46, 0xca, 0x63, 0xc1, 0x1d, 
-0xb9, 0x31, 0x0a, 0x60, 0x00, 0x22, 0x8a, 0x60, 0x04, 0x4a, 0xc0, 0x46, 
-0x4a, 0x61, 0x8a, 0x61, 0x01, 0x21, 0xd0, 0x30, 0x41, 0x70, 0x08, 0x1c, 
-0x70, 0x47, 0x00, 0x00, 0xb1, 0xc5, 0x21, 0x40, 0xf8, 0xb5, 0x07, 0x1c, 
-0x00, 0x20, 0x00, 0x90, 0xfe, 0x1d, 0xc9, 0x36, 0x30, 0x78, 0x00, 0x01, 
-0xc0, 0x19, 0xc4, 0x1d, 0x15, 0x34, 0x80, 0x6a, 0x45, 0x08, 0x6d, 0x00, 
-0x04, 0x21, 0x38, 0x1c, 0xff, 0xf7, 0xb2, 0xfe, 0x31, 0x78, 0x40, 0x18, 
-0x01, 0x06, 0x09, 0x0e, 0x00, 0x20, 0xa2, 0x68, 0x00, 0x2a, 0x0a, 0xd9, 
-0x2a, 0x78, 0x4a, 0x40, 0x2a, 0x70, 0x01, 0x30, 0x09, 0x18, 0x09, 0x06, 
-0x09, 0x0e, 0xa2, 0x68, 0x01, 0x35, 0x82, 0x42, 
-0xf4, 0xd8, 0xe0, 0x68, 0xa1, 0x68, 0x40, 0x08, 0x40, 0x00, 0xff, 0xf7, 
-0x99, 0xfe, 0x61, 0x78, 0x81, 0x42, 0x0a, 0xd0, 0x38, 0x1c, 0x00, 0xf0, 
-0x0f, 0xf8, 0xf8, 0x1d, 0x79, 0x30, 0x80, 0x6b, 0xf9, 0x1d, 0xb9, 0x31, 
-0xc8, 0x60, 0x0c, 0x20, 0x00, 0x90, 0x30, 0x78, 0x01, 0x30, 0x30, 0x70, 
-0x00, 0x98, 0xf8, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0xc2, 0x1d, 0xc9, 0x32, 
-0x11, 0x78, 0x09, 0x01, 0x09, 0x18, 0x09, 0x6a, 0xc3, 0x1d, 0x79, 0x33, 
-0xd9, 0x63, 0x13, 0x78, 0x1b, 0x01, 0x1b, 0x18, 0x5b, 0x6a, 0xcb, 0x18, 
-0xc1, 0x1d, 0xb9, 0x31, 0x0b, 0x60, 0x13, 0x78, 0x1b, 0x01, 0x1b, 0x18, 
-0x9b, 0x6a, 0xc0, 0x46, 0x8b, 0x60, 0x07, 0x4b, 0xc0, 0x46, 0x4b, 0x61, 
-0x12, 0x78, 0x00, 0x7e, 0x01, 0x32, 0x82, 0x42, 0x01, 0xdb, 0x04, 0x48, 
-0x00, 0xe0, 0x04, 0x48, 0xc0, 0x46, 0x88, 0x61, 0x00, 0x20, 0x70, 0x47, 
-0x79, 0xc6, 0x21, 0x40, 0x4d, 0xc6, 0x21, 0x40, 0xf9, 0xc6, 0x21, 0x40, 
-0xf8, 0xb5, 0x04, 0x1c, 0x00, 0x20, 0x00, 0x90, 0x25, 0x7e, 0x29, 0x01, 
-0xe0, 0x1d, 0x15, 0x30, 0xff, 0xf7, 0x4e, 0xfe, 0xa1, 0x7e, 0x81, 0x42, 
-0x0a, 0xd0, 0x20, 0x1c, 0x00, 0xf0, 0x61, 0xf8, 0xe0, 0x1d, 0x79, 0x30, 
-0x80, 0x6b, 0xe1, 0x1d, 0xb9, 0x31, 0xc8, 0x60, 0x0b, 0x20, 0x55, 0xe0, 
-0x00, 0x27, 0x00, 0x2d, 0x0f, 0xdd, 0x38, 0x01, 0x00, 0x19, 0x00, 0x7f, 
-0x00, 0x06, 0x00, 0x16, 0x00, 0xf0, 0x1c, 0xfa, 0x00, 0x28, 0x01, 0xd1, 
-0x09, 0x20, 0x47, 0xe0, 0x78, 0x1c, 0x07, 0x06, 0x3f, 0x0e, 0xaf, 0x42, 
-0xef, 0xdb, 0x00, 0x26, 0x00, 0x2d, 0x38, 0xdd, 0x30, 0x01, 0x00, 0x19, 
-0xc7, 0x1d, 0x15, 0x37, 0x00, 0x7f, 0x00, 0x06, 0x00, 0x16, 0x00, 0xf0, 
-0x07, 0xfa, 0x00, 0x23, 0xc1, 0x56, 0x05, 0x29, 0x0c, 0xdc, 0x42, 0x68, 
-0x00, 0x2a, 0x04, 0xd0, 0xc1, 0x68, 0xb8, 0x68, 0xfa, 0xf7, 0xb6, 0xfd, 
-0xf8, 0x60, 0xf8, 0x68, 0x00, 0x28, 0x1b, 0xd1, 0x0e, 0x20, 0x17, 0xe0, 
-0xc0, 0x68, 0x00, 0x28, 0x07, 0xd0, 0xfa, 0xf7, 0xa9, 0xfd, 0x00, 0x28, 
-0x05, 0xda, 0x40, 0x42, 0xb9, 0x68, 0x81, 0x42, 0x04, 0xd0, 0x05, 0x20, 
-0x0a, 0xe0, 0xb9, 0x68, 0x81, 0x42, 0xfa, 0xd8, 0x09, 0x21, 0xb8, 0x68, 
-0xfa, 0xf7, 0x7e, 0xfc, 0xf8, 0x60, 0x00, 0x28, 0x02, 0xd1, 0x06, 0x20, 
-0x00, 0x90, 0x07, 0xe0, 0x70, 0x1c, 0x06, 0x06, 0x36, 0x0e, 0xae, 0x42, 
-0xc6, 0xdb, 0x00, 0x98, 0x00, 0x28, 0x02, 0xd0, 0x20, 0x1c, 0xff, 0xf7, 
-0x92, 0xfe, 0x00, 0x98, 0xf8, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0xc2, 0x1d, 
-0x79, 0x32, 0x41, 0x69, 0xc0, 0x46, 0xd1, 0x63, 0x02, 0x7e, 0x12, 0x01, 
-0x8a, 0x18, 0xc1, 0x1d, 0xb9, 0x31, 0x0a, 0x60, 0xc2, 0x1d, 0x15, 0x32, 
-0x8a, 0x60, 0x05, 0x4a, 0xc0, 0x46, 0x4a, 0x61, 0x04, 0x4a, 0xc0, 0x46, 
-0x8a, 0x61, 0x00, 0x21, 0xd0, 0x30, 0x01, 0x70, 0x08, 0x1c, 0x70, 0x47, 
-0x51, 0xc7, 0x21, 0x40, 0xf9, 0xc6, 0x21, 0x40, 0x90, 0xb5, 0x07, 0x1c, 
-0x38, 0x68, 0x1d, 0x4b, 0x98, 0x42, 0x03, 0xd0, 0x03, 0x20, 0x90, 0xbc, 
-0x08, 0xbc, 0x18, 0x47, 0x1c, 0x21, 0x38, 0x1c, 0xff, 0xf7, 0xbc, 0xfd, 
-0xfc, 0x1d, 0x79, 0x34, 0x00, 0x28, 0x09, 0xd0, 0x38, 0x1c, 0x00, 0xf0, 
-0x2d, 0xf8, 0xf9, 0x1d, 0xb9, 0x31, 0xa0, 0x6b, 0xc0, 0x46, 0xc8, 0x60, 
-0x0a, 0x20, 0xea, 0xe7, 0x38, 0x7a, 0x1c, 0x28, 0x04, 0xd0, 0x78, 0x7a, 
-0x10, 0x28, 0x01, 0xd0, 0x04, 0x20, 0xe2, 0xe7, 0xb8, 0x7a, 0x01, 0x28, 
-0x01, 0xd0, 0x07, 0x20, 0xdd, 0xe7, 0x60, 0x6b, 
-0xf9, 0x68, 0x88, 0x42, 0x01, 0xd0, 0x05, 0x20, 0xd7, 0xe7, 0x38, 0x69, 
-0x00, 0x28, 0x04, 0xd0, 0x06, 0x4b, 0x98, 0x42, 0x01, 0xd0, 0x08, 0x20, 
-0xcf, 0xe7, 0x38, 0x7e, 0x08, 0x28, 0x01, 0xdd, 0x12, 0x20, 0xca, 0xe7, 
-0x00, 0x20, 0xc8, 0xe7, 0x73, 0x6e, 0x69, 0x70, 0x02, 0x10, 0x00, 0x03, 
-0xb8, 0xb5, 0x07, 0x1c, 0x38, 0x1c, 0xff, 0xf7, 0x2a, 0xfe, 0x00, 0x25, 
-0xf8, 0x1d, 0xc9, 0x30, 0x45, 0x70, 0xfc, 0x1d, 0xb9, 0x34, 0xe5, 0x61, 
-0x68, 0x46, 0xff, 0xf7, 0x9d, 0xfd, 0x00, 0x28, 0x01, 0xd1, 0x0d, 0x20, 
-0x0d, 0xe0, 0xf8, 0x1d, 0x79, 0x30, 0x85, 0x63, 0xc5, 0x63, 0x1b, 0x20, 
-0x20, 0x60, 0xa7, 0x60, 0x04, 0x48, 0xc0, 0x46, 0x60, 0x61, 0x04, 0x48, 
-0xc0, 0x46, 0xa0, 0x61, 0x28, 0x1c, 0xb8, 0xbc, 0x08, 0xbc, 0x18, 0x47, 
-0x6d, 0xc8, 0x21, 0x40, 0x33, 0xc8, 0x21, 0x40, 0xf0, 0xb5, 0x82, 0xb0, 
-0x07, 0x1c, 0x00, 0x20, 0xfd, 0x1d, 0x79, 0x35, 0xfc, 0x1d, 0xb9, 0x34, 
-0xe9, 0x6a, 0xc0, 0x46, 0x61, 0x60, 0x62, 0x68, 0xe9, 0x6b, 0x8a, 0x42, 
-0x03, 0xd2, 0x61, 0x60, 0x2a, 0x6b, 0x91, 0x42, 0x34, 0xd2, 0x66, 0x68, 
-0xc0, 0x46, 0x01, 0x96, 0xe9, 0x6b, 0x73, 0x1a, 0xe9, 0x6a, 0x71, 0x1a, 
-0x26, 0x68, 0x2a, 0x6b, 0x96, 0x42, 0x00, 0xd2, 0x32, 0x1c, 0x01, 0x9e, 
-0x96, 0x1b, 0xa2, 0x68, 0xc0, 0x46, 0x00, 0x92, 0x00, 0x2a, 0x09, 0xd0, 
-0x28, 0x6a, 0x6a, 0x6a, 0x41, 0x18, 0x00, 0x98, 0xc0, 0x18, 0x33, 0x1c, 
-0xfc, 0xf7, 0x68, 0xff, 0x00, 0x28, 0x1b, 0xd1, 0x61, 0x68, 0x89, 0x19, 
-0x61, 0x60, 0x22, 0x68, 0x91, 0x42, 0x0d, 0xd1, 0x61, 0x69, 0x38, 0x1c, 
-0xfa, 0xf7, 0xc5, 0xfc, 0x00, 0x06, 0x00, 0x0e, 0x0e, 0xd1, 0xa1, 0x69, 
-0x38, 0x1c, 0xfa, 0xf7, 0xbe, 0xfc, 0x00, 0x06, 0x00, 0x0e, 0x07, 0xd1, 
-0x61, 0x68, 0x2a, 0x6b, 0x91, 0x42, 0xc2, 0xd3, 0xa9, 0x6b, 0xaa, 0x6a, 
-0x89, 0x18, 0xa9, 0x63, 0x02, 0xb0, 0xf0, 0xbc, 0x08, 0xbc, 0x18, 0x47, 
-0xf0, 0xb5, 0x84, 0xb0, 0x07, 0x1c, 0x69, 0x46, 0x38, 0x1c, 0xfa, 0xf7, 
-0xc3, 0xfe, 0xfa, 0x1d, 0x09, 0x32, 0x37, 0x49, 0x00, 0x20, 0xc0, 0x43, 
-0xcc, 0x1d, 0xb9, 0x34, 0xe0, 0x60, 0xf8, 0x88, 0xcb, 0x1d, 0x89, 0x33, 
-0x18, 0x73, 0xc8, 0x1d, 0x79, 0x30, 0xbd, 0x68, 0xc0, 0x46, 0x05, 0x62, 
-0xff, 0x68, 0xc0, 0x46, 0x47, 0x62, 0x17, 0x68, 0xc0, 0x46, 0x87, 0x62, 
-0x57, 0x68, 0xc0, 0x46, 0xc7, 0x62, 0x92, 0x68, 0xc0, 0x46, 0x42, 0x63, 
-0xc2, 0x6a, 0x87, 0x6a, 0xd2, 0x19, 0x02, 0x63, 0x1a, 0x7b, 0x28, 0x4d, 
-0x01, 0x2a, 0x0d, 0xd0, 0x02, 0x2a, 0x1c, 0xd0, 0x03, 0x2a, 0x35, 0xd1, 
-0xca, 0x1d, 0xc9, 0x32, 0x52, 0x78, 0x00, 0x2a, 0x08, 0xd1, 0x10, 0x27, 
-0x80, 0x6b, 0xc0, 0x46, 0xe0, 0x60, 0x2c, 0xe0, 0x08, 0x1c, 0xff, 0xf7, 
-0x4b, 0xff, 0x22, 0xe0, 0x08, 0x1c, 0xff, 0xf7, 0xa9, 0xfd, 0x07, 0x1c, 
-0x23, 0xd1, 0xe0, 0x69, 0x00, 0x28, 0x1c, 0xd0, 0x00, 0x7a, 0x1a, 0x4b, 
-0xc0, 0x18, 0x02, 0x90, 0x17, 0xe0, 0x82, 0x6a, 0xc3, 0x6a, 0x9f, 0x18, 
-0x46, 0x6b, 0xb7, 0x42, 0x05, 0xd8, 0x00, 0x2a, 0x03, 0xd0, 0x9f, 0x07, 
-0x01, 0xd1, 0x92, 0x07, 0x01, 0xd0, 0x0f, 0x27, 0x0d, 0xe0, 0x80, 0x6b, 
-0x98, 0x42, 0x01, 0xd0, 0xe0, 0x60, 0xf8, 0xe7, 0x08, 0x1c, 0xff, 0xf7, 
-0x4f, 0xff, 0x07, 0x1c, 0x03, 0xd1, 0x00, 0xf0, 0x1f, 0xfe, 0x01, 0xe0, 
-0x10, 0x27, 0x00, 0x20, 0x28, 0x65, 0x01, 0xab, 0x5f, 0x80, 0xe0, 0x68, 
-0xc0, 0x46, 0x03, 0x90, 0x68, 0x46, 0x00, 0x21, 
-0xfa, 0xf7, 0x98, 0xfd, 0x01, 0x20, 0x04, 0xb0, 0xf0, 0xbc, 0x08, 0xbc, 
-0x18, 0x47, 0x00, 0x00, 0x3c, 0xac, 0x20, 0x40, 0x00, 0x00, 0x00, 0x80, 
-0x0d, 0xf0, 0xfe, 0xca, 0x80, 0xb5, 0x85, 0xb0, 0x07, 0x1c, 0x38, 0x1c, 
-0x01, 0xa9, 0xfa, 0xf7, 0x45, 0xfe, 0x68, 0x46, 0xb9, 0x68, 0xff, 0xf7, 
-0x94, 0xfc, 0x00, 0x28, 0x02, 0xd1, 0x00, 0x98, 0xff, 0xf7, 0xb8, 0xfc, 
-0x02, 0xab, 0x58, 0x80, 0x00, 0x21, 0x01, 0xa8, 0xfa, 0xf7, 0x76, 0xfd, 
-0x01, 0x20, 0x05, 0xb0, 0x80, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x80, 0xb5, 
-0x85, 0xb0, 0x07, 0x1c, 0x38, 0x1c, 0x01, 0xa9, 0xfa, 0xf7, 0x2a, 0xfe, 
-0x68, 0x46, 0xb9, 0x68, 0xff, 0xf7, 0x79, 0xfc, 0x00, 0x28, 0x00, 0xd1, 
-0x02, 0x20, 0x02, 0xab, 0x58, 0x80, 0x00, 0x21, 0x01, 0xa8, 0xfa, 0xf7, 
-0x5d, 0xfd, 0x01, 0x20, 0x05, 0xb0, 0x80, 0xbc, 0x08, 0xbc, 0x18, 0x47, 
-0x90, 0xb5, 0x85, 0xb0, 0x07, 0x1c, 0x38, 0x1c, 0x01, 0xa9, 0xfa, 0xf7, 
-0x11, 0xfe, 0x3c, 0x69, 0x38, 0x1c, 0x01, 0xa9, 0xfa, 0xf7, 0x0c, 0xfe, 
-0x68, 0x46, 0x21, 0x1c, 0xff, 0xf7, 0x5b, 0xfc, 0x8c, 0x24, 0x00, 0x28, 
-0x0e, 0xd1, 0xb9, 0x68, 0x00, 0x29, 0x02, 0xd1, 0xfa, 0x68, 0x00, 0x2a, 
-0x08, 0xd0, 0xf8, 0x88, 0x23, 0x1c, 0x8c, 0x28, 0x00, 0xd8, 0x03, 0x1c, 
-0xf8, 0x68, 0x00, 0x9a, 0xfc, 0xf7, 0xd0, 0xfd, 0x02, 0xab, 0x58, 0x80, 
-0x03, 0x94, 0x00, 0x21, 0x01, 0xa8, 0xfa, 0xf7, 0x2f, 0xfd, 0x01, 0x20, 
-0x05, 0xb0, 0x90, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x21, 0x04, 0x48, 
-0xff, 0x22, 0x02, 0x72, 0x8c, 0x30, 0x01, 0x31, 0x04, 0x29, 0xfa, 0xd3, 
-0x70, 0x47, 0x00, 0x00, 0xb0, 0x6e, 0x21, 0x40, 0x02, 0x48, 0x03, 0x49, 
-0x40, 0x1a, 0x40, 0x42, 0x70, 0x47, 0x00, 0x00, 0xed, 0xd6, 0x21, 0x40, 
-0xe9, 0xd6, 0x21, 0x40, 0x00, 0x21, 0x08, 0x4a, 0x8b, 0x00, 0x5b, 0x18, 
-0x9b, 0x00, 0xd3, 0x56, 0x83, 0x42, 0x04, 0xd1, 0x88, 0x00, 0x40, 0x18, 
-0x80, 0x00, 0x80, 0x18, 0x70, 0x47, 0x01, 0x31, 0x01, 0x29, 0xf1, 0xd3, 
-0x00, 0x20, 0xf9, 0xe7, 0xe0, 0x70, 0x21, 0x40, 0x80, 0xb5, 0x00, 0xf0, 
-0x0c, 0xf8, 0x00, 0x27, 0x38, 0x1c, 0x00, 0xf0, 0x45, 0xf8, 0x78, 0x1c, 
-0x07, 0x04, 0x3f, 0x0c, 0x0c, 0x2f, 0xf7, 0xdd, 0x80, 0xbc, 0x08, 0xbc, 
-0x18, 0x47, 0x1c, 0x48, 0x02, 0x68, 0x1c, 0x49, 0x8b, 0x69, 0xd2, 0x18, 
-0x02, 0x60, 0x8a, 0x6a, 0x43, 0x68, 0x9b, 0x18, 0x43, 0x60, 0x93, 0x42, 
-0x02, 0xd2, 0x82, 0x68, 0x01, 0x32, 0x82, 0x60, 0xc2, 0x68, 0x0b, 0x6a, 
-0xd2, 0x18, 0xc2, 0x60, 0x42, 0x69, 0xcb, 0x68, 0xd2, 0x18, 0x42, 0x61, 
-0xc2, 0x69, 0x8b, 0x68, 0xd2, 0x18, 0xc2, 0x61, 0x02, 0x69, 0x0b, 0x69, 
-0xd2, 0x18, 0x02, 0x61, 0x82, 0x69, 0x0b, 0x68, 0xd2, 0x18, 0x82, 0x61, 
-0x02, 0x6b, 0xcb, 0x69, 0xd2, 0x18, 0x02, 0x63, 0x4a, 0x6a, 0x43, 0x6b, 
-0x9b, 0x18, 0x43, 0x63, 0x93, 0x42, 0x02, 0xd2, 0x82, 0x6b, 0x01, 0x32, 
-0x82, 0x63, 0xc2, 0x6b, 0x4b, 0x69, 0xd2, 0x18, 0xc2, 0x63, 0x02, 0x6c, 
-0xc9, 0x6a, 0x51, 0x18, 0x01, 0x64, 0x70, 0x47, 0xa4, 0x2a, 0x00, 0x80, 
+0x00, 0x10, 0x83, 0xe5, 0x1e, 0xff, 0x2f, 0xe1, 0xf8, 0x00, 0x18, 0x40, 
+0x04, 0x01, 0x18, 0x40, 0x00, 0x01, 0x18, 0x40, 0xfc, 0x00, 0x18, 0x40, 
+0x80, 0xb5, 0x00, 0xf0, 0x0c, 0xf8, 0x00, 0x27, 0x38, 0x1c, 0x00, 0xf0, 
+0x47, 0xf8, 0x78, 0x1c, 0x07, 0x04, 0x3f, 0x0c, 0x0c, 0x2f, 0xf7, 0xdd, 
+0x80, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x1d, 0x48, 
+0x02, 0x68, 0x1d, 0x49, 0x8b, 0x69, 0xd2, 0x18, 0x02, 0x60, 0x02, 0x66, 
+0x8a, 0x6a, 0x43, 0x68, 0x9b, 0x18, 0x43, 0x60, 0x93, 0x42, 0x02, 0xd2, 
+0x82, 0x68, 0x01, 0x32, 0x82, 0x60, 0xc2, 0x68, 0x0b, 0x6a, 0xd2, 0x18, 
+0xc2, 0x60, 0x42, 0x69, 0xcb, 0x68, 0xd2, 0x18, 0x42, 0x61, 0xc2, 0x69, 
+0x8b, 0x68, 0xd2, 0x18, 0xc2, 0x61, 0x02, 0x69, 0x0b, 0x69, 0xd2, 0x18, 
+0x02, 0x61, 0x82, 0x69, 0x0b, 0x68, 0xd2, 0x18, 0x82, 0x61, 0x02, 0x6b, 
+0xcb, 0x69, 0xd2, 0x18, 0x02, 0x63, 0x4a, 0x6a, 0x43, 0x6b, 0x9b, 0x18, 
+0x43, 0x63, 0x93, 0x42, 0x02, 0xd2, 0x82, 0x6b, 0x01, 0x32, 0x82, 0x63, 
+0xc2, 0x6b, 0x4b, 0x69, 0xd2, 0x18, 0xc2, 0x63, 0x02, 0x6c, 0xc9, 0x6a, 
+0x51, 0x18, 0x01, 0x64, 0x70, 0x47, 0x00, 0x00, 0xa4, 0x2a, 0x00, 0x80, 
 0x00, 0x08, 0x14, 0x40, 0x88, 0xb5, 0x69, 0x46, 0x00, 0xf0, 0x17, 0xf8, 
 0x81, 0x08, 0x0a, 0xd0, 0x00, 0x20, 0x00, 0x29, 0x07, 0xd9, 0x00, 0x22, 
 0x83, 0x00, 0x00, 0x9f, 0xc0, 0x46, 0xfa, 0x50, 0x01, 0x30, 0x88, 0x42, 
 0xf8, 0xd3, 0x88, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0xb5, 0x00, 0xf0, 
-0x04, 0xf8, 0x00, 0x04, 0x00, 0x0c, 0x08, 0xbc, 
-0x18, 0x47, 0x00, 0x22, 0x00, 0x28, 0x0a, 0xd0, 0x01, 0x28, 0x0a, 0xd0, 
-0x02, 0x28, 0x0c, 0xd0, 0x03, 0x28, 0x02, 0xd1, 0x07, 0x48, 0x1c, 0x22, 
-0x08, 0x60, 0x10, 0x1c, 0x70, 0x47, 0x06, 0x48, 0x04, 0xe0, 0x06, 0x48, 
-0x50, 0x22, 0x08, 0x60, 0xf7, 0xe7, 0x05, 0x48, 0x68, 0x22, 0x08, 0x60, 
-0xf3, 0xe7, 0x00, 0x00, 0x08, 0x83, 0x20, 0x40, 0xa4, 0x2a, 0x00, 0x80, 
-0x0c, 0x2b, 0x00, 0x80, 0xa0, 0x82, 0x20, 0x40, 0x98, 0xb5, 0x00, 0x27, 
-0x68, 0x46, 0xfe, 0xf7, 0x6f, 0xfb, 0x10, 0x4c, 0x00, 0x28, 0x0b, 0xd0, 
-0x00, 0xf0, 0x44, 0xf8, 0x00, 0x28, 0x07, 0xd0, 0x01, 0x27, 0x10, 0x23, 
-0x60, 0x68, 0x18, 0x43, 0x60, 0x60, 0xa0, 0x68, 0x18, 0x43, 0x0b, 0xe0, 
-0x10, 0x23, 0xe0, 0x68, 0x98, 0x43, 0xe0, 0x60, 0x60, 0x69, 0x98, 0x43, 
-0x60, 0x61, 0x60, 0x68, 0x98, 0x43, 0x60, 0x60, 0xa0, 0x68, 0x98, 0x43, 
-0xa0, 0x60, 0x38, 0x1c, 0x98, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 
-0x68, 0x19, 0x00, 0x80, 0x00, 0xb5, 0x00, 0xf0, 0xc7, 0xfc, 0x04, 0x49, 
-0x09, 0x6d, 0x08, 0x43, 0xfe, 0xf7, 0x8a, 0xfb, 0x00, 0x20, 0x08, 0xbc, 
-0x18, 0x47, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xf0, 0xb5, 0x14, 0x24, 
-0x00, 0x25, 0x00, 0x27, 0x08, 0x4e, 0x02, 0x20, 0x21, 0x1c, 0x32, 0x1c, 
-0xfa, 0xf7, 0xde, 0xfa, 0x78, 0x40, 0x07, 0x04, 0x3f, 0x0c, 0x02, 0x34, 
-0x01, 0x35, 0x03, 0x2d, 0xf3, 0xd3, 0x38, 0x1c, 0xf0, 0xbc, 0x08, 0xbc, 
-0x18, 0x47, 0x00, 0x00, 0x79, 0xbf, 0x21, 0x40, 0x01, 0x20, 0x70, 0x47, 
-0xb0, 0xb5, 0x01, 0x27, 0x3a, 0x1c, 0x18, 0x4b, 0xdb, 0x68, 0x01, 0x2b, 
-0x00, 0xd0, 0x00, 0x22, 0x12, 0x06, 0x12, 0x0e, 0x00, 0x24, 0x00, 0x2a, 
-0x23, 0xd0, 0x14, 0x4a, 0x53, 0x68, 0x1b, 0x04, 0x1b, 0x0c, 0x1d, 0x02, 
-0x1b, 0x12, 0x2b, 0x43, 0x92, 0x68, 0x12, 0x04, 0x12, 0x0c, 0x15, 0x02, 
-0x12, 0x12, 0x2a, 0x43, 0x12, 0x04, 0x12, 0x0c, 0x1b, 0x04, 0x1a, 0x43, 
-0x51, 0x40, 0x01, 0x31, 0x0f, 0xd1, 0x00, 0x28, 0x02, 0xd0, 0xff, 0xf7, 
-0xc1, 0xff, 0xc4, 0x43, 0x22, 0x04, 0x12, 0x0c, 0x07, 0x4b, 0x3a, 0x21, 
-0x02, 0x20, 0xfa, 0xf7, 0xa2, 0xfa, 0x38, 0x1c, 0xb0, 0xbc, 0x08, 0xbc, 
-0x18, 0x47, 0x20, 0x1c, 0xfa, 0xe7, 0x00, 0x00, 0x68, 0x0e, 0x00, 0x80, 
-0x40, 0x00, 0x14, 0x40, 0xd9, 0xbf, 0x21, 0x40, 0x80, 0xb4, 0x03, 0x22, 
-0xc2, 0x80, 0x15, 0x4a, 0xc0, 0x46, 0x82, 0x60, 0x14, 0x4a, 0x12, 0x88, 
-0x01, 0x32, 0xc2, 0x60, 0x00, 0x20, 0x13, 0x4a, 0x13, 0x5c, 0xc0, 0x46, 
-0x0b, 0x70, 0x01, 0x30, 0x01, 0x31, 0x08, 0x28, 0xf8, 0xd3, 0x20, 0x22, 
-0x0a, 0x70, 0x01, 0x31, 0x00, 0x20, 0x0e, 0x4b, 0x1f, 0x5c, 0xc0, 0x46, 
-0x0f, 0x70, 0x01, 0x30, 0x01, 0x31, 0x08, 0x28, 0xf8, 0xd3, 0x0a, 0x70, 
-0x01, 0x31, 0x00, 0x20, 0x09, 0x4a, 0x13, 0x5c, 0xc0, 0x46, 0x0b, 0x70, 
-0x01, 0x30, 0x01, 0x31, 0x08, 0x28, 0xf8, 0xd3, 0x00, 0x20, 0x08, 0x70, 
-0x80, 0xbc, 0x70, 0x47, 0x02, 0x10, 0x00, 0x03, 0x68, 0x0e, 0x00, 0x80, 
-0x7c, 0x04, 0x00, 0x80, 0x85, 0x04, 0x00, 0x80, 0x8e, 0x04, 0x00, 0x80, 
-0x00, 0xb5, 0x01, 0x23, 0x0a, 0x48, 0xc1, 0x1d, 0x89, 0x31, 0x4b, 0x70, 
-0x00, 0x22, 0x0a, 0x70, 0x64, 0x21, 0x80, 0x30, 0xc1, 0x82, 0x01, 0x83, 
-0x43, 0x83, 0x7d, 0x21, 0xc9, 0x00, 0x81, 0x83, 0xc2, 0x83, 0x04, 0x48, 
-0x01, 0x22, 0x00, 0x21, 0x00, 0xf0, 0x38, 0xfb, 0x08, 0xbc, 0x18, 0x47, 
-0x68, 0x0e, 0x00, 0x80, 0xa1, 0x22, 0xff, 0xff, 
-0x00, 0xb5, 0xff, 0xf7, 0xe1, 0xff, 0x13, 0x48, 0x02, 0x22, 0x00, 0x21, 
-0x00, 0xf0, 0x2a, 0xfb, 0x01, 0x23, 0xd8, 0x42, 0x0a, 0xd1, 0x10, 0x48, 
-0xc1, 0x1d, 0x39, 0x31, 0xca, 0x88, 0x01, 0x32, 0xca, 0x80, 0x81, 0x79, 
-0x01, 0x31, 0x81, 0x71, 0xfc, 0xf7, 0x5c, 0xfd, 0x0b, 0x48, 0xc0, 0x68, 
-0x01, 0x28, 0x05, 0xd1, 0x0a, 0x48, 0x7d, 0x22, 0xd2, 0x00, 0x00, 0x21, 
-0x00, 0xf0, 0x12, 0xfb, 0x08, 0x48, 0xfa, 0xf7, 0x1b, 0xfa, 0x08, 0x48, 
-0x28, 0x22, 0x00, 0x21, 0x00, 0xf0, 0x0a, 0xfb, 0x08, 0xbc, 0x18, 0x47, 
-0x65, 0x21, 0xff, 0xff, 0xa0, 0x82, 0x20, 0x40, 0x68, 0x0e, 0x00, 0x80, 
-0x95, 0x7e, 0x21, 0x40, 0x81, 0x2c, 0xff, 0xff, 0x59, 0x03, 0xff, 0xff, 
-0x00, 0xb5, 0x10, 0x20, 0x0f, 0x49, 0xc0, 0x46, 0x08, 0x60, 0x0f, 0x4a, 
-0x0f, 0x48, 0x64, 0x21, 0xfa, 0xf7, 0x00, 0xfa, 0x0e, 0x48, 0x01, 0x22, 
-0x12, 0x04, 0x01, 0x68, 0x0a, 0x40, 0x08, 0x21, 0x00, 0x2a, 0x05, 0xd1, 
-0x02, 0x68, 0x12, 0x0c, 0x07, 0xd1, 0x00, 0x68, 0x80, 0x0a, 0x04, 0xd3, 
-0x08, 0x48, 0xc0, 0x46, 0xc1, 0x60, 0x08, 0xbc, 0x18, 0x47, 0x07, 0x48, 
-0xc0, 0x46, 0x01, 0x64, 0xf9, 0xe7, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 
-0x91, 0x55, 0xff, 0xff, 0x7c, 0x29, 0x00, 0x80, 0x00, 0x00, 0x10, 0x40, 
-0x40, 0x01, 0x18, 0x00, 0x00, 0x00, 0x00, 0x80, 0xf8, 0xb5, 0x27, 0x48, 
-0x01, 0x22, 0x12, 0x04, 0x01, 0x68, 0x0a, 0x40, 0x07, 0x21, 0x00, 0x2a, 
-0x05, 0xd1, 0x02, 0x68, 0x12, 0x0c, 0x06, 0xd1, 0x00, 0x68, 0x80, 0x0a, 
-0x03, 0xd3, 0x21, 0x48, 0xc0, 0x46, 0xc1, 0x60, 0x02, 0xe0, 0x20, 0x48, 
-0xc0, 0x46, 0x01, 0x64, 0x1f, 0x48, 0xfa, 0xf7, 0xc1, 0xf9, 0x1f, 0x48, 
-0xc1, 0x6b, 0xff, 0x29, 0xfc, 0xd1, 0x81, 0x6b, 0x42, 0x6b, 0x16, 0x1c, 
-0x0f, 0x1c, 0x1c, 0x4c, 0x10, 0x23, 0x60, 0x69, 0x18, 0x43, 0x60, 0x61, 
-0xa1, 0x69, 0x99, 0x43, 0x1d, 0x04, 0xa1, 0x61, 0xe8, 0x60, 0xa0, 0x69, 
-0xc0, 0x46, 0x28, 0x61, 0x16, 0x4a, 0x17, 0x49, 0x64, 0x20, 0xfa, 0xf7, 
-0xa9, 0xf9, 0x16, 0x4a, 0xc0, 0x46, 0x00, 0x92, 0x15, 0x4b, 0x00, 0x20, 
-0x39, 0x1c, 0x32, 0x1c, 0xfa, 0xf7, 0xa8, 0xf9, 0x13, 0x48, 0xc1, 0x68, 
-0x08, 0x29, 0xfc, 0xd1, 0x12, 0x48, 0xfa, 0xf7, 0x97, 0xf9, 0x10, 0x23, 
-0x60, 0x69, 0x98, 0x43, 0x60, 0x61, 0xe8, 0x60, 0x01, 0x20, 0xe3, 0x23, 
-0x1b, 0x01, 0xe1, 0x18, 0xc8, 0x71, 0xf8, 0xbc, 0x08, 0xbc, 0x18, 0x47, 
-0x00, 0x00, 0x10, 0x40, 0x40, 0x01, 0x18, 0x00, 0x00, 0x00, 0x00, 0x80, 
-0x04, 0x02, 0xff, 0xff, 0x00, 0x01, 0x18, 0x40, 0x68, 0x0e, 0x00, 0x80, 
-0x0c, 0x55, 0xff, 0xff, 0x2d, 0xcf, 0x21, 0x40, 0x64, 0x00, 0x30, 0x02, 
-0x44, 0x80, 0x20, 0x40, 0x40, 0x01, 0x18, 0x40, 0xf4, 0x01, 0xff, 0xff, 
-0x00, 0xb5, 0xfd, 0xf7, 0xeb, 0xfa, 0x06, 0x48, 0xfa, 0xf7, 0x6c, 0xf9, 
-0xfd, 0xf7, 0xc0, 0xfa, 0xfd, 0xf7, 0xee, 0xfb, 0xfd, 0xf7, 0x00, 0xfc, 
-0xfd, 0xf7, 0x0e, 0xfc, 0x08, 0xbc, 0x18, 0x47, 0x91, 0x03, 0xff, 0xff, 
-0x90, 0xb5, 0xfd, 0xf7, 0x55, 0xf8, 0x34, 0x4f, 0x00, 0x24, 0xf9, 0x68, 
-0xf8, 0x1d, 0x79, 0x30, 0x01, 0x29, 0x0f, 0xd1, 0x31, 0x49, 0xc0, 0x46, 
-0xf9, 0x67, 0x31, 0x49, 0xc0, 0x46, 0x01, 0x60, 0x30, 0x49, 0xc0, 0x46, 
-0x0c, 0x60, 0x4c, 0x60, 0x8c, 0x60, 0xcc, 0x60, 0x0c, 0x61, 0x4c, 0x61, 
-0x8c, 0x61, 0x04, 0xe0, 0xf9, 0x1d, 0x7d, 0x31, 0xf9, 0x67, 0x12, 0xc0, 
-0x08, 0x38, 0x00, 0x68, 0x60, 0x23, 0x01, 0x68, 
-0x19, 0x43, 0x01, 0x60, 0xf8, 0x6f, 0x20, 0x23, 0x01, 0x68, 0x19, 0x43, 
-0x01, 0x60, 0xf8, 0x6f, 0x40, 0x23, 0x01, 0x68, 0x99, 0x43, 0x01, 0x60, 
-0x00, 0xf0, 0x54, 0xf8, 0xfd, 0xf7, 0x38, 0xf8, 0x00, 0xf0, 0x08, 0xf9, 
-0xfc, 0xf7, 0x5f, 0xfc, 0xff, 0xf7, 0x84, 0xfd, 0xfd, 0xf7, 0x18, 0xfa, 
-0xfd, 0xf7, 0xa0, 0xf9, 0xfd, 0xf7, 0xac, 0xfa, 0xfd, 0xf7, 0x3e, 0xf9, 
-0xfd, 0xf7, 0xf4, 0xf8, 0xfd, 0xf7, 0x7e, 0xf9, 0x00, 0xf0, 0xc4, 0xf9, 
-0xfd, 0xf7, 0x86, 0xfb, 0xfd, 0xf7, 0xf4, 0xfa, 0xfd, 0xf7, 0xbc, 0xfa, 
-0xfd, 0xf7, 0x26, 0xf8, 0xfa, 0xf7, 0x12, 0xf8, 0xff, 0xf7, 0x40, 0xfd, 
-0x00, 0x20, 0xff, 0xf7, 0x17, 0xfe, 0xff, 0xf7, 0x97, 0xff, 0x71, 0x23, 
-0x5b, 0x01, 0xf8, 0x18, 0x04, 0x72, 0x44, 0x72, 0x07, 0x23, 0x5b, 0x02, 
-0xf8, 0x18, 0x04, 0x63, 0x09, 0x48, 0xc0, 0x46, 0x44, 0x62, 0x00, 0xf0, 
-0xc3, 0xf9, 0x08, 0x48, 0xfa, 0xf7, 0xf8, 0xf8, 0x90, 0xbc, 0x08, 0xbc, 
-0x18, 0x47, 0x00, 0x00, 0x68, 0x0e, 0x00, 0x80, 0x00, 0x01, 0x11, 0x40, 
-0x04, 0x01, 0x11, 0x40, 0x00, 0x01, 0x11, 0x00, 0xc0, 0x00, 0x18, 0x00, 
-0x65, 0x9f, 0x21, 0x40, 0x00, 0xb5, 0x04, 0x48, 0xfa, 0xf7, 0xe4, 0xf8, 
-0xfd, 0xf7, 0x48, 0xfb, 0xfd, 0xf7, 0x0e, 0xf8, 0x08, 0xbc, 0x18, 0x47, 
-0x61, 0xa9, 0x21, 0x40, 0xfa, 0x21, 0x03, 0x48, 0xc0, 0x46, 0x41, 0x62, 
-0x40, 0x21, 0x41, 0x62, 0x70, 0x47, 0x00, 0x00, 0xc0, 0x00, 0x18, 0x00, 
-0x07, 0x48, 0x41, 0x69, 0x07, 0x4b, 0x19, 0x43, 0x41, 0x61, 0x82, 0x69, 
-0x9a, 0x43, 0x82, 0x61, 0x01, 0x22, 0x12, 0x05, 0xd1, 0x60, 0x80, 0x69, 
-0xc0, 0x46, 0x10, 0x61, 0x70, 0x47, 0x00, 0x00, 0x68, 0x0e, 0x00, 0x80, 
-0xfe, 0xaf, 0x9a, 0x10, 0x00, 0xb5, 0x02, 0x48, 0xfa, 0xf7, 0xba, 0xf8, 
-0x08, 0xbc, 0x18, 0x47, 0xb4, 0x57, 0xff, 0xff, 0xf0, 0xb5, 0x24, 0x4c, 
-0x01, 0x21, 0x09, 0x04, 0x20, 0x68, 0x01, 0x40, 0x09, 0x20, 0x22, 0x4e, 
-0x22, 0x4d, 0x00, 0x29, 0x05, 0xd1, 0x21, 0x68, 0x09, 0x0c, 0x04, 0xd1, 
-0x21, 0x68, 0x89, 0x0a, 0x01, 0xd3, 0xf0, 0x60, 0x00, 0xe0, 0x28, 0x64, 
-0x1d, 0x48, 0xfa, 0xf7, 0x9f, 0xf8, 0x1d, 0x4f, 0x1d, 0x49, 0x88, 0x69, 
-0x01, 0x30, 0x88, 0x61, 0x38, 0x7a, 0x00, 0x28, 0x02, 0xd1, 0x78, 0x7a, 
-0x00, 0x28, 0x1f, 0xd0, 0x19, 0x48, 0xfa, 0xf7, 0x91, 0xf8, 0x19, 0x48, 
-0xfa, 0xf7, 0x8e, 0xf8, 0x00, 0x28, 0xfa, 0xd1, 0x38, 0x7a, 0x00, 0x28, 
-0x02, 0xd0, 0x16, 0x48, 0xfa, 0xf7, 0x86, 0xf8, 0x01, 0x21, 0x09, 0x04, 
-0x20, 0x68, 0x01, 0x40, 0x14, 0x20, 0x00, 0x29, 0x05, 0xd1, 0x21, 0x68, 
-0x09, 0x0c, 0x04, 0xd1, 0x21, 0x68, 0x89, 0x0a, 0x01, 0xd3, 0xf0, 0x60, 
-0x01, 0xe0, 0x28, 0x64, 0xff, 0xe7, 0xfe, 0xe7, 0xff, 0xf7, 0xdd, 0xfc, 
-0x0b, 0x48, 0xfa, 0xf7, 0x6f, 0xf8, 0xff, 0xf7, 0xaf, 0xff, 0xcd, 0xe7, 
-0x00, 0x00, 0x10, 0x40, 0x40, 0x01, 0x18, 0x00, 0x00, 0x00, 0x00, 0x80, 
-0x04, 0x02, 0xff, 0xff, 0x88, 0x1c, 0x00, 0x80, 0x08, 0x83, 0x20, 0x40, 
-0xf4, 0x01, 0xff, 0xff, 0xb5, 0x07, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 
-0xe9, 0xaf, 0x21, 0x40, 0x00, 0xb5, 0x16, 0x49, 0x01, 0x22, 0x12, 0x04, 
+0x04, 0xf8, 0x00, 0x04, 0x00, 0x0c, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x22, 
+0x00, 0x28, 0x0a, 0xd0, 0x01, 0x28, 0x0a, 0xd0, 0x02, 0x28, 0x0c, 0xd0, 
+0x03, 0x28, 0x02, 0xd1, 0x07, 0x48, 0x1c, 0x22, 0x08, 0x60, 0x10, 0x1c, 
+0x70, 0x47, 0x06, 0x48, 0x04, 0xe0, 0x06, 0x48, 0x50, 0x22, 0x08, 0x60, 
+0xf7, 0xe7, 0x05, 0x48, 0x68, 0x22, 0x08, 0x60, 0xf3, 0xe7, 0x00, 0x00, 
+0x08, 0x83, 0x20, 0x40, 0xa4, 0x2a, 0x00, 0x80, 0x0c, 0x2b, 0x00, 0x80, 
+0xa0, 0x82, 0x20, 0x40, 0x80, 0xb4, 0x03, 0x22, 0xc2, 0x80, 0x15, 0x4a, 
+0xc0, 0x46, 0x82, 0x60, 0x14, 0x4a, 0x12, 0x88, 0x01, 0x32, 0xc2, 0x60, 
+0x00, 0x20, 0x13, 0x4a, 0x13, 0x5c, 0xc0, 0x46, 0x0b, 0x70, 0x01, 0x30, 
+0x01, 0x31, 0x08, 0x28, 0xf8, 0xd3, 0x20, 0x22, 0x0a, 0x70, 0x01, 0x31, 
+0x00, 0x20, 0x0e, 0x4b, 0x1f, 0x5c, 0xc0, 0x46, 0x0f, 0x70, 0x01, 0x30, 
+0x01, 0x31, 0x08, 0x28, 0xf8, 0xd3, 0x0a, 0x70, 0x01, 0x31, 0x00, 0x20, 
+0x09, 0x4a, 0x13, 0x5c, 0xc0, 0x46, 0x0b, 0x70, 0x01, 0x30, 0x01, 0x31, 
+0x08, 0x28, 0xf8, 0xd3, 0x00, 0x20, 0x08, 0x70, 0x80, 0xbc, 0x70, 0x47, 
+0x08, 0x10, 0x00, 0x03, 0x68, 0x0e, 0x00, 0x80, 0x7c, 0x04, 0x00, 0x80, 
+0x85, 0x04, 0x00, 0x80, 0x8e, 0x04, 0x00, 0x80, 0x00, 0xb5, 0x01, 0x23, 
+0x0a, 0x48, 0xc1, 0x1d, 0x89, 0x31, 0x4b, 0x70, 0x00, 0x22, 0x0a, 0x70, 
+0x64, 0x21, 0x80, 0x30, 0xc1, 0x82, 0x01, 0x83, 0x43, 0x83, 0x7d, 0x21, 
+0xc9, 0x00, 0x81, 0x83, 0xc2, 0x83, 0x04, 0x48, 0x01, 0x22, 0x00, 0x21, 
+0x00, 0xf0, 0x8e, 0xfb, 0x08, 0xbc, 0x18, 0x47, 0x68, 0x0e, 0x00, 0x80, 
+0xb5, 0x22, 0xff, 0xff, 0x00, 0xb5, 0xff, 0xf7, 0xe1, 0xff, 0x13, 0x48, 
+0x02, 0x22, 0x00, 0x21, 0x00, 0xf0, 0x80, 0xfb, 0x01, 0x23, 0xd8, 0x42, 
+0x0a, 0xd1, 0x10, 0x48, 0xc1, 0x1d, 0x39, 0x31, 0xca, 0x88, 0x01, 0x32, 
+0xca, 0x80, 0x81, 0x79, 0x01, 0x31, 0x81, 0x71, 0xfd, 0xf7, 0x70, 0xf9, 
+0x0b, 0x48, 0xc0, 0x68, 0x01, 0x28, 0x05, 0xd1, 0x0a, 0x48, 0x7d, 0x22, 
+0xd2, 0x00, 0x00, 0x21, 0x00, 0xf0, 0x68, 0xfb, 0x08, 0x48, 0xfb, 0xf7, 
+0xe1, 0xfc, 0x08, 0x48, 0x28, 0x22, 0x00, 0x21, 0x00, 0xf0, 0x60, 0xfb, 
+0x08, 0xbc, 0x18, 0x47, 0x79, 0x21, 0xff, 0xff, 0xa0, 0x82, 0x20, 0x40, 
+0x68, 0x0e, 0x00, 0x80, 0xa5, 0x7b, 0x21, 0x40, 
+0x95, 0x2c, 0xff, 0xff, 0x59, 0x03, 0xff, 0xff, 0x00, 0xb5, 0x10, 0x20, 
+0x0f, 0x49, 0xc0, 0x46, 0x08, 0x60, 0x0f, 0x4a, 0x0f, 0x48, 0x64, 0x21, 
+0xfb, 0xf7, 0xc6, 0xfc, 0x0e, 0x48, 0x01, 0x22, 0x12, 0x04, 0x01, 0x68, 
+0x0a, 0x40, 0x08, 0x21, 0x00, 0x2a, 0x05, 0xd1, 0x02, 0x68, 0x12, 0x0c, 
+0x07, 0xd1, 0x00, 0x68, 0x80, 0x0a, 0x04, 0xd3, 0x08, 0x48, 0xc0, 0x46, 
+0xc1, 0x60, 0x08, 0xbc, 0x18, 0x47, 0x07, 0x48, 0xc0, 0x46, 0x01, 0x64, 
+0xf9, 0xe7, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb0, 0xa5, 0x55, 0xff, 0xff, 
+0x7c, 0x29, 0x00, 0x80, 0x00, 0x00, 0x10, 0x40, 0x40, 0x01, 0x18, 0x00, 
+0x00, 0x00, 0x00, 0x80, 0xf8, 0xb5, 0x27, 0x48, 0x01, 0x22, 0x12, 0x04, 
+0x01, 0x68, 0x0a, 0x40, 0x07, 0x21, 0x00, 0x2a, 0x05, 0xd1, 0x02, 0x68, 
+0x12, 0x0c, 0x06, 0xd1, 0x00, 0x68, 0x80, 0x0a, 0x03, 0xd3, 0x21, 0x48, 
+0xc0, 0x46, 0xc1, 0x60, 0x02, 0xe0, 0x20, 0x48, 0xc0, 0x46, 0x01, 0x64, 
+0x1f, 0x48, 0xfb, 0xf7, 0x87, 0xfc, 0x1f, 0x48, 0xc1, 0x6b, 0xff, 0x29, 
+0xfc, 0xd1, 0x81, 0x6b, 0x42, 0x6b, 0x16, 0x1c, 0x0f, 0x1c, 0x1c, 0x4c, 
+0x10, 0x23, 0x60, 0x69, 0x18, 0x43, 0x60, 0x61, 0xa1, 0x69, 0x99, 0x43, 
+0x1d, 0x04, 0xa1, 0x61, 0xe8, 0x60, 0xa0, 0x69, 0xc0, 0x46, 0x28, 0x61, 
+0x16, 0x4a, 0x17, 0x49, 0x64, 0x20, 0xfb, 0xf7, 0x6f, 0xfc, 0x16, 0x4a, 
+0xc0, 0x46, 0x00, 0x92, 0x15, 0x4b, 0x00, 0x20, 0x39, 0x1c, 0x32, 0x1c, 
+0xfb, 0xf7, 0x6e, 0xfc, 0x13, 0x48, 0xc1, 0x68, 0x08, 0x29, 0xfc, 0xd1, 
+0x12, 0x48, 0xfb, 0xf7, 0x5d, 0xfc, 0x10, 0x23, 0x60, 0x69, 0x98, 0x43, 
+0x60, 0x61, 0xe8, 0x60, 0x01, 0x20, 0xe3, 0x23, 0x1b, 0x01, 0xe1, 0x18, 
+0xc8, 0x71, 0xf8, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 0x10, 0x40, 
+0x40, 0x01, 0x18, 0x00, 0x00, 0x00, 0x00, 0x80, 0x04, 0x02, 0xff, 0xff, 
+0x00, 0x01, 0x18, 0x40, 0x68, 0x0e, 0x00, 0x80, 0x20, 0x55, 0xff, 0xff, 
+0xb5, 0xb6, 0x21, 0x40, 0x64, 0x00, 0x30, 0x02, 0x44, 0x80, 0x20, 0x40, 
+0x40, 0x01, 0x18, 0x40, 0xf4, 0x01, 0xff, 0xff, 0x00, 0xb5, 0xfd, 0xf7, 
+0x01, 0xff, 0x06, 0x48, 0xfb, 0xf7, 0x32, 0xfc, 0xfd, 0xf7, 0xd6, 0xfe, 
+0xfe, 0xf7, 0x04, 0xf8, 0xfe, 0xf7, 0x16, 0xf8, 0xfe, 0xf7, 0x24, 0xf8, 
+0x08, 0xbc, 0x18, 0x47, 0x91, 0x03, 0xff, 0xff, 0x90, 0xb5, 0xfd, 0xf7, 
+0x6b, 0xfc, 0x34, 0x4f, 0x00, 0x24, 0xf9, 0x68, 0xf8, 0x1d, 0x79, 0x30, 
+0x01, 0x29, 0x0f, 0xd1, 0x31, 0x49, 0xc0, 0x46, 0xf9, 0x67, 0x31, 0x49, 
+0xc0, 0x46, 0x01, 0x60, 0x30, 0x49, 0xc0, 0x46, 0x0c, 0x60, 0x4c, 0x60, 
+0x8c, 0x60, 0xcc, 0x60, 0x0c, 0x61, 0x4c, 0x61, 0x8c, 0x61, 0x04, 0xe0, 
+0xf9, 0x1d, 0x7d, 0x31, 0xf9, 0x67, 0x12, 0xc0, 0x08, 0x38, 0x00, 0x68, 
+0x60, 0x23, 0x01, 0x68, 0x19, 0x43, 0x01, 0x60, 0xf8, 0x6f, 0x20, 0x23, 
+0x01, 0x68, 0x19, 0x43, 0x01, 0x60, 0xf8, 0x6f, 0x40, 0x23, 0x01, 0x68, 
+0x99, 0x43, 0x01, 0x60, 0x00, 0xf0, 0x54, 0xf8, 0xfd, 0xf7, 0x4e, 0xfc, 
+0x00, 0xf0, 0x5e, 0xf9, 0xfd, 0xf7, 0x73, 0xf8, 0xff, 0xf7, 0x0c, 0xfe, 
+0xfd, 0xf7, 0x2e, 0xfe, 0xfd, 0xf7, 0xb6, 0xfd, 0xfd, 0xf7, 0xc2, 0xfe, 
+0xfd, 0xf7, 0x54, 0xfd, 0xfd, 0xf7, 0x0a, 0xfd, 0xfd, 0xf7, 0x94, 0xfd, 
+0x00, 0xf0, 0x1a, 0xfa, 0xfd, 0xf7, 0x9c, 0xff, 0xfd, 0xf7, 0x0a, 0xff, 
+0xfd, 0xf7, 0xd2, 0xfe, 0xfd, 0xf7, 0x3c, 0xfc, 0xfb, 0xf7, 0xdc, 0xfa, 
+0xff, 0xf7, 0x9c, 0xff, 0x71, 0x23, 0x5b, 0x01, 
+0xf8, 0x18, 0x04, 0x72, 0x44, 0x72, 0x07, 0x23, 0x5b, 0x02, 0xf8, 0x18, 
+0x04, 0x63, 0xf8, 0x68, 0x01, 0x28, 0x02, 0xd1, 0xa8, 0x20, 0xfe, 0xf7, 
+0xb1, 0xfd, 0x09, 0x48, 0xc0, 0x46, 0x44, 0x62, 0x00, 0xf0, 0x18, 0xfa, 
+0x07, 0x48, 0xfb, 0xf7, 0xbd, 0xfb, 0x90, 0xbc, 0x08, 0xbc, 0x18, 0x47, 
+0x68, 0x0e, 0x00, 0x80, 0x00, 0x01, 0x11, 0x40, 0x04, 0x01, 0x11, 0x40, 
+0x00, 0x01, 0x11, 0x00, 0xc0, 0x00, 0x18, 0x00, 0x15, 0x8f, 0x21, 0x40, 
+0x00, 0xb5, 0x04, 0x48, 0xfb, 0xf7, 0xaa, 0xfb, 0xfd, 0xf7, 0x5e, 0xff, 
+0xfd, 0xf7, 0x24, 0xfc, 0x08, 0xbc, 0x18, 0x47, 0x15, 0x99, 0x21, 0x40, 
+0xfa, 0x21, 0x03, 0x48, 0xc0, 0x46, 0x41, 0x62, 0x40, 0x21, 0x41, 0x62, 
+0x70, 0x47, 0x00, 0x00, 0xc0, 0x00, 0x18, 0x00, 0x07, 0x48, 0x41, 0x69, 
+0x07, 0x4b, 0x19, 0x43, 0x41, 0x61, 0x82, 0x69, 0x9a, 0x43, 0x82, 0x61, 
+0x01, 0x22, 0x12, 0x05, 0xd1, 0x60, 0x80, 0x69, 0xc0, 0x46, 0x10, 0x61, 
+0x70, 0x47, 0x00, 0x00, 0x68, 0x0e, 0x00, 0x80, 0xfe, 0xaf, 0x9a, 0x10, 
+0x00, 0xb5, 0x02, 0x48, 0xfb, 0xf7, 0x80, 0xfb, 0x08, 0xbc, 0x18, 0x47, 
+0xc8, 0x57, 0xff, 0xff, 0xf0, 0xb5, 0x24, 0x4c, 0x01, 0x21, 0x09, 0x04, 
+0x20, 0x68, 0x01, 0x40, 0x09, 0x20, 0x22, 0x4e, 0x22, 0x4d, 0x00, 0x29, 
+0x05, 0xd1, 0x21, 0x68, 0x09, 0x0c, 0x04, 0xd1, 0x21, 0x68, 0x89, 0x0a, 
+0x01, 0xd3, 0xf0, 0x60, 0x00, 0xe0, 0x28, 0x64, 0x1d, 0x48, 0xfb, 0xf7, 
+0x65, 0xfb, 0x1d, 0x4f, 0x1d, 0x49, 0x88, 0x69, 0x01, 0x30, 0x88, 0x61, 
+0x38, 0x7a, 0x00, 0x28, 0x02, 0xd1, 0x78, 0x7a, 0x00, 0x28, 0x1f, 0xd0, 
+0x19, 0x48, 0xfb, 0xf7, 0x57, 0xfb, 0x19, 0x48, 0xfb, 0xf7, 0x54, 0xfb, 
+0x00, 0x28, 0xfa, 0xd1, 0x38, 0x7a, 0x00, 0x28, 0x02, 0xd0, 0x16, 0x48, 
+0xfb, 0xf7, 0x4c, 0xfb, 0x01, 0x21, 0x09, 0x04, 0x20, 0x68, 0x01, 0x40, 
+0x14, 0x20, 0x00, 0x29, 0x05, 0xd1, 0x21, 0x68, 0x09, 0x0c, 0x04, 0xd1, 
+0x21, 0x68, 0x89, 0x0a, 0x01, 0xd3, 0xf0, 0x60, 0x01, 0xe0, 0x28, 0x64, 
+0xff, 0xe7, 0xfe, 0xe7, 0xff, 0xf7, 0x65, 0xfd, 0x0b, 0x48, 0xfb, 0xf7, 
+0x35, 0xfb, 0xff, 0xf7, 0xaf, 0xff, 0xcd, 0xe7, 0x00, 0x00, 0x10, 0x40, 
+0x40, 0x01, 0x18, 0x00, 0x00, 0x00, 0x00, 0x80, 0x04, 0x02, 0xff, 0xff, 
+0x88, 0x1c, 0x00, 0x80, 0x08, 0x83, 0x20, 0x40, 0xf4, 0x01, 0xff, 0xff, 
+0xb5, 0x07, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x99, 0x9f, 0x21, 0x40, 
+0x00, 0x20, 0x07, 0x4a, 0x01, 0x21, 0x09, 0x05, 0x50, 0x61, 0xc8, 0x60, 
+0xd0, 0x61, 0xc8, 0x61, 0x03, 0x23, 0xdb, 0x04, 0x03, 0x4a, 0x01, 0x21, 
+0xd1, 0x63, 0x58, 0x60, 0xfc, 0xe7, 0x00, 0x00, 0x68, 0x0e, 0x00, 0x80, 
+0xc0, 0x00, 0x18, 0x00, 0x80, 0xb5, 0xc0, 0xb0, 0x01, 0x22, 0x00, 0x21, 
+0x0a, 0x20, 0xfc, 0xf7, 0xd1, 0xff, 0x07, 0x1c, 0xff, 0x2f, 0x28, 0xd0, 
+0x69, 0x46, 0xff, 0x22, 0x38, 0x1c, 0x01, 0x32, 0xfd, 0xf7, 0x54, 0xf9, 
+0xff, 0x23, 0x01, 0x33, 0x98, 0x42, 0x1b, 0xd1, 0x0d, 0x98, 0x00, 0x09, 
+0x18, 0xd3, 0x38, 0x1c, 0xfd, 0xf7, 0x8d, 0xf8, 0x0e, 0x49, 0x01, 0x22, 
+0x12, 0x04, 0x08, 0x68, 0x02, 0x40, 0x0d, 0x48, 0x05, 0xd1, 0x0a, 0x68, 
+0x12, 0x0c, 0x06, 0xd1, 0x09, 0x68, 0x89, 0x0a, 0x03, 0xd3, 0x0a, 0x49, 
+0xc0, 0x46, 0xc8, 0x60, 0x02, 0xe0, 0x09, 0x49, 0xc0, 0x46, 0x08, 0x64, 
+0xff, 0xf7, 0xbc, 0xff, 0x38, 0x1c, 0xfd, 0xf7, 0x74, 0xf8, 0x40, 0xb0, 
+0x80, 0xbc, 0x08, 0xbc, 0x18, 0x47, 0x00, 0x00, 
+0x00, 0x00, 0x10, 0x40, 0x07, 0x80, 0x00, 0x00, 0x40, 0x01, 0x18, 0x00, 
+0x00, 0x00, 0x00, 0x80, 0x00, 0xb5, 0x17, 0x49, 0x01, 0x22, 0x12, 0x04, 
 0x08, 0x68, 0x02, 0x40, 0x06, 0x20, 0x00, 0x2a, 0x05, 0xd1, 0x0a, 0x68, 
-0x12, 0x0c, 0x06, 0xd1, 0x09, 0x68, 0x89, 0x0a, 0x03, 0xd3, 0x10, 0x49, 
-0xc0, 0x46, 0xc8, 0x60, 0x02, 0xe0, 0x0f, 0x49, 0xc0, 0x46, 0x08, 0x64, 
-0x03, 0x20, 0xfe, 0xf7, 0x55, 0xf9, 0xfa, 0xf7, 
-0x9d, 0xfc, 0x01, 0x23, 0x18, 0x43, 0xfa, 0xf7, 0x77, 0xfd, 0xff, 0xf7, 
-0xd7, 0xfe, 0xff, 0xf7, 0x5b, 0xfe, 0xff, 0xf7, 0x4b, 0xff, 0xff, 0xf7, 
-0x5f, 0xff, 0xff, 0xf7, 0xf1, 0xfd, 0xff, 0xf7, 0x77, 0xff, 0x08, 0xbc, 
+0x12, 0x0c, 0x06, 0xd1, 0x09, 0x68, 0x89, 0x0a, 0x03, 0xd3, 0x11, 0x49, 
+0xc0, 0x46, 0xc8, 0x60, 0x02, 0xe0, 0x10, 0x49, 0xc0, 0x46, 0x08, 0x64, 
+0x03, 0x20, 0xfe, 0xf7, 0xd3, 0xfc, 0xfb, 0xf7, 0x0d, 0xff, 0x01, 0x23, 
+0x18, 0x43, 0xfb, 0xf7, 0xe7, 0xff, 0xff, 0xf7, 0x83, 0xfe, 0xff, 0xf7, 
+0x9d, 0xff, 0xff, 0xf7, 0x05, 0xfe, 0xff, 0xf7, 0xf5, 0xfe, 0xff, 0xf7, 
+0x09, 0xff, 0xff, 0xf7, 0x9b, 0xfd, 0xff, 0xf7, 0x21, 0xff, 0x08, 0xbc, 
 0x18, 0x47, 0x00, 0x00, 0x00, 0x00, 0x10, 0x40, 0x40, 0x01, 0x18, 0x00, 
 0x00, 0x00, 0x00, 0x80, 0xf0, 0xb4, 0x46, 0x4a, 0x01, 0x21, 0xc9, 0x03, 
 0x45, 0x4d, 0x19, 0x23, 0xdb, 0x01, 0xec, 0x18, 0xa1, 0x61, 0x28, 0x88, 
@@ -4231,7 +3722,7 @@
 0x00, 0x2b, 0x07, 0xd9, 0x87, 0x00, 0x4b, 0x6a, 0xc0, 0x46, 0xda, 0x51, 
 0x0b, 0x69, 0x01, 0x30, 0x83, 0x42, 0xf7, 0xd8, 0x49, 0x6a, 0x80, 0x00, 
 0x08, 0x18, 0x04, 0x38, 0x28, 0x61, 0xf0, 0xbc, 0x70, 0x47, 0x00, 0x00, 
-0xec, 0xd6, 0x21, 0x40, 0x68, 0x0e, 0x00, 0x80, 0x00, 0x00, 0x20, 0x40, 
+0xb0, 0xbe, 0x21, 0x40, 0x68, 0x0e, 0x00, 0x80, 0x00, 0x00, 0x20, 0x40, 
 0x4c, 0x2a, 0x00, 0x80, 0x00, 0x00, 0x20, 0x40, 0x00, 0xad, 0xde, 0x00, 
 0x0a, 0x48, 0x01, 0x23, 0x1b, 0x06, 0x41, 0x69, 0x99, 0x43, 0x1a, 0x09, 
 0x41, 0x61, 0xd1, 0x60, 0x00, 0x21, 0xa1, 0x22, 0x52, 0x03, 0x91, 0x61, 
@@ -4239,14 +3730,14 @@
 0x59, 0x05, 0x08, 0x60, 0x70, 0x47, 0x00, 0x00, 0x68, 0x0e, 0x00, 0x80, 
 0x80, 0xb4, 0x02, 0x1c, 0x0b, 0x48, 0x1b, 0x23, 0xdb, 0x01, 0xc3, 0x18, 
 0x9a, 0x61, 0x01, 0x23, 0x1b, 0x06, 0x42, 0x69, 0x1a, 0x43, 0x42, 0x61, 
-0x87, 0x69, 0x9f, 0x43, 0x01, 0x23, 0x1b, 0x05, 0x87, 0x61, 0xda, 0x60, 
-0x80, 0x69, 0xc0, 0x46, 0x18, 0x61, 0xa1, 0x20, 0x40, 0x03, 0x81, 0x61, 
-0x80, 0xbc, 0x70, 0x47, 0x68, 0x0e, 0x00, 0x80, 0x80, 0xb5, 0xff, 0xf7, 
-0xc9, 0xff, 0x00, 0x20, 0x00, 0xf0, 0x20, 0xf8, 0x00, 0x20, 0x09, 0x49, 
-0x00, 0x22, 0x03, 0x01, 0x5f, 0x18, 0x33, 0x23, 0x9b, 0x01, 0xfb, 0x18, 
-0x9a, 0x62, 0x01, 0x30, 0x0b, 0x28, 0xf6, 0xd3, 0x04, 0x48, 0x01, 0x22, 
-0x00, 0x21, 0x00, 0xf0, 0x33, 0xf8, 0x80, 0xbc, 
-0x08, 0xbc, 0x18, 0x47, 0x68, 0x0e, 0x00, 0x80, 0x09, 0x3e, 0xff, 0xff, 
+0x87, 0x69, 0x9f, 0x43, 0x01, 0x23, 0x1b, 0x05, 
+0x87, 0x61, 0xda, 0x60, 0x80, 0x69, 0xc0, 0x46, 0x18, 0x61, 0xa1, 0x20, 
+0x40, 0x03, 0x81, 0x61, 0x80, 0xbc, 0x70, 0x47, 0x68, 0x0e, 0x00, 0x80, 
+0x80, 0xb5, 0xff, 0xf7, 0xc9, 0xff, 0x00, 0x20, 0x00, 0xf0, 0x20, 0xf8, 
+0x00, 0x20, 0x09, 0x49, 0x00, 0x22, 0x03, 0x01, 0x5f, 0x18, 0x33, 0x23, 
+0x9b, 0x01, 0xfb, 0x18, 0x9a, 0x62, 0x01, 0x30, 0x0b, 0x28, 0xf6, 0xd3, 
+0x04, 0x48, 0x01, 0x22, 0x00, 0x21, 0x00, 0xf0, 0x33, 0xf8, 0x80, 0xbc, 
+0x08, 0xbc, 0x18, 0x47, 0x68, 0x0e, 0x00, 0x80, 0x1d, 0x3e, 0xff, 0xff, 
 0x00, 0xb5, 0x02, 0x48, 0x00, 0xf0, 0x04, 0xf8, 0x08, 0xbc, 0x18, 0x47, 
 0xa8, 0x61, 0x00, 0x00, 0x80, 0xb4, 0x01, 0x22, 0x12, 0x05, 0x0f, 0x4b, 
 0xa1, 0x21, 0x49, 0x03, 0x00, 0x28, 0x0e, 0xd0, 0xc8, 0x61, 0x18, 0x1c, 
@@ -4280,17 +3771,8 @@
 0x90, 0xb4, 0x08, 0x4a, 0xd0, 0x69, 0x00, 0x21, 0x07, 0x4f, 0xd3, 0x69, 
 0x83, 0x42, 0x02, 0xd9, 0xfc, 0x1a, 0x20, 0x18, 0x00, 0xe0, 0xc0, 0x1a, 
 0x09, 0x18, 0x18, 0x1c, 0xb9, 0x42, 0xf4, 0xd9, 0x90, 0xbc, 0x70, 0x47, 
-0x00, 0x20, 0x14, 0x40, 0xa8, 0x61, 0x00, 0x00, 0x43, 0x1a, 0x93, 0x42, 
-0x30, 0xd3, 0x84, 0x46, 0x8b, 0x07, 0x07, 0xd0, 0x52, 0x1e, 0x29, 0xd3, 
-0x0b, 0x78, 0x03, 0x70, 0x40, 0x1c, 0x49, 0x1c, 0x8b, 0x07, 0xf7, 0xd1, 
-0x83, 0x07, 0x17, 0xd1, 0x10, 0x3a, 0x05, 0xd3, 0xb0, 0xb4, 0xb8, 0xc9, 
-0xb8, 0xc0, 0x10, 0x3a, 0xfb, 0xd2, 0xb0, 0xbc, 0x0c, 0x32, 0x0f, 0xd3, 
-0x08, 0xc9, 0x08, 0xc0, 0x12, 0x1f, 0xfb, 0xd2, 0x0a, 0xe0, 0x08, 0xc9, 
-0x03, 0x70, 0x1b, 0x0a, 0x43, 0x70, 0x1b, 0x0a, 0x83, 0x70, 0x1b, 0x0a, 
-0xc3, 0x70, 0x00, 0x1d, 0x12, 0x1f, 0xf4, 0xd2, 0xd2, 0x1c, 0x05, 0xd3, 
-0x0b, 0x78, 0x03, 0x70, 0x49, 0x1c, 0x40, 0x1c, 
-0x52, 0x1e, 0xf9, 0xd2, 0x60, 0x46, 0x70, 0x47, 0x03, 0x1c, 0x0b, 0x43, 
-0x13, 0x43, 0x9b, 0x07, 0x04, 0xd1, 0x12, 0x1f, 0x8b, 0x58, 0x83, 0x50, 
-0xfb, 0xd1, 0x70, 0x47, 0x52, 0x1e, 0x8b, 0x5c, 0x83, 0x54, 0xfb, 0xd1, 
-0x70, 0x47, 0x00, 0x00, 0x00, 0x20, 0x70, 0x47, 
+0x00, 0x20, 0x14, 0x40, 0xa8, 0x61, 0x00, 0x00, 0x90, 0xb5, 0x07, 0x1c, 
+0x00, 0x24, 0x00, 0x2f, 0x04, 0xd3, 0xff, 0xf7, 0xe3, 0xff, 0x01, 0x34, 
+0xbc, 0x42, 0xfa, 0xd9, 0x90, 0xbc, 0x08, 0xbc, 
+0x18, 0x47, 0x00, 0x00, 
 };
diff -Nru a/drivers/net/typhoon.c b/drivers/net/typhoon.c
--- a/drivers/net/typhoon.c	2005-03-11 12:51:47 -08:00
+++ b/drivers/net/typhoon.c	2005-03-11 12:51:47 -08:00
@@ -50,6 +50,13 @@
  */
 static int rx_copybreak = 200;
 
+/* Should we use MMIO or Port IO?
+ * 0: Port IO
+ * 1: MMIO
+ * 2: Try MMIO, fallback to Port IO
+ */
+static unsigned int use_mmio = 2;
+
 /* end user-configurable values */
 
 /* Maximum number of multicast addresses to filter (vs. rx-all-multicast).
@@ -93,8 +100,8 @@
 #define PKT_BUF_SZ		1536
 
 #define DRV_MODULE_NAME		"typhoon"
-#define DRV_MODULE_VERSION 	"1.5.4"
-#define DRV_MODULE_RELDATE	"04/09/09"
+#define DRV_MODULE_VERSION 	"1.5.7"
+#define DRV_MODULE_RELDATE	"05/01/07"
 #define PFX			DRV_MODULE_NAME ": "
 #define ERR_PFX			KERN_ERR PFX
 
@@ -131,9 +138,16 @@
     "typhoon.c: version " DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
 
 MODULE_AUTHOR("David Dillow <dave@thedillows.org>");
+MODULE_VERSION(DRV_MODULE_VERSION);
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("3Com Typhoon Family (3C990, 3CR990, and variants)");
-MODULE_PARM(rx_copybreak, "i");
+MODULE_PARM_DESC(rx_copybreak, "Packets smaller than this are copied and "
+			       "the buffer given back to the NIC. Default "
+			       "is 200.");
+MODULE_PARM_DESC(use_mmio, "Use MMIO (1) or PIO(0) to access the NIC. "
+			   "Default is to try MMIO and fallback to PIO.");
+module_param(rx_copybreak, int, 0);
+module_param(use_mmio, int, 0);
 
 #if defined(NETIF_F_TSO) && MAX_SKB_FRAGS > 32
 #warning Typhoon only supports 32 entries in its SG list for TSO, disabling TSO
@@ -310,7 +324,7 @@
  * cannot pass a read, so this forces current writes to post.
  */
 #define typhoon_post_pci_writes(x) \
-	do { readl(x + TYPHOON_REG_HEARTBEAT); } while(0)
+	do { if(likely(use_mmio)) ioread32(x+TYPHOON_REG_HEARTBEAT); } while(0)
 
 /* We'll wait up to six seconds for a reset, and half a second normally.
  */
@@ -391,17 +405,17 @@
 	else
 		timeout = TYPHOON_RESET_TIMEOUT_SLEEP;
 
-	writel(TYPHOON_INTR_ALL, ioaddr + TYPHOON_REG_INTR_MASK);
-	writel(TYPHOON_INTR_ALL, ioaddr + TYPHOON_REG_INTR_STATUS);
+	iowrite32(TYPHOON_INTR_ALL, ioaddr + TYPHOON_REG_INTR_MASK);
+	iowrite32(TYPHOON_INTR_ALL, ioaddr + TYPHOON_REG_INTR_STATUS);
 
-	writel(TYPHOON_RESET_ALL, ioaddr + TYPHOON_REG_SOFT_RESET);
+	iowrite32(TYPHOON_RESET_ALL, ioaddr + TYPHOON_REG_SOFT_RESET);
 	typhoon_post_pci_writes(ioaddr);
 	udelay(1);
-	writel(TYPHOON_RESET_NONE, ioaddr + TYPHOON_REG_SOFT_RESET);
+	iowrite32(TYPHOON_RESET_NONE, ioaddr + TYPHOON_REG_SOFT_RESET);
 
 	if(wait_type != NoWait) {
 		for(i = 0; i < timeout; i++) {
-			if(readl(ioaddr + TYPHOON_REG_STATUS) ==
+			if(ioread32(ioaddr + TYPHOON_REG_STATUS) ==
 			   TYPHOON_STATUS_WAITING_FOR_HOST)
 				goto out;
 
@@ -416,8 +430,8 @@
 	}
 
 out:
-	writel(TYPHOON_INTR_ALL, ioaddr + TYPHOON_REG_INTR_MASK);
-	writel(TYPHOON_INTR_ALL, ioaddr + TYPHOON_REG_INTR_STATUS);
+	iowrite32(TYPHOON_INTR_ALL, ioaddr + TYPHOON_REG_INTR_MASK);
+	iowrite32(TYPHOON_INTR_ALL, ioaddr + TYPHOON_REG_INTR_STATUS);
 
 	/* The 3XP seems to need a little extra time to complete the load
 	 * of the sleep image before we can reliably boot it. Failure to
@@ -442,7 +456,7 @@
 	int i, err = 0;
 
 	for(i = 0; i < TYPHOON_WAIT_TIMEOUT; i++) {
-		if(readl(ioaddr + TYPHOON_REG_STATUS) == wait_value)
+		if(ioread32(ioaddr + TYPHOON_REG_STATUS) == wait_value)
 			goto out;
 		udelay(TYPHOON_UDELAY);
 	}
@@ -478,7 +492,7 @@
 
 		INIT_COMMAND_NO_RESPONSE(cmd, TYPHOON_CMD_HELLO_RESP);
 		smp_wmb();
-		writel(ring->lastWrite, tp->ioaddr + TYPHOON_REG_CMD_READY);
+		iowrite32(ring->lastWrite, tp->ioaddr + TYPHOON_REG_CMD_READY);
 		spin_unlock(&tp->command_lock);
 	}
 }
@@ -633,7 +647,7 @@
 	/* "I feel a presence... another warrior is on the the mesa."
 	 */
 	wmb();
-	writel(ring->lastWrite, tp->ioaddr + TYPHOON_REG_CMD_READY);
+	iowrite32(ring->lastWrite, tp->ioaddr + TYPHOON_REG_CMD_READY);
 	typhoon_post_pci_writes(tp->ioaddr);
 
 	if((cmd->flags & TYPHOON_CMD_RESPOND) == 0)
@@ -687,7 +701,7 @@
 		 * is the case.
 		 */
 		if(indexes->respCleared != indexes->respReady)
-			writel(1, tp->ioaddr + TYPHOON_REG_SELF_INTERRUPT);
+			iowrite32(1, tp->ioaddr + TYPHOON_REG_SELF_INTERRUPT);
 	}
 
 	spin_unlock(&tp->command_lock);
@@ -889,7 +903,7 @@
 	/* Kick the 3XP
 	 */
 	wmb();
-	writel(txRing->lastWrite, tp->tx_ioaddr + txRing->writeRegister);
+	iowrite32(txRing->lastWrite, tp->tx_ioaddr + txRing->writeRegister);
 
 	dev->trans_start = jiffies;
 
@@ -1058,8 +1072,10 @@
 		if(typhoon_issue_command(tp, 1, &xp_cmd, 3, xp_resp) < 0) {
 			strcpy(info->fw_version, "Unknown runtime");
 		} else {
-			strncpy(info->fw_version, (char *) &xp_resp[1], 32);
-			info->fw_version[31] = 0;
+			u32 sleep_ver = xp_resp[0].parm2;
+			snprintf(info->fw_version, 32, "%02x.%03x.%03x",
+				 sleep_ver >> 24, (sleep_ver >> 12) & 0xfff, 
+				 sleep_ver & 0xfff);
 		}
 	}
 
@@ -1251,7 +1267,7 @@
 	int i, err = 0;
 
 	for(i = 0; i < TYPHOON_WAIT_TIMEOUT; i++) {
-		if(readl(ioaddr + TYPHOON_REG_INTR_STATUS) &
+		if(ioread32(ioaddr + TYPHOON_REG_INTR_STATUS) &
 		   TYPHOON_INTR_BOOTCMD)
 			goto out;
 		udelay(TYPHOON_UDELAY);
@@ -1260,7 +1276,7 @@
 	err = -ETIMEDOUT;
 
 out:
-	writel(TYPHOON_INTR_BOOTCMD, ioaddr + TYPHOON_REG_INTR_STATUS);
+	iowrite32(TYPHOON_INTR_BOOTCMD, ioaddr + TYPHOON_REG_INTR_STATUS);
 	return err;
 }
 
@@ -1394,11 +1410,11 @@
 		goto err_out;
 	}
 
-	irqEnabled = readl(ioaddr + TYPHOON_REG_INTR_ENABLE);
-	writel(irqEnabled | TYPHOON_INTR_BOOTCMD,
+	irqEnabled = ioread32(ioaddr + TYPHOON_REG_INTR_ENABLE);
+	iowrite32(irqEnabled | TYPHOON_INTR_BOOTCMD,
 	       ioaddr + TYPHOON_REG_INTR_ENABLE);
-	irqMasked = readl(ioaddr + TYPHOON_REG_INTR_MASK);
-	writel(irqMasked | TYPHOON_INTR_BOOTCMD,
+	irqMasked = ioread32(ioaddr + TYPHOON_REG_INTR_MASK);
+	iowrite32(irqMasked | TYPHOON_INTR_BOOTCMD,
 	       ioaddr + TYPHOON_REG_INTR_MASK);
 
 	err = -ETIMEDOUT;
@@ -1410,24 +1426,24 @@
 	numSections = le32_to_cpu(fHdr->numSections);
 	load_addr = le32_to_cpu(fHdr->startAddr);
 
-	writel(TYPHOON_INTR_BOOTCMD, ioaddr + TYPHOON_REG_INTR_STATUS);
-	writel(load_addr, ioaddr + TYPHOON_REG_DOWNLOAD_BOOT_ADDR);
+	iowrite32(TYPHOON_INTR_BOOTCMD, ioaddr + TYPHOON_REG_INTR_STATUS);
+	iowrite32(load_addr, ioaddr + TYPHOON_REG_DOWNLOAD_BOOT_ADDR);
 	hmac = le32_to_cpu(fHdr->hmacDigest[0]);
-	writel(hmac, ioaddr + TYPHOON_REG_DOWNLOAD_HMAC_0);
+	iowrite32(hmac, ioaddr + TYPHOON_REG_DOWNLOAD_HMAC_0);
 	hmac = le32_to_cpu(fHdr->hmacDigest[1]);
-	writel(hmac, ioaddr + TYPHOON_REG_DOWNLOAD_HMAC_1);
+	iowrite32(hmac, ioaddr + TYPHOON_REG_DOWNLOAD_HMAC_1);
 	hmac = le32_to_cpu(fHdr->hmacDigest[2]);
-	writel(hmac, ioaddr + TYPHOON_REG_DOWNLOAD_HMAC_2);
+	iowrite32(hmac, ioaddr + TYPHOON_REG_DOWNLOAD_HMAC_2);
 	hmac = le32_to_cpu(fHdr->hmacDigest[3]);
-	writel(hmac, ioaddr + TYPHOON_REG_DOWNLOAD_HMAC_3);
+	iowrite32(hmac, ioaddr + TYPHOON_REG_DOWNLOAD_HMAC_3);
 	hmac = le32_to_cpu(fHdr->hmacDigest[4]);
-	writel(hmac, ioaddr + TYPHOON_REG_DOWNLOAD_HMAC_4);
+	iowrite32(hmac, ioaddr + TYPHOON_REG_DOWNLOAD_HMAC_4);
 	typhoon_post_pci_writes(ioaddr);
-	writel(TYPHOON_BOOTCMD_RUNTIME_IMAGE, ioaddr + TYPHOON_REG_COMMAND);
+	iowrite32(TYPHOON_BOOTCMD_RUNTIME_IMAGE, ioaddr + TYPHOON_REG_COMMAND);
 
 	image_data += sizeof(struct typhoon_file_header);
 
-	/* The readl() in typhoon_wait_interrupt() will force the
+	/* The ioread32() in typhoon_wait_interrupt() will force the
 	 * last write to the command register to post, so
 	 * we don't need a typhoon_post_pci_writes() after it.
 	 */
@@ -1441,7 +1457,7 @@
 			len = min_t(u32, section_len, PAGE_SIZE);
 
 			if(typhoon_wait_interrupt(ioaddr) < 0 ||
-			   readl(ioaddr + TYPHOON_REG_STATUS) !=
+			   ioread32(ioaddr + TYPHOON_REG_STATUS) !=
 			   TYPHOON_STATUS_WAITING_FOR_SEGMENT) {
 				printk(KERN_ERR "%s: segment ready timeout\n",
 				       tp->name);
@@ -1458,13 +1474,14 @@
 			csum = csum_fold(csum);
 			csum = le16_to_cpu(csum);
 
-			writel(len, ioaddr + TYPHOON_REG_BOOT_LENGTH);
-			writel(csum, ioaddr + TYPHOON_REG_BOOT_CHECKSUM);
-			writel(load_addr, ioaddr + TYPHOON_REG_BOOT_DEST_ADDR);
-			writel(0, ioaddr + TYPHOON_REG_BOOT_DATA_HI);
-			writel(dpage_dma, ioaddr + TYPHOON_REG_BOOT_DATA_LO);
+			iowrite32(len, ioaddr + TYPHOON_REG_BOOT_LENGTH);
+			iowrite32(csum, ioaddr + TYPHOON_REG_BOOT_CHECKSUM);
+			iowrite32(load_addr,
+					ioaddr + TYPHOON_REG_BOOT_DEST_ADDR);
+			iowrite32(0, ioaddr + TYPHOON_REG_BOOT_DATA_HI);
+			iowrite32(dpage_dma, ioaddr + TYPHOON_REG_BOOT_DATA_LO);
 			typhoon_post_pci_writes(ioaddr);
-			writel(TYPHOON_BOOTCMD_SEG_AVAILABLE,
+			iowrite32(TYPHOON_BOOTCMD_SEG_AVAILABLE,
 			       ioaddr + TYPHOON_REG_COMMAND);
 
 			image_data += len;
@@ -1474,25 +1491,25 @@
 	}
 
 	if(typhoon_wait_interrupt(ioaddr) < 0 ||
-	   readl(ioaddr + TYPHOON_REG_STATUS) !=
+	   ioread32(ioaddr + TYPHOON_REG_STATUS) !=
 	   TYPHOON_STATUS_WAITING_FOR_SEGMENT) {
 		printk(KERN_ERR "%s: final segment ready timeout\n", tp->name);
 		goto err_out_irq;
 	}
 
-	writel(TYPHOON_BOOTCMD_DNLD_COMPLETE, ioaddr + TYPHOON_REG_COMMAND);
+	iowrite32(TYPHOON_BOOTCMD_DNLD_COMPLETE, ioaddr + TYPHOON_REG_COMMAND);
 
 	if(typhoon_wait_status(ioaddr, TYPHOON_STATUS_WAITING_FOR_BOOT) < 0) {
 		printk(KERN_ERR "%s: boot ready timeout, status 0x%0x\n",
-		       tp->name, readl(ioaddr + TYPHOON_REG_STATUS));
+		       tp->name, ioread32(ioaddr + TYPHOON_REG_STATUS));
 		goto err_out_irq;
 	}
 
 	err = 0;
 
 err_out_irq:
-	writel(irqMasked, ioaddr + TYPHOON_REG_INTR_MASK);
-	writel(irqEnabled, ioaddr + TYPHOON_REG_INTR_ENABLE);
+	iowrite32(irqMasked, ioaddr + TYPHOON_REG_INTR_MASK);
+	iowrite32(irqEnabled, ioaddr + TYPHOON_REG_INTR_ENABLE);
 
 	pci_free_consistent(pdev, PAGE_SIZE, dpage, dpage_dma);
 
@@ -1510,24 +1527,25 @@
 		goto out_timeout;
 	}
 
-	writel(0, ioaddr + TYPHOON_REG_BOOT_RECORD_ADDR_HI);
-	writel(tp->shared_dma, ioaddr + TYPHOON_REG_BOOT_RECORD_ADDR_LO);
+	iowrite32(0, ioaddr + TYPHOON_REG_BOOT_RECORD_ADDR_HI);
+	iowrite32(tp->shared_dma, ioaddr + TYPHOON_REG_BOOT_RECORD_ADDR_LO);
 	typhoon_post_pci_writes(ioaddr);
-	writel(TYPHOON_BOOTCMD_REG_BOOT_RECORD, ioaddr + TYPHOON_REG_COMMAND);
+	iowrite32(TYPHOON_BOOTCMD_REG_BOOT_RECORD,
+				ioaddr + TYPHOON_REG_COMMAND);
 
 	if(typhoon_wait_status(ioaddr, TYPHOON_STATUS_RUNNING) < 0) {
 		printk(KERN_ERR "%s: boot finish timeout (status 0x%x)\n",
-		       tp->name, readl(ioaddr + TYPHOON_REG_STATUS));
+		       tp->name, ioread32(ioaddr + TYPHOON_REG_STATUS));
 		goto out_timeout;
 	}
 
 	/* Clear the Transmit and Command ready registers
 	 */
-	writel(0, ioaddr + TYPHOON_REG_TX_HI_READY);
-	writel(0, ioaddr + TYPHOON_REG_CMD_READY);
-	writel(0, ioaddr + TYPHOON_REG_TX_LO_READY);
+	iowrite32(0, ioaddr + TYPHOON_REG_TX_HI_READY);
+	iowrite32(0, ioaddr + TYPHOON_REG_CMD_READY);
+	iowrite32(0, ioaddr + TYPHOON_REG_TX_LO_READY);
 	typhoon_post_pci_writes(ioaddr);
-	writel(TYPHOON_BOOTCMD_BOOT, ioaddr + TYPHOON_REG_COMMAND);
+	iowrite32(TYPHOON_BOOTCMD_BOOT, ioaddr + TYPHOON_REG_COMMAND);
 
 	return 0;
 
@@ -1806,7 +1824,8 @@
 
 	if(done) {
 		netif_rx_complete(dev);
-		writel(TYPHOON_INTR_NONE, tp->ioaddr + TYPHOON_REG_INTR_MASK);
+		iowrite32(TYPHOON_INTR_NONE,
+				tp->ioaddr + TYPHOON_REG_INTR_MASK);
 		typhoon_post_pci_writes(tp->ioaddr);
 	}
 
@@ -1821,14 +1840,14 @@
 	void __iomem *ioaddr = tp->ioaddr;
 	u32 intr_status;
 
-	intr_status = readl(ioaddr + TYPHOON_REG_INTR_STATUS);
+	intr_status = ioread32(ioaddr + TYPHOON_REG_INTR_STATUS);
 	if(!(intr_status & TYPHOON_INTR_HOST_INT))
 		return IRQ_NONE;
 
-	writel(intr_status, ioaddr + TYPHOON_REG_INTR_STATUS);
+	iowrite32(intr_status, ioaddr + TYPHOON_REG_INTR_STATUS);
 
 	if(netif_rx_schedule_prep(dev)) {
-		writel(TYPHOON_INTR_ALL, ioaddr + TYPHOON_REG_INTR_MASK);
+		iowrite32(TYPHOON_INTR_ALL, ioaddr + TYPHOON_REG_INTR_MASK);
 		typhoon_post_pci_writes(ioaddr);
 		__netif_rx_schedule(dev);
 	} else {
@@ -1855,7 +1874,7 @@
 }
 
 static int
-typhoon_sleep(struct typhoon *tp, int state, u16 events)
+typhoon_sleep(struct typhoon *tp, pci_power_t state, u16 events)
 {
 	struct pci_dev *pdev = tp->pdev;
 	void __iomem *ioaddr = tp->ioaddr;
@@ -1905,7 +1924,7 @@
 	 * we can download the Runtime Image. But let's not make users of
 	 * the old firmware pay for the reset.
 	 */
-	writel(TYPHOON_BOOTCMD_WAKEUP, ioaddr + TYPHOON_REG_COMMAND);
+	iowrite32(TYPHOON_BOOTCMD_WAKEUP, ioaddr + TYPHOON_REG_COMMAND);
 	if(typhoon_wait_status(ioaddr, TYPHOON_STATUS_WAITING_FOR_HOST) < 0 ||
 			(tp->capabilities & TYPHOON_WAKEUP_NEEDS_RESET))
 		return typhoon_reset(ioaddr, wait_type);
@@ -1994,8 +2013,8 @@
 	tp->card_state = Running;
 	smp_wmb();
 
-	writel(TYPHOON_INTR_ENABLE_ALL, ioaddr + TYPHOON_REG_INTR_ENABLE);
-	writel(TYPHOON_INTR_NONE, ioaddr + TYPHOON_REG_INTR_MASK);
+	iowrite32(TYPHOON_INTR_ENABLE_ALL, ioaddr + TYPHOON_REG_INTR_ENABLE);
+	iowrite32(TYPHOON_INTR_NONE, ioaddr + TYPHOON_REG_INTR_MASK);
 	typhoon_post_pci_writes(ioaddr);
 
 	return 0;
@@ -2020,7 +2039,7 @@
 	 * when called with !netif_running(). This will be posted
 	 * when we force the posting of the command.
 	 */
-	writel(TYPHOON_INTR_NONE, ioaddr + TYPHOON_REG_INTR_ENABLE);
+	iowrite32(TYPHOON_INTR_NONE, ioaddr + TYPHOON_REG_INTR_ENABLE);
 
 	INIT_COMMAND_NO_RESPONSE(&xp_cmd, TYPHOON_CMD_RX_DISABLE);
 	typhoon_issue_command(tp, 1, &xp_cmd, 0, NULL);
@@ -2136,7 +2155,7 @@
 		goto out;
 	}
 
-	if(typhoon_sleep(tp, 3, 0) < 0) 
+	if(typhoon_sleep(tp, PCI_D3hot, 0) < 0) 
 		printk(KERN_ERR "%s: unable to go back to sleep\n", dev->name);
 
 out:
@@ -2163,7 +2182,7 @@
 	if(typhoon_boot_3XP(tp, TYPHOON_STATUS_WAITING_FOR_HOST) < 0)
 		printk(KERN_ERR "%s: unable to boot sleep image\n", dev->name);
 
-	if(typhoon_sleep(tp, 3, 0) < 0)
+	if(typhoon_sleep(tp, PCI_D3hot, 0) < 0)
 		printk(KERN_ERR "%s: unable to put card to sleep\n", dev->name);
 
 	return 0;
@@ -2203,7 +2222,7 @@
 }
 
 static int
-typhoon_suspend(struct pci_dev *pdev, u32 state)
+typhoon_suspend(struct pci_dev *pdev, pm_message_t state)
 {
 	struct net_device *dev = pci_get_drvdata(pdev);
 	struct typhoon *tp = netdev_priv(dev);
@@ -2275,14 +2294,59 @@
 #endif
 
 static int __devinit
+typhoon_test_mmio(struct pci_dev *pdev)
+{
+	void __iomem *ioaddr = pci_iomap(pdev, 1, 128);
+	int mode = 0;
+	u32 val;
+
+	if(!ioaddr)
+		goto out;
+
+	if(ioread32(ioaddr + TYPHOON_REG_STATUS) !=
+				TYPHOON_STATUS_WAITING_FOR_HOST)
+		goto out_unmap;
+
+	iowrite32(TYPHOON_INTR_ALL, ioaddr + TYPHOON_REG_INTR_MASK);
+	iowrite32(TYPHOON_INTR_ALL, ioaddr + TYPHOON_REG_INTR_STATUS);
+	iowrite32(TYPHOON_INTR_ALL, ioaddr + TYPHOON_REG_INTR_ENABLE);
+
+	/* Ok, see if we can change our interrupt status register by
+	 * sending ourselves an interrupt. If so, then MMIO works.
+	 * The 50usec delay is arbitrary -- it could probably be smaller.
+	 */
+	val = ioread32(ioaddr + TYPHOON_REG_INTR_STATUS);
+	if((val & TYPHOON_INTR_SELF) == 0) {
+		iowrite32(1, ioaddr + TYPHOON_REG_SELF_INTERRUPT);
+		ioread32(ioaddr + TYPHOON_REG_INTR_STATUS);
+		udelay(50);
+		val = ioread32(ioaddr + TYPHOON_REG_INTR_STATUS);
+		if(val & TYPHOON_INTR_SELF)
+			mode = 1;
+	}
+
+	iowrite32(TYPHOON_INTR_ALL, ioaddr + TYPHOON_REG_INTR_MASK);
+	iowrite32(TYPHOON_INTR_ALL, ioaddr + TYPHOON_REG_INTR_STATUS);
+	iowrite32(TYPHOON_INTR_NONE, ioaddr + TYPHOON_REG_INTR_ENABLE);
+	ioread32(ioaddr + TYPHOON_REG_INTR_STATUS);
+
+out_unmap:
+	pci_iounmap(pdev, ioaddr);
+
+out:
+	if(!mode)
+		printk(KERN_INFO PFX "falling back to port IO\n");
+	return mode;
+}
+
+static int __devinit
 typhoon_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
 	static int did_version = 0;
 	struct net_device *dev;
 	struct typhoon *tp;
 	int card_id = (int) ent->driver_data;
-	unsigned long ioaddr;
-	void __iomem *ioaddr_mapped;
+	void __iomem *ioaddr;
 	void *shared;
 	dma_addr_t shared_dma;
 	struct cmd_desc xp_cmd;
@@ -2323,8 +2387,21 @@
 		goto error_out_mwi;
 	}
 
-	/* sanity checks, resource #1 is our mmio area
+	/* sanity checks on IO and MMIO BARs
 	 */
+	if(!(pci_resource_flags(pdev, 0) & IORESOURCE_IO)) {
+		printk(ERR_PFX
+		       "%s: region #1 not a PCI IO resource, aborting\n",
+		       pci_name(pdev));
+		err = -ENODEV;
+		goto error_out_mwi;
+	}
+	if(pci_resource_len(pdev, 0) < 128) {
+		printk(ERR_PFX "%s: Invalid PCI IO region size, aborting\n",
+		       pci_name(pdev));
+		err = -ENODEV;
+		goto error_out_mwi;
+	}
 	if(!(pci_resource_flags(pdev, 1) & IORESOURCE_MEM)) {
 		printk(ERR_PFX
 		       "%s: region #1 not a PCI MMIO resource, aborting\n",
@@ -2346,12 +2423,14 @@
 		goto error_out_mwi;
 	}
 
-	/* map our MMIO region
+	/* map our registers
 	 */
-	ioaddr = pci_resource_start(pdev, 1);
-	ioaddr_mapped = ioremap(ioaddr, 128);
-	if (!ioaddr_mapped) {
-		printk(ERR_PFX "%s: cannot remap MMIO, aborting\n",
+	if(use_mmio != 0 && use_mmio != 1)
+		use_mmio = typhoon_test_mmio(pdev);
+
+	ioaddr = pci_iomap(pdev, use_mmio, 128);
+	if (!ioaddr) {
+		printk(ERR_PFX "%s: cannot remap registers, aborting\n",
 		       pci_name(pdev));
 		err = -EIO;
 		goto error_out_regions;
@@ -2374,13 +2453,10 @@
 	tp->shared_dma = shared_dma;
 	tp->pdev = pdev;
 	tp->tx_pdev = pdev;
-	tp->ioaddr = ioaddr_mapped;
-	tp->tx_ioaddr = ioaddr_mapped;
+	tp->ioaddr = ioaddr;
+	tp->tx_ioaddr = ioaddr;
 	tp->dev = dev;
 
-	/* need to be able to restore PCI state after a suspend */
-	pci_save_state(pdev);
-
 	/* Init sequence:
 	 * 1) Reset the adapter to clear any bad juju
 	 * 2) Reload the sleep image
@@ -2388,16 +2464,18 @@
 	 * 4) Get the hardware address.
 	 * 5) Put the card to sleep.
 	 */
-	if (typhoon_reset(ioaddr_mapped, WaitSleep) < 0) {
+	if (typhoon_reset(ioaddr, WaitSleep) < 0) {
 		printk(ERR_PFX "%s: could not reset 3XP\n", pci_name(pdev));
 		err = -EIO;
 		goto error_out_dma;
 	}
 
 	/* Now that we've reset the 3XP and are sure it's not going to
-	 * write all over memory, enable bus mastering.
+	 * write all over memory, enable bus mastering, and save our
+	 * state for resuming after a suspend.
 	 */
 	pci_set_master(pdev);
+	pci_save_state(pdev);
 
 	/* dev->name is not valid until we register, but we need to
 	 * use some common routines to initialize the card. So that those
@@ -2438,7 +2516,7 @@
 	INIT_COMMAND_WITH_RESPONSE(&xp_cmd, TYPHOON_CMD_READ_VERSIONS);
 	if(typhoon_issue_command(tp, 1, &xp_cmd, 3, xp_resp) < 0) {
 		printk(ERR_PFX "%s: Could not get Sleep Image version\n",
-			pdev->slot_name);
+			pci_name(pdev));
 		goto error_out_reset;
 	}
 
@@ -2454,7 +2532,7 @@
 	if(xp_resp[0].numDesc != 0)
 		tp->capabilities |= TYPHOON_WAKEUP_NEEDS_RESET;
 
-	if(typhoon_sleep(tp, 3, 0) < 0) {
+	if(typhoon_sleep(tp, PCI_D3hot, 0) < 0) {
 		printk(ERR_PFX "%s: cannot put adapter to sleep\n",
 		       pci_name(pdev));
 		err = -EIO;
@@ -2491,8 +2569,9 @@
 
 	pci_set_drvdata(pdev, dev);
 
-	printk(KERN_INFO "%s: %s at 0x%lx, ",
-	       dev->name, typhoon_card_info[card_id].name, ioaddr);
+	printk(KERN_INFO "%s: %s at %s 0x%lx, ",
+	       dev->name, typhoon_card_info[card_id].name,
+	       use_mmio ? "MMIO" : "IO", pci_resource_start(pdev, use_mmio));
 	for(i = 0; i < 5; i++)
 		printk("%2.2x:", dev->dev_addr[i]);
 	printk("%2.2x\n", dev->dev_addr[i]);
@@ -2515,7 +2594,8 @@
 		u8 *ver_string = (u8 *) &xp_resp[1];
 		ver_string[25] = 0;
 		printk(KERN_INFO "%s: Typhoon 1.1+ Sleep Image version "
-			"%u.%u.%u.%u %s\n", dev->name, HIPQUAD(sleep_ver),
+			"%02x.%03x.%03x %s\n", dev->name, sleep_ver >> 24,
+			(sleep_ver >> 12) & 0xfff, sleep_ver & 0xfff,
 			ver_string);
 	} else {
 		printk(KERN_WARNING "%s: Unknown Sleep Image version "
@@ -2526,13 +2606,13 @@
 	return 0;
 
 error_out_reset:
-	typhoon_reset(ioaddr_mapped, NoWait);
+	typhoon_reset(ioaddr, NoWait);
 
 error_out_dma:
 	pci_free_consistent(pdev, sizeof(struct typhoon_shared),
 			    shared, shared_dma);
 error_out_remap:
-	iounmap(ioaddr_mapped);
+	pci_iounmap(pdev, ioaddr);
 error_out_regions:
 	pci_release_regions(pdev);
 error_out_mwi:
@@ -2555,7 +2635,7 @@
 	pci_set_power_state(pdev, PCI_D0);
 	pci_restore_state(pdev);
 	typhoon_reset(tp->ioaddr, NoWait);
-	iounmap(tp->ioaddr);
+	pci_iounmap(pdev, tp->ioaddr);
 	pci_free_consistent(pdev, sizeof(struct typhoon_shared),
 			    tp->shared, tp->shared_dma);
 	pci_release_regions(pdev);
diff -Nru a/drivers/net/via-rhine.c b/drivers/net/via-rhine.c
--- a/drivers/net/via-rhine.c	2005-03-11 12:51:51 -08:00
+++ b/drivers/net/via-rhine.c	2005-03-11 12:51:51 -08:00
@@ -390,7 +390,7 @@
 
 #ifdef USE_MMIO
 /* Registers we check that mmio and reg are the same. */
-int mmio_verify_registers[] = {
+static const int mmio_verify_registers[] = {
 	RxConfig, TxConfig, IntrEnable, ConfigA, ConfigB, ConfigC, ConfigD,
 	0
 };
@@ -1197,8 +1197,10 @@
 		       dev->name, rp->pdev->irq);
 
 	rc = alloc_ring(dev);
-	if (rc)
+	if (rc) {
+		free_irq(rp->pdev->irq, dev);
 		return rc;
+	}
 	alloc_rbufs(dev);
 	alloc_tbufs(dev);
 	rhine_chip_reset(dev);
@@ -1899,6 +1901,9 @@
 	struct rhine_private *rp = netdev_priv(dev);
 	void __iomem *ioaddr = rp->base;
 
+	if (!(rp->quirks & rqWOL))
+		return; /* Nothing to do for non-WOL adapters */
+
 	rhine_power_init(dev);
 
 	/* Make sure we use pattern 0, 1 and not 4, 5 */
@@ -1937,7 +1942,7 @@
 }
 
 #ifdef CONFIG_PM
-static int rhine_suspend(struct pci_dev *pdev, u32 state)
+static int rhine_suspend(struct pci_dev *pdev, pm_message_t state)
 {
 	struct net_device *dev = pci_get_drvdata(pdev);
 	struct rhine_private *rp = netdev_priv(dev);
diff -Nru a/drivers/net/via-velocity.c b/drivers/net/via-velocity.c
--- a/drivers/net/via-velocity.c	2005-03-11 12:51:50 -08:00
+++ b/drivers/net/via-velocity.c	2005-03-11 12:51:50 -08:00
@@ -263,7 +263,7 @@
 
 #ifdef CONFIG_PM
 
-static int velocity_suspend(struct pci_dev *pdev, u32 state);
+static int velocity_suspend(struct pci_dev *pdev, pm_message_t state);
 static int velocity_resume(struct pci_dev *pdev);
 
 static int velocity_netdev_event(struct notifier_block *nb, unsigned long notification, void *ptr);
@@ -2898,7 +2898,7 @@
 	struct velocity_info *vptr = dev->priv;
 	strcpy(info->driver, VELOCITY_NAME);
 	strcpy(info->version, VELOCITY_VERSION);
-	strcpy(info->bus_info, vptr->pdev->slot_name);
+	strcpy(info->bus_info, pci_name(vptr->pdev));
 }
 
 static void velocity_ethtool_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
@@ -3096,7 +3096,7 @@
  *	we are interested in.
  */
 
-u16 wol_calc_crc(int size, u8 * pattern, u8 *mask_pattern)
+static u16 wol_calc_crc(int size, u8 * pattern, u8 *mask_pattern)
 {
 	u16 crc = 0xFFFF;
 	u8 mask;
@@ -3210,7 +3210,7 @@
 	return 0;
 }
 
-static int velocity_suspend(struct pci_dev *pdev, u32 state)
+static int velocity_suspend(struct pci_dev *pdev, pm_message_t state)
 {
 	struct velocity_info *vptr = pci_get_drvdata(pdev);
 	unsigned long flags;
diff -Nru a/drivers/net/wan/Kconfig b/drivers/net/wan/Kconfig
--- a/drivers/net/wan/Kconfig	2005-03-11 12:51:42 -08:00
+++ b/drivers/net/wan/Kconfig	2005-03-11 12:51:42 -08:00
@@ -155,7 +155,8 @@
 	  Network) card supported by this driver and you are planning to
 	  connect the box to a WAN.
 
-	  You will need supporting software from <http://hq.pm.waw.pl/hdlc/>.
+	  You will need supporting software from
+	  <http://www.kernel.org/pub/linux/utils/net/hdlc/>.
 	  Generic HDLC driver currently supports raw HDLC, Cisco HDLC, Frame
 	  Relay, synchronous Point-to-Point Protocol (PPP) and X.25.
 
@@ -225,7 +226,7 @@
 	  Driver for PCI200SYN cards by Goramo sp. j.
 
 	  If you have such a card, say Y here and see
-	  <http://hq.pm.waw.pl/hdlc/>.
+	  <http://www.kernel.org/pub/linux/utils/net/hdlc/>.
 
 	  To compile this as a module, choose M here: the
 	  module will be called pci200syn.
@@ -239,7 +240,7 @@
 	  Driver for wanXL PCI cards by SBE Inc.
 
 	  If you have such a card, say Y here and see
-	  <http://hq.pm.waw.pl/hdlc/>.
+	  <http://www.kernel.org/pub/linux/utils/net/hdlc/>.
 
 	  To compile this as a module, choose M here: the
 	  module will be called wanxl.
@@ -292,7 +293,7 @@
 	  SDL Communications Inc.
 
 	  If you have such a card, say Y here and see
-	  <http://hq.pm.waw.pl/hdlc/>.
+	  <http://www.kernel.org/pub/linux/utils/net/hdlc/>.
 
 	  Note that N2csu and N2dds cards are not supported by this driver.
 
@@ -308,7 +309,7 @@
 	  Driver for C101 SuperSync ISA cards by Moxa Technologies Co., Ltd.
 
 	  If you have such a card, say Y here and see
-	  <http://hq.pm.waw.pl/pub/hdlc/>
+	  <http://www.kernel.org/pub/linux/utils/net/hdlc/>.
 
 	  To compile this driver as a module, choose M here: the
 	  module will be called c101.
diff -Nru a/drivers/net/wan/cosa.c b/drivers/net/wan/cosa.c
--- a/drivers/net/wan/cosa.c	2005-03-11 12:51:41 -08:00
+++ b/drivers/net/wan/cosa.c	2005-03-11 12:51:41 -08:00
@@ -543,7 +543,7 @@
 		 * FIXME: When this code is not used as module, we should
 		 * probably call udelay() instead of the interruptible sleep.
 		 */
-		current->state = TASK_INTERRUPTIBLE;
+		set_current_state(TASK_INTERRUPTIBLE);
 		cosa_putstatus(cosa, SR_TX_INT_ENA);
 		schedule_timeout(30);
 		irq = probe_irq_off(irqs);
@@ -1564,8 +1564,7 @@
 	cosa_getdata8(cosa);
 	cosa_putstatus(cosa, SR_RST);
 #ifdef MODULE
-	current->state = TASK_INTERRUPTIBLE;
-	schedule_timeout(HZ/2);
+	msleep(500);
 #else
 	udelay(5*100000);
 #endif
@@ -1618,7 +1617,7 @@
 			return r;
 		}
 		/* sleep if not ready to read */
-		current->state = TASK_INTERRUPTIBLE;
+		set_current_state(TASK_INTERRUPTIBLE);
 		schedule_timeout(1);
 	}
 	printk(KERN_INFO "cosa: timeout in get_wait_data (status 0x%x)\n",
diff -Nru a/drivers/net/wan/hd6457x.c b/drivers/net/wan/hd6457x.c
--- a/drivers/net/wan/hd6457x.c	2005-03-11 12:51:41 -08:00
+++ b/drivers/net/wan/hd6457x.c	2005-03-11 12:51:41 -08:00
@@ -315,7 +315,7 @@
 #endif
 	stats->rx_packets++;
 	stats->rx_bytes += skb->len;
-	skb->dev->last_rx = jiffies;
+	dev->last_rx = jiffies;
 	skb->protocol = hdlc_type_trans(skb, dev);
 	netif_rx(skb);
 }
diff -Nru a/drivers/net/wan/sbni.c b/drivers/net/wan/sbni.c
--- a/drivers/net/wan/sbni.c	2005-03-11 12:51:42 -08:00
+++ b/drivers/net/wan/sbni.c	2005-03-11 12:51:42 -08:00
@@ -176,7 +176,7 @@
 
 #ifndef MODULE
 typedef u32  iarr[];
-static iarr  *dest[5] = { &io, &irq, &baud, &rxl, &mac };
+static iarr __initdata *dest[5] = { &io, &irq, &baud, &rxl, &mac };
 #endif
 
 /* A zero-terminated list of I/O addresses to be probed on ISA bus */
diff -Nru a/drivers/net/wan/wanxl.c b/drivers/net/wan/wanxl.c
--- a/drivers/net/wan/wanxl.c	2005-03-11 12:51:51 -08:00
+++ b/drivers/net/wan/wanxl.c	2005-03-11 12:51:51 -08:00
@@ -72,7 +72,7 @@
 	u8 irq;
 
 	u8 __iomem *plx;	/* PLX PCI9060 virtual base address */
-	struct pci_dev *pdev;	/* for pdev->slot_name */
+	struct pci_dev *pdev;	/* for pci_name(pdev) */
 	int rx_in;
 	struct sk_buff *rx_skbs[RX_QUEUE_LENGTH];
 	card_status_t *status;	/* shared between host and card */
@@ -88,12 +88,6 @@
 }
 
 
-static inline const char* card_name(struct pci_dev *pdev)
-{
-	return pdev->slot_name;
-}
-
-
 static inline port_status_t* get_status(port_t *port)
 {
 	return &port->card->status->port_status[port->node];
@@ -107,7 +101,7 @@
 	dma_addr_t addr = pci_map_single(pdev, ptr, size, direction);
 	if (addr + size > 0x100000000LL)
 		printk(KERN_CRIT "wanXL %s: pci_map_single() returned memory"
-		       " at 0x%LX!\n", card_name(pdev),
+		       " at 0x%LX!\n", pci_name(pdev),
 		       (unsigned long long)addr);
 	return addr;
 }
@@ -201,7 +195,7 @@
 	       desc->stat != PACKET_EMPTY) {
 		if ((desc->stat & PACKET_PORT_MASK) > card->n_ports)
 			printk(KERN_CRIT "wanXL %s: received packet for"
-			       " nonexistent port\n", card_name(card->pdev));
+			       " nonexistent port\n", pci_name(card->pdev));
 		else {
 			struct sk_buff *skb = card->rx_skbs[card->rx_in];
 			port_t *port = &card->ports[desc->stat &
@@ -604,7 +598,7 @@
 	card = kmalloc(alloc_size, GFP_KERNEL);
 	if (card == NULL) {
 		printk(KERN_ERR "wanXL %s: unable to allocate memory\n",
-		       card_name(pdev));
+		       pci_name(pdev));
 		pci_release_regions(pdev);
 		pci_disable_device(pdev);
 		return -ENOBUFS;
@@ -623,7 +617,7 @@
 
 #ifdef DEBUG_PCI
 	printk(KERN_DEBUG "wanXL %s: pci_alloc_consistent() returned memory"
-	       " at 0x%LX\n", card_name(pdev),
+	       " at 0x%LX\n", pci_name(pdev),
 	       (unsigned long long)card->status_address);
 #endif
 
@@ -649,7 +643,7 @@
 	while ((stat = readl(card->plx + PLX_MAILBOX_0)) != 0) {
 		if (time_before(timeout, jiffies)) {
 			printk(KERN_WARNING "wanXL %s: timeout waiting for"
-			       " PUTS to complete\n", card_name(pdev));
+			       " PUTS to complete\n", pci_name(pdev));
 			wanxl_pci_remove_one(pdev);
 			return -ENODEV;
 		}
@@ -661,7 +655,7 @@
 
 		default:
 			printk(KERN_WARNING "wanXL %s: PUTS test 0x%X"
-			       " failed\n", card_name(pdev), stat & 0x30);
+			       " failed\n", pci_name(pdev), stat & 0x30);
 			wanxl_pci_remove_one(pdev);
 			return -ENODEV;
 		}
@@ -681,7 +675,7 @@
 	    (TX_BUFFERS + RX_BUFFERS) * BUFFER_LENGTH * ports) {
 		printk(KERN_WARNING "wanXL %s: no enough on-board RAM"
 		       " (%u bytes detected, %u bytes required)\n",
-		       card_name(pdev), ramsize, BUFFERS_ADDR +
+		       pci_name(pdev), ramsize, BUFFERS_ADDR +
 		       (TX_BUFFERS + RX_BUFFERS) * BUFFER_LENGTH * ports);
 		wanxl_pci_remove_one(pdev);
 		return -ENODEV;
@@ -689,7 +683,7 @@
 
 	if (wanxl_puts_command(card, MBX1_CMD_BSWAP)) {
 		printk(KERN_WARNING "wanXL %s: unable to Set Byte Swap"
-		       " Mode\n", card_name(pdev));
+		       " Mode\n", pci_name(pdev));
 		wanxl_pci_remove_one(pdev);
 		return -ENODEV;
 	}
@@ -720,7 +714,7 @@
 
 	if (wanxl_puts_command(card, MBX1_CMD_ABORTJ)) {
 		printk(KERN_WARNING "wanXL %s: unable to Abort and Jump\n",
-		       card_name(pdev));
+		       pci_name(pdev));
 		wanxl_pci_remove_one(pdev);
 		return -ENODEV;
 	}
@@ -735,7 +729,7 @@
 
 	if (!stat) {
 		printk(KERN_WARNING "wanXL %s: timeout while initializing card"
-		       "firmware\n", card_name(pdev));
+		       "firmware\n", pci_name(pdev));
 		wanxl_pci_remove_one(pdev);
 		return -ENODEV;
 	}
@@ -745,12 +739,12 @@
 #endif
 
 	printk(KERN_INFO "wanXL %s: at 0x%X, %u KB of RAM at 0x%X, irq %u\n",
-	       card_name(pdev), plx_phy, ramsize / 1024, mem_phy, pdev->irq);
+	       pci_name(pdev), plx_phy, ramsize / 1024, mem_phy, pdev->irq);
 
 	/* Allocate IRQ */
 	if (request_irq(pdev->irq, wanxl_intr, SA_SHIRQ, "wanXL", card)) {
 		printk(KERN_WARNING "wanXL %s: could not allocate IRQ%i.\n",
-		       card_name(pdev), pdev->irq);
+		       pci_name(pdev), pdev->irq);
 		wanxl_pci_remove_one(pdev);
 		return -EBUSY;
 	}
@@ -762,7 +756,7 @@
 		struct net_device *dev = alloc_hdlcdev(port);
 		if (!dev) {
 			printk(KERN_ERR "wanXL %s: unable to allocate"
-			       " memory\n", card_name(pdev));
+			       " memory\n", pci_name(pdev));
 			wanxl_pci_remove_one(pdev);
 			return -ENOMEM;
 		}
@@ -783,7 +777,7 @@
 		get_status(port)->clocking = CLOCK_EXT;
 		if (register_hdlc_device(dev)) {
 			printk(KERN_ERR "wanXL %s: unable to register hdlc"
-			       " device\n", card_name(pdev));
+			       " device\n", pci_name(pdev));
 			free_netdev(dev);
 			wanxl_pci_remove_one(pdev);
 			return -ENOBUFS;
@@ -791,7 +785,7 @@
 		card->n_ports++;
 	}
 
-	printk(KERN_INFO "wanXL %s: port", card_name(pdev));
+	printk(KERN_INFO "wanXL %s: port", pci_name(pdev));
 	for (i = 0; i < ports; i++)
 		printk("%s #%i: %s", i ? "," : "", i,
 		       card->ports[i].dev->name);
diff -Nru a/drivers/net/wan/z85230.c b/drivers/net/wan/z85230.c
--- a/drivers/net/wan/z85230.c	2005-03-11 12:51:41 -08:00
+++ b/drivers/net/wan/z85230.c	2005-03-11 12:51:41 -08:00
@@ -734,7 +734,7 @@
 	u8 intr;
 	static volatile int locker=0;
 	int work=0;
-	struct z8530_irqhandler *irqs=dev->chanA.irqs;
+	struct z8530_irqhandler *irqs;
 	
 	if(locker)
 	{
@@ -758,6 +758,8 @@
 		/* Now walk the chip and see what it is wanting - it may be
 		   an IRQ for someone else remember */
 		   
+		irqs=dev->chanA.irqs;
+
 		if(intr & (CHARxIP|CHATxIP|CHAEXT))
 		{
 			if(intr&CHARxIP)
diff -Nru a/drivers/net/wd.c b/drivers/net/wd.c
--- a/drivers/net/wd.c	2005-03-11 12:51:41 -08:00
+++ b/drivers/net/wd.c	2005-03-11 12:51:41 -08:00
@@ -131,6 +131,7 @@
 {
 	free_irq(dev->irq, dev);
 	release_region(dev->base_addr - WD_NIC_OFFSET, WD_IO_EXTENT);
+	iounmap(ei_status.mem);
 }
 
 #ifndef MODULE
@@ -317,16 +318,22 @@
 	ei_status.rx_start_page = WD_START_PG + TX_PAGES;
 
 	/* Don't map in the shared memory until the board is actually opened. */
-	ei_status.rmem_start = dev->mem_start + TX_PAGES*256;
 
 	/* Some cards (eg WD8003EBT) can be jumpered for more (32k!) memory. */
 	if (dev->mem_end != 0) {
 		ei_status.stop_page = (dev->mem_end - dev->mem_start)/256;
+		ei_status.priv = dev->mem_end - dev->mem_start;
 	} else {
 		ei_status.stop_page = word16 ? WD13_STOP_PG : WD03_STOP_PG;
 		dev->mem_end = dev->mem_start + (ei_status.stop_page - WD_START_PG)*256;
+		ei_status.priv = (ei_status.stop_page - WD_START_PG)*256;
+	}
+
+	ei_status.mem = ioremap(dev->mem_start, ei_status.priv);
+	if (!ei_status.mem) {
+		free_irq(dev->irq, dev);
+		return -ENOMEM;
 	}
-	ei_status.rmem_end = dev->mem_end;
 
 	printk(" %s, IRQ %d, shared memory at %#lx-%#lx.\n",
 		   model_name, dev->irq, dev->mem_start, dev->mem_end-1);
@@ -397,7 +404,7 @@
 {
 
 	int wd_cmdreg = dev->base_addr - WD_NIC_OFFSET; /* WD_CMDREG */
-	unsigned long hdr_start = dev->mem_start + ((ring_page - WD_START_PG)<<8);
+	void __iomem *hdr_start = ei_status.mem + ((ring_page - WD_START_PG)<<8);
 
 	/* We'll always get a 4 byte header read followed by a packet read, so
 	   we enable 16 bit mode before the header, and disable after the body. */
@@ -407,10 +414,10 @@
 #ifdef __BIG_ENDIAN
 	/* Officially this is what we are doing, but the readl() is faster */
 	/* unfortunately it isn't endian aware of the struct               */
-	isa_memcpy_fromio(hdr, hdr_start, sizeof(struct e8390_pkt_hdr));
+	memcpy_fromio(hdr, hdr_start, sizeof(struct e8390_pkt_hdr));
 	hdr->count = le16_to_cpu(hdr->count);
 #else
-	((unsigned int*)hdr)[0] = isa_readl(hdr_start);
+	((unsigned int*)hdr)[0] = readl(hdr_start);
 #endif
 }
 
@@ -423,17 +430,18 @@
 wd_block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset)
 {
 	int wd_cmdreg = dev->base_addr - WD_NIC_OFFSET; /* WD_CMDREG */
-	unsigned long xfer_start = dev->mem_start + ring_offset - (WD_START_PG<<8);
+	unsigned long offset = ring_offset - (WD_START_PG<<8);
+	void __iomem *xfer_start = ei_status.mem + offset;
 
-	if (xfer_start + count > ei_status.rmem_end) {
+	if (offset + count > ei_status.priv) {
 		/* We must wrap the input move. */
-		int semi_count = ei_status.rmem_end - xfer_start;
-		isa_memcpy_fromio(skb->data, xfer_start, semi_count);
+		int semi_count = ei_status.priv - offset;
+		memcpy_fromio(skb->data, xfer_start, semi_count);
 		count -= semi_count;
-		isa_memcpy_fromio(skb->data + semi_count, ei_status.rmem_start, count);
+		memcpy_fromio(skb->data + semi_count, ei_status.mem + TX_PAGES * 256, count);
 	} else {
 		/* Packet is in one chunk -- we can copy + cksum. */
-		isa_eth_io_copy_and_sum(skb, xfer_start, count, 0);
+		eth_io_copy_and_sum(skb, xfer_start, count, 0);
 	}
 
 	/* Turn off 16 bit access so that reboot works.	 ISA brain-damage */
@@ -446,16 +454,16 @@
 				int start_page)
 {
 	int wd_cmdreg = dev->base_addr - WD_NIC_OFFSET; /* WD_CMDREG */
-	long shmem = dev->mem_start + ((start_page - WD_START_PG)<<8);
+	void __iomem *shmem = ei_status.mem + ((start_page - WD_START_PG)<<8);
 
 
 	if (ei_status.word16) {
 		/* Turn on and off 16 bit access so that reboot works. */
 		outb(ISA16 | ei_status.reg5, wd_cmdreg+WD_CMDREG5);
-		isa_memcpy_toio(shmem, buf, count);
+		memcpy_toio(shmem, buf, count);
 		outb(ei_status.reg5, wd_cmdreg+WD_CMDREG5);
 	} else
-		isa_memcpy_toio(shmem, buf, count);
+		memcpy_toio(shmem, buf, count);
 }
 
 
diff -Nru a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c
--- a/drivers/net/wireless/airo.c	2005-03-11 12:51:41 -08:00
+++ b/drivers/net/wireless/airo.c	2005-03-11 12:51:41 -08:00
@@ -1698,9 +1698,8 @@
 			issuecommand(ai, &cmd, &rsp);
 			up(&ai->sem);
 			/* Let the command take effect */
-			set_current_state (TASK_INTERRUPTIBLE);
 			ai->task = current;
-			schedule_timeout (3*HZ);
+			ssleep(3);
 			ai->task = NULL;
 		}
 	rc = PC4500_readrid(ai, first ? RID_BSSLISTFIRST : RID_BSSLISTNEXT,
@@ -2685,11 +2684,9 @@
 		return -1;
 	waitbusy (ai);
 	OUT4500(ai,COMMAND,CMD_SOFTRESET);
-	set_current_state (TASK_UNINTERRUPTIBLE);
-	schedule_timeout (HZ/5);
+	msleep(200);
 	waitbusy (ai);
-	set_current_state (TASK_UNINTERRUPTIBLE);
-	schedule_timeout (HZ/5);
+	msleep(200);
 	if (lock)
 		up(&ai->sem);
 	return 0;
@@ -5516,12 +5513,12 @@
 	} else {
 		OUT4500(ai, EVACK, EV_AWAKEN);
 		OUT4500(ai, EVACK, EV_AWAKEN);
-		schedule_timeout(HZ/10);
+		msleep(100);
 	}
 
 	set_bit (FLAG_COMMIT, &ai->flags);
 	disable_MAC(ai, 0);
-        schedule_timeout (HZ/5);
+        msleep(200);
 	if (ai->SSID) {
 		writeSsidRid(ai, ai->SSID, 0);
 		kfree(ai->SSID);
@@ -7470,8 +7467,7 @@
 
 	OUT4500(ai,COMMAND,CMD_SOFTRESET);
 
-	set_current_state (TASK_UNINTERRUPTIBLE);
-	schedule_timeout (HZ);          /* WAS 600 12/7/00 */
+	ssleep(1);			/* WAS 600 12/7/00 */
 
 	if(!waitbusy (ai)){
 		printk(KERN_INFO "Waitbusy hang AFTER RESET\n");
@@ -7498,8 +7494,7 @@
 		OUT4500(ai, SWS3, FLASH_COMMAND);
 		OUT4500(ai, COMMAND,0);
 	}
-	set_current_state (TASK_UNINTERRUPTIBLE);
-	schedule_timeout (HZ/2); /* 500ms delay */
+	msleep(500);		/* 500ms delay */
 
 	if(!waitbusy(ai)) {
 		clear_bit (FLAG_FLASHING, &ai->flags);
@@ -7609,8 +7604,7 @@
 int flashrestart(struct airo_info *ai,struct net_device *dev){
 	int    i,status;
 
-	set_current_state (TASK_UNINTERRUPTIBLE);
-	schedule_timeout (HZ);          /* Added 12/7/00 */
+	ssleep(1);			/* Added 12/7/00 */
 	clear_bit (FLAG_FLASHING, &ai->flags);
 	if (test_bit(FLAG_MPI, &ai->flags)) {
 		status = mpi_init_descriptors(ai);
@@ -7625,8 +7619,7 @@
 				( ai, 2312, i >= MAX_FIDS / 2 );
 		}
 
-	set_current_state (TASK_UNINTERRUPTIBLE);
-	schedule_timeout (HZ);          /* Added 12/7/00 */
+	ssleep(1);			/* Added 12/7/00 */
 	return status;
 }
 #endif /* CISCO_EXT */
diff -Nru a/drivers/net/wireless/airport.c b/drivers/net/wireless/airport.c
--- a/drivers/net/wireless/airport.c	2005-03-11 12:51:51 -08:00
+++ b/drivers/net/wireless/airport.c	2005-03-11 12:51:51 -08:00
@@ -28,7 +28,6 @@
 #include <linux/if_arp.h>
 #include <linux/etherdevice.h>
 #include <linux/wireless.h>
-#include <linux/delay.h>
 
 #include <asm/io.h>
 #include <asm/system.h>
@@ -45,7 +44,7 @@
 
 struct airport {
 	struct macio_dev *mdev;
-	void *vaddr;
+	void __iomem *vaddr;
 	int irq_requested;
 	int ndev_registered;
 };
@@ -150,7 +149,7 @@
 	ssleep(1);
 
 	macio_set_drvdata(mdev, NULL);
-	free_netdev(dev);
+	free_orinocodev(dev);
 
 	return 0;
 }
@@ -194,14 +193,14 @@
 	hermes_t *hw;
 
 	if (macio_resource_count(mdev) < 1 || macio_irq_count(mdev) < 1) {
-		printk(KERN_ERR PFX "wrong interrupt/addresses in OF tree\n");
+		printk(KERN_ERR PFX "Wrong interrupt/addresses in OF tree\n");
 		return -ENODEV;
 	}
 
 	/* Allocate space for private device-specific data */
 	dev = alloc_orinocodev(sizeof(*card), airport_hard_reset);
 	if (! dev) {
-		printk(KERN_ERR PFX "can't allocate device datas\n");
+		printk(KERN_ERR PFX "Cannot allocate network device\n");
 		return -ENODEV;
 	}
 	priv = netdev_priv(dev);
@@ -212,7 +211,7 @@
 
 	if (macio_request_resource(mdev, 0, "airport")) {
 		printk(KERN_ERR PFX "can't request IO resource !\n");
-		free_netdev(dev);
+		free_orinocodev(dev);
 		return -EBUSY;
 	}
 
@@ -224,16 +223,15 @@
 	/* Setup interrupts & base address */
 	dev->irq = macio_irq(mdev, 0);
 	phys_addr = macio_resource_start(mdev, 0);  /* Physical address */
-	printk(KERN_DEBUG PFX "Airport at physical address %lx\n", phys_addr);
+	printk(KERN_DEBUG PFX "Physical address %lx\n", phys_addr);
 	dev->base_addr = phys_addr;
 	card->vaddr = ioremap(phys_addr, AIRPORT_IO_LEN);
 	if (!card->vaddr) {
-		printk(PFX "ioremap() failed\n");
+		printk(KERN_ERR PFX "ioremap() failed\n");
 		goto failed;
 	}
 
-	hermes_struct_init(hw, (ulong)card->vaddr,
-			HERMES_MEM, HERMES_16BIT_REGSPACING);
+	hermes_struct_init(hw, card->vaddr, HERMES_16BIT_REGSPACING);
 		
 	/* Power up card */
 	pmac_call_feature(PMAC_FTR_AIRPORT_ENABLE, macio_get_of_node(mdev), 0, 1);
@@ -242,7 +240,7 @@
 	/* Reset it before we get the interrupt */
 	hermes_init(hw);
 
-	if (request_irq(dev->irq, orinoco_interrupt, 0, "Airport", dev)) {
+	if (request_irq(dev->irq, orinoco_interrupt, 0, dev->name, dev)) {
 		printk(KERN_ERR PFX "Couldn't get IRQ %d\n", dev->irq);
 		goto failed;
 	}
@@ -253,7 +251,7 @@
 		printk(KERN_ERR PFX "register_netdev() failed\n");
 		goto failed;
 	}
-	printk(KERN_DEBUG PFX "card registered for interface %s\n", dev->name);
+	printk(KERN_DEBUG PFX "Card registered for interface %s\n", dev->name);
 	card->ndev_registered = 1;
 	return 0;
  failed:
diff -Nru a/drivers/net/wireless/arlan.h b/drivers/net/wireless/arlan.h
--- a/drivers/net/wireless/arlan.h	2005-03-11 12:51:46 -08:00
+++ b/drivers/net/wireless/arlan.h	2005-03-11 12:51:46 -08:00
@@ -43,8 +43,8 @@
 extern int init_arlan_proc(void);
 extern void cleanup_arlan_proc(void);
 #else
-#define init_arlan_proc()	(0)
-#define cleanup_arlan_proc()	do { } while (0);
+#define init_arlan_proc()	({ 0; })
+#define cleanup_arlan_proc()	do { } while (0)
 #endif
 
 extern struct net_device *arlan_device[MAX_ARLANS];
diff -Nru a/drivers/net/wireless/atmel.c b/drivers/net/wireless/atmel.c
--- a/drivers/net/wireless/atmel.c	2005-03-11 12:51:42 -08:00
+++ b/drivers/net/wireless/atmel.c	2005-03-11 12:51:42 -08:00
@@ -69,6 +69,7 @@
 #include <linux/moduleparam.h>
 #include <linux/firmware.h>
 #include "ieee802_11.h"
+#include "atmel.h"
 
 #define DRIVER_MAJOR 0
 #define DRIVER_MINOR 96
@@ -83,6 +84,23 @@
 static char *firmware = NULL;
 module_param(firmware, charp, 0);
 
+/* table of firmware file names */
+static struct { 
+	AtmelFWType fw_type;
+	const char *fw_file;
+	const char *fw_file_ext;
+} fw_table[] = {
+	{ ATMEL_FW_TYPE_502,      "atmel_at76c502",      "bin" },
+	{ ATMEL_FW_TYPE_502D,     "atmel_at76c502d",     "bin" },
+	{ ATMEL_FW_TYPE_502E,     "atmel_at76c502e",     "bin" },
+	{ ATMEL_FW_TYPE_502_3COM, "atmel_at76c502_3com", "bin" },
+	{ ATMEL_FW_TYPE_504,      "atmel_at76c504",      "bin" },
+	{ ATMEL_FW_TYPE_504_2958, "atmel_at76c504_2958", "bin" },
+	{ ATMEL_FW_TYPE_504A_2958,"atmel_at76c504a_2958","bin" },
+	{ ATMEL_FW_TYPE_506,      "atmel_at76c506",      "bin" },
+	{ ATMEL_FW_TYPE_NONE,      NULL,                  NULL }
+};
+
 #define MAX_SSID_LENGTH 32
 #define MGMT_JIFFIES (256 * HZ / 100)
 
@@ -458,8 +476,8 @@
 	void *card; /* Bus dependent stucture varies for PCcard */
 	int (*present_callback)(void *); /* And callback which uses it */
 	char firmware_id[32];
-	char firmware_template[32];
-	unsigned char *firmware;
+	AtmelFWType firmware_type;
+	u8 *firmware;
 	int firmware_length;
 	struct timer_list management_timer;
 	struct net_device *dev;
@@ -1293,17 +1311,21 @@
 	if (priv->operating_mode == IW_MODE_INFRA) {
 		if (priv->station_state != STATION_STATE_READY) {
 			priv->wstats.qual.qual = 0;
-			priv->wstats.qual.level	= 0;
+			priv->wstats.qual.level = 0;
+			priv->wstats.qual.updated = (IW_QUAL_QUAL_INVALID
+					| IW_QUAL_LEVEL_INVALID);
 		}
 		priv->wstats.qual.noise = 0;
-		priv->wstats.qual.updated = 7;
+		priv->wstats.qual.updated |= IW_QUAL_NOISE_INVALID;
 	} else {
 		/* Quality levels cannot be determined in ad-hoc mode,
 		   because we can 'hear' more that one remote station. */
 		priv->wstats.qual.qual = 0;
 		priv->wstats.qual.level	= 0;
 		priv->wstats.qual.noise	= 0;
-		priv->wstats.qual.updated = 0;
+		priv->wstats.qual.updated = IW_QUAL_QUAL_INVALID
+					| IW_QUAL_LEVEL_INVALID
+					| IW_QUAL_NOISE_INVALID;
 		priv->wstats.miss.beacon = 0;
 	}
 	
@@ -1482,7 +1504,7 @@
         return len;
 }
 
-struct net_device *init_atmel_card( unsigned short irq, int port, char *firmware_id,  
+struct net_device *init_atmel_card( unsigned short irq, int port, const AtmelFWType fw_type,  
 				    struct device *sys_dev, int (*card_present)(void *), void *card)
 {
 	struct net_device *dev;
@@ -1507,11 +1529,9 @@
 	priv->card = card;
 	priv->firmware = NULL;
 	priv->firmware_id[0] = '\0';
-	priv->firmware_template[0] = '\0';
+	priv->firmware_type = fw_type;
 	if (firmware) /* module parameter */
 		strcpy(priv->firmware_id, firmware);
-	else if (firmware_id) /* from PCMCIA card-matching or PCI */
-		strcpy(priv->firmware_template, firmware_id);
 	priv->bus_type = card_present ? BUS_TYPE_PCCARD : BUS_TYPE_PCI;
 	priv->station_state = STATION_STATE_DOWN;
 	priv->do_rx_crc = 0;
@@ -1579,6 +1599,8 @@
 	dev->irq = irq;
 	dev->base_addr = port;
 	
+	SET_NETDEV_DEV(dev, sys_dev);
+	
 	if ((rc = request_irq(dev->irq, service_interrupt, SA_SHIRQ, dev->name, dev))) {
 		printk(KERN_ERR "%s: register interrupt %d failed, rc %d\n", dev->name, irq, rc );
 		goto err_out_free;
@@ -2218,6 +2240,13 @@
 	range->max_qual.qual = 100;
 	range->max_qual.level = 100;
 	range->max_qual.noise = 0;
+	range->max_qual.updated = IW_QUAL_NOISE_INVALID;
+
+	range->avg_qual.qual = 50;
+	range->avg_qual.level = 50;
+	range->avg_qual.noise = 0;
+	range->avg_qual.updated = IW_QUAL_NOISE_INVALID;
+
 	range->sensitivity = 0;
 
 	range->bitrate[0] =  1000000;
@@ -2247,9 +2276,6 @@
 	range->r_time_flags = 0;
 	range->min_retry = 1;
 	range->max_retry = 65535;
-	range->avg_qual.qual = 50;
-	range->avg_qual.level = 50;
-	range->avg_qual.noise = 0;
 
 	return 0;
 }
@@ -3025,16 +3051,23 @@
 static void smooth_rssi(struct atmel_private *priv, u8 rssi)
 {
 	u8 old = priv->wstats.qual.level;
+	u8 max_rssi = 42; /* 502-rmfd-revd max by experiment, default for now */
 
-	/* 502-rmfd-revd gives max signal level as 42, by experiment.
-	   This is going to break for other hardware variants. */
+	switch (priv->firmware_type) {
+		case ATMEL_FW_TYPE_502E:
+			max_rssi = 63; /* 502-rmfd-reve max by experiment */
+			break;
+		default:
+			break;
+	}
 
-	rssi = rssi * 100 / 42;
+	rssi = rssi * 100 / max_rssi;
 	if((rssi + old) % 2)
 		priv->wstats.qual.level =  ((rssi + old)/2) + 1;
 	else
 		priv->wstats.qual.level =  ((rssi + old)/2);		
-	
+	priv->wstats.qual.updated |= IW_QUAL_LEVEL_UPDATED;
+	priv->wstats.qual.updated &= ~IW_QUAL_LEVEL_INVALID;
 }
 
 static void atmel_smooth_qual(struct atmel_private *priv)
@@ -3047,8 +3080,10 @@
 			priv->beacons_this_sec * priv->beacon_period * (priv->wstats.qual.level + 100) / 4000;
 		priv->beacons_this_sec = 0;
 	}
+	priv->wstats.qual.updated |= IW_QUAL_QUAL_UPDATED;
+	priv->wstats.qual.updated &= ~IW_QUAL_QUAL_INVALID;
 }
-	
+
 /* deals with incoming managment frames. */
 static void atmel_management_frame(struct atmel_private *priv, struct ieee802_11_hdr *header, 
 		      u16 frame_len, u8 rssi)
@@ -3611,8 +3646,8 @@
 		const struct firmware *fw_entry = NULL;
 		unsigned char *fw;
 		int len = priv->firmware_length;
-		if (!(fw = priv->firmware)) { 
-			if (strlen(priv->firmware_template) == 0) {	
+		if (!(fw = priv->firmware)) {
+			if (priv->firmware_type == ATMEL_FW_TYPE_NONE) {
 				if (strlen(priv->firmware_id) == 0) {
 					printk(KERN_INFO
 					       "%s: card type is unknown: assuming at76c502 firmware is OK.\n",
@@ -3627,24 +3662,36 @@
 					       "%s: firmware %s is missing, cannot continue.\n", 
 					       dev->name, priv->firmware_id);
 					return 0;
-					
-				} 
+				}
 			} else {
-				int i;
+				int fw_index = 0;
+				int success = 0;
+
+				/* get firmware filename entry based on firmware type ID */
+				while (fw_table[fw_index].fw_type != priv->firmware_type
+						&& fw_table[fw_index].fw_type != ATMEL_FW_TYPE_NONE)
+					fw_index++;
 				
-				for (i = 0; firmware_modifier[i]; i++) {
-					sprintf(priv->firmware_id, priv->firmware_template, firmware_modifier[i]);
-					if (request_firmware(&fw_entry, priv->firmware_id, priv->sys_dev) == 0) 
-						break;
+				/* construct the actual firmware file name */
+				if (fw_table[fw_index].fw_type != ATMEL_FW_TYPE_NONE) {
+					int i;
+					for (i = 0; firmware_modifier[i]; i++) {
+						snprintf(priv->firmware_id, 32, "%s%s.%s", fw_table[fw_index].fw_file,
+							firmware_modifier[i], fw_table[fw_index].fw_file_ext);
+						priv->firmware_id[31] = '\0';
+						if (request_firmware(&fw_entry, priv->firmware_id, priv->sys_dev) == 0) {
+							success = 1;
+							break;
+						}
+					}
 				}
-				if (!firmware_modifier[i]) {
+				if (!success) {
 					printk(KERN_ALERT 
 					       "%s: firmware %s is missing, cannot start.\n", 
 					       dev->name, priv->firmware_id);
 					priv->firmware_id[0] = '\0';
 					return 0;	
 				}
-				priv->firmware_template[0] = '\0';	
 			}
 			
 			fw = fw_entry->data;
diff -Nru a/drivers/net/wireless/atmel.h b/drivers/net/wireless/atmel.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/net/wireless/atmel.h	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,43 @@
+/*** -*- linux-c -*- **********************************************************
+
+     Driver for Atmel at76c502 at76c504 and at76c506 wireless cards.
+
+         Copyright 2005 Dan Williams and Red Hat, Inc.
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This software is 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 Atmel wireless lan drivers; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+******************************************************************************/
+
+#ifndef _ATMEL_H
+#define _ATMEL_H
+
+typedef enum {
+	ATMEL_FW_TYPE_NONE = 0,
+	ATMEL_FW_TYPE_502,
+	ATMEL_FW_TYPE_502D,
+	ATMEL_FW_TYPE_502E,
+	ATMEL_FW_TYPE_502_3COM,
+	ATMEL_FW_TYPE_504,
+	ATMEL_FW_TYPE_504_2958,
+	ATMEL_FW_TYPE_504A_2958,
+	ATMEL_FW_TYPE_506
+} AtmelFWType;
+
+struct net_device *init_atmel_card(unsigned short, int, const AtmelFWType, struct device *, 
+				    int (*present_func)(void *), void * );
+void stop_atmel_card( struct net_device *, int );
+int atmel_open( struct net_device * );
+
+#endif
diff -Nru a/drivers/net/wireless/atmel_cs.c b/drivers/net/wireless/atmel_cs.c
--- a/drivers/net/wireless/atmel_cs.c	2005-03-11 12:51:46 -08:00
+++ b/drivers/net/wireless/atmel_cs.c	2005-03-11 12:51:46 -08:00
@@ -55,6 +55,7 @@
 #include <asm/system.h>
 #include <linux/wireless.h>
 
+#include "atmel.h"
 
 /*
    All the PCMCIA modules use PCMCIA_DEBUG to control debugging.  If
@@ -90,11 +91,6 @@
    event handler. 
 */
 
-struct net_device *init_atmel_card(int, int, char *, struct device *, 
-				    int (*present_func)(void *), void * );
-void stop_atmel_card( struct net_device *, int );
-int atmel_open( struct net_device * );
-
 static void atmel_config(dev_link_t *link);
 static void atmel_release(dev_link_t *link);
 static int atmel_event(event_t event, int priority,
@@ -307,28 +303,29 @@
 static struct { 
 	int manf, card;
 	char *ver1;
-	char *firmware;
+	AtmelFWType firmware;
 	char *name;
 } card_table[] = {
-	{ 0, 0, "WLAN/802.11b PC CARD", "atmel_at76c502d%s.bin", "Actiontec 802CAT1" },  
-	{ 0, 0, "ATMEL/AT76C502AR", "atmel_at76c502%s.bin", "NoName-RFMD" }, 
-	{ 0, 0, "ATMEL/AT76C502AR_D", "atmel_at76c502d%s.bin", "NoName-revD" }, 
-	{ 0, 0, "ATMEL/AT76C502AR_E", "atmel_at76c502e%s.bin", "NoName-revE" },
-	{ 0, 0, "ATMEL/AT76C504", "atmel_at76c504%s.bin", "NoName-504" },
-	{ 0, 0, "ATMEL/AT76C504A", "atmel_at76c504a_2958%s.bin", "NoName-504a-2958" },
-	{ 0, 0, "ATMEL/AT76C504_R", "atmel_at76c504_2958%s.bin", "NoName-504-2958" },
-	{ MANFID_3COM, 0x0620, NULL, "atmel_at76c502_3com%s.bin", "3com 3CRWE62092B" }, 
-	{ MANFID_3COM, 0x0696, NULL, "atmel_at76c502_3com%s.bin", "3com 3CRSHPW196" }, 
-	{ 0, 0, "SMC/2632W-V2", "atmel_at76c502%s.bin", "SMC 2632W-V2" },
-        { 0, 0, "SMC/2632W", "atmel_at76c502d%s.bin", "SMC 2632W-V3" },
-	{ 0xd601, 0x0007, NULL, "atmel_at76c502%s.bin", "Sitecom WLAN-011" }, 
-	{ 0x01bf, 0x3302, NULL, "atmel_at76c502e%s.bin", "Belkin F5D6020-V2" }, 
-	{ 0, 0, "BT/Voyager 1020 Laptop Adapter", "atmel_at76c502%s.bin", "BT Voyager 1020" },
-        { 0, 0, "IEEE 802.11b/Wireless LAN PC Card", "atmel_at76c502%s.bin", "Siemens Gigaset PC Card II" },
-	{ 0, 0, "CNet/CNWLC 11Mbps Wireless PC Card V-5", "atmel_at76c502e%s.bin", "CNet CNWLC-811ARL" },
-	{ 0, 0, "Wireless/PC_CARD", "atmel_at76c502d%s.bin", "Planet WL-3552" },
-	{ 0, 0, "OEM/11Mbps Wireless LAN PC Card V-3", "atmel_at76c502%s.bin", "OEM 11Mbps WLAN PCMCIA Card" },
-	{ 0, 0, "11WAVE/11WP611AL-E", "atmel_at76c502e%s.bin", "11WAVE WaveBuddy" } 
+	{ 0, 0, "WLAN/802.11b PC CARD", ATMEL_FW_TYPE_502D, "Actiontec 802CAT1" },  
+	{ 0, 0, "ATMEL/AT76C502AR", ATMEL_FW_TYPE_502, "NoName-RFMD" }, 
+	{ 0, 0, "ATMEL/AT76C502AR_D", ATMEL_FW_TYPE_502D, "NoName-revD" }, 
+	{ 0, 0, "ATMEL/AT76C502AR_E", ATMEL_FW_TYPE_502E, "NoName-revE" },
+	{ 0, 0, "ATMEL/AT76C504", ATMEL_FW_TYPE_504, "NoName-504" },
+	{ 0, 0, "ATMEL/AT76C504A", ATMEL_FW_TYPE_504A_2958, "NoName-504a-2958" },
+	{ 0, 0, "ATMEL/AT76C504_R", ATMEL_FW_TYPE_504_2958, "NoName-504-2958" },
+	{ MANFID_3COM, 0x0620, NULL, ATMEL_FW_TYPE_502_3COM, "3com 3CRWE62092B" }, 
+	{ MANFID_3COM, 0x0696, NULL, ATMEL_FW_TYPE_502_3COM, "3com 3CRSHPW196" }, 
+	{ 0, 0, "SMC/2632W-V2", ATMEL_FW_TYPE_502, "SMC 2632W-V2" },
+	{ 0, 0, "SMC/2632W", ATMEL_FW_TYPE_502D, "SMC 2632W-V3" },
+	{ 0xd601, 0x0007, NULL, ATMEL_FW_TYPE_502, "Sitecom WLAN-011" }, 
+	{ 0x01bf, 0x3302, NULL, ATMEL_FW_TYPE_502E, "Belkin F5D6020-V2" }, 
+	{ 0, 0, "BT/Voyager 1020 Laptop Adapter", ATMEL_FW_TYPE_502, "BT Voyager 1020" },
+	{ 0, 0, "IEEE 802.11b/Wireless LAN PC Card", ATMEL_FW_TYPE_502, "Siemens Gigaset PC Card II" },
+	{ 0, 0, "CNet/CNWLC 11Mbps Wireless PC Card V-5", ATMEL_FW_TYPE_502E, "CNet CNWLC-811ARL" },
+	{ 0, 0, "Wireless/PC_CARD", ATMEL_FW_TYPE_502D, "Planet WL-3552" },
+	{ 0, 0, "OEM/11Mbps Wireless LAN PC Card V-3", ATMEL_FW_TYPE_502, "OEM 11Mbps WLAN PCMCIA Card" },
+	{ 0, 0, "11WAVE/11WP611AL-E", ATMEL_FW_TYPE_502E, "11WAVE WaveBuddy" },
+	{ 0, 0, "LG/LW2100N", ATMEL_FW_TYPE_502E, "LG LW2100N 11Mbps WLAN PCMCIA Card" },
 };
 
 static void atmel_config(dev_link_t *link)
@@ -520,7 +517,7 @@
 	((local_info_t*)link->priv)->eth_dev = 
 		init_atmel_card(link->irq.AssignedIRQ,
 				link->io.BasePort1,
-				card_index == -1 ? NULL :  card_table[card_index].firmware,
+				card_index == -1 ? ATMEL_FW_TYPE_NONE :  card_table[card_index].firmware,
 				&handle_to_dev(handle),
 				card_present, 
 				link);
diff -Nru a/drivers/net/wireless/atmel_pci.c b/drivers/net/wireless/atmel_pci.c
--- a/drivers/net/wireless/atmel_pci.c	2005-03-11 12:51:47 -08:00
+++ b/drivers/net/wireless/atmel_pci.c	2005-03-11 12:51:47 -08:00
@@ -25,6 +25,7 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/netdevice.h>
+#include "atmel.h"
 
 MODULE_AUTHOR("Simon Kelley");
 MODULE_DESCRIPTION("Support for Atmel at76c50x 802.11 wireless ethernet cards.");
@@ -40,9 +41,6 @@
 
 static int atmel_pci_probe(struct pci_dev *, const struct pci_device_id *);
 static void atmel_pci_remove(struct pci_dev *);
-struct net_device *init_atmel_card(int, int, char *, struct device *, 
-				   int (*present_func)(void *), void * );
-void stop_atmel_card( struct net_device *, int );
 
 static struct pci_driver atmel_driver = {
 	.name     = "atmel",
@@ -63,7 +61,7 @@
 	pci_set_master(pdev);
 	
 	dev = init_atmel_card(pdev->irq, pdev->resource[1].start, 
-			      "atmel_at76c506%s.bin",
+			      ATMEL_FW_TYPE_506,
 			      &pdev->dev, NULL, NULL);
 	if (!dev)
 		return -ENODEV;
diff -Nru a/drivers/net/wireless/hermes.c b/drivers/net/wireless/hermes.c
--- a/drivers/net/wireless/hermes.c	2005-03-11 12:51:41 -08:00
+++ b/drivers/net/wireless/hermes.c	2005-03-11 12:51:41 -08:00
@@ -48,6 +48,7 @@
 #include <linux/delay.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
+#include <linux/net.h>
 #include <asm/errno.h>
 
 #include "hermes.h"
@@ -67,8 +68,7 @@
  * Debugging helpers
  */
 
-#define IO_TYPE(hw)	((hw)->io_space ? "IO " : "MEM ")
-#define DMSG(stuff...) do {printk(KERN_DEBUG "hermes @ %s0x%x: " , IO_TYPE(hw), hw->iobase); \
+#define DMSG(stuff...) do {printk(KERN_DEBUG "hermes @ %p: " , hw->iobase); \
 			printk(stuff);} while (0)
 
 #undef HERMES_DEBUG
@@ -123,11 +123,9 @@
  * Function definitions
  */
 
-void hermes_struct_init(hermes_t *hw, ulong address,
-			int io_space, int reg_spacing)
+void hermes_struct_init(hermes_t *hw, void __iomem *address, int reg_spacing)
 {
 	hw->iobase = address;
-	hw->io_space = io_space;
 	hw->reg_spacing = reg_spacing;
 	hw->inten = 0x0;
 
@@ -200,9 +198,9 @@
 	}
 		
 	if (! (reg & HERMES_EV_CMD)) {
-		printk(KERN_ERR "hermes @ %s0x%lx: " 
+		printk(KERN_ERR "hermes @ %p: " 
 		       "Timeout waiting for card to reset (reg=0x%04x)!\n",
-		       IO_TYPE(hw), hw->iobase, reg);
+		       hw->iobase, reg);
 		err = -ETIMEDOUT;
 		goto out;
 	}
@@ -235,13 +233,16 @@
 	err = hermes_issue_cmd(hw, cmd, parm0);
 	if (err) {
 		if (! hermes_present(hw)) {
-			printk(KERN_WARNING "hermes @ %s0x%lx: "
-			       "Card removed while issuing command.\n",
-			       IO_TYPE(hw), hw->iobase);
+			if (net_ratelimit())
+				printk(KERN_WARNING "hermes @ %p: "
+				       "Card removed while issuing command "
+				       "0x%04x.\n", hw->iobase, cmd);
 			err = -ENODEV;
 		} else 
-			printk(KERN_ERR "hermes @ %s0x%lx: Error %d issuing command.\n",
-			       IO_TYPE(hw), hw->iobase, err);
+			if (net_ratelimit())
+				printk(KERN_ERR "hermes @ %p: "
+				       "Error %d issuing command 0x%04x.\n",
+				       hw->iobase, err, cmd);
 		goto out;
 	}
 
@@ -254,17 +255,16 @@
 	}
 
 	if (! hermes_present(hw)) {
-		printk(KERN_WARNING "hermes @ %s0x%lx: "
-		       "Card removed while waiting for command completion.\n",
-		       IO_TYPE(hw), hw->iobase);
+		printk(KERN_WARNING "hermes @ %p: Card removed "
+		       "while waiting for command 0x%04x completion.\n",
+		       hw->iobase, cmd);
 		err = -ENODEV;
 		goto out;
 	}
 		
 	if (! (reg & HERMES_EV_CMD)) {
-		printk(KERN_ERR "hermes @ %s0x%lx: "
-		       "Timeout waiting for command completion.\n",
-		       IO_TYPE(hw), hw->iobase);
+		printk(KERN_ERR "hermes @ %p: Timeout waiting for "
+		       "command 0x%04x completion.\n", hw->iobase, cmd);
 		err = -ETIMEDOUT;
 		goto out;
 	}
@@ -309,16 +309,16 @@
 	}
 	
 	if (! hermes_present(hw)) {
-		printk(KERN_WARNING "hermes @ %s0x%lx: "
+		printk(KERN_WARNING "hermes @ %p: "
 		       "Card removed waiting for frame allocation.\n",
-		       IO_TYPE(hw), hw->iobase);
+		       hw->iobase);
 		return -ENODEV;
 	}
 		
 	if (! (reg & HERMES_EV_ALLOC)) {
-		printk(KERN_ERR "hermes @ %s0x%lx: "
+		printk(KERN_ERR "hermes @ %p: "
 		       "Timeout waiting for frame allocation\n",
-		       IO_TYPE(hw), hw->iobase);
+		       hw->iobase);
 		return -ETIMEDOUT;
 	}
 
@@ -383,12 +383,17 @@
 		reg = hermes_read_reg(hw, oreg);
 	}
 
-	if (reg & HERMES_OFFSET_BUSY) {
-		return -ETIMEDOUT;
-	}
+	if (reg != offset) {
+		printk(KERN_ERR "hermes @ %p: BAP%d offset %s: "
+		       "reg=0x%x id=0x%x offset=0x%x\n", hw->iobase, bap,
+		       (reg & HERMES_OFFSET_BUSY) ? "timeout" : "error",
+		       reg, id, offset);
+
+		if (reg & HERMES_OFFSET_BUSY) {
+			return -ETIMEDOUT;
+		}
 
-	if (reg & HERMES_OFFSET_ERR) {
-		return -EIO;
+		return -EIO;		/* error or wrong offset */
 	}
 
 	return 0;
@@ -476,7 +481,7 @@
 	rlength = hermes_read_reg(hw, dreg);
 
 	if (! rlength)
-		return -ENOENT;
+		return -ENODATA;
 
 	rtype = hermes_read_reg(hw, dreg);
 
@@ -484,14 +489,13 @@
 		*length = rlength;
 
 	if (rtype != rid)
-		printk(KERN_WARNING "hermes @ %s0x%lx: "
-		       "hermes_read_ltv(): rid  (0x%04x) does not match type (0x%04x)\n",
-		       IO_TYPE(hw), hw->iobase, rid, rtype);
+		printk(KERN_WARNING "hermes @ %p: %s(): "
+		       "rid (0x%04x) does not match type (0x%04x)\n",
+		       hw->iobase, __FUNCTION__, rid, rtype);
 	if (HERMES_RECLEN_TO_BYTES(rlength) > bufsize)
-		printk(KERN_WARNING "hermes @ %s0x%lx: "
+		printk(KERN_WARNING "hermes @ %p: "
 		       "Truncating LTV record from %d to %d bytes. "
-		       "(rid=0x%04x, len=0x%04x)\n",
-		       IO_TYPE(hw), hw->iobase,
+		       "(rid=0x%04x, len=0x%04x)\n", hw->iobase,
 		       HERMES_RECLEN_TO_BYTES(rlength), bufsize, rid, rlength);
 
 	nwords = min((unsigned)rlength - 1, bufsize / 2);
diff -Nru a/drivers/net/wireless/hermes.h b/drivers/net/wireless/hermes.h
--- a/drivers/net/wireless/hermes.h	2005-03-11 12:51:41 -08:00
+++ b/drivers/net/wireless/hermes.h	2005-03-11 12:51:41 -08:00
@@ -340,14 +340,11 @@
 #ifdef __KERNEL__
 
 /* Timeouts */
-#define HERMES_BAP_BUSY_TIMEOUT (500) /* In iterations of ~1us */
+#define HERMES_BAP_BUSY_TIMEOUT (10000) /* In iterations of ~1us */
 
 /* Basic control structure */
 typedef struct hermes {
-	unsigned long iobase;
-	int io_space; /* 1 if we IO-mapped IO, 0 for memory-mapped IO? */
-#define HERMES_IO	1
-#define HERMES_MEM	0
+	void __iomem *iobase;
 	int reg_spacing;
 #define HERMES_16BIT_REGSPACING	0
 #define HERMES_32BIT_REGSPACING	1
@@ -362,21 +359,15 @@
 } hermes_t;
 
 /* Register access convenience macros */
-#define hermes_read_reg(hw, off) ((hw)->io_space ? \
-	inw((hw)->iobase + ( (off) << (hw)->reg_spacing )) : \
-	readw((hw)->iobase + ( (off) << (hw)->reg_spacing )))
-#define hermes_write_reg(hw, off, val) do { \
-	if ((hw)->io_space) \
-		outw_p((val), (hw)->iobase + ((off) << (hw)->reg_spacing)); \
-	else \
-		writew((val), (hw)->iobase + ((off) << (hw)->reg_spacing)); \
-	} while (0)
+#define hermes_read_reg(hw, off) \
+	(ioread16((hw)->iobase + ( (off) << (hw)->reg_spacing )))
+#define hermes_write_reg(hw, off, val) \
+	(iowrite16((val), (hw)->iobase + ((off) << (hw)->reg_spacing)))
 #define hermes_read_regn(hw, name) hermes_read_reg((hw), HERMES_##name)
 #define hermes_write_regn(hw, name, val) hermes_write_reg((hw), HERMES_##name, (val))
 
 /* Function prototypes */
-void hermes_struct_init(hermes_t *hw, ulong address, int io_space,
-			int reg_spacing);
+void hermes_struct_init(hermes_t *hw, void __iomem *address, int reg_spacing);
 int hermes_init(hermes_t *hw);
 int hermes_docmd_wait(hermes_t *hw, u16 cmd, u16 parm0,
 		      struct hermes_response *resp);
@@ -430,41 +421,13 @@
 static inline void hermes_read_words(struct hermes *hw, int off, void *buf, unsigned count)
 {
 	off = off << hw->reg_spacing;
-
-	if (hw->io_space) {
-		insw(hw->iobase + off, buf, count);
-	} else {
-		unsigned i;
-		u16 *p;
-
-		/* This needs to *not* byteswap (like insw()) but
-		 * readw() does byteswap hence the conversion.  I hope
-		 * gcc is smart enough to fold away the two swaps on
-		 * big-endian platforms. */
-		for (i = 0, p = buf; i < count; i++) {
-			*p++ = cpu_to_le16(readw(hw->iobase + off));
-		}
-	}
+	ioread16_rep(hw->iobase + off, buf, count);
 }
 
 static inline void hermes_write_words(struct hermes *hw, int off, const void *buf, unsigned count)
 {
 	off = off << hw->reg_spacing;
-
-	if (hw->io_space) {
-		outsw(hw->iobase + off, buf, count);
-	} else {
-		unsigned i;
-		const u16 *p;
-
-		/* This needs to *not* byteswap (like outsw()) but
-		 * writew() does byteswap hence the conversion.  I
-		 * hope gcc is smart enough to fold away the two swaps
-		 * on big-endian platforms. */
-		for (i = 0, p = buf; i < count; i++) {
-			writew(le16_to_cpu(*p++), hw->iobase + off);
-		}
-	}
+	iowrite16_rep(hw->iobase + off, buf, count);
 }
 
 static inline void hermes_clear_words(struct hermes *hw, int off, unsigned count)
@@ -473,13 +436,8 @@
 
 	off = off << hw->reg_spacing;
 
-	if (hw->io_space) {
-		for (i = 0; i < count; i++)
-			outw(0, hw->iobase + off);
-	} else {
-		for (i = 0; i < count; i++)
-			writew(0, hw->iobase + off);
-	}
+	for (i = 0; i < count; i++)
+		iowrite16(0, hw->iobase + off);
 }
 
 #define HERMES_READ_RECORD(hw, bap, rid, buf) \
diff -Nru a/drivers/net/wireless/orinoco.c b/drivers/net/wireless/orinoco.c
--- a/drivers/net/wireless/orinoco.c	2005-03-11 12:51:52 -08:00
+++ b/drivers/net/wireless/orinoco.c	2005-03-11 12:51:52 -08:00
@@ -393,6 +393,29 @@
  *	  in the rx_dropped statistics.
  *	o Provided a module parameter to suppress linkstatus messages.
  *
+ * v0.13e -> v0.14alpha1 - 30 Sep 2003 - David Gibson
+ *	o Replaced priv->connected logic with netif_carrier_on/off()
+ *	  calls.
+ *	o Remove has_ibss_any and never set the CREATEIBSS RID when
+ *	  the ESSID is empty.  Too many firmwares break if we do.
+ *	o 2.6 merges: Replace pdev->slot_name with pci_name(), remove
+ *	  __devinitdata from PCI ID tables, use free_netdev().
+ *	o Enabled shared-key authentication for Agere firmware (from
+ *	  Robert J. Moore <Robert.J.Moore AT allanbank.com>
+ *	o Move netif_wake_queue() (back) to the Tx completion from the
+ *	  ALLOC event.  This seems to prevent/mitigate the rolling
+ *	  error -110 problems at least on some Intersil firmwares.
+ *	  Theoretically reduces performance, but I can't measure it.
+ *	  Patch from Andrew Tridgell <tridge AT samba.org>
+ *
+ * v0.14alpha1 -> v0.14alpha2 - 20 Oct 2003 - David Gibson
+ *	o Correctly turn off shared-key authentication when requested
+ *	  (bugfix from Robert J. Moore).
+ *	o Correct airport sleep interfaces for current 2.6 kernels.
+ *	o Add code for key change without disabling/enabling the MAC
+ *	  port.  This is supposed to allow 802.1x to work sanely, but
+ *	  doesn't seem to yet.
+ *
  * TODO
  *	o New wireless extensions API (patch from Moustafa
  *	  Youssef, updated by Jim Carter and Pavel Roskin).
@@ -461,12 +484,14 @@
 /* Level of debugging. Used in the macros in orinoco.h */
 #ifdef ORINOCO_DEBUG
 int orinoco_debug = ORINOCO_DEBUG;
-module_param(orinoco_debug, int, 0);
+module_param(orinoco_debug, int, 0644);
+MODULE_PARM_DESC(orinoco_debug, "Debug level");
 EXPORT_SYMBOL(orinoco_debug);
 #endif
 
 static int suppress_linkstatus; /* = 0 */
-module_param(suppress_linkstatus, bool, 0);
+module_param(suppress_linkstatus, bool, 0644);
+MODULE_PARM_DESC(suppress_linkstatus, "Don't log link status changes");
 
 /********************************************************************/
 /* Compile time configuration and compatibility stuff               */
@@ -784,7 +809,7 @@
 		return 1;
 	}
 
-	if (! priv->connected) {
+	if (! netif_carrier_ok(dev)) {
 		/* Oops, the firmware hasn't established a connection,
                    silently drop the packet (this seems to be the
                    safest approach). */
@@ -805,8 +830,9 @@
  	desc.tx_control = cpu_to_le16(HERMES_TXCTRL_TX_OK | HERMES_TXCTRL_TX_EX);
 	err = hermes_bap_pwrite(hw, USER_BAP, &desc, sizeof(desc), txfid, 0);
 	if (err) {
-		printk(KERN_ERR "%s: Error %d writing Tx descriptor to BAP\n",
-		       dev->name, err);
+		if (net_ratelimit())
+			printk(KERN_ERR "%s: Error %d writing Tx descriptor "
+			       "to BAP\n", dev->name, err);
 		stats->tx_errors++;
 		goto fail;
 	}
@@ -836,8 +862,9 @@
 		err  = hermes_bap_pwrite(hw, USER_BAP, &hdr, sizeof(hdr),
 					 txfid, HERMES_802_3_OFFSET);
 		if (err) {
-			printk(KERN_ERR "%s: Error %d writing packet header to BAP\n",
-			       dev->name, err);
+			if (net_ratelimit())
+				printk(KERN_ERR "%s: Error %d writing packet "
+				       "header to BAP\n", dev->name, err);
 			stats->tx_errors++;
 			goto fail;
 		}
@@ -897,8 +924,6 @@
 			printk(KERN_WARNING "%s: Allocate event on unexpected fid (%04X)\n",
 			       dev->name, fid);
 		return;
-	} else {
-		netif_wake_queue(dev);
 	}
 
 	hermes_write_regn(hw, ALLOCFID, DUMMY_FID);
@@ -911,6 +936,8 @@
 
 	stats->tx_packets++;
 
+	netif_wake_queue(dev);
+
 	hermes_write_regn(hw, TXCOMPLFID, DUMMY_FID);
 }
 
@@ -937,6 +964,7 @@
 	
 	stats->tx_errors++;
 
+	netif_wake_queue(dev);
 	hermes_write_regn(hw, TXCOMPLFID, DUMMY_FID);
 }
 
@@ -962,15 +990,17 @@
 
 /* Does the frame have a SNAP header indicating it should be
  * de-encapsulated to Ethernet-II? */
-static inline int is_ethersnap(struct header_struct *hdr)
+static inline int is_ethersnap(void *_hdr)
 {
+	u8 *hdr = _hdr;
+
 	/* We de-encapsulate all packets which, a) have SNAP headers
 	 * (i.e. SSAP=DSAP=0xaa and CTRL=0x3 in the 802.2 LLC header
 	 * and where b) the OUI of the SNAP header is 00:00:00 or
 	 * 00:00:f8 - we need both because different APs appear to use
 	 * different OUIs for some reason */
-	return (memcmp(&hdr->dsap, &encaps_hdr, 5) == 0)
-		&& ( (hdr->oui[2] == 0x00) || (hdr->oui[2] == 0xf8) );
+	return (memcmp(hdr, &encaps_hdr, 5) == 0)
+		&& ( (hdr[5] == 0x00) || (hdr[5] == 0xf8) );
 }
 
 static inline void orinoco_spy_gather(struct net_device *dev, u_char *mac,
@@ -1269,6 +1299,7 @@
 	case HERMES_INQ_LINKSTATUS: {
 		struct hermes_linkstatus linkstatus;
 		u16 newstatus;
+		int connected;
 
 		if (len != sizeof(linkstatus)) {
 			printk(KERN_WARNING "%s: Unexpected size for linkstatus frame (%d bytes)\n",
@@ -1280,15 +1311,14 @@
 				  len / 2);
 		newstatus = le16_to_cpu(linkstatus.linkstatus);
 
-		if ( (newstatus == HERMES_LINKSTATUS_CONNECTED)
-		     || (newstatus == HERMES_LINKSTATUS_AP_CHANGE)
-		     || (newstatus == HERMES_LINKSTATUS_AP_IN_RANGE) )
-			priv->connected = 1;
-		else if ( (newstatus == HERMES_LINKSTATUS_NOT_CONNECTED)
-			  || (newstatus == HERMES_LINKSTATUS_DISCONNECTED)
-			  || (newstatus == HERMES_LINKSTATUS_AP_OUT_OF_RANGE)
-			  || (newstatus == HERMES_LINKSTATUS_ASSOC_FAILED) )
-			priv->connected = 0;
+		connected = (newstatus == HERMES_LINKSTATUS_CONNECTED)
+			|| (newstatus == HERMES_LINKSTATUS_AP_CHANGE)
+			|| (newstatus == HERMES_LINKSTATUS_AP_IN_RANGE);
+
+		if (connected)
+			netif_carrier_on(dev);
+		else
+			netif_carrier_off(dev);
 
 		if (newstatus != priv->last_linkstatus)
 			print_linkstatus(dev, newstatus);
@@ -1297,8 +1327,8 @@
 	}
 	break;
 	default:
-		printk(KERN_DEBUG "%s: Unknown information frame received "
-		       "(type %04x).\n", dev->name, type);
+		printk(KERN_DEBUG "%s: Unknown information frame received: "
+		       "type 0x%04x, length %d\n", dev->name, type, len);
 		/* We don't actually do anything about it */
 		break;
 	}
@@ -1307,7 +1337,7 @@
 static void __orinoco_ev_infdrop(struct net_device *dev, hermes_t *hw)
 {
 	if (net_ratelimit())
-		printk(KERN_WARNING "%s: Information frame lost.\n", dev->name);
+		printk(KERN_DEBUG "%s: Information frame lost.\n", dev->name);
 }
 
 /********************************************************************/
@@ -1366,8 +1396,8 @@
 	}
 	
 	/* firmware will have to reassociate */
+	netif_carrier_off(dev);
 	priv->last_linkstatus = 0xffff;
-	priv->connected = 0;
 
 	return 0;
 }
@@ -1430,55 +1460,46 @@
 	return err;
 }
 
-static int __orinoco_hw_setup_wep(struct orinoco_private *priv)
+/* Change the WEP keys and/or the current keys.  Can be called
+ * either from __orinoco_hw_setup_wep() or directly from
+ * orinoco_ioctl_setiwencode().  In the later case the association
+ * with the AP is not broken (if the firmware can handle it),
+ * which is needed for 802.1x implementations. */
+static int __orinoco_hw_setup_wepkeys(struct orinoco_private *priv)
 {
 	hermes_t *hw = &priv->hw;
 	int err = 0;
-	int	master_wep_flag;
-	int	auth_flag;
 
 	switch (priv->firmware_type) {
-	case FIRMWARE_TYPE_AGERE: /* Agere style WEP */
-		if (priv->wep_on) {
-			err = hermes_write_wordrec(hw, USER_BAP,
-						   HERMES_RID_CNFTXKEY_AGERE,
-						   priv->tx_key);
-			if (err)
-				return err;
-			
-			err = HERMES_WRITE_RECORD(hw, USER_BAP,
-						  HERMES_RID_CNFWEPKEYS_AGERE,
-						  &priv->keys);
-			if (err)
-				return err;
-		}
+	case FIRMWARE_TYPE_AGERE:
+		err = HERMES_WRITE_RECORD(hw, USER_BAP,
+					  HERMES_RID_CNFWEPKEYS_AGERE,
+					  &priv->keys);
+		if (err)
+			return err;
 		err = hermes_write_wordrec(hw, USER_BAP,
-					   HERMES_RID_CNFWEPENABLED_AGERE,
-					   priv->wep_on);
+					   HERMES_RID_CNFTXKEY_AGERE,
+					   priv->tx_key);
 		if (err)
 			return err;
 		break;
-
-	case FIRMWARE_TYPE_INTERSIL: /* Intersil style WEP */
-	case FIRMWARE_TYPE_SYMBOL: /* Symbol style WEP */
-		master_wep_flag = 0;		/* Off */
-		if (priv->wep_on) {
+	case FIRMWARE_TYPE_INTERSIL:
+	case FIRMWARE_TYPE_SYMBOL:
+		{
 			int keylen;
 			int i;
 
-			/* Fudge around firmware weirdness */
+			/* Force uniform key length to work around firmware bugs */
 			keylen = le16_to_cpu(priv->keys[priv->tx_key].len);
 			
+			if (keylen > LARGE_KEY_SIZE) {
+				printk(KERN_ERR "%s: BUG: Key %d has oversize length %d.\n",
+				       priv->ndev->name, priv->tx_key, keylen);
+				return -E2BIG;
+			}
+
 			/* Write all 4 keys */
 			for(i = 0; i < ORINOCO_MAX_KEYS; i++) {
-/*  				int keylen = le16_to_cpu(priv->keys[i].len); */
-				
-				if (keylen > LARGE_KEY_SIZE) {
-					printk(KERN_ERR "%s: BUG: Key %d has oversize length %d.\n",
-					       priv->ndev->name, i, keylen);
-					return -E2BIG;
-				}
-
 				err = hermes_write_ltv(hw, USER_BAP,
 						       HERMES_RID_CNFDEFAULTKEY0 + i,
 						       HERMES_BYTES_TO_RECLEN(keylen),
@@ -1493,27 +1514,63 @@
 						   priv->tx_key);
 			if (err)
 				return err;
-			
-			if (priv->wep_restrict) {
-				auth_flag = 2;
-				master_wep_flag = 3;
-			} else {
-				/* Authentication is where Intersil and Symbol
-				 * firmware differ... */
-				auth_flag = 1;
-				if (priv->firmware_type == FIRMWARE_TYPE_SYMBOL)
-					master_wep_flag = 3; /* Symbol */ 
-				else 
-					master_wep_flag = 1; /* Intersil */
-			}
+		}
+		break;
+	}
 
+	return 0;
+}
+
+static int __orinoco_hw_setup_wep(struct orinoco_private *priv)
+{
+	hermes_t *hw = &priv->hw;
+	int err = 0;
+	int master_wep_flag;
+	int auth_flag;
+
+	if (priv->wep_on)
+		__orinoco_hw_setup_wepkeys(priv);
+
+	if (priv->wep_restrict)
+		auth_flag = HERMES_AUTH_SHARED_KEY;
+	else
+		auth_flag = HERMES_AUTH_OPEN;
+
+	switch (priv->firmware_type) {
+	case FIRMWARE_TYPE_AGERE: /* Agere style WEP */
+		if (priv->wep_on) {
+			/* Enable the shared-key authentication. */
+			err = hermes_write_wordrec(hw, USER_BAP,
+						   HERMES_RID_CNFAUTHENTICATION_AGERE,
+						   auth_flag);
+		}
+		err = hermes_write_wordrec(hw, USER_BAP,
+					   HERMES_RID_CNFWEPENABLED_AGERE,
+					   priv->wep_on);
+		if (err)
+			return err;
+		break;
+
+	case FIRMWARE_TYPE_INTERSIL: /* Intersil style WEP */
+	case FIRMWARE_TYPE_SYMBOL: /* Symbol style WEP */
+		if (priv->wep_on) {
+			if (priv->wep_restrict ||
+			    (priv->firmware_type == FIRMWARE_TYPE_SYMBOL))
+				master_wep_flag = HERMES_WEP_PRIVACY_INVOKED |
+						  HERMES_WEP_EXCL_UNENCRYPTED;
+			else
+				master_wep_flag = HERMES_WEP_PRIVACY_INVOKED;
 
 			err = hermes_write_wordrec(hw, USER_BAP,
 						   HERMES_RID_CNFAUTHENTICATION,
 						   auth_flag);
 			if (err)
 				return err;
-		}
+		} else
+			master_wep_flag = 0;
+
+		if (priv->iw_mode == IW_MODE_MONITOR)
+			master_wep_flag |= HERMES_WEP_HOST_DECRYPT;
 
 		/* Master WEP setting : on/off */
 		err = hermes_write_wordrec(hw, USER_BAP,
@@ -1523,13 +1580,6 @@
 			return err;	
 
 		break;
-
-	default:
-		if (priv->wep_on) {
-			printk(KERN_ERR "%s: WEP enabled, although not supported!\n",
-			       priv->ndev->name);
-			return -EINVAL;
-		}
 	}
 
 	return 0;
@@ -1574,21 +1624,26 @@
 	}
 
 	if (priv->has_ibss) {
-		err = hermes_write_wordrec(hw, USER_BAP,
-					   HERMES_RID_CNFCREATEIBSS,
-					   priv->createibss);
-		if (err) {
-			printk(KERN_ERR "%s: Error %d setting CREATEIBSS\n", dev->name, err);
-			return err;
-		}
+		u16 createibss;
 
-		if ((strlen(priv->desired_essid) == 0) && (priv->createibss)
-		   && (!priv->has_ibss_any)) {
+		if ((strlen(priv->desired_essid) == 0) && (priv->createibss)) {
 			printk(KERN_WARNING "%s: This firmware requires an "
 			       "ESSID in IBSS-Ad-Hoc mode.\n", dev->name);
 			/* With wvlan_cs, in this case, we would crash.
 			 * hopefully, this driver will behave better...
 			 * Jean II */
+			createibss = 0;
+		} else {
+			createibss = priv->createibss;
+		}
+		
+		err = hermes_write_wordrec(hw, USER_BAP,
+					   HERMES_RID_CNFCREATEIBSS,
+					   createibss);
+		if (err) {
+			printk(KERN_ERR "%s: Error %d setting CREATEIBSS\n",
+			       dev->name, err);
+			return err;
 		}
 	}
 
@@ -1785,7 +1840,8 @@
 		}
 		
 		if (p)
-			printk(KERN_WARNING "Multicast list is longer than mc_count\n");
+			printk(KERN_WARNING "%s: Multicast list is "
+			       "longer than mc_count\n", dev->name);
 
 		err = hermes_write_ltv(hw, USER_BAP, HERMES_RID_CNFGROUPADDRESSES,
 				       HERMES_BYTES_TO_RECLEN(priv->mc_count * ETH_ALEN),
@@ -1878,7 +1934,7 @@
 
 	priv->hw_unavailable++;
 	priv->last_linkstatus = 0xffff; /* firmware will have to reassociate */
-	priv->connected = 0;
+	netif_carrier_off(dev);
 
 	orinoco_unlock(priv, &flags);
 
@@ -2014,51 +2070,81 @@
 /* Initialization                                                   */
 /********************************************************************/
 
-struct sta_id {
+struct comp_id {
 	u16 id, variant, major, minor;
 } __attribute__ ((packed));
 
-static int determine_firmware_type(struct net_device *dev, struct sta_id *sta_id)
+static inline fwtype_t determine_firmware_type(struct comp_id *nic_id)
 {
-	/* FIXME: this is fundamentally broken */
-	unsigned int firmver = ((u32)sta_id->major << 16) | sta_id->minor;
-	
-	if (sta_id->variant == 1)
+	if (nic_id->id < 0x8000)
 		return FIRMWARE_TYPE_AGERE;
-	else if ((sta_id->variant == 2) &&
-		   ((firmver == 0x10001) || (firmver == 0x20001)))
+	else if (nic_id->id == 0x8000 && nic_id->major == 0)
 		return FIRMWARE_TYPE_SYMBOL;
 	else
 		return FIRMWARE_TYPE_INTERSIL;
 }
 
-static void determine_firmware(struct net_device *dev)
+/* Set priv->firmware type, determine firmware properties */
+static int determine_firmware(struct net_device *dev)
 {
 	struct orinoco_private *priv = netdev_priv(dev);
 	hermes_t *hw = &priv->hw;
 	int err;
-	struct sta_id sta_id;
+	struct comp_id nic_id, sta_id;
 	unsigned int firmver;
 	char tmp[SYMBOL_MAX_VER_LEN+1];
 
+	/* Get the hardware version */
+	err = HERMES_READ_RECORD(hw, USER_BAP, HERMES_RID_NICID, &nic_id);
+	if (err) {
+		printk(KERN_ERR "%s: Cannot read hardware identity: error %d\n",
+		       dev->name, err);
+		return err;
+	}
+
+	le16_to_cpus(&nic_id.id);
+	le16_to_cpus(&nic_id.variant);
+	le16_to_cpus(&nic_id.major);
+	le16_to_cpus(&nic_id.minor);
+	printk(KERN_DEBUG "%s: Hardware identity %04x:%04x:%04x:%04x\n",
+	       dev->name, nic_id.id, nic_id.variant,
+	       nic_id.major, nic_id.minor);
+
+	priv->firmware_type = determine_firmware_type(&nic_id);
+
 	/* Get the firmware version */
 	err = HERMES_READ_RECORD(hw, USER_BAP, HERMES_RID_STAID, &sta_id);
 	if (err) {
-		printk(KERN_WARNING "%s: Error %d reading firmware info. Wildly guessing capabilities...\n",
+		printk(KERN_ERR "%s: Cannot read station identity: error %d\n",
 		       dev->name, err);
-		memset(&sta_id, 0, sizeof(sta_id));
+		return err;
 	}
 
 	le16_to_cpus(&sta_id.id);
 	le16_to_cpus(&sta_id.variant);
 	le16_to_cpus(&sta_id.major);
 	le16_to_cpus(&sta_id.minor);
-	printk(KERN_DEBUG "%s: Station identity %04x:%04x:%04x:%04x\n",
+	printk(KERN_DEBUG "%s: Station identity  %04x:%04x:%04x:%04x\n",
 	       dev->name, sta_id.id, sta_id.variant,
 	       sta_id.major, sta_id.minor);
 
-	if (! priv->firmware_type)
-		priv->firmware_type = determine_firmware_type(dev, &sta_id);
+	switch (sta_id.id) {
+	case 0x15:
+		printk(KERN_ERR "%s: Primary firmware is active\n",
+		       dev->name);
+		return -ENODEV;
+	case 0x14b:
+		printk(KERN_ERR "%s: Tertiary firmware is active\n",
+		       dev->name);
+		return -ENODEV;
+	case 0x1f:	/* Intersil, Agere, Symbol Spectrum24 */
+	case 0x21:	/* Symbol Spectrum24 Trilogy */
+		break;
+	default:
+		printk(KERN_NOTICE "%s: Unknown station ID, please report\n",
+		       dev->name);
+		break;
+	}
 
 	/* Default capabilities */
 	priv->has_sensitivity = 1;
@@ -2066,7 +2152,6 @@
 	priv->has_preamble = 0;
 	priv->has_port3 = 1;
 	priv->has_ibss = 1;
-	priv->has_ibss_any = 0;
 	priv->has_wep = 0;
 	priv->has_big_wep = 0;
 
@@ -2075,14 +2160,12 @@
 	case FIRMWARE_TYPE_AGERE:
 		/* Lucent Wavelan IEEE, Lucent Orinoco, Cabletron RoamAbout,
 		   ELSA, Melco, HP, IBM, Dell 1150, Compaq 110/210 */
-		printk(KERN_DEBUG "%s: Looks like a Lucent/Agere firmware "
-		       "version %d.%02d\n", dev->name,
-		       sta_id.major, sta_id.minor);
+		snprintf(priv->fw_name, sizeof(priv->fw_name) - 1,
+			 "Lucent/Agere %d.%02d", sta_id.major, sta_id.minor);
 
 		firmver = ((unsigned long)sta_id.major << 16) | sta_id.minor;
 
 		priv->has_ibss = (firmver >= 0x60006);
-		priv->has_ibss_any = (firmver >= 0x60010);
 		priv->has_wep = (firmver >= 0x40020);
 		priv->has_big_wep = 1; /* FIXME: this is wrong - how do we tell
 					  Gold cards from the others? */
@@ -2121,14 +2204,15 @@
 			tmp[SYMBOL_MAX_VER_LEN] = '\0';
 		}
 
-		printk(KERN_DEBUG "%s: Looks like a Symbol firmware "
-		       "version [%s] (parsing to %X)\n", dev->name,
-		       tmp, firmver);
+		snprintf(priv->fw_name, sizeof(priv->fw_name) - 1,
+			 "Symbol %s", tmp);
 
 		priv->has_ibss = (firmver >= 0x20000);
 		priv->has_wep = (firmver >= 0x15012);
 		priv->has_big_wep = (firmver >= 0x20000);
-		priv->has_pm = (firmver >= 0x20000) && (firmver < 0x22000);
+		priv->has_pm = (firmver >= 0x20000 && firmver < 0x22000) || 
+			       (firmver >= 0x29000 && firmver < 0x30000) ||
+			       firmver >= 0x31000;
 		priv->has_preamble = (firmver >= 0x20000);
 		priv->ibss_port = 4;
 		/* Tested with Intel firmware : 0x20015 => Jean II */
@@ -2140,9 +2224,9 @@
 		 * different and less well tested */
 		/* D-Link MAC : 00:40:05:* */
 		/* Addtron MAC : 00:90:D1:* */
-		printk(KERN_DEBUG "%s: Looks like an Intersil firmware "
-		       "version %d.%d.%d\n", dev->name,
-		       sta_id.major, sta_id.minor, sta_id.variant);
+		snprintf(priv->fw_name, sizeof(priv->fw_name) - 1,
+			 "Intersil %d.%d.%d", sta_id.major, sta_id.minor,
+			 sta_id.variant);
 
 		firmver = ((unsigned long)sta_id.major << 16) |
 			((unsigned long)sta_id.minor << 8) | sta_id.variant;
@@ -2160,9 +2244,11 @@
 			priv->ibss_port = 1;
 		}
 		break;
-	default:
-		break;
 	}
+	printk(KERN_DEBUG "%s: Firmware determined as %s\n", dev->name,
+	       priv->fw_name);
+
+	return 0;
 }
 
 static int orinoco_init(struct net_device *dev)
@@ -2188,7 +2274,12 @@
 		goto out;
 	}
 
-	determine_firmware(dev);
+	err = determine_firmware(dev);
+	if (err != 0) {
+		printk(KERN_ERR "%s: Incompatible firmware, aborting\n",
+		       dev->name);
+		goto out;
+	}
 
 	if (priv->has_port3)
 		printk(KERN_DEBUG "%s: Ad-hoc demo mode supported\n", dev->name);
@@ -2388,13 +2479,18 @@
 				   * hardware */
 	INIT_WORK(&priv->reset_work, (void (*)(void *))orinoco_reset, dev);
 
+	netif_carrier_off(dev);
 	priv->last_linkstatus = 0xffff;
-	priv->connected = 0;
 
 	return dev;
 
 }
 
+void free_orinocodev(struct net_device *dev)
+{
+	free_netdev(dev);
+}
+
 /********************************************************************/
 /* Wireless extensions                                              */
 /********************************************************************/
@@ -2686,11 +2782,17 @@
 	int err = 0;
 	char keybuf[ORINOCO_MAX_KEY_SIZE];
 	unsigned long flags;
-	
+
+	if (! priv->has_wep)
+		return -EOPNOTSUPP;
+
 	if (erq->pointer) {
-		/* We actually have a key to set */
-		if ( (erq->length < SMALL_KEY_SIZE) || (erq->length > ORINOCO_MAX_KEY_SIZE) )
-			return -EINVAL;
+		/* We actually have a key to set - check its length */
+		if (erq->length > LARGE_KEY_SIZE)
+			return -E2BIG;
+
+		if ( (erq->length > SMALL_KEY_SIZE) && !priv->has_big_wep )
+			return -E2BIG;
 		
 		if (copy_from_user(keybuf, erq->pointer, erq->length))
 			return -EFAULT;
@@ -2698,19 +2800,8 @@
 
 	if (orinoco_lock(priv, &flags) != 0)
 		return -EBUSY;
-	
+
 	if (erq->pointer) {
-		if (erq->length > ORINOCO_MAX_KEY_SIZE) {
-			err = -E2BIG;
-			goto out;
-		}
-		
-		if ( (erq->length > LARGE_KEY_SIZE)
-		     || ( ! priv->has_big_wep && (erq->length > SMALL_KEY_SIZE))  ) {
-			err = -EINVAL;
-			goto out;
-		}
-		
 		if ((index < 0) || (index >= ORINOCO_MAX_KEYS))
 			index = priv->tx_key;
 
@@ -2721,7 +2812,7 @@
 			xlen = SMALL_KEY_SIZE;
 		} else
 			xlen = 0;
-		
+
 		/* Switch on WEP if off */
 		if ((!enable) && (xlen > 0)) {
 			setindex = index;
@@ -2745,10 +2836,9 @@
 			setindex = index;
 		}
 	}
-	
+
 	if (erq->flags & IW_ENCODE_DISABLED)
 		enable = 0;
-	/* Only for Prism2 & Symbol cards (so far) - Jean II */
 	if (erq->flags & IW_ENCODE_OPEN)
 		restricted = 0;
 	if (erq->flags & IW_ENCODE_RESTRICTED)
@@ -2761,6 +2851,15 @@
 		memcpy(priv->keys[index].data, keybuf, erq->length);
 	}
 	priv->tx_key = setindex;
+
+	/* Try fast key change if connected and only keys are changed */
+	if (priv->wep_on && enable && (priv->wep_restrict == restricted) &&
+	    netif_carrier_ok(dev)) {
+		err = __orinoco_hw_setup_wepkeys(priv);
+		/* No need to commit if successful */
+		goto out;
+	}
+
 	priv->wep_on = enable;
 	priv->wep_restrict = restricted;
 
@@ -2778,6 +2877,9 @@
 	char keybuf[ORINOCO_MAX_KEY_SIZE];
 	unsigned long flags;
 
+	if (! priv->has_wep)
+		return -EOPNOTSUPP;
+
 	if (orinoco_lock(priv, &flags) != 0)
 		return -EBUSY;
 
@@ -2788,23 +2890,18 @@
 	if (! priv->wep_on)
 		erq->flags |= IW_ENCODE_DISABLED;
 	erq->flags |= index + 1;
-	
-	/* Only for symbol cards - Jean II */
-	if (priv->firmware_type != FIRMWARE_TYPE_AGERE) {
-		if(priv->wep_restrict)
-			erq->flags |= IW_ENCODE_RESTRICTED;
-		else
-			erq->flags |= IW_ENCODE_OPEN;
-	}
+
+	if (priv->wep_restrict)
+		erq->flags |= IW_ENCODE_RESTRICTED;
+	else
+		erq->flags |= IW_ENCODE_OPEN;
 
 	xlen = le16_to_cpu(priv->keys[index].len);
 
 	erq->length = xlen;
 
-	if (erq->pointer) {
-		memcpy(keybuf, priv->keys[index].data, ORINOCO_MAX_KEY_SIZE);
-	}
-	
+	memcpy(keybuf, priv->keys[index].data, ORINOCO_MAX_KEY_SIZE);
+
 	orinoco_unlock(priv, &flags);
 
 	if (erq->pointer) {
@@ -3045,8 +3142,9 @@
 			priv->mwo_robust = 0;
 		else {
 			if (frq->fixed)
-				printk(KERN_WARNING "%s: Fixed fragmentation not \
-supported on this firmware. Using MWO robust instead.\n", dev->name);
+				printk(KERN_WARNING "%s: Fixed fragmentation is "
+				       "not supported on this firmware. "
+				       "Using MWO robust instead.\n", dev->name);
 			priv->mwo_robust = 1;
 		}
 	} else {
@@ -3518,7 +3616,7 @@
 		}
 		/* Copy stats */
 		/* In theory, we should disable irqs while copying the stats
-		 * because the rx path migh update it in the middle...
+		 * because the rx path might update it in the middle...
 		 * Bah, who care ? - Jean II */
 		memcpy(&spy_stat, priv->spy_stat,
 		       sizeof(struct iw_quality) * IW_MAX_SPY);
@@ -3609,22 +3707,12 @@
 		break;
 
 	case SIOCSIWENCODE:
-		if (! priv->has_wep) {
-			err = -EOPNOTSUPP;
-			break;
-		}
-
 		err = orinoco_ioctl_setiwencode(dev, &wrq->u.encoding);
 		if (! err)
 			changed = 1;
 		break;
 
 	case SIOCGIWENCODE:
-		if (! priv->has_wep) {
-			err = -EOPNOTSUPP;
-			break;
-		}
-
 		if (! capable(CAP_NET_ADMIN)) {
 			err = -EPERM;
 			break;
@@ -4127,6 +4215,7 @@
 /********************************************************************/
 
 EXPORT_SYMBOL(alloc_orinocodev);
+EXPORT_SYMBOL(free_orinocodev);
 
 EXPORT_SYMBOL(__orinoco_up);
 EXPORT_SYMBOL(__orinoco_down);
diff -Nru a/drivers/net/wireless/orinoco.h b/drivers/net/wireless/orinoco.h
--- a/drivers/net/wireless/orinoco.h	2005-03-11 12:51:42 -08:00
+++ b/drivers/net/wireless/orinoco.h	2005-03-11 12:51:42 -08:00
@@ -7,7 +7,7 @@
 #ifndef _ORINOCO_H
 #define _ORINOCO_H
 
-#define DRIVER_VERSION "0.13e"
+#define DRIVER_VERSION "0.14alpha2"
 
 #include <linux/types.h>
 #include <linux/spinlock.h>
@@ -30,6 +30,12 @@
 	char data[ORINOCO_MAX_KEY_SIZE];
 } __attribute__ ((packed));
 
+typedef enum {
+	FIRMWARE_TYPE_AGERE,
+	FIRMWARE_TYPE_INTERSIL,
+	FIRMWARE_TYPE_SYMBOL
+} fwtype_t;
+
 struct orinoco_private {
 	void *card;	/* Pointer to card dependent structure */
 	int (*hard_reset)(struct orinoco_private *);
@@ -42,7 +48,6 @@
 	/* driver state */
 	int open;
 	u16 last_linkstatus;
-	int connected;
 
 	/* Net device stuff */
 	struct net_device *ndev;
@@ -54,19 +59,22 @@
 	u16 txfid;
 
 	/* Capabilities of the hardware/firmware */
-	int firmware_type;
-#define FIRMWARE_TYPE_AGERE 1
-#define FIRMWARE_TYPE_INTERSIL 2
-#define FIRMWARE_TYPE_SYMBOL 3
-	int has_ibss, has_port3, has_ibss_any, ibss_port;
-	int has_wep, has_big_wep;
-	int has_mwo;
-	int has_pm;
-	int has_preamble;
-	int has_sensitivity;
+	fwtype_t firmware_type;
+	char fw_name[32];
+	int ibss_port;
 	int nicbuf_size;
 	u16 channel_mask;
-	int broken_disableport;
+
+	/* Boolean capabilities */
+	unsigned int has_ibss:1;
+	unsigned int has_port3:1;
+	unsigned int has_wep:1;
+	unsigned int has_big_wep:1;
+	unsigned int has_mwo:1;
+	unsigned int has_pm:1;
+	unsigned int has_preamble:1;
+	unsigned int has_sensitivity:1;
+	unsigned int broken_disableport:1;
 
 	/* Configuration paramaters */
 	u32 iw_mode;
@@ -108,6 +116,7 @@
 
 extern struct net_device *alloc_orinocodev(int sizeof_card,
 					   int (*hard_reset)(struct orinoco_private *));
+extern void free_orinocodev(struct net_device *dev);
 extern int __orinoco_up(struct net_device *dev);
 extern int __orinoco_down(struct net_device *dev);
 extern int orinoco_stop(struct net_device *dev);
@@ -127,7 +136,7 @@
 {
 	spin_lock_irqsave(&priv->lock, *flags);
 	if (priv->hw_unavailable) {
-		printk(KERN_DEBUG "orinoco_lock() called with hw_unavailable (dev=%p)\n",
+		DEBUG(1, "orinoco_lock() called with hw_unavailable (dev=%p)\n",
 		       priv->ndev);
 		spin_unlock_irqrestore(&priv->lock, *flags);
 		return -EBUSY;
diff -Nru a/drivers/net/wireless/orinoco_cs.c b/drivers/net/wireless/orinoco_cs.c
--- a/drivers/net/wireless/orinoco_cs.c	2005-03-11 12:51:51 -08:00
+++ b/drivers/net/wireless/orinoco_cs.c	2005-03-11 12:51:51 -08:00
@@ -57,8 +57,8 @@
 /* Some D-Link cards have buggy CIS. They do work at 5v properly, but
  * don't have any CIS entry for it. This workaround it... */
 static int ignore_cis_vcc; /* = 0 */
-
 module_param(ignore_cis_vcc, int, 0);
+MODULE_PARM_DESC(ignore_cis_vcc, "Allow voltage mismatch between card and socket");
 
 /********************************************************************/
 /* Magic constants						    */
@@ -128,6 +128,7 @@
 	if (err)
 		return err;
 
+	msleep(100);
 	clear_bit(0, &card->hard_reset_in_progress);
 
 	return 0;
@@ -166,9 +167,10 @@
 	link->priv = dev;
 
 	/* Interrupt setup */
-	link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
+	link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT;
 	link->irq.IRQInfo1 = IRQ_LEVEL_ID;
-	link->irq.Handler = NULL;
+	link->irq.Handler = orinoco_interrupt;
+	link->irq.Instance = dev; 
 
 	/* General socket configuration defaults can go here.  In this
 	 * client, we assume very little, and rely on the CIS for
@@ -235,7 +237,7 @@
 		      dev);
 		unregister_netdev(dev);
 	}
-	free_netdev(dev);
+	free_orinocodev(dev);
 }				/* orinoco_cs_detach */
 
 /*
@@ -262,6 +264,7 @@
 	cisinfo_t info;
 	tuple_t tuple;
 	cisparse_t parse;
+	void __iomem *mem;
 
 	CS_CHECK(ValidateCIS, pcmcia_validate_cis(handle, &info));
 
@@ -308,8 +311,8 @@
 		cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);
 		cistpl_cftable_entry_t dflt = { .index = 0 };
 
-		if (pcmcia_get_tuple_data(handle, &tuple) != 0 ||
-				pcmcia_parse_tuple(handle, &tuple, &parse) != 0)
+		if ( (pcmcia_get_tuple_data(handle, &tuple) != 0)
+		    || (pcmcia_parse_tuple(handle, &tuple, &parse) != 0))
 			goto next_entry;
 
 		if (cfg->flags & CISTPL_CFTABLE_DEFAULT)
@@ -348,8 +351,7 @@
 			    dflt.vpp1.param[CISTPL_POWER_VNOM] / 10000;
 		
 		/* Do we need to allocate an interrupt? */
-		if (cfg->irq.IRQInfo1 || dflt.irq.IRQInfo1)
-			link->conf.Attributes |= CONF_ENABLE_IRQ;
+		link->conf.Attributes |= CONF_ENABLE_IRQ;
 
 		/* IO window settings */
 		link->io.NumPorts1 = link->io.NumPorts2 = 0;
@@ -390,7 +392,7 @@
 		last_ret = pcmcia_get_next_tuple(handle, &tuple);
 		if (last_ret  == CS_NO_MORE_ITEMS) {
 			printk(KERN_ERR PFX "GetNextTuple(): No matching "
-			       "CIS configuration, maybe you need the "
+			       "CIS configuration.  Maybe you need the "
 			       "ignore_cis_vcc=1 parameter.\n");
 			goto cs_failed;
 		}
@@ -401,20 +403,16 @@
 	 * a handler to the interrupt, unless the 'Handler' member of
 	 * the irq structure is initialized.
 	 */
-	if (link->conf.Attributes & CONF_ENABLE_IRQ) {
-		link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT;
-		link->irq.IRQInfo1 = IRQ_LEVEL_ID;
-  		link->irq.Handler = orinoco_interrupt; 
-  		link->irq.Instance = dev; 
-		
-		CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq));
-	}
+	CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq));
 
 	/* We initialize the hermes structure before completing PCMCIA
 	 * configuration just in case the interrupt handler gets
 	 * called. */
-	hermes_struct_init(hw, link->io.BasePort1,
-				HERMES_IO, HERMES_16BIT_REGSPACING);
+	mem = ioport_map(link->io.BasePort1, link->io.NumPorts1);
+	if (!mem)
+		goto cs_failed;
+
+	hermes_struct_init(hw, mem, HERMES_16BIT_REGSPACING);
 
 	/*
 	 * This actually configures the PCMCIA socket -- setting up
@@ -430,8 +428,6 @@
 	SET_MODULE_OWNER(dev);
 	card->node.major = card->node.minor = 0;
 
-	/* register_netdev will give us an ethX name */
-	dev->name[0] = '\0';
 	SET_NETDEV_DEV(dev, &handle_to_dev(handle));
 	/* Tell the stack we exist */
 	if (register_netdev(dev) != 0) {
@@ -454,8 +450,7 @@
 	if (link->conf.Vpp1)
 		printk(", Vpp %d.%d", link->conf.Vpp1 / 10,
 		       link->conf.Vpp1 % 10);
-	if (link->conf.Attributes & CONF_ENABLE_IRQ)
-		printk(", irq %d", link->irq.AssignedIRQ);
+	printk(", irq %d", link->irq.AssignedIRQ);
 	if (link->io.NumPorts1)
 		printk(", io 0x%04x-0x%04x", link->io.BasePort1,
 		       link->io.BasePort1 + link->io.NumPorts1 - 1);
@@ -498,6 +493,8 @@
 	if (link->irq.AssignedIRQ)
 		pcmcia_release_irq(link->handle, &link->irq);
 	link->state &= ~DEV_CONFIG;
+	if (priv->hw.iobase)
+		ioport_unmap(priv->hw.iobase);
 }				/* orinoco_cs_release */
 
 /*
@@ -519,12 +516,12 @@
 	case CS_EVENT_CARD_REMOVAL:
 		link->state &= ~DEV_PRESENT;
 		if (link->state & DEV_CONFIG) {
-			orinoco_lock(priv, &flags);
+			unsigned long flags;
 
+			spin_lock_irqsave(&priv->lock, flags);
 			netif_device_detach(dev);
 			priv->hw_unavailable++;
-
-			orinoco_unlock(priv, &flags);
+			spin_unlock_irqrestore(&priv->lock, flags);
 		}
 		break;
 
diff -Nru a/drivers/net/wireless/orinoco_pci.c b/drivers/net/wireless/orinoco_pci.c
--- a/drivers/net/wireless/orinoco_pci.c	2005-03-11 12:51:47 -08:00
+++ b/drivers/net/wireless/orinoco_pci.c	2005-03-11 12:51:47 -08:00
@@ -129,6 +129,11 @@
 #define HERMES_PCI_COR_OFFT	(500)		/* ms */
 #define HERMES_PCI_COR_BUSYT	(500)		/* ms */
 
+/* Orinoco PCI specific data */
+struct orinoco_pci_card {
+	void __iomem *pci_ioaddr;
+};
+
 /*
  * Do a soft reset of the PCI card using the Configuration Option Register
  * We need this to get going...
@@ -151,25 +156,11 @@
 
 	/* Assert the reset until the card notice */
 	hermes_write_regn(hw, PCI_COR, HERMES_PCI_COR_MASK);
-	printk(KERN_NOTICE "Reset done");
-	timeout = jiffies + (HERMES_PCI_COR_ONT * HZ / 1000);
-	while(time_before(jiffies, timeout)) {
-		printk(".");
-		mdelay(1);
-	}
-	printk(";\n");
-	//mdelay(HERMES_PCI_COR_ONT);
+	mdelay(HERMES_PCI_COR_ONT);
 
 	/* Give time for the card to recover from this hard effort */
 	hermes_write_regn(hw, PCI_COR, 0x0000);
-	printk(KERN_NOTICE "Clear Reset");
-	timeout = jiffies + (HERMES_PCI_COR_OFFT * HZ / 1000);
-	while(time_before(jiffies, timeout)) {
-		printk(".");
-		mdelay(1);
-	}
-	printk(";\n");
-	//mdelay(HERMES_PCI_COR_OFFT);
+	mdelay(HERMES_PCI_COR_OFFT);
 
 	/* The card is ready when it's no longer busy */
 	timeout = jiffies + (HERMES_PCI_COR_BUSYT * HZ / 1000);
@@ -178,12 +169,12 @@
 		mdelay(1);
 		reg = hermes_read_regn(hw, CMD);
 	}
-	/* Did we timeout ? */
-	if(time_after_eq(jiffies, timeout)) {
+
+	/* Still busy? */
+	if (reg & HERMES_CMD_BUSY) {
 		printk(KERN_ERR PFX "Busy timeout\n");
 		return -ETIMEDOUT;
 	}
-	printk(KERN_NOTICE "pci_cor : reg = 0x%X - %lX - %lX\n", reg, timeout, jiffies);
 
 	return 0;
 }
@@ -196,84 +187,93 @@
 {
 	int err = 0;
 	unsigned long pci_iorange;
-	u16 *pci_ioaddr = NULL;
+	u16 __iomem *pci_ioaddr = NULL;
 	unsigned long pci_iolen;
 	struct orinoco_private *priv = NULL;
+	struct orinoco_pci_card *card;
 	struct net_device *dev = NULL;
 
 	err = pci_enable_device(pdev);
-	if (err)
-		return -EIO;
+	if (err) {
+		printk(KERN_ERR PFX "Cannot enable PCI device\n");
+		return err;
+	}
+
+	err = pci_request_regions(pdev, DRIVER_NAME);
+	if (err != 0) {
+		printk(KERN_ERR PFX "Cannot obtain PCI resources\n");
+		goto fail_resources;
+	}
 
 	/* Resource 0 is mapped to the hermes registers */
 	pci_iorange = pci_resource_start(pdev, 0);
 	pci_iolen = pci_resource_len(pdev, 0);
 	pci_ioaddr = ioremap(pci_iorange, pci_iolen);
-	if (! pci_iorange)
-		goto fail;
+	if (!pci_iorange) {
+		printk(KERN_ERR PFX "Cannot remap hardware registers\n");
+		goto fail_map;
+	}
 
 	/* Allocate network device */
-	dev = alloc_orinocodev(0, NULL);
+	dev = alloc_orinocodev(sizeof(*card), orinoco_pci_cor_reset);
 	if (! dev) {
 		err = -ENOMEM;
-		goto fail;
+		goto fail_alloc;
 	}
 
 	priv = netdev_priv(dev);
-	dev->base_addr = (unsigned long) pci_ioaddr;
+	card = priv->card;
+	card->pci_ioaddr = pci_ioaddr;
 	dev->mem_start = pci_iorange;
 	dev->mem_end = pci_iorange + pci_iolen - 1;
 	SET_MODULE_OWNER(dev);
 	SET_NETDEV_DEV(dev, &pdev->dev);
 
-	printk(KERN_DEBUG PFX
-	       "Detected Orinoco/Prism2 PCI device at %s, mem:0x%lX to 0x%lX -> 0x%p, irq:%d\n",
-	       pci_name(pdev), dev->mem_start, dev->mem_end, pci_ioaddr, pdev->irq);
+	hermes_struct_init(&priv->hw, pci_ioaddr, HERMES_32BIT_REGSPACING);
 
-	hermes_struct_init(&priv->hw, dev->base_addr,
-			   HERMES_MEM, HERMES_32BIT_REGSPACING);
-	pci_set_drvdata(pdev, dev);
+	printk(KERN_DEBUG PFX "Detected device %s, mem:0x%lx-0x%lx, irq %d\n",
+	       pci_name(pdev), dev->mem_start, dev->mem_end, pdev->irq);
 
 	err = request_irq(pdev->irq, orinoco_interrupt, SA_SHIRQ,
 			  dev->name, dev);
 	if (err) {
-		printk(KERN_ERR PFX "Error allocating IRQ %d.\n",
-		       pdev->irq);
+		printk(KERN_ERR PFX "Cannot allocate IRQ %d\n", pdev->irq);
 		err = -EBUSY;
-		goto fail;
+		goto fail_irq;
 	}
 	dev->irq = pdev->irq;
 
 	/* Perform a COR reset to start the card */
-	if(orinoco_pci_cor_reset(priv) != 0) {
-		printk(KERN_ERR "%s: Failed to start the card\n", dev->name);
-		err = -ETIMEDOUT;
+	err = orinoco_pci_cor_reset(priv);
+	if (err) {
+		printk(KERN_ERR PFX "Initial reset failed\n");
 		goto fail;
 	}
 
-	/* Override the normal firmware detection - the Prism 2.5 PCI
-	 * cards look like Lucent firmware but are actually Intersil */
-	priv->firmware_type = FIRMWARE_TYPE_INTERSIL;
-
 	err = register_netdev(dev);
 	if (err) {
-		printk(KERN_ERR "%s: Failed to register net device\n", dev->name);
+		printk(KERN_ERR PFX "Failed to register net device\n");
 		goto fail;
 	}
 
+	pci_set_drvdata(pdev, dev);
+
 	return 0;
 
  fail:
-	if (dev) {
-		if (dev->irq)
-			free_irq(dev->irq, dev);
+	free_irq(pdev->irq, dev);
 
-		free_netdev(dev);
-	}
+ fail_irq:
+	pci_set_drvdata(pdev, NULL);
+	free_orinocodev(dev);
 
-	if (pci_ioaddr)
-		iounmap(pci_ioaddr);
+ fail_alloc:
+	iounmap(pci_ioaddr);
 
+ fail_map:
+	pci_release_regions(pdev);
+
+ fail_resources:
 	pci_disable_device(pdev);
 
 	return err;
@@ -283,18 +283,14 @@
 {
 	struct net_device *dev = pci_get_drvdata(pdev);
 	struct orinoco_private *priv = netdev_priv(dev);
+	struct orinoco_pci_card *card = priv->card;
 
 	unregister_netdev(dev);
-
-	if (dev->irq)
-		free_irq(dev->irq, dev);
-
-	if (priv->hw.iobase)
-		iounmap((unsigned char *) priv->hw.iobase);
-
+	free_irq(dev->irq, dev);
 	pci_set_drvdata(pdev, NULL);
-	free_netdev(dev);
-
+	free_orinocodev(dev);
+	iounmap(card->pci_ioaddr);
+	pci_release_regions(pdev);
 	pci_disable_device(pdev);
 }
 
@@ -326,6 +322,9 @@
 	
 	orinoco_unlock(priv, &flags);
 
+	pci_save_state(pdev);
+	pci_set_power_state(pdev, 3);
+
 	return 0;
 }
 
@@ -338,6 +337,9 @@
 
 	printk(KERN_DEBUG "%s: Orinoco-PCI waking up\n", dev->name);
 
+	pci_set_power_state(pdev, 0);
+	pci_restore_state(pdev);
+
 	err = orinoco_reinit_firmware(dev);
 	if (err) {
 		printk(KERN_ERR "%s: Error %d re-initializing firmware on orinoco_pci_resume()\n",
@@ -368,6 +370,8 @@
 	{0x1260, 0x3872, PCI_ANY_ID, PCI_ANY_ID,},
 	/* Intersil Prism 2.5 */
 	{0x1260, 0x3873, PCI_ANY_ID, PCI_ANY_ID,},
+	/* Samsung MagicLAN SWL-2210P */
+	{0x167d, 0xa000, PCI_ANY_ID, PCI_ANY_ID,},
 	{0,},
 };
 
diff -Nru a/drivers/net/wireless/orinoco_plx.c b/drivers/net/wireless/orinoco_plx.c
--- a/drivers/net/wireless/orinoco_plx.c	2005-03-11 12:51:51 -08:00
+++ b/drivers/net/wireless/orinoco_plx.c	2005-03-11 12:51:51 -08:00
@@ -142,146 +142,199 @@
 #include "hermes.h"
 #include "orinoco.h"
 
-#define COR_OFFSET	(0x3e0/2) /* COR attribute offset of Prism2 PC card */
+#define COR_OFFSET	(0x3e0)	/* COR attribute offset of Prism2 PC card */
 #define COR_VALUE	(COR_LEVEL_REQ | COR_FUNC_ENA) /* Enable PC card with interrupt in level trigger */
+#define COR_RESET     (0x80)	/* reset bit in the COR register */
+#define PLX_RESET_TIME	(500)	/* milliseconds */
 
 #define PLX_INTCSR		0x4c /* Interrupt Control & Status Register */
 #define PLX_INTCSR_INTEN	(1<<6) /* Interrupt Enable bit */
 
-static const u16 cis_magic[] = {
-	0x0001, 0x0003, 0x0000, 0x0000, 0x00ff, 0x0017, 0x0004, 0x0067
+static const u8 cis_magic[] = {
+	0x01, 0x03, 0x00, 0x00, 0xff, 0x17, 0x04, 0x67
 };
 
+/* Orinoco PLX specific data */
+struct orinoco_plx_card {
+	void __iomem *attr_mem;
+};
+
+/*
+ * Do a soft reset of the card using the Configuration Option Register
+ */
+static int orinoco_plx_cor_reset(struct orinoco_private *priv)
+{
+	hermes_t *hw = &priv->hw;
+	struct orinoco_plx_card *card = priv->card;
+	u8 __iomem *attr_mem = card->attr_mem;
+	unsigned long timeout;
+	u16 reg;
+
+	writeb(COR_VALUE | COR_RESET, attr_mem + COR_OFFSET);
+	mdelay(1);
+
+	writeb(COR_VALUE, attr_mem + COR_OFFSET);
+	mdelay(1);
+
+	/* Just in case, wait more until the card is no longer busy */
+	timeout = jiffies + (PLX_RESET_TIME * HZ / 1000);
+	reg = hermes_read_regn(hw, CMD);
+	while (time_before(jiffies, timeout) && (reg & HERMES_CMD_BUSY)) {
+		mdelay(1);
+		reg = hermes_read_regn(hw, CMD);
+	}
+
+	/* Did we timeout ? */
+	if (reg & HERMES_CMD_BUSY) {
+		printk(KERN_ERR PFX "Busy timeout\n");
+		return -ETIMEDOUT;
+	}
+
+	return 0;
+}
+
+
 static int orinoco_plx_init_one(struct pci_dev *pdev,
 				const struct pci_device_id *ent)
 {
 	int err = 0;
-	u16 *attr_mem = NULL;
-	u32 reg, addr;
+	u8 __iomem *attr_mem = NULL;
+	u32 csr_reg, plx_addr;
 	struct orinoco_private *priv = NULL;
+	struct orinoco_plx_card *card;
 	unsigned long pccard_ioaddr = 0;
 	unsigned long pccard_iolen = 0;
 	struct net_device *dev = NULL;
+	void __iomem *mem;
 	int i;
 
 	err = pci_enable_device(pdev);
-	if (err)
-		return -EIO;
-
-	/* Resource 2 is mapped to the PCMCIA space */
-	attr_mem = ioremap(pci_resource_start(pdev, 2), PAGE_SIZE);
-	if (! attr_mem)
-		goto fail;
-
-	printk(KERN_DEBUG "orinoco_plx: CIS: ");
-	for (i = 0; i < 16; i++) {
-		printk("%02X:", (int)attr_mem[i]);
+	if (err) {
+		printk(KERN_ERR PFX "Cannot enable PCI device\n");
+		return err;
 	}
-	printk("\n");
 
-	/* Verify whether PC card is present */
-	/* FIXME: we probably need to be smarted about this */
-	if (memcmp(attr_mem, cis_magic, sizeof(cis_magic)) != 0) {
-		printk(KERN_ERR "orinoco_plx: The CIS value of Prism2 PC card is invalid.\n");
-		err = -EIO;
-		goto fail;
+	err = pci_request_regions(pdev, DRIVER_NAME);
+	if (err != 0) {
+		printk(KERN_ERR PFX "Cannot obtain PCI resources\n");
+		goto fail_resources;
 	}
 
-	/* PCMCIA COR is the first byte following CIS: this write should
-	 * enable I/O mode and select level-triggered interrupts */
-	attr_mem[COR_OFFSET] = COR_VALUE;
-	mdelay(1);
-	reg = attr_mem[COR_OFFSET];
-	if (reg != COR_VALUE) {
-		printk(KERN_ERR "orinoco_plx: Error setting COR value (reg=%x)\n", reg);
-		goto fail;
-	}			
-
-	iounmap(attr_mem);
-	attr_mem = NULL; /* done with this now, it seems */
+	/* Resource 1 is mapped to PLX-specific registers */
+	plx_addr = pci_resource_start(pdev, 1);
 
-	/* bjoern: We need to tell the card to enable interrupts, in
-	   case the serial eprom didn't do this already. See the
-	   PLX9052 data book, p8-1 and 8-24 for reference. */
-	addr = pci_resource_start(pdev, 1);
-	reg = 0;
-	reg = inl(addr+PLX_INTCSR);
-	if (reg & PLX_INTCSR_INTEN)
-		printk(KERN_DEBUG "orinoco_plx: "
-		       "Local Interrupt already enabled\n");
-	else {
-		reg |= PLX_INTCSR_INTEN;
-		outl(reg, addr+PLX_INTCSR);
-		reg = inl(addr+PLX_INTCSR);
-		if(!(reg & PLX_INTCSR_INTEN)) {
-			printk(KERN_ERR "orinoco_plx: "
-			       "Couldn't enable Local Interrupts\n");
-			goto fail;
-		}
+	/* Resource 2 is mapped to the PCMCIA attribute memory */
+	attr_mem = ioremap(pci_resource_start(pdev, 2),
+			   pci_resource_len(pdev, 2));
+	if (!attr_mem) {
+		printk(KERN_ERR PFX "Cannot remap PCMCIA space\n");
+		goto fail_map_attr;
 	}
 
-	/* and 3 to the PCMCIA slot I/O address space */
+	/* Resource 3 is mapped to the PCMCIA I/O address space */
 	pccard_ioaddr = pci_resource_start(pdev, 3);
 	pccard_iolen = pci_resource_len(pdev, 3);
-	if (! request_region(pccard_ioaddr, pccard_iolen, DRIVER_NAME)) {
-		printk(KERN_ERR "orinoco_plx: I/O resource 0x%lx @ 0x%lx busy\n",
-		       pccard_iolen, pccard_ioaddr);
-		pccard_ioaddr = 0;
-		err = -EBUSY;
-		goto fail;
+
+	mem = pci_iomap(pdev, 3, 0);
+	if (!mem) {
+		err = -ENOMEM;
+		goto fail_map_io;
 	}
 
 	/* Allocate network device */
-	dev = alloc_orinocodev(0, NULL);
-	if (! dev) {
+	dev = alloc_orinocodev(sizeof(*card), orinoco_plx_cor_reset);
+	if (!dev) {
+		printk(KERN_ERR PFX "Cannot allocate network device\n");
 		err = -ENOMEM;
-		goto fail;
+		goto fail_alloc;
 	}
 
 	priv = netdev_priv(dev);
+	card = priv->card;
+	card->attr_mem = attr_mem;
 	dev->base_addr = pccard_ioaddr;
 	SET_MODULE_OWNER(dev);
 	SET_NETDEV_DEV(dev, &pdev->dev);
 
+	hermes_struct_init(&priv->hw, mem, HERMES_16BIT_REGSPACING);
+
 	printk(KERN_DEBUG PFX "Detected Orinoco/Prism2 PLX device "
 	       "at %s irq:%d, io addr:0x%lx\n", pci_name(pdev), pdev->irq,
 	       pccard_ioaddr);
 
-	hermes_struct_init(&(priv->hw), dev->base_addr, HERMES_IO,
-			   HERMES_16BIT_REGSPACING);
-	pci_set_drvdata(pdev, dev);
-
 	err = request_irq(pdev->irq, orinoco_interrupt, SA_SHIRQ,
 			  dev->name, dev);
 	if (err) {
-		printk(KERN_ERR PFX "Error allocating IRQ %d.\n", pdev->irq);
+		printk(KERN_ERR PFX "Cannot allocate IRQ %d\n", pdev->irq);
 		err = -EBUSY;
-		goto fail;
+		goto fail_irq;
 	}
 	dev->irq = pdev->irq;
 
+	/* bjoern: We need to tell the card to enable interrupts, in
+	   case the serial eprom didn't do this already.  See the
+	   PLX9052 data book, p8-1 and 8-24 for reference. */
+	csr_reg = inl(plx_addr + PLX_INTCSR);
+	if (!(csr_reg & PLX_INTCSR_INTEN)) {
+		csr_reg |= PLX_INTCSR_INTEN;
+		outl(csr_reg, plx_addr + PLX_INTCSR);
+		csr_reg = inl(plx_addr + PLX_INTCSR);
+		if (!(csr_reg & PLX_INTCSR_INTEN)) {
+			printk(KERN_ERR PFX "Cannot enable interrupts\n");
+			goto fail;
+		}
+	}
+
+	err = orinoco_plx_cor_reset(priv);
+	if (err) {
+		printk(KERN_ERR PFX "Initial reset failed\n");
+		goto fail;
+	}
+
+	printk(KERN_DEBUG PFX "CIS: ");
+	for (i = 0; i < 16; i++) {
+		printk("%02X:", readb(attr_mem + 2*i));
+	}
+	printk("\n");
+
+	/* Verify whether a supported PC card is present */
+	/* FIXME: we probably need to be smarted about this */
+	for (i = 0; i < sizeof(cis_magic); i++) {
+		if (cis_magic[i] != readb(attr_mem +2*i)) {
+			printk(KERN_ERR PFX "The CIS value of Prism2 PC "
+			       "card is unexpected\n");
+			err = -EIO;
+			goto fail;
+		}
+	}
+
 	err = register_netdev(dev);
-	if (err)
+	if (err) {
+		printk(KERN_ERR PFX "Cannot register network device\n");
 		goto fail;
+	}
+
+	pci_set_drvdata(pdev, dev);
 
 	return 0;
 
  fail:
-	printk(KERN_DEBUG PFX "init_one(), FAIL!\n");
+	free_irq(pdev->irq, dev);
 
-	if (dev) {
-		if (dev->irq)
-			free_irq(dev->irq, dev);
-		
-		free_netdev(dev);
-	}
+ fail_irq:
+	pci_set_drvdata(pdev, NULL);
+	free_orinocodev(dev);
 
-	if (pccard_ioaddr)
-		release_region(pccard_ioaddr, pccard_iolen);
+ fail_alloc:
+	pci_iounmap(pdev, mem);
+
+ fail_map_io:
+	iounmap(attr_mem);
 
-	if (attr_mem)
-		iounmap(attr_mem);
+ fail_map_attr:
+	pci_release_regions(pdev);
 
+ fail_resources:
 	pci_disable_device(pdev);
 
 	return err;
@@ -290,20 +343,19 @@
 static void __devexit orinoco_plx_remove_one(struct pci_dev *pdev)
 {
 	struct net_device *dev = pci_get_drvdata(pdev);
+	struct orinoco_private *priv = netdev_priv(dev);
+	struct orinoco_plx_card *card = priv->card;
+	u8 __iomem *attr_mem = card->attr_mem;
 
 	BUG_ON(! dev);
 
 	unregister_netdev(dev);
-		
-	if (dev->irq)
-		free_irq(dev->irq, dev);
-		
+	free_irq(dev->irq, dev);
 	pci_set_drvdata(pdev, NULL);
-
-	free_netdev(dev);
-
-	release_region(pci_resource_start(pdev, 3), pci_resource_len(pdev, 3));
-
+	free_orinocodev(dev);
+	pci_iounmap(pdev, priv->hw.iobase);
+	iounmap(attr_mem);
+	pci_release_regions(pdev);
 	pci_disable_device(pdev);
 }
 
@@ -352,8 +404,7 @@
 static void __exit orinoco_plx_exit(void)
 {
 	pci_unregister_driver(&orinoco_plx_driver);
-	current->state = TASK_UNINTERRUPTIBLE;
-	schedule_timeout(HZ);
+	ssleep(1);
 }
 
 module_init(orinoco_plx_init);
diff -Nru a/drivers/net/wireless/orinoco_tmd.c b/drivers/net/wireless/orinoco_tmd.c
--- a/drivers/net/wireless/orinoco_tmd.c	2005-03-11 12:51:41 -08:00
+++ b/drivers/net/wireless/orinoco_tmd.c	2005-03-11 12:51:41 -08:00
@@ -79,90 +79,137 @@
 #include "orinoco.h"
 
 #define COR_VALUE	(COR_LEVEL_REQ | COR_FUNC_ENA) /* Enable PC card with interrupt in level trigger */
+#define COR_RESET     (0x80)	/* reset bit in the COR register */
+#define TMD_RESET_TIME	(500)	/* milliseconds */
+
+/* Orinoco TMD specific data */
+struct orinoco_tmd_card {
+	u32 tmd_io;
+};
+
+
+/*
+ * Do a soft reset of the card using the Configuration Option Register
+ */
+static int orinoco_tmd_cor_reset(struct orinoco_private *priv)
+{
+	hermes_t *hw = &priv->hw;
+	struct orinoco_tmd_card *card = priv->card;
+	u32 addr = card->tmd_io;
+	unsigned long timeout;
+	u16 reg;
+
+	outb(COR_VALUE | COR_RESET, addr);
+	mdelay(1);
+
+	outb(COR_VALUE, addr);
+	mdelay(1);
+
+	/* Just in case, wait more until the card is no longer busy */
+	timeout = jiffies + (TMD_RESET_TIME * HZ / 1000);
+	reg = hermes_read_regn(hw, CMD);
+	while (time_before(jiffies, timeout) && (reg & HERMES_CMD_BUSY)) {
+		mdelay(1);
+		reg = hermes_read_regn(hw, CMD);
+	}
+
+	/* Did we timeout ? */
+	if (reg & HERMES_CMD_BUSY) {
+		printk(KERN_ERR PFX "Busy timeout\n");
+		return -ETIMEDOUT;
+	}
+
+	return 0;
+}
+
 
 static int orinoco_tmd_init_one(struct pci_dev *pdev,
 				const struct pci_device_id *ent)
 {
 	int err = 0;
-	u32 reg, addr;
 	struct orinoco_private *priv = NULL;
-	unsigned long pccard_ioaddr = 0;
-	unsigned long pccard_iolen = 0;
+	struct orinoco_tmd_card *card;
 	struct net_device *dev = NULL;
+	void __iomem *mem;
 
 	err = pci_enable_device(pdev);
-	if (err)
-		return -EIO;
+	if (err) {
+		printk(KERN_ERR PFX "Cannot enable PCI device\n");
+		return err;
+	}
 
-	printk(KERN_DEBUG PFX "TMD setup\n");
-	pccard_ioaddr = pci_resource_start(pdev, 2);
-	pccard_iolen = pci_resource_len(pdev, 2);
-	if (! request_region(pccard_ioaddr, pccard_iolen, DRIVER_NAME)) {
-		printk(KERN_ERR PFX "I/O resource at 0x%lx len 0x%lx busy\n",
-			pccard_ioaddr, pccard_iolen);
-		pccard_ioaddr = 0;
-		err = -EBUSY;
-		goto fail;
+	err = pci_request_regions(pdev, DRIVER_NAME);
+	if (err != 0) {
+		printk(KERN_ERR PFX "Cannot obtain PCI resources\n");
+		goto fail_resources;
 	}
-	addr = pci_resource_start(pdev, 1);
-	outb(COR_VALUE, addr);
-	mdelay(1);
-	reg = inb(addr);
-	if (reg != COR_VALUE) {
-		printk(KERN_ERR PFX "Error setting TMD COR values %x should be %x\n", reg, COR_VALUE);
-		err = -EIO;
-		goto fail;
+
+	mem = pci_iomap(pdev, 2, 0);
+	if (! mem) {
+		err = -ENOMEM;
+		goto fail_iomap;
 	}
 
 	/* Allocate network device */
-	dev = alloc_orinocodev(0, NULL);
+	dev = alloc_orinocodev(sizeof(*card), orinoco_tmd_cor_reset);
 	if (! dev) {
+		printk(KERN_ERR PFX "Cannot allocate network device\n");
 		err = -ENOMEM;
-		goto fail;
+		goto fail_alloc;
 	}
 
 	priv = netdev_priv(dev);
-	dev->base_addr = pccard_ioaddr;
+	card = priv->card;
+	card->tmd_io = pci_resource_start(pdev, 1);
+	dev->base_addr = pci_resource_start(pdev, 2);
 	SET_MODULE_OWNER(dev);
 	SET_NETDEV_DEV(dev, &pdev->dev);
 
+	hermes_struct_init(&priv->hw, mem, HERMES_16BIT_REGSPACING);
+
 	printk(KERN_DEBUG PFX "Detected Orinoco/Prism2 TMD device "
 	       "at %s irq:%d, io addr:0x%lx\n", pci_name(pdev), pdev->irq,
-	       pccard_ioaddr);
-
-	hermes_struct_init(&(priv->hw), dev->base_addr,
-			HERMES_IO, HERMES_16BIT_REGSPACING);
-	pci_set_drvdata(pdev, dev);
+	       dev->base_addr);
 
 	err = request_irq(pdev->irq, orinoco_interrupt, SA_SHIRQ,
 			  dev->name, dev);
 	if (err) {
-		printk(KERN_ERR PFX "Error allocating IRQ %d.\n",
-		       pdev->irq);
+		printk(KERN_ERR PFX "Cannot allocate IRQ %d\n", pdev->irq);
 		err = -EBUSY;
-		goto fail;
+		goto fail_irq;
 	}
 	dev->irq = pdev->irq;
 
+	err = orinoco_tmd_cor_reset(priv);
+	if (err) {
+		printk(KERN_ERR PFX "Initial reset failed\n");
+		goto fail;
+	}
+
 	err = register_netdev(dev);
-	if (err)
+	if (err) {
+		printk(KERN_ERR PFX "Cannot register network device\n");
 		goto fail;
+	}
+
+	pci_set_drvdata(pdev, dev);
 
 	return 0;
 
  fail:
-	printk(KERN_DEBUG PFX "init_one(), FAIL!\n");
+	free_irq(pdev->irq, dev);
 
-	if (dev) {
-		if (dev->irq)
-			free_irq(dev->irq, dev);
-		
-		free_netdev(dev);
-	}
+ fail_irq:
+	pci_set_drvdata(pdev, NULL);
+	free_orinocodev(dev);
+
+ fail_alloc:
+	pci_iounmap(pdev, mem);
 
-	if (pccard_ioaddr)
-		release_region(pccard_ioaddr, pccard_iolen);
+ fail_iomap:
+	pci_release_regions(pdev);
 
+ fail_resources:
 	pci_disable_device(pdev);
 
 	return err;
@@ -171,20 +218,16 @@
 static void __devexit orinoco_tmd_remove_one(struct pci_dev *pdev)
 {
 	struct net_device *dev = pci_get_drvdata(pdev);
+	struct orinoco_private *priv = dev->priv;
 
 	BUG_ON(! dev);
 
 	unregister_netdev(dev);
-		
-	if (dev->irq)
-		free_irq(dev->irq, dev);
-		
+	free_irq(dev->irq, dev);
 	pci_set_drvdata(pdev, NULL);
-
-	free_netdev(dev);
-
-	release_region(pci_resource_start(pdev, 2), pci_resource_len(pdev, 2));
-
+	free_orinocodev(dev);
+	pci_iounmap(pdev, priv->hw.iobase);
+	pci_release_regions(pdev);
 	pci_disable_device(pdev);
 }
 
@@ -218,8 +261,7 @@
 static void __exit orinoco_tmd_exit(void)
 {
 	pci_unregister_driver(&orinoco_tmd_driver);
-	current->state = TASK_UNINTERRUPTIBLE;
-	schedule_timeout(HZ);
+	ssleep(1);
 }
 
 module_init(orinoco_tmd_init);
diff -Nru a/drivers/net/wireless/prism54/isl_38xx.c b/drivers/net/wireless/prism54/isl_38xx.c
--- a/drivers/net/wireless/prism54/isl_38xx.c	2005-03-11 12:51:46 -08:00
+++ b/drivers/net/wireless/prism54/isl_38xx.c	2005-03-11 12:51:46 -08:00
@@ -125,11 +125,11 @@
 #if VERBOSE > SHOW_ERROR_MESSAGES
 		do_gettimeofday(&current_time);
 		DEBUG(SHOW_TRACING, "%08li.%08li Device wakeup triggered\n",
-		      current_time.tv_sec, current_time.tv_usec);
+		      current_time.tv_sec, (long)current_time.tv_usec);
 #endif
 
 		DEBUG(SHOW_TRACING, "%08li.%08li Device register read %08x\n",
-		      current_time.tv_sec, current_time.tv_usec,
+		      current_time.tv_sec, (long)current_time.tv_usec,
 		      readl(device_base + ISL38XX_CTRL_STAT_REG));
 		udelay(ISL38XX_WRITEIO_DELAY);
 
@@ -139,7 +139,7 @@
 			do_gettimeofday(&current_time);
 			DEBUG(SHOW_TRACING,
 			      "%08li.%08li Device register abadface\n",
-			      current_time.tv_sec, current_time.tv_usec);
+			      current_time.tv_sec, (long)current_time.tv_usec);
 #endif
 			/* read the Device Status Register until Sleepmode bit is set */
 			while (reg = readl(device_base + ISL38XX_CTRL_STAT_REG),
@@ -150,7 +150,7 @@
 
 			DEBUG(SHOW_TRACING,
 			      "%08li.%08li Device register read %08x\n",
-			      current_time.tv_sec, current_time.tv_usec,
+			      current_time.tv_sec, (long)current_time.tv_usec,
 			      readl(device_base + ISL38XX_CTRL_STAT_REG));
 			udelay(ISL38XX_WRITEIO_DELAY);
 
@@ -158,7 +158,7 @@
 			do_gettimeofday(&current_time);
 			DEBUG(SHOW_TRACING,
 			      "%08li.%08li Device asleep counter %i\n",
-			      current_time.tv_sec, current_time.tv_usec,
+			      current_time.tv_sec, (long)current_time.tv_usec,
 			      counter);
 #endif
 		}
@@ -174,7 +174,7 @@
 #if VERBOSE > SHOW_ERROR_MESSAGES
 		do_gettimeofday(&current_time);
 		DEBUG(SHOW_TRACING, "%08li.%08li Device register read %08x\n",
-		      current_time.tv_sec, current_time.tv_usec, reg);
+		      current_time.tv_sec, (long)current_time.tv_usec, reg);
 #endif
 	} else {
 		/* device is (still) awake  */
diff -Nru a/drivers/net/wireless/prism54/isl_ioctl.c b/drivers/net/wireless/prism54/isl_ioctl.c
--- a/drivers/net/wireless/prism54/isl_ioctl.c	2005-03-11 12:51:42 -08:00
+++ b/drivers/net/wireless/prism54/isl_ioctl.c	2005-03-11 12:51:42 -08:00
@@ -1750,7 +1750,7 @@
 	u8 wpa_ie[MAX_WPA_IE_LEN];
 	int wpa_ie_len;
 	size_t len = 0; /* u16, better? */
-	u8 *payload = 0, *pos = 0;
+	u8 *payload = NULL, *pos = NULL;
 	int ret;
 
 	/* I think all trapable objects are listed here.
diff -Nru a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c
--- a/drivers/net/wireless/ray_cs.c	2005-03-11 12:51:42 -08:00
+++ b/drivers/net/wireless/ray_cs.c	2005-03-11 12:51:42 -08:00
@@ -1215,6 +1215,9 @@
 #if WIRELESS_EXT > 7
     struct iwreq *wrq = (struct iwreq *) ifr;
 #endif	/* WIRELESS_EXT > 7 */
+#ifdef WIRELESS_SPY
+    struct sockaddr	address[IW_MAX_SPY];
+#endif	/* WIRELESS_SPY */
 
     if (!(link->state & DEV_PRESENT)) {
         DEBUG(2,"ray_dev_ioctl - device not present\n");
@@ -1511,7 +1514,6 @@
       /* If there is some addresses to copy */
       if(local->spy_number > 0)
 	{
-	  struct sockaddr	address[IW_MAX_SPY];
 	  int			i;
 
 	  /* Copy addresses to the driver */
@@ -1551,7 +1553,6 @@
       /* If the user want to have the addresses back... */
       if((local->spy_number > 0) && (wrq->u.data.pointer != (caddr_t) 0))
 	{
-	  struct sockaddr	address[IW_MAX_SPY];
 	  int			i;
 
 	  /* Copy addresses from the lp structure */
diff -Nru a/drivers/net/wireless/strip.c b/drivers/net/wireless/strip.c
--- a/drivers/net/wireless/strip.c	2005-03-11 12:51:47 -08:00
+++ b/drivers/net/wireless/strip.c	2005-03-11 12:51:47 -08:00
@@ -876,7 +876,7 @@
  */
 static int strip_change_mtu(struct net_device *dev, int new_mtu)
 {
-	struct strip *strip_info = dev->priv;
+	struct strip *strip_info = netdev_priv(dev);
 	int old_mtu = strip_info->mtu;
 	unsigned char *orbuff = strip_info->rx_buff;
 	unsigned char *osbuff = strip_info->sx_buff;
@@ -1563,7 +1563,7 @@
 /* Encapsulate a datagram and kick it into a TTY queue. */
 static int strip_xmit(struct sk_buff *skb, struct net_device *dev)
 {
-	struct strip *strip_info = (struct strip *) (dev->priv);
+	struct strip *strip_info = netdev_priv(dev);
 
 	if (!netif_running(dev)) {
 		printk(KERN_ERR "%s: xmit call when iface is down\n",
@@ -1639,7 +1639,7 @@
 			unsigned short type, void *daddr, void *saddr,
 			unsigned len)
 {
-	struct strip *strip_info = (struct strip *) (dev->priv);
+	struct strip *strip_info = netdev_priv(dev);
 	STRIP_Header *header = (STRIP_Header *) skb_push(skb, sizeof(STRIP_Header));
 
 	/*printk(KERN_INFO "%s: strip_header 0x%04X %s\n", dev->name, type,
@@ -1648,7 +1648,7 @@
 	header->src_addr = strip_info->true_dev_addr;
 	header->protocol = htons(type);
 
-	/*HexDump("strip_header", (struct strip *)(dev->priv), skb->data, skb->data + skb->len); */
+	/*HexDump("strip_header", netdev_priv(dev), skb->data, skb->data + skb->len); */
 
 	if (!daddr)
 		return (-dev->hard_header_len);
@@ -2400,7 +2400,7 @@
 
 static int strip_set_mac_address(struct net_device *dev, void *addr)
 {
-	struct strip *strip_info = (struct strip *) (dev->priv);
+	struct strip *strip_info = netdev_priv(dev);
 	struct sockaddr *sa = addr;
 	printk(KERN_INFO "%s: strip_set_dev_mac_address called\n", dev->name);
 	set_mac_address(strip_info, (MetricomAddress *) sa->sa_data);
@@ -2409,8 +2409,8 @@
 
 static struct net_device_stats *strip_get_stats(struct net_device *dev)
 {
+	struct strip *strip_info = netdev_priv(dev);
 	static struct net_device_stats stats;
-	struct strip *strip_info = (struct strip *) (dev->priv);
 
 	memset(&stats, 0, sizeof(struct net_device_stats));
 
@@ -2454,7 +2454,7 @@
 
 static int strip_open_low(struct net_device *dev)
 {
-	struct strip *strip_info = (struct strip *) (dev->priv);
+	struct strip *strip_info = netdev_priv(dev);
 
 	if (strip_info->tty == NULL)
 		return (-ENODEV);
@@ -2487,7 +2487,7 @@
 
 static int strip_close_low(struct net_device *dev)
 {
-	struct strip *strip_info = (struct strip *) (dev->priv);
+	struct strip *strip_info = netdev_priv(dev);
 
 	if (strip_info->tty == NULL)
 		return -EBUSY;
diff -Nru a/drivers/parisc/Kconfig b/drivers/parisc/Kconfig
--- a/drivers/parisc/Kconfig	2005-03-11 12:51:47 -08:00
+++ b/drivers/parisc/Kconfig	2005-03-11 12:51:47 -08:00
@@ -110,6 +110,14 @@
 #	help
 #	  Say Y here for V-class PCI, DMA/IOMMU, IRQ subsystem support.
 
+source "drivers/pcmcia/Kconfig"
+
+source "drivers/pci/hotplug/Kconfig"
+
+endmenu
+
+menu "PA-RISC specific drivers"
+
 config SUPERIO
 	bool "SuperIO (SuckyIO) support"
 	depends on PCI_LBA
@@ -144,9 +152,18 @@
 	  
 	  If unsure, say Y.
 
-source "drivers/pcmcia/Kconfig"
-
-source "drivers/pci/hotplug/Kconfig"
-
+config PDC_STABLE
+	tristate "PDC Stable Storage support"
+	depends on SYSFS
+	default y
+	help
+	  Say Y here if you want to enable support for accessing Stable Storage
+	  variables (PDC non volatile variables such as Primary Boot Path,
+	  Console Path, Autoboot, Autosearch, etc) through SysFS.
+	
+	  If unsure, say Y.
+	
+	  To compile this driver as a module, choose M here.
+	  The module will be called pdc_stable.
 
 endmenu
diff -Nru a/drivers/parisc/Makefile b/drivers/parisc/Makefile
--- a/drivers/parisc/Makefile	2005-03-11 12:51:41 -08:00
+++ b/drivers/parisc/Makefile	2005-03-11 12:51:41 -08:00
@@ -22,5 +22,6 @@
 
 obj-$(CONFIG_SUPERIO)		+= superio.o
 obj-$(CONFIG_CHASSIS_LCD_LED)	+= led.o
+obj-$(CONFIG_PDC_STABLE)	+= pdc_stable.o
 obj-y				+= power.o
 
diff -Nru a/drivers/parisc/asp.c b/drivers/parisc/asp.c
--- a/drivers/parisc/asp.c	2005-03-11 12:51:52 -08:00
+++ b/drivers/parisc/asp.c	2005-03-11 12:51:52 -08:00
@@ -30,6 +30,8 @@
 
 #define VIPER_INT_WORD  0xFFFBF088      /* addr of viper interrupt word */
 
+static struct gsc_asic asp;
+
 static void asp_choose_irq(struct parisc_device *dev, void *ctrl)
 {
 	int irq;
@@ -64,20 +66,15 @@
 int __init
 asp_init_chip(struct parisc_device *dev)
 {
-	struct gsc_asic *asp;
 	struct gsc_irq gsc_irq;
 	int ret;
 
-	asp = kmalloc(sizeof(*asp), GFP_KERNEL);
-	if(!asp)
-		return -ENOMEM;
-
-	asp->version = gsc_readb(dev->hpa + ASP_VER_OFFSET) & 0xf;
-	asp->name = (asp->version == 1) ? "Asp" : "Cutoff";
-	asp->hpa = ASP_INTERRUPT_ADDR;
+	asp.version = gsc_readb(dev->hpa + ASP_VER_OFFSET) & 0xf;
+	asp.name = (asp.version == 1) ? "Asp" : "Cutoff";
+	asp.hpa = ASP_INTERRUPT_ADDR;
 
 	printk(KERN_INFO "%s version %d at 0x%lx found.\n", 
-		asp->name, asp->version, dev->hpa);
+		asp.name, asp.version, dev->hpa);
 
 	/* the IRQ ASP should use */
 	ret = -EBUSY;
@@ -87,9 +84,9 @@
 		goto out;
 	}
 
-	asp->eim = ((u32) gsc_irq.txn_addr) | gsc_irq.txn_data;
+	asp.eim = ((u32) gsc_irq.txn_addr) | gsc_irq.txn_data;
 
-	ret = request_irq(gsc_irq.irq, gsc_asic_intr, 0, "asp", asp);
+	ret = request_irq(gsc_irq.irq, gsc_asic_intr, 0, "asp", &asp);
 	if (ret < 0)
 		goto out;
 
@@ -97,13 +94,13 @@
 	gsc_writel((1 << (31 - ASP_GSC_IRQ)),VIPER_INT_WORD);
 
 	/* Done init'ing, register this driver */
-	ret = gsc_common_setup(dev, asp);
+	ret = gsc_common_setup(dev, &asp);
 	if (ret)
 		goto out;
 
-	gsc_fixup_irqs(dev, asp, asp_choose_irq);
+	gsc_fixup_irqs(dev, &asp, asp_choose_irq);
 	/* Mongoose is a sibling of Asp, not a child... */
-	gsc_fixup_irqs(parisc_parent(dev), asp, asp_choose_irq);
+	gsc_fixup_irqs(parisc_parent(dev), &asp, asp_choose_irq);
 
 	/* initialize the chassis LEDs */ 
 #ifdef CONFIG_CHASSIS_LCD_LED	
@@ -111,10 +108,7 @@
 		    ASP_LED_ADDR);
 #endif
 
-	return 0;
-
-out:
-	kfree(asp);
+ out:
 	return ret;
 }
 
diff -Nru a/drivers/parisc/ccio-dma.c b/drivers/parisc/ccio-dma.c
--- a/drivers/parisc/ccio-dma.c	2005-03-11 12:51:41 -08:00
+++ b/drivers/parisc/ccio-dma.c	2005-03-11 12:51:41 -08:00
@@ -262,8 +262,6 @@
 	struct resource mmio_region[2]; /* The "routed" MMIO regions */
 };
 
-/* Ratio of Host MEM to IOV Space size */
-static unsigned long ccio_mem_ratio = 4;
 static struct ioc *ioc_list;
 static int ioc_count;
 
@@ -559,7 +557,7 @@
 ccio_io_pdir_entry(u64 *pdir_ptr, space_t sid, unsigned long vba,
 		   unsigned long hints)
 {
-	register unsigned long pa = (volatile unsigned long) vba;
+	register unsigned long pa;
 	register unsigned long ci; /* coherent index */
 
 	/* We currently only support kernel addresses */
@@ -1243,6 +1241,21 @@
 #define CCIO_CHAINID_MASK	0xff
 #endif /* 0 */
 
+/* We *can't* support JAVA (T600). Venture there at your own risk. */
+static struct parisc_device_id ccio_tbl[] = {
+	{ HPHW_IOA, HVERSION_REV_ANY_ID, U2_IOA_RUNWAY, 0xb }, /* U2 */
+	{ HPHW_IOA, HVERSION_REV_ANY_ID, UTURN_IOA_RUNWAY, 0xb }, /* UTurn */
+	{ 0, }
+};
+
+static int ccio_probe(struct parisc_device *dev);
+
+static struct parisc_driver ccio_driver = {
+	.name =		"U2:Uturn",
+	.id_table =	ccio_tbl,
+	.probe =	ccio_probe,
+};
+
 /**
  * ccio_ioc_init - Initalize the I/O Controller
  * @ioc: The I/O Controller.
@@ -1254,9 +1267,9 @@
 static void
 ccio_ioc_init(struct ioc *ioc)
 {
-	int i, iov_order;
+	int i;
+	unsigned int iov_order;
 	u32 iova_space_size;
-	unsigned long physmem;
 
 	/*
 	** Determine IOVA Space size from memory size.
@@ -1269,17 +1282,16 @@
 	** Hot-Plug/Removal of PCI cards. (aka PCI OLARD).
 	*/
 
+	iova_space_size = (u32) (num_physpages / count_parisc_driver(&ccio_driver));
+
 	/* limit IOVA space size to 1MB-1GB */
 
-	physmem = num_physpages << PAGE_SHIFT;
-	if(physmem < (ccio_mem_ratio * 1024 * 1024)) {
-		iova_space_size = 1024 * 1024;
+	if (iova_space_size < (1 << (20 - PAGE_SHIFT))) {
+		iova_space_size =  1 << (20 - PAGE_SHIFT);
 #ifdef __LP64__
-	} else if(physmem > (ccio_mem_ratio * 512 * 1024 * 1024)) {
-		iova_space_size = 512 * 1024 * 1024;
+	} else if (iova_space_size > (1 << (30 - PAGE_SHIFT))) {
+		iova_space_size =  1 << (30 - PAGE_SHIFT);
 #endif
-	} else {
-		iova_space_size = (u32)(physmem / ccio_mem_ratio);
 	}
 
 	/*
@@ -1295,10 +1307,10 @@
 	**   this is the case under linux."
 	*/
 
-	iov_order = get_order(iova_space_size) >> (IOVP_SHIFT - PAGE_SHIFT);
-	BUG_ON(iov_order > (30 - IOVP_SHIFT));   /* iova_space_size <= 1GB */
-	BUG_ON(iov_order < (20 - IOVP_SHIFT));   /* iova_space_size >= 1MB */
-	iova_space_size = 1 << (iov_order + IOVP_SHIFT);
+	iov_order = get_order(iova_space_size << PAGE_SHIFT);
+
+	/* iova_space_size is now bytes, not pages */
+	iova_space_size = 1 << (iov_order + PAGE_SHIFT);
 
 	ioc->pdir_size = (iova_space_size / IOVP_SIZE) * sizeof(u64);
 
@@ -1307,9 +1319,12 @@
 	/* Verify it's a power of two */
 	BUG_ON((1 << get_order(ioc->pdir_size)) != (ioc->pdir_size >> PAGE_SHIFT));
 
-	DBG_INIT("%s() hpa 0x%p mem %luMB IOV %dMB (%d bits) PDIR size 0x%0x",
-		__FUNCTION__, ioc->ioc_hpa, physmem>>20, iova_space_size>>20,
-		 iov_order + PAGE_SHIFT, ioc->pdir_size);
+	DBG_INIT("%s() hpa 0x%lx mem %luMB IOV %dMB (%d bits)\n",
+			__FUNCTION__,
+			ioc->ioc_hpa,
+			(unsigned long) num_physpages >> (20 - PAGE_SHIFT),
+			iova_space_size>>20,
+			iov_order + PAGE_SHIFT);
 
 	ioc->pdir_base = (u64 *)__get_free_pages(GFP_KERNEL, 
 						 get_order(ioc->pdir_size));
@@ -1565,19 +1580,6 @@
 	parisc_has_iommu();
 	return 0;
 }
-
-/* We *can't* support JAVA (T600). Venture there at your own risk. */
-static struct parisc_device_id ccio_tbl[] = {
-	{ HPHW_IOA, HVERSION_REV_ANY_ID, U2_IOA_RUNWAY, 0xb }, /* U2 */
-	{ HPHW_IOA, HVERSION_REV_ANY_ID, UTURN_IOA_RUNWAY, 0xb }, /* UTurn */
-	{ 0, }
-};
-
-static struct parisc_driver ccio_driver = {
-	.name =		"U2:Uturn",
-	.id_table =	ccio_tbl,
-	.probe =	ccio_probe,
-};
 
 /**
  * ccio_init - ccio initalization procedure.
diff -Nru a/drivers/parisc/dino.c b/drivers/parisc/dino.c
--- a/drivers/parisc/dino.c	2005-03-11 12:51:41 -08:00
+++ b/drivers/parisc/dino.c	2005-03-11 12:51:41 -08:00
@@ -653,14 +653,13 @@
 				      PCI_INTERRUPT_PIN, 1, &irq_pin);
 			irq_pin = (irq_pin + PCI_SLOT(dev->devfn) - 1) % 4 ;
 			printk(KERN_WARNING "Device %s has undefined IRQ, "
-					"setting to %d\n", dev->slot_name,
-					irq_pin);
+					"setting to %d\n", pci_name(dev), irq_pin);
 			dino_cfg_write(dev->bus, dev->devfn, 
 				       PCI_INTERRUPT_LINE, 1, irq_pin);
 			dino_assign_irq(dino_dev, irq_pin, &dev->irq);
 #else
 			dev->irq = 65535;
-			printk(KERN_WARNING "Device %s has unassigned IRQ\n", dev->slot_name);	
+			printk(KERN_WARNING "Device %s has unassigned IRQ\n", pci_name(dev));
 #endif
 		} else {
 
diff -Nru a/drivers/parisc/eisa.c b/drivers/parisc/eisa.c
--- a/drivers/parisc/eisa.c	2005-03-11 12:51:40 -08:00
+++ b/drivers/parisc/eisa.c	2005-03-11 12:51:40 -08:00
@@ -44,6 +44,7 @@
 #include <asm/parisc-device.h>
 #include <asm/delay.h>
 #include <asm/eisa_bus.h>
+#include <asm/eisa_eeprom.h>
 
 #if 0
 #define EISA_DBG(msg, arg... ) printk(KERN_DEBUG "eisa: " msg , ## arg )
@@ -56,6 +57,8 @@
 
 static DEFINE_SPINLOCK(eisa_irq_lock);
 
+void __iomem *eisa_eeprom_addr;
+
 /* We can only have one EISA adapter in the system because neither
  * implementation can be flexed.
  */
@@ -351,6 +354,7 @@
 	}
 	
 	EISA_bus = 1;
+
 	if (dev->num_addrs) {
 		/* newer firmware hand out the eeprom address */
 		eisa_dev.eeprom_addr = dev->addr[0];
@@ -362,8 +366,9 @@
 			eisa_dev.eeprom_addr = MIRAGE_EEPROM_BASE_ADDR;
 		}
 	}
-	eisa_eeprom_init(eisa_dev.eeprom_addr);
-	result = eisa_enumerator(eisa_dev.eeprom_addr, &eisa_dev.hba.io_space, &eisa_dev.hba.lmmio_space);
+	eisa_eeprom_addr = ioremap(eisa_dev.eeprom_addr, HPEE_MAX_LENGTH);
+	result = eisa_enumerator(eisa_dev.eeprom_addr, &eisa_dev.hba.io_space,
+			&eisa_dev.hba.lmmio_space);
 	init_eisa_pic();
 
 	if (result >= 0) {
diff -Nru a/drivers/parisc/eisa_eeprom.c b/drivers/parisc/eisa_eeprom.c
--- a/drivers/parisc/eisa_eeprom.c	2005-03-11 12:51:51 -08:00
+++ b/drivers/parisc/eisa_eeprom.c	2005-03-11 12:51:51 -08:00
@@ -19,7 +19,6 @@
  *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
@@ -32,8 +31,6 @@
 
 #define 	EISA_EEPROM_MINOR 241
 
-static unsigned long eeprom_addr;
-
 static loff_t eisa_eeprom_llseek(struct file *file, loff_t offset, int origin )
 {
 	switch (origin) {
@@ -64,7 +61,7 @@
 	tmp = kmalloc(count, GFP_KERNEL);
 	if (tmp) {
 		for (i = 0; i < count; i++)
-			tmp[i] = gsc_readb(eeprom_addr+(*ppos)++);
+			tmp[i] = readb(eisa_eeprom_addr+(*ppos)++);
 
 		if (copy_to_user (buf, tmp, count))
 			ret = -EFAULT;
@@ -86,7 +83,7 @@
 
 static int eisa_eeprom_open(struct inode *inode, struct file *file)
 {
-	if (file->f_mode & 2 || eeprom_addr == 0)
+	if (file->f_mode & 2)
 		return -EINVAL;
    
 	return 0;
@@ -109,22 +106,18 @@
 	.release =	eisa_eeprom_release,
 };
 
-static struct miscdevice eisa_eeprom_dev=
-{
+static struct miscdevice eisa_eeprom_dev = {
 	EISA_EEPROM_MINOR,
-	"eisa eeprom",
+	"eisa_eeprom",
 	&eisa_eeprom_fops
 };
 
-int __init eisa_eeprom_init(unsigned long addr)
+static int __init eisa_eeprom_init(void)
 {
 	int retval;
 
-	/* XXX why return success when we haven't done anything? */
-	if (!addr)
-		return 0;
-
-	eeprom_addr = addr;
+	if (!eisa_eeprom_addr)
+		return -ENODEV;
 
 	retval = misc_register(&eisa_eeprom_dev);
 	if (retval < 0) {
@@ -132,8 +125,10 @@
 		return retval;
 	}
 
-	printk(KERN_INFO "EISA EEPROM at 0x%lx\n", eeprom_addr);
+	printk(KERN_INFO "EISA EEPROM at 0x%p\n", eisa_eeprom_addr);
 	return 0;
 }
 
 MODULE_LICENSE("GPL");
+
+module_init(eisa_eeprom_init);
diff -Nru a/drivers/parisc/gsc.c b/drivers/parisc/gsc.c
--- a/drivers/parisc/gsc.c	2005-03-11 12:51:51 -08:00
+++ b/drivers/parisc/gsc.c	2005-03-11 12:51:51 -08:00
@@ -38,14 +38,14 @@
 
 int gsc_alloc_irq(struct gsc_irq *i)
 {
-	int irq = txn_alloc_irq();
+	int irq = txn_alloc_irq(GSC_EIM_WIDTH);
 	if (irq < 0) {
 		printk("cannot get irq\n");
 		return irq;
 	}
 
 	i->txn_addr = txn_alloc_addr(irq);
-	i->txn_data = txn_alloc_data(irq, GSC_EIM_WIDTH);
+	i->txn_data = txn_alloc_data(irq);
 	i->irq = irq;
 
 	return irq;
@@ -64,7 +64,7 @@
 	}
 
 	i->txn_addr = txn_alloc_addr(irq);
-	i->txn_data = txn_alloc_data(irq, GSC_EIM_WIDTH);
+	i->txn_data = txn_alloc_data(irq);
 	i->irq = irq;
 
 	return irq;
diff -Nru a/drivers/parisc/hppb.c b/drivers/parisc/hppb.c
--- a/drivers/parisc/hppb.c	2005-03-11 12:51:52 -08:00
+++ b/drivers/parisc/hppb.c	2005-03-11 12:51:52 -08:00
@@ -16,7 +16,6 @@
 **
 */
 
-#include <linux/config.h>
 #include <linux/types.h>
 #include <linux/init.h>
 #include <linux/mm.h>
diff -Nru a/drivers/parisc/iosapic.c b/drivers/parisc/iosapic.c
--- a/drivers/parisc/iosapic.c	2005-03-11 12:51:52 -08:00
+++ b/drivers/parisc/iosapic.c	2005-03-11 12:51:52 -08:00
@@ -158,31 +158,9 @@
 
 
 #ifdef DEBUG_IOSAPIC
-static char assert_buf[128];
-
-static int
-assert_failed (char *a, char *f, int l)
-{
-        sprintf(assert_buf,
-			"ASSERT(%s) failed!\nline %d in %s\n",
-			a,      /* assertion text */
-			l,      /* line number */
-			f);     /* file name */
-        panic(assert_buf);
-	return 0;
-}
-
-#undef ASSERT
-#define ASSERT(EX) { if (!(EX)) assert_failed(# EX, __FILE__, __LINE__); }
-
 #define DBG(x...) printk(x)
-
 #else /* DEBUG_IOSAPIC */
-
 #define DBG(x...)
-#undef	ASSERT
-#define ASSERT(EX)
-
 #endif /* DEBUG_IOSAPIC */
 
 #ifdef DEBUG_IOSAPIC_IRT
@@ -191,6 +169,12 @@
 #define DBG_IRT(x...)
 #endif
 
+#ifdef CONFIG_64BIT
+#define COMPARE_IRTE_ADDR(irte, hpa)	((irte)->dest_iosapic_addr == (hpa))
+#else
+#define COMPARE_IRTE_ADDR(irte, hpa)	\
+		((irte)->dest_iosapic_addr == ((hpa) | 0xffffffff00000000ULL))
+#endif
 
 #define IOSAPIC_REG_SELECT              0x00
 #define IOSAPIC_REG_WINDOW              0x10
@@ -201,33 +185,18 @@
 #define IOSAPIC_IRDT_ENTRY(idx)		(0x10+(idx)*2)
 #define IOSAPIC_IRDT_ENTRY_HI(idx)	(0x11+(idx)*2)
 
-static inline unsigned int iosapic_read(unsigned long iosapic, unsigned int reg)
+static inline unsigned int iosapic_read(void __iomem *iosapic, unsigned int reg)
 {
 	writel(reg, iosapic + IOSAPIC_REG_SELECT);
 	return readl(iosapic + IOSAPIC_REG_WINDOW);
 }
 
-static inline void iosapic_write(unsigned long iosapic, unsigned int reg, u32 val)
+static inline void iosapic_write(void __iomem *iosapic, unsigned int reg, u32 val)
 {
 	writel(reg, iosapic + IOSAPIC_REG_SELECT);
 	writel(val, iosapic + IOSAPIC_REG_WINDOW);
 }
 
-/*
-**     GFP_KERNEL includes __GFP_WAIT flag and that may not
-**     be acceptable. Since this is boot time, we shouldn't have
-**     to wait ever and this code should (will?) never get called
-**     from the interrrupt context.
-*/
-#define	IOSAPIC_KALLOC(a_type, cnt) \
-			(a_type *) kmalloc(sizeof(a_type)*(cnt), GFP_KERNEL)
-#define IOSAPIC_FREE(addr, f_type, cnt) kfree((void *)addr)
-
-
-#define	IOSAPIC_LOCK(lck)	spin_lock_irqsave(lck, irqflags)
-#define	IOSAPIC_UNLOCK(lck)	spin_unlock_irqrestore(lck, irqflags)
-
-
 #define IOSAPIC_VERSION_MASK	0x000000ff
 #define	IOSAPIC_VERSION(ver)	((int) (ver & IOSAPIC_VERSION_MASK))
 
@@ -265,52 +234,64 @@
 static struct irt_entry *irt_cell;
 static size_t irt_num_entry;
 
+static struct irt_entry *iosapic_alloc_irt(int num_entries)
+{
+	unsigned long a;
 
+	/* The IRT needs to be 8-byte aligned for the PDC call. 
+	 * Normally kmalloc would guarantee larger alignment, but
+	 * if CONFIG_DEBUG_SLAB is enabled, then we can get only
+	 * 4-byte alignment on 32-bit kernels
+	 */
+	a = (unsigned long)kmalloc(sizeof(struct irt_entry) * num_entries + 8, GFP_KERNEL);
+	a = (a + 7) & ~7;
+	return (struct irt_entry *)a;
+}
 
-/*
-** iosapic_load_irt
-**
-** The "Get PCI INT Routing Table Size" option returns the number of 
-** entries in the PCI interrupt routing table for the cell specified 
-** in the cell_number argument.  The cell number must be for a cell 
-** within the caller's protection domain.
-**
-** The "Get PCI INT Routing Table" option returns, for the cell 
-** specified in the cell_number argument, the PCI interrupt routing 
-** table in the caller allocated memory pointed to by mem_addr.
-** We assume the IRT only contains entries for I/O SAPIC and
-** calculate the size based on the size of I/O sapic entries.
-**
-** The PCI interrupt routing table entry format is derived from the
-** IA64 SAL Specification 2.4.   The PCI interrupt routing table defines
-** the routing of PCI interrupt signals between the PCI device output
-** "pins" and the IO SAPICs' input "lines" (including core I/O PCI
-** devices).  This table does NOT include information for devices/slots
-** behind PCI to PCI bridges. See PCI to PCI Bridge Architecture Spec.
-** for the architected method of routing of IRQ's behind PPB's.
-*/
+/**
+ * iosapic_load_irt - Fill in the interrupt routing table
+ * @cell_num: The cell number of the CPU we're currently executing on
+ * @irt: The address to place the new IRT at
+ * @return The number of entries found
+ *
+ * The "Get PCI INT Routing Table Size" option returns the number of 
+ * entries in the PCI interrupt routing table for the cell specified 
+ * in the cell_number argument.  The cell number must be for a cell 
+ * within the caller's protection domain.
+ *
+ * The "Get PCI INT Routing Table" option returns, for the cell 
+ * specified in the cell_number argument, the PCI interrupt routing 
+ * table in the caller allocated memory pointed to by mem_addr.
+ * We assume the IRT only contains entries for I/O SAPIC and
+ * calculate the size based on the size of I/O sapic entries.
+ *
+ * The PCI interrupt routing table entry format is derived from the
+ * IA64 SAL Specification 2.4.   The PCI interrupt routing table defines
+ * the routing of PCI interrupt signals between the PCI device output
+ * "pins" and the IO SAPICs' input "lines" (including core I/O PCI
+ * devices).  This table does NOT include information for devices/slots
+ * behind PCI to PCI bridges. See PCI to PCI Bridge Architecture Spec.
+ * for the architected method of routing of IRQ's behind PPB's.
+ */
 
 
-static int __init /* return number of entries as success/fail flag */
+static int __init
 iosapic_load_irt(unsigned long cell_num, struct irt_entry **irt)
 {
 	long status;              /* PDC return value status */
 	struct irt_entry *table;  /* start of interrupt routing tbl */
 	unsigned long num_entries = 0UL;
 
-	ASSERT(NULL != irt);
+	BUG_ON(!irt);
 
 	if (is_pdc_pat()) {
-
 		/* Use pat pdc routine to get interrupt routing table size */
 		DBG("calling get_irt_size (cell %ld)\n", cell_num);
 		status = pdc_pat_get_irt_size(&num_entries, cell_num);
 		DBG("get_irt_size: %ld\n", status);
 
-		ASSERT(status == PDC_OK);
-
-		/* save the number of entries in the table */
-		ASSERT(0UL != num_entries);
+		BUG_ON(status != PDC_OK);
+		BUG_ON(num_entries == 0);
 
 		/*
 		** allocate memory for interrupt routing table
@@ -318,45 +299,47 @@
 		** the contents of the table are exclusively
 		** for I/O sapic devices.
 		*/
-		table = IOSAPIC_KALLOC(struct irt_entry, num_entries);
+		table = iosapic_alloc_irt(num_entries);
 		if (table == NULL) {
-			printk(KERN_WARNING MODULE_NAME ": read_irt : can not alloc mem for IRT\n");
+			printk(KERN_WARNING MODULE_NAME ": read_irt : can "
+					"not alloc mem for IRT\n");
 			return 0;
 		}
 
 		/* get PCI INT routing table */
 		status = pdc_pat_get_irt(table, cell_num);
 		DBG("pdc_pat_get_irt: %ld\n", status);
-		ASSERT(status == PDC_OK);
+		WARN_ON(status != PDC_OK);
 	} else {
 		/*
 		** C3000/J5000 (and similar) platforms with Sprockets PDC
 		** will return exactly one IRT for all iosapics.
 		** So if we have one, don't need to get it again.
 		*/
-		if (NULL != irt_cell)
+		if (irt_cell)
 			return 0;
 
 		/* Should be using the Elroy's HPA, but it's ignored anyway */
 		status = pdc_pci_irt_size(&num_entries, 0);
 		DBG("pdc_pci_irt_size: %ld\n", status);
 
-		if (PDC_OK != status) {
+		if (status != PDC_OK) {
 			/* Not a "legacy" system with I/O SAPIC either */
 			return 0;
 		}
 
-		ASSERT(0UL != num_entries);
+		BUG_ON(num_entries == 0);
 
-		table = IOSAPIC_KALLOC(struct irt_entry, num_entries);
-		if (table == NULL) {
-			printk(KERN_WARNING MODULE_NAME ": read_irt : can not alloc mem for IRT\n");
+		table = iosapic_alloc_irt(num_entries);
+		if (!table) {
+			printk(KERN_WARNING MODULE_NAME ": read_irt : can "
+					"not alloc mem for IRT\n");
 			return 0;
 		}
 
 		/* HPA ignored by this call too. */
 		status = pdc_pci_irt(num_entries, 0, table);
-		ASSERT(PDC_OK == status);
+		BUG_ON(status != PDC_OK);
 	}
 
 	/* return interrupt table address */
@@ -390,16 +373,10 @@
 
 
 
-void __init
-iosapic_init(void)
+void __init iosapic_init(void)
 {
 	unsigned long cell = 0;
 
-	/* init global data */
-	spin_lock_init(&iosapic_lock);
-        iosapic_list = (struct iosapic_info *) NULL;
-	iosapic_count = 0;
-
 	DBG("iosapic_init()\n");
 
 #ifdef __LP64__
@@ -414,11 +391,9 @@
 	}
 #endif
 
-	/*
-	**  get IRT for this cell.
-	*/
-	irt_num_entry =  iosapic_load_irt(cell, &irt_cell);
-	if (0 == irt_num_entry)
+	/* get interrupt routing table for this cell */
+	irt_num_entry = iosapic_load_irt(cell, &irt_cell);
+	if (irt_num_entry == 0)
 		irt_cell = NULL;	/* old PDC w/o iosapic */
 }
 
@@ -459,10 +434,7 @@
 			continue;
 		}
 
-		/*
-		** Compare: dest_iosapic_addr, src_bus_irq_devno
-		*/
-		if (i->dest_iosapic_addr != (u64) ((long) isi->isi_hpa))
+		if (!COMPARE_IRTE_ADDR(i, isi->isi_hpa))
 			continue;
 
 		if ((i->src_bus_irq_devno & IRT_IRQ_DEVNO_MASK) != irq_devno)
@@ -506,10 +478,10 @@
 
 	pci_read_config_byte(pcidev, PCI_INTERRUPT_PIN, &intr_pin);
 
-	DBG_IRT("iosapic_xlate_pin() SLOT %d pin %d\n",
-		PCI_SLOT(pcidev->devfn), intr_pin);
+	DBG_IRT("iosapic_xlate_pin(%s) SLOT %d pin %d\n",
+		pcidev->slot_name, PCI_SLOT(pcidev->devfn), intr_pin);
 
-	if (0 == intr_pin) {
+	if (intr_pin == 0) {
 		/* The device does NOT support/use IRQ lines.  */
 		return NULL;
 	}
@@ -606,7 +578,6 @@
 {
 	u32 mode = 0;
 	struct irt_entry *p = vi->irte;
-	ASSERT(NULL != vi->irte);
 
 	if ((p->polarity_trigger & IRT_PO_MASK) == IRT_ACTIVE_LO)
 		mode |= IOSAPIC_IRDT_PO_LOW;
@@ -619,7 +590,6 @@
 	** PA doesn't support EXTINT or LPRIO bits.
 	*/
 
-	ASSERT(vi->txn_data);
 	*dp0 = mode | (u32) vi->txn_data;
 
 	/*
@@ -802,22 +772,23 @@
 
 	vi->irte = irte;
 
-	/* Allocate processor IRQ */
-	vi->txn_irq = txn_alloc_irq();
-
 	/*
+	 * Allocate processor IRQ
+	 *
 	 * XXX/FIXME The txn_alloc_irq() code and related code should be
 	 * moved to enable_irq(). That way we only allocate processor IRQ
 	 * bits for devices that actually have drivers claiming them.
 	 * Right now we assign an IRQ to every PCI device present,
 	 * regardless of whether it's used or not.
 	 */
+	vi->txn_irq = txn_alloc_irq(8);
+
 	if (vi->txn_irq < 0)
 		panic("I/O sapic: couldn't get TXN IRQ\n");
 
 	/* enable_irq() will use txn_* to program IRdT */
 	vi->txn_addr = txn_alloc_addr(vi->txn_irq);
-	vi->txn_data = txn_alloc_data(vi->txn_irq, 8);
+	vi->txn_data = txn_alloc_data(vi->txn_irq);
 
 	vi->eoi_addr = isi->addr + IOSAPIC_REG_EOI;
 	vi->eoi_data = cpu_to_le32(vi->txn_data);
@@ -841,10 +812,7 @@
 static unsigned int
 iosapic_rd_version(struct iosapic_info *isi)
 {
-	ASSERT(isi);
-	ASSERT(isi->isi_hpa);
-
-	return iosapic_read(isi->isi_hpa, IOSAPIC_REG_VERSION);
+	return iosapic_read(isi->addr, IOSAPIC_REG_VERSION);
 }
 
 
@@ -866,44 +834,38 @@
 	int cnt;	/* track how many entries we've looked at */
 
 	/*
-	** Astro based platforms can't support PCI OLARD if they
-	** implement the legacy PDC (not PAT). Though Legacy PDC
-	** supports an IRT, LBA's with no device under them
-	** are *not* listed in the IRT.
-	** Search the IRT and ignore iosapic's which aren't
-	** in the IRT.
-	*/
-	ASSERT(NULL != irte);	/* always have built-in devices */
+	 * Astro based platforms can only support PCI OLARD if they implement
+	 * PAT PDC.  Legacy PDC omits LBAs with no PCI devices from the IRT.
+	 * Search the IRT and ignore iosapic's which aren't in the IRT.
+	 */
 	for (cnt=0; cnt < irt_num_entry; cnt++, irte++) {
-		ASSERT(IRT_IOSAPIC_TYPE == irte->entry_type);
-		/*
-		** We need sign extension of the hpa on 32-bit kernels.
-		** The address in the IRT is *always* 64 bit and really
-		** is an unsigned quantity (like all physical addresses).
-		*/ 
-		if (irte->dest_iosapic_addr == (s64) ((long) hpa))
+		WARN_ON(IRT_IOSAPIC_TYPE != irte->entry_type);
+		if (COMPARE_IRTE_ADDR(irte, hpa))
 			break;
 	}
 
-	if (cnt  >= irt_num_entry)
-		return (NULL);
+	if (cnt >= irt_num_entry) {
+		DBG("iosapic_register() ignoring 0x%lx (NOT FOUND)\n", hpa);
+		return NULL;
+	}
 
-	if ((isi = IOSAPIC_KALLOC(struct iosapic_info, 1)) == NULL) {
+	isi = (struct iosapic_info *)kmalloc(sizeof(struct iosapic_info), GFP_KERNEL);
+	if (!isi) {
 		BUG();
-		return (NULL);
+		return NULL;
 	}
 
 	memset(isi, 0, sizeof(struct iosapic_info));
 
-	isi->isi_hpa         = hpa;
-	isi->isi_version     = iosapic_rd_version(isi);
+	isi->addr = ioremap(hpa, 4096);
+	isi->isi_hpa = hpa;
+	isi->isi_version = iosapic_rd_version(isi);
 	isi->isi_num_vectors = IOSAPIC_IRDT_MAX_ENTRY(isi->isi_version) + 1;
 
-	vip = isi->isi_vector =
-		 IOSAPIC_KALLOC(struct vector_info, isi->isi_num_vectors);
-
+	vip = isi->isi_vector = (struct vector_info *)
+		kmalloc(sizeof(struct vector_info) * isi->isi_num_vectors, GFP_KERNEL);
 	if (vip == NULL) {
-		IOSAPIC_FREE(isi, struct iosapic_info, 1);
+		kfree(isi);
 		return NULL;
 	}
 
@@ -924,7 +886,6 @@
 {
 	unsigned int i, *irp = (unsigned int *) irt;
 
-	ASSERT(NULL != irt);
 
 	printk(KERN_DEBUG MODULE_NAME ": Interrupt Routing Table (%lx entries)\n", num_entry);
 
@@ -938,8 +899,6 @@
 static void
 iosapic_prt_vi(struct vector_info *vi)
 {
-	ASSERT(NULL != vi);
-
 	printk(KERN_DEBUG MODULE_NAME ": vector_info[%d] is at %p\n", vi->irqline, vi);
 	printk(KERN_DEBUG "\t\tstatus:	 %.4x\n", vi->status);
 	printk(KERN_DEBUG "\t\ttxn_irq:  %d\n",  vi->txn_irq);
@@ -953,10 +912,9 @@
 static void
 iosapic_prt_isi(struct iosapic_info *isi)
 {
-	ASSERT(NULL != isi);
 	printk(KERN_DEBUG MODULE_NAME ": io_sapic_info at %p\n", isi);
 	printk(KERN_DEBUG "\t\tisi_hpa:       %lx\n", isi->isi_hpa);
-	printk(KERN_DEBUG "\t\tisi_status:     %x\n", isi->isi_status);
+	printk(KERN_DEBUG "\t\tisi_status:    %x\n", isi->isi_status);
 	printk(KERN_DEBUG "\t\tisi_version:   %x\n", isi->isi_version);
 	printk(KERN_DEBUG "\t\tisi_vector:    %p\n", isi->isi_vector);
 }
diff -Nru a/drivers/parisc/lba_pci.c b/drivers/parisc/lba_pci.c
--- a/drivers/parisc/lba_pci.c	2005-03-11 12:51:47 -08:00
+++ b/drivers/parisc/lba_pci.c	2005-03-11 12:51:47 -08:00
@@ -51,11 +51,6 @@
 #include <asm/iosapic.h>	/* for iosapic_register() */
 #include <asm/io.h>		/* read/write stuff */
 
-#ifndef TRUE
-#define TRUE (1 == 1)
-#define FALSE (1 == 0)
-#endif
-
 #undef DEBUG_LBA	/* general stuff */
 #undef DEBUG_LBA_PORT	/* debug I/O Port access */
 #undef DEBUG_LBA_CFG	/* debug Config Space Access (ie PCI Bus walk) */
@@ -88,18 +83,6 @@
 #define DBG_PAT(x...)
 #endif
 
-#ifdef DEBUG_LBA
-#undef ASSERT
-#define ASSERT(expr) \
-	if(!(expr)) { \
-		printk("\n%s:%d: Assertion " #expr " failed!\n", \
-				__FILE__, __LINE__); \
-		panic(#expr); \
-	}
-#else
-#define ASSERT(expr)
-#endif
-
 
 /*
 ** Config accessor functions only pass in the 8-bit bus number and not
@@ -184,6 +167,7 @@
 
 /* non-postable I/O port space, densely packed */
 #define LBA_PORT_BASE	(PCI_F_EXTEND | 0xfee00000UL)
+static void __iomem *astro_iop_base;
 
 #define ELROY_HVERS	0x782
 #define MERCURY_HVERS	0x783
@@ -214,8 +198,8 @@
 	spinlock_t	lba_lock;
 	void		*iosapic_obj;
 
-#ifdef CONFIG_PARISC64
-	unsigned long	iop_base;    /* PA_VIEW - for IO port accessor funcs */
+#ifdef CONFIG_64BIT
+	void __iomem *	iop_base;    /* PA_VIEW - for IO port accessor funcs */
 #endif
 
 	int		flags;       /* state/functionality enabled */
@@ -225,15 +209,9 @@
 
 static u32 lba_t32;
 
-/*
-** lba "flags"
-*/
-#define LBA_FLAG_NO_DMA_DURING_CFG	0x01
+/* lba flags */
 #define LBA_FLAG_SKIP_PROBE	0x10
 
-/* Tape Release 4 == hw_rev 5 */
-#define LBA_TR4PLUS(d)      ((d)->hw_rev > 0x4)
-#define LBA_DMA_DURING_CFG_DISABLED(d) ((d)->flags & LBA_FLAG_NO_DMA_DURING_CFG)
 #define LBA_SKIP_PROBE(d) ((d)->flags & LBA_FLAG_SKIP_PROBE)
 
 
@@ -293,7 +271,7 @@
 
 	printk(KERN_DEBUG "(%p)", r->parent);
 	for (i = d; i ; --i) printk(" ");
-	printk(KERN_DEBUG "%p [%lx,%lx]/%x\n", r, r->start, r->end, (int) r->flags);
+	printk(KERN_DEBUG "%p [%lx,%lx]/%lx\n", r, r->start, r->end, r->flags);
 	lba_dump_res(r->child, d+2);
 	lba_dump_res(r->sibling, d);
 }
@@ -303,7 +281,7 @@
 ** LBA rev 2.0, 2.1, 2.2, and 3.0 bus walks require a complex
 ** workaround for cfg cycles:
 **	-- preserve  LBA state
-**	-- LBA_FLAG_NO_DMA_DURING_CFG workaround
+**	-- prevent any DMA from occurring
 **	-- turn on smart mode
 **	-- probe with config writes before doing config reads
 **	-- check ERROR_STATUS
@@ -313,25 +291,18 @@
 ** The workaround is only used for device discovery.
 */
 
-static int
-lba_device_present( u8 bus, u8 dfn, struct lba_device *d)
+static int lba_device_present(u8 bus, u8 dfn, struct lba_device *d)
 {
 	u8 first_bus = d->hba.hba_bus->secondary;
 	u8 last_sub_bus = d->hba.hba_bus->subordinate;
 
-	ASSERT(bus >= first_bus);
-	ASSERT(bus <= last_sub_bus);
-	ASSERT((bus - first_bus) < LBA_MAX_NUM_BUSES);
-
 	if ((bus < first_bus) ||
 	    (bus > last_sub_bus) ||
-	    ((bus - first_bus) >= LBA_MAX_NUM_BUSES))
-	{
-	    /* devices that fall into any of these cases won't get claimed */
-	    return(FALSE);
+	    ((bus - first_bus) >= LBA_MAX_NUM_BUSES)) {
+		return 0;
 	}
 
-	return TRUE;
+	return 1;
 }
 
 
@@ -346,7 +317,6 @@
     /* For LBA rev 2.0, 2.1, 2.2, and 3.0, we must disable DMA		\
     ** arbitration for full bus walks.					\
     */									\
-    if (LBA_DMA_DURING_CFG_DISABLED(d)) {				\
 	/* Save contents of arb mask register. */			\
 	arb_mask = READ_REG32(d->hba.base_addr + LBA_ARB_MASK);		\
 \
@@ -354,8 +324,7 @@
 	 * Turn off all device arbitration bits (i.e. everything	\
 	 * except arbitration enable bit).				\
 	 */								\
-	WRITE_REG32(0x1, d->hba.base_addr + LBA_ARB_MASK);			\
-    }									\
+	WRITE_REG32(0x1, d->hba.base_addr + LBA_ARB_MASK);		\
 \
     /*									\
      * Set the smart mode bit so that master aborts don't cause		\
@@ -375,7 +344,7 @@
      * Read address register to ensure that LBA is the bus master,	\
      * which implies that DMA traffic has stopped when DMA arb is off.	\
      */									\
-    lba_t32 = READ_REG32((d)->hba.base_addr + LBA_PCI_CFG_ADDR);		\
+    lba_t32 = READ_REG32((d)->hba.base_addr + LBA_PCI_CFG_ADDR);	\
     /*									\
      * Generate a cfg write cycle (will have no affect on		\
      * Vendor ID register since read-only).				\
@@ -385,7 +354,7 @@
      * Make sure write has completed before proceeding further,		\
      * i.e. before setting clear enable.				\
      */									\
-    lba_t32 = READ_REG32((d)->hba.base_addr + LBA_PCI_CFG_ADDR);		\
+    lba_t32 = READ_REG32((d)->hba.base_addr + LBA_PCI_CFG_ADDR);	\
 }
 
 
@@ -439,20 +408,16 @@
     }									\
 }
 
-#define LBA_CFG_TR4_ADDR_SETUP(d, addr) \
-    WRITE_REG32(((addr) & ~3), (d)->hba.base_addr + LBA_PCI_CFG_ADDR); \
-    lba_t32 = READ_REG32((d)->hba.base_addr + LBA_PCI_CFG_ADDR)
+#define LBA_CFG_TR4_ADDR_SETUP(d, addr)					\
+	WRITE_REG32(((addr) & ~3), (d)->hba.base_addr + LBA_PCI_CFG_ADDR);
 
-#define LBA_CFG_ADDR_SETUP(d, addr) {				\
+#define LBA_CFG_ADDR_SETUP(d, addr) {					\
     WRITE_REG32(((addr) & ~3), (d)->hba.base_addr + LBA_PCI_CFG_ADDR);	\
     /*									\
-     * HPREVISIT:							\
-     *       --	Potentially could skip this once DMA bug fixed.		\
-     *									\
      * Read address register to ensure that LBA is the bus master,	\
      * which implies that DMA traffic has stopped when DMA arb is off.	\
      */									\
-    lba_t32 = READ_REG32((d)->hba.base_addr + LBA_PCI_CFG_ADDR);		\
+    lba_t32 = READ_REG32((d)->hba.base_addr + LBA_PCI_CFG_ADDR);	\
 }
 
 
@@ -465,12 +430,10 @@
      * Restore error config register (turn off smart mode).		\
      */									\
     WRITE_REG32(error_config, base + LBA_ERROR_CONFIG);			\
-    if (LBA_DMA_DURING_CFG_DISABLED(d)) {				\
 	/*								\
 	 * Restore arb mask register (reenables DMA arbitration).	\
 	 */								\
 	WRITE_REG32(arb_mask, base + LBA_ARB_MASK);			\
-    }									\
 }
 
 
@@ -478,39 +441,23 @@
 static unsigned int
 lba_rd_cfg(struct lba_device *d, u32 tok, u8 reg, u32 size)
 {
-	u32 data = ~0;
+	u32 data = ~0U;
 	int error = 0;
 	u32 arb_mask = 0;	/* used by LBA_CFG_SETUP/RESTORE */
 	u32 error_config = 0;	/* used by LBA_CFG_SETUP/RESTORE */
 	u32 status_control = 0;	/* used by LBA_CFG_SETUP/RESTORE */
 
-	ASSERT((size == sizeof(u8)) ||
-		(size == sizeof(u16)) ||
-		(size == sizeof(u32)));
-
-	if ((size != sizeof(u8)) &&
-		(size != sizeof(u16)) &&
-		(size != sizeof(u32))) {
-		return(data);
-	}
-
 	LBA_CFG_SETUP(d, tok);
 	LBA_CFG_PROBE(d, tok);
 	LBA_CFG_MASTER_ABORT_CHECK(d, d->hba.base_addr, tok, error);
 	if (!error) {
+		void __iomem *data_reg = d->hba.base_addr + LBA_PCI_CFG_DATA;
+
 		LBA_CFG_ADDR_SETUP(d, tok | reg);
 		switch (size) {
-		case sizeof(u8):
-			data = (u32) READ_REG8(d->hba.base_addr + LBA_PCI_CFG_DATA + (reg & 3));
-			break;
-		case sizeof(u16):
-			data = (u32) READ_REG16(d->hba.base_addr + LBA_PCI_CFG_DATA + (reg & 2));
-			break;
-		case sizeof(u32):
-			data = READ_REG32(d->hba.base_addr + LBA_PCI_CFG_DATA);
-			break;
-		default:
-			break; /* leave data as -1 */
+		case 1: data = (u32) READ_REG8(data_reg + (reg & 3)); break;
+		case 2: data = (u32) READ_REG16(data_reg+ (reg & 2)); break;
+		case 4: data = READ_REG32(data_reg); break;
 		}
 	}
 	LBA_CFG_RESTORE(d, d->hba.base_addr);
@@ -518,142 +465,26 @@
 }
 
 
-#if USE_PAT_PDC_CFG
-
-/* PAT PDC needs to be relocated in order to perform properly.
- * tg3 driver does about 1600 PCI Cfg writes to initialize the card.
- * On 440Mhz A500, PDC takes ~20ms/write, or ~30 seconds per card.
- * On PA8800, that takes about 5ms/write (8 seconds).
- * But relocating PDC will burn at least 4MB of RAM.
- * Easier/Cheaper to just maintain our own mercury cfg ops.
- */
-#define pat_cfg_addr(bus, devfn, addr) (((bus) << 16) | ((devfn) << 8) | (addr))
-
-static int pat_cfg_read(struct pci_bus *bus, unsigned int devfn, int pos, int size, u32 *data)
-{
-	int tok = pat_cfg_addr(bus->number, devfn, pos);
-	u32 tmp;
-	int ret = pdc_pat_io_pci_cfg_read(tok, size, &tmp);
-
-	DBG_CFG("%s(%d:%d.%d+0x%02x) -> 0x%x %d\n", __FUNCTION__, bus->number, PCI_SLOT(devfn), PCI_FUNC(devfn), pos, tmp, ret);
-
-	switch (size) {
-		case 1: *data = (u8)  tmp; return (tmp == (u8)  ~0);
-		case 2: *data = (u16) tmp; return (tmp == (u16) ~0);
-		case 4: *data = (u32) tmp; return (tmp == (u32) ~0);
-	}
-	*data = ~0;
-	return (ret);
-}
-
-static int pat_cfg_write(struct pci_bus *bus, unsigned int devfn, int pos, int size, u32 data)
-{
-	int tok = pat_cfg_addr(bus->number, devfn, pos);
-	int ret = pdc_pat_io_pci_cfg_write(tok, size, data);
-
-	DBG_CFG("%s(%d:%d.%d+0x%02x, 0x%lx/%d)\n", __FUNCTION__, bus->number, PCI_SLOT(devfn), PCI_FUNC(devfn), pos, data, size);
-	return (ret);
-}
-
-static struct pci_ops pat_cfg_ops = {
-	.read =		pat_cfg_read,
-	.write =	pat_cfg_write,
-};
-#endif
-
-
-#ifdef CONFIG_PARISC64
-static int mercury_cfg_read(struct pci_bus *bus, unsigned int devfn, int pos, int size, u32 *data)
+static int elroy_cfg_read(struct pci_bus *bus, unsigned int devfn, int pos, int size, u32 *data)
 {
 	struct lba_device *d = LBA_DEV(parisc_walk_tree(bus->bridge));
 	u32 local_bus = (bus->parent == NULL) ? 0 : bus->secondary;
 	u32 tok = LBA_CFG_TOK(local_bus, devfn);
+	void __iomem *data_reg = d->hba.base_addr + LBA_PCI_CFG_DATA;
 
-	/* Basic Algorithm
-	** Should only get here on fully working LBA rev.
-	** This is how simple the original LBA code should have been.
-	*/
-	LBA_CFG_TR4_ADDR_SETUP(d, tok | pos);
-	switch(size) {
-	case 1: *(u8 *)  data = READ_REG8(d->hba.base_addr + LBA_PCI_CFG_DATA
-							+ (pos & 3));
-		DBG_CFG("%s(%x+%2x) -> 0x%x (c)\n", __FUNCTION__, tok, pos,
-				*(u8 *)data);
-		return(*(u8 *)data == (u8) ~0U);
-	case 2: *(u16 *) data = READ_REG16(d->hba.base_addr + LBA_PCI_CFG_DATA
-							+ (pos & 2));
-		DBG_CFG("%s(%x+%2x) -> 0x%x (c)\n", __FUNCTION__, tok, pos,
-				*(u16 *)data);
-		return(*(u16 *)data == (u16) ~0U);
-	case 4: *(u32 *) data = READ_REG32(d->hba.base_addr + LBA_PCI_CFG_DATA);
-		DBG_CFG("%s(%x+%2x) -> 0x%x (c)\n", __FUNCTION__, tok, pos, *data);
-		return(*data == ~0U);
-	}
-	DBG_CFG("%s(%x+%2x) -> bad size (%d)\n", __FUNCTION__, tok, pos, size);
-	*data = ~0U;
-	return(!PCIBIOS_SUCCESSFUL);	/* failed */
-}
-
-/*
- * LBA 4.0 config write code implements non-postable semantics
- * by doing a read of CONFIG ADDR after the write.
- */
-
-static int mercury_cfg_write(struct pci_bus *bus, unsigned int devfn, int pos, int size, u32 data)
-{
-	struct lba_device *d = LBA_DEV(parisc_walk_tree(bus->bridge));
-	unsigned long data_reg = d->hba.base_addr + LBA_PCI_CFG_DATA;
-	u32 local_bus = (bus->parent == NULL) ? 0 : bus->secondary;
-	u32 tok = LBA_CFG_TOK(local_bus,devfn);
-
- 	ASSERT((tok & 0xff) == 0);
-	ASSERT(pos < 0x100);
-
-	DBG_CFG("%s(%x+%2x) <- 0x%x (c)\n", __FUNCTION__, tok, pos, data);
-
-	/* Basic Algorithm */
-	LBA_CFG_TR4_ADDR_SETUP(d, tok | pos);
-	switch(size) {
-	case 1:		WRITE_REG8 (data, data_reg + (pos & 3)); break;
-	case 2:		WRITE_REG16(data, data_reg + (pos & 2)); break;
-	case 4:		WRITE_REG32(data, data_reg);             break;
-	default: 
-		DBG_CFG("%s(%x+%2x) WTF! size %d\n", __FUNCTION__, tok, pos,
-				size);
-	}
-
-	/* flush posted write */
-	lba_t32 = READ_U32(d->hba.base_addr + LBA_PCI_CFG_ADDR);
-	return PCIBIOS_SUCCESSFUL;
-}
-
-
-static struct pci_ops mercury_cfg_ops = {
-	.read =		mercury_cfg_read,
-	.write =	mercury_cfg_write,
-};
-#else
-#define mercury_cfg_ops lba_cfg_ops
-#endif /* CONFIG_PARISC64 */
-
-
-static int lba_cfg_read(struct pci_bus *bus, unsigned int devfn, int pos, int size, u32 *data)
-{
-	struct lba_device *d = LBA_DEV(parisc_walk_tree(bus->bridge));
-	u32 local_bus = (bus->parent == NULL) ? 0 : bus->secondary;
-	u32 tok = LBA_CFG_TOK(local_bus, devfn);
+	if ((pos > 255) || (devfn > 255))
+		return -EINVAL;
 
 /* FIXME: B2K/C3600 workaround is always use old method... */
-	/* if (!LBA_TR4PLUS(d) && !LBA_SKIP_PROBE(d)) */ {
+	/* if (!LBA_SKIP_PROBE(d)) */ {
 		/* original - Generate config cycle on broken elroy
 		  with risk we will miss PCI bus errors. */
 		*data = lba_rd_cfg(d, tok, pos, size);
 		DBG_CFG("%s(%x+%2x) -> 0x%x (a)\n", __FUNCTION__, tok, pos, *data);
-		return(*data == ~0U);
+		return 0;
 	}
 
-	if (LBA_SKIP_PROBE(d) && (!lba_device_present(bus->secondary, devfn, d)))
-	{
+	if (LBA_SKIP_PROBE(d) && !lba_device_present(bus->secondary, devfn, d)) {
 		DBG_CFG("%s(%x+%2x) -> -1 (b)\n", __FUNCTION__, tok, pos);
 		/* either don't want to look or know device isn't present. */
 		*data = ~0U;
@@ -664,52 +495,32 @@
 	** Should only get here on fully working LBA rev.
 	** This is how simple the code should have been.
 	*/
-	LBA_CFG_TR4_ADDR_SETUP(d, tok | pos);
+	LBA_CFG_ADDR_SETUP(d, tok | pos);
 	switch(size) {
-	case 1: *(u8 *)  data = READ_REG8(d->hba.base_addr + LBA_PCI_CFG_DATA + (pos & 3));
-		break;
-	case 2: *(u16 *) data = READ_REG16(d->hba.base_addr + LBA_PCI_CFG_DATA + (pos & 2));
-		break;
-	case 4: *(u32 *) data = READ_REG32(d->hba.base_addr + LBA_PCI_CFG_DATA);
-	   break;
+	case 1: *data = READ_REG8 (data_reg + (pos & 3)); break;
+	case 2: *data = READ_REG16(data_reg + (pos & 2)); break;
+	case 4: *data = READ_REG32(data_reg); break;
 	}
 	DBG_CFG("%s(%x+%2x) -> 0x%x (c)\n", __FUNCTION__, tok, pos, *data);
-	return(*data == ~0U);
+	return 0;
 }
 
 
 static void
-lba_wr_cfg( struct lba_device *d, u32 tok, u8 reg, u32 data, u32 size)
+lba_wr_cfg(struct lba_device *d, u32 tok, u8 reg, u32 data, u32 size)
 {
 	int error = 0;
 	u32 arb_mask = 0;
 	u32 error_config = 0;
 	u32 status_control = 0;
-
-	ASSERT((size == sizeof(u8)) ||
-		(size == sizeof(u16)) ||
-		(size == sizeof(u32)));
-
-	if ((size != sizeof(u8)) &&
-		(size != sizeof(u16)) &&
-		(size != sizeof(u32))) {
-			return;
-	}
+	void __iomem *data_reg = d->hba.base_addr + LBA_PCI_CFG_DATA;
 
 	LBA_CFG_SETUP(d, tok);
 	LBA_CFG_ADDR_SETUP(d, tok | reg);
 	switch (size) {
-	case sizeof(u8):
-		WRITE_REG8((u8) data, d->hba.base_addr + LBA_PCI_CFG_DATA + (reg&3));
-		break;
-	case sizeof(u16):
-		WRITE_REG16((u8) data, d->hba.base_addr + LBA_PCI_CFG_DATA +(reg&2));
-		break;
-	case sizeof(u32):
-		WRITE_REG32(data, d->hba.base_addr + LBA_PCI_CFG_DATA);
-		break;
-	default:
-		break;
+	case 1: WRITE_REG8 (data, data_reg + (reg & 3)); break;
+	case 2: WRITE_REG16(data, data_reg + (reg & 2)); break;
+	case 4: WRITE_REG32(data, data_reg);             break;
 	}
 	LBA_CFG_MASTER_ABORT_CHECK(d, d->hba.base_addr, tok, error);
 	LBA_CFG_RESTORE(d, d->hba.base_addr);
@@ -721,16 +532,16 @@
  * by doing a read of CONFIG ADDR after the write.
  */
 
-static int lba_cfg_write(struct pci_bus *bus, unsigned int devfn, int pos, int size, u32 data)
+static int elroy_cfg_write(struct pci_bus *bus, unsigned int devfn, int pos, int size, u32 data)
 {
 	struct lba_device *d = LBA_DEV(parisc_walk_tree(bus->bridge));
 	u32 local_bus = (bus->parent == NULL) ? 0 : bus->secondary;
 	u32 tok = LBA_CFG_TOK(local_bus,devfn);
 
- 	ASSERT((tok & 0xff) == 0);
-	ASSERT(pos < 0x100);
+	if ((pos > 255) || (devfn > 255))
+		return -EINVAL;
 
-	if (!LBA_TR4PLUS(d) && !LBA_SKIP_PROBE(d)) {
+	if (!LBA_SKIP_PROBE(d)) {
 		/* Original Workaround */
 		lba_wr_cfg(d, tok, pos, (u32) data, size);
 		DBG_CFG("%s(%x+%2x) = 0x%x (a)\n", __FUNCTION__, tok, pos,data);
@@ -745,7 +556,7 @@
 	DBG_CFG("%s(%x+%2x) = 0x%x (c)\n", __FUNCTION__, tok, pos, data);
 
 	/* Basic Algorithm */
-	LBA_CFG_TR4_ADDR_SETUP(d, tok | pos);
+	LBA_CFG_ADDR_SETUP(d, tok | pos);
 	switch(size) {
 	case 1: WRITE_REG8 (data, d->hba.base_addr + LBA_PCI_CFG_DATA + (pos & 3));
 		   break;
@@ -760,9 +571,82 @@
 }
 
 
-static struct pci_ops lba_cfg_ops = {
-	.read =		lba_cfg_read,
-	.write =	lba_cfg_write,
+static struct pci_ops elroy_cfg_ops = {
+	.read =		elroy_cfg_read,
+	.write =	elroy_cfg_write,
+};
+
+/*
+ * The mercury_cfg_ops are slightly misnamed; they're also used for Elroy
+ * TR4.0 as no additional bugs were found in this areea between Elroy and
+ * Mercury
+ */
+
+static int mercury_cfg_read(struct pci_bus *bus, unsigned int devfn, int pos, int size, u32 *data)
+{
+	struct lba_device *d = LBA_DEV(parisc_walk_tree(bus->bridge));
+	u32 local_bus = (bus->parent == NULL) ? 0 : bus->secondary;
+	u32 tok = LBA_CFG_TOK(local_bus, devfn);
+	void __iomem *data_reg = d->hba.base_addr + LBA_PCI_CFG_DATA;
+
+	if ((pos > 255) || (devfn > 255))
+		return -EINVAL;
+
+	LBA_CFG_TR4_ADDR_SETUP(d, tok | pos);
+	switch(size) {
+	case 1:
+		*data = READ_REG8(data_reg + (pos & 3));
+		break;
+	case 2:
+		*data = READ_REG16(data_reg + (pos & 2));
+		break;
+	case 4:
+		*data = READ_REG32(data_reg);             break;
+		break;
+	}
+
+	DBG_CFG("mercury_cfg_read(%x+%2x) -> 0x%x\n", tok, pos, *data);
+	return 0;
+}
+
+/*
+ * LBA 4.0 config write code implements non-postable semantics
+ * by doing a read of CONFIG ADDR after the write.
+ */
+
+static int mercury_cfg_write(struct pci_bus *bus, unsigned int devfn, int pos, int size, u32 data)
+{
+	struct lba_device *d = LBA_DEV(parisc_walk_tree(bus->bridge));
+	void __iomem *data_reg = d->hba.base_addr + LBA_PCI_CFG_DATA;
+	u32 local_bus = (bus->parent == NULL) ? 0 : bus->secondary;
+	u32 tok = LBA_CFG_TOK(local_bus,devfn);
+
+	if ((pos > 255) || (devfn > 255))
+		return -EINVAL;
+
+	DBG_CFG("%s(%x+%2x) <- 0x%x (c)\n", __FUNCTION__, tok, pos, data);
+
+	LBA_CFG_TR4_ADDR_SETUP(d, tok | pos);
+	switch(size) {
+	case 1:
+		WRITE_REG8 (data, data_reg + (pos & 3));
+		break;
+	case 2:
+		WRITE_REG16(data, data_reg + (pos & 2));
+		break;
+	case 4:
+		WRITE_REG32(data, data_reg);
+		break;
+	}
+
+	/* flush posted write */
+	lba_t32 = READ_U32(d->hba.base_addr + LBA_PCI_CFG_ADDR);
+	return 0;
+}
+
+static struct pci_ops mercury_cfg_ops = {
+	.read =		mercury_cfg_read,
+	.write =	mercury_cfg_write,
 };
 
 
@@ -773,7 +657,7 @@
 }
 
 
-#ifdef CONFIG_PARISC64
+#ifdef CONFIG_64BIT
 
 /*
 ** Determine if a device is already configured.
@@ -802,11 +686,11 @@
 	for (i = 0; i <= PCI_ROM_RESOURCE; i++) {
 		if (dev->resource[i].flags & srch_flags) {
 			pci_claim_resource(dev, i);
-			DBG("   claimed %s %d [%lx,%lx]/%x\n",
+			DBG("   claimed %s %d [%lx,%lx]/%lx\n",
 				pci_name(dev), i,
 				dev->resource[i].start,
 				dev->resource[i].end,
-				(int) dev->resource[i].flags
+				dev->resource[i].flags
 				);
 		}
 	}
@@ -835,7 +719,7 @@
 	struct lba_device *ldev = LBA_DEV(parisc_walk_tree(bus->bridge));
 	int lba_portbase = HBA_PORT_BASE(ldev->hba.hba_num);
 
-	DBG("lba_fixup_bus(0x%p) bus %d sysdata 0x%p\n",
+	DBG("lba_fixup_bus(0x%p) bus %d platform_data 0x%p\n",
 		bus, bus->secondary, bus->bridge->platform_data);
 
 	/*
@@ -849,14 +733,14 @@
 		/* Host-PCI Bridge */
 		int err, i;
 
-		DBG("lba_fixup_bus() %s [%lx/%lx]/%x\n",
+		DBG("lba_fixup_bus() %s [%lx/%lx]/%lx\n",
 			ldev->hba.io_space.name,
 			ldev->hba.io_space.start, ldev->hba.io_space.end,
-			(int) ldev->hba.io_space.flags);
-		DBG("lba_fixup_bus() %s [%lx/%lx]/%x\n",
+			ldev->hba.io_space.flags);
+		DBG("lba_fixup_bus() %s [%lx/%lx]/%lx\n",
 			ldev->hba.lmmio_space.name,
 			ldev->hba.lmmio_space.start, ldev->hba.lmmio_space.end,
-			(int) ldev->hba.lmmio_space.flags);
+			ldev->hba.lmmio_space.flags);
 
 		err = request_resource(&ioport_resource, &(ldev->hba.io_space));
 		if (err < 0) {
@@ -895,7 +779,7 @@
 			/* lba_dump_res(&iomem_resource, 2); */
 		}
 
-#ifdef CONFIG_PARISC64
+#ifdef CONFIG_64BIT
 		/* GMMIO is  distributed range. Every LBA/Rope gets part it. */
 		if (ldev->hba.gmmio_space.flags) {
 			err = request_resource(&iomem_resource, &(ldev->hba.gmmio_space));
@@ -1035,7 +919,7 @@
 static u##size lba_astro_in##size (struct pci_hba_data *d, u16 addr) \
 { \
 	u##size t; \
-	t = READ_REG##size(LBA_PORT_BASE + addr); \
+	t = READ_REG##size(astro_iop_base + addr); \
 	DBG_PORT(" 0x%x\n", t); \
 	return (t); \
 }
@@ -1075,9 +959,8 @@
 #define LBA_PORT_OUT(size, mask) \
 static void lba_astro_out##size (struct pci_hba_data *d, u16 addr, u##size val) \
 { \
-	ASSERT(d != NULL); \
 	DBG_PORT("%s(0x%p, 0x%x, 0x%x)\n", __FUNCTION__, d, addr, val); \
-	WRITE_REG##size(val, LBA_PORT_BASE + addr); \
+	WRITE_REG##size(val, astro_iop_base + addr); \
 	if (LBA_DEV(d)->hw_rev < 3) \
 		lba_t32 = READ_U32(d->base_addr + LBA_FUNC_ID); \
 }
@@ -1097,7 +980,7 @@
 };
 
 
-#ifdef CONFIG_PARISC64
+#ifdef CONFIG_64BIT
 #define PIOP_TO_GMMIO(lba, addr) \
 	((lba)->iop_base + (((addr)&0xFFFC)<<10) + ((addr)&3))
 
@@ -1215,16 +1098,19 @@
 		case PAT_LMMIO:
 			/* used to fix up pre-initialized MEM BARs */
 			if (!lba_dev->hba.lmmio_space.start) {
-				sprintf(lba_dev->hba.lmmio_name, "PCI%02x LMMIO",
-					(int) lba_dev->hba.bus_num.start);
-				lba_dev->hba.lmmio_space_offset = p->start - io->start;
-				r = &(lba_dev->hba.lmmio_space);
-				r->name  = lba_dev->hba.lmmio_name;
+				sprintf(lba_dev->hba.lmmio_name,
+						"PCI%02lx LMMIO",
+						lba_dev->hba.bus_num.start);
+				lba_dev->hba.lmmio_space_offset = p->start -
+					io->start;
+				r = &lba_dev->hba.lmmio_space;
+				r->name = lba_dev->hba.lmmio_name;
 			} else if (!lba_dev->hba.elmmio_space.start) {
-				sprintf(lba_dev->hba.elmmio_name, "PCI%02x ELMMIO",
-					(int) lba_dev->hba.bus_num.start);
-				r = &(lba_dev->hba.elmmio_space);
-				r->name  = lba_dev->hba.elmmio_name;
+				sprintf(lba_dev->hba.elmmio_name,
+						"PCI%02lx ELMMIO",
+						lba_dev->hba.bus_num.start);
+				r = &lba_dev->hba.elmmio_space;
+				r->name = lba_dev->hba.elmmio_name;
 			} else {
 				printk(KERN_WARNING MODULE_NAME
 					" only supports 2 LMMIO resources!\n");
@@ -1239,9 +1125,9 @@
 
 		case PAT_GMMIO:
 			/* MMIO space > 4GB phys addr; for 64-bit BAR */
-			sprintf(lba_dev->hba.gmmio_name, "PCI%02x GMMIO",
-					(int) lba_dev->hba.bus_num.start);
-			r = &(lba_dev->hba.gmmio_space);
+			sprintf(lba_dev->hba.gmmio_name, "PCI%02lx GMMIO",
+					lba_dev->hba.bus_num.start);
+			r = &lba_dev->hba.gmmio_space;
 			r->name  = lba_dev->hba.gmmio_name;
 			r->start  = p->start;
 			r->end    = p->end;
@@ -1260,11 +1146,11 @@
 			** Postable I/O port space is per PCI host adapter.
 			** base of 64MB PIOP region
 			*/
-			lba_dev->iop_base = p->start;
+			lba_dev->iop_base = ioremap(p->start, 64 * 1024 * 1024);
 
-			sprintf(lba_dev->hba.io_name, "PCI%02x Ports",
-					(int) lba_dev->hba.bus_num.start);
-			r = &(lba_dev->hba.io_space);
+			sprintf(lba_dev->hba.io_name, "PCI%02lx Ports",
+					lba_dev->hba.bus_num.start);
+			r = &lba_dev->hba.io_space;
 			r->name  = lba_dev->hba.io_name;
 			r->start  = HBA_PORT_BASE(lba_dev->hba.hba_num);
 			r->end    = r->start + HBA_PORT_SPACE_SIZE - 1;
@@ -1284,7 +1170,7 @@
 /* keep compiler from complaining about missing declarations */
 #define lba_pat_port_ops lba_astro_port_ops
 #define lba_pat_resources(pa_dev, lba_dev)
-#endif	/* CONFIG_PARISC64 */
+#endif	/* CONFIG_64BIT */
 
 
 extern void sba_distributed_lmmio(struct parisc_device *, struct resource *);
@@ -1306,7 +1192,7 @@
 	** PCI bus walk *should* end up with the same result.
 	** FIXME: But we don't have sanity checks in PCI or LBA.
 	*/
-	lba_num = READ_REG32(pa_dev->hpa + LBA_FW_SCRATCH);
+	lba_num = READ_REG32(lba_dev->hba.base_addr + LBA_FW_SCRATCH);
 	r = &(lba_dev->hba.bus_num);
 	r->name = "LBA PCI Busses";
 	r->start = lba_num & 0xff;
@@ -1316,8 +1202,8 @@
 	** Legacy boxes but it's nice to see in /proc/iomem.
 	*/
 	r = &(lba_dev->hba.lmmio_space);
-	sprintf(lba_dev->hba.lmmio_name, "PCI%02x LMMIO",
-					(int) lba_dev->hba.bus_num.start);
+	sprintf(lba_dev->hba.lmmio_name, "PCI%02lx LMMIO",
+					lba_dev->hba.bus_num.start);
 	r->name  = lba_dev->hba.lmmio_name;
 
 #if 1
@@ -1387,7 +1273,7 @@
 	 *
 	 * All is well now.
 	 */
-	r->start = (long) READ_REG32(pa_dev->hpa + LBA_LMMIO_BASE);
+	r->start = READ_REG32(lba_dev->hba.base_addr + LBA_LMMIO_BASE);
 	if (r->start & 1) {
 		unsigned long rsize;
 
@@ -1395,7 +1281,7 @@
 		/* mmio_mask also clears Enable bit */
 		r->start &= mmio_mask;
 		r->start = PCI_HOST_ADDR(HBA_DATA(lba_dev), r->start);
-		rsize = ~ READ_REG32(pa_dev->hpa + LBA_LMMIO_MASK);
+		rsize = ~ READ_REG32(lba_dev->hba.base_addr + LBA_LMMIO_MASK);
 
 		/*
 		** Each rope only gets part of the distributed range.
@@ -1425,15 +1311,15 @@
 	** an existing (but unused portion of) distributed range.
 	*/
 	r = &(lba_dev->hba.elmmio_space);
-	sprintf(lba_dev->hba.elmmio_name, "PCI%02x ELMMIO",
-					(int) lba_dev->hba.bus_num.start);
+	sprintf(lba_dev->hba.elmmio_name, "PCI%02lx ELMMIO",
+					lba_dev->hba.bus_num.start);
 	r->name  = lba_dev->hba.elmmio_name;
 
 #if 1
 	/* See comment which precedes call to sba_directed_lmmio() */
 	sba_directed_lmmio(pa_dev, r);
 #else
-	r->start = READ_REG32(pa_dev->hpa + LBA_ELMMIO_BASE);
+	r->start = READ_REG32(lba_dev->hba.base_addr + LBA_ELMMIO_BASE);
 
 	if (r->start & 1) {
 		unsigned long rsize;
@@ -1441,18 +1327,18 @@
 		/* mmio_mask also clears Enable bit */
 		r->start &= mmio_mask;
 		r->start = PCI_HOST_ADDR(HBA_DATA(lba_dev), r->start);
-		rsize = READ_REG32(pa_dev->hpa + LBA_ELMMIO_MASK);
+		rsize = READ_REG32(lba_dev->hba.base_addr + LBA_ELMMIO_MASK);
 		r->end = r->start + ~rsize;
 	}
 #endif
 
 	r = &(lba_dev->hba.io_space);
-	sprintf(lba_dev->hba.io_name, "PCI%02x Ports",
-					(int) lba_dev->hba.bus_num.start);
+	sprintf(lba_dev->hba.io_name, "PCI%02lx Ports",
+					lba_dev->hba.bus_num.start);
 	r->name  = lba_dev->hba.io_name;
 	r->flags = IORESOURCE_IO;
-	r->start = READ_REG32(pa_dev->hpa + LBA_IOS_BASE) & ~1L;
-	r->end   = r->start + (READ_REG32(pa_dev->hpa + LBA_IOS_MASK) ^ (HBA_PORT_SPACE_SIZE - 1));
+	r->start = READ_REG32(lba_dev->hba.base_addr + LBA_IOS_BASE) & ~1L;
+	r->end   = r->start + (READ_REG32(lba_dev->hba.base_addr + LBA_IOS_MASK) ^ (HBA_PORT_SPACE_SIZE - 1));
 
 	/* Virtualize the I/O Port space ranges */
 	lba_num = HBA_PORT_BASE(lba_dev->hba.hba_num);
@@ -1501,7 +1387,7 @@
 	printk("\n");
 #endif	/* DEBUG_LBA_PAT */
 
-#ifdef CONFIG_PARISC64
+#ifdef CONFIG_64BIT
 /*
  * FIXME add support for PDC_PAT_IO "Get slot status" - OLAR support
  * Only N-Class and up can really make use of Get slot status.
@@ -1558,23 +1444,6 @@
 
 
 
-static void __init
-lba_common_init(struct lba_device *lba_dev)
-{
-	pci_bios = &lba_bios_ops;
-	pcibios_register_hba(HBA_DATA(lba_dev));
-	spin_lock_init(&lba_dev->lba_lock);
-
-	/*
-	** Set flags which depend on hw_rev
-	*/
-	if (!LBA_TR4PLUS(lba_dev)) {
-		lba_dev->flags |= LBA_FLAG_NO_DMA_DURING_CFG;
-	}
-}
-
-
-
 /*
 ** Determine if lba should claim this chip (return 0) or not (return 1).
 ** If so, initialize the chip and tell other partners in crime they
@@ -1585,12 +1454,14 @@
 {
 	struct lba_device *lba_dev;
 	struct pci_bus *lba_bus;
+	struct pci_ops *cfg_ops;
 	u32 func_class;
 	void *tmp_obj;
 	char *version;
+	void __iomem *addr = ioremap(dev->hpa, 4096);
 
 	/* Read HW Rev First */
-	func_class = READ_REG32(dev->hpa + LBA_FCLASS);
+	func_class = READ_REG32(addr + LBA_FCLASS);
 
 	if (IS_ELROY(dev)) {	
 		func_class &= 0xf;
@@ -1603,24 +1474,40 @@
 		case 5:	version = "TR4.0"; break;
 		default: version = "TR4+";
 		}
+
 		printk(KERN_INFO "%s version %s (0x%x) found at 0x%lx\n",
 			MODULE_NAME, version, func_class & 0xf, dev->hpa);
 
-		/* Just in case we find some prototypes... */
+		if (func_class < 2) {
+			printk(KERN_WARNING "Can't support LBA older than "
+				"TR2.1 - continuing under adversity.\n");
+		}
+
+#if 0
+/* Elroy TR4.0 should work with simple algorithm.
+   But it doesn't.  Still missing something. *sigh*
+*/
+		if (func_class > 4) {
+			cfg_ops = &mercury_cfg_ops;
+		} else
+#endif
+		{
+			cfg_ops = &elroy_cfg_ops;
+		}
+
 	} else if (IS_MERCURY(dev) || IS_QUICKSILVER(dev)) {
 		func_class &= 0xff;
 		version = kmalloc(6, GFP_KERNEL);
 		sprintf(version,"TR%d.%d",(func_class >> 4),(func_class & 0xf));
-		/* We could use one printk for both and have it outside,
+		/* We could use one printk for both Elroy and Mercury,
                  * but for the mask for func_class.
                  */ 
 		printk(KERN_INFO "%s version %s (0x%x) found at 0x%lx\n",
 			MODULE_NAME, version, func_class & 0xff, dev->hpa);
-	}
-
-	if (func_class < 2) {
-		printk(KERN_WARNING "Can't support LBA older than TR2.1"
-				" - continuing under adversity.\n");
+		cfg_ops = &mercury_cfg_ops;
+	} else {
+		printk(KERN_ERR "Unknown LBA found at 0x%lx\n", dev->hpa);
+		return -ENODEV;
 	}
 
 	/*
@@ -1633,8 +1520,7 @@
 	*/
 	
 	lba_dev = kmalloc(sizeof(struct lba_device), GFP_KERNEL);
-	if (NULL == lba_dev)
-	{
+	if (!lba_dev) {
 		printk(KERN_ERR "lba_init_chip - couldn't alloc lba_device\n");
 		return(1);
 	}
@@ -1644,19 +1530,16 @@
 
 	/* ---------- First : initialize data we already have --------- */
 
-	/*
-	** Need hw_rev to adjust configuration space behavior.
-	** LBA_TR4PLUS macro uses hw_rev field.
-	*/
 	lba_dev->hw_rev = func_class;
-
-	lba_dev->hba.base_addr = dev->hpa;  /* faster access */
+	lba_dev->hba.base_addr = addr;
 	lba_dev->hba.dev = dev;
 	lba_dev->iosapic_obj = tmp_obj;  /* save interrupt handle */
 	lba_dev->hba.iommu = sba_get_iommu(dev);  /* get iommu data */
 
 	/* ------------ Second : initialize common stuff ---------- */
-	lba_common_init(lba_dev);
+	pci_bios = &lba_bios_ops;
+	pcibios_register_hba(HBA_DATA(lba_dev));
+	spin_lock_init(&lba_dev->lba_lock);
 
 	if (lba_hw_init(lba_dev))
 		return(1);
@@ -1669,8 +1552,11 @@
 		/* Go ask PDC PAT what resources this LBA has */
 		lba_pat_resources(dev, lba_dev);
 	} else {
-		/* Sprockets PDC uses NPIOP region */
-		pci_port = &lba_astro_port_ops;
+		if (!astro_iop_base) {
+			/* Sprockets PDC uses NPIOP region */
+			astro_iop_base = ioremap(LBA_PORT_BASE, 64 * 1024);
+			pci_port = &lba_astro_port_ops;
+		}
 
 		/* Poke the chip a bit for /proc output */
 		lba_legacy_resources(dev, lba_dev);
@@ -1683,8 +1569,7 @@
 	dev->dev.platform_data = lba_dev;
 	lba_bus = lba_dev->hba.hba_bus =
 		pci_scan_bus_parented(&dev->dev, lba_dev->hba.bus_num.start,
-				IS_ELROY(dev) ? &lba_cfg_ops : &mercury_cfg_ops,
-				NULL);
+				cfg_ops, NULL);
 
 	/* This is in lieu of calling pci_assign_unassigned_resources() */
 	if (is_pdc_pat()) {
@@ -1711,7 +1596,7 @@
 	** space is restricted. Avoids master aborts on config cycles.
 	** Early LBA revs go fatal on *any* master abort.
 	*/
-	if (!LBA_TR4PLUS(lba_dev)) {
+	if (cfg_ops == &elroy_cfg_ops) {
 		lba_dev->flags |= LBA_FLAG_SKIP_PROBE;
 	}
 
@@ -1746,18 +1631,19 @@
 ** Only called from sba_iommu.c in order to route ranges (MMIO vs DMA).
 ** sba_iommu is responsible for locking (none needed at init time).
 */
-void
-lba_set_iregs(struct parisc_device *lba, u32 ibase, u32 imask)
+void lba_set_iregs(struct parisc_device *lba, u32 ibase, u32 imask)
 {
-	unsigned long base_addr = lba->hpa;
+	void __iomem * base_addr = ioremap(lba->hpa, 4096);
 
 	imask <<= 2;	/* adjust for hints - 2 more bits */
 
-	ASSERT((ibase & 0x003fffff) == 0);
-	ASSERT((imask & 0x003fffff) == 0);
+	/* Make sure we aren't trying to set bits that aren't writeable. */
+	WARN_ON((ibase & 0x001fffff) != 0);
+	WARN_ON((imask & 0x001fffff) != 0);
 	
 	DBG("%s() ibase 0x%x imask 0x%x\n", __FUNCTION__, ibase, imask);
 	WRITE_REG32( imask, base_addr + LBA_IMASK);
 	WRITE_REG32( ibase, base_addr + LBA_IBASE);
+	iounmap(base_addr);
 }
 
diff -Nru a/drivers/parisc/pdc_stable.c b/drivers/parisc/pdc_stable.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/parisc/pdc_stable.c	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,735 @@
+/* 
+ *    Interfaces to retrieve and set PDC Stable options (firmware)
+ *
+ *    Copyright (C) 2005 Thibaut VARENE <varenet@parisc-linux.org>
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ *
+ *    DEV NOTE: the PDC Procedures reference states that:
+ *    "A minimum of 96 bytes of Stable Storage is required. Providing more than
+ *    96 bytes of Stable Storage is optional [...]. Failure to provide the
+ *    optional locations from 96 to 192 results in the loss of certain
+ *    functionality during boot."
+ *
+ *    Since locations between 96 and 192 are the various paths, most (if not
+ *    all) PA-RISC machines should have them. Anyway, for safety reasons, the
+ *    following code can deal with only 96 bytes of Stable Storage, and all
+ *    sizes between 96 and 192 bytes (provided they are multiple of struct
+ *    device_path size, eg: 128, 160 and 192) to provide full information.
+ *    The code makes no use of data above 192 bytes. One last word: there's one
+ *    path we can always count on: the primary path.
+ */
+
+#undef PDCS_DEBUG
+#ifdef PDCS_DEBUG
+#define DPRINTK(fmt, args...)	printk(KERN_DEBUG fmt, ## args)
+#else
+#define DPRINTK(fmt, args...)
+#endif
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/sched.h>		/* for capable() */
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/ctype.h>
+#include <linux/sysfs.h>
+#include <linux/kobject.h>
+#include <linux/device.h>
+#include <linux/errno.h>
+
+#include <asm/pdc.h>
+#include <asm/page.h>
+#include <asm/uaccess.h>
+#include <asm/hardware.h>
+
+#define PDCS_VERSION	"0.09"
+
+#define PDCS_ADDR_PPRI	0x00
+#define PDCS_ADDR_OSID	0x40
+#define PDCS_ADDR_FSIZ	0x5C
+#define PDCS_ADDR_PCON	0x60
+#define PDCS_ADDR_PALT	0x80
+#define PDCS_ADDR_PKBD	0xA0
+
+MODULE_AUTHOR("Thibaut VARENE <varenet@parisc-linux.org>");
+MODULE_DESCRIPTION("sysfs interface to HP PDC Stable Storage data");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(PDCS_VERSION);
+
+static unsigned long pdcs_size = 0;
+
+/* This struct defines what we need to deal with a parisc pdc path entry */
+struct pdcspath_entry {
+	short ready;			/* entry record is valid if != 0 */
+	unsigned long addr;		/* entry address in stable storage */
+	char *name;			/* entry name */
+	struct device_path devpath;	/* device path in parisc representation */
+	struct device *dev;		/* corresponding device */
+	struct kobject kobj;
+};
+
+struct pdcspath_attribute {
+	struct attribute attr;
+	ssize_t (*show)(struct pdcspath_entry *entry, char *buf);
+	ssize_t (*store)(struct pdcspath_entry *entry, const char *buf, size_t count);
+};
+
+#define PDCSPATH_ENTRY(_addr, _name) \
+struct pdcspath_entry pdcspath_entry_##_name = { \
+	.ready = 0, \
+	.addr = _addr, \
+	.name = __stringify(_name), \
+};
+
+#define PDCS_ATTR(_name, _mode, _show, _store) \
+struct subsys_attribute pdcs_attr_##_name = { \
+	.attr = {.name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE}, \
+	.show = _show, \
+	.store = _store, \
+};
+
+#define PATHS_ATTR(_name, _mode, _show, _store) \
+struct pdcspath_attribute paths_attr_##_name = { \
+	.attr = {.name = __stringify(_name), .mode = _mode, .owner = THIS_MODULE}, \
+	.show = _show, \
+	.store = _store, \
+};
+
+#define to_pdcspath_attribute(_attr) container_of(_attr, struct pdcspath_attribute, attr)
+#define to_pdcspath_entry(obj)  container_of(obj, struct pdcspath_entry, kobj)
+
+/**
+ * pdcspath_fetch - This function populates the path entry structs.
+ * @entry: A pointer to an allocated pdcspath_entry.
+ * 
+ * The general idea is that you don't read from the Stable Storage every time
+ * you access the files provided by the facilites. We store a copy of the
+ * content of the stable storage WRT various paths in these structs. We read
+ * these structs when reading the files, and we will write to these structs when
+ * writing to the files, and only then write them back to the Stable Storage.
+ */
+static int
+pdcspath_fetch(struct pdcspath_entry *entry)
+{
+	struct device_path *devpath;
+
+	if (!entry)
+		return -EINVAL;
+
+	devpath = &entry->devpath;
+	
+	DPRINTK("%s: fetch: 0x%p, 0x%p, addr: 0x%lx\n", __func__,
+			entry, devpath, entry->addr);
+
+	/* addr, devpath and count must be word aligned */
+	if (pdc_stable_read(entry->addr, devpath, sizeof(*devpath)) != PDC_OK)
+		return -EIO;
+		
+	/* Find the matching device.
+	   NOTE: hardware_path overlays with device_path, so the nice cast can
+	   be used */
+	entry->dev = hwpath_to_device((struct hardware_path *)devpath);
+
+	entry->ready = 1;
+	
+	DPRINTK("%s: device: 0x%p\n", __func__, entry->dev);
+	
+	return 0;
+}
+
+/**
+ * pdcspath_store - This function writes a path to stable storage.
+ * @entry: A pointer to an allocated pdcspath_entry.
+ * 
+ * It can be used in two ways: either by passing it a preset devpath struct
+ * containing an already computed hardware path, or by passing it a device
+ * pointer, from which it'll find out the corresponding hardware path.
+ * For now we do not handle the case where there's an error in writing to the
+ * Stable Storage area, so you'd better not mess up the data :P
+ */
+static int
+pdcspath_store(struct pdcspath_entry *entry)
+{
+	struct device_path *devpath;
+
+	if (!entry)
+		return -EINVAL;
+
+	devpath = &entry->devpath;
+	
+	/* We expect the caller to set the ready flag to 0 if the hardware
+	   path struct provided is invalid, so that we know we have to fill it.
+	   First case, we don't have a preset hwpath... */
+	if (!entry->ready) {
+		/* ...but we have a device, map it */
+		if (entry->dev)
+			device_to_hwpath(entry->dev, (struct hardware_path *)devpath);
+		else
+			return -EINVAL;
+	}
+	/* else, we expect the provided hwpath to be valid. */
+	
+	DPRINTK("%s: store: 0x%p, 0x%p, addr: 0x%lx\n", __func__,
+			entry, devpath, entry->addr);
+
+	/* addr, devpath and count must be word aligned */
+	if (pdc_stable_write(entry->addr, devpath, sizeof(*devpath)) != PDC_OK) {
+		printk(KERN_ERR "%s: an error occured when writing to PDC.\n"
+				"It is likely that the Stable Storage data has been corrupted.\n"
+				"Please check it carefully upon next reboot.\n", __func__);
+		return -EIO;
+	}
+		
+	entry->ready = 1;
+	
+	DPRINTK("%s: device: 0x%p\n", __func__, entry->dev);
+	
+	return 0;
+}
+
+/**
+ * pdcspath_hwpath_read - This function handles hardware path pretty printing.
+ * @entry: An allocated and populated pdscpath_entry struct.
+ * @buf: The output buffer to write to.
+ * 
+ * We will call this function to format the output of the hwpath attribute file.
+ */
+static ssize_t
+pdcspath_hwpath_read(struct pdcspath_entry *entry, char *buf)
+{
+	char *out = buf;
+	struct device_path *devpath;
+	unsigned short i;
+
+	if (!entry || !buf)
+		return -EINVAL;
+
+	devpath = &entry->devpath;
+
+	if (!entry->ready)
+		return -ENODATA;
+	
+	for (i = 0; i < 6; i++) {
+		if (devpath->bc[i] >= 128)
+			continue;
+		out += sprintf(out, "%u/", (unsigned char)devpath->bc[i]);
+	}
+	out += sprintf(out, "%u\n", (unsigned char)devpath->mod);
+	
+	return out - buf;
+}
+
+/**
+ * pdcspath_hwpath_write - This function handles hardware path modifying.
+ * @entry: An allocated and populated pdscpath_entry struct.
+ * @buf: The input buffer to read from.
+ * @count: The number of bytes to be read.
+ * 
+ * We will call this function to change the current hardware path.
+ * Hardware paths are to be given '/'-delimited, without brackets.
+ * We take care to make sure that the provided path actually maps to an existing
+ * device, BUT nothing would prevent some foolish user to set the path to some
+ * PCI bridge or even a CPU...
+ * A better work around would be to make sure we are at the end of a device tree
+ * for instance, but it would be IMHO beyond the simple scope of that driver.
+ * The aim is to provide a facility. Data correctness is left to userland.
+ */
+static ssize_t
+pdcspath_hwpath_write(struct pdcspath_entry *entry, const char *buf, size_t count)
+{
+	struct hardware_path hwpath;
+	unsigned short i;
+	char in[count+1], *temp;
+	struct device *dev;
+
+	if (!entry || !buf || !count)
+		return -EINVAL;
+
+	/* We'll use a local copy of buf */
+	memset(in, 0, count+1);
+	strncpy(in, buf, count);
+	
+	/* Let's clean up the target. 0xff is a blank pattern */
+	memset(&hwpath, 0xff, sizeof(hwpath));
+	
+	/* First, pick the mod field (the last one of the input string) */
+	if (!(temp = strrchr(in, '/')))
+		return -EINVAL;
+			
+	hwpath.mod = simple_strtoul(temp+1, NULL, 10);
+	in[temp-in] = '\0';	/* truncate the remaining string. just precaution */
+	DPRINTK("%s: mod: %d\n", __func__, hwpath.mod);
+	
+	/* Then, loop for each delimiter, making sure we don't have too many.
+	   we write the bc fields in a down-top way. No matter what, we stop
+	   before writing the last field. If there are too many fields anyway,
+	   then the user is a moron and it'll be caught up later when we'll
+	   check the consistency of the given hwpath. */
+	for (i=5; ((temp = strrchr(in, '/'))) && (temp-in > 0) && (likely(i)); i--) {
+		hwpath.bc[i] = simple_strtoul(temp+1, NULL, 10);
+		in[temp-in] = '\0';
+		DPRINTK("%s: bc[%d]: %d\n", __func__, i, hwpath.bc[i]);
+	}
+	
+	/* Store the final field */		
+	hwpath.bc[i] = simple_strtoul(in, NULL, 10);
+	DPRINTK("%s: bc[%d]: %d\n", __func__, i, hwpath.bc[i]);
+	
+	/* Now we check that the user isn't trying to lure us */
+	if (!(dev = hwpath_to_device((struct hardware_path *)&hwpath))) {
+		printk(KERN_WARNING "%s: attempt to set invalid \"%s\" "
+			"hardware path: %s\n", __func__, entry->name, buf);
+		return -EINVAL;
+	}
+	
+	/* So far so good, let's get in deep */
+	entry->ready = 0;
+	entry->dev = dev;
+	
+	/* Now, dive in. Write back to the hardware */
+	WARN_ON(pdcspath_store(entry));	/* this warn should *NEVER* happen */
+	
+	/* Update the symlink to the real device */
+	sysfs_remove_link(&entry->kobj, "device");
+	sysfs_create_link(&entry->kobj, &entry->dev->kobj, "device");
+	
+	printk(KERN_INFO "PDC Stable Storage: changed \"%s\" path to \"%s\"\n",
+		entry->name, buf);
+	
+	return count;
+}
+
+/**
+ * pdcspath_layer_read - Extended layer (eg. SCSI ids) pretty printing.
+ * @entry: An allocated and populated pdscpath_entry struct.
+ * @buf: The output buffer to write to.
+ * 
+ * We will call this function to format the output of the layer attribute file.
+ */
+static ssize_t
+pdcspath_layer_read(struct pdcspath_entry *entry, char *buf)
+{
+	char *out = buf;
+	struct device_path *devpath;
+	unsigned short i;
+
+	if (!entry || !buf)
+		return -EINVAL;
+	
+	devpath = &entry->devpath;
+
+	if (!entry->ready)
+		return -ENODATA;
+	
+	for (i = 0; devpath->layers[i] && (likely(i < 6)); i++)
+		out += sprintf(out, "%u ", devpath->layers[i]);
+
+	out += sprintf(out, "\n");
+	
+	return out - buf;
+}
+
+/**
+ * pdcspath_layer_write - This function handles extended layer modifying.
+ * @entry: An allocated and populated pdscpath_entry struct.
+ * @buf: The input buffer to read from.
+ * @count: The number of bytes to be read.
+ * 
+ * We will call this function to change the current layer value.
+ * Layers are to be given '.'-delimited, without brackets.
+ * XXX beware we are far less checky WRT input data provided than for hwpath.
+ * Potential harm can be done, since there's no way to check the validity of
+ * the layer fields.
+ */
+static ssize_t
+pdcspath_layer_write(struct pdcspath_entry *entry, const char *buf, size_t count)
+{
+	unsigned int layers[6]; /* device-specific info (ctlr#, unit#, ...) */
+	unsigned short i;
+	char in[count+1], *temp;
+
+	if (!entry || !buf || !count)
+		return -EINVAL;
+
+	/* We'll use a local copy of buf */
+	memset(in, 0, count+1);
+	strncpy(in, buf, count);
+	
+	/* Let's clean up the target. 0 is a blank pattern */
+	memset(&layers, 0, sizeof(layers));
+	
+	/* First, pick the first layer */
+	if (unlikely(!isdigit(*in)))
+		return -EINVAL;
+	layers[0] = simple_strtoul(in, NULL, 10);
+	DPRINTK("%s: layer[0]: %d\n", __func__, layers[0]);
+	
+	temp = in;
+	for (i=1; ((temp = strchr(temp, '.'))) && (likely(i<6)); i++) {
+		if (unlikely(!isdigit(*(++temp))))
+			return -EINVAL;
+		layers[i] = simple_strtoul(temp, NULL, 10);
+		DPRINTK("%s: layer[%d]: %d\n", __func__, i, layers[i]);
+	}
+		
+	/* So far so good, let's get in deep */
+	
+	/* First, overwrite the current layers with the new ones, not touching
+	   the hardware path. */
+	memcpy(&entry->devpath.layers, &layers, sizeof(layers));
+	
+	/* Now, dive in. Write back to the hardware */
+	WARN_ON(pdcspath_store(entry));	/* this warn should *NEVER* happen */
+	
+	printk(KERN_INFO "PDC Stable Storage: changed \"%s\" layers to \"%s\"\n",
+		entry->name, buf);
+	
+	return count;
+}
+
+/**
+ * pdcspath_attr_show - Generic read function call wrapper.
+ * @kobj: The kobject to get info from.
+ * @attr: The attribute looked upon.
+ * @buf: The output buffer.
+ */
+static ssize_t
+pdcspath_attr_show(struct kobject *kobj, struct attribute *attr, char *buf)
+{
+	struct pdcspath_entry *entry = to_pdcspath_entry(kobj);
+	struct pdcspath_attribute *pdcs_attr = to_pdcspath_attribute(attr);
+	ssize_t ret = 0;
+
+	if (!capable(CAP_SYS_ADMIN))
+		return -EACCES;
+
+	if (pdcs_attr->show)
+		ret = pdcs_attr->show(entry, buf);
+
+	return ret;
+}
+
+/**
+ * pdcspath_attr_store - Generic write function call wrapper.
+ * @kobj: The kobject to write info to.
+ * @attr: The attribute to be modified.
+ * @buf: The input buffer.
+ * @count: The size of the buffer.
+ */
+static ssize_t
+pdcspath_attr_store(struct kobject *kobj, struct attribute *attr,
+			const char *buf, size_t count)
+{
+	struct pdcspath_entry *entry = to_pdcspath_entry(kobj);
+	struct pdcspath_attribute *pdcs_attr = to_pdcspath_attribute(attr);
+	ssize_t ret = 0;
+
+	if (!capable(CAP_SYS_ADMIN))
+		return -EACCES;
+
+	if (pdcs_attr->store)
+		ret = pdcs_attr->store(entry, buf, count);
+
+	return ret;
+}
+
+static struct sysfs_ops pdcspath_attr_ops = {
+	.show = pdcspath_attr_show,
+	.store = pdcspath_attr_store,
+};
+
+/* These are the two attributes of any PDC path. */
+static PATHS_ATTR(hwpath, 0600, pdcspath_hwpath_read, pdcspath_hwpath_write);
+static PATHS_ATTR(layer, 0600, pdcspath_layer_read, pdcspath_layer_write);
+
+static struct attribute *paths_subsys_attrs[] = {
+	&paths_attr_hwpath.attr,
+	&paths_attr_layer.attr,
+	NULL,
+};
+
+/* Specific kobject type for our PDC paths */
+static struct kobj_type ktype_pdcspath = {
+	.sysfs_ops = &pdcspath_attr_ops,
+	.default_attrs = paths_subsys_attrs,
+};
+
+/* We hard define the 4 types of path we expect to find */
+static PDCSPATH_ENTRY(PDCS_ADDR_PPRI, primary);
+static PDCSPATH_ENTRY(PDCS_ADDR_PCON, console);
+static PDCSPATH_ENTRY(PDCS_ADDR_PALT, alternative);
+static PDCSPATH_ENTRY(PDCS_ADDR_PKBD, keyboard);
+
+/* An array containing all PDC paths we will deal with */
+static struct pdcspath_entry *pdcspath_entries[] = {
+	&pdcspath_entry_primary,
+	&pdcspath_entry_alternative,
+	&pdcspath_entry_console,
+	&pdcspath_entry_keyboard,
+	NULL,
+};
+
+/**
+ * pdcs_info_read - Pretty printing of the remaining useful data.
+ * @entry: An allocated and populated subsytem struct. We don't use it tho.
+ * @buf: The output buffer to write to.
+ * 
+ * We will call this function to format the output of the 'info' attribute file.
+ * Please refer to PDC Procedures documentation, section PDC_STABLE to get a
+ * better insight of what we're doing here.
+ */
+static ssize_t
+pdcs_info_read(struct subsystem *entry, char *buf)
+{
+	char *out = buf;
+	__u32 result;
+	struct device_path devpath;
+	char *tmpstr = NULL;
+	
+	if (!entry || !buf)
+		return -EINVAL;
+		
+	/* show the size of the stable storage */
+	out += sprintf(out, "Stable Storage size: %ld bytes\n", pdcs_size);
+
+	/* deal with flags */
+	if (pdc_stable_read(PDCS_ADDR_PPRI, &devpath, sizeof(devpath)) != PDC_OK)
+		return -EIO;
+	
+	out += sprintf(out, "Autoboot: %s\n", (devpath.flags & PF_AUTOBOOT) ? "On" : "Off");
+	out += sprintf(out, "Autosearch: %s\n", (devpath.flags & PF_AUTOSEARCH) ? "On" : "Off");
+	out += sprintf(out, "Timer: %u s\n", (devpath.flags & PF_TIMER) ? (1 << (devpath.flags & PF_TIMER)) : 0);
+
+	/* get OSID */
+	if (pdc_stable_read(PDCS_ADDR_OSID, &result, sizeof(result)) != PDC_OK)
+		return -EIO;
+
+	/* the actual result is 16 bits away */
+	switch (result >> 16) {
+		case 0x0000:	tmpstr = "No OS-dependent data"; break;
+		case 0x0001:	tmpstr = "HP-UX dependent data"; break;
+		case 0x0002:	tmpstr = "MPE-iX dependent data"; break;
+		case 0x0003:	tmpstr = "OSF dependent data"; break;
+		case 0x0004:	tmpstr = "HP-RT dependent data"; break;
+		case 0x0005:	tmpstr = "Novell Netware dependent data"; break;
+		default:	tmpstr = "Unknown"; break;
+	}
+	out += sprintf(out, "OS ID: %s (0x%.4x)\n", tmpstr, (result >> 16));
+
+	/* get fast-size */
+	if (pdc_stable_read(PDCS_ADDR_FSIZ, &result, sizeof(result)) != PDC_OK)
+		return -EIO;
+
+	out += sprintf(out, "Memory tested: ");
+	if ((result & 0x0F) < 0x0E)
+		out += sprintf(out, "%.3f MB", 0.256*(1<<(result & 0x0F)));
+	else
+		out += sprintf(out, "All");
+	out += sprintf(out, "\n");
+	
+	return out - buf;
+}
+
+/**
+ * pdcs_info_write - This function handles boot flag modifying.
+ * @entry: An allocated and populated subsytem struct. We don't use it tho.
+ * @buf: The input buffer to read from.
+ * @count: The number of bytes to be read.
+ * 
+ * We will call this function to change the current boot flags.
+ * We expect a precise syntax:
+ *	\"n n\" (n == 0 or 1) to toggle respectively AutoBoot and AutoSearch
+ *
+ * As of now there is no incentive on my side to provide more "knobs" to that
+ * interface, since modifying the rest of the data is pretty meaningless when
+ * the machine is running and for the expected use of that facility, such as
+ * PALO setting up the boot disk when installing a Linux distribution...
+ */
+static ssize_t
+pdcs_info_write(struct subsystem *entry, const char *buf, size_t count)
+{
+	struct pdcspath_entry *pathentry;
+	unsigned char flags;
+	char in[count+1], *temp;
+	char c;
+
+	if (!capable(CAP_SYS_ADMIN))
+		return -EACCES;
+
+	if (!entry || !buf || !count)
+		return -EINVAL;
+
+	/* We'll use a local copy of buf */
+	memset(in, 0, count+1);
+	strncpy(in, buf, count);
+
+	/* Current flags are stored in primary boot path entry */
+	pathentry = &pdcspath_entry_primary;
+	
+	/* Be nice to the existing flag record */
+	flags = pathentry->devpath.flags;
+	
+	DPRINTK("%s: flags before: 0x%X\n", __func__, flags);
+			
+	temp = in;
+	
+	while (*temp && isspace(*temp))
+		temp++;
+	
+	c = *temp++ - '0';
+	if ((c != 0) && (c != 1))
+		goto parse_error;
+	if (c == 0)
+		flags &= ~PF_AUTOBOOT;
+	else
+		flags |= PF_AUTOBOOT;
+	
+	if (*temp++ != ' ')
+		goto parse_error;
+	
+	c = *temp++ - '0';
+	if ((c != 0) && (c != 1))
+		goto parse_error;
+	if (c == 0)
+		flags &= ~PF_AUTOSEARCH;
+	else
+		flags |= PF_AUTOSEARCH;
+	
+	DPRINTK("%s: flags after: 0x%X\n", __func__, flags);
+		
+	/* So far so good, let's get in deep */
+	
+	/* Change the path entry flags first */
+	pathentry->devpath.flags = flags;
+		
+	/* Now, dive in. Write back to the hardware */
+	WARN_ON(pdcspath_store(pathentry));	/* this warn should *NEVER* happen */
+	
+	printk(KERN_INFO "PDC Stable Storage: changed flags to \"%s\"\n", buf);
+	
+	return count;
+
+parse_error:
+	printk(KERN_WARNING "%s: Parse error: expect \"n n\" (n == 0 or 1) for AB and AS\n", __func__);
+	return -EINVAL;
+}
+
+/* The last attribute (the 'root' one actually) with all remaining data. */
+static PDCS_ATTR(info, 0600, pdcs_info_read, pdcs_info_write);
+
+static struct subsys_attribute *pdcs_subsys_attrs[] = {
+	&pdcs_attr_info,
+	NULL,	/* maybe more in the future? */
+};
+
+static decl_subsys(paths, &ktype_pdcspath, NULL);
+static decl_subsys(pdc, NULL, NULL);
+
+/**
+ * pdcs_register_pathentries - Prepares path entries kobjects for sysfs usage.
+ * 
+ * It creates kobjects corresponding to each path entry with nice sysfs
+ * links to the real device. This is where the magic takes place: when
+ * registering the subsystem attributes during module init, each kobject hereby
+ * created will show in the sysfs tree as a folder containing files as defined
+ * by path_subsys_attr[].
+ */
+static inline int __init
+pdcs_register_pathentries(void)
+{
+	unsigned short i;
+	struct pdcspath_entry *entry;
+	
+	for (i = 0; (entry = pdcspath_entries[i]); i++) {
+		if (pdcspath_fetch(entry) < 0)
+			continue;
+
+		kobject_set_name(&entry->kobj, "%s", entry->name);
+		kobj_set_kset_s(entry, paths_subsys);
+		kobject_register(&entry->kobj);
+
+		if (!entry->dev)
+			continue;
+
+		/* Add a nice symlink to the real device */
+		sysfs_create_link(&entry->kobj, &entry->dev->kobj, "device");
+	}
+	
+	return 0;
+}
+
+/**
+ * pdcs_unregister_pathentries - Routine called when unregistering the module.
+ */
+static inline void __exit
+pdcs_unregister_pathentries(void)
+{
+	unsigned short i;
+	struct pdcspath_entry *entry;
+	
+	for (i = 0; (entry = pdcspath_entries[i]); i++)
+		if (entry->ready)
+			kobject_unregister(&entry->kobj);	
+}
+
+/*
+ * For now we register the pdc subsystem with the firmware subsystem
+ * and the paths subsystem with the pdc subsystem
+ */
+static int __init
+pdc_stable_init(void)
+{
+	struct subsys_attribute *attr;
+	int i, rc = 0, error = 0;
+
+	/* find the size of the stable storage */
+	if (pdc_stable_get_size(&pdcs_size) != PDC_OK) 
+		return -ENODEV;
+
+	printk(KERN_INFO "PDC Stable Storage facility v%s\n", PDCS_VERSION);
+
+	/* For now we'll register the pdc subsys within this driver */
+	if ((rc = firmware_register(&pdc_subsys)))
+		return rc;
+
+	/* Don't forget the info entry */
+	for (i = 0; (attr = pdcs_subsys_attrs[i]) && !error; i++)
+		if (attr->show)
+			error = subsys_create_file(&pdc_subsys, attr);
+	
+	/* register the paths subsys as a subsystem of pdc subsys */
+	kset_set_kset_s(&paths_subsys, pdc_subsys);
+	subsystem_register(&paths_subsys);
+
+	/* now we create all "files" for the paths subsys */
+	pdcs_register_pathentries();
+	
+	return 0;
+}
+
+static void __exit
+pdc_stable_exit(void)
+{
+	pdcs_unregister_pathentries();
+	subsystem_unregister(&paths_subsys);
+
+	firmware_unregister(&pdc_subsys);
+}
+
+
+module_init(pdc_stable_init);
+module_exit(pdc_stable_exit);
diff -Nru a/drivers/parisc/sba_iommu.c b/drivers/parisc/sba_iommu.c
--- a/drivers/parisc/sba_iommu.c	2005-03-11 12:51:48 -08:00
+++ b/drivers/parisc/sba_iommu.c	2005-03-11 12:51:48 -08:00
@@ -58,7 +58,6 @@
 ** Don't even think about messing with it unless you have
 ** plenty of 710's to sacrifice to the computer gods. :^)
 */
-#undef DEBUG_SBA_ASSERT
 #undef DEBUG_SBA_INIT
 #undef DEBUG_SBA_RUN
 #undef DEBUG_SBA_RUN_SG
@@ -92,19 +91,6 @@
 #define DBG_RES(x...)
 #endif
 
-#ifdef DEBUG_SBA_ASSERT
-#undef ASSERT
-#define ASSERT(expr) \
-	if(!(expr)) { \
-		printk("\n%s:%d: Assertion " #expr " failed!\n", \
-				__FILE__, __LINE__); \
-		panic(#expr); \
-	}
-#else
-#define ASSERT(expr)
-#endif
-
-
 #if defined(__LP64__) && !defined(CONFIG_PDC_NARROW)
 /* "low end" PA8800 machines use ZX1 chipset */
 #define ZX1_SUPPORT
@@ -125,39 +111,24 @@
 #define DEFAULT_DMA_HINT_REG	0
 
 #define ASTRO_RUNWAY_PORT	0x582
-#define ASTRO_ROPES_PORT	0x780
-
 #define IKE_MERCED_PORT		0x803
-#define IKE_ROPES_PORT		0x781
-
 #define REO_MERCED_PORT		0x804
-#define REO_ROPES_PORT		0x782
-
 #define REOG_MERCED_PORT	0x805
-#define REOG_ROPES_PORT		0x783
-
 #define PLUTO_MCKINLEY_PORT	0x880
-#define PLUTO_ROPES_PORT	0x784
 
 #define SBA_FUNC_ID	0x0000	/* function id */
 #define SBA_FCLASS	0x0008	/* function class, bist, header, rev... */
 
-#define IS_ASTRO(id) \
-(((id)->hversion == ASTRO_RUNWAY_PORT) || ((id)->hversion == ASTRO_ROPES_PORT))
-
-#define IS_IKE(id) \
-(((id)->hversion == IKE_MERCED_PORT) || ((id)->hversion == IKE_ROPES_PORT))
-
-#define IS_PLUTO(id) \
-(((id)->hversion == PLUTO_MCKINLEY_PORT) || ((id)->hversion == PLUTO_ROPES_PORT))
+#define IS_ASTRO(id)		((id)->hversion == ASTRO_RUNWAY_PORT)
+#define IS_IKE(id)		((id)->hversion == IKE_MERCED_PORT)
+#define IS_PLUTO(id)		((id)->hversion == PLUTO_MCKINLEY_PORT)
 
 #define SBA_FUNC_SIZE 4096   /* SBA configuration function reg set */
 
-#define ASTRO_IOC_OFFSET 0x20000
-/* Ike's IOC's occupy functions 2 and 3 (not 0 and 1) */
-#define IKE_IOC_OFFSET(p) ((p+2)*SBA_FUNC_SIZE)
-
-#define PLUTO_IOC_OFFSET 0x1000
+#define ASTRO_IOC_OFFSET	(32 * SBA_FUNC_SIZE)
+#define PLUTO_IOC_OFFSET	(1 * SBA_FUNC_SIZE)
+/* Ike's IOC's occupy functions 2 and 3 */
+#define IKE_IOC_OFFSET(p)	((p+2) * SBA_FUNC_SIZE)
 
 #define IOC_CTRL          0x8	/* IOC_CTRL offset */
 #define IOC_CTRL_TC       (1 << 0) /* TOC Enable */
@@ -165,6 +136,8 @@
 #define IOC_CTRL_DE       (1 << 2) /* Dillon Enable */
 #define IOC_CTRL_RM       (1 << 8) /* Real Mode */
 #define IOC_CTRL_NC       (1 << 9) /* Non Coherent Mode */
+#define IOC_CTRL_D4       (1 << 11) /* Disable 4-byte coalescing */
+#define IOC_CTRL_DD       (1 << 13) /* Disable distr. LMMIO range coalescing */
 
 #define MAX_IOC		2	/* per Ike. Pluto/Astro only have 1. */
 
@@ -246,9 +219,9 @@
 
 
 struct ioc {
-	unsigned long	ioc_hpa;	/* I/O MMU base address */
-	char	*res_map;	/* resource map, bit == pdir entry */
-	u64	*pdir_base;	/* physical base address */
+	void __iomem	*ioc_hpa;	/* I/O MMU base address */
+	char		*res_map;	/* resource map, bit == pdir entry */
+	u64		*pdir_base;	/* physical base address */
 	unsigned long	ibase;	/* pdir IOV Space base - shared w/lba_pci */
 	unsigned long	imask;	/* pdir IOV Space mask - shared w/lba_pci */
 #ifdef ZX1_SUPPORT
@@ -295,7 +268,7 @@
 	struct parisc_device	*dev;	/* dev found in bus walk */
 	struct parisc_device_id	*iodc;	/* data about dev from firmware */
 	const char 		*name;
-	unsigned long		sba_hpa; /* base address */
+	void __iomem		*sba_hpa; /* base address */
 	spinlock_t		sba_lock;
 	unsigned int		flags;  /* state/functionality enabled */
 	unsigned int		hw_rev;  /* HW revision of chip */
@@ -312,9 +285,6 @@
 
 static unsigned long ioc_needs_fdc = 0;
 
-/* Ratio of Host MEM to IOV Space size */
-static unsigned long sba_mem_ratio = 8;
-
 /* global count of IOMMUs in the system */
 static unsigned int global_ioc_cnt = 0;
 
@@ -364,9 +334,9 @@
  * IO Adapter (aka Bus Converter).
  */
 static void
-sba_dump_ranges(unsigned long hpa)
+sba_dump_ranges(void __iomem *hpa)
 {
-	DBG_INIT("SBA at 0x%lx\n", hpa);
+	DBG_INIT("SBA at 0x%p\n", hpa);
 	DBG_INIT("IOS_DIST_BASE   : %Lx\n", READ_REG64(hpa+IOS_DIST_BASE));
 	DBG_INIT("IOS_DIST_MASK   : %Lx\n", READ_REG64(hpa+IOS_DIST_MASK));
 	DBG_INIT("IOS_DIST_ROUTE  : %Lx\n", READ_REG64(hpa+IOS_DIST_ROUTE));
@@ -382,10 +352,9 @@
  *
  * Print the size/location of the IO MMU PDIR.
  */
-static void
-sba_dump_tlb(unsigned long hpa)
+static void sba_dump_tlb(void __iomem *hpa)
 {
-	DBG_INIT("IO TLB at 0x%lx\n", hpa);
+	DBG_INIT("IO TLB at 0x%p\n", hpa);
 	DBG_INIT("IOC_IBASE    : 0x%Lx\n", READ_REG64(hpa+IOC_IBASE));
 	DBG_INIT("IOC_IMASK    : 0x%Lx\n", READ_REG64(hpa+IOC_IMASK));
 	DBG_INIT("IOC_TCNFG    : 0x%Lx\n", READ_REG64(hpa+IOC_TCNFG));
@@ -547,8 +516,6 @@
 	unsigned long *res_end = (unsigned long *) &(ioc->res_map[ioc->res_size]);
 	unsigned long pide = ~0UL;
 
-	ASSERT(((unsigned long) ioc->res_hint & (sizeof(unsigned long) - 1UL)) == 0);
-	ASSERT(res_ptr < res_end);
 	if (bits_wanted > (BITS_PER_LONG/2)) {
 		/* Search word at a time - no mask needed */
 		for(; res_ptr < res_end; ++res_ptr) {
@@ -583,8 +550,8 @@
 		while(res_ptr < res_end)
 		{ 
 			DBG_RES("    %p %lx %lx\n", res_ptr, mask, *res_ptr);
-			BUG_ON(0 == mask);
-			if(0 == ((*res_ptr) & mask)) {
+			WARN_ON(mask == 0);
+			if(((*res_ptr) & mask) == 0) {
 				*res_ptr |= mask;     /* mark resources busy! */
 				pide = ((unsigned long)res_ptr - (unsigned long)ioc->res_map);
 				pide <<= 3;	/* convert to bit address */
@@ -593,7 +560,7 @@
 			}
 			mask >>= o;
 			bitshiftcnt += o;
-			if (0 == mask) {
+			if (mask == 0) {
 				mask = RESMAP_MASK(bits_wanted);
 				bitshiftcnt=0;
 				res_ptr++;
@@ -631,21 +598,11 @@
 #endif
 	unsigned long pide;
 
-	ASSERT(pages_needed);
-	ASSERT((pages_needed * IOVP_SIZE) <= DMA_CHUNK_SIZE);
-	ASSERT(pages_needed <= BITS_PER_LONG);
-	ASSERT(0 == (size & ~IOVP_MASK));
-
-	/*
-	** "seek and ye shall find"...praying never hurts either...
-	** ggg sacrifices another 710 to the computer gods.
-	*/
-
 	pide = sba_search_bitmap(ioc, pages_needed);
 	if (pide >= (ioc->res_size << 3)) {
 		pide = sba_search_bitmap(ioc, pages_needed);
 		if (pide >= (ioc->res_size << 3))
-			panic("%s: I/O MMU @ %lx is out of mapping resources\n",
+			panic("%s: I/O MMU @ %p is out of mapping resources\n",
 			      __FILE__, ioc->ioc_hpa);
 	}
 
@@ -707,11 +664,6 @@
 	ioc->used_pages -= bits_not_wanted;
 #endif
 
-	ASSERT(m != 0);
-	ASSERT(bits_not_wanted);
-	ASSERT((bits_not_wanted * IOVP_SIZE) <= DMA_CHUNK_SIZE);
-	ASSERT(bits_not_wanted <= BITS_PER_LONG);
-	ASSERT((*res_ptr & m) == m); /* verify same bits are set */
 	*res_ptr &= ~m;
 }
 
@@ -732,8 +684,9 @@
 /**
  * sba_io_pdir_entry - fill in one IO PDIR entry
  * @pdir_ptr:  pointer to IO PDIR entry
- * @sid: process Space ID
+ * @sid: process Space ID - currently only support KERNEL_SPACE
  * @vba: Virtual CPU address of buffer to map
+ * @hint: DMA hint set to use for this mapping
  *
  * SBA Mapping Routine
  *
@@ -768,7 +721,6 @@
  * IOMMU uses little endian for the pdir.
  */
 
-
 void SBA_INLINE
 sba_io_pdir_entry(u64 *pdir_ptr, space_t sid, unsigned long vba,
 		  unsigned long hint)
@@ -776,12 +728,6 @@
 	u64 pa; /* physical address */
 	register unsigned ci; /* coherent index */
 
-	/* We currently only support kernel addresses.
-	 * fdc instr below will need to reload sr1 with KERNEL_SPACE
-	 * once we try to support direct DMA to user space.
-	 */
-	ASSERT(sid == KERNEL_SPACE);
-
 	pa = virt_to_phys(vba);
 	pa &= IOVP_MASK;
 
@@ -830,10 +776,6 @@
 	*/
 	int off = PDIR_INDEX(iovp)*sizeof(u64)+7;
 
-	/* Must be non-zero and rounded up */
-	ASSERT(byte_cnt > 0);
-	ASSERT(0 == (byte_cnt & ~IOVP_MASK));
-
 #ifdef ASSERT_PDIR_SANITY
 	/* Assert first pdir entry is set */
 	if (0x80 != (((u8 *) ioc->pdir_base)[off])) {
@@ -843,8 +785,6 @@
 
 	if (byte_cnt <= IOVP_SIZE)
 	{
-		ASSERT( off < ioc->pdir_size);
-
 		iovp |= IOVP_SHIFT;     /* set "size" field for PCOM */
 
 		/*
@@ -858,11 +798,7 @@
 		u32 t = get_order(byte_cnt) + PAGE_SHIFT;
 
 		iovp |= t;
-		ASSERT(t <= 31);   /* 2GB! Max value of "size" field */
-
 		do {
-			/* verify this pdir entry is enabled */
-			ASSERT(0x80 == (((u8 *) ioc->pdir_base)[off] & 0x80));
 			/* clear I/O Pdir entry "valid" bit first */
 			((u8 *)(ioc->pdir_base))[off] = 0;
 			off += sizeof(u64);
@@ -880,17 +816,21 @@
  *
  * See Documentation/DMA-mapping.txt
  */
-static int
-sba_dma_supported( struct device *dev, u64 mask)
+static int sba_dma_supported( struct device *dev, u64 mask)
 {
+	struct ioc *ioc;
 	if (dev == NULL) {
 		printk(KERN_ERR MODULE_NAME ": EISA/ISA/et al not supported\n");
 		BUG();
 		return(0);
 	}
 
-	/* only support 32-bit PCI devices - no DAC support (yet) */
-	return((int) (mask == 0xffffffffUL));
+	ioc = GET_IOC(dev);
+
+	/* check if mask is > than the largest IO Virt Address */
+
+	return((int) (mask >= (ioc->ibase +
+				(ioc->pdir_size / sizeof(u64) * IOVP_SIZE) )));
 }
 
 
@@ -914,11 +854,7 @@
 	u64 *pdir_start;
 	int pide;
 
-	ASSERT(size > 0);
-	ASSERT(size <= DMA_CHUNK_SIZE);
-
 	ioc = GET_IOC(dev);
-	ASSERT(ioc);
 
 	/* save offset bits */
 	offset = ((dma_addr_t) (long) addr) & ~IOVP_MASK;
@@ -944,7 +880,6 @@
 	pdir_start = &(ioc->pdir_base[pide]);
 
 	while (size > 0) {
-		ASSERT(((u8 *)pdir_start)[7] == 0); /* verify availability */
 		sba_io_pdir_entry(pdir_start, KERNEL_SPACE, (unsigned long) addr, 0);
 
 		DBG_RUN("	pdir 0x%p %02x%02x%02x%02x%02x%02x%02x%02x\n",
@@ -992,14 +927,10 @@
 	unsigned long flags; 
 	dma_addr_t offset;
 
-	ioc = GET_IOC(dev);
-	ASSERT(ioc);
+	DBG_RUN("%s() iovp 0x%lx/%x\n", __FUNCTION__, (long) iova, size);
 
+	ioc = GET_IOC(dev);
 	offset = iova & ~IOVP_MASK;
-
-	DBG_RUN("%s() iovp 0x%lx/%x\n",
-		__FUNCTION__, (long) iova, size);
-
 	iova ^= offset;        /* clear offset bits */
 	size += offset;
 	size = ROUNDUP(size, IOVP_SIZE);
@@ -1131,7 +1062,6 @@
 	DBG_RUN_SG("%s() START %d entries\n", __FUNCTION__, nents);
 
 	ioc = GET_IOC(dev);
-	ASSERT(ioc);
 
 	/* Fast path single entry scatterlists. */
 	if (nents == 1) {
@@ -1186,7 +1116,6 @@
 
 	spin_unlock_irqrestore(&ioc->res_lock, flags);
 
-	ASSERT(coalesced == filled);
 	DBG_RUN_SG("%s() DONE %d mappings\n", __FUNCTION__, filled);
 
 	return filled;
@@ -1215,7 +1144,6 @@
 		__FUNCTION__, nents, sg_virt_addr(sglist), sglist->length);
 
 	ioc = GET_IOC(dev);
-	ASSERT(ioc);
 
 #ifdef SBA_COLLECT_STATS
 	ioc->usg_calls++;
@@ -1394,16 +1322,27 @@
 	return (void *) pdir_base;
 }
 
-static void
-sba_ioc_init_pluto(struct parisc_device *sba, struct ioc *ioc, int ioc_num)
+/* setup Mercury or Elroy IBASE/IMASK registers. */
+static void setup_ibase_imask(struct parisc_device *sba, struct ioc *ioc, int ioc_num)
 {
-        /* lba_set_iregs() is in arch/parisc/kernel/lba_pci.c */
+        /* lba_set_iregs() is in drivers/parisc/lba_pci.c */
         extern void lba_set_iregs(struct parisc_device *, u32, u32);
+	struct device *dev;
+
+	list_for_each_entry(dev, &sba->dev.children, node) {
+		struct parisc_device *lba = to_parisc_device(dev);
+		int rope_num = (lba->hpa >> 13) & 0xf;
+		if (rope_num >> 3 == ioc_num)
+			lba_set_iregs(lba, ioc->ibase, ioc->imask);
+	}
+}
 
+static void
+sba_ioc_init_pluto(struct parisc_device *sba, struct ioc *ioc, int ioc_num)
+{
 	u32 iova_space_mask;
 	u32 iova_space_size;
 	int iov_order, tcnfg;
-	struct parisc_device *lba;
 #if SBA_AGP_SUPPORT
 	int agp_found = 0;
 #endif
@@ -1449,7 +1388,7 @@
 		ioc->hint_shift_pdir, ioc->hint_mask_pdir);
 #endif
 
-	ASSERT((((unsigned long) ioc->pdir_base) & PAGE_MASK) == (unsigned long) ioc->pdir_base);
+	WARN_ON((((unsigned long) ioc->pdir_base) & PAGE_MASK) != (unsigned long) ioc->pdir_base);
 	WRITE_REG(virt_to_phys(ioc->pdir_base), ioc->ioc_hpa + IOC_PDIR_BASE);
 
 	/* build IMASK for IOC and Elroy */
@@ -1461,14 +1400,7 @@
 #endif
 	sba_dump_tlb(ioc->ioc_hpa);
 
-	/*
-	** setup Mercury IBASE/IMASK registers as well.
-	*/
-	for (lba = sba->child; lba; lba = lba->sibling) {
-		int rope_num = (lba->hpa >> 13) & 0xf;
-		if (rope_num >> 3 == ioc_num)
-			lba_set_iregs(lba, ioc->ibase, ioc->imask);
-	}
+	setup_ibase_imask(sba, ioc, ioc_num);
 
 	WRITE_REG(ioc->imask, ioc->ioc_hpa + IOC_IMASK);
 
@@ -1534,13 +1466,8 @@
 static void
 sba_ioc_init(struct parisc_device *sba, struct ioc *ioc, int ioc_num)
 {
-	/* lba_set_iregs() is in arch/parisc/kernel/lba_pci.c */
-	extern void lba_set_iregs(struct parisc_device *, u32, u32);
-
 	u32 iova_space_size, iova_space_mask;
-	int pdir_size, iov_order;
-	unsigned long physmem;
-	struct parisc_device *lba;
+	unsigned int pdir_size, iov_order;
 
 	/*
 	** Determine IOVA Space size from memory size.
@@ -1556,16 +1483,15 @@
 	** for DMA hints - ergo only 30 bits max.
 	*/
 
-	physmem = num_physpages << PAGE_SHIFT;
-	iova_space_size = (u32) (physmem/(sba_mem_ratio*global_ioc_cnt));
+	iova_space_size = (u32) (num_physpages/global_ioc_cnt);
 
 	/* limit IOVA space size to 1MB-1GB */
-	if (iova_space_size < 1024*1024) {
-		iova_space_size = 1024*1024;
+	if (iova_space_size < (1 << (20 - PAGE_SHIFT))) {
+		iova_space_size = 1 << (20 - PAGE_SHIFT);
 	}
 #ifdef __LP64__
-	else if (iova_space_size > 512*1024*1024) {
-		iova_space_size = 512*1024*1024;
+	else if (iova_space_size > (1 << (30 - PAGE_SHIFT))) {
+		iova_space_size = 1 << (30 - PAGE_SHIFT);
 	}
 #endif
 
@@ -1574,21 +1500,19 @@
 	** thus, pdir/res_map will also be log2().
 	** PIRANHA BUG: Exception is when IO Pdir is 2MB (gets reduced)
 	*/
-	iov_order = get_order(iova_space_size >> (IOVP_SHIFT-PAGE_SHIFT));
-	ASSERT(iov_order <= (30 - IOVP_SHIFT));   /* iova_space_size <= 1GB */
-	ASSERT(iov_order >= (20 - IOVP_SHIFT));   /* iova_space_size >= 1MB */
-	iova_space_size = 1 << (iov_order + IOVP_SHIFT);
+	iov_order = get_order(iova_space_size << PAGE_SHIFT);
 
-	ioc->pdir_size = pdir_size = (iova_space_size/IOVP_SIZE) * sizeof(u64);
+	/* iova_space_size is now bytes, not pages */
+	iova_space_size = 1 << (iov_order + PAGE_SHIFT);
 
-	ASSERT(pdir_size < 4*1024*1024);   /* max pdir size == 2MB */
-
-	/* Verify it's a power of two */
-	ASSERT((1 << get_order(pdir_size)) == (pdir_size >> PAGE_SHIFT));
+	ioc->pdir_size = pdir_size = (iova_space_size/IOVP_SIZE) * sizeof(u64);
 
-	DBG_INIT("%s() hpa 0x%lx mem %dMB IOV %dMB (%d bits) PDIR size 0x%0x\n",
-		__FUNCTION__, ioc->ioc_hpa, (int) (physmem>>20),
-		iova_space_size>>20, iov_order + PAGE_SHIFT, pdir_size);
+	DBG_INIT("%s() hpa 0x%lx mem %ldMB IOV %dMB (%d bits)\n",
+			__FUNCTION__,
+			ioc->ioc_hpa,
+			(unsigned long) num_physpages >> (20 - PAGE_SHIFT),
+			iova_space_size>>20,
+			iov_order + PAGE_SHIFT);
 
 	ioc->pdir_base = sba_alloc_pdir(pdir_size);
 
@@ -1604,7 +1528,6 @@
 			ioc->hint_shift_pdir, ioc->hint_mask_pdir);
 #endif
 
-	ASSERT((((unsigned long) ioc->pdir_base) & PAGE_MASK) == (unsigned long) ioc->pdir_base);
 	WRITE_REG64(virt_to_phys(ioc->pdir_base), ioc->ioc_hpa + IOC_PDIR_BASE);
 
 	/* build IMASK for IOC and Elroy */
@@ -1630,14 +1553,7 @@
 	** can't reprogram them the way drivers want.
 	*/
 
-	/*
-	** setup Elroy IBASE/IMASK registers as well.
-	*/
-	for (lba = sba->child; lba; lba = lba->sibling) {
-		int rope_num = (lba->hpa >> 13) & 0xf;
-		if (rope_num >> 3 == ioc_num)
-			lba_set_iregs(lba, ioc->ibase, ioc->imask);
-	}
+	setup_ibase_imask(sba, ioc, ioc_num);
 
 	/*
 	** Program the IOC's ibase and enable IOVA translation
@@ -1672,8 +1588,12 @@
 **
 **************************************************************************/
 
-static void
-sba_hw_init(struct sba_device *sba_dev)
+static void __iomem *ioc_remap(struct sba_device *sba_dev, int offset)
+{
+	return ioremap(sba_dev->dev->hpa + offset, SBA_FUNC_SIZE);
+}
+
+static void sba_hw_init(struct sba_device *sba_dev)
 { 
 	int i;
 	int num_ioc;
@@ -1682,24 +1602,55 @@
 	if (!is_pdc_pat()) {
 		/* Shutdown the USB controller on Astro-based workstations.
 		** Once we reprogram the IOMMU, the next DMA performed by
-		** USB will HPMC the box.
+		** USB will HPMC the box. USB is only enabled if a
+		** keyboard is present and found.
+		**
+		** With serial console, j6k v5.0 firmware says:
+		**   mem_kbd hpa 0xfee003f8 sba 0x0 pad 0x0 cl_class 0x7
+		**
+		** FIXME: Using GFX+USB console at power up but direct
+		**	linux to serial console is still broken.
+		**	USB could generate DMA so we must reset USB.
+		**	The proper sequence would be:
+		**	o block console output
+		**	o reset USB device
+		**	o reprogram serial port
+		**	o unblock console output
 		*/
-		pdc_io_reset_devices();
+		if (PAGE0->mem_kbd.cl_class == CL_KEYBD) {
+			pdc_io_reset_devices();
+		}
 
-		/*
-		** XXX May need something more sophisticated to deal
-		**     with DMA from LAN. Maybe use page zero boot device
-		**     as a handle to talk to PDC about which device to
-		**     shutdown. This also needs to work for is_pdc_pat(). 
-		*/
 	}
 
+
+#if 0
+printk("sba_hw_init(): mem_boot 0x%x 0x%x 0x%x 0x%x\n", PAGE0->mem_boot.hpa,
+	PAGE0->mem_boot.spa, PAGE0->mem_boot.pad, PAGE0->mem_boot.cl_class);
+
+	/*
+	** Need to deal with DMA from LAN.
+	**	Maybe use page zero boot device as a handle to talk
+	**	to PDC about which device to shutdown.
+	**
+	** Netbooting, j6k v5.0 firmware says:
+	** 	mem_boot hpa 0xf4008000 sba 0x0 pad 0x0 cl_class 0x1002
+	** ARGH! invalid class.
+	*/
+	if ((PAGE0->mem_boot.cl_class != CL_RANDOM)
+		&& (PAGE0->mem_boot.cl_class != CL_SEQU)) {
+			pdc_io_reset();
+	}
+#endif
+
 	if (!IS_PLUTO(sba_dev->iodc)) {
 		ioc_ctl = READ_REG(sba_dev->sba_hpa+IOC_CTRL);
 		DBG_INIT("%s() hpa 0x%lx ioc_ctl 0x%Lx ->",
 			__FUNCTION__, sba_dev->sba_hpa, ioc_ctl);
 		ioc_ctl &= ~(IOC_CTRL_RM | IOC_CTRL_NC | IOC_CTRL_CE);
-		ioc_ctl |= IOC_CTRL_TC;	/* Astro: firmware enables this */
+		ioc_ctl |= IOC_CTRL_DD | IOC_CTRL_D4 | IOC_CTRL_TC;
+			/* j6700 v1.6 firmware sets 0x294f */
+			/* A500 firmware sets 0x4d */
 
 		WRITE_REG(ioc_ctl, sba_dev->sba_hpa+IOC_CTRL);
 
@@ -1712,7 +1663,7 @@
 	if (IS_ASTRO(sba_dev->iodc)) {
 		int err;
 		/* PAT_PDC (L-class) also reports the same goofy base */
-		sba_dev->ioc[0].ioc_hpa = ASTRO_IOC_OFFSET;
+		sba_dev->ioc[0].ioc_hpa = ioc_remap(sba_dev, ASTRO_IOC_OFFSET);
 		num_ioc = 1;
 
 		sba_dev->chip_resv.name = "Astro Intr Ack";
@@ -1730,32 +1681,32 @@
                  * corrected when we add it with IKE's IOC offset.
 		 * Doesnt look clean, but fewer code. 
                  */
-		sba_dev->ioc[0].ioc_hpa = -PLUTO_IOC_OFFSET;
+		sba_dev->ioc[0].ioc_hpa = ioc_remap(sba_dev, PLUTO_IOC_OFFSET);
 		num_ioc = 1;
 
 		sba_dev->chip_resv.name = "Pluto Intr/PIOP/VGA";
 		sba_dev->chip_resv.start = PCI_F_EXTEND | 0xfee00000UL;
 		sba_dev->chip_resv.end   = PCI_F_EXTEND | (0xff200000UL - 1);
 		err = request_resource(&iomem_resource, &(sba_dev->chip_resv));
-		BUG_ON(err < 0);
+		WARN_ON(err < 0);
 
 		sba_dev->iommu_resv.name = "IOVA Space";
 		sba_dev->iommu_resv.start = 0x40000000UL;
 		sba_dev->iommu_resv.end   = 0x50000000UL - 1;
 		err = request_resource(&iomem_resource, &(sba_dev->iommu_resv));
-		BUG_ON(err < 0);
+		WARN_ON(err < 0);
 	} else {
 		/* IS_IKE (ie N-class, L3000, L1500) */
-		sba_dev->ioc[0].ioc_hpa = sba_dev->ioc[1].ioc_hpa = 0;
+		sba_dev->ioc[0].ioc_hpa = ioc_remap(sba_dev, IKE_IOC_OFFSET(0));
+		sba_dev->ioc[1].ioc_hpa = ioc_remap(sba_dev, IKE_IOC_OFFSET(1));
 		num_ioc = 2;
 
 		/* TODO - LOOKUP Ike/Stretch chipset mem map */
 	}
+	/* XXX: What about Reo? */
 
 	sba_dev->num_ioc = num_ioc;
 	for (i = 0; i < num_ioc; i++) {
-		sba_dev->ioc[i].ioc_hpa += sba_dev->sba_hpa + IKE_IOC_OFFSET(i);
-
 		/*
 		** Make sure the box crashes if we get any errors on a rope.
 		*/
@@ -1771,6 +1722,16 @@
 		/* flush out the writes */
 		READ_REG(sba_dev->ioc[i].ioc_hpa + ROPE7_CTL);
 
+		DBG_INIT("	ioc[%d] ROPE_CFG 0x%Lx  ROPE_DBG 0x%Lx\n",
+				i,
+				READ_REG(sba_dev->ioc[i].ioc_hpa + 0x40),
+				READ_REG(sba_dev->ioc[i].ioc_hpa + 0x50)
+			);
+		DBG_INIT("	STATUS_CONTROL 0x%Lx  FLUSH_CTRL 0x%Lx\n",
+				READ_REG(sba_dev->ioc[i].ioc_hpa + 0x108),
+				READ_REG(sba_dev->ioc[i].ioc_hpa + 0x400)
+			);
+
 		if (IS_PLUTO(sba_dev->iodc)) {
 			sba_ioc_init_pluto(sba_dev->dev, &(sba_dev->ioc[i]), i);
 		} else {
@@ -1984,16 +1945,6 @@
 	{ HPHW_BCPORT, HVERSION_REV_ANY_ID, REO_MERCED_PORT, 0xc },
 	{ HPHW_BCPORT, HVERSION_REV_ANY_ID, REOG_MERCED_PORT, 0xc },
 	{ HPHW_IOA, HVERSION_REV_ANY_ID, PLUTO_MCKINLEY_PORT, 0xc },
-/* These two entries commented out because we don't find them in a
- * buswalk yet.  If/when we do, they would cause us to think we had
- * many more SBAs then we really do.
- *	{ HPHW_BCPORT, HVERSION_REV_ANY_ID, ASTRO_ROPES_PORT, 0xc },
- *	{ HPHW_BCPORT, HVERSION_REV_ANY_ID, IKE_ROPES_PORT, 0xc },
- */
-/* We shall also comment out Pluto Ropes Port since bus walk doesnt
- * report it yet. 
- *	{ HPHW_BCPORT, HVERSION_REV_ANY_ID, PLUTO_ROPES_PORT, 0xc },
- */
 	{ 0, }
 };
 
@@ -2017,18 +1968,19 @@
 	u32 func_class;
 	int i;
 	char *version;
+	void __iomem *sba_addr = ioremap(dev->hpa, SBA_FUNC_SIZE);
 
-	sba_dump_ranges(dev->hpa);
+	sba_dump_ranges(sba_addr);
 
 	/* Read HW Rev First */
-	func_class = READ_REG(dev->hpa + SBA_FCLASS);
+	func_class = READ_REG(sba_addr + SBA_FCLASS);
 
 	if (IS_ASTRO(&dev->id)) {
 		unsigned long fclass;
 		static char astro_rev[]="Astro ?.?";
 
 		/* Astro is broken...Read HW Rev First */
-		fclass = READ_REG(dev->hpa);
+		fclass = READ_REG(sba_addr);
 
 		astro_rev[6] = '1' + (char) (fclass & 0x7);
 		astro_rev[8] = '0' + (char) ((fclass & 0x18) >> 3);
@@ -2061,12 +2013,12 @@
 		MODULE_NAME, version, dev->hpa);
 
 	sba_dev = kmalloc(sizeof(struct sba_device), GFP_KERNEL);
-	if (NULL == sba_dev) {
+	if (!sba_dev) {
 		printk(KERN_ERR MODULE_NAME " - couldn't alloc sba_device\n");
-		return(1);
+		return -ENOMEM;
 	}
 
-	dev->sysdata = (void *) sba_dev;
+	parisc_set_drvdata(dev, sba_dev);
 	memset(sba_dev, 0, sizeof(struct sba_device));
 
 	for(i=0; i<MAX_IOC; i++)
@@ -2076,7 +2028,7 @@
 	sba_dev->hw_rev = func_class;
 	sba_dev->iodc = &dev->id;
 	sba_dev->name = dev->name;
-	sba_dev->sba_hpa = dev->hpa;  /* faster access */
+	sba_dev->sba_hpa = sba_addr;
 
 	sba_get_pat_resources(sba_dev);
 	sba_hw_init(sba_dev);
@@ -2100,7 +2052,7 @@
 #endif
 	parisc_vmerge_boundary = IOVP_SIZE;
 	parisc_vmerge_max_size = IOVP_SIZE * BITS_PER_LONG;
-
+	parisc_has_iommu();
 	return 0;
 }
 
@@ -2129,7 +2081,7 @@
 	char t = sba_dev->id.hw_type;
 	int iocnum = (pci_hba->hw_path >> 3);	/* rope # */
 
-	BUG_ON((t != HPHW_IOA) && (t != HPHW_BCPORT));
+	WARN_ON((t != HPHW_IOA) && (t != HPHW_BCPORT));
 
 	return &(sba->ioc[iocnum]);
 }
@@ -2159,7 +2111,7 @@
 	/* Astro has 4 directed ranges. Not sure about Ike/Pluto/et al */
 	for (i=0; i<4; i++) {
 		int base, size;
-		unsigned long reg = sba->sba_hpa + i*0x18;
+		void __iomem *reg = sba->sba_hpa + i*0x18;
 
 		base = READ_REG32(reg + LMMIO_DIRECT0_BASE);
 		if ((base & 1) == 0)
diff -Nru a/drivers/parport/parport_gsc.c b/drivers/parport/parport_gsc.c
--- a/drivers/parport/parport_gsc.c	2005-03-11 12:51:51 -08:00
+++ b/drivers/parport/parport_gsc.c	2005-03-11 12:51:51 -08:00
@@ -42,7 +42,7 @@
 #include <asm/pdc.h>
 #include <asm/parisc-device.h>
 #include <asm/hardware.h>
-#include <asm/parport_gsc.h>
+#include "parport_gsc.h"
 
 
 MODULE_AUTHOR("Helge Deller <deller@gmx.de>");
@@ -85,95 +85,6 @@
 {
 	parport_generic_irq(irq, (struct parport *) dev_id, regs);
 	return IRQ_HANDLED;
-}
-
-void parport_gsc_write_data(struct parport *p, unsigned char d)
-{
-	parport_writeb (d, DATA (p));
-}
-
-unsigned char parport_gsc_read_data(struct parport *p)
-{
-	unsigned char c = parport_readb (DATA (p));
-	return c;
-}
-
-void parport_gsc_write_control(struct parport *p, unsigned char d)
-{
-	const unsigned char wm = (PARPORT_CONTROL_STROBE |
-				  PARPORT_CONTROL_AUTOFD |
-				  PARPORT_CONTROL_INIT |
-				  PARPORT_CONTROL_SELECT);
-
-	/* Take this out when drivers have adapted to the newer interface. */
-	if (d & 0x20) {
-		pr_debug("%s (%s): use data_reverse for this!\n",
-			    p->name, p->cad->name);
-		parport_gsc_data_reverse (p);
-	}
-
-	__parport_gsc_frob_control (p, wm, d & wm);
-}
-
-unsigned char parport_gsc_read_control(struct parport *p)
-{
-	const unsigned char wm = (PARPORT_CONTROL_STROBE |
-				  PARPORT_CONTROL_AUTOFD |
-				  PARPORT_CONTROL_INIT |
-				  PARPORT_CONTROL_SELECT);
-	const struct parport_gsc_private *priv = p->physport->private_data;
-	return priv->ctr & wm; /* Use soft copy */
-}
-
-unsigned char parport_gsc_frob_control (struct parport *p, unsigned char mask,
-				       unsigned char val)
-{
-	const unsigned char wm = (PARPORT_CONTROL_STROBE |
-				  PARPORT_CONTROL_AUTOFD |
-				  PARPORT_CONTROL_INIT |
-				  PARPORT_CONTROL_SELECT);
-
-	/* Take this out when drivers have adapted to the newer interface. */
-	if (mask & 0x20) {
-		pr_debug("%s (%s): use data_%s for this!\n",
-			p->name, p->cad->name,
-			(val & 0x20) ? "reverse" : "forward");
-		if (val & 0x20)
-			parport_gsc_data_reverse (p);
-		else
-			parport_gsc_data_forward (p);
-	}
-
-	/* Restrict mask and val to control lines. */
-	mask &= wm;
-	val &= wm;
-
-	return __parport_gsc_frob_control (p, mask, val);
-}
-
-unsigned char parport_gsc_read_status(struct parport *p)
-{
-	return parport_readb (STATUS (p));
-}
-
-void parport_gsc_disable_irq(struct parport *p)
-{
-	__parport_gsc_frob_control (p, 0x10, 0);
-}
-
-void parport_gsc_enable_irq(struct parport *p)
-{
-	__parport_gsc_frob_control (p, 0x10, 0x10);
-}
-
-void parport_gsc_data_forward (struct parport *p)
-{
-	__parport_gsc_frob_control (p, 0x20, 0);
-}
-
-void parport_gsc_data_reverse (struct parport *p)
-{
-	__parport_gsc_frob_control (p, 0x20, 0x20);
 }
 
 void parport_gsc_init_state(struct pardevice *dev, struct parport_state *s)
diff -Nru a/drivers/parport/parport_gsc.h b/drivers/parport/parport_gsc.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/parport/parport_gsc.h	2005-03-11 12:51:51 -08:00
@@ -0,0 +1,222 @@
+/*
+ *	Low-level parallel-support for PC-style hardware integrated in the
+ *	LASI-Controller (on GSC-Bus) for HP-PARISC Workstations
+ *
+ *	(C) 1999-2001 by Helge Deller <deller@gmx.de>
+ *
+ *
+ *	This program is free software; you can redistribute it and/or modify
+ *	it under the terms of the GNU General Public License as published by
+ *	the Free Software Foundation; either version 2 of the License, or
+ *	(at your option) any later version.
+ *
+ *	This program is distributed in the hope that it will be useful,
+ *	but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *	GNU General Public License for more details.
+ *
+ *	You should have received a copy of the GNU General Public License
+ *	along with this program; if not, write to the Free Software
+ *	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * based on parport_pc.c by
+ * 	    Grant Guenther <grant@torque.net>
+ * 	    Phil Blundell <Philip.Blundell@pobox.com>
+ *          Tim Waugh <tim@cyberelk.demon.co.uk>
+ *	    Jose Renau <renau@acm.org>
+ *          David Campbell <campbell@torque.net>
+ *          Andrea Arcangeli
+ */
+
+#ifndef	__DRIVERS_PARPORT_PARPORT_GSC_H
+#define	__DRIVERS_PARPORT_PARPORT_GSC_H
+
+#include <asm/io.h>
+#include <linux/delay.h>
+
+#undef	DEBUG_PARPORT	/* undefine for production */
+#define DELAY_TIME 	0
+
+#if DELAY_TIME == 0
+#define parport_readb	gsc_readb
+#define parport_writeb	gsc_writeb
+#else
+static __inline__ unsigned char parport_readb( unsigned long port )
+{
+    udelay(DELAY_TIME);
+    return gsc_readb(port);
+}
+
+static __inline__ void parport_writeb( unsigned char value, unsigned long port )
+{
+    gsc_writeb(value,port);
+    udelay(DELAY_TIME);
+}
+#endif
+
+/* --- register definitions ------------------------------- */
+
+#define EPPDATA(p)  ((p)->base    + 0x4)
+#define EPPADDR(p)  ((p)->base    + 0x3)
+#define CONTROL(p)  ((p)->base    + 0x2)
+#define STATUS(p)   ((p)->base    + 0x1)
+#define DATA(p)     ((p)->base    + 0x0)
+
+struct parport_gsc_private {
+	/* Contents of CTR. */
+	unsigned char ctr;
+
+	/* Bitmask of writable CTR bits. */
+	unsigned char ctr_writable;
+
+	/* Number of bytes per portword. */
+	int pword;
+
+	/* Not used yet. */
+	int readIntrThreshold;
+	int writeIntrThreshold;
+
+	/* buffer suitable for DMA, if DMA enabled */
+	char *dma_buf;
+	dma_addr_t dma_handle;
+	struct pci_dev *dev;
+};
+
+static inline void parport_gsc_write_data(struct parport *p, unsigned char d)
+{
+#ifdef DEBUG_PARPORT
+	printk (KERN_DEBUG "parport_gsc_write_data(%p,0x%02x)\n", p, d);
+#endif
+	parport_writeb(d, DATA(p));
+}
+
+static inline unsigned char parport_gsc_read_data(struct parport *p)
+{
+	unsigned char val = parport_readb (DATA (p));
+#ifdef DEBUG_PARPORT
+	printk (KERN_DEBUG "parport_gsc_read_data(%p) = 0x%02x\n",
+		p, val);
+#endif
+	return val;
+}
+
+/* __parport_gsc_frob_control differs from parport_gsc_frob_control in that
+ * it doesn't do any extra masking. */
+static inline unsigned char __parport_gsc_frob_control(struct parport *p,
+							unsigned char mask,
+							unsigned char val)
+{
+	struct parport_gsc_private *priv = p->physport->private_data;
+	unsigned char ctr = priv->ctr;
+#ifdef DEBUG_PARPORT
+	printk (KERN_DEBUG
+		"__parport_gsc_frob_control(%02x,%02x): %02x -> %02x\n",
+		mask, val, ctr, ((ctr & ~mask) ^ val) & priv->ctr_writable);
+#endif
+	ctr = (ctr & ~mask) ^ val;
+	ctr &= priv->ctr_writable; /* only write writable bits. */
+	parport_writeb (ctr, CONTROL (p));
+	priv->ctr = ctr;	/* Update soft copy */
+	return ctr;
+}
+
+static inline void parport_gsc_data_reverse(struct parport *p)
+{
+	__parport_gsc_frob_control (p, 0x20, 0x20);
+}
+
+static inline void parport_gsc_data_forward(struct parport *p)
+{
+	__parport_gsc_frob_control (p, 0x20, 0x00);
+}
+
+static inline void parport_gsc_write_control(struct parport *p,
+						 unsigned char d)
+{
+	const unsigned char wm = (PARPORT_CONTROL_STROBE |
+				  PARPORT_CONTROL_AUTOFD |
+				  PARPORT_CONTROL_INIT |
+				  PARPORT_CONTROL_SELECT);
+
+	/* Take this out when drivers have adapted to newer interface. */
+	if (d & 0x20) {
+		printk (KERN_DEBUG "%s (%s): use data_reverse for this!\n",
+			p->name, p->cad->name);
+		parport_gsc_data_reverse (p);
+	}
+
+	__parport_gsc_frob_control (p, wm, d & wm);
+}
+
+static inline unsigned char parport_gsc_read_control(struct parport *p)
+{
+	const unsigned char rm = (PARPORT_CONTROL_STROBE |
+				  PARPORT_CONTROL_AUTOFD |
+				  PARPORT_CONTROL_INIT |
+				  PARPORT_CONTROL_SELECT);
+	const struct parport_gsc_private *priv = p->physport->private_data;
+	return priv->ctr & rm; /* Use soft copy */
+}
+
+static inline unsigned char parport_gsc_frob_control(struct parport *p,
+							unsigned char mask,
+							unsigned char val)
+{
+	const unsigned char wm = (PARPORT_CONTROL_STROBE |
+				  PARPORT_CONTROL_AUTOFD |
+				  PARPORT_CONTROL_INIT |
+				  PARPORT_CONTROL_SELECT);
+
+	/* Take this out when drivers have adapted to newer interface. */
+	if (mask & 0x20) {
+		printk (KERN_DEBUG "%s (%s): use data_%s for this!\n",
+			p->name, p->cad->name,
+			(val & 0x20) ? "reverse" : "forward");
+		if (val & 0x20)
+			parport_gsc_data_reverse (p);
+		else
+			parport_gsc_data_forward (p);
+	}
+
+	/* Restrict mask and val to control lines. */
+	mask &= wm;
+	val &= wm;
+
+	return __parport_gsc_frob_control (p, mask, val);
+}
+
+static inline unsigned char parport_gsc_read_status(struct parport *p)
+{
+	return parport_readb (STATUS(p));
+}
+
+static inline void parport_gsc_disable_irq(struct parport *p)
+{
+	__parport_gsc_frob_control (p, 0x10, 0x00);
+}
+
+static inline void parport_gsc_enable_irq(struct parport *p)
+{
+	__parport_gsc_frob_control (p, 0x10, 0x10);
+}
+
+extern void parport_gsc_release_resources(struct parport *p);
+
+extern int parport_gsc_claim_resources(struct parport *p);
+
+extern void parport_gsc_init_state(struct pardevice *, struct parport_state *s);
+
+extern void parport_gsc_save_state(struct parport *p, struct parport_state *s);
+
+extern void parport_gsc_restore_state(struct parport *p, struct parport_state *s);
+
+extern void parport_gsc_inc_use_count(void);
+
+extern void parport_gsc_dec_use_count(void);
+
+extern struct parport *parport_gsc_probe_port(unsigned long base,
+						unsigned long base_hi,
+						int irq, int dma,
+						struct pci_dev *dev);
+
+#endif	/* __DRIVERS_PARPORT_PARPORT_GSC_H */
diff -Nru a/drivers/parport/parport_pc.c b/drivers/parport/parport_pc.c
--- a/drivers/parport/parport_pc.c	2005-03-11 12:51:51 -08:00
+++ b/drivers/parport/parport_pc.c	2005-03-11 12:51:51 -08:00
@@ -2907,10 +2907,16 @@
 };
 MODULE_DEVICE_TABLE(pci,parport_pc_pci_tbl);
 
+struct pci_parport_data {
+	int num;
+	struct parport *ports[2];
+};
+
 static int parport_pc_pci_probe (struct pci_dev *dev,
 					   const struct pci_device_id *id)
 {
 	int err, count, n, i = id->driver_data;
+	struct pci_parport_data *data;
 
 	if (i < last_sio)
 		/* This is an onboard Super-IO and has already been probed */
@@ -2922,9 +2928,15 @@
 	if ((err = pci_enable_device (dev)) != 0)
 		return err;
 
+	data = kmalloc(sizeof(struct pci_parport_data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
 	if (cards[i].preinit_hook &&
-	    cards[i].preinit_hook (dev, PARPORT_IRQ_NONE, PARPORT_DMA_NONE))
+	    cards[i].preinit_hook (dev, PARPORT_IRQ_NONE, PARPORT_DMA_NONE)) {
+		kfree(data);
 		return -ENODEV;
+	}
 
 	for (n = 0; n < cards[i].numports; n++) {
 		int lo = cards[i].addr[n].lo;
@@ -2943,21 +2955,46 @@
 			"I/O at %#lx(%#lx)\n",
 			parport_pc_pci_tbl[i + last_sio].vendor,
 			parport_pc_pci_tbl[i + last_sio].device, io_lo, io_hi);
-		if (parport_pc_probe_port (io_lo, io_hi, PARPORT_IRQ_NONE,
-					   PARPORT_DMA_NONE, dev))
+		data->ports[count] =
+			parport_pc_probe_port (io_lo, io_hi, PARPORT_IRQ_NONE,
+					       PARPORT_DMA_NONE, dev);
+		if (data->ports[count])
 			count++;
 	}
 
+	data->num = count;
+
 	if (cards[i].postinit_hook)
 		cards[i].postinit_hook (dev, count == 0);
 
-	return count == 0 ? -ENODEV : 0;
+	if (count) {
+		pci_set_drvdata(dev, data);
+		return 0;
+	}
+
+	kfree(data);
+
+	return -ENODEV;
+}
+
+static void __devexit parport_pc_pci_remove(struct pci_dev *dev)
+{
+	struct pci_parport_data *data = pci_get_drvdata(dev);
+	int i;
+
+	pci_set_drvdata(dev, NULL);
+
+	for (i = data->num - 1; i >= 0; i--)
+		parport_pc_unregister_port(data->ports[i]);
+
+	kfree(data);
 }
 
 static struct pci_driver parport_pc_pci_driver = {
 	.name		= "parport_pc",
 	.id_table	= parport_pc_pci_tbl,
 	.probe		= parport_pc_pci_probe,
+	.remove		= __devexit_p(parport_pc_pci_remove),
 };
 
 static int __init parport_pc_init_superio (int autoirq, int autodma)
diff -Nru a/drivers/pci/hotplug/ibmphp_pci.c b/drivers/pci/hotplug/ibmphp_pci.c
--- a/drivers/pci/hotplug/ibmphp_pci.c	2005-03-11 12:51:40 -08:00
+++ b/drivers/pci/hotplug/ibmphp_pci.c	2005-03-11 12:51:40 -08:00
@@ -1384,9 +1384,6 @@
 		return -EINVAL;
 	}
 
-	pci_bus_read_config_byte (ibmphp_pci_bus, devfn, PCI_SECONDARY_BUS, &sec_number);
-	sec_no = (int) sec_no;
-
 	pci_bus_read_config_byte (ibmphp_pci_bus, devfn, PCI_SUBORDINATE_BUS, &sub_number);
 	sub_no = (int) sub_number;
 	debug ("sub_no is %d, sec_no is %d\n", sub_no, sec_no);
diff -Nru a/drivers/pci/hotplug/pciehp_ctrl.c b/drivers/pci/hotplug/pciehp_ctrl.c
--- a/drivers/pci/hotplug/pciehp_ctrl.c	2005-03-11 12:51:41 -08:00
+++ b/drivers/pci/hotplug/pciehp_ctrl.c	2005-03-11 12:51:41 -08:00
@@ -1354,10 +1354,11 @@
 				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
+			} 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);
 		}
diff -Nru a/drivers/pci/hotplug/pciehprm_acpi.c b/drivers/pci/hotplug/pciehprm_acpi.c
--- a/drivers/pci/hotplug/pciehprm_acpi.c	2005-03-11 12:51:51 -08:00
+++ b/drivers/pci/hotplug/pciehprm_acpi.c	2005-03-11 12:51:51 -08:00
@@ -254,10 +254,9 @@
 {
 	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);
+	status = acpi_evaluate_object(ab->handle, METHOD_NAME_OSHP, NULL, NULL);
 	if (ACPI_FAILURE(status)) {
 		err("acpi_pciehprm:%s OSHP fails=0x%x\n", path_name, status);
 		oshp_run_status = (status == AE_NOT_FOUND) ? OSHP_NOT_EXIST : OSHP_RUN_FAILED;
diff -Nru a/drivers/pci/hotplug/rpadlpar_core.c b/drivers/pci/hotplug/rpadlpar_core.c
--- a/drivers/pci/hotplug/rpadlpar_core.c	2005-03-11 12:51:47 -08:00
+++ b/drivers/pci/hotplug/rpadlpar_core.c	2005-03-11 12:51:47 -08:00
@@ -142,7 +142,7 @@
 	child = pci_add_new_bus(bridge_dev->bus, bridge_dev, sec_busno);
 	if (!child) {
 		printk(KERN_ERR "%s: could not add secondary bus\n", __FUNCTION__);
-		return 1;
+		return -ENOMEM;
 	}
 
 	sprintf(child->name, "PCI Bus #%02x", child->number);
@@ -204,7 +204,7 @@
 	if (!bridge_dev) {
 		printk(KERN_ERR "%s: unexpected null device\n",
 			__FUNCTION__);
-		return 1;
+		return -EINVAL;
 	}
 
 	secondary_bus = bridge_dev->subordinate;
@@ -212,7 +212,7 @@
 	if (unmap_bus_range(secondary_bus)) {
 		printk(KERN_ERR "%s: failed to unmap bus range\n",
 			__FUNCTION__);
-		return 1;
+		return -ERANGE;
 	}
 
 	pci_remove_bus_device(bridge_dev);
@@ -282,7 +282,7 @@
 	}
 
 	rc = dlpar_remove_root_bus(phb);
-	if (rc)
+	if (rc < 0)
 		return rc;
 
 	return 0;
@@ -294,7 +294,7 @@
 
 	phb = init_phb_dynamic(dn);
 	if (!phb)
-		return 1;
+		return -EINVAL;
 
 	return 0;
 }
diff -Nru a/drivers/pci/hotplug/rpaphp.h b/drivers/pci/hotplug/rpaphp.h
--- a/drivers/pci/hotplug/rpaphp.h	2005-03-11 12:51:42 -08:00
+++ b/drivers/pci/hotplug/rpaphp.h	2005-03-11 12:51:42 -08:00
@@ -45,11 +45,6 @@
 #define LED_ID		2	/* slow blinking */
 #define LED_ACTION	3	/* fast blinking */
 
-/* Error status from rtas_get-sensor */
-#define NEED_POWER    -9000	/* slot must be power up and unisolated to get state */
-#define PWR_ONLY      -9001	/* slot must be powerd up to get state, leave isolated */
-#define ERR_SENSE_USE -9002	/* No DR operation will succeed, slot is unusable  */
-
 /* Sensor values from rtas_get-sensor */
 #define EMPTY           0	/* No card in slot */
 #define PRESENT         1	/* Card in slot */
diff -Nru a/drivers/pci/hotplug/rpaphp_core.c b/drivers/pci/hotplug/rpaphp_core.c
--- a/drivers/pci/hotplug/rpaphp_core.c	2005-03-11 12:51:51 -08:00
+++ b/drivers/pci/hotplug/rpaphp_core.c	2005-03-11 12:51:51 -08:00
@@ -256,12 +256,12 @@
 	my_index = (int *) get_property(dn, "ibm,my-drc-index", NULL);
 	if (!my_index) {
 		/* Node isn't DLPAR/hotplug capable */
-		return 1;
+		return -EINVAL;
 	}
 
 	rc = get_children_props(dn->parent, &indexes, &names, &types, &domains);
 	if (rc < 0) {
-		return 1;
+		return -EINVAL;
 	}
 
 	name_tmp = (char *) &names[1];
@@ -284,7 +284,7 @@
 		type_tmp += (strlen(type_tmp) + 1);
 	}
 
-	return 1;
+	return -EINVAL;
 }
 
 static int is_php_type(char *drc_type)
diff -Nru a/drivers/pci/hotplug/rpaphp_pci.c b/drivers/pci/hotplug/rpaphp_pci.c
--- a/drivers/pci/hotplug/rpaphp_pci.c	2005-03-11 12:51:40 -08:00
+++ b/drivers/pci/hotplug/rpaphp_pci.c	2005-03-11 12:51:40 -08:00
@@ -81,8 +81,8 @@
 
 	rc = rtas_get_sensor(DR_ENTITY_SENSE, slot->index, state);
 
-	if (rc) {
-		if (rc == NEED_POWER || rc == PWR_ONLY) {
+	if (rc < 0) {
+		if (rc == -EFAULT || rc == -EEXIST) {
 			dbg("%s: slot must be power up to get sensor-state\n",
 			    __FUNCTION__);
 
@@ -91,14 +91,14 @@
 			 */
 			rc = rtas_set_power_level(slot->power_domain, POWER_ON,
 						  &setlevel);
-			if (rc) {
+			if (rc < 0) {
 				dbg("%s: power on slot[%s] failed rc=%d.\n",
 				    __FUNCTION__, slot->name, rc);
 			} else {
 				rc = rtas_get_sensor(DR_ENTITY_SENSE,
 						     slot->index, state);
 			}
-		} else if (rc == ERR_SENSE_USE)
+		} else if (rc == -ENODEV)
 			info("%s: slot is unusable\n", __FUNCTION__);
 		else
 			err("%s failed to get sensor state\n", __FUNCTION__);
@@ -413,7 +413,7 @@
 	if (slot->hotplug_slot->info->adapter_status == NOT_VALID) {
 		err("%s: NOT_VALID: skip dn->full_name=%s\n",
 		    __FUNCTION__, slot->dn->full_name);
-		return -1;
+		return -EINVAL;
 	}
 	return 0;
 }
@@ -426,15 +426,15 @@
 
 	dn = slot->dn;
 	if (!dn) {
-		return 1;
+		return -EINVAL;
 	}
 	phb = dn->phb;
 	if (!phb) {
-		return 1;
+		return -EINVAL;
 	}
 	bus = phb->bus;
 	if (!bus) {
-		return 1;
+		return -EINVAL;
 	}
 
 	sprintf(slot->name, "%04x:%02x:%02x.%x", pci_domain_nr(bus),
@@ -448,7 +448,7 @@
 
 	if (slot->type == PHB) {
 		rc = set_phb_slot_name(slot);
-		if (rc) {
+		if (rc < 0) {
 			err("%s: failed to set phb slot name\n", __FUNCTION__);
 			goto exit_rc;
 		}
@@ -509,12 +509,12 @@
 	return 0;
 exit_rc:
 	dealloc_slot_struct(slot);
-	return 1;
+	return -EINVAL;
 }
 
 int register_pci_slot(struct slot *slot)
 {
-	int rc = 1;
+	int rc = -EINVAL;
 
 	slot->dev_type = PCI_DEV;
 	if ((slot->type == EMBEDDED) || (slot->type == PHB))
diff -Nru a/drivers/pci/hotplug/rpaphp_slot.c b/drivers/pci/hotplug/rpaphp_slot.c
--- a/drivers/pci/hotplug/rpaphp_slot.c	2005-03-11 12:51:46 -08:00
+++ b/drivers/pci/hotplug/rpaphp_slot.c	2005-03-11 12:51:46 -08:00
@@ -211,7 +211,7 @@
 	if (is_registered(slot)) { /* should't be here */
 		err("register_slot: slot[%s] is already registered\n", slot->name);
 		rpaphp_release_slot(slot->hotplug_slot);
-		return 1;
+		return -EAGAIN;
 	}	
 	retval = pci_hp_register(slot->hotplug_slot);
 	if (retval) {
@@ -270,7 +270,7 @@
 
 	/* status: LED_OFF or LED_ON */
 	rc = rtas_set_indicator(DR_INDICATOR, slot->index, status);
-	if (rc)
+	if (rc < 0)
 		err("slot(name=%s location=%s index=0x%x) set attention-status(%d) failed! rc=0x%x\n",
 		    slot->name, slot->location, slot->index, status, rc);
 
diff -Nru a/drivers/pci/hotplug/rpaphp_vio.c b/drivers/pci/hotplug/rpaphp_vio.c
--- a/drivers/pci/hotplug/rpaphp_vio.c	2005-03-11 12:51:47 -08:00
+++ b/drivers/pci/hotplug/rpaphp_vio.c	2005-03-11 12:51:47 -08:00
@@ -71,11 +71,11 @@
 {
 	u32 *index;
 	char *name;
-	int rc = 1;
+	int rc = -EINVAL;
 	struct slot *slot = NULL;
 	
 	rc = rpaphp_get_drc_props(dn, NULL, &name, NULL, NULL);
-	if (rc)
+	if (rc < 0)
 		goto exit_rc;
 	index = (u32 *) get_property(dn, "ibm,my-drc-index", NULL);
 	if (!index)
diff -Nru a/drivers/pci/hotplug/shpchprm_acpi.c b/drivers/pci/hotplug/shpchprm_acpi.c
--- a/drivers/pci/hotplug/shpchprm_acpi.c	2005-03-11 12:51:42 -08:00
+++ b/drivers/pci/hotplug/shpchprm_acpi.c	2005-03-11 12:51:42 -08:00
@@ -242,10 +242,9 @@
 {
 	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);
+	status = acpi_evaluate_object(ab->handle, METHOD_NAME_OSHP, NULL, NULL);
 	if (ACPI_FAILURE(status)) {
 		err("acpi_pciehprm:%s OSHP fails=0x%x\n", path_name, status);
 	} else
diff -Nru a/drivers/pci/msi.c b/drivers/pci/msi.c
--- a/drivers/pci/msi.c	2005-03-11 12:51:51 -08:00
+++ b/drivers/pci/msi.c	2005-03-11 12:51:51 -08:00
@@ -20,6 +20,7 @@
 #include <asm/io.h>
 #include <asm/smp.h>
 
+#include "pci.h"
 #include "msi.h"
 
 static DEFINE_SPINLOCK(msi_lock);
@@ -372,6 +373,13 @@
 	if (!status)
 		return status;
 
+	if (pci_msi_quirk) {
+		pci_msi_enable = 0;
+		printk(KERN_WARNING "PCI: MSI quirk detected. MSI disabled.\n");
+		status = -EINVAL;
+		return status;
+	}
+
 	if ((status = msi_cache_init()) < 0) {
 		pci_msi_enable = 0;
 		printk(KERN_WARNING "PCI: MSI cache init failed\n");
@@ -616,15 +624,10 @@
 	bir = (u8)(table_offset & PCI_MSIX_FLAGS_BIRMASK);
 	phys_addr = pci_resource_start (dev, bir);
 	phys_addr += (u32)(table_offset & ~PCI_MSIX_FLAGS_BIRMASK);
-	if (!request_mem_region(phys_addr,
-		nr_entries * PCI_MSIX_ENTRY_SIZE,
-		"MSI-X vector table"))
-		return -ENOMEM;
 	base = ioremap_nocache(phys_addr, nr_entries * PCI_MSIX_ENTRY_SIZE);
-	if (base == NULL) {
-		release_mem_region(phys_addr, nr_entries * PCI_MSIX_ENTRY_SIZE);
+	if (base == NULL)
 		return -ENOMEM;
-	}
+
 	/* MSI-X Table Initialization */
 	for (i = 0; i < nvec; i++) {
 		entry = alloc_msi_entry();
@@ -859,8 +862,6 @@
 			phys_addr += (u32)(table_offset &
 				~PCI_MSIX_FLAGS_BIRMASK);
 			iounmap(base);
-			release_mem_region(phys_addr,
-				nr_entries * PCI_MSIX_ENTRY_SIZE);
 		}
 	}
 
@@ -1133,8 +1134,6 @@
 			phys_addr += (u32)(table_offset &
 				~PCI_MSIX_FLAGS_BIRMASK);
 			iounmap(base);
-			release_mem_region(phys_addr, PCI_MSIX_ENTRY_SIZE *
-				multi_msix_capable(control));
 			printk(KERN_WARNING "PCI: %s: msi_remove_pci_irq_vectors() "
 			       "called without free_irq() on all MSI-X vectors\n",
 			       pci_name(dev));
diff -Nru a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c
--- a/drivers/pci/pci-driver.c	2005-03-11 12:51:47 -08:00
+++ b/drivers/pci/pci-driver.c	2005-03-11 12:51:47 -08:00
@@ -115,7 +115,6 @@
 static inline void
 pci_init_dynids(struct pci_dynids *dynids)
 {
-	memset(dynids, 0, sizeof(*dynids));
 	spin_lock_init(&dynids->lock);
 	INIT_LIST_HEAD(&dynids->list);
 }
diff -Nru a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c
--- a/drivers/pci/pci-sysfs.c	2005-03-11 12:51:46 -08:00
+++ b/drivers/pci/pci-sysfs.c	2005-03-11 12:51:46 -08:00
@@ -481,7 +481,7 @@
 	struct pci_dev *pdev = NULL;
 	
 	sysfs_initialized = 1;
-	while ((pdev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, pdev)) != NULL)
+	while ((pdev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pdev)) != NULL)
 		pci_create_sysfs_dev_files(pdev);
 
 	return 0;
diff -Nru a/drivers/pci/pci.c b/drivers/pci/pci.c
--- a/drivers/pci/pci.c	2005-03-11 12:51:42 -08:00
+++ b/drivers/pci/pci.c	2005-03-11 12:51:42 -08:00
@@ -271,7 +271,7 @@
 	if ((pmc & PCI_PM_CAP_VER_MASK) > 2) {
 		printk(KERN_DEBUG
 		       "PCI: %s has unsupported PM cap regs version (%u)\n",
-		       dev->slot_name, pmc & PCI_PM_CAP_VER_MASK);
+		       pci_name(dev), pmc & PCI_PM_CAP_VER_MASK);
 		return -EIO;
 	}
 
diff -Nru a/drivers/pci/pci.h b/drivers/pci/pci.h
--- a/drivers/pci/pci.h	2005-03-11 12:51:42 -08:00
+++ b/drivers/pci/pci.h	2005-03-11 12:51:42 -08:00
@@ -65,6 +65,7 @@
 extern spinlock_t pci_bus_lock;
 
 extern int pcie_mch_quirk;
+extern int pci_msi_quirk;
 extern struct device_attribute pci_dev_attrs[];
 extern struct class_device_attribute class_device_attr_cpuaffinity;
 
diff -Nru a/drivers/pci/pci.ids b/drivers/pci/pci.ids
--- a/drivers/pci/pci.ids	2005-03-11 12:51:46 -08:00
+++ b/drivers/pci/pci.ids	2005-03-11 12:51:46 -08:00
@@ -7,7 +7,7 @@
 #	so if you have anything to contribute, please visit the home page or
 #	send a diff -u against the most recent pci.ids to pci-ids@ucw.cz.
 #
-#	Daily snapshot on Mon 2004-07-12 10:00:27
+#	Partial sync-up to daily snapshot on Tue 2005-02-08 11:00:09
 #
 
 # Vendors, devices and subsystems. Please keep sorted.
@@ -28,6 +28,9 @@
 	4001  WinTV PVR-250 (v1)
 	4009  WinTV PVR-250
 	4801  WinTV PVR-250 MCE
+0071  Nebula Electronics Ltd.
+0095  Silicon Image, Inc. (Wrong ID)
+	0680  Ultra ATA/133 IDE RAID CONTROLLER CARD
 0100  Ncipher Corp Ltd
 # 018a is not LevelOne but there is a board misprogrammed
 018a  LevelOne
@@ -41,6 +44,11 @@
 # SpeedStream is Efficient Networks, Inc, a Siemens Company
 02ac  SpeedStream
 	1012  1012 PCMCIA 10/100 Ethernet Card [RTL81xx]
+0357  TTTech AG
+	000a  TTP-Monitoring Card V2.0
+0432  SCM Microsystems, Inc.
+05e3  CyberDoor
+	0701  CBD516
 0675  Dynalink
 	1700  IS64PH ISDN Adapter
 	1702  IS64PH ISDN Adapter
@@ -49,6 +57,9 @@
 09c1  Arris
 	0704  CM 200E Cable Modem
 0a89  BREA Technologies Inc
+0b49  ASCII Corporation
+# see http://homepage1.nifty.com/mcn/lab/machines/trance_vibrator/usbview.vib.txt
+	064f  Trance Vibrator
 0e11  Compaq Computer Corporation
 	0001  PCI to EISA Bridge
 	0002  PCI to ISA Bridge
@@ -150,6 +161,8 @@
 		0e11 4082  Smart Array 532
 		0e11 4083  Smart Array 5312
 	b1a4  NC7131 Gigabit Server Adapter
+# HP Memory Hot-Plug Controller
+	b200  Memory Hot-Plug Controller
 	b203  Integrated Lights Out Controller
 	b204  Integrated Lights Out  Processor
 	f130  NetFlex-3/P ThunderLAN 1.0
@@ -169,6 +182,7 @@
 	000a  53c1510
 		1000 1000  LSI53C1510 PCI to Dual Channel Wide Ultra2 SCSI Controller (Nonintelligent mode)
 	000b  53C896/897
+		0e11 6004  EOB003 Series SCSI host adapter
 		1000 1000  LSI53C896/7 PCI to Dual Channel Ultra2 SCSI Multifunction Controller
 		1000 1010  LSI22910 PCI to Dual Channel Ultra2 SCSI host adapter
 		1000 1020  LSI21002 PCI to Dual Channel Ultra2 SCSI host adapter
@@ -191,7 +205,7 @@
 		4c53 1050  CT7 mainboard
 	0010  53C1510
 		0e11 4040  Integrated Array Controller
-		0e11 4048  Integrated Array Controller
+		0e11 4048  RAID LC2 Controller
 		1000 1000  53C1510 PCI to Dual Channel Wide Ultra2 SCSI Controller (Intelligent mode)
 	0012  53c895a
 		1000 1000  LSI53C895A PCI to Ultra2 SCSI Controller
@@ -202,6 +216,7 @@
 		1de1 1020  DC-390U3W
 	0021  53c1010 66MHz  Ultra3 SCSI Adapter
 		1000 1000  LSI53C1000/1000R/1010R/1010-66 PCI to Ultra160 SCSI Controller
+		1000 1010  Asus TR-DLS onboard 53C1010-66
 		124b 1070  PMC-USCSI3
 		4c53 1080  CT8 mainboard
 		4c53 1300  P017 mezzanine (32-bit PMC)
@@ -209,6 +224,7 @@
 	0030  53c1030 PCI-X Fusion-MPT Dual Ultra320 SCSI
 		1028 0123  PowerEdge 2600
 		1028 014a  PowerEdge 1750
+		1028 016c  PowerEdge 1850 MPT Fusion SCSI/RAID (Perc 4)
 		1028 1010  LSI U320 SCSI Controller
 	0031  53c1030ZC PCI-X Fusion-MPT Dual Ultra320 SCSI
 	0032  53c1035 PCI-X Fusion-MPT Dual Ultra320 SCSI
@@ -226,21 +242,23 @@
 		1000 0531  MegaRAID 531 SCSI 320-4X RAID Controller
 		1000 0532  MegaRAID 532 SCSI 320-2X RAID Controller
 		1028 0531  PowerEdge Expandable RAID Controller 4/QC
+		1028 0533  PowerEdge Expandable RAID Controller 4/QC
 		8086 0530  MegaRAID Intel RAID Controller SRCZCRX
 		8086 0532  MegaRAID Intel RAID Controller SRCU42X
 	0408  MegaRAID
 		1000 0001  MegaRAID SCSI 320-1E RAID Controller
 		1000 0002  MegaRAID SCSI 320-2E RAID Controller
-		1028 0001  Dell PowerEdge RAID Controller PERC4e/SC
-		1028 0002  Dell PowerEdge RAID Controller PERC4e/DC
+		1025 004d  MegaRAID ACER ROMB-2E RAID Controller
+		1028 0001  PowerEdge RAID Controller PERC4e/SC
+		1028 0002  PowerEdge RAID Controller PERC4e/DC
 		1734 1065  FSC MegaRAID PCI Express ROMB
 		8086 0002  MegaRAID Intel RAID Controller SRCU42E
 	0409  MegaRAID
 		1000 3004  MegaRAID SATA 300-4X RAID Controller
 		1000 3008  MegaRAID SATA 300-8X RAID Controller
-		8086 3008  MegaRAID Intel RAID Controller SRCS28X
-		8086 3431  MegaRAID Intel RAID Controller Alief SROMBU42E
-		8086 3499  MegaRAID Intel RAID Controller Harwich SROMBU42E
+		8086 3008  MegaRAID RAID Controller SRCS28X
+		8086 3431  MegaRAID RAID Controller Alief SROMBU42E
+		8086 3499  MegaRAID RAID Controller Harwich SROMBU42E
 	0621  FC909 Fibre Channel Adapter
 	0622  FC929 Fibre Channel Adapter
 		1000 1020  44929 O Dual Fibre Channel card
@@ -272,8 +290,8 @@
 		1028 0520  MegaRAID 520 DELL PERC 4/SC RAID Controller
 		1028 0531  PowerEdge Expandable RAID Controller 4/QC
 		1028 0533  PowerEdge Expandable RAID Controller 4/QC
-		8086 0520  MegaRAID Intel RAID Controller SRCU41L
-		8086 0523  MegaRAID Intel RAID Controller SRCS16
+		8086 0520  MegaRAIDRAID Controller SRCU41L
+		8086 0523  MegaRAID RAID Controller SRCS16
 1001  Kolter Electronic
 	0010  PCI 1616 Measurement card with 32 digital I/O lines
 	0011  OPTO-PCI Opto-Isolated digital I/O board
@@ -285,7 +303,13 @@
 	0017  PROTO-3 PCI Prototyping board
 	9100  INI-9100/9100W SCSI Host
 1002  ATI Technologies Inc
+	3150  M24 1P [Radeon Mobility X600]
+	3154  M24 1T [FireGL M24 GL]
+	3e50  RV380 0x3e50 [Radeon X600]
+	3e54  RV380 0x3e54 [FireGL V3200]
+	3e70  RV380 [Radeon X600] Secondary
 	4136  Radeon IGP 320 M
+	4137  Radeon IGP330/340/350
 	4144  R300 AD [Radeon 9500 Pro]
 # New PCI ID provided by ATI developer relations (correction to above)
 	4145  R300 AE [Radeon 9700 Pro]
@@ -294,19 +318,27 @@
 	4147  R300 AG [FireGL Z1/X1]
 	4148  R350 AH [Radeon 9800]
 	4149  R350 AI [Radeon 9800]
-	414b  R350 AK [Fire GL ??]
+	414a  R350 AJ [Radeon 9800]
+	414b  R350 AK [Fire GL X2]
 # New PCI ID provided by ATI developer relations
 	4150  RV350 AP [Radeon 9600]
+		1002 0002  R9600 Pro primary (Asus OEM for HP)
+		1002 0003  R9600 Pro secondary (Asus OEM for HP)
 		1458 4024  Giga-Byte GV-R96128D Primary
 		148c 2064  PowerColor R96A-C3N
 		148c 2066  PowerColor R96A-C3N
 		174b 7c19  Sapphire Atlantis Radeon 9600 Pro
 		174b 7c29  GC-R9600PRO Primary [Sapphire]
+		17ee 2002  Radeon 9600 256Mb Primary
 		18bc 0101  GC-R9600PRO Primary
 # New PCI ID provided by ATI developer relations
 	4151  RV350 AQ [Radeon 9600]
+		1043 c004  A9600SE
 # New PCI ID provided by ATI developer relations
 	4152  RV350 AR [Radeon 9600]
+		1002 0002  Radeon 9600XT
+		1043 c002  Radeon 9600 XT TVD
+	4153  RV350 AS [Radeon 9600 AS]
 	4154  RV350 AT [Fire GL T2]
 	4155  RV350 AU [Fire GL T2]
 	4156  RV350 AV [Fire GL T2]
@@ -325,20 +357,35 @@
 		1458 4025  Giga-Byte GV-R96128D Secondary
 		148c 2067  PowerColor R96A-C3N (Secondary)
 		174b 7c28  GC-R9600PRO Secondary [Sapphire]
+		17ee 2003  Radeon 9600 256Mb Secondary
 		18bc 0100  GC-R9600PRO Secondary
 # New PCI ID provided by ATI developer relations (correction to above)
 	4171  RV350 AQ [Radeon 9600] (Secondary)
+		1043 c005  A9600SE (Secondary)
 # New PCI ID provided by ATI developer relations (correction to above)
 	4172  RV350 AR [Radeon 9600] (Secondary)
+		1002 0003  Radeon 9600XT (Secondary)
+		1043 c003  A9600XT (Secondary)
+	4173  RV350 ?? [Radeon 9550] (Secondary)
+	4237  Radeon 7000 IGP
 	4242  R200 BB [Radeon All in Wonder 8500DV]
 		1002 02aa  Radeon 8500 AIW DV Edition
+	4243  R200 BC [Radeon All in Wonder 8500]
 	4336  Radeon Mobility U1
-	4337  Radeon IGP 340M
+		103c 0024  Pavilion ze4400 builtin Video
+	4337  Radeon IGP 330M/340M/350M
+		1014 053a  ThinkPad R40e (2684-HVG) builtin VGA controller
+		103c 0850  Radeon IGP 345M
 	4341  IXP150 AC'97 Audio Controller
+	4345  EHCI USB Controller
+	4347  OHCI USB Controller #1
+	4348  OHCI USB Controller #2
+	434d  IXP AC'97 Modem
 # Radeon 9100 IGP integrated
 	4353  ATI SMBus
 	4354  215CT [Mach64 CT]
 	4358  210888CX [Mach64 CX]
+	4437  Radeon Mobility 7000 IGP
 	4554  210888ET [Mach64 ET]
 	4654  Mach64 VT
 	4742  3D Rage Pro AGP 1X/2X
@@ -389,6 +436,7 @@
 		1002 8008  Rage XL
 		1028 00ce  PowerEdge 1400
 		1028 00d1  PowerEdge 2550
+		1028 00d9  PowerEdge 2500
 		8086 3411  SDS2 Mainboard
 		8086 3427  S875WP1-E mainboard
 	4753  Rage XC
@@ -406,6 +454,7 @@
 	4758  210888GX [Mach64 GX]
 	4759  3D Rage IIC
 	475a  3D Rage IIC AGP
+		1002 0084  Rage 3D Pro AGP 2x XPERT 98
 		1002 0087  Rage 3D IIC
 		1002 475a  Rage IIC AGP
 	4964  Radeon RV250 Id [Radeon 9000]
@@ -422,6 +471,15 @@
 		17af 2006  RV250 If [Excalibur Radeon 9000]
 	4967  Radeon RV250 Ig [Radeon 9000]
 	496e  Radeon RV250 [Radeon 9000] (Secondary)
+	4a48  R420 JH [Radeon X800]
+	4a49  R420 JI [Radeon X800PRO]
+	4a4a  R420 JJ [Radeon X800SE]
+	4a4b  R420 JK [Radeon X800]
+	4a4c  R420 JL [Radeon X800]
+	4a4d  R420 JM [FireGL X3]
+	4a4e  M18 JN [Radeon Mobility 9800]
+	4a50  R420 JP [Radeon X800XT]
+	4a70  R420 [X800XT-PE] (Secondary)
 	4c42  3D Rage LT Pro AGP-133
 		0e11 b0e7  Rage LT Pro (Compaq Presario 5240)
 		0e11 b0e8  Rage 3D LT Pro
@@ -452,6 +510,7 @@
 		1002 4c50  Rage LT Pro
 	4c51  3D Rage LT Pro
 	4c52  Rage Mobility P/M
+		1033 8112  Versa Note VXi
 	4c53  Rage Mobility L
 	4c54  264LT [Mach64 LT]
 	4c57  Radeon Mobility M7 LW [Radeon Mobility 7500]
@@ -488,9 +547,14 @@
 	4e4b  R350 NK [Fire GL X2]
 # New PCI ID provided by ATI developer relations
 	4e50  RV350 [Mobility Radeon 9600 M10]
-# New PCI ID provided by ATI developer relations
+		1025 005a  TravelMate 290
+		103c 0890  NC6000 laptop
+		1734 1055  Amilo M1420W
+	4e51  M10 NQ [Radeon Mobility 9600]
 	4e52  RV350 [Mobility Radeon 9600 M10]
+	4e53  M10 NS [Radeon Mobility 9600]
 	4e54  M10 NT [FireGL Mobility T2]
+	4e56  M11 NV [FireGL Mobility T2e]
 	4e64  Radeon R300 [Radeon 9700 Pro] (Secondary)
 	4e65  Radeon R300 [Radeon 9500 Pro] (Secondary)
 		1002 0003  Radeon R300 NE [Radeon 9500 Pro]
@@ -568,6 +632,7 @@
 		1002 003a  Radeon R200 QL [Radeon 8500 LE]
 		1002 013a  Radeon 8500
 		148c 2026  R200 QL [Radeon 8500 Evil Master II Multi Display Edition]
+		1681 0010  Radeon 8500 [3D Prophet 8500 128Mb]
 		174b 7149  Radeon R200 QL [Sapphire Radeon 8500 LE]
 	514d  Radeon R200 QM [Radeon 9100]
 	514e  Radeon R200 QN [Radeon 8500LE]
@@ -576,6 +641,7 @@
 	5155  R200 QU [Radeon 9100]
 	5157  Radeon RV200 QW [Radeon 7500]
 		1002 013a  Radeon 7500
+		1002 103a  Dell Optiplex GX260
 		1458 4000  RV200 QW [RADEON 7500 PRO MAYA AR]
 		148c 2024  RV200 QW [Radeon 7500LE Dual Display]
 		148c 2025  RV200 QW [Radeon 7500 Evil Master Multi Display Edition]
@@ -596,6 +662,7 @@
 		148c 2003  RV100 QY [Radeon 7000 Multi-Display Edition]
 		148c 2023  RV100 QY [Radeon 7000 Evil Master Multi-Display]
 		174b 7112  RV100 QY [Sapphire Radeon VE 7000]
+		174b 7c28  Sapphire Radeon VE 7000 DDR
 		1787 0202  RV100 QY [Excalibur Radeon 7000]
 	515a  Radeon RV100 QZ [Radeon 7000/VE]
 	5168  Radeon R200 Qh
@@ -650,29 +717,78 @@
 	5453  Rage 128 Pro Ultra TS
 	5454  Rage 128 Pro Ultra TT
 	5455  Rage 128 Pro Ultra TU
+	5460  M22 [Radeon Mobility M300]
+	5464  M22 [FireGL GL]
+	5548  R423 UH [Radeon X800 (PCIE)]
+	5549  R423 UI [Radeon X800PRO (PCIE)]
+	554a  R423 UJ [Radeon X800LE (PCIE)]
+	554b  R423 UK [Radeon X800SE (PCIE)]
+	5551  R423 UQ [FireGL V7200 (PCIE)]
+	5552  R423 UR [FireGL V5100 (PCIE)]
+	5554  R423 UT [FireGL V7100 (PCIE)]
+	556b  Radeon R423 UK (PCIE) [X800 SE] (Secondary)
 	5654  264VT [Mach64 VT]
 		1002 5654  Mach64VT Reference
 	5655  264VT3 [Mach64 VT3]
 	5656  264VT4 [Mach64 VT4]
+	5830  RS300 Host Bridge
+	5831  RS300 Host Bridge
+	5832  RS300 Host Bridge
+	5833  Radeon 9100 IGP Host Bridge
+	5834  Radeon 9100 IGP
+	5835  RS300M AGP [Radeon Mobility 9100IGP]
+	5838  Radeon 9100 IGP AGP Bridge
 	5941  RV280 [Radeon 9200] (Secondary)
+		174b 7c12  Sapphire Radeon 9200
 # http://www.hightech.com.hk/html/9200.htm
 		17af 200d  Excalibur Radeon 9200
 		18bc 0050  GeXcube GC-R9200-C3 (Secondary)
+	5944  RV280 [Radeon 9200 SE (PCI)]
 	5960  RV280 [Radeon 9200 PRO]
 	5961  RV280 [Radeon 9200]
+		1002 2f72  All-in-Wonder 9200 Series
+		12ab 5961  YUAN SMARTVGA Radeon 9200
+		1458 4018  Gigabyte Radeon 9200
+		174b 7c13  Sapphire Radeon 9200
 # http://www.hightech.com.hk/html/9200.htm
 		17af 200c  Excalibur Radeon 9200
+		18bc 0050  Radeon 9200 Game Buster
 		18bc 0051  GeXcube GC-R9200-C3
+		18bc 0053  Radeon 9200 Game Buster VIVO
+	5962  RV280 [Radeon 9200]
 	5964  RV280 [Radeon 9200 SE]
+		1043 c006  ASUS Radeon 9200 SE / TD / 128M
+		1458 4018  Radeon 9200 SE
 		148c 2073  CN-AG92E
+		174b 7c13  Sapphire Radeon 9200 SE
+		1787 5964  Excalibur 9200SE VIVO 128M
+		17af 2012  Radeon 9200 SE Excalibur
+		18bc 0170  Sapphire Radeon 9200 SE 128MB Game Buster
+# 128MB DDR, DVI/VGA/TV out
+		18bc 0173  GC-R9200L(SE)-C3H [Radeon 9200 Game Buster]
+	5b60  RV370 5B60 [Radeon X300 (PCIE)]
+		1043 002a  EAX300SE
+	5b62  RV370 5B62 [Radeon X600 (PCIE)]
+	5b64  RV370 5B64 [FireGL V3100 (PCIE)]
+	5b65  RV370 5B65 [FireGL D1100 (PCIE)]
 	5c61  RV250 5c61 [Radeon Mobility 9200 M9+]
 	5c63  RV250 5c63 [Radeon Mobility 9200 M9+]
 	5d44  RV280 [Radeon 9200 SE] (Secondary)
+		1458 4019  Radeon 9200 SE (Secondary)
+		174b 7c12  Sapphire Radeon 9200 SE (Secondary)
+		1787 5965  Excalibur 9200SE VIVO 128M (Secondary)
+		17af 2013  Radeon 9200 SE Excalibur (Secondary)
+		18bc 0171  Radeon 9200 SE 128MB Game Buster (Secondary)
+		18bc 0172  GC-R9200L(SE)-C3H [Radeon 9200 Game Buster]
+	5d57  R423 5F57 [Radeon X800XT (PCIE)]
 	700f  PCI Bridge [IGP 320M]
 	7010  PCI Bridge [IGP 340M]
+	7834  Radeon 9100 PRO IGP
+	7835  Radeon Mobility 9200 IGP
 	7c37  RV350 AQ [Radeon 9600 SE]
 	cab0  AGP Bridge [IGP 320M]
 	cab2  RS200/RS200M AGP Bridge [IGP 340M]
+	cbb2  RS200/RS200M AGP Bridge [IGP 340M]
 1003  ULSI Systems
 	0201  US201
 1004  VLSI Technology Inc
@@ -726,6 +842,7 @@
 	0011  NS87560 National PCI System I/O
 	0012  USB Controller
 	0020  DP83815 (MacPhyter) Ethernet Controller
+		103c 0024  Pavilion ze4400 builtin Network
 		1385 f311  FA311 / FA312 (FA311 with WoL HW)
 	0022  DP83820 10/100/1000 Ethernet Controller
 	0028  CS5535 Host bridge
@@ -734,12 +851,16 @@
 	002e  CS5535 Audio
 	002f  CS5535 USB
 	0030  CS5535 Video
+	0035  DP83065 [Saturn] 10/100/1000 Ethernet Controller
 	0500  SCx200 Bridge
 	0501  SCx200 SMI
 	0502  SCx200 IDE
 	0503  SCx200 Audio
 	0504  SCx200 Video
 	0505  SCx200 XBus
+	0510  SC1100 Bridge
+	0511  SC1100 SMI
+	0515  SC1100 XBus
 	d001  87410 IDE
 100c  Tseng Labs Inc
 	3202  ET4000/W32p rev A
@@ -820,6 +941,7 @@
 		1385 2100  FA510
 		1395 0001  10/100 Ethernet CardBus PC Card
 		13d1 ab01  EtherFast 10/100 Cardbus (PCMPC200)
+		14cb 0100  LNDL-100N 100Base-TX Ethernet PC Card
 		8086 0001  EtherExpress PRO/100 Mobile CardBus 32
 	001a  Farallon PN9000SX Gigabit Ethernet
 	0021  DECchip 21052
@@ -915,6 +1037,7 @@
 # AS400 iSeries PCI sync serial card
 		1014 0031  2721 WAN IOA - 2 Port Sync Serial Adapter
 	0036  Miami
+	0037  82660 CPU to PCI Bridge
 	003a  CPU to PCI Bridge
 	003c  GXT250P/GXT255P Graphics Adapter
 	003e  16/4 Token ring UTP/STP controller
@@ -940,6 +1063,7 @@
 	005e  GXT800P Graphics Adapter
 	007c  ATM Controller (14107c00)
 	007d  3780IDSP [MWave]
+	008b  EADS PCI to PCI Bridge
 	008e  GXT3000P Graphics Adapter
 	0090  GXT 3000P
 		1014 008e  GXT-3000P
@@ -953,6 +1077,7 @@
 	00a5  ATM Controller (1410a500)
 	00a6  ATM 155MBPS MM Controller (1410a600)
 	00b7  256-bit Graphics Rasterizer [Fire GL1]
+		1092 00b8  FireGL1 AGP 32Mb
 	00b8  GXT2000P Graphics Adapter
 	00be  ATM 622MBPS Controller (1410be00)
 	00dc  Advanced Systems Management Adapter (ASMA)
@@ -974,6 +1099,7 @@
 		1014 0241  iSeries 2757 DASD IOA
 		1014 0264  Quad Channel PCI-X U320 SCSI RAID Adapter (2780)
 		1014 02BD  Quad Channel PCI-X U320 DDR SCSI RAID Adapter (570F)
+	0188  EADS-X PCI-X to PCI-X Bridge
 	01a7  PCI-X to PCI-X Bridge
 	01bd  ServeRAID Controller
 		1014 01be  ServeRAID-4M
@@ -999,6 +1125,7 @@
 	028C  Citrine chipset SCSI controller
 		1014 02BE  Dual Channel PCI-X U320 DDR SCSI RAID Adapter (571B)
 	0302  X-Architecture Bridge [Summit]
+	0314  ZISC 036 Neural accelerator card
 	ffff  MPIC-2 interrupt controller
 1015  LSI Logic Corp of Canada
 1016  ICL Personal Systems
@@ -1048,10 +1175,10 @@
 1020  Hitachi Computer Products
 1021  OKI Electric Industry Co. Ltd.
 1022  Advanced Micro Devices [AMD]
-	1100  K8 NorthBridge
-	1101  K8 NorthBridge
-	1102  K8 NorthBridge
-	1103  K8 NorthBridge
+	1100  K8 [Athlon64/Opteron] HyperTransport Technology Configuration
+	1101  K8 [Athlon64/Opteron] Address Map
+	1102  K8 [Athlon64/Opteron] DRAM Controller
+	1103  K8 [Athlon64/Opteron] Miscellaneous Control
 	2000  79c970 [PCnet32 LANCE]
 		1014 2000  NetFinity 10/100 Fast Ethernet
 		1022 2000  PCnet - Fast 79C971
@@ -1081,6 +1208,8 @@
 	3000  ELanSC520 Microcontroller
 	7006  AMD-751 [Irongate] System Controller
 	7007  AMD-751 [Irongate] AGP Bridge
+	700a  AMD-IGR4 AGP Host to PCI Bridge
+	700b  AMD-IGR4 PCI to PCI Bridge
 	700c  AMD-760 MP [IGD4-2P] System Controller
 	700d  AMD-760 MP [IGD4-2P] AGP Bridge
 	700e  AMD-760 [IGD4-1P] System Controller
@@ -1209,6 +1338,8 @@
 	1631  M1631 Northbridge+3D Graphics [Aladdin TNT2]
 	1641  M1641 Northbridge [Aladdin-Pro IV]
 	1647  M1647 [MaGiK1] PCI North Bridge
+	1671  M1671 Northbridge [ALADDiN-P4]
+	1672  Northbridge [CyberALADDiN-P4]
 	3141  M3141
 	3143  M3143
 	3145  M3145
@@ -1353,6 +1484,7 @@
 		102b 07c1  Millennium G450 SDR Dual Head LE
 		102b 0d41  Millennium G450 Dual Head PCI
 		102b 0d42  Millennium G450 Dual Head LX PCI
+		102b 0d43  Millennium G450 32Mb Dual Head PCI
 		102b 0e00  Marvel G450 eTV
 		102b 0e01  Marvel G450 eTV
 		102b 0e02  Marvel G450 eTV
@@ -1436,13 +1568,18 @@
 102e  Olivetti Advanced Technology
 102f  Toshiba America
 	0009  r4x00
+	000a  TX3927 MIPS RISC PCI Controller
 	0020  ATM Meteor 155
 		102f 00f8  ATM Meteor 155
+	0030  TC35815CF PCI 10/100 Mbit Ethernet Controller
+	0031  TC35815CF PCI 10/100 Mbit Ethernet Controller with WOL
 	0105  TC86C001 [goku-s] IDE
 	0106  TC86C001 [goku-s] USB 1.1 Host
 	0107  TC86C001 [goku-s] USB Device Controller
 	0108  TC86C001 [goku-s] I2C/SIO/GPIO Controller
-	0180  TX4927
+	0180  TX4927/38 MIPS RISC PCI Controller
+	0181  TX4925 MIPS RISC PCI Controller
+	0182  TX4937 MIPS RISC PCI Controller
 1030  TMC Research
 1031  Miro Computer Products AG
 	5601  DC20 ASIC
@@ -1517,7 +1654,12 @@
 	0006  85C501/2/3
 	0008  SiS85C503/5513 (LPC Bridge)
 	0009  ACPI
+# source: http://members.datafast.net.au/dft0802/downloads/pcidevs.txt
+	0016  SiS961/2 SMBus Controller
 	0018  SiS85C503/5513 (LPC Bridge)
+# Controller for 2 PATA and 2 SATA channels
+	0180  RAID bus controller 180 SATA/PATA  [SiS]
+	0181  SiS SATA
 	0200  5597/5598/6326 VGA
 		1039 0000  SiS5597 SVGA (Shared RAM)
 	0204  82C204
@@ -1557,6 +1699,7 @@
 	0755  755 Host
 	0760  760/M760 Host
 	0900  SiS900 PCI Fast Ethernet
+		1019 0a14  K7S5A motherboard
 		1039 0900  SiS900 10/100 Ethernet Adapter
 		1043 8035  CUSI-FX motherboard
 	0961  SiS961 [MuTIOL Media IO]
@@ -1599,9 +1742,10 @@
 		1092 4910  SpeedStar A70
 		1092 4920  SpeedStar A70
 		1569 6326  SiS6326 GUI Accelerator
-	6330  661FX/M661FX/M661MX/741/M741/760/M760 PCI/AGP
-		1039 6330  [M]661FX/M661MX/[M]741/[M]760 PCI/AGP VGA Display Adapter
+	6330  661/741/760 PCI/AGP VGA Display Adapter
+		1039 6330  [M]661xX/[M]741[GX]/[M]760 PCI/AGP VGA Adapter
 	7001  USB 1.0 Controller
+		1019 0a14  K7S5A motherboard
 		1039 7000  Onboard USB Controller
 	7002  USB 2.0 Controller
 		1509 7002  Onboard USB Controller
@@ -1694,13 +1838,14 @@
 	3000  Samurai_0
 	3010  Samurai_1
 	3020  Samurai_IDE
-1043  Asustek Computer, Inc.
+1043  ASUSTeK Computer Inc.
 	0675  ISDNLink P-IN100-ST-D
 	4015  v7100 SDRAM [GeForce2 MX]
 	4021  v7100 Combo Deluxe [GeForce2 MX + TV tuner]
 	4057  v8200 GeForce 3
 	8043  v8240 PAL 128M [P4T] Motherboard
 	807b  v9280/TD [Geforce4 TI4200 8X With TV-Out and DVI]
+	80bb  v9180 Magic/T [GeForce4 MX440 AGP 8x 64MB TV-out]
 1044  Adaptec (formerly DPT)
 	1012  Domino RAID Engine
 	a400  SmartCache/Raid I-IV Controller
@@ -1769,9 +1914,11 @@
 1046  IPC Corporation, Ltd.
 1047  Genoa Systems Corp
 1048  Elsa AG
+	0c60  Gladiac MX
 	0d22  Quadro4 900XGL [ELSA GLoria4 900XGL]
 	1000  QuickStep 1000
 	3000  QuickStep 3000
+	8901  Gloria XL
 1049  Fountain Technologies, Inc.
 # # nee SGS Thomson Microelectronics
 104a  STMicroelectronics
@@ -1841,15 +1988,19 @@
 	8023  TSB43AB22/A IEEE-1394a-2000 Controller (PHY/Link)
 	8024  TSB43AB23 IEEE-1394a-2000 Controller (PHY/Link)
 	8025  TSB82AA2 IEEE-1394b Link Layer Controller
+		55aa 55aa  FireWire 800 PCI Card
 	8026  TSB43AB21 IEEE-1394a-2000 Controller (PHY/Link)
 	8027  PCI4451 IEEE-1394 Controller
 		1028 00e6  PCI4451 IEEE-1394 Controller (Dell Inspiron 8100)
 	8029  PCI4510 IEEE-1394 Controller
+		1028 0163  Latitude D505
 		1071 8160  MIM2900
 	802e  PCI7x20 1394a-2000 OHCI Two-Port PHY/Link-Layer Controller
+	8201  PCI1620 Firmware Loading Function
 	8400  ACX 100 22Mbps Wireless Interface
 		00fc 16ec  U.S. Robotics 22 Mbps Wireless PC Card (model 2210)
 		00fd 16ec  U.S. Robotics 22Mbps Wireless PCI Adapter (model 2216)
+		1186 3b00  DWL-650+ PC Card cardbus 22Mbs Wireless Adapter [AirPlus]
 		1186 3b01  DWL-520+ 22Mbps PCI Wireless Adapter
 	8401  ACX 100 22Mbps Wireless Interface
 # OK, this info is almost useless as is, but at least it's known that it's a wireless card. More info requested from reporter (whi
@@ -1891,6 +2042,7 @@
 	ac42  PCI4451 PC card Cardbus Controller
 		1028 00e6  PCI4451 PC card CardBus Controller (Dell Inspiron 8100)
 	ac44  PCI4510 PC card Cardbus Controller
+		1028 0163  Latitude D505
 		1071 8160  MIM2000
 	ac46  PCI4520 PC card Cardbus Controller
 	ac50  PCI1410 PC card Cardbus Controller
@@ -1898,20 +2050,23 @@
 		1014 023b  ThinkPad T23 (2647-4MG)
 		1028 00b1  Latitude C600
 		1028 012a  Latitude C640
+		1033 80cd  Versa Note VXi
 		10cf 1095  Lifebook C6155
 		e4bf 1000  CP2-2-HIPHOP
 	ac52  PCI1451 PC card Cardbus Controller
 	ac53  PCI1421 PC card Cardbus Controller
+	ac54  PCI1620 PC Card Controller
 	ac55  PCI1520 PC card Cardbus Controller
 		1014 0512  ThinkPad T30/T40
 	ac56  PCI1510 PC card Cardbus Controller
+		1014 0528  ThinkPad R40e (2684-HVG) Cardbus Controller
 	ac60  PCI2040 PCI to DSP Bridge Controller
 		175c 5100  ASI51xx Audio Adapter
 		175c 6100  ASI61xx Audio Adapter
 		175c 6200  ASI62xx Audio Adapter
 	ac8d  PCI 7620
 	ac8e  PCI7420 CardBus Controller
-	ac8f  PCI7420 Flash Media Controller
+	ac8f  PCI7420/PCI7620 Dual Socket CardBus and Smart Card Cont.
 	fe00  FireWire Host Controller
 	fe03  12C01A FireWire Host Controller
 104d  Sony Corporation
@@ -1937,6 +2092,8 @@
 	0940  W89C940
 	5a5a  W89C940F
 	6692  W6692
+	9921  W99200F MPEG-1 Video Encoder
+	9922  W99200F/W9922PF MPEG-1/2 Video Encoder
 	9970  W9970CF
 1051  Anigma, Inc.
 1052  ?Young Micro Systems
@@ -1975,6 +2132,7 @@
 		175c 4400  ASI4401 Audio Adapter
 		ecc0 0030  Layla
 	18c0  MPC8265A/MPC8266
+	18c1  MPC8271/MPC8272
 	4801  Raven
 	4802  Falcon
 	4803  Hawk
@@ -1998,7 +2156,9 @@
 		14c8 0302  SM56 PCI Fax Modem
 		1668 0300  SM56 PCI Speakerphone Modem
 		1668 0302  SM56 PCI Fax Modem
+	5803  MPC5200
 	6400  MPC190 Security Processor (S1 family, encryption)
+	6405  MPC184 Security Processor (S1 family)
 1058  Electronics & Telecommunications RSH
 1059  Teknor Industrial Computers Inc
 105a  Promise Technology, Inc.
@@ -2018,6 +2178,8 @@
 	3375  PDC20375 (SATA150 TX2plus)
 	3376  PDC20376 (FastTrak 376)
 		1043 809e  A7V8X motherboard
+	3574  PDC20579 SATAII 150 IDE Controller
+	3d18  PDC20518 SATAII 150 IDE Controller
 	4d30  PDC20267 (FastTrak100/Ultra100)
 		105a 4d33  Ultra100
 		105a 4d39  FastTrak100
@@ -2189,8 +2351,16 @@
 	0049  K2 HT-PCI Bridge
 	004b  U3 AGP
 	004c  K2 GMAC (Sun GEM)
+	004f  Shasta Mac I/O
+	0050  Shasta IDE
+	0051  Shasta (Sun GEM)
+	0052  Shasta Firewire
+	0053  Shasta PCI Bridge
+	0054  Shasta PCI Bridge
+	0055  Shasta PCI Bridge
+	0058  U3L AGP Bridge
 	1645  Tigon3 Gigabit Ethernet NIC (BCM5701)
-106c  Hyundai Electronics America
+106c  Hynix Semiconductor
 	8801  Dual Pentium ISA/PCI Motherboard
 	8802  PowerPC ISA/PCI Motherboard
 	8803  Dual Window Graphics Accelerator
@@ -2270,6 +2440,7 @@
 107d  LeadTek Research Inc.
 	0000  P86C850
 	2134  WinFast 3D S320 II
+	2971  [GeForce FX 5900] WinFast A350 TDH MyViVo
 107e  Interphase Corporation
 	0001  5515 ATM Adapter [Flipper]
 	0002  100 VG AnyLan Controller
@@ -2347,6 +2518,7 @@
 	a000  Ultra IIi
 	a001  Ultra IIe
 	a801  Tomatillo PCI Bus Module
+	abba  Cassini 10/100/1000
 108f  Systemsoft
 1090  Encore Computer Corporation
 1091  Intergraph Corporation
@@ -2357,6 +2529,8 @@
 	0060  Proprietary bus bridge
 	00e4  Powerstorm 4D50T
 	0720  Motion JPEG codec
+	07a0  Sun Expert3D-Lite Graphics Accelerator
+	1091  Sun Expert3D Graphics Accelerator
 1092  Diamond Multimedia Systems
 	00a0  Speedstar Pro SE
 	00a8  Speedstar 64
@@ -2386,9 +2560,19 @@
 	1190  PCI-MIO-16E-4
 	1330  PCI-6031E
 	1350  PCI-6071E
+	14e0  PCI-6110
+	14f0  PCI-6111
 	17d0  PCI-6503
+	1870  PCI-6713
+	1880  PCI-6711
+	18b0  PCI-6052E
 	2410  PCI-6733
+	2890  PCI-6036E
 	2a60  PCI-6023E
+	2a70  PCI-6024E
+	2a80  PCI-6025E
+	2c80  PCI-6035E
+	2ca0  PCI-6034E
 	b001  IMAQ-PCI-1408
 	b011  IMAQ-PXI-1408
 	b021  IMAQ-PCI-1424
@@ -2403,13 +2587,13 @@
 	c831  PCI-GPIB bridge
 1094  First International Computers [FIC]
 1095  Silicon Image, Inc. (formerly CMD Technology Inc)
-	0240  Adaptec AAR-1210SA SATA HostRAID
+	0240  Adaptec AAR-1210SA SATA HostRAID Contr.
 	0640  PCI0640
 	0643  PCI0643
 	0646  PCI0646
 	0647  PCI0647
 	0648  PCI0648
-	0649  PCI0649
+	0649  SiI 0649 Ultra ATA-100 Host Controller
 		0e11 005d  Integrated Ultra ATA-100 Dual Channel Controller
 		0e11 007e  Integrated Ultra ATA-100 IDE RAID Controller
 		101e 0649  AMI MegaRAID IDE 100 Controller
@@ -2420,9 +2604,16 @@
 	0680  PCI0680 Ultra ATA-133 Host Controller
 		1095 3680  Winic W-680 (Silicon Image 680 based)
 	3112  SiI 3112 [SATALink/SATARaid] Serial ATA Controller
-		1095 6112  Asus A7N8X
+		1095 3112  SiI 3112 SATALink Controller
+		1095 6112  SiI 3112 SATARaid Controller
 	3114  SiI 3114 [SATALink/SATARaid] Serial ATA Controller
+		1095 3114  SiI 3114 SATALink Controller
+		1095 6114  SiI 3114 SATARaid Controller
+	3124  SiI 3124 PCI-X Serial ATA Controller
+		1095 3124  SiI 3124 PCI-X Serial ATA Controller
 	3512  SiI 3512 [SATALink/SATARaid] Serial ATA Controller
+		1095 3512  SiI 3512 SATALink Controller
+		1095 6512  SiI 3512 SATARaid Controller
 1096  Alacron
 1097  Appian Technology
 1098  Quantum Designs (H.K.) Ltd
@@ -2444,6 +2635,7 @@
 	036e  Bt878 Video Capture
 		0070 13eb  WinTV Series
 		0070 ff01  Viewcast Osprey 200
+		0071 0101  DigiTV PCI
 		107d 6606  WinFast TV 2000
 		11bd 0012  PCTV pro (TV + FM stereo receiver)
 		11bd 001c  PCTV Sat (DBC receiver)
@@ -2454,6 +2646,7 @@
 		144f 3000  MagicTView CPH060 - Video
 		1461 0002  TV98 Series (TV/No FM/Remote)
 		1461 0004  AVerTV WDM Video Capture
+		1461 0761  AverTV DVB-T
 		14f1 0001  Bt878 Mediastream Controller NTSC
 		14f1 0002  Bt878 Mediastream Controller PAL BG
 		14f1 0003  Bt878a Mediastream Controller PAL BG
@@ -2462,6 +2655,7 @@
 		1851 1850  FlyVideo'98 - Video
 		1851 1851  FlyVideo II
 		1852 1852  FlyVideo'98 - Video (with FM Tuner)
+		270f fc00  Digitop DTT-1000
 		bd11 1200  PCTV pro (TV + FM stereo receiver)
 	036f  Bt879 Video Capture
 		127a 0044  Bt879 Video Capture NTSC
@@ -2500,6 +2694,7 @@
 	0878  Bt878 Audio Capture
 		0070 13eb  WinTV Series
 		0070 ff01  Viewcast Osprey 200
+		0071 0101  DigiTV PCI
 		1002 0001  TV-Wonder
 		1002 0003  TV-Wonder/VE
 		11bd 0012  PCTV pro (TV + FM stereo receiver, audio section)
@@ -2511,11 +2706,13 @@
 		13e9 0070  Win/TV (Audio Section)
 		144f 3000  MagicTView CPH060 - Audio
 		1461 0004  AVerTV WDM Audio Capture
+		1461 0761  AVerTV DVB-T
 		14f1 0001  Bt878 Video Capture (Audio Section)
 		14f1 0002  Bt878 Video Capture (Audio Section)
 		14f1 0003  Bt878 Video Capture (Audio Section)
 		14f1 0048  Bt878 Video Capture (Audio Section)
 		1822 0001  VisionPlus DVB Card
+		270f fc00  Digitop DTT-1000
 		bd11 1200  PCTV pro (TV + FM stereo receiver, audio section)
 	0879  Bt879 Audio Capture
 		127a 0044  Bt879 Video Capture (Audio Section)
@@ -2631,12 +2828,15 @@
 		15ed 1003  MCCS 16-port Serial Hot Swap
 	9036  9036
 	9050  PCI <-> IOBus Bridge
+		10b5 1067  IXXAT CAN i165
+		10b5 1172  IK220 (Heidenhain)
 		10b5 2036  SatPak GPS
 		10b5 2221  Alpermann+Velte PCL PCI LV: Timecode Reader Board
 		10b5 2273  SH-ARC SoHard ARCnet card
 		10b5 2431  Alpermann+Velte PCL PCI D: Timecode Reader Board
 		10b5 2905  Alpermann+Velte PCI TS: Time Synchronisation Board
 		10b5 9050  MP9050
+		1498 0362  TPMC866 8 Channel Serial Card
 		1522 0001  RockForce 4 Port V.90 Data/Fax/Voice Modem
 		1522 0002  RockForce 2 Port V.90 Data/Fax/Voice Modem
 		1522 0003  RockForce 6 Port V.90 Data/Fax/Voice Modem
@@ -2689,6 +2889,8 @@
 		125c 0640  Aries 16000P
 	906e  9060ES
 	9080  9080
+		103c 10eb  (Agilent) E2777B 83K Series PCI based Optical Communication Interface
+		103c 10ec  (Agilent) E6978-66442 PCI CIC
 		10b5 9080  9080 [real subsystem ID not set]
 		129d 0002  Aculab PCI Prosidy card
 		12d9 0002  PCI Prosody Card
@@ -2721,6 +2923,8 @@
 	1001  Collage 155 ATM Server Adapter
 10b7  3Com Corporation
 	0001  3c985 1000BaseSX (SX/TX)
+	0013  AR5212 802.11abg NIC (3CRDAG675)
+		10b7 2031  3CRDAG675 11a/b/g Wireless PCI Adapter
 	0910  3C910-A01
 	1006  MINI PCI type 3B Data Fax Modem
 	1007  Mini PCI 56k Winmodem
@@ -2731,6 +2935,7 @@
 		1043 80eb  P4P800 Mainboard
 		10b7 0010  3C940 Gigabit LOM Ethernet Adapter
 		10b7 0020  3C941 Gigabit LOM Ethernet Adapter
+		147b 1407  KV8-MAX3 motherboard
 	3390  3c339 TokenLink Velocity
 	3590  3c359 TokenLink Velocity XL
 		10b7 3590  TokenLink Velocity XL Adapter (3C359/359B)
@@ -2769,6 +2974,7 @@
 	7940  3c803 FDDILink UTP Controller
 	7980  3c804 FDDILink SAS Controller
 	7990  3c805 FDDILink DAS Controller
+	80eb  3c940B 10/100/1000Base-T
 	8811  Token ring
 	9000  3c900 10BaseT [Boomerang]
 	9001  3c900 10Mbps Combo [Boomerang]
@@ -2808,6 +3014,7 @@
 	9200  3c905C-TX/TX-M [Tornado]
 		1028 0095  3C920 Integrated Fast Ethernet Controller
 		1028 0097  3C920 Integrated Fast Ethernet Controller
+		1028 00fe  Optiplex GX240
 		1028 012a  3C920 Integrated Fast Ethernet Controller [Latitude C640]
 		10b7 1000  3C905C-TX Fast Etherlink for PC Management NIC
 		10b7 7000  10/100 Mini PCI Ethernet Adapter
@@ -2820,6 +3027,8 @@
 	9800  3c980-TX Fast Etherlink XL Server Adapter [Cyclone]
 		10b7 9800  3c980-TX Fast Etherlink XL Server Adapter
 	9805  3c980-C 10/100baseTX NIC [Python-T]
+		10b7 1201  EtherLink Server 10/100 Dual Port A
+		10b7 1202  EtherLink Server 10/100 Dual Port B
 		10b7 9805  3c980 10/100baseTX NIC [Python-T]
 		10f1 2462  Thunder K7 S2462
 	9900  3C990-TX [Typhoon]
@@ -2861,8 +3070,11 @@
 	a011  83C170QF
 	b106  SMC34C90
 10b9  ALi Corporation
+	0101  CMI8338/C3DX PCI Audio Device
 	0111  C-Media CMI8738/C3DX Audio Device (OEM)
 		10b9 0111  C-Media CMI8738/C3DX Audio Device (OEM)
+	0780  Multi-IO Card
+	0782  Multi-IO Card
 	1435  M1435
 	1445  M1445
 	1449  M1449
@@ -2878,6 +3090,7 @@
 		10b9 1523  ALI M1523 ISA Bridge
 	1531  M1531 [Aladdin IV]
 	1533  M1533 PCI to ISA Bridge [Aladdin IV]
+		1014 053b  ThinkPad R40e (2684-HVG) PCI to ISA Bridge
 		10b9 1533  ALI M1533 Aladdin IV ISA Bridge
 	1541  M1541
 		10b9 1541  ALI M1541 Aladdin V/V+ AGP System Controller
@@ -2892,8 +3105,10 @@
 	1647  M1647 Northbridge [MAGiK 1 / MobileMAGiK 1]
 	1651  M1651/M1651T Northbridge [Aladdin-Pro 5/5M,Aladdin-Pro 5T/5TM]
 	1671  M1671 Super P4 Northbridge [AGP4X,PCI and SDR/DDR]
+	1672  M1672 Northbridge [CyberALADDiN-P4]
 	1681  M1681 P4 Northbridge [AGP8X,HyperTransport and SDR/DDR]
 	1687  M1687 K8 Northbridge [AGP8X and HyperTransport]
+	1689  M1689 K8 Northbridge [Super K8 Single Chip]
 	3141  M3141
 	3143  M3143
 	3145  M3145
@@ -2910,22 +3125,34 @@
 	5225  M5225
 	5229  M5229 IDE
 		1014 050f  ThinkPad R30
+		1014 053d  ThinkPad R40e (2684-HVG) builtin IDE
+		103c 0024  Pavilion ze4400 builtin IDE
 		1043 8053  A7A266 Motherboard IDE
 	5235  M5225
 	5237  USB 1.1 Controller
+		1014 0540  ThinkPad R40e (2684-HVG) builtin USB
+		103c 0024  Pavilion ze4400 builtin USB
 	5239  USB 2.0 Controller
 	5243  M1541 PCI to AGP Controller
+	5246  AGP8X Controller
 	5247  PCI to AGP Controller
 	5249  M5249 HTT to PCI Bridge
 	5251  M5251 P1394 OHCI 1.0 Controller
 	5253  M5253 P1394 OHCI 1.1 Controller
 	5261  M5261 Ethernet Controller
+	5263  M5263 Ethernet Controller
+	5281  ALi M5281 Serial ATA / RAID Host Controller
 	5450  Lucent Technologies Soft Modem AMR
 	5451  M5451 PCI AC-Link Controller Audio Device
 		1014 0506  ThinkPad R30
+		1014 053e  ThinkPad R40e (2684-HVG) builtin Audio
+		103c 0024  Pavilion ze4400 builtin Audio
+		10b9 5451  HP Compaq nc4010 (DY885AA#ABN)
 	5453  M5453 PCI AC-Link Controller Modem Device
 	5455  M5455 PCI AC-Link Controller Audio Device
 	5457  M5457 AC'97 Modem Controller
+		1014 0535  ThinkPad R40e (2684-HVG) builtin modem
+		103c 0024  Pavilion ze4400 builtin Modem Device
 # Same but more usefull for driver's lookup
 	5459  SmartLink SmartPCI561 56K Modem
 # SmartLink PCI SoftModem
@@ -2934,6 +3161,8 @@
 	5473  M5473 SD-MMC Controller
 	7101  M7101 Power Management Controller [PMU]
 		1014 0510  ThinkPad R30
+		1014 053c  ThinkPad R40e (2684-HVG) Power Management Controller
+		103c 0024  Pavilion ze4400
 10ba  Mitsubishi Electric Corp.
 	0301  AccelGraphics AccelECLIPSE
 	0304  AccelGALAXY A2100 [OEM Evans & Sutherland]
@@ -2990,6 +3219,7 @@
 		0e11 b126  MagicMedia 256AV Audio Device on Durango
 		1014 00dd  MagicMedia 256AV Audio Device on BlackTip Thinkpad
 		1025 1003  MagicMedia 256AV Audio Device on TravelMate 720
+		1028 0088  Latitude CPi A
 		1028 008f  MagicMedia 256AV Audio Device on Colorado Inspiron
 		103c 0007  MagicMedia 256AV Audio Device on Voyager II
 		103c 0008  MagicMedia 256AV Audio Device on Voyager III
@@ -3074,6 +3304,7 @@
 		1043 0205  PCI-V3800
 		1043 4000  AGP-V3800PRO
 		1048 0c21  Synergy II
+		1048 0c31  Erazor III
 		107d 2134  WinFast 3D S320 II + TV-Out
 		1092 4804  Viper V770
 		1092 4a00  Viper V770
@@ -3115,7 +3346,35 @@
 		1554 1041  Pixelview RIVA TNT2 M64
 	002e  NV6 [Vanta]
 	002f  NV6 [Vanta]
-	0041  NV40 OS1RT00B30
+	0034  MCP04 SMBus
+	0035  MCP04 IDE
+	0036  MCP04 Serial ATA Controller
+	0037  MCP04 Ethernet Controller
+	0038  MCP04 Ethernet Controller
+	003a  MCP04 AC'97 Audio Controller
+	003b  MCP04 USB Controller
+	003c  MCP04 USB Controller
+	003d  MCP04 PCI Bridge
+	003e  MCP04 Serial ATA Controller
+	0040  NV40 [GeForce 6800 Ultra]
+	0041  NV40 [GeForce 6800]
+	0042  NV40.2
+	0043  NV40.3
+	0045  NV40 [GeForce 6800 GT]
+	0049  NV40GL
+	004e  NV40GL [Quadro FX 4000]
+	0052  CK804 SMBus
+	0053  CK804 IDE
+	0054  CK804 Serial ATA Controller
+	0055  CK804 Serial ATA Controller
+	0056  CK804 Ethernet Controller
+	0057  CK804 Ethernet Controller
+	0059  CK804 AC'97 Audio Controller
+	005a  CK804 USB Controller
+	005b  CK804 USB Controller
+	005c  CK804 PCI Bridge
+	005d  CK804 PCIE Bridge
+	005e  CK804 Memory Controller
 	0060  nForce2 ISA Bridge
 		1043 80ad  A7N8X Mainboard
 	0064  nForce2 SMBus (MCP)
@@ -3128,14 +3387,30 @@
 		1043 0c11  A7N8X Mainboard
 	006a  nForce2 AC97 Audio Controler (MCP)
 	006b  nForce MultiMedia audio [Via VT82C686B]
+		10de 006b  nForce2 MCP Audio Processing Unit
 	006c  nForce2 External PCI Bridge
 	006d  nForce2 PCI Bridge
 	006e  nForce2 FireWire (IEEE 1394) Controller
+	0084  MCP2A SMBus
+	0085  MCP2A IDE
+	0086  MCP2A Ethernet Controller
+	0087  MCP2A USB Controller
+	0088  MCP2A USB Controller
+	008a  MCP2S AC'97 Audio Controller
+	008b  MCP2A PCI Bridge
+	008c  MCP2A Ethernet Controller
+	008e  nForce2 Serial ATA Controller
 	00a0  NV5 [Aladdin TNT2]
 		14af 5810  Maxi Gamer Xentor
+	00c0  NV41.0
+	00c1  NV41.1
+	00c2  NV41.2
+	00c8  NV41.8
+	00ce  NV41GL
 	00d0  nForce3 LPC Bridge
 	00d1  nForce3 Host Bridge
 	00d2  nForce3 AGP Bridge
+	00d3  CK804 Memory Controller
 	00d4  nForce3 SMBus
 	00d5  nForce3 IDE
 	00d6  nForce3 Ethernet
@@ -3143,6 +3418,29 @@
 	00d8  nForce3 USB 2.0
 	00da  nForce3 Audio
 	00dd  nForce3 PCI Bridge
+	00df  CK8S Ethernet Controller
+	00e1  nForce3 250Gb Host Bridge
+	00e2  nForce3 250Gb AGP Host to PCI Bridge
+	00e3  CK8S Serial ATA Controller (v2.5)
+	00e4  nForce 250Gb PCI System Management
+	00e5  CK8S Parallel ATA Controller (v2.5)
+	00e6  CK8S Ethernet Controller
+	00e7  CK8S USB Controller
+	00e8  CK8S USB Controller
+	00ea  nForce3 250Gb AC'97 Audio Controller
+	00ed  nForce3 250Gb PCI-to-PCI Bridge
+	00ee  CK8S Serial ATA Controller (v2.5)
+	00f0  NV40 [GeForce 6800/GeForce 6800 Ultra]
+	00f1  NV43 [GeForce 6600/GeForce 6600 GT]
+	00f2  NV43 [GeForce 6600 GT]
+	00f8  NV45GL [Quadro FX 3400]
+	00f9  NV40 [GeForce 6800 Ultra]
+	00fa  NV36 [GeForce PCX 5750]
+	00fb  NV35 [GeForce PCX 5900]
+	00fc  NV37GL [Quadro FX 330/GeForce PCX 5300]
+	00fd  NV37GL [Quadro FX 330]
+	00fe  NV38GL [Quadro FX 1300]
+	00ff  NV18 [GeForce PCX 4300]
 	0100  NV10 [GeForce 256 SDR]
 		1043 0200  AGP-V6600 SGRAM
 		1043 0201  AGP-V6600 SDRAM
@@ -3161,6 +3459,7 @@
 	0110  NV11 [GeForce2 MX/MX 400]
 		1043 4015  AGP-V7100 Pro
 		1043 4031  V7100 Pro with TV output
+		10de 0091  Dell OEM GeForce 2 MX 400
 		1462 8817  MSI GeForce2 MX400 Pro32S [MS-8817]
 		14af 7102  3D Prophet II MX
 		14af 7103  3D Prophet II MX Dual-Display
@@ -3197,6 +3496,7 @@
 	017a  NV17GL [Quadro4 200/400 NVS]
 	017b  NV17GL [Quadro4 550 XGL]
 	017c  NV17GL [Quadro4 550 GoGL]
+	017d  NV17 [GeForce4 410 Go 16M]
 	0181  NV18 [GeForce4 MX 440 AGP 8x]
 		1043 806f  V9180 Magic
 		1462 8880  MS-StarForce GeForce4 MX 440 with AGP8X
@@ -3206,14 +3506,18 @@
 	0182  NV18 [GeForce4 MX 440SE AGP 8x]
 	0183  NV18 [GeForce4 MX 420 AGP 8x]
 	0185  NV18 [GeForce4 MX 4000 AGP 8x]
+	0186  NV18M [GeForce4 448 Go]
+	0187  NV18M [GeForce4 488 Go]
 	0188  NV18GL [Quadro4 580 XGL]
 	018a  NV18GL [Quadro4 NVS AGP 8x]
 	018b  NV18GL [Quadro4 380 XGL]
+	018d  NV18M [GeForce4 448 Go]
 	01a0  NVCrush11 [GeForce2 MX Integrated Graphics]
 	01a4  nForce CPU bridge
 	01ab  nForce 420 Memory Controller (DDR)
 	01ac  nForce 220/420 Memory Controller
 	01ad  nForce 220/420 Memory Controller
+	01b0  nForce Audio
 	01b1  nForce Audio
 	01b2  nForce ISA Bridge
 	01b4  nForce PCI System Management
@@ -3241,6 +3545,7 @@
 	0203  NV20DCC [Quadro DCC]
 	0250  NV25 [GeForce4 Ti 4600]
 	0251  NV25 [GeForce4 Ti 4400]
+		1043 8023  v8440 GeForce 4 Ti4400
 	0252  NV25 [GeForce4 Ti]
 	0253  NV25 [GeForce4 Ti 4200]
 		107d 2896  WinFast A250 LE TD (Dual VGA/TV-out/DVI)
@@ -3254,6 +3559,7 @@
 	0286  NV28 [GeForce4 Ti 4200 Go AGP 8x]
 	0288  NV28GL [Quadro4 980 XGL]
 	0289  NV28GL [Quadro4 780 XGL]
+	028c  NV28GLM [Quadro4 700 GoGL]
 	0300  NV30 [GeForce FX]
 	0301  NV30 [GeForce FX 5800 Ultra]
 	0302  NV30 [GeForce FX 5800]
@@ -3261,32 +3567,66 @@
 	0309  NV30GL [Quadro FX 1000]
 	0311  NV31 [GeForce FX 5600 Ultra]
 	0312  NV31 [GeForce FX 5600]
+	0313  NV31
 	0314  NV31 [GeForce FX 5600XT]
+		1043 814a  V9560XT/TD
+	0316  NV31
+	0317  NV31
 	031a  NV31M [GeForce FX Go 5600]
+	031b  NV31M [GeForce FX Go5650]
 	031c  NVIDIA Quadro FX 700 Go
+	031d  NV31
+	031e  NV31
+	031f  NV31
+	0320  NV34 [GeForce FX 5200]
 	0321  NV34 [GeForce FX 5200 Ultra]
 	0322  NV34 [GeForce FX 5200]
 		1462 9171  MS-8917 (FX5200-T128)
+	0323  NV34 [GeForce FX 5200LE]
 	0324  NV34M [GeForce FX Go 5200]
 		1071 8160  MIM2000
+	0325  NV34M [GeForce FX Go5250]
+	0326  NV34 [GeForce FX 5500]
+	0327  NV34 [GeForce FX 5100]
 	0328  NV34M [GeForce FX Go 5200]
 	0329  NV34M [GeForce FX Go5200]
-	032b  NV34GL [Quadro FX 500]
+	032a  NV34GL [Quadro NVS 280 PCI]
+	032b  NV34GL [Quadro FX 500/600 PCI]
 	032c  NV34GLM [GeForce FX Go 5300]
+	032d  NV34 [GeForce FX Go5100]
+	032f  NV34
 	0330  NV35 [GeForce FX 5900 Ultra]
 	0331  NV35 [GeForce FX 5900]
+		1043 8145  V9950GE
 	0332  NV35 [GeForce FX 5900XT]
 	0333  NV38 [GeForce FX 5950 Ultra]
+	0334  NV35 [GeForce FX 5900ZT]
 	0338  NV35GL [Quadro FX 3000]
-	0341  NV 36 [GeForce 5700 Ultra]
-	0342  NV 36 [GeForce 5700]
+	033f  NV35GL [Quadro FX 700]
+	0341  NV36.1 [GeForce FX 5700 Ultra]
+	0342  NV36.2 [GeForce FX 5700]
+	0343  NV36 [GeForce FX 5700LE]
+	0344  NV36.4 [GeForce FX 5700VE]
+	0345  NV36.5
+	0347  NV36 [GeForce FX Go5700]
+	0348  NV36 [GeForce FX Go5700]
+	0349  NV36
+	034b  NV36
+	034c  NV36 [Quadro FX Go1000]
+	034e  NV36GL [Quadro FX 1100]
+	034f  NV36GL
 10df  Emulex Corporation
 	1ae5  LP6000 Fibre Channel Host Adapter
 	1ae6  LP 8000 Fibre Channel Host Adapter Alternate ID (JX1:2-3, JX2:1-2)
 	1ae7  LP 8000 Fibre Channel Host Adapter Alternate ID (JX1:2-3, JX2:2-3)
+	f015  LP1150e
 	f085  LP850 Fibre Channel Adapter
 	f095  LP952 Fibre Channel Adapter
 	f098  LP982 Fibre Channel Adapter
+	f0a1  LightPulse Fibre Channel Adapter
+	f0a5  LP1050
+	f0d5  LP1150
+	f100  LP11000e
 	f700  LP7000 Fibre Channel Host Adapter
 	f701  LP 7000EFibre Channel Host Adapter Alternate ID (JX1:2-3, JX2:1-2)
 	f800  LP8000 Fibre Channel Host Adapter
@@ -3297,6 +3637,9 @@
 	f981  LP 9802 Fibre Channel Host Adapter Alternate ID
 	f982  LP 9802 Fibre Channel Host Adapter Alternate ID
 	fa00  LP10000 Fibre Channel Host Adapter
+	fa01  LP101
+	fb00  LightPulse Fibre Channel Adapter
+	fd00  LP11000
 10e0  Integrated Micro Solutions Inc.
 	5026  IMS5026/27/28
 	5027  IMS5027
@@ -3314,6 +3657,8 @@
 	0000  CA91C042 [Universe]
 	0860  CA91C860 [QSpan]
 	0862  CA91C862A [QSpan-II]
+	8260  CA91L8200B [Dual PCI PowerSpan II]
+	8261  CA91L8260B [Single PCI PowerSpan II]
 10e4  Tandem Computers
 10e5  Micro Industries Corporation
 10e6  Gainbery Computer Products Inc.
@@ -3333,8 +3678,18 @@
 	80d9  PCI-9118
 	80da  PCI-9812
 	811a  PCI-IEEE1355-DS-DE Interface
+	814c  Fastcom ESCC-PCI (Commtech, Inc.)
 	8170  S5933 [Matchmaker] (Chipset Development Tool)
+# sold with Roper Scientifc(Photometrics) CoolSnap HQ camera
+	81e6  Multimedia video controller
+	8291  Fastcom 232/8-PCI (Commtech, Inc.)
+	82c4  Fastcom 422/4-PCI (Commtech, Inc.)
+	82c5  Fastcom 422/2-PCI (Commtech, Inc.)
+	82c6  Fastcom IG422/1-PCI (Commtech, Inc.)
+	82c7  Fastcom IG232/2-PCI (Commtech, Inc.)
+	82ca  Fastcom 232/4-PCI (Commtech, Inc.)
 	82db  AJA HDNTV HD SDI Framestore
+	82e2  Fastcom DIO24H-PCI (Commtech, Inc.)
 	8851  S5933 on Innes Corp FM Radio Capture card
 10e9  Alps Electric Co., Ltd.
 10ea  Intergraphics Systems
@@ -3363,6 +3718,8 @@
 	8138  RT8139 (B/C) Cardbus Fast Ethernet Adapter
 		10ec 8138  RT8139 (B/C) Fast Ethernet Adapter
 	8139  RTL-8139/8139C/8139C+
+		0357 000a  TTP-Monitoring Card V2.0
+		1025 005a  TravelMate 290
 		1025 8920  ALN-325
 		1025 8921  ALN-325
 		1071 8160  MIM2000
@@ -3378,19 +3735,23 @@
 		1429 d010  ND010
 		1432 9130  EN-9130TX
 		1436 8139  RT8139
-		1458 e000  GA-7VM400M Motherboard
+		1458 e000  GA-7VM400M/7VT600 Motherboard
 		146c 1439  FE-1439TX
 		1489 6001  GF100TXRII
 		1489 6002  GF100TXRA
 		149c 139a  LFE-8139ATX
 		149c 8139  LFE-8139TX
+		14cb 0200  LNR-100 Family 10/100 Base-TX Ethernet
 		1799 5000  F5D5000 PCI Card/Desktop Network PCI Card
 		2646 0001  EtheRx
 		8e2e 7000  KF-230TX
 		8e2e 7100  KF-230TX/2
 		a0a0 0007  ALN-325C
 	8169  RTL-8169 Gigabit Ethernet
+		1259 c107  CG-LAPCIGT
 		1371 434e  ProG-2000L
+		1458 e000  GA-K8VT800 Pro Motherboard
+		1462 702c  K8T NEO 2 motherboard
 	8180  RTL8180L 802.11b MAC
 	8197  SmartLAN56 56K Modem
 10ed  Ascii Corporation
@@ -3455,6 +3816,7 @@
 		1102 8061  SBLive! Player 5.1
 		1102 8064  SB Live! 5.1 Model SB0100
 		1102 8065  SBLive! 5.1 Digital Model SB0220
+		1102 8067  SBLive! 5.1 eMicro 28028
 	0004  SB Audigy
 		1102 0051  SB0090 Audigy Player
 		1102 0053  SB0090 Audigy Player/OEM
@@ -3462,6 +3824,9 @@
 		1102 2002  SB Audigy 2 ZS (SB0350)
 	0006  [SB Live! Value] EMU10k1X
 	0007  SB Audigy LS
+		1102 1001  SB0310 Audigy LS
+		1102 1002  SB0312 Audigy LS
+	0008  SB0400 Audigy2 Value
 	4001  SB Audigy FireWire Port
 		1102 0010  SB Audigy FireWire Port
 	7002  SB Live! MIDI/Game Port
@@ -3470,6 +3835,8 @@
 		1102 0040  SB Audigy MIDI/Game Port
 	7004  [SB Live! Value] Input device controller
 	7005  SB Audigy LS MIDI/Game port
+		1102 1001  SB0310 Audigy LS MIDI/Game port
+		1102 1002  SB0312 Audigy LS MIDI/Game port
 	8064  SB0100 [SBLive! 5.1 OEM]
 	8938  Ectiva EV1938
 1103  Triones Technologies, Inc.
@@ -3477,7 +3844,12 @@
 # Revisions: 01=HPT366, 03=HPT370, 04=HPT370A, 05=HPT372
 	0004  HPT366/368/370/370A/372
 		1103 0001  HPT370A
+		1103 0003  HPT343 / HPT345 / HPT363 UDMA33
+		1103 0004  HPT366 UDMA66 (r1) / HPT368 UDMA66 (r2) / HPT370 UDMA100 (r3) / HPT370 UDMA100 RAID (r4)
 		1103 0005  HPT370 UDMA100
+		1103 0006  HPT302
+		1103 0007  HPT371 UDMA133
+		1103 0008  HPT374 UDMA/ATA133 RAID Controller
 	0005  HPT372A
 	0006  HPT302
 	0007  HPT371
@@ -3519,6 +3891,9 @@
 		1179 0001  Magnia Z310
 		1297 f641  FX41 motherboard
 		1458 5002  GA-7VAX Mainboard
+		1462 7020  K8T NEO 2 motherboard
+		147b 1407  KV8-MAX3 motherboard
+		1849 0571  K7VT2 motherboard
 	0576  VT82C576 3V [Apollo Master]
 	0585  VT82C585VP [Apollo VP1/VPX]
 	0586  VT82C586/A/B PCI-to-ISA [Apollo VP]
@@ -3555,6 +3930,7 @@
 	1106  VT82C570MV
 	1571  VT82C576M/VT82C586
 	1595  VT82C595/97 [Apollo VP2/97]
+	3022  CLE266
 # This is *not* USB 2.0 as the existing entry suggests
 	3038  VT82xxxxx UHCI USB 1.1 Controller
 		0925 1234  USB Controller
@@ -3565,12 +3941,17 @@
 		1043 80ed  A7V600 motherboard
 		1179 0001  Magnia Z310
 		1458 5004  GA-7VAX Mainboard
+		1462 7020  K8T NEO 2 motherboard
+		147b 1407  KV8-MAX3 motherboard
 	3040  VT82C586B ACPI
 	3043  VT86C100A [Rhine]
 		10bd 0000  VT86C100A Fast Ethernet Adapter
 		1106 0100  VT86C100A Fast Ethernet Adapter
 		1186 1400  DFE-530TX rev A
 	3044  IEEE 1394 Host Controller
+		1025 005a  TravelMate 290
+		1458 1000  GA-7VT600-1394 Motherboard
+		1462 702d  K8T NEO 2 motherboard
 	3050  VT82C596 Power Management
 	3051  VT82C596 Power Management
 	3053  VT6105M [Rhine-III]
@@ -3597,16 +3978,20 @@
 		1043 80a1  A7V8X-X Motherboard
 		1043 80b0  A7V600 motherboard (ADI AD1980 codec [SoundMAX])
 		1106 3059  L7VMM2 Motherboard
+		1106 4161  K7VT2 motherboard
 		1297 c160  FX41 motherboard (Realtek ALC650 codec)
 		1458 a002  GA-7VAX Onboard Audio (Realtek ALC650)
+		1462 0080  K8T NEO 2 motherboard
 		1462 3800  KT266 onboard audio
+		147b 1407  KV8-MAX3 motherboard
 	3065  VT6102 [Rhine-II]
 		1043 80a1  A7V8X-X Motherboard
 		1106 0102  VT6102 [Rhine II] Embeded Ethernet Controller on VT8235
 		1186 1400  DFE-530TX rev A
 		1186 1401  DFE-530TX rev B
 		13b9 1421  LD-10/100AL PCI Fast Ethernet Adapter (rev.B)
-	3068  Intel 537 [AC97 Modem]
+# This hosts more than just the Intel 537 codec, it also hosts PCtel (SIL33) and SmartLink (SIL34) codecs
+	3068  AC'97 Modem Controller
 		1462 309e  MS-6309 Saturn Motherboard
 	3074  VT8233 PCI to ISA Bridge
 		1043 8052  VT8233A
@@ -3614,6 +3999,7 @@
 	3099  VT8366/A/7 [Apollo KT266/A/333]
 		1043 8064  A7V266-E Mainboard
 		1043 807f  A7V333 Mainboard
+		1849 3099  K7VT2 motherboard
 	3101  VT8653 Host Bridge
 	3102  VT8662 Host Bridge
 	3103  VT8615 Host Bridge
@@ -3624,12 +4010,17 @@
 		1043 80ed  A7V600 motherboard
 		1297 f641  FX41 motherboard
 		1458 5004  GA-7VAX Mainboard
+		1462 7020  K8T NEO 2 motherboard
+		147b 1407  KV8-MAX3 motherboard
 	3106  VT6105 [Rhine-III]
 		1186 1403  DFE-530TX rev C
+	3108  S3 Unichrome Pro VGA Adapter
 	3109  VT8233C PCI to ISA Bridge
 	3112  VT8361 [KLE133] Host Bridge
 	3116  VT8375 [KM266/KL266] Host Bridge
 		1297 f641  FX41 motherboard
+	3118  S3 Unichrome Pro VGA Adapter
+	3119  VT6120/VT6121/VT6122 Gigabit Ethernet Adapter
 # found on EPIA M6000/9000 mainboard
 	3122  VT8623 [Apollo CLE266] integrated CastleRock graphics
 # found on EPIA M6000/9000 mainboard
@@ -3640,6 +4031,7 @@
 	3148  P4M266 Host Bridge
 	3149  VIA VT6420 SATA RAID Controller
 		1043 80ed  A7V600 motherboard
+		1458 b003  GA-7VM400AM(F) Motherboard
 		1462 7020  MSI Neo K8T FIS2R mainboard
 	3156  P/KN266 Host Bridge
 # on ASUS P4P800
@@ -3651,20 +4043,27 @@
 		1043 80a1  A7V8X-X motherboard
 		1297 f641  FX41 motherboard
 		1458 5001  GA-7VAX Mainboard
+		1849 3177  K7VT2 motherboard
 	3188  VT8385 [K8T800 AGP] Host Bridge
+		147b 1407  KV8-MAX3 motherboard
 	3189  VT8377 [KT400/KT600 AGP] Host Bridge
 		1043 807f  A7V8X motherboard
 		1458 5000  GA-7VAX Mainboard
-# Updated the entry to the proper "chip [name] desc" format
-	3205  VT8378 [KM400] Chipset Host Bridge
+	3204  K8M800
+	3205  VT8378 [KM400/A] Chipset Host Bridge
 		1458 5000  GA-7VM400M Motherboard
-	3227  VT8237 ISA bridge [K8T800 South]
+	3227  VT8237 ISA bridge [KT600/K8T800 South]
 		1043 80ed  A7V600 motherboard
+		1106 3227  DFI KT600-AL Motherboard
+		1458 5001  GA-7VT600 Motherboard
+		147b 1407  KV8-MAX3 motherboard
+	4149  VIA VT6420 (ATA133) Controller
 	5030  VT82C596 ACPI [Apollo PRO]
 	6100  VT85C100A [Rhine II]
+	7204  K8M800
 # S3 Graphics UniChromeâ„¢ 2D/3D Graphics with motion compensation
 	7205  VT8378 [S3 UniChrome] Integrated Video
-		1458 d000  GA-7VM400M Motherboard
+		1458 d000  Gigabyte GA-7VM400(A)M(F) Motherboard
 	8231  VT8231 [PCI-to-ISA Bridge]
 	8235  VT8235 ACPI
 	8305  VT8363/8365 [KT133/KM133 AGP]
@@ -3686,6 +4085,7 @@
 	b112  VT8361 [KLE133] AGP Bridge
 	b168  VT8235 PCI Bridge
 	b188  VT8237 PCI bridge [K8T800 South]
+		147b 1407  KV8-MAX3 motherboard
 	b198  VT8237 PCI Bridge
 # 32-Bit PCI bus master Ethernet MAC with standard MII interface
 	d104  VT8237 Integrated Fast Ethernet Controller
@@ -3711,9 +4111,12 @@
 	007b  FSC Remote Service Controller, mailbox device
 	007c  FSC Remote Service Controller, shared memory device
 	007d  FSC Remote Service Controller, SMIC device
-	2102  DSCC4 WAN adapter
+# Superfastcom-PCI (Commtech, Inc.) or DSCC4 WAN Adapter
+	2102  DSCC4 PEB/PEF 20534 DMA Supported Serial Communication Contr.
 	2104  Eicon Diva 2.02 compatible passive ISDN card
+	3142  SIMATIC NET CP 5613A1 (Profibus Adapter)
 	4021  SIMATIC NET CP 5512 (Profibus and MPI Cardbus Adapter)
+	4029  SIMATIC NET CP 5613A2 (Profibus Adapter)
 	4942  FPGA I-Bus Tracer for MBD
 	6120  SZB6120
 110b  Chromatic Research Inc.
@@ -3745,6 +4148,8 @@
 	9211  EN-1207D Fast Ethernet Adapter
 		1113 9211  EN-1207D Fast Ethernet Adapter
 	9511  21x4x DEC-Tulip compatible Fast Ethernet
+	d301  CPWNA100 (Philips wireless PCMCIA)
+	ec02  SMC 1244TX v3
 1114  Atmel Corporation
 	0506  802.11b Wireless Network Adaptor (at76c506)
 1115  3D Labs
@@ -3854,9 +4259,11 @@
 111b  Teledyne Electronic Systems
 111c  Tricord Systems Inc.
 	0001  Powerbis Bridge
-111d  Integrated Device Tech
-	0001  IDT77211 ATM Adapter
-	0003  IDT77252 ATM network controller
+111d  Integrated Device Technology, Inc.
+	0001  IDT77201/77211 155Mbps ATM SAR Controller [NICStAR]
+	0003  IDT77222/77252 155Mbps ATM MICRO ABR SAR Controller
+	0004  IDT77V252 155Mbps ATM MICRO ABR SAR Controller
+	0005  IDT77V222 155Mbps ATM MICRO ABR SAR Controller
 111e  Eldec
 111f  Precision Digital Images
 	4a47  Precision MX Video engine interface
@@ -3890,10 +4297,13 @@
 	1561  USB 1.1 Host Controller
 	1562  USB 2.0 Host Controller
 	3400  SmartPCI56(UCB1500) 56K Modem
+	5400  TriMedia TM1000/1100
+	5402  TriMedia TM-1300
 	7130  SAA7130 Video Broadcast Decoder
 		5168 0138  LiveView FlyVideo 2000
-	7133  SAA7133 Audio+video broadcast decoder
+	7133  SAA713X Audio+video broadcast decoder
 		5168 0138  LifeView FlyVideo 3000
+		5168 0212  LifeView FlyTV Platinum mini
 # PCI audio and video broadcast decoder (http://www.semiconductors.philips.com/pip/saa7134hl)
 	7134  SAA7134
 	7135  SAA7135 Audio+video broadcast decoder
@@ -3906,7 +4316,7 @@
 		114b 2003  DVRaptor Video Edit/Capture Card
 		11bd 0006  DV500 Overlay
 		11bd 000a  DV500 Overlay
-		13c2 0000  Siemens/Technotrend/Hauppauge DVB card rev1.3
+		13c2 0000  Siemens/Technotrend/Hauppauge DVB card rev1.3 or rev1.5
 		13c2 0001  Technotrend/Hauppauge DVB card rev1.3 or rev1.6
 		13c2 0002  Technotrend/Hauppauge DVB card rev2.1
 		13c2 0003  Technotrend/Hauppauge DVB card rev2.1
@@ -3998,9 +4408,14 @@
 		1133 2002  Diva Server 4PRI/E1-120
 		1133 2003  Diva Server 4PRI/T1-96
 	e024  Diva Server Analog-4P
+		1133 2400  Diva Server V-Analog-4P
+		1133 e024  Diva Server Analog-4P
 	e028  Diva Server Analog-8P
+		1133 2800  Diva Server V-Analog-8P
+		1133 e028  Diva Server Analog-8P
 1134  Mercury Computer Systems
 	0001  Raceway Bridge
+	0002  Dual PCI to RapidIO Bridge
 1135  Fuji Xerox Co Ltd
 	0001  Printer controller
 1136  Momentum Data Systems
@@ -4048,7 +4463,8 @@
 	f015  NinjaSCSI-32 Melco
 1146  Force Computers
 1147  Interface Corp
-1148  Syskonnect (Schneider & Koch)
+# Formerly (Schneider & Koch)
+1148  SysKonnect
 	4000  FDDI Adapter
 		0e11 b03b  Netelligent 100 FDDI DAS Fibre SC
 		0e11 b03c  Netelligent 100 FDDI SAS Fibre SC
@@ -4106,6 +4522,14 @@
 		1148 9521  SK-9521 10/100/1000Base-T Adapter
 	4400  SK-9Dxx Gigabit Ethernet Adapter
 	4500  SK-9Mxx Gigabit Ethernet Adapter
+	9e00  SK-9Exx 10/100/1000Base-T Adapter
+		1148 2100  SK-9E21 Server Adapter
+		1148 21d0  SK-9E21D 10/100/1000Base-T Adapter
+		1148 2200  SK-9E22 Server Adapter
+		1148 8100  SK-9E81 Server Adapter
+		1148 8200  SK-9E82 Server Adapter
+		1148 9100  SK-9E91 Server Adapter
+		1148 9200  SK-9E92 Server Adapter
 1149  Win System Corporation
 114a  VMIC
 	5579  VMIPCI-5579 (Reflective Memory Card)
@@ -4259,6 +4683,7 @@
 	0212  CSB5 IDE Controller
 		4c53 1080  CT8 mainboard
 	0213  CSB6 RAID/IDE Controller
+	0217  CSB6 IDE Controller
 	0220  OSB4/CSB5 OHCI USB Controller
 		4c53 1080  CT8 mainboard
 	0221  CSB6 OHCI USB Controller
@@ -4268,6 +4693,7 @@
 	0227  GCLE-2 Host Bridge
 	0230  CSB5 LPC bridge
 		4c53 1080  CT8 mainboard
+	0240  K2 SATA
 1167  Mutoh Industries Inc
 1168  Thine Electronics Inc
 1169  Centre for Development of Advanced Computing
@@ -4300,7 +4726,7 @@
 	0603  ToPIC95 PCI to CardBus Bridge for Notebooks
 	060a  ToPIC95
 	060f  ToPIC97
-	0617  ToPIC95 PCI to Cardbus Bridge with ZV Support
+	0617  ToPIC100 PCI to Cardbus Bridge with ZV Support
 	0618  CPU to PCI and PCI to ISA bridge
 # Claimed to be Lucent DSP1645 [Mars], but that's apparently incorrect. Does anyone know the correct ID?
 	0701  FIR Port
@@ -4342,16 +4768,33 @@
 	1002  DL10050 Sundance Ethernet
 		1186 1002  DFE-550TX
 		1186 1012  DFE-580TX
+	1025  AirPlus Xtreme G DWL-G650 Adapter
+	1026  AirXpert DWL-AG650 Wireless Cardbus Adapter
+	1043  AirXpert DWL-AG650 Wireless Cardbus Adapter
 	1300  RTL8139 Ethernet
 		1186 1300  DFE-538TX 10/100 Ethernet Adapter
 		1186 1301  DFE-530TX+ 10/100 Ethernet Adapter
 	1340  DFE-690TXD CardBus PC Card
 	1541  DFE-680TXD CardBus PC Card
 	1561  DRP-32TXD Cardbus PC Card
+	2027  AirPlus Xtreme G DWL-G520 Adapter
+	3203  AirPlus Xtreme G DWL-G520 Adapter
 	3300  DWL-510 2.4GHz Wireless PCI Adapter
+	3a03  AirPro DWL-A650 Wireless Cardbus Adapter(rev.B)
+	3a04  AirPro DWL-AB650 Multimode Wireless Cardbus Adapter
+	3a05  AirPro DWL-AB520 Multimode Wireless PCI Adapter
+	3a07  AirXpert DWL-AG650 Wireless Cardbus Adapter
+	3a08  AirXpert DWL-AG520 Wireless PCI Adapter
+	3a10  AirXpert DWL-AG650 Wireless Cardbus Adapter(rev.B)
+	3a11  AirXpert DWL-AG520 Wireless PCI Adapter(rev.B)
+	3a12  AirPlus DWL-G650 Wireless Cardbus Adapter(rev.C)
+	3a13  AirPlus DWL-G520 Wireless PCI Adapter(rev.B)
+	3a14  AirPremier DWL-AG530 Wireless PCI Adapter
+	3a63  AirXpert DWL-AG660 Wireless Cardbus Adapter
 	3b05  DWL-G650+ CardBus PC Card
 	4000  DL2000-based Gigabit Ethernet
 	4c00  Gigabit Ethernet Adapter
+		1186 4c00  DGE-530T Gigabit Ethernet Adapter
 	8400  D-Link DWL-650+ CardBus PC Card
 1187  Advanced Technology Laboratories, Inc.
 1188  Shima Seiki Manufacturing Ltd.
@@ -4432,9 +4875,118 @@
 # Formerly Galileo Technology, Inc.
 11ab  Marvell Technology Group Ltd.
 	0146  GT-64010/64010A System Controller
+	138f  W8300 802.11 Adapter (rev 07)
 	1fa6  Marvell W8300 802.11 Adapter
 	4146  GT-64011/GT-64111 System Controller
-	4320  Yukon Gigabit Ethernet 10/100/1000Base-T Adapter
+	4320  Gigabit Ethernet Controller
+		1019 0f38  Marvell 88E8001 Gigabit Ethernet Controller (ECS)
+		1019 8001  Marvell 88E8001 Gigabit Ethernet Controller (ECS)
+		1043 173c  Marvell 88E8001 Gigabit Ethernet Controller (Asus)
+		1043 811a  Marvell 88E8001 Gigabit Ethernet Controller (Asus)
+		105b 0c19  Marvell 88E8001 Gigabit Ethernet Controller (Foxconn)
+		10b8 b452  SMC EZ Card 1000 (SMC9452TXV.2)
+		11ab 0121  Marvell RDK-8001
+		11ab 0321  Marvell RDK-8003
+		11ab 1021  Marvell RDK-8010
+		11ab 5021  Marvell Yukon Gigabit Ethernet 10/100/1000Base-T Controller (64 bit)
+		11ab 9521  Marvell Yukon Gigabit Ethernet 10/100/1000Base-T Controller (32 bit)
+		1458 e000  Marvell 88E8001 Gigabit Ethernet Controller (Gigabyte)
+		147b 1406  Marvell 88E8001 Gigabit Ethernet Controller (Abit)
+		15d4 0047  Marvell 88E8001 Gigabit Ethernet Controller (Iwill)
+		1695 9025  Marvell 88E8001 Gigabit Ethernet Controller (Epox)
+		17f2 1c03  Marvell 88E8001 Gigabit Ethernet Controller (Albatron)
+		270f 2803  Marvell 88E8001 Gigabit Ethernet Controller (Chaintech)
+	4350  Fast Ethernet Controller
+		1179 0001  Marvell 88E8035 Fast Ethernet Controller (Toshiba)
+		11ab 3521  Marvell RDK-8035
+		1854 000d  Marvell 88E8035 Fast Ethernet Controller (LGE)
+		1854 000e  Marvell 88E8035 Fast Ethernet Controller (LGE)
+		1854 000f  Marvell 88E8035 Fast Ethernet Controller (LGE)
+		1854 0011  Marvell 88E8035 Fast Ethernet Controller (LGE)
+		1854 0012  Marvell 88E8035 Fast Ethernet Controller (LGE)
+		1854 0016  Marvell 88E8035 Fast Ethernet Controller (LGE)
+		1854 0017  Marvell 88E8035 Fast Ethernet Controller (LGE)
+		1854 0018  Marvell 88E8035 Fast Ethernet Controller (LGE)
+		1854 0019  Marvell 88E8035 Fast Ethernet Controller (LGE)
+		1854 001c  Marvell 88E8035 Fast Ethernet Controller (LGE)
+		1854 001e  Marvell 88E8035 Fast Ethernet Controller (LGE)
+		1854 0020  Marvell 88E8035 Fast Ethernet Controller (LGE)
+	4351  Fast Ethernet Controller
+		107b 4009  Marvell 88E8036 Fast Ethernet Controller (Wistron)
+		10f7 8338  Marvell 88E8036 Fast Ethernet Controller (Panasonic)
+		1179 0001  Marvell 88E8036 Fast Ethernet Controller (Toshiba)
+		1179 ff00  Marvell 88E8036 Fast Ethernet Controller (Compal)
+		1179 ff10  Marvell 88E8036 Fast Ethernet Controller (Inventec)
+		11ab 3621  Marvell RDK-8036
+		13d1 ac12  Abocom EFE3K - 10/100 Ethernet Expresscard
+		161f 203d  Marvell 88E8036 Fast Ethernet Controller (Arima)
+		1854 000d  Marvell 88E8036 Fast Ethernet Controller (LGE)
+		1854 000e  Marvell 88E8036 Fast Ethernet Controller (LGE)
+		1854 000f  Marvell 88E8036 Fast Ethernet Controller (LGE)
+		1854 0011  Marvell 88E8036 Fast Ethernet Controller (LGE)
+		1854 0012  Marvell 88E8036 Fast Ethernet Controller (LGE)
+		1854 0016  Marvell 88E8036 Fast Ethernet Controller (LGE)
+		1854 0017  Marvell 88E8036 Fast Ethernet Controller (LGE)
+		1854 0018  Marvell 88E8036 Fast Ethernet Controller (LGE)
+		1854 0019  Marvell 88E8036 Fast Ethernet Controller (LGE)
+		1854 001c  Marvell 88E8036 Fast Ethernet Controller (LGE)
+		1854 001e  Marvell 88E8036 Fast Ethernet Controller (LGE)
+		1854 0020  Marvell 88E8036 Fast Ethernet Controller (LGE)
+	4360  Gigabit Ethernet Controller
+		1043 8134  Marvell 88E8052 Gigabit Ethernet Controller (Asus)
+		107b 4009  Marvell 88E8052 Gigabit Ethernet Controller (Wistron)
+		11ab 5221  Marvell RDK-8052
+		1458 e000  Marvell 88E8052 Gigabit Ethernet Controller (Gigabyte)
+		1462 052c  Marvell 88E8052 Gigabit Ethernet Controller (MSI)
+		1849 8052  Marvell 88E8052 Gigabit Ethernet Controller (ASRock)
+		1940 e000  Marvell 88E8052 Gigabit Ethernet Controller (Gigabyte)
+		a0a0 0509  Marvell 88E8052 Gigabit Ethernet Controller (Aopen)
+	4361  Gigabit Ethernet Controller
+		107b 3015  Marvell 88E8050 Gigabit Ethernet Controller (Gateway)
+		11ab 5021  Marvell 88E8050 Gigabit Ethernet Controller (Intel)
+		8086 3063  D925XCVLK mainboard
+	4362  Gigabit Ethernet Controller
+		103c 2a0d  Marvell 88E8053 Gigabit Ethernet Controller (Asus)
+		1043 8142  Marvell 88E8053 Gigabit Ethernet Controller (Asus)
+		109f 3197  Marvell 88E8053 Gigabit Ethernet Controller (Trigem)
+		10f7 8338  Marvell 88E8053 Gigabit Ethernet Controller (Panasonic)
+		10fd a430  Marvell 88E8053 Gigabit Ethernet Controller (SOYO)
+		1179 0001  Marvell 88E8053 Gigabit Ethernet Controller (Toshiba)
+		1179 ff00  Marvell 88E8053 Gigabit Ethernet Controller (Compal)
+		1179 ff10  Marvell 88E8053 Gigabit Ethernet Controller (Inventec)
+		11ab 5321  Marvell RDK-8053
+		1297 c240  Marvell 88E8053 Gigabit Ethernet Controller (Shuttle)
+		1297 c241  Marvell 88E8053 Gigabit Ethernet Controller (Shuttle)
+		1297 c242  Marvell 88E8053 Gigabit Ethernet Controller (Shuttle)
+		1297 c243  Marvell 88E8053 Gigabit Ethernet Controller (Shuttle)
+		1297 c244  Marvell 88E8053 Gigabit Ethernet Controller (Shuttle)
+		13d1 ac11  Abocom EGE5K - Giga Ethernet Expresscard
+		1458 e000  Marvell 88E8053 Gigabit Ethernet Controller (Gigabyte)
+		1462 058c  Marvell 88E8053 Gigabit Ethernet Controller (MSI)
+		14c0 0012  Marvell 88E8053 Gigabit Ethernet Controller (Compal)
+		1558 04a0  Marvell 88E8053 Gigabit Ethernet Controller (Clevo)
+		15bd 1003  Marvell 88E8053 Gigabit Ethernet Controller (DFI)
+		161f 203c  Marvell 88E8053 Gigabit Ethernet Controller (Arima)
+		161f 203d  Marvell 88E8053 Gigabit Ethernet Controller (Arima)
+		1695 9029  Marvell 88E8053 Gigabit Ethernet Controller (Epox)
+		17f2 2c08  Marvell 88E8053 Gigabit Ethernet Controller (Albatron)
+		17ff 0585  Marvell 88E8053 Gigabit Ethernet Controller (Quanta)
+		1849 8053  Marvell 88E8053 Gigabit Ethernet Controller (ASRock)
+		1854 000b  Marvell 88E8053 Gigabit Ethernet Controller (LGE)
+		1854 000c  Marvell 88E8053 Gigabit Ethernet Controller (LGE)
+		1854 0010  Marvell 88E8053 Gigabit Ethernet Controller (LGE)
+		1854 0013  Marvell 88E8053 Gigabit Ethernet Controller (LGE)
+		1854 0014  Marvell 88E8053 Gigabit Ethernet Controller (LGE)
+		1854 0015  Marvell 88E8053 Gigabit Ethernet Controller (LGE)
+		1854 001a  Marvell 88E8053 Gigabit Ethernet Controller (LGE)
+		1854 001b  Marvell 88E8053 Gigabit Ethernet Controller (LGE)
+		1854 001d  Marvell 88E8053 Gigabit Ethernet Controller (LGE)
+		1854 001f  Marvell 88E8053 Gigabit Ethernet Controller (LGE)
+		1854 0021  Marvell 88E8053 Gigabit Ethernet Controller (LGE)
+		1854 0022  Marvell 88E8053 Gigabit Ethernet Controller (LGE)
+		1940 e000  Marvell 88E8053 Gigabit Ethernet Controller (Gigabyte)
+		270f 2801  Marvell 88E8053 Gigabit Ethernet Controller (Chaintech)
+		a0a0 0506  Marvell 88E8053 Gigabit Ethernet Controller (Aopen)
 	4611  GT-64115 System Controller
 	4620  GT-64120/64120A/64121A System Controller
 	4801  GT-48001
@@ -4483,7 +5035,7 @@
 11be  International Microcircuits Inc
 11bf  Astrodesign, Inc.
 11c0  Hewlett Packard
-11c1  Lucent Microelectronics
+11c1  Agere Systems (former Lucent Microelectronics)
 	0440  56k WinModem
 		1033 8015  LT WinModem 56k Data+Fax+Voice+Dsvd
 		1033 8047  LT WinModem 56k Data+Fax+Voice+Dsvd
@@ -4586,12 +5138,25 @@
 	0462  V90 WildWire Modem
 	0480  Venus Modem (V90, 56KFlex)
 	048c  V.92 56K WinModem
+# InPorte Home Internal 56k Modem/fax/answering machine/SMS Features
+	048f  V.92 56k WinModem
 	5801  USB
 	5802  USS-312 USB Controller
 # 4 port PCI USB Controller made by Agere (formely Lucent)
 	5803  USS-344S USB Controller
 	5811  FW323
+		8086 524c  D865PERL mainboard
 		dead 0800  FireWire Host Bus Adapter
+	ab10  WL60010 Wireless LAN MAC
+	ab11  WL60040 Multimode Wireles LAN MAC
+		11c1 ab12  WaveLAN 11abg Cardbus card (Model 1102)
+		11c1 ab13  WaveLAN 11abg MiniPCI card (Model 0512)
+		11c1 ab15  WaveLAN 11abg Cardbus card (Model 1106)
+		11c1 ab16  WaveLAN 11abg MiniPCI card (Model 0516)
+	ab20  ORiNOCO PCI Adapter
+	ab21  Agere Wireless PCI Adapter
+	ab30  Hermes2 Mini-PCI WaveLAN a/b/g
+		14cd 2012  Hermes2 Mini-PCI WaveLAN a/b/g
 11c2  Sand Microelectronics
 11c3  NEC Corporation
 11c4  Document Technologies, Inc
@@ -4717,6 +5282,7 @@
 	0903  RocketPort Compact PCI 16 port w/external I/F
 	8015  RocketPort 4-port UART 16954
 11ff  Scion Corporation
+	0003  AG-5
 1200  CSS Corporation
 1201  Vista Controls Corp
 1202  Network General Corp.
@@ -4774,6 +5340,7 @@
 		1014 020c  ThinkPad R30
 		1179 0001  Magnia Z310
 	7110  OZ711Mx MultiMediaBay Accelerator
+		103c 0890  NC6000 laptop
 	7112  OZ711EC1/M1 SmartCardBus MultiMediaBay Controller
 	7113  OZ711EC1 SmartCardBus Controller
 	7114  OZ711M1 SmartCardBus MultiMediaBay Controller
@@ -4781,6 +5348,7 @@
 	7212  OZ711M2 SmartCardBus MultiMediaBay Controller
 	7213  OZ6933E CardBus Controller
 	7223  OZ711M3 SmartCardBus MultiMediaBay Controller
+		103c 0890  NC6000 laptop
 1218  Hybricon Corp.
 1219  First Virtual Corporation
 121a  3Dfx Interactive, Inc.
@@ -4808,7 +5376,7 @@
 		121a 0030  Voodoo3 AGP
 		121a 0031  Voodoo3 AGP
 		121a 0034  Voodoo3 AGP
-		121a 0036  Voodoo3
+		121a 0036  Voodoo3 2000 PCI
 		121a 0037  Voodoo3 AGP
 		121a 0038  Voodoo3 AGP
 		121a 003a  Voodoo3 AGP
@@ -4913,6 +5481,7 @@
 	1100  C2 ISDN
 	1200  T1 ISDN
 	2700  Fritz!Card DSL SL
+	2900  Fritz!Card DSL v2.0
 1245  A.P.D., S.A.
 1246  Dipix Technologies, Inc.
 1247  Xylon Research, Inc.
@@ -4929,7 +5498,7 @@
 	0003  EasyIO
 	0004  EasyConnection/RA
 124e  Cylink
-124f  Infotrend Technology, Inc.
+124f  Infortrend Technology, Inc.
 	0041  IFT-2000 Series RAID Controller
 1250  Hitachi Microcomputer System Ltd
 1251  VLSI Solutions Oy
@@ -4998,6 +5567,8 @@
 125e  Specialvideo Engineering SRL
 125f  Concurrent Technologies, Inc.
 1260  Intersil Corporation
+	3872  Prism 2.5 Wavelan chipset
+		1468 0202  LAN-Express IEEE 802.11b Wireless LAN
 	3873  Prism 2.5 Wavelan chipset
 		1186 3501  DWL-520 Wireless PCI Adapter
 		1186 3700  DWL-520 Wireless PCI Adapter, Rev E1
@@ -5007,10 +5578,18 @@
 		1737 3874  WMP11 Wireless 802.11b PCI Adapter
 		8086 2513  Wireless 802.11b MiniPCI Adapter
 	3886  ISL3886 [Prism Javelin/Prism Xbow]
+		17cf 0037  Z-Com XG-901 and clones Wireless Adapter
 	3890  Intersil ISL3890 [Prism GT/Prism Duette]
+		10b8 2802  SMC2802W Wireless PCI Adapter
+		10b8 2835  SMC2835W Wireless Cardbus Adapter
 		10b8 a835  SMC2835W V2 Wireless Cardbus Adapter
+		1113 ee03  SMC2802W V2 Wireless PCI Adapter
+		1186 3202  DWL-G650 A1 Wireless Adapter
+		1259 c104  CG-WLCB54GT Wireless Adapter
+		1385 4800  WG511 Wireless Adapter
 		16a5 1605  ALLNET ALL0271 Wireless PCI Adapter
-		17cf 0014  Ovislink WL-5400PCM, Prism GT
+		17cf 0014  Z-Com XG-600 and clones Wireless Adapter
+		17cf 0020  Z-Com XG-900 and clones Wireless Adapter
 	8130  HMP8130 NTSC/PAL Video Decoder
 	8131  HMP8131 NTSC/PAL Video Decoder
 1261  Matsushita-Kotobuki Electronics Industries, Ltd.
@@ -5256,6 +5835,7 @@
 1283  Integrated Technology Express, Inc.
 	673a  IT8330G
 	8212  IT/ITE8212 Dual channel ATA RAID controller
+		1283 0001  IT/ITE8212 Dual channel ATA RAID controller
 	8330  IT8330G
 	8872  IT8874F PCI Dual Serial Port Controller
 	8888  IT8888F PCI to ISA Bridge with SMB
@@ -5312,11 +5892,13 @@
 12a9  Xiotech Corporation
 12aa  SDL Communications, Inc.
 12ab  Yuan Yuan Enterprise Co., Ltd.
+	0002  AU8830 [Vortex2] Based Sound Card With A3D Support
 	3000  MPG-200C PCI DVD Decoder Card
 12ac  Measurex Corporation
 12ad  Multidata GmbH
 12ae  Alteon Networks Inc.
 	0001  AceNIC Gigabit Ethernet
+		1014 0104  Gigabit Ethernet-SX PCI Adapter
 		12ae 0001  Gigabit Ethernet-SX (Universal)
 		1410 0104  Gigabit Ethernet-SX PCI Adapter
 	0002  AceNIC Gigabit Ethernet (Copper)
@@ -5333,7 +5915,7 @@
 12b6  Natural Microsystems
 12b7  Cognex Modular Vision Systems Div. - Acumen Inc.
 12b8  Korg
-12b9  5610 56K FaxModem
+12b9  3Com Corp, Modem Division (formerly US Robotics)
 	1006  WinModem
 		12b9 005c  USR 56k Internal Voice WinModem (Model 3472)
 		12b9 005e  USR 56k Internal WinModem (Models 662975)
@@ -5417,7 +5999,7 @@
 12d3  Vingmed Sound A/S
 12d4  Ulticom (Formerly DGM&S)
 	0200  T1 Card
-12d5  Equator Technologies
+12d5  Equator Technologies Inc
 12d6  Analogic Corp
 12d7  Biotronic SRL
 12d8  Pericom Semiconductor
@@ -5546,6 +6128,7 @@
 	004c  PCI-DAS1000
 	004d  PCI-QUAD04
 	0052  PCI-DAS4020/12
+	005e  PCI-DAS6025
 1308  Jato Technologies Inc.
 	0001  NetCelerator Adapter
 		1308 0001  NetCelerator Adapter
@@ -5569,6 +6152,7 @@
 	8201  ADMtek ADM8211 802.11b Wireless Interface
 		10b8 2635  SMC2635W 802.11b (11Mbps) wireless lan pcmcia (cardbus) card
 		1317 8201  SMC2635W 802.11b (11mbps) wireless lan pcmcia (cardbus) card
+	8211  ADMtek ADM8211 802.11b Wireless Interface
 	9511  21x4x DEC-Tulip compatible 10/100 Ethernet
 1318  Packet Engines Inc.
 	0911  GNIC-II PCI Gigabit Ethernet [Hamachi]
@@ -5620,6 +6204,7 @@
 	2060  Trio 2S(16550)+1P
 	2061  Trio 2S(16650)+1P
 	2062  Trio 2S(16850)+1P
+	2081  CyberSerial (8-port) ST16654
 1320  Crypto AG
 1321  Arcobel Graphics BV
 1322  MTT Co., Ltd
@@ -5636,6 +6221,7 @@
 132d  Integrated Silicon Solution, Inc.
 1330  MMC Networks
 1331  Radisys Corp.
+	0030  ENP-2611
 	8200  82600 Host Bridge
 	8201  82600 IDE
 	8202  82600 USB
@@ -5667,6 +6253,8 @@
 134b  ARK Research Corp.
 134c  Chori Joho System Co. Ltd
 134d  PCTel Inc
+	2189  HSP56 MicroModem
+	2486  2304WT V.92 MDC Modem
 	7890  HSP MicroModem 56
 		134d 0001  PCT789 adapter
 	7891  HSP MicroModem 56
@@ -5718,6 +6306,13 @@
 	8001  8001 Digital I/O Adapter
 135f  I-Data International A-S
 1360  Meinberg Funkuhren
+	0101  PCI32 DCF77 Radio Clock
+	0102  PCI509 DCF77 Radio Clock
+	0103  PCI510 DCF77 Radio Clock
+	0201  GPS167PCI GPS Receiver
+	0202  GPS168PCI GPS Receiver
+	0203  GPS169PCI GPS Receiver
+	0301  TCR510PCI IRIG Receiver
 1361  Soliton Systems K.K.
 1362  Fujifacom Corporation
 1363  Phoenix Technology Ltd
@@ -5736,6 +6331,7 @@
 1370  ATL Products
 1371  CNet Technology Inc
 	434e  GigaCard Network Adapter
+		1371 434e  N-Way PCI-Bus Giga-Card 1000/100/10Mbps(L)
 1373  Silicon Vision Inc
 1374  Silicom Ltd
 1375  Argosystems Inc
@@ -5753,13 +6349,21 @@
 1380  Sanritz Automation Co Ltd
 1381  Brains Co. Ltd
 1382  Marian - Electronic & Software
+	0001  ARC88 audio recording card
 	2088  Marc-8 MIDI 8 channel audio card
 1383  Controlnet Inc
 1384  Reality Simulation Systems Inc
 1385  Netgear
+# Note: This lists as Atheros Communications, Inc. AR5212 802.11abg NIC because of Madwifi
+	0013  WG311T
 	4100  802.11b Wireless Adapter (MA301)
 	4105  MA311 802.11b wireless adapter
-	4a00  WAG311 802.11abg Wireless Adapter
+	4400  WAG511 802.11a/b/g Dual Band Wireless PC Card
+	4600  WAG511 802.11a/b/g Dual Band Wireless PC Card
+	4601  WAG511 802.11a/b/g Dual Band Wireless PC Card
+	4610  WAG511 802.11a/b/g Dual Band Wireless PC Card
+	4a00  WAG311 802.11a/g Wireless PCI Adapter
+	4c00  WG311v2 54 Mbps Wireless PCI Adapter
 	620a  GA620 Gigabit Ethernet
 	622a  GA622
 	630a  GA630 Gigabit Ethernet
@@ -5853,10 +6457,10 @@
 	0030  SyncLink Multiport Adapter
 	0210  SyncLink Adapter v2
 13c1  3ware Inc
-	1000  3ware ATA-RAID
-	1001  3ware 7000-series ATA-RAID
+	1000  3ware Inc 3ware 5xxx/6xxx-series PATA-RAID
+	1001  3ware Inc 3ware 7xxx/8xxx-series PATA/SATA-RAID
 		13c1 1001  3ware Inc 3ware 7xxx/8xxx-series PATA/SATA-RAID
-	1002  3ware ATA-RAID
+	1002  3ware Inc 3ware 9xxx-series SATA-RAID
 13c2  Technotrend Systemtechnik GmbH
 13c3  Janz Computer AG
 13c4  Phase Metrics
@@ -5944,6 +6548,7 @@
 13fc  Computer Peripherals International
 13fd  Micro Science Inc
 13fe  Advantech Co. Ltd
+	1240  PCI-1240 4-channel stepper motor controller card
 	1600  PCI-1612 4-port RS-232/422/485 PCI Communication Card
 	1752  PCI-1752
 	1754  PCI-1754
@@ -5998,6 +6603,7 @@
 1415  Oxford Semiconductor Ltd
 	8403  VScom 011H-EP1 1 port parallel adaptor
 	9501  OX16PCI954 (Quad 16950 UART) function 0
+		131f 2050  CyberPro (4-port)
 		15ed 2000  MCCR Serial p0-3 of 8
 		15ed 2001  MCCR Serial p0-3 of 16
 	950a  EXSYS EX-41092 Dual 16950 Serial adapter
@@ -6022,7 +6628,7 @@
 1422  Ygrec Systems Co Ltd
 1423  Custom Technology Corp.
 1424  Videoserver Connections
-1425  ASIC Designers Inc
+1425  Chelsio Communications Inc
 1426  Storage Technology Corp.
 1427  Better On-Line Solutions
 1428  Edec Co Ltd
@@ -6067,6 +6673,7 @@
 	7434  PCI-7434
 	7841  PCI-7841
 	8133  PCI-8133
+	8164  PCI-8164
 	8554  PCI-8554
 	9111  PCI-9111
 	9113  PCI-9113
@@ -6156,6 +6763,7 @@
 1496  JOYTECH Computer Co., Ltd.
 1497  SMA Regelsysteme GmBH
 1498  TEWS Datentechnik GmBH
+	30c8  TPCI200
 1499  EMTEC CO., Ltd
 149a  ANDOR Technology Ltd
 149b  SEIKO Instruments Inc
@@ -6208,6 +6816,7 @@
 	4800  Cisco Aironet 340 802.11b WLAN Adapter/Aironet PC4800
 	a504  Cisco Aironet Wireless 802.11b
 	a505  Cisco Aironet CB20a 802.11a Wireless LAN Adapter
+	a506  Cisco Aironet Mini PCI b/g
 14ba  INTERNIX Inc.
 14bb  SEMTECH Corporation
 14bc  Globespan Semiconductor Inc.
@@ -6259,6 +6868,7 @@
 # Formerly SiPackets, Inc., formerly API NetWorks, Inc., formerly Alpha Processor, Inc.
 14d9  Alliance Semiconductor Corporation
 	0010  AP1011/SP1011 HyperTransport-PCI Bridge [Sturgeon]
+	9000  AS90L10204/10208 HyperTransport to PCI-X Bridge
 14da  National Aerospace Laboratories
 14db  AFAVLAB Technology Inc
 	2120  TK9902
@@ -6353,17 +6963,27 @@
 		10b7 2000  3C998-T Dual Port 10/100/1000 PCI-X
 		10b7 3000  3C999-T Quad Port 10/100/1000 PCI-X
 		1166 1648  NetXtreme CIOB-E 1000Base-T
+	164a  NetXtreme II BCM5706 Gigabit Ethernet
 	164d  NetXtreme BCM5702FE Gigabit Ethernet
 	1653  NetXtreme BCM5705 Gigabit Ethernet
+		0e11 00e3  NC7761 Gigabit Server Adapter
 	1654  NetXtreme BCM5705_2 Gigabit Ethernet
+		0e11 00e3  NC7761 Gigabit Server Adapter
+		103c 3100  NC1020 HP ProLiant Gigabit Server Adapter 32 PCI
 	1659  NetXtreme BCM5721 Gigabit Ethernet PCI Express
 	165d  NetXtreme BCM5705M Gigabit Ethernet
 	165e  NetXtreme BCM5705M_2 Gigabit Ethernet
+		103c 0890  NC6000 laptop
+	166e  570x 10/100 Integrated Controller
 	1677  NetXtreme BCM5751 Gigabit Ethernet PCI Express
+		1028 0179  Optiplex GX280
+	167d  NetXtreme BCM5751M Gigabit Ethernet PCI Express
+	167e  NetXtreme BCM5751F Fast Ethernet PCI Express
 	1696  NetXtreme BCM5782 Gigabit Ethernet
 		103c 12bc  HP d530 CMT (DG746A)
 		14e4 000d  NetXtreme BCM5782 1000Base-T
 	169c  NetXtreme BCM5788 Gigabit Ethernet
+	169d  NetLink BCM5789 Gigabit Ethernet PCI Express
 	16a6  NetXtreme BCM5702X Gigabit Ethernet
 		0e11 00bb  NC7760 Gigabit Server Adapter (PCI-X, 10/100/1000-T)
 		1028 0126  BCM5702 1000Base-T
@@ -6378,30 +6998,58 @@
 		14e4 800a  NetXtreme BCM5703 1000Base-T
 	16a8  NetXtreme BCM5704S Gigabit Ethernet
 		10b7 2001  3C998-SX Dual Port 1000-SX PCI-X
+	16aa  NetXtreme II BCM5706S Gigabit Ethernet
 	16c6  NetXtreme BCM5702A3 Gigabit Ethernet
 		10b7 1100  3C1000B-T 10/100/1000 PCI
 		14e4 000c  BCM5702 1000Base-T
 		14e4 8009  BCM5702 1000Base-T
 	16c7  NetXtreme BCM5703 Gigabit Ethernet
+		0e11 00ca  NC7771 Gigabit Server Adapter (PCI-X, 10,100,1000-T)
+		0e11 00cb  NC7781 Gigabit Server Adapter (PCI-X, 10,100,1000-T)
 		103c 12c3  HP Combo FC/GigE-SX [A9782A]
 		103c 12ca  HP Combo FC/GigE-T [A9784A]
 		14e4 0009  NetXtreme BCM5703 1000Base-T
 		14e4 000a  NetXtreme BCM5703 1000Base-SX
+	16dd  NetLink BCM5781 Gigabit Ethernet PCI Express
+	16f7  NetXtreme BCM5753 Gigabit Ethernet PCI Express
+	16fd  NetXtreme BCM5753M Gigabit Ethernet PCI Express
+	16fe  NetXtreme BCM5753F Fast Ethernet PCI Express
 	170c  BCM4401-B0 100Base-TX
 	170d  NetXtreme BCM5901 100Base-TX
+		1014 0545  ThinkPad R40e (2684-HVG) builtin ethernet controller
 	170e  NetXtreme BCM5901 100Base-TX
 	3352  BCM3352
 	3360  BCM3360
 	4210  BCM4210 iLine10 HomePNA 2.0
 	4211  BCM4211 iLine10 HomePNA 2.0 + V.90 56k modem
 	4212  BCM4212 v.90 56k modem
-	4301  BCM4301 802.11b
+	4301  BCM4303 802.11b Wireless LAN Controller
+		1028 0407  TrueMobile 1180 Onboard WLAN
+		1043 0120  WL-103b Wireless LAN PC Card
+	4305  BCM4307 V.90 56k Modem
+	4306  BCM4307 Ethernet Controller
 	4307  BCM4307 802.11b Wireless LAN Controller
+	4310  BCM4310 Chipcommon I/OController
+	4312  BCM4310 UART
+	4313  BCM4310 Ethernet Controller
+	4315  BCM4310 USB Controller
 	4320  BCM4306 802.11b/g Wireless LAN Controller
 		1028 0001  TrueMobile 1300 WLAN Mini-PCI Card
+		1028 0003  Wireless 1350 WLAN Mini-PCI Card
+		1043 100f  WL-100G
+		14e4 4320  Linksys WMP54G PCI
 		1737 4320  WPC54G
+		1799 7010  Belkin F5D7010 54g Wireless Network card
+	4321  BCM4306 802.11a Wireless LAN Controller
+	4322  BCM4306 UART
 	4324  BCM4309 802.11a/b/g
 		1028 0001  Truemobile 1400
+		1028 0003  Truemobile 1450 MiniPCI
+	4325  BCM43xG 802.11b/g
+		1414 0003  Wireless Notebook Adapter MN-720
+		1414 0004  Wireless PCI Adapter MN-730
+# probably this is a correct ID...
+	4326  BCM4307 Chipcommon I/O Controller?
 	4401  BCM4401 100Base-T
 		1043 80a8  A7V8X motherboard
 	4402  BCM4402 Integrated 10/100BaseT
@@ -6418,16 +7066,20 @@
 	4614  BCM4610 Sentry5 External Interface
 	4615  BCM4610 Sentry5 USB Controller
 	4704  BCM4704 PCI to SB Bridge
-	4708  BCM4708 Sentry5 PCI to SB Bridge
+	4705  BCM4704 Sentry5 802.11b Wireless LAN Controller
+	4706  BCM4704 Sentry5 Ethernet Controller
+	4707  BCM4704 Sentry5 USB Controller
+	4708  BCM4704 Crypto Accelerator
 	4710  BCM4710 Sentry5 PCI to SB Bridge
 	4711  BCM47xx Sentry5 iLine32 HomePNA 2.0
-	4712  Sentry5 UART
+	4712  BCM47xx V.92 56k modem
 	4713  Sentry5 Ethernet Controller
 	4714  BCM47xx Sentry5 External Interface
 	4715  Sentry5 USB Controller
 	4716  BCM47xx Sentry5 USB Host Controller
 	4717  BCM47xx Sentry5 USB Device Controller
 	4718  Sentry5 Crypto Accelerator
+	4720  BCM4712 MIPS CPU
 	5365  BCM5365P Sentry5 Host Bridge
 	5600  BCM5600 StrataSwitch 24+2 Ethernet Switch Controller
 	5605  BCM5605 StrataSwitch 24+2 Ethernet Switch Controller
@@ -6595,6 +7247,8 @@
 		13e0 8d84  IBM HSFi V.90
 		13e0 8d85  Compaq Stinger
 		14f1 2004  Dynalink 56PMi
+	2f02  HSF 56k HSFi Data/Fax
+	2f11  HSF 56k HSFi Modem
 	8234  RS8234 ATM SAR Controller [ServiceSAR Plus]
 	8800  Winfast TV2000 XP
 14f2  MOBILITY Electronics
@@ -6603,12 +7257,16 @@
 	0122  EV1000 Serial port
 	0123  EV1000 Keyboard controller
 	0124  EV1000 Mouse controller
-14f3  BROADLOGIC
+14f3  BroadLogic
+	2030  2030 DVB-S Satellite Reciever
+	2050  2050 DVB-T Terrestrial (Cable) Reciever
+	2060  2060 ATSC Terrestrial (Cable) Reciever
 14f4  TOKYO Electronic Industry CO Ltd
 14f5  SOPAC Ltd
 14f6  COYOTE Technologies LLC
 14f7  WOLF Technology Inc
 14f8  AUDIOCODES Inc
+	2077  TP-240 dual span E1 VoIP PCI card
 14f9  AG COMMUNICATIONS
 14fa  WANDEL & GOCHERMANN
 14fb  TRANSAS MARINE (UK) Ltd
@@ -6687,12 +7345,16 @@
 1523  MUSIC Semiconductors
 1524  ENE Technology Inc
 	0510  CB710 Memory Card Reader Controller
+	0610  PCI Smart Card Reader Controller
 	1211  CB1211 Cardbus Controller
 	1225  CB1225 Cardbus Controller
 	1410  CB1410 Cardbus Controller
-	1411  CB710 Cardbus Controller
+		1025 005a  TravelMate 290
+	1411  CB-710/2/4 Cardbus Controller
+	1412  CB-712/4 Cardbus Controller
 	1420  CB1420 Cardbus Controller
-	1421  CB720 Cardbus Controller
+	1421  CB-720/2/4 Cardbus Controller
+	1422  CB-722/4 Cardbus Controller
 1525  IMPACT Technologies
 1526  ISS, Inc
 1527  SOLECTRON
@@ -6717,6 +7379,9 @@
 153a  ONO SOKKI
 153b  TERRATEC Electronic GmbH
 	1144  Aureon 5.1
+# Terratec seems to use several IDs for the same card.
+	1147  Aureon 5.1 Sky
+	1158  Philips Semiconductors SAA7134 (rev 01) [Terratec Cinergy 600 TV]
 153c  ANTAL Electronic
 153d  FILANET Corp
 153e  TECHWELL Inc
@@ -6859,18 +7524,24 @@
 15aa  Moreton Bay
 15ab  Bluesteel Networks Inc
 15ac  North Atlantic Instruments
-15ad  VMWare Inc
-	0405  [VMWare SVGA II] PCI Display Adapter
+15ad  VMware Inc
+	0405  [VMware SVGA II] PCI Display Adapter
 	0710  Virtual SVGA
+	0720  VMware High-Speed Virtual NIC [vmxnet]
 15ae  Amersham Pharmacia Biotech
 15b0  Zoltrix International Ltd
 15b1  Source Technology Inc
 15b2  Mosaid Technologies Inc
-15b3  Mellanox Technology
+15b3  Mellanox Technologies
 	5274  MT21108 InfiniBridge
 	5a44  MT23108 InfiniHost
-	5a45  MT23108 InfiniHost (Tavor)
+	5a45  MT23108 [Infinihost HCA Flash Recovery]
 	5a46  MT23108 PCI Bridge
+	5e8c  MT24204 [InfiniHost III Lx HCA]
+	5e8d  MT24204 [InfiniHost III Lx HCA Flash Recovery]
+	6278  MT25208 InfiniHost III Ex (Tavor compatibility mode)
+	6279  MT25208 [InfiniHost III Ex HCA Flash Recovery]
+	6282  MT25208 InfiniHost III Ex
 15b4  CCI/TRIAD
 15b5  Cimetrics Inc
 15b6  Texas Memory Systems Inc
@@ -6981,7 +7652,7 @@
 1637  Linksys
 	3874  Linksys 802.11b WMP11 PCI Wireless card
 1638  Standard Microsystems Corp [SMC]
-	1100  SMC2602W EZConnect/Addtron AWA-100/Eumitcom WL11000
+	1100  SMC2602W EZConnect/Addtron AWA-100/Eumitcom PCI WL11000
 163c  Smart Link Ltd.
 	3052  SmartLink SmartPCI562 56K Modem
 	5449  SmartPCI561 Modem
@@ -6998,6 +7669,10 @@
 166d  Broadcom Corporation
 	0001  SiByte BCM1125/1125H/1250 System-on-a-Chip PCI
 	0002  SiByte BCM1125H/1250 System-on-a-Chip HyperTransport
+1677  Bernecker + Rainer
+	104e  5LS172.6 B&R Dual CAN Interface Card
+	12d7  5LS172.61 B&R Dual CAN Interface Card
+167b  ZyDAS Technology Corp.
 1681  Hercules
 # More specs, more accurate desc.
 	0010  Hercules 3d Prophet II Ultra 64MB [ 350 MHz NV15BR core, 128-bit DDR @ 460 MHz, 1.5v AGP4x  ]
@@ -7010,9 +7685,13 @@
 	0013  AR5212 802.11abg NIC
 		1186 3202  D-link DWL-G650 B3 Wireless cardbus adapter
 		1186 3203  DWL-G520 Wireless PCI Adapter
+		1186 3a13  DWL-G520 Wireless PCI Adapter rev. B
 		1186 3a94  C54C Wireless 801.11g cardbus
+		1385 4d00  Netgear WG311T Wireless PCI Adapter
+		14b7 0a60  8482-WD ORiNOCO 11a/b/g Wireless PCI Adapter
 		168c 0013  WG511T Wireless CardBus Adapter
 		168c 1025  DWL-G650B2 Wireless CardBus Adapter
+		168c 2026  Netgate 5354MP ARIES a(108Mb turbo)/b/g MiniPCI Adapter
 	1014  AR5212 802.11abg NIC
 16a5  Tekram Technology Co.,Ltd.
 16ab  Global Sun Technology Inc
@@ -7021,10 +7700,12 @@
 	1102  PCMCIA-to-PCI Wireless Network Bridge
 16ae  Safenet Inc
 	1141  SafeXcel-1141
+16b4  Aspex Semiconductor Ltd
 16be  Creatix Polymedia GmbH
 16ca  CENATEK Inc
 	0001  Rocket Drive DL
 16cd  Densitron Technologies
+16ce  Roland Corp.
 # www.pikatechnologies.com
 16df  PIKA Technologies Inc.
 16e3  European Space Agency
@@ -7032,6 +7713,9 @@
 16ec  U.S. Robotics
 	00ff  USR997900 10/100 Mbps PCI Network Card
 	3685  Wireless Access PCI Adapter Model 022415
+16ed  Sycron N. V.
+	1001  UMIO communication card
+16f3  Jetway Information Co., Ltd.
 16f4  Vweb Corp
 	8000  VW2010
 16f6  VideoTele.com, Inc.
@@ -7045,8 +7729,10 @@
 1725  Vitesse Semiconductor
 	7174  VSC7174 PCI/PCI-X Serial ATA Host Bus Controller
 172a  Accelerated Encryption
+1734  Fujitsu Siemens Computer GmbH
 1737  Linksys
 	0013  WMP54G Wireless Pci Card
+	0015  WMP54GS Wireless Pci Card
 	1032  Gigabit Network Adapter
 		1737 0015  EG1032 v2 Instant Gigabit Network Adapter
 	1064  Gigabit Network Adapter
@@ -7081,6 +7767,9 @@
 	6020  Wireless PCMCIA Card - F5D6020
 	6060  Wireless PDA Card - F5D6060
 	7000  Wireless PCI Card - F5D7000
+17a0  Genesys Logic, Inc
+	8033  GL880S USB 1.1 controller
+	8034  GL880S USB 2.0 controller
 17af  Hightech Information System Ltd.
 17b3  Hawking Technologies
 	ab08  PN672TX 10/100 Ethernet
@@ -7090,9 +7779,12 @@
 17c2  Newisys, Inc.
 17cc  NetChip Technology, Inc
 	2280  USB 2.0
+17d3  Areca Technology Corp.
 # S2io ships 10Gb PCI-X Ethernet adapters www.s2io.com
 17d5  S2io Inc.
-# Supplying full name for a currently green entry
+17de  KWorld Computer Co. Ltd.
+# http://www.connect3d.com
+17ee  Connect Components Ltd
 17fe  Linksys, A Division of Cisco Systems
 	2220  [AirConn] INPROCOMM IPN 2220 WLAN Adapter (rev 01)
 1813  Ambient Technologies Inc
@@ -7103,15 +7795,30 @@
 1814  RaLink
 	0101  Wireless PCI Adpator RT2400 / RT2460
 	0201  Ralink RT2500 802.11 Cardbus Reference Card
+		1371 001e  CWC-854 Wireless-G CardBus Adapter
+		1371 001f  CWM-854 Wireless-G Mini PCI Adapter
+		1371 0020  CWP-854 Wireless-G PCI Adapter
 1820  InfiniCon Systems Inc.
 1822  Twinhan Technology Co. Ltd
+182d  SiteCom Europe BV
+# HFC-based ISDN card
+	3069  ISDN PCI DC-105V2
 1830  Credence Systems Corporation
+183b  MikroM GmbH
+	08a7  MVC100 DVI
+	08a8  MVC101 SDI
+	08a9  MVC102 DVI+Audio
+1849  ASRock Incorporation
 1851  Microtune, Inc.
 1852  Anritsu Corp.
+185f  Wistron NeWeb Corp.
 1867  Topspin Communications
 	5a44  MT23108 PCI-X HCA
 	5a45  MT23108 PCI-X HCA flash recovery
 	5a46  MT23108 PCI-X HCA bridge
+	6278  MT25208 InfiniHost III Ex (Tavor compatibility mode)
+	6282  MT25208 InfiniHost III Ex
+187e  ZyXEL Communication Corporation
 1888  Varisys Ltd
 	0301  VMFX1 FPGA PMC module
 	0601  VSM2 dual PMC carrier
@@ -7119,14 +7826,30 @@
 	0720  VS24x series PowerPC PCI board
 # found e.g. on KNC DVB-S card
 1894  KNC One
+1896  B&B Electronics Manufacturing Company, Inc.
 18a1  Astute Networks Inc.
+18ac  DViCO Corporation
+	d810  FusionHDTV 3 Gold
+18b8  Ammasso
 18bc  Info-Tek Corp.
+# assigned to Octigabay System, which has been acquired by Cray
+18c8  Cray Inc
 18c9  ARVOO Engineering BV
 18ca  XGI - Xabre Graphics Inc
 	0040  Volari V8
 18e6  MPL AG
 	0001  OSCI [Octal Serial Communication Interface]
+18f7  Commtech, Inc.
+	0001  Fastcom ESCC-PCI-335
+	0002  Fastcom 422/4-PCI-335
+	0004  Fastcom 422/2-PCI-335
+	0005  Fastcom IGESCC-PCI-ISO/1
+	000a  Fastcom 232/4-PCI-335
 18fb  Resilience Corporation
+1924  Level 5 Networks Inc.
+1966  Orad Hi-Tec Systems
+1975  Pudlis Co. Ltd.
+1993  Innominate Security Technologies AG
 1a08  Sierra semiconductor
 	0000  SC15064
 1b13  Jaton Corp
@@ -7165,6 +7888,7 @@
 		4c53 10a0  CA3/CR3 mainboard
 		4c53 3010  PPCI mezzanine (32-bit PMC)
 		4c53 3011  PPCI mezzanine (64-bit PMC)
+	0022  HiNT HB4 PCI-PCI Bridge (PCI6150)
 	0026  HB2 PCI-PCI Bridge
 	101a  E.Band [AudioTrak Inca88]
 	101b  E.Band [AudioTrak Inca88]
@@ -7176,6 +7900,7 @@
 		3388 8013  VXPro II Chipset EIDE Controller
 3411  Quantum Designs (H.K.) Inc
 3513  ARCOM Control Systems Ltd
+3842  eVga.com. Corp.
 38ef  4Links
 3d3d  3DLabs
 	0001  GLINT 300SX
@@ -7211,6 +7936,7 @@
 	0024  VP9 visual processor
 	0100  Permedia II 2D+3D
 	07a1  Wildcat III 6210
+	07a2  Sun XVR-500 Graphics Accelerator
 	07a3  Wildcat IV 7210
 	1004  Permedia
 	3d04  Permedia
@@ -7252,6 +7978,8 @@
 4916  RedCreek Communications Inc
 	1960  RedCreek PCI adapter
 4943  Growth Networks
+494f  ACCES I/O Products, Inc.
+	10e8  LPCI-COM-8SM
 4978  Axil Computer Inc
 4a14  NetVin
 	5000  NV5000SC
@@ -7366,6 +8094,7 @@
 	8a22  Savage 4
 		1033 8068  Savage 4
 		1033 8069  Savage 4
+		1033 8110  Savage4 LT
 		105d 0018  SR9 8Mb SDRAM
 		105d 002a  SR9 Pro 16Mb SDRAM
 		105d 003a  SR9 Pro 32Mb SDRAM
@@ -7458,7 +8187,7 @@
 	0011  PWDOG2 [PCI-Watchdog 2]
 # Wrong ID used in subsystem ID of AsusTek PCI-USB2 PCI card.
 807d  Asustek Computer, Inc.
-8086  Intel Corp.
+8086  Intel Corporation
 	0007  82379AB
 	0008  Extended Express System Support Controller
 		0008 1000  WorldMark 4300 INCA ASIC
@@ -7466,11 +8195,11 @@
 	0122  82437FX
 	0309  80303 I/O Processor PCI-to-PCI Bridge
 	030d  80312 I/O Companion Chip PCI-to-PCI Bridge
-	0326  PCI Bridge Hub I/OxAPIC Interrupt Controller A
-	0327  PCI Bridge Hub I/OxAPIC Interrupt Controller B
-	0329  PCI Bridge Hub A
-	032a  PCI Bridge Hub B
-	032c  PCI Bridge Hub
+	0326  6700/6702PXH I/OxAPIC Interrupt Controller A
+	0327  6700PXH I/OxAPIC Interrupt Controller B
+	0329  6700PXH PCI Express-to-PCI Bridge A
+	032a  6700PXH PCI Express-to-PCI Bridge B
+	032c  6702PXH PCI Express-to-PCI Bridge A
 # A-segment bridge
 	0330  80332 [Dobson] I/O processor
 # A-segment IOAPIC
@@ -7521,6 +8250,8 @@
 	0600  RAID Controller
 		8086 01c1  ICP Vortex GDT8546RZ
 		8086 01f7  SCRU32
+# uninitialized SRCU32 RAID Controller
+	061f  80303 I/O Processor
 	0960  80960RP [i960 RP Microprocessor/Bridge]
 	0962  80960RM [i960RM Bridge]
 	0964  80960RP [i960 RP Microprocessor/Bridge]
@@ -7533,6 +8264,7 @@
 	1001  82543GC Gigabit Ethernet Controller (Fiber)
 		0e11 004a  NC6136 Gigabit Server Adapter
 		1014 01ea  Netfinity Gigabit Ethernet SX Adapter
+		8086 1002  PRO/1000 F Server Adapter
 		8086 1003  PRO/1000 F Server Adapter
 	1002  Pro 100 LAN+Modem 56 Cardbus II
 		8086 200e  Pro 100 LAN+Modem 56 Cardbus II
@@ -7567,6 +8299,8 @@
 		1014 0265  PRO/1000 MT Network Connection
 		1014 0267  PRO/1000 MT Network Connection
 		1014 026a  PRO/1000 MT Network Connection
+		1028 002e  Optiplex GX260
+		1028 0151  PRO/1000 MT Network Connection
 		107b 8920  PRO/1000 MT Desktop Adapter
 		8086 001e  PRO/1000 MT Desktop Adapter
 		8086 002e  PRO/1000 MT Desktop Adapter
@@ -7582,6 +8316,7 @@
 		4c53 10a0  CA3/CR3 mainboard
 		8086 1011  PRO/1000 MT Dual Port Server Adapter
 		8086 101a  PRO/1000 MT Dual Port Network Adapter
+		8086 3424  SE7501HG2 Mainboard
 	1011  82545EM Gigabit Ethernet Controller (Fiber)
 		1014 0268  iSeries Gigabit Ethernet Adapter
 		8086 1002  PRO/1000 MF Server Adapter
@@ -7590,6 +8325,7 @@
 		8086 1012  PRO/1000 MF Dual Port Server Adapter
 	1013  82541EI Gigabit Ethernet Controller (Copper)
 		8086 0013  PRO/1000 MT Network Connection
+		8086 1013  IBM ThinkCentre Network Card
 		8086 1113  PRO/1000 MT Desktop Adapter
 	1014  82541ER Gigabit Ethernet Controller
 	1015  82540EM Gigabit Ethernet Controller (LOM)
@@ -7605,6 +8341,7 @@
 	1019  82547EI Gigabit Ethernet Controller (LOM)
 		1458 1019  GA-8IPE1000 Pro2 motherboard (865PE)
 		8086 1019  PRO/1000 CT Desktop Connection
+		8086 301f  D865PERL mainboard
 		8086 3427  S875WP1-E mainboard
 	101d  82546EB Gigabit Ethernet Controller
 		8086 1000  PRO/1000 MT Quad Port Server Adapter
@@ -7642,13 +8379,13 @@
 	1036  82801CAM (ICH3) 82562EH Ethernet Controller
 	1037  82801CAM (ICH3) Chipset Ethernet Controller
 	1038  82801CAM (ICH3) PRO/100 VM (KM) Ethernet Controller
-	1039  82801BD PRO/100 VE (LOM) Ethernet Controller
+	1039  82801DB PRO/100 VE (LOM) Ethernet Controller
 		1014 0267  NetVista A30p
-	103a  82801BD PRO/100 VE (CNR) Ethernet Controller
-	103b  82801BD PRO/100 VM (LOM) Ethernet Controller
-	103c  82801BD PRO/100 VM (CNR) Ethernet Controller
-	103d  82801BD PRO/100 VE (MOB) Ethernet Controller
-	103e  82801BD PRO/100 VM (MOB) Ethernet Controller
+	103a  82801DB PRO/100 VE (CNR) Ethernet Controller
+	103b  82801DB PRO/100 VM (LOM) Ethernet Controller
+	103c  82801DB PRO/100 VM (CNR) Ethernet Controller
+	103d  82801DB PRO/100 VE (MOB) Ethernet Controller
+	103e  82801DB PRO/100 VM (MOB) Ethernet Controller
 	1040  536EP Data Fax Modem
 		16be 1040  V.9X DSP Data Fax Modem
 	1043  PRO/Wireless LAN 2100 3B Mini PCI Adapter
@@ -7662,42 +8399,55 @@
 		8086 3427  S875WP1-E mainboard
 	1051  82801EB/ER (ICH5/ICH5R) integrated LAN Controller
 	1059  82551QM Ethernet Controller
-	1065  82801FB/FBM/FR/FW/FRW (ICH6 Family) LAN Controller
-# Updated controller name from 82547EI to 82547GI
+# ICH-6 Component
+	1064  82562ET/EZ/GT/GZ - PRO/100 VE (LOM) Ethernet Controller
+# ICH-6 Component
+	1065  82562ET/EZ/GT/GZ - PRO/100 VE Ethernet Controller
+# ICH-6 Component
+	1066  82562 EM/EX/GX - PRO/100 VM (LOM) Ethernet Controller
+# ICH-6 Component
+	1067  82562 EM/EX/GX - PRO/100 VM Ethernet Controller
+# ICH-6 Component
+	1068  82562ET/EZ/GT/GZ - PRO/100 VE (LOM) Ethernet Controller Mobile
+# ICH-6 Component
+	1069  82562 EM/EX/GX - PRO/100 VM (LOM) Ethernet Controller Mobile
+# ICH-6 Component
+	106a  82562G \t- PRO/100 VE (LOM) Ethernet Controller
+# ICH-6 Component
+	106b  82562G \t- PRO/100 VE Ethernet Controller Mobile
 	1075  82547GI Gigabit Ethernet Controller
+		1028 0165  PowerEdge 750
 		8086 0075  PRO/1000 CT Network Connection
 		8086 1075  PRO/1000 CT Network Connection
-# Added PI to part name.  Previous part name was 82541GI
 	1076  82541GI/PI Gigabit Ethernet Controller
+		1028 0165  PowerEdge 750
 		8086 0076  PRO/1000 MT Network Connection
 		8086 1076  PRO/1000 MT Network Connection
 		8086 1176  PRO/1000 MT Desktop Adapter
 		8086 1276  PRO/1000 MT Desktop Adapter
-# Update controller name from 82541EI to 82541GI
 	1077  82541GI Gigabit Ethernet Controller
 		1179 0001  PRO/1000 MT Mobile Connection
 		8086 0077  PRO/1000 MT Mobile Connection
 		8086 1077  PRO/1000 MT Mobile Connection
 	1078  82541EI Gigabit Ethernet Controller
 		8086 1078  PRO/1000 MT Network Connection
-# Update from mistaken ID of 82546EB
 	1079  82546GB Gigabit Ethernet Controller
 		103c 12a6  HP Dual Port 1000Base-T [A9900A]
 		103c 12cf  HP Core Dual Port 1000Base-T [AB352A]
 		4c53 1090  Cx9 / Vx9 mainboard
+		4c53 10b0  CL9 mainboard
 		8086 0079  PRO/1000 MT Dual Port Network Connection
 		8086 1079  PRO/1000 MT Dual Port Network Connection
 		8086 1179  PRO/1000 MT Dual Port Network Connection
 		8086 117a  PRO/1000 MT Dual Port Server Adapter
-# Update from mistaken ID of 82546EB
 	107a  82546GB Gigabit Ethernet Controller
 		103c 12a8  HP Dual Port 1000base-SX [A9899A]
 		8086 107a  PRO/1000 MF Dual Port Server Adapter
 		8086 127a  PRO/1000 MF Dual Port Server Adapter
-# Update from mistaken ID of 82546EB
 	107b  82546GB Gigabit Ethernet Controller
 		8086 007b  PRO/1000 MB Dual Port Server Connection
 		8086 107b  PRO/1000 MB Dual Port Server Connection
+	1107  PRO/1000 MF Server Adapter (LX)
 	1130  82815 815 Chipset Host Bridge and Memory Controller Hub
 		1025 1016  Travelmate 612 TX
 		1043 8027  TUSL2-C Mainboard
@@ -7715,7 +8465,7 @@
 	1162  Xscale 80200 Big Endian Companion Chip
 	1200  Intel IXP1200 Network Processor
 		172a 0000  AEP SSL Accelerator
-	1209  82559ER
+	1209  8255xER/82551IT Fast Ethernet Controller
 		4c53 1050  CT7 mainboard
 		4c53 1051  CE7 mainboard
 		4c53 1070  PC6 mainboard
@@ -7766,7 +8516,7 @@
 		1014 605c  10/100 EtherJet Secure Management Adapter
 		1014 705c  10/100 Netfinity 10/100 Ethernet Security Adapter
 		1014 805c  10/100 Netfinity 10/100 Ethernet Security Adapter
-		1028 009b  PowerEdge 2550
+		1028 009b  PowerEdge 2500/2550
 		1028 00ce  PowerEdge 1400
 		1033 8000  PC-9821X-B06
 		1033 8016  PK-UG-X006
@@ -7937,6 +8687,7 @@
 	1a23  82840 840 (Carmel) Chipset AGP Bridge
 	1a24  82840 840 (Carmel) Chipset PCI Bridge (Hub B)
 	1a30  82845 845 (Brookdale) Chipset Host Bridge
+		1028 010e  Optiplex GX240
 	1a31  82845 845 (Brookdale) Chipset AGP Bridge
 	2410  82801AA ISA Bridge (LPC)
 	2411  82801AA IDE
@@ -7962,6 +8713,8 @@
 	2442  82801BA/BAM USB (Hub #1)
 		1014 01c6  Netvista A40/A40p
 		1025 1016  Travelmate 612 TX
+		1028 010e  Optiplex GX240
+		1043 8027  TUSL2-C Mainboard
 		104d 80df  Vaio PCG-FX403
 		147b 0507  TH7II-RAID
 		8086 4532  D815EEA2 mainboard
@@ -7969,6 +8722,7 @@
 	2443  82801BA/BAM SMBus
 		1014 01c6  Netvista A40/A40p
 		1025 1016  Travelmate 612 TX
+		1028 010e  Optiplex GX240
 		1043 8027  TUSL2-C Mainboard
 		104d 80df  Vaio PCG-FX403
 		147b 0507  TH7II-RAID
@@ -7976,6 +8730,8 @@
 		8086 4557  D815EGEW Mainboard
 	2444  82801BA/BAM USB (Hub #2)
 		1025 1016  Travelmate 612 TX
+		1028 010e  Optiplex GX240
+		1043 8027  TUSL2-C Mainboard
 		104d 80df  Vaio PCG-FX403
 		147b 0507  TH7II-RAID
 		8086 4532  D815EEA2 mainboard
@@ -8026,6 +8782,7 @@
 		104d 80df  Vaio PCG-FX403
 	244b  82801BA IDE U100
 		1014 01c6  Netvista A40/A40p
+		1028 010e  Optiplex GX240
 		1043 8027  TUSL2-C Mainboard
 		147b 0507  TH7II-RAID
 		8086 4532  D815EEA2 mainboard
@@ -8046,6 +8803,7 @@
 		104d 80e7  VAIO PCG-GR214EP/GR214MP/GR215MP/GR314MP/GR315MP
 		15d9 3480  P4DP6
 		8086 1958  vpr Matrix 170B4
+		8086 3424  SE7501HG2 Mainboard
 		8086 4541  Latitude C640
 	2483  82801CA/CAM SMBus Controller
 		1014 0220  ThinkPad A/T/X Series
@@ -8058,6 +8816,7 @@
 		15d9 3480  P4DP6
 		8086 1958  vpr Matrix 170B4
 	2485  82801CA/CAM AC'97 Audio Controller
+		1013 5959  Crystal WMD Audio Codec
 		1014 0222  ThinkPad T23 (2647-4MG) or A30/A30p (2652/2653)
 		1014 0508  ThinkPad T30
 		1014 051c  ThinkPad A/T/X Series
@@ -8086,76 +8845,117 @@
 	248b  82801CA Ultra ATA Storage Controller
 		15d9 3480  P4DP6
 	248c  82801CAM ISA Bridge (LPC)
-	24c0  82801DB/DBL (ICH4/ICH4-L) LPC Bridge
+	24c0  82801DB/DBL (ICH4/ICH4-L) LPC Interface Bridge
 		1014 0267  NetVista A30p
 		1462 5800  845PE Max (MS-6580)
 	24c1  82801DBL (ICH4-L) IDE Controller
 	24c2  82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #1
 		1014 0267  NetVista A30p
+		1025 005a  TravelMate 290
+		1028 0126  Optiplex GX260
+		1028 0163  Latitude D505
+		103c 0890  NC6000 laptop
 		1071 8160  MIM2000
 		1462 5800  845PE Max (MS-6580)
+		1509 2990  Averatec 5110H laptop
+		4c53 1090  Cx9 / Vx9 mainboard
 	24c3  82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) SMBus Controller
 		1014 0267  NetVista A30p
+		1025 005a  TravelMate 290
+		1028 0126  Optiplex GX260
+		103c 0890  NC6000 laptop
 		1071 8160  MIM2000
 		1458 24c2  GA-8PE667 Ultra
 		1462 5800  845PE Max (MS-6580)
 		4c53 1090  Cx9 / Vx9 mainboard
 	24c4  82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #2
 		1014 0267  NetVista A30p
+		1025 005a  TravelMate 290
+		1028 0126  Optiplex GX260
+		1028 0163  Latitude D505
+		103c 0890  NC6000 laptop
 		1071 8160  MIM2000
 		1462 5800  845PE Max (MS-6580)
+		1509 2990  Averatec 5110H
 		4c53 1090  Cx9 / Vx9 mainboard
 	24c5  82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) AC'97 Audio Controller
 		0e11 00b8  Analog Devices Inc. codec [SoundMAX]
 		1014 0267  NetVista A30p
+		1025 005a  TravelMate 290
+		1028 0163  Latitude D505
+		103c 0890  NC6000 laptop
 		1071 8160  MIM2000
 		1458 a002  GA-8PE667 Ultra
 		1462 5800  845PE Max (MS-6580)
 	24c6  82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) AC'97 Modem Controller
+		1025 005a  TravelMate 290
+		103c 0890  NC6000 laptop
 		1071 8160  MIM2000
 	24c7  82801DB/DBL/DBM (ICH4/ICH4-L/ICH4-M) USB UHCI Controller #3
 		1014 0267  NetVista A30p
+		1025 005a  TravelMate 290
+		1028 0126  Optiplex GX260
+		1028 0163  Latitude D505
+		103c 0890  NC6000 laptop
 		1071 8160  MIM2000
 		1462 5800  845PE Max (MS-6580)
+		1509 2990  Averatec 5110H
+		4c53 1090  Cx9 / Vx9 mainboard
 	24ca  82801DBM (ICH4) Ultra ATA Storage Controller
+		1025 005a  TravelMate 290
+		1028 0163  Latitude D505
+		103c 0890  NC6000 laptop
 		1071 8160  MIM2000
 	24cb  82801DB/DBL (ICH4/ICH4-L) UltraATA-100 IDE Controller
 		1014 0267  NetVista A30p
+		1028 0126  Optiplex GX260
 		1458 24c2  GA-8PE667 Ultra
 		1462 5800  845PE Max (MS-6580)
 		4c53 1090  Cx9 / Vx9 mainboard
 	24cc  82801DBM LPC Interface Controller
 	24cd  82801DB/DBM (ICH4/ICH4-M) USB 2.0 EHCI Controller
 		1014 0267  NetVista A30p
+		1025 005a  TravelMate 290
+		1028 0126  Optiplex GX260
+		1028 0163  Latitude D505
+		103c 0890  NC6000 laptop
 		1071 8160  MIM2000
 		1462 3981  845PE Max (MS-6580)
+		1509 1968  Averatec 5110H
 		4c53 1090  Cx9 / Vx9 mainboard
-	24d0  82801EB/ER (ICH5/ICH5R) LPC Bridge
+	24d0  82801EB/ER (ICH5/ICH5R) LPC Interface Bridge
 	24d1  82801EB (ICH5) Serial ATA 150 Storage Controller
 		103c 12bc  d530 CMT (DG746A)
 		1458 24d1  GA-8IPE1000 Pro2 motherboard (865PE)
 		1462 7280  865PE Neo2 (MS-6728)
 		8086 3427  S875WP1-E mainboard
-	24d2  82801EB/ER (ICH5/ICH5R) USB UHCI #1
+		8086 524c  D865PERL mainboard
+	24d2  82801EB/ER (ICH5/ICH5R) USB UHCI Controller #1
 		103c 12bc  d530 CMT (DG746A)
 		1043 80a6  P4P800 Mainboard
+		1458 24d2  GA-8KNXP motherboard (875P)
 		1462 7280  865PE Neo2 (MS-6728)
 		8086 3427  S875WP1-E mainboard
+		8086 524c  D865PERL mainboard
 	24d3  82801EB/ER (ICH5/ICH5R) SMBus Controller
 		1043 80a6  P4P800 Mainboard
 		1458 24d2  GA-8IPE1000 Pro2 motherboard (865PE)
 		1462 7280  865PE Neo2 (MS-6728)
 		8086 3427  S875WP1-E mainboard
-	24d4  82801EB/ER (ICH5/ICH5R) USB UHCI #2
+		8086 524c  D865PERL mainboard
+	24d4  82801EB/ER (ICH5/ICH5R) USB UHCI Controller #2
 		103c 12bc  d530 CMT (DG746A)
 		1043 80a6  P4P800 Mainboard
 		1458 24d2  GA-8IPE1000 Pro2 motherboard (865PE)
 		1462 7280  865PE Neo2 (MS-6728)
 		8086 3427  S875WP1-E mainboard
+		8086 524c  D865PERL mainboard
 	24d5  82801EB/ER (ICH5/ICH5R) AC'97 Audio Controller
 		103c 12bc  Analog Devices codec [SoundMAX Integrated Digital Audio]
 		1043 80f3  P4P800 Mainboard
+		1458 a002  GA-8KNXP motherboard (875P)
 		1462 7280  865PE Neo2 (MS-6728)
+		8086 a000  D865PERL mainboard
 	24d6  82801EB/ER (ICH5/ICH5R) AC'97 Modem Controller
 	24d7  82801EB/ER (ICH5/ICH5R) USB UHCI #3
 		103c 12bc  d530 CMT (DG746A)
@@ -8163,6 +8963,7 @@
 		1458 24d2  GA-8IPE1000 Pro2 motherboard (865PE)
 		1462 7280  865PE Neo2 (MS-6728)
 		8086 3427  S875WP1-E mainboard
+		8086 524c  D865PERL mainboard
 	24db  82801EB/ER (ICH5/ICH5R) Ultra ATA 100 Storage Controller
 		103c 12bc  d530 CMT (DG746A)
 		1043 80a6  P4P800 Mainboard
@@ -8170,18 +8971,21 @@
 		1462 7280  865PE Neo2 (MS-6728)
 		1462 7580  MSI 875P
 		8086 3427  S875WP1-E mainboard
-	24dc  82801EB LPC Interface Controller
+		8086 524c  D865PERL mainboard
+	24dc  82801EB (ICH5) LPC Interface Bridge
 	24dd  82801EB/ER (ICH5/ICH5R) USB2 EHCI Controller
 		103c 12bc  d530 CMT (DG746A)
 		1043 80a6  P4P800 Mainboard
 		1458 5006  GA-8IPE1000 Pro2 motherboard (865PE)
 		1462 7280  865PE Neo2 (MS-6728)
 		8086 3427  S875WP1-E mainboard
-	24de  82801EB/ER (ICH5/ICH5R) USB UHCI #4
+		8086 524c  D865PERL mainboard
+	24de  82801EB/ER (ICH5/ICH5R) USB UHCI Controller #4
 		1043 80a6  P4P800 Mainboard
 		1458 24d2  GA-8IPE1000 Pro2 motherboard (865PE)
 		1462 7280  865PE Neo2 (MS-6728)
 		8086 3427  S875WP1-E mainboard
+		8086 524c  D865PERL mainboard
 	24df  82801EB (ICH5R) SATA (cc=RAID)
 	2500  82820 820 (Camino) Chipset Host Bridge (MCH)
 		1028 0095  Precision Workstation 220 Chipset
@@ -8203,6 +9007,7 @@
 	2541  E7500/E7501 Host RASUM Controller
 		15d9 3480  P4DP6
 		4c53 1090  Cx9 / Vx9 mainboard
+		8086 3424  SE7501HG2 Mainboard
 	2543  E7500/E7501 Hub Interface B PCI-to-PCI Bridge
 	2544  E7500/E7501 Hub Interface B RASUM Controller
 		4c53 1090  Cx9 / Vx9 mainboard
@@ -8212,6 +9017,7 @@
 	2548  E7500/E7501 Hub Interface D RASUM Controller
 	254c  E7501 Memory Controller Hub
 		4c53 1090  Cx9 / Vx9 mainboard
+		8086 3424  SE7501HG2 Mainboard
 	2550  E7505 Memory Controller Hub
 	2551  E7505/E7205 Series RAS Controller
 	2552  E7505/E7205 PCI-to-AGP Bridge
@@ -8219,6 +9025,7 @@
 	2554  E7505 Hub Interface B PCI-to-PCI Bridge RAS Controller
 	255d  E7205 Memory Controller Hub
 	2560  82845G/GL[Brookdale-G]/GE/PE DRAM Controller/Host-Hub Interface
+		1028 0126  Optiplex GX260
 		1458 2560  GA-8PE667 Ultra
 		1462 5800  845PE Max (MS-6580)
 	2561  82845G/GL[Brookdale-G]/GE/PE Host-to-AGP Bridge
@@ -8228,37 +9035,47 @@
 		1043 80f2  P4P800 Mainboard
 		1458 2570  GA-8IPE1000 Pro2 motherboard (865PE)
 	2571  82865G/PE/P PCI to AGP Controller
-	2572  82865G Integrated Graphics Device
+	2572  82865G Integrated Graphics Controller
 	2573  82865G/PE/P PCI to CSA Bridge
 	2576  82865G/PE/P Processor to I/O Memory Interface
-	2578  82875P Memory Controller Hub
+	2578  82875P/E7210 Memory Controller Hub
+		1458 2578  GA-8KNXP motherboard (875P)
 		1462 7580  MS-6758 (875P Neo)
 # Motherboard P4SCE
 		15d9 4580  Super Micro Computer Inc. P4SCE
 	2579  82875P Processor to AGP Controller
-	257b  82875P Processor to PCI to CSA Bridge
-	257e  82875P Processor to I/O Memory Interface
+	257b  82875P/E7210 Processor to PCI to CSA Bridge
+	257e  82875P/E7210 Processor to I/O Memory Interface
 	2580  915G/P/GV Processor to I/O Controller
 	2581  915G/P/GV PCI Express Root Port
-	2582  82915G Express Chipset Family Graphics Controller
-	2584  925X Memory Controller Hub
-	2585  925X PCI Express Root Port
-	2588  Server Memory Controller Hub
-	2589  Server Memory Controller Hub PCI Express Port
-	258a  Graphics Controller
-	2590  Mobile Memory Controller Hub
-	2591  Mobile Memory Controller Hub PCI Express Port
-	2592  Mobile Graphics Controller
+	2582  82915G/GV/910GL Express Chipset Family Graphics Controller
+		1028 1079  Optiplex GX280
+	2584  925X/XE Memory Controller Hub
+	2585  925X/XE PCI Express Root Port
+	2588  E7220/E7221 Memory Controller Hub
+	2589  E7220/E7221 PCI Express Root Port
+	258a  E7221 Integrated Graphics Controller
+	2590  Mobile 915GM/PM/GMS/910GML Express Processor to DRAM Controller
+	2591  Mobile 915GM/PM Express PCI Express Root Port
+	2592  Mobile 915GM/GMS/910GML Express Graphics Controller
 	25a1  6300ESB LPC Interface Controller
 	25a2  6300ESB PATA Storage Controller
+		4c53 10b0  CL9 mainboard
 	25a3  6300ESB SATA Storage Controller
+		4c53 10b0  CL9 mainboard
 	25a4  6300ESB SMBus Controller
+		4c53 10b0  CL9 mainboard
 	25a6  6300ESB AC'97 Audio Controller
+		4c53 10b0  CL9 mainboard
 	25a7  6300ESB AC'97 Modem Controller
 	25a9  6300ESB USB Universal Host Controller
+		4c53 10b0  CL9 mainboard
 	25aa  6300ESB USB Universal Host Controller
+		4c53 10b0  CL9 mainboard
 	25ab  6300ESB Watchdog Timer
+		4c53 10b0  CL9 mainboard
 	25ac  6300ESB I/O Advanced Programmable Interrupt Controller
+		4c53 10b0  CL9 mainboard
 	25ad  6300ESB USB2 Enhanced Host Controller
 	25ae  6300ESB 64-bit PCI-X Bridge
 	25b0  6300ESB SATA RAID Controller
@@ -8300,28 +9117,71 @@
 	2641  82801FBM (ICH6M) LPC Interface Bridge
 	2642  82801FW/FRW (ICH6W/ICH6RW) LPC Interface Bridge
 	2651  82801FB/FW (ICH6/ICH6W) SATA Controller
+		1028 0179  Optiplex GX280
 	2652  82801FR/FRW (ICH6R/ICH6RW) SATA Controller
 	2653  82801FBM (ICH6M) SATA Controller
 	2658  82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #1
+		1028 0179  Optiplex GX280
 	2659  82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #2
+		1028 0179  Optiplex GX280
 	265a  82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #3
+		1028 0179  Optiplex GX280
 	265b  82801FB/FBM/FR/FW/FRW (ICH6 Family) USB UHCI #4
+		1028 0179  Optiplex GX280
 	265c  82801FB/FBM/FR/FW/FRW (ICH6 Family) USB2 EHCI Controller
+		1028 0179  Optiplex GX280
 	2660  82801FB/FBM/FR/FW/FRW (ICH6 Family) PCI Express Port 1
 	2662  82801FB/FBM/FR/FW/FRW (ICH6 Family) PCI Express Port 2
 	2664  82801FB/FBM/FR/FW/FRW (ICH6 Family) PCI Express Port 3
 	2666  82801FB/FBM/FR/FW/FRW (ICH6 Family) PCI Express Port 4
 	2668  82801FB/FBM/FR/FW/FRW (ICH6 Family) High Definition Audio Controller
 	266a  82801FB/FBM/FR/FW/FRW (ICH6 Family) SMBus Controller
+		1028 0179  Optiplex GX280
 	266c  82801FB/FBM/FR/FW/FRW (ICH6 Family) LAN Controller
 	266d  82801FB/FBM/FR/FW/FRW (ICH6 Family) AC'97 Modem Controller
 	266e  82801FB/FBM/FR/FW/FRW (ICH6 Family) AC'97 Audio Controller
+		1028 0179  Optiplex GX280
 	266f  82801FB/FBM/FR/FW/FRW (ICH6 Family) IDE Controller
+	2770  Memory Controller Hub
+	2771  PCI Express Graphics Port
+	2772  Integrated Graphics Controller
+	2774  Workstation Memory Controller Hub
+	2775  PCI Express Graphics Port
+	2776  Integrated Graphics Controller
+	2778  Server Memory Controller Hub
+	2779  PCI Express Root Port
 	2782  82915G Express Chipset Family Graphics Controller
-	2792  Mobile Graphics Controller
+	2792  Mobile 915GM/GMS/910GML Express Graphics Controller
+	27b1  Mobile I/O Controller Hub LPC
+	27b8  I/O Controller Hub LPC
+	27c0  I/O Controller Hub SATA cc=IDE
+	27c1  I/O Controller Hub SATA cc=AHCI
+	27c2  I/O Controller Hub SATA cc=RAID
+	27c3  I/O Controller Hub SATA cc=RAID
+	27c4  Mobile I/O Controller Hub SATA cc=IDE
+	27c5  Mobile I/O Controller Hub SATA cc=AHCI
+	27c8  I/O Controller Hub UHCI USB #1
+	27c9  I/O Controller Hub UHCI USB #2
+	27ca  I/O Controller Hub UHCI USB #3
+	27cb  I/O Controller Hub UHCI USB #4
+	27cc  I/O Controller Hub EHCI USB
+	27d0  I/O Controller Hub PCI Express Port 1
+	27d2  I/O Controller Hub PCI Express Port 2
+	27d4  I/O Controller Hub PCI Express Port 3
+	27d6  I/O Controller Hub PCI Express Port 4
+	27d8  I/O Controller Hub High Definition Audio
+	27da  I/O Controller Hub SMBus
+	27dc  I/O Controller Hub LAN
+	27dd  I/O Controller Hub AC'97 Modem
+	27de  I/O Controller Hub AC'97 Audio
+	27df  I/O Controller Hub PATA
+	27e0  I/O Controller Hub PCI Express Port 5
+	27e2  I/O Controller Hub PCI Express Port 6
 	3092  Integrated RAID
 	3200  GD31244 PCI-X SATA HBA
 	3340  82855PM Processor to I/O Controller
+		1025 005a  TravelMate 290
+		103c 0890  NC6000 laptop
 	3341  82855PM Processor to AGP Controller
 	3575  82830 830 Chipset Host Bridge
 		1014 021d  ThinkPad A/T/X Series
@@ -8330,25 +9190,34 @@
 	3577  82830 CGC [Chipset Graphics Controller]
 		1014 0513  ThinkPad A/T/X Series
 	3578  82830 830 Chipset Host Bridge
-	3580  82852/855GM Host Bridge
-	3581  855GME GMCH Host-to-AGP Bridge (Virtual PCI-to-PCI)
+	3580  82852/82855 GM/GME/PM/GMV Processor to I/O Controller
+		1028 0163  Latitude D505
+		4c53 10b0  CL9 mainboard
+	3581  82852/82855 GM/GME/PM/GMV Processor to AGP Controller
 	3582  82852/855GM Integrated Graphics Device
-	3584  855GM/GME GMCH Memory I/O Control Registers
-	3585  855GM/GME GMCH Configuration Process Registers
-	3590  Server Memory Controller Hub
-	3591  Memory Controller Hub Error Reporting Register
-	3592  Server Memory Controller Hub
-	3593  Memory Controller Hub Error Reporting Register
-	3594  Memory Controller Hub DMA Controller
-	3595  Memory Controller Hub PCI Express Port A0
-	3596  Memory Controller Hub PCI Express Port A1
-	3597  Memory Controller Hub PCI Express Port B0
-	3598  Memory Controller Hub PCI Express Port B1
-	3599  Memory Controller Hub PCI Express Port C0
-	359a  Memory Controller Hub PCI Express Port C1
-	359b  Memory Controller Hub Extended Configuration Registers
-	359e  Workstation Memory Controller Hub
+		1028 0163  Latitude D505
+		4c53 10b0  CL9 mainboard
+	3584  82852/82855 GM/GME/PM/GMV Processor to I/O Controller
+		1028 0163  Latitude D505
+		4c53 10b0  CL9 mainboard
+	3585  82852/82855 GM/GME/PM/GMV Processor to I/O Controller
+		1028 0163  Latitude D505
+		4c53 10b0  CL9 mainboard
+	3590  E7520 Memory Controller Hub
+	3591  E7525/E7520 Error Reporting Registers
+	3592  E7320 Memory Controller Hub
+	3593  E7320 Error Reporting Registers
+	3594  E7520 DMA Controller
+	3595  E7525/E7520/E7320 PCI Express Port A
+	3596  E7525/E7520/E7320 PCI Express Port A1
+	3597  E7525/E7520 PCI Express Port B
+	3598  E7520 PCI Express Port B1
+	3599  E7520 PCI Express Port C
+	359a  E7520 PCI Express Port C1
+	359b  E7525/E7520/E7320 Extended Configuration Registers
+	359e  E7525 Memory Controller Hub
 	4220  PRO/Wireless 2200BG
+	4223  PRO/Wireless 2915ABG MiniPCI Adapter
 	5200  EtherExpress PRO/100 Intelligent Server
 	5201  EtherExpress PRO/100 Intelligent Server
 		8086 0001  EtherExpress PRO/100 Server Ethernet Adapter
@@ -8360,9 +9229,13 @@
 	7050  Intel Intercast Video Capture Card
 	7100  430TX - 82439TX MTXC
 	7110  82371AB/EB/MB PIIX4 ISA
+		15ad 1976  virtualHW v3
 	7111  82371AB/EB/MB PIIX4 IDE
+		15ad 1976  virtualHW v3
 	7112  82371AB/EB/MB PIIX4 USB
+		15ad 1976  virtualHW v3
 	7113  82371AB/EB/MB PIIX4 ACPI
+		15ad 1976  virtualHW v3
 	7120  82810 GMCH [Graphics Memory Controller Hub]
 		4c53 1040  CL7 mainboard
 		4c53 1060  PC7 mainboard
@@ -8383,6 +9256,7 @@
 		0e11 0500  Armada 1750 Laptop System Chipset
 		0e11 b110  Armada M700/E500
 		1179 0001  Toshiba Tecra 8100 Laptop System Chipset
+		15ad 1976  virtualHW v3
 		4c53 1050  CT7 mainboard
 		4c53 1051  CE7 mainboard
 	7191  440BX/ZX/DX - 82443BX/ZX/DX AGP bridge
@@ -8393,6 +9267,7 @@
 		1033 0000  Versa Note Vxi
 		4c53 10a0  CA3/CR3 mainboard
 	7195  82440MX AC'97 Audio Controller
+		1033 80cc  Versa Note VXi
 		10cf 1099  QSound_SigmaTel Stac97 PCI Audio
 		11d4 0040  SoundMAX Integrated Digital Audio
 		11d4 0048  SoundMAX Integrated Digital Audio
@@ -8430,7 +9305,7 @@
 	84e4  460GX - 84460GX Memory Data Controller (MDC)
 	84e6  460GX - 82466GX Wide and fast PCI eXpander Bridge (WXB)
 	84ea  460GX - 84460GX AGP Bridge (GXB function 1)
-	8500  IXP4xx Family  Network Processor (IXP420, 421, 422, 425 and IXC1100)
+	8500  IXP4XX Network Processor family. IXP420/IXP421/IXP422/IXP425/IXC1100
 	9000  IXP2000 Family Network Processor
 	9001  IXP2400 Network Processor
 	9004  IXP2800 Network Processor
@@ -8438,10 +9313,15 @@
 	9622  Integrated RAID
 	9641  Integrated RAID
 	96a1  Integrated RAID
+# retail verson
+	a01f  PRO/10GbE LR Server Adapter
+# OEM version
+	a11f  PRO/10GbE LR Server Adapter
 	b152  21152 PCI-to-PCI Bridge
 # observed, and documented in Intel revision note; new mask of 1011:0026
 	b154  21154 PCI-to-PCI Bridge
 	b555  21555 Non transparent PCI-to-PCI Bridge
+		12d9 000a  PCI VoIP Gateway
 		1331 0030  ENP-2611
 		4c53 1050  CT7 mainboard
 		4c53 1051  CE7 mainboard
@@ -8616,6 +9496,7 @@
 	00cf  AIC-7899P U160/m
 		1028 00ce  PowerEdge 1400
 		1028 00d1  PowerEdge 2550
+		1028 00d9  PowerEdge 2500
 		10f1 2462  Thunder K7 S2462
 		15d9 9005  Onboard SCSI Host Adapter
 		8086 3411  SDS2 Mainboard
@@ -8685,12 +9566,14 @@
 9699  Omni Media Technology Inc
 	6565  6565
 9710  NetMos Technology
+	7780  USB IRDA-port
 	9815  PCI 9815 Multi-I/O Controller
 		1000 0020  2P0S (2 port parallel adaptor)
 	9835  PCI 9835 Multi-I/O Controller
 		1000 0002  2S (16C550 UART)
 		1000 0012  1P2S
 	9845  PCI 9845 Multi-I/O Controller
+		1000 0004  0P4S (4 port 16550A serial card)
 		1000 0006  0P6S (6 port 16550a serial card)
 	9855  PCI 9855 Multi-I/O Controller
 		1000 0014  1P4S
@@ -8705,8 +9588,10 @@
 a25b  Hewlett Packard GmbH PL24-MKT
 a304  Sony
 a727  3Com Corporation
+	0013  3CRPAG175 Wireless PC Card
 aa42  Scitex Digital Video
 ac1e  Digital Receiver Technology Inc
+ac3d  Actuality Systems
 aecb  Adrienne Electronics Corporation
 b1b3  Shiva Europe Limited
 # Pinnacle should be 11bd, but they got it wrong several times --mj
diff -Nru a/drivers/pci/pcie/Kconfig b/drivers/pci/pcie/Kconfig
--- a/drivers/pci/pcie/Kconfig	2005-03-11 12:51:52 -08:00
+++ b/drivers/pci/pcie/Kconfig	2005-03-11 12:51:52 -08:00
@@ -3,7 +3,6 @@
 #
 config PCIEPORTBUS
 	bool "PCI Express support"
-	depends on PCI_GOMMCONFIG || PCI_GOANY
 	default n
 
 	---help---
diff -Nru a/drivers/pci/pcie/portdrv_pci.c b/drivers/pci/pcie/portdrv_pci.c
--- a/drivers/pci/pcie/portdrv_pci.c	2005-03-11 12:51:46 -08:00
+++ b/drivers/pci/pcie/portdrv_pci.c	2005-03-11 12:51:46 -08:00
@@ -106,7 +106,7 @@
 	int retval = 0;
 
 	pcie_port_bus_register();
-	retval = pci_module_init(&pcie_portdrv);
+	retval = pci_register_driver(&pcie_portdrv);
 	if (retval)
 		pcie_port_bus_unregister();
 	return retval;
diff -Nru a/drivers/pci/probe.c b/drivers/pci/probe.c
--- a/drivers/pci/probe.c	2005-03-11 12:51:47 -08:00
+++ b/drivers/pci/probe.c	2005-03-11 12:51:47 -08:00
@@ -64,9 +64,11 @@
 
 void pci_remove_legacy_files(struct pci_bus *b)
 {
-	class_device_remove_bin_file(&b->class_dev, b->legacy_io);
-	class_device_remove_bin_file(&b->class_dev, b->legacy_mem);
-	kfree(b->legacy_io); /* both are allocated here */
+	if (b->legacy_io) {
+		class_device_remove_bin_file(&b->class_dev, b->legacy_io);
+		class_device_remove_bin_file(&b->class_dev, b->legacy_mem);
+		kfree(b->legacy_io); /* both are allocated here */
+	}
 }
 #else /* !HAVE_PCI_LEGACY */
 static inline void pci_create_legacy_files(struct pci_bus *bus) { return; }
@@ -549,7 +551,6 @@
 {
 	u32 class;
 
-	dev->slot_name = dev->dev.bus_id;
 	sprintf(pci_name(dev), "%04x:%02x:%02x.%d", pci_domain_nr(dev->bus),
 		dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn));
 
diff -Nru a/drivers/pci/proc.c b/drivers/pci/proc.c
--- a/drivers/pci/proc.c	2005-03-11 12:51:47 -08:00
+++ b/drivers/pci/proc.c	2005-03-11 12:51:47 -08:00
@@ -384,26 +384,32 @@
 int pci_proc_attach_device(struct pci_dev *dev)
 {
 	struct pci_bus *bus = dev->bus;
-	struct proc_dir_entry *de, *e;
+	struct proc_dir_entry *e;
 	char name[16];
 
 	if (!proc_initialized)
 		return -EACCES;
 
-	if (!(de = bus->procdir)) {
-		if (pci_name_bus(name, bus))
-			return -EEXIST;
-		de = bus->procdir = proc_mkdir(name, proc_bus_pci_dir);
-		if (!de)
+	if (!bus->procdir) {
+		if (pci_proc_domain(bus)) {
+			sprintf(name, "%04x:%02x", pci_domain_nr(bus),
+					bus->number);
+		} else {
+			sprintf(name, "%02x", bus->number);
+		}
+		bus->procdir = proc_mkdir(name, proc_bus_pci_dir);
+		if (!bus->procdir)
 			return -ENOMEM;
 	}
+
 	sprintf(name, "%02x.%x", PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn));
-	e = dev->procent = create_proc_entry(name, S_IFREG | S_IRUGO | S_IWUSR, de);
+	e = create_proc_entry(name, S_IFREG | S_IRUGO | S_IWUSR, bus->procdir);
 	if (!e)
 		return -ENOMEM;
 	e->proc_fops = &proc_bus_pci_operations;
 	e->data = dev;
 	e->size = dev->cfg_size;
+	dev->procent = e;
 
 	return 0;
 }
diff -Nru a/drivers/pci/quirks.c b/drivers/pci/quirks.c
--- a/drivers/pci/quirks.c	2005-03-11 12:51:41 -08:00
+++ b/drivers/pci/quirks.c	2005-03-11 12:51:41 -08:00
@@ -429,6 +429,8 @@
 }
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_SI,	PCI_ANY_ID,			quirk_ioapic_rmw );
 
+int pci_msi_quirk;
+
 #define AMD8131_revA0        0x01
 #define AMD8131_revB0        0x11
 #define AMD8131_MISC         0x40
@@ -437,6 +439,9 @@
 { 
         unsigned char revid, tmp;
         
+	pci_msi_quirk = 1;
+	printk(KERN_WARNING "PCI: MSI quirk detected. pci_msi_quirk set.\n");
+
         if (nr_ioapics == 0) 
                 return;
 
@@ -786,6 +791,7 @@
 			}
 		if (dev->device == PCI_DEVICE_ID_INTEL_82855PM_HB)
 			switch (dev->subsystem_device) {
+			case 0x184b: /* W1N notebook */
 			case 0x186a: /* M6Ne notebook */
 				asus_hides_smbus = 1;
 			}
@@ -801,6 +807,18 @@
 			case 0x12bc: /* HP D330L */
 				asus_hides_smbus = 1;
 			}
+	} else if (unlikely(dev->subsystem_vendor == PCI_VENDOR_ID_TOSHIBA)) {
+		if (dev->device == PCI_DEVICE_ID_INTEL_82855GM_HB)
+			switch(dev->subsystem_device) {
+			case 0x0001: /* Toshiba Satellite A40 */
+				asus_hides_smbus = 1;
+			}
+       } else if (unlikely(dev->subsystem_vendor == PCI_VENDOR_ID_SAMSUNG)) {
+               if (dev->device ==  PCI_DEVICE_ID_INTEL_82855PM_HB)
+                       switch(dev->subsystem_device) {
+                       case 0xC00C: /* Samsung P35 notebook */
+                               asus_hides_smbus = 1;
+                       }
 	}
 }
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82845_HB,	asus_hides_smbus_hostbridge );
diff -Nru a/drivers/pci/setup-res.c b/drivers/pci/setup-res.c
--- a/drivers/pci/setup-res.c	2005-03-11 12:51:51 -08:00
+++ b/drivers/pci/setup-res.c	2005-03-11 12:51:51 -08:00
@@ -86,11 +86,11 @@
 	}
 	res->flags &= ~IORESOURCE_UNSET;
 	DBGC((KERN_INFO "PCI: moved device %s resource %d (%lx) to %x\n",
-		dev->slot_name, resno, res->flags,
+		pci_name(dev), resno, res->flags,
 		new & ~PCI_REGION_FLAG_MASK));
 }
 
-int __init
+int __devinit
 pci_claim_resource(struct pci_dev *dev, int resource)
 {
 	struct resource *res = &dev->resource[resource];
diff -Nru a/drivers/pcmcia/pxa2xx_sharpsl.c b/drivers/pcmcia/pxa2xx_sharpsl.c
--- a/drivers/pcmcia/pxa2xx_sharpsl.c	2005-03-11 12:51:51 -08:00
+++ b/drivers/pcmcia/pxa2xx_sharpsl.c	2005-03-11 12:51:51 -08:00
@@ -38,7 +38,7 @@
 
 static void sharpsl_pcmcia_init_reset(void)
 {
-	reset_scoop();
+	reset_scoop(&corgiscoop_device.dev);
 	keep_vs = NO_KEEP_VS;
 	keep_rd = 0;
 }
@@ -79,8 +79,8 @@
 	}
 
 	/* Enable interrupt */
-	write_scoop_reg(SCOOP_IMR, 0x00C0);
-	write_scoop_reg(SCOOP_MCR, 0x0101);
+	write_scoop_reg(&corgiscoop_device.dev, SCOOP_IMR, 0x00C0);
+	write_scoop_reg(&corgiscoop_device.dev, SCOOP_MCR, 0x0101);
 	keep_vs = NO_KEEP_VS;
 
 	skt->irq = CORGI_IRQ_GPIO_CF_IRQ;
@@ -102,30 +102,30 @@
 {
 	unsigned short cpr, csr;
 
-	cpr = read_scoop_reg(SCOOP_CPR);
+	cpr = read_scoop_reg(&corgiscoop_device.dev, SCOOP_CPR);
 
-	write_scoop_reg(SCOOP_IRM, 0x00FF);
-	write_scoop_reg(SCOOP_ISR, 0x0000);
-	write_scoop_reg(SCOOP_IRM, 0x0000);
-	csr = read_scoop_reg(SCOOP_CSR);
+	write_scoop_reg(&corgiscoop_device.dev, SCOOP_IRM, 0x00FF);
+	write_scoop_reg(&corgiscoop_device.dev, SCOOP_ISR, 0x0000);
+	write_scoop_reg(&corgiscoop_device.dev, SCOOP_IRM, 0x0000);
+	csr = read_scoop_reg(&corgiscoop_device.dev, SCOOP_CSR);
 	if (csr & 0x0004) {
 		/* card eject */
-		write_scoop_reg(SCOOP_CDR, 0x0000);
+		write_scoop_reg(&corgiscoop_device.dev, SCOOP_CDR, 0x0000);
 		keep_vs = NO_KEEP_VS;
 	}
 	else if (!(keep_vs & NO_KEEP_VS)) {
 		/* keep vs1,vs2 */
-		write_scoop_reg(SCOOP_CDR, 0x0000);
+		write_scoop_reg(&corgiscoop_device.dev, SCOOP_CDR, 0x0000);
 		csr |= keep_vs;
 	}
 	else if (cpr & 0x0003) {
 		/* power on */
-		write_scoop_reg(SCOOP_CDR, 0x0000);
+		write_scoop_reg(&corgiscoop_device.dev, SCOOP_CDR, 0x0000);
 		keep_vs = (csr & 0x00C0);
 	}
 	else {
 		/* card detect */
-		write_scoop_reg(SCOOP_CDR, 0x0002);
+		write_scoop_reg(&corgiscoop_device.dev, SCOOP_CDR, 0x0002);
 	}
 
 	state->detect = (csr & 0x0004) ? 0 : 1;
@@ -166,10 +166,10 @@
 
 	local_irq_save(flags);
 
-	nmcr = (mcr = read_scoop_reg(SCOOP_MCR)) & ~0x0010;
-	ncpr = (cpr = read_scoop_reg(SCOOP_CPR)) & ~0x0083;
-	nccr = (ccr = read_scoop_reg(SCOOP_CCR)) & ~0x0080;
-	nimr = (imr = read_scoop_reg(SCOOP_IMR)) & ~0x003E;
+	nmcr = (mcr = read_scoop_reg(&corgiscoop_device.dev, SCOOP_MCR)) & ~0x0010;
+	ncpr = (cpr = read_scoop_reg(&corgiscoop_device.dev, SCOOP_CPR)) & ~0x0083;
+	nccr = (ccr = read_scoop_reg(&corgiscoop_device.dev, SCOOP_CCR)) & ~0x0080;
+	nimr = (imr = read_scoop_reg(&corgiscoop_device.dev, SCOOP_IMR)) & ~0x003E;
 
 	ncpr |= (state->Vcc == 33) ? 0x0001 :
 				(state->Vcc == 50) ? 0x0002 : 0;
@@ -193,13 +193,13 @@
 	}
 
 	if (mcr != nmcr)
-		write_scoop_reg(SCOOP_MCR, nmcr);
+		write_scoop_reg(&corgiscoop_device.dev, SCOOP_MCR, nmcr);
 	if (cpr != ncpr)
-		write_scoop_reg(SCOOP_CPR, ncpr);
+		write_scoop_reg(&corgiscoop_device.dev, SCOOP_CPR, ncpr);
 	if (ccr != nccr)
-		write_scoop_reg(SCOOP_CCR, nccr);
+		write_scoop_reg(&corgiscoop_device.dev, SCOOP_CCR, nccr);
 	if (imr != nimr)
-		write_scoop_reg(SCOOP_IMR, nimr);
+		write_scoop_reg(&corgiscoop_device.dev, SCOOP_IMR, nimr);
 
 	local_irq_restore(flags);
 
diff -Nru a/drivers/pcmcia/yenta_socket.c b/drivers/pcmcia/yenta_socket.c
--- a/drivers/pcmcia/yenta_socket.c	2005-03-11 12:51:47 -08:00
+++ b/drivers/pcmcia/yenta_socket.c	2005-03-11 12:51:47 -08:00
@@ -963,7 +963,7 @@
 	 * the irq stuff...
 	 */
 	printk(KERN_INFO "Yenta: CardBus bridge found at %s [%04x:%04x]\n",
-		dev->slot_name, dev->subsystem_vendor, dev->subsystem_device);
+		pci_name(dev), dev->subsystem_vendor, dev->subsystem_device);
 
 	yenta_config_init(socket);
 
diff -Nru a/drivers/s390/char/keyboard.c b/drivers/s390/char/keyboard.c
--- a/drivers/s390/char/keyboard.c	2005-03-11 12:51:42 -08:00
+++ b/drivers/s390/char/keyboard.c	2005-03-11 12:51:42 -08:00
@@ -32,11 +32,11 @@
 static k_handler_fn *k_handler[16] = { K_HANDLERS };
 
 /* maximum values each key_handler can handle */
-static const int max_vals[] = {
+static const int kbd_max_vals[] = {
 	255, ARRAY_SIZE(func_table) - 1, NR_FN_HANDLER - 1, 0,
 	NR_DEAD - 1, 0, 0, 0, 0, 0, 0, 0, 0, 0
 };
-static const int NR_TYPES = ARRAY_SIZE(max_vals);
+static const int KBD_NR_TYPES = ARRAY_SIZE(kbd_max_vals);
 
 static unsigned char ret_diacr[NR_DEAD] = {
 	'`', '\'', '^', '~', '"', ','
@@ -360,7 +360,7 @@
 		key_map = kbd->key_maps[tmp.kb_table];
 		if (key_map) {
 		    val = U(key_map[tmp.kb_index]);
-		    if (KTYP(val) >= NR_TYPES)
+		    if (KTYP(val) >= KBD_NR_TYPES)
 			val = K_HOLE;
 		} else
 		    val = (tmp.kb_index ? K_HOLE : K_NOSUCHMAP);
@@ -378,9 +378,9 @@
 			break;
 		}
 
-		if (KTYP(tmp.kb_value) >= NR_TYPES)
+		if (KTYP(tmp.kb_value) >= KBD_NR_TYPES)
 			return -EINVAL;
-		if (KVAL(tmp.kb_value) > max_vals[KTYP(tmp.kb_value)])
+		if (KVAL(tmp.kb_value) > kbd_max_vals[KTYP(tmp.kb_value)])
 			return -EINVAL;
 
 		if (!(key_map = kbd->key_maps[tmp.kb_table])) {
diff -Nru a/drivers/s390/char/sclp_quiesce.c b/drivers/s390/char/sclp_quiesce.c
--- a/drivers/s390/char/sclp_quiesce.c	2005-03-11 12:51:52 -08:00
+++ b/drivers/s390/char/sclp_quiesce.c	2005-03-11 12:51:52 -08:00
@@ -30,31 +30,16 @@
 {
 	static atomic_t cpuid = ATOMIC_INIT(-1);
 	psw_t quiesce_psw;
-	__u32 status;
-	int i;
+	int cpu;
 
 	if (atomic_compare_and_swap(-1, smp_processor_id(), &cpuid))
 		signal_processor(smp_processor_id(), sigp_stop);
 	/* Wait for all other cpus to enter stopped state */
-	i = 1;
-	while (i < NR_CPUS) {
-		if (!cpu_online(i)) {
-			i++;
+	for_each_online_cpu(cpu) {
+		if (cpu == smp_processor_id())
 			continue;
-		}
-		switch (signal_processor_ps(&status, 0, i, sigp_sense)) {
-		case sigp_order_code_accepted:
-		case sigp_status_stored:
-			/* Check for stopped and check stop state */
-			if (status & 0x50)
-				i++;
-			break;
-		case sigp_busy:
-			break;
-		case sigp_not_operational:
-			i++;
-			break;
-		}
+		while(!smp_cpu_not_running(cpu))
+			cpu_relax();
 	}
 	/* Quiesce the last cpu with the special psw */
 	quiesce_psw.mask = PSW_BASE_BITS | PSW_MASK_WAIT;
diff -Nru a/drivers/s390/cio/chsc.c b/drivers/s390/cio/chsc.c
--- a/drivers/s390/cio/chsc.c	2005-03-11 12:51:46 -08:00
+++ b/drivers/s390/cio/chsc.c	2005-03-11 12:51:46 -08:00
@@ -1,7 +1,7 @@
 /*
  *  drivers/s390/cio/chsc.c
  *   S/390 common I/O routines -- channel subsystem call
- *   $Revision: 1.115 $
+ *   $Revision: 1.118 $
  *
  *    Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH,
  *			      IBM Corporation
@@ -423,12 +423,12 @@
 			     sch->schib.pmcw.pam &
 			     sch->schib.pmcw.pom)
 			    | chp_mask) & sch->opm;
-		spin_unlock_irq(&sch->lock);
 		if (!old_lpm && sch->lpm)
 			device_trigger_reprobe(sch);
 		else if (sch->driver && sch->driver->verify)
 			sch->driver->verify(&sch->dev);
 
+		spin_unlock_irq(&sch->lock);
 		put_device(&sch->dev);
 		if (fla_mask != 0)
 			break;
@@ -703,6 +703,9 @@
 {
 	int cc;
 
+	if (!device_is_online(sch))
+		/* cio could be doing I/O. */
+		return 0;
 	cc = stsch(sch->irq, &sch->schib);
 	if (cc)
 		return 0;
@@ -717,10 +720,12 @@
 __s390_subchannel_vary_chpid(struct subchannel *sch, __u8 chpid, int on)
 {
 	int chp, old_lpm;
+	unsigned long flags;
 
 	if (!sch->ssd_info.valid)
 		return;
 	
+	spin_lock_irqsave(&sch->lock, flags);
 	old_lpm = sch->lpm;
 	for (chp = 0; chp < 8; chp++) {
 		if (sch->ssd_info.chpid[chp] != chpid)
@@ -751,6 +756,7 @@
 		}
 		break;
 	}
+	spin_unlock_irqrestore(&sch->lock, flags);
 }
 
 static int
diff -Nru a/drivers/s390/cio/chsc.h b/drivers/s390/cio/chsc.h
--- a/drivers/s390/cio/chsc.h	2005-03-11 12:51:50 -08:00
+++ b/drivers/s390/cio/chsc.h	2005-03-11 12:51:50 -08:00
@@ -18,8 +18,6 @@
 	struct device dev;
 };
 
-extern struct channel_path *chps[];
-
 extern void s390_process_css( void );
 extern void chsc_validate_chpids(struct subchannel *);
 extern void chpid_is_actually_online(int);
diff -Nru a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c
--- a/drivers/s390/cio/css.c	2005-03-11 12:51:52 -08:00
+++ b/drivers/s390/cio/css.c	2005-03-11 12:51:52 -08:00
@@ -1,7 +1,7 @@
 /*
  *  drivers/s390/cio/css.c
  *  driver for channel subsystem
- *   $Revision: 1.84 $
+ *   $Revision: 1.85 $
  *
  *    Copyright (C) 2002 IBM Deutschland Entwicklung GmbH,
  *			 IBM Corporation
@@ -180,6 +180,7 @@
 {
 	int event, ret, disc;
 	struct subchannel *sch;
+	unsigned long flags;
 
 	sch = get_subchannel_by_schid(irq);
 	disc = sch ? device_is_disconnected(sch) : 0;
@@ -221,7 +222,9 @@
 			 * coming operational again. It won't do harm in real
 			 * no path situations.
 			 */
+			spin_lock_irqsave(&sch->lock, flags);
 			device_trigger_reprobe(sch);
+			spin_unlock_irqrestore(&sch->lock, flags);
 			ret = 0;
 			break;
 		}
@@ -262,14 +265,19 @@
 			 * We can't immediately deregister the disconnected
 			 * device since it might block.
 			 */
+			spin_lock_irqsave(&sch->lock, flags);
 			device_trigger_reprobe(sch);
+			spin_unlock_irqrestore(&sch->lock, flags);
 			ret = 0;
 		}
 		break;
 	case CIO_OPER:
-		if (disc)
+		if (disc) {
+			spin_lock_irqsave(&sch->lock, flags);
 			/* Get device operational again. */
 			device_trigger_reprobe(sch);
+			spin_unlock_irqrestore(&sch->lock, flags);
+		}
 		ret = sch ? 0 : css_probe_device(irq);
 		break;
 	default:
diff -Nru a/drivers/s390/cio/css.h b/drivers/s390/cio/css.h
--- a/drivers/s390/cio/css.h	2005-03-11 12:51:52 -08:00
+++ b/drivers/s390/cio/css.h	2005-03-11 12:51:52 -08:00
@@ -84,6 +84,7 @@
 		unsigned int doverify:1;    /* delayed path verification */
 		unsigned int donotify:1;    /* call notify function */
 		unsigned int recog_done:1;  /* dev. recog. complete */
+		unsigned int fake_irb:1;    /* deliver faked irb */
 	} __attribute__((packed)) flags;
 	unsigned long intparm;	/* user interruption parameter */
 	struct qdio_irq *qdio_data;
@@ -136,6 +137,7 @@
 void device_trigger_reprobe(struct subchannel *);
 
 /* Helper functions for vary on/off. */
+int device_is_online(struct subchannel *);
 void device_set_waiting(struct subchannel *);
 
 /* Machine check helper function. */
diff -Nru a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c
--- a/drivers/s390/cio/device.c	2005-03-11 12:51:47 -08:00
+++ b/drivers/s390/cio/device.c	2005-03-11 12:51:47 -08:00
@@ -1,7 +1,7 @@
 /*
  *  drivers/s390/cio/device.c
  *  bus driver for ccw devices
- *   $Revision: 1.129 $
+ *   $Revision: 1.131 $
  *
  *    Copyright (C) 2002 IBM Deutschland Entwicklung GmbH,
  *			 IBM Corporation
@@ -293,6 +293,14 @@
 	cdev->online = 0;
 	spin_lock_irq(cdev->ccwlock);
 	ret = ccw_device_offline(cdev);
+	if (ret == -ENODEV) {
+		if (cdev->private->state != DEV_STATE_NOT_OPER) {
+			cdev->private->state = DEV_STATE_OFFLINE;
+			dev_fsm_event(cdev, DEV_EVENT_NOTOPER);
+		}
+		spin_unlock_irq(cdev->ccwlock);
+		return ret;
+	}
 	spin_unlock_irq(cdev->ccwlock);
 	if (ret == 0)
 		wait_event(cdev->private->wait_q, dev_fsm_final_state(cdev));
diff -Nru a/drivers/s390/cio/device_fsm.c b/drivers/s390/cio/device_fsm.c
--- a/drivers/s390/cio/device_fsm.c	2005-03-11 12:51:46 -08:00
+++ b/drivers/s390/cio/device_fsm.c	2005-03-11 12:51:46 -08:00
@@ -24,6 +24,17 @@
 #include "qdio.h"
 
 int
+device_is_online(struct subchannel *sch)
+{
+	struct ccw_device *cdev;
+
+	if (!sch->dev.driver_data)
+		return 0;
+	cdev = sch->dev.driver_data;
+	return (cdev->private->state == DEV_STATE_ONLINE);
+}
+
+int
 device_is_disconnected(struct subchannel *sch)
 {
 	struct ccw_device *cdev;
@@ -44,6 +55,7 @@
 		return;
 	cdev = sch->dev.driver_data;
 	ccw_device_set_timeout(cdev, 0);
+	cdev->private->flags.fake_irb = 0;
 	cdev->private->state = DEV_STATE_DISCONNECTED;
 }
 
@@ -474,6 +486,7 @@
 	} else {
 		cio_disable_subchannel(sch);
 		ccw_device_set_timeout(cdev, 0);
+		cdev->private->flags.fake_irb = 0;
 		cdev->private->state = DEV_STATE_DISCONNECTED;
 		wake_up(&cdev->private->wait_q);
 	}
@@ -488,6 +501,21 @@
 		cdev->private->options.pgroup = 0;
 	case 0:
 		ccw_device_done(cdev, DEV_STATE_ONLINE);
+		/* Deliver fake irb to device driver, if needed. */
+		if (cdev->private->flags.fake_irb) {
+			memset(&cdev->private->irb, 0, sizeof(struct irb));
+			cdev->private->irb.scsw = (struct scsw) {
+				.cc = 1,
+				.fctl = SCSW_FCTL_START_FUNC,
+				.actl = SCSW_ACTL_START_PEND,
+				.stctl = SCSW_STCTL_STATUS_PEND,
+			};
+			cdev->private->flags.fake_irb = 0;
+			if (cdev->handler)
+				cdev->handler(cdev, cdev->private->intparm,
+					      &cdev->private->irb);
+			memset(&cdev->private->irb, 0, sizeof(struct irb));
+		}
 		break;
 	case -ETIME:
 		ccw_device_done(cdev, DEV_STATE_BOXED);
@@ -560,6 +588,8 @@
 	struct subchannel *sch;
 
 	sch = to_subchannel(cdev->dev.parent);
+	if (stsch(sch->irq, &sch->schib) || !sch->schib.pmcw.dnv)
+		return -ENODEV;
 	if (cdev->private->state != DEV_STATE_ONLINE) {
 		if (sch->schib.scsw.actl != 0)
 			return -EBUSY;
@@ -637,6 +667,7 @@
 	if (sch->driver->notify &&
 	    sch->driver->notify(&sch->dev, sch->lpm ? CIO_GONE : CIO_NO_PATH)) {
 			ccw_device_set_timeout(cdev, 0);
+			cdev->private->flags.fake_irb = 0;
 			cdev->private->state = DEV_STATE_DISCONNECTED;
 			wake_up(&cdev->private->wait_q);
 			return;
@@ -668,6 +699,12 @@
 		return;
 	}
 	sch = to_subchannel(cdev->dev.parent);
+	/*
+	 * Since we might not just be coming from an interrupt from the
+	 * subchannel we have to update the schib.
+	 */
+	stsch(sch->irq, &sch->schib);
+
 	if (sch->schib.scsw.actl != 0 ||
 	    (cdev->private->irb.scsw.stctl & SCSW_STCTL_STATUS_PEND)) {
 		/*
@@ -982,21 +1019,17 @@
 device_trigger_reprobe(struct subchannel *sch)
 {
 	struct ccw_device *cdev;
-	unsigned long flags;
 
 	if (!sch->dev.driver_data)
 		return;
 	cdev = sch->dev.driver_data;
-	spin_lock_irqsave(&sch->lock, flags);
-	if (cdev->private->state != DEV_STATE_DISCONNECTED) {
-		spin_unlock_irqrestore(&sch->lock, flags);
+	if (cdev->private->state != DEV_STATE_DISCONNECTED)
 		return;
-	}
+
 	/* Update some values. */
-	if (stsch(sch->irq, &sch->schib)) {
-		spin_unlock_irqrestore(&sch->lock, flags);
+	if (stsch(sch->irq, &sch->schib))
 		return;
-	}
+
 	/*
 	 * The pim, pam, pom values may not be accurate, but they are the best
 	 * we have before performing device selection :/
@@ -1014,7 +1047,6 @@
 	sch->schib.pmcw.intparm = (__u32)(unsigned long)sch;
 	/* We should also udate ssd info, but this has to wait. */
 	ccw_device_start_id(cdev, 0);
-	spin_unlock_irqrestore(&sch->lock, flags);
 }
 
 static void
diff -Nru a/drivers/s390/cio/device_id.c b/drivers/s390/cio/device_id.c
--- a/drivers/s390/cio/device_id.c	2005-03-11 12:51:40 -08:00
+++ b/drivers/s390/cio/device_id.c	2005-03-11 12:51:40 -08:00
@@ -316,6 +316,7 @@
 	if (ccw_device_accumulate_and_sense(cdev, irb) != 0)
 		return;
 	ret = ccw_device_check_sense_id(cdev);
+	memset(&cdev->private->irb, 0, sizeof(struct irb));
 	switch (ret) {
 	/* 0, -ETIME, -EOPNOTSUPP, -EAGAIN or -EACCES */
 	case 0:			/* Sense id succeeded. */
diff -Nru a/drivers/s390/cio/device_ops.c b/drivers/s390/cio/device_ops.c
--- a/drivers/s390/cio/device_ops.c	2005-03-11 12:51:52 -08:00
+++ b/drivers/s390/cio/device_ops.c	2005-03-11 12:51:52 -08:00
@@ -1,7 +1,7 @@
 /*
  *  drivers/s390/cio/device_ops.c
  *
- *   $Revision: 1.53 $
+ *   $Revision: 1.55 $
  *
  *    Copyright (C) 2002 IBM Deutschland Entwicklung GmbH,
  *			 IBM Corporation
@@ -81,6 +81,16 @@
 		return -ENODEV;
 	if (cdev->private->state == DEV_STATE_NOT_OPER)
 		return -ENODEV;
+	if (cdev->private->state == DEV_STATE_VERIFY) {
+		/* Remember to fake irb when finished. */
+		if (!cdev->private->flags.fake_irb) {
+			cdev->private->flags.fake_irb = 1;
+			cdev->private->intparm = intparm;
+			return 0;
+		} else
+			/* There's already a fake I/O around. */
+			return -EBUSY;
+	}
 	if (cdev->private->state != DEV_STATE_ONLINE ||
 	    ((sch->schib.scsw.stctl & SCSW_STCTL_PRIM_STATUS) &&
 	     !(sch->schib.scsw.stctl & SCSW_STCTL_SEC_STATUS)) ||
diff -Nru a/drivers/s390/cio/device_pgid.c b/drivers/s390/cio/device_pgid.c
--- a/drivers/s390/cio/device_pgid.c	2005-03-11 12:51:46 -08:00
+++ b/drivers/s390/cio/device_pgid.c	2005-03-11 12:51:46 -08:00
@@ -156,7 +156,9 @@
 	if (ccw_device_accumulate_and_sense(cdev, irb) != 0)
 		return;
 	sch = to_subchannel(cdev->dev.parent);
-	switch (__ccw_device_check_sense_pgid(cdev)) {
+	ret = __ccw_device_check_sense_pgid(cdev);
+	memset(&cdev->private->irb, 0, sizeof(struct irb));
+	switch (ret) {
 	/* 0, -ETIME, -EOPNOTSUPP, -EAGAIN, -EACCES or -EUSERS */
 	case 0:			/* Sense Path Group ID successful. */
 		if (cdev->private->pgid.inf.ps.state1 == SNID_STATE1_RESET)
@@ -307,6 +309,7 @@
 {
 	struct subchannel *sch;
 	struct irb *irb;
+	int ret;
 
 	irb = (struct irb *) __LC_IRB;
 	/* Retry set pgid for cc=1. */
@@ -319,7 +322,9 @@
 	if (ccw_device_accumulate_and_sense(cdev, irb) != 0)
 		return;
 	sch = to_subchannel(cdev->dev.parent);
-	switch (__ccw_device_check_pgid(cdev)) {
+	ret = __ccw_device_check_pgid(cdev);
+	memset(&cdev->private->irb, 0, sizeof(struct irb));
+	switch (ret) {
 	/* 0, -ETIME, -EAGAIN, -EOPNOTSUPP or -EACCES */
 	case 0:
 		/* Establish or Resign Path Group done. Update vpm. */
@@ -405,6 +410,7 @@
 		return;
 	sch = to_subchannel(cdev->dev.parent);
 	ret = __ccw_device_check_pgid(cdev);
+	memset(&cdev->private->irb, 0, sizeof(struct irb));
 	switch (ret) {
 	/* 0, -ETIME, -EAGAIN, -EOPNOTSUPP or -EACCES */
 	case 0:			/* disband successful. */
diff -Nru a/drivers/s390/crypto/z90main.c b/drivers/s390/crypto/z90main.c
--- a/drivers/s390/crypto/z90main.c	2005-03-11 12:51:40 -08:00
+++ b/drivers/s390/crypto/z90main.c	2005-03-11 12:51:40 -08:00
@@ -2657,8 +2657,8 @@
 
 	/**
 	 * we use workavail = 2 to ensure 2 passes with nothing dequeued before
-	 * exiting the loop. If pendingq_count == 0 after the loop, there is no
-	 * work remaining on the queues.
+	 * exiting the loop. If (pendingq_count+requestq_count) == 0 after the
+	 * loop, there is no work remaining on the queues.
 	 */
 	resp_addr = 0;
 	workavail = 2;
@@ -2697,7 +2697,7 @@
 		spin_unlock_irq(&queuespinlock);
 	}
 
-	if (pendingq_count)
+	if (pendingq_count + requestq_count)
 		z90crypt_schedule_reader_timer();
 }
 
diff -Nru a/drivers/s390/net/ctcmain.c b/drivers/s390/net/ctcmain.c
--- a/drivers/s390/net/ctcmain.c	2005-03-11 12:51:52 -08:00
+++ b/drivers/s390/net/ctcmain.c	2005-03-11 12:51:52 -08:00
@@ -1,5 +1,5 @@
 /*
- * $Id: ctcmain.c,v 1.68 2004/12/27 09:25:27 heicarst Exp $
+ * $Id: ctcmain.c,v 1.69 2005/02/27 19:46:44 ptiedem Exp $
  *
  * CTC / ESCON network driver
  *
@@ -7,6 +7,7 @@
  * Author(s): Fritz Elfert (elfert@de.ibm.com, felfert@millenux.com)
  * Fixes by : Jochen Röhrig (roehrig@de.ibm.com)
  *            Arnaldo Carvalho de Melo <acme@conectiva.com.br>
+	      Peter Tiedemann (ptiedem@de.ibm.com)
  * Driver Model stuff by : Cornelia Huck <cohuck@de.ibm.com>
  *
  * Documentation used:
@@ -36,7 +37,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * RELEASE-TAG: CTC/ESCON network driver $Revision: 1.68 $
+ * RELEASE-TAG: CTC/ESCON network driver $Revision: 1.69 $
  *
  */
 
@@ -1894,13 +1895,15 @@
 		return -1;
 	}
 	memset(ch, 0, sizeof (struct channel));
-	if ((ch->ccw = (struct ccw1 *) kmalloc(sizeof (struct ccw1) * 8,
+	if ((ch->ccw = (struct ccw1 *) kmalloc(8*sizeof(struct ccw1),
 					       GFP_KERNEL | GFP_DMA)) == NULL) {
 		kfree(ch);
 		ctc_pr_warn("ctc: Out of memory in add_channel\n");
 		return -1;
 	}
 
+	memset(ch->ccw, 0, 8*sizeof(struct ccw1));	// assure all flags and counters are reset
+
 	/**
 	 * "static" ccws are used in the following way:
 	 *
@@ -1914,21 +1917,17 @@
 	 *           4: write (idal allocated on every write).
 	 *           5: nop
 	 * ccw[6..7] (Channel program for initial channel setup):
-	 *           3: set extended mode
-	 *           4: nop
+	 *           6: set extended mode
+	 *           7: nop
 	 *
 	 * ch->ccw[0..5] are initialized in ch_action_start because
 	 * the channel's direction is yet unknown here.
 	 */
 	ch->ccw[6].cmd_code = CCW_CMD_SET_EXTENDED;
 	ch->ccw[6].flags = CCW_FLAG_SLI;
-	ch->ccw[6].count = 0;
-	ch->ccw[6].cda = 0;
 
 	ch->ccw[7].cmd_code = CCW_CMD_NOOP;
 	ch->ccw[7].flags = CCW_FLAG_SLI;
-	ch->ccw[7].count = 0;
-	ch->ccw[7].cda = 0;
 
 	ch->cdev = cdev;
 	snprintf(ch->id, CTC_ID_SIZE, "ch-%s", cdev->dev.bus_id);
@@ -1955,7 +1954,7 @@
 	memset(ch->irb, 0, sizeof (struct irb));
 	while (*c && less_than((*c)->id, ch->id))
 		c = &(*c)->next;
-	if (!strncmp((*c)->id, ch->id, CTC_ID_SIZE)) {
+	if (*c && (!strncmp((*c)->id, ch->id, CTC_ID_SIZE))) {
 		ctc_pr_debug(
 			"ctc: add_channel: device %s already in list, "
 			"using old entry\n", (*c)->id);
@@ -2011,6 +2010,8 @@
 				dev_kfree_skb(ch->trans_skb);
 			}
 			kfree(ch->ccw);
+			kfree(ch->irb);
+			kfree(ch);
 			return;
 		}
 		c = &((*c)->next);
diff -Nru a/drivers/s390/net/iucv.c b/drivers/s390/net/iucv.c
--- a/drivers/s390/net/iucv.c	2005-03-11 12:51:41 -08:00
+++ b/drivers/s390/net/iucv.c	2005-03-11 12:51:41 -08:00
@@ -1,5 +1,5 @@
 /* 
- * $Id: iucv.c,v 1.42 2005/01/07 10:49:54 braunu Exp $
+ * $Id: iucv.c,v 1.43 2005/02/09 14:47:43 braunu Exp $
  *
  * IUCV network driver
  *
@@ -29,7 +29,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * RELEASE-TAG: IUCV lowlevel driver $Revision: 1.42 $
+ * RELEASE-TAG: IUCV lowlevel driver $Revision: 1.43 $
  *
  */
 
@@ -355,7 +355,7 @@
 static void
 iucv_banner(void)
 {
-	char vbuf[] = "$Revision: 1.42 $";
+	char vbuf[] = "$Revision: 1.43 $";
 	char *version = vbuf;
 
 	if ((version = strchr(version, ':'))) {
@@ -2525,7 +2525,7 @@
 	return;
 }
 
-module_init(iucv_init);
+subsys_initcall(iucv_init);
 module_exit(iucv_exit);
 
 /**
diff -Nru a/drivers/s390/net/qeth_main.c b/drivers/s390/net/qeth_main.c
--- a/drivers/s390/net/qeth_main.c	2005-03-11 12:51:52 -08:00
+++ b/drivers/s390/net/qeth_main.c	2005-03-11 12:51:52 -08:00
@@ -1,6 +1,6 @@
 /*
  *
- * linux/drivers/s390/net/qeth_main.c ($Revision: 1.191 $)
+ * linux/drivers/s390/net/qeth_main.c ($Revision: 1.203 $)
  *
  * Linux on zSeries OSA Express and HiperSockets support
  *
@@ -12,7 +12,7 @@
  *			  Frank Pavlic (pavlic@de.ibm.com) and
  *		 	  Thomas Spatzier <tspat@de.ibm.com>
  *
- *    $Revision: 1.191 $	 $Date: 2005/01/31 13:13:57 $
+ *    $Revision: 1.203 $	 $Date: 2005/03/02 15:53:57 $
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -77,7 +77,7 @@
 #include "qeth_mpc.h"
 #include "qeth_fs.h"
 
-#define VERSION_QETH_C "$Revision: 1.191 $"
+#define VERSION_QETH_C "$Revision: 1.203 $"
 static const char *version = "qeth S/390 OSA-Express driver";
 
 /**
@@ -1631,10 +1631,7 @@
 				QETH_DBF_TEXT(trace,3, "irla");
 				break;
 			case IPA_CMD_UNREGISTER_LOCAL_ADDR:
-				PRINT_WARN("probably problem on %s: "
-					   "received IPA command 0x%X\n",
-					   QETH_CARD_IFNAME(card),
-					   cmd->hdr.command);
+				QETH_DBF_TEXT(trace,3, "urla");
 				break;
 			default:
 				PRINT_WARN("Received data is IPA "
@@ -2263,19 +2260,25 @@
 			struct qeth_hdr *hdr)
 {
 	unsigned short vlan_id = 0;
+#ifdef CONFIG_QETH_VLAN
+	struct vlan_hdr *vhdr;
+#endif
 
 	skb->pkt_type = PACKET_HOST;
+	skb->protocol = qeth_type_trans(skb, skb->dev);
 	if (card->options.checksum_type == NO_CHECKSUMMING)
 		skb->ip_summed = CHECKSUM_UNNECESSARY;
 	else
 		skb->ip_summed = CHECKSUM_NONE;
 #ifdef CONFIG_QETH_VLAN
 	if (hdr->hdr.l2.flags[2] & (QETH_LAYER2_FLAG_VLAN)) {
+		vhdr = (struct vlan_hdr *) skb->data;
+		skb->protocol =
+			__constant_htons(vhdr->h_vlan_encapsulated_proto);
 		vlan_id = hdr->hdr.l2.vlan_id;
 		skb_pull(skb, VLAN_HLEN);
 	}
 #endif
-	skb->protocol = qeth_type_trans(skb, skb->dev);
 	return vlan_id;
 }
 
@@ -3388,11 +3391,9 @@
 		     unsigned len)
 {
 	struct ethhdr *hdr;
-	struct qeth_card *card;
 
-	card = (struct qeth_card *)dev->priv;
         hdr = (struct ethhdr *)skb_push(skb, QETH_FAKE_LL_LEN);
-	memcpy(hdr->h_source, card->dev->dev_addr, ETH_ALEN);
+	memcpy(hdr->h_source, dev->dev_addr, ETH_ALEN);
         memcpy(hdr->h_dest, "FAKELL", ETH_ALEN);
         if (type != ETH_P_802_3)
                 hdr->h_proto = htons(type);
@@ -3430,14 +3431,6 @@
 	card->perf_stats.outbound_cnt++;
 	card->perf_stats.outbound_start_time = qeth_get_micros();
 #endif
-	if (dev->hard_header == qeth_fake_header) {
-               if ((skb = qeth_pskb_unshare(skb, GFP_ATOMIC)) == NULL) {
-                        card->stats.tx_dropped++;
-                        dev_kfree_skb_irq(skb);
-                        return 0;
-                }
-                skb_pull(skb, QETH_FAKE_LL_LEN);
-	}
 	/*
 	 * We only call netif_stop_queue in case of errors. Since we've
 	 * got our own synchronization on queues we can keep the stack's
@@ -4060,8 +4053,17 @@
 
 	QETH_DBF_TEXT(trace, 6, "sendpkt");
 
-	if (!card->options.layer2)
+	if (!card->options.layer2) {
 		ipv = qeth_get_ip_version(skb);
+		if ((card->dev->hard_header == qeth_fake_header) && ipv) {
+               		if ((skb = qeth_pskb_unshare(skb,GFP_ATOMIC)) == NULL) {
+                        	card->stats.tx_dropped++;
+                        	dev_kfree_skb_irq(skb);
+                        	return 0;
+                	}
+                	skb_pull(skb, QETH_FAKE_LL_LEN);
+		}
+	}
 	cast_type = qeth_get_cast_type(card, skb);
 	queue = card->qdio.out_qs
 		[qeth_get_priority_queue(card, skb, ipv, cast_type)];
@@ -5242,7 +5244,8 @@
 	struct inet6_dev *in6_dev;
 
 	QETH_DBF_TEXT(trace,4,"chkmcv6");
-	if (!qeth_is_supported(card, IPA_IPV6))
+	if ((card->options.layer2 == 0) &&
+	    (!qeth_is_supported(card, IPA_IPV6)) )
 		return ;
 
 	in6_dev = in6_dev_get(card->dev);
@@ -7117,10 +7120,7 @@
 	}
 /*maybe it was set offline without ifconfig down
  * we can also use this state for recovery purposes*/
-	if (card->options.layer2)
-		qeth_set_allowed_threads(card, QETH_RECOVER_THREAD, 0);
-	else
-		qeth_set_allowed_threads(card, 0xffffffff, 0);
+	qeth_set_allowed_threads(card, 0xffffffff, 0);
 	if (recover_flag == CARD_STATE_RECOVER)
 		qeth_start_again(card);
 	qeth_notify_processes();
diff -Nru a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
--- a/drivers/scsi/Kconfig	2005-03-11 12:51:51 -08:00
+++ b/drivers/scsi/Kconfig	2005-03-11 12:51:51 -08:00
@@ -273,8 +273,8 @@
 	tristate "ACARD SCSI support"
 	depends on PCI && SCSI
 	help
-	  This driver supports the ACARD 870U/W SCSI host adapter.
-
+	  This driver supports the ACARD SCSI host adapter.
+	  Support Chip <ATP870 ATP876 ATP880 ATP885>
 	  To compile this driver as a module, choose M here: the
 	  module will be called atp870u.
 
diff -Nru a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c
--- a/drivers/scsi/ahci.c	2005-03-11 12:51:41 -08:00
+++ b/drivers/scsi/ahci.c	2005-03-11 12:51:41 -08:00
@@ -199,6 +199,7 @@
 	.dma_boundary		= AHCI_DMA_BOUNDARY,
 	.slave_configure	= ata_scsi_slave_config,
 	.bios_param		= ata_std_bios_param,
+	.ordered_flush		= 1,
 };
 
 static struct ata_port_operations ahci_ops = {
@@ -574,7 +575,7 @@
 	writel(tmp, port_mmio + PORT_CMD);
 	readl(port_mmio + PORT_CMD); /* flush */
 
-	printk(KERN_WARNING "ata%u: error occurred, port reset\n", ap->port_no);
+	printk(KERN_WARNING "ata%u: error occurred, port reset\n", ap->id);
 }
 
 static void ahci_eng_timeout(struct ata_port *ap)
@@ -766,10 +767,10 @@
 
 	using_dac = hpriv->cap & HOST_CAP_64;
 	if (using_dac &&
-	    !pci_set_dma_mask(pdev, 0xffffffffffffffffULL)) {
-		rc = pci_set_consistent_dma_mask(pdev, 0xffffffffffffffffULL);
+	    !pci_set_dma_mask(pdev, DMA_64BIT_MASK)) {
+		rc = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK);
 		if (rc) {
-			rc = pci_set_consistent_dma_mask(pdev, 0xffffffffULL);
+			rc = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
 			if (rc) {
 				printk(KERN_ERR DRV_NAME "(%s): 64-bit DMA enable failed\n",
 					pci_name(pdev));
@@ -779,13 +780,13 @@
 
 		hpriv->flags |= HOST_CAP_64;
 	} else {
-		rc = pci_set_dma_mask(pdev, 0xffffffffULL);
+		rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
 		if (rc) {
 			printk(KERN_ERR DRV_NAME "(%s): 32-bit DMA enable failed\n",
 				pci_name(pdev));
 			return rc;
 		}
-		rc = pci_set_consistent_dma_mask(pdev, 0xffffffffULL);
+		rc = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
 		if (rc) {
 			printk(KERN_ERR DRV_NAME "(%s): 32-bit consistent DMA enable failed\n",
 				pci_name(pdev));
diff -Nru a/drivers/scsi/arm/arxescsi.c b/drivers/scsi/arm/arxescsi.c
--- a/drivers/scsi/arm/arxescsi.c	2005-03-11 12:51:46 -08:00
+++ b/drivers/scsi/arm/arxescsi.c	2005-03-11 12:51:46 -08:00
@@ -43,6 +43,7 @@
 struct arxescsi_info {
 	FAS216_Info		info;
 	struct expansion_card	*ec;
+	void __iomem		*base;
 };
 
 #define DMADATA_OFFSET	(0x200)
@@ -73,7 +74,7 @@
 	return fasdma_pseudo;
 }
 
-static void arxescsi_pseudo_dma_write(unsigned char *addr, unsigned char *base)
+static void arxescsi_pseudo_dma_write(unsigned char *addr, void __iomem *base)
 {
        __asm__ __volatile__(
        "               stmdb   sp!, {r0-r12}\n"
@@ -115,7 +116,7 @@
 {
 	struct arxescsi_info *info = (struct arxescsi_info *)host->hostdata;
 	unsigned int length, error = 0;
-	unsigned char *base = info->info.scsi.io_base;
+	void __iomem *base = info->info.scsi.io_base;
 	unsigned char *addr;
 
 	length = SCp->this_residual;
@@ -283,7 +284,7 @@
 	struct Scsi_Host *host;
 	struct arxescsi_info *info;
 	unsigned long resbase, reslen;
-	unsigned char *base;
+	void __iomem *base;
 	int ret;
 
 	ret = ecard_request_resources(ec);
@@ -304,15 +305,13 @@
 		goto out_unmap;
 	}
 
-	host->base = (unsigned long)base;
-	host->irq = NO_IRQ;
-	host->dma_channel = NO_DMA;
-
 	info = (struct arxescsi_info *)host->hostdata;
 	info->ec = ec;
+	info->base = base;
 
 	info->info.scsi.io_base		= base + 0x2000;
-	info->info.scsi.irq		= host->irq;
+	info->info.scsi.irq		= NO_IRQ;
+	info->info.scsi.dma		= NO_DMA;
 	info->info.scsi.io_shift	= 5;
 	info->info.ifcfg.clockrate	= 24; /* MHz */
 	info->info.ifcfg.select_timeout = 255;
@@ -351,11 +350,12 @@
 static void __devexit arxescsi_remove(struct expansion_card *ec)
 {
 	struct Scsi_Host *host = ecard_get_drvdata(ec);
+	struct arxescsi_info *info = (struct arxescsi_info *)host->hostdata;
 
 	ecard_set_drvdata(ec, NULL);
 	fas216_remove(host);
 
-	iounmap((void *)host->base);
+	iounmap(info->base);
 
 	fas216_release(host);
 	scsi_host_put(host);
diff -Nru a/drivers/scsi/arm/cumana_2.c b/drivers/scsi/arm/cumana_2.c
--- a/drivers/scsi/arm/cumana_2.c	2005-03-11 12:51:47 -08:00
+++ b/drivers/scsi/arm/cumana_2.c	2005-03-11 12:51:47 -08:00
@@ -1,7 +1,7 @@
 /*
  *  linux/drivers/acorn/scsi/cumana_2.c
  *
- *  Copyright (C) 1997-2002 Russell King
+ *  Copyright (C) 1997-2005 Russell King
  *
  * 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
@@ -78,11 +78,8 @@
 struct cumanascsi2_info {
 	FAS216_Info		info;
 	struct expansion_card	*ec;
-
-	void			*status;	/* card status register	*/
-	void			*alatch;	/* Control register	*/
+	void __iomem		*base;
 	unsigned int		terms;		/* Terminator state	*/
-	void			*dmaarea;	/* Pseudo DMA area	*/
 	struct scatterlist	sg[NR_SG];	/* Scatter DMA list	*/
 };
 
@@ -97,7 +94,8 @@
 static void
 cumanascsi_2_irqenable(struct expansion_card *ec, int irqnr)
 {
-	writeb(ALATCH_ENA_INT, ec->irq_data);
+	struct cumanascsi2_info *info = ec->irq_data;
+	writeb(ALATCH_ENA_INT, info->base + CUMANASCSI2_ALATCH);
 }
 
 /* Prototype: void cumanascsi_2_irqdisable(ec, irqnr)
@@ -108,7 +106,8 @@
 static void
 cumanascsi_2_irqdisable(struct expansion_card *ec, int irqnr)
 {
-	writeb(ALATCH_DIS_INT, ec->irq_data);
+	struct cumanascsi2_info *info = ec->irq_data;
+	writeb(ALATCH_DIS_INT, info->base + CUMANASCSI2_ALATCH);
 }
 
 static const expansioncard_ops_t cumanascsi_2_ops = {
@@ -128,10 +127,10 @@
 
 	if (on_off) {
 		info->terms = 1;
-		writeb(ALATCH_ENA_TERM, info->alatch);
+		writeb(ALATCH_ENA_TERM, info->base + CUMANASCSI2_ALATCH);
 	} else {
 		info->terms = 0;
-		writeb(ALATCH_DIS_TERM, info->alatch);
+		writeb(ALATCH_DIS_TERM, info->base + CUMANASCSI2_ALATCH);
 	}
 }
 
@@ -163,9 +162,9 @@
 {
 	struct cumanascsi2_info *info = (struct cumanascsi2_info *)host->hostdata;
 	struct device *dev = scsi_get_device(host);
-	int dmach = host->dma_channel;
+	int dmach = info->info.scsi.dma;
 
-	writeb(ALATCH_DIS_DMA, info->alatch);
+	writeb(ALATCH_DIS_DMA, info->base + CUMANASCSI2_ALATCH);
 
 	if (dmach != NO_DMA &&
 	    (min_type == fasdma_real_all || SCp->this_residual >= 512)) {
@@ -186,11 +185,11 @@
 
 		disable_dma(dmach);
 		set_dma_sg(dmach, info->sg, bufs + 1);
-		writeb(alatch_dir, info->alatch);
+		writeb(alatch_dir, info->base + CUMANASCSI2_ALATCH);
 		set_dma_mode(dmach, dma_dir);
 		enable_dma(dmach);
-		writeb(ALATCH_ENA_DMA, info->alatch);
-		writeb(ALATCH_DIS_BIT32, info->alatch);
+		writeb(ALATCH_ENA_DMA, info->base + CUMANASCSI2_ALATCH);
+		writeb(ALATCH_DIS_BIT32, info->base + CUMANASCSI2_ALATCH);
 		return fasdma_real_all;
 	}
 
@@ -224,7 +223,7 @@
 #if 0
 		while (length > 1) {
 			unsigned long word;
-			unsigned int status = readb(info->status);
+			unsigned int status = readb(info->base + CUMANASCSI2_STATUS);
 
 			if (status & STATUS_INT)
 				goto end;
@@ -233,7 +232,7 @@
 				continue;
 
 			word = *addr | *(addr + 1) << 8;
-			writew(word, info->dmaarea);
+			writew(word, info->base + CUMANASCSI2_PSEUDODMA);
 			addr += 2;
 			length -= 2;
 		}
@@ -243,7 +242,7 @@
 	else {
 		if (transfer && (transfer & 255)) {
 			while (length >= 256) {
-				unsigned int status = readb(info->status);
+				unsigned int status = readb(info->base + CUMANASCSI2_STATUS);
 
 				if (status & STATUS_INT)
 					return;
@@ -251,7 +250,8 @@
 				if (!(status & STATUS_DRQ))
 					continue;
 
-				readsw(info->dmaarea, addr, 256 >> 1);
+				readsw(info->base + CUMANASCSI2_PSEUDODMA,
+				       addr, 256 >> 1);
 				addr += 256;
 				length -= 256;
 			}
@@ -259,7 +259,7 @@
 
 		while (length > 0) {
 			unsigned long word;
-			unsigned int status = readb(info->status);
+			unsigned int status = readb(info->base + CUMANASCSI2_STATUS);
 
 			if (status & STATUS_INT)
 				return;
@@ -267,7 +267,7 @@
 			if (!(status & STATUS_DRQ))
 				continue;
 
-			word = readw(info->dmaarea);
+			word = readw(info->base + CUMANASCSI2_PSEUDODMA);
 			*addr++ = word;
 			if (--length > 0) {
 				*addr++ = word >> 8;
@@ -286,9 +286,9 @@
 cumanascsi_2_dma_stop(struct Scsi_Host *host, Scsi_Pointer *SCp)
 {
 	struct cumanascsi2_info *info = (struct cumanascsi2_info *)host->hostdata;
-	if (host->dma_channel != NO_DMA) {
-		writeb(ALATCH_DIS_DMA, info->alatch);
-		disable_dma(host->dma_channel);
+	if (info->info.scsi.dma != NO_DMA) {
+		writeb(ALATCH_DIS_DMA, info->base + CUMANASCSI2_ALATCH);
+		disable_dma(info->info.scsi.dma);
 	}
 }
 
@@ -405,7 +405,7 @@
 	struct Scsi_Host *host;
 	struct cumanascsi2_info *info;
 	unsigned long resbase, reslen;
-	unsigned char *base;
+	void __iomem *base;
 	int ret;
 
 	ret = ecard_request_resources(ec);
@@ -427,28 +427,18 @@
 		goto out_unmap;
 	}
 
-	host->base	  = (unsigned long)base;
-	host->irq	  = ec->irq;
-	host->dma_channel = ec->dma;
-
 	ecard_set_drvdata(ec, host);
 
 	info = (struct cumanascsi2_info *)host->hostdata;
 	info->ec	= ec;
-	info->dmaarea	= base + CUMANASCSI2_PSEUDODMA;
-	info->status	= base + CUMANASCSI2_STATUS;
-	info->alatch	= base + CUMANASCSI2_ALATCH;
-
-	ec->irqaddr	= info->status;
-	ec->irqmask	= STATUS_INT;
-	ec->irq_data	= base + CUMANASCSI2_ALATCH;
-	ec->ops		= &cumanascsi_2_ops;
+	info->base	= base;
 
 	cumanascsi_2_terminator_ctl(host, term[ec->slot_no]);
 
 	info->info.scsi.io_base		= base + CUMANASCSI2_FAS216_OFFSET;
 	info->info.scsi.io_shift	= CUMANASCSI2_FAS216_SHIFT;
-	info->info.scsi.irq		= host->irq;
+	info->info.scsi.irq		= ec->irq;
+	info->info.scsi.dma		= ec->dma;
 	info->info.ifcfg.clockrate	= 40; /* MHz */
 	info->info.ifcfg.select_timeout	= 255;
 	info->info.ifcfg.asyncperiod	= 200; /* ns */
@@ -461,25 +451,30 @@
 	info->info.dma.pseudo		= cumanascsi_2_dma_pseudo;
 	info->info.dma.stop		= cumanascsi_2_dma_stop;
 
+	ec->irqaddr	= info->base + CUMANASCSI2_STATUS;
+	ec->irqmask	= STATUS_INT;
+	ec->irq_data	= info;
+	ec->ops		= &cumanascsi_2_ops;
+
 	ret = fas216_init(host);
 	if (ret)
 		goto out_free;
 
-	ret = request_irq(host->irq, cumanascsi_2_intr,
+	ret = request_irq(ec->irq, cumanascsi_2_intr,
 			  SA_INTERRUPT, "cumanascsi2", info);
 	if (ret) {
 		printk("scsi%d: IRQ%d not free: %d\n",
-		       host->host_no, host->irq, ret);
+		       host->host_no, ec->irq, ret);
 		goto out_release;
 	}
 
-	if (host->dma_channel != NO_DMA) {
-		if (request_dma(host->dma_channel, "cumanascsi2")) {
+	if (info->info.scsi.dma != NO_DMA) {
+		if (request_dma(info->info.scsi.dma, "cumanascsi2")) {
 			printk("scsi%d: DMA%d not free, using PIO\n",
-			       host->host_no, host->dma_channel);
-			host->dma_channel = NO_DMA;
+			       host->host_no, info->info.scsi.dma);
+			info->info.scsi.dma = NO_DMA;
 		} else {
-			set_dma_speed(host->dma_channel, 180);
+			set_dma_speed(info->info.scsi.dma, 180);
 			info->info.ifcfg.capabilities |= FASCAP_DMA;
 		}
 	}
@@ -488,9 +483,9 @@
 	if (ret == 0)
 		goto out;
 
-	if (host->dma_channel != NO_DMA)
-		free_dma(host->dma_channel);
-	free_irq(host->irq, host);
+	if (info->info.scsi.dma != NO_DMA)
+		free_dma(info->info.scsi.dma);
+	free_irq(ec->irq, host);
 
  out_release:
 	fas216_release(host);
@@ -516,11 +511,11 @@
 	ecard_set_drvdata(ec, NULL);
 	fas216_remove(host);
 
-	if (host->dma_channel != NO_DMA)
-		free_dma(host->dma_channel);
-	free_irq(host->irq, info);
+	if (info->info.scsi.dma != NO_DMA)
+		free_dma(info->info.scsi.dma);
+	free_irq(ec->irq, info);
 
-	iounmap((void *)host->base);
+	iounmap(info->base);
 
 	fas216_release(host);
 	scsi_host_put(host);
diff -Nru a/drivers/scsi/arm/eesox.c b/drivers/scsi/arm/eesox.c
--- a/drivers/scsi/arm/eesox.c	2005-03-11 12:51:51 -08:00
+++ b/drivers/scsi/arm/eesox.c	2005-03-11 12:51:52 -08:00
@@ -1,7 +1,7 @@
 /*
  *  linux/drivers/acorn/scsi/eesox.c
  *
- *  Copyright (C) 1997-2003 Russell King
+ *  Copyright (C) 1997-2005 Russell King
  *
  * 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
@@ -73,8 +73,8 @@
 struct eesoxscsi_info {
 	FAS216_Info		info;
 	struct expansion_card	*ec;
-
-	void			*ctl_port;
+	void __iomem		*base;
+	void __iomem		*ctl_port;
 	unsigned int		control;
 	struct scatterlist	sg[NR_SG];	/* Scatter DMA list	*/
 };
@@ -163,7 +163,7 @@
 {
 	struct eesoxscsi_info *info = (struct eesoxscsi_info *)host->hostdata;
 	struct device *dev = scsi_get_device(host);
-	int dmach = host->dma_channel;
+	int dmach = info->info.scsi.dma;
 
 	if (dmach != NO_DMA &&
 	    (min_type == fasdma_real_all || SCp->this_residual >= 512)) {
@@ -194,11 +194,11 @@
 	return fasdma_pseudo;
 }
 
-static void eesoxscsi_buffer_in(void *buf, int length, void *base)
+static void eesoxscsi_buffer_in(void *buf, int length, void __iomem *base)
 {
-	const void *reg_fas = base + EESOX_FAS216_OFFSET;
-	const void *reg_dmastat = base + EESOX_DMASTAT;
-	const void *reg_dmadata = base + EESOX_DMADATA;
+	const void __iomem *reg_fas = base + EESOX_FAS216_OFFSET;
+	const void __iomem *reg_dmastat = base + EESOX_DMASTAT;
+	const void __iomem *reg_dmadata = base + EESOX_DMADATA;
 	const register unsigned long mask = 0xffff;
 
 	do {
@@ -272,11 +272,11 @@
 	} while (length);
 }
 
-static void eesoxscsi_buffer_out(void *buf, int length, void *base)
+static void eesoxscsi_buffer_out(void *buf, int length, void __iomem *base)
 {
-	const void *reg_fas = base + EESOX_FAS216_OFFSET;
-	const void *reg_dmastat = base + EESOX_DMASTAT;
-	const void *reg_dmadata = base + EESOX_DMADATA;
+	const void __iomem *reg_fas = base + EESOX_FAS216_OFFSET;
+	const void __iomem *reg_dmastat = base + EESOX_DMASTAT;
+	const void __iomem *reg_dmadata = base + EESOX_DMADATA;
 
 	do {
 		unsigned int status;
@@ -356,11 +356,11 @@
 eesoxscsi_dma_pseudo(struct Scsi_Host *host, Scsi_Pointer *SCp,
 		     fasdmadir_t dir, int transfer_size)
 {
-	void *base = (void *)host->base;
+	struct eesoxscsi_info *info = (struct eesoxscsi_info *)host->hostdata;
 	if (dir == DMA_IN) {
-		eesoxscsi_buffer_in(SCp->ptr, SCp->this_residual, base);
+		eesoxscsi_buffer_in(SCp->ptr, SCp->this_residual, info->base);
 	} else {
-		eesoxscsi_buffer_out(SCp->ptr, SCp->this_residual, base);
+		eesoxscsi_buffer_out(SCp->ptr, SCp->this_residual, info->base);
 	}
 }
 
@@ -372,8 +372,9 @@
 static void
 eesoxscsi_dma_stop(struct Scsi_Host *host, Scsi_Pointer *SCp)
 {
-	if (host->dma_channel != NO_DMA)
-		disable_dma(host->dma_channel);
+	struct eesoxscsi_info *info = (struct eesoxscsi_info *)host->hostdata;
+	if (info->info.scsi.dma != NO_DMA)
+		disable_dma(info->info.scsi.dma);
 }
 
 /* Prototype: const char *eesoxscsi_info(struct Scsi_Host * host)
@@ -522,7 +523,7 @@
 	struct Scsi_Host *host;
 	struct eesoxscsi_info *info;
 	unsigned long resbase, reslen;
-	unsigned char *base;
+	void __iomem *base;
 	int ret;
 
 	ret = ecard_request_resources(ec);
@@ -544,26 +545,19 @@
 		goto out_unmap;
 	}
 
-	host->base	  = (unsigned long)base;
-	host->irq	  = ec->irq;
-	host->dma_channel = ec->dma;
-
 	ecard_set_drvdata(ec, host);
 
 	info = (struct eesoxscsi_info *)host->hostdata;
 	info->ec	= ec;
+	info->base	= base;
 	info->ctl_port	= base + EESOX_CONTROL;
 	info->control	= term[ec->slot_no] ? EESOX_TERM_ENABLE : 0;
 	writeb(info->control, info->ctl_port);
 
-	ec->irqaddr	= base + EESOX_DMASTAT;
-	ec->irqmask	= EESOX_STAT_INTR;
-	ec->irq_data	= info;
-	ec->ops		= &eesoxscsi_ops;
-
 	info->info.scsi.io_base		= base + EESOX_FAS216_OFFSET;
 	info->info.scsi.io_shift	= EESOX_FAS216_SHIFT;
-	info->info.scsi.irq		= host->irq;
+	info->info.scsi.irq		= ec->irq;
+	info->info.scsi.dma		= ec->dma;
 	info->info.ifcfg.clockrate	= 40; /* MHz */
 	info->info.ifcfg.select_timeout	= 255;
 	info->info.ifcfg.asyncperiod	= 200; /* ns */
@@ -576,26 +570,31 @@
 	info->info.dma.pseudo		= eesoxscsi_dma_pseudo;
 	info->info.dma.stop		= eesoxscsi_dma_stop;
 
+	ec->irqaddr	= base + EESOX_DMASTAT;
+	ec->irqmask	= EESOX_STAT_INTR;
+	ec->irq_data	= info;
+	ec->ops		= &eesoxscsi_ops;
+
 	device_create_file(&ec->dev, &dev_attr_bus_term);
 
 	ret = fas216_init(host);
 	if (ret)
 		goto out_free;
 
-	ret = request_irq(host->irq, eesoxscsi_intr, 0, "eesoxscsi", info);
+	ret = request_irq(ec->irq, eesoxscsi_intr, 0, "eesoxscsi", info);
 	if (ret) {
 		printk("scsi%d: IRQ%d not free: %d\n",
-		       host->host_no, host->irq, ret);
+		       host->host_no, ec->irq, ret);
 		goto out_remove;
 	}
 
-	if (host->dma_channel != NO_DMA) {
-		if (request_dma(host->dma_channel, "eesox")) {
+	if (info->info.scsi.dma != NO_DMA) {
+		if (request_dma(info->info.scsi.dma, "eesox")) {
 			printk("scsi%d: DMA%d not free, DMA disabled\n",
-			       host->host_no, host->dma_channel);
-			host->dma_channel = NO_DMA;
+			       host->host_no, info->info.scsi.dma);
+			info->info.scsi.dma = NO_DMA;
 		} else {
-			set_dma_speed(host->dma_channel, 180);
+			set_dma_speed(info->info.scsi.dma, 180);
 			info->info.ifcfg.capabilities |= FASCAP_DMA;
 			info->info.ifcfg.cntl3 |= CNTL3_BS8;
 		}
@@ -605,9 +604,9 @@
 	if (ret == 0)
 		goto out;
 
-	if (host->dma_channel != NO_DMA)
-		free_dma(host->dma_channel);
-	free_irq(host->irq, host);
+	if (info->info.scsi.dma != NO_DMA)
+		free_dma(info->info.scsi.dma);
+	free_irq(ec->irq, host);
 
  out_remove:
 	fas216_remove(host);
@@ -634,13 +633,13 @@
 	ecard_set_drvdata(ec, NULL);
 	fas216_remove(host);
 
-	if (host->dma_channel != NO_DMA)
-		free_dma(host->dma_channel);
-	free_irq(host->irq, info);
+	if (info->info.scsi.dma != NO_DMA)
+		free_dma(info->info.scsi.dma);
+	free_irq(ec->irq, info);
 
 	device_remove_file(&ec->dev, &dev_attr_bus_term);
 
-	iounmap((void *)host->base);
+	iounmap(info->base);
 
 	fas216_release(host);
 	scsi_host_put(host);
@@ -679,4 +678,3 @@
 MODULE_PARM(term, "1-8i");
 MODULE_PARM_DESC(term, "SCSI bus termination");
 MODULE_LICENSE("GPL");
-
diff -Nru a/drivers/scsi/arm/fas216.c b/drivers/scsi/arm/fas216.c
--- a/drivers/scsi/arm/fas216.c	2005-03-11 12:51:42 -08:00
+++ b/drivers/scsi/arm/fas216.c	2005-03-11 12:51:42 -08:00
@@ -142,19 +142,13 @@
 static inline unsigned char fas216_readb(FAS216_Info *info, unsigned int reg)
 {
 	unsigned int off = reg << info->scsi.io_shift;
-	if (info->scsi.io_base)
-		return readb(info->scsi.io_base + off);
-	else
-		return inb(info->scsi.io_port + off);
+	return readb(info->scsi.io_base + off);
 }
 
 static inline void fas216_writeb(FAS216_Info *info, unsigned int reg, unsigned int val)
 {
 	unsigned int off = reg << info->scsi.io_shift;
-	if (info->scsi.io_base)
-		writeb(val, info->scsi.io_base + off);
-	else
-		outb(val, info->scsi.io_port + off);
+	writeb(val, info->scsi.io_base + off);
 }
 
 static void fas216_dumpstate(FAS216_Info *info)
@@ -197,8 +191,8 @@
 	printk("  { magic_start=%lX host=%p SCpnt=%p origSCpnt=%p\n",
 		info->magic_start, info->host, info->SCpnt,
 		info->origSCpnt);
-	printk("    scsi={ io_port=%X io_shift=%X irq=%X cfg={ %X %X %X %X }\n",
-		info->scsi.io_port, info->scsi.io_shift, info->scsi.irq,
+	printk("    scsi={ io_shift=%X irq=%X cfg={ %X %X %X %X }\n",
+		info->scsi.io_shift, info->scsi.irq,
 		info->scsi.cfg[0], info->scsi.cfg[1], info->scsi.cfg[2],
 		info->scsi.cfg[3]);
 	printk("           type=%p phase=%X\n",
@@ -2967,11 +2961,11 @@
 	return sprintf(buffer,
 			"\n"
 			"Chip    : %s\n"
-			" Address: 0x%08lx\n"
+			" Address: 0x%p\n"
 			" IRQ    : %d\n"
 			" DMA    : %d\n",
-			info->scsi.type, info->host->io_port,
-			info->host->irq, info->host->dma_channel);
+			info->scsi.type, info->scsi.io_base,
+			info->scsi.irq, info->scsi.dma);
 }
 
 int fas216_print_stats(FAS216_Info *info, char *buffer)
diff -Nru a/drivers/scsi/arm/fas216.h b/drivers/scsi/arm/fas216.h
--- a/drivers/scsi/arm/fas216.h	2005-03-11 12:51:52 -08:00
+++ b/drivers/scsi/arm/fas216.h	2005-03-11 12:51:52 -08:00
@@ -236,12 +236,12 @@
 	/* driver information */
 	struct {
 		phase_t		phase;			/* current phase			*/
-		void		*io_base;		/* iomem base of FAS216			*/
-		unsigned int	io_port;		/* base address of FAS216		*/
+		void __iomem	*io_base;		/* iomem base of FAS216			*/
 		unsigned int	io_shift;		/* shift to adjust reg offsets by	*/
 		unsigned char	cfg[4];			/* configuration registers		*/
 		const char	*type;			/* chip type				*/
 		unsigned int	irq;			/* interrupt				*/
+		int		dma;			/* dma channel				*/
 
 		Scsi_Pointer	SCp;			/* current commands data pointer	*/
 
diff -Nru a/drivers/scsi/arm/powertec.c b/drivers/scsi/arm/powertec.c
--- a/drivers/scsi/arm/powertec.c	2005-03-11 12:51:47 -08:00
+++ b/drivers/scsi/arm/powertec.c	2005-03-11 12:51:47 -08:00
@@ -1,7 +1,7 @@
 /*
  *  linux/drivers/acorn/scsi/powertec.c
  *
- *  Copyright (C) 1997-2003 Russell King
+ *  Copyright (C) 1997-2005 Russell King
  *
  * 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
@@ -61,7 +61,7 @@
 struct powertec_info {
 	FAS216_Info		info;
 	struct expansion_card	*ec;
-	void			*term_port;
+	void __iomem		*base;
 	unsigned int		term_ctl;
 	struct scatterlist	sg[NR_SG];
 };
@@ -74,7 +74,8 @@
 static void
 powertecscsi_irqenable(struct expansion_card *ec, int irqnr)
 {
-	writeb(POWERTEC_INTR_ENABLE, ec->irq_data);
+	struct powertec_info *info = ec->irq_data;
+	writeb(POWERTEC_INTR_ENABLE, info->base + POWERTEC_INTR_CONTROL);
 }
 
 /* Prototype: void powertecscsi_irqdisable(ec, irqnr)
@@ -85,7 +86,8 @@
 static void
 powertecscsi_irqdisable(struct expansion_card *ec, int irqnr)
 {
-	writeb(POWERTEC_INTR_DISABLE, ec->irq_data);
+	struct powertec_info *info = ec->irq_data;
+	writeb(POWERTEC_INTR_DISABLE, info->base + POWERTEC_INTR_CONTROL);
 }
 
 static const expansioncard_ops_t powertecscsi_ops = {
@@ -104,7 +106,7 @@
 	struct powertec_info *info = (struct powertec_info *)host->hostdata;
 
 	info->term_ctl = on_off ? POWERTEC_TERM_ENABLE : 0;
-	writeb(info->term_ctl, info->term_port);
+	writeb(info->term_ctl, info->base + POWERTEC_TERM_CONTROL);
 }
 
 /* Prototype: void powertecscsi_intr(irq, *dev_id, *regs)
@@ -135,7 +137,7 @@
 {
 	struct powertec_info *info = (struct powertec_info *)host->hostdata;
 	struct device *dev = scsi_get_device(host);
-	int dmach = host->dma_channel;
+	int dmach = info->info.scsi.dma;
 
 	if (info->info.ifcfg.capabilities & FASCAP_DMA &&
 	    min_type == fasdma_real_all) {
@@ -174,8 +176,9 @@
 static void
 powertecscsi_dma_stop(struct Scsi_Host *host, Scsi_Pointer *SCp)
 {
-	if (host->dma_channel != NO_DMA)
-		disable_dma(host->dma_channel);
+	struct powertec_info *info = (struct powertec_info *)host->hostdata;
+	if (info->info.scsi.dma != NO_DMA)
+		disable_dma(info->info.scsi.dma);
 }
 
 /* Prototype: const char *powertecscsi_info(struct Scsi_Host * host)
@@ -315,7 +318,7 @@
 	struct Scsi_Host *host;
 	struct powertec_info *info;
 	unsigned long resbase, reslen;
-	unsigned char *base;
+	void __iomem *base;
 	int ret;
 
 	ret = ecard_request_resources(ec);
@@ -337,26 +340,16 @@
 		goto out_unmap;
 	}
 
-	host->base	  = (unsigned long)base;
-	host->irq	  = ec->irq;
-	host->dma_channel = ec->dma;
-
-	ec->irqaddr	= base + POWERTEC_INTR_STATUS;
-	ec->irqmask	= POWERTEC_INTR_BIT;
-	ec->irq_data	= base + POWERTEC_INTR_CONTROL;
-	ec->ops		= &powertecscsi_ops;
-
 	ecard_set_drvdata(ec, host);
 
 	info = (struct powertec_info *)host->hostdata;
-	info->term_port = base + POWERTEC_TERM_CONTROL;
+	info->base = base;
 	powertecscsi_terminator_ctl(host, term[ec->slot_no]);
 
-	device_create_file(&ec->dev, &dev_attr_bus_term);
-
 	info->info.scsi.io_base		= base + POWERTEC_FAS216_OFFSET;
 	info->info.scsi.io_shift	= POWERTEC_FAS216_SHIFT;
-	info->info.scsi.irq		= host->irq;
+	info->info.scsi.irq		= ec->irq;
+	info->info.scsi.dma		= ec->dma;
 	info->info.ifcfg.clockrate	= 40; /* MHz */
 	info->info.ifcfg.select_timeout	= 255;
 	info->info.ifcfg.asyncperiod	= 200; /* ns */
@@ -369,25 +362,32 @@
 	info->info.dma.pseudo		= NULL;
 	info->info.dma.stop		= powertecscsi_dma_stop;
 
+	ec->irqaddr	= base + POWERTEC_INTR_STATUS;
+	ec->irqmask	= POWERTEC_INTR_BIT;
+	ec->irq_data	= info;
+	ec->ops		= &powertecscsi_ops;
+
+	device_create_file(&ec->dev, &dev_attr_bus_term);
+
 	ret = fas216_init(host);
 	if (ret)
 		goto out_free;
 
-	ret = request_irq(host->irq, powertecscsi_intr,
+	ret = request_irq(ec->irq, powertecscsi_intr,
 			  SA_INTERRUPT, "powertec", info);
 	if (ret) {
 		printk("scsi%d: IRQ%d not free: %d\n",
-		       host->host_no, host->irq, ret);
+		       host->host_no, ec->irq, ret);
 		goto out_release;
 	}
 
-	if (host->dma_channel != NO_DMA) {
-		if (request_dma(host->dma_channel, "powertec")) {
+	if (info->info.scsi.dma != NO_DMA) {
+		if (request_dma(info->info.scsi.dma, "powertec")) {
 			printk("scsi%d: DMA%d not free, using PIO\n",
-			       host->host_no, host->dma_channel);
-			host->dma_channel = NO_DMA;
+			       host->host_no, info->info.scsi.dma);
+			info->info.scsi.dma = NO_DMA;
 		} else {
-			set_dma_speed(host->dma_channel, 180);
+			set_dma_speed(info->info.scsi.dma, 180);
 			info->info.ifcfg.capabilities |= FASCAP_DMA;
 		}
 	}
@@ -396,9 +396,9 @@
 	if (ret == 0)
 		goto out;
 
-	if (host->dma_channel != NO_DMA)
-		free_dma(host->dma_channel);
-	free_irq(host->irq, host);
+	if (info->info.scsi.dma != NO_DMA)
+		free_dma(info->info.scsi.dma);
+	free_irq(ec->irq, host);
 
  out_release:
 	fas216_release(host);
@@ -420,18 +420,18 @@
 static void __devexit powertecscsi_remove(struct expansion_card *ec)
 {
 	struct Scsi_Host *host = ecard_get_drvdata(ec);
-	struct powertecscsi_info *info = (struct powertecscsi_info *)host->hostdata;
+	struct powertec_info *info = (struct powertec_info *)host->hostdata;
 
 	ecard_set_drvdata(ec, NULL);
 	fas216_remove(host);
 
 	device_remove_file(&ec->dev, &dev_attr_bus_term);
 
-	if (host->dma_channel != NO_DMA)
-		free_dma(host->dma_channel);
-	free_irq(host->irq, info);
+	if (info->info.scsi.dma != NO_DMA)
+		free_dma(info->info.scsi.dma);
+	free_irq(ec->irq, info);
 
-	iounmap((void *)host->base);
+	iounmap(info->base);
 
 	fas216_release(host);
 	scsi_host_put(host);
diff -Nru a/drivers/scsi/ata_piix.c b/drivers/scsi/ata_piix.c
--- a/drivers/scsi/ata_piix.c	2005-03-11 12:51:52 -08:00
+++ b/drivers/scsi/ata_piix.c	2005-03-11 12:51:52 -08:00
@@ -121,6 +121,7 @@
 	.dma_boundary		= ATA_DMA_BOUNDARY,
 	.slave_configure	= ata_scsi_slave_config,
 	.bios_param		= ata_std_bios_param,
+	.ordered_flush		= 1,
 };
 
 static struct ata_port_operations piix_pata_ops = {
diff -Nru a/drivers/scsi/atp870u.c b/drivers/scsi/atp870u.c
--- a/drivers/scsi/atp870u.c	2005-03-11 12:51:42 -08:00
+++ b/drivers/scsi/atp870u.c	2005-03-11 12:51:42 -08:00
@@ -1,4 +1,4 @@
-/*
+/* 
  *  Copyright (C) 1997	Wu Ching Chen
  *  2.1.x update (C) 1998  Krzysztof G. Baranowski
  *  2.5.x update (C) 2002  Red Hat <alan@redhat.com>
@@ -13,8 +13,9 @@
  *		   fix disconnect bug  2000/12/21
  *		   support atp880 chip lvd u160 2001/05/15
  *		   fix prd table bug 2001/09/12 (7.1)
+ *
+ * atp885 support add by ACARD Hao Ping Lian 2005/01/05
  */
-
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
@@ -38,39 +39,54 @@
 #include "atp870u.h"
 
 static struct scsi_host_template atp870u_template;
-static void send_s870(struct Scsi_Host *host);
+void send_s870(struct atp_unit *dev,unsigned char c);
+void is885(struct atp_unit *dev, unsigned int wkport,unsigned char c);
+void tscam_885(void);
 
-
-static irqreturn_t atp870u_intr_handle(int irq, void *dev_id,
-					struct pt_regs *regs)
+static irqreturn_t atp870u_intr_handle(int irq, void *dev_id, struct pt_regs *regs)
 {
 	unsigned long flags;
 	unsigned short int tmpcip, id;
-	unsigned char i, j, target_id, lun;
+	unsigned char i, j, c, target_id, lun,cmdp;
 	unsigned char *prd;
-	struct scsi_cmnd *workrequ;
-	unsigned int workportu, tmport;
-	unsigned long adrcntu, k;
+	struct scsi_cmnd *workreq;
+	unsigned int workport, tmport, tmport1;
+	unsigned long adrcnt, k;
+#ifdef ED_DBGP
+	unsigned long l;
+#endif
 	int errstus;
 	struct Scsi_Host *host = dev_id;
 	struct atp_unit *dev = (struct atp_unit *)&host->hostdata;
 
-	dev->in_int = 1;
-	workportu = dev->ioport;
-	tmport = workportu;
-
-	if (dev->working != 0) {
-		tmport += 0x1f;
+	for (c = 0; c < 2; c++) {
+		tmport = dev->ioport[c] + 0x1f;
 		j = inb(tmport);
-		if ((j & 0x80) == 0) {
-			dev->in_int = 0;
-			return IRQ_NONE;
-		}
-
-		tmpcip = dev->pciport;
-		if ((inb(tmpcip) & 0x08) != 0) {
+		if ((j & 0x80) != 0)
+		{			
+	   		goto ch_sel;
+		}
+		dev->in_int[c] = 0;
+	}
+	return IRQ_NONE;
+ch_sel:
+#ifdef ED_DBGP	
+	printk("atp870u_intr_handle enter\n");
+#endif	
+	dev->in_int[c] = 1;
+	cmdp = inb(dev->ioport[c] + 0x10);
+	workport = dev->ioport[c];
+	if (dev->working[c] != 0) {
+		if (dev->dev_id == ATP885_DEVID) {
+			tmport1 = workport + 0x16;
+			if ((inb(tmport1) & 0x80) == 0)
+				outb((inb(tmport1) | 0x80), tmport1);
+		}		
+		tmpcip = dev->pciport[c];
+		if ((inb(tmpcip) & 0x08) != 0)
+		{
 			tmpcip += 0x2;
-			for (k = 0; k < 1000; k++) {
+			for (k=0; k < 1000; k++) {
 				if ((inb(tmpcip) & 0x08) == 0) {
 					goto stop_dma;
 				}
@@ -80,18 +96,24 @@
 			}
 		}
 stop_dma:
-		tmpcip = dev->pciport;
+		tmpcip = dev->pciport[c];
 		outb(0x00, tmpcip);
 		tmport -= 0x08;
-
+		
 		i = inb(tmport);
+		
+		if (dev->dev_id == ATP885_DEVID) {
+			tmpcip += 2;
+			outb(0x06, tmpcip);
+			tmpcip -= 2;
+		}
 
 		tmport -= 0x02;
 		target_id = inb(tmport);
 		tmport += 0x02;
 
 		/*
-		 *      Remap wide devices onto id numbers
+		 *	Remap wide devices onto id numbers
 		 */
 
 		if ((target_id & 0x40) != 0) {
@@ -101,332 +123,460 @@
 		}
 
 		if ((j & 0x40) != 0) {
-			if (dev->last_cmd == 0xff) {
-				dev->last_cmd = target_id;
-			}
-			dev->last_cmd |= 0x40;
-		}
-
+		     if (dev->last_cmd[c] == 0xff) {
+			dev->last_cmd[c] = target_id;
+		     }
+		     dev->last_cmd[c] |= 0x40;
+		}
+		if (dev->dev_id == ATP885_DEVID) 
+			dev->r1f[c][target_id] |= j;
+#ifdef ED_DBGP
+		printk("atp870u_intr_handle status = %x\n",i);
+#endif	
 		if (i == 0x85) {
-			if ((dev->last_cmd & 0xf0) != 0x40) {
-				dev->last_cmd = 0xff;
+			if ((dev->last_cmd[c] & 0xf0) != 0x40) {
+			   dev->last_cmd[c] = 0xff;
+			}
+			if (dev->dev_id == ATP885_DEVID) {
+				tmport -= 0x05;
+				adrcnt = 0;
+				((unsigned char *) &adrcnt)[2] = inb(tmport++);
+				((unsigned char *) &adrcnt)[1] = inb(tmport++);
+				((unsigned char *) &adrcnt)[0] = inb(tmport);
+				if (dev->id[c][target_id].last_len != adrcnt)
+				{
+			   		k = dev->id[c][target_id].last_len;
+			   		k -= adrcnt;
+			   		dev->id[c][target_id].tran_len = k;			   
+			   	dev->id[c][target_id].last_len = adrcnt;			   
+				}
+#ifdef ED_DBGP
+				printk("tmport = %x dev->id[c][target_id].last_len = %d dev->id[c][target_id].tran_len = %d\n",tmport,dev->id[c][target_id].last_len,dev->id[c][target_id].tran_len);
+#endif		
 			}
+
 			/*
 			 *      Flip wide
-			 */
-			if (dev->wide_idu != 0) {
-				tmport = workportu + 0x1b;
+			 */			
+			if (dev->wide_id[c] != 0) {
+				tmport = workport + 0x1b;
 				outb(0x01, tmport);
 				while ((inb(tmport) & 0x01) != 0x01) {
 					outb(0x01, tmport);
 				}
-			}
+			}		
 			/*
-			 *      Issue more commands
+			 *	Issue more commands
 			 */
-			spin_lock_irqsave(dev->host->host_lock, flags);
-			if (((dev->quhdu != dev->quendu) || (dev->last_cmd != 0xff)) && (dev->in_snd == 0)) {
-				send_s870(host);
+			spin_lock_irqsave(dev->host->host_lock, flags);			 			 
+			if (((dev->quhd[c] != dev->quend[c]) || (dev->last_cmd[c] != 0xff)) &&
+			    (dev->in_snd[c] == 0)) {
+#ifdef ED_DBGP
+				printk("Call sent_s870\n");
+#endif				
+				send_s870(dev,c);
 			}
 			spin_unlock_irqrestore(dev->host->host_lock, flags);
 			/*
-			 *      Done
+			 *	Done
 			 */
-			dev->in_int = 0;
-			goto out;
+			dev->in_int[c] = 0;
+#ifdef ED_DBGP
+				printk("Status 0x85 return\n");
+#endif				
+			goto handled;
 		}
 
 		if (i == 0x40) {
-			dev->last_cmd |= 0x40;
-			dev->in_int = 0;
-			goto out;
+		     dev->last_cmd[c] |= 0x40;
+		     dev->in_int[c] = 0;
+		     goto handled;
 		}
 
 		if (i == 0x21) {
-			if ((dev->last_cmd & 0xf0) != 0x40) {
-				dev->last_cmd = 0xff;
+			if ((dev->last_cmd[c] & 0xf0) != 0x40) {
+			   dev->last_cmd[c] = 0xff;
 			}
 			tmport -= 0x05;
-			adrcntu = 0;
-			((unsigned char *) &adrcntu)[2] = inb(tmport++);
-			((unsigned char *) &adrcntu)[1] = inb(tmport++);
-			((unsigned char *) &adrcntu)[0] = inb(tmport);
-			k = dev->id[target_id].last_lenu;
-			k -= adrcntu;
-			dev->id[target_id].tran_lenu = k;
-			dev->id[target_id].last_lenu = adrcntu;
+			adrcnt = 0;
+			((unsigned char *) &adrcnt)[2] = inb(tmport++);
+			((unsigned char *) &adrcnt)[1] = inb(tmport++);
+			((unsigned char *) &adrcnt)[0] = inb(tmport);
+			k = dev->id[c][target_id].last_len;
+			k -= adrcnt;
+			dev->id[c][target_id].tran_len = k;
+			dev->id[c][target_id].last_len = adrcnt;
 			tmport -= 0x04;
 			outb(0x41, tmport);
 			tmport += 0x08;
 			outb(0x08, tmport);
-			dev->in_int = 0;
-			goto out;
+			dev->in_int[c] = 0;
+			goto handled;
+		}
+
+		if (dev->dev_id == ATP885_DEVID) {
+			if ((i == 0x4c) || (i == 0x4d) || (i == 0x8c) || (i == 0x8d)) {
+		   		if ((i == 0x4c) || (i == 0x8c)) 
+		      			i=0x48;
+		   		else 
+		      			i=0x49;
+		   	}	
+			
 		}
 		if ((i == 0x80) || (i == 0x8f)) {
+#ifdef ED_DBGP
+			printk(KERN_DEBUG "Device reselect\n");
+#endif			
 			lun = 0;
 			tmport -= 0x07;
-			j = inb(tmport);
-			if (j == 0x44 || i == 0x80) {
+			if (cmdp == 0x44 || i==0x80) {
 				tmport += 0x0d;
 				lun = inb(tmport) & 0x07;
 			} else {
-				if ((dev->last_cmd & 0xf0) != 0x40) {
-					dev->last_cmd = 0xff;
+				if ((dev->last_cmd[c] & 0xf0) != 0x40) {
+				   dev->last_cmd[c] = 0xff;
 				}
-				if (j == 0x41) {
+				if (cmdp == 0x41) {
+#ifdef ED_DBGP
+					printk("cmdp = 0x41\n");
+#endif						
 					tmport += 0x02;
-					adrcntu = 0;
-					((unsigned char *) &adrcntu)[2] = inb(tmport++);
-					((unsigned char *) &adrcntu)[1] = inb(tmport++);
-					((unsigned char *) &adrcntu)[0] = inb(tmport);
-					k = dev->id[target_id].last_lenu;
-					k -= adrcntu;
-					dev->id[target_id].tran_lenu = k;
-					dev->id[target_id].last_lenu = adrcntu;
+					adrcnt = 0;
+					((unsigned char *) &adrcnt)[2] = inb(tmport++);
+					((unsigned char *) &adrcnt)[1] = inb(tmport++);
+					((unsigned char *) &adrcnt)[0] = inb(tmport);
+					k = dev->id[c][target_id].last_len;
+					k -= adrcnt;
+					dev->id[c][target_id].tran_len = k;
+					dev->id[c][target_id].last_len = adrcnt;
 					tmport += 0x04;
 					outb(0x08, tmport);
-					dev->in_int = 0;
-					goto out;
+					dev->in_int[c] = 0;
+					goto handled;
 				} else {
+#ifdef ED_DBGP
+					printk("cmdp != 0x41\n");
+#endif						
 					outb(0x46, tmport);
-					dev->id[target_id].dirctu = 0x00;
+					dev->id[c][target_id].dirct = 0x00;
 					tmport += 0x02;
 					outb(0x00, tmport++);
 					outb(0x00, tmport++);
 					outb(0x00, tmport++);
 					tmport += 0x03;
 					outb(0x08, tmport);
-					dev->in_int = 0;
-					goto out;
+					dev->in_int[c] = 0;
+					goto handled;
 				}
 			}
-			if (dev->last_cmd != 0xff) {
-				dev->last_cmd |= 0x40;
+			if (dev->last_cmd[c] != 0xff) {
+			   dev->last_cmd[c] |= 0x40;
 			}
-			tmport = workportu + 0x10;
-			outb(0x45, tmport);
-			tmport += 0x06;
+			if (dev->dev_id == ATP885_DEVID) {
+				j = inb(dev->baseport + 0x29) & 0xfe;
+				outb(j, dev->baseport + 0x29);
+				tmport = workport + 0x16;
+			} else {
+				tmport = workport + 0x10;
+				outb(0x45, tmport);
+				tmport += 0x06;				
+			}
+			
 			target_id = inb(tmport);
 			/*
-			 *      Remap wide identifiers
+			 *	Remap wide identifiers
 			 */
 			if ((target_id & 0x10) != 0) {
 				target_id = (target_id & 0x07) | 0x08;
 			} else {
 				target_id &= 0x07;
 			}
-			workrequ = dev->id[target_id].curr_req;
-			tmport = workportu + 0x0f;
+			if (dev->dev_id == ATP885_DEVID) {
+				tmport = workport + 0x10;
+				outb(0x45, tmport);
+			}
+			workreq = dev->id[c][target_id].curr_req;
+#ifdef ED_DBGP			
+			printk(KERN_DEBUG "Channel = %d ID = %d LUN = %d CDB",c,workreq->device->id,workreq->device->lun);
+			for(l=0;l<workreq->cmd_len;l++)
+			{
+				printk(KERN_DEBUG " %x",workreq->cmnd[l]);
+			}
+#endif	
+			
+			tmport = workport + 0x0f;
 			outb(lun, tmport);
 			tmport += 0x02;
-			outb(dev->id[target_id].devspu, tmport++);
-			adrcntu = dev->id[target_id].tran_lenu;
-			k = dev->id[target_id].last_lenu;
+			outb(dev->id[c][target_id].devsp, tmport++);
+			adrcnt = dev->id[c][target_id].tran_len;
+			k = dev->id[c][target_id].last_len;
+
 			outb(((unsigned char *) &k)[2], tmport++);
 			outb(((unsigned char *) &k)[1], tmport++);
 			outb(((unsigned char *) &k)[0], tmport++);
+#ifdef ED_DBGP			
+			printk("k %x, k[0] 0x%x k[1] 0x%x k[2] 0x%x\n", k, inb(tmport-1), inb(tmport-2), inb(tmport-3));
+#endif			
 			/* Remap wide */
 			j = target_id;
 			if (target_id > 7) {
 				j = (j & 0x07) | 0x40;
 			}
 			/* Add direction */
-			j |= dev->id[target_id].dirctu;
+			j |= dev->id[c][target_id].dirct;
 			outb(j, tmport++);
-			outb(0x80, tmport);
-
-			/* enable 32 bit fifo transfer */
-			if (dev->deviceid != 0x8081) {
-				tmport = workportu + 0x3a;
-				if ((dev->ata_cdbu[0] == 0x08) || (dev->ata_cdbu[0] == 0x28) || (dev->ata_cdbu[0] == 0x0a) || (dev->ata_cdbu[0] == 0x2a)) {
-					outb((unsigned char) ((inb(tmport) & 0xf3) | 0x08), tmport);
-				} else {
-					outb((unsigned char) (inb(tmport) & 0xf3), tmport);
+			outb(0x80,tmport);
+			
+			/* enable 32 bit fifo transfer */	
+			if (dev->dev_id == ATP885_DEVID) {
+				tmpcip = dev->pciport[c] + 1;
+				i=inb(tmpcip) & 0xf3;
+				//j=workreq->cmnd[0];	    		    	
+				if ((workreq->cmnd[0] == 0x08) || (workreq->cmnd[0] == 0x28) || (workreq->cmnd[0] == 0x0a) || (workreq->cmnd[0] == 0x2a)) {
+				   i |= 0x0c;
 				}
-			} else {
-				tmport = workportu - 0x05;
-				if ((dev->ata_cdbu[0] == 0x08) || (dev->ata_cdbu[0] == 0x28) || (dev->ata_cdbu[0] == 0x0a) || (dev->ata_cdbu[0] == 0x2a)) {
+				outb(i,tmpcip);		    		    		
+			} else if ((dev->dev_id == ATP880_DEVID1) ||
+	    		    	   (dev->dev_id == ATP880_DEVID2) ) {
+				tmport = workport - 0x05;
+				if ((workreq->cmnd[0] == 0x08) || (workreq->cmnd[0] == 0x28) || (workreq->cmnd[0] == 0x0a) || (workreq->cmnd[0] == 0x2a)) {
 					outb((unsigned char) ((inb(tmport) & 0x3f) | 0xc0), tmport);
 				} else {
 					outb((unsigned char) (inb(tmport) & 0x3f), tmport);
 				}
-			}
-
-			tmport = workportu + 0x1b;
+			} else {				
+				tmport = workport + 0x3a;
+				if ((workreq->cmnd[0] == 0x08) || (workreq->cmnd[0] == 0x28) || (workreq->cmnd[0] == 0x0a) || (workreq->cmnd[0] == 0x2a)) {
+					outb((unsigned char) ((inb(tmport) & 0xf3) | 0x08), tmport);
+				} else {
+					outb((unsigned char) (inb(tmport) & 0xf3), tmport);
+				}														
+			}	
+			tmport = workport + 0x1b;
 			j = 0;
 			id = 1;
 			id = id << target_id;
 			/*
-			 *      Is this a wide device
+			 *	Is this a wide device
 			 */
-			if ((id & dev->wide_idu) != 0) {
+			if ((id & dev->wide_id[c]) != 0) {
 				j |= 0x01;
 			}
 			outb(j, tmport);
 			while ((inb(tmport) & 0x01) != j) {
-				outb(j, tmport);
+			   outb(j,tmport);
 			}
-
-			if (dev->id[target_id].last_lenu == 0) {
-				tmport = workportu + 0x18;
+			if (dev->id[c][target_id].last_len == 0) {
+				tmport = workport + 0x18;
 				outb(0x08, tmport);
-				dev->in_int = 0;
-				goto out;
-			}
-			prd = dev->id[target_id].prd_posu;
-			while (adrcntu != 0) {
-				id = ((unsigned short int *) (prd))[2];
+				dev->in_int[c] = 0;
+#ifdef ED_DBGP
+				printk("dev->id[c][target_id].last_len = 0\n");
+#endif					
+				goto handled;
+			}
+#ifdef ED_DBGP
+			printk("target_id = %d adrcnt = %d\n",target_id,adrcnt);
+#endif			
+			prd = dev->id[c][target_id].prd_pos;
+			while (adrcnt != 0) {
+				id = ((unsigned short int *)prd)[2];
 				if (id == 0) {
 					k = 0x10000;
 				} else {
 					k = id;
 				}
-				if (k > adrcntu) {
-					((unsigned short int *) (prd))[2] = (unsigned short int)
-					    (k - adrcntu);
-					((unsigned long *) (prd))[0] += adrcntu;
-					adrcntu = 0;
-					dev->id[target_id].prd_posu = prd;
+				if (k > adrcnt) {
+					((unsigned short int *)prd)[2] = (unsigned short int)
+					    (k - adrcnt);
+					((unsigned long *)prd)[0] += adrcnt;
+					adrcnt = 0;
+					dev->id[c][target_id].prd_pos = prd;
 				} else {
-					adrcntu -= k;
-					dev->id[target_id].prdaddru += 0x08;
+					adrcnt -= k;
+					dev->id[c][target_id].prdaddr += 0x08;
 					prd += 0x08;
-					if (adrcntu == 0) {
-						dev->id[target_id].prd_posu = prd;
+					if (adrcnt == 0) {
+						dev->id[c][target_id].prd_pos = prd;
 					}
-				}
+				}				
 			}
-			tmpcip = dev->pciport + 0x04;
-			outl(dev->id[target_id].prdaddru, tmpcip);
-			tmpcip -= 0x02;
-			outb(0x06, tmpcip);
-			outb(0x00, tmpcip);
-			tmpcip -= 0x02;
-			tmport = workportu + 0x18;
+			tmpcip = dev->pciport[c] + 0x04;
+			outl(dev->id[c][target_id].prdaddr, tmpcip);
+#ifdef ED_DBGP
+			printk("dev->id[%d][%d].prdaddr 0x%8x\n", c, target_id, dev->id[c][target_id].prdaddr);
+#endif
+			if (dev->dev_id == ATP885_DEVID) {
+				tmpcip -= 0x04;
+			} else {
+				tmpcip -= 0x02;
+				outb(0x06, tmpcip);
+				outb(0x00, tmpcip);
+				tmpcip -= 0x02;
+			}
+			tmport = workport + 0x18;
 			/*
-			 *      Check transfer direction
+			 *	Check transfer direction
 			 */
-			if (dev->id[target_id].dirctu != 0) {
+			if (dev->id[c][target_id].dirct != 0) {
 				outb(0x08, tmport);
 				outb(0x01, tmpcip);
-				dev->in_int = 0;
-				goto out;
+				dev->in_int[c] = 0;
+#ifdef ED_DBGP
+				printk("status 0x80 return dirct != 0\n");
+#endif				
+				goto handled;
 			}
 			outb(0x08, tmport);
 			outb(0x09, tmpcip);
-			dev->in_int = 0;
-			goto out;
+			dev->in_int[c] = 0;
+#ifdef ED_DBGP
+			printk("status 0x80 return dirct = 0\n");
+#endif			
+			goto handled;
 		}
 
 		/*
-		 *      Current scsi request on this target
+		 *	Current scsi request on this target
 		 */
 
-		workrequ = dev->id[target_id].curr_req;
+		workreq = dev->id[c][target_id].curr_req;
 
 		if (i == 0x42) {
-			if ((dev->last_cmd & 0xf0) != 0x40) {
-				dev->last_cmd = 0xff;
+			if ((dev->last_cmd[c] & 0xf0) != 0x40)
+			{
+			   dev->last_cmd[c] = 0xff;
 			}
 			errstus = 0x02;
-			workrequ->result = errstus;
+			workreq->result = errstus;
 			goto go_42;
 		}
 		if (i == 0x16) {
-			if ((dev->last_cmd & 0xf0) != 0x40) {
-				dev->last_cmd = 0xff;
+			if ((dev->last_cmd[c] & 0xf0) != 0x40) {
+			   dev->last_cmd[c] = 0xff;
 			}
 			errstus = 0;
 			tmport -= 0x08;
 			errstus = inb(tmport);
-			workrequ->result = errstus;
+			if (((dev->r1f[c][target_id] & 0x10) != 0)&&(dev->dev_id==ATP885_DEVID)) {
+			   printk(KERN_WARNING "AEC67162 CRC ERROR !\n");
+			   errstus = 0x02;
+			}
+			workreq->result = errstus;
 go_42:
+			if (dev->dev_id == ATP885_DEVID) {		
+				j = inb(dev->baseport + 0x29) | 0x01;
+				outb(j, dev->baseport + 0x29);
+			}
 			/*
-			 *      Complete the command
+			 *	Complete the command
 			 */
-			 
-			if (workrequ->use_sg) {
+			if (workreq->use_sg) {
 				pci_unmap_sg(dev->pdev,
-					(struct scatterlist *)workrequ->buffer,
-					workrequ->use_sg,
-					workrequ->sc_data_direction);
-			} else if (workrequ->request_bufflen &&
-					workrequ->sc_data_direction != DMA_NONE) {
+					(struct scatterlist *)workreq->buffer,
+					workreq->use_sg,
+					workreq->sc_data_direction);
+			} else if (workreq->request_bufflen &&
+					workreq->sc_data_direction != DMA_NONE) {
 				pci_unmap_single(dev->pdev,
-					workrequ->SCp.dma_handle,
-					workrequ->request_bufflen,
-					workrequ->sc_data_direction);
-			}
+					workreq->SCp.dma_handle,
+					workreq->request_bufflen,
+					workreq->sc_data_direction);
+			}			
 			spin_lock_irqsave(dev->host->host_lock, flags);
-			(*workrequ->scsi_done) (workrequ);
-
+			(*workreq->scsi_done) (workreq);
+#ifdef ED_DBGP
+			   printk("workreq->scsi_done\n");
+#endif	
 			/*
-			 *      Clear it off the queue
+			 *	Clear it off the queue
 			 */
-			dev->id[target_id].curr_req = NULL;
-			dev->working--;
+			dev->id[c][target_id].curr_req = 0;
+			dev->working[c]--;
 			spin_unlock_irqrestore(dev->host->host_lock, flags);
 			/*
 			 *      Take it back wide
 			 */
-			if (dev->wide_idu != 0) {
-				tmport = workportu + 0x1b;
+			if (dev->wide_id[c] != 0) {
+				tmport = workport + 0x1b;
 				outb(0x01, tmport);
 				while ((inb(tmport) & 0x01) != 0x01) {
 					outb(0x01, tmport);
-				}
-			}
+				}       
+			} 
 			/*
-			 *      If there is stuff to send and nothing going then send it
+			 *	If there is stuff to send and nothing going then send it
 			 */
 			spin_lock_irqsave(dev->host->host_lock, flags);
-			if (((dev->last_cmd != 0xff) || (dev->quhdu != dev->quendu)) && (dev->in_snd == 0)) {
-				send_s870(host);
+			if (((dev->last_cmd[c] != 0xff) || (dev->quhd[c] != dev->quend[c])) &&
+			    (dev->in_snd[c] == 0)) {
+#ifdef ED_DBGP
+			   printk("Call sent_s870(scsi_done)\n");
+#endif				   
+			   send_s870(dev,c);
 			}
 			spin_unlock_irqrestore(dev->host->host_lock, flags);
-			dev->in_int = 0;
-			goto out;
+			dev->in_int[c] = 0;
+			goto handled;
 		}
-		if ((dev->last_cmd & 0xf0) != 0x40) {
-			dev->last_cmd = 0xff;
+		if ((dev->last_cmd[c] & 0xf0) != 0x40) {
+		   dev->last_cmd[c] = 0xff;
 		}
 		if (i == 0x4f) {
 			i = 0x89;
 		}
 		i &= 0x0f;
 		if (i == 0x09) {
-			tmpcip = tmpcip + 4;
-			outl(dev->id[target_id].prdaddru, tmpcip);
+			tmpcip += 4;
+			outl(dev->id[c][target_id].prdaddr, tmpcip);
 			tmpcip = tmpcip - 2;
 			outb(0x06, tmpcip);
 			outb(0x00, tmpcip);
 			tmpcip = tmpcip - 2;
-			tmport = workportu + 0x10;
+			tmport = workport + 0x10;
 			outb(0x41, tmport);
-			dev->id[target_id].dirctu = 0x00;
-			tmport += 0x08;
+			if (dev->dev_id == ATP885_DEVID) {
+				tmport += 2;
+				k = dev->id[c][target_id].last_len;
+				outb((unsigned char) (((unsigned char *) (&k))[2]), tmport++);
+				outb((unsigned char) (((unsigned char *) (&k))[1]), tmport++);
+				outb((unsigned char) (((unsigned char *) (&k))[0]), tmport);
+				dev->id[c][target_id].dirct = 0x00;
+				tmport += 0x04;
+			} else {
+				dev->id[c][target_id].dirct = 0x00;
+				tmport += 0x08;				
+			}
 			outb(0x08, tmport);
 			outb(0x09, tmpcip);
-			dev->in_int = 0;
-			goto out;
+			dev->in_int[c] = 0;
+			goto handled;
 		}
 		if (i == 0x08) {
-			tmpcip = tmpcip + 4;
-			outl(dev->id[target_id].prdaddru, tmpcip);
+			tmpcip += 4;
+			outl(dev->id[c][target_id].prdaddr, tmpcip);
 			tmpcip = tmpcip - 2;
 			outb(0x06, tmpcip);
 			outb(0x00, tmpcip);
 			tmpcip = tmpcip - 2;
-			tmport = workportu + 0x10;
+			tmport = workport + 0x10;
 			outb(0x41, tmport);
-			tmport += 0x05;
+			if (dev->dev_id == ATP885_DEVID) {		
+				tmport += 2;
+				k = dev->id[c][target_id].last_len;
+				outb((unsigned char) (((unsigned char *) (&k))[2]), tmport++);
+				outb((unsigned char) (((unsigned char *) (&k))[1]), tmport++);
+				outb((unsigned char) (((unsigned char *) (&k))[0]), tmport++);
+			} else {
+				tmport += 5;
+			}
 			outb((unsigned char) (inb(tmport) | 0x20), tmport);
-			dev->id[target_id].dirctu = 0x20;
+			dev->id[c][target_id].dirct = 0x20;
 			tmport += 0x03;
 			outb(0x08, tmport);
 			outb(0x01, tmpcip);
-			dev->in_int = 0;
-			goto out;
+			dev->in_int[c] = 0;
+			goto handled;
 		}
 		tmport -= 0x07;
 		if (i == 0x0a) {
@@ -434,25 +584,29 @@
 		} else {
 			outb(0x46, tmport);
 		}
-		dev->id[target_id].dirctu = 0x00;
+		dev->id[c][target_id].dirct = 0x00;
 		tmport += 0x02;
 		outb(0x00, tmport++);
 		outb(0x00, tmport++);
 		outb(0x00, tmport++);
 		tmport += 0x03;
 		outb(0x08, tmport);
-		dev->in_int = 0;
-		goto out;
+		dev->in_int[c] = 0;
+		goto handled;
 	} else {
-//              tmport = workportu + 0x17;
-//              inb(tmport);
-//              dev->working = 0;
-		dev->in_int = 0;
+//		tmport = workport + 0x17;
+//		inb(tmport);
+//		dev->working[c] = 0;
+		dev->in_int[c] = 0;
+		goto handled;
 	}
-out:
+	
+handled:
+#ifdef ED_DBGP
+	printk("atp870u_intr_handle exit\n");
+#endif			
 	return IRQ_HANDLED;
 }
-
 /**
  *	atp870u_queuecommand	-	Queue SCSI command
  *	@req_p: request block
@@ -460,24 +614,30 @@
  *
  *	Queue a command to the ATP queue. Called with the host lock held.
  */
- 
-static int atp870u_queuecommand(struct scsi_cmnd *req_p,
-		void (*done) (struct scsi_cmnd *))
+int atp870u_queuecommand(struct scsi_cmnd * req_p, void (*done) (struct scsi_cmnd *))
 {
-	unsigned short int m;
-	unsigned int tmport;
-	struct Scsi_Host *host;
+	unsigned char c;
+	unsigned int tmport,m;	
 	struct atp_unit *dev;
+	struct Scsi_Host *host;
 
-	if (req_p->device->channel != 0) {
+	c = req_p->device->channel;	
+	req_p->sense_buffer[0]=0;
+	req_p->resid = 0;
+	if (req_p->device->channel > 1) {
 		req_p->result = 0x00040000;
 		done(req_p);
+#ifdef ED_DBGP		
+		printk("atp870u_queuecommand : req_p->device->channel > 1\n");	
+#endif			
 		return 0;
-	};
+	}
 
 	host = req_p->device->host;
 	dev = (struct atp_unit *)&host->hostdata;
-	
+		
+
+		
 	m = 1;
 	m = m << req_p->device->id;
 
@@ -485,44 +645,60 @@
 	 *      Fake a timeout for missing targets
 	 */
 
-	if ((m & dev->active_idu) == 0) {
+	if ((m & dev->active_id[c]) == 0) {
 		req_p->result = 0x00040000;
 		done(req_p);
 		return 0;
 	}
+
 	if (done) {
 		req_p->scsi_done = done;
 	} else {
-		printk(KERN_WARNING "atp870u_queuecommand: done can't be NULL\n");
+#ifdef ED_DBGP		
+		printk( "atp870u_queuecommand: done can't be NULL\n");
+#endif		
 		req_p->result = 0;
 		done(req_p);
 		return 0;
 	}
+	
 	/*
-	 *      Count new command
+	 *	Count new command
 	 */
-
-	dev->quendu++;
-	if (dev->quendu >= qcnt) {
-		dev->quendu = 0;
+	dev->quend[c]++;
+	if (dev->quend[c] >= qcnt) {
+		dev->quend[c] = 0;
 	}
+	
 	/*
-	 *      Check queue state
+	 *	Check queue state
 	 */
-	if (dev->quhdu == dev->quendu) {
-		if (dev->quendu == 0) {
-			dev->quendu = qcnt;
-		}
-		dev->quendu--;
+	if (dev->quhd[c] == dev->quend[c]) {
+		if (dev->quend[c] == 0) {
+			dev->quend[c] = qcnt;
+		}
+#ifdef ED_DBGP		
+		printk("atp870u_queuecommand : dev->quhd[c] == dev->quend[c]\n");
+#endif		
+		dev->quend[c]--;
 		req_p->result = 0x00020000;
-		done(req_p);
+		done(req_p);	
 		return 0;
 	}
-	dev->querequ[dev->quendu] = req_p;
-	tmport = dev->ioport + 0x1c;
-	if ((inb(tmport) == 0) && (dev->in_int == 0) && (dev->in_snd == 0)) {
-		send_s870(host);
-	}
+	dev->quereq[c][dev->quend[c]] = req_p;
+	tmport = dev->ioport[c] + 0x1c;
+#ifdef ED_DBGP	
+	printk("dev->ioport[c] = %x inb(tmport) = %x dev->in_int[%d] = %d dev->in_snd[%d] = %d\n",dev->ioport[c],inb(tmport),c,dev->in_int[c],c,dev->in_snd[c]);
+#endif
+	if ((inb(tmport) == 0) && (dev->in_int[c] == 0) && (dev->in_snd[c] == 0)) {
+#ifdef ED_DBGP
+		printk("Call sent_s870(atp870u_queuecommand)\n");
+#endif		
+		send_s870(dev,c);
+	}
+#ifdef ED_DBGP	
+	printk("atp870u_queuecommand : exit\n");
+#endif	
 	return 0;
 }
 
@@ -535,194 +711,270 @@
  *
  *	Caller holds the host lock.
  */
- 
-static void send_s870(struct Scsi_Host *host)
+void send_s870(struct atp_unit *dev,unsigned char c)
 {
 	unsigned int tmport;
-	struct scsi_cmnd *workrequ;
-	unsigned int i;
-	unsigned char j, target_id;
+	struct scsi_cmnd *workreq;
+	unsigned int i;//,k;
+	unsigned char  j, target_id;
 	unsigned char *prd;
 	unsigned short int tmpcip, w;
-	unsigned long l;
-	dma_addr_t bttl;
-	unsigned int workportu;
+	unsigned long l, bttl = 0;
+	unsigned int workport;
 	struct scatterlist *sgpnt;
-	struct atp_unit *dev = (struct atp_unit *)&host->hostdata;
-	int sg_count;
+	unsigned long  sg_count;
 
-	if (dev->in_snd != 0) {
+	if (dev->in_snd[c] != 0) {
+#ifdef ED_DBGP		
+		printk("cmnd in_snd\n");
+#endif
 		return;
 	}
-	dev->in_snd = 1;
-	if ((dev->last_cmd != 0xff) && ((dev->last_cmd & 0x40) != 0)) {
-		dev->last_cmd &= 0x0f;
-		workrequ = dev->id[dev->last_cmd].curr_req;
-		if (workrequ != NULL) {	/* check NULL pointer */
-			goto cmd_subp;
-		}
-		dev->last_cmd = 0xff;
-		if (dev->quhdu == dev->quendu) {
-			dev->in_snd = 0;
-			return;
-		}
-	}
-	if ((dev->last_cmd != 0xff) && (dev->working != 0)) {
-		dev->in_snd = 0;
-		return;
-	}
-	dev->working++;
-	j = dev->quhdu;
-	dev->quhdu++;
-	if (dev->quhdu >= qcnt) {
-		dev->quhdu = 0;
-	}
-	workrequ = dev->querequ[dev->quhdu];
-	if (dev->id[workrequ->device->id].curr_req == 0) {
-		dev->id[workrequ->device->id].curr_req = workrequ;
-		dev->last_cmd = workrequ->device->id;
+#ifdef ED_DBGP
+	printk("Sent_s870 enter\n");
+#endif
+	dev->in_snd[c] = 1;
+	if ((dev->last_cmd[c] != 0xff) && ((dev->last_cmd[c] & 0x40) != 0)) {
+		dev->last_cmd[c] &= 0x0f;
+		workreq = dev->id[c][dev->last_cmd[c]].curr_req;
+		if (workreq != NULL) {	/* check NULL pointer */
+		   goto cmd_subp;
+		}
+		dev->last_cmd[c] = 0xff;	
+		if (dev->quhd[c] == dev->quend[c]) {
+		   	dev->in_snd[c] = 0;
+		   	return ;
+		}
+	}
+	if ((dev->last_cmd[c] != 0xff) && (dev->working[c] != 0)) {
+	     	dev->in_snd[c] = 0;
+	     	return ;
+	}
+	dev->working[c]++;
+	j = dev->quhd[c];
+	dev->quhd[c]++;
+	if (dev->quhd[c] >= qcnt) {
+		dev->quhd[c] = 0;
+	}
+	workreq = dev->quereq[c][dev->quhd[c]];
+	if (dev->id[c][workreq->device->id].curr_req == 0) {	
+		dev->id[c][workreq->device->id].curr_req = workreq;
+		dev->last_cmd[c] = workreq->device->id;
 		goto cmd_subp;
-	}
-	dev->quhdu = j;
-	dev->working--;
-	dev->in_snd = 0;
+	}	
+	dev->quhd[c] = j;
+	dev->working[c]--;
+	dev->in_snd[c] = 0;
 	return;
 cmd_subp:
-	workportu = dev->ioport;
-	tmport = workportu + 0x1f;
+	workport = dev->ioport[c];
+	tmport = workport + 0x1f;
 	if ((inb(tmport) & 0xb0) != 0) {
 		goto abortsnd;
 	}
-	tmport = workportu + 0x1c;
+	tmport = workport + 0x1c;
 	if (inb(tmport) == 0) {
 		goto oktosend;
 	}
 abortsnd:
-	dev->last_cmd |= 0x40;
-	dev->in_snd = 0;
+#ifdef ED_DBGP
+	printk("Abort to Send\n");
+#endif
+	dev->last_cmd[c] |= 0x40;
+	dev->in_snd[c] = 0;
 	return;
 oktosend:
-	memcpy(&dev->ata_cdbu[0], &workrequ->cmnd[0], workrequ->cmd_len);
-	if (dev->ata_cdbu[0] == READ_CAPACITY) {
-		if (workrequ->request_bufflen > 8) {
-			workrequ->request_bufflen = 0x08;
+#ifdef ED_DBGP
+	printk("OK to Send\n");
+	printk("CDB");
+	for(i=0;i<workreq->cmd_len;i++) {
+		printk(" %x",workreq->cmnd[i]);
+	}
+	printk("\nChannel = %d ID = %d LUN = %d\n",c,workreq->device->id,workreq->device->lun);
+#endif	
+	if (dev->dev_id == ATP885_DEVID) {
+		j = inb(dev->baseport + 0x29) & 0xfe;
+		outb(j, dev->baseport + 0x29);
+		dev->r1f[c][workreq->device->id] = 0;
+	}
+	
+	if (workreq->cmnd[0] == READ_CAPACITY) {
+		if (workreq->request_bufflen > 8) {
+			workreq->request_bufflen = 0x08;
 		}
 	}
-	if (dev->ata_cdbu[0] == 0x00) {
-		workrequ->request_bufflen = 0;
+	if (workreq->cmnd[0] == 0x00) {
+		workreq->request_bufflen = 0;
 	}
 
-	tmport = workportu + 0x1b;
+	tmport = workport + 0x1b;
 	j = 0;
-	target_id = workrequ->device->id;
+	target_id = workreq->device->id;
 
 	/*
-	 *      Wide ?
+	 *	Wide ?
 	 */
 	w = 1;
 	w = w << target_id;
-	if ((w & dev->wide_idu) != 0) {
+	if ((w & dev->wide_id[c]) != 0) {
 		j |= 0x01;
 	}
 	outb(j, tmport);
 	while ((inb(tmport) & 0x01) != j) {
-		outb(j, tmport);
+	   outb(j,tmport);
+#ifdef ED_DBGP
+	   printk("send_s870 while loop 1\n");
+#endif
 	}
-
 	/*
-	 *      Write the command
+	 *	Write the command
 	 */
 
-	tmport = workportu;
-	outb(workrequ->cmd_len, tmport++);
+	tmport = workport;
+	outb(workreq->cmd_len, tmport++);
 	outb(0x2c, tmport++);
-	outb(0xcf, tmport++);
-	for (i = 0; i < workrequ->cmd_len; i++) {
-		outb(dev->ata_cdbu[i], tmport++);
+	if (dev->dev_id == ATP885_DEVID) {
+		outb(0x7f, tmport++);
+	} else {
+		outb(0xcf, tmport++); 	
+	}	
+	for (i = 0; i < workreq->cmd_len; i++) {
+		outb(workreq->cmnd[i], tmport++);
 	}
-	tmport = workportu + 0x0f;
-	outb(workrequ->device->lun, tmport);
+	tmport = workport + 0x0f;
+	outb(workreq->device->lun, tmport);
 	tmport += 0x02;
 	/*
-	 *      Write the target
+	 *	Write the target
 	 */
-	outb(dev->id[target_id].devspu, tmport++);
-
+	outb(dev->id[c][target_id].devsp, tmport++);	 
+#ifdef ED_DBGP	
+	printk("dev->id[%d][%d].devsp = %2x\n",c,target_id,dev->id[c][target_id].devsp);
+#endif
 	/*
-	 *      Figure out the transfer size
+	 *	Figure out the transfer size
 	 */
-	if (workrequ->use_sg) {
+	if (workreq->use_sg) {
+#ifdef ED_DBGP
+		printk("Using SGL\n");
+#endif		
 		l = 0;
-		sgpnt = (struct scatterlist *) workrequ->request_buffer;
-		sg_count = pci_map_sg(dev->pdev, sgpnt, workrequ->use_sg,
-				workrequ->sc_data_direction);
-		for (i = 0; i < workrequ->use_sg; i++) {
-			if (sgpnt[i].length == 0 || workrequ->use_sg > ATP870U_SCATTER) {
+		
+		sgpnt = (struct scatterlist *) workreq->request_buffer;
+		sg_count = pci_map_sg(dev->pdev, sgpnt, workreq->use_sg,
+	   			workreq->sc_data_direction);		
+		
+		for (i = 0; i < workreq->use_sg; i++) {
+			if (sgpnt[i].length == 0 || workreq->use_sg > ATP870U_SCATTER) {
 				panic("Foooooooood fight!");
 			}
 			l += sgpnt[i].length;
 		}
-	} else if(workrequ->request_bufflen && workrequ->sc_data_direction != PCI_DMA_NONE) {
-		workrequ->SCp.dma_handle = pci_map_single(dev->pdev,
-				workrequ->request_buffer,
-				workrequ->request_bufflen,
-				workrequ->sc_data_direction);
-		l = workrequ->request_bufflen;
-	}
-	else l = 0;
+#ifdef ED_DBGP		
+		printk( "send_s870: workreq->use_sg %d, sg_count %d l %8ld\n", workreq->use_sg, sg_count, l);
+#endif
+	} else if(workreq->request_bufflen && workreq->sc_data_direction != PCI_DMA_NONE) {
+#ifdef ED_DBGP
+		printk("Not using SGL\n");
+#endif					
+		workreq->SCp.dma_handle = pci_map_single(dev->pdev, workreq->request_buffer,
+				workreq->request_bufflen,
+				workreq->sc_data_direction);		
+		l = workreq->request_bufflen;
+#ifdef ED_DBGP		
+		printk( "send_s870: workreq->use_sg %d, l %8ld\n", workreq->use_sg, l);
+#endif
+	} else l = 0;
 	/*
-	 *      Write transfer size
+	 *	Write transfer size
 	 */
 	outb((unsigned char) (((unsigned char *) (&l))[2]), tmport++);
 	outb((unsigned char) (((unsigned char *) (&l))[1]), tmport++);
 	outb((unsigned char) (((unsigned char *) (&l))[0]), tmport++);
-	j = target_id;
-	dev->id[j].last_lenu = l;
-	dev->id[j].tran_lenu = 0;
+	j = target_id;	
+	dev->id[c][j].last_len = l;
+	dev->id[c][j].tran_len = 0;
+#ifdef ED_DBGP	
+	printk("dev->id[%2d][%2d].last_len = %d\n",c,j,dev->id[c][j].last_len);
+#endif	
 	/*
-	 *      Flip the wide bits
+	 *	Flip the wide bits
 	 */
 	if ((j & 0x08) != 0) {
 		j = (j & 0x07) | 0x40;
 	}
 	/*
-	 *      Check transfer direction
+	 *	Check transfer direction
 	 */
-	if (workrequ->sc_data_direction == DMA_TO_DEVICE) {
+	if (workreq->sc_data_direction == DMA_TO_DEVICE) {
 		outb((unsigned char) (j | 0x20), tmport++);
 	} else {
 		outb(j, tmport++);
 	}
 	outb((unsigned char) (inb(tmport) | 0x80), tmport);
 	outb(0x80, tmport);
-	tmport = workportu + 0x1c;
-	dev->id[target_id].dirctu = 0;
+	tmport = workport + 0x1c;
+	dev->id[c][target_id].dirct = 0;
 	if (l == 0) {
 		if (inb(tmport) == 0) {
-			tmport = workportu + 0x18;
+			tmport = workport + 0x18;
+#ifdef ED_DBGP
+			printk("change SCSI_CMD_REG 0x08\n");	
+#endif				
 			outb(0x08, tmport);
 		} else {
-			dev->last_cmd |= 0x40;
+			dev->last_cmd[c] |= 0x40;
 		}
-		dev->in_snd = 0;
+		dev->in_snd[c] = 0;
 		return;
 	}
-	tmpcip = dev->pciport;
-	prd = dev->id[target_id].prd_tableu;
-	dev->id[target_id].prd_posu = prd;
+	tmpcip = dev->pciport[c];
+	prd = dev->id[c][target_id].prd_table;
+	dev->id[c][target_id].prd_pos = prd;
 
 	/*
-	 *      Now write the request list. Either as scatter/gather or as
-	 *      a linear chain.
+	 *	Now write the request list. Either as scatter/gather or as
+	 *	a linear chain.
 	 */
 
-	if (workrequ->use_sg) {
-		sgpnt = (struct scatterlist *) workrequ->request_buffer;
+	if (workreq->use_sg) {
+		sgpnt = (struct scatterlist *) workreq->request_buffer;
 		i = 0;
-		for (j = 0; j < workrequ->use_sg; j++) {
+		for (j = 0; j < workreq->use_sg; j++) {
 			bttl = sg_dma_address(&sgpnt[j]);
-			l = sg_dma_len(&sgpnt[j]);
+			l=sg_dma_len(&sgpnt[j]);
+#ifdef ED_DBGP		
+		printk("1. bttl %x, l %x\n",bttl, l);
+#endif			
 			while (l > 0x10000) {
+					(((u16 *) (prd))[i + 3]) = 0x0000;
+					(((u16 *) (prd))[i + 2]) = 0x0000;
+					(((u32 *) (prd))[i >> 1]) = cpu_to_le32(bttl);
+					l -= 0x10000;
+					bttl += 0x10000;
+					i += 0x04;
+				}
+				(((u32 *) (prd))[i >> 1]) = cpu_to_le32(bttl);
+				(((u16 *) (prd))[i + 2]) = cpu_to_le16(l);
+				(((u16 *) (prd))[i + 3]) = 0;
+				i += 0x04;			
+		}
+		(((u16 *) (prd))[i - 1]) = cpu_to_le16(0x8000);	
+#ifdef ED_DBGP		
+		printk("prd %4x %4x %4x %4x\n",(((unsigned short int *)prd)[0]),(((unsigned short int *)prd)[1]),(((unsigned short int *)prd)[2]),(((unsigned short int *)prd)[3]));
+		printk("2. bttl %x, l %x\n",bttl, l);
+#endif			
+	} else {
+		/*
+		 *	For a linear request write a chain of blocks
+		 */        
+		bttl = workreq->SCp.dma_handle;
+		l = workreq->request_bufflen;
+		i = 0;
+#ifdef ED_DBGP		
+		printk("3. bttl %x, l %x\n",bttl, l);
+#endif			
+		while (l > 0x10000) {
 				(((u16 *) (prd))[i + 3]) = 0x0000;
 				(((u16 *) (prd))[i + 2]) = 0x0000;
 				(((u32 *) (prd))[i >> 1]) = cpu_to_le32(bttl);
@@ -730,76 +982,80 @@
 				bttl += 0x10000;
 				i += 0x04;
 			}
-			(((u32 *) (prd))[i >> 1]) = cpu_to_le32(bttl);
+			(((u16 *) (prd))[i + 3]) = cpu_to_le16(0x8000);
 			(((u16 *) (prd))[i + 2]) = cpu_to_le16(l);
-			(((u16 *) (prd))[i + 3]) = 0;
-			i += 0x04;
-		}
-		(((u16 *) (prd))[i - 1]) = cpu_to_le16(0x8000);
-	} else {
-		/*
-		 *      For a linear request write a chain of blocks
-		 */
-		bttl = workrequ->SCp.dma_handle;
-		l = workrequ->request_bufflen;
-		i = 0;
-		while (l > 0x10000) {
-			(((u16 *) (prd))[i + 3]) = 0x0000;
-			(((u16 *) (prd))[i + 2]) = 0x0000;
-			(((u32 *) (prd))[i >> 1]) = cpu_to_le32(bttl);
-			l -= 0x10000;
-			bttl += 0x10000;
-			i += 0x04;
-		}
-		(((u16 *) (prd))[i + 3]) = cpu_to_le16(0x8000);
-		(((u16 *) (prd))[i + 2]) = cpu_to_le16(l);
-		(((u32 *) (prd))[i >> 1]) = cpu_to_le32(bttl);
-	}
-	tmpcip = tmpcip + 4;
-	dev->id[target_id].prdaddru = dev->id[target_id].prd_phys;
-	outl(dev->id[target_id].prd_phys, tmpcip);
+			(((u32 *) (prd))[i >> 1]) = cpu_to_le32(bttl);		
+#ifdef ED_DBGP		
+		printk("prd %4x %4x %4x %4x\n",(((unsigned short int *)prd)[0]),(((unsigned short int *)prd)[1]),(((unsigned short int *)prd)[2]),(((unsigned short int *)prd)[3]));
+		printk("4. bttl %x, l %x\n",bttl, l);
+#endif			
+		
+	}
+	tmpcip += 4;
+#ifdef ED_DBGP		
+	printk("send_s870: prdaddr_2 0x%8x tmpcip %x target_id %d\n", dev->id[c][target_id].prdaddr,tmpcip,target_id);
+#endif	
+	outl(dev->id[c][target_id].prdaddr, tmpcip);
 	tmpcip = tmpcip - 2;
 	outb(0x06, tmpcip);
 	outb(0x00, tmpcip);
-	tmpcip = tmpcip - 2;
-
-	if (dev->deviceid != 0x8081) {
-		tmport = workportu + 0x3a;
-		if ((dev->ata_cdbu[0] == 0x08) || (dev->ata_cdbu[0] == 0x28) || (dev->ata_cdbu[0] == 0x0a) || (dev->ata_cdbu[0] == 0x2a)) {
-			outb((inb(tmport) & 0xf3) | 0x08, tmport);
-		} else {
-			outb(inb(tmport) & 0xf3, tmport);
-		}
-	} else {
-		tmport = workportu - 0x05;
-		if ((dev->ata_cdbu[0] == 0x08) || (dev->ata_cdbu[0] == 0x28) || (dev->ata_cdbu[0] == 0x0a) || (dev->ata_cdbu[0] == 0x2a)) {
+	if (dev->dev_id == ATP885_DEVID) {
+		tmpcip--;
+		j=inb(tmpcip) & 0xf3;
+		if ((workreq->cmnd[0] == 0x08) || (workreq->cmnd[0] == 0x28) ||
+	    	(workreq->cmnd[0] == 0x0a) || (workreq->cmnd[0] == 0x2a)) {
+	   		j |= 0x0c;
+		}
+		outb(j,tmpcip);
+		tmpcip--;	    	
+	} else if ((dev->dev_id == ATP880_DEVID1) ||
+	    	   (dev->dev_id == ATP880_DEVID2)) {
+		tmpcip =tmpcip -2;	
+		tmport = workport - 0x05;
+		if ((workreq->cmnd[0] == 0x08) || (workreq->cmnd[0] == 0x28) || (workreq->cmnd[0] == 0x0a) || (workreq->cmnd[0] == 0x2a)) {
 			outb((unsigned char) ((inb(tmport) & 0x3f) | 0xc0), tmport);
 		} else {
 			outb((unsigned char) (inb(tmport) & 0x3f), tmport);
-		}
-	}
-	tmport = workportu + 0x1c;
+		}		
+	} else {		
+		tmpcip =tmpcip -2;
+		tmport = workport + 0x3a;
+		if ((workreq->cmnd[0] == 0x08) || (workreq->cmnd[0] == 0x28) || (workreq->cmnd[0] == 0x0a) || (workreq->cmnd[0] == 0x2a)) {
+			outb((inb(tmport) & 0xf3) | 0x08, tmport);
+		} else {
+			outb(inb(tmport) & 0xf3, tmport);
+		}		
+	}	
+	tmport = workport + 0x1c;
 
-	if (workrequ->sc_data_direction == DMA_TO_DEVICE) {
-		dev->id[target_id].dirctu = 0x20;
+	if(workreq->sc_data_direction == DMA_TO_DEVICE) {
+		dev->id[c][target_id].dirct = 0x20;
 		if (inb(tmport) == 0) {
-			tmport = workportu + 0x18;
+			tmport = workport + 0x18;
 			outb(0x08, tmport);
 			outb(0x01, tmpcip);
+#ifdef ED_DBGP		
+		printk( "start DMA(to target)\n");
+#endif				
 		} else {
-			dev->last_cmd |= 0x40;
+			dev->last_cmd[c] |= 0x40;
 		}
-		dev->in_snd = 0;
+		dev->in_snd[c] = 0;
 		return;
 	}
-	if (inb(tmport) == 0) {
-		tmport = workportu + 0x18;
+	if (inb(tmport) == 0) {		
+		tmport = workport + 0x18;
 		outb(0x08, tmport);
 		outb(0x09, tmpcip);
+#ifdef ED_DBGP		
+		printk( "start DMA(to host)\n");
+#endif			
 	} else {
-		dev->last_cmd |= 0x40;
+		dev->last_cmd[c] |= 0x40;
 	}
-	dev->in_snd = 0;
+	dev->in_snd[c] = 0;
+	return;
+
 }
 
 static unsigned char fun_scam(struct atp_unit *dev, unsigned short int *val)
@@ -808,7 +1064,7 @@
 	unsigned short int i, k;
 	unsigned char j;
 
-	tmport = dev->ioport + 0x1c;
+	tmport = dev->ioport[0] + 0x1c;
 	outw(*val, tmport);
 FUN_D7:
 	for (i = 0; i < 10; i++) {	/* stable >= bus settle delay(400 ns)  */
@@ -863,24 +1119,24 @@
 	}
  */
 
-	tmport = dev->ioport + 1;
+	tmport = dev->ioport[0] + 1;
 	outb(0x08, tmport++);
 	outb(0x7f, tmport);
-	tmport = dev->ioport + 0x11;
+	tmport = dev->ioport[0] + 0x11;
 	outb(0x20, tmport);
 
 	if ((dev->scam_on & 0x40) == 0) {
 		return;
 	}
 	m = 1;
-	m <<= dev->host_idu;
+	m <<= dev->host_id[0];
 	j = 16;
-	if (dev->chip_veru < 4) {
+	if (dev->chip_ver < 4) {
 		m |= 0xff00;
 		j = 8;
 	}
 	assignid_map = m;
-	tmport = dev->ioport + 0x02;
+	tmport = dev->ioport[0] + 0x02;
 	outb(0x02, tmport++);	/* 2*2=4ms,3EH 2/32*3E=3.9ms */
 	outb(0, tmport++);
 	outb(0, tmport++);
@@ -895,7 +1151,7 @@
 		if ((m & assignid_map) != 0) {
 			continue;
 		}
-		tmport = dev->ioport + 0x0f;
+		tmport = dev->ioport[0] + 0x0f;
 		outb(0, tmport++);
 		tmport += 0x02;
 		outb(0, tmport++);
@@ -907,14 +1163,14 @@
 			k = i;
 		}
 		outb(k, tmport++);
-		tmport = dev->ioport + 0x1b;
-		if (dev->chip_veru == 4) {
+		tmport = dev->ioport[0] + 0x1b;
+		if (dev->chip_ver == 4) {
 			outb(0x01, tmport);
 		} else {
 			outb(0x00, tmport);
 		}
 wait_rdyok:
-		tmport = dev->ioport + 0x18;
+		tmport = dev->ioport[0] + 0x18;
 		outb(0x09, tmport);
 		tmport += 0x07;
 
@@ -925,22 +1181,22 @@
 			if ((k == 0x85) || (k == 0x42)) {
 				continue;
 			}
-			tmport = dev->ioport + 0x10;
+			tmport = dev->ioport[0] + 0x10;
 			outb(0x41, tmport);
 			goto wait_rdyok;
 		}
 		assignid_map |= m;
 
 	}
-	tmport = dev->ioport + 0x02;
+	tmport = dev->ioport[0] + 0x02;
 	outb(0x7f, tmport);
-	tmport = dev->ioport + 0x1b;
+	tmport = dev->ioport[0] + 0x1b;
 	outb(0x02, tmport);
 
 	outb(0, 0x80);
 
 	val = 0x0080;		/* bsy  */
-	tmport = dev->ioport + 0x1c;
+	tmport = dev->ioport[0] + 0x1c;
 	outw(val, tmport);
 	val |= 0x0040;		/* sel  */
 	outw(val, tmport);
@@ -984,7 +1240,7 @@
 	if ((inb(tmport) & 0x80) == 0x00) {	/* bsy ? */
 		outw(0, tmport--);
 		outb(0, tmport);
-		tmport = dev->ioport + 0x15;
+		tmport = dev->ioport[0] + 0x15;
 		outb(0, tmport);
 		tmport += 0x03;
 		outb(0x09, tmport);
@@ -1085,7 +1341,7 @@
 
 }
 
-static void is870(struct Scsi_Host *host, unsigned int wkport)
+void is870(struct atp_unit *dev, unsigned int wkport)
 {
 	unsigned int tmport;
 	unsigned char i, j, k, rmb, n;
@@ -1097,26 +1353,25 @@
 	static unsigned char synu[6] = { 0x80, 1, 3, 1, 0x0c, 0x0e };
 	static unsigned char synw[6] = { 0x80, 1, 3, 1, 0x0c, 0x07 };
 	static unsigned char wide[6] = { 0x80, 1, 2, 3, 1, 0 };
-	struct atp_unit *dev = (struct atp_unit *)&host->hostdata;
-
+	
 	tmport = wkport + 0x3a;
 	outb((unsigned char) (inb(tmport) | 0x10), tmport);
 
 	for (i = 0; i < 16; i++) {
-		if ((dev->chip_veru != 4) && (i > 7)) {
+		if ((dev->chip_ver != 4) && (i > 7)) {
 			break;
 		}
 		m = 1;
 		m = m << i;
-		if ((m & dev->active_idu) != 0) {
+		if ((m & dev->active_id[0]) != 0) {
 			continue;
 		}
-		if (i == dev->host_idu) {
-			printk(KERN_INFO "         ID: %2d  Host Adapter\n", dev->host_idu);
+		if (i == dev->host_id[0]) {
+			printk(KERN_INFO "         ID: %2d  Host Adapter\n", dev->host_id[0]);
 			continue;
 		}
 		tmport = wkport + 0x1b;
-		if (dev->chip_veru == 4) {
+		if (dev->chip_ver == 4) {
 			outb(0x01, tmport);
 		} else {
 			outb(0x00, tmport);
@@ -1133,7 +1388,7 @@
 		tmport += 0x06;
 		outb(0, tmport);
 		tmport += 0x02;
-		outb(dev->id[i].devspu, tmport++);
+		outb(dev->id[0][i].devsp, tmport++);
 		outb(0, tmport++);
 		outb(satn[6], tmport++);
 		outb(satn[7], tmport++);
@@ -1152,7 +1407,7 @@
 			continue;
 		}
 		while (inb(tmport) != 0x8e);
-		dev->active_idu |= m;
+		dev->active_id[0] |= m;
 
 		tmport = wkport + 0x10;
 		outb(0x30, tmport);
@@ -1182,7 +1437,7 @@
 		tmport += 0x07;
 		outb(0, tmport);
 		tmport += 0x02;
-		outb(dev->id[i].devspu, tmport++);
+		outb(dev->id[0][i].devsp, tmport++);
 		outb(0, tmport++);
 		outb(inqd[6], tmport++);
 		outb(inqd[7], tmport++);
@@ -1196,7 +1451,7 @@
 		}
 		while (inb(tmport) != 0x8e);
 		tmport = wkport + 0x1b;
-		if (dev->chip_veru == 4) {
+		if (dev->chip_ver == 4) {
 			outb(0x00, tmport);
 		}
 		tmport = wkport + 0x18;
@@ -1236,16 +1491,16 @@
 inq_ok:
 		mbuf[36] = 0;
 		printk(KERN_INFO "         ID: %2d  %s\n", i, &mbuf[8]);
-		dev->id[i].devtypeu = mbuf[0];
+		dev->id[0][i].devtype = mbuf[0];
 		rmb = mbuf[1];
 		n = mbuf[7];
-		if (dev->chip_veru != 4) {
+		if (dev->chip_ver != 4) {
 			goto not_wide;
 		}
 		if ((mbuf[7] & 0x60) == 0) {
 			goto not_wide;
 		}
-		if ((dev->global_map & 0x20) == 0) {
+		if ((dev->global_map[0] & 0x20) == 0) {
 			goto not_wide;
 		}
 		tmport = wkport + 0x1b;
@@ -1260,7 +1515,7 @@
 		tmport += 0x06;
 		outb(0, tmport);
 		tmport += 0x02;
-		outb(dev->id[i].devspu, tmport++);
+		outb(dev->id[0][i].devsp, tmport++);
 		outb(0, tmport++);
 		outb(satn[6], tmport++);
 		outb(satn[7], tmport++);
@@ -1386,16 +1641,16 @@
 		}
 		m = 1;
 		m = m << i;
-		dev->wide_idu |= m;
+		dev->wide_id[0] |= m;
 not_wide:
-		if ((dev->id[i].devtypeu == 0x00) || (dev->id[i].devtypeu == 0x07) || ((dev->id[i].devtypeu == 0x05) && ((n & 0x10) != 0))) {
+		if ((dev->id[0][i].devtype == 0x00) || (dev->id[0][i].devtype == 0x07) || ((dev->id[0][i].devtype == 0x05) && ((n & 0x10) != 0))) {
 			goto set_sync;
 		}
 		continue;
 set_sync:
 		tmport = wkport + 0x1b;
 		j = 0;
-		if ((m & dev->wide_idu) != 0) {
+		if ((m & dev->wide_id[0]) != 0) {
 			j |= 0x01;
 		}
 		outb(j, tmport);
@@ -1409,7 +1664,7 @@
 		tmport += 0x06;
 		outb(0, tmport);
 		tmport += 0x02;
-		outb(dev->id[i].devspu, tmport++);
+		outb(dev->id[0][i].devsp, tmport++);
 		outb(0, tmport++);
 		outb(satn[6], tmport++);
 		outb(satn[7], tmport++);
@@ -1434,10 +1689,10 @@
 		while ((inb(tmport) & 0x80) == 0) {
 			if ((inb(tmport) & 0x01) != 0) {
 				tmport -= 0x06;
-				if ((m & dev->wide_idu) != 0) {
+				if ((m & dev->wide_id[0]) != 0) {
 					outb(synw[j++], tmport);
 				} else {
-					if ((m & dev->ultra_map) != 0) {
+					if ((m & dev->ultra_map[0]) != 0) {
 						outb(synu[j++], tmport);
 					} else {
 						outb(synn[j++], tmport);
@@ -1551,7 +1806,7 @@
 		if (mbuf[4] > 0x0c) {
 			mbuf[4] = 0x0c;
 		}
-		dev->id[i].devspu = mbuf[4];
+		dev->id[0][i].devsp = mbuf[4];
 		if ((mbuf[3] < 0x0d) && (rmb == 0)) {
 			j = 0xa0;
 			goto set_syn_ok;
@@ -1570,13 +1825,13 @@
 		}
 		j = 0x60;
 set_syn_ok:
-		dev->id[i].devspu = (dev->id[i].devspu & 0x0f) | j;
+		dev->id[0][i].devsp = (dev->id[0][i].devsp & 0x0f) | j;
 	}
 	tmport = wkport + 0x3a;
 	outb((unsigned char) (inb(tmport) & 0xef), tmport);
 }
 
-static void is880(struct Scsi_Host *host, unsigned int wkport)
+static void is880(struct atp_unit *dev, unsigned int wkport)
 {
 	unsigned int tmport;
 	unsigned char i, j, k, rmb, n, lvdmode;
@@ -1590,18 +1845,17 @@
 	unsigned char synuw[6] = { 0x80, 1, 3, 1, 0x0a, 0x0e };
 	static unsigned char wide[6] = { 0x80, 1, 2, 3, 1, 0 };
 	static unsigned char u3[9] = { 0x80, 1, 6, 4, 0x09, 00, 0x0e, 0x01, 0x02 };
-	struct atp_unit *dev = (struct atp_unit *)&host->hostdata;
 
 	lvdmode = inb(wkport + 0x3f) & 0x40;
 
 	for (i = 0; i < 16; i++) {
 		m = 1;
 		m = m << i;
-		if ((m & dev->active_idu) != 0) {
+		if ((m & dev->active_id[0]) != 0) {
 			continue;
 		}
-		if (i == dev->host_idu) {
-			printk(KERN_INFO "         ID: %2d  Host Adapter\n", dev->host_idu);
+		if (i == dev->host_id[0]) {
+			printk(KERN_INFO "         ID: %2d  Host Adapter\n", dev->host_id[0]);
 			continue;
 		}
 		tmport = wkport + 0x5b;
@@ -1618,7 +1872,7 @@
 		tmport += 0x06;
 		outb(0, tmport);
 		tmport += 0x02;
-		outb(dev->id[i].devspu, tmport++);
+		outb(dev->id[0][i].devsp, tmport++);
 		outb(0, tmport++);
 		outb(satn[6], tmport++);
 		outb(satn[7], tmport++);
@@ -1637,7 +1891,7 @@
 			continue;
 		}
 		while (inb(tmport) != 0x8e);
-		dev->active_idu |= m;
+		dev->active_id[0] |= m;
 
 		tmport = wkport + 0x50;
 		outb(0x30, tmport);
@@ -1667,7 +1921,7 @@
 		tmport += 0x07;
 		outb(0, tmport);
 		tmport += 0x02;
-		outb(dev->id[i].devspu, tmport++);
+		outb(dev->id[0][i].devsp, tmport++);
 		outb(0, tmport++);
 		outb(inqd[6], tmport++);
 		outb(inqd[7], tmport++);
@@ -1719,19 +1973,19 @@
 inq_ok:
 		mbuf[36] = 0;
 		printk(KERN_INFO "         ID: %2d  %s\n", i, &mbuf[8]);
-		dev->id[i].devtypeu = mbuf[0];
+		dev->id[0][i].devtype = mbuf[0];
 		rmb = mbuf[1];
 		n = mbuf[7];
 		if ((mbuf[7] & 0x60) == 0) {
 			goto not_wide;
 		}
-		if ((i < 8) && ((dev->global_map & 0x20) == 0)) {
+		if ((i < 8) && ((dev->global_map[0] & 0x20) == 0)) {
 			goto not_wide;
 		}
 		if (lvdmode == 0) {
 			goto chg_wide;
 		}
-		if (dev->sp[i] != 0x04)	// force u2
+		if (dev->sp[0][i] != 0x04)	// force u2
 		{
 			goto chg_wide;
 		}
@@ -1748,7 +2002,7 @@
 		tmport += 0x06;
 		outb(0, tmport);
 		tmport += 0x02;
-		outb(dev->id[i].devspu, tmport++);
+		outb(dev->id[0][i].devsp, tmport++);
 		outb(0, tmport++);
 		outb(satn[6], tmport++);
 		outb(satn[7], tmport++);
@@ -1872,8 +2126,8 @@
 		if (mbuf[3] == 0x09) {
 			m = 1;
 			m = m << i;
-			dev->wide_idu |= m;
-			dev->id[i].devspu = 0xce;
+			dev->wide_id[0] |= m;
+			dev->id[0][i].devsp = 0xce;
 			continue;
 		}
 chg_wide:
@@ -1889,7 +2143,7 @@
 		tmport += 0x06;
 		outb(0, tmport);
 		tmport += 0x02;
-		outb(dev->id[i].devspu, tmport++);
+		outb(dev->id[0][i].devsp, tmport++);
 		outb(0, tmport++);
 		outb(satn[6], tmport++);
 		outb(satn[7], tmport++);
@@ -2015,29 +2269,29 @@
 		}
 		m = 1;
 		m = m << i;
-		dev->wide_idu |= m;
+		dev->wide_id[0] |= m;
 not_wide:
-		if ((dev->id[i].devtypeu == 0x00) || (dev->id[i].devtypeu == 0x07) || ((dev->id[i].devtypeu == 0x05) && ((n & 0x10) != 0))) {
+		if ((dev->id[0][i].devtype == 0x00) || (dev->id[0][i].devtype == 0x07) || ((dev->id[0][i].devtype == 0x05) && ((n & 0x10) != 0))) {
 			m = 1;
 			m = m << i;
-			if ((dev->async & m) != 0) {
+			if ((dev->async[0] & m) != 0) {
 				goto set_sync;
 			}
 		}
 		continue;
 set_sync:
-		if (dev->sp[i] == 0x02) {
+		if (dev->sp[0][i] == 0x02) {
 			synu[4] = 0x0c;
 			synuw[4] = 0x0c;
 		} else {
-			if (dev->sp[i] >= 0x03) {
+			if (dev->sp[0][i] >= 0x03) {
 				synu[4] = 0x0a;
 				synuw[4] = 0x0a;
 			}
 		}
 		tmport = wkport + 0x5b;
 		j = 0;
-		if ((m & dev->wide_idu) != 0) {
+		if ((m & dev->wide_id[0]) != 0) {
 			j |= 0x01;
 		}
 		outb(j, tmport);
@@ -2051,7 +2305,7 @@
 		tmport += 0x06;
 		outb(0, tmport);
 		tmport += 0x02;
-		outb(dev->id[i].devspu, tmport++);
+		outb(dev->id[0][i].devsp, tmport++);
 		outb(0, tmport++);
 		outb(satn[6], tmport++);
 		outb(satn[7], tmport++);
@@ -2076,14 +2330,14 @@
 		while ((inb(tmport) & 0x80) == 0) {
 			if ((inb(tmport) & 0x01) != 0) {
 				tmport -= 0x06;
-				if ((m & dev->wide_idu) != 0) {
-					if ((m & dev->ultra_map) != 0) {
+				if ((m & dev->wide_id[0]) != 0) {
+					if ((m & dev->ultra_map[0]) != 0) {
 						outb(synuw[j++], tmport);
 					} else {
 						outb(synw[j++], tmport);
 					}
 				} else {
-					if ((m & dev->ultra_map) != 0) {
+					if ((m & dev->ultra_map[0]) != 0) {
 						outb(synu[j++], tmport);
 					} else {
 						outb(synn[j++], tmport);
@@ -2197,7 +2451,7 @@
 		if (mbuf[4] > 0x0e) {
 			mbuf[4] = 0x0e;
 		}
-		dev->id[i].devspu = mbuf[4];
+		dev->id[0][i].devsp = mbuf[4];
 		if (mbuf[3] < 0x0c) {
 			j = 0xb0;
 			goto set_syn_ok;
@@ -2220,249 +2474,179 @@
 		}
 		j = 0x60;
 set_syn_ok:
-		dev->id[i].devspu = (dev->id[i].devspu & 0x0f) | j;
+		dev->id[0][i].devsp = (dev->id[0][i].devsp & 0x0f) | j;
 	}
 }
 
 static void atp870u_free_tables(struct Scsi_Host *host)
 {
 	struct atp_unit *atp_dev = (struct atp_unit *)&host->hostdata;
-	int k;
-
-	for (k = 0; k < 16; k++) {
-		if (!atp_dev->id[k].prd_tableu)
-			continue;
-		pci_free_consistent(atp_dev->pdev, 1024, atp_dev->id[k].prd_tableu,
-					atp_dev->id[k].prd_phys);
-		atp_dev->id[k].prd_tableu = NULL;
+	int j, k;
+	for (j=0; j < 2; j++) {
+		for (k = 0; k < 16; k++) {
+			if (!atp_dev->id[j][k].prd_table)
+				continue;
+			pci_free_consistent(atp_dev->pdev, 1024, atp_dev->id[j][k].prd_table, atp_dev->id[j][k].prdaddr);
+			atp_dev->id[j][k].prd_table = NULL;
+		}
 	}
 }
 
 static int atp870u_init_tables(struct Scsi_Host *host)
 {
-	struct atp_unit *dev = (struct atp_unit *)&host->hostdata;
-	int k, i;
-
-	for (i = k = 0; k < 16; k++) {
-		dev->id[k].prd_tableu = pci_alloc_consistent(dev->pdev, 1024, &dev->id[k].prd_phys);
-		if (!dev->id[k].prd_tableu) {
-			atp870u_free_tables(host);
-			return -ENOMEM;
-		}
-		dev->id[k].devspu = 0x20;
-		dev->id[k].devtypeu = 0;
-		dev->id[k].curr_req = NULL;
-	}
-	dev->active_idu = 0;
-	dev->wide_idu = 0;
-	dev->host_idu = 0x07;
-	dev->quhdu = 0;
-	dev->quendu = 0;
-	dev->chip_veru = 0;
-	dev->last_cmd = 0xff;
-	dev->in_snd = 0;
-	dev->in_int = 0;
-	for (k = 0; k < qcnt; k++) {
-		dev->querequ[k] = NULL;
-	}
-	for (k = 0; k < 16; k++) {
-		dev->id[k].curr_req = NULL;
-		dev->sp[k] = 0x04;
+	struct atp_unit *atp_dev = (struct atp_unit *)&host->hostdata;
+	int c,k;
+	for(c=0;c < 2;c++) {
+	   	for(k=0;k<16;k++) {
+	   			atp_dev->id[c][k].prd_table = pci_alloc_consistent(atp_dev->pdev, 1024, &(atp_dev->id[c][k].prdaddr));
+	   			if (!atp_dev->id[c][k].prd_table) {
+	   				printk("atp870u_init_tables fail\n");
+				atp870u_free_tables(host);
+				return -ENOMEM;
+			}
+			atp_dev->id[c][k].devsp=0x20;
+			atp_dev->id[c][k].devtype = 0x7f;
+			atp_dev->id[c][k].curr_req = NULL;			   
+	   	}
+	   			
+	   	atp_dev->active_id[c] = 0;
+	   	atp_dev->wide_id[c] = 0;
+	   	atp_dev->host_id[c] = 0x07;
+	   	atp_dev->quhd[c] = 0;
+	   	atp_dev->quend[c] = 0;
+	   	atp_dev->last_cmd[c] = 0xff;
+	   	atp_dev->in_snd[c] = 0;
+	   	atp_dev->in_int[c] = 0;
+	   	
+	   	for (k = 0; k < qcnt; k++) {
+	   		  atp_dev->quereq[c][k] = NULL;
+	   	}	   		   
+	   	for (k = 0; k < 16; k++) {
+			   atp_dev->id[c][k].curr_req = NULL;
+			   atp_dev->sp[c][k] = 0x04;
+	   	}		   
 	}
 	return 0;
 }
 
 /* return non-zero on detection */
-static int atp870u_probe(struct pci_dev *dev, const struct pci_device_id *ent)
+static int atp870u_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
-	unsigned char k, m;
+	unsigned char k, m, c;
 	unsigned long flags;
-	unsigned int base_io, error, tmport;
+	unsigned int base_io, tmport, error,n;
 	unsigned char host_id;
-	unsigned short n;
-	struct Scsi_Host *shpnt;
+	struct Scsi_Host *shpnt = NULL;
 	struct atp_unit atp_dev, *p;
-	static int count;
-
-	if (pci_enable_device(dev))
+	unsigned char setupdata[2][16];
+	int count = 0;
+	
+	if (pci_enable_device(pdev))
 		return -EIO;
 
-	if (pci_set_dma_mask(dev, 0xFFFFFFFFUL)) {
-		printk(KERN_ERR "atp870u: 32bit DMA mask required but not available.\n");
-		return -EIO;
-	}
-	
+        if (!pci_set_dma_mask(pdev, 0xFFFFFFUL)) {
+                printk(KERN_INFO "atp870u: use 32bit DMA mask.\n");
+        } else {
+                printk(KERN_ERR "atp870u: DMA mask required but not available.\n");
+                return -EIO;
+        }
+
 	memset(&atp_dev, 0, sizeof atp_dev);
- 
 	/*
 	 * It's probably easier to weed out some revisions like
 	 * this than via the PCI device table
 	 */
 	if (ent->device == PCI_DEVICE_ID_ARTOP_AEC7610) {
-		error = pci_read_config_byte(dev, PCI_CLASS_REVISION, &atp_dev.chip_veru);
-		if (atp_dev.chip_veru < 2)
+		error = pci_read_config_byte(pdev, PCI_CLASS_REVISION, &atp_dev.chip_ver);
+		if (atp_dev.chip_ver < 2)
 			return -EIO;
 	}
 
 	switch (ent->device) {
-	case 0x8081:
 	case PCI_DEVICE_ID_ARTOP_AEC7612UW:
 	case PCI_DEVICE_ID_ARTOP_AEC7612SUW:
-		atp_dev.chip_veru = 0x04;
+	case ATP880_DEVID1:	
+	case ATP880_DEVID2:	
+	case ATP885_DEVID:	
+		atp_dev.chip_ver = 0x04;
 	default:
 		break;
 	}
+	base_io = pci_resource_start(pdev, 0);
+	base_io &= 0xfffffff8;
+	
+	if ((ent->device == ATP880_DEVID1)||(ent->device == ATP880_DEVID2)) {
+		error = pci_read_config_byte(pdev, PCI_CLASS_REVISION, &atp_dev.chip_ver);
+		pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0x80);//JCC082803
 
-	base_io = pci_resource_start(dev, 0);
-
-	if (ent->device != 0x8081) {
-		error = pci_read_config_byte(dev, 0x49, &host_id);
-		base_io &= 0xfffffff8;
-
-		printk(KERN_INFO "   ACARD AEC-671X PCI Ultra/W SCSI-3 Host Adapter: %d "
-			"IO:%x, IRQ:%d.\n", count, base_io, dev->irq);
-
-		atp_dev.unit = count;	
-		atp_dev.ioport = base_io;
-		atp_dev.pciport = base_io + 0x20;
-		atp_dev.deviceid = ent->device;
-		host_id &= 0x07;
-		atp_dev.host_idu = host_id;
-		tmport = base_io + 0x22;
-		atp_dev.scam_on = inb(tmport);
-		tmport += 0x0b;
-		atp_dev.global_map = inb(tmport++);
-		atp_dev.ultra_map = inw(tmport);
-
-		if (atp_dev.ultra_map == 0) {
-			atp_dev.scam_on = 0x00;
-			atp_dev.global_map = 0x20;
-			atp_dev.ultra_map = 0xffff;
-		}
-
-		shpnt = scsi_host_alloc(&atp870u_template, sizeof(struct atp_unit));
-		if (!shpnt)
-			return -ENOMEM;
-
-		p = (struct atp_unit *)&shpnt->hostdata;
-		
-		atp_dev.host = shpnt;
-		atp_dev.pdev = dev;
-		pci_set_drvdata(dev, p);
-		memcpy(p, &atp_dev, sizeof atp_dev);
-		if (atp870u_init_tables(shpnt) < 0)
-			goto unregister;
-
-		if (request_irq(dev->irq, atp870u_intr_handle, SA_SHIRQ, "atp870u", shpnt)) {
-			printk(KERN_ERR "Unable to allocate IRQ%d for Acard controller.\n", dev->irq);
-			goto free_tables;
-		}
-
-		spin_lock_irqsave(shpnt->host_lock, flags);
-		if (atp_dev.chip_veru > 0x07) {	/* check if atp876 chip then enable terminator */
-			tmport = base_io + 0x3e;
-			outb(0x00, tmport);
-		}
- 
-		tmport = base_io + 0x3a;
-		k = (inb(tmport) & 0xf3) | 0x10;
-		outb(k, tmport);
-		outb((k & 0xdf), tmport);
-		mdelay(32);
-		outb(k, tmport);
-		mdelay(32);
-		tmport = base_io;
-		outb((host_id | 0x08), tmport);
-		tmport += 0x18;
-		outb(0, tmport);
-		tmport += 0x07;
-		while ((inb(tmport) & 0x80) == 0)
-			mdelay(1);
-
-		tmport -= 0x08;
-		inb(tmport);
-		tmport = base_io + 1;
-		outb(8, tmport++);
-		outb(0x7f, tmport);
-		tmport = base_io + 0x11;
-		outb(0x20, tmport);
-
-		tscam(shpnt);
-		is870(shpnt, base_io);
-		tmport = base_io + 0x3a;
-		outb((inb(tmport) & 0xef), tmport);
-		tmport++;
-		outb((inb(tmport) | 0x20), tmport);
-	} else {
-		base_io &= 0xfffffff8;
 		host_id = inb(base_io + 0x39);
 		host_id >>= 0x04;
 
 		printk(KERN_INFO "   ACARD AEC-67160 PCI Ultra3 LVD Host Adapter: %d"
-			"    IO:%x, IRQ:%d.\n", count, base_io, dev->irq);
-		atp_dev.ioport = base_io + 0x40;
-		atp_dev.pciport = base_io + 0x28;
-		atp_dev.deviceid = ent->device;
-		atp_dev.host_idu = host_id;
+			"    IO:%x, IRQ:%d.\n", count, base_io, pdev->irq);
+		atp_dev.ioport[0] = base_io + 0x40;
+		atp_dev.pciport[0] = base_io + 0x28;
+		atp_dev.dev_id = ent->device;
+		atp_dev.host_id[0] = host_id;
 
 		tmport = base_io + 0x22;
 		atp_dev.scam_on = inb(tmport);
 		tmport += 0x13;
-		atp_dev.global_map = inb(tmport);
+		atp_dev.global_map[0] = inb(tmport);
 		tmport += 0x07;
-		atp_dev.ultra_map = inw(tmport);
+		atp_dev.ultra_map[0] = inw(tmport);
 
 		n = 0x3f09;
-next_fblk:
+next_fblk_880:
 		if (n >= 0x4000)
-			goto flash_ok;
+			goto flash_ok_880;
 
 		m = 0;
 		outw(n, base_io + 0x34);
 		n += 0x0002;
 		if (inb(base_io + 0x30) == 0xff)
-			goto flash_ok;
+			goto flash_ok_880;
 
-		atp_dev.sp[m++] = inb(base_io + 0x30);
-		atp_dev.sp[m++] = inb(base_io + 0x31);
-		atp_dev.sp[m++] = inb(base_io + 0x32);
-		atp_dev.sp[m++] = inb(base_io + 0x33);
+		atp_dev.sp[0][m++] = inb(base_io + 0x30);
+		atp_dev.sp[0][m++] = inb(base_io + 0x31);
+		atp_dev.sp[0][m++] = inb(base_io + 0x32);
+		atp_dev.sp[0][m++] = inb(base_io + 0x33);
 		outw(n, base_io + 0x34);
 		n += 0x0002;
-		atp_dev.sp[m++] = inb(base_io + 0x30);
-		atp_dev.sp[m++] = inb(base_io + 0x31);
-		atp_dev.sp[m++] = inb(base_io + 0x32);
-		atp_dev.sp[m++] = inb(base_io + 0x33);
+		atp_dev.sp[0][m++] = inb(base_io + 0x30);
+		atp_dev.sp[0][m++] = inb(base_io + 0x31);
+		atp_dev.sp[0][m++] = inb(base_io + 0x32);
+		atp_dev.sp[0][m++] = inb(base_io + 0x33);
 		outw(n, base_io + 0x34);
 		n += 0x0002;
-		atp_dev.sp[m++] = inb(base_io + 0x30);
-		atp_dev.sp[m++] = inb(base_io + 0x31);
-		atp_dev.sp[m++] = inb(base_io + 0x32);
-		atp_dev.sp[m++] = inb(base_io + 0x33);
+		atp_dev.sp[0][m++] = inb(base_io + 0x30);
+		atp_dev.sp[0][m++] = inb(base_io + 0x31);
+		atp_dev.sp[0][m++] = inb(base_io + 0x32);
+		atp_dev.sp[0][m++] = inb(base_io + 0x33);
 		outw(n, base_io + 0x34);
 		n += 0x0002;
-		atp_dev.sp[m++] = inb(base_io + 0x30);
-		atp_dev.sp[m++] = inb(base_io + 0x31);
-		atp_dev.sp[m++] = inb(base_io + 0x32);
-		atp_dev.sp[m++] = inb(base_io + 0x33);
+		atp_dev.sp[0][m++] = inb(base_io + 0x30);
+		atp_dev.sp[0][m++] = inb(base_io + 0x31);
+		atp_dev.sp[0][m++] = inb(base_io + 0x32);
+		atp_dev.sp[0][m++] = inb(base_io + 0x33);
 		n += 0x0018;
-		goto next_fblk;
-flash_ok:
+		goto next_fblk_880;
+flash_ok_880:
 		outw(0, base_io + 0x34);
-		atp_dev.ultra_map = 0;
-		atp_dev.async = 0;
+		atp_dev.ultra_map[0] = 0;
+		atp_dev.async[0] = 0;
 		for (k = 0; k < 16; k++) {
 			n = 1;
 			n = n << k;
-			if (atp_dev.sp[k] > 1) {
-				atp_dev.ultra_map |= n;
+			if (atp_dev.sp[0][k] > 1) {
+				atp_dev.ultra_map[0] |= n;
 			} else {
-				if (atp_dev.sp[k] == 0)
-					atp_dev.async |= n;
+				if (atp_dev.sp[0][k] == 0)
+					atp_dev.async[0] |= n;
  			}
 	 	}
-		atp_dev.async = ~(atp_dev.async);
-		outb(atp_dev.global_map, base_io + 0x35);
+		atp_dev.async[0] = ~(atp_dev.async[0]);
+		outb(atp_dev.global_map[0], base_io + 0x35);
  
 		shpnt = scsi_host_alloc(&atp870u_template, sizeof(struct atp_unit));
 		if (!shpnt)
@@ -2471,16 +2655,16 @@
 		p = (struct atp_unit *)&shpnt->hostdata;
 
 		atp_dev.host = shpnt;
-		atp_dev.pdev = dev;
-		pci_set_drvdata(dev, p);
+		atp_dev.pdev = pdev;
+		pci_set_drvdata(pdev, p);
 		memcpy(p, &atp_dev, sizeof atp_dev);
 		if (atp870u_init_tables(shpnt) < 0) {
 			printk(KERN_ERR "Unable to allocate tables for Acard controller\n");
 			goto unregister;
 		}
 
-		if (request_irq(dev->irq, atp870u_intr_handle, SA_SHIRQ, "atp870u", shpnt)) {
- 			printk(KERN_ERR "Unable to allocate IRQ%d for Acard controller.\n", dev->irq);
+		if (request_irq(pdev->irq, atp870u_intr_handle, SA_SHIRQ, "atp880i", shpnt)) {
+ 			printk(KERN_ERR "Unable to allocate IRQ%d for Acard controller.\n", pdev->irq);
 			goto free_tables;
 		}
 
@@ -2513,96 +2697,354 @@
 		outb(0x20, tmport);
 
 		tscam(shpnt);
-		is880(shpnt, base_io);
+		is880(p, base_io);
 		tmport = base_io + 0x38;
 		outb(0xb0, tmport);
-	}
-
-	if (p->chip_veru == 4)
 		shpnt->max_id = 16;
-
-	shpnt->this_id = host_id;
-	shpnt->unique_id = base_io;
-	shpnt->io_port = base_io;
-	if (ent->device == 0x8081) {
+		shpnt->this_id = host_id;
+		shpnt->unique_id = base_io;
+		shpnt->io_port = base_io;
 		shpnt->n_io_port = 0x60;	/* Number of bytes of I/O space used */
+		shpnt->irq = pdev->irq;			
+	} else if (ent->device == ATP885_DEVID) {	
+			printk(KERN_INFO "   ACARD AEC-67162 PCI Ultra3 LVD Host Adapter:  IO:%x, IRQ:%d.\n"
+			       , base_io, pdev->irq);
+        	
+		atp_dev.pdev = pdev;	
+		atp_dev.dev_id  = ent->device;
+		atp_dev.baseport = base_io;
+		atp_dev.ioport[0] = base_io + 0x80;
+		atp_dev.ioport[1] = base_io + 0xc0;
+		atp_dev.pciport[0] = base_io + 0x40;
+		atp_dev.pciport[1] = base_io + 0x50;
+				
+		shpnt = scsi_host_alloc(&atp870u_template, sizeof(struct atp_unit));
+		if (!shpnt)
+			return -ENOMEM;
+        	
+		p = (struct atp_unit *)&shpnt->hostdata;
+        	
+		atp_dev.host = shpnt;
+		atp_dev.pdev = pdev;
+		pci_set_drvdata(pdev, p);
+		memcpy(p, &atp_dev, sizeof(struct atp_unit));
+		if (atp870u_init_tables(shpnt) < 0)
+			goto unregister;
+			
+#ifdef ED_DBGP		
+	printk("request_irq() shpnt %p hostdata %p\n", shpnt, p);
+#endif	        
+		if (request_irq(pdev->irq, atp870u_intr_handle, SA_SHIRQ, "atp870u", shpnt)) {
+				printk(KERN_ERR "Unable to allocate IRQ for Acard controller.\n");
+			goto free_tables;
+		}
+		
+		spin_lock_irqsave(shpnt->host_lock, flags);        					
+        			
+		c=inb(base_io + 0x29);
+		outb((c | 0x04),base_io + 0x29);
+        	
+		n=0x1f80;
+next_fblk_885:
+		if (n >= 0x2000) {
+		   goto flash_ok_885;
+		}
+		outw(n,base_io + 0x3c);
+		if (inl(base_io + 0x38) == 0xffffffff) {
+		   goto flash_ok_885;
+		}
+		for (m=0; m < 2; m++) {
+		    p->global_map[m]= 0;
+		    for (k=0; k < 4; k++) {
+			outw(n++,base_io + 0x3c);
+			((unsigned long *)&setupdata[m][0])[k]=inl(base_io + 0x38);
+		    }
+		    for (k=0; k < 4; k++) {
+			outw(n++,base_io + 0x3c);
+			((unsigned long *)&p->sp[m][0])[k]=inl(base_io + 0x38);
+		    }
+		    n += 8;
+		}
+		goto next_fblk_885;
+flash_ok_885:
+#ifdef ED_DBGP
+		printk( "Flash Read OK\n");
+#endif	
+		c=inb(base_io + 0x29);
+		outb((c & 0xfb),base_io + 0x29);
+		for (c=0;c < 2;c++) {
+		    p->ultra_map[c]=0;
+		    p->async[c] = 0;
+		    for (k=0; k < 16; k++) {
+			n=1;
+			n = n << k;
+			if (p->sp[c][k] > 1) {
+			   p->ultra_map[c] |= n;
+			} else {
+			   if (p->sp[c][k] == 0) {
+			      p->async[c] |= n;
+			   }
+			}
+		    }
+		    p->async[c] = ~(p->async[c]);
+
+		    if (p->global_map[c] == 0) {
+		       k=setupdata[c][1];
+		       if ((k & 0x40) != 0)
+			  p->global_map[c] |= 0x20;
+		       k &= 0x07;
+		       p->global_map[c] |= k;
+		       if ((setupdata[c][2] & 0x04) != 0)
+			  p->global_map[c] |= 0x08;
+		       p->host_id[c] = setupdata[c][0] & 0x07;
+		    }
+		}
+
+		k = inb(base_io + 0x28) & 0x8f;
+		k |= 0x10;
+		outb(k, base_io + 0x28);
+		outb(0x80, base_io + 0x41);
+		outb(0x80, base_io + 0x51);
+		mdelay(100);
+		outb(0, base_io + 0x41);
+		outb(0, base_io + 0x51);
+		mdelay(1000);
+		inb(base_io + 0x9b);
+		inb(base_io + 0x97);
+		inb(base_io + 0xdb);
+		inb(base_io + 0xd7);
+		tmport = base_io + 0x80;
+		k=p->host_id[0];
+		if (k > 7)
+		   k = (k & 0x07) | 0x40;
+		k |= 0x08;
+		outb(k, tmport);
+		tmport += 0x18;
+		outb(0, tmport);
+		tmport += 0x07;
+		while ((inb(tmport) & 0x80) == 0);
+		tmport -= 0x08;
+		inb(tmport);
+		tmport = base_io + 0x81;
+		outb(8, tmport++);
+		outb(0x7f, tmport);
+		tmport = base_io + 0x91;
+		outb(0x20, tmport);
+
+		tmport = base_io + 0xc0;
+		k=p->host_id[1];
+		if (k > 7)
+		   k = (k & 0x07) | 0x40;
+		k |= 0x08;
+		outb(k, tmport);
+		tmport += 0x18;
+		outb(0, tmport);
+		tmport += 0x07;
+		while ((inb(tmport) & 0x80) == 0);
+		tmport -= 0x08;
+		inb(tmport);
+		tmport = base_io + 0xc1;
+		outb(8, tmport++);
+		outb(0x7f, tmport);
+		tmport = base_io + 0xd1;
+		outb(0x20, tmport);
+
+		tscam_885();
+		printk(KERN_INFO "   Scanning Channel A SCSI Device ...\n");
+		is885(p, base_io + 0x80, 0);
+		printk(KERN_INFO "   Scanning Channel B SCSI Device ...\n");
+		is885(p, base_io + 0xc0, 1);
+
+		k = inb(base_io + 0x28) & 0xcf;
+		k |= 0xc0;
+		outb(k, base_io + 0x28);
+		k = inb(base_io + 0x1f) | 0x80;
+		outb(k, base_io + 0x1f);
+		k = inb(base_io + 0x29) | 0x01;
+		outb(k, base_io + 0x29);
+#ifdef ED_DBGP
+		//printk("atp885: atp_host[0] 0x%p\n", atp_host[0]);
+#endif		
+		shpnt->max_id = 16;
+		shpnt->max_lun = (p->global_map[0] & 0x07) + 1;
+		shpnt->max_channel = 1;
+		shpnt->this_id = p->host_id[0];
+		shpnt->unique_id = base_io;
+		shpnt->io_port = base_io;
+		shpnt->n_io_port = 0xff;	/* Number of bytes of I/O space used */
+		shpnt->irq = pdev->irq;
+				
 	} else {
+		error = pci_read_config_byte(pdev, 0x49, &host_id);
+
+		printk(KERN_INFO "   ACARD AEC-671X PCI Ultra/W SCSI-2/3 Host Adapter: %d "
+			"IO:%x, IRQ:%d.\n", count, base_io, pdev->irq);
+
+		atp_dev.ioport[0] = base_io;
+		atp_dev.pciport[0] = base_io + 0x20;
+		atp_dev.dev_id = ent->device;
+		host_id &= 0x07;
+		atp_dev.host_id[0] = host_id;
+		tmport = base_io + 0x22;
+		atp_dev.scam_on = inb(tmport);
+		tmport += 0x0b;
+		atp_dev.global_map[0] = inb(tmport++);
+		atp_dev.ultra_map[0] = inw(tmport);
+
+		if (atp_dev.ultra_map[0] == 0) {
+			atp_dev.scam_on = 0x00;
+			atp_dev.global_map[0] = 0x20;
+			atp_dev.ultra_map[0] = 0xffff;
+		}
+
+		shpnt = scsi_host_alloc(&atp870u_template, sizeof(struct atp_unit));
+		if (!shpnt)
+			return -ENOMEM;
+
+		p = (struct atp_unit *)&shpnt->hostdata;
+		
+		atp_dev.host = shpnt;
+		atp_dev.pdev = pdev;
+		pci_set_drvdata(pdev, p);
+		memcpy(p, &atp_dev, sizeof atp_dev);
+		if (atp870u_init_tables(shpnt) < 0)
+			goto unregister;
+
+		if (request_irq(pdev->irq, atp870u_intr_handle, SA_SHIRQ, "atp870i", shpnt)) {
+			printk(KERN_ERR "Unable to allocate IRQ%d for Acard controller.\n", pdev->irq);
+			goto free_tables;
+		}
+
+		spin_lock_irqsave(shpnt->host_lock, flags);
+		if (atp_dev.chip_ver > 0x07) {	/* check if atp876 chip then enable terminator */
+			tmport = base_io + 0x3e;
+			outb(0x00, tmport);
+		}
+ 
+		tmport = base_io + 0x3a;
+		k = (inb(tmport) & 0xf3) | 0x10;
+		outb(k, tmport);
+		outb((k & 0xdf), tmport);
+		mdelay(32);
+		outb(k, tmport);
+		mdelay(32);
+		tmport = base_io;
+		outb((host_id | 0x08), tmport);
+		tmport += 0x18;
+		outb(0, tmport);
+		tmport += 0x07;
+		while ((inb(tmport) & 0x80) == 0)
+			mdelay(1);
+
+		tmport -= 0x08;
+		inb(tmport);
+		tmport = base_io + 1;
+		outb(8, tmport++);
+		outb(0x7f, tmport);
+		tmport = base_io + 0x11;
+		outb(0x20, tmport);
+
+		tscam(shpnt);
+		is870(p, base_io);
+		tmport = base_io + 0x3a;
+		outb((inb(tmport) & 0xef), tmport);
+		tmport++;
+		outb((inb(tmport) | 0x20), tmport);
+		if (atp_dev.chip_ver == 4)
+			shpnt->max_id = 16;
+		else		
+			shpnt->max_id = 7;
+		shpnt->this_id = host_id;
+		shpnt->unique_id = base_io;
+		shpnt->io_port = base_io;
 		shpnt->n_io_port = 0x40;	/* Number of bytes of I/O space used */
-	}
-	shpnt->irq = dev->irq;
-	spin_unlock_irqrestore(shpnt->host_lock, flags);
-	if (ent->device == 0x8081) {
-		if (!request_region(base_io, 0x60, "atp870u"))
-			goto request_io_fail;
-	} else {
-		if (!request_region(base_io, 0x40, "atp870u"))
-			goto request_io_fail;
-	}
+		shpnt->irq = pdev->irq;		
+	} 
+		spin_unlock_irqrestore(shpnt->host_lock, flags);
+		if(ent->device==ATP885_DEVID) {
+			if(!request_region(base_io, 0xff, "atp870u")) /* Register the IO ports that we use */
+				goto request_io_fail;
+		} else if((ent->device==ATP880_DEVID1)||(ent->device==ATP880_DEVID2)) {
+			if(!request_region(base_io, 0x60, "atp870u")) /* Register the IO ports that we use */
+				goto request_io_fail;
+		} else {
+			if(!request_region(base_io, 0x40, "atp870u")) /* Register the IO ports that we use */
+				goto request_io_fail;
+		}				
+		count++;
+		if (scsi_add_host(shpnt, &pdev->dev))
+			goto scsi_add_fail;
+		scsi_scan_host(shpnt);
+#ifdef ED_DBGP			
+		printk("atp870u_prob : exit\n");
+#endif		
+		return 0;
 
-	count++;
-	if (scsi_add_host(shpnt, &dev->dev))
-		goto scsi_add_fail;
-	scsi_scan_host(shpnt);
-	return 0;
-  
 scsi_add_fail:
-	if (ent->device == 0x8081)
+	printk("atp870u_prob:scsi_add_fail\n");
+	if(ent->device==ATP885_DEVID) {
+		release_region(base_io, 0xff);
+	} else if((ent->device==ATP880_DEVID1)||(ent->device==ATP880_DEVID2)) {
 		release_region(base_io, 0x60);
-	else
+	} else {
 		release_region(base_io, 0x40);
+	}
 request_io_fail:
-	free_irq(dev->irq, shpnt);
+	printk("atp870u_prob:request_io_fail\n");
+	free_irq(pdev->irq, shpnt);
 free_tables:
+	printk("atp870u_prob:free_table\n");
 	atp870u_free_tables(shpnt);
 unregister:
+	printk("atp870u_prob:unregister\n");
 	scsi_host_put(shpnt);
-	return -1;
+	return -1;		
 }
 
 /* The abort command does not leave the device in a clean state where
    it is available to be used again.  Until this gets worked out, we will
    leave it commented out.  */
 
-static int atp870u_abort(struct scsi_cmnd * SCpnt)
+int atp870u_abort(struct scsi_cmnd * SCpnt)
 {
-	unsigned char j, k;
+	unsigned char  j, k, c;
 	struct scsi_cmnd *workrequ;
 	unsigned int tmport;
-	struct atp_unit *dev = (struct atp_unit *)&SCpnt->device->host->hostdata;
+	struct atp_unit *dev;	
+	struct Scsi_Host *host;
+	host = SCpnt->device->host;
 
-	printk(KERN_DEBUG "working=%x last_cmd=%x ", dev->working, dev->last_cmd);
-	printk(" quhdu=%x quendu=%x ", dev->quhdu, dev->quendu);
-	tmport = dev->ioport;
-	for (j = 0; j < 0x17; j++) {
+	dev = (struct atp_unit *)&host->hostdata;
+	c=SCpnt->device->channel;
+	printk(" atp870u: abort Channel = %x \n", c);
+	printk("working=%x last_cmd=%x ", dev->working[c], dev->last_cmd[c]);
+	printk(" quhdu=%x quendu=%x ", dev->quhd[c], dev->quend[c]);
+	tmport = dev->ioport[c];
+	for (j = 0; j < 0x18; j++) {
 		printk(" r%2x=%2x", j, inb(tmport++));
 	}
-	tmport += 0x05;
+	tmport += 0x04;
 	printk(" r1c=%2x", inb(tmport));
 	tmport += 0x03;
-	printk(" r1f=%2x in_snd=%2x ", inb(tmport), dev->in_snd);
-	tmport = dev->pciport;
-	printk(" r20=%2x", inb(tmport));
+	printk(" r1f=%2x in_snd=%2x ", inb(tmport), dev->in_snd[c]);
+	tmport= dev->pciport[c];
+	printk(" d00=%2x", inb(tmport));
 	tmport += 0x02;
-	printk(" r22=%2x", inb(tmport));
-	tmport = dev->ioport + 0x3a;
-	printk(" r3a=%2x \n", inb(tmport));
-	tmport = dev->ioport + 0x3b;
-	printk(" r3b=%2x \n", inb(tmport));
-	for (j = 0; j < 16; j++) {
-		if (dev->id[j].curr_req != NULL) {
-			workrequ = dev->id[j].curr_req;
-			printk("\n que cdb= ");
-			for (k = 0; k < workrequ->cmd_len; k++) {
-				printk(" %2x ", workrequ->cmnd[k]);
-			}
-			printk(" last_lenu= %lx ", dev->id[j].last_lenu);
+	printk(" d02=%2x", inb(tmport));
+	for(j=0;j<16;j++) {
+	   if (dev->id[c][j].curr_req != NULL) {
+		workrequ = dev->id[c][j].curr_req;
+		printk("\n que cdb= ");
+		for (k=0; k < workrequ->cmd_len; k++) {
+		    printk(" %2x ",workrequ->cmnd[k]);
 		}
+		printk(" last_lenu= %x ",(unsigned int)dev->id[c][j].last_len);
+	   }
 	}
-	/* Sort of - the thing handles itself */
 	return SUCCESS;
 }
 
-static const char *atp870u_info(struct Scsi_Host *notused)
+const char *atp870u_info(struct Scsi_Host *notused)
 {
 	static char buffer[128];
 
@@ -2611,17 +3053,21 @@
 	return buffer;
 }
 
+int atp870u_set_info(char *buffer, int length, struct Scsi_Host *HBAptr)
+{
+	return -ENOSYS; 	/* Currently this is a no-op */
+}
+
 #define BLS buffer + len + size
-static int atp870u_proc_info(struct Scsi_Host *HBAptr, char *buffer,
-		char **start, off_t offset, int length, int inout)
+int atp870u_proc_info(struct Scsi_Host *HBAptr, char *buffer, char **start, off_t offset, int length, int inout)
 {
 	static u8 buff[512];
 	int size = 0;
 	int len = 0;
 	off_t begin = 0;
 	off_t pos = 0;
-
-	if (inout)
+	
+	if (inout) 	
 		return -ENOSYS;
 	if (offset == 0) {
 		memset(buff, 0, sizeof(buff));
@@ -2637,7 +3083,7 @@
 	size += sprintf(BLS, "                   IRQ: %d\n", HBAptr->irq);
 	len += size;
 	pos = begin + len;
-
+	
 	*start = buffer + (offset - begin);	/* Start of wanted data */
 	len -= (offset - begin);	/* Start slop */
 	if (len > length) {
@@ -2646,15 +3092,15 @@
 	return (len);
 }
 
-static int atp870u_biosparam(struct scsi_device *sdev,
-		struct block_device *dev, sector_t capacity, int *ip)
+
+static int atp870u_biosparam(struct scsi_device *disk, struct block_device *dev,
+			sector_t capacity, int *ip)
 {
 	int heads, sectors, cylinders;
 
 	heads = 64;
 	sectors = 32;
 	cylinders = (unsigned long)capacity / (heads * sectors);
-
 	if (cylinders > 1024) {
 		heads = 255;
 		sectors = 63;
@@ -2667,39 +3113,46 @@
 	return 0;
 }
 
-static void atp870u_remove(struct pci_dev *pdev)
-{
-	struct atp_unit *atp_dev = pci_get_drvdata(pdev);
-	struct Scsi_Host *pshost = atp_dev->host;
-
+static void atp870u_remove (struct pci_dev *pdev)
+{	
+	struct atp_unit *devext = pci_get_drvdata(pdev);
+	struct Scsi_Host *pshost = devext->host;
+	
+	
 	scsi_remove_host(pshost);
+	printk(KERN_INFO "free_irq : %d\n",pshost->irq);
 	free_irq(pshost->irq, pshost);
 	release_region(pshost->io_port, pshost->n_io_port);
+	printk(KERN_INFO "atp870u_free_tables : %p\n",pshost);
 	atp870u_free_tables(pshost);
+	printk(KERN_INFO "scsi_host_put : %p\n",pshost);
 	scsi_host_put(pshost);
-	pci_set_drvdata(pdev, NULL);
+	printk(KERN_INFO "pci_set_drvdata : %p\n",pdev);
+	pci_set_drvdata(pdev, NULL);	
 }
-
 MODULE_LICENSE("GPL");
 
 static struct scsi_host_template atp870u_template = {
-	.module			= THIS_MODULE,
-	.name			= "atp870u",
-	.proc_name		= "atp870u",
-	.proc_info		= atp870u_proc_info,
-	.info			= atp870u_info,
-	.queuecommand		= atp870u_queuecommand,
-	.eh_abort_handler	= atp870u_abort,
-	.bios_param		= atp870u_biosparam,
-	.can_queue		= qcnt,
-	.this_id		= 7,
-	.sg_tablesize		= ATP870U_SCATTER,
-	.cmd_per_lun		= ATP870U_CMDLUN,
-	.use_clustering		= ENABLE_CLUSTERING,
+     .module			= THIS_MODULE,
+     .name              	= "atp870u"		/* name */,
+     .proc_name			= "atp870u",
+     .proc_info			= atp870u_proc_info,
+     .info              	= atp870u_info		/* info */,
+     .queuecommand      	= atp870u_queuecommand	/* queuecommand */,
+     .eh_abort_handler  	= atp870u_abort		/* abort */,
+     .bios_param        	= atp870u_biosparam	/* biosparm */,
+     .can_queue         	= qcnt			/* can_queue */,
+     .this_id           	= 7			/* SCSI ID */,
+     .sg_tablesize      	= ATP870U_SCATTER	/*SG_ALL*/ /*SG_NONE*/,
+     .cmd_per_lun       	= ATP870U_CMDLUN		/* commands per lun */,
+     .use_clustering    	= ENABLE_CLUSTERING,
+     .max_sectors		= ATP870U_MAX_SECTORS,
 };
 
 static struct pci_device_id atp870u_id_table[] = {
-	{ PCI_DEVICE(PCI_VENDOR_ID_ARTOP, 0x8081)			  },
+	{ PCI_DEVICE(PCI_VENDOR_ID_ARTOP, ATP885_DEVID)			  },
+	{ PCI_DEVICE(PCI_VENDOR_ID_ARTOP, ATP880_DEVID1)			  },
+	{ PCI_DEVICE(PCI_VENDOR_ID_ARTOP, ATP880_DEVID2)			  },
 	{ PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_AEC7610)    },
 	{ PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_AEC7612UW)  },
 	{ PCI_DEVICE(PCI_VENDOR_ID_ARTOP, PCI_DEVICE_ID_ARTOP_AEC7612U)   },
@@ -2712,7 +3165,7 @@
 
 MODULE_DEVICE_TABLE(pci, atp870u_id_table);
 
-static struct pci_driver atp870u_driver = {	
+static struct pci_driver atp870u_driver = {
 	.id_table	= atp870u_id_table,
 	.name		= "atp870u",
 	.probe		= atp870u_probe,
@@ -2721,12 +3174,686 @@
 
 static int __init atp870u_init(void)
 {
-	return pci_module_init(&atp870u_driver);
+#ifdef ED_DBGP	
+	printk("atp870u_init: Entry\n");
+#endif	
+	return pci_register_driver(&atp870u_driver);
 }
 
 static void __exit atp870u_exit(void)
 {
+#ifdef ED_DBGP	
+	printk("atp870u_exit: Entry\n");
+#endif
 	pci_unregister_driver(&atp870u_driver);
+}
+
+void tscam_885(void)
+{
+	unsigned char i;
+
+	for (i = 0; i < 0x2; i++) {
+		mdelay(300);
+	}
+	return;
+}
+
+
+
+void is885(struct atp_unit *dev, unsigned int wkport,unsigned char c)
+{
+	unsigned int tmport;
+	unsigned char i, j, k, rmb, n, lvdmode;
+	unsigned short int m;
+	static unsigned char mbuf[512];
+	static unsigned char satn[9] =	{0, 0, 0, 0, 0, 0, 0, 6, 6};
+	static unsigned char inqd[9] =	{0x12, 0, 0, 0, 0x24, 0, 0, 0x24, 6};
+	static unsigned char synn[6] =	{0x80, 1, 3, 1, 0x19, 0x0e};
+	unsigned char synu[6] =  {0x80, 1, 3, 1, 0x0a, 0x0e};
+	static unsigned char synw[6] =	{0x80, 1, 3, 1, 0x19, 0x0e};
+	unsigned char synuw[6] =  {0x80, 1, 3, 1, 0x0a, 0x0e};
+	static unsigned char wide[6] =	{0x80, 1, 2, 3, 1, 0};
+	static unsigned char u3[9] = { 0x80,1,6,4,0x09,00,0x0e,0x01,0x02 };
+
+	lvdmode=inb(wkport + 0x1b) >> 7;
+
+	for (i = 0; i < 16; i++) {
+		m = 1;
+		m = m << i;
+		if ((m & dev->active_id[c]) != 0) {
+			continue;
+		}
+		if (i == dev->host_id[c]) {
+			printk(KERN_INFO "         ID: %2d  Host Adapter\n", dev->host_id[c]);
+			continue;
+		}
+		tmport = wkport + 0x1b;
+		outb(0x01, tmport);
+		tmport = wkport + 0x01;
+		outb(0x08, tmport++);
+		outb(0x7f, tmport++);
+		outb(satn[0], tmport++);
+		outb(satn[1], tmport++);
+		outb(satn[2], tmport++);
+		outb(satn[3], tmport++);
+		outb(satn[4], tmport++);
+		outb(satn[5], tmport++);
+		tmport += 0x06;
+		outb(0, tmport);
+		tmport += 0x02;
+		outb(dev->id[c][i].devsp, tmport++);
+		
+		outb(0, tmport++);
+		outb(satn[6], tmport++);
+		outb(satn[7], tmport++);
+		j = i;
+		if ((j & 0x08) != 0) {
+			j = (j & 0x07) | 0x40;
+		}
+		outb(j, tmport);
+		tmport += 0x03;
+		outb(satn[8], tmport);
+		tmport += 0x07;
+
+		while ((inb(tmport) & 0x80) == 0x00);
+		tmport -= 0x08;
+		if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) {
+			continue;
+		}
+		while (inb(tmport) != 0x8e);
+		dev->active_id[c] |= m;
+
+		tmport = wkport + 0x10;
+		outb(0x30, tmport);
+		tmport = wkport + 0x14;
+		outb(0x00, tmport);
+
+phase_cmd:
+		tmport = wkport + 0x18;
+		outb(0x08, tmport);
+		tmport += 0x07;
+		while ((inb(tmport) & 0x80) == 0x00);
+		tmport -= 0x08;
+		j = inb(tmport);
+		if (j != 0x16) {
+			tmport = wkport + 0x10;
+			outb(0x41, tmport);
+			goto phase_cmd;
+		}
+sel_ok:
+		tmport = wkport + 0x03;
+		outb(inqd[0], tmport++);
+		outb(inqd[1], tmport++);
+		outb(inqd[2], tmport++);
+		outb(inqd[3], tmport++);
+		outb(inqd[4], tmport++);
+		outb(inqd[5], tmport);
+		tmport += 0x07;
+		outb(0, tmport);
+		tmport += 0x02;
+		outb(dev->id[c][i].devsp, tmport++);
+		outb(0, tmport++);
+		outb(inqd[6], tmport++);
+		outb(inqd[7], tmport++);
+		tmport += 0x03;
+		outb(inqd[8], tmport);
+		tmport += 0x07;
+		while ((inb(tmport) & 0x80) == 0x00);
+		tmport -= 0x08;
+		if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) {
+			continue;
+		}
+		while (inb(tmport) != 0x8e);
+		tmport = wkport + 0x1b;
+		outb(0x00, tmport);
+		tmport = wkport + 0x18;
+		outb(0x08, tmport);
+		tmport += 0x07;
+		j = 0;
+rd_inq_data:
+		k = inb(tmport);
+		if ((k & 0x01) != 0) {
+			tmport -= 0x06;
+			mbuf[j++] = inb(tmport);
+			tmport += 0x06;
+			goto rd_inq_data;
+		}
+		if ((k & 0x80) == 0) {
+			goto rd_inq_data;
+		}
+		tmport -= 0x08;
+		j = inb(tmport);
+		if (j == 0x16) {
+			goto inq_ok;
+		}
+		tmport = wkport + 0x10;
+		outb(0x46, tmport);
+		tmport += 0x02;
+		outb(0, tmport++);
+		outb(0, tmport++);
+		outb(0, tmport++);
+		tmport += 0x03;
+		outb(0x08, tmport);
+		tmport += 0x07;
+		while ((inb(tmport) & 0x80) == 0x00);
+		tmport -= 0x08;
+		if (inb(tmport) != 0x16) {
+			goto sel_ok;
+		}
+inq_ok:
+		mbuf[36] = 0;
+		printk( KERN_INFO"         ID: %2d  %s\n", i, &mbuf[8]);
+		dev->id[c][i].devtype = mbuf[0];
+		rmb = mbuf[1];
+		n = mbuf[7];
+		if ((mbuf[7] & 0x60) == 0) {
+			goto not_wide;
+		}
+		if ((i < 8) && ((dev->global_map[c] & 0x20) == 0)) {
+			goto not_wide;
+		}
+		if (lvdmode == 0) {
+		   goto chg_wide;
+		}
+		if (dev->sp[c][i] != 0x04) {	// force u2
+		   goto chg_wide;
+		}
+
+		tmport = wkport + 0x1b;
+		outb(0x01, tmport);
+		tmport = wkport + 0x03;
+		outb(satn[0], tmport++);
+		outb(satn[1], tmport++);
+		outb(satn[2], tmport++);
+		outb(satn[3], tmport++);
+		outb(satn[4], tmport++);
+		outb(satn[5], tmport++);
+		tmport += 0x06;
+		outb(0, tmport);
+		tmport += 0x02;
+		outb(dev->id[c][i].devsp, tmport++);
+		outb(0, tmport++);
+		outb(satn[6], tmport++);
+		outb(satn[7], tmport++);
+		tmport += 0x03;
+		outb(satn[8], tmport);
+		tmport += 0x07;
+
+		while ((inb(tmport) & 0x80) == 0x00);
+		tmport -= 0x08;
+		if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) {
+			continue;
+		}
+		while (inb(tmport) != 0x8e);
+try_u3:
+		j = 0;
+		tmport = wkport + 0x14;
+		outb(0x09, tmport);
+		tmport += 0x04;
+		outb(0x20, tmport);
+		tmport += 0x07;
+
+		while ((inb(tmport) & 0x80) == 0) {
+			if ((inb(tmport) & 0x01) != 0) {
+				tmport -= 0x06;
+				outb(u3[j++], tmport);
+				tmport += 0x06;
+			}
+		}
+		tmport -= 0x08;
+		while ((inb(tmport) & 0x80) == 0x00);
+		j = inb(tmport) & 0x0f;
+		if (j == 0x0f) {
+			goto u3p_in;
+		}
+		if (j == 0x0a) {
+			goto u3p_cmd;
+		}
+		if (j == 0x0e) {
+			goto try_u3;
+		}
+		continue;
+u3p_out:
+		tmport = wkport + 0x18;
+		outb(0x20, tmport);
+		tmport += 0x07;
+		while ((inb(tmport) & 0x80) == 0) {
+			if ((inb(tmport) & 0x01) != 0) {
+				tmport -= 0x06;
+				outb(0, tmport);
+				tmport += 0x06;
+			}
+		}
+		tmport -= 0x08;
+		j = inb(tmport) & 0x0f;
+		if (j == 0x0f) {
+			goto u3p_in;
+		}
+		if (j == 0x0a) {
+			goto u3p_cmd;
+		}
+		if (j == 0x0e) {
+			goto u3p_out;
+		}
+		continue;
+u3p_in:
+		tmport = wkport + 0x14;
+		outb(0x09, tmport);
+		tmport += 0x04;
+		outb(0x20, tmport);
+		tmport += 0x07;
+		k = 0;
+u3p_in1:
+		j = inb(tmport);
+		if ((j & 0x01) != 0) {
+			tmport -= 0x06;
+			mbuf[k++] = inb(tmport);
+			tmport += 0x06;
+			goto u3p_in1;
+		}
+		if ((j & 0x80) == 0x00) {
+			goto u3p_in1;
+		}
+		tmport -= 0x08;
+		j = inb(tmport) & 0x0f;
+		if (j == 0x0f) {
+			goto u3p_in;
+		}
+		if (j == 0x0a) {
+			goto u3p_cmd;
+		}
+		if (j == 0x0e) {
+			goto u3p_out;
+		}
+		continue;
+u3p_cmd:
+		tmport = wkport + 0x10;
+		outb(0x30, tmport);
+		tmport = wkport + 0x14;
+		outb(0x00, tmport);
+		tmport += 0x04;
+		outb(0x08, tmport);
+		tmport += 0x07;
+		while ((inb(tmport) & 0x80) == 0x00);
+		tmport -= 0x08;
+		j = inb(tmport);
+		if (j != 0x16) {
+			if (j == 0x4e) {
+				goto u3p_out;
+			}
+			continue;
+		}
+		if (mbuf[0] != 0x01) {
+			goto chg_wide;
+		}
+		if (mbuf[1] != 0x06) {
+			goto chg_wide;
+		}
+		if (mbuf[2] != 0x04) {
+			goto chg_wide;
+		}
+		if (mbuf[3] == 0x09) {
+		   m = 1;
+		   m = m << i;
+		   dev->wide_id[c] |= m;
+		   dev->id[c][i].devsp = 0xce;
+#ifdef ED_DBGP		   
+		   printk("dev->id[%2d][%2d].devsp = %2x\n",c,i,dev->id[c][i].devsp);
+#endif
+		   continue;
+		}
+chg_wide:
+		tmport = wkport + 0x1b;
+		outb(0x01, tmport);
+		tmport = wkport + 0x03;
+		outb(satn[0], tmport++);
+		outb(satn[1], tmport++);
+		outb(satn[2], tmport++);
+		outb(satn[3], tmport++);
+		outb(satn[4], tmport++);
+		outb(satn[5], tmport++);
+		tmport += 0x06;
+		outb(0, tmport);
+		tmport += 0x02;
+		outb(dev->id[c][i].devsp, tmport++);
+		outb(0, tmport++);
+		outb(satn[6], tmport++);
+		outb(satn[7], tmport++);
+		tmport += 0x03;
+		outb(satn[8], tmport);
+		tmport += 0x07;
+
+		while ((inb(tmport) & 0x80) == 0x00);
+		tmport -= 0x08;
+		if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) {
+			continue;
+		}
+		while (inb(tmport) != 0x8e);
+try_wide:
+		j = 0;
+		tmport = wkport + 0x14;
+		outb(0x05, tmport);
+		tmport += 0x04;
+		outb(0x20, tmport);
+		tmport += 0x07;
+
+		while ((inb(tmport) & 0x80) == 0) {
+			if ((inb(tmport) & 0x01) != 0) {
+				tmport -= 0x06;
+				outb(wide[j++], tmport);
+				tmport += 0x06;
+			}
+		}
+		tmport -= 0x08;
+		while ((inb(tmport) & 0x80) == 0x00);
+		j = inb(tmport) & 0x0f;
+		if (j == 0x0f) {
+			goto widep_in;
+		}
+		if (j == 0x0a) {
+			goto widep_cmd;
+		}
+		if (j == 0x0e) {
+			goto try_wide;
+		}
+		continue;
+widep_out:
+		tmport = wkport + 0x18;
+		outb(0x20, tmport);
+		tmport += 0x07;
+		while ((inb(tmport) & 0x80) == 0) {
+			if ((inb(tmport) & 0x01) != 0) {
+				tmport -= 0x06;
+				outb(0, tmport);
+				tmport += 0x06;
+			}
+		}
+		tmport -= 0x08;
+		j = inb(tmport) & 0x0f;
+		if (j == 0x0f) {
+			goto widep_in;
+		}
+		if (j == 0x0a) {
+			goto widep_cmd;
+		}
+		if (j == 0x0e) {
+			goto widep_out;
+		}
+		continue;
+widep_in:
+		tmport = wkport + 0x14;
+		outb(0xff, tmport);
+		tmport += 0x04;
+		outb(0x20, tmport);
+		tmport += 0x07;
+		k = 0;
+widep_in1:
+		j = inb(tmport);
+		if ((j & 0x01) != 0) {
+			tmport -= 0x06;
+			mbuf[k++] = inb(tmport);
+			tmport += 0x06;
+			goto widep_in1;
+		}
+		if ((j & 0x80) == 0x00) {
+			goto widep_in1;
+		}
+		tmport -= 0x08;
+		j = inb(tmport) & 0x0f;
+		if (j == 0x0f) {
+			goto widep_in;
+		}
+		if (j == 0x0a) {
+			goto widep_cmd;
+		}
+		if (j == 0x0e) {
+			goto widep_out;
+		}
+		continue;
+widep_cmd:
+		tmport = wkport + 0x10;
+		outb(0x30, tmport);
+		tmport = wkport + 0x14;
+		outb(0x00, tmport);
+		tmport += 0x04;
+		outb(0x08, tmport);
+		tmport += 0x07;
+		while ((inb(tmport) & 0x80) == 0x00);
+		tmport -= 0x08;
+		j = inb(tmport);
+		if (j != 0x16) {
+			if (j == 0x4e) {
+				goto widep_out;
+			}
+			continue;
+		}
+		if (mbuf[0] != 0x01) {
+			goto not_wide;
+		}
+		if (mbuf[1] != 0x02) {
+			goto not_wide;
+		}
+		if (mbuf[2] != 0x03) {
+			goto not_wide;
+		}
+		if (mbuf[3] != 0x01) {
+			goto not_wide;
+		}
+		m = 1;
+		m = m << i;
+		dev->wide_id[c] |= m;
+not_wide:
+		if ((dev->id[c][i].devtype == 0x00) || (dev->id[c][i].devtype == 0x07) ||
+		    ((dev->id[c][i].devtype == 0x05) && ((n & 0x10) != 0))) {
+			m = 1;
+			m = m << i;
+			if ((dev->async[c] & m) != 0) {
+			   goto set_sync;
+			}
+		}
+		continue;
+set_sync:
+		if (dev->sp[c][i] == 0x02) {
+		   synu[4]=0x0c;
+		   synuw[4]=0x0c;
+		} else {
+		   if (dev->sp[c][i] >= 0x03) {
+		      synu[4]=0x0a;
+		      synuw[4]=0x0a;
+		   }
+		}
+		tmport = wkport + 0x1b;
+		j = 0;
+		if ((m & dev->wide_id[c]) != 0) {
+			j |= 0x01;
+		}
+		outb(j, tmport);
+		tmport = wkport + 0x03;
+		outb(satn[0], tmport++);
+		outb(satn[1], tmport++);
+		outb(satn[2], tmport++);
+		outb(satn[3], tmport++);
+		outb(satn[4], tmport++);
+		outb(satn[5], tmport++);
+		tmport += 0x06;
+		outb(0, tmport);
+		tmport += 0x02;
+		outb(dev->id[c][i].devsp, tmport++);
+		outb(0, tmport++);
+		outb(satn[6], tmport++);
+		outb(satn[7], tmport++);
+		tmport += 0x03;
+		outb(satn[8], tmport);
+		tmport += 0x07;
+
+		while ((inb(tmport) & 0x80) == 0x00);
+		tmport -= 0x08;
+		if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) {
+			continue;
+		}
+		while (inb(tmport) != 0x8e);
+try_sync:
+		j = 0;
+		tmport = wkport + 0x14;
+		outb(0x06, tmport);
+		tmport += 0x04;
+		outb(0x20, tmport);
+		tmport += 0x07;
+
+		while ((inb(tmport) & 0x80) == 0) {
+			if ((inb(tmport) & 0x01) != 0) {
+				tmport -= 0x06;
+				if ((m & dev->wide_id[c]) != 0) {
+					if ((m & dev->ultra_map[c]) != 0) {
+						outb(synuw[j++], tmport);
+					} else {
+						outb(synw[j++], tmport);
+					}
+				} else {
+					if ((m & dev->ultra_map[c]) != 0) {
+						outb(synu[j++], tmport);
+					} else {
+						outb(synn[j++], tmport);
+					}
+				}
+				tmport += 0x06;
+			}
+		}
+		tmport -= 0x08;
+		while ((inb(tmport) & 0x80) == 0x00);
+		j = inb(tmport) & 0x0f;
+		if (j == 0x0f) {
+			goto phase_ins;
+		}
+		if (j == 0x0a) {
+			goto phase_cmds;
+		}
+		if (j == 0x0e) {
+			goto try_sync;
+		}
+		continue;
+phase_outs:
+		tmport = wkport + 0x18;
+		outb(0x20, tmport);
+		tmport += 0x07;
+		while ((inb(tmport) & 0x80) == 0x00) {
+			if ((inb(tmport) & 0x01) != 0x00) {
+				tmport -= 0x06;
+				outb(0x00, tmport);
+				tmport += 0x06;
+			}
+		}
+		tmport -= 0x08;
+		j = inb(tmport);
+		if (j == 0x85) {
+			goto tar_dcons;
+		}
+		j &= 0x0f;
+		if (j == 0x0f) {
+			goto phase_ins;
+		}
+		if (j == 0x0a) {
+			goto phase_cmds;
+		}
+		if (j == 0x0e) {
+			goto phase_outs;
+		}
+		continue;
+phase_ins:
+		tmport = wkport + 0x14;
+		outb(0x06, tmport);
+		tmport += 0x04;
+		outb(0x20, tmport);
+		tmport += 0x07;
+		k = 0;
+phase_ins1:
+		j = inb(tmport);
+		if ((j & 0x01) != 0x00) {
+			tmport -= 0x06;
+			mbuf[k++] = inb(tmport);
+			tmport += 0x06;
+			goto phase_ins1;
+		}
+		if ((j & 0x80) == 0x00) {
+			goto phase_ins1;
+		}
+		tmport -= 0x08;
+		while ((inb(tmport) & 0x80) == 0x00);
+		j = inb(tmport);
+		if (j == 0x85) {
+			goto tar_dcons;
+		}
+		j &= 0x0f;
+		if (j == 0x0f) {
+			goto phase_ins;
+		}
+		if (j == 0x0a) {
+			goto phase_cmds;
+		}
+		if (j == 0x0e) {
+			goto phase_outs;
+		}
+		continue;
+phase_cmds:
+		tmport = wkport + 0x10;
+		outb(0x30, tmport);
+tar_dcons:
+		tmport = wkport + 0x14;
+		outb(0x00, tmport);
+		tmport += 0x04;
+		outb(0x08, tmport);
+		tmport += 0x07;
+		while ((inb(tmport) & 0x80) == 0x00);
+		tmport -= 0x08;
+		j = inb(tmport);
+		if (j != 0x16) {
+			continue;
+		}
+		if (mbuf[0] != 0x01) {
+			continue;
+		}
+		if (mbuf[1] != 0x03) {
+			continue;
+		}
+		if (mbuf[4] == 0x00) {
+			continue;
+		}
+		if (mbuf[3] > 0x64) {
+			continue;
+		}
+		if (mbuf[4] > 0x0e) {
+			mbuf[4] = 0x0e;
+		}
+		dev->id[c][i].devsp = mbuf[4];
+		if (mbuf[3] < 0x0c){
+			j = 0xb0;
+			goto set_syn_ok;
+		}
+		if ((mbuf[3] < 0x0d) && (rmb == 0)) {
+			j = 0xa0;
+			goto set_syn_ok;
+		}
+		if (mbuf[3] < 0x1a) {
+			j = 0x20;
+			goto set_syn_ok;
+		}
+		if (mbuf[3] < 0x33) {
+			j = 0x40;
+			goto set_syn_ok;
+		}
+		if (mbuf[3] < 0x4c) {
+			j = 0x50;
+			goto set_syn_ok;
+		}
+		j = 0x60;
+	      set_syn_ok:
+		dev->id[c][i].devsp = (dev->id[c][i].devsp & 0x0f) | j;
+#ifdef ED_DBGP		
+		printk("dev->id[%2d][%2d].devsp = %2x\n",c,i,dev->id[c][i].devsp);
+#endif
+	}
+	tmport = wkport + 0x16;
+	outb(0x80, tmport);
 }
 
 module_init(atp870u_init);
diff -Nru a/drivers/scsi/atp870u.h b/drivers/scsi/atp870u.h
--- a/drivers/scsi/atp870u.h	2005-03-11 12:51:41 -08:00
+++ b/drivers/scsi/atp870u.h	2005-03-11 12:51:41 -08:00
@@ -2,50 +2,64 @@
 #define _ATP870U_H
 
 #include <linux/types.h>
+#include <linux/kdev_t.h>
 
 /* I/O Port */
 
-#define MAX_CDB		12
-#define MAX_SENSE	14
-#define qcnt		32
-#define ATP870U_SCATTER 128
-#define ATP870U_CMDLUN 	1
-
-struct atp_unit {
-	unsigned long ioport;
-	unsigned long pciport;
-	unsigned char last_cmd;
-	unsigned char in_snd;
-	unsigned char in_int;
-	unsigned char quhdu;
-	unsigned char quendu;
+#define MAX_CDB 	12
+#define MAX_SENSE 	14
+#define qcnt	       	32
+#define ATP870U_SCATTER 	128
+#define ATP870U_CMDLUN  	1
+
+#define MAX_ADAPTER	8
+#define MAX_SCSI_ID	16
+#define ATP870U_MAX_SECTORS 128
+
+#define ATP885_DEVID 0x808A
+#define ATP880_DEVID1 0x8080
+#define ATP880_DEVID2 0x8081
+
+//#define ED_DBGP
+
+struct atp_unit
+{
+	unsigned long baseport;
+	unsigned long ioport[2];
+	unsigned long pciport[2];
+	unsigned long irq;
+	unsigned char last_cmd[2];
+	unsigned char in_snd[2];
+	unsigned char in_int[2];
+	unsigned char quhd[2];
+	unsigned char quend[2];
+	unsigned char global_map[2];
+	unsigned char chip_ver;
 	unsigned char scam_on;
-	unsigned char global_map;
-	unsigned char chip_veru;
-	unsigned char host_idu;
-	volatile int working;
-	unsigned short wide_idu;
-	unsigned short active_idu;
-	unsigned short ultra_map;
-	unsigned short async;
-	unsigned short deviceid;
-	unsigned char ata_cdbu[16];
-	unsigned char sp[16];
-	struct scsi_cmnd *querequ[qcnt];
-	struct atp_id {
-		unsigned char dirctu;
-		unsigned char devspu;
-		unsigned char devtypeu;
-		unsigned long prdaddru;
-		unsigned long tran_lenu;
-		unsigned long last_lenu;
-		unsigned char *prd_posu;
-		unsigned char *prd_tableu;
-		dma_addr_t prd_phys;
+	unsigned char host_id[2];
+	unsigned int working[2];
+	unsigned short wide_id[2];
+	unsigned short active_id[2];
+	unsigned short ultra_map[2];
+	unsigned short async[2];
+	unsigned short dev_id;
+	unsigned char sp[2][16];
+	unsigned char r1f[2][16];		
+	struct scsi_cmnd *quereq[2][qcnt];
+	struct atp_id
+	{
+		unsigned char dirct;
+		unsigned char devsp;
+		unsigned char devtype;
+		unsigned long tran_len;
+		unsigned long last_len;
+		unsigned char *prd_pos;
+		unsigned char *prd_table;
+		dma_addr_t prdaddr;
 		struct scsi_cmnd *curr_req;
-	} id[16];
-	struct Scsi_Host *host;
-	struct pci_dev *pdev;
+	} id[2][16];
+    	struct Scsi_Host *host;
+    	struct pci_dev *pdev;
 	unsigned int unit;
 };
 
diff -Nru a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c
--- a/drivers/scsi/hosts.c	2005-03-11 12:51:41 -08:00
+++ b/drivers/scsi/hosts.c	2005-03-11 12:51:41 -08:00
@@ -247,6 +247,16 @@
 	shost->cmd_per_lun = sht->cmd_per_lun;
 	shost->unchecked_isa_dma = sht->unchecked_isa_dma;
 	shost->use_clustering = sht->use_clustering;
+	shost->ordered_flush = sht->ordered_flush;
+	shost->ordered_tag = sht->ordered_tag;
+
+	/*
+	 * hosts/devices that do queueing must support ordered tags
+	 */
+	if (shost->can_queue > 1 && shost->ordered_flush) {
+		printk(KERN_ERR "scsi: ordered flushes don't support queueing\n");
+		shost->ordered_flush = 0;
+	}
 
 	if (sht->max_host_blocked)
 		shost->max_host_blocked = sht->max_host_blocked;
diff -Nru a/drivers/scsi/ide-scsi.c b/drivers/scsi/ide-scsi.c
--- a/drivers/scsi/ide-scsi.c	2005-03-11 12:51:47 -08:00
+++ b/drivers/scsi/ide-scsi.c	2005-03-11 12:51:47 -08:00
@@ -679,7 +679,6 @@
 static void idescsi_setup (ide_drive_t *drive, idescsi_scsi_t *scsi)
 {
 	DRIVER(drive)->busy++;
-	drive->ready_stat = 0;
 	if (drive->id && (drive->id->config & 0x0060) == 0x20)
 		set_bit (IDESCSI_DRQ_INTERRUPT, &scsi->flags);
 	set_bit(IDESCSI_TRANSFORM, &scsi->transform);
@@ -709,6 +708,15 @@
 
 static int idescsi_attach(ide_drive_t *drive);
 
+#ifdef CONFIG_PROC_FS
+static ide_proc_entry_t idescsi_proc[] = {
+	{ "capacity", S_IFREG|S_IRUGO, proc_ide_read_capacity, NULL },
+	{ NULL, 0, NULL, NULL }
+};
+#else
+# define idescsi_proc	NULL
+#endif
+
 /*
  *	IDE subdriver functions, registered with ide.c
  */
@@ -719,6 +727,7 @@
 	.media			= ide_scsi,
 	.busy			= 0,
 	.supports_dsc_overlap	= 0,
+	.proc			= idescsi_proc,
 	.attach			= idescsi_attach,
 	.cleanup		= idescsi_cleanup,
 	.do_request		= idescsi_do_request,
diff -Nru a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c
--- a/drivers/scsi/libata-core.c	2005-03-11 12:51:40 -08:00
+++ b/drivers/scsi/libata-core.c	2005-03-11 12:51:40 -08:00
@@ -3884,26 +3884,22 @@
 		ap = host_set->ports[i];
 
 		ata_scsi_release(ap->host);
-		scsi_host_put(ap->host);
-	}
-
-	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) {
+			struct ata_ioports *ioaddr = &ap->ioaddr;
+
 			if (ioaddr->cmd_addr == 0x1f0)
 				release_region(0x1f0, 8);
 			else if (ioaddr->cmd_addr == 0x170)
 				release_region(0x170, 8);
 		}
+
+		scsi_host_put(ap->host);
 	}
 
 	kfree(host_set);
+
+	pci_release_regions(pdev);
 	pci_disable_device(pdev);
 	dev_set_drvdata(dev, NULL);
 }
diff -Nru a/drivers/scsi/osst.c b/drivers/scsi/osst.c
--- a/drivers/scsi/osst.c	2005-03-11 12:51:46 -08:00
+++ b/drivers/scsi/osst.c	2005-03-11 12:51:46 -08:00
@@ -4318,7 +4318,13 @@
 	int		      dev  = TAPE_NR(inode);
 	int		      mode = TAPE_MODE(inode);
 
-	nonseekable_open(inode, filp);
+	/*
+	 * We really want to do nonseekable_open(inode, filp); here, but some
+	 * versions of tar incorrectly call lseek on tapes and bail out if that
+	 * fails.  So we disallow pread() and pwrite(), but permit lseeks.
+	 */
+	filp->f_mode &= ~(FMODE_PREAD | FMODE_PWRITE);
+
 	write_lock(&os_scsi_tapes_lock);
 	if (dev >= osst_max_dev || os_scsi_tapes == NULL ||
 	    (STp = os_scsi_tapes[dev]) == NULL || !STp->device) {
diff -Nru a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
--- a/drivers/scsi/qla2xxx/qla_os.c	2005-03-11 12:51:51 -08:00
+++ b/drivers/scsi/qla2xxx/qla_os.c	2005-03-11 12:51:51 -08:00
@@ -1847,13 +1847,13 @@
 		if (pio_len < MIN_IOBASE_LEN) {
 			qla_printk(KERN_WARNING, ha,
 			    "Invalid PCI I/O region size (%s)...\n",
-			    ha->pdev->slot_name);
+				pci_name(ha->pdev));
 			pio = 0;
 		}
 	} else {
 		qla_printk(KERN_WARNING, ha,
 		    "region #0 not a PIO resource (%s)...\n",
-		    ha->pdev->slot_name);
+		    pci_name(ha->pdev));
 		pio = 0;
 	}
 
@@ -1865,20 +1865,20 @@
 	if (!(mmio_flags & IORESOURCE_MEM)) {
 		qla_printk(KERN_ERR, ha,
 		    "region #0 not an MMIO resource (%s), aborting\n",
-		    ha->pdev->slot_name);
+		    pci_name(ha->pdev));
 		goto iospace_error_exit;
 	}
 	if (mmio_len < MIN_IOBASE_LEN) {
 		qla_printk(KERN_ERR, ha,
 		    "Invalid PCI mem region size (%s), aborting\n",
-		    ha->pdev->slot_name);
+			pci_name(ha->pdev));
 		goto iospace_error_exit;
 	}
 
 	if (pci_request_regions(ha->pdev, ha->brd_info->drv_name)) {
 		qla_printk(KERN_WARNING, ha,
-		    "Failed to reserve PIO/MMIO regions (%s)\n", 
-		    ha->pdev->slot_name);
+		    "Failed to reserve PIO/MMIO regions (%s)\n",
+		    pci_name(ha->pdev));
 
 		goto iospace_error_exit;
 	}
@@ -1888,7 +1888,7 @@
 	ha->iobase = ioremap(mmio, MIN_IOBASE_LEN);
 	if (!ha->iobase) {
 		qla_printk(KERN_ERR, ha,
-		    "cannot remap MMIO (%s), aborting\n", ha->pdev->slot_name);
+		    "cannot remap MMIO (%s), aborting\n", pci_name(ha->pdev));
 
 		goto iospace_error_exit;
 	}
diff -Nru a/drivers/scsi/sata_nv.c b/drivers/scsi/sata_nv.c
--- a/drivers/scsi/sata_nv.c	2005-03-11 12:51:41 -08:00
+++ b/drivers/scsi/sata_nv.c	2005-03-11 12:51:41 -08:00
@@ -99,7 +99,8 @@
 #define NV_MCP_SATA_CFG_20_SATA_SPACE_EN	0x04
 
 static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent);
-irqreturn_t nv_interrupt (int irq, void *dev_instance, struct pt_regs *regs);
+static irqreturn_t nv_interrupt (int irq, void *dev_instance,
+				 struct pt_regs *regs);
 static u32 nv_scr_read (struct ata_port *ap, unsigned int sc_reg);
 static void nv_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val);
 static void nv_host_stop (struct ata_host_set *host_set);
@@ -205,6 +206,7 @@
 	.dma_boundary		= ATA_DMA_BOUNDARY,
 	.slave_configure	= ata_scsi_slave_config,
 	.bios_param		= ata_std_bios_param,
+	.ordered_flush		= 1,
 };
 
 static struct ata_port_operations nv_ops = {
@@ -257,7 +259,8 @@
 MODULE_DEVICE_TABLE(pci, nv_pci_tbl);
 MODULE_VERSION(DRV_VERSION);
 
-irqreturn_t nv_interrupt (int irq, void *dev_instance, struct pt_regs *regs)
+static irqreturn_t nv_interrupt (int irq, void *dev_instance,
+				 struct pt_regs *regs)
 {
 	struct ata_host_set *host_set = dev_instance;
 	struct nv_host *host = host_set->private_data;
diff -Nru a/drivers/scsi/sata_promise.c b/drivers/scsi/sata_promise.c
--- a/drivers/scsi/sata_promise.c	2005-03-11 12:51:47 -08:00
+++ b/drivers/scsi/sata_promise.c	2005-03-11 12:51:47 -08:00
@@ -102,6 +102,7 @@
 	.dma_boundary		= ATA_DMA_BOUNDARY,
 	.slave_configure	= ata_scsi_slave_config,
 	.bios_param		= ata_std_bios_param,
+	.ordered_flush		= 1,
 };
 
 static struct ata_port_operations pdc_ata_ops = {
diff -Nru a/drivers/scsi/sata_qstor.c b/drivers/scsi/sata_qstor.c
--- a/drivers/scsi/sata_qstor.c	2005-03-11 12:51:47 -08:00
+++ b/drivers/scsi/sata_qstor.c	2005-03-11 12:51:47 -08:00
@@ -38,7 +38,7 @@
 #include <linux/libata.h>
 
 #define DRV_NAME	"sata_qstor"
-#define DRV_VERSION	"0.03"
+#define DRV_VERSION	"0.04"
 
 enum {
 	QS_PORTS		= 4,
@@ -120,6 +120,7 @@
 static void qs_bmdma_stop(struct ata_port *ap);
 static u8 qs_bmdma_status(struct ata_port *ap);
 static void qs_irq_clear(struct ata_port *ap);
+static void qs_eng_timeout(struct ata_port *ap);
 
 static Scsi_Host_Template qs_ata_sht = {
 	.module			= THIS_MODULE,
@@ -152,7 +153,7 @@
 	.phy_reset		= qs_phy_reset,
 	.qc_prep		= qs_qc_prep,
 	.qc_issue		= qs_qc_issue,
-	.eng_timeout		= ata_eng_timeout,
+	.eng_timeout		= qs_eng_timeout,
 	.irq_handler		= qs_intr,
 	.irq_clear		= qs_irq_clear,
 	.scr_read		= qs_scr_read,
@@ -212,7 +213,7 @@
 	/* nothing */
 }
 
-static void qs_enter_reg_mode(struct ata_port *ap)
+static inline void qs_enter_reg_mode(struct ata_port *ap)
 {
 	u8 __iomem *chan = ap->host_set->mmio_base + (ap->port_no * 0x4000);
 
@@ -220,17 +221,34 @@
 	readb(chan + QS_CCT_CTR0);        /* flush */
 }
 
-static void qs_phy_reset(struct ata_port *ap)
+static inline void qs_reset_channel_logic(struct ata_port *ap)
 {
 	u8 __iomem *chan = ap->host_set->mmio_base + (ap->port_no * 0x4000);
-	struct qs_port_priv *pp = ap->private_data;
 
-	pp->state = qs_state_idle;
 	writeb(QS_CTR1_RCHN, chan + QS_CCT_CTR1);
+	readb(chan + QS_CCT_CTR0);        /* flush */
 	qs_enter_reg_mode(ap);
+}
+
+static void qs_phy_reset(struct ata_port *ap)
+{
+	struct qs_port_priv *pp = ap->private_data;
+
+	pp->state = qs_state_idle;
+	qs_reset_channel_logic(ap);
 	sata_phy_reset(ap);
 }
 
+static void qs_eng_timeout(struct ata_port *ap)
+{
+	struct qs_port_priv *pp = ap->private_data;
+
+	if (pp->state != qs_state_idle) /* healthy paranoia */
+		pp->state = qs_state_mmio;
+	qs_reset_channel_logic(ap);
+	ata_eng_timeout(ap);
+}
+
 static u32 qs_scr_read (struct ata_port *ap, unsigned int sc_reg)
 {
 	if (sc_reg > SCR_CONTROL)
@@ -261,11 +279,11 @@
 		u32 len;
 
 		addr = sg_dma_address(sg);
-		*(u64 *)prd = cpu_to_le64(addr);
+		*(__le64 *)prd = cpu_to_le64(addr);
 		prd += sizeof(u64);
 
 		len = sg_dma_len(sg);
-		*(u32 *)prd = cpu_to_le32(len);
+		*(__le32 *)prd = cpu_to_le32(len);
 		prd += sizeof(u64);
 
 		VPRINTK("PRD[%u] = (0x%llX, 0x%X)\n", nelem,
@@ -298,10 +316,10 @@
 	/* host control block (HCB) */
 	buf[ 0] = QS_HCB_HDR;
 	buf[ 1] = hflags;
-	*(u32 *)(&buf[ 4]) = cpu_to_le32(qc->nsect * ATA_SECT_SIZE);
-	*(u32 *)(&buf[ 8]) = cpu_to_le32(qc->n_elem);
+	*(__le32 *)(&buf[ 4]) = cpu_to_le32(qc->nsect * ATA_SECT_SIZE);
+	*(__le32 *)(&buf[ 8]) = cpu_to_le32(qc->n_elem);
 	addr = ((u64)pp->pkt_dma) + QS_CPB_BYTES;
-	*(u64 *)(&buf[16]) = cpu_to_le64(addr);
+	*(__le64 *)(&buf[16]) = cpu_to_le64(addr);
 
 	/* device control block (DCB) */
 	buf[24] = QS_DCB_HDR;
@@ -566,10 +584,10 @@
 	int rc, have_64bit_bus = (bus_info & QS_HPHY_64BIT);
 
 	if (have_64bit_bus &&
-	    !pci_set_dma_mask(pdev, 0xffffffffffffffffULL)) {
-		rc = pci_set_consistent_dma_mask(pdev, 0xffffffffffffffffULL);
+	    !pci_set_dma_mask(pdev, DMA_64BIT_MASK)) {
+		rc = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK);
 		if (rc) {
-			rc = pci_set_consistent_dma_mask(pdev, 0xffffffffULL);
+			rc = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
 			if (rc) {
 				printk(KERN_ERR DRV_NAME
 					"(%s): 64-bit DMA enable failed\n",
@@ -578,14 +596,14 @@
 			}
 		}
 	} else {
-		rc = pci_set_dma_mask(pdev, 0xffffffffULL);
+		rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
 		if (rc) {
 			printk(KERN_ERR DRV_NAME
 				"(%s): 32-bit DMA enable failed\n",
 				pci_name(pdev));
 			return rc;
 		}
-		rc = pci_set_consistent_dma_mask(pdev, 0xffffffffULL);
+		rc = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
 		if (rc) {
 			printk(KERN_ERR DRV_NAME
 				"(%s): 32-bit consistent DMA enable failed\n",
diff -Nru a/drivers/scsi/sata_sil.c b/drivers/scsi/sata_sil.c
--- a/drivers/scsi/sata_sil.c	2005-03-11 12:51:40 -08:00
+++ b/drivers/scsi/sata_sil.c	2005-03-11 12:51:40 -08:00
@@ -78,7 +78,7 @@
 
 
 /* TODO firmware versions should be added - eric */
-struct sil_drivelist {
+static const struct sil_drivelist {
 	const char * product;
 	unsigned int quirk;
 } sil_blacklist [] = {
@@ -125,6 +125,7 @@
 	.dma_boundary		= ATA_DMA_BOUNDARY,
 	.slave_configure	= ata_scsi_slave_config,
 	.bios_param		= ata_std_bios_param,
+	.ordered_flush		= 1,
 };
 
 static struct ata_port_operations sil_ops = {
diff -Nru a/drivers/scsi/sata_sis.c b/drivers/scsi/sata_sis.c
--- a/drivers/scsi/sata_sis.c	2005-03-11 12:51:46 -08:00
+++ b/drivers/scsi/sata_sis.c	2005-03-11 12:51:46 -08:00
@@ -90,6 +90,7 @@
 	.dma_boundary		= ATA_DMA_BOUNDARY,
 	.slave_configure	= ata_scsi_slave_config,
 	.bios_param		= ata_std_bios_param,
+	.ordered_flush		= 1,
 };
 
 static struct ata_port_operations sis_ops = {
diff -Nru a/drivers/scsi/sata_svw.c b/drivers/scsi/sata_svw.c
--- a/drivers/scsi/sata_svw.c	2005-03-11 12:51:47 -08:00
+++ b/drivers/scsi/sata_svw.c	2005-03-11 12:51:47 -08:00
@@ -156,7 +156,7 @@
  *	spin_lock_irqsave(host_set lock)
  */
 
-void k2_bmdma_setup_mmio (struct ata_queued_cmd *qc)
+static void k2_bmdma_setup_mmio (struct ata_queued_cmd *qc)
 {
 	struct ata_port *ap = qc->ap;
 	unsigned int rw = (qc->tf.flags & ATA_TFLAG_WRITE);
@@ -186,7 +186,7 @@
  *	spin_lock_irqsave(host_set lock)
  */
 
-void k2_bmdma_start_mmio (struct ata_queued_cmd *qc)
+static void k2_bmdma_start_mmio (struct ata_queued_cmd *qc)
 {
 	struct ata_port *ap = qc->ap;
 	void *mmio = (void *) ap->ioaddr.bmdma_addr;
@@ -288,6 +288,7 @@
 	.proc_info		= k2_sata_proc_info,
 #endif
 	.bios_param		= ata_std_bios_param,
+	.ordered_flush		= 1,
 };
 
 
diff -Nru a/drivers/scsi/sata_sx4.c b/drivers/scsi/sata_sx4.c
--- a/drivers/scsi/sata_sx4.c	2005-03-11 12:51:40 -08:00
+++ b/drivers/scsi/sata_sx4.c	2005-03-11 12:51:40 -08:00
@@ -188,6 +188,7 @@
 	.dma_boundary		= ATA_DMA_BOUNDARY,
 	.slave_configure	= ata_scsi_slave_config,
 	.bios_param		= ata_std_bios_param,
+	.ordered_flush		= 1,
 };
 
 static struct ata_port_operations pdc_20621_ops = {
diff -Nru a/drivers/scsi/sata_uli.c b/drivers/scsi/sata_uli.c
--- a/drivers/scsi/sata_uli.c	2005-03-11 12:51:51 -08:00
+++ b/drivers/scsi/sata_uli.c	2005-03-11 12:51:51 -08:00
@@ -82,6 +82,7 @@
 	.dma_boundary		= ATA_DMA_BOUNDARY,
 	.slave_configure	= ata_scsi_slave_config,
 	.bios_param		= ata_std_bios_param,
+	.ordered_flush		= 1,
 };
 
 static struct ata_port_operations uli_ops = {
diff -Nru a/drivers/scsi/sata_via.c b/drivers/scsi/sata_via.c
--- a/drivers/scsi/sata_via.c	2005-03-11 12:51:41 -08:00
+++ b/drivers/scsi/sata_via.c	2005-03-11 12:51:41 -08:00
@@ -102,6 +102,7 @@
 	.dma_boundary		= ATA_DMA_BOUNDARY,
 	.slave_configure	= ata_scsi_slave_config,
 	.bios_param		= ata_std_bios_param,
+	.ordered_flush		= 1,
 };
 
 static struct ata_port_operations svia_sata_ops = {
diff -Nru a/drivers/scsi/sata_vsc.c b/drivers/scsi/sata_vsc.c
--- a/drivers/scsi/sata_vsc.c	2005-03-11 12:51:46 -08:00
+++ b/drivers/scsi/sata_vsc.c	2005-03-11 12:51:46 -08:00
@@ -155,7 +155,8 @@
  *
  * 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)
+static 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;
@@ -204,6 +205,7 @@
 	.dma_boundary		= ATA_DMA_BOUNDARY,
 	.slave_configure	= ata_scsi_slave_config,
 	.bios_param		= ata_std_bios_param,
+	.ordered_flush		= 1,
 };
 
 
@@ -285,10 +287,10 @@
 	/*
 	 * Use 32 bit DMA mask, because 64 bit address support is poor.
 	 */
-	rc = pci_set_dma_mask(pdev, 0xFFFFFFFFULL);
+	rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
 	if (rc)
 		goto err_out_regions;
-	rc = pci_set_consistent_dma_mask(pdev, 0xFFFFFFFFULL);
+	rc = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK);
 	if (rc)
 		goto err_out_regions;
 
diff -Nru a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
--- a/drivers/scsi/scsi_lib.c	2005-03-11 12:51:46 -08:00
+++ b/drivers/scsi/scsi_lib.c	2005-03-11 12:51:46 -08:00
@@ -697,6 +697,9 @@
 	int sense_valid = 0;
 	int sense_deferred = 0;
 
+	if (blk_complete_barrier_rq(q, req, good_bytes >> 9))
+		return;
+
 	/*
 	 * Free up any indirection buffers we allocated for DMA purposes. 
 	 * For the case of a READ, we need to copy the data out of the
@@ -723,7 +726,7 @@
 		req->errors = result;
 		if (result) {
 			clear_errors = 0;
-			if (sense_valid) {
+			if (sense_valid && req->sense) {
 				/*
 				 * SG_IO wants current and deferred errors
 				 */
@@ -962,6 +965,38 @@
 	return BLKPREP_KILL;
 }
 
+static int scsi_prepare_flush_fn(request_queue_t *q, struct request *rq)
+{
+	struct scsi_device *sdev = q->queuedata;
+	struct scsi_driver *drv;
+
+	if (sdev->sdev_state == SDEV_RUNNING) {
+		drv = *(struct scsi_driver **) rq->rq_disk->private_data;
+
+		if (drv->prepare_flush)
+			return drv->prepare_flush(q, rq);
+	}
+
+	return 0;
+}
+
+static void scsi_end_flush_fn(request_queue_t *q, struct request *rq)
+{
+	struct scsi_device *sdev = q->queuedata;
+	struct request *flush_rq = rq->end_io_data;
+	struct scsi_driver *drv;
+
+	if (flush_rq->errors) {
+		printk("scsi: barrier error, disabling flush support\n");
+		blk_queue_ordered(q, QUEUE_ORDERED_NONE);
+	}
+
+	if (sdev->sdev_state == SDEV_RUNNING) {
+		drv = *(struct scsi_driver **) rq->rq_disk->private_data;
+		drv->end_flush(q, rq);
+	}
+}
+
 static int scsi_issue_flush_fn(request_queue_t *q, struct gendisk *disk,
 			       sector_t *error_sector)
 {
@@ -1365,6 +1400,17 @@
 	blk_queue_bounce_limit(q, scsi_calculate_bounce_limit(shost));
 	blk_queue_segment_boundary(q, shost->dma_boundary);
 	blk_queue_issue_flush_fn(q, scsi_issue_flush_fn);
+
+	/*
+	 * ordered tags are superior to flush ordering
+	 */
+	if (shost->ordered_tag)
+		blk_queue_ordered(q, QUEUE_ORDERED_TAG);
+	else if (shost->ordered_flush) {
+		blk_queue_ordered(q, QUEUE_ORDERED_FLUSH);
+		q->prepare_flush_fn = scsi_prepare_flush_fn;
+		q->end_flush_fn = scsi_end_flush_fn;
+	}
 
 	if (!shost->use_clustering)
 		clear_bit(QUEUE_FLAG_CLUSTER, &q->queue_flags);
diff -Nru a/drivers/scsi/sd.c b/drivers/scsi/sd.c
--- a/drivers/scsi/sd.c	2005-03-11 12:51:48 -08:00
+++ b/drivers/scsi/sd.c	2005-03-11 12:51:48 -08:00
@@ -122,6 +122,8 @@
 static void sd_rescan(struct device *);
 static int sd_init_command(struct scsi_cmnd *);
 static int sd_issue_flush(struct device *, sector_t *);
+static void sd_end_flush(request_queue_t *, struct request *);
+static int sd_prepare_flush(request_queue_t *, struct request *);
 static void sd_read_capacity(struct scsi_disk *sdkp, char *diskname,
 		 struct scsi_request *SRpnt, unsigned char *buffer);
 
@@ -136,6 +138,8 @@
 	.rescan			= sd_rescan,
 	.init_command		= sd_init_command,
 	.issue_flush		= sd_issue_flush,
+	.prepare_flush		= sd_prepare_flush,
+	.end_flush		= sd_end_flush,
 };
 
 /*
@@ -733,6 +737,45 @@
 		return 0;
 
 	return sd_sync_cache(sdp);
+}
+
+static void sd_end_flush(request_queue_t *q, struct request *flush_rq)
+{
+	struct request *rq = flush_rq->end_io_data;
+	struct scsi_cmnd *cmd = rq->special;
+	unsigned int bytes = rq->hard_nr_sectors << 9;
+
+	if (!flush_rq->errors) {
+		spin_unlock(q->queue_lock);
+		scsi_io_completion(cmd, bytes, 0);
+		spin_lock(q->queue_lock);
+	} else if (blk_barrier_postflush(rq)) {
+		spin_unlock(q->queue_lock);
+		scsi_io_completion(cmd, 0, bytes);
+		spin_lock(q->queue_lock);
+	} else {
+		/*
+		 * force journal abort of barriers
+		 */
+		end_that_request_first(rq, -EOPNOTSUPP, rq->hard_nr_sectors);
+		end_that_request_last(rq);
+	}
+}
+
+static int sd_prepare_flush(request_queue_t *q, struct request *rq)
+{
+	struct scsi_device *sdev = q->queuedata;
+	struct scsi_disk *sdkp = dev_get_drvdata(&sdev->sdev_gendev);
+
+	if (sdkp->WCE) {
+		memset(rq->cmd, 0, sizeof(rq->cmd));
+		rq->flags |= REQ_BLOCK_PC | REQ_SOFTBARRIER;
+		rq->timeout = SD_TIMEOUT;
+		rq->cmd[0] = SYNCHRONIZE_CACHE;
+		return 1;
+	}
+
+	return 0;
 }
 
 static void sd_rescan(struct device *dev)
diff -Nru a/drivers/scsi/st.c b/drivers/scsi/st.c
--- a/drivers/scsi/st.c	2005-03-11 12:51:47 -08:00
+++ b/drivers/scsi/st.c	2005-03-11 12:51:47 -08:00
@@ -1004,7 +1004,13 @@
 	int dev = TAPE_NR(inode);
 	char *name;
 
-	nonseekable_open(inode, filp);
+	/*
+	 * We really want to do nonseekable_open(inode, filp); here, but some
+	 * versions of tar incorrectly call lseek on tapes and bail out if that
+	 * fails.  So we disallow pread() and pwrite(), but permit lseeks.
+	 */
+	filp->f_mode &= ~(FMODE_PREAD | FMODE_PWRITE);
+
 	write_lock(&st_dev_arr_lock);
 	if (dev >= st_dev_max || scsi_tapes == NULL ||
 	    ((STp = scsi_tapes[dev]) == NULL)) {
diff -Nru a/drivers/serial/21285.c b/drivers/serial/21285.c
--- a/drivers/serial/21285.c	2005-03-11 12:51:48 -08:00
+++ b/drivers/serial/21285.c	2005-03-11 12:51:48 -08:00
@@ -142,7 +142,6 @@
 	}
 	tty_flip_buffer_push(tty);
 
- out:
 	return IRQ_HANDLED;
 }
 
@@ -383,11 +382,9 @@
 };
 
 static struct uart_port serial21285_port = {
-	.membase	= 0,
 	.mapbase	= 0x42000160,
 	.iotype		= SERIAL_IO_MEM,
 	.irq		= NO_IRQ,
-	.uartclk	= 0,
 	.fifosize	= 16,
 	.ops		= &serial21285_ops,
 	.flags		= ASYNC_BOOT_AUTOCONF,
diff -Nru a/drivers/serial/8250.c b/drivers/serial/8250.c
--- a/drivers/serial/8250.c	2005-03-11 12:51:41 -08:00
+++ b/drivers/serial/8250.c	2005-03-11 12:51:41 -08:00
@@ -642,6 +642,7 @@
 static void autoconfig_16550a(struct uart_8250_port *up)
 {
 	unsigned char status1, status2;
+	unsigned int iersave;
 
 	up->port.type = PORT_16550A;
 	up->capabilities |= UART_CAP_FIFO;
@@ -728,6 +729,7 @@
 	serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO | UART_FCR7_64BYTE);
 	status2 = serial_in(up, UART_IIR) >> 5;
 	serial_outp(up, UART_FCR, UART_FCR_ENABLE_FIFO);
+	serial_outp(up, UART_LCR, 0);
 
 	DEBUG_AUTOCONF("iir1=%d iir2=%d ", status1, status2);
 
@@ -736,6 +738,40 @@
 		up->capabilities |= UART_CAP_AFE | UART_CAP_SLEEP;
 		return;
 	}
+
+	/*
+	 * Try writing and reading the UART_IER_UUE bit (b6).
+	 * If it works, this is probably one of the Xscale platform's
+	 * internal UARTs.
+	 * We're going to explicitly set the UUE bit to 0 before
+	 * trying to write and read a 1 just to make sure it's not
+	 * already a 1 and maybe locked there before we even start start.
+	 */
+	iersave = serial_in(up, UART_IER);
+	serial_outp(up, UART_IER, iersave & ~UART_IER_UUE);
+	if (!(serial_in(up, UART_IER) & UART_IER_UUE)) {
+		/*
+		 * OK it's in a known zero state, try writing and reading
+		 * without disturbing the current state of the other bits.
+		 */
+		serial_outp(up, UART_IER, iersave | UART_IER_UUE);
+		if (serial_in(up, UART_IER) & UART_IER_UUE) {
+			/*
+			 * It's an Xscale.
+			 * We'll leave the UART_IER_UUE bit set to 1 (enabled).
+			 */
+			DEBUG_AUTOCONF("Xscale ");
+			up->port.type = PORT_XSCALE;
+			return;
+		}
+	} else {
+		/*
+		 * If we got here we couldn't force the IER_UUE bit to 0.
+		 * Log it and continue.
+		 */
+		DEBUG_AUTOCONF("Couldn't force IER_UUE to 0 ");
+	}
+	serial_outp(up, UART_IER, iersave);
 }
 
 /*
diff -Nru a/drivers/serial/8250_pci.c b/drivers/serial/8250_pci.c
--- a/drivers/serial/8250_pci.c	2005-03-11 12:51:48 -08:00
+++ b/drivers/serial/8250_pci.c	2005-03-11 12:51:48 -08:00
@@ -1759,7 +1759,7 @@
 	}
 }
 
-static int pciserial_suspend_one(struct pci_dev *dev, u32 state)
+static int pciserial_suspend_one(struct pci_dev *dev, pm_message_t state)
 {
 	struct serial_private *priv = pci_get_drvdata(dev);
 
@@ -1769,6 +1769,8 @@
 		for (i = 0; i < priv->nr; i++)
 			serial8250_suspend_port(priv->line[i]);
 	}
+	pci_save_state(dev);
+	pci_set_power_state(dev, pci_choose_state(dev, state));
 	return 0;
 }
 
@@ -1776,8 +1778,16 @@
 {
 	struct serial_private *priv = pci_get_drvdata(dev);
 
+	pci_set_power_state(dev, PCI_D0);
+	pci_restore_state(dev);
+
 	if (priv) {
 		int i;
+
+		/*
+		 * The device may have been disabled.  Re-enable it.
+		 */
+		pci_enable_device(dev);
 
 		/*
 		 * Ensure that the board is correctly configured.
diff -Nru a/drivers/serial/Kconfig b/drivers/serial/Kconfig
--- a/drivers/serial/Kconfig	2005-03-11 12:51:51 -08:00
+++ b/drivers/serial/Kconfig	2005-03-11 12:51:51 -08:00
@@ -810,4 +810,21 @@
 	bool "TX39XX/49XX SIO act as standard serial"
 	depends on !SERIAL_8250 && SERIAL_TXX9
 
+config SERIAL_VR41XX
+	tristate "NEC VR4100 series Serial Interface Unit support"
+	depends on CPU_VR41XX
+	select SERIAL_CORE
+	help
+	  If you have a NEC VR4100 series processor and you want to use
+	  Serial Interface Unit(SIU) or Debug Serial Interface Unit(DSIU)
+	  (not include VR4111/VR4121 DSIU), say Y.  Otherwise, say N.
+
+config SERIAL_VR41XX_CONSOLE
+	bool "Enable NEC VR4100 series Serial Interface Unit console"
+	depends on SERIAL_VR41XX
+	select SERIAL_CORE_CONSOLE
+	help
+	  If you have a NEC VR4100 series processor and you want to use
+	  a console on a serial port, say Y.  Otherwise, say N.
+
 endmenu
diff -Nru a/drivers/serial/Makefile b/drivers/serial/Makefile
--- a/drivers/serial/Makefile	2005-03-11 12:51:46 -08:00
+++ b/drivers/serial/Makefile	2005-03-11 12:51:46 -08:00
@@ -49,3 +49,5 @@
 obj-$(CONFIG_SERIAL_MPSC) += mpsc.o
 obj-$(CONFIG_ETRAX_SERIAL) += crisv10.o
 obj-$(CONFIG_SERIAL_TXX9) += serial_txx9.o
+obj-$(CONFIG_SERIAL_VR41XX) += vr41xx_siu.o
+obj-$(CONFIG_BLK_DEV_SGIIOC4) += ioc4_serial.o
diff -Nru a/drivers/serial/cpm_uart/cpm_uart_core.c b/drivers/serial/cpm_uart/cpm_uart_core.c
--- a/drivers/serial/cpm_uart/cpm_uart_core.c	2005-03-11 12:51:51 -08:00
+++ b/drivers/serial/cpm_uart/cpm_uart_core.c	2005-03-11 12:51:51 -08:00
@@ -864,6 +864,7 @@
 			.irq		= SMC1_IRQ,
 			.ops		= &cpm_uart_pops,
 			.iotype		= SERIAL_IO_MEM,
+			.lock		= SPIN_LOCK_UNLOCKED,
 		},
 		.flags = FLAG_SMC,
 		.tx_nrfifos = TX_NUM_FIFO,
@@ -877,6 +878,7 @@
 			.irq		= SMC2_IRQ,
 			.ops		= &cpm_uart_pops,
 			.iotype		= SERIAL_IO_MEM,
+			.lock		= SPIN_LOCK_UNLOCKED,
 		},
 		.flags = FLAG_SMC,
 		.tx_nrfifos = TX_NUM_FIFO,
@@ -893,6 +895,7 @@
 			.irq		= SCC1_IRQ,
 			.ops		= &cpm_uart_pops,
 			.iotype		= SERIAL_IO_MEM,
+			.lock		= SPIN_LOCK_UNLOCKED,
 		},
 		.tx_nrfifos = TX_NUM_FIFO,
 		.tx_fifosize = TX_BUF_SIZE,
@@ -905,6 +908,7 @@
 			.irq		= SCC2_IRQ,
 			.ops		= &cpm_uart_pops,
 			.iotype		= SERIAL_IO_MEM,
+			.lock		= SPIN_LOCK_UNLOCKED,
 		},
 		.tx_nrfifos = TX_NUM_FIFO,
 		.tx_fifosize = TX_BUF_SIZE,
@@ -917,6 +921,7 @@
 			.irq		= SCC3_IRQ,
 			.ops		= &cpm_uart_pops,
 			.iotype		= SERIAL_IO_MEM,
+			.lock		= SPIN_LOCK_UNLOCKED,
 		},
 		.tx_nrfifos = TX_NUM_FIFO,
 		.tx_fifosize = TX_BUF_SIZE,
@@ -929,6 +934,7 @@
 			.irq		= SCC4_IRQ,
 			.ops		= &cpm_uart_pops,
 			.iotype		= SERIAL_IO_MEM,
+			.lock		= SPIN_LOCK_UNLOCKED,
 		},
 		.tx_nrfifos = TX_NUM_FIFO,
 		.tx_fifosize = TX_BUF_SIZE,
diff -Nru a/drivers/serial/ioc4_serial.c b/drivers/serial/ioc4_serial.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/serial/ioc4_serial.c	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,2909 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2003-2005 Silicon Graphics, Inc.  All Rights Reserved.
+ */
+
+
+/*
+ * This file contains a module version of the ioc4 serial driver. This
+ * includes all the support functions needed (support functions, etc.)
+ * and the serial driver itself.
+ */
+#include <linux/errno.h>
+#include <linux/tty.h>
+#include <linux/serial.h>
+#include <linux/serialP.h>
+#include <linux/circ_buf.h>
+#include <linux/serial_reg.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/ioc4_common.h>
+#include <linux/serial_core.h>
+
+/*
+ * interesting things about the ioc4
+ */
+
+#define IOC4_NUM_SERIAL_PORTS	4	/* max ports per card */
+#define IOC4_NUM_CARDS		8	/* max cards per partition */
+
+#define	GET_SIO_IR(_n)	(_n == 0) ? (IOC4_SIO_IR_S0) : \
+				(_n == 1) ? (IOC4_SIO_IR_S1) : \
+				(_n == 2) ? (IOC4_SIO_IR_S2) : \
+				(IOC4_SIO_IR_S3)
+
+#define	GET_OTHER_IR(_n)  (_n == 0) ? (IOC4_OTHER_IR_S0_MEMERR) : \
+				(_n == 1) ? (IOC4_OTHER_IR_S1_MEMERR) : \
+				(_n == 2) ? (IOC4_OTHER_IR_S2_MEMERR) : \
+				(IOC4_OTHER_IR_S3_MEMERR)
+
+
+/*
+ * All IOC4 registers are 32 bits wide.
+ */
+
+/*
+ * PCI Memory Space Map
+ */
+#define IOC4_PCI_ERR_ADDR_L     0x000	/* Low Error Address */
+#define IOC4_PCI_ERR_ADDR_VLD	        (0x1 << 0)
+#define IOC4_PCI_ERR_ADDR_MST_ID_MSK    (0xf << 1)
+#define IOC4_PCI_ERR_ADDR_MST_NUM_MSK   (0xe << 1)
+#define IOC4_PCI_ERR_ADDR_MST_TYP_MSK   (0x1 << 1)
+#define IOC4_PCI_ERR_ADDR_MUL_ERR       (0x1 << 5)
+#define IOC4_PCI_ERR_ADDR_ADDR_MSK      (0x3ffffff << 6)
+
+/* Interrupt types */
+#define	IOC4_SIO_INTR_TYPE	0
+#define	IOC4_OTHER_INTR_TYPE	1
+#define	IOC4_NUM_INTR_TYPES	2
+
+/* Bitmasks for IOC4_SIO_IR, IOC4_SIO_IEC, and IOC4_SIO_IES  */
+#define IOC4_SIO_IR_S0_TX_MT	   0x00000001	/* Serial port 0 TX empty */
+#define IOC4_SIO_IR_S0_RX_FULL	   0x00000002	/* Port 0 RX buf full */
+#define IOC4_SIO_IR_S0_RX_HIGH	   0x00000004	/* Port 0 RX hiwat */
+#define IOC4_SIO_IR_S0_RX_TIMER	   0x00000008	/* Port 0 RX timeout */
+#define IOC4_SIO_IR_S0_DELTA_DCD   0x00000010	/* Port 0 delta DCD */
+#define IOC4_SIO_IR_S0_DELTA_CTS   0x00000020	/* Port 0 delta CTS */
+#define IOC4_SIO_IR_S0_INT	   0x00000040	/* Port 0 pass-thru intr */
+#define IOC4_SIO_IR_S0_TX_EXPLICIT 0x00000080	/* Port 0 explicit TX thru */
+#define IOC4_SIO_IR_S1_TX_MT	   0x00000100	/* Serial port 1 */
+#define IOC4_SIO_IR_S1_RX_FULL	   0x00000200	/* */
+#define IOC4_SIO_IR_S1_RX_HIGH	   0x00000400	/* */
+#define IOC4_SIO_IR_S1_RX_TIMER	   0x00000800	/* */
+#define IOC4_SIO_IR_S1_DELTA_DCD   0x00001000	/* */
+#define IOC4_SIO_IR_S1_DELTA_CTS   0x00002000	/* */
+#define IOC4_SIO_IR_S1_INT	   0x00004000	/* */
+#define IOC4_SIO_IR_S1_TX_EXPLICIT 0x00008000	/* */
+#define IOC4_SIO_IR_S2_TX_MT	   0x00010000	/* Serial port 2 */
+#define IOC4_SIO_IR_S2_RX_FULL	   0x00020000	/* */
+#define IOC4_SIO_IR_S2_RX_HIGH	   0x00040000	/* */
+#define IOC4_SIO_IR_S2_RX_TIMER	   0x00080000	/* */
+#define IOC4_SIO_IR_S2_DELTA_DCD   0x00100000	/* */
+#define IOC4_SIO_IR_S2_DELTA_CTS   0x00200000	/* */
+#define IOC4_SIO_IR_S2_INT	   0x00400000	/* */
+#define IOC4_SIO_IR_S2_TX_EXPLICIT 0x00800000	/* */
+#define IOC4_SIO_IR_S3_TX_MT	   0x01000000	/* Serial port 3 */
+#define IOC4_SIO_IR_S3_RX_FULL	   0x02000000	/* */
+#define IOC4_SIO_IR_S3_RX_HIGH	   0x04000000	/* */
+#define IOC4_SIO_IR_S3_RX_TIMER	   0x08000000	/* */
+#define IOC4_SIO_IR_S3_DELTA_DCD   0x10000000	/* */
+#define IOC4_SIO_IR_S3_DELTA_CTS   0x20000000	/* */
+#define IOC4_SIO_IR_S3_INT	   0x40000000	/* */
+#define IOC4_SIO_IR_S3_TX_EXPLICIT 0x80000000	/* */
+
+/* Per device interrupt masks */
+#define IOC4_SIO_IR_S0		(IOC4_SIO_IR_S0_TX_MT | \
+				 IOC4_SIO_IR_S0_RX_FULL | \
+				 IOC4_SIO_IR_S0_RX_HIGH | \
+				 IOC4_SIO_IR_S0_RX_TIMER | \
+				 IOC4_SIO_IR_S0_DELTA_DCD | \
+				 IOC4_SIO_IR_S0_DELTA_CTS | \
+				 IOC4_SIO_IR_S0_INT | \
+				 IOC4_SIO_IR_S0_TX_EXPLICIT)
+#define IOC4_SIO_IR_S1		(IOC4_SIO_IR_S1_TX_MT | \
+				 IOC4_SIO_IR_S1_RX_FULL | \
+				 IOC4_SIO_IR_S1_RX_HIGH | \
+				 IOC4_SIO_IR_S1_RX_TIMER | \
+				 IOC4_SIO_IR_S1_DELTA_DCD | \
+				 IOC4_SIO_IR_S1_DELTA_CTS | \
+				 IOC4_SIO_IR_S1_INT | \
+				 IOC4_SIO_IR_S1_TX_EXPLICIT)
+#define IOC4_SIO_IR_S2		(IOC4_SIO_IR_S2_TX_MT | \
+				 IOC4_SIO_IR_S2_RX_FULL | \
+				 IOC4_SIO_IR_S2_RX_HIGH | \
+				 IOC4_SIO_IR_S2_RX_TIMER | \
+				 IOC4_SIO_IR_S2_DELTA_DCD | \
+				 IOC4_SIO_IR_S2_DELTA_CTS | \
+				 IOC4_SIO_IR_S2_INT | \
+				 IOC4_SIO_IR_S2_TX_EXPLICIT)
+#define IOC4_SIO_IR_S3		(IOC4_SIO_IR_S3_TX_MT | \
+				 IOC4_SIO_IR_S3_RX_FULL | \
+				 IOC4_SIO_IR_S3_RX_HIGH | \
+				 IOC4_SIO_IR_S3_RX_TIMER | \
+				 IOC4_SIO_IR_S3_DELTA_DCD | \
+				 IOC4_SIO_IR_S3_DELTA_CTS | \
+				 IOC4_SIO_IR_S3_INT | \
+				 IOC4_SIO_IR_S3_TX_EXPLICIT)
+
+/* Bitmasks for IOC4_OTHER_IR, IOC4_OTHER_IEC, and IOC4_OTHER_IES  */
+#define IOC4_OTHER_IR_ATA_INT           0x00000001  /* ATAPI intr pass-thru */
+#define IOC4_OTHER_IR_ATA_MEMERR        0x00000002  /* ATAPI DMA PCI error */
+#define IOC4_OTHER_IR_S0_MEMERR         0x00000004  /* Port 0 PCI error */
+#define IOC4_OTHER_IR_S1_MEMERR         0x00000008  /* Port 1 PCI error */
+#define IOC4_OTHER_IR_S2_MEMERR         0x00000010  /* Port 2 PCI error */
+#define IOC4_OTHER_IR_S3_MEMERR         0x00000020  /* Port 3 PCI error */
+
+/* Bitmasks for IOC4_SIO_CR */
+#define IOC4_SIO_CR_CMD_PULSE_SHIFT              0  /* byte bus strobe shift */
+#define IOC4_SIO_CR_ARB_DIAG_TX0	0x00000000
+#define IOC4_SIO_CR_ARB_DIAG_RX0	0x00000010
+#define IOC4_SIO_CR_ARB_DIAG_TX1	0x00000020
+#define IOC4_SIO_CR_ARB_DIAG_RX1	0x00000030
+#define IOC4_SIO_CR_ARB_DIAG_TX2	0x00000040
+#define IOC4_SIO_CR_ARB_DIAG_RX2	0x00000050
+#define IOC4_SIO_CR_ARB_DIAG_TX3	0x00000060
+#define IOC4_SIO_CR_ARB_DIAG_RX3	0x00000070
+#define IOC4_SIO_CR_SIO_DIAG_IDLE	0x00000080  /* 0 -> active request among
+							   serial ports (ro) */
+/* Defs for some of the generic I/O pins */
+#define IOC4_GPCR_UART0_MODESEL	   0x10	/* Pin is output to port 0
+						   mode sel */
+#define IOC4_GPCR_UART1_MODESEL	   0x20	/* Pin is output to port 1
+						   mode sel */
+#define IOC4_GPCR_UART2_MODESEL	   0x40	/* Pin is output to port 2
+						   mode sel */
+#define IOC4_GPCR_UART3_MODESEL	   0x80	/* Pin is output to port 3
+						   mode sel */
+
+#define IOC4_GPPR_UART0_MODESEL_PIN   4	/* GIO pin controlling
+					   uart 0 mode select */
+#define IOC4_GPPR_UART1_MODESEL_PIN   5	/* GIO pin controlling
+					   uart 1 mode select */
+#define IOC4_GPPR_UART2_MODESEL_PIN   6	/* GIO pin controlling
+					   uart 2 mode select */
+#define IOC4_GPPR_UART3_MODESEL_PIN   7	/* GIO pin controlling
+					   uart 3 mode select */
+
+/* Bitmasks for serial RX status byte */
+#define IOC4_RXSB_OVERRUN       0x01	/* Char(s) lost */
+#define IOC4_RXSB_PAR_ERR	0x02	/* Parity error */
+#define IOC4_RXSB_FRAME_ERR	0x04	/* Framing error */
+#define IOC4_RXSB_BREAK	        0x08	/* Break character */
+#define IOC4_RXSB_CTS	        0x10	/* State of CTS */
+#define IOC4_RXSB_DCD	        0x20	/* State of DCD */
+#define IOC4_RXSB_MODEM_VALID   0x40	/* DCD, CTS, and OVERRUN are valid */
+#define IOC4_RXSB_DATA_VALID    0x80	/* Data byte, FRAME_ERR PAR_ERR
+					 * & BREAK valid */
+
+/* Bitmasks for serial TX control byte */
+#define IOC4_TXCB_INT_WHEN_DONE 0x20	/* Interrupt after this byte is sent */
+#define IOC4_TXCB_INVALID	0x00	/* Byte is invalid */
+#define IOC4_TXCB_VALID	        0x40	/* Byte is valid */
+#define IOC4_TXCB_MCR	        0x80	/* Data<7:0> to modem control reg */
+#define IOC4_TXCB_DELAY	        0xc0	/* Delay data<7:0> mSec */
+
+/* Bitmasks for IOC4_SBBR_L */
+#define IOC4_SBBR_L_SIZE	0x00000001  /* 0 == 1KB rings, 1 == 4KB rings */
+
+/* Bitmasks for IOC4_SSCR_<3:0> */
+#define IOC4_SSCR_RX_THRESHOLD  0x000001ff  /* Hiwater mark */
+#define IOC4_SSCR_TX_TIMER_BUSY 0x00010000  /* TX timer in progress */
+#define IOC4_SSCR_HFC_EN	0x00020000  /* Hardware flow control enabled */
+#define IOC4_SSCR_RX_RING_DCD   0x00040000  /* Post RX record on delta-DCD */
+#define IOC4_SSCR_RX_RING_CTS   0x00080000  /* Post RX record on delta-CTS */
+#define IOC4_SSCR_DIAG	        0x00200000  /* Bypass clock divider for sim */
+#define IOC4_SSCR_RX_DRAIN	0x08000000  /* Drain RX buffer to memory */
+#define IOC4_SSCR_DMA_EN	0x10000000  /* Enable ring buffer DMA */
+#define IOC4_SSCR_DMA_PAUSE	0x20000000  /* Pause DMA */
+#define IOC4_SSCR_PAUSE_STATE   0x40000000  /* Sets when PAUSE takes effect */
+#define IOC4_SSCR_RESET	        0x80000000  /* Reset DMA channels */
+
+/* All producer/comsumer pointers are the same bitfield */
+#define IOC4_PROD_CONS_PTR_4K   0x00000ff8	/* For 4K buffers */
+#define IOC4_PROD_CONS_PTR_1K   0x000003f8	/* For 1K buffers */
+#define IOC4_PROD_CONS_PTR_OFF           3
+
+/* Bitmasks for IOC4_SRCIR_<3:0> */
+#define IOC4_SRCIR_ARM	        0x80000000	/* Arm RX timer */
+
+/* Bitmasks for IOC4_SHADOW_<3:0> */
+#define IOC4_SHADOW_DR	 0x00000001	/* Data ready */
+#define IOC4_SHADOW_OE	 0x00000002	/* Overrun error */
+#define IOC4_SHADOW_PE	 0x00000004	/* Parity error */
+#define IOC4_SHADOW_FE	 0x00000008	/* Framing error */
+#define IOC4_SHADOW_BI	 0x00000010	/* Break interrupt */
+#define IOC4_SHADOW_THRE 0x00000020	/* Xmit holding register empty */
+#define IOC4_SHADOW_TEMT 0x00000040	/* Xmit shift register empty */
+#define IOC4_SHADOW_RFCE 0x00000080	/* Char in RX fifo has an error */
+#define IOC4_SHADOW_DCTS 0x00010000	/* Delta clear to send */
+#define IOC4_SHADOW_DDCD 0x00080000	/* Delta data carrier detect */
+#define IOC4_SHADOW_CTS	 0x00100000	/* Clear to send */
+#define IOC4_SHADOW_DCD	 0x00800000	/* Data carrier detect */
+#define IOC4_SHADOW_DTR	 0x01000000	/* Data terminal ready */
+#define IOC4_SHADOW_RTS	 0x02000000	/* Request to send */
+#define IOC4_SHADOW_OUT1 0x04000000	/* 16550 OUT1 bit */
+#define IOC4_SHADOW_OUT2 0x08000000	/* 16550 OUT2 bit */
+#define IOC4_SHADOW_LOOP 0x10000000	/* Loopback enabled */
+
+/* Bitmasks for IOC4_SRTR_<3:0> */
+#define IOC4_SRTR_CNT	        0x00000fff	/* Reload value for RX timer */
+#define IOC4_SRTR_CNT_VAL	0x0fff0000	/* Current value of RX timer */
+#define IOC4_SRTR_CNT_VAL_SHIFT         16
+#define IOC4_SRTR_HZ                 16000	/* SRTR clock frequency */
+
+/* Serial port register map used for DMA and PIO serial I/O */
+struct ioc4_serialregs {
+	uint32_t sscr;
+	uint32_t stpir;
+	uint32_t stcir;
+	uint32_t srpir;
+	uint32_t srcir;
+	uint32_t srtr;
+	uint32_t shadow;
+};
+
+/* IOC4 UART register map */
+struct ioc4_uartregs {
+	char i4u_lcr;
+	union {
+		char iir;	/* read only */
+		char fcr;	/* write only */
+	} u3;
+	union {
+		char ier;	/* DLAB == 0 */
+		char dlm;	/* DLAB == 1 */
+	} u2;
+	union {
+		char rbr;	/* read only, DLAB == 0 */
+		char thr;	/* write only, DLAB == 0 */
+		char dll;	/* DLAB == 1 */
+	} u1;
+	char i4u_scr;
+	char i4u_msr;
+	char i4u_lsr;
+	char i4u_mcr;
+};
+
+/* short names */
+#define i4u_dll u1.dll
+#define i4u_ier u2.ier
+#define i4u_dlm u2.dlm
+#define i4u_fcr u3.fcr
+
+/* PCI memory space register map addressed using pci_bar0 */
+struct ioc4_memregs {
+	struct ioc4_mem {
+		/* Miscellaneous IOC4  registers */
+		uint32_t pci_err_addr_l;
+		uint32_t pci_err_addr_h;
+		uint32_t sio_ir;
+		uint32_t other_ir;
+
+		/* These registers are read-only for general kernel code.  */
+		uint32_t sio_ies_ro;
+		uint32_t other_ies_ro;
+		uint32_t sio_iec_ro;
+		uint32_t other_iec_ro;
+		uint32_t sio_cr;
+		uint32_t misc_fill1;
+		uint32_t int_out;
+		uint32_t misc_fill2;
+		uint32_t gpcr_s;
+		uint32_t gpcr_c;
+		uint32_t gpdr;
+		uint32_t misc_fill3;
+		uint32_t gppr_0;
+		uint32_t gppr_1;
+		uint32_t gppr_2;
+		uint32_t gppr_3;
+		uint32_t gppr_4;
+		uint32_t gppr_5;
+		uint32_t gppr_6;
+		uint32_t gppr_7;
+	} ioc4_mem;
+
+	char misc_fill4[0x100 - 0x5C - 4];
+
+	/* ATA/ATAP registers */
+	uint32_t ata_notused[9];
+	char ata_fill1[0x140 - 0x120 - 4];
+	uint32_t ata_notused1[8];
+	char ata_fill2[0x200 - 0x15C - 4];
+
+	/* Keyboard and mouse registers */
+	uint32_t km_notused[5];;
+	char km_fill1[0x300 - 0x210 - 4];
+
+	/* Serial port registers used for DMA serial I/O */
+	struct ioc4_serial {
+		uint32_t sbbr01_l;
+		uint32_t sbbr01_h;
+		uint32_t sbbr23_l;
+		uint32_t sbbr23_h;
+
+		struct ioc4_serialregs port_0;
+		struct ioc4_serialregs port_1;
+		struct ioc4_serialregs port_2;
+		struct ioc4_serialregs port_3;
+		struct ioc4_uartregs uart_0;
+		struct ioc4_uartregs uart_1;
+		struct ioc4_uartregs uart_2;
+		struct ioc4_uartregs uart_3;
+	} ioc4_serial;
+};
+
+/* UART clock speed */
+#define IOC4_SER_XIN_CLK        IOC4_SER_XIN_CLK_66
+#define IOC4_SER_XIN_CLK_66     66666667
+#define IOC4_SER_XIN_CLK_33     33333333
+
+#define IOC4_W_IES		0
+#define IOC4_W_IEC		1
+
+typedef void ioc4_intr_func_f(void *, uint32_t);
+typedef ioc4_intr_func_f *ioc4_intr_func_t;
+
+/* defining this will get you LOTS of great debug info */
+//#define DEBUG_INTERRUPTS
+#define DPRINT_CONFIG(_x...)	;
+//#define DPRINT_CONFIG(_x...)	printk _x
+
+/* number of characters left in xmit buffer before we ask for more */
+#define WAKEUP_CHARS	256
+
+/* number of characters we want to transmit to the lower level at a time */
+#define IOC4_MAX_CHARS	128
+
+/* Device name we're using */
+#define DEVICE_NAME	"ttyIOC"
+#define DEVICE_MAJOR 204
+#define DEVICE_MINOR 50
+
+/* register offsets */
+#define IOC4_SERIAL_OFFSET	0x300
+
+/* flags for next_char_state */
+#define NCS_BREAK	0x1
+#define NCS_PARITY	0x2
+#define NCS_FRAMING	0x4
+#define NCS_OVERRUN	0x8
+
+/* cause we need SOME parameters ... */
+#define MIN_BAUD_SUPPORTED	1200
+#define MAX_BAUD_SUPPORTED	115200
+
+/* protocol types supported */
+enum sio_proto {
+	PROTO_RS232,
+	PROTO_RS422
+};
+
+/* Notification types */
+#define N_DATA_READY	0x01
+#define N_OUTPUT_LOWAT	0x02
+#define N_BREAK		0x04
+#define N_PARITY_ERROR	0x08
+#define N_FRAMING_ERROR	0x10
+#define N_OVERRUN_ERROR	0x20
+#define N_DDCD		0x40
+#define N_DCTS		0x80
+
+#define N_ALL_INPUT	(N_DATA_READY | N_BREAK |			\
+			 N_PARITY_ERROR | N_FRAMING_ERROR |		\
+			 N_OVERRUN_ERROR | N_DDCD | N_DCTS)
+
+#define N_ALL_OUTPUT	N_OUTPUT_LOWAT
+
+#define N_ALL_ERRORS	(N_PARITY_ERROR | N_FRAMING_ERROR | N_OVERRUN_ERROR)
+
+#define N_ALL		(N_DATA_READY | N_OUTPUT_LOWAT | N_BREAK |	\
+			 N_PARITY_ERROR | N_FRAMING_ERROR |		\
+			 N_OVERRUN_ERROR | N_DDCD | N_DCTS)
+
+#define SER_DIVISOR(_x, clk)		(((clk) + (_x) * 8) / ((_x) * 16))
+#define DIVISOR_TO_BAUD(div, clk)	((clk) / 16 / (div))
+
+/* Some masks */
+#define LCR_MASK_BITS_CHAR	(UART_LCR_WLEN5 | UART_LCR_WLEN6 \
+					| UART_LCR_WLEN7 | UART_LCR_WLEN8)
+#define LCR_MASK_STOP_BITS	(UART_LCR_STOP)
+
+#define PENDING(_p)	(readl(&(_p)->ip_mem->sio_ir) & _p->ip_ienb)
+#define READ_SIO_IR(_p) readl(&(_p)->ip_mem->sio_ir)
+
+/* Default to 4k buffers */
+#ifdef IOC4_1K_BUFFERS
+#define RING_BUF_SIZE 1024
+#define IOC4_BUF_SIZE_BIT 0
+#define PROD_CONS_MASK IOC4_PROD_CONS_PTR_1K
+#else
+#define RING_BUF_SIZE 4096
+#define IOC4_BUF_SIZE_BIT IOC4_SBBR_L_SIZE
+#define PROD_CONS_MASK IOC4_PROD_CONS_PTR_4K
+#endif
+
+#define TOTAL_RING_BUF_SIZE (RING_BUF_SIZE * 4)
+
+/*
+ * This is the entry saved by the driver - one per card
+ */
+struct ioc4_control {
+	int ic_irq;
+	struct {
+		/* uart ports are allocated here */
+		struct uart_port icp_uart_port;
+		/* Handy reference material */
+		struct ioc4_port *icp_port;
+	} ic_port[IOC4_NUM_SERIAL_PORTS];
+	struct ioc4_soft *ic_soft;
+};
+
+/*
+ * per-IOC4 data structure
+ */
+#define MAX_IOC4_INTR_ENTS	(8 * sizeof(uint32_t))
+struct ioc4_soft {
+	struct ioc4_mem __iomem *is_ioc4_mem_addr;
+	struct ioc4_serial __iomem *is_ioc4_serial_addr;
+
+	/* Each interrupt type has an entry in the array */
+	struct ioc4_intr_type {
+
+		/*
+		 * Each in-use entry in this array contains at least
+		 * one nonzero bit in sd_bits; no two entries in this
+		 * array have overlapping sd_bits values.
+		 */
+		struct ioc4_intr_info {
+			uint32_t sd_bits;
+			ioc4_intr_func_f *sd_intr;
+			void *sd_info;
+		} is_intr_info[MAX_IOC4_INTR_ENTS];
+
+		/* Number of entries active in the above array */
+		atomic_t is_num_intrs;
+	} is_intr_type[IOC4_NUM_INTR_TYPES];
+
+	/* is_ir_lock must be held while
+	 * modifying sio_ie values, so
+	 * we can be sure that sio_ie is
+	 * not changing when we read it
+	 * along with sio_ir.
+	 */
+	spinlock_t is_ir_lock;	/* SIO_IE[SC] mod lock */
+};
+
+/* Local port info for each IOC4 serial ports */
+struct ioc4_port {
+	struct uart_port *ip_port;
+	/* Back ptrs for this port */
+	struct ioc4_control *ip_control;
+	struct pci_dev *ip_pdev;
+	struct ioc4_soft *ip_ioc4_soft;
+
+	/* pci mem addresses */
+	struct ioc4_mem __iomem *ip_mem;
+	struct ioc4_serial __iomem *ip_serial;
+	struct ioc4_serialregs __iomem *ip_serial_regs;
+	struct ioc4_uartregs __iomem *ip_uart_regs;
+
+	/* Ring buffer page for this port */
+	dma_addr_t ip_dma_ringbuf;
+	/* vaddr of ring buffer */
+	struct ring_buffer *ip_cpu_ringbuf;
+
+	/* Rings for this port */
+	struct ring *ip_inring;
+	struct ring *ip_outring;
+
+	/* Hook to port specific values */
+	struct hooks *ip_hooks;
+
+	spinlock_t ip_lock;
+
+	/* Various rx/tx parameters */
+	int ip_baud;
+	int ip_tx_lowat;
+	int ip_rx_timeout;
+
+	/* Copy of notification bits */
+	int ip_notify;
+
+	/* Shadow copies of various registers so we don't need to PIO
+	 * read them constantly
+	 */
+	uint32_t ip_ienb;	/* Enabled interrupts */
+	uint32_t ip_sscr;
+	uint32_t ip_tx_prod;
+	uint32_t ip_rx_cons;
+	int ip_pci_bus_speed;
+	unsigned char ip_flags;
+};
+
+/* tx low water mark.  We need to notify the driver whenever tx is getting
+ * close to empty so it can refill the tx buffer and keep things going.
+ * Let's assume that if we interrupt 1 ms before the tx goes idle, we'll
+ * have no trouble getting in more chars in time (I certainly hope so).
+ */
+#define TX_LOWAT_LATENCY      1000
+#define TX_LOWAT_HZ          (1000000 / TX_LOWAT_LATENCY)
+#define TX_LOWAT_CHARS(baud) (baud / 10 / TX_LOWAT_HZ)
+
+/* Flags per port */
+#define INPUT_HIGH	0x01
+#define DCD_ON		0x02
+#define LOWAT_WRITTEN	0x04
+#define READ_ABORTED	0x08
+
+/* Since each port has different register offsets and bitmasks
+ * for everything, we'll store those that we need in tables so we
+ * don't have to be constantly checking the port we are dealing with.
+ */
+struct hooks {
+	uint32_t intr_delta_dcd;
+	uint32_t intr_delta_cts;
+	uint32_t intr_tx_mt;
+	uint32_t intr_rx_timer;
+	uint32_t intr_rx_high;
+	uint32_t intr_tx_explicit;
+	uint32_t intr_dma_error;
+	uint32_t intr_clear;
+	uint32_t intr_all;
+	char rs422_select_pin;
+};
+
+static struct hooks hooks_array[IOC4_NUM_SERIAL_PORTS] = {
+	/* Values for port 0 */
+	{
+	 IOC4_SIO_IR_S0_DELTA_DCD, IOC4_SIO_IR_S0_DELTA_CTS,
+	 IOC4_SIO_IR_S0_TX_MT, IOC4_SIO_IR_S0_RX_TIMER,
+	 IOC4_SIO_IR_S0_RX_HIGH, IOC4_SIO_IR_S0_TX_EXPLICIT,
+	 IOC4_OTHER_IR_S0_MEMERR,
+	 (IOC4_SIO_IR_S0_TX_MT | IOC4_SIO_IR_S0_RX_FULL |
+	  IOC4_SIO_IR_S0_RX_HIGH | IOC4_SIO_IR_S0_RX_TIMER |
+	  IOC4_SIO_IR_S0_DELTA_DCD | IOC4_SIO_IR_S0_DELTA_CTS |
+	  IOC4_SIO_IR_S0_INT | IOC4_SIO_IR_S0_TX_EXPLICIT),
+	 IOC4_SIO_IR_S0, IOC4_GPPR_UART0_MODESEL_PIN,
+	 },
+
+	/* Values for port 1 */
+	{
+	 IOC4_SIO_IR_S1_DELTA_DCD, IOC4_SIO_IR_S1_DELTA_CTS,
+	 IOC4_SIO_IR_S1_TX_MT, IOC4_SIO_IR_S1_RX_TIMER,
+	 IOC4_SIO_IR_S1_RX_HIGH, IOC4_SIO_IR_S1_TX_EXPLICIT,
+	 IOC4_OTHER_IR_S1_MEMERR,
+	 (IOC4_SIO_IR_S1_TX_MT | IOC4_SIO_IR_S1_RX_FULL |
+	  IOC4_SIO_IR_S1_RX_HIGH | IOC4_SIO_IR_S1_RX_TIMER |
+	  IOC4_SIO_IR_S1_DELTA_DCD | IOC4_SIO_IR_S1_DELTA_CTS |
+	  IOC4_SIO_IR_S1_INT | IOC4_SIO_IR_S1_TX_EXPLICIT),
+	 IOC4_SIO_IR_S1, IOC4_GPPR_UART1_MODESEL_PIN,
+	 },
+
+	/* Values for port 2 */
+	{
+	 IOC4_SIO_IR_S2_DELTA_DCD, IOC4_SIO_IR_S2_DELTA_CTS,
+	 IOC4_SIO_IR_S2_TX_MT, IOC4_SIO_IR_S2_RX_TIMER,
+	 IOC4_SIO_IR_S2_RX_HIGH, IOC4_SIO_IR_S2_TX_EXPLICIT,
+	 IOC4_OTHER_IR_S2_MEMERR,
+	 (IOC4_SIO_IR_S2_TX_MT | IOC4_SIO_IR_S2_RX_FULL |
+	  IOC4_SIO_IR_S2_RX_HIGH | IOC4_SIO_IR_S2_RX_TIMER |
+	  IOC4_SIO_IR_S2_DELTA_DCD | IOC4_SIO_IR_S2_DELTA_CTS |
+	  IOC4_SIO_IR_S2_INT | IOC4_SIO_IR_S2_TX_EXPLICIT),
+	 IOC4_SIO_IR_S2, IOC4_GPPR_UART2_MODESEL_PIN,
+	 },
+
+	/* Values for port 3 */
+	{
+	 IOC4_SIO_IR_S3_DELTA_DCD, IOC4_SIO_IR_S3_DELTA_CTS,
+	 IOC4_SIO_IR_S3_TX_MT, IOC4_SIO_IR_S3_RX_TIMER,
+	 IOC4_SIO_IR_S3_RX_HIGH, IOC4_SIO_IR_S3_TX_EXPLICIT,
+	 IOC4_OTHER_IR_S3_MEMERR,
+	 (IOC4_SIO_IR_S3_TX_MT | IOC4_SIO_IR_S3_RX_FULL |
+	  IOC4_SIO_IR_S3_RX_HIGH | IOC4_SIO_IR_S3_RX_TIMER |
+	  IOC4_SIO_IR_S3_DELTA_DCD | IOC4_SIO_IR_S3_DELTA_CTS |
+	  IOC4_SIO_IR_S3_INT | IOC4_SIO_IR_S3_TX_EXPLICIT),
+	 IOC4_SIO_IR_S3, IOC4_GPPR_UART3_MODESEL_PIN,
+	 }
+};
+
+/* A ring buffer entry */
+struct ring_entry {
+	union {
+		struct {
+			uint32_t alldata;
+			uint32_t allsc;
+		} all;
+		struct {
+			char data[4];	/* data bytes */
+			char sc[4];	/* status/control */
+		} s;
+	} u;
+};
+
+/* Test the valid bits in any of the 4 sc chars using "allsc" member */
+#define RING_ANY_VALID \
+	((uint32_t)(IOC4_RXSB_MODEM_VALID | IOC4_RXSB_DATA_VALID) * 0x01010101)
+
+#define ring_sc     u.s.sc
+#define ring_data   u.s.data
+#define ring_allsc  u.all.allsc
+
+/* Number of entries per ring buffer. */
+#define ENTRIES_PER_RING (RING_BUF_SIZE / (int) sizeof(struct ring_entry))
+
+/* An individual ring */
+struct ring {
+	struct ring_entry entries[ENTRIES_PER_RING];
+};
+
+/* The whole enchilada */
+struct ring_buffer {
+	struct ring TX_0_OR_2;
+	struct ring RX_0_OR_2;
+	struct ring TX_1_OR_3;
+	struct ring RX_1_OR_3;
+};
+
+/* Get a ring from a port struct */
+#define RING(_p, _wh)	&(((struct ring_buffer *)((_p)->ip_cpu_ringbuf))->_wh)
+
+/* Infinite loop detection.
+ */
+#define MAXITER 10000000
+
+/* Prototypes */
+static void receive_chars(struct uart_port *);
+static void handle_intr(void *arg, uint32_t sio_ir);
+
+/**
+ * write_ireg - write the interrupt regs
+ * @ioc4_soft: ptr to soft struct for this port
+ * @val: value to write
+ * @which: which register
+ * @type: which ireg set
+ */
+static inline void
+write_ireg(struct ioc4_soft *ioc4_soft, uint32_t val, int which, int type)
+{
+	struct ioc4_mem __iomem *mem = ioc4_soft->is_ioc4_mem_addr;
+	unsigned long flags;
+
+	spin_lock_irqsave(&ioc4_soft->is_ir_lock, flags);
+
+	switch (type) {
+	case IOC4_SIO_INTR_TYPE:
+		switch (which) {
+		case IOC4_W_IES:
+			writel(val, &mem->sio_ies_ro);
+			break;
+
+		case IOC4_W_IEC:
+			writel(val, &mem->sio_iec_ro);
+			break;
+		}
+		break;
+
+	case IOC4_OTHER_INTR_TYPE:
+		switch (which) {
+		case IOC4_W_IES:
+			writel(val, &mem->other_ies_ro);
+			break;
+
+		case IOC4_W_IEC:
+			writel(val, &mem->other_iec_ro);
+			break;
+		}
+		break;
+
+	default:
+		break;
+	}
+	spin_unlock_irqrestore(&ioc4_soft->is_ir_lock, flags);
+}
+
+/**
+ * set_baud - Baud rate setting code
+ * @port: port to set
+ * @baud: baud rate to use
+ */
+static int set_baud(struct ioc4_port *port, int baud)
+{
+	int actual_baud;
+	int diff;
+	int lcr;
+	unsigned short divisor;
+	struct ioc4_uartregs __iomem *uart;
+
+	divisor = SER_DIVISOR(baud, port->ip_pci_bus_speed);
+	if (!divisor)
+		return 1;
+	actual_baud = DIVISOR_TO_BAUD(divisor, port->ip_pci_bus_speed);
+
+	diff = actual_baud - baud;
+	if (diff < 0)
+		diff = -diff;
+
+	/* If we're within 1%, we've found a match */
+	if (diff * 100 > actual_baud)
+		return 1;
+
+	uart = port->ip_uart_regs;
+	lcr = readb(&uart->i4u_lcr);
+	writeb(lcr | UART_LCR_DLAB, &uart->i4u_lcr);
+	writeb((unsigned char)divisor, &uart->i4u_dll);
+	writeb((unsigned char)(divisor >> 8), &uart->i4u_dlm);
+	writeb(lcr, &uart->i4u_lcr);
+	return 0;
+}
+
+
+/**
+ * get_ioc4_port - given a uart port, return the control structure
+ * @port: uart port
+ */
+static struct ioc4_port *get_ioc4_port(struct uart_port *the_port)
+{
+	struct ioc4_control *control = dev_get_drvdata(the_port->dev);
+	int ii;
+
+	if (control) {
+		for ( ii = 0; ii < IOC4_NUM_SERIAL_PORTS; ii++ ) {
+			if (!control->ic_port[ii].icp_port)
+				continue;
+			if (the_port == control->ic_port[ii].icp_port->ip_port)
+				return control->ic_port[ii].icp_port;
+		}
+	}
+	return NULL;
+}
+
+/* The IOC4 hardware provides no atomic way to determine if interrupts
+ * are pending since two reads are required to do so.  The handler must
+ * read the SIO_IR and the SIO_IES, and take the logical and of the
+ * two.  When this value is zero, all interrupts have been serviced and
+ * the handler may return.
+ *
+ * This has the unfortunate "hole" that, if some other CPU or
+ * some other thread or some higher level interrupt manages to
+ * modify SIO_IE between our reads of SIO_IR and SIO_IE, we may
+ * think we have observed SIO_IR&SIO_IE==0 when in fact this
+ * condition never really occurred.
+ *
+ * To solve this, we use a simple spinlock that must be held
+ * whenever modifying SIO_IE; holding this lock while observing
+ * both SIO_IR and SIO_IE guarantees that we do not falsely
+ * conclude that no enabled interrupts are pending.
+ */
+
+static inline uint32_t
+pending_intrs(struct ioc4_soft *soft, int type)
+{
+	struct ioc4_mem __iomem *mem = soft->is_ioc4_mem_addr;
+	unsigned long flag;
+	uint32_t intrs = 0;
+
+	BUG_ON(!((type == IOC4_SIO_INTR_TYPE)
+	       || (type == IOC4_OTHER_INTR_TYPE)));
+
+	spin_lock_irqsave(&soft->is_ir_lock, flag);
+
+	switch (type) {
+	case IOC4_SIO_INTR_TYPE:
+		intrs = readl(&mem->sio_ir) & readl(&mem->sio_ies_ro);
+		break;
+
+	case IOC4_OTHER_INTR_TYPE:
+		intrs = readl(&mem->other_ir) & readl(&mem->other_ies_ro);
+
+		/* Don't process any ATA interrupte */
+		intrs &= ~(IOC4_OTHER_IR_ATA_INT | IOC4_OTHER_IR_ATA_MEMERR);
+		break;
+
+	default:
+		break;
+	}
+	spin_unlock_irqrestore(&soft->is_ir_lock, flag);
+	return intrs;
+}
+
+/**
+ * port_init - Initialize the sio and ioc4 hardware for a given port
+ *			called per port from attach...
+ * @port: port to initialize
+ */
+static int inline port_init(struct ioc4_port *port)
+{
+	uint32_t sio_cr;
+	struct hooks *hooks = port->ip_hooks;
+	struct ioc4_uartregs __iomem *uart;
+
+	/* Idle the IOC4 serial interface */
+	writel(IOC4_SSCR_RESET, &port->ip_serial_regs->sscr);
+
+	/* Wait until any pending bus activity for this port has ceased */
+	do
+		sio_cr = readl(&port->ip_mem->sio_cr);
+	while (!(sio_cr & IOC4_SIO_CR_SIO_DIAG_IDLE));
+
+	/* Finish reset sequence */
+	writel(0, &port->ip_serial_regs->sscr);
+
+	/* Once RESET is done, reload cached tx_prod and rx_cons values
+	 * and set rings to empty by making prod == cons
+	 */
+	port->ip_tx_prod = readl(&port->ip_serial_regs->stcir) & PROD_CONS_MASK;
+	writel(port->ip_tx_prod, &port->ip_serial_regs->stpir);
+	port->ip_rx_cons = readl(&port->ip_serial_regs->srpir) & PROD_CONS_MASK;
+	writel(port->ip_rx_cons, &port->ip_serial_regs->srcir);
+
+	/* Disable interrupts for this 16550 */
+	uart = port->ip_uart_regs;
+	writeb(0, &uart->i4u_lcr);
+	writeb(0, &uart->i4u_ier);
+
+	/* Set the default baud */
+	set_baud(port, port->ip_baud);
+
+	/* Set line control to 8 bits no parity */
+	writeb(UART_LCR_WLEN8 | 0, &uart->i4u_lcr);
+					/* UART_LCR_STOP == 1 stop */
+
+	/* Enable the FIFOs */
+	writeb(UART_FCR_ENABLE_FIFO, &uart->i4u_fcr);
+	/* then reset 16550 FIFOs */
+	writeb(UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT,
+			&uart->i4u_fcr);
+
+	/* Clear modem control register */
+	writeb(0, &uart->i4u_mcr);
+
+	/* Clear deltas in modem status register */
+	readb(&uart->i4u_msr);
+
+	/* Only do this once per port pair */
+	if (port->ip_hooks == &hooks_array[0]
+			    || port->ip_hooks == &hooks_array[2]) {
+		unsigned long ring_pci_addr;
+		uint32_t __iomem *sbbr_l;
+		uint32_t __iomem *sbbr_h;
+
+		if (port->ip_hooks == &hooks_array[0]) {
+			sbbr_l = &port->ip_serial->sbbr01_l;
+			sbbr_h = &port->ip_serial->sbbr01_h;
+		} else {
+			sbbr_l = &port->ip_serial->sbbr23_l;
+			sbbr_h = &port->ip_serial->sbbr23_h;
+		}
+
+		ring_pci_addr = (unsigned long __iomem)port->ip_dma_ringbuf;
+		DPRINT_CONFIG(("%s: ring_pci_addr 0x%lx\n",
+					__FUNCTION__, ring_pci_addr));
+
+		writel((unsigned int)((uint64_t)ring_pci_addr >> 32), sbbr_h);
+		writel((unsigned int)ring_pci_addr | IOC4_BUF_SIZE_BIT, sbbr_l);
+	}
+
+	/* Set the receive timeout value to 10 msec */
+	writel(IOC4_SRTR_HZ / 100, &port->ip_serial_regs->srtr);
+
+	/* Set rx threshold, enable DMA */
+	/* Set high water mark at 3/4 of full ring */
+	port->ip_sscr = (ENTRIES_PER_RING * 3 / 4);
+	writel(port->ip_sscr, &port->ip_serial_regs->sscr);
+
+	/* Disable and clear all serial related interrupt bits */
+	write_ireg(port->ip_ioc4_soft, hooks->intr_clear,
+		       IOC4_W_IEC, IOC4_SIO_INTR_TYPE);
+	port->ip_ienb &= ~hooks->intr_clear;
+	writel(hooks->intr_clear, &port->ip_mem->sio_ir);
+	return 0;
+}
+
+/**
+ * handle_dma_error_intr - service any pending DMA error interrupts for the
+ *			given port - 2nd level called via sd_intr
+ * @arg: handler arg
+ * @other_ir: ioc4regs
+ */
+static void handle_dma_error_intr(void *arg, uint32_t other_ir)
+{
+	struct ioc4_port *port = (struct ioc4_port *)arg;
+	struct hooks *hooks = port->ip_hooks;
+	unsigned int flags;
+
+	spin_lock_irqsave(&port->ip_lock, flags);
+
+	/* ACK the interrupt */
+	writel(hooks->intr_dma_error, &port->ip_mem->other_ir);
+
+	if (readl(&port->ip_mem->pci_err_addr_l) & IOC4_PCI_ERR_ADDR_VLD) {
+		printk(KERN_ERR
+			"PCI error address is 0x%lx, "
+				"master is serial port %c %s\n",
+		     (((uint64_t)readl(&port->ip_mem->pci_err_addr_h)
+							 << 32)
+				| readl(&port->ip_mem->pci_err_addr_l))
+					& IOC4_PCI_ERR_ADDR_ADDR_MSK, '1' +
+		     ((char)(readl(&port->ip_mem-> pci_err_addr_l) &
+			     IOC4_PCI_ERR_ADDR_MST_NUM_MSK) >> 1),
+		     (readl(&port->ip_mem->pci_err_addr_l)
+				& IOC4_PCI_ERR_ADDR_MST_TYP_MSK)
+				? "RX" : "TX");
+
+		if (readl(&port->ip_mem->pci_err_addr_l)
+						& IOC4_PCI_ERR_ADDR_MUL_ERR) {
+			printk(KERN_ERR
+				"Multiple errors occurred\n");
+		}
+	}
+	spin_unlock_irqrestore(&port->ip_lock, flags);
+
+	/* Re-enable DMA error interrupts */
+	write_ireg(port->ip_ioc4_soft, hooks->intr_dma_error, IOC4_W_IES,
+						IOC4_OTHER_INTR_TYPE);
+}
+
+/**
+ * intr_connect - interrupt connect function
+ * @soft: soft struct for this card
+ * @type: interrupt type
+ * @intrbits: bit pattern to set
+ * @intr: handler function
+ * @info: handler arg
+ */
+static void
+intr_connect(struct ioc4_soft *soft, int type,
+		  uint32_t intrbits, ioc4_intr_func_f * intr, void *info)
+{
+	int i;
+	struct ioc4_intr_info *intr_ptr;
+
+	BUG_ON(!((type == IOC4_SIO_INTR_TYPE)
+	       || (type == IOC4_OTHER_INTR_TYPE)));
+
+	i = atomic_inc(&soft-> is_intr_type[type].is_num_intrs) - 1;
+	BUG_ON(!(i < MAX_IOC4_INTR_ENTS || (printk("i %d\n", i), 0)));
+
+	/* Save off the lower level interrupt handler */
+	intr_ptr = &soft->is_intr_type[type].is_intr_info[i];
+	intr_ptr->sd_bits = intrbits;
+	intr_ptr->sd_intr = intr;
+	intr_ptr->sd_info = info;
+}
+
+/**
+ * ioc4_intr - Top level IOC4 interrupt handler.
+ * @irq: irq value
+ * @arg: handler arg
+ * @regs: registers
+ */
+static irqreturn_t ioc4_intr(int irq, void *arg, struct pt_regs *regs)
+{
+	struct ioc4_soft *soft;
+	uint32_t this_ir, this_mir;
+	int xx, num_intrs = 0;
+	int intr_type;
+	int handled = 0;
+	struct ioc4_intr_info *ii;
+
+	soft = arg;
+	for (intr_type = 0; intr_type < IOC4_NUM_INTR_TYPES; intr_type++) {
+		num_intrs = (int)atomic_read(
+				&soft->is_intr_type[intr_type].is_num_intrs);
+
+		this_mir = this_ir = pending_intrs(soft, intr_type);
+
+		/* Farm out the interrupt to the various drivers depending on
+		 * which interrupt bits are set.
+		 */
+		for (xx = 0; xx < num_intrs; xx++) {
+			ii = &soft->is_intr_type[intr_type].is_intr_info[xx];
+			if ((this_mir = this_ir & ii->sd_bits)) {
+				/* Disable owned interrupts, call handler */
+				handled++;
+				write_ireg(soft, ii->sd_bits, IOC4_W_IEC,
+								intr_type);
+				ii->sd_intr(ii->sd_info, this_mir);
+				this_ir &= ~this_mir;
+			}
+		}
+		if (this_ir) {
+			printk(KERN_ERR
+			       "unknown IOC4 %s interrupt 0x%x, sio_ir = 0x%x,"
+				" sio_ies = 0x%x, other_ir = 0x%x :"
+				"other_ies = 0x%x\n",
+			       (intr_type == IOC4_SIO_INTR_TYPE) ? "sio" :
+			       "other", this_ir,
+			       readl(&soft->is_ioc4_mem_addr->sio_ir),
+			       readl(&soft->is_ioc4_mem_addr->sio_ies_ro),
+			       readl(&soft->is_ioc4_mem_addr->other_ir),
+			       readl(&soft->is_ioc4_mem_addr->other_ies_ro));
+		}
+	}
+#ifdef DEBUG_INTERRUPTS
+	{
+		struct ioc4_mem __iomem *mem = soft->is_ioc4_mem_addr;
+		spinlock_t *lp = &soft->is_ir_lock;
+		unsigned long flag;
+
+		spin_lock_irqsave(&soft->is_ir_lock, flag);
+		printk ("%s : %d : mem 0x%p sio_ir 0x%x sio_ies_ro 0x%x "
+				"other_ir 0x%x other_ies_ro 0x%x mask 0x%x\n",
+		     __FUNCTION__, __LINE__,
+		     (void *)mem, readl(&mem->sio_ir),
+		     readl(&mem->sio_ies_ro),
+		     readl(&mem->other_ir),
+		     readl(&mem->other_ies_ro),
+		     IOC4_OTHER_IR_ATA_INT | IOC4_OTHER_IR_ATA_MEMERR);
+		spin_unlock_irqrestore(&soft->is_ir_lock, flag);
+	}
+#endif
+	return handled ? IRQ_HANDLED : IRQ_NONE;
+}
+
+/**
+ * ioc4_attach_local - Device initialization.
+ *			Called at *_attach() time for each
+ *			IOC4 with serial ports in the system.
+ * @control: ioc4_control ptr
+ * @pdev: PCI handle for this device
+ * @soft: soft struct for this device
+ * @ioc4: ioc4 mem space
+ */
+static int inline ioc4_attach_local(struct pci_dev *pdev,
+			struct ioc4_control *control,
+			struct ioc4_soft *soft, void __iomem *ioc4_mem,
+			void __iomem *ioc4_serial)
+{
+	struct ioc4_port *port;
+	struct ioc4_port *ports[IOC4_NUM_SERIAL_PORTS];
+	int port_number;
+	uint16_t ioc4_revid_min = 62;
+	uint16_t ioc4_revid;
+
+	/* IOC4 firmware must be at least rev 62 */
+	pci_read_config_word(pdev, PCI_COMMAND_SPECIAL, &ioc4_revid);
+
+	printk(KERN_INFO "IOC4 firmware revision %d\n", ioc4_revid);
+	if (ioc4_revid < ioc4_revid_min) {
+		printk(KERN_WARNING
+		    "IOC4 serial not supported on firmware rev %d, "
+				"please upgrade to rev %d or higher\n",
+				ioc4_revid, ioc4_revid_min);
+		return -EPERM;
+	}
+	BUG_ON(ioc4_mem == NULL);
+	BUG_ON(ioc4_serial == NULL);
+
+	/* Create port structures for each port */
+	for (port_number = 0; port_number < IOC4_NUM_SERIAL_PORTS;
+							port_number++) {
+		port = kmalloc(sizeof(struct ioc4_port), GFP_KERNEL);
+		if (!port) {
+			printk(KERN_WARNING
+				"IOC4 serial memory not available for port\n");
+			return -ENOMEM;
+		}
+		memset(port, 0, sizeof(struct ioc4_port));
+
+		/* we need to remember the previous ones, to point back to
+		 * them farther down - setting up the ring buffers.
+		 */
+		ports[port_number] = port;
+
+		/* Allocate buffers and jumpstart the hardware.  */
+		control->ic_port[port_number].icp_port = port;
+		port->ip_ioc4_soft = soft;
+		port->ip_pdev = pdev;
+		port->ip_ienb = 0;
+		port->ip_pci_bus_speed = IOC4_SER_XIN_CLK;
+		port->ip_baud = 9600;
+		port->ip_control = control;
+		port->ip_mem = ioc4_mem;
+		port->ip_serial = ioc4_serial;
+
+		/* point to the right hook */
+		port->ip_hooks = &hooks_array[port_number];
+
+		/* Get direct hooks to the serial regs and uart regs
+		 * for this port
+		 */
+		switch (port_number) {
+		case 0:
+			port->ip_serial_regs = &(port->ip_serial->port_0);
+			port->ip_uart_regs = &(port->ip_serial->uart_0);
+			break;
+		case 1:
+			port->ip_serial_regs = &(port->ip_serial->port_1);
+			port->ip_uart_regs = &(port->ip_serial->uart_1);
+			break;
+		case 2:
+			port->ip_serial_regs = &(port->ip_serial->port_2);
+			port->ip_uart_regs = &(port->ip_serial->uart_2);
+			break;
+		default:
+		case 3:
+			port->ip_serial_regs = &(port->ip_serial->port_3);
+			port->ip_uart_regs = &(port->ip_serial->uart_3);
+			break;
+		}
+
+		/* ring buffers are 1 to a pair of ports */
+		if (port_number && (port_number & 1)) {
+			/* odd use the evens buffer */
+			port->ip_dma_ringbuf =
+					ports[port_number - 1]->ip_dma_ringbuf;
+			port->ip_cpu_ringbuf =
+					ports[port_number - 1]->ip_cpu_ringbuf;
+			port->ip_inring = RING(port, RX_1_OR_3);
+			port->ip_outring = RING(port, TX_1_OR_3);
+
+		} else {
+			if (port->ip_dma_ringbuf == 0) {
+				port->ip_cpu_ringbuf = pci_alloc_consistent
+					(pdev, TOTAL_RING_BUF_SIZE,
+					&port->ip_dma_ringbuf);
+
+			}
+			BUG_ON(!((((int64_t)port->ip_dma_ringbuf) &
+				(TOTAL_RING_BUF_SIZE - 1)) == 0));
+			DPRINT_CONFIG(("%s : ip_cpu_ringbuf 0x%p "
+						"ip_dma_ringbuf 0x%p\n",
+					__FUNCTION__,
+					(void *)port->ip_cpu_ringbuf,
+					(void *)port->ip_dma_ringbuf));
+			port->ip_inring = RING(port, RX_0_OR_2);
+			port->ip_outring = RING(port, TX_0_OR_2);
+		}
+		DPRINT_CONFIG(("%s : port %d [addr 0x%p] control 0x%p",
+				__FUNCTION__,
+				port_number, (void *)port, (void *)control));
+		DPRINT_CONFIG((" ip_serial_regs 0x%p ip_uart_regs 0x%p\n",
+				(void *)port->ip_serial_regs,
+				(void *)port->ip_uart_regs));
+
+		/* Initialize the hardware for IOC4 */
+		port_init(port);
+
+		DPRINT_CONFIG(("%s: port_number %d port 0x%p inring 0x%p "
+						"outring 0x%p\n",
+				__FUNCTION__,
+				port_number, (void *)port,
+				(void *)port->ip_inring,
+				(void *)port->ip_outring));
+
+		/* Attach interrupt handlers */
+		intr_connect(soft, IOC4_SIO_INTR_TYPE,
+				GET_SIO_IR(port_number),
+				handle_intr, port);
+
+		intr_connect(soft, IOC4_OTHER_INTR_TYPE,
+				GET_OTHER_IR(port_number),
+				handle_dma_error_intr, port);
+	}
+	return 0;
+}
+
+/**
+ * enable_intrs - enable interrupts
+ * @port: port to enable
+ * @mask: mask to use
+ */
+static void enable_intrs(struct ioc4_port *port, uint32_t mask)
+{
+	struct hooks *hooks = port->ip_hooks;
+
+	if ((port->ip_ienb & mask) != mask) {
+		write_ireg(port->ip_ioc4_soft, mask, IOC4_W_IES,
+						IOC4_SIO_INTR_TYPE);
+		port->ip_ienb |= mask;
+	}
+
+	if (port->ip_ienb)
+		write_ireg(port->ip_ioc4_soft, hooks->intr_dma_error,
+				IOC4_W_IES, IOC4_OTHER_INTR_TYPE);
+}
+
+/**
+ * local_open - local open a port
+ * @port: port to open
+ */
+static inline int local_open(struct ioc4_port *port)
+{
+	int spiniter = 0;
+
+	port->ip_flags = 0;
+
+	/* Pause the DMA interface if necessary */
+	if (port->ip_sscr & IOC4_SSCR_DMA_EN) {
+		writel(port->ip_sscr | IOC4_SSCR_DMA_PAUSE,
+			&port->ip_serial_regs->sscr);
+		while((readl(&port->ip_serial_regs-> sscr)
+				& IOC4_SSCR_PAUSE_STATE) == 0) {
+			spiniter++;
+			if (spiniter > MAXITER) {
+				return -1;
+			}
+		}
+	}
+
+	/* Reset the input fifo.  If the uart received chars while the port
+	 * was closed and DMA is not enabled, the uart may have a bunch of
+	 * chars hanging around in its rx fifo which will not be discarded
+	 * by rclr in the upper layer. We must get rid of them here.
+	 */
+	writeb(UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR,
+				&port->ip_uart_regs->i4u_fcr);
+
+	writeb(UART_LCR_WLEN8, &port->ip_uart_regs->i4u_lcr);
+					/* UART_LCR_STOP == 1 stop */
+
+	/* Re-enable DMA, set default threshold to intr whenever there is
+	 * data available.
+	 */
+	port->ip_sscr &= ~IOC4_SSCR_RX_THRESHOLD;
+	port->ip_sscr |= 1;	/* default threshold */
+
+	/* Plug in the new sscr.  This implicitly clears the DMA_PAUSE
+	 * flag if it was set above
+	 */
+	writel(port->ip_sscr, &port->ip_serial_regs->sscr);
+	port->ip_tx_lowat = 1;
+	return 0;
+}
+
+/**
+ * set_rx_timeout - Set rx timeout and threshold values.
+ * @port: port to use
+ * @timeout: timeout value in ticks
+ */
+static inline int set_rx_timeout(struct ioc4_port *port, int timeout)
+{
+	int threshold;
+
+	port->ip_rx_timeout = timeout;
+
+	/* Timeout is in ticks.  Let's figure out how many chars we
+	 * can receive at the current baud rate in that interval
+	 * and set the rx threshold to that amount.  There are 4 chars
+	 * per ring entry, so we'll divide the number of chars that will
+	 * arrive in timeout by 4.
+	 */
+	threshold = timeout * port->ip_baud / 10 / HZ / 4;
+	if (threshold == 0)
+		threshold = 1;	/* otherwise we'll intr all the time! */
+
+	if ((unsigned)threshold > (unsigned)IOC4_SSCR_RX_THRESHOLD)
+		return 1;
+
+	port->ip_sscr &= ~IOC4_SSCR_RX_THRESHOLD;
+	port->ip_sscr |= threshold;
+
+	writel(port->ip_sscr, &port->ip_serial_regs->sscr);
+
+	/* Now set the rx timeout to the given value */
+	timeout = timeout * IOC4_SRTR_HZ / HZ;
+	if (timeout > IOC4_SRTR_CNT)
+		timeout = IOC4_SRTR_CNT;
+
+	writel(timeout, &port->ip_serial_regs->srtr);
+	return 0;
+}
+
+/**
+ * config_port - config the hardware
+ * @port: port to config
+ * @baud: baud rate for the port
+ * @byte_size: data size
+ * @stop_bits: number of stop bits
+ * @parenb: parity enable ?
+ * @parodd: odd parity ?
+ */
+static inline int
+config_port(struct ioc4_port *port,
+	    int baud, int byte_size, int stop_bits, int parenb, int parodd)
+{
+	char lcr, sizebits;
+	int spiniter = 0;
+
+	DPRINT_CONFIG(("%s: baud %d byte_size %d stop %d parenb %d parodd %d\n",
+		__FUNCTION__, baud, byte_size, stop_bits, parenb, parodd));
+
+	if (set_baud(port, baud))
+		return 1;
+
+	switch (byte_size) {
+	case 5:
+		sizebits = UART_LCR_WLEN5;
+		break;
+	case 6:
+		sizebits = UART_LCR_WLEN6;
+		break;
+	case 7:
+		sizebits = UART_LCR_WLEN7;
+		break;
+	case 8:
+		sizebits = UART_LCR_WLEN8;
+		break;
+	default:
+		return 1;
+	}
+
+	/* Pause the DMA interface if necessary */
+	if (port->ip_sscr & IOC4_SSCR_DMA_EN) {
+		writel(port->ip_sscr | IOC4_SSCR_DMA_PAUSE,
+			&port->ip_serial_regs->sscr);
+		while((readl(&port->ip_serial_regs->sscr)
+						& IOC4_SSCR_PAUSE_STATE) == 0) {
+			spiniter++;
+			if (spiniter > MAXITER)
+				return -1;
+		}
+	}
+
+	/* Clear relevant fields in lcr */
+	lcr = readb(&port->ip_uart_regs->i4u_lcr);
+	lcr &= ~(LCR_MASK_BITS_CHAR | UART_LCR_EPAR |
+		 UART_LCR_PARITY | LCR_MASK_STOP_BITS);
+
+	/* Set byte size in lcr */
+	lcr |= sizebits;
+
+	/* Set parity */
+	if (parenb) {
+		lcr |= UART_LCR_PARITY;
+		if (!parodd)
+			lcr |= UART_LCR_EPAR;
+	}
+
+	/* Set stop bits */
+	if (stop_bits)
+		lcr |= UART_LCR_STOP /* 2 stop bits */ ;
+
+	writeb(lcr, &port->ip_uart_regs->i4u_lcr);
+
+	/* Re-enable the DMA interface if necessary */
+	if (port->ip_sscr & IOC4_SSCR_DMA_EN) {
+		writel(port->ip_sscr, &port->ip_serial_regs->sscr);
+	}
+	port->ip_baud = baud;
+
+	/* When we get within this number of ring entries of filling the
+	 * entire ring on tx, place an EXPLICIT intr to generate a lowat
+	 * notification when output has drained.
+	 */
+	port->ip_tx_lowat = (TX_LOWAT_CHARS(baud) + 3) / 4;
+	if (port->ip_tx_lowat == 0)
+		port->ip_tx_lowat = 1;
+
+	set_rx_timeout(port, port->ip_rx_timeout);
+
+	return 0;
+}
+
+/**
+ * do_write - Write bytes to the port.  Returns the number of bytes
+ *			actually written. Called from transmit_chars
+ * @port: port to use
+ * @buf: the stuff to write
+ * @len: how many bytes in 'buf'
+ */
+static inline int do_write(struct ioc4_port *port, char *buf, int len)
+{
+	int prod_ptr, cons_ptr, total = 0;
+	struct ring *outring;
+	struct ring_entry *entry;
+	struct hooks *hooks = port->ip_hooks;
+
+	BUG_ON(!(len >= 0));
+
+	prod_ptr = port->ip_tx_prod;
+	cons_ptr = readl(&port->ip_serial_regs->stcir) & PROD_CONS_MASK;
+	outring = port->ip_outring;
+
+	/* Maintain a 1-entry red-zone.  The ring buffer is full when
+	 * (cons - prod) % ring_size is 1.  Rather than do this subtraction
+	 * in the body of the loop, I'll do it now.
+	 */
+	cons_ptr = (cons_ptr - (int)sizeof(struct ring_entry)) & PROD_CONS_MASK;
+
+	/* Stuff the bytes into the output */
+	while ((prod_ptr != cons_ptr) && (len > 0)) {
+		int xx;
+
+		/* Get 4 bytes (one ring entry) at a time */
+		entry = (struct ring_entry *)((caddr_t) outring + prod_ptr);
+
+		/* Invalidate all entries */
+		entry->ring_allsc = 0;
+
+		/* Copy in some bytes */
+		for (xx = 0; (xx < 4) && (len > 0); xx++) {
+			entry->ring_data[xx] = *buf++;
+			entry->ring_sc[xx] = IOC4_TXCB_VALID;
+			len--;
+			total++;
+		}
+
+		/* If we are within some small threshold of filling up the
+		 * entire ring buffer, we must place an EXPLICIT intr here
+		 * to generate a lowat interrupt in case we subsequently
+		 * really do fill up the ring and the caller goes to sleep.
+		 * No need to place more than one though.
+		 */
+		if (!(port->ip_flags & LOWAT_WRITTEN) &&
+			((cons_ptr - prod_ptr) & PROD_CONS_MASK)
+				<= port->ip_tx_lowat
+					* (int)sizeof(struct ring_entry)) {
+			port->ip_flags |= LOWAT_WRITTEN;
+			entry->ring_sc[0] |= IOC4_TXCB_INT_WHEN_DONE;
+		}
+
+		/* Go on to next entry */
+		prod_ptr += sizeof(struct ring_entry);
+		prod_ptr &= PROD_CONS_MASK;
+	}
+
+	/* If we sent something, start DMA if necessary */
+	if (total > 0 && !(port->ip_sscr & IOC4_SSCR_DMA_EN)) {
+		port->ip_sscr |= IOC4_SSCR_DMA_EN;
+		writel(port->ip_sscr, &port->ip_serial_regs->sscr);
+	}
+
+	/* Store the new producer pointer.  If tx is disabled, we stuff the
+	 * data into the ring buffer, but we don't actually start tx.
+	 */
+	if (!uart_tx_stopped(port->ip_port)) {
+		writel(prod_ptr, &port->ip_serial_regs->stpir);
+
+		/* If we are now transmitting, enable tx_mt interrupt so we
+		 * can disable DMA if necessary when the tx finishes.
+		 */
+		if (total > 0)
+			enable_intrs(port, hooks->intr_tx_mt);
+	}
+	port->ip_tx_prod = prod_ptr;
+	return total;
+}
+
+/**
+ * disable_intrs - disable interrupts
+ * @port: port to enable
+ * @mask: mask to use
+ */
+static void disable_intrs(struct ioc4_port *port, uint32_t mask)
+{
+	struct hooks *hooks = port->ip_hooks;
+
+	if (port->ip_ienb & mask) {
+		write_ireg(port->ip_ioc4_soft, mask, IOC4_W_IEC,
+					IOC4_SIO_INTR_TYPE);
+		port->ip_ienb &= ~mask;
+	}
+
+	if (!port->ip_ienb)
+		write_ireg(port->ip_ioc4_soft, hooks->intr_dma_error,
+				IOC4_W_IEC, IOC4_OTHER_INTR_TYPE);
+}
+
+/**
+ * set_notification - Modify event notification
+ * @port: port to use
+ * @mask: events mask
+ * @set_on: set ?
+ */
+static int set_notification(struct ioc4_port *port, int mask, int set_on)
+{
+	struct hooks *hooks = port->ip_hooks;
+	uint32_t intrbits, sscrbits;
+
+	BUG_ON(!mask);
+
+	intrbits = sscrbits = 0;
+
+	if (mask & N_DATA_READY)
+		intrbits |= (hooks->intr_rx_timer | hooks->intr_rx_high);
+	if (mask & N_OUTPUT_LOWAT)
+		intrbits |= hooks->intr_tx_explicit;
+	if (mask & N_DDCD) {
+		intrbits |= hooks->intr_delta_dcd;
+		sscrbits |= IOC4_SSCR_RX_RING_DCD;
+	}
+	if (mask & N_DCTS)
+		intrbits |= hooks->intr_delta_cts;
+
+	if (set_on) {
+		enable_intrs(port, intrbits);
+		port->ip_notify |= mask;
+		port->ip_sscr |= sscrbits;
+	} else {
+		disable_intrs(port, intrbits);
+		port->ip_notify &= ~mask;
+		port->ip_sscr &= ~sscrbits;
+	}
+
+	/* We require DMA if either DATA_READY or DDCD notification is
+	 * currently requested. If neither of these is requested and
+	 * there is currently no tx in progress, DMA may be disabled.
+	 */
+	if (port->ip_notify & (N_DATA_READY | N_DDCD))
+		port->ip_sscr |= IOC4_SSCR_DMA_EN;
+	else if (!(port->ip_ienb & hooks->intr_tx_mt))
+		port->ip_sscr &= ~IOC4_SSCR_DMA_EN;
+
+	writel(port->ip_sscr, &port->ip_serial_regs->sscr);
+	return 0;
+}
+
+/**
+ * set_mcr - set the master control reg
+ * @the_port: port to use
+ * @set: set ?
+ * @mask1: mcr mask
+ * @mask2: shadow mask
+ */
+static inline int set_mcr(struct uart_port *the_port, int set,
+		int mask1, int mask2)
+{
+	struct ioc4_port *port = get_ioc4_port(the_port);
+	uint32_t shadow;
+	int spiniter = 0;
+	char mcr;
+
+	if (!port)
+		return -1;
+
+	/* Pause the DMA interface if necessary */
+	if (port->ip_sscr & IOC4_SSCR_DMA_EN) {
+		writel(port->ip_sscr | IOC4_SSCR_DMA_PAUSE,
+			&port->ip_serial_regs->sscr);
+		while ((readl(&port->ip_serial_regs->sscr)
+					& IOC4_SSCR_PAUSE_STATE) == 0) {
+			spiniter++;
+			if (spiniter > MAXITER)
+				return -1;
+		}
+	}
+	shadow = readl(&port->ip_serial_regs->shadow);
+	mcr = (shadow & 0xff000000) >> 24;
+
+	/* Set new value */
+	if (set) {
+		mcr |= mask1;
+		shadow |= mask2;
+	} else {
+		mcr &= ~mask1;
+		shadow &= ~mask2;
+	}
+	writeb(mcr, &port->ip_uart_regs->i4u_mcr);
+	writel(shadow, &port->ip_serial_regs->shadow);
+
+	/* Re-enable the DMA interface if necessary */
+	if (port->ip_sscr & IOC4_SSCR_DMA_EN) {
+		writel(port->ip_sscr, &port->ip_serial_regs->sscr);
+	}
+	return 0;
+}
+
+/**
+ * ioc4_set_proto - set the protocol for the port
+ * @port: port to use
+ * @proto: protocol to use
+ */
+static int ioc4_set_proto(struct ioc4_port *port, enum sio_proto proto)
+{
+	struct hooks *hooks = port->ip_hooks;
+
+	switch (proto) {
+	case PROTO_RS232:
+		/* Clear the appropriate GIO pin */
+		writel(0, (&port->ip_mem->gppr_0 +
+				  hooks->rs422_select_pin));
+		break;
+
+	case PROTO_RS422:
+		/* Set the appropriate GIO pin */
+		writel(1, (&port->ip_mem->gppr_0 +
+				  hooks->rs422_select_pin));
+		break;
+
+	default:
+		return 1;
+	}
+	return 0;
+}
+
+/**
+ * transmit_chars - upper level write, called with ip_lock
+ * @the_port: port to write
+ */
+static void transmit_chars(struct uart_port *the_port)
+{
+	int xmit_count, tail, head;
+	int result;
+	char *start;
+	struct tty_struct *tty;
+	struct ioc4_port *port = get_ioc4_port(the_port);
+	struct uart_info *info;
+
+	if (!the_port)
+		return;
+	if (!port)
+		return;
+
+	info = the_port->info;
+	tty = info->tty;
+
+	if (uart_circ_empty(&info->xmit) || uart_tx_stopped(the_port)) {
+		/* Nothing to do or hw stopped */
+		set_notification(port, N_ALL_OUTPUT, 0);
+		return;
+	}
+
+	head = info->xmit.head;
+	tail = info->xmit.tail;
+	start = (char *)&info->xmit.buf[tail];
+
+	/* write out all the data or until the end of the buffer */
+	xmit_count = (head < tail) ? (UART_XMIT_SIZE - tail) : (head - tail);
+	if (xmit_count > 0) {
+		result = do_write(port, start, xmit_count);
+		if (result > 0) {
+			/* booking */
+			xmit_count -= result;
+			the_port->icount.tx += result;
+			/* advance the pointers */
+			tail += result;
+			tail &= UART_XMIT_SIZE - 1;
+			info->xmit.tail = tail;
+			start = (char *)&info->xmit.buf[tail];
+		}
+	}
+	if (uart_circ_chars_pending(&info->xmit) < WAKEUP_CHARS)
+		uart_write_wakeup(the_port);
+
+	if (uart_circ_empty(&info->xmit)) {
+		set_notification(port, N_OUTPUT_LOWAT, 0);
+	} else {
+		set_notification(port, N_OUTPUT_LOWAT, 1);
+	}
+}
+
+/**
+ * ioc4_change_speed - change the speed of the port
+ * @the_port: port to change
+ * @new_termios: new termios settings
+ * @old_termios: old termios settings
+ */
+static void
+ioc4_change_speed(struct uart_port *the_port,
+		  struct termios *new_termios, struct termios *old_termios)
+{
+	struct ioc4_port *port = get_ioc4_port(the_port);
+	int baud, bits;
+	unsigned cflag, cval;
+	int new_parity = 0, new_parity_enable = 0, new_stop = 1, new_data = 8;
+	struct uart_info *info = the_port->info;
+
+	cflag = new_termios->c_cflag;
+
+	switch (cflag & CSIZE) {
+	case CS5:
+		new_data = 5;
+		cval = 0x00;
+		bits = 7;
+		break;
+	case CS6:
+		new_data = 6;
+		cval = 0x01;
+		bits = 8;
+		break;
+	case CS7:
+		new_data = 7;
+		cval = 0x02;
+		bits = 9;
+		break;
+	case CS8:
+		new_data = 8;
+		cval = 0x03;
+		bits = 10;
+		break;
+	default:
+		/* cuz we always need a default ... */
+		new_data = 5;
+		cval = 0x00;
+		bits = 7;
+		break;
+	}
+	if (cflag & CSTOPB) {
+		cval |= 0x04;
+		bits++;
+		new_stop = 1;
+	}
+	if (cflag & PARENB) {
+		cval |= UART_LCR_PARITY;
+		bits++;
+		new_parity_enable = 1;
+	}
+	if (cflag & PARODD) {
+		cval |= UART_LCR_EPAR;
+		new_parity = 1;
+	}
+	if (cflag & IGNPAR) {
+		cval &= ~UART_LCR_PARITY;
+		new_parity_enable = 0;
+	}
+	baud = uart_get_baud_rate(the_port, new_termios, old_termios,
+				MIN_BAUD_SUPPORTED, MAX_BAUD_SUPPORTED);
+	DPRINT_CONFIG(("%s: returned baud %d\n", __FUNCTION__, baud));
+
+	/* default is 9600 */
+	if (!baud)
+		baud = 9600;
+
+	if (!the_port->fifosize)
+		the_port->fifosize = IOC4_MAX_CHARS;
+	the_port->timeout = ((the_port->fifosize * HZ * bits) / (baud / 10));
+	the_port->timeout += HZ / 50;	/* Add .02 seconds of slop */
+
+	the_port->ignore_status_mask = N_ALL_INPUT;
+
+	if (I_IGNPAR(info->tty))
+		the_port->ignore_status_mask &= ~(N_PARITY_ERROR
+						| N_FRAMING_ERROR);
+	if (I_IGNBRK(info->tty)) {
+		the_port->ignore_status_mask &= ~N_BREAK;
+		if (I_IGNPAR(info->tty))
+			the_port->ignore_status_mask &= ~N_OVERRUN_ERROR;
+	}
+	if (!(cflag & CREAD)) {
+		/* ignore everything */
+		the_port->ignore_status_mask &= ~N_DATA_READY;
+	}
+
+	if (cflag & CRTSCTS)
+		info->flags |= ASYNC_CTS_FLOW;
+	else
+		info->flags &= ~ASYNC_CTS_FLOW;
+
+	/* Set the configuration and proper notification call */
+	DPRINT_CONFIG(("%s : port 0x%p cflag 0%o "
+		"config_port(baud %d data %d stop %d p enable %d parity %d),"
+		" notification 0x%x\n",
+	     __FUNCTION__, (void *)port, cflag, baud, new_data, new_stop,
+	     new_parity_enable, new_parity, the_port->ignore_status_mask));
+
+	if ((config_port(port, baud,		/* baud */
+			 new_data,		/* byte size */
+			 new_stop,		/* stop bits */
+			 new_parity_enable,	/* set parity */
+			 new_parity)) >= 0) {	/* parity 1==odd */
+		set_notification(port, the_port->ignore_status_mask, 1);
+	}
+}
+
+/**
+ * ic4_startup_local - Start up the serial port - returns >= 0 if no errors
+ * @the_port: Port to operate on
+ */
+static inline int ic4_startup_local(struct uart_port *the_port)
+{
+	int retval = 0;
+	struct ioc4_port *port;
+	struct uart_info *info;
+
+	if (!the_port)
+		return -1;
+
+	port = get_ioc4_port(the_port);
+	if (!port)
+		return -1;
+
+	info = the_port->info;
+	if (info->flags & UIF_INITIALIZED) {
+		return retval;
+	}
+
+	if (info->tty) {
+		set_bit(TTY_IO_ERROR, &info->tty->flags);
+		clear_bit(TTY_IO_ERROR, &info->tty->flags);
+		if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
+			info->tty->alt_speed = 57600;
+		if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
+			info->tty->alt_speed = 115200;
+		if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
+			info->tty->alt_speed = 230400;
+		if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
+			info->tty->alt_speed = 460800;
+	}
+	local_open(port);
+
+	/* set the speed of the serial port */
+	ioc4_change_speed(the_port, info->tty->termios, (struct termios *)0);
+
+	/* enable hardware flow control - after ioc4_change_speed because
+	 * ASYNC_CTS_FLOW is set there */
+	if (info->flags & ASYNC_CTS_FLOW) {
+		port->ip_sscr |= IOC4_SSCR_HFC_EN;
+		writel(port->ip_sscr, &port->ip_serial_regs->sscr);
+	}
+	info->flags |= UIF_INITIALIZED;
+	return 0;
+}
+
+/*
+ * ioc4_cb_output_lowat - called when the output low water mark is hit
+ * @port: port to output
+ */
+static void ioc4_cb_output_lowat(struct ioc4_port *port)
+{
+	/* ip_lock is set on the call here */
+	if (port->ip_port) {
+		transmit_chars(port->ip_port);
+	}
+}
+
+
+/**
+ * handle_intr - service any interrupts for the given port - 2nd level
+ *			called via sd_intr
+ * @arg: handler arg
+ * @sio_ir: ioc4regs
+ */
+static void handle_intr(void *arg, uint32_t sio_ir)
+{
+	struct ioc4_port *port = (struct ioc4_port *)arg;
+	struct hooks *hooks = port->ip_hooks;
+	unsigned int rx_high_rd_aborted = 0;
+	unsigned int flags;
+	struct uart_port *the_port;
+	int loop_counter;
+
+	/* Possible race condition here: The tx_mt interrupt bit may be
+	 * cleared without the intervention of the interrupt handler,
+	 * e.g. by a write.  If the top level interrupt handler reads a
+	 * tx_mt, then some other processor does a write, starting up
+	 * output, then we come in here, see the tx_mt and stop DMA, the
+	 * output started by the other processor will hang.  Thus we can
+	 * only rely on tx_mt being legitimate if it is read while the
+	 * port lock is held.  Therefore this bit must be ignored in the
+	 * passed in interrupt mask which was read by the top level
+	 * interrupt handler since the port lock was not held at the time
+	 * it was read.  We can only rely on this bit being accurate if it
+	 * is read while the port lock is held.  So we'll clear it for now,
+	 * and reload it later once we have the port lock.
+	 */
+	sio_ir &= ~(hooks->intr_tx_mt);
+
+	spin_lock_irqsave(&port->ip_lock, flags);
+
+	loop_counter = MAXITER;	/* to avoid hangs */
+
+	do {
+		uint32_t shadow;
+
+		if ( loop_counter-- <= 0 ) {
+			printk(KERN_WARNING "IOC4 serial: "
+					"possible hang condition/"
+					"port stuck on interrupt.\n");
+			break;
+		}
+
+		/* Handle a DCD change */
+		if (sio_ir & hooks->intr_delta_dcd) {
+			/* ACK the interrupt */
+			writel(hooks->intr_delta_dcd,
+				&port->ip_mem->sio_ir);
+
+			shadow = readl(&port->ip_serial_regs->shadow);
+
+			if ((port->ip_notify & N_DDCD)
+					&& (shadow & IOC4_SHADOW_DCD)
+					&& (port->ip_port)) {
+				the_port = port->ip_port;
+				the_port->icount.dcd = 1;
+				wake_up_interruptible
+					    (&the_port-> info->delta_msr_wait);
+			} else if ((port->ip_notify & N_DDCD)
+					&& !(shadow & IOC4_SHADOW_DCD)) {
+				/* Flag delta DCD/no DCD */
+				port->ip_flags |= DCD_ON;
+			}
+		}
+
+		/* Handle a CTS change */
+		if (sio_ir & hooks->intr_delta_cts) {
+			/* ACK the interrupt */
+			writel(hooks->intr_delta_cts,
+					&port->ip_mem->sio_ir);
+
+			shadow = readl(&port->ip_serial_regs->shadow);
+
+			if ((port->ip_notify & N_DCTS)
+					&& (port->ip_port)) {
+				the_port = port->ip_port;
+				the_port->icount.cts =
+					(shadow & IOC4_SHADOW_CTS) ? 1 : 0;
+				wake_up_interruptible
+					(&the_port->info->delta_msr_wait);
+			}
+		}
+
+		/* rx timeout interrupt.  Must be some data available.  Put this
+		 * before the check for rx_high since servicing this condition
+		 * may cause that condition to clear.
+		 */
+		if (sio_ir & hooks->intr_rx_timer) {
+			/* ACK the interrupt */
+			writel(hooks->intr_rx_timer,
+				&port->ip_mem->sio_ir);
+
+			if ((port->ip_notify & N_DATA_READY)
+					&& (port->ip_port)) {
+				/* ip_lock is set on call here */
+				receive_chars(port->ip_port);
+			}
+		}
+
+		/* rx high interrupt. Must be after rx_timer.  */
+		else if (sio_ir & hooks->intr_rx_high) {
+			/* Data available, notify upper layer */
+			if ((port->ip_notify & N_DATA_READY)
+						&& port->ip_port) {
+				/* ip_lock is set on call here */
+				receive_chars(port->ip_port);
+			}
+
+			/* We can't ACK this interrupt.  If receive_chars didn't
+			 * cause the condition to clear, we'll have to disable
+			 * the interrupt until the data is drained.
+			 * If the read was aborted, don't disable the interrupt
+			 * as this may cause us to hang indefinitely.  An
+			 * aborted read generally means that this interrupt
+			 * hasn't been delivered to the cpu yet anyway, even
+			 * though we see it as asserted when we read the sio_ir.
+			 */
+			if ((sio_ir = PENDING(port)) & hooks->intr_rx_high) {
+				if ((port->ip_flags & READ_ABORTED) == 0) {
+					port->ip_ienb &= ~hooks->intr_rx_high;
+					port->ip_flags |= INPUT_HIGH;
+				} else {
+					rx_high_rd_aborted++;
+				}
+			}
+		}
+
+		/* We got a low water interrupt: notify upper layer to
+		 * send more data.  Must come before tx_mt since servicing
+		 * this condition may cause that condition to clear.
+		 */
+		if (sio_ir & hooks->intr_tx_explicit) {
+			port->ip_flags &= ~LOWAT_WRITTEN;
+
+			/* ACK the interrupt */
+			writel(hooks->intr_tx_explicit,
+					&port->ip_mem->sio_ir);
+
+			if (port->ip_notify & N_OUTPUT_LOWAT)
+				ioc4_cb_output_lowat(port);
+		}
+
+		/* Handle tx_mt.  Must come after tx_explicit.  */
+		else if (sio_ir & hooks->intr_tx_mt) {
+			/* If we are expecting a lowat notification
+			 * and we get to this point it probably means that for
+			 * some reason the tx_explicit didn't work as expected
+			 * (that can legitimately happen if the output buffer is
+			 * filled up in just the right way).
+			 * So send the notification now.
+			 */
+			if (port->ip_notify & N_OUTPUT_LOWAT) {
+				ioc4_cb_output_lowat(port);
+
+				/* We need to reload the sio_ir since the lowat
+				 * call may have caused another write to occur,
+				 * clearing the tx_mt condition.
+				 */
+				sio_ir = PENDING(port);
+			}
+
+			/* If the tx_mt condition still persists even after the
+			 * lowat call, we've got some work to do.
+			 */
+			if (sio_ir & hooks->intr_tx_mt) {
+
+				/* If we are not currently expecting DMA input,
+				 * and the transmitter has just gone idle,
+				 * there is no longer any reason for DMA, so
+				 * disable it.
+				 */
+				if (!(port->ip_notify
+						& (N_DATA_READY | N_DDCD))) {
+					BUG_ON(!(port->ip_sscr
+							& IOC4_SSCR_DMA_EN));
+					port->ip_sscr &= ~IOC4_SSCR_DMA_EN;
+					writel(port->ip_sscr,
+					   &port->ip_serial_regs->sscr);
+				}
+
+				/* Prevent infinite tx_mt interrupt */
+				port->ip_ienb &= ~hooks->intr_tx_mt;
+			}
+		}
+		sio_ir = PENDING(port);
+
+		/* if the read was aborted and only hooks->intr_rx_high,
+		 * clear hooks->intr_rx_high, so we do not loop forever.
+		 */
+
+		if (rx_high_rd_aborted && (sio_ir == hooks->intr_rx_high)) {
+			sio_ir &= ~hooks->intr_rx_high;
+		}
+	} while (sio_ir & hooks->intr_all);
+
+	spin_unlock_irqrestore(&port->ip_lock, flags);
+
+	/* Re-enable interrupts before returning from interrupt handler.
+	 * Getting interrupted here is okay.  It'll just v() our semaphore, and
+	 * we'll come through the loop again.
+	 */
+
+	write_ireg(port->ip_ioc4_soft, port->ip_ienb, IOC4_W_IES,
+							IOC4_SIO_INTR_TYPE);
+}
+
+/*
+ * ioc4_cb_post_ncs - called for some basic errors
+ * @port: port to use
+ * @ncs: event
+ */
+static void ioc4_cb_post_ncs(struct uart_port *the_port, int ncs)
+{
+	struct uart_icount *icount;
+
+	icount = &the_port->icount;
+
+	if (ncs & NCS_BREAK)
+		icount->brk++;
+	if (ncs & NCS_FRAMING)
+		icount->frame++;
+	if (ncs & NCS_OVERRUN)
+		icount->overrun++;
+	if (ncs & NCS_PARITY)
+		icount->parity++;
+}
+
+/**
+ * do_read - Read in bytes from the port.  Return the number of bytes
+ *			actually read.
+ * @the_port: port to use
+ * @buf: place to put the stuff we read
+ * @len: how big 'buf' is
+ */
+
+static inline int do_read(struct uart_port *the_port, unsigned char *buf,
+				int len)
+{
+	int prod_ptr, cons_ptr, total;
+	struct ioc4_port *port = get_ioc4_port(the_port);
+	struct ring *inring;
+	struct ring_entry *entry;
+	struct hooks *hooks = port->ip_hooks;
+	int byte_num;
+	char *sc;
+	int loop_counter;
+
+	BUG_ON(!(len >= 0));
+	BUG_ON(!port);
+
+	/* There is a nasty timing issue in the IOC4. When the rx_timer
+	 * expires or the rx_high condition arises, we take an interrupt.
+	 * At some point while servicing the interrupt, we read bytes from
+	 * the ring buffer and re-arm the rx_timer.  However the rx_timer is
+	 * not started until the first byte is received *after* it is armed,
+	 * and any bytes pending in the rx construction buffers are not drained
+	 * to memory until either there are 4 bytes available or the rx_timer
+	 * expires.  This leads to a potential situation where data is left
+	 * in the construction buffers forever - 1 to 3 bytes were received
+	 * after the interrupt was generated but before the rx_timer was
+	 * re-armed. At that point as long as no subsequent bytes are received
+	 * the timer will never be started and the bytes will remain in the
+	 * construction buffer forever.  The solution is to execute a DRAIN
+	 * command after rearming the timer.  This way any bytes received before
+	 * the DRAIN will be drained to memory, and any bytes received after
+	 * the DRAIN will start the TIMER and be drained when it expires.
+	 * Luckily, this only needs to be done when the DMA buffer is empty
+	 * since there is no requirement that this function return all
+	 * available data as long as it returns some.
+	 */
+	/* Re-arm the timer */
+	writel(port->ip_rx_cons | IOC4_SRCIR_ARM,
+			&port->ip_serial_regs->srcir);
+
+	prod_ptr = readl(&port->ip_serial_regs->srpir) & PROD_CONS_MASK;
+	cons_ptr = port->ip_rx_cons;
+
+	if (prod_ptr == cons_ptr) {
+		int reset_dma = 0;
+
+		/* Input buffer appears empty, do a flush. */
+
+		/* DMA must be enabled for this to work. */
+		if (!(port->ip_sscr & IOC4_SSCR_DMA_EN)) {
+			port->ip_sscr |= IOC4_SSCR_DMA_EN;
+			reset_dma = 1;
+		}
+
+		/* Potential race condition: we must reload the srpir after
+		 * issuing the drain command, otherwise we could think the rx
+		 * buffer is empty, then take a very long interrupt, and when
+		 * we come back it's full and we wait forever for the drain to
+		 * complete.
+		 */
+		writel(port->ip_sscr | IOC4_SSCR_RX_DRAIN,
+				&port->ip_serial_regs->sscr);
+		prod_ptr = readl(&port->ip_serial_regs->srpir)
+				& PROD_CONS_MASK;
+
+		/* We must not wait for the DRAIN to complete unless there are
+		 * at least 8 bytes (2 ring entries) available to receive the
+		 * data otherwise the DRAIN will never complete and we'll
+		 * deadlock here.
+		 * In fact, to make things easier, I'll just ignore the flush if
+		 * there is any data at all now available.
+		 */
+		if (prod_ptr == cons_ptr) {
+			loop_counter = 0;
+			while (readl(&port->ip_serial_regs->sscr) &
+						IOC4_SSCR_RX_DRAIN) {
+				loop_counter++;
+				if (loop_counter > MAXITER)
+					return -1;
+			}
+
+			/* SIGH. We have to reload the prod_ptr *again* since
+			 * the drain may have caused it to change
+			 */
+			prod_ptr = readl(&port->ip_serial_regs->srpir)
+							& PROD_CONS_MASK;
+		}
+		if (reset_dma) {
+			port->ip_sscr &= ~IOC4_SSCR_DMA_EN;
+			writel(port->ip_sscr, &port->ip_serial_regs->sscr);
+		}
+	}
+	inring = port->ip_inring;
+	port->ip_flags &= ~READ_ABORTED;
+
+	total = 0;
+	loop_counter = 0xfffff;	/* to avoid hangs */
+
+	/* Grab bytes from the hardware */
+	while ((prod_ptr != cons_ptr) && (len > 0)) {
+		entry = (struct ring_entry *)((caddr_t)inring + cons_ptr);
+
+		if ( loop_counter-- <= 0 ) {
+			printk(KERN_WARNING "IOC4 serial: "
+					"possible hang condition/"
+					"port stuck on read.\n");
+			break;
+		}
+
+		/* According to the producer pointer, this ring entry
+		 * must contain some data.  But if the PIO happened faster
+		 * than the DMA, the data may not be available yet, so let's
+		 * wait until it arrives.
+		 */
+		if ((entry->ring_allsc & RING_ANY_VALID) == 0) {
+			/* Indicate the read is aborted so we don't disable
+			 * the interrupt thinking that the consumer is
+			 * congested.
+			 */
+			port->ip_flags |= READ_ABORTED;
+			len = 0;
+			break;
+		}
+
+		/* Load the bytes/status out of the ring entry */
+		for (byte_num = 0; byte_num < 4 && len > 0; byte_num++) {
+			sc = &(entry->ring_sc[byte_num]);
+
+			/* Check for change in modem state or overrun */
+			if ((*sc & IOC4_RXSB_MODEM_VALID)
+						&& (port->ip_notify & N_DDCD)) {
+				/* Notify upper layer if DCD dropped */
+
+				if ((port->ip_flags & DCD_ON)
+						&& !(*sc & IOC4_RXSB_DCD)) {
+
+					/* If we have already copied some data,
+					 * return it.  We'll pick up the carrier
+					 * drop on the next pass.  That way we
+					 * don't throw away the data that has
+					 * already been copied back to
+					 * the caller's buffer.
+					 */
+					if (total > 0) {
+						len = 0;
+						break;
+					}
+					port->ip_flags &= ~DCD_ON;
+
+					/* Turn off this notification so the
+					 * carrier drop protocol won't see it
+					 * again when it does a read.
+					 */
+					*sc &= ~IOC4_RXSB_MODEM_VALID;
+
+					/* To keep things consistent, we need
+					 * to update the consumer pointer so
+					 * the next reader won't come in and
+					 * try to read the same ring entries
+					 * again. This must be done here before
+					 * the dcd change.
+					 */
+
+					if ((entry->ring_allsc & RING_ANY_VALID)
+									== 0) {
+						cons_ptr += (int)sizeof
+							(struct ring_entry);
+						cons_ptr &= PROD_CONS_MASK;
+					}
+					writel(cons_ptr,
+						&port->ip_serial_regs->srcir);
+					port->ip_rx_cons = cons_ptr;
+
+					/* Notify upper layer of carrier drop */
+					if ((port->ip_notify & N_DDCD)
+						   && port->ip_port) {
+						the_port->icount.dcd = 0;
+						wake_up_interruptible
+						    (&the_port->info->
+							delta_msr_wait);
+					}
+
+					/* If we had any data to return, we
+					 * would have returned it above.
+					 */
+					return 0;
+				}
+			}
+			if (*sc & IOC4_RXSB_MODEM_VALID) {
+				/* Notify that an input overrun occurred */
+				if ((*sc & IOC4_RXSB_OVERRUN)
+				    && (port->ip_notify & N_OVERRUN_ERROR)) {
+					ioc4_cb_post_ncs(the_port, NCS_OVERRUN);
+				}
+				/* Don't look at this byte again */
+				*sc &= ~IOC4_RXSB_MODEM_VALID;
+			}
+
+			/* Check for valid data or RX errors */
+			if ((*sc & IOC4_RXSB_DATA_VALID) &&
+					((*sc & (IOC4_RXSB_PAR_ERR
+							| IOC4_RXSB_FRAME_ERR
+							| IOC4_RXSB_BREAK))
+					&& (port->ip_notify & (N_PARITY_ERROR
+							| N_FRAMING_ERROR
+							| N_BREAK)))) {
+				/* There is an error condition on the next byte.
+				 * If we have already transferred some bytes,
+				 * we'll stop here. Otherwise if this is the
+				 * first byte to be read, we'll just transfer
+				 * it alone after notifying the
+				 * upper layer of its status.
+				 */
+				if (total > 0) {
+					len = 0;
+					break;
+				} else {
+					if ((*sc & IOC4_RXSB_PAR_ERR) &&
+					   (port->ip_notify & N_PARITY_ERROR)) {
+						ioc4_cb_post_ncs(the_port,
+								NCS_PARITY);
+					}
+					if ((*sc & IOC4_RXSB_FRAME_ERR) &&
+					   (port->ip_notify & N_FRAMING_ERROR)){
+						ioc4_cb_post_ncs(the_port,
+								NCS_FRAMING);
+					}
+					if ((*sc & IOC4_RXSB_BREAK)
+					    && (port->ip_notify & N_BREAK)) {
+							ioc4_cb_post_ncs
+								    (the_port,
+								     NCS_BREAK);
+					}
+					len = 1;
+				}
+			}
+			if (*sc & IOC4_RXSB_DATA_VALID) {
+				*sc &= ~IOC4_RXSB_DATA_VALID;
+				*buf = entry->ring_data[byte_num];
+				buf++;
+				len--;
+				total++;
+			}
+		}
+
+		/* If we used up this entry entirely, go on to the next one,
+		 * otherwise we must have run out of buffer space, so
+		 * leave the consumer pointer here for the next read in case
+		 * there are still unread bytes in this entry.
+		 */
+		if ((entry->ring_allsc & RING_ANY_VALID) == 0) {
+			cons_ptr += (int)sizeof(struct ring_entry);
+			cons_ptr &= PROD_CONS_MASK;
+		}
+	}
+
+	/* Update consumer pointer and re-arm rx timer interrupt */
+	writel(cons_ptr, &port->ip_serial_regs->srcir);
+	port->ip_rx_cons = cons_ptr;
+
+	/* If we have now dipped below the rx high water mark and we have
+	 * rx_high interrupt turned off, we can now turn it back on again.
+	 */
+	if ((port->ip_flags & INPUT_HIGH) && (((prod_ptr - cons_ptr)
+			& PROD_CONS_MASK) < ((port->ip_sscr &
+				IOC4_SSCR_RX_THRESHOLD)
+					<< IOC4_PROD_CONS_PTR_OFF))) {
+		port->ip_flags &= ~INPUT_HIGH;
+		enable_intrs(port, hooks->intr_rx_high);
+	}
+	return total;
+}
+/**
+ * receive_chars - upper level read. Called with ip_lock.
+ * @the_port: port to read from
+ */
+static void receive_chars(struct uart_port *the_port)
+{
+	struct tty_struct *tty;
+	unsigned char ch[IOC4_MAX_CHARS];
+	int read_count, request_count;
+	struct uart_icount *icount;
+	struct uart_info *info = the_port->info;
+
+	/* Make sure all the pointers are "good" ones */
+	if (!info)
+		return;
+	if (!info->tty)
+		return;
+
+	tty = info->tty;
+
+	request_count = TTY_FLIPBUF_SIZE - tty->flip.count - 1;
+
+	if (request_count > 0) {
+		if (request_count > IOC4_MAX_CHARS - 2)
+			request_count = IOC4_MAX_CHARS - 2;
+		icount = &the_port->icount;
+		read_count = do_read(the_port, ch, request_count);
+		if (read_count > 0) {
+			memcpy(tty->flip.char_buf_ptr, ch, read_count);
+			memset(tty->flip.flag_buf_ptr, TTY_NORMAL, read_count);
+			tty->flip.char_buf_ptr += read_count;
+			tty->flip.flag_buf_ptr += read_count;
+			tty->flip.count += read_count;
+			icount->rx += read_count;
+		}
+	}
+	tty_flip_buffer_push(tty);
+}
+
+/**
+ * ic4_type - What type of console are we?
+ * @port: Port to operate with (we ignore since we only have one port)
+ *
+ */
+static const char *ic4_type(struct uart_port *the_port)
+{
+	return "SGI IOC4 Serial";
+}
+
+/**
+ * ic4_tx_empty - Is the transmitter empty?  We pretend we're always empty
+ * @port: Port to operate on (we ignore since we always return 1)
+ *
+ */
+static unsigned int ic4_tx_empty(struct uart_port *the_port)
+{
+	return 1;
+}
+
+/**
+ * ic4_stop_tx - stop the transmitter
+ * @port: Port to operate on
+ * @tty_stop: Set to 1 if called via uart_stop
+ *
+ */
+static void ic4_stop_tx(struct uart_port *the_port, unsigned int tty_stop)
+{
+}
+
+/**
+ * null_void_function -
+ * @port: Port to operate on
+ *
+ */
+static void null_void_function(struct uart_port *the_port)
+{
+}
+
+/**
+ * ic4_shutdown - shut down the port - free irq and disable
+ * @port: Port to shut down
+ *
+ */
+static void ic4_shutdown(struct uart_port *the_port)
+{
+	unsigned long port_flags;
+	struct ioc4_port *port;
+	struct uart_info *info;
+
+	port = get_ioc4_port(the_port);
+	if (!port)
+		return;
+
+	info = the_port->info;
+
+	if (!(info->flags & UIF_INITIALIZED))
+		return;
+
+	wake_up_interruptible(&info->delta_msr_wait);
+
+	if (info->tty)
+		set_bit(TTY_IO_ERROR, &info->tty->flags);
+
+	spin_lock_irqsave(&port->ip_lock, port_flags);
+	set_notification(port, N_ALL, 0);
+	info->flags &= ~UIF_INITIALIZED;
+	spin_unlock_irqrestore(&port->ip_lock, port_flags);
+}
+
+/**
+ * ic4_set_mctrl - set control lines (dtr, rts, etc)
+ * @port: Port to operate on
+ * @mctrl: Lines to set/unset
+ *
+ */
+static void ic4_set_mctrl(struct uart_port *the_port, unsigned int mctrl)
+{
+	unsigned char mcr = 0;
+
+	if (mctrl & TIOCM_RTS)
+		mcr |= UART_MCR_RTS;
+	if (mctrl & TIOCM_DTR)
+		mcr |= UART_MCR_DTR;
+	if (mctrl & TIOCM_OUT1)
+		mcr |= UART_MCR_OUT1;
+	if (mctrl & TIOCM_OUT2)
+		mcr |= UART_MCR_OUT2;
+	if (mctrl & TIOCM_LOOP)
+		mcr |= UART_MCR_LOOP;
+
+	set_mcr(the_port, 1, mcr, IOC4_SHADOW_DTR);
+}
+
+/**
+ * ic4_get_mctrl - get control line info
+ * @port: port to operate on
+ *
+ */
+static unsigned int ic4_get_mctrl(struct uart_port *the_port)
+{
+	struct ioc4_port *port = get_ioc4_port(the_port);
+	uint32_t shadow;
+	unsigned int ret = 0;
+
+	if (!port)
+		return 0;
+
+	shadow = readl(&port->ip_serial_regs->shadow);
+	if (shadow & IOC4_SHADOW_DCD)
+		ret |= TIOCM_CAR;
+	if (shadow & IOC4_SHADOW_DR)
+		ret |= TIOCM_DSR;
+	if (shadow & IOC4_SHADOW_CTS)
+		ret |= TIOCM_CTS;
+	return ret;
+}
+
+/**
+ * ic4_start_tx - Start transmitter, flush any output
+ * @port: Port to operate on
+ * @tty_stop: Set to 1 if called via uart_start
+ *
+ */
+static void ic4_start_tx(struct uart_port *the_port, unsigned int tty_stop)
+{
+	struct ioc4_port *port = get_ioc4_port(the_port);
+	unsigned long flags;
+
+	if (port) {
+		spin_lock_irqsave(&port->ip_lock, flags);
+		transmit_chars(the_port);
+		spin_unlock_irqrestore(&port->ip_lock, flags);
+	}
+}
+
+/**
+ * ic4_break_ctl - handle breaks
+ * @port: Port to operate on
+ * @break_state: Break state
+ *
+ */
+static void ic4_break_ctl(struct uart_port *the_port, int break_state)
+{
+}
+
+/**
+ * ic4_startup - Start up the serial port - always return 0 (We're always on)
+ * @port: Port to operate on
+ *
+ */
+static int ic4_startup(struct uart_port *the_port)
+{
+	int retval;
+	struct ioc4_port *port;
+	struct ioc4_control *control;
+	struct uart_info *info;
+	unsigned long port_flags;
+
+	if (!the_port) {
+		return -ENODEV;
+	}
+	port = get_ioc4_port(the_port);
+	if (!port) {
+		return -ENODEV;
+	}
+	info = the_port->info;
+
+	control = port->ip_control;
+	if (!control) {
+		return -ENODEV;
+	}
+
+	/* Start up the serial port */
+	spin_lock_irqsave(&port->ip_lock, port_flags);
+	retval = ic4_startup_local(the_port);
+	spin_unlock_irqrestore(&port->ip_lock, port_flags);
+	return retval;
+}
+
+/**
+ * ic4_set_termios - set termios stuff
+ * @port: port to operate on
+ * @termios: New settings
+ * @termios: Old
+ *
+ */
+static void
+ic4_set_termios(struct uart_port *the_port,
+		struct termios *termios, struct termios *old_termios)
+{
+	struct ioc4_port *port = get_ioc4_port(the_port);
+	unsigned long port_flags;
+
+	spin_lock_irqsave(&port->ip_lock, port_flags);
+	ioc4_change_speed(the_port, termios, old_termios);
+	spin_unlock_irqrestore(&port->ip_lock, port_flags);
+}
+
+/**
+ * ic4_request_port - allocate resources for port - no op....
+ * @port: port to operate on
+ *
+ */
+static int ic4_request_port(struct uart_port *port)
+{
+	return 0;
+}
+
+/* Associate the uart functions above - given to serial core */
+
+static struct uart_ops ioc4_ops = {
+	.tx_empty	= ic4_tx_empty,
+	.set_mctrl	= ic4_set_mctrl,
+	.get_mctrl	= ic4_get_mctrl,
+	.stop_tx	= ic4_stop_tx,
+	.start_tx	= ic4_start_tx,
+	.stop_rx	= null_void_function,
+	.enable_ms	= null_void_function,
+	.break_ctl	= ic4_break_ctl,
+	.startup	= ic4_startup,
+	.shutdown	= ic4_shutdown,
+	.set_termios	= ic4_set_termios,
+	.type		= ic4_type,
+	.release_port	= null_void_function,
+	.request_port	= ic4_request_port,
+};
+
+/*
+ * Boot-time initialization code
+ */
+
+static struct uart_driver ioc4_uart = {
+	.owner		= THIS_MODULE,
+	.driver_name	= "ioc4_serial",
+	.dev_name	= DEVICE_NAME,
+	.major		= DEVICE_MAJOR,
+	.minor		= DEVICE_MINOR,
+	.nr		= IOC4_NUM_CARDS * IOC4_NUM_SERIAL_PORTS,
+};
+
+/**
+ * ioc4_serial_core_attach - register with serial core
+ *		This is done during pci probing
+ * @pdev: handle for this card
+ */
+static inline int
+ioc4_serial_core_attach(struct pci_dev *pdev)
+{
+	struct ioc4_port *port;
+	struct uart_port *the_port;
+	struct ioc4_control *control = pci_get_drvdata(pdev);
+	int ii;
+
+	DPRINT_CONFIG(("%s: attach pdev 0x%p - control 0x%p\n",
+			__FUNCTION__, pdev, (void *)control));
+
+	if (!control)
+		return -ENODEV;
+
+	/* once around for each port on this card */
+	for (ii = 0; ii < IOC4_NUM_SERIAL_PORTS; ii++) {
+		the_port = &control->ic_port[ii].icp_uart_port;
+		port = control->ic_port[ii].icp_port;
+		port->ip_port = the_port;
+
+		DPRINT_CONFIG(("%s: attach the_port 0x%p / port 0x%p\n",
+				__FUNCTION__, (void *)the_port,
+				(void *)port));
+
+		the_port->lock = SPIN_LOCK_UNLOCKED;
+		/* membase, iobase and mapbase just need to be non-0 */
+		the_port->membase = (unsigned char __iomem *)1;
+		the_port->line = the_port->iobase = ii;
+		the_port->mapbase = 1;
+		the_port->type = PORT_16550A;
+		the_port->fifosize = IOC4_MAX_CHARS;
+		the_port->ops = &ioc4_ops;
+		the_port->irq = control->ic_irq;
+		the_port->dev = &pdev->dev;
+		if (uart_add_one_port(&ioc4_uart, the_port) < 0) {
+			printk(KERN_WARNING
+				       "%s: unable to add port %d\n",
+				       __FUNCTION__, the_port->line);
+		} else {
+			DPRINT_CONFIG(
+				    ("IOC4 serial driver port %d irq = %d\n",
+				       the_port->line, the_port->irq));
+		}
+		/* all ports are rs232 for now */
+		ioc4_set_proto(port, PROTO_RS232);
+	}
+	return 0;
+}
+
+/**
+ * ioc4_serial_attach_one - register attach function
+ *		called per card found from ioc4_serial_detect as part
+ *		of module_init().
+ * @pdev: handle for this card
+ * @pci_id: pci id for this card
+ */
+int
+ioc4_serial_attach_one(struct pci_dev *pdev, const struct pci_device_id *pci_id)
+{
+	struct ioc4_mem __iomem *mem;
+	unsigned long tmp_addr, tmp_addr1;
+	struct ioc4_serial __iomem *serial;
+	struct ioc4_soft *soft;
+	struct ioc4_control *control;
+	int tmp, ret = 0;
+
+
+	DPRINT_CONFIG(("%s (0x%p, 0x%p)\n", __FUNCTION__, pdev, pci_id));
+
+	/* Map in the ioc4 memory */
+	tmp_addr = pci_resource_start(pdev, 0);
+	if (!tmp_addr) {
+		printk(KERN_WARNING
+			 "ioc4 (%p) : unable to get PIO mapping for "
+				"MEM space\n", (void *)pdev);
+		return -ENODEV;
+	}
+	if (!request_region(tmp_addr, sizeof(struct ioc4_mem), "sioc4_mem")) {
+		printk(KERN_ALERT
+			"ioc4 (%p): unable to get request region for "
+			"MEM space\n", (void *)pdev);
+		return -ENODEV;
+	}
+	mem = ioremap(tmp_addr, sizeof(struct ioc4_mem));
+	if (!mem) {
+		printk(KERN_WARNING
+			 "ioc4 (%p) : unable to remap ioc4 memory\n",
+				(void *)pdev);
+		ret = -ENODEV;
+		goto out1;
+	}
+
+	/* request serial registers */
+	tmp_addr1 = pci_resource_start(pdev, 0) + IOC4_SERIAL_OFFSET;
+
+	if (!request_region(tmp_addr1, sizeof(struct ioc4_serial),
+					"sioc4_uart")) {
+		printk(KERN_WARNING
+			"ioc4 (%p): unable to get request region for "
+				"uart space\n", (void *)pdev);
+		ret = -ENODEV;
+		goto out1;
+	}
+	serial = ioremap(tmp_addr1, sizeof(struct ioc4_serial));
+	if (!serial) {
+		printk(KERN_WARNING
+			 "ioc4 (%p) : unable to remap ioc4 serial register\n",
+				(void *)pdev);
+		ret = -ENODEV;
+		goto out2;
+	}
+	DPRINT_CONFIG(("%s : mem 0x%p, serial 0x%p\n",
+				__FUNCTION__, (void *)mem, (void *)serial));
+
+	/* Get memory for the new card */
+	control = kmalloc(sizeof(struct ioc4_control) * IOC4_NUM_SERIAL_PORTS,
+						GFP_KERNEL);
+
+	if (!control) {
+		printk(KERN_WARNING "ioc4_attach_one"
+		       ": unable to get memory for the IOC4\n");
+		ret = -ENOMEM;
+		goto out2;
+	}
+	memset(control, 0, sizeof(struct ioc4_control));
+	pci_set_drvdata(pdev, control);
+
+	/* Allocate the soft structure */
+	soft = kmalloc(sizeof(struct ioc4_soft), GFP_KERNEL);
+	if (!soft) {
+		printk(KERN_WARNING
+		       "ioc4 (%p): unable to get memory for the soft struct\n",
+		       (void *)pdev);
+		ret = -ENOMEM;
+		goto out3;
+	}
+	memset(soft, 0, sizeof(struct ioc4_soft));
+
+	spin_lock_init(&soft->is_ir_lock);
+	soft->is_ioc4_mem_addr = mem;
+	soft->is_ioc4_serial_addr = serial;
+
+	/* Init the IOC4 */
+	pci_read_config_dword(pdev, PCI_COMMAND, &tmp);
+	pci_write_config_dword(pdev, PCI_COMMAND,
+			       tmp | PCI_COMMAND_PARITY | PCI_COMMAND_SERR);
+
+	writel(0xf << IOC4_SIO_CR_CMD_PULSE_SHIFT, &mem->sio_cr);
+
+	/* Enable serial port mode select generic PIO pins as outputs */
+	writel(IOC4_GPCR_UART0_MODESEL | IOC4_GPCR_UART1_MODESEL
+		| IOC4_GPCR_UART2_MODESEL | IOC4_GPCR_UART3_MODESEL,
+		&mem->gpcr_s);
+
+	/* Clear and disable all interrupts */
+	write_ireg(soft, ~0, IOC4_W_IEC, IOC4_SIO_INTR_TYPE);
+	writel(~0, &mem->sio_ir);
+	write_ireg(soft, ~(IOC4_OTHER_IR_ATA_INT | IOC4_OTHER_IR_ATA_MEMERR),
+			IOC4_W_IEC, IOC4_OTHER_INTR_TYPE);
+	writel(~(IOC4_OTHER_IR_ATA_MEMERR | IOC4_OTHER_IR_ATA_MEMERR),
+					&mem->other_ir);
+	control->ic_soft = soft;
+	if (!request_irq(pdev->irq, ioc4_intr, SA_SHIRQ,
+				"sgi-ioc4serial", (void *)soft)) {
+		control->ic_irq = pdev->irq;
+	} else {
+		printk(KERN_WARNING
+		    "%s : request_irq fails for IRQ 0x%x\n ",
+			__FUNCTION__, pdev->irq);
+	}
+	if ((ret = ioc4_attach_local(pdev, control, soft,
+				soft->is_ioc4_mem_addr,
+				soft->is_ioc4_serial_addr)))
+		goto out4;
+
+	/* register port with the serial core */
+
+	if ((ret = ioc4_serial_core_attach(pdev)))
+		goto out4;
+
+	return ret;
+
+	/* error exits that give back resources */
+out4:
+	kfree(soft);
+out3:
+	kfree(control);
+out2:
+	release_region(tmp_addr1, sizeof(struct ioc4_serial));
+out1:
+	release_region(tmp_addr, sizeof(struct ioc4_mem));
+
+	return ret;
+}
+
+
+/**
+ * ioc4_serial_remove_one - detach function
+ *
+ * @pdev: handle for this card
+ */
+
+#if 0
+void ioc4_serial_remove_one(struct pci_dev *pdev)
+{
+	int ii;
+	struct ioc4_control *control;
+	struct uart_port *the_port;
+	struct ioc4_port *port;
+	struct ioc4_soft *soft;
+
+	control = pci_get_drvdata(pdev);
+
+	for (ii = 0; ii < IOC4_NUM_SERIAL_PORTS; ii++) {
+		the_port = &control->ic_port[ii].icp_uart_port;
+		if (the_port) {
+			uart_remove_one_port(&ioc4_uart, the_port);
+		}
+		port = control->ic_port[ii].icp_port;
+		if (!(ii & 1) && port) {
+			pci_free_consistent(port->ip_pdev,
+					TOTAL_RING_BUF_SIZE,
+					(void *)port->ip_cpu_ringbuf,
+					port->ip_dma_ringbuf);
+			kfree(port);
+		}
+	}
+	soft = control->ic_soft;
+	if (soft) {
+		free_irq(control->ic_irq, (void *)soft);
+		if (soft->is_ioc4_serial_addr) {
+			release_region((unsigned long)
+			     soft->is_ioc4_serial_addr,
+				sizeof(struct ioc4_serial));
+		}
+		kfree(soft);
+	}
+	kfree(control);
+	pci_set_drvdata(pdev, NULL);
+	uart_unregister_driver(&ioc4_uart);
+}
+#endif
+
+/**
+ * ioc4_serial_init - module init
+ */
+int ioc4_serial_init(void)
+{
+	int ret;
+
+	/* register with serial core */
+	if ((ret = uart_register_driver(&ioc4_uart)) < 0) {
+		printk(KERN_WARNING
+			"%s: Couldn't register IOC4 serial driver\n",
+			__FUNCTION__);
+		return ret;
+	}
+	return 0;
+}
+
+MODULE_AUTHOR("Pat Gefre - Silicon Graphics Inc. (SGI) <pfg@sgi.com>");
+MODULE_DESCRIPTION("Serial PCI driver module for SGI IOC4 Base-IO Card");
+MODULE_LICENSE("GPL");
+
+EXPORT_SYMBOL(ioc4_serial_init);
+EXPORT_SYMBOL(ioc4_serial_attach_one);
diff -Nru a/drivers/serial/s3c2410.c b/drivers/serial/s3c2410.c
--- a/drivers/serial/s3c2410.c	2005-03-11 12:51:46 -08:00
+++ b/drivers/serial/s3c2410.c	2005-03-11 12:51:46 -08:00
@@ -5,7 +5,8 @@
  *
  * Based on drivers/char/serial.c and drivers/char/21285.c
  *
- * Ben Dooks, (c) 2003 Simtec Electronics
+ * Ben Dooks, (c) 2003-2005 Simtec Electronics
+ *	http://www.simtec.co.uk/products/SWLINUX/
  *
  * Changelog:
  *
@@ -24,6 +25,19 @@
  *		     - spin-lock initialisation (Dimitry Andric)
  *		     - added clock control
  *		     - updated init code to use platform_device info
+ *
+ * 06-Mar-2005  BJD  Add s3c2440 fclk clock source
+ *
+ * 09-Mar-2005  BJD  Add s3c2400 support
+ *
+ * 10-Mar-2005  LCVR Changed S3C2410_VA_UART to S3C24XX_VA_UART
+*/
+
+/* Note on 2440 fclk clock source handling
+ *
+ * Whilst it is possible to use the fclk as clock source, the method
+ * of properly switching too/from this is currently un-implemented, so
+ * whichever way is configured at startup is the one that will be used.
 */
 
 /* Hote on 2410 error handling
@@ -87,6 +101,9 @@
 
 	int (*get_clksrc)(struct uart_port *, struct s3c24xx_uart_clksrc *clk);
 	int (*set_clksrc)(struct uart_port *, struct s3c24xx_uart_clksrc *clk);
+
+	/* uart controls */
+	int (*reset_port)(struct uart_port *, struct s3c2410_uartcfg *);
 };
 
 struct s3c24xx_uart_port {
@@ -606,11 +623,6 @@
  * baud clocks (and the resultant actual baud rates) and then tries to
  * pick the closest one and select that.
  *
- * NOTES:
- *	1) there is no current code to properly select/deselect FCLK on
- *	   the s3c2440, so only specify FCLK or non-FCLK in the clock
- *	   sources for the UART
- *
 */
 
 
@@ -658,6 +670,7 @@
 		return 0;
 
 	rate = clk_get_rate(calc->src);
+	rate /= clksrc->divisor;
 
 	calc->clksrc = clksrc;
 	calc->quot = (rate + (8 * baud)) / (16 * baud);
@@ -685,6 +698,27 @@
 		if (cfg->clocks_size == 0)
 			clkp = &tmp_clksrc;
 
+		/* check to see if we're sourcing fclk, and if so we're
+		 * going to have to update the clock source
+		 */
+
+		if (strcmp(clkp->name, "fclk") == 0) {
+			struct s3c24xx_uart_clksrc src;
+
+			s3c24xx_serial_getsource(port, &src);
+
+			/* check that the port already using fclk, and if
+			 * not, then re-select fclk
+			 */
+
+			if (strcmp(src.name, clkp->name) == 0) {
+				s3c24xx_serial_setsource(port, clkp);
+				s3c24xx_serial_getsource(port, &src);
+			}
+
+			clkp->divisor = src.divisor;
+		}
+
 		s3c24xx_serial_calcbaud(res, port, clkp, baud);
 		best = res;
 		resptr = best + 1;
@@ -955,8 +989,6 @@
 	[0] = {
 		.port = {
 			.lock		= SPIN_LOCK_UNLOCKED,
-			.membase	= 0,
-			.mapbase	= 0,
 			.iotype		= UPIO_MEM,
 			.irq		= IRQ_S3CUART_RX0,
 			.uartclk	= 0,
@@ -969,8 +1001,6 @@
 	[1] = {
 		.port = {
 			.lock		= SPIN_LOCK_UNLOCKED,
-			.membase	= 0,
-			.mapbase	= 0,
 			.iotype		= UPIO_MEM,
 			.irq		= IRQ_S3CUART_RX1,
 			.uartclk	= 0,
@@ -985,8 +1015,6 @@
 	[2] = {
 		.port = {
 			.lock		= SPIN_LOCK_UNLOCKED,
-			.membase	= 0,
-			.mapbase	= 0,
 			.iotype		= UPIO_MEM,
 			.irq		= IRQ_S3CUART_RX2,
 			.uartclk	= 0,
@@ -999,24 +1027,18 @@
 #endif
 };
 
+/* s3c24xx_serial_resetport
+ *
+ * wrapper to call the specific reset for this port (reset the fifos
+ * and the settings)
+*/
 
-static int s3c24xx_serial_resetport(struct uart_port *port,
-				    struct s3c2410_uartcfg *cfg)
+static inline int s3c24xx_serial_resetport(struct uart_port * port,
+					   struct s3c2410_uartcfg *cfg)
 {
-	/* ensure registers are setup */
-
-	dbg("s3c24xx_serial_resetport: port=%p (%08lx), cfg=%p\n",
-	    port, port->mapbase, cfg);
-
-	wr_regl(port, S3C2410_UCON,  cfg->ucon);
-	wr_regl(port, S3C2410_ULCON, cfg->ulcon);
-
-	/* reset both fifos */
-
-	wr_regl(port, S3C2410_UFCON, cfg->ufcon | S3C2410_UFCON_RESETBOTH);
-	wr_regl(port, S3C2410_UFCON, cfg->ufcon);
+	struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port);
 
-	return 0;
+	return (info->reset_port)(port, cfg);
 }
 
 /* s3c24xx_serial_init_port
@@ -1073,7 +1095,7 @@
 
 	port->mapbase	= res->start;
 	port->membase	= (void __iomem *)(res->start - S3C2410_PA_UART);
-	port->membase  += S3C2410_VA_UART;
+	port->membase  += S3C24XX_VA_UART;
 	port->irq	= platform_get_irq(platdev, 0);
 
 	ourport->clk	= clk_get(&platdev->dev, "uart");
@@ -1180,6 +1202,97 @@
 
 /* cpu specific variations on the serial port support */
 
+#ifdef CONFIG_CPU_S3C2400
+
+static int s3c2400_serial_getsource(struct uart_port *port,
+				    struct s3c24xx_uart_clksrc *clk)
+{
+	clk->divisor = 1;
+	clk->name = "pclk";
+
+	return 0;
+}
+
+static int s3c2400_serial_setsource(struct uart_port *port,
+				    struct s3c24xx_uart_clksrc *clk)
+{
+	return 0;
+}
+
+static int s3c2400_serial_resetport(struct uart_port *port,
+				    struct s3c2410_uartcfg *cfg)
+{
+	dbg("s3c2400_serial_resetport: port=%p (%08lx), cfg=%p\n",
+	    port, port->mapbase, cfg);
+
+	wr_regl(port, S3C2410_UCON,  cfg->ucon);
+	wr_regl(port, S3C2410_ULCON, cfg->ulcon);
+
+	/* reset both fifos */
+
+	wr_regl(port, S3C2410_UFCON, cfg->ufcon | S3C2410_UFCON_RESETBOTH);
+	wr_regl(port, S3C2410_UFCON, cfg->ufcon);
+
+	return 0;
+}
+
+static struct s3c24xx_uart_info s3c2400_uart_inf = {
+	.name		= "Samsung S3C2400 UART",
+	.type		= PORT_S3C2400,
+	.fifosize	= 16,
+	.rx_fifomask	= S3C2410_UFSTAT_RXMASK,
+	.rx_fifoshift	= S3C2410_UFSTAT_RXSHIFT,
+	.rx_fifofull	= S3C2410_UFSTAT_RXFULL,
+	.tx_fifofull	= S3C2410_UFSTAT_TXFULL,
+	.tx_fifomask	= S3C2410_UFSTAT_TXMASK,
+	.tx_fifoshift	= S3C2410_UFSTAT_TXSHIFT,
+	.get_clksrc	= s3c2400_serial_getsource,
+	.set_clksrc	= s3c2400_serial_setsource,
+	.reset_port	= s3c2400_serial_resetport,
+};
+
+static int s3c2400_serial_probe(struct device *dev)
+{
+	return s3c24xx_serial_probe(dev, &s3c2400_uart_inf);
+}
+
+static struct device_driver s3c2400_serial_drv = {
+	.name		= "s3c2400-uart",
+	.bus		= &platform_bus_type,
+	.probe		= s3c2400_serial_probe,
+	.remove		= s3c24xx_serial_remove,
+	.suspend	= s3c24xx_serial_suspend,
+	.resume		= s3c24xx_serial_resume,
+};
+
+static inline int s3c2400_serial_init(void)
+{
+	return s3c24xx_serial_init(&s3c2400_serial_drv, &s3c2400_uart_inf);
+}
+
+static inline void s3c2400_serial_exit(void)
+{
+	driver_unregister(&s3c2400_serial_drv);
+}
+
+#define s3c2400_uart_inf_at &s3c2400_uart_inf
+#else
+
+static inline int s3c2400_serial_init(void)
+{
+	return 0;
+}
+
+static inline void s3c2400_serial_exit(void)
+{
+}
+
+#define s3c2400_uart_inf_at NULL
+
+#endif /* CONFIG_CPU_S3C2400 */
+
+/* S3C2410 support */
+
 #ifdef CONFIG_CPU_S3C2410
 
 static int s3c2410_serial_setsource(struct uart_port *port,
@@ -1207,6 +1320,23 @@
 	return 0;
 }
 
+static int s3c2410_serial_resetport(struct uart_port *port,
+				    struct s3c2410_uartcfg *cfg)
+{
+	dbg("s3c2410_serial_resetport: port=%p (%08lx), cfg=%p\n",
+	    port, port->mapbase, cfg);
+
+	wr_regl(port, S3C2410_UCON,  cfg->ucon);
+	wr_regl(port, S3C2410_ULCON, cfg->ulcon);
+
+	/* reset both fifos */
+
+	wr_regl(port, S3C2410_UFCON, cfg->ufcon | S3C2410_UFCON_RESETBOTH);
+	wr_regl(port, S3C2410_UFCON, cfg->ufcon);
+
+	return 0;
+}
+
 static struct s3c24xx_uart_info s3c2410_uart_inf = {
 	.name		= "Samsung S3C2410 UART",
 	.type		= PORT_S3C2410,
@@ -1219,6 +1349,7 @@
 	.tx_fifoshift	= S3C2410_UFSTAT_TXSHIFT,
 	.get_clksrc	= s3c2410_serial_getsource,
 	.set_clksrc	= s3c2410_serial_setsource,
+	.reset_port	= s3c2410_serial_resetport,
 };
 
 /* device management */
@@ -1294,6 +1425,7 @@
 				    struct s3c24xx_uart_clksrc *clk)
 {
 	unsigned long ucon = rd_regl(port, S3C2410_UCON);
+	unsigned long ucon0, ucon1, ucon2;
 
 	switch (ucon & S3C2440_UCON_CLKMASK) {
 	case S3C2440_UCON_UCLK:
@@ -1308,7 +1440,33 @@
 		break;
 
 	case S3C2440_UCON_FCLK:
-		clk->divisor = 7; /* todo - work out divisor */
+		/* the fun of calculating the uart divisors on
+		 * the s3c2440 */
+
+		ucon0 = __raw_readl(S3C24XX_VA_UART0 + S3C2410_UCON);
+		ucon1 = __raw_readl(S3C24XX_VA_UART1 + S3C2410_UCON);
+		ucon2 = __raw_readl(S3C24XX_VA_UART2 + S3C2410_UCON);
+
+		printk("ucons: %08lx, %08lx, %08lx\n", ucon0, ucon1, ucon2);
+
+		ucon0 &= S3C2440_UCON0_DIVMASK;
+		ucon1 &= S3C2440_UCON1_DIVMASK;
+		ucon2 &= S3C2440_UCON2_DIVMASK;
+
+		if (ucon0 != 0) {
+			clk->divisor = ucon0 >> S3C2440_UCON_DIVSHIFT;
+			clk->divisor += 6;
+		} else if (ucon1 != 0) {
+			clk->divisor = ucon1 >> S3C2440_UCON_DIVSHIFT;
+			clk->divisor += 21;
+		} else if (ucon2 != 0) {
+			clk->divisor = ucon2 >> S3C2440_UCON_DIVSHIFT;
+			clk->divisor += 36;
+		} else {
+			/* manual calims 44, seems to be 9 */
+			clk->divisor = 9;
+		}
+
 		clk->name = "fclk";
 		break;
 	}
@@ -1316,6 +1474,28 @@
 	return 0;
 }
 
+static int s3c2440_serial_resetport(struct uart_port *port,
+				    struct s3c2410_uartcfg *cfg)
+{
+	unsigned long ucon = rd_regl(port, S3C2410_UCON);
+
+	dbg("s3c2440_serial_resetport: port=%p (%08lx), cfg=%p\n",
+	    port, port->mapbase, cfg);
+
+	/* ensure we don't change the clock settings... */
+
+	ucon &= (S3C2440_UCON0_DIVMASK | (3<<10));
+
+	wr_regl(port, S3C2410_UCON,  ucon | cfg->ucon);
+	wr_regl(port, S3C2410_ULCON, cfg->ulcon);
+
+	/* reset both fifos */
+
+	wr_regl(port, S3C2410_UFCON, cfg->ufcon | S3C2410_UFCON_RESETBOTH);
+	wr_regl(port, S3C2410_UFCON, cfg->ufcon);
+
+	return 0;
+}
 
 static struct s3c24xx_uart_info s3c2440_uart_inf = {
 	.name		= "Samsung S3C2440 UART",
@@ -1328,7 +1508,8 @@
 	.tx_fifomask	= S3C2440_UFSTAT_TXMASK,
 	.tx_fifoshift	= S3C2440_UFSTAT_TXSHIFT,
 	.get_clksrc	= s3c2440_serial_getsource,
-	.set_clksrc	= s3c2440_serial_setsource
+	.set_clksrc	= s3c2440_serial_setsource,
+	.reset_port	= s3c2440_serial_resetport,
 };
 
 /* device management */
@@ -1386,6 +1567,7 @@
 		return -1;
 	}
 
+	s3c2400_serial_init();
 	s3c2410_serial_init();
 	s3c2440_serial_init();
 
@@ -1394,6 +1576,7 @@
 
 static void __exit s3c24xx_serial_modexit(void)
 {
+	s3c2400_serial_exit();
 	s3c2410_serial_exit();
 	s3c2440_serial_exit();
 
@@ -1509,7 +1692,7 @@
 
 		clk = clk_get(port->dev, clksrc.name);
 		if (!IS_ERR(clk) && clk != NULL)
-			rate = clk_get_rate(clk);
+			rate = clk_get_rate(clk) / clksrc.divisor;
 		else
 			rate = 1;
 
@@ -1603,7 +1786,6 @@
 	.setup		= s3c24xx_serial_console_setup
 };
 
-
 static int s3c24xx_serial_initconsole(void)
 {
 	struct s3c24xx_uart_info *info;
@@ -1618,7 +1800,9 @@
 		return 0;
 	}
 
-	if (strcmp(dev->name, "s3c2410-uart") == 0) {
+	if (strcmp(dev->name, "s3c2400-uart") == 0) {
+		info = s3c2400_uart_inf_at;
+	} else if (strcmp(dev->name, "s3c2410-uart") == 0) {
 		info = s3c2410_uart_inf_at;
 	} else if (strcmp(dev->name, "s3c2440-uart") == 0) {
 		info = s3c2440_uart_inf_at;
diff -Nru a/drivers/serial/sn_console.c b/drivers/serial/sn_console.c
--- a/drivers/serial/sn_console.c	2005-03-11 12:51:43 -08:00
+++ b/drivers/serial/sn_console.c	2005-03-11 12:51:43 -08:00
@@ -6,7 +6,7 @@
  * driver for that.
  *
  *
- * Copyright (c) 2004 Silicon Graphics, Inc.  All Rights Reserved.
+ * Copyright (c) 2004-2005 Silicon Graphics, Inc.  All Rights Reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of version 2 of the GNU General Public License
@@ -104,6 +104,7 @@
 };
 
 static struct sn_cons_port sal_console_port;
+static int sn_process_input;
 
 /* Only used if USE_DYNAMIC_MINOR is set to 1 */
 static struct miscdevice misc;	/* used with misc_register for dynamic */
@@ -681,7 +682,8 @@
 
 	if (!port->sc_port.irq) {
 		spin_lock_irqsave(&port->sc_port.lock, flags);
-		sn_receive_chars(port, NULL, flags);
+		if (sn_process_input)
+			sn_receive_chars(port, NULL, flags);
 		sn_transmit_chars(port, TRANSMIT_RAW);
 		spin_unlock_irqrestore(&port->sc_port.lock, flags);
 		mod_timer(&port->sc_timer,
@@ -878,6 +880,7 @@
 	if (!IS_RUNNING_ON_SIMULATOR()) {
 		sn_sal_switch_to_interrupts(&sal_console_port);
 	}
+	sn_process_input = 1;
 	return 0;
 }
 
diff -Nru a/drivers/serial/sunsu.c b/drivers/serial/sunsu.c
--- a/drivers/serial/sunsu.c	2005-03-11 12:51:41 -08:00
+++ b/drivers/serial/sunsu.c	2005-03-11 12:51:41 -08:00
@@ -1314,12 +1314,13 @@
 
 		serio->port_data = up;
 
-		serio->type = SERIO_RS232;
+		serio->id.type = SERIO_RS232;
 		if (up->su_type == SU_PORT_KBD) {
-			serio->type |= SERIO_SUNKBD;
+			serio->id.proto = SERIO_SUNKBD;
 			strlcpy(serio->name, "sukbd", sizeof(serio->name));
 		} else {
-			serio->type |= (SERIO_SUN | (1 << 16));
+			serio->id.proto = SERIO_SUN;
+			serio->id.extra = 1;
 			strlcpy(serio->name, "sums", sizeof(serio->name));
 		}
 		strlcpy(serio->phys, (channel == 0 ? "su/serio0" : "su/serio1"),
diff -Nru a/drivers/serial/sunzilog.c b/drivers/serial/sunzilog.c
--- a/drivers/serial/sunzilog.c	2005-03-11 12:51:51 -08:00
+++ b/drivers/serial/sunzilog.c	2005-03-11 12:51:51 -08:00
@@ -1562,12 +1562,13 @@
 
 		serio->port_data = up;
 
-		serio->type = SERIO_RS232;
+		serio->id.type = SERIO_RS232;
 		if (channel == KEYBOARD_LINE) {
-			serio->type |= SERIO_SUNKBD;
+			serio->id.proto = SERIO_SUNKBD;
 			strlcpy(serio->name, "zskbd", sizeof(serio->name));
 		} else {
-			serio->type |= (SERIO_SUN | (1 << 16));
+			serio->id.proto = SERIO_SUN;
+			serio->id.extra = 1;
 			strlcpy(serio->name, "zsms", sizeof(serio->name));
 		}
 		strlcpy(serio->phys,
diff -Nru a/drivers/serial/vr41xx_siu.c b/drivers/serial/vr41xx_siu.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/serial/vr41xx_siu.c	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,1100 @@
+/*
+ *  Driver for NEC VR4100 series Serial Interface Unit.
+ *
+ *  Copyright (C) 2004-2005  Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
+ *
+ *  Based on drivers/serial/8250.c, by Russell King.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#include <linux/config.h>
+
+#if defined(CONFIG_SERIAL_VR41XX_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
+#define SUPPORT_SYSRQ
+#endif
+
+#include <linux/console.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/ioport.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/serial.h>
+#include <linux/serial_core.h>
+#include <linux/serial_reg.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+
+#include <asm/io.h>
+#include <asm/vr41xx/siu.h>
+#include <asm/vr41xx/vr41xx.h>
+
+#define SIU_PORTS_MAX	2
+#define SIU_BAUD_BASE	1152000
+#define SIU_MAJOR	204
+#define SIU_MINOR_BASE	82
+
+#define RX_MAX_COUNT	256
+#define TX_MAX_COUNT	15
+
+#define SIUIRSEL	0x08
+ #define TMICMODE	0x20
+ #define TMICTX		0x10
+ #define IRMSEL		0x0c
+ #define IRMSEL_HP	0x08
+ #define IRMSEL_TEMIC	0x04
+ #define IRMSEL_SHARP	0x00
+ #define IRUSESEL	0x02
+ #define SIRSEL		0x01
+
+struct siu_port {
+	unsigned int type;
+	unsigned int irq;
+	unsigned long start;
+};
+
+static const struct siu_port siu_type1_ports[] = {
+	{	.type		= PORT_VR41XX_SIU,
+		.irq		= SIU_IRQ,
+		.start		= 0x0c000000UL,		},
+};
+
+#define SIU_TYPE1_NR_PORTS	(sizeof(siu_type1_ports) / sizeof(struct siu_port))
+
+static const struct siu_port siu_type2_ports[] = {
+	{	.type		= PORT_VR41XX_SIU,
+		.irq		= SIU_IRQ,
+		.start		= 0x0f000800UL,		},
+	{	.type		= PORT_VR41XX_DSIU,
+		.irq		= DSIU_IRQ,
+		.start		= 0x0f000820UL,		},
+};
+
+#define SIU_TYPE2_NR_PORTS	(sizeof(siu_type2_ports) / sizeof(struct siu_port))
+
+static struct uart_port siu_uart_ports[SIU_PORTS_MAX];
+static uint8_t lsr_break_flag[SIU_PORTS_MAX];
+
+#define siu_read(port, offset)		readb((port)->membase + (offset))
+#define siu_write(port, offset, value)	writeb((value), (port)->membase + (offset))
+
+void vr41xx_select_siu_interface(siu_interface_t interface)
+{
+	struct uart_port *port;
+	unsigned long flags;
+	uint8_t irsel;
+
+	port = &siu_uart_ports[0];
+
+	spin_lock_irqsave(&port->lock, flags);
+
+	irsel = siu_read(port, SIUIRSEL);
+	if (interface == SIU_INTERFACE_IRDA)
+		irsel |= SIRSEL;
+	else
+		irsel &= ~SIRSEL;
+	siu_write(port, SIUIRSEL, irsel);
+
+	spin_unlock_irqrestore(&port->lock, flags);
+}
+
+EXPORT_SYMBOL_GPL(vr41xx_select_siu_interface);
+
+void vr41xx_use_irda(irda_use_t use)
+{
+	struct uart_port *port;
+	unsigned long flags;
+	uint8_t irsel;
+
+	port = &siu_uart_ports[0];
+
+	spin_lock_irqsave(&port->lock, flags);
+
+	irsel = siu_read(port, SIUIRSEL);
+	if (use == FIR_USE_IRDA)
+		irsel |= IRUSESEL;
+	else
+		irsel &= ~IRUSESEL;
+	siu_write(port, SIUIRSEL, irsel);
+
+	spin_unlock_irqrestore(&port->lock, flags);
+}
+
+EXPORT_SYMBOL_GPL(vr41xx_use_irda);
+
+void vr41xx_select_irda_module(irda_module_t module, irda_speed_t speed)
+{
+	struct uart_port *port;
+	unsigned long flags;
+	uint8_t irsel;
+
+	port = &siu_uart_ports[0];
+
+	spin_lock_irqsave(&port->lock, flags);
+
+	irsel = siu_read(port, SIUIRSEL);
+	irsel &= ~(IRMSEL | TMICTX | TMICMODE);
+	switch (module) {
+	case SHARP_IRDA:
+		irsel |= IRMSEL_SHARP;
+		break;
+	case TEMIC_IRDA:
+		irsel |= IRMSEL_TEMIC | TMICMODE;
+		if (speed == IRDA_TX_4MBPS)
+			irsel |= TMICTX;
+		break;
+	case HP_IRDA:
+		irsel |= IRMSEL_HP;
+		break;
+	default:
+		break;
+	}
+	siu_write(port, SIUIRSEL, irsel);
+
+	spin_unlock_irqrestore(&port->lock, flags);
+}
+
+EXPORT_SYMBOL_GPL(vr41xx_select_irda_module);
+
+static inline void siu_clear_fifo(struct uart_port *port)
+{
+	siu_write(port, UART_FCR, UART_FCR_ENABLE_FIFO);
+	siu_write(port, UART_FCR, UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR |
+	                          UART_FCR_CLEAR_XMIT);
+	siu_write(port, UART_FCR, 0);
+}
+
+static inline int siu_probe_ports(void)
+{
+	switch (current_cpu_data.cputype) {
+	case CPU_VR4111:
+	case CPU_VR4121:
+		return SIU_TYPE1_NR_PORTS;
+	case CPU_VR4122:
+	case CPU_VR4131:
+	case CPU_VR4133:
+		return SIU_TYPE2_NR_PORTS;
+	}
+
+	return 0;
+}
+
+static inline unsigned long siu_port_size(struct uart_port *port)
+{
+	switch (port->type) {
+	case PORT_VR41XX_SIU:
+		return 11UL;
+	case PORT_VR41XX_DSIU:
+		return 8UL;
+	}
+
+	return 0;
+}
+
+static inline unsigned int siu_check_type(struct uart_port *port)
+{
+	switch (current_cpu_data.cputype) {
+	case CPU_VR4111:
+	case CPU_VR4121:
+		if (port->line == 0)
+			return PORT_VR41XX_SIU;
+		break;
+	case CPU_VR4122:
+	case CPU_VR4131:
+	case CPU_VR4133:
+		if (port->line == 0)
+			return PORT_VR41XX_SIU;
+		else if (port->line == 1)
+			return PORT_VR41XX_DSIU;
+		break;
+	}
+
+	return PORT_UNKNOWN;
+}
+
+static inline const char *siu_type_name(struct uart_port *port)
+{
+	switch (port->type) {
+	case PORT_VR41XX_SIU:
+		return "SIU";
+	case PORT_VR41XX_DSIU:
+		return "DSIU";
+	}
+
+	return "unknown";
+}
+
+static unsigned int siu_tx_empty(struct uart_port *port)
+{
+	uint8_t lsr;
+
+	lsr = siu_read(port, UART_LSR);
+	if (lsr & UART_LSR_TEMT)
+		return TIOCSER_TEMT;
+
+	return 0;
+}
+
+static void siu_set_mctrl(struct uart_port *port, unsigned int mctrl)
+{
+	uint8_t mcr = 0;
+
+	if (mctrl & TIOCM_DTR)
+		mcr |= UART_MCR_DTR;
+	if (mctrl & TIOCM_RTS)
+		mcr |= UART_MCR_RTS;
+	if (mctrl & TIOCM_OUT1)
+		mcr |= UART_MCR_OUT1;
+	if (mctrl & TIOCM_OUT2)
+		mcr |= UART_MCR_OUT2;
+	if (mctrl & TIOCM_LOOP)
+		mcr |= UART_MCR_LOOP;
+
+	siu_write(port, UART_MCR, mcr);
+}
+
+static unsigned int siu_get_mctrl(struct uart_port *port)
+{
+	uint8_t msr;
+	unsigned int mctrl = 0;
+
+	msr = siu_read(port, UART_MSR);
+	if (msr & UART_MSR_DCD)
+		mctrl |= TIOCM_CAR;
+	if (msr & UART_MSR_RI)
+		mctrl |= TIOCM_RNG;
+	if (msr & UART_MSR_DSR)
+		mctrl |= TIOCM_DSR;
+	if (msr & UART_MSR_CTS)
+		mctrl |= TIOCM_CTS;
+
+	return mctrl;
+}
+
+static void siu_stop_tx(struct uart_port *port, unsigned int tty_stop)
+{
+	unsigned long flags;
+	uint8_t ier;
+
+	spin_lock_irqsave(&port->lock, flags);
+
+	ier = siu_read(port, UART_IER);
+	ier &= ~UART_IER_THRI;
+	siu_write(port, UART_IER, ier);
+
+	spin_unlock_irqrestore(&port->lock, flags);
+}
+
+static void siu_start_tx(struct uart_port *port, unsigned int tty_start)
+{
+	unsigned long flags;
+	uint8_t ier;
+
+	spin_lock_irqsave(&port->lock, flags);
+
+	ier = siu_read(port, UART_IER);
+	ier |= UART_IER_THRI;
+	siu_write(port, UART_IER, ier);
+
+	spin_unlock_irqrestore(&port->lock, flags);
+}
+
+static void siu_stop_rx(struct uart_port *port)
+{
+	unsigned long flags;
+	uint8_t ier;
+
+	spin_lock_irqsave(&port->lock, flags);
+
+	ier = siu_read(port, UART_IER);
+	ier &= ~UART_IER_RLSI;
+	siu_write(port, UART_IER, ier);
+
+	port->read_status_mask &= ~UART_LSR_DR;
+
+	spin_unlock_irqrestore(&port->lock, flags);
+}
+
+static void siu_enable_ms(struct uart_port *port)
+{
+	unsigned long flags;
+	uint8_t ier;
+
+	spin_lock_irqsave(&port->lock, flags);
+
+	ier = siu_read(port, UART_IER);
+	ier |= UART_IER_MSI;
+	siu_write(port, UART_IER, ier);
+
+	spin_unlock_irqrestore(&port->lock, flags);
+}
+
+static void siu_break_ctl(struct uart_port *port, int ctl)
+{
+	unsigned long flags;
+	uint8_t lcr;
+
+	spin_lock_irqsave(&port->lock, flags);
+
+	lcr = siu_read(port, UART_LCR);
+	if (ctl == -1)
+		lcr |= UART_LCR_SBC;
+	else
+		lcr &= ~UART_LCR_SBC;
+	siu_write(port, UART_LCR, lcr);
+
+	spin_unlock_irqrestore(&port->lock, flags);
+}
+
+static inline void receive_chars(struct uart_port *port, uint8_t *status,
+                                 struct pt_regs *regs)
+{
+	struct tty_struct *tty;
+	uint8_t lsr, ch;
+	char flag;
+	int max_count = RX_MAX_COUNT;
+
+	tty = port->info->tty;
+	lsr = *status;
+
+	do {
+		if (unlikely(tty->flip.count >= TTY_FLIPBUF_SIZE)) {
+			if (tty->low_latency)
+				tty_flip_buffer_push(tty);
+		}
+
+		ch = siu_read(port, UART_RX);
+		port->icount.rx++;
+		flag = TTY_NORMAL;
+
+#ifdef CONFIG_SERIAL_VR41XX_CONSOLE
+		lsr |= lsr_break_flag[port->line];
+		lsr_break_flag[port->line] = 0;
+#endif
+		if (unlikely(lsr & (UART_LSR_BI | UART_LSR_FE |
+		                    UART_LSR_PE | UART_LSR_OE))) {
+			if (lsr & UART_LSR_BI) {
+				lsr &= ~(UART_LSR_FE | UART_LSR_PE);
+				port->icount.brk++;
+
+				if (uart_handle_break(port))
+					goto ignore_char;
+			}
+
+			if (lsr & UART_LSR_FE)
+				port->icount.frame++;
+			if (lsr & UART_LSR_PE)
+				port->icount.parity++;
+			if (lsr & UART_LSR_OE)
+				port->icount.overrun++;
+
+			lsr &= port->read_status_mask;
+			if (lsr & UART_LSR_BI)
+				flag = TTY_BREAK;
+			if (lsr & UART_LSR_FE)
+				flag = TTY_FRAME;
+			if (lsr & UART_LSR_PE)
+				flag = TTY_PARITY;
+		}
+
+		if (uart_handle_sysrq_char(port, ch, regs))
+			goto ignore_char;
+		if ((lsr & port->ignore_status_mask) == 0)
+			tty_insert_flip_char(tty, ch, flag);
+		if ((lsr & UART_LSR_OE) && (tty->flip.count < TTY_FLIPBUF_SIZE))
+			tty_insert_flip_char(tty, 0, TTY_OVERRUN);
+
+	ignore_char:
+		lsr = siu_read(port, UART_LSR);
+	} while ((lsr & UART_LSR_DR) && (max_count-- > 0));
+
+	tty_flip_buffer_push(tty);
+
+	*status = lsr;
+}
+
+static inline void check_modem_status(struct uart_port *port)
+{
+	uint8_t msr;
+
+	msr = siu_read(port, UART_MSR);
+	if ((msr & UART_MSR_ANY_DELTA) == 0)
+		return;
+	if (msr & UART_MSR_DDCD)
+		uart_handle_dcd_change(port, msr & UART_MSR_DCD);
+	if (msr & UART_MSR_TERI)
+		port->icount.rng++;
+	if (msr & UART_MSR_DDSR)
+		port->icount.dsr++;
+	if (msr & UART_MSR_DCTS)
+		uart_handle_cts_change(port, msr & UART_MSR_CTS);
+
+	wake_up_interruptible(&port->info->delta_msr_wait);
+}
+
+static inline void transmit_chars(struct uart_port *port)
+{
+	struct circ_buf *xmit;
+	int max_count = TX_MAX_COUNT;
+
+	xmit = &port->info->xmit;
+
+	if (port->x_char) {
+		siu_write(port, UART_TX, port->x_char);
+		port->icount.tx++;
+		port->x_char = 0;
+		return;
+	}
+
+	if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
+		siu_stop_tx(port, 0);
+		return;
+	}
+
+	do {
+		siu_write(port, UART_TX, xmit->buf[xmit->tail]);
+		xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
+		port->icount.tx++;
+		if (uart_circ_empty(xmit))
+			break;
+	} while (max_count-- > 0);
+
+	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+		uart_write_wakeup(port);
+
+	if (uart_circ_empty(xmit))
+		siu_stop_tx(port, 0);
+}
+
+static irqreturn_t siu_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+	struct uart_port *port;
+	uint8_t iir, lsr;
+
+	if (dev_id == NULL)
+		return IRQ_NONE;
+
+	port = (struct uart_port *)dev_id;
+
+	iir = siu_read(port, UART_IIR);
+	if (iir & UART_IIR_NO_INT)
+		return IRQ_NONE;
+
+	lsr = siu_read(port, UART_LSR);
+	if (lsr & UART_LSR_DR)
+		receive_chars(port, &lsr, regs);
+
+	check_modem_status(port);
+
+	if (lsr & UART_LSR_THRE)
+		transmit_chars(port);
+
+	return IRQ_HANDLED;
+}
+
+static int siu_startup(struct uart_port *port)
+{
+	int retval;
+
+	siu_clear_fifo(port);
+
+	(void)siu_read(port, UART_LSR);
+	(void)siu_read(port, UART_RX);
+	(void)siu_read(port, UART_IIR);
+	(void)siu_read(port, UART_MSR);
+
+	if (siu_read(port, UART_LSR) == 0xff)
+		return -ENODEV;
+
+	retval = request_irq(port->irq, siu_interrupt, 0, siu_type_name(port), port);
+	if (retval)
+		return retval;
+
+	if (port->type == PORT_VR41XX_DSIU)
+		vr41xx_enable_dsiuint(DSIUINT_ALL);
+
+	siu_write(port, UART_LCR, UART_LCR_WLEN8);
+
+	spin_lock_irq(&port->lock);
+	siu_set_mctrl(port, port->mctrl);
+	spin_unlock_irq(&port->lock);
+
+	siu_write(port, UART_IER, UART_IER_RLSI | UART_IER_RDI);
+
+	(void)siu_read(port, UART_LSR);
+	(void)siu_read(port, UART_RX);
+	(void)siu_read(port, UART_IIR);
+	(void)siu_read(port, UART_MSR);
+
+	return 0;
+}
+
+static void siu_shutdown(struct uart_port *port)
+{
+	unsigned long flags;
+	uint8_t lcr;
+
+	if (port->membase == NULL)
+		return;
+
+	siu_write(port, UART_IER, 0);
+
+	spin_lock_irqsave(&port->lock, flags);
+
+	port->mctrl &= ~TIOCM_OUT2;
+	siu_set_mctrl(port, port->mctrl);
+
+	spin_unlock_irqrestore(&port->lock, flags);
+
+	lcr = siu_read(port, UART_LCR);
+	lcr &= ~UART_LCR_SBC;
+	siu_write(port, UART_LCR, lcr);
+
+	siu_clear_fifo(port);
+
+	(void)siu_read(port, UART_RX);
+
+	if (port->type == PORT_VR41XX_DSIU)
+		vr41xx_disable_dsiuint(DSIUINT_ALL);
+
+	free_irq(port->irq, port);
+}
+
+static void siu_set_termios(struct uart_port *port, struct termios *new,
+                            struct termios *old)
+{
+	tcflag_t c_cflag, c_iflag;
+	uint8_t lcr, fcr, ier;
+	unsigned int baud, quot;
+	unsigned long flags;
+
+	c_cflag = new->c_cflag;
+	switch (c_cflag & CSIZE) {
+	case CS5:
+		lcr = UART_LCR_WLEN5;
+		break;
+	case CS6:
+		lcr = UART_LCR_WLEN6;
+		break;
+	case CS7:
+		lcr = UART_LCR_WLEN7;
+		break;
+	default:
+		lcr = UART_LCR_WLEN8;
+		break;
+	}
+
+	if (c_cflag & CSTOPB)
+		lcr |= UART_LCR_STOP;
+	if (c_cflag & PARENB)
+		lcr |= UART_LCR_PARITY;
+	if ((c_cflag & PARODD) != PARODD)
+		lcr |= UART_LCR_EPAR;
+	if (c_cflag & CMSPAR)
+		lcr |= UART_LCR_SPAR;
+
+	baud = uart_get_baud_rate(port, new, old, 0, port->uartclk/16);
+	quot = uart_get_divisor(port, baud);
+
+	fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10;
+
+	spin_lock_irqsave(&port->lock, flags);
+
+	uart_update_timeout(port, c_cflag, baud);
+
+	c_iflag = new->c_iflag;
+
+	port->read_status_mask = UART_LSR_THRE | UART_LSR_OE | UART_LSR_DR;
+	if (c_iflag & INPCK)
+		port->read_status_mask |= UART_LSR_FE | UART_LSR_PE;
+	if (c_iflag & (BRKINT | PARMRK))
+		port->read_status_mask |= UART_LSR_BI;
+
+	port->ignore_status_mask = 0;
+	if (c_iflag & IGNPAR)
+		port->ignore_status_mask |= UART_LSR_FE | UART_LSR_PE;
+	if (c_iflag & IGNBRK) {
+		port->ignore_status_mask |= UART_LSR_BI;
+		if (c_iflag & IGNPAR)
+			port->ignore_status_mask |= UART_LSR_OE;
+	}
+
+	if ((c_cflag & CREAD) == 0)
+		port->ignore_status_mask |= UART_LSR_DR;
+
+	ier = siu_read(port, UART_IER);
+	ier &= ~UART_IER_MSI;
+	if (UART_ENABLE_MS(port, c_cflag))
+		ier |= UART_IER_MSI;
+	siu_write(port, UART_IER, ier);
+
+	siu_write(port, UART_LCR, lcr | UART_LCR_DLAB);
+
+	siu_write(port, UART_DLL, (uint8_t)quot);
+	siu_write(port, UART_DLM, (uint8_t)(quot >> 8));
+
+	siu_write(port, UART_LCR, lcr);
+
+	siu_write(port, UART_FCR, fcr);
+
+	siu_set_mctrl(port, port->mctrl);
+
+	spin_unlock_irqrestore(&port->lock, flags);
+}
+
+static void siu_pm(struct uart_port *port, unsigned int state, unsigned int oldstate)
+{
+	switch (state) {
+	case 0:
+		switch (port->type) {
+		case PORT_VR41XX_SIU:
+			vr41xx_supply_clock(SIU_CLOCK);
+			break;
+		case PORT_VR41XX_DSIU:
+			vr41xx_supply_clock(DSIU_CLOCK);
+			break;
+		}
+		break;
+	case 3:
+		switch (port->type) {
+		case PORT_VR41XX_SIU:
+			vr41xx_mask_clock(SIU_CLOCK);
+			break;
+		case PORT_VR41XX_DSIU:
+			vr41xx_mask_clock(DSIU_CLOCK);
+			break;
+		}
+		break;
+	}
+}
+
+static const char *siu_type(struct uart_port *port)
+{
+	return siu_type_name(port);
+}
+
+static void siu_release_port(struct uart_port *port)
+{
+	unsigned long size;
+
+	if (port->flags	& UPF_IOREMAP) {
+		iounmap(port->membase);
+		port->membase = NULL;
+	}
+
+	size = siu_port_size(port);
+	release_mem_region(port->mapbase, size);
+}
+
+static int siu_request_port(struct uart_port *port)
+{
+	unsigned long size;
+	struct resource *res;
+
+	size = siu_port_size(port);
+	res = request_mem_region(port->mapbase, size, siu_type_name(port));
+	if (res == NULL)
+		return -EBUSY;
+
+	if (port->flags & UPF_IOREMAP) {
+		port->membase = ioremap(port->mapbase, size);
+		if (port->membase == NULL) {
+			release_resource(res);
+			return -ENOMEM;
+		}
+	}
+
+	return 0;
+}
+
+static void siu_config_port(struct uart_port *port, int flags)
+{
+	if (flags & UART_CONFIG_TYPE) {
+		port->type = siu_check_type(port);
+		(void)siu_request_port(port);
+	}
+}
+
+static int siu_verify_port(struct uart_port *port, struct serial_struct *serial)
+{
+	if (port->type != PORT_VR41XX_SIU && port->type != PORT_VR41XX_DSIU)
+		return -EINVAL;
+	if (port->irq != serial->irq)
+		return -EINVAL;
+	if (port->iotype != serial->io_type)
+		return -EINVAL;
+	if (port->mapbase != (unsigned long)serial->iomem_base)
+		return -EINVAL;
+
+	return 0;
+}
+
+static struct uart_ops siu_uart_ops = {
+	.tx_empty	= siu_tx_empty,
+	.set_mctrl	= siu_set_mctrl,
+	.get_mctrl	= siu_get_mctrl,
+	.stop_tx	= siu_stop_tx,
+	.start_tx	= siu_start_tx,
+	.stop_rx	= siu_stop_rx,
+	.enable_ms	= siu_enable_ms,
+	.break_ctl	= siu_break_ctl,
+	.startup	= siu_startup,
+	.shutdown	= siu_shutdown,
+	.set_termios	= siu_set_termios,
+	.pm		= siu_pm,
+	.type		= siu_type,
+	.release_port	= siu_release_port,
+	.request_port	= siu_request_port,
+	.config_port	= siu_config_port,
+	.verify_port	= siu_verify_port,
+};
+
+static int siu_init_ports(void)
+{
+	const struct siu_port *siu;
+	struct uart_port *port;
+	int i, num;
+
+	switch (current_cpu_data.cputype) {
+	case CPU_VR4111:
+	case CPU_VR4121:
+		siu = siu_type1_ports;
+		break;
+	case CPU_VR4122:
+	case CPU_VR4131:
+	case CPU_VR4133:
+		siu = siu_type2_ports;
+		break;
+	default:
+		return 0;
+	}
+
+	port = siu_uart_ports;
+	num = siu_probe_ports();
+	for (i = 0; i < num; i++) {
+		spin_lock_init(&port->lock);
+		port->irq = siu->irq;
+		port->uartclk = SIU_BAUD_BASE * 16;
+		port->fifosize = 16;
+		port->regshift = 0;
+		port->iotype = UPIO_MEM;
+		port->flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF;
+		port->type = siu->type;
+		port->line = i;
+		port->mapbase = siu->start;
+		siu++;
+		port++;
+	}
+
+	return num;
+}
+
+#ifdef CONFIG_SERIAL_VR41XX_CONSOLE
+
+static void early_set_termios(struct uart_port *port, struct termios *new,
+                              struct termios *old)
+{
+	tcflag_t c_cflag;
+	uint8_t lcr;
+	unsigned int baud, quot;
+
+	c_cflag = new->c_cflag;
+	switch (c_cflag & CSIZE) {
+	case CS5:
+		lcr = UART_LCR_WLEN5;
+		break;
+	case CS6:
+		lcr = UART_LCR_WLEN6;
+		break;
+	case CS7:
+		lcr = UART_LCR_WLEN7;
+		break;
+	default:
+		lcr = UART_LCR_WLEN8;
+		break;
+	}
+
+	if (c_cflag & CSTOPB)
+		lcr |= UART_LCR_STOP;
+	if (c_cflag & PARENB)
+		lcr |= UART_LCR_PARITY;
+	if ((c_cflag & PARODD) != PARODD)
+		lcr |= UART_LCR_EPAR;
+	if (c_cflag & CMSPAR)
+		lcr |= UART_LCR_SPAR;
+
+	baud = uart_get_baud_rate(port, new, old, 0, port->uartclk/16);
+	quot = uart_get_divisor(port, baud);
+
+	siu_write(port, UART_LCR, lcr | UART_LCR_DLAB);
+
+	siu_write(port, UART_DLL, (uint8_t)quot);
+	siu_write(port, UART_DLM, (uint8_t)(quot >> 8));
+
+	siu_write(port, UART_LCR, lcr);
+}
+
+static struct uart_ops early_uart_ops = {
+	.set_termios	= early_set_termios,
+};
+
+#define BOTH_EMPTY	(UART_LSR_TEMT | UART_LSR_THRE)
+
+static void wait_for_xmitr(struct uart_port *port)
+{
+	int timeout = 10000;
+	uint8_t lsr, msr;
+
+	do {
+		lsr = siu_read(port, UART_LSR);
+		if (lsr & UART_LSR_BI)
+			lsr_break_flag[port->line] = UART_LSR_BI;
+
+		if ((lsr & BOTH_EMPTY) == BOTH_EMPTY)
+			break;
+	} while (timeout-- > 0);
+
+	if (port->flags & UPF_CONS_FLOW) {
+		timeout = 1000000;
+
+		do {
+			msr = siu_read(port, UART_MSR);
+			if ((msr & UART_MSR_CTS) != 0)
+				break;
+		} while (timeout-- > 0);
+	}
+}
+
+static void siu_console_write(struct console *con, const char *s, unsigned count)
+{
+	struct uart_port *port;
+	uint8_t ier;
+	unsigned i;
+
+	port = &siu_uart_ports[con->index];
+
+	ier = siu_read(port, UART_IER);
+	siu_write(port, UART_IER, 0);
+
+	for (i = 0; i < count && *s != '\0'; i++, s++) {
+		wait_for_xmitr(port);
+		siu_write(port, UART_TX, *s);
+		if (*s == '\n') {
+			wait_for_xmitr(port);
+			siu_write(port, UART_TX, '\r');
+		}
+	}
+
+	wait_for_xmitr(port);
+	siu_write(port, UART_IER, ier);
+}
+
+static int siu_console_setup(struct console *con, char *options)
+{
+	struct uart_port *port;
+	int baud = 9600;
+	int parity = 'n';
+	int bits = 8;
+	int flow = 'n';
+
+	if (con->index >= SIU_PORTS_MAX)
+		con->index = 0;
+
+	port = &siu_uart_ports[con->index];
+	if (port->membase == NULL) {
+		if (port->mapbase == 0)
+			return -ENODEV;
+		port->membase = (unsigned char __iomem *)KSEG1ADDR(port->mapbase);
+	}
+
+	vr41xx_select_siu_interface(SIU_INTERFACE_RS232C);
+
+	if (options != NULL)
+		uart_parse_options(options, &baud, &parity, &bits, &flow);
+
+	return uart_set_options(port, con, baud, parity, bits, flow);
+}
+
+static struct uart_driver siu_uart_driver;
+
+static struct console siu_console = {
+	.name	= "ttyVR",
+	.write	= siu_console_write,
+	.device	= uart_console_device,
+	.setup	= siu_console_setup,
+	.flags	= CON_PRINTBUFFER,
+	.index	= -1,
+	.data	= &siu_uart_driver,
+};
+
+static int __devinit siu_console_init(void)
+{
+	struct uart_port *port;
+	int num, i;
+
+	num = siu_init_ports();
+	if (num <= 0)
+		return -ENODEV;
+
+	for (i = 0; i < num; i++) {
+		port = &siu_uart_ports[i];
+		port->ops = &early_uart_ops;
+	}
+
+	register_console(&siu_console);
+
+	return 0;
+}
+
+console_initcall(siu_console_init);
+
+#define SERIAL_VR41XX_CONSOLE	&siu_console
+#else
+#define SERIAL_VR41XX_CONSOLE	NULL
+#endif
+
+static struct uart_driver siu_uart_driver = {
+	.owner		= THIS_MODULE,
+	.driver_name	= "SIU",
+	.dev_name	= "ttyVR",
+	.devfs_name	= "ttvr/",
+	.major		= SIU_MAJOR,
+	.minor		= SIU_MINOR_BASE,
+	.cons		= SERIAL_VR41XX_CONSOLE,
+};
+
+static int siu_probe(struct device *dev)
+{
+	struct uart_port *port;
+	int num, i, retval;
+
+	num = siu_init_ports();
+	if (num <= 0)
+		return -ENODEV;
+
+	siu_uart_driver.nr = num;
+	retval = uart_register_driver(&siu_uart_driver);
+	if (retval)
+		return retval;
+
+	for (i = 0; i < num; i++) {
+		port = &siu_uart_ports[i];
+		port->ops = &siu_uart_ops;
+		port->dev = dev;
+
+		retval = uart_add_one_port(&siu_uart_driver, port);
+		if (retval)
+			break;
+	}
+
+	if (i == 0 && retval < 0) {
+		uart_unregister_driver(&siu_uart_driver);
+		return retval;
+	}
+
+	return 0;
+}
+
+static int siu_remove(struct device *dev)
+{
+	struct uart_port *port;
+	int i;
+
+	for (i = 0; i < siu_uart_driver.nr; i++) {
+		port = &siu_uart_ports[i];
+		if (port->dev == dev) {
+			uart_remove_one_port(&siu_uart_driver, port);
+			port->dev = NULL;
+		}
+	}
+
+	uart_unregister_driver(&siu_uart_driver);
+
+	return 0;
+}
+
+static int siu_suspend(struct device *dev, u32 state, u32 level)
+{
+	struct uart_port *port;
+	int i;
+
+	if (level != SUSPEND_DISABLE)
+		return 0;
+
+	for (i = 0; i < siu_uart_driver.nr; i++) {
+		port = &siu_uart_ports[i];
+		if ((port->type == PORT_VR41XX_SIU ||
+		     port->type == PORT_VR41XX_DSIU) && port->dev == dev)
+			uart_suspend_port(&siu_uart_driver, port);
+
+	}
+
+	return 0;
+}
+
+static int siu_resume(struct device *dev, u32 level)
+{
+	struct uart_port *port;
+	int i;
+
+	if (level != RESUME_ENABLE)
+		return 0;
+
+	for (i = 0; i < siu_uart_driver.nr; i++) {
+		port = &siu_uart_ports[i];
+		if ((port->type == PORT_VR41XX_SIU ||
+		     port->type == PORT_VR41XX_DSIU) && port->dev == dev)
+			uart_resume_port(&siu_uart_driver, port);
+	}
+
+	return 0;
+}
+
+static struct platform_device *siu_platform_device;
+
+static struct device_driver siu_device_driver = {
+	.name		= "SIU",
+	.bus		= &platform_bus_type,
+	.probe		= siu_probe,
+	.remove		= siu_remove,
+	.suspend	= siu_suspend,
+	.resume		= siu_resume,
+};
+
+static int __devinit vr41xx_siu_init(void)
+{
+	int retval;
+
+	siu_platform_device = platform_device_register_simple("SIU", -1, NULL, 0);
+	if (IS_ERR(siu_platform_device))
+		return PTR_ERR(siu_platform_device);
+
+	retval = driver_register(&siu_device_driver);
+	if (retval < 0)
+		platform_device_unregister(siu_platform_device);
+
+	return retval;
+}
+
+static void __devexit vr41xx_siu_exit(void)
+{
+	driver_unregister(&siu_device_driver);
+
+	platform_device_unregister(siu_platform_device);
+}
+
+module_init(vr41xx_siu_init);
+module_exit(vr41xx_siu_exit);
diff -Nru a/drivers/sh/Makefile b/drivers/sh/Makefile
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/sh/Makefile	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,6 @@
+#
+# Makefile for the SuperH specific drivers.
+#
+
+obj-$(CONFIG_SUPERHYWAY) += superhyway/
+
diff -Nru a/drivers/sh/superhyway/Makefile b/drivers/sh/superhyway/Makefile
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/sh/superhyway/Makefile	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,7 @@
+#
+# Makefile for the SuperHyway bus drivers.
+#
+
+obj-$(CONFIG_SUPERHYWAY)	+= superhyway.o
+obj-$(CONFIG_SYSFS)		+= superhyway-sysfs.o
+
diff -Nru a/drivers/sh/superhyway/superhyway-sysfs.c b/drivers/sh/superhyway/superhyway-sysfs.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/sh/superhyway/superhyway-sysfs.c	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,45 @@
+/*
+ * drivers/sh/superhyway/superhyway-sysfs.c
+ *
+ * SuperHyway Bus sysfs interface
+ *
+ * Copyright (C) 2004, 2005  Paul Mundt <lethal@linux-sh.org>
+ *
+ * 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/device.h>
+#include <linux/types.h>
+#include <linux/superhyway.h>
+
+#define superhyway_ro_attr(name, fmt, field)				\
+static ssize_t name##_show(struct device *dev, char *buf)		\
+{									\
+	struct superhyway_device *s = to_superhyway_device(dev);	\
+	return sprintf(buf, fmt, s->field);				\
+}
+
+/* VCR flags */
+superhyway_ro_attr(perr_flags, "0x%02x\n", vcr.perr_flags);
+superhyway_ro_attr(merr_flags, "0x%02x\n", vcr.merr_flags);
+superhyway_ro_attr(mod_vers, "0x%04x\n", vcr.mod_vers);
+superhyway_ro_attr(mod_id, "0x%04x\n", vcr.mod_id);
+superhyway_ro_attr(bot_mb, "0x%02x\n", vcr.bot_mb);
+superhyway_ro_attr(top_mb, "0x%02x\n", vcr.top_mb);
+
+/* Misc */
+superhyway_ro_attr(resource, "0x%08lx\n", resource.start);
+
+struct device_attribute superhyway_dev_attrs[] = {
+	__ATTR_RO(perr_flags),
+	__ATTR_RO(merr_flags),
+	__ATTR_RO(mod_vers),
+	__ATTR_RO(mod_id),
+	__ATTR_RO(bot_mb),
+	__ATTR_RO(top_mb),
+	__ATTR_RO(resource),
+	__ATTR_NULL,
+};
+
diff -Nru a/drivers/sh/superhyway/superhyway.c b/drivers/sh/superhyway/superhyway.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/sh/superhyway/superhyway.c	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,201 @@
+/*
+ * drivers/sh/superhyway/superhyway.c
+ *
+ * SuperHyway Bus Driver
+ *
+ * Copyright (C) 2004, 2005  Paul Mundt <lethal@linux-sh.org>
+ *
+ * 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/device.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/list.h>
+#include <linux/superhyway.h>
+
+static int superhyway_devices;
+
+static struct device superhyway_bus_device = {
+	.bus_id = "superhyway",
+};
+
+static void superhyway_device_release(struct device *dev)
+{
+	kfree(to_superhyway_device(dev));
+}
+
+/**
+ * superhyway_add_device - Add a SuperHyway module
+ * @mod_id: Module ID (taken from MODULE.VCR.MOD_ID).
+ * @base: Physical address where module is mapped.
+ * @vcr: VCR value.
+ *
+ * This is responsible for adding a new SuperHyway module. This sets up a new
+ * struct superhyway_device for the module being added. Each one of @mod_id,
+ * @base, and @vcr are registered with the new device for further use
+ * elsewhere.
+ *
+ * Devices are initially added in the order that they are scanned (from the
+ * top-down of the memory map), and are assigned an ID based on the order that
+ * they are added. Any manual addition of a module will thus get the ID after
+ * the devices already discovered regardless of where it resides in memory.
+ *
+ * Further work can and should be done in superhyway_scan_bus(), to be sure
+ * that any new modules are properly discovered and subsequently registered.
+ */
+int superhyway_add_device(unsigned int mod_id, unsigned long base,
+			  unsigned long long vcr)
+{
+	struct superhyway_device *dev;
+
+	dev = kmalloc(sizeof(struct superhyway_device), GFP_KERNEL);
+	if (!dev)
+		return -ENOMEM;
+
+	memset(dev, 0, sizeof(struct superhyway_device));
+
+	dev->id.id = mod_id;
+	sprintf(dev->name, "SuperHyway device %04x", dev->id.id);
+
+	dev->vcr		= *((struct vcr_info *)(&vcr));
+	dev->resource.name	= dev->name;
+	dev->resource.start	= base;
+	dev->resource.end	= dev->resource.start + 0x01000000;
+	dev->dev.parent		= &superhyway_bus_device;
+	dev->dev.bus		= &superhyway_bus_type;
+	dev->dev.release	= superhyway_device_release;
+
+	sprintf(dev->dev.bus_id, "%02x", superhyway_devices);
+
+	superhyway_devices++;
+
+	return device_register(&dev->dev);
+}
+
+static int __init superhyway_init(void)
+{
+	device_register(&superhyway_bus_device);
+	return superhyway_scan_bus();
+}
+
+postcore_initcall(superhyway_init);
+
+static const struct superhyway_device_id *
+superhyway_match_id(const struct superhyway_device_id *ids,
+		    struct superhyway_device *dev)
+{
+	while (ids->id) {
+		if (ids->id == dev->id.id)
+			return ids;
+
+		ids++;
+	}
+
+	return NULL;
+}
+
+static int superhyway_device_probe(struct device *dev)
+{
+	struct superhyway_device *shyway_dev = to_superhyway_device(dev);
+	struct superhyway_driver *shyway_drv = to_superhyway_driver(dev->driver);
+
+	if (shyway_drv && shyway_drv->probe) {
+		const struct superhyway_device_id *id;
+
+		id = superhyway_match_id(shyway_drv->id_table, shyway_dev);
+		if (id)
+			return shyway_drv->probe(shyway_dev, id);
+	}
+
+	return -ENODEV;
+}
+
+static int superhyway_device_remove(struct device *dev)
+{
+	struct superhyway_device *shyway_dev = to_superhyway_device(dev);
+	struct superhyway_driver *shyway_drv = to_superhyway_driver(dev->driver);
+
+	if (shyway_drv && shyway_drv->remove) {
+		shyway_drv->remove(shyway_dev);
+		return 0;
+	}
+
+	return -ENODEV;
+}
+
+/**
+ * superhyway_register_driver - Register a new SuperHyway driver
+ * @drv: SuperHyway driver to register.
+ *
+ * This registers the passed in @drv. Any devices matching the id table will
+ * automatically be populated and handed off to the driver's specified probe
+ * routine.
+ */
+int superhyway_register_driver(struct superhyway_driver *drv)
+{
+	drv->drv.name	= drv->name;
+	drv->drv.bus	= &superhyway_bus_type;
+	drv->drv.probe	= superhyway_device_probe;
+	drv->drv.remove	= superhyway_device_remove;
+
+	return driver_register(&drv->drv);
+}
+
+/**
+ * superhyway_unregister_driver - Unregister a SuperHyway driver
+ * @drv: SuperHyway driver to unregister.
+ *
+ * This cleans up after superhyway_register_driver(), and should be invoked in
+ * the exit path of any module drivers.
+ */
+void superhyway_unregister_driver(struct superhyway_driver *drv)
+{
+	driver_unregister(&drv->drv);
+}
+
+static int superhyway_bus_match(struct device *dev, struct device_driver *drv)
+{
+	struct superhyway_device *shyway_dev = to_superhyway_device(dev);
+	struct superhyway_driver *shyway_drv = to_superhyway_driver(drv);
+	const struct superhyway_device_id *ids = shyway_drv->id_table;
+
+	if (!ids)
+		return -EINVAL;
+	if (superhyway_match_id(ids, shyway_dev))
+		return 1;
+
+	return -ENODEV;
+}
+
+struct bus_type superhyway_bus_type = {
+	.name		= "superhyway",
+	.match		= superhyway_bus_match,
+#ifdef CONFIG_SYSFS
+	.dev_attrs	= superhyway_dev_attrs,
+#endif
+};
+
+static int __init superhyway_bus_init(void)
+{
+	return bus_register(&superhyway_bus_type);
+}
+
+static void __exit superhyway_bus_exit(void)
+{
+	device_unregister(&superhyway_bus_device);
+	bus_unregister(&superhyway_bus_type);
+}
+
+core_initcall(superhyway_bus_init);
+module_exit(superhyway_bus_exit);
+
+EXPORT_SYMBOL(superhyway_bus_type);
+EXPORT_SYMBOL(superhyway_add_device);
+EXPORT_SYMBOL(superhyway_register_driver);
+EXPORT_SYMBOL(superhyway_unregister_driver);
+
+MODULE_LICENSE("GPL");
diff -Nru a/drivers/sn/Makefile b/drivers/sn/Makefile
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/sn/Makefile	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,6 @@
+#
+# Makefile for the Altix device drivers.
+#
+#
+
+obj-$(CONFIG_BLK_DEV_SGIIOC4) += ioc4.o
diff -Nru a/drivers/sn/ioc4.c b/drivers/sn/ioc4.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/sn/ioc4.c	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,65 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2005 Silicon Graphics, Inc.  All Rights Reserved.
+ */
+
+/*
+ * This file contains a shim driver for the IOC4 IDE and serial drivers.
+ */
+
+#include <linux/errno.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/ioc4_common.h>
+#include <linux/ide.h>
+
+
+static int __devinit
+ioc4_probe_one(struct pci_dev *pdev, const struct pci_device_id *pci_id)
+{
+	int ret;
+
+	if ((ret = pci_enable_device(pdev))) {
+		printk(KERN_WARNING
+			 "%s: Failed to enable device with "
+				"pci_dev 0x%p... returning\n",
+				__FUNCTION__, (void *)pdev);
+		return ret;
+	}
+	pci_set_master(pdev);
+
+	/* attach each sub-device */
+	ret = ioc4_ide_attach_one(pdev, pci_id);
+	if (ret)
+		return ret;
+	return ioc4_serial_attach_one(pdev, pci_id);
+}
+
+/* pci device struct */
+static struct pci_device_id ioc4_s_id_table[] = {
+	{PCI_VENDOR_ID_SGI, PCI_DEVICE_ID_SGI_IOC4, PCI_ANY_ID,
+	 PCI_ANY_ID, 0x0b4000, 0xFFFFFF},
+	{0}
+};
+MODULE_DEVICE_TABLE(pci, ioc4_s_id_table);
+
+static struct pci_driver __devinitdata ioc4_s_driver = {
+	.name	= "IOC4",
+	.id_table = ioc4_s_id_table,
+	.probe	= ioc4_probe_one,
+};
+
+static int __devinit ioc4_detect(void)
+{
+	ioc4_serial_init();
+
+	return pci_register_driver(&ioc4_s_driver);
+}
+module_init(ioc4_detect);
+
+MODULE_AUTHOR("Pat Gefre - Silicon Graphics Inc. (SGI) <pfg@sgi.com>");
+MODULE_DESCRIPTION("PCI driver module for SGI IOC4 Base-IO Card");
+MODULE_LICENSE("GPL");
diff -Nru a/drivers/usb/Kconfig b/drivers/usb/Kconfig
--- a/drivers/usb/Kconfig	2005-03-11 12:51:41 -08:00
+++ b/drivers/usb/Kconfig	2005-03-11 12:51:41 -08:00
@@ -56,6 +56,8 @@
 
 source "drivers/usb/net/Kconfig"
 
+source "drivers/usb/mon/Kconfig"
+
 comment "USB port drivers"
 	depends on USB
 
diff -Nru a/drivers/usb/Makefile b/drivers/usb/Makefile
--- a/drivers/usb/Makefile	2005-03-11 12:51:51 -08:00
+++ b/drivers/usb/Makefile	2005-03-11 12:51:51 -08:00
@@ -6,6 +6,8 @@
 
 obj-$(CONFIG_USB)		+= core/
 
+obj-$(CONFIG_USB_MON)		+= mon/
+
 obj-$(CONFIG_USB_EHCI_HCD)	+= host/
 obj-$(CONFIG_USB_OHCI_HCD)	+= host/
 obj-$(CONFIG_USB_UHCI_HCD)	+= host/
diff -Nru a/drivers/usb/atm/speedtch.c b/drivers/usb/atm/speedtch.c
--- a/drivers/usb/atm/speedtch.c	2005-03-11 12:51:52 -08:00
+++ b/drivers/usb/atm/speedtch.c	2005-03-11 12:51:52 -08:00
@@ -58,8 +58,8 @@
 #define SPEEDTOUCH_PRODUCTID		0x4061
 
 /* Timeout in jiffies */
-#define CTRL_TIMEOUT (2*HZ)
-#define DATA_TIMEOUT (2*HZ)
+#define CTRL_TIMEOUT 2000
+#define DATA_TIMEOUT 2000
 
 #define OFFSET_7  0		/* size 1 */
 #define OFFSET_b  1		/* size 8 */
@@ -474,7 +474,7 @@
 	/* URB 7 */
 	if (dl_512_first) {	/* some modems need a read before writing the firmware */
 		ret = usb_bulk_msg(usb_dev, usb_rcvbulkpipe(usb_dev, SPEEDTCH_ENDPOINT_FIRMWARE),
-				   buffer, 0x200, &actual_length, 2 * HZ);
+				   buffer, 0x200, &actual_length, 2000);
 
 		if (ret < 0 && ret != -ETIMEDOUT)
 			dbg("speedtch_upload_firmware: read BLOCK0 from modem failed (%d)!", ret);
@@ -766,7 +766,7 @@
 
 	/* First check whether the modem already seems to be alive */
 	ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
-			      0x12, 0xc0, 0x07, 0x00, buf7, SIZE_7, HZ / 2);
+			      0x12, 0xc0, 0x07, 0x00, buf7, SIZE_7, 500);
 
 	if (ret == SIZE_7) {
 		dbg("firmware appears to be already loaded");
diff -Nru a/drivers/usb/class/audio.c b/drivers/usb/class/audio.c
--- a/drivers/usb/class/audio.c	2005-03-11 12:51:51 -08:00
+++ b/drivers/usb/class/audio.c	2005-03-11 12:51:51 -08:00
@@ -1561,7 +1561,7 @@
 	if (fmt->attributes & 0x02) {
 		data[0] = 1;
 		if ((ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), SET_CUR, USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_OUT, 
-					   PITCH_CONTROL << 8, ep, data, 1, HZ)) < 0) {
+					   PITCH_CONTROL << 8, ep, data, 1, 1000)) < 0) {
 			printk(KERN_ERR "usbaudio: failure (error %d) to set output pitch control device %d interface %u endpoint 0x%x to %u\n",
 			       ret, dev->devnum, u->interface, ep, d->srate);
 			return -1;
@@ -1573,13 +1573,13 @@
 		data[1] = d->srate >> 8;
 		data[2] = d->srate >> 16;
 		if ((ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), SET_CUR, USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_OUT, 
-					   SAMPLING_FREQ_CONTROL << 8, ep, data, 3, HZ)) < 0) {
+					   SAMPLING_FREQ_CONTROL << 8, ep, data, 3, 1000)) < 0) {
 			printk(KERN_ERR "usbaudio: failure (error %d) to set input sampling frequency device %d interface %u endpoint 0x%x to %u\n",
 			       ret, dev->devnum, u->interface, ep, d->srate);
 			return -1;
 		}
 		if ((ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), GET_CUR, USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_IN,
-					   SAMPLING_FREQ_CONTROL << 8, ep, data, 3, HZ)) < 0) {
+					   SAMPLING_FREQ_CONTROL << 8, ep, data, 3, 1000)) < 0) {
 			printk(KERN_ERR "usbaudio: failure (error %d) to get input sampling frequency device %d interface %u endpoint 0x%x\n",
 			       ret, dev->devnum, u->interface, ep);
 			return -1;
@@ -1657,7 +1657,7 @@
 	if (fmt->attributes & 0x02) {
 		data[0] = 1;
 		if ((ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), SET_CUR, USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_OUT, 
-					   PITCH_CONTROL << 8, ep, data, 1, HZ)) < 0) {
+					   PITCH_CONTROL << 8, ep, data, 1, 1000)) < 0) {
 			printk(KERN_ERR "usbaudio: failure (error %d) to set output pitch control device %d interface %u endpoint 0x%x to %u\n",
 			       ret, dev->devnum, u->interface, ep, d->srate);
 			return -1;
@@ -1669,13 +1669,13 @@
 		data[1] = d->srate >> 8;
 		data[2] = d->srate >> 16;
 		if ((ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), SET_CUR, USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_OUT, 
-					   SAMPLING_FREQ_CONTROL << 8, ep, data, 3, HZ)) < 0) {
+					   SAMPLING_FREQ_CONTROL << 8, ep, data, 3, 1000)) < 0) {
 			printk(KERN_ERR "usbaudio: failure (error %d) to set output sampling frequency device %d interface %u endpoint 0x%x to %u\n",
 			       ret, dev->devnum, u->interface, ep, d->srate);
 			return -1;
 		}
 		if ((ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), GET_CUR, USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_IN,
-					   SAMPLING_FREQ_CONTROL << 8, ep, data, 3, HZ)) < 0) {
+					   SAMPLING_FREQ_CONTROL << 8, ep, data, 3, 1000)) < 0) {
 			printk(KERN_ERR "usbaudio: failure (error %d) to get output sampling frequency device %d interface %u endpoint 0x%x\n",
 			       ret, dev->devnum, u->interface, ep);
 			return -1;
@@ -1754,7 +1754,7 @@
 		data[0] = v1;
 		data[1] = v1 >> 8;
 		if (usb_control_msg(dev, usb_sndctrlpipe(dev, 0), SET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT,
-				    (ch->chnum << 8) | 1, ms->iface | (ch->unitid << 8), data, 2, HZ) < 0)
+				    (ch->chnum << 8) | 1, ms->iface | (ch->unitid << 8), data, 2, 1000) < 0)
 			goto err;
 		if (!(ch->flags & (MIXFLG_STEREOIN | MIXFLG_STEREOOUT)))
 			return 0;
@@ -1762,7 +1762,7 @@
 		data[1] = v2 >> 8;
 		if (usb_control_msg(dev, usb_sndctrlpipe(dev, 0), SET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT,
 				    ((ch->chnum + !!(ch->flags & MIXFLG_STEREOIN)) << 8) | (1 + !!(ch->flags & MIXFLG_STEREOOUT)),
-				    ms->iface | (ch->unitid << 8), data, 2, HZ) < 0)
+				    ms->iface | (ch->unitid << 8), data, 2, 1000) < 0)
 			goto err;
 		return 0;
 
@@ -1771,14 +1771,14 @@
 		data[0] = v1;
 		data[1] = v1 >> 8;
 		if (usb_control_msg(dev, usb_sndctrlpipe(dev, 0), SET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT,
-				    (ch->selector << 8) | ch->chnum, ms->iface | (ch->unitid << 8), data, 2, HZ) < 0)
+				    (ch->selector << 8) | ch->chnum, ms->iface | (ch->unitid << 8), data, 2, 1000) < 0)
 			goto err;
 		if (!(ch->flags & (MIXFLG_STEREOIN | MIXFLG_STEREOOUT)))
 			return 0;
 		data[0] = v2;
 		data[1] = v2 >> 8;
 		if (usb_control_msg(dev, usb_sndctrlpipe(dev, 0), SET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT,
-				    (ch->selector << 8) | (ch->chnum + 1), ms->iface | (ch->unitid << 8), data, 2, HZ) < 0)
+				    (ch->selector << 8) | (ch->chnum + 1), ms->iface | (ch->unitid << 8), data, 2, 1000) < 0)
 			goto err;
 		return 0;
                 
@@ -1787,13 +1787,13 @@
 	case TREBLE_CONTROL:
 		data[0] = v1 >> 8;
 		if (usb_control_msg(dev, usb_sndctrlpipe(dev, 0), SET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT,
-				    (ch->selector << 8) | ch->chnum, ms->iface | (ch->unitid << 8), data, 1, HZ) < 0)
+				    (ch->selector << 8) | ch->chnum, ms->iface | (ch->unitid << 8), data, 1, 1000) < 0)
 			goto err;
 		if (!(ch->flags & (MIXFLG_STEREOIN | MIXFLG_STEREOOUT)))
 			return 0;
 		data[0] = v2 >> 8;
 		if (usb_control_msg(dev, usb_sndctrlpipe(dev, 0), SET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT,
-				    (ch->selector << 8) | (ch->chnum + 1), ms->iface | (ch->unitid << 8), data, 1, HZ) < 0)
+				    (ch->selector << 8) | (ch->chnum + 1), ms->iface | (ch->unitid << 8), data, 1, 1000) < 0)
 			goto err;
 		return 0;
 
@@ -1820,7 +1820,7 @@
 		if (!ms->ch[i].slctunitid || (mask & (1 << i)))
 			continue;
 		if (usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), GET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
-				    0, ms->iface | (ms->ch[i].slctunitid << 8), &buf, 1, HZ) < 0) {
+				    0, ms->iface | (ms->ch[i].slctunitid << 8), &buf, 1, 1000) < 0) {
 			err = -EIO;
 			printk(KERN_ERR "usbaudio: selector read request device %u if %u unit %u failed\n", 
 			       dev->devnum, ms->iface, ms->ch[i].slctunitid & 0xff);
@@ -1851,7 +1851,7 @@
 		if (!ms->ch[i].slctunitid || (mask & (1 << i)))
 			continue;
 		if (usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), GET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
-				    0, ms->iface | (ms->ch[i].slctunitid << 8), &buf, 1, HZ) < 0) {
+				    0, ms->iface | (ms->ch[i].slctunitid << 8), &buf, 1, 1000) < 0) {
 			err = -EIO;
 			printk(KERN_ERR "usbaudio: selector read request device %u if %u unit %u failed\n", 
 			       dev->devnum, ms->iface, ms->ch[i].slctunitid & 0xff);
@@ -1880,7 +1880,7 @@
 				continue;
 			buf = ms->ch[j].slctunitid >> 8;
 			if (usb_control_msg(dev, usb_sndctrlpipe(dev, 0), SET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT,
-				    0, ms->iface | (ms->ch[j].slctunitid << 8), &buf, 1, HZ) < 0) {
+				    0, ms->iface | (ms->ch[j].slctunitid << 8), &buf, 1, 1000) < 0) {
 				err = -EIO;
 				printk(KERN_ERR "usbaudio: selector write request device %u if %u unit %u failed\n", 
 				       dev->devnum, ms->iface, ms->ch[j].slctunitid & 0xff);
@@ -3136,18 +3136,18 @@
 	switch (ch->selector) {
 	case 0:  /* mixer unit request */
 		if (usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), GET_MIN, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
-				    (ch->chnum << 8) | 1, state->ctrlif | (ch->unitid << 8), buf, 2, HZ) < 0)
+				    (ch->chnum << 8) | 1, state->ctrlif | (ch->unitid << 8), buf, 2, 1000) < 0)
 			goto err;
 		ch->minval = buf[0] | (buf[1] << 8);
 		if (usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), GET_MAX, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
-				    (ch->chnum << 8) | 1, state->ctrlif | (ch->unitid << 8), buf, 2, HZ) < 0)
+				    (ch->chnum << 8) | 1, state->ctrlif | (ch->unitid << 8), buf, 2, 1000) < 0)
 			goto err;
 		ch->maxval = buf[0] | (buf[1] << 8);
 		v2 = ch->maxval - ch->minval;
 		if (!v2)
 			v2 = 1;
 		if (usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), GET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
-				    (ch->chnum << 8) | 1, state->ctrlif | (ch->unitid << 8), buf, 2, HZ) < 0)
+				    (ch->chnum << 8) | 1, state->ctrlif | (ch->unitid << 8), buf, 2, 1000) < 0)
 			goto err;
 		v1 = buf[0] | (buf[1] << 8);
 		v3 = v1 - ch->minval;
@@ -3158,7 +3158,7 @@
 		if (ch->flags & (MIXFLG_STEREOIN | MIXFLG_STEREOOUT)) {
 			if (usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), GET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
 					    ((ch->chnum + !!(ch->flags & MIXFLG_STEREOIN)) << 8) | (1 + !!(ch->flags & MIXFLG_STEREOOUT)),
-					    state->ctrlif | (ch->unitid << 8), buf, 2, HZ) < 0)
+					    state->ctrlif | (ch->unitid << 8), buf, 2, 1000) < 0)
 			goto err;
 			v1 = buf[0] | (buf[1] << 8);
 			v3 = v1 - ch->minval;
@@ -3172,15 +3172,15 @@
 		/* various feature unit controls */
 	case VOLUME_CONTROL:
 		if (usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), GET_MIN, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
-				    (ch->selector << 8) | ch->chnum, state->ctrlif | (ch->unitid << 8), buf, 2, HZ) < 0)
+				    (ch->selector << 8) | ch->chnum, state->ctrlif | (ch->unitid << 8), buf, 2, 1000) < 0)
 			goto err;
 		ch->minval = buf[0] | (buf[1] << 8);
 		if (usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), GET_MAX, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
-				    (ch->selector << 8) | ch->chnum, state->ctrlif | (ch->unitid << 8), buf, 2, HZ) < 0)
+				    (ch->selector << 8) | ch->chnum, state->ctrlif | (ch->unitid << 8), buf, 2, 1000) < 0)
 			goto err;
 		ch->maxval = buf[0] | (buf[1] << 8);
 		if (usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), GET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
-				    (ch->selector << 8) | ch->chnum, state->ctrlif | (ch->unitid << 8), buf, 2, HZ) < 0)
+				    (ch->selector << 8) | ch->chnum, state->ctrlif | (ch->unitid << 8), buf, 2, 1000) < 0)
 			goto err;
 		v1 = buf[0] | (buf[1] << 8);
 		v2 = ch->maxval - ch->minval;
@@ -3193,7 +3193,7 @@
 		ch->value = v3;
 		if (ch->flags & (MIXFLG_STEREOIN | MIXFLG_STEREOOUT)) {
 			if (usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), GET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
-					    (ch->selector << 8) | (ch->chnum + 1), state->ctrlif | (ch->unitid << 8), buf, 2, HZ) < 0)
+					    (ch->selector << 8) | (ch->chnum + 1), state->ctrlif | (ch->unitid << 8), buf, 2, 1000) < 0)
 				goto err;
 			v1 = buf[0] | (buf[1] << 8);
 			v3 = v1 - ch->minval;
@@ -3208,15 +3208,15 @@
 	case MID_CONTROL:
 	case TREBLE_CONTROL:
 		if (usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), GET_MIN, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
-				    (ch->selector << 8) | ch->chnum, state->ctrlif | (ch->unitid << 8), buf, 1, HZ) < 0)
+				    (ch->selector << 8) | ch->chnum, state->ctrlif | (ch->unitid << 8), buf, 1, 1000) < 0)
 			goto err;
 		ch->minval = buf[0] << 8;
 		if (usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), GET_MAX, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
-				    (ch->selector << 8) | ch->chnum, state->ctrlif | (ch->unitid << 8), buf, 1, HZ) < 0)
+				    (ch->selector << 8) | ch->chnum, state->ctrlif | (ch->unitid << 8), buf, 1, 1000) < 0)
 			goto err;
 		ch->maxval = buf[0] << 8;
 		if (usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), GET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
-				    (ch->selector << 8) | ch->chnum, state->ctrlif | (ch->unitid << 8), buf, 1, HZ) < 0)
+				    (ch->selector << 8) | ch->chnum, state->ctrlif | (ch->unitid << 8), buf, 1, 1000) < 0)
 			goto err;
 		v1 = buf[0] << 8;
 		v2 = ch->maxval - ch->minval;
@@ -3229,7 +3229,7 @@
 		ch->value = v3;
 		if (ch->flags & (MIXFLG_STEREOIN | MIXFLG_STEREOOUT)) {
 			if (usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), GET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
-					    (ch->selector << 8) | (ch->chnum + 1), state->ctrlif | (ch->unitid << 8), buf, 1, HZ) < 0)
+					    (ch->selector << 8) | (ch->chnum + 1), state->ctrlif | (ch->unitid << 8), buf, 1, 1000) < 0)
 				goto err;
 			v1 = buf[0] << 8;
 			v3 = v1 - ch->minval;
@@ -3522,7 +3522,7 @@
 		printk(KERN_DEBUG "usbaudio: unmuting feature unit %u interface %u\n", ftr[3], state->ctrlif);
 		data[0] = 0;
 		if (usb_control_msg(dev, usb_sndctrlpipe(dev, 0), SET_CUR, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT,
-				    (MUTE_CONTROL << 8) | 0xff, state->ctrlif | (ftr[3] << 8), data, 1, HZ) < 0)
+				    (MUTE_CONTROL << 8) | 0xff, state->ctrlif | (ftr[3] << 8), data, 1, 1000) < 0)
 			printk(KERN_WARNING "usbaudio: failure to unmute feature unit %u interface %u\n", ftr[3], state->ctrlif);
  	}
 #endif
diff -Nru a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
--- a/drivers/usb/class/cdc-acm.c	2005-03-11 12:51:47 -08:00
+++ b/drivers/usb/class/cdc-acm.c	2005-03-11 12:51:47 -08:00
@@ -60,6 +60,7 @@
 #include <linux/smp_lock.h>
 #include <asm/uaccess.h>
 #include <linux/usb.h>
+#include <linux/usb_cdc.h>
 #include <asm/byteorder.h>
 #include <asm/unaligned.h>
 
@@ -89,7 +90,7 @@
 	int retval = usb_control_msg(acm->dev, usb_sndctrlpipe(acm->dev, 0),
 		request, USB_RT_ACM, value,
 		acm->control->altsetting[0].desc.bInterfaceNumber,
-		buf, len, HZ * 5);
+		buf, len, 5000);
 	dbg("acm_control_msg: rq: 0x%02x val: %#x len: %#x result: %d", request, value, len, retval);
 	return retval < 0 ? retval : 0;
 }
@@ -97,9 +98,12 @@
 /* devices aren't required to support these requests.
  * the cdc acm descriptor tells whether they do...
  */
-#define acm_set_control(acm, control)	acm_ctrl_msg(acm, ACM_REQ_SET_CONTROL, control, NULL, 0)
-#define acm_set_line(acm, line)		acm_ctrl_msg(acm, ACM_REQ_SET_LINE, 0, line, sizeof(struct acm_line))
-#define acm_send_break(acm, ms)		acm_ctrl_msg(acm, ACM_REQ_SEND_BREAK, ms, NULL, 0)
+#define acm_set_control(acm, control) \
+	acm_ctrl_msg(acm, USB_CDC_REQ_SET_CONTROL_LINE_STATE, control, NULL, 0)
+#define acm_set_line(acm, line) \
+	acm_ctrl_msg(acm, USB_CDC_REQ_SET_LINE_CODING, 0, line, sizeof *(line))
+#define acm_send_break(acm, ms) \
+	acm_ctrl_msg(acm, USB_CDC_REQ_SEND_BREAK, ms, NULL, 0)
 
 /*
  * Interrupt handlers for various ACM device responses
@@ -109,7 +113,7 @@
 static void acm_ctrl_irq(struct urb *urb, struct pt_regs *regs)
 {
 	struct acm *acm = urb->context;
-	struct usb_ctrlrequest *dr = urb->transfer_buffer;
+	struct usb_cdc_notification *dr = urb->transfer_buffer;
 	unsigned char *data;
 	int newctrl;
 	int status;
@@ -133,14 +137,14 @@
 		goto exit;
 
 	data = (unsigned char *)(dr + 1);
-	switch (dr->bRequest) {
+	switch (dr->bNotificationType) {
 
-		case ACM_IRQ_NETWORK:
+		case USB_CDC_NOTIFY_NETWORK_CONNECTION:
 
 			dbg("%s network", dr->wValue ? "connected to" : "disconnected from");
 			break;
 
-		case ACM_IRQ_LINE_STATE:
+		case USB_CDC_NOTIFY_SERIAL_STATE:
 
 			newctrl = le16_to_cpu(get_unaligned((__le16 *) data));
 
@@ -160,8 +164,9 @@
 			break;
 
 		default:
-			dbg("unknown control event received: request %d index %d len %d data0 %d data1 %d",
-				dr->bRequest, dr->wIndex, dr->wLength, data[0], data[1]);
+			dbg("unknown notification %d received: index %d len %d data0 %d data1 %d",
+				dr->bNotificationType, dr->wIndex,
+				dr->wLength, data[0], data[1]);
 			break;
 	}
 exit:
@@ -485,32 +490,34 @@
 {
 	struct acm *acm = tty->driver_data;
 	struct termios *termios = tty->termios;
-	struct acm_line newline;
+	struct usb_cdc_line_coding newline;
 	int newctrl = acm->ctrlout;
 
 	if (!ACM_READY(acm))
 		return;
 
-	newline.speed = cpu_to_le32p(acm_tty_speed +
+	newline.dwDTERate = cpu_to_le32p(acm_tty_speed +
 		(termios->c_cflag & CBAUD & ~CBAUDEX) + (termios->c_cflag & CBAUDEX ? 15 : 0));
-	newline.stopbits = termios->c_cflag & CSTOPB ? 2 : 0;
-	newline.parity = termios->c_cflag & PARENB ?
+	newline.bCharFormat = termios->c_cflag & CSTOPB ? 2 : 0;
+	newline.bParityType = termios->c_cflag & PARENB ?
 		(termios->c_cflag & PARODD ? 1 : 2) + (termios->c_cflag & CMSPAR ? 2 : 0) : 0;
-	newline.databits = acm_tty_size[(termios->c_cflag & CSIZE) >> 4];
+	newline.bDataBits = acm_tty_size[(termios->c_cflag & CSIZE) >> 4];
 
 	acm->clocal = ((termios->c_cflag & CLOCAL) != 0);
 
-	if (!newline.speed) {
-		newline.speed = acm->line.speed;
+	if (!newline.dwDTERate) {
+		newline.dwDTERate = acm->line.dwDTERate;
 		newctrl &= ~ACM_CTRL_DTR;
 	} else  newctrl |=  ACM_CTRL_DTR;
 
 	if (newctrl != acm->ctrlout)
 		acm_set_control(acm, acm->ctrlout = newctrl);
 
-	if (memcmp(&acm->line, &newline, sizeof(struct acm_line))) {
-		memcpy(&acm->line, &newline, sizeof(struct acm_line));
-		dbg("set line: %d %d %d %d", newline.speed, newline.stopbits, newline.parity, newline.databits);
+	if (memcmp(&acm->line, &newline, sizeof newline)) {
+		memcpy(&acm->line, &newline, sizeof newline);
+		dbg("set line: %d %d %d %d", le32_to_cpu(newline.dwDTERate),
+			newline.bCharFormat, newline.bParityType,
+			newline.bDataBits);
 		acm_set_line(acm, &acm->line);
 	}
 }
@@ -522,7 +529,7 @@
 static int acm_probe (struct usb_interface *intf,
 		      const struct usb_device_id *id)
 {
-	struct union_desc *union_header = NULL;
+	struct usb_cdc_union_desc *union_header = NULL;
 	char *buffer = intf->altsetting->extra;
 	int buflen = intf->altsetting->extralen;
 	struct usb_interface *control_interface;
@@ -573,21 +580,22 @@
 		}
 
 		switch (buffer [2]) {
-			case CDC_UNION_TYPE: /* we've found it */
+			case USB_CDC_UNION_TYPE: /* we've found it */
 				if (union_header) {
 					err("More than one union descriptor, skipping ...");
 					goto next_desc;
 				}
-				union_header = (struct union_desc *)buffer;
+				union_header = (struct usb_cdc_union_desc *)
+							buffer;
 				break;
-			case CDC_COUNTRY_TYPE: /* maybe somehow export */
+			case USB_CDC_COUNTRY_TYPE: /* maybe somehow export */
 				break; /* for now we ignore it */
-			case CDC_HEADER_TYPE: /* maybe check version */ 
+			case USB_CDC_HEADER_TYPE: /* maybe check version */ 
 				break; /* for now we ignore it */ 
-			case CDC_AC_MANAGEMENT_TYPE:
+			case USB_CDC_ACM_TYPE:
 				ac_management_function = buffer[3];
 				break;
-			case CDC_CALL_MANAGEMENT_TYPE:
+			case USB_CDC_CALL_MANAGEMENT_TYPE:
 				call_management_function = buffer[3];
 				call_interface_num = buffer[4];
 				if ((call_management_function & 3) != 3)
@@ -750,8 +758,8 @@
 
 	acm_set_control(acm, acm->ctrlout);
 
-	acm->line.speed = cpu_to_le32(9600);
-	acm->line.databits = 8;
+	acm->line.dwDTERate = cpu_to_le32(9600);
+	acm->line.bDataBits = 8;
 	acm_set_line(acm, &acm->line);
 
 	usb_driver_claim_interface(&acm_driver, data_interface, acm);
@@ -831,14 +839,20 @@
 	.driver_info = NO_UNION_NORMAL, /* has no union descriptor */
 	},
 	/* control interfaces with various AT-command sets */
-	{ USB_INTERFACE_INFO(USB_CLASS_COMM, 2, 1) },
-	{ USB_INTERFACE_INFO(USB_CLASS_COMM, 2, 2) },
-	{ USB_INTERFACE_INFO(USB_CLASS_COMM, 2, 3) },
-	{ USB_INTERFACE_INFO(USB_CLASS_COMM, 2, 4) },
-	{ USB_INTERFACE_INFO(USB_CLASS_COMM, 2, 5) },
-	{ USB_INTERFACE_INFO(USB_CLASS_COMM, 2, 6) },
+	{ USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM,
+		USB_CDC_ACM_PROTO_AT_V25TER) },
+	{ USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM,
+		USB_CDC_ACM_PROTO_AT_PCCA101) },
+	{ USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM,
+		USB_CDC_ACM_PROTO_AT_PCCA101_WAKE) },
+	{ USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM,
+		USB_CDC_ACM_PROTO_AT_GSM) },
+	{ USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM,
+		USB_CDC_ACM_PROTO_AT_3G	) },
+	{ USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM,
+		USB_CDC_ACM_PROTO_AT_CDMA) },
 
-	/* NOTE:  COMM/2/0xff is likely MSFT RNDIS ... NOT a modem!! */
+	/* NOTE:  COMM/ACM/0xff is likely MSFT RNDIS ... NOT a modem!! */
 	{ }
 };
 
diff -Nru a/drivers/usb/class/cdc-acm.h b/drivers/usb/class/cdc-acm.h
--- a/drivers/usb/class/cdc-acm.h	2005-03-11 12:51:52 -08:00
+++ b/drivers/usb/class/cdc-acm.h	2005-03-11 12:51:52 -08:00
@@ -27,24 +27,6 @@
 
 #define USB_RT_ACM		(USB_TYPE_CLASS | USB_RECIP_INTERFACE)
 
-#define ACM_REQ_COMMAND		0x00
-#define ACM_REQ_RESPONSE	0x01
-#define ACM_REQ_SET_FEATURE	0x02
-#define ACM_REQ_GET_FEATURE	0x03
-#define ACM_REQ_CLEAR_FEATURE	0x04
-
-#define ACM_REQ_SET_LINE	0x20
-#define ACM_REQ_GET_LINE	0x21
-#define ACM_REQ_SET_CONTROL	0x22
-#define ACM_REQ_SEND_BREAK	0x23
-
-/*
- * IRQs.
- */
-
-#define ACM_IRQ_NETWORK		0x00
-#define ACM_IRQ_LINE_STATE	0x20
-
 /*
  * Output control lines.
  */
@@ -66,17 +48,6 @@
 #define ACM_CTRL_OVERRUN	0x40
 
 /*
- * Line speed and caracter encoding.
- */
-
-struct acm_line {
-	__le32 speed;
-	__u8 stopbits;
-	__u8 parity;
-	__u8 databits;
-} __attribute__ ((packed));
-
-/*
  * Internal driver structures.
  */
 
@@ -88,7 +59,7 @@
 	struct urb *ctrlurb, *readurb, *writeurb;	/* urbs */
 	u8 *ctrl_buffer, *read_buffer, *write_buffer;	/* buffers of urbs */
 	dma_addr_t ctrl_dma, read_dma, write_dma;	/* dma handles of buffers */
-	struct acm_line line;				/* line coding (bits, stop, parity) */
+	struct usb_cdc_line_coding line;		/* bits, stop, parity */
 	struct work_struct work;			/* work queue entry for line discipline waking up */
 	struct tasklet_struct bh;			/* rx processing */
 	spinlock_t throttle_lock;			/* synchronize throtteling and read callback */
@@ -104,24 +75,6 @@
 	unsigned char resubmit_to_unthrottle;		/* throtteling has disabled the read urb */
 	unsigned int ctrl_caps;				/* control capabilities from the class specific header */
 };
-
-/* "Union Functional Descriptor" from CDC spec 5.2.3.X */
-struct union_desc {
-	u8	bLength;
-	u8	bDescriptorType;
-	u8	bDescriptorSubType;
-
-	u8	bMasterInterface0;
-	u8	bSlaveInterface0;
-	/* ... and there could be other slave interfaces */
-} __attribute__ ((packed));
-
-/* class specific descriptor types */
-#define CDC_HEADER_TYPE			0x00
-#define CDC_CALL_MANAGEMENT_TYPE	0x01
-#define CDC_AC_MANAGEMENT_TYPE		0x02
-#define CDC_UNION_TYPE			0x06
-#define CDC_COUNTRY_TYPE		0x07
 
 #define CDC_DATA_INTERFACE_TYPE	0x0a
 
diff -Nru a/drivers/usb/class/usblp.c b/drivers/usb/class/usblp.c
--- a/drivers/usb/class/usblp.c	2005-03-11 12:51:41 -08:00
+++ b/drivers/usb/class/usblp.c	2005-03-11 12:51:41 -08:00
@@ -114,7 +114,7 @@
 #define USBLP_MINORS		16
 #define USBLP_MINOR_BASE	0
 
-#define USBLP_WRITE_TIMEOUT	(5*HZ)			/* 5 seconds */
+#define USBLP_WRITE_TIMEOUT	(5000)			/* 5 seconds */
 
 #define USBLP_FIRST_PROTOCOL	1
 #define USBLP_LAST_PROTOCOL	3
diff -Nru a/drivers/usb/core/config.c b/drivers/usb/core/config.c
--- a/drivers/usb/core/config.c	2005-03-11 12:51:41 -08:00
+++ b/drivers/usb/core/config.c	2005-03-11 12:51:41 -08:00
@@ -420,6 +420,9 @@
 	for (c = 0; c < dev->descriptor.bNumConfigurations; c++) {
 		struct usb_host_config *cf = &dev->config[c];
 
+		if (cf->string)
+			kfree(cf->string);
+
 		for (i = 0; i < cf->desc.bNumInterfaces; i++) {
 			if (cf->intf_cache[i])
 				kref_put(&cf->intf_cache[i]->ref, 
diff -Nru a/drivers/usb/core/devices.c b/drivers/usb/core/devices.c
--- a/drivers/usb/core/devices.c	2005-03-11 12:51:51 -08:00
+++ b/drivers/usb/core/devices.c	2005-03-11 12:51:51 -08:00
@@ -362,33 +362,21 @@
  */
 static char *usb_dump_device_strings (char *start, char *end, struct usb_device *dev)
 {
-	char *buf;
-
 	if (start > end)
 		return start;
-	buf = kmalloc(128, GFP_KERNEL);
-	if (!buf)
-		return start;
-	if (dev->descriptor.iManufacturer) {
-		if (usb_string(dev, dev->descriptor.iManufacturer, buf, 128) > 0)
-			start += sprintf(start, format_string_manufacturer, buf);
-	}				
+	if (dev->manufacturer)
+		start += sprintf(start, format_string_manufacturer, dev->manufacturer);
 	if (start > end)
 		goto out;
-	if (dev->descriptor.iProduct) {
-		if (usb_string(dev, dev->descriptor.iProduct, buf, 128) > 0)
-			start += sprintf(start, format_string_product, buf);
-	}
+	if (dev->product)
+		start += sprintf(start, format_string_product, dev->product);
 	if (start > end)
 		goto out;
 #ifdef ALLOW_SERIAL_NUMBER
-	if (dev->descriptor.iSerialNumber) {
-		if (usb_string(dev, dev->descriptor.iSerialNumber, buf, 128) > 0)
-			start += sprintf(start, format_string_serialnumber, buf);
-	}
+	if (dev->serial)
+		start += sprintf(start, format_string_serialnumber, dev->serial);
 #endif
  out:
-	kfree(buf);
 	return start;
 }
 
@@ -620,6 +608,7 @@
 		/* we may have dropped BKL - need to check for having lost the race */
 		if (file->private_data) {
 			kfree(st);
+			st = file->private_data;
 			goto lost_race;
 		}
 
diff -Nru a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
--- a/drivers/usb/core/devio.c	2005-03-11 12:51:46 -08:00
+++ b/drivers/usb/core/devio.c	2005-03-11 12:51:46 -08:00
@@ -565,7 +565,7 @@
 		return -EINVAL;
 	if (!(tbuf = (unsigned char *)__get_free_page(GFP_KERNEL)))
 		return -ENOMEM;
-	tmo = (ctrl.timeout * HZ + 999) / 1000;
+	tmo = ctrl.timeout;
 	if (ctrl.bRequestType & 0x80) {
 		if (ctrl.wLength && !access_ok(VERIFY_WRITE, ctrl.data, ctrl.wLength)) {
 			free_page((unsigned long)tbuf);
@@ -646,7 +646,7 @@
 		return -EINVAL;
 	if (!(tbuf = kmalloc(len1, GFP_KERNEL)))
 		return -ENOMEM;
-	tmo = (bulk.timeout * HZ + 999) / 1000;
+	tmo = bulk.timeout;
 	if (bulk.ep & 0x80) {
 		if (len1 && !access_ok(VERIFY_WRITE, bulk.data, len1)) {
 			kfree(tbuf);
@@ -673,11 +673,8 @@
 		usb_lock_device(dev);
 	}
 	kfree(tbuf);
-	if (i < 0) {
-		dev_warn(&dev->dev, "usbfs: USBDEVFS_BULK failed "
-			 "ep 0x%x len %u ret %d\n", bulk.ep, bulk.len, i);
+	if (i < 0)
 		return i;
-	}
 	return len2;
 }
 
@@ -816,9 +813,11 @@
 	return status;
 }
 
-static int proc_submiturb(struct dev_state *ps, void __user *arg)
+
+static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb,
+			     struct usbdevfs_iso_packet_desc __user *iso_frame_desc,
+			     void __user *arg)
 {
-	struct usbdevfs_urb uurb;
 	struct usbdevfs_iso_packet_desc *isopkt = NULL;
 	struct usb_host_endpoint *ep;
 	struct async *as;
@@ -826,42 +825,40 @@
 	unsigned int u, totlen, isofrmlen;
 	int ret, interval = 0, ifnum = -1;
 
-	if (copy_from_user(&uurb, arg, sizeof(uurb)))
-		return -EFAULT;
-	if (uurb.flags & ~(USBDEVFS_URB_ISO_ASAP|USBDEVFS_URB_SHORT_NOT_OK|
+	if (uurb->flags & ~(USBDEVFS_URB_ISO_ASAP|USBDEVFS_URB_SHORT_NOT_OK|
 			   URB_NO_FSBR|URB_ZERO_PACKET))
 		return -EINVAL;
-	if (!uurb.buffer)
+	if (!uurb->buffer)
 		return -EINVAL;
-	if (uurb.signr != 0 && (uurb.signr < SIGRTMIN || uurb.signr > SIGRTMAX))
+	if (uurb->signr != 0 && (uurb->signr < SIGRTMIN || uurb->signr > SIGRTMAX))
 		return -EINVAL;
-	if (!(uurb.type == USBDEVFS_URB_TYPE_CONTROL && (uurb.endpoint & ~USB_ENDPOINT_DIR_MASK) == 0)) {
-		if ((ifnum = findintfep(ps->dev, uurb.endpoint)) < 0)
+	if (!(uurb->type == USBDEVFS_URB_TYPE_CONTROL && (uurb->endpoint & ~USB_ENDPOINT_DIR_MASK) == 0)) {
+		if ((ifnum = findintfep(ps->dev, uurb->endpoint)) < 0)
 			return ifnum;
 		if ((ret = checkintf(ps, ifnum)))
 			return ret;
 	}
-	if ((uurb.endpoint & USB_ENDPOINT_DIR_MASK) != 0)
-		ep = ps->dev->ep_in [uurb.endpoint & USB_ENDPOINT_NUMBER_MASK];
+	if ((uurb->endpoint & USB_ENDPOINT_DIR_MASK) != 0)
+		ep = ps->dev->ep_in [uurb->endpoint & USB_ENDPOINT_NUMBER_MASK];
 	else
-		ep = ps->dev->ep_out [uurb.endpoint & USB_ENDPOINT_NUMBER_MASK];
+		ep = ps->dev->ep_out [uurb->endpoint & USB_ENDPOINT_NUMBER_MASK];
 	if (!ep)
 		return -ENOENT;
-	switch(uurb.type) {
+	switch(uurb->type) {
 	case USBDEVFS_URB_TYPE_CONTROL:
 		if ((ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
 				!= USB_ENDPOINT_XFER_CONTROL)
 			return -EINVAL;
 		/* min 8 byte setup packet, max arbitrary */
-		if (uurb.buffer_length < 8 || uurb.buffer_length > PAGE_SIZE)
+		if (uurb->buffer_length < 8 || uurb->buffer_length > PAGE_SIZE)
 			return -EINVAL;
 		if (!(dr = kmalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL)))
 			return -ENOMEM;
-		if (copy_from_user(dr, uurb.buffer, 8)) {
+		if (copy_from_user(dr, uurb->buffer, 8)) {
 			kfree(dr);
 			return -EFAULT;
 		}
-		if (uurb.buffer_length < (le16_to_cpup(&dr->wLength) + 8)) {
+		if (uurb->buffer_length < (le16_to_cpup(&dr->wLength) + 8)) {
 			kfree(dr);
 			return -EINVAL;
 		}
@@ -869,11 +866,11 @@
 			kfree(dr);
 			return ret;
 		}
-		uurb.endpoint = (uurb.endpoint & ~USB_ENDPOINT_DIR_MASK) | (dr->bRequestType & USB_ENDPOINT_DIR_MASK);
-		uurb.number_of_packets = 0;
-		uurb.buffer_length = le16_to_cpup(&dr->wLength);
-		uurb.buffer += 8;
-		if (!access_ok((uurb.endpoint & USB_DIR_IN) ?  VERIFY_WRITE : VERIFY_READ, uurb.buffer, uurb.buffer_length)) {
+		uurb->endpoint = (uurb->endpoint & ~USB_ENDPOINT_DIR_MASK) | (dr->bRequestType & USB_ENDPOINT_DIR_MASK);
+		uurb->number_of_packets = 0;
+		uurb->buffer_length = le16_to_cpup(&dr->wLength);
+		uurb->buffer += 8;
+		if (!access_ok((uurb->endpoint & USB_DIR_IN) ?  VERIFY_WRITE : VERIFY_READ, uurb->buffer, uurb->buffer_length)) {
 			kfree(dr);
 			return -EFAULT;
 		}
@@ -886,29 +883,29 @@
 			return -EINVAL;
 		/* allow single-shot interrupt transfers, at bogus rates */
 		}
-		uurb.number_of_packets = 0;
-		if (uurb.buffer_length > MAX_USBFS_BUFFER_SIZE)
+		uurb->number_of_packets = 0;
+		if (uurb->buffer_length > MAX_USBFS_BUFFER_SIZE)
 			return -EINVAL;
-		if (!access_ok((uurb.endpoint & USB_DIR_IN) ? VERIFY_WRITE : VERIFY_READ, uurb.buffer, uurb.buffer_length))
+		if (!access_ok((uurb->endpoint & USB_DIR_IN) ? VERIFY_WRITE : VERIFY_READ, uurb->buffer, uurb->buffer_length))
 			return -EFAULT;
 		break;
 
 	case USBDEVFS_URB_TYPE_ISO:
 		/* arbitrary limit */
-		if (uurb.number_of_packets < 1 || uurb.number_of_packets > 128)
+		if (uurb->number_of_packets < 1 || uurb->number_of_packets > 128)
 			return -EINVAL;
 		if ((ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
 				!= USB_ENDPOINT_XFER_ISOC)
 			return -EINVAL;
 		interval = 1 << min (15, ep->desc.bInterval - 1);
-		isofrmlen = sizeof(struct usbdevfs_iso_packet_desc) * uurb.number_of_packets;
+		isofrmlen = sizeof(struct usbdevfs_iso_packet_desc) * uurb->number_of_packets;
 		if (!(isopkt = kmalloc(isofrmlen, GFP_KERNEL)))
 			return -ENOMEM;
-		if (copy_from_user(isopkt, &((struct usbdevfs_urb __user *)arg)->iso_frame_desc, isofrmlen)) {
+		if (copy_from_user(isopkt, iso_frame_desc, isofrmlen)) {
 			kfree(isopkt);
 			return -EFAULT;
 		}
-		for (totlen = u = 0; u < uurb.number_of_packets; u++) {
+		for (totlen = u = 0; u < uurb->number_of_packets; u++) {
 			if (isopkt[u].length > 1023) {
 				kfree(isopkt);
 				return -EINVAL;
@@ -919,11 +916,11 @@
 			kfree(isopkt);
 			return -EINVAL;
 		}
-		uurb.buffer_length = totlen;
+		uurb->buffer_length = totlen;
 		break;
 
 	case USBDEVFS_URB_TYPE_INTERRUPT:
-		uurb.number_of_packets = 0;
+		uurb->number_of_packets = 0;
 		if ((ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
 				!= USB_ENDPOINT_XFER_INT)
 			return -EINVAL;
@@ -931,23 +928,23 @@
 			interval = 1 << min (15, ep->desc.bInterval - 1);
 		else
 			interval = ep->desc.bInterval;
-		if (uurb.buffer_length > MAX_USBFS_BUFFER_SIZE)
+		if (uurb->buffer_length > MAX_USBFS_BUFFER_SIZE)
 			return -EINVAL;
-		if (!access_ok((uurb.endpoint & USB_DIR_IN) ? VERIFY_WRITE : VERIFY_READ, uurb.buffer, uurb.buffer_length))
+		if (!access_ok((uurb->endpoint & USB_DIR_IN) ? VERIFY_WRITE : VERIFY_READ, uurb->buffer, uurb->buffer_length))
 			return -EFAULT;
 		break;
 
 	default:
 		return -EINVAL;
 	}
-	if (!(as = alloc_async(uurb.number_of_packets))) {
+	if (!(as = alloc_async(uurb->number_of_packets))) {
 		if (isopkt)
 			kfree(isopkt);
 		if (dr)
 			kfree(dr);
 		return -ENOMEM;
 	}
-	if (!(as->urb->transfer_buffer = kmalloc(uurb.buffer_length, GFP_KERNEL))) {
+	if (!(as->urb->transfer_buffer = kmalloc(uurb->buffer_length, GFP_KERNEL))) {
 		if (isopkt)
 			kfree(isopkt);
 		if (dr)
@@ -956,16 +953,16 @@
 		return -ENOMEM;
 	}
         as->urb->dev = ps->dev;
-        as->urb->pipe = (uurb.type << 30) | __create_pipe(ps->dev, uurb.endpoint & 0xf) | (uurb.endpoint & USB_DIR_IN);
-        as->urb->transfer_flags = uurb.flags;
-	as->urb->transfer_buffer_length = uurb.buffer_length;
+        as->urb->pipe = (uurb->type << 30) | __create_pipe(ps->dev, uurb->endpoint & 0xf) | (uurb->endpoint & USB_DIR_IN);
+        as->urb->transfer_flags = uurb->flags;
+	as->urb->transfer_buffer_length = uurb->buffer_length;
 	as->urb->setup_packet = (unsigned char*)dr;
-	as->urb->start_frame = uurb.start_frame;
-	as->urb->number_of_packets = uurb.number_of_packets;
+	as->urb->start_frame = uurb->start_frame;
+	as->urb->number_of_packets = uurb->number_of_packets;
 	as->urb->interval = interval;
         as->urb->context = as;
         as->urb->complete = async_completed;
-	for (totlen = u = 0; u < uurb.number_of_packets; u++) {
+	for (totlen = u = 0; u < uurb->number_of_packets; u++) {
 		as->urb->iso_frame_desc[u].offset = totlen;
 		as->urb->iso_frame_desc[u].length = isopkt[u].length;
 		totlen += isopkt[u].length;
@@ -974,15 +971,15 @@
 		kfree(isopkt);
 	as->ps = ps;
         as->userurb = arg;
-	if (uurb.endpoint & USB_DIR_IN)
-		as->userbuffer = uurb.buffer;
+	if (uurb->endpoint & USB_DIR_IN)
+		as->userbuffer = uurb->buffer;
 	else
 		as->userbuffer = NULL;
-	as->signr = uurb.signr;
+	as->signr = uurb->signr;
 	as->ifnum = ifnum;
 	as->task = current;
-	if (!(uurb.endpoint & USB_DIR_IN)) {
-		if (copy_from_user(as->urb->transfer_buffer, uurb.buffer, as->urb->transfer_buffer_length)) {
+	if (!(uurb->endpoint & USB_DIR_IN)) {
+		if (copy_from_user(as->urb->transfer_buffer, uurb->buffer, as->urb->transfer_buffer_length)) {
 			free_async(as);
 			return -EFAULT;
 		}
@@ -997,6 +994,16 @@
         return 0;
 }
 
+static int proc_submiturb(struct dev_state *ps, void __user *arg)
+{
+	struct usbdevfs_urb uurb;
+
+	if (copy_from_user(&uurb, arg, sizeof(uurb)))
+		return -EFAULT;
+
+	return proc_do_submiturb(ps, &uurb, (((struct usbdevfs_urb __user *)arg)->iso_frame_desc), arg);
+}
+
 static int proc_unlinkurb(struct dev_state *ps, void __user *arg)
 {
 	struct async *as;
@@ -1008,10 +1015,11 @@
 	return 0;
 }
 
-static int processcompl(struct async *as)
+static int processcompl(struct async *as, void __user * __user *arg)
 {
 	struct urb *urb = as->urb;
 	struct usbdevfs_urb __user *userurb = as->userurb;
+	void __user *addr = as->userurb;
 	unsigned int i;
 
 	if (as->userbuffer)
@@ -1034,16 +1042,19 @@
 			     &userurb->iso_frame_desc[i].status))
 			return -EFAULT;
 	}
+
+	free_async(as);
+
+	if (put_user(addr, (void __user * __user *)arg))
+		return -EFAULT;
 	return 0;
 }
 
-static int proc_reapurb(struct dev_state *ps, void __user *arg)
+static struct async* reap_as(struct dev_state *ps)
 {
         DECLARE_WAITQUEUE(wait, current);
 	struct async *as = NULL;
-	void __user *addr;
 	struct usb_device *dev = ps->dev;
-	int ret;
 
 	add_wait_queue(&ps->wait, &wait);
 	for (;;) {
@@ -1058,16 +1069,14 @@
 	}
 	remove_wait_queue(&ps->wait, &wait);
 	set_current_state(TASK_RUNNING);
-	if (as) {
-		ret = processcompl(as);
-		addr = as->userurb;
-		free_async(as);
-		if (ret)
-			return ret;
-		if (put_user(addr, (void __user * __user *)arg))
-			return -EFAULT;
-		return 0;
-	}
+	return as;
+}
+
+static int proc_reapurb(struct dev_state *ps, void __user *arg)
+{
+	struct async *as = reap_as(ps);
+	if (as)
+		return processcompl(as, (void __user * __user *)arg);
 	if (signal_pending(current))
 		return -EINTR;
 	return -EIO;
@@ -1076,21 +1085,107 @@
 static int proc_reapurbnonblock(struct dev_state *ps, void __user *arg)
 {
 	struct async *as;
-	void __user *addr;
-	int ret;
 
 	if (!(as = async_getcompleted(ps)))
 		return -EAGAIN;
-	ret = processcompl(as);
-	addr = as->userurb;
+	return processcompl(as, (void __user * __user *)arg);
+}
+
+#ifdef CONFIG_COMPAT
+
+static int get_urb32(struct usbdevfs_urb *kurb,
+		     struct usbdevfs_urb32 __user *uurb)
+{
+	__u32  uptr;
+	if (get_user(kurb->type, &uurb->type) ||
+	    __get_user(kurb->endpoint, &uurb->endpoint) ||
+	    __get_user(kurb->status, &uurb->status) ||
+	    __get_user(kurb->flags, &uurb->flags) ||
+	    __get_user(kurb->buffer_length, &uurb->buffer_length) ||
+	    __get_user(kurb->actual_length, &uurb->actual_length) ||
+	    __get_user(kurb->start_frame, &uurb->start_frame) ||
+	    __get_user(kurb->number_of_packets, &uurb->number_of_packets) ||
+	    __get_user(kurb->error_count, &uurb->error_count) ||
+	    __get_user(kurb->signr, &uurb->signr))
+		return -EFAULT;
+
+	if (__get_user(uptr, &uurb->buffer))
+		return -EFAULT;
+	kurb->buffer = compat_ptr(uptr);
+	if (__get_user(uptr, &uurb->buffer))
+		return -EFAULT;
+	kurb->usercontext = compat_ptr(uptr);
+
+	return 0;
+}
+
+static int proc_submiturb_compat(struct dev_state *ps, void __user *arg)
+{
+	struct usbdevfs_urb uurb;
+
+	if (get_urb32(&uurb,(struct usbdevfs_urb32 *)arg))
+		return -EFAULT;
+
+	return proc_do_submiturb(ps, &uurb, ((struct usbdevfs_urb __user *)arg)->iso_frame_desc, arg);
+}
+
+static int processcompl_compat(struct async *as, void __user * __user *arg)
+{
+	struct urb *urb = as->urb;
+	struct usbdevfs_urb32 __user *userurb = as->userurb;
+	void __user *addr = as->userurb;
+	unsigned int i;
+
+	if (as->userbuffer)
+		if (copy_to_user(as->userbuffer, urb->transfer_buffer, urb->transfer_buffer_length))
+			return -EFAULT;
+	if (put_user(urb->status, &userurb->status))
+		return -EFAULT;
+	if (put_user(urb->actual_length, &userurb->actual_length))
+		return -EFAULT;
+	if (put_user(urb->error_count, &userurb->error_count))
+		return -EFAULT;
+
+	if (!(usb_pipeisoc(urb->pipe)))
+		return 0;
+	for (i = 0; i < urb->number_of_packets; i++) {
+		if (put_user(urb->iso_frame_desc[i].actual_length,
+			     &userurb->iso_frame_desc[i].actual_length))
+			return -EFAULT;
+		if (put_user(urb->iso_frame_desc[i].status,
+			     &userurb->iso_frame_desc[i].status))
+			return -EFAULT;
+	}
+
 	free_async(as);
-	if (ret)
-		return ret;
-	if (put_user(addr, (void __user * __user *)arg))
+	if (put_user((u32)(u64)addr, (u32 __user *)arg))
 		return -EFAULT;
 	return 0;
 }
 
+static int proc_reapurb_compat(struct dev_state *ps, void __user *arg)
+{
+	struct async *as = reap_as(ps);
+	if (as)
+		return processcompl_compat(as, (void __user * __user *)arg);
+	if (signal_pending(current))
+		return -EINTR;
+	return -EIO;
+}
+
+static int proc_reapurbnonblock_compat(struct dev_state *ps, void __user *arg)
+{
+	struct async *as;
+
+	printk("reapurbnblock\n");
+	if (!(as = async_getcompleted(ps)))
+		return -EAGAIN;
+	printk("reap got as %p\n", as);
+	return processcompl_compat(as, (void __user * __user *)arg);
+}
+
+#endif
+
 static int proc_disconnectsignal(struct dev_state *ps, void __user *arg)
 {
 	struct usbdevfs_disconnectsignal ds;
@@ -1301,6 +1396,27 @@
 		if (ret >= 0)
 			inode->i_mtime = CURRENT_TIME;
 		break;
+
+#ifdef CONFIG_COMPAT
+
+	case USBDEVFS_SUBMITURB32:
+		snoop(&dev->dev, "%s: SUBMITURB32\n", __FUNCTION__);
+		ret = proc_submiturb_compat(ps, p);
+		if (ret >= 0)
+			inode->i_mtime = CURRENT_TIME;
+		break;
+
+	case USBDEVFS_REAPURB32:
+		snoop(&dev->dev, "%s: REAPURB32\n", __FUNCTION__);
+		ret = proc_reapurb_compat(ps, p);
+		break;
+
+	case USBDEVFS_REAPURBNDELAY32:
+		snoop(&dev->dev, "%s: REAPURBDELAY32\n", __FUNCTION__);
+		ret = proc_reapurbnonblock_compat(ps, p);
+		break;
+
+#endif
 
 	case USBDEVFS_DISCARDURB:
 		snoop(&dev->dev, "%s: DISCARDURB\n", __FUNCTION__);
diff -Nru a/drivers/usb/core/file.c b/drivers/usb/core/file.c
--- a/drivers/usb/core/file.c	2005-03-11 12:51:52 -08:00
+++ b/drivers/usb/core/file.c	2005-03-11 12:51:52 -08:00
@@ -66,16 +66,7 @@
 	.open =		usb_open,
 };
 
-static void release_usb_class_dev(struct class_device *class_dev)
-{
-	dbg("%s - %s", __FUNCTION__, class_dev->class_id);
-	kfree(class_dev);
-}
-
-static struct class usb_class = {
-	.name		= "usb",
-	.release	= &release_usb_class_dev,
-};
+static struct class_simple *usb_class;
 
 int usb_major_init(void)
 {
@@ -87,9 +78,9 @@
 		goto out;
 	}
 
-	error = class_register(&usb_class);
-	if (error) {
-		err("class_register failed for usb devices");
+	usb_class = class_simple_create(THIS_MODULE, "usb");
+	if (IS_ERR(usb_class)) {
+		err("class_simple_create failed for usb devices");
 		unregister_chrdev(USB_MAJOR, "usb");
 		goto out;
 	}
@@ -102,18 +93,11 @@
 
 void usb_major_cleanup(void)
 {
-	class_unregister(&usb_class);
+	class_simple_destroy(usb_class);
 	devfs_remove("usb");
 	unregister_chrdev(USB_MAJOR, "usb");
 }
 
-static ssize_t show_dev(struct class_device *class_dev, char *buf)
-{
-	int minor = (int)(long)class_get_devdata(class_dev);
-	return print_dev_t(buf, MKDEV(USB_MAJOR, minor));
-}
-static CLASS_DEVICE_ATTR(dev, S_IRUGO, show_dev, NULL);
-
 /**
  * usb_register_dev - register a USB device, and ask for a minor number
  * @intf: pointer to the usb_interface that is being registered
@@ -141,7 +125,6 @@
 	int minor_base = class_driver->minor_base;
 	int minor = 0;
 	char name[BUS_ID_SIZE];
-	struct class_device *class_dev;
 	char *temp;
 
 #ifdef CONFIG_USB_DYNAMIC_MINORS
@@ -181,22 +164,18 @@
 	devfs_mk_cdev(MKDEV(USB_MAJOR, minor), class_driver->mode, name);
 
 	/* create a usb class device for this usb interface */
-	class_dev = kmalloc(sizeof(*class_dev), GFP_KERNEL);
-	if (class_dev) {
-		memset(class_dev, 0x00, sizeof(struct class_device));
-		class_dev->class = &usb_class;
-		class_dev->dev = &intf->dev;
-
-		temp = strrchr(name, '/');
-		if (temp && (temp[1] != 0x00))
-			++temp;
-		else
-			temp = name;
-		snprintf(class_dev->class_id, BUS_ID_SIZE, "%s", temp);
-		class_set_devdata(class_dev, (void *)(long)intf->minor);
-		class_device_register(class_dev);
-		class_device_create_file(class_dev, &class_device_attr_dev);
-		intf->class_dev = class_dev;
+	temp = strrchr(name, '/');
+	if (temp && (temp[1] != 0x00))
+		++temp;
+	else
+		temp = name;
+	intf->class_dev = class_simple_device_add(usb_class, MKDEV(USB_MAJOR, minor), &intf->dev, "%s", temp);
+	if (IS_ERR(intf->class_dev)) {
+		spin_lock (&minor_lock);
+		usb_minors[intf->minor] = NULL;
+		spin_unlock (&minor_lock);
+		devfs_remove (name);
+		retval = PTR_ERR(intf->class_dev);
 	}
 exit:
 	return retval;
@@ -239,11 +218,8 @@
 
 	snprintf(name, BUS_ID_SIZE, class_driver->name, intf->minor - minor_base);
 	devfs_remove (name);
-
-	if (intf->class_dev) {
-		class_device_unregister(intf->class_dev);
-		intf->class_dev = NULL;
-	}
+	class_simple_device_remove(MKDEV(USB_MAJOR, intf->minor));
+	intf->class_dev = NULL;
 	intf->minor = -1;
 }
 EXPORT_SYMBOL(usb_deregister_dev);
diff -Nru a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c
--- a/drivers/usb/core/hcd-pci.c	2005-03-11 12:51:46 -08:00
+++ b/drivers/usb/core/hcd-pci.c	2005-03-11 12:51:46 -08:00
@@ -56,11 +56,8 @@
 int usb_hcd_pci_probe (struct pci_dev *dev, const struct pci_device_id *id)
 {
 	struct hc_driver	*driver;
-	unsigned long		resource, len;
-	void __iomem		*base;
 	struct usb_hcd		*hcd;
-	int			retval, region;
-	char			buf [8], *bufp = buf;
+	int			retval;
 
 	if (usb_disabled())
 		return -ENODEV;
@@ -78,122 +75,75 @@
 			"Found HC with no IRQ.  Check BIOS/PCI %s setup!\n",
 			pci_name(dev));
    	        retval = -ENODEV;
-		goto done;
+		goto err1;
         }
-	
+
+	hcd = usb_create_hcd (driver, &dev->dev, pci_name(dev));
+	if (!hcd) {
+		retval = -ENOMEM;
+		goto err1;
+	}
+
 	if (driver->flags & HCD_MEMORY) {	// EHCI, OHCI
-		region = 0;
-		resource = pci_resource_start (dev, 0);
-		len = pci_resource_len (dev, 0);
-		if (!request_mem_region (resource, len, driver->description)) {
+		hcd->rsrc_start = pci_resource_start (dev, 0);
+		hcd->rsrc_len = pci_resource_len (dev, 0);
+		if (!request_mem_region (hcd->rsrc_start, hcd->rsrc_len,
+				driver->description)) {
 			dev_dbg (&dev->dev, "controller already in use\n");
 			retval = -EBUSY;
-			goto done;
+			goto err2;
 		}
-		base = ioremap_nocache (resource, len);
-		if (base == NULL) {
+		hcd->regs = ioremap_nocache (hcd->rsrc_start, hcd->rsrc_len);
+		if (hcd->regs == NULL) {
 			dev_dbg (&dev->dev, "error mapping memory\n");
 			retval = -EFAULT;
-clean_1:
-			release_mem_region (resource, len);
-			dev_err (&dev->dev, "init %s fail, %d\n",
-				pci_name(dev), retval);
-			goto done;
+			goto err3;
 		}
 
 	} else { 				// UHCI
-		resource = len = 0;
+		int	region;
+
 		for (region = 0; region < PCI_ROM_RESOURCE; region++) {
-			if (!(pci_resource_flags (dev, region) & IORESOURCE_IO))
+			if (!(pci_resource_flags (dev, region) &
+					IORESOURCE_IO))
 				continue;
 
-			resource = pci_resource_start (dev, region);
-			len = pci_resource_len (dev, region);
-			if (request_region (resource, len,
+			hcd->rsrc_start = pci_resource_start (dev, region);
+			hcd->rsrc_len = pci_resource_len (dev, region);
+			if (request_region (hcd->rsrc_start, hcd->rsrc_len,
 					driver->description))
 				break;
 		}
 		if (region == PCI_ROM_RESOURCE) {
 			dev_dbg (&dev->dev, "no i/o regions available\n");
 			retval = -EBUSY;
-			goto done;
-		}
-		base = (void __iomem *) resource;
-	}
-
-	// driver->reset(), later on, will transfer device from
-	// control by SMM/BIOS to control by Linux (if needed)
-
-	hcd = usb_create_hcd (driver);
-	if (hcd == NULL){
-		dev_dbg (&dev->dev, "hcd alloc fail\n");
-		retval = -ENOMEM;
-clean_2:
-		if (driver->flags & HCD_MEMORY) {
-			iounmap (base);
-			goto clean_1;
-		} else {
-			release_region (resource, len);
-			dev_err (&dev->dev, "init %s fail, %d\n",
-				pci_name(dev), retval);
-			goto done;
+			goto err1;
 		}
 	}
-	// hcd zeroed everything
-	hcd->regs = base;
-	hcd->region = region;
 
-	pci_set_drvdata (dev, hcd);
-	hcd->self.bus_name = pci_name(dev);
 #ifdef CONFIG_PCI_NAMES
 	hcd->product_desc = dev->pretty_name;
 #endif
-	hcd->self.controller = &dev->dev;
-
-	if ((retval = hcd_buffer_create (hcd)) != 0) {
-clean_3:
-		pci_set_drvdata (dev, NULL);
-		usb_put_hcd (hcd);
-		goto clean_2;
-	}
-
-	dev_info (hcd->self.controller, "%s\n", hcd->product_desc);
-
-	/* till now HC has been in an indeterminate state ... */
-	if (driver->reset && (retval = driver->reset (hcd)) < 0) {
-		dev_err (hcd->self.controller, "can't reset\n");
-		goto clean_3;
-	}
 
 	pci_set_master (dev);
-#ifndef __sparc__
-	sprintf (buf, "%d", dev->irq);
-#else
-	bufp = __irq_itoa(dev->irq);
-#endif
-	retval = request_irq (dev->irq, usb_hcd_irq, SA_SHIRQ,
-				hcd->driver->description, hcd);
-	if (retval != 0) {
-		dev_err (hcd->self.controller,
-				"request interrupt %s failed\n", bufp);
-		goto clean_3;
-	}
-	hcd->irq = dev->irq;
-
-	dev_info (hcd->self.controller, "irq %s, %s 0x%lx\n", bufp,
-		(driver->flags & HCD_MEMORY) ? "pci mem" : "io base",
-		resource);
-
-	usb_register_bus (&hcd->self);
 
-	if ((retval = driver->start (hcd)) < 0) {
-		dev_err (hcd->self.controller, "init error %d\n", retval);
-		usb_hcd_pci_remove (dev);
-	}
-
-done:
+	retval = usb_add_hcd (hcd, dev->irq, SA_SHIRQ);
 	if (retval != 0)
-		pci_disable_device (dev);
+		goto err4;
+	return retval;
+
+ err4:
+	if (driver->flags & HCD_MEMORY) {
+		iounmap (hcd->regs);
+ err3:
+		release_mem_region (hcd->rsrc_start, hcd->rsrc_len);
+	} else
+		release_region (hcd->rsrc_start, hcd->rsrc_len);
+ err2:
+	usb_put_hcd (hcd);
+ err1:
+	pci_disable_device (dev);
+	dev_err (&dev->dev, "init %s fail, %d\n", pci_name(dev), retval);
 	return retval;
 } 
 EXPORT_SYMBOL (usb_hcd_pci_probe);
@@ -220,34 +170,15 @@
 	hcd = pci_get_drvdata(dev);
 	if (!hcd)
 		return;
-	dev_info (hcd->self.controller, "remove, state %x\n", hcd->state);
-
-	if (in_interrupt ())
-		BUG ();
-
-	if (HCD_IS_RUNNING (hcd->state))
-		hcd->state = USB_STATE_QUIESCING;
-
-	dev_dbg (hcd->self.controller, "roothub graceful disconnect\n");
-	usb_disconnect (&hcd->self.root_hub);
 
-	hcd->driver->stop (hcd);
-	hcd_buffer_destroy (hcd);
-	hcd->state = USB_STATE_HALT;
-	pci_set_drvdata(dev, NULL);
-
-	free_irq (hcd->irq, hcd);
+	usb_remove_hcd (hcd);
 	if (hcd->driver->flags & HCD_MEMORY) {
 		iounmap (hcd->regs);
-		release_mem_region (pci_resource_start (dev, 0),
-			pci_resource_len (dev, 0));
+		release_mem_region (hcd->rsrc_start, hcd->rsrc_len);
 	} else {
-		release_region (pci_resource_start (dev, hcd->region),
-			pci_resource_len (dev, hcd->region));
+		release_region (hcd->rsrc_start, hcd->rsrc_len);
 	}
-
-	usb_deregister_bus (&hcd->self);
-
+	usb_put_hcd (hcd);
 	pci_disable_device(dev);
 }
 EXPORT_SYMBOL (usb_hcd_pci_remove);
diff -Nru a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
--- a/drivers/usb/core/hcd.c	2005-03-11 12:51:47 -08:00
+++ b/drivers/usb/core/hcd.c	2005-03-11 12:51:47 -08:00
@@ -46,6 +46,7 @@
 
 #include "usb.h"
 #include "hcd.h"
+#include "hub.h"
 
 
 // #define USB_BANDWIDTH_MESSAGES
@@ -87,6 +88,7 @@
 
 /* host controllers we manage */
 LIST_HEAD (usb_bus_list);
+EXPORT_SYMBOL_GPL (usb_bus_list);
 
 /* used when allocating bus numbers */
 #define USB_MAXBUS		64
@@ -97,6 +99,7 @@
 
 /* used when updating list of hcds */
 DECLARE_MUTEX (usb_bus_list_lock);	/* exported only for usbfs */
+EXPORT_SYMBOL_GPL (usb_bus_list_lock);
 
 /* used when updating hcd data */
 static DEFINE_SPINLOCK(hcd_data_lock);
@@ -272,6 +275,10 @@
 		*utf++ = *s++;
 		*utf++ = 0;
 	}
+	if (utfmax > 0) {
+		*utf = *s;
+		++retval;
+	}
 	return retval;
 }
 
@@ -296,30 +303,40 @@
 
 	// language ids
 	if (id == 0) {
-		*data++ = 4; *data++ = 3;	/* 4 bytes string data */
-		*data++ = 0x09; *data++ = 0x04;	/* MSFT-speak for "en-us" */
-		return 4;
+		buf[0] = 4;    buf[1] = 3;	/* 4 bytes string data */
+		buf[2] = 0x09; buf[3] = 0x04;	/* MSFT-speak for "en-us" */
+		len = min (len, 4);
+		memcpy (data, buf, len);
+		return len;
 
 	// serial number
 	} else if (id == 1) {
-		strcpy (buf, hcd->self.bus_name);
+		strlcpy (buf, hcd->self.bus_name, sizeof buf);
 
 	// product description
 	} else if (id == 2) {
-                strcpy (buf, hcd->product_desc);
+		strlcpy (buf, hcd->product_desc, sizeof buf);
 
  	// id 3 == vendor description
 	} else if (id == 3) {
-                sprintf (buf, "%s %s %s",  system_utsname.sysname,
+		snprintf (buf, sizeof buf, "%s %s %s", system_utsname.sysname,
 			system_utsname.release, hcd->driver->description);
 
 	// unsupported IDs --> "protocol stall"
 	} else
-	    return 0;
+		return -EPIPE;
 
-	data [0] = 2 * (strlen (buf) + 1);
-	data [1] = 3;	/* type == string */
-	return 2 + ascii2utf (buf, data + 2, len - 2);
+	switch (len) {		/* All cases fall through */
+	default:
+		len = 2 + ascii2utf (buf, data + 2, len - 2);
+	case 2:
+		data [1] = 3;	/* type == string */
+	case 1:
+		data [0] = 2 * (strlen (buf) + 1);
+	case 0:
+		;		/* Compiler wants a statement here */
+	}
+	return len;
 }
 
 
@@ -328,11 +345,14 @@
 {
 	struct usb_ctrlrequest *cmd;
  	u16		typeReq, wValue, wIndex, wLength;
-	const u8	*bufp = NULL;
 	u8		*ubuf = urb->transfer_buffer;
+	u8		tbuf [sizeof (struct usb_hub_descriptor)];
+	const u8	*bufp = tbuf;
 	int		len = 0;
 	int		patch_wakeup = 0;
 	unsigned long	flags;
+	int		status = 0;
+	int		n;
 
 	cmd = (struct usb_ctrlrequest *) urb->setup_packet;
 	typeReq  = (cmd->bRequestType << 8) | cmd->bRequest;
@@ -343,17 +363,16 @@
 	if (wLength > urb->transfer_buffer_length)
 		goto error;
 
-	/* set up for success */
-	urb->status = 0;
-	urb->actual_length = wLength;
+	urb->actual_length = 0;
 	switch (typeReq) {
 
 	/* DEVICE REQUESTS */
 
 	case DeviceRequest | USB_REQ_GET_STATUS:
-		ubuf [0] = (hcd->remote_wakeup << USB_DEVICE_REMOTE_WAKEUP)
+		tbuf [0] = (hcd->remote_wakeup << USB_DEVICE_REMOTE_WAKEUP)
 				| (1 << USB_DEVICE_SELF_POWERED);
-		ubuf [1] = 0;
+		tbuf [1] = 0;
+		len = 2;
 		break;
 	case DeviceOutRequest | USB_REQ_CLEAR_FEATURE:
 		if (wValue == USB_DEVICE_REMOTE_WAKEUP)
@@ -368,7 +387,8 @@
 			goto error;
 		break;
 	case DeviceRequest | USB_REQ_GET_CONFIGURATION:
-		ubuf [0] = 1;
+		tbuf [0] = 1;
+		len = 1;
 			/* FALLTHROUGH */
 	case DeviceOutRequest | USB_REQ_SET_CONFIGURATION:
 		break;
@@ -395,16 +415,18 @@
 				patch_wakeup = 1;
 			break;
 		case USB_DT_STRING << 8:
-			urb->actual_length = rh_string (
-				wValue & 0xff, hcd,
-				ubuf, wLength);
+			n = rh_string (wValue & 0xff, hcd, ubuf, wLength);
+			if (n < 0)
+				goto error;
+			urb->actual_length = n;
 			break;
 		default:
 			goto error;
 		}
 		break;
 	case DeviceRequest | USB_REQ_GET_INTERFACE:
-		ubuf [0] = 0;
+		tbuf [0] = 0;
+		len = 1;
 			/* FALLTHROUGH */
 	case DeviceOutRequest | USB_REQ_SET_INTERFACE:
 		break;
@@ -420,8 +442,9 @@
 
 	case EndpointRequest | USB_REQ_GET_STATUS:
 		// ENDPOINT_HALT flag
-		ubuf [0] = 0;
-		ubuf [1] = 0;
+		tbuf [0] = 0;
+		tbuf [1] = 0;
+		len = 2;
 			/* FALLTHROUGH */
 	case EndpointOutRequest | USB_REQ_CLEAR_FEATURE:
 	case EndpointOutRequest | USB_REQ_SET_FEATURE:
@@ -433,19 +456,30 @@
 	default:
 		/* non-generic request */
 		if (HCD_IS_SUSPENDED (hcd->state))
-			urb->status = -EAGAIN;
-		else
-			urb->status = hcd->driver->hub_control (hcd,
+			status = -EAGAIN;
+		else {
+			switch (typeReq) {
+			case GetHubStatus:
+			case GetPortStatus:
+				len = 4;
+				break;
+			case GetHubDescriptor:
+				len = sizeof (struct usb_hub_descriptor);
+				break;
+			}
+			status = hcd->driver->hub_control (hcd,
 				typeReq, wValue, wIndex,
-				ubuf, wLength);
+				tbuf, wLength);
+		}
 		break;
 error:
 		/* "protocol stall" on error */
-		urb->status = -EPIPE;
+		status = -EPIPE;
 	}
-	if (urb->status) {
-		urb->actual_length = 0;
-		if (urb->status != -EPIPE) {
+
+	if (status) {
+		len = 0;
+		if (status != -EPIPE) {
 			dev_dbg (hcd->self.controller,
 				"CTRL: TypeReq=0x%x val=0x%x "
 				"idx=0x%x len=%d ==> %d\n",
@@ -453,7 +487,7 @@
 				wLength, urb->status);
 		}
 	}
-	if (bufp) {
+	if (len) {
 		if (urb->transfer_buffer_length < len)
 			len = urb->transfer_buffer_length;
 		urb->actual_length = len;
@@ -461,13 +495,19 @@
 		memcpy (ubuf, bufp, len);
 
 		/* report whether RH hardware supports remote wakeup */
-		if (patch_wakeup)
+		if (patch_wakeup &&
+				len > offsetof (struct usb_config_descriptor,
+						bmAttributes))
 			((struct usb_config_descriptor *)ubuf)->bmAttributes
 				|= USB_CONFIG_ATT_WAKEUP;
 	}
 
 	/* any errors get returned through the urb completion */
 	local_irq_save (flags);
+	spin_lock (&urb->lock);
+	if (urb->status == -EINPROGRESS)
+		urb->status = status;
+	spin_unlock (&urb->lock);
 	usb_hcd_giveback_urb (hcd, urb, NULL);
 	local_irq_restore (flags);
 	return 0;
@@ -747,6 +787,7 @@
 	up (&usb_bus_list_lock);
 
 	usbfs_add_bus (bus);
+	usbmon_notify_bus_add (bus);
 
 	dev_info (bus->controller, "new USB bus registered, assigned bus number %d\n", bus->busnum);
 	return 0;
@@ -774,11 +815,12 @@
 	list_del (&bus->bus_list);
 	up (&usb_bus_list_lock);
 
+	usbmon_notify_bus_remove (bus);
 	usbfs_remove_bus (bus);
 
 	clear_bit (bus->busnum, busmap.busmap);
 
-	class_device_unregister(&bus->class_dev);
+	class_device_del(&bus->class_dev);
 }
 EXPORT_SYMBOL (usb_deregister_bus);
 
@@ -1049,19 +1091,10 @@
 	struct usb_host_endpoint *ep;
 	unsigned long		flags;
 
-	ep = (usb_pipein(urb->pipe) ? urb->dev->ep_in : urb->dev->ep_out)
-			[usb_pipeendpoint(urb->pipe)];
-	if (!hcd || !ep)
+	if (!hcd)
 		return -ENODEV;
 
-	/*
-	 * FIXME:  make urb timeouts be generic, keeping the HCD cores
-	 * as simple as possible.
-	 */
-
-	// NOTE:  a generic device/urb monitoring hook would go here.
-	// hcd_monitor_hook(MONITOR_URB_SUBMIT, urb)
-	// It would catch submission paths for all urbs.
+	usbmon_urb_submit(&hcd->self, urb);
 
 	/*
 	 * Atomically queue the urb,  first to our records, then to the HCD.
@@ -1072,7 +1105,11 @@
 	// FIXME:  verify that quiescing hc works right (RH cleans up)
 
 	spin_lock_irqsave (&hcd_data_lock, flags);
-	if (unlikely (urb->reject))
+	ep = (usb_pipein(urb->pipe) ? urb->dev->ep_in : urb->dev->ep_out)
+			[usb_pipeendpoint(urb->pipe)];
+	if (unlikely (!ep))
+		status = -ENOENT;
+	else if (unlikely (urb->reject))
 		status = -EPERM;
 	else switch (hcd->state) {
 	case USB_STATE_RUNNING:
@@ -1088,6 +1125,7 @@
 	spin_unlock_irqrestore (&hcd_data_lock, flags);
 	if (status) {
 		INIT_LIST_HEAD (&urb->urb_list);
+		usbmon_urb_submit_error(&hcd->self, urb, status);
 		return status;
 	}
 
@@ -1104,8 +1142,6 @@
 		 * valid and usb_buffer_{sync,unmap}() not be needed, since
 		 * they could clobber root hub response data.
 		 */
-		urb->transfer_flags |= (URB_NO_TRANSFER_DMA_MAP
-					| URB_NO_SETUP_DMA_MAP);
 		status = rh_urb_enqueue (hcd, urb);
 		goto done;
 	}
@@ -1140,6 +1176,7 @@
 		if (urb->reject)
 			wake_up (&usb_kill_urb_queue);
 		usb_put_urb (urb);
+		usbmon_urb_submit_error(&hcd->self, urb, status);
 	}
 	return status;
 }
@@ -1462,14 +1499,13 @@
  */
 void usb_hcd_giveback_urb (struct usb_hcd *hcd, struct urb *urb, struct pt_regs *regs)
 {
-	urb_unlink (urb);
+	int at_root_hub;
 
-	// NOTE:  a generic device/urb monitoring hook would go here.
-	// hcd_monitor_hook(MONITOR_URB_FINISH, urb, dev)
-	// It would catch exit/unlink paths for all urbs.
+	at_root_hub = (urb->dev == hcd->self.root_hub);
+	urb_unlink (urb);
 
 	/* lower level hcd code should use *_dma exclusively */
-	if (hcd->self.controller->dma_mask) {
+	if (hcd->self.controller->dma_mask && !at_root_hub) {
 		if (usb_pipecontrol (urb->pipe)
 			&& !(urb->transfer_flags & URB_NO_SETUP_DMA_MAP))
 			dma_unmap_single (hcd->self.controller, urb->setup_dma,
@@ -1485,6 +1521,7 @@
 					    : DMA_TO_DEVICE);
 	}
 
+	usbmon_urb_complete (&hcd->self, urb);
 	/* pass ownership to the completion handler */
 	urb->complete (urb, regs);
 	atomic_dec (&urb->use_count);
@@ -1499,12 +1536,11 @@
 /**
  * usb_hcd_irq - hook IRQs to HCD framework (bus glue)
  * @irq: the IRQ being raised
- * @__hcd: pointer to the HCD whose IRQ is beinng signaled
+ * @__hcd: pointer to the HCD whose IRQ is being signaled
  * @r: saved hardware registers
  *
- * When registering a USB bus through the HCD framework code, use this
- * to handle interrupts.  The PCI glue layer does so automatically; only
- * bus glue for non-PCI system busses will need to use this.
+ * If the controller isn't HALTed, calls the driver's irq handler.
+ * Checks whether the controller is now dead.
  */
 irqreturn_t usb_hcd_irq (int irq, void *__hcd, struct pt_regs * r)
 {
@@ -1555,6 +1591,8 @@
 /**
  * usb_create_hcd - create and initialize an HCD structure
  * @driver: HC driver that will use this hcd
+ * @dev: device for this HC, stored in hcd->self.controller
+ * @bus_name: value to store in hcd->self.bus_name
  * Context: !in_interrupt()
  *
  * Allocate a struct usb_hcd, with extra space at the end for the
@@ -1563,25 +1601,30 @@
  *
  * If memory is unavailable, returns NULL.
  */
-struct usb_hcd *usb_create_hcd (const struct hc_driver *driver)
+struct usb_hcd *usb_create_hcd (const struct hc_driver *driver,
+		struct device *dev, char *bus_name)
 {
 	struct usb_hcd *hcd;
 
 	hcd = kcalloc(1, sizeof(*hcd) + driver->hcd_priv_size, GFP_KERNEL);
-	if (!hcd)
+	if (!hcd) {
+		dev_dbg (dev, "hcd alloc failed\n");
 		return NULL;
+	}
+	dev_set_drvdata(dev, hcd);
 
 	usb_bus_init(&hcd->self);
 	hcd->self.op = &usb_hcd_operations;
 	hcd->self.hcpriv = hcd;
 	hcd->self.release = &hcd_release;
+	hcd->self.controller = dev;
+	hcd->self.bus_name = bus_name;
 
 	init_timer(&hcd->rh_timer);
 
 	hcd->driver = driver;
 	hcd->product_desc = (driver->product_desc) ? driver->product_desc :
 			"USB Host Controller";
-	hcd->state = USB_STATE_HALT;
 
 	return hcd;
 }
@@ -1589,6 +1632,153 @@
 
 void usb_put_hcd (struct usb_hcd *hcd)
 {
+	dev_set_drvdata(hcd->self.controller, NULL);
 	usb_bus_put(&hcd->self);
 }
 EXPORT_SYMBOL (usb_put_hcd);
+
+/**
+ * usb_add_hcd - finish generic HCD structure initialization and register
+ * @hcd: the usb_hcd structure to initialize
+ * @irqnum: Interrupt line to allocate
+ * @irqflags: Interrupt type flags
+ *
+ * Finish the remaining parts of generic HCD initialization: allocate the
+ * buffers of consistent memory, register the bus, request the IRQ line,
+ * and call the driver's reset() and start() routines.
+ */
+int usb_add_hcd(struct usb_hcd *hcd,
+		unsigned int irqnum, unsigned long irqflags)
+{
+	int	retval;
+
+	dev_info(hcd->self.controller, "%s\n", hcd->product_desc);
+
+	/* till now HC has been in an indeterminate state ... */
+	if (hcd->driver->reset && (retval = hcd->driver->reset(hcd)) < 0) {
+		dev_err(hcd->self.controller, "can't reset\n");
+		return retval;
+	}
+
+	if ((retval = hcd_buffer_create(hcd)) != 0) {
+		dev_dbg(hcd->self.controller, "pool alloc failed\n");
+		return retval;
+	}
+
+	if ((retval = usb_register_bus(&hcd->self)) < 0)
+		goto err1;
+
+	if (hcd->driver->irq) {
+		char	buf[8], *bufp = buf;
+
+#ifdef __sparc__
+		bufp = __irq_itoa(irqnum);
+#else
+		sprintf(buf, "%d", irqnum);
+#endif
+
+		snprintf(hcd->irq_descr, sizeof(hcd->irq_descr), "%s:usb%d",
+				hcd->driver->description, hcd->self.busnum);
+		if ((retval = request_irq(irqnum, &usb_hcd_irq, irqflags,
+				hcd->irq_descr, hcd)) != 0) {
+			dev_err(hcd->self.controller,
+					"request interrupt %s failed\n", bufp);
+			goto err2;
+		}
+		hcd->irq = irqnum;
+		dev_info(hcd->self.controller, "irq %s, %s 0x%08llx\n", bufp,
+				(hcd->driver->flags & HCD_MEMORY) ?
+					"io mem" : "io base", hcd->rsrc_start);
+	} else {
+		hcd->irq = -1;
+		if (hcd->rsrc_start)
+			dev_info(hcd->self.controller, "%s 0x%08llx\n",
+					(hcd->driver->flags & HCD_MEMORY) ?
+					"io mem" : "io base", hcd->rsrc_start);
+	}
+
+	if ((retval = hcd->driver->start(hcd)) < 0) {
+		dev_err(hcd->self.controller, "startup error %d\n", retval);
+		goto err3;
+	}
+
+	return retval;
+
+ err3:
+	if (hcd->irq >= 0)
+		free_irq(irqnum, hcd);
+ err2:
+	usb_deregister_bus(&hcd->self);
+ err1:
+	hcd_buffer_destroy(hcd);
+	return retval;
+} 
+EXPORT_SYMBOL (usb_add_hcd);
+
+/**
+ * usb_remove_hcd - shutdown processing for generic HCDs
+ * @hcd: the usb_hcd structure to remove
+ * Context: !in_interrupt()
+ *
+ * Disconnects the root hub, then reverses the effects of usb_add_hcd(),
+ * invoking the HCD's stop() method.
+ */
+void usb_remove_hcd(struct usb_hcd *hcd)
+{
+	dev_info(hcd->self.controller, "remove, state %x\n", hcd->state);
+
+	if (HCD_IS_RUNNING (hcd->state))
+		hcd->state = USB_STATE_QUIESCING;
+
+	dev_dbg(hcd->self.controller, "roothub graceful disconnect\n");
+	usb_disconnect(&hcd->self.root_hub);
+
+	hcd->driver->stop(hcd);
+	hcd->state = USB_STATE_HALT;
+
+	if (hcd->irq >= 0)
+		free_irq(hcd->irq, hcd);
+	usb_deregister_bus(&hcd->self);
+	hcd_buffer_destroy(hcd);
+}
+EXPORT_SYMBOL (usb_remove_hcd);
+
+/*-------------------------------------------------------------------------*/
+
+#if defined(CONFIG_USB_MON) || defined(CONFIG_USB_MON_MODULE)
+
+struct usb_mon_operations *mon_ops;
+
+/*
+ * The registration is unlocked.
+ * We do it this way because we do not want to lock in hot paths.
+ *
+ * Notice that the code is minimally error-proof. Because usbmon needs
+ * symbols from usbcore, usbcore gets referenced and cannot be unloaded first.
+ */
+ 
+int usb_mon_register (struct usb_mon_operations *ops)
+{
+
+	if (mon_ops)
+		return -EBUSY;
+
+	mon_ops = ops;
+	mb();
+	return 0;
+}
+EXPORT_SYMBOL_GPL (usb_mon_register);
+
+void usb_mon_deregister (void)
+{
+
+	if (mon_ops == NULL) {
+		printk(KERN_ERR "USB: monitor was not registered\n");
+		return;
+	}
+	mon_ops = NULL;
+	mb();
+}
+EXPORT_SYMBOL_GPL (usb_mon_deregister);
+
+#endif /* CONFIG_USB_MON */
diff -Nru a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h
--- a/drivers/usb/core/hcd.h	2005-03-11 12:51:42 -08:00
+++ b/drivers/usb/core/hcd.h	2005-03-11 12:51:42 -08:00
@@ -63,6 +63,7 @@
 	struct usb_bus		self;		/* hcd is-a bus */
 
 	const char		*product_desc;	/* product/vendor string */
+	char			irq_descr[24];	/* driver + bus # */
 
 	struct timer_list	rh_timer;	/* drives root hub */
 
@@ -75,10 +76,8 @@
 	unsigned		remote_wakeup:1;/* sw should use wakeup? */
 	int			irq;		/* irq allocated */
 	void __iomem		*regs;		/* device memory/io */
-
-#ifdef	CONFIG_PCI
-	int			region;		/* pci region for regs */
-#endif
+	u64			rsrc_start;	/* memory/io resource start */
+	u64			rsrc_len;	/* memory/io resource length */
 
 #define HCD_BUFFER_POOLS	4
 	struct dma_pool		*pool [HCD_BUFFER_POOLS];
@@ -211,9 +210,12 @@
 extern void usb_hcd_giveback_urb (struct usb_hcd *hcd, struct urb *urb, struct pt_regs *regs);
 extern void usb_bus_init (struct usb_bus *bus);
 
-extern struct usb_hcd *usb_create_hcd (const struct hc_driver *driver);
+extern struct usb_hcd *usb_create_hcd (const struct hc_driver *driver,
+		struct device *dev, char *bus_name);
 extern void usb_put_hcd (struct usb_hcd *hcd);
-
+extern int usb_add_hcd(struct usb_hcd *hcd,
+		unsigned int irqnum, unsigned long irqflags);
+extern void usb_remove_hcd(struct usb_hcd *hcd);
 
 #ifdef CONFIG_PCI
 struct pci_dev;
@@ -408,6 +410,66 @@
 static inline void usbfs_cleanup(void) { }
 
 #endif /* CONFIG_USB_DEVICEFS */
+
+/*-------------------------------------------------------------------------*/
+
+#if defined(CONFIG_USB_MON) || defined(CONFIG_USB_MON_MODULE)
+
+struct usb_mon_operations {
+	void (*urb_submit)(struct usb_bus *bus, struct urb *urb);
+	void (*urb_submit_error)(struct usb_bus *bus, struct urb *urb, int err);
+	void (*urb_complete)(struct usb_bus *bus, struct urb *urb);
+	/* void (*urb_unlink)(struct usb_bus *bus, struct urb *urb); */
+	void (*bus_add)(struct usb_bus *bus);
+	void (*bus_remove)(struct usb_bus *bus);
+};
+
+extern struct usb_mon_operations *mon_ops;
+
+static inline void usbmon_urb_submit(struct usb_bus *bus, struct urb *urb)
+{
+	if (bus->monitored)
+		(*mon_ops->urb_submit)(bus, urb);
+}
+
+static inline void usbmon_urb_submit_error(struct usb_bus *bus, struct urb *urb,
+    int error)
+{
+	if (bus->monitored)
+		(*mon_ops->urb_submit_error)(bus, urb, error);
+}
+
+static inline void usbmon_urb_complete(struct usb_bus *bus, struct urb *urb)
+{
+	if (bus->monitored)
+		(*mon_ops->urb_complete)(bus, urb);
+}
+ 
+static inline void usbmon_notify_bus_add(struct usb_bus *bus)
+{
+	if (mon_ops)
+		(*mon_ops->bus_add)(bus);
+}
+
+static inline void usbmon_notify_bus_remove(struct usb_bus *bus)
+{
+	if (mon_ops)
+		(*mon_ops->bus_remove)(bus);
+}
+
+int usb_mon_register(struct usb_mon_operations *ops);
+void usb_mon_deregister(void);
+
+#else
+
+static inline void usbmon_urb_submit(struct usb_bus *bus, struct urb *urb) {}
+static inline void usbmon_urb_submit_error(struct usb_bus *bus, struct urb *urb,
+    int error) {}
+static inline void usbmon_urb_complete(struct usb_bus *bus, struct urb *urb) {}
+static inline void usbmon_notify_bus_add(struct usb_bus *bus) {}
+static inline void usbmon_notify_bus_remove(struct usb_bus *bus) {}
+
+#endif /* CONFIG_USB_MON */
 
 /*-------------------------------------------------------------------------*/
 
diff -Nru a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
--- a/drivers/usb/core/hub.c	2005-03-11 12:51:46 -08:00
+++ b/drivers/usb/core/hub.c	2005-03-11 12:51:46 -08:00
@@ -74,7 +74,7 @@
 MODULE_PARM_DESC(old_scheme_first,
 		 "start with the old device initialization scheme");
 
-static int use_both_schemes = 0;
+static int use_both_schemes = 1;
 module_param(use_both_schemes, bool, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(use_both_schemes,
 		"try the other device initialization scheme if the "
@@ -108,7 +108,7 @@
 		ret = usb_control_msg(hdev, usb_rcvctrlpipe(hdev, 0),
 			USB_REQ_GET_DESCRIPTOR, USB_DIR_IN | USB_RT_HUB,
 			USB_DT_HUB << 8, 0, data, size,
-			HZ * USB_CTRL_GET_TIMEOUT);
+			USB_CTRL_GET_TIMEOUT);
 		if (ret >= (USB_DT_HUB_NONVAR_SIZE + 2))
 			return ret;
 	}
@@ -121,7 +121,7 @@
 static int clear_hub_feature(struct usb_device *hdev, int feature)
 {
 	return usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0),
-		USB_REQ_CLEAR_FEATURE, USB_RT_HUB, feature, 0, NULL, 0, HZ);
+		USB_REQ_CLEAR_FEATURE, USB_RT_HUB, feature, 0, NULL, 0, 1000);
 }
 
 /*
@@ -131,7 +131,7 @@
 {
 	return usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0),
 		USB_REQ_CLEAR_FEATURE, USB_RT_PORT, feature, port1,
-		NULL, 0, HZ);
+		NULL, 0, 1000);
 }
 
 /*
@@ -141,7 +141,7 @@
 {
 	return usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0),
 		USB_REQ_SET_FEATURE, USB_RT_PORT, feature, port1,
-		NULL, 0, HZ);
+		NULL, 0, 1000);
 }
 
 /*
@@ -242,7 +242,7 @@
 }
 
 /* use a short timeout for hub/port status fetches */
-#define	USB_STS_TIMEOUT		1
+#define	USB_STS_TIMEOUT		1000
 #define	USB_STS_RETRIES		5
 
 /*
@@ -256,7 +256,7 @@
 	for (i = 0; i < USB_STS_RETRIES && status == -ETIMEDOUT; i++) {
 		status = usb_control_msg(hdev, usb_rcvctrlpipe(hdev, 0),
 			USB_REQ_GET_STATUS, USB_DIR_IN | USB_RT_HUB, 0, 0,
-			data, sizeof(*data), HZ * USB_STS_TIMEOUT);
+			data, sizeof(*data), USB_STS_TIMEOUT);
 	}
 	return status;
 }
@@ -272,7 +272,7 @@
 	for (i = 0; i < USB_STS_RETRIES && status == -ETIMEDOUT; i++) {
 		status = usb_control_msg(hdev, usb_rcvctrlpipe(hdev, 0),
 			USB_REQ_GET_STATUS, USB_DIR_IN | USB_RT_PORT, 0, port1,
-			data, sizeof(*data), HZ * USB_STS_TIMEOUT);
+			data, sizeof(*data), USB_STS_TIMEOUT);
 	}
 	return status;
 }
@@ -342,7 +342,7 @@
 {
 	return usb_control_msg(hdev, usb_rcvctrlpipe(hdev, 0),
 			       HUB_CLEAR_TT_BUFFER, USB_RT_PORT, devinfo,
-			       tt, NULL, 0, HZ);
+			       tt, NULL, 0, 1000);
 }
 
 /*
@@ -459,6 +459,7 @@
 	int	status;
 
 	hub->quiescing = 0;
+	hub->activating = 1;
 	status = usb_submit_urb(hub->urb, GFP_NOIO);
 	if (status < 0)
 		dev_err(hub->intfdev, "activate --> %d\n", status);
@@ -466,7 +467,6 @@
 		schedule_delayed_work(&hub->leds, LED_CYCLE_PERIOD);
 
 	/* scan all ports ASAP */
-	hub->event_bits[0] = (1UL << (hub->descriptor->bNbrPorts + 1)) - 1;
 	kick_khubd(hub);
 }
 
@@ -689,7 +689,6 @@
 		hub->indicator [0] = INDICATOR_CYCLE;
 
 	hub_power_on(hub);
-	hub->change_bits[0] = (1UL << (hub->descriptor->bNbrPorts + 1)) - 2;
 	hub_activate(hub);
 	return 0;
 
@@ -1103,23 +1102,33 @@
 }
 
 #ifdef DEBUG
-static void show_string(struct usb_device *udev, char *id, int index)
+static void show_string(struct usb_device *udev, char *id, char *string)
+{
+	if (!string)
+		return;
+	dev_printk(KERN_INFO, &udev->dev, "%s: %s\n", id, string);
+}
+
+#else
+static inline void show_string(struct usb_device *udev, char *id, char *string)
+{}
+#endif
+
+static void get_string(struct usb_device *udev, char **string, int index)
 {
 	char *buf;
 
 	if (!index)
 		return;
-	if (!(buf = kmalloc(256, GFP_KERNEL)))
+	buf = kmalloc(256, GFP_KERNEL);
+	if (!buf)
 		return;
 	if (usb_string(udev, index, buf, 256) > 0)
-		dev_printk(KERN_INFO, &udev->dev, "%s: %s\n", id, buf);
-	kfree(buf);
+		*string = buf;
+	else
+		kfree(buf);
 }
 
-#else
-static inline void show_string(struct usb_device *udev, char *id, int index)
-{}
-#endif
 
 #ifdef	CONFIG_USB_OTG
 #include "otg_whitelist.h"
@@ -1157,22 +1166,20 @@
 		goto fail;
 	}
 
+	/* read the standard strings and cache them if present */
+	get_string(udev, &udev->product, udev->descriptor.iProduct);
+	get_string(udev, &udev->manufacturer, udev->descriptor.iManufacturer);
+	get_string(udev, &udev->serial, udev->descriptor.iSerialNumber);
+
 	/* Tell the world! */
 	dev_dbg(&udev->dev, "new device strings: Mfr=%d, Product=%d, "
 			"SerialNumber=%d\n",
 			udev->descriptor.iManufacturer,
 			udev->descriptor.iProduct,
 			udev->descriptor.iSerialNumber);
-
-	if (udev->descriptor.iProduct)
-		show_string(udev, "Product",
-				udev->descriptor.iProduct);
-	if (udev->descriptor.iManufacturer)
-		show_string(udev, "Manufacturer",
-				udev->descriptor.iManufacturer);
-	if (udev->descriptor.iSerialNumber)
-		show_string(udev, "SerialNumber",
-				udev->descriptor.iSerialNumber);
+	show_string(udev, "Product", udev->product);
+	show_string(udev, "Manufacturer", udev->manufacturer);
+	show_string(udev, "SerialNumber", udev->serial);
 
 #ifdef	CONFIG_USB_OTG
 	/*
@@ -1214,7 +1221,7 @@
 					bus->b_hnp_enable
 						? USB_DEVICE_B_HNP_ENABLE
 						: USB_DEVICE_A_ALT_HNP_SUPPORT,
-					0, NULL, 0, HZ * USB_CTRL_SET_TIMEOUT);
+					0, NULL, 0, USB_CTRL_SET_TIMEOUT);
 				if (err < 0) {
 					/* OTG MESSAGE: report errors here,
 					 * customize to match your product.
@@ -1235,10 +1242,10 @@
 		 */
 		if (udev->bus->b_hnp_enable || udev->bus->is_b_host) {
 			static int __usb_suspend_device (struct usb_device *,
-						int port1, u32 state);
+						int port1, pm_message_t state);
 			err = __usb_suspend_device(udev,
 					udev->bus->otg_port,
-					PM_SUSPEND_MEM);
+					PMSG_SUSPEND);
 			if (err < 0)
 				dev_dbg(&udev->dev, "HNP fail, %d\n", err);
 		}
@@ -1526,7 +1533,7 @@
  * Linux (2.6) currently has NO mechanisms to initiate that:  no khubd
  * timer, no SRP, no requests through sysfs.
  */
-int __usb_suspend_device (struct usb_device *udev, int port1, u32 state)
+int __usb_suspend_device (struct usb_device *udev, int port1, pm_message_t state)
 {
 	int	status;
 
@@ -1624,7 +1631,7 @@
 /**
  * usb_suspend_device - suspend a usb device
  * @udev: device that's no longer in active use
- * @state: PM_SUSPEND_MEM to suspend
+ * @state: PMSG_SUSPEND to suspend
  * Context: must be able to sleep; device not locked
  *
  * Suspends a USB device that isn't in active use, conserving power.
@@ -1673,7 +1680,7 @@
 	usb_set_device_state(udev, udev->actconfig
 			? USB_STATE_CONFIGURED
 			: USB_STATE_ADDRESS);
-	udev->dev.power.power_state = PM_SUSPEND_ON;
+	udev->dev.power.power_state = PMSG_ON;
 
  	/* 10.5.4.5 says be sure devices in the tree are still there.
  	 * For now let's assume the device didn't go crazy on resume,
@@ -1874,7 +1881,7 @@
 	return status;
 }
 
-static int hub_suspend(struct usb_interface *intf, u32 state)
+static int hub_suspend(struct usb_interface *intf, pm_message_t state)
 {
 	struct usb_hub		*hub = usb_get_intfdata (intf);
 	struct usb_device	*hdev = hub->hdev;
@@ -1946,7 +1953,7 @@
 		}
 		up(&udev->serialize);
 	}
-	intf->dev.power.power_state = PM_SUSPEND_ON;
+	intf->dev.power.power_state = PMSG_ON;
 
 	hub_activate(hub);
 	return 0;
@@ -2058,7 +2065,7 @@
 		return -EINVAL;
 	retval = usb_control_msg(udev, usb_sndaddr0pipe(),
 		USB_REQ_SET_ADDRESS, 0, udev->devnum, 0,
-		NULL, 0, HZ * USB_CTRL_SET_TIMEOUT);
+		NULL, 0, USB_CTRL_SET_TIMEOUT);
 	if (retval == 0) {
 		usb_set_device_state(udev, USB_STATE_ADDRESS);
 		ep0_reinit(udev);
@@ -2181,24 +2188,35 @@
 				retval = -ENOMEM;
 				continue;
 			}
-			buf->bMaxPacketSize0 = 0;
 
 			/* Use a short timeout the first time through,
 			 * so that recalcitrant full-speed devices with
 			 * 8- or 16-byte ep0-maxpackets won't slow things
 			 * down tremendously by NAKing the unexpectedly
-			 * early status stage.  Also, retry on length 0
-			 * or stall; some devices are flakey.
+			 * early status stage.  Also, retry on all errors;
+			 * some devices are flakey.
 			 */
 			for (j = 0; j < 3; ++j) {
+				buf->bMaxPacketSize0 = 0;
 				r = usb_control_msg(udev, usb_rcvaddr0pipe(),
 					USB_REQ_GET_DESCRIPTOR, USB_DIR_IN,
 					USB_DT_DEVICE << 8, 0,
 					buf, GET_DESCRIPTOR_BUFSIZE,
-					(i ? HZ * USB_CTRL_GET_TIMEOUT : HZ));
-				if (r == 0 || r == -EPIPE)
-					continue;
-				if (r < 0)
+					(i ? USB_CTRL_GET_TIMEOUT : 1000));
+				switch (buf->bMaxPacketSize0) {
+				case 8: case 16: case 32: case 64:
+					if (buf->bDescriptorType ==
+							USB_DT_DEVICE) {
+						r = 0;
+						break;
+					}
+					/* FALL THROUGH */
+				default:
+					if (r == 0)
+						r = -EPROTO;
+					break;
+				}
+				if (r == 0)
 					break;
 			}
 			udev->descriptor.bMaxPacketSize0 =
@@ -2214,10 +2232,7 @@
 				retval = -ENODEV;
 				goto fail;
 			}
-			switch (udev->descriptor.bMaxPacketSize0) {
-			case 64: case 32: case 16: case 8:
-				break;
-			default:
+			if (r) {
 				dev_err(&udev->dev, "device descriptor "
 						"read/%s, error %d\n",
 						"64", r);
@@ -2630,7 +2645,7 @@
 		for (i = 1; i <= hub->descriptor->bNbrPorts; i++) {
 			connect_change = test_bit(i, hub->change_bits);
 			if (!test_and_clear_bit(i, hub->event_bits) &&
-					!connect_change)
+					!connect_change && !hub->activating)
 				continue;
 
 			ret = hub_port_status(hub, i,
@@ -2638,6 +2653,11 @@
 			if (ret < 0)
 				continue;
 
+			if (hub->activating && !hdev->children[i-1] &&
+					(portstatus &
+						USB_PORT_STAT_CONNECTION))
+				connect_change = 1;
+
 			if (portchange & USB_PORT_STAT_C_CONNECTION) {
 				clear_port_feature(hdev, i,
 					USB_PORT_FEAT_C_CONNECTION);
@@ -2728,6 +2748,8 @@
 			}
 		}
 
+		hub->activating = 0;
+
 loop:
 		usb_unlock_device(hdev);
 		usb_put_intf(intf);
@@ -2952,7 +2974,7 @@
 	ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
 			USB_REQ_SET_CONFIGURATION, 0,
 			udev->actconfig->desc.bConfigurationValue, 0,
-			NULL, 0, HZ * USB_CTRL_SET_TIMEOUT);
+			NULL, 0, USB_CTRL_SET_TIMEOUT);
 	if (ret < 0) {
 		dev_err(&udev->dev,
 			"can't restore configuration #%d (error=%d)\n",
diff -Nru a/drivers/usb/core/hub.h b/drivers/usb/core/hub.h
--- a/drivers/usb/core/hub.h	2005-03-11 12:51:41 -08:00
+++ b/drivers/usb/core/hub.h	2005-03-11 12:51:41 -08:00
@@ -215,6 +215,7 @@
 	u8			power_budget;	/* in 2mA units; or zero */
 
 	unsigned		quiescing:1;
+	unsigned		activating:1;
 
 	unsigned		has_indicators:1;
 	enum hub_led_mode	indicator[USB_MAXCHILDREN];
diff -Nru a/drivers/usb/core/message.c b/drivers/usb/core/message.c
--- a/drivers/usb/core/message.c	2005-03-11 12:51:42 -08:00
+++ b/drivers/usb/core/message.c	2005-03-11 12:51:42 -08:00
@@ -55,7 +55,7 @@
 	if (status == 0) {
 		if (timeout > 0) {
 			init_timer(&timer);
-			timer.expires = jiffies + timeout;
+			timer.expires = jiffies + msecs_to_jiffies(timeout);
 			timer.data = (unsigned long)urb;
 			timer.function = timeout_kill;
 			/* grr.  timeout _should_ include submit delays. */
@@ -65,12 +65,18 @@
 		status = urb->status;
 		/* note:  HCDs return ETIMEDOUT for other reasons too */
 		if (status == -ECONNRESET) {
-			dev_warn(&urb->dev->dev,
-				"%s timed out on ep%d%s\n",
+			dev_dbg(&urb->dev->dev,
+				"%s timed out on ep%d%s len=%d/%d\n",
 				current->comm,
 				usb_pipeendpoint(urb->pipe),
-				usb_pipein(urb->pipe) ? "in" : "out");
-			status = -ETIMEDOUT;
+				usb_pipein(urb->pipe) ? "in" : "out",
+				urb->actual_length,
+				urb->transfer_buffer_length
+				);
+			if (urb->actual_length > 0)
+				status = 0;
+			else
+				status = -ETIMEDOUT;
 		}
 		if (timeout > 0)
 			del_timer_sync(&timer);
@@ -115,7 +121,7 @@
  *	@index: USB message index value
  *	@data: pointer to the data to send
  *	@size: length in bytes of the data to send
- *	@timeout: time in jiffies to wait for the message to complete before
+ *	@timeout: time in msecs to wait for the message to complete before
  *		timing out (if 0 the wait is forever)
  *	Context: !in_interrupt ()
  *
@@ -163,7 +169,7 @@
  *	@data: pointer to the data to send
  *	@len: length in bytes of the data to send
  *	@actual_length: pointer to a location to put the actual length transferred in bytes
- *	@timeout: time in jiffies to wait for the message to complete before
+ *	@timeout: time in msecs to wait for the message to complete before
  *		timing out (if 0 the wait is forever)
  *	Context: !in_interrupt ()
  *
@@ -196,7 +202,7 @@
 	usb_fill_bulk_urb(urb, usb_dev, pipe, data, len,
 			  usb_api_blocking_completion, NULL);
 
-	return usb_start_wait_urb(urb,timeout,actual_length);
+	return usb_start_wait_urb(urb, timeout, actual_length);
 }
 
 /*-------------------------------------------------------------------*/
@@ -579,7 +585,7 @@
 		result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
 				USB_REQ_GET_DESCRIPTOR, USB_DIR_IN,
 				(type << 8) + index, 0, buf, size,
-				HZ * USB_CTRL_GET_TIMEOUT);
+				USB_CTRL_GET_TIMEOUT);
 		if (result == 0 || result == -EPIPE)
 			continue;
 		if (result > 1 && ((u8 *)buf)[1] != type) {
@@ -624,7 +630,7 @@
 		result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
 			USB_REQ_GET_DESCRIPTOR, USB_DIR_IN,
 			(USB_DT_STRING << 8) + index, langid, buf, size,
-			HZ * USB_CTRL_GET_TIMEOUT);
+			USB_CTRL_GET_TIMEOUT);
 		if (!(result == 0 || result == -EPIPE))
 			break;
 	}
@@ -834,7 +840,7 @@
 
 	ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
 		USB_REQ_GET_STATUS, USB_DIR_IN | type, 0, target, status,
-		sizeof(*status), HZ * USB_CTRL_GET_TIMEOUT);
+		sizeof(*status), USB_CTRL_GET_TIMEOUT);
 
 	*(u16 *)data = *status;
 	kfree(status);
@@ -879,7 +885,7 @@
 	result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
 		USB_REQ_CLEAR_FEATURE, USB_RECIP_ENDPOINT,
 		USB_ENDPOINT_HALT, endp, NULL, 0,
-		HZ * USB_CTRL_SET_TIMEOUT);
+		USB_CTRL_SET_TIMEOUT);
 
 	/* don't un-halt or force to DATA0 except on success */
 	if (result < 0)
@@ -982,6 +988,8 @@
 			dev_dbg (&dev->dev, "unregistering interface %s\n",
 				interface->dev.bus_id);
 			usb_remove_sysfs_intf_files(interface);
+			kfree(interface->cur_altsetting->string);
+			interface->cur_altsetting->string = NULL;
 			device_del (&interface->dev);
 		}
 
@@ -1101,7 +1109,7 @@
 
 	ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
 				   USB_REQ_SET_INTERFACE, USB_RECIP_INTERFACE,
-				   alternate, interface, NULL, 0, HZ * 5);
+				   alternate, interface, NULL, 0, 5000);
 
 	/* 9.4.10 says devices don't need this and are free to STALL the
 	 * request if the interface only has one alternate setting.
@@ -1123,10 +1131,29 @@
 	/* prevent submissions using previous endpoint settings */
 	usb_disable_interface(dev, iface);
 
+	/* 9.1.1.5 says:
+	 *
+	 *	Configuring a device or changing an alternate setting
+	 *	causes all of the status and configuration values
+	 *	associated with endpoints in the affected interfaces to
+	 *	be set to their default values. This includes setting
+	 *	the data toggle of any endpoint using data toggles to
+	 *	the value DATA0.
+	 *
+	 * Some devices take this too literally and don't reset the data
+	 * toggles if the new altsetting is the same as the old one (the
+	 * command isn't "changing" an alternate setting).  We will manually
+	 * reset the toggles when the new and old altsettings are the same.
+	 * Most devices won't need this, but fortunately it doesn't happen
+	 * often.
+	 */
+	if (iface->cur_altsetting == alt)
+		manual = 1;
 	iface->cur_altsetting = alt;
 
 	/* If the interface only has one altsetting and the device didn't
-	 * accept the request, we attempt to carry out the equivalent action
+	 * accept the request (or whenever the old altsetting is the same
+	 * as the new one), we attempt to carry out the equivalent action
 	 * by manually clearing the HALT feature for each endpoint in the
 	 * new altsetting.
 	 */
@@ -1202,7 +1229,7 @@
 	retval = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
 			USB_REQ_SET_CONFIGURATION, 0,
 			config->desc.bConfigurationValue, 0,
-			NULL, 0, HZ * USB_CTRL_SET_TIMEOUT);
+			NULL, 0, USB_CTRL_SET_TIMEOUT);
 	if (retval < 0) {
 		usb_set_device_state(dev, USB_STATE_ADDRESS);
 		return retval;
@@ -1337,7 +1364,7 @@
 
 	if ((ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
 			USB_REQ_SET_CONFIGURATION, 0, configuration, 0,
-			NULL, 0, HZ * USB_CTRL_SET_TIMEOUT)) < 0)
+			NULL, 0, USB_CTRL_SET_TIMEOUT)) < 0)
 		goto free_interfaces;
 
 	dev->actconfig = cp;
@@ -1386,6 +1413,13 @@
 		}
 		kfree(new_interfaces);
 
+		if ((cp->desc.iConfiguration) &&
+		    (cp->string == NULL)) {
+			cp->string = kmalloc(256, GFP_KERNEL);
+			if (cp->string)
+				usb_string(dev, cp->desc.iConfiguration, cp->string, 256);
+		}
+
 		/* Now that all the interfaces are set up, register them
 		 * to trigger binding of drivers to interfaces.  probe()
 		 * routines may install different altsettings and may
@@ -1408,6 +1442,13 @@
 					intf->dev.bus_id,
 					ret);
 				continue;
+			}
+			if ((intf->cur_altsetting->desc.iInterface) &&
+			    (intf->cur_altsetting->string == NULL)) {
+				intf->cur_altsetting->string = kmalloc(256, GFP_KERNEL);
+				if (intf->cur_altsetting->string)
+					usb_string(dev, intf->cur_altsetting->desc.iInterface,
+						   intf->cur_altsetting->string, 256);
 			}
 			usb_create_sysfs_intf_files (intf);
 		}
diff -Nru a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c
--- a/drivers/usb/core/sysfs.c	2005-03-11 12:51:42 -08:00
+++ b/drivers/usb/core/sysfs.c	2005-03-11 12:51:42 -08:00
@@ -46,27 +46,24 @@
 usb_actconfig_attr (bmAttributes, 1, "%2x\n")
 usb_actconfig_attr (bMaxPower, 2, "%3dmA\n")
 
-#define usb_actconfig_str(name, field)					\
-static ssize_t  show_##name(struct device *dev, char *buf)		\
-{									\
-	struct usb_device *udev;					\
-	struct usb_host_config *actconfig;				\
-	int len;							\
-									\
-	udev = to_usb_device (dev);					\
-	actconfig = udev->actconfig;					\
-	if (!actconfig)							\
-		return 0;						\
-	len = usb_string(udev, actconfig->desc.field, buf, PAGE_SIZE);	\
-	if (len < 0)							\
-		return 0;						\
-	buf[len] = '\n';						\
-	buf[len+1] = 0;							\
-	return len+1;							\
-}									\
-static DEVICE_ATTR(name, S_IRUGO, show_##name, NULL);
+static ssize_t show_configuration_string(struct device *dev, char *buf)
+{
+	struct usb_device *udev;
+	struct usb_host_config *actconfig;
+	int len;
 
-usb_actconfig_str (configuration, iConfiguration)
+	udev = to_usb_device (dev);
+	actconfig = udev->actconfig;
+	if ((!actconfig) || (!actconfig->string))
+		return 0;
+	len = sprintf(buf, actconfig->string, PAGE_SIZE);
+	if (len < 0)
+		return 0;
+	buf[len] = '\n';
+	buf[len+1] = 0;
+	return len+1;
+}
+static DEVICE_ATTR(configuration, S_IRUGO, show_configuration_string, NULL);
 
 /* configuration value is always present, and r/w */
 usb_actconfig_show(bConfigurationValue, 1, "%u\n");
@@ -89,14 +86,14 @@
 		show_bConfigurationValue, set_bConfigurationValue);
 
 /* String fields */
-#define usb_string_attr(name, field)		\
+#define usb_string_attr(name)						\
 static ssize_t  show_##name(struct device *dev, char *buf)		\
 {									\
 	struct usb_device *udev;					\
 	int len;							\
 									\
 	udev = to_usb_device (dev);					\
-	len = usb_string(udev, udev->descriptor.field, buf, PAGE_SIZE);	\
+	len = snprintf(buf, 256, "%s", udev->name);			\
 	if (len < 0)							\
 		return 0;						\
 	buf[len] = '\n';						\
@@ -105,9 +102,9 @@
 }									\
 static DEVICE_ATTR(name, S_IRUGO, show_##name, NULL);
 
-usb_string_attr(product, iProduct);
-usb_string_attr(manufacturer, iManufacturer);
-usb_string_attr(serial, iSerialNumber);
+usb_string_attr(product);
+usb_string_attr(manufacturer);
+usb_string_attr(serial);
 
 static ssize_t
 show_speed (struct device *dev, char *buf)
@@ -230,11 +227,11 @@
 
 	sysfs_create_group(&dev->kobj, &dev_attr_grp);
 
-	if (udev->descriptor.iManufacturer)
+	if (udev->manufacturer)
 		device_create_file (dev, &dev_attr_manufacturer);
-	if (udev->descriptor.iProduct)
+	if (udev->product)
 		device_create_file (dev, &dev_attr_product);
-	if (udev->descriptor.iSerialNumber)
+	if (udev->serial)
 		device_create_file (dev, &dev_attr_serial);
 	device_create_file (dev, &dev_attr_configuration);
 }
@@ -272,25 +269,22 @@
 usb_intf_attr (bInterfaceSubClass, "%02x\n")
 usb_intf_attr (bInterfaceProtocol, "%02x\n")
 
-#define usb_intf_str(name, field)					\
-static ssize_t  show_##name(struct device *dev, char *buf)		\
-{									\
-	struct usb_interface *intf;					\
-	struct usb_device *udev;					\
-	int len;							\
-									\
-	intf = to_usb_interface (dev);					\
-	udev = interface_to_usbdev (intf);				\
-	len = usb_string(udev, intf->cur_altsetting->desc.field, buf, PAGE_SIZE);\
-	if (len < 0)							\
-		return 0;						\
-	buf[len] = '\n';						\
-	buf[len+1] = 0;							\
-	return len+1;							\
-}									\
-static DEVICE_ATTR(name, S_IRUGO, show_##name, NULL);
+static ssize_t show_interface_string(struct device *dev, char *buf)
+{
+	struct usb_interface *intf;
+	struct usb_device *udev;
+	int len;
 
-usb_intf_str (interface, iInterface);
+	intf = to_usb_interface (dev);
+	udev = interface_to_usbdev (intf);
+	len = snprintf(buf, 256, "%s", intf->cur_altsetting->string);
+	if (len < 0)
+		return 0;
+	buf[len] = '\n';
+	buf[len+1] = 0;
+	return len+1;
+}
+static DEVICE_ATTR(interface, S_IRUGO, show_interface_string, NULL);
 
 static struct attribute *intf_attrs[] = {
 	&dev_attr_bInterfaceNumber.attr,
@@ -309,7 +303,7 @@
 {
 	sysfs_create_group(&intf->dev.kobj, &intf_attr_grp);
 
-	if (intf->cur_altsetting->desc.iInterface)
+	if (intf->cur_altsetting->string)
 		device_create_file(&intf->dev, &dev_attr_interface);
 		
 }
@@ -318,7 +312,7 @@
 {
 	sysfs_remove_group(&intf->dev.kobj, &intf_attr_grp);
 
-	if (intf->cur_altsetting->desc.iInterface)
+	if (intf->cur_altsetting->string)
 		device_remove_file(&intf->dev, &dev_attr_interface);
 
 }
diff -Nru a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
--- a/drivers/usb/core/usb.c	2005-03-11 12:51:46 -08:00
+++ b/drivers/usb/core/usb.c	2005-03-11 12:51:46 -08:00
@@ -647,7 +647,10 @@
 
 	usb_destroy_configuration(udev);
 	usb_bus_put(udev->bus);
-	kfree (udev);
+	kfree(udev->product);
+	kfree(udev->manufacturer);
+	kfree(udev->serial);
+	kfree(udev);
 }
 
 /**
diff -Nru a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
--- a/drivers/usb/gadget/Kconfig	2005-03-11 12:51:42 -08:00
+++ b/drivers/usb/gadget/Kconfig	2005-03-11 12:51:42 -08:00
@@ -87,10 +87,10 @@
 	default USB_GADGET
 
 config USB_GADGET_PXA2XX
-	boolean "PXA 2xx or IXP 4xx"
-	depends on ARCH_PXA || ARCH_IXP4XX
+	boolean "PXA 25x or IXP 4xx"
+	depends on (ARCH_PXA && PXA25x) || ARCH_IXP4XX
 	help
-	   Intel's PXA 2xx series XScale ARM-5TE processors include
+	   Intel's PXA 25x series XScale ARM-5TE processors include
 	   an integrated full speed USB 1.1 device controller.  The
 	   controller in the IXP 4xx series is register-compatible.
 
@@ -194,7 +194,7 @@
 config USB_GADGET_OMAP
 	boolean "OMAP USB Device Controller"
 	depends on ARCH_OMAP
-	select ISP1301_OMAP if MACH_OMAP_H2
+	select ISP1301_OMAP if MACH_OMAP_H2 || MACH_OMAP_H3
 	help
 	   Many Texas Instruments OMAP processors have flexible full
 	   speed USB device controllers, with support for up to 30
diff -Nru a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c
--- a/drivers/usb/gadget/dummy_hcd.c	2005-03-11 12:51:41 -08:00
+++ b/drivers/usb/gadget/dummy_hcd.c	2005-03-11 12:51:41 -08:00
@@ -4,7 +4,7 @@
  * Maintainer: Alan Stern <stern@rowland.harvard.edu>
  *
  * Copyright (C) 2003 David Brownell
- * Copyright (C) 2003, 2004 Alan Stern
+ * Copyright (C) 2003-2005 Alan Stern
  *
  * 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
@@ -167,7 +167,6 @@
 	 */
 	struct timer_list		timer;
 	u32				port_status;
-	unsigned			started:1;
 	unsigned			resuming:1;
 	unsigned long			re_timeout;
 
@@ -1637,7 +1636,6 @@
 	 * just like more familiar pci-based HCDs.
 	 */
 	spin_lock_init (&dum->lock);
-
 	init_timer (&dum->timer);
 	dum->timer.function = dummy_timer;
 	dum->timer.data = (unsigned long) dum;
@@ -1654,25 +1652,25 @@
 
 	/* ...then configured, so khubd sees us. */
 	if ((retval = hcd_register_root (root, hcd)) != 0) {
-		usb_put_dev (root);
-clean:
-		hcd->state = USB_STATE_QUIESCING;
-		return retval;
+		goto err1;
 	}
 
 	/* only show a low-power port: just 8mA */
 	hub_set_power_budget (root, 8);
 
-	if ((retval = dummy_register_udc (dum)) != 0) {
-		usb_disconnect (&hcd->self.root_hub);
-		goto clean;
-	}
+	if ((retval = dummy_register_udc (dum)) != 0)
+		goto err2;
 
 	/* FIXME 'urbs' should be a per-device thing, maybe in usbcore */
 	device_create_file (dummy_dev(dum), &dev_attr_urbs);
-
-	dum->started = 1;
 	return 0;
+
+ err2:
+	usb_disconnect (&hcd->self.root_hub);
+ err1:
+	usb_put_dev (root);
+	hcd->state = USB_STATE_QUIESCING;
+	return retval;
 }
 
 static void dummy_stop (struct usb_hcd *hcd)
@@ -1680,9 +1678,6 @@
 	struct dummy		*dum;
 
 	dum = hcd_to_dummy (hcd);
-	if (!dum->started)
-		return;
-	dum->started = 0;
 
 	device_remove_file (dummy_dev(dum), &dev_attr_urbs);
 
@@ -1718,71 +1713,33 @@
 	.hub_control = 		dummy_hub_control,
 };
 
-static void dummy_remove (struct device *dev);
-
 static int dummy_probe (struct device *dev)
 {
 	struct usb_hcd		*hcd;
-	struct dummy		*dum;
 	int			retval;
 
 	dev_info (dev, "%s, driver " DRIVER_VERSION "\n", driver_desc);
 
-	hcd = usb_create_hcd (&dummy_hcd);
-	if (hcd == NULL) {
-		dev_dbg (dev, "hcd_alloc failed\n");
+	hcd = usb_create_hcd (&dummy_hcd, dev, dev->bus_id);
+	if (!hcd)
 		return -ENOMEM;
-	}
+	the_controller = hcd_to_dummy (hcd);
 
-	dev_set_drvdata (dev, hcd);
-	dum = hcd_to_dummy (hcd);
-	the_controller = dum;
-
-	hcd->self.controller = dev;
-
-	/* FIXME don't require the pci-based buffer/alloc impls;
-	 * the "generic dma" implementation still requires them,
-	 * it's not very generic yet.
-	 */
-	retval = hcd_buffer_create (hcd);
+	retval = usb_add_hcd(hcd, 0, 0);
 	if (retval != 0) {
-		dev_dbg (dev, "pool alloc failed\n");
-		goto err1;
+		usb_put_hcd (hcd);
+		the_controller = NULL;
 	}
-
-	hcd->self.bus_name = dev->bus_id;
-	usb_register_bus (&hcd->self);
-
-	if ((retval = dummy_start (hcd)) < 0) 
-		dummy_remove (dev);
-	return retval;
-
-err1:
-	usb_put_hcd (hcd);
-	dev_set_drvdata (dev, NULL);
 	return retval;
 }
 
 static void dummy_remove (struct device *dev)
 {
 	struct usb_hcd		*hcd;
-	struct dummy		*dum;
 
 	hcd = dev_get_drvdata (dev);
-	dum = hcd_to_dummy (hcd);
-
-	hcd->state = USB_STATE_QUIESCING;
-
-	dev_dbg (dev, "roothub graceful disconnect\n");
-	usb_disconnect (&hcd->self.root_hub);
-
-	hcd->driver->stop (hcd);
-	hcd->state = USB_STATE_HALT;
-
-	hcd_buffer_destroy (hcd);
-
-	dev_set_drvdata (dev, NULL);
-	usb_deregister_bus (&hcd->self);
+	usb_remove_hcd (hcd);
+	usb_put_hcd (hcd);
 	the_controller = NULL;
 }
 
diff -Nru a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c
--- a/drivers/usb/gadget/ether.c	2005-03-11 12:51:51 -08:00
+++ b/drivers/usb/gadget/ether.c	2005-03-11 12:51:51 -08:00
@@ -49,6 +49,7 @@
 #include <asm/unaligned.h>
 
 #include <linux/usb_ch9.h>
+#include <linux/usb_cdc.h>
 #include <linux/usb_gadget.h>
 
 #include <linux/random.h>
@@ -259,6 +260,9 @@
 #define	DEV_CONFIG_SUBSET
 #endif
 
+#ifdef CONFIG_USB_GADGET_S3C2410
+#define DEV_CONFIG_CDC
+#endif
 
 /*-------------------------------------------------------------------------*/
 
@@ -432,8 +436,8 @@
 	/* status endpoint is optional; this may be patched later */
 	.bNumEndpoints =	1,
 	.bInterfaceClass =	USB_CLASS_COMM,
-	.bInterfaceSubClass =	6,	/* ethernet control model */
-	.bInterfaceProtocol =	0,
+	.bInterfaceSubClass =	USB_CDC_SUBCLASS_ETHERNET,
+	.bInterfaceProtocol =	USB_CDC_PROTO_NONE,
 	.iInterface =		STRING_CONTROL,
 };
 #endif
@@ -447,46 +451,26 @@
 	.bInterfaceNumber =     0,
 	.bNumEndpoints =        1,
 	.bInterfaceClass =      USB_CLASS_COMM,
-	.bInterfaceSubClass =   2,	/* abstract control model */
-	.bInterfaceProtocol =   0xff,	/* vendor specific */
+	.bInterfaceSubClass =   USB_CDC_SUBCLASS_ACM,
+	.bInterfaceProtocol =   USB_CDC_ACM_PROTO_VENDOR,
 	.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 {
-	u8	bLength;
-	u8	bDescriptorType;
-	u8	bDescriptorSubType;
-
-	u16	bcdCDC;
-} __attribute__ ((packed));
-
-static const struct header_desc header_desc = {
+static const struct usb_cdc_header_desc header_desc = {
 	.bLength =		sizeof header_desc,
 	.bDescriptorType =	USB_DT_CS_INTERFACE,
-	.bDescriptorSubType =	0,
+	.bDescriptorSubType =	USB_CDC_HEADER_TYPE,
 
 	.bcdCDC =		__constant_cpu_to_le16 (0x0110),
 };
 
-/* "Union Functional Descriptor" from CDC spec 5.2.3.8 */
-struct union_desc {
-	u8	bLength;
-	u8	bDescriptorType;
-	u8	bDescriptorSubType;
-
-	u8	bMasterInterface0;
-	u8	bSlaveInterface0;
-	/* ... and there could be other slave interfaces */
-} __attribute__ ((packed));
-
-static const struct union_desc union_desc = {
+static const struct usb_cdc_union_desc union_desc = {
 	.bLength =		sizeof union_desc,
 	.bDescriptorType =	USB_DT_CS_INTERFACE,
-	.bDescriptorSubType =	6,
+	.bDescriptorSubType =	USB_CDC_UNION_TYPE,
 
 	.bMasterInterface0 =	0,	/* index of control interface */
 	.bSlaveInterface0 =	1,	/* index of DATA interface */
@@ -496,64 +480,31 @@
 
 #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 = {
+static const struct usb_cdc_call_mgmt_descriptor call_mgmt_descriptor = {
 	.bLength =  		sizeof call_mgmt_descriptor,
 	.bDescriptorType = 	USB_DT_CS_INTERFACE,
-	.bDescriptorSubType = 	0x01,
+	.bDescriptorSubType = 	USB_CDC_CALL_MANAGEMENT_TYPE,
 
 	.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 = {
+static struct usb_cdc_acm_descriptor acm_descriptor = {
 	.bLength =  		sizeof acm_descriptor,
 	.bDescriptorType = 	USB_DT_CS_INTERFACE,
-	.bDescriptorSubType = 	0x02,
+	.bDescriptorSubType = 	USB_CDC_ACM_TYPE,
 
-	.bmCapabilities = 	0X00,
+	.bmCapabilities = 	0x00,
 };
 
 #endif
 
 #ifdef	DEV_CONFIG_CDC
 
-/* "Ethernet Networking Functional Descriptor" from CDC spec 5.2.3.16 */
-struct ether_desc {
-	u8	bLength;
-	u8	bDescriptorType;
-	u8	bDescriptorSubType;
-
-	u8	iMACAddress;
-	u32	bmEthernetStatistics;
-	u16	wMaxSegmentSize;
-	u16	wNumberMCFilters;
-	u8	bNumberPowerFilters;
-} __attribute__ ((packed));
-
-static const struct ether_desc ether_desc = {
+static const struct usb_cdc_ether_desc ether_desc = {
 	.bLength =		sizeof ether_desc,
 	.bDescriptorType =	USB_DT_CS_INTERFACE,
-	.bDescriptorSubType =	0x0f,
+	.bDescriptorSubType =	USB_CDC_ETHERNET_TYPE,
 
 	/* this descriptor actually adds value, surprise! */
 	.iMACAddress =		STRING_ETHADDR,
@@ -1242,47 +1193,30 @@
 
 /*-------------------------------------------------------------------------*/
 
-/* 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;
-	u16	wValue;
-	u16	wIndex;
-	u16	wLength;
-
-	/* SPEED_CHANGE data looks like this */
-	u32	data [2];
-};
-
 static void eth_status_complete (struct usb_ep *ep, struct usb_request *req)
 {
-	struct cdc_notification	*event = req->buf;
-	int			value = req->status;
-	struct eth_dev		*dev = ep->driver_data;
+	struct usb_cdc_notification	*event = req->buf;
+	int				value = req->status;
+	struct eth_dev			*dev = ep->driver_data;
 
 	/* issue the second notification if host reads the first */
-	if (event->bNotificationType == CDC_NOTIFY_NETWORK_CONNECTION
+	if (event->bNotificationType == USB_CDC_NOTIFY_NETWORK_CONNECTION
 			&& value == 0) {
+		__le32	*data = req->buf + sizeof *event;
+
 		event->bmRequestType = 0xA1;
-		event->bNotificationType = CDC_NOTIFY_SPEED_CHANGE;
+		event->bNotificationType = USB_CDC_NOTIFY_SPEED_CHANGE;
 		event->wValue = __constant_cpu_to_le16 (0);
 		event->wIndex = __constant_cpu_to_le16 (1);
 		event->wLength = __constant_cpu_to_le16 (8);
 
 		/* SPEED_CHANGE data is up/down speeds in bits/sec */
-		event->data [0] = event->data [1] =
+		data [0] = data [1] = cpu_to_le32(
 			(dev->gadget->speed == USB_SPEED_HIGH)
 				? (13 * 512 * 8 * 1000 * 8)
-				: (19 *  64 * 1 * 1000 * 8);
+				: (19 *  64 * 1 * 1000 * 8));
 
 		req->length = 16;
 		value = usb_ep_queue (ep, req, GFP_ATOMIC);
@@ -1300,9 +1234,9 @@
 
 static void issue_start_status (struct eth_dev *dev)
 {
-	struct usb_request	*req;
-	struct cdc_notification	*event;
-	int			value;
+	struct usb_request		*req;
+	struct usb_cdc_notification	*event;
+	int				value;
  
 	DEBUG (dev, "%s, flush old status first\n", __FUNCTION__);
 
@@ -1336,7 +1270,7 @@
 	 */
 	event = req->buf;
 	event->bmRequestType = 0xA1;
-	event->bNotificationType = CDC_NOTIFY_NETWORK_CONNECTION;
+	event->bNotificationType = USB_CDC_NOTIFY_NETWORK_CONNECTION;
 	event->wValue = __constant_cpu_to_le16 (1);	/* connected */
 	event->wIndex = __constant_cpu_to_le16 (1);
 	event->wLength = 0;
@@ -1364,26 +1298,6 @@
 				req->status, req->actual, req->length);
 }
 
-/* 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_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)
@@ -1393,7 +1307,7 @@
 			"rndis response complete --> %d, %d/%d\n",
 			req->status, req->actual, req->length);
 
-	/* done sending after CDC_GET_ENCAPSULATED_RESPONSE */
+	/* done sending after USB_CDC_GET_ENCAPSULATED_RESPONSE */
 }
 
 static void rndis_command_complete (struct usb_ep *ep, struct usb_request *req)
@@ -1401,7 +1315,7 @@
 	struct eth_dev          *dev = ep->driver_data;
 	int			status;
 	
-	/* received RNDIS command from CDC_SEND_ENCAPSULATED_COMMAND */
+	/* received RNDIS command from USB_CDC_SEND_ENCAPSULATED_COMMAND */
 	spin_lock(&dev->lock);
 	status = rndis_msg_parser (dev->rndis_config, (u8 *) req->buf);
 	if (status < 0)
@@ -1426,6 +1340,9 @@
 	struct eth_dev		*dev = get_gadget_data (gadget);
 	struct usb_request	*req = dev->req;
 	int			value = -EOPNOTSUPP;
+	u16			wIndex = ctrl->wIndex;
+	u16			wValue = ctrl->wValue;
+	u16			wLength = ctrl->wLength;
 
 	/* descriptors just go into the pre-allocated ep0 buffer,
 	 * while config change events may enable network traffic.
@@ -1436,17 +1353,17 @@
 	case USB_REQ_GET_DESCRIPTOR:
 		if (ctrl->bRequestType != USB_DIR_IN)
 			break;
-		switch (ctrl->wValue >> 8) {
+		switch (wValue >> 8) {
 
 		case USB_DT_DEVICE:
-			value = min (ctrl->wLength, (u16) sizeof device_desc);
+			value = min (wLength, (u16) sizeof device_desc);
 			memcpy (req->buf, &device_desc, value);
 			break;
 #ifdef CONFIG_USB_GADGET_DUALSPEED
 		case USB_DT_DEVICE_QUALIFIER:
 			if (!gadget->is_dualspeed)
 				break;
-			value = min (ctrl->wLength, (u16) sizeof dev_qualifier);
+			value = min (wLength, (u16) sizeof dev_qualifier);
 			memcpy (req->buf, &dev_qualifier, value);
 			break;
 
@@ -1457,18 +1374,18 @@
 #endif /* CONFIG_USB_GADGET_DUALSPEED */
 		case USB_DT_CONFIG:
 			value = config_buf (gadget->speed, req->buf,
-					ctrl->wValue >> 8,
-					ctrl->wValue & 0xff,
+					wValue >> 8,
+					wValue & 0xff,
 					gadget->is_otg);
 			if (value >= 0)
-				value = min (ctrl->wLength, (u16) value);
+				value = min (wLength, (u16) value);
 			break;
 
 		case USB_DT_STRING:
 			value = usb_gadget_get_string (&stringtab,
-					ctrl->wValue & 0xff, req->buf);
+					wValue & 0xff, req->buf);
 			if (value >= 0)
-				value = min (ctrl->wLength, (u16) value);
+				value = min (wLength, (u16) value);
 			break;
 		}
 		break;
@@ -1481,22 +1398,22 @@
 		else if (gadget->a_alt_hnp_support)
 			DEBUG (dev, "HNP needs a different root port\n");
 		spin_lock (&dev->lock);
-		value = eth_set_config (dev, ctrl->wValue, GFP_ATOMIC);
+		value = eth_set_config (dev, wValue, GFP_ATOMIC);
 		spin_unlock (&dev->lock);
 		break;
 	case USB_REQ_GET_CONFIGURATION:
 		if (ctrl->bRequestType != USB_DIR_IN)
 			break;
 		*(u8 *)req->buf = dev->config;
-		value = min (ctrl->wLength, (u16) 1);
+		value = min (wLength, (u16) 1);
 		break;
 
 	case USB_REQ_SET_INTERFACE:
 		if (ctrl->bRequestType != USB_RECIP_INTERFACE
 				|| !dev->config
-				|| ctrl->wIndex > 1)
+				|| wIndex > 1)
 			break;
-		if (!dev->cdc && ctrl->wIndex != 0)
+		if (!dev->cdc && wIndex != 0)
 			break;
 		spin_lock (&dev->lock);
 
@@ -1510,9 +1427,9 @@
 		}
 
 #ifdef DEV_CONFIG_CDC
-		switch (ctrl->wIndex) {
+		switch (wIndex) {
 		case 0:		/* control/master intf */
-			if (ctrl->wValue != 0)
+			if (wValue != 0)
 				break;
 			if (dev->status_ep) {
 				usb_ep_disable (dev->status_ep);
@@ -1521,7 +1438,7 @@
 			value = 0;
 			break;
 		case 1:		/* data intf */
-			if (ctrl->wValue > 1)
+			if (wValue > 1)
 				break;
 			usb_ep_disable (dev->in_ep);
 			usb_ep_disable (dev->out_ep);
@@ -1530,7 +1447,7 @@
 			 * the default interface setting ... also, setting
 			 * the non-default interface clears filters etc.
 			 */
-			if (ctrl->wValue == 1) {
+			if (wValue == 1) {
 				usb_ep_enable (dev->in_ep, dev->in);
 				usb_ep_enable (dev->out_ep, dev->out);
 				netif_carrier_on (dev->net);
@@ -1561,36 +1478,36 @@
 	case USB_REQ_GET_INTERFACE:
 		if (ctrl->bRequestType != (USB_DIR_IN|USB_RECIP_INTERFACE)
 				|| !dev->config
-				|| ctrl->wIndex > 1)
+				|| wIndex > 1)
 			break;
-		if (!(dev->cdc || dev->rndis) && ctrl->wIndex != 0)
+		if (!(dev->cdc || dev->rndis) && wIndex != 0)
 			break;
 
 		/* for CDC, iff carrier is on, data interface is active. */
-		if (dev->rndis || ctrl->wIndex != 1)
+		if (dev->rndis || wIndex != 1)
 			*(u8 *)req->buf = 0;
 		else
 			*(u8 *)req->buf = netif_carrier_ok (dev->net) ? 1 : 0;
-		value = min (ctrl->wLength, (u16) 1);
+		value = min (wLength, (u16) 1);
 		break;
 
 #ifdef DEV_CONFIG_CDC
-	case CDC_SET_ETHERNET_PACKET_FILTER:
+	case USB_CDC_SET_ETHERNET_PACKET_FILTER:
 		/* see 6.2.30: no data, wIndex = interface,
 		 * wValue = packet filter bitmap
 		 */
 		if (ctrl->bRequestType != (USB_TYPE_CLASS|USB_RECIP_INTERFACE)
 				|| !dev->cdc
 				|| dev->rndis
-				|| ctrl->wLength != 0
-				|| ctrl->wIndex > 1)
+				|| wLength != 0
+				|| wIndex > 1)
 			break;
-		DEBUG (dev, "NOP packet filter %04x\n", ctrl->wValue);
+		DEBUG (dev, "NOP packet filter %04x\n", wValue);
 		/* NOTE: table 62 has 5 filter bits to reduce traffic,
 		 * and we "must" support multicast and promiscuous.
 		 * this NOP implements a bad filter (always promisc)
 		 */
-		dev->cdc_filter = ctrl->wValue;
+		dev->cdc_filter = wValue;
 		value = 0;
 		break;
 #endif /* DEV_CONFIG_CDC */
@@ -1599,28 +1516,28 @@
 	/* 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:
+	case USB_CDC_SEND_ENCAPSULATED_COMMAND:
 		if (ctrl->bRequestType != (USB_TYPE_CLASS|USB_RECIP_INTERFACE)
 				|| !dev->rndis
-				|| ctrl->wLength > USB_BUFSIZ
-				|| ctrl->wValue
+				|| wLength > USB_BUFSIZ
+				|| wValue
 				|| rndis_control_intf.bInterfaceNumber
-					!= ctrl->wIndex)
+					!= wIndex)
 			break;
 		/* read the request, then process it */
-		value = ctrl->wLength;
+		value = wLength;
 		req->complete = rndis_command_complete;
 		/* later, rndis_control_ack () sends a notification */
 		break;
 		
-	case CDC_GET_ENCAPSULATED_RESPONSE:
+	case USB_CDC_GET_ENCAPSULATED_RESPONSE:
 		if ((USB_DIR_IN|USB_TYPE_CLASS|USB_RECIP_INTERFACE)
 					== ctrl->bRequestType
 				&& dev->rndis
-				// && ctrl->wLength >= 0x0400
-				&& !ctrl->wValue
+				// && wLength >= 0x0400
+				&& !wValue
 				&& rndis_control_intf.bInterfaceNumber
-					== ctrl->wIndex) {
+					== wIndex) {
 			u8 *buf;
 
 			/* return the result */
@@ -1640,13 +1557,13 @@
 		VDEBUG (dev,
 			"unknown control req%02x.%02x v%04x i%04x l%d\n",
 			ctrl->bRequestType, ctrl->bRequest,
-			ctrl->wValue, ctrl->wIndex, ctrl->wLength);
+			wValue, wIndex, wLength);
 	}
 
 	/* respond with data transfer before status phase? */
 	if (value >= 0) {
 		req->length = value;
-		req->zero = value < ctrl->wLength
+		req->zero = value < wLength
 				&& (value % gadget->ep0->maxpacket) == 0;
 		value = usb_ep_queue (gadget->ep0, req, GFP_ATOMIC);
 		if (value < 0) {
@@ -1761,10 +1678,16 @@
 #endif	
 	size -= size % dev->out_ep->maxpacket;
 
-	if ((skb = alloc_skb (size, gfp_flags)) == 0) {
+	if ((skb = alloc_skb (size + NET_IP_ALIGN, gfp_flags)) == 0) {
 		DEBUG (dev, "no rx skb\n");
 		goto enomem;
 	}
+	
+	/* Some platforms perform better when IP packets are aligned,
+	 * but on at least one, checksumming fails otherwise.  Note:
+	 * this doesn't account for variable-sized RNDIS headers.
+	 */
+	skb_reserve(skb, NET_IP_ALIGN);
 
 	req->buf = skb->data;
 	req->length = size;
@@ -1990,7 +1913,7 @@
 	unsigned long		flags;
 
 	/* FIXME check dev->cdc_filter to decide whether to send this,
-	 * instead of acting as if CDC_PACKET_TYPE_PROMISCUOUS were
+	 * instead of acting as if USB_CDC_PACKET_TYPE_PROMISCUOUS were
 	 * always set.  RNDIS has the same kind of outgoing filter.
 	 */
 
@@ -2124,13 +2047,13 @@
 	}
 	
 	/* Send RNDIS RESPONSE_AVAILABLE notification;
-	 * CDC_NOTIFY_RESPONSE_AVAILABLE should work too
+	 * USB_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);
+	*((__le32 *) resp->buf) = __constant_cpu_to_le32 (1);
+	*((__le32 *) resp->buf + 1) = __constant_cpu_to_le32 (0);
 	
 	length = usb_ep_queue (dev->status_ep, resp, GFP_ATOMIC);
 	if (length < 0) {
@@ -2326,6 +2249,8 @@
 		device_desc.bcdDevice = __constant_cpu_to_le16 (0x0210);
 	} else if (gadget_is_pxa27x(gadget)) {
 		device_desc.bcdDevice = __constant_cpu_to_le16 (0x0211);
+ 	} else if (gadget_is_s3c2410(gadget)) {
+ 		device_desc.bcdDevice = __constant_cpu_to_le16 (0x0212);
 	} else {
 		/* can't assume CDC works.  don't want to default to
 		 * anything less functional on CDC-capable hardware,
@@ -2414,9 +2339,12 @@
 				"can't run RNDIS on %s\n",
 				gadget->name);
 			return -ENODEV;
+#ifdef DEV_CONFIG_CDC
+		/* pxa25x only does CDC subset; often used with RNDIS */
 		} else if (cdc) {
 			control_intf.bNumEndpoints = 0;
 			/* FIXME remove endpoint from descriptor list */
+#endif
 		}
 	}
 #endif
diff -Nru a/drivers/usb/gadget/gadget_chips.h b/drivers/usb/gadget/gadget_chips.h
--- a/drivers/usb/gadget/gadget_chips.h	2005-03-11 12:51:40 -08:00
+++ b/drivers/usb/gadget/gadget_chips.h	2005-03-11 12:51:40 -08:00
@@ -74,6 +74,12 @@
 #define	gadget_is_pxa27x(g)	0
 #endif
 
+#ifdef CONFIG_USB_GADGET_S3C2410
+#define gadget_is_s3c2410(g)    !strcmp("s3c2410_udc", (g)->name)
+#else
+#define gadget_is_s3c2410(g)    0
+#endif
+
 // CONFIG_USB_GADGET_AT91RM9200
 // CONFIG_USB_GADGET_SX2
 // CONFIG_USB_GADGET_AU1X00
diff -Nru a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c
--- a/drivers/usb/gadget/net2280.c	2005-03-11 12:51:41 -08:00
+++ b/drivers/usb/gadget/net2280.c	2005-03-11 12:51:41 -08:00
@@ -1,8 +1,9 @@
 /*
- * Driver for the NetChip 2280 USB device controller.
- * Specs and errata are available from <http://www.netchip.com>.
+ * Driver for the PLX NET2280 USB device controller.
+ * Specs and errata are available from <http://www.plxtech.com>.
  *
- * NetChip Technology Inc. supported the development of this driver.
+ * PLX Technology Inc. (formerly NetChip Technology) supported the 
+ * development of this driver.
  *
  *
  * CODE STATUS HIGHLIGHTS
@@ -23,7 +24,7 @@
 
 /*
  * Copyright (C) 2003 David Brownell
- * Copyright (C) 2003 NetChip Technologies
+ * Copyright (C) 2003-2005 PLX Technology, Inc.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -69,8 +70,8 @@
 #include <asm/unaligned.h>
 
 
-#define	DRIVER_DESC		"NetChip 2280 USB Peripheral Controller"
-#define	DRIVER_VERSION		"2004 Jan 14"
+#define	DRIVER_DESC		"PLX NET2280 USB Peripheral Controller"
+#define	DRIVER_VERSION		"2005 Feb 03"
 
 #define	DMA_ADDR_INVALID	(~(dma_addr_t)0)
 #define	EP_DONTUSE		13	/* nonzero */
@@ -113,6 +114,16 @@
 /* "modprobe net2280 fifo_mode=1" etc */
 module_param (fifo_mode, ushort, 0644);
 
+/* enable_suspend -- When enabled, the driver will respond to
+ * USB suspend requests by powering down the NET2280.  Otherwise,
+ * USB suspend requests will be ignored.  This is acceptible for
+ * self-powered devices, and helps avoid some quirks.
+ */
+static int enable_suspend = 0;
+
+/* "modprobe net2280 enable_suspend=1" etc */
+module_param (enable_suspend, bool, S_IRUGO);
+
 
 #define	DIR_STRING(bAddress) (((bAddress) & USB_DIR_IN) ? "in" : "out")
 
@@ -2561,6 +2572,8 @@
 		if (stat & (1 << SUSPEND_REQUEST_INTERRUPT)) {
 			if (dev->driver->suspend)
 				dev->driver->suspend (&dev->gadget);
+			if (!enable_suspend)
+				stat &= ~(1 << SUSPEND_REQUEST_INTERRUPT);
 		} else {
 			if (dev->driver->resume)
 				dev->driver->resume (&dev->gadget);
diff -Nru a/drivers/usb/gadget/omap_udc.c b/drivers/usb/gadget/omap_udc.c
--- a/drivers/usb/gadget/omap_udc.c	2005-03-11 12:51:42 -08:00
+++ b/drivers/usb/gadget/omap_udc.c	2005-03-11 12:51:42 -08:00
@@ -2,7 +2,7 @@
  * omap_udc.c -- for OMAP full speed udc; most chips support OTG.
  *
  * Copyright (C) 2004 Texas Instruments, Inc.
- * Copyright (C) 2004 David Brownell
+ * Copyright (C) 2004-2005 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
@@ -2046,7 +2046,10 @@
 			pullup_disable (udc);
 	}
 
-	if (machine_is_omap_innovator())
+	/* boards that don't have VBUS sensing can't autogate 48MHz;
+	 * can't enter deep sleep while a gadget driver is active.
+	 */
+	if (machine_is_omap_innovator() || machine_is_omap_osk())
 		omap_vbus_session(&udc->gadget, 1);
 
 done:
@@ -2064,7 +2067,7 @@
 	if (!driver || driver != udc->driver)
 		return -EINVAL;
 
-	if (machine_is_omap_innovator())
+	if (machine_is_omap_innovator() || machine_is_omap_osk())
 		omap_vbus_session(&udc->gadget, 0);
 
 	if (udc->transceiver)
@@ -2157,13 +2160,13 @@
 		}
 }
 
-static char *trx_mode(unsigned m)
+static char *trx_mode(unsigned m, int enabled)
 {
 	switch (m) {
-	case 3:
-	case 0:		return "6wire";
+	case 0:		return enabled ? "*6wire" : "unused";
 	case 1:		return "4wire";
 	case 2:		return "3wire";
+	case 3: 	return "6wire";
 	default:	return "unknown";
 	}
 }
@@ -2171,17 +2174,20 @@
 static int proc_otg_show(struct seq_file *s)
 {
 	u32		tmp;
+	u32		trans;
 
 	tmp = OTG_REV_REG;
-	seq_printf(s, "OTG rev %d.%d, transceiver_ctrl %08x\n",
-		tmp >> 4, tmp & 0xf,
-		USB_TRANSCEIVER_CTRL_REG);
+	trans = USB_TRANSCEIVER_CTRL_REG;
+	seq_printf(s, "OTG rev %d.%d, transceiver_ctrl %03x\n",
+		tmp >> 4, tmp & 0xf, trans);
 	tmp = OTG_SYSCON_1_REG;
 	seq_printf(s, "otg_syscon1 %08x usb2 %s, usb1 %s, usb0 %s,"
 			FOURBITS "\n", tmp,
-		trx_mode(USB2_TRX_MODE(tmp)),
-		trx_mode(USB1_TRX_MODE(tmp)),
-		trx_mode(USB0_TRX_MODE(tmp)),
+		trx_mode(USB2_TRX_MODE(tmp), trans & CONF_USB2_UNI_R),
+		trx_mode(USB1_TRX_MODE(tmp), trans & CONF_USB1_UNI_R),
+		(USB0_TRX_MODE(tmp) == 0)
+			? "internal"
+			: trx_mode(USB0_TRX_MODE(tmp), 1),
 		(tmp & OTG_IDLE_EN) ? " !otg" : "",
 		(tmp & HST_IDLE_EN) ? " !host" : "",
 		(tmp & DEV_IDLE_EN) ? " !dev" : "",
diff -Nru a/drivers/usb/gadget/pxa2xx_udc.c b/drivers/usb/gadget/pxa2xx_udc.c
--- a/drivers/usb/gadget/pxa2xx_udc.c	2005-03-11 12:51:47 -08:00
+++ b/drivers/usb/gadget/pxa2xx_udc.c	2005-03-11 12:51:47 -08:00
@@ -943,6 +943,7 @@
 						UDCCFR = UDCCFR_AREN|UDCCFR_ACM;
 					done(ep, req, 0);
 					dev->ep0state = EP0_END_XFER;
+					local_irq_restore (flags);
 					return 0;
 				}
 				if (dev->req_pending)
diff -Nru a/drivers/usb/gadget/rndis.c b/drivers/usb/gadget/rndis.c
--- a/drivers/usb/gadget/rndis.c	2005-03-11 12:51:41 -08:00
+++ b/drivers/usb/gadget/rndis.c	2005-03-11 12:51:41 -08:00
@@ -730,7 +730,7 @@
 
 		/* 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:
+		 * NDIS_PACKET_TYPE_x == USB_CDC_PACKET_TYPE_x for x in:
 		 *	PROMISCUOUS, DIRECTED,
 		 *	MULTICAST, ALL_MULTICAST, BROADCAST
 		 */
diff -Nru a/drivers/usb/gadget/serial.c b/drivers/usb/gadget/serial.c
--- a/drivers/usb/gadget/serial.c	2005-03-11 12:51:50 -08:00
+++ b/drivers/usb/gadget/serial.c	2005-03-11 12:51:50 -08:00
@@ -45,6 +45,7 @@
 #include <asm/uaccess.h>
 
 #include <linux/usb_ch9.h>
+#include <linux/usb_cdc.h>
 #include <linux/usb_gadget.h>
 
 #include "gadget_chips.h"
@@ -122,80 +123,6 @@
 })
 
 
-/* CDC-ACM Defines and Structures */
-
-#define USB_CDC_SUBCLASS_ACM			2
-
-#define USB_CDC_CTRL_PROTO_NONE			0
-#define USB_CDC_CTRL_PROTO_AT			1
-#define USB_CDC_CTRL_PROTO_VENDOR		0xff
-
-#define USB_CDC_SUBTYPE_HEADER			0
-#define USB_CDC_SUBTYPE_CALL_MGMT		1
-#define USB_CDC_SUBTYPE_ACM			2
-#define USB_CDC_SUBTYPE_UNION			6
-
-#define USB_CDC_CALL_MGMT_CAP_CALL_MGMT		0x01
-#define USB_CDC_CALL_MGMT_CAP_DATA_INTF		0x02
-
-#define USB_CDC_REQ_SET_LINE_CODING		0x20
-#define USB_CDC_REQ_GET_LINE_CODING		0x21
-#define USB_CDC_REQ_SET_CONTROL_LINE_STATE	0x22
-
-#define USB_CDC_1_STOP_BITS			0
-#define USB_CDC_1_5_STOP_BITS			1
-#define USB_CDC_2_STOP_BITS			2
-
-#define USB_CDC_NO_PARITY			0
-#define USB_CDC_ODD_PARITY			1
-#define USB_CDC_EVEN_PARITY			2
-#define USB_CDC_MARK_PARITY			3
-#define USB_CDC_SPACE_PARITY			4
-
-/* Header Functional Descriptor from CDC spec 5.2.3.1 */
-struct usb_cdc_header_desc {
-	u8	bLength;
-	u8	bDescriptorType;
-	u8	bDescriptorSubType;
-	u16	bcdCDC;
-} __attribute__ ((packed));
-
-/* Call Management Descriptor from CDC spec 5.2.3.3 */
-struct usb_cdc_call_mgmt_desc {
-	u8  bLength;
-	u8  bDescriptorType;
-	u8  bDescriptorSubType;
-	u8  bmCapabilities;
-	u8  bDataInterface;
-} __attribute__ ((packed));
-
-/* Abstract Control Management Descriptor from CDC spec 5.2.3.4 */
-struct usb_cdc_acm_desc {
-	u8  bLength;
-	u8  bDescriptorType;
-	u8  bDescriptorSubType;
-	u8  bmCapabilities;
-} __attribute__ ((packed));
-
-/* Union Functional Descriptor from CDC spec 5.2.3.8 */
-struct usb_cdc_union_desc {
-	u8	bLength;
-	u8	bDescriptorType;
-	u8	bDescriptorSubType;
-	u8	bMasterInterface0;
-	u8	bSlaveInterface0;
-	/* ... and there could be other slave interfaces */
-} __attribute__ ((packed));
-
-/* Line Coding Structure from CDC spec 6.2.13 */
-struct usb_cdc_line_coding {
-	u32 dwDTERate;
-	u8 bCharFormat;
-	u8 bParityType;
-	u8 bDataBits;
-} __attribute__ ((packed));
-
-
 /* Defines */
 
 #define GS_VERSION_STR			"v2.0"
@@ -542,7 +469,7 @@
 	.bNumEndpoints =	1,
 	.bInterfaceClass =	USB_CLASS_COMM,
 	.bInterfaceSubClass =	USB_CDC_SUBCLASS_ACM,
-	.bInterfaceProtocol =	USB_CDC_CTRL_PROTO_AT,
+	.bInterfaceProtocol =	USB_CDC_ACM_PROTO_AT_V25TER,
 	.iInterface =		GS_CONTROL_STR_ID,
 };
 
@@ -560,29 +487,29 @@
 static const struct usb_cdc_header_desc gs_header_desc = {
 	.bLength =		sizeof(gs_header_desc),
 	.bDescriptorType =	USB_DT_CS_INTERFACE,
-	.bDescriptorSubType =	USB_CDC_SUBTYPE_HEADER,
+	.bDescriptorSubType =	USB_CDC_HEADER_TYPE,
 	.bcdCDC =		__constant_cpu_to_le16(0x0110),
 };
 
-static const struct usb_cdc_call_mgmt_desc gs_call_mgmt_descriptor = {
+static const struct usb_cdc_call_mgmt_descriptor gs_call_mgmt_descriptor = {
 	.bLength =  		sizeof(gs_call_mgmt_descriptor),
 	.bDescriptorType = 	USB_DT_CS_INTERFACE,
-	.bDescriptorSubType = 	USB_CDC_SUBTYPE_CALL_MGMT,
+	.bDescriptorSubType = 	USB_CDC_CALL_MANAGEMENT_TYPE,
 	.bmCapabilities = 	0,
 	.bDataInterface = 	1,	/* index of data interface */
 };
 
-static struct usb_cdc_acm_desc gs_acm_descriptor = {
+static struct usb_cdc_acm_descriptor gs_acm_descriptor = {
 	.bLength =  		sizeof(gs_acm_descriptor),
 	.bDescriptorType = 	USB_DT_CS_INTERFACE,
-	.bDescriptorSubType = 	USB_CDC_SUBTYPE_ACM,
+	.bDescriptorSubType = 	USB_CDC_ACM_TYPE,
 	.bmCapabilities = 	0,
 };
 
 static const struct usb_cdc_union_desc gs_union_desc = {
 	.bLength =		sizeof(gs_union_desc),
 	.bDescriptorType =	USB_DT_CS_INTERFACE,
-	.bDescriptorSubType =	USB_CDC_SUBTYPE_UNION,
+	.bDescriptorSubType =	USB_CDC_UNION_TYPE,
 	.bMasterInterface0 =	0,	/* index of control interface */
 	.bSlaveInterface0 =	1,	/* index of data interface */
 };
@@ -1531,6 +1458,9 @@
 	} else if (gadget_is_pxa27x(gadget)) {
 		gs_device_desc.bcdDevice =
 			__constant_cpu_to_le16(GS_VERSION_NUM|0x0011);
+	} else if (gadget_is_s3c2410(gadget)) {
+		gs_device_desc.bcdDevice =
+			__constant_cpu_to_le16(GS_VERSION_NUM|0x0012);
 	} else {
 		printk(KERN_WARNING "gs_bind: controller '%s' not recognized\n",
 			gadget->name);
@@ -1674,6 +1604,9 @@
 	int ret = -EOPNOTSUPP;
 	struct gs_dev *dev = get_gadget_data(gadget);
 	struct usb_request *req = dev->dev_ctrl_req;
+	u16 wIndex = ctrl->wIndex;
+	u16 wValue = ctrl->wValue;
+	u16 wLength = ctrl->wLength;
 
 	switch (ctrl->bRequestType & USB_TYPE_MASK) {
 	case USB_TYPE_STANDARD:
@@ -1686,15 +1619,15 @@
 
 	default:
 		printk(KERN_ERR "gs_setup: unknown request, type=%02x, request=%02x, value=%04x, index=%04x, length=%d\n",
-			ctrl->bRequestType, ctrl->bRequest, ctrl->wValue,
-			ctrl->wIndex, ctrl->wLength);
+			ctrl->bRequestType, ctrl->bRequest,
+			wValue, wIndex, wLength);
 		break;
 	}
 
 	/* respond with data transfer before status phase? */
 	if (ret >= 0) {
 		req->length = ret;
-		req->zero = ret < ctrl->wLength
+		req->zero = ret < wLength
 				&& (ret % gadget->ep0->maxpacket) == 0;
 		ret = usb_ep_queue(gadget->ep0, req, GFP_ATOMIC);
 		if (ret < 0) {
@@ -1715,15 +1648,18 @@
 	int ret = -EOPNOTSUPP;
 	struct gs_dev *dev = get_gadget_data(gadget);
 	struct usb_request *req = dev->dev_ctrl_req;
+	u16 wIndex = ctrl->wIndex;
+	u16 wValue = ctrl->wValue;
+	u16 wLength = ctrl->wLength;
 
 	switch (ctrl->bRequest) {
 	case USB_REQ_GET_DESCRIPTOR:
 		if (ctrl->bRequestType != USB_DIR_IN)
 			break;
 
-		switch (ctrl->wValue >> 8) {
+		switch (wValue >> 8) {
 		case USB_DT_DEVICE:
-			ret = min(ctrl->wLength,
+			ret = min(wLength,
 				(u16)sizeof(struct usb_device_descriptor));
 			memcpy(req->buf, &gs_device_desc, ret);
 			break;
@@ -1732,7 +1668,7 @@
 		case USB_DT_DEVICE_QUALIFIER:
 			if (!gadget->is_dualspeed)
 				break;
-			ret = min(ctrl->wLength,
+			ret = min(wLength,
 				(u16)sizeof(struct usb_qualifier_descriptor));
 			memcpy(req->buf, &gs_qualifier_desc, ret);
 			break;
@@ -1744,18 +1680,18 @@
 #endif /* CONFIG_USB_GADGET_DUALSPEED */
 		case USB_DT_CONFIG:
 			ret = gs_build_config_buf(req->buf, gadget->speed,
-				ctrl->wValue >> 8, ctrl->wValue & 0xff,
+				wValue >> 8, wValue & 0xff,
 				gadget->is_otg);
 			if (ret >= 0)
-				ret = min(ctrl->wLength, (u16)ret);
+				ret = min(wLength, (u16)ret);
 			break;
 
 		case USB_DT_STRING:
 			/* wIndex == language code. */
 			ret = usb_gadget_get_string(&gs_string_table,
-				ctrl->wValue & 0xff, req->buf);
+				wValue & 0xff, req->buf);
 			if (ret >= 0)
-				ret = min(ctrl->wLength, (u16)ret);
+				ret = min(wLength, (u16)ret);
 			break;
 		}
 		break;
@@ -1764,7 +1700,7 @@
 		if (ctrl->bRequestType != 0)
 			break;
 		spin_lock(&dev->dev_lock);
-		ret = gs_set_config(dev, ctrl->wValue);
+		ret = gs_set_config(dev, wValue);
 		spin_unlock(&dev->dev_lock);
 		break;
 
@@ -1772,18 +1708,19 @@
 		if (ctrl->bRequestType != USB_DIR_IN)
 			break;
 		*(u8 *)req->buf = dev->dev_config;
-		ret = min(ctrl->wLength, (u16)1);
+		ret = min(wLength, (u16)1);
 		break;
 
 	case USB_REQ_SET_INTERFACE:
 		if (ctrl->bRequestType != USB_RECIP_INTERFACE
-		|| !dev->dev_config || ctrl->wIndex >= GS_MAX_NUM_INTERFACES)
+				|| !dev->dev_config
+				|| wIndex >= GS_MAX_NUM_INTERFACES)
 			break;
 		if (dev->dev_config == GS_BULK_CONFIG_ID
-		&& ctrl->wIndex != GS_BULK_INTERFACE_ID)
+				&& wIndex != GS_BULK_INTERFACE_ID)
 			break;
 		/* no alternate interface settings */
-		if (ctrl->wValue != 0)
+		if (wValue != 0)
 			break;
 		spin_lock(&dev->dev_lock);
 		/* PXA hardware partially handles SET_INTERFACE;
@@ -1794,7 +1731,7 @@
 			goto set_interface_done;
 		}
 		if (dev->dev_config != GS_BULK_CONFIG_ID
-		&& ctrl->wIndex == GS_CONTROL_INTERFACE_ID) {
+				&& wIndex == GS_CONTROL_INTERFACE_ID) {
 			if (dev->dev_notify_ep) {
 				usb_ep_disable(dev->dev_notify_ep);
 				usb_ep_enable(dev->dev_notify_ep, dev->dev_notify_ep_desc);
@@ -1814,21 +1751,21 @@
 		if (ctrl->bRequestType != (USB_DIR_IN|USB_RECIP_INTERFACE)
 		|| dev->dev_config == GS_NO_CONFIG_ID)
 			break;
-		if (ctrl->wIndex >= GS_MAX_NUM_INTERFACES
-		|| (dev->dev_config == GS_BULK_CONFIG_ID
-		&& ctrl->wIndex != GS_BULK_INTERFACE_ID)) {
+		if (wIndex >= GS_MAX_NUM_INTERFACES
+				|| (dev->dev_config == GS_BULK_CONFIG_ID
+				&& wIndex != GS_BULK_INTERFACE_ID)) {
 			ret = -EDOM;
 			break;
 		}
 		/* no alternate interface settings */
 		*(u8 *)req->buf = 0;
-		ret = min(ctrl->wLength, (u16)1);
+		ret = min(wLength, (u16)1);
 		break;
 
 	default:
 		printk(KERN_ERR "gs_setup: unknown standard request, type=%02x, request=%02x, value=%04x, index=%04x, length=%d\n",
-			ctrl->bRequestType, ctrl->bRequest, ctrl->wValue,
-			ctrl->wIndex, ctrl->wLength);
+			ctrl->bRequestType, ctrl->bRequest,
+			wValue, wIndex, wLength);
 		break;
 	}
 
@@ -1842,10 +1779,13 @@
 	struct gs_dev *dev = get_gadget_data(gadget);
 	struct gs_port *port = dev->dev_port[0];	/* ACM only has one port */
 	struct usb_request *req = dev->dev_ctrl_req;
+	u16 wIndex = ctrl->wIndex;
+	u16 wValue = ctrl->wValue;
+	u16 wLength = ctrl->wLength;
 
 	switch (ctrl->bRequest) {
 	case USB_CDC_REQ_SET_LINE_CODING:
-		ret = min(ctrl->wLength,
+		ret = min(wLength,
 			(u16)sizeof(struct usb_cdc_line_coding));
 		if (port) {
 			spin_lock(&port->port_lock);
@@ -1856,7 +1796,7 @@
 
 	case USB_CDC_REQ_GET_LINE_CODING:
 		port = dev->dev_port[0];	/* ACM only has one port */
-		ret = min(ctrl->wLength,
+		ret = min(wLength,
 			(u16)sizeof(struct usb_cdc_line_coding));
 		if (port) {
 			spin_lock(&port->port_lock);
@@ -1871,8 +1811,8 @@
 
 	default:
 		printk(KERN_ERR "gs_setup: unknown class request, type=%02x, request=%02x, value=%04x, index=%04x, length=%d\n",
-			ctrl->bRequestType, ctrl->bRequest, ctrl->wValue,
-			ctrl->wIndex, ctrl->wLength);
+			ctrl->bRequestType, ctrl->bRequest,
+			wValue, wIndex, wLength);
 		break;
 	}
 
@@ -2272,7 +2212,7 @@
 		memset(port, 0, sizeof(struct gs_port));
 		port->port_dev = dev;
 		port->port_num = i;
-		port->port_line_coding.dwDTERate = GS_DEFAULT_DTE_RATE;
+		port->port_line_coding.dwDTERate = cpu_to_le32(GS_DEFAULT_DTE_RATE);
 		port->port_line_coding.bCharFormat = GS_DEFAULT_CHAR_FORMAT;
 		port->port_line_coding.bParityType = GS_DEFAULT_PARITY;
 		port->port_line_coding.bDataBits = GS_DEFAULT_DATA_BITS;
@@ -2324,6 +2264,7 @@
 				}
 				spin_unlock_irqrestore(&port->port_lock, flags);
 			} else {
+				spin_unlock_irqrestore(&port->port_lock, flags);
 				kfree(port);
 			}
 
diff -Nru a/drivers/usb/gadget/zero.c b/drivers/usb/gadget/zero.c
--- a/drivers/usb/gadget/zero.c	2005-03-11 12:51:42 -08:00
+++ b/drivers/usb/gadget/zero.c	2005-03-11 12:51:42 -08:00
@@ -1191,6 +1191,8 @@
 		device_desc.bcdDevice = __constant_cpu_to_le16 (0x0210);
 	} else if (gadget_is_pxa27x(gadget)) {
 		device_desc.bcdDevice = __constant_cpu_to_le16 (0x0211);
+	} else if (gadget_is_s3c2410(gadget)) {
+		device_desc.bcdDevice = __constant_cpu_to_le16 (0x0212);
 	} else {
 		/* gadget zero is so simple (for now, no altsettings) that
 		 * it SHOULD NOT have problems with bulk-capable hardware.
diff -Nru a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
--- a/drivers/usb/host/Kconfig	2005-03-11 12:51:51 -08:00
+++ b/drivers/usb/host/Kconfig	2005-03-11 12:51:51 -08:00
@@ -7,13 +7,20 @@
 	default y if ARM				# SL-811
 	default PCI
 
-# many non-PCI hcds implement OHCI
+# many non-PCI SOC chips embed OHCI
 config USB_ARCH_HAS_OHCI
 	boolean
+	# ARM:
 	default y if SA1111
 	default y if ARCH_OMAP
 	default y if ARCH_LH7A404
 	default y if PXA27x
+	# PPC:
+	default y if STB03xxx
+	default y if PPC_MPC52xx
+	# MIPS:
+	default y if SOC_AU1X00
+	# more:
 	default PCI
 
 #
@@ -65,7 +72,7 @@
 	  controller is needed.  It's safe to say "y" even if your
 	  controller doesn't support this feature.
 
-	  This supports the EHCI implementation from ARC International.
+	  This supports the EHCI implementation from TransDimension Inc.
 
 config USB_OHCI_HCD
 	tristate "OHCI HCD support"
@@ -83,6 +90,35 @@
 
 	  To compile this driver as a module, choose M here: the
 	  module will be called ohci-hcd.
+
+config USB_OHCI_HCD_PPC_SOC
+	bool "OHCI support for on-chip PPC USB controller"
+	depends on USB_OHCI_HCD && (STB03xxx || PPC_MPC52xx)
+	default y
+	select USB_OHCI_BIG_ENDIAN
+	---help---
+	  Enables support for the USB controller on the MPC52xx or
+	  STB03xxx processor chip.  If unsure, say Y.
+
+config USB_OHCI_HCD_PCI
+	bool "OHCI support for PCI-bus USB controllers"
+	depends on USB_OHCI_HCD && PCI && (STB03xxx || PPC_MPC52xx)
+	default y
+	select USB_OHCI_LITTLE_ENDIAN
+	---help---
+	  Enables support for PCI-bus plug-in USB controller cards.
+	  If unsure, say Y.
+
+config USB_OHCI_BIG_ENDIAN
+	bool
+	depends on USB_OHCI_HCD
+	default n
+
+config USB_OHCI_LITTLE_ENDIAN
+	bool
+	depends on USB_OHCI_HCD
+	default n if STB03xxx || PPC_MPC52xx
+	default y
 
 config USB_UHCI_HCD
 	tristate "UHCI HCD (most Intel and VIA) support"
diff -Nru a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
--- a/drivers/usb/host/ehci-hcd.c	2005-03-11 12:51:52 -08:00
+++ b/drivers/usb/host/ehci-hcd.c	2005-03-11 12:51:52 -08:00
@@ -191,9 +191,22 @@
 	return handshake (&ehci->regs->status, STS_HALT, STS_HALT, 16 * 125);
 }
 
+/* put TDI/ARC silicon into EHCI mode */
+static void tdi_reset (struct ehci_hcd *ehci)
+{
+	u32 __iomem	*reg_ptr;
+	u32		tmp;
+
+	reg_ptr = (u32 __iomem *)(((u8 __iomem *)ehci->regs) + 0x68);
+	tmp = readl (reg_ptr);
+	tmp |= 0x3;
+	writel (tmp, reg_ptr);
+}
+
 /* reset a non-running (STS_HALT == 1) controller */
 static int ehci_reset (struct ehci_hcd *ehci)
 {
+	int	retval;
 	u32	command = readl (&ehci->regs->command);
 
 	command |= CMD_RESET;
@@ -201,7 +214,15 @@
 	writel (command, &ehci->regs->command);
 	ehci_to_hcd(ehci)->state = USB_STATE_HALT;
 	ehci->next_statechange = jiffies;
-	return handshake (&ehci->regs->command, CMD_RESET, 0, 250 * 1000);
+	retval = handshake (&ehci->regs->command, CMD_RESET, 0, 250 * 1000);
+
+	if (retval)
+		return retval;
+
+	if (ehci_is_TDI(ehci))
+		tdi_reset (ehci);
+
+	return retval;
 }
 
 /* idle the controller (from running) */
@@ -346,11 +367,20 @@
 	if (hcd->self.controller->bus == &pci_bus_type) {
 		struct pci_dev	*pdev = to_pci_dev(hcd->self.controller);
 
-		/* AMD8111 EHCI doesn't work, according to AMD errata */
-		if ((pdev->vendor == PCI_VENDOR_ID_AMD)
-				&& (pdev->device == 0x7463)) {
-			ehci_info (ehci, "ignoring AMD8111 (errata)\n");
-			return -EIO;
+		switch (pdev->vendor) {
+		case PCI_VENDOR_ID_TDI:
+			if (pdev->device == PCI_DEVICE_ID_TDI_EHCI) {
+				ehci->is_tdi_rh_tt = 1;
+				tdi_reset (ehci);
+			}
+			break;
+		case PCI_VENDOR_ID_AMD:
+			/* AMD8111 EHCI doesn't work, according to AMD errata */
+			if (pdev->device == 0x7463) {
+				ehci_info (ehci, "ignoring AMD8111 (errata)\n");
+				return -EIO;
+			}
+			break;
 		}
 
 		temp = HCC_EXT_CAPS (readl (&ehci->caps->hcc_params));
@@ -380,6 +410,8 @@
 		ehci_err (ehci, "bogus capabilities ... PCI problems!\n");
 		return -EIO;
 	}
+	if (ehci_is_TDI(ehci))
+		ehci_reset (ehci);
 #endif
 
 	/* cache this readonly data; minimize PCI reads */
@@ -481,15 +513,6 @@
 
 		/* help hc dma work well with cachelines */
 		pci_set_mwi (pdev);
-
-		/* chip-specific init */
-		switch (pdev->vendor) {
-		case PCI_VENDOR_ID_ARC:
-			if (pdev->device == PCI_DEVICE_ID_ARC_EHCI)
-				ehci->is_arc_rh_tt = 1;
-			break;
-		}
-
 	}
 #endif
 
diff -Nru a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
--- a/drivers/usb/host/ehci-hub.c	2005-03-11 12:51:51 -08:00
+++ b/drivers/usb/host/ehci-hub.c	2005-03-11 12:51:51 -08:00
@@ -178,7 +178,7 @@
 	if (!(port_status & PORT_PE)) {
 
 		/* with integrated TT, there's nobody to hand it to! */
-		if (ehci_is_ARC(ehci)) {
+		if (ehci_is_TDI(ehci)) {
 			ehci_dbg (ehci,
 				"Failed to enable port %d on root hub TT\n",
 				index+1);
@@ -517,7 +517,7 @@
 			 * transaction translator built in.
 			 */
 			if ((temp & (PORT_PE|PORT_CONNECT)) == PORT_CONNECT
-					&& !ehci_is_ARC(ehci)
+					&& !ehci_is_TDI(ehci)
 					&& PORT_USB11 (temp)) {
 				ehci_dbg (ehci,
 					"port %d low speed --> companion\n",
diff -Nru a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
--- a/drivers/usb/host/ehci-q.c	2005-03-11 12:51:50 -08:00
+++ b/drivers/usb/host/ehci-q.c	2005-03-11 12:51:50 -08:00
@@ -198,7 +198,7 @@
 				&& urb->dev->tt && !usb_pipeint (urb->pipe)
 				&& ((token & QTD_STS_MMF) != 0
 					|| QTD_CERR(token) == 0)
-				&& (!ehci_is_ARC(ehci)
+				&& (!ehci_is_TDI(ehci)
                 	                || urb->dev->tt->hub !=
 					   ehci_to_hcd(ehci)->self.root_hub)) {
 #ifdef DEBUG
@@ -714,10 +714,10 @@
 		info2 |= (EHCI_TUNE_MULT_TT << 30);
 		info2 |= urb->dev->ttport << 23;
 
-		/* set the address of the TT; for ARC's integrated
+		/* set the address of the TT; for TDI's integrated
 		 * root hub tt, leave it zeroed.
 		 */
-		if (!ehci_is_ARC(ehci)
+		if (!ehci_is_TDI(ehci)
 				|| urb->dev->tt->hub !=
 					ehci_to_hcd(ehci)->self.root_hub)
 			info2 |= urb->dev->tt->hub->devnum << 16;
diff -Nru a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
--- a/drivers/usb/host/ehci-sched.c	2005-03-11 12:51:42 -08:00
+++ b/drivers/usb/host/ehci-sched.c	2005-03-11 12:51:42 -08:00
@@ -650,6 +650,7 @@
 
 static void
 iso_stream_init (
+	struct ehci_hcd		*ehci,
 	struct ehci_iso_stream	*stream,
 	struct usb_device	*dev,
 	int			pipe,
@@ -701,7 +702,10 @@
 		u32		addr;
 
 		addr = dev->ttport << 24;
-		addr |= dev->tt->hub->devnum << 16;
+		if (!ehci_is_TDI(ehci)
+				|| (dev->tt->hub !=
+					ehci_to_hcd(ehci)->self.root_hub))
+			addr |= dev->tt->hub->devnum << 16;
 		addr |= epnum << 8;
 		addr |= dev->devnum;
 		stream->usecs = HS_USECS_ISO (maxp);
@@ -819,7 +823,7 @@
 			/* dev->ep owns the initial refcount */
 			ep->hcpriv = stream;
 			stream->ep = ep;
-			iso_stream_init(stream, urb->dev, urb->pipe,
+			iso_stream_init(ehci, stream, urb->dev, urb->pipe,
 					urb->interval);
 		}
 
diff -Nru a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
--- a/drivers/usb/host/ehci.h	2005-03-11 12:51:51 -08:00
+++ b/drivers/usb/host/ehci.h	2005-03-11 12:51:51 -08:00
@@ -82,7 +82,7 @@
 	unsigned long		next_statechange;
 	u32			command;
 
-	unsigned		is_arc_rh_tt:1;	/* ARC roothub with TT */
+	unsigned		is_tdi_rh_tt:1;	/* TDI roothub with TT */
 
 	/* glue to PCI and HCD framework */
 	struct ehci_caps __iomem *caps;
@@ -599,13 +599,13 @@
  * needed (mostly in root hub code).
  */
 
-#define	ehci_is_ARC(e)			((e)->is_arc_rh_tt)
+#define	ehci_is_TDI(e)			((e)->is_tdi_rh_tt)
 
 /* Returns the speed of a device attached to a port on the root hub. */
 static inline unsigned int
 ehci_port_speed(struct ehci_hcd *ehci, unsigned int portsc)
 {
-	if (ehci_is_ARC(ehci)) {
+	if (ehci_is_TDI(ehci)) {
 		switch ((portsc>>26)&3) {
 		case 0:
 			return 0;
@@ -621,7 +621,7 @@
 
 #else
 
-#define	ehci_is_ARC(e)			(0)
+#define	ehci_is_TDI(e)			(0)
 
 #define	ehci_port_speed(ehci, portsc)	(1<<USB_PORT_FEAT_HIGHSPEED)
 #endif
diff -Nru a/drivers/usb/host/ohci-au1xxx.c b/drivers/usb/host/ohci-au1xxx.c
--- a/drivers/usb/host/ohci-au1xxx.c	2005-03-11 12:51:41 -08:00
+++ b/drivers/usb/host/ohci-au1xxx.c	2005-03-11 12:51:41 -08:00
@@ -70,19 +70,6 @@
 
 /*-------------------------------------------------------------------------*/
 
-
-static irqreturn_t usb_hcd_au1xxx_hcim_irq (int irq, void *__hcd,
-					     struct pt_regs * r)
-{
-	struct usb_hcd *hcd = __hcd;
-
-	return usb_hcd_irq(irq, hcd, r);
-}
-
-/*-------------------------------------------------------------------------*/
-
-void usb_hcd_au1xxx_remove (struct usb_hcd *, struct platform_device *);
-
 /* configure so an HC device and id are always provided */
 /* always called with process context; sleeping is OK */
 
@@ -97,90 +84,48 @@
  *
  */
 int usb_hcd_au1xxx_probe (const struct hc_driver *driver,
-			  struct usb_hcd **hcd_out,
 			  struct platform_device *dev)
 {
 	int retval;
-	struct usb_hcd *hcd = 0;
-
-	unsigned int *addr = NULL;
-
-	if (!request_mem_region(dev->resource[0].start,
-				dev->resource[0].end
-				- dev->resource[0].start + 1, hcd_name)) {
-		pr_debug("request_mem_region failed");
-		return -EBUSY;
-	}
-
-	au1xxx_start_hc(dev);
-
-	addr = ioremap(dev->resource[0].start,
-		       dev->resource[0].end
-		       - dev->resource[0].start + 1);
-	if (!addr) {
-		pr_debug("ioremap failed");
-		retval = -ENOMEM;
-		goto err1;
-	}
+	struct usb_hcd *hcd;
 
 	if(dev->resource[1].flags != IORESOURCE_IRQ) {
 		pr_debug ("resource[1] is not IORESOURCE_IRQ");
-		retval = -ENOMEM;
-		goto err1;
+		return -ENOMEM;
 	}
 
-	hcd = usb_create_hcd(driver);
-	if (hcd == NULL) {
-		pr_debug ("usb_create_hcd failed");
-		retval = -ENOMEM;
+	hcd = usb_create_hcd(driver, &dev->dev, "au1xxx");
+	if (!hcd)
+		return -ENOMEM;
+	hcd->rsrc_start = dev->resource[0].start;
+	hcd->rsrc_len = dev->resource[0].end - dev->resource[0].start + 1;
+
+	if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
+		pr_debug("request_mem_region failed");
+		retval = -EBUSY;
 		goto err1;
 	}
-	ohci_hcd_init(hcd_to_ohci(hcd));
 
-	hcd->irq = dev->resource[1].start;
-	hcd->regs = addr;
-	hcd->self.controller = &dev->dev;
-
-	retval = hcd_buffer_create (hcd);
-	if (retval != 0) {
-		pr_debug ("pool alloc fail");
+	hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
+	if (!hcd->regs) {
+		pr_debug("ioremap failed");
+		retval = -ENOMEM;
 		goto err2;
 	}
 
-	retval = request_irq (hcd->irq, usb_hcd_au1xxx_hcim_irq, SA_INTERRUPT,
-			      hcd->driver->description, hcd);
-	if (retval != 0) {
-		pr_debug("request_irq failed");
-		retval = -EBUSY;
-		goto err3;
-	}
-
-	pr_debug ("%s (Au1xxx) at 0x%p, irq %d",
-	     hcd->driver->description, hcd->regs, hcd->irq);
-
-	hcd->self.bus_name = "au1xxx";
-
-	usb_register_bus (&hcd->self);
+	au1xxx_start_hc(dev);
+	ohci_hcd_init(hcd_to_ohci(hcd));
 
-	if ((retval = driver->start (hcd)) < 0)
-	{
-		usb_hcd_au1xxx_remove(hcd, dev);
-		printk("bad driver->start\n");
+	retval = usb_add_hcd(hcd, dev->resource[1].start, SA_INTERRUPT);
+	if (retval == 0)
 		return retval;
-	}
 
-	*hcd_out = hcd;
-	return 0;
-
- err3:
-	hcd_buffer_destroy (hcd);
+	au1xxx_stop_hc(dev);
+	iounmap(hcd->regs);
  err2:
-	usb_put_hcd(hcd);
+	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
  err1:
-	au1xxx_stop_hc(dev);
-	release_mem_region(dev->resource[0].start,
-				dev->resource[0].end
-			   - dev->resource[0].start + 1);
+	usb_put_hcd(hcd);
 	return retval;
 }
 
@@ -200,28 +145,11 @@
  */
 void usb_hcd_au1xxx_remove (struct usb_hcd *hcd, struct platform_device *dev)
 {
-	pr_debug ("remove: %s, state %x", hcd->self.bus_name, hcd->state);
-
-	if (in_interrupt ())
-		BUG ();
-
-	hcd->state = USB_STATE_QUIESCING;
-
-	pr_debug ("%s: roothub graceful disconnect", hcd->self.bus_name);
-	usb_disconnect (&hcd->self.root_hub);
-
-	hcd->driver->stop (hcd);
-	hcd->state = USB_STATE_HALT;
-
-	free_irq (hcd->irq, hcd);
-	hcd_buffer_destroy (hcd);
-
-	usb_deregister_bus (&hcd->self);
-
+	usb_remove_hcd(hcd);
 	au1xxx_stop_hc(dev);
-	release_mem_region(dev->resource[0].start,
-			   dev->resource[0].end
-			   - dev->resource[0].start + 1);
+	iounmap(hcd->regs);
+	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+	usb_put_hcd(hcd);
 }
 
 /*-------------------------------------------------------------------------*/
@@ -257,7 +185,7 @@
 	 * generic hardware linkage
 	 */
 	.irq =			ohci_irq,
-	.flags =		HCD_USB11,
+	.flags =		HCD_USB11 | HCD_MEMORY,
 
 	/*
 	 * basic lifecycle operations
@@ -293,7 +221,6 @@
 static int ohci_hcd_au1xxx_drv_probe(struct device *dev)
 {
 	struct platform_device *pdev = to_platform_device(dev);
-	struct usb_hcd *hcd = NULL;
 	int ret;
 
 	pr_debug ("In ohci_hcd_au1xxx_drv_probe");
@@ -301,11 +228,7 @@
 	if (usb_disabled())
 		return -ENODEV;
 
-	ret = usb_hcd_au1xxx_probe(&ohci_au1xxx_hc_driver, &hcd, pdev);
-
-	if (ret == 0)
-		dev_set_drvdata(dev, hcd);
-
+	ret = usb_hcd_au1xxx_probe(&ohci_au1xxx_hc_driver, pdev);
 	return ret;
 }
 
@@ -315,7 +238,6 @@
 	struct usb_hcd *hcd = dev_get_drvdata(dev);
 
 	usb_hcd_au1xxx_remove(hcd, pdev);
-	dev_set_drvdata(dev, NULL);
 	return 0;
 }
 	/*TBD*/
diff -Nru a/drivers/usb/host/ohci-dbg.c b/drivers/usb/host/ohci-dbg.c
--- a/drivers/usb/host/ohci-dbg.c	2005-03-11 12:51:51 -08:00
+++ b/drivers/usb/host/ohci-dbg.c	2005-03-11 12:51:51 -08:00
@@ -138,7 +138,7 @@
 	ohci_dbg_sw (controller, next, size,
 		"OHCI %d.%d, %s legacy support registers\n",
 		0x03 & (temp >> 4), (temp & 0x0f),
-		(temp & 0x10) ? "with" : "NO");
+		(temp & 0x0100) ? "with" : "NO");
 
 	temp = ohci_readl (controller, &regs->control);
 	ohci_dbg_sw (controller, next, size,
@@ -328,7 +328,7 @@
 			hc32_to_cpup (ohci, &td->hwCBP) & ~0x0fff,
 			hc32_to_cpup (ohci, &td->hwBE));
 		for (i = 0; i < MAXPSW; i++) {
-			u16	psw = hc16_to_cpup (ohci, &td->hwPSW [i]);
+			u16	psw = ohci_hwPSW (ohci, td, i);
 			int	cc = (psw >> 12) & 0x0f;
 			ohci_dbg (ohci, "    psw [%d] = %2x, CC=%x %s=%d\n", i,
 				psw, cc,
diff -Nru a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
--- a/drivers/usb/host/ohci-hcd.c	2005-03-11 12:51:41 -08:00
+++ b/drivers/usb/host/ohci-hcd.c	2005-03-11 12:51:41 -08:00
@@ -148,10 +148,22 @@
 #include "ohci-q.c"
 
 
-/* Some boards don't support per-port power switching */
-static int power_switching = 0;
-module_param (power_switching, bool, 0);
-MODULE_PARM_DESC (power_switching, "true (not default) to switch port power");
+/*
+ * On architectures with edge-triggered interrupts we must never return
+ * IRQ_NONE.
+ */
+#if defined(CONFIG_SA1111)  /* ... or other edge-triggered systems */
+#define IRQ_NOTMINE	IRQ_HANDLED
+#else
+#define IRQ_NOTMINE	IRQ_NONE
+#endif
+
+
+/* Some boards misreport power switching/overcurrent */
+static int distrust_firmware = 1;
+module_param (distrust_firmware, bool, 0);
+MODULE_PARM_DESC (distrust_firmware,
+	"true to distrust firmware power/overcurrent setup");
 
 /* Some boards leave IR set wrongly, since they fail BIOS/SMM handshakes */
 static int no_handshake = 0;
@@ -532,8 +544,9 @@
 	// flush the writes
 	(void) ohci_readl (ohci, &ohci->regs->control);
 	msleep(temp);
-	if (power_switching) {
-		unsigned ports = roothub_a (ohci) & RH_A_NDP; 
+	temp = roothub_a (ohci);
+	if (!(temp & RH_A_NPS)) {
+		unsigned ports = temp & RH_A_NDP; 
 
 		/* power down each port */
 		for (temp = 0; temp < ports; temp++)
@@ -624,21 +637,16 @@
 		/* NSC 87560 and maybe others */
 		temp |= RH_A_NOCP;
 		temp &= ~(RH_A_POTPGT | RH_A_NPS);
-	} else if (power_switching) {
-		/* act like most external hubs:  use per-port power
-		 * switching and overcurrent reporting.
-		 */
-		temp &= ~(RH_A_NPS | RH_A_NOCP);
-		temp |= RH_A_PSM | RH_A_OCPM;
-	} else {
+		ohci_writel (ohci, temp, &ohci->regs->roothub.a);
+	} else if ((ohci->flags & OHCI_QUIRK_AMD756) || distrust_firmware) {
 		/* hub power always on; required for AMD-756 and some
 		 * Mac platforms.  ganged overcurrent reporting, if any.
 		 */
 		temp |= RH_A_NPS;
+		ohci_writel (ohci, temp, &ohci->regs->roothub.a);
 	}
-	ohci_writel (ohci, temp, &ohci->regs->roothub.a);
 	ohci_writel (ohci, RH_HS_LPSC, &ohci->regs->roothub.status);
-	ohci_writel (ohci, power_switching ? RH_B_PPCM : 0,
+	ohci_writel (ohci, (temp & RH_A_NPS) ? 0 : RH_B_PPCM,
 						&ohci->regs->roothub.b);
 	// flush those writes
 	(void) ohci_readl (ohci, &ohci->regs->control);
@@ -646,7 +654,7 @@
 	spin_unlock_irq (&ohci->lock);
 
 	// POTPGT delay is bits 24-31, in 2 ms units.
-	mdelay ((roothub_a (ohci) >> 23) & 0x1fe);
+	mdelay ((temp >> 23) & 0x1fe);
 	bus = &ohci_to_hcd(ohci)->self;
 	ohci_to_hcd(ohci)->state = USB_STATE_RUNNING;
 
@@ -706,7 +714,7 @@
 
 	/* interrupt for some other device? */
 	} else if ((ints &= ohci_readl (ohci, &regs->intrenable)) == 0) {
-		return IRQ_NONE;
+		return IRQ_NOTMINE;
 	} 
 
 	if (ints & OHCI_INTR_UE) {
@@ -901,12 +909,17 @@
 #include "ohci-au1xxx.c"
 #endif
 
+#ifdef CONFIG_USB_OHCI_HCD_PPC_SOC
+#include "ohci-ppc-soc.c"
+#endif
+
 #if !(defined(CONFIG_PCI) \
       || defined(CONFIG_SA1111) \
       || defined(CONFIG_ARCH_OMAP) \
       || defined (CONFIG_ARCH_LH7A404) \
       || defined (CONFIG_PXA27x) \
       || defined (CONFIG_SOC_AU1X00) \
+      || defined (CONFIG_USB_OHCI_HCD_PPC_SOC) \
 	)
 #error "missing bus glue for ohci-hcd"
 #endif
diff -Nru a/drivers/usb/host/ohci-lh7a404.c b/drivers/usb/host/ohci-lh7a404.c
--- a/drivers/usb/host/ohci-lh7a404.c	2005-03-11 12:51:51 -08:00
+++ b/drivers/usb/host/ohci-lh7a404.c	2005-03-11 12:51:51 -08:00
@@ -53,19 +53,6 @@
 
 /*-------------------------------------------------------------------------*/
 
-
-static irqreturn_t usb_hcd_lh7a404_hcim_irq (int irq, void *__hcd,
-					     struct pt_regs * r)
-{
-	struct usb_hcd *hcd = __hcd;
-
-	return usb_hcd_irq(irq, hcd, r);
-}
-
-/*-------------------------------------------------------------------------*/
-
-void usb_hcd_lh7a404_remove (struct usb_hcd *, struct platform_device *);
-
 /* configure so an HC device and id are always provided */
 /* always called with process context; sleeping is OK */
 
@@ -80,90 +67,48 @@
  *
  */
 int usb_hcd_lh7a404_probe (const struct hc_driver *driver,
-			  struct usb_hcd **hcd_out,
 			  struct platform_device *dev)
 {
 	int retval;
-	struct usb_hcd *hcd = 0;
-
-	unsigned int *addr = NULL;
+	struct usb_hcd *hcd;
 
-	if (!request_mem_region(dev->resource[0].start,
-				dev->resource[0].end
-				- dev->resource[0].start + 1, hcd_name)) {
-		pr_debug("request_mem_region failed");
-		return -EBUSY;
-	}
-	
-	
-	lh7a404_start_hc(dev);
-	
-	addr = ioremap(dev->resource[0].start,
-		       dev->resource[0].end
-		       - dev->resource[0].start + 1);
-	if (!addr) {
-		pr_debug("ioremap failed");
-		retval = -ENOMEM;
-		goto err1;
+	if (dev->resource[1].flags != IORESOURCE_IRQ) {
+		pr_debug("resource[1] is not IORESOURCE_IRQ");
+		return -ENOMEM;
 	}
 
-	if(dev->resource[1].flags != IORESOURCE_IRQ){
-		pr_debug ("resource[1] is not IORESOURCE_IRQ");
-		retval = -ENOMEM;
+	hcd = usb_create_hcd(driver, &dev->dev, "lh7a404");
+	if (!hcd)
+		return -ENOMEM;
+	hcd->rsrc_start = dev->resource[0].start;
+	hcd->rsrc_len = dev->resource[0].end - dev->resource[0].start + 1;
+
+	if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
+		pr_debug("request_mem_region failed");
+		retval = -EBUSY;
 		goto err1;
 	}
 	
-
-	hcd = usb_create_hcd (driver);
-	if (hcd == NULL){
-		pr_debug ("hcd_alloc failed");
+	hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
+	if (!hcd->regs) {
+		pr_debug("ioremap failed");
 		retval = -ENOMEM;
-		goto err1;
-	}
-	ohci_hcd_init(hcd_to_ohci(hcd));
-
-	hcd->irq = dev->resource[1].start;
-	hcd->regs = addr;
-	hcd->self.controller = &dev->dev;
-
-	retval = hcd_buffer_create (hcd);
-	if (retval != 0) {
-		pr_debug ("pool alloc fail");
 		goto err2;
 	}
 
-	retval = request_irq (hcd->irq, usb_hcd_lh7a404_hcim_irq, SA_INTERRUPT,
-			      hcd->driver->description, hcd);
-	if (retval != 0) {
-		pr_debug("request_irq failed");
-		retval = -EBUSY;
-		goto err3;
-	}
-
-	pr_debug ("%s (LH7A404) at 0x%p, irq %d",
-		hcd->driver->description, hcd->regs, hcd->irq);
-
-	hcd->self.bus_name = "lh7a404";
-	usb_register_bus (&hcd->self);
+	lh7a404_start_hc(dev);
+	ohci_hcd_init(hcd_to_ohci(hcd));
 
-	if ((retval = driver->start (hcd)) < 0)
-	{
-		usb_hcd_lh7a404_remove(hcd, dev);
+	retval = usb_add_hcd(hcd, dev->resource[1].start, SA_INTERRUPT);
+	if (retval == 0)
 		return retval;
-	}
-
-	*hcd_out = hcd;
-	return 0;
 
- err3:
-	hcd_buffer_destroy (hcd);
+	lh7a404_stop_hc(dev);
+	iounmap(hcd->regs);
  err2:
-	usb_put_hcd(hcd);
+	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
  err1:
-	lh7a404_stop_hc(dev);
-	release_mem_region(dev->resource[0].start,
-				dev->resource[0].end
-			   - dev->resource[0].start + 1);
+	usb_put_hcd(hcd);
 	return retval;
 }
 
@@ -183,28 +128,11 @@
  */
 void usb_hcd_lh7a404_remove (struct usb_hcd *hcd, struct platform_device *dev)
 {
-	pr_debug ("remove: %s, state %x", hcd->self.bus_name, hcd->state);
-
-	if (in_interrupt ())
-		BUG ();
-
-	hcd->state = USB_STATE_QUIESCING;
-
-	pr_debug ("%s: roothub graceful disconnect", hcd->self.bus_name);
-	usb_disconnect (&hcd->self.root_hub);
-
-	hcd->driver->stop (hcd);
-	hcd->state = USB_STATE_HALT;
-
-	free_irq (hcd->irq, hcd);
-	hcd_buffer_destroy (hcd);
-
-	usb_deregister_bus (&hcd->self);
-
+	usb_remove_hcd(hcd);
 	lh7a404_stop_hc(dev);
-	release_mem_region(dev->resource[0].start,
-			   dev->resource[0].end
-			   - dev->resource[0].start + 1);
+	iounmap(hcd->regs);
+	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+	usb_put_hcd(hcd);
 }
 
 /*-------------------------------------------------------------------------*/
@@ -238,7 +166,7 @@
 	 * generic hardware linkage
 	 */
 	.irq =			ohci_irq,
-	.flags =		HCD_USB11,
+	.flags =		HCD_USB11 | HCD_MEMORY,
 
 	/*
 	 * basic lifecycle operations
@@ -274,7 +202,6 @@
 static int ohci_hcd_lh7a404_drv_probe(struct device *dev)
 {
 	struct platform_device *pdev = to_platform_device(dev);
-	struct usb_hcd *hcd = NULL;
 	int ret;
 
 	pr_debug ("In ohci_hcd_lh7a404_drv_probe");
@@ -282,11 +209,7 @@
 	if (usb_disabled())
 		return -ENODEV;
 
-	ret = usb_hcd_lh7a404_probe(&ohci_lh7a404_hc_driver, &hcd, pdev);
-
-	if (ret == 0)
-		dev_set_drvdata(dev, hcd);
-
+	ret = usb_hcd_lh7a404_probe(&ohci_lh7a404_hc_driver, pdev);
 	return ret;
 }
 
@@ -296,7 +219,6 @@
 	struct usb_hcd *hcd = dev_get_drvdata(dev);
 
 	usb_hcd_lh7a404_remove(hcd, pdev);
-	dev_set_drvdata(dev, NULL);
 	return 0;
 }
 	/*TBD*/
diff -Nru a/drivers/usb/host/ohci-omap.c b/drivers/usb/host/ohci-omap.c
--- a/drivers/usb/host/ohci-omap.c	2005-03-11 12:51:47 -08:00
+++ b/drivers/usb/host/ohci-omap.c	2005-03-11 12:51:47 -08:00
@@ -33,11 +33,27 @@
 #error "This file is OMAP bus glue.  CONFIG_OMAP must be defined."
 #endif
 
+#ifdef CONFIG_TPS65010
+#include <asm/arch/tps65010.h>
+#else
+
+#define LOW	0
+#define HIGH	1
+
+#define GPIO1	1
+
+static inline int tps65010_set_gpio_out_value(unsigned gpio, unsigned value)
+{
+	return 0;
+}
+
+#endif
+
 extern int usb_disabled(void);
 extern int ocpi_enable(void);
 
 /*
- * OHCI clock initialization for OMAP-1510 and 1610
+ * OHCI clock initialization for OMAP-1510 and 16xx
  */
 static int omap_ohci_clock_power(int on)
 {
@@ -78,7 +94,8 @@
 }
 
 /*
- * Hardware specific transceiver power on/off
+ * Board specific gang-switched transceiver power on/off.
+ * NOTE:  OSK supplies power from DC, not battery.
  */
 static int omap_ohci_transceiver_power(int on)
 {
@@ -87,17 +104,15 @@
 			fpga_write(fpga_read(INNOVATOR_FPGA_CAM_USB_CONTROL)
 				| ((1 << 5/*usb1*/) | (1 << 3/*usb2*/)), 
 			       INNOVATOR_FPGA_CAM_USB_CONTROL);
-		else if (machine_is_omap_osk()) {
-			/* FIXME: GPIO1 -> 1 on the TPS65010 I2C chip */
-		}
+		else if (machine_is_omap_osk())
+			tps65010_set_gpio_out_value(GPIO1, LOW);
 	} else {
 		if (machine_is_omap_innovator() && cpu_is_omap1510())
 			fpga_write(fpga_read(INNOVATOR_FPGA_CAM_USB_CONTROL)
 				& ~((1 << 5/*usb1*/) | (1 << 3/*usb2*/)), 
 			       INNOVATOR_FPGA_CAM_USB_CONTROL);
-		else if (machine_is_omap_osk()) {
-			/* FIXME: GPIO1 -> 0 on the TPS65010 I2C chip */
-		}
+		else if (machine_is_omap_osk())
+			tps65010_set_gpio_out_value(GPIO1, HIGH);
 	}
 
 	return 0;
@@ -177,6 +192,7 @@
 {
 	struct omap_usb_config	*config = pdev->dev.platform_data;
 	int			need_transceiver = (config->otg != 0);
+	int			ret;
 
 	dev_dbg(&pdev->dev, "starting USB Controller\n");
 
@@ -213,21 +229,44 @@
 	}
 #endif
 
-	if (machine_is_omap_osk()) {
-		omap_request_gpio(9);
-		omap_set_gpio_direction(9, 1);
-		omap_set_gpio_dataout(9, 1);
-	}
-
 	omap_ohci_clock_power(1);
 
-	omap_ohci_transceiver_power(1);
-
 	if (cpu_is_omap1510()) {
 		omap_1510_local_bus_power(1);
 		omap_1510_local_bus_init();
 	}
 
+	if ((ret = ohci_init(ohci)) < 0)
+		return ret;
+
+	/* board-specific power switching and overcurrent support */
+	if (machine_is_omap_osk() || machine_is_omap_innovator()) {
+		u32	rh = roothub_a (ohci);
+
+		/* power switching (ganged by default) */
+		rh &= ~RH_A_NPS;
+
+		/* TPS2045 switch for internal transceiver (port 1) */
+		if (machine_is_omap_osk()) {
+			ohci->power_budget = 250;
+
+			rh &= ~RH_A_NOCP;
+
+			/* gpio9 for overcurrent detction */
+			omap_cfg_reg(W8_1610_GPIO9);
+			omap_request_gpio(9);
+			omap_set_gpio_direction(9, 1 /* IN */);
+
+			/* for paranoia's sake:  disable USB.PUEN */
+			omap_cfg_reg(W4_USB_HIGHZ);
+		}
+		ohci_writel(ohci, rh, &ohci->regs->roothub.a);
+		// distrust_firmware = 0;
+	}
+
+	/* FIXME khubd hub requests should manage power switching */
+	omap_ohci_transceiver_power(1);
+
 	/* board init will have already handled HMC and mux setup.
 	 * any external transceiver should already be initialized
 	 * too, so all configured ports use the right signaling now.
@@ -254,8 +293,6 @@
 
 /*-------------------------------------------------------------------------*/
 
-void usb_hcd_omap_remove (struct usb_hcd *, struct platform_device *);
-
 /* configure so an HC device and id are always provided */
 /* always called with process context; sleeping is OK */
 
@@ -272,7 +309,7 @@
 			  struct platform_device *pdev)
 {
 	int retval;
-	struct usb_hcd *hcd = 0;
+	struct usb_hcd *hcd;
 	struct ohci_hcd *ohci;
 
 	if (pdev->num_resources != 2) {
@@ -287,68 +324,38 @@
 		return -ENODEV;
 	}
 
-	if (!request_mem_region(pdev->resource[0].start, 
-				pdev->resource[0].end - pdev->resource[0].start + 1, hcd_name)) {
-		dev_dbg(&pdev->dev, "request_mem_region failed\n");
-		return -EBUSY;
-	}
+	hcd = usb_create_hcd (driver, &pdev->dev, pdev->dev.bus_id);
+	if (!hcd)
+		return -ENOMEM;
+	hcd->rsrc_start = pdev->resource[0].start;
+	hcd->rsrc_len = pdev->resource[0].end - pdev->resource[0].start + 1;
 
-	hcd = usb_create_hcd (driver);
-	if (hcd == NULL){
-		dev_dbg(&pdev->dev, "hcd_alloc failed\n");
-		retval = -ENOMEM;
+	if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
+		dev_dbg(&pdev->dev, "request_mem_region failed\n");
+		retval = -EBUSY;
 		goto err1;
 	}
-	dev_set_drvdata(&pdev->dev, hcd);
+
+	/* FIXME: Cast to pointer from integer of different size!
+	 * Needs ioremap */
+	hcd->regs = (void __iomem *) (u32) hcd->rsrc_start;
+
 	ohci = hcd_to_ohci(hcd);
 	ohci_hcd_init(ohci);
 
-	hcd->irq = pdev->resource[1].start;
-	hcd->regs = (void *)pdev->resource[0].start;
-	hcd->self.controller = &pdev->dev;
-
 	retval = omap_start_hc(ohci, pdev);
 	if (retval < 0)
 		goto err2;
 
-	retval = hcd_buffer_create (hcd);
-	if (retval != 0) {
-		dev_dbg(&pdev->dev, "pool alloc fail\n");
-		goto err2;
-	}
-
-	retval = request_irq (hcd->irq, usb_hcd_irq, 
-			      SA_INTERRUPT, hcd->driver->description, hcd);
-	if (retval != 0) {
-		dev_dbg(&pdev->dev, "request_irq failed\n");
-		retval = -EBUSY;
-		goto err3;
-	}
-
-	dev_info(&pdev->dev, "at 0x%p, irq %d\n", hcd->regs, hcd->irq);
-
-	hcd->self.bus_name = pdev->dev.bus_id;
-	usb_register_bus (&hcd->self);
-
-	if ((retval = driver->start (hcd)) < 0) 
-	{
-		usb_hcd_omap_remove(hcd, pdev);
+	retval = usb_add_hcd(hcd, pdev->resource[1].start, SA_INTERRUPT);
+	if (retval == 0)
 		return retval;
-	}
 
-	return 0;
-
- err3:
-	hcd_buffer_destroy (hcd);
+	omap_stop_hc(pdev);
  err2:
-	dev_set_drvdata(&pdev->dev, NULL);
-	usb_put_hcd(hcd);
+	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
  err1:
-	omap_stop_hc(pdev);
-
-	release_mem_region(pdev->resource[0].start, 
-			   pdev->resource[0].end - pdev->resource[0].start + 1);
-
+	usb_put_hcd(hcd);
 	return retval;
 }
 
@@ -368,31 +375,12 @@
  */
 void usb_hcd_omap_remove (struct usb_hcd *hcd, struct platform_device *pdev)
 {
-	dev_info(&pdev->dev, "remove: state %x\n", hcd->state);
-
-	if (in_interrupt ())
-		BUG ();
-
-	hcd->state = USB_STATE_QUIESCING;
-
-	dev_dbg(&pdev->dev, "roothub graceful disconnect\n");
-	usb_disconnect (&hcd->self.root_hub);
-
-	hcd->driver->stop (hcd);
-	hcd_buffer_destroy (hcd);
-	hcd->state = USB_STATE_HALT;
-
+	usb_remove_hcd(hcd);
 	if (machine_is_omap_osk())
 		omap_free_gpio(9);
-
-	free_irq (hcd->irq, hcd);
-
-	usb_deregister_bus (&hcd->self);
-
 	omap_stop_hc(pdev);
-
-	release_mem_region(pdev->resource[0].start, 
-			   pdev->resource[0].end - pdev->resource[0].start + 1);
+	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+	usb_put_hcd(hcd);
 }
 
 /*-------------------------------------------------------------------------*/
@@ -404,9 +392,6 @@
 	struct ohci_hcd	*ohci = hcd_to_ohci (hcd);
 	int		ret;
 
-	if ((ret = ohci_init(ohci)) < 0)
-		return ret;
-
 	config = hcd->self.controller->platform_data;
 	if (config->otg || config->rwc)
 		writel(OHCI_CTRL_RWC, &ohci->regs->control);
@@ -430,7 +415,7 @@
 	 * generic hardware linkage
 	 */
 	.irq =			ohci_irq,
-	.flags =		HCD_USB11,
+	.flags =		HCD_USB11 | HCD_MEMORY,
 
 	/*
 	 * basic lifecycle operations
@@ -481,7 +466,6 @@
 		(void) otg_set_host(ohci->transceiver, 0);
 		put_device(ohci->transceiver->dev);
 	}
-	dev_set_drvdata(dev, NULL);
 
 	return 0;
 }
@@ -499,6 +483,8 @@
 	struct ohci_hcd	*ohci = hcd_to_ohci(dev_get_drvdata(dev));
 	int		status = -EINVAL;
 
+	if (level != SUSPEND_POWER_DOWN)
+		return 0;
 	if (state <= dev->power.power_state)
 		return 0;
 
@@ -524,6 +510,9 @@
 {
 	struct ohci_hcd	*ohci = hcd_to_ohci(dev_get_drvdata(dev));
 	int		status = 0;
+
+	if (level != RESUME_POWER_ON)
+		return 0;
 
 	switch (dev->power.power_state) {
 	case 0:
diff -Nru a/drivers/usb/host/ohci-ppc-soc.c b/drivers/usb/host/ohci-ppc-soc.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/usb/host/ohci-ppc-soc.c	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,234 @@
+/*
+ * OHCI HCD (Host Controller Driver) for USB.
+ *
+ * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
+ * (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net>
+ * (C) Copyright 2002 Hewlett-Packard Company
+ * (C) Copyright 2003-2005 MontaVista Software Inc.
+ * 
+ * Bus Glue for PPC On-Chip OHCI driver
+ * Tested on Freescale MPC5200 and IBM STB04xxx
+ *
+ * Modified by Dale Farnsworth <dale@farnsworth.org> from ohci-sa1111.c
+ *
+ * This file is licenced under the GPL.
+ */
+
+#include <asm/usb.h>
+
+/* configure so an HC device and id are always provided */
+/* always called with process context; sleeping is OK */
+
+/**
+ * usb_hcd_ppc_soc_probe - initialize On-Chip HCDs
+ * Context: !in_interrupt()
+ *
+ * Allocates basic resources for this USB host controller, and
+ * then invokes the start() method for the HCD associated with it
+ * through the hotplug entry's driver_data.
+ *
+ * Store this function in the HCD's struct pci_driver as probe().
+ */
+static int usb_hcd_ppc_soc_probe(const struct hc_driver *driver,
+			  struct platform_device *pdev)
+{
+	int retval;
+	struct usb_hcd *hcd;
+	struct ohci_hcd	*ohci;
+	struct resource *res;
+	int irq;
+	struct usb_hcd_platform_data *pd = pdev->dev.platform_data;
+
+	pr_debug("initializing PPC-SOC USB Controller\n");
+
+	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (!res) {
+		pr_debug(__FILE__ ": no irq\n");
+		return -ENODEV;
+	}
+	irq = res->start;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		pr_debug(__FILE__ ": no reg addr\n");
+		return -ENODEV;
+	}
+
+	hcd = usb_create_hcd(driver, &pdev->dev, "PPC-SOC USB");
+	if (!hcd)
+		return -ENOMEM;
+	hcd->rsrc_start = res->start;
+	hcd->rsrc_len = res->end - res->start + 1;
+
+	if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
+		pr_debug(__FILE__ ": request_mem_region failed\n");
+		retval = -EBUSY;
+		goto err1;
+	}
+
+	hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
+	if (!hcd->regs) {
+		pr_debug(__FILE__ ": ioremap failed\n");
+		retval = -ENOMEM;
+		goto err2;
+	}
+
+	if (pd->start && (retval = pd->start(pdev)))
+		goto err3;
+
+	ohci = hcd_to_ohci(hcd);
+	ohci->flags |= OHCI_BIG_ENDIAN;
+	ohci_hcd_init(ohci);
+
+	retval = usb_add_hcd(hcd, irq, SA_INTERRUPT);
+	if (retval == 0)
+		return retval;
+
+	pr_debug("Removing PPC-SOC USB Controller\n");
+	if (pd && pd->stop)
+		pd->stop(pdev);
+ err3:
+	iounmap(hcd->regs);
+ err2:
+	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+ err1:
+ 	usb_put_hcd(hcd);
+	return retval;
+}
+
+
+/* may be called without controller electrically present */
+/* may be called with controller, bus, and devices active */
+
+/**
+ * usb_hcd_ppc_soc_remove - shutdown processing for On-Chip HCDs
+ * @pdev: USB Host Controller being removed
+ * Context: !in_interrupt()
+ *
+ * Reverses the effect of usb_hcd_ppc_soc_probe(), first invoking
+ * the HCD's stop() method.  It is always called from a thread
+ * context, normally "rmmod", "apmd", or something similar.
+ *
+ */
+static void usb_hcd_ppc_soc_remove(struct usb_hcd *hcd,
+		struct platform_device *pdev)
+{
+	struct usb_hcd_platform_data *pd = pdev->dev.platform_data;
+
+	usb_remove_hcd(hcd);
+
+	pr_debug("stopping PPC-SOC USB Controller\n");
+	if (pd && pd->stop)
+		pd->stop(pdev);
+
+	iounmap(hcd->regs);
+	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+	usb_hcd_put(hcd);
+}
+
+static int __devinit
+ohci_ppc_soc_start(struct usb_hcd *hcd)
+{
+	struct ohci_hcd	*ohci = hcd_to_ohci(hcd);
+	int		ret;
+
+	if ((ret = ohci_init(ohci)) < 0)
+		return ret;
+
+	if ((ret = ohci_run(ohci)) < 0) {
+		err("can't start %s", ohci_to_hcd(ohci)->self.bus_name);
+		ohci_stop(hcd);
+		return ret;
+	}
+
+	return 0;
+}
+
+static const struct hc_driver ohci_ppc_soc_hc_driver = {
+	.description =		hcd_name,
+	.hcd_priv_size =	sizeof(struct ohci_hcd),
+
+	/*
+	 * generic hardware linkage
+	 */
+	.irq =			ohci_irq,
+	.flags =		HCD_USB11 | HCD_MEMORY,
+
+	/*
+	 * basic lifecycle operations
+	 */
+	.start =		ohci_ppc_soc_start,
+	.stop =			ohci_stop,
+
+	/*
+	 * managing i/o requests and associated device resources
+	 */
+	.urb_enqueue =		ohci_urb_enqueue,
+	.urb_dequeue =		ohci_urb_dequeue,
+	.endpoint_disable =	ohci_endpoint_disable,
+
+	/*
+	 * scheduling support
+	 */
+	.get_frame_number =	ohci_get_frame,
+
+	/*
+	 * root hub support
+	 */
+	.hub_status_data =	ohci_hub_status_data,
+	.hub_control =		ohci_hub_control,
+#ifdef	CONFIG_USB_SUSPEND
+	.hub_suspend =		ohci_hub_suspend,
+	.hub_resume =		ohci_hub_resume,
+#endif
+	.start_port_reset =	ohci_start_port_reset,
+};
+
+static int ohci_hcd_ppc_soc_drv_probe(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	int ret;
+
+	if (usb_disabled())
+		return -ENODEV;
+
+	ret = usb_hcd_ppc_soc_probe(&ohci_ppc_soc_hc_driver, pdev);
+	return ret;
+}
+
+static int ohci_hcd_ppc_soc_drv_remove(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct usb_hcd *hcd = dev_get_drvdata(dev);
+
+	usb_hcd_ppc_soc_remove(hcd, pdev);
+	return 0;
+}
+
+static struct device_driver ohci_hcd_ppc_soc_driver = {
+	.name		= "ppc-soc-ohci",
+	.bus		= &platform_bus_type,
+	.probe		= ohci_hcd_ppc_soc_drv_probe,
+	.remove		= ohci_hcd_ppc_soc_drv_remove,
+#if	defined(CONFIG_USB_SUSPEND) || defined(CONFIG_PM)
+	/*.suspend	= ohci_hcd_ppc_soc_drv_suspend,*/
+	/*.resume	= ohci_hcd_ppc_soc_drv_resume,*/
+#endif
+};
+
+static int __init ohci_hcd_ppc_soc_init(void)
+{
+	pr_debug(DRIVER_INFO " (PPC SOC)\n");
+	pr_debug("block sizes: ed %d td %d\n", sizeof(struct ed),
+							sizeof(struct td));
+
+	return driver_register(&ohci_hcd_ppc_soc_driver);
+}
+
+static void __exit ohci_hcd_ppc_soc_cleanup(void)
+{
+	driver_unregister(&ohci_hcd_ppc_soc_driver);
+}
+
+module_init(ohci_hcd_ppc_soc_init);
+module_exit(ohci_hcd_ppc_soc_cleanup);
diff -Nru a/drivers/usb/host/ohci-pxa27x.c b/drivers/usb/host/ohci-pxa27x.c
--- a/drivers/usb/host/ohci-pxa27x.c	2005-03-11 12:51:46 -08:00
+++ b/drivers/usb/host/ohci-pxa27x.c	2005-03-11 12:51:46 -08:00
@@ -152,8 +152,6 @@
 
 /*-------------------------------------------------------------------------*/
 
-void usb_hcd_pxa27x_remove (struct usb_hcd *, struct platform_device *);
-
 /* configure so an HC device and id are always provided */
 /* always called with process context; sleeping is OK */
 
@@ -168,19 +166,33 @@
  *
  */
 int usb_hcd_pxa27x_probe (const struct hc_driver *driver,
-			  struct usb_hcd **hcd_out,
 			  struct platform_device *dev)
 {
 	int retval;
-	struct usb_hcd *hcd = 0;
+	struct usb_hcd *hcd;
+
+	if (dev->resource[1].flags != IORESOURCE_IRQ) {
+		pr_debug ("resource[1] is not IORESOURCE_IRQ");
+		return -ENOMEM;
+	}
 
-	unsigned int *addr = NULL;
+	hcd = usb_create_hcd (driver, &dev->dev, "pxa27x");
+	if (!hcd)
+		return -ENOMEM;
+	hcd->rsrc_start = dev->resource[0].start;
+	hcd->rsrc_len = dev->resource[0].end - dev->resource[0].start + 1;
 
-	if (!request_mem_region(dev->resource[0].start,
-				dev->resource[0].end
-				- dev->resource[0].start + 1, hcd_name)) {
+	if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
 		pr_debug("request_mem_region failed");
-		return -EBUSY;
+		retval = -EBUSY;
+		goto err1;
+	}
+
+	hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
+	if (!hcd->regs) {
+		pr_debug("ioremap failed");
+		retval = -ENOMEM;
+		goto err2;
 	}
 
 	pxa27x_start_hc(dev);
@@ -198,69 +210,18 @@
 	if (pxa27x_ohci_clear_port_power(3) < 0)
 		printk(KERN_ERR "Setting port 3 power failed.\n");
 
-	addr = ioremap(dev->resource[0].start,
-		       dev->resource[0].end - dev->resource[0].start + 1);
-	if (!addr) {
-		pr_debug("ioremap failed");
-		retval = -ENOMEM;
-		goto err1;
-	}
-
-	if(dev->resource[1].flags != IORESOURCE_IRQ){
-		pr_debug ("resource[1] is not IORESOURCE_IRQ");
-		retval = -ENOMEM;
-		goto err1;
-	}
-
-	hcd = usb_create_hcd (driver);
-	if (hcd == NULL){
-		pr_debug ("hcd_alloc failed");
-		retval = -ENOMEM;
-		goto err1;
-	}
 	ohci_hcd_init(hcd_to_ohci(hcd));
 
-	hcd->irq = dev->resource[1].start;
-	hcd->regs = addr;
-	hcd->self.controller = &dev->dev;
-
-	retval = hcd_buffer_create (hcd);
-	if (retval != 0) {
-		pr_debug ("pool alloc fail");
-		goto err2;
-	}
-
-	retval = request_irq (hcd->irq, usb_hcd_irq, SA_INTERRUPT,
-			      hcd->driver->description, hcd);
-	if (retval != 0) {
-		pr_debug("request_irq(%d) failed with retval %d\n",hcd->irq,retval);
-		retval = -EBUSY;
-		goto err3;
-	}
-
-	pr_debug ("%s (pxa27x) at 0x%p, irq %d",
-		hcd->driver->description, hcd->regs, hcd->irq);
-
-	hcd->self.bus_name = "pxa27x";
-	usb_register_bus (&hcd->self);
-
-	if ((retval = driver->start (hcd)) < 0) {
-		usb_hcd_pxa27x_remove(hcd, dev);
+	retval = usb_add_hcd(hcd, dev->resource[1].start, SA_INTERRUPT);
+	if (retval == 0)
 		return retval;
-	}
-
-	*hcd_out = hcd;
-	return 0;
 
- err3:
-	hcd_buffer_destroy (hcd);
+	pxa27x_stop_hc(dev);
+	iounmap(hcd->regs);
  err2:
-	usb_put_hcd(hcd);
+	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
  err1:
-	pxa27x_stop_hc(dev);
-	release_mem_region(dev->resource[0].start,
-				dev->resource[0].end
-			   - dev->resource[0].start + 1);
+	usb_put_hcd(hcd);
 	return retval;
 }
 
@@ -280,27 +241,11 @@
  */
 void usb_hcd_pxa27x_remove (struct usb_hcd *hcd, struct platform_device *dev)
 {
-	pr_debug ("remove: %s, state %x", hcd->self.bus_name, hcd->state);
-
-	if (in_interrupt ())
-		BUG ();
-
-	hcd->state = USB_STATE_QUIESCING;
-
-	pr_debug ("%s: roothub graceful disconnect", hcd->self.bus_name);
-	usb_disconnect (&hcd->self.root_hub);
-
-	hcd->driver->stop (hcd);
-	hcd->state = USB_STATE_HALT;
-
-	free_irq (hcd->irq, hcd);
-	hcd_buffer_destroy (hcd);
-
-	usb_deregister_bus (&hcd->self);
-
+	usb_remove_hcd(hcd);
 	pxa27x_stop_hc(dev);
-	release_mem_region(dev->resource[0].start,
-			   dev->resource[0].end - dev->resource[0].start + 1);
+	iounmap(hcd->regs);
+	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+	usb_put_hcd(hcd);
 }
 
 /*-------------------------------------------------------------------------*/
@@ -336,7 +281,7 @@
 	 * generic hardware linkage
 	 */
 	.irq =			ohci_irq,
-	.flags =		HCD_USB11,
+	.flags =		HCD_USB11 | HCD_MEMORY,
 
 	/*
 	 * basic lifecycle operations
@@ -372,7 +317,6 @@
 static int ohci_hcd_pxa27x_drv_probe(struct device *dev)
 {
 	struct platform_device *pdev = to_platform_device(dev);
-	struct usb_hcd *hcd = NULL;
 	int ret;
 
 	pr_debug ("In ohci_hcd_pxa27x_drv_probe");
@@ -380,11 +324,7 @@
 	if (usb_disabled())
 		return -ENODEV;
 
-	ret = usb_hcd_pxa27x_probe(&ohci_pxa27x_hc_driver, &hcd, pdev);
-
-	if (ret == 0)
-		dev_set_drvdata(dev, hcd);
-
+	ret = usb_hcd_pxa27x_probe(&ohci_pxa27x_hc_driver, pdev);
 	return ret;
 }
 
@@ -394,7 +334,6 @@
 	struct usb_hcd *hcd = dev_get_drvdata(dev);
 
 	usb_hcd_pxa27x_remove(hcd, pdev);
-	dev_set_drvdata(dev, NULL);
 	return 0;
 }
 
diff -Nru a/drivers/usb/host/ohci-q.c b/drivers/usb/host/ohci-q.c
--- a/drivers/usb/host/ohci-q.c	2005-03-11 12:51:51 -08:00
+++ b/drivers/usb/host/ohci-q.c	2005-03-11 12:51:51 -08:00
@@ -547,7 +547,8 @@
 	td->hwINFO = cpu_to_hc32 (ohci, info);
 	if (is_iso) {
 		td->hwCBP = cpu_to_hc32 (ohci, data & 0xFFFFF000);
-		td->hwPSW [0] = cpu_to_hc16 (ohci, (data & 0x0FFF) | 0xE000);
+		*ohci_hwPSWp(ohci, td, 0) = cpu_to_hc16 (ohci,
+						(data & 0x0FFF) | 0xE000);
 		td->ed->last_iso = info & 0xffff;
 	} else {
 		td->hwCBP = cpu_to_hc32 (ohci, data); 
@@ -719,10 +720,12 @@
 
 	/* ISO ... drivers see per-TD length/status */
   	if (tdINFO & TD_ISO) {
- 		u16	tdPSW = hc16_to_cpu (ohci, td->hwPSW [0]);
+ 		u16	tdPSW = ohci_hwPSW (ohci, td, 0);
 		int	dlen = 0;
 
-		/* NOTE:  assumes FC in tdINFO == 0 (and MAXPSW == 1) */
+		/* NOTE:  assumes FC in tdINFO == 0, and that
+		 * only the first of 0..MAXPSW psws is used.
+		 */
 
  		cc = (tdPSW >> 12) & 0xF;
   		if (tdINFO & TD_CC)	/* hc didn't touch? */
diff -Nru a/drivers/usb/host/ohci-sa1111.c b/drivers/usb/host/ohci-sa1111.c
--- a/drivers/usb/host/ohci-sa1111.c	2005-03-11 12:51:46 -08:00
+++ b/drivers/usb/host/ohci-sa1111.c	2005-03-11 12:51:46 -08:00
@@ -105,34 +105,8 @@
 }
 #endif
 
-static irqreturn_t usb_hcd_sa1111_hcim_irq (int irq, void *__hcd, struct pt_regs * r)
-{
-	struct usb_hcd *hcd = __hcd;
-//	unsigned long status = sa1111_readl(hcd->regs + SA1111_USB_STATUS);
-
-	//dump_hci_status(hcd, "irq");
-
-#if 0
-	/* may work better this way -- need to investigate further */
-	if (status & USB_STATUS_NIRQHCIM) {
-		//dbg ("not normal HC interrupt; ignoring");
-		return;
-	}
-#endif
-
-	usb_hcd_irq(irq, hcd, r);
-
-	/*
-	 * SA1111 seems to re-assert its interrupt immediately
-	 * after processing an interrupt.  Always return IRQ_HANDLED.
-	 */
-	return IRQ_HANDLED;
-}
-
 /*-------------------------------------------------------------------------*/
 
-void usb_hcd_sa1111_remove (struct usb_hcd *, struct sa1111_dev *);
-
 /* configure so an HC device and id are always provided */
 /* always called with process context; sleeping is OK */
 
@@ -148,68 +122,35 @@
  * Store this function in the HCD's struct pci_driver as probe().
  */
 int usb_hcd_sa1111_probe (const struct hc_driver *driver,
-			  struct usb_hcd **hcd_out,
 			  struct sa1111_dev *dev)
 {
+	struct usb_hcd *hcd;
 	int retval;
-	struct usb_hcd *hcd = 0;
 
-	if (!request_mem_region(dev->res.start, 
-				dev->res.end - dev->res.start + 1, hcd_name)) {
-		dbg("request_mem_region failed");
-		return -EBUSY;
-	}
-
-	sa1111_start_hc(dev);
+	hcd = usb_create_hcd (driver, &dev->dev, "sa1111");
+	if (!hcd)
+		return -ENOMEM;
+	hcd->rsrc_start = dev->res.start;
+	hcd->rsrc_len = dev->res.end - dev->res.start + 1;
 
-	hcd = usb_create_hcd (driver);
-	if (hcd == NULL){
-		dbg ("hcd_alloc failed");
-		retval = -ENOMEM;
+	if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
+		dbg("request_mem_region failed");
+		retval = -EBUSY;
 		goto err1;
 	}
-	ohci_hcd_init(hcd_to_ohci(hcd));
-
-	hcd->irq = dev->irq[1];
 	hcd->regs = dev->mapbase;
-	hcd->self.controller = &dev->dev;
-
-	retval = hcd_buffer_create (hcd);
-	if (retval != 0) {
-		dbg ("pool alloc fail");
-		goto err2;
-	}
-
-	retval = request_irq (hcd->irq, usb_hcd_sa1111_hcim_irq, SA_INTERRUPT,
-			      hcd->driver->description, hcd);
-	if (retval != 0) {
-		dbg("request_irq failed");
-		retval = -EBUSY;
-		goto err3;
-	}
 
-	info ("%s (SA-1111) at 0x%p, irq %d\n",
-		hcd->driver->description, hcd->regs, hcd->irq);
-
-	hcd->self.bus_name = "sa1111";
-	usb_register_bus (&hcd->self);
+	sa1111_start_hc(dev);
+	ohci_hcd_init(hcd_to_ohci(hcd));
 
-	if ((retval = driver->start (hcd)) < 0) 
-	{
-		usb_hcd_sa1111_remove(hcd, dev);
+	retval = usb_add_hcd(hcd, dev->irq[1], SA_INTERRUPT);
+	if (retval == 0)
 		return retval;
-	}
 
-	*hcd_out = hcd;
-	return 0;
-
- err3:
-	hcd_buffer_destroy (hcd);
- err2:
-	usb_put_hcd(hcd);
- err1:
 	sa1111_stop_hc(dev);
-	release_mem_region(dev->res.start, dev->res.end - dev->res.start + 1);
+	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+ err1:
+	usb_put_hcd(hcd);
 	return retval;
 }
 
@@ -229,26 +170,10 @@
  */
 void usb_hcd_sa1111_remove (struct usb_hcd *hcd, struct sa1111_dev *dev)
 {
-	info ("remove: %s, state %x", hcd->self.bus_name, hcd->state);
-
-	if (in_interrupt ())
-		BUG ();
-
-	hcd->state = USB_STATE_QUIESCING;
-
-	dbg ("%s: roothub graceful disconnect", hcd->self.bus_name);
-	usb_disconnect (&hcd->self.root_hub);
-
-	hcd->driver->stop (hcd);
-	hcd->state = USB_STATE_HALT;
-
-	free_irq (hcd->irq, hcd);
-	hcd_buffer_destroy (hcd);
-
-	usb_deregister_bus (&hcd->self);
-
+	usb_remove_hcd(hcd);
 	sa1111_stop_hc(dev);
-	release_mem_region(dev->res.start, dev->res.end - dev->res.start + 1);
+	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+	usb_put_hcd(hcd);
 }
 
 /*-------------------------------------------------------------------------*/
@@ -281,7 +206,7 @@
 	 * generic hardware linkage
 	 */
 	.irq =			ohci_irq,
-	.flags =		HCD_USB11,
+	.flags =		HCD_USB11 | HCD_MEMORY,
 
 	/*
 	 * basic lifecycle operations
@@ -294,11 +219,6 @@
 	.stop =			ohci_stop,
 
 	/*
-	 * memory lifecycle (except per-request)
-	 */
-	.hcd_alloc =		ohci_hcd_alloc,
-
-	/*
 	 * managing i/o requests and associated device resources
 	 */
 	.urb_enqueue =		ohci_urb_enqueue,
@@ -325,17 +245,12 @@
 
 static int ohci_hcd_sa1111_drv_probe(struct sa1111_dev *dev)
 {
-	struct usb_hcd *hcd = NULL;
 	int ret;
 
 	if (usb_disabled())
 		return -ENODEV;
 
-	ret = usb_hcd_sa1111_probe(&ohci_sa1111_hc_driver, &hcd, dev);
-
-	if (ret == 0)
-		sa1111_set_drvdata(dev, hcd);
-
+	ret = usb_hcd_sa1111_probe(&ohci_sa1111_hc_driver, dev);
 	return ret;
 }
 
@@ -344,9 +259,6 @@
 	struct usb_hcd *hcd = sa1111_get_drvdata(dev);
 
 	usb_hcd_sa1111_remove(hcd, dev);
-
-	sa1111_set_drvdata(dev, NULL);
-
 	return 0;
 }
 
diff -Nru a/drivers/usb/host/ohci.h b/drivers/usb/host/ohci.h
--- a/drivers/usb/host/ohci.h	2005-03-11 12:51:52 -08:00
+++ b/drivers/usb/host/ohci.h	2005-03-11 12:51:52 -08:00
@@ -111,8 +111,10 @@
   	__hc32		hwNextTD;	/* Next TD Pointer */
   	__hc32		hwBE;		/* Memory Buffer End Pointer */
 
-	/* PSW is only for ISO */
-#define MAXPSW 1		/* hardware allows 8 */
+	/* PSW is only for ISO.  Only 1 PSW entry is used, but on
+	 * big-endian PPC hardware that's the second entry.
+	 */
+#define MAXPSW	2
   	__hc16		hwPSW [MAXPSW];
 
 	/* rest are purely for the driver's use */
@@ -183,7 +185,7 @@
 	/* 
 	 * OHCI defines u16 frame_no, followed by u16 zero pad.
 	 * Since some processors can't do 16 bit bus accesses,
-	 * portable access must be a 32 bit byteswapped access.
+	 * portable access must be a 32 bits wide.
 	 */
 	__hc32	frame_no;		/* current frame number */
 	__hc32	done_head;		/* info returned for an interrupt */
@@ -191,8 +193,6 @@
 	u8	what [4];		/* spec only identifies 252 bytes :) */
 } __attribute__ ((aligned(256)));
 
-#define ohci_frame_no(ohci) ((u16)hc32_to_cpup(ohci,&(ohci)->hcca->frame_no))
-  
 /*
  * This is the structure of the OHCI controller's memory mapped I/O region.
  * You must use readl() and writel() (in <asm/io.h>) to access these fields!!
@@ -550,6 +550,44 @@
 static inline u32 hc32_to_cpup (const struct ohci_hcd *ohci, const __hc32 *x)
 {
 	return big_endian(ohci) ? be32_to_cpup((__force __be32 *)x) : le32_to_cpup((__force __le32 *)x);
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* HCCA frame number is 16 bits, but is accessed as 32 bits since not all
+ * hardware handles 16 bit reads.  That creates a different confusion on
+ * some big-endian SOC implementations.  Same thing happens with PSW access.
+ */
+
+#ifdef CONFIG_STB03xxx
+#define OHCI_BE_FRAME_NO_SHIFT	16
+#else
+#define OHCI_BE_FRAME_NO_SHIFT	0
+#endif
+
+static inline u16 ohci_frame_no(const struct ohci_hcd *ohci)
+{
+	u32 tmp;
+	if (big_endian(ohci)) {
+		tmp = be32_to_cpup((__force __be32 *)&ohci->hcca->frame_no);
+		tmp >>= OHCI_BE_FRAME_NO_SHIFT;
+	} else
+		tmp = le32_to_cpup((__force __le32 *)&ohci->hcca->frame_no);
+
+	return (u16)tmp;
+}
+
+static inline __hc16 *ohci_hwPSWp(const struct ohci_hcd *ohci,
+                                 const struct td *td, int index)
+{
+	return (__hc16 *)(big_endian(ohci) ?
+			&td->hwPSW[index ^ 1] : &td->hwPSW[index]);
+}
+
+static inline u16 ohci_hwPSW(const struct ohci_hcd *ohci,
+                               const struct td *td, int index)
+{
+	return hc16_to_cpup(ohci, ohci_hwPSWp(ohci, td, index));
 }
 
 /*-------------------------------------------------------------------------*/
diff -Nru a/drivers/usb/host/sl811-hcd.c b/drivers/usb/host/sl811-hcd.c
--- a/drivers/usb/host/sl811-hcd.c	2005-03-11 12:51:42 -08:00
+++ b/drivers/usb/host/sl811-hcd.c	2005-03-11 12:51:42 -08:00
@@ -90,8 +90,6 @@
 
 /*-------------------------------------------------------------------------*/
 
-static irqreturn_t sl811h_irq(int irq, void *_hcd, struct pt_regs *regs);
-
 static void port_power(struct sl811 *sl811, int is_on)
 {
 	struct usb_hcd	*hcd = sl811_to_hcd(sl811);
@@ -645,9 +643,8 @@
 	return irqstat;
 }
 
-static irqreturn_t sl811h_irq(int irq, void *_hcd, struct pt_regs *regs)
+static irqreturn_t sl811h_irq(struct usb_hcd *hcd, struct pt_regs *regs)
 {
-	struct usb_hcd	*hcd = _hcd;
 	struct sl811	*sl811 = hcd_to_sl811(hcd);
 	u8		irqstat;
 	irqreturn_t	ret = IRQ_NONE;
@@ -666,7 +663,7 @@
 	/* this may no longer be necessary ... */
 	if (irqstat == 0 && ret == IRQ_NONE) {
 		irqstat = checkdone(sl811);
-		if (irqstat && irq != ~0)
+		if (irqstat /* && irq != ~0 */ )
 			sl811->stat_lost++;
 	}
 #endif
@@ -760,7 +757,6 @@
 		if (sl811->port1 & (1 << USB_PORT_FEAT_ENABLE))
 			start_transfer(sl811);
 		ret = IRQ_HANDLED;
-		hcd->saw_irq = 1;
 		if (retries--)
 			goto retry;
 	}
@@ -1073,7 +1069,7 @@
 	 */
 	local_irq_save(flags);
 	if (!timer_pending(&sl811->timer)) {
-		if (sl811h_irq(~0, sl811, NULL) != IRQ_NONE)
+		if (sl811h_irq( /* ~0, */ hcd, NULL) != IRQ_NONE)
 			sl811->stat_lost++;
 	}
 	local_irq_restore(flags);
@@ -1592,7 +1588,12 @@
 	/*
 	 * generic hardware linkage
 	 */
-	.flags =		HCD_USB11,
+	.irq =			sl811h_irq,
+	.flags =		HCD_USB11 | HCD_MEMORY,
+
+	/* Basic lifecycle operations */
+	.start =		sl811h_start,
+	.stop =			sl811h_stop,
 
 	/*
 	 * managing i/o requests and associated device resources
@@ -1620,23 +1621,15 @@
 static int __init_or_module
 sl811h_remove(struct device *dev)
 {
-	struct sl811		*sl811 = dev_get_drvdata(dev);
-	struct usb_hcd		*hcd = sl811_to_hcd(sl811);
+	struct usb_hcd		*hcd = dev_get_drvdata(dev);
+	struct sl811		*sl811 = hcd_to_sl811(hcd);
 	struct platform_device	*pdev;
 	struct resource		*res;
 
 	pdev = container_of(dev, struct platform_device, dev);
 
-	if (HCD_IS_RUNNING(hcd->state))
-		hcd->state = USB_STATE_QUIESCING;
-
-	usb_disconnect(&hcd->self.root_hub);
 	remove_debug_file(sl811);
-	sl811h_stop(hcd);
-
-	usb_deregister_bus(&hcd->self);
-
-	free_irq(hcd->irq, hcd);
+	usb_remove_hcd(hcd);
 
 	iounmap(sl811->data_reg);
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
@@ -1707,18 +1700,13 @@
 	}
 
 	/* allocate and initialize hcd */
-	hcd = usb_create_hcd(&sl811h_hc_driver);
+	hcd = usb_create_hcd(&sl811h_hc_driver, dev, dev->bus_id);
 	if (!hcd) {
-		retval = 0;
+		retval = -ENOMEM;
 		goto err5;
 	}
+	hcd->rsrc_start = addr->start;
 	sl811 = hcd_to_sl811(hcd);
-	dev_set_drvdata(dev, sl811);
-
-	hcd->self.controller = dev;
-	hcd->self.bus_name = dev->bus_id;
-	hcd->irq = irq;
-	hcd->regs = addr_reg;
 
 	spin_lock_init(&sl811->lock);
 	INIT_LIST_HEAD(&sl811->async);
@@ -1754,28 +1742,13 @@
 	/* Cypress docs say the IRQ is IRQT_HIGH ... */
 	set_irq_type(irq, IRQT_RISING);
 #endif
-	retval = request_irq(irq, sl811h_irq, SA_INTERRUPT,
-			hcd->driver->description, hcd);
+	retval = usb_add_hcd(hcd, irq, SA_INTERRUPT);
 	if (retval != 0)
 		goto err6;
 
-	INFO("%s, irq %d\n", hcd->product_desc, irq);
-
-	retval = usb_register_bus(&hcd->self);
-	if (retval < 0)
-		goto err7;
-
-	retval = sl811h_start(hcd);
-	if (retval < 0)
-		goto err8;
-
 	create_debug_file(sl811);
-	return 0;
+	return retval;
 
- err8:
-	usb_deregister_bus(&hcd->self);
- err7:
-	free_irq(hcd->irq, hcd);
  err6:
 	usb_put_hcd(hcd);
  err5:
@@ -1801,14 +1774,15 @@
 static int
 sl811h_suspend(struct device *dev, u32 state, u32 phase)
 {
-	struct sl811	*sl811 = dev_get_drvdata(dev);
+	struct usb_hcd	*hcd = dev_get_drvdata(dev);
+	struct sl811	*sl811 = hcd_to_sl811(hcd);
 	int		retval = 0;
 
 	if (phase != SUSPEND_POWER_DOWN)
 		return retval;
 
 	if (state <= PM_SUSPEND_MEM)
-		retval = sl811h_hub_suspend(sl811_to_hcd(sl811));
+		retval = sl811h_hub_suspend(hcd);
 	else
 		port_power(sl811, 0);
 	if (retval == 0)
@@ -1819,7 +1793,8 @@
 static int
 sl811h_resume(struct device *dev, u32 phase)
 {
-	struct sl811	*sl811 = dev_get_drvdata(dev);
+	struct usb_hcd	*hcd = dev_get_drvdata(dev);
+	struct sl811	*sl811 = hcd_to_sl811(hcd);
 
 	if (phase != RESUME_POWER_ON)
 		return 0;
@@ -1828,14 +1803,14 @@
 	 * let's assume it'd only be powered to enable remote wakeup.
 	 */
 	if (dev->power.power_state > PM_SUSPEND_MEM
-			|| !sl811_to_hcd(sl811)->can_wakeup) {
+			|| !hcd->can_wakeup) {
 		sl811->port1 = 0;
 		port_power(sl811, 1);
 		return 0;
 	}
 
 	dev->power.power_state = PM_SUSPEND_ON;
-	return sl811h_hub_resume(sl811_to_hcd(sl811));
+	return sl811h_hub_resume(hcd);
 }
 
 #else
diff -Nru a/drivers/usb/host/uhci-debug.c b/drivers/usb/host/uhci-debug.c
--- a/drivers/usb/host/uhci-debug.c	2005-03-11 12:51:41 -08:00
+++ b/drivers/usb/host/uhci-debug.c	2005-03-11 12:51:41 -08:00
@@ -17,6 +17,8 @@
 
 #include "uhci-hcd.h"
 
+static struct dentry *uhci_debugfs_root = NULL;
+
 /* Handle REALLY large printk's so we don't overflow buffers */
 static inline void lprintk(char *buf)
 {
@@ -497,8 +499,6 @@
 
 #define MAX_OUTPUT	(64 * 1024)
 
-static struct dentry *uhci_debugfs_root = NULL;
-
 struct uhci_debug {
 	int size;
 	char *data;
@@ -579,4 +579,9 @@
 	.read =		uhci_debug_read,
 	.release =	uhci_debug_release,
 };
+
+#else	/* CONFIG_DEBUG_FS */
+
+#define uhci_debug_operations (* (struct file_operations *) NULL)
+
 #endif
diff -Nru a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
--- a/drivers/usb/host/uhci-hcd.c	2005-03-11 12:51:51 -08:00
+++ b/drivers/usb/host/uhci-hcd.c	2005-03-11 12:51:51 -08:00
@@ -87,19 +87,9 @@
 static char *errbuf;
 #define ERRBUF_LEN    (32 * 1024)
 
-#include "uhci-hub.c"
-#include "uhci-debug.c"
-
 static kmem_cache_t *uhci_up_cachep;	/* urb_priv */
 
 static unsigned int uhci_get_current_frame_number(struct uhci_hcd *uhci);
-static int uhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb);
-static void uhci_unlink_generic(struct uhci_hcd *uhci, struct urb *urb);
-static void uhci_remove_pending_urbps(struct uhci_hcd *uhci);
-static void uhci_finish_completion(struct usb_hcd *hcd, struct pt_regs *regs);
-static void uhci_free_pending_qhs(struct uhci_hcd *uhci);
-static void uhci_free_pending_tds(struct uhci_hcd *uhci);
-
 static void hc_state_transitions(struct uhci_hcd *uhci);
 
 /* If a transfer is still active after this much time, turn off FSBR */
@@ -111,1424 +101,9 @@
 /* to make sure it doesn't hog all of the bandwidth */
 #define DEPTH_INTERVAL 5
 
-/*
- * Technically, updating td->status here is a race, but it's not really a
- * problem. The worst that can happen is that we set the IOC bit again
- * generating a spurious interrupt. We could fix this by creating another
- * QH and leaving the IOC bit always set, but then we would have to play
- * games with the FSBR code to make sure we get the correct order in all
- * the cases. I don't think it's worth the effort
- */
-static inline void uhci_set_next_interrupt(struct uhci_hcd *uhci)
-{
-	uhci->term_td->status |= cpu_to_le32(TD_CTRL_IOC); 
-}
-
-static inline void uhci_clear_next_interrupt(struct uhci_hcd *uhci)
-{
-	uhci->term_td->status &= ~cpu_to_le32(TD_CTRL_IOC);
-}
-
-static inline void uhci_moveto_complete(struct uhci_hcd *uhci, 
-					struct urb_priv *urbp)
-{
-	list_move_tail(&urbp->urb_list, &uhci->complete_list);
-}
-
-static struct uhci_td *uhci_alloc_td(struct uhci_hcd *uhci, struct usb_device *dev)
-{
-	dma_addr_t dma_handle;
-	struct uhci_td *td;
-
-	td = dma_pool_alloc(uhci->td_pool, GFP_ATOMIC, &dma_handle);
-	if (!td)
-		return NULL;
-
-	td->dma_handle = dma_handle;
-
-	td->link = UHCI_PTR_TERM;
-	td->buffer = 0;
-
-	td->frame = -1;
-	td->dev = dev;
-
-	INIT_LIST_HEAD(&td->list);
-	INIT_LIST_HEAD(&td->remove_list);
-	INIT_LIST_HEAD(&td->fl_list);
-
-	usb_get_dev(dev);
-
-	return td;
-}
-
-static inline void uhci_fill_td(struct uhci_td *td, u32 status,
-		u32 token, u32 buffer)
-{
-	td->status = cpu_to_le32(status);
-	td->token = cpu_to_le32(token);
-	td->buffer = cpu_to_le32(buffer);
-}
-
-/*
- * We insert Isochronous URB's directly into the frame list at the beginning
- */
-static void uhci_insert_td_frame_list(struct uhci_hcd *uhci, struct uhci_td *td, unsigned framenum)
-{
-	framenum &= (UHCI_NUMFRAMES - 1);
-
-	td->frame = framenum;
-
-	/* Is there a TD already mapped there? */
-	if (uhci->fl->frame_cpu[framenum]) {
-		struct uhci_td *ftd, *ltd;
-
-		ftd = uhci->fl->frame_cpu[framenum];
-		ltd = list_entry(ftd->fl_list.prev, struct uhci_td, fl_list);
-
-		list_add_tail(&td->fl_list, &ftd->fl_list);
-
-		td->link = ltd->link;
-		wmb();
-		ltd->link = cpu_to_le32(td->dma_handle);
-	} else {
-		td->link = uhci->fl->frame[framenum];
-		wmb();
-		uhci->fl->frame[framenum] = cpu_to_le32(td->dma_handle);
-		uhci->fl->frame_cpu[framenum] = td;
-	}
-}
-
-static void uhci_remove_td(struct uhci_hcd *uhci, struct uhci_td *td)
-{
-	/* If it's not inserted, don't remove it */
-	if (td->frame == -1 && list_empty(&td->fl_list))
-		return;
-
-	if (td->frame != -1 && uhci->fl->frame_cpu[td->frame] == td) {
-		if (list_empty(&td->fl_list)) {
-			uhci->fl->frame[td->frame] = td->link;
-			uhci->fl->frame_cpu[td->frame] = NULL;
-		} else {
-			struct uhci_td *ntd;
-
-			ntd = list_entry(td->fl_list.next, struct uhci_td, fl_list);
-			uhci->fl->frame[td->frame] = cpu_to_le32(ntd->dma_handle);
-			uhci->fl->frame_cpu[td->frame] = ntd;
-		}
-	} else {
-		struct uhci_td *ptd;
-
-		ptd = list_entry(td->fl_list.prev, struct uhci_td, fl_list);
-		ptd->link = td->link;
-	}
-
-	wmb();
-	td->link = UHCI_PTR_TERM;
-
-	list_del_init(&td->fl_list);
-	td->frame = -1;
-}
-
-/*
- * Inserts a td list into qh.
- */
-static void uhci_insert_tds_in_qh(struct uhci_qh *qh, struct urb *urb, __le32 breadth)
-{
-	struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
-	struct uhci_td *td;
-	__le32 *plink;
-
-	/* Ordering isn't important here yet since the QH hasn't been */
-	/* inserted into the schedule yet */
-	plink = &qh->element;
-	list_for_each_entry(td, &urbp->td_list, list) {
-		*plink = cpu_to_le32(td->dma_handle) | breadth;
-		plink = &td->link;
-	}
-	*plink = UHCI_PTR_TERM;
-}
-
-static void uhci_free_td(struct uhci_hcd *uhci, struct uhci_td *td)
-{
-	if (!list_empty(&td->list))
-		dev_warn(uhci_dev(uhci), "td %p still in list!\n", td);
-	if (!list_empty(&td->remove_list))
-		dev_warn(uhci_dev(uhci), "td %p still in remove_list!\n", td);
-	if (!list_empty(&td->fl_list))
-		dev_warn(uhci_dev(uhci), "td %p still in fl_list!\n", td);
-
-	if (td->dev)
-		usb_put_dev(td->dev);
-
-	dma_pool_free(uhci->td_pool, td, td->dma_handle);
-}
-
-static struct uhci_qh *uhci_alloc_qh(struct uhci_hcd *uhci, struct usb_device *dev)
-{
-	dma_addr_t dma_handle;
-	struct uhci_qh *qh;
-
-	qh = dma_pool_alloc(uhci->qh_pool, GFP_ATOMIC, &dma_handle);
-	if (!qh)
-		return NULL;
-
-	qh->dma_handle = dma_handle;
-
-	qh->element = UHCI_PTR_TERM;
-	qh->link = UHCI_PTR_TERM;
-
-	qh->dev = dev;
-	qh->urbp = NULL;
-
-	INIT_LIST_HEAD(&qh->list);
-	INIT_LIST_HEAD(&qh->remove_list);
-
-	usb_get_dev(dev);
-
-	return qh;
-}
-
-static void uhci_free_qh(struct uhci_hcd *uhci, struct uhci_qh *qh)
-{
-	if (!list_empty(&qh->list))
-		dev_warn(uhci_dev(uhci), "qh %p list not empty!\n", qh);
-	if (!list_empty(&qh->remove_list))
-		dev_warn(uhci_dev(uhci), "qh %p still in remove_list!\n", qh);
-
-	if (qh->dev)
-		usb_put_dev(qh->dev);
-
-	dma_pool_free(uhci->qh_pool, qh, qh->dma_handle);
-}
-
-/*
- * Append this urb's qh after the last qh in skelqh->list
- *
- * Note that urb_priv.queue_list doesn't have a separate queue head;
- * it's a ring with every element "live".
- */
-static void uhci_insert_qh(struct uhci_hcd *uhci, struct uhci_qh *skelqh, struct urb *urb)
-{
-	struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
-	struct urb_priv *turbp;
-	struct uhci_qh *lqh;
-
-	/* Grab the last QH */
-	lqh = list_entry(skelqh->list.prev, struct uhci_qh, list);
-
-	/* Point to the next skelqh */
-	urbp->qh->link = lqh->link;
-	wmb();				/* Ordering is important */
-
-	/*
-	 * Patch QHs for previous endpoint's queued URBs?  HC goes
-	 * here next, not to the next skelqh it now points to.
-	 *
-	 *    lqh --> td ... --> qh ... --> td --> qh ... --> td
-	 *     |                 |                 |
-	 *     v                 v                 v
-	 *     +<----------------+-----------------+
-	 *     v
-	 *    newqh --> td ... --> td
-	 *     |
-	 *     v
-	 *    ...
-	 *
-	 * The HC could see (and use!) any of these as we write them.
-	 */
-	lqh->link = cpu_to_le32(urbp->qh->dma_handle) | UHCI_PTR_QH;
-	if (lqh->urbp) {
-		list_for_each_entry(turbp, &lqh->urbp->queue_list, queue_list)
-			turbp->qh->link = lqh->link;
-	}
-
-	list_add_tail(&urbp->qh->list, &skelqh->list);
-}
-
-/*
- * Start removal of QH from schedule; it finishes next frame.
- * TDs should be unlinked before this is called.
- */
-static void uhci_remove_qh(struct uhci_hcd *uhci, struct uhci_qh *qh)
-{
-	struct uhci_qh *pqh;
-	__le32 newlink;
-	unsigned int age;
-
-	if (!qh)
-		return;
-
-	/*
-	 * Only go through the hoops if it's actually linked in
-	 */
-	if (!list_empty(&qh->list)) {
-
-		/* If our queue is nonempty, make the next URB the head */
-		if (!list_empty(&qh->urbp->queue_list)) {
-			struct urb_priv *nurbp;
-
-			nurbp = list_entry(qh->urbp->queue_list.next,
-					struct urb_priv, queue_list);
-			nurbp->queued = 0;
-			list_add(&nurbp->qh->list, &qh->list);
-			newlink = cpu_to_le32(nurbp->qh->dma_handle) | UHCI_PTR_QH;
-		} else
-			newlink = qh->link;
-
-		/* Fix up the previous QH's queue to link to either
-		 * the new head of this queue or the start of the
-		 * next endpoint's queue. */
-		pqh = list_entry(qh->list.prev, struct uhci_qh, list);
-		pqh->link = newlink;
-		if (pqh->urbp) {
-			struct urb_priv *turbp;
-
-			list_for_each_entry(turbp, &pqh->urbp->queue_list,
-					queue_list)
-				turbp->qh->link = newlink;
-		}
-		wmb();
-
-		/* Leave qh->link in case the HC is on the QH now, it will */
-		/* continue the rest of the schedule */
-		qh->element = UHCI_PTR_TERM;
-
-		list_del_init(&qh->list);
-	}
-
-	list_del_init(&qh->urbp->queue_list);
-	qh->urbp = NULL;
-
-	age = uhci_get_current_frame_number(uhci);
-	if (age != uhci->qh_remove_age) {
-		uhci_free_pending_qhs(uhci);
-		uhci->qh_remove_age = age;
-	}
-
-	/* Check to see if the remove list is empty. Set the IOC bit */
-	/* to force an interrupt so we can remove the QH */
-	if (list_empty(&uhci->qh_remove_list))
-		uhci_set_next_interrupt(uhci);
-
-	list_add(&qh->remove_list, &uhci->qh_remove_list);
-}
-
-static int uhci_fixup_toggle(struct urb *urb, unsigned int toggle)
-{
-	struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
-	struct uhci_td *td;
-
-	list_for_each_entry(td, &urbp->td_list, list) {
-		if (toggle)
-			td->token |= cpu_to_le32(TD_TOKEN_TOGGLE);
-		else
-			td->token &= ~cpu_to_le32(TD_TOKEN_TOGGLE);
-
-		toggle ^= 1;
-	}
-
-	return toggle;
-}
-
-/* This function will append one URB's QH to another URB's QH. This is for */
-/* queuing interrupt, control or bulk transfers */
-static void uhci_append_queued_urb(struct uhci_hcd *uhci, struct urb *eurb, struct urb *urb)
-{
-	struct urb_priv *eurbp, *urbp, *furbp, *lurbp;
-	struct uhci_td *lltd;
-
-	eurbp = eurb->hcpriv;
-	urbp = urb->hcpriv;
-
-	/* Find the first URB in the queue */
-	furbp = eurbp;
-	if (eurbp->queued) {
-		list_for_each_entry(furbp, &eurbp->queue_list, queue_list)
-			if (!furbp->queued)
-				break;
-	}
-
-	lurbp = list_entry(furbp->queue_list.prev, struct urb_priv, queue_list);
-
-	lltd = list_entry(lurbp->td_list.prev, struct uhci_td, list);
-
-	/* Control transfers always start with toggle 0 */
-	if (!usb_pipecontrol(urb->pipe))
-		usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe),
-				usb_pipeout(urb->pipe),
-				uhci_fixup_toggle(urb,
-					uhci_toggle(td_token(lltd)) ^ 1));
-
-	/* All qh's in the queue need to link to the next queue */
-	urbp->qh->link = eurbp->qh->link;
-
-	wmb();			/* Make sure we flush everything */
-
-	lltd->link = cpu_to_le32(urbp->qh->dma_handle) | UHCI_PTR_QH;
-
-	list_add_tail(&urbp->queue_list, &furbp->queue_list);
-
-	urbp->queued = 1;
-}
-
-static void uhci_delete_queued_urb(struct uhci_hcd *uhci, struct urb *urb)
-{
-	struct urb_priv *urbp, *nurbp, *purbp, *turbp;
-	struct uhci_td *pltd;
-	unsigned int toggle;
-
-	urbp = urb->hcpriv;
-
-	if (list_empty(&urbp->queue_list))
-		return;
-
-	nurbp = list_entry(urbp->queue_list.next, struct urb_priv, queue_list);
-
-	/*
-	 * Fix up the toggle for the following URBs in the queue.
-	 * Only needed for bulk and interrupt: control and isochronous
-	 * endpoints don't propagate toggles between messages.
-	 */
-	if (usb_pipebulk(urb->pipe) || usb_pipeint(urb->pipe)) {
-		if (!urbp->queued)
-			/* We just set the toggle in uhci_unlink_generic */
-			toggle = usb_gettoggle(urb->dev,
-					usb_pipeendpoint(urb->pipe),
-					usb_pipeout(urb->pipe));
-		else {
-			/* If we're in the middle of the queue, grab the */
-			/* toggle from the TD previous to us */
-			purbp = list_entry(urbp->queue_list.prev,
-					struct urb_priv, queue_list);
-			pltd = list_entry(purbp->td_list.prev,
-					struct uhci_td, list);
-			toggle = uhci_toggle(td_token(pltd)) ^ 1;
-		}
-
-		list_for_each_entry(turbp, &urbp->queue_list, queue_list) {
-			if (!turbp->queued)
-				break;
-			toggle = uhci_fixup_toggle(turbp->urb, toggle);
-		}
-
-		usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe),
-				usb_pipeout(urb->pipe), toggle);
-	}
-
-	if (urbp->queued) {
-		/* We're somewhere in the middle (or end).  The case where
-		 * we're at the head is handled in uhci_remove_qh(). */
-		purbp = list_entry(urbp->queue_list.prev, struct urb_priv,
-				queue_list);
-
-		pltd = list_entry(purbp->td_list.prev, struct uhci_td, list);
-		if (nurbp->queued)
-			pltd->link = cpu_to_le32(nurbp->qh->dma_handle) | UHCI_PTR_QH;
-		else
-			/* The next URB happens to be the beginning, so */
-			/*  we're the last, end the chain */
-			pltd->link = UHCI_PTR_TERM;
-	}
-
-	/* urbp->queue_list is handled in uhci_remove_qh() */
-}
-
-static struct urb_priv *uhci_alloc_urb_priv(struct uhci_hcd *uhci, struct urb *urb)
-{
-	struct urb_priv *urbp;
-
-	urbp = kmem_cache_alloc(uhci_up_cachep, SLAB_ATOMIC);
-	if (!urbp)
-		return NULL;
-
-	memset((void *)urbp, 0, sizeof(*urbp));
-
-	urbp->inserttime = jiffies;
-	urbp->fsbrtime = jiffies;
-	urbp->urb = urb;
-	
-	INIT_LIST_HEAD(&urbp->td_list);
-	INIT_LIST_HEAD(&urbp->queue_list);
-	INIT_LIST_HEAD(&urbp->urb_list);
-
-	list_add_tail(&urbp->urb_list, &uhci->urb_list);
-
-	urb->hcpriv = urbp;
-
-	return urbp;
-}
-
-static void uhci_add_td_to_urb(struct urb *urb, struct uhci_td *td)
-{
-	struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
-
-	td->urb = urb;
-
-	list_add_tail(&td->list, &urbp->td_list);
-}
-
-static void uhci_remove_td_from_urb(struct uhci_td *td)
-{
-	if (list_empty(&td->list))
-		return;
-
-	list_del_init(&td->list);
-
-	td->urb = NULL;
-}
-
-static void uhci_destroy_urb_priv(struct uhci_hcd *uhci, struct urb *urb)
-{
-	struct uhci_td *td, *tmp;
-	struct urb_priv *urbp;
-	unsigned int age;
-
-	urbp = (struct urb_priv *)urb->hcpriv;
-	if (!urbp)
-		return;
-
-	if (!list_empty(&urbp->urb_list))
-		dev_warn(uhci_dev(uhci), "urb %p still on uhci->urb_list "
-				"or uhci->remove_list!\n", urb);
-
-	age = uhci_get_current_frame_number(uhci);
-	if (age != uhci->td_remove_age) {
-		uhci_free_pending_tds(uhci);
-		uhci->td_remove_age = age;
-	}
-
-	/* Check to see if the remove list is empty. Set the IOC bit */
-	/* to force an interrupt so we can remove the TD's*/
-	if (list_empty(&uhci->td_remove_list))
-		uhci_set_next_interrupt(uhci);
-
-	list_for_each_entry_safe(td, tmp, &urbp->td_list, list) {
-		uhci_remove_td_from_urb(td);
-		uhci_remove_td(uhci, td);
-		list_add(&td->remove_list, &uhci->td_remove_list);
-	}
-
-	urb->hcpriv = NULL;
-	kmem_cache_free(uhci_up_cachep, urbp);
-}
-
-static void uhci_inc_fsbr(struct uhci_hcd *uhci, struct urb *urb)
-{
-	struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
-
-	if ((!(urb->transfer_flags & URB_NO_FSBR)) && !urbp->fsbr) {
-		urbp->fsbr = 1;
-		if (!uhci->fsbr++ && !uhci->fsbrtimeout)
-			uhci->skel_term_qh->link = cpu_to_le32(uhci->skel_fs_control_qh->dma_handle) | UHCI_PTR_QH;
-	}
-}
-
-static void uhci_dec_fsbr(struct uhci_hcd *uhci, struct urb *urb)
-{
-	struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
-
-	if ((!(urb->transfer_flags & URB_NO_FSBR)) && urbp->fsbr) {
-		urbp->fsbr = 0;
-		if (!--uhci->fsbr)
-			uhci->fsbrtimeout = jiffies + FSBR_DELAY;
-	}
-}
-
-/*
- * Map status to standard result codes
- *
- * <status> is (td_status(td) & 0xF60000), a.k.a.
- * uhci_status_bits(td_status(td)).
- * Note: <status> does not include the TD_CTRL_NAK bit.
- * <dir_out> is True for output TDs and False for input TDs.
- */
-static int uhci_map_status(int status, int dir_out)
-{
-	if (!status)
-		return 0;
-	if (status & TD_CTRL_BITSTUFF)			/* Bitstuff error */
-		return -EPROTO;
-	if (status & TD_CTRL_CRCTIMEO) {		/* CRC/Timeout */
-		if (dir_out)
-			return -EPROTO;
-		else
-			return -EILSEQ;
-	}
-	if (status & TD_CTRL_BABBLE)			/* Babble */
-		return -EOVERFLOW;
-	if (status & TD_CTRL_DBUFERR)			/* Buffer error */
-		return -ENOSR;
-	if (status & TD_CTRL_STALLED)			/* Stalled */
-		return -EPIPE;
-	WARN_ON(status & TD_CTRL_ACTIVE);		/* Active */
-	return 0;
-}
-
-/*
- * Control transfers
- */
-static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb, struct urb *eurb)
-{
-	struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
-	struct uhci_td *td;
-	struct uhci_qh *qh, *skelqh;
-	unsigned long destination, status;
-	int maxsze = usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe));
-	int len = urb->transfer_buffer_length;
-	dma_addr_t data = urb->transfer_dma;
-
-	/* The "pipe" thing contains the destination in bits 8--18 */
-	destination = (urb->pipe & PIPE_DEVEP_MASK) | USB_PID_SETUP;
-
-	/* 3 errors */
-	status = TD_CTRL_ACTIVE | uhci_maxerr(3);
-	if (urb->dev->speed == USB_SPEED_LOW)
-		status |= TD_CTRL_LS;
-
-	/*
-	 * Build the TD for the control request setup packet
-	 */
-	td = uhci_alloc_td(uhci, urb->dev);
-	if (!td)
-		return -ENOMEM;
-
-	uhci_add_td_to_urb(urb, td);
-	uhci_fill_td(td, status, destination | uhci_explen(7),
-		urb->setup_dma);
-
-	/*
-	 * If direction is "send", change the packet ID from SETUP (0x2D)
-	 * to OUT (0xE1).  Else change it from SETUP to IN (0x69) and
-	 * set Short Packet Detect (SPD) for all data packets.
-	 */
-	if (usb_pipeout(urb->pipe))
-		destination ^= (USB_PID_SETUP ^ USB_PID_OUT);
-	else {
-		destination ^= (USB_PID_SETUP ^ USB_PID_IN);
-		status |= TD_CTRL_SPD;
-	}
-
-	/*
-	 * Build the DATA TD's
-	 */
-	while (len > 0) {
-		int pktsze = len;
-
-		if (pktsze > maxsze)
-			pktsze = maxsze;
-
-		td = uhci_alloc_td(uhci, urb->dev);
-		if (!td)
-			return -ENOMEM;
-
-		/* Alternate Data0/1 (start with Data1) */
-		destination ^= TD_TOKEN_TOGGLE;
-	
-		uhci_add_td_to_urb(urb, td);
-		uhci_fill_td(td, status, destination | uhci_explen(pktsze - 1),
-			data);
-
-		data += pktsze;
-		len -= pktsze;
-	}
-
-	/*
-	 * Build the final TD for control status 
-	 */
-	td = uhci_alloc_td(uhci, urb->dev);
-	if (!td)
-		return -ENOMEM;
-
-	/*
-	 * It's IN if the pipe is an output pipe or we're not expecting
-	 * data back.
-	 */
-	destination &= ~TD_TOKEN_PID_MASK;
-	if (usb_pipeout(urb->pipe) || !urb->transfer_buffer_length)
-		destination |= USB_PID_IN;
-	else
-		destination |= USB_PID_OUT;
-
-	destination |= TD_TOKEN_TOGGLE;		/* End in Data1 */
-
-	status &= ~TD_CTRL_SPD;
-
-	uhci_add_td_to_urb(urb, td);
-	uhci_fill_td(td, status | TD_CTRL_IOC,
-		destination | uhci_explen(UHCI_NULL_DATA_SIZE), 0);
-
-	qh = uhci_alloc_qh(uhci, urb->dev);
-	if (!qh)
-		return -ENOMEM;
-
-	urbp->qh = qh;
-	qh->urbp = urbp;
-
-	uhci_insert_tds_in_qh(qh, urb, UHCI_PTR_BREADTH);
-
-	/* Low-speed transfers get a different queue, and won't hog the bus.
-	 * Also, some devices enumerate better without FSBR; the easiest way
-	 * to do that is to put URBs on the low-speed queue while the device
-	 * is in the DEFAULT state. */
-	if (urb->dev->speed == USB_SPEED_LOW ||
-			urb->dev->state == USB_STATE_DEFAULT)
-		skelqh = uhci->skel_ls_control_qh;
-	else {
-		skelqh = uhci->skel_fs_control_qh;
-		uhci_inc_fsbr(uhci, urb);
-	}
-
-	if (eurb)
-		uhci_append_queued_urb(uhci, eurb, urb);
-	else
-		uhci_insert_qh(uhci, skelqh, urb);
-
-	return -EINPROGRESS;
-}
-
-/*
- * If control-IN transfer was short, the status packet wasn't sent.
- * This routine changes the element pointer in the QH to point at the
- * status TD.  It's safe to do this even while the QH is live, because
- * the hardware only updates the element pointer following a successful
- * transfer.  The inactive TD for the short packet won't cause an update,
- * so the pointer won't get overwritten.  The next time the controller
- * sees this QH, it will send the status packet.
- */
-static int usb_control_retrigger_status(struct uhci_hcd *uhci, struct urb *urb)
-{
-	struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
-	struct uhci_td *td;
-
-	urbp->short_control_packet = 1;
-
-	td = list_entry(urbp->td_list.prev, struct uhci_td, list);
-	urbp->qh->element = cpu_to_le32(td->dma_handle);
-
-	return -EINPROGRESS;
-}
-
-
-static int uhci_result_control(struct uhci_hcd *uhci, struct urb *urb)
-{
-	struct list_head *tmp, *head;
-	struct urb_priv *urbp = urb->hcpriv;
-	struct uhci_td *td;
-	unsigned int status;
-	int ret = 0;
-
-	if (list_empty(&urbp->td_list))
-		return -EINVAL;
-
-	head = &urbp->td_list;
-
-	if (urbp->short_control_packet) {
-		tmp = head->prev;
-		goto status_stage;
-	}
-
-	tmp = head->next;
-	td = list_entry(tmp, struct uhci_td, list);
-
-	/* The first TD is the SETUP stage, check the status, but skip */
-	/*  the count */
-	status = uhci_status_bits(td_status(td));
-	if (status & TD_CTRL_ACTIVE)
-		return -EINPROGRESS;
-
-	if (status)
-		goto td_error;
-
-	urb->actual_length = 0;
-
-	/* The rest of the TD's (but the last) are data */
-	tmp = tmp->next;
-	while (tmp != head && tmp->next != head) {
-		unsigned int ctrlstat;
-
-		td = list_entry(tmp, struct uhci_td, list);
-		tmp = tmp->next;
-
-		ctrlstat = td_status(td);
-		status = uhci_status_bits(ctrlstat);
-		if (status & TD_CTRL_ACTIVE)
-			return -EINPROGRESS;
-
-		urb->actual_length += uhci_actual_length(ctrlstat);
-
-		if (status)
-			goto td_error;
-
-		/* Check to see if we received a short packet */
-		if (uhci_actual_length(ctrlstat) <
-				uhci_expected_length(td_token(td))) {
-			if (urb->transfer_flags & URB_SHORT_NOT_OK) {
-				ret = -EREMOTEIO;
-				goto err;
-			}
-
-			if (uhci_packetid(td_token(td)) == USB_PID_IN)
-				return usb_control_retrigger_status(uhci, urb);
-			else
-				return 0;
-		}
-	}
-
-status_stage:
-	td = list_entry(tmp, struct uhci_td, list);
-
-	/* Control status stage */
-	status = td_status(td);
-
-#ifdef I_HAVE_BUGGY_APC_BACKUPS
-	/* APC BackUPS Pro kludge */
-	/* It tries to send all of the descriptor instead of the amount */
-	/*  we requested */
-	if (status & TD_CTRL_IOC &&	/* IOC is masked out by uhci_status_bits */
-	    status & TD_CTRL_ACTIVE &&
-	    status & TD_CTRL_NAK)
-		return 0;
-#endif
-
-	status = uhci_status_bits(status);
-	if (status & TD_CTRL_ACTIVE)
-		return -EINPROGRESS;
-
-	if (status)
-		goto td_error;
-
-	return 0;
-
-td_error:
-	ret = uhci_map_status(status, uhci_packetout(td_token(td)));
-
-err:
-	if ((debug == 1 && ret != -EPIPE) || debug > 1) {
-		/* Some debugging code */
-		dev_dbg(uhci_dev(uhci), "%s: failed with status %x\n",
-				__FUNCTION__, status);
-
-		if (errbuf) {
-			/* Print the chain for debugging purposes */
-			uhci_show_qh(urbp->qh, errbuf, ERRBUF_LEN, 0);
-
-			lprintk(errbuf);
-		}
-	}
-
-	return ret;
-}
-
-/*
- * Common submit for bulk and interrupt
- */
-static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb, struct urb *eurb, struct uhci_qh *skelqh)
-{
-	struct uhci_td *td;
-	struct uhci_qh *qh;
-	unsigned long destination, status;
-	int maxsze = usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe));
-	int len = urb->transfer_buffer_length;
-	struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
-	dma_addr_t data = urb->transfer_dma;
-
-	if (len < 0)
-		return -EINVAL;
-
-	/* The "pipe" thing contains the destination in bits 8--18 */
-	destination = (urb->pipe & PIPE_DEVEP_MASK) | usb_packetid(urb->pipe);
-
-	status = uhci_maxerr(3) | TD_CTRL_ACTIVE;
-	if (urb->dev->speed == USB_SPEED_LOW)
-		status |= TD_CTRL_LS;
-	if (usb_pipein(urb->pipe))
-		status |= TD_CTRL_SPD;
-
-	/*
-	 * Build the DATA TD's
-	 */
-	do {	/* Allow zero length packets */
-		int pktsze = maxsze;
-
-		if (pktsze >= len) {
-			pktsze = len;
-			if (!(urb->transfer_flags & URB_SHORT_NOT_OK))
-				status &= ~TD_CTRL_SPD;
-		}
-
-		td = uhci_alloc_td(uhci, urb->dev);
-		if (!td)
-			return -ENOMEM;
-
-		uhci_add_td_to_urb(urb, td);
-		uhci_fill_td(td, status, destination | uhci_explen(pktsze - 1) |
-			(usb_gettoggle(urb->dev, usb_pipeendpoint(urb->pipe),
-			 usb_pipeout(urb->pipe)) << TD_TOKEN_TOGGLE_SHIFT),
-			data);
-
-		data += pktsze;
-		len -= maxsze;
-
-		usb_dotoggle(urb->dev, usb_pipeendpoint(urb->pipe),
-			usb_pipeout(urb->pipe));
-	} while (len > 0);
-
-	/*
-	 * URB_ZERO_PACKET means adding a 0-length packet, if direction
-	 * is OUT and the transfer_length was an exact multiple of maxsze,
-	 * hence (len = transfer_length - N * maxsze) == 0
-	 * however, if transfer_length == 0, the zero packet was already
-	 * prepared above.
-	 */
-	if (usb_pipeout(urb->pipe) && (urb->transfer_flags & URB_ZERO_PACKET) &&
-	    !len && urb->transfer_buffer_length) {
-		td = uhci_alloc_td(uhci, urb->dev);
-		if (!td)
-			return -ENOMEM;
-
-		uhci_add_td_to_urb(urb, td);
-		uhci_fill_td(td, status, destination | uhci_explen(UHCI_NULL_DATA_SIZE) |
-			(usb_gettoggle(urb->dev, usb_pipeendpoint(urb->pipe),
-			 usb_pipeout(urb->pipe)) << TD_TOKEN_TOGGLE_SHIFT),
-			data);
-
-		usb_dotoggle(urb->dev, usb_pipeendpoint(urb->pipe),
-			usb_pipeout(urb->pipe));
-	}
-
-	/* Set the interrupt-on-completion flag on the last packet.
-	 * A more-or-less typical 4 KB URB (= size of one memory page)
-	 * will require about 3 ms to transfer; that's a little on the
-	 * fast side but not enough to justify delaying an interrupt
-	 * more than 2 or 3 URBs, so we will ignore the URB_NO_INTERRUPT
-	 * flag setting. */
-	td->status |= cpu_to_le32(TD_CTRL_IOC);
-
-	qh = uhci_alloc_qh(uhci, urb->dev);
-	if (!qh)
-		return -ENOMEM;
-
-	urbp->qh = qh;
-	qh->urbp = urbp;
-
-	/* Always breadth first */
-	uhci_insert_tds_in_qh(qh, urb, UHCI_PTR_BREADTH);
-
-	if (eurb)
-		uhci_append_queued_urb(uhci, eurb, urb);
-	else
-		uhci_insert_qh(uhci, skelqh, urb);
-
-	return -EINPROGRESS;
-}
-
-/*
- * Common result for bulk and interrupt
- */
-static int uhci_result_common(struct uhci_hcd *uhci, struct urb *urb)
-{
-	struct urb_priv *urbp = urb->hcpriv;
-	struct uhci_td *td;
-	unsigned int status = 0;
-	int ret = 0;
-
-	urb->actual_length = 0;
-
-	list_for_each_entry(td, &urbp->td_list, list) {
-		unsigned int ctrlstat = td_status(td);
-
-		status = uhci_status_bits(ctrlstat);
-		if (status & TD_CTRL_ACTIVE)
-			return -EINPROGRESS;
-
-		urb->actual_length += uhci_actual_length(ctrlstat);
-
-		if (status)
-			goto td_error;
-
-		if (uhci_actual_length(ctrlstat) <
-				uhci_expected_length(td_token(td))) {
-			if (urb->transfer_flags & URB_SHORT_NOT_OK) {
-				ret = -EREMOTEIO;
-				goto err;
-			} else
-				return 0;
-		}
-	}
-
-	return 0;
-
-td_error:
-	ret = uhci_map_status(status, uhci_packetout(td_token(td)));
-
-err:
-	/* 
-	 * Enable this chunk of code if you want to see some more debugging.
-	 * But be careful, it has the tendancy to starve out khubd and prevent
-	 * disconnects from happening successfully if you have a slow debug
-	 * log interface (like a serial console.
-	 */
-#if 0
-	if ((debug == 1 && ret != -EPIPE) || debug > 1) {
-		/* Some debugging code */
-		dev_dbg(uhci_dev(uhci), "%s: failed with status %x\n",
-				__FUNCTION__, status);
-
-		if (errbuf) {
-			/* Print the chain for debugging purposes */
-			uhci_show_qh(urbp->qh, errbuf, ERRBUF_LEN, 0);
-
-			lprintk(errbuf);
-		}
-	}
-#endif
-	return ret;
-}
-
-static inline int uhci_submit_bulk(struct uhci_hcd *uhci, struct urb *urb, struct urb *eurb)
-{
-	int ret;
-
-	/* Can't have low-speed bulk transfers */
-	if (urb->dev->speed == USB_SPEED_LOW)
-		return -EINVAL;
-
-	ret = uhci_submit_common(uhci, urb, eurb, uhci->skel_bulk_qh);
-	if (ret == -EINPROGRESS)
-		uhci_inc_fsbr(uhci, urb);
-
-	return ret;
-}
-
-static inline int uhci_submit_interrupt(struct uhci_hcd *uhci, struct urb *urb, struct urb *eurb)
-{
-	/* USB 1.1 interrupt transfers only involve one packet per interval;
-	 * that's the uhci_submit_common() "breadth first" policy.  Drivers
-	 * can submit urbs of any length, but longer ones might need many
-	 * intervals to complete.
-	 */
-	return uhci_submit_common(uhci, urb, eurb, uhci->skelqh[__interval_to_skel(urb->interval)]);
-}
-
-/*
- * Isochronous transfers
- */
-static int isochronous_find_limits(struct uhci_hcd *uhci, struct urb *urb, unsigned int *start, unsigned int *end)
-{
-	struct urb *last_urb = NULL;
-	struct urb_priv *up;
-	int ret = 0;
-
-	list_for_each_entry(up, &uhci->urb_list, urb_list) {
-		struct urb *u = up->urb;
-
-		/* look for pending URB's with identical pipe handle */
-		if ((urb->pipe == u->pipe) && (urb->dev == u->dev) &&
-		    (u->status == -EINPROGRESS) && (u != urb)) {
-			if (!last_urb)
-				*start = u->start_frame;
-			last_urb = u;
-		}
-	}
-
-	if (last_urb) {
-		*end = (last_urb->start_frame + last_urb->number_of_packets *
-				last_urb->interval) & (UHCI_NUMFRAMES-1);
-		ret = 0;
-	} else
-		ret = -1;	/* no previous urb found */
-
-	return ret;
-}
-
-static int isochronous_find_start(struct uhci_hcd *uhci, struct urb *urb)
-{
-	int limits;
-	unsigned int start = 0, end = 0;
-
-	if (urb->number_of_packets > 900)	/* 900? Why? */
-		return -EFBIG;
-
-	limits = isochronous_find_limits(uhci, urb, &start, &end);
-
-	if (urb->transfer_flags & URB_ISO_ASAP) {
-		if (limits)
-			urb->start_frame =
-					(uhci_get_current_frame_number(uhci) +
-						10) & (UHCI_NUMFRAMES - 1);
-		else
-			urb->start_frame = end;
-	} else {
-		urb->start_frame &= (UHCI_NUMFRAMES - 1);
-		/* FIXME: Sanity check */
-	}
-
-	return 0;
-}
-
-/*
- * Isochronous transfers
- */
-static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb)
-{
-	struct uhci_td *td;
-	int i, ret, frame;
-	int status, destination;
-
-	status = TD_CTRL_ACTIVE | TD_CTRL_IOS;
-	destination = (urb->pipe & PIPE_DEVEP_MASK) | usb_packetid(urb->pipe);
-
-	ret = isochronous_find_start(uhci, urb);
-	if (ret)
-		return ret;
-
-	frame = urb->start_frame;
-	for (i = 0; i < urb->number_of_packets; i++, frame += urb->interval) {
-		if (!urb->iso_frame_desc[i].length)
-			continue;
-
-		td = uhci_alloc_td(uhci, urb->dev);
-		if (!td)
-			return -ENOMEM;
-
-		uhci_add_td_to_urb(urb, td);
-		uhci_fill_td(td, status, destination | uhci_explen(urb->iso_frame_desc[i].length - 1),
-			urb->transfer_dma + urb->iso_frame_desc[i].offset);
-
-		if (i + 1 >= urb->number_of_packets)
-			td->status |= cpu_to_le32(TD_CTRL_IOC);
-
-		uhci_insert_td_frame_list(uhci, td, frame);
-	}
-
-	return -EINPROGRESS;
-}
-
-static int uhci_result_isochronous(struct uhci_hcd *uhci, struct urb *urb)
-{
-	struct uhci_td *td;
-	struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
-	int status;
-	int i, ret = 0;
-
-	urb->actual_length = 0;
-
-	i = 0;
-	list_for_each_entry(td, &urbp->td_list, list) {
-		int actlength;
-		unsigned int ctrlstat = td_status(td);
-
-		if (ctrlstat & TD_CTRL_ACTIVE)
-			return -EINPROGRESS;
-
-		actlength = uhci_actual_length(ctrlstat);
-		urb->iso_frame_desc[i].actual_length = actlength;
-		urb->actual_length += actlength;
-
-		status = uhci_map_status(uhci_status_bits(ctrlstat),
-				usb_pipeout(urb->pipe));
-		urb->iso_frame_desc[i].status = status;
-		if (status) {
-			urb->error_count++;
-			ret = status;
-		}
-
-		i++;
-	}
-
-	return ret;
-}
-
-static struct urb *uhci_find_urb_ep(struct uhci_hcd *uhci, struct urb *urb)
-{
-	struct urb_priv *up;
-
-	/* We don't match Isoc transfers since they are special */
-	if (usb_pipeisoc(urb->pipe))
-		return NULL;
-
-	list_for_each_entry(up, &uhci->urb_list, urb_list) {
-		struct urb *u = up->urb;
-
-		if (u->dev == urb->dev && u->status == -EINPROGRESS) {
-			/* For control, ignore the direction */
-			if (usb_pipecontrol(urb->pipe) &&
-			    (u->pipe & ~USB_DIR_IN) == (urb->pipe & ~USB_DIR_IN))
-				return u;
-			else if (u->pipe == urb->pipe)
-				return u;
-		}
-	}
-
-	return NULL;
-}
-
-static int uhci_urb_enqueue(struct usb_hcd *hcd,
-		struct usb_host_endpoint *ep,
-		struct urb *urb, int mem_flags)
-{
-	int ret;
-	struct uhci_hcd *uhci = hcd_to_uhci(hcd);
-	unsigned long flags;
-	struct urb *eurb;
-	int bustime;
-
-	spin_lock_irqsave(&uhci->schedule_lock, flags);
-
-	ret = urb->status;
-	if (ret != -EINPROGRESS)		/* URB already unlinked! */
-		goto out;
-
-	eurb = uhci_find_urb_ep(uhci, urb);
-
-	if (!uhci_alloc_urb_priv(uhci, urb)) {
-		ret = -ENOMEM;
-		goto out;
-	}
-
-	switch (usb_pipetype(urb->pipe)) {
-	case PIPE_CONTROL:
-		ret = uhci_submit_control(uhci, urb, eurb);
-		break;
-	case PIPE_INTERRUPT:
-		if (!eurb) {
-			bustime = usb_check_bandwidth(urb->dev, urb);
-			if (bustime < 0)
-				ret = bustime;
-			else {
-				ret = uhci_submit_interrupt(uhci, urb, eurb);
-				if (ret == -EINPROGRESS)
-					usb_claim_bandwidth(urb->dev, urb, bustime, 0);
-			}
-		} else {	/* inherit from parent */
-			urb->bandwidth = eurb->bandwidth;
-			ret = uhci_submit_interrupt(uhci, urb, eurb);
-		}
-		break;
-	case PIPE_BULK:
-		ret = uhci_submit_bulk(uhci, urb, eurb);
-		break;
-	case PIPE_ISOCHRONOUS:
-		bustime = usb_check_bandwidth(urb->dev, urb);
-		if (bustime < 0) {
-			ret = bustime;
-			break;
-		}
-
-		ret = uhci_submit_isochronous(uhci, urb);
-		if (ret == -EINPROGRESS)
-			usb_claim_bandwidth(urb->dev, urb, bustime, 1);
-		break;
-	}
-
-	if (ret != -EINPROGRESS) {
-		/* Submit failed, so delete it from the urb_list */
-		struct urb_priv *urbp = urb->hcpriv;
-
-		list_del_init(&urbp->urb_list);
-		uhci_destroy_urb_priv(uhci, urb);
-	} else
-		ret = 0;
-
-out:
-	spin_unlock_irqrestore(&uhci->schedule_lock, flags);
-	return ret;
-}
-
-/*
- * Return the result of a transfer
- */
-static void uhci_transfer_result(struct uhci_hcd *uhci, struct urb *urb)
-{
-	int ret = -EINPROGRESS;
-	struct urb_priv *urbp;
-
-	spin_lock(&urb->lock);
-
-	urbp = (struct urb_priv *)urb->hcpriv;
-
-	if (urb->status != -EINPROGRESS)	/* URB already dequeued */
-		goto out;
-
-	switch (usb_pipetype(urb->pipe)) {
-	case PIPE_CONTROL:
-		ret = uhci_result_control(uhci, urb);
-		break;
-	case PIPE_BULK:
-	case PIPE_INTERRUPT:
-		ret = uhci_result_common(uhci, urb);
-		break;
-	case PIPE_ISOCHRONOUS:
-		ret = uhci_result_isochronous(uhci, urb);
-		break;
-	}
-
-	if (ret == -EINPROGRESS)
-		goto out;
-	urb->status = ret;
-
-	switch (usb_pipetype(urb->pipe)) {
-	case PIPE_CONTROL:
-	case PIPE_BULK:
-	case PIPE_ISOCHRONOUS:
-		/* Release bandwidth for Interrupt or Isoc. transfers */
-		if (urb->bandwidth)
-			usb_release_bandwidth(urb->dev, urb, 1);
-		uhci_unlink_generic(uhci, urb);
-		break;
-	case PIPE_INTERRUPT:
-		/* Release bandwidth for Interrupt or Isoc. transfers */
-		/* Make sure we don't release if we have a queued URB */
-		if (list_empty(&urbp->queue_list) && urb->bandwidth)
-			usb_release_bandwidth(urb->dev, urb, 0);
-		else
-			/* bandwidth was passed on to queued URB, */
-			/* so don't let usb_unlink_urb() release it */
-			urb->bandwidth = 0;
-		uhci_unlink_generic(uhci, urb);
-		break;
-	default:
-		dev_info(uhci_dev(uhci), "%s: unknown pipe type %d "
-				"for urb %p\n",
-				__FUNCTION__, usb_pipetype(urb->pipe), urb);
-	}
-
-	/* Move it from uhci->urb_list to uhci->complete_list */
-	uhci_moveto_complete(uhci, urbp);
-
-out:
-	spin_unlock(&urb->lock);
-}
-
-static void uhci_unlink_generic(struct uhci_hcd *uhci, struct urb *urb)
-{
-	struct list_head *head;
-	struct uhci_td *td;
-	struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
-	int prevactive = 0;
-
-	uhci_dec_fsbr(uhci, urb);	/* Safe since it checks */
-
-	/*
-	 * Now we need to find out what the last successful toggle was
-	 * so we can update the local data toggle for the next transfer
-	 *
-	 * There are 2 ways the last successful completed TD is found:
-	 *
-	 * 1) The TD is NOT active and the actual length < expected length
-	 * 2) The TD is NOT active and it's the last TD in the chain
-	 *
-	 * and a third way the first uncompleted TD is found:
-	 *
-	 * 3) The TD is active and the previous TD is NOT active
-	 *
-	 * Control and Isochronous ignore the toggle, so this is safe
-	 * for all types
-	 *
-	 * FIXME: The toggle fixups won't be 100% reliable until we
-	 * change over to using a single queue for each endpoint and
-	 * stop the queue before unlinking.
-	 */
-	head = &urbp->td_list;
-	list_for_each_entry(td, head, list) {
-		unsigned int ctrlstat = td_status(td);
-
-		if (!(ctrlstat & TD_CTRL_ACTIVE) &&
-				(uhci_actual_length(ctrlstat) <
-				 uhci_expected_length(td_token(td)) ||
-				td->list.next == head))
-			usb_settoggle(urb->dev, uhci_endpoint(td_token(td)),
-				uhci_packetout(td_token(td)),
-				uhci_toggle(td_token(td)) ^ 1);
-		else if ((ctrlstat & TD_CTRL_ACTIVE) && !prevactive)
-			usb_settoggle(urb->dev, uhci_endpoint(td_token(td)),
-				uhci_packetout(td_token(td)),
-				uhci_toggle(td_token(td)));
-
-		prevactive = ctrlstat & TD_CTRL_ACTIVE;
-	}
-
-	uhci_delete_queued_urb(uhci, urb);
-
-	/* The interrupt loop will reclaim the QH's */
-	uhci_remove_qh(uhci, urbp->qh);
-	urbp->qh = NULL;
-}
-
-static int uhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb)
-{
-	struct uhci_hcd *uhci = hcd_to_uhci(hcd);
-	unsigned long flags;
-	struct urb_priv *urbp;
-	unsigned int age;
-
-	spin_lock_irqsave(&uhci->schedule_lock, flags);
-	urbp = urb->hcpriv;
-	if (!urbp)			/* URB was never linked! */
-		goto done;
-	list_del_init(&urbp->urb_list);
-
-	uhci_unlink_generic(uhci, urb);
-
-	age = uhci_get_current_frame_number(uhci);
-	if (age != uhci->urb_remove_age) {
-		uhci_remove_pending_urbps(uhci);
-		uhci->urb_remove_age = age;
-	}
-
-	/* If we're the first, set the next interrupt bit */
-	if (list_empty(&uhci->urb_remove_list))
-		uhci_set_next_interrupt(uhci);
-	list_add_tail(&urbp->urb_list, &uhci->urb_remove_list);
-
-done:
-	spin_unlock_irqrestore(&uhci->schedule_lock, flags);
-	return 0;
-}
-
-static int uhci_fsbr_timeout(struct uhci_hcd *uhci, struct urb *urb)
-{
-	struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
-	struct list_head *head;
-	struct uhci_td *td;
-	int count = 0;
-
-	uhci_dec_fsbr(uhci, urb);
-
-	urbp->fsbr_timeout = 1;
-
-	/*
-	 * Ideally we would want to fix qh->element as well, but it's
-	 * read/write by the HC, so that can introduce a race. It's not
-	 * really worth the hassle
-	 */
-
-	head = &urbp->td_list;
-	list_for_each_entry(td, head, list) {
-		/*
-		 * Make sure we don't do the last one (since it'll have the
-		 * TERM bit set) as well as we skip every so many TD's to
-		 * make sure it doesn't hog the bandwidth
-		 */
-		if (td->list.next != head && (count % DEPTH_INTERVAL) ==
-				(DEPTH_INTERVAL - 1))
-			td->link |= UHCI_PTR_DEPTH;
-
-		count++;
-	}
-
-	return 0;
-}
-
-/*
- * uhci_get_current_frame_number()
- *
- * returns the current frame number for a USB bus/controller.
- */
-static unsigned int uhci_get_current_frame_number(struct uhci_hcd *uhci)
-{
-	return inw(uhci->io_addr + USBFRNUM);
-}
+#include "uhci-hub.c"
+#include "uhci-debug.c"
+#include "uhci-q.c"
 
 static int init_stall_timer(struct usb_hcd *hcd);
 
@@ -1592,62 +167,6 @@
 	return 0;
 }
 
-static void uhci_free_pending_qhs(struct uhci_hcd *uhci)
-{
-	struct uhci_qh *qh, *tmp;
-
-	list_for_each_entry_safe(qh, tmp, &uhci->qh_remove_list, remove_list) {
-		list_del_init(&qh->remove_list);
-
-		uhci_free_qh(uhci, qh);
-	}
-}
-
-static void uhci_free_pending_tds(struct uhci_hcd *uhci)
-{
-	struct uhci_td *td, *tmp;
-
-	list_for_each_entry_safe(td, tmp, &uhci->td_remove_list, remove_list) {
-		list_del_init(&td->remove_list);
-
-		uhci_free_td(uhci, td);
-	}
-}
-
-static void
-uhci_finish_urb(struct usb_hcd *hcd, struct urb *urb, struct pt_regs *regs)
-__releases(uhci->schedule_lock)
-__acquires(uhci->schedule_lock)
-{
-	struct uhci_hcd *uhci = hcd_to_uhci(hcd);
-
-	uhci_destroy_urb_priv(uhci, urb);
-
-	spin_unlock(&uhci->schedule_lock);
-	usb_hcd_giveback_urb(hcd, urb, regs);
-	spin_lock(&uhci->schedule_lock);
-}
-
-static void uhci_finish_completion(struct usb_hcd *hcd, struct pt_regs *regs)
-{
-	struct uhci_hcd *uhci = hcd_to_uhci(hcd);
-	struct urb_priv *urbp, *tmp;
-
-	list_for_each_entry_safe(urbp, tmp, &uhci->complete_list, urb_list) {
-		struct urb *urb = urbp->urb;
-
-		list_del_init(&urbp->urb_list);
-		uhci_finish_urb(hcd, urb, regs);
-	}
-}
-
-static void uhci_remove_pending_urbps(struct uhci_hcd *uhci)
-{
-
-	/* Splice the urb_remove_list onto the end of the complete_list */
-	list_splice_init(&uhci->urb_remove_list, uhci->complete_list.prev);
-}
-
 static irqreturn_t uhci_irq(struct usb_hcd *hcd, struct pt_regs *regs)
 {
 	struct uhci_hcd *uhci = hcd_to_uhci(hcd);
@@ -1866,6 +385,14 @@
 	}
 }
 
+/*
+ * returns the current frame number for a USB bus/controller.
+ */
+static unsigned int uhci_get_current_frame_number(struct uhci_hcd *uhci)
+{
+	return inw(uhci->io_addr + USBFRNUM);
+}
+
 static int start_hc(struct uhci_hcd *uhci)
 {
 	unsigned long io_addr = uhci->io_addr;
@@ -1906,7 +433,7 @@
 }
 
 /*
- * De-allocate all resources..
+ * De-allocate all resources
  */
 static void release_uhci(struct uhci_hcd *uhci)
 {
@@ -1949,7 +476,7 @@
 {
 	struct uhci_hcd *uhci = hcd_to_uhci(hcd);
 
-	uhci->io_addr = (unsigned long) hcd->regs;
+	uhci->io_addr = (unsigned long) hcd->rsrc_start;
 
 	/* Kick BIOS off this hardware and reset, so we won't get
 	 * interrupts from any previous setup.
@@ -1984,7 +511,7 @@
 	struct usb_device *udev;
 	struct dentry *dentry;
 
-	io_size = pci_resource_len(to_pci_dev(uhci_dev(uhci)), hcd->region);
+	io_size = (unsigned) hcd->rsrc_len;
 
 	dentry = debugfs_create_file(hcd->self.bus_name, S_IFREG|S_IRUGO|S_IWUSR, uhci_debugfs_root, uhci, &uhci_debug_operations);
 	if (!dentry) {
diff -Nru a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/usb/host/uhci-q.c	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,1488 @@
+/*
+ * Universal Host Controller Interface driver for USB.
+ *
+ * Maintainer: Alan Stern <stern@rowland.harvard.edu>
+ *
+ * (C) Copyright 1999 Linus Torvalds
+ * (C) Copyright 1999-2002 Johannes Erdfelt, johannes@erdfelt.com
+ * (C) Copyright 1999 Randy Dunlap
+ * (C) Copyright 1999 Georg Acher, acher@in.tum.de
+ * (C) Copyright 1999 Deti Fliegl, deti@fliegl.de
+ * (C) Copyright 1999 Thomas Sailer, sailer@ife.ee.ethz.ch
+ * (C) Copyright 1999 Roman Weissgaerber, weissg@vienna.at
+ * (C) Copyright 2000 Yggdrasil Computing, Inc. (port of new PCI interface
+ *               support from usb-ohci.c by Adam Richter, adam@yggdrasil.com).
+ * (C) Copyright 1999 Gregory P. Smith (from usb-ohci.c)
+ * (C) Copyright 2004 Alan Stern, stern@rowland.harvard.edu
+ */
+
+static int uhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb);
+static void uhci_unlink_generic(struct uhci_hcd *uhci, struct urb *urb);
+static void uhci_remove_pending_urbps(struct uhci_hcd *uhci);
+static void uhci_free_pending_qhs(struct uhci_hcd *uhci);
+static void uhci_free_pending_tds(struct uhci_hcd *uhci);
+
+/*
+ * Technically, updating td->status here is a race, but it's not really a
+ * problem. The worst that can happen is that we set the IOC bit again
+ * generating a spurious interrupt. We could fix this by creating another
+ * QH and leaving the IOC bit always set, but then we would have to play
+ * games with the FSBR code to make sure we get the correct order in all
+ * the cases. I don't think it's worth the effort
+ */
+static inline void uhci_set_next_interrupt(struct uhci_hcd *uhci)
+{
+	uhci->term_td->status |= cpu_to_le32(TD_CTRL_IOC); 
+}
+
+static inline void uhci_clear_next_interrupt(struct uhci_hcd *uhci)
+{
+	uhci->term_td->status &= ~cpu_to_le32(TD_CTRL_IOC);
+}
+
+static inline void uhci_moveto_complete(struct uhci_hcd *uhci, 
+					struct urb_priv *urbp)
+{
+	list_move_tail(&urbp->urb_list, &uhci->complete_list);
+}
+
+static struct uhci_td *uhci_alloc_td(struct uhci_hcd *uhci, struct usb_device *dev)
+{
+	dma_addr_t dma_handle;
+	struct uhci_td *td;
+
+	td = dma_pool_alloc(uhci->td_pool, GFP_ATOMIC, &dma_handle);
+	if (!td)
+		return NULL;
+
+	td->dma_handle = dma_handle;
+
+	td->link = UHCI_PTR_TERM;
+	td->buffer = 0;
+
+	td->frame = -1;
+	td->dev = dev;
+
+	INIT_LIST_HEAD(&td->list);
+	INIT_LIST_HEAD(&td->remove_list);
+	INIT_LIST_HEAD(&td->fl_list);
+
+	usb_get_dev(dev);
+
+	return td;
+}
+
+static inline void uhci_fill_td(struct uhci_td *td, u32 status,
+		u32 token, u32 buffer)
+{
+	td->status = cpu_to_le32(status);
+	td->token = cpu_to_le32(token);
+	td->buffer = cpu_to_le32(buffer);
+}
+
+/*
+ * We insert Isochronous URB's directly into the frame list at the beginning
+ */
+static void uhci_insert_td_frame_list(struct uhci_hcd *uhci, struct uhci_td *td, unsigned framenum)
+{
+	framenum &= (UHCI_NUMFRAMES - 1);
+
+	td->frame = framenum;
+
+	/* Is there a TD already mapped there? */
+	if (uhci->fl->frame_cpu[framenum]) {
+		struct uhci_td *ftd, *ltd;
+
+		ftd = uhci->fl->frame_cpu[framenum];
+		ltd = list_entry(ftd->fl_list.prev, struct uhci_td, fl_list);
+
+		list_add_tail(&td->fl_list, &ftd->fl_list);
+
+		td->link = ltd->link;
+		wmb();
+		ltd->link = cpu_to_le32(td->dma_handle);
+	} else {
+		td->link = uhci->fl->frame[framenum];
+		wmb();
+		uhci->fl->frame[framenum] = cpu_to_le32(td->dma_handle);
+		uhci->fl->frame_cpu[framenum] = td;
+	}
+}
+
+static void uhci_remove_td(struct uhci_hcd *uhci, struct uhci_td *td)
+{
+	/* If it's not inserted, don't remove it */
+	if (td->frame == -1 && list_empty(&td->fl_list))
+		return;
+
+	if (td->frame != -1 && uhci->fl->frame_cpu[td->frame] == td) {
+		if (list_empty(&td->fl_list)) {
+			uhci->fl->frame[td->frame] = td->link;
+			uhci->fl->frame_cpu[td->frame] = NULL;
+		} else {
+			struct uhci_td *ntd;
+
+			ntd = list_entry(td->fl_list.next, struct uhci_td, fl_list);
+			uhci->fl->frame[td->frame] = cpu_to_le32(ntd->dma_handle);
+			uhci->fl->frame_cpu[td->frame] = ntd;
+		}
+	} else {
+		struct uhci_td *ptd;
+
+		ptd = list_entry(td->fl_list.prev, struct uhci_td, fl_list);
+		ptd->link = td->link;
+	}
+
+	wmb();
+	td->link = UHCI_PTR_TERM;
+
+	list_del_init(&td->fl_list);
+	td->frame = -1;
+}
+
+/*
+ * Inserts a td list into qh.
+ */
+static void uhci_insert_tds_in_qh(struct uhci_qh *qh, struct urb *urb, __le32 breadth)
+{
+	struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
+	struct uhci_td *td;
+	__le32 *plink;
+
+	/* Ordering isn't important here yet since the QH hasn't been */
+	/* inserted into the schedule yet */
+	plink = &qh->element;
+	list_for_each_entry(td, &urbp->td_list, list) {
+		*plink = cpu_to_le32(td->dma_handle) | breadth;
+		plink = &td->link;
+	}
+	*plink = UHCI_PTR_TERM;
+}
+
+static void uhci_free_td(struct uhci_hcd *uhci, struct uhci_td *td)
+{
+	if (!list_empty(&td->list))
+		dev_warn(uhci_dev(uhci), "td %p still in list!\n", td);
+	if (!list_empty(&td->remove_list))
+		dev_warn(uhci_dev(uhci), "td %p still in remove_list!\n", td);
+	if (!list_empty(&td->fl_list))
+		dev_warn(uhci_dev(uhci), "td %p still in fl_list!\n", td);
+
+	if (td->dev)
+		usb_put_dev(td->dev);
+
+	dma_pool_free(uhci->td_pool, td, td->dma_handle);
+}
+
+static struct uhci_qh *uhci_alloc_qh(struct uhci_hcd *uhci, struct usb_device *dev)
+{
+	dma_addr_t dma_handle;
+	struct uhci_qh *qh;
+
+	qh = dma_pool_alloc(uhci->qh_pool, GFP_ATOMIC, &dma_handle);
+	if (!qh)
+		return NULL;
+
+	qh->dma_handle = dma_handle;
+
+	qh->element = UHCI_PTR_TERM;
+	qh->link = UHCI_PTR_TERM;
+
+	qh->dev = dev;
+	qh->urbp = NULL;
+
+	INIT_LIST_HEAD(&qh->list);
+	INIT_LIST_HEAD(&qh->remove_list);
+
+	usb_get_dev(dev);
+
+	return qh;
+}
+
+static void uhci_free_qh(struct uhci_hcd *uhci, struct uhci_qh *qh)
+{
+	if (!list_empty(&qh->list))
+		dev_warn(uhci_dev(uhci), "qh %p list not empty!\n", qh);
+	if (!list_empty(&qh->remove_list))
+		dev_warn(uhci_dev(uhci), "qh %p still in remove_list!\n", qh);
+
+	if (qh->dev)
+		usb_put_dev(qh->dev);
+
+	dma_pool_free(uhci->qh_pool, qh, qh->dma_handle);
+}
+
+/*
+ * Append this urb's qh after the last qh in skelqh->list
+ *
+ * Note that urb_priv.queue_list doesn't have a separate queue head;
+ * it's a ring with every element "live".
+ */
+static void uhci_insert_qh(struct uhci_hcd *uhci, struct uhci_qh *skelqh, struct urb *urb)
+{
+	struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
+	struct urb_priv *turbp;
+	struct uhci_qh *lqh;
+
+	/* Grab the last QH */
+	lqh = list_entry(skelqh->list.prev, struct uhci_qh, list);
+
+	/* Point to the next skelqh */
+	urbp->qh->link = lqh->link;
+	wmb();				/* Ordering is important */
+
+	/*
+	 * Patch QHs for previous endpoint's queued URBs?  HC goes
+	 * here next, not to the next skelqh it now points to.
+	 *
+	 *    lqh --> td ... --> qh ... --> td --> qh ... --> td
+	 *     |                 |                 |
+	 *     v                 v                 v
+	 *     +<----------------+-----------------+
+	 *     v
+	 *    newqh --> td ... --> td
+	 *     |
+	 *     v
+	 *    ...
+	 *
+	 * The HC could see (and use!) any of these as we write them.
+	 */
+	lqh->link = cpu_to_le32(urbp->qh->dma_handle) | UHCI_PTR_QH;
+	if (lqh->urbp) {
+		list_for_each_entry(turbp, &lqh->urbp->queue_list, queue_list)
+			turbp->qh->link = lqh->link;
+	}
+
+	list_add_tail(&urbp->qh->list, &skelqh->list);
+}
+
+/*
+ * Start removal of QH from schedule; it finishes next frame.
+ * TDs should be unlinked before this is called.
+ */
+static void uhci_remove_qh(struct uhci_hcd *uhci, struct uhci_qh *qh)
+{
+	struct uhci_qh *pqh;
+	__le32 newlink;
+	unsigned int age;
+
+	if (!qh)
+		return;
+
+	/*
+	 * Only go through the hoops if it's actually linked in
+	 */
+	if (!list_empty(&qh->list)) {
+
+		/* If our queue is nonempty, make the next URB the head */
+		if (!list_empty(&qh->urbp->queue_list)) {
+			struct urb_priv *nurbp;
+
+			nurbp = list_entry(qh->urbp->queue_list.next,
+					struct urb_priv, queue_list);
+			nurbp->queued = 0;
+			list_add(&nurbp->qh->list, &qh->list);
+			newlink = cpu_to_le32(nurbp->qh->dma_handle) | UHCI_PTR_QH;
+		} else
+			newlink = qh->link;
+
+		/* Fix up the previous QH's queue to link to either
+		 * the new head of this queue or the start of the
+		 * next endpoint's queue. */
+		pqh = list_entry(qh->list.prev, struct uhci_qh, list);
+		pqh->link = newlink;
+		if (pqh->urbp) {
+			struct urb_priv *turbp;
+
+			list_for_each_entry(turbp, &pqh->urbp->queue_list,
+					queue_list)
+				turbp->qh->link = newlink;
+		}
+		wmb();
+
+		/* Leave qh->link in case the HC is on the QH now, it will */
+		/* continue the rest of the schedule */
+		qh->element = UHCI_PTR_TERM;
+
+		list_del_init(&qh->list);
+	}
+
+	list_del_init(&qh->urbp->queue_list);
+	qh->urbp = NULL;
+
+	age = uhci_get_current_frame_number(uhci);
+	if (age != uhci->qh_remove_age) {
+		uhci_free_pending_qhs(uhci);
+		uhci->qh_remove_age = age;
+	}
+
+	/* Check to see if the remove list is empty. Set the IOC bit */
+	/* to force an interrupt so we can remove the QH */
+	if (list_empty(&uhci->qh_remove_list))
+		uhci_set_next_interrupt(uhci);
+
+	list_add(&qh->remove_list, &uhci->qh_remove_list);
+}
+
+static int uhci_fixup_toggle(struct urb *urb, unsigned int toggle)
+{
+	struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
+	struct uhci_td *td;
+
+	list_for_each_entry(td, &urbp->td_list, list) {
+		if (toggle)
+			td->token |= cpu_to_le32(TD_TOKEN_TOGGLE);
+		else
+			td->token &= ~cpu_to_le32(TD_TOKEN_TOGGLE);
+
+		toggle ^= 1;
+	}
+
+	return toggle;
+}
+
+/* This function will append one URB's QH to another URB's QH. This is for */
+/* queuing interrupt, control or bulk transfers */
+static void uhci_append_queued_urb(struct uhci_hcd *uhci, struct urb *eurb, struct urb *urb)
+{
+	struct urb_priv *eurbp, *urbp, *furbp, *lurbp;
+	struct uhci_td *lltd;
+
+	eurbp = eurb->hcpriv;
+	urbp = urb->hcpriv;
+
+	/* Find the first URB in the queue */
+	furbp = eurbp;
+	if (eurbp->queued) {
+		list_for_each_entry(furbp, &eurbp->queue_list, queue_list)
+			if (!furbp->queued)
+				break;
+	}
+
+	lurbp = list_entry(furbp->queue_list.prev, struct urb_priv, queue_list);
+
+	lltd = list_entry(lurbp->td_list.prev, struct uhci_td, list);
+
+	/* Control transfers always start with toggle 0 */
+	if (!usb_pipecontrol(urb->pipe))
+		usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe),
+				usb_pipeout(urb->pipe),
+				uhci_fixup_toggle(urb,
+					uhci_toggle(td_token(lltd)) ^ 1));
+
+	/* All qh's in the queue need to link to the next queue */
+	urbp->qh->link = eurbp->qh->link;
+
+	wmb();			/* Make sure we flush everything */
+
+	lltd->link = cpu_to_le32(urbp->qh->dma_handle) | UHCI_PTR_QH;
+
+	list_add_tail(&urbp->queue_list, &furbp->queue_list);
+
+	urbp->queued = 1;
+}
+
+static void uhci_delete_queued_urb(struct uhci_hcd *uhci, struct urb *urb)
+{
+	struct urb_priv *urbp, *nurbp, *purbp, *turbp;
+	struct uhci_td *pltd;
+	unsigned int toggle;
+
+	urbp = urb->hcpriv;
+
+	if (list_empty(&urbp->queue_list))
+		return;
+
+	nurbp = list_entry(urbp->queue_list.next, struct urb_priv, queue_list);
+
+	/*
+	 * Fix up the toggle for the following URBs in the queue.
+	 * Only needed for bulk and interrupt: control and isochronous
+	 * endpoints don't propagate toggles between messages.
+	 */
+	if (usb_pipebulk(urb->pipe) || usb_pipeint(urb->pipe)) {
+		if (!urbp->queued)
+			/* We just set the toggle in uhci_unlink_generic */
+			toggle = usb_gettoggle(urb->dev,
+					usb_pipeendpoint(urb->pipe),
+					usb_pipeout(urb->pipe));
+		else {
+			/* If we're in the middle of the queue, grab the */
+			/* toggle from the TD previous to us */
+			purbp = list_entry(urbp->queue_list.prev,
+					struct urb_priv, queue_list);
+			pltd = list_entry(purbp->td_list.prev,
+					struct uhci_td, list);
+			toggle = uhci_toggle(td_token(pltd)) ^ 1;
+		}
+
+		list_for_each_entry(turbp, &urbp->queue_list, queue_list) {
+			if (!turbp->queued)
+				break;
+			toggle = uhci_fixup_toggle(turbp->urb, toggle);
+		}
+
+		usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe),
+				usb_pipeout(urb->pipe), toggle);
+	}
+
+	if (urbp->queued) {
+		/* We're somewhere in the middle (or end).  The case where
+		 * we're at the head is handled in uhci_remove_qh(). */
+		purbp = list_entry(urbp->queue_list.prev, struct urb_priv,
+				queue_list);
+
+		pltd = list_entry(purbp->td_list.prev, struct uhci_td, list);
+		if (nurbp->queued)
+			pltd->link = cpu_to_le32(nurbp->qh->dma_handle) | UHCI_PTR_QH;
+		else
+			/* The next URB happens to be the beginning, so */
+			/*  we're the last, end the chain */
+			pltd->link = UHCI_PTR_TERM;
+	}
+
+	/* urbp->queue_list is handled in uhci_remove_qh() */
+}
+
+static struct urb_priv *uhci_alloc_urb_priv(struct uhci_hcd *uhci, struct urb *urb)
+{
+	struct urb_priv *urbp;
+
+	urbp = kmem_cache_alloc(uhci_up_cachep, SLAB_ATOMIC);
+	if (!urbp)
+		return NULL;
+
+	memset((void *)urbp, 0, sizeof(*urbp));
+
+	urbp->inserttime = jiffies;
+	urbp->fsbrtime = jiffies;
+	urbp->urb = urb;
+	
+	INIT_LIST_HEAD(&urbp->td_list);
+	INIT_LIST_HEAD(&urbp->queue_list);
+	INIT_LIST_HEAD(&urbp->urb_list);
+
+	list_add_tail(&urbp->urb_list, &uhci->urb_list);
+
+	urb->hcpriv = urbp;
+
+	return urbp;
+}
+
+static void uhci_add_td_to_urb(struct urb *urb, struct uhci_td *td)
+{
+	struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
+
+	td->urb = urb;
+
+	list_add_tail(&td->list, &urbp->td_list);
+}
+
+static void uhci_remove_td_from_urb(struct uhci_td *td)
+{
+	if (list_empty(&td->list))
+		return;
+
+	list_del_init(&td->list);
+
+	td->urb = NULL;
+}
+
+static void uhci_destroy_urb_priv(struct uhci_hcd *uhci, struct urb *urb)
+{
+	struct uhci_td *td, *tmp;
+	struct urb_priv *urbp;
+	unsigned int age;
+
+	urbp = (struct urb_priv *)urb->hcpriv;
+	if (!urbp)
+		return;
+
+	if (!list_empty(&urbp->urb_list))
+		dev_warn(uhci_dev(uhci), "urb %p still on uhci->urb_list "
+				"or uhci->remove_list!\n", urb);
+
+	age = uhci_get_current_frame_number(uhci);
+	if (age != uhci->td_remove_age) {
+		uhci_free_pending_tds(uhci);
+		uhci->td_remove_age = age;
+	}
+
+	/* Check to see if the remove list is empty. Set the IOC bit */
+	/* to force an interrupt so we can remove the TD's*/
+	if (list_empty(&uhci->td_remove_list))
+		uhci_set_next_interrupt(uhci);
+
+	list_for_each_entry_safe(td, tmp, &urbp->td_list, list) {
+		uhci_remove_td_from_urb(td);
+		uhci_remove_td(uhci, td);
+		list_add(&td->remove_list, &uhci->td_remove_list);
+	}
+
+	urb->hcpriv = NULL;
+	kmem_cache_free(uhci_up_cachep, urbp);
+}
+
+static void uhci_inc_fsbr(struct uhci_hcd *uhci, struct urb *urb)
+{
+	struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
+
+	if ((!(urb->transfer_flags & URB_NO_FSBR)) && !urbp->fsbr) {
+		urbp->fsbr = 1;
+		if (!uhci->fsbr++ && !uhci->fsbrtimeout)
+			uhci->skel_term_qh->link = cpu_to_le32(uhci->skel_fs_control_qh->dma_handle) | UHCI_PTR_QH;
+	}
+}
+
+static void uhci_dec_fsbr(struct uhci_hcd *uhci, struct urb *urb)
+{
+	struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
+
+	if ((!(urb->transfer_flags & URB_NO_FSBR)) && urbp->fsbr) {
+		urbp->fsbr = 0;
+		if (!--uhci->fsbr)
+			uhci->fsbrtimeout = jiffies + FSBR_DELAY;
+	}
+}
+
+/*
+ * Map status to standard result codes
+ *
+ * <status> is (td_status(td) & 0xF60000), a.k.a.
+ * uhci_status_bits(td_status(td)).
+ * Note: <status> does not include the TD_CTRL_NAK bit.
+ * <dir_out> is True for output TDs and False for input TDs.
+ */
+static int uhci_map_status(int status, int dir_out)
+{
+	if (!status)
+		return 0;
+	if (status & TD_CTRL_BITSTUFF)			/* Bitstuff error */
+		return -EPROTO;
+	if (status & TD_CTRL_CRCTIMEO) {		/* CRC/Timeout */
+		if (dir_out)
+			return -EPROTO;
+		else
+			return -EILSEQ;
+	}
+	if (status & TD_CTRL_BABBLE)			/* Babble */
+		return -EOVERFLOW;
+	if (status & TD_CTRL_DBUFERR)			/* Buffer error */
+		return -ENOSR;
+	if (status & TD_CTRL_STALLED)			/* Stalled */
+		return -EPIPE;
+	WARN_ON(status & TD_CTRL_ACTIVE);		/* Active */
+	return 0;
+}
+
+/*
+ * Control transfers
+ */
+static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb, struct urb *eurb)
+{
+	struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
+	struct uhci_td *td;
+	struct uhci_qh *qh, *skelqh;
+	unsigned long destination, status;
+	int maxsze = usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe));
+	int len = urb->transfer_buffer_length;
+	dma_addr_t data = urb->transfer_dma;
+
+	/* The "pipe" thing contains the destination in bits 8--18 */
+	destination = (urb->pipe & PIPE_DEVEP_MASK) | USB_PID_SETUP;
+
+	/* 3 errors */
+	status = TD_CTRL_ACTIVE | uhci_maxerr(3);
+	if (urb->dev->speed == USB_SPEED_LOW)
+		status |= TD_CTRL_LS;
+
+	/*
+	 * Build the TD for the control request setup packet
+	 */
+	td = uhci_alloc_td(uhci, urb->dev);
+	if (!td)
+		return -ENOMEM;
+
+	uhci_add_td_to_urb(urb, td);
+	uhci_fill_td(td, status, destination | uhci_explen(7),
+		urb->setup_dma);
+
+	/*
+	 * If direction is "send", change the packet ID from SETUP (0x2D)
+	 * to OUT (0xE1).  Else change it from SETUP to IN (0x69) and
+	 * set Short Packet Detect (SPD) for all data packets.
+	 */
+	if (usb_pipeout(urb->pipe))
+		destination ^= (USB_PID_SETUP ^ USB_PID_OUT);
+	else {
+		destination ^= (USB_PID_SETUP ^ USB_PID_IN);
+		status |= TD_CTRL_SPD;
+	}
+
+	/*
+	 * Build the DATA TD's
+	 */
+	while (len > 0) {
+		int pktsze = len;
+
+		if (pktsze > maxsze)
+			pktsze = maxsze;
+
+		td = uhci_alloc_td(uhci, urb->dev);
+		if (!td)
+			return -ENOMEM;
+
+		/* Alternate Data0/1 (start with Data1) */
+		destination ^= TD_TOKEN_TOGGLE;
+	
+		uhci_add_td_to_urb(urb, td);
+		uhci_fill_td(td, status, destination | uhci_explen(pktsze - 1),
+			data);
+
+		data += pktsze;
+		len -= pktsze;
+	}
+
+	/*
+	 * Build the final TD for control status 
+	 */
+	td = uhci_alloc_td(uhci, urb->dev);
+	if (!td)
+		return -ENOMEM;
+
+	/*
+	 * It's IN if the pipe is an output pipe or we're not expecting
+	 * data back.
+	 */
+	destination &= ~TD_TOKEN_PID_MASK;
+	if (usb_pipeout(urb->pipe) || !urb->transfer_buffer_length)
+		destination |= USB_PID_IN;
+	else
+		destination |= USB_PID_OUT;
+
+	destination |= TD_TOKEN_TOGGLE;		/* End in Data1 */
+
+	status &= ~TD_CTRL_SPD;
+
+	uhci_add_td_to_urb(urb, td);
+	uhci_fill_td(td, status | TD_CTRL_IOC,
+		destination | uhci_explen(UHCI_NULL_DATA_SIZE), 0);
+
+	qh = uhci_alloc_qh(uhci, urb->dev);
+	if (!qh)
+		return -ENOMEM;
+
+	urbp->qh = qh;
+	qh->urbp = urbp;
+
+	uhci_insert_tds_in_qh(qh, urb, UHCI_PTR_BREADTH);
+
+	/* Low-speed transfers get a different queue, and won't hog the bus.
+	 * Also, some devices enumerate better without FSBR; the easiest way
+	 * to do that is to put URBs on the low-speed queue while the device
+	 * is in the DEFAULT state. */
+	if (urb->dev->speed == USB_SPEED_LOW ||
+			urb->dev->state == USB_STATE_DEFAULT)
+		skelqh = uhci->skel_ls_control_qh;
+	else {
+		skelqh = uhci->skel_fs_control_qh;
+		uhci_inc_fsbr(uhci, urb);
+	}
+
+	if (eurb)
+		uhci_append_queued_urb(uhci, eurb, urb);
+	else
+		uhci_insert_qh(uhci, skelqh, urb);
+
+	return -EINPROGRESS;
+}
+
+/*
+ * If control-IN transfer was short, the status packet wasn't sent.
+ * This routine changes the element pointer in the QH to point at the
+ * status TD.  It's safe to do this even while the QH is live, because
+ * the hardware only updates the element pointer following a successful
+ * transfer.  The inactive TD for the short packet won't cause an update,
+ * so the pointer won't get overwritten.  The next time the controller
+ * sees this QH, it will send the status packet.
+ */
+static int usb_control_retrigger_status(struct uhci_hcd *uhci, struct urb *urb)
+{
+	struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
+	struct uhci_td *td;
+
+	urbp->short_control_packet = 1;
+
+	td = list_entry(urbp->td_list.prev, struct uhci_td, list);
+	urbp->qh->element = cpu_to_le32(td->dma_handle);
+
+	return -EINPROGRESS;
+}
+
+
+static int uhci_result_control(struct uhci_hcd *uhci, struct urb *urb)
+{
+	struct list_head *tmp, *head;
+	struct urb_priv *urbp = urb->hcpriv;
+	struct uhci_td *td;
+	unsigned int status;
+	int ret = 0;
+
+	if (list_empty(&urbp->td_list))
+		return -EINVAL;
+
+	head = &urbp->td_list;
+
+	if (urbp->short_control_packet) {
+		tmp = head->prev;
+		goto status_stage;
+	}
+
+	tmp = head->next;
+	td = list_entry(tmp, struct uhci_td, list);
+
+	/* The first TD is the SETUP stage, check the status, but skip */
+	/*  the count */
+	status = uhci_status_bits(td_status(td));
+	if (status & TD_CTRL_ACTIVE)
+		return -EINPROGRESS;
+
+	if (status)
+		goto td_error;
+
+	urb->actual_length = 0;
+
+	/* The rest of the TD's (but the last) are data */
+	tmp = tmp->next;
+	while (tmp != head && tmp->next != head) {
+		unsigned int ctrlstat;
+
+		td = list_entry(tmp, struct uhci_td, list);
+		tmp = tmp->next;
+
+		ctrlstat = td_status(td);
+		status = uhci_status_bits(ctrlstat);
+		if (status & TD_CTRL_ACTIVE)
+			return -EINPROGRESS;
+
+		urb->actual_length += uhci_actual_length(ctrlstat);
+
+		if (status)
+			goto td_error;
+
+		/* Check to see if we received a short packet */
+		if (uhci_actual_length(ctrlstat) <
+				uhci_expected_length(td_token(td))) {
+			if (urb->transfer_flags & URB_SHORT_NOT_OK) {
+				ret = -EREMOTEIO;
+				goto err;
+			}
+
+			if (uhci_packetid(td_token(td)) == USB_PID_IN)
+				return usb_control_retrigger_status(uhci, urb);
+			else
+				return 0;
+		}
+	}
+
+status_stage:
+	td = list_entry(tmp, struct uhci_td, list);
+
+	/* Control status stage */
+	status = td_status(td);
+
+#ifdef I_HAVE_BUGGY_APC_BACKUPS
+	/* APC BackUPS Pro kludge */
+	/* It tries to send all of the descriptor instead of the amount */
+	/*  we requested */
+	if (status & TD_CTRL_IOC &&	/* IOC is masked out by uhci_status_bits */
+	    status & TD_CTRL_ACTIVE &&
+	    status & TD_CTRL_NAK)
+		return 0;
+#endif
+
+	status = uhci_status_bits(status);
+	if (status & TD_CTRL_ACTIVE)
+		return -EINPROGRESS;
+
+	if (status)
+		goto td_error;
+
+	return 0;
+
+td_error:
+	ret = uhci_map_status(status, uhci_packetout(td_token(td)));
+
+err:
+	if ((debug == 1 && ret != -EPIPE) || debug > 1) {
+		/* Some debugging code */
+		dev_dbg(uhci_dev(uhci), "%s: failed with status %x\n",
+				__FUNCTION__, status);
+
+		if (errbuf) {
+			/* Print the chain for debugging purposes */
+			uhci_show_qh(urbp->qh, errbuf, ERRBUF_LEN, 0);
+
+			lprintk(errbuf);
+		}
+	}
+
+	return ret;
+}
+
+/*
+ * Common submit for bulk and interrupt
+ */
+static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb, struct urb *eurb, struct uhci_qh *skelqh)
+{
+	struct uhci_td *td;
+	struct uhci_qh *qh;
+	unsigned long destination, status;
+	int maxsze = usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe));
+	int len = urb->transfer_buffer_length;
+	struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
+	dma_addr_t data = urb->transfer_dma;
+
+	if (len < 0)
+		return -EINVAL;
+
+	/* The "pipe" thing contains the destination in bits 8--18 */
+	destination = (urb->pipe & PIPE_DEVEP_MASK) | usb_packetid(urb->pipe);
+
+	status = uhci_maxerr(3) | TD_CTRL_ACTIVE;
+	if (urb->dev->speed == USB_SPEED_LOW)
+		status |= TD_CTRL_LS;
+	if (usb_pipein(urb->pipe))
+		status |= TD_CTRL_SPD;
+
+	/*
+	 * Build the DATA TD's
+	 */
+	do {	/* Allow zero length packets */
+		int pktsze = maxsze;
+
+		if (pktsze >= len) {
+			pktsze = len;
+			if (!(urb->transfer_flags & URB_SHORT_NOT_OK))
+				status &= ~TD_CTRL_SPD;
+		}
+
+		td = uhci_alloc_td(uhci, urb->dev);
+		if (!td)
+			return -ENOMEM;
+
+		uhci_add_td_to_urb(urb, td);
+		uhci_fill_td(td, status, destination | uhci_explen(pktsze - 1) |
+			(usb_gettoggle(urb->dev, usb_pipeendpoint(urb->pipe),
+			 usb_pipeout(urb->pipe)) << TD_TOKEN_TOGGLE_SHIFT),
+			data);
+
+		data += pktsze;
+		len -= maxsze;
+
+		usb_dotoggle(urb->dev, usb_pipeendpoint(urb->pipe),
+			usb_pipeout(urb->pipe));
+	} while (len > 0);
+
+	/*
+	 * URB_ZERO_PACKET means adding a 0-length packet, if direction
+	 * is OUT and the transfer_length was an exact multiple of maxsze,
+	 * hence (len = transfer_length - N * maxsze) == 0
+	 * however, if transfer_length == 0, the zero packet was already
+	 * prepared above.
+	 */
+	if (usb_pipeout(urb->pipe) && (urb->transfer_flags & URB_ZERO_PACKET) &&
+	    !len && urb->transfer_buffer_length) {
+		td = uhci_alloc_td(uhci, urb->dev);
+		if (!td)
+			return -ENOMEM;
+
+		uhci_add_td_to_urb(urb, td);
+		uhci_fill_td(td, status, destination | uhci_explen(UHCI_NULL_DATA_SIZE) |
+			(usb_gettoggle(urb->dev, usb_pipeendpoint(urb->pipe),
+			 usb_pipeout(urb->pipe)) << TD_TOKEN_TOGGLE_SHIFT),
+			data);
+
+		usb_dotoggle(urb->dev, usb_pipeendpoint(urb->pipe),
+			usb_pipeout(urb->pipe));
+	}
+
+	/* Set the interrupt-on-completion flag on the last packet.
+	 * A more-or-less typical 4 KB URB (= size of one memory page)
+	 * will require about 3 ms to transfer; that's a little on the
+	 * fast side but not enough to justify delaying an interrupt
+	 * more than 2 or 3 URBs, so we will ignore the URB_NO_INTERRUPT
+	 * flag setting. */
+	td->status |= cpu_to_le32(TD_CTRL_IOC);
+
+	qh = uhci_alloc_qh(uhci, urb->dev);
+	if (!qh)
+		return -ENOMEM;
+
+	urbp->qh = qh;
+	qh->urbp = urbp;
+
+	/* Always breadth first */
+	uhci_insert_tds_in_qh(qh, urb, UHCI_PTR_BREADTH);
+
+	if (eurb)
+		uhci_append_queued_urb(uhci, eurb, urb);
+	else
+		uhci_insert_qh(uhci, skelqh, urb);
+
+	return -EINPROGRESS;
+}
+
+/*
+ * Common result for bulk and interrupt
+ */
+static int uhci_result_common(struct uhci_hcd *uhci, struct urb *urb)
+{
+	struct urb_priv *urbp = urb->hcpriv;
+	struct uhci_td *td;
+	unsigned int status = 0;
+	int ret = 0;
+
+	urb->actual_length = 0;
+
+	list_for_each_entry(td, &urbp->td_list, list) {
+		unsigned int ctrlstat = td_status(td);
+
+		status = uhci_status_bits(ctrlstat);
+		if (status & TD_CTRL_ACTIVE)
+			return -EINPROGRESS;
+
+		urb->actual_length += uhci_actual_length(ctrlstat);
+
+		if (status)
+			goto td_error;
+
+		if (uhci_actual_length(ctrlstat) <
+				uhci_expected_length(td_token(td))) {
+			if (urb->transfer_flags & URB_SHORT_NOT_OK) {
+				ret = -EREMOTEIO;
+				goto err;
+			} else
+				return 0;
+		}
+	}
+
+	return 0;
+
+td_error:
+	ret = uhci_map_status(status, uhci_packetout(td_token(td)));
+
+err:
+	/* 
+	 * Enable this chunk of code if you want to see some more debugging.
+	 * But be careful, it has the tendancy to starve out khubd and prevent
+	 * disconnects from happening successfully if you have a slow debug
+	 * log interface (like a serial console.
+	 */
+#if 0
+	if ((debug == 1 && ret != -EPIPE) || debug > 1) {
+		/* Some debugging code */
+		dev_dbg(uhci_dev(uhci), "%s: failed with status %x\n",
+				__FUNCTION__, status);
+
+		if (errbuf) {
+			/* Print the chain for debugging purposes */
+			uhci_show_qh(urbp->qh, errbuf, ERRBUF_LEN, 0);
+
+			lprintk(errbuf);
+		}
+	}
+#endif
+	return ret;
+}
+
+static inline int uhci_submit_bulk(struct uhci_hcd *uhci, struct urb *urb, struct urb *eurb)
+{
+	int ret;
+
+	/* Can't have low-speed bulk transfers */
+	if (urb->dev->speed == USB_SPEED_LOW)
+		return -EINVAL;
+
+	ret = uhci_submit_common(uhci, urb, eurb, uhci->skel_bulk_qh);
+	if (ret == -EINPROGRESS)
+		uhci_inc_fsbr(uhci, urb);
+
+	return ret;
+}
+
+static inline int uhci_submit_interrupt(struct uhci_hcd *uhci, struct urb *urb, struct urb *eurb)
+{
+	/* USB 1.1 interrupt transfers only involve one packet per interval;
+	 * that's the uhci_submit_common() "breadth first" policy.  Drivers
+	 * can submit urbs of any length, but longer ones might need many
+	 * intervals to complete.
+	 */
+	return uhci_submit_common(uhci, urb, eurb, uhci->skelqh[__interval_to_skel(urb->interval)]);
+}
+
+/*
+ * Isochronous transfers
+ */
+static int isochronous_find_limits(struct uhci_hcd *uhci, struct urb *urb, unsigned int *start, unsigned int *end)
+{
+	struct urb *last_urb = NULL;
+	struct urb_priv *up;
+	int ret = 0;
+
+	list_for_each_entry(up, &uhci->urb_list, urb_list) {
+		struct urb *u = up->urb;
+
+		/* look for pending URB's with identical pipe handle */
+		if ((urb->pipe == u->pipe) && (urb->dev == u->dev) &&
+		    (u->status == -EINPROGRESS) && (u != urb)) {
+			if (!last_urb)
+				*start = u->start_frame;
+			last_urb = u;
+		}
+	}
+
+	if (last_urb) {
+		*end = (last_urb->start_frame + last_urb->number_of_packets *
+				last_urb->interval) & (UHCI_NUMFRAMES-1);
+		ret = 0;
+	} else
+		ret = -1;	/* no previous urb found */
+
+	return ret;
+}
+
+static int isochronous_find_start(struct uhci_hcd *uhci, struct urb *urb)
+{
+	int limits;
+	unsigned int start = 0, end = 0;
+
+	if (urb->number_of_packets > 900)	/* 900? Why? */
+		return -EFBIG;
+
+	limits = isochronous_find_limits(uhci, urb, &start, &end);
+
+	if (urb->transfer_flags & URB_ISO_ASAP) {
+		if (limits)
+			urb->start_frame =
+					(uhci_get_current_frame_number(uhci) +
+						10) & (UHCI_NUMFRAMES - 1);
+		else
+			urb->start_frame = end;
+	} else {
+		urb->start_frame &= (UHCI_NUMFRAMES - 1);
+		/* FIXME: Sanity check */
+	}
+
+	return 0;
+}
+
+/*
+ * Isochronous transfers
+ */
+static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb)
+{
+	struct uhci_td *td;
+	int i, ret, frame;
+	int status, destination;
+
+	status = TD_CTRL_ACTIVE | TD_CTRL_IOS;
+	destination = (urb->pipe & PIPE_DEVEP_MASK) | usb_packetid(urb->pipe);
+
+	ret = isochronous_find_start(uhci, urb);
+	if (ret)
+		return ret;
+
+	frame = urb->start_frame;
+	for (i = 0; i < urb->number_of_packets; i++, frame += urb->interval) {
+		if (!urb->iso_frame_desc[i].length)
+			continue;
+
+		td = uhci_alloc_td(uhci, urb->dev);
+		if (!td)
+			return -ENOMEM;
+
+		uhci_add_td_to_urb(urb, td);
+		uhci_fill_td(td, status, destination | uhci_explen(urb->iso_frame_desc[i].length - 1),
+			urb->transfer_dma + urb->iso_frame_desc[i].offset);
+
+		if (i + 1 >= urb->number_of_packets)
+			td->status |= cpu_to_le32(TD_CTRL_IOC);
+
+		uhci_insert_td_frame_list(uhci, td, frame);
+	}
+
+	return -EINPROGRESS;
+}
+
+static int uhci_result_isochronous(struct uhci_hcd *uhci, struct urb *urb)
+{
+	struct uhci_td *td;
+	struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
+	int status;
+	int i, ret = 0;
+
+	urb->actual_length = 0;
+
+	i = 0;
+	list_for_each_entry(td, &urbp->td_list, list) {
+		int actlength;
+		unsigned int ctrlstat = td_status(td);
+
+		if (ctrlstat & TD_CTRL_ACTIVE)
+			return -EINPROGRESS;
+
+		actlength = uhci_actual_length(ctrlstat);
+		urb->iso_frame_desc[i].actual_length = actlength;
+		urb->actual_length += actlength;
+
+		status = uhci_map_status(uhci_status_bits(ctrlstat),
+				usb_pipeout(urb->pipe));
+		urb->iso_frame_desc[i].status = status;
+		if (status) {
+			urb->error_count++;
+			ret = status;
+		}
+
+		i++;
+	}
+
+	return ret;
+}
+
+static struct urb *uhci_find_urb_ep(struct uhci_hcd *uhci, struct urb *urb)
+{
+	struct urb_priv *up;
+
+	/* We don't match Isoc transfers since they are special */
+	if (usb_pipeisoc(urb->pipe))
+		return NULL;
+
+	list_for_each_entry(up, &uhci->urb_list, urb_list) {
+		struct urb *u = up->urb;
+
+		if (u->dev == urb->dev && u->status == -EINPROGRESS) {
+			/* For control, ignore the direction */
+			if (usb_pipecontrol(urb->pipe) &&
+			    (u->pipe & ~USB_DIR_IN) == (urb->pipe & ~USB_DIR_IN))
+				return u;
+			else if (u->pipe == urb->pipe)
+				return u;
+		}
+	}
+
+	return NULL;
+}
+
+static int uhci_urb_enqueue(struct usb_hcd *hcd,
+		struct usb_host_endpoint *ep,
+		struct urb *urb, int mem_flags)
+{
+	int ret;
+	struct uhci_hcd *uhci = hcd_to_uhci(hcd);
+	unsigned long flags;
+	struct urb *eurb;
+	int bustime;
+
+	spin_lock_irqsave(&uhci->schedule_lock, flags);
+
+	ret = urb->status;
+	if (ret != -EINPROGRESS)		/* URB already unlinked! */
+		goto out;
+
+	eurb = uhci_find_urb_ep(uhci, urb);
+
+	if (!uhci_alloc_urb_priv(uhci, urb)) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	switch (usb_pipetype(urb->pipe)) {
+	case PIPE_CONTROL:
+		ret = uhci_submit_control(uhci, urb, eurb);
+		break;
+	case PIPE_INTERRUPT:
+		if (!eurb) {
+			bustime = usb_check_bandwidth(urb->dev, urb);
+			if (bustime < 0)
+				ret = bustime;
+			else {
+				ret = uhci_submit_interrupt(uhci, urb, eurb);
+				if (ret == -EINPROGRESS)
+					usb_claim_bandwidth(urb->dev, urb, bustime, 0);
+			}
+		} else {	/* inherit from parent */
+			urb->bandwidth = eurb->bandwidth;
+			ret = uhci_submit_interrupt(uhci, urb, eurb);
+		}
+		break;
+	case PIPE_BULK:
+		ret = uhci_submit_bulk(uhci, urb, eurb);
+		break;
+	case PIPE_ISOCHRONOUS:
+		bustime = usb_check_bandwidth(urb->dev, urb);
+		if (bustime < 0) {
+			ret = bustime;
+			break;
+		}
+
+		ret = uhci_submit_isochronous(uhci, urb);
+		if (ret == -EINPROGRESS)
+			usb_claim_bandwidth(urb->dev, urb, bustime, 1);
+		break;
+	}
+
+	if (ret != -EINPROGRESS) {
+		/* Submit failed, so delete it from the urb_list */
+		struct urb_priv *urbp = urb->hcpriv;
+
+		list_del_init(&urbp->urb_list);
+		uhci_destroy_urb_priv(uhci, urb);
+	} else
+		ret = 0;
+
+out:
+	spin_unlock_irqrestore(&uhci->schedule_lock, flags);
+	return ret;
+}
+
+/*
+ * Return the result of a transfer
+ */
+static void uhci_transfer_result(struct uhci_hcd *uhci, struct urb *urb)
+{
+	int ret = -EINPROGRESS;
+	struct urb_priv *urbp;
+
+	spin_lock(&urb->lock);
+
+	urbp = (struct urb_priv *)urb->hcpriv;
+
+	if (urb->status != -EINPROGRESS)	/* URB already dequeued */
+		goto out;
+
+	switch (usb_pipetype(urb->pipe)) {
+	case PIPE_CONTROL:
+		ret = uhci_result_control(uhci, urb);
+		break;
+	case PIPE_BULK:
+	case PIPE_INTERRUPT:
+		ret = uhci_result_common(uhci, urb);
+		break;
+	case PIPE_ISOCHRONOUS:
+		ret = uhci_result_isochronous(uhci, urb);
+		break;
+	}
+
+	if (ret == -EINPROGRESS)
+		goto out;
+	urb->status = ret;
+
+	switch (usb_pipetype(urb->pipe)) {
+	case PIPE_CONTROL:
+	case PIPE_BULK:
+	case PIPE_ISOCHRONOUS:
+		/* Release bandwidth for Interrupt or Isoc. transfers */
+		if (urb->bandwidth)
+			usb_release_bandwidth(urb->dev, urb, 1);
+		uhci_unlink_generic(uhci, urb);
+		break;
+	case PIPE_INTERRUPT:
+		/* Release bandwidth for Interrupt or Isoc. transfers */
+		/* Make sure we don't release if we have a queued URB */
+		if (list_empty(&urbp->queue_list) && urb->bandwidth)
+			usb_release_bandwidth(urb->dev, urb, 0);
+		else
+			/* bandwidth was passed on to queued URB, */
+			/* so don't let usb_unlink_urb() release it */
+			urb->bandwidth = 0;
+		uhci_unlink_generic(uhci, urb);
+		break;
+	default:
+		dev_info(uhci_dev(uhci), "%s: unknown pipe type %d "
+				"for urb %p\n",
+				__FUNCTION__, usb_pipetype(urb->pipe), urb);
+	}
+
+	/* Move it from uhci->urb_list to uhci->complete_list */
+	uhci_moveto_complete(uhci, urbp);
+
+out:
+	spin_unlock(&urb->lock);
+}
+
+static void uhci_unlink_generic(struct uhci_hcd *uhci, struct urb *urb)
+{
+	struct list_head *head;
+	struct uhci_td *td;
+	struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
+	int prevactive = 0;
+
+	uhci_dec_fsbr(uhci, urb);	/* Safe since it checks */
+
+	/*
+	 * Now we need to find out what the last successful toggle was
+	 * so we can update the local data toggle for the next transfer
+	 *
+	 * There are 2 ways the last successful completed TD is found:
+	 *
+	 * 1) The TD is NOT active and the actual length < expected length
+	 * 2) The TD is NOT active and it's the last TD in the chain
+	 *
+	 * and a third way the first uncompleted TD is found:
+	 *
+	 * 3) The TD is active and the previous TD is NOT active
+	 *
+	 * Control and Isochronous ignore the toggle, so this is safe
+	 * for all types
+	 *
+	 * FIXME: The toggle fixups won't be 100% reliable until we
+	 * change over to using a single queue for each endpoint and
+	 * stop the queue before unlinking.
+	 */
+	head = &urbp->td_list;
+	list_for_each_entry(td, head, list) {
+		unsigned int ctrlstat = td_status(td);
+
+		if (!(ctrlstat & TD_CTRL_ACTIVE) &&
+				(uhci_actual_length(ctrlstat) <
+				 uhci_expected_length(td_token(td)) ||
+				td->list.next == head))
+			usb_settoggle(urb->dev, uhci_endpoint(td_token(td)),
+				uhci_packetout(td_token(td)),
+				uhci_toggle(td_token(td)) ^ 1);
+		else if ((ctrlstat & TD_CTRL_ACTIVE) && !prevactive)
+			usb_settoggle(urb->dev, uhci_endpoint(td_token(td)),
+				uhci_packetout(td_token(td)),
+				uhci_toggle(td_token(td)));
+
+		prevactive = ctrlstat & TD_CTRL_ACTIVE;
+	}
+
+	uhci_delete_queued_urb(uhci, urb);
+
+	/* The interrupt loop will reclaim the QH's */
+	uhci_remove_qh(uhci, urbp->qh);
+	urbp->qh = NULL;
+}
+
+static int uhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb)
+{
+	struct uhci_hcd *uhci = hcd_to_uhci(hcd);
+	unsigned long flags;
+	struct urb_priv *urbp;
+	unsigned int age;
+
+	spin_lock_irqsave(&uhci->schedule_lock, flags);
+	urbp = urb->hcpriv;
+	if (!urbp)			/* URB was never linked! */
+		goto done;
+	list_del_init(&urbp->urb_list);
+
+	uhci_unlink_generic(uhci, urb);
+
+	age = uhci_get_current_frame_number(uhci);
+	if (age != uhci->urb_remove_age) {
+		uhci_remove_pending_urbps(uhci);
+		uhci->urb_remove_age = age;
+	}
+
+	/* If we're the first, set the next interrupt bit */
+	if (list_empty(&uhci->urb_remove_list))
+		uhci_set_next_interrupt(uhci);
+	list_add_tail(&urbp->urb_list, &uhci->urb_remove_list);
+
+done:
+	spin_unlock_irqrestore(&uhci->schedule_lock, flags);
+	return 0;
+}
+
+static int uhci_fsbr_timeout(struct uhci_hcd *uhci, struct urb *urb)
+{
+	struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
+	struct list_head *head;
+	struct uhci_td *td;
+	int count = 0;
+
+	uhci_dec_fsbr(uhci, urb);
+
+	urbp->fsbr_timeout = 1;
+
+	/*
+	 * Ideally we would want to fix qh->element as well, but it's
+	 * read/write by the HC, so that can introduce a race. It's not
+	 * really worth the hassle
+	 */
+
+	head = &urbp->td_list;
+	list_for_each_entry(td, head, list) {
+		/*
+		 * Make sure we don't do the last one (since it'll have the
+		 * TERM bit set) as well as we skip every so many TD's to
+		 * make sure it doesn't hog the bandwidth
+		 */
+		if (td->list.next != head && (count % DEPTH_INTERVAL) ==
+				(DEPTH_INTERVAL - 1))
+			td->link |= UHCI_PTR_DEPTH;
+
+		count++;
+	}
+
+	return 0;
+}
+
+static void uhci_free_pending_qhs(struct uhci_hcd *uhci)
+{
+	struct uhci_qh *qh, *tmp;
+
+	list_for_each_entry_safe(qh, tmp, &uhci->qh_remove_list, remove_list) {
+		list_del_init(&qh->remove_list);
+
+		uhci_free_qh(uhci, qh);
+	}
+}
+
+static void uhci_free_pending_tds(struct uhci_hcd *uhci)
+{
+	struct uhci_td *td, *tmp;
+
+	list_for_each_entry_safe(td, tmp, &uhci->td_remove_list, remove_list) {
+		list_del_init(&td->remove_list);
+
+		uhci_free_td(uhci, td);
+	}
+}
+
+static void
+uhci_finish_urb(struct usb_hcd *hcd, struct urb *urb, struct pt_regs *regs)
+__releases(uhci->schedule_lock)
+__acquires(uhci->schedule_lock)
+{
+	struct uhci_hcd *uhci = hcd_to_uhci(hcd);
+
+	uhci_destroy_urb_priv(uhci, urb);
+
+	spin_unlock(&uhci->schedule_lock);
+	usb_hcd_giveback_urb(hcd, urb, regs);
+	spin_lock(&uhci->schedule_lock);
+}
+
+static void uhci_finish_completion(struct usb_hcd *hcd, struct pt_regs *regs)
+{
+	struct uhci_hcd *uhci = hcd_to_uhci(hcd);
+	struct urb_priv *urbp, *tmp;
+
+	list_for_each_entry_safe(urbp, tmp, &uhci->complete_list, urb_list) {
+		struct urb *urb = urbp->urb;
+
+		list_del_init(&urbp->urb_list);
+		uhci_finish_urb(hcd, urb, regs);
+	}
+}
+
+static void uhci_remove_pending_urbps(struct uhci_hcd *uhci)
+{
+
+	/* Splice the urb_remove_list onto the end of the complete_list */
+	list_splice_init(&uhci->urb_remove_list, uhci->complete_list.prev);
+}
diff -Nru a/drivers/usb/image/mdc800.c b/drivers/usb/image/mdc800.c
--- a/drivers/usb/image/mdc800.c	2005-03-11 12:51:46 -08:00
+++ b/drivers/usb/image/mdc800.c	2005-03-11 12:51:46 -08:00
@@ -95,6 +95,7 @@
 #include <linux/slab.h>
 #include <linux/module.h>
 #include <linux/smp_lock.h>
+#include <linux/wait.h>
 
 #include <linux/usb.h>
 #include <linux/fs.h>
@@ -330,7 +331,7 @@
 	{
 		mdc800->camera_request_ready=0;
 		mdc800->irq_woken=1;
-		wake_up_interruptible (&mdc800->irq_wait);
+		wake_up (&mdc800->irq_wait);
 	}
 }
 
@@ -346,19 +347,9 @@
  */
 static int mdc800_usb_waitForIRQ (int mode, int msec)
 {
-        DECLARE_WAITQUEUE(wait, current);
-	long timeout;
-
 	mdc800->camera_request_ready=1+mode;
 
-	add_wait_queue(&mdc800->irq_wait, &wait);
-	timeout = msec*HZ/1000;
-	while (!mdc800->irq_woken && timeout)
-	{
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		timeout = schedule_timeout (timeout);
-	}
-        remove_wait_queue(&mdc800->irq_wait, &wait);
+	wait_event_timeout(mdc800->irq_wait, mdc800->irq_woken, msec*HZ/1000);
 	mdc800->irq_woken = 0;
 
 	if (mdc800->camera_request_ready>0)
@@ -395,7 +386,7 @@
 		mdc800->state=READY;
 	}
 	mdc800->written = 1;
-	wake_up_interruptible (&mdc800->write_wait);
+	wake_up (&mdc800->write_wait);
 }
 
 
@@ -423,7 +414,7 @@
 		err ("request bytes fails (status:%i)", urb->status);
 	}
 	mdc800->downloaded = 1;
-	wake_up_interruptible (&mdc800->download_wait);
+	wake_up (&mdc800->download_wait);
 }
 
 
@@ -704,8 +695,6 @@
 {
 	size_t left=len, sts=len; /* single transfer size */
 	char __user *ptr = buf;
-	long timeout;
-	DECLARE_WAITQUEUE(wait, current);
 
 	down (&mdc800->io_lock);
 	if (mdc800->state == NOT_CONNECTED)
@@ -751,14 +740,8 @@
 					up (&mdc800->io_lock);
 					return len-left;
 				}
-				add_wait_queue(&mdc800->download_wait, &wait);
-				timeout = TO_DOWNLOAD_GET_READY*HZ/1000;
-				while (!mdc800->downloaded && timeout)
-				{
-					set_current_state(TASK_UNINTERRUPTIBLE);
-					timeout = schedule_timeout (timeout);
-				}
-				remove_wait_queue(&mdc800->download_wait, &wait);
+				wait_event_timeout(mdc800->download_wait, mdc800->downloaded,
+										TO_DOWNLOAD_GET_READY*HZ/1000);
 				mdc800->downloaded = 0;
 				if (mdc800->download_urb->status != 0)
 				{
@@ -802,7 +785,6 @@
 static ssize_t mdc800_device_write (struct file *file, const char __user *buf, size_t len, loff_t *pos)
 {
 	size_t i=0;
-	DECLARE_WAITQUEUE(wait, current);
 
 	down (&mdc800->io_lock);
 	if (mdc800->state != READY)
@@ -856,7 +838,6 @@
 		if (mdc800->in_count == 8)
 		{
 			int answersize;
-			long timeout;
 
 			if (mdc800_usb_waitForIRQ (0,TO_GET_READY))
 			{
@@ -876,14 +857,7 @@
 				up (&mdc800->io_lock);
 				return -EIO;
 			}
-			add_wait_queue(&mdc800->write_wait, &wait);
-			timeout = TO_WRITE_GET_READY*HZ/1000;
-			while (!mdc800->written && timeout)
-			{
-				set_current_state(TASK_UNINTERRUPTIBLE);
-				timeout = schedule_timeout (timeout);
-			}
-			remove_wait_queue(&mdc800->write_wait, &wait);
+			wait_event_timeout(mdc800->write_wait, mdc800->written, TO_WRITE_GET_READY*HZ/1000);
 			mdc800->written = 0;
 			if (mdc800->state == WORKING)
 			{
diff -Nru a/drivers/usb/input/aiptek.c b/drivers/usb/input/aiptek.c
--- a/drivers/usb/input/aiptek.c	2005-03-11 12:51:48 -08:00
+++ b/drivers/usb/input/aiptek.c	2005-03-11 12:51:48 -08:00
@@ -297,8 +297,6 @@
 	int firmwareCode;	/* prom/eeprom version            */
 	char usbPath[64 + 1];	/* device's physical usb path     */
 	char inputPath[64 + 1];	/* input device path              */
-	char manuName[64 + 1];	/* manufacturer name              */
-	char prodName[64 + 1];	/* product name                   */
 };
 
 struct aiptek_settings {
@@ -855,7 +853,7 @@
 			       USB_REQ_SET_REPORT,
 			       USB_TYPE_CLASS | USB_RECIP_INTERFACE |
 			       USB_DIR_OUT, (report_type << 8) + report_id,
-			       aiptek->ifnum, buffer, size, 5 * HZ);
+			       aiptek->ifnum, buffer, size, 5000);
 }
 
 static int
@@ -868,7 +866,7 @@
 			       USB_REQ_GET_REPORT,
 			       USB_TYPE_CLASS | USB_RECIP_INTERFACE |
 			       USB_DIR_IN, (report_type << 8) + report_id,
-			       aiptek->ifnum, buffer, size, 5 * HZ);
+			       aiptek->ifnum, buffer, size, 5000);
 }
 
 /***********************************************************************
@@ -1089,7 +1087,7 @@
 	if (aiptek == NULL)
 		return 0;
 
-	retval = snprintf(buf, PAGE_SIZE, "%s\n", aiptek->features.manuName);
+	retval = snprintf(buf, PAGE_SIZE, "%s\n", aiptek->usbdev->manufacturer);
 	return retval;
 }
 
@@ -1106,7 +1104,7 @@
 	if (aiptek == NULL)
 		return 0;
 
-	retval = snprintf(buf, PAGE_SIZE, "%s\n", aiptek->features.prodName);
+	retval = snprintf(buf, PAGE_SIZE, "%s\n", aiptek->usbdev->product);
 	return retval;
 }
 
@@ -2165,19 +2163,6 @@
 	/* Register the tablet as an Input Device
 	 */
 	input_register_device(&aiptek->inputdev);
-
-	/* Go and decode the USB representation of the tablet's manufacturer
-	 * name and product name. They only change once every hotplug event,
-	 * which is why we put it here instead of in the sysfs interface.
-	 */
-	usb_string(usbdev,
-		   usbdev->descriptor.iManufacturer,
-		   aiptek->features.manuName,
-		   sizeof(aiptek->features.manuName));
-	usb_string(usbdev,
-		   usbdev->descriptor.iProduct,
-		   aiptek->features.prodName,
-		   sizeof(aiptek->features.prodName));
 
 	/* We now will look for the evdev device which is mapped to
 	 * the tablet. The partial name is kept in the link list of
diff -Nru a/drivers/usb/input/ati_remote.c b/drivers/usb/input/ati_remote.c
--- a/drivers/usb/input/ati_remote.c	2005-03-11 12:51:47 -08:00
+++ b/drivers/usb/input/ati_remote.c	2005-03-11 12:51:47 -08:00
@@ -94,6 +94,7 @@
 #include <linux/moduleparam.h>
 #include <linux/input.h>
 #include <linux/usb.h>
+#include <linux/wait.h>
 
 /*
  * Module and Version Information, Module Parameters
@@ -174,7 +175,6 @@
 	dma_addr_t outbuf_dma;
 
 	int open;                   /* open counter */
-	int present;                /* device plugged in? */
 	
 	unsigned char old_data[2];  /* Detect duplicate events */
 	unsigned long old_jiffies;
@@ -252,8 +252,8 @@
 	{KIND_FILTERED, 0xdd, 0x18, EV_KEY, KEY_KPENTER, 1},    /* "check" */
 	{KIND_FILTERED, 0xdb, 0x16, EV_KEY, KEY_MENU, 1},       /* "menu" */
 	{KIND_FILTERED, 0xc7, 0x02, EV_KEY, KEY_POWER, 1},      /* Power */
-	{KIND_FILTERED, 0xc8, 0x03, EV_KEY, KEY_PROG1, 1},      /* TV */
-	{KIND_FILTERED, 0xc9, 0x04, EV_KEY, KEY_PROG2, 1},      /* DVD */
+	{KIND_FILTERED, 0xc8, 0x03, EV_KEY, KEY_TV, 1},         /* TV */
+	{KIND_FILTERED, 0xc9, 0x04, EV_KEY, KEY_DVD, 1},        /* DVD */
 	{KIND_FILTERED, 0xca, 0x05, EV_KEY, KEY_WWW, 1},        /* WEB */
 	{KIND_FILTERED, 0xcb, 0x06, EV_KEY, KEY_BOOKMARKS, 1},  /* "book" */
 	{KIND_FILTERED, 0xcc, 0x07, EV_KEY, KEY_EDIT, 1},       /* "hand" */
@@ -263,14 +263,14 @@
 	{KIND_FILTERED, 0xe4, 0x1f, EV_KEY, KEY_RIGHT, 1},      /* right */
 	{KIND_FILTERED, 0xe7, 0x22, EV_KEY, KEY_DOWN, 1},       /* down */
 	{KIND_FILTERED, 0xdf, 0x1a, EV_KEY, KEY_UP, 1},         /* up */
-	{KIND_FILTERED, 0xe3, 0x1e, EV_KEY, KEY_ENTER, 1},      /* "OK" */
+	{KIND_FILTERED, 0xe3, 0x1e, EV_KEY, KEY_OK, 1},         /* "OK" */
 	{KIND_FILTERED, 0xce, 0x09, EV_KEY, KEY_VOLUMEDOWN, 1}, /* VOL + */
 	{KIND_FILTERED, 0xcd, 0x08, EV_KEY, KEY_VOLUMEUP, 1},   /* VOL - */
 	{KIND_FILTERED, 0xcf, 0x0a, EV_KEY, KEY_MUTE, 1},       /* MUTE  */
-	{KIND_FILTERED, 0xd1, 0x0c, EV_KEY, KEY_CHANNELUP, 1},  /* CH + */
-	{KIND_FILTERED, 0xd0, 0x0b, EV_KEY, KEY_CHANNELDOWN, 1},/* CH - */
+	{KIND_FILTERED, 0xd0, 0x0b, EV_KEY, KEY_CHANNELUP, 1},  /* CH + */
+	{KIND_FILTERED, 0xd1, 0x0c, EV_KEY, KEY_CHANNELDOWN, 1},/* CH - */
 	{KIND_FILTERED, 0xec, 0x27, EV_KEY, KEY_RECORD, 1},     /* ( o) red */
-	{KIND_FILTERED, 0xea, 0x25, EV_KEY, KEY_PLAYCD, 1},     /* ( >) */
+	{KIND_FILTERED, 0xea, 0x25, EV_KEY, KEY_PLAY, 1},       /* ( >) */
 	{KIND_FILTERED, 0xe9, 0x24, EV_KEY, KEY_REWIND, 1},     /* (<<) */
 	{KIND_FILTERED, 0xeb, 0x26, EV_KEY, KEY_FORWARD, 1},    /* (>>) */
 	{KIND_FILTERED, 0xed, 0x28, EV_KEY, KEY_STOP, 1},       /* ([]) */ 
@@ -356,19 +356,8 @@
 {
 	struct ati_remote *ati_remote = inputdev->private;
 	
-	if (ati_remote == NULL) {
-		err("ati_remote: %s: object is NULL!\n", __FUNCTION__);
-		return;
-	}
-	
-	if (ati_remote->open <= 0)
-		dev_dbg(&ati_remote->interface->dev, "%s: Not open.\n", __FUNCTION__);
-	else
-		--ati_remote->open;
-	
-	/* If still present, disconnect will call delete. */
-	if (!ati_remote->present && !ati_remote->open)
-		ati_remote_delete(ati_remote);
+	if (!--ati_remote->open)
+		usb_kill_urb(ati_remote->irq_urb);
 }
 
 /*
@@ -396,8 +385,6 @@
  */
 static int ati_remote_sendpacket(struct ati_remote *ati_remote, u16 cmd, unsigned char *data)
 {
-	DECLARE_WAITQUEUE(wait, current);
-	int timeout = HZ;	/* 1 second */
 	int retval = 0;
 	
 	/* Set up out_urb */
@@ -415,18 +402,10 @@
 		return retval;
 	}
 
-	set_current_state(TASK_INTERRUPTIBLE);
-	add_wait_queue(&ati_remote->wait, &wait);
-
-	while (timeout && (ati_remote->out_urb->status == -EINPROGRESS) 
-	       && !(ati_remote->send_flags & SEND_FLAG_COMPLETE)) {
-		set_current_state(TASK_INTERRUPTIBLE);
-		timeout = schedule_timeout(timeout);
-		rmb();
-	}
-
-	set_current_state(TASK_RUNNING);
-	remove_wait_queue(&ati_remote->wait, &wait);
+	wait_event_timeout(ati_remote->wait,
+		((ati_remote->out_urb->status != -EINPROGRESS) ||
+		 	(ati_remote->send_flags & SEND_FLAG_COMPLETE)),
+		HZ);
 	usb_kill_urb(ati_remote->out_urb);
 	
 	return retval;
@@ -727,7 +706,6 @@
 	struct usb_host_interface *iface_host;
 	int retval = -ENOMEM;
 	char path[64];
-	char *buf = NULL;
 
 	/* Allocate and clear an ati_remote struct */
 	if (!(ati_remote = kmalloc(sizeof (struct ati_remote), GFP_KERNEL)))
@@ -761,8 +739,6 @@
 		retval = -ENODEV;
 		goto error;
 	}
-	if (!(buf = kmalloc(NAME_BUFSIZE, GFP_KERNEL)))
-		goto error;
 
 	/* Allocate URB buffers, URBs */
 	ati_remote->inbuf = usb_buffer_alloc(udev, DATA_BUFSIZE, SLAB_ATOMIC,
@@ -785,14 +761,11 @@
 
 	usb_make_path(udev, path, NAME_BUFSIZE);
 	sprintf(ati_remote->phys, "%s/input%d", path, ATI_INPUTNUM);
-	if (udev->descriptor.iManufacturer && 
-	    (usb_string(udev, udev->descriptor.iManufacturer, buf, 
-			NAME_BUFSIZE) > 0))
-		strcat(ati_remote->name, buf);
-
-	if (udev->descriptor.iProduct && 
-	    (usb_string(udev, udev->descriptor.iProduct, buf, NAME_BUFSIZE) > 0))
-		sprintf(ati_remote->name, "%s %s", ati_remote->name, buf);
+	if (udev->manufacturer)
+		strcat(ati_remote->name, udev->manufacturer);
+
+	if (udev->product)
+		sprintf(ati_remote->name, "%s %s", ati_remote->name, udev->product);
 
 	if (!strlen(ati_remote->name))
 		sprintf(ati_remote->name, DRIVER_DESC "(%04x,%04x)",
@@ -812,12 +785,8 @@
 		 ati_remote->name, path);
 
 	usb_set_intfdata(interface, ati_remote);
-	ati_remote->present = 1;	
 	
 error:
-	if (buf)
-		kfree(buf);
-
 	if (retval)
 		ati_remote_delete(ati_remote);
 
@@ -840,12 +809,7 @@
 		return;
 	}
 	
-	/* Mark device as unplugged */
-	ati_remote->present = 0;
-
-	/* If device is still open, ati_remote_close will call delete. */
-	if (!ati_remote->open)
-		ati_remote_delete(ati_remote);
+	ati_remote_delete(ati_remote);
 
 	up(&disconnect_sem);
 }
diff -Nru a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c
--- a/drivers/usb/input/hid-core.c	2005-03-11 12:51:47 -08:00
+++ b/drivers/usb/input/hid-core.c	2005-03-11 12:51:47 -08:00
@@ -24,6 +24,7 @@
 #include <asm/unaligned.h>
 #include <asm/byteorder.h>
 #include <linux/input.h>
+#include <linux/wait.h>
 
 #undef DEBUG
 #undef DEBUG_DATA
@@ -37,13 +38,20 @@
  * Version Information
  */
 
-#define DRIVER_VERSION "v2.0"
+#define DRIVER_VERSION "v2.01"
 #define DRIVER_AUTHOR "Andreas Gal, Vojtech Pavlik"
 #define DRIVER_DESC "USB HID core driver"
 #define DRIVER_LICENSE "GPL"
 
 static char *hid_types[] = {"Device", "Pointer", "Mouse", "Device", "Joystick",
 				"Gamepad", "Keyboard", "Keypad", "Multi-Axis Controller"};
+/*
+ * Module parameters.
+ */
+
+static unsigned int hid_mousepoll_interval;
+module_param_named(mousepoll, hid_mousepoll_interval, uint, 0644);
+MODULE_PARM_DESC(mousepoll, "Polling interval of mice");
 
 /*
  * Register a new report for a device.
@@ -121,18 +129,17 @@
 
 	if (parser->device->maxcollection == parser->device->collection_size) {
 		collection = kmalloc(sizeof(struct hid_collection) *
-				     parser->device->collection_size * 2,
-				     GFP_KERNEL);
+				parser->device->collection_size * 2, GFP_KERNEL);
 		if (collection == NULL) {
 			dbg("failed to reallocate collection array");
 			return -1;
 		}
 		memcpy(collection, parser->device->collection,
-		       sizeof(struct hid_collection) *
-		       parser->device->collection_size);
+			sizeof(struct hid_collection) *
+			parser->device->collection_size);
 		memset(collection + parser->device->collection_size, 0,
-		       sizeof(struct hid_collection) *
-		       parser->device->collection_size);
+			sizeof(struct hid_collection) *
+			parser->device->collection_size);
 		kfree(parser->device->collection);
 		parser->device->collection = collection;
 		parser->device->collection_size *= 2;
@@ -141,12 +148,12 @@
 	parser->collection_stack[parser->collection_stack_ptr++] =
 		parser->device->maxcollection;
 
-	collection = parser->device->collection + 
+	collection = parser->device->collection +
 		parser->device->maxcollection++;
 	collection->type = type;
 	collection->usage = usage;
 	collection->level = parser->collection_stack_ptr - 1;
-	
+
 	if (type == HID_COLLECTION_APPLICATION)
 		parser->device->maxapplication++;
 
@@ -193,7 +200,7 @@
 	}
 	parser->local.usage[parser->local.usage_index] = usage;
 	parser->local.collection_index[parser->local.usage_index] =
-		parser->collection_stack_ptr ? 
+		parser->collection_stack_ptr ?
 		parser->collection_stack[parser->collection_stack_ptr - 1] : 0;
 	parser->local.usage_index++;
 	return 0;
@@ -220,13 +227,15 @@
 		dbg("logical range invalid %d %d", parser->global.logical_minimum, parser->global.logical_maximum);
 		return -1;
 	}
-	
-	if (!(usages = max_t(int, parser->local.usage_index, parser->global.report_count)))
-		return 0; /* Ignore padding fields */
 
 	offset = report->size;
 	report->size += parser->global.report_size * parser->global.report_count;
 
+	if (!parser->local.usage_index) /* Ignore padding fields */
+		return 0; 
+
+	usages = max_t(int, parser->local.usage_index, parser->global.report_count);
+
 	if ((field = hid_register_field(report, usages, parser->global.report_count)) == NULL)
 		return 0;
 
@@ -581,13 +590,13 @@
 		item->size = *start++;
 		item->tag  = *start++;
 
-		if ((end - start) < item->size) 
+		if ((end - start) < item->size)
 			return NULL;
 
 		item->data.longdata = start;
 		start += item->size;
 		return start;
-	} 
+	}
 
 	item->format = HID_ITEM_FORMAT_SHORT;
 	item->size = b & 3;
@@ -604,7 +613,7 @@
 			return start;
 
 		case 2:
-			if ((end - start) < 2) 
+			if ((end - start) < 2)
 				return NULL;
 			item->data.u16 = le16_to_cpu(get_unaligned((__le16*)start));
 			start = (__u8 *)((__le16 *)start + 1);
@@ -646,13 +655,13 @@
 		return NULL;
 	memset(device, 0, sizeof(struct hid_device));
 
-	if (!(device->collection =kmalloc(sizeof(struct hid_collection) *
+	if (!(device->collection = kmalloc(sizeof(struct hid_collection) *
 				   HID_DEFAULT_NUM_COLLECTIONS, GFP_KERNEL))) {
 		kfree(device);
 		return NULL;
 	}
 	memset(device->collection, 0, sizeof(struct hid_collection) *
-	       HID_DEFAULT_NUM_COLLECTIONS);
+		HID_DEFAULT_NUM_COLLECTIONS);
 	device->collection_size = HID_DEFAULT_NUM_COLLECTIONS;
 
 	for (i = 0; i < HID_REPORT_TYPES; i++)
@@ -806,8 +815,7 @@
 	__s32 max = field->logical_maximum;
 	__s32 *value;
 
-	value = kmalloc(sizeof(__s32)*count, GFP_ATOMIC);
-	if (!value)
+	if (!(value = kmalloc(sizeof(__s32) * count, GFP_ATOMIC)))
 		return;
 
 	for (n = 0; n < count; n++) {
@@ -824,14 +832,6 @@
 	for (n = 0; n < count; n++) {
 
 		if (HID_MAIN_ITEM_VARIABLE & field->flags) {
-
-			if (field->flags & HID_MAIN_ITEM_RELATIVE) {
-				if (!value[n])
-					continue;
-			} else {
-				if (value[n] == field->value[n])
-					continue;
-			}	
 			hid_process_event(hid, field, &field->usage[n], value[n], regs);
 			continue;
 		}
@@ -893,10 +893,8 @@
 
 	size = ((report->size - 1) >> 3) + 1;
 
-	if (len < size) {
+	if (len < size)
 		dbg("report %d is too short, (%d < %d)", report->id, len, size);
-		return -1;
-	}
 
 	if (hid->claimed & HID_CLAIMED_HIDDEV)
 		hiddev_report_event(hid, report);
@@ -934,7 +932,7 @@
 		default:		/* error */
 			warn("input irq status %d received", urb->status);
 	}
-	
+
 	status = usb_submit_urb(urb, SLAB_ATOMIC);
 	if (status)
 		err("can't resubmit intr, %s-%s/input%d, status %d",
@@ -956,7 +954,7 @@
 	for (n = 0; n < count; n++) {
 		if (field->logical_minimum < 0)	/* signed values */
 			implement(data, offset + n * size, size, s32ton(field->value[n], size));
-		 else				/* unsigned values */
+		else				/* unsigned values */
 			implement(data, offset + n * size, size, field->value[n]);
 	}
 }
@@ -1003,64 +1001,22 @@
 	return 0;
 }
 
-int hid_find_field(struct hid_device *hid, unsigned int type, unsigned int code, struct hid_field **field)
-{
-	struct hid_report_enum *report_enum = hid->report_enum + HID_OUTPUT_REPORT;
-	struct list_head *list = report_enum->report_list.next;
-	int i, j;
-
-	while (list != &report_enum->report_list) {
-		struct hid_report *report = (struct hid_report *) list;
-		list = list->next;
-		for (i = 0; i < report->maxfield; i++) {
-			*field = report->field[i];
-			for (j = 0; j < (*field)->maxusage; j++)
-				if ((*field)->usage[j].type == type && (*field)->usage[j].code == code)
-					return j;
-		}
-	}
-	return -1;
-}
-
 /*
- * Find a report with a specified HID usage.
+ * Find a report field with a specified HID usage.
  */
 
-int hid_find_report_by_usage(struct hid_device *hid, __u32 wanted_usage, struct hid_report **report, int type)
+struct hid_field *hid_find_field_by_usage(struct hid_device *hid, __u32 wanted_usage, int type)
 {
-	struct hid_report_enum *report_enum = hid->report_enum + type;
-	struct list_head *list = report_enum->report_list.next;
-	int i, j;
+	struct hid_report *report;
+	int i;
 
-	while (list != &report_enum->report_list) {
-		*report = (struct hid_report *) list;
-		list = list->next;
-		for (i = 0; i < (*report)->maxfield; i++) {
-			struct hid_field *field = (*report)->field[i];
-			for (j = 0; j < field->maxusage; j++)
-				if (field->logical == wanted_usage)
-					return j;
-		}
-	}
-	return -1;
+	list_for_each_entry(report, &hid->report_enum[type].report_list, list)
+		for (i = 0; i < report->maxfield; i++)
+			if (report->field[i]->logical == wanted_usage)
+				return report->field[i];
+	return NULL;
 }
 
-#if 0
-static int hid_find_field_in_report(struct hid_report *report, __u32 wanted_usage, struct hid_field **field)
-{
-	int i, j;
-
-	for (i = 0; i < report->maxfield; i++) {
-		*field = report->field[i];
-		for (j = 0; j < (*field)->maxusage; j++)
-			if ((*field)->usage[j].hid == wanted_usage)
-				return j;
-	}
-
-	return -1;
-}
-#endif
-
 static int hid_submit_out(struct hid_device *hid)
 {
 	struct hid_report *report;
@@ -1118,8 +1074,8 @@
 	hid->cr->wLength = cpu_to_le16(len);
 
 	dbg("submitting ctrl urb: %s wValue=0x%04x wIndex=0x%04x wLength=%u",
-	    hid->cr->bRequest == HID_REQ_SET_REPORT ? "Set_Report" : "Get_Report",
-	    hid->cr->wValue, hid->cr->wIndex, hid->cr->wLength);
+		hid->cr->bRequest == HID_REQ_SET_REPORT ? "Set_Report" : "Get_Report",
+		hid->cr->wValue, hid->cr->wIndex, hid->cr->wLength);
 
 	if (usb_submit_urb(hid->urbctrl, GFP_ATOMIC)) {
 		err("usb_submit_urb(ctrl) failed");
@@ -1186,7 +1142,7 @@
 
 	switch (urb->status) {
 		case 0:			/* success */
-			if (hid->ctrl[hid->ctrltail].dir == USB_DIR_IN) 
+			if (hid->ctrl[hid->ctrltail].dir == USB_DIR_IN)
 				hid_input_report(hid->ctrl[hid->ctrltail].report->type, urb, regs);
 		case -ESHUTDOWN:	/* unplug */
 		case -EILSEQ:		/* unplug timectrl on uhci */
@@ -1268,22 +1224,9 @@
 
 int hid_wait_io(struct hid_device *hid)
 {
-	DECLARE_WAITQUEUE(wait, current);
-	int timeout = 10*HZ;
-
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	add_wait_queue(&hid->wait, &wait);
-
-	while (timeout && (test_bit(HID_CTRL_RUNNING, &hid->iofl) ||
-			   test_bit(HID_OUT_RUNNING, &hid->iofl))) {
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		timeout = schedule_timeout(timeout);
-	}
-
-	set_current_state(TASK_RUNNING);
-	remove_wait_queue(&hid->wait, &wait);
-
-	if (!timeout) {
+	if (!wait_event_timeout(hid->wait, (!test_bit(HID_CTRL_RUNNING, &hid->iofl) &&
+					!test_bit(HID_OUT_RUNNING, &hid->iofl)),
+					10*HZ)) {
 		dbg("timeout waiting for ctrl or out queue to clear");
 		return -1;
 	}
@@ -1301,7 +1244,7 @@
 	do {
 		result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
 				USB_REQ_GET_DESCRIPTOR, USB_RECIP_INTERFACE | USB_DIR_IN,
-				(type << 8), ifnum, buf, size, HZ * USB_CTRL_GET_TIMEOUT);
+				(type << 8), ifnum, buf, size, USB_CTRL_GET_TIMEOUT);
 		retries--;
 	} while (result < size && retries);
 	return result;
@@ -1332,47 +1275,19 @@
 
 void hid_init_reports(struct hid_device *hid)
 {
-	struct hid_report_enum *report_enum;
 	struct hid_report *report;
-	struct list_head *list;
-	int err, ret, size;
-
-	/*
-	 * The Set_Idle request is supposed to affect only the
-	 * "Interrupt In" pipe. Unfortunately, buggy devices such as
-	 * the BTC keyboard (ID 046e:5303) the request also affects
-	 * Get_Report requests on the control pipe.  In the worst
-	 * case, if the device was put on idle for an indefinite
-	 * amount of time (as we do below) and there are no input
-	 * events to report, the Get_Report requests will just hang
-	 * until we get a USB timeout.  To avoid this, we temporarily
-	 * establish a minimal idle time of 1ms.  This shouldn't hurt
-	 * bugfree devices and will cause a worst-case extra delay of
-	 * 1ms for buggy ones.
-	 */
-	usb_control_msg(hid->dev, usb_sndctrlpipe(hid->dev, 0),
-			HID_REQ_SET_IDLE, USB_TYPE_CLASS | USB_RECIP_INTERFACE, (1 << 8),
-			hid->ifnum, NULL, 0, HZ * USB_CTRL_SET_TIMEOUT);
+	int err, ret;
 
-	report_enum = hid->report_enum + HID_INPUT_REPORT;
-	list = report_enum->report_list.next;
-	while (list != &report_enum->report_list) {
-		report = (struct hid_report *) list;
-		size = ((report->size - 1) >> 3) + 1 + report_enum->numbered;
+	list_for_each_entry(report, &hid->report_enum[HID_INPUT_REPORT].report_list, list) {
+		int size = ((report->size - 1) >> 3) + 1 + hid->report_enum[HID_INPUT_REPORT].numbered;
 		if (size > HID_BUFFER_SIZE) size = HID_BUFFER_SIZE;
 		if (size > hid->urbin->transfer_buffer_length)
 			hid->urbin->transfer_buffer_length = size;
 		hid_submit_report(hid, report, USB_DIR_IN);
-		list = list->next;
 	}
 
-	report_enum = hid->report_enum + HID_FEATURE_REPORT;
-	list = report_enum->report_list.next;
-	while (list != &report_enum->report_list) {
-		report = (struct hid_report *) list;
+	list_for_each_entry(report, &hid->report_enum[HID_FEATURE_REPORT].report_list, list)
 		hid_submit_report(hid, report, USB_DIR_IN);
-		list = list->next;
-	}
 
 	err = 0;
 	ret = hid_wait_io(hid);
@@ -1388,15 +1303,9 @@
 	if (err)
 		warn("timeout initializing reports\n");
 
-	report_enum = hid->report_enum + HID_INPUT_REPORT;
-	list = report_enum->report_list.next;
-	while (list != &report_enum->report_list) {
-		report = (struct hid_report *) list;
-		usb_control_msg(hid->dev, usb_sndctrlpipe(hid->dev, 0),
-			HID_REQ_SET_IDLE, USB_TYPE_CLASS | USB_RECIP_INTERFACE, report->id,
-			hid->ifnum, NULL, 0, HZ * USB_CTRL_SET_TIMEOUT);
-		list = list->next;
-	}
+	usb_control_msg(hid->dev, usb_sndctrlpipe(hid->dev, 0),
+		HID_REQ_SET_IDLE, USB_TYPE_CLASS | USB_RECIP_INTERFACE, 0,
+		hid->ifnum, NULL, 0, USB_CTRL_SET_TIMEOUT);
 }
 
 #define USB_VENDOR_ID_WACOM		0x056a
@@ -1405,11 +1314,11 @@
 #define USB_DEVICE_ID_WACOM_INTUOS	0x0020
 #define USB_DEVICE_ID_WACOM_PL		0x0030
 #define USB_DEVICE_ID_WACOM_INTUOS2	0x0040
-#define USB_DEVICE_ID_WACOM_VOLITO      0x0060
-#define USB_DEVICE_ID_WACOM_PTU         0x0003
+#define USB_DEVICE_ID_WACOM_VOLITO	0x0060
+#define USB_DEVICE_ID_WACOM_PTU		0x0003
 
-#define USB_VENDOR_ID_KBGEAR            0x084e
-#define USB_DEVICE_ID_KBGEAR_JAMSTUDIO  0x1001
+#define USB_VENDOR_ID_KBGEAR		0x084e
+#define USB_DEVICE_ID_KBGEAR_JAMSTUDIO	0x1001
 
 #define USB_VENDOR_ID_AIPTEK		0x08ca
 #define USB_DEVICE_ID_AIPTEK_01		0x0001
@@ -1424,35 +1333,35 @@
 #define USB_DEVICE_ID_POWERMATE		0x0410
 #define USB_DEVICE_ID_SOUNDKNOB		0x04AA
 
-#define USB_VENDOR_ID_ATEN             0x0557  
-#define USB_DEVICE_ID_ATEN_UC100KM     0x2004
-#define USB_DEVICE_ID_ATEN_CS124U      0x2202
-#define USB_DEVICE_ID_ATEN_2PORTKVM    0x2204
-#define USB_DEVICE_ID_ATEN_4PORTKVM    0x2205
-#define USB_DEVICE_ID_ATEN_4PORTKVMC   0x2208
-
-#define USB_VENDOR_ID_TOPMAX           0x0663
-#define USB_DEVICE_ID_TOPMAX_COBRAPAD  0x0103
-
-#define USB_VENDOR_ID_HAPP             0x078b
-#define USB_DEVICE_ID_UGCI_DRIVING     0x0010
-#define USB_DEVICE_ID_UGCI_FLYING      0x0020
-#define USB_DEVICE_ID_UGCI_FIGHTING    0x0030
-
-#define USB_VENDOR_ID_MGE              0x0463
-#define USB_DEVICE_ID_MGE_UPS          0xffff
-#define USB_DEVICE_ID_MGE_UPS1         0x0001
+#define USB_VENDOR_ID_ATEN		0x0557
+#define USB_DEVICE_ID_ATEN_UC100KM	0x2004
+#define USB_DEVICE_ID_ATEN_CS124U	0x2202
+#define USB_DEVICE_ID_ATEN_2PORTKVM	0x2204
+#define USB_DEVICE_ID_ATEN_4PORTKVM	0x2205
+#define USB_DEVICE_ID_ATEN_4PORTKVMC	0x2208
+
+#define USB_VENDOR_ID_TOPMAX		0x0663
+#define USB_DEVICE_ID_TOPMAX_COBRAPAD	0x0103
+
+#define USB_VENDOR_ID_HAPP		0x078b
+#define USB_DEVICE_ID_UGCI_DRIVING	0x0010
+#define USB_DEVICE_ID_UGCI_FLYING	0x0020
+#define USB_DEVICE_ID_UGCI_FIGHTING	0x0030
+
+#define USB_VENDOR_ID_MGE		0x0463
+#define USB_DEVICE_ID_MGE_UPS		0xffff
+#define USB_DEVICE_ID_MGE_UPS1		0x0001
 
 #define USB_VENDOR_ID_ONTRAK		0x0a07
 #define USB_DEVICE_ID_ONTRAK_ADU100	0x0064
 
-#define USB_VENDOR_ID_TANGTOP          0x0d3d
-#define USB_DEVICE_ID_TANGTOP_USBPS2   0x0001
+#define USB_VENDOR_ID_TANGTOP		0x0d3d
+#define USB_DEVICE_ID_TANGTOP_USBPS2	0x0001
 
 #define USB_VENDOR_ID_ESSENTIAL_REALITY	0x0d7f
-#define USB_DEVICE_ID_ESSENTIAL_REALITY_P5	0x0100
+#define USB_DEVICE_ID_ESSENTIAL_REALITY_P5 0x0100
 
-#define USB_VENDOR_ID_A4TECH		0x09DA
+#define USB_VENDOR_ID_A4TECH		0x09da
 #define USB_DEVICE_ID_A4TECH_WCP32PU	0x0006
 
 #define USB_VENDOR_ID_CYPRESS		0x04b4
@@ -1494,6 +1403,21 @@
 #define USB_VENDOR_ID_DELORME		0x1163
 #define USB_DEVICE_ID_DELORME_EARTHMATE 0x0100
 
+#define USB_VENDOR_ID_MCC		0x09db
+#define USB_DEVICE_ID_MCC_PMD1024LS	0x0076
+#define USB_DEVICE_ID_MCC_PMD1208LS	0x007a
+
+#define USB_VENDOR_ID_CHICONY		0x04f2
+#define USB_DEVICE_ID_CHICONY_USBHUB_KB	0x0100
+
+#define USB_VENDOR_ID_BTC		0x046e
+#define USB_DEVICE_ID_BTC_KEYBOARD	0x5303
+
+
+/*
+ * Alphabetically sorted blacklist by quirk type.
+ */
+
 static struct hid_blacklist {
 	__u16 idVendor;
 	__u16 idProduct;
@@ -1512,9 +1436,9 @@
 	{ USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW24, HID_QUIRK_IGNORE },
 	{ USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW48, HID_QUIRK_IGNORE },
 	{ USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW28, HID_QUIRK_IGNORE },
-	
+	{ USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_HIDCOM, HID_QUIRK_IGNORE },
+	{ USB_VENDOR_ID_DELORME, USB_DEVICE_ID_DELORME_EARTHMATE, HID_QUIRK_IGNORE },
 	{ USB_VENDOR_ID_ESSENTIAL_REALITY, USB_DEVICE_ID_ESSENTIAL_REALITY_P5, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_KBGEAR, USB_DEVICE_ID_KBGEAR_JAMSTUDIO, HID_QUIRK_IGNORE },
 	{ USB_VENDOR_ID_GLAB, USB_DEVICE_ID_4_PHIDGETSERVO_30, HID_QUIRK_IGNORE },
 	{ USB_VENDOR_ID_GLAB, USB_DEVICE_ID_1_PHIDGETSERVO_30, HID_QUIRK_IGNORE },
 	{ USB_VENDOR_ID_GLAB, USB_DEVICE_ID_8_8_8_IF_KIT, HID_QUIRK_IGNORE },
@@ -1522,6 +1446,9 @@
 	{ USB_VENDOR_ID_GLAB, USB_DEVICE_ID_0_8_8_IF_KIT, HID_QUIRK_IGNORE },
 	{ USB_VENDOR_ID_GRIFFIN, USB_DEVICE_ID_POWERMATE, HID_QUIRK_IGNORE },
 	{ USB_VENDOR_ID_GRIFFIN, USB_DEVICE_ID_SOUNDKNOB, HID_QUIRK_IGNORE },
+	{ USB_VENDOR_ID_KBGEAR, USB_DEVICE_ID_KBGEAR_JAMSTUDIO, HID_QUIRK_IGNORE },
+	{ USB_VENDOR_ID_MCC, USB_DEVICE_ID_MCC_PMD1024LS, HID_QUIRK_IGNORE },
+	{ USB_VENDOR_ID_MCC, USB_DEVICE_ID_MCC_PMD1208LS, HID_QUIRK_IGNORE },
 	{ USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS, HID_QUIRK_IGNORE },
 	{ USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS1, HID_QUIRK_IGNORE },
 	{ USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100, HID_QUIRK_IGNORE },
@@ -1557,18 +1484,18 @@
 	{ USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_PTU, HID_QUIRK_IGNORE },
 	{ USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_4_PHIDGETSERVO_20, HID_QUIRK_IGNORE },
 	{ USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_1_PHIDGETSERVO_20, HID_QUIRK_IGNORE },
-	
 
 	{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_UC100KM, HID_QUIRK_NOGET },
 	{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_CS124U, HID_QUIRK_NOGET },
 	{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_2PORTKVM, HID_QUIRK_NOGET },
 	{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVM, HID_QUIRK_NOGET },
 	{ USB_VENDOR_ID_ATEN, USB_DEVICE_ID_ATEN_4PORTKVMC, HID_QUIRK_NOGET },
+	{ USB_VENDOR_ID_BTC, USB_DEVICE_ID_BTC_KEYBOARD, HID_QUIRK_NOGET},
+	{ USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_USBHUB_KB, HID_QUIRK_NOGET},
 	{ USB_VENDOR_ID_TANGTOP, USB_DEVICE_ID_TANGTOP_USBPS2, HID_QUIRK_NOGET },
 
 	{ USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_WCP32PU, HID_QUIRK_2WHEEL_MOUSE_HACK_7 },
 	{ USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_MOUSE, HID_QUIRK_2WHEEL_MOUSE_HACK_5 },
-	{ USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_HIDCOM, HID_QUIRK_IGNORE },
 
 	{ USB_VENDOR_ID_ALPS, USB_DEVICE_ID_IBM_GAMEPAD, HID_QUIRK_BADPAD },
 	{ USB_VENDOR_ID_CHIC, USB_DEVICE_ID_CHIC_GAMEPAD, HID_QUIRK_BADPAD },
@@ -1579,13 +1506,6 @@
 	{ USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_RUMBLEPAD, HID_QUIRK_BADPAD },
 	{ USB_VENDOR_ID_TOPMAX, USB_DEVICE_ID_TOPMAX_COBRAPAD, HID_QUIRK_BADPAD },
 
-	{ USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW40, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW24, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW48, HID_QUIRK_IGNORE },
-	{ USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW28, HID_QUIRK_IGNORE },
-
-	{ USB_VENDOR_ID_DELORME, USB_DEVICE_ID_DELORME_EARTHMATE, HID_QUIRK_IGNORE },
-
 	{ 0, 0 }
 };
 
@@ -1695,6 +1615,10 @@
 		if (dev->speed == USB_SPEED_HIGH)
 			interval = 1 << (interval - 1);
 
+		/* Change the polling interval of mice. */
+		if (hid->collection->usage == HID_GD_MOUSE && hid_mousepoll_interval > 0)
+			interval = hid_mousepoll_interval;
+		
 		if (endpoint->bEndpointAddress & USB_DIR_IN) {
 			if (hid->urbin)
 				continue;
@@ -1724,7 +1648,7 @@
 	}
 
 	init_waitqueue_head(&hid->wait);
-	
+
 	spin_lock_init(&hid->outlock);
 	spin_lock_init(&hid->ctrllock);
 
@@ -1739,16 +1663,16 @@
 	if (!(buf = kmalloc(64, GFP_KERNEL)))
 		goto fail;
 
-	if (usb_string(dev, dev->descriptor.iManufacturer, buf, 64) > 0) {
-		strcat(hid->name, buf);
-		if (usb_string(dev, dev->descriptor.iProduct, buf, 64) > 0)
-			snprintf(hid->name, 64, "%s %s", hid->name, buf);
-	} else if (usb_string(dev, dev->descriptor.iProduct, buf, 64) > 0) {
-			snprintf(hid->name, 128, "%s", buf);
+	if (dev->manufacturer) {
+		strcat(hid->name, dev->manufacturer);
+		if (dev->product)
+			snprintf(hid->name, 64, "%s %s", hid->name, dev->product);
+	} else if (dev->product) {
+			snprintf(hid->name, 128, "%s", dev->product);
 	} else
-		snprintf(hid->name, 128, "%04x:%04x", 
-			 le16_to_cpu(dev->descriptor.idVendor),
-			 le16_to_cpu(dev->descriptor.idProduct));
+		snprintf(hid->name, 128, "%04x:%04x",
+			le16_to_cpu(dev->descriptor.idVendor),
+			le16_to_cpu(dev->descriptor.idProduct));
 
 	usb_make_path(dev, buf, 64);
 	snprintf(hid->phys, 64, "%s/input%d", buf,
@@ -1810,7 +1734,7 @@
 	hid_free_device(hid);
 }
 
-static int hid_probe (struct usb_interface *intf, const struct usb_device_id *id)
+static int hid_probe(struct usb_interface *intf, const struct usb_device_id *id)
 {
 	struct hid_device *hid;
 	char path[64];
@@ -1892,7 +1816,7 @@
 
 static struct usb_device_id hid_usb_ids [] = {
 	{ .match_flags = USB_DEVICE_ID_MATCH_INT_CLASS,
-	    .bInterfaceClass = USB_INTERFACE_CLASS_HID },
+		.bInterfaceClass = USB_INTERFACE_CLASS_HID },
 	{ }						/* Terminating entry */
 };
 
diff -Nru a/drivers/usb/input/hid-debug.h b/drivers/usb/input/hid-debug.h
--- a/drivers/usb/input/hid-debug.h	2005-03-11 12:51:46 -08:00
+++ b/drivers/usb/input/hid-debug.h	2005-03-11 12:51:46 -08:00
@@ -473,7 +473,6 @@
 
 
 static char *events[EV_MAX + 1] = {
-	[0 ... EV_MAX] = NULL,
 	[EV_SYN] = "Sync",			[EV_KEY] = "Key",
 	[EV_REL] = "Relative",			[EV_ABS] = "Absolute",
 	[EV_MSC] = "Misc",			[EV_LED] = "LED",
@@ -483,11 +482,9 @@
 };
 
 static char *syncs[2] = {
-	[0 ... 1] = NULL,
 	[SYN_REPORT] = "Report",		[SYN_CONFIG] = "Config",
 };
 static char *keys[KEY_MAX + 1] = {
-	[0 ... KEY_MAX] = NULL,
 	[KEY_RESERVED] = "Reserved",		[KEY_ESC] = "Esc",
 	[KEY_1] = "1",				[KEY_2] = "2",
 	[KEY_3] = "3",				[KEY_4] = "4",
@@ -665,7 +662,6 @@
 };
 
 static char *relatives[REL_MAX + 1] = {
-	[0 ... REL_MAX] = NULL,
 	[REL_X] = "X",			[REL_Y] = "Y",
 	[REL_Z] = "Z",			[REL_HWHEEL] = "HWheel",
 	[REL_DIAL] = "Dial",		[REL_WHEEL] = "Wheel", 
@@ -673,7 +669,6 @@
 };
 
 static char *absolutes[ABS_MAX + 1] = {
-	[0 ... ABS_MAX] = NULL,
 	[ABS_X] = "X",			[ABS_Y] = "Y",
 	[ABS_Z] = "Z",			[ABS_RX] = "Rx",
 	[ABS_RY] = "Ry",		[ABS_RZ] = "Rz",
@@ -690,13 +685,11 @@
 };
 
 static char *misc[MSC_MAX + 1] = {
-	[ 0 ... MSC_MAX] = NULL,
 	[MSC_SERIAL] = "Serial",	[MSC_PULSELED] = "Pulseled",
 	[MSC_GESTURE] = "Gesture",	[MSC_RAW] = "RawData"
 };
 
 static char *leds[LED_MAX + 1] = {
-	[0 ... LED_MAX] = NULL,
 	[LED_NUML] = "NumLock",		[LED_CAPSL] = "CapsLock", 
 	[LED_SCROLLL] = "ScrollLock",	[LED_COMPOSE] = "Compose",
 	[LED_KANA] = "Kana",		[LED_SLEEP] = "Sleep", 
@@ -705,25 +698,22 @@
 };
 
 static char *repeats[REP_MAX + 1] = {
-	[0 ... REP_MAX] = NULL,
 	[REP_DELAY] = "Delay",		[REP_PERIOD] = "Period"
 };
 
 static char *sounds[SND_MAX + 1] = {
-	[0 ... SND_MAX] = NULL,
 	[SND_CLICK] = "Click",		[SND_BELL] = "Bell",
 	[SND_TONE] = "Tone"
 };
 
 static char **names[EV_MAX + 1] = {
-	[0 ... EV_MAX] = NULL,
 	[EV_SYN] = syncs,			[EV_KEY] = keys,
 	[EV_REL] = relatives,			[EV_ABS] = absolutes,
 	[EV_MSC] = misc,			[EV_LED] = leds,
 	[EV_SND] = sounds,			[EV_REP] = repeats,
 };
 
-static void resolv_event(__u8 type, __u16 code) {
+static void __attribute__((unused)) resolv_event(__u8 type, __u16 code) {
 
 	printk("%s.%s", events[type] ? events[type] : "?",
 		names[type] ? (names[type][code] ? names[type][code] : "?") : "?");
diff -Nru a/drivers/usb/input/hid-ff.c b/drivers/usb/input/hid-ff.c
--- a/drivers/usb/input/hid-ff.c	2005-03-11 12:51:46 -08:00
+++ b/drivers/usb/input/hid-ff.c	2005-03-11 12:51:46 -08:00
@@ -55,6 +55,7 @@
 	{0x46d, 0xc211, hid_lgff_init}, // Logitech Cordless rumble pad
 	{0x46d, 0xc283, hid_lgff_init}, // Logitech Wingman Force 3d
 	{0x46d, 0xc295, hid_lgff_init},	// Logitech MOMO force wheel
+	{0x46d, 0xc219, hid_lgff_init}, // Logitech Cordless rumble pad 2
 #endif
 #ifdef CONFIG_HID_PID
 	{0x45e, 0x001b, hid_pid_init},
diff -Nru a/drivers/usb/input/hid-input.c b/drivers/usb/input/hid-input.c
--- a/drivers/usb/input/hid-input.c	2005-03-11 12:51:42 -08:00
+++ b/drivers/usb/input/hid-input.c	2005-03-11 12:51:42 -08:00
@@ -404,7 +404,6 @@
 		return;
 
 	input_regs(input, regs);
-	input_event(input, EV_MSC, MSC_SCAN, usage->hid);
 
 	if (!usage->type)
 		return;
@@ -483,10 +482,26 @@
 	}
 }
 
+static int hidinput_find_field(struct hid_device *hid, unsigned int type, unsigned int code, struct hid_field **field)
+{
+	struct hid_report *report;
+	int i, j;
+
+	list_for_each_entry(report, &hid->report_enum[HID_OUTPUT_REPORT].report_list, list) {
+		for (i = 0; i < report->maxfield; i++) {
+			*field = report->field[i];
+			for (j = 0; j < (*field)->maxusage; j++)
+				if ((*field)->usage[j].type == type && (*field)->usage[j].code == code)
+					return j;
+		}
+	}
+	return -1;
+}
+
 static int hidinput_input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
 {
 	struct hid_device *hid = dev->private;
-	struct hid_field *field = NULL;
+	struct hid_field *field;
 	int offset;
 
 	if (type == EV_FF)
@@ -495,7 +510,7 @@
 	if (type != EV_LED)
 		return -1;
 
-	if ((offset = hid_find_field(hid, type, code, &field)) == -1) {
+	if ((offset = hidinput_find_field(hid, type, code, &field)) == -1) {
 		warn("event field not found");
 		return -1;
 	}
@@ -527,9 +542,7 @@
 int hidinput_connect(struct hid_device *hid)
 {
 	struct usb_device *dev = hid->dev;
-	struct hid_report_enum *report_enum;
 	struct hid_report *report;
-	struct list_head *list;
 	struct hid_input *hidinput = NULL;
 	int i, j, k;
 
@@ -544,16 +557,11 @@
 	if (i == hid->maxcollection)
 		return -1;
 
-	for (k = HID_INPUT_REPORT; k <= HID_OUTPUT_REPORT; k++) {
-		report_enum = hid->report_enum + k;
-		list = report_enum->report_list.next;
-		while (list != &report_enum->report_list) {
-			report = (struct hid_report *) list;
+	for (k = HID_INPUT_REPORT; k <= HID_OUTPUT_REPORT; k++)
+		list_for_each_entry(report, &hid->report_enum[k].report_list, list) {
 
-			if (!report->maxfield) {
-				list = list->next;
+			if (!report->maxfield)
 				continue;
-			}
 
 			if (!hidinput) {
 				hidinput = kmalloc(sizeof(*hidinput), GFP_KERNEL);
@@ -578,9 +586,6 @@
 				hidinput->input.id.product = le16_to_cpu(dev->descriptor.idProduct);
 				hidinput->input.id.version = le16_to_cpu(dev->descriptor.bcdDevice);
 				hidinput->input.dev = &hid->intf->dev;
-
-				set_bit(EV_MSC, hidinput->input.evbit);
-				set_bit(MSC_SCAN, hidinput->input.mscbit);
 			}
 
 			for (i = 0; i < report->maxfield; i++)
@@ -598,10 +603,7 @@
 				input_register_device(&hidinput->input);
 				hidinput = NULL;
 			}
-
-			list = list->next;
 		}
-	}
 
 	/* This only gets called when we are a single-input (most of the
 	 * time). IOW, not a HID_QUIRK_MULTI_INPUT. The hid_ff_init() is
@@ -619,7 +621,7 @@
 	struct list_head *lh, *next;
 	struct hid_input *hidinput;
 
-	list_for_each_safe (lh, next, &hid->inputs) {
+	list_for_each_safe(lh, next, &hid->inputs) {
 		hidinput = list_entry(lh, struct hid_input, list);
 		input_unregister_device(&hidinput->input);
 		list_del(&hidinput->list);
diff -Nru a/drivers/usb/input/hid-lgff.c b/drivers/usb/input/hid-lgff.c
--- a/drivers/usb/input/hid-lgff.c	2005-03-11 12:51:50 -08:00
+++ b/drivers/usb/input/hid-lgff.c	2005-03-11 12:51:50 -08:00
@@ -126,6 +126,7 @@
 
 static struct device_type devices[] = {
 	{0x046d, 0xc211, ff_rumble},
+	{0x046d, 0xc219, ff_rumble},
 	{0x046d, 0xc283, ff_joystick},
 	{0x0000, 0x0000, ff_joystick}
 };
diff -Nru a/drivers/usb/input/hid.h b/drivers/usb/input/hid.h
--- a/drivers/usb/input/hid.h	2005-03-11 12:51:40 -08:00
+++ b/drivers/usb/input/hid.h	2005-03-11 12:51:40 -08:00
@@ -484,11 +484,10 @@
 
 int hid_open(struct hid_device *);
 void hid_close(struct hid_device *);
-int hid_find_field(struct hid_device *, unsigned int, unsigned int, struct hid_field **);
 int hid_set_field(struct hid_field *, unsigned, __s32);
 void hid_submit_report(struct hid_device *, struct hid_report *, unsigned char dir);
 void hid_init_reports(struct hid_device *hid);
-int hid_find_report_by_usage(struct hid_device *hid, __u32 wanted_usage, struct hid_report **report, int type);
+struct hid_field *hid_find_field_by_usage(struct hid_device *hid, __u32 wanted_usage, int type);
 int hid_wait_io(struct hid_device* hid);
 
 
diff -Nru a/drivers/usb/input/hiddev.c b/drivers/usb/input/hiddev.c
--- a/drivers/usb/input/hiddev.c	2005-03-11 12:51:42 -08:00
+++ b/drivers/usb/input/hiddev.c	2005-03-11 12:51:42 -08:00
@@ -124,7 +124,6 @@
 	int i, j;
 	struct hid_report *report;
 	struct hid_report_enum *report_enum;
-	struct list_head *list;
 	struct hid_field *field;
 
 	if (uref->report_type < HID_REPORT_TYPE_MIN ||
@@ -132,9 +131,8 @@
 
 	report_enum = hid->report_enum +
 		(uref->report_type - HID_REPORT_TYPE_MIN);
-	list = report_enum->report_list.next;
-	while (list != &report_enum->report_list) {
-		report = (struct hid_report *) list;
+
+	list_for_each_entry(report, &report_enum->report_list, list)
 		for (i = 0; i < report->maxfield; i++) {
 			field = report->field[i];
 			for (j = 0; j < field->maxusage; j++) {
@@ -146,8 +144,6 @@
 				}
 			}
 		}
-		list = list->next;
-	}
 
 	return NULL;
 }
@@ -634,9 +630,8 @@
 				goto inval;
 
 			else if ((cmd == HIDIOCGUSAGES || cmd == HIDIOCSUSAGES) &&
-				 (uref_multi->num_values >= HID_MAX_MULTI_USAGES ||
-				  uref->usage_index + uref_multi->num_values >= field->report_count ||
-				  uref->usage_index + uref_multi->num_values < uref->usage_index))
+				 (uref_multi->num_values > HID_MAX_MULTI_USAGES ||
+				  uref->usage_index + uref_multi->num_values >= field->report_count))
 				goto inval;
 			}
 
diff -Nru a/drivers/usb/input/mtouchusb.c b/drivers/usb/input/mtouchusb.c
--- a/drivers/usb/input/mtouchusb.c	2005-03-11 12:51:46 -08:00
+++ b/drivers/usb/input/mtouchusb.c	2005-03-11 12:51:46 -08:00
@@ -34,6 +34,9 @@
  *    Eliminated vendor/product module params
  *    Performed multiple successfull tests with an EXII-5010UC
  *
+ *  1.5 02/27/2005 ddstreet@ieee.org
+ *    Added module parameter to select raw or hw-calibrated coordinate reporting
+ *
  *****************************************************************************/
 
 #include <linux/config.h>
@@ -52,11 +55,13 @@
 #include <linux/usb.h>
 
 #define MTOUCHUSB_MIN_XC                0x0
-#define MTOUCHUSB_MAX_XC                0x4000
+#define MTOUCHUSB_MAX_RAW_XC            0x4000
+#define MTOUCHUSB_MAX_CALIB_XC          0xffff
 #define MTOUCHUSB_XC_FUZZ               0x0
 #define MTOUCHUSB_XC_FLAT               0x0
 #define MTOUCHUSB_MIN_YC                0x0
-#define MTOUCHUSB_MAX_YC                0x4000
+#define MTOUCHUSB_MAX_RAW_YC            0x4000
+#define MTOUCHUSB_MAX_CALIB_YC          0xffff
 #define MTOUCHUSB_YC_FUZZ               0x0
 #define MTOUCHUSB_YC_FLAT               0x0
 
@@ -65,15 +70,28 @@
 #define MTOUCHUSB_REPORT_DATA_SIZE      11
 #define MTOUCHUSB_REQ_CTRLLR_ID         10
 
-#define MTOUCHUSB_GET_XC(data)          (data[8]<<8 | data[7])
-#define MTOUCHUSB_GET_YC(data)          (data[10]<<8 | data[9])
+#define MTOUCHUSB_GET_RAW_XC(data)      (data[8]<<8 | data[7])
+#define MTOUCHUSB_GET_CALIB_XC(data)    (data[4]<<8 | data[3])
+#define MTOUCHUSB_GET_RAW_YC(data)      (data[10]<<8 | data[9])
+#define MTOUCHUSB_GET_CALIB_YC(data)    (data[6]<<8 | data[5])
+#define MTOUCHUSB_GET_XC(data)          (raw_coordinates ? \
+                                         MTOUCHUSB_GET_RAW_XC(data) : \
+                                         MTOUCHUSB_GET_CALIB_XC(data))
+#define MTOUCHUSB_GET_YC(data)          (raw_coordinates ? \
+                                         MTOUCHUSB_GET_RAW_YC(data) : \
+                                         MTOUCHUSB_GET_CALIB_YC(data))
 #define MTOUCHUSB_GET_TOUCHED(data)     ((data[2] & 0x40) ? 1:0)
 
-#define DRIVER_VERSION "v1.4"
+#define DRIVER_VERSION "v1.5"
 #define DRIVER_AUTHOR "Todd E. Johnson, tejohnson@yahoo.com"
 #define DRIVER_DESC "3M USB Touchscreen Driver"
 #define DRIVER_LICENSE "GPL"
 
+static int raw_coordinates = 1;
+
+module_param(raw_coordinates, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(raw_coordinates, "report raw coordinate values (y, default) or hardware-calibrated coordinate values (n)");
+
 struct mtouch_usb {
         unsigned char *data;
         dma_addr_t data_dma;
@@ -123,7 +141,8 @@
         input_report_abs(&mtouch->input, ABS_X,
                          MTOUCHUSB_GET_XC(mtouch->data));
         input_report_abs(&mtouch->input, ABS_Y,
-                         MTOUCHUSB_GET_YC(mtouch->data));
+			 (raw_coordinates ? MTOUCHUSB_MAX_RAW_YC : MTOUCHUSB_MAX_CALIB_YC)
+                         - MTOUCHUSB_GET_YC(mtouch->data));
         input_sync(&mtouch->input);
 
 exit:
@@ -187,7 +206,6 @@
         struct usb_endpoint_descriptor *endpoint;
         struct usb_device *udev = interface_to_usbdev (intf);
         char path[64];
-        char *buf;
         int nRet;
 
         dbg("%s - called", __FUNCTION__);
@@ -234,32 +252,25 @@
 
         /* Used to Scale Compensated Data and Flip Y */
         mtouch->input.absmin[ABS_X] =  MTOUCHUSB_MIN_XC;
-        mtouch->input.absmax[ABS_X] =  MTOUCHUSB_MAX_XC;
+        mtouch->input.absmax[ABS_X] =  raw_coordinates ? \
+                                       MTOUCHUSB_MAX_RAW_XC : MTOUCHUSB_MAX_CALIB_XC;
         mtouch->input.absfuzz[ABS_X] = MTOUCHUSB_XC_FUZZ;
         mtouch->input.absflat[ABS_X] = MTOUCHUSB_XC_FLAT;
         mtouch->input.absmin[ABS_Y] =  MTOUCHUSB_MIN_YC;
-        mtouch->input.absmax[ABS_Y] =  MTOUCHUSB_MAX_YC;
+        mtouch->input.absmax[ABS_Y] =  raw_coordinates ? \
+                                       MTOUCHUSB_MAX_RAW_YC : MTOUCHUSB_MAX_CALIB_YC;
         mtouch->input.absfuzz[ABS_Y] = MTOUCHUSB_YC_FUZZ;
         mtouch->input.absflat[ABS_Y] = MTOUCHUSB_YC_FLAT;
 
-        if (!(buf = kmalloc(63, GFP_KERNEL))) {
-                kfree(mtouch);
-                return -ENOMEM;
-        }
-
-        if (udev->descriptor.iManufacturer &&
-            usb_string(udev, udev->descriptor.iManufacturer, buf, 63) > 0)
-                        strcat(mtouch->name, buf);
-        if (udev->descriptor.iProduct &&
-            usb_string(udev, udev->descriptor.iProduct, buf, 63) > 0)
-                        sprintf(mtouch->name, "%s %s", mtouch->name, buf);
+	if (udev->manufacturer)
+		strcat(mtouch->name, udev->manufacturer);
+	if (udev->product)
+		sprintf(mtouch->name, "%s %s", mtouch->name, udev->product);
 
         if (!strlen(mtouch->name))
                 sprintf(mtouch->name, "USB Touchscreen %04x:%04x",
                         mtouch->input.id.vendor, mtouch->input.id.product);
 
-        kfree(buf);
-
         nRet = usb_control_msg(mtouch->udev,
                                usb_rcvctrlpipe(udev, 0),
                                MTOUCHUSB_RESET,
@@ -268,7 +279,7 @@
                                0,
                                NULL,
                                0,
-                               HZ * USB_CTRL_SET_TIMEOUT);
+                               USB_CTRL_SET_TIMEOUT);
         dbg("%s - usb_control_msg - MTOUCHUSB_RESET - bytes|err: %d",
             __FUNCTION__, nRet);
 
@@ -302,7 +313,7 @@
                                1,
                                NULL,
                                0,
-                               HZ * USB_CTRL_SET_TIMEOUT);
+                               USB_CTRL_SET_TIMEOUT);
         dbg("%s - usb_control_msg - MTOUCHUSB_ASYNC_REPORT - bytes|err: %d",
             __FUNCTION__, nRet);
 
diff -Nru a/drivers/usb/input/pid.c b/drivers/usb/input/pid.c
--- a/drivers/usb/input/pid.c	2005-03-11 12:51:51 -08:00
+++ b/drivers/usb/input/pid.c	2005-03-11 12:51:51 -08:00
@@ -48,106 +48,96 @@
 /* Called when a transfer is completed */
 static void hid_pid_ctrl_out(struct urb *u, struct pt_regs *regs)
 {
-    dev_dbg(&u->dev->dev, "hid_pid_ctrl_out - Transfer Completed\n");
+	dev_dbg(&u->dev->dev, "hid_pid_ctrl_out - Transfer Completed\n");
 }
 
-static void hid_pid_exit(struct hid_device* hid)
+static void hid_pid_exit(struct hid_device *hid)
 {
-    struct hid_ff_pid *private = hid->ff_private;
-    
-    if (private->urbffout) {
-	usb_kill_urb(private->urbffout);
-	usb_free_urb(private->urbffout);
-    }
+	struct hid_ff_pid *private = hid->ff_private;
+
+	if (private->urbffout) {
+		usb_kill_urb(private->urbffout);
+		usb_free_urb(private->urbffout);
+	}
 }
 
-static int pid_upload_periodic(struct hid_ff_pid *pid, struct ff_effect *effect, int is_update) {
-    dev_info(&pid->hid->dev->dev, "requested periodic force upload\n");
-    return 0;
+static int pid_upload_periodic(struct hid_ff_pid *pid, struct ff_effect *effect, int is_update)
+{
+	dev_info(&pid->hid->dev->dev, "requested periodic force upload\n");
+	return 0;
 }
 
-static int pid_upload_constant(struct hid_ff_pid *pid, struct ff_effect *effect, int is_update) {
-    dev_info(&pid->hid->dev->dev, "requested constant force upload\n");
-    return 0;
+static int pid_upload_constant(struct hid_ff_pid *pid, struct ff_effect *effect, int is_update)
+{
+	dev_info(&pid->hid->dev->dev, "requested constant force upload\n");
+	return 0;
 }
 
-static int pid_upload_condition(struct hid_ff_pid *pid, struct ff_effect *effect, int is_update) {
-    dev_info(&pid->hid->dev->dev, "requested Condition force upload\n");
-    return 0;
+static int pid_upload_condition(struct hid_ff_pid *pid, struct ff_effect *effect, int is_update)
+{
+	dev_info(&pid->hid->dev->dev, "requested Condition force upload\n");
+	return 0;
 }
 
-static int pid_upload_ramp(struct hid_ff_pid *pid, struct ff_effect *effect, int is_update) {
-    dev_info(&pid->hid->dev->dev, "request ramp force upload\n");
-    return 0;
+static int pid_upload_ramp(struct hid_ff_pid *pid, struct ff_effect *effect, int is_update)
+{
+	dev_info(&pid->hid->dev->dev, "request ramp force upload\n");
+	return 0;
 }
 
 static int hid_pid_event(struct hid_device *hid, struct input_dev *input,
-			  unsigned int type, unsigned int code, int value)
+			 unsigned int type, unsigned int code, int value)
 {
-    dev_dbg(&hid->dev->dev, "PID event received: type=%d,code=%d,value=%d.\n", type, code, value);
+	dev_dbg(&hid->dev->dev, "PID event received: type=%d,code=%d,value=%d.\n", type, code, value);
 
-    if (type != EV_FF)
-	return -1;
+	if (type != EV_FF)
+		return -1;
 
-    
-
-    return 0;
+	return 0;
 }
 
 /* Lock must be held by caller */
-static void hid_pid_ctrl_playback(struct hid_device *hid,
-				   struct hid_pid_effect *effect, int play)
+static void hid_pid_ctrl_playback(struct hid_device *hid, struct hid_pid_effect *effect, int play)
 {
-	if (play) {
+	if (play)
 		set_bit(FF_PID_FLAGS_PLAYING, &effect->flags);
-
-	} else {
+	else
 		clear_bit(FF_PID_FLAGS_PLAYING, &effect->flags);
-	}
 }
 
-
 static int hid_pid_erase(struct input_dev *dev, int id)
 {
 	struct hid_device *hid = dev->private;
-	struct hid_field* field;
-	struct hid_report* report;
 	struct hid_ff_pid *pid = hid->ff_private;
+	struct hid_field *field;
 	unsigned long flags;
-	unsigned wanted_report = HID_UP_PID | FF_PID_USAGE_BLOCK_FREE;  /*  PID Block Free Report */
 	int ret;
 
 	if (!CHECK_OWNERSHIP(id, pid))
 		return -EACCES;
 
 	/* Find report */
-	ret =  hid_find_report_by_usage(hid, wanted_report, &report, HID_OUTPUT_REPORT);
-	if(!ret) {
+	field = hid_find_field_by_usage(hid, HID_UP_PID | FF_PID_USAGE_BLOCK_FREE,
+					HID_OUTPUT_REPORT);
+	if (!field) {
 		dev_err(&hid->dev->dev, "couldn't find report\n");
-		return ret;
-	}
-
-	/* Find field */
-	field = (struct hid_field *) kmalloc(sizeof(struct hid_field), GFP_KERNEL);
-	if(!field) {
-		dev_err(&hid->dev->dev, "couldn't allocate field\n");
-		return -ENOMEM;
+		return -EIO;
 	}
 
-	ret = hid_set_field(field, ret, pid->effects[id].device_id);
-	if(!ret) {
+	ret = hid_set_field(field, 0, pid->effects[id].device_id);
+	if (ret) {
 		dev_err(&hid->dev->dev, "couldn't set field\n");
 		return ret;
 	}
 
-	hid_submit_report(hid, report, USB_DIR_OUT);
+	hid_submit_report(hid, field->report, USB_DIR_OUT);
 
 	spin_lock_irqsave(&pid->lock, flags);
 	hid_pid_ctrl_playback(hid, pid->effects + id, 0);
 	pid->effects[id].flags = 0;
 	spin_unlock_irqrestore(&pid->lock, flags);
 
-	return ret;
+	return 0;
 }
 
 /* Erase all effects this process owns */
@@ -158,31 +148,32 @@
 	int i;
 
 	/*NOTE: no need to lock here. The only times EFFECT_USED is
-	  modified is when effects are uploaded or when an effect is
-	  erased. But a process cannot close its dev/input/eventX fd
-	  and perform ioctls on the same fd all at the same time */
-	for (i=0; i<dev->ff_effects_max; ++i)
-		if ( current->pid == pid->effects[i].owner
-		     && test_bit(FF_PID_FLAGS_USED, &pid->effects[i].flags))
+	   modified is when effects are uploaded or when an effect is
+	   erased. But a process cannot close its dev/input/eventX fd
+	   and perform ioctls on the same fd all at the same time */
+	/*FIXME: multiple threads, anyone? */
+	for (i = 0; i < dev->ff_effects_max; ++i)
+		if (current->pid == pid->effects[i].owner
+		    && test_bit(FF_PID_FLAGS_USED, &pid->effects[i].flags))
 			if (hid_pid_erase(dev, i))
 				dev_warn(&hid->dev->dev, "erase effect %d failed", i);
 
 	return 0;
 }
 
-
 static int hid_pid_upload_effect(struct input_dev *dev,
-				  struct ff_effect *effect)
+				 struct ff_effect *effect)
 {
-	struct hid_ff_pid* pid_private  = (struct hid_ff_pid*)(dev->private);
+	struct hid_ff_pid *pid_private = (struct hid_ff_pid *)(dev->private);
 	int ret;
 	int is_update;
-	unsigned long flags = 0;
+	unsigned long flags;
 
-        dev_dbg(&pid_private->hid->dev->dev, "upload effect called: effect_type=%x\n",effect->type);
+	dev_dbg(&pid_private->hid->dev->dev, "upload effect called: effect_type=%x\n", effect->type);
 	/* Check this effect type is supported by this device */
 	if (!test_bit(effect->type, dev->ffbit)) {
-		dev_dbg(&pid_private->hid->dev->dev, "invalid kind of effect requested.\n");
+		dev_dbg(&pid_private->hid->dev->dev,
+			"invalid kind of effect requested.\n");
 		return -EINVAL;
 	}
 
@@ -190,31 +181,30 @@
 	 * If we want to create a new effect, get a free id
 	 */
 	if (effect->id == -1) {
-		int id=0;
+		int id = 0;
 
 		// Spinlock so we don`t get a race condition when choosing IDs
 		spin_lock_irqsave(&pid_private->lock, flags);
 
-		while(id < FF_EFFECTS_MAX)
-			if (!test_and_set_bit(FF_PID_FLAGS_USED, &pid_private->effects[id++].flags)) 
-			    break;
+		while (id < FF_EFFECTS_MAX)
+			if (!test_and_set_bit(FF_PID_FLAGS_USED, &pid_private->effects[id++].flags))
+				break;
 
-		if ( id == FF_EFFECTS_MAX) {
-			spin_unlock_irqrestore(&pid_private->lock,flags);
+		if (id == FF_EFFECTS_MAX) {
+			spin_unlock_irqrestore(&pid_private->lock, flags);
 // TEMP - We need to get ff_effects_max correctly first:  || id >= dev->ff_effects_max) {
 			dev_dbg(&pid_private->hid->dev->dev, "Not enough device memory\n");
 			return -ENOMEM;
 		}
 
 		effect->id = id;
-		dev_dbg(&pid_private->hid->dev->dev, "effect ID is %d\n.",id);
+		dev_dbg(&pid_private->hid->dev->dev, "effect ID is %d\n.", id);
 		pid_private->effects[id].owner = current->pid;
-		pid_private->effects[id].flags = (1<<FF_PID_FLAGS_USED);
-		spin_unlock_irqrestore(&pid_private->lock,flags);
+		pid_private->effects[id].flags = (1 << FF_PID_FLAGS_USED);
+		spin_unlock_irqrestore(&pid_private->lock, flags);
 
 		is_update = FF_PID_FALSE;
-	}
-	else {
+	} else {
 		/* We want to update an effect */
 		if (!CHECK_OWNERSHIP(effect->id, pid_private))
 			return -EACCES;
@@ -224,9 +214,8 @@
 			return -EINVAL;
 
 		/* Check the effect is not already being updated */
-		if (test_bit(FF_PID_FLAGS_UPDATING, &pid_private->effects[effect->id].flags)) {
+		if (test_bit(FF_PID_FLAGS_UPDATING, &pid_private->effects[effect->id].flags))
 			return -EAGAIN;
-		}
 
 		is_update = FF_PID_TRUE;
 	}
@@ -235,28 +224,30 @@
 	 * Upload the effect
 	 */
 	switch (effect->type) {
-		case FF_PERIODIC:
-			ret = pid_upload_periodic(pid_private, effect, is_update);
-			break;
-
-		case FF_CONSTANT:
-			ret = pid_upload_constant(pid_private, effect, is_update);
-			break;
-
-		case FF_SPRING:
-		case FF_FRICTION:
-		case FF_DAMPER:
-		case FF_INERTIA:
-			ret = pid_upload_condition(pid_private, effect, is_update);
-			break;
-
-		case FF_RAMP:
-			ret = pid_upload_ramp(pid_private, effect, is_update);
-			break;
-
-		default:
-			dev_dbg(&pid_private->hid->dev->dev, "invalid type of effect requested - %x.\n", effect->type);
-			return -EINVAL;
+	case FF_PERIODIC:
+		ret = pid_upload_periodic(pid_private, effect, is_update);
+		break;
+
+	case FF_CONSTANT:
+		ret = pid_upload_constant(pid_private, effect, is_update);
+		break;
+
+	case FF_SPRING:
+	case FF_FRICTION:
+	case FF_DAMPER:
+	case FF_INERTIA:
+		ret = pid_upload_condition(pid_private, effect, is_update);
+		break;
+
+	case FF_RAMP:
+		ret = pid_upload_ramp(pid_private, effect, is_update);
+		break;
+
+	default:
+		dev_dbg(&pid_private->hid->dev->dev,
+			"invalid type of effect requested - %x.\n",
+			effect->type);
+		return -EINVAL;
 	}
 	/* If a packet was sent, forbid new updates until we are notified
 	 * that the packet was updated
@@ -269,37 +260,36 @@
 
 int hid_pid_init(struct hid_device *hid)
 {
-    struct hid_ff_pid *private;
-    struct hid_input *hidinput = list_entry(&hid->inputs, struct hid_input, list);
+	struct hid_ff_pid *private;
+	struct hid_input *hidinput = list_entry(&hid->inputs, struct hid_input, list);
 
-    private = hid->ff_private = kmalloc(sizeof(struct hid_ff_pid), GFP_KERNEL);
-    if (!private) return -1;
-    
-    memset(private,0,sizeof(struct hid_ff_pid));
-
-    hid->ff_private = private; /* 'cause memset can move the block away */
-
-    private->hid = hid;
-    
-    hid->ff_exit = hid_pid_exit;
-    hid->ff_event = hid_pid_event;
-    
-    /* Open output URB */
-    if (!(private->urbffout = usb_alloc_urb(0, GFP_KERNEL))) {
-	kfree(private);
-	return -1;
-    }
-
-    usb_fill_control_urb(private->urbffout, hid->dev,0,(void *) &private->ffcr,private->ctrl_buffer,8,hid_pid_ctrl_out,hid);
-    hidinput->input.upload_effect = hid_pid_upload_effect;
-    hidinput->input.flush = hid_pid_flush;
-    hidinput->input.ff_effects_max = 8;  // A random default
-    set_bit(EV_FF, hidinput->input.evbit);
-    set_bit(EV_FF_STATUS, hidinput->input.evbit);
-
-    spin_lock_init(&private->lock);
-
-    printk(KERN_INFO "Force feedback driver for PID devices by Rodrigo Damazio <rdamazio@lsi.usp.br>.\n");
-    
-    return 0;    
+	private = hid->ff_private = kcalloc(1, sizeof(struct hid_ff_pid), GFP_KERNEL);
+	if (!private)
+		return -ENOMEM;
+
+	private->hid = hid;
+
+	hid->ff_exit = hid_pid_exit;
+	hid->ff_event = hid_pid_event;
+
+	/* Open output URB */
+	if (!(private->urbffout = usb_alloc_urb(0, GFP_KERNEL))) {
+		kfree(private);
+		return -1;
+	}
+
+	usb_fill_control_urb(private->urbffout, hid->dev, 0,
+			     (void *)&private->ffcr, private->ctrl_buffer, 8,
+			     hid_pid_ctrl_out, hid);
+	hidinput->input.upload_effect = hid_pid_upload_effect;
+	hidinput->input.flush = hid_pid_flush;
+	hidinput->input.ff_effects_max = 8;	// A random default
+	set_bit(EV_FF, hidinput->input.evbit);
+	set_bit(EV_FF_STATUS, hidinput->input.evbit);
+
+	spin_lock_init(&private->lock);
+
+	printk(KERN_INFO "Force feedback driver for PID devices by Rodrigo Damazio <rdamazio@lsi.usp.br>.\n");
+
+	return 0;
 }
diff -Nru a/drivers/usb/input/pid.h b/drivers/usb/input/pid.h
--- a/drivers/usb/input/pid.h	2005-03-11 12:51:41 -08:00
+++ b/drivers/usb/input/pid.h	2005-03-11 12:51:41 -08:00
@@ -25,31 +25,31 @@
 
 #define FF_EFFECTS_MAX 64
 
-#define FF_PID_FLAGS_USED	1  /* If the effect exists */
-#define FF_PID_FLAGS_UPDATING	2  /* If the effect is being updated */
-#define FF_PID_FLAGS_PLAYING	3  /* If the effect is currently being played */
+#define FF_PID_FLAGS_USED	1	/* If the effect exists */
+#define FF_PID_FLAGS_UPDATING	2	/* If the effect is being updated */
+#define FF_PID_FLAGS_PLAYING	3	/* If the effect is currently being played */
 
 #define FF_PID_FALSE	0
 #define FF_PID_TRUE	1
 
 struct hid_pid_effect {
-    unsigned long flags;
-    pid_t owner;
-    unsigned int device_id;  // The device-assigned ID
-    struct ff_effect effect;
+	unsigned long flags;
+	pid_t owner;
+	unsigned int device_id;	/* The device-assigned ID */
+	struct ff_effect effect;
 };
 
 struct hid_ff_pid {
-    struct hid_device *hid;
-    unsigned long int gain;
+	struct hid_device *hid;
+	unsigned long gain;
 
-    struct urb *urbffout;
-    struct usb_ctrlrequest ffcr;
-    spinlock_t lock;
+	struct urb *urbffout;
+	struct usb_ctrlrequest ffcr;
+	spinlock_t lock;
 
-    char ctrl_buffer[8];
+	unsigned char ctrl_buffer[8];
 
-    struct hid_pid_effect effects[FF_EFFECTS_MAX];
+	struct hid_pid_effect effects[FF_EFFECTS_MAX];
 };
 
 /*
diff -Nru a/drivers/usb/input/powermate.c b/drivers/usb/input/powermate.c
--- a/drivers/usb/input/powermate.c	2005-03-11 12:51:47 -08:00
+++ b/drivers/usb/input/powermate.c	2005-03-11 12:51:47 -08:00
@@ -320,7 +320,7 @@
 	usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
 		0x0a, USB_TYPE_CLASS | USB_RECIP_INTERFACE,
 		0, interface->desc.bInterfaceNumber, NULL, 0,
-		HZ * USB_CTRL_SET_TIMEOUT);
+		USB_CTRL_SET_TIMEOUT);
 
 	if (!(pm = kmalloc(sizeof(struct powermate_device), GFP_KERNEL)))
 		return -ENOMEM;
@@ -395,6 +395,7 @@
 	pm->input.id.version = le16_to_cpu(udev->descriptor.bcdDevice);
 	pm->input.event = powermate_input_event;
 	pm->input.dev = &intf->dev;
+	pm->input.phys = pm->phys;
 
 	input_register_device(&pm->input);
 
diff -Nru a/drivers/usb/input/touchkitusb.c b/drivers/usb/input/touchkitusb.c
--- a/drivers/usb/input/touchkitusb.c	2005-03-11 12:51:41 -08:00
+++ b/drivers/usb/input/touchkitusb.c	2005-03-11 12:51:41 -08:00
@@ -184,7 +184,6 @@
 	struct usb_endpoint_descriptor *endpoint;
 	struct usb_device *udev = interface_to_usbdev(intf);
 	char path[64];
-	char *buf;
 
 	interface = intf->cur_altsetting;
 	endpoint = &interface->endpoint[0].desc;
@@ -230,24 +229,14 @@
 	touchkit->input.absfuzz[ABS_Y] = TOUCHKIT_YC_FUZZ;
 	touchkit->input.absflat[ABS_Y] = TOUCHKIT_YC_FLAT;
 
-	buf = kmalloc(63, GFP_KERNEL);
-	if (!buf) {
-		ret = -ENOMEM;
-		goto out_free_buffers;
-	}
-
-	if (udev->descriptor.iManufacturer &&
-	    usb_string(udev, udev->descriptor.iManufacturer, buf, 63) > 0)
-		strcat(touchkit->name, buf);
-	if (udev->descriptor.iProduct &&
-	    usb_string(udev, udev->descriptor.iProduct, buf, 63) > 0)
-		sprintf(touchkit->name, "%s %s", touchkit->name, buf);
+	if (udev->manufacturer)
+		strcat(touchkit->name, udev->manufacturer);
+	if (udev->product)
+		sprintf(touchkit->name, "%s %s", touchkit->name, udev->product);
 
 	if (!strlen(touchkit->name))
 		sprintf(touchkit->name, "USB Touchscreen %04x:%04x",
 		        touchkit->input.id.vendor, touchkit->input.id.product);
-
-	kfree(buf);
 
 	touchkit->irq = usb_alloc_urb(0, GFP_KERNEL);
 	if (!touchkit->irq) {
diff -Nru a/drivers/usb/input/usbkbd.c b/drivers/usb/input/usbkbd.c
--- a/drivers/usb/input/usbkbd.c	2005-03-11 12:51:51 -08:00
+++ b/drivers/usb/input/usbkbd.c	2005-03-11 12:51:51 -08:00
@@ -238,7 +238,6 @@
 	struct usb_kbd *kbd;
 	int i, pipe, maxp;
 	char path[64];
-	char *buf;
 
 	interface = iface->cur_altsetting;
 
@@ -301,25 +300,14 @@
 	kbd->dev.id.version = le16_to_cpu(dev->descriptor.bcdDevice);
 	kbd->dev.dev = &iface->dev;
 
-	if (!(buf = kmalloc(63, GFP_KERNEL))) {
-		usb_free_urb(kbd->irq);
-		usb_kbd_free_mem(dev, kbd);
-		kfree(kbd);
-		return -ENOMEM;
-	}
-
-	if (dev->descriptor.iManufacturer &&
-		usb_string(dev, dev->descriptor.iManufacturer, buf, 63) > 0)
-			strcat(kbd->name, buf);
-	if (dev->descriptor.iProduct &&
-		usb_string(dev, dev->descriptor.iProduct, buf, 63) > 0)
-			sprintf(kbd->name, "%s %s", kbd->name, buf);
+	if (dev->manufacturer)
+		strcat(kbd->name, dev->manufacturer);
+	if (dev->product)
+		sprintf(kbd->name, "%s %s", kbd->name, dev->product);
 
 	if (!strlen(kbd->name))
 		sprintf(kbd->name, "USB HIDBP Keyboard %04x:%04x",
 			kbd->dev.id.vendor, kbd->dev.id.product);
-
-	kfree(buf);
 
 	usb_fill_control_urb(kbd->led, dev, usb_sndctrlpipe(dev, 0),
 			     (void *) kbd->cr, kbd->leds, 1,
diff -Nru a/drivers/usb/input/usbmouse.c b/drivers/usb/input/usbmouse.c
--- a/drivers/usb/input/usbmouse.c	2005-03-11 12:51:51 -08:00
+++ b/drivers/usb/input/usbmouse.c	2005-03-11 12:51:51 -08:00
@@ -129,7 +129,6 @@
 	struct usb_mouse *mouse;
 	int pipe, maxp;
 	char path[64];
-	char *buf;
 
 	interface = intf->cur_altsetting;
 
@@ -185,24 +184,14 @@
 	mouse->dev.id.version = le16_to_cpu(dev->descriptor.bcdDevice);
 	mouse->dev.dev = &intf->dev;
 
-	if (!(buf = kmalloc(63, GFP_KERNEL))) {
-		usb_buffer_free(dev, 8, mouse->data, mouse->data_dma);
-		kfree(mouse);
-		return -ENOMEM;
-	}
-
-	if (dev->descriptor.iManufacturer &&
-		usb_string(dev, dev->descriptor.iManufacturer, buf, 63) > 0)
-			strcat(mouse->name, buf);
-	if (dev->descriptor.iProduct &&
-		usb_string(dev, dev->descriptor.iProduct, buf, 63) > 0)
-			sprintf(mouse->name, "%s %s", mouse->name, buf);
+	if (dev->manufacturer)
+		strcat(mouse->name, dev->manufacturer);
+	if (dev->product)
+		sprintf(mouse->name, "%s %s", mouse->name, dev->product);
 
 	if (!strlen(mouse->name))
 		sprintf(mouse->name, "USB HIDBP Mouse %04x:%04x",
 			mouse->dev.id.vendor, mouse->dev.id.product);
-
-	kfree(buf);
 
 	usb_fill_int_urb(mouse->irq, dev, pipe, mouse->data,
 			 (maxp > 8 ? 8 : maxp),
diff -Nru a/drivers/usb/input/wacom.c b/drivers/usb/input/wacom.c
--- a/drivers/usb/input/wacom.c	2005-03-11 12:51:41 -08:00
+++ b/drivers/usb/input/wacom.c	2005-03-11 12:51:41 -08:00
@@ -72,7 +72,7 @@
 /*
  * Version Information
  */
-#define DRIVER_VERSION "v1.30"
+#define DRIVER_VERSION "v1.40"
 #define DRIVER_AUTHOR "Vojtech Pavlik <vojtech@ucw.cz>"
 #define DRIVER_DESC "USB Wacom Graphire and Wacom Intuos tablet driver"
 #define DRIVER_LICENSE "GPL"
@@ -115,7 +115,7 @@
 		usb_sndctrlpipe(interface_to_usbdev(intf), 0),
                 USB_REQ_SET_REPORT, USB_TYPE_CLASS | USB_RECIP_INTERFACE,
                 (type << 8) + id, intf->altsetting[0].desc.bInterfaceNumber,
-		buf, size, HZ);
+		buf, size, 1000);
 }
 
 static void wacom_pl_irq(struct urb *urb, struct pt_regs *regs)
@@ -141,8 +141,10 @@
 		goto exit;
 	}
 
-	if (data[0] != 2)
+	if (data[0] != 2) {
 		dbg("wacom_pl_irq: received unknown report #%d", data[0]);
+		goto exit;
+	}
 
 	prox = data[1] & 0x40;
 
@@ -233,6 +235,7 @@
 	if (data[0] != 2)
 	{
 		printk(KERN_INFO "wacom_ptu_irq: received unknown report #%d\n", data[0]);
+		goto exit;
 	}
 
 	input_regs(dev, regs);
@@ -246,9 +249,9 @@
 		input_report_key(dev, BTN_TOOL_PEN, data[1] & 0x20);
 		input_report_key(dev, BTN_TOUCH, data[1] & 0x01);
 	}
-	input_report_abs(dev, ABS_X, data[3] << 8 | data[2]);
-	input_report_abs(dev, ABS_Y, data[5] << 8 | data[4]);
-	input_report_abs(dev, ABS_PRESSURE, (data[6]|data[7] << 8));
+	input_report_abs(dev, ABS_X, le16_to_cpu(*(__le16 *) &data[2]));
+	input_report_abs(dev, ABS_Y, le16_to_cpu(*(__le16 *) &data[4]));
+	input_report_abs(dev, ABS_PRESSURE, le16_to_cpu(*(__le16 *) &data[6]));
 	input_report_key(dev, BTN_STYLUS, data[1] & 0x02);
 	input_report_key(dev, BTN_STYLUS2, data[1] & 0x10);
 
@@ -283,10 +286,15 @@
 		goto exit;
 	}
 
+	if (data[0] != 2) {
+		printk(KERN_INFO "wacom_penpartner_irq: received unknown report #%d\n", data[0]);
+		goto exit;
+	}
+
 	input_regs(dev, regs);
 	input_report_key(dev, BTN_TOOL_PEN, 1);
-	input_report_abs(dev, ABS_X, le16_to_cpu(get_unaligned((__le16 *) &data[1])));
-	input_report_abs(dev, ABS_Y, le16_to_cpu(get_unaligned((__le16 *) &data[3])));
+	input_report_abs(dev, ABS_X, le16_to_cpu(*(__le16 *) &data[1]));
+	input_report_abs(dev, ABS_Y, le16_to_cpu(*(__le16 *) &data[3]));
 	input_report_abs(dev, ABS_PRESSURE, (signed char)data[6] + 127);
 	input_report_key(dev, BTN_TOUCH, ((signed char)data[6] > -80) && !(data[5] & 0x20));
 	input_report_key(dev, BTN_STYLUS, (data[5] & 0x40));
@@ -322,12 +330,10 @@
 		goto exit;
 	}
 
-	/* check if we can handle the data */
-	if (data[0] == 99)
-		goto exit;
-
-	if (data[0] != 2)
+	if (data[0] != 2) {
 		dbg("wacom_graphire_irq: received unknown report #%d", data[0]);
+		goto exit;
+	}
 
 	x = le16_to_cpu(*(__le16 *) &data[2]);
 	y = le16_to_cpu(*(__le16 *) &data[4]);
@@ -381,107 +387,171 @@
 		     __FUNCTION__, retval);
 }
 
-static void wacom_intuos_irq(struct urb *urb, struct pt_regs *regs)
+static int wacom_intuos_inout(struct urb *urb)
 {
 	struct wacom *wacom = urb->context;
 	unsigned char *data = wacom->data;
 	struct input_dev *dev = &wacom->dev;
-	unsigned int t;
 	int idx;
-	int retval;
-
-	switch (urb->status) {
-	case 0:
-		/* success */
-		break;
-	case -ECONNRESET:
-	case -ENOENT:
-	case -ESHUTDOWN:
-		/* this urb is terminated, clean up */
-		dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status);
-		return;
-	default:
-		dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status);
-		goto exit;
-	}
-
-	if (data[0] != 2)
-		dbg("wacom_intuos_irq: received unknown report #%d", data[0]);
-
-	input_regs(dev, regs);
 
 	/* tool number */
 	idx = data[1] & 0x01;
 
-	if ((data[1] & 0xfc) == 0xc0) {						/* Enter report */
-
-		wacom->serial[idx] = ((__u32)(data[3] & 0x0f) << 28) +		/* serial number of the tool */
+	/* Enter report */
+	if ((data[1] & 0xfc) == 0xc0)
+	{
+		/* serial number of the tool */
+		wacom->serial[idx] = ((__u32)(data[3] & 0x0f) << 28) +
 			((__u32)data[4] << 20) + ((__u32)data[5] << 12) +
 			((__u32)data[6] << 4) + (data[7] >> 4);
 
 		switch (((__u32)data[2] << 4) | (data[3] >> 4)) {
-			case 0x812:
-			case 0x012: wacom->tool[idx] = BTN_TOOL_PENCIL;		break;	/* Inking pen */
-			case 0x822:
+			case 0x812: /* Inking pen */
+			case 0x801: /* Intuos3 Inking pen */
+			case 0x012:
+				wacom->tool[idx] = BTN_TOOL_PENCIL;
+				break;
+			case 0x822: /* Pen */
 			case 0x842:
 			case 0x852:
-			case 0x022: wacom->tool[idx] = BTN_TOOL_PEN;		break;	/* Pen */
-			case 0x832:
-			case 0x032: wacom->tool[idx] = BTN_TOOL_BRUSH;		break;	/* Stroke pen */
-			case 0x007:
+			case 0x823: /* Intuos3 Grip Pen */
+			case 0x813: /* Intuos3 Classic Pen */
+			case 0x885: /* Intuos3 Marker Pen */
+			case 0x022:
+				wacom->tool[idx] = BTN_TOOL_PEN;
+				break;
+			case 0x832: /* Stroke pen */
+			case 0x032:
+				wacom->tool[idx] = BTN_TOOL_BRUSH;
+				break;
+			case 0x007: /* Mouse 4D and 2D */
 		        case 0x09c:
-			case 0x094: wacom->tool[idx] = BTN_TOOL_MOUSE;		break;	/* Mouse 4D and 2D */
-			case 0x096: wacom->tool[idx] = BTN_TOOL_LENS;		break;	/* Lens cursor */
-			case 0x82a:
+			case 0x094:
+			case 0x017: /* Intuos3 2D Mouse */
+				wacom->tool[idx] = BTN_TOOL_MOUSE;
+				break;
+			case 0x096: /* Lens cursor */
+			case 0x097: /* Intuos3 Lens cursor */
+				wacom->tool[idx] = BTN_TOOL_LENS;
+				break;
+			case 0x82a: /* Eraser */
 			case 0x85a:
 		        case 0x91a:
 			case 0xd1a:
-			case 0x0fa: wacom->tool[idx] = BTN_TOOL_RUBBER;		break;	/* Eraser */
+			case 0x0fa:
+			case 0x82b: /* Intuos3 Grip Pen Eraser */
+			case 0x81b: /* Intuos3 Classic Pen Eraser */
+			case 0x91b: /* Intuos3 Airbrush Eraser */
+				wacom->tool[idx] = BTN_TOOL_RUBBER;
+				break;
 			case 0xd12:
 			case 0x912:
-			case 0x112: wacom->tool[idx] = BTN_TOOL_AIRBRUSH;	break;	/* Airbrush */
-			default:    wacom->tool[idx] = BTN_TOOL_PEN;		break;	/* Unknown tool */
+			case 0x112:
+			case 0x913: /* Intuos3 Airbrush */
+				wacom->tool[idx] = BTN_TOOL_AIRBRUSH;
+				break;	/* Airbrush */
+			default: /* Unknown tool */
+				wacom->tool[idx] = BTN_TOOL_PEN;
 		}
-
 		input_report_key(dev, wacom->tool[idx], 1);
 		input_event(dev, EV_MSC, MSC_SERIAL, wacom->serial[idx]);
 		input_sync(dev);
-		goto exit;
+		return 1;
 	}
 
-	if ((data[1] & 0xfe) == 0x80) {						/* Exit report */
+	/* Exit report */
+	if ((data[1] & 0xfe) == 0x80) {
 		input_report_key(dev, wacom->tool[idx], 0);
 		input_event(dev, EV_MSC, MSC_SERIAL, wacom->serial[idx]);
 		input_sync(dev);
-		goto exit;
+		return 1;
 	}
 
-	input_report_abs(dev, ABS_X, be16_to_cpu(*(__be16 *) &data[2]));
-	input_report_abs(dev, ABS_Y, be16_to_cpu(*(__be16 *) &data[4]));
-	input_report_abs(dev, ABS_DISTANCE, data[9]);
+	return 0;
+}
 
-	if ((data[1] & 0xb8) == 0xa0) {						/* general pen packet */
-		input_report_abs(dev, ABS_PRESSURE, t = ((__u32)data[6] << 2) | ((data[7] >> 6) & 3));
-		input_report_abs(dev, ABS_TILT_X, ((data[7] << 1) & 0x7e) | (data[8] >> 7));
+static void wacom_intuos_general(struct urb *urb)
+{
+	struct wacom *wacom = urb->context;
+	unsigned char *data = wacom->data;
+	struct input_dev *dev = &wacom->dev;
+	unsigned int t;
+
+	/* general pen packet */
+	if ((data[1] & 0xb8) == 0xa0)
+	{
+		t = ((__u32)data[6] << 2) | ((data[7] >> 6) & 3);
+		input_report_abs(dev, ABS_PRESSURE, t);
+		input_report_abs(dev, ABS_TILT_X,
+				((data[7] << 1) & 0x7e) | (data[8] >> 7));
 		input_report_abs(dev, ABS_TILT_Y, data[8] & 0x7f);
 		input_report_key(dev, BTN_STYLUS, data[1] & 2);
 		input_report_key(dev, BTN_STYLUS2, data[1] & 4);
 		input_report_key(dev, BTN_TOUCH, t > 10);
 	}
 
-	if ((data[1] & 0xbc) == 0xb4) {						/* airbrush second packet */
-		input_report_abs(dev, ABS_WHEEL, ((__u32)data[6] << 2) | ((data[7] >> 6) & 3));
-		input_report_abs(dev, ABS_TILT_X, ((data[7] << 1) & 0x7e) | (data[8] >> 7));
+	/* airbrush second packet */
+	if ((data[1] & 0xbc) == 0xb4)
+	{
+		input_report_abs(dev, ABS_WHEEL,
+				((__u32)data[6] << 2) | ((data[7] >> 6) & 3));
+		input_report_abs(dev, ABS_TILT_X,
+				((data[7] << 1) & 0x7e) | (data[8] >> 7));
 		input_report_abs(dev, ABS_TILT_Y, data[8] & 0x7f);
 	}
+	return;
+}
+
+static void wacom_intuos_irq(struct urb *urb, struct pt_regs *regs)
+{
+	struct wacom *wacom = urb->context;
+	unsigned char *data = wacom->data;
+	struct input_dev *dev = &wacom->dev;
+	unsigned int t;
+	int idx;
+	int retval;
+
+	switch (urb->status) {
+	case 0:
+		/* success */
+		break;
+	case -ECONNRESET:
+	case -ENOENT:
+	case -ESHUTDOWN:
+		/* this urb is terminated, clean up */
+		dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status);
+		return;
+	default:
+		dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status);
+		goto exit;
+	}
+
+	if (data[0] != 2 && data[0] != 5 && data[0] != 6) {
+		dbg("wacom_intuos_irq: received unknown report #%d", data[0]);
+		goto exit;
+	}
+
+	input_regs(dev, regs);
+
+	/* tool number */
+	idx = data[1] & 0x01;
+
+	/* process in/out prox events */
+	if (wacom_intuos_inout(urb)) goto exit;
+
+	input_report_abs(dev, ABS_X, be16_to_cpu(*(__be16 *) &data[2]));
+	input_report_abs(dev, ABS_Y, be16_to_cpu(*(__be16 *) &data[4]));
+	input_report_abs(dev, ABS_DISTANCE, data[9]);
+
+	/* process general packets */
+	wacom_intuos_general(urb);
 	
 	if ((data[1] & 0xbc) == 0xa8 || (data[1] & 0xbe) == 0xb0) {		/* 4D mouse or Lens cursor packets */
 
 		if (data[1] & 0x02) {						/* Rotation packet */
 
-			input_report_abs(dev, ABS_RZ, (data[7] & 0x20) ?
-					 ((__u32)data[6] << 3) | ((data[7] >> 5) & 7):
-					 (-(((__u32)data[6] << 3) | ((data[7] >> 5) & 7))) - 1);
+			t = ((__u32)data[6] << 3) | ((data[7] >> 5) & 7);
+			input_report_abs(dev, ABS_RZ, (data[7] & 0x20) ? ((t - 1) / 2) : -t / 2);
 
 		} else {
 
@@ -493,9 +563,8 @@
 
 				input_report_key(dev, BTN_SIDE,   data[8] & 0x20);
 				input_report_key(dev, BTN_EXTRA,  data[8] & 0x10);
-				input_report_abs(dev, ABS_THROTTLE,  -((data[8] & 0x08) ?
-						 ((__u32)data[6] << 2) | ((data[7] >> 6) & 3) :
-						 -((__u32)data[6] << 2) | ((data[7] >> 6) & 3)));
+				t = ((__u32)data[6] << 2) | ((data[7] >> 6) & 3);
+				input_report_abs(dev, ABS_THROTTLE, (data[8] & 0x08) ? -t : t);
 
 			} else {
 				if (wacom->tool[idx] == BTN_TOOL_MOUSE) {	/* 2D mouse packets */	
@@ -527,6 +596,111 @@
 		     __FUNCTION__, retval);
 }
 
+static void wacom_intuos3_irq(struct urb *urb, struct pt_regs *regs)
+{
+	struct wacom *wacom = urb->context;
+	unsigned char *data = wacom->data;
+	struct input_dev *dev = &wacom->dev;
+	unsigned int t;
+	int idx, retval;
+
+	switch (urb->status) {
+	case 0:
+		/* success */
+		break;
+	case -ECONNRESET:
+	case -ENOENT:
+	case -ESHUTDOWN:
+		/* this urb is terminated, clean up */
+		dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status);
+		return;
+	default:
+		dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status);
+		goto exit;
+	}
+
+	/* check for valid report */
+	if (data[0] != 2 && data[0] != 5 && data[0] != 12)
+	{
+		printk(KERN_INFO "wacom_intuos3_irq: received unknown report #%d\n", data[0]);
+		goto exit;
+	}
+
+	input_regs(dev, regs);
+
+	/* tool index is always 0 here since there is no dual input tool */
+	idx = data[1] & 0x01;
+
+	/* pad packets. Works as a second tool and is always in prox */
+	if (data[0] == 12)
+	{
+		/* initiate the pad as a device */
+		if (wacom->tool[1] != BTN_TOOL_FINGER)
+		{
+			wacom->tool[1] = BTN_TOOL_FINGER;
+			input_report_key(dev, wacom->tool[1], 1);
+		}
+		input_report_key(dev, BTN_0, (data[5] & 0x01));
+		input_report_key(dev, BTN_1, (data[5] & 0x02));
+		input_report_key(dev, BTN_2, (data[5] & 0x04));
+		input_report_key(dev, BTN_3, (data[5] & 0x08));
+		input_report_key(dev, BTN_4, (data[6] & 0x01));
+		input_report_key(dev, BTN_5, (data[6] & 0x02));
+		input_report_key(dev, BTN_6, (data[6] & 0x04));
+		input_report_key(dev, BTN_7, (data[6] & 0x08));
+		input_report_abs(dev, ABS_RX, ((data[1] & 0x1f) << 8) | data[2]);
+		input_report_abs(dev, ABS_RY, ((data[3] & 0x1f) << 8) | data[4]);
+		input_event(dev, EV_MSC, MSC_SERIAL, 0xffffffff);
+		input_sync(dev);
+		goto exit;
+	}
+
+	/* process in/out prox events */
+	if (wacom_intuos_inout(urb)) goto exit;
+
+	input_report_abs(dev, ABS_X, ((__u32)data[2] << 9) | ((__u32)data[3] << 1) | ((data[9] >> 1) & 1));
+	input_report_abs(dev, ABS_Y, ((__u32)data[4] << 9) | ((__u32)data[5] << 1) | (data[9] & 1));
+	input_report_abs(dev, ABS_DISTANCE, ((data[9] >> 2) & 0x3f));
+
+	/* process general packets */
+	wacom_intuos_general(urb);
+
+	if ((data[1] & 0xbc) == 0xa8 || (data[1] & 0xbe) == 0xb0)
+	{
+		/* Marker pen rotation packet. Reported as wheel due to valuator limitation */
+		if (data[1] & 0x02)
+		{
+			t = ((__u32)data[6] << 3) | ((data[7] >> 5) & 7);
+			t = (data[7] & 0x20) ? ((t > 900) ? ((t-1) / 2 - 1350) :
+				((t-1) / 2 + 450)) : (450 - t / 2) ;
+			input_report_abs(dev, ABS_WHEEL, t);
+		}
+
+		/* 2D mouse packets */
+		if (wacom->tool[idx] == BTN_TOOL_MOUSE)
+		{
+			input_report_key(dev, BTN_LEFT,   data[8] & 0x04);
+			input_report_key(dev, BTN_MIDDLE, data[8] & 0x08);
+			input_report_key(dev, BTN_RIGHT,  data[8] & 0x10);
+			input_report_key(dev, BTN_SIDE,   data[8] & 0x40);
+			input_report_key(dev, BTN_EXTRA,  data[8] & 0x20);
+			/* mouse wheel is positive when rolled backwards */
+			input_report_rel(dev, REL_WHEEL,  ((__u32)((data[8] & 0x02) >> 1)
+					 - (__u32)(data[8] & 0x01)));
+		}
+	}
+
+	input_report_key(dev, wacom->tool[idx], 1);
+	input_event(dev, EV_MSC, MSC_SERIAL, wacom->serial[idx]);
+	input_sync(dev);
+
+exit:
+	retval = usb_submit_urb (urb, GFP_ATOMIC);
+	if (retval)
+		err ("%s - usb_submit_urb failed with result %d",
+		    __FUNCTION__, retval);
+}
+
 static struct wacom_features wacom_features[] = {
 	{ "Wacom Penpartner",    7,   5040,  3780,  255, 32, 0, wacom_penpartner_irq },
         { "Wacom Graphire",      8,  10206,  7422,  511, 32, 1, wacom_graphire_irq },
@@ -552,6 +726,9 @@
 	{ "Wacom Intuos2 12x18", 10, 45720, 31680, 1023, 15, 2, wacom_intuos_irq },
 	{ "Wacom Volito",        8,   5104,  3712,  511, 32, 1, wacom_graphire_irq },
 	{ "Wacom Cintiq Partner",8,  20480, 15360,  511, 32, 3, wacom_ptu_irq },
+	{ "Wacom Intuos3 4x5",   10, 25400, 20320, 1023, 15, 4, wacom_intuos3_irq },
+	{ "Wacom Intuos3 6x8",   10, 40640, 30480, 1023, 15, 4, wacom_intuos3_irq },
+	{ "Wacom Intuos3 9x12",  10, 60960, 45720, 1023, 15, 4, wacom_intuos3_irq },
 	{ "Wacom Intuos2 6x8",   10, 20320, 16240, 1023, 15, 2, wacom_intuos_irq },
  	{ }
 };
@@ -581,6 +758,9 @@
 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x45) },
 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x60) },
 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x03) },
+	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB0) },
+	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB1) },
+	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0xB2) },
 	{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x47) },
 	{ }
 };
@@ -651,6 +831,12 @@
  			wacom->dev.keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_RUBBER) | BIT(BTN_TOOL_MOUSE) | BIT(BTN_STYLUS2);
 			break;
 
+		case 4: /* new functions for Intuos3 */
+			wacom->dev.keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_FINGER);
+			wacom->dev.keybit[LONG(BTN_LEFT)] |= BIT(BTN_0) | BIT(BTN_1) | BIT(BTN_2) | BIT(BTN_3) | BIT(BTN_4) | BIT(BTN_5) | BIT(BTN_6) | BIT(BTN_7);
+			wacom->dev.absbit[0] |= BIT(ABS_RX) | BIT(ABS_RY);
+			/* fall through */
+
 		case 2:
 			wacom->dev.evbit[0] |= BIT(EV_MSC) | BIT(EV_REL);
 			wacom->dev.mscbit[0] |= BIT(MSC_SERIAL);
@@ -662,7 +848,7 @@
 			break;
 
 		case 3:
- 			wacom->dev.keybit[LONG(BTN_DIGI)] |= BIT(BTN_STYLUS2);
+ 			wacom->dev.keybit[LONG(BTN_DIGI)] |= BIT(BTN_STYLUS2) | BIT(BTN_TOOL_RUBBER);
 			break;
 	}
 
@@ -674,6 +860,8 @@
 	wacom->dev.absmax[ABS_TILT_Y] = 127;
 	wacom->dev.absmax[ABS_WHEEL] = 1023;
 
+	wacom->dev.absmax[ABS_RX] = 4097;
+	wacom->dev.absmax[ABS_RY] = 4097;
 	wacom->dev.absmin[ABS_RZ] = -900;
 	wacom->dev.absmax[ABS_RZ] = 899;
 	wacom->dev.absmin[ABS_THROTTLE] = -1023;
@@ -712,9 +900,10 @@
 
 	input_register_device(&wacom->dev);
 
+	/* ask the tablet to report tablet data */
+	usb_set_report(intf, 3, 2, rep_data, 2);
+	/* repeat once (not sure why the first call often fails) */
 	usb_set_report(intf, 3, 2, rep_data, 2);
-	usb_set_report(intf, 3, 5, rep_data, 0);
-	usb_set_report(intf, 3, 6, rep_data, 0);
 
 	printk(KERN_INFO "input: %s on %s\n", wacom->features->name, path);
 
diff -Nru a/drivers/usb/media/Kconfig b/drivers/usb/media/Kconfig
--- a/drivers/usb/media/Kconfig	2005-03-11 12:51:40 -08:00
+++ b/drivers/usb/media/Kconfig	2005-03-11 12:51:40 -08:00
@@ -175,3 +175,39 @@
 
 	  To compile this driver as a module, choose M here: the
 	  module will be called w9968cf.
+
+config USB_PWC
+	tristate "USB Philips Cameras"
+	depends on USB && VIDEO_DEV
+	---help---
+	  Say Y or M here if you want to use one of these Philips & OEM
+          webcams:
+           * Philips PCA645, PCA646
+           * Philips PCVC675, PCVC680, PCVC690
+           * Philips PCVC720/40, PCVC730, PCVC740, PCVC750
+	   * Askey VC010
+	   * Logitech QuickCam Pro 3000, 4000, 'Zoom', 'Notebook Pro' 
+             and 'Orbit'/'Sphere'
+           * Samsung MPC-C10, MPC-C30
+	   * Creative Webcam 5, Pro Ex
+	   * SOTEC Afina Eye
+	   * Visionite VCS-UC300, VCS-UM100
+	   
+	  The PCA635, PCVC665 and PCVC720/20 are not supported by this driver
+	  and never will be, but the 665 and 720/20 are supported by other 
+	  drivers.
+
+	  See <file:Documentation/usb/philips.txt> for more information and
+	  installation instructions.
+
+	  The built-in microphone is enabled by selecting USB Audio support.
+
+	  This driver uses the Video For Linux API. You must say Y or M to
+	  "Video For Linux" (under Character Devices) to use this driver.
+	  Information on this API and pointers to "v4l" programs may be found
+	  at <file:Documentation/video4linux/API.html>.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called pwc.
+
+
diff -Nru a/drivers/usb/media/Makefile b/drivers/usb/media/Makefile
--- a/drivers/usb/media/Makefile	2005-03-11 12:51:40 -08:00
+++ b/drivers/usb/media/Makefile	2005-03-11 12:51:40 -08:00
@@ -14,3 +14,4 @@
 obj-$(CONFIG_USB_STV680)	+= stv680.o
 obj-$(CONFIG_USB_VICAM)		+= vicam.o usbvideo.o
 obj-$(CONFIG_USB_W9968CF)	+= w9968cf.o
+obj-$(CONFIG_USB_PWC)           += pwc/
diff -Nru a/drivers/usb/media/ibmcam.c b/drivers/usb/media/ibmcam.c
--- a/drivers/usb/media/ibmcam.c	2005-03-11 12:51:42 -08:00
+++ b/drivers/usb/media/ibmcam.c	2005-03-11 12:51:42 -08:00
@@ -1137,7 +1137,7 @@
 			index,
 			cp,
 			sizeof(cp),
-			HZ);
+			1000);
 #if 0
 		info("USB => %02x%02x%02x%02x%02x%02x%02x%02x "
 		       "(req=$%02x val=$%04x ind=$%04x)",
@@ -1154,7 +1154,7 @@
 			index,
 			NULL,
 			0,
-			HZ);
+			1000);
 	}
 	if (i < 0) {
 		err("%s: ERROR=%d. Camera stopped; Reconnect or reload driver.",
diff -Nru a/drivers/usb/media/konicawc.c b/drivers/usb/media/konicawc.c
--- a/drivers/usb/media/konicawc.c	2005-03-11 12:51:40 -08:00
+++ b/drivers/usb/media/konicawc.c	2005-03-11 12:51:40 -08:00
@@ -133,7 +133,7 @@
 {
         int retval = usb_control_msg(uvd->dev,
 		dir ? usb_rcvctrlpipe(uvd->dev, 0) : usb_sndctrlpipe(uvd->dev, 0),
-		    request, 0x40 | dir, value, index, buf, len, HZ);
+		    request, 0x40 | dir, value, index, buf, len, 1000);
         return retval < 0 ? retval : 0;
 }
 
diff -Nru a/drivers/usb/media/ov511.c b/drivers/usb/media/ov511.c
--- a/drivers/usb/media/ov511.c	2005-03-11 12:51:42 -08:00
+++ b/drivers/usb/media/ov511.c	2005-03-11 12:51:42 -08:00
@@ -383,7 +383,7 @@
 			     usb_sndctrlpipe(ov->dev, 0),
 			     (ov->bclass == BCL_OV518)?1:2 /* REG_IO */,
 			     USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-			     0, (__u16)reg, &ov->cbuf[0], 1, HZ);
+			     0, (__u16)reg, &ov->cbuf[0], 1, 1000);
 	up(&ov->cbuf_lock);
 
 	if (rc < 0)
@@ -404,7 +404,7 @@
 			     usb_rcvctrlpipe(ov->dev, 0),
 			     (ov->bclass == BCL_OV518)?1:3 /* REG_IO */,
 			     USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-			     0, (__u16)reg, &ov->cbuf[0], 1, HZ);
+			     0, (__u16)reg, &ov->cbuf[0], 1, 1000);
 
 	if (rc < 0) {
 		err("reg read: error %d: %s", rc, symbolic(urb_errlist, rc));
@@ -464,7 +464,7 @@
 			     usb_sndctrlpipe(ov->dev, 0),
 			     1 /* REG_IO */,
 			     USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-			     0, (__u16)reg, ov->cbuf, n, HZ);
+			     0, (__u16)reg, ov->cbuf, n, 1000);
 	up(&ov->cbuf_lock);
 
 	if (rc < 0)
diff -Nru a/drivers/usb/media/pwc/ChangeLog b/drivers/usb/media/pwc/ChangeLog
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/usb/media/pwc/ChangeLog	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,143 @@
+9.0.2
+
+* Adding #ifdef to compile PWC before and after 2.6.5
+
+9.0.1
+
+9.0
+
+
+8.12
+
+* Implement motorized pan/tilt feature for Logitech QuickCam Orbit/Spere.
+
+8.11.1
+
+* Fix for PCVC720/40, would not be able to set videomode
+* Fix for Samsung MPC models, appearantly they are based on a newer chipset
+
+8.11
+
+* 20 dev_hints (per request)
+* Hot unplugging should be better, no more dangling pointers or memory leaks
+* Added reserved Logitech webcam IDs
+* Device now remembers size & fps between close()/open()
+* Removed palette stuff altogether
+
+8.10.1
+
+* Added IDs for PCVC720K/40 and Creative Labs Webcam Pro
+
+8.10
+
+* Fixed ID for QuickCam Notebook pro
+* Added GREALSIZE ioctl() call
+* Fixed bug in case PWCX was not loaded and invalid size was set
+
+8.9
+
+* Merging with kernel 2.5.49
+* Adding IDs for QuickCam Zoom & QuickCam Notebook
+
+8.8
+
+* Fixing 'leds' parameter
+* Adding IDs for Logitech QuickCam Pro 4000
+* Making URB init/cleanup a little nicer
+
+8.7
+
+* Incorporating changes in ioctl() parameter passing
+* Also changes to URB mechanism
+
+8.6
+
+* Added ID's for Visionite VCS UM100 and UC300
+* Removed YUV420-interlaced palette altogether (was confusing)
+* Removed MIRROR stuff as it didn't work anyway
+* Fixed a problem with the 'leds' parameter (wouldn't blink)
+* Added ioctl()s for advanced features: 'extended' whitebalance ioctl()s,
+  CONTOUR, BACKLIGHT, FLICKER, DYNNOISE.
+* VIDIOCGCAP.name now contains real camera model name instead of
+  'Philips xxx webcam'
+* Added PROBE ioctl (see previous point & API doc)
+
+8.5
+
+* Adding IDs for Creative Labs Webcam 5
+* Adding IDs for SOTEC CMS-001 webcam
+* Solving possible hang in VIDIOCSYNC when unplugging the cam 
+* Forgot to return structure in VIDIOCPWCGAWB, oops
+* Time interval for the LEDs are now in milliseconds
+
+8.4
+
+* Fixing power_save option for Vesta range
+* Handling new error codes in ISOC callback
+* Adding dev_hint module parameter, to specify /dev/videoX device nodes
+
+8.3
+
+* Adding Samsung C10 and C30 cameras
+* Removing palette module parameter
+* Fixed typo in ID of QuickCam 3000 Pro
+* Adding LED settings (blinking while in use) for ToUCam cameras.
+* Turns LED off when camera is not in use.
+
+8.2
+
+* Making module more silent when trace = 0 
+* Adding QuickCam 3000 Pro IDs
+* Chrominance control for the Vesta cameras
+* Hopefully fixed problems on machines with BIGMEM and > 1GB of RAM
+* Included Oliver Neukem's lock_kernel() patch
+* Allocates less memory for image buffers
+* Adds ioctl()s for the whitebalancing
+
+8.1
+
+* Adding support for 750
+* Adding V4L GAUDIO/SAUDIO/UNIT ioctl() calls
+
+8.0
+* 'damage control' after inclusion in 2.4.5.
+* Changed wait-queue mechanism in read/mmap/poll according to the book.
+* Included YUV420P palette.
+* Changed interface to decompressor module.
+* Cleaned up pwc structure a bit.
+
+7.0
+
+* Fixed bug in vcvt_420i_yuyv; extra variables on stack were misaligned.
+* There is now a clear error message when an image size is selected that
+  is only supported using the decompressor, and the decompressor isn't
+  loaded.
+* When the decompressor wasn't loaded, selecting large image size
+  would create skewed or double images.
+
+6.3
+
+* Introduced spinlocks for the buffer pointer manipulation; a number of
+  reports seem to suggest the down()/up() semaphores were the cause of
+  lockups, since they are not suitable for interrupt/user locking.
+* Separated decompressor and core code into 2 modules.
+
+6.2
+
+* Non-integral image sizes are now padded with gray or black.
+* Added SHUTTERSPEED ioctl().
+* Fixed buglet in VIDIOCPWCSAGC; the function would always return an error,
+  even though the call succeeded.
+* Added hotplug support for 2.4.*.
+* Memory: the 645/646 uses less memory now.
+
+6.1
+
+* VIDIOCSPICT returns -EINVAL with invalid palettes.
+* Added saturation control.
+* Split decompressors from rest.
+* Fixed bug that would reset the framerate to the default framerate if 
+  the rate field was set to 0 (which is not what I intended, nl. do not 
+  change the framerate!).
+* VIDIOCPWCSCQUAL (setting compression quality) now takes effect immediately.
+* Workaround for a bug in the 730 sensor.
diff -Nru a/drivers/usb/media/pwc/Makefile b/drivers/usb/media/pwc/Makefile
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/usb/media/pwc/Makefile	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,20 @@
+ifneq ($(KERNELRELEASE),)
+
+pwc-objs	:= pwc-if.o pwc-misc.o pwc-ctrl.o pwc-uncompress.o pwc-dec1.o pwc-dec23.o pwc-kiara.o pwc-timon.o
+
+obj-$(CONFIG_USB_PWC) += pwc.o
+
+else
+
+KDIR := /lib/modules/$(shell uname -r)/build
+PWD := $(shell pwd)
+
+default:
+	$(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules
+
+endif
+
+clean:
+	rm -f *.[oas] .*.flags *.ko .*.cmd .*.d .*.tmp *.mod.c 
+	rm -rf .tmp_versions
+
diff -Nru a/drivers/usb/media/pwc/philips.txt b/drivers/usb/media/pwc/philips.txt
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/usb/media/pwc/philips.txt	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,236 @@
+This file contains some additional information for the Philips and OEM webcams.
+E-mail: webcam@smcc.demon.nl                        Last updated: 2004-01-19
+Site: http://www.smcc.demon.nl/webcam/
+
+As of this moment, the following cameras are supported:
+ * Philips PCA645
+ * Philips PCA646
+ * Philips PCVC675
+ * Philips PCVC680
+ * Philips PCVC690
+ * Philips PCVC720/40
+ * Philips PCVC730
+ * Philips PCVC740
+ * Philips PCVC750
+ * Askey VC010
+ * Creative Labs Webcam 5
+ * Creative Labs Webcam Pro Ex
+ * Logitech QuickCam 3000 Pro
+ * Logitech QuickCam 4000 Pro
+ * Logitech QuickCam Notebook Pro
+ * Logitech QuickCam Zoom
+ * Logitech QuickCam Orbit
+ * Logitech QuickCam Sphere
+ * Samsung MPC-C10
+ * Samsung MPC-C30
+ * Sotec Afina Eye
+ * AME CU-001
+ * Visionite VCS-UM100
+ * Visionite VCS-UC300
+
+The main webpage for the Philips driver is at the address above. It contains
+a lot of extra information, a FAQ, and the binary plugin 'PWCX'. This plugin
+contains decompression routines that allow you to use higher image sizes and
+framerates; in addition the webcam uses less bandwidth on the USB bus (handy
+if you want to run more than 1 camera simultaneously). These routines fall
+under a NDA, and may therefor not be distributed as source; however, its use
+is completely optional.
+
+You can build this code either into your kernel, or as a module. I recommend
+the latter, since it makes troubleshooting a lot easier. The built-in
+microphone is supported through the USB Audio class.
+
+When you load the module you can set some default settings for the
+camera; some programs depend on a particular image-size or -format and
+don't know how to set it properly in the driver. The options are:
+
+size
+   Can be one of 'sqcif', 'qsif', 'qcif', 'sif', 'cif' or
+   'vga', for an image size of resp. 128x96, 160x120, 176x144,
+   320x240, 352x288 and 640x480 (of course, only for those cameras that 
+   support these resolutions).
+
+fps
+   Specifies the desired framerate. Is an integer in the range of 4-30.
+
+fbufs
+   This paramter specifies the number of internal buffers to use for storing 
+   frames from the cam. This will help if the process that reads images from 
+   the cam is a bit slow or momentarely busy. However, on slow machines it 
+   only introduces lag, so choose carefully. The default is 3, which is 
+   reasonable. You can set it between 2 and 5.
+
+mbufs
+   This is an integer between 1 and 10. It will tell the module the number of
+   buffers to reserve for mmap(), VIDIOCCGMBUF, VIDIOCMCAPTURE and friends.
+   The default is 2, which is adequate for most applications (double
+   buffering).
+      
+   Should you experience a lot of 'Dumping frame...' messages during
+   grabbing with a tool that uses mmap(), you might want to increase if. 
+   However, it doesn't really buffer images, it just gives you a bit more
+   slack when your program is behind. But you need a multi-threaded or
+   forked program to really take advantage of these buffers.
+
+   The absolute maximum is 10, but don't set it too high!  Every buffer takes
+   up 460 KB of RAM, so unless you have a lot of memory setting this to
+   something more than 4 is an absolute waste.  This memory is only
+   allocated during open(), so nothing is wasted when the camera is not in
+   use.
+
+power_save
+   When power_save is enabled (set to 1), the module will try to shut down
+   the cam on close() and re-activate on open(). This will save power and
+   turn off the LED. Not all cameras support this though (the 645 and 646
+   don't have power saving at all), and some models don't work either (they
+   will shut down, but never wake up). Consider this experimental. By
+   default this option is disabled.
+
+compression (only useful with the plugin)
+   With this option you can control the compression factor that the camera
+   uses to squeeze the image through the USB bus. You can set the 
+   parameter between 0 and 3:
+     0 = prefer uncompressed images; if the requested mode is not available
+         in an uncompressed format, the driver will silently switch to low
+         compression.
+     1 = low compression.
+     2 = medium compression.
+     3 = high compression.
+      
+   High compression takes less bandwidth of course, but it could also
+   introduce some unwanted artefacts. The default is 2, medium compression.
+   See the FAQ on the website for an overview of which modes require
+   compression.
+
+   The compression parameter does not apply to the 645 and 646 cameras
+   and OEM models derived from those (only a few). Most cams honour this
+   parameter.
+
+leds
+   This settings takes 2 integers, that define the on/off time for the LED
+   (in milliseconds). One of the interesting things that you can do with
+   this is let the LED blink while the camera is in use. This:
+
+     leds=500,500
+      
+   will blink the LED once every second. But with:
+
+     leds=0,0
+
+   the LED never goes on, making it suitable for silent surveillance.
+
+   By default the camera's LED is on solid while in use, and turned off
+   when the camera is not used anymore.
+
+   This parameter works only with the ToUCam range of cameras (720, 730, 740,
+   750) and OEMs. For other cameras this command is silently ignored, and 
+   the LED cannot be controlled.
+
+   Finally: this parameters does not take effect UNTIL the first time you
+   open the camera device. Until then, the LED remains on.
+
+dev_hint
+   A long standing problem with USB devices is their dynamic nature: you
+   never know what device a camera gets assigned; it depends on module load
+   order, the hub configuration, the order in which devices are plugged in,
+   and the phase of the moon (i.e. it can be random). With this option you
+   can give the driver a hint as to what video device node (/dev/videoX) it
+   should use with a specific camera. This is also handy if you have two
+   cameras of the same model.
+
+   A camera is specified by its type (the number from the camera model,
+   like PCA645, PCVC750VC, etc) and optionally the serial number (visible
+   in /proc/bus/usb/devices). A hint consists of a string with the following
+   format:
+
+      [type[.serialnumber]:]node
+      
+   The square brackets mean that both the type and the serialnumber are
+   optional, but a serialnumber cannot be specified without a type (which
+   would be rather pointless). The serialnumber is separated from the type
+   by a '.'; the node number by a ':'.
+   
+   This somewhat cryptic syntax is best explained by a few examples:
+
+     dev_hint=3,5              The first detected cam gets assigned
+                               /dev/video3, the second /dev/video5. Any
+                               other cameras will get the first free 
+                               available slot (see below).
+
+     dev_hint=645:1,680:2      The PCA645 camera will get /dev/video1,
+                               and a PCVC680 /dev/video2.
+                               
+     dev_hint=645.0123:3,645.4567:0	The PCA645 camera with serialnumber 
+                                        0123 goes to /dev/video3, the same
+                                        camera model with the 4567 serial
+                                        gets /dev/video0.
+
+     dev_hint=750:1,4,5,6       The PCVC750 camera will get /dev/video1, the 
+                                next 3 Philips cams will use /dev/video4 
+                                through /dev/video6.
+
+   Some points worth knowing:
+   - Serialnumbers are case sensitive and must be written full, including 
+     leading zeroes (it's treated as a string).
+   - If a device node is already occupied, registration will fail and 
+     the webcam is not available.
+   - You can have up to 64 video devices; be sure to make enough device
+     nodes in /dev if you want to spread the numbers (this does not apply
+     to devfs). After /dev/video9 comes /dev/video10 (not /dev/videoA).
+   - If a camera does not match any dev_hint, it will simply get assigned
+     the first available device node, just as it used to be.
+
+trace
+   In order to better detect problems, it is now possible to turn on a
+   'trace' of some of the calls the module makes; it logs all items in your
+   kernel log at debug level.
+
+   The trace variable is a bitmask; each bit represents a certain feature.
+   If you want to trace something, look up the bit value(s) in the table 
+   below, add the values together and supply that to the trace variable.
+
+   Value  Value   Description					   Default
+   (dec)  (hex)
+       1    0x1   Module initialization; this will log messages       On
+                  while loading and unloading the module
+
+       2    0x2   probe() and disconnect() traces                     On
+
+       4    0x4   Trace open() and close() calls                      Off
+
+       8    0x8   read(), mmap() and associated ioctl() calls         Off
+
+      16   0x10   Memory allocation of buffers, etc.                  Off
+
+      32   0x20   Showing underflow, overflow and Dumping frame       On
+                  messages
+
+      64   0x40   Show viewport and image sizes                       Off
+
+     128   0x80   PWCX debugging                                      Off
+
+   For example, to trace the open() & read() fuctions, sum 8 + 4 = 12,
+   so you would supply trace=12 during insmod or modprobe. If
+   you want to turn the initialization and probing tracing off, set trace=0.
+   The default value for trace is 35 (0x23).
+
+
+
+Example:
+     
+     # modprobe pwc size=cif fps=15 power_save=1
+
+The fbufs, mbufs and trace parameters are global and apply to all connected
+cameras. Each camera has its own set of buffers.
+
+size and fps only specify defaults when you open() the device; this is to
+accommodate some tools that don't set the size. You can change these
+settings after open() with the Video4Linux ioctl() calls. The default of
+defaults is QCIF size at 10 fps.
+
+The compression parameter is semiglobal; it sets the initial compression
+preference for all camera's, but this parameter can be set per camera with
+the VIDIOCPWCSCQUAL ioctl() call.
+
+All parameters are optional.
+
diff -Nru a/drivers/usb/media/pwc/pwc-ctrl.c b/drivers/usb/media/pwc/pwc-ctrl.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/usb/media/pwc/pwc-ctrl.c	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,1630 @@
+/* Driver for Philips webcam
+   Functions that send various control messages to the webcam, including
+   video modes.
+   (C) 1999-2003 Nemosoft Unv.
+   (C) 2004      Luc Saillard (luc@saillard.org)
+
+   NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
+   driver and thus may have bugs that are not present in the original version.
+   Please send bug reports and support requests to <luc@saillard.org>.
+
+   NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
+   driver and thus may have bugs that are not present in the original version.
+   Please send bug reports and support requests to <luc@saillard.org>.
+   The decompression routines have been implemented by reverse-engineering the
+   Nemosoft binary pwcx module. Caveat emptor.
+
+   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
+*/
+
+/*
+   Changes
+   2001/08/03  Alvarado   Added methods for changing white balance and 
+                          red/green gains
+ */
+
+/* Control functions for the cam; brightness, contrast, video mode, etc. */
+
+#ifdef __KERNEL__
+#include <asm/uaccess.h> 
+#endif
+#include <asm/errno.h>
+#include <linux/version.h>
+ 
+#include "pwc.h"
+#include "pwc-ioctl.h"
+#include "pwc-uncompress.h"
+#include "pwc-kiara.h"
+#include "pwc-timon.h"
+#include "pwc-dec1.h"
+#include "pwc-dec23.h"
+
+/* Request types: video */
+#define SET_LUM_CTL			0x01
+#define GET_LUM_CTL			0x02
+#define SET_CHROM_CTL			0x03
+#define GET_CHROM_CTL			0x04
+#define SET_STATUS_CTL			0x05
+#define GET_STATUS_CTL			0x06
+#define SET_EP_STREAM_CTL		0x07
+#define GET_EP_STREAM_CTL		0x08
+#define SET_MPT_CTL			0x0D
+#define GET_MPT_CTL			0x0E
+
+/* Selectors for the Luminance controls [GS]ET_LUM_CTL */
+#define AGC_MODE_FORMATTER			0x2000
+#define PRESET_AGC_FORMATTER			0x2100
+#define SHUTTER_MODE_FORMATTER			0x2200
+#define PRESET_SHUTTER_FORMATTER		0x2300
+#define PRESET_CONTOUR_FORMATTER		0x2400
+#define AUTO_CONTOUR_FORMATTER			0x2500
+#define BACK_LIGHT_COMPENSATION_FORMATTER	0x2600
+#define CONTRAST_FORMATTER			0x2700
+#define DYNAMIC_NOISE_CONTROL_FORMATTER		0x2800
+#define FLICKERLESS_MODE_FORMATTER		0x2900
+#define AE_CONTROL_SPEED			0x2A00
+#define BRIGHTNESS_FORMATTER			0x2B00
+#define GAMMA_FORMATTER				0x2C00
+
+/* Selectors for the Chrominance controls [GS]ET_CHROM_CTL */
+#define WB_MODE_FORMATTER			0x1000
+#define AWB_CONTROL_SPEED_FORMATTER		0x1100
+#define AWB_CONTROL_DELAY_FORMATTER		0x1200
+#define PRESET_MANUAL_RED_GAIN_FORMATTER	0x1300
+#define PRESET_MANUAL_BLUE_GAIN_FORMATTER	0x1400
+#define COLOUR_MODE_FORMATTER			0x1500
+#define SATURATION_MODE_FORMATTER1		0x1600
+#define SATURATION_MODE_FORMATTER2		0x1700
+
+/* Selectors for the Status controls [GS]ET_STATUS_CTL */
+#define SAVE_USER_DEFAULTS_FORMATTER		0x0200
+#define RESTORE_USER_DEFAULTS_FORMATTER		0x0300
+#define RESTORE_FACTORY_DEFAULTS_FORMATTER	0x0400
+#define READ_AGC_FORMATTER			0x0500
+#define READ_SHUTTER_FORMATTER			0x0600
+#define READ_RED_GAIN_FORMATTER			0x0700
+#define READ_BLUE_GAIN_FORMATTER		0x0800
+#define SENSOR_TYPE_FORMATTER1			0x0C00
+#define READ_RAW_Y_MEAN_FORMATTER		0x3100
+#define SET_POWER_SAVE_MODE_FORMATTER		0x3200
+#define MIRROR_IMAGE_FORMATTER			0x3300
+#define LED_FORMATTER				0x3400
+#define SENSOR_TYPE_FORMATTER2			0x3700
+
+/* Formatters for the Video Endpoint controls [GS]ET_EP_STREAM_CTL */
+#define VIDEO_OUTPUT_CONTROL_FORMATTER		0x0100
+
+/* Formatters for the motorized pan & tilt [GS]ET_MPT_CTL */
+#define PT_RELATIVE_CONTROL_FORMATTER		0x01
+#define PT_RESET_CONTROL_FORMATTER		0x02
+#define PT_STATUS_FORMATTER			0x03
+
+static char *size2name[PSZ_MAX] =
+{
+	"subQCIF",
+	"QSIF",
+	"QCIF",
+	"SIF",
+	"CIF",
+	"VGA",
+};  
+
+/********/
+
+/* Entries for the Nala (645/646) camera; the Nala doesn't have compression 
+   preferences, so you either get compressed or non-compressed streams.
+   
+   An alternate value of 0 means this mode is not available at all.
+ */
+
+struct Nala_table_entry {
+	char alternate;			/* USB alternate setting */
+	int compressed;			/* Compressed yes/no */
+
+	unsigned char mode[3];		/* precomputed mode table */
+};
+
+static struct Nala_table_entry Nala_table[PSZ_MAX][8] =
+{
+#include "pwc-nala.h"
+};
+
+
+/****************************************************************************/
+
+
+#define SendControlMsg(request, value, buflen) \
+	usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0), \
+		request, \
+		USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, \
+		value, \
+		pdev->vcinterface, \
+		&buf, buflen, HZ / 2)
+
+#define RecvControlMsg(request, value, buflen) \
+	usb_control_msg(pdev->udev, usb_rcvctrlpipe(pdev->udev, 0), \
+		request, \
+		USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, \
+		value, \
+		pdev->vcinterface, \
+		&buf, buflen, HZ / 2)
+
+
+#if PWC_DEBUG
+void pwc_hexdump(void *p, int len)
+{
+	int i;
+	unsigned char *s;
+	char buf[100], *d;
+
+	s = (unsigned char *)p;
+	d = buf;
+	*d = '\0';
+	Debug("Doing hexdump @ %p, %d bytes.\n", p, len);
+	for (i = 0; i < len; i++) {
+		d += sprintf(d, "%02X ", *s++);
+		if ((i & 0xF) == 0xF) {
+			Debug("%s\n", buf);
+			d = buf;
+			*d = '\0';
+		}
+	}
+	if ((i & 0xF) != 0)
+		Debug("%s\n", buf);
+}
+#endif
+
+static inline int send_video_command(struct usb_device *udev, int index, void *buf, int buflen)
+{
+	return usb_control_msg(udev,
+		usb_sndctrlpipe(udev, 0),
+		SET_EP_STREAM_CTL,
+		USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+		VIDEO_OUTPUT_CONTROL_FORMATTER,
+		index,
+		buf, buflen, HZ);
+}
+
+
+
+static inline int set_video_mode_Nala(struct pwc_device *pdev, int size, int frames)
+{
+	unsigned char buf[3];
+	int ret, fps;
+	struct Nala_table_entry *pEntry;
+	int frames2frames[31] =
+	{ /* closest match of framerate */
+	   0,  0,  0,  0,  4,  /*  0-4  */
+	   5,  5,  7,  7, 10,  /*  5-9  */
+          10, 10, 12, 12, 15,  /* 10-14 */
+          15, 15, 15, 20, 20,  /* 15-19 */
+          20, 20, 20, 24, 24,  /* 20-24 */
+          24, 24, 24, 24, 24,  /* 25-29 */
+          24                   /* 30    */
+	};
+	int frames2table[31] = 
+	{ 0, 0, 0, 0, 0, /*  0-4  */
+	  1, 1, 1, 2, 2, /*  5-9  */
+	  3, 3, 4, 4, 4, /* 10-14 */
+	  5, 5, 5, 5, 5, /* 15-19 */
+	  6, 6, 6, 6, 7, /* 20-24 */
+	  7, 7, 7, 7, 7, /* 25-29 */
+	  7              /* 30    */
+	};
+	
+	if (size < 0 || size > PSZ_CIF || frames < 4 || frames > 25)
+		return -EINVAL;
+	frames = frames2frames[frames];
+	fps = frames2table[frames];
+	pEntry = &Nala_table[size][fps];
+	if (pEntry->alternate == 0)
+		return -EINVAL;
+
+	if (pEntry->compressed)
+		return -ENOENT; /* Not supported. */
+
+	memcpy(buf, pEntry->mode, 3);	
+	ret = send_video_command(pdev->udev, pdev->vendpoint, buf, 3);
+	if (ret < 0) {
+		Debug("Failed to send video command... %d\n", ret);
+		return ret;
+	}
+	if (pEntry->compressed && pdev->vpalette != VIDEO_PALETTE_RAW)
+	 {
+	   switch(pdev->type) {
+	     case 645:
+	     case 646:
+	       pwc_dec1_init(pdev->type, pdev->release, buf, pdev->decompress_data);
+	       break;
+
+	     case 675:
+	     case 680:
+	     case 690:
+	     case 720:
+	     case 730:
+	     case 740:
+	     case 750:
+	       pwc_dec23_init(pdev->type, pdev->release, buf, pdev->decompress_data);
+	       break;
+	   }
+	}
+ 
+	pdev->cmd_len = 3;
+	memcpy(pdev->cmd_buf, buf, 3);
+
+	/* Set various parameters */
+	pdev->vframes = frames;
+	pdev->vsize = size;
+	pdev->valternate = pEntry->alternate;
+	pdev->image = pwc_image_sizes[size];
+	pdev->frame_size = (pdev->image.x * pdev->image.y * 3) / 2;
+	if (pEntry->compressed) {
+		if (pdev->release < 5) { /* 4 fold compression */
+			pdev->vbandlength = 528;
+			pdev->frame_size /= 4;
+		}
+		else {
+			pdev->vbandlength = 704;
+			pdev->frame_size /= 3;
+		}
+	}
+	else
+		pdev->vbandlength = 0;
+	return 0;
+}
+
+
+static inline int set_video_mode_Timon(struct pwc_device *pdev, int size, int frames, int compression, int snapshot)
+{
+	unsigned char buf[13];
+	const struct Timon_table_entry *pChoose;
+	int ret, fps;
+
+	if (size >= PSZ_MAX || frames < 5 || frames > 30 || compression < 0 || compression > 3)
+		return -EINVAL;
+	if (size == PSZ_VGA && frames > 15)
+		return -EINVAL;
+	fps = (frames / 5) - 1;
+
+	/* Find a supported framerate with progressively higher compression ratios
+	   if the preferred ratio is not available.
+	*/
+	pChoose = NULL;
+	while (compression <= 3) {
+	   pChoose = &Timon_table[size][fps][compression];
+	   if (pChoose->alternate != 0)
+	     break;
+	   compression++;
+	}
+	if (pChoose == NULL || pChoose->alternate == 0)
+		return -ENOENT; /* Not supported. */
+
+	memcpy(buf, pChoose->mode, 13);
+	if (snapshot)
+		buf[0] |= 0x80;
+	ret = send_video_command(pdev->udev, pdev->vendpoint, buf, 13);
+	if (ret < 0)
+		return ret;
+
+	if (pChoose->bandlength > 0 && pdev->vpalette != VIDEO_PALETTE_RAW)
+	   pwc_dec23_init(pdev->type, pdev->release, buf, pdev->decompress_data);
+
+	pdev->cmd_len = 13;
+	memcpy(pdev->cmd_buf, buf, 13);
+
+	/* Set various parameters */
+	pdev->vframes = frames;
+	pdev->vsize = size;
+	pdev->vsnapshot = snapshot;
+	pdev->valternate = pChoose->alternate;
+	pdev->image = pwc_image_sizes[size];
+	pdev->vbandlength = pChoose->bandlength;
+	if (pChoose->bandlength > 0)
+		pdev->frame_size = (pChoose->bandlength * pdev->image.y) / 4;
+	else
+		pdev->frame_size = (pdev->image.x * pdev->image.y * 12) / 8;
+	return 0;
+}
+
+
+static inline int set_video_mode_Kiara(struct pwc_device *pdev, int size, int frames, int compression, int snapshot)
+{
+	const struct Kiara_table_entry *pChoose = 0;
+	int fps, ret;
+	unsigned char buf[12];
+	struct Kiara_table_entry RawEntry = {6, 773, 1272, {0xAD, 0xF4, 0x10, 0x27, 0xB6, 0x24, 0x96, 0x02, 0x30, 0x05, 0x03, 0x80}};
+
+	if (size >= PSZ_MAX || frames < 5 || frames > 30 || compression < 0 || compression > 3)
+		return -EINVAL;
+	if (size == PSZ_VGA && frames > 15)
+		return -EINVAL;
+	fps = (frames / 5) - 1;
+
+	/* special case: VGA @ 5 fps and snapshot is raw bayer mode */
+	if (size == PSZ_VGA && frames == 5 && snapshot)
+	{
+		/* Only available in case the raw palette is selected or 
+		   we have the decompressor available. This mode is 
+		   only available in compressed form 
+		*/
+		if (pdev->vpalette == VIDEO_PALETTE_RAW)
+		{
+	                Info("Choosing VGA/5 BAYER mode (%d).\n", pdev->vpalette);
+			pChoose = &RawEntry;
+		}
+		else
+		{
+			Info("VGA/5 BAYER mode _must_ have a decompressor available, or use RAW palette.\n");
+		}
+	}
+	else
+	{
+        	/* Find a supported framerate with progressively higher compression ratios
+		   if the preferred ratio is not available.
+                   Skip this step when using RAW modes.
+		*/
+		while (compression <= 3) {
+			pChoose = &Kiara_table[size][fps][compression];
+			if (pChoose->alternate != 0)
+				break;
+			compression++;
+		}
+	}
+	if (pChoose == NULL || pChoose->alternate == 0)
+		return -ENOENT; /* Not supported. */
+
+	Debug("Using alternate setting %d.\n", pChoose->alternate);
+	
+	/* usb_control_msg won't take staticly allocated arrays as argument?? */
+	memcpy(buf, pChoose->mode, 12);
+	if (snapshot)
+		buf[0] |= 0x80;
+
+	/* Firmware bug: video endpoint is 5, but commands are sent to endpoint 4 */
+	ret = send_video_command(pdev->udev, 4 /* pdev->vendpoint */, buf, 12);
+	if (ret < 0)
+		return ret;
+
+	if (pChoose->bandlength > 0 && pdev->vpalette != VIDEO_PALETTE_RAW)
+	  pwc_dec23_init(pdev->type, pdev->release, buf, pdev->decompress_data);
+
+	pdev->cmd_len = 12;
+	memcpy(pdev->cmd_buf, buf, 12);
+	/* All set and go */
+	pdev->vframes = frames;
+	pdev->vsize = size;
+	pdev->vsnapshot = snapshot;
+	pdev->valternate = pChoose->alternate;
+	pdev->image = pwc_image_sizes[size];
+	pdev->vbandlength = pChoose->bandlength;
+	if (pdev->vbandlength > 0)
+		pdev->frame_size = (pdev->vbandlength * pdev->image.y) / 4;
+	else
+		pdev->frame_size = (pdev->image.x * pdev->image.y * 12) / 8;
+	return 0;
+}
+
+
+
+/**
+   @pdev: device structure
+   @width: viewport width
+   @height: viewport height
+   @frame: framerate, in fps
+   @compression: preferred compression ratio
+   @snapshot: snapshot mode or streaming
+ */
+int pwc_set_video_mode(struct pwc_device *pdev, int width, int height, int frames, int compression, int snapshot)
+{
+        int ret, size;
+
+        Trace(TRACE_FLOW, "set_video_mode(%dx%d @ %d, palette %d).\n", width, height, frames, pdev->vpalette);
+	size = pwc_decode_size(pdev, width, height);
+	if (size < 0) {
+		Debug("Could not find suitable size.\n");
+		return -ERANGE;
+	}
+	Debug("decode_size = %d.\n", size);
+
+        ret = -EINVAL;
+	switch(pdev->type) {
+	case 645:
+	case 646:
+		ret = set_video_mode_Nala(pdev, size, frames);
+		break;
+
+	case 675:
+	case 680:
+	case 690:
+		ret = set_video_mode_Timon(pdev, size, frames, compression, snapshot);
+		break;
+	
+	case 720:
+	case 730:
+	case 740:
+	case 750:
+		ret = set_video_mode_Kiara(pdev, size, frames, compression, snapshot);
+		break;
+	}
+	if (ret < 0) {
+		if (ret == -ENOENT)
+			Info("Video mode %s@%d fps is only supported with the decompressor module (pwcx).\n", size2name[size], frames);
+		else {
+			Err("Failed to set video mode %s@%d fps; return code = %d\n", size2name[size], frames, ret);
+		}
+		return ret;
+	}
+	pdev->view.x = width;
+	pdev->view.y = height;
+	pdev->frame_total_size = pdev->frame_size + pdev->frame_header_size + pdev->frame_trailer_size;
+	pwc_set_image_buffer_size(pdev);
+	Trace(TRACE_SIZE, "Set viewport to %dx%d, image size is %dx%d.\n", width, height, pwc_image_sizes[size].x, pwc_image_sizes[size].y);
+	return 0;
+}
+
+
+void pwc_set_image_buffer_size(struct pwc_device *pdev)
+{
+	int i, factor = 0, filler = 0;
+
+	/* for PALETTE_YUV420P */
+	switch(pdev->vpalette)
+	{
+	case VIDEO_PALETTE_YUV420P:
+		factor = 6;
+		filler = 128;
+		break;
+	case VIDEO_PALETTE_RAW:
+		factor = 6; /* can be uncompressed YUV420P */
+		filler = 0;
+		break;
+	}
+
+	/* Set sizes in bytes */
+	pdev->image.size = pdev->image.x * pdev->image.y * factor / 4;
+	pdev->view.size  = pdev->view.x  * pdev->view.y  * factor / 4;
+
+	/* Align offset, or you'll get some very weird results in
+	   YUV420 mode... x must be multiple of 4 (to get the Y's in
+	   place), and y even (or you'll mixup U & V). This is less of a
+	   problem for YUV420P.
+	 */
+	pdev->offset.x = ((pdev->view.x - pdev->image.x) / 2) & 0xFFFC;
+	pdev->offset.y = ((pdev->view.y - pdev->image.y) / 2) & 0xFFFE;
+
+	/* Fill buffers with gray or black */
+	for (i = 0; i < MAX_IMAGES; i++) {
+		if (pdev->image_ptr[i] != NULL)
+			memset(pdev->image_ptr[i], filler, pdev->view.size);
+	}
+}
+
+
+
+/* BRIGHTNESS */
+
+int pwc_get_brightness(struct pwc_device *pdev)
+{
+	char buf;
+	int ret;
+
+	ret = RecvControlMsg(GET_LUM_CTL, BRIGHTNESS_FORMATTER, 1);	
+	if (ret < 0)
+		return ret;
+	return buf << 9;
+}
+
+int pwc_set_brightness(struct pwc_device *pdev, int value)
+{
+	char buf;
+
+	if (value < 0)
+		value = 0;
+	if (value > 0xffff)
+		value = 0xffff;
+	buf = (value >> 9) & 0x7f;
+	return SendControlMsg(SET_LUM_CTL, BRIGHTNESS_FORMATTER, 1);
+}
+
+/* CONTRAST */
+
+int pwc_get_contrast(struct pwc_device *pdev)
+{
+	char buf;
+	int ret;
+
+	ret = RecvControlMsg(GET_LUM_CTL, CONTRAST_FORMATTER, 1);
+	if (ret < 0)
+		return ret;
+	return buf << 10;
+}
+
+int pwc_set_contrast(struct pwc_device *pdev, int value)
+{
+	char buf;
+
+	if (value < 0)
+		value = 0;
+	if (value > 0xffff)
+		value = 0xffff;
+	buf = (value >> 10) & 0x3f;
+	return SendControlMsg(SET_LUM_CTL, CONTRAST_FORMATTER, 1);
+}
+
+/* GAMMA */
+
+int pwc_get_gamma(struct pwc_device *pdev)
+{
+	char buf;
+	int ret;
+	
+	ret = RecvControlMsg(GET_LUM_CTL, GAMMA_FORMATTER, 1);
+	if (ret < 0)
+		return ret;
+	return buf << 11;
+}
+
+int pwc_set_gamma(struct pwc_device *pdev, int value)
+{
+	char buf;
+
+	if (value < 0)
+		value = 0;
+	if (value > 0xffff)
+		value = 0xffff;
+	buf = (value >> 11) & 0x1f;
+	return SendControlMsg(SET_LUM_CTL, GAMMA_FORMATTER, 1);
+}
+
+
+/* SATURATION */
+
+int pwc_get_saturation(struct pwc_device *pdev)
+{
+	char buf;
+	int ret;
+
+	if (pdev->type < 675)
+		return -1;
+	ret = RecvControlMsg(GET_CHROM_CTL, pdev->type < 730 ? SATURATION_MODE_FORMATTER2 : SATURATION_MODE_FORMATTER1, 1);
+	if (ret < 0)
+		return ret;
+	return 32768 + buf * 327;
+}
+
+int pwc_set_saturation(struct pwc_device *pdev, int value)
+{
+	char buf;
+
+	if (pdev->type < 675)
+		return -EINVAL;
+	if (value < 0)
+		value = 0;
+	if (value > 0xffff)
+		value = 0xffff;
+	/* saturation ranges from -100 to +100 */
+	buf = (value - 32768) / 327;
+	return SendControlMsg(SET_CHROM_CTL, pdev->type < 730 ? SATURATION_MODE_FORMATTER2 : SATURATION_MODE_FORMATTER1, 1);
+}
+
+/* AGC */
+
+static inline int pwc_set_agc(struct pwc_device *pdev, int mode, int value)
+{
+	char buf;
+	int ret;
+	
+	if (mode)
+		buf = 0x0; /* auto */
+	else
+		buf = 0xff; /* fixed */
+
+	ret = SendControlMsg(SET_LUM_CTL, AGC_MODE_FORMATTER, 1);
+	
+	if (!mode && ret >= 0) {
+		if (value < 0)
+			value = 0;
+		if (value > 0xffff)
+			value = 0xffff;
+		buf = (value >> 10) & 0x3F;
+		ret = SendControlMsg(SET_LUM_CTL, PRESET_AGC_FORMATTER, 1);
+	}
+	if (ret < 0)
+		return ret;
+	return 0;
+}
+
+static inline int pwc_get_agc(struct pwc_device *pdev, int *value)
+{
+	unsigned char buf;
+	int ret;
+	
+	ret = RecvControlMsg(GET_LUM_CTL, AGC_MODE_FORMATTER, 1);
+	if (ret < 0)
+		return ret;
+
+	if (buf != 0) { /* fixed */
+		ret = RecvControlMsg(GET_LUM_CTL, PRESET_AGC_FORMATTER, 1);
+		if (ret < 0)
+			return ret;
+		if (buf > 0x3F)
+			buf = 0x3F;
+		*value = (buf << 10);		
+	}
+	else { /* auto */
+		ret = RecvControlMsg(GET_STATUS_CTL, READ_AGC_FORMATTER, 1);
+		if (ret < 0)
+			return ret;
+		/* Gah... this value ranges from 0x00 ... 0x9F */
+		if (buf > 0x9F)
+			buf = 0x9F;
+		*value = -(48 + buf * 409);
+	}
+
+	return 0;
+}
+
+static inline int pwc_set_shutter_speed(struct pwc_device *pdev, int mode, int value)
+{
+	char buf[2];
+	int speed, ret;
+
+
+	if (mode)
+		buf[0] = 0x0;	/* auto */
+	else
+		buf[0] = 0xff; /* fixed */
+	
+	ret = SendControlMsg(SET_LUM_CTL, SHUTTER_MODE_FORMATTER, 1);
+
+	if (!mode && ret >= 0) {
+		if (value < 0)
+			value = 0;
+		if (value > 0xffff)
+			value = 0xffff;
+		switch(pdev->type) {
+		case 675:
+		case 680:
+		case 690:
+			/* speed ranges from 0x0 to 0x290 (656) */
+			speed = (value / 100);
+			buf[1] = speed >> 8;
+			buf[0] = speed & 0xff;
+			break;
+		case 720:
+		case 730:
+		case 740:
+		case 750:
+			/* speed seems to range from 0x0 to 0xff */
+			buf[1] = 0;
+			buf[0] = value >> 8;
+			break;
+		}
+
+		ret = SendControlMsg(SET_LUM_CTL, PRESET_SHUTTER_FORMATTER, 2);
+	}
+	return ret;
+}	
+
+
+/* POWER */
+
+int pwc_camera_power(struct pwc_device *pdev, int power)
+{
+	char buf;
+
+	if (pdev->type < 675 || (pdev->type < 730 && pdev->release < 6))
+		return 0;	/* Not supported by Nala or Timon < release 6 */
+
+	if (power)
+		buf = 0x00; /* active */
+	else
+		buf = 0xFF; /* power save */
+	return SendControlMsg(SET_STATUS_CTL, SET_POWER_SAVE_MODE_FORMATTER, 1);
+}
+
+
+
+/* private calls */
+
+static inline int pwc_restore_user(struct pwc_device *pdev)
+{
+	char buf; /* dummy */
+	return SendControlMsg(SET_STATUS_CTL, RESTORE_USER_DEFAULTS_FORMATTER, 0);
+}
+
+static inline int pwc_save_user(struct pwc_device *pdev)
+{
+	char buf; /* dummy */
+	return SendControlMsg(SET_STATUS_CTL, SAVE_USER_DEFAULTS_FORMATTER, 0);
+}
+
+static inline int pwc_restore_factory(struct pwc_device *pdev)
+{
+	char buf; /* dummy */
+	return SendControlMsg(SET_STATUS_CTL, RESTORE_FACTORY_DEFAULTS_FORMATTER, 0);
+}
+
+ /* ************************************************* */
+ /* Patch by Alvarado: (not in the original version   */
+
+ /*
+  * the camera recognizes modes from 0 to 4:
+  *
+  * 00: indoor (incandescant lighting)
+  * 01: outdoor (sunlight)
+  * 02: fluorescent lighting
+  * 03: manual
+  * 04: auto
+  */ 
+static inline int pwc_set_awb(struct pwc_device *pdev, int mode)
+{
+	char buf;
+	int ret;
+	
+	if (mode < 0)
+	    mode = 0;
+	
+	if (mode > 4)
+	    mode = 4;
+	
+	buf = mode & 0x07; /* just the lowest three bits */
+	
+	ret = SendControlMsg(SET_CHROM_CTL, WB_MODE_FORMATTER, 1);
+	
+	if (ret < 0)
+		return ret;
+	return 0;
+}
+
+static inline int pwc_get_awb(struct pwc_device *pdev)
+{
+	unsigned char buf;
+	int ret;
+	
+	ret = RecvControlMsg(GET_CHROM_CTL, WB_MODE_FORMATTER, 1);
+
+	if (ret < 0) 
+		return ret;
+	return buf;
+}
+
+static inline int pwc_set_red_gain(struct pwc_device *pdev, int value)
+{
+        unsigned char buf;
+
+	if (value < 0)
+		value = 0;
+	if (value > 0xffff)
+		value = 0xffff;
+	/* only the msb is considered */
+	buf = value >> 8;
+	return SendControlMsg(SET_CHROM_CTL, PRESET_MANUAL_RED_GAIN_FORMATTER, 1);
+}
+
+static inline int pwc_get_red_gain(struct pwc_device *pdev, int *value)
+{
+	unsigned char buf;
+	int ret;
+	
+	ret = RecvControlMsg(GET_CHROM_CTL, PRESET_MANUAL_RED_GAIN_FORMATTER, 1);
+	if (ret < 0)
+	    return ret;
+	*value = buf << 8;
+	return 0;
+}
+
+
+static inline int pwc_set_blue_gain(struct pwc_device *pdev, int value)
+{
+	unsigned char buf;
+
+	if (value < 0)
+		value = 0;
+	if (value > 0xffff)
+		value = 0xffff;
+	/* only the msb is considered */
+	buf = value >> 8;
+	return SendControlMsg(SET_CHROM_CTL, PRESET_MANUAL_BLUE_GAIN_FORMATTER, 1);
+}
+
+static inline int pwc_get_blue_gain(struct pwc_device *pdev, int *value)
+{
+	unsigned char buf;
+	int ret;
+	
+	ret = RecvControlMsg(GET_CHROM_CTL, PRESET_MANUAL_BLUE_GAIN_FORMATTER, 1);
+	if (ret < 0)
+	    return ret;
+	*value = buf << 8;
+	return 0;
+}
+
+
+/* The following two functions are different, since they only read the
+   internal red/blue gains, which may be different from the manual 
+   gains set or read above.
+ */   
+static inline int pwc_read_red_gain(struct pwc_device *pdev, int *value)
+{
+	unsigned char buf;
+	int ret;
+	
+	ret = RecvControlMsg(GET_STATUS_CTL, READ_RED_GAIN_FORMATTER, 1);
+	if (ret < 0)
+		return ret;
+	*value = buf << 8;
+	return 0;
+}
+
+static inline int pwc_read_blue_gain(struct pwc_device *pdev, int *value)
+{
+	unsigned char buf;
+	int ret;
+	
+	ret = RecvControlMsg(GET_STATUS_CTL, READ_BLUE_GAIN_FORMATTER, 1);
+	if (ret < 0)
+		return ret;
+	*value = buf << 8;
+	return 0;
+}
+
+
+static inline int pwc_set_wb_speed(struct pwc_device *pdev, int speed)
+{
+	unsigned char buf;
+	
+	/* useful range is 0x01..0x20 */
+	buf = speed / 0x7f0;
+	return SendControlMsg(SET_CHROM_CTL, AWB_CONTROL_SPEED_FORMATTER, 1);
+}
+
+static inline int pwc_get_wb_speed(struct pwc_device *pdev, int *value)
+{
+	unsigned char buf;
+	int ret;
+	
+	ret = RecvControlMsg(GET_CHROM_CTL, AWB_CONTROL_SPEED_FORMATTER, 1);
+	if (ret < 0)
+		return ret;
+	*value = buf * 0x7f0;
+	return 0;
+}
+
+
+static inline int pwc_set_wb_delay(struct pwc_device *pdev, int delay)
+{
+	unsigned char buf;
+	
+	/* useful range is 0x01..0x3F */
+	buf = (delay >> 10);
+	return SendControlMsg(SET_CHROM_CTL, AWB_CONTROL_DELAY_FORMATTER, 1);
+}
+
+static inline int pwc_get_wb_delay(struct pwc_device *pdev, int *value)
+{
+	unsigned char buf;
+	int ret;
+	
+	ret = RecvControlMsg(GET_CHROM_CTL, AWB_CONTROL_DELAY_FORMATTER, 1);
+	if (ret < 0)
+		return ret;
+	*value = buf << 10;
+	return 0;
+}
+
+
+int pwc_set_leds(struct pwc_device *pdev, int on_value, int off_value)
+{
+	unsigned char buf[2];
+
+	if (pdev->type < 730)
+		return 0;
+	on_value /= 100;
+	off_value /= 100;
+	if (on_value < 0)
+		on_value = 0;
+	if (on_value > 0xff)
+		on_value = 0xff;
+	if (off_value < 0)
+		off_value = 0;
+	if (off_value > 0xff)
+		off_value = 0xff;
+
+	buf[0] = on_value;
+	buf[1] = off_value;
+
+	return SendControlMsg(SET_STATUS_CTL, LED_FORMATTER, 2);
+}
+
+int pwc_get_leds(struct pwc_device *pdev, int *on_value, int *off_value)
+{
+	unsigned char buf[2];
+	int ret;
+	
+	if (pdev->type < 730) {
+		*on_value = -1;
+		*off_value = -1;
+		return 0;
+	}
+
+	ret = RecvControlMsg(GET_STATUS_CTL, LED_FORMATTER, 2);
+	if (ret < 0)
+		return ret;
+	*on_value = buf[0] * 100;
+	*off_value = buf[1] * 100;
+	return 0;
+}
+
+static inline int pwc_set_contour(struct pwc_device *pdev, int contour)
+{
+	unsigned char buf;
+	int ret;
+	
+	if (contour < 0)
+		buf = 0xff; /* auto contour on */
+	else
+		buf = 0x0; /* auto contour off */
+	ret = SendControlMsg(SET_LUM_CTL, AUTO_CONTOUR_FORMATTER, 1);
+	if (ret < 0)
+		return ret;
+	
+	if (contour < 0)
+		return 0;
+	if (contour > 0xffff)
+		contour = 0xffff;
+	
+	buf = (contour >> 10); /* contour preset is [0..3f] */
+	ret = SendControlMsg(SET_LUM_CTL, PRESET_CONTOUR_FORMATTER, 1);
+	if (ret < 0)	
+		return ret;	
+	return 0;
+}
+
+static inline int pwc_get_contour(struct pwc_device *pdev, int *contour)
+{
+	unsigned char buf;
+	int ret;
+	
+	ret = RecvControlMsg(GET_LUM_CTL, AUTO_CONTOUR_FORMATTER, 1);
+	if (ret < 0)
+		return ret;
+
+	if (buf == 0) {
+		/* auto mode off, query current preset value */
+		ret = RecvControlMsg(GET_LUM_CTL, PRESET_CONTOUR_FORMATTER, 1);
+		if (ret < 0)	
+			return ret;
+		*contour = buf << 10;
+	}
+	else
+		*contour = -1;
+	return 0;
+}
+
+
+static inline int pwc_set_backlight(struct pwc_device *pdev, int backlight)
+{
+	unsigned char buf;
+	
+	if (backlight)
+		buf = 0xff;
+	else
+		buf = 0x0;
+	return SendControlMsg(SET_LUM_CTL, BACK_LIGHT_COMPENSATION_FORMATTER, 1);
+}
+
+static inline int pwc_get_backlight(struct pwc_device *pdev, int *backlight)
+{
+	int ret;
+	unsigned char buf;
+	
+	ret = RecvControlMsg(GET_LUM_CTL, BACK_LIGHT_COMPENSATION_FORMATTER, 1);
+	if (ret < 0)
+		return ret;
+	*backlight = buf;
+	return 0;
+}
+
+
+static inline int pwc_set_flicker(struct pwc_device *pdev, int flicker)
+{
+	unsigned char buf;
+	
+	if (flicker)
+		buf = 0xff;
+	else
+		buf = 0x0;
+	return SendControlMsg(SET_LUM_CTL, FLICKERLESS_MODE_FORMATTER, 1);
+}
+
+static inline int pwc_get_flicker(struct pwc_device *pdev, int *flicker)
+{
+	int ret;
+	unsigned char buf;
+	
+	ret = RecvControlMsg(GET_LUM_CTL, FLICKERLESS_MODE_FORMATTER, 1);
+	if (ret < 0)
+		return ret;
+	*flicker = buf;
+	return 0;
+}
+
+
+static inline int pwc_set_dynamic_noise(struct pwc_device *pdev, int noise)
+{
+	unsigned char buf;
+
+	if (noise < 0)
+		noise = 0;
+	if (noise > 3)
+		noise = 3;
+	buf = noise;
+	return SendControlMsg(SET_LUM_CTL, DYNAMIC_NOISE_CONTROL_FORMATTER, 1);
+}
+
+static inline int pwc_get_dynamic_noise(struct pwc_device *pdev, int *noise)
+{
+	int ret;
+	unsigned char buf;
+	
+	ret = RecvControlMsg(GET_LUM_CTL, DYNAMIC_NOISE_CONTROL_FORMATTER, 1);
+	if (ret < 0)
+		return ret;
+	*noise = buf;
+	return 0;
+}
+
+int pwc_mpt_reset(struct pwc_device *pdev, int flags)
+{
+	unsigned char buf;
+	
+	buf = flags & 0x03; // only lower two bits are currently used
+	return SendControlMsg(SET_MPT_CTL, PT_RESET_CONTROL_FORMATTER, 1);
+}
+
+static inline int pwc_mpt_set_angle(struct pwc_device *pdev, int pan, int tilt)
+{
+	unsigned char buf[4];
+	
+	/* set new relative angle; angles are expressed in degrees * 100,
+	   but cam as .5 degree resolution, hence devide by 200. Also
+	   the angle must be multiplied by 64 before it's send to
+	   the cam (??)
+	 */
+	pan  =  64 * pan  / 100;
+	tilt = -64 * tilt / 100; /* positive tilt is down, which is not what the user would expect */
+	buf[0] = pan & 0xFF;
+	buf[1] = (pan >> 8) & 0xFF;
+	buf[2] = tilt & 0xFF;
+	buf[3] = (tilt >> 8) & 0xFF;
+	return SendControlMsg(SET_MPT_CTL, PT_RELATIVE_CONTROL_FORMATTER, 4);
+}
+
+static inline int pwc_mpt_get_status(struct pwc_device *pdev, struct pwc_mpt_status *status)
+{
+	int ret;
+	unsigned char buf[5];
+	
+	ret = RecvControlMsg(GET_MPT_CTL, PT_STATUS_FORMATTER, 5);
+	if (ret < 0)
+		return ret;
+	status->status = buf[0] & 0x7; // 3 bits are used for reporting
+	status->time_pan = (buf[1] << 8) + buf[2];
+	status->time_tilt = (buf[3] << 8) + buf[4];
+	return 0;
+}
+
+
+int pwc_get_cmos_sensor(struct pwc_device *pdev, int *sensor)
+{
+	unsigned char buf;
+	int ret = -1, request;
+	
+	if (pdev->type < 675)
+		request = SENSOR_TYPE_FORMATTER1;
+	else if (pdev->type < 730)
+		return -1; /* The Vesta series doesn't have this call */
+	else
+		request = SENSOR_TYPE_FORMATTER2;
+	
+	ret = RecvControlMsg(GET_STATUS_CTL, request, 1);
+	if (ret < 0)
+		return ret;
+	if (pdev->type < 675)
+		*sensor = buf | 0x100;
+	else
+		*sensor = buf;
+	return 0;
+}
+
+
+ /* End of Add-Ons                                    */
+ /* ************************************************* */
+
+/* Linux 2.5.something and 2.6 pass direct pointers to arguments of
+   ioctl() calls. With 2.4, you have to do tedious copy_from_user()
+   and copy_to_user() calls. With these macros we circumvent this,
+   and let me maintain only one source file. The functionality is
+   exactly the same otherwise.
+ */   
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
+
+/* define local variable for arg */
+#define ARG_DEF(ARG_type, ARG_name)\
+	ARG_type *ARG_name = arg;
+/* copy arg to local variable */	
+#define ARG_IN(ARG_name) /* nothing */
+/* argument itself (referenced) */
+#define ARGR(ARG_name) (*ARG_name)
+/* argument address */
+#define ARGA(ARG_name) ARG_name
+/* copy local variable to arg */
+#define ARG_OUT(ARG_name) /* nothing */
+
+#else
+
+#define ARG_DEF(ARG_type, ARG_name)\
+	ARG_type ARG_name;
+#define ARG_IN(ARG_name)\
+	if (copy_from_user(&ARG_name, arg, sizeof(ARG_name))) {\
+		ret = -EFAULT;\
+		break;\
+	}
+#define ARGR(ARG_name) ARG_name
+#define ARGA(ARG_name) &ARG_name
+#define ARG_OUT(ARG_name)\
+	if (copy_to_user(arg, &ARG_name, sizeof(ARG_name))) {\
+		ret = -EFAULT;\
+		break;\
+	}
+
+#endif
+
+int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg)
+{
+	int ret = 0;
+
+	switch(cmd) {
+	case VIDIOCPWCRUSER:
+	{
+		if (pwc_restore_user(pdev))
+			ret = -EINVAL;
+		break;
+	}
+	
+	case VIDIOCPWCSUSER:
+	{
+		if (pwc_save_user(pdev))
+			ret = -EINVAL;
+		break;
+	}
+		
+	case VIDIOCPWCFACTORY:
+	{
+		if (pwc_restore_factory(pdev))
+			ret = -EINVAL;
+		break;
+	}
+	
+	case VIDIOCPWCSCQUAL:
+	{	
+		ARG_DEF(int, qual)
+
+		ARG_IN(qual)
+		if (ARGR(qual) < 0 || ARGR(qual) > 3)
+			ret = -EINVAL;
+		else
+			ret = pwc_try_video_mode(pdev, pdev->view.x, pdev->view.y, pdev->vframes, ARGR(qual), pdev->vsnapshot);
+		if (ret >= 0)
+			pdev->vcompression = ARGR(qual);
+		break;
+	}
+	
+	case VIDIOCPWCGCQUAL:
+	{
+		ARG_DEF(int, qual)
+		
+		ARGR(qual) = pdev->vcompression;
+		ARG_OUT(qual)
+		break;
+	}
+	
+	case VIDIOCPWCPROBE:
+	{
+		ARG_DEF(struct pwc_probe, probe)
+		
+		strcpy(ARGR(probe).name, pdev->vdev->name);
+		ARGR(probe).type = pdev->type;
+		ARG_OUT(probe)
+		break;
+	}
+
+	case VIDIOCPWCGSERIAL:
+	{
+		ARG_DEF(struct pwc_serial, serial)
+		
+		strcpy(ARGR(serial).serial, pdev->serial);
+		ARG_OUT(serial)
+		break;
+	}
+
+	case VIDIOCPWCSAGC:
+	{
+		ARG_DEF(int, agc)
+
+		ARG_IN(agc)
+		if (pwc_set_agc(pdev, ARGR(agc) < 0 ? 1 : 0, ARGR(agc)))
+			ret = -EINVAL;
+		break;
+	}
+	
+	case VIDIOCPWCGAGC:
+	{
+		ARG_DEF(int, agc)
+		
+		if (pwc_get_agc(pdev, ARGA(agc)))
+			ret = -EINVAL;
+		ARG_OUT(agc)
+		break;
+	}
+	
+	case VIDIOCPWCSSHUTTER:
+	{
+		ARG_DEF(int, shutter_speed)
+
+		ARG_IN(shutter_speed)
+		ret = pwc_set_shutter_speed(pdev, ARGR(shutter_speed) < 0 ? 1 : 0, ARGR(shutter_speed));
+		break;
+	}
+	
+        case VIDIOCPWCSAWB:
+	{
+		ARG_DEF(struct pwc_whitebalance, wb)
+		
+		ARG_IN(wb)
+		ret = pwc_set_awb(pdev, ARGR(wb).mode);
+		if (ret >= 0 && ARGR(wb).mode == PWC_WB_MANUAL) {
+			pwc_set_red_gain(pdev, ARGR(wb).manual_red);
+			pwc_set_blue_gain(pdev, ARGR(wb).manual_blue);
+		}
+		break;
+	}
+
+	case VIDIOCPWCGAWB:
+	{
+		ARG_DEF(struct pwc_whitebalance, wb)
+
+		memset(ARGA(wb), 0, sizeof(struct pwc_whitebalance));
+		ARGR(wb).mode = pwc_get_awb(pdev);
+		if (ARGR(wb).mode < 0)
+			ret = -EINVAL;
+		else {
+			if (ARGR(wb).mode == PWC_WB_MANUAL) {
+				ret = pwc_get_red_gain(pdev, &ARGR(wb).manual_red);
+				if (ret < 0)
+					break;
+				ret = pwc_get_blue_gain(pdev, &ARGR(wb).manual_blue);
+				if (ret < 0)
+					break;
+			}
+			if (ARGR(wb).mode == PWC_WB_AUTO) {
+				ret = pwc_read_red_gain(pdev, &ARGR(wb).read_red);
+				if (ret < 0)
+					break;
+ 				ret =pwc_read_blue_gain(pdev, &ARGR(wb).read_blue);
+ 				if (ret < 0)
+ 					break;
+			}
+		}
+		ARG_OUT(wb)
+		break;
+	}
+	
+	case VIDIOCPWCSAWBSPEED:
+	{
+		ARG_DEF(struct pwc_wb_speed, wbs)
+		
+		if (ARGR(wbs).control_speed > 0) {
+			ret = pwc_set_wb_speed(pdev, ARGR(wbs).control_speed);
+		}
+		if (ARGR(wbs).control_delay > 0) {
+			ret = pwc_set_wb_delay(pdev, ARGR(wbs).control_delay);
+		}
+		break;
+	}
+	
+	case VIDIOCPWCGAWBSPEED:
+	{
+		ARG_DEF(struct pwc_wb_speed, wbs)
+		
+		ret = pwc_get_wb_speed(pdev, &ARGR(wbs).control_speed);
+		if (ret < 0)
+			break;
+		ret = pwc_get_wb_delay(pdev, &ARGR(wbs).control_delay);
+		if (ret < 0)
+			break;
+		ARG_OUT(wbs)
+		break;
+	}
+
+        case VIDIOCPWCSLED:
+	{
+		ARG_DEF(struct pwc_leds, leds)
+
+		ARG_IN(leds)
+		ret = pwc_set_leds(pdev, ARGR(leds).led_on, ARGR(leds).led_off);
+	    	break;
+	}
+
+
+	case VIDIOCPWCGLED:
+	{
+		ARG_DEF(struct pwc_leds, leds)
+		
+		ret = pwc_get_leds(pdev, &ARGR(leds).led_on, &ARGR(leds).led_off);
+		ARG_OUT(leds)
+		break;
+	}
+
+	case VIDIOCPWCSCONTOUR:
+	{
+		ARG_DEF(int, contour)
+
+		ARG_IN(contour)
+		ret = pwc_set_contour(pdev, ARGR(contour));
+		break;
+	}
+			
+	case VIDIOCPWCGCONTOUR:
+	{
+		ARG_DEF(int, contour)
+		
+		ret = pwc_get_contour(pdev, ARGA(contour));
+		ARG_OUT(contour)
+		break;
+	}
+	
+	case VIDIOCPWCSBACKLIGHT:
+	{
+		ARG_DEF(int, backlight)
+		
+		ARG_IN(backlight)
+		ret = pwc_set_backlight(pdev, ARGR(backlight));
+		break;
+	}
+
+	case VIDIOCPWCGBACKLIGHT:
+	{
+		ARG_DEF(int, backlight)
+		
+		ret = pwc_get_backlight(pdev, ARGA(backlight));
+		ARG_OUT(backlight)
+		break;
+	}
+	
+	case VIDIOCPWCSFLICKER:
+	{
+		ARG_DEF(int, flicker)
+		
+		ARG_IN(flicker)
+		ret = pwc_set_flicker(pdev, ARGR(flicker));
+		break;
+	}
+
+	case VIDIOCPWCGFLICKER:
+	{
+		ARG_DEF(int, flicker)
+		
+		ret = pwc_get_flicker(pdev, ARGA(flicker));
+		ARG_OUT(flicker)
+		break;
+	}
+	
+	case VIDIOCPWCSDYNNOISE:
+	{
+		ARG_DEF(int, dynnoise)
+		
+		ARG_IN(dynnoise)
+		ret = pwc_set_dynamic_noise(pdev, ARGR(dynnoise));
+		break;
+	}
+	
+	case VIDIOCPWCGDYNNOISE:
+	{
+		ARG_DEF(int, dynnoise)
+
+		ret = pwc_get_dynamic_noise(pdev, ARGA(dynnoise));
+		ARG_OUT(dynnoise);
+		break;
+	}
+
+	case VIDIOCPWCGREALSIZE:
+	{
+		ARG_DEF(struct pwc_imagesize, size)
+		
+		ARGR(size).width = pdev->image.x;
+		ARGR(size).height = pdev->image.y;
+		ARG_OUT(size)
+		break;
+ 	}
+ 	
+ 	case VIDIOCPWCMPTRESET:
+ 	{
+ 		if (pdev->features & FEATURE_MOTOR_PANTILT)
+ 		{
+	 		ARG_DEF(int, flags)
+
+ 			ARG_IN(flags)
+			ret = pwc_mpt_reset(pdev, ARGR(flags));
+ 			if (ret >= 0)
+ 			{
+ 				pdev->pan_angle = 0;
+ 				pdev->tilt_angle = 0;
+ 			}
+ 		}
+ 		else
+ 		{
+ 			ret = -ENXIO;
+ 		}
+ 		break;		
+ 	}
+ 	
+ 	case VIDIOCPWCMPTGRANGE:
+ 	{
+ 		if (pdev->features & FEATURE_MOTOR_PANTILT)
+ 		{
+ 			ARG_DEF(struct pwc_mpt_range, range)
+ 			
+ 			ARGR(range) = pdev->angle_range;
+ 			ARG_OUT(range)
+ 		}
+ 		else
+ 		{	
+ 			ret = -ENXIO;
+ 		}
+ 		break;
+ 	}
+ 	
+ 	case VIDIOCPWCMPTSANGLE:
+ 	{
+ 		int new_pan, new_tilt;
+ 		
+ 		if (pdev->features & FEATURE_MOTOR_PANTILT)
+ 		{
+	 		ARG_DEF(struct pwc_mpt_angles, angles)
+
+	 		ARG_IN(angles)
+			/* The camera can only set relative angles, so
+			   do some calculations when getting an absolute angle .
+			 */
+			if (ARGR(angles).absolute)
+			{
+ 				new_pan  = ARGR(angles).pan; 
+ 				new_tilt = ARGR(angles).tilt;
+ 			}
+ 			else
+ 			{
+ 				new_pan  = pdev->pan_angle  + ARGR(angles).pan;
+ 				new_tilt = pdev->tilt_angle + ARGR(angles).tilt;
+			}
+			/* check absolute ranges */
+			if (new_pan  < pdev->angle_range.pan_min  ||
+			    new_pan  > pdev->angle_range.pan_max  ||
+			    new_tilt < pdev->angle_range.tilt_min ||
+			    new_tilt > pdev->angle_range.tilt_max)
+			{
+				ret = -ERANGE;
+			}
+			else
+			{
+				/* go to relative range, check again */
+				new_pan  -= pdev->pan_angle;
+				new_tilt -= pdev->tilt_angle;
+				/* angles are specified in degrees * 100, thus the limit = 36000 */
+				if (new_pan < -36000 || new_pan > 36000 || new_tilt < -36000 || new_tilt > 36000)
+					ret = -ERANGE;
+			}
+			if (ret == 0) /* no errors so far */
+			{
+				ret = pwc_mpt_set_angle(pdev, new_pan, new_tilt);
+				if (ret >= 0)
+				{
+					pdev->pan_angle  += new_pan;
+					pdev->tilt_angle += new_tilt;
+				}
+				if (ret == -EPIPE) /* stall -> out of range */
+					ret = -ERANGE;				
+			}
+ 		}
+ 		else
+ 		{
+ 			ret = -ENXIO;
+ 		}
+ 		break;
+ 	}
+
+ 	case VIDIOCPWCMPTGANGLE:
+ 	{
+ 		
+ 		if (pdev->features & FEATURE_MOTOR_PANTILT)
+ 		{
+	 		ARG_DEF(struct pwc_mpt_angles, angles)
+
+ 			ARGR(angles).absolute = 1;
+ 			ARGR(angles).pan  = pdev->pan_angle;
+ 			ARGR(angles).tilt = pdev->tilt_angle;
+ 			ARG_OUT(angles)
+ 		}
+ 		else
+ 		{
+ 			ret = -ENXIO;
+ 		}
+ 		break;
+ 	}
+ 
+ 	case VIDIOCPWCMPTSTATUS:
+ 	{
+ 		if (pdev->features & FEATURE_MOTOR_PANTILT)
+ 		{
+ 			ARG_DEF(struct pwc_mpt_status, status)
+ 			
+ 			ret = pwc_mpt_get_status(pdev, ARGA(status));
+ 			ARG_OUT(status)
+ 		}
+ 		else
+ 		{
+ 			ret = -ENXIO;
+ 		}
+ 		break;
+	}
+
+	case VIDIOCPWCGVIDCMD:
+	{
+		ARG_DEF(struct pwc_video_command, cmd);
+		
+                ARGR(cmd).type = pdev->type;
+		ARGR(cmd).release = pdev->release;
+		ARGR(cmd).command_len = pdev->cmd_len;
+		memcpy(&ARGR(cmd).command_buf, pdev->cmd_buf, pdev->cmd_len);
+		ARGR(cmd).bandlength = pdev->vbandlength;
+		ARGR(cmd).frame_size = pdev->frame_size;
+		ARG_OUT(cmd)
+		break;
+	}
+       /*
+	case VIDIOCPWCGVIDTABLE:
+	{
+		ARG_DEF(struct pwc_table_init_buffer, table);
+		ARGR(table).len = pdev->cmd_len;
+		memcpy(&ARGR(table).buffer, pdev->decompress_data, pdev->decompressor->table_size);
+		ARG_OUT(table)
+		break;
+	}
+	*/
+
+	default:
+		ret = -ENOIOCTLCMD;
+		break;
+	}
+	
+	if (ret > 0)
+		return 0;
+	return ret;
+}
+
+
+
diff -Nru a/drivers/usb/media/pwc/pwc-dec1.c b/drivers/usb/media/pwc/pwc-dec1.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/usb/media/pwc/pwc-dec1.c	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,42 @@
+/* Linux driver for Philips webcam
+   Decompression for chipset version 1
+   (C) 2004      Luc Saillard (luc@saillard.org)
+
+   NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
+   driver and thus may have bugs that are not present in the original version.
+   Please send bug reports and support requests to <luc@saillard.org>.
+   The decompression routines have been implemented by reverse-engineering the
+   Nemosoft binary pwcx module. Caveat emptor.
+
+   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 "pwc-dec1.h"
+
+
+void pwc_dec1_init(int type, int release, void *buffer, void *table)
+{
+
+}
+
+void pwc_dec1_exit(void)
+{
+
+
+
+}
+
diff -Nru a/drivers/usb/media/pwc/pwc-dec1.h b/drivers/usb/media/pwc/pwc-dec1.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/usb/media/pwc/pwc-dec1.h	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,36 @@
+/* Linux driver for Philips webcam
+   (C) 2004      Luc Saillard (luc@saillard.org)
+
+   NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
+   driver and thus may have bugs that are not present in the original version.
+   Please send bug reports and support requests to <luc@saillard.org>.
+   The decompression routines have been implemented by reverse-engineering the
+   Nemosoft binary pwcx module. Caveat emptor.
+
+   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 PWC_DEC1_H
+#define PWC_DEC1_H
+
+void pwc_dec1_init(int type, int release, void *buffer, void *private_data);
+void pwc_dec1_exit(void);
+
+#endif
+
+
+
diff -Nru a/drivers/usb/media/pwc/pwc-dec23.c b/drivers/usb/media/pwc/pwc-dec23.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/usb/media/pwc/pwc-dec23.c	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,623 @@
+/* Linux driver for Philips webcam
+   Decompression for chipset version 2 et 3
+   (C) 2004      Luc Saillard (luc@saillard.org)
+
+   NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
+   driver and thus may have bugs that are not present in the original version.
+   Please send bug reports and support requests to <luc@saillard.org>.
+   The decompression routines have been implemented by reverse-engineering the
+   Nemosoft binary pwcx module. Caveat emptor.
+
+   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 "pwc-timon.h"
+#include "pwc-kiara.h"
+#include "pwc-dec23.h"
+#include "pwc-ioctl.h"
+
+#include <linux/string.h>
+
+/****
+ *
+ *
+ *
+ */
+
+
+static void fill_table_a000(unsigned int *p)
+{
+  static unsigned int initial_values[12] = {
+     0xFFAD9B00, 0xFFDDEE00, 0x00221200, 0x00526500,
+     0xFFC21E00, 0x003DE200, 0xFF924B80, 0xFFD2A300,
+     0x002D5D00, 0x006DB480, 0xFFED3E00, 0x0012C200
+  };
+  static unsigned int values_derivated[12] = {
+     0x0000A4CA, 0x00004424, 0xFFFFBBDC, 0xFFFF5B36,
+     0x00007BC4, 0xFFFF843C, 0x0000DB69, 0x00005ABA,
+     0xFFFFA546, 0xFFFF2497, 0x00002584, 0xFFFFDA7C
+  };
+  unsigned int temp_values[12];
+  int i,j;
+
+  memcpy(temp_values,initial_values,sizeof(initial_values));
+  for (i=0;i<256;i++)
+   {
+     for (j=0;j<12;j++)
+      {
+	*p++ = temp_values[j];
+	temp_values[j] += values_derivated[j];
+      }
+   }
+}
+
+static void fill_table_d000(unsigned char *p)
+{
+  int bit,byte;
+
+  for (bit=0; bit<8; bit++)
+   {
+     unsigned char bitpower = 1<<bit;
+     unsigned char mask = bitpower-1;
+     for (byte=0; byte<256; byte++)
+      {
+	if (byte & bitpower)
+	  *p++ = -(byte & mask);
+	else
+	  *p++ = (byte & mask);
+      }
+   }
+}
+
+/*
+ *
+ * Kiara: 0 <= ver <= 7
+ * Timon: 0 <= ver <= 15
+ *
+ */
+void fill_table_color(unsigned int version, const unsigned int *romtable, 
+    unsigned char *p0004, 
+    unsigned char *p8004)
+{
+  const unsigned int *table;
+  unsigned char *p0, *p8;
+  int i,j,k;
+  int dl,bit,pw;
+
+  romtable += version*256;
+
+  for (i=0; i<2; i++)
+   {
+     table = romtable + i*128;
+
+     for (dl=0; dl<16; dl++)
+      {
+	p0 = p0004 + (i<<14) + (dl<<10);
+	p8 = p8004 + (i<<12) + (dl<<8);
+
+	for (j=0; j<8; j++ , table++, p0+=128)
+	 {
+	   for (k=0; k<16; k++)
+	    {
+	      if (k==0)
+		bit=1;
+	      else if (k>=1 && k<3)
+		bit=(table[0]>>15)&7;
+	      else if (k>=3 && k<6)
+		bit=(table[0]>>12)&7;
+	      else if (k>=6 && k<10)
+		bit=(table[0]>>9)&7;
+	      else if (k>=10 && k<13)
+		bit=(table[0]>>6)&7;
+	      else if (k>=13 && k<15)
+		bit=(table[0]>>3)&7;
+	      else
+		bit=(table[0])&7;
+	      if (k == 0)
+		*(unsigned char *)p8++ = 8;
+	      else
+		*(unsigned char *)p8++ = j - bit;
+	      *(unsigned char *)p8++ = bit;
+
+	      pw = 1<<bit;
+	      p0[k+0x00] = (1*pw)  + 0x80;
+	      p0[k+0x10] = (2*pw)  + 0x80;
+	      p0[k+0x20] = (3*pw)  + 0x80;
+	      p0[k+0x30] = (4*pw)  + 0x80;
+	      p0[k+0x40] = (-pw)   + 0x80;
+	      p0[k+0x50] = (2*-pw) + 0x80;
+	      p0[k+0x60] = (3*-pw) + 0x80;
+	      p0[k+0x70] = (4*-pw) + 0x80;
+	    } /* end of for (k=0; k<16; k++, p8++) */
+	 } /* end of for (j=0; j<8; j++ , table++) */
+      } /* end of for (dl=0; dl<16; dl++) */
+   } /* end of for (i=0; i<2; i++) */
+}
+
+/*
+ * precision = (pdev->xx + pdev->yy)
+ *
+ */
+void fill_table_dc00_d800(unsigned int precision, unsigned int *pdc00, unsigned int *pd800)
+{
+  int i;
+  unsigned int offset1, offset2;
+ 
+  for(i=0,offset1=0x4000, offset2=0; i<256 ; i++,offset1+=0x7BC4, offset2+=0x7BC4)
+   {
+     unsigned int msb = offset1 >> 15;
+
+     if ( msb > 255)
+      {
+	if (msb)
+	  msb=0;
+	else
+	  msb=255;
+      }
+
+     *pdc00++ = msb << precision;
+     *pd800++ = offset2;
+   }
+
+}
+
+/*
+ * struct {
+ *   unsigned char op;	    // operation to execute
+ *   unsigned char bits;    // bits use to perform operation
+ *   unsigned char offset1; // offset to add to access in the table_0004 % 16
+ *   unsigned char offset2; // offset to add to access in the table_0004
+ * }
+ *
+ */
+static unsigned int table_ops[] = {
+0x02,0x00,0x00,0x00, 0x00,0x03,0x01,0x00, 0x00,0x04,0x01,0x10, 0x00,0x06,0x01,0x30,
+0x02,0x00,0x00,0x00, 0x00,0x03,0x01,0x40, 0x00,0x05,0x01,0x20, 0x01,0x00,0x00,0x00,
+0x02,0x00,0x00,0x00, 0x00,0x03,0x01,0x00, 0x00,0x04,0x01,0x50, 0x00,0x05,0x02,0x00,
+0x02,0x00,0x00,0x00, 0x00,0x03,0x01,0x40, 0x00,0x05,0x03,0x00, 0x01,0x00,0x00,0x00,
+0x02,0x00,0x00,0x00, 0x00,0x03,0x01,0x00, 0x00,0x04,0x01,0x10, 0x00,0x06,0x02,0x10,
+0x02,0x00,0x00,0x00, 0x00,0x03,0x01,0x40, 0x00,0x05,0x01,0x60, 0x01,0x00,0x00,0x00,
+0x02,0x00,0x00,0x00, 0x00,0x03,0x01,0x00, 0x00,0x04,0x01,0x50, 0x00,0x05,0x02,0x40,
+0x02,0x00,0x00,0x00, 0x00,0x03,0x01,0x40, 0x00,0x05,0x03,0x40, 0x01,0x00,0x00,0x00,
+0x02,0x00,0x00,0x00, 0x00,0x03,0x01,0x00, 0x00,0x04,0x01,0x10, 0x00,0x06,0x01,0x70,
+0x02,0x00,0x00,0x00, 0x00,0x03,0x01,0x40, 0x00,0x05,0x01,0x20, 0x01,0x00,0x00,0x00,
+0x02,0x00,0x00,0x00, 0x00,0x03,0x01,0x00, 0x00,0x04,0x01,0x50, 0x00,0x05,0x02,0x00,
+0x02,0x00,0x00,0x00, 0x00,0x03,0x01,0x40, 0x00,0x05,0x03,0x00, 0x01,0x00,0x00,0x00,
+0x02,0x00,0x00,0x00, 0x00,0x03,0x01,0x00, 0x00,0x04,0x01,0x10, 0x00,0x06,0x02,0x50,
+0x02,0x00,0x00,0x00, 0x00,0x03,0x01,0x40, 0x00,0x05,0x01,0x60, 0x01,0x00,0x00,0x00,
+0x02,0x00,0x00,0x00, 0x00,0x03,0x01,0x00, 0x00,0x04,0x01,0x50, 0x00,0x05,0x02,0x40,
+0x02,0x00,0x00,0x00, 0x00,0x03,0x01,0x40, 0x00,0x05,0x03,0x40, 0x01,0x00,0x00,0x00
+};
+
+/*
+ * TODO: multiply by 4 all values
+ *
+ */
+static unsigned int MulIdx[256] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3,
+ 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3,
+ 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 4, 4, 4, 4,
+ 6, 7, 8, 9, 7,10,11, 8, 8,11,10, 7, 9, 8, 7, 6,
+ 4, 5, 5, 4, 4, 5, 5, 4, 4, 5, 5, 4, 4, 5, 5, 4,
+ 1, 3, 0, 2, 1, 3, 0, 2, 1, 3, 0, 2, 1, 3, 0, 2,
+ 0, 3, 3, 0, 1, 2, 2, 1, 2, 1, 1, 2, 3, 0, 0, 3,
+ 0, 1, 2, 3, 3, 2, 1, 0, 3, 2, 1, 0, 0, 1, 2, 3,
+ 1, 1, 1, 1, 3, 3, 3, 3, 0, 0, 0, 0, 2, 2, 2, 2,
+ 7,10,11, 8, 9, 8, 7, 6, 6, 7, 8, 9, 8,11,10, 7,
+ 4, 5, 5, 4, 5, 4, 4, 5, 5, 4, 4, 5, 4, 5, 5, 4,
+ 7, 9, 6, 8,10, 8, 7,11,11, 7, 8,10, 8, 6, 9, 7,
+ 1, 3, 0, 2, 2, 0, 3, 1, 2, 0, 3, 1, 1, 3, 0, 2,
+ 1, 2, 2, 1, 3, 0, 0, 3, 0, 3, 3, 0, 2, 1, 1, 2,
+10, 8, 7,11, 8, 6, 9, 7, 7, 9, 6, 8,11, 7, 8,10
+};
+
+
+
+void pwc_dec23_init(int type, int release, unsigned char *mode, void *data)
+{
+  int flags;
+  struct pwc_dec23_private *pdev = data;
+  release = release;
+
+  switch (type)
+   {
+    case 720:
+    case 730:
+    case 740:
+    case 750:
+      flags = mode[2]&0x18;	/* our: flags = 8, mode[2]==e8 */
+      if (flags==8)
+	pdev->zz = 7;
+      else if (flags==0x10)
+	pdev->zz = 8;
+      else
+	pdev->zz = 6;
+      flags = mode[2]>>5;	/* our: 7 */
+
+      fill_table_color(flags, (unsigned int *)KiaraRomTable, pdev->table_0004, pdev->table_8004);
+      break;
+
+
+    case 675:
+    case 680:
+    case 690:
+      flags = mode[2]&6;
+      if (flags==2)
+	pdev->zz = 7;
+      else if (flags==4)
+	pdev->zz = 8;
+      else
+	pdev->zz = 6;
+      flags = mode[2]>>3;
+
+      fill_table_color(flags, (unsigned int *)TimonRomTable, pdev->table_0004, pdev->table_8004);
+      break;
+
+    default:
+      /* Not supported */
+      return;
+   }
+
+  /* * * * ** */
+  pdev->xx = 8 - pdev->zz;
+  pdev->yy = 15 - pdev->xx;
+  pdev->zzmask = 0xFF>>pdev->xx;
+  //pdev->zzmask = (1U<<pdev->zz)-1;
+
+
+  fill_table_dc00_d800(pdev->xx + pdev->yy, pdev->table_dc00, pdev->table_d800);
+  fill_table_a000(pdev->table_a004);
+  fill_table_d000(pdev->table_d004);
+}
+
+
+/*
+ * To manage the stream, we keep in a 32 bits variables,
+ * the next bits in the stream. fill_reservoir() add to
+ * the reservoir at least wanted nbits.
+ *
+ *
+ */
+#define fill_nbits(reservoir,nbits_in_reservoir,stream,nbits_wanted) do { \
+   while (nbits_in_reservoir<nbits_wanted) \
+    { \
+      reservoir |= (*(stream)++) << nbits_in_reservoir; \
+      nbits_in_reservoir+=8; \
+    } \
+}  while(0);
+
+#define get_nbits(reservoir,nbits_in_reservoir,stream,nbits_wanted,result) do { \
+   fill_nbits(reservoir,nbits_in_reservoir,stream,nbits_wanted); \
+   result = (reservoir) & ((1U<<nbits_wanted)-1); \
+   reservoir >>= nbits_wanted; \
+   nbits_in_reservoir -= nbits_wanted; \
+}  while(0);
+
+
+
+static void DecompressBand23(const struct pwc_dec23_private *pdev,
+                             const unsigned char *rawyuv,
+			     unsigned char *planar_y,
+			     unsigned char *planar_u,
+			     unsigned char *planar_v,
+			     unsigned int image_x,		/* aka number of pixels wanted ??? */
+			     unsigned int pixels_per_line,	/* aka number of pixels per line */
+			     int flags)
+{
+
+
+  unsigned int reservoir, nbits_in_reservoir;
+  int first_4_bits;
+  unsigned int bytes_per_channel;
+  int line_size;	/* size of the line (4Y+U+V) */
+  int passes;
+  const unsigned char *ptable0004, *ptable8004;
+
+  int even_line;
+  unsigned int temp_colors[16];
+  int nblocks;
+
+  const unsigned char *stream;
+  unsigned char *dest_y, *dest_u=NULL, *dest_v=NULL;
+  unsigned int offset_to_plane_u, offset_to_plane_v;
+
+  int i;
+
+
+  reservoir = 0;
+  nbits_in_reservoir = 0;
+  stream = rawyuv+1;	/* The first byte of the stream is skipped */
+  even_line = 1;
+
+  get_nbits(reservoir,nbits_in_reservoir,stream,4,first_4_bits);
+
+  line_size = pixels_per_line*3;
+
+  for (passes=0;passes<2;passes++)
+   {
+     if (passes==0)
+      {
+	bytes_per_channel = pixels_per_line;
+	dest_y = planar_y;
+	nblocks = image_x/4;
+      }
+     else
+      {
+	/* Format planar: All Y, then all U, then all V */
+	bytes_per_channel = pixels_per_line/2;
+	dest_u = planar_u;
+	dest_v = planar_v;
+	dest_y = dest_u;
+	nblocks = image_x/8;
+      }
+
+     offset_to_plane_u = bytes_per_channel*2;
+     offset_to_plane_v = bytes_per_channel*3;
+     /*
+     printf("bytes_per_channel = %d\n",bytes_per_channel);
+     printf("offset_to_plane_u = %d\n",offset_to_plane_u);
+     printf("offset_to_plane_v = %d\n",offset_to_plane_v);
+     */
+
+     while (nblocks-->0)
+      {
+	unsigned int gray_index;
+
+	fill_nbits(reservoir,nbits_in_reservoir,stream,16);
+	gray_index = reservoir & pdev->zzmask;
+	reservoir >>= pdev->zz;
+	nbits_in_reservoir -= pdev->zz;
+
+	fill_nbits(reservoir,nbits_in_reservoir,stream,2);
+
+	if ( (reservoir & 3) == 0)
+	 {
+	   reservoir>>=2;
+	   nbits_in_reservoir-=2;
+	   for (i=0;i<16;i++)
+	     temp_colors[i] = pdev->table_dc00[gray_index];
+
+	 }
+	else
+	 {
+	   unsigned int channel_v, offset1;
+
+	   /* swap bit 0 and 2 of offset_OR */
+	   channel_v = ((reservoir & 1) << 2) | (reservoir & 2) | ((reservoir & 4)>>2);
+	   reservoir>>=3;
+	   nbits_in_reservoir-=3;
+
+	   for (i=0;i<16;i++)
+	     temp_colors[i] = pdev->table_d800[gray_index];
+
+	   ptable0004 = pdev->table_0004 + (passes*16384) + (first_4_bits*1024) + (channel_v*128);
+	   ptable8004 = pdev->table_8004 + (passes*4096)  + (first_4_bits*256)  + (channel_v*32);
+
+	   offset1 = 0;
+	   while(1) 
+	    {
+	      unsigned int index_in_table_ops, op, rows=0;
+	      fill_nbits(reservoir,nbits_in_reservoir,stream,16);
+
+	      /* mode is 0,1 or 2 */
+	      index_in_table_ops = (reservoir&0x3F);
+	      op = table_ops[ index_in_table_ops*4 ];
+	      if (op == 2)
+	       {
+		 reservoir >>= 2;
+		 nbits_in_reservoir -= 2;
+		 break;	/* exit the while(1) */
+	       }
+	      if (op == 0)
+	       {
+		 unsigned int shift;
+
+		 offset1 = (offset1 + table_ops[index_in_table_ops*4+2]) & 0x0F;
+		 shift = table_ops[ index_in_table_ops*4+1 ];
+		 reservoir >>= shift;
+		 nbits_in_reservoir -= shift;
+		 rows = ptable0004[ offset1 + table_ops[index_in_table_ops*4+3] ];
+	       }
+	      if (op == 1)
+	       {
+		  /* 10bits [ xxxx xxxx yyyy 000 ]
+		   * yyy => offset in the table8004
+		   * xxx => offset in the tabled004
+		   */
+		 unsigned int mask, shift;
+		 unsigned int col1, row1, total_bits;
+
+		 offset1 = (offset1 + ((reservoir>>3)&0x0F)+1) & 0x0F;
+
+		 col1 = (reservoir>>7) & 0xFF;
+		 row1 = ptable8004 [ offset1*2 ];
+
+		 /* Bit mask table */
+		 mask = pdev->table_d004[ (row1<<8) + col1 ];
+		 shift = ptable8004 [ offset1*2 + 1];
+		 rows = ((mask << shift) + 0x80) & 0xFF;
+
+		 total_bits = row1 + 8;
+		 reservoir >>= total_bits;
+		 nbits_in_reservoir -= total_bits;
+	       }
+	       {
+		 const unsigned int *table_a004 = pdev->table_a004 + rows*12;
+		 unsigned int *poffset = MulIdx + offset1*16;	/* 64/4 (int) */
+		 for (i=0;i<16;i++)
+		  {
+		    temp_colors[i] += table_a004[ *poffset ];
+		    poffset++;
+		  }
+	       }
+	   }
+	 }
+#define USE_SIGNED_INT_FOR_COLOR
+#ifdef USE_SIGNED_INT_FOR_COLOR
+#  define CLAMP(x) ((x)>255?255:((x)<0?0:x))
+#else
+#  define CLAMP(x) ((x)>255?255:x)
+#endif
+
+	if (passes == 0)
+	 {
+#ifdef USE_SIGNED_INT_FOR_COLOR
+	   const int *c = temp_colors;
+#else
+	   const unsigned int *c = temp_colors;
+#endif
+	   unsigned char *d;
+
+	   d = dest_y;
+	   for (i=0;i<4;i++,c++)
+	     *d++ = CLAMP((*c) >> pdev->yy);
+
+	   d = dest_y + bytes_per_channel;
+	   for (i=0;i<4;i++,c++)
+	     *d++ = CLAMP((*c) >> pdev->yy);
+
+	   d = dest_y + offset_to_plane_u;
+	   for (i=0;i<4;i++,c++)
+	     *d++ = CLAMP((*c) >> pdev->yy);
+
+	   d = dest_y + offset_to_plane_v;
+	   for (i=0;i<4;i++,c++)
+	     *d++ = CLAMP((*c) >> pdev->yy);
+
+	   dest_y += 4;
+	 }
+	else if (passes == 1)
+	 {
+#ifdef USE_SIGNED_INT_FOR_COLOR
+	   int *c1 = temp_colors;
+	   int *c2 = temp_colors+4;
+#else
+	   unsigned int *c1 = temp_colors;
+	   unsigned int *c2 = temp_colors+4;
+#endif
+	   unsigned char *d;
+
+	   d = dest_y;
+	   for (i=0;i<4;i++,c1++,c2++)
+	    {
+	      *d++ = CLAMP((*c1) >> pdev->yy);
+	      *d++ = CLAMP((*c2) >> pdev->yy);
+	    }
+	   c1 = temp_colors+12;
+	   //c2 = temp_colors+8;
+	   d = dest_y + bytes_per_channel;
+	   for (i=0;i<4;i++,c1++,c2++)
+	    {
+	      *d++ = CLAMP((*c1) >> pdev->yy);
+	      *d++ = CLAMP((*c2) >> pdev->yy);
+	    }
+
+	   if (even_line)	/* Each line, swap u/v */
+	    {
+	      even_line=0;
+	      dest_y = dest_v;
+	      dest_u += 8;
+	    }
+	   else
+	    {
+	      even_line=1;
+	      dest_y = dest_u;
+	      dest_v += 8;
+	    }
+	 }
+
+      } /* end of while (nblocks-->0) */
+
+   } /* end of for (passes=0;passes<2;passes++) */
+
+}
+
+
+/**
+ *
+ * image: size of the image wanted
+ * view : size of the image returned by the camera
+ * offset: (x,y) to displayer image in the view
+ *
+ * src: raw data
+ * dst: image output
+ * flags: PWCX_FLAG_PLANAR
+ * pdev: private buffer
+ * bandlength:
+ *
+ */
+void pwc_dec23_decompress(const struct pwc_coord *image,
+                            const struct pwc_coord *view,
+			    const struct pwc_coord *offset,
+			    const void *src,
+			    void *dst,
+			    int flags,
+			    const void *data,
+			    int bandlength)
+{
+  const struct pwc_dec23_private *pdev = data;
+  unsigned char *pout, *pout_planar_y=NULL, *pout_planar_u=NULL, *pout_planar_v=NULL;
+  int i,n,stride,pixel_size;
+
+
+  if (flags & PWCX_FLAG_BAYER)
+   {
+     pout = dst + (view->x * offset->y) + offset->x;
+     pixel_size = view->x * 4;
+   }
+  else
+   {
+     n = view->x * view->y;
+
+     /* offset in Y plane */
+     stride = view->x * offset->y;
+     pout_planar_y = dst + stride + offset->x;
+
+     /* offsets in U/V planes */
+     stride = (view->x * offset->y)/4 + offset->x/2;
+     pout_planar_u = dst + n +     + stride;
+     pout_planar_v = dst + n + n/4 + stride;
+
+     pixel_size = view->x * 4;
+   }
+
+
+  for (i=0;i<image->y;i+=4)
+   {
+     if (flags & PWCX_FLAG_BAYER)
+      {
+	//TODO:
+	//DecompressBandBayer(pdev,src,pout,image.x,view->x,flags);
+	src += bandlength;
+	pout += pixel_size;
+      }
+     else
+      {
+	DecompressBand23(pdev,src,pout_planar_y,pout_planar_u,pout_planar_v,image->x,view->x,flags);
+	src += bandlength;
+	pout_planar_y += pixel_size;
+	pout_planar_u += view->x;
+	pout_planar_v += view->x;
+      }
+   }
+}
+
+void pwc_dec23_exit(void)
+{
+  /* Do nothing */
+
+}
+
diff -Nru a/drivers/usb/media/pwc/pwc-dec23.h b/drivers/usb/media/pwc/pwc-dec23.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/usb/media/pwc/pwc-dec23.h	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,58 @@
+/* Linux driver for Philips webcam
+   (C) 2004      Luc Saillard (luc@saillard.org)
+
+   NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
+   driver and thus may have bugs that are not present in the original version.
+   Please send bug reports and support requests to <luc@saillard.org>.
+   The decompression routines have been implemented by reverse-engineering the
+   Nemosoft binary pwcx module. Caveat emptor.
+
+   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 PWC_DEC23_H
+#define PWC_DEC23_H
+
+struct pwc_dec23_private
+{
+  unsigned char xx,yy,zz,zzmask;
+
+  unsigned char table_0004[2*0x4000];
+  unsigned char table_8004[2*0x1000];
+  unsigned int  table_a004[256*12];
+
+  unsigned char table_d004[8*256];
+  unsigned int  table_d800[256];
+  unsigned int  table_dc00[256];
+};
+
+
+void pwc_dec23_init(int type, int release, unsigned char *buffer, void *private_data);
+void pwc_dec23_exit(void);
+void pwc_dec23_decompress(const struct pwc_coord *image,
+                            const struct pwc_coord *view,
+			    const struct pwc_coord *offset,
+			    const void *src,
+			    void *dst,
+			    int flags,
+			    const void *data,
+			    int bandlength);
+
+
+
+#endif
+
+
+
diff -Nru a/drivers/usb/media/pwc/pwc-if.c b/drivers/usb/media/pwc/pwc-if.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/usb/media/pwc/pwc-if.c	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,2211 @@
+/* Linux driver for Philips webcam
+   USB and Video4Linux interface part.
+   (C) 1999-2004 Nemosoft Unv.
+   (C) 2004      Luc Saillard (luc@saillard.org)
+
+   NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
+   driver and thus may have bugs that are not present in the original version.
+   Please send bug reports and support requests to <luc@saillard.org>.
+   The decompression routines have been implemented by reverse-engineering the
+   Nemosoft binary pwcx module. Caveat emptor.
+
+   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 code forms the interface between the USB layers and the Philips
+   specific stuff. Some adanved stuff of the driver falls under an
+   NDA, signed between me and Philips B.V., Eindhoven, the Netherlands, and
+   is thus not distributed in source form. The binary pwcx.o module 
+   contains the code that falls under the NDA.
+   
+   In case you're wondering: 'pwc' stands for "Philips WebCam", but 
+   I really didn't want to type 'philips_web_cam' every time (I'm lazy as
+   any Linux kernel hacker, but I don't like uncomprehensible abbreviations
+   without explanation).
+   
+   Oh yes, convention: to disctinguish between all the various pointers to
+   device-structures, I use these names for the pointer variables:
+   udev: struct usb_device *
+   vdev: struct video_device *
+   pdev: struct pwc_devive *
+*/
+
+/* Contributors:
+   - Alvarado: adding whitebalance code
+   - Alistar Moire: QuickCam 3000 Pro device/product ID
+   - Tony Hoyle: Creative Labs Webcam 5 device/product ID
+   - Mark Burazin: solving hang in VIDIOCSYNC when camera gets unplugged
+   - Jk Fang: Sotec Afina Eye ID
+   - Xavier Roche: QuickCam Pro 4000 ID
+   - Jens Knudsen: QuickCam Zoom ID
+   - J. Debert: QuickCam for Notebooks ID
+*/
+
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/poll.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <asm/io.h>
+
+#include "pwc.h"
+#include "pwc-ioctl.h"
+#include "pwc-kiara.h"
+#include "pwc-timon.h"
+#include "pwc-dec23.h"
+#include "pwc-dec1.h"
+#include "pwc-uncompress.h"
+
+/* Function prototypes and driver templates */
+
+/* hotplug device table support */
+static struct usb_device_id pwc_device_table [] = {
+	{ USB_DEVICE(0x0471, 0x0302) }, /* Philips models */
+	{ USB_DEVICE(0x0471, 0x0303) },
+	{ USB_DEVICE(0x0471, 0x0304) },
+	{ USB_DEVICE(0x0471, 0x0307) },
+	{ USB_DEVICE(0x0471, 0x0308) },
+	{ USB_DEVICE(0x0471, 0x030C) },
+	{ USB_DEVICE(0x0471, 0x0310) },
+	{ USB_DEVICE(0x0471, 0x0311) },
+	{ USB_DEVICE(0x0471, 0x0312) },
+	{ USB_DEVICE(0x0471, 0x0313) }, /* the 'new' 720K */
+	{ USB_DEVICE(0x069A, 0x0001) }, /* Askey */
+	{ USB_DEVICE(0x046D, 0x08B0) }, /* Logitech QuickCam Pro 3000 */
+	{ USB_DEVICE(0x046D, 0x08B1) }, /* Logitech QuickCam Notebook Pro */
+	{ USB_DEVICE(0x046D, 0x08B2) }, /* Logitech QuickCam Pro 4000 */
+	{ USB_DEVICE(0x046D, 0x08B3) }, /* Logitech QuickCam Zoom (old model) */
+	{ USB_DEVICE(0x046D, 0x08B4) }, /* Logitech QuickCam Zoom (new model) */
+	{ USB_DEVICE(0x046D, 0x08B5) }, /* Logitech QuickCam Orbit/Sphere */
+	{ USB_DEVICE(0x046D, 0x08B6) }, /* Logitech (reserved) */
+	{ USB_DEVICE(0x046D, 0x08B7) }, /* Logitech (reserved) */
+	{ USB_DEVICE(0x046D, 0x08B8) }, /* Logitech (reserved) */
+	{ USB_DEVICE(0x055D, 0x9000) }, /* Samsung */
+	{ USB_DEVICE(0x055D, 0x9001) },
+	{ USB_DEVICE(0x041E, 0x400C) }, /* Creative Webcam 5 */
+	{ USB_DEVICE(0x041E, 0x4011) }, /* Creative Webcam Pro Ex */
+	{ USB_DEVICE(0x04CC, 0x8116) }, /* Afina Eye */
+	{ USB_DEVICE(0x06BE, 0x8116) }, /* new Afina Eye */
+	{ USB_DEVICE(0x0d81, 0x1910) }, /* Visionite */
+	{ USB_DEVICE(0x0d81, 0x1900) },
+	{ }
+};
+MODULE_DEVICE_TABLE(usb, pwc_device_table);
+
+static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id *id);
+static void usb_pwc_disconnect(struct usb_interface *intf);
+
+static struct usb_driver pwc_driver = {
+	.owner =		THIS_MODULE,
+	.name =			"Philips webcam",	/* name */
+	.id_table =		pwc_device_table,
+	.probe =		usb_pwc_probe,		/* probe() */
+	.disconnect =		usb_pwc_disconnect,	/* disconnect() */
+};
+
+#define MAX_DEV_HINTS	20
+#define MAX_ISOC_ERRORS	20
+
+static int default_size = PSZ_QCIF;
+static int default_fps = 10;
+static int default_fbufs = 3;   /* Default number of frame buffers */
+static int default_mbufs = 2;	/* Default number of mmap() buffers */
+       int pwc_trace = TRACE_MODULE | TRACE_FLOW | TRACE_PWCX;
+static int power_save = 0;
+static int led_on = 100, led_off = 0; /* defaults to LED that is on while in use */
+       int pwc_preferred_compression = 2; /* 0..3 = uncompressed..high */
+static struct {
+	int type;
+	char serial_number[30];
+	int device_node;
+	struct pwc_device *pdev;
+} device_hint[MAX_DEV_HINTS];
+
+/***/
+
+static int pwc_video_open(struct inode *inode, struct file *file);
+static int pwc_video_close(struct inode *inode, struct file *file);
+static ssize_t pwc_video_read(struct file *file, char *buf,
+			  size_t count, loff_t *ppos);
+static unsigned int pwc_video_poll(struct file *file, poll_table *wait);
+static int  pwc_video_ioctl(struct inode *inode, struct file *file,
+			    unsigned int ioctlnr, unsigned long arg);
+static int  pwc_video_mmap(struct file *file, struct vm_area_struct *vma);
+
+static struct file_operations pwc_fops = {
+	.owner =	THIS_MODULE,
+	.open =		pwc_video_open,
+	.release =     	pwc_video_close,
+	.read =		pwc_video_read,
+	.poll =		pwc_video_poll,
+	.mmap =		pwc_video_mmap,
+	.ioctl =        pwc_video_ioctl,
+	.llseek =       no_llseek,
+};
+static struct video_device pwc_template = {
+	.owner =	THIS_MODULE,
+	.name =		"Philips Webcam",	/* Filled in later */
+	.type =		VID_TYPE_CAPTURE,
+	.hardware =	VID_HARDWARE_PWC,
+	.release =	video_device_release,
+	.fops =         &pwc_fops,
+	.minor =        -1,
+};
+
+/***************************************************************************/
+
+/* Okay, this is some magic that I worked out and the reasoning behind it...
+
+   The biggest problem with any USB device is of course: "what to do 
+   when the user unplugs the device while it is in use by an application?"
+   We have several options:
+   1) Curse them with the 7 plagues when they do (requires divine intervention)
+   2) Tell them not to (won't work: they'll do it anyway)
+   3) Oops the kernel (this will have a negative effect on a user's uptime)
+   4) Do something sensible.
+   
+   Of course, we go for option 4.
+
+   It happens that this device will be linked to two times, once from
+   usb_device and once from the video_device in their respective 'private'
+   pointers. This is done when the device is probed() and all initialization
+   succeeded. The pwc_device struct links back to both structures.
+
+   When a device is unplugged while in use it will be removed from the 
+   list of known USB devices; I also de-register it as a V4L device, but 
+   unfortunately I can't free the memory since the struct is still in use
+   by the file descriptor. This free-ing is then deferend until the first
+   opportunity. Crude, but it works.
+   
+   A small 'advantage' is that if a user unplugs the cam and plugs it back
+   in, it should get assigned the same video device minor, but unfortunately
+   it's non-trivial to re-link the cam back to the video device... (that 
+   would surely be magic! :))
+*/
+
+/***************************************************************************/
+/* Private functions */
+
+/* Here we want the physical address of the memory.
+ * This is used when initializing the contents of the area.
+ */
+static inline unsigned long kvirt_to_pa(unsigned long adr) 
+{
+        unsigned long kva, ret;
+
+	kva = (unsigned long) page_address(vmalloc_to_page((void *)adr));
+	kva |= adr & (PAGE_SIZE-1); /* restore the offset */
+	ret = __pa(kva);
+        return ret;
+}
+
+static void * rvmalloc(unsigned long size)
+{
+	void * mem;
+	unsigned long adr;
+
+	size=PAGE_ALIGN(size);
+        mem=vmalloc_32(size);
+	if (mem) 
+	{
+		memset(mem, 0, size); /* Clear the ram out, no junk to the user */
+	        adr=(unsigned long) mem;
+		while (size > 0) 
+                {
+			SetPageReserved(vmalloc_to_page((void *)adr));
+			adr+=PAGE_SIZE;
+			size-=PAGE_SIZE;
+		}
+	}
+	return mem;
+}
+
+static void rvfree(void * mem, unsigned long size)
+{
+        unsigned long adr;
+
+	if (mem) 
+	{
+	        adr=(unsigned long) mem;
+		while ((long) size > 0) 
+                {
+			ClearPageReserved(vmalloc_to_page((void *)adr));
+			adr+=PAGE_SIZE;
+			size-=PAGE_SIZE;
+		}
+		vfree(mem);
+	}
+}
+
+
+
+
+static int pwc_allocate_buffers(struct pwc_device *pdev)
+{
+	int i;
+	void *kbuf;
+
+	Trace(TRACE_MEMORY, ">> pwc_allocate_buffers(pdev = 0x%p)\n", pdev);
+
+	if (pdev == NULL)
+		return -ENXIO;
+		
+#ifdef PWC_MAGIC
+	if (pdev->magic != PWC_MAGIC) {
+		Err("allocate_buffers(): magic failed.\n");
+		return -ENXIO;
+	}
+#endif	
+	/* Allocate Isochronuous pipe buffers */
+	for (i = 0; i < MAX_ISO_BUFS; i++) {
+		if (pdev->sbuf[i].data == NULL) {
+			kbuf = kmalloc(ISO_BUFFER_SIZE, GFP_KERNEL);
+			if (kbuf == NULL) {
+				Err("Failed to allocate iso buffer %d.\n", i);
+				return -ENOMEM;
+			}
+			Trace(TRACE_MEMORY, "Allocated iso buffer at %p.\n", kbuf);
+			pdev->sbuf[i].data = kbuf;
+			memset(kbuf, 0, ISO_BUFFER_SIZE);
+		}
+	}
+
+	/* Allocate frame buffer structure */
+	if (pdev->fbuf == NULL) {
+		kbuf = kmalloc(default_fbufs * sizeof(struct pwc_frame_buf), GFP_KERNEL);
+		if (kbuf == NULL) {
+			Err("Failed to allocate frame buffer structure.\n");
+			return -ENOMEM;
+		}
+		Trace(TRACE_MEMORY, "Allocated frame buffer structure at %p.\n", kbuf);
+		pdev->fbuf = kbuf;
+		memset(kbuf, 0, default_fbufs * sizeof(struct pwc_frame_buf));
+	}
+	/* create frame buffers, and make circular ring */
+	for (i = 0; i < default_fbufs; i++) {
+		if (pdev->fbuf[i].data == NULL) {
+			kbuf = vmalloc(PWC_FRAME_SIZE); /* need vmalloc since frame buffer > 128K */
+			if (kbuf == NULL) {
+				Err("Failed to allocate frame buffer %d.\n", i);
+				return -ENOMEM;
+			}
+			Trace(TRACE_MEMORY, "Allocated frame buffer %d at %p.\n", i, kbuf);
+			pdev->fbuf[i].data = kbuf;
+			memset(kbuf, 128, PWC_FRAME_SIZE);
+		}
+	}
+	
+	/* Allocate decompressor table space */
+	kbuf = NULL;
+	switch (pdev->type)
+	 {
+	  case 675:
+	  case 680:
+	  case 690:
+	  case 720:
+	  case 730:
+	  case 740:
+	  case 750:
+	    Trace(TRACE_MEMORY,"private_data(%d)\n",sizeof(struct pwc_dec23_private));
+	    kbuf = kmalloc(sizeof(struct pwc_dec23_private), GFP_KERNEL);	/* Timon & Kiara */
+	    break;
+	  case 645:
+	  case 646:
+	    /* TODO & FIXME */
+	    kbuf = kmalloc(sizeof(struct pwc_dec23_private), GFP_KERNEL);
+	    break;
+	 }
+	if (kbuf == NULL) {
+	   Err("Failed to allocate decompress table.\n");
+	   return -ENOMEM;
+	}
+	pdev->decompress_data = kbuf;
+	
+	/* Allocate image buffer; double buffer for mmap() */
+	kbuf = rvmalloc(default_mbufs * pdev->len_per_image);
+	if (kbuf == NULL) {
+		Err("Failed to allocate image buffer(s). needed (%d)\n",default_mbufs * pdev->len_per_image);
+		return -ENOMEM;
+	}
+	Trace(TRACE_MEMORY, "Allocated image buffer at %p.\n", kbuf);
+	pdev->image_data = kbuf;
+	for (i = 0; i < default_mbufs; i++)
+		pdev->image_ptr[i] = kbuf + i * pdev->len_per_image;
+	for (; i < MAX_IMAGES; i++)
+		pdev->image_ptr[i] = NULL;
+
+	kbuf = NULL;
+	  
+	Trace(TRACE_MEMORY, "<< pwc_allocate_buffers()\n");
+	return 0;
+}
+
+static void pwc_free_buffers(struct pwc_device *pdev)
+{
+	int i;
+
+	Trace(TRACE_MEMORY, "Entering free_buffers(%p).\n", pdev);
+
+	if (pdev == NULL)
+		return;
+#ifdef PWC_MAGIC
+	if (pdev->magic != PWC_MAGIC) {
+		Err("free_buffers(): magic failed.\n");
+		return;
+	}
+#endif	
+
+	/* Release Iso-pipe buffers */
+	for (i = 0; i < MAX_ISO_BUFS; i++)
+		if (pdev->sbuf[i].data != NULL) {
+			Trace(TRACE_MEMORY, "Freeing ISO buffer at %p.\n", pdev->sbuf[i].data);
+			kfree(pdev->sbuf[i].data);
+			pdev->sbuf[i].data = NULL;
+		}
+
+	/* The same for frame buffers */
+	if (pdev->fbuf != NULL) {
+		for (i = 0; i < default_fbufs; i++) {
+			if (pdev->fbuf[i].data != NULL) {
+				Trace(TRACE_MEMORY, "Freeing frame buffer %d at %p.\n", i, pdev->fbuf[i].data);
+				vfree(pdev->fbuf[i].data);
+				pdev->fbuf[i].data = NULL;
+			}
+		}
+		kfree(pdev->fbuf);
+		pdev->fbuf = NULL;
+	}
+
+	/* Intermediate decompression buffer & tables */
+	if (pdev->decompress_data != NULL) {
+		Trace(TRACE_MEMORY, "Freeing decompression buffer at %p.\n", pdev->decompress_data);
+		kfree(pdev->decompress_data);
+		pdev->decompress_data = NULL;
+	}
+	pdev->decompressor = NULL;
+
+	/* Release image buffers */
+	if (pdev->image_data != NULL) {
+		Trace(TRACE_MEMORY, "Freeing image buffer at %p.\n", pdev->image_data);
+		rvfree(pdev->image_data, default_mbufs * pdev->len_per_image);
+	}
+	pdev->image_data = NULL;
+	
+	Trace(TRACE_MEMORY, "Leaving free_buffers().\n");
+}
+
+/* The frame & image buffer mess. 
+
+   Yes, this is a mess. Well, it used to be simple, but alas...  In this
+   module, 3 buffers schemes are used to get the data from the USB bus to
+   the user program. The first scheme involves the ISO buffers (called thus
+   since they transport ISO data from the USB controller), and not really
+   interesting. Suffices to say the data from this buffer is quickly 
+   gathered in an interrupt handler (pwc_isoc_handler) and placed into the
+   frame buffer.
+
+   The frame buffer is the second scheme, and is the central element here.
+   It collects the data from a single frame from the camera (hence, the
+   name). Frames are delimited by the USB camera with a short USB packet,
+   so that's easy to detect. The frame buffers form a list that is filled
+   by the camera+USB controller and drained by the user process through
+   either read() or mmap().
+
+   The image buffer is the third scheme, in which frames are decompressed
+   and converted into planar format. For mmap() there is more than
+   one image buffer available.
+
+   The frame buffers provide the image buffering. In case the user process
+   is a bit slow, this introduces lag and some undesired side-effects.
+   The problem arises when the frame buffer is full. I used to drop the last
+   frame, which makes the data in the queue stale very quickly. But dropping
+   the frame at the head of the queue proved to be a litte bit more difficult.
+   I tried a circular linked scheme, but this introduced more problems than
+   it solved.
+
+   Because filling and draining are completely asynchronous processes, this
+   requires some fiddling with pointers and mutexes.
+
+   Eventually, I came up with a system with 2 lists: an 'empty' frame list
+   and a 'full' frame list:
+     * Initially, all frame buffers but one are on the 'empty' list; the one
+       remaining buffer is our initial fill frame.
+     * If a frame is needed for filling, we try to take it from the 'empty' 
+       list, unless that list is empty, in which case we take the buffer at 
+       the head of the 'full' list.
+     * When our fill buffer has been filled, it is appended to the 'full'
+       list.
+     * If a frame is needed by read() or mmap(), it is taken from the head of
+       the 'full' list, handled, and then appended to the 'empty' list. If no
+       buffer is present on the 'full' list, we wait.
+   The advantage is that the buffer that is currently being decompressed/
+   converted, is on neither list, and thus not in our way (any other scheme
+   I tried had the problem of old data lingering in the queue).
+
+   Whatever strategy you choose, it always remains a tradeoff: with more
+   frame buffers the chances of a missed frame are reduced. On the other
+   hand, on slower machines it introduces lag because the queue will
+   always be full.
+ */
+
+/**
+  \brief Find next frame buffer to fill. Take from empty or full list, whichever comes first.
+ */
+static inline int pwc_next_fill_frame(struct pwc_device *pdev)
+{
+	int ret;
+	unsigned long flags;
+
+	ret = 0;
+	spin_lock_irqsave(&pdev->ptrlock, flags);
+	if (pdev->fill_frame != NULL) {
+		/* append to 'full' list */
+		if (pdev->full_frames == NULL) {
+			pdev->full_frames = pdev->fill_frame;
+			pdev->full_frames_tail = pdev->full_frames;
+		}
+		else {
+			pdev->full_frames_tail->next = pdev->fill_frame;
+			pdev->full_frames_tail = pdev->fill_frame;
+		}
+	}
+	if (pdev->empty_frames != NULL) {
+		/* We have empty frames available. That's easy */
+		pdev->fill_frame = pdev->empty_frames;
+		pdev->empty_frames = pdev->empty_frames->next;
+	}
+	else {
+		/* Hmm. Take it from the full list */
+#if PWC_DEBUG
+		/* sanity check */
+		if (pdev->full_frames == NULL) {
+			Err("Neither empty or full frames available!\n");
+			spin_unlock_irqrestore(&pdev->ptrlock, flags);
+			return -EINVAL;
+		}
+#endif
+		pdev->fill_frame = pdev->full_frames;
+		pdev->full_frames = pdev->full_frames->next;
+		ret = 1;
+	}
+	pdev->fill_frame->next = NULL;
+#if PWC_DEBUG
+	Trace(TRACE_SEQUENCE, "Assigning sequence number %d.\n", pdev->sequence);
+	pdev->fill_frame->sequence = pdev->sequence++;
+#endif
+	spin_unlock_irqrestore(&pdev->ptrlock, flags);
+	return ret;
+}
+
+
+/**
+  \brief Reset all buffers, pointers and lists, except for the image_used[] buffer.
+
+  If the image_used[] buffer is cleared too, mmap()/VIDIOCSYNC will run into trouble.
+ */
+static void pwc_reset_buffers(struct pwc_device *pdev)
+{
+	int i;
+	unsigned long flags;
+
+	spin_lock_irqsave(&pdev->ptrlock, flags);
+	pdev->full_frames = NULL;
+	pdev->full_frames_tail = NULL;
+	for (i = 0; i < default_fbufs; i++) {
+		pdev->fbuf[i].filled = 0;
+		if (i > 0)
+			pdev->fbuf[i].next = &pdev->fbuf[i - 1];
+		else
+			pdev->fbuf->next = NULL;
+	}
+	pdev->empty_frames = &pdev->fbuf[default_fbufs - 1];
+	pdev->empty_frames_tail = pdev->fbuf;
+	pdev->read_frame = NULL;
+	pdev->fill_frame = pdev->empty_frames;
+	pdev->empty_frames = pdev->empty_frames->next;
+
+	pdev->image_read_pos = 0;
+	pdev->fill_image = 0;
+	spin_unlock_irqrestore(&pdev->ptrlock, flags);
+}
+
+
+/**
+  \brief Do all the handling for getting one frame: get pointer, decompress, advance pointers.
+ */
+static int pwc_handle_frame(struct pwc_device *pdev)
+{
+	int ret = 0;
+	unsigned long flags;
+
+	spin_lock_irqsave(&pdev->ptrlock, flags);
+	/* First grab our read_frame; this is removed from all lists, so
+	   we can release the lock after this without problems */
+	if (pdev->read_frame != NULL) {
+		/* This can't theoretically happen */
+		Err("Huh? Read frame still in use?\n");
+	}
+	else {
+		if (pdev->full_frames == NULL) {
+			Err("Woops. No frames ready.\n");
+		}
+		else {
+			pdev->read_frame = pdev->full_frames;
+			pdev->full_frames = pdev->full_frames->next;
+			pdev->read_frame->next = NULL;
+		}
+
+		if (pdev->read_frame != NULL) {
+#if PWC_DEBUG
+			Trace(TRACE_SEQUENCE, "Decompressing frame %d\n", pdev->read_frame->sequence);
+#endif
+			/* Decompression is a lenghty process, so it's outside of the lock.
+			   This gives the isoc_handler the opportunity to fill more frames
+			   in the mean time.
+			*/
+			spin_unlock_irqrestore(&pdev->ptrlock, flags);
+			ret = pwc_decompress(pdev);
+			spin_lock_irqsave(&pdev->ptrlock, flags);
+
+			/* We're done with read_buffer, tack it to the end of the empty buffer list */
+			if (pdev->empty_frames == NULL) {
+				pdev->empty_frames = pdev->read_frame;
+				pdev->empty_frames_tail = pdev->empty_frames;
+			}
+			else {
+				pdev->empty_frames_tail->next = pdev->read_frame;
+				pdev->empty_frames_tail = pdev->read_frame;
+			}
+			pdev->read_frame = NULL;
+		}
+	}
+	spin_unlock_irqrestore(&pdev->ptrlock, flags);
+	return ret;
+}
+
+/**
+  \brief Advance pointers of image buffer (after each user request)
+*/
+static inline void pwc_next_image(struct pwc_device *pdev)
+{
+	pdev->image_used[pdev->fill_image] = 0;
+	pdev->fill_image = (pdev->fill_image + 1) % default_mbufs;
+}
+
+
+/* This gets called for the Isochronous pipe (video). This is done in
+ * interrupt time, so it has to be fast, not crash, and not stall. Neat.
+ */
+static void pwc_isoc_handler(struct urb *urb, struct pt_regs *regs)
+{
+	struct pwc_device *pdev;
+	int i, fst, flen;
+	int awake;
+	struct pwc_frame_buf *fbuf;
+	unsigned char *fillptr = 0, *iso_buf = 0;
+
+	awake = 0;
+	pdev = (struct pwc_device *)urb->context;
+	if (pdev == NULL) {
+		Err("isoc_handler() called with NULL device?!\n");
+		return;
+	}
+#ifdef PWC_MAGIC
+	if (pdev->magic != PWC_MAGIC) {
+		Err("isoc_handler() called with bad magic!\n");
+		return;
+	}
+#endif
+	if (urb->status == -ENOENT || urb->status == -ECONNRESET) {
+		Trace(TRACE_OPEN, "pwc_isoc_handler(): URB (%p) unlinked %ssynchronuously.\n", urb, urb->status == -ENOENT ? "" : "a");
+		return;
+	}
+	if (urb->status != -EINPROGRESS && urb->status != 0) {
+		const char *errmsg;
+
+		errmsg = "Unknown";
+		switch(urb->status) {
+			case -ENOSR:		errmsg = "Buffer error (overrun)"; break;
+			case -EPIPE:		errmsg = "Stalled (device not responding)"; break;
+			case -EOVERFLOW:	errmsg = "Babble (bad cable?)"; break;
+			case -EPROTO:		errmsg = "Bit-stuff error (bad cable?)"; break;
+			case -EILSEQ:		errmsg = "CRC/Timeout (could be anything)"; break;
+			case -ETIMEDOUT:	errmsg = "NAK (device does not respond)"; break;
+		}
+		Trace(TRACE_FLOW, "pwc_isoc_handler() called with status %d [%s].\n", urb->status, errmsg);
+		/* Give up after a number of contiguous errors on the USB bus. 
+		   Appearantly something is wrong so we simulate an unplug event.
+		 */
+		if (++pdev->visoc_errors > MAX_ISOC_ERRORS)
+		{
+			Info("Too many ISOC errors, bailing out.\n");
+			pdev->error_status = EIO;
+			awake = 1;
+			wake_up_interruptible(&pdev->frameq);
+		}
+		goto handler_end; // ugly, but practical
+	}
+
+	fbuf = pdev->fill_frame;
+	if (fbuf == NULL) {
+		Err("pwc_isoc_handler without valid fill frame.\n");
+		awake = 1;
+		goto handler_end;
+	}
+	else {
+		fillptr = fbuf->data + fbuf->filled;
+	}
+
+	/* Reset ISOC error counter. We did get here, after all. */
+	pdev->visoc_errors = 0;
+
+	/* vsync: 0 = don't copy data
+	          1 = sync-hunt
+	          2 = synched
+	 */
+	/* Compact data */
+	for (i = 0; i < urb->number_of_packets; i++) {
+		fst  = urb->iso_frame_desc[i].status;
+		flen = urb->iso_frame_desc[i].actual_length;
+		iso_buf = urb->transfer_buffer + urb->iso_frame_desc[i].offset;
+		if (fst == 0) {
+			if (flen > 0) { /* if valid data... */
+				if (pdev->vsync > 0) { /* ...and we are not sync-hunting... */
+					pdev->vsync = 2;
+
+					/* ...copy data to frame buffer, if possible */
+					if (flen + fbuf->filled > pdev->frame_total_size) {
+						Trace(TRACE_FLOW, "Frame buffer overflow (flen = %d, frame_total_size = %d).\n", flen, pdev->frame_total_size);
+						pdev->vsync = 0; /* Hmm, let's wait for an EOF (end-of-frame) */
+						pdev->vframes_error++;
+					}
+					else {
+						memmove(fillptr, iso_buf, flen);
+						fillptr += flen;
+					}
+				}
+				fbuf->filled += flen;
+			} /* ..flen > 0 */
+
+			if (flen < pdev->vlast_packet_size) {
+				/* Shorter packet... We probably have the end of an image-frame; 
+				   wake up read() process and let select()/poll() do something.
+				   Decompression is done in user time over there.
+				 */
+				if (pdev->vsync == 2) {
+					/* The ToUCam Fun CMOS sensor causes the firmware to send 2 or 3 bogus 
+					   frames on the USB wire after an exposure change. This conditition is 
+					   however detected  in the cam and a bit is set in the header.
+					 */
+					if (pdev->type == 730) {
+						unsigned char *ptr = (unsigned char *)fbuf->data;
+						
+						if (ptr[1] == 1 && ptr[0] & 0x10) {
+#if PWC_DEBUG
+							Debug("Hyundai CMOS sensor bug. Dropping frame %d.\n", fbuf->sequence);
+#endif
+							pdev->drop_frames += 2;
+							pdev->vframes_error++;
+						}
+						if ((ptr[0] ^ pdev->vmirror) & 0x01) {
+							if (ptr[0] & 0x01)
+								Info("Snapshot button pressed.\n");
+							else
+								Info("Snapshot button released.\n");
+						}
+						if ((ptr[0] ^ pdev->vmirror) & 0x02) {
+							if (ptr[0] & 0x02)
+								Info("Image is mirrored.\n");
+							else
+								Info("Image is normal.\n");
+						}
+						pdev->vmirror = ptr[0] & 0x03;
+						/* Sometimes the trailer of the 730 is still sent as a 4 byte packet 
+						   after a short frame; this condition is filtered out specifically. A 4 byte
+						   frame doesn't make sense anyway.
+						   So we get either this sequence: 
+						   	drop_bit set -> 4 byte frame -> short frame -> good frame
+						   Or this one:
+						   	drop_bit set -> short frame -> good frame
+						   So we drop either 3 or 2 frames in all!
+						 */
+						if (fbuf->filled == 4)
+							pdev->drop_frames++;
+					}
+
+					/* In case we were instructed to drop the frame, do so silently.
+					   The buffer pointers are not updated either (but the counters are reset below).
+					 */
+					if (pdev->drop_frames > 0)
+						pdev->drop_frames--;
+					else {
+						/* Check for underflow first */
+						if (fbuf->filled < pdev->frame_total_size) {
+							Trace(TRACE_FLOW, "Frame buffer underflow (%d bytes); discarded.\n", fbuf->filled);
+							pdev->vframes_error++;
+						}
+						else {
+							/* Send only once per EOF */
+							awake = 1; /* delay wake_ups */
+
+							/* Find our next frame to fill. This will always succeed, since we
+							 * nick a frame from either empty or full list, but if we had to
+							 * take it from the full list, it means a frame got dropped.
+							 */
+							if (pwc_next_fill_frame(pdev)) {
+								pdev->vframes_dumped++;
+								if ((pdev->vframe_count > FRAME_LOWMARK) && (pwc_trace & TRACE_FLOW)) {
+									if (pdev->vframes_dumped < 20)
+										Trace(TRACE_FLOW, "Dumping frame %d.\n", pdev->vframe_count);
+									if (pdev->vframes_dumped == 20)
+										Trace(TRACE_FLOW, "Dumping frame %d (last message).\n", pdev->vframe_count);
+								}
+							}
+							fbuf = pdev->fill_frame;
+						}
+					} /* !drop_frames */
+					pdev->vframe_count++;
+				}
+				fbuf->filled = 0;
+				fillptr = fbuf->data;
+				pdev->vsync = 1;
+			} /* .. flen < last_packet_size */
+			pdev->vlast_packet_size = flen;
+		} /* ..status == 0 */
+#if PWC_DEBUG
+		/* This is normally not interesting to the user, unless you are really debugging something */
+		else {
+			static int iso_error = 0;
+			iso_error++;
+			if (iso_error < 20)
+				Trace(TRACE_FLOW, "Iso frame %d of USB has error %d\n", i, fst);
+		}
+#endif
+	}
+
+handler_end:
+	if (awake)
+		wake_up_interruptible(&pdev->frameq);
+
+	urb->dev = pdev->udev;
+	i = usb_submit_urb(urb, GFP_ATOMIC);
+	if (i != 0)
+		Err("Error (%d) re-submitting urb in pwc_isoc_handler.\n", i);
+}
+
+
+static int pwc_isoc_init(struct pwc_device *pdev)
+{
+	struct usb_device *udev;
+	struct urb *urb;
+	int i, j, ret;
+
+	struct usb_interface *intf;
+	struct usb_host_interface *idesc = NULL;
+
+	if (pdev == NULL)
+		return -EFAULT;
+	if (pdev->iso_init)
+		return 0;
+	pdev->vsync = 0;
+	udev = pdev->udev;
+
+	/* Get the current alternate interface, adjust packet size */
+	if (!udev->actconfig)
+		return -EFAULT;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,5)
+	idesc = &udev->actconfig->interface[0]->altsetting[pdev->valternate];
+#else
+	intf = usb_ifnum_to_if(udev, 0);
+	if (intf)
+		idesc = usb_altnum_to_altsetting(intf, pdev->valternate);
+#endif
+		
+	if (!idesc)
+		return -EFAULT;
+
+	/* Search video endpoint */
+	pdev->vmax_packet_size = -1;
+	for (i = 0; i < idesc->desc.bNumEndpoints; i++)
+		if ((idesc->endpoint[i].desc.bEndpointAddress & 0xF) == pdev->vendpoint) {
+			pdev->vmax_packet_size = idesc->endpoint[i].desc.wMaxPacketSize;
+			break;
+		}
+	
+	if (pdev->vmax_packet_size < 0 || pdev->vmax_packet_size > ISO_MAX_FRAME_SIZE) {
+		Err("Failed to find packet size for video endpoint in current alternate setting.\n");
+		return -ENFILE; /* Odd error, that should be noticable */
+	}
+
+	/* Set alternate interface */
+	ret = 0;
+	Trace(TRACE_OPEN, "Setting alternate interface %d\n", pdev->valternate);
+	ret = usb_set_interface(pdev->udev, 0, pdev->valternate);
+	if (ret < 0)
+		return ret;
+
+	for (i = 0; i < MAX_ISO_BUFS; i++) {
+		urb = usb_alloc_urb(ISO_FRAMES_PER_DESC, GFP_KERNEL);
+		if (urb == NULL) {
+			Err("Failed to allocate urb %d\n", i);
+			ret = -ENOMEM;
+			break;
+		}
+		pdev->sbuf[i].urb = urb;
+		Trace(TRACE_MEMORY, "Allocated URB at 0x%p\n", urb);
+	}
+	if (ret) {
+		/* De-allocate in reverse order */
+		while (i >= 0) {
+			if (pdev->sbuf[i].urb != NULL)
+				usb_free_urb(pdev->sbuf[i].urb);
+			pdev->sbuf[i].urb = NULL;
+			i--;
+		}
+		return ret;
+	}
+
+	/* init URB structure */	
+	for (i = 0; i < MAX_ISO_BUFS; i++) {
+		urb = pdev->sbuf[i].urb;
+
+		urb->interval = 1; // devik
+		urb->dev = udev;
+	        urb->pipe = usb_rcvisocpipe(udev, pdev->vendpoint);
+		urb->transfer_flags = URB_ISO_ASAP;
+	        urb->transfer_buffer = pdev->sbuf[i].data;
+	        urb->transfer_buffer_length = ISO_BUFFER_SIZE;
+	        urb->complete = pwc_isoc_handler;
+	        urb->context = pdev;
+		urb->start_frame = 0;
+		urb->number_of_packets = ISO_FRAMES_PER_DESC;
+		for (j = 0; j < ISO_FRAMES_PER_DESC; j++) {
+			urb->iso_frame_desc[j].offset = j * ISO_MAX_FRAME_SIZE;
+			urb->iso_frame_desc[j].length = pdev->vmax_packet_size;
+		}
+	}
+
+	/* link */
+	for (i = 0; i < MAX_ISO_BUFS; i++) {
+		ret = usb_submit_urb(pdev->sbuf[i].urb, GFP_KERNEL);
+		if (ret)
+			Err("isoc_init() submit_urb %d failed with error %d\n", i, ret);
+		else
+			Trace(TRACE_MEMORY, "URB 0x%p submitted.\n", pdev->sbuf[i].urb);
+	}
+
+	/* All is done... */
+	pdev->iso_init = 1;
+	Trace(TRACE_OPEN, "<< pwc_isoc_init()\n");
+	return 0;
+}
+
+static void pwc_isoc_cleanup(struct pwc_device *pdev)
+{
+	int i;
+
+	Trace(TRACE_OPEN, ">> pwc_isoc_cleanup()\n");
+	if (pdev == NULL)
+		return;
+
+	/* Unlinking ISOC buffers one by one */
+	for (i = 0; i < MAX_ISO_BUFS; i++) {
+		struct urb *urb;
+
+		urb = pdev->sbuf[i].urb;
+		if (urb != 0) {
+			if (pdev->iso_init) {
+				Trace(TRACE_MEMORY, "Unlinking URB %p\n", urb);
+				usb_kill_urb(urb);
+			}
+			Trace(TRACE_MEMORY, "Freeing URB\n");
+			usb_free_urb(urb);
+			pdev->sbuf[i].urb = NULL;
+		}
+	}
+
+	/* Stop camera, but only if we are sure the camera is still there (unplug
+	   is signalled by EPIPE) 
+	 */
+	if (pdev->error_status && pdev->error_status != EPIPE) {
+		Trace(TRACE_OPEN, "Setting alternate interface 0.\n");
+		usb_set_interface(pdev->udev, 0, 0);
+	}
+
+	pdev->iso_init = 0;
+	Trace(TRACE_OPEN, "<< pwc_isoc_cleanup()\n");
+}
+
+int pwc_try_video_mode(struct pwc_device *pdev, int width, int height, int new_fps, int new_compression, int new_snapshot)
+{
+	int ret, start;
+
+	/* Stop isoc stuff */
+	pwc_isoc_cleanup(pdev);
+	/* Reset parameters */
+	pwc_reset_buffers(pdev);
+	/* Try to set video mode... */
+	start = ret = pwc_set_video_mode(pdev, width, height, new_fps, new_compression, new_snapshot);
+	if (ret) { 
+	        Trace(TRACE_FLOW, "pwc_set_video_mode attempt 1 failed.\n");
+		/* That failed... restore old mode (we know that worked) */
+		start = pwc_set_video_mode(pdev, pdev->view.x, pdev->view.y, pdev->vframes, pdev->vcompression, pdev->vsnapshot);
+		if (start) {
+		        Trace(TRACE_FLOW, "pwc_set_video_mode attempt 2 failed.\n");
+		}
+	}
+	if (start == 0)
+	{
+		if (pwc_isoc_init(pdev) < 0)
+		{
+			Info("Failed to restart ISOC transfers in pwc_try_video_mode.\n");
+			ret = -EAGAIN; /* let's try again, who knows if it works a second time */
+		}
+	}
+	pdev->drop_frames++; /* try to avoid garbage during switch */
+	return ret; /* Return original error code */
+}
+
+
+/***************************************************************************/
+/* Video4Linux functions */
+
+static int pwc_video_open(struct inode *inode, struct file *file)
+{
+	int i;
+	struct video_device *vdev = video_devdata(file);
+	struct pwc_device *pdev;
+
+	Trace(TRACE_OPEN, ">> video_open called(vdev = 0x%p).\n", vdev);
+	
+	pdev = (struct pwc_device *)vdev->priv;
+	if (pdev == NULL)
+		BUG();
+	if (pdev->vopen)
+		return -EBUSY;
+	
+	down(&pdev->modlock);
+	if (!pdev->usb_init) {
+		Trace(TRACE_OPEN, "Doing first time initialization.\n");
+		pdev->usb_init = 1;
+		
+		if (pwc_trace & TRACE_OPEN)
+		{
+			/* Query sensor type */
+			const char *sensor_type = NULL;
+			int ret;
+
+			ret = pwc_get_cmos_sensor(pdev, &i);
+			if (ret >= 0)
+			{
+				switch(i) {
+				case 0x00:  sensor_type = "Hyundai CMOS sensor"; break;
+				case 0x20:  sensor_type = "Sony CCD sensor + TDA8787"; break;
+				case 0x2E:  sensor_type = "Sony CCD sensor + Exas 98L59"; break;
+				case 0x2F:  sensor_type = "Sony CCD sensor + ADI 9804"; break;
+				case 0x30:  sensor_type = "Sharp CCD sensor + TDA8787"; break;
+				case 0x3E:  sensor_type = "Sharp CCD sensor + Exas 98L59"; break;
+				case 0x3F:  sensor_type = "Sharp CCD sensor + ADI 9804"; break;
+				case 0x40:  sensor_type = "UPA 1021 sensor"; break;
+				case 0x100: sensor_type = "VGA sensor"; break;
+				case 0x101: sensor_type = "PAL MR sensor"; break;
+				default:    sensor_type = "unknown type of sensor"; break;
+				}
+			}
+			if (sensor_type != NULL)
+				Info("This %s camera is equipped with a %s (%d).\n", pdev->vdev->name, sensor_type, i);
+		}
+	}
+
+	/* Turn on camera */
+	if (power_save) {
+		i = pwc_camera_power(pdev, 1);
+		if (i < 0)
+			Info("Failed to restore power to the camera! (%d)\n", i);
+	}
+	/* Set LED on/off time */
+	if (pwc_set_leds(pdev, led_on, led_off) < 0)
+		Info("Failed to set LED on/off time.\n");
+	
+	pwc_construct(pdev); /* set min/max sizes correct */
+
+	/* So far, so good. Allocate memory. */
+	i = pwc_allocate_buffers(pdev);
+	if (i < 0) {
+		Trace(TRACE_OPEN, "Failed to allocate buffer memory.\n");
+		up(&pdev->modlock);
+		return i;
+	}
+	
+	/* Reset buffers & parameters */
+	pwc_reset_buffers(pdev);
+	for (i = 0; i < default_mbufs; i++)
+		pdev->image_used[i] = 0;
+	pdev->vframe_count = 0;
+	pdev->vframes_dumped = 0;
+	pdev->vframes_error = 0;
+	pdev->visoc_errors = 0;
+	pdev->error_status = 0;
+#if PWC_DEBUG
+	pdev->sequence = 0;
+#endif
+	pwc_construct(pdev); /* set min/max sizes correct */
+
+	/* Set some defaults */
+	pdev->vsnapshot = 0;
+
+	/* Start iso pipe for video; first try the last used video size
+	   (or the default one); if that fails try QCIF/10 or QSIF/10;
+	   it that fails too, give up.
+	 */
+	i = pwc_set_video_mode(pdev, pwc_image_sizes[pdev->vsize].x, pwc_image_sizes[pdev->vsize].y, pdev->vframes, pdev->vcompression, 0);
+	if (i)	{
+		Trace(TRACE_OPEN, "First attempt at set_video_mode failed.\n");
+		if (pdev->type == 730 || pdev->type == 740 || pdev->type == 750)
+			i = pwc_set_video_mode(pdev, pwc_image_sizes[PSZ_QSIF].x, pwc_image_sizes[PSZ_QSIF].y, 10, pdev->vcompression, 0);
+		else
+			i = pwc_set_video_mode(pdev, pwc_image_sizes[PSZ_QCIF].x, pwc_image_sizes[PSZ_QCIF].y, 10, pdev->vcompression, 0);
+	}
+	if (i) {
+		Trace(TRACE_OPEN, "Second attempt at set_video_mode failed.\n");
+		up(&pdev->modlock);
+		return i;
+	}
+	
+	i = pwc_isoc_init(pdev);
+	if (i) {
+		Trace(TRACE_OPEN, "Failed to init ISOC stuff = %d.\n", i);
+		up(&pdev->modlock);
+		return i;
+	}
+
+	pdev->vopen++;
+	file->private_data = vdev;
+	up(&pdev->modlock);
+	Trace(TRACE_OPEN, "<< video_open() returns 0.\n");
+	return 0;
+}
+
+/* Note that all cleanup is done in the reverse order as in _open */
+static int pwc_video_close(struct inode *inode, struct file *file)
+{
+	struct video_device *vdev = file->private_data;
+	struct pwc_device *pdev;
+	int i;
+
+	Trace(TRACE_OPEN, ">> video_close called(vdev = 0x%p).\n", vdev);
+
+	pdev = (struct pwc_device *)vdev->priv;
+	if (pdev->vopen == 0)
+		Info("video_close() called on closed device?\n");
+
+	/* Dump statistics, but only if a reasonable amount of frames were
+	   processed (to prevent endless log-entries in case of snap-shot
+	   programs)
+	 */
+	if (pdev->vframe_count > 20)
+		Info("Closing video device: %d frames received, dumped %d frames, %d frames with errors.\n", pdev->vframe_count, pdev->vframes_dumped, pdev->vframes_error);
+
+	switch (pdev->type)
+	 {
+	  case 675:
+	  case 680:
+	  case 690:
+	  case 720:
+	  case 730:
+	  case 740:
+	  case 750:
+	    pwc_dec23_exit();	/* Timon & Kiara */
+	    break;
+	  case 645:
+	  case 646:
+	    pwc_dec1_exit();
+	    break;
+	 }
+
+	pwc_isoc_cleanup(pdev);
+	pwc_free_buffers(pdev);
+
+	/* Turn off LEDS and power down camera, but only when not unplugged */
+	if (pdev->error_status != EPIPE) {
+		/* Turn LEDs off */
+		if (pwc_set_leds(pdev, 0, 0) < 0)
+			Info("Failed to set LED on/off time.\n");
+		if (power_save) {
+			i = pwc_camera_power(pdev, 0);
+			if (i < 0)
+				Err("Failed to power down camera (%d)\n", i);
+		}
+	}
+	pdev->vopen = 0;
+	Trace(TRACE_OPEN, "<< video_close()\n");
+	return 0;
+}
+
+/*
+ *	FIXME: what about two parallel reads ????
+ *      ANSWER: Not supported. You can't open the device more than once,
+                despite what the V4L1 interface says. First, I don't see
+                the need, second there's no mechanism of alerting the
+                2nd/3rd/... process of events like changing image size.
+                And I don't see the point of blocking that for the
+                2nd/3rd/... process.
+                In multi-threaded environments reading parallel from any
+                device is tricky anyhow.
+ */
+
+static ssize_t pwc_video_read(struct file *file, char *buf,
+			  size_t count, loff_t *ppos)
+{
+	struct video_device *vdev = file->private_data;
+	struct pwc_device *pdev;
+	int noblock = file->f_flags & O_NONBLOCK;
+	DECLARE_WAITQUEUE(wait, current);
+        int bytes_to_read;
+
+	Trace(TRACE_READ, "video_read(0x%p, %p, %d) called.\n", vdev, buf, count);
+	if (vdev == NULL)
+		return -EFAULT;
+	pdev = vdev->priv;
+	if (pdev == NULL)
+		return -EFAULT;
+	if (pdev->error_status)
+		return -pdev->error_status; /* Something happened, report what. */
+
+	/* In case we're doing partial reads, we don't have to wait for a frame */
+	if (pdev->image_read_pos == 0) {
+		/* Do wait queueing according to the (doc)book */
+		add_wait_queue(&pdev->frameq, &wait);
+		while (pdev->full_frames == NULL) {
+			/* Check for unplugged/etc. here */
+			if (pdev->error_status) {
+				remove_wait_queue(&pdev->frameq, &wait);
+				set_current_state(TASK_RUNNING);
+				return -pdev->error_status ;
+			}
+	                if (noblock) {
+	                	remove_wait_queue(&pdev->frameq, &wait);
+	                	set_current_state(TASK_RUNNING);
+	                	return -EWOULDBLOCK;
+	                }
+	                if (signal_pending(current)) {
+	                	remove_wait_queue(&pdev->frameq, &wait);
+	                	set_current_state(TASK_RUNNING);
+	                	return -ERESTARTSYS;
+	                }
+	                schedule();
+	               	set_current_state(TASK_INTERRUPTIBLE);
+		}
+		remove_wait_queue(&pdev->frameq, &wait);
+		set_current_state(TASK_RUNNING);
+                                                                                                                                                                                
+		/* Decompress and release frame */
+		if (pwc_handle_frame(pdev))
+			return -EFAULT;
+	}
+
+	Trace(TRACE_READ, "Copying data to user space.\n");
+	if (pdev->vpalette == VIDEO_PALETTE_RAW)
+		bytes_to_read = pdev->frame_size;
+	else
+ 		bytes_to_read = pdev->view.size;
+
+	/* copy bytes to user space; we allow for partial reads */
+	if (count + pdev->image_read_pos > bytes_to_read)
+		count = bytes_to_read - pdev->image_read_pos;
+	if (copy_to_user(buf, pdev->image_ptr[pdev->fill_image] + pdev->image_read_pos, count))
+		return -EFAULT;
+	pdev->image_read_pos += count;
+	if (pdev->image_read_pos >= bytes_to_read) { /* All data has been read */
+		pdev->image_read_pos = 0;
+		pwc_next_image(pdev);
+	}
+	return count;
+}
+
+static unsigned int pwc_video_poll(struct file *file, poll_table *wait)
+{
+	struct video_device *vdev = file->private_data;
+	struct pwc_device *pdev;
+
+	if (vdev == NULL)
+		return -EFAULT;
+	pdev = vdev->priv;
+	if (pdev == NULL)
+		return -EFAULT;
+
+	poll_wait(file, &pdev->frameq, wait);
+	if (pdev->error_status)
+		return POLLERR;
+	if (pdev->full_frames != NULL) /* we have frames waiting */
+		return (POLLIN | POLLRDNORM);
+
+	return 0;
+}
+
+static int pwc_video_do_ioctl(struct inode *inode, struct file *file,
+			      unsigned int cmd, void *arg)
+{
+	struct video_device *vdev = file->private_data;
+	struct pwc_device *pdev;
+	DECLARE_WAITQUEUE(wait, current);
+
+	if (vdev == NULL)
+		return -EFAULT;
+	pdev = vdev->priv;
+	if (pdev == NULL)
+		return -EFAULT;
+
+	switch (cmd) {
+		/* Query cabapilities */
+		case VIDIOCGCAP:
+		{
+			struct video_capability *caps = arg;
+
+			strcpy(caps->name, vdev->name);
+			caps->type = VID_TYPE_CAPTURE;
+			caps->channels = 1;
+			caps->audios = 1;
+			caps->minwidth  = pdev->view_min.x;
+			caps->minheight = pdev->view_min.y;
+			caps->maxwidth  = pdev->view_max.x;
+			caps->maxheight = pdev->view_max.y;
+			break;
+		}
+
+		/* Channel functions (simulate 1 channel) */
+		case VIDIOCGCHAN:
+		{
+			struct video_channel *v = arg;
+
+			if (v->channel != 0)
+				return -EINVAL;
+			v->flags = 0;
+			v->tuners = 0;
+			v->type = VIDEO_TYPE_CAMERA;
+			strcpy(v->name, "Webcam");
+			return 0;
+		}
+
+		case VIDIOCSCHAN:
+		{
+			/* The spec says the argument is an integer, but
+			   the bttv driver uses a video_channel arg, which
+			   makes sense becasue it also has the norm flag.
+			 */
+			struct video_channel *v = arg;
+			if (v->channel != 0)
+				return -EINVAL;
+			return 0;
+		}
+
+
+		/* Picture functions; contrast etc. */
+		case VIDIOCGPICT:
+		{
+			struct video_picture *p = arg;
+			int val;
+
+			val = pwc_get_brightness(pdev);
+			if (val >= 0)
+				p->brightness = val;
+			else
+				p->brightness = 0xffff;
+			val = pwc_get_contrast(pdev);
+			if (val >= 0)
+				p->contrast = val;
+			else
+				p->contrast = 0xffff;
+			/* Gamma, Whiteness, what's the difference? :) */
+			val = pwc_get_gamma(pdev);
+			if (val >= 0)
+				p->whiteness = val;
+			else
+				p->whiteness = 0xffff;
+			val = pwc_get_saturation(pdev);
+			if (val >= 0)
+				p->colour = val;
+			else
+				p->colour = 0xffff;
+			p->depth = 24;
+			p->palette = pdev->vpalette;
+			p->hue = 0xFFFF; /* N/A */
+			break;
+		}
+
+		case VIDIOCSPICT:
+		{
+			struct video_picture *p = arg;
+			/*
+			 *	FIXME:	Suppose we are mid read
+			        ANSWER: No problem: the firmware of the camera
+			                can handle brightness/contrast/etc
+			                changes at _any_ time, and the palette
+			                is used exactly once in the uncompress
+			                routine.
+			 */
+			pwc_set_brightness(pdev, p->brightness);
+			pwc_set_contrast(pdev, p->contrast);
+			pwc_set_gamma(pdev, p->whiteness);
+			pwc_set_saturation(pdev, p->colour);
+			if (p->palette && p->palette != pdev->vpalette) {
+				switch (p->palette) {
+					case VIDEO_PALETTE_YUV420P:
+					case VIDEO_PALETTE_RAW:
+						pdev->vpalette = p->palette;
+						return pwc_try_video_mode(pdev, pdev->image.x, pdev->image.y, pdev->vframes, pdev->vcompression, pdev->vsnapshot);
+						break;
+					default:
+						return -EINVAL;
+						break;
+				}
+			}
+			break;
+		}
+
+		/* Window/size parameters */		
+		case VIDIOCGWIN:
+		{
+			struct video_window *vw = arg;
+			
+			vw->x = 0;
+			vw->y = 0;
+			vw->width = pdev->view.x;
+			vw->height = pdev->view.y;
+			vw->chromakey = 0;
+			vw->flags = (pdev->vframes << PWC_FPS_SHIFT) | 
+			           (pdev->vsnapshot ? PWC_FPS_SNAPSHOT : 0);
+			break;
+		}
+		
+		case VIDIOCSWIN:
+		{
+			struct video_window *vw = arg;
+			int fps, snapshot, ret;
+
+			fps = (vw->flags & PWC_FPS_FRMASK) >> PWC_FPS_SHIFT;
+			snapshot = vw->flags & PWC_FPS_SNAPSHOT;
+			if (fps == 0)
+				fps = pdev->vframes;
+			if (pdev->view.x == vw->width && pdev->view.y && fps == pdev->vframes && snapshot == pdev->vsnapshot)
+				return 0;
+			ret = pwc_try_video_mode(pdev, vw->width, vw->height, fps, pdev->vcompression, snapshot);
+			if (ret)
+				return ret;
+			break;		
+		}
+		
+		/* We don't have overlay support (yet) */
+		case VIDIOCGFBUF:
+		{
+			struct video_buffer *vb = arg;
+
+			memset(vb,0,sizeof(*vb));
+			break;
+		}
+
+		/* mmap() functions */
+		case VIDIOCGMBUF:
+		{
+			/* Tell the user program how much memory is needed for a mmap() */
+			struct video_mbuf *vm = arg;
+			int i;
+
+			memset(vm, 0, sizeof(*vm));
+			vm->size = default_mbufs * pdev->len_per_image;
+			vm->frames = default_mbufs; /* double buffering should be enough for most applications */
+			for (i = 0; i < default_mbufs; i++)
+				vm->offsets[i] = i * pdev->len_per_image;
+			break;
+		}
+
+		case VIDIOCMCAPTURE:
+		{
+			/* Start capture into a given image buffer (called 'frame' in video_mmap structure) */
+			struct video_mmap *vm = arg;
+
+			Trace(TRACE_READ, "VIDIOCMCAPTURE: %dx%d, frame %d, format %d\n", vm->width, vm->height, vm->frame, vm->format);
+			if (vm->frame < 0 || vm->frame >= default_mbufs)
+				return -EINVAL;
+
+			/* xawtv is nasty. It probes the available palettes
+			   by setting a very small image size and trying
+			   various palettes... The driver doesn't support
+			   such small images, so I'm working around it.
+			 */
+			if (vm->format)
+			{
+				switch (vm->format)
+				{
+					case VIDEO_PALETTE_YUV420P:
+					case VIDEO_PALETTE_RAW:
+						break;
+					default:
+						return -EINVAL;
+						break;
+				}
+			}
+
+			if ((vm->width != pdev->view.x || vm->height != pdev->view.y) &&
+			    (vm->width >= pdev->view_min.x && vm->height >= pdev->view_min.y)) {
+				int ret;
+
+				Trace(TRACE_OPEN, "VIDIOCMCAPTURE: changing size to please xawtv :-(.\n");
+				ret = pwc_try_video_mode(pdev, vm->width, vm->height, pdev->vframes, pdev->vcompression, pdev->vsnapshot);
+				if (ret)
+					return ret;
+			} /* ... size mismatch */
+
+			/* FIXME: should we lock here? */
+			if (pdev->image_used[vm->frame])
+				return -EBUSY;	/* buffer wasn't available. Bummer */
+			pdev->image_used[vm->frame] = 1;
+
+			/* Okay, we're done here. In the SYNC call we wait until a 
+			   frame comes available, then expand image into the given 
+			   buffer.
+			   In contrast to the CPiA cam the Philips cams deliver a
+			   constant stream, almost like a grabber card. Also,
+			   we have separate buffers for the rawdata and the image,
+			   meaning we can nearly always expand into the requested buffer.
+			 */
+			Trace(TRACE_READ, "VIDIOCMCAPTURE done.\n");
+			break;
+		}
+
+		case VIDIOCSYNC:
+		{
+			/* The doc says: "Whenever a buffer is used it should
+			   call VIDIOCSYNC to free this frame up and continue."
+			   
+			   The only odd thing about this whole procedure is 
+			   that MCAPTURE flags the buffer as "in use", and
+			   SYNC immediately unmarks it, while it isn't 
+			   after SYNC that you know that the buffer actually
+			   got filled! So you better not start a CAPTURE in
+			   the same frame immediately (use double buffering). 
+			   This is not a problem for this cam, since it has 
+			   extra intermediate buffers, but a hardware 
+			   grabber card will then overwrite the buffer 
+			   you're working on.
+			 */
+			int *mbuf = arg;
+			int ret;
+
+			Trace(TRACE_READ, "VIDIOCSYNC called (%d).\n", *mbuf);
+
+			/* bounds check */
+			if (*mbuf < 0 || *mbuf >= default_mbufs)
+				return -EINVAL;
+			/* check if this buffer was requested anyway */
+			if (pdev->image_used[*mbuf] == 0)
+				return -EINVAL;
+
+			/* Add ourselves to the frame wait-queue.
+			   
+			   FIXME: needs auditing for safety.
+			   QUESTION: In what respect? I think that using the
+			             frameq is safe now.
+			 */
+			add_wait_queue(&pdev->frameq, &wait);
+			while (pdev->full_frames == NULL) {
+				if (pdev->error_status) {
+					remove_wait_queue(&pdev->frameq, &wait);
+					set_current_state(TASK_RUNNING);
+					return -pdev->error_status;
+				}
+			
+	                	if (signal_pending(current)) {
+	                		remove_wait_queue(&pdev->frameq, &wait);
+		                	set_current_state(TASK_RUNNING);
+		                	return -ERESTARTSYS;
+	        	        }
+	                	schedule();
+		                set_current_state(TASK_INTERRUPTIBLE);
+			}
+			remove_wait_queue(&pdev->frameq, &wait);
+			set_current_state(TASK_RUNNING);
+				
+			/* The frame is ready. Expand in the image buffer 
+			   requested by the user. I don't care if you 
+			   mmap() 5 buffers and request data in this order: 
+			   buffer 4 2 3 0 1 2 3 0 4 3 1 . . .
+			   Grabber hardware may not be so forgiving.
+			 */
+			Trace(TRACE_READ, "VIDIOCSYNC: frame ready.\n");
+			pdev->fill_image = *mbuf; /* tell in which buffer we want the image to be expanded */
+			/* Decompress, etc */
+			ret = pwc_handle_frame(pdev);
+			pdev->image_used[*mbuf] = 0;
+			if (ret)
+				return -EFAULT;
+			break;
+		}
+		
+		case VIDIOCGAUDIO:
+		{
+			struct video_audio *v = arg;
+			
+			strcpy(v->name, "Microphone");
+			v->audio = -1; /* unknown audio minor */
+			v->flags = 0;
+			v->mode = VIDEO_SOUND_MONO;
+			v->volume = 0;
+			v->bass = 0;
+			v->treble = 0;
+			v->balance = 0x8000;
+			v->step = 1;
+			break;	
+		}
+		
+		case VIDIOCSAUDIO:
+		{
+			/* Dummy: nothing can be set */
+			break;
+		}
+		
+		case VIDIOCGUNIT:
+		{
+			struct video_unit *vu = arg;
+			
+			vu->video = pdev->vdev->minor & 0x3F;
+			vu->audio = -1; /* not known yet */
+			vu->vbi = -1;
+			vu->radio = -1;
+			vu->teletext = -1;
+			break;
+		}
+		default:
+			return pwc_ioctl(pdev, cmd, arg);
+	} /* ..switch */
+	return 0;
+}	
+
+static int pwc_video_ioctl(struct inode *inode, struct file *file,
+			   unsigned int cmd, unsigned long arg)
+{
+	return video_usercopy(inode, file, cmd, arg, pwc_video_do_ioctl);
+}
+
+
+static int pwc_video_mmap(struct file *file, struct vm_area_struct *vma)
+{
+	struct video_device *vdev = file->private_data;
+	struct pwc_device *pdev;
+	unsigned long start = vma->vm_start;
+	unsigned long size  = vma->vm_end-vma->vm_start;
+	unsigned long page, pos;
+	
+	Trace(TRACE_MEMORY, "mmap(0x%p, 0x%lx, %lu) called.\n", vdev, start, size);
+	pdev = vdev->priv;
+	
+	vma->vm_flags |= VM_IO;
+
+	pos = (unsigned long)pdev->image_data;
+	while (size > 0) {
+		page = vmalloc_to_pfn((void *)pos);
+		if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED))
+			return -EAGAIN;
+
+		start += PAGE_SIZE;
+		pos += PAGE_SIZE;
+		if (size > PAGE_SIZE)
+			size -= PAGE_SIZE;
+		else
+			size = 0;
+	}
+
+	return 0;
+}
+
+/***************************************************************************/
+/* USB functions */
+
+/* This function gets called when a new device is plugged in or the usb core
+ * is loaded.
+ */
+
+static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id *id)
+{
+	struct usb_device *udev = interface_to_usbdev(intf);
+	struct pwc_device *pdev = NULL;
+	int vendor_id, product_id, type_id;
+	int i, hint;
+	int features = 0;
+	int video_nr = -1; /* default: use next available device */
+	char serial_number[30], *name;
+
+	/* Check if we can handle this device */
+	Trace(TRACE_PROBE, "probe() called [%04X %04X], if %d\n", 
+		udev->descriptor.idVendor, udev->descriptor.idProduct, 
+		intf->altsetting->desc.bInterfaceNumber);
+
+	/* the interfaces are probed one by one. We are only interested in the
+	   video interface (0) now.
+	   Interface 1 is the Audio Control, and interface 2 Audio itself.
+	 */
+	if (intf->altsetting->desc.bInterfaceNumber > 0)
+		return -ENODEV;
+
+	vendor_id = udev->descriptor.idVendor;
+	product_id = udev->descriptor.idProduct;
+
+	if (vendor_id == 0x0471) {
+		switch (product_id) {
+		case 0x0302:
+			Info("Philips PCA645VC USB webcam detected.\n");
+			name = "Philips 645 webcam";
+			type_id = 645;
+			break;
+		case 0x0303:
+			Info("Philips PCA646VC USB webcam detected.\n");
+			name = "Philips 646 webcam";
+			type_id = 646;
+			break;
+		case 0x0304:
+			Info("Askey VC010 type 2 USB webcam detected.\n");
+			name = "Askey VC010 webcam";
+			type_id = 646;
+			break;
+		case 0x0307:
+			Info("Philips PCVC675K (Vesta) USB webcam detected.\n");
+			name = "Philips 675 webcam";
+			type_id = 675;
+			break;
+		case 0x0308:
+			Info("Philips PCVC680K (Vesta Pro) USB webcam detected.\n");
+			name = "Philips 680 webcam";
+			type_id = 680;
+			break;
+		case 0x030C:
+			Info("Philips PCVC690K (Vesta Pro Scan) USB webcam detected.\n");
+			name = "Philips 690 webcam";
+			type_id = 690;
+			break;
+		case 0x0310:
+			Info("Philips PCVC730K (ToUCam Fun)/PCVC830 (ToUCam II) USB webcam detected.\n");
+			name = "Philips 730 webcam";
+			type_id = 730;
+			break;
+		case 0x0311:
+			Info("Philips PCVC740K (ToUCam Pro)/PCVC840 (ToUCam II) USB webcam detected.\n");
+			name = "Philips 740 webcam";
+			type_id = 740;
+			break;
+		case 0x0312:
+			Info("Philips PCVC750K (ToUCam Pro Scan) USB webcam detected.\n");
+			name = "Philips 750 webcam";
+			type_id = 750;
+			break;
+		case 0x0313:
+			Info("Philips PCVC720K/40 (ToUCam XS) USB webcam detected.\n");
+			name = "Philips 720K/40 webcam";
+			type_id = 720;
+			break;
+		default:
+			return -ENODEV;
+			break;
+		}
+	}
+	else if (vendor_id == 0x069A) {
+		switch(product_id) {
+		case 0x0001:
+			Info("Askey VC010 type 1 USB webcam detected.\n");
+			name = "Askey VC010 webcam";
+			type_id = 645;
+			break;
+		default:
+			return -ENODEV;
+			break;
+		}
+	}
+	else if (vendor_id == 0x046d) {
+		switch(product_id) {
+		case 0x08b0:
+			Info("Logitech QuickCam Pro 3000 USB webcam detected.\n");
+			name = "Logitech QuickCam Pro 3000";
+			type_id = 740; /* CCD sensor */
+			break;
+		case 0x08b1:
+			Info("Logitech QuickCam Notebook Pro USB webcam detected.\n");
+			name = "Logitech QuickCam Notebook Pro";
+			type_id = 740; /* CCD sensor */
+			break;
+		case 0x08b2:
+			Info("Logitech QuickCam 4000 Pro USB webcam detected.\n");
+			name = "Logitech QuickCam Pro 4000";
+			type_id = 740; /* CCD sensor */
+			break;
+		case 0x08b3:
+			Info("Logitech QuickCam Zoom USB webcam detected.\n");
+			name = "Logitech QuickCam Zoom";
+			type_id = 740; /* CCD sensor */
+			break;
+		case 0x08B4:
+			Info("Logitech QuickCam Zoom (new model) USB webcam detected.\n");
+			name = "Logitech QuickCam Zoom";
+			type_id = 740; /* CCD sensor */
+			break;
+		case 0x08b5:
+			Info("Logitech QuickCam Orbit/Sphere USB webcam detected.\n");
+			name = "Logitech QuickCam Orbit";
+			type_id = 740; /* CCD sensor */
+			features |= FEATURE_MOTOR_PANTILT;
+			break;
+		case 0x08b6:
+		case 0x08b7:
+		case 0x08b8:
+			Info("Logitech QuickCam detected (reserved ID).\n");
+			name = "Logitech QuickCam (res.)";
+			type_id = 730; /* Assuming CMOS */
+			break;
+        	default:
+			return -ENODEV;
+        		break;
+        	}
+        }
+	else if (vendor_id == 0x055d) {
+		/* I don't know the difference between the C10 and the C30;
+		   I suppose the difference is the sensor, but both cameras
+		   work equally well with a type_id of 675
+		 */
+		switch(product_id) {
+		case 0x9000:
+			Info("Samsung MPC-C10 USB webcam detected.\n");
+			name = "Samsung MPC-C10";
+			type_id = 675;
+			break;
+		case 0x9001:
+			Info("Samsung MPC-C30 USB webcam detected.\n");
+			name = "Samsung MPC-C30";
+			type_id = 675;
+			break;
+		default:
+			return -ENODEV;
+			break;
+		}
+	}
+	else if (vendor_id == 0x041e) {
+		switch(product_id) {
+		case 0x400c:
+			Info("Creative Labs Webcam 5 detected.\n");
+			name = "Creative Labs Webcam 5";
+			type_id = 730;
+			break;
+		case 0x4011:
+			Info("Creative Labs Webcam Pro Ex detected.\n");
+			name = "Creative Labs Webcam Pro Ex";
+			type_id = 740;
+			break;
+		default:
+			return -ENODEV;
+			break;
+		}
+	}
+	else if (vendor_id == 0x04cc) {
+		switch(product_id) {
+		case 0x8116:
+			Info("Sotec Afina Eye USB webcam detected.\n");
+			name = "Sotec Afina Eye";
+			type_id = 730;
+			break;
+		default:
+			return -ENODEV;
+			break;
+		}
+	}
+	else if (vendor_id == 0x06be) {
+		switch(product_id) {
+		case 0x8116:
+			/* This is essentially the same cam as the Sotec Afina Eye */
+			Info("AME Co. Afina Eye USB webcam detected.\n");
+			name = "AME Co. Afina Eye";
+			type_id = 750;
+			break;
+		default:
+			return -ENODEV;
+			break;
+		}
+	
+	}
+	else if (vendor_id == 0x0d81) {
+		switch(product_id) {
+		case 0x1900:
+			Info("Visionite VCS-UC300 USB webcam detected.\n");
+			name = "Visionite VCS-UC300";
+			type_id = 740; /* CCD sensor */
+			break;
+		case 0x1910:
+			Info("Visionite VCS-UM100 USB webcam detected.\n");
+			name = "Visionite VCS-UM100";
+			type_id = 730; /* CMOS sensor */
+			break;
+		default:
+			return -ENODEV;
+			break;
+		}
+	}
+	else 
+		return -ENODEV; /* Not any of the know types; but the list keeps growing. */
+
+	memset(serial_number, 0, 30);
+	usb_string(udev, udev->descriptor.iSerialNumber, serial_number, 29);
+	Trace(TRACE_PROBE, "Device serial number is %s\n", serial_number);
+
+	if (udev->descriptor.bNumConfigurations > 1)
+		Info("Warning: more than 1 configuration available.\n");
+
+	/* Allocate structure, initialize pointers, mutexes, etc. and link it to the usb_device */
+	pdev = kmalloc(sizeof(struct pwc_device), GFP_KERNEL);
+	if (pdev == NULL) {
+		Err("Oops, could not allocate memory for pwc_device.\n");
+		return -ENOMEM;
+	}
+	memset(pdev, 0, sizeof(struct pwc_device));
+	pdev->type = type_id;
+	pdev->vsize = default_size;
+	pdev->vframes = default_fps;
+	strcpy(pdev->serial, serial_number);
+	pdev->features = features;
+	if (vendor_id == 0x046D && product_id == 0x08B5)
+	{
+		/* Logitech QuickCam Orbit
+	           The ranges have been determined experimentally; they may differ from cam to cam.
+	           Also, the exact ranges left-right and up-down are different for my cam
+	          */
+		pdev->angle_range.pan_min  = -7000;
+		pdev->angle_range.pan_max  =  7000;
+		pdev->angle_range.tilt_min = -3000;
+		pdev->angle_range.tilt_max =  2500;
+	}
+
+	init_MUTEX(&pdev->modlock);
+	pdev->ptrlock = SPIN_LOCK_UNLOCKED;
+
+	pdev->udev = udev;
+	init_waitqueue_head(&pdev->frameq);
+	pdev->vcompression = pwc_preferred_compression;
+
+	/* Allocate video_device structure */
+	pdev->vdev = video_device_alloc();
+	if (pdev->vdev == 0)
+	{
+		Err("Err, cannot allocate video_device struture. Failing probe.");
+		kfree(pdev);
+		return -ENOMEM;
+	}
+	memcpy(pdev->vdev, &pwc_template, sizeof(pwc_template));
+	strcpy(pdev->vdev->name, name);
+	pdev->vdev->owner = THIS_MODULE;
+	video_set_drvdata(pdev->vdev, pdev);
+
+	pdev->release = udev->descriptor.bcdDevice;
+	Trace(TRACE_PROBE, "Release: %04x\n", pdev->release);
+
+	/* Now search device_hint[] table for a match, so we can hint a node number. */
+	for (hint = 0; hint < MAX_DEV_HINTS; hint++) {
+		if (((device_hint[hint].type == -1) || (device_hint[hint].type == pdev->type)) &&
+		     (device_hint[hint].pdev == NULL)) {
+			/* so far, so good... try serial number */
+			if ((device_hint[hint].serial_number[0] == '*') || !strcmp(device_hint[hint].serial_number, serial_number)) {
+			    	/* match! */
+			    	video_nr = device_hint[hint].device_node;
+			    	Trace(TRACE_PROBE, "Found hint, will try to register as /dev/video%d\n", video_nr);
+			    	break;
+			}
+		}
+	}
+
+	pdev->vdev->release = video_device_release;
+	i = video_register_device(pdev->vdev, VFL_TYPE_GRABBER, video_nr);
+	if (i < 0) {
+		Err("Failed to register as video device (%d).\n", i);
+		video_device_release(pdev->vdev); /* Drip... drip... drip... */
+		kfree(pdev); /* Oops, no memory leaks please */
+		return -EIO;
+	}
+	else {
+		Info("Registered as /dev/video%d.\n", pdev->vdev->minor & 0x3F);
+	}
+
+	/* occupy slot */
+	if (hint < MAX_DEV_HINTS) 
+		device_hint[hint].pdev = pdev;
+
+	Trace(TRACE_PROBE, "probe() function returning struct at 0x%p.\n", pdev);
+	usb_set_intfdata (intf, pdev);
+	return 0;
+}
+
+/* The user janked out the cable... */
+static void usb_pwc_disconnect(struct usb_interface *intf)
+{
+	struct pwc_device *pdev;
+	int hint;
+
+	lock_kernel();
+	pdev = usb_get_intfdata (intf);
+	usb_set_intfdata (intf, NULL);
+	if (pdev == NULL) {
+		Err("pwc_disconnect() Called without private pointer.\n");
+		goto disconnect_out;
+	}
+	if (pdev->udev == NULL) {
+		Err("pwc_disconnect() already called for %p\n", pdev);
+		goto disconnect_out;
+	}
+	if (pdev->udev != interface_to_usbdev(intf)) {
+		Err("pwc_disconnect() Woops: pointer mismatch udev/pdev.\n");
+		goto disconnect_out;
+	}
+#ifdef PWC_MAGIC	
+	if (pdev->magic != PWC_MAGIC) {
+		Err("pwc_disconnect() Magic number failed. Consult your scrolls and try again.\n");
+		goto disconnect_out;
+	}
+#endif
+	
+	/* We got unplugged; this is signalled by an EPIPE error code */
+	if (pdev->vopen) {
+		Info("Disconnected while webcam is in use!\n");
+		pdev->error_status = EPIPE;
+	}
+
+	/* Alert waiting processes */
+	wake_up_interruptible(&pdev->frameq);
+	/* Wait until device is closed */
+	while (pdev->vopen)
+		schedule();
+	/* Device is now closed, so we can safely unregister it */
+	Trace(TRACE_PROBE, "Unregistering video device in disconnect().\n");
+	video_unregister_device(pdev->vdev);
+
+	/* Free memory (don't set pdev to 0 just yet) */
+	kfree(pdev);
+
+disconnect_out:
+	/* search device_hint[] table if we occupy a slot, by any chance */
+	for (hint = 0; hint < MAX_DEV_HINTS; hint++)
+		if (device_hint[hint].pdev == pdev)
+			device_hint[hint].pdev = NULL;
+
+	unlock_kernel();
+}
+
+
+/* *grunt* We have to do atoi ourselves :-( */
+static int pwc_atoi(const char *s)
+{
+	int k = 0;
+
+	k = 0;
+	while (*s != '\0' && *s >= '0' && *s <= '9') {
+		k = 10 * k + (*s - '0');
+		s++;
+	}
+	return k;
+}
+
+
+/* 
+ * Initialization code & module stuff 
+ */
+
+static char *size = NULL;
+static int fps = 0;
+static int fbufs = 0;
+static int mbufs = 0;
+static int trace = -1;
+static int compression = -1;
+static int leds[2] = { -1, -1 };
+static char *dev_hint[MAX_DEV_HINTS] = { };
+
+MODULE_PARM(size, "s");
+MODULE_PARM_DESC(size, "Initial image size. One of sqcif, qsif, qcif, sif, cif, vga");
+MODULE_PARM(fps, "i");
+MODULE_PARM_DESC(fps, "Initial frames per second. Varies with model, useful range 5-30");
+MODULE_PARM(fbufs, "i");
+MODULE_PARM_DESC(fbufs, "Number of internal frame buffers to reserve");
+MODULE_PARM(mbufs, "i");
+MODULE_PARM_DESC(mbufs, "Number of external (mmap()ed) image buffers");
+MODULE_PARM(trace, "i");
+MODULE_PARM_DESC(trace, "For debugging purposes");
+MODULE_PARM(power_save, "i");
+MODULE_PARM_DESC(power_save, "Turn power save feature in camera on or off");
+MODULE_PARM(compression, "i");
+MODULE_PARM_DESC(compression, "Preferred compression quality. Range 0 (uncompressed) to 3 (high compression)");
+MODULE_PARM(leds, "2i");
+MODULE_PARM_DESC(leds, "LED on,off time in milliseconds");
+MODULE_PARM(dev_hint, "0-20s");
+MODULE_PARM_DESC(dev_hint, "Device node hints");
+
+MODULE_DESCRIPTION("Philips & OEM USB webcam driver");
+MODULE_AUTHOR("Luc Saillard <luc@saillard.org>");
+MODULE_LICENSE("GPL");
+
+static int __init usb_pwc_init(void)
+{
+	int i, sz;
+	char *sizenames[PSZ_MAX] = { "sqcif", "qsif", "qcif", "sif", "cif", "vga" };
+
+	Info("Philips webcam module version " PWC_VERSION " loaded.\n");
+	Info("Supports Philips PCA645/646, PCVC675/680/690, PCVC720[40]/730/740/750 & PCVC830/840.\n");
+	Info("Also supports the Askey VC010, various Logitech Quickcams, Samsung MPC-C10 and MPC-C30,\n");
+	Info("the Creative WebCam 5 & Pro Ex, SOTEC Afina Eye and Visionite VCS-UC300 and VCS-UM100.\n");
+
+	if (fps) {
+		if (fps < 4 || fps > 30) {
+			Err("Framerate out of bounds (4-30).\n");
+			return -EINVAL;
+		}
+		default_fps = fps;
+		Info("Default framerate set to %d.\n", default_fps);
+	}
+
+	if (size) {
+		/* string; try matching with array */
+		for (sz = 0; sz < PSZ_MAX; sz++) {
+			if (!strcmp(sizenames[sz], size)) { /* Found! */
+				default_size = sz;
+				break;
+			}
+		}
+		if (sz == PSZ_MAX) {
+			Err("Size not recognized; try size=[sqcif | qsif | qcif | sif | cif | vga].\n");
+			return -EINVAL;
+		}
+		Info("Default image size set to %s [%dx%d].\n", sizenames[default_size], pwc_image_sizes[default_size].x, pwc_image_sizes[default_size].y);
+	}
+	if (mbufs) {
+		if (mbufs < 1 || mbufs > MAX_IMAGES) {
+			Err("Illegal number of mmap() buffers; use a number between 1 and %d.\n", MAX_IMAGES);
+			return -EINVAL;
+		}
+		default_mbufs = mbufs;
+		Info("Number of image buffers set to %d.\n", default_mbufs);
+	}
+	if (fbufs) {
+		if (fbufs < 2 || fbufs > MAX_FRAMES) {
+			Err("Illegal number of frame buffers; use a number between 2 and %d.\n", MAX_FRAMES);
+			return -EINVAL;
+		}
+		default_fbufs = fbufs;
+		Info("Number of frame buffers set to %d.\n", default_fbufs);
+	}
+	if (trace >= 0) {
+		Info("Trace options: 0x%04x\n", trace);
+		pwc_trace = trace;
+	}
+	if (compression >= 0) {
+		if (compression > 3) {
+			Err("Invalid compression setting; use a number between 0 (uncompressed) and 3 (high).\n");
+			return -EINVAL;
+		}
+		pwc_preferred_compression = compression;
+		Info("Preferred compression set to %d.\n", pwc_preferred_compression);
+	}
+	if (power_save)
+		Info("Enabling power save on open/close.\n");
+	if (leds[0] >= 0)
+		led_on = leds[0];
+	if (leds[1] >= 0)
+		led_off = leds[1];
+
+	/* Big device node whoopla. Basicly, it allows you to assign a
+	   device node (/dev/videoX) to a camera, based on its type
+	   & serial number. The format is [type[.serialnumber]:]node.
+
+	   Any camera that isn't matched by these rules gets the next
+	   available free device node.
+	 */
+	for (i = 0; i < MAX_DEV_HINTS; i++) {
+		char *s, *colon, *dot;
+
+		/* This loop also initializes the array */
+		device_hint[i].pdev = NULL;
+		s = dev_hint[i];
+		if (s != NULL && *s != '\0') {
+			device_hint[i].type = -1; /* wildcard */
+			strcpy(device_hint[i].serial_number, "*");
+
+			/* parse string: chop at ':' & '/' */
+			colon = dot = s;
+			while (*colon != '\0' && *colon != ':')
+				colon++;
+			while (*dot != '\0' && *dot != '.')
+				dot++;
+			/* Few sanity checks */
+			if (*dot != '\0' && dot > colon) {
+				Err("Malformed camera hint: the colon must be after the dot.\n");
+				return -EINVAL;
+			}
+
+			if (*colon == '\0') {
+				/* No colon */
+				if (*dot != '\0') {
+					Err("Malformed camera hint: no colon + device node given.\n");
+					return -EINVAL;
+				}
+				else {
+					/* No type or serial number specified, just a number. */
+					device_hint[i].device_node = pwc_atoi(s);
+				}
+			}
+			else {
+				/* There's a colon, so we have at least a type and a device node */
+				device_hint[i].type = pwc_atoi(s);
+				device_hint[i].device_node = pwc_atoi(colon + 1);
+				if (*dot != '\0') {
+					/* There's a serial number as well */
+					int k;
+					
+					dot++;
+					k = 0;
+					while (*dot != ':' && k < 29) {
+						device_hint[i].serial_number[k++] = *dot;
+						dot++;
+					}
+					device_hint[i].serial_number[k] = '\0';
+				}
+			}
+#if PWC_DEBUG		
+			Debug("device_hint[%d]:\n", i);
+			Debug("  type    : %d\n", device_hint[i].type);
+			Debug("  serial# : %s\n", device_hint[i].serial_number);
+			Debug("  node    : %d\n", device_hint[i].device_node);
+#endif			
+		}
+		else
+			device_hint[i].type = 0; /* not filled */
+	} /* ..for MAX_DEV_HINTS */
+
+ 	Trace(TRACE_PROBE, "Registering driver at address 0x%p.\n", &pwc_driver);
+	return usb_register(&pwc_driver);
+}
+
+static void __exit usb_pwc_exit(void)
+{
+	Trace(TRACE_MODULE, "Deregistering driver.\n");
+	usb_deregister(&pwc_driver);
+	Info("Philips webcam module removed.\n");
+}
+
+module_init(usb_pwc_init);
+module_exit(usb_pwc_exit);
+
diff -Nru a/drivers/usb/media/pwc/pwc-ioctl.h b/drivers/usb/media/pwc/pwc-ioctl.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/usb/media/pwc/pwc-ioctl.h	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,292 @@
+#ifndef PWC_IOCTL_H
+#define PWC_IOCTL_H
+
+/* (C) 2001-2004 Nemosoft Unv.
+   (C) 2004      Luc Saillard (luc@saillard.org)
+
+   NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
+   driver and thus may have bugs that are not present in the original version.
+   Please send bug reports and support requests to <luc@saillard.org>.
+   The decompression routines have been implemented by reverse-engineering the
+   Nemosoft binary pwcx module. Caveat emptor.
+
+   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 is pwc-ioctl.h belonging to PWC 8.12.1
+   It contains structures and defines to communicate from user space
+   directly to the driver.
+ */
+
+/*
+   Changes
+   2001/08/03  Alvarado   Added ioctl constants to access methods for
+                          changing white balance and red/blue gains
+   2002/12/15  G. H. Fernandez-Toribio   VIDIOCGREALSIZE
+   2003/12/13  Nemosft Unv. Some modifications to make interfacing to
+               PWCX easier
+ */
+
+/* These are private ioctl() commands, specific for the Philips webcams.
+   They contain functions not found in other webcams, and settings not
+   specified in the Video4Linux API.
+
+   The #define names are built up like follows:
+   VIDIOC		VIDeo IOCtl prefix
+         PWC		Philps WebCam
+            G           optional: Get
+            S           optional: Set
+             ... 	the function
+ */
+
+
+ /* Enumeration of image sizes */
+#define PSZ_SQCIF	0x00
+#define PSZ_QSIF	0x01
+#define PSZ_QCIF	0x02
+#define PSZ_SIF		0x03
+#define PSZ_CIF		0x04
+#define PSZ_VGA		0x05
+#define PSZ_MAX		6
+
+
+/* The frame rate is encoded in the video_window.flags parameter using
+   the upper 16 bits, since some flags are defined nowadays. The following
+   defines provide a mask and shift to filter out this value.
+
+   In 'Snapshot' mode the camera freezes its automatic exposure and colour
+   balance controls.
+ */
+#define PWC_FPS_SHIFT		16
+#define PWC_FPS_MASK		0x00FF0000
+#define PWC_FPS_FRMASK		0x003F0000
+#define PWC_FPS_SNAPSHOT	0x00400000
+
+
+/* structure for transfering x & y coordinates */
+struct pwc_coord
+{
+	int x, y;		/* guess what */
+	int size;		/* size, or offset */
+};
+
+
+/* Used with VIDIOCPWCPROBE */
+struct pwc_probe
+{
+	char name[32];
+	int type;
+};
+
+struct pwc_serial
+{
+	char serial[30];	/* String with serial number. Contains terminating 0 */
+};
+	
+/* pwc_whitebalance.mode values */
+#define PWC_WB_INDOOR		0
+#define PWC_WB_OUTDOOR		1
+#define PWC_WB_FL		2
+#define PWC_WB_MANUAL		3
+#define PWC_WB_AUTO		4
+
+/* Used with VIDIOCPWC[SG]AWB (Auto White Balance). 
+   Set mode to one of the PWC_WB_* values above.
+   *red and *blue are the respective gains of these colour components inside 
+   the camera; range 0..65535
+   When 'mode' == PWC_WB_MANUAL, 'manual_red' and 'manual_blue' are set or read; 
+   otherwise undefined.
+   'read_red' and 'read_blue' are read-only.
+*/   
+struct pwc_whitebalance
+{
+	int mode;
+	int manual_red, manual_blue;	/* R/W */
+	int read_red, read_blue;	/* R/O */
+};
+
+/* 
+   'control_speed' and 'control_delay' are used in automatic whitebalance mode,
+   and tell the camera how fast it should react to changes in lighting, and 
+   with how much delay. Valid values are 0..65535.
+*/
+struct pwc_wb_speed
+{
+	int control_speed;
+	int control_delay;
+
+};
+
+/* Used with VIDIOCPWC[SG]LED */
+struct pwc_leds
+{
+	int led_on;			/* Led on-time; range = 0..25000 */
+	int led_off;			/* Led off-time; range = 0..25000  */
+};
+
+/* Image size (used with GREALSIZE) */
+struct pwc_imagesize
+{
+	int width;
+	int height;
+};
+
+/* Defines and structures for Motorized Pan & Tilt */
+#define PWC_MPT_PAN		0x01
+#define PWC_MPT_TILT		0x02
+#define PWC_MPT_TIMEOUT		0x04 /* for status */
+
+/* Set angles; when absolute != 0, the angle is absolute and the 
+   driver calculates the relative offset for you. This can only
+   be used with VIDIOCPWCSANGLE; VIDIOCPWCGANGLE always returns
+   absolute angles.
+ */   
+struct pwc_mpt_angles
+{
+	int absolute;		/* write-only */
+	int pan;		/* degrees * 100 */
+	int tilt;		/* degress * 100 */
+};
+
+/* Range of angles of the camera, both horizontally and vertically.
+ */
+struct pwc_mpt_range
+{
+	int pan_min, pan_max;		/* degrees * 100 */
+	int tilt_min, tilt_max;
+};
+
+struct pwc_mpt_status
+{
+	int status;
+	int time_pan;
+	int time_tilt;
+};
+
+
+/* This is used for out-of-kernel decompression. With it, you can get
+   all the necessary information to initialize and use the decompressor
+   routines in standalone applications.
+ */   
+struct pwc_video_command
+{
+	int type;		/* camera type (645, 675, 730, etc.) */
+	int release;		/* release number */
+
+        int size;		/* one of PSZ_* */
+        int alternate;
+	int command_len;	/* length of USB video command */
+	unsigned char command_buf[13];	/* Actual USB video command */
+	int bandlength;		/* >0 = compressed */
+	int frame_size;		/* Size of one (un)compressed frame */
+};
+
+/* Flags for PWCX subroutines. Not all modules honour all flags. */
+#define PWCX_FLAG_PLANAR	0x0001
+#define PWCX_FLAG_BAYER		0x0008
+
+
+/* IOCTL definitions */
+
+ /* Restore user settings */
+#define VIDIOCPWCRUSER		_IO('v', 192)
+ /* Save user settings */
+#define VIDIOCPWCSUSER		_IO('v', 193)
+ /* Restore factory settings */
+#define VIDIOCPWCFACTORY	_IO('v', 194)
+
+ /* You can manipulate the compression factor. A compression preference of 0
+    means use uncompressed modes when available; 1 is low compression, 2 is
+    medium and 3 is high compression preferred. Of course, the higher the
+    compression, the lower the bandwidth used but more chance of artefacts
+    in the image. The driver automatically chooses a higher compression when
+    the preferred mode is not available.
+  */
+ /* Set preferred compression quality (0 = uncompressed, 3 = highest compression) */
+#define VIDIOCPWCSCQUAL		_IOW('v', 195, int)
+ /* Get preferred compression quality */
+#define VIDIOCPWCGCQUAL		_IOR('v', 195, int)
+
+
+/* Retrieve serial number of camera */
+#define VIDIOCPWCGSERIAL	_IOR('v', 198, struct pwc_serial)
+
+ /* This is a probe function; since so many devices are supported, it
+    becomes difficult to include all the names in programs that want to
+    check for the enhanced Philips stuff. So in stead, try this PROBE;
+    it returns a structure with the original name, and the corresponding
+    Philips type.
+    To use, fill the structure with zeroes, call PROBE and if that succeeds,
+    compare the name with that returned from VIDIOCGCAP; they should be the
+    same. If so, you can be assured it is a Philips (OEM) cam and the type
+    is valid.
+ */
+#define VIDIOCPWCPROBE		_IOR('v', 199, struct pwc_probe)
+
+ /* Set AGC (Automatic Gain Control); int < 0 = auto, 0..65535 = fixed */
+#define VIDIOCPWCSAGC		_IOW('v', 200, int)
+ /* Get AGC; int < 0 = auto; >= 0 = fixed, range 0..65535 */
+#define VIDIOCPWCGAGC		_IOR('v', 200, int)
+ /* Set shutter speed; int < 0 = auto; >= 0 = fixed, range 0..65535 */
+#define VIDIOCPWCSSHUTTER	_IOW('v', 201, int)
+
+ /* Color compensation (Auto White Balance) */
+#define VIDIOCPWCSAWB           _IOW('v', 202, struct pwc_whitebalance)
+#define VIDIOCPWCGAWB           _IOR('v', 202, struct pwc_whitebalance)
+
+ /* Auto WB speed */
+#define VIDIOCPWCSAWBSPEED	_IOW('v', 203, struct pwc_wb_speed)
+#define VIDIOCPWCGAWBSPEED	_IOR('v', 203, struct pwc_wb_speed)
+
+ /* LEDs on/off/blink; int range 0..65535 */
+#define VIDIOCPWCSLED           _IOW('v', 205, struct pwc_leds)
+#define VIDIOCPWCGLED           _IOR('v', 205, struct pwc_leds)
+
+  /* Contour (sharpness); int < 0 = auto, 0..65536 = fixed */
+#define VIDIOCPWCSCONTOUR	_IOW('v', 206, int)
+#define VIDIOCPWCGCONTOUR	_IOR('v', 206, int)
+
+  /* Backlight compensation; 0 = off, otherwise on */
+#define VIDIOCPWCSBACKLIGHT	_IOW('v', 207, int)
+#define VIDIOCPWCGBACKLIGHT	_IOR('v', 207, int)
+
+  /* Flickerless mode; = 0 off, otherwise on */
+#define VIDIOCPWCSFLICKER	_IOW('v', 208, int)
+#define VIDIOCPWCGFLICKER	_IOR('v', 208, int)  
+
+  /* Dynamic noise reduction; 0 off, 3 = high noise reduction */
+#define VIDIOCPWCSDYNNOISE	_IOW('v', 209, int)
+#define VIDIOCPWCGDYNNOISE	_IOR('v', 209, int)
+
+ /* Real image size as used by the camera; tells you whether or not there's a gray border around the image */
+#define VIDIOCPWCGREALSIZE	_IOR('v', 210, struct pwc_imagesize)
+
+ /* Motorized pan & tilt functions */ 
+#define VIDIOCPWCMPTRESET	_IOW('v', 211, int)
+#define VIDIOCPWCMPTGRANGE	_IOR('v', 211, struct pwc_mpt_range)
+#define VIDIOCPWCMPTSANGLE	_IOW('v', 212, struct pwc_mpt_angles)
+#define VIDIOCPWCMPTGANGLE	_IOR('v', 212, struct pwc_mpt_angles)
+#define VIDIOCPWCMPTSTATUS	_IOR('v', 213, struct pwc_mpt_status)
+
+ /* Get the USB set-video command; needed for initializing libpwcx */
+#define VIDIOCPWCGVIDCMD	_IOR('v', 215, struct pwc_video_command)
+struct pwc_table_init_buffer {
+   int len;
+   char *buffer;
+
+};
+#define VIDIOCPWCGVIDTABLE	_IOR('v', 216, struct pwc_table_init_buffer)
+
+#endif
diff -Nru a/drivers/usb/media/pwc/pwc-kiara.c b/drivers/usb/media/pwc/pwc-kiara.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/usb/media/pwc/pwc-kiara.c	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,891 @@
+/* Linux driver for Philips webcam
+   (C) 2004      Luc Saillard (luc@saillard.org)
+
+   NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
+   driver and thus may have bugs that are not present in the original version.
+   Please send bug reports and support requests to <luc@saillard.org>.
+   The decompression routines have been implemented by reverse-engineering the
+   Nemosoft binary pwcx module. Caveat emptor.
+
+   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 tables contains entries for the 730/740/750 (Kiara) camera, with
+   4 different qualities (no compression, low, medium, high).
+   It lists the bandwidth requirements for said mode by its alternate interface
+   number. An alternate of 0 means that the mode is unavailable.
+
+   There are 6 * 4 * 4 entries:
+     6 different resolutions subqcif, qsif, qcif, sif, cif, vga
+     6 framerates: 5, 10, 15, 20, 25, 30
+     4 compression modi: none, low, medium, high
+
+   When an uncompressed mode is not available, the next available compressed mode
+   will be chosen (unless the decompressor is absent). Sometimes there are only
+   1 or 2 compressed modes available; in that case entries are duplicated.
+*/
+
+
+#include "pwc-kiara.h"
+#include "pwc-uncompress.h"
+
+const struct Kiara_table_entry Kiara_table[PSZ_MAX][6][4] =
+{
+   /* SQCIF */
+   {
+      /* 5 fps */
+      {
+         {0, },
+         {0, },
+         {0, },
+         {0, },
+      },
+      /* 10 fps */
+      {
+         {0, },
+         {0, },
+         {0, },
+         {0, },
+      },
+      /* 15 fps */
+      {
+         {0, },
+         {0, },
+         {0, },
+         {0, },
+      },
+      /* 20 fps */
+      {
+         {0, },
+         {0, },
+         {0, },
+         {0, },
+      },
+      /* 25 fps */
+      {
+         {0, },
+         {0, },
+         {0, },
+         {0, },
+      },
+      /* 30 fps */
+      {
+         {0, },
+         {0, },
+         {0, },
+         {0, },
+      },
+   },
+   /* QSIF */
+   {
+      /* 5 fps */
+      {
+         {1, 146,    0, {0x1D, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0x00, 0x80}},
+         {1, 146,    0, {0x1D, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0x00, 0x80}},
+         {1, 146,    0, {0x1D, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0x00, 0x80}},
+         {1, 146,    0, {0x1D, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0x00, 0x80}},
+      },
+      /* 10 fps */
+      {
+         {2, 291,    0, {0x1C, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x23, 0x01, 0x80}},
+         {1, 192,  630, {0x14, 0xF4, 0x30, 0x13, 0xA9, 0x12, 0xE1, 0x17, 0x08, 0xC0, 0x00, 0x80}},
+         {1, 192,  630, {0x14, 0xF4, 0x30, 0x13, 0xA9, 0x12, 0xE1, 0x17, 0x08, 0xC0, 0x00, 0x80}},
+         {1, 192,  630, {0x14, 0xF4, 0x30, 0x13, 0xA9, 0x12, 0xE1, 0x17, 0x08, 0xC0, 0x00, 0x80}},
+      },
+      /* 15 fps */
+      {
+         {3, 437,    0, {0x1B, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0xB5, 0x01, 0x80}},
+         {2, 292,  640, {0x13, 0xF4, 0x30, 0x13, 0xF7, 0x13, 0x2F, 0x13, 0x20, 0x24, 0x01, 0x80}},
+         {2, 292,  640, {0x13, 0xF4, 0x30, 0x13, 0xF7, 0x13, 0x2F, 0x13, 0x20, 0x24, 0x01, 0x80}},
+         {1, 192,  420, {0x13, 0xF4, 0x30, 0x0D, 0x1B, 0x0C, 0x53, 0x1E, 0x18, 0xC0, 0x00, 0x80}},
+      },
+      /* 20 fps */
+      {
+         {4, 589,    0, {0x1A, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x4D, 0x02, 0x80}},
+         {3, 448,  730, {0x12, 0xF4, 0x30, 0x16, 0xC9, 0x16, 0x01, 0x0E, 0x18, 0xC0, 0x01, 0x80}},
+         {2, 292,  476, {0x12, 0xF4, 0x30, 0x0E, 0xD8, 0x0E, 0x10, 0x19, 0x18, 0x24, 0x01, 0x80}},
+         {1, 192,  312, {0x12, 0xF4, 0x50, 0x09, 0xB3, 0x08, 0xEB, 0x1E, 0x18, 0xC0, 0x00, 0x80}},
+      },
+      /* 25 fps */
+      {
+         {5, 703,    0, {0x19, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0xBF, 0x02, 0x80}},
+         {3, 447,  610, {0x11, 0xF4, 0x30, 0x13, 0x0B, 0x12, 0x43, 0x14, 0x28, 0xBF, 0x01, 0x80}},
+         {2, 292,  398, {0x11, 0xF4, 0x50, 0x0C, 0x6C, 0x0B, 0xA4, 0x1E, 0x28, 0x24, 0x01, 0x80}},
+         {1, 193,  262, {0x11, 0xF4, 0x50, 0x08, 0x23, 0x07, 0x5B, 0x1E, 0x28, 0xC1, 0x00, 0x80}},
+      },
+      /* 30 fps */
+      {
+         {8, 874,    0, {0x18, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x6A, 0x03, 0x80}},
+         {5, 704,  730, {0x10, 0xF4, 0x30, 0x16, 0xC9, 0x16, 0x01, 0x0E, 0x28, 0xC0, 0x02, 0x80}},
+         {3, 448,  492, {0x10, 0xF4, 0x30, 0x0F, 0x5D, 0x0E, 0x95, 0x15, 0x28, 0xC0, 0x01, 0x80}},
+         {2, 292,  320, {0x10, 0xF4, 0x50, 0x09, 0xFB, 0x09, 0x33, 0x1E, 0x28, 0x24, 0x01, 0x80}},
+      },
+   },
+   /* QCIF */
+   {
+      /* 5 fps */
+      {
+         {0, },
+         {0, },
+         {0, },
+         {0, },
+      },
+      /* 10 fps */
+      {
+         {0, },
+         {0, },
+         {0, },
+         {0, },
+      },
+      /* 15 fps */
+      {
+         {0, },
+         {0, },
+         {0, },
+         {0, },
+      },
+      /* 20 fps */
+      {
+         {0, },
+         {0, },
+         {0, },
+         {0, },
+      },
+      /* 25 fps */
+      {
+         {0, },
+         {0, },
+         {0, },
+         {0, },
+      },
+      /* 30 fps */
+      {
+         {0, },
+         {0, },
+         {0, },
+         {0, },
+      },
+   },
+   /* SIF */
+   {
+      /* 5 fps */
+      {
+         {4, 582,    0, {0x0D, 0xF4, 0x30, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x46, 0x02, 0x80}},
+         {3, 387, 1276, {0x05, 0xF4, 0x30, 0x27, 0xD8, 0x26, 0x48, 0x03, 0x10, 0x83, 0x01, 0x80}},
+         {2, 291,  960, {0x05, 0xF4, 0x30, 0x1D, 0xF2, 0x1C, 0x62, 0x04, 0x10, 0x23, 0x01, 0x80}},
+         {1, 191,  630, {0x05, 0xF4, 0x50, 0x13, 0xA9, 0x12, 0x19, 0x05, 0x18, 0xBF, 0x00, 0x80}},
+      },
+      /* 10 fps */
+      {
+         {0, },
+         {6, 775, 1278, {0x04, 0xF4, 0x30, 0x27, 0xE8, 0x26, 0x58, 0x05, 0x30, 0x07, 0x03, 0x80}},
+         {3, 447,  736, {0x04, 0xF4, 0x30, 0x16, 0xFB, 0x15, 0x6B, 0x05, 0x28, 0xBF, 0x01, 0x80}},
+         {2, 292,  480, {0x04, 0xF4, 0x70, 0x0E, 0xF9, 0x0D, 0x69, 0x09, 0x28, 0x24, 0x01, 0x80}},
+      },
+      /* 15 fps */
+      {
+         {0, },
+         {9, 955, 1050, {0x03, 0xF4, 0x30, 0x20, 0xCF, 0x1F, 0x3F, 0x06, 0x48, 0xBB, 0x03, 0x80}},
+         {4, 592,  650, {0x03, 0xF4, 0x30, 0x14, 0x44, 0x12, 0xB4, 0x08, 0x30, 0x50, 0x02, 0x80}},
+         {3, 448,  492, {0x03, 0xF4, 0x50, 0x0F, 0x52, 0x0D, 0xC2, 0x09, 0x38, 0xC0, 0x01, 0x80}},
+      },
+      /* 20 fps */
+      {
+         {0, },
+         {9, 958,  782, {0x02, 0xF4, 0x30, 0x18, 0x6A, 0x16, 0xDA, 0x0B, 0x58, 0xBE, 0x03, 0x80}},
+         {5, 703,  574, {0x02, 0xF4, 0x50, 0x11, 0xE7, 0x10, 0x57, 0x0B, 0x40, 0xBF, 0x02, 0x80}},
+         {3, 446,  364, {0x02, 0xF4, 0x90, 0x0B, 0x5C, 0x09, 0xCC, 0x0E, 0x38, 0xBE, 0x01, 0x80}},
+      },
+      /* 25 fps */
+      {
+         {0, },
+         {9, 958,  654, {0x01, 0xF4, 0x30, 0x14, 0x66, 0x12, 0xD6, 0x0B, 0x50, 0xBE, 0x03, 0x80}},
+         {6, 776,  530, {0x01, 0xF4, 0x50, 0x10, 0x8C, 0x0E, 0xFC, 0x0C, 0x48, 0x08, 0x03, 0x80}},
+         {4, 592,  404, {0x01, 0xF4, 0x70, 0x0C, 0x96, 0x0B, 0x06, 0x0B, 0x48, 0x50, 0x02, 0x80}},
+      },
+      /* 30 fps */
+      {
+         {0, },
+         {9, 957,  526, {0x00, 0xF4, 0x50, 0x10, 0x68, 0x0E, 0xD8, 0x0D, 0x58, 0xBD, 0x03, 0x80}},
+         {6, 775,  426, {0x00, 0xF4, 0x70, 0x0D, 0x48, 0x0B, 0xB8, 0x0F, 0x50, 0x07, 0x03, 0x80}},
+         {4, 590,  324, {0x00, 0x7A, 0x88, 0x0A, 0x1C, 0x08, 0xB4, 0x0E, 0x50, 0x4E, 0x02, 0x80}},
+      },
+   },
+   /* CIF */
+   {
+      /* 5 fps */
+      {
+         {0, },
+         {0, },
+         {0, },
+         {0, },
+      },
+      /* 10 fps */
+      {
+         {0, },
+         {0, },
+         {0, },
+         {0, },
+      },
+      /* 15 fps */
+      {
+         {0, },
+         {0, },
+         {0, },
+         {0, },
+      },
+      /* 20 fps */
+      {
+         {0, },
+         {0, },
+         {0, },
+         {0, },
+      },
+      /* 25 fps */
+      {
+         {0, },
+         {0, },
+         {0, },
+         {0, },
+      },
+      /* 30 fps */
+      {
+         {0, },
+         {0, },
+         {0, },
+         {0, },
+      },
+   },
+   /* VGA */
+   {
+      /* 5 fps */
+      {
+         {0, },
+         {6, 773, 1272, {0x25, 0xF4, 0x30, 0x27, 0xB6, 0x24, 0x96, 0x02, 0x30, 0x05, 0x03, 0x80}},
+         {4, 592,  976, {0x25, 0xF4, 0x50, 0x1E, 0x78, 0x1B, 0x58, 0x03, 0x30, 0x50, 0x02, 0x80}},
+         {3, 448,  738, {0x25, 0xF4, 0x90, 0x17, 0x0C, 0x13, 0xEC, 0x04, 0x30, 0xC0, 0x01, 0x80}},
+      },
+      /* 10 fps */
+      {
+         {0, },
+         {9, 956,  788, {0x24, 0xF4, 0x70, 0x18, 0x9C, 0x15, 0x7C, 0x03, 0x48, 0xBC, 0x03, 0x80}},
+         {6, 776,  640, {0x24, 0xF4, 0xB0, 0x13, 0xFC, 0x11, 0x2C, 0x04, 0x48, 0x08, 0x03, 0x80}},
+         {4, 592,  488, {0x24, 0x7A, 0xE8, 0x0F, 0x3C, 0x0C, 0x6C, 0x06, 0x48, 0x50, 0x02, 0x80}},
+      },
+      /* 15 fps */
+      {
+         {0, },
+         {9, 957,  526, {0x23, 0x7A, 0xE8, 0x10, 0x68, 0x0D, 0x98, 0x06, 0x58, 0xBD, 0x03, 0x80}},
+         {9, 957,  526, {0x23, 0x7A, 0xE8, 0x10, 0x68, 0x0D, 0x98, 0x06, 0x58, 0xBD, 0x03, 0x80}},
+         {8, 895,  492, {0x23, 0x7A, 0xE8, 0x0F, 0x5D, 0x0C, 0x8D, 0x06, 0x58, 0x7F, 0x03, 0x80}},
+      },
+      /* 20 fps */
+      {
+         {0, },
+         {0, },
+         {0, },
+         {0, },
+      },
+      /* 25 fps */
+      {
+         {0, },
+         {0, },
+         {0, },
+         {0, },
+      },
+      /* 30 fps */
+      {
+         {0, },
+         {0, },
+         {0, },
+         {0, },
+      },
+   },
+};
+
+
+/*
+ * Rom table for kiara chips
+ *
+ * 32 roms tables (one for each resolution ?)
+ *  2 tables per roms (one for each passes) (Y, and U&V)
+ * 128 bytes per passes
+ */
+
+const unsigned int KiaraRomTable [8][2][16][8] =  
+{
+ { /* version 0 */
+  { /* version 0, passes 0 */
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000001,0x00000001},
+   {0x00000000,0x00000000,0x00000009,0x00000009,
+    0x00000009,0x00000009,0x00000009,0x00000009},
+   {0x00000000,0x00000000,0x00000009,0x00000049,
+    0x00000049,0x00000049,0x00000049,0x00000049},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000249,0x0000024a,0x00000049},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000249,0x00000249,0x0000024a,0x0000024a},
+   {0x00000000,0x00000000,0x00000049,0x00000249,
+    0x00000249,0x0000124a,0x0000024a,0x0000024a},
+   {0x00000000,0x00000000,0x00000049,0x00000249,
+    0x0000124a,0x00009252,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x00009252,0x00009292,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x00000249,0x00001249,
+    0x00009292,0x00009292,0x00009493,0x000124db},
+   {0x00000000,0x00000000,0x00000249,0x0000924a,
+    0x00009492,0x0000a49b,0x0000a49b,0x000124db},
+   {0x00000000,0x00000000,0x00001249,0x00009252,
+    0x0000a493,0x000124db,0x000124db,0x000126dc},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x000124db,0x000126dc,0x000136e4,0x000126dc},
+   {0x00000000,0x00000000,0x00009292,0x0000a49b,
+    0x000124db,0x000136e4,0x000136e4,0x000136e4},
+   {0x00000000,0x00000000,0x00009292,0x0000a49b,
+    0x000126dc,0x0001b724,0x0001b92d,0x0001b925},
+   {0x00000000,0x00000000,0x00009492,0x000124db,
+    0x000136e4,0x0001b925,0x0001c96e,0x0001c92d},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  },
+  { /* version 0, passes 1 */
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000},
+   {0x00000000,0x00000000,0x00000001,0x00000009,
+    0x00000009,0x00000009,0x00000009,0x00000001},
+   {0x00000000,0x00000000,0x00000009,0x00000009,
+    0x00000049,0x00000049,0x00000049,0x00000049},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000049,0x0000024a,0x0000024a},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000249,0x00000249,0x0000024a,0x0000024a},
+   {0x00000000,0x00000000,0x00000049,0x00000249,
+    0x00000249,0x00000249,0x0000024a,0x00001252},
+   {0x00000000,0x00000000,0x00000049,0x00001249,
+    0x0000124a,0x0000124a,0x00001252,0x00009292},
+   {0x00000000,0x00000000,0x00000249,0x00001249,
+    0x00009252,0x00009252,0x00009292,0x00009493},
+   {0x00000000,0x00000000,0x00000249,0x0000924a,
+    0x00009292,0x00009292,0x00009292,0x00009493},
+   {0x00000000,0x00000000,0x00000249,0x00009292,
+    0x00009492,0x00009493,0x0000a49b,0x00009493},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x0000a493,0x000124db,0x000126dc,0x000126dc},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x000126dc,0x000136e4,0x000136e4},
+   {0x00000000,0x00000000,0x00009252,0x00009493,
+    0x000126dc,0x000126dc,0x000136e4,0x000136e4},
+   {0x00000000,0x00000000,0x00009292,0x0000a49b,
+    0x000136e4,0x000136e4,0x0001b725,0x0001b724},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  }
+ },
+ { /* version 1 */
+  { /* version 1, passes 0 */
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000001},
+   {0x00000000,0x00000000,0x00000009,0x00000009,
+    0x00000009,0x00000009,0x00000009,0x00000009},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000049,0x00000049,0x00000049},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000249,0x0000024a,0x0000024a},
+   {0x00000000,0x00000000,0x00000049,0x00000249,
+    0x00000249,0x00000249,0x0000024a,0x00001252},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x00000249,0x0000124a,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x0000124a,0x0000124a,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x00000249,0x00001249,
+    0x0000124a,0x00009252,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x00000249,0x00001249,
+    0x00009252,0x00009292,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x00000249,0x00001249,
+    0x00009252,0x00009292,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x00000249,0x0000924a,
+    0x00009252,0x00009493,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x00000249,0x0000924a,
+    0x00009292,0x00009493,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x00000249,0x00009252,
+    0x00009492,0x00009493,0x0000a49b,0x0000a49b},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x00009492,0x000124db,0x000124db,0x000124db},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x000126dc,0x000126dc,0x000126dc},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  },
+  { /* version 1, passes 1 */
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000},
+   {0x00000000,0x00000000,0x00000049,0x00000009,
+    0x00000049,0x00000009,0x00000001,0x00000000},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000049,0x00000049,0x00000000},
+   {0x00000000,0x00000000,0x00000249,0x00000049,
+    0x00000249,0x00000049,0x0000024a,0x00000001},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x00000249,0x00000249,0x0000024a,0x00000001},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x00000249,0x00000249,0x0000024a,0x00000001},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x00000249,0x00000249,0x0000024a,0x00000009},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x0000124a,0x0000124a,0x0000024a,0x00000009},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x0000124a,0x0000124a,0x0000024a,0x00000009},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x0000124a,0x00009252,0x00001252,0x00000049},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x0000124a,0x00009292,0x00001252,0x00000049},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x0000124a,0x00009292,0x00001252,0x00000049},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009252,0x00009292,0x00001252,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009292,0x00009292,0x00001252,0x0000024a},
+   {0x00000000,0x00000000,0x0000924a,0x0000924a,
+    0x00009492,0x00009493,0x00009292,0x00001252},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  }
+ },
+ { /* version 2 */
+  { /* version 2, passes 0 */
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000049,0x0000024a,0x0000024a},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x00000249,0x0000124a,0x00001252,0x00009292},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x0000124a,0x00009252,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x00000249,0x00001249,
+    0x0000124a,0x00009292,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x00000249,0x00001249,
+    0x00009252,0x00009493,0x00009493,0x0000a49b},
+   {0x00000000,0x00000000,0x00000249,0x0000924a,
+    0x00009292,0x00009493,0x0000a49b,0x0000a49b},
+   {0x00000000,0x00000000,0x00001249,0x0000924a,
+    0x00009292,0x00009493,0x0000a49b,0x000124db},
+   {0x00000000,0x00000000,0x00001249,0x00009252,
+    0x00009492,0x0000a49b,0x0000a49b,0x000124db},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x00009492,0x000124db,0x000124db,0x000126dc},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x0000a493,0x000124db,0x000126dc,0x000126dc},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x000124db,0x000126dc,0x000136e4},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x000126dc,0x000136e4,0x000136e4},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0001249b,0x000126dc,0x000136e4,0x000136e4},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000124db,0x000136e4,0x000136e4,0x0001b724},
+   {0x00000000,0x00000000,0x00009252,0x000124db,
+    0x000126dc,0x0001b724,0x0001b725,0x0001b925},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  },
+  { /* version 2, passes 1 */
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000049,0x00000049,0x00000049},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x00000249,0x00000249,0x0000024a,0x00000049},
+   {0x00000000,0x00000000,0x00001249,0x00000249,
+    0x0000124a,0x0000124a,0x00001252,0x00000049},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x0000124a,0x0000124a,0x00009292,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009252,0x00009292,0x00009292,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009252,0x00009292,0x0000a49b,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009292,0x00009493,0x0000a49b,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009292,0x00009493,0x0000a49b,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x0000924a,
+    0x00009492,0x0000a49b,0x0000a49b,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x00009252,
+    0x00009492,0x0000a49b,0x0000a49b,0x00009292},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x00009492,0x0000a49b,0x0000a49b,0x00009292},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x0000a49b,0x0000a49b,0x00009292},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x0000a49b,0x0000a49b,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x000124db,0x0000a49b,0x00009493},
+   {0x00000000,0x00000000,0x00009252,0x0000a49b,
+    0x0001249b,0x000126dc,0x000124db,0x0000a49b},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  }
+ },
+ { /* version 3 */
+  { /* version 3, passes 0 */
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x0000124a,0x0000124a,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009292,0x00009493,0x0000a49b,0x0000a49b},
+   {0x00000000,0x00000000,0x00001249,0x0000924a,
+    0x00009492,0x0000a49b,0x0000a49b,0x000124db},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x00009492,0x000124db,0x000126dc,0x000126dc},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x000124db,0x000126dc,0x000126dc},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x000126dc,0x000136e4,0x000136e4},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x000126dc,0x000136e4,0x0001b724},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0001249b,0x000126dc,0x000136e4,0x0001b724},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000126dc,0x000136e4,0x0001b724},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000136e4,0x0001b725,0x0001b724},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000124db,0x000136e4,0x0001b725,0x0001b925},
+   {0x00000000,0x00000000,0x00009292,0x0000a49b,
+    0x000126dc,0x000136e4,0x0001b92d,0x0001b925},
+   {0x00000000,0x00000000,0x00009292,0x0000a49b,
+    0x000126dc,0x0001b724,0x0001b92d,0x0001c92d},
+   {0x00000000,0x00000000,0x00009492,0x000124db,
+    0x000126dc,0x0001b724,0x0001c96e,0x0001c92d},
+   {0x00000000,0x00000000,0x0000a492,0x000126db,
+    0x000136e4,0x0001b925,0x00025bb6,0x00024b77},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  },
+  { /* version 3, passes 1 */
+   {0x00000000,0x00000000,0x00001249,0x00000249,
+    0x0000124a,0x0000124a,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009252,0x00009292,0x00009292,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x0000924a,
+    0x00009492,0x00009493,0x0000a49b,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x00009252,
+    0x00009492,0x0000a49b,0x0000a49b,0x00009292},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x00009492,0x0000a49b,0x0000a49b,0x00009292},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x0000a49b,0x000126dc,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x0000a49b,0x000126dc,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x0000a49b,0x000126dc,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x000124db,0x000126dc,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x000124db,0x000126dc,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x000124db,0x000126dc,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000126dc,0x000126dc,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000124db,0x000136e4,0x000126dc,0x000124db},
+   {0x00000000,0x00000000,0x00009492,0x0000a49b,
+    0x000136e4,0x000136e4,0x000126dc,0x000124db},
+   {0x00000000,0x00000000,0x0000a492,0x000124db,
+    0x0001b724,0x0001b724,0x000136e4,0x000126dc},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  }
+ },
+ { /* version 4 */
+  { /* version 4, passes 0 */
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000049,0x00000049,0x00000049},
+   {0x00000000,0x00000000,0x00000249,0x00000049,
+    0x00000249,0x00000249,0x0000024a,0x00000049},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x0000124a,0x00009252,0x00001252,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009252,0x00009292,0x00009493,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x0000924a,
+    0x00009292,0x00009493,0x00009493,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x00009492,0x0000a49b,0x0000a49b,0x00009292},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x000124db,0x000124db,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x000124db,0x000126dc,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x000124db,0x000126dc,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0001249b,0x000126dc,0x000126dc,0x000124db},
+   {0x00000000,0x00000000,0x00009252,0x00009493,
+    0x000124db,0x000136e4,0x000136e4,0x000126dc},
+   {0x00000000,0x00000000,0x00009252,0x0000a49b,
+    0x000124db,0x000136e4,0x000136e4,0x000126dc},
+   {0x00000000,0x00000000,0x00009292,0x0000a49b,
+    0x000126dc,0x000136e4,0x000136e4,0x000136e4},
+   {0x00000000,0x00000000,0x00009492,0x0000a49b,
+    0x000126dc,0x0001b724,0x0001b725,0x0001b724},
+   {0x00000000,0x00000000,0x0000a492,0x000124db,
+    0x000136e4,0x0001b925,0x0001b92d,0x0001b925},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  },
+  { /* version 4, passes 1 */
+   {0x00000000,0x00000000,0x00000249,0x00000049,
+    0x00000009,0x00000009,0x00000009,0x00000009},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x00000049,0x00000049,0x00000009,0x00000009},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x0000124a,0x00000249,0x00000049,0x00000049},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x0000124a,0x0000124a,0x00000049,0x00000049},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009252,0x0000124a,0x0000024a,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x0000924a,
+    0x00009252,0x0000124a,0x0000024a,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x00009492,0x00009252,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x00009292,0x00009292,0x00001252},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x00009292,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x00009493,0x00009493,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x0000a49b,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x0000a49b,0x0000a49b,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000124db,0x0000a49b,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000136e4,0x000126dc,0x000124db,0x0000a49b},
+   {0x00000000,0x00000000,0x00009252,0x000124db,
+    0x0001b724,0x000136e4,0x000126dc,0x000124db},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  }
+ },
+ { /* version 5 */
+  { /* version 5, passes 0 */
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x00000249,0x00000249,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009252,0x00009292,0x00009292,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x0000924a,
+    0x00009492,0x0000a49b,0x0000a49b,0x00009292},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x0000a49b,0x000124db,0x00009493},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x000124db,0x000126dc,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x000126dc,0x000126dc,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000126dc,0x000136e4,0x000124db},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000126dc,0x000136e4,0x000136e4,0x000126dc},
+   {0x00000000,0x00000000,0x00009292,0x0000a49b,
+    0x000126dc,0x000136e4,0x000136e4,0x000126dc},
+   {0x00000000,0x00000000,0x00009292,0x0000a49b,
+    0x000126dc,0x0001b724,0x0001b725,0x000136e4},
+   {0x00000000,0x00000000,0x00009292,0x0000a49b,
+    0x000136e4,0x0001b724,0x0001b92d,0x0001b724},
+   {0x00000000,0x00000000,0x00009492,0x0000a49b,
+    0x000136e4,0x0001b724,0x0001b92d,0x0001b724},
+   {0x00000000,0x00000000,0x00009492,0x000124db,
+    0x000136e4,0x0001b925,0x0001c96e,0x0001b925},
+   {0x00000000,0x00000000,0x00009492,0x000124db,
+    0x0001b724,0x0001b925,0x0001c96e,0x0001c92d},
+   {0x00000000,0x00000000,0x0000a492,0x000126db,
+    0x0001c924,0x0002496d,0x00025bb6,0x00024b77},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  },
+  { /* version 5, passes 1 */
+   {0x00000000,0x00000000,0x00001249,0x00000249,
+    0x00000249,0x00000249,0x0000024a,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x0000124a,0x0000124a,0x0000024a,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x0000924a,
+    0x00009252,0x00009252,0x0000024a,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x00009492,0x0000a49b,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x0000a49b,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x0000a49b,0x00009292,0x00001252},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x0000a49b,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x0000a49b,0x00009493,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000124db,0x00009493,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000124db,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000124db,0x000124db,0x0000a49b,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x000124db,
+    0x000126dc,0x000126dc,0x0000a49b,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x000124db,
+    0x000136e4,0x000126dc,0x000124db,0x0000a49b},
+   {0x00000000,0x00000000,0x00009292,0x000124db,
+    0x000136e4,0x000126dc,0x000124db,0x0000a49b},
+   {0x00000000,0x00000000,0x00009492,0x000126db,
+    0x0001b724,0x000136e4,0x000126dc,0x000124db},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  }
+ },
+ { /* version 6 */
+  { /* version 6, passes 0 */
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009252,0x00009292,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x0000a493,0x0000a49b,0x0000a49b,0x00009493},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x000124db,0x000124db,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x000126dc,0x000126dc,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000126dc,0x000136e4,0x000124db},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000126dc,0x000136e4,0x000136e4,0x000126dc},
+   {0x00000000,0x00000000,0x00009292,0x0000a49b,
+    0x000126dc,0x0001b724,0x0001b725,0x000126dc},
+   {0x00000000,0x00000000,0x00009292,0x0000a49b,
+    0x000136e4,0x0001b724,0x0001b92d,0x000136e4},
+   {0x00000000,0x00000000,0x00009492,0x0000a49b,
+    0x000136e4,0x0001b724,0x0001b92d,0x0001b724},
+   {0x00000000,0x00000000,0x00009492,0x000124db,
+    0x000136e4,0x0001b724,0x0001b92d,0x0001b724},
+   {0x00000000,0x00000000,0x00009492,0x000124db,
+    0x000136e4,0x0001b925,0x0001b92d,0x0001b925},
+   {0x00000000,0x00000000,0x00009492,0x000124db,
+    0x0001b724,0x0001b925,0x0001c96e,0x0001c92d},
+   {0x00000000,0x00000000,0x0000a492,0x000124db,
+    0x0001b724,0x0001c92d,0x0001c96e,0x0001c92d},
+   {0x00000000,0x00000000,0x0000a492,0x000124db,
+    0x0001b724,0x0001c92d,0x00024b76,0x0002496e},
+   {0x00000000,0x00000000,0x00012492,0x000126db,
+    0x0001c924,0x00024b6d,0x0002ddb6,0x00025bbf},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  },
+  { /* version 6, passes 1 */
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x0000124a,0x0000124a,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x00009492,0x00009252,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x00009292,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x0000a49b,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x0000a49b,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x0000a49b,0x00009493,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000124db,0x000124db,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000124db,0x000124db,0x0000a49b,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x000124db,
+    0x000126dc,0x000124db,0x0000a49b,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x000124db,
+    0x000126dc,0x000126dc,0x0000a49b,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x000124db,
+    0x000136e4,0x000126dc,0x000124db,0x0000a49b},
+   {0x00000000,0x00000000,0x00009492,0x000126db,
+    0x000136e4,0x000126dc,0x000124db,0x0000a49b},
+   {0x00000000,0x00000000,0x00009492,0x000126db,
+    0x0001b724,0x000136e4,0x000126dc,0x000124db},
+   {0x00000000,0x00000000,0x00009492,0x000126db,
+    0x0001b724,0x000136e4,0x000126dc,0x000124db},
+   {0x00000000,0x00000000,0x0000a492,0x000136db,
+    0x0001c924,0x0001b724,0x000136e4,0x000126dc},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  }
+ },
+ { /* version 7 */
+  { /* version 7, passes 0 */
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009252,0x00009292,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x000124db,0x000126dc,0x00009493},
+   {0x00000000,0x00000000,0x00001249,0x0000a49b,
+    0x0001249b,0x000126dc,0x000126dc,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000126dc,0x000136e4,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000126dc,0x000136e4,0x0001b725,0x000124db},
+   {0x00000000,0x00000000,0x00009292,0x0000a49b,
+    0x000136e4,0x0001b724,0x0001b725,0x000126dc},
+   {0x00000000,0x00000000,0x00009292,0x000124db,
+    0x000136e4,0x0001b724,0x0001b725,0x000126dc},
+   {0x00000000,0x00000000,0x00009492,0x000124db,
+    0x000136e4,0x0001b724,0x0001c96e,0x000136e4},
+   {0x00000000,0x00000000,0x00009492,0x000124db,
+    0x000136e4,0x0001c92d,0x0001c96e,0x0001b724},
+   {0x00000000,0x00000000,0x0000a492,0x000124db,
+    0x000136e4,0x0001c92d,0x0001c96e,0x0001b724},
+   {0x00000000,0x00000000,0x0000a492,0x000124db,
+    0x0001b724,0x0001c92d,0x0001c96e,0x0001b925},
+   {0x00000000,0x00000000,0x0000a492,0x000126db,
+    0x0001b724,0x0001c92d,0x00024b76,0x0001c92d},
+   {0x00000000,0x00000000,0x0000a492,0x000126db,
+    0x0001b924,0x0001c92d,0x00024b76,0x0001c92d},
+   {0x00000000,0x00000000,0x0000a492,0x000126db,
+    0x0001b924,0x0001c92d,0x00024b76,0x0002496e},
+   {0x00000000,0x00000000,0x00012492,0x000136db,
+    0x00024924,0x00024b6d,0x0002ddb6,0x00025bbf},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  },
+  { /* version 7, passes 1 */
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x0000124a,0x0000124a,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x00009492,0x00009292,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x0000a49b,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x0000a49b,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x0000a49b,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000126dc,0x0000a49b,0x00009493,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x000124db,
+    0x000126dc,0x000124db,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x000124db,
+    0x000136e4,0x000124db,0x0000a49b,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x000136db,
+    0x0001b724,0x000124db,0x0000a49b,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x000136db,
+    0x0001b724,0x000126dc,0x0000a49b,0x0000a49b},
+   {0x00000000,0x00000000,0x00009292,0x000136db,
+    0x0001b724,0x000126dc,0x000124db,0x0000a49b},
+   {0x00000000,0x00000000,0x00009492,0x000136db,
+    0x0001b724,0x000126dc,0x000124db,0x0000a49b},
+   {0x00000000,0x00000000,0x0000a492,0x000136db,
+    0x0001b724,0x000136e4,0x000126dc,0x000124db},
+   {0x00000000,0x00000000,0x0000a492,0x000136db,
+    0x0001b724,0x000136e4,0x000126dc,0x000124db},
+   {0x00000000,0x00000000,0x00012492,0x0001b6db,
+    0x0001c924,0x0001b724,0x000136e4,0x000126dc},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  }
+ }
+};
+
diff -Nru a/drivers/usb/media/pwc/pwc-kiara.h b/drivers/usb/media/pwc/pwc-kiara.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/usb/media/pwc/pwc-kiara.h	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,45 @@
+/* Linux driver for Philips webcam
+   (C) 2004      Luc Saillard (luc@saillard.org)
+
+   NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
+   driver and thus may have bugs that are not present in the original version.
+   Please send bug reports and support requests to <luc@saillard.org>.
+   The decompression routines have been implemented by reverse-engineering the
+   Nemosoft binary pwcx module. Caveat emptor.
+
+   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
+*/
+
+/* Entries for the Kiara (730/740/750) camera */
+
+#ifndef PWC_KIARA_H
+#define PWC_KIARA_H
+
+#include "pwc-ioctl.h"
+
+struct Kiara_table_entry
+{
+	char alternate;			/* USB alternate interface */
+	unsigned short packetsize;	/* Normal packet size */
+	unsigned short bandlength;	/* Bandlength when decompressing */
+	unsigned char mode[12];		/* precomputed mode settings for cam */
+};
+
+const extern struct Kiara_table_entry Kiara_table[PSZ_MAX][6][4];
+const extern unsigned int KiaraRomTable[8][2][16][8];
+
+#endif
+
+
diff -Nru a/drivers/usb/media/pwc/pwc-misc.c b/drivers/usb/media/pwc/pwc-misc.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/usb/media/pwc/pwc-misc.c	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,140 @@
+/* Linux driver for Philips webcam 
+   Various miscellaneous functions and tables.
+   (C) 1999-2003 Nemosoft Unv.
+   (C) 2004      Luc Saillard (luc@saillard.org)
+
+   NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
+   driver and thus may have bugs that are not present in the original version.
+   Please send bug reports and support requests to <luc@saillard.org>.
+   The decompression routines have been implemented by reverse-engineering the
+   Nemosoft binary pwcx module. Caveat emptor.
+
+   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/slab.h>
+
+#include "pwc.h"
+
+struct pwc_coord pwc_image_sizes[PSZ_MAX] =
+{
+	{ 128,  96, 0 },
+	{ 160, 120, 0 },
+	{ 176, 144, 0 },
+	{ 320, 240, 0 },
+	{ 352, 288, 0 },
+	{ 640, 480, 0 },
+};
+
+/* x,y -> PSZ_ */
+int pwc_decode_size(struct pwc_device *pdev, int width, int height)
+{
+	int i, find;
+
+	/* Make sure we don't go beyond our max size.
+           NB: we have different limits for RAW and normal modes. In case
+           you don't have the decompressor loaded or use RAW mode, 
+           the maximum viewable size is smaller.
+        */
+	if (pdev->vpalette == VIDEO_PALETTE_RAW)
+	{
+		if (width > pdev->abs_max.x || height > pdev->abs_max.y)
+		{
+			Debug("VIDEO_PALETTE_RAW: going beyond abs_max.\n");
+                	return -1;
+                }
+	}
+	else
+	{
+		if (width > pdev->view_max.x || height > pdev->view_max.y)
+		{
+			Debug("VIDEO_PALETTE_ not RAW: going beyond view_max.\n");
+			return -1;
+		}
+	}
+
+	/* Find the largest size supported by the camera that fits into the
+	   requested size.
+	 */
+	find = -1;
+	for (i = 0; i < PSZ_MAX; i++) {
+		if (pdev->image_mask & (1 << i)) {
+			if (pwc_image_sizes[i].x <= width && pwc_image_sizes[i].y <= height)
+				find = i;
+		}
+	}
+	return find;
+}
+
+/* initialize variables depending on type and decompressor*/
+void pwc_construct(struct pwc_device *pdev)
+{
+	switch(pdev->type) {
+	case 645:
+	case 646:
+		pdev->view_min.x = 128;
+		pdev->view_min.y =  96;
+		pdev->view_max.x = 352;
+		pdev->view_max.y = 288;
+                pdev->abs_max.x  = 352;
+                pdev->abs_max.y  = 288;
+		pdev->image_mask = 1 << PSZ_SQCIF | 1 << PSZ_QCIF | 1 << PSZ_CIF;
+		pdev->vcinterface = 2;
+		pdev->vendpoint = 4;
+		pdev->frame_header_size = 0;
+		pdev->frame_trailer_size = 0;
+		break;
+	case 675:
+	case 680:
+	case 690:
+		pdev->view_min.x = 128;
+		pdev->view_min.y =  96;
+		/* Anthill bug #38: PWC always reports max size, even without PWCX */
+		pdev->view_max.x = 640;
+		pdev->view_max.y = 480;
+		pdev->image_mask = 1 << PSZ_SQCIF | 1 << PSZ_QSIF | 1 << PSZ_QCIF | 1 << PSZ_SIF | 1 << PSZ_CIF | 1 << PSZ_VGA;
+                pdev->abs_max.x = 640;
+                pdev->abs_max.y = 480;
+		pdev->vcinterface = 3;
+		pdev->vendpoint = 4;
+		pdev->frame_header_size = 0;
+		pdev->frame_trailer_size = 0;
+		break;
+	case 720:
+	case 730:
+	case 740:
+	case 750:
+		pdev->view_min.x = 160;
+		pdev->view_min.y = 120;
+		pdev->view_max.x = 640;
+		pdev->view_max.y = 480;
+		pdev->image_mask = 1 << PSZ_QSIF | 1 << PSZ_SIF | 1 << PSZ_VGA;
+                pdev->abs_max.x = 640;
+                pdev->abs_max.y = 480;
+		pdev->vcinterface = 3;
+		pdev->vendpoint = 5;
+		pdev->frame_header_size = TOUCAM_HEADER_SIZE;
+		pdev->frame_trailer_size = TOUCAM_TRAILER_SIZE;
+		break;
+	}
+	Debug("type = %d\n",pdev->type);
+	pdev->vpalette = VIDEO_PALETTE_YUV420P; /* default */
+	pdev->view_min.size = pdev->view_min.x * pdev->view_min.y;
+	pdev->view_max.size = pdev->view_max.x * pdev->view_max.y;
+	/* length of image, in YUV format; always allocate enough memory. */
+	pdev->len_per_image = (pdev->abs_max.x * pdev->abs_max.y * 3) / 2;
+}
+
+
diff -Nru a/drivers/usb/media/pwc/pwc-nala.h b/drivers/usb/media/pwc/pwc-nala.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/usb/media/pwc/pwc-nala.h	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,66 @@
+   /* SQCIF */
+   {
+      {0, 0, {0x04, 0x01, 0x03}},
+      {8, 0, {0x05, 0x01, 0x03}},
+      {7, 0, {0x08, 0x01, 0x03}},
+      {7, 0, {0x0A, 0x01, 0x03}},
+      {6, 0, {0x0C, 0x01, 0x03}},
+      {5, 0, {0x0F, 0x01, 0x03}},
+      {4, 0, {0x14, 0x01, 0x03}},
+      {3, 0, {0x18, 0x01, 0x03}},
+   },
+   /* QSIF */
+   {
+      {0},
+      {0},
+      {0},
+      {0},
+      {0},
+      {0},
+      {0},
+      {0},
+   },
+   /* QCIF */
+   {
+      {0, 0, {0x04, 0x01, 0x02}},
+      {8, 0, {0x05, 0x01, 0x02}},
+      {7, 0, {0x08, 0x01, 0x02}},
+      {6, 0, {0x0A, 0x01, 0x02}},
+      {5, 0, {0x0C, 0x01, 0x02}},
+      {4, 0, {0x0F, 0x01, 0x02}},
+      {1, 0, {0x14, 0x01, 0x02}},
+      {1, 0, {0x18, 0x01, 0x02}},
+   },
+   /* SIF */
+   {
+      {0},
+      {0},
+      {0},
+      {0},
+      {0},
+      {0},
+      {0},
+      {0},
+   },
+   /* CIF */
+   {
+      {4, 0, {0x04, 0x01, 0x01}},
+      {7, 1, {0x05, 0x03, 0x01}},
+      {6, 1, {0x08, 0x03, 0x01}},
+      {4, 1, {0x0A, 0x03, 0x01}},
+      {3, 1, {0x0C, 0x03, 0x01}},
+      {2, 1, {0x0F, 0x03, 0x01}},
+      {0},
+      {0},
+   },
+   /* VGA */
+   {  
+      {0},
+      {0},
+      {0},
+      {0},
+      {0},
+      {0},
+      {0},
+      {0},
+   },
diff -Nru a/drivers/usb/media/pwc/pwc-timon.c b/drivers/usb/media/pwc/pwc-timon.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/usb/media/pwc/pwc-timon.c	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,1446 @@
+/* Linux driver for Philips webcam
+   (C) 2004      Luc Saillard (luc@saillard.org)
+
+   NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
+   driver and thus may have bugs that are not present in the original version.
+   Please send bug reports and support requests to <luc@saillard.org>.
+   The decompression routines have been implemented by reverse-engineering the
+   Nemosoft binary pwcx module. Caveat emptor.
+
+   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 tables contains entries for the 675/680/690 (Timon) camera, with
+   4 different qualities (no compression, low, medium, high).
+   It lists the bandwidth requirements for said mode by its alternate interface
+   number. An alternate of 0 means that the mode is unavailable.
+
+   There are 6 * 4 * 4 entries:
+     6 different resolutions subqcif, qsif, qcif, sif, cif, vga
+     6 framerates: 5, 10, 15, 20, 25, 30
+     4 compression modi: none, low, medium, high
+
+   When an uncompressed mode is not available, the next available compressed mode
+   will be chosen (unless the decompressor is absent). Sometimes there are only
+   1 or 2 compressed modes available; in that case entries are duplicated.
+*/
+
+#include "pwc-timon.h"
+
+const struct Timon_table_entry Timon_table[PSZ_MAX][6][4] =
+{
+   /* SQCIF */
+   {
+      /* 5 fps */
+      {
+         {1, 140,    0, {0x05, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x8C, 0xFC, 0x80, 0x02}},
+         {1, 140,    0, {0x05, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x8C, 0xFC, 0x80, 0x02}},
+         {1, 140,    0, {0x05, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x8C, 0xFC, 0x80, 0x02}},
+         {1, 140,    0, {0x05, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x8C, 0xFC, 0x80, 0x02}},
+      },
+      /* 10 fps */
+      {
+         {2, 280,    0, {0x04, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x18, 0xA9, 0x80, 0x02}},
+         {2, 280,    0, {0x04, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x18, 0xA9, 0x80, 0x02}},
+         {2, 280,    0, {0x04, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x18, 0xA9, 0x80, 0x02}},
+         {2, 280,    0, {0x04, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x18, 0xA9, 0x80, 0x02}},
+      },
+      /* 15 fps */
+      {
+         {3, 410,    0, {0x03, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x9A, 0x71, 0x80, 0x02}},
+         {3, 410,    0, {0x03, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x9A, 0x71, 0x80, 0x02}},
+         {3, 410,    0, {0x03, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x9A, 0x71, 0x80, 0x02}},
+         {3, 410,    0, {0x03, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x9A, 0x71, 0x80, 0x02}},
+      },
+      /* 20 fps */
+      {
+         {4, 559,    0, {0x02, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x2F, 0x56, 0x80, 0x02}},
+         {4, 559,    0, {0x02, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x2F, 0x56, 0x80, 0x02}},
+         {4, 559,    0, {0x02, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x2F, 0x56, 0x80, 0x02}},
+         {4, 559,    0, {0x02, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x2F, 0x56, 0x80, 0x02}},
+      },
+      /* 25 fps */
+      {
+         {5, 659,    0, {0x01, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x93, 0x46, 0x80, 0x02}},
+         {5, 659,    0, {0x01, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x93, 0x46, 0x80, 0x02}},
+         {5, 659,    0, {0x01, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x93, 0x46, 0x80, 0x02}},
+         {5, 659,    0, {0x01, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x93, 0x46, 0x80, 0x02}},
+      },
+      /* 30 fps */
+      {
+         {7, 838,    0, {0x00, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x46, 0x3B, 0x80, 0x02}},
+         {7, 838,    0, {0x00, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x46, 0x3B, 0x80, 0x02}},
+         {7, 838,    0, {0x00, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x46, 0x3B, 0x80, 0x02}},
+         {7, 838,    0, {0x00, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x13, 0x00, 0x46, 0x3B, 0x80, 0x02}},
+      },
+   },
+   /* QSIF */
+   {
+      /* 5 fps */
+      {
+         {1, 146,    0, {0x2D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0xFC, 0xC0, 0x02}},
+         {1, 146,    0, {0x2D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0xFC, 0xC0, 0x02}},
+         {1, 146,    0, {0x2D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0xFC, 0xC0, 0x02}},
+         {1, 146,    0, {0x2D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x92, 0xFC, 0xC0, 0x02}},
+      },
+      /* 10 fps */
+      {
+         {2, 291,    0, {0x2C, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x23, 0xA1, 0xC0, 0x02}},
+         {1, 191,  630, {0x2C, 0xF4, 0x05, 0x13, 0xA9, 0x12, 0xE1, 0x17, 0x08, 0xBF, 0xF4, 0xC0, 0x02}},
+         {1, 191,  630, {0x2C, 0xF4, 0x05, 0x13, 0xA9, 0x12, 0xE1, 0x17, 0x08, 0xBF, 0xF4, 0xC0, 0x02}},
+         {1, 191,  630, {0x2C, 0xF4, 0x05, 0x13, 0xA9, 0x12, 0xE1, 0x17, 0x08, 0xBF, 0xF4, 0xC0, 0x02}},
+      },
+      /* 15 fps */
+      {
+         {3, 437,    0, {0x2B, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0xB5, 0x6D, 0xC0, 0x02}},
+         {2, 291,  640, {0x2B, 0xF4, 0x05, 0x13, 0xF7, 0x13, 0x2F, 0x13, 0x08, 0x23, 0xA1, 0xC0, 0x02}},
+         {2, 291,  640, {0x2B, 0xF4, 0x05, 0x13, 0xF7, 0x13, 0x2F, 0x13, 0x08, 0x23, 0xA1, 0xC0, 0x02}},
+         {1, 191,  420, {0x2B, 0xF4, 0x0D, 0x0D, 0x1B, 0x0C, 0x53, 0x1E, 0x08, 0xBF, 0xF4, 0xC0, 0x02}},
+      },
+      /* 20 fps */
+      {
+         {4, 588,    0, {0x2A, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x4C, 0x52, 0xC0, 0x02}},
+         {3, 447,  730, {0x2A, 0xF4, 0x05, 0x16, 0xC9, 0x16, 0x01, 0x0E, 0x18, 0xBF, 0x69, 0xC0, 0x02}},
+         {2, 292,  476, {0x2A, 0xF4, 0x0D, 0x0E, 0xD8, 0x0E, 0x10, 0x19, 0x18, 0x24, 0xA1, 0xC0, 0x02}},
+         {1, 192,  312, {0x2A, 0xF4, 0x1D, 0x09, 0xB3, 0x08, 0xEB, 0x1E, 0x18, 0xC0, 0xF4, 0xC0, 0x02}},
+      },
+      /* 25 fps */
+      {
+         {5, 703,    0, {0x29, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0xBF, 0x42, 0xC0, 0x02}},
+         {3, 447,  610, {0x29, 0xF4, 0x05, 0x13, 0x0B, 0x12, 0x43, 0x14, 0x18, 0xBF, 0x69, 0xC0, 0x02}},
+         {2, 292,  398, {0x29, 0xF4, 0x0D, 0x0C, 0x6C, 0x0B, 0xA4, 0x1E, 0x18, 0x24, 0xA1, 0xC0, 0x02}},
+         {1, 192,  262, {0x29, 0xF4, 0x25, 0x08, 0x23, 0x07, 0x5B, 0x1E, 0x18, 0xC0, 0xF4, 0xC0, 0x02}},
+      },
+      /* 30 fps */
+      {
+         {8, 873,    0, {0x28, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x69, 0x37, 0xC0, 0x02}},
+         {5, 704,  774, {0x28, 0xF4, 0x05, 0x18, 0x21, 0x17, 0x59, 0x0F, 0x18, 0xC0, 0x42, 0xC0, 0x02}},
+         {3, 448,  492, {0x28, 0xF4, 0x05, 0x0F, 0x5D, 0x0E, 0x95, 0x15, 0x18, 0xC0, 0x69, 0xC0, 0x02}},
+         {2, 291,  320, {0x28, 0xF4, 0x1D, 0x09, 0xFB, 0x09, 0x33, 0x1E, 0x18, 0x23, 0xA1, 0xC0, 0x02}},
+      },
+   },
+   /* QCIF */
+   {
+      /* 5 fps */
+      {
+         {1, 193,    0, {0x0D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0xC1, 0xF4, 0xC0, 0x02}},
+         {1, 193,    0, {0x0D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0xC1, 0xF4, 0xC0, 0x02}},
+         {1, 193,    0, {0x0D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0xC1, 0xF4, 0xC0, 0x02}},
+         {1, 193,    0, {0x0D, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0xC1, 0xF4, 0xC0, 0x02}},
+      },
+      /* 10 fps */
+      {
+         {3, 385,    0, {0x0C, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x81, 0x79, 0xC0, 0x02}},
+         {2, 291,  800, {0x0C, 0xF4, 0x05, 0x18, 0xF4, 0x18, 0x18, 0x11, 0x08, 0x23, 0xA1, 0xC0, 0x02}},
+         {2, 291,  800, {0x0C, 0xF4, 0x05, 0x18, 0xF4, 0x18, 0x18, 0x11, 0x08, 0x23, 0xA1, 0xC0, 0x02}},
+         {1, 194,  532, {0x0C, 0xF4, 0x05, 0x10, 0x9A, 0x0F, 0xBE, 0x1B, 0x08, 0xC2, 0xF0, 0xC0, 0x02}},
+      },
+      /* 15 fps */
+      {
+         {4, 577,    0, {0x0B, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x41, 0x52, 0xC0, 0x02}},
+         {3, 447,  818, {0x0B, 0xF4, 0x05, 0x19, 0x89, 0x18, 0xAD, 0x0F, 0x10, 0xBF, 0x69, 0xC0, 0x02}},
+         {2, 292,  534, {0x0B, 0xF4, 0x05, 0x10, 0xA3, 0x0F, 0xC7, 0x19, 0x10, 0x24, 0xA1, 0xC0, 0x02}},
+         {1, 195,  356, {0x0B, 0xF4, 0x15, 0x0B, 0x11, 0x0A, 0x35, 0x1E, 0x10, 0xC3, 0xF0, 0xC0, 0x02}},
+      },
+      /* 20 fps */
+      {
+         {6, 776,    0, {0x0A, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x08, 0x3F, 0xC0, 0x02}},
+         {4, 591,  804, {0x0A, 0xF4, 0x05, 0x19, 0x1E, 0x18, 0x42, 0x0F, 0x18, 0x4F, 0x4E, 0xC0, 0x02}},
+         {3, 447,  608, {0x0A, 0xF4, 0x05, 0x12, 0xFD, 0x12, 0x21, 0x15, 0x18, 0xBF, 0x69, 0xC0, 0x02}},
+         {2, 291,  396, {0x0A, 0xF4, 0x15, 0x0C, 0x5E, 0x0B, 0x82, 0x1E, 0x18, 0x23, 0xA1, 0xC0, 0x02}},
+      },
+      /* 25 fps */
+      {
+         {9, 928,    0, {0x09, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0xA0, 0x33, 0xC0, 0x02}},
+         {5, 703,  800, {0x09, 0xF4, 0x05, 0x18, 0xF4, 0x18, 0x18, 0x10, 0x18, 0xBF, 0x42, 0xC0, 0x02}},
+         {3, 447,  508, {0x09, 0xF4, 0x0D, 0x0F, 0xD2, 0x0E, 0xF6, 0x1B, 0x18, 0xBF, 0x69, 0xC0, 0x02}},
+         {2, 292,  332, {0x09, 0xF4, 0x1D, 0x0A, 0x5A, 0x09, 0x7E, 0x1E, 0x18, 0x24, 0xA1, 0xC0, 0x02}},
+      },
+      /* 30 fps */
+      {
+         {0, },
+         {9, 956,  876, {0x08, 0xF4, 0x05, 0x1B, 0x58, 0x1A, 0x7C, 0x0E, 0x20, 0xBC, 0x33, 0x10, 0x02}},
+         {4, 592,  542, {0x08, 0xF4, 0x05, 0x10, 0xE4, 0x10, 0x08, 0x17, 0x20, 0x50, 0x4E, 0x10, 0x02}},
+         {2, 291,  266, {0x08, 0xF4, 0x25, 0x08, 0x48, 0x07, 0x6C, 0x1E, 0x20, 0x23, 0xA1, 0x10, 0x02}},
+      },
+   },
+   /* SIF */
+   {
+      /* 5 fps */
+      {
+         {4, 582,    0, {0x35, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x46, 0x52, 0x60, 0x02}},
+         {3, 387, 1276, {0x35, 0xF4, 0x05, 0x27, 0xD8, 0x26, 0x48, 0x03, 0x10, 0x83, 0x79, 0x60, 0x02}},
+         {2, 291,  960, {0x35, 0xF4, 0x0D, 0x1D, 0xF2, 0x1C, 0x62, 0x04, 0x10, 0x23, 0xA1, 0x60, 0x02}},
+         {1, 191,  630, {0x35, 0xF4, 0x1D, 0x13, 0xA9, 0x12, 0x19, 0x05, 0x08, 0xBF, 0xF4, 0x60, 0x02}},
+      },
+      /* 10 fps */
+      {
+         {0, },
+         {6, 775, 1278, {0x34, 0xF4, 0x05, 0x27, 0xE8, 0x26, 0x58, 0x05, 0x30, 0x07, 0x3F, 0x10, 0x02}},
+         {3, 447,  736, {0x34, 0xF4, 0x15, 0x16, 0xFB, 0x15, 0x6B, 0x05, 0x18, 0xBF, 0x69, 0x10, 0x02}},
+         {2, 291,  480, {0x34, 0xF4, 0x2D, 0x0E, 0xF9, 0x0D, 0x69, 0x09, 0x18, 0x23, 0xA1, 0x10, 0x02}},
+      },
+      /* 15 fps */
+      {
+         {0, },
+         {9, 955, 1050, {0x33, 0xF4, 0x05, 0x20, 0xCF, 0x1F, 0x3F, 0x06, 0x48, 0xBB, 0x33, 0x10, 0x02}},
+         {4, 591,  650, {0x33, 0xF4, 0x15, 0x14, 0x44, 0x12, 0xB4, 0x08, 0x30, 0x4F, 0x4E, 0x10, 0x02}},
+         {3, 448,  492, {0x33, 0xF4, 0x25, 0x0F, 0x52, 0x0D, 0xC2, 0x09, 0x28, 0xC0, 0x69, 0x10, 0x02}},
+      },
+      /* 20 fps */
+      {
+         {0, },
+         {9, 958,  782, {0x32, 0xF4, 0x0D, 0x18, 0x6A, 0x16, 0xDA, 0x0B, 0x58, 0xBE, 0x33, 0xD0, 0x02}},
+         {5, 703,  574, {0x32, 0xF4, 0x1D, 0x11, 0xE7, 0x10, 0x57, 0x0B, 0x40, 0xBF, 0x42, 0xD0, 0x02}},
+         {3, 446,  364, {0x32, 0xF4, 0x3D, 0x0B, 0x5C, 0x09, 0xCC, 0x0E, 0x30, 0xBE, 0x69, 0xD0, 0x02}},
+      },
+      /* 25 fps */
+      {
+         {0, },
+         {9, 958,  654, {0x31, 0xF4, 0x15, 0x14, 0x66, 0x12, 0xD6, 0x0B, 0x50, 0xBE, 0x33, 0x90, 0x02}},
+         {6, 776,  530, {0x31, 0xF4, 0x25, 0x10, 0x8C, 0x0E, 0xFC, 0x0C, 0x48, 0x08, 0x3F, 0x90, 0x02}},
+         {4, 592,  404, {0x31, 0xF4, 0x35, 0x0C, 0x96, 0x0B, 0x06, 0x0B, 0x38, 0x50, 0x4E, 0x90, 0x02}},
+      },
+      /* 30 fps */
+      {
+         {0, },
+         {9, 957,  526, {0x30, 0xF4, 0x25, 0x10, 0x68, 0x0E, 0xD8, 0x0D, 0x58, 0xBD, 0x33, 0x60, 0x02}},
+         {6, 775,  426, {0x30, 0xF4, 0x35, 0x0D, 0x48, 0x0B, 0xB8, 0x0F, 0x50, 0x07, 0x3F, 0x60, 0x02}},
+         {4, 590,  324, {0x30, 0x7A, 0x4B, 0x0A, 0x1C, 0x08, 0xB4, 0x0E, 0x40, 0x4E, 0x52, 0x60, 0x02}},
+      },
+   },
+   /* CIF */
+   {
+      /* 5 fps */
+      {
+         {6, 771,    0, {0x15, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x03, 0x3F, 0x80, 0x02}},
+         {4, 465, 1278, {0x15, 0xF4, 0x05, 0x27, 0xEE, 0x26, 0x36, 0x03, 0x18, 0xD1, 0x65, 0x80, 0x02}},
+         {2, 291,  800, {0x15, 0xF4, 0x15, 0x18, 0xF4, 0x17, 0x3C, 0x05, 0x18, 0x23, 0xA1, 0x80, 0x02}},
+         {1, 193,  528, {0x15, 0xF4, 0x2D, 0x10, 0x7E, 0x0E, 0xC6, 0x0A, 0x18, 0xC1, 0xF4, 0x80, 0x02}},
+      },
+      /* 10 fps */
+      {
+         {0, },
+         {9, 932, 1278, {0x14, 0xF4, 0x05, 0x27, 0xEE, 0x26, 0x36, 0x04, 0x30, 0xA4, 0x33, 0x10, 0x02}},
+         {4, 591,  812, {0x14, 0xF4, 0x15, 0x19, 0x56, 0x17, 0x9E, 0x06, 0x28, 0x4F, 0x4E, 0x10, 0x02}},
+         {2, 291,  400, {0x14, 0xF4, 0x3D, 0x0C, 0x7A, 0x0A, 0xC2, 0x0E, 0x28, 0x23, 0xA1, 0x10, 0x02}},
+      },
+      /* 15 fps */
+      {
+         {0, },
+         {9, 956,  876, {0x13, 0xF4, 0x0D, 0x1B, 0x58, 0x19, 0xA0, 0x05, 0x38, 0xBC, 0x33, 0x60, 0x02}},
+         {5, 703,  644, {0x13, 0xF4, 0x1D, 0x14, 0x1C, 0x12, 0x64, 0x08, 0x38, 0xBF, 0x42, 0x60, 0x02}},
+         {3, 448,  410, {0x13, 0xF4, 0x3D, 0x0C, 0xC4, 0x0B, 0x0C, 0x0E, 0x38, 0xC0, 0x69, 0x60, 0x02}},
+      },
+      /* 20 fps */
+      {
+         {0, },
+         {9, 956,  650, {0x12, 0xF4, 0x1D, 0x14, 0x4A, 0x12, 0x92, 0x09, 0x48, 0xBC, 0x33, 0x10, 0x03}},
+         {6, 776,  528, {0x12, 0xF4, 0x2D, 0x10, 0x7E, 0x0E, 0xC6, 0x0A, 0x40, 0x08, 0x3F, 0x10, 0x03}},
+         {4, 591,  402, {0x12, 0xF4, 0x3D, 0x0C, 0x8F, 0x0A, 0xD7, 0x0E, 0x40, 0x4F, 0x4E, 0x10, 0x03}},
+      },
+      /* 25 fps */
+      {
+         {0, },
+         {9, 956,  544, {0x11, 0xF4, 0x25, 0x10, 0xF4, 0x0F, 0x3C, 0x0A, 0x48, 0xBC, 0x33, 0xC0, 0x02}},
+         {7, 840,  478, {0x11, 0xF4, 0x2D, 0x0E, 0xEB, 0x0D, 0x33, 0x0B, 0x48, 0x48, 0x3B, 0xC0, 0x02}},
+         {5, 703,  400, {0x11, 0xF4, 0x3D, 0x0C, 0x7A, 0x0A, 0xC2, 0x0E, 0x48, 0xBF, 0x42, 0xC0, 0x02}},
+      },
+      /* 30 fps */
+      {
+         {0, },
+         {9, 956,  438, {0x10, 0xF4, 0x35, 0x0D, 0xAC, 0x0B, 0xF4, 0x0D, 0x50, 0xBC, 0x33, 0x10, 0x02}},
+         {7, 838,  384, {0x10, 0xF4, 0x45, 0x0B, 0xFD, 0x0A, 0x45, 0x0F, 0x50, 0x46, 0x3B, 0x10, 0x02}},
+         {6, 773,  354, {0x10, 0x7A, 0x4B, 0x0B, 0x0C, 0x09, 0x80, 0x10, 0x50, 0x05, 0x3F, 0x10, 0x02}},
+      },
+   },
+   /* VGA */
+   {
+      /* 5 fps */
+      {
+         {0, },
+         {6, 773, 1272, {0x1D, 0xF4, 0x15, 0x27, 0xB6, 0x24, 0x96, 0x02, 0x30, 0x05, 0x3F, 0x10, 0x02}},
+         {4, 592,  976, {0x1D, 0xF4, 0x25, 0x1E, 0x78, 0x1B, 0x58, 0x03, 0x30, 0x50, 0x4E, 0x10, 0x02}},
+         {3, 448,  738, {0x1D, 0xF4, 0x3D, 0x17, 0x0C, 0x13, 0xEC, 0x04, 0x30, 0xC0, 0x69, 0x10, 0x02}},
+      },
+      /* 10 fps */
+      {
+         {0, },
+         {9, 956,  788, {0x1C, 0xF4, 0x35, 0x18, 0x9C, 0x15, 0x7C, 0x03, 0x48, 0xBC, 0x33, 0x10, 0x02}},
+         {6, 776,  640, {0x1C, 0x7A, 0x53, 0x13, 0xFC, 0x11, 0x2C, 0x04, 0x48, 0x08, 0x3F, 0x10, 0x02}},
+         {4, 592,  488, {0x1C, 0x7A, 0x6B, 0x0F, 0x3C, 0x0C, 0x6C, 0x06, 0x48, 0x50, 0x4E, 0x10, 0x02}},
+      },
+      /* 15 fps */
+      {
+         {0, },
+         {9, 957,  526, {0x1B, 0x7A, 0x63, 0x10, 0x68, 0x0D, 0x98, 0x06, 0x58, 0xBD, 0x33, 0x80, 0x02}},
+         {9, 957,  526, {0x1B, 0x7A, 0x63, 0x10, 0x68, 0x0D, 0x98, 0x06, 0x58, 0xBD, 0x33, 0x80, 0x02}},
+         {8, 895,  492, {0x1B, 0x7A, 0x6B, 0x0F, 0x5D, 0x0C, 0x8D, 0x06, 0x58, 0x7F, 0x37, 0x80, 0x02}},
+      },
+      /* 20 fps */
+      {
+         {0, },
+         {0, },
+         {0, },
+         {0, },
+      },
+      /* 25 fps */
+      {
+         {0, },
+         {0, },
+         {0, },
+         {0, },
+      },
+      /* 30 fps */
+      {
+         {0, },
+         {0, },
+         {0, },
+         {0, },
+      },
+   },
+};
+
+/*
+ * 16 versions:
+ *   2 tables  (one for Y, and one for U&V)
+ *   16 levels of details per tables
+ *   8 blocs
+ */
+
+const unsigned int TimonRomTable [16][2][16][8] =  
+{
+ { /* version 0 */
+  { /* version 0, passes 0 */
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000001},
+   {0x00000000,0x00000000,0x00000001,0x00000001,
+    0x00000001,0x00000001,0x00000001,0x00000001},
+   {0x00000000,0x00000000,0x00000001,0x00000001,
+    0x00000001,0x00000009,0x00000009,0x00000009},
+   {0x00000000,0x00000000,0x00000009,0x00000001,
+    0x00000009,0x00000009,0x00000009,0x00000009},
+   {0x00000000,0x00000000,0x00000009,0x00000009,
+    0x00000009,0x00000009,0x00000049,0x00000009},
+   {0x00000000,0x00000000,0x00000009,0x00000009,
+    0x00000009,0x00000049,0x00000049,0x00000049},
+   {0x00000000,0x00000000,0x00000009,0x00000009,
+    0x00000049,0x00000049,0x00000049,0x00000049},
+   {0x00000000,0x00000000,0x00000009,0x00000049,
+    0x00000049,0x00000049,0x00000049,0x00000049},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000049,0x0000024a,0x0000024a},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000249,0x0000024a,0x0000024a},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000249,0x00000249,0x0000024a,0x0000024a},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000249,0x00000249,0x00001252,0x0000024a},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000249,0x0000124a,0x00001252,0x0000024a},
+   {0x00000000,0x00000000,0x00000049,0x00000249,
+    0x00000249,0x0000124a,0x00001252,0x0000024a},
+   {0x00000000,0x00000000,0x00000249,0x00001249,
+    0x0000124a,0x00009252,0x00009292,0x00001252},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  },
+  { /* version 0, passes 1 */
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000},
+   {0x00000000,0x00000000,0x00000001,0x00000001,
+    0x00000001,0x00000001,0x00000000,0x00000000},
+   {0x00000000,0x00000000,0x00000009,0x00000001,
+    0x00000001,0x00000009,0x00000000,0x00000000},
+   {0x00000000,0x00000000,0x00000009,0x00000009,
+    0x00000009,0x00000009,0x00000000,0x00000000},
+   {0x00000000,0x00000000,0x00000009,0x00000009,
+    0x00000009,0x00000009,0x00000001,0x00000000},
+   {0x00000000,0x00000000,0x00000049,0x00000009,
+    0x00000009,0x00000049,0x00000001,0x00000001},
+   {0x00000000,0x00000000,0x00000049,0x00000009,
+    0x00000009,0x00000049,0x00000001,0x00000001},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000049,0x00000009,0x00000001},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000049,0x00000009,0x00000001},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000049,0x00000009,0x00000001},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000049,0x00000009,0x00000009},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000249,0x00000049,0x00000009},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000249,0x00000049,0x00000009},
+   {0x00000000,0x00000000,0x00000249,0x00000049,
+    0x00000249,0x00000249,0x00000049,0x00000009},
+   {0x00000000,0x00000000,0x00001249,0x00000249,
+    0x0000124a,0x0000124a,0x0000024a,0x00000049},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  }
+ },
+ { /* version 1 */
+  { /* version 1, passes 0 */
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000001},
+   {0x00000000,0x00000000,0x00000001,0x00000001,
+    0x00000001,0x00000009,0x00000009,0x00000009},
+   {0x00000000,0x00000000,0x00000009,0x00000009,
+    0x00000009,0x00000009,0x00000009,0x00000009},
+   {0x00000000,0x00000000,0x00000009,0x00000009,
+    0x00000009,0x00000049,0x00000049,0x00000049},
+   {0x00000000,0x00000000,0x00000009,0x00000049,
+    0x00000049,0x00000049,0x00000049,0x00000049},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000249,0x0000024a,0x0000024a},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000249,0x00000249,0x0000024a,0x0000024a},
+   {0x00000000,0x00000000,0x00000049,0x00000249,
+    0x00000249,0x00000249,0x0000024a,0x00001252},
+   {0x00000000,0x00000000,0x00000049,0x00000249,
+    0x00000249,0x0000124a,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x00000049,0x00000249,
+    0x0000124a,0x0000124a,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x0000124a,0x0000124a,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x00000249,0x00001249,
+    0x0000124a,0x00009252,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x00000249,0x00001249,
+    0x00009252,0x00009252,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x00000249,0x0000924a,
+    0x00009292,0x00009493,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x00001249,0x00009252,
+    0x00009492,0x0000a49b,0x0000a49b,0x0000a49b},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  },
+  { /* version 1, passes 1 */
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000},
+   {0x00000000,0x00000000,0x00000009,0x00000009,
+    0x00000009,0x00000001,0x00000001,0x00000000},
+   {0x00000000,0x00000000,0x00000009,0x00000009,
+    0x00000009,0x00000009,0x00000001,0x00000000},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000009,0x00000001,0x00000000},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000049,0x00000001,0x00000001},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000049,0x00000009,0x00000001},
+   {0x00000000,0x00000000,0x00000249,0x00000049,
+    0x00000049,0x00000249,0x00000009,0x00000001},
+   {0x00000000,0x00000000,0x00000249,0x00000049,
+    0x00000249,0x00000249,0x00000009,0x00000009},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x00000249,0x00000249,0x00000049,0x00000009},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x00000249,0x0000124a,0x00000049,0x00000009},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x00000249,0x0000124a,0x00000049,0x00000009},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x00000249,0x0000124a,0x0000024a,0x00000049},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x0000124a,0x0000124a,0x0000024a,0x00000049},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x0000124a,0x0000124a,0x0000024a,0x00000049},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009252,0x00009252,0x00001252,0x0000024a},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  }
+ },
+ { /* version 2 */
+  { /* version 2, passes 0 */
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000001},
+   {0x00000000,0x00000000,0x00000009,0x00000009,
+    0x00000009,0x00000009,0x00000009,0x00000009},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000049,0x00000049,0x00000049},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000249,0x0000024a,0x0000024a},
+   {0x00000000,0x00000000,0x00000049,0x00000249,
+    0x00000249,0x00000249,0x0000024a,0x00001252},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x00000249,0x0000124a,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x0000124a,0x0000124a,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x00000249,0x00001249,
+    0x0000124a,0x00009252,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x00000249,0x00001249,
+    0x00009252,0x00009292,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x00000249,0x00001249,
+    0x00009252,0x00009292,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x00000249,0x0000924a,
+    0x00009252,0x00009493,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x00000249,0x0000924a,
+    0x00009292,0x00009493,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x00000249,0x00009252,
+    0x00009492,0x00009493,0x0000a49b,0x0000a49b},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x00009492,0x000124db,0x000124db,0x000124db},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x000126dc,0x000126dc,0x000126dc},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  },
+  { /* version 2, passes 1 */
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000},
+   {0x00000000,0x00000000,0x00000049,0x00000009,
+    0x00000049,0x00000009,0x00000001,0x00000000},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000049,0x00000049,0x00000000},
+   {0x00000000,0x00000000,0x00000249,0x00000049,
+    0x00000249,0x00000049,0x0000024a,0x00000001},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x00000249,0x00000249,0x0000024a,0x00000001},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x00000249,0x00000249,0x0000024a,0x00000001},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x00000249,0x00000249,0x0000024a,0x00000009},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x0000124a,0x0000124a,0x0000024a,0x00000009},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x0000124a,0x0000124a,0x0000024a,0x00000009},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x0000124a,0x00009252,0x00001252,0x00000049},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x0000124a,0x00009292,0x00001252,0x00000049},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x0000124a,0x00009292,0x00001252,0x00000049},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009252,0x00009292,0x00001252,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009292,0x00009292,0x00001252,0x0000024a},
+   {0x00000000,0x00000000,0x0000924a,0x0000924a,
+    0x00009492,0x00009493,0x00009292,0x00001252},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  }
+ },
+ { /* version 3 */
+  { /* version 3, passes 0 */
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000001},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000049,0x00000049,0x00000049},
+   {0x00000000,0x00000000,0x00000049,0x00000249,
+    0x00000249,0x00000249,0x00001252,0x0000024a},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x00000249,0x0000124a,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x0000124a,0x00009252,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x00000249,0x00001249,
+    0x0000124a,0x00009292,0x00009292,0x00009493},
+   {0x00000000,0x00000000,0x00000249,0x00001249,
+    0x00009252,0x00009292,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x00000249,0x00001249,
+    0x00009292,0x00009493,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x00000249,0x00009252,
+    0x00009292,0x00009493,0x0000a49b,0x0000a49b},
+   {0x00000000,0x00000000,0x00001249,0x00009252,
+    0x00009292,0x0000a49b,0x0000a49b,0x0000a49b},
+   {0x00000000,0x00000000,0x00001249,0x00009252,
+    0x00009492,0x0000a49b,0x0000a49b,0x0000a49b},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x00009492,0x0000a49b,0x000124db,0x000124db},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x0000a493,0x0000a49b,0x000124db,0x000124db},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0001249b,0x000126dc,0x000136e4,0x000126dc},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000124db,0x000136e4,0x0001b725,0x000136e4},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  },
+  { /* version 3, passes 1 */
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000},
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000049,0x00000001,0x00000000},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x00000249,0x00000249,0x00000049,0x00000001},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x00000249,0x0000124a,0x00001252,0x00000001},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x0000124a,0x0000124a,0x00001252,0x00000009},
+   {0x00000000,0x00000000,0x00000249,0x00001249,
+    0x0000124a,0x00009252,0x00009292,0x00000009},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x0000124a,0x00009252,0x00009292,0x00000049},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009252,0x00009252,0x00009292,0x00000049},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009252,0x00009493,0x00009292,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009252,0x00009493,0x00009292,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009252,0x00009493,0x00009493,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x0000924a,
+    0x00009292,0x00009493,0x00009493,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x0000924a,
+    0x00009492,0x00009493,0x00009493,0x00009292},
+   {0x00000000,0x00000000,0x00001249,0x00009252,
+    0x00009492,0x0000a49b,0x00009493,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x00009292,
+    0x0000a493,0x000124db,0x0000a49b,0x00009493},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  }
+ },
+ { /* version 4 */
+  { /* version 4, passes 0 */
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000049,0x0000024a,0x0000024a},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x00000249,0x0000124a,0x00001252,0x00009292},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x0000124a,0x00009252,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x00000249,0x00001249,
+    0x0000124a,0x00009292,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x00000249,0x00001249,
+    0x00009252,0x00009493,0x00009493,0x0000a49b},
+   {0x00000000,0x00000000,0x00000249,0x0000924a,
+    0x00009292,0x00009493,0x0000a49b,0x0000a49b},
+   {0x00000000,0x00000000,0x00001249,0x0000924a,
+    0x00009292,0x00009493,0x0000a49b,0x000124db},
+   {0x00000000,0x00000000,0x00001249,0x00009252,
+    0x00009492,0x0000a49b,0x0000a49b,0x000124db},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x00009492,0x000124db,0x000124db,0x000126dc},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x0000a493,0x000124db,0x000126dc,0x000126dc},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x000124db,0x000126dc,0x000136e4},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x000126dc,0x000136e4,0x000136e4},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0001249b,0x000126dc,0x000136e4,0x000136e4},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000124db,0x000136e4,0x000136e4,0x0001b724},
+   {0x00000000,0x00000000,0x00009252,0x000124db,
+    0x000126dc,0x0001b724,0x0001b725,0x0001b925},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  },
+  { /* version 4, passes 1 */
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000049,0x00000049,0x00000049},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x00000249,0x00000249,0x0000024a,0x00000049},
+   {0x00000000,0x00000000,0x00001249,0x00000249,
+    0x0000124a,0x0000124a,0x00001252,0x00000049},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x0000124a,0x0000124a,0x00009292,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009252,0x00009292,0x00009292,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009252,0x00009292,0x0000a49b,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009292,0x00009493,0x0000a49b,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009292,0x00009493,0x0000a49b,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x0000924a,
+    0x00009492,0x0000a49b,0x0000a49b,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x00009252,
+    0x00009492,0x0000a49b,0x0000a49b,0x00009292},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x00009492,0x0000a49b,0x0000a49b,0x00009292},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x0000a49b,0x0000a49b,0x00009292},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x0000a49b,0x0000a49b,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x000124db,0x0000a49b,0x00009493},
+   {0x00000000,0x00000000,0x00009252,0x0000a49b,
+    0x0001249b,0x000126dc,0x000124db,0x0000a49b},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  }
+ },
+ { /* version 5 */
+  { /* version 5, passes 0 */
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x00000249,0x0000124a,0x00001252,0x00009292},
+   {0x00000000,0x00000000,0x00000249,0x00001249,
+    0x0000124a,0x00009292,0x00009292,0x00009493},
+   {0x00000000,0x00000000,0x00000249,0x0000924a,
+    0x00009292,0x00009493,0x0000a49b,0x0000a49b},
+   {0x00000000,0x00000000,0x00001249,0x0000924a,
+    0x00009292,0x00009493,0x0000a49b,0x0000a49b},
+   {0x00000000,0x00000000,0x00001249,0x0000924a,
+    0x00009492,0x0000a49b,0x0000a49b,0x000124db},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x00009492,0x0000a49b,0x000124db,0x000124db},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x0000a493,0x000124db,0x000124db,0x000126dc},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x000124db,0x000126dc,0x000126dc},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x000126dc,0x000136e4,0x000136e4},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0001249b,0x000126dc,0x000136e4,0x000136e4},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0001249b,0x000126dc,0x000136e4,0x000136e4},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0001249b,0x000126dc,0x0001b725,0x0001b724},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000124db,0x000126dc,0x0001b725,0x0001b724},
+   {0x00000000,0x00000000,0x00009292,0x0000a49b,
+    0x000126dc,0x000136e4,0x0001b92d,0x0001b925},
+   {0x00000000,0x00000000,0x00009492,0x000124db,
+    0x000136e4,0x0001b724,0x0001c96e,0x0001c92d},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  },
+  { /* version 5, passes 1 */
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x0000124a,0x00000249,0x0000024a,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x0000124a,0x0000124a,0x00001252,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009292,0x00009493,0x00009493,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009292,0x00009493,0x00009493,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009292,0x00009493,0x0000a49b,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x0000924a,
+    0x00009492,0x00009493,0x000124db,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x00009492,0x00009493,0x000124db,0x00009292},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x00009492,0x0000a49b,0x000124db,0x00009292},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x0000a49b,0x000124db,0x00009292},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x000124db,0x000124db,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x000124db,0x000124db,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x000124db,0x000124db,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x000124db,0x000124db,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000124db,0x000126dc,0x000124db,0x0000a49b},
+   {0x00000000,0x00000000,0x00009252,0x000124db,
+    0x000126dc,0x000136e4,0x000126dc,0x000124db},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  }
+ },
+ { /* version 6 */
+  { /* version 6, passes 0 */
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x0000124a,0x0000124a,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009292,0x00009493,0x0000a49b,0x0000a49b},
+   {0x00000000,0x00000000,0x00001249,0x0000924a,
+    0x00009492,0x0000a49b,0x0000a49b,0x000124db},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x00009492,0x000124db,0x000126dc,0x000126dc},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x000124db,0x000126dc,0x000126dc},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x000126dc,0x000136e4,0x000136e4},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x000126dc,0x000136e4,0x0001b724},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0001249b,0x000126dc,0x000136e4,0x0001b724},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000126dc,0x000136e4,0x0001b724},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000136e4,0x0001b725,0x0001b724},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000124db,0x000136e4,0x0001b725,0x0001b925},
+   {0x00000000,0x00000000,0x00009292,0x0000a49b,
+    0x000126dc,0x000136e4,0x0001b92d,0x0001b925},
+   {0x00000000,0x00000000,0x00009292,0x0000a49b,
+    0x000126dc,0x0001b724,0x0001b92d,0x0001c92d},
+   {0x00000000,0x00000000,0x00009492,0x000124db,
+    0x000126dc,0x0001b724,0x0001c96e,0x0001c92d},
+   {0x00000000,0x00000000,0x0000a492,0x000126db,
+    0x000136e4,0x0001b925,0x00025bb6,0x00024b77},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  },
+  { /* version 6, passes 1 */
+   {0x00000000,0x00000000,0x00001249,0x00000249,
+    0x0000124a,0x0000124a,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009252,0x00009292,0x00009292,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x0000924a,
+    0x00009492,0x00009493,0x0000a49b,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x00009252,
+    0x00009492,0x0000a49b,0x0000a49b,0x00009292},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x00009492,0x0000a49b,0x0000a49b,0x00009292},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x0000a49b,0x000126dc,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x0000a49b,0x000126dc,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x0000a49b,0x000126dc,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x000124db,0x000126dc,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x000124db,0x000126dc,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x000124db,0x000126dc,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000126dc,0x000126dc,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000124db,0x000136e4,0x000126dc,0x000124db},
+   {0x00000000,0x00000000,0x00009492,0x0000a49b,
+    0x000136e4,0x000136e4,0x000126dc,0x000124db},
+   {0x00000000,0x00000000,0x0000a492,0x000124db,
+    0x0001b724,0x0001b724,0x000136e4,0x000126dc},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  }
+ },
+ { /* version 7 */
+  { /* version 7, passes 0 */
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009292,0x00009493,0x0000a49b,0x000124db},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x0000a493,0x0000a49b,0x000124db,0x000126dc},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x000124db,0x000126dc,0x000136e4},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x000124db,0x000136e4,0x000136e4},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0001249b,0x000126dc,0x000136e4,0x000136e4},
+   {0x00000000,0x00000000,0x00001249,0x0000a49b,
+    0x0001249b,0x000126dc,0x000136e4,0x0001b724},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000126dc,0x000136e4,0x0001b724},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000124db,0x000136e4,0x0001b725,0x0001b724},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000126dc,0x000136e4,0x0001b725,0x0001b925},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000126dc,0x0001b724,0x0001b92d,0x0001b925},
+   {0x00000000,0x00000000,0x00009292,0x0000a49b,
+    0x000126dc,0x0001b724,0x0001c96e,0x0001c92d},
+   {0x00000000,0x00000000,0x00009292,0x000124db,
+    0x000126dc,0x0001b724,0x0001c96e,0x0001c92d},
+   {0x00000000,0x00000000,0x00009492,0x000124db,
+    0x000136e4,0x0001b724,0x0001c96e,0x0002496e},
+   {0x00000000,0x00000000,0x00009492,0x000126db,
+    0x000136e4,0x0001b925,0x0001c96e,0x0002496e},
+   {0x00000000,0x00000000,0x0000a492,0x000136db,
+    0x0001b724,0x0002496d,0x00025bb6,0x00025bbf},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  },
+  { /* version 7, passes 1 */
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009252,0x00009292,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x00001249,0x0000924a,
+    0x00009492,0x00009493,0x00009493,0x00009292},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x0000a49b,0x0000a49b,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x0000a49b,0x000124db,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x000124db,0x000124db,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x000124db,0x000136e4,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x000124db,0x000136e4,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000124db,0x000136e4,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000126dc,0x000136e4,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000126dc,0x000136e4,0x000124db},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000126dc,0x000136e4,0x000136e4,0x000124db},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000126dc,0x000136e4,0x000136e4,0x000124db},
+   {0x00000000,0x00000000,0x0000924a,0x000124db,
+    0x000136e4,0x000136e4,0x000136e4,0x000126dc},
+   {0x00000000,0x00000000,0x0000a492,0x000124db,
+    0x000136e4,0x0001b724,0x000136e4,0x000126dc},
+   {0x00000000,0x00000000,0x00012492,0x000126db,
+    0x0001b724,0x0001b925,0x0001b725,0x000136e4},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  }
+ },
+ { /* version 8 */
+  { /* version 8, passes 0 */
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009292,0x00009493,0x0000a49b,0x000124db},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x0000a493,0x000124db,0x000126dc,0x000126dc},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x000124db,0x000126dc,0x000136e4},
+   {0x00000000,0x00000000,0x00001249,0x0000a49b,
+    0x0001249b,0x000126dc,0x000136e4,0x0001b724},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000126dc,0x000136e4,0x0001b724},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000124db,0x000136e4,0x0001b725,0x0001b724},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000126dc,0x000136e4,0x0001b725,0x0001b925},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000126dc,0x0001b724,0x0001b92d,0x0001c92d},
+   {0x00000000,0x00000000,0x00009252,0x000124db,
+    0x000126dc,0x0001b724,0x0001b92d,0x0001c92d},
+   {0x00000000,0x00000000,0x00009292,0x000124db,
+    0x000126dc,0x0001b925,0x0001c96e,0x0001c92d},
+   {0x00000000,0x00000000,0x00009492,0x000124db,
+    0x000136e4,0x0001b925,0x0001c96e,0x0001c92d},
+   {0x00000000,0x00000000,0x00009492,0x000124db,
+    0x000136e4,0x0001b925,0x00024b76,0x00024b77},
+   {0x00000000,0x00000000,0x00009492,0x000126db,
+    0x000136e4,0x0001b925,0x00024b76,0x00025bbf},
+   {0x00000000,0x00000000,0x0000a492,0x000126db,
+    0x000136e4,0x0001c92d,0x00024b76,0x00025bbf},
+   {0x00000000,0x00000000,0x00012492,0x000136db,
+    0x0001b724,0x00024b6d,0x0002ddb6,0x0002efff},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  },
+  { /* version 8, passes 1 */
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009252,0x00009493,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x0000a493,0x0000a49b,0x0000a49b,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x0000a49b,0x000124db,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x000124db,0x000126dc,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x000124db,0x000126dc,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x000124db,0x000136e4,0x000124db},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000126dc,0x000136e4,0x000124db},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000126dc,0x000126dc,0x000136e4,0x000126dc},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000126dc,0x000136e4,0x000136e4,0x000126dc},
+   {0x00000000,0x00000000,0x0000924a,0x000124db,
+    0x000126dc,0x000136e4,0x000136e4,0x000126dc},
+   {0x00000000,0x00000000,0x0000924a,0x000124db,
+    0x000126dc,0x000136e4,0x000136e4,0x000136e4},
+   {0x00000000,0x00000000,0x00009292,0x000124db,
+    0x000136e4,0x0001b724,0x0001b725,0x000136e4},
+   {0x00000000,0x00000000,0x00009492,0x000126db,
+    0x000136e4,0x0001b925,0x0001b725,0x0001b724},
+   {0x00000000,0x00000000,0x00009492,0x000126db,
+    0x000136e4,0x0001b925,0x0001b725,0x0001b724},
+   {0x00000000,0x00000000,0x0000a492,0x000136db,
+    0x0001b724,0x0002496d,0x0001b92d,0x0001b925},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  }
+ },
+ { /* version 9 */
+  { /* version 9, passes 0 */
+   {0x00000000,0x00000000,0x00000049,0x00000049,
+    0x00000049,0x00000049,0x00000049,0x00000049},
+   {0x00000000,0x00000000,0x00000249,0x00000049,
+    0x00000249,0x00000249,0x0000024a,0x00000049},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x0000124a,0x00009252,0x00001252,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009252,0x00009292,0x00009493,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x0000924a,
+    0x00009292,0x00009493,0x00009493,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x00009492,0x0000a49b,0x0000a49b,0x00009292},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x000124db,0x000124db,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x000124db,0x000126dc,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x000124db,0x000126dc,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0001249b,0x000126dc,0x000126dc,0x000124db},
+   {0x00000000,0x00000000,0x00009252,0x00009493,
+    0x000124db,0x000136e4,0x000136e4,0x000126dc},
+   {0x00000000,0x00000000,0x00009252,0x0000a49b,
+    0x000124db,0x000136e4,0x000136e4,0x000126dc},
+   {0x00000000,0x00000000,0x00009292,0x0000a49b,
+    0x000126dc,0x000136e4,0x000136e4,0x000136e4},
+   {0x00000000,0x00000000,0x00009492,0x0000a49b,
+    0x000126dc,0x0001b724,0x0001b725,0x0001b724},
+   {0x00000000,0x00000000,0x0000a492,0x000124db,
+    0x000136e4,0x0001b925,0x0001b92d,0x0001b925},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  },
+  { /* version 9, passes 1 */
+   {0x00000000,0x00000000,0x00000249,0x00000049,
+    0x00000009,0x00000009,0x00000009,0x00000009},
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x00000049,0x00000049,0x00000009,0x00000009},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x0000124a,0x00000249,0x00000049,0x00000049},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x0000124a,0x0000124a,0x00000049,0x00000049},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009252,0x0000124a,0x0000024a,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x0000924a,
+    0x00009252,0x0000124a,0x0000024a,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x00009492,0x00009252,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x00009292,0x00009292,0x00001252},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x00009292,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x00009493,0x00009493,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x0000a49b,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x0000a49b,0x0000a49b,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000124db,0x0000a49b,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000136e4,0x000126dc,0x000124db,0x0000a49b},
+   {0x00000000,0x00000000,0x00009252,0x000124db,
+    0x0001b724,0x000136e4,0x000126dc,0x000124db},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  }
+ },
+ { /* version 10 */
+  { /* version 10, passes 0 */
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x00000249,0x00000249,0x0000024a,0x0000024a},
+   {0x00000000,0x00000000,0x00000249,0x00001249,
+    0x00009252,0x00009292,0x00009292,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009252,0x00009292,0x00009292,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x0000924a,
+    0x00009492,0x00009493,0x0000a49b,0x00009292},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x00009492,0x000124db,0x000124db,0x00009292},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x000124db,0x000124db,0x00009493},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x000124db,0x000126dc,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x000124db,0x000126dc,0x000124db},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0001249b,0x000126dc,0x000126dc,0x000124db},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000124db,0x000126dc,0x000136e4,0x000126dc},
+   {0x00000000,0x00000000,0x00009252,0x0000a49b,
+    0x000124db,0x000136e4,0x000136e4,0x000136e4},
+   {0x00000000,0x00000000,0x00009292,0x0000a49b,
+    0x000126dc,0x000136e4,0x000136e4,0x000136e4},
+   {0x00000000,0x00000000,0x00009492,0x0000a49b,
+    0x000126dc,0x0001b724,0x0001b92d,0x0001b724},
+   {0x00000000,0x00000000,0x00009492,0x000124db,
+    0x000126dc,0x0001b925,0x0001b92d,0x0001b925},
+   {0x00000000,0x00000000,0x0000a492,0x000126db,
+    0x000136e4,0x0002496d,0x0001c96e,0x0001c92d},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  },
+  { /* version 10, passes 1 */
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x00000049,0x00000049,0x00000049,0x00000049},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x0000124a,0x00000249,0x00000049,0x00000049},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x0000124a,0x00009252,0x0000024a,0x00000049},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009252,0x00009493,0x0000024a,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x00009252,
+    0x00009492,0x00009493,0x00001252,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x00009492,0x00009493,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x00009492,0x00009493,0x00009292,0x00001252},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x00009493,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x0000a49b,0x00009493,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x0000a49b,0x00009493,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x000124db,0x0000a49b,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x000124db,0x0000a49b,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x000124db,
+    0x000136e4,0x000126dc,0x000124db,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x000124db,
+    0x000136e4,0x000126dc,0x000124db,0x0000a49b},
+   {0x00000000,0x00000000,0x00009252,0x000126db,
+    0x0001b724,0x000136e4,0x000126dc,0x000124db},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  }
+ },
+ { /* version 11 */
+  { /* version 11, passes 0 */
+   {0x00000000,0x00000000,0x00000249,0x00000249,
+    0x00000249,0x00000249,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009252,0x00009292,0x00009292,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x0000924a,
+    0x00009492,0x0000a49b,0x0000a49b,0x00009292},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x0000a49b,0x000124db,0x00009493},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x000124db,0x000126dc,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x000126dc,0x000126dc,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000126dc,0x000136e4,0x000124db},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000126dc,0x000136e4,0x000136e4,0x000126dc},
+   {0x00000000,0x00000000,0x00009292,0x0000a49b,
+    0x000126dc,0x000136e4,0x000136e4,0x000126dc},
+   {0x00000000,0x00000000,0x00009292,0x0000a49b,
+    0x000126dc,0x0001b724,0x0001b725,0x000136e4},
+   {0x00000000,0x00000000,0x00009292,0x0000a49b,
+    0x000136e4,0x0001b724,0x0001b92d,0x0001b724},
+   {0x00000000,0x00000000,0x00009492,0x0000a49b,
+    0x000136e4,0x0001b724,0x0001b92d,0x0001b724},
+   {0x00000000,0x00000000,0x00009492,0x000124db,
+    0x000136e4,0x0001b925,0x0001c96e,0x0001b925},
+   {0x00000000,0x00000000,0x00009492,0x000124db,
+    0x0001b724,0x0001b925,0x0001c96e,0x0001c92d},
+   {0x00000000,0x00000000,0x0000a492,0x000126db,
+    0x0001c924,0x0002496d,0x00025bb6,0x00024b77},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  },
+  { /* version 11, passes 1 */
+   {0x00000000,0x00000000,0x00001249,0x00000249,
+    0x00000249,0x00000249,0x0000024a,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x0000124a,0x0000124a,0x0000024a,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x0000924a,
+    0x00009252,0x00009252,0x0000024a,0x0000024a},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x00009492,0x0000a49b,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x0000a49b,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x0000a49b,0x00009292,0x00001252},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x0000a49b,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x0000a49b,0x00009493,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000124db,0x00009493,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000124db,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000124db,0x000124db,0x0000a49b,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x000124db,
+    0x000126dc,0x000126dc,0x0000a49b,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x000124db,
+    0x000136e4,0x000126dc,0x000124db,0x0000a49b},
+   {0x00000000,0x00000000,0x00009292,0x000124db,
+    0x000136e4,0x000126dc,0x000124db,0x0000a49b},
+   {0x00000000,0x00000000,0x00009492,0x000126db,
+    0x0001b724,0x000136e4,0x000126dc,0x000124db},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  }
+ },
+ { /* version 12 */
+  { /* version 12, passes 0 */
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009252,0x00009292,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x0000a493,0x0000a49b,0x0000a49b,0x00009493},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x000124db,0x000124db,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x000126dc,0x000126dc,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000126dc,0x000136e4,0x000124db},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000126dc,0x000136e4,0x000136e4,0x000126dc},
+   {0x00000000,0x00000000,0x00009292,0x0000a49b,
+    0x000126dc,0x0001b724,0x0001b725,0x000126dc},
+   {0x00000000,0x00000000,0x00009292,0x0000a49b,
+    0x000136e4,0x0001b724,0x0001b92d,0x000136e4},
+   {0x00000000,0x00000000,0x00009492,0x0000a49b,
+    0x000136e4,0x0001b724,0x0001b92d,0x0001b724},
+   {0x00000000,0x00000000,0x00009492,0x000124db,
+    0x000136e4,0x0001b724,0x0001b92d,0x0001b724},
+   {0x00000000,0x00000000,0x00009492,0x000124db,
+    0x000136e4,0x0001b925,0x0001b92d,0x0001b925},
+   {0x00000000,0x00000000,0x00009492,0x000124db,
+    0x0001b724,0x0001b925,0x0001c96e,0x0001c92d},
+   {0x00000000,0x00000000,0x0000a492,0x000124db,
+    0x0001b724,0x0001c92d,0x0001c96e,0x0001c92d},
+   {0x00000000,0x00000000,0x0000a492,0x000124db,
+    0x0001b724,0x0001c92d,0x00024b76,0x0002496e},
+   {0x00000000,0x00000000,0x00012492,0x000126db,
+    0x0001c924,0x00024b6d,0x0002ddb6,0x00025bbf},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  },
+  { /* version 12, passes 1 */
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x0000124a,0x0000124a,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x00001249,0x00009292,
+    0x00009492,0x00009252,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x00009292,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x0000a49b,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x0000a49b,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x0000a49b,0x00009493,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000124db,0x000124db,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000124db,0x000124db,0x0000a49b,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x000124db,
+    0x000126dc,0x000124db,0x0000a49b,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x000124db,
+    0x000126dc,0x000126dc,0x0000a49b,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x000124db,
+    0x000136e4,0x000126dc,0x000124db,0x0000a49b},
+   {0x00000000,0x00000000,0x00009492,0x000126db,
+    0x000136e4,0x000126dc,0x000124db,0x0000a49b},
+   {0x00000000,0x00000000,0x00009492,0x000126db,
+    0x0001b724,0x000136e4,0x000126dc,0x000124db},
+   {0x00000000,0x00000000,0x00009492,0x000126db,
+    0x0001b724,0x000136e4,0x000126dc,0x000124db},
+   {0x00000000,0x00000000,0x0000a492,0x000136db,
+    0x0001c924,0x0001b724,0x000136e4,0x000126dc},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  }
+ },
+ { /* version 13 */
+  { /* version 13, passes 0 */
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x00009252,0x00009292,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x000124db,0x000126dc,0x00009493},
+   {0x00000000,0x00000000,0x00001249,0x0000a49b,
+    0x0001249b,0x000126dc,0x000126dc,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000126dc,0x000136e4,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000126dc,0x000136e4,0x0001b725,0x000124db},
+   {0x00000000,0x00000000,0x00009292,0x0000a49b,
+    0x000136e4,0x0001b724,0x0001b725,0x000126dc},
+   {0x00000000,0x00000000,0x00009292,0x000124db,
+    0x000136e4,0x0001b724,0x0001b725,0x000126dc},
+   {0x00000000,0x00000000,0x00009492,0x000124db,
+    0x000136e4,0x0001b724,0x0001c96e,0x000136e4},
+   {0x00000000,0x00000000,0x00009492,0x000124db,
+    0x000136e4,0x0001c92d,0x0001c96e,0x0001b724},
+   {0x00000000,0x00000000,0x0000a492,0x000124db,
+    0x000136e4,0x0001c92d,0x0001c96e,0x0001b724},
+   {0x00000000,0x00000000,0x0000a492,0x000124db,
+    0x0001b724,0x0001c92d,0x0001c96e,0x0001b925},
+   {0x00000000,0x00000000,0x0000a492,0x000126db,
+    0x0001b724,0x0001c92d,0x00024b76,0x0001c92d},
+   {0x00000000,0x00000000,0x0000a492,0x000126db,
+    0x0001b924,0x0001c92d,0x00024b76,0x0001c92d},
+   {0x00000000,0x00000000,0x0000a492,0x000126db,
+    0x0001b924,0x0001c92d,0x00024b76,0x0002496e},
+   {0x00000000,0x00000000,0x00012492,0x000136db,
+    0x00024924,0x00024b6d,0x0002ddb6,0x00025bbf},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  },
+  { /* version 13, passes 1 */
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x0000124a,0x0000124a,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x00009492,0x00009292,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x0000a49b,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x0000a49b,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x0000a49b,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000126dc,0x0000a49b,0x00009493,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x000124db,
+    0x000126dc,0x000124db,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x000124db,
+    0x000136e4,0x000124db,0x0000a49b,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x000136db,
+    0x0001b724,0x000124db,0x0000a49b,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x000136db,
+    0x0001b724,0x000126dc,0x0000a49b,0x0000a49b},
+   {0x00000000,0x00000000,0x00009292,0x000136db,
+    0x0001b724,0x000126dc,0x000124db,0x0000a49b},
+   {0x00000000,0x00000000,0x00009492,0x000136db,
+    0x0001b724,0x000126dc,0x000124db,0x0000a49b},
+   {0x00000000,0x00000000,0x0000a492,0x000136db,
+    0x0001b724,0x000136e4,0x000126dc,0x000124db},
+   {0x00000000,0x00000000,0x0000a492,0x000136db,
+    0x0001b724,0x000136e4,0x000126dc,0x000124db},
+   {0x00000000,0x00000000,0x00012492,0x0001b6db,
+    0x0001c924,0x0001b724,0x000136e4,0x000126dc},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  }
+ },
+ { /* version 14 */
+  { /* version 14, passes 0 */
+   {0x00000000,0x00000000,0x00001249,0x0000924a,
+    0x00009292,0x00009493,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x00001249,0x0000a49b,
+    0x0000a493,0x000124db,0x000126dc,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000126dc,0x000136e4,0x0000a49b},
+   {0x00000000,0x00000000,0x0000924a,0x000124db,
+    0x000126dc,0x000136e4,0x0001b725,0x000124db},
+   {0x00000000,0x00000000,0x00009292,0x000124db,
+    0x000126dc,0x0001b724,0x0001b92d,0x000126dc},
+   {0x00000000,0x00000000,0x00009492,0x000124db,
+    0x000136e4,0x0001b724,0x0001b92d,0x000126dc},
+   {0x00000000,0x00000000,0x00009492,0x000124db,
+    0x000136e4,0x0001c92d,0x0001c96e,0x000136e4},
+   {0x00000000,0x00000000,0x00009492,0x000124db,
+    0x0001b724,0x0001c92d,0x0001c96e,0x0001b724},
+   {0x00000000,0x00000000,0x0000a492,0x000124db,
+    0x0001b724,0x0001c92d,0x00024b76,0x0001b925},
+   {0x00000000,0x00000000,0x0000a492,0x000126db,
+    0x0001b724,0x0001c92d,0x00024b76,0x0001c92d},
+   {0x00000000,0x00000000,0x0000a492,0x000126db,
+    0x0001b724,0x0001c92d,0x00024b76,0x0001c92d},
+   {0x00000000,0x00000000,0x0000a492,0x000136db,
+    0x0001b724,0x0001c92d,0x00024b76,0x0002496e},
+   {0x00000000,0x00000000,0x0000a492,0x000136db,
+    0x0001b924,0x0002496d,0x00024b76,0x00024b77},
+   {0x00000000,0x00000000,0x0000a492,0x000136db,
+    0x0001b924,0x00024b6d,0x0002ddb6,0x00025bbf},
+   {0x00000000,0x00000000,0x00012492,0x0001b6db,
+    0x00024924,0x0002db6d,0x00036db6,0x0002efff},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  },
+  { /* version 14, passes 1 */
+   {0x00000000,0x00000000,0x00001249,0x00001249,
+    0x0000124a,0x0000124a,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x0000924a,0x00009493,
+    0x0000a493,0x00009292,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x0000a49b,0x00001252,0x00001252},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000136e4,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000136e4,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x000124db,
+    0x000136e4,0x000136e4,0x00009493,0x00009292},
+   {0x00000000,0x00000000,0x00009492,0x000136db,
+    0x0001b724,0x000136e4,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x00009492,0x000136db,
+    0x0001b724,0x000136e4,0x0000a49b,0x00009493},
+   {0x00000000,0x00000000,0x00009492,0x000136db,
+    0x0001b724,0x000136e4,0x0000a49b,0x00009493},
+   {0x00000000,0x00000000,0x00009492,0x000136db,
+    0x0001b724,0x000136e4,0x0000a49b,0x0000a49b},
+   {0x00000000,0x00000000,0x0000a492,0x000136db,
+    0x0001b724,0x000136e4,0x000124db,0x0000a49b},
+   {0x00000000,0x00000000,0x0000a492,0x000136db,
+    0x0001b724,0x000136e4,0x000124db,0x0000a49b},
+   {0x00000000,0x00000000,0x0000a492,0x000136db,
+    0x0001b724,0x000136e4,0x000126dc,0x000124db},
+   {0x00000000,0x00000000,0x0000a492,0x000136db,
+    0x0001b724,0x000136e4,0x000126dc,0x000124db},
+   {0x00000000,0x00000000,0x00012492,0x0001b6db,
+    0x0001c924,0x0001b724,0x000136e4,0x000126dc},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  }
+ },
+ { /* version 15 */
+  { /* version 15, passes 0 */
+   {0x00000000,0x00000000,0x00001249,0x00009493,
+    0x0000a493,0x0000a49b,0x000124db,0x000124db},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0001249b,0x000126dc,0x000136e4,0x000124db},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x000126dc,0x0001b724,0x0001b725,0x000126dc},
+   {0x00000000,0x00000000,0x0000924a,0x000124db,
+    0x000136e4,0x0001b724,0x0001b92d,0x000126dc},
+   {0x00000000,0x00000000,0x00009492,0x000124db,
+    0x000136e4,0x0001b925,0x0001c96e,0x000136e4},
+   {0x00000000,0x00000000,0x00009492,0x000124db,
+    0x0001b724,0x0001c92d,0x0001c96e,0x0001b724},
+   {0x00000000,0x00000000,0x0000a492,0x000124db,
+    0x0001b724,0x0001c92d,0x0001c96e,0x0001b724},
+   {0x00000000,0x00000000,0x0000a492,0x000126db,
+    0x0001b724,0x0001c92d,0x0001c96e,0x0001b925},
+   {0x00000000,0x00000000,0x0000a492,0x000126db,
+    0x0001b924,0x0001c92d,0x00024b76,0x0001c92d},
+   {0x00000000,0x00000000,0x0000a492,0x000136db,
+    0x0001b924,0x0001c92d,0x00024b76,0x0001c92d},
+   {0x00000000,0x00000000,0x0000a492,0x000136db,
+    0x0001b924,0x0002496d,0x00024b76,0x0002496e},
+   {0x00000000,0x00000000,0x0000a492,0x000136db,
+    0x0001c924,0x0002496d,0x00025bb6,0x00024b77},
+   {0x00000000,0x00000000,0x0000a492,0x000136db,
+    0x0001c924,0x00024b6d,0x00025bb6,0x00024b77},
+   {0x00000000,0x00000000,0x00012492,0x000136db,
+    0x0001c924,0x00024b6d,0x0002ddb6,0x00025bbf},
+   {0x00000000,0x00000000,0x00012492,0x0001b6db,
+    0x00024924,0x0002db6d,0x00036db6,0x0002efff},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  },
+  { /* version 15, passes 1 */
+   {0x00000000,0x00000000,0x0000924a,0x0000924a,
+    0x00009292,0x00009292,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x0000a49b,
+    0x0000a493,0x000124db,0x00009292,0x00009292},
+   {0x00000000,0x00000000,0x0000924a,0x000124db,
+    0x000124db,0x0001b724,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x000124db,
+    0x000126dc,0x0001b724,0x00009493,0x00009493},
+   {0x00000000,0x00000000,0x0000924a,0x000124db,
+    0x000136e4,0x0001b724,0x0000a49b,0x0000a49b},
+   {0x00000000,0x00000000,0x00009292,0x000136db,
+    0x0001b724,0x0001b724,0x0000a49b,0x0000a49b},
+   {0x00000000,0x00000000,0x00009492,0x000136db,
+    0x0001c924,0x0001b724,0x000124db,0x000124db},
+   {0x00000000,0x00000000,0x00009492,0x000136db,
+    0x0001c924,0x0001b724,0x000124db,0x000124db},
+   {0x00000000,0x00000000,0x0000a492,0x000136db,
+    0x0001c924,0x0001b724,0x000126dc,0x000126dc},
+   {0x00000000,0x00000000,0x0000a492,0x000136db,
+    0x0001c924,0x0001b925,0x000126dc,0x000126dc},
+   {0x00000000,0x00000000,0x0000a492,0x000136db,
+    0x0001c924,0x0001b925,0x000136e4,0x000136e4},
+   {0x00000000,0x00000000,0x0000a492,0x000136db,
+    0x0001c924,0x0001b925,0x000136e4,0x000136e4},
+   {0x00000000,0x00000000,0x0000a492,0x000136db,
+    0x0001c924,0x0001b925,0x0001b725,0x0001b724},
+   {0x00000000,0x00000000,0x00012492,0x000136db,
+    0x0001c924,0x0001b925,0x0001b725,0x0001b724},
+   {0x00000000,0x00000000,0x00012492,0x0001b6db,
+    0x00024924,0x0002496d,0x0001b92d,0x0001b925},
+   {0x00000000,0x00000000,0x00000000,0x00000000,
+    0x00000000,0x00000000,0x00000000,0x00000000}
+  }
+ }
+};
diff -Nru a/drivers/usb/media/pwc/pwc-timon.h b/drivers/usb/media/pwc/pwc-timon.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/usb/media/pwc/pwc-timon.h	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,61 @@
+/* Linux driver for Philips webcam
+   (C) 2004      Luc Saillard (luc@saillard.org)
+
+   NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
+   driver and thus may have bugs that are not present in the original version.
+   Please send bug reports and support requests to <luc@saillard.org>.
+   The decompression routines have been implemented by reverse-engineering the
+   Nemosoft binary pwcx module. Caveat emptor.
+
+   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 tables contains entries for the 675/680/690 (Timon) camera, with
+   4 different qualities (no compression, low, medium, high).
+   It lists the bandwidth requirements for said mode by its alternate interface
+   number. An alternate of 0 means that the mode is unavailable.
+
+   There are 6 * 4 * 4 entries:
+     6 different resolutions subqcif, qsif, qcif, sif, cif, vga
+     6 framerates: 5, 10, 15, 20, 25, 30
+     4 compression modi: none, low, medium, high
+
+   When an uncompressed mode is not available, the next available compressed mode
+   will be chosen (unless the decompressor is absent). Sometimes there are only
+   1 or 2 compressed modes available; in that case entries are duplicated.
+*/
+
+#ifndef PWC_TIMON_H
+#define PWC_TIMON_H
+
+#include "pwc-ioctl.h"
+
+struct Timon_table_entry
+{
+	char alternate;			/* USB alternate interface */
+	unsigned short packetsize;	/* Normal packet size */
+	unsigned short bandlength;	/* Bandlength when decompressing */
+	unsigned char mode[13];		/* precomputed mode settings for cam */
+};
+
+const extern struct Timon_table_entry Timon_table[PSZ_MAX][6][4];
+const extern unsigned int TimonRomTable [16][2][16][8];
+
+
+#endif
+
+
diff -Nru a/drivers/usb/media/pwc/pwc-uncompress.c b/drivers/usb/media/pwc/pwc-uncompress.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/usb/media/pwc/pwc-uncompress.c	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,147 @@
+/* Linux driver for Philips webcam
+   Decompression frontend.
+   (C) 1999-2003 Nemosoft Unv.
+   (C) 2004      Luc Saillard (luc@saillard.org)
+
+   NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
+   driver and thus may have bugs that are not present in the original version.
+   Please send bug reports and support requests to <luc@saillard.org>.
+   The decompression routines have been implemented by reverse-engineering the
+   Nemosoft binary pwcx module. Caveat emptor.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include <asm/current.h>
+#include <asm/types.h>
+
+#include "pwc.h"
+#include "pwc-uncompress.h"
+#include "pwc-dec1.h"
+#include "pwc-dec23.h"
+
+int pwc_decompress(struct pwc_device *pdev)
+{
+	struct pwc_frame_buf *fbuf;
+	int n, line, col, stride;
+	void *yuv, *image;
+	u16 *src;
+	u16 *dsty, *dstu, *dstv;
+
+	if (pdev == NULL)
+		return -EFAULT;
+#if defined(__KERNEL__) && defined(PWC_MAGIC)
+	if (pdev->magic != PWC_MAGIC) {
+		Err("pwc_decompress(): magic failed.\n");
+		return -EFAULT;
+	}
+#endif
+
+	fbuf = pdev->read_frame;
+	if (fbuf == NULL)
+		return -EFAULT;
+	image = pdev->image_ptr[pdev->fill_image];
+	if (!image)
+		return -EFAULT;
+
+	yuv = fbuf->data + pdev->frame_header_size;  /* Skip header */
+
+	/* Raw format; that's easy... */
+	if (pdev->vpalette == VIDEO_PALETTE_RAW)
+	{
+		memcpy(image, yuv, pdev->frame_size);
+		return 0;
+	}
+
+	if (pdev->vbandlength == 0) {
+		/* Uncompressed mode. We copy the data into the output buffer,
+		   using the viewport size (which may be larger than the image
+		   size). Unfortunately we have to do a bit of byte stuffing
+		   to get the desired output format/size.
+		 */
+			/*
+			 * We do some byte shuffling here to go from the
+			 * native format to YUV420P.
+			 */
+			src = (u16 *)yuv;
+			n = pdev->view.x * pdev->view.y;
+
+			/* offset in Y plane */
+			stride = pdev->view.x * pdev->offset.y + pdev->offset.x;
+			dsty = (u16 *)(image + stride);
+
+			/* offsets in U/V planes */
+			stride = pdev->view.x * pdev->offset.y / 4 + pdev->offset.x / 2;
+			dstu = (u16 *)(image + n +         stride);
+			dstv = (u16 *)(image + n + n / 4 + stride);
+
+			/* increment after each line */
+			stride = (pdev->view.x - pdev->image.x) / 2; /* u16 is 2 bytes */
+
+			for (line = 0; line < pdev->image.y; line++) {
+				for (col = 0; col < pdev->image.x; col += 4) {
+					*dsty++ = *src++;
+					*dsty++ = *src++;
+					if (line & 1)
+						*dstv++ = *src++;
+					else
+						*dstu++ = *src++;
+				}
+				dsty += stride;
+				if (line & 1)
+					dstv += (stride >> 1);
+				else
+					dstu += (stride >> 1);
+			}
+	}
+	else {
+		/* Compressed; the decompressor routines will write the data
+		   in planar format immediately.
+		 */
+		int flags;
+                
+                flags = PWCX_FLAG_PLANAR;
+                if (pdev->vsize == PSZ_VGA && pdev->vframes == 5 && pdev->vsnapshot)
+		 {
+		   printk(KERN_ERR "pwc: Mode Bayer is not supported for now\n");
+		   flags |= PWCX_FLAG_BAYER;
+		   return -ENXIO; /* No such device or address: missing decompressor */
+		 }
+
+		switch (pdev->type)
+		 {
+		  case 675:
+		  case 680:
+		  case 690:
+		  case 720:
+		  case 730:
+		  case 740:
+		  case 750:
+		    pwc_dec23_decompress(&pdev->image, &pdev->view, &pdev->offset,
+				yuv, image,
+				flags,
+				pdev->decompress_data, pdev->vbandlength);
+		    break;
+		  case 645:
+		  case 646:
+		    /* TODO & FIXME */
+		    return -ENXIO; /* No such device or address: missing decompressor */
+		    break;
+		 }
+	}
+	return 0;
+}
+
+
diff -Nru a/drivers/usb/media/pwc/pwc-uncompress.h b/drivers/usb/media/pwc/pwc-uncompress.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/usb/media/pwc/pwc-uncompress.h	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,41 @@
+/* (C) 1999-2003 Nemosoft Unv.
+   (C) 2004      Luc Saillard (luc@saillard.org)
+
+   NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
+   driver and thus may have bugs that are not present in the original version.
+   Please send bug reports and support requests to <luc@saillard.org>.
+   The decompression routines have been implemented by reverse-engineering the
+   Nemosoft binary pwcx module. Caveat emptor.
+
+   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 file is the bridge between the kernel module and the plugin; it
+   describes the structures and datatypes used in both modules. Any
+   significant change should be reflected by increasing the 
+   pwc_decompressor_version major number.
+ */
+#ifndef PWC_UNCOMPRESS_H
+#define PWC_UNCOMPRESS_H
+
+#include <linux/config.h>
+
+#include "pwc-ioctl.h"
+
+/* from pwc-dec.h */
+#define PWCX_FLAG_PLANAR        0x0001
+/* */
+
+#endif
diff -Nru a/drivers/usb/media/pwc/pwc.h b/drivers/usb/media/pwc/pwc.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/usb/media/pwc/pwc.h	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,278 @@
+/* (C) 1999-2003 Nemosoft Unv.
+   (C) 2004      Luc Saillard (luc@saillard.org)
+
+   NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
+   driver and thus may have bugs that are not present in the original version.
+   Please send bug reports and support requests to <luc@saillard.org>.
+   The decompression routines have been implemented by reverse-engineering the
+   Nemosoft binary pwcx module. Caveat emptor.
+
+   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 PWC_H
+#define PWC_H
+
+#include <linux/version.h>
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/usb.h>
+#include <linux/spinlock.h>
+#include <linux/videodev.h>
+#include <linux/wait.h>
+#include <linux/smp_lock.h>
+#include <asm/semaphore.h>
+#include <asm/errno.h>
+
+#include "pwc-uncompress.h"
+#include "pwc-ioctl.h"
+
+/* Defines and structures for the Philips webcam */
+/* Used for checking memory corruption/pointer validation */
+#define PWC_MAGIC 0x89DC10ABUL
+#undef PWC_MAGIC
+
+/* Turn some debugging options on/off */
+#define PWC_DEBUG 0
+
+/* Trace certain actions in the driver */
+#define TRACE_MODULE	0x0001
+#define TRACE_PROBE	0x0002
+#define TRACE_OPEN	0x0004
+#define TRACE_READ	0x0008
+#define TRACE_MEMORY	0x0010
+#define TRACE_FLOW	0x0020
+#define TRACE_SIZE	0x0040
+#define TRACE_PWCX	0x0080
+#define TRACE_SEQUENCE	0x1000
+
+#define Trace(R, A...) if (pwc_trace & R) printk(KERN_DEBUG PWC_NAME " " A)
+#define Debug(A...) printk(KERN_DEBUG PWC_NAME " " A)
+#define Info(A...)  printk(KERN_INFO  PWC_NAME " " A)
+#define Err(A...)   printk(KERN_ERR   PWC_NAME " " A)
+
+
+/* Defines for ToUCam cameras */
+#define TOUCAM_HEADER_SIZE		8
+#define TOUCAM_TRAILER_SIZE		4
+
+#define FEATURE_MOTOR_PANTILT		0x0001
+
+/* Version block */
+#define PWC_MAJOR	9
+#define PWC_MINOR	0
+#define PWC_VERSION 	"9.0.2-unofficial"
+#define PWC_NAME 	"pwc"
+
+/* Turn certain features on/off */
+#define PWC_INT_PIPE 0
+
+/* Ignore errors in the first N frames, to allow for startup delays */
+#define FRAME_LOWMARK 5
+
+/* Size and number of buffers for the ISO pipe. */
+#define MAX_ISO_BUFS		2
+#define ISO_FRAMES_PER_DESC	10
+#define ISO_MAX_FRAME_SIZE	960
+#define ISO_BUFFER_SIZE 	(ISO_FRAMES_PER_DESC * ISO_MAX_FRAME_SIZE)
+
+/* Frame buffers: contains compressed or uncompressed video data. */
+#define MAX_FRAMES		5
+/* Maximum size after decompression is 640x480 YUV data, 1.5 * 640 * 480 */
+#define PWC_FRAME_SIZE 		(460800 + TOUCAM_HEADER_SIZE + TOUCAM_TRAILER_SIZE)
+
+/* Absolute maximum number of buffers available for mmap() */
+#define MAX_IMAGES 		10
+
+/* The following structures were based on cpia.h. Why reinvent the wheel? :-) */
+struct pwc_iso_buf
+{
+	void *data;
+	int  length;
+	int  read;
+	struct urb *urb;
+};
+
+/* intermediate buffers with raw data from the USB cam */
+struct pwc_frame_buf
+{
+   void *data;
+   volatile int filled;		/* number of bytes filled */
+   struct pwc_frame_buf *next;	/* list */
+#if PWC_DEBUG
+   int sequence;		/* Sequence number */
+#endif
+};
+
+struct pwc_device
+{
+   struct video_device *vdev;
+#ifdef PWC_MAGIC
+   int magic;
+#endif
+   /* Pointer to our usb_device */
+   struct usb_device *udev;
+   
+   int type;                    /* type of cam (645, 646, 675, 680, 690, 720, 730, 740, 750) */
+   int release;			/* release number */
+   int features;		/* feature bits */
+   char serial[30];		/* serial number (string) */
+   int error_status;		/* set when something goes wrong with the cam (unplugged, USB errors) */
+   int usb_init;		/* set when the cam has been initialized over USB */
+
+   /*** Video data ***/
+   int vopen;			/* flag */
+   int vendpoint;		/* video isoc endpoint */
+   int vcinterface;		/* video control interface */
+   int valternate;		/* alternate interface needed */
+   int vframes, vsize;		/* frames-per-second & size (see PSZ_*) */
+   int vpalette;		/* palette: 420P, RAW or RGBBAYER */
+   int vframe_count;		/* received frames */
+   int vframes_dumped; 		/* counter for dumped frames */
+   int vframes_error;		/* frames received in error */
+   int vmax_packet_size;	/* USB maxpacket size */
+   int vlast_packet_size;	/* for frame synchronisation */
+   int visoc_errors;		/* number of contiguous ISOC errors */
+   int vcompression;		/* desired compression factor */
+   int vbandlength;		/* compressed band length; 0 is uncompressed */
+   char vsnapshot;		/* snapshot mode */
+   char vsync;			/* used by isoc handler */
+   char vmirror;		/* for ToUCaM series */
+   
+   int cmd_len;
+   unsigned char cmd_buf[13];
+
+   /* The image acquisition requires 3 to 4 steps:
+      1. data is gathered in short packets from the USB controller
+      2. data is synchronized and packed into a frame buffer
+      3a. in case data is compressed, decompress it directly into image buffer
+      3b. in case data is uncompressed, copy into image buffer with viewport
+      4. data is transferred to the user process
+
+      Note that MAX_ISO_BUFS != MAX_FRAMES != MAX_IMAGES....
+      We have in effect a back-to-back-double-buffer system.
+    */
+   /* 1: isoc */
+   struct pwc_iso_buf sbuf[MAX_ISO_BUFS];
+   char iso_init;
+
+   /* 2: frame */
+   struct pwc_frame_buf *fbuf;	/* all frames */
+   struct pwc_frame_buf *empty_frames, *empty_frames_tail;	/* all empty frames */
+   struct pwc_frame_buf *full_frames, *full_frames_tail;	/* all filled frames */
+   struct pwc_frame_buf *fill_frame;	/* frame currently being filled */
+   struct pwc_frame_buf *read_frame;	/* frame currently read by user process */
+   int frame_header_size, frame_trailer_size;
+   int frame_size;
+   int frame_total_size; /* including header & trailer */
+   int drop_frames;
+#if PWC_DEBUG
+   int sequence;			/* Debugging aid */
+#endif
+
+   /* 3: decompression */
+   struct pwc_decompressor *decompressor;	/* function block with decompression routines */
+   void *decompress_data;		/* private data for decompression engine */
+
+   /* 4: image */
+   /* We have an 'image' and a 'view', where 'image' is the fixed-size image
+      as delivered by the camera, and 'view' is the size requested by the
+      program. The camera image is centered in this viewport, laced with
+      a gray or black border. view_min <= image <= view <= view_max;
+    */
+   int image_mask;			/* bitmask of supported sizes */
+   struct pwc_coord view_min, view_max;	/* minimum and maximum viewable sizes */
+   struct pwc_coord abs_max;            /* maximum supported size with compression */
+   struct pwc_coord image, view;	/* image and viewport size */
+   struct pwc_coord offset;		/* offset within the viewport */
+
+   void *image_data;			/* total buffer, which is subdivided into ... */
+   void *image_ptr[MAX_IMAGES];		/* ...several images... */
+   int fill_image;			/* ...which are rotated. */
+   int len_per_image;			/* length per image */
+   int image_read_pos;			/* In case we read data in pieces, keep track of were we are in the imagebuffer */
+   int image_used[MAX_IMAGES];		/* For MCAPTURE and SYNC */
+
+   struct semaphore modlock;		/* to prevent races in video_open(), etc */
+   spinlock_t ptrlock;			/* for manipulating the buffer pointers */
+
+   /*** motorized pan/tilt feature */
+   struct pwc_mpt_range angle_range;
+   int pan_angle;			/* in degrees * 100 */
+   int tilt_angle;			/* absolute angle; 0,0 is home position */
+
+   /*** Misc. data ***/
+   wait_queue_head_t frameq;		/* When waiting for a frame to finish... */
+#if PWC_INT_PIPE
+   void *usb_int_handler;		/* for the interrupt endpoint */
+#endif
+};
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Global variables */
+extern int pwc_trace;
+extern int pwc_preferred_compression;
+
+/** functions in pwc-if.c */
+int pwc_try_video_mode(struct pwc_device *pdev, int width, int height, int new_fps, int new_compression, int new_snapshot);
+
+/** Functions in pwc-misc.c */
+/* sizes in pixels */
+extern struct pwc_coord pwc_image_sizes[PSZ_MAX];
+
+int pwc_decode_size(struct pwc_device *pdev, int width, int height);
+void pwc_construct(struct pwc_device *pdev);
+
+/** Functions in pwc-ctrl.c */
+/* Request a certain video mode. Returns < 0 if not possible */
+extern int pwc_set_video_mode(struct pwc_device *pdev, int width, int height, int frames, int compression, int snapshot);
+/* Calculate the number of bytes per image (not frame) */
+extern void pwc_set_image_buffer_size(struct pwc_device *pdev);
+
+/* Various controls; should be obvious. Value 0..65535, or < 0 on error */
+extern int pwc_get_brightness(struct pwc_device *pdev);
+extern int pwc_set_brightness(struct pwc_device *pdev, int value);
+extern int pwc_get_contrast(struct pwc_device *pdev);
+extern int pwc_set_contrast(struct pwc_device *pdev, int value);
+extern int pwc_get_gamma(struct pwc_device *pdev);
+extern int pwc_set_gamma(struct pwc_device *pdev, int value);
+extern int pwc_get_saturation(struct pwc_device *pdev);
+extern int pwc_set_saturation(struct pwc_device *pdev, int value);
+extern int pwc_set_leds(struct pwc_device *pdev, int on_value, int off_value);
+extern int pwc_get_leds(struct pwc_device *pdev, int *on_value, int *off_value);
+extern int pwc_get_cmos_sensor(struct pwc_device *pdev, int *sensor);
+
+/* Power down or up the camera; not supported by all models */
+extern int pwc_camera_power(struct pwc_device *pdev, int power);
+
+/* Private ioctl()s; see pwc-ioctl.h */
+extern int pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg);
+
+
+/** pwc-uncompress.c */
+/* Expand frame to image, possibly including decompression. Uses read_frame and fill_image */
+extern int pwc_decompress(struct pwc_device *pdev);
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif
diff -Nru a/drivers/usb/media/se401.c b/drivers/usb/media/se401.c
--- a/drivers/usb/media/se401.c	2005-03-11 12:51:42 -08:00
+++ b/drivers/usb/media/se401.c	2005-03-11 12:51:42 -08:00
@@ -122,7 +122,7 @@
                 0,
                 cp,
                 size,
-                HZ
+                1000
         );
 }
 
@@ -142,7 +142,7 @@
 		selector,
                 NULL,
                 0,
-                HZ
+                1000
         );
 }
 
@@ -162,7 +162,7 @@
                 selector,
                 cp,
                 2,
-                HZ
+                1000
         );
 	return cp[0]+cp[1]*256;
 }
diff -Nru a/drivers/usb/media/sn9c102.h b/drivers/usb/media/sn9c102.h
--- a/drivers/usb/media/sn9c102.h	2005-03-11 12:51:46 -08:00
+++ b/drivers/usb/media/sn9c102.h	2005-03-11 12:51:46 -08:00
@@ -48,16 +48,16 @@
 #define SN9C102_ISO_PACKETS       7
 #define SN9C102_ALTERNATE_SETTING 8
 #define SN9C102_URB_TIMEOUT       msecs_to_jiffies(2 * SN9C102_ISO_PACKETS)
-#define SN9C102_CTRL_TIMEOUT      msecs_to_jiffies(300)
+#define SN9C102_CTRL_TIMEOUT      300
 
 /*****************************************************************************/
 
 #define SN9C102_MODULE_NAME     "V4L2 driver for SN9C10x PC Camera Controllers"
-#define SN9C102_MODULE_AUTHOR   "(C) 2004 Luca Risolia"
+#define SN9C102_MODULE_AUTHOR   "(C) 2004-2005 Luca Risolia"
 #define SN9C102_AUTHOR_EMAIL    "<luca.risolia@studio.unibo.it>"
 #define SN9C102_MODULE_LICENSE  "GPL"
-#define SN9C102_MODULE_VERSION  "1:1.22"
-#define SN9C102_MODULE_VERSION_CODE  KERNEL_VERSION(1, 0, 22)
+#define SN9C102_MODULE_VERSION  "1:1.24"
+#define SN9C102_MODULE_VERSION_CODE  KERNEL_VERSION(1, 0, 24)
 
 enum sn9c102_bridge {
 	BRIDGE_SN9C101 = 0x01,
diff -Nru a/drivers/usb/media/sn9c102_core.c b/drivers/usb/media/sn9c102_core.c
--- a/drivers/usb/media/sn9c102_core.c	2005-03-11 12:51:41 -08:00
+++ b/drivers/usb/media/sn9c102_core.c	2005-03-11 12:51:41 -08:00
@@ -164,8 +164,8 @@
 	struct v4l2_rect* r = &(cam->sensor->cropcap.bounds);
 	const size_t imagesize = cam->module_param.force_munmap ||
 	                         io == IO_READ ?
-	                         (p->width * p->height * p->priv)/8 :
-	                         (r->width * r->height * p->priv)/8;
+	                         (p->width * p->height * p->priv) / 8 :
+	                         (r->width * r->height * p->priv) / 8;
 	void* buff = NULL;
 	u32 i;
 
@@ -499,6 +499,7 @@
 {
 	struct sn9c102_device* cam = urb->context;
 	struct sn9c102_frame_t** f;
+	size_t imagesize;
 	unsigned long lock_flags;
 	u8 i;
 	int err = 0;
@@ -516,8 +517,13 @@
 		wake_up_interruptible(&cam->wait_stream);
 	}
 
-	if ((cam->state & DEV_DISCONNECTED)||(cam->state & DEV_MISCONFIGURED))
+	if (cam->state & DEV_DISCONNECTED)
+		return;
+
+	if (cam->state & DEV_MISCONFIGURED) {
+		wake_up_interruptible(&cam->wait_frame);
 		return;
+	}
 
 	if (cam->stream == STREAM_OFF || list_empty(&cam->inqueue))
 		goto resubmit_urb;
@@ -526,6 +532,10 @@
 		(*f) = list_entry(cam->inqueue.next, struct sn9c102_frame_t,
 		                  frame);
 
+	imagesize = (cam->sensor->pix_format.width *
+	             cam->sensor->pix_format.height *
+	             cam->sensor->pix_format.priv) / 8;
+
 	for (i = 0; i < urb->number_of_packets; i++) {
 		unsigned int img, len, status;
 		void *pos, *sof, *eof;
@@ -560,11 +570,10 @@
 				if (eof)
 					img = (eof > pos) ? eof - pos - 1 : 0;
 
-				if ((*f)->buf.bytesused+img>(*f)->buf.length) {
+				if ((*f)->buf.bytesused+img > imagesize) {
 					u32 b = (*f)->buf.bytesused + img -
-					        (*f)->buf.length;
-					img = (*f)->buf.length - 
-					      (*f)->buf.bytesused;
+					        imagesize;
+					img = imagesize - (*f)->buf.bytesused;
 					DBG(3, "Expected EOF not found: "
 					       "video frame cut")
 					if (eof)
@@ -580,7 +589,7 @@
 
 				(*f)->buf.bytesused += img;
 
-				if ((*f)->buf.bytesused == (*f)->buf.length ||
+				if ((*f)->buf.bytesused == imagesize ||
 				    (cam->sensor->pix_format.pixelformat ==
 				                V4L2_PIX_FMT_SN9C10X && eof)) {
 					u32 b = (*f)->buf.bytesused;
@@ -1558,7 +1567,8 @@
 		err = wait_event_interruptible
 		      ( cam->wait_frame, 
 		        (!list_empty(&cam->outqueue)) ||
-		        (cam->state & DEV_DISCONNECTED) );
+		        (cam->state & DEV_DISCONNECTED) ||
+			(cam->state & DEV_MISCONFIGURED) );
 		if (err) {
 			up(&cam->fileop_sem);
 			return err;
@@ -1567,6 +1577,10 @@
 			up(&cam->fileop_sem);
 			return -ENODEV;
 		}
+		if (cam->state & DEV_MISCONFIGURED) {
+			up(&cam->fileop_sem);
+			return -EIO;
+		}
 	}
 
 	f = list_entry(cam->outqueue.prev, struct sn9c102_frame_t, frame);
@@ -1615,7 +1629,8 @@
 	}
 
 	if (cam->io == IO_NONE) {
-		if (!sn9c102_request_buffers(cam, 2, IO_READ)) {
+		if (!sn9c102_request_buffers(cam, cam->nreadbuffers,
+		                             IO_READ)) {
 			DBG(1, "poll() failed, not enough memory")
 			goto error;
 		}
@@ -1729,7 +1744,7 @@
 }
 
 
-static int sn9c102_v4l2_ioctl(struct inode* inode, struct file* filp,
+static int sn9c102_ioctl_v4l2(struct inode* inode, struct file* filp,
                               unsigned int cmd, void __user * arg)
 {
 	struct sn9c102_device* cam = video_get_drvdata(video_devdata(filp));
@@ -1970,7 +1985,7 @@
 			return -EFAULT;
 		}
 
-		if (cam->module_param.force_munmap)
+		if (cam->module_param.force_munmap || cam->io == IO_READ)
 			sn9c102_release_buffers(cam);
 
 		err = sn9c102_set_crop(cam, rect);
@@ -1990,7 +2005,7 @@
 		s->pix_format.height = rect->height/scale;
 		memcpy(&(s->_rect), rect, sizeof(*rect));
 
-		if (cam->module_param.force_munmap &&
+		if ((cam->module_param.force_munmap || cam->io == IO_READ) &&
 		    nbuffers != sn9c102_request_buffers(cam, nbuffers,
 		                                        cam->io)) {
 			cam->state |= DEV_MISCONFIGURED;
@@ -2146,7 +2161,7 @@
 			return -EFAULT;
 		}
 
-		if (cam->module_param.force_munmap)
+		if (cam->module_param.force_munmap  || cam->io == IO_READ)
 			sn9c102_release_buffers(cam);
 
 		err += sn9c102_set_pix_format(cam, pix);
@@ -2168,7 +2183,7 @@
 		memcpy(pfmt, pix, sizeof(*pix));
 		memcpy(&(s->_rect), &rect, sizeof(rect));
 
-		if (cam->module_param.force_munmap &&
+		if ((cam->module_param.force_munmap  || cam->io == IO_READ) &&
 		    nbuffers != sn9c102_request_buffers(cam, nbuffers,
 		                                        cam->io)) {
 			cam->state |= DEV_MISCONFIGURED;
@@ -2346,11 +2361,14 @@
 			err = wait_event_interruptible
 			      ( cam->wait_frame, 
 			        (!list_empty(&cam->outqueue)) ||
-			        (cam->state & DEV_DISCONNECTED) );
+			        (cam->state & DEV_DISCONNECTED) ||
+			        (cam->state & DEV_MISCONFIGURED) );
 			if (err)
 				return err;
 			if (cam->state & DEV_DISCONNECTED)
 				return -ENODEV;
+			if (cam->state & DEV_MISCONFIGURED)
+				return -EIO;
 		}
 
 		spin_lock_irqsave(&cam->queue_lock, lock_flags);
@@ -2495,7 +2513,7 @@
 		return -EIO;
 	}
 
-	err = sn9c102_v4l2_ioctl(inode, filp, cmd, (void __user *)arg);
+	err = sn9c102_ioctl_v4l2(inode, filp, cmd, (void __user *)arg);
 
 	up(&cam->fileop_sem);
 
diff -Nru a/drivers/usb/media/ultracam.c b/drivers/usb/media/ultracam.c
--- a/drivers/usb/media/ultracam.c	2005-03-11 12:51:41 -08:00
+++ b/drivers/usb/media/ultracam.c	2005-03-11 12:51:41 -08:00
@@ -155,7 +155,7 @@
 			index,
 			cp,
 			sizeof(cp),
-			HZ);
+			1000);
 #if 1
 		info("USB => %02x%02x%02x%02x%02x%02x%02x%02x "
 		       "(req=$%02x val=$%04x ind=$%04x)",
@@ -172,7 +172,7 @@
 			index,
 			NULL,
 			0,
-			HZ);
+			1000);
 	}
 	if (i < 0) {
 		err("%s: ERROR=%d. Camera stopped; Reconnect or reload driver.",
diff -Nru a/drivers/usb/media/vicam.c b/drivers/usb/media/vicam.c
--- a/drivers/usb/media/vicam.c	2005-03-11 12:51:42 -08:00
+++ b/drivers/usb/media/vicam.c	2005-03-11 12:51:42 -08:00
@@ -441,7 +441,7 @@
 				 request,
 				 USB_DIR_OUT | USB_TYPE_VENDOR |
 				 USB_RECIP_DEVICE, value, index,
-				 cp, size, HZ);
+				 cp, size, 1000);
 
 	status = min(status, 0);
 
@@ -977,7 +977,7 @@
 	n = usb_bulk_msg(cam->udev,
 			 usb_rcvbulkpipe(cam->udev, cam->bulkEndpoint),
 			 cam->raw_image,
-			 512 * 242 + 128, &actual_length, HZ*10);
+			 512 * 242 + 128, &actual_length, 10000);
 
 	if (n < 0) {
 		printk(KERN_ERR "Problem during bulk read of frame data: %d\n",
diff -Nru a/drivers/usb/media/w9968cf.h b/drivers/usb/media/w9968cf.h
--- a/drivers/usb/media/w9968cf.h	2005-03-11 12:51:41 -08:00
+++ b/drivers/usb/media/w9968cf.h	2005-03-11 12:51:41 -08:00
@@ -65,7 +65,7 @@
 #define W9968CF_PACKET_SIZE      1023 /* according to wMaxPacketSizes[] */
 #define W9968CF_MIN_PACKET_SIZE  63 /* minimum value */
 #define W9968CF_ISO_PACKETS      5 /* n.of packets for isochronous transfers */
-#define W9968CF_USB_CTRL_TIMEOUT HZ /* timeout for usb control commands */
+#define W9968CF_USB_CTRL_TIMEOUT 1000 /* timeout (ms) for usb control commands */
 #define W9968CF_URBS             2 /* n. of scheduled URBs for ISO transfer */
 
 #define W9968CF_I2C_BUS_DELAY    4 /* delay in us for I2C bit r/w operations */
diff -Nru a/drivers/usb/misc/Kconfig b/drivers/usb/misc/Kconfig
--- a/drivers/usb/misc/Kconfig	2005-03-11 12:51:51 -08:00
+++ b/drivers/usb/misc/Kconfig	2005-03-11 12:51:51 -08:00
@@ -137,6 +137,8 @@
 
 	  See also <http://www.fs.tum.de/~echtler/idmouse/>.
 
+source "drivers/usb/misc/sisusbvga/Kconfig"
+
 config USB_TEST
 	tristate "USB testing driver (DEVELOPMENT)"
 	depends on USB && USB_DEVICEFS && EXPERIMENTAL
diff -Nru a/drivers/usb/misc/Makefile b/drivers/usb/misc/Makefile
--- a/drivers/usb/misc/Makefile	2005-03-11 12:51:46 -08:00
+++ b/drivers/usb/misc/Makefile	2005-03-11 12:51:46 -08:00
@@ -16,3 +16,5 @@
 obj-$(CONFIG_USB_RIO500)	+= rio500.o
 obj-$(CONFIG_USB_TEST)		+= usbtest.o
 obj-$(CONFIG_USB_USS720)	+= uss720.o
+
+obj-$(CONFIG_USB_SISUSBVGA)	+= sisusbvga/
\ No newline at end of file
diff -Nru a/drivers/usb/misc/auerswald.c b/drivers/usb/misc/auerswald.c
--- a/drivers/usb/misc/auerswald.c	2005-03-11 12:51:42 -08:00
+++ b/drivers/usb/misc/auerswald.c	2005-03-11 12:51:42 -08:00
@@ -29,6 +29,7 @@
 #include <linux/slab.h>
 #include <linux/module.h>
 #include <linux/init.h>
+#include <linux/wait.h>
 #undef DEBUG   		/* include debug macros until it's done	*/
 #include <linux/usb.h>
 
@@ -605,7 +606,6 @@
 /* Starts chained urb and waits for completion or timeout */
 static int auerchain_start_wait_urb (pauerchain_t acp, struct urb *urb, int timeout, int* actual_length)
 {
-	DECLARE_WAITQUEUE (wait, current);
 	auerchain_chs_t chs;
 	int status;
 
@@ -613,26 +613,13 @@
 	init_waitqueue_head (&chs.wqh);
 	chs.done = 0;
 
-	set_current_state (TASK_UNINTERRUPTIBLE);
-	add_wait_queue (&chs.wqh, &wait);
 	urb->context = &chs;
 	status = auerchain_submit_urb (acp, urb);
-	if (status) {
+	if (status)
 		/* something went wrong */
-		set_current_state (TASK_RUNNING);
-		remove_wait_queue (&chs.wqh, &wait);
 		return status;
-	}
-
-	while (timeout && !chs.done)
-	{
-		timeout = schedule_timeout (timeout);
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		rmb();
-	}
 
-	set_current_state (TASK_RUNNING);
-	remove_wait_queue (&chs.wqh, &wait);
+	timeout = wait_event_timeout(chs.wqh, chs.done, timeout);
 
 	if (!timeout && !chs.done) {
 		if (urb->status != -EINPROGRESS) {	/* No callback?!! */
@@ -2009,7 +1996,7 @@
                 AUDI_MBCTRANS,                      /* USB message index value */
                 pbuf,                               /* pointer to the receive buffer */
                 2,                                  /* length of the buffer */
-                HZ * 2);                            /* time to wait for the message to complete before timing out */
+                2000);                            /* time to wait for the message to complete before timing out */
         if (ret == 2) {
 	        cp->maxControlLength = le16_to_cpup(pbuf);
                 kfree(pbuf);
diff -Nru a/drivers/usb/misc/cytherm.c b/drivers/usb/misc/cytherm.c
--- a/drivers/usb/misc/cytherm.c	2005-03-11 12:51:52 -08:00
+++ b/drivers/usb/misc/cytherm.c	2005-03-11 12:51:52 -08:00
@@ -77,7 +77,7 @@
 			       USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_OTHER,
 			       value, 
 			       index, buf, size,
-			       HZ * USB_CTRL_GET_TIMEOUT);
+			       USB_CTRL_GET_TIMEOUT);
 }
 
 
diff -Nru a/drivers/usb/misc/idmouse.c b/drivers/usb/misc/idmouse.c
--- a/drivers/usb/misc/idmouse.c	2005-03-11 12:51:42 -08:00
+++ b/drivers/usb/misc/idmouse.c	2005-03-11 12:51:42 -08:00
@@ -124,28 +124,28 @@
 	   means init..
 	*/
 	result = usb_control_msg (dev->udev, usb_sndctrlpipe (dev->udev, 0),
-				0x21, 0x42, 0x0001, 0x0002, NULL, 0, HZ);
+				0x21, 0x42, 0x0001, 0x0002, NULL, 0, 1000);
 	if (result < 0)
 		return result;
 	result = usb_control_msg (dev->udev, usb_sndctrlpipe (dev->udev, 0),
-				0x20, 0x42, 0x0001, 0x0002, NULL, 0, HZ);
+				0x20, 0x42, 0x0001, 0x0002, NULL, 0, 1000);
 	if (result < 0)
 		return result;
 	result = usb_control_msg (dev->udev, usb_sndctrlpipe (dev->udev, 0),
-				0x22, 0x42, 0x0000, 0x0002, NULL, 0, HZ);
+				0x22, 0x42, 0x0000, 0x0002, NULL, 0, 1000);
 	if (result < 0)
 		return result;
 
 	result = usb_control_msg (dev->udev, usb_sndctrlpipe (dev->udev, 0),
-				0x21, 0x42, 0x0001, 0x0002, NULL, 0, HZ);
+				0x21, 0x42, 0x0001, 0x0002, NULL, 0, 1000);
 	if (result < 0)
 		return result;
 	result = usb_control_msg (dev->udev, usb_sndctrlpipe (dev->udev, 0),
-				0x20, 0x42, 0x0001, 0x0002, NULL, 0, HZ);
+				0x20, 0x42, 0x0001, 0x0002, NULL, 0, 1000);
 	if (result < 0)
 		return result;
 	result = usb_control_msg (dev->udev, usb_sndctrlpipe (dev->udev, 0),
-				0x20, 0x42, 0x0000, 0x0002, NULL, 0, HZ);
+				0x20, 0x42, 0x0000, 0x0002, NULL, 0, 1000);
 	if (result < 0)
 		return result;
 
@@ -154,7 +154,7 @@
 		result = usb_bulk_msg (dev->udev,
 				usb_rcvbulkpipe (dev->udev, dev->bulk_in_endpointAddr),
 				dev->bulk_in_buffer + bytes_read,
-				dev->bulk_in_size, &bulk_read, HZ * 5);
+				dev->bulk_in_size, &bulk_read, 5000);
 		if (result < 0)
 			return result;
 		if (signal_pending(current))
@@ -164,7 +164,7 @@
 
 	/* reset the device */
 	result = usb_control_msg (dev->udev, usb_sndctrlpipe (dev->udev, 0),
-				0x22, 0x42, 0x0000, 0x0002, NULL, 0, HZ);
+				0x22, 0x42, 0x0000, 0x0002, NULL, 0, 1000);
 	if (result < 0)
 		return result;
 
diff -Nru a/drivers/usb/misc/legousbtower.c b/drivers/usb/misc/legousbtower.c
--- a/drivers/usb/misc/legousbtower.c	2005-03-11 12:51:46 -08:00
+++ b/drivers/usb/misc/legousbtower.c	2005-03-11 12:51:46 -08:00
@@ -391,7 +391,7 @@
 				  0,
 				  &reset_reply,
 				  sizeof(reset_reply),
-				  HZ);
+				  1000);
 	if (result < 0) {
 		err("LEGO USB Tower reset control request failed");
 		retval = result;
@@ -972,7 +972,7 @@
 				  0,
 				  &get_version_reply,
 				  sizeof(get_version_reply),
-				  HZ);
+				  1000);
 	if (result < 0) {
 		err("LEGO USB Tower get version control request failed");
 		retval = result;
diff -Nru a/drivers/usb/misc/phidgetkit.c b/drivers/usb/misc/phidgetkit.c
--- a/drivers/usb/misc/phidgetkit.c	2005-03-11 12:51:51 -08:00
+++ b/drivers/usb/misc/phidgetkit.c	2005-03-11 12:51:51 -08:00
@@ -103,14 +103,15 @@
 		}
 	}
 
-	dev_dbg(&kit->udev->dev, "data: %02x %02x\n", buffer[0], buffer[1]);
+	dev_dbg(&kit->udev->dev, "sending data: %02x\n", buffer[0]);
 
 	retval = usb_control_msg(kit->udev,
 			 usb_sndctrlpipe(kit->udev, 0),
-			 0x09, 0x21, 0x0200, 0x0000, buffer, 4, 2 * HZ);
+			 0x09, 0x21, 0x0200, 0x0000, buffer, 4, 2000);
 
 	if (retval != 4)
-		dev_err(&kit->udev->dev, "retval = %d\n", retval);
+		dev_err(&kit->udev->dev, "usb_control_msg returned %d\n", 
+				retval);
 	kfree(buffer);
 
 	return retval < 0 ? retval : 0;
@@ -158,7 +159,7 @@
 
 		retval = usb_control_msg(kit->udev,
 				 usb_sndctrlpipe(kit->udev, 0),
-				 0x09, 0x21, 0x0200, 0x0000, buffer, 8, 2 * HZ);
+				 0x09, 0x21, 0x0200, 0x0000, buffer, 8, 2000);
 		if (retval < 0)
 			goto exit;
 	}
@@ -210,7 +211,7 @@
 	
 	retval = usb_control_msg(kit->udev,
 			 usb_sndctrlpipe(kit->udev, 0),
-			 0x09, 0x21, 0x0200, 0x0000, buffer, 8, 2 * HZ);
+			 0x09, 0x21, 0x0200, 0x0000, buffer, 8, 2000);
 	if (retval < 0)
 		goto exit;
 
@@ -328,7 +329,7 @@
 	struct usb_interface *intf = to_usb_interface(dev);		\
 	struct phidget_interfacekit *kit = usb_get_intfdata(intf);	\
 									\
-	return sprintf(buf, "%d\n", kit->outputs[value - 1 ]);		\
+	return sprintf(buf, "%d\n", kit->outputs[value - 1]);		\
 }									\
 static DEVICE_ATTR(output##value, S_IWUGO | S_IRUGO,			\
 		show_output##value, set_output##value);
@@ -440,11 +441,13 @@
 		return -EIO;
 	}
 
-	if (ifkit->outputs == 8) {
+	if (ifkit->outputs >= 4) {
 		device_create_file(&intf->dev, &dev_attr_output1);
 		device_create_file(&intf->dev, &dev_attr_output2);
 		device_create_file(&intf->dev, &dev_attr_output3);
 		device_create_file(&intf->dev, &dev_attr_output4);
+	}
+	if (ifkit->outputs == 8) {
 		device_create_file(&intf->dev, &dev_attr_output5);
 		device_create_file(&intf->dev, &dev_attr_output6);
 		device_create_file(&intf->dev, &dev_attr_output7);
@@ -483,7 +486,7 @@
 		device_create_file(&intf->dev, &dev_attr_lcd);
 
 	dev_info(&intf->dev, "USB PhidgetInterfaceKit %d/%d/%d attached\n",
-			ifkit->inputs, ifkit->outputs, ifkit->sensors);
+			ifkit->sensors, ifkit->inputs, ifkit->outputs);
 
 	return 0;
 }
@@ -497,15 +500,17 @@
 	if (!kit)
 		return;
 
-	if (kit->ifkit->outputs == MAX_INTERFACES) {
+	if (kit->ifkit->outputs >= 4) {
 		device_remove_file(&interface->dev, &dev_attr_output1);
 		device_remove_file(&interface->dev, &dev_attr_output2);
 		device_remove_file(&interface->dev, &dev_attr_output3);
 		device_remove_file(&interface->dev, &dev_attr_output4);
+	}
+	if (kit->ifkit->outputs == 8) {
 		device_remove_file(&interface->dev, &dev_attr_output5);
 		device_remove_file(&interface->dev, &dev_attr_output6);
 		device_remove_file(&interface->dev, &dev_attr_output7);
-		device_remove_file(&interface->dev, &dev_attr_output7);
+		device_remove_file(&interface->dev, &dev_attr_output8);
 	}
 
 	if (kit->ifkit->inputs >= 4) {
@@ -536,10 +541,10 @@
 		device_remove_file(&interface->dev, &dev_attr_sensor8);
 	}
 	if (kit->ifkit->has_lcd)
-		device_create_file(&interface->dev, &dev_attr_lcd);
+		device_remove_file(&interface->dev, &dev_attr_lcd);
 
 	dev_info(&interface->dev, "USB PhidgetInterfaceKit %d/%d/%d detached\n",
-		kit->ifkit->inputs, kit->ifkit->outputs, kit->ifkit->sensors);
+		kit->ifkit->sensors, kit->ifkit->inputs, kit->ifkit->outputs);
 
 	usb_kill_urb(kit->irq);
 	usb_free_urb(kit->irq);
diff -Nru a/drivers/usb/misc/phidgetservo.c b/drivers/usb/misc/phidgetservo.c
--- a/drivers/usb/misc/phidgetservo.c	2005-03-11 12:51:47 -08:00
+++ b/drivers/usb/misc/phidgetservo.c	2005-03-11 12:51:47 -08:00
@@ -148,7 +148,7 @@
 
 	retval = usb_control_msg(servo->udev,
 				 usb_sndctrlpipe(servo->udev, 0),
-				 0x09, 0x21, 0x0200, 0x0000, buffer, 6, 2 * HZ);
+				 0x09, 0x21, 0x0200, 0x0000, buffer, 6, 2000);
 
 	kfree(buffer);
 
@@ -199,7 +199,7 @@
 
 	retval = usb_control_msg(servo->udev,
 				 usb_sndctrlpipe(servo->udev, 0),
-				 0x09, 0x21, 0x0200, 0x0000, buffer, 2, 2 * HZ);
+				 0x09, 0x21, 0x0200, 0x0000, buffer, 2, 2000);
 
 	kfree(buffer);
 
diff -Nru a/drivers/usb/misc/rio500.c b/drivers/usb/misc/rio500.c
--- a/drivers/usb/misc/rio500.c	2005-03-11 12:51:47 -08:00
+++ b/drivers/usb/misc/rio500.c	2005-03-11 12:51:47 -08:00
@@ -166,7 +166,7 @@
 						 rio_cmd.value,
 						 rio_cmd.index, buffer,
 						 rio_cmd.length,
-						 rio_cmd.timeout);
+						 jiffies_to_msecs(rio_cmd.timeout));
 			if (result == -ETIMEDOUT)
 				retries--;
 			else if (result < 0) {
@@ -233,7 +233,7 @@
 						 rio_cmd.value,
 						 rio_cmd.index, buffer,
 						 rio_cmd.length,
-						 rio_cmd.timeout);
+						 jiffies_to_msecs(rio_cmd.timeout));
 			if (result == -ETIMEDOUT)
 				retries--;
 			else if (result < 0) {
@@ -309,7 +309,7 @@
 
 			result = usb_bulk_msg(rio->rio_dev,
 					 usb_sndbulkpipe(rio->rio_dev, 2),
-					 obuf, thistime, &partial, 5 * HZ);
+					 obuf, thistime, &partial, 5000);
 
 			dbg("write stats: result:%d thistime:%lu partial:%u",
 			     result, thistime, partial);
@@ -386,7 +386,7 @@
 		result = usb_bulk_msg(rio->rio_dev,
 				      usb_rcvbulkpipe(rio->rio_dev, 1),
 				      ibuf, this_read, &partial,
-				      (int) (HZ * 8));
+				      8000);
 
 		dbg(KERN_DEBUG "read stats: result:%d this_read:%u partial:%u",
 		       result, this_read, partial);
diff -Nru a/drivers/usb/misc/sisusbvga/Kconfig b/drivers/usb/misc/sisusbvga/Kconfig
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/usb/misc/sisusbvga/Kconfig	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,14 @@
+
+config USB_SISUSBVGA
+	tristate "USB 2.0 SVGA dongle support (Net2280/SiS315)"
+	depends on USB && USB_EHCI_HCD
+        ---help---
+	  Say Y here if you intend to attach a USB2VGA dongle based on a
+	  Net2280 and a SiS315 chip. 
+	  
+	  Note that this device requires a USB 2.0 host controller. It will not 
+	  work with USB 1.x controllers.
+
+	  To compile this driver as a module, choose M here: the module will be
+	  called sisusb.  If unsure, say N.
+
diff -Nru a/drivers/usb/misc/sisusbvga/Makefile b/drivers/usb/misc/sisusbvga/Makefile
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/usb/misc/sisusbvga/Makefile	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,6 @@
+#
+# Makefile for the sisusb driver (if driver is inside kernel tree).
+#
+
+obj-$(CONFIG_USB_SISUSBVGA) += sisusb.o
+
diff -Nru a/drivers/usb/misc/sisusbvga/sisusb.c b/drivers/usb/misc/sisusbvga/sisusb.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/usb/misc/sisusbvga/sisusb.c	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,3144 @@
+/*
+ * sisusb - usb kernel driver for SiS315(E) based USB2VGA dongles
+ *
+ * Copyright (C) 2005 by Thomas Winischhofer, Vienna, Austria
+ *
+ * If distributed as part of the Linux kernel, this code is licensed under the
+ * terms of the GPL v2.
+ *
+ * Otherwise, the following license terms apply:
+ *
+ * * Redistribution and use in source and binary forms, with or without
+ * * modification, are permitted provided that the following conditions
+ * * are met:
+ * * 1) Redistributions of source code must retain the above copyright
+ * *    notice, this list of conditions and the following disclaimer.
+ * * 2) Redistributions in binary form must reproduce the above copyright
+ * *    notice, this list of conditions and the following disclaimer in the
+ * *    documentation and/or other materials provided with the distribution.
+ * * 3) The name of the author may not be used to endorse or promote products
+ * *    derived from this software without specific psisusbr written permission.
+ * *
+ * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESSED OR
+ * * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Author: 	Thomas Winischhofer <thomas@winischhofer.net>
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/poll.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/kref.h>
+#include <linux/usb.h>
+#include <linux/smp_lock.h>
+
+#include "sisusb.h"
+
+#define SISUSB_DONTSYNC
+
+/* Forward declarations / clean-up routines */
+
+static struct usb_driver sisusb_driver;
+
+static DECLARE_MUTEX(disconnect_sem);
+
+static void
+sisusb_free_buffers(struct sisusb_usb_data *sisusb)
+{
+	int i;
+
+	for (i = 0; i < NUMOBUFS; i++) {
+		if (sisusb->obuf[i]) {
+			usb_buffer_free(sisusb->sisusb_dev, sisusb->obufsize,
+				sisusb->obuf[i], sisusb->transfer_dma_out[i]);
+			sisusb->obuf[i] = NULL;
+		}
+	}
+	if (sisusb->ibuf) {
+		usb_buffer_free(sisusb->sisusb_dev, sisusb->ibufsize,
+			sisusb->ibuf, sisusb->transfer_dma_in);
+		sisusb->ibuf = NULL;
+	}
+}
+
+static void
+sisusb_free_urbs(struct sisusb_usb_data *sisusb)
+{
+	int i;
+
+	for (i = 0; i < NUMOBUFS; i++) {
+		usb_free_urb(sisusb->sisurbout[i]);
+		sisusb->sisurbout[i] = NULL;
+	}
+	usb_free_urb(sisusb->sisurbin);
+	sisusb->sisurbin = NULL;
+}
+
+/* Level 0: USB transport layer */
+
+/* 1. out-bulks */
+
+/* out-urb management */
+
+/* Return 1 if all free, 0 otherwise */
+static int
+sisusb_all_free(struct sisusb_usb_data *sisusb)
+{
+	int i;
+
+	for (i = 0; i < sisusb->numobufs; i++) {
+
+		if (sisusb->urbstatus[i] & SU_URB_BUSY)
+			return 0;
+
+	}
+
+	return 1;
+}
+
+/* Kill all busy URBs */
+static void
+sisusb_kill_all_busy(struct sisusb_usb_data *sisusb)
+{
+	int i;
+
+	if (sisusb_all_free(sisusb))
+		return;
+
+	for (i = 0; i < sisusb->numobufs; i++) {
+
+		if (sisusb->urbstatus[i] & SU_URB_BUSY)
+			usb_kill_urb(sisusb->sisurbout[i]);
+
+	}
+}
+
+/* Return 1 if ok, 0 if error (not all complete within timeout) */
+static int
+sisusb_wait_all_out_complete(struct sisusb_usb_data *sisusb)
+{
+	int timeout = 5 * HZ, i = 1;
+
+	wait_event_timeout(sisusb->wait_q,
+				(i = sisusb_all_free(sisusb)),
+				 timeout);
+
+	return i;
+}
+
+static int
+sisusb_outurb_available(struct sisusb_usb_data *sisusb)
+{
+	int i;
+
+	for (i = 0; i < sisusb->numobufs; i++) {
+
+		if ((sisusb->urbstatus[i] & (SU_URB_BUSY|SU_URB_ALLOC)) == 0)
+			return i;
+
+	}
+
+	return -1;
+}
+
+static int
+sisusb_get_free_outbuf(struct sisusb_usb_data *sisusb)
+{
+	int i, timeout = 5 * HZ;
+
+	wait_event_timeout(sisusb->wait_q,
+				((i = sisusb_outurb_available(sisusb)) >= 0),
+				timeout);
+
+	return i;
+}
+
+static int
+sisusb_alloc_outbuf(struct sisusb_usb_data *sisusb)
+{
+	int i;
+
+	i = sisusb_outurb_available(sisusb);
+
+	if (i >= 0)
+		sisusb->urbstatus[i] |= SU_URB_ALLOC;
+
+	return i;
+}
+
+static void
+sisusb_free_outbuf(struct sisusb_usb_data *sisusb, int index)
+{
+	if ((index >= 0) && (index < sisusb->numobufs))
+		sisusb->urbstatus[index] &= ~SU_URB_ALLOC;
+}
+
+/* completion callback */
+
+static void
+sisusb_bulk_completeout(struct urb *urb, struct pt_regs *regs)
+{
+	struct sisusb_urb_context *context = urb->context;
+	struct sisusb_usb_data *sisusb;
+
+	if (!context)
+		return;
+
+	sisusb = context->sisusb;
+
+	if (!sisusb || !sisusb->sisusb_dev || !sisusb->present)
+		return;
+
+#ifndef SISUSB_DONTSYNC
+	if (context->actual_length)
+		*(context->actual_length) += urb->actual_length;
+#endif
+
+	sisusb->urbstatus[context->urbindex] &= ~SU_URB_BUSY;
+	wake_up(&sisusb->wait_q);
+}
+
+static int
+sisusb_bulkout_msg(struct sisusb_usb_data *sisusb, int index, unsigned int pipe, void *data,
+		int len, int *actual_length, int timeout, unsigned int tflags,
+		dma_addr_t transfer_dma)
+{
+	struct urb *urb = sisusb->sisurbout[index];
+	int retval, byteswritten = 0;
+
+	/* Set up URB */
+	urb->transfer_flags = 0;
+
+	usb_fill_bulk_urb(urb, sisusb->sisusb_dev, pipe, data, len,
+		sisusb_bulk_completeout, &sisusb->urbout_context[index]);
+
+	urb->transfer_flags |= (tflags | URB_ASYNC_UNLINK);
+	urb->actual_length = 0;
+
+	if ((urb->transfer_dma = transfer_dma))
+		urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+
+	/* Set up context */
+	sisusb->urbout_context[index].actual_length = (timeout) ?
+						NULL : actual_length;
+
+	/* Declare this urb/buffer in use */
+	sisusb->urbstatus[index] |= SU_URB_BUSY;
+
+	/* Submit URB */
+	retval = usb_submit_urb(urb, GFP_ATOMIC);
+
+	/* If OK, and if timeout > 0, wait for completion */
+	if ((retval == 0) && timeout) {
+		wait_event_timeout(sisusb->wait_q,
+				   (!(sisusb->urbstatus[index] & SU_URB_BUSY)),
+				   timeout);
+		if (sisusb->urbstatus[index] & SU_URB_BUSY) {
+			/* URB timed out... kill it and report error */
+			usb_kill_urb(urb);
+			retval = -ETIMEDOUT;
+		} else {
+			/* Otherwise, report urb status */
+			retval = urb->status;
+			byteswritten = urb->actual_length;
+		}
+	}
+
+	if (actual_length)
+		*actual_length = byteswritten;
+
+	return retval;
+}
+
+/* 2. in-bulks */
+
+/* completion callback */
+
+static void
+sisusb_bulk_completein(struct urb *urb, struct pt_regs *regs)
+{
+	struct sisusb_usb_data *sisusb = urb->context;
+
+	if (!sisusb || !sisusb->sisusb_dev || !sisusb->present)
+		return;
+
+	sisusb->completein = 1;
+	wake_up(&sisusb->wait_q);
+}
+
+static int
+sisusb_bulkin_msg(struct sisusb_usb_data *sisusb, unsigned int pipe, void *data, int len,
+		int *actual_length, int timeout, unsigned int tflags, dma_addr_t transfer_dma)
+{
+	struct urb *urb = sisusb->sisurbin;
+	int retval, readbytes = 0;
+
+	urb->transfer_flags = 0;
+
+	usb_fill_bulk_urb(urb, sisusb->sisusb_dev, pipe, data, len,
+			sisusb_bulk_completein, sisusb);
+
+	urb->transfer_flags |= (tflags | URB_ASYNC_UNLINK);
+	urb->actual_length = 0;
+
+	if ((urb->transfer_dma = transfer_dma))
+		urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+
+	sisusb->completein = 0;
+	retval = usb_submit_urb(urb, GFP_ATOMIC);
+	if (retval == 0) {
+		wait_event_timeout(sisusb->wait_q, sisusb->completein, timeout);
+		if (!sisusb->completein) {
+			/* URB timed out... kill it and report error */
+			usb_kill_urb(urb);
+			retval = -ETIMEDOUT;
+		} else {
+			/* URB completed within timout */
+			retval = urb->status;
+			readbytes = urb->actual_length;
+		}
+	}
+
+	if (actual_length)
+		*actual_length = readbytes;
+
+	return retval;
+}
+
+
+/* Level 1:  */
+
+/* Send a bulk message of variable size
+ *
+ * To copy the data from userspace, give pointer to "userbuffer",
+ * to copy from (non-DMA) kernel memory, give "kernbuffer". If
+ * both of these are NULL, it is assumed, that the transfer
+ * buffer "sisusb->obuf[index]" is set up with the data to send.
+ * Index is ignored if either kernbuffer or userbuffer is set.
+ * If async is nonzero, URBs will be sent without waiting for
+ * completion of the previous URB.
+ *
+ * (return 0 on success)
+ */
+
+static int sisusb_send_bulk_msg(struct sisusb_usb_data *sisusb, int ep, int len,
+		char *kernbuffer, const char __user *userbuffer, int index,
+		ssize_t *bytes_written, unsigned int tflags, int async)
+{
+	int result = 0, retry, count = len;
+	int passsize, thispass, transferred_len = 0;
+	int fromuser = (userbuffer != NULL) ? 1 : 0;
+	int fromkern = (kernbuffer != NULL) ? 1 : 0;
+	unsigned int pipe;
+	char *buffer;
+
+	(*bytes_written) = 0;
+
+	/* Sanity check */
+	if (!sisusb || !sisusb->present || !sisusb->sisusb_dev)
+		return -ENODEV;
+
+	/* If we copy data from kernel or userspace, force the
+	 * allocation of a buffer/urb. If we have the data in
+	 * the transfer buffer[index] already, reuse the buffer/URB
+	 * if the length is > buffer size. (So, transmitting
+	 * large data amounts directly from the transfer buffer
+	 * treats the buffer as a ring buffer. However, we need
+	 * to sync in this case.)
+	 */
+	if (fromuser || fromkern)
+		index = -1;
+	else if (len > sisusb->obufsize)
+		async = 0;
+
+	pipe = usb_sndbulkpipe(sisusb->sisusb_dev, ep);
+
+	do {
+		passsize = thispass = (sisusb->obufsize < count) ?
+						sisusb->obufsize : count;
+
+		if (index < 0)
+			index = sisusb_get_free_outbuf(sisusb);
+
+		if (index < 0)
+			return -EIO;
+
+		buffer = sisusb->obuf[index];
+
+		if (fromuser) {
+
+			if (copy_from_user(buffer, userbuffer, passsize))
+				return -EFAULT;
+
+			userbuffer += passsize;
+
+		} else if (fromkern) {
+
+			memcpy(buffer, kernbuffer, passsize);
+			kernbuffer += passsize;
+
+		}
+
+		retry = 5;
+		while (thispass) {
+
+			if (!sisusb->sisusb_dev)
+				return -ENODEV;
+
+			result = sisusb_bulkout_msg(sisusb,
+						index,
+						pipe,
+						buffer,
+						thispass,
+						&transferred_len,
+						async ? 0 : 5 * HZ,
+						tflags,
+						sisusb->transfer_dma_out[index]);
+
+			if (result == -ETIMEDOUT) {
+
+				/* Will not happen if async */
+				if (!retry--)
+					return -ETIME;
+
+				continue;
+
+			} else if ((result == 0) && !async && transferred_len) {
+
+				thispass -= transferred_len;
+				if (thispass) {
+					if (sisusb->transfer_dma_out) {
+						/* If DMA, copy remaining
+						 * to beginning of buffer
+						 */
+						memcpy(buffer,
+						       buffer + transferred_len,
+						       thispass);
+					} else {
+						/* If not DMA, simply increase
+						 * the pointer
+						 */
+						buffer += transferred_len;
+					}
+				}
+
+			} else
+				break;
+		};
+
+		if (result)
+			return result;
+
+		(*bytes_written) += passsize;
+		count            -= passsize;
+
+		/* Force new allocation in next iteration */
+		if (fromuser || fromkern)
+			index = -1;
+
+	} while (count > 0);
+
+	if (async) {
+#ifdef SISUSB_DONTSYNC
+		(*bytes_written) = len;
+		/* Some URBs/buffers might be busy */
+#else
+		sisusb_wait_all_out_complete(sisusb);
+		(*bytes_written) = transferred_len;
+		/* All URBs and all buffers are available */
+#endif
+	}
+
+	return ((*bytes_written) == len) ? 0 : -EIO;
+}
+
+/* Receive a bulk message of variable size
+ *
+ * To copy the data to userspace, give pointer to "userbuffer",
+ * to copy to kernel memory, give "kernbuffer". One of them
+ * MUST be set. (There is no technique for letting the caller
+ * read directly from the ibuf.)
+ *
+ */
+
+static int sisusb_recv_bulk_msg(struct sisusb_usb_data *sisusb, int ep, int len,
+		void *kernbuffer, char __user *userbuffer, ssize_t *bytes_read,
+		unsigned int tflags)
+{
+	int result = 0, retry, count = len;
+	int bufsize, thispass, transferred_len;
+	unsigned int pipe;
+	char *buffer;
+
+	(*bytes_read) = 0;
+
+	/* Sanity check */
+	if (!sisusb || !sisusb->present || !sisusb->sisusb_dev)
+		return -ENODEV;
+
+	pipe = usb_rcvbulkpipe(sisusb->sisusb_dev, ep);
+	buffer = sisusb->ibuf;
+	bufsize = sisusb->ibufsize;
+
+	retry = 5;
+
+#ifdef SISUSB_DONTSYNC
+	if (!(sisusb_wait_all_out_complete(sisusb)))
+		return -EIO;
+#endif
+
+	while (count > 0) {
+
+		if (!sisusb->sisusb_dev)
+			return -ENODEV;
+
+		thispass = (bufsize < count) ? bufsize : count;
+
+		result = sisusb_bulkin_msg(sisusb,
+					   pipe,
+					   buffer,
+					   thispass,
+					   &transferred_len,
+					   5 * HZ,
+					   tflags,
+					   sisusb->transfer_dma_in);
+
+		if (transferred_len)
+			thispass = transferred_len;
+
+		else if (result == -ETIMEDOUT) {
+
+			if (!retry--)
+				return -ETIME;
+
+			continue;
+
+		} else
+			return -EIO;
+
+
+		if (thispass) {
+
+			(*bytes_read) += thispass;
+			count         -= thispass;
+
+			if (userbuffer) {
+
+				if (copy_to_user(userbuffer, buffer, thispass))
+					return -EFAULT;
+
+				userbuffer += thispass;
+
+			} else {
+
+				memcpy(kernbuffer, buffer, thispass);
+				kernbuffer += thispass;
+
+			}
+
+		}
+
+	}
+
+	return ((*bytes_read) == len) ? 0 : -EIO;
+}
+
+static int sisusb_send_packet(struct sisusb_usb_data *sisusb, int len,
+						struct sisusb_packet *packet)
+{
+	int ret;
+	int bytes_transferred = 0;
+	__le32 tmp;
+
+	if (len == 6)
+		packet->data = 0;
+
+#ifdef SISUSB_DONTSYNC
+	if (!(sisusb_wait_all_out_complete(sisusb)))
+		return 1;
+#endif
+
+	/* Eventually correct endianness */
+	SISUSB_CORRECT_ENDIANNESS_PACKET(packet);
+
+	/* 1. send the packet */
+	ret = sisusb_send_bulk_msg(sisusb, SISUSB_EP_GFX_OUT, len,
+			(char *)packet, NULL, 0, &bytes_transferred, 0, 0);
+
+	if ((ret == 0) && (len == 6)) {
+
+		/* 2. if packet len == 6, it means we read, so wait for 32bit
+		 *    return value and write it to packet->data
+		 */
+		ret = sisusb_recv_bulk_msg(sisusb, SISUSB_EP_GFX_IN, 4,
+				(char *)&tmp, NULL, &bytes_transferred, 0);
+
+		packet->data = le32_to_cpu(tmp);
+	}
+
+	return ret;
+}
+
+static int sisusb_send_bridge_packet(struct sisusb_usb_data *sisusb, int len,
+					struct sisusb_packet *packet,
+					unsigned int tflags)
+{
+	int ret;
+	int bytes_transferred = 0;
+	__le32 tmp;
+
+	if (len == 6)
+		packet->data = 0;
+
+#ifdef SISUSB_DONTSYNC
+	if (!(sisusb_wait_all_out_complete(sisusb)))
+		return 1;
+#endif
+
+	/* Eventually correct endianness */
+	SISUSB_CORRECT_ENDIANNESS_PACKET(packet);
+
+	/* 1. send the packet */
+	ret = sisusb_send_bulk_msg(sisusb, SISUSB_EP_BRIDGE_OUT, len,
+			(char *)packet, NULL, 0, &bytes_transferred, tflags, 0);
+
+	if ((ret == 0) && (len == 6)) {
+
+		/* 2. if packet len == 6, it means we read, so wait for 32bit
+		 *    return value and write it to packet->data
+		 */
+		ret = sisusb_recv_bulk_msg(sisusb, SISUSB_EP_BRIDGE_IN, 4,
+				(char *)&tmp, NULL, &bytes_transferred, 0);
+
+		packet->data = le32_to_cpu(tmp);
+	}
+
+	return ret;
+}
+
+/* access video memory and mmio (return 0 on success) */
+
+/* Low level */
+
+/* The following routines assume being used to transfer byte, word,
+ * long etc.
+ * This means that they assume "data" in machine endianness format.
+ */
+
+static int sisusb_write_memio_byte(struct sisusb_usb_data *sisusb, int type,
+							u32 addr, u8 data)
+{
+	struct sisusb_packet packet;
+	int ret;
+
+	packet.header  = (1 << (addr & 3)) | (type << 6);
+	packet.address = addr & ~3;
+	packet.data    = data << ((addr & 3) << 3);
+	ret = sisusb_send_packet(sisusb, 10, &packet);
+	return ret;
+}
+
+static int sisusb_write_memio_word(struct sisusb_usb_data *sisusb, int type,
+							u32 addr, u16 data)
+{
+	struct sisusb_packet packet;
+	int ret = 0;
+
+	packet.address = addr & ~3;
+
+	switch (addr & 3) {
+		case 0:
+			packet.header = (type << 6) | 0x0003;
+			packet.data   = (u32)data;
+			ret = sisusb_send_packet(sisusb, 10, &packet);
+			break;
+		case 1:
+			packet.header = (type << 6) | 0x0006;
+			packet.data   = (u32)data << 8;
+			ret = sisusb_send_packet(sisusb, 10, &packet);
+			break;
+		case 2:
+			packet.header = (type << 6) | 0x000c;
+			packet.data   = (u32)data << 16;
+			ret = sisusb_send_packet(sisusb, 10, &packet);
+			break;
+		case 3:
+			packet.header = (type << 6) | 0x0008;
+			packet.data   = (u32)data << 24;
+			ret = sisusb_send_packet(sisusb, 10, &packet);
+			packet.header = (type << 6) | 0x0001;
+			packet.address = (addr & ~3) + 4;
+			packet.data   = (u32)data >> 8;
+			ret |= sisusb_send_packet(sisusb, 10, &packet);
+	}
+
+	return ret;
+}
+
+static int sisusb_write_memio_24bit(struct sisusb_usb_data *sisusb, int type,
+							u32 addr, u32 data)
+{
+	struct sisusb_packet packet;
+	int ret = 0;
+
+	packet.address = addr & ~3;
+
+	switch (addr & 3) {
+		case 0:
+			packet.header  = (type << 6) | 0x0007;
+			packet.data    = data & 0x00ffffff;
+			ret = sisusb_send_packet(sisusb, 10, &packet);
+			break;
+		case 1:
+			packet.header  = (type << 6) | 0x000e;
+			packet.data    = data << 8;
+			ret = sisusb_send_packet(sisusb, 10, &packet);
+			break;
+		case 2:
+			packet.header  = (type << 6) | 0x000c;
+			packet.data    = data << 16;
+			ret = sisusb_send_packet(sisusb, 10, &packet);
+			packet.header  = (type << 6) | 0x0001;
+			packet.address = (addr & ~3) + 4;
+			packet.data    = (data >> 16) & 0x00ff;
+			ret |= sisusb_send_packet(sisusb, 10, &packet);
+			break;
+		case 3:
+			packet.header  = (type << 6) | 0x0008;
+			packet.data    = data << 24;
+			ret = sisusb_send_packet(sisusb, 10, &packet);
+			packet.header  = (type << 6) | 0x0003;
+			packet.address = (addr & ~3) + 4;
+			packet.data    = (data >> 8) & 0xffff;
+			ret |= sisusb_send_packet(sisusb, 10, &packet);
+	}
+
+	return ret;
+}
+
+static int sisusb_write_memio_long(struct sisusb_usb_data *sisusb, int type,
+							u32 addr, u32 data)
+{
+	struct sisusb_packet packet;
+	int ret = 0;
+
+	packet.address = addr & ~3;
+
+	switch (addr & 3) {
+		case 0:
+			packet.header  = (type << 6) | 0x000f;
+			packet.data    = data;
+			ret = sisusb_send_packet(sisusb, 10, &packet);
+			break;
+		case 1:
+			packet.header  = (type << 6) | 0x000e;
+			packet.data    = data << 8;
+			ret = sisusb_send_packet(sisusb, 10, &packet);
+			packet.header  = (type << 6) | 0x0001;
+			packet.address = (addr & ~3) + 4;
+			packet.data    = data >> 24;
+			ret |= sisusb_send_packet(sisusb, 10, &packet);
+			break;
+		case 2:
+			packet.header  = (type << 6) | 0x000c;
+			packet.data    = data << 16;
+			ret = sisusb_send_packet(sisusb, 10, &packet);
+			packet.header  = (type << 6) | 0x0003;
+			packet.address = (addr & ~3) + 4;
+			packet.data    = data >> 16;
+			ret |= sisusb_send_packet(sisusb, 10, &packet);
+			break;
+		case 3:
+			packet.header  = (type << 6) | 0x0008;
+			packet.data    = data << 24;
+			ret = sisusb_send_packet(sisusb, 10, &packet);
+			packet.header  = (type << 6) | 0x0007;
+			packet.address = (addr & ~3) + 4;
+			packet.data    = data >> 8;
+			ret |= sisusb_send_packet(sisusb, 10, &packet);
+	}
+
+	return ret;
+}
+
+/* The xxx_bulk routines copy a buffer of variable size. They treat the
+ * buffer as chars, therefore lsb/msb has to be corrected if using the
+ * byte/word/long/etc routines for speed-up
+ *
+ * If data is from userland, set "userbuffer" (and clear "kernbuffer"),
+ * if data is in kernel space, set "kernbuffer" (and clear "userbuffer");
+ * if neither "kernbuffer" nor "userbuffer" are given, it is assumed
+ * that the data already is in the transfer buffer "sisusb->obuf[index]".
+ */
+
+static int sisusb_write_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr,
+				char *kernbuffer, int length,
+				const char __user *userbuffer, int index,
+				ssize_t *bytes_written)
+{
+	struct sisusb_packet packet;
+	int  ret = 0;
+	static int msgcount = 0;
+	u8   swap8, fromkern = kernbuffer ? 1 : 0;
+	u16  swap16;
+	u32  swap32, flag = (length >> 28) & 1;
+	char buf[4];
+
+	/* if neither kernbuffer not userbuffer are given, assume
+	 * data in obuf
+	 */
+	if (!fromkern && !userbuffer)
+		kernbuffer = sisusb->obuf[index];
+
+	(*bytes_written = 0);
+
+	length &= 0x00ffffff;
+
+	while (length) {
+
+	    switch (length) {
+
+		case 0:
+			return ret;
+
+		case 1:
+			if (userbuffer) {
+				if (get_user(swap8, (u8 __user *)userbuffer))
+					return -EFAULT;
+			} else
+				swap8 = kernbuffer[0];
+
+			ret = sisusb_write_memio_byte(sisusb,
+							SISUSB_TYPE_MEM,
+							addr, swap8);
+
+			if (!ret)
+				(*bytes_written)++;
+
+			return ret;
+
+		case 2:
+			if (userbuffer) {
+				if (get_user(swap16, (u16 __user *)userbuffer))
+					return -EFAULT;
+			} else
+				swap16 = (kernbuffer[0] << 8) | kernbuffer[1];
+
+			ret = sisusb_write_memio_word(sisusb,
+							SISUSB_TYPE_MEM,
+							addr,
+							swap16);
+
+			if (!ret)
+				(*bytes_written) += 2;
+
+			return ret;
+
+		case 3:
+			if (userbuffer) {
+				if (copy_from_user(&buf, userbuffer, 3))
+					return -EFAULT;
+
+				swap32 = (buf[0] << 16) |
+					 (buf[1] <<  8) |
+					 buf[2];
+			} else
+				swap32 = (kernbuffer[0] << 16) |
+					 (kernbuffer[1] <<  8) |
+					 kernbuffer[2];
+
+			ret = sisusb_write_memio_24bit(sisusb,
+							SISUSB_TYPE_MEM,
+							addr,
+							swap32);
+
+			if (!ret)
+				(*bytes_written) += 3;
+
+			return ret;
+
+		case 4:
+			if (userbuffer) {
+				if (get_user(swap32, (u32 __user *)userbuffer))
+					return -EFAULT;
+			} else
+				swap32 = (kernbuffer[0] << 24) |
+					 (kernbuffer[1] << 16) |
+					 (kernbuffer[2] <<  8) |
+					 kernbuffer[3];
+
+			ret = sisusb_write_memio_long(sisusb,
+							SISUSB_TYPE_MEM,
+							addr,
+							swap32);
+			if (!ret)
+				(*bytes_written) += 4;
+
+			return ret;
+
+		default:
+			if ((length & ~3) > 0x10000) {
+
+			   packet.header  = 0x001f;
+			   packet.address = 0x000001d4;
+			   packet.data    = addr;
+			   ret = sisusb_send_bridge_packet(sisusb, 10,
+								&packet, 0);
+			   packet.header  = 0x001f;
+			   packet.address = 0x000001d0;
+			   packet.data    = (length & ~3);
+			   ret |= sisusb_send_bridge_packet(sisusb, 10,
+								&packet, 0);
+			   packet.header  = 0x001f;
+			   packet.address = 0x000001c0;
+			   packet.data    = flag | 0x16;
+			   ret |= sisusb_send_bridge_packet(sisusb, 10,
+								&packet, 0);
+			   if (userbuffer) {
+				ret |= sisusb_send_bulk_msg(sisusb,
+							SISUSB_EP_GFX_LBULK_OUT,
+							(length & ~3),
+							NULL, userbuffer, 0,
+							bytes_written, 0, 1);
+				userbuffer += (*bytes_written);
+			   } else if (fromkern) {
+				ret |= sisusb_send_bulk_msg(sisusb,
+							SISUSB_EP_GFX_LBULK_OUT,
+							(length & ~3),
+							kernbuffer, NULL, 0,
+							bytes_written, 0, 1);
+				kernbuffer += (*bytes_written);
+			   } else {
+			ret |= sisusb_send_bulk_msg(sisusb,
+							SISUSB_EP_GFX_LBULK_OUT,
+							(length & ~3),
+							NULL, NULL, index,
+							bytes_written, 0, 1);
+				kernbuffer += ((*bytes_written) &
+						(sisusb->obufsize-1));
+			   }
+
+			} else {
+
+			   packet.header  = 0x001f;
+			   packet.address = 0x00000194;
+			   packet.data    = addr;
+			   ret = sisusb_send_bridge_packet(sisusb, 10,
+			   					&packet, 0);
+			   packet.header  = 0x001f;
+			   packet.address = 0x00000190;
+			   packet.data    = (length & ~3);
+			   ret |= sisusb_send_bridge_packet(sisusb, 10,
+			   					&packet, 0);
+			   if (sisusb->flagb0 != 0x16) {
+				packet.header  = 0x001f;
+				packet.address = 0x00000180;
+				packet.data    = flag | 0x16;
+				ret |= sisusb_send_bridge_packet(sisusb, 10,
+								&packet, 0);
+				sisusb->flagb0 = 0x16;
+			   }
+			   if (userbuffer) {
+				ret |= sisusb_send_bulk_msg(sisusb,
+							SISUSB_EP_GFX_BULK_OUT,
+							(length & ~3),
+							NULL, userbuffer, 0,
+							bytes_written, 0, 1);
+				userbuffer += (*bytes_written);
+			   } else if (fromkern) {
+				ret |= sisusb_send_bulk_msg(sisusb,
+							SISUSB_EP_GFX_BULK_OUT,
+							(length & ~3),
+							kernbuffer, NULL, 0,
+							bytes_written, 0, 1);
+				kernbuffer += (*bytes_written);
+			   } else {
+				ret |= sisusb_send_bulk_msg(sisusb,
+							SISUSB_EP_GFX_BULK_OUT,
+							(length & ~3),
+							NULL, NULL, index,
+							bytes_written, 0, 1);
+				kernbuffer += ((*bytes_written) &
+						(sisusb->obufsize-1));
+			   }
+			}
+			if (ret) {
+				msgcount++;
+				if (msgcount < 500)
+					printk(KERN_ERR
+						"sisusbvga[%d]: Wrote %d of "
+						"%d bytes, error %d\n",
+						sisusb->minor, *bytes_written,
+						length, ret);
+				else if (msgcount == 500)
+					printk(KERN_ERR
+						"sisusbvga[%d]: Too many errors"
+						", logging stopped\n",
+						sisusb->minor);
+			}
+			addr += (*bytes_written);
+			length -= (*bytes_written);
+	    }
+
+	    if (ret)
+	    	break;
+
+	}
+
+	return ret ? -EIO : 0;
+}
+
+static int sisusb_read_memio_byte(struct sisusb_usb_data *sisusb, int type,
+							u32 addr, u8 *data)
+{
+	struct sisusb_packet packet;
+	int ret;
+
+	CLEARPACKET(&packet);
+	packet.header  = (1 << (addr & 3)) | (type << 6);
+	packet.address = addr & ~3;
+	ret = sisusb_send_packet(sisusb, 6, &packet);
+	*data = (u8)(packet.data >> ((addr & 3) << 3));
+	return ret;
+}
+
+static int sisusb_read_memio_word(struct sisusb_usb_data *sisusb, int type,
+							u32 addr, u16 *data)
+{
+	struct sisusb_packet packet;
+	int ret = 0;
+
+	CLEARPACKET(&packet);
+
+	packet.address = addr & ~3;
+
+	switch (addr & 3) {
+		case 0:
+			packet.header = (type << 6) | 0x0003;
+			ret = sisusb_send_packet(sisusb, 6, &packet);
+			*data = (u16)(packet.data);
+			break;
+		case 1:
+			packet.header = (type << 6) | 0x0006;
+			ret = sisusb_send_packet(sisusb, 6, &packet);
+			*data = (u16)(packet.data >> 8);
+			break;
+		case 2:
+			packet.header = (type << 6) | 0x000c;
+			ret = sisusb_send_packet(sisusb, 6, &packet);
+			*data = (u16)(packet.data >> 16);
+			break;
+		case 3:
+			packet.header = (type << 6) | 0x0008;
+			ret = sisusb_send_packet(sisusb, 6, &packet);
+			*data = (u16)(packet.data >> 24);
+			packet.header = (type << 6) | 0x0001;
+			packet.address = (addr & ~3) + 4;
+			ret |= sisusb_send_packet(sisusb, 6, &packet);
+			*data |= (u16)(packet.data << 8);
+	}
+
+	return ret;
+}
+
+static int sisusb_read_memio_24bit(struct sisusb_usb_data *sisusb, int type,
+							u32 addr, u32 *data)
+{
+	struct sisusb_packet packet;
+	int ret = 0;
+
+	packet.address = addr & ~3;
+
+	switch (addr & 3) {
+		case 0:
+			packet.header  = (type << 6) | 0x0007;
+			ret = sisusb_send_packet(sisusb, 6, &packet);
+			*data = packet.data & 0x00ffffff;
+			break;
+		case 1:
+			packet.header  = (type << 6) | 0x000e;
+			ret = sisusb_send_packet(sisusb, 6, &packet);
+			*data = packet.data >> 8;
+			break;
+		case 2:
+			packet.header  = (type << 6) | 0x000c;
+			ret = sisusb_send_packet(sisusb, 6, &packet);
+			*data = packet.data >> 16;
+			packet.header  = (type << 6) | 0x0001;
+			packet.address = (addr & ~3) + 4;
+			ret |= sisusb_send_packet(sisusb, 6, &packet);
+			*data |= ((packet.data & 0xff) << 16);
+			break;
+		case 3:
+			packet.header  = (type << 6) | 0x0008;
+			ret = sisusb_send_packet(sisusb, 6, &packet);
+			*data = packet.data >> 24;
+			packet.header  = (type << 6) | 0x0003;
+			packet.address = (addr & ~3) + 4;
+			ret |= sisusb_send_packet(sisusb, 6, &packet);
+			*data |= ((packet.data & 0xffff) << 8);
+	}
+
+	return ret;
+}
+
+static int sisusb_read_memio_long(struct sisusb_usb_data *sisusb, int type,
+							u32 addr, u32 *data)
+{
+	struct sisusb_packet packet;
+	int ret = 0;
+
+	packet.address = addr & ~3;
+
+	switch (addr & 3) {
+		case 0:
+			packet.header  = (type << 6) | 0x000f;
+			ret = sisusb_send_packet(sisusb, 6, &packet);
+			*data = packet.data;
+			break;
+		case 1:
+			packet.header  = (type << 6) | 0x000e;
+			ret = sisusb_send_packet(sisusb, 6, &packet);
+			*data = packet.data >> 8;
+			packet.header  = (type << 6) | 0x0001;
+			packet.address = (addr & ~3) + 4;
+			ret |= sisusb_send_packet(sisusb, 6, &packet);
+			*data |= (packet.data << 24);
+			break;
+		case 2:
+			packet.header  = (type << 6) | 0x000c;
+			ret = sisusb_send_packet(sisusb, 6, &packet);
+			*data = packet.data >> 16;
+			packet.header  = (type << 6) | 0x0003;
+			packet.address = (addr & ~3) + 4;
+			ret |= sisusb_send_packet(sisusb, 6, &packet);
+			*data |= (packet.data << 16);
+			break;
+		case 3:
+			packet.header  = (type << 6) | 0x0008;
+			ret = sisusb_send_packet(sisusb, 6, &packet);
+			*data = packet.data >> 24;
+			packet.header  = (type << 6) | 0x0007;
+			packet.address = (addr & ~3) + 4;
+			ret |= sisusb_send_packet(sisusb, 6, &packet);
+			*data |= (packet.data << 8);
+	}
+
+	return ret;
+}
+
+static int sisusb_read_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr,
+				char *kernbuffer, int length,
+				char __user *userbuffer, ssize_t *bytes_read)
+{
+	int ret = 0;
+	char buf[4];
+	u16 swap16;
+	u32 swap32;
+
+	(*bytes_read = 0);
+
+	length &= 0x00ffffff;
+
+	while (length) {
+
+	    switch (length) {
+
+		case 0:
+			return ret;
+
+		case 1:
+
+			ret |= sisusb_read_memio_byte(sisusb, SISUSB_TYPE_MEM,
+								addr, &buf[0]);
+			if (!ret) {
+				(*bytes_read)++;
+				if (userbuffer) {
+					if (put_user(buf[0],
+						(u8 __user *)userbuffer)) {
+						return -EFAULT;
+					}
+				} else {
+					kernbuffer[0] = buf[0];
+				}
+			}
+			return ret;
+
+		case 2:
+			ret |= sisusb_read_memio_word(sisusb, SISUSB_TYPE_MEM,
+								addr, &swap16);
+			if (!ret) {
+				(*bytes_read) += 2;
+				if (userbuffer) {
+					if (put_user(swap16,
+						(u16 __user *)userbuffer))
+						return -EFAULT;
+				} else {
+					kernbuffer[0] = swap16 >> 8;
+					kernbuffer[1] = swap16 & 0xff;
+				}
+			}
+			return ret;
+
+		case 3:
+			ret |= sisusb_read_memio_24bit(sisusb, SISUSB_TYPE_MEM,
+								addr, &swap32);
+			if (!ret) {
+				(*bytes_read) += 3;
+				buf[0] = (swap32 >> 16) & 0xff;
+				buf[1] = (swap32 >> 8) & 0xff;
+				buf[2] = swap32 & 0xff;
+				if (userbuffer) {
+					if (copy_to_user(userbuffer, &buf[0], 3))
+						return -EFAULT;
+				} else {
+					kernbuffer[0] = buf[0];
+					kernbuffer[1] = buf[1];
+					kernbuffer[2] = buf[2];
+				}
+			}
+			return ret;
+
+		default:
+			ret |= sisusb_read_memio_long(sisusb, SISUSB_TYPE_MEM,
+								addr, &swap32);
+			if (!ret) {
+				(*bytes_read) += 4;
+				if (userbuffer) {
+					if (put_user(swap32,
+						(u32 __user *)userbuffer))
+						return -EFAULT;
+
+					userbuffer += 4;
+				} else {
+					kernbuffer[0] = (swap32 >> 24) & 0xff;
+					kernbuffer[1] = (swap32 >> 16) & 0xff;
+					kernbuffer[2] = (swap32 >> 8) & 0xff;
+					kernbuffer[3] = swap32 & 0xff;
+					kernbuffer += 4;
+				}
+				addr += 4;
+				length -= 4;
+			}
+#if 0		/* That does not work, as EP 2 is an OUT EP! */
+		default:
+			CLEARPACKET(&packet);
+			packet.header  = 0x001f;
+			packet.address = 0x000001a0;
+			packet.data    = 0x00000006;
+			ret |= sisusb_send_bridge_packet(sisusb, 10,
+								&packet, 0);
+			packet.header  = 0x001f;
+			packet.address = 0x000001b0;
+			packet.data    = (length & ~3) | 0x40000000;
+			ret |= sisusb_send_bridge_packet(sisusb, 10,
+								&packet, 0);
+			packet.header  = 0x001f;
+			packet.address = 0x000001b4;
+			packet.data    = addr;
+			ret |= sisusb_send_bridge_packet(sisusb, 10,
+								&packet, 0);
+			packet.header  = 0x001f;
+			packet.address = 0x000001a4;
+			packet.data    = 0x00000001;
+			ret |= sisusb_send_bridge_packet(sisusb, 10,
+								&packet, 0);
+			if (userbuffer) {
+				ret |= sisusb_recv_bulk_msg(sisusb,
+							SISUSB_EP_GFX_BULK_IN,
+							(length & ~3),
+							NULL, userbuffer,
+							bytes_read, 0);
+				if (!ret) userbuffer += (*bytes_read);
+			} else {
+				ret |= sisusb_recv_bulk_msg(sisusb,
+							SISUSB_EP_GFX_BULK_IN,
+							(length & ~3),
+							kernbuffer, NULL,
+							bytes_read, 0);
+				if (!ret) kernbuffer += (*bytes_read);
+			}
+			addr += (*bytes_read);
+			length -= (*bytes_read);
+#endif
+	    }
+
+	    if (ret)
+	    	break;
+	}
+
+	return ret;
+}
+
+/* High level: Gfx (indexed) register access */
+
+static int
+sisusb_setidxreg(struct sisusb_usb_data *sisusb, int port, u8 index, u8 data)
+{
+	int ret;
+	ret = sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port, index);
+	ret |= sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port + 1, data);
+	return ret;
+}
+
+static int
+sisusb_getidxreg(struct sisusb_usb_data *sisusb, int port, u8 index, u8 *data)
+{
+	int ret;
+	ret = sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port, index);
+	ret |= sisusb_read_memio_byte(sisusb, SISUSB_TYPE_IO, port + 1, data);
+	return ret;
+}
+
+static int
+sisusb_setidxregandor(struct sisusb_usb_data *sisusb, int port, u8 idx,
+							u8 myand, u8 myor)
+{
+	int ret;
+	u8 tmp;
+
+	ret = sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port, idx);
+	ret |= sisusb_read_memio_byte(sisusb, SISUSB_TYPE_IO, port + 1, &tmp);
+	tmp &= myand;
+	tmp |= myor;
+	ret |= sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port + 1, tmp);
+	return ret;
+}
+
+static int
+sisusb_setidxregmask(struct sisusb_usb_data *sisusb, int port, u8 idx,
+							u8 data, u8 mask)
+{
+	int ret;
+	u8 tmp;
+	ret = sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port, idx);
+	ret |= sisusb_read_memio_byte(sisusb, SISUSB_TYPE_IO, port + 1, &tmp);
+	tmp &= ~(mask);
+	tmp |= (data & mask);
+	ret |= sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port + 1, tmp);
+	return ret;
+}
+
+static int
+sisusb_setidxregor(struct sisusb_usb_data *sisusb, int port, u8 index, u8 myor)
+{
+	return(sisusb_setidxregandor(sisusb, port, index, 0xff, myor));
+}
+
+static int
+sisusb_setidxregand(struct sisusb_usb_data *sisusb, int port, u8 idx, u8 myand)
+{
+	return(sisusb_setidxregandor(sisusb, port, idx, myand, 0x00));
+}
+
+/* access pci config registers (reg numbers 0, 4, 8, etc) */
+
+static int
+sisusb_write_pci_config(struct sisusb_usb_data *sisusb, int regnum, u32 data)
+{
+	struct sisusb_packet packet;
+	int ret;
+
+	packet.header = 0x008f;
+	packet.address = regnum | 0x10000;
+	packet.data = data;
+	ret = sisusb_send_packet(sisusb, 10, &packet);
+	return ret;
+}
+
+static int
+sisusb_read_pci_config(struct sisusb_usb_data *sisusb, int regnum, u32 *data)
+{
+	struct sisusb_packet packet;
+	int ret;
+
+	packet.header = 0x008f;
+	packet.address = (u32)regnum | 0x10000;
+	ret = sisusb_send_packet(sisusb, 6, &packet);
+	*data = packet.data;
+	return ret;
+}
+
+/* Clear video RAM */
+
+static int
+sisusb_clear_vram(struct sisusb_usb_data *sisusb, u32 address, int length)
+{
+	int ret, i, j;
+
+	if (address < sisusb->vrambase)
+		return 1;
+
+	if (address >= sisusb->vrambase + sisusb->vramsize)
+		return 1;
+
+	if (address + length > sisusb->vrambase + sisusb->vramsize)
+		length = sisusb->vrambase + sisusb->vramsize - address;
+
+	if (length <= 0)
+		return 0;
+
+	/* allocate free buffer/urb and clear the buffer */
+	if ((i = sisusb_alloc_outbuf(sisusb)) < 0)
+		return -EBUSY;
+
+	memset(sisusb->obuf[i], 0, sisusb->obufsize);
+
+	/* We can write a length > buffer size here. The buffer
+	 * data will simply be re-used (like a ring-buffer).
+	 */
+	ret = sisusb_write_mem_bulk(sisusb, address, NULL, length, NULL, i, &j);
+
+	/* Free the buffer/urb */
+	sisusb_free_outbuf(sisusb, i);
+
+	return ret;
+}
+
+/* Initialize the graphics core (return 0 on success)
+ * This resets the graphics hardware and puts it into
+ * a defined mode (640x480@60Hz)
+ */
+
+#define GETREG(r,d)     sisusb_read_memio_byte(sisusb, SISUSB_TYPE_IO, r, d)
+#define SETREG(r,d)	sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, r, d)
+#define SETIREG(r,i,d)	sisusb_setidxreg(sisusb, r, i, d)
+#define GETIREG(r,i,d)  sisusb_getidxreg(sisusb, r, i, d)
+#define SETIREGOR(r,i,o)	sisusb_setidxregor(sisusb, r, i, o)
+#define SETIREGAND(r,i,a)	sisusb_setidxregand(sisusb, r, i, a)
+#define SETIREGANDOR(r,i,a,o)	sisusb_setidxregandor(sisusb, r, i, a, o)
+#define READL(a,d)	sisusb_read_memio_long(sisusb, SISUSB_TYPE_MEM, a, d)
+#define WRITEL(a,d) 	sisusb_write_memio_long(sisusb, SISUSB_TYPE_MEM, a, d)
+#define READB(a,d)	sisusb_read_memio_byte(sisusb, SISUSB_TYPE_MEM, a, d)
+#define WRITEB(a,d) 	sisusb_write_memio_byte(sisusb, SISUSB_TYPE_MEM, a, d)
+
+static int
+sisusb_triggersr16(struct sisusb_usb_data *sisusb, u8 ramtype)
+{
+	int ret;
+	u8 tmp8;
+
+	ret = GETIREG(SISSR, 0x16, &tmp8);
+	if (ramtype <= 1) {
+		tmp8 &= 0x3f;
+		ret |= SETIREG(SISSR, 0x16, tmp8);
+		tmp8 |= 0x80;
+		ret |= SETIREG(SISSR, 0x16, tmp8);
+	} else {
+		tmp8 |= 0xc0;
+		ret |= SETIREG(SISSR, 0x16, tmp8);
+		tmp8 &= 0x0f;
+		ret |= SETIREG(SISSR, 0x16, tmp8);
+		tmp8 |= 0x80;
+		ret |= SETIREG(SISSR, 0x16, tmp8);
+		tmp8 &= 0x0f;
+		ret |= SETIREG(SISSR, 0x16, tmp8);
+		tmp8 |= 0xd0;
+		ret |= SETIREG(SISSR, 0x16, tmp8);
+		tmp8 &= 0x0f;
+		ret |= SETIREG(SISSR, 0x16, tmp8);
+		tmp8 |= 0xa0;
+		ret |= SETIREG(SISSR, 0x16, tmp8);
+	}
+	return ret;
+}
+
+static int
+sisusb_getbuswidth(struct sisusb_usb_data *sisusb, int *bw, int *chab)
+{
+	int ret;
+	u8  ramtype, done = 0;
+	u32 t0, t1, t2, t3;
+	u32 ramptr = SISUSB_PCI_MEMBASE;
+
+	ret = GETIREG(SISSR, 0x3a, &ramtype);
+	ramtype &= 3;
+
+	ret |= SETIREG(SISSR, 0x13, 0x00);
+
+	if (ramtype <= 1) {
+		ret |= SETIREG(SISSR, 0x14, 0x12);
+		ret |= SETIREGAND(SISSR, 0x15, 0xef);
+	} else {
+		ret |= SETIREG(SISSR, 0x14, 0x02);
+	}
+
+	ret |= sisusb_triggersr16(sisusb, ramtype);
+	ret |= WRITEL(ramptr +  0, 0x01234567);
+	ret |= WRITEL(ramptr +  4, 0x456789ab);
+	ret |= WRITEL(ramptr +  8, 0x89abcdef);
+	ret |= WRITEL(ramptr + 12, 0xcdef0123);
+	ret |= WRITEL(ramptr + 16, 0x55555555);
+	ret |= WRITEL(ramptr + 20, 0x55555555);
+	ret |= WRITEL(ramptr + 24, 0xffffffff);
+	ret |= WRITEL(ramptr + 28, 0xffffffff);
+	ret |= READL(ramptr +  0, &t0);
+	ret |= READL(ramptr +  4, &t1);
+	ret |= READL(ramptr +  8, &t2);
+	ret |= READL(ramptr + 12, &t3);
+
+	if (ramtype <= 1) {
+
+		*chab = 0; *bw = 64;
+
+		if ((t3 != 0xcdef0123) || (t2 != 0x89abcdef)) {
+			if ((t1 == 0x456789ab) && (t0 == 0x01234567)) {
+				*chab = 0; *bw = 64;
+				ret |= SETIREGAND(SISSR, 0x14, 0xfd);
+			}
+		}
+		if ((t1 != 0x456789ab) || (t0 != 0x01234567)) {
+			*chab = 1; *bw = 64;
+			ret |= SETIREGANDOR(SISSR, 0x14, 0xfc,0x01);
+
+			ret |= sisusb_triggersr16(sisusb, ramtype);
+			ret |= WRITEL(ramptr +  0, 0x89abcdef);
+			ret |= WRITEL(ramptr +  4, 0xcdef0123);
+			ret |= WRITEL(ramptr +  8, 0x55555555);
+			ret |= WRITEL(ramptr + 12, 0x55555555);
+			ret |= WRITEL(ramptr + 16, 0xaaaaaaaa);
+			ret |= WRITEL(ramptr + 20, 0xaaaaaaaa);
+			ret |= READL(ramptr +  4, &t1);
+
+			if (t1 != 0xcdef0123) {
+				*bw = 32;
+				ret |= SETIREGOR(SISSR, 0x15, 0x10);
+			}
+		}
+
+	} else {
+
+		*chab = 0; *bw = 64;	/* default: cha, bw = 64 */
+
+		done = 0;
+
+		if (t1 == 0x456789ab) {
+			if (t0 == 0x01234567) {
+				*chab = 0; *bw = 64;
+				done = 1;
+			}
+		} else {
+			if (t0 == 0x01234567) {
+				*chab = 0; *bw = 32;
+				ret |= SETIREG(SISSR, 0x14, 0x00);
+				done = 1;
+			}
+		}
+
+		if (!done) {
+			ret |= SETIREG(SISSR, 0x14, 0x03);
+			ret |= sisusb_triggersr16(sisusb, ramtype);
+
+			ret |= WRITEL(ramptr +  0, 0x01234567);
+			ret |= WRITEL(ramptr +  4, 0x456789ab);
+			ret |= WRITEL(ramptr +  8, 0x89abcdef);
+			ret |= WRITEL(ramptr + 12, 0xcdef0123);
+			ret |= WRITEL(ramptr + 16, 0x55555555);
+			ret |= WRITEL(ramptr + 20, 0x55555555);
+			ret |= WRITEL(ramptr + 24, 0xffffffff);
+			ret |= WRITEL(ramptr + 28, 0xffffffff);
+			ret |= READL(ramptr +  0, &t0);
+			ret |= READL(ramptr +  4, &t1);
+
+			if (t1 == 0x456789ab) {
+				if (t0 == 0x01234567) {
+					*chab = 1; *bw = 64;
+					return ret;
+				} /* else error */
+			} else {
+				if (t0 == 0x01234567) {
+					*chab = 1; *bw = 32;
+					ret |= SETIREG(SISSR, 0x14, 0x01);
+				} /* else error */
+			}
+		}
+	}
+	return ret;
+}
+
+static int
+sisusb_verify_mclk(struct sisusb_usb_data *sisusb)
+{
+	int ret = 0;
+	u32 ramptr = SISUSB_PCI_MEMBASE;
+	u8 tmp1, tmp2, i, j;
+
+	ret |= WRITEB(ramptr, 0xaa);
+	ret |= WRITEB(ramptr + 16, 0x55);
+	ret |= READB(ramptr, &tmp1);
+	ret |= READB(ramptr + 16, &tmp2);
+	if ((tmp1 != 0xaa) || (tmp2 != 0x55)) {
+		for (i = 0, j = 16; i < 2; i++, j += 16) {
+			ret |= GETIREG(SISSR, 0x21, &tmp1);
+			ret |= SETIREGAND(SISSR, 0x21, (tmp1 & 0xfb));
+			ret |= SETIREGOR(SISSR, 0x3c, 0x01);  /* not on 330 */
+			ret |= SETIREGAND(SISSR, 0x3c, 0xfe); /* not on 330 */
+			ret |= SETIREG(SISSR, 0x21, tmp1);
+			ret |= WRITEB(ramptr + 16 + j, j);
+			ret |= READB(ramptr + 16 + j, &tmp1);
+			if (tmp1 == j) {
+				ret |= WRITEB(ramptr + j, j);
+				break;
+			}
+		}
+	}
+	return ret;
+}
+
+static int
+sisusb_set_rank(struct sisusb_usb_data *sisusb, int *iret, int index,
+			u8 rankno, u8 chab, const u8 dramtype[][5],
+			int bw)
+{
+	int ret = 0, ranksize;
+	u8 tmp;
+
+	*iret = 0;
+
+	if ((rankno == 2) && (dramtype[index][0] == 2))
+		return ret;
+
+	ranksize = dramtype[index][3] / 2 * bw / 32;
+
+	if ((ranksize * rankno) > 128)
+		return ret;
+
+	tmp = 0;
+	while ((ranksize >>= 1) > 0) tmp += 0x10;
+	tmp |= ((rankno - 1) << 2);
+	tmp |= ((bw / 64) & 0x02);
+	tmp |= (chab & 0x01);
+
+	ret = SETIREG(SISSR, 0x14, tmp);
+	ret |= sisusb_triggersr16(sisusb, 0); /* sic! */
+
+	*iret = 1;
+
+	return ret;
+}
+
+static int
+sisusb_check_rbc(struct sisusb_usb_data *sisusb, int *iret, u32 inc, int testn)
+{
+	int ret = 0, i;
+	u32 j, tmp;
+
+	*iret = 0;
+
+	for (i = 0, j = 0; i < testn; i++) {
+		ret |= WRITEL(sisusb->vrambase + j, j);
+		j += inc;
+	}
+
+	for (i = 0, j = 0; i < testn; i++) {
+		ret |= READL(sisusb->vrambase + j, &tmp);
+		if (tmp != j) return ret;
+		j += inc;
+	}
+
+	*iret = 1;
+	return ret;
+}
+
+static int
+sisusb_check_ranks(struct sisusb_usb_data *sisusb, int *iret, int rankno,
+					int idx, int bw, const u8 rtype[][5])
+{
+	int ret = 0, i, i2ret;
+	u32 inc;
+
+	*iret = 0;
+
+	for (i = rankno; i >= 1; i--) {
+		inc = 1 << (rtype[idx][2] +
+			    rtype[idx][1] +
+			    rtype[idx][0] +
+			    bw / 64 + i);
+		ret |= sisusb_check_rbc(sisusb, &i2ret, inc, 2);
+		if (!i2ret)
+			return ret;
+	}
+
+	inc = 1 << (rtype[idx][2] + bw / 64 + 2);
+	ret |= sisusb_check_rbc(sisusb, &i2ret, inc, 4);
+	if (!i2ret)
+		return ret;
+
+	inc = 1 << (10 + bw / 64);
+	ret |= sisusb_check_rbc(sisusb, &i2ret, inc, 2);
+	if (!i2ret)
+		return ret;
+
+	*iret = 1;
+	return ret;
+}
+
+static int
+sisusb_get_sdram_size(struct sisusb_usb_data *sisusb, int *iret, int bw,
+								int chab)
+{
+	int ret = 0, i2ret = 0, i, j;
+	static const u8 sdramtype[13][5] = {
+		{ 2, 12, 9, 64, 0x35 },
+		{ 1, 13, 9, 64, 0x44 },
+		{ 2, 12, 8, 32, 0x31 },
+		{ 2, 11, 9, 32, 0x25 },
+		{ 1, 12, 9, 32, 0x34 },
+		{ 1, 13, 8, 32, 0x40 },
+		{ 2, 11, 8, 16, 0x21 },
+		{ 1, 12, 8, 16, 0x30 },
+		{ 1, 11, 9, 16, 0x24 },
+		{ 1, 11, 8,  8, 0x20 },
+		{ 2,  9, 8,  4, 0x01 },
+		{ 1, 10, 8,  4, 0x10 },
+		{ 1,  9, 8,  2, 0x00 }
+	};
+
+	*iret = 1; /* error */
+
+	for (i = 0; i < 13; i++) {
+		ret |= SETIREGANDOR(SISSR, 0x13, 0x80, sdramtype[i][4]);
+		for (j = 2; j > 0; j--) {
+			ret |= sisusb_set_rank(sisusb, &i2ret, i, j,
+						chab, sdramtype, bw);
+			if (!i2ret)
+				continue;
+
+			ret |= sisusb_check_ranks(sisusb, &i2ret, j, i,
+						bw, sdramtype);
+			if (i2ret) {
+				*iret = 0;	/* ram size found */
+				return ret;
+			}
+		}
+	}
+
+	return ret;
+}
+
+static int
+sisusb_setup_screen(struct sisusb_usb_data *sisusb, int clrall, int drwfr)
+{
+	int ret = 0;
+	u32 address;
+	int i, length, modex, modey, bpp;
+
+	modex = 640; modey = 480; bpp = 2;
+
+	address = sisusb->vrambase;	/* Clear video ram */
+
+	if (clrall)
+		length = sisusb->vramsize;
+	else
+		length = modex * bpp * modey;
+
+	ret = sisusb_clear_vram(sisusb, address, length);
+
+	if (!ret && drwfr) {
+		for (i = 0; i < modex; i++) {
+			address = sisusb->vrambase + (i * bpp);
+			ret |= sisusb_write_memio_word(sisusb, SISUSB_TYPE_MEM,
+							address, 0xf100);
+			address += (modex * (modey-1) * bpp);
+			ret |= sisusb_write_memio_word(sisusb, SISUSB_TYPE_MEM,
+							address, 0xf100);
+		}
+		for (i = 0; i < modey; i++) {
+			address = sisusb->vrambase + ((i * modex) * bpp);
+			ret |= sisusb_write_memio_word(sisusb, SISUSB_TYPE_MEM,
+							address, 0xf100);
+			address += ((modex - 1) * bpp);
+			ret |= sisusb_write_memio_word(sisusb, SISUSB_TYPE_MEM,
+							address, 0xf100);
+		}
+	}
+
+	return ret;
+}
+
+static int
+sisusb_set_default_mode(struct sisusb_usb_data *sisusb, int touchengines)
+{
+	int ret = 0, i, j, modex, modey, bpp, du;
+	u8 sr31, cr63, tmp8;
+	static const char attrdata[] = {
+		0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
+		0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,
+		0x01,0x00,0x00,0x00
+	};
+	static const char crtcrdata[] = {
+		0x5f,0x4f,0x50,0x82,0x54,0x80,0x0b,0x3e,
+		0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,
+		0xea,0x8c,0xdf,0x28,0x40,0xe7,0x04,0xa3,
+		0xff
+	};
+	static const char grcdata[] = {
+		0x00,0x00,0x00,0x00,0x00,0x40,0x05,0x0f,
+		0xff
+	};
+	static const char crtcdata[] = {
+		0x5f,0x4f,0x4f,0x83,0x55,0x81,0x0b,0x3e,
+		0xe9,0x8b,0xdf,0xe8,0x0c,0x00,0x00,0x05,
+		0x00
+	};
+
+	modex = 640; modey = 480; bpp = 2;
+
+	GETIREG(SISSR, 0x31, &sr31);
+	GETIREG(SISCR, 0x63, &cr63);
+	SETIREGOR(SISSR, 0x01, 0x20);
+	SETIREG(SISCR, 0x63, cr63 & 0xbf);
+	SETIREGOR(SISCR, 0x17, 0x80);
+	SETIREGOR(SISSR, 0x1f, 0x04);
+	SETIREGAND(SISSR, 0x07, 0xfb);
+	SETIREG(SISSR, 0x00, 0x03);	/* seq */
+	SETIREG(SISSR, 0x01, 0x21);
+	SETIREG(SISSR, 0x02, 0x0f);
+	SETIREG(SISSR, 0x03, 0x00);
+	SETIREG(SISSR, 0x04, 0x0e);
+	SETREG(SISMISCW, 0x23);		/* misc */
+	for (i = 0; i <= 0x18; i++) {	/* crtc */
+		SETIREG(SISCR, i, crtcrdata[i]);
+	}
+	for (i = 0; i <= 0x13; i++) {	/* att */
+		GETREG(SISINPSTAT, &tmp8);
+		SETREG(SISAR, i);
+		SETREG(SISAR, attrdata[i]);
+	}
+	GETREG(SISINPSTAT, &tmp8);
+	SETREG(SISAR, 0x14);
+	SETREG(SISAR, 0x00);
+	GETREG(SISINPSTAT, &tmp8);
+	SETREG(SISAR, 0x20);
+	GETREG(SISINPSTAT, &tmp8);
+	for (i = 0; i <= 0x08; i++) {	/* grc */
+		SETIREG(SISGR, i, grcdata[i]);
+	}
+	SETIREGAND(SISGR, 0x05, 0xbf);
+	for (i = 0x0A; i <= 0x0E; i++) {	/* clr ext */
+		SETIREG(SISSR, i, 0x00);
+	}
+	SETIREGAND(SISSR, 0x37, 0xfe);
+	SETREG(SISMISCW, 0xef);		/* sync */
+	SETIREG(SISCR, 0x11, 0x00);	/* crtc */
+	for (j = 0x00, i = 0; i <= 7; i++, j++) {
+		SETIREG(SISCR, j, crtcdata[i]);
+	}
+	for (j = 0x10; i <= 10; i++, j++) {
+		SETIREG(SISCR, j, crtcdata[i]);
+	}
+	for (j = 0x15; i <= 12; i++, j++) {
+		SETIREG(SISCR, j, crtcdata[i]);
+	}
+	for (j = 0x0A; i <= 15; i++, j++) {
+		SETIREG(SISSR, j, crtcdata[i]);
+	}
+	SETIREG(SISSR, 0x0E, (crtcdata[16] & 0xE0));
+	SETIREGANDOR(SISCR, 0x09, 0x5f, ((crtcdata[16] & 0x01) << 5));
+	SETIREG(SISCR, 0x14, 0x4f);
+	du = (modex / 16) * (bpp * 2);	/* offset/pitch */
+	if (modex % 16) du += bpp;
+	SETIREGANDOR(SISSR, 0x0e, 0xf0, ((du >> 8) & 0x0f));
+	SETIREG(SISCR, 0x13, (du & 0xff));
+	du <<= 5;
+	tmp8 = du >> 8;
+	if (du & 0xff) tmp8++;
+	SETIREG(SISSR, 0x10, tmp8);
+	SETIREG(SISSR, 0x31, 0x00);	/* VCLK */
+	SETIREG(SISSR, 0x2b, 0x1b);
+	SETIREG(SISSR, 0x2c, 0xe1);
+	SETIREG(SISSR, 0x2d, 0x01);
+	SETIREGAND(SISSR, 0x3d, 0xfe);	/* FIFO */
+	SETIREG(SISSR, 0x08, 0xae);
+	SETIREGAND(SISSR, 0x09, 0xf0);
+	SETIREG(SISSR, 0x08, 0x34);
+	SETIREGOR(SISSR, 0x3d, 0x01);
+	SETIREGAND(SISSR, 0x1f, 0x3f);	/* mode regs */
+	SETIREGANDOR(SISSR, 0x06, 0xc0, 0x0a);
+	SETIREG(SISCR, 0x19, 0x00);
+	SETIREGAND(SISCR, 0x1a, 0xfc);
+	SETIREGAND(SISSR, 0x0f, 0xb7);
+	SETIREGAND(SISSR, 0x31, 0xfb);
+	SETIREGANDOR(SISSR, 0x21, 0x1f, 0xa0);
+	SETIREGAND(SISSR, 0x32, 0xf3);
+	SETIREGANDOR(SISSR, 0x07, 0xf8, 0x03);
+	SETIREG(SISCR, 0x52, 0x6c);
+
+	SETIREG(SISCR, 0x0d, 0x00);	/* adjust frame */
+	SETIREG(SISCR, 0x0c, 0x00);
+	SETIREG(SISSR, 0x0d, 0x00);
+	SETIREGAND(SISSR, 0x37, 0xfe);
+
+	SETIREG(SISCR, 0x32, 0x20);
+	SETIREGAND(SISSR, 0x01, 0xdf);	/* enable display */
+	SETIREG(SISCR, 0x63, (cr63 & 0xbf));
+	SETIREG(SISSR, 0x31, (sr31 & 0xfb));
+
+	if (touchengines) {
+		SETIREG(SISSR, 0x20, 0xa1);	/* enable engines */
+		SETIREGOR(SISSR, 0x1e, 0x5a);
+
+		SETIREG(SISSR, 0x26, 0x01);	/* disable cmdqueue */
+		SETIREG(SISSR, 0x27, 0x1f);
+		SETIREG(SISSR, 0x26, 0x00);
+	}
+
+	SETIREG(SISCR, 0x34, 0x44);  	/* we just set std mode #44 */
+
+	return ret;
+}
+
+static int
+sisusb_init_gfxcore(struct sisusb_usb_data *sisusb)
+{
+	int ret = 0, i, j, bw, chab, iret, retry = 3;
+	u8 tmp8, ramtype;
+	u32 tmp32;
+	static const char mclktable[] = {
+		0x3b, 0x22, 0x01, 143,
+		0x3b, 0x22, 0x01, 143,
+		0x3b, 0x22, 0x01, 143,
+		0x3b, 0x22, 0x01, 143
+	};
+	static const char eclktable[] = {
+		0x3b, 0x22, 0x01, 143,
+		0x3b, 0x22, 0x01, 143,
+		0x3b, 0x22, 0x01, 143,
+		0x3b, 0x22, 0x01, 143
+	};
+	static const char ramtypetable1[] = {
+		0x00, 0x04, 0x60, 0x60,
+		0x0f, 0x0f, 0x1f, 0x1f,
+		0xba, 0xba, 0xba, 0xba,
+		0xa9, 0xa9, 0xac, 0xac,
+		0xa0, 0xa0, 0xa0, 0xa8,
+		0x00, 0x00, 0x02, 0x02,
+		0x30, 0x30, 0x40, 0x40
+	};
+	static const char ramtypetable2[] = {
+		0x77, 0x77, 0x44, 0x44,
+		0x77, 0x77, 0x44, 0x44,
+		0x00, 0x00, 0x00, 0x00,
+		0x5b, 0x5b, 0xab, 0xab,
+		0x00, 0x00, 0xf0, 0xf8
+	};
+
+	while (retry--) {
+
+		/* Enable VGA */
+		ret = GETREG(SISVGAEN, &tmp8);
+		ret |= SETREG(SISVGAEN, (tmp8 | 0x01));
+
+		/* Enable GPU access to VRAM */
+		ret |= GETREG(SISMISCR, &tmp8);
+		ret |= SETREG(SISMISCW, (tmp8 | 0x01));
+
+		if (ret) continue;
+
+		/* Reset registers */
+		ret |= SETIREGAND(SISCR, 0x5b, 0xdf);
+		ret |= SETIREG(SISSR, 0x05, 0x86);
+		ret |= SETIREGOR(SISSR, 0x20, 0x01);
+
+		ret |= SETREG(SISMISCW, 0x67);
+
+		for (i = 0x06; i <= 0x1f; i++) {
+			ret |= SETIREG(SISSR, i, 0x00);
+		}
+		for (i = 0x21; i <= 0x27; i++) {
+			ret |= SETIREG(SISSR, i, 0x00);
+		}
+		for (i = 0x31; i <= 0x3d; i++) {
+			ret |= SETIREG(SISSR, i, 0x00);
+		}
+		for (i = 0x12; i <= 0x1b; i++) {
+			ret |= SETIREG(SISSR, i, 0x00);
+		}
+		for (i = 0x79; i <= 0x7c; i++) {
+			ret |= SETIREG(SISCR, i, 0x00);
+		}
+
+		if (ret) continue;
+
+		ret |= SETIREG(SISCR, 0x63, 0x80);
+
+		ret |= GETIREG(SISSR, 0x3a, &ramtype);
+		ramtype &= 0x03;
+
+		ret |= SETIREG(SISSR, 0x28, mclktable[ramtype * 4]);
+		ret |= SETIREG(SISSR, 0x29, mclktable[(ramtype * 4) + 1]);
+		ret |= SETIREG(SISSR, 0x2a, mclktable[(ramtype * 4) + 2]);
+
+		ret |= SETIREG(SISSR, 0x2e, eclktable[ramtype * 4]);
+		ret |= SETIREG(SISSR, 0x2f, eclktable[(ramtype * 4) + 1]);
+		ret |= SETIREG(SISSR, 0x30, eclktable[(ramtype * 4) + 2]);
+
+		ret |= SETIREG(SISSR, 0x07, 0x18);
+		ret |= SETIREG(SISSR, 0x11, 0x0f);
+
+		if (ret) continue;
+
+		for (i = 0x15, j = 0; i <= 0x1b; i++, j++) {
+			ret |= SETIREG(SISSR, i, ramtypetable1[(j*4) + ramtype]);
+		}
+		for (i = 0x40, j = 0; i <= 0x44; i++, j++) {
+			ret |= SETIREG(SISCR, i, ramtypetable2[(j*4) + ramtype]);
+		}
+
+		ret |= SETIREG(SISCR, 0x49, 0xaa);
+
+		ret |= SETIREG(SISSR, 0x1f, 0x00);
+		ret |= SETIREG(SISSR, 0x20, 0xa0);
+		ret |= SETIREG(SISSR, 0x23, 0xf6);
+		ret |= SETIREG(SISSR, 0x24, 0x0d);
+		ret |= SETIREG(SISSR, 0x25, 0x33);
+
+		ret |= SETIREG(SISSR, 0x11, 0x0f);
+
+		ret |= SETIREGOR(SISPART1, 0x2f, 0x01);
+
+		ret |= SETIREGAND(SISCAP, 0x3f, 0xef);
+
+		if (ret) continue;
+
+		ret |= SETIREG(SISPART1, 0x00, 0x00);
+
+		ret |= GETIREG(SISSR, 0x13, &tmp8);
+		tmp8 >>= 4;
+
+		ret |= SETIREG(SISPART1, 0x02, 0x00);
+		ret |= SETIREG(SISPART1, 0x2e, 0x08);
+
+		ret |= sisusb_read_pci_config(sisusb, 0x50, &tmp32);
+		tmp32 &= 0x00f00000;
+		tmp8 = (tmp32 == 0x100000) ? 0x33 : 0x03;
+		ret |= SETIREG(SISSR, 0x25, tmp8);
+		tmp8 = (tmp32 == 0x100000) ? 0xaa : 0x88;
+		ret |= SETIREG(SISCR, 0x49, tmp8);
+
+		ret |= SETIREG(SISSR, 0x27, 0x1f);
+		ret |= SETIREG(SISSR, 0x31, 0x00);
+		ret |= SETIREG(SISSR, 0x32, 0x11);
+		ret |= SETIREG(SISSR, 0x33, 0x00);
+
+		if (ret) continue;
+
+		ret |= SETIREG(SISCR, 0x83, 0x00);
+
+		ret |= sisusb_set_default_mode(sisusb, 0);
+
+		ret |= SETIREGAND(SISSR, 0x21, 0xdf);
+		ret |= SETIREGOR(SISSR, 0x01, 0x20);
+		ret |= SETIREGOR(SISSR, 0x16, 0x0f);
+
+		ret |= sisusb_triggersr16(sisusb, ramtype);
+
+		/* Disable refresh */
+		ret |= SETIREGAND(SISSR, 0x17, 0xf8);
+		ret |= SETIREGOR(SISSR, 0x19, 0x03);
+
+		ret |= sisusb_getbuswidth(sisusb, &bw, &chab);
+		ret |= sisusb_verify_mclk(sisusb);
+
+		if (ramtype <= 1) {
+			ret |= sisusb_get_sdram_size(sisusb, &iret, bw, chab);
+			if (iret) {
+				printk(KERN_ERR "sisusbvga[%d]: RAM size "
+					"detection failed, "
+					"assuming 8MB video RAM\n",
+					sisusb->minor);
+				ret |= SETIREG(SISSR,0x14,0x31);
+				/* TODO */
+			}
+		} else {
+			printk(KERN_ERR "sisusbvga[%d]: DDR RAM device found, "
+					"assuming 8MB video RAM\n",
+					sisusb->minor);
+			ret |= SETIREG(SISSR,0x14,0x31);
+			/* *** TODO *** */
+		}
+
+		/* Enable refresh */
+		ret |= SETIREG(SISSR, 0x16, ramtypetable1[4 + ramtype]);
+		ret |= SETIREG(SISSR, 0x17, ramtypetable1[8 + ramtype]);
+		ret |= SETIREG(SISSR, 0x19, ramtypetable1[16 + ramtype]);
+
+		ret |= SETIREGOR(SISSR, 0x21, 0x20);
+
+		ret |= SETIREG(SISSR, 0x22, 0xfb);
+		ret |= SETIREG(SISSR, 0x21, 0xa5);
+
+		if (ret == 0)
+			break;
+	}
+
+	return ret;
+}
+
+#undef SETREG
+#undef GETREG
+#undef SETIREG
+#undef GETIREG
+#undef SETIREGOR
+#undef SETIREGAND
+#undef SETIREGANDOR
+#undef READL
+#undef WRITEL
+
+static void
+sisusb_get_ramconfig(struct sisusb_usb_data *sisusb)
+{
+	u8 tmp8, tmp82, ramtype;
+	int bw = 0;
+	char *ramtypetext1 = NULL;
+	const char *ramtypetext2[] = {	"SDR SDRAM", "SDR SGRAM",
+					"DDR SDRAM", "DDR SGRAM" };
+	static const int busSDR[4]  = {64, 64, 128, 128};
+	static const int busDDR[4]  = {32, 32,  64,  64};
+	static const int busDDRA[4] = {64+32, 64+32 , (64+32)*2, (64+32)*2};
+
+	sisusb_getidxreg(sisusb, SISSR, 0x14, &tmp8);
+	sisusb_getidxreg(sisusb, SISSR, 0x15, &tmp82);
+	sisusb_getidxreg(sisusb, SISSR, 0x3a, &ramtype);
+	sisusb->vramsize = (1 << ((tmp8 & 0xf0) >> 4)) * 1024 * 1024;
+	ramtype &= 0x03;
+	switch ((tmp8 >> 2) & 0x03) {
+	case 0: ramtypetext1 = "1 ch/1 r";
+		if (tmp82 & 0x10) {
+			bw = 32;
+		} else {
+			bw = busSDR[(tmp8 & 0x03)];
+		}
+		break;
+	case 1: ramtypetext1 = "1 ch/2 r";
+		sisusb->vramsize <<= 1;
+		bw = busSDR[(tmp8 & 0x03)];
+		break;
+	case 2: ramtypetext1 = "asymmeric";
+		sisusb->vramsize += sisusb->vramsize/2;
+		bw = busDDRA[(tmp8 & 0x03)];
+		break;
+	case 3: ramtypetext1 = "2 channel";
+		sisusb->vramsize <<= 1;
+		bw = busDDR[(tmp8 & 0x03)];
+		break;
+	}
+
+	printk(KERN_INFO "sisusbvga[%d]: %dMB %s %s, bus width %d\n",
+			sisusb->minor, (sisusb->vramsize >> 20), ramtypetext1,
+			ramtypetext2[ramtype], bw);
+}
+
+static int
+sisusb_do_init_gfxdevice(struct sisusb_usb_data *sisusb)
+{
+	struct sisusb_packet packet;
+	int ret;
+	u32 tmp32;
+
+	/* Do some magic */
+	packet.header  = 0x001f;
+	packet.address = 0x00000324;
+	packet.data    = 0x00000004;
+	ret = sisusb_send_bridge_packet(sisusb, 10, &packet, 0);
+
+	packet.header  = 0x001f;
+	packet.address = 0x00000364;
+	packet.data    = 0x00000004;
+	ret |= sisusb_send_bridge_packet(sisusb, 10, &packet, 0);
+
+	packet.header  = 0x001f;
+	packet.address = 0x00000384;
+	packet.data    = 0x00000004;
+	ret |= sisusb_send_bridge_packet(sisusb, 10, &packet, 0);
+
+	packet.header  = 0x001f;
+	packet.address = 0x00000100;
+	packet.data    = 0x00000700;
+	ret |= sisusb_send_bridge_packet(sisusb, 10, &packet, 0);
+
+	packet.header  = 0x000f;
+	packet.address = 0x00000004;
+	ret |= sisusb_send_bridge_packet(sisusb, 6, &packet, 0);
+	packet.data |= 0x17;
+	ret |= sisusb_send_bridge_packet(sisusb, 10, &packet, 0);
+
+	/* Init BAR 0 (VRAM) */
+	ret |= sisusb_read_pci_config(sisusb, 0x10, &tmp32);
+	ret |= sisusb_write_pci_config(sisusb, 0x10, 0xfffffff0);
+	ret |= sisusb_read_pci_config(sisusb, 0x10, &tmp32);
+	tmp32 &= 0x0f;
+	tmp32 |= SISUSB_PCI_MEMBASE;
+	ret |= sisusb_write_pci_config(sisusb, 0x10, tmp32);
+
+	/* Init BAR 1 (MMIO) */
+	ret |= sisusb_read_pci_config(sisusb, 0x14, &tmp32);
+	ret |= sisusb_write_pci_config(sisusb, 0x14, 0xfffffff0);
+	ret |= sisusb_read_pci_config(sisusb, 0x14, &tmp32);
+	tmp32 &= 0x0f;
+	tmp32 |= SISUSB_PCI_MMIOBASE;
+	ret |= sisusb_write_pci_config(sisusb, 0x14, tmp32);
+
+	/* Init BAR 2 (i/o ports) */
+	ret |= sisusb_read_pci_config(sisusb, 0x18, &tmp32);
+	ret |= sisusb_write_pci_config(sisusb, 0x18, 0xfffffff0);
+	ret |= sisusb_read_pci_config(sisusb, 0x18, &tmp32);
+	tmp32 &= 0x0f;
+	tmp32 |= SISUSB_PCI_IOPORTBASE;
+	ret |= sisusb_write_pci_config(sisusb, 0x18, tmp32);
+
+	/* Enable memory and i/o access */
+	ret |= sisusb_read_pci_config(sisusb, 0x04, &tmp32);
+	tmp32 |= 0x3;
+	ret |= sisusb_write_pci_config(sisusb, 0x04, tmp32);
+
+	if (ret == 0) {
+		/* Some further magic */
+		packet.header  = 0x001f;
+		packet.address = 0x00000050;
+		packet.data    = 0x000000ff;
+		ret |= sisusb_send_bridge_packet(sisusb, 10, &packet, 0);
+	}
+
+	return ret;
+}
+
+/* Initialize the graphics device (return 0 on success)
+ * This initializes the net2280 as well as the PCI registers
+ * of the graphics board.
+ */
+
+static int
+sisusb_init_gfxdevice(struct sisusb_usb_data *sisusb, int initscreen)
+{
+	int ret = 0, test = 0;
+	u32 tmp32;
+
+	if (sisusb->devinit == 1) {
+		/* Read PCI BARs and see if they have been set up */
+		ret |= sisusb_read_pci_config(sisusb, 0x10, &tmp32);
+		if (ret) return ret;
+		if ((tmp32 & 0xfffffff0) == SISUSB_PCI_MEMBASE) test++;
+
+		ret |= sisusb_read_pci_config(sisusb, 0x14, &tmp32);
+		if (ret) return ret;
+		if ((tmp32 & 0xfffffff0) == SISUSB_PCI_MMIOBASE) test++;
+
+		ret |= sisusb_read_pci_config(sisusb, 0x18, &tmp32);
+		if (ret) return ret;
+		if ((tmp32 & 0xfffffff0) == SISUSB_PCI_IOPORTBASE) test++;
+	}
+
+	/* No? So reset the device */
+	if ((sisusb->devinit == 0) || (test != 3)) {
+
+		ret |= sisusb_do_init_gfxdevice(sisusb);
+
+		if (ret == 0)
+			sisusb->devinit = 1;
+
+	}
+
+	if (sisusb->devinit) {
+		/* Initialize the graphics core */
+		if (sisusb_init_gfxcore(sisusb) == 0) {
+			sisusb->gfxinit = 1;
+			sisusb_get_ramconfig(sisusb);
+			ret |= sisusb_set_default_mode(sisusb, 1);
+			ret |= sisusb_setup_screen(sisusb, 1, initscreen);
+		}
+	}
+
+	return ret;
+}
+
+/* fops */
+
+int
+sisusb_open(struct inode *inode, struct file *file)
+{
+	struct sisusb_usb_data *sisusb;
+	struct usb_interface *interface;
+	int subminor = iminor(inode);
+
+	down(&disconnect_sem);
+
+	if (!(interface = usb_find_interface(&sisusb_driver, subminor))) {
+		printk(KERN_ERR "sisusb[%d]: Failed to find interface\n",
+				subminor);
+		up(&disconnect_sem);
+		return -ENODEV;
+	}
+
+	if (!(sisusb = usb_get_intfdata(interface))) {
+		up(&disconnect_sem);
+		return -ENODEV;
+	}
+
+	down(&sisusb->lock);
+
+	if (!sisusb->present || !sisusb->ready) {
+		up(&sisusb->lock);
+		up(&disconnect_sem);
+		return -ENODEV;
+	}
+
+	if (sisusb->isopen) {
+		up(&sisusb->lock);
+		up(&disconnect_sem);
+		return -EBUSY;
+	}
+
+	if (!sisusb->devinit) {
+		if (sisusb->sisusb_dev->speed == USB_SPEED_HIGH) {
+			if (sisusb_init_gfxdevice(sisusb, 0)) {
+				up(&sisusb->lock);
+				up(&disconnect_sem);
+				printk(KERN_ERR
+					"sisusbvga[%d]: Failed to initialize "
+					"device\n",
+					sisusb->minor);
+				return -EIO;
+			}
+		} else {
+			up(&sisusb->lock);
+			up(&disconnect_sem);
+			printk(KERN_ERR
+				"sisusbvga[%d]: Device not attached to "
+				"USB 2.0 hub\n",
+				sisusb->minor);
+			return -EIO;
+		}
+	}
+
+	/* increment usage count for the device */
+	kref_get(&sisusb->kref);
+
+	sisusb->isopen = 1;
+
+	file->private_data = sisusb;
+
+	up(&sisusb->lock);
+
+	up(&disconnect_sem);
+
+	printk(KERN_DEBUG "sisusbvga[%d]: opened", sisusb->minor);
+
+	return 0;
+}
+
+static void
+sisusb_delete(struct kref *kref)
+{
+	struct sisusb_usb_data *sisusb = to_sisusb_dev(kref);
+
+	if (!sisusb)
+		return;
+
+	if (sisusb->sisusb_dev)
+		usb_put_dev(sisusb->sisusb_dev);
+
+	sisusb->sisusb_dev = NULL;
+	sisusb_free_buffers(sisusb);
+	sisusb_free_urbs(sisusb);
+	kfree(sisusb);
+}
+
+int
+sisusb_release(struct inode *inode, struct file *file)
+{
+	struct sisusb_usb_data *sisusb;
+	int myminor;
+
+	down(&disconnect_sem);
+
+	if (!(sisusb = (struct sisusb_usb_data *)file->private_data)) {
+		up(&disconnect_sem);
+		return -ENODEV;
+	}
+
+	down(&sisusb->lock);
+
+	if (sisusb->present) {
+		/* Wait for all URBs to finish if device still present */
+		if (!sisusb_wait_all_out_complete(sisusb))
+			sisusb_kill_all_busy(sisusb);
+	}
+
+	myminor = sisusb->minor;
+
+	sisusb->isopen = 0;
+	file->private_data = NULL;
+
+	up(&sisusb->lock);
+
+	/* decrement the usage count on our device */
+	kref_put(&sisusb->kref, sisusb_delete);
+
+	up(&disconnect_sem);
+
+	printk(KERN_DEBUG "sisusbvga[%d]: released", myminor);
+
+	return 0;
+}
+
+ssize_t
+sisusb_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos)
+{
+	struct sisusb_usb_data *sisusb;
+	ssize_t bytes_read = 0;
+	int errno = 0;
+	u8 buf8;
+	u16 buf16;
+	u32 buf32, address;
+
+	if (!(sisusb = (struct sisusb_usb_data *)file->private_data))
+		return -ENODEV;
+
+	down(&sisusb->lock);
+
+	/* Sanity check */
+	if (!sisusb->present || !sisusb->ready || !sisusb->sisusb_dev) {
+		up(&sisusb->lock);
+		return -ENODEV;
+	}
+
+	if ((*ppos) >= SISUSB_PCI_PSEUDO_IOPORTBASE &&
+	    (*ppos) <  SISUSB_PCI_PSEUDO_IOPORTBASE + 128) {
+
+		address = (*ppos) -
+			SISUSB_PCI_PSEUDO_IOPORTBASE +
+			SISUSB_PCI_IOPORTBASE;
+
+		/* Read i/o ports
+		 * Byte, word and long(32) can be read. As this
+		 * emulates inX instructions, the data returned is
+		 * in machine-endianness.
+		 */
+		switch (count) {
+
+			case 1:
+				if (sisusb_read_memio_byte(sisusb,
+							SISUSB_TYPE_IO,
+							address, &buf8))
+					errno = -EIO;
+				else if (put_user(buf8, (u8 __user *)buffer))
+					errno = -EFAULT;
+				else
+					bytes_read = 1;
+
+				break;
+
+			case 2:
+				if (sisusb_read_memio_word(sisusb,
+							SISUSB_TYPE_IO,
+							address, &buf16))
+					errno = -EIO;
+				else if (put_user(buf16, (u16 __user *)buffer))
+					errno = -EFAULT;
+				else
+					bytes_read = 2;
+
+				break;
+
+			case 4:
+				if (sisusb_read_memio_long(sisusb,
+							SISUSB_TYPE_IO,
+							address, &buf32))
+					errno = -EIO;
+				else if (put_user(buf32, (u32 __user *)buffer))
+					errno = -EFAULT;
+				else
+					bytes_read = 4;
+
+				break;
+
+			default:
+				errno = -EIO;
+
+		}
+
+	} else if ((*ppos) >= SISUSB_PCI_PSEUDO_MEMBASE &&
+		   (*ppos) <  SISUSB_PCI_PSEUDO_MEMBASE + sisusb->vramsize) {
+
+		address = (*ppos) -
+			SISUSB_PCI_PSEUDO_MEMBASE +
+			SISUSB_PCI_MEMBASE;
+
+		/* Read video ram
+		 * Remember: Data delivered is never endian-corrected
+		 */
+		errno = sisusb_read_mem_bulk(sisusb, address,
+					NULL, count, buffer, &bytes_read);
+
+		if (bytes_read)
+			errno = bytes_read;
+
+	} else  if ((*ppos) >= SISUSB_PCI_PSEUDO_MMIOBASE &&
+		    (*ppos) <  SISUSB_PCI_PSEUDO_MMIOBASE + SISUSB_PCI_MMIOSIZE) {
+
+		address = (*ppos) -
+			SISUSB_PCI_PSEUDO_MMIOBASE +
+			SISUSB_PCI_MMIOBASE;
+
+		/* Read MMIO
+		 * Remember: Data delivered is never endian-corrected
+		 */
+		errno = sisusb_read_mem_bulk(sisusb, address,
+					NULL, count, buffer, &bytes_read);
+
+		if (bytes_read)
+			errno = bytes_read;
+
+	} else  if ((*ppos) >= SISUSB_PCI_PSEUDO_PCIBASE &&
+		    (*ppos) <= SISUSB_PCI_PSEUDO_PCIBASE + 0x5c) {
+
+		if (count != 4) {
+			up(&sisusb->lock);
+			return -EINVAL;
+		}
+
+		address = (*ppos) - SISUSB_PCI_PSEUDO_PCIBASE;
+
+		/* Read PCI config register
+		 * Return value delivered in machine endianness.
+		 */
+		if (sisusb_read_pci_config(sisusb, address, &buf32))
+			errno = -EIO;
+		else if (put_user(buf32, (u32 __user *)buffer))
+			errno = -EFAULT;
+		else
+			bytes_read = 4;
+
+	} else {
+
+		errno = -EBADFD;
+
+	}
+
+	(*ppos) += bytes_read;
+
+	up(&sisusb->lock);
+
+	return errno ? errno : bytes_read;
+}
+
+ssize_t
+sisusb_write(struct file *file, const char __user *buffer, size_t count,
+								loff_t *ppos)
+{
+	struct sisusb_usb_data *sisusb;
+	int errno = 0;
+	ssize_t bytes_written = 0;
+	u8 buf8;
+	u16 buf16;
+	u32 buf32, address;
+
+	if (!(sisusb = (struct sisusb_usb_data *)file->private_data))
+		return -ENODEV;
+
+	down(&sisusb->lock);
+
+	/* Sanity check */
+	if (!sisusb->present || !sisusb->ready || !sisusb->sisusb_dev) {
+		up(&sisusb->lock);
+		return -ENODEV;
+	}
+
+	if ((*ppos) >= SISUSB_PCI_PSEUDO_IOPORTBASE &&
+	    (*ppos) <  SISUSB_PCI_PSEUDO_IOPORTBASE + 128) {
+
+		address = (*ppos) -
+			SISUSB_PCI_PSEUDO_IOPORTBASE +
+			SISUSB_PCI_IOPORTBASE;
+
+		/* Write i/o ports
+		 * Byte, word and long(32) can be written. As this
+		 * emulates outX instructions, the data is expected
+		 * in machine-endianness.
+		 */
+		switch (count) {
+
+			case 1:
+				if (get_user(buf8, (u8 __user *)buffer))
+					errno = -EFAULT;
+				else if (sisusb_write_memio_byte(sisusb,
+							SISUSB_TYPE_IO,
+							address, buf8))
+					errno = -EIO;
+				else
+					bytes_written = 1;
+
+				break;
+
+			case 2:
+				if (get_user(buf16, (u16 __user *)buffer))
+					errno = -EFAULT;
+				else if (sisusb_write_memio_word(sisusb,
+							SISUSB_TYPE_IO,
+							address, buf16))
+					errno = -EIO;
+				else
+					bytes_written = 2;
+
+				break;
+
+			case 4:
+				if (get_user(buf32, (u32 __user *)buffer))
+					errno = -EFAULT;
+				else if (sisusb_write_memio_long(sisusb,
+							SISUSB_TYPE_IO,
+							address, buf32))
+					errno = -EIO;
+				else
+					bytes_written = 4;
+
+				break;
+
+			default:
+				errno = -EIO;
+		}
+
+	} else if ((*ppos) >= SISUSB_PCI_PSEUDO_MEMBASE &&
+		   (*ppos) <  SISUSB_PCI_PSEUDO_MEMBASE + sisusb->vramsize) {
+
+		address = (*ppos) -
+			SISUSB_PCI_PSEUDO_MEMBASE +
+			SISUSB_PCI_MEMBASE;
+
+		/* Write video ram.
+		 * Buffer is copied 1:1, therefore, on big-endian
+		 * machines, the data must be swapped by userland
+		 * in advance (if applicable; no swapping in 8bpp
+		 * mode or if YUV data is being transferred).
+		 */
+		errno = sisusb_write_mem_bulk(sisusb, address, NULL,
+					count, buffer, 0, &bytes_written);
+
+		if (bytes_written)
+			errno = bytes_written;
+
+	} else  if ((*ppos) >= SISUSB_PCI_PSEUDO_MMIOBASE &&
+		    (*ppos) <  SISUSB_PCI_PSEUDO_MMIOBASE + SISUSB_PCI_MMIOSIZE) {
+
+		address = (*ppos) -
+			SISUSB_PCI_PSEUDO_MMIOBASE +
+			SISUSB_PCI_MMIOBASE;
+
+		/* Write MMIO.
+		 * Buffer is copied 1:1, therefore, on big-endian
+		 * machines, the data must be swapped by userland
+		 * in advance.
+		 */
+		errno = sisusb_write_mem_bulk(sisusb, address, NULL,
+					count, buffer, 0, &bytes_written);
+
+		if (bytes_written)
+			errno = bytes_written;
+
+	} else  if ((*ppos) >= SISUSB_PCI_PSEUDO_PCIBASE &&
+		    (*ppos) <= SISUSB_PCI_PSEUDO_PCIBASE + SISUSB_PCI_PCONFSIZE) {
+
+		if (count != 4) {
+			up(&sisusb->lock);
+			return -EINVAL;
+		}
+
+		address = (*ppos) - SISUSB_PCI_PSEUDO_PCIBASE;
+
+		/* Write PCI config register.
+		 * Given value expected in machine endianness.
+		 */
+		if (get_user(buf32, (u32 __user *)buffer))
+			errno = -EFAULT;
+		else if (sisusb_write_pci_config(sisusb, address, buf32))
+			errno = -EIO;
+		else
+			bytes_written = 4;
+
+
+	} else {
+
+		/* Error */
+		errno = -EBADFD;
+
+	}
+
+	(*ppos) += bytes_written;
+
+	up(&sisusb->lock);
+
+	return errno ? errno : bytes_written;
+}
+
+static loff_t
+sisusb_lseek(struct file *file, loff_t offset, int orig)
+{
+	struct sisusb_usb_data *sisusb;
+	loff_t ret;
+
+	if (!(sisusb = (struct sisusb_usb_data *)file->private_data))
+		return -ENODEV;
+
+	down(&sisusb->lock);
+
+	/* Sanity check */
+	if (!sisusb->present || !sisusb->ready || !sisusb->sisusb_dev) {
+		up(&sisusb->lock);
+		return -ENODEV;
+	}
+
+	switch (orig) {
+		case 0:
+			file->f_pos = offset;
+			ret = file->f_pos;
+			/* never negative, no force_successful_syscall needed */
+			break;
+		case 1:
+			file->f_pos += offset;
+			ret = file->f_pos;
+			/* never negative, no force_successful_syscall needed */
+			break;
+		default:
+			/* seeking relative to "end of file" is not supported */
+			ret = -EINVAL;
+	}
+
+	up(&sisusb->lock);
+	return ret;
+}
+
+static int
+sisusb_handle_command(struct sisusb_usb_data *sisusb, struct sisusb_command *y,
+							unsigned long arg)
+{
+	int 	retval, port, length;
+	u32	address;
+
+	port = y->data3 -
+		SISUSB_PCI_PSEUDO_IOPORTBASE +
+		SISUSB_PCI_IOPORTBASE;
+
+	switch (y->operation) {
+		case SUCMD_GET:
+			retval = sisusb_getidxreg(sisusb, port,
+							 y->data0, &y->data1);
+			if (!retval) {
+				if (copy_to_user((void __user *)arg, y,
+							sizeof(*y)))
+					retval = -EFAULT;
+			}
+			break;
+
+		case SUCMD_SET:
+			retval = sisusb_setidxreg(sisusb, port,
+						y->data0, y->data1);
+			break;
+
+		case SUCMD_SETOR:
+			retval = sisusb_setidxregor(sisusb, port,
+						y->data0, y->data1);
+			break;
+
+		case SUCMD_SETAND:
+			retval = sisusb_setidxregand(sisusb, port,
+						y->data0, y->data1);
+			break;
+
+		case SUCMD_SETANDOR:
+			retval = sisusb_setidxregandor(sisusb, port,
+						y->data0, y->data1, y->data2);
+			break;
+
+		case SUCMD_SETMASK:
+			retval = sisusb_setidxregmask(sisusb, port,
+						y->data0, y->data1, y->data2);
+			break;
+
+		case SUCMD_CLRSCR:
+			length = (y->data0 << 16) | (y->data1 << 8) | y->data2;
+			address = y->data3 -
+				SISUSB_PCI_PSEUDO_MEMBASE +
+				SISUSB_PCI_MEMBASE;
+			retval = sisusb_clear_vram(sisusb, address, length);
+			break;
+
+		default:
+			retval = -EINVAL;
+	}
+
+	if(retval > 0)
+		retval = -EIO;
+
+	return retval;
+}
+
+static int
+sisusb_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
+	     						unsigned long arg)
+{
+	struct sisusb_usb_data *sisusb;
+	struct sisusb_info x;
+	struct sisusb_command y;
+	int 	retval = 0;
+	u32 __user *argp = (u32 __user *)arg;
+
+	if (!(sisusb = (struct sisusb_usb_data *)file->private_data))
+		return -ENODEV;
+
+	down(&sisusb->lock);
+
+	/* Sanity check */
+	if (!sisusb->present || !sisusb->ready || !sisusb->sisusb_dev) {
+		retval = -ENODEV;
+		goto err_out;
+	}
+
+	switch (cmd) {
+
+		case SISUSB_GET_CONFIG_SIZE:
+
+			if (put_user(sizeof(x), argp))
+				retval = -EFAULT;
+
+			break;
+
+		case SISUSB_GET_CONFIG:
+
+			x.sisusb_id   	    = SISUSB_ID;
+			x.sisusb_version    = SISUSB_VERSION;
+			x.sisusb_revision   = SISUSB_REVISION;
+			x.sisusb_patchlevel = SISUSB_PATCHLEVEL;
+			x.sisusb_gfxinit    = sisusb->gfxinit;
+			x.sisusb_vrambase   = SISUSB_PCI_PSEUDO_MEMBASE;
+			x.sisusb_mmiobase   = SISUSB_PCI_PSEUDO_MMIOBASE;
+			x.sisusb_iobase     = SISUSB_PCI_PSEUDO_IOPORTBASE;
+			x.sisusb_pcibase    = SISUSB_PCI_PSEUDO_PCIBASE;
+			x.sisusb_vramsize   = sisusb->vramsize;
+			x.sisusb_minor	    = sisusb->minor;
+			x.sisusb_fbdevactive= 0;
+
+			if (copy_to_user((void __user *)arg, &x, sizeof(x)))
+				retval = -EFAULT;
+
+			break;
+
+		case SISUSB_COMMAND:
+
+			if (copy_from_user(&y, (void __user *)arg, sizeof(y)))
+				retval = -EFAULT;
+			else
+				retval = sisusb_handle_command(sisusb, &y, arg);
+
+			break;
+
+		default:
+			retval = -EINVAL;
+			break;
+	}
+
+err_out:
+	up(&sisusb->lock);
+	return retval;
+}
+
+#ifdef SISUSB_NEW_CONFIG_COMPAT
+static long
+sisusb_compat_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
+{
+	long retval;
+
+	switch (cmd) {
+		case SISUSB_GET_CONFIG_SIZE:
+		case SISUSB_GET_CONFIG:
+		case SISUSB_COMMAND:
+			lock_kernel();
+			retval = sisusb_ioctl(f->f_dentry->d_inode, f, cmd, arg);
+			unlock_kernel();
+			return retval;
+
+		default:
+			return -ENOIOCTLCMD;
+	}
+}
+#endif
+
+static struct file_operations usb_sisusb_fops = {
+	.owner =	THIS_MODULE,
+	.open =		sisusb_open,
+	.release =	sisusb_release,
+	.read =		sisusb_read,
+	.write =	sisusb_write,
+	.llseek = 	sisusb_lseek,
+#ifdef SISUSB_NEW_CONFIG_COMPAT
+	.compat_ioctl = sisusb_compat_ioctl,
+#endif
+	.ioctl =	sisusb_ioctl
+};
+
+static struct usb_class_driver usb_sisusb_class = {
+	.name =		"usb/sisusbvga%d",
+	.fops =		&usb_sisusb_fops,
+	.mode =		S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP,
+	.minor_base =	SISUSB_MINOR
+};
+
+static int sisusb_probe(struct usb_interface *intf,
+			const struct usb_device_id *id)
+{
+	struct usb_device *dev = interface_to_usbdev(intf);
+	struct sisusb_usb_data *sisusb;
+	int retval = 0, i;
+	const char *memfail =
+		KERN_ERR
+		"sisusbvga[%d]: Failed to allocate memory for %s buffer\n";
+
+	printk(KERN_INFO "sisusb: USB2VGA dongle found at address %d\n",
+		dev->devnum);
+
+	/* Allocate memory for our private */
+	if (!(sisusb = kmalloc(sizeof(*sisusb), GFP_KERNEL))) {
+		printk(KERN_ERR
+			"sisusb: Failed to allocate memory for private data\n");
+		return -ENOMEM;
+	}
+	memset(sisusb, 0, sizeof(*sisusb));
+	kref_init(&sisusb->kref);
+
+	init_MUTEX(&(sisusb->lock));
+
+	/* Register device */
+	if ((retval = usb_register_dev(intf, &usb_sisusb_class))) {
+		printk(KERN_ERR
+			"sisusb: Failed to get a minor for device %d\n",
+			dev->devnum);
+		retval = -ENODEV;
+		goto error_1;
+	}
+
+	sisusb->sisusb_dev = dev;
+	sisusb->minor      = intf->minor;
+	sisusb->vrambase   = SISUSB_PCI_MEMBASE;
+	sisusb->mmiobase   = SISUSB_PCI_MMIOBASE;
+	sisusb->mmiosize   = SISUSB_PCI_MMIOSIZE;
+	sisusb->ioportbase = SISUSB_PCI_IOPORTBASE;
+	/* Everything else is zero */
+
+	/* Allocate buffers */
+	sisusb->ibufsize = SISUSB_IBUF_SIZE;
+	if (!(sisusb->ibuf = usb_buffer_alloc(dev, SISUSB_IBUF_SIZE,
+					GFP_KERNEL, &sisusb->transfer_dma_in))) {
+		printk(memfail, "input", sisusb->minor);
+		retval = -ENOMEM;
+		goto error_2;
+	}
+
+	sisusb->numobufs = 0;
+	sisusb->obufsize = SISUSB_OBUF_SIZE;
+	for (i = 0; i < NUMOBUFS; i++) {
+		if (!(sisusb->obuf[i] = usb_buffer_alloc(dev, SISUSB_OBUF_SIZE,
+					GFP_KERNEL,
+					&sisusb->transfer_dma_out[i]))) {
+			if (i == 0) {
+				printk(memfail, "output", sisusb->minor);
+				retval = -ENOMEM;
+				goto error_3;
+			}
+			break;
+		} else
+			sisusb->numobufs++;
+
+	}
+
+	/* Allocate URBs */
+	if (!(sisusb->sisurbin = usb_alloc_urb(0, GFP_KERNEL))) {
+		printk(KERN_ERR
+			"sisusbvga[%d]: Failed to allocate URBs\n",
+			sisusb->minor);
+		retval = -ENOMEM;
+		goto error_3;
+	}
+	sisusb->completein = 1;
+
+	for (i = 0; i < sisusb->numobufs; i++) {
+		if (!(sisusb->sisurbout[i] = usb_alloc_urb(0, GFP_KERNEL))) {
+			printk(KERN_ERR
+				"sisusbvga[%d]: Failed to allocate URBs\n",
+				sisusb->minor);
+			retval = -ENOMEM;
+			goto error_4;
+		}
+		sisusb->urbout_context[i].sisusb = (void *)sisusb;
+		sisusb->urbout_context[i].urbindex = i;
+		sisusb->urbstatus[i] = 0;
+	}
+
+	printk(KERN_INFO "sisusbvga[%d]: Allocated %d output buffers\n",
+					sisusb->minor, sisusb->numobufs);
+
+	/* Do remaining init stuff */
+
+	init_waitqueue_head(&sisusb->wait_q);
+
+	usb_set_intfdata(intf, sisusb);
+
+#ifdef SISUSB_OLD_CONFIG_COMPAT
+	{
+	int ret;
+	/* Our ioctls are all "32/64bit compatible" */
+	ret =  register_ioctl32_conversion(SISUSB_GET_CONFIG_SIZE, NULL);
+	ret |= register_ioctl32_conversion(SISUSB_GET_CONFIG,      NULL);
+	ret |= register_ioctl32_conversion(SISUSB_COMMAND,         NULL);
+	if (ret)
+		printk(KERN_ERR
+			"sisusbvga[%d]: Error registering ioctl32 "
+			"translations\n",
+			sisusb->minor);
+	else
+		sisusb->ioctl32registered = 1;
+
+	}
+#endif
+
+	sisusb->present = 1;
+
+	if (dev->speed == USB_SPEED_HIGH) {
+		if (sisusb_init_gfxdevice(sisusb, 1))
+			printk(KERN_ERR
+				"sisusbvga[%d]: Failed to early "
+				"initialize device\n",
+				sisusb->minor);
+
+	} else
+		printk(KERN_INFO
+			"sisusbvga[%d]: Not attached to USB 2.0 hub, "
+			"deferring init\n",
+			sisusb->minor);
+
+	sisusb->ready = 1;
+
+	return 0;
+
+error_4:
+	sisusb_free_urbs(sisusb);
+error_3:
+	sisusb_free_buffers(sisusb);
+error_2:
+	usb_deregister_dev(intf, &usb_sisusb_class);
+error_1:
+	kfree(sisusb);
+	return retval;
+}
+
+static void sisusb_disconnect(struct usb_interface *intf)
+{
+	struct sisusb_usb_data *sisusb;
+	int minor;
+
+	down(&disconnect_sem);
+
+	/* This should *not* happen */
+	if (!(sisusb = usb_get_intfdata(intf))) {
+		up(&disconnect_sem);
+		return;
+	}
+
+	down(&sisusb->lock);
+
+	/* Wait for all URBs to complete and kill them in case (MUST do) */
+	if (!sisusb_wait_all_out_complete(sisusb))
+		sisusb_kill_all_busy(sisusb);
+
+	minor = sisusb->minor;
+
+	usb_set_intfdata(intf, NULL);
+
+	usb_deregister_dev(intf, &usb_sisusb_class);
+
+#ifdef SISUSB_OLD_CONFIG_COMPAT
+	if (sisusb->ioctl32registered) {
+		int ret;
+		sisusb->ioctl32registered = 0;
+		ret =  unregister_ioctl32_conversion(SISUSB_GET_CONFIG_SIZE);
+		ret |= unregister_ioctl32_conversion(SISUSB_GET_CONFIG);
+		ret |= unregister_ioctl32_conversion(SISUSB_COMMAND);
+		if (ret) {
+			printk(KERN_ERR
+				"sisusbvga[%d]: Error unregistering "
+				"ioctl32 translations\n",
+				minor);
+		}
+	}
+#endif
+
+	sisusb->present = 0;
+	sisusb->ready = 0;
+
+	up(&sisusb->lock);
+
+	/* decrement our usage count */
+	kref_put(&sisusb->kref, sisusb_delete);
+
+	up(&disconnect_sem);
+
+	printk(KERN_INFO "sisusbvga[%d]: Disconnected\n", minor);
+}
+
+static struct usb_device_id sisusb_table [] = {
+	{ USB_DEVICE(0x0711, 0x0900) },
+	{ }
+};
+
+MODULE_DEVICE_TABLE (usb, sisusb_table);
+
+static struct usb_driver sisusb_driver = {
+	.owner =	THIS_MODULE,
+	.name =		"sisusb",
+	.probe =	sisusb_probe,
+	.disconnect =	sisusb_disconnect,
+	.id_table =	sisusb_table
+};
+
+static int __init usb_sisusb_init(void)
+{
+	int retval;
+
+	if (!(retval = usb_register(&sisusb_driver))) {
+		printk(KERN_INFO "sisusb: Driver version %d.%d.%d\n",
+			SISUSB_VERSION, SISUSB_REVISION, SISUSB_PATCHLEVEL);
+		printk(KERN_INFO
+			"sisusb: Copyright (C) 2005 Thomas Winischhofer\n");
+	}
+
+	return retval;
+}
+
+static void __exit usb_sisusb_exit(void)
+{
+	usb_deregister(&sisusb_driver);
+}
+
+module_init(usb_sisusb_init);
+module_exit(usb_sisusb_exit);
+
+MODULE_AUTHOR("Thomas Winischhofer <thomas@winischhofer.net>");
+MODULE_DESCRIPTION("sisusb - Driver for Net2280/SiS315-based USB2VGA dongles");
+MODULE_LICENSE("GPL");
+
diff -Nru a/drivers/usb/misc/sisusbvga/sisusb.h b/drivers/usb/misc/sisusbvga/sisusb.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/usb/misc/sisusbvga/sisusb.h	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,278 @@
+/*
+ * sisusb - usb kernel driver for Net2280/SiS315 based USB2VGA dongles
+ *
+ * Copyright (C) 2005 by Thomas Winischhofer, Vienna, Austria
+ *
+ * If distributed as part of the Linux kernel, this code is licensed under the
+ * terms of the GPL v2.
+ *
+ * Otherwise, the following license terms apply:
+ *
+ * * Redistribution and use in source and binary forms, with or without
+ * * modification, are permitted provided that the following conditions
+ * * are met:
+ * * 1) Redistributions of source code must retain the above copyright
+ * *    notice, this list of conditions and the following disclaimer.
+ * * 2) Redistributions in binary form must reproduce the above copyright
+ * *    notice, this list of conditions and the following disclaimer in the
+ * *    documentation and/or other materials provided with the distribution.
+ * * 3) The name of the author may not be used to endorse or promote products
+ * *    derived from this software without specific prior written permission.
+ * *
+ * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESSED OR
+ * * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Author: 	Thomas Winischhofer <thomas@winischhofer.net>
+ *
+ */
+
+#ifndef _SISUSB_H_
+#define _SISUSB_H_
+
+#ifdef CONFIG_COMPAT
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,10)
+#include <linux/ioctl32.h>
+#define SISUSB_OLD_CONFIG_COMPAT
+#else
+#define SISUSB_NEW_CONFIG_COMPAT
+#endif
+#endif
+
+/* Version Information */
+
+#define SISUSB_VERSION		0
+#define SISUSB_REVISION 	0
+#define SISUSB_PATCHLEVEL	7
+
+/* USB related */
+
+#define SISUSB_MINOR	133		/* FIXME */
+
+/* Size of the sisusb input/output buffers */
+#define SISUSB_IBUF_SIZE  0x01000
+#define SISUSB_OBUF_SIZE  0x10000	/* fixed */
+
+#define NUMOBUFS 8			/* max number of output buffers/output URBs */
+
+/* About endianness:
+ *
+ * 1) I/O ports, PCI config registers. The read/write()
+ *    calls emulate inX/outX. Hence, the data is
+ *    expected/delivered in machine endiannes by this
+ *    driver.
+ * 2) Video memory. The data is copied 1:1. There is
+ *    no swapping. Ever. This means for userland that
+ *    the data has to be prepared properly. (Hint:
+ *    think graphics data format, command queue,
+ *    hardware cursor.)
+ * 3) MMIO. Data is copied 1:1. MMIO must be swapped
+ *    properly by userland.
+ *
+ */
+
+#ifdef __BIG_ENDIAN
+#define SISUSB_CORRECT_ENDIANNESS_PACKET(p) 		\
+	do {						\
+		p->header  = cpu_to_le16(p->header);	\
+		p->address = cpu_to_le32(p->address);	\
+		p->data    = cpu_to_le32(p->data);	\
+	} while(0)
+#else
+#define SISUSB_CORRECT_ENDIANNESS_PACKET(p)
+#endif
+
+struct sisusb_usb_data;
+
+struct sisusb_urb_context {		/* urb->context for outbound bulk URBs */
+	struct sisusb_usb_data *sisusb;
+	int urbindex;
+	int *actual_length;
+};
+
+struct sisusb_usb_data {
+	struct usb_device *sisusb_dev;
+	struct usb_interface *interface;
+	struct kref kref;
+	wait_queue_head_t wait_q;	/* for syncind and timeouts */
+	struct semaphore lock;		/* general race avoidance */
+	unsigned int ifnum;		/* interface number of the USB device */
+	int minor;			/* minor (for logging clarity) */
+	int isopen;			/* !=0 if open */
+	int present;			/* !=0 if device is present on the bus */
+	int ready;			/* !=0 if device is ready for userland */
+#ifdef SISUSB_OLD_CONFIG_COMPAT
+	int ioctl32registered;
+#endif
+	int numobufs;			/* number of obufs = number of out urbs */
+	char *obuf[NUMOBUFS], *ibuf;	/* transfer buffers */
+	int obufsize, ibufsize;
+	dma_addr_t transfer_dma_out[NUMOBUFS];
+	dma_addr_t transfer_dma_in;
+	struct urb *sisurbout[NUMOBUFS];
+	struct urb *sisurbin;
+	unsigned char urbstatus[NUMOBUFS];
+	unsigned char completein;
+	struct sisusb_urb_context urbout_context[NUMOBUFS];
+	unsigned long flagb0;
+	unsigned long vrambase;		/* framebuffer base */
+	unsigned int vramsize;		/* framebuffer size (bytes) */
+	unsigned long mmiobase;
+	unsigned int mmiosize;
+	unsigned long ioportbase;
+	unsigned char devinit;		/* device initialized? */
+	unsigned char gfxinit;		/* graphics core initialized? */
+	unsigned short chipid, chipvendor;
+	unsigned short chiprevision;
+};
+
+#define to_sisusb_dev(d) container_of(d, struct sisusb_usb_data, kref)
+
+/* USB transport related */
+
+/* urbstatus */
+#define SU_URB_BUSY   1
+#define SU_URB_ALLOC  2
+
+/* Endpoints */
+
+#define SISUSB_EP_GFX_IN	0x0e	/* gfx std packet out(0e)/in(8e) */
+#define SISUSB_EP_GFX_OUT	0x0e
+
+#define SISUSB_EP_GFX_BULK_OUT	0x01	/* gfx mem bulk out/in */
+#define SISUSB_EP_GFX_BULK_IN	0x02	/* ? 2 is "OUT" ? */
+
+#define SISUSB_EP_GFX_LBULK_OUT	0x03	/* gfx large mem bulk out */
+
+#define SISUSB_EP_UNKNOWN_04	0x04	/* ? 4 is "OUT" ? - unused */
+
+#define SISUSB_EP_BRIDGE_IN	0x0d	/* Net2280 out(0d)/in(8d) */
+#define SISUSB_EP_BRIDGE_OUT	0x0d
+
+#define SISUSB_TYPE_MEM		0
+#define SISUSB_TYPE_IO		1
+
+struct sisusb_packet {
+	unsigned short header;
+	u32 address;
+	u32 data;
+} __attribute__((__packed__));
+
+#define CLEARPACKET(packet) memset(packet, 0, 10)
+
+/* PCI bridge related */
+
+#define SISUSB_PCI_MEMBASE	0xd0000000
+#define SISUSB_PCI_MMIOBASE	0xe4000000
+#define SISUSB_PCI_IOPORTBASE	0x0000d000
+
+#define SISUSB_PCI_PSEUDO_MEMBASE	0x10000000
+#define SISUSB_PCI_PSEUDO_MMIOBASE	0x20000000
+#define SISUSB_PCI_PSEUDO_IOPORTBASE	0x0000d000
+#define SISUSB_PCI_PSEUDO_PCIBASE	0x00010000
+
+#define SISUSB_PCI_MMIOSIZE	(128*1024)
+#define SISUSB_PCI_PCONFSIZE	0x5c
+
+/* graphics core related */
+
+#define AROFFSET	0x40
+#define ARROFFSET	0x41
+#define GROFFSET	0x4e
+#define SROFFSET	0x44
+#define CROFFSET	0x54
+#define MISCROFFSET	0x4c
+#define MISCWOFFSET	0x42
+#define INPUTSTATOFFSET 0x5A
+#define PART1OFFSET	0x04
+#define PART2OFFSET	0x10
+#define PART3OFFSET	0x12
+#define PART4OFFSET	0x14
+#define PART5OFFSET	0x16
+#define CAPTUREOFFSET	0x00
+#define VIDEOOFFSET	0x02
+#define COLREGOFFSET	0x48
+#define PELMASKOFFSET	0x46
+#define VGAENABLE	0x43
+
+#define SISAR		SISUSB_PCI_IOPORTBASE + AROFFSET
+#define SISARR		SISUSB_PCI_IOPORTBASE + ARROFFSET
+#define SISGR		SISUSB_PCI_IOPORTBASE + GROFFSET
+#define SISSR		SISUSB_PCI_IOPORTBASE + SROFFSET
+#define SISCR		SISUSB_PCI_IOPORTBASE + CROFFSET
+#define SISMISCR	SISUSB_PCI_IOPORTBASE + MISCROFFSET
+#define SISMISCW	SISUSB_PCI_IOPORTBASE + MISCWOFFSET
+#define SISINPSTAT	SISUSB_PCI_IOPORTBASE + INPUTSTATOFFSET
+#define SISPART1	SISUSB_PCI_IOPORTBASE + PART1OFFSET
+#define SISPART2	SISUSB_PCI_IOPORTBASE + PART2OFFSET
+#define SISPART3	SISUSB_PCI_IOPORTBASE + PART3OFFSET
+#define SISPART4	SISUSB_PCI_IOPORTBASE + PART4OFFSET
+#define SISPART5	SISUSB_PCI_IOPORTBASE + PART5OFFSET
+#define SISCAP		SISUSB_PCI_IOPORTBASE + CAPTUREOFFSET
+#define SISVID		SISUSB_PCI_IOPORTBASE + VIDEOOFFSET
+#define SISCOLIDXR	SISUSB_PCI_IOPORTBASE + COLREGOFFSET - 1
+#define SISCOLIDX	SISUSB_PCI_IOPORTBASE + COLREGOFFSET
+#define SISCOLDATA	SISUSB_PCI_IOPORTBASE + COLREGOFFSET + 1
+#define SISCOL2IDX	SISPART5
+#define SISCOL2DATA	SISPART5 + 1
+#define SISPEL		SISUSB_PCI_IOPORTBASE + PELMASKOFFSET
+#define SISVGAEN	SISUSB_PCI_IOPORTBASE + VGAENABLE
+#define SISDACA		SISCOLIDX
+#define SISDACD		SISCOLDATA
+
+/* ioctl related */
+
+/* Structure argument for SISUSB_GET_INFO ioctl  */
+struct sisusb_info {
+	__u32	sisusb_id;		/* for identifying sisusb */
+#define SISUSB_ID  0x53495355		/* Identify myself with 'SISU' */
+	__u8	sisusb_version;
+	__u8	sisusb_revision;
+	__u8	sisusb_patchlevel;
+	__u8	sisusb_gfxinit;		/* graphics core initialized? */
+
+	__u32	sisusb_vrambase;
+	__u32	sisusb_mmiobase;
+	__u32	sisusb_iobase;
+	__u32	sisusb_pcibase;
+
+	__u32	sisusb_vramsize;	/* framebuffer size in bytes */
+
+	__u32	sisusb_minor;
+
+	__u32   sisusb_fbdevactive;	/* != 0 if framebuffer device active */
+
+	__u8	sisusb_reserved[32];	/* for future use */
+};
+
+struct sisusb_command {
+	__u8   operation;	/* see below */
+	__u8   data0;		/* operation dependent */
+	__u8   data1;		/* operation dependent */
+	__u8   data2;		/* operation dependent */
+	__u32  data3;		/* operation dependent */
+	__u32  data4;		/* for future use */
+};
+
+#define SUCMD_GET      0x01	/* for all: data0 = index, data3 = port */
+#define SUCMD_SET      0x02	/* data1 = value */
+#define SUCMD_SETOR    0x03	/* data1 = or */
+#define SUCMD_SETAND   0x04	/* data1 = and */
+#define SUCMD_SETANDOR 0x05	/* data1 = and, data2 = or */
+#define SUCMD_SETMASK  0x06	/* data1 = data, data2 = mask */
+
+#define SUCMD_CLRSCR   0x07	/* data0:1:2 = length, data3 = address */
+
+#define SISUSB_COMMAND		_IOWR(0xF3,0x3D,struct sisusb_command)
+#define SISUSB_GET_CONFIG_SIZE 	_IOR(0xF3,0x3E,__u32)
+#define SISUSB_GET_CONFIG  	_IOR(0xF3,0x3F,struct sisusb_info)
+
+#endif /* SISUSB_H */
+
diff -Nru a/drivers/usb/misc/usblcd.c b/drivers/usb/misc/usblcd.c
--- a/drivers/usb/misc/usblcd.c	2005-03-11 12:51:40 -08:00
+++ b/drivers/usb/misc/usblcd.c	2005-03-11 12:51:40 -08:00
@@ -144,7 +144,7 @@
 
 			result = usb_bulk_msg(lcd->lcd_dev,
 					 usb_sndbulkpipe(lcd->lcd_dev, 1),
-					 obuf, thistime, &partial, 10 * HZ);
+					 obuf, thistime, &partial, 10000);
 
 			dbg("write stats: result:%d thistime:%lu partial:%u",
 			     result, thistime, partial);
@@ -203,7 +203,7 @@
 		result = usb_bulk_msg(lcd->lcd_dev,
 				      usb_rcvbulkpipe(lcd->lcd_dev, 0),
 				      ibuf, this_read, &partial,
-				      (int) (HZ * 8));
+				      8000);
 
 		dbg(KERN_DEBUG "read stats: result:%d this_read:%u partial:%u",
 		       result, this_read, partial);
diff -Nru a/drivers/usb/misc/usbled.c b/drivers/usb/misc/usbled.c
--- a/drivers/usb/misc/usbled.c	2005-03-11 12:51:41 -08:00
+++ b/drivers/usb/misc/usbled.c	2005-03-11 12:51:41 -08:00
@@ -74,7 +74,7 @@
 				(0x00 * 0x100) + color,
 				buffer,	
 				8,
-				2 * HZ);
+				2000);
 	if (retval)
 		dev_dbg(&led->udev->dev, "retval = %d\n", retval);
 	kfree(buffer);
diff -Nru a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c
--- a/drivers/usb/misc/usbtest.c	2005-03-11 12:51:51 -08:00
+++ b/drivers/usb/misc/usbtest.c	2005-03-11 12:51:51 -08:00
@@ -472,7 +472,7 @@
 	retval = usb_control_msg (udev, usb_rcvctrlpipe (udev, 0),
 			USB_REQ_GET_INTERFACE, USB_DIR_IN|USB_RECIP_INTERFACE,
 			0, iface->altsetting [0].desc.bInterfaceNumber,
-			dev->buf, 1, HZ * USB_CTRL_GET_TIMEOUT);
+			dev->buf, 1, USB_CTRL_GET_TIMEOUT);
 	switch (retval) {
 	case 1:
 		return dev->buf [0];
@@ -602,7 +602,7 @@
 		retval = usb_control_msg (udev, usb_rcvctrlpipe (udev, 0),
 				USB_REQ_GET_CONFIGURATION,
 				USB_DIR_IN | USB_RECIP_DEVICE,
-				0, 0, dev->buf, 1, HZ * USB_CTRL_GET_TIMEOUT);
+				0, 0, dev->buf, 1, USB_CTRL_GET_TIMEOUT);
 		if (retval != 1 || dev->buf [0] != expected) {
 			dev_dbg (&iface->dev,
 				"get config --> %d (%d)\n", retval,
@@ -1173,7 +1173,7 @@
 	retval = usb_control_msg (urb->dev, usb_sndctrlpipe (urb->dev, 0),
 			USB_REQ_SET_FEATURE, USB_RECIP_ENDPOINT,
 			USB_ENDPOINT_HALT, ep,
-			NULL, 0, HZ * USB_CTRL_SET_TIMEOUT);
+			NULL, 0, USB_CTRL_SET_TIMEOUT);
 	if (retval < 0) {
 		dbg ("ep %02x couldn't set halt, %d", ep, retval);
 		return retval;
@@ -1263,7 +1263,7 @@
 			buf [j] = i + j;
 		retval = usb_control_msg (udev, usb_sndctrlpipe (udev,0),
 				0x5b, USB_DIR_OUT|USB_TYPE_VENDOR,
-				0, 0, buf, len, HZ * USB_CTRL_SET_TIMEOUT);
+				0, 0, buf, len, USB_CTRL_SET_TIMEOUT);
 		if (retval != len) {
 			what = "write";
 			break;
@@ -1272,7 +1272,7 @@
 		/* read it back -- assuming nothing intervened!!  */
 		retval = usb_control_msg (udev, usb_rcvctrlpipe (udev,0),
 				0x5c, USB_DIR_IN|USB_TYPE_VENDOR,
-				0, 0, buf, len, HZ * USB_CTRL_GET_TIMEOUT);
+				0, 0, buf, len, USB_CTRL_GET_TIMEOUT);
 		if (retval != len) {
 			what = "read";
 			break;
diff -Nru a/drivers/usb/misc/uss720.c b/drivers/usb/misc/uss720.c
--- a/drivers/usb/misc/uss720.c	2005-03-11 12:51:40 -08:00
+++ b/drivers/usb/misc/uss720.c	2005-03-11 12:51:40 -08:00
@@ -75,7 +75,7 @@
 
 	if (!usbdev)
 		return -1;
-	ret = usb_control_msg(usbdev, usb_rcvctrlpipe(usbdev,0), 3, 0xc0, ((unsigned int)reg) << 8, 0, priv->reg, 7, HZ);
+	ret = usb_control_msg(usbdev, usb_rcvctrlpipe(usbdev,0), 3, 0xc0, ((unsigned int)reg) << 8, 0, priv->reg, 7, 1000);
 	if (ret != 7) {
 		printk(KERN_DEBUG "uss720: get_1284_register(%d) failed, status 0x%x expected 7\n",
 		       (unsigned int)reg, ret);
@@ -105,7 +105,7 @@
 
 	if (!usbdev)
 		return -1;
-	ret = usb_control_msg(usbdev, usb_sndctrlpipe(usbdev,0), 4, 0x40, (((unsigned int)reg) << 8) | val, 0, NULL, 0, HZ);
+	ret = usb_control_msg(usbdev, usb_sndctrlpipe(usbdev,0), 4, 0x40, (((unsigned int)reg) << 8) | val, 0, NULL, 0, 1000);
 	if (ret) {
 		printk(KERN_DEBUG "uss720: set_1284_register(%u,0x%02x) failed, status 0x%x\n", 
 		       (unsigned int)reg, (unsigned int)val, ret);
@@ -374,7 +374,7 @@
 		return 0;
 	if (change_mode(pp, ECR_EPP))
 		return 0;
-	i = usb_bulk_msg(usbdev, usb_sndbulkpipe(usbdev, 1), (void *)buf, length, &rlen, HZ*20);
+	i = usb_bulk_msg(usbdev, usb_sndbulkpipe(usbdev, 1), (void *)buf, length, &rlen, 20000);
 	if (i)
 		printk(KERN_ERR "uss720: sendbulk ep 1 buf %p len %Zu rlen %u\n", buf, length, rlen);
 	change_mode(pp, ECR_PS2);
@@ -435,7 +435,7 @@
 		return 0;
 	if (change_mode(pp, ECR_ECP))
 		return 0;
-	i = usb_bulk_msg(usbdev, usb_sndbulkpipe(usbdev, 1), (void *)buffer, len, &rlen, HZ*20);
+	i = usb_bulk_msg(usbdev, usb_sndbulkpipe(usbdev, 1), (void *)buffer, len, &rlen, 20000);
 	if (i)
 		printk(KERN_ERR "uss720: sendbulk ep 1 buf %p len %Zu rlen %u\n", buffer, len, rlen);
 	change_mode(pp, ECR_PS2);
@@ -453,7 +453,7 @@
 		return 0;
 	if (change_mode(pp, ECR_ECP))
 		return 0;
-	i = usb_bulk_msg(usbdev, usb_rcvbulkpipe(usbdev, 2), buffer, len, &rlen, HZ*20);
+	i = usb_bulk_msg(usbdev, usb_rcvbulkpipe(usbdev, 2), buffer, len, &rlen, 20000);
 	if (i)
 		printk(KERN_ERR "uss720: recvbulk ep 2 buf %p len %Zu rlen %u\n", buffer, len, rlen);
 	change_mode(pp, ECR_PS2);
@@ -486,7 +486,7 @@
 		return 0;
 	if (change_mode(pp, ECR_PPF))
 		return 0;
-	i = usb_bulk_msg(usbdev, usb_sndbulkpipe(usbdev, 1), (void *)buffer, len, &rlen, HZ*20);
+	i = usb_bulk_msg(usbdev, usb_sndbulkpipe(usbdev, 1), (void *)buffer, len, &rlen, 20000);
 	if (i)
 		printk(KERN_ERR "uss720: sendbulk ep 1 buf %p len %Zu rlen %u\n", buffer, len, rlen);
 	change_mode(pp, ECR_PS2);
diff -Nru a/drivers/usb/mon/Kconfig b/drivers/usb/mon/Kconfig
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/usb/mon/Kconfig	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,22 @@
+#
+# USB Monitor configuration
+#
+
+# In normal life, it makes little sense to have usbmon as a module, and in fact
+# it is harmful, because there is no way to autoload the module.
+# The 'm' option is allowed for hackers who debug the usbmon itself,
+# and for those who have usbcore as a module.
+config USB_MON
+	tristate "USB Monitor"
+	depends on USB
+	default y
+	help
+	  If you say Y here, a component which captures the USB traffic
+	  between peripheral-specific drivers and HC drivers will be built.
+	  The USB_MON is similar in spirit and may be compatible with Dave
+	  Harding's USBMon.
+
+	  This is somewhat experimental at this time, but it should be safe,
+	  as long as you aren't building this as a module and then removing it.
+
+	  If unsure, say Y. Do not say M.
diff -Nru a/drivers/usb/mon/Makefile b/drivers/usb/mon/Makefile
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/usb/mon/Makefile	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,7 @@
+#
+# Makefile for USB Core files and filesystem
+#
+
+usbmon-objs	:= mon_main.o mon_stat.o mon_text.o
+
+obj-$(CONFIG_USB_MON)	+= usbmon.o
diff -Nru a/drivers/usb/mon/mon_main.c b/drivers/usb/mon/mon_main.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/usb/mon/mon_main.c	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,377 @@
+/*
+ * The USB Monitor, inspired by Dave Harding's USBMon.
+ *
+ * mon_main.c: Main file, module initiation and exit, registrations, etc.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/usb.h>
+#include <linux/debugfs.h>
+#include <linux/smp_lock.h>
+
+#include "usb_mon.h"
+#include "../core/hcd.h"
+
+static void mon_submit(struct usb_bus *ubus, struct urb *urb);
+static void mon_complete(struct usb_bus *ubus, struct urb *urb);
+static void mon_stop(struct mon_bus *mbus);
+static void mon_dissolve(struct mon_bus *mbus, struct usb_bus *ubus);
+static void mon_bus_drop(struct kref *r);
+static void mon_bus_init(struct dentry *mondir, struct usb_bus *ubus);
+
+DECLARE_MUTEX(mon_lock);
+
+static struct dentry *mon_dir;		/* /dbg/usbmon */
+static LIST_HEAD(mon_buses);		/* All buses we know: struct mon_bus */
+
+/*
+ * Link a reader into the bus.
+ *
+ * This must be called with mon_lock taken because of mbus->ref.
+ */
+void mon_reader_add(struct mon_bus *mbus, struct mon_reader *r)
+{
+	unsigned long flags;
+	struct usb_bus *ubus;
+
+	spin_lock_irqsave(&mbus->lock, flags);
+	if (mbus->nreaders == 0) {
+		ubus = mbus->u_bus;
+		if (ubus->monitored) {
+			/*
+			 * Something is really broken, refuse to go on and
+			 * possibly corrupt ops pointers or worse.
+			 */
+			printk(KERN_ERR TAG ": bus %d is already monitored\n",
+			    ubus->busnum);
+			spin_unlock_irqrestore(&mbus->lock, flags);
+			return;
+		}
+		ubus->monitored = 1;
+	}
+	mbus->nreaders++;
+	list_add_tail(&r->r_link, &mbus->r_list);
+	spin_unlock_irqrestore(&mbus->lock, flags);
+
+	kref_get(&mbus->ref);
+}
+
+/*
+ * Unlink reader from the bus.
+ *
+ * This is called with mon_lock taken, so we can decrement mbus->ref.
+ */
+void mon_reader_del(struct mon_bus *mbus, struct mon_reader *r)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&mbus->lock, flags);
+	list_del(&r->r_link);
+	--mbus->nreaders;
+	if (mbus->nreaders == 0)
+		mon_stop(mbus);
+	spin_unlock_irqrestore(&mbus->lock, flags);
+
+	kref_put(&mbus->ref, mon_bus_drop);
+}
+
+/*
+ */
+static void mon_submit(struct usb_bus *ubus, struct urb *urb)
+{
+	struct mon_bus *mbus;
+	unsigned long flags;
+	struct list_head *pos;
+	struct mon_reader *r;
+
+	mbus = ubus->mon_bus;
+	if (mbus == NULL)
+		goto out_unlocked;
+
+	spin_lock_irqsave(&mbus->lock, flags);
+	if (mbus->nreaders == 0)
+		goto out_locked;
+
+	list_for_each (pos, &mbus->r_list) {
+		r = list_entry(pos, struct mon_reader, r_link);
+		r->rnf_submit(r->r_data, urb);
+	}
+
+	spin_unlock_irqrestore(&mbus->lock, flags);
+	return;
+
+out_locked:
+	spin_unlock_irqrestore(&mbus->lock, flags);
+out_unlocked:
+	return;
+}
+
+/*
+ */
+static void mon_submit_error(struct usb_bus *ubus, struct urb *urb, int err)
+{
+	struct mon_bus *mbus;
+
+	mbus = ubus->mon_bus;
+	if (mbus == NULL)
+		goto out_unlocked;
+
+	/*
+	 * XXX Capture the error code and the 'E' event.
+	 */
+
+	return;
+
+out_unlocked:
+	return;
+}
+
+/*
+ */
+static void mon_complete(struct usb_bus *ubus, struct urb *urb)
+{
+	struct mon_bus *mbus;
+	unsigned long flags;
+	struct list_head *pos;
+	struct mon_reader *r;
+
+	mbus = ubus->mon_bus;
+	if (mbus == NULL) {
+		/*
+		 * This should not happen.
+		 * At this point we do not even know the bus number...
+		 */
+		printk(KERN_ERR TAG ": Null mon bus in URB, pipe 0x%x\n",
+		    urb->pipe);
+		return;
+	}
+
+	spin_lock_irqsave(&mbus->lock, flags);
+	list_for_each (pos, &mbus->r_list) {
+		r = list_entry(pos, struct mon_reader, r_link);
+		r->rnf_complete(r->r_data, urb);
+	}
+	spin_unlock_irqrestore(&mbus->lock, flags);
+}
+
+/* int (*unlink_urb) (struct urb *urb, int status); */
+
+/*
+ * Stop monitoring.
+ * Obviously this must be well locked, so no need to play with mb's.
+ */
+static void mon_stop(struct mon_bus *mbus)
+{
+	struct usb_bus *ubus = mbus->u_bus;
+
+	/*
+	 * A stop can be called for a dissolved mon_bus in case of
+	 * a reader staying across an rmmod foo_hcd.
+	 */
+	if (ubus != NULL) {
+		ubus->monitored = 0;
+		mb();
+	}
+}
+
+/*
+ * Add a USB bus (usually by a modprobe foo-hcd)
+ *
+ * This does not return an error code because the core cannot care less
+ * if monitoring is not established.
+ */
+static void mon_bus_add(struct usb_bus *ubus)
+{
+	mon_bus_init(mon_dir, ubus);
+}
+
+/*
+ * Remove a USB bus (either from rmmod foo-hcd or from a hot-remove event).
+ */
+static void mon_bus_remove(struct usb_bus *ubus)
+{
+	struct mon_bus *mbus = ubus->mon_bus;
+
+	down(&mon_lock);
+	list_del(&mbus->bus_link);
+	debugfs_remove(mbus->dent_t);
+	debugfs_remove(mbus->dent_s);
+
+	mon_dissolve(mbus, ubus);
+	kref_put(&mbus->ref, mon_bus_drop);
+	up(&mon_lock);
+}
+
+/*
+ * Ops
+ */
+static struct usb_mon_operations mon_ops_0 = {
+	.urb_submit =	mon_submit,
+	.urb_submit_error = mon_submit_error,
+	.urb_complete =	mon_complete,
+	.bus_add =	mon_bus_add,
+	.bus_remove =	mon_bus_remove,
+};
+
+/*
+ * Tear usb_bus and mon_bus apart.
+ */
+static void mon_dissolve(struct mon_bus *mbus, struct usb_bus *ubus)
+{
+
+	/*
+	 * Never happens, but...
+	 */
+	if (ubus->monitored) {
+		printk(KERN_ERR TAG ": bus %d is dissolved while monitored\n",
+		    ubus->busnum);
+		ubus->monitored = 0;
+		mb();
+	}
+
+	ubus->mon_bus = NULL;
+	mbus->u_bus = NULL;
+	mb();
+	// usb_bus_put(ubus);
+}
+
+/*
+ */
+static void mon_bus_drop(struct kref *r)
+{
+	struct mon_bus *mbus = container_of(r, struct mon_bus, ref);
+	kfree(mbus);
+}
+
+/*
+ * Initialize a bus for us:
+ *  - allocate mon_bus
+ *  - refcount USB bus struct
+ *  - link
+ */
+static void mon_bus_init(struct dentry *mondir, struct usb_bus *ubus)
+{
+	struct dentry *d;
+	struct mon_bus *mbus;
+	enum { NAMESZ = 10 };
+	char name[NAMESZ];
+	int rc;
+
+	if ((mbus = kmalloc(sizeof(struct mon_bus), GFP_KERNEL)) == NULL)
+		goto err_alloc;
+	memset(mbus, 0, sizeof(struct mon_bus));
+	kref_init(&mbus->ref);
+	spin_lock_init(&mbus->lock);
+	INIT_LIST_HEAD(&mbus->r_list);
+
+	/*
+	 * This usb_bus_get here is superfluous, because we receive
+	 * a notification if usb_bus is about to be removed.
+	 */
+	// usb_bus_get(ubus);
+	mbus->u_bus = ubus;
+	ubus->mon_bus = mbus;
+
+	rc = snprintf(name, NAMESZ, "%dt", ubus->busnum);
+	if (rc <= 0 || rc >= NAMESZ)
+		goto err_print_t;
+	d = debugfs_create_file(name, 0600, mondir, mbus, &mon_fops_text);
+	if (d == NULL)
+		goto err_create_t;
+	mbus->dent_t = d;
+
+	rc = snprintf(name, NAMESZ, "%ds", ubus->busnum);
+	if (rc <= 0 || rc >= NAMESZ)
+		goto err_print_s;
+	d = debugfs_create_file(name, 0600, mondir, mbus, &mon_fops_stat);
+	if (d == NULL)
+		goto err_create_s;
+	mbus->dent_s = d;
+
+	down(&mon_lock);
+	list_add_tail(&mbus->bus_link, &mon_buses);
+	up(&mon_lock);
+	return;
+
+err_create_s:
+err_print_s:
+	debugfs_remove(mbus->dent_t);
+err_create_t:
+err_print_t:
+	kfree(mbus);
+err_alloc:
+	return;
+}
+
+static int __init mon_init(void)
+{
+	struct usb_bus *ubus;
+	struct dentry *mondir;
+
+	mondir = debugfs_create_dir("usbmon", NULL);
+	if (IS_ERR(mondir)) {
+		printk(KERN_NOTICE TAG ": debugs is not available\n");
+		return -ENODEV;
+	}
+	if (mondir == NULL) {
+		printk(KERN_NOTICE TAG ": unable to create usbmon directory\n");
+		return -ENODEV;
+	}
+	mon_dir = mondir;
+
+	if (usb_mon_register(&mon_ops_0) != 0) {
+		printk(KERN_NOTICE TAG ": unable to register with the core\n");
+		debugfs_remove(mondir);
+		return -ENODEV;
+	}
+	// MOD_INC_USE_COUNT(which_module?);
+
+	down(&usb_bus_list_lock);
+	list_for_each_entry (ubus, &usb_bus_list, bus_list) {
+		mon_bus_init(mondir, ubus);
+	}
+	up(&usb_bus_list_lock);
+	return 0;
+}
+
+static void __exit mon_exit(void)
+{
+	struct mon_bus *mbus;
+	struct list_head *p;
+
+	usb_mon_deregister();
+
+	down(&mon_lock);
+	while (!list_empty(&mon_buses)) {
+		p = mon_buses.next;
+		mbus = list_entry(p, struct mon_bus, bus_link);
+		list_del(p);
+
+		debugfs_remove(mbus->dent_t);
+		debugfs_remove(mbus->dent_s);
+
+		/*
+		 * This never happens, because the open/close paths in
+		 * file level maintain module use counters and so rmmod fails
+		 * before reaching here. However, better be safe...
+		 */
+		if (mbus->nreaders) {
+			printk(KERN_ERR TAG
+			    ": Outstanding opens (%d) on usb%d, leaking...\n",
+			    mbus->nreaders, mbus->u_bus->busnum);
+			atomic_set(&mbus->ref.refcount, 2);	/* Force leak */
+		}
+
+		mon_dissolve(mbus, mbus->u_bus);
+		kref_put(&mbus->ref, mon_bus_drop);
+	}
+	up(&mon_lock);
+
+	debugfs_remove(mon_dir);
+}
+
+module_init(mon_init);
+module_exit(mon_exit);
+
+MODULE_LICENSE("GPL");
diff -Nru a/drivers/usb/mon/mon_stat.c b/drivers/usb/mon/mon_stat.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/usb/mon/mon_stat.c	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,74 @@
+/*
+ * The USB Monitor, inspired by Dave Harding's USBMon.
+ *
+ * This is the 's' or 'stat' reader which debugs usbmon itself.
+ * Note that this code blows through locks, so make sure that
+ * /dbg/usbmon/0s is well protected from non-root users.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/usb.h>
+#include <asm/uaccess.h>
+
+#include "usb_mon.h"
+
+#define STAT_BUF_SIZE  80
+
+struct snap {
+	int slen;
+	char str[STAT_BUF_SIZE];
+};
+
+static int mon_stat_open(struct inode *inode, struct file *file)
+{
+	struct mon_bus *mbus;
+	struct snap *sp;
+
+	if ((sp = kmalloc(sizeof(struct snap), GFP_KERNEL)) == NULL)
+		return -ENOMEM;
+
+	mbus = inode->u.generic_ip;
+
+	sp->slen = snprintf(sp->str, STAT_BUF_SIZE,
+	    "nreaders %d text_lost %u\n",
+	    mbus->nreaders, mbus->cnt_text_lost);
+
+	file->private_data = sp;
+	return 0;
+}
+
+static ssize_t mon_stat_read(struct file *file, char __user *buf,
+				size_t nbytes, loff_t *ppos)
+{
+	struct snap *sp = file->private_data;
+	loff_t pos = *ppos;
+	int cnt;
+
+	if (pos < 0 || pos >= sp->slen)
+		return 0;
+	if (nbytes == 0)
+		return 0;
+	if ((cnt = sp->slen - pos) > nbytes)
+		cnt = nbytes;
+	if (copy_to_user(buf, sp->str + pos, cnt))
+		return -EFAULT;
+	*ppos = pos + cnt;
+	return cnt;
+}
+
+static int mon_stat_release(struct inode *inode, struct file *file)
+{
+	return 0;
+}
+
+struct file_operations mon_fops_stat = {
+	.owner =	THIS_MODULE,
+	.open =		mon_stat_open,
+	.llseek =	no_llseek,
+	.read =		mon_stat_read,
+	/* .write =	mon_stat_write, */
+	/* .poll =		mon_stat_poll, */
+	/* .ioctl =	mon_stat_ioctl, */
+	.release =	mon_stat_release,
+};
diff -Nru a/drivers/usb/mon/mon_text.c b/drivers/usb/mon/mon_text.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/usb/mon/mon_text.c	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,395 @@
+/*
+ * The USB Monitor, inspired by Dave Harding's USBMon.
+ *
+ * This is a text format reader.
+ */
+
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/usb.h>
+#include <linux/time.h>
+#include <asm/uaccess.h>
+
+#include "usb_mon.h"
+
+/*
+ * No, we do not want arbitrarily long data strings.
+ * Use the binary interface if you want to capture bulk data!
+ */
+#define DATA_MAX  32
+
+/*
+ * This limit exists to prevent OOMs when the user process stops reading.
+ */
+#define EVENT_MAX  25
+
+#define PRINTF_DFL  120
+
+struct mon_event_text {
+	struct list_head e_link;
+	int type;		/* submit, complete, etc. */
+	unsigned int pipe;	/* Pipe */
+	unsigned long id;	/* From pointer, most of the time */
+	unsigned int tstamp;
+	int length;		/* Depends on type: xfer length or act length */
+	int status;
+	char data_flag;
+	unsigned char data[DATA_MAX];
+};
+
+#define SLAB_NAME_SZ  30
+struct mon_reader_text {
+	kmem_cache_t *e_slab;
+	int nevents;
+	struct list_head e_list;
+	struct mon_reader r;	/* In C, parent class can be placed anywhere */
+
+	wait_queue_head_t wait;
+	int printf_size;
+	char *printf_buf;
+	struct semaphore printf_lock;
+
+	char slab_name[SLAB_NAME_SZ];
+};
+
+static void mon_text_ctor(void *, kmem_cache_t *, unsigned long);
+static void mon_text_dtor(void *, kmem_cache_t *, unsigned long);
+
+/*
+ * mon_text_submit
+ * mon_text_complete
+ *
+ * May be called from an interrupt.
+ *
+ * This is called with the whole mon_bus locked, so no additional lock.
+ */
+
+static inline char mon_text_get_data(struct mon_event_text *ep, struct urb *urb,
+    int len, char ev_type)
+{
+	int pipe = urb->pipe;
+	unsigned char *data;
+
+	/*
+	 * The check to see if it's safe to poke at data has an enormous
+	 * number of corner cases, but it seems that the following is
+	 * more or less safe.
+	 *
+	 * We do not even try to look transfer_buffer, because it can
+	 * contain non-NULL garbage in case the upper level promised to
+	 * set DMA for the HCD.
+	 */
+	if (urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP)
+		return 'D';
+
+	if (len <= 0)
+		return 'L';
+
+	if ((data = urb->transfer_buffer) == NULL)
+		return 'Z';	/* '0' would be not as pretty. */
+
+	/*
+	 * Bulk is easy to shortcut reliably. 
+	 * XXX Control needs setup packet taken.
+	 * XXX Other pipe types need consideration. Currently, we overdo it
+	 * and collect garbage for them: better more than less.
+	 */
+	if (usb_pipebulk(pipe) || usb_pipecontrol(pipe)) {
+		if (usb_pipein(pipe)) {
+			if (ev_type == 'S')
+				return '<';
+		} else {
+			if (ev_type == 'C')
+				return '>';
+		}
+	}
+
+	if (len >= DATA_MAX)
+		len = DATA_MAX;
+	memcpy(ep->data, urb->transfer_buffer, len);
+	return 0;
+}
+
+static inline unsigned int mon_get_timestamp(void)
+{
+	struct timeval tval;
+	unsigned int stamp;
+
+	do_gettimeofday(&tval);
+	stamp = tval.tv_sec & 0xFFFF;	/* 2^32 = 4294967296. Limit to 4096s. */
+	stamp = stamp * 1000000 + tval.tv_usec;
+	return stamp;
+}
+
+static void mon_text_event(struct mon_reader_text *rp, struct urb *urb,
+    char ev_type)
+{
+	struct mon_event_text *ep;
+	unsigned int stamp;
+
+	stamp = mon_get_timestamp();
+
+	if (rp->nevents >= EVENT_MAX ||
+	    (ep = kmem_cache_alloc(rp->e_slab, SLAB_ATOMIC)) == NULL) {
+		rp->r.m_bus->cnt_text_lost++;
+		return;
+	}
+
+	ep->type = ev_type;
+	ep->pipe = urb->pipe;
+	ep->id = (unsigned long) urb;
+	ep->tstamp = stamp;
+	ep->length = (ev_type == 'S') ?
+	    urb->transfer_buffer_length : urb->actual_length;
+	/* Collecting status makes debugging sense for submits, too */
+	ep->status = urb->status;
+
+	ep->data_flag = mon_text_get_data(ep, urb, ep->length, ev_type);
+
+	rp->nevents++;
+	list_add_tail(&ep->e_link, &rp->e_list);
+	wake_up(&rp->wait);
+}
+
+static void mon_text_submit(void *data, struct urb *urb)
+{
+	struct mon_reader_text *rp = data;
+	mon_text_event(rp, urb, 'S');
+}
+
+static void mon_text_complete(void *data, struct urb *urb)
+{
+	struct mon_reader_text *rp = data;
+	mon_text_event(rp, urb, 'C');
+}
+
+/*
+ * Fetch next event from the circular buffer.
+ */
+static struct mon_event_text *mon_text_fetch(struct mon_reader_text *rp,
+    struct mon_bus *mbus)
+{
+	struct list_head *p;
+	unsigned long flags;
+
+	spin_lock_irqsave(&mbus->lock, flags);
+	if (list_empty(&rp->e_list)) {
+		spin_unlock_irqrestore(&mbus->lock, flags);
+		return NULL;
+	}
+	p = rp->e_list.next;
+	list_del(p);
+	--rp->nevents;
+	spin_unlock_irqrestore(&mbus->lock, flags);
+	return list_entry(p, struct mon_event_text, e_link);
+}
+
+/*
+ */
+static int mon_text_open(struct inode *inode, struct file *file)
+{
+	struct mon_bus *mbus;
+	struct usb_bus *ubus;
+	struct mon_reader_text *rp;
+	int rc;
+
+	down(&mon_lock);
+	mbus = inode->u.generic_ip;
+	ubus = mbus->u_bus;
+
+	rp = kmalloc(sizeof(struct mon_reader_text), GFP_KERNEL);
+	if (rp == NULL) {
+		rc = -ENOMEM;
+		goto err_alloc;
+	}
+	memset(rp, 0, sizeof(struct mon_reader_text));
+	INIT_LIST_HEAD(&rp->e_list);
+	init_waitqueue_head(&rp->wait);
+	init_MUTEX(&rp->printf_lock);
+
+	rp->printf_size = PRINTF_DFL;
+	rp->printf_buf = kmalloc(rp->printf_size, GFP_KERNEL);
+	if (rp->printf_buf == NULL) {
+		rc = -ENOMEM;
+		goto err_alloc_pr;
+	}
+
+	rp->r.m_bus = mbus;
+	rp->r.r_data = rp;
+	rp->r.rnf_submit = mon_text_submit;
+	rp->r.rnf_complete = mon_text_complete;
+
+	snprintf(rp->slab_name, SLAB_NAME_SZ, "mon%dt_%lx", ubus->busnum,
+	    (long)rp);
+	rp->e_slab = kmem_cache_create(rp->slab_name,
+	    sizeof(struct mon_event_text), sizeof(long), 0,
+	    mon_text_ctor, mon_text_dtor);
+	if (rp->e_slab == NULL) {
+		rc = -ENOMEM;
+		goto err_slab;
+	}
+
+	mon_reader_add(mbus, &rp->r);
+
+	file->private_data = rp;
+	up(&mon_lock);
+	return 0;
+
+// err_busy:
+//	kmem_cache_destroy(rp->e_slab);
+err_slab:
+	kfree(rp->printf_buf);
+err_alloc_pr:
+	kfree(rp);
+err_alloc:
+	up(&mon_lock);
+	return rc;
+}
+
+/*
+ * For simplicity, we read one record in one system call and throw out
+ * what does not fit. This means that the following does not work:
+ *   dd if=/dbg/usbmon/0t bs=10
+ * Also, we do not allow seeks and do not bother advancing the offset.
+ */
+static ssize_t mon_text_read(struct file *file, char __user *buf,
+				size_t nbytes, loff_t *ppos)
+{
+	struct mon_reader_text *rp = file->private_data;
+	struct mon_bus *mbus = rp->r.m_bus;
+	DECLARE_WAITQUEUE(waita, current);
+	struct mon_event_text *ep;
+	int cnt, limit;
+	char *pbuf;
+	int data_len, i;
+
+	add_wait_queue(&rp->wait, &waita);
+	set_current_state(TASK_INTERRUPTIBLE);
+	while ((ep = mon_text_fetch(rp, mbus)) == NULL) {
+		if (file->f_flags & O_NONBLOCK) {
+			set_current_state(TASK_RUNNING);
+			remove_wait_queue(&rp->wait, &waita);
+			return -EWOULDBLOCK;	/* Same as EAGAIN in Linux */
+		}
+		/*
+		 * We do not count nwaiters, because ->release is supposed
+		 * to be called when all openers are gone only.
+		 */
+		schedule();
+		if (signal_pending(current)) {
+			remove_wait_queue(&rp->wait, &waita);
+			return -EINTR;
+		}
+		set_current_state(TASK_INTERRUPTIBLE);
+	}
+	set_current_state(TASK_RUNNING);
+	remove_wait_queue(&rp->wait, &waita);
+
+	down(&rp->printf_lock);
+	cnt = 0;
+	pbuf = rp->printf_buf;
+	limit = rp->printf_size;
+
+	cnt += snprintf(pbuf + cnt, limit - cnt,
+	    "%lx %u %c %08x %d %d",
+	    ep->id, ep->tstamp, ep->type, ep->pipe, ep->status, ep->length);
+
+	if ((data_len = ep->length) > 0) {
+		if (ep->data_flag == 0) {
+			cnt += snprintf(pbuf + cnt, limit - cnt, " =");
+			if (data_len >= DATA_MAX)
+				data_len = DATA_MAX;
+			for (i = 0; i < data_len; i++) {
+				if (i % 4 == 0) {
+					cnt += snprintf(pbuf + cnt, limit - cnt,
+					    " ");
+				}
+				cnt += snprintf(pbuf + cnt, limit - cnt,
+				    "%02x", ep->data[i]);
+			}
+			cnt += snprintf(pbuf + cnt, limit - cnt, "\n");
+		} else {
+			cnt += snprintf(pbuf + cnt, limit - cnt,
+			    " %c\n", ep->data_flag);
+		}
+	} else {
+		cnt += snprintf(pbuf + cnt, limit - cnt, "\n");
+	}
+
+	if (copy_to_user(buf, rp->printf_buf, cnt))
+		cnt = -EFAULT;
+	up(&rp->printf_lock);
+	kmem_cache_free(rp->e_slab, ep);
+	return cnt;
+}
+
+static int mon_text_release(struct inode *inode, struct file *file)
+{
+	struct mon_reader_text *rp = file->private_data;
+	struct mon_bus *mbus;
+	/* unsigned long flags; */
+	struct list_head *p;
+	struct mon_event_text *ep;
+
+	down(&mon_lock);
+	mbus = inode->u.generic_ip;
+
+	if (mbus->nreaders <= 0) {
+		printk(KERN_ERR TAG ": consistency error on close\n");
+		up(&mon_lock);
+		return 0;
+	}
+	mon_reader_del(mbus, &rp->r);
+
+	/*
+	 * In theory, e_list is protected by mbus->lock. However,
+	 * after mon_reader_del has finished, the following is the case:
+	 *  - we are not on reader list anymore, so new events won't be added;
+	 *  - whole mbus may be dropped if it was orphaned.
+	 * So, we better not touch mbus.
+	 */
+	/* spin_lock_irqsave(&mbus->lock, flags); */
+	while (!list_empty(&rp->e_list)) {
+		p = rp->e_list.next;
+		ep = list_entry(p, struct mon_event_text, e_link);
+		list_del(p);
+		--rp->nevents;
+		kmem_cache_free(rp->e_slab, ep);
+	}
+	/* spin_unlock_irqrestore(&mbus->lock, flags); */
+
+	kmem_cache_destroy(rp->e_slab);
+	kfree(rp->printf_buf);
+	kfree(rp);
+
+	up(&mon_lock);
+	return 0;
+}
+
+struct file_operations mon_fops_text = {
+	.owner =	THIS_MODULE,
+	.open =		mon_text_open,
+	.llseek =	no_llseek,
+	.read =		mon_text_read,
+	/* .write =	mon_text_write, */
+	/* .poll =		mon_text_poll, */
+	/* .ioctl =	mon_text_ioctl, */
+	.release =	mon_text_release,
+};
+
+/*
+ * Slab interface: constructor.
+ */
+static void mon_text_ctor(void *mem, kmem_cache_t *slab, unsigned long sflags)
+{
+	/*
+	 * Nothing to initialize. No, really!
+	 * So, we fill it with garbage to emulate a reused object.
+	 */
+	memset(mem, 0xe5, sizeof(struct mon_event_text));
+}
+
+static void mon_text_dtor(void *mem, kmem_cache_t *slab, unsigned long sflags)
+{
+	;
+}
diff -Nru a/drivers/usb/mon/usb_mon.h b/drivers/usb/mon/usb_mon.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/usb/mon/usb_mon.h	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,51 @@
+/*
+ * The USB Monitor, inspired by Dave Harding's USBMon.
+ */
+
+#ifndef __USB_MON_H
+#define __USB_MON_H
+
+#include <linux/list.h>
+#include <linux/slab.h>
+#include <linux/kref.h>
+/* #include <linux/usb.h> */	/* We use struct pointers only in this header */
+
+#define TAG "usbmon"
+
+struct mon_bus {
+	struct list_head bus_link;
+	spinlock_t lock;
+	struct dentry *dent_s;		/* Debugging file */
+	struct dentry *dent_t;		/* Text interface file */
+	struct usb_bus *u_bus;
+
+	/* Ref */
+	int nreaders;			/* Under mon_lock AND mbus->lock */
+	struct list_head r_list;	/* Chain of readers (usually one) */
+	struct kref ref;		/* Under mon_lock */
+
+	/* Stats */
+	unsigned int cnt_text_lost;
+};
+
+/*
+ * An instance of a process which opened a file (but can fork later)
+ */
+struct mon_reader {
+	struct list_head r_link;
+	struct mon_bus *m_bus;
+	void *r_data;		/* Use container_of instead? */
+
+	void (*rnf_submit)(void *data, struct urb *urb);
+	void (*rnf_complete)(void *data, struct urb *urb);
+};
+
+void mon_reader_add(struct mon_bus *mbus, struct mon_reader *r);
+void mon_reader_del(struct mon_bus *mbus, struct mon_reader *r);
+
+extern struct semaphore mon_lock;
+
+extern struct file_operations mon_fops_text;
+extern struct file_operations mon_fops_stat;
+
+#endif /* __USB_MON_H */
diff -Nru a/drivers/usb/net/Kconfig b/drivers/usb/net/Kconfig
--- a/drivers/usb/net/Kconfig	2005-03-11 12:51:47 -08:00
+++ b/drivers/usb/net/Kconfig	2005-03-11 12:51:47 -08:00
@@ -260,13 +260,13 @@
 	depends on USB_USBNET
 
 config USB_AX8817X
-	boolean "ASIX AX88172 Based USB 2.0 Ethernet Devices"
+	boolean "ASIX AX88xxx Based USB 2.0 Ethernet Devices"
 	depends on USB_USBNET && NET_ETHERNET
 	select CRC32
 	select MII
 	default y
 	help
-	  This option adds support for ASIX AX88172 based USB 2.0
+	  This option adds support for ASIX AX88xxx based USB 2.0
 	  10/100 Ethernet devices.
 
  	  This driver should work with at least the following devices:
@@ -286,5 +286,22 @@
 
 	  This driver creates an interface named "ethX", where X depends on
 	  what other networking devices you have in use.  
+
+config USB_ZD1201
+	tristate "USB ZD1201 based Wireless device support"
+	depends on NET_RADIO
+	select FW_LOADER
+	---help---
+	  Say Y if you want to use wireless LAN adapters based on the ZyDAS
+	  ZD1201 chip.
+
+	  This driver makes the adapter appear as a normal Ethernet interface,
+	  typically on wlan0.
+	  
+	  The zd1201 device requires external firmware to be loaded.
+	  This can be found at http://linux-lc100020.sourceforge.net/
+	  
+	  To compile this driver as a module, choose M here: the
+	  module will be called zd1201.
 
 endmenu
diff -Nru a/drivers/usb/net/Makefile b/drivers/usb/net/Makefile
--- a/drivers/usb/net/Makefile	2005-03-11 12:51:41 -08:00
+++ b/drivers/usb/net/Makefile	2005-03-11 12:51:41 -08:00
@@ -7,3 +7,6 @@
 obj-$(CONFIG_USB_PEGASUS)	+= pegasus.o
 obj-$(CONFIG_USB_RTL8150)	+= rtl8150.o
 obj-$(CONFIG_USB_USBNET)	+= usbnet.o
+obj-$(CONFIG_USB_ZD1201)	+= zd1201.o
+
+CFLAGS_zd1201.o = -Idrivers/net/wireless/
diff -Nru a/drivers/usb/net/catc.c b/drivers/usb/net/catc.c
--- a/drivers/usb/net/catc.c	2005-03-11 12:51:46 -08:00
+++ b/drivers/usb/net/catc.c	2005-03-11 12:51:46 -08:00
@@ -457,7 +457,7 @@
 {
         int retval = usb_control_msg(catc->usbdev,
 		dir ? usb_rcvctrlpipe(catc->usbdev, 0) : usb_sndctrlpipe(catc->usbdev, 0),
-		 request, 0x40 | dir, value, index, buf, len, HZ);
+		 request, 0x40 | dir, value, index, buf, len, 1000);
         return retval < 0 ? retval : 0;
 }
 
diff -Nru a/drivers/usb/net/kaweth.c b/drivers/usb/net/kaweth.c
--- a/drivers/usb/net/kaweth.c	2005-03-11 12:51:47 -08:00
+++ b/drivers/usb/net/kaweth.c	2005-03-11 12:51:47 -08:00
@@ -58,6 +58,7 @@
 #include <linux/ethtool.h>
 #include <linux/pci.h>
 #include <linux/dma-mapping.h>
+#include <linux/wait.h>
 #include <asm/uaccess.h>
 #include <asm/semaphore.h>
 #include <asm/byteorder.h>
@@ -1180,31 +1181,21 @@
 // Starts urb and waits for completion or timeout
 static int usb_start_wait_urb(struct urb *urb, int timeout, int* actual_length)
 {
-        DECLARE_WAITQUEUE(wait, current);
 	struct usb_api_data awd;
         int status;
 
         init_waitqueue_head(&awd.wqh);
         awd.done = 0;
 
-        add_wait_queue(&awd.wqh, &wait);
         urb->context = &awd;
         status = usb_submit_urb(urb, GFP_NOIO);
         if (status) {
                 // something went wrong
                 usb_free_urb(urb);
-                remove_wait_queue(&awd.wqh, &wait);
                 return status;
         }
 
-	while (timeout && !awd.done) {
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		timeout = schedule_timeout(timeout);
-	}
-
-        remove_wait_queue(&awd.wqh, &wait);
-
-        if (!timeout) {
+	if (!wait_event_timeout(awd.wqh, awd.done, timeout)) {
                 // timeout
                 kaweth_warn("usb_control/bulk_msg: timeout");
                 usb_kill_urb(urb);  // remove urb safely
diff -Nru a/drivers/usb/net/pegasus.c b/drivers/usb/net/pegasus.c
--- a/drivers/usb/net/pegasus.c	2005-03-11 12:51:51 -08:00
+++ b/drivers/usb/net/pegasus.c	2005-03-11 12:51:51 -08:00
@@ -1,5 +1,5 @@
 /*
- *  Copyright (c) 1999-2003 Petko Manolov (petkan@users.sourceforge.net)
+ *  Copyright (c) 1999-2005 Petko Manolov (petkan@users.sourceforge.net)
  *
  * 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
@@ -47,7 +47,7 @@
 /*
  * Version Information
  */
-#define DRIVER_VERSION "v0.5.12 (2005/01/13)"
+#define DRIVER_VERSION "v0.6.12 (2005/01/13)"
 #define DRIVER_AUTHOR "Petko Manolov <petkan@users.sourceforge.net>"
 #define DRIVER_DESC "Pegasus/Pegasus II USB Ethernet driver"
 
@@ -301,20 +301,20 @@
 	if (i < REG_TIMEOUT) {
 		get_registers(pegasus, PhyData, 2, &regdi);
 		*regd = le16_to_cpu(regdi);
-		return 0;
+		return 1;
 	}
 	warn("%s: failed", __FUNCTION__);
 
-	return 1;
+	return 0;
 }
 
 static int mdio_read(struct net_device *dev, int phy_id, int loc)
 {
 	pegasus_t *pegasus = (pegasus_t *) netdev_priv(dev);
-	int res;
+	__le16 res;
 
-	read_mii_word(pegasus, phy_id, loc, (u16 *) & res);
-	return res & 0xffff;
+	read_mii_word(pegasus, phy_id, loc, &res);
+	return (int)res;
 }
 
 static int write_mii_word(pegasus_t * pegasus, __u8 phy, __u8 indx, __u16 regd)
@@ -636,7 +636,7 @@
 
 	return;
 
-      tl_sched:
+tl_sched:
 	tasklet_schedule(&pegasus->rx_tl);
 }
 
@@ -845,14 +845,14 @@
 static void set_carrier(struct net_device *net)
 {
 	pegasus_t *pegasus = netdev_priv(net);
-	short tmp;
+	__le16 tmp;
 
-	read_mii_word(pegasus, pegasus->phy, MII_BMSR, &tmp);
+	if (read_mii_word(pegasus, pegasus->phy, MII_BMSR, &tmp))
+		return;
 	if (tmp & BMSR_LSTATUS)
 		netif_carrier_on(net);
 	else
 		netif_carrier_off(net);
-
 }
 
 static void free_all_urbs(pegasus_t * pegasus)
@@ -997,8 +997,7 @@
 	return set_register(pegasus, WakeupControl, reg78);
 }
 
-static inline void
-pegasus_reset_wol(struct net_device *dev)
+static inline void pegasus_reset_wol(struct net_device *dev)
 {
 	struct ethtool_wolinfo wol;
 	
@@ -1009,10 +1008,17 @@
 static int
 pegasus_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
 {
-	pegasus_t *pegasus = netdev_priv(dev);
+	pegasus_t *pegasus;
+
+	if (in_atomic())
+		return 0;
+
+	pegasus = netdev_priv(dev);
 	mii_ethtool_gset(&pegasus->mii, ecmd);
+
 	return 0;
 }
+
 static int
 pegasus_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
 {
@@ -1149,6 +1155,20 @@
 		set_register(pegasus, Reg81, 2);
 }
 
+
+struct workqueue_struct *pegasus_workqueue = NULL;
+#define CARRIER_CHECK_DELAY (2 * HZ)
+
+void check_carrier(void *data)
+{
+	pegasus_t *pegasus = data;
+	set_carrier(pegasus->net);
+	if (!(pegasus->flags & PEGASUS_UNPLUG)) {
+		queue_delayed_work(pegasus_workqueue, &pegasus->carrier_check,
+			CARRIER_CHECK_DELAY);
+	}
+}
+
 static int pegasus_probe(struct usb_interface *intf,
 			 const struct usb_device_id *id)
 {
@@ -1175,6 +1195,8 @@
 
 	tasklet_init(&pegasus->rx_tl, rx_fixup, (unsigned long) pegasus);
 
+	INIT_WORK(&pegasus->carrier_check, check_carrier, pegasus);
+
 	pegasus->usb = dev;
 	pegasus->net = net;
 	SET_MODULE_OWNER(net);
@@ -1212,12 +1234,14 @@
 		dev_warn(&intf->dev, "can't locate MII phy, using default\n");
 		pegasus->phy = 1;
 	}
+	pegasus->mii.phy_id = pegasus->phy;
 	usb_set_intfdata(intf, pegasus);
 	SET_NETDEV_DEV(net, &intf->dev);
 	pegasus_reset_wol(net);
 	res = register_netdev(net);
 	if (res)
 		goto out3;
+	queue_delayed_work(pegasus_workqueue, &pegasus->carrier_check, CARRIER_CHECK_DELAY);
 	pr_info("%s: %s\n", net->name, usb_dev_id[dev_index].name);
 	return 0;
 
@@ -1239,11 +1263,12 @@
 
 	usb_set_intfdata(intf, NULL);
 	if (!pegasus) {
-		warn("unregistering non-existant device");
+		warn("unregistering non-existent device");
 		return;
 	}
 
 	pegasus->flags |= PEGASUS_UNPLUG;
+	cancel_delayed_work(&pegasus->carrier_check);
 	unregister_netdev(pegasus->net);
 	usb_put_dev(interface_to_usbdev(intf));
 	free_all_urbs(pegasus);
@@ -1253,7 +1278,7 @@
 	free_netdev(pegasus->net);
 }
 
-static int pegasus_suspend (struct usb_interface *intf, u32 state)
+static int pegasus_suspend (struct usb_interface *intf, pm_message_t state)
 {
 	struct pegasus *pegasus = usb_get_intfdata(intf);
 	
@@ -1281,11 +1306,15 @@
 static int __init pegasus_init(void)
 {
 	pr_info("%s: %s, " DRIVER_DESC "\n", driver_name, DRIVER_VERSION);
+	pegasus_workqueue = create_singlethread_workqueue("pegasus");
+	if (!pegasus_workqueue)
+		return -ENOMEM;
 	return usb_register(&pegasus_driver);
 }
 
 static void __exit pegasus_exit(void)
 {
+	destroy_workqueue(pegasus_workqueue);
 	usb_deregister(&pegasus_driver);
 }
 
diff -Nru a/drivers/usb/net/pegasus.h b/drivers/usb/net/pegasus.h
--- a/drivers/usb/net/pegasus.h	2005-03-11 12:51:51 -08:00
+++ b/drivers/usb/net/pegasus.h	2005-03-11 12:51:51 -08:00
@@ -96,6 +96,7 @@
 	int			dev_index;
 	int			intr_interval;
 	struct tasklet_struct	rx_tl;
+	struct work_struct	carrier_check;
 	struct urb		*ctrl_urb, *rx_urb, *tx_urb, *intr_urb;
 	struct sk_buff		*rx_pool[RX_SKBS];
 	struct sk_buff		*rx_skb;
diff -Nru a/drivers/usb/net/rtl8150.c b/drivers/usb/net/rtl8150.c
--- a/drivers/usb/net/rtl8150.c	2005-03-11 12:51:47 -08:00
+++ b/drivers/usb/net/rtl8150.c	2005-03-11 12:51:47 -08:00
@@ -195,14 +195,14 @@
 {
 	return usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0),
 			       RTL8150_REQ_GET_REGS, RTL8150_REQT_READ,
-			       indx, 0, data, size, HZ / 2);
+			       indx, 0, data, size, 500);
 }
 
 static int set_registers(rtl8150_t * dev, u16 indx, u16 size, void *data)
 {
 	return usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0),
 			       RTL8150_REQ_SET_REGS, RTL8150_REQT_WRITE,
-			       indx, 0, data, size, HZ / 2);
+			       indx, 0, data, size, 500);
 }
 
 static void ctrl_callback(struct urb *urb, struct pt_regs *regs)
diff -Nru a/drivers/usb/net/usbnet.c b/drivers/usb/net/usbnet.c
--- a/drivers/usb/net/usbnet.c	2005-03-11 12:51:46 -08:00
+++ b/drivers/usb/net/usbnet.c	2005-03-11 12:51:46 -08:00
@@ -2,7 +2,8 @@
  * USB Networking Links
  * Copyright (C) 2000-2003 by David Brownell <dbrownell@users.sourceforge.net>
  * Copyright (C) 2002 Pavel Machek <pavel@ucw.cz>
- * Copyright (C) 2003 David Hollis <dhollis@davehollis.com>
+ * Copyright (C) 2003-2005 David Hollis <dhollis@davehollis.com>
+ * Copyright (C) 2005 Phil Chang <pchang23@sbcglobal.net>
  * Copyright (c) 2002-2003 TiVo Inc.
  *
  * This program is free software; you can redistribute it and/or modify
@@ -109,6 +110,7 @@
  *		(Neil Bortnak)
  * 03-nov-2004	Trivial patch for KC2190 (KC-190) chip. (Jonathan McDowell)
  *
+ * 01-feb-2005	AX88772 support (Phil Chang & Dave Hollis)
  *-------------------------------------------------------------------------*/
 
 // #define	DEBUG			// error path messages, extra info
@@ -164,8 +166,7 @@
 #define THROTTLE_JIFFIES	(HZ/8)
 
 // for vendor-specific control operations
-#define	CONTROL_TIMEOUT_MS	(500)			/* msec */
-#define CONTROL_TIMEOUT_JIFFIES ((CONTROL_TIMEOUT_MS * HZ)/1000)
+#define	CONTROL_TIMEOUT_MS	500
 
 // between wakeups
 #define UNLINK_TIMEOUT_MS	3
@@ -222,6 +223,8 @@
 #define FLAG_NO_SETINT	0x0010		/* device can't set_interface() */
 #define FLAG_ETHER	0x0020		/* maybe use "eth%d" names */
 
+#define FLAG_FRAMING_AX 0x0040          /* AX88772/178 packets */
+
 	/* init device ... can sleep, or cause probe() failure */
 	int	(*bind)(struct usbnet *, struct usb_interface *);
 
@@ -274,9 +277,6 @@
 MODULE_PARM_DESC (msg_level, "Initial message level (default = 1)");
 
 
-#define	RUN_CONTEXT (in_irq () ? "in_irq" \
-			: (in_interrupt () ? "in_interrupt" : "can sleep"))
-
 #ifdef DEBUG
 #define devdbg(usbnet, fmt, arg...) \
 	printk(KERN_DEBUG "%s: " fmt "\n" , (usbnet)->net->name , ## arg)
@@ -435,6 +435,8 @@
 #define AX_CMD_SET_HW_MII		0x0a
 #define AX_CMD_READ_EEPROM		0x0b
 #define AX_CMD_WRITE_EEPROM		0x0c
+#define AX_CMD_WRITE_ENABLE		0x0d
+#define AX_CMD_WRITE_DISABLE		0x0e
 #define AX_CMD_WRITE_RX_CTL		0x10
 #define AX_CMD_READ_IPG012		0x11
 #define AX_CMD_WRITE_IPG0		0x12
@@ -447,6 +449,10 @@
 #define AX_CMD_READ_MONITOR_MODE	0x1c
 #define AX_CMD_WRITE_MONITOR_MODE	0x1d
 #define AX_CMD_WRITE_GPIOS		0x1f
+#define AX_CMD_SW_RESET			0x20
+#define AX_CMD_SW_PHY_STATUS		0x21
+#define AX_CMD_SW_PHY_SELECT		0x22
+#define AX88772_CMD_READ_NODE_ID	0x13
 
 #define AX_MONITOR_MODE			0x01
 #define AX_MONITOR_LINK			0x02
@@ -458,6 +464,23 @@
 
 #define AX_INTERRUPT_BUFSIZE		8
 
+#define AX_EEPROM_LEN			0x40
+
+#define AX_SWRESET_CLEAR		0x00
+#define AX_SWRESET_RR			0x01
+#define AX_SWRESET_RT			0x02
+#define AX_SWRESET_PRTE			0x04
+#define AX_SWRESET_PRL			0x08
+#define AX_SWRESET_BZ			0x10
+#define AX_SWRESET_IPRL			0x20
+#define AX_SWRESET_IPPD			0x40
+
+#define AX88772_IPG0_DEFAULT		0x15
+#define AX88772_IPG1_DEFAULT		0x0c
+#define AX88772_IPG2_DEFAULT		0x12
+
+#define AX_EEPROM_MAGIC			0xdeadbeef
+
 /* This structure cannot exceed sizeof(unsigned long [5]) AKA 20 bytes */
 struct ax8817x_data {
 	u8 multi_filter[AX_MCAST_FILTER_SIZE];
@@ -477,7 +500,7 @@
 		index,
 		data,
 		size,
-		CONTROL_TIMEOUT_JIFFIES);
+		CONTROL_TIMEOUT_MS);
 }
 
 static int ax8817x_write_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index,
@@ -492,7 +515,7 @@
 		index,
 		data,
 		size,
-		CONTROL_TIMEOUT_JIFFIES);
+		CONTROL_TIMEOUT_MS);
 }
 
 static void ax8817x_async_cmd_callback(struct urb *urb, struct pt_regs *regs)
@@ -514,18 +537,16 @@
 	int link;
 
 	if (urb->status < 0) {
-		printk(KERN_DEBUG "ax8817x_interrupt_complete() failed with %d",
+		devdbg(dev,"ax8817x_interrupt_complete() failed with %d",
 			urb->status);
 	} else {
-		if (data->int_buf[5] == 0x90) {
-			link = data->int_buf[2] & 0x01;
-			if (netif_carrier_ok(dev->net) != link) {
-				if (link)
-					netif_carrier_on(dev->net);
-				else
-					netif_carrier_off(dev->net);
-				devdbg(dev, "ax8817x - Link Status is: %d", link);
-			}
+		link = data->int_buf[2] & 0x01;
+		if (netif_carrier_ok(dev->net) != link) {
+			if (link)
+				netif_carrier_on(dev->net);
+			else
+				netif_carrier_off(dev->net);
+			devdbg(dev, "ax8817x - Link Status is: %d", link);
 		}
 		usb_submit_urb(data->int_urb, GFP_ATOMIC);
 	}
@@ -674,6 +695,11 @@
 	return 0;
 }
 
+static int ax8817x_get_eeprom_len(struct net_device *net)
+{
+	return AX_EEPROM_LEN;
+}
+
 static int ax8817x_get_eeprom(struct net_device *net,
 			      struct ethtool_eeprom *eeprom, u8 *data)
 {
@@ -687,13 +713,15 @@
 	if (eeprom->len % 2)
 		return -EINVAL;
 
+	eeprom->magic = AX_EEPROM_MAGIC;
+
 	/* ax8817x returns 2 bytes from eeprom on read */
 	for (i=0; i < eeprom->len / 2; i++) {
 		if (ax8817x_read_cmd(dev, AX_CMD_READ_EEPROM, 
 			eeprom->offset + i, 0, 2, &ebuf[i]) < 0)
 			return -EINVAL;
 	}
-	return i * 2;
+	return 0;
 }
 
 static void ax8817x_get_drvinfo (struct net_device *net,
@@ -728,6 +756,7 @@
 	.set_msglevel		= usbnet_set_msglevel,
 	.get_wol		= ax8817x_get_wol,
 	.set_wol		= ax8817x_set_wol,
+	.get_eeprom_len		= ax8817x_get_eeprom_len,
 	.get_eeprom		= ax8817x_get_eeprom,
 	.get_settings		= ax8817x_get_settings,
 	.set_settings		= ax8817x_set_settings,
@@ -735,27 +764,26 @@
 
 static int ax8817x_bind(struct usbnet *dev, struct usb_interface *intf)
 {
-	int ret;
-	u8 buf[6];
+	int ret = 0;
+	void *buf;
 	int i;
 	unsigned long gpio_bits = dev->driver_info->data;
 	struct ax8817x_data *data = (struct ax8817x_data *)dev->data;
 
-	dev->in = usb_rcvbulkpipe(dev->udev, 3);
-	dev->out = usb_sndbulkpipe(dev->udev, 2);
+	get_endpoints(dev,intf);
 
-	// allocate irq urb
 	if ((data->int_urb = usb_alloc_urb (0, GFP_KERNEL)) == NULL) {
 		dbg ("%s: cannot allocate interrupt URB",
 			dev->net->name);
-		return -ENOMEM;
+		ret = -ENOMEM;
+		goto out1;
 	}
 	
 	if ((data->int_buf = kmalloc(AX_INTERRUPT_BUFSIZE, GFP_KERNEL)) == NULL) {
 		dbg ("%s: cannot allocate memory for interrupt buffer",
 			dev->net->name);
-		usb_free_urb(data->int_urb);
-		return -ENOMEM;
+		ret = -ENOMEM;
+		goto out1;
 	}
 	memset(data->int_buf, 0, AX_INTERRUPT_BUFSIZE);
 
@@ -765,36 +793,43 @@
 		ax8817x_interrupt_complete, dev,
 		dev->udev->speed == USB_SPEED_HIGH ? 8 : 100);
 
+	buf = kmalloc(ETH_ALEN, GFP_KERNEL);
+	if(!buf) {
+		ret = -ENOMEM;
+		goto out2;
+	}
+
 	/* Toggle the GPIOs in a manufacturer/model specific way */
 	for (i = 2; i >= 0; i--) {
 		if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_GPIOS,
 					(gpio_bits >> (i * 8)) & 0xff, 0, 0,
 					buf)) < 0)
-			return ret;
+			goto out3;
 		msleep(5);
 	}
 
 	if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_RX_CTL, 0x80, 0, 0, buf)) < 0) {
 		dbg("send AX_CMD_WRITE_RX_CTL failed: %d", ret);
-		return ret;
+		goto out3;
 	}
 
 	/* Get the MAC address */
 	memset(buf, 0, ETH_ALEN);
 	if ((ret = ax8817x_read_cmd(dev, AX_CMD_READ_NODE_ID, 0, 0, 6, buf)) < 0) {
 		dbg("read AX_CMD_READ_NODE_ID failed: %d", ret);
-		return ret;
+		goto out3;
 	}
 	memcpy(dev->net->dev_addr, buf, ETH_ALEN);
 
 	/* Get the PHY id */
 	if ((ret = ax8817x_read_cmd(dev, AX_CMD_READ_PHY_ID, 0, 0, 2, buf)) < 0) {
 		dbg("error on read AX_CMD_READ_PHY_ID: %02x", ret);
-		return ret;
+		goto out3;
 	} else if (ret < 2) {
 		/* this should always return 2 bytes */
 		dbg("AX_CMD_READ_PHY_ID returned less than 2 bytes: ret=%02x", ret);
-		return -EIO;
+		ret = -EIO;
+		goto out3;
 	}
 
 	/* Initialize MII structure */
@@ -803,7 +838,7 @@
 	dev->mii.mdio_write = ax8817x_mdio_write;
 	dev->mii.phy_id_mask = 0x3f;
 	dev->mii.reg_num_mask = 0x1f;
-	dev->mii.phy_id = buf[1];
+	dev->mii.phy_id = *((u8 *)buf + 1);
 
 	dev->net->set_multicast_list = ax8817x_set_multicast;
 	dev->net->ethtool_ops = &ax8817x_ethtool_ops;
@@ -816,11 +851,17 @@
 
 	if((ret = usb_submit_urb(data->int_urb, GFP_KERNEL)) < 0) {
 		dbg("Failed to submit interrupt URB: %02x", ret);
-		usb_free_urb(data->int_urb);
-		return ret;
+		goto out2;
 	}
 
 	return 0;
+out3:
+	kfree(buf);
+out2:
+	kfree(data->int_buf);
+out1:
+	usb_free_urb(data->int_urb);
+	return ret;
 }
 
 static void ax8817x_unbind(struct usbnet *dev, struct usb_interface *intf)
@@ -832,6 +873,290 @@
 	kfree(data->int_buf);
 }
 
+static struct ethtool_ops ax88772_ethtool_ops = {
+	.get_drvinfo		= ax8817x_get_drvinfo,
+	.get_link		= ethtool_op_get_link,
+	.get_msglevel		= usbnet_get_msglevel,
+	.set_msglevel		= usbnet_set_msglevel,
+	.get_wol		= ax8817x_get_wol,
+	.set_wol		= ax8817x_set_wol,
+	.get_eeprom_len		= ax8817x_get_eeprom_len,
+	.get_eeprom		= ax8817x_get_eeprom,
+	.get_settings		= ax8817x_get_settings,
+	.set_settings		= ax8817x_set_settings,
+};
+
+static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf)
+{
+	int ret;
+	void *buf;
+	struct ax8817x_data *data = (struct ax8817x_data *)dev->data;
+
+	get_endpoints(dev,intf);
+
+	if ((data->int_urb = usb_alloc_urb (0, GFP_KERNEL)) == 0) {
+		dbg ("Cannot allocate interrupt URB");
+		ret = -ENOMEM;
+		goto out1;
+	}
+	
+	if ((data->int_buf = kmalloc(AX_INTERRUPT_BUFSIZE, GFP_KERNEL)) == NULL) {
+		dbg ("Cannot allocate memory for interrupt buffer");
+		ret = -ENOMEM;
+		goto out1;
+	}
+	memset(data->int_buf, 0, AX_INTERRUPT_BUFSIZE);
+
+	usb_fill_int_urb (data->int_urb, dev->udev,
+		usb_rcvintpipe (dev->udev, 1),
+		data->int_buf, AX_INTERRUPT_BUFSIZE,
+		ax8817x_interrupt_complete, dev,
+		dev->udev->speed == USB_SPEED_HIGH ? 8 : 100);
+
+	buf = kmalloc(6, GFP_KERNEL);
+	if(!buf) {
+		dbg ("Cannot allocate memory for buffer");
+		ret = -ENOMEM;
+		goto out2;
+	}
+
+	if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_GPIOS,
+				     0x00B0, 0, 0, buf)) < 0)
+		goto out3;
+
+	msleep(5);
+	if ((ret = ax8817x_write_cmd(dev, AX_CMD_SW_PHY_SELECT, 0x0001, 0, 0, buf)) < 0) {
+		dbg("Select PHY #1 failed: %d", ret);
+		goto out3;
+	}
+
+	if ((ret =
+	     ax8817x_write_cmd(dev, AX_CMD_SW_RESET, AX_SWRESET_IPPD, 0, 0, buf)) < 0) {
+		dbg("Failed to power down internal PHY: %d", ret);
+		goto out3;
+	}
+
+	msleep(150);
+	if ((ret =
+	     ax8817x_write_cmd(dev, AX_CMD_SW_RESET, AX_SWRESET_CLEAR, 0, 0, buf)) < 0) {
+		dbg("Failed to perform software reset: %d", ret);
+		goto out3;
+	}
+
+	msleep(150);
+	if ((ret =
+	     ax8817x_write_cmd(dev, AX_CMD_SW_RESET, AX_SWRESET_IPRL | AX_SWRESET_PRL, 0, 0, buf)) < 0) {
+		dbg("Failed to set Internal/External PHY reset control: %d", ret);
+		goto out3;
+	}
+
+	msleep(150);
+	if ((ret =
+	     ax8817x_write_cmd(dev, AX_CMD_WRITE_RX_CTL, 0x0000, 0, 0,
+			       buf)) < 0) {
+		dbg("Failed to reset RX_CTL: %d", ret);
+		goto out3;
+	}
+
+	/* Get the MAC address */
+	memset(buf, 0, ETH_ALEN);
+	if ((ret = ax8817x_read_cmd(dev, AX88772_CMD_READ_NODE_ID, 0, 0, ETH_ALEN, buf)) < 0) {
+		dbg("Failed to read MAC address: %d", ret);
+		goto out3;
+	}
+	memcpy(dev->net->dev_addr, buf, ETH_ALEN);
+
+	if ((ret = ax8817x_write_cmd(dev, AX_CMD_SET_SW_MII, 0, 0, 0, buf)) < 0) {
+		dbg("Enabling software MII failed: %d", ret);
+		goto out3;
+	}
+
+	if (((ret =
+	      ax8817x_read_cmd(dev, AX_CMD_READ_MII_REG, 0x0010, 2, 2, buf)) < 0)
+	    || (*((u16 *)buf) != 0x003b)) {
+		dbg("Read PHY register 2 must be 0x3b00: %d", ret);
+		goto out3;
+	}
+
+	/* Initialize MII structure */
+	dev->mii.dev = dev->net;
+	dev->mii.mdio_read = ax8817x_mdio_read;
+	dev->mii.mdio_write = ax8817x_mdio_write;
+	dev->mii.phy_id_mask = 0xff;
+	dev->mii.reg_num_mask = 0xff;
+
+	/* Get the PHY id */
+	if ((ret = ax8817x_read_cmd(dev, AX_CMD_READ_PHY_ID, 0, 0, 2, buf)) < 0) {
+		dbg("Error reading PHY ID: %02x", ret);
+		goto out3;
+	} else if (ret < 2) {
+		/* this should always return 2 bytes */
+		dbg("AX_CMD_READ_PHY_ID returned less than 2 bytes: ret=%02x",
+		    ret);
+		ret = -EIO;
+		goto out3;
+	}
+	dev->mii.phy_id = *((u8 *)buf + 1);
+
+	if ((ret =
+	     ax8817x_write_cmd(dev, AX_CMD_SW_RESET, AX_SWRESET_PRL, 0, 0, buf)) < 0) {
+		dbg("Set external PHY reset pin level: %d", ret);
+		goto out3;
+	}
+	msleep(150);
+	if ((ret =
+	     ax8817x_write_cmd(dev, AX_CMD_SW_RESET, AX_SWRESET_IPRL | AX_SWRESET_PRL, 0, 0, buf)) < 0) {
+		dbg("Set Internal/External PHY reset control: %d", ret);
+		goto out3;
+	}
+	msleep(150);
+
+
+	dev->net->set_multicast_list = ax8817x_set_multicast;
+	dev->net->ethtool_ops = &ax88772_ethtool_ops;
+
+	ax8817x_mdio_write(dev->net, dev->mii.phy_id, MII_BMCR,
+			cpu_to_le16(BMCR_RESET));
+	ax8817x_mdio_write(dev->net, dev->mii.phy_id, MII_ADVERTISE,
+			cpu_to_le16(ADVERTISE_ALL | ADVERTISE_CSMA));
+	mii_nway_restart(&dev->mii);
+
+	if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_MEDIUM_MODE, 0x0336, 0, 0, buf)) < 0) {
+		dbg("Write medium mode register: %d", ret);
+		goto out3;
+	}
+
+	if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_IPG0, AX88772_IPG0_DEFAULT | AX88772_IPG1_DEFAULT,AX88772_IPG2_DEFAULT, 0, buf)) < 0) {
+		dbg("Write IPG,IPG1,IPG2 failed: %d", ret);
+		goto out3;
+	}
+	if ((ret =
+	     ax8817x_write_cmd(dev, AX_CMD_SET_HW_MII, 0, 0, 0, &buf)) < 0) {
+		dbg("Failed to set hardware MII: %02x", ret);
+		goto out3;
+	}
+
+	/* Set RX_CTL to default values with 2k buffer, and enable cactus */
+	if ((ret =
+	     ax8817x_write_cmd(dev, AX_CMD_WRITE_RX_CTL, 0x0088, 0, 0,
+			       buf)) < 0) {
+		dbg("Reset RX_CTL failed: %d", ret);
+		goto out3;
+	}
+
+	if((ret = usb_submit_urb(data->int_urb, GFP_KERNEL)) < 0) {
+		dbg("Failed to submit interrupt URB: %02x", ret);
+		goto out3;
+	}
+
+	kfree(buf);
+
+	return 0;
+
+out3:
+	kfree(buf);
+out2:
+	kfree(data->int_buf);
+out1:
+	usb_free_urb(data->int_urb);
+
+	return ret;
+}
+
+static int ax88772_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
+{
+	u32 *header;
+	char *packet;
+	struct sk_buff *ax_skb;
+	u16 size;
+
+	header = (u32 *) skb->data;
+	le32_to_cpus(header);
+	packet = (char *)(header + 1);
+
+	skb_pull(skb, 4);
+
+	while (skb->len > 0) {
+		if ((short)(*header & 0x0000ffff) !=
+		    ~((short)((*header & 0xffff0000) >> 16))) {
+			devdbg(dev,"header length data is error");
+		}
+		/* get the packet length */
+		size = (u16) (*header & 0x0000ffff);
+
+		if ((skb->len) - ((size + 1) & 0xfffe) == 0)
+			return 2;
+		if (size > ETH_FRAME_LEN) {
+			devdbg(dev,"invalid rx length %d", size);
+			return 0;
+		}
+		ax_skb = skb_clone(skb, GFP_ATOMIC);
+		if (ax_skb) {
+			ax_skb->len = size;
+			ax_skb->data = packet;
+			ax_skb->tail = packet + size;
+			skb_return(dev, ax_skb);
+		} else {
+			return 0;
+		}
+
+		skb_pull(skb, (size + 1) & 0xfffe);
+
+		if (skb->len == 0)
+			break;
+
+		header = (u32 *) skb->data;
+		le32_to_cpus(header);
+		packet = (char *)(header + 1);
+		skb_pull(skb, 4);
+	}
+
+	if (skb->len < 0) {
+		devdbg(dev,"invalid rx length %d", skb->len);
+		return 0;
+	}
+	return 1;
+}
+
+static struct sk_buff *ax88772_tx_fixup(struct usbnet *dev, struct sk_buff *skb,
+					int flags)
+{
+	int padlen;
+	int headroom = skb_headroom(skb);
+	int tailroom = skb_tailroom(skb);
+	u32 *packet_len;
+	u32 *padbytes_ptr;
+
+	padlen = ((skb->len + 4) % 512) ? 0 : 4;
+
+	if ((!skb_cloned(skb))
+	    && ((headroom + tailroom) >= (4 + padlen))) {
+		if ((headroom < 4) || (tailroom < padlen)) {
+			skb->data = memmove(skb->head + 4, skb->data, skb->len);
+			skb->tail = skb->data + skb->len;
+		}
+	} else {
+		struct sk_buff *skb2;
+		skb2 = skb_copy_expand(skb, 4, padlen, flags);
+		dev_kfree_skb_any(skb);
+		skb = skb2;
+		if (!skb)
+			return NULL;
+	}
+
+	packet_len = (u32 *) skb_push(skb, 4);
+
+	packet_len = (u32 *) skb->data;
+	*packet_len = (((skb->len - 4) ^ 0x0000ffff) << 16) + (skb->len - 4);
+
+	if ((skb->len % 512) == 0) {
+		padbytes_ptr = (u32 *) skb->tail;
+		*padbytes_ptr = 0xffff0000;
+		skb_put(skb, padlen);
+	}
+	return skb;
+}
+
 static const struct driver_info ax8817x_info = {
 	.description = "ASIX AX8817x USB 2.0 Ethernet",
 	.bind = ax8817x_bind,
@@ -864,6 +1189,16 @@
 	.data = 0x001f1d1f,
 };
 
+static const struct driver_info ax88772_info = {
+	.description = "ASIX AX88772 USB 2.0 Ethernet",
+	.bind = ax88772_bind,
+	.unbind = ax8817x_unbind,
+	.flags = FLAG_ETHER | FLAG_FRAMING_AX,
+	.rx_fixup = ax88772_rx_fixup,
+	.tx_fixup = ax88772_tx_fixup,
+	.data = 0x00130103,
+};
+
 #endif /* CONFIG_USB_AX8817X */
 
 
@@ -911,45 +1246,14 @@
 
 #ifdef	NEED_GENERIC_CDC
 
-/* "Header Functional Descriptor" from CDC spec  5.2.3.1 */
-struct header_desc {
-	u8	bLength;
-	u8	bDescriptorType;
-	u8	bDescriptorSubType;
-
-	u16	bcdCDC;
-} __attribute__ ((packed));
-
-/* "Union Functional Descriptor" from CDC spec 5.2.3.X */
-struct union_desc {
-	u8	bLength;
-	u8	bDescriptorType;
-	u8	bDescriptorSubType;
-
-	u8	bMasterInterface0;
-	u8	bSlaveInterface0;
-	/* ... and there could be other slave interfaces */
-} __attribute__ ((packed));
-
-/* "Ethernet Networking Functional Descriptor" from CDC spec 5.2.3.16 */
-struct ether_desc {
-	u8	bLength;
-	u8	bDescriptorType;
-	u8	bDescriptorSubType;
-
-	u8	iMACAddress;
-	u32	bmEthernetStatistics;
-	__le16	wMaxSegmentSize;
-	__le16	wNumberMCFilters;
-	u8	bNumberPowerFilters;
-} __attribute__ ((packed));
+#include <linux/usb_cdc.h>
 
 struct cdc_state {
-	struct header_desc	*header;
-	struct union_desc	*u;
-	struct ether_desc	*ether;
-	struct usb_interface	*control;
-	struct usb_interface	*data;
+	struct usb_cdc_header_desc	*header;
+	struct usb_cdc_union_desc	*u;
+	struct usb_cdc_ether_desc	*ether;
+	struct usb_interface		*control;
+	struct usb_interface		*data;
 };
 
 static struct usb_driver usbnet_driver;
@@ -1004,7 +1308,7 @@
 		 * CDC Ethernet achieves with a simple descriptor.
 		 */
 		switch (buf [2]) {
-		case 0x00:		/* Header, mostly useless */
+		case USB_CDC_HEADER_TYPE:
 			if (info->header) {
 				dev_dbg (&intf->dev, "extra CDC header\n");
 				goto bad_desc;
@@ -1016,7 +1320,7 @@
 				goto bad_desc;
 			}
 			break;
-		case 0x06:		/* Union (groups interfaces) */
+		case USB_CDC_UNION_TYPE:
 			if (info->u) {
 				dev_dbg (&intf->dev, "extra CDC union\n");
 				goto bad_desc;
@@ -1065,7 +1369,7 @@
 				goto bad_desc;
 			}
 			break;
-		case 0x0F:		/* Ethernet Networking */
+		case USB_CDC_ETHERNET_TYPE:
 			if (info->ether) {
 				dev_dbg (&intf->dev, "extra CDC ether\n");
 				goto bad_desc;
@@ -1169,7 +1473,7 @@
 }
 
 static inline int
-get_ethernet_addr (struct usbnet *dev, struct ether_desc *e)
+get_ethernet_addr (struct usbnet *dev, struct usb_cdc_ether_desc *e)
 {
 	int 		tmp, i;
 	unsigned char	buf [13];
@@ -1321,7 +1625,7 @@
 		      0,			// index
 		      0,			// data buffer
 		      0,			// size
-		      CONTROL_TIMEOUT_JIFFIES);
+		      CONTROL_TIMEOUT_MS);
 	return retval;
 }
 
@@ -1602,9 +1906,9 @@
  */
 
 struct nc_header {		// packed:
-	u16	hdr_len;		// sizeof nc_header (LE, all)
-	u16	packet_len;		// payload size (including ethhdr)
-	u16	packet_id;		// detects dropped packets
+	__le16	hdr_len;		// sizeof nc_header (LE, all)
+	__le16	packet_len;		// payload size (including ethhdr)
+	__le16	packet_id;		// detects dropped packets
 #define MIN_HEADER	6
 
 	// all else is optional, and must start with:
@@ -1615,7 +1919,7 @@
 #define	PAD_BYTE	((unsigned char)0xAC)
 
 struct nc_trailer {
-	u16	packet_id;
+	__le16	packet_id;
 } __attribute__((__packed__));
 
 // packets may use FLAG_FRAMING_NC and optional pad
@@ -1658,7 +1962,7 @@
 		USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
 		0, regnum,
 		retval_ptr, sizeof *retval_ptr,
-		CONTROL_TIMEOUT_JIFFIES);
+		CONTROL_TIMEOUT_MS);
 	if (status > 0)
 		status = 0;
 	if (!status)
@@ -1682,7 +1986,7 @@
 		USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
 		value, regnum,
 		NULL, 0,			// data is in setup packet
-		CONTROL_TIMEOUT_JIFFIES);
+		CONTROL_TIMEOUT_MS);
 }
 
 static inline void
@@ -1973,6 +2277,7 @@
 {
 	struct nc_header	*header;
 	struct nc_trailer	*trailer;
+	u16			hdr_len, packet_len;
 
 	if (!(skb->len & 0x01)
 			|| MIN_FRAMED > skb->len
@@ -1986,50 +2291,50 @@
 	}
 
 	header = (struct nc_header *) skb->data;
-	le16_to_cpus (&header->hdr_len);
-	le16_to_cpus (&header->packet_len);
-	if (FRAMED_SIZE (header->packet_len) > MAX_PACKET) {
+	hdr_len = le16_to_cpup (&header->hdr_len);
+	packet_len = le16_to_cpup (&header->packet_len);
+	if (FRAMED_SIZE (packet_len) > MAX_PACKET) {
 		dev->stats.rx_frame_errors++;
-		dbg ("packet too big, %d", header->packet_len);
+		dbg ("packet too big, %d", packet_len);
 		nc_ensure_sync (dev);
 		return 0;
-	} else if (header->hdr_len < MIN_HEADER) {
+	} else if (hdr_len < MIN_HEADER) {
 		dev->stats.rx_frame_errors++;
-		dbg ("header too short, %d", header->hdr_len);
+		dbg ("header too short, %d", hdr_len);
 		nc_ensure_sync (dev);
 		return 0;
-	} else if (header->hdr_len > MIN_HEADER) {
+	} else if (hdr_len > MIN_HEADER) {
 		// out of band data for us?
-		dbg ("header OOB, %d bytes",
-			header->hdr_len - MIN_HEADER);
+		dbg ("header OOB, %d bytes", hdr_len - MIN_HEADER);
 		nc_ensure_sync (dev);
 		// switch (vendor/product ids) { ... }
 	}
-	skb_pull (skb, header->hdr_len);
+	skb_pull (skb, hdr_len);
 
 	trailer = (struct nc_trailer *)
 		(skb->data + skb->len - sizeof *trailer);
 	skb_trim (skb, skb->len - sizeof *trailer);
 
-	if ((header->packet_len & 0x01) == 0) {
-		if (skb->data [header->packet_len] != PAD_BYTE) {
+	if ((packet_len & 0x01) == 0) {
+		if (skb->data [packet_len] != PAD_BYTE) {
 			dev->stats.rx_frame_errors++;
 			dbg ("bad pad");
 			return 0;
 		}
 		skb_trim (skb, skb->len - 1);
 	}
-	if (skb->len != header->packet_len) {
+	if (skb->len != packet_len) {
 		dev->stats.rx_frame_errors++;
 		dbg ("bad packet len %d (expected %d)",
-			skb->len, header->packet_len);
+			skb->len, packet_len);
 		nc_ensure_sync (dev);
 		return 0;
 	}
 	if (header->packet_id != get_unaligned (&trailer->packet_id)) {
 		dev->stats.rx_fifo_errors++;
 		dbg ("(2+ dropped) rx packet_id mismatch 0x%x 0x%x",
-			header->packet_id, trailer->packet_id);
+			le16_to_cpu (header->packet_id),
+			le16_to_cpu (trailer->packet_id));
 		return 0;
 	}
 #if 0
@@ -2125,7 +2430,7 @@
 		USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
 		val, index,
 		NULL, 0,
-		CONTROL_TIMEOUT_JIFFIES);
+		CONTROL_TIMEOUT_MS);
 }
 
 static inline int
@@ -2402,14 +2707,20 @@
 		size = RNDIS_MAX_TRANSFER;
 	else
 #endif
+#ifdef CONFIG_USB_AX8817X
+	if (dev->driver_info->flags & FLAG_FRAMING_AX)
+		size = 2048;
+	else
+#endif
 		size = (sizeof (struct ethhdr) + dev->net->mtu);
 
-	if ((skb = alloc_skb (size, flags)) == NULL) {
+	if ((skb = alloc_skb (size + NET_IP_ALIGN, flags)) == NULL) {
 		devdbg (dev, "no rx skb");
 		defer_kevent (dev, EVENT_RX_MEMORY);
 		usb_free_urb (urb);
 		return;
 	}
+	skb_reserve (skb, NET_IP_ALIGN);
 
 	entry = (struct skb_data *) skb->cb;
 	entry->urb = urb;
@@ -2677,6 +2988,8 @@
 			framing = "Zaurus";
 		else if (dev->driver_info->flags & FLAG_FRAMING_RN)
 			framing = "RNDIS";
+		else if (dev->driver_info->flags & FLAG_FRAMING_AX)
+			framing = "ASIX";
 		else
 			framing = "simple";
 
@@ -3197,6 +3510,32 @@
 	return status;
 }
 
+/*-------------------------------------------------------------------------*/
+
+#ifdef	CONFIG_PM
+
+static int usbnet_suspend (struct usb_interface *intf, u32 state)
+{
+	struct usbnet		*dev = usb_get_intfdata(intf);
+	
+	netif_device_detach (dev->net);
+	return 0;
+}
+
+static int usbnet_resume (struct usb_interface *intf)
+{
+	struct usbnet		*dev = usb_get_intfdata(intf);
+
+	netif_device_attach (dev->net);
+	return 0;
+}
+
+#else	/* !CONFIG_PM */
+
+#define	usbnet_suspend	NULL
+#define	usbnet_resume	NULL
+
+#endif	/* CONFIG_PM */
 
 /*-------------------------------------------------------------------------*/
 
@@ -3290,6 +3629,10 @@
 	// goodway corp usb gwusb2e
 	USB_DEVICE (0x1631, 0x6200),
 	.driver_info = (unsigned long) &ax8817x_info,
+}, {
+	// ASIX AX88772 10/100
+        USB_DEVICE (0x0b95, 0x7720),
+        .driver_info = (unsigned long) &ax88772_info,
 },
 #endif
 
@@ -3374,6 +3717,7 @@
 	.driver_info =	(unsigned long) &blob_info,
 }, {
 	// Linux Ethernet/RNDIS gadget on pxa210/25x/26x
+	// e.g. Gumstix, current OpenZaurus, ...
 	USB_DEVICE_VER (0x0525, 0xa4a2, 0x0203, 0x0203),
 	.driver_info =	(unsigned long) &linuxdev_info,
 }, 
@@ -3386,72 +3730,64 @@
  *
  * PXA-2xx based models are also lying-about-cdc.
  *
+ * NOTE:  OpenZaurus versions with 2.6 kernels won't use these entries,
+ * unlike the older ones with 2.4 "embedix" kernels.
+ *
  * NOTE:  These entries do double-duty, serving as blacklist entries
  * whenever Zaurus support isn't enabled, but CDC Ethernet is.
  */
+#define	ZAURUS_MASTER_INTERFACE \
+	.bInterfaceClass	= USB_CLASS_COMM, \
+	.bInterfaceSubClass	= USB_CDC_SUBCLASS_ETHERNET, \
+	.bInterfaceProtocol	= USB_CDC_PROTO_NONE
 {
 	.match_flags	=   USB_DEVICE_ID_MATCH_INT_INFO
 			  | USB_DEVICE_ID_MATCH_DEVICE, 
 	.idVendor		= 0x04DD,
 	.idProduct		= 0x8004,
-	/* match the master interface */
-	.bInterfaceClass	= USB_CLASS_COMM,
-	.bInterfaceSubClass	= 6 /* Ethernet model */,
-	.bInterfaceProtocol	= 0,
+	ZAURUS_MASTER_INTERFACE,
 	.driver_info = ZAURUS_STRONGARM_INFO,
 }, {
 	.match_flags	=   USB_DEVICE_ID_MATCH_INT_INFO
 			  | USB_DEVICE_ID_MATCH_DEVICE, 
 	.idVendor		= 0x04DD,
 	.idProduct		= 0x8005,	/* A-300 */
-	.bInterfaceClass	= USB_CLASS_COMM,
-	.bInterfaceSubClass	= 6 /* Ethernet model */,
-	.bInterfaceProtocol	= 0x00,
+	ZAURUS_MASTER_INTERFACE,
 	.driver_info = ZAURUS_PXA_INFO,
 }, {
 	.match_flags	=   USB_DEVICE_ID_MATCH_INT_INFO
 			  | USB_DEVICE_ID_MATCH_DEVICE, 
 	.idVendor		= 0x04DD,
 	.idProduct		= 0x8006,	/* B-500/SL-5600 */
-	.bInterfaceClass	= USB_CLASS_COMM,
-	.bInterfaceSubClass	= 6 /* Ethernet model */,
-	.bInterfaceProtocol	= 0x00,
+	ZAURUS_MASTER_INTERFACE,
 	.driver_info = ZAURUS_PXA_INFO,
 }, {
 	.match_flags    =   USB_DEVICE_ID_MATCH_INT_INFO
 	          | USB_DEVICE_ID_MATCH_DEVICE,
 	.idVendor		= 0x04DD,
 	.idProduct		= 0x8007,	/* C-700 */
-	.bInterfaceClass	= USB_CLASS_COMM,
-	.bInterfaceSubClass	= 6 /* Ethernet model */,
-	.bInterfaceProtocol = 0x00,
+	ZAURUS_MASTER_INTERFACE,
 	.driver_info = ZAURUS_PXA_INFO,
 }, {
 	.match_flags    =   USB_DEVICE_ID_MATCH_INT_INFO
 		 | USB_DEVICE_ID_MATCH_DEVICE,
 	.idVendor               = 0x04DD,
 	.idProduct              = 0x9031,	/* C-750 C-760 */
-	.bInterfaceClass	= USB_CLASS_COMM,
-	.bInterfaceSubClass	= 6 /* Ethernet model */,
-	.bInterfaceProtocol     = 0x00,
+	ZAURUS_MASTER_INTERFACE,
 	.driver_info = ZAURUS_PXA_INFO,
 }, {
 	.match_flags    =   USB_DEVICE_ID_MATCH_INT_INFO
 		 | USB_DEVICE_ID_MATCH_DEVICE,
 	.idVendor               = 0x04DD,
 	.idProduct              = 0x9032,	/* SL-6000 */
-	.bInterfaceClass	= USB_CLASS_COMM,
-	.bInterfaceSubClass	= 6 /* Ethernet model */,
-	.bInterfaceProtocol     = 0x00,
+	ZAURUS_MASTER_INTERFACE,
 	.driver_info = ZAURUS_PXA_INFO,
 }, {
 	.match_flags    =   USB_DEVICE_ID_MATCH_INT_INFO
 		 | USB_DEVICE_ID_MATCH_DEVICE,
 	.idVendor               = 0x04DD,
 	.idProduct              = 0x9050,	/* C-860 */
-	.bInterfaceClass	= USB_CLASS_COMM,
-	.bInterfaceSubClass	= 6 /* Ethernet model */,
-	.bInterfaceProtocol     = 0x00,
+	ZAURUS_MASTER_INTERFACE,
 	.driver_info = ZAURUS_PXA_INFO,
 },
 
@@ -3463,9 +3799,7 @@
 		 | USB_DEVICE_ID_MATCH_DEVICE,
 	.idVendor               = 0x07B4,
 	.idProduct              = 0x0F02,	/* R-1000 */
-	.bInterfaceClass	= USB_CLASS_COMM,
-	.bInterfaceSubClass	= 6 /* Ethernet model */,
-	.bInterfaceProtocol     = 0x00,
+	ZAURUS_MASTER_INTERFACE,
 	.driver_info = OLYMPUS_MXL_INFO,
 },
 #endif
@@ -3480,7 +3814,8 @@
 	 * NOTE:  this match must come AFTER entries working around
 	 * bugs/quirks in a given product (like Zaurus, above).
 	 */
-	USB_INTERFACE_INFO (USB_CLASS_COMM, 6 /* Ethernet model */, 0),
+	USB_INTERFACE_INFO (USB_CLASS_COMM, USB_CDC_SUBCLASS_ETHERNET,
+			USB_CDC_PROTO_NONE),
 	.driver_info = (unsigned long) &cdc_info,
 },
 #endif
@@ -3495,6 +3830,8 @@
 	.id_table =	products,
 	.probe =	usbnet_probe,
 	.disconnect =	usbnet_disconnect,
+	.suspend =	usbnet_suspend,
+	.resume =	usbnet_resume,
 };
 
 /* Default ethtool_ops assigned.  Devices can override in their bind() routine */
diff -Nru a/drivers/usb/net/zd1201.c b/drivers/usb/net/zd1201.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/usb/net/zd1201.c	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,1905 @@
+/*
+ *	Driver for ZyDAS zd1201 based wireless USB devices.
+ *
+ *	Copyright (c) 2004, 2005 Jeroen Vreeken (pe1rxq@amsat.org)
+ *
+ *	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.
+ *
+ *	Parts of this driver have been derived from a wlan-ng version
+ *	modified by ZyDAS. They also made documentation available, thanks!
+ *	Copyright (C) 1999 AbsoluteValue Systems, Inc.  All Rights Reserved.
+ */
+
+#include <linux/module.h>
+#include <linux/usb.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/wireless.h>
+#include <net/iw_handler.h>
+#include <linux/string.h>
+#include <linux/if_arp.h>
+#include <linux/firmware.h>
+#include <ieee802_11.h>
+#include "zd1201.h"
+
+static struct usb_device_id zd1201_table[] = {
+	{USB_DEVICE(0x0586, 0x3400)}, /* Peabird Wireless USB Adapter */
+	{USB_DEVICE(0x0ace, 0x1201)}, /* ZyDAS ZD1201 Wireless USB Adapter */
+	{USB_DEVICE(0x050d, 0x6051)}, /* Belkin F5D6051 usb  adapter */
+	{USB_DEVICE(0x0db0, 0x6823)}, /* MSI UB11B usb  adapter */
+	{}
+};
+
+static int ap = 0;	/* Are we an AP or a normal station? */
+
+#define ZD1201_VERSION	"0.15"
+
+MODULE_AUTHOR("Jeroen Vreeken <pe1rxq@amsat.org>");
+MODULE_DESCRIPTION("Driver for ZyDAS ZD1201 based USB Wireless adapters");
+MODULE_VERSION(ZD1201_VERSION);
+MODULE_LICENSE("GPL");
+module_param(ap, int, 0);
+MODULE_PARM_DESC(ap, "If non-zero Access Point firmware will be loaded");
+MODULE_DEVICE_TABLE(usb, zd1201_table);
+
+
+int zd1201_fw_upload(struct usb_device *dev, int apfw)
+{
+	const struct firmware *fw_entry;
+	char* data;
+	unsigned long len;
+	int err;
+	unsigned char ret;
+	char *buf;
+	char *fwfile;
+
+	if (apfw)
+		fwfile = "zd1201-ap.fw";
+	else
+		fwfile = "zd1201.fw";
+
+	err = request_firmware(&fw_entry, fwfile, &dev->dev);
+	if (err) {
+		dev_err(&dev->dev, "Failed to load %s firmware file!\n", fwfile);
+		dev_err(&dev->dev, "Make sure the hotplug firmware loader is installed.\n");
+		dev_err(&dev->dev, "Goto http://linux-lc100020.sourceforge.net for more info\n");
+		return err;
+	}
+
+	data = fw_entry->data;
+        len = fw_entry->size;
+
+	buf = kmalloc(1024, GFP_ATOMIC);
+	if (!buf)
+		goto exit;
+	
+	while (len > 0) {
+		int translen = (len > 1024) ? 1024 : len;
+		memcpy(buf, data, translen);
+
+		err = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), 0,
+		    USB_DIR_OUT | 0x40, 0, 0, buf, translen,
+		    ZD1201_FW_TIMEOUT);
+		if (err < 0)
+			goto exit;
+
+		len -= translen;
+		data += translen;
+	}
+                                        
+	err = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), 0x2,
+	    USB_DIR_OUT | 0x40, 0, 0, NULL, 0, ZD1201_FW_TIMEOUT);
+	if (err < 0)
+		goto exit;
+                                                                                                                                                                
+	err = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), 0x4,
+	    USB_DIR_IN | 0x40, 0,0, &ret, sizeof(ret), ZD1201_FW_TIMEOUT);
+	if (err < 0)
+		goto exit;
+                                                                                                                                                                                                                                                                                        
+	if (ret & 0x80) {
+		err = -EIO;
+		goto exit;
+	}
+
+	err = 0;
+exit:
+ 	if (buf)
+		kfree(buf);
+	release_firmware(fw_entry);
+	return err;
+}
+
+void zd1201_usbfree(struct urb *urb, struct pt_regs *regs)
+{
+	struct zd1201 *zd = urb->context;
+
+	switch(urb->status) {
+		case -EILSEQ:
+		case -ENODEV:
+		case -ETIMEDOUT:
+		case -ENOENT:
+		case -EPIPE:
+		case -EOVERFLOW:
+		case -ESHUTDOWN:
+			dev_warn(&zd->usb->dev, "%s: urb failed: %d\n", 
+			    zd->dev->name, urb->status);
+	}
+
+	kfree(urb->transfer_buffer);
+	usb_free_urb(urb);
+	return;
+}
+
+/* cmdreq message: 
+	u32 type
+	u16 cmd
+	u16 parm0
+	u16 parm1
+	u16 parm2
+	u8  pad[4]
+
+	total: 4 + 2 + 2 + 2 + 2 + 4 = 16
+*/
+int zd1201_docmd(struct zd1201 *zd, int cmd, int parm0, int parm1, int parm2)
+{
+	unsigned char *command;
+	int ret;
+	struct urb *urb;
+
+	command = kmalloc(16, GFP_ATOMIC);
+	if (!command)
+		return -ENOMEM;
+
+	*((__le32*)command) = cpu_to_le32(ZD1201_USB_CMDREQ);
+	*((__le16*)&command[4]) = cpu_to_le16(cmd);
+	*((__le16*)&command[6]) = cpu_to_le16(parm0);
+	*((__le16*)&command[8]) = cpu_to_le16(parm1);
+	*((__le16*)&command[10])= cpu_to_le16(parm2);
+
+	urb = usb_alloc_urb(0, GFP_ATOMIC);
+	if (!urb) {
+		kfree(command);
+		return -ENOMEM;
+	}
+	usb_fill_bulk_urb(urb, zd->usb, usb_sndbulkpipe(zd->usb, zd->endp_out2),
+	     command, 16, zd1201_usbfree, zd);
+	ret = usb_submit_urb(urb, GFP_ATOMIC);
+	if (ret) {
+		kfree(command);
+		usb_free_urb(urb);
+	}
+	
+	return ret;
+}
+
+/* Callback after sending out a packet */
+void zd1201_usbtx(struct urb *urb, struct pt_regs *regs)
+{
+	struct zd1201 *zd = urb->context;
+	netif_wake_queue(zd->dev);
+	return;
+}
+
+/* Incomming data */
+void zd1201_usbrx(struct urb *urb, struct pt_regs *regs)
+{
+	struct zd1201 *zd = urb->context;
+	int free = 0;
+	unsigned char *data = urb->transfer_buffer;
+	struct sk_buff *skb;
+	unsigned char type;
+
+	if (!zd) {
+		free = 1;
+		goto exit;
+	}
+
+	switch(urb->status) {
+		case -EILSEQ:
+		case -ENODEV:
+		case -ETIMEDOUT:
+		case -ENOENT:
+		case -EPIPE:
+		case -EOVERFLOW:
+		case -ESHUTDOWN:
+			dev_warn(&zd->usb->dev, "%s: rx urb failed: %d\n",
+			    zd->dev->name, urb->status);
+			free = 1;
+			goto exit;
+	}
+	
+	if (urb->status != 0 || urb->actual_length == 0)
+		goto resubmit;
+
+	type = data[0];
+	if (type == ZD1201_PACKET_EVENTSTAT || type == ZD1201_PACKET_RESOURCE) {
+		memcpy(zd->rxdata, data, urb->actual_length);
+		zd->rxlen = urb->actual_length;
+		zd->rxdatas = 1;
+		wake_up(&zd->rxdataq);
+	}
+	/* Info frame */
+	if (type == ZD1201_PACKET_INQUIRE) {
+		int i = 0;
+		unsigned short infotype, framelen, copylen;
+		framelen = le16_to_cpu(*(__le16*)&data[4]);
+		infotype = le16_to_cpu(*(__le16*)&data[6]);
+
+		if (infotype == ZD1201_INF_LINKSTATUS) {
+			short linkstatus;
+
+			linkstatus = le16_to_cpu(*(__le16*)&data[8]);
+			switch(linkstatus) {
+				case 1:
+					netif_carrier_on(zd->dev);
+					break;
+				case 2:
+					netif_carrier_off(zd->dev);
+					break;
+				case 3:
+					netif_carrier_off(zd->dev);
+					break;
+				case 4:
+					netif_carrier_on(zd->dev);
+					break;
+				default:
+					netif_carrier_off(zd->dev);
+			}
+			goto resubmit;
+		}
+		if (infotype == ZD1201_INF_ASSOCSTATUS) {
+			short status = le16_to_cpu(*(__le16*)(data+8));
+			int event;
+			union iwreq_data wrqu;
+
+			switch (status) {
+				case ZD1201_ASSOCSTATUS_STAASSOC:
+				case ZD1201_ASSOCSTATUS_REASSOC:
+					event = IWEVREGISTERED;
+					break;
+				case ZD1201_ASSOCSTATUS_DISASSOC:
+				case ZD1201_ASSOCSTATUS_ASSOCFAIL:
+				case ZD1201_ASSOCSTATUS_AUTHFAIL:
+				default:
+					event = IWEVEXPIRED;
+			}
+			memcpy(wrqu.addr.sa_data, data+10, ETH_ALEN);
+			wrqu.addr.sa_family = ARPHRD_ETHER;
+
+			/* Send event to user space */
+			wireless_send_event(zd->dev, event, &wrqu, NULL);
+
+			goto resubmit;
+		}
+		if (infotype == ZD1201_INF_AUTHREQ) {
+			union iwreq_data wrqu;
+
+			memcpy(wrqu.addr.sa_data, data+8, ETH_ALEN);
+			wrqu.addr.sa_family = ARPHRD_ETHER;
+			/* There isn't a event that trully fits this request.
+			   We assume that userspace will be smart enough to
+			   see a new station being expired and sends back a
+			   authstation ioctl to authorize it. */
+			wireless_send_event(zd->dev, IWEVEXPIRED, &wrqu, NULL);
+			goto resubmit;
+		}
+		/* Other infotypes are handled outside this handler */
+		zd->rxlen = 0;
+		while (i < urb->actual_length) {
+			copylen = le16_to_cpu(*(__le16*)&data[i+2]);
+			/* Sanity check, sometimes we get junk */
+			if (copylen+zd->rxlen > sizeof(zd->rxdata))
+				break;
+			memcpy(zd->rxdata+zd->rxlen, data+i+4, copylen);
+			zd->rxlen += copylen;
+			i += 64;
+		}
+		if (i >= urb->actual_length) {
+			zd->rxdatas = 1;
+			wake_up(&zd->rxdataq);
+		}
+		goto  resubmit;
+	}
+	/* Actual data */
+	if (data[urb->actual_length-1] == ZD1201_PACKET_RXDATA) {
+		int datalen = urb->actual_length-1;
+		unsigned short len, fc, seq;
+		struct hlist_node *node;
+
+		len = ntohs(*(__be16 *)&data[datalen-2]);
+		if (len>datalen)
+			len=datalen;
+		fc = le16_to_cpu(*(__le16 *)&data[datalen-16]);
+		seq = le16_to_cpu(*(__le16 *)&data[datalen-24]);
+
+		if(zd->monitor) {
+			if (datalen < 24)
+				goto resubmit;
+			if (!(skb = dev_alloc_skb(datalen+24)))
+				goto resubmit;
+			
+			memcpy(skb_put(skb, 2), &data[datalen-16], 2);
+			memcpy(skb_put(skb, 2), &data[datalen-2], 2);
+			memcpy(skb_put(skb, 6), &data[datalen-14], 6);
+			memcpy(skb_put(skb, 6), &data[datalen-22], 6);
+			memcpy(skb_put(skb, 6), &data[datalen-8], 6);
+			memcpy(skb_put(skb, 2), &data[datalen-24], 2);
+			memcpy(skb_put(skb, len), data, len);
+			skb->dev = zd->dev;
+			skb->dev->last_rx = jiffies;
+			skb->protocol = eth_type_trans(skb, zd->dev);
+			zd->stats.rx_packets++;
+			zd->stats.rx_bytes += skb->len;
+			netif_rx(skb);
+			goto resubmit;
+		}
+			
+		if ((seq & IEEE802_11_SCTL_FRAG) ||
+		    (fc & IEEE802_11_FCTL_MOREFRAGS)) {
+			struct zd1201_frag *frag = NULL;
+			char *ptr;
+
+			if (datalen<14)
+				goto resubmit;
+			if ((seq & IEEE802_11_SCTL_FRAG) == 0) {
+				frag = kmalloc(sizeof(struct zd1201_frag*),
+				    GFP_ATOMIC);
+				if (!frag)
+					goto resubmit;
+				skb = dev_alloc_skb(IEEE802_11_DATA_LEN +14+2);
+				if (!skb) {
+					kfree(frag);
+					goto resubmit;
+				}
+				frag->skb = skb;
+				frag->seq = seq & IEEE802_11_SCTL_SEQ;
+				skb_reserve(skb, 2);
+				memcpy(skb_put(skb, 12), &data[datalen-14], 12);
+				memcpy(skb_put(skb, 2), &data[6], 2);
+				memcpy(skb_put(skb, len), data+8, len);
+				hlist_add_head(&frag->fnode, &zd->fraglist);
+				goto resubmit;
+			}
+			hlist_for_each_entry(frag, node, &zd->fraglist, fnode)
+				if(frag->seq == (seq&IEEE802_11_SCTL_SEQ))
+					break;
+			if (!frag)
+				goto resubmit;
+			skb = frag->skb;
+			ptr = skb_put(skb, len);
+			if (ptr)
+				memcpy(ptr, data+8, len);
+			if (fc & IEEE802_11_FCTL_MOREFRAGS)
+				goto resubmit;
+			hlist_del_init(&frag->fnode);
+			kfree(frag);
+			/* Fallthrough */
+		} else {
+			if (datalen<14)
+				goto resubmit;
+			skb = dev_alloc_skb(len + 14 + 2);
+			if (!skb)
+				goto resubmit;
+			skb_reserve(skb, 2);
+			memcpy(skb_put(skb, 12), &data[datalen-14], 12);
+			memcpy(skb_put(skb, 2), &data[6], 2);
+			memcpy(skb_put(skb, len), data+8, len);
+		}
+		skb->dev = zd->dev;
+		skb->dev->last_rx = jiffies;
+		skb->protocol = eth_type_trans(skb, zd->dev);
+		zd->stats.rx_packets++;
+		zd->stats.rx_bytes += skb->len;
+		netif_rx(skb);
+	}
+resubmit:
+	memset(data, 0, ZD1201_RXSIZE);
+
+	urb->status = 0;
+	urb->dev = zd->usb;
+	if(usb_submit_urb(urb, GFP_ATOMIC))
+		free = 1;
+
+exit:
+	if (free) {
+		zd->rxlen = 0;
+		zd->rxdatas = 1;
+		wake_up(&zd->rxdataq);
+		kfree(urb->transfer_buffer);
+	}
+	return;
+}
+
+static int zd1201_getconfig(struct zd1201 *zd, int rid, void *riddata,
+	unsigned int riddatalen)
+{
+	int err;
+	int i = 0;
+	int code;
+	int rid_fid;
+	int length;
+	unsigned char *pdata;
+	
+	zd->rxdatas = 0;
+	err = zd1201_docmd(zd, ZD1201_CMDCODE_ACCESS, rid, 0, 0);
+	if (err)
+		return err;
+
+	wait_event_interruptible(zd->rxdataq, zd->rxdatas);
+	if (!zd->rxlen)
+		return -EIO;
+
+	code = le16_to_cpu(*(__le16*)(&zd->rxdata[4]));
+	rid_fid = le16_to_cpu(*(__le16*)(&zd->rxdata[6]));
+	length = le16_to_cpu(*(__le16*)(&zd->rxdata[8]));
+	if (length > zd->rxlen)
+		length = zd->rxlen-6;
+
+	/* If access bit is not on, then error */
+	if ((code & ZD1201_ACCESSBIT) != ZD1201_ACCESSBIT || rid_fid != rid )
+		return -EINVAL;
+
+	/* Not enough buffer for allocating data */
+	if (riddatalen != (length - 4)) {
+		dev_dbg(&zd->usb->dev, "riddatalen mismatches, expected=%u, (packet=%u) length=%u, rid=0x%04X, rid_fid=0x%04X\n",
+		    riddatalen, zd->rxlen, length, rid, rid_fid);
+		return -ENODATA;
+	}
+
+	zd->rxdatas = 0;
+	/* Issue SetRxRid commnd */			
+	err = zd1201_docmd(zd, ZD1201_CMDCODE_SETRXRID, rid, 0, length);
+	if (err)
+		return err;
+
+	/* Receive RID record from resource packets */
+	wait_event_interruptible(zd->rxdataq, zd->rxdatas);
+	if (!zd->rxlen)
+		return -EIO;
+
+	if (zd->rxdata[zd->rxlen - 1] != ZD1201_PACKET_RESOURCE) {
+		dev_dbg(&zd->usb->dev, "Packet type mismatch: 0x%x not 0x3\n",
+		    zd->rxdata[zd->rxlen-1]);
+		return -EINVAL;
+	}
+
+	/* Set the data pointer and received data length */
+	pdata = zd->rxdata;
+	length = zd->rxlen;
+
+	do {
+		int  actual_length;
+
+		actual_length = (length > 64) ? 64 : length;
+
+		if(pdata[0] != 0x3) {
+			dev_dbg(&zd->usb->dev, "Rx Resource packet type error: %02X\n",
+			    pdata[0]);
+			return -EINVAL;
+		}
+
+		if (actual_length != 64) {
+			/* Trim the last packet type byte */
+			actual_length--;
+		}
+
+		/* Skip the 4 bytes header (RID length and RID) */
+		if(i == 0) {
+			pdata += 8;
+			actual_length -= 8;
+		}
+		else {
+			pdata += 4;
+			actual_length -= 4;
+		}
+		
+		memcpy(riddata, pdata, actual_length);
+		riddata += actual_length;
+		pdata += actual_length;
+		length -= 64;
+		i++;
+	} while (length > 0);
+
+	return 0;
+}
+
+/*
+ *	resreq:
+ *		byte	type
+ *		byte	sequence
+ *		u16	reserved
+ *		byte	data[12]
+ *	total: 16
+ */
+static int zd1201_setconfig(struct zd1201 *zd, int rid, void *buf, int len, int wait)
+{
+	int err;
+	unsigned char *request;
+	int reqlen;
+	char seq=0;
+	struct urb *urb;
+	unsigned int gfp_mask = wait ? GFP_NOIO : GFP_ATOMIC;
+
+	len += 4;			/* first 4 are for header */
+
+	zd->rxdatas = 0;
+	zd->rxlen = 0;
+	for (seq=0; len > 0; seq++) {
+		request = kmalloc(16, gfp_mask);
+		if (!request)
+			return -ENOMEM;
+		urb = usb_alloc_urb(0, gfp_mask);
+		if (!urb) {
+			kfree(request);
+			return -ENOMEM;
+		}
+		memset(request, 0, 16);
+		reqlen = len>12 ? 12 : len;
+		request[0] = ZD1201_USB_RESREQ;
+		request[1] = seq;
+		request[2] = 0;
+		request[3] = 0;
+		if (request[1] == 0) {
+			/* add header */
+			*(__le16*)&request[4] = cpu_to_le16((len-2+1)/2);
+			*(__le16*)&request[6] = cpu_to_le16(rid);
+			memcpy(request+8, buf, reqlen-4);
+			buf += reqlen-4;
+		} else {
+			memcpy(request+4, buf, reqlen);
+			buf += reqlen;
+		}
+
+		len -= reqlen;
+
+		usb_fill_bulk_urb(urb, zd->usb, usb_sndbulkpipe(zd->usb,
+		    zd->endp_out2), request, 16, zd1201_usbfree, zd);
+		err = usb_submit_urb(urb, gfp_mask);
+		if (err)
+			goto err;
+	}
+
+	request = kmalloc(16, gfp_mask);
+	if (!request)
+		return -ENOMEM;
+	urb = usb_alloc_urb(0, gfp_mask);
+	if (!urb) {
+		kfree(request);
+		return -ENOMEM;
+	}
+	*((__le32*)request) = cpu_to_le32(ZD1201_USB_CMDREQ);
+	*((__le16*)&request[4]) = 
+	    cpu_to_le16(ZD1201_CMDCODE_ACCESS|ZD1201_ACCESSBIT);
+	*((__le16*)&request[6]) = cpu_to_le16(rid);
+	*((__le16*)&request[8]) = cpu_to_le16(0);
+	*((__le16*)&request[10]) = cpu_to_le16(0);
+	usb_fill_bulk_urb(urb, zd->usb, usb_sndbulkpipe(zd->usb, zd->endp_out2),
+	     request, 16, zd1201_usbfree, zd);
+	err = usb_submit_urb(urb, gfp_mask);
+	if (err)
+		goto err;
+	
+	if (wait) {
+		wait_event_interruptible(zd->rxdataq, zd->rxdatas);
+		if (!zd->rxlen || le16_to_cpu(*(__le16*)&zd->rxdata[6]) != rid) {
+			dev_dbg(&zd->usb->dev, "wrong or no RID received\n");
+		}
+	}
+
+	return 0;
+err:
+	kfree(request);
+	usb_free_urb(urb);
+	return err;
+}
+
+static inline int zd1201_getconfig16(struct zd1201 *zd, int rid, short *val)
+{
+	int err;
+	__le16 zdval;
+
+	err = zd1201_getconfig(zd, rid, &zdval, sizeof(__le16));
+	if (err)
+		return err;
+	*val = le16_to_cpu(zdval);
+	return 0;
+}
+
+static inline int zd1201_setconfig16(struct zd1201 *zd, int rid, short val)
+{
+	__le16 zdval = cpu_to_le16(val);
+	return (zd1201_setconfig(zd, rid, &zdval, sizeof(__le16), 1));
+}
+
+int zd1201_drvr_start(struct zd1201 *zd)
+{
+	int err, i;
+	short max;
+	__le16 zdmax;
+	unsigned char *buffer;
+	
+	buffer = kmalloc(ZD1201_RXSIZE, GFP_KERNEL);
+	if (!buffer)
+		return -ENOMEM;
+	memset(buffer, 0, ZD1201_RXSIZE);
+
+	usb_fill_bulk_urb(zd->rx_urb, zd->usb, 
+	    usb_rcvbulkpipe(zd->usb, zd->endp_in), buffer, ZD1201_RXSIZE,
+	    zd1201_usbrx, zd);
+
+	err = usb_submit_urb(zd->rx_urb, GFP_KERNEL);
+	if (err)
+		goto err_buffer;
+	
+	err = zd1201_docmd(zd, ZD1201_CMDCODE_INIT, 0, 0, 0);
+	if (err)
+		goto err_urb;
+
+	err = zd1201_getconfig(zd, ZD1201_RID_CNFMAXTXBUFFERNUMBER, &zdmax,
+	    sizeof(__le16));
+	if (err)
+		goto err_urb;
+
+	max = le16_to_cpu(zdmax);
+	for (i=0; i<max; i++) {
+		err = zd1201_docmd(zd, ZD1201_CMDCODE_ALLOC, 1514, 0, 0);
+		if (err)
+			goto err_urb;
+	}
+
+	return 0;
+
+err_urb:
+	usb_kill_urb(zd->rx_urb);
+	return err;
+err_buffer:
+	kfree(buffer);
+	return err;
+}
+
+/*	Magic alert: The firmware doesn't seem to like the MAC state being
+ *	toggled in promisc (aka monitor) mode.
+ *	(It works a number of times, but will halt eventually)
+ *	So we turn it of before disabling and on after enabling if needed.
+ */
+static int zd1201_enable(struct zd1201 *zd)
+{
+	int err;
+
+	if (zd->mac_enabled)
+		return 0;
+
+	err = zd1201_docmd(zd, ZD1201_CMDCODE_ENABLE, 0, 0, 0);
+	if (!err);
+		zd->mac_enabled = 1;
+
+	if (zd->monitor)
+		err = zd1201_setconfig16(zd, ZD1201_RID_PROMISCUOUSMODE, 1);
+
+	return err;
+}
+
+static int zd1201_disable(struct zd1201 *zd)
+{
+	int err;
+	
+	if (!zd->mac_enabled)
+		return 0;
+	if (zd->monitor) {
+		err = zd1201_setconfig16(zd, ZD1201_RID_PROMISCUOUSMODE, 0);
+		if (err);
+			return err;
+	}
+
+	err = zd1201_docmd(zd, ZD1201_CMDCODE_DISABLE, 0, 0, 0);
+	if (!err)
+		zd->mac_enabled = 0;
+	return err;
+}
+
+static int zd1201_mac_reset(struct zd1201 *zd)
+{
+	if (!zd->mac_enabled)
+		return 0;
+	zd1201_disable(zd);
+	return zd1201_enable(zd);
+}
+
+static int zd1201_join(struct zd1201 *zd, char *essid, int essidlen)
+{
+	int err, val;
+	char buf[IW_ESSID_MAX_SIZE+2];
+
+	err = zd1201_disable(zd);
+	if (err)
+		return err;
+
+	val = ZD1201_CNFAUTHENTICATION_OPENSYSTEM;
+	val |= ZD1201_CNFAUTHENTICATION_SHAREDKEY;
+	err = zd1201_setconfig16(zd, ZD1201_RID_CNFAUTHENTICATION, val);
+	if (err)
+		return err;
+
+	*(__le16 *)buf = cpu_to_le16(essidlen);
+	memcpy(buf+2, essid, essidlen);
+	if (!zd->ap) {	/* Normal station */
+		err = zd1201_setconfig(zd, ZD1201_RID_CNFDESIREDSSID, buf,
+		    IW_ESSID_MAX_SIZE+2, 1);
+		if (err)
+			return err;
+	} else {	/* AP */
+		err = zd1201_setconfig(zd, ZD1201_RID_CNFOWNSSID, buf,
+		    IW_ESSID_MAX_SIZE+2, 1);
+		if (err)
+			return err;
+	}
+
+	err = zd1201_setconfig(zd, ZD1201_RID_CNFOWNMACADDR, 
+	    zd->dev->dev_addr, zd->dev->addr_len, 1);
+	if (err)
+		return err;
+
+	err = zd1201_enable(zd);
+	if (err)
+		return err;
+
+	msleep(100);
+	return 0;
+}
+
+static int zd1201_net_open(struct net_device *dev)
+{
+	struct zd1201 *zd = (struct zd1201 *)dev->priv;
+
+	/* Start MAC with wildcard if no essid set */
+	if (!zd->mac_enabled)
+		zd1201_join(zd, zd->essid, zd->essidlen);
+	netif_start_queue(dev);
+
+	return 0;
+}
+
+static int zd1201_net_stop(struct net_device *dev)
+{
+	netif_stop_queue(dev);
+	
+	return 0;
+}
+
+/*
+	RFC 1042 encapsulates Ethernet frames in 802.11 frames
+	by prefixing them with 0xaa, 0xaa, 0x03) followed by a SNAP OID of 0
+	(0x00, 0x00, 0x00). Zd requires an additionnal padding, copy
+	of ethernet addresses, length of the standard RFC 1042 packet
+	and a command byte (which is nul for tx).
+	
+	tx frame (from Wlan NG):
+	RFC 1042:
+		llc		0xAA 0xAA 0x03 (802.2 LLC)
+		snap		0x00 0x00 0x00 (Ethernet encapsulated)
+		type		2 bytes, Ethernet type field
+		payload		(minus eth header)
+	Zydas specific:
+		padding		1B if (skb->len+8+1)%64==0
+		Eth MAC addr	12 bytes, Ethernet MAC addresses
+		length		2 bytes, RFC 1042 packet length 
+				(llc+snap+type+payload)
+		zd		1 null byte, zd1201 packet type
+ */
+static int zd1201_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+	struct zd1201 *zd = (struct zd1201 *)dev->priv;
+	unsigned char *txbuf = zd->txdata;
+	int txbuflen, pad = 0, err;
+	struct urb *urb = zd->tx_urb;
+
+	if (!zd->mac_enabled || zd->monitor) {
+		zd->stats.tx_dropped++;
+		kfree_skb(skb);
+		return 0;
+	}
+	netif_stop_queue(dev);
+
+	txbuflen = skb->len + 8 + 1;
+	if (txbuflen%64 == 0) {
+		pad = 1;
+		txbuflen++;
+	}
+	txbuf[0] = 0xAA;
+	txbuf[1] = 0xAA;
+	txbuf[2] = 0x03;
+	txbuf[3] = 0x00;	/* rfc1042 */
+	txbuf[4] = 0x00;
+	txbuf[5] = 0x00;
+
+	memcpy(txbuf+6, skb->data+12, skb->len-12);
+	if (pad)
+		txbuf[skb->len-12+6]=0;
+	memcpy(txbuf+skb->len-12+6+pad, skb->data, 12);
+	*(__be16*)&txbuf[skb->len+6+pad] = htons(skb->len-12+6);
+	txbuf[txbuflen-1] = 0;
+
+	usb_fill_bulk_urb(urb, zd->usb, usb_sndbulkpipe(zd->usb, zd->endp_out),
+	    txbuf, txbuflen, zd1201_usbtx, zd);
+
+	err = usb_submit_urb(zd->tx_urb, GFP_ATOMIC);
+	if (err) {
+		zd->stats.tx_errors++;
+		netif_start_queue(dev);
+		return err;
+	}
+	zd->stats.tx_packets++;
+	zd->stats.tx_bytes += skb->len;
+	dev->trans_start = jiffies;
+	kfree_skb(skb);
+
+	return 0;
+}
+
+static void zd1201_tx_timeout(struct net_device *dev)
+{
+	struct zd1201 *zd = (struct zd1201 *)dev->priv;
+
+	if (!zd)
+		return;
+	dev_warn(&zd->usb->dev, "%s: TX timeout, shooting down urb\n",
+	    dev->name);
+	zd->tx_urb->transfer_flags |= URB_ASYNC_UNLINK;
+	usb_unlink_urb(zd->tx_urb);
+	zd->stats.tx_errors++;
+	/* Restart the timeout to quiet the watchdog: */
+	dev->trans_start = jiffies;
+}
+
+static int zd1201_set_mac_address(struct net_device *dev, void *p)
+{
+	struct sockaddr *addr = p;
+	struct zd1201 *zd = (struct zd1201 *)dev->priv;
+	int err;
+
+	if (!zd)
+		return -ENODEV;
+
+	err = zd1201_setconfig(zd, ZD1201_RID_CNFOWNMACADDR, 
+	    addr->sa_data, dev->addr_len, 1);
+	if (err)
+		return err;
+	memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
+
+	return zd1201_mac_reset(zd);
+}
+
+static struct net_device_stats *zd1201_get_stats(struct net_device *dev)
+{
+	struct zd1201 *zd = (struct zd1201 *)dev->priv;
+
+	return &zd->stats;
+}
+
+static struct iw_statistics *zd1201_get_wireless_stats(struct net_device *dev)
+{
+	struct zd1201 *zd = (struct zd1201 *)dev->priv;
+
+	return &zd->iwstats;
+}
+
+static void zd1201_set_multicast(struct net_device *dev)
+{
+	struct zd1201 *zd = (struct zd1201 *)dev->priv;
+	struct dev_mc_list *mc = dev->mc_list;
+	unsigned char reqbuf[ETH_ALEN*ZD1201_MAXMULTI];
+	int i;
+
+	if (dev->mc_count > ZD1201_MAXMULTI)
+		return;
+
+	for (i=0; i<dev->mc_count; i++) {
+		memcpy(reqbuf+i*ETH_ALEN, mc->dmi_addr, ETH_ALEN);
+		mc = mc->next;
+	}
+	zd1201_setconfig(zd, ZD1201_RID_CNFGROUPADDRESS, reqbuf,
+	    dev->mc_count*ETH_ALEN, 0);
+	
+}
+
+static int zd1201_config_commit(struct net_device *dev, 
+    struct iw_request_info *info, struct iw_point *data, char *essid)
+{
+	struct zd1201 *zd = (struct zd1201 *)dev->priv;
+
+	return zd1201_mac_reset(zd);
+}
+
+static int zd1201_get_name(struct net_device *dev,
+    struct iw_request_info *info, char *name, char *extra)
+{
+	strcpy(name, "IEEE 802.11b");
+
+	return 0;
+}
+
+static int zd1201_set_freq(struct net_device *dev,
+    struct iw_request_info *info, struct iw_freq *freq, char *extra)
+{
+	struct zd1201 *zd = (struct zd1201 *)dev->priv;
+	short channel = 0;
+	int err;
+
+	if (freq->e == 0)
+		channel = freq->m;
+	else {
+		if (freq->m >= 2482)
+			channel = 14;
+		if (freq->m >= 2407)
+			channel = (freq->m-2407)/5;
+	}
+
+	err = zd1201_setconfig16(zd, ZD1201_RID_CNFOWNCHANNEL, channel);
+	if (err)
+		return err;
+
+	zd1201_mac_reset(zd);
+
+	return 0;
+}
+
+static int zd1201_get_freq(struct net_device *dev,
+    struct iw_request_info *info, struct iw_freq *freq, char *extra)
+{
+	struct zd1201 *zd = (struct zd1201 *)dev->priv;
+	short channel;
+	int err;
+
+	err = zd1201_getconfig16(zd, ZD1201_RID_CNFOWNCHANNEL, &channel);
+	if (err)
+		return err;
+	freq->e = 0;
+	freq->m = channel;
+
+	return 0;
+}
+
+static int zd1201_set_mode(struct net_device *dev,
+    struct iw_request_info *info, __u32 *mode, char *extra)
+{
+	struct zd1201 *zd = (struct zd1201 *)dev->priv;
+	short porttype, monitor = 0;
+	unsigned char buffer[IW_ESSID_MAX_SIZE+2];
+	int err;
+
+	if (zd->ap) {
+		if (*mode != IW_MODE_MASTER)
+			return -EINVAL;
+		return 0;
+	}
+
+	err = zd1201_setconfig16(zd, ZD1201_RID_PROMISCUOUSMODE, 0);
+	if (err)
+		return err;
+	zd->dev->type = ARPHRD_ETHER;
+	switch(*mode) {
+		case IW_MODE_MONITOR:
+			monitor = 1;
+			zd->dev->type = ARPHRD_IEEE80211;
+			/* Make sure we are no longer associated with by
+			   setting an 'impossible' essid.
+			   (otherwise we mess up firmware)
+			 */
+			zd1201_join(zd, "\0-*#\0", 5);
+			/* Put port in pIBSS */
+		case 8: /* No pseudo-IBSS in wireless extensions (yet) */
+			porttype = ZD1201_PORTTYPE_PSEUDOIBSS;
+			break;
+		case IW_MODE_ADHOC:
+			porttype = ZD1201_PORTTYPE_IBSS;
+			break;
+		case IW_MODE_INFRA:
+			porttype = ZD1201_PORTTYPE_BSS;
+			break;
+		default:
+			return -EINVAL;
+	}
+
+	err = zd1201_setconfig16(zd, ZD1201_RID_CNFPORTTYPE, porttype);
+	if (err)
+		return err;
+	if (zd->monitor && !monitor) {
+			zd1201_disable(zd);
+			*(__le16 *)buffer = cpu_to_le16(zd->essidlen);
+			memcpy(buffer+2, zd->essid, zd->essidlen);
+			err = zd1201_setconfig(zd, ZD1201_RID_CNFDESIREDSSID,
+			    buffer, IW_ESSID_MAX_SIZE+2, 1);
+			if (err)
+				return err;
+	}
+	zd->monitor=monitor;
+	/* If monitor mode is set we don't actually turn it on here since it
+	 * is done during mac reset anyway (see zd1201_mac_enable).
+	 */
+
+	zd1201_mac_reset(zd);
+
+	return 0;
+}
+
+static int zd1201_get_mode(struct net_device *dev,
+    struct iw_request_info *info, __u32 *mode, char *extra)
+{
+	struct zd1201 *zd = (struct zd1201 *)dev->priv;
+	short porttype;
+	int err;
+
+	err = zd1201_getconfig16(zd, ZD1201_RID_CNFPORTTYPE, &porttype);
+	if (err)
+		return err;
+	switch(porttype) {
+		case ZD1201_PORTTYPE_IBSS:
+			*mode = IW_MODE_ADHOC;
+			break;
+		case ZD1201_PORTTYPE_BSS:
+			*mode = IW_MODE_INFRA;
+			break;
+		case ZD1201_PORTTYPE_WDS:
+			*mode = IW_MODE_REPEAT;
+			break;
+		case ZD1201_PORTTYPE_PSEUDOIBSS:
+			*mode = 8;/* No Pseudo-IBSS... */
+			break;
+		case ZD1201_PORTTYPE_AP:
+			*mode = IW_MODE_MASTER;
+			break;
+		default:
+			dev_dbg(&zd->usb->dev, "Unknown porttype: %d\n",
+			    porttype);
+			*mode = IW_MODE_AUTO;
+	}
+	if (zd->monitor)
+		*mode = IW_MODE_MONITOR;
+
+	return 0;
+}
+
+static int zd1201_get_range(struct net_device *dev,
+    struct iw_request_info *info, struct iw_point *wrq, char *extra)
+{
+	struct iw_range *range = (struct iw_range *)extra;
+
+	wrq->length = sizeof(struct iw_range);
+	memset(range, 0, sizeof(struct iw_range));
+	range->we_version_compiled = WIRELESS_EXT;
+	range->we_version_source = WIRELESS_EXT;
+
+	range->max_qual.qual = 128;
+	range->max_qual.level = 128;
+	range->max_qual.noise = 128;
+	range->max_qual.updated = 7;
+
+	range->encoding_size[0] = 5;
+	range->encoding_size[1] = 13;
+	range->num_encoding_sizes = 2;
+	range->max_encoding_tokens = ZD1201_NUMKEYS;
+
+	range->num_bitrates = 4;
+	range->bitrate[0] = 1000000;
+	range->bitrate[1] = 2000000;
+	range->bitrate[2] = 5500000;
+	range->bitrate[3] = 11000000;
+
+	range->min_rts = 0;
+	range->min_frag = ZD1201_FRAGMIN;
+	range->max_rts = ZD1201_RTSMAX;
+	range->min_frag = ZD1201_FRAGMAX;
+
+	return 0;
+}
+
+/*	Little bit of magic here: we only get the quality if we poll
+ *	for it, and we never get an actual request to trigger such
+ *	a poll. Therefore we 'asume' that the user will soon ask for
+ *	the stats after asking the bssid.
+ */
+static int zd1201_get_wap(struct net_device *dev,
+    struct iw_request_info *info, struct sockaddr *ap_addr, char *extra)
+{
+	struct zd1201 *zd = (struct zd1201 *)dev->priv;
+	unsigned char buffer[6];
+
+	if (!zd1201_getconfig(zd, ZD1201_RID_COMMSQUALITY, buffer, 6)) {
+		/* Unfortunatly the quality and noise reported is useless.
+		   they seem to be accumulators that increase until you
+		   read them, unless we poll on a fixed interval we can't
+		   use them
+		 */
+		/*zd->iwstats.qual.qual = le16_to_cpu(((__le16 *)buffer)[0]);*/
+		zd->iwstats.qual.level = le16_to_cpu(((__le16 *)buffer)[1]);
+		/*zd->iwstats.qual.noise = le16_to_cpu(((__le16 *)buffer)[2]);*/
+		zd->iwstats.qual.updated = 2;
+	}
+
+	return zd1201_getconfig(zd,ZD1201_RID_CURRENTBSSID,ap_addr->sa_data,6);
+}
+
+static int zd1201_set_scan(struct net_device *dev,
+    struct iw_request_info *info, struct iw_point *srq, char *extra)
+{
+	/* We do everything in get_scan */
+	return 0;
+}
+
+static int zd1201_get_scan(struct net_device *dev,
+    struct iw_request_info *info, struct iw_point *srq, char *extra)
+{
+	struct zd1201 *zd = (struct zd1201 *)dev->priv;
+	int err, i, j, enabled_save;
+	struct iw_event iwe;
+	char *cev = extra;
+	char *end_buf = extra + IW_SCAN_MAX_DATA;
+
+	/* No scanning in AP mode */
+	if (zd->ap)
+		return -EOPNOTSUPP;
+
+	/* Scan doesn't seem to work if disabled */
+	enabled_save = zd->mac_enabled;
+	zd1201_enable(zd);
+
+	zd->rxdatas = 0;
+	err = zd1201_docmd(zd, ZD1201_CMDCODE_INQUIRE, 
+	     ZD1201_INQ_SCANRESULTS, 0, 0);
+	if (err)
+		return err;
+
+	wait_event_interruptible(zd->rxdataq, zd->rxdatas);
+	if (!zd->rxlen)
+		return -EIO;
+
+	if (le16_to_cpu(*(__le16*)&zd->rxdata[2]) != ZD1201_INQ_SCANRESULTS)
+		return -EIO;
+
+	for(i=8; i<zd->rxlen; i+=62) {
+		iwe.cmd = SIOCGIWAP;
+		iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
+		memcpy(iwe.u.ap_addr.sa_data, zd->rxdata+i+6, 6);
+		cev = iwe_stream_add_event(cev, end_buf, &iwe, IW_EV_ADDR_LEN);
+
+		iwe.cmd = SIOCGIWESSID;
+		iwe.u.data.length = zd->rxdata[i+16];
+		iwe.u.data.flags = 1;
+		cev = iwe_stream_add_point(cev, end_buf, &iwe, zd->rxdata+i+18);
+
+		iwe.cmd = SIOCGIWMODE;
+		if (zd->rxdata[i+14]&0x01)
+			iwe.u.mode = IW_MODE_MASTER;
+		else
+			iwe.u.mode = IW_MODE_ADHOC;
+		cev = iwe_stream_add_event(cev, end_buf, &iwe, IW_EV_UINT_LEN);
+		
+		iwe.cmd = SIOCGIWFREQ;
+		iwe.u.freq.m = zd->rxdata[i+0];
+		iwe.u.freq.e = 0;
+		cev = iwe_stream_add_event(cev, end_buf, &iwe, IW_EV_FREQ_LEN);
+		
+		iwe.cmd = SIOCGIWRATE;
+		iwe.u.bitrate.fixed = 0;
+		iwe.u.bitrate.disabled = 0;
+		for (j=0; j<10; j++) if (zd->rxdata[i+50+j]) {
+			iwe.u.bitrate.value = (zd->rxdata[i+50+j]&0x7f)*500000;
+			cev=iwe_stream_add_event(cev, end_buf, &iwe,
+			    IW_EV_PARAM_LEN);
+		}
+		
+		iwe.cmd = SIOCGIWENCODE;
+		iwe.u.data.length = 0;
+		if (zd->rxdata[i+14]&0x10)
+			iwe.u.data.flags = IW_ENCODE_ENABLED;
+		else
+			iwe.u.data.flags = IW_ENCODE_DISABLED;
+		cev = iwe_stream_add_point(cev, end_buf, &iwe, NULL);
+		
+		iwe.cmd = IWEVQUAL;
+		iwe.u.qual.qual = zd->rxdata[i+4];
+		iwe.u.qual.noise= zd->rxdata[i+2]/10-100;
+		iwe.u.qual.level = (256+zd->rxdata[i+4]*100)/255-100;
+		iwe.u.qual.updated = 7;
+		cev = iwe_stream_add_event(cev, end_buf, &iwe, IW_EV_QUAL_LEN);
+	}
+
+	if (!enabled_save)
+		zd1201_disable(zd);
+
+	srq->length = cev - extra;
+	srq->flags = 0;
+
+	return 0;
+}
+
+static int zd1201_set_essid(struct net_device *dev,
+    struct iw_request_info *info, struct iw_point *data, char *essid)
+{
+	struct zd1201 *zd = (struct zd1201 *)dev->priv;
+
+	if (data->length > IW_ESSID_MAX_SIZE)
+		return -EINVAL;
+	if (data->length < 1)
+		data->length = 1;
+	zd->essidlen = data->length-1;
+	memset(zd->essid, 0, IW_ESSID_MAX_SIZE+1);
+	memcpy(zd->essid, essid, data->length);
+	return zd1201_join(zd, zd->essid, zd->essidlen);
+}
+
+static int zd1201_get_essid(struct net_device *dev,
+    struct iw_request_info *info, struct iw_point *data, char *essid)
+{
+	struct zd1201 *zd = (struct zd1201 *)dev->priv;
+
+	memcpy(essid, zd->essid, zd->essidlen);
+	data->flags = 1;
+	data->length = zd->essidlen;
+
+	return 0;
+}
+
+static int zd1201_get_nick(struct net_device *dev, struct iw_request_info *info,
+    struct iw_point *data, char *nick)
+{
+	strcpy(nick, "zd1201");
+	data->flags = 1;
+	data->length = strlen(nick);
+	return 0;
+}
+
+static int zd1201_set_rate(struct net_device *dev,
+    struct iw_request_info *info, struct iw_param *rrq, char *extra)
+{
+	struct zd1201 *zd = (struct zd1201 *)dev->priv;
+	short rate;
+	int err;
+
+	switch (rrq->value) {
+		case 1000000:
+			rate = ZD1201_RATEB1;
+			break;
+		case 2000000:
+			rate = ZD1201_RATEB2;
+			break;
+		case 5500000:
+			rate = ZD1201_RATEB5;
+			break;
+		case 11000000:
+		default:
+			rate = ZD1201_RATEB11;
+			break;
+	}
+	if (!rrq->fixed) { /* Also enable all lower bitrates */
+		rate |= rate-1;
+	}
+	
+	err = zd1201_setconfig16(zd, ZD1201_RID_TXRATECNTL, rate);
+	if (err)
+		return err;
+
+	return zd1201_mac_reset(zd);
+}
+
+static int zd1201_get_rate(struct net_device *dev,
+    struct iw_request_info *info, struct iw_param *rrq, char *extra)
+{
+	struct zd1201 *zd = (struct zd1201 *)dev->priv;
+	short rate;
+	int err;
+
+	err = zd1201_getconfig16(zd, ZD1201_RID_CURRENTTXRATE, &rate);
+	if (err)
+		return err;
+
+	switch(rate) {
+		case 1:
+			rrq->value = 1000000;
+			break;
+		case 2:
+			rrq->value = 2000000;
+			break;
+		case 5:
+			rrq->value = 5500000;
+			break;
+		case 11:
+			rrq->value = 11000000;
+			break;
+		default:
+			rrq->value = 0;
+	}
+	rrq->fixed = 0;
+	rrq->disabled = 0;
+
+	return 0;
+}
+
+static int zd1201_set_rts(struct net_device *dev, struct iw_request_info *info,
+    struct iw_param *rts, char *extra)
+{
+	struct zd1201 *zd = (struct zd1201 *)dev->priv;
+	int err;
+	short val = rts->value;
+
+	if (rts->disabled || !rts->fixed)
+		val = ZD1201_RTSMAX;
+	if (val > ZD1201_RTSMAX)
+		return -EINVAL;
+	if (val < 0)
+		return -EINVAL;
+
+	err = zd1201_setconfig16(zd, ZD1201_RID_CNFRTSTHRESHOLD, val);
+	if (err)
+		return err;
+	return zd1201_mac_reset(zd);
+}
+
+static int zd1201_get_rts(struct net_device *dev, struct iw_request_info *info,
+    struct iw_param *rts, char *extra)
+{
+	struct zd1201 *zd = (struct zd1201 *)dev->priv;
+	short rtst;
+	int err;
+
+	err = zd1201_getconfig16(zd, ZD1201_RID_CNFRTSTHRESHOLD, &rtst);
+	if (err)
+		return err;
+	rts->value = rtst;
+	rts->disabled = (rts->value == ZD1201_RTSMAX);
+	rts->fixed = 1;
+
+	return 0;
+}
+
+static int zd1201_set_frag(struct net_device *dev, struct iw_request_info *info,
+    struct iw_param *frag, char *extra)
+{
+	struct zd1201 *zd = (struct zd1201 *)dev->priv;
+	int err;
+	short val = frag->value;
+
+	if (frag->disabled || !frag->fixed)
+		val = ZD1201_FRAGMAX;
+	if (val > ZD1201_FRAGMAX)
+		return -EINVAL;
+	if (val < ZD1201_FRAGMIN)
+		return -EINVAL;
+	if (val & 1)
+		return -EINVAL;
+	err = zd1201_setconfig16(zd, ZD1201_RID_CNFFRAGTHRESHOLD, val);
+	if (err)
+		return err;
+	return zd1201_mac_reset(zd);
+}
+
+static int zd1201_get_frag(struct net_device *dev, struct iw_request_info *info,
+    struct iw_param *frag, char *extra)
+{
+	struct zd1201 *zd = (struct zd1201 *)dev->priv;
+	short fragt;
+	int err;
+
+	err = zd1201_getconfig16(zd, ZD1201_RID_CNFFRAGTHRESHOLD, &fragt);
+	if (err)
+		return err;
+	frag->value = fragt;
+	frag->disabled = (frag->value == ZD1201_FRAGMAX);
+	frag->fixed = 1;
+
+	return 0;
+}
+
+static int zd1201_set_retry(struct net_device *dev,
+    struct iw_request_info *info, struct iw_param *rrq, char *extra)
+{
+	return 0;
+}
+
+static int zd1201_get_retry(struct net_device *dev,
+    struct iw_request_info *info, struct iw_param *rrq, char *extra)
+{
+	return 0;
+}
+
+static int zd1201_set_encode(struct net_device *dev,
+    struct iw_request_info *info, struct iw_point *erq, char *key)
+{
+	struct zd1201 *zd = (struct zd1201 *)dev->priv;
+	short i;
+	int err, rid;
+
+	if (erq->length > ZD1201_MAXKEYLEN)
+		return -EINVAL;
+
+	i = (erq->flags & IW_ENCODE_INDEX)-1;
+	if (i == -1) {
+		err = zd1201_getconfig16(zd,ZD1201_RID_CNFDEFAULTKEYID,&i);
+		if (err)
+			return err;
+	} else {
+		err = zd1201_setconfig16(zd, ZD1201_RID_CNFDEFAULTKEYID, i);
+		if (err)
+			return err;
+	}
+
+	if (i < 0 || i >= ZD1201_NUMKEYS)
+		return -EINVAL;
+
+	rid = ZD1201_RID_CNFDEFAULTKEY0 + i;
+	err = zd1201_setconfig(zd, rid, key, erq->length, 1);
+	if (err)
+		return err;
+	zd->encode_keylen[i] = erq->length;
+	memcpy(zd->encode_keys[i], key, erq->length);
+
+	i=0;
+	if (!(erq->flags & IW_ENCODE_DISABLED & IW_ENCODE_MODE)) {
+		i |= 0x01;
+		zd->encode_enabled = 1;
+	} else
+		zd->encode_enabled = 0;
+	if (erq->flags & IW_ENCODE_RESTRICTED & IW_ENCODE_MODE) {
+		i |= 0x02;
+		zd->encode_restricted = 1;
+	} else
+		zd->encode_restricted = 0;
+	err = zd1201_setconfig16(zd, ZD1201_RID_CNFWEBFLAGS, i);
+	if (err)
+		return err;
+
+	if (zd->encode_enabled)
+		i = ZD1201_CNFAUTHENTICATION_SHAREDKEY;
+	else
+		i = ZD1201_CNFAUTHENTICATION_OPENSYSTEM;
+	err = zd1201_setconfig16(zd, ZD1201_RID_CNFAUTHENTICATION, i);
+	if (err)
+		return err;
+
+	return zd1201_mac_reset(zd);
+}
+
+static int zd1201_get_encode(struct net_device *dev,
+    struct iw_request_info *info, struct iw_point *erq, char *key)
+{
+	struct zd1201 *zd = (struct zd1201 *)dev->priv;
+	short i;
+	int err;
+
+	if (zd->encode_enabled)
+		erq->flags = IW_ENCODE_ENABLED;
+	else
+		erq->flags = IW_ENCODE_DISABLED;
+	if (zd->encode_restricted)
+		erq->flags |= IW_ENCODE_RESTRICTED;
+	else
+		erq->flags |= IW_ENCODE_OPEN;
+
+	i = (erq->flags & IW_ENCODE_INDEX) -1;
+	if (i == -1) {
+		err = zd1201_getconfig16(zd, ZD1201_RID_CNFDEFAULTKEYID, &i);
+		if (err)
+			return err;
+	}
+	if (i<0 || i>= ZD1201_NUMKEYS)
+		return -EINVAL;
+
+	erq->flags |= i+1;
+	
+	erq->length = zd->encode_keylen[i];
+	memcpy(key, zd->encode_keys[i], erq->length);
+
+	return 0;
+}
+
+static int zd1201_set_power(struct net_device *dev, 
+    struct iw_request_info *info, struct iw_param *vwrq, char *extra)
+{
+	struct zd1201 *zd = (struct zd1201 *)dev->priv;
+	short enabled, duration, level;
+	int err;
+
+	enabled = vwrq->disabled ? 0 : 1;
+	if (enabled) {
+		if (vwrq->flags & IW_POWER_PERIOD) {
+			duration = vwrq->value;
+			err = zd1201_setconfig16(zd, 
+			    ZD1201_RID_CNFMAXSLEEPDURATION, duration);
+			if (err)
+				return err;
+			goto out;
+		}
+		if (vwrq->flags & IW_POWER_TIMEOUT) {
+			err = zd1201_getconfig16(zd, 
+			    ZD1201_RID_CNFMAXSLEEPDURATION, &duration);
+			if (err)
+				return err;
+			level = vwrq->value * 4 / duration;
+			if (level > 4)
+				level = 4;
+			if (level < 0)
+				level = 0;
+			err = zd1201_setconfig16(zd, ZD1201_RID_CNFPMEPS,
+			    level);
+			if (err)
+				return err;
+			goto out;
+		}
+		return -EINVAL;
+	}
+out:
+	err = zd1201_setconfig16(zd, ZD1201_RID_CNFPMENABLED, enabled);
+	if (err)
+		return err;
+
+	return 0;
+}
+
+static int zd1201_get_power(struct net_device *dev,
+    struct iw_request_info *info, struct iw_param *vwrq, char *extra)
+{
+	struct zd1201 *zd = (struct zd1201 *)dev->priv;
+	short enabled, level, duration;
+	int err;
+
+	err = zd1201_getconfig16(zd, ZD1201_RID_CNFPMENABLED, &enabled);
+	if (err)
+		return err;
+	err = zd1201_getconfig16(zd, ZD1201_RID_CNFPMEPS, &level);
+	if (err)
+		return err;
+	err = zd1201_getconfig16(zd, ZD1201_RID_CNFMAXSLEEPDURATION, &duration);
+	if (err)
+		return err;
+	vwrq->disabled = enabled ? 0 : 1;
+	if (vwrq->flags & IW_POWER_TYPE) {
+		if (vwrq->flags & IW_POWER_PERIOD) {
+			vwrq->value = duration;
+			vwrq->flags = IW_POWER_PERIOD;
+		} else {
+			vwrq->value = duration * level / 4;
+			vwrq->flags = IW_POWER_TIMEOUT;
+		}
+	}
+	if (vwrq->flags & IW_POWER_MODE) {
+		if (enabled && level)
+			vwrq->flags = IW_POWER_UNICAST_R;
+		else
+			vwrq->flags = IW_POWER_ALL_R;
+	}
+
+	return 0;
+}
+
+
+static const iw_handler zd1201_iw_handler[] =
+{
+	(iw_handler) zd1201_config_commit,	/* SIOCSIWCOMMIT */
+	(iw_handler) zd1201_get_name,    	/* SIOCGIWNAME */
+	(iw_handler) NULL,			/* SIOCSIWNWID */
+	(iw_handler) NULL,			/* SIOCGIWNWID */
+	(iw_handler) zd1201_set_freq,		/* SIOCSIWFREQ */
+	(iw_handler) zd1201_get_freq,		/* SIOCGIWFREQ */
+	(iw_handler) zd1201_set_mode,		/* SIOCSIWMODE */
+	(iw_handler) zd1201_get_mode,		/* SIOCGIWMODE */
+	(iw_handler) NULL,                  	/* SIOCSIWSENS */
+	(iw_handler) NULL,           		/* SIOCGIWSENS */
+	(iw_handler) NULL,			/* SIOCSIWRANGE */
+	(iw_handler) zd1201_get_range,           /* SIOCGIWRANGE */
+	(iw_handler) NULL,			/* SIOCSIWPRIV */
+	(iw_handler) NULL,			/* SIOCGIWPRIV */
+	(iw_handler) NULL,			/* SIOCSIWSTATS */
+	(iw_handler) NULL,			/* SIOCGIWSTATS */
+	(iw_handler) NULL,			/* SIOCSIWSPY */
+	(iw_handler) NULL,			/* SIOCGIWSPY */
+	(iw_handler) NULL,			/* -- hole -- */
+	(iw_handler) NULL,			/* -- hole -- */
+	(iw_handler) NULL/*zd1201_set_wap*/,		/* SIOCSIWAP */
+	(iw_handler) zd1201_get_wap,		/* SIOCGIWAP */
+	(iw_handler) NULL,			/* -- hole -- */
+	(iw_handler) NULL,       		/* SIOCGIWAPLIST */
+	(iw_handler) zd1201_set_scan,		/* SIOCSIWSCAN */
+	(iw_handler) zd1201_get_scan,		/* SIOCGIWSCAN */
+	(iw_handler) zd1201_set_essid,		/* SIOCSIWESSID */
+	(iw_handler) zd1201_get_essid,		/* SIOCGIWESSID */
+	(iw_handler) NULL,         		/* SIOCSIWNICKN */
+	(iw_handler) zd1201_get_nick, 		/* SIOCGIWNICKN */
+	(iw_handler) NULL,			/* -- hole -- */
+	(iw_handler) NULL,			/* -- hole -- */
+	(iw_handler) zd1201_set_rate,		/* SIOCSIWRATE */
+	(iw_handler) zd1201_get_rate,		/* SIOCGIWRATE */
+	(iw_handler) zd1201_set_rts,		/* SIOCSIWRTS */
+	(iw_handler) zd1201_get_rts,		/* SIOCGIWRTS */
+	(iw_handler) zd1201_set_frag,		/* SIOCSIWFRAG */
+	(iw_handler) zd1201_get_frag,		/* SIOCGIWFRAG */
+	(iw_handler) NULL,         		/* SIOCSIWTXPOW */
+	(iw_handler) NULL,          		/* SIOCGIWTXPOW */
+	(iw_handler) zd1201_set_retry,		/* SIOCSIWRETRY */
+	(iw_handler) zd1201_get_retry,		/* SIOCGIWRETRY */
+	(iw_handler) zd1201_set_encode,		/* SIOCSIWENCODE */
+	(iw_handler) zd1201_get_encode,		/* SIOCGIWENCODE */
+	(iw_handler) zd1201_set_power,		/* SIOCSIWPOWER */
+	(iw_handler) zd1201_get_power,		/* SIOCGIWPOWER */
+};
+
+static int zd1201_set_hostauth(struct net_device *dev,
+    struct iw_request_info *info, struct iw_param *rrq, char *extra)
+{
+	struct zd1201 *zd = (struct zd1201 *)dev->priv;
+	int err;
+
+	if (!zd->ap)
+		return -EOPNOTSUPP;
+
+	err = zd1201_setconfig16(zd, ZD1201_RID_CNFHOSTAUTH, rrq->value);
+	if (err)
+		return err;
+	return 0;
+}
+
+static int zd1201_get_hostauth(struct net_device *dev,
+    struct iw_request_info *info, struct iw_param *rrq, char *extra)
+{
+	struct zd1201 *zd = (struct zd1201 *)dev->priv;
+	short hostauth;
+	int err;
+
+	if (!zd->ap)
+		return -EOPNOTSUPP;
+
+	err = zd1201_getconfig16(zd, ZD1201_RID_CNFHOSTAUTH, &hostauth);
+	if (err)
+		return err;
+	rrq->value = hostauth;
+	rrq->fixed = 1;
+
+	return 0;
+}
+
+static int zd1201_auth_sta(struct net_device *dev,
+    struct iw_request_info *info, struct sockaddr *sta, char *extra)
+{
+	struct zd1201 *zd = (struct zd1201 *)dev->priv;
+	unsigned char buffer[10];
+
+	if (!zd->ap)
+		return -EOPNOTSUPP;
+
+	memcpy(buffer, sta->sa_data, ETH_ALEN);
+	*(short*)(buffer+6) = 0;	/* 0==success, 1==failure */
+	*(short*)(buffer+8) = 0;
+
+	return zd1201_setconfig(zd, ZD1201_RID_AUTHENTICATESTA, buffer, 10, 1);
+}
+
+static int zd1201_set_maxassoc(struct net_device *dev,
+    struct iw_request_info *info, struct iw_param *rrq, char *extra)
+{
+	struct zd1201 *zd = (struct zd1201 *)dev->priv;
+	int err;
+
+	if (!zd->ap)
+		return -EOPNOTSUPP;
+
+	err = zd1201_setconfig16(zd, ZD1201_RID_CNFMAXASSOCSTATIONS, rrq->value);
+	if (err)
+		return err;
+	return 0;
+}
+
+static int zd1201_get_maxassoc(struct net_device *dev,
+    struct iw_request_info *info, struct iw_param *rrq, char *extra)
+{
+	struct zd1201 *zd = (struct zd1201 *)dev->priv;
+	short maxassoc;
+	int err;
+
+	if (!zd->ap)
+		return -EOPNOTSUPP;
+
+	err = zd1201_getconfig16(zd, ZD1201_RID_CNFMAXASSOCSTATIONS, &maxassoc);
+	if (err)
+		return err;
+	rrq->value = maxassoc;
+	rrq->fixed = 1;
+
+	return 0;
+}
+
+static const iw_handler zd1201_private_handler[] = {
+	(iw_handler) zd1201_set_hostauth,	/* ZD1201SIWHOSTAUTH */
+	(iw_handler) zd1201_get_hostauth,	/* ZD1201GIWHOSTAUTH */
+	(iw_handler) zd1201_auth_sta,		/* ZD1201SIWAUTHSTA */
+	(iw_handler) NULL,			/* nothing to get */
+	(iw_handler) zd1201_set_maxassoc,	/* ZD1201SIMAXASSOC */
+	(iw_handler) zd1201_get_maxassoc,	/* ZD1201GIMAXASSOC */
+};
+
+static const struct iw_priv_args zd1201_private_args[] = {
+	{ ZD1201SIWHOSTAUTH, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+	    IW_PRIV_TYPE_NONE, "sethostauth" },
+	{ ZD1201GIWHOSTAUTH, IW_PRIV_TYPE_NONE,
+	    IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "gethostauth" },
+	{ ZD1201SIWAUTHSTA, IW_PRIV_TYPE_ADDR | IW_PRIV_SIZE_FIXED | 1, 
+	    IW_PRIV_TYPE_NONE, "authstation" },
+	{ ZD1201SIWMAXASSOC, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+	    IW_PRIV_TYPE_NONE, "setmaxassoc" },
+	{ ZD1201GIWMAXASSOC, IW_PRIV_TYPE_NONE,
+	    IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getmaxassoc" },
+};
+
+static const struct iw_handler_def zd1201_iw_handlers = {
+	.num_standard 		= sizeof(zd1201_iw_handler)/sizeof(iw_handler),
+	.num_private 		= sizeof(zd1201_private_handler)/sizeof(iw_handler),
+	.num_private_args 	= sizeof(zd1201_private_args)/sizeof(struct iw_priv_args),
+	.standard 		= (iw_handler *)zd1201_iw_handler,
+	.private 		= (iw_handler *)zd1201_private_handler,
+	.private_args 		= (struct iw_priv_args *) zd1201_private_args,
+};
+
+int zd1201_probe(struct usb_interface *interface, const struct usb_device_id *id)
+{
+	struct zd1201 *zd;
+	struct usb_device *usb;
+	int i, err;
+	short porttype;
+	char buf[IW_ESSID_MAX_SIZE+2];
+
+	usb = interface_to_usbdev(interface);
+
+	zd = kmalloc(sizeof(struct zd1201), GFP_KERNEL);
+	if (!zd) {
+		return -ENOMEM;
+	}
+	memset(zd, 0, sizeof(struct zd1201));
+	zd->ap = ap;
+	zd->usb = usb;
+	zd->removed = 0;
+	init_waitqueue_head(&zd->rxdataq);
+	INIT_HLIST_HEAD(&zd->fraglist);
+	
+	err = zd1201_fw_upload(usb, zd->ap);
+	if (err) {
+		dev_err(&usb->dev, "zd1201 firmware upload failed: %d\n", err);
+		goto err_zd;
+	}
+	
+	zd->endp_in = 1;
+	zd->endp_out = 1;
+	zd->endp_out2 = 2;
+	zd->rx_urb = usb_alloc_urb(0, GFP_KERNEL);
+	zd->tx_urb = usb_alloc_urb(0, GFP_KERNEL);
+	if (!zd->rx_urb || !zd->tx_urb)
+		goto err_zd;
+
+	for(i = 0; i<100; i++)
+		udelay(1000);
+
+	err = zd1201_drvr_start(zd);
+	if (err)
+		goto err_zd;
+
+	err = zd1201_setconfig16(zd, ZD1201_RID_CNFMAXDATALEN, 2312);
+	if (err)
+		goto err_start;
+
+	err = zd1201_setconfig16(zd, ZD1201_RID_TXRATECNTL,
+	    ZD1201_RATEB1 | ZD1201_RATEB2 | ZD1201_RATEB5 | ZD1201_RATEB11);
+	if (err)
+		goto err_start;
+
+	zd->dev = alloc_etherdev(0);
+	if (!zd->dev)
+		goto err_start;
+
+	zd->dev->priv = zd;
+	zd->dev->open = zd1201_net_open;
+	zd->dev->stop = zd1201_net_stop;
+	zd->dev->get_stats = zd1201_get_stats;
+	zd->dev->get_wireless_stats = zd1201_get_wireless_stats;
+	zd->dev->wireless_handlers =
+	    (struct iw_handler_def *)&zd1201_iw_handlers;
+	zd->dev->hard_start_xmit = zd1201_hard_start_xmit;
+	zd->dev->watchdog_timeo = ZD1201_TX_TIMEOUT;
+	zd->dev->tx_timeout = zd1201_tx_timeout;
+	zd->dev->set_multicast_list = zd1201_set_multicast;
+	zd->dev->set_mac_address = zd1201_set_mac_address;
+	strcpy(zd->dev->name, "wlan%d");
+
+	err = zd1201_getconfig(zd, ZD1201_RID_CNFOWNMACADDR, 
+	    zd->dev->dev_addr, zd->dev->addr_len);
+	if (err)
+		goto err_net;
+
+	/* Set wildcard essid to match zd->essid */
+	*(__le16 *)buf = cpu_to_le16(0);
+	err = zd1201_setconfig(zd, ZD1201_RID_CNFDESIREDSSID, buf,
+	    IW_ESSID_MAX_SIZE+2, 1);
+	if (err)
+		goto err_net;
+
+	if (zd->ap)
+		porttype = ZD1201_PORTTYPE_AP;
+	else
+		porttype = ZD1201_PORTTYPE_BSS;
+	err = zd1201_setconfig16(zd, ZD1201_RID_CNFPORTTYPE, porttype);
+	if (err)
+		goto err_net;
+
+	err = register_netdev(zd->dev);
+	if (err)
+		goto err_net;
+	dev_info(&usb->dev, "%s: ZD1201 USB Wireless interface\n",
+	    zd->dev->name);
+	
+	usb_set_intfdata(interface, zd);
+	return 0;
+
+err_net:
+	free_netdev(zd->dev);
+err_start:
+	/* Leave the device in reset state */
+	zd1201_docmd(zd, ZD1201_CMDCODE_INIT, 0, 0, 0);
+err_zd:
+	if (zd->tx_urb)
+		usb_free_urb(zd->tx_urb);
+	if (zd->rx_urb)
+		usb_free_urb(zd->rx_urb);
+	kfree(zd);
+	return err;
+}
+
+void zd1201_disconnect(struct usb_interface *interface)
+{
+	struct zd1201 *zd=(struct zd1201 *)usb_get_intfdata(interface);
+	struct hlist_node *node, *node2;
+	struct zd1201_frag *frag;
+
+	if (!zd)
+		return;
+	usb_set_intfdata(interface, NULL);
+	if (zd->dev) {
+		unregister_netdev(zd->dev);
+		free_netdev(zd->dev);
+	}
+
+	hlist_for_each_entry_safe(frag, node, node2, &zd->fraglist, fnode) {
+		hlist_del_init(&frag->fnode);
+		kfree_skb(frag->skb);
+		kfree(frag);
+	}
+
+	if (zd->tx_urb) {
+		usb_kill_urb(zd->tx_urb);
+		usb_free_urb(zd->tx_urb);
+	}
+	if (zd->rx_urb) {
+		usb_kill_urb(zd->rx_urb);
+		usb_free_urb(zd->rx_urb);
+	}
+	kfree(zd);
+}
+
+struct usb_driver zd1201_usb = {
+	.owner = THIS_MODULE,
+	.name = "zd1201",
+	.probe = zd1201_probe,
+	.disconnect = zd1201_disconnect,
+	.id_table = zd1201_table,
+};
+
+static int __init zd1201_init(void)
+{
+	return usb_register(&zd1201_usb);
+}
+
+static void __exit zd1201_cleanup(void)
+{
+	usb_deregister(&zd1201_usb);
+}
+
+module_init(zd1201_init);
+module_exit(zd1201_cleanup);
diff -Nru a/drivers/usb/net/zd1201.h b/drivers/usb/net/zd1201.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/usb/net/zd1201.h	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,147 @@
+/*
+ *	Copyright (c) 2004, 2005 Jeroen Vreeken (pe1rxq@amsat.org)
+ *
+ *	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.
+ *
+ *	Parts of this driver have been derived from a wlan-ng version
+ *	modified by ZyDAS.
+ *	Copyright (C) 1999 AbsoluteValue Systems, Inc.  All Rights Reserved.
+ */
+
+#ifndef _INCLUDE_ZD1201_H_
+#define _INCLUDE_ZD1201_H_
+
+#define ZD1201_NUMKEYS		4
+#define ZD1201_MAXKEYLEN	13
+#define ZD1201_MAXMULTI		16
+#define ZD1201_FRAGMAX		2500
+#define ZD1201_FRAGMIN		256
+#define ZD1201_RTSMAX		2500
+
+#define ZD1201_RXSIZE		3000
+
+struct zd1201 {
+	struct usb_device	*usb;
+	int			removed;
+	struct net_device	*dev;
+	struct net_device_stats stats;
+	struct iw_statistics	iwstats;
+
+	int			endp_in;
+	int			endp_out;
+	int			endp_out2;
+	struct urb		*rx_urb;
+	struct urb		*tx_urb;
+
+	unsigned char 		rxdata[ZD1201_RXSIZE];
+	int			rxlen;
+	wait_queue_head_t	rxdataq;
+	int			rxdatas;
+	struct hlist_head	fraglist;
+	unsigned char		txdata[ZD1201_RXSIZE];
+
+	int			ap;
+	char			essid[IW_ESSID_MAX_SIZE+1];
+	int			essidlen;
+	int			mac_enabled;
+	int			monitor;
+	int			encode_enabled;
+	int			encode_restricted;
+	unsigned char		encode_keys[ZD1201_NUMKEYS][ZD1201_MAXKEYLEN];
+	int			encode_keylen[ZD1201_NUMKEYS];
+};
+
+struct zd1201_frag {
+	struct hlist_node	fnode;
+	int			seq;
+	struct sk_buff		*skb;
+};
+
+#define ZD1201SIWHOSTAUTH SIOCIWFIRSTPRIV
+#define ZD1201GIWHOSTAUTH ZD1201SIWHOSTAUTH+1
+#define ZD1201SIWAUTHSTA SIOCIWFIRSTPRIV+2
+#define ZD1201SIWMAXASSOC SIOCIWFIRSTPRIV+4
+#define ZD1201GIWMAXASSOC ZD1201SIWMAXASSOC+1
+
+#define ZD1201_FW_TIMEOUT	(1000)
+
+#define ZD1201_TX_TIMEOUT	(2000)
+
+#define ZD1201_USB_CMDREQ	0
+#define ZD1201_USB_RESREQ	1
+
+#define	ZD1201_CMDCODE_INIT	0x00
+#define ZD1201_CMDCODE_ENABLE	0x01
+#define ZD1201_CMDCODE_DISABLE	0x02
+#define ZD1201_CMDCODE_ALLOC	0x0a
+#define ZD1201_CMDCODE_INQUIRE	0x11
+#define ZD1201_CMDCODE_SETRXRID	0x17
+#define ZD1201_CMDCODE_ACCESS	0x21
+
+#define ZD1201_PACKET_EVENTSTAT	0x0
+#define ZD1201_PACKET_RXDATA	0x1
+#define ZD1201_PACKET_INQUIRE	0x2
+#define ZD1201_PACKET_RESOURCE	0x3
+
+#define ZD1201_ACCESSBIT	0x0100
+
+#define ZD1201_RID_CNFPORTTYPE		0xfc00
+#define ZD1201_RID_CNFOWNMACADDR	0xfc01
+#define ZD1201_RID_CNFDESIREDSSID	0xfc02
+#define ZD1201_RID_CNFOWNCHANNEL	0xfc03
+#define ZD1201_RID_CNFOWNSSID		0xfc04
+#define ZD1201_RID_CNFMAXDATALEN	0xfc07
+#define ZD1201_RID_CNFPMENABLED		0xfc09
+#define ZD1201_RID_CNFPMEPS		0xfc0a
+#define ZD1201_RID_CNFMAXSLEEPDURATION	0xfc0c
+#define ZD1201_RID_CNFDEFAULTKEYID	0xfc23
+#define ZD1201_RID_CNFDEFAULTKEY0	0xfc24
+#define ZD1201_RID_CNFDEFAULTKEY1	0xfc25
+#define ZD1201_RID_CNFDEFAULTKEY2	0xfc26
+#define ZD1201_RID_CNFDEFAULTKEY3	0xfc27
+#define ZD1201_RID_CNFWEBFLAGS		0xfc28
+#define ZD1201_RID_CNFAUTHENTICATION	0xfc2a
+#define ZD1201_RID_CNFMAXASSOCSTATIONS	0xfc2b
+#define ZD1201_RID_CNFHOSTAUTH		0xfc2e
+#define ZD1201_RID_CNFGROUPADDRESS	0xfc80
+#define ZD1201_RID_CNFFRAGTHRESHOLD	0xfc82
+#define ZD1201_RID_CNFRTSTHRESHOLD	0xfc83
+#define ZD1201_RID_TXRATECNTL		0xfc84
+#define ZD1201_RID_PROMISCUOUSMODE	0xfc85
+#define ZD1201_RID_CNFBASICRATES	0xfcb3
+#define ZD1201_RID_AUTHENTICATESTA	0xfce3
+#define ZD1201_RID_CURRENTBSSID		0xfd42
+#define ZD1201_RID_COMMSQUALITY		0xfd43
+#define ZD1201_RID_CURRENTTXRATE	0xfd44
+#define ZD1201_RID_CNFMAXTXBUFFERNUMBER	0xfda0
+#define ZD1201_RID_CURRENTCHANNEL	0xfdc1
+
+#define ZD1201_INQ_SCANRESULTS		0xf101
+
+#define ZD1201_INF_LINKSTATUS		0xf200
+#define ZD1201_INF_ASSOCSTATUS		0xf201
+#define ZD1201_INF_AUTHREQ		0xf202
+
+#define ZD1201_ASSOCSTATUS_STAASSOC	0x1
+#define ZD1201_ASSOCSTATUS_REASSOC	0x2
+#define ZD1201_ASSOCSTATUS_DISASSOC	0x3
+#define ZD1201_ASSOCSTATUS_ASSOCFAIL	0x4
+#define ZD1201_ASSOCSTATUS_AUTHFAIL	0x5
+
+#define ZD1201_PORTTYPE_IBSS		0
+#define ZD1201_PORTTYPE_BSS		1
+#define ZD1201_PORTTYPE_WDS		2
+#define ZD1201_PORTTYPE_PSEUDOIBSS	3
+#define ZD1201_PORTTYPE_AP		6
+
+#define ZD1201_RATEB1	1
+#define ZD1201_RATEB2	2
+#define ZD1201_RATEB5	4	/* 5.5 really, but 5 is shorter :) */
+#define ZD1201_RATEB11	8
+
+#define ZD1201_CNFAUTHENTICATION_OPENSYSTEM	0
+#define ZD1201_CNFAUTHENTICATION_SHAREDKEY	1
+
+#endif /* _INCLUDE_ZD1201_H_ */
diff -Nru a/drivers/usb/serial/belkin_sa.c b/drivers/usb/serial/belkin_sa.c
--- a/drivers/usb/serial/belkin_sa.c	2005-03-11 12:51:47 -08:00
+++ b/drivers/usb/serial/belkin_sa.c	2005-03-11 12:51:47 -08:00
@@ -158,7 +158,7 @@
  * ***************************************************************************
  */
 
-#define WDR_TIMEOUT (HZ * 5 ) /* default urb timeout */
+#define WDR_TIMEOUT 5000 /* default urb timeout */
 
 /* assumes that struct usb_serial *serial is available */
 #define BSA_USB_CMD(c,v) usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), \
diff -Nru a/drivers/usb/serial/cyberjack.c b/drivers/usb/serial/cyberjack.c
--- a/drivers/usb/serial/cyberjack.c	2005-03-11 12:51:51 -08:00
+++ b/drivers/usb/serial/cyberjack.c	2005-03-11 12:51:51 -08:00
@@ -4,7 +4,7 @@
  *  Copyright (C) 2001  REINER SCT
  *  Author: Matthias Bruestle
  *
- *  Contact: linux-usb@sii.li (see MAINTAINERS)
+ *  Contact: support@reiner-sct.com (see MAINTAINERS)
  *
  *  This program is largely derived from work by the linux-usb group
  *  and associated source files.  Please see the usb/serial files for
@@ -20,6 +20,11 @@
  *
  *  In case of problems, please write to the contact e-mail address
  *  mentioned above.
+ *
+ *  Please note that later models of the cyberjack reader family are
+ *  supported by a libusb-based userspace device driver.
+ *
+ *  Homepage: http://www.reiner-sct.de/support/treiber_cyberjack.php#linux
  */
 
 
diff -Nru a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c
--- a/drivers/usb/serial/cypress_m8.c	2005-03-11 12:51:52 -08:00
+++ b/drivers/usb/serial/cypress_m8.c	2005-03-11 12:51:52 -08:00
@@ -57,9 +57,10 @@
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/spinlock.h>
-#include <asm/uaccess.h>
 #include <linux/usb.h>
 #include <linux/serial.h>
+#include <linux/delay.h>
+#include <asm/uaccess.h>
 
 #include "usb-serial.h"
 #include "cypress_m8.h"
@@ -1013,8 +1014,7 @@
 	cypress_serial_control(port, baud_mask, data_bits, stop_bits, parity_enable,
 			       parity_type, 0, CYPRESS_SET_CONFIG);
 
-	set_current_state(TASK_INTERRUPTIBLE);
-	schedule_timeout(50*HZ/1000); /* give some time between change and read (50ms) */ 
+	msleep(50);			/* give some time between change and read (50ms) */
 
 	/* we perform a CYPRESS_GET_CONFIG so that the current settings are filled into the private structure
          * this should confirm that all is working if it returns what we just set */
diff -Nru a/drivers/usb/serial/ezusb.c b/drivers/usb/serial/ezusb.c
--- a/drivers/usb/serial/ezusb.c	2005-03-11 12:51:41 -08:00
+++ b/drivers/usb/serial/ezusb.c	2005-03-11 12:51:41 -08:00
@@ -38,7 +38,7 @@
 		return -ENOMEM;
 	}
 	memcpy (transfer_buffer, data, length);
-	result = usb_control_msg (serial->dev, usb_sndctrlpipe(serial->dev, 0), bRequest, 0x40, address, 0, transfer_buffer, length, 3*HZ);
+	result = usb_control_msg (serial->dev, usb_sndctrlpipe(serial->dev, 0), bRequest, 0x40, address, 0, transfer_buffer, length, 3000);
 	kfree (transfer_buffer);
 	return result;
 }
diff -Nru a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
--- a/drivers/usb/serial/ftdi_sio.c	2005-03-11 12:51:50 -08:00
+++ b/drivers/usb/serial/ftdi_sio.c	2005-03-11 12:51:50 -08:00
@@ -296,6 +296,7 @@
 	{ USB_DEVICE_VER(FTDI_VID, FTDI_IRTRANS_PID, 0, 0x3ff) },
 	{ USB_DEVICE_VER(FTDI_VID, FTDI_8U232AM_PID, 0, 0x3ff) },
 	{ USB_DEVICE_VER(FTDI_VID, FTDI_8U232AM_ALT_PID, 0, 0x3ff) },
+	{ USB_DEVICE_VER(FTDI_VID, FTDI_8U232AM_ALT_ALT_PID, 0, 0x3ff) },
 	{ USB_DEVICE_VER(FTDI_VID, FTDI_RELAIS_PID, 0, 0x3ff) },
 	{ USB_DEVICE(INTERBIOMETRICS_VID, INTERBIOMETRICS_IOBOARD_PID) },
 	{ USB_DEVICE(INTERBIOMETRICS_VID, INTERBIOMETRICS_MINI_IOBOARD_PID) },
@@ -381,6 +382,7 @@
 	{ USB_DEVICE_VER(FTDI_VID, FTDI_IRTRANS_PID, 0x400, 0xffff) },
 	{ USB_DEVICE_VER(FTDI_VID, FTDI_8U232AM_PID, 0x400, 0xffff) },
 	{ USB_DEVICE_VER(FTDI_VID, FTDI_8U232AM_ALT_PID, 0x400, 0xffff) },
+	{ USB_DEVICE_VER(FTDI_VID, FTDI_8U232AM_ALT_ALT_PID, 0x400, 0xffff) },
 	{ USB_DEVICE_VER(FTDI_VID, FTDI_RELAIS_PID, 0x400, 0xffff) },
 	{ USB_DEVICE_VER(FTDI_NF_RIC_VID, FTDI_NF_RIC_PID, 0x400, 0xffff) },
 	{ USB_DEVICE_VER(FTDI_VID, FTDI_XF_632_PID, 0x400, 0xffff) },
@@ -515,6 +517,7 @@
 	{ USB_DEVICE(FTDI_VID, FTDI_SIO_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_8U232AM_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_8U232AM_ALT_PID) },
+	{ USB_DEVICE(FTDI_VID, FTDI_8U232AM_ALT_ALT_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_8U2232C_PID) },
 	{ USB_DEVICE(FTDI_VID, FTDI_RELAIS_PID) },
 	{ USB_DEVICE(INTERBIOMETRICS_VID, INTERBIOMETRICS_IOBOARD_PID) },
@@ -852,7 +855,7 @@
 
 
 
-#define WDR_TIMEOUT (HZ * 5 ) /* default urb timeout */
+#define WDR_TIMEOUT 5000 /* default urb timeout */
 
 /* High and low are for DTR, RTS etc etc */
 #define HIGH 1
diff -Nru a/drivers/usb/serial/ftdi_sio.h b/drivers/usb/serial/ftdi_sio.h
--- a/drivers/usb/serial/ftdi_sio.h	2005-03-11 12:51:51 -08:00
+++ b/drivers/usb/serial/ftdi_sio.h	2005-03-11 12:51:51 -08:00
@@ -26,6 +26,7 @@
 #define FTDI_SIO_PID	0x8372	/* Product Id SIO application of 8U100AX  */
 #define FTDI_8U232AM_PID 0x6001 /* Similar device to SIO above */
 #define FTDI_8U232AM_ALT_PID 0x6006 /* FTDI's alternate PID for above */
+#define FTDI_8U232AM_ALT_ALT_PID 0xf3c0 /* FTDI's second alternate PID for above */
 #define FTDI_8U2232C_PID 0x6010 /* Dual channel device */
 #define FTDI_RELAIS_PID	0xFA10  /* Relais device from Rudolf Gugler */
 #define FTDI_NF_RIC_VID	0x0DCD	/* Vendor Id */
diff -Nru a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c
--- a/drivers/usb/serial/io_edgeport.c	2005-03-11 12:51:41 -08:00
+++ b/drivers/usb/serial/io_edgeport.c	2005-03-11 12:51:41 -08:00
@@ -261,6 +261,7 @@
 #include <linux/spinlock.h>
 #include <linux/serial.h>
 #include <linux/ioctl.h>
+#include <linux/wait.h>
 #include <asm/uaccess.h>
 #include <linux/usb.h>
 #include "usb-serial.h"
@@ -971,7 +972,7 @@
 
 	/* we have completed the command */
 	edge_port->commandPending = FALSE;
-	wake_up_interruptible(&edge_port->wait_command);
+	wake_up(&edge_port->wait_command);
 }
 
 
@@ -991,7 +992,6 @@
 	struct usb_serial *serial;
 	struct edgeport_serial *edge_serial;
 	int response;
-	int timeout;
 
 	dbg("%s - port %d", __FUNCTION__, port->number);
 
@@ -1073,10 +1073,7 @@
 	}
 
 	/* now wait for the port to be completely opened */
-	timeout = OPEN_TIMEOUT;
-	while (timeout && edge_port->openPending == TRUE) {
-		timeout = interruptible_sleep_on_timeout (&edge_port->wait_open, timeout);
-	}
+	wait_event_timeout(edge_port->wait_open, (edge_port->openPending != TRUE), OPEN_TIMEOUT);
 
 	if (edge_port->open == FALSE) {
 		/* open timed out */
@@ -1128,9 +1125,10 @@
  ************************************************************************/
 static void block_until_chase_response(struct edgeport_port *edge_port)
 {
+	DEFINE_WAIT(wait);
 	__u16 lastCredits;
 	int timeout = 1*HZ;
-	int wait = 10;
+	int loop = 10;
 
 	while (1) {
 		// Save Last credits
@@ -1148,12 +1146,14 @@
 		}
 
 		// Block the thread for a while
-		interruptible_sleep_on_timeout (&edge_port->wait_chase, timeout);
+		prepare_to_wait(&edge_port->wait_chase, &wait, TASK_UNINTERRUPTIBLE);
+		schedule_timeout(timeout);
+		finish_wait(&edge_port->wait_chase, &wait);
 
 		if (lastCredits == edge_port->txCredits) {
 			// No activity.. count down.
-			wait--;
-			if (wait == 0) {
+			loop--;
+			if (loop == 0) {
 				edge_port->chaseResponsePending = FALSE;
 				dbg("%s - Chase TIMEOUT", __FUNCTION__);
 				return;
@@ -1161,7 +1161,7 @@
 		} else {
 			// Reset timout value back to 10 seconds
 			dbg("%s - Last %d, Current %d", __FUNCTION__, lastCredits, edge_port->txCredits);
-			wait = 10;
+			loop = 10;
 		}
 	}
 }
@@ -1179,10 +1179,11 @@
  ************************************************************************/
 static void block_until_tx_empty (struct edgeport_port *edge_port)
 {
+	DEFINE_WAIT(wait);
 	struct TxFifo *fifo = &edge_port->txfifo;
 	__u32 lastCount;
 	int timeout = HZ/10;
-	int wait = 30;
+	int loop = 30;
 
 	while (1) {
 		// Save Last count
@@ -1195,20 +1196,22 @@
 		}
 
 		// Block the thread for a while
-		interruptible_sleep_on_timeout (&edge_port->wait_chase, timeout);
+		prepare_to_wait (&edge_port->wait_chase, &wait, TASK_UNINTERRUPTIBLE);
+		schedule_timeout(timeout);
+		finish_wait(&edge_port->wait_chase, &wait);
 
 		dbg("%s wait", __FUNCTION__);
 
 		if (lastCount == fifo->count) {
 			// No activity.. count down.
-			wait--;
-			if (wait == 0) {
+			loop--;
+			if (loop == 0) {
 				dbg("%s - TIMEOUT", __FUNCTION__);
 				return;
 			}
 		} else {
 			// Reset timout value back to seconds
-			wait = 30;
+			loop = 30;
 		}
 	}
 }
@@ -1836,12 +1839,12 @@
  *****************************************************************************/
 static int edge_ioctl (struct usb_serial_port *port, struct file *file, unsigned int cmd, unsigned long arg)
 {
+	DEFINE_WAIT(wait);
 	struct edgeport_port *edge_port = usb_get_serial_port_data(port);
 	struct async_icount cnow;
 	struct async_icount cprev;
 	struct serial_icounter_struct icount;
 
-
 	dbg("%s - port %d, cmd = 0x%x", __FUNCTION__, port->number, cmd);
 
 	switch (cmd) {
@@ -1868,7 +1871,9 @@
 			dbg("%s (%d) TIOCMIWAIT", __FUNCTION__,  port->number);
 			cprev = edge_port->icount;
 			while (1) {
-				interruptible_sleep_on(&edge_port->delta_msr_wait);
+				prepare_to_wait(&edge_port->delta_msr_wait, &wait, TASK_INTERRUPTIBLE);
+				schedule();
+				finish_wait(&edge_port->delta_msr_wait, &wait);
 				/* see if a signal did it */
 				if (signal_pending(current))
 					return -ERESTARTSYS;
@@ -2108,7 +2113,7 @@
 				// We could choose to do something else when Byte3 says Timeout on Chase from Edgeport,
 				// like wait longer in block_until_chase_response, but for now we don't. 
 				edge_port->chaseResponsePending = FALSE;
-				wake_up_interruptible (&edge_port->wait_chase);
+				wake_up (&edge_port->wait_chase);
 				return;
 
 			case IOSP_EXT_STATUS_RX_CHECK_RSP:
@@ -2131,7 +2136,7 @@
 		/* we have completed the open */
 		edge_port->openPending = FALSE;
 		edge_port->open = TRUE;
-		wake_up_interruptible(&edge_port->wait_open);
+		wake_up(&edge_port->wait_open);
 		return;
 	}
 
@@ -2500,9 +2505,7 @@
 	// wait for command to finish
 	timeout = COMMAND_TIMEOUT;
 #if 0
-	while (timeout && edge_port->commandPending == TRUE) {
-		timeout = interruptible_sleep_on_timeout (&edge_port->wait_command, timeout);
-	}
+	wait_event (&edge_port->wait_command, (edge_port->commandPending == FALSE));
 
 	if (edge_port->commandPending == TRUE) {
 		/* command timed out */
diff -Nru a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c
--- a/drivers/usb/serial/io_ti.c	2005-03-11 12:51:51 -08:00
+++ b/drivers/usb/serial/io_ti.c	2005-03-11 12:51:51 -08:00
@@ -273,7 +273,7 @@
 				index,
 				data,
 				size,
-				HZ);
+				1000);
 	if (status < 0)
 		return status;
 	if (status != size) {
@@ -303,8 +303,7 @@
 				index,
 				data,
 				size,
-				HZ);
-
+				1000);
 	if (status < 0)
 		return status;
 	if (status != size) {
@@ -985,7 +984,7 @@
 				buffer,
 				length,
 				num_sent,
-				HZ);
+				1000);
 	return status;
 }
 
diff -Nru a/drivers/usb/serial/ipaq.c b/drivers/usb/serial/ipaq.c
--- a/drivers/usb/serial/ipaq.c	2005-03-11 12:51:51 -08:00
+++ b/drivers/usb/serial/ipaq.c	2005-03-11 12:51:51 -08:00
@@ -662,7 +662,7 @@
 	while (retries--) {
 		result = usb_control_msg(serial->dev,
 				usb_sndctrlpipe(serial->dev, 0), 0x22, 0x21,
-				0x1, 0, NULL, 0, HZ / 10 + 1);
+				0x1, 0, NULL, 0, 100);
 		if (result == 0) {
 			return 0;
 		}
diff -Nru a/drivers/usb/serial/ipw.c b/drivers/usb/serial/ipw.c
--- a/drivers/usb/serial/ipw.c	2005-03-11 12:51:42 -08:00
+++ b/drivers/usb/serial/ipw.c	2005-03-11 12:51:42 -08:00
@@ -232,7 +232,7 @@
 				 0, /* index */
 				 NULL,
 				 0,
-				 100*HZ);
+				 100000);
 	if (result < 0)
 		dev_err(&port->dev, "Init of modem failed (error = %d)", result);
 
@@ -260,7 +260,7 @@
 				 0, /* index */
 				 NULL,
 				 0,
-				 100*HZ);
+				 100000);
 	if (result < 0) 
 		dev_err(&port->dev, "Enabling bulk RxRead failed (error = %d)", result);
 
@@ -273,7 +273,7 @@
 				 0,
 				 buf_flow_init,
 				 0x10,
-				 200*HZ);
+				 200000);
 	if (result < 0)
 		dev_err(&port->dev, "initial flowcontrol failed (error = %d)", result);
 
@@ -287,7 +287,7 @@
 				 0,
 				 NULL,
 				 0,
-				 200*HZ);
+				 200000);
 	if (result < 0)
 		dev_err(&port->dev, "setting dtr failed (error = %d)", result);
 
@@ -300,7 +300,7 @@
 				 0,
 				 NULL,
 				 0,
-				 200*HZ);
+				 200000);
 	if (result < 0)
 		dev_err(&port->dev, "setting dtr failed (error = %d)", result);
 	
@@ -327,7 +327,7 @@
 				 0,
 				 NULL,
 				 0,
-				 200*HZ);
+				 200000);
 	if (result < 0)
 		dev_err(&port->dev, "dropping dtr failed (error = %d)", result);
 
@@ -339,7 +339,7 @@
 				 0,
 				 NULL,
 				 0,
-				 200*HZ);
+				 200000);
 	if (result < 0)
 		dev_err(&port->dev, "dropping rts failed (error = %d)", result);
 
@@ -352,7 +352,7 @@
 				 0,
 				 NULL,
 				 0,
-				 200*HZ);
+				 200000);
 	if (result < 0)
 		dev_err(&port->dev, "purge failed (error = %d)", result);
 
@@ -365,7 +365,7 @@
 				 0, /* index */
 				 NULL,
 				 0,
-				 100*HZ);
+				 100000);
 
 	if (result < 0)
 		dev_err(&port->dev, "Disabling bulk RxRead failed (error = %d)", result);
diff -Nru a/drivers/usb/serial/ir-usb.c b/drivers/usb/serial/ir-usb.c
--- a/drivers/usb/serial/ir-usb.c	2005-03-11 12:51:46 -08:00
+++ b/drivers/usb/serial/ir-usb.c	2005-03-11 12:51:46 -08:00
@@ -189,7 +189,7 @@
 	ret = usb_control_msg(dev, usb_rcvctrlpipe(dev,0),
 			IU_REQ_GET_CLASS_DESC,
 			USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
-			0, ifnum, desc, sizeof(*desc), HZ);
+			0, ifnum, desc, sizeof(*desc), 1000);
 	
 	dbg("%s -  ret=%d", __FUNCTION__, ret);
 	if (ret < sizeof(*desc)) {
diff -Nru a/drivers/usb/serial/keyspan_pda.c b/drivers/usb/serial/keyspan_pda.c
--- a/drivers/usb/serial/keyspan_pda.c	2005-03-11 12:51:47 -08:00
+++ b/drivers/usb/serial/keyspan_pda.c	2005-03-11 12:51:47 -08:00
@@ -205,7 +205,7 @@
 				 0, /* index */
 				 NULL,
 				 0,
-				 2*HZ);
+				 2000);
 	if (result < 0)
 		dbg("%s - error %d from usb_control_msg", 
 		    __FUNCTION__, result);
@@ -330,7 +330,7 @@
 			     0, /* index */
 			     NULL, /* &data */
 			     0, /* size */
-			     2*HZ); /* timeout */
+			     2000); /* timeout */
 	return(rc);
 }
 
@@ -348,7 +348,7 @@
 	result = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
 				4, /* set break */
 				USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT,
-				value, 0, NULL, 0, 2*HZ);
+				value, 0, NULL, 0, 2000);
 	if (result < 0)
 		dbg("%s - error %d from usb_control_msg", 
 		    __FUNCTION__, result);
@@ -416,7 +416,7 @@
 	rc = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
 			     3, /* get pins */
 			     USB_TYPE_VENDOR|USB_RECIP_INTERFACE|USB_DIR_IN,
-			     0, 0, &data, 1, 2*HZ);
+			     0, 0, &data, 1, 2000);
 	if (rc > 0)
 		*value = data;
 	return rc;
@@ -430,7 +430,7 @@
 	rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
 			     3, /* set pins */
 			     USB_TYPE_VENDOR|USB_RECIP_INTERFACE|USB_DIR_OUT,
-			     value, 0, NULL, 0, 2*HZ);
+			     value, 0, NULL, 0, 2000);
 	return rc;
 }
 
@@ -545,7 +545,7 @@
 				     0, /* index */
 				     &room,
 				     1,
-				     2*HZ);
+				     2000);
 		if (rc < 0) {
 			dbg(" roomquery failed");
 			goto exit;
@@ -653,7 +653,7 @@
 			     0, /* index */
 			     &room,
 			     1,
-			     2*HZ);
+			     2000);
 	if (rc < 0) {
 		dbg("%s - roomquery failed", __FUNCTION__);
 		goto error;
diff -Nru a/drivers/usb/serial/kl5kusb105.c b/drivers/usb/serial/kl5kusb105.c
--- a/drivers/usb/serial/kl5kusb105.c	2005-03-11 12:51:46 -08:00
+++ b/drivers/usb/serial/kl5kusb105.c	2005-03-11 12:51:46 -08:00
@@ -178,7 +178,7 @@
  */
 
 
-#define KLSI_TIMEOUT	 (HZ * 5 ) /* default urb timeout */
+#define KLSI_TIMEOUT	 5000 /* default urb timeout */
 
 static int klsi_105_chg_port_settings(struct usb_serial_port *port,
 				      struct klsi_105_port_settings *settings)
diff -Nru a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c
--- a/drivers/usb/serial/mct_u232.c	2005-03-11 12:51:47 -08:00
+++ b/drivers/usb/serial/mct_u232.c	2005-03-11 12:51:47 -08:00
@@ -166,7 +166,7 @@
  * Handle vendor specific USB requests
  */
 
-#define WDR_TIMEOUT (HZ * 5 ) /* default urb timeout */
+#define WDR_TIMEOUT 5000 /* default urb timeout */
 
 /*
  * Later day 2.6.0-test kernels have new baud rates like B230400 which
diff -Nru a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c
--- a/drivers/usb/serial/ti_usb_3410_5052.c	2005-03-11 12:51:52 -08:00
+++ b/drivers/usb/serial/ti_usb_3410_5052.c	2005-03-11 12:51:52 -08:00
@@ -1580,7 +1580,7 @@
 	status = usb_control_msg(tdev->td_serial->dev,
 		usb_sndctrlpipe(tdev->td_serial->dev, 0), command,
 		(USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT),
-		value, moduleid, data, size, HZ);
+		value, moduleid, data, size, 1000);
 
 	if (status == size)
 		status = 0;
@@ -1600,7 +1600,7 @@
 	status = usb_control_msg(tdev->td_serial->dev,
 		usb_rcvctrlpipe(tdev->td_serial->dev, 0), command,
 		(USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN),
-		value, moduleid, data, size, HZ);
+		value, moduleid, data, size, 1000);
 
 	if (status == size)
 		status = 0;
@@ -1685,7 +1685,7 @@
 	dbg("%s - downloading firmware", __FUNCTION__);
 	for (pos = 0; pos < buffer_size; pos += done) {
 		len = min(buffer_size - pos, TI_DOWNLOAD_MAX_PACKET_SIZE);
-		status = usb_bulk_msg(dev, pipe, buffer+pos, len, &done, HZ);
+		status = usb_bulk_msg(dev, pipe, buffer+pos, len, &done, 1000);
 		if (status)
 			break;
 	}
diff -Nru a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c
--- a/drivers/usb/serial/visor.c	2005-03-11 12:51:42 -08:00
+++ b/drivers/usb/serial/visor.c	2005-03-11 12:51:42 -08:00
@@ -891,7 +891,7 @@
 	/* get the config number */
 	result = usb_control_msg (serial->dev, usb_rcvctrlpipe(serial->dev, 0),
 				  USB_REQ_GET_CONFIGURATION, USB_DIR_IN,
-				  0, 0, &data, 1, HZ * 3);
+				  0, 0, &data, 1, 3000);
 	if (result < 0) {
 		dev_err(dev, "%s: get config number failed: %d\n", __FUNCTION__, result);
 		return result;
@@ -905,7 +905,7 @@
 	result = usb_control_msg (serial->dev, usb_rcvctrlpipe(serial->dev, 0),
 				  USB_REQ_GET_INTERFACE, 
 				  USB_DIR_IN | USB_RECIP_INTERFACE,
-				  0, 0, &data, 1, HZ * 3);
+				  0, 0, &data, 1, 3000);
 	if (result < 0) {
 		dev_err(dev, "%s: get interface number failed: %d\n", __FUNCTION__, result);
 		return result;
diff -Nru a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c
--- a/drivers/usb/serial/whiteheat.c	2005-03-11 12:51:42 -08:00
+++ b/drivers/usb/serial/whiteheat.c	2005-03-11 12:51:42 -08:00
@@ -254,6 +254,7 @@
 
 #define COMMAND_PORT		4
 #define COMMAND_TIMEOUT		(2*HZ)	/* 2 second timeout for a command */
+#define	COMMAND_TIMEOUT_MS	2000
 #define CLOSING_DELAY		(30 * HZ)
 
 
@@ -379,7 +380,7 @@
          * unlinking bug in disguise. Same for the call below.
          */
 	usb_clear_halt(serial->dev, pipe);
-	ret = usb_bulk_msg (serial->dev, pipe, command, 2, &alen, COMMAND_TIMEOUT);
+	ret = usb_bulk_msg (serial->dev, pipe, command, 2, &alen, COMMAND_TIMEOUT_MS);
 	if (ret) {
 		err("%s: Couldn't send command [%d]", serial->type->name, ret);
 		goto no_firmware;
@@ -391,7 +392,7 @@
 	pipe = usb_rcvbulkpipe (serial->dev, command_port->bulk_in_endpointAddress);
 	/* See the comment on the usb_clear_halt() above */
 	usb_clear_halt(serial->dev, pipe);
-	ret = usb_bulk_msg (serial->dev, pipe, result, sizeof(*hw_info) + 1, &alen, COMMAND_TIMEOUT);
+	ret = usb_bulk_msg (serial->dev, pipe, result, sizeof(*hw_info) + 1, &alen, COMMAND_TIMEOUT_MS);
 	if (ret) {
 		err("%s: Couldn't get results [%d]", serial->type->name, ret);
 		goto no_firmware;
diff -Nru a/drivers/usb/storage/Kconfig b/drivers/usb/storage/Kconfig
--- a/drivers/usb/storage/Kconfig	2005-03-11 12:51:51 -08:00
+++ b/drivers/usb/storage/Kconfig	2005-03-11 12:51:51 -08:00
@@ -89,12 +89,26 @@
 	  Say Y here to support the Microtech/ZiO! CompactFlash reader.
 	  There is a web page at <http://www.ziocorp.com/products/>.
 
-config USB_STORAGE_HP8200e
-	bool "HP CD-Writer 82xx support (EXPERIMENTAL)"
+config USB_STORAGE_USBAT
+	bool "USBAT/USBAT02-based storage support (EXPERIMENTAL)"
 	depends on USB_STORAGE && EXPERIMENTAL
 	help
-	  Say Y here to include additional code to support Hewlett-Packard
-	  8200e/8210e/8230e CD-Writer Plus drives.
+	  Say Y here to include additional code to support storage devices
+	  based on the SCM/Shuttle USBAT/USBAT02 processors.
+
+	  Devices reported to work with this driver include:
+	  - CompactFlash reader included with Kodak DC3800 camera
+	  - Dane-Elec Zmate CompactFlash reader
+	  - Delkin Efilm reader2
+	  - HP 8200e/8210e/8230e CD-Writer Plus drives
+	  - I-JAM JS-50U
+	  - Jessops CompactFlash JESDCFRU BLACK
+	  - Kingston Technology PCREAD-USB/CF
+	  - Maxell UA4 CompactFlash reader
+	  - Memorex UCF-100
+	  - Microtech ZiO! ICS-45 CF2
+	  - RCA LYRA MP3 portable
+	  - Sandisk ImageMate SDDR-05b
 
 config USB_STORAGE_SDDR09
 	bool "SanDisk SDDR-09 (and other SmartMedia) support (EXPERIMENTAL)"
diff -Nru a/drivers/usb/storage/Makefile b/drivers/usb/storage/Makefile
--- a/drivers/usb/storage/Makefile	2005-03-11 12:51:47 -08:00
+++ b/drivers/usb/storage/Makefile	2005-03-11 12:51:47 -08:00
@@ -10,7 +10,7 @@
 obj-$(CONFIG_USB_STORAGE)	+= usb-storage.o
 
 usb-storage-obj-$(CONFIG_USB_STORAGE_DEBUG)	+= debug.o
-usb-storage-obj-$(CONFIG_USB_STORAGE_HP8200e)	+= shuttle_usbat.o
+usb-storage-obj-$(CONFIG_USB_STORAGE_USBAT)	+= shuttle_usbat.o
 usb-storage-obj-$(CONFIG_USB_STORAGE_SDDR09)	+= sddr09.o
 usb-storage-obj-$(CONFIG_USB_STORAGE_SDDR55)	+= sddr55.o
 usb-storage-obj-$(CONFIG_USB_STORAGE_FREECOM)	+= freecom.o
diff -Nru a/drivers/usb/storage/protocol.c b/drivers/usb/storage/protocol.c
--- a/drivers/usb/storage/protocol.c	2005-03-11 12:51:40 -08:00
+++ b/drivers/usb/storage/protocol.c	2005-03-11 12:51:40 -08:00
@@ -54,39 +54,6 @@
 #include "transport.h"
 
 /***********************************************************************
- * Helper routines
- ***********************************************************************/
-
-/*
- * Fix-up the return data from a READ CAPACITY command. My Feiya reader
- * returns a value that is 1 too large.
- */
-static void fix_read_capacity(struct scsi_cmnd *srb)
-{
-	unsigned int index, offset;
-	__be32 c;
-	unsigned long capacity;
-
-	/* verify that it's a READ CAPACITY command */
-	if (srb->cmnd[0] != READ_CAPACITY)
-		return;
-
-	index = offset = 0;
-	if (usb_stor_access_xfer_buf((unsigned char *) &c, 4, srb,
-			&index, &offset, FROM_XFER_BUF) != 4)
-		return;
-
-	capacity = be32_to_cpu(c);
-	US_DEBUGP("US: Fixing capacity: from %ld to %ld\n",
-	       capacity+1, capacity);
-	c = cpu_to_be32(capacity - 1);
-
-	index = offset = 0;
-	usb_stor_access_xfer_buf((unsigned char *) &c, 4, srb,
-			&index, &offset, TO_XFER_BUF);
-}
-
-/***********************************************************************
  * Protocol routines
  ***********************************************************************/
 
@@ -174,12 +141,6 @@
 {
 	/* send the command to the transport layer */
 	usb_stor_invoke_transport(srb, us);
-
-	if (srb->result == SAM_STAT_GOOD) {
-		/* Fix the READ CAPACITY result if necessary */
-		if (us->flags & US_FL_FIX_CAPACITY)
-			fix_read_capacity(srb);
-	}
 }
 
 /***********************************************************************
diff -Nru a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c
--- a/drivers/usb/storage/scsiglue.c	2005-03-11 12:51:46 -08:00
+++ b/drivers/usb/storage/scsiglue.c	2005-03-11 12:51:46 -08:00
@@ -149,6 +149,11 @@
 		sdev->skip_ms_page_3f = 1;
 #endif
 
+		/* Some disks return the total number of blocks in response
+		 * to READ CAPACITY rather than the highest block number.
+		 * If this device makes that mistake, tell the sd driver. */
+		if (us->flags & US_FL_FIX_CAPACITY)
+			sdev->fix_capacity = 1;
 	} else {
 
 		/* Non-disk-type devices don't need to blacklist any pages
@@ -157,6 +162,11 @@
 		sdev->use_10_for_ms = 1;
 	}
 
+	/* Some devices choke when they receive a PREVENT-ALLOW MEDIUM
+	 * REMOVAL command, so suppress those commands. */
+	if (us->flags & US_FL_NOT_LOCKABLE)
+		sdev->lockable = 0;
+
 	/* this is to satisfy the compiler, tho I don't think the 
 	 * return code is ever checked anywhere. */
 	return 0;
@@ -346,9 +356,22 @@
 	SPRINTF("   Host scsi%d: usb-storage\n", hostptr->host_no);
 
 	/* print product, vendor, and serial number strings */
-	SPRINTF("       Vendor: %s\n", us->vendor);
-	SPRINTF("      Product: %s\n", us->product);
-	SPRINTF("Serial Number: %s\n", us->serial);
+	if (us->pusb_dev->manufacturer)
+		SPRINTF("       Vendor: %s\n", us->pusb_dev->manufacturer);
+	else if (us->unusual_dev->vendorName)
+		SPRINTF("       Vendor: %s\n", us->unusual_dev->vendorName);
+	else
+		SPRINTF("       Vendor: Unknown\n");
+	if (us->pusb_dev->product)
+		SPRINTF("      Product: %s\n", us->pusb_dev->product);
+	else if (us->unusual_dev->productName)
+		SPRINTF("      Product: %s\n", us->unusual_dev->productName);
+	else
+		SPRINTF("      Product: Unknown\n");
+	if (us->pusb_dev->serial)
+		SPRINTF("Serial Number: %s\n", us->pusb_dev->serial);
+	else
+		SPRINTF("Serial Number: None\n");
 
 	/* show the protocol and transport */
 	SPRINTF("     Protocol: %s\n", us->protocol_name);
diff -Nru a/drivers/usb/storage/shuttle_usbat.c b/drivers/usb/storage/shuttle_usbat.c
--- a/drivers/usb/storage/shuttle_usbat.c	2005-03-11 12:51:40 -08:00
+++ b/drivers/usb/storage/shuttle_usbat.c	2005-03-11 12:51:40 -08:00
@@ -4,10 +4,14 @@
  *
  * Current development and maintenance by:
  *   (c) 2000, 2001 Robert Baruch (autophile@starband.net)
+ *   (c) 2004, 2005 Daniel Drake <dsd@gentoo.org>
  *
  * Developed with the assistance of:
  *   (c) 2002 Alan Stern <stern@rowland.org>
  *
+ * Flash support based on earlier work by:
+ *   (c) 2002 Thomas Kreiling <usbdev@sm04.de>
+ *
  * Many originally ATAPI devices were slightly modified to meet the USB
  * market by using some kind of translation from ATAPI to USB on the host,
  * and the peripheral would translate from USB back to ATAPI.
@@ -21,8 +25,8 @@
  * as well. This driver is only guaranteed to work with the ATAPI
  * translation.
  *
- * The only peripheral that I know of (as of 27 Mar 2001) that uses this
- * device is the Hewlett-Packard 8200e/8210e/8230e CD-Writer Plus.
+ * See the Kconfig help text for a list of devices known to be supported by
+ * this driver.
  *
  * 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
@@ -59,44 +63,149 @@
 
 int transferred = 0;
 
+/*
+ * Convenience function to produce an ATAPI read/write sectors command
+ * Use cmd=0x20 for read, cmd=0x30 for write
+ */
+static void usbat_pack_atapi_sector_cmd(unsigned char *buf,
+					unsigned char thistime,
+					u32 sector, unsigned char cmd)
+{
+	buf[0] = 0;
+	buf[1] = thistime;
+	buf[2] = sector & 0xFF;
+	buf[3] = (sector >>  8) & 0xFF;
+	buf[4] = (sector >> 16) & 0xFF;
+	buf[5] = 0xE0 | ((sector >> 24) & 0x0F);
+	buf[6] = cmd;
+}
+
+/*
+ * Convenience function to get the device type (flash or hp8200)
+ */
+static int usbat_get_device_type(struct us_data *us)
+{
+	return ((struct usbat_info*)us->extra)->devicetype;
+}
+
+/*
+ * Read a register from the device
+ */
 static int usbat_read(struct us_data *us,
 		      unsigned char access,
 		      unsigned char reg,
 		      unsigned char *content)
 {
-	int result;
-
-	result = usb_stor_ctrl_transfer(us,
+	return usb_stor_ctrl_transfer(us,
 		us->recv_ctrl_pipe,
-		access,
+		access | USBAT_CMD_READ_REG,
 		0xC0,
 		(u16)reg,
 		0,
 		content,
 		1);
-
-	return result;
 }
 
+/*
+ * Write to a register on the device
+ */
 static int usbat_write(struct us_data *us,
 		       unsigned char access,
 		       unsigned char reg,
 		       unsigned char content)
 {
-	int result;
-
-	result = usb_stor_ctrl_transfer(us,
+	return usb_stor_ctrl_transfer(us,
 		us->send_ctrl_pipe,
-		access|0x01,
+		access | USBAT_CMD_WRITE_REG,
 		0x40,
 		short_pack(reg, content),
 		0,
 		NULL,
 		0);
+}
 
-	return result;
+/*
+ * Convenience function to perform a bulk read
+ */
+static int usbat_bulk_read(struct us_data *us,
+							 unsigned char *data,
+							 unsigned int len)
+{
+	if (len == 0)
+		return USB_STOR_XFER_GOOD;
+
+	US_DEBUGP("usbat_bulk_read: len = %d\n", len);
+	return usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe, data, len, NULL);
 }
 
+/*
+ * Convenience function to perform a bulk write
+ */
+static int usbat_bulk_write(struct us_data *us,
+							unsigned char *data,
+							unsigned int len)
+{
+	if (len == 0)
+		return USB_STOR_XFER_GOOD;
+
+	US_DEBUGP("usbat_bulk_write:  len = %d\n", len);
+	return usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe, data, len, NULL);
+}
+
+/*
+ * Some USBAT-specific commands can only be executed over a command transport
+ * This transport allows one (len=8) or two (len=16) vendor-specific commands
+ * to be executed.
+ */
+static int usbat_execute_command(struct us_data *us,
+								 unsigned char *commands,
+								 unsigned int len)
+{
+	return usb_stor_ctrl_transfer(us, us->send_ctrl_pipe,
+								  USBAT_CMD_EXEC_CMD, 0x40, 0, 0,
+								  commands, len);
+}
+
+/*
+ * Read the status register
+ */
+static int usbat_get_status(struct us_data *us, unsigned char *status)
+{
+	int rc;
+	rc = usbat_read(us, USBAT_ATA, USBAT_ATA_STATUS, status);
+
+	US_DEBUGP("usbat_get_status: 0x%02X\n", (unsigned short) (*status));
+	return rc;
+}
+
+/*
+ * Check the device status
+ */
+static int usbat_check_status(struct us_data *us)
+{
+	unsigned char *reply = us->iobuf;
+	int rc;
+
+	if (!us)
+		return USB_STOR_TRANSPORT_ERROR;
+
+	rc = usbat_get_status(us, reply);
+	if (rc != USB_STOR_XFER_GOOD)
+		return USB_STOR_TRANSPORT_FAILED;
+
+	if (*reply & 0x01 && *reply != 0x51) // error/check condition (0x51 is ok)
+		return USB_STOR_TRANSPORT_FAILED;
+
+	if (*reply & 0x20) // device fault
+		return USB_STOR_TRANSPORT_FAILED;
+
+	return USB_STOR_TRANSPORT_GOOD;
+}
+
+/*
+ * Stores critical information in internal registers in prepartion for the execution
+ * of a conditional usbat_read_blocks or usbat_write_blocks call.
+ */
 static int usbat_set_shuttle_features(struct us_data *us,
 				      unsigned char external_trigger,
 				      unsigned char epp_control,
@@ -105,76 +214,44 @@
 				      unsigned char subcountH,
 				      unsigned char subcountL)
 {
-	int result;
 	unsigned char *command = us->iobuf;
 
 	command[0] = 0x40;
-	command[1] = 0x81;
+	command[1] = USBAT_CMD_SET_FEAT;
+
+	// The only bit relevant to ATA access is bit 6
+	// which defines 8 bit data access (set) or 16 bit (unset)
 	command[2] = epp_control;
+
+	// If FCQ is set in the qualifier (defined in R/W cmd), then bits U0, U1,
+	// ET1 and ET2 define an external event to be checked for on event of a
+	// _read_blocks or _write_blocks operation. The read/write will not take
+	// place unless the defined trigger signal is active.
 	command[3] = external_trigger;
+
+	// The resultant byte of the mask operation (see mask_byte) is compared for
+	// equivalence with this test pattern. If equal, the read/write will take
+	// place.
 	command[4] = test_pattern;
+
+	// This value is logically ANDed with the status register field specified
+	// in the read/write command.
 	command[5] = mask_byte;
+
+	// If ALQ is set in the qualifier, this field contains the address of the
+	// registers where the byte count should be read for transferring the data.
+	// If ALQ is not set, then this field contains the number of bytes to be
+	// transferred.
 	command[6] = subcountL;
 	command[7] = subcountH;
 
-	result = usb_stor_ctrl_transfer(us,
-		us->send_ctrl_pipe,
-		0x80,
-		0x40,
-		0,
-		0,
-		command,
-		8);
-
-	return result;
-}
-
-static int usbat_read_block(struct us_data *us,
-			    unsigned char access,
-			    unsigned char reg,
-			    unsigned char *content,
-			    unsigned short len,
-			    int use_sg)
-{
-	int result;
-	unsigned char *command = us->iobuf;
-
-	if (!len)
-		return USB_STOR_TRANSPORT_GOOD;
-
-	command[0] = 0xC0;
-	command[1] = access | 0x02;
-	command[2] = reg;
-	command[3] = 0;
-	command[4] = 0;
-	command[5] = 0;
-	command[6] = LSB_of(len);
-	command[7] = MSB_of(len);
-
-	result = usb_stor_ctrl_transfer(us,
-		us->send_ctrl_pipe,
-		0x80,
-		0x40,
-		0,
-		0,
-		command,
-		8);
-
-	if (result != USB_STOR_XFER_GOOD)
-		return USB_STOR_TRANSPORT_ERROR;
-
-	result = usb_stor_bulk_transfer_sg(us, us->recv_bulk_pipe,
-			content, len, use_sg, NULL);
-
-	return (result == USB_STOR_XFER_GOOD ?
-			USB_STOR_TRANSPORT_GOOD : USB_STOR_TRANSPORT_ERROR);
+	return usbat_execute_command(us, command, 8);
 }
 
 /*
  * Block, waiting for an ATA device to become not busy or to report
  * an error condition.
  */
-
 static int usbat_wait_not_busy(struct us_data *us, int minutes)
 {
 	int i;
@@ -189,7 +266,7 @@
 
 	for (i=0; i<1200+minutes*60; i++) {
 
- 		result = usbat_read(us, USBAT_ATA, 0x17, status);
+ 		result = usbat_get_status(us, status);
 
 		if (result!=USB_STOR_XFER_GOOD)
 			return USB_STOR_TRANSPORT_ERROR;
@@ -220,12 +297,45 @@
 	return USB_STOR_TRANSPORT_FAILED;
 }
 
+/*
+ * Read block data from the data register
+ */
+static int usbat_read_block(struct us_data *us,
+			    unsigned char *content,
+			    unsigned short len)
+{
+	int result;
+	unsigned char *command = us->iobuf;
+
+	if (!len)
+		return USB_STOR_TRANSPORT_GOOD;
+
+	command[0] = 0xC0;
+	command[1] = USBAT_ATA | USBAT_CMD_READ_BLOCK;
+	command[2] = USBAT_ATA_DATA;
+	command[3] = 0;
+	command[4] = 0;
+	command[5] = 0;
+	command[6] = LSB_of(len);
+	command[7] = MSB_of(len);
+
+	result = usbat_execute_command(us, command, 8);
+	if (result != USB_STOR_XFER_GOOD)
+		return USB_STOR_TRANSPORT_ERROR;
+
+	result = usbat_bulk_read(us, content, len);
+	return (result == USB_STOR_XFER_GOOD ?
+			USB_STOR_TRANSPORT_GOOD : USB_STOR_TRANSPORT_ERROR);
+}
+
+/*
+ * Write block data via the data register
+ */
 static int usbat_write_block(struct us_data *us,
-			     unsigned char access, 
-			     unsigned char reg,
+			     unsigned char access,
 			     unsigned char *content,
 			     unsigned short len,
-			     int use_sg, int minutes)
+			     int minutes)
 {
 	int result;
 	unsigned char *command = us->iobuf;
@@ -234,57 +344,48 @@
 		return USB_STOR_TRANSPORT_GOOD;
 
 	command[0] = 0x40;
-	command[1] = access | 0x03;
-	command[2] = reg;
+	command[1] = access | USBAT_CMD_WRITE_BLOCK;
+	command[2] = USBAT_ATA_DATA;
 	command[3] = 0;
 	command[4] = 0;
 	command[5] = 0;
 	command[6] = LSB_of(len);
 	command[7] = MSB_of(len);
 
-	result = usb_stor_ctrl_transfer(us,
-		us->send_ctrl_pipe,
-		0x80,
-		0x40,
-		0,
-		0,
-		command,
-		8);
+	result = usbat_execute_command(us, command, 8);
 
 	if (result != USB_STOR_XFER_GOOD)
 		return USB_STOR_TRANSPORT_ERROR;
 
-	result = usb_stor_bulk_transfer_sg(us, us->send_bulk_pipe,
-			content, len, use_sg, NULL);
-
+	result = usbat_bulk_write(us, content, len);
 	if (result != USB_STOR_XFER_GOOD)
 		return USB_STOR_TRANSPORT_ERROR;
 
 	return usbat_wait_not_busy(us, minutes);
 }
 
-static int usbat_rw_block_test(struct us_data *us,
-			       unsigned char access,
-			       unsigned char *registers,
-			       unsigned char *data_out,
-			       unsigned short num_registers,
-			       unsigned char data_reg,
-			       unsigned char status_reg,
-			       unsigned char timeout,
-			       unsigned char qualifier,
-			       int direction,
-			       unsigned char *content,
-			       unsigned short len,
-			       int use_sg,
-			       int minutes)
+/*
+ * Process read and write requests
+ */
+static int usbat_hp8200e_rw_block_test(struct us_data *us,
+				       unsigned char access,
+				       unsigned char *registers,
+				       unsigned char *data_out,
+				       unsigned short num_registers,
+				       unsigned char data_reg,
+				       unsigned char status_reg,
+				       unsigned char timeout,
+				       unsigned char qualifier,
+				       int direction,
+				       unsigned char *content,
+				       unsigned short len,
+				       int use_sg,
+				       int minutes)
 {
 	int result;
 	unsigned int pipe = (direction == DMA_FROM_DEVICE) ?
 			us->recv_bulk_pipe : us->send_bulk_pipe;
 
-	// Not really sure the 0x07, 0x17, 0xfc, 0xe7 is necessary here,
-	// but that's what came out of the trace every single time.
-
 	unsigned char *command = us->iobuf;
 	int i, j;
 	int cmdlen;
@@ -308,8 +409,11 @@
 
 		if (i==0) {
 			cmdlen = 16;
+			// Write to multiple registers
+			// Not really sure the 0x07, 0x17, 0xfc, 0xe7 is necessary here,
+			// but that's what came out of the trace every single time.
 			command[0] = 0x40;
-			command[1] = access | 0x07;
+			command[1] = access | USBAT_CMD_WRITE_REGS;
 			command[2] = 0x07;
 			command[3] = 0x17;
 			command[4] = 0xFC;
@@ -319,9 +423,11 @@
 		} else
 			cmdlen = 8;
 
+		// Conditionally read or write blocks
 		command[cmdlen-8] = (direction==DMA_TO_DEVICE ? 0x40 : 0xC0);
 		command[cmdlen-7] = access |
-				(direction==DMA_TO_DEVICE ? 0x05 : 0x04);
+				(direction==DMA_TO_DEVICE ?
+				 USBAT_CMD_COND_WRITE_BLOCK : USBAT_CMD_COND_READ_BLOCK);
 		command[cmdlen-6] = data_reg;
 		command[cmdlen-5] = status_reg;
 		command[cmdlen-4] = timeout;
@@ -329,14 +435,7 @@
 		command[cmdlen-2] = LSB_of(len);
 		command[cmdlen-1] = MSB_of(len);
 
-		result = usb_stor_ctrl_transfer(us,
-			us->send_ctrl_pipe,
-			0x80,
-			0x40,
-			0,
-			0,
-			command,
-			cmdlen);
+		result = usbat_execute_command(us, command, cmdlen);
 
 		if (result != USB_STOR_XFER_GOOD)
 			return USB_STOR_TRANSPORT_ERROR;
@@ -348,10 +447,7 @@
 				data[1+(j<<1)] = data_out[j];
 			}
 
-			result = usb_stor_bulk_transfer_buf(us,
-					us->send_bulk_pipe,
-					data, num_registers*2, NULL);
-
+			result = usbat_bulk_write(us, data, num_registers*2);
 			if (result != USB_STOR_XFER_GOOD)
 				return USB_STOR_TRANSPORT_ERROR;
 
@@ -403,7 +499,8 @@
 			 */
 
  			result = usbat_read(us, USBAT_ATA, 
-				direction==DMA_TO_DEVICE ? 0x17 : 0x0E, 
+				direction==DMA_TO_DEVICE ?
+					USBAT_ATA_STATUS : USBAT_ATA_ALTSTATUS,
 				status);
 
 			if (result!=USB_STOR_XFER_GOOD)
@@ -430,101 +527,602 @@
 }
 
 /*
- * Write data to multiple registers at once. Not meant for large
- * transfers of data!
+ * Write to multiple registers:
+ * Allows us to write specific data to any registers. The data to be written
+ * gets packed in this sequence: reg0, data0, reg1, data1, ..., regN, dataN
+ * which gets sent through bulk out.
+ * Not designed for large transfers of data!
  */
-
 static int usbat_multiple_write(struct us_data *us,
-				unsigned char access,
 				unsigned char *registers,
 				unsigned char *data_out,
 				unsigned short num_registers)
 {
-	int result;
+	int i, result;
 	unsigned char *data = us->iobuf;
-	int i;
 	unsigned char *command = us->iobuf;
 
 	BUG_ON(num_registers > US_IOBUF_SIZE/2);
 
+	// Write to multiple registers, ATA access
 	command[0] = 0x40;
-	command[1] = access | 0x07;
+	command[1] = USBAT_ATA | USBAT_CMD_WRITE_REGS;
+
+	// No relevance
 	command[2] = 0;
 	command[3] = 0;
 	command[4] = 0;
 	command[5] = 0;
+
+	// Number of bytes to be transferred (incl. addresses and data)
 	command[6] = LSB_of(num_registers*2);
 	command[7] = MSB_of(num_registers*2);
 
-	result = usb_stor_ctrl_transfer(us,
-		us->send_ctrl_pipe,
-		0x80,
-		0x40,
-		0,
-		0,
-		command,
-		8);
-
+	// The setup command
+	result = usbat_execute_command(us, command, 8);
 	if (result != USB_STOR_XFER_GOOD)
 		return USB_STOR_TRANSPORT_ERROR;
 
+	// Create the reg/data, reg/data sequence
 	for (i=0; i<num_registers; i++) {
 		data[i<<1] = registers[i];
 		data[1+(i<<1)] = data_out[i];
 	}
 
-	result = usb_stor_bulk_transfer_buf(us,
-		us->send_bulk_pipe, data, num_registers*2, NULL);
-
+	// Send the data
+	result = usbat_bulk_write(us, data, num_registers*2);
 	if (result != USB_STOR_XFER_GOOD)
 		return USB_STOR_TRANSPORT_ERROR;
 
-	return usbat_wait_not_busy(us, 0);
+	if (usbat_get_device_type(us) == USBAT_DEV_HP8200)
+		return usbat_wait_not_busy(us, 0);
+	else
+		return USB_STOR_TRANSPORT_GOOD;
+}
+
+/*
+ * Conditionally read blocks from device:
+ * Allows us to read blocks from a specific data register, based upon the
+ * condition that a status register can be successfully masked with a status
+ * qualifier. If this condition is not initially met, the read will wait
+ * up until a maximum amount of time has elapsed, as specified by timeout.
+ * The read will start when the condition is met, otherwise the command aborts.
+ *
+ * The qualifier defined here is not the value that is masked, it defines
+ * conditions for the write to take place. The actual masked qualifier (and
+ * other related details) are defined beforehand with _set_shuttle_features().
+ */
+static int usbat_read_blocks(struct us_data *us,
+							 unsigned char *buffer,
+							 int len)
+{
+	int result;
+	unsigned char *command = us->iobuf;
+
+	command[0] = 0xC0;
+	command[1] = USBAT_ATA | USBAT_CMD_COND_READ_BLOCK;
+	command[2] = USBAT_ATA_DATA;
+	command[3] = USBAT_ATA_STATUS;
+	command[4] = 0xFD; // Timeout (ms);
+	command[5] = USBAT_QUAL_FCQ;
+	command[6] = LSB_of(len);
+	command[7] = MSB_of(len);
+
+	// Multiple block read setup command
+	result = usbat_execute_command(us, command, 8);
+	if (result != USB_STOR_XFER_GOOD)
+		return USB_STOR_TRANSPORT_FAILED;
+	
+	// Read the blocks we just asked for
+	result = usbat_bulk_read(us, buffer, len);
+	if (result != USB_STOR_XFER_GOOD)
+		return USB_STOR_TRANSPORT_FAILED;
+
+	return USB_STOR_TRANSPORT_GOOD;
+}
+
+/*
+ * Conditionally write blocks to device:
+ * Allows us to write blocks to a specific data register, based upon the
+ * condition that a status register can be successfully masked with a status
+ * qualifier. If this condition is not initially met, the write will wait
+ * up until a maximum amount of time has elapsed, as specified by timeout.
+ * The read will start when the condition is met, otherwise the command aborts.
+ *
+ * The qualifier defined here is not the value that is masked, it defines
+ * conditions for the write to take place. The actual masked qualifier (and
+ * other related details) are defined beforehand with _set_shuttle_features().
+ */
+static int usbat_write_blocks(struct us_data *us,
+							  unsigned char *buffer,
+							  int len)
+{
+	int result;
+	unsigned char *command = us->iobuf;
+
+	command[0] = 0x40;
+	command[1] = USBAT_ATA | USBAT_CMD_COND_WRITE_BLOCK;
+	command[2] = USBAT_ATA_DATA;
+	command[3] = USBAT_ATA_STATUS;
+	command[4] = 0xFD; // Timeout (ms)
+	command[5] = USBAT_QUAL_FCQ;
+	command[6] = LSB_of(len);
+	command[7] = MSB_of(len);
+
+	// Multiple block write setup command
+	result = usbat_execute_command(us, command, 8);
+	if (result != USB_STOR_XFER_GOOD)
+		return USB_STOR_TRANSPORT_FAILED;
+	
+	// Write the data
+	result = usbat_bulk_write(us, buffer, len);
+	if (result != USB_STOR_XFER_GOOD)
+		return USB_STOR_TRANSPORT_FAILED;
+
+	return USB_STOR_TRANSPORT_GOOD;
 }
 
+/*
+ * Read the User IO register
+ */
 static int usbat_read_user_io(struct us_data *us, unsigned char *data_flags)
 {
 	int result;
 
 	result = usb_stor_ctrl_transfer(us,
 		us->recv_ctrl_pipe,
-		0x82,
+		USBAT_CMD_UIO,
 		0xC0,
 		0,
 		0,
 		data_flags,
-		1);
+		USBAT_UIO_READ);
+
+	US_DEBUGP("usbat_read_user_io: UIO register reads %02X\n", (unsigned short) (*data_flags));
 
 	return result;
 }
 
+/*
+ * Write to the User IO register
+ */
 static int usbat_write_user_io(struct us_data *us,
 			       unsigned char enable_flags,
 			       unsigned char data_flags)
 {
-	int result;
-
-	result = usb_stor_ctrl_transfer(us,
+	return usb_stor_ctrl_transfer(us,
 		us->send_ctrl_pipe,
-		0x82,
+		USBAT_CMD_UIO,
 		0x40,
 		short_pack(enable_flags, data_flags),
 		0,
 		NULL,
-		0);
+		USBAT_UIO_WRITE);
+}
+
+/*
+ * Reset the device
+ * Often needed on media change.
+ */
+static int usbat_device_reset(struct us_data *us)
+{
+	int rc;
+
+	// Reset peripheral, enable peripheral control signals
+	// (bring reset signal up)
+	rc = usbat_write_user_io(us,
+							 USBAT_UIO_DRVRST | USBAT_UIO_OE1 | USBAT_UIO_OE0,
+							 USBAT_UIO_EPAD | USBAT_UIO_1);
+	if (rc != USB_STOR_XFER_GOOD)
+		return USB_STOR_TRANSPORT_ERROR;
+			
+	// Enable peripheral control signals
+	// (bring reset signal down)
+	rc = usbat_write_user_io(us,
+							 USBAT_UIO_OE1  | USBAT_UIO_OE0,
+							 USBAT_UIO_EPAD | USBAT_UIO_1);
+	if (rc != USB_STOR_XFER_GOOD)
+		return USB_STOR_TRANSPORT_ERROR;
+
+	return USB_STOR_TRANSPORT_GOOD;
+}
+
+/*
+ * Enable card detect
+ */
+static int usbat_device_enable_cdt(struct us_data *us)
+{
+	int rc;
+
+	// Enable peripheral control signals and card detect
+	rc = usbat_write_user_io(us,
+							 USBAT_UIO_ACKD | USBAT_UIO_OE1  | USBAT_UIO_OE0,
+							 USBAT_UIO_EPAD | USBAT_UIO_1);
+	if (rc != USB_STOR_XFER_GOOD)
+		return USB_STOR_TRANSPORT_ERROR;
 
+	return USB_STOR_TRANSPORT_GOOD;
+}
+
+/*
+ * Determine if media is present.
+ */
+static int usbat_flash_check_media_present(unsigned char *uio)
+{
+	if (*uio & USBAT_UIO_UI0) {
+		US_DEBUGP("usbat_flash_check_media_present: no media detected\n");
+		return USBAT_FLASH_MEDIA_NONE;
+	}
+
+	return USBAT_FLASH_MEDIA_CF;
+}
+
+/*
+ * Determine if media has changed since last operation
+ */
+static int usbat_flash_check_media_changed(unsigned char *uio)
+{
+	if (*uio & USBAT_UIO_0) {
+		US_DEBUGP("usbat_flash_check_media_changed: media change detected\n");
+		return USBAT_FLASH_MEDIA_CHANGED;
+	}
+
+	return USBAT_FLASH_MEDIA_SAME;
+}
+
+/*
+ * Check for media change / no media and handle the situation appropriately
+ */
+static int usbat_flash_check_media(struct us_data *us,
+				   struct usbat_info *info)
+{
+	int rc;
+	unsigned char *uio = us->iobuf;
+
+	rc = usbat_read_user_io(us, uio);
+	if (rc != USB_STOR_XFER_GOOD)
+		return USB_STOR_TRANSPORT_ERROR;
+
+	// Check for media existance
+	rc = usbat_flash_check_media_present(uio);
+	if (rc == USBAT_FLASH_MEDIA_NONE) {
+		info->sense_key = 0x02;
+		info->sense_asc = 0x3A;
+		info->sense_ascq = 0x00;
+		return USB_STOR_TRANSPORT_FAILED;
+	}
+
+	// Check for media change
+	rc = usbat_flash_check_media_changed(uio);
+	if (rc == USBAT_FLASH_MEDIA_CHANGED) {
+
+		// Reset and re-enable card detect
+		rc = usbat_device_reset(us);
+		if (rc != USB_STOR_TRANSPORT_GOOD)
+			return rc;
+		rc = usbat_device_enable_cdt(us);
+		if (rc != USB_STOR_TRANSPORT_GOOD)
+			return rc;
+
+		msleep(50);
+
+		rc = usbat_read_user_io(us, uio);
+		if (rc != USB_STOR_XFER_GOOD)
+			return USB_STOR_TRANSPORT_ERROR;
+		
+		info->sense_key = UNIT_ATTENTION;
+		info->sense_asc = 0x28;
+		info->sense_ascq = 0x00;
+		return USB_STOR_TRANSPORT_FAILED;
+	}
+
+	return USB_STOR_TRANSPORT_GOOD;
+}
+
+/*
+ * Determine whether we are controlling a flash-based reader/writer,
+ * or a HP8200-based CD drive.
+ * Sets transport functions as appropriate.
+ */
+static int usbat_identify_device(struct us_data *us,
+				 struct usbat_info *info)
+{
+	int rc;
+	unsigned char status;
+
+	if (!us || !info)
+		return USB_STOR_TRANSPORT_ERROR;
+
+	rc = usbat_device_reset(us);
+	if (rc != USB_STOR_TRANSPORT_GOOD)
+		return rc;
+
+	/*
+	 * By examining the device signature after a reset, we can identify
+	 * whether the device supports the ATAPI packet interface.
+	 * The flash-devices do not support this, whereas the HP CDRW's obviously
+	 * do.
+	 *
+	 * This method is not ideal, but works because no other devices have been
+	 * produced based on the USBAT/USBAT02.
+	 *
+	 * Section 9.1 of the ATAPI-4 spec states (amongst other things) that
+	 * after a device reset, a Cylinder low of 0x14 indicates that the device
+	 * does support packet commands.
+	 */
+	rc = usbat_read(us, USBAT_ATA, USBAT_ATA_LBA_ME, &status);
+	if (rc != USB_STOR_XFER_GOOD)
+		return USB_STOR_TRANSPORT_ERROR;
+
+	US_DEBUGP("usbat_identify_device: Cylinder low is %02X\n", status);
+
+	if (status == 0x14) {
+		// Device is HP 8200
+		US_DEBUGP("usbat_identify_device: Detected HP8200 CDRW\n");
+		info->devicetype = USBAT_DEV_HP8200;
+	} else {
+		// Device is a CompactFlash reader/writer
+		US_DEBUGP("usbat_identify_device: Detected Flash reader/writer\n");
+		info->devicetype = USBAT_DEV_FLASH;
+	}
+
+	return USB_STOR_TRANSPORT_GOOD;
+}
+
+/*
+ * Set the transport function based on the device type
+ */
+int usbat_set_transport(struct us_data *us,
+			struct usbat_info *info)
+{
+	int rc;
+
+	if (!info->devicetype) {
+		rc = usbat_identify_device(us, info);
+		if (rc != USB_STOR_TRANSPORT_GOOD) {
+			US_DEBUGP("usbat_set_transport: Could not identify device\n");
+			return 1;
+		}
+	}
+
+	if (usbat_get_device_type(us) == USBAT_DEV_HP8200)
+		us->transport = usbat_hp8200e_transport;
+	else if (usbat_get_device_type(us) == USBAT_DEV_FLASH)
+		us->transport = usbat_flash_transport;
+
+	return 0;
+}
+
+/*
+ * Read the media capacity
+ */
+static int usbat_flash_get_sector_count(struct us_data *us,
+					struct usbat_info *info)
+{
+	unsigned char registers[3] = {
+		USBAT_ATA_SECCNT,
+		USBAT_ATA_DEVICE,
+		USBAT_ATA_CMD,
+	};
+	unsigned char  command[3] = { 0x01, 0xA0, 0xEC };
+	unsigned char *reply;
+	unsigned char status;
+	int rc;
+
+	if (!us || !info)
+		return USB_STOR_TRANSPORT_ERROR;
+
+	reply = kmalloc(512, GFP_NOIO);
+	if (!reply)
+		return USB_STOR_TRANSPORT_ERROR;
+
+	// ATAPI command : IDENTIFY DEVICE
+	rc = usbat_multiple_write(us, registers, command, 3);
+	if (rc != USB_STOR_XFER_GOOD) {
+		US_DEBUGP("usbat_flash_get_sector_count: Gah! identify_device failed\n");
+		rc = USB_STOR_TRANSPORT_ERROR;
+		goto leave;
+	}
+
+	// Read device status
+	if (usbat_get_status(us, &status) != USB_STOR_XFER_GOOD) {
+		rc = USB_STOR_TRANSPORT_ERROR;
+		goto leave;
+	}
+
+	msleep(100);
+
+	// Read the device identification data
+	rc = usbat_read_block(us, reply, 512);
+	if (rc != USB_STOR_TRANSPORT_GOOD)
+		goto leave;
+
+	info->sectors = ((u32)(reply[117]) << 24) |
+		((u32)(reply[116]) << 16) |
+		((u32)(reply[115]) <<  8) |
+		((u32)(reply[114])      );
+
+	rc = USB_STOR_TRANSPORT_GOOD;
+
+ leave:
+	kfree(reply);
+	return rc;
+}
+
+/*
+ * Read data from device
+ */
+static int usbat_flash_read_data(struct us_data *us,
+								 struct usbat_info *info,
+								 u32 sector,
+								 u32 sectors)
+{
+	unsigned char registers[7] = {
+		USBAT_ATA_FEATURES,
+		USBAT_ATA_SECCNT,
+		USBAT_ATA_SECNUM,
+		USBAT_ATA_LBA_ME,
+		USBAT_ATA_LBA_HI,
+		USBAT_ATA_DEVICE,
+		USBAT_ATA_STATUS,
+	};
+	unsigned char command[7];
+	unsigned char *buffer;
+	unsigned char  thistime;
+	unsigned int totallen, alloclen;
+	int len, result;
+	unsigned int sg_idx = 0, sg_offset = 0;
+
+	result = usbat_flash_check_media(us, info);
+	if (result != USB_STOR_TRANSPORT_GOOD)
+		return result;
+
+	// we're working in LBA mode.  according to the ATA spec,
+	// we can support up to 28-bit addressing.  I don't know if Jumpshot
+	// supports beyond 24-bit addressing.  It's kind of hard to test
+	// since it requires > 8GB CF card.
+
+	if (sector > 0x0FFFFFFF)
+		return USB_STOR_TRANSPORT_ERROR;
+
+	totallen = sectors * info->ssize;
+
+	// Since we don't read more than 64 KB at a time, we have to create
+	// a bounce buffer and move the data a piece at a time between the
+	// bounce buffer and the actual transfer buffer.
+
+	alloclen = min(totallen, 65536u);
+	buffer = kmalloc(alloclen, GFP_NOIO);
+	if (buffer == NULL)
+		return USB_STOR_TRANSPORT_ERROR;
+
+	do {
+		// loop, never allocate or transfer more than 64k at once
+		// (min(128k, 255*info->ssize) is the real limit)
+		len = min(totallen, alloclen);
+		thistime = (len / info->ssize) & 0xff;
+ 
+		// ATAPI command 0x20 (READ SECTORS)
+		usbat_pack_atapi_sector_cmd(command, thistime, sector, 0x20);
+
+		// Write/execute ATAPI read command
+		result = usbat_multiple_write(us, registers, command, 7);
+		if (result != USB_STOR_TRANSPORT_GOOD)
+			goto leave;
+
+		// Read the data we just requested
+		result = usbat_read_blocks(us, buffer, len);
+		if (result != USB_STOR_TRANSPORT_GOOD)
+			goto leave;
+  	 
+		US_DEBUGP("usbat_flash_read_data:  %d bytes\n", len);
+	
+		// Store the data in the transfer buffer
+		usb_stor_access_xfer_buf(buffer, len, us->srb,
+					 &sg_idx, &sg_offset, TO_XFER_BUF);
+
+		sector += thistime;
+		totallen -= len;
+	} while (totallen > 0);
+
+	kfree(buffer);
+	return USB_STOR_TRANSPORT_GOOD;
+
+leave:
+	kfree(buffer);
+	return USB_STOR_TRANSPORT_ERROR;
+}
+
+/*
+ * Write data to device
+ */
+static int usbat_flash_write_data(struct us_data *us,
+								  struct usbat_info *info,
+								  u32 sector,
+								  u32 sectors)
+{
+	unsigned char registers[7] = {
+		USBAT_ATA_FEATURES,
+		USBAT_ATA_SECCNT,
+		USBAT_ATA_SECNUM,
+		USBAT_ATA_LBA_ME,
+		USBAT_ATA_LBA_HI,
+		USBAT_ATA_DEVICE,
+		USBAT_ATA_STATUS,
+	};
+	unsigned char command[7];
+	unsigned char *buffer;
+	unsigned char  thistime;
+	unsigned int totallen, alloclen;
+	int len, result;
+	unsigned int sg_idx = 0, sg_offset = 0;
+
+	result = usbat_flash_check_media(us, info);
+	if (result != USB_STOR_TRANSPORT_GOOD)
+		return result;
+
+	// we're working in LBA mode.  according to the ATA spec,
+	// we can support up to 28-bit addressing.  I don't know if Jumpshot
+	// supports beyond 24-bit addressing.  It's kind of hard to test
+	// since it requires > 8GB CF card.
+
+	if (sector > 0x0FFFFFFF)
+		return USB_STOR_TRANSPORT_ERROR;
+
+	totallen = sectors * info->ssize;
+
+	// Since we don't write more than 64 KB at a time, we have to create
+	// a bounce buffer and move the data a piece at a time between the
+	// bounce buffer and the actual transfer buffer.
+
+	alloclen = min(totallen, 65536u);
+	buffer = kmalloc(alloclen, GFP_NOIO);
+	if (buffer == NULL)
+		return USB_STOR_TRANSPORT_ERROR;
+
+	do {
+		// loop, never allocate or transfer more than 64k at once
+		// (min(128k, 255*info->ssize) is the real limit)
+		len = min(totallen, alloclen);
+		thistime = (len / info->ssize) & 0xff;
+
+		// Get the data from the transfer buffer
+		usb_stor_access_xfer_buf(buffer, len, us->srb,
+					 &sg_idx, &sg_offset, FROM_XFER_BUF);
+
+		// ATAPI command 0x30 (WRITE SECTORS)
+		usbat_pack_atapi_sector_cmd(command, thistime, sector, 0x30);		
+
+		// Write/execute ATAPI write command
+		result = usbat_multiple_write(us, registers, command, 7);
+		if (result != USB_STOR_TRANSPORT_GOOD)
+			goto leave;
+
+		// Write the data
+		result = usbat_write_blocks(us, buffer, len);
+		if (result != USB_STOR_TRANSPORT_GOOD)
+			goto leave;
+
+		sector += thistime;
+		totallen -= len;
+	} while (totallen > 0);
+
+	kfree(buffer);
 	return result;
+
+leave:
+	kfree(buffer);
+	return USB_STOR_TRANSPORT_ERROR;
 }
 
 /*
  * Squeeze a potentially huge (> 65535 byte) read10 command into
  * a little ( <= 65535 byte) ATAPI pipe
  */
-
-static int usbat_handle_read10(struct us_data *us,
-			       unsigned char *registers,
-			       unsigned char *data,
-			       struct scsi_cmnd *srb)
+static int usbat_hp8200e_handle_read10(struct us_data *us,
+				       unsigned char *registers,
+				       unsigned char *data,
+				       struct scsi_cmnd *srb)
 {
 	int result = USB_STOR_TRANSPORT_GOOD;
 	unsigned char *buffer;
@@ -538,9 +1136,10 @@
 
 	if (srb->request_bufflen < 0x10000) {
 
-		result = usbat_rw_block_test(us, USBAT_ATA, 
+		result = usbat_hp8200e_rw_block_test(us, USBAT_ATA, 
 			registers, data, 19,
-			0x10, 0x17, 0xFD, 0x30,
+			USBAT_ATA_DATA, USBAT_ATA_STATUS, 0xFD,
+			(USBAT_QUAL_FCQ | USBAT_QUAL_ALQ),
 			DMA_FROM_DEVICE,
 			srb->request_buffer, 
 			srb->request_bufflen, srb->use_sg, 1);
@@ -607,9 +1206,10 @@
 		data[7+7] = MSB_of(len / srb->transfersize); // SCSI command
 		data[7+8] = LSB_of(len / srb->transfersize); // num sectors
 
-		result = usbat_rw_block_test(us, USBAT_ATA, 
+		result = usbat_hp8200e_rw_block_test(us, USBAT_ATA, 
 			registers, data, 19,
-			0x10, 0x17, 0xFD, 0x30,
+			USBAT_ATA_DATA, USBAT_ATA_STATUS, 0xFD, 
+			(USBAT_QUAL_FCQ | USBAT_QUAL_ALQ),
 			DMA_FROM_DEVICE,
 			buffer,
 			len, 0, 1);
@@ -632,48 +1232,52 @@
 	return result;
 }
 
-static int hp_8200e_select_and_test_registers(struct us_data *us)
+static int usbat_select_and_test_registers(struct us_data *us)
 {
 	int selector;
 	unsigned char *status = us->iobuf;
+	unsigned char max_selector = 0xB0;
+	if (usbat_get_device_type(us) == USBAT_DEV_FLASH)
+		max_selector = 0xA0;
 
 	// try device = master, then device = slave.
 
-	for (selector = 0xA0; selector <= 0xB0; selector += 0x10) {
+	for (selector = 0xA0; selector <= max_selector; selector += 0x10) {
 
-		if (usbat_write(us, USBAT_ATA, 0x16, selector) != 
+		if (usbat_get_device_type(us) == USBAT_DEV_HP8200 &&
+			usbat_write(us, USBAT_ATA, USBAT_ATA_DEVICE, selector) != 
 				USB_STOR_XFER_GOOD)
 			return USB_STOR_TRANSPORT_ERROR;
 
-		if (usbat_read(us, USBAT_ATA, 0x17, status) != 
+		if (usbat_read(us, USBAT_ATA, USBAT_ATA_STATUS, status) != 
 				USB_STOR_XFER_GOOD)
 			return USB_STOR_TRANSPORT_ERROR;
 
-		if (usbat_read(us, USBAT_ATA, 0x16, status) != 
+		if (usbat_read(us, USBAT_ATA, USBAT_ATA_DEVICE, status) != 
 				USB_STOR_XFER_GOOD)
 			return USB_STOR_TRANSPORT_ERROR;
 
-		if (usbat_read(us, USBAT_ATA, 0x14, status) != 
+		if (usbat_read(us, USBAT_ATA, USBAT_ATA_LBA_ME, status) != 
 				USB_STOR_XFER_GOOD)
 			return USB_STOR_TRANSPORT_ERROR;
 
-		if (usbat_read(us, USBAT_ATA, 0x15, status) != 
+		if (usbat_read(us, USBAT_ATA, USBAT_ATA_LBA_HI, status) != 
 				USB_STOR_XFER_GOOD)
 			return USB_STOR_TRANSPORT_ERROR;
 
-		if (usbat_write(us, USBAT_ATA, 0x14, 0x55) != 
+		if (usbat_write(us, USBAT_ATA, USBAT_ATA_LBA_ME, 0x55) != 
 				USB_STOR_XFER_GOOD)
 			return USB_STOR_TRANSPORT_ERROR;
 
-		if (usbat_write(us, USBAT_ATA, 0x15, 0xAA) != 
+		if (usbat_write(us, USBAT_ATA, USBAT_ATA_LBA_HI, 0xAA) != 
 				USB_STOR_XFER_GOOD)
 			return USB_STOR_TRANSPORT_ERROR;
 
-		if (usbat_read(us, USBAT_ATA, 0x14, status) != 
+		if (usbat_read(us, USBAT_ATA, USBAT_ATA_LBA_ME, status) != 
 				USB_STOR_XFER_GOOD)
 			return USB_STOR_TRANSPORT_ERROR;
 
-		if (usbat_read(us, USBAT_ATA, 0x15, status) != 
+		if (usbat_read(us, USBAT_ATA, USBAT_ATA_LBA_ME, status) != 
 				USB_STOR_XFER_GOOD)
 			return USB_STOR_TRANSPORT_ERROR;
 	}
@@ -681,125 +1285,131 @@
 	return USB_STOR_TRANSPORT_GOOD;
 }
 
-int init_8200e(struct us_data *us)
+/*
+ * Initialize the USBAT processor and the storage device
+ */
+int init_usbat(struct us_data *us)
 {
-	int result;
+	int rc;
+	struct usbat_info *info;
+	unsigned char subcountH = USBAT_ATA_LBA_HI;
+	unsigned char subcountL = USBAT_ATA_LBA_ME;
 	unsigned char *status = us->iobuf;
 
-	// Enable peripheral control signals
+	us->extra = kmalloc(sizeof(struct usbat_info), GFP_NOIO);
+	if (!us->extra) {
+		US_DEBUGP("init_usbat: Gah! Can't allocate storage for usbat info struct!\n");
+		return 1;
+	}
+	memset(us->extra, 0, sizeof(struct usbat_info));
+	info = (struct usbat_info *) (us->extra);
 
-	if (usbat_write_user_io(us,
-	  USBAT_UIO_OE1 | USBAT_UIO_OE0,
-	  USBAT_UIO_EPAD | USBAT_UIO_1) != USB_STOR_XFER_GOOD)
+	// Enable peripheral control signals
+	rc = usbat_write_user_io(us,
+				 USBAT_UIO_OE1 | USBAT_UIO_OE0,
+				 USBAT_UIO_EPAD | USBAT_UIO_1);
+	if (rc != USB_STOR_XFER_GOOD)
 		return USB_STOR_TRANSPORT_ERROR;
 
 	US_DEBUGP("INIT 1\n");
 
 	msleep(2000);
 
-	if (usbat_read_user_io(us, status) !=
-			USB_STOR_XFER_GOOD)
-		return USB_STOR_TRANSPORT_ERROR;
+	rc = usbat_read_user_io(us, status);
+	if (rc != USB_STOR_TRANSPORT_GOOD)
+		return rc;
 
 	US_DEBUGP("INIT 2\n");
 
-	if (usbat_read_user_io(us, status) !=
-			USB_STOR_XFER_GOOD)
+	rc = usbat_read_user_io(us, status);
+	if (rc != USB_STOR_XFER_GOOD)
 		return USB_STOR_TRANSPORT_ERROR;
 
-	US_DEBUGP("INIT 3\n");
-
-	// Reset peripheral, enable periph control signals
-	// (bring reset signal up)
-
-	if (usbat_write_user_io(us,
-	  USBAT_UIO_DRVRST | USBAT_UIO_OE1 | USBAT_UIO_OE0,
-	  USBAT_UIO_EPAD | USBAT_UIO_1) != USB_STOR_XFER_GOOD)
+	rc = usbat_read_user_io(us, status);
+	if (rc != USB_STOR_XFER_GOOD)
 		return USB_STOR_TRANSPORT_ERROR;
 
-	US_DEBUGP("INIT 4\n");
-
-	// Enable periph control signals
-	// (bring reset signal down)
+	US_DEBUGP("INIT 3\n");
 
-	if (usbat_write_user_io(us,
-	  USBAT_UIO_OE1 | USBAT_UIO_OE0,
-	  USBAT_UIO_EPAD | USBAT_UIO_1) != USB_STOR_XFER_GOOD)
+	// At this point, we need to detect which device we are using
+	if (usbat_set_transport(us, info))
 		return USB_STOR_TRANSPORT_ERROR;
 
-	US_DEBUGP("INIT 5\n");
+	US_DEBUGP("INIT 4\n");
 
-	msleep(250);
+	if (usbat_get_device_type(us) == USBAT_DEV_HP8200) {
+		msleep(250);
 
-	// Write 0x80 to ISA port 0x3F
+		// Write 0x80 to ISA port 0x3F
+		rc = usbat_write(us, USBAT_ISA, 0x3F, 0x80);
+		if (rc != USB_STOR_XFER_GOOD)
+			return USB_STOR_TRANSPORT_ERROR;
 
-	if (usbat_write(us, USBAT_ISA, 0x3F, 0x80) !=
-			USB_STOR_XFER_GOOD)
-		return USB_STOR_TRANSPORT_ERROR;
+		US_DEBUGP("INIT 5\n");
 
-	US_DEBUGP("INIT 6\n");
+		// Read ISA port 0x27
+		rc = usbat_read(us, USBAT_ISA, 0x27, status);
+		if (rc != USB_STOR_XFER_GOOD)
+			return USB_STOR_TRANSPORT_ERROR;
 
-	// Read ISA port 0x27
+		US_DEBUGP("INIT 6\n");
 
-	if (usbat_read(us, USBAT_ISA, 0x27, status) !=
-			USB_STOR_XFER_GOOD)
-		return USB_STOR_TRANSPORT_ERROR;
+		rc = usbat_read_user_io(us, status);
+		if (rc != USB_STOR_XFER_GOOD)
+			return USB_STOR_TRANSPORT_ERROR;
 
-	US_DEBUGP("INIT 7\n");
+		US_DEBUGP("INIT 7\n");
+	}
 
-	if (usbat_read_user_io(us, status) !=
-			USB_STOR_XFER_GOOD)
-		return USB_STOR_TRANSPORT_ERROR;
+	rc = usbat_select_and_test_registers(us);
+	if (rc != USB_STOR_TRANSPORT_GOOD)
+		return rc;
 
 	US_DEBUGP("INIT 8\n");
 
-	if ( (result = hp_8200e_select_and_test_registers(us)) !=
-			 USB_STOR_TRANSPORT_GOOD)
-		return result;
+	rc = usbat_read_user_io(us, status);
+	if (rc != USB_STOR_XFER_GOOD)
+		return USB_STOR_TRANSPORT_ERROR;
 
 	US_DEBUGP("INIT 9\n");
 
-	if (usbat_read_user_io(us, status) !=
-			USB_STOR_XFER_GOOD)
-		return USB_STOR_TRANSPORT_ERROR;
+	// Enable peripheral control signals and card detect
+	rc = usbat_device_enable_cdt(us);
+	if (rc != USB_STOR_TRANSPORT_GOOD)
+		return rc;
 
 	US_DEBUGP("INIT 10\n");
 
-	// Enable periph control signals and card detect
-
-	if (usbat_write_user_io(us,
-	  USBAT_UIO_ACKD |USBAT_UIO_OE1 | USBAT_UIO_OE0,
-	  USBAT_UIO_EPAD | USBAT_UIO_1) != USB_STOR_XFER_GOOD)
+	rc = usbat_read_user_io(us, status);
+	if (rc != USB_STOR_XFER_GOOD)
 		return USB_STOR_TRANSPORT_ERROR;
 
 	US_DEBUGP("INIT 11\n");
 
-	if (usbat_read_user_io(us, status) !=
-			USB_STOR_XFER_GOOD)
-		return USB_STOR_TRANSPORT_ERROR;
-
-	US_DEBUGP("INIT 12\n");
-
 	msleep(1400);
 
-	if (usbat_read_user_io(us, status) !=
-			USB_STOR_XFER_GOOD)
+	rc = usbat_read_user_io(us, status);
+	if (rc != USB_STOR_XFER_GOOD)
 		return USB_STOR_TRANSPORT_ERROR;
 
-	US_DEBUGP("INIT 13\n");
+	US_DEBUGP("INIT 12\n");
 
-	if ( (result = hp_8200e_select_and_test_registers(us)) !=
-			 USB_STOR_TRANSPORT_GOOD)
-		return result;
+	rc = usbat_select_and_test_registers(us);
+	if (rc != USB_STOR_TRANSPORT_GOOD)
+		return rc;
 
-	US_DEBUGP("INIT 14\n");
+	US_DEBUGP("INIT 13\n");
 
-	if (usbat_set_shuttle_features(us, 
-			0x83, 0x00, 0x88, 0x08, 0x15, 0x14) !=
-			 USB_STOR_XFER_GOOD)
+	if (usbat_get_device_type(us) == USBAT_DEV_FLASH) { 
+		subcountH = 0x02;
+		subcountL = 0x00;
+	}
+	rc = usbat_set_shuttle_features(us, (USBAT_FEAT_ETEN | USBAT_FEAT_ET2 | USBAT_FEAT_ET1),
+									0x00, 0x88, 0x08, subcountH, subcountL);
+	if (rc != USB_STOR_XFER_GOOD)
 		return USB_STOR_TRANSPORT_ERROR;
 
-	US_DEBUGP("INIT 15\n");
+	US_DEBUGP("INIT 14\n");
 
 	return USB_STOR_TRANSPORT_GOOD;
 }
@@ -807,7 +1417,7 @@
 /*
  * Transport for the HP 8200e
  */
-int hp8200e_transport(struct scsi_cmnd *srb, struct us_data *us)
+int usbat_hp8200e_transport(struct scsi_cmnd *srb, struct us_data *us)
 {
 	int result;
 	unsigned char *status = us->iobuf;
@@ -824,13 +1434,13 @@
 	   commands... just ATA Packet Commands.
  	 */
 
-	registers[0] = 0x11;
-	registers[1] = 0x12;
-	registers[2] = 0x13;
-	registers[3] = 0x14;
-	registers[4] = 0x15;
-	registers[5] = 0x16;
-	registers[6] = 0x17;
+	registers[0] = USBAT_ATA_FEATURES;
+	registers[1] = USBAT_ATA_SECCNT;
+	registers[2] = USBAT_ATA_SECNUM;
+	registers[3] = USBAT_ATA_LBA_ME;
+	registers[4] = USBAT_ATA_LBA_HI;
+	registers[5] = USBAT_ATA_DEVICE;
+	registers[6] = USBAT_ATA_CMD;
 	data[0] = 0x00;
 	data[1] = 0x00;
 	data[2] = 0x00;
@@ -844,7 +1454,7 @@
 		data[i] = (i-7 >= srb->cmd_len) ? 0 : srb->cmnd[i-7];
 	}
 
-	result = usbat_read(us, USBAT_ATA, 0x17, status);
+	result = usbat_get_status(us, status);
 	US_DEBUGP("Status = %02X\n", *status);
 	if (result != USB_STOR_XFER_GOOD)
 		return USB_STOR_TRANSPORT_ERROR;
@@ -853,9 +1463,10 @@
 
 	if (srb->sc_data_direction == DMA_TO_DEVICE) {
 
-		result = usbat_rw_block_test(us, USBAT_ATA, 
+		result = usbat_hp8200e_rw_block_test(us, USBAT_ATA, 
 			registers, data, 19,
-			0x10, 0x17, 0xFD, 0x30,
+			USBAT_ATA_DATA, USBAT_ATA_STATUS, 0xFD,
+			(USBAT_QUAL_FCQ | USBAT_QUAL_ALQ),
 			DMA_TO_DEVICE,
 			srb->request_buffer, 
 			len, srb->use_sg, 10);
@@ -870,7 +1481,7 @@
 	} else if (srb->cmnd[0] == READ_10 ||
 		   srb->cmnd[0] == GPCMD_READ_CD) {
 
-		return usbat_handle_read10(us, registers, data, srb);
+		return usbat_hp8200e_handle_read10(us, registers, data, srb);
 
 	}
 
@@ -881,7 +1492,6 @@
 	}
 
 	if ( (result = usbat_multiple_write(us, 
-			USBAT_ATA,
 			registers, data, 7)) != USB_STOR_TRANSPORT_GOOD) {
 		return result;
 	}
@@ -895,7 +1505,7 @@
 	// AT SPEED 4 IS UNRELIABLE!!!
 
 	if ( (result = usbat_write_block(us, 
-			USBAT_ATA, 0x10, srb->cmnd, 12, 0,
+			USBAT_ATA, srb->cmnd, 12,
 			srb->cmnd[0]==GPCMD_BLANK ? 75 : 10)) !=
 				USB_STOR_TRANSPORT_GOOD) {
 		return result;
@@ -908,14 +1518,14 @@
 
 		// How many bytes to read in? Check cylL register
 
-		if (usbat_read(us, USBAT_ATA, 0x14, status) != 
+		if (usbat_read(us, USBAT_ATA, USBAT_ATA_LBA_ME, status) != 
 		    	USB_STOR_XFER_GOOD) {
 			return USB_STOR_TRANSPORT_ERROR;
 		}
 
 		if (len > 0xFF) { // need to read cylH also
 			len = *status;
-			if (usbat_read(us, USBAT_ATA, 0x15, status) !=
+			if (usbat_read(us, USBAT_ATA, USBAT_ATA_LBA_HI, status) !=
 				    USB_STOR_XFER_GOOD) {
 				return USB_STOR_TRANSPORT_ERROR;
 			}
@@ -925,8 +1535,7 @@
 			len = *status;
 
 
-		result = usbat_read_block(us, USBAT_ATA, 0x10, 
-			srb->request_buffer, len, srb->use_sg);
+		result = usbat_read_block(us, srb->request_buffer, len);
 
 		/* Debug-print the first 32 bytes of the transfer */
 
@@ -948,4 +1557,153 @@
 	return result;
 }
 
+/*
+ * Transport for USBAT02-based CompactFlash and similar storage devices
+ */
+int usbat_flash_transport(struct scsi_cmnd * srb, struct us_data *us)
+{
+	int rc;
+	struct usbat_info *info = (struct usbat_info *) (us->extra);
+	unsigned long block, blocks;
+	unsigned char *ptr = us->iobuf;
+	static unsigned char inquiry_response[36] = {
+		0x00, 0x80, 0x00, 0x01, 0x1F, 0x00, 0x00, 0x00
+	};
+
+	if (srb->cmnd[0] == INQUIRY) {
+		US_DEBUGP("usbat_flash_transport: INQUIRY. Returning bogus response.\n");
+		memcpy(ptr, inquiry_response, sizeof(inquiry_response));
+		fill_inquiry_response(us, ptr, 36);
+		return USB_STOR_TRANSPORT_GOOD;
+	}
+
+	if (srb->cmnd[0] == READ_CAPACITY) {
+		rc = usbat_flash_check_media(us, info);
+		if (rc != USB_STOR_TRANSPORT_GOOD)
+			return rc;
+
+		rc = usbat_flash_get_sector_count(us, info);
+		if (rc != USB_STOR_TRANSPORT_GOOD)
+			return rc;
+
+		info->ssize = 0x200;  // hard coded 512 byte sectors as per ATA spec
+		US_DEBUGP("usbat_flash_transport: READ_CAPACITY: %ld sectors, %ld bytes per sector\n",
+			  info->sectors, info->ssize);
+
+		// build the reply
+		// note: must return the sector number of the last sector,
+		// *not* the total number of sectors
+		((__be32 *) ptr)[0] = cpu_to_be32(info->sectors - 1);
+		((__be32 *) ptr)[1] = cpu_to_be32(info->ssize);
+		usb_stor_set_xfer_buf(ptr, 8, srb);
+
+		return USB_STOR_TRANSPORT_GOOD;
+	}
+
+	if (srb->cmnd[0] == MODE_SELECT_10) {
+		US_DEBUGP("usbat_flash_transport:  Gah! MODE_SELECT_10.\n");
+		return USB_STOR_TRANSPORT_ERROR;
+	}
+
+	if (srb->cmnd[0] == READ_10) {
+		block = ((u32)(srb->cmnd[2]) << 24) | ((u32)(srb->cmnd[3]) << 16) |
+				((u32)(srb->cmnd[4]) <<  8) | ((u32)(srb->cmnd[5]));
+
+		blocks = ((u32)(srb->cmnd[7]) << 8) | ((u32)(srb->cmnd[8]));
+
+		US_DEBUGP("usbat_flash_transport:  READ_10: read block 0x%04lx  count %ld\n", block, blocks);
+		return usbat_flash_read_data(us, info, block, blocks);
+	}
+
+	if (srb->cmnd[0] == READ_12) {
+		// I don't think we'll ever see a READ_12 but support it anyway...
+		block = ((u32)(srb->cmnd[2]) << 24) | ((u32)(srb->cmnd[3]) << 16) |
+		        ((u32)(srb->cmnd[4]) <<  8) | ((u32)(srb->cmnd[5]));
+
+		blocks = ((u32)(srb->cmnd[6]) << 24) | ((u32)(srb->cmnd[7]) << 16) |
+		         ((u32)(srb->cmnd[8]) <<  8) | ((u32)(srb->cmnd[9]));
+
+		US_DEBUGP("usbat_flash_transport: READ_12: read block 0x%04lx  count %ld\n", block, blocks);
+		return usbat_flash_read_data(us, info, block, blocks);
+	}
+
+	if (srb->cmnd[0] == WRITE_10) {
+		block = ((u32)(srb->cmnd[2]) << 24) | ((u32)(srb->cmnd[3]) << 16) |
+		        ((u32)(srb->cmnd[4]) <<  8) | ((u32)(srb->cmnd[5]));
+
+		blocks = ((u32)(srb->cmnd[7]) << 8) | ((u32)(srb->cmnd[8]));
+
+		US_DEBUGP("usbat_flash_transport: WRITE_10: write block 0x%04lx  count %ld\n", block, blocks);
+		return usbat_flash_write_data(us, info, block, blocks);
+	}
+
+	if (srb->cmnd[0] == WRITE_12) {
+		// I don't think we'll ever see a WRITE_12 but support it anyway...
+		block = ((u32)(srb->cmnd[2]) << 24) | ((u32)(srb->cmnd[3]) << 16) |
+		        ((u32)(srb->cmnd[4]) <<  8) | ((u32)(srb->cmnd[5]));
+
+		blocks = ((u32)(srb->cmnd[6]) << 24) | ((u32)(srb->cmnd[7]) << 16) |
+		         ((u32)(srb->cmnd[8]) <<  8) | ((u32)(srb->cmnd[9]));
+
+		US_DEBUGP("usbat_flash_transport: WRITE_12: write block 0x%04lx  count %ld\n", block, blocks);
+		return usbat_flash_write_data(us, info, block, blocks);
+	}
+
+
+	if (srb->cmnd[0] == TEST_UNIT_READY) {
+		US_DEBUGP("usbat_flash_transport: TEST_UNIT_READY.\n");
+
+		rc = usbat_flash_check_media(us, info);
+		if (rc != USB_STOR_TRANSPORT_GOOD)
+			return rc;
+
+		return usbat_check_status(us);
+	}
+
+	if (srb->cmnd[0] == REQUEST_SENSE) {
+		US_DEBUGP("usbat_flash_transport: REQUEST_SENSE.\n");
+
+		memset(ptr, 0, 18);
+		ptr[0] = 0xF0;
+		ptr[2] = info->sense_key;
+		ptr[7] = 11;
+		ptr[12] = info->sense_asc;
+		ptr[13] = info->sense_ascq;
+		usb_stor_set_xfer_buf(ptr, 18, srb);
+
+		return USB_STOR_TRANSPORT_GOOD;
+	}
+
+	if (srb->cmnd[0] == ALLOW_MEDIUM_REMOVAL) {
+		// sure.  whatever.  not like we can stop the user from popping
+		// the media out of the device (no locking doors, etc)
+		return USB_STOR_TRANSPORT_GOOD;
+	}
+
+	US_DEBUGP("usbat_flash_transport: Gah! Unknown command: %d (0x%x)\n",
+			  srb->cmnd[0], srb->cmnd[0]);
+	info->sense_key = 0x05;
+	info->sense_asc = 0x20;
+	info->sense_ascq = 0x00;
+	return USB_STOR_TRANSPORT_FAILED;
+}
+
+/*
+ * Default transport function. Attempts to detect which transport function
+ * should be called, makes it the new default, and calls it.
+ *
+ * This function should never be called. Our usbat_init() function detects the
+ * device type and changes the us->transport ptr to the transport function
+ * relevant to the device.
+ * However, we'll support this impossible(?) case anyway.
+ */
+int usbat_transport(struct scsi_cmnd *srb, struct us_data *us)
+{
+	struct usbat_info *info = (struct usbat_info*) (us->extra);
+
+	if (usbat_set_transport(us, info))
+		return USB_STOR_TRANSPORT_ERROR;
+
+	return us->transport(srb, us);	
+}
 
diff -Nru a/drivers/usb/storage/shuttle_usbat.h b/drivers/usb/storage/shuttle_usbat.h
--- a/drivers/usb/storage/shuttle_usbat.h	2005-03-11 12:51:41 -08:00
+++ b/drivers/usb/storage/shuttle_usbat.h	2005-03-11 12:51:41 -08:00
@@ -5,8 +5,9 @@
  *
  * Current development and maintenance by:
  *   (c) 2000 Robert Baruch (autophile@dol.net)
+ *   (c) 2004, 2005 Daniel Drake <dsd@gentoo.org>
  *
- * See scm.c for more explanation
+ * See shuttle_usbat.c for more explanation
  *
  * 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
@@ -26,13 +27,59 @@
 #ifndef _USB_SHUTTLE_USBAT_H
 #define _USB_SHUTTLE_USBAT_H
 
+/* Supported device types */
+#define USBAT_DEV_HP8200	0x01
+#define USBAT_DEV_FLASH		0x02
+
 #define USBAT_EPP_PORT		0x10
 #define USBAT_EPP_REGISTER	0x30
 #define USBAT_ATA		0x40
 #define USBAT_ISA		0x50
 
-/* SCM User I/O Data registers */
+/* Commands (need to be logically OR'd with an access type */
+#define USBAT_CMD_READ_REG		0x00
+#define USBAT_CMD_WRITE_REG		0x01
+#define USBAT_CMD_READ_BLOCK	0x02
+#define USBAT_CMD_WRITE_BLOCK	0x03
+#define USBAT_CMD_COND_READ_BLOCK	0x04
+#define USBAT_CMD_COND_WRITE_BLOCK	0x05
+#define USBAT_CMD_WRITE_REGS	0x07
+
+/* Commands (these don't need an access type) */
+#define USBAT_CMD_EXEC_CMD	0x80
+#define USBAT_CMD_SET_FEAT	0x81
+#define USBAT_CMD_UIO		0x82
+
+/* Methods of accessing UIO register */
+#define USBAT_UIO_READ	1
+#define USBAT_UIO_WRITE	0
+
+/* Qualifier bits */
+#define USBAT_QUAL_FCQ	0x20 // full compare
+#define USBAT_QUAL_ALQ	0x10 // auto load subcount
+
+/* USBAT Flash Media status types */
+#define USBAT_FLASH_MEDIA_NONE	0
+#define USBAT_FLASH_MEDIA_CF	1
+
+/* USBAT Flash Media change types */
+#define USBAT_FLASH_MEDIA_SAME	0
+#define USBAT_FLASH_MEDIA_CHANGED	1
+
+/* USBAT ATA registers */
+#define USBAT_ATA_DATA      0x10  // read/write data (R/W)
+#define USBAT_ATA_FEATURES  0x11  // set features (W)
+#define USBAT_ATA_ERROR     0x11  // error (R)
+#define USBAT_ATA_SECCNT    0x12  // sector count (R/W)
+#define USBAT_ATA_SECNUM    0x13  // sector number (R/W)
+#define USBAT_ATA_LBA_ME    0x14  // cylinder low (R/W)
+#define USBAT_ATA_LBA_HI    0x15  // cylinder high (R/W)
+#define USBAT_ATA_DEVICE    0x16  // head/device selection (R/W)
+#define USBAT_ATA_STATUS    0x17  // device status (R)
+#define USBAT_ATA_CMD       0x17  // device command (W)
+#define USBAT_ATA_ALTSTATUS 0x0E  // status (no clear IRQ) (R)
 
+/* USBAT User I/O Data registers */
 #define USBAT_UIO_EPAD		0x80 // Enable Peripheral Control Signals
 #define USBAT_UIO_CDT		0x40 // Card Detect (Read Only)
 				     // CDT = ACKD & !UI1 & !UI0
@@ -43,8 +90,7 @@
 #define USBAT_UIO_UI0		0x02 // Input 0
 #define USBAT_UIO_INTR_ACK	0x01 // Interrupt (ATA & ISA)/Acknowledge (EPP)
 
-/* SCM User I/O Enable registers */
-
+/* USBAT User I/O Enable registers */
 #define USBAT_UIO_DRVRST	0x80 // Reset Peripheral
 #define USBAT_UIO_ACKD		0x40 // Enable Card Detect
 #define USBAT_UIO_OE1		0x20 // I/O 1 set=output/clr=input
@@ -52,8 +98,30 @@
 #define USBAT_UIO_OE0		0x10 // I/O 0 set=output/clr=input
 #define USBAT_UIO_ADPRST	0x01 // Reset SCM chip
 
-/* HP 8200e stuff */
-extern int hp8200e_transport(struct scsi_cmnd *srb, struct us_data *us);
-extern int init_8200e(struct us_data *us);
+/* USBAT Features */
+#define USBAT_FEAT_ETEN	0x80 // External trigger enable
+#define USBAT_FEAT_U1	0x08
+#define USBAT_FEAT_U0	0x04
+#define USBAT_FEAT_ET1	0x02
+#define USBAT_FEAT_ET2	0x01
+
+/* Transport functions */
+int usbat_hp8200e_transport(struct scsi_cmnd *srb, struct us_data *us);
+int usbat_flash_transport(struct scsi_cmnd * srb, struct us_data *us);
+
+extern int usbat_transport(struct scsi_cmnd *srb, struct us_data *us);
+extern int init_usbat(struct us_data *us);
+
+struct usbat_info {
+	int devicetype;
+
+	/* Used for Flash readers only */
+	unsigned long sectors;     // total sector count
+	unsigned long ssize;       // sector size in bytes
+
+	unsigned char sense_key;
+	unsigned long sense_asc;   // additional sense code
+	unsigned long sense_ascq;  // additional sense code qualifier
+};
 
 #endif
diff -Nru a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c
--- a/drivers/usb/storage/transport.c	2005-03-11 12:51:42 -08:00
+++ b/drivers/usb/storage/transport.c	2005-03-11 12:51:42 -08:00
@@ -991,10 +991,10 @@
 	/* DATA STAGE */
 	/* send/receive data payload, if there is any */
 
-	/* Genesys Logic interface chips need a 100us delay between the
+	/* Some USB-IDE converter chips need a 100us delay between the
 	 * command phase and the data phase.  Some devices need a little
 	 * more than that, probably because of clock rate inaccuracies. */
-	if (le16_to_cpu(us->pusb_dev->descriptor.idVendor) == USB_VENDOR_ID_GENESYS)
+	if (unlikely(us->flags & US_FL_GO_SLOW))
 		udelay(110);
 
 	if (transfer_length) {
@@ -1055,19 +1055,31 @@
 	US_DEBUGP("Bulk Status S 0x%x T 0x%x R %u Stat 0x%x\n",
 			le32_to_cpu(bcs->Signature), bcs->Tag, 
 			residue, bcs->Status);
-	if ((bcs->Signature != cpu_to_le32(US_BULK_CS_SIGN) &&
-		    bcs->Signature != cpu_to_le32(US_BULK_CS_OLYMPUS_SIGN)) ||
-			bcs->Tag != srb->serial_number || 
-			bcs->Status > US_BULK_STAT_PHASE) {
+	if (bcs->Tag != srb->serial_number || bcs->Status > US_BULK_STAT_PHASE) {
 		US_DEBUGP("Bulk logical error\n");
 		return USB_STOR_TRANSPORT_ERROR;
 	}
 
+	/* Some broken devices report odd signatures, so we do not check them
+	 * for validity against the spec. We store the first one we see,
+	 * and check subsequent transfers for validity against this signature.
+	 */
+	if (!us->bcs_signature) {
+		us->bcs_signature = bcs->Signature;
+		if (us->bcs_signature != cpu_to_le32(US_BULK_CS_SIGN))
+			US_DEBUGP("Learnt BCS signature 0x%08X\n",
+					le32_to_cpu(us->bcs_signature));
+	} else if (bcs->Signature != us->bcs_signature) {
+		US_DEBUGP("Signature mismatch: got %08X, expecting %08X\n",
+			  le32_to_cpu(bcs->Signature),
+			  le32_to_cpu(us->bcs_signature));
+		return USB_STOR_TRANSPORT_ERROR;
+	}
+
 	/* try to compute the actual residue, based on how much data
 	 * was really transferred and what the device tells us */
 	if (residue) {
-		if (!(us->flags & US_FL_IGNORE_RESIDUE) ||
-				srb->sc_data_direction == DMA_TO_DEVICE) {
+		if (!(us->flags & US_FL_IGNORE_RESIDUE)) {
 			residue = min(residue, transfer_length);
 			srb->resid = max(srb->resid, (int) residue);
 		}
diff -Nru a/drivers/usb/storage/transport.h b/drivers/usb/storage/transport.h
--- a/drivers/usb/storage/transport.h	2005-03-11 12:51:42 -08:00
+++ b/drivers/usb/storage/transport.h	2005-03-11 12:51:42 -08:00
@@ -52,7 +52,7 @@
 #define US_PR_CBI	0x00		/* Control/Bulk/Interrupt */
 #define US_PR_CB	0x01		/* Control/Bulk w/o interrupt */
 #define US_PR_BULK	0x50		/* bulk only */
-#ifdef CONFIG_USB_STORAGE_HP8200e
+#ifdef CONFIG_USB_STORAGE_USBAT
 #define US_PR_SCM_ATAPI	0x80		/* SCM-ATAPI bridge */
 #endif
 #ifdef CONFIG_USB_STORAGE_SDDR09
@@ -108,8 +108,6 @@
 
 #define US_BULK_CS_WRAP_LEN	13
 #define US_BULK_CS_SIGN		0x53425355	/* spells out 'USBS' */
-/* This is for Olympus Camedia digital cameras */
-#define US_BULK_CS_OLYMPUS_SIGN		0x55425355	/* spells out 'USBU' */
 #define US_BULK_STAT_OK		0
 #define US_BULK_STAT_FAIL	1
 #define US_BULK_STAT_PHASE	2
diff -Nru a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
--- a/drivers/usb/storage/unusual_devs.h	2005-03-11 12:51:50 -08:00
+++ b/drivers/usb/storage/unusual_devs.h	2005-03-11 12:51:50 -08:00
@@ -59,16 +59,16 @@
 		"CD-Writer+",
 		US_SC_8070, US_PR_CB, NULL, 0), 
 
-#ifdef CONFIG_USB_STORAGE_HP8200e
+#ifdef CONFIG_USB_STORAGE_USBAT
 UNUSUAL_DEV(  0x03f0, 0x0207, 0x0001, 0x0001, 
 		"HP",
 		"CD-Writer+ 8200e",
-		US_SC_8070, US_PR_SCM_ATAPI, init_8200e, 0), 
+		US_SC_8070, US_PR_SCM_ATAPI, init_usbat, 0), 
 
 UNUSUAL_DEV(  0x03f0, 0x0307, 0x0001, 0x0001, 
 		"HP",
 		"CD-Writer+ CD-4e",
-		US_SC_8070, US_PR_SCM_ATAPI, init_8200e, 0), 
+		US_SC_8070, US_PR_SCM_ATAPI, init_usbat, 0), 
 #endif
 
 /* Deduced by Jonathan Woithe <jwoithe@physics.adelaide.edu.au>
@@ -123,6 +123,13 @@
 		"DVD-CAM DZ-MV100A Camcorder",
 		US_SC_SCSI, US_PR_CB, NULL, US_FL_SINGLE_LUN),
 
+/* Reported by Andreas Bockhold <andreas@bockionline.de> */
+UNUSUAL_DEV(  0x04b0, 0x0405, 0x0100, 0x0100,
+		"NIKON",
+		"NIKON DSC D70",
+		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		US_FL_FIX_CAPACITY),
+
 /* Reported by Simon Levitt <simon@whattf.com>
  * This entry needs Sub and Proto fields */
 UNUSUAL_DEV(  0x04b8, 0x0601, 0x0100, 0x0100,
@@ -171,15 +178,12 @@
 		"CD-R/RW Drive",
 		US_SC_8070, US_PR_CB, NULL, 0),
 
-/* Reported by Adriaan Penning <a.penning@luon.net>
- * Note that these cameras report "Medium not present" after
- * ALLOW_MEDIUM_REMOVAL, so they also need to be marked
- * NOT_LOCKABLE in the SCSI blacklist (and the vendor is MATSHITA). */
+/* Reported by Adriaan Penning <a.penning@luon.net> */
 UNUSUAL_DEV(  0x04da, 0x2372, 0x0000, 0x9999,
 		"Panasonic",
 		"DMC-LCx Camera",
 		US_SC_DEVICE, US_PR_DEVICE, NULL,
-		US_FL_FIX_CAPACITY ),
+		US_FL_FIX_CAPACITY | US_FL_NOT_LOCKABLE ),
 
 /* Most of the following entries were developed with the help of
  * Shuttle/SCM directly.
@@ -268,6 +272,14 @@
 		US_SC_DEVICE, US_PR_DEVICE, NULL,
 		US_FL_BULK32),
 
+#ifdef CONFIG_USB_STORAGE_USBAT
+UNUSUAL_DEV(  0x04e6, 0x1010, 0x0000, 0x9999,
+		"SCM",
+		"SCM USBAT-02",
+		US_SC_SCSI, US_PR_SCM_ATAPI, init_usbat,
+		US_FL_SINGLE_LUN),
+#endif
+
 /* Reported by Bob Sass <rls@vectordb.com> -- only rev 1.33 tested */
 UNUSUAL_DEV(  0x050d, 0x0115, 0x0133, 0x0133,
 		"Belkin",
@@ -324,12 +336,11 @@
 		US_SC_DEVICE, US_PR_DEVICE, NULL,
 		US_FL_IGNORE_RESIDUE ),
 
-/* This entry is needed because the device reports Sub=ff */
 UNUSUAL_DEV(  0x054c, 0x0010, 0x0106, 0x0450, 
 		"Sony",
 		"DSC-S30/S70/S75/505V/F505/F707/F717/P8", 
 		US_SC_SCSI, US_PR_DEVICE, NULL,
-		US_FL_SINGLE_LUN ),
+		US_FL_SINGLE_LUN | US_FL_NOT_LOCKABLE ),
 
 /* This entry is needed because the device reports Sub=ff */
 UNUSUAL_DEV(  0x054c, 0x0010, 0x0500, 0x0500, 
@@ -512,6 +523,25 @@
 		US_SC_DEVICE, US_PR_DEVICE, NULL,
 		US_FL_FIX_INQUIRY ),
 
+/* The following two entries are for a Genesys USB to IDE
+ * converter chip, but it changes its ProductId depending
+ * on whether or not a disk or an optical device is enclosed
+ * They were originally reported by Alexander Oltu
+ * <alexander@all-2.com> and Peter Marks <peter.marks@turner.com>
+ * respectively.
+ */
+UNUSUAL_DEV(  0x05e3, 0x0701, 0x0000, 0xffff,
+		"Genesys Logic",
+		"USB to IDE Optical",
+		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		US_FL_GO_SLOW ),
+
+UNUSUAL_DEV(  0x05e3, 0x0702, 0x0000, 0xffff,
+		"Genesys Logic",
+		"USB to IDE Disk",
+		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		US_FL_GO_SLOW ),
+
 /* Reported by Hanno Boeck <hanno@gmx.de>
  * Taken from the Lycoris Kernel */
 UNUSUAL_DEV(  0x0636, 0x0003, 0x0000, 0x9999,
@@ -540,19 +570,19 @@
 		US_SC_DEVICE, US_PR_DEVICE, NULL,
 		US_FL_FIX_CAPACITY ),
 
-/* Reported by Alex Butcher <alex.butcher@assursys.co.uk> */
-UNUSUAL_DEV( 0x067b, 0x3507, 0x0001, 0x0001,
+/* Reported by Richard -=[]=- <micro_flyer@hotmail.com> */
+UNUSUAL_DEV( 0x067b, 0x2507, 0x0100, 0x0100,
 		"Prolific Technology Inc.",
-		"ATAPI-6 Bridge Controller",
+		"Mass Storage Device",
 		US_SC_DEVICE, US_PR_DEVICE, NULL,
-		US_FL_FIX_CAPACITY ),
+		US_FL_FIX_CAPACITY | US_FL_GO_SLOW ),
 
 /* Reported by Alex Butcher <alex.butcher@assursys.co.uk> */
 UNUSUAL_DEV( 0x067b, 0x3507, 0x0001, 0x0001,
 		"Prolific Technology Inc.",
 		"ATAPI-6 Bridge Controller",
 		US_SC_DEVICE, US_PR_DEVICE, NULL,
-		US_FL_FIX_CAPACITY ),
+		US_FL_FIX_CAPACITY | US_FL_GO_SLOW ),
 
 /* Submitted by Benny Sjostrand <benny@hostmobility.com> */
 UNUSUAL_DEV( 0x0686, 0x4011, 0x0001, 0x0001,
@@ -582,12 +612,18 @@
 		US_SC_SCSI, US_PR_CB, NULL,
 		US_FL_SINGLE_LUN ),
 
-#if !defined(CONFIG_BLK_DEV_UB) && !defined(CONFIG_BLK_DEV_UB_MODULE)
 UNUSUAL_DEV(  0x0781, 0x0002, 0x0009, 0x0009, 
 		"Sandisk",
 		"ImageMate SDDR-31",
 		US_SC_DEVICE, US_PR_DEVICE, NULL,
 		US_FL_IGNORE_SER ),
+
+#ifdef CONFIG_USB_STORAGE_USBAT
+UNUSUAL_DEV(  0x0781, 0x0005, 0x0005, 0x0005,
+		"Sandisk",
+		"ImageMate SDDR-05b",
+		US_SC_SCSI, US_PR_SCM_ATAPI, init_usbat,
+		US_FL_SINGLE_LUN),
 #endif
 
 UNUSUAL_DEV(  0x0781, 0x0100, 0x0100, 0x0100,
@@ -866,6 +902,13 @@
 		US_SC_DEVICE, US_PR_DEVICE, NULL,
 		US_FL_IGNORE_RESIDUE ),
 
+/* Reported by Ian McConnell <ian at emit.demon.co.uk> */
+UNUSUAL_DEV(  0x0dda, 0x0301, 0x0012, 0x0012,
+		"PNP_MP3",
+		"PNP_MP3 PLAYER",
+		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		US_FL_IGNORE_RESIDUE ),
+
 /* Submitted by Antoine Mairesse <antoine.mairesse@free.fr> */
 UNUSUAL_DEV( 0x0ed1, 0x6660, 0x0100, 0x0300,
 		"USB",
@@ -904,6 +947,13 @@
 		"Black Silver",
 		US_SC_DEVICE, US_PR_DEVICE, NULL,
 		US_FL_IGNORE_RESIDUE ),
+
+/* Reported by Radovan Garabik <garabik@kassiopeia.juls.savba.sk> */
+UNUSUAL_DEV(  0x2735, 0x100b, 0x0000, 0x9999,
+		"MPIO",
+		"HS200",
+		US_SC_DEVICE, US_PR_DEVICE, NULL,
+		US_FL_GO_SLOW ),
 
 #ifdef CONFIG_USB_STORAGE_SDDR55
 UNUSUAL_DEV(  0x55aa, 0xa103, 0x0000, 0x9999, 
diff -Nru a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
--- a/drivers/usb/storage/usb.c	2005-03-11 12:51:42 -08:00
+++ b/drivers/usb/storage/usb.c	2005-03-11 12:51:42 -08:00
@@ -63,7 +63,7 @@
 #include "debug.h"
 #include "initializers.h"
 
-#ifdef CONFIG_USB_STORAGE_HP8200e
+#ifdef CONFIG_USB_STORAGE_USBAT
 #include "shuttle_usbat.h"
 #endif
 #ifdef CONFIG_USB_STORAGE_SDDR09
@@ -144,9 +144,7 @@
 	{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_QIC, US_PR_BULK) },
 	{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_UFI, US_PR_BULK) },
 	{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_8070, US_PR_BULK) },
-#if !defined(CONFIG_BLK_DEV_UB) && !defined(CONFIG_BLK_DEV_UB_MODULE)
 	{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, US_SC_SCSI, US_PR_BULK) },
-#endif
 
 	/* Terminating entry */
 	{ }
@@ -220,10 +218,8 @@
 	  .useTransport = US_PR_BULK},
 	{ .useProtocol = US_SC_8070,
 	  .useTransport = US_PR_BULK},
-#if !defined(CONFIG_BLK_DEV_UB) && !defined(CONFIG_BLK_DEV_UB_MODULE)
 	{ .useProtocol = US_SC_SCSI,
 	  .useTransport = US_PR_BULK},
-#endif
 
 	/* Terminating entry */
 	{ NULL }
@@ -483,6 +479,13 @@
 			unusual_dev->useTransport;
 	us->flags = unusual_dev->flags;
 
+	/*
+	 * This flag is only needed when we're in high-speed, so let's
+	 * disable it if we're in full-speed
+	 */
+	if (dev->speed != USB_SPEED_HIGH)
+		us->flags &= ~US_FL_GO_SLOW;
+
 	/* Log a message if a non-generic unusual_dev entry contains an
 	 * unnecessary subclass or protocol override.  This may stimulate
 	 * reports from users that will help us remove unneeded entries
@@ -515,37 +518,6 @@
 				idesc->bInterfaceProtocol,
 				msgs[msg]);
 	}
-
-	/* Read the device's string descriptors */
-	if (dev->descriptor.iManufacturer)
-		usb_string(dev, dev->descriptor.iManufacturer, 
-			   us->vendor, sizeof(us->vendor));
-	if (dev->descriptor.iProduct)
-		usb_string(dev, dev->descriptor.iProduct, 
-			   us->product, sizeof(us->product));
-	if (dev->descriptor.iSerialNumber)
-		usb_string(dev, dev->descriptor.iSerialNumber, 
-			   us->serial, sizeof(us->serial));
-
-	/* Use the unusual_dev strings if the device didn't provide them */
-	if (strlen(us->vendor) == 0) {
-		if (unusual_dev->vendorName)
-			strlcpy(us->vendor, unusual_dev->vendorName,
-				sizeof(us->vendor));
-		else
-			strcpy(us->vendor, "Unknown");
-	}
-	if (strlen(us->product) == 0) {
-		if (unusual_dev->productName)
-			strlcpy(us->product, unusual_dev->productName,
-				sizeof(us->product));
-		else
-			strcpy(us->product, "Unknown");
-	}
-	if (strlen(us->serial) == 0)
-		strcpy(us->serial, "None");
-
-	US_DEBUGP("Vendor: %s,  Product: %s\n", us->vendor, us->product);
 }
 
 /* Get the transport settings */
@@ -572,10 +544,10 @@
 		us->transport_reset = usb_stor_Bulk_reset;
 		break;
 
-#ifdef CONFIG_USB_STORAGE_HP8200e
+#ifdef CONFIG_USB_STORAGE_USBAT
 	case US_PR_SCM_ATAPI:
 		us->transport_name = "SCM/ATAPI";
-		us->transport = hp8200e_transport;
+		us->transport = usbat_transport;
 		us->transport_reset = usb_stor_CB_reset;
 		us->max_lun = 1;
 		break;
diff -Nru a/drivers/usb/storage/usb.h b/drivers/usb/storage/usb.h
--- a/drivers/usb/storage/usb.h	2005-03-11 12:51:47 -08:00
+++ b/drivers/usb/storage/usb.h	2005-03-11 12:51:47 -08:00
@@ -75,6 +75,8 @@
 #define US_FL_FIX_CAPACITY    0x00000080 /* READ CAPACITY response too big  */
 #define US_FL_IGNORE_RESIDUE  0x00000100 /* reported residue is wrong	    */
 #define US_FL_BULK32          0x00000200 /* Uses 32-byte CBW length         */
+#define US_FL_NOT_LOCKABLE    0x00000400 /* PREVENT/ALLOW not supported     */
+#define US_FL_GO_SLOW         0x00000800 /* Need delay after Command phase  */
 
 /* Dynamic flag definitions: used in set_bit() etc. */
 #define US_FLIDX_URB_ACTIVE	18  /* 0x00040000  current_urb is in use  */
@@ -121,11 +123,9 @@
 	unsigned int		recv_intr_pipe;
 
 	/* information about the device */
-	char			vendor[USB_STOR_STRING_LEN];
-	char			product[USB_STOR_STRING_LEN];
-	char			serial[USB_STOR_STRING_LEN];
 	char			*transport_name;
 	char			*protocol_name;
+	__le32			bcs_signature;
 	u8			subclass;
 	u8			protocol;
 	u8			max_lun;
diff -Nru a/drivers/usb/usb-skeleton.c b/drivers/usb/usb-skeleton.c
--- a/drivers/usb/usb-skeleton.c	2005-03-11 12:51:46 -08:00
+++ b/drivers/usb/usb-skeleton.c	2005-03-11 12:51:46 -08:00
@@ -120,7 +120,7 @@
 			      usb_rcvbulkpipe(dev->udev, dev->bulk_in_endpointAddr),
 			      dev->bulk_in_buffer,
 			      min(dev->bulk_in_size, count),
-			      &count, HZ*10);
+			      &count, 10000);
 
 	/* if the read was successful, copy the data to userspace */
 	if (!retval) {
@@ -271,7 +271,7 @@
 		}
 
 		if (!dev->bulk_out_endpointAddr &&
-		    !(endpoint->bEndpointAddress & USB_DIR_IN) &&
+		    !(endpoint->bEndpointAddress & USB_DIR_OUT) &&
 		    ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
 					== USB_ENDPOINT_XFER_BULK)) {
 			/* we found a bulk out endpoint */
diff -Nru a/drivers/video/Kconfig b/drivers/video/Kconfig
--- a/drivers/video/Kconfig	2005-03-11 12:51:41 -08:00
+++ b/drivers/video/Kconfig	2005-03-11 12:51:41 -08:00
@@ -5,7 +5,7 @@
 menu "Graphics support"
 
 config FB
-	bool "Support for frame buffer devices"
+	tristate "Support for frame buffer devices"
 	---help---
 	  The frame buffer device provides an abstraction for the graphics
 	  hardware. It represents the frame buffer of some video hardware and
@@ -38,6 +38,42 @@
 	  (e.g. an accelerated X server) and that are not frame buffer
 	  device-aware may cause unexpected results. If unsure, say N.
 
+config FB_CFB_FILLRECT
+	tristate
+	depends on FB
+	default n
+	---help---
+	  Include the cfb_fillrect function for generic software rectangle
+	  filling. This is used by drivers that don't provide their own
+	  (accelerated) version.
+
+config FB_CFB_COPYAREA
+	tristate
+	depends on FB
+	default n
+	---help---
+	  Include the cfb_copyarea function for generic software area copying.
+	  This is used by drivers that don't provide their own (accelerated)
+	  version.
+
+config FB_CFB_IMAGEBLIT
+	tristate
+	depends on FB
+	default n
+	---help---
+	  Include the cfb_imageblit function for generic software image
+	  blitting. This is used by drivers that don't provide their own
+	  (accelerated) version.
+
+config FB_SOFT_CURSOR
+	tristate
+	depends on FB
+	default n
+	---help---
+	  Include the soft_cursor function for generic software cursor support.
+	  This is used by drivers that don't provide their own (accelerated)
+	  version.
+
 config FB_MODE_HELPERS
         bool "Enable Video Mode Handling Helpers"
         depends on FB
@@ -70,6 +106,10 @@
 config FB_CIRRUS
 	tristate "Cirrus Logic support"
 	depends on FB && (ZORRO || PCI)
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	select FB_SOFT_CURSOR
 	---help---
 	  This enables support for Cirrus Logic GD542x/543x based boards on
 	  Amiga: SD64, Piccolo, Picasso II/II+, Picasso IV, or EGS Spectrum.
@@ -85,6 +125,10 @@
 config FB_PM2
 	tristate "Permedia2 support"
 	depends on FB && ((AMIGA && BROKEN) || PCI)
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	select FB_SOFT_CURSOR
 	help
 	  This is the frame buffer device driver for the Permedia2 AGP frame
 	  buffer card from ASK, aka `Graphic Blaster Exxtreme'.  There is a
@@ -100,6 +144,10 @@
 config FB_ARMCLCD
 	tristate "ARM PrimeCell PL110 support"
 	depends on FB && ARM && ARM_AMBA
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	select FB_SOFT_CURSOR
 	help
 	  This framebuffer device driver is for the ARM PrimeCell PL110
 	  Colour LCD controller.  ARM PrimeCells provide the building
@@ -112,7 +160,11 @@
 
 config FB_ACORN
 	bool "Acorn VIDC support"
-	depends on FB && ARM && ARCH_ACORN
+	depends on (FB = y) && ARM && ARCH_ACORN
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	select FB_SOFT_CURSOR
 	help
 	  This is the frame buffer device driver for the Acorn VIDC graphics
 	  hardware found in Acorn RISC PCs and other ARM-based machines.  If
@@ -120,11 +172,19 @@
 
 config FB_CLPS711X
 	bool "CLPS711X LCD support"
-	depends on FB && ARM && ARCH_CLPS711X
+	depends on (FB = y) && ARM && ARCH_CLPS711X
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	select FB_SOFT_CURSOR
 
 config FB_SA1100
 	bool "SA-1100 LCD support"
-	depends on FB && ARM && ARCH_SA1100
+	depends on (FB = y) && ARM && ARCH_SA1100
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	select FB_SOFT_CURSOR
 	help
 	  This is a framebuffer device for the SA-1100 LCD Controller.
 	  See <http://www.linux-fbdev.org/> for information on framebuffer
@@ -136,6 +196,10 @@
 config FB_CYBER2000
 	tristate "CyberPro 2000/2010/5000 support"
 	depends on FB && PCI && (BROKEN || !SPARC64)
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	select FB_SOFT_CURSOR
 	help
 	  This enables support for the Integraphics CyberPro 20x0 and 5000
 	  VGA chips used in the Rebel.com Netwinder and other machines.
@@ -144,17 +208,25 @@
 
 config FB_APOLLO
 	bool
-	depends on FB && APOLLO
+	depends on (FB = y) && APOLLO
 	default y
+	select FB_CFB_FILLRECT
+	select FB_CFB_IMAGEBLIT
+	select FB_SOFT_CURSOR
 
 config FB_Q40
 	bool
-	depends on FB && Q40
+	depends on (FB = y) && Q40
 	default y
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	select FB_SOFT_CURSOR
 
 config FB_AMIGA
 	tristate "Amiga native chipset support"
 	depends on FB && AMIGA
+	select FB_SOFT_CURSOR
 	help
 	  This is the frame buffer device driver for the builtin graphics
 	  chipset found in Amigas.
@@ -191,6 +263,10 @@
 config FB_CYBER
 	tristate "Amiga CyberVision 64 support"
 	depends on FB && ZORRO && BROKEN
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	select FB_SOFT_CURSOR
 	help
 	  This enables support for the Cybervision 64 graphics card from
 	  Phase5. Please note that its use is not all that intuitive (i.e. if
@@ -201,7 +277,11 @@
 
 config FB_VIRGE
 	bool "Amiga CyberVision 64/3D support "
-	depends on FB && ZORRO && BROKEN
+	depends on (FB = y) && ZORRO && BROKEN
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	select FB_SOFT_CURSOR
 	help
 	  This enables support for the Cybervision 64/3D graphics card from
 	  Phase5. Please note that its use is not all that intuitive (i.e. if
@@ -212,7 +292,7 @@
 
 config FB_RETINAZ3
 	tristate "Amiga Retina Z3 support"
-	depends on FB && ZORRO && BROKEN
+	depends on (FB = y) && ZORRO && BROKEN
 	help
 	  This enables support for the Retina Z3 graphics card. Say N unless
 	  you have a Retina Z3 or plan to get one before you next recompile
@@ -220,73 +300,107 @@
 
 config FB_FM2
 	bool "Amiga FrameMaster II/Rainbow II support"
-	depends on FB && ZORRO
+	depends on (FB = y) && ZORRO
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	select FB_SOFT_CURSOR
 	help
 	  This is the frame buffer device driver for the Amiga FrameMaster
 	  card from BSC (exhibited 1992 but not shipped as a CBM product).
 
 config FB_ATARI
 	bool "Atari native chipset support"
-	depends on FB && ATARI && BROKEN
+	depends on (FB = y) && ATARI && BROKEN
 	help
 	  This is the frame buffer device driver for the builtin graphics
 	  chipset found in Ataris.
 
 config FB_OF
 	bool "Open Firmware frame buffer device support"
-	depends on FB && (PPC64 || PPC_OF)
+	depends on (FB = y) && (PPC64 || PPC_OF)
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	select FB_SOFT_CURSOR
 	help
 	  Say Y if you want support with Open Firmware for your graphics
 	  board.
 
 config FB_CONTROL
 	bool "Apple \"control\" display support"
-	depends on FB && PPC_PMAC
+	depends on (FB = y) && PPC_PMAC
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	select FB_SOFT_CURSOR
 	help
 	  This driver supports a frame buffer for the graphics adapter in the
 	  Power Macintosh 7300 and others.
 
 config FB_PLATINUM
 	bool "Apple \"platinum\" display support"
-	depends on FB && PPC_PMAC
+	depends on (FB = y) && PPC_PMAC
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	select FB_SOFT_CURSOR
 	help
 	  This driver supports a frame buffer for the "platinum" graphics
 	  adapter in some Power Macintoshes.
 
 config FB_VALKYRIE
 	bool "Apple \"valkyrie\" display support"
-	depends on FB && (MAC || PPC_PMAC)
+	depends on (FB = y) && (MAC || PPC_PMAC)
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	select FB_SOFT_CURSOR
 	help
 	  This driver supports a frame buffer for the "valkyrie" graphics
 	  adapter in some Power Macintoshes.
 
 config FB_CT65550
 	bool "Chips 65550 display support"
-	depends on FB && PPC
+	depends on (FB = y) && PPC
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	select FB_SOFT_CURSOR
 	help
 	  This is the frame buffer device driver for the Chips & Technologies
 	  65550 graphics chip in PowerBooks.
 
 config FB_ASILIANT
 	bool "Chips 69000 display support"
-	depends on FB && PCI
+	depends on (FB = y) && PCI
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	select FB_SOFT_CURSOR
 
 config FB_IMSTT
 	bool "IMS Twin Turbo display support"
-	depends on FB && PCI
+	depends on (FB = y) && PCI
+	select FB_CFB_IMAGEBLIT
+	select FB_SOFT_CURSOR
 	help
 	  The IMS Twin Turbo is a PCI-based frame buffer card bundled with
 	  many Macintosh and compatible computers.
 
 config FB_S3TRIO
 	bool "S3 Trio display support"
-	depends on FB && PPC && BROKEN
+	depends on (FB = y) && PPC && BROKEN
 	help
 	  If you have a S3 Trio say Y. Say N for S3 Virge.
 
 config FB_VGA16
 	tristate "VGA 16-color graphics support"
 	depends on FB && (X86 || PPC)
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	select FB_SOFT_CURSOR
 	help
 	  This is the frame buffer device driver for VGA 16 color graphic
 	  cards. Say Y if you have such a card.
@@ -297,6 +411,10 @@
 config FB_STI
 	tristate "HP STI frame buffer device support"
 	depends on FB && PARISC
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	select FB_SOFT_CURSOR
 	default y
 	---help---
 	  STI refers to the HP "Standard Text Interface" which is a set of
@@ -313,24 +431,39 @@
 
 config FB_MAC
 	bool "Generic Macintosh display support"
-	depends on FB && MAC
+	depends on (FB = y) && MAC
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	select FB_SOFT_CURSOR
 
 #      bool '  Apple DAFB display support' CONFIG_FB_DAFB
 config FB_HP300
 	bool
-	depends on FB && HP300
+	depends on (FB = y) && HP300
+	select FB_CFB_FILLRECT
+	select FB_CFB_IMAGEBLIT
+	select FB_SOFT_CURSOR
 	default y
 
 config FB_TGA
 	tristate "TGA framebuffer support"
 	depends on FB && ALPHA
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	select FB_SOFT_CURSOR
 	help
 	  This is the frame buffer device driver for generic TGA graphic
 	  cards. Say Y if you have one of those.
 
 config FB_VESA
 	bool "VESA VGA graphics support"
-	depends on FB && (X86 || X86_64)
+	depends on (FB = y) && (X86 || X86_64)
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	select FB_SOFT_CURSOR
 	help
 	  This is the frame buffer device driver for generic VESA 2.0
 	  compliant graphic cards. The older VESA 1.2 cards are not supported.
@@ -345,6 +478,10 @@
 config FB_HGA
 	tristate "Hercules mono graphics support"
 	depends on FB && X86
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	select FB_SOFT_CURSOR
 	help
 	  Say Y here if you have a Hercules mono graphics card.
 
@@ -364,18 +501,26 @@
 
 config VIDEO_SELECT
 	bool
-	depends on FB && X86
+	depends on (FB = y) && X86
 	default y
 
 config FB_SGIVW
 	tristate "SGI Visual Workstation framebuffer support"
 	depends on FB && X86_VISWS
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	select FB_SOFT_CURSOR
 	help
 	  SGI Visual Workstation support for framebuffer graphics.
 
 config FB_GBE
 	bool "SGI Graphics Backend frame buffer support"
-	depends on FB && (SGI_IP32 || X86_VISWS)
+	depends on (FB = y) && (SGI_IP32 || X86_VISWS)
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	select FB_SOFT_CURSOR
  	help
 	  This is the frame buffer device driver for SGI Graphics Backend.
 	  This chip is used in SGI O2 and Visual Workstation 320/540.
@@ -390,28 +535,38 @@
 
 config BUS_I2C
 	bool
-	depends on FB && VISWS
+	depends on (FB = y) && VISWS
 	default y
 
 config FB_SUN3
 	bool "Sun3 framebuffer support"
-	depends on FB && (SUN3 || SUN3X) && BROKEN
+	depends on (FB = y) && (SUN3 || SUN3X) && BROKEN
 
 config FB_BW2
 	bool "BWtwo support"
-	depends on FB && ((SPARC32 || SPARC64) && FB_SBUS || (SUN3 || SUN3X) && FB_SUN3)
+	depends on (FB = y) && ((SPARC32 || SPARC64) && FB_SBUS || (SUN3 || SUN3X) && FB_SUN3)
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	select FB_SOFT_CURSOR
 	help
 	  This is the frame buffer device driver for the BWtwo frame buffer.
 
 config FB_CG3
 	bool "CGthree support"
-	depends on FB && ((SPARC32 || SPARC64) && FB_SBUS || (SUN3 || SUN3X) && FB_SUN3)
+	depends on (FB = y) && ((SPARC32 || SPARC64) && FB_SBUS || (SUN3 || SUN3X) && FB_SUN3)
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	select FB_SOFT_CURSOR
 	help
 	  This is the frame buffer device driver for the CGthree frame buffer.
 
 config FB_CG6
 	bool "CGsix (GX,TurboGX) support"
-	depends on FB && ((SPARC32 || SPARC64) && FB_SBUS || (SUN3 || SUN3X) && FB_SUN3)
+	depends on (FB = y) && ((SPARC32 || SPARC64) && FB_SBUS || (SUN3 || SUN3X) && FB_SUN3)
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	select FB_SOFT_CURSOR
 	help
 	  This is the frame buffer device driver for the CGsix (GX, TurboGX)
 	  frame buffer.
@@ -419,6 +574,10 @@
 config FB_PVR2
 	tristate "NEC PowerVR 2 display support"
 	depends on FB && SH_DREAMCAST
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	select FB_SOFT_CURSOR
 	---help---
 	  Say Y here if you have a PowerVR 2 card in your box.  If you plan to
 	  run linux on your Dreamcast, you will have to say Y here.
@@ -436,19 +595,59 @@
 
 config FB_EPSON1355
 	bool "Epson 1355 framebuffer support"
-	depends on FB && (SUPERH || ARCH_CEIVA)
+	depends on (FB = y) && (SUPERH || ARCH_CEIVA)
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	select FB_SOFT_CURSOR
 	help
 	  Build in support for the SED1355 Epson Research Embedded RAMDAC
 	  LCD/CRT Controller (since redesignated as the S1D13505) as a
 	  framebuffer.  Product specs at
 	  <http://www.erd.epson.com/vdc/html/products.htm>.
 
+config FB_NVIDIA
+	tristate "nVidia Framebuffer Support"
+	depends on FB && PCI
+	select I2C_ALGOBIT if FB_NVIDIA_I2C
+	select I2C if FB_NVIDIA_I2C
+	select FB_MODE_HELPERS
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	select FB_SOFT_CURSOR
+	help
+	  This driver supports graphics boards with the nVidia chips, TNT
+	  and newer. For very old chipsets, such as the RIVA128, then use
+	  the the rivafb.
+	  Say Y if you have such a graphics board.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called nvidiafb.
+          none yet
+
+config FB_NVIDIA_I2C
+       bool "Enable DDC Support"
+       depends on FB_NVIDIA && !PPC_OF
+       help
+	  This enables I2C support for nVidia Chipsets.  This is used
+	  only for getting EDID information from the attached display
+	  allowing for robust video mode handling and switching.
+
+	  Because fbdev-2.6 requires that drivers must be able to
+	  independently validate video mode parameters, you should say Y
+	  here.
+
 config FB_RIVA
 	tristate "nVidia Riva support"
 	depends on FB && PCI
 	select I2C_ALGOBIT if FB_RIVA_I2C
 	select I2C if FB_RIVA_I2C
 	select FB_MODE_HELPERS
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	select FB_SOFT_CURSOR
 	help
 	  This driver supports graphics boards with the nVidia Riva/Geforce
 	  chips.
@@ -484,6 +683,10 @@
 	select AGP
 	select AGP_INTEL
 	select FB_MODE_HELPERS
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	select FB_SOFT_CURSOR
 	help
 	  This driver supports the on-board graphics built in to the Intel 810 
           and 815 chipsets.  Say Y if you have and plan to use such a board.
@@ -522,6 +725,11 @@
 	depends on FB && EXPERIMENTAL && PCI && X86 && !X86_64
 	select AGP
 	select AGP_INTEL
+	select FB_MODE_HELPERS
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	select FB_SOFT_CURSOR
 	help
 	  This driver supports the on-board graphics built in to the Intel
           830M/845G/852GM/855GM/865G chipsets.
@@ -541,6 +749,11 @@
 config FB_MATROX
 	tristate "Matrox acceleration"
 	depends on FB && PCI
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	select FB_SOFT_CURSOR
+	select FB_TILEBLITTING
 	---help---
 	  Say Y here if you have a Matrox Millennium, Matrox Millennium II,
 	  Matrox Mystique, Matrox Mystique 220, Matrox Productiva G100, Matrox
@@ -676,6 +889,10 @@
 config FB_RADEON_OLD
 	tristate "ATI Radeon display support (Old driver)"
 	depends on FB && PCI
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	select FB_SOFT_CURSOR
 	help
 	  Choose this option if you want to use an ATI Radeon graphics card as
 	  a framebuffer device.  There are both PCI and AGP versions.  You
@@ -689,6 +906,10 @@
 	select I2C_ALGOBIT if FB_RADEON_I2C
 	select I2C if FB_RADEON_I2C
 	select FB_MODE_HELPERS
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	select FB_SOFT_CURSOR
 	help
 	  Choose this option if you want to use an ATI Radeon graphics card as
 	  a framebuffer device.  There are both PCI and AGP versions.  You
@@ -723,6 +944,10 @@
 config FB_ATY128
 	tristate "ATI Rage128 display support"
 	depends on FB && PCI
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	select FB_SOFT_CURSOR
 	help
 	  This driver supports graphics boards with the ATI Rage128 chips.
 	  Say Y if you have such a graphics board and read
@@ -734,6 +959,10 @@
 config FB_ATY
 	tristate "ATI Mach64 display support" if PCI || ATARI
 	depends on FB
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	select FB_SOFT_CURSOR
 	help
 	  This driver supports graphics boards with the ATI Mach64 chips.
 	  Say Y if you have such a graphics board.
@@ -781,6 +1010,10 @@
 	select I2C_ALGOBIT if FB_SAVAGE_I2C
 	select I2C if FB_SAVAGE_I2C
 	select FB_MODE_HELPERS
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	select FB_SOFT_CURSOR
 	help
 	  This driver supports notebooks and computers with S3 Savage PCI/AGP
 	  chips.
@@ -791,7 +1024,7 @@
 	  will be called savagefb.
 
 config FB_SAVAGE_I2C
-       tristate "Enable DDC2 Support"
+       bool "Enable DDC2 Support"
        depends on FB_SAVAGE
        help
 	  This enables I2C support for S3 Savage Chipsets.  This is used
@@ -803,7 +1036,7 @@
 	  here.
 
 config FB_SAVAGE_ACCEL
-       tristate "Enable Console Acceleration"
+       bool "Enable Console Acceleration"
        depends on FB_SAVAGE
        default n
        help
@@ -814,6 +1047,10 @@
 config FB_SIS
 	tristate "SiS acceleration"
 	depends on FB && PCI
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	select FB_SOFT_CURSOR
 	help
 	  This is the frame buffer device driver for the SiS 300, 315 and
 	  330 series VGA chipsets. Specs available at <http://www.sis.com>
@@ -838,6 +1075,10 @@
 	tristate "NeoMagic display support"
 	depends on FB && PCI
 	select FB_MODE_HELPERS
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	select FB_SOFT_CURSOR
 	help
 	  This driver supports notebooks with NeoMagic PCI chips.
 	  Say Y if you have such a graphics card. 
@@ -848,6 +1089,10 @@
 config FB_KYRO
 	tristate "IMG Kyro support"
 	depends on FB && PCI
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	select FB_SOFT_CURSOR
 	help
 	  Say Y here if you have a STG4000 / Kyro / PowerVR 3 based
 	  graphics board.
@@ -858,6 +1103,10 @@
 config FB_3DFX
 	tristate "3Dfx Banshee/Voodoo3 display support"
 	depends on FB && PCI
+	select FB_CFB_IMAGEBLIT
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_SOFT_CURSOR
 	help
 	  This driver supports graphics boards with the 3Dfx Banshee/Voodoo3
 	  chips. Say Y if you have such a graphics board.
@@ -876,6 +1125,10 @@
 config FB_VOODOO1
 	tristate "3Dfx Voodoo Graphics (sst1) support"
 	depends on FB && PCI
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	select FB_SOFT_CURSOR
 	---help---
 	  Say Y here if you have a 3Dfx Voodoo Graphics (Voodoo1/sst1) or 
 	  Voodoo2 (cvg) based graphics card.
@@ -891,6 +1144,10 @@
 config FB_TRIDENT
 	tristate "Trident support"
 	depends on FB && PCI
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	select FB_SOFT_CURSOR
 	---help---
 	  This driver is supposed to support graphics boards with the
 	  Trident CyberXXXX/Image/CyberBlade chips mostly found in laptops
@@ -953,17 +1210,22 @@
 
 config FB_AU1100
 	bool "Au1100 LCD Driver"
-	depends on FB && EXPERIMENTAL && PCI && MIPS && MIPS_PB1100=y
+	depends on (FB = y) && EXPERIMENTAL && PCI && MIPS && MIPS_PB1100=y
+
+source "drivers/video/geode/Kconfig"
 
 config FB_SBUS
 	bool "SBUS and UPA framebuffers"
-	depends on FB && (SPARC32 || SPARC64)
+	depends on (FB = y) && (SPARC32 || SPARC64)
 	help
 	  Say Y if you want support for SBUS or UPA based frame buffer device.
 
 config FB_FFB
 	bool "Creator/Creator3D/Elite3D support"
 	depends on FB_SBUS && SPARC64
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	select FB_SOFT_CURSOR
 	help
 	  This is the frame buffer device driver for the Creator, Creator3D,
 	  and Elite3D graphics boards.
@@ -971,6 +1233,10 @@
 config FB_TCX
 	bool "TCX (SS4/SS5 only) support"
 	depends on FB_SBUS
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	select FB_SOFT_CURSOR
 	help
 	  This is the frame buffer device driver for the TCX 24/8bit frame
 	  buffer.
@@ -978,6 +1244,10 @@
 config FB_CG14
 	bool "CGfourteen (SX) support"
 	depends on FB_SBUS
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	select FB_SOFT_CURSOR
 	help
 	  This is the frame buffer device driver for the CGfourteen frame
 	  buffer on Desktop SPARCsystems with the SX graphics option.
@@ -985,6 +1255,10 @@
 config FB_P9100
 	bool "P9100 (Sparcbook 3 only) support"
 	depends on FB_SBUS
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	select FB_SOFT_CURSOR
 	help
 	  This is the frame buffer device driver for the P9100 card
 	  supported on Sparcbook 3 machines.
@@ -992,17 +1266,25 @@
 config FB_LEO
 	bool "Leo (ZX) support"
 	depends on FB_SBUS
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	select FB_SOFT_CURSOR
 	help
 	  This is the frame buffer device driver for the SBUS-based Sun ZX
 	  (leo) frame buffer cards.
 
 config FB_PCI
 	bool "PCI framebuffers"
-	depends on FB && PCI && (SPARC64 || SPARC32)
+	depends on (FB = y) && PCI && (SPARC64 || SPARC32)
 
 config FB_IGA
 	bool "IGA 168x display support"
 	depends on SPARC32 && FB_PCI
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	select FB_SOFT_CURSOR
 	help
 	  This is the framebuffer device for the INTERGRAPHICS 1680 and
 	  successor frame buffer cards.
@@ -1010,27 +1292,43 @@
 config FB_HIT
 	tristate "HD64461 Frame Buffer support"
 	depends on FB && HD64461
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	select FB_SOFT_CURSOR
 	help
 	  This is the frame buffer device driver for the Hitachi HD64461 LCD
 	  frame buffer card.
 
 config FB_PMAG_AA
 	bool "PMAG-AA TURBOchannel framebuffer support"
-	depends on FB && MACH_DECSTATION && TC
+	depends on (FB = y) && MACH_DECSTATION && TC
+ 	select FB_CFB_FILLRECT
+ 	select FB_CFB_COPYAREA
+ 	select FB_CFB_IMAGEBLIT
+	select FB_SOFT_CURSOR
 	help
 	  Support for the PMAG-AA TURBOchannel framebuffer card (1280x1024x1)
 	  used mainly in the MIPS-based DECstation series.
 
 config FB_PMAG_BA
 	bool "PMAG-BA TURBOchannel framebuffer support"
-	depends on FB && MACH_DECSTATION && TC
+	depends on (FB = y) && MACH_DECSTATION && TC
+ 	select FB_CFB_FILLRECT
+ 	select FB_CFB_COPYAREA
+ 	select FB_CFB_IMAGEBLIT
+	select FB_SOFT_CURSOR
 	help
 	  Support for the PMAG-BA TURBOchannel framebuffer card (1024x864x8)
 	  used mainly in the MIPS-based DECstation series.
 
 config FB_PMAGB_B
 	bool "PMAGB-B TURBOchannel framebuffer support"
-	depends on FB && MACH_DECSTATION && TC
+	depends on (FB = y) && MACH_DECSTATION && TC
+ 	select FB_CFB_FILLRECT
+ 	select FB_CFB_COPYAREA
+ 	select FB_CFB_IMAGEBLIT
+	select FB_SOFT_CURSOR
 	help
 	  Support for the PMAGB-B TURBOchannel framebuffer card used mainly
 	  in the MIPS-based DECstation series. The card is currently only
@@ -1038,7 +1336,11 @@
 
 config FB_MAXINE
 	bool "Maxine (Personal DECstation) onboard framebuffer support"
-	depends on FB && MACH_DECSTATION && TC
+	depends on (FB = y) && MACH_DECSTATION && TC
+ 	select FB_CFB_FILLRECT
+ 	select FB_CFB_COPYAREA
+ 	select FB_CFB_IMAGEBLIT
+	select FB_SOFT_CURSOR
 	help
 	  Support for the onboard framebuffer (1024x768x8) in the Personal
 	  DECstation series (Personal DECstation 5000/20, /25, /33, /50,
@@ -1046,7 +1348,11 @@
 
 config FB_TX3912
 	bool "TMPTX3912/PR31700 frame buffer support"
-	depends on FB && NINO
+	depends on (FB = y) && NINO
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	select FB_SOFT_CURSOR
 	help
 	  The TX3912 is a Toshiba RISC processor based on the MIPS 3900 core
 	  see <http://www.toshiba.com/taec/components/Generic/risc/tx3912.htm>.
@@ -1056,6 +1362,10 @@
 config FB_G364
 	bool
 	depends on MIPS_MAGNUM_4000 || OLIVETTI_M700
+ 	select FB_CFB_FILLRECT
+ 	select FB_CFB_COPYAREA
+ 	select FB_CFB_IMAGEBLIT
+	select FB_SOFT_CURSOR
 	help
 	  The G364 driver is the framebuffer used in MIPS Magnum 4000 and
 	  Olivetti M700-10 systems.
@@ -1063,6 +1373,10 @@
 config FB_68328
 	bool "Motorola 68328 native frame buffer support"
 	depends on (M68328 || M68EZ328 || M68VZ328)
+ 	select FB_CFB_FILLRECT
+ 	select FB_CFB_COPYAREA
+ 	select FB_CFB_IMAGEBLIT
+	select FB_SOFT_CURSOR
 	help
 	  Say Y here if you want to support the built-in frame buffer of
 	  the Motorola 68328 CPU family.
@@ -1070,6 +1384,10 @@
 config FB_PXA
 	tristate "PXA LCD framebuffer support"
 	depends on FB && ARCH_PXA
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	select FB_SOFT_CURSOR
 	---help---
 	  Frame buffer driver for the built-in LCD controller in the Intel
 	  PXA2x0 processor.
@@ -1084,6 +1402,10 @@
 config FB_W100
 	tristate "W100 frame buffer support"
 	depends on FB && PXA_SHARPSL
+ 	select FB_CFB_FILLRECT
+ 	select FB_CFB_COPYAREA
+ 	select FB_CFB_IMAGEBLIT
+	select FB_SOFT_CURSOR
 	---help---
 	  Frame buffer driver for the w100 as found on the Sharp SL-Cxx series.
 
@@ -1114,6 +1436,10 @@
 config FB_VIRTUAL
 	tristate "Virtual Frame Buffer support (ONLY FOR TESTING!)"
 	depends on FB
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	select FB_SOFT_CURSOR
 	---help---
 	  This is a `virtual' frame buffer device. It operates on a chunk of
 	  unswappable kernel memory instead of on the memory of a graphics
diff -Nru a/drivers/video/Makefile b/drivers/video/Makefile
--- a/drivers/video/Makefile	2005-03-11 12:51:41 -08:00
+++ b/drivers/video/Makefile	2005-03-11 12:51:41 -08:00
@@ -8,102 +8,91 @@
 obj-$(CONFIG_LOGO)		  += logo/
 obj-$(CONFIG_SYSFS)		  += backlight/
 
-obj-$(CONFIG_FB)                  += fbmem.o fbmon.o fbcmap.o fbsysfs.o modedb.o softcursor.o
-# Only include macmodes.o if we have FB support and are PPC
-ifeq ($(CONFIG_FB),y)
-obj-$(CONFIG_PPC)                 += macmodes.o
-endif
+obj-$(CONFIG_FB)                  += fb.o
+fb-y                              := fbmem.o fbmon.o fbcmap.o fbsysfs.o modedb.o
+fb-objs                           := $(fb-y)
+
+obj-$(CONFIG_FB_CFB_FILLRECT)  += cfbfillrect.o
+obj-$(CONFIG_FB_CFB_COPYAREA)  += cfbcopyarea.o
+obj-$(CONFIG_FB_CFB_IMAGEBLIT) += cfbimgblt.o
+obj-$(CONFIG_FB_SOFT_CURSOR)   += softcursor.o
 
 # Hardware specific drivers go first
 obj-$(CONFIG_FB_RETINAZ3)         += retz3fb.o
 obj-$(CONFIG_FB_AMIGA)            += amifb.o c2p.o
-obj-$(CONFIG_FB_CLPS711X)         += clps711xfb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
+obj-$(CONFIG_FB_CLPS711X)         += clps711xfb.o
 obj-$(CONFIG_FB_CYBER)            += cyberfb.o
-obj-$(CONFIG_FB_CYBER2000)        += cyber2000fb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
-obj-$(CONFIG_FB_PM2)              += pm2fb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
+obj-$(CONFIG_FB_CYBER2000)        += cyber2000fb.o
+obj-$(CONFIG_FB_PM2)              += pm2fb.o
 obj-$(CONFIG_FB_PM3)		  += pm3fb.o
 
-obj-$(CONFIG_FB_MATROX)		  += matrox/ cfbfillrect.o cfbcopyarea.o cfbimgblt.o
-obj-$(CONFIG_FB_RIVA)		  += riva/ cfbimgblt.o cfbfillrect.o \
-				     cfbcopyarea.o vgastate.o
-obj-$(CONFIG_FB_ATY)		  += aty/ cfbcopyarea.o cfbfillrect.o cfbimgblt.o
-obj-$(CONFIG_FB_ATY128)		  += aty/ cfbcopyarea.o cfbfillrect.o cfbimgblt.o
-obj-$(CONFIG_FB_RADEON)		  += aty/ cfbcopyarea.o cfbfillrect.o cfbimgblt.o
-obj-$(CONFIG_FB_SIS)		  += sis/ cfbcopyarea.o cfbfillrect.o cfbimgblt.o
-obj-$(CONFIG_FB_KYRO)             += kyro/ cfbfillrect.o cfbcopyarea.o cfbimgblt.o
-obj-$(CONFIG_FB_SAVAGE)		  += savage/ cfbfillrect.o cfbcopyarea.o \
-				     cfbimgblt.o
-obj-$(CONFIG_FB_I810)             += cfbcopyarea.o cfbfillrect.o cfbimgblt.o \
-				     vgastate.o
-obj-$(CONFIG_FB_INTEL)            += cfbfillrect.o cfbcopyarea.o \
-	                             cfbimgblt.o
-
-obj-$(CONFIG_FB_RADEON_OLD)	  += radeonfb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
-obj-$(CONFIG_FB_NEOMAGIC)         += neofb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o vgastate.o
+obj-$(CONFIG_FB_MATROX)		  += matrox/
+obj-$(CONFIG_FB_RIVA)		  += riva/ vgastate.o
+obj-$(CONFIG_FB_NVIDIA)		  += nvidia/
+obj-$(CONFIG_FB_ATY)		  += aty/
+obj-$(CONFIG_FB_ATY128)		  += aty/
+obj-$(CONFIG_FB_RADEON)		  += aty/
+obj-$(CONFIG_FB_SIS)		  += sis/
+obj-$(CONFIG_FB_KYRO)             += kyro/
+obj-$(CONFIG_FB_SAVAGE)		  += savage/
+obj-$(CONFIG_FB_GEODE)		  += geode/
+obj-$(CONFIG_FB_I810)             += vgastate.o
+obj-$(CONFIG_FB_RADEON_OLD)	  += radeonfb.o
+obj-$(CONFIG_FB_NEOMAGIC)         += neofb.o vgastate.o
 obj-$(CONFIG_FB_VIRGE)            += virgefb.o
-obj-$(CONFIG_FB_3DFX)             += tdfxfb.o cfbimgblt.o
-ifneq ($(CONFIG_FB_3DFX_ACCEL),y)
-obj-$(CONFIG_FB_3DFX)             += cfbfillrect.o cfbcopyarea.o
-endif
-obj-$(CONFIG_FB_CONTROL)          += controlfb.o macmodes.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
-obj-$(CONFIG_FB_PLATINUM)         += platinumfb.o macmodes.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
-obj-$(CONFIG_FB_VALKYRIE)         += valkyriefb.o macmodes.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
-obj-$(CONFIG_FB_CT65550)          += chipsfb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
-obj-$(CONFIG_FB_IMSTT)            += imsttfb.o cfbimgblt.o
+obj-$(CONFIG_FB_3DFX)             += tdfxfb.o
+obj-$(CONFIG_FB_CONTROL)          += controlfb.o macmodes.o
+obj-$(CONFIG_FB_PLATINUM)         += platinumfb.o macmodes.o
+obj-$(CONFIG_FB_VALKYRIE)         += valkyriefb.o macmodes.o
+obj-$(CONFIG_FB_CT65550)          += chipsfb.o
+obj-$(CONFIG_FB_IMSTT)            += imsttfb.o
 obj-$(CONFIG_FB_S3TRIO)           += S3triofb.o
-obj-$(CONFIG_FB_FM2)              += fm2fb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
-obj-$(CONFIG_FB_TRIDENT)	  += tridentfb.o cfbfillrect.o cfbimgblt.o cfbcopyarea.o
-obj-$(CONFIG_FB_STI)              += stifb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
-obj-$(CONFIG_FB_FFB)              += ffb.o sbuslib.o cfbimgblt.o cfbcopyarea.o
-obj-$(CONFIG_FB_CG6)              += cg6.o sbuslib.o cfbimgblt.o cfbcopyarea.o
-obj-$(CONFIG_FB_CG3)              += cg3.o sbuslib.o cfbimgblt.o cfbcopyarea.o \
-				     cfbfillrect.o
-obj-$(CONFIG_FB_BW2)              += bw2.o sbuslib.o cfbimgblt.o cfbcopyarea.o \
-				     cfbfillrect.o
-obj-$(CONFIG_FB_CG14)             += cg14.o sbuslib.o cfbimgblt.o cfbcopyarea.o \
-				     cfbfillrect.o
-obj-$(CONFIG_FB_P9100)            += p9100.o sbuslib.o cfbimgblt.o cfbcopyarea.o \
-				     cfbfillrect.o
-obj-$(CONFIG_FB_TCX)              += tcx.o sbuslib.o cfbimgblt.o cfbcopyarea.o \
-				     cfbfillrect.o
-obj-$(CONFIG_FB_LEO)              += leo.o sbuslib.o cfbimgblt.o cfbcopyarea.o \
-				     cfbfillrect.o
-obj-$(CONFIG_FB_SGIVW)            += sgivwfb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
-obj-$(CONFIG_FB_ACORN)            += acornfb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
+obj-$(CONFIG_FB_FM2)              += fm2fb.o
+obj-$(CONFIG_FB_TRIDENT)	  += tridentfb.o
+obj-$(CONFIG_FB_STI)              += stifb.o
+obj-$(CONFIG_FB_FFB)              += ffb.o sbuslib.o
+obj-$(CONFIG_FB_CG6)              += cg6.o sbuslib.o
+obj-$(CONFIG_FB_CG3)              += cg3.o sbuslib.o
+obj-$(CONFIG_FB_BW2)              += bw2.o sbuslib.o
+obj-$(CONFIG_FB_CG14)             += cg14.o sbuslib.o
+obj-$(CONFIG_FB_P9100)            += p9100.o sbuslib.o
+obj-$(CONFIG_FB_TCX)              += tcx.o sbuslib.o
+obj-$(CONFIG_FB_LEO)              += leo.o sbuslib.o
+obj-$(CONFIG_FB_SGIVW)            += sgivwfb.o
+obj-$(CONFIG_FB_ACORN)            += acornfb.o
 obj-$(CONFIG_FB_ATARI)            += atafb.o
-obj-$(CONFIG_FB_MAC)              += macfb.o macmodes.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
-obj-$(CONFIG_FB_HGA)              += hgafb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o 
-obj-$(CONFIG_FB_IGA)              += igafb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
-obj-$(CONFIG_FB_APOLLO)           += dnfb.o cfbfillrect.o cfbimgblt.o
-obj-$(CONFIG_FB_Q40)              += q40fb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
-obj-$(CONFIG_FB_TGA)              += tgafb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
-obj-$(CONFIG_FB_HP300)            += hpfb.o cfbfillrect.o cfbimgblt.o
-obj-$(CONFIG_FB_G364)             += g364fb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
-obj-$(CONFIG_FB_SA1100)           += sa1100fb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
+obj-$(CONFIG_FB_MAC)              += macfb.o macmodes.o
+obj-$(CONFIG_FB_HGA)              += hgafb.o
+obj-$(CONFIG_FB_IGA)              += igafb.o
+obj-$(CONFIG_FB_APOLLO)           += dnfb.o
+obj-$(CONFIG_FB_Q40)              += q40fb.o
+obj-$(CONFIG_FB_TGA)              += tgafb.o
+obj-$(CONFIG_FB_HP300)            += hpfb.o
+obj-$(CONFIG_FB_G364)             += g364fb.o
+obj-$(CONFIG_FB_SA1100)           += sa1100fb.o
 obj-$(CONFIG_FB_SUN3)             += sun3fb.o
-obj-$(CONFIG_FB_HIT)              += hitfb.o cfbfillrect.o cfbimgblt.o
-obj-$(CONFIG_FB_EPSON1355)	  += epson1355fb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
-obj-$(CONFIG_FB_PVR2)             += pvr2fb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
-obj-$(CONFIG_FB_VOODOO1)          += sstfb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
-obj-$(CONFIG_FB_ARMCLCD)	  += amba-clcd.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
-obj-$(CONFIG_FB_68328)            += 68328fb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
-obj-$(CONFIG_FB_GBE)              += gbefb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
-obj-$(CONFIG_FB_CIRRUS)		  += cirrusfb.o cfbfillrect.o cfbimgblt.o cfbcopyarea.o
-obj-$(CONFIG_FB_ASILIANT)	  += asiliantfb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
-obj-$(CONFIG_FB_PXA)		  += pxafb.o cfbimgblt.o cfbcopyarea.o cfbfillrect.o
-obj-$(CONFIG_FB_W100)		   += w100fb.o cfbimgblt.o cfbcopyarea.o cfbfillrect.o
+obj-$(CONFIG_FB_HIT)              += hitfb.o
+obj-$(CONFIG_FB_EPSON1355)	  += epson1355fb.o
+obj-$(CONFIG_FB_PVR2)             += pvr2fb.o
+obj-$(CONFIG_FB_VOODOO1)          += sstfb.o
+obj-$(CONFIG_FB_ARMCLCD)	  += amba-clcd.o
+obj-$(CONFIG_FB_68328)            += 68328fb.o
+obj-$(CONFIG_FB_GBE)              += gbefb.o
+obj-$(CONFIG_FB_CIRRUS)		  += cirrusfb.o
+obj-$(CONFIG_FB_ASILIANT)	  += asiliantfb.o
+obj-$(CONFIG_FB_PXA)		  += pxafb.o
+obj-$(CONFIG_FB_W100)		  += w100fb.o
 obj-$(CONFIG_FB_AU1100)		  += au1100fb.o fbgen.o
-obj-$(CONFIG_FB_PMAG_AA)	  += pmag-aa-fb.o  cfbfillrect.o cfbcopyarea.o cfbimgblt.o
-obj-$(CONFIG_FB_PMAG_BA)	  += pmag-ba-fb.o  cfbfillrect.o cfbcopyarea.o cfbimgblt.o
-obj-$(CONFIG_FB_PMAGB_B)	  += pmagb-b-fb.o  cfbfillrect.o cfbcopyarea.o cfbimgblt.o
-obj-$(CONFIG_FB_MAXINE)		  += maxinefb.o  cfbfillrect.o cfbcopyarea.o cfbimgblt.o
-obj-$(CONFIG_FB_TX3912)		  += tx3912fb.o  cfbfillrect.o cfbcopyarea.o cfbimgblt.o
+obj-$(CONFIG_FB_PMAG_AA)	  += pmag-aa-fb.o
+obj-$(CONFIG_FB_PMAG_BA)	  += pmag-ba-fb.o
+obj-$(CONFIG_FB_PMAGB_B)	  += pmagb-b-fb.o
+obj-$(CONFIG_FB_MAXINE)		  += maxinefb.o
+obj-$(CONFIG_FB_TX3912)		  += tx3912fb.o
 
 # Platform or fallback drivers go here
-obj-$(CONFIG_FB_VESA)             += vesafb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
-obj-$(CONFIG_FB_VGA16)            += vga16fb.o cfbfillrect.o cfbcopyarea.o \
-	                             cfbimgblt.o vgastate.o
-obj-$(CONFIG_FB_OF)               += offb.o cfbfillrect.o cfbimgblt.o cfbcopyarea.o
+obj-$(CONFIG_FB_VESA)             += vesafb.o
+obj-$(CONFIG_FB_VGA16)            += vga16fb.o vgastate.o
+obj-$(CONFIG_FB_OF)               += offb.o
 
 # the test framebuffer is last
-obj-$(CONFIG_FB_VIRTUAL)          += vfb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
+obj-$(CONFIG_FB_VIRTUAL)          += vfb.o
diff -Nru a/drivers/video/asiliantfb.c b/drivers/video/asiliantfb.c
--- a/drivers/video/asiliantfb.c	2005-03-11 12:51:51 -08:00
+++ b/drivers/video/asiliantfb.c	2005-03-11 12:51:51 -08:00
@@ -465,7 +465,7 @@
 	{0xd1, 0x01},
 };
 
-static void __init chips_hw_init(struct fb_info *p)
+static void __devinit chips_hw_init(struct fb_info *p)
 {
 	int i;
 
@@ -488,7 +488,7 @@
 		write_fr(chips_init_fr[i].addr, chips_init_fr[i].data);
 }
 
-static struct fb_fix_screeninfo asiliantfb_fix __initdata = {
+static struct fb_fix_screeninfo asiliantfb_fix __devinitdata = {
 	.id =		"Asiliant 69000",
 	.type =		FB_TYPE_PACKED_PIXELS,
 	.visual =	FB_VISUAL_PSEUDOCOLOR,
@@ -497,7 +497,7 @@
 	.smem_len =	0x200000,	/* 2MB */
 };
 
-static struct fb_var_screeninfo asiliantfb_var __initdata = {
+static struct fb_var_screeninfo asiliantfb_var __devinitdata = {
 	.xres 		= 640,
 	.yres 		= 480,
 	.xres_virtual 	= 640,
@@ -518,7 +518,7 @@
 	.vsync_len 	= 2,
 };
 
-static void __init init_asiliant(struct fb_info *p, unsigned long addr)
+static void __devinit init_asiliant(struct fb_info *p, unsigned long addr)
 {
 	p->fix			= asiliantfb_fix;
 	p->fix.smem_start	= addr;
diff -Nru a/drivers/video/aty/aty128fb.c b/drivers/video/aty/aty128fb.c
--- a/drivers/video/aty/aty128fb.c	2005-03-11 12:51:46 -08:00
+++ b/drivers/video/aty/aty128fb.c	2005-03-11 12:51:46 -08:00
@@ -425,11 +425,6 @@
 
 #define round_div(n, d) ((n+(d/2))/d)
 
-    /*
-     *  Interface used by the world
-     */
-int aty128fb_init(void);
-
 static int aty128fb_check_var(struct fb_var_screeninfo *var,
 			      struct fb_info *info);
 static int aty128fb_set_par(struct fb_info *info);
@@ -1648,7 +1643,8 @@
 	return 0;
 }
 
-int __init aty128fb_setup(char *options)
+#ifndef MODULE
+static int __init aty128fb_setup(char *options)
 {
 	char *this_opt;
 
@@ -1701,6 +1697,7 @@
 	}
 	return 0;
 }
+#endif  /*  MODULE  */
 
 
 /*
@@ -2334,6 +2331,7 @@
 {
 	struct fb_info *info = pci_get_drvdata(pdev);
 	struct aty128fb_par *par = info->par;
+	u8 agp;
 
 	/* We don't do anything but D2, for now we return 0, but
 	 * we may want to change that. How do we know if the BIOS
@@ -2371,6 +2369,27 @@
 	par->asleep = 1;
 	par->lock_blank = 1;
 
+	/* Disable AGP. The AGP host should have done it, but since ordering
+	 * isn't always properly guaranteed in this specific case, let's make
+	 * sure it's disabled on card side now. Ultimately, when merging fbdev
+	 * and dri into some common infrastructure, this will be handled
+	 * more nicely. The host bridge side will (or will not) be dealt with
+	 * by the bridge AGP driver, we don't attempt to touch it here.
+	 */
+	agp = pci_find_capability(pdev, PCI_CAP_ID_AGP);
+	if (agp) {
+		u32 cmd;
+
+		pci_read_config_dword(pdev, agp + PCI_AGP_COMMAND, &cmd);
+		if (cmd & PCI_AGP_COMMAND_AGP) {
+			printk(KERN_INFO "aty128fb: AGP was enabled, "
+			       "disabling ...\n");
+			cmd &= ~PCI_AGP_COMMAND_AGP;
+			pci_write_config_dword(pdev, agp + PCI_AGP_COMMAND,
+					       cmd);
+		}
+	}
+
 	/* We need a way to make sure the fbdev layer will _not_ touch the
 	 * framebuffer before we put the chip to suspend state. On 2.4, I
 	 * used dummy fb ops, 2.5 need proper support for this at the
@@ -2432,7 +2451,7 @@
 }
 
 
-int __init aty128fb_init(void)
+static int __init aty128fb_init(void)
 {
 #ifndef MODULE
 	char *option = NULL;
@@ -2452,7 +2471,6 @@
 
 module_init(aty128fb_init);
 
-#ifdef MODULE
 module_exit(aty128fb_exit);
 
 MODULE_AUTHOR("(c)1999-2003 Brad Douglas <brad@neruo.com>");
@@ -2463,6 +2481,5 @@
 #ifdef CONFIG_MTRR
 module_param_named(nomtrr, mtrr, invbool, 0);
 MODULE_PARM_DESC(nomtrr, "bool: Disable MTRR support (0 or 1=disabled) (default=0)");
-#endif
 #endif
 
diff -Nru a/drivers/video/aty/atyfb.h b/drivers/video/aty/atyfb.h
--- a/drivers/video/aty/atyfb.h	2005-03-11 12:51:47 -08:00
+++ b/drivers/video/aty/atyfb.h	2005-03-11 12:51:47 -08:00
@@ -334,7 +334,6 @@
      */
 
 extern int aty_init_cursor(struct fb_info *info);
-extern int atyfb_cursor(struct fb_info *info, struct fb_cursor *cursor);
 
     /*
      *  Hardware acceleration
diff -Nru a/drivers/video/aty/atyfb_base.c b/drivers/video/aty/atyfb_base.c
--- a/drivers/video/aty/atyfb_base.c	2005-03-11 12:51:47 -08:00
+++ b/drivers/video/aty/atyfb_base.c	2005-03-11 12:51:47 -08:00
@@ -209,7 +209,7 @@
 	unsigned long prot_mask;
 };
 
-static struct fb_fix_screeninfo atyfb_fix __initdata = {
+static struct fb_fix_screeninfo atyfb_fix __devinitdata = {
 	.id		= "ATY Mach64",
 	.type		= FB_TYPE_PACKED_PIXELS,
 	.visual		= FB_VISUAL_PSEUDOCOLOR,
@@ -265,7 +265,7 @@
      *  Interface used by the world
      */
 
-struct fb_var_screeninfo default_var = {
+static struct fb_var_screeninfo default_var = {
 	/* 640x480, 60 Hz, Non-Interlaced (25.175 MHz dotclock) */
 	640, 480, 640, 480, 0, 0, 8, 0,
 	{0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
@@ -361,7 +361,7 @@
 	const char *name;
 	int pll, mclk, xclk;
 	u32 features;
-} aty_chips[] __initdata = {
+} aty_chips[] __devinitdata = {
 #ifdef CONFIG_FB_ATY_GX
 	/* Mach64 GX */
 	{ PCI_CHIP_MACH64GX, "ATI888GX00 (Mach64 GX)", 135, 50, 50, ATI_CHIP_88800GX },
@@ -492,31 +492,31 @@
 	return 0;
 }
 
-static char ram_dram[] __initdata = "DRAM";
-static char ram_resv[] __initdata = "RESV";
+static char ram_dram[] __devinitdata = "DRAM";
+static char ram_resv[] __devinitdata = "RESV";
 #ifdef CONFIG_FB_ATY_GX
-static char ram_vram[] __initdata = "VRAM";
+static char ram_vram[] __devinitdata = "VRAM";
 #endif /* CONFIG_FB_ATY_GX */
 #ifdef CONFIG_FB_ATY_CT
-static char ram_edo[] __initdata = "EDO";
-static char ram_sdram[] __initdata = "SDRAM (1:1)";
-static char ram_sgram[] __initdata = "SGRAM (1:1)";
-static char ram_sdram32[] __initdata = "SDRAM (2:1) (32-bit)";
-static char ram_off[] __initdata = "OFF";
+static char ram_edo[] __devinitdata = "EDO";
+static char ram_sdram[] __devinitdata = "SDRAM (1:1)";
+static char ram_sgram[] __devinitdata = "SGRAM (1:1)";
+static char ram_sdram32[] __devinitdata = "SDRAM (2:1) (32-bit)";
+static char ram_off[] __devinitdata = "OFF";
 #endif /* CONFIG_FB_ATY_CT */
 
 
 static u32 pseudo_palette[17];
 
 #ifdef CONFIG_FB_ATY_GX
-static char *aty_gx_ram[8] __initdata = {
+static char *aty_gx_ram[8] __devinitdata = {
 	ram_dram, ram_vram, ram_vram, ram_dram,
 	ram_dram, ram_vram, ram_vram, ram_resv
 };
 #endif /* CONFIG_FB_ATY_GX */
 
 #ifdef CONFIG_FB_ATY_CT
-static char *aty_ct_ram[8] __initdata = {
+static char *aty_ct_ram[8] __devinitdata = {
 	ram_off, ram_dram, ram_edo, ram_edo,
 	ram_sdram, ram_sgram, ram_sdram32, ram_resv
 };
@@ -2990,7 +2990,7 @@
 
 #ifdef __i386__
 #ifdef CONFIG_FB_ATY_GENERIC_LCD
-void aty_init_lcd(struct atyfb_par *par, u32 bios_base)
+static void aty_init_lcd(struct atyfb_par *par, u32 bios_base)
 {
 	u32 driv_inf_tab, sig;
 	u16 lcd_ofs;
@@ -3589,7 +3589,8 @@
 
 #endif /* CONFIG_PCI */
 
-int __init atyfb_setup(char *options)
+#ifndef MODULE
+static int __init atyfb_setup(char *options)
 {
 	char *this_opt;
 
@@ -3657,8 +3658,9 @@
 	}
 	return 0;
 }
+#endif  /*  MODULE  */
 
-int __init atyfb_init(void)
+static int __init atyfb_init(void)
 {
 #ifndef MODULE
     char *option = NULL;
@@ -3677,7 +3679,7 @@
     return 0;
 }
 
-void __exit atyfb_exit(void)
+static void __exit atyfb_exit(void)
 {
 #ifdef CONFIG_PCI
 	pci_unregister_driver(&atyfb_driver);
@@ -3685,9 +3687,7 @@
 }
 
 module_init(atyfb_init);
-#ifdef MODULE
 module_exit(atyfb_exit);
-#endif
 
 MODULE_DESCRIPTION("FBDev driver for ATI Mach64 cards");
 MODULE_LICENSE("GPL");
diff -Nru a/drivers/video/aty/mach64_ct.c b/drivers/video/aty/mach64_ct.c
--- a/drivers/video/aty/mach64_ct.c	2005-03-11 12:51:52 -08:00
+++ b/drivers/video/aty/mach64_ct.c	2005-03-11 12:51:52 -08:00
@@ -359,7 +359,8 @@
 #endif
 }
 
-void __init aty_get_pll_ct(const struct fb_info *info, union aty_pll *pll)
+static void __init aty_get_pll_ct(const struct fb_info *info,
+				  union aty_pll *pll)
 {
 	struct atyfb_par *par = (struct atyfb_par *) info->par;
 	u8 tmp, clock;
@@ -382,7 +383,9 @@
 	}
 }
 
-int __init aty_init_pll_ct(const struct fb_info *info, union aty_pll *pll) {
+static int __init aty_init_pll_ct(const struct fb_info *info,
+				 union aty_pll *pll)
+{
 	struct atyfb_par *par = (struct atyfb_par *) info->par;
 	u8 mpost_div, xpost_div, sclk_post_div_real, sclk_fb_div, spll_cntl2;
 	u32 q, i, memcntl, trp;
diff -Nru a/drivers/video/aty/mach64_cursor.c b/drivers/video/aty/mach64_cursor.c
--- a/drivers/video/aty/mach64_cursor.c	2005-03-11 12:51:52 -08:00
+++ b/drivers/video/aty/mach64_cursor.c	2005-03-11 12:51:52 -08:00
@@ -71,7 +71,7 @@
 	0xa8, 0x28, 0x88, 0x08, 0xa0, 0x20, 0x80, 0x00
 };
 
-int atyfb_cursor(struct fb_info *info, struct fb_cursor *cursor)
+static int atyfb_cursor(struct fb_info *info, struct fb_cursor *cursor)
 {
 	struct atyfb_par *par = (struct atyfb_par *) info->par;
 	u16 xoff, yoff;
diff -Nru a/drivers/video/aty/radeon_base.c b/drivers/video/aty/radeon_base.c
--- a/drivers/video/aty/radeon_base.c	2005-03-11 12:51:42 -08:00
+++ b/drivers/video/aty/radeon_base.c	2005-03-11 12:51:42 -08:00
@@ -530,7 +530,11 @@
         break;
 	}
 
+	radeon_pll_workaround_before(rinfo);
 	ppll_div_sel = INREG8(CLOCK_CNTL_INDEX + 1) & 0x3;
+	radeon_pll_workaround_after(rinfo);
+	if (rinfo->R300_cg_workaround)
+		R300_cg_workardound(rinfo);
 
 	n = (INPLL(PPLL_DIV_0 + ppll_div_sel) & 0x7ff);
 	m = (INPLL(PPLL_REF_DIV) & 0x3ff);
@@ -913,7 +917,7 @@
 
 			OUTREG(CRTC_EXT_CNTL, tmp);
 
-			break;
+			return 0;
 		case FBIO_RADEON_GET_MIRROR:
 			if (!rinfo->is_mobility)
 				return -EINVAL;
@@ -1139,7 +1143,8 @@
 }
 
 
-void radeon_save_state (struct radeonfb_info *rinfo, struct radeon_regs *save)
+static void radeon_save_state (struct radeonfb_info *rinfo,
+			       struct radeon_regs *save)
 {
 	/* CRTC regs */
 	save->crtc_gen_cntl = INREG(CRTC_GEN_CNTL);
@@ -1168,7 +1173,11 @@
 	save->vclk_ecp_cntl = INPLL(VCLK_ECP_CNTL);
 
 	/* PLL regs */
+	radeon_pll_workaround_before(rinfo);
 	save->clk_cntl_index = INREG(CLOCK_CNTL_INDEX) & ~0x3f;
+	radeon_pll_workaround_after(rinfo);
+	if (rinfo->R300_cg_workaround)
+		R300_cg_workardound(rinfo);
 	save->ppll_div_3 = INPLL(PPLL_DIV_3);
 	save->ppll_ref_div = INPLL(PPLL_REF_DIV);
 }
@@ -1195,9 +1204,13 @@
 			/* We still have to force a switch to selected PPLL div thanks to
 			 * an XFree86 driver bug which will switch it away in some cases
 			 * even when using UseFDev */
+			radeon_pll_workaround_before(rinfo);
 			OUTREGP(CLOCK_CNTL_INDEX,
 				mode->clk_cntl_index & PPLL_DIV_SEL_MASK,
 				~PPLL_DIV_SEL_MASK);
+			radeon_pll_workaround_after(rinfo);
+			if (rinfo->R300_cg_workaround)
+				R300_cg_workardound(rinfo);
             		return;
 		}
 	}
@@ -1211,9 +1224,13 @@
 		~(PPLL_RESET | PPLL_ATOMIC_UPDATE_EN | PPLL_VGA_ATOMIC_UPDATE_EN));
 
 	/* Switch to selected PPLL divider */
+	radeon_pll_workaround_before(rinfo);
 	OUTREGP(CLOCK_CNTL_INDEX,
 		mode->clk_cntl_index & PPLL_DIV_SEL_MASK,
 		~PPLL_DIV_SEL_MASK);
+	radeon_pll_workaround_after(rinfo);
+	if (rinfo->R300_cg_workaround)
+		R300_cg_workardound(rinfo);
 
 	/* Set PPLL ref. div */
 	if (rinfo->family == CHIP_FAMILY_R300 ||
@@ -2359,6 +2376,15 @@
 	radeon_save_state (rinfo, &rinfo->init_state);
 	memcpy(&rinfo->state, &rinfo->init_state, sizeof(struct radeon_regs));
 
+	/* Setup Power Management capabilities */
+	if (default_dynclk < -1) {
+		/* -2 is special: means  ON on mobility chips and do not
+		 * change on others
+		 */
+		radeonfb_pm_init(rinfo, rinfo->is_mobility ? 1 : -1);
+	} else
+		radeonfb_pm_init(rinfo, default_dynclk);
+
 	pci_set_drvdata(pdev, info);
 
 	/* Register with fbdev layer */
@@ -2369,13 +2395,6 @@
 		goto err_unmap_fb;
 	}
 
-	/* Setup Power Management capabilities */
-	if (default_dynclk < -1) {
-		/* -2 is special: means  ON on mobility chips and do not change on others */
-		radeonfb_pm_init(rinfo, rinfo->is_mobility ? 1 : -1);
-	} else
-		radeonfb_pm_init(rinfo, default_dynclk);
-
 #ifdef CONFIG_MTRR
 	rinfo->mtrr_hdl = nomtrr ? -1 : mtrr_add(rinfo->fb_base_phys,
 						 rinfo->video_ram,
@@ -2486,27 +2505,8 @@
 #endif /* CONFIG_PM */
 };
 
-int __init radeonfb_setup (char *options);
-
-int __init radeonfb_init (void)
-{
 #ifndef MODULE
-	char *option = NULL;
-
-	if (fb_get_options("radeonfb", &option))
-		return -ENODEV;
-	radeonfb_setup(option);
-#endif
-	return pci_module_init (&radeonfb_driver);
-}
-
-
-void __exit radeonfb_exit (void)
-{
-	pci_unregister_driver (&radeonfb_driver);
-}
-
-int __init radeonfb_setup (char *options)
+static int __init radeonfb_setup (char *options)
 {
 	char *this_opt;
 
@@ -2540,12 +2540,28 @@
 	}
 	return 0;
 }
+#endif  /*  MODULE  */
 
-module_init(radeonfb_init);
+static int __init radeonfb_init (void)
+{
+#ifndef MODULE
+	char *option = NULL;
 
-#ifdef MODULE
-module_exit(radeonfb_exit);
+	if (fb_get_options("radeonfb", &option))
+		return -ENODEV;
+	radeonfb_setup(option);
 #endif
+	return pci_module_init (&radeonfb_driver);
+}
+
+
+static void __exit radeonfb_exit (void)
+{
+	pci_unregister_driver (&radeonfb_driver);
+}
+
+module_init(radeonfb_init);
+module_exit(radeonfb_exit);
 
 MODULE_AUTHOR("Ani Joshi");
 MODULE_DESCRIPTION("framebuffer driver for ATI Radeon chipset");
diff -Nru a/drivers/video/aty/radeon_monitor.c b/drivers/video/aty/radeon_monitor.c
--- a/drivers/video/aty/radeon_monitor.c	2005-03-11 12:51:40 -08:00
+++ b/drivers/video/aty/radeon_monitor.c	2005-03-11 12:51:40 -08:00
@@ -655,8 +655,14 @@
 	 */
 	if (!rinfo->panel_info.use_bios_dividers && rinfo->mon1_type == MT_LCD
 	    && rinfo->is_mobility) {
-		int ppll_div_sel = INREG8(CLOCK_CNTL_INDEX + 1) & 0x3;
-		u32 ppll_divn = INPLL(PPLL_DIV_0 + ppll_div_sel);
+		int ppll_div_sel;
+		u32 ppll_divn;
+		radeon_pll_workaround_before(rinfo);
+		ppll_div_sel = INREG8(CLOCK_CNTL_INDEX + 1) & 0x3;
+		radeon_pll_workaround_after(rinfo);
+		if (rinfo->R300_cg_workaround)
+			R300_cg_workardound(rinfo);
+		ppll_divn = INPLL(PPLL_DIV_0 + ppll_div_sel);
 		rinfo->panel_info.ref_divider = rinfo->pll.ref_div;
 		rinfo->panel_info.fbk_divider = ppll_divn & 0x7ff;
 		rinfo->panel_info.post_divider = (ppll_divn >> 16) & 0x7;
diff -Nru a/drivers/video/aty/radeon_pm.c b/drivers/video/aty/radeon_pm.c
--- a/drivers/video/aty/radeon_pm.c	2005-03-11 12:51:47 -08:00
+++ b/drivers/video/aty/radeon_pm.c	2005-03-11 12:51:47 -08:00
@@ -27,7 +27,7 @@
 
 #include "ati_ids.h"
 
-void radeon_pm_disable_dynamic_mode(struct radeonfb_info *rinfo)
+static void radeon_pm_disable_dynamic_mode(struct radeonfb_info *rinfo)
 {
 	u32 tmp;
 
@@ -229,7 +229,7 @@
 	radeon_msleep(16);
 }
 
-void radeon_pm_enable_dynamic_mode(struct radeonfb_info *rinfo)
+static void radeon_pm_enable_dynamic_mode(struct radeonfb_info *rinfo)
 {
 	u32 tmp;
 
@@ -1372,8 +1372,12 @@
 
 	/* Reconfigure SPLL charge pump, VCO gain, duty cycle */
 	tmp = INPLL(pllSPLL_CNTL);
+	radeon_pll_workaround_before(rinfo);
 	OUTREG8(CLOCK_CNTL_INDEX, pllSPLL_CNTL + PLL_WR_EN);
+	radeon_pll_workaround_after(rinfo);
 	OUTREG8(CLOCK_CNTL_DATA + 1, (tmp >> 8) & 0xff);
+	if (rinfo->R300_cg_workaround)
+		R300_cg_workardound(rinfo);
 
 	/* Set SPLL feedback divider */
 	tmp = INPLL(pllM_SPLL_REF_FB_DIV);
@@ -1405,8 +1409,12 @@
 
 	/* Reconfigure MPLL charge pump, VCO gain, duty cycle */
 	tmp = INPLL(pllMPLL_CNTL);
+	radeon_pll_workaround_before(rinfo);
 	OUTREG8(CLOCK_CNTL_INDEX, pllMPLL_CNTL + PLL_WR_EN);
+	radeon_pll_workaround_after(rinfo);
 	OUTREG8(CLOCK_CNTL_DATA + 1, (tmp >> 8) & 0xff);
+	if (rinfo->R300_cg_workaround)
+		R300_cg_workardound(rinfo);
 
 	/* Set MPLL feedback divider */
 	tmp = INPLL(pllM_SPLL_REF_FB_DIV);
@@ -1524,8 +1532,12 @@
 {
 	u32 tmp;
 
+	radeon_pll_workaround_before(rinfo);
 	OUTREG8(CLOCK_CNTL_INDEX, pllHTOTAL_CNTL + PLL_WR_EN);
+	radeon_pll_workaround_after(rinfo);
 	OUTREG8(CLOCK_CNTL_DATA, 0);
+	if (rinfo->R300_cg_workaround)
+		R300_cg_workardound(rinfo);
 
 	tmp = INPLL(pllVCLK_ECP_CNTL);
 	OUTPLL(pllVCLK_ECP_CNTL, tmp | 0x80);
@@ -1540,12 +1552,12 @@
 	 * probably useless since we already did it ...
 	 */
 	tmp = INPLL(pllPPLL_CNTL);
+	radeon_pll_workaround_before(rinfo);
 	OUTREG8(CLOCK_CNTL_INDEX, pllSPLL_CNTL + PLL_WR_EN);
+	radeon_pll_workaround_after(rinfo);
 	OUTREG8(CLOCK_CNTL_DATA + 1, (tmp >> 8) & 0xff);
-
-	/* Not sure what was intended here ... */
-	tmp = INREG(CLOCK_CNTL_INDEX);
-	OUTREG(CLOCK_CNTL_INDEX, tmp);
+	if (rinfo->R300_cg_workaround)
+		R300_cg_workardound(rinfo);
 
 	/* Restore our "reference" PPLL divider set by firmware
 	 * according to proper spread spectrum calculations
@@ -1569,7 +1581,11 @@
 	mdelay(5);
 
 	/* Switch pixel clock to firmware default div 0 */
+	radeon_pll_workaround_before(rinfo);
 	OUTREG8(CLOCK_CNTL_INDEX+1, 0);
+	radeon_pll_workaround_after(rinfo);
+	if (rinfo->R300_cg_workaround)
+		R300_cg_workardound(rinfo);
 }
 
 static void radeon_pm_m10_reconfigure_mc(struct radeonfb_info *rinfo)
@@ -2400,7 +2416,8 @@
 	 * including PCI config registers, clocks, AGP conf, ...)
 	 */
 	if (suspend) {
-		printk(KERN_DEBUG "radeonfb: switching to D2 state...\n");
+		printk(KERN_DEBUG "radeonfb (%s): switching to D2 state...\n",
+		       pci_name(rinfo->pdev));
 
 		/* Disable dynamic power management of clocks for the
 		 * duration of the suspend/resume process
@@ -2453,7 +2470,8 @@
 			mdelay(500);
 		}
 	} else {
-		printk(KERN_DEBUG "radeonfb: switching to D0 state...\n");
+		printk(KERN_DEBUG "radeonfb (%s): switching to D0 state...\n",
+		       pci_name(rinfo->pdev));
 
 		/* Switch back PCI powermanagment to D0 */
 		mdelay(200);
@@ -2507,6 +2525,7 @@
 {
         struct fb_info *info = pci_get_drvdata(pdev);
         struct radeonfb_info *rinfo = info->par;
+	u8 agp;
 	int i;
 
 	if (state == pdev->dev.power.power_state)
@@ -2523,7 +2542,8 @@
 	if (state != PM_SUSPEND_MEM)
 		goto done;
 	if (susdisking) {
-		printk("suspending to disk but state = %d\n", state);
+		printk("radeonfb (%s): suspending to disk but state = %d\n",
+		       pci_name(pdev), state);
 		goto done;
 	}
 
@@ -2546,6 +2566,28 @@
 	rinfo->lock_blank = 1;
 	del_timer_sync(&rinfo->lvds_timer);
 
+	/* Disable AGP. The AGP host should have done it, but since ordering
+	 * isn't always properly guaranteed in this specific case, let's make
+	 * sure it's disabled on card side now. Ultimately, when merging fbdev
+	 * and dri into some common infrastructure, this will be handled
+	 * more nicely. The host bridge side will (or will not) be dealt with
+	 * by the bridge AGP driver, we don't attempt to touch it here.
+	 */
+	agp = pci_find_capability(pdev, PCI_CAP_ID_AGP);
+	if (agp) {
+		u32 cmd;
+
+		pci_read_config_dword(pdev, agp + PCI_AGP_COMMAND, &cmd);
+		if (cmd & PCI_AGP_COMMAND_AGP) {
+			printk(KERN_INFO "radeonfb (%s): AGP was enabled, "
+			       "disabling ...\n",
+			       pci_name(pdev));
+			cmd &= ~PCI_AGP_COMMAND_AGP;
+			pci_write_config_dword(pdev, agp + PCI_AGP_COMMAND,
+					       cmd);
+		}
+	}
+
 	/* If we support wakeup from poweroff, we save all regs we can including cfg
 	 * space
 	 */
@@ -2569,12 +2611,11 @@
 			OUTREG(LVDS_PLL_CNTL, (INREG(LVDS_PLL_CNTL) & ~30000) | 0x20000);
 			mdelay(20);
 			OUTREG(LVDS_GEN_CNTL, INREG(LVDS_GEN_CNTL) & ~(LVDS_DIGON));
-
-			// FIXME: Use PCI layer
-			for (i = 0; i < 64; ++i)
-				pci_read_config_dword(rinfo->pdev, i * 4,
-						      &rinfo->cfg_save[i]);
 		}
+		// FIXME: Use PCI layer
+		for (i = 0; i < 64; ++i)
+			pci_read_config_dword(pdev, i * 4, &rinfo->cfg_save[i]);
+		pci_disable_device(pdev);
 	}
 	/* If we support D2, we go to it (should be fixed later with a flag forcing
 	 * D3 only for some laptops)
@@ -2727,8 +2768,6 @@
 		if (!strcmp(rinfo->of_node->name, "ATY,ViaParent")) {
 			rinfo->reinit_func = radeon_reinitialize_M9P;
 			rinfo->pm_mode |= radeon_pm_off;
-			/* Workaround not used for now */
-			rinfo->m9p_workaround = 1;
 		}
 
 		/* If any of the above is set, we assume the machine can sleep/resume.
diff -Nru a/drivers/video/aty/radeonfb.h b/drivers/video/aty/radeonfb.h
--- a/drivers/video/aty/radeonfb.h	2005-03-11 12:51:52 -08:00
+++ b/drivers/video/aty/radeonfb.h	2005-03-11 12:51:52 -08:00
@@ -22,11 +22,6 @@
 
 #include <video/radeon.h>
 
-/* Some weird black magic use by Apple driver that we don't use for
- * now --BenH
- */
-#undef HAS_PLL_M9_GPIO_MAGIC
-
 /***************************************************************
  * Most of the definitions here are adapted right from XFree86 *
  ***************************************************************/
@@ -311,7 +306,6 @@
 	int			is_mobility;
 	int			is_IGP;
 	int			R300_cg_workaround;
-	int			m9p_workaround;
 	int			reversed_DAC;
 	int			reversed_TMDS;
 	struct panel_info	panel_info;
@@ -396,6 +390,11 @@
 
 #define OUTREGP(addr,val,mask)	_OUTREGP(rinfo, addr, val,mask)
 
+/* This function is required to workaround a hardware bug in some (all?)
+ * revisions of the R300.  This workaround should be called after every
+ * CLOCK_CNTL_INDEX register access.  If not, register reads afterward
+ * may not be correct.
+ */
 static inline void R300_cg_workardound(struct radeonfb_info *rinfo)
 {
 	u32 save, tmp;
@@ -406,35 +405,36 @@
 	OUTREG(CLOCK_CNTL_INDEX, save);
 }
 
+/*
+ * PLL accesses suffer from various HW issues on the different chip
+ * families. Some R300's need the above workaround, rv200 & friends
+ * need a couple of dummy reads after any write of CLOCK_CNTL_INDEX,
+ * and some RS100/200 need a dummy read before writing to
+ * CLOCK_CNTL_INDEX as well. Instead of testing every chip revision,
+ * we just unconditionally do  the workarounds at once since PLL
+ * accesses are far from beeing performance critical. Except for R300
+ * one which stays separate for now
+ */
+
+static inline void radeon_pll_workaround_before(struct radeonfb_info *rinfo)
+{
+	(void)INREG(CRTC_GEN_CNTL);
+}
+
+static inline void radeon_pll_workaround_after(struct radeonfb_info *rinfo)
+{
+	(void)INREG(CLOCK_CNTL_DATA);
+	(void)INREG(CRTC_GEN_CNTL);
+}
 
 static inline u32 __INPLL(struct radeonfb_info *rinfo, u32 addr)
 {
 	u32 data;
-#ifdef HAS_PLL_M9_GPIO_MAGIC
-	u32 sv[3];
-
-	if (rinfo->m9p_workaround) {
-		sv[0] = INREG(0x19c);
-		sv[1] = INREG(0x1a0);
-		sv[2] = INREG(0x198);
-		OUTREG(0x198, 0);
-		OUTREG(0x1a0, 0);
-		OUTREG(0x19c, 0);
-	}
-#endif /* HAS_PLL_M9_GPIO_MAGIC */
 
+	radeon_pll_workaround_before(rinfo);
 	OUTREG8(CLOCK_CNTL_INDEX, addr & 0x0000003f);
-	data = (INREG(CLOCK_CNTL_DATA));
-
-#ifdef HAS_PLL_M9_GPIO_MAGIC
-	if (rinfo->m9p_workaround) {
-		(void)INREG(CRTC_GEN_CNTL);
-		data = INREG(CLOCK_CNTL_DATA);
-		OUTREG(0x19c, sv[0]);
-		OUTREG(0x1a0, sv[1]);
-		OUTREG(0x198, sv[2]);
-	}
-#endif /* HAS_PLL_M9_GPIO_MAGIC */
+	radeon_pll_workaround_after(rinfo);
+	data = INREG(CLOCK_CNTL_DATA);
 	if (rinfo->R300_cg_workaround)
 		R300_cg_workardound(rinfo);
 	return data;
@@ -454,32 +454,16 @@
 #define INPLL(addr)		_INPLL(rinfo, addr)
 
 
-static inline void __OUTPLL(struct radeonfb_info *rinfo, unsigned int index, u32 val)
+static inline void __OUTPLL(struct radeonfb_info *rinfo, unsigned int index,
+			    u32 val)
 {
-#ifdef HAS_PLL_M9_GPIO_MAGIC
-	u32 sv[3];
-
-	if (rinfo->m9p_workaround) {
-		sv[0] = INREG(0x19c);
-		sv[1] = INREG(0x1a0);
-		sv[2] = INREG(0x198);
-		OUTREG(0x198, 0);
-		OUTREG(0x1a0, 0);
-		OUTREG(0x19c, 0);
-		mdelay(1);
-	}
-#endif /* HAS_PLL_M9_GPIO_MAGIC */
 
+	radeon_pll_workaround_before(rinfo);
 	OUTREG8(CLOCK_CNTL_INDEX, (index & 0x0000003f) | 0x00000080);
+	radeon_pll_workaround_after(rinfo);
 	OUTREG(CLOCK_CNTL_DATA, val);
-
-#ifdef HAS_PLL_M9_GPIO_MAGIC
-	if (rinfo->m9p_workaround) {
-		OUTREG(0x19c, sv[0]);
-		OUTREG(0x1a0, sv[1]);
-		OUTREG(0x198, sv[2]);
-	}
-#endif /* HAS_PLL_M9_GPIO_MAGIC */
+	if (rinfo->R300_cg_workaround)
+		R300_cg_workardound(rinfo);
 }
 
 static inline void _OUTPLL(struct radeonfb_info *rinfo, unsigned int index, u32 val)
@@ -647,7 +631,6 @@
 
 /* Other functions */
 extern int radeon_screen_blank(struct radeonfb_info *rinfo, int blank, int mode_switch);
-extern void radeon_save_state (struct radeonfb_info *rinfo, struct radeon_regs *save);
 extern void radeon_write_mode (struct radeonfb_info *rinfo, struct radeon_regs *mode,
 			       int reg_only);
 
diff -Nru a/drivers/video/backlight/backlight.c b/drivers/video/backlight/backlight.c
--- a/drivers/video/backlight/backlight.c	2005-03-11 12:51:40 -08:00
+++ b/drivers/video/backlight/backlight.c	2005-03-11 12:51:40 -08:00
@@ -111,7 +111,7 @@
 	kfree(bd);
 }
 
-struct class backlight_class = {
+static struct class backlight_class = {
 	.name = "backlight",
 	.release = backlight_class_release,
 };
diff -Nru a/drivers/video/backlight/corgi_bl.c b/drivers/video/backlight/corgi_bl.c
--- a/drivers/video/backlight/corgi_bl.c	2005-03-11 12:51:42 -08:00
+++ b/drivers/video/backlight/corgi_bl.c	2005-03-11 12:51:42 -08:00
@@ -52,9 +52,9 @@
 	corgi_ssp_blduty_set(intensity & 0x1f);
 	/* Bit 5 is via SCOOP */
 	if (intensity & 0x0020)
-		set_scoop_gpio(CORGI_SCP_BACKLIGHT_CONT);
+		set_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_BACKLIGHT_CONT);
 	else
-		reset_scoop_gpio(CORGI_SCP_BACKLIGHT_CONT);
+		reset_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_BACKLIGHT_CONT);
 	spin_unlock_irqrestore(&bl_lock, flags);
 }
 
diff -Nru a/drivers/video/backlight/lcd.c b/drivers/video/backlight/lcd.c
--- a/drivers/video/backlight/lcd.c	2005-03-11 12:51:51 -08:00
+++ b/drivers/video/backlight/lcd.c	2005-03-11 12:51:51 -08:00
@@ -111,7 +111,7 @@
 	kfree(ld);
 }
 
-struct class lcd_class = {
+static struct class lcd_class = {
 	.name = "lcd",
 	.release = lcd_class_release,
 };
diff -Nru a/drivers/video/cfbcopyarea.c b/drivers/video/cfbcopyarea.c
--- a/drivers/video/cfbcopyarea.c	2005-03-11 12:51:51 -08:00
+++ b/drivers/video/cfbcopyarea.c	2005-03-11 12:51:51 -08:00
@@ -1,25 +1,29 @@
 /*
  *  Generic function for frame buffer with packed pixels of any depth.
  *
- *      Copyright (C)  June 1999 James Simmons
+ *      Copyright (C)  1999-2005 James Simmons <jsimmons@www.infradead.org>
  *
  *  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.
  *
  * NOTES:
- * 
- *  This is for cfb packed pixels. Iplan and such are incorporated in the 
+ *
+ *  This is for cfb packed pixels. Iplan and such are incorporated in the
  *  drivers that need them.
- * 
+ *
  *  FIXME
- *  The code for 24 bit is horrible. It copies byte by byte size instead of 
- *  longs like the other sizes. Needs to be optimized. 
  *
- *  Also need to add code to deal with cards endians that are different than 
+ *  Also need to add code to deal with cards endians that are different than
  *  the native cpu endians. I also need to deal with MSB position in the word.
- *  
+ *
+ *  The two functions or copying forward and backward could be split up like
+ *  the ones for filling, i.e. in aligned and unaligned versions. This would
+ *  help moving some redundant computations and branches out of the loop, too.
  */
+
+
+
 #include <linux/config.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
@@ -29,58 +33,61 @@
 #include <asm/types.h>
 #include <asm/io.h>
 
-#define LONG_MASK  (BITS_PER_LONG - 1)
-
 #if BITS_PER_LONG == 32
-#define FB_WRITEL fb_writel
-#define FB_READL  fb_readl
-#define SHIFT_PER_LONG 5
-#define BYTES_PER_LONG 4
+#  define FB_WRITEL fb_writel
+#  define FB_READL  fb_readl
 #else
-#define FB_WRITEL fb_writeq
-#define FB_READL  fb_readq
-#define SHIFT_PER_LONG 6
-#define BYTES_PER_LONG 8
+#  define FB_WRITEL fb_writeq
+#  define FB_READL  fb_readq
 #endif
 
-static void bitcpy(unsigned long __iomem *dst, int dst_idx,
-		   const unsigned long __iomem *src, int src_idx,
-		   unsigned long n)
+    /*
+     *  Compose two values, using a bitmask as decision value
+     *  This is equivalent to (a & mask) | (b & ~mask)
+     */
+
+static inline unsigned long
+comp(unsigned long a, unsigned long b, unsigned long mask)
+{
+    return ((a ^ b) & mask) ^ b;
+}
+
+    /*
+     *  Generic bitwise copy algorithm
+     */
+
+static void
+bitcpy(unsigned long __iomem *dst, int dst_idx, const unsigned long __iomem *src,
+	int src_idx, int bits, unsigned n)
 {
 	unsigned long first, last;
-	int shift = dst_idx-src_idx, left, right;
-	unsigned long d0, d1;
-	int m;
-	
-	if (!n)
-		return;
-	
-	shift = dst_idx-src_idx;
+	int const shift = dst_idx-src_idx;
+	int left, right;
+
 	first = ~0UL >> dst_idx;
-	last = ~(~0UL >> ((dst_idx+n) % BITS_PER_LONG));
-	
+	last = ~(~0UL >> ((dst_idx+n) % bits));
+
 	if (!shift) {
 		// Same alignment for source and dest
-		
-		if (dst_idx+n <= BITS_PER_LONG) {
+
+		if (dst_idx+n <= bits) {
 			// Single word
 			if (last)
 				first &= last;
-			FB_WRITEL((FB_READL(src) & first) | (FB_READL(dst) & ~first), dst);
+			FB_WRITEL( comp( FB_READL(src), FB_READL(dst), first), dst);
 		} else {
 			// Multiple destination words
+
 			// Leading bits
-			if (first) {
-				
-				FB_WRITEL((FB_READL(src) & first) | 
-					  (FB_READL(dst) & ~first), dst);
+			if (first != ~0UL) {
+				FB_WRITEL( comp( FB_READL(src), FB_READL(dst), first), dst);
 				dst++;
 				src++;
-				n -= BITS_PER_LONG-dst_idx;
+				n -= bits - dst_idx;
 			}
-			
+
 			// Main chunk
-			n /= BITS_PER_LONG;
+			n /= bits;
 			while (n >= 8) {
 				FB_WRITEL(FB_READL(src++), dst++);
 				FB_WRITEL(FB_READL(src++), dst++);
@@ -94,58 +101,61 @@
 			}
 			while (n--)
 				FB_WRITEL(FB_READL(src++), dst++);
+
 			// Trailing bits
 			if (last)
-				FB_WRITEL((FB_READL(src) & last) | (FB_READL(dst) & ~last), dst);
+				FB_WRITEL( comp( FB_READL(src), FB_READL(dst), last), dst);
 		}
 	} else {
+		unsigned long d0, d1;
+		int m;
 		// Different alignment for source and dest
-		
-		right = shift & (BITS_PER_LONG-1);
-		left = -shift & (BITS_PER_LONG-1);
-		
-		if (dst_idx+n <= BITS_PER_LONG) {
+
+		right = shift & (bits - 1);
+		left = -shift & (bits - 1);
+
+		if (dst_idx+n <= bits) {
 			// Single destination word
 			if (last)
 				first &= last;
 			if (shift > 0) {
 				// Single source word
-				FB_WRITEL(((FB_READL(src) >> right) & first) | 
-					  (FB_READL(dst) & ~first), dst);
-			} else if (src_idx+n <= BITS_PER_LONG) {
+				FB_WRITEL( comp( FB_READL(src) >> right, FB_READL(dst), first), dst);
+			} else if (src_idx+n <= bits) {
 				// Single source word
-				FB_WRITEL(((FB_READL(src) << left) & first) | 
-					  (FB_READL(dst) & ~first), dst);
+				FB_WRITEL( comp(FB_READL(src) << left, FB_READL(dst), first), dst);
 			} else {
 				// 2 source words
 				d0 = FB_READL(src++);
 				d1 = FB_READL(src);
-				FB_WRITEL(((d0<<left | d1>>right) & first) | 
-					  (FB_READL(dst) & ~first), dst);
+				FB_WRITEL( comp(d0<<left | d1>>right, FB_READL(dst), first), dst);
 			}
 		} else {
 			// Multiple destination words
+			/** We must always remember the last value read, because in case
+			SRC and DST overlap bitwise (e.g. when moving just one pixel in
+			1bpp), we always collect one full long for DST and that might
+			overlap with the current long from SRC. We store this value in
+			'd0'. */
 			d0 = FB_READL(src++);
 			// Leading bits
 			if (shift > 0) {
 				// Single source word
-				FB_WRITEL(((d0 >> right) & first) | 
-					  (FB_READL(dst) & ~first), dst);
+				FB_WRITEL( comp(d0 >> right, FB_READL(dst), first), dst);
 				dst++;
-				n -= BITS_PER_LONG-dst_idx;
+				n -= bits - dst_idx;
 			} else {
 				// 2 source words
 				d1 = FB_READL(src++);
-				FB_WRITEL(((d0<<left | d1>>right) & first) | 
-					  (FB_READL(dst) & ~first), dst);
+				FB_WRITEL( comp(d0<<left | d1>>right, FB_READL(dst), first), dst);
 				d0 = d1;
 				dst++;
-				n -= BITS_PER_LONG-dst_idx;
+				n -= bits - dst_idx;
 			}
-			
+
 			// Main chunk
-			m = n % BITS_PER_LONG;
-			n /= BITS_PER_LONG;
+			m = n % bits;
+			n /= bits;
 			while (n >= 4) {
 				d1 = FB_READL(src++);
 				FB_WRITEL(d0 << left | d1 >> right, dst++);
@@ -166,72 +176,70 @@
 				FB_WRITEL(d0 << left | d1 >> right, dst++);
 				d0 = d1;
 			}
-			
+
 			// Trailing bits
 			if (last) {
 				if (m <= right) {
 					// Single source word
-					FB_WRITEL(((d0 << left) & last) | 
-						  (FB_READL(dst) & ~last), 
-						  dst);
+					FB_WRITEL( comp(d0 << left, FB_READL(dst), last), dst);
 				} else {
 					// 2 source words
 					d1 = FB_READL(src);
-					FB_WRITEL(((d0<<left | d1>>right) & 
-						   last) | (FB_READL(dst) & 
-							    ~last), dst);
+					FB_WRITEL( comp(d0<<left | d1>>right, FB_READL(dst), last), dst);
 				}
 			}
 		}
 	}
 }
 
-static void bitcpy_rev(unsigned long __iomem *dst, int dst_idx,
-		       const unsigned long __iomem *src, int src_idx, unsigned long n)
+    /*
+     *  Generic bitwise copy algorithm, operating backward
+     */
+
+static void
+bitcpy_rev(unsigned long __iomem *dst, int dst_idx, const unsigned long __iomem *src,
+		int src_idx, int bits, unsigned n)
 {
 	unsigned long first, last;
-	int shift = dst_idx-src_idx, left, right;
-	unsigned long d0, d1;
-	int m;
-	
-	if (!n)
-		return;
-	
-	dst += (n-1)/BITS_PER_LONG;
-	src += (n-1)/BITS_PER_LONG;
-	if ((n-1) % BITS_PER_LONG) {
-		dst_idx += (n-1) % BITS_PER_LONG;
-		dst += dst_idx >> SHIFT_PER_LONG;
-		dst_idx &= BITS_PER_LONG-1;
-		src_idx += (n-1) % BITS_PER_LONG;
-		src += src_idx >> SHIFT_PER_LONG;
-		src_idx &= BITS_PER_LONG-1;
+	int shift;
+
+	dst += (n-1)/bits;
+	src += (n-1)/bits;
+	if ((n-1) % bits) {
+		dst_idx += (n-1) % bits;
+		dst += dst_idx >> (ffs(bits) - 1);
+		dst_idx &= bits - 1;
+		src_idx += (n-1) % bits;
+		src += src_idx >> (ffs(bits) - 1);
+		src_idx &= bits - 1;
 	}
-	
+
 	shift = dst_idx-src_idx;
-	first = ~0UL << (BITS_PER_LONG-1-dst_idx);
-	last = ~(~0UL << (BITS_PER_LONG-1-((dst_idx-n) % BITS_PER_LONG)));
-	
+
+	first = ~0UL << (bits - 1 - dst_idx);
+	last = ~(~0UL << (bits - 1 - ((dst_idx-n) % bits)));
+
 	if (!shift) {
 		// Same alignment for source and dest
-		
+
 		if ((unsigned long)dst_idx+1 >= n) {
 			// Single word
 			if (last)
 				first &= last;
-			FB_WRITEL((FB_READL(src) & first) | (FB_READL(dst) & ~first), dst); 
+			FB_WRITEL( comp( FB_READL(src), FB_READL(dst), first), dst);
 		} else {
 			// Multiple destination words
+
 			// Leading bits
-			if (first) {
-				FB_WRITEL((FB_READL(src) & first) | (FB_READL(dst) & ~first), dst); 
+			if (first != ~0UL) {
+				FB_WRITEL( comp( FB_READL(src), FB_READL(dst), first), dst);
 				dst--;
 				src--;
 				n -= dst_idx+1;
 			}
-			
+
 			// Main chunk
-			n /= BITS_PER_LONG;
+			n /= bits;
 			while (n >= 8) {
 				FB_WRITEL(FB_READL(src--), dst--);
 				FB_WRITEL(FB_READL(src--), dst--);
@@ -245,59 +253,58 @@
 			}
 			while (n--)
 				FB_WRITEL(FB_READL(src--), dst--);
-			
+
 			// Trailing bits
 			if (last)
-				FB_WRITEL((FB_READL(src) & last) | (FB_READL(dst) & ~last), dst);
+				FB_WRITEL( comp( FB_READL(src), FB_READL(dst), last), dst);
 		}
 	} else {
 		// Different alignment for source and dest
-		
-		right = shift & (BITS_PER_LONG-1);
-		left = -shift & (BITS_PER_LONG-1);
-		
+
+		int const left = -shift & (bits-1);
+		int const right = shift & (bits-1);
+
 		if ((unsigned long)dst_idx+1 >= n) {
 			// Single destination word
 			if (last)
 				first &= last;
 			if (shift < 0) {
 				// Single source word
-				FB_WRITEL((FB_READL(src) << left & first) | 
-					  (FB_READL(dst) & ~first), dst);
+				FB_WRITEL( comp( FB_READL(src)<<left, FB_READL(dst), first), dst);
 			} else if (1+(unsigned long)src_idx >= n) {
 				// Single source word
-				FB_WRITEL(((FB_READL(src) >> right) & first) | 
-					  (FB_READL(dst) & ~first), dst);
+				FB_WRITEL( comp( FB_READL(src)>>right, FB_READL(dst), first), dst);
 			} else {
 				// 2 source words
-				d0 = FB_READL(src--);
-				d1 = FB_READL(src);
-				FB_WRITEL(((d0>>right | d1<<left) & first) | 
-					  (FB_READL(dst) & ~first), dst);
+				FB_WRITEL( comp( (FB_READL(src)>>right | FB_READL(src-1)<<left), FB_READL(dst), first), dst);
 			}
 		} else {
 			// Multiple destination words
+			/** We must always remember the last value read, because in case
+			SRC and DST overlap bitwise (e.g. when moving just one pixel in
+			1bpp), we always collect one full long for DST and that might
+			overlap with the current long from SRC. We store this value in
+			'd0'. */
+			unsigned long d0, d1;
+			int m;
+
 			d0 = FB_READL(src--);
 			// Leading bits
 			if (shift < 0) {
 				// Single source word
-				FB_WRITEL(((d0 << left) & first) | 
-					  (FB_READL(dst) & ~first), dst);
-				dst--;
-				n -= dst_idx+1;
+				FB_WRITEL( comp( (d0 << left), FB_READL(dst), first), dst);
 			} else {
 				// 2 source words
 				d1 = FB_READL(src--);
-				FB_WRITEL(((d0>>right | d1<<left) & first) | 
-					  (FB_READL(dst) & ~first), dst);
+				FB_WRITEL( comp( (d0>>right | d1<<left), FB_READL(dst), first), dst);
 				d0 = d1;
-				dst--;
-				n -= dst_idx+1;
 			}
-			
+			dst--;
+			n -= dst_idx+1;
+
 			// Main chunk
-			m = n % BITS_PER_LONG;
-			n /= BITS_PER_LONG;
+			m = n % bits;
+			n /= bits;
 			while (n >= 4) {
 				d1 = FB_READL(src--);
 				FB_WRITEL(d0 >> right | d1 << left, dst--);
@@ -318,20 +325,16 @@
 				FB_WRITEL(d0 >> right | d1 << left, dst--);
 				d0 = d1;
 			}
-			
+
 			// Trailing bits
 			if (last) {
 				if (m <= left) {
 					// Single source word
-					FB_WRITEL(((d0 >> right) & last) | 
-						  (FB_READL(dst) & ~last), 
-						  dst);
+					FB_WRITEL( comp(d0 >> right, FB_READL(dst), last), dst);
 				} else {
 					// 2 source words
 					d1 = FB_READL(src);
-					FB_WRITEL(((d0>>right | d1<<left) & 
-						   last) | (FB_READL(dst) & 
-							    ~last), dst);
+					FB_WRITEL( comp(d0>>right | d1<<left, FB_READL(dst), last), dst);
 				}
 			}
 		}
@@ -342,30 +345,27 @@
 {
 	u32 dx = area->dx, dy = area->dy, sx = area->sx, sy = area->sy;
 	u32 height = area->height, width = area->width;
-	int x2, y2, old_dx, old_dy, vxres, vyres;
-	unsigned long next_line = p->fix.line_length;
-	int dst_idx = 0, src_idx = 0, rev_copy = 0;
+	unsigned long const bits_per_line = p->fix.line_length*8u;
 	unsigned long __iomem *dst = NULL, *src = NULL;
+	int bits = BITS_PER_LONG, bytes = bits >> 3;
+	int dst_idx = 0, src_idx = 0, rev_copy = 0;
+	int x2, y2, vxres, vyres;
 
 	if (p->state != FBINFO_STATE_RUNNING)
 		return;
 
 	/* We want rotation but lack hardware to do it for us. */
 	if (!p->fbops->fb_rotate && p->var.rotate) {
-	}	
-	
+	}
+
 	vxres = p->var.xres_virtual;
 	vyres = p->var.yres_virtual;
 
-	if (area->dx > vxres || area->sx > vxres || 
+	if (area->dx > vxres || area->sx > vxres ||
 	    area->dy > vyres || area->sy > vyres)
 		return;
 
-	/* clip the destination */
-	old_dx = area->dx;
-	old_dy = area->dy;
-
-	/*
+	/* clip the destination
 	 * We could use hardware clipping but on many cards you get around
 	 * hardware clipping by writing to framebuffer directly.
 	 */
@@ -378,53 +378,58 @@
 	width = x2 - dx;
 	height = y2 - dy;
 
+	if ((width==0) ||(height==0))
+		return;
+
 	/* update sx1,sy1 */
-	sx += (dx - old_dx);
-	sy += (dy - old_dy);
+	sx += (dx - area->dx);
+	sy += (dy - area->dy);
 
 	/* the source must be completely inside the virtual screen */
-	if (sx < 0 || sy < 0 ||
-	    (sx + width) > vxres ||
-	    (sy + height) > vyres)
+	if (sx < 0 || sy < 0 || (sx + width) > vxres || (sy + height) > vyres)
 		return;
 
-	if ((dy == sy && dx > sx) ||	
-	    (dy > sy)) { 
+	/* if the beginning of the target area might overlap with the end of
+	the source area, be have to copy the area reverse. */
+	if ((dy == sy && dx > sx) || (dy > sy)) {
 		dy += height;
 		sy += height;
 		rev_copy = 1;
 	}
 
-	dst = src = (unsigned long __iomem *)((unsigned long)p->screen_base & 
-				      ~(BYTES_PER_LONG-1));
-	dst_idx = src_idx = (unsigned long)p->screen_base & (BYTES_PER_LONG-1);
-	dst_idx += dy*next_line*8 + dx*p->var.bits_per_pixel;
-	src_idx += sy*next_line*8 + sx*p->var.bits_per_pixel;
-	
+	// split the base of the framebuffer into a long-aligned address and the
+	// index of the first bit
+	dst = src = (unsigned long __iomem *)((unsigned long)p->screen_base & ~(bytes-1));
+	dst_idx = src_idx = 8*((unsigned long)p->screen_base & (bytes-1));
+	// add offset of source and target area
+	dst_idx += dy*bits_per_line + dx*p->var.bits_per_pixel;
+	src_idx += sy*bits_per_line + sx*p->var.bits_per_pixel;
+
 	if (p->fbops->fb_sync)
 		p->fbops->fb_sync(p);
+
 	if (rev_copy) {
 		while (height--) {
-			dst_idx -= next_line*8;
-			src_idx -= next_line*8;
-			dst += dst_idx >> SHIFT_PER_LONG;
-			dst_idx &= (BYTES_PER_LONG-1);
-			src += src_idx >> SHIFT_PER_LONG;
-			src_idx &= (BYTES_PER_LONG-1);
-			bitcpy_rev(dst, dst_idx, src, src_idx, 
-				   width*p->var.bits_per_pixel);
-		}	
+			dst_idx -= bits_per_line;
+			src_idx -= bits_per_line;
+			dst += dst_idx >> (ffs(bits) - 1);
+			dst_idx &= (bytes - 1);
+			src += src_idx >> (ffs(bits) - 1);
+			src_idx &= (bytes - 1);
+			bitcpy_rev(dst, dst_idx, src, src_idx, bits,
+				width*p->var.bits_per_pixel);
+		}
 	} else {
 		while (height--) {
-			dst += dst_idx >> SHIFT_PER_LONG;
-			dst_idx &= (BYTES_PER_LONG-1);
-			src += src_idx >> SHIFT_PER_LONG;
-			src_idx &= (BYTES_PER_LONG-1);
-			bitcpy(dst, dst_idx, src, src_idx, 
-			       width*p->var.bits_per_pixel);
-			dst_idx += next_line*8;
-			src_idx += next_line*8;
-		}	
+			dst += dst_idx >> (ffs(bits) - 1);
+			dst_idx &= (bytes - 1);
+			src += src_idx >> (ffs(bits) - 1);
+			src_idx &= (bytes - 1);
+			bitcpy(dst, dst_idx, src, src_idx, bits,
+				width*p->var.bits_per_pixel);
+			dst_idx += bits_per_line;
+			src_idx += bits_per_line;
+		}
 	}
 }
 
diff -Nru a/drivers/video/cfbfillrect.c b/drivers/video/cfbfillrect.c
--- a/drivers/video/cfbfillrect.c	2005-03-11 12:51:46 -08:00
+++ b/drivers/video/cfbfillrect.c	2005-03-11 12:51:46 -08:00
@@ -1,7 +1,7 @@
 /*
- *  Generic fillrect for frame buffers with packed pixels of any depth. 
+ *  Generic fillrect for frame buffers with packed pixels of any depth.
  *
- *      Copyright (C)  2000 James Simmons (jsimmons@linux-fbdev.org) 
+ *      Copyright (C)  2000 James Simmons (jsimmons@linux-fbdev.org)
  *
  *  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
@@ -9,8 +9,8 @@
  *
  * NOTES:
  *
- *  The code for depths like 24 that don't have integer number of pixels per 
- *  long is broken and needs to be fixed. For now I turned these types of 
+ *  The code for depths like 24 that don't have integer number of pixels per
+ *  long is broken and needs to be fixed. For now I turned these types of
  *  mode off.
  *
  *  Also need to add code to deal with cards endians that are different than
@@ -24,149 +24,129 @@
 #include <asm/types.h>
 
 #if BITS_PER_LONG == 32
-#define FB_WRITEL fb_writel
-#define FB_READL  fb_readl
-#define BYTES_PER_LONG 4
-#define SHIFT_PER_LONG 5
+#  define FB_WRITEL fb_writel
+#  define FB_READL  fb_readl
 #else
-#define FB_WRITEL fb_writeq
-#define FB_READL  fb_readq
-#define BYTES_PER_LONG 8
-#define SHIFT_PER_LONG 6
+#  define FB_WRITEL fb_writeq
+#  define FB_READL  fb_readq
 #endif
 
-#define EXP1(x)		0xffffffffU*x
-#define EXP2(x)		0x55555555U*x
-#define EXP4(x)		0x11111111U*0x ## x
-
-typedef u32 pixel_t;
-
-static const u32 bpp1tab[2] = {
-    EXP1(0), EXP1(1)
-};
-
-static const u32 bpp2tab[4] = {
-    EXP2(0), EXP2(1), EXP2(2), EXP2(3)
-};
-
-static const u32 bpp4tab[16] = {
-    EXP4(0), EXP4(1), EXP4(2), EXP4(3), EXP4(4), EXP4(5), EXP4(6), EXP4(7),
-    EXP4(8), EXP4(9), EXP4(a), EXP4(b), EXP4(c), EXP4(d), EXP4(e), EXP4(f)
-};
-
     /*
      *  Compose two values, using a bitmask as decision value
      *  This is equivalent to (a & mask) | (b & ~mask)
      */
 
-static inline unsigned long comp(unsigned long a, unsigned long b,
-				 unsigned long mask)
+static inline unsigned long
+comp(unsigned long a, unsigned long b, unsigned long mask)
 {
     return ((a ^ b) & mask) ^ b;
 }
 
-static inline u32 pixel_to_pat32(const struct fb_info *p, pixel_t pixel)
-{
-    u32 pat = pixel;
+    /*
+     *  Create a pattern with the given pixel's color
+     */
 
-    switch (p->var.bits_per_pixel) {
+#if BITS_PER_LONG == 64
+static inline unsigned long
+pixel_to_pat( u32 bpp, u32 pixel)
+{
+	switch (bpp) {
 	case 1:
-	    pat = bpp1tab[pat];
-	    break;
-
+		return 0xfffffffffffffffful*pixel;
 	case 2:
-	    pat = bpp2tab[pat];
-	    break;
-
+		return 0x5555555555555555ul*pixel;
 	case 4:
-	    pat = bpp4tab[pat];
-	    break;
-
+		return 0x1111111111111111ul*pixel;
 	case 8:
-	    pat |= pat << 8;
-	    // Fall through
+		return 0x0101010101010101ul*pixel;
+	case 12:
+		return 0x0001001001001001ul*pixel;
 	case 16:
-	    pat |= pat << 16;
-	    // Fall through
+		return 0x0001000100010001ul*pixel;
+	case 24:
+		return 0x0000000001000001ul*pixel;
 	case 32:
-	    break;
+		return 0x0000000100000001ul*pixel;
+	default:
+		panic("pixel_to_pat(): unsupported pixelformat\n");
     }
-    return pat;
 }
-
-    /*
-     *  Expand a pixel value to a generic 32/64-bit pattern and rotate it to
-     *  the correct start position
-     */
-
-static inline unsigned long pixel_to_pat(const struct fb_info *p, 
-					 pixel_t pixel, int left)
+#else
+static inline unsigned long
+pixel_to_pat( u32 bpp, u32 pixel)
 {
-    unsigned long pat = pixel;
-    u32 bpp = p->var.bits_per_pixel;
-    int i;
-
-    /* expand pixel value */
-    for (i = bpp; i < BITS_PER_LONG; i *= 2)
-	pat |= pat << i;
-
-    /* rotate pattern to correct start position */
-    pat = pat << left | pat >> (bpp-left);
-    return pat;
+	switch (bpp) {
+	case 1:
+		return 0xfffffffful*pixel;
+	case 2:
+		return 0x55555555ul*pixel;
+	case 4:
+		return 0x11111111ul*pixel;
+	case 8:
+		return 0x01010101ul*pixel;
+	case 12:
+		return 0x00001001ul*pixel;
+	case 16:
+		return 0x00010001ul*pixel;
+	case 24:
+		return 0x00000001ul*pixel;
+	case 32:
+		return 0x00000001ul*pixel;
+	default:
+		panic("pixel_to_pat(): unsupported pixelformat\n");
+    }
 }
+#endif
 
     /*
-     *  Unaligned 32-bit pattern fill using 32/64-bit memory accesses
+     *  Aligned pattern fill using 32/64-bit memory accesses
      */
 
-void bitfill32(unsigned long __iomem *dst, int dst_idx, u32 pat, u32 n)
+static void
+bitfill_aligned(unsigned long __iomem *dst, int dst_idx, unsigned long pat, unsigned n, int bits)
 {
-	unsigned long val = pat;
 	unsigned long first, last;
-	
+
 	if (!n)
 		return;
-	
-#if BITS_PER_LONG == 64
-	val |= val << 32;
-#endif
-	
+
 	first = ~0UL >> dst_idx;
-	last = ~(~0UL >> ((dst_idx+n) % BITS_PER_LONG));
-	
-	if (dst_idx+n <= BITS_PER_LONG) {
+	last = ~(~0UL >> ((dst_idx+n) % bits));
+
+	if (dst_idx+n <= bits) {
 		// Single word
 		if (last)
 			first &= last;
-		FB_WRITEL(comp(val, FB_READL(dst), first), dst);
+		FB_WRITEL(comp(pat, FB_READL(dst), first), dst);
 	} else {
 		// Multiple destination words
+
 		// Leading bits
-		if (first) {
-			FB_WRITEL(comp(val, FB_READL(dst), first), dst);
+		if (first!= ~0UL) {
+			FB_WRITEL(comp(pat, FB_READL(dst), first), dst);
 			dst++;
-			n -= BITS_PER_LONG-dst_idx;
+			n -= bits - dst_idx;
 		}
-		
+
 		// Main chunk
-		n /= BITS_PER_LONG;
+		n /= bits;
 		while (n >= 8) {
-			FB_WRITEL(val, dst++);
-			FB_WRITEL(val, dst++);
-			FB_WRITEL(val, dst++);
-			FB_WRITEL(val, dst++);
-			FB_WRITEL(val, dst++);
-			FB_WRITEL(val, dst++);
-			FB_WRITEL(val, dst++);
-			FB_WRITEL(val, dst++);
+			FB_WRITEL(pat, dst++);
+			FB_WRITEL(pat, dst++);
+			FB_WRITEL(pat, dst++);
+			FB_WRITEL(pat, dst++);
+			FB_WRITEL(pat, dst++);
+			FB_WRITEL(pat, dst++);
+			FB_WRITEL(pat, dst++);
+			FB_WRITEL(pat, dst++);
 			n -= 8;
 		}
 		while (n--)
-			FB_WRITEL(val, dst++);
-		
+			FB_WRITEL(pat, dst++);
+
 		// Trailing bits
 		if (last)
-			FB_WRITEL(comp(val, FB_READL(dst), first), dst);
+			FB_WRITEL(comp(pat, FB_READL(dst), last), dst);
 	}
 }
 
@@ -178,18 +158,19 @@
      *  used for the next 32/64-bit word
      */
 
-void bitfill(unsigned long __iomem *dst, int dst_idx, unsigned long pat, int left,
-	     int right, u32 n)
+static void
+bitfill_unaligned(unsigned long __iomem *dst, int dst_idx, unsigned long pat,
+			int left, int right, unsigned n, int bits)
 {
 	unsigned long first, last;
 
 	if (!n)
 		return;
-	
+
 	first = ~0UL >> dst_idx;
-	last = ~(~0UL >> ((dst_idx+n) % BITS_PER_LONG));
-	
-	if (dst_idx+n <= BITS_PER_LONG) {
+	last = ~(~0UL >> ((dst_idx+n) % bits));
+
+	if (dst_idx+n <= bits) {
 		// Single word
 		if (last)
 			first &= last;
@@ -201,11 +182,11 @@
 			FB_WRITEL(comp(pat, FB_READL(dst), first), dst);
 			dst++;
 			pat = pat << left | pat >> right;
-			n -= BITS_PER_LONG-dst_idx;
+			n -= bits - dst_idx;
 		}
-		
+
 		// Main chunk
-		n /= BITS_PER_LONG;
+		n /= bits;
 		while (n >= 4) {
 			FB_WRITEL(pat, dst++);
 			pat = pat << left | pat >> right;
@@ -221,29 +202,29 @@
 			FB_WRITEL(pat, dst++);
 			pat = pat << left | pat >> right;
 		}
-		
+
 		// Trailing bits
 		if (last)
 			FB_WRITEL(comp(pat, FB_READL(dst), first), dst);
 	}
 }
 
-void bitfill32_rev(unsigned long __iomem *dst, int dst_idx, u32 pat, u32 n)
+    /*
+     *  Aligned pattern invert using 32/64-bit memory accesses
+     */
+static void
+bitfill_aligned_rev(unsigned long __iomem *dst, int dst_idx, unsigned long pat, unsigned n, int bits)
 {
 	unsigned long val = pat, dat;
 	unsigned long first, last;
-	
+
 	if (!n)
 		return;
-	
-#if BITS_PER_LONG == 64
-	val |= val << 32;
-#endif
-	
+
 	first = ~0UL >> dst_idx;
-	last = ~(~0UL >> ((dst_idx+n) % BITS_PER_LONG));
-	
-	if (dst_idx+n <= BITS_PER_LONG) {
+	last = ~(~0UL >> ((dst_idx+n) % bits));
+
+	if (dst_idx+n <= bits) {
 		// Single word
 		if (last)
 			first &= last;
@@ -252,15 +233,15 @@
 	} else {
 		// Multiple destination words
 		// Leading bits
-		if (first) {
+		if (first!=0UL) {
 			dat = FB_READL(dst);
 			FB_WRITEL(comp(dat ^ val, dat, first), dst);
 			dst++;
-			n -= BITS_PER_LONG-dst_idx;
+			n -= bits - dst_idx;
 		}
-		
+
 		// Main chunk
-		n /= BITS_PER_LONG;
+		n /= bits;
 		while (n >= 8) {
 			FB_WRITEL(FB_READL(dst) ^ val, dst);
 			dst++;
@@ -283,35 +264,36 @@
 		while (n--) {
 			FB_WRITEL(FB_READL(dst) ^ val, dst);
 			dst++;
-		}		
+		}
 		// Trailing bits
 		if (last) {
 			dat = FB_READL(dst);
-			FB_WRITEL(comp(dat ^ val, dat, first), dst);
+			FB_WRITEL(comp(dat ^ val, dat, last), dst);
 		}
 	}
 }
 
 
     /*
-     *  Unaligned generic pattern fill using 32/64-bit memory accesses
+     *  Unaligned generic pattern invert using 32/64-bit memory accesses
      *  The pattern must have been expanded to a full 32/64-bit value
      *  Left/right are the appropriate shifts to convert to the pattern to be
      *  used for the next 32/64-bit word
      */
 
-void bitfill_rev(unsigned long __iomem *dst, int dst_idx, unsigned long pat, int left,
-	     int right, u32 n)
+static void
+bitfill_unaligned_rev(unsigned long __iomem *dst, int dst_idx, unsigned long pat,
+			int left, int right, unsigned n, int bits)
 {
 	unsigned long first, last, dat;
 
 	if (!n)
 		return;
-	
+
 	first = ~0UL >> dst_idx;
-	last = ~(~0UL >> ((dst_idx+n) % BITS_PER_LONG));
-	
-	if (dst_idx+n <= BITS_PER_LONG) {
+	last = ~(~0UL >> ((dst_idx+n) % bits));
+
+	if (dst_idx+n <= bits) {
 		// Single word
 		if (last)
 			first &= last;
@@ -319,17 +301,18 @@
 		FB_WRITEL(comp(dat ^ pat, dat, first), dst);
 	} else {
 		// Multiple destination words
+
 		// Leading bits
-		if (first) {
+		if (first != 0UL) {
 			dat = FB_READL(dst);
 			FB_WRITEL(comp(dat ^ pat, dat, first), dst);
 			dst++;
 			pat = pat << left | pat >> right;
-			n -= BITS_PER_LONG-dst_idx;
+			n -= bits - dst_idx;
 		}
-		
+
 		// Main chunk
-		n /= BITS_PER_LONG;
+		n /= bits;
 		while (n >= 4) {
 			FB_WRITEL(FB_READL(dst) ^ pat, dst);
 			dst++;
@@ -350,20 +333,20 @@
 			dst++;
 			pat = pat << left | pat >> right;
 		}
-		
+
 		// Trailing bits
 		if (last) {
 			dat = FB_READL(dst);
-			FB_WRITEL(comp(dat ^ pat, dat, first), dst);
+			FB_WRITEL(comp(dat ^ pat, dat, last), dst);
 		}
 	}
 }
 
 void cfb_fillrect(struct fb_info *p, const struct fb_fillrect *rect)
 {
+	unsigned long x2, y2, vxres, vyres, height, width, pat, fg;
+	int bits = BITS_PER_LONG, bytes = bits >> 3;
 	u32 bpp = p->var.bits_per_pixel;
-	unsigned long x2, y2, vxres, vyres;
-	unsigned long height, width, fg;
 	unsigned long __iomem *dst;
 	int dst_idx, left;
 
@@ -372,81 +355,91 @@
 
 	/* We want rotation but lack hardware to do it for us. */
 	if (!p->fbops->fb_rotate && p->var.rotate) {
-	}	
-	
+	}
+
 	vxres = p->var.xres_virtual;
 	vyres = p->var.yres_virtual;
 
-	if (!rect->width || !rect->height || 
+	if (!rect->width || !rect->height ||
 	    rect->dx > vxres || rect->dy > vyres)
 		return;
 
 	/* We could use hardware clipping but on many cards you get around
 	 * hardware clipping by writing to framebuffer directly. */
-	
+
 	x2 = rect->dx + rect->width;
 	y2 = rect->dy + rect->height;
 	x2 = x2 < vxres ? x2 : vxres;
 	y2 = y2 < vyres ? y2 : vyres;
 	width = x2 - rect->dx;
 	height = y2 - rect->dy;
-	
+
 	if (p->fix.visual == FB_VISUAL_TRUECOLOR ||
 	    p->fix.visual == FB_VISUAL_DIRECTCOLOR )
 		fg = ((u32 *) (p->pseudo_palette))[rect->color];
 	else
 		fg = rect->color;
-	
-	dst = (unsigned long __iomem *)((unsigned long)p->screen_base & 
-				~(BYTES_PER_LONG-1));
-	dst_idx = ((unsigned long)p->screen_base & (BYTES_PER_LONG-1))*8;
+
+	pat = pixel_to_pat( bpp, fg);
+
+	dst = (unsigned long __iomem *)((unsigned long)p->screen_base & ~(bytes-1));
+	dst_idx = ((unsigned long)p->screen_base & (bytes - 1))*8;
 	dst_idx += rect->dy*p->fix.line_length*8+rect->dx*bpp;
 	/* FIXME For now we support 1-32 bpp only */
-	left = BITS_PER_LONG % bpp;
+	left = bits % bpp;
 	if (p->fbops->fb_sync)
 		p->fbops->fb_sync(p);
 	if (!left) {
-		u32 pat = pixel_to_pat32(p, fg);
-		void (*fill_op32)(unsigned long __iomem *dst, int dst_idx, u32 pat, 
-				  u32 n) = NULL;
-		
+		void (*fill_op32)(unsigned long __iomem *dst, int dst_idx,
+		                  unsigned long pat, unsigned n, int bits) = NULL;
+
 		switch (rect->rop) {
 		case ROP_XOR:
-			fill_op32 = bitfill32_rev;
+			fill_op32 = bitfill_aligned_rev;
 			break;
 		case ROP_COPY:
+			fill_op32 = bitfill_aligned;
+			break;
 		default:
-			fill_op32 = bitfill32;
+			printk( KERN_ERR "cfb_fillrect(): unknown rop, defaulting to ROP_COPY\n");
+			fill_op32 = bitfill_aligned;
 			break;
 		}
 		while (height--) {
-			dst += dst_idx >> SHIFT_PER_LONG;
-			dst_idx &= (BITS_PER_LONG-1);
-			fill_op32(dst, dst_idx, pat, width*bpp);
+			dst += dst_idx >> (ffs(bits) - 1);
+			dst_idx &= (bits - 1);
+			fill_op32(dst, dst_idx, pat, width*bpp, bits);
 			dst_idx += p->fix.line_length*8;
 		}
 	} else {
-		unsigned long pat = pixel_to_pat(p, fg, (left-dst_idx) % bpp);
-		int right = bpp-left;
+		int right;
 		int r;
-		void (*fill_op)(unsigned long __iomem *dst, int dst_idx, 
-				unsigned long pat, int left, int right, 
-				u32 n) = NULL;
-		
+		int rot = (left-dst_idx) % bpp;
+		void (*fill_op)(unsigned long __iomem *dst, int dst_idx,
+		                unsigned long pat, int left, int right,
+		                unsigned n, int bits) = NULL;
+
+		/* rotate pattern to correct start position */
+		pat = pat << rot | pat >> (bpp-rot);
+
+		right = bpp-left;
 		switch (rect->rop) {
 		case ROP_XOR:
-			fill_op = bitfill_rev;
+			fill_op = bitfill_unaligned_rev;
 			break;
 		case ROP_COPY:
+			fill_op = bitfill_unaligned;
+			break;
 		default:
-			fill_op = bitfill;
+			printk( KERN_ERR "cfb_fillrect(): unknown rop, defaulting to ROP_COPY\n");
+			fill_op = bitfill_unaligned;
 			break;
 		}
 		while (height--) {
-			dst += dst_idx >> SHIFT_PER_LONG;
-			dst_idx &= (BITS_PER_LONG-1);
-			fill_op(dst, dst_idx, pat, left, right, 
-				width*bpp);
+			dst += dst_idx >> (ffs(bits) - 1);
+			dst_idx &= (bits - 1);
+			fill_op(dst, dst_idx, pat, left, right,
+				width*bpp, bits);
 			r = (p->fix.line_length*8) % bpp;
 			pat = pat << (bpp-r) | pat >> r;
 			dst_idx += p->fix.line_length*8;
diff -Nru a/drivers/video/console/Makefile b/drivers/video/console/Makefile
--- a/drivers/video/console/Makefile	2005-03-11 12:51:46 -08:00
+++ b/drivers/video/console/Makefile	2005-03-11 12:51:46 -08:00
@@ -25,7 +25,9 @@
 obj-$(CONFIG_VGA_CONSOLE)         += vgacon.o
 obj-$(CONFIG_MDA_CONSOLE)         += mdacon.o
 obj-$(CONFIG_FRAMEBUFFER_CONSOLE) += fbcon.o bitblit.o font.o
-obj-$(CONFIG_FB_TILEBLITTING)     += tileblit.o
+ifeq ($(CONFIG_FB_TILEBLITTING),y)
+obj-$(CONFIG_FRAMEBUFFER_CONSOLE)     += tileblit.o
+endif
 
 obj-$(CONFIG_FB_STI)              += sticore.o
 
diff -Nru a/drivers/video/console/bitblit.c b/drivers/video/console/bitblit.c
--- a/drivers/video/console/bitblit.c	2005-03-11 12:51:52 -08:00
+++ b/drivers/video/console/bitblit.c	2005-03-11 12:51:52 -08:00
@@ -39,7 +39,7 @@
 {
 	int attribute = 0;
 
-	if (fb_get_color_depth(info) == 1) {
+	if (fb_get_color_depth(&info->var) == 1) {
 		if (attr_underline(c))
 			attribute |= FBCON_ATTRIBUTE_UNDERLINE;
 		if (attr_reverse(c))
@@ -236,7 +236,7 @@
 }
 
 static void bit_cursor(struct vc_data *vc, struct fb_info *info,
-		       struct display *p, int mode, int fg, int bg)
+		       struct display *p, int mode, int softback_lines, int fg, int bg)
 {
 	struct fb_cursor cursor;
 	struct fbcon_ops *ops = (struct fbcon_ops *) info->fbcon_par;
@@ -247,6 +247,15 @@
 	char *src;
 
 	cursor.set = 0;
+
+	if (softback_lines) {
+		if (y + softback_lines >= vc->vc_rows) {
+			mode = CM_ERASE;
+			ops->cursor_flash = 0;
+			return;
+		} else
+			y += softback_lines;
+	}
 
  	c = scr_readw((u16 *) vc->vc_pos);
 	attribute = get_attribute(info, c);
diff -Nru a/drivers/video/console/dummycon.c b/drivers/video/console/dummycon.c
--- a/drivers/video/console/dummycon.c	2005-03-11 12:51:51 -08:00
+++ b/drivers/video/console/dummycon.c	2005-03-11 12:51:51 -08:00
@@ -42,7 +42,7 @@
 	vc->vc_cols = DUMMY_COLUMNS;
 	vc->vc_rows = DUMMY_ROWS;
     } else
-	vc_resize(vc->vc_num, DUMMY_COLUMNS, DUMMY_ROWS);
+	vc_resize(vc, DUMMY_COLUMNS, DUMMY_ROWS);
 }
 
 static int dummycon_dummy(void)
diff -Nru a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c
--- a/drivers/video/console/fbcon.c	2005-03-11 12:51:47 -08:00
+++ b/drivers/video/console/fbcon.c	2005-03-11 12:51:47 -08:00
@@ -182,8 +182,10 @@
 static __inline__ void ypan_down(struct vc_data *vc, int count);
 static void fbcon_bmove_rec(struct vc_data *vc, struct display *p, int sy, int sx,
 			    int dy, int dx, int height, int width, u_int y_break);
-static void fbcon_set_disp(struct fb_info *info, struct vc_data *vc);
-static void fbcon_preset_disp(struct fb_info *info, int unit);
+static void fbcon_set_disp(struct fb_info *info, struct fb_var_screeninfo *var,
+			   struct vc_data *vc);
+static void fbcon_preset_disp(struct fb_info *info, struct fb_var_screeninfo *var,
+			      int unit);
 static void fbcon_redraw_move(struct vc_data *vc, struct display *p,
 			      int line, int count, int dy);
 
@@ -203,13 +205,13 @@
 static inline int fbcon_is_inactive(struct vc_data *vc, struct fb_info *info)
 {
 	return (info->state != FBINFO_STATE_RUNNING ||
-		vt_cons[vc->vc_num]->vc_mode != KD_TEXT);
+		vc->vc_mode != KD_TEXT);
 }
 
 static inline int get_color(struct vc_data *vc, struct fb_info *info,
 	      u16 c, int is_fg)
 {
-	int depth = fb_get_color_depth(info);
+	int depth = fb_get_color_depth(&info->var);
 	int color = 0;
 
 	if (console_blanked) {
@@ -277,7 +279,7 @@
 	c = scr_readw((u16 *) vc->vc_pos);
 	mode = (!ops->cursor_flash || ops->cursor_state.enable) ?
 		CM_ERASE : CM_DRAW;
-	ops->cursor(vc, info, p, mode, get_color(vc, info, c, 1),
+	ops->cursor(vc, info, p, mode, softback_lines, get_color(vc, info, c, 1),
 		    get_color(vc, info, c, 0));
 	release_console_sem();
 }
@@ -418,7 +420,7 @@
 	 * remove underline attribute from erase character
 	 * if black and white framebuffer.
 	 */
-	if (fb_get_color_depth(info) == 1)
+	if (fb_get_color_depth(&info->var) == 1)
 		erase &= ~0x400;
 	logo_height = fb_prepare_logo(info);
 	logo_lines = (logo_height + vc->vc_font.height - 1) /
@@ -456,9 +458,9 @@
 		    erase,
 		    vc->vc_size_row * logo_lines);
 
-	if (CON_IS_VISIBLE(vc) && vt_cons[vc->vc_num]->vc_mode == KD_TEXT) {
+	if (CON_IS_VISIBLE(vc) && vc->vc_mode == KD_TEXT) {
 		fbcon_clear_margins(vc, 0);
-		update_screen(vc->vc_num);
+		update_screen(vc);
 	}
 
 	if (save) {
@@ -595,9 +597,9 @@
 		info->fbops->fb_set_par(info);
 
 	if (vc)
-		fbcon_set_disp(info, vc);
+		fbcon_set_disp(info, &info->var, vc);
 	else
-		fbcon_preset_disp(info, unit);
+		fbcon_preset_disp(info, &info->var, unit);
 
 	if (show_logo) {
 		struct vc_data *fg_vc = vc_cons[fg_console].d;
@@ -609,7 +611,7 @@
 				   fg_vc->vc_rows);
 	}
 
-	switch_screen(fg_console);
+	update_screen(vc_cons[fg_console].d);
 }
 
 /**
@@ -802,7 +804,7 @@
 
 	cols = info->var.xres / vc->vc_font.width;
 	rows = info->var.yres / vc->vc_font.height;
-	vc_resize(vc->vc_num, cols, rows);
+	vc_resize(vc, cols, rows);
 
 	DPRINTK("mode:   %s\n", info->fix.id);
 	DPRINTK("visual: %d\n", info->fix.visual);
@@ -890,13 +892,12 @@
 	struct vc_data **default_mode = vc->vc_display_fg;
 	struct vc_data *svc = *default_mode;
 	struct display *t, *p = &fb_display[vc->vc_num];
-	int display_fg = (*default_mode)->vc_num;
 	int logo = 1, new_rows, new_cols, rows, cols, charcnt = 256;
 	int cap = info->flags;
 
 	if (info_idx == -1 || info == NULL)
 	    return;
-	if (vc->vc_num != display_fg || logo_shown == FBCON_LOGO_DONTSHOW ||
+	if (vc != svc || logo_shown == FBCON_LOGO_DONTSHOW ||
 	    (info->fix.type == FB_TYPE_TEXT))
 		logo = 0;
 
@@ -907,7 +908,7 @@
 
 	/* If we are not the first console on this
 	   fb, copy the font from that console */
-	t = &fb_display[display_fg];
+	t = &fb_display[svc->vc_num];
 	if (!vc->vc_font.data) {
 		vc->vc_font.data = p->fontdata = t->fontdata;
 		vc->vc_font.width = (*default_mode)->vc_font.width;
@@ -918,7 +919,7 @@
 	}
 	if (p->userfont)
 		charcnt = FNTCHARCNT(p->fontdata);
-	vc->vc_can_do_color = (fb_get_color_depth(info) != 1);
+	vc->vc_can_do_color = (fb_get_color_depth(&info->var) != 1);
 	vc->vc_complement_mask = vc->vc_can_do_color ? 0x7700 : 0x0800;
 	if (charcnt == 256) {
 		vc->vc_hi_font_mask = 0;
@@ -929,15 +930,15 @@
 	}
 
 	if (!*svc->vc_uni_pagedir_loc)
-		con_set_default_unimap(display_fg);
+		con_set_default_unimap(svc);
 	if (!*vc->vc_uni_pagedir_loc)
-		con_copy_unimap(vc->vc_num, display_fg);
+		con_copy_unimap(vc, svc);
 
 	cols = vc->vc_cols;
 	rows = vc->vc_rows;
 	new_cols = info->var.xres / vc->vc_font.width;
 	new_rows = info->var.yres / vc->vc_font.height;
-	vc_resize(vc->vc_num, new_cols, new_rows);
+	vc_resize(vc, new_cols, new_rows);
 	/*
 	 * We must always set the mode. The mode of the previous console
 	 * driver could be in the same resolution but we are using different
@@ -968,7 +969,7 @@
 	if (logo)
 		fbcon_prepare_logo(vc, info, cols, rows, new_cols, new_rows);
 
-	if (vc->vc_num == display_fg && softback_buf) {
+	if (vc == svc && softback_buf) {
 		int l = fbcon_softback_size / vc->vc_size_row;
 		if (l > 5)
 			softback_end = softback_buf + l * vc->vc_size_row;
@@ -1085,27 +1086,23 @@
 	struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]];
 	struct fbcon_ops *ops = info->fbcon_par;
 	struct display *p = &fb_display[vc->vc_num];
-	int y = real_y(p, vc->vc_y);
+	int y;
  	int c = scr_readw((u16 *) vc->vc_pos);
 
 	if (fbcon_is_inactive(vc, info))
 		return;
 
-	ops->cursor_flash = 1;
+	ops->cursor_flash = (mode == CM_ERASE) ? 0 : 1;
 	if (mode & CM_SOFTBACK) {
 		mode &= ~CM_SOFTBACK;
-		if (softback_lines) {
-			if (y + softback_lines >= vc->vc_rows) {
-				mode = CM_ERASE;
-				ops->cursor_flash = 0;
-			}
-			else
-				y += softback_lines;
-		}
-	} else if (softback_lines)
-		fbcon_set_origin(vc);
+		y = softback_lines;
+	} else {
+		if (softback_lines)
+			fbcon_set_origin(vc);
+		y = 0;
+	}
 
-	ops->cursor(vc, info, p, mode, get_color(vc, info, c, 1),
+	ops->cursor(vc, info, p, mode, y, get_color(vc, info, c, 1),
 		    get_color(vc, info, c, 0));
 	vbl_cursor_cnt = CURSOR_DRAW_DELAY;
 }
@@ -1124,13 +1121,14 @@
 /*
  * If no vc is existent yet, just set struct display
  */
-static void fbcon_preset_disp(struct fb_info *info, int unit)
+static void fbcon_preset_disp(struct fb_info *info, struct fb_var_screeninfo *var,
+			      int unit)
 {
 	struct display *p = &fb_display[unit];
 	struct display *t = &fb_display[fg_console];
 
-	info->var.xoffset = info->var.yoffset = p->yscroll = 0;
-	if (var_to_display(p, &info->var, info))
+	var->xoffset = var->yoffset = p->yscroll = 0;
+	if (var_to_display(p, var, info))
 		return;
 
 	p->fontdata = t->fontdata;
@@ -1139,18 +1137,18 @@
 		REFCOUNT(p->fontdata)++;
 }
 
-static void fbcon_set_disp(struct fb_info *info, struct vc_data *vc)
+static void fbcon_set_disp(struct fb_info *info, struct fb_var_screeninfo *var,
+			   struct vc_data *vc)
 {
 	struct display *p = &fb_display[vc->vc_num], *t;
 	struct vc_data **default_mode = vc->vc_display_fg;
 	struct vc_data *svc = *default_mode;
-	int display_fg = (*default_mode)->vc_num;
 	int rows, cols, charcnt = 256;
 
-	info->var.xoffset = info->var.yoffset = p->yscroll = 0;
-	if (var_to_display(p, &info->var, info))
+	var->xoffset = var->yoffset = p->yscroll = 0;
+	if (var_to_display(p, var, info))
 		return;
-	t = &fb_display[display_fg];
+	t = &fb_display[svc->vc_num];
 	if (!vc->vc_font.data) {
 		vc->vc_font.data = p->fontdata = t->fontdata;
 		vc->vc_font.width = (*default_mode)->vc_font.width;
@@ -1162,7 +1160,7 @@
 	if (p->userfont)
 		charcnt = FNTCHARCNT(p->fontdata);
 
-	vc->vc_can_do_color = (fb_get_color_depth(info) != 1);
+	vc->vc_can_do_color = (fb_get_color_depth(var) != 1);
 	vc->vc_complement_mask = vc->vc_can_do_color ? 0x7700 : 0x0800;
 	if (charcnt == 256) {
 		vc->vc_hi_font_mask = 0;
@@ -1173,15 +1171,15 @@
 	}
 
 	if (!*svc->vc_uni_pagedir_loc)
-		con_set_default_unimap(display_fg);
+		con_set_default_unimap(svc);
 	if (!*vc->vc_uni_pagedir_loc)
-		con_copy_unimap(vc->vc_num, display_fg);
+		con_copy_unimap(vc, svc);
 
-	cols = info->var.xres / vc->vc_font.width;
-	rows = info->var.yres / vc->vc_font.height;
-	vc_resize(vc->vc_num, cols, rows);
+	cols = var->xres / vc->vc_font.width;
+	rows = var->yres / vc->vc_font.height;
+	vc_resize(vc, cols, rows);
 	if (CON_IS_VISIBLE(vc)) {
-		update_screen(vc->vc_num);
+		update_screen(vc);
 		if (softback_buf) {
 			int l = fbcon_softback_size / vc->vc_size_row;
 
@@ -1957,7 +1955,7 @@
 	set_blitting_type(vc, info, p);
 	((struct fbcon_ops *)info->fbcon_par)->cursor_reset = 1;
 
-	vc->vc_can_do_color = (fb_get_color_depth(info) != 1);
+	vc->vc_can_do_color = (fb_get_color_depth(&info->var) != 1);
 	vc->vc_complement_mask = vc->vc_can_do_color ? 0x7700 : 0x0800;
 	updatescrollmode(p, info, vc);
 
@@ -1987,7 +1985,7 @@
 		logo_shown = fg_console;
 		/* This is protected above by initmem_freed */
 		fb_show_logo(info);
-		update_region(fg_console,
+		update_region(vc,
 			      vc->vc_origin + vc->vc_size_row * vc->vc_top,
 			      vc->vc_size_row * (vc->vc_bottom -
 						 vc->vc_top) / 2);
@@ -2048,7 +2046,7 @@
 		}
 
  		if (!blank)
- 			update_screen(vc->vc_num);
+ 			update_screen(vc);
  	}
 
  	return 0;
@@ -2198,7 +2196,7 @@
 	if (resize) {
 		/* reset wrap/pan */
 		info->var.xoffset = info->var.yoffset = p->yscroll = 0;
-		vc_resize(vc->vc_num, info->var.xres / w, info->var.yres / h);
+		vc_resize(vc, info->var.xres / w, info->var.yres / h);
 		if (CON_IS_VISIBLE(vc) && softback_buf) {
 			int l = fbcon_softback_size / vc->vc_size_row;
 			if (l > 5)
@@ -2211,9 +2209,9 @@
 			}
 		}
 	} else if (CON_IS_VISIBLE(vc)
-		   && vt_cons[vc->vc_num]->vc_mode == KD_TEXT) {
+		   && vc->vc_mode == KD_TEXT) {
 		fbcon_clear_margins(vc, 0);
-		update_screen(vc->vc_num);
+		update_screen(vc);
 	}
 
 	if (old_data && (--REFCOUNT(old_data) == 0))
@@ -2328,7 +2326,7 @@
 	if (fbcon_is_inactive(vc, info))
 		return -EINVAL;
 
-	depth = fb_get_color_depth(info);
+	depth = fb_get_color_depth(&info->var);
 	if (depth > 3) {
 		for (i = j = 0; i < 16; i++) {
 			k = table[i];
@@ -2438,7 +2436,7 @@
 	if (softback_top) {
 		if (vc->vc_num != fg_console)
 			return 0;
-		if (vt_cons[vc->vc_num]->vc_mode != KD_TEXT || !lines)
+		if (vc->vc_mode != KD_TEXT || !lines)
 			return 0;
 		if (logo_shown >= 0) {
 			struct vc_data *conp2 = vc_cons[logo_shown].d;
@@ -2464,7 +2462,7 @@
 						    vc->vc_size_row);
 				}
 				softback_in = p;
-				update_region(vc->vc_num, vc->vc_origin,
+				update_region(vc, vc->vc_origin,
 					      logo_lines * vc->vc_cols);
 			}
 			logo_shown = FBCON_LOGO_CANSHOW;
@@ -2545,7 +2543,7 @@
 		return;
 	vc = vc_cons[ops->currcon].d;
 
-	update_screen(vc->vc_num);
+	update_screen(vc);
 }
 
 static void fbcon_modechanged(struct fb_info *info)
@@ -2555,11 +2553,11 @@
 	struct display *p;
 	int rows, cols;
 
-	if (!ops || ops->currcon < 0 || vt_cons[ops->currcon]->vc_mode !=
-	    KD_TEXT || registered_fb[con2fb_map[ops->currcon]] != info)
+	if (!ops || ops->currcon < 0)
 		return;
-
 	vc = vc_cons[ops->currcon].d;
+	if (vc->vc_mode != KD_TEXT || registered_fb[con2fb_map[ops->currcon]] != info)
+		return;
 
 	p = &fb_display[vc->vc_num];
 
@@ -2569,13 +2567,13 @@
 		var_to_display(p, &info->var, info);
 		cols = info->var.xres / vc->vc_font.width;
 		rows = info->var.yres / vc->vc_font.height;
-		vc_resize(vc->vc_num, cols, rows);
+		vc_resize(vc, cols, rows);
 		updatescrollmode(p, info, vc);
 		scrollback_max = 0;
 		scrollback_current = 0;
 		update_var(vc->vc_num, info);
 		fbcon_set_palette(vc, color_table);
-		update_screen(vc->vc_num);
+		update_screen(vc);
 		if (softback_buf) {
 			int l = fbcon_softback_size / vc->vc_size_row;
 			if (l > 5)
@@ -2641,25 +2639,47 @@
 static void fbcon_fb_blanked(struct fb_info *info, int blank)
 {
 	struct fbcon_ops *ops = info->fbcon_par;
-	int valid = 1;
+	struct vc_data *vc;
 
-	if (!ops || ops->currcon < 0 ||
-	    vt_cons[ops->currcon]->vc_mode != KD_TEXT ||
-	    registered_fb[con2fb_map[ops->currcon]] != info)
-		valid = 0;
+	if (!ops || ops->currcon < 0)
+		return;
 
-	if (valid) {
-		struct vc_data *vc;
+	vc = vc_cons[ops->currcon].d;
+	if (vc->vc_mode != KD_TEXT ||
+			registered_fb[con2fb_map[ops->currcon]] != info)
+		return;
 
-		vc = vc_cons[ops->currcon].d;
+	if (CON_IS_VISIBLE(vc)) {
+		if (blank)
+			do_blank_screen(0);
+		else
+			do_unblank_screen(0);
+	}
+	ops->blank_state = blank;
+}
+
+static void fbcon_new_modelist(struct fb_info *info)
+{
+	int i;
+	struct vc_data *vc;
+	struct fb_var_screeninfo var;
+	struct fb_videomode *mode;
+
+	for (i = 0; i < MAX_NR_CONSOLES; i++) {
+		if (registered_fb[con2fb_map[i]] != info)
+			continue;
+		if (!fb_display[i].mode)
+			continue;
+		vc = vc_cons[i].d;
+		display_to_var(&var, &fb_display[i]);
+		mode = fb_find_nearest_mode(&var, &info->modelist);
+		fb_videomode_to_var(&var, mode);
+
+		if (vc)
+			fbcon_set_disp(info, &var, vc);
+		else
+			fbcon_preset_disp(info, &var, i);
 
-		if (CON_IS_VISIBLE(vc)) {
-			if (blank)
-				do_blank_screen(0);
-			else
-				do_unblank_screen(0);
-		}
-		ops->blank_state = blank;
 	}
 }
 
@@ -2700,6 +2720,9 @@
 		break;
 	case FB_EVENT_BLANK:
 		fbcon_fb_blanked(info, *(int *)event->data);
+		break;
+	case FB_EVENT_NEW_MODELIST:
+		fbcon_new_modelist(info);
 		break;
 	}
 
diff -Nru a/drivers/video/console/fbcon.h b/drivers/video/console/fbcon.h
--- a/drivers/video/console/fbcon.h	2005-03-11 12:51:47 -08:00
+++ b/drivers/video/console/fbcon.h	2005-03-11 12:51:47 -08:00
@@ -59,7 +59,7 @@
 	void (*clear_margins)(struct vc_data *vc, struct fb_info *info,
 			      int bottom_only);
 	void (*cursor)(struct vc_data *vc, struct fb_info *info,
-		       struct display *p, int mode, int fg, int bg);
+		       struct display *p, int mode, int softback_lines, int fg, int bg);
 
 	struct timer_list cursor_timer; /* Cursor timer */
 	struct fb_cursor cursor_state;
diff -Nru a/drivers/video/console/mdacon.c b/drivers/video/console/mdacon.c
--- a/drivers/video/console/mdacon.c	2005-03-11 12:51:46 -08:00
+++ b/drivers/video/console/mdacon.c	2005-03-11 12:51:46 -08:00
@@ -351,10 +351,9 @@
 	if (init) {
 		c->vc_cols = mda_num_columns;
 		c->vc_rows = mda_num_lines;
-	} else {
-		vc_resize(c->vc_num, mda_num_columns, mda_num_lines);
-        }
-	
+	} else
+		vc_resize(c, mda_num_columns, mda_num_lines);
+
 	/* make the first MDA console visible */
 
 	if (mda_display_fg == NULL)
diff -Nru a/drivers/video/console/promcon.c b/drivers/video/console/promcon.c
--- a/drivers/video/console/promcon.c	2005-03-11 12:51:47 -08:00
+++ b/drivers/video/console/promcon.c	2005-03-11 12:51:47 -08:00
@@ -155,9 +155,9 @@
 			k++;
 		}
 	set_fs(KERNEL_DS);
-	con_clear_unimap(conp->vc_num, NULL);
-	con_set_unimap(conp->vc_num, k, p);
-	con_protect_unimap(conp->vc_num, 1);
+	con_clear_unimap(conp, NULL);
+	con_set_unimap(conp, k, p);
+	con_protect_unimap(conp, 1);
 	set_fs(old_fs);
 	kfree(p);
 }
@@ -175,7 +175,7 @@
 	p = *conp->vc_uni_pagedir_loc;
 	if (conp->vc_uni_pagedir_loc == &conp->vc_uni_pagedir ||
 	    !--conp->vc_uni_pagedir_loc[1])
-		con_free_unimap(conp->vc_num);
+		con_free_unimap(conp);
 	conp->vc_uni_pagedir_loc = promcon_uni_pagedir;
 	promcon_uni_pagedir[1]++;
 	if (!promcon_uni_pagedir[0] && p) {
@@ -183,7 +183,7 @@
 	}
 	if (!init) {
 		if (conp->vc_cols != pw + 1 || conp->vc_rows != ph + 1)
-			vc_resize(conp->vc_num, pw + 1, ph + 1);
+			vc_resize(conp, pw + 1, ph + 1);
 	}
 }
 
@@ -192,9 +192,9 @@
 {
 	/* When closing the last console, reset video origin */
 	if (!--promcon_uni_pagedir[1])
-		con_free_unimap(conp->vc_num);
+		con_free_unimap(conp);
 	conp->vc_uni_pagedir_loc = &conp->vc_uni_pagedir;
-	con_set_default_unimap(conp->vc_num);
+	con_set_default_unimap(conp);
 }
 
 static int
diff -Nru a/drivers/video/console/sticon.c b/drivers/video/console/sticon.c
--- a/drivers/video/console/sticon.c	2005-03-11 12:51:52 -08:00
+++ b/drivers/video/console/sticon.c	2005-03-11 12:51:52 -08:00
@@ -87,13 +87,12 @@
 
 static void sticon_putc(struct vc_data *conp, int c, int ypos, int xpos)
 {
-    int unit = conp->vc_num;
     int redraw_cursor = 0;
 
     if (vga_is_gfx || console_blanked)
 	    return;
-	    
-    if (vt_cons[unit]->vc_mode != KD_TEXT)
+
+    if (conp->vc_mode != KD_TEXT)
     	    return;
 #if 0
     if ((p->cursor_x == xpos) && (p->cursor_y == ypos)) {
@@ -111,15 +110,14 @@
 static void sticon_putcs(struct vc_data *conp, const unsigned short *s,
 			 int count, int ypos, int xpos)
 {
-    int unit = conp->vc_num;
     int redraw_cursor = 0;
 
     if (vga_is_gfx || console_blanked)
 	    return;
 
-    if (vt_cons[unit]->vc_mode != KD_TEXT)
+    if (conp->vc_mode != KD_TEXT)
     	    return;
-    
+
 #if 0
     if ((p->cursor_y == ypos) && (xpos <= p->cursor_x) &&
 	(p->cursor_x < (xpos + count))) {
@@ -217,7 +215,7 @@
     } else {
 	/* vc_rows = (c->vc_rows > vc_rows) ? vc_rows : c->vc_rows; */
 	/* vc_cols = (c->vc_cols > vc_cols) ? vc_cols : c->vc_cols; */
-	vc_resize(c->vc_num, vc_cols, vc_rows); 
+	vc_resize(c, vc_cols, vc_rows);
 /*	vc_resize_con(vc_rows, vc_cols, c->vc_num); */
     }
 }
diff -Nru a/drivers/video/console/tileblit.c b/drivers/video/console/tileblit.c
--- a/drivers/video/console/tileblit.c	2005-03-11 12:51:46 -08:00
+++ b/drivers/video/console/tileblit.c	2005-03-11 12:51:46 -08:00
@@ -81,7 +81,8 @@
 }
 
 static void tile_cursor(struct vc_data *vc, struct fb_info *info,
-			struct display *p, int mode, int fg, int bg)
+			struct display *p, int mode, int softback_lines,
+			int fg, int bg)
 {
 	struct fb_tilecursor cursor;
 	int use_sw = (vc->vc_cursor_type & 0x01);
diff -Nru a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
--- a/drivers/video/console/vgacon.c	2005-03-11 12:51:43 -08:00
+++ b/drivers/video/console/vgacon.c	2005-03-11 12:51:43 -08:00
@@ -340,11 +340,11 @@
 	p = *c->vc_uni_pagedir_loc;
 	if (c->vc_uni_pagedir_loc == &c->vc_uni_pagedir ||
 	    !--c->vc_uni_pagedir_loc[1])
-		con_free_unimap(c->vc_num);
+		con_free_unimap(c);
 	c->vc_uni_pagedir_loc = vgacon_uni_pagedir;
 	vgacon_uni_pagedir[1]++;
 	if (!vgacon_uni_pagedir[0] && p)
-		con_set_default_unimap(c->vc_num);
+		con_set_default_unimap(c);
 }
 
 static inline void vga_set_mem_top(struct vc_data *c)
@@ -358,10 +358,10 @@
 	if (!--vgacon_uni_pagedir[1]) {
 		c->vc_visible_origin = vga_vram_base;
 		vga_set_mem_top(c);
-		con_free_unimap(c->vc_num);
+		con_free_unimap(c);
 	}
 	c->vc_uni_pagedir_loc = &c->vc_uni_pagedir;
-	con_set_default_unimap(c->vc_num);
+	con_set_default_unimap(c);
 }
 
 static u8 vgacon_build_attr(struct vc_data *c, u8 color, u8 intensity,
@@ -908,7 +908,7 @@
 				c->vc_sw->con_cursor(c, CM_DRAW);
 			}
 			c->vc_font.height = fontheight;
-			vc_resize(c->vc_num, 0, rows);	/* Adjust console size */
+			vc_resize(c, 0, rows);	/* Adjust console size */
 		}
 	}
 	return 0;
diff -Nru a/drivers/video/cyber2000fb.c b/drivers/video/cyber2000fb.c
--- a/drivers/video/cyber2000fb.c	2005-03-11 12:51:41 -08:00
+++ b/drivers/video/cyber2000fb.c	2005-03-11 12:51:41 -08:00
@@ -92,7 +92,6 @@
 	u_char			ramdac_powerdown;
 };
 
-static char default_font_storage[40];
 static char *default_font = "Acorn8x8";
 module_param(default_font, charp, 0);
 MODULE_PARM_DESC(default_font, "Default font name");
@@ -1306,7 +1305,8 @@
  * Parse Cyber2000fb options.  Usage:
  *  video=cyber2000:font:fontname
  */
-int
+#ifndef MODULE
+static int
 cyber2000fb_setup(char *options)
 {
 	char *opt;
@@ -1319,6 +1319,8 @@
 			continue;
 
 		if (strncmp(opt, "font:", 5) == 0) {
+			static char default_font_storage[40];
+
 			strlcpy(default_font_storage, opt + 5, sizeof(default_font_storage));
 			default_font = default_font_storage;
 			continue;
@@ -1328,6 +1330,7 @@
 	}
 	return 0;
 }
+#endif  /*  MODULE  */
 
 /*
  * The CyberPro chips can be placed on many different bus types.
@@ -1717,7 +1720,7 @@
  *
  * Tony: "module_init" is now required
  */
-int __init cyber2000fb_init(void)
+static int __init cyber2000fb_init(void)
 {
 	int ret = -1, err;
 
diff -Nru a/drivers/video/fbmem.c b/drivers/video/fbmem.c
--- a/drivers/video/fbmem.c	2005-03-11 12:51:40 -08:00
+++ b/drivers/video/fbmem.c	2005-03-11 12:51:40 -08:00
@@ -62,10 +62,8 @@
  * Helpers
  */
 
-int fb_get_color_depth(struct fb_info *info)
+int fb_get_color_depth(struct fb_var_screeninfo *var)
 {
-	struct fb_var_screeninfo *var = &info->var;
-
 	if (var->green.length == var->blue.length &&
 	    var->green.length == var->red.length &&
 	    !var->green.offset && !var->blue.offset &&
@@ -300,7 +298,7 @@
 	const u8 *src = logo->data;
 	u8 d, xor = (info->fix.visual == FB_VISUAL_MONO01) ? 0xff : 0;
 
-	if (fb_get_color_depth(info) == 3)
+	if (fb_get_color_depth(&info->var) == 3)
 		fg = 7;
 
 	switch (depth) {
@@ -365,7 +363,7 @@
 
 int fb_prepare_logo(struct fb_info *info)
 {
-	int depth = fb_get_color_depth(info);
+	int depth = fb_get_color_depth(&info->var);
 
 	memset(&fb_logo, 0, sizeof(struct logo_data));
 
@@ -876,7 +874,8 @@
 	int fbidx = iminor(file->f_dentry->d_inode);
 	struct fb_info *info = registered_fb[fbidx];
 	struct fb_ops *fb = info->fbops;
-	int ret;
+	long ret;
+
 	if (fb->fb_compat_ioctl == NULL)
 		return -ENOIOCTLCMD;
 	lock_kernel();
@@ -1058,7 +1057,6 @@
 register_framebuffer(struct fb_info *fb_info)
 {
 	int i;
-	struct class_device *c;
 	struct fb_event event;
 
 	if (num_registered_fb == FB_MAX)
@@ -1069,13 +1067,15 @@
 			break;
 	fb_info->node = i;
 
-	c = class_simple_device_add(fb_class, MKDEV(FB_MAJOR, i),
+	fb_info->class_device = class_simple_device_add(fb_class, MKDEV(FB_MAJOR, i),
 				    fb_info->device, "fb%d", i);
-	if (IS_ERR(c)) {
+	if (IS_ERR(fb_info->class_device)) {
 		/* Not fatal */
-		printk(KERN_WARNING "Unable to create class_device for framebuffer %d; errno = %ld\n", i, PTR_ERR(c));
-	}
-	
+		printk(KERN_WARNING "Unable to create class_device for framebuffer %d; errno = %ld\n", i, PTR_ERR(fb_info->class_device));
+		fb_info->class_device = NULL;
+	} else
+		fb_init_class_device(fb_info);
+
 	if (fb_info->pixmap.addr == NULL) {
 		fb_info->pixmap.addr = kmalloc(FBPIXMAPSIZE, GFP_KERNEL);
 		if (fb_info->pixmap.addr) {
@@ -1134,6 +1134,7 @@
 	fb_destroy_modelist(&fb_info->modelist);
 	registered_fb[i]=NULL;
 	num_registered_fb--;
+	fb_cleanup_class_device(fb_info);
 	class_simple_device_remove(MKDEV(FB_MAJOR, i));
 	return 0;
 }
@@ -1188,7 +1189,7 @@
  *
  */
 
-int __init
+static int __init
 fbmem_init(void)
 {
 	create_proc_read_entry("fb", 0, NULL, fbmem_read_proc, NULL);
@@ -1204,7 +1205,55 @@
 	}
 	return 0;
 }
+
+#ifdef MODULE
+module_init(fbmem_init);
+static void __exit
+fbmem_exit(void)
+{
+	class_simple_destroy(fb_class);
+}
+
+module_exit(fbmem_exit);
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Framebuffer base");
+#else
 subsys_initcall(fbmem_init);
+#endif
+
+int fb_new_modelist(struct fb_info *info)
+{
+	struct fb_event event;
+	struct fb_var_screeninfo var = info->var;
+	struct list_head *pos, *n;
+	struct fb_modelist *modelist;
+	struct fb_videomode *m, mode;
+	int err = 1;
+
+	list_for_each_safe(pos, n, &info->modelist) {
+		modelist = list_entry(pos, struct fb_modelist, list);
+		m = &modelist->mode;
+		fb_videomode_to_var(&var, m);
+		var.activate = FB_ACTIVATE_TEST;
+		err = fb_set_var(info, &var);
+		fb_var_to_videomode(&mode, &var);
+		if (err || !fb_mode_is_equal(m, &mode)) {
+			list_del(pos);
+			kfree(pos);
+		}
+	}
+
+	err = 1;
+
+	if (!list_empty(&info->modelist)) {
+		event.info = info;
+		err = notifier_call_chain(&fb_notifier_list,
+					   FB_EVENT_NEW_MODELIST,
+					   &event);
+	}
+
+	return err;
+}
 
 static char *video_options[FB_MAX];
 static int ofonly;
@@ -1317,5 +1366,6 @@
 EXPORT_SYMBOL(fb_register_client);
 EXPORT_SYMBOL(fb_unregister_client);
 EXPORT_SYMBOL(fb_get_options);
+EXPORT_SYMBOL(fb_new_modelist);
 
 MODULE_LICENSE("GPL");
diff -Nru a/drivers/video/fbmon.c b/drivers/video/fbmon.c
--- a/drivers/video/fbmon.c	2005-03-11 12:51:51 -08:00
+++ b/drivers/video/fbmon.c	2005-03-11 12:51:51 -08:00
@@ -518,7 +518,7 @@
  * This function builds a mode database using the contents of the EDID
  * data
  */
-struct fb_videomode *fb_create_modedb(unsigned char *edid, int *dbsize)
+static struct fb_videomode *fb_create_modedb(unsigned char *edid, int *dbsize)
 {
 	struct fb_videomode *mode, *m;
 	unsigned char *block;
@@ -593,7 +593,7 @@
 		kfree(modedb);
 }
 
-int fb_get_monitor_limits(unsigned char *edid, struct fb_monspecs *specs)
+static int fb_get_monitor_limits(unsigned char *edid, struct fb_monspecs *specs)
 {
 	int i, retval = 1;
 	unsigned char *block;
@@ -1197,17 +1197,9 @@
 {
 	return NULL;
 }
-struct fb_videomode *fb_create_modedb(unsigned char *edid, int *dbsize)
-{
-	return NULL;
-}
 void fb_destroy_modedb(struct fb_videomode *modedb)
 {
 }
-int fb_get_monitor_limits(unsigned char *edid, struct fb_monspecs *specs)
-{
-	return 1;
-}
 int fb_get_mode(int flags, u32 val, struct fb_var_screeninfo *var,
 		struct fb_info *info)
 {
@@ -1282,6 +1274,4 @@
 
 EXPORT_SYMBOL(fb_get_mode);
 EXPORT_SYMBOL(fb_validate_mode);
-EXPORT_SYMBOL(fb_create_modedb);
 EXPORT_SYMBOL(fb_destroy_modedb);
-EXPORT_SYMBOL(fb_get_monitor_limits);
diff -Nru a/drivers/video/fbsysfs.c b/drivers/video/fbsysfs.c
--- a/drivers/video/fbsysfs.c	2005-03-11 12:51:51 -08:00
+++ b/drivers/video/fbsysfs.c	2005-03-11 12:51:51 -08:00
@@ -17,6 +17,7 @@
 
 #include <linux/kernel.h>
 #include <linux/fb.h>
+#include <linux/console.h>
 
 /**
  * framebuffer_alloc - creates a new frame buffer info structure
@@ -57,6 +58,7 @@
 #undef PADDING
 #undef BYTES_PER_LONG
 }
+EXPORT_SYMBOL(framebuffer_alloc);
 
 /**
  * framebuffer_release - marks the structure available for freeing
@@ -71,6 +73,317 @@
 {
 	kfree(info);
 }
-
 EXPORT_SYMBOL(framebuffer_release);
-EXPORT_SYMBOL(framebuffer_alloc);
+
+static int activate(struct fb_info *fb_info, struct fb_var_screeninfo *var)
+{
+	int err;
+
+	var->activate |= FB_ACTIVATE_FORCE;
+	acquire_console_sem();
+	fb_info->flags |= FBINFO_MISC_USEREVENT;
+	err = fb_set_var(fb_info, var);
+	fb_info->flags &= ~FBINFO_MISC_USEREVENT;
+	release_console_sem();
+	if (err)
+		return err;
+	return 0;
+}
+
+static int mode_string(char *buf, unsigned int offset,
+		       const struct fb_videomode *mode)
+{
+	char m = 'U';
+	if (mode->flag & FB_MODE_IS_DETAILED)
+		m = 'D';
+	if (mode->flag & FB_MODE_IS_VESA)
+		m = 'V';
+	if (mode->flag & FB_MODE_IS_STANDARD)
+		m = 'S';
+	return snprintf(&buf[offset], PAGE_SIZE - offset, "%c:%dx%d-%d\n", m, mode->xres, mode->yres, mode->refresh);
+}
+
+static ssize_t store_mode(struct class_device *class_device, const char * buf,
+			  size_t count)
+{
+	struct fb_info *fb_info =
+		(struct fb_info *)class_get_devdata(class_device);
+	char mstr[100];
+	struct fb_var_screeninfo var;
+	struct fb_modelist *modelist;
+	struct fb_videomode *mode;
+	struct list_head *pos;
+	size_t i;
+	int err;
+
+	memset(&var, 0, sizeof(var));
+
+	list_for_each(pos, &fb_info->modelist) {
+		modelist = list_entry(pos, struct fb_modelist, list);
+		mode = &modelist->mode;
+		i = mode_string(mstr, 0, mode);
+		if (strncmp(mstr, buf, max(count, i)) == 0) {
+
+			var = fb_info->var;
+			fb_videomode_to_var(&var, mode);
+			if ((err = activate(fb_info, &var)))
+				return err;
+			fb_info->mode = mode;
+			return count;
+		}
+	}
+	return -EINVAL;
+}
+
+static ssize_t show_mode(struct class_device *class_device, char *buf)
+{
+	struct fb_info *fb_info =
+		(struct fb_info *)class_get_devdata(class_device);
+
+	if (!fb_info->mode)
+		return 0;
+
+	return mode_string(buf, 0, fb_info->mode);
+}
+
+static ssize_t store_modes(struct class_device *class_device, const char * buf,
+			   size_t count)
+{
+	struct fb_info *fb_info =
+		(struct fb_info *)class_get_devdata(class_device);
+	LIST_HEAD(old_list);
+	int i = count / sizeof(struct fb_videomode);
+
+	if (i * sizeof(struct fb_videomode) != count)
+		return -EINVAL;
+
+	acquire_console_sem();
+	list_splice(&fb_info->modelist, &old_list);
+	fb_videomode_to_modelist((struct fb_videomode *)buf, i,
+				 &fb_info->modelist);
+	if (fb_new_modelist(fb_info)) {
+		fb_destroy_modelist(&fb_info->modelist);
+		list_splice(&old_list, &fb_info->modelist);
+	} else
+		fb_destroy_modelist(&old_list);
+
+	release_console_sem();
+
+	return 0;
+}
+
+static ssize_t show_modes(struct class_device *class_device, char *buf)
+{
+	struct fb_info *fb_info =
+		(struct fb_info *)class_get_devdata(class_device);
+	unsigned int i;
+	struct list_head *pos;
+	struct fb_modelist *modelist;
+	const struct fb_videomode *mode;
+
+	i = 0;
+	list_for_each(pos, &fb_info->modelist) {
+		modelist = list_entry(pos, struct fb_modelist, list);
+		mode = &modelist->mode;
+		i += mode_string(buf, i, mode);
+	}
+	return i;
+}
+
+static ssize_t store_bpp(struct class_device *class_device, const char * buf,
+			 size_t count)
+{
+	struct fb_info *fb_info =
+		(struct fb_info *)class_get_devdata(class_device);
+	struct fb_var_screeninfo var;
+	char ** last = NULL;
+	int err;
+
+	var = fb_info->var;
+	var.bits_per_pixel = simple_strtoul(buf, last, 0);
+	if ((err = activate(fb_info, &var)))
+		return err;
+	return count;
+}
+
+static ssize_t show_bpp(struct class_device *class_device, char *buf)
+{
+	struct fb_info *fb_info =
+		(struct fb_info *)class_get_devdata(class_device);
+	return snprintf(buf, PAGE_SIZE, "%d\n", fb_info->var.bits_per_pixel);
+}
+
+static ssize_t store_virtual(struct class_device *class_device,
+			     const char * buf, size_t count)
+{
+	struct fb_info *fb_info =
+		(struct fb_info *)class_get_devdata(class_device);
+	struct fb_var_screeninfo var;
+	char *last = NULL;
+	int err;
+
+	var = fb_info->var;
+	var.xres_virtual = simple_strtoul(buf, &last, 0);
+	last++;
+	if (last - buf >= count)
+		return -EINVAL;
+	var.yres_virtual = simple_strtoul(last, &last, 0);
+	printk(KERN_ERR "fb: xres %d yres %d\n", var.xres_virtual,
+	       var.yres_virtual);
+
+	if ((err = activate(fb_info, &var)))
+		return err;
+	return count;
+}
+
+static ssize_t show_virtual(struct class_device *class_device, char *buf)
+{
+	struct fb_info *fb_info =
+		(struct fb_info *)class_get_devdata(class_device);
+	return snprintf(buf, PAGE_SIZE, "%d,%d\n", fb_info->var.xres_virtual,
+			fb_info->var.xres_virtual);
+}
+
+static ssize_t store_cmap(struct class_device *class_device, const char * buf,
+			  size_t count)
+{
+//	struct fb_info *fb_info = (struct fb_info *)class_get_devdata(class_device);
+	return 0;
+}
+
+static ssize_t show_cmap(struct class_device *class_device, char *buf)
+{
+	struct fb_info *fb_info =
+		(struct fb_info *)class_get_devdata(class_device);
+	unsigned int offset = 0, i;
+
+	if (!fb_info->cmap.red || !fb_info->cmap.blue ||
+	    fb_info->cmap.green || fb_info->cmap.transp)
+		return -EINVAL;
+
+	for (i = 0; i < fb_info->cmap.len; i++) {
+		offset += snprintf(buf, PAGE_SIZE - offset,
+				   "%d,%d,%d,%d,%d\n", i + fb_info->cmap.start,
+				   fb_info->cmap.red[i], fb_info->cmap.blue[i],
+				   fb_info->cmap.green[i],
+				   fb_info->cmap.transp[i]);
+	}
+	return offset;
+}
+
+static ssize_t store_blank(struct class_device *class_device, const char * buf,
+			   size_t count)
+{
+	struct fb_info *fb_info =
+		(struct fb_info *)class_get_devdata(class_device);
+	char *last = NULL;
+	int err;
+
+	acquire_console_sem();
+	fb_info->flags |= FBINFO_MISC_USEREVENT;
+	err = fb_blank(fb_info, simple_strtoul(buf, &last, 0));
+	fb_info->flags &= ~FBINFO_MISC_USEREVENT;
+	release_console_sem();
+	if (err < 0)
+		return err;
+	return count;
+}
+
+static ssize_t show_blank(struct class_device *class_device, char *buf)
+{
+//	struct fb_info *fb_info = (struct fb_info *)class_get_devdata(class_device);
+	return 0;
+}
+
+static ssize_t store_console(struct class_device *class_device,
+			     const char * buf, size_t count)
+{
+//	struct fb_info *fb_info = (struct fb_info *)class_get_devdata(class_device);
+	return 0;
+}
+
+static ssize_t show_console(struct class_device *class_device, char *buf)
+{
+//	struct fb_info *fb_info = (struct fb_info *)class_get_devdata(class_device);
+	return 0;
+}
+
+static ssize_t store_cursor(struct class_device *class_device,
+			    const char * buf, size_t count)
+{
+//	struct fb_info *fb_info = (struct fb_info *)class_get_devdata(class_device);
+	return 0;
+}
+
+static ssize_t show_cursor(struct class_device *class_device, char *buf)
+{
+//	struct fb_info *fb_info = (struct fb_info *)class_get_devdata(class_device);
+	return 0;
+}
+
+static ssize_t store_pan(struct class_device *class_device, const char * buf,
+			 size_t count)
+{
+	struct fb_info *fb_info =
+		(struct fb_info *)class_get_devdata(class_device);
+	struct fb_var_screeninfo var;
+	char *last = NULL;
+	int err;
+
+	var = fb_info->var;
+	var.xoffset = simple_strtoul(buf, &last, 0);
+	last++;
+	if (last - buf >= count)
+		return -EINVAL;
+	var.yoffset = simple_strtoul(last, &last, 0);
+
+	acquire_console_sem();
+	err = fb_pan_display(fb_info, &var);
+	release_console_sem();
+
+	if (err < 0)
+		return err;
+	return count;
+}
+
+static ssize_t show_pan(struct class_device *class_device, char *buf)
+{
+	struct fb_info *fb_info =
+		(struct fb_info *)class_get_devdata(class_device);
+	return snprintf(buf, PAGE_SIZE, "%d,%d\n", fb_info->var.xoffset,
+			fb_info->var.xoffset);
+}
+
+struct class_device_attribute class_device_attrs[] = {
+	__ATTR(bits_per_pixel, S_IRUGO|S_IWUSR, show_bpp, store_bpp),
+	__ATTR(blank, S_IRUGO|S_IWUSR, show_blank, store_blank),
+	__ATTR(color_map, S_IRUGO|S_IWUSR, show_cmap, store_cmap),
+	__ATTR(console, S_IRUGO|S_IWUSR, show_console, store_console),
+	__ATTR(cursor, S_IRUGO|S_IWUSR, show_cursor, store_cursor),
+	__ATTR(mode, S_IRUGO|S_IWUSR, show_mode, store_mode),
+	__ATTR(modes, S_IRUGO|S_IWUSR, show_modes, store_modes),
+	__ATTR(pan, S_IRUGO|S_IWUSR, show_pan, store_pan),
+	__ATTR(virtual_size, S_IRUGO|S_IWUSR, show_virtual, store_virtual),
+};
+
+int fb_init_class_device(struct fb_info *fb_info)
+{
+	unsigned int i;
+	class_set_devdata(fb_info->class_device, fb_info);
+
+	for (i = 0; i < ARRAY_SIZE(class_device_attrs); i++)
+		class_device_create_file(fb_info->class_device,
+					 &class_device_attrs[i]);
+	return 0;
+}
+
+void fb_cleanup_class_device(struct fb_info *fb_info)
+{
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(class_device_attrs); i++)
+		class_device_remove_file(fb_info->class_device,
+					 &class_device_attrs[i]);
+}
+
+
diff -Nru a/drivers/video/geode/Kconfig b/drivers/video/geode/Kconfig
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/video/geode/Kconfig	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,29 @@
+#
+# Geode family framebuffer configuration
+#
+config FB_GEODE
+	bool "AMD Geode family framebuffer support (EXPERIMENTAL)"
+	default n
+	depends on FB && EXPERIMENTAL && X86
+	---help---
+	  Say 'Y' here to allow you to select framebuffer drivers for
+	  the AMD Geode family of processors.
+
+config FB_GEODE_GX1
+	tristate "AMD Geode GX1 framebuffer support (EXPERIMENTAL)"
+	default n
+	depends on FB_GEODE && EXPERIMENTAL
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	select FB_SOFT_CURSOR
+	---help---
+	  Framebuffer driver for the display controller integrated into the
+	  AMD Geode GX1 processor.
+
+	  This driver is also available as a module ( = code which can be
+	  inserted and removed from the running kernel whenever you want). The
+	  module will be called gx1fb. If you want to compile it as a module,
+	  say M here and read <file:Documentation/modules.txt>.
+
+	  If unsure, say N.
diff -Nru a/drivers/video/geode/Makefile b/drivers/video/geode/Makefile
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/video/geode/Makefile	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,5 @@
+# Makefile for the Geode family framebuffer drivers
+
+obj-$(CONFIG_FB_GEODE_GX1) += gx1fb.o
+
+gx1fb-objs   		:= gx1fb_core.o display_gx1.o video_cs5530.o
diff -Nru a/drivers/video/geode/display_gx1.c b/drivers/video/geode/display_gx1.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/video/geode/display_gx1.c	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,214 @@
+/*
+ * drivers/video/geode/display_gx1.c
+ *   -- Geode GX1 display controller
+ *
+ * Copyright (C) 2005 Arcom Control Systems Ltd.
+ *
+ * Based on AMD's original 2.4 driver:
+ *   Copyright (C) 2004 Advanced Micro Devices, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+#include <linux/spinlock.h>
+#include <linux/fb.h>
+#include <linux/delay.h>
+#include <asm/io.h>
+#include <asm/div64.h>
+#include <asm/delay.h>
+
+#include "geodefb.h"
+#include "display_gx1.h"
+
+static spinlock_t gx1_conf_reg_lock = SPIN_LOCK_UNLOCKED;
+
+static u8 gx1_read_conf_reg(u8 reg)
+{
+	u8 val, ccr3;
+	unsigned long flags;
+
+	spin_lock_irqsave(&gx1_conf_reg_lock, flags);
+
+	outb(CONFIG_CCR3, 0x22);
+	ccr3 = inb(0x23);
+	outb(CONFIG_CCR3, 0x22);
+	outb(ccr3 | CONFIG_CCR3_MAPEN, 0x23);
+	outb(reg, 0x22);
+	val = inb(0x23);
+	outb(CONFIG_CCR3, 0x22);
+	outb(ccr3, 0x23);
+
+	spin_unlock_irqrestore(&gx1_conf_reg_lock, flags);
+
+	return val;
+}
+
+unsigned gx1_gx_base(void)
+{
+	return (gx1_read_conf_reg(CONFIG_GCR) & 0x03) << 30;
+}
+
+int gx1_frame_buffer_size(void)
+{
+	void __iomem *mc_regs;
+	u32 bank_cfg;
+	int d;
+	unsigned dram_size = 0, fb_base;
+
+	mc_regs = ioremap(gx1_gx_base() + 0x8400, 0x100);
+	if (!mc_regs)
+		return -ENOMEM;
+
+
+	/* Calculate the total size of both DIMM0 and DIMM1. */
+	bank_cfg = readl(mc_regs + MC_BANK_CFG);
+
+	for (d = 0; d < 2; d++) {
+		if ((bank_cfg & MC_BCFG_DIMM0_PG_SZ_MASK) != MC_BCFG_DIMM0_PG_SZ_NO_DIMM)
+			dram_size += 0x400000 << ((bank_cfg & MC_BCFG_DIMM0_SZ_MASK) >> 8);
+		bank_cfg >>= 16; /* look at DIMM1 next */
+	}
+
+	fb_base = (readl(mc_regs + MC_GBASE_ADD) & MC_GADD_GBADD_MASK) << 19;
+
+	iounmap(mc_regs);
+
+	return dram_size - fb_base;
+}
+
+static void gx1_set_mode(struct fb_info *info)
+{
+	struct geodefb_par *par = info->par;
+	u32 gcfg, tcfg, ocfg, dclk_div, val;
+	int hactive, hblankstart, hsyncstart, hsyncend, hblankend, htotal;
+	int vactive, vblankstart, vsyncstart, vsyncend, vblankend, vtotal;
+
+	/* Unlock the display controller registers. */
+	readl(par->dc_regs + DC_UNLOCK);
+	writel(DC_UNLOCK_CODE, par->dc_regs + DC_UNLOCK);
+
+	gcfg = readl(par->dc_regs + DC_GENERAL_CFG);
+	tcfg = readl(par->dc_regs + DC_TIMING_CFG);
+
+	/* Blank the display and disable the timing generator. */
+	tcfg &= ~(DC_TCFG_BLKE | DC_TCFG_TGEN);
+	writel(tcfg, par->dc_regs + DC_TIMING_CFG);
+
+	/* Wait for pending memory requests before disabling the FIFO load. */
+	udelay(100);
+
+	/* Disable FIFO load and compression. */
+	gcfg &= ~(DC_GCFG_DFLE | DC_GCFG_CMPE | DC_GCFG_DECE);
+	writel(gcfg, par->dc_regs + DC_GENERAL_CFG);
+
+	/* Setup DCLK and its divisor. */
+	gcfg &= ~DC_GCFG_DCLK_MASK;
+	writel(gcfg, par->dc_regs + DC_GENERAL_CFG);
+
+	par->vid_ops->set_dclk(info);
+
+	dclk_div = DC_GCFG_DCLK_DIV_1; /* FIXME: may need to divide DCLK by 2 sometimes? */
+	gcfg |= dclk_div;
+	writel(gcfg, par->dc_regs + DC_GENERAL_CFG);
+
+	/* Wait for the clock generatation to settle.  This is needed since
+	 * some of the register writes that follow require that clock to be
+	 * present. */
+	udelay(1000); /* FIXME: seems a little long */
+
+	/*
+	 * Setup new mode.
+	 */
+
+	/* Clear all unused feature bits. */
+	gcfg = DC_GCFG_VRDY | dclk_div;
+
+	/* Set FIFO priority (default 6/5) and enable. */
+	/* FIXME: increase fifo priority for 1280x1024 modes? */
+	gcfg |= (6 << DC_GCFG_DFHPEL_POS) | (5 << DC_GCFG_DFHPSL_POS) | DC_GCFG_DFLE;
+
+	/* FIXME: Set pixel and line double bits if necessary. */
+
+	/* Framebuffer start offset. */
+	writel(0, par->dc_regs + DC_FB_ST_OFFSET);
+
+	/* Line delta and line buffer length. */
+	writel(info->fix.line_length >> 2, par->dc_regs + DC_LINE_DELTA);
+	writel(((info->var.xres * info->var.bits_per_pixel/8) >> 3) + 2,
+	       par->dc_regs + DC_BUF_SIZE);
+
+	/* Output configuration. Enable panel data, set pixel format. */
+	ocfg = DC_OCFG_PCKE | DC_OCFG_PDEL | DC_OCFG_PDEH;
+	if (info->var.bits_per_pixel == 8) ocfg |= DC_OCFG_8BPP;
+
+	/* Enable timing generator, sync and FP data. */
+	tcfg = DC_TCFG_FPPE | DC_TCFG_HSYE | DC_TCFG_VSYE | DC_TCFG_BLKE
+		| DC_TCFG_TGEN;
+
+	/* Horizontal and vertical timings. */
+	hactive = info->var.xres;
+	hblankstart = hactive;
+	hsyncstart = hblankstart + info->var.right_margin;
+	hsyncend =  hsyncstart + info->var.hsync_len;
+	hblankend = hsyncend + info->var.left_margin;
+	htotal = hblankend;
+
+	vactive = info->var.yres;
+	vblankstart = vactive;
+	vsyncstart = vblankstart + info->var.lower_margin;
+	vsyncend =  vsyncstart + info->var.vsync_len;
+	vblankend = vsyncend + info->var.upper_margin;
+	vtotal = vblankend;
+
+	val = (hactive - 1) | ((htotal - 1) << 16);
+	writel(val, par->dc_regs + DC_H_TIMING_1);
+	val = (hblankstart - 1) | ((hblankend - 1) << 16);
+	writel(val, par->dc_regs + DC_H_TIMING_2);
+	val = (hsyncstart - 1) | ((hsyncend - 1) << 16);
+	writel(val, par->dc_regs + DC_H_TIMING_3);
+	writel(val, par->dc_regs + DC_FP_H_TIMING);
+	val = (vactive - 1) | ((vtotal - 1) << 16);
+	writel(val, par->dc_regs + DC_V_TIMING_1);
+	val = (vblankstart - 1) | ((vblankend - 1) << 16);
+	writel(val, par->dc_regs + DC_V_TIMING_2);
+	val = (vsyncstart - 1) | ((vsyncend - 1) << 16);
+	writel(val, par->dc_regs + DC_V_TIMING_3);
+	val = (vsyncstart - 2) | ((vsyncend - 2) << 16);
+	writel(val, par->dc_regs + DC_FP_V_TIMING);
+
+	/* Write final register values. */
+	writel(ocfg, par->dc_regs + DC_OUTPUT_CFG);
+	writel(tcfg, par->dc_regs + DC_TIMING_CFG);
+	udelay(1000); /* delay after TIMING_CFG. FIXME: perhaps a little long */
+	writel(gcfg, par->dc_regs + DC_GENERAL_CFG);
+
+	par->vid_ops->configure_display(info);
+
+	/* Relock display controller registers */
+	writel(0, par->dc_regs + DC_UNLOCK);
+
+	/* FIXME: write line_length and bpp to Graphics Pipeline GP_BLT_STATUS
+	 * register. */
+}
+
+static void gx1_set_hw_palette_reg(struct fb_info *info, unsigned regno,
+				   unsigned red, unsigned green, unsigned blue)
+{
+	struct geodefb_par *par = info->par;
+	int val;
+
+	/* Hardware palette is in RGB 6-6-6 format. */
+	val  = (red   <<  2) & 0x3f000;
+	val |= (green >>  4) & 0x00fc0;
+	val |= (blue  >> 10) & 0x0003f;
+
+	writel(regno, par->dc_regs + DC_PAL_ADDRESS);
+	writel(val, par->dc_regs + DC_PAL_DATA);
+}
+
+struct geode_dc_ops gx1_dc_ops = {
+	.set_mode	 = gx1_set_mode,
+	.set_palette_reg = gx1_set_hw_palette_reg,
+};
diff -Nru a/drivers/video/geode/display_gx1.h b/drivers/video/geode/display_gx1.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/video/geode/display_gx1.h	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,154 @@
+/*
+ * drivers/video/geode/display_gx1.h
+ *   -- Geode GX1 display controller
+ *
+ * Copyright (C) 2005 Arcom Control Systems Ltd.
+ *
+ * Based on AMD's original 2.4 driver:
+ *   Copyright (C) 2004 Advanced Micro Devices, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+#ifndef __DISPLAY_GX1_H__
+#define __DISPLAY_GX1_H__
+
+unsigned gx1_gx_base(void);
+int gx1_frame_buffer_size(void);
+
+extern struct geode_dc_ops gx1_dc_ops;
+
+/* GX1 configuration I/O registers */
+
+#define CONFIG_CCR3 0xc3
+#  define CONFIG_CCR3_MAPEN 0x10
+#define CONFIG_GCR  0xb8
+
+/* Memory controller registers */
+
+#define MC_BANK_CFG		0x08
+#  define MC_BCFG_DIMM0_SZ_MASK		0x00000700
+#  define MC_BCFG_DIMM0_PG_SZ_MASK	0x00000070
+#  define MC_BCFG_DIMM0_PG_SZ_NO_DIMM	0x00000070
+
+#define MC_GBASE_ADD		0x14
+#  define MC_GADD_GBADD_MASK		0x000003ff
+
+/* Display controller registers */
+
+#define DC_PAL_ADDRESS		0x70
+#define DC_PAL_DATA		0x74
+
+#define DC_UNLOCK		0x00
+#  define DC_UNLOCK_CODE		0x00004758
+
+#define DC_GENERAL_CFG		0x04
+#  define DC_GCFG_DFLE			0x00000001
+#  define DC_GCFG_CURE			0x00000002
+#  define DC_GCFG_VCLK_DIV		0x00000004
+#  define DC_GCFG_PLNO			0x00000004
+#  define DC_GCFG_PPC			0x00000008
+#  define DC_GCFG_CMPE			0x00000010
+#  define DC_GCFG_DECE			0x00000020
+#  define DC_GCFG_DCLK_MASK		0x000000C0
+#  define DC_GCFG_DCLK_DIV_1		0x00000080
+#  define DC_GCFG_DFHPSL_MASK		0x00000F00
+#  define DC_GCFG_DFHPSL_POS			 8
+#  define DC_GCFG_DFHPEL_MASK		0x0000F000
+#  define DC_GCFG_DFHPEL_POS			12
+#  define DC_GCFG_CIM_MASK		0x00030000
+#  define DC_GCFG_CIM_POS			16
+#  define DC_GCFG_FDTY			0x00040000
+#  define DC_GCFG_RTPM			0x00080000
+#  define DC_GCFG_DAC_RS_MASK		0x00700000
+#  define DC_GCFG_DAC_RS_POS			20
+#  define DC_GCFG_CKWR			0x00800000
+#  define DC_GCFG_LDBL			0x01000000
+#  define DC_GCFG_DIAG			0x02000000
+#  define DC_GCFG_CH4S			0x04000000
+#  define DC_GCFG_SSLC			0x08000000
+#  define DC_GCFG_VIDE			0x10000000
+#  define DC_GCFG_VRDY			0x20000000
+#  define DC_GCFG_DPCK			0x40000000
+#  define DC_GCFG_DDCK			0x80000000
+
+#define DC_TIMING_CFG		0x08
+#  define DC_TCFG_FPPE			0x00000001
+#  define DC_TCFG_HSYE			0x00000002
+#  define DC_TCFG_VSYE			0x00000004
+#  define DC_TCFG_BLKE			0x00000008
+#  define DC_TCFG_DDCK			0x00000010
+#  define DC_TCFG_TGEN			0x00000020
+#  define DC_TCFG_VIEN			0x00000040
+#  define DC_TCFG_BLNK			0x00000080
+#  define DC_TCFG_CHSP			0x00000100
+#  define DC_TCFG_CVSP			0x00000200
+#  define DC_TCFG_FHSP			0x00000400
+#  define DC_TCFG_FVSP			0x00000800
+#  define DC_TCFG_FCEN			0x00001000
+#  define DC_TCFG_CDCE			0x00002000
+#  define DC_TCFG_PLNR			0x00002000
+#  define DC_TCFG_INTL			0x00004000
+#  define DC_TCFG_PXDB			0x00008000
+#  define DC_TCFG_BKRT			0x00010000
+#  define DC_TCFG_PSD_MASK		0x000E0000
+#  define DC_TCFG_PSD_POS			17
+#  define DC_TCFG_DDCI			0x08000000
+#  define DC_TCFG_SENS			0x10000000
+#  define DC_TCFG_DNA			0x20000000
+#  define DC_TCFG_VNA			0x40000000
+#  define DC_TCFG_VINT			0x80000000
+
+#define DC_OUTPUT_CFG		0x0C
+#  define DC_OCFG_8BPP			0x00000001
+#  define DC_OCFG_555			0x00000002
+#  define DC_OCFG_PCKE			0x00000004
+#  define DC_OCFG_FRME			0x00000008
+#  define DC_OCFG_DITE			0x00000010
+#  define DC_OCFG_2PXE			0x00000020
+#  define DC_OCFG_2XCK			0x00000040
+#  define DC_OCFG_2IND			0x00000080
+#  define DC_OCFG_34ADD			0x00000100
+#  define DC_OCFG_FRMS			0x00000200
+#  define DC_OCFG_CKSL			0x00000400
+#  define DC_OCFG_PRMP			0x00000800
+#  define DC_OCFG_PDEL			0x00001000
+#  define DC_OCFG_PDEH			0x00002000
+#  define DC_OCFG_CFRW			0x00004000
+#  define DC_OCFG_DIAG			0x00008000
+
+#define DC_FB_ST_OFFSET		0x10
+#define DC_CB_ST_OFFSET		0x14
+#define DC_CURS_ST_OFFSET	0x18
+#define DC_ICON_ST_OFFSET	0x1C
+#define DC_VID_ST_OFFSET	0x20
+#define DC_LINE_DELTA		0x24
+#define DC_BUF_SIZE		0x28
+
+#define DC_H_TIMING_1		0x30
+#define DC_H_TIMING_2		0x34
+#define DC_H_TIMING_3		0x38
+#define DC_FP_H_TIMING		0x3C
+
+#define DC_V_TIMING_1		0x40
+#define DC_V_TIMING_2		0x44
+#define DC_V_TIMING_3		0x48
+#define DC_FP_V_TIMING		0x4C
+
+#define DC_CURSOR_X		0x50
+#define DC_ICON_X		0x54
+#define DC_V_LINE_CNT		0x54
+#define DC_CURSOR_Y		0x58
+#define DC_ICON_Y		0x5C
+#define DC_SS_LINE_CMP		0x5C
+#define DC_CURSOR_COLOR		0x60
+#define DC_ICON_COLOR		0x64
+#define DC_BORDER_COLOR		0x68
+#define DC_PAL_ADDRESS		0x70
+#define DC_PAL_DATA		0x74
+#define DC_DFIFO_DIAG		0x78
+#define DC_CFIFO_DIAG		0x7C
+
+#endif /* !__DISPLAY_GX1_H__ */
diff -Nru a/drivers/video/geode/geodefb.h b/drivers/video/geode/geodefb.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/video/geode/geodefb.h	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,39 @@
+/*
+ * drivers/video/geode/geodefb.h
+ *   -- Geode framebuffer driver
+ *
+ * Copyright (C) 2005 Arcom Control Systems Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+#ifndef __GEODEFB_H__
+#define __GEODEFB_H__
+
+struct geodefb_info;
+
+struct geode_dc_ops {
+	void (*set_mode)(struct fb_info *);
+	void (*set_palette_reg)(struct fb_info *, unsigned, unsigned, unsigned, unsigned);
+};
+
+struct geode_vid_ops {
+	void (*set_dclk)(struct fb_info *);
+	void (*configure_display)(struct fb_info *);
+	int  (*blank_display)(struct fb_info *, int blank_mode);
+};
+
+struct geodefb_par {
+	int enable_crt;
+	int panel_x; /* dimensions of an attached flat panel, non-zero => enable panel */
+	int panel_y;
+	struct pci_dev *vid_dev;
+	void __iomem *dc_regs;
+	void __iomem *vid_regs;
+	struct geode_dc_ops  *dc_ops;
+	struct geode_vid_ops *vid_ops;
+};
+
+#endif /* !__GEODEFB_H__ */
diff -Nru a/drivers/video/geode/gx1fb_core.c b/drivers/video/geode/gx1fb_core.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/video/geode/gx1fb_core.c	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,359 @@
+/*
+ * drivers/video/geode/gx1fb_core.c
+ *   -- Geode GX1 framebuffer driver
+ *
+ * Copyright (C) 2005 Arcom Control Systems Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#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/init.h>
+#include <linux/pci.h>
+
+#include "geodefb.h"
+#include "display_gx1.h"
+#include "video_cs5530.h"
+
+static char mode_option[32] = "640x480-16@60";
+static int  crt_option = 1;
+static char panel_option[32] = "";
+
+static int gx1_line_delta(int xres, int bpp)
+{
+	int line_delta = xres * (bpp >> 3);
+
+	if (line_delta > 2048)
+		line_delta = 4096;
+	else if (line_delta > 1024)
+		line_delta = 2048;
+	else
+		line_delta = 1024;
+	return line_delta;
+}
+
+static int gx1fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+	struct geodefb_par *par = info->par;
+
+	printk(KERN_DEBUG "%s()\n", __FUNCTION__);
+
+	/* Maximum resolution is 1280x1024. */
+	if (var->xres > 1280 || var->yres > 1024)
+		return -EINVAL;
+
+	if (par->panel_x && (var->xres > par->panel_x || var->yres > par->panel_y))
+		return -EINVAL;
+
+	/* Only 16 bpp and 8 bpp is supported by the hardware. */
+	if (var->bits_per_pixel == 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;
+	} else if (var->bits_per_pixel == 8) {
+		var->red.offset   = 0; var->red.length   = 8;
+		var->green.offset = 0; var->green.length = 8;
+		var->blue.offset  = 0; var->blue.length  = 8;
+		var->transp.offset = 0; var->transp.length = 0;
+	} else
+		return -EINVAL;
+
+	/* Enough video memory? */
+	if (gx1_line_delta(var->xres, var->bits_per_pixel) * var->yres > info->fix.smem_len)
+		return -EINVAL;
+
+	/* FIXME: Check timing parameters here? */
+
+	return 0;
+}
+
+static int gx1fb_set_par(struct fb_info *info)
+{
+	struct geodefb_par *par = info->par;
+
+	if (info->var.bits_per_pixel == 16) {
+		info->fix.visual = FB_VISUAL_TRUECOLOR;
+		fb_dealloc_cmap(&info->cmap);
+	} else {
+		info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
+		fb_alloc_cmap(&info->cmap, 1<<info->var.bits_per_pixel, 0);
+	}
+
+	info->fix.line_length = gx1_line_delta(info->var.xres, info->var.bits_per_pixel);
+
+	par->dc_ops->set_mode(info);
+
+	return 0;
+}
+
+static inline u_int chan_to_field(u_int chan, struct fb_bitfield *bf)
+{
+	chan &= 0xffff;
+	chan >>= 16 - bf->length;
+	return chan << bf->offset;
+}
+
+static int gx1fb_setcolreg(unsigned regno, unsigned red, unsigned green,
+			   unsigned blue, unsigned transp,
+			   struct fb_info *info)
+{
+	struct geodefb_par *par = info->par;
+
+	if (info->var.grayscale) {
+		/* grayscale = 0.30*R + 0.59*G + 0.11*B */
+		red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8;
+	}
+
+	/* Truecolor has hardware independent palette */
+	if (info->fix.visual == FB_VISUAL_TRUECOLOR) {
+		u32 *pal = info->pseudo_palette;
+		u32 v;
+
+		if (regno >= 16)
+			return -EINVAL;
+
+		v  = chan_to_field(red, &info->var.red);
+		v |= chan_to_field(green, &info->var.green);
+		v |= chan_to_field(blue, &info->var.blue);
+
+		pal[regno] = v;
+	} else {
+		if (regno >= 256)
+			return -EINVAL;
+
+		par->dc_ops->set_palette_reg(info, regno, red, green, blue);
+	}
+
+	return 0;
+}
+
+static int gx1fb_blank(int blank_mode, struct fb_info *info)
+{
+	struct geodefb_par *par = info->par;
+
+	return par->vid_ops->blank_display(info, blank_mode);
+}
+
+static int __init gx1fb_map_video_memory(struct fb_info *info)
+{
+	struct geodefb_par *par = info->par;
+	unsigned gx_base;
+	int fb_len;
+
+	gx_base = gx1_gx_base();
+	if (!gx_base)
+		return -ENODEV;
+
+	par->vid_dev = pci_get_device(PCI_VENDOR_ID_CYRIX,
+				      PCI_DEVICE_ID_CYRIX_5530_VIDEO, NULL);
+	if (!par->vid_dev)
+		return -ENODEV;
+
+	par->vid_regs = ioremap(pci_resource_start(par->vid_dev, 1),
+				pci_resource_len(par->vid_dev, 1));
+	if (!par->vid_regs)
+		return -ENOMEM;
+
+	par->dc_regs = ioremap(gx_base + 0x8300, 0x100);
+	if (!par->dc_regs)
+		return -ENOMEM;
+
+	info->fix.smem_start = gx_base + 0x800000;
+	if ((fb_len = gx1_frame_buffer_size()) < 0)
+		return -ENOMEM;
+	info->fix.smem_len = fb_len;
+	info->screen_base = ioremap(info->fix.smem_start, info->fix.smem_len);
+	if (!info->screen_base)
+		return -ENOMEM;
+
+	printk(KERN_INFO "%s: %d Kibyte of video memory at 0x%lx\n",
+	       info->fix.id, info->fix.smem_len / 1024, info->fix.smem_start);
+
+	return 0;
+}
+
+static int parse_panel_option(struct fb_info *info)
+{
+	struct geodefb_par *par = info->par;
+
+	if (strcmp(panel_option, "") != 0) {
+		int x, y;
+		char *s;
+		x = simple_strtol(panel_option, &s, 10);
+		if (!x)
+			return -EINVAL;
+		y = simple_strtol(s + 1, NULL, 10);
+		if (!y)
+			return -EINVAL;
+		par->panel_x = x;
+		par->panel_y = y;
+	}
+	return 0;
+}
+
+static struct fb_ops gx1fb_ops = {
+	.owner		= THIS_MODULE,
+	.fb_check_var	= gx1fb_check_var,
+	.fb_set_par	= gx1fb_set_par,
+	.fb_setcolreg	= gx1fb_setcolreg,
+	.fb_blank       = gx1fb_blank,
+	/* No HW acceleration for now. */
+	.fb_fillrect	= cfb_fillrect,
+	.fb_copyarea	= cfb_copyarea,
+	.fb_imageblit	= cfb_imageblit,
+	.fb_cursor	= soft_cursor,
+};
+
+static struct fb_info * __init gx1fb_init_fbinfo(void)
+{
+	struct fb_info *info;
+	struct geodefb_par *par;
+
+	/* Alloc enough space for the pseudo palette. */
+	info = framebuffer_alloc(sizeof(struct geodefb_par) + sizeof(u32) * 16, NULL);
+	if (!info)
+		return NULL;
+
+	par = info->par;
+
+	strcpy(info->fix.id, "GX1");
+
+	info->fix.type		= FB_TYPE_PACKED_PIXELS;
+	info->fix.type_aux	= 0;
+	info->fix.xpanstep	= 0;
+	info->fix.ypanstep	= 0;
+	info->fix.ywrapstep	= 0;
+	info->fix.accel		= FB_ACCEL_NONE;
+
+	info->var.nonstd	= 0;
+	info->var.activate	= FB_ACTIVATE_NOW;
+	info->var.height	= -1;
+	info->var.width	= -1;
+	info->var.accel_flags = 0;
+	info->var.vmode	= FB_VMODE_NONINTERLACED;
+
+	info->fbops		= &gx1fb_ops;
+	info->flags		= FBINFO_DEFAULT;
+	info->node		= -1;
+
+	info->pseudo_palette	= (void *)par + sizeof(struct geodefb_par);
+
+	info->var.grayscale	= 0;
+
+	/* CRT and panel options */
+	par->enable_crt = crt_option;
+	if (parse_panel_option(info) < 0)
+		printk(KERN_WARNING "%s: invalid 'panel' option -- disabling flat panel\n",
+		       info->fix.id);
+	if (!par->panel_x)
+		par->enable_crt = 1; /* fall back to CRT if no panel is specified */
+
+	return info;
+}
+
+
+static struct fb_info *gx1fb_info;
+
+static int __init gx1fb_init(void)
+{
+	struct fb_info *info;
+        struct geodefb_par *par;
+	int ret;
+
+#ifndef MODULE
+	if (fb_get_options("gx1fb", NULL))
+		return -ENODEV;
+#endif
+
+	info = gx1fb_init_fbinfo();
+	if (!info)
+		return -ENOMEM;
+	gx1fb_info = info;
+
+	par = info->par;
+
+	/* GX1 display controller and CS5530 video device */
+	par->dc_ops  = &gx1_dc_ops;
+	par->vid_ops = &cs5530_vid_ops;
+
+	if ((ret = gx1fb_map_video_memory(info)) < 0) {
+		printk(KERN_ERR "%s: gx1fb_map_video_memory() failed\n", info->fix.id);
+		goto err;
+	}
+
+	ret = fb_find_mode(&info->var, info, mode_option, NULL, 0, NULL, 16);
+	if (ret == 0 || ret == 4) {
+		printk(KERN_ERR "%s: could not find valid video mode\n", info->fix.id);
+		ret = -EINVAL;
+		goto err;
+	}
+
+        /* Clear the frame buffer of garbage. */
+        memset_io(info->screen_base, 0, info->fix.smem_len);
+
+	gx1fb_check_var(&info->var, info);
+	gx1fb_set_par(info);
+
+	if (register_framebuffer(info) < 0) {
+		ret = -EINVAL;
+		goto err;
+	}
+	printk(KERN_INFO "fb%d: %s frame buffer device\n", info->node, info->fix.id);
+	return 0;
+
+  err:
+	if (info->screen_base)
+		iounmap(info->screen_base);
+	if (par->vid_regs)
+		iounmap(par->vid_regs);
+	if (par->dc_regs)
+		iounmap(par->dc_regs);
+	if (par->vid_dev)
+		pci_dev_put(par->vid_dev);
+	if (info)
+		framebuffer_release(info);
+	return ret;
+}
+
+static void __exit gx1fb_cleanup(void)
+{
+	struct fb_info *info = gx1fb_info;
+	struct geodefb_par *par = gx1fb_info->par;
+
+	unregister_framebuffer(info);
+
+	iounmap((void __iomem *)info->screen_base);
+	iounmap(par->vid_regs);
+	iounmap(par->dc_regs);
+
+	pci_dev_put(par->vid_dev);
+
+	framebuffer_release(info);
+}
+
+module_init(gx1fb_init);
+module_exit(gx1fb_cleanup);
+
+module_param_string(mode, mode_option, sizeof(mode_option), 0444);
+MODULE_PARM_DESC(mode, "video mode (<x>x<y>[-<bpp>][@<refr>])");
+
+module_param_named(crt, crt_option, int, 0444);
+MODULE_PARM_DESC(crt, "enable CRT output. 0 = off, 1 = on (default)");
+
+module_param_string(panel, panel_option, sizeof(panel_option), 0444);
+MODULE_PARM_DESC(panel, "size of attached flat panel (<x>x<y>)");
+
+MODULE_DESCRIPTION("framebuffer driver for the AMD Geode GX1");
+MODULE_LICENSE("GPL");
diff -Nru a/drivers/video/geode/video_cs5530.c b/drivers/video/geode/video_cs5530.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/video/geode/video_cs5530.c	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,195 @@
+/*
+ * drivers/video/geode/video_cs5530.c
+ *   -- CS5530 video device
+ *
+ * Copyright (C) 2005 Arcom Control Systems Ltd.
+ *
+ * Based on AMD's original 2.4 driver:
+ *   Copyright (C) 2004 Advanced Micro Devices, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+#include <linux/fb.h>
+#include <linux/delay.h>
+#include <asm/io.h>
+#include <asm/delay.h>
+
+#include "geodefb.h"
+#include "video_cs5530.h"
+
+/*
+ * CS5530 PLL table. This maps pixclocks to the appropriate PLL register
+ * value.
+ */
+struct cs5530_pll_entry {
+	long pixclock; /* ps */
+	u32 pll_value;
+};
+
+static const struct cs5530_pll_entry cs5530_pll_table[] = {
+	{ 39721, 0x31C45801, }, /*  25.1750 MHz */
+	{ 35308, 0x20E36802, }, /*  28.3220 */
+	{ 31746, 0x33915801, }, /*  31.5000 */
+	{ 27777, 0x31EC4801, }, /*  36.0000 */
+	{ 26666, 0x21E22801, }, /*  37.5000 */
+	{ 25000, 0x33088801, }, /*  40.0000 */
+	{ 22271, 0x33E22801, }, /*  44.9000 */
+	{ 20202, 0x336C4801, }, /*  49.5000 */
+	{ 20000, 0x23088801, }, /*  50.0000 */
+	{ 19860, 0x23088801, }, /*  50.3500 */
+	{ 18518, 0x3708A801, }, /*  54.0000 */
+	{ 17777, 0x23E36802, }, /*  56.2500 */
+	{ 17733, 0x23E36802, }, /*  56.3916 */
+	{ 17653, 0x23E36802, }, /*  56.6444 */
+	{ 16949, 0x37C45801, }, /*  59.0000 */
+	{ 15873, 0x23EC4801, }, /*  63.0000 */
+	{ 15384, 0x37911801, }, /*  65.0000 */
+	{ 14814, 0x37963803, }, /*  67.5000 */
+	{ 14124, 0x37058803, }, /*  70.8000 */
+	{ 13888, 0x3710C805, }, /*  72.0000 */
+	{ 13333, 0x37E22801, }, /*  75.0000 */
+	{ 12698, 0x27915801, }, /*  78.7500 */
+	{ 12500, 0x37D8D802, }, /*  80.0000 */
+	{ 11135, 0x27588802, }, /*  89.8000 */
+	{ 10582, 0x27EC4802, }, /*  94.5000 */
+	{ 10101, 0x27AC6803, }, /*  99.0000 */
+	{ 10000, 0x27088801, }, /* 100.0000 */
+	{  9259, 0x2710C805, }, /* 108.0000 */
+	{  8888, 0x27E36802, }, /* 112.5000 */
+	{  7692, 0x27C58803, }, /* 130.0000 */
+	{  7407, 0x27316803, }, /* 135.0000 */
+	{  6349, 0x2F915801, }, /* 157.5000 */
+	{  6172, 0x2F08A801, }, /* 162.0000 */
+	{  5714, 0x2FB11802, }, /* 175.0000 */
+	{  5291, 0x2FEC4802, }, /* 189.0000 */
+	{  4950, 0x2F963803, }, /* 202.0000 */
+	{  4310, 0x2FB1B802, }, /* 232.0000 */
+};
+
+#define NUM_CS5530_FREQUENCIES sizeof(cs5530_pll_table)/sizeof(struct cs5530_pll_entry)
+
+static void cs5530_set_dclk_frequency(struct fb_info *info)
+{
+	struct geodefb_par *par = info->par;
+	int i;
+	u32 value;
+	long min, diff;
+
+	/* Search the table for the closest pixclock. */
+	value = cs5530_pll_table[0].pll_value;
+	min = cs5530_pll_table[0].pixclock - info->var.pixclock;
+	if (min < 0) min = -min;
+	for (i = 1; i < NUM_CS5530_FREQUENCIES; i++) {
+		diff = cs5530_pll_table[i].pixclock - info->var.pixclock;
+		if (diff < 0L) diff = -diff;
+		if (diff < min) {
+			min = diff;
+			value = cs5530_pll_table[i].pll_value;
+		}
+	}
+
+	writel(value, par->vid_regs + CS5530_DOT_CLK_CONFIG);
+	writel(value | 0x80000100, par->vid_regs + CS5530_DOT_CLK_CONFIG); /* set reset and bypass */
+	udelay(500); /* wait for PLL to settle */
+	writel(value & 0x7FFFFFFF, par->vid_regs + CS5530_DOT_CLK_CONFIG); /* clear reset */
+	writel(value & 0x7FFFFEFF, par->vid_regs + CS5530_DOT_CLK_CONFIG); /* clear bypass */
+}
+
+static void cs5530_configure_display(struct fb_info *info)
+{
+	struct geodefb_par *par = info->par;
+	u32 dcfg;
+
+	dcfg = readl(par->vid_regs + CS5530_DISPLAY_CONFIG);
+
+	/* Clear bits from existing mode. */
+	dcfg &= ~(CS5530_DCFG_CRT_SYNC_SKW_MASK | CS5530_DCFG_PWR_SEQ_DLY_MASK
+		  | CS5530_DCFG_CRT_HSYNC_POL   | CS5530_DCFG_CRT_VSYNC_POL
+		  | CS5530_DCFG_FP_PWR_EN       | CS5530_DCFG_FP_DATA_EN
+		  | CS5530_DCFG_DAC_PWR_EN      | CS5530_DCFG_VSYNC_EN
+		  | CS5530_DCFG_HSYNC_EN);
+
+	/* Set default sync skew and power sequence delays.  */
+	dcfg |= (CS5530_DCFG_CRT_SYNC_SKW_INIT | CS5530_DCFG_PWR_SEQ_DLY_INIT
+		 | CS5530_DCFG_GV_PAL_BYP);
+
+	/* Enable DACs, hsync and vsync for CRTs */
+	if (par->enable_crt) {
+		dcfg |= CS5530_DCFG_DAC_PWR_EN;
+		dcfg |= CS5530_DCFG_HSYNC_EN | CS5530_DCFG_VSYNC_EN;
+	}
+	/* Enable panel power and data if using a flat panel. */
+	if (par->panel_x > 0) {
+		dcfg |= CS5530_DCFG_FP_PWR_EN;
+		dcfg |= CS5530_DCFG_FP_DATA_EN;
+	}
+
+	/* Sync polarities. */
+	if (info->var.sync & FB_SYNC_HOR_HIGH_ACT)
+		dcfg |= CS5530_DCFG_CRT_HSYNC_POL;
+	if (info->var.sync & FB_SYNC_VERT_HIGH_ACT)
+		dcfg |= CS5530_DCFG_CRT_VSYNC_POL;
+
+	writel(dcfg, par->vid_regs + CS5530_DISPLAY_CONFIG);
+}
+
+static int cs5530_blank_display(struct fb_info *info, int blank_mode)
+{
+	struct geodefb_par *par = info->par;
+	u32 dcfg;
+	int blank, hsync, vsync;
+
+	switch (blank_mode) {
+	case FB_BLANK_UNBLANK:
+		blank = 0; hsync = 1; vsync = 1;
+		break;
+	case FB_BLANK_NORMAL:
+		blank = 1; hsync = 1; vsync = 1;
+		break;
+	case FB_BLANK_VSYNC_SUSPEND:
+		blank = 1; hsync = 1; vsync = 0;
+		break;
+	case FB_BLANK_HSYNC_SUSPEND:
+		blank = 1; hsync = 0; vsync = 1;
+		break;
+	case FB_BLANK_POWERDOWN:
+		blank = 1; hsync = 0; vsync = 0;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	dcfg = readl(par->vid_regs + CS5530_DISPLAY_CONFIG);
+
+	dcfg &= ~(CS5530_DCFG_DAC_BL_EN | CS5530_DCFG_DAC_PWR_EN
+		  | CS5530_DCFG_HSYNC_EN | CS5530_DCFG_VSYNC_EN
+		  | CS5530_DCFG_FP_DATA_EN | CS5530_DCFG_FP_PWR_EN);
+
+	if (par->enable_crt) {
+		if (!blank)
+			dcfg |= CS5530_DCFG_DAC_BL_EN | CS5530_DCFG_DAC_PWR_EN;
+		if (hsync)
+			dcfg |= CS5530_DCFG_HSYNC_EN;
+		if (vsync)
+			dcfg |= CS5530_DCFG_VSYNC_EN;
+	}
+	if (par->panel_x > 0) {
+		if (!blank)
+			dcfg |= CS5530_DCFG_FP_DATA_EN;
+		if (hsync && vsync)
+			dcfg |= CS5530_DCFG_FP_PWR_EN;
+	}
+
+	writel(dcfg, par->vid_regs + CS5530_DISPLAY_CONFIG);
+
+	return 0;
+}
+
+struct geode_vid_ops cs5530_vid_ops = {
+	.set_dclk          = cs5530_set_dclk_frequency,
+	.configure_display = cs5530_configure_display,
+	.blank_display     = cs5530_blank_display,
+};
diff -Nru a/drivers/video/geode/video_cs5530.h b/drivers/video/geode/video_cs5530.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/video/geode/video_cs5530.h	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,75 @@
+/*
+ * drivers/video/geode/video_cs5530.h
+ *   -- CS5530 video device
+ *
+ * Copyright (C) 2005 Arcom Control Systems Ltd.
+ *
+ * Based on AMD's original 2.4 driver:
+ *   Copyright (C) 2004 Advanced Micro Devices, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+#ifndef __VIDEO_CS5530_H__
+#define __VIDEO_CS5530_H__
+
+extern struct geode_vid_ops cs5530_vid_ops;
+
+/* CS5530 Video device registers */
+
+#define CS5530_VIDEO_CONFIG	0x0000
+#  define CS5530_VCFG_VID_EN			0x00000001
+#  define CS5530_VCFG_VID_REG_UPDATE		0x00000002
+#  define CS5530_VCFG_VID_INP_FORMAT		0x0000000C
+#  define CS5530_VCFG_8_BIT_4_2_0		0x00000004
+#  define CS5530_VCFG_16_BIT_4_2_0		0x00000008
+#  define CS5530_VCFG_GV_SEL			0x00000010
+#  define CS5530_VCFG_CSC_BYPASS		0x00000020
+#  define CS5530_VCFG_X_FILTER_EN		0x00000040
+#  define CS5530_VCFG_Y_FILTER_EN		0x00000080
+#  define CS5530_VCFG_LINE_SIZE_LOWER_MASK	0x0000FF00
+#  define CS5530_VCFG_INIT_READ_MASK		0x01FF0000
+#  define CS5530_VCFG_EARLY_VID_RDY		0x02000000
+#  define CS5530_VCFG_LINE_SIZE_UPPER		0x08000000
+#  define CS5530_VCFG_4_2_0_MODE		0x10000000
+#  define CS5530_VCFG_16_BIT_EN			0x20000000
+#  define CS5530_VCFG_HIGH_SPD_INT		0x40000000
+
+#define CS5530_DISPLAY_CONFIG	0x0004
+#  define CS5530_DCFG_DIS_EN			0x00000001
+#  define CS5530_DCFG_HSYNC_EN			0x00000002
+#  define CS5530_DCFG_VSYNC_EN			0x00000004
+#  define CS5530_DCFG_DAC_BL_EN			0x00000008
+#  define CS5530_DCFG_DAC_PWR_EN		0x00000020
+#  define CS5530_DCFG_FP_PWR_EN			0x00000040
+#  define CS5530_DCFG_FP_DATA_EN		0x00000080
+#  define CS5530_DCFG_CRT_HSYNC_POL		0x00000100
+#  define CS5530_DCFG_CRT_VSYNC_POL		0x00000200
+#  define CS5530_DCFG_FP_HSYNC_POL		0x00000400
+#  define CS5530_DCFG_FP_VSYNC_POL		0x00000800
+#  define CS5530_DCFG_XGA_FP			0x00001000
+#  define CS5530_DCFG_FP_DITH_EN		0x00002000
+#  define CS5530_DCFG_CRT_SYNC_SKW_MASK		0x0001C000
+#  define CS5530_DCFG_CRT_SYNC_SKW_INIT		0x00010000
+#  define CS5530_DCFG_PWR_SEQ_DLY_MASK		0x000E0000
+#  define CS5530_DCFG_PWR_SEQ_DLY_INIT		0x00080000
+#  define CS5530_DCFG_VG_CK			0x00100000
+#  define CS5530_DCFG_GV_PAL_BYP		0x00200000
+#  define CS5530_DCFG_DDC_SCL			0x00400000
+#  define CS5530_DCFG_DDC_SDA			0x00800000
+#  define CS5530_DCFG_DDC_OE			0x01000000
+#  define CS5530_DCFG_16_BIT_EN			0x02000000
+
+#define CS5530_VIDEO_X_POS	0x0008
+#define CS5530_VIDEO_Y_POS	0x000C
+#define CS5530_VIDEO_SCALE	0x0010
+#define CS5530_VIDEO_COLOR_KEY	0x0014
+#define CS5530_VIDEO_COLOR_MASK 0x0018
+#define CS5530_PALETTE_ADDRESS	0x001C
+#define CS5530_PALETTE_DATA	0x0020
+#define CS5530_DOT_CLK_CONFIG	0x0024
+#define CS5530_CRCSIG_TFT_TV	0x0028
+
+#endif /* !__VIDEO_CS5530_H__ */
diff -Nru a/drivers/video/hgafb.c b/drivers/video/hgafb.c
--- a/drivers/video/hgafb.c	2005-03-11 12:51:50 -08:00
+++ b/drivers/video/hgafb.c	2005-03-11 12:51:50 -08:00
@@ -412,7 +412,8 @@
  *	A zero is returned on success and %-EINVAL for failure.
  */
 
-int hgafb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
+static int hgafb_pan_display(struct fb_var_screeninfo *var,
+			     struct fb_info *info)
 {
 	if (var->vmode & FB_VMODE_YWRAP) {
 		if (var->yoffset < 0 || 
@@ -548,7 +549,7 @@
 	 *  Initialization
 	 */
 
-int __init hgafb_init(void)
+static int __init hgafb_init(void)
 {
 	if (fb_get_options("hgafb", NULL))
 		return -ENODEV;
@@ -584,15 +585,6 @@
 
         printk(KERN_INFO "fb%d: %s frame buffer device\n",
                fb_info.node, fb_info.fix.id);
-	return 0;
-}
-
-	/*
-	 *  Setup
-	 */
-
-int __init hgafb_setup(char *options)
-{
 	return 0;
 }
 
diff -Nru a/drivers/video/hitfb.c b/drivers/video/hitfb.c
--- a/drivers/video/hitfb.c	2005-03-11 12:51:41 -08:00
+++ b/drivers/video/hitfb.c	2005-03-11 12:51:41 -08:00
@@ -1,6 +1,6 @@
 /*
- * $Id: hitfb.c,v 1.12 2004/03/16 00:07:51 lethal Exp $
  * linux/drivers/video/hitfb.c -- Hitachi LCD frame buffer device
+ *
  * (C) 1999 Mihai Spatar
  * (C) 2000 YAEGASHI Takeshi
  * (C) 2003, 2004 Paul Mundt
@@ -40,15 +40,15 @@
 static struct fb_var_screeninfo hitfb_var __initdata = {
 	.activate	= FB_ACTIVATE_NOW,
 	.height		= -1,
-	.width 		= -1,
-	.vmode 		= FB_VMODE_NONINTERLACED,
+	.width		= -1,
+	.vmode		= FB_VMODE_NONINTERLACED,
 };
 
 static struct fb_fix_screeninfo hitfb_fix __initdata = {
-	.id 		= "Hitachi HD64461",
-	.type 		= FB_TYPE_PACKED_PIXELS,
-	.ypanstep 	= 8,
-	.accel 		= FB_ACCEL_NONE,
+	.id		= "Hitachi HD64461",
+	.type		= FB_TYPE_PACKED_PIXELS,
+	.ypanstep	= 8,
+	.accel		= FB_ACCEL_NONE,
 };
 
 static u32 pseudo_palette[16];
@@ -255,14 +255,14 @@
 }
 
 static struct fb_ops hitfb_ops = {
-	.owner 			= THIS_MODULE,
-	.fb_setcolreg 	= hitfb_setcolreg,
-	.fb_blank 		= hitfb_blank,
+	.owner		= THIS_MODULE,
+	.fb_setcolreg	= hitfb_setcolreg,
+	.fb_blank	= hitfb_blank,
 	.fb_pan_display = hitfb_pan_display,
-	.fb_fillrect 	= hitfb_fillrect,
-	.fb_copyarea 	= hitfb_copyarea,
-	.fb_imageblit 	= cfb_imageblit,
-	.fb_cursor 		= soft_cursor,
+	.fb_fillrect	= hitfb_fillrect,
+	.fb_copyarea	= hitfb_copyarea,
+	.fb_imageblit	= cfb_imageblit,
+	.fb_cursor	= soft_cursor,
 };
 
 int __init hitfb_init(void)
@@ -324,7 +324,7 @@
 	fb_info.var = hitfb_var;
 	fb_info.fix = hitfb_fix;
 	fb_info.pseudo_palette = pseudo_palette;
-	fb_info.flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
+	fb_info.flags = FBINFO_DEFAULT;
 
 	fb_info.screen_base = (void *)hitfb_fix.smem_start;
 
@@ -345,9 +345,6 @@
 }
 
 module_init(hitfb_init);
-
-#ifdef MODULE
 module_exit(hitfb_exit);
-#endif
 
 MODULE_LICENSE("GPL");
diff -Nru a/drivers/video/i810/i810_main.c b/drivers/video/i810/i810_main.c
--- a/drivers/video/i810/i810_main.c	2005-03-11 12:51:42 -08:00
+++ b/drivers/video/i810/i810_main.c	2005-03-11 12:51:42 -08:00
@@ -1591,40 +1591,41 @@
 {
 	struct i810fb_par *par = (struct i810fb_par *) info->par;
 	int size;
+	struct agp_bridge_data *bridge;
 	
 	i810_fix_offsets(par);
 	size = par->fb.size + par->iring.size;
 
-	if (agp_backend_acquire()) {
+	if (!(bridge = agp_backend_acquire(par->dev))) {
 		printk("i810fb_alloc_fbmem: cannot acquire agpgart\n");
 		return -ENODEV;
 	}
 	if (!(par->i810_gtt.i810_fb_memory = 
-	      agp_allocate_memory(size >> 12, AGP_NORMAL_MEMORY))) {
+	      agp_allocate_memory(bridge, size >> 12, AGP_NORMAL_MEMORY))) {
 		printk("i810fb_alloc_fbmem: can't allocate framebuffer "
 		       "memory\n");
-		agp_backend_release();
+		agp_backend_release(bridge);
 		return -ENOMEM;
 	}
 	if (agp_bind_memory(par->i810_gtt.i810_fb_memory,
 			    par->fb.offset)) {
 		printk("i810fb_alloc_fbmem: can't bind framebuffer memory\n");
-		agp_backend_release();
+		agp_backend_release(bridge);
 		return -EBUSY;
 	}	
 	
 	if (!(par->i810_gtt.i810_cursor_memory = 
-	      agp_allocate_memory(par->cursor_heap.size >> 12,
+	      agp_allocate_memory(bridge, par->cursor_heap.size >> 12,
 				  AGP_PHYSICAL_MEMORY))) {
 		printk("i810fb_alloc_cursormem:  can't allocate" 
 		       "cursor memory\n");
-		agp_backend_release();
+		agp_backend_release(bridge);
 		return -ENOMEM;
 	}
 	if (agp_bind_memory(par->i810_gtt.i810_cursor_memory,
 			    par->cursor_heap.offset)) {
 		printk("i810fb_alloc_cursormem: cannot bind cursor memory\n");
-		agp_backend_release();
+		agp_backend_release(bridge);
 		return -EBUSY;
 	}	
 
@@ -1632,7 +1633,7 @@
 
 	i810_fix_pointers(par);
 
-	agp_backend_release();
+	agp_backend_release(bridge);
 
 	return 0;
 }
@@ -1994,7 +1995,7 @@
 
 #ifdef MODULE
 
-int __init i810fb_init(void)
+static int __init i810fb_init(void)
 {
 	hsync1 *= 1000;
 	hsync2 *= 1000;
diff -Nru a/drivers/video/imsttfb.c b/drivers/video/imsttfb.c
--- a/drivers/video/imsttfb.c	2005-03-11 12:51:46 -08:00
+++ b/drivers/video/imsttfb.c	2005-03-11 12:51:46 -08:00
@@ -228,7 +228,7 @@
 	__u8 addr, value;
 };
 
-static struct initvalues ibm_initregs[] __initdata = {
+static struct initvalues ibm_initregs[] __devinitdata = {
 	{ CLKCTL,	0x21 },
 	{ SYNCCTL,	0x00 },
 	{ HSYNCPOS,	0x00 },
@@ -275,7 +275,7 @@
 	{ KEYCTL,	0x00 }
 };
 
-static struct initvalues tvp_initregs[] __initdata = {
+static struct initvalues tvp_initregs[] __devinitdata = {
 	{ TVPIRICC,	0x00 },
 	{ TVPIRBRC,	0xe4 },
 	{ TVPIRLAC,	0x06 },
@@ -338,7 +338,7 @@
 static int inverse = 0;
 static char fontname[40] __initdata = { 0 };
 #if defined(CONFIG_PPC)
-static signed char init_vmode __initdata = -1, init_cmode __initdata = -1;
+static signed char init_vmode __devinitdata = -1, init_cmode __devinitdata = -1;
 #endif
 
 static struct imstt_regvals tvp_reg_init_2 = {
@@ -1348,7 +1348,7 @@
 	.fb_ioctl 	= imsttfb_ioctl,
 };
 
-static void __init 
+static void __devinit
 init_imstt(struct fb_info *info)
 {
 	struct imstt_par *par = (struct imstt_par *) info->par;
@@ -1547,7 +1547,7 @@
 }
 
 #ifndef MODULE
-int __init 
+static int __init
 imsttfb_setup(char *options)
 {
 	char *this_opt;
@@ -1601,7 +1601,7 @@
 
 #endif /* MODULE */
 
-int __init imsttfb_init(void)
+static int __init imsttfb_init(void)
 {
 #ifndef MODULE
 	char *option = NULL;
@@ -1619,9 +1619,8 @@
 	pci_unregister_driver(&imsttfb_pci_driver);
 }
 
-#ifdef MODULE
 MODULE_LICENSE("GPL");
-#endif
+
 module_init(imsttfb_init);
 module_exit(imsttfb_exit);
 
diff -Nru a/drivers/video/intelfb/intelfb.h b/drivers/video/intelfb/intelfb.h
--- a/drivers/video/intelfb/intelfb.h	2005-03-11 12:51:46 -08:00
+++ b/drivers/video/intelfb/intelfb.h	2005-03-11 12:51:46 -08:00
@@ -10,7 +10,7 @@
 /*** Version/name ***/
 #define INTELFB_VERSION			"0.9.2"
 #define INTELFB_MODULE_NAME		"intelfb"
-#define SUPPORTED_CHIPSETS		"830M/845G/852GM/855GM/865G"
+#define SUPPORTED_CHIPSETS		"830M/845G/852GM/855GM/865G/915G"
 
 
 /*** Debug/feature defines ***/
@@ -36,7 +36,7 @@
 #endif
 
 #ifndef PREFERRED_MODE
-#define PREFERRED_MODE			"1024x768-16@60"
+#define PREFERRED_MODE			"1024x768-32@70"
 #endif
 
 /*** hw-related values ***/
@@ -46,6 +46,7 @@
 #define PCI_DEVICE_ID_INTEL_845G	0x2562
 #define PCI_DEVICE_ID_INTEL_85XGM	0x3582
 #define PCI_DEVICE_ID_INTEL_865G	0x2572
+#define PCI_DEVICE_ID_INTEL_915G	0x2582
 
 /* Size of MMIO region */
 #define INTEL_REG_SIZE			0x80000
@@ -117,7 +118,8 @@
 	INTEL_852GME,
 	INTEL_855GM,
 	INTEL_855GME,
-	INTEL_865G
+	INTEL_865G,
+	INTEL_915G
 };
 
 struct intelfb_hwstate {
diff -Nru a/drivers/video/intelfb/intelfbdrv.c b/drivers/video/intelfb/intelfbdrv.c
--- a/drivers/video/intelfb/intelfbdrv.c	2005-03-11 12:51:47 -08:00
+++ b/drivers/video/intelfb/intelfbdrv.c	2005-03-11 12:51:47 -08:00
@@ -1,7 +1,7 @@
 /*
  * intelfb
  *
- * Linux framebuffer driver for Intel(R) 830M/845G/852GM/855GM/865G
+ * Linux framebuffer driver for Intel(R) 830M/845G/852GM/855GM/865G/915G
  * integrated graphics chips.
  *
  * Copyright © 2002, 2003 David Dawes <dawes@xfree86.org>
@@ -153,6 +153,7 @@
 	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_845G, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_845G },
 	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_85XGM, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_85XGM },
 	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_865G, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_865G },
+	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_915G, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_915G },
 	{ 0, }
 };
 
@@ -226,42 +227,6 @@
 module_param(mode, charp, S_IRUGO);
 MODULE_PARM_DESC(mode,
 		 "Initial video mode \"<xres>x<yres>[-<depth>][@<refresh>]\"");
-/***************************************************************
- *                     modules entry points                    *
- ***************************************************************/
-
-/* module load/unload entry points */
-int __init
-intelfb_init(void)
-{
-#ifndef MODULE
-	char *option = NULL;
-#endif
-
-	DBG_MSG("intelfb_init\n");
-
-	INF_MSG("Framebuffer driver for "
-		"Intel(R) " SUPPORTED_CHIPSETS " chipsets\n");
-	INF_MSG("Version " INTELFB_VERSION "\n");
-
-	if (idonly)
-		return -ENODEV;
-
-#ifndef MODULE
-	if (fb_get_options("intelfb", &option))
-		return -ENODEV;
-	intelfb_setup(option);
-#endif
-
-	return pci_module_init(&intelfb_driver);
-}
-
-static void __exit
-intelfb_exit(void)
-{
-	DBG_MSG("intelfb_exit\n");
-	pci_unregister_driver(&intelfb_driver);
-}
 
 #ifndef MODULE
 #define OPT_EQUAL(opt, name) (!strncmp(opt, name, strlen(name)))
@@ -321,7 +286,7 @@
 	return 1;
 }
 
-int __init
+static int __init
 intelfb_setup(char *options)
 {
 	char *this_opt;
@@ -373,12 +338,41 @@
 
 #endif
 
-module_init(intelfb_init);
+static int __init
+intelfb_init(void)
+{
+#ifndef MODULE
+	char *option = NULL;
+#endif
 
-#ifdef MODULE
-module_exit(intelfb_exit);
+	DBG_MSG("intelfb_init\n");
+
+	INF_MSG("Framebuffer driver for "
+		"Intel(R) " SUPPORTED_CHIPSETS " chipsets\n");
+	INF_MSG("Version " INTELFB_VERSION "\n");
+
+	if (idonly)
+		return -ENODEV;
+
+#ifndef MODULE
+	if (fb_get_options("intelfb", &option))
+		return -ENODEV;
+	intelfb_setup(option);
 #endif
 
+	return pci_module_init(&intelfb_driver);
+}
+
+static void __exit
+intelfb_exit(void)
+{
+	DBG_MSG("intelfb_exit\n");
+	pci_unregister_driver(&intelfb_driver);
+}
+
+module_init(intelfb_init);
+module_exit(intelfb_exit);
+
 /***************************************************************
  *                     mtrr support functions                  *
  ***************************************************************/
@@ -470,6 +464,9 @@
 	struct agp_kern_info gtt_info;
 	int agp_memtype;
 	const char *s;
+	struct agp_bridge_data *bridge;
+ 	int aperture_bar = 0;
+ 	int mmio_bar = 1;
 
 	DBG_MSG("intelfb_pci_register\n");
 
@@ -516,13 +513,20 @@
 	}
 
 	/* Set base addresses. */
-	dinfo->aperture.physical = pci_resource_start(pdev, 0);
-	dinfo->aperture.size     = pci_resource_len(pdev, 0);
-	dinfo->mmio_base_phys    = pci_resource_start(pdev, 1);
-
-	DBG_MSG("fb aperture: 0x%lx/0x%lx, MMIO region: 0x%lx/0x%lx\n",
-		pci_resource_start(pdev, 0), pci_resource_len(pdev, 0),
-		pci_resource_start(pdev, 1), pci_resource_len(pdev, 1));
+	if (ent->device == PCI_DEVICE_ID_INTEL_915G) {
+		aperture_bar = 2;
+		mmio_bar = 0;
+		/* Disable HW cursor on 915G (not implemented yet) */
+		hwcursor = 0;
+	}
+	dinfo->aperture.physical = pci_resource_start(pdev, aperture_bar);
+	dinfo->aperture.size     = pci_resource_len(pdev, aperture_bar);
+	dinfo->mmio_base_phys    = pci_resource_start(pdev, mmio_bar);
+	DBG_MSG("fb aperture: 0x%llx/0x%llx, MMIO region: 0x%llx/0x%llx\n",
+		(unsigned long long)pci_resource_start(pdev, aperture_bar),
+		(unsigned long long)pci_resource_len(pdev, aperture_bar),
+		(unsigned long long)pci_resource_start(pdev, mmio_bar),
+		(unsigned long long)pci_resource_len(pdev, mmio_bar));
 
 	/* Reserve the fb and MMIO regions */
 	if (!request_mem_region(dinfo->aperture.physical, dinfo->aperture.size,
@@ -605,16 +609,16 @@
 	}
 
 	/* Use agpgart to manage the GATT */
-	if (agp_backend_acquire()) {
+	if (!(bridge = agp_backend_acquire(pdev))) {
 		ERR_MSG("cannot acquire agp\n");
 		cleanup(dinfo);
 		return -ENODEV;
 	}
 
 	/* get the current gatt info */
-	if (agp_copy_info(&gtt_info)) {
+	if (agp_copy_info(bridge, &gtt_info)) {
 		ERR_MSG("cannot get agp info\n");
-		agp_backend_release();
+		agp_backend_release(bridge);
 		cleanup(dinfo);
 		return -ENODEV;
 	}
@@ -637,17 +641,17 @@
 	/* Allocate memories (which aren't stolen) */
 	if (dinfo->accel) {
 		if (!(dinfo->gtt_ring_mem =
-		      agp_allocate_memory(dinfo->ring.size >> 12,
+		      agp_allocate_memory(bridge, dinfo->ring.size >> 12,
 					  AGP_NORMAL_MEMORY))) {
 			ERR_MSG("cannot allocate ring buffer memory\n");
-			agp_backend_release();
+			agp_backend_release(bridge);
 			cleanup(dinfo);
 			return -ENOMEM;
 		}
 		if (agp_bind_memory(dinfo->gtt_ring_mem,
 				    dinfo->ring.offset)) {
 			ERR_MSG("cannot bind ring buffer memory\n");
-			agp_backend_release();
+			agp_backend_release(bridge);
 			cleanup(dinfo);
 			return -EBUSY;
 		}
@@ -661,17 +665,17 @@
 		agp_memtype = dinfo->mobile ? AGP_PHYSICAL_MEMORY
 			: AGP_NORMAL_MEMORY;
 		if (!(dinfo->gtt_cursor_mem =
-		      agp_allocate_memory(dinfo->cursor.size >> 12,
+		      agp_allocate_memory(bridge, dinfo->cursor.size >> 12,
 					  agp_memtype))) {
 			ERR_MSG("cannot allocate cursor memory\n");
-			agp_backend_release();
+			agp_backend_release(bridge);
 			cleanup(dinfo);
 			return -ENOMEM;
 		}
 		if (agp_bind_memory(dinfo->gtt_cursor_mem,
 				    dinfo->cursor.offset)) {
 			ERR_MSG("cannot bind cursor memory\n");
-			agp_backend_release();
+			agp_backend_release(bridge);
 			cleanup(dinfo);
 			return -EBUSY;
 		}
@@ -686,7 +690,7 @@
 	}
 	if (dinfo->fbmem_gart) {
 		if (!(dinfo->gtt_fb_mem =
-		      agp_allocate_memory(dinfo->fb.size >> 12,
+		      agp_allocate_memory(bridge, dinfo->fb.size >> 12,
 					  AGP_NORMAL_MEMORY))) {
 			WRN_MSG("cannot allocate framebuffer memory - use "
 				"the stolen one\n");
@@ -709,7 +713,7 @@
 	dinfo->fb_start = dinfo->fb.offset << 12;
 
 	/* release agpgart */
-	agp_backend_release();
+	agp_backend_release(bridge);
 
 	if (mtrr)
 		set_mtrr(dinfo);
@@ -989,13 +993,15 @@
 	} else {
 		if (mode) {
 			msrc = fb_find_mode(var, dinfo->info, mode,
-					    NULL, 0, NULL, 0);
+					    vesa_modes, VESA_MODEDB_SIZE,
+					    NULL, 0);
 			if (msrc)
 				msrc |= 8;
 		}
 		if (!msrc) {
 			msrc = fb_find_mode(var, dinfo->info, PREFERRED_MODE,
-					    NULL, 0, NULL, 0);
+					    vesa_modes, VESA_MODEDB_SIZE,
+					    NULL, 0);
 		}
 	}
 
diff -Nru a/drivers/video/intelfb/intelfbdrv.h b/drivers/video/intelfb/intelfbdrv.h
--- a/drivers/video/intelfb/intelfbdrv.h	2005-03-11 12:51:46 -08:00
+++ b/drivers/video/intelfb/intelfbdrv.h	2005-03-11 12:51:46 -08:00
@@ -5,7 +5,7 @@
  ******************************************************************************
  * intelfb
  *
- * Linux framebuffer driver for Intel(R) 830M/845G/852GM/855GM/865G
+ * Linux framebuffer driver for Intel(R) 830M/845G/852GM/855GM/865G/915G
  * integrated graphics chips.
  *
  * Copyright © 2004 Sylvain Meyer
@@ -28,7 +28,7 @@
  *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
-int __init intelfb_setup(char *options);
+static int __init intelfb_setup(char *options);
 static void __devinit get_initial_mode(struct intelfb_info *dinfo);
 static void update_dinfo(struct intelfb_info *dinfo,
 			 struct fb_var_screeninfo *var);
diff -Nru a/drivers/video/intelfb/intelfbhw.c b/drivers/video/intelfb/intelfbhw.c
--- a/drivers/video/intelfb/intelfbhw.c	2005-03-11 12:51:41 -08:00
+++ b/drivers/video/intelfb/intelfbhw.c	2005-03-11 12:51:41 -08:00
@@ -98,6 +98,11 @@
 		*chipset = INTEL_865G;
 		*mobile = 0;
 		return 0;
+	case PCI_DEVICE_ID_INTEL_915G:
+		*name = "Intel(R) 915G";
+		*chipset = INTEL_915G;
+		*mobile = 0;
+		return 0;
 	default:
 		return 1;
 	}
@@ -168,6 +173,12 @@
 			return 0;
 		case INTEL_855_GMCH_GMS_STOLEN_32M:
 			*stolen_size = MB(32) - KB(132);
+			return 0;
+		case INTEL_915G_GMCH_GMS_STOLEN_48M:
+			*stolen_size = MB(48) - KB(132);
+			return 0;
+		case INTEL_915G_GMCH_GMS_STOLEN_64M:
+			*stolen_size = MB(64) - KB(132);
 			return 0;
 		case INTEL_855_GMCH_GMS_DISABLED:
 			ERR_MSG("video memory is disabled\n");
diff -Nru a/drivers/video/intelfb/intelfbhw.h b/drivers/video/intelfb/intelfbhw.h
--- a/drivers/video/intelfb/intelfbhw.h	2005-03-11 12:51:40 -08:00
+++ b/drivers/video/intelfb/intelfbhw.h	2005-03-11 12:51:40 -08:00
@@ -46,6 +46,9 @@
 #define INTEL_855_GMCH_GMS_STOLEN_16M	(0x4 << 4)
 #define INTEL_855_GMCH_GMS_STOLEN_32M	(0x5 << 4)
 
+#define INTEL_915G_GMCH_GMS_STOLEN_48M	(0x6 << 4)
+#define INTEL_915G_GMCH_GMS_STOLEN_64M	(0x7 << 4)
+
 /* HW registers */
 
 /* Fence registers */
diff -Nru a/drivers/video/kyro/fbdev.c b/drivers/video/kyro/fbdev.c
--- a/drivers/video/kyro/fbdev.c	2005-03-11 12:51:41 -08:00
+++ b/drivers/video/kyro/fbdev.c	2005-03-11 12:51:41 -08:00
@@ -1,5 +1,5 @@
 /*
- *  linux/drivers/video/kyro/kyrofb.c
+ *  linux/drivers/video/kyro/fbdev.c
  *
  *  Copyright (C) 2002 STMicroelectronics
  *  Copyright (C) 2003, 2004 Paul Mundt
@@ -43,14 +43,14 @@
 #define KHZ2PICOS(a) (1000000000UL/(a))
 
 /****************************************************************************/
-static struct fb_fix_screeninfo kyro_fix __initdata = {
+static struct fb_fix_screeninfo kyro_fix __devinitdata = {
 	.id		= "ST Kyro",
 	.type		= FB_TYPE_PACKED_PIXELS,
 	.visual		= FB_VISUAL_TRUECOLOR,
 	.accel		= FB_ACCEL_NONE,
 };
 
-static struct fb_var_screeninfo kyro_var __initdata = {
+static struct fb_var_screeninfo kyro_var __devinitdata = {
 	/* 640x480, 16bpp @ 60 Hz */
 	.xres		= 640,
 	.yres		= 480,
@@ -86,18 +86,18 @@
 /* global graphics card info structure (one per card) */
 static device_info_t deviceInfo;
 
-static char *mode_option __initdata = NULL;
-static int nopan __initdata = 0;
-static int nowrap __initdata = 1;
+static char *mode_option __devinitdata = NULL;
+static int nopan __devinitdata = 0;
+static int nowrap __devinitdata = 1;
 #ifdef CONFIG_MTRR
-static int nomtrr __initdata = 0;
+static int nomtrr __devinitdata = 0;
 #endif
 
 /* PCI driver prototypes */
 static int kyrofb_probe(struct pci_dev *pdev, const struct pci_device_id *ent);
 static void kyrofb_remove(struct pci_dev *pdev);
 
-static struct fb_videomode kyro_modedb[] __initdata = {
+static struct fb_videomode kyro_modedb[] __devinitdata = {
 	{
 		/* 640x350 @ 85Hz */
 		NULL, 85, 640, 350, KHZ2PICOS(31500),
@@ -594,7 +594,8 @@
 
 	switch (cmd) {
 	case KYRO_IOCTL_OVERLAY_CREATE:
-		copy_from_user(&ol_create, argp, sizeof(overlay_create));
+		if (copy_from_user(&ol_create, argp, sizeof(overlay_create)))
+			return -EFAULT;
 
 		if (kyro_dev_overlay_create(ol_create.ulWidth,
 					    ol_create.ulHeight, 0) < 0) {
@@ -604,8 +605,9 @@
 		}
 		break;
 	case KYRO_IOCTL_OVERLAY_VIEWPORT_SET:
-		copy_from_user(&ol_viewport_set, argp,
-			       sizeof(overlay_viewport_set));
+		if (copy_from_user(&ol_viewport_set, argp,
+			       sizeof(overlay_viewport_set)))
+			return -EFAULT;
 
 		if (kyro_dev_overlay_viewport_set(ol_viewport_set.xOrgin,
 						  ol_viewport_set.yOrgin,
@@ -625,13 +627,16 @@
 		}
 		break;
 	case KYRO_IOCTL_UVSTRIDE:
-		copy_to_user(argp, &deviceInfo.ulOverlayUVStride, sizeof(unsigned long));
+		if (copy_to_user(argp, &deviceInfo.ulOverlayUVStride, sizeof(unsigned long)))
+			return -EFAULT;
 		break;
 	case KYRO_IOCTL_STRIDE:
-		copy_to_user(argp, &deviceInfo.ulOverlayStride, sizeof(unsigned long));
+		if (copy_to_user(argp, &deviceInfo.ulOverlayStride, sizeof(unsigned long)))
+			return -EFAULT;
 		break;
 	case KYRO_IOCTL_OVERLAY_OFFSET:
-		copy_to_user(argp, &deviceInfo.ulOverlayOffset, sizeof(unsigned long));
+		if (copy_to_user(argp, &deviceInfo.ulOverlayOffset, sizeof(unsigned long)))
+			return -EFAULT;
 		break;
 	}
 
diff -Nru a/drivers/video/logo/Kconfig b/drivers/video/logo/Kconfig
--- a/drivers/video/logo/Kconfig	2005-03-11 12:51:42 -08:00
+++ b/drivers/video/logo/Kconfig	2005-03-11 12:51:42 -08:00
@@ -25,7 +25,7 @@
 
 config LOGO_DEC_CLUT224
 	bool "224-color Digital Equipment Corporation Linux logo"
-	depends on LOGO && MACH_DECSTATION
+	depends on LOGO && (MACH_DECSTATION || ALPHA)
 	default y
 
 config LOGO_MAC_CLUT224
diff -Nru a/drivers/video/logo/Makefile b/drivers/video/logo/Makefile
--- a/drivers/video/logo/Makefile	2005-03-11 12:51:47 -08:00
+++ b/drivers/video/logo/Makefile	2005-03-11 12:51:47 -08:00
@@ -23,35 +23,32 @@
 # Mono logos
 extra-y += $(call logo-cfiles,_mono,pbm)
 
-quiet_cmd_logo_mono    = MONO    $@
-      cmd_logo_mono    = scripts/pnmtologo -t mono -n $*_mono -o $@ $<
-
-$(obj)/%_mono.c: $(src)/%_mono.pbm FORCE
-	$(call if_changed,logo_mono)
-
 # VGA16 logos
 extra-y += $(call logo-cfiles,_vga16,ppm)
 
-quiet_cmd_logo_vga16   = VGA16   $@
-      cmd_logo_vga16   = scripts/pnmtologo -t vga16 -n $*_vga16 -o $@ $<
-
-$(obj)/%_vga16.c: $(src)/%_vga16.ppm FORCE
-	$(call if_changed,logo_vga16)
-
-#224 Logos
+# 224 Logos
 extra-y += $(call logo-cfiles,_clut224,ppm)
 
-quiet_cmd_logo_clut224 = CLUT224 $@
-      cmd_logo_clut224 = scripts/pnmtologo -t clut224 -n $*_clut224 -o $@ $<
-
-$(obj)/%_clut224.c: $(src)/%_clut224.ppm FORCE
-	$(call if_changed,logo_clut224)
-
 # Gray 256
 extra-y += $(call logo-cfiles,_gray256,pgm)
 
-quiet_cmd_logo_gray256 = GRAY256 $@
-      cmd_logo_gray256 = scripts/pnmtologo -t gray256 -n $*_gray256 -o $@ $<
+# Create commands like "pnmtologo -t mono -n logo_mac_mono -o ..."
+quiet_cmd_logo = LOGO	$@
+	cmd_logo = scripts/pnmtologo \
+			-t $(patsubst $*_%,%,$(notdir $(basename $<))) \
+			-n $(notdir $(basename $<)) -o $@ $<
+
+$(obj)/%_mono.c: $(src)/%_mono.pbm FORCE
+	$(call if_changed,logo)
+
+$(obj)/%_vga16.c: $(src)/%_vga16.ppm FORCE
+	$(call if_changed,logo)
+
+$(obj)/%_clut224.c: $(src)/%_clut224.ppm FORCE
+	$(call if_changed,logo)
 
 $(obj)/%_gray256.c: $(src)/%_gray256.pgm FORCE
-	$(call if_changed,logo_gray256)
+	$(call if_changed,logo)
+
+# Files generated that shall be removed upon make clean
+clean-files := *.o *_mono.c *_vga16.c *_clut224.c *_gray256.c
diff -Nru a/drivers/video/logo/logo.c b/drivers/video/logo/logo.c
--- a/drivers/video/logo/logo.c	2005-03-11 12:51:47 -08:00
+++ b/drivers/video/logo/logo.c	2005-03-11 12:51:47 -08:00
@@ -12,6 +12,7 @@
 #include <linux/config.h>
 #include <linux/linux_logo.h>
 #include <linux/stddef.h>
+#include <linux/module.h>
 
 #ifdef CONFIG_M68K
 #include <asm/setup.h>
@@ -66,8 +67,10 @@
 		logo = &logo_linux_clut224;
 #endif
 #ifdef CONFIG_LOGO_DEC_CLUT224
-		/* DEC Linux logo on MIPS/MIPS64 */
+		/* DEC Linux logo on MIPS/MIPS64 or ALPHA */
+#ifndef CONFIG_ALPHA
 		if (mips_machgroup == MACH_GROUP_DEC)
+#endif
 			logo = &logo_dec_clut224;
 #endif
 #ifdef CONFIG_LOGO_MAC_CLUT224
@@ -97,4 +100,4 @@
 	}
 	return logo;
 }
-
+EXPORT_SYMBOL_GPL(fb_find_logo);
diff -Nru a/drivers/video/modedb.c b/drivers/video/modedb.c
--- a/drivers/video/modedb.c	2005-03-11 12:51:46 -08:00
+++ b/drivers/video/modedb.c	2005-03-11 12:51:46 -08:00
@@ -722,6 +722,47 @@
 }
 
 /**
+ * fb_find_nearest_mode - find mode closest video mode
+ *
+ * @var: pointer to struct fb_var_screeninfo
+ * @head: pointer to modelist
+ *
+ * Finds best matching videomode, smaller or greater in dimension.
+ * If more than 1 videomode is found, will return the videomode with
+ * the closest refresh rate
+ */
+struct fb_videomode *fb_find_nearest_mode(struct fb_var_screeninfo *var,
+					  struct list_head *head)
+{
+	struct list_head *pos;
+	struct fb_modelist *modelist;
+	struct fb_videomode *mode, *best = NULL;
+	u32 diff = -1, diff_refresh = -1;
+
+	list_for_each(pos, head) {
+		u32 d;
+
+		modelist = list_entry(pos, struct fb_modelist, list);
+		mode = &modelist->mode;
+
+		d = abs(mode->xres - var->xres) +
+			abs(mode->yres - var->yres);
+		if (diff > d) {
+			diff = d;
+			best = mode;
+		} else if (diff == d) {
+			d = abs(mode->refresh - best->refresh);
+			if (diff_refresh > d) {
+				diff_refresh = d;
+				best = mode;
+			}
+		}
+	}
+
+	return best;
+}
+
+/**
  * fb_match_mode - find a videomode which exactly matches the timings in var
  * @var: pointer to struct fb_var_screeninfo
  * @head: pointer to struct list_head of modelist
@@ -846,5 +887,6 @@
 EXPORT_SYMBOL(fb_destroy_modelist);
 EXPORT_SYMBOL(fb_match_mode);
 EXPORT_SYMBOL(fb_find_best_mode);
+EXPORT_SYMBOL(fb_find_nearest_mode);
 EXPORT_SYMBOL(fb_videomode_to_modelist);
 EXPORT_SYMBOL(fb_find_mode);
diff -Nru a/drivers/video/neofb.c b/drivers/video/neofb.c
--- a/drivers/video/neofb.c	2005-03-11 12:51:47 -08:00
+++ b/drivers/video/neofb.c	2005-03-11 12:51:47 -08:00
@@ -93,7 +93,7 @@
 static int libretto;
 static int nostretch;
 static int nopciburst;
-static char *mode_option __initdata = NULL;
+static char *mode_option __devinitdata = NULL;
 
 #ifdef MODULE
 
@@ -400,21 +400,21 @@
  */
 static int paletteEnabled = 0;
 
-inline void VGAenablePalette(void)
+static inline void VGAenablePalette(void)
 {
 	vga_r(NULL, VGA_IS1_RC);
 	vga_w(NULL, VGA_ATT_W, 0x00);
 	paletteEnabled = 1;
 }
 
-inline void VGAdisablePalette(void)
+static inline void VGAdisablePalette(void)
 {
 	vga_r(NULL, VGA_IS1_RC);
 	vga_w(NULL, VGA_ATT_W, 0x20);
 	paletteEnabled = 0;
 }
 
-inline void VGAwATTR(u8 index, u8 value)
+static inline void VGAwATTR(u8 index, u8 value)
 {
 	if (paletteEnabled)
 		index &= ~0x20;
@@ -425,7 +425,7 @@
 	vga_wattr(NULL, index, value);
 }
 
-void vgaHWProtect(int on)
+static void vgaHWProtect(int on)
 {
 	unsigned char tmp;
 
@@ -1315,7 +1315,7 @@
 /*
  *    (Un)Blank the display.
  */
-int neofb_blank(int blank_mode, struct fb_info *info)
+static int neofb_blank(int blank_mode, struct fb_info *info)
 {
 	/*
 	 *  Blank the screen if blank_mode != 0, else unblank.
@@ -2230,7 +2230,8 @@
 
 /* ************************* init in-kernel code ************************** */
 
-int __init neofb_setup(char *options)
+#ifndef MODULE
+static int __init neofb_setup(char *options)
 {
 	char *this_opt;
 
@@ -2258,8 +2259,9 @@
 	}
 	return 0;
 }
+#endif  /*  MODULE  */
 
-int __init neofb_init(void)
+static int __init neofb_init(void)
 {
 #ifndef MODULE
 	char *option = NULL;
diff -Nru a/drivers/video/nvidia/Makefile b/drivers/video/nvidia/Makefile
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/video/nvidia/Makefile	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,12 @@
+#
+# Makefile for the nVidia framebuffer driver
+#
+
+obj-$(CONFIG_FB_NVIDIA)          += nvidiafb.o
+
+nvidiafb-y                       := nvidia.o nv_hw.o nv_setup.o \
+			            nv_accel.o
+nvidiafb-$(CONFIG_FB_NVIDIA_I2C) += nv_i2c.o
+nvidiafb-$(CONFIG_PPC_OF)	 += nv_of.o
+
+nvidiafb-objs                    := $(nvidiafb-y)
\ No newline at end of file
diff -Nru a/drivers/video/nvidia/nv_accel.c b/drivers/video/nvidia/nv_accel.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/video/nvidia/nv_accel.c	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,367 @@
+/*
+ * linux/drivers/video/nvidia/nv_accel.c - nVidia Hardware Acceleration
+ *
+ * Copyright 2004 Antonino Daplas <adaplas@pol.net>
+ *
+ * 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/fb.h>
+#include "nv_type.h"
+#include "nv_proto.h"
+#include "nv_dma.h"
+#include "nv_local.h"
+
+/* There is a HW race condition with videoram command buffers.
+   You can't jump to the location of your put offset.  We write put
+   at the jump offset + SKIPS dwords with noop padding in between
+   to solve this problem */
+#define SKIPS  8
+
+static const int NVCopyROP[16] = {
+	0xCC,			/* copy   */
+	0x55			/* invert */
+};
+
+static const int NVCopyROP_PM[16] = {
+	0xCA,			/* copy  */
+	0x5A,			/* invert */
+};
+
+static inline void NVFlush(struct nvidia_par *par)
+{
+	int count = 1000000000;
+
+	while (--count && READ_GET(par) != par->dmaPut) ;
+
+	if (!count) {
+		printk("nvidiafb: DMA Flush lockup\n");
+		par->lockup = 1;
+	}
+}
+
+static inline void NVSync(struct nvidia_par *par)
+{
+	int count = 1000000000;
+
+	while (--count && NV_RD32(par->PGRAPH, 0x0700)) ;
+
+	if (!count) {
+		printk("nvidiafb: DMA Sync lockup\n");
+		par->lockup = 1;
+	}
+}
+
+static void NVDmaKickoff(struct nvidia_par *par)
+{
+	if (par->dmaCurrent != par->dmaPut) {
+		par->dmaPut = par->dmaCurrent;
+		WRITE_PUT(par, par->dmaPut);
+	}
+}
+
+static void NVDmaWait(struct nvidia_par *par, int size)
+{
+	int dmaGet;
+	int count = 1000000000, cnt;
+	size++;
+
+	while (par->dmaFree < size && --count && !par->lockup) {
+		dmaGet = READ_GET(par);
+
+		if (par->dmaPut >= dmaGet) {
+			par->dmaFree = par->dmaMax - par->dmaCurrent;
+			if (par->dmaFree < size) {
+				NVDmaNext(par, 0x20000000);
+				if (dmaGet <= SKIPS) {
+					if (par->dmaPut <= SKIPS)
+						WRITE_PUT(par, SKIPS + 1);
+					cnt = 1000000000;
+					do {
+						dmaGet = READ_GET(par);
+					} while (--cnt && dmaGet <= SKIPS);
+					if (!cnt) {
+						printk("DMA Get lockup\n");
+						par->lockup = 1;
+					}
+				}
+				WRITE_PUT(par, SKIPS);
+				par->dmaCurrent = par->dmaPut = SKIPS;
+				par->dmaFree = dmaGet - (SKIPS + 1);
+			}
+		} else
+			par->dmaFree = dmaGet - par->dmaCurrent - 1;
+	}
+
+	if (!count) {
+		printk("DMA Wait Lockup\n");
+		par->lockup = 1;
+	}
+}
+
+static void NVSetPattern(struct nvidia_par *par, u32 clr0, u32 clr1,
+			 u32 pat0, u32 pat1)
+{
+	NVDmaStart(par, PATTERN_COLOR_0, 4);
+	NVDmaNext(par, clr0);
+	NVDmaNext(par, clr1);
+	NVDmaNext(par, pat0);
+	NVDmaNext(par, pat1);
+}
+
+static void NVSetRopSolid(struct nvidia_par *par, u32 rop, u32 planemask)
+{
+	if (planemask != ~0) {
+		NVSetPattern(par, 0, planemask, ~0, ~0);
+		if (par->currentRop != (rop + 32)) {
+			NVDmaStart(par, ROP_SET, 1);
+			NVDmaNext(par, NVCopyROP_PM[rop]);
+			par->currentRop = rop + 32;
+		}
+	} else if (par->currentRop != rop) {
+		if (par->currentRop >= 16)
+			NVSetPattern(par, ~0, ~0, ~0, ~0);
+		NVDmaStart(par, ROP_SET, 1);
+		NVDmaNext(par, NVCopyROP[rop]);
+		par->currentRop = rop;
+	}
+}
+
+static void NVSetClippingRectangle(struct fb_info *info, int x1, int y1,
+				   int x2, int y2)
+{
+	struct nvidia_par *par = info->par;
+	int h = y2 - y1 + 1;
+	int w = x2 - x1 + 1;
+
+	NVDmaStart(par, CLIP_POINT, 2);
+	NVDmaNext(par, (y1 << 16) | x1);
+	NVDmaNext(par, (h << 16) | w);
+}
+
+void NVResetGraphics(struct fb_info *info)
+{
+	struct nvidia_par *par = info->par;
+	u32 surfaceFormat, patternFormat, rectFormat, lineFormat;
+	int pitch, i;
+
+	pitch = info->fix.line_length;
+
+	par->dmaBase = (u32 __iomem *) (&par->FbStart[par->FbUsableSize]);
+
+	for (i = 0; i < SKIPS; i++)
+		NV_WR32(&par->dmaBase[i], 0, 0x00000000);
+
+	NV_WR32(&par->dmaBase[0x0 + SKIPS], 0, 0x00040000);
+	NV_WR32(&par->dmaBase[0x1 + SKIPS], 0, 0x80000010);
+	NV_WR32(&par->dmaBase[0x2 + SKIPS], 0, 0x00042000);
+	NV_WR32(&par->dmaBase[0x3 + SKIPS], 0, 0x80000011);
+	NV_WR32(&par->dmaBase[0x4 + SKIPS], 0, 0x00044000);
+	NV_WR32(&par->dmaBase[0x5 + SKIPS], 0, 0x80000012);
+	NV_WR32(&par->dmaBase[0x6 + SKIPS], 0, 0x00046000);
+	NV_WR32(&par->dmaBase[0x7 + SKIPS], 0, 0x80000013);
+	NV_WR32(&par->dmaBase[0x8 + SKIPS], 0, 0x00048000);
+	NV_WR32(&par->dmaBase[0x9 + SKIPS], 0, 0x80000014);
+	NV_WR32(&par->dmaBase[0xA + SKIPS], 0, 0x0004A000);
+	NV_WR32(&par->dmaBase[0xB + SKIPS], 0, 0x80000015);
+	NV_WR32(&par->dmaBase[0xC + SKIPS], 0, 0x0004C000);
+	NV_WR32(&par->dmaBase[0xD + SKIPS], 0, 0x80000016);
+	NV_WR32(&par->dmaBase[0xE + SKIPS], 0, 0x0004E000);
+	NV_WR32(&par->dmaBase[0xF + SKIPS], 0, 0x80000017);
+
+	par->dmaPut = 0;
+	par->dmaCurrent = 16 + SKIPS;
+	par->dmaMax = 8191;
+	par->dmaFree = par->dmaMax - par->dmaCurrent;
+
+	switch (info->var.bits_per_pixel) {
+	case 32:
+	case 24:
+		surfaceFormat = SURFACE_FORMAT_DEPTH24;
+		patternFormat = PATTERN_FORMAT_DEPTH24;
+		rectFormat = RECT_FORMAT_DEPTH24;
+		lineFormat = LINE_FORMAT_DEPTH24;
+		break;
+	case 16:
+		surfaceFormat = SURFACE_FORMAT_DEPTH16;
+		patternFormat = PATTERN_FORMAT_DEPTH16;
+		rectFormat = RECT_FORMAT_DEPTH16;
+		lineFormat = LINE_FORMAT_DEPTH16;
+		break;
+	default:
+		surfaceFormat = SURFACE_FORMAT_DEPTH8;
+		patternFormat = PATTERN_FORMAT_DEPTH8;
+		rectFormat = RECT_FORMAT_DEPTH8;
+		lineFormat = LINE_FORMAT_DEPTH8;
+		break;
+	}
+
+	NVDmaStart(par, SURFACE_FORMAT, 4);
+	NVDmaNext(par, surfaceFormat);
+	NVDmaNext(par, pitch | (pitch << 16));
+	NVDmaNext(par, 0);
+	NVDmaNext(par, 0);
+
+	NVDmaStart(par, PATTERN_FORMAT, 1);
+	NVDmaNext(par, patternFormat);
+
+	NVDmaStart(par, RECT_FORMAT, 1);
+	NVDmaNext(par, rectFormat);
+
+	NVDmaStart(par, LINE_FORMAT, 1);
+	NVDmaNext(par, lineFormat);
+
+	par->currentRop = ~0;	/* set to something invalid */
+	NVSetRopSolid(par, ROP_COPY, ~0);
+
+	NVSetClippingRectangle(info, 0, 0, info->var.xres_virtual,
+			       info->var.yres_virtual);
+
+	NVDmaKickoff(par);
+}
+
+u8 byte_rev[256] = {
+	0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
+	0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
+	0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
+	0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
+	0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
+	0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
+	0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
+	0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
+	0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
+	0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
+	0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
+	0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
+	0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
+	0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
+	0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
+	0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
+	0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
+	0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
+	0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
+	0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
+	0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
+	0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
+	0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
+	0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
+	0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
+	0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
+	0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
+	0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
+	0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
+	0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
+	0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
+	0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff,
+};
+
+int nvidiafb_sync(struct fb_info *info)
+{
+	struct nvidia_par *par = info->par;
+
+	if (!par->lockup)
+		NVFlush(par);
+
+	if (!par->lockup)
+		NVSync(par);
+
+	return 0;
+}
+
+void nvidiafb_copyarea(struct fb_info *info, const struct fb_copyarea *region)
+{
+	struct nvidia_par *par = info->par;
+
+	if (par->lockup)
+		return cfb_copyarea(info, region);
+
+	NVDmaStart(par, BLIT_POINT_SRC, 3);
+	NVDmaNext(par, (region->sy << 16) | region->sx);
+	NVDmaNext(par, (region->dy << 16) | region->dx);
+	NVDmaNext(par, (region->height << 16) | region->width);
+
+	NVDmaKickoff(par);
+}
+
+void nvidiafb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
+{
+	struct nvidia_par *par = info->par;
+	u32 color;
+
+	if (par->lockup)
+		return cfb_fillrect(info, rect);
+
+	if (info->var.bits_per_pixel == 8)
+		color = rect->color;
+	else
+		color = ((u32 *) info->pseudo_palette)[rect->color];
+
+	if (rect->rop != ROP_COPY)
+		NVSetRopSolid(par, rect->rop, ~0);
+
+	NVDmaStart(par, RECT_SOLID_COLOR, 1);
+	NVDmaNext(par, color);
+
+	NVDmaStart(par, RECT_SOLID_RECTS(0), 2);
+	NVDmaNext(par, (rect->dx << 16) | rect->dy);
+	NVDmaNext(par, (rect->width << 16) | rect->height);
+
+	NVDmaKickoff(par);
+
+	if (rect->rop != ROP_COPY)
+		NVSetRopSolid(par, ROP_COPY, ~0);
+}
+
+static void nvidiafb_mono_color_expand(struct fb_info *info,
+				       const struct fb_image *image)
+{
+	struct nvidia_par *par = info->par;
+	u32 fg, bg, mask = ~(~0 >> (32 - info->var.bits_per_pixel));
+	u32 dsize, width, *data = (u32 *) image->data, tmp;
+	int i, j, k = 0;
+
+	width = (image->width + 31) & ~31;
+	dsize = width >> 5;
+
+	if (info->var.bits_per_pixel == 8) {
+		fg = image->fg_color | mask;
+		bg = image->bg_color | mask;
+	} else {
+		fg = ((u32 *) info->pseudo_palette)[image->fg_color] | mask;
+		bg = ((u32 *) info->pseudo_palette)[image->bg_color] | mask;
+	}
+
+	NVDmaStart(par, RECT_EXPAND_TWO_COLOR_CLIP, 7);
+	NVDmaNext(par, (image->dy << 16) | (image->dx & 0xffff));
+	NVDmaNext(par, ((image->dy + image->height) << 16) |
+		  ((image->dx + image->width) & 0xffff));
+	NVDmaNext(par, bg);
+	NVDmaNext(par, fg);
+	NVDmaNext(par, (image->height << 16) | width);
+	NVDmaNext(par, (image->height << 16) | width);
+	NVDmaNext(par, (image->dy << 16) | (image->dx & 0xffff));
+
+	for (i = image->height; i--;) {
+		NVDmaStart(par, RECT_EXPAND_TWO_COLOR_DATA(0), dsize);
+		for (j = dsize; j--;) {
+			tmp = data[k++];
+			reverse_order(&tmp);
+			NVDmaNext(par, tmp);
+		}
+	}
+
+	NVDmaKickoff(par);
+}
+
+void nvidiafb_imageblit(struct fb_info *info, const struct fb_image *image)
+{
+	struct nvidia_par *par = info->par;
+
+	if (image->depth == 1 && !par->lockup)
+		nvidiafb_mono_color_expand(info, image);
+	else
+		cfb_imageblit(info, image);
+}
diff -Nru a/drivers/video/nvidia/nv_dma.h b/drivers/video/nvidia/nv_dma.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/video/nvidia/nv_dma.h	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,178 @@
+
+ /***************************************************************************\
+|*                                                                           *|
+|*       Copyright 2003 NVIDIA, Corporation.  All rights reserved.           *|
+|*                                                                           *|
+|*     NOTICE TO USER:   The source code  is copyrighted under  U.S. and     *|
+|*     international laws.  Users and possessors of this source code are     *|
+|*     hereby granted a nonexclusive,  royalty-free copyright license to     *|
+|*     use this code in individual and commercial software.                  *|
+|*                                                                           *|
+|*     Any use of this source code must include,  in the user documenta-     *|
+|*     tion and  internal comments to the code,  notices to the end user     *|
+|*     as follows:                                                           *|
+|*                                                                           *|
+|*       Copyright 2003 NVIDIA, Corporation.  All rights reserved.           *|
+|*                                                                           *|
+|*     NVIDIA, CORPORATION MAKES NO REPRESENTATION ABOUT THE SUITABILITY     *|
+|*     OF  THIS SOURCE  CODE  FOR ANY PURPOSE.  IT IS  PROVIDED  "AS IS"     *|
+|*     WITHOUT EXPRESS OR IMPLIED WARRANTY OF ANY KIND.  NVIDIA, CORPOR-     *|
+|*     ATION DISCLAIMS ALL WARRANTIES  WITH REGARD  TO THIS SOURCE CODE,     *|
+|*     INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGE-     *|
+|*     MENT,  AND FITNESS  FOR A PARTICULAR PURPOSE.   IN NO EVENT SHALL     *|
+|*     NVIDIA, CORPORATION  BE LIABLE FOR ANY SPECIAL,  INDIRECT,  INCI-     *|
+|*     DENTAL, OR CONSEQUENTIAL DAMAGES,  OR ANY DAMAGES  WHATSOEVER RE-     *|
+|*     SULTING FROM LOSS OF USE,  DATA OR PROFITS,  WHETHER IN AN ACTION     *|
+|*     OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,  ARISING OUT OF     *|
+|*     OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOURCE CODE.     *|
+|*                                                                           *|
+|*     U.S. Government  End  Users.   This source code  is a "commercial     *|
+|*     item,"  as that  term is  defined at  48 C.F.R. 2.101 (OCT 1995),     *|
+|*     consisting  of "commercial  computer  software"  and  "commercial     *|
+|*     computer  software  documentation,"  as such  terms  are  used in     *|
+|*     48 C.F.R. 12.212 (SEPT 1995)  and is provided to the U.S. Govern-     *|
+|*     ment only as  a commercial end item.   Consistent with  48 C.F.R.     *|
+|*     12.212 and  48 C.F.R. 227.7202-1 through  227.7202-4 (JUNE 1995),     *|
+|*     all U.S. Government End Users  acquire the source code  with only     *|
+|*     those rights set forth herein.                                        *|
+|*                                                                           *|
+ \***************************************************************************/
+
+#define SURFACE_FORMAT                                              0x00000300
+#define SURFACE_FORMAT_DEPTH8                                       0x00000001
+#define SURFACE_FORMAT_DEPTH15                                      0x00000002
+#define SURFACE_FORMAT_DEPTH16                                      0x00000004
+#define SURFACE_FORMAT_DEPTH24                                      0x00000006
+#define SURFACE_PITCH                                               0x00000304
+#define SURFACE_PITCH_SRC                                           15:0
+#define SURFACE_PITCH_DST                                           31:16
+#define SURFACE_OFFSET_SRC                                          0x00000308
+#define SURFACE_OFFSET_DST                                          0x0000030C
+
+#define ROP_SET                                                     0x00002300
+
+#define PATTERN_FORMAT                                              0x00004300
+#define PATTERN_FORMAT_DEPTH8                                       0x00000003
+#define PATTERN_FORMAT_DEPTH16                                      0x00000001
+#define PATTERN_FORMAT_DEPTH24                                      0x00000003
+#define PATTERN_COLOR_0                                             0x00004310
+#define PATTERN_COLOR_1                                             0x00004314
+#define PATTERN_PATTERN_0                                           0x00004318
+#define PATTERN_PATTERN_1                                           0x0000431C
+
+#define CLIP_POINT                                                  0x00006300
+#define CLIP_POINT_X                                                15:0
+#define CLIP_POINT_Y                                                31:16
+#define CLIP_SIZE                                                   0x00006304
+#define CLIP_SIZE_WIDTH                                             15:0
+#define CLIP_SIZE_HEIGHT                                            31:16
+
+#define LINE_FORMAT                                                 0x00008300
+#define LINE_FORMAT_DEPTH8                                          0x00000003
+#define LINE_FORMAT_DEPTH16                                         0x00000001
+#define LINE_FORMAT_DEPTH24                                         0x00000003
+#define LINE_COLOR                                                  0x00008304
+#define LINE_MAX_LINES                                              16
+#define LINE_LINES(i)                                               0x00008400\
+                                                                    +(i)*8
+#define LINE_LINES_POINT0_X                                         15:0
+#define LINE_LINES_POINT0_Y                                         31:16
+#define LINE_LINES_POINT1_X                                         47:32
+#define LINE_LINES_POINT1_Y                                         63:48
+
+#define BLIT_POINT_SRC                                              0x0000A300
+#define BLIT_POINT_SRC_X                                            15:0
+#define BLIT_POINT_SRC_Y                                            31:16
+#define BLIT_POINT_DST                                              0x0000A304
+#define BLIT_POINT_DST_X                                            15:0
+#define BLIT_POINT_DST_Y                                            31:16
+#define BLIT_SIZE                                                   0x0000A308
+#define BLIT_SIZE_WIDTH                                             15:0
+#define BLIT_SIZE_HEIGHT                                            31:16
+
+#define RECT_FORMAT                                                 0x0000C300
+#define RECT_FORMAT_DEPTH8                                          0x00000003
+#define RECT_FORMAT_DEPTH16                                         0x00000001
+#define RECT_FORMAT_DEPTH24                                         0x00000003
+#define RECT_SOLID_COLOR                                            0x0000C3FC
+#define RECT_SOLID_RECTS_MAX_RECTS                                  32
+#define RECT_SOLID_RECTS(i)                                         0x0000C400\
+                                                                    +(i)*8
+#define RECT_SOLID_RECTS_Y                                          15:0
+#define RECT_SOLID_RECTS_X                                          31:16
+#define RECT_SOLID_RECTS_HEIGHT                                     47:32
+#define RECT_SOLID_RECTS_WIDTH                                      63:48
+
+#define RECT_EXPAND_ONE_COLOR_CLIP                                  0x0000C7EC
+#define RECT_EXPAND_ONE_COLOR_CLIP_POINT0_X                         15:0
+#define RECT_EXPAND_ONE_COLOR_CLIP_POINT0_Y                         31:16
+#define RECT_EXPAND_ONE_COLOR_CLIP_POINT1_X                         47:32
+#define RECT_EXPAND_ONE_COLOR_CLIP_POINT1_Y                         63:48
+#define RECT_EXPAND_ONE_COLOR_COLOR                                 0x0000C7F4
+#define RECT_EXPAND_ONE_COLOR_SIZE                                  0x0000C7F8
+#define RECT_EXPAND_ONE_COLOR_SIZE_WIDTH                            15:0
+#define RECT_EXPAND_ONE_COLOR_SIZE_HEIGHT                           31:16
+#define RECT_EXPAND_ONE_COLOR_POINT                                 0x0000C7FC
+#define RECT_EXPAND_ONE_COLOR_POINT_X                               15:0
+#define RECT_EXPAND_ONE_COLOR_POINT_Y                               31:16
+#define RECT_EXPAND_ONE_COLOR_DATA_MAX_DWORDS                       128
+#define RECT_EXPAND_ONE_COLOR_DATA(i)                               0x0000C800\
+                                                                    +(i)*4
+
+#define RECT_EXPAND_TWO_COLOR_CLIP                                  0x0000CBE4
+#define RECT_EXPAND_TWO_COLOR_CLIP_POINT0_X                         15:0
+#define RECT_EXPAND_TWO_COLOR_CLIP_POINT0_Y                         31:16
+#define RECT_EXPAND_TWO_COLOR_CLIP_POINT1_X                         47:32
+#define RECT_EXPAND_TWO_COLOR_CLIP_POINT1_Y                         63:48
+#define RECT_EXPAND_TWO_COLOR_COLOR_0                               0x0000CBEC
+#define RECT_EXPAND_TWO_COLOR_COLOR_1                               0x0000CBF0
+#define RECT_EXPAND_TWO_COLOR_SIZE_IN                               0x0000CBF4
+#define RECT_EXPAND_TWO_COLOR_SIZE_IN_WIDTH                         15:0
+#define RECT_EXPAND_TWO_COLOR_SIZE_IN_HEIGHT                        31:16
+#define RECT_EXPAND_TWO_COLOR_SIZE_OUT                              0x0000CBF8
+#define RECT_EXPAND_TWO_COLOR_SIZE_OUT_WIDTH                        15:0
+#define RECT_EXPAND_TWO_COLOR_SIZE_OUT_HEIGHT                       31:16
+#define RECT_EXPAND_TWO_COLOR_POINT                                 0x0000CBFC
+#define RECT_EXPAND_TWO_COLOR_POINT_X                               15:0
+#define RECT_EXPAND_TWO_COLOR_POINT_Y                               31:16
+#define RECT_EXPAND_TWO_COLOR_DATA_MAX_DWORDS                       128
+#define RECT_EXPAND_TWO_COLOR_DATA(i)                               0x0000CC00\
+                                                                    +(i)*4
+
+#define STRETCH_BLIT_FORMAT                                         0x0000E300
+#define STRETCH_BLIT_FORMAT_DEPTH8                                  0x00000004
+#define STRETCH_BLIT_FORMAT_DEPTH16                                 0x00000007
+#define STRETCH_BLIT_FORMAT_DEPTH24                                 0x00000004
+#define STRETCH_BLIT_FORMAT_X8R8G8B8                                0x00000004
+#define STRETCH_BLIT_FORMAT_YUYV                                    0x00000005
+#define STRETCH_BLIT_FORMAT_UYVY                                    0x00000006
+#define STRETCH_BLIT_CLIP_POINT                                     0x0000E308
+#define STRETCH_BLIT_CLIP_POINT_X                                   15:0
+#define STRETCH_BLIT_CLIP_POINT_Y                                   31:16
+#define STRETCH_BLIT_CLIP_POINT                                     0x0000E308
+#define STRETCH_BLIT_CLIP_SIZE                                      0x0000E30C
+#define STRETCH_BLIT_CLIP_SIZE_WIDTH                                15:0
+#define STRETCH_BLIT_CLIP_SIZE_HEIGHT                               31:16
+#define STRETCH_BLIT_DST_POINT                                      0x0000E310
+#define STRETCH_BLIT_DST_POINT_X                                    15:0
+#define STRETCH_BLIT_DST_POINT_Y                                    31:16
+#define STRETCH_BLIT_DST_SIZE                                       0x0000E314
+#define STRETCH_BLIT_DST_SIZE_WIDTH                                 15:0
+#define STRETCH_BLIT_DST_SIZE_HEIGHT                                31:16
+#define STRETCH_BLIT_DU_DX                                          0x0000E318
+#define STRETCH_BLIT_DV_DY                                          0x0000E31C
+#define STRETCH_BLIT_SRC_SIZE                                       0x0000E400
+#define STRETCH_BLIT_SRC_SIZE_WIDTH                                 15:0
+#define STRETCH_BLIT_SRC_SIZE_HEIGHT                                31:16
+#define STRETCH_BLIT_SRC_FORMAT                                     0x0000E404
+#define STRETCH_BLIT_SRC_FORMAT_PITCH                               15:0
+#define STRETCH_BLIT_SRC_FORMAT_ORIGIN                              23:16
+#define STRETCH_BLIT_SRC_FORMAT_ORIGIN_CENTER                       0x00000001
+#define STRETCH_BLIT_SRC_FORMAT_ORIGIN_CORNER                       0x00000002
+#define STRETCH_BLIT_SRC_FORMAT_FILTER                              31:24
+#define STRETCH_BLIT_SRC_FORMAT_FILTER_POINT_SAMPLE                 0x00000000
+#define STRETCH_BLIT_SRC_FORMAT_FILTER_BILINEAR                     0x00000001
+#define STRETCH_BLIT_SRC_OFFSET                                     0x0000E408
+#define STRETCH_BLIT_SRC_POINT                                      0x0000E40C
+#define STRETCH_BLIT_SRC_POINT_U                                    15:0
+#define STRETCH_BLIT_SRC_POINT_V                                    31:16
diff -Nru a/drivers/video/nvidia/nv_hw.c b/drivers/video/nvidia/nv_hw.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/video/nvidia/nv_hw.c	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,1582 @@
+ /***************************************************************************\
+|*                                                                           *|
+|*       Copyright 1993-2003 NVIDIA, Corporation.  All rights reserved.      *|
+|*                                                                           *|
+|*     NOTICE TO USER:   The source code  is copyrighted under  U.S. and     *|
+|*     international laws.  Users and possessors of this source code are     *|
+|*     hereby granted a nonexclusive,  royalty-free copyright license to     *|
+|*     use this code in individual and commercial software.                  *|
+|*                                                                           *|
+|*     Any use of this source code must include,  in the user documenta-     *|
+|*     tion and  internal comments to the code,  notices to the end user     *|
+|*     as follows:                                                           *|
+|*                                                                           *|
+|*       Copyright 1993-2003 NVIDIA, Corporation.  All rights reserved.      *|
+|*                                                                           *|
+|*     NVIDIA, CORPORATION MAKES NO REPRESENTATION ABOUT THE SUITABILITY     *|
+|*     OF  THIS SOURCE  CODE  FOR ANY PURPOSE.  IT IS  PROVIDED  "AS IS"     *|
+|*     WITHOUT EXPRESS OR IMPLIED WARRANTY OF ANY KIND.  NVIDIA, CORPOR-     *|
+|*     ATION DISCLAIMS ALL WARRANTIES  WITH REGARD  TO THIS SOURCE CODE,     *|
+|*     INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGE-     *|
+|*     MENT,  AND FITNESS  FOR A PARTICULAR PURPOSE.   IN NO EVENT SHALL     *|
+|*     NVIDIA, CORPORATION  BE LIABLE FOR ANY SPECIAL,  INDIRECT,  INCI-     *|
+|*     DENTAL, OR CONSEQUENTIAL DAMAGES,  OR ANY DAMAGES  WHATSOEVER RE-     *|
+|*     SULTING FROM LOSS OF USE,  DATA OR PROFITS,  WHETHER IN AN ACTION     *|
+|*     OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,  ARISING OUT OF     *|
+|*     OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOURCE CODE.     *|
+|*                                                                           *|
+|*     U.S. Government  End  Users.   This source code  is a "commercial     *|
+|*     item,"  as that  term is  defined at  48 C.F.R. 2.101 (OCT 1995),     *|
+|*     consisting  of "commercial  computer  software"  and  "commercial     *|
+|*     computer  software  documentation,"  as such  terms  are  used in     *|
+|*     48 C.F.R. 12.212 (SEPT 1995)  and is provided to the U.S. Govern-     *|
+|*     ment only as  a commercial end item.   Consistent with  48 C.F.R.     *|
+|*     12.212 and  48 C.F.R. 227.7202-1 through  227.7202-4 (JUNE 1995),     *|
+|*     all U.S. Government End Users  acquire the source code  with only     *|
+|*     those rights set forth herein.                                        *|
+|*                                                                           *|
+ \***************************************************************************/
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/nv/nv_hw.c,v 1.4 2003/11/03 05:11:25 tsi Exp $ */
+
+#include <linux/pci.h>
+#include "nv_type.h"
+#include "nv_local.h"
+
+void NVLockUnlock(struct nvidia_par *par, int Lock)
+{
+	u8 cr11;
+
+	VGA_WR08(par->PCIO, 0x3D4, 0x1F);
+	VGA_WR08(par->PCIO, 0x3D5, Lock ? 0x99 : 0x57);
+
+	VGA_WR08(par->PCIO, 0x3D4, 0x11);
+	cr11 = VGA_RD08(par->PCIO, 0x3D5);
+	if (Lock)
+		cr11 |= 0x80;
+	else
+		cr11 &= ~0x80;
+	VGA_WR08(par->PCIO, 0x3D5, cr11);
+}
+
+int NVShowHideCursor(struct nvidia_par *par, int ShowHide)
+{
+	int cur = par->CurrentState->cursor1;
+
+	par->CurrentState->cursor1 = (par->CurrentState->cursor1 & 0xFE) |
+	    (ShowHide & 0x01);
+	VGA_WR08(par->PCIO, 0x3D4, 0x31);
+	VGA_WR08(par->PCIO, 0x3D5, par->CurrentState->cursor1);
+
+	if (par->Architecture == NV_ARCH_40)
+		NV_WR32(par->PRAMDAC, 0x0300, NV_RD32(par->PRAMDAC, 0x0300));
+
+	return (cur & 0x01);
+}
+
+/****************************************************************************\
+*                                                                            *
+* The video arbitration routines calculate some "magic" numbers.  Fixes      *
+* the snow seen when accessing the framebuffer without it.                   *
+* It just works (I hope).                                                    *
+*                                                                            *
+\****************************************************************************/
+
+typedef struct {
+	int graphics_lwm;
+	int video_lwm;
+	int graphics_burst_size;
+	int video_burst_size;
+	int valid;
+} nv4_fifo_info;
+
+typedef struct {
+	int pclk_khz;
+	int mclk_khz;
+	int nvclk_khz;
+	char mem_page_miss;
+	char mem_latency;
+	int memory_width;
+	char enable_video;
+	char gr_during_vid;
+	char pix_bpp;
+	char mem_aligned;
+	char enable_mp;
+} nv4_sim_state;
+
+typedef struct {
+	int graphics_lwm;
+	int video_lwm;
+	int graphics_burst_size;
+	int video_burst_size;
+	int valid;
+} nv10_fifo_info;
+
+typedef struct {
+	int pclk_khz;
+	int mclk_khz;
+	int nvclk_khz;
+	char mem_page_miss;
+	char mem_latency;
+	int memory_type;
+	int memory_width;
+	char enable_video;
+	char gr_during_vid;
+	char pix_bpp;
+	char mem_aligned;
+	char enable_mp;
+} nv10_sim_state;
+
+static void nvGetClocks(struct nvidia_par *par, unsigned int *MClk,
+			unsigned int *NVClk)
+{
+	unsigned int pll, N, M, MB, NB, P;
+
+	if (par->Architecture >= NV_ARCH_40) {
+		pll = NV_RD32(par->PMC, 0x4020);
+		P = (pll >> 16) & 0x03;
+		pll = NV_RD32(par->PMC, 0x4024);
+		M = pll & 0xFF;
+		N = (pll >> 8) & 0xFF;
+		MB = (pll >> 16) & 0xFF;
+		NB = (pll >> 24) & 0xFF;
+		*MClk = ((N * NB * par->CrystalFreqKHz) / (M * MB)) >> P;
+
+		pll = NV_RD32(par->PMC, 0x4000);
+		P = (pll >> 16) & 0x03;
+		pll = NV_RD32(par->PMC, 0x4004);
+		M = pll & 0xFF;
+		N = (pll >> 8) & 0xFF;
+		MB = (pll >> 16) & 0xFF;
+		NB = (pll >> 24) & 0xFF;
+
+		*NVClk = ((N * NB * par->CrystalFreqKHz) / (M * MB)) >> P;
+	} else if (par->twoStagePLL) {
+		pll = NV_RD32(par->PRAMDAC0, 0x0504);
+		M = pll & 0xFF;
+		N = (pll >> 8) & 0xFF;
+		P = (pll >> 16) & 0x0F;
+		pll = NV_RD32(par->PRAMDAC0, 0x0574);
+		if (pll & 0x80000000) {
+			MB = pll & 0xFF;
+			NB = (pll >> 8) & 0xFF;
+		} else {
+			MB = 1;
+			NB = 1;
+		}
+		*MClk = ((N * NB * par->CrystalFreqKHz) / (M * MB)) >> P;
+
+		pll = NV_RD32(par->PRAMDAC0, 0x0500);
+		M = pll & 0xFF;
+		N = (pll >> 8) & 0xFF;
+		P = (pll >> 16) & 0x0F;
+		pll = NV_RD32(par->PRAMDAC0, 0x0570);
+		if (pll & 0x80000000) {
+			MB = pll & 0xFF;
+			NB = (pll >> 8) & 0xFF;
+		} else {
+			MB = 1;
+			NB = 1;
+		}
+		*NVClk = ((N * NB * par->CrystalFreqKHz) / (M * MB)) >> P;
+	} else
+	    if (((par->Chipset & 0x0ff0) == 0x0300) ||
+		((par->Chipset & 0x0ff0) == 0x0330)) {
+		pll = NV_RD32(par->PRAMDAC0, 0x0504);
+		M = pll & 0x0F;
+		N = (pll >> 8) & 0xFF;
+		P = (pll >> 16) & 0x07;
+		if (pll & 0x00000080) {
+			MB = (pll >> 4) & 0x07;
+			NB = (pll >> 19) & 0x1f;
+		} else {
+			MB = 1;
+			NB = 1;
+		}
+		*MClk = ((N * NB * par->CrystalFreqKHz) / (M * MB)) >> P;
+
+		pll = NV_RD32(par->PRAMDAC0, 0x0500);
+		M = pll & 0x0F;
+		N = (pll >> 8) & 0xFF;
+		P = (pll >> 16) & 0x07;
+		if (pll & 0x00000080) {
+			MB = (pll >> 4) & 0x07;
+			NB = (pll >> 19) & 0x1f;
+		} else {
+			MB = 1;
+			NB = 1;
+		}
+		*NVClk = ((N * NB * par->CrystalFreqKHz) / (M * MB)) >> P;
+	} else {
+		pll = NV_RD32(par->PRAMDAC0, 0x0504);
+		M = pll & 0xFF;
+		N = (pll >> 8) & 0xFF;
+		P = (pll >> 16) & 0x0F;
+		*MClk = (N * par->CrystalFreqKHz / M) >> P;
+
+		pll = NV_RD32(par->PRAMDAC0, 0x0500);
+		M = pll & 0xFF;
+		N = (pll >> 8) & 0xFF;
+		P = (pll >> 16) & 0x0F;
+		*NVClk = (N * par->CrystalFreqKHz / M) >> P;
+	}
+}
+
+static void nv4CalcArbitration(nv4_fifo_info * fifo, nv4_sim_state * arb)
+{
+	int data, pagemiss, cas, width, video_enable, bpp;
+	int nvclks, mclks, pclks, vpagemiss, crtpagemiss, vbs;
+	int found, mclk_extra, mclk_loop, cbs, m1, p1;
+	int mclk_freq, pclk_freq, nvclk_freq, mp_enable;
+	int us_m, us_n, us_p, video_drain_rate, crtc_drain_rate;
+	int vpm_us, us_video, vlwm, video_fill_us, cpm_us, us_crt, clwm;
+
+	fifo->valid = 1;
+	pclk_freq = arb->pclk_khz;
+	mclk_freq = arb->mclk_khz;
+	nvclk_freq = arb->nvclk_khz;
+	pagemiss = arb->mem_page_miss;
+	cas = arb->mem_latency;
+	width = arb->memory_width >> 6;
+	video_enable = arb->enable_video;
+	bpp = arb->pix_bpp;
+	mp_enable = arb->enable_mp;
+	clwm = 0;
+	vlwm = 0;
+	cbs = 128;
+	pclks = 2;
+	nvclks = 2;
+	nvclks += 2;
+	nvclks += 1;
+	mclks = 5;
+	mclks += 3;
+	mclks += 1;
+	mclks += cas;
+	mclks += 1;
+	mclks += 1;
+	mclks += 1;
+	mclks += 1;
+	mclk_extra = 3;
+	nvclks += 2;
+	nvclks += 1;
+	nvclks += 1;
+	nvclks += 1;
+	if (mp_enable)
+		mclks += 4;
+	nvclks += 0;
+	pclks += 0;
+	found = 0;
+	vbs = 0;
+	while (found != 1) {
+		fifo->valid = 1;
+		found = 1;
+		mclk_loop = mclks + mclk_extra;
+		us_m = mclk_loop * 1000 * 1000 / mclk_freq;
+		us_n = nvclks * 1000 * 1000 / nvclk_freq;
+		us_p = nvclks * 1000 * 1000 / pclk_freq;
+		if (video_enable) {
+			video_drain_rate = pclk_freq * 2;
+			crtc_drain_rate = pclk_freq * bpp / 8;
+			vpagemiss = 2;
+			vpagemiss += 1;
+			crtpagemiss = 2;
+			vpm_us =
+			    (vpagemiss * pagemiss) * 1000 * 1000 / mclk_freq;
+			if (nvclk_freq * 2 > mclk_freq * width)
+				video_fill_us =
+				    cbs * 1000 * 1000 / 16 / nvclk_freq;
+			else
+				video_fill_us =
+				    cbs * 1000 * 1000 / (8 * width) /
+				    mclk_freq;
+			us_video = vpm_us + us_m + us_n + us_p + video_fill_us;
+			vlwm = us_video * video_drain_rate / (1000 * 1000);
+			vlwm++;
+			vbs = 128;
+			if (vlwm > 128)
+				vbs = 64;
+			if (vlwm > (256 - 64))
+				vbs = 32;
+			if (nvclk_freq * 2 > mclk_freq * width)
+				video_fill_us =
+				    vbs * 1000 * 1000 / 16 / nvclk_freq;
+			else
+				video_fill_us =
+				    vbs * 1000 * 1000 / (8 * width) /
+				    mclk_freq;
+			cpm_us =
+			    crtpagemiss * pagemiss * 1000 * 1000 / mclk_freq;
+			us_crt =
+			    us_video + video_fill_us + cpm_us + us_m + us_n +
+			    us_p;
+			clwm = us_crt * crtc_drain_rate / (1000 * 1000);
+			clwm++;
+		} else {
+			crtc_drain_rate = pclk_freq * bpp / 8;
+			crtpagemiss = 2;
+			crtpagemiss += 1;
+			cpm_us =
+			    crtpagemiss * pagemiss * 1000 * 1000 / mclk_freq;
+			us_crt = cpm_us + us_m + us_n + us_p;
+			clwm = us_crt * crtc_drain_rate / (1000 * 1000);
+			clwm++;
+		}
+		m1 = clwm + cbs - 512;
+		p1 = m1 * pclk_freq / mclk_freq;
+		p1 = p1 * bpp / 8;
+		if ((p1 < m1) && (m1 > 0)) {
+			fifo->valid = 0;
+			found = 0;
+			if (mclk_extra == 0)
+				found = 1;
+			mclk_extra--;
+		} else if (video_enable) {
+			if ((clwm > 511) || (vlwm > 255)) {
+				fifo->valid = 0;
+				found = 0;
+				if (mclk_extra == 0)
+					found = 1;
+				mclk_extra--;
+			}
+		} else {
+			if (clwm > 519) {
+				fifo->valid = 0;
+				found = 0;
+				if (mclk_extra == 0)
+					found = 1;
+				mclk_extra--;
+			}
+		}
+		if (clwm < 384)
+			clwm = 384;
+		if (vlwm < 128)
+			vlwm = 128;
+		data = (int)(clwm);
+		fifo->graphics_lwm = data;
+		fifo->graphics_burst_size = 128;
+		data = (int)((vlwm + 15));
+		fifo->video_lwm = data;
+		fifo->video_burst_size = vbs;
+	}
+}
+
+static void nv4UpdateArbitrationSettings(unsigned VClk,
+					 unsigned pixelDepth,
+					 unsigned *burst,
+					 unsigned *lwm, struct nvidia_par *par)
+{
+	nv4_fifo_info fifo_data;
+	nv4_sim_state sim_data;
+	unsigned int MClk, NVClk, cfg1;
+
+	nvGetClocks(par, &MClk, &NVClk);
+
+	cfg1 = NV_RD32(par->PFB, 0x00000204);
+	sim_data.pix_bpp = (char)pixelDepth;
+	sim_data.enable_video = 0;
+	sim_data.enable_mp = 0;
+	sim_data.memory_width = (NV_RD32(par->PEXTDEV, 0x0000) & 0x10) ?
+	    128 : 64;
+	sim_data.mem_latency = (char)cfg1 & 0x0F;
+	sim_data.mem_aligned = 1;
+	sim_data.mem_page_miss =
+	    (char)(((cfg1 >> 4) & 0x0F) + ((cfg1 >> 31) & 0x01));
+	sim_data.gr_during_vid = 0;
+	sim_data.pclk_khz = VClk;
+	sim_data.mclk_khz = MClk;
+	sim_data.nvclk_khz = NVClk;
+	nv4CalcArbitration(&fifo_data, &sim_data);
+	if (fifo_data.valid) {
+		int b = fifo_data.graphics_burst_size >> 4;
+		*burst = 0;
+		while (b >>= 1)
+			(*burst)++;
+		*lwm = fifo_data.graphics_lwm >> 3;
+	}
+}
+
+static void nv10CalcArbitration(nv10_fifo_info * fifo, nv10_sim_state * arb)
+{
+	int data, pagemiss, width, video_enable, bpp;
+	int nvclks, mclks, pclks, vpagemiss, crtpagemiss;
+	int nvclk_fill;
+	int found, mclk_extra, mclk_loop, cbs, m1;
+	int mclk_freq, pclk_freq, nvclk_freq, mp_enable;
+	int us_m, us_m_min, us_n, us_p, crtc_drain_rate;
+	int vus_m;
+	int vpm_us, us_video, cpm_us, us_crt, clwm;
+	int clwm_rnd_down;
+	int m2us, us_pipe_min, p1clk, p2;
+	int min_mclk_extra;
+	int us_min_mclk_extra;
+
+	fifo->valid = 1;
+	pclk_freq = arb->pclk_khz;	/* freq in KHz */
+	mclk_freq = arb->mclk_khz;
+	nvclk_freq = arb->nvclk_khz;
+	pagemiss = arb->mem_page_miss;
+	width = arb->memory_width / 64;
+	video_enable = arb->enable_video;
+	bpp = arb->pix_bpp;
+	mp_enable = arb->enable_mp;
+	clwm = 0;
+
+	cbs = 512;
+
+	pclks = 4;	/* lwm detect. */
+
+	nvclks = 3;	/* lwm -> sync. */
+	nvclks += 2;	/* fbi bus cycles (1 req + 1 busy) */
+	/* 2 edge sync.  may be very close to edge so just put one. */
+	mclks = 1;
+	mclks += 1;	/* arb_hp_req */
+	mclks += 5;	/* ap_hp_req   tiling pipeline */
+
+	mclks += 2;	/* tc_req     latency fifo */
+	mclks += 2;	/* fb_cas_n_  memory request to fbio block */
+	mclks += 7;	/* sm_d_rdv   data returned from fbio block */
+
+	/* fb.rd.d.Put_gc   need to accumulate 256 bits for read */
+	if (arb->memory_type == 0)
+		if (arb->memory_width == 64)	/* 64 bit bus */
+			mclks += 4;
+		else
+			mclks += 2;
+	else if (arb->memory_width == 64)	/* 64 bit bus */
+		mclks += 2;
+	else
+		mclks += 1;
+
+	if ((!video_enable) && (arb->memory_width == 128)) {
+		mclk_extra = (bpp == 32) ? 31 : 42;	/* Margin of error */
+		min_mclk_extra = 17;
+	} else {
+		mclk_extra = (bpp == 32) ? 8 : 4;	/* Margin of error */
+		/* mclk_extra = 4; *//* Margin of error */
+		min_mclk_extra = 18;
+	}
+
+	/* 2 edge sync.  may be very close to edge so just put one. */
+	nvclks += 1;
+	nvclks += 1;		/* fbi_d_rdv_n */
+	nvclks += 1;		/* Fbi_d_rdata */
+	nvclks += 1;		/* crtfifo load */
+
+	if (mp_enable)
+		mclks += 4;	/* Mp can get in with a burst of 8. */
+	/* Extra clocks determined by heuristics */
+
+	nvclks += 0;
+	pclks += 0;
+	found = 0;
+	while (found != 1) {
+		fifo->valid = 1;
+		found = 1;
+		mclk_loop = mclks + mclk_extra;
+		/* Mclk latency in us */
+		us_m = mclk_loop * 1000 * 1000 / mclk_freq;
+		/* Minimum Mclk latency in us */
+		us_m_min = mclks * 1000 * 1000 / mclk_freq;
+		us_min_mclk_extra = min_mclk_extra * 1000 * 1000 / mclk_freq;
+		/* nvclk latency in us */
+		us_n = nvclks * 1000 * 1000 / nvclk_freq;
+		/* nvclk latency in us */
+		us_p = pclks * 1000 * 1000 / pclk_freq;
+		us_pipe_min = us_m_min + us_n + us_p;
+
+		/* Mclk latency in us */
+		vus_m = mclk_loop * 1000 * 1000 / mclk_freq;
+
+		if (video_enable) {
+			crtc_drain_rate = pclk_freq * bpp / 8;	/* MB/s */
+
+			vpagemiss = 1;	/* self generating page miss */
+			vpagemiss += 1;	/* One higher priority before */
+
+			crtpagemiss = 2;	/* self generating page miss */
+			if (mp_enable)
+				crtpagemiss += 1;	/* if MA0 conflict */
+
+			vpm_us =
+			    (vpagemiss * pagemiss) * 1000 * 1000 / mclk_freq;
+
+			/* Video has separate read return path */
+			us_video = vpm_us + vus_m;
+
+			cpm_us =
+			    crtpagemiss * pagemiss * 1000 * 1000 / mclk_freq;
+			/* Wait for video */
+			us_crt = us_video
+			    + cpm_us	/* CRT Page miss */
+			    + us_m + us_n + us_p	/* other latency */
+			    ;
+
+			clwm = us_crt * crtc_drain_rate / (1000 * 1000);
+			/* fixed point <= float_point - 1.  Fixes that */
+			clwm++;
+		} else {
+		    /* bpp * pclk/8 */
+			crtc_drain_rate = pclk_freq * bpp / 8;
+
+			crtpagemiss = 1;	/* self generating page miss */
+			crtpagemiss += 1;	/* MA0 page miss */
+			if (mp_enable)
+				crtpagemiss += 1;	/* if MA0 conflict */
+			cpm_us =
+			    crtpagemiss * pagemiss * 1000 * 1000 / mclk_freq;
+			us_crt = cpm_us + us_m + us_n + us_p;
+			clwm = us_crt * crtc_drain_rate / (1000 * 1000);
+			/* fixed point <= float_point - 1.  Fixes that */
+			clwm++;
+
+			/* Finally, a heuristic check when width == 64 bits */
+			if (width == 1) {
+				nvclk_fill = nvclk_freq * 8;
+				if (crtc_drain_rate * 100 >= nvclk_fill * 102)
+					/*Large number to fail */
+					clwm = 0xfff;
+
+				else if (crtc_drain_rate * 100 >=
+					 nvclk_fill * 98) {
+					clwm = 1024;
+					cbs = 512;
+				}
+			}
+		}
+
+		/*
+		   Overfill check:
+		 */
+
+		clwm_rnd_down = ((int)clwm / 8) * 8;
+		if (clwm_rnd_down < clwm)
+			clwm += 8;
+
+		m1 = clwm + cbs - 1024;	/* Amount of overfill */
+		m2us = us_pipe_min + us_min_mclk_extra;
+
+		/* pclk cycles to drain */
+		p1clk = m2us * pclk_freq / (1000 * 1000);
+		p2 = p1clk * bpp / 8;	/* bytes drained. */
+
+		if ((p2 < m1) && (m1 > 0)) {
+			fifo->valid = 0;
+			found = 0;
+			if (min_mclk_extra == 0) {
+				if (cbs <= 32) {
+					/* Can't adjust anymore! */
+					found = 1;
+				} else {
+					/* reduce the burst size */
+					cbs = cbs / 2;
+				}
+			} else {
+				min_mclk_extra--;
+			}
+		} else {
+			if (clwm > 1023) {	/* Have some margin */
+				fifo->valid = 0;
+				found = 0;
+				if (min_mclk_extra == 0)
+					/* Can't adjust anymore! */
+					found = 1;
+				else
+					min_mclk_extra--;
+			}
+		}
+
+		if (clwm < (1024 - cbs + 8))
+			clwm = 1024 - cbs + 8;
+		data = (int)(clwm);
+		/*  printf("CRT LWM: %f bytes, prog: 0x%x, bs: 256\n",
+		    clwm, data ); */
+		fifo->graphics_lwm = data;
+		fifo->graphics_burst_size = cbs;
+
+		fifo->video_lwm = 1024;
+		fifo->video_burst_size = 512;
+	}
+}
+
+static void nv10UpdateArbitrationSettings(unsigned VClk,
+					  unsigned pixelDepth,
+					  unsigned *burst,
+					  unsigned *lwm,
+					  struct nvidia_par *par)
+{
+	nv10_fifo_info fifo_data;
+	nv10_sim_state sim_data;
+	unsigned int MClk, NVClk, cfg1;
+
+	nvGetClocks(par, &MClk, &NVClk);
+
+	cfg1 = NV_RD32(par->PFB, 0x0204);
+	sim_data.pix_bpp = (char)pixelDepth;
+	sim_data.enable_video = 1;
+	sim_data.enable_mp = 0;
+	sim_data.memory_type = (NV_RD32(par->PFB, 0x0200) & 0x01) ? 1 : 0;
+	sim_data.memory_width = (NV_RD32(par->PEXTDEV, 0x0000) & 0x10) ?
+	    128 : 64;
+	sim_data.mem_latency = (char)cfg1 & 0x0F;
+	sim_data.mem_aligned = 1;
+	sim_data.mem_page_miss =
+	    (char)(((cfg1 >> 4) & 0x0F) + ((cfg1 >> 31) & 0x01));
+	sim_data.gr_during_vid = 0;
+	sim_data.pclk_khz = VClk;
+	sim_data.mclk_khz = MClk;
+	sim_data.nvclk_khz = NVClk;
+	nv10CalcArbitration(&fifo_data, &sim_data);
+	if (fifo_data.valid) {
+		int b = fifo_data.graphics_burst_size >> 4;
+		*burst = 0;
+		while (b >>= 1)
+			(*burst)++;
+		*lwm = fifo_data.graphics_lwm >> 3;
+	}
+}
+
+static void nv30UpdateArbitrationSettings (
+    struct nvidia_par *par,
+    unsigned int      *burst,
+    unsigned int      *lwm
+)
+{
+    unsigned int MClk, NVClk;
+    unsigned int fifo_size, burst_size, graphics_lwm;
+
+    fifo_size = 2048;
+    burst_size = 512;
+    graphics_lwm = fifo_size - burst_size;
+
+    nvGetClocks(par, &MClk, &NVClk);
+
+    *burst = 0;
+    burst_size >>= 5;
+    while(burst_size >>= 1) (*burst)++;
+    *lwm = graphics_lwm >> 3;
+}
+
+static void nForceUpdateArbitrationSettings(unsigned VClk,
+					    unsigned pixelDepth,
+					    unsigned *burst,
+					    unsigned *lwm,
+					    struct nvidia_par *par)
+{
+	nv10_fifo_info fifo_data;
+	nv10_sim_state sim_data;
+	unsigned int M, N, P, pll, MClk, NVClk, memctrl;
+	struct pci_dev *dev;
+
+	if ((par->Chipset & 0x0FF0) == 0x01A0) {
+		unsigned int uMClkPostDiv;
+		dev = pci_find_slot(0, 3);
+		pci_read_config_dword(dev, 0x6C, &uMClkPostDiv);
+		uMClkPostDiv = (uMClkPostDiv >> 8) & 0xf;
+
+		if (!uMClkPostDiv)
+			uMClkPostDiv = 4;
+		MClk = 400000 / uMClkPostDiv;
+	} else {
+		dev = pci_find_slot(0, 5);
+		pci_read_config_dword(dev, 0x4c, &MClk);
+		MClk /= 1000;
+	}
+
+	pll = NV_RD32(par->PRAMDAC0, 0x0500);
+	M = (pll >> 0) & 0xFF;
+	N = (pll >> 8) & 0xFF;
+	P = (pll >> 16) & 0x0F;
+	NVClk = (N * par->CrystalFreqKHz / M) >> P;
+	sim_data.pix_bpp = (char)pixelDepth;
+	sim_data.enable_video = 0;
+	sim_data.enable_mp = 0;
+	pci_find_slot(0, 1);
+	pci_read_config_dword(dev, 0x7C, &sim_data.memory_type);
+	sim_data.memory_type = (sim_data.memory_type >> 12) & 1;
+	sim_data.memory_width = 64;
+
+	dev = pci_find_slot(0, 3);
+	pci_read_config_dword(dev, 0, &memctrl);
+	memctrl >>= 16;
+
+	if ((memctrl == 0x1A9) || (memctrl == 0x1AB) || (memctrl == 0x1ED)) {
+		int dimm[3];
+
+		pci_find_slot(0, 2);
+		pci_read_config_dword(dev, 0x40, &dimm[0]);
+		dimm[0] = (dimm[0] >> 8) & 0x4f;
+		pci_read_config_dword(dev, 0x44, &dimm[1]);
+		dimm[1] = (dimm[1] >> 8) & 0x4f;
+		pci_read_config_dword(dev, 0x48, &dimm[2]);
+		dimm[2] = (dimm[2] >> 8) & 0x4f;
+
+		if ((dimm[0] + dimm[1]) != dimm[2]) {
+			printk("nvidiafb: your nForce DIMMs are not arranged "
+			       "in optimal banks!\n");
+		}
+	}
+
+	sim_data.mem_latency = 3;
+	sim_data.mem_aligned = 1;
+	sim_data.mem_page_miss = 10;
+	sim_data.gr_during_vid = 0;
+	sim_data.pclk_khz = VClk;
+	sim_data.mclk_khz = MClk;
+	sim_data.nvclk_khz = NVClk;
+	nv10CalcArbitration(&fifo_data, &sim_data);
+	if (fifo_data.valid) {
+		int b = fifo_data.graphics_burst_size >> 4;
+		*burst = 0;
+		while (b >>= 1)
+			(*burst)++;
+		*lwm = fifo_data.graphics_lwm >> 3;
+	}
+}
+
+/****************************************************************************\
+*                                                                            *
+*                          RIVA Mode State Routines                          *
+*                                                                            *
+\****************************************************************************/
+
+/*
+ * Calculate the Video Clock parameters for the PLL.
+ */
+static void CalcVClock(int clockIn,
+		       int *clockOut, u32 * pllOut, struct nvidia_par *par)
+{
+	unsigned lowM, highM;
+	unsigned DeltaNew, DeltaOld;
+	unsigned VClk, Freq;
+	unsigned M, N, P;
+
+	DeltaOld = 0xFFFFFFFF;
+
+	VClk = (unsigned)clockIn;
+
+	if (par->CrystalFreqKHz == 13500) {
+		lowM = 7;
+		highM = 13;
+	} else {
+		lowM = 8;
+		highM = 14;
+	}
+
+	for (P = 0; P <= 4; P++) {
+		Freq = VClk << P;
+		if ((Freq >= 128000) && (Freq <= 350000)) {
+			for (M = lowM; M <= highM; M++) {
+				N = ((VClk << P) * M) / par->CrystalFreqKHz;
+				if (N <= 255) {
+					Freq =
+					    ((par->CrystalFreqKHz * N) /
+					     M) >> P;
+					if (Freq > VClk)
+						DeltaNew = Freq - VClk;
+					else
+						DeltaNew = VClk - Freq;
+					if (DeltaNew < DeltaOld) {
+						*pllOut =
+						    (P << 16) | (N << 8) | M;
+						*clockOut = Freq;
+						DeltaOld = DeltaNew;
+					}
+				}
+			}
+		}
+	}
+}
+
+static void CalcVClock2Stage(int clockIn,
+			     int *clockOut,
+			     u32 * pllOut,
+			     u32 * pllBOut, struct nvidia_par *par)
+{
+	unsigned DeltaNew, DeltaOld;
+	unsigned VClk, Freq;
+	unsigned M, N, P;
+
+	DeltaOld = 0xFFFFFFFF;
+
+	*pllBOut = 0x80000401;	/* fixed at x4 for now */
+
+	VClk = (unsigned)clockIn;
+
+	for (P = 0; P <= 6; P++) {
+		Freq = VClk << P;
+		if ((Freq >= 400000) && (Freq <= 1000000)) {
+			for (M = 1; M <= 13; M++) {
+				N = ((VClk << P) * M) /
+				    (par->CrystalFreqKHz << 2);
+				if ((N >= 5) && (N <= 255)) {
+					Freq =
+					    (((par->CrystalFreqKHz << 2) * N) /
+					     M) >> P;
+					if (Freq > VClk)
+						DeltaNew = Freq - VClk;
+					else
+						DeltaNew = VClk - Freq;
+					if (DeltaNew < DeltaOld) {
+						*pllOut =
+						    (P << 16) | (N << 8) | M;
+						*clockOut = Freq;
+						DeltaOld = DeltaNew;
+					}
+				}
+			}
+		}
+	}
+}
+
+/*
+ * Calculate extended mode parameters (SVGA) and save in a
+ * mode state structure.
+ */
+void NVCalcStateExt(struct nvidia_par *par,
+		    RIVA_HW_STATE * state,
+		    int bpp,
+		    int width,
+		    int hDisplaySize, int height, int dotClock, int flags)
+{
+	int pixelDepth, VClk;
+	/*
+	 * Save mode parameters.
+	 */
+	state->bpp = bpp;	/* this is not bitsPerPixel, it's 8,15,16,32 */
+	state->width = width;
+	state->height = height;
+	/*
+	 * Extended RIVA registers.
+	 */
+	pixelDepth = (bpp + 1) / 8;
+	if (par->twoStagePLL)
+		CalcVClock2Stage(dotClock, &VClk, &state->pll, &state->pllB,
+				 par);
+	else
+		CalcVClock(dotClock, &VClk, &state->pll, par);
+
+	switch (par->Architecture) {
+	case NV_ARCH_04:
+		nv4UpdateArbitrationSettings(VClk,
+					     pixelDepth * 8,
+					     &(state->arbitration0),
+					     &(state->arbitration1), par);
+		state->cursor0 = 0x00;
+		state->cursor1 = 0xbC;
+		if (flags & FB_VMODE_DOUBLE)
+			state->cursor1 |= 2;
+		state->cursor2 = 0x00000000;
+		state->pllsel = 0x10000700;
+		state->config = 0x00001114;
+		state->general = bpp == 16 ? 0x00101100 : 0x00100100;
+		state->repaint1 = hDisplaySize < 1280 ? 0x04 : 0x00;
+		break;
+	case NV_ARCH_10:
+	case NV_ARCH_20:
+	case NV_ARCH_30:
+	default:
+		if (((par->Chipset & 0xffff) == 0x01A0) ||
+		    ((par->Chipset & 0xffff) == 0x01f0)) {
+			nForceUpdateArbitrationSettings(VClk,
+							pixelDepth * 8,
+							&(state->arbitration0),
+							&(state->arbitration1),
+							par);
+		} else if (par->Architecture < NV_ARCH_30) {
+			nv10UpdateArbitrationSettings(VClk,
+						      pixelDepth * 8,
+						      &(state->arbitration0),
+						      &(state->arbitration1),
+						      par);
+		} else {
+			nv30UpdateArbitrationSettings(par,
+						      &(state->arbitration0),
+						      &(state->arbitration1));
+		}
+
+		state->cursor0 = 0x80 | (par->CursorStart >> 17);
+		state->cursor1 = (par->CursorStart >> 11) << 2;
+		state->cursor2 = par->CursorStart >> 24;
+		if (flags & FB_VMODE_DOUBLE)
+			state->cursor1 |= 2;
+		state->pllsel = 0x10000700;
+		state->config = NV_RD32(par->PFB, 0x00000200);
+		state->general = bpp == 16 ? 0x00101100 : 0x00100100;
+		state->repaint1 = hDisplaySize < 1280 ? 0x04 : 0x00;
+		break;
+	}
+
+	if (bpp != 8)		/* DirectColor */
+		state->general |= 0x00000030;
+
+	state->repaint0 = (((width / 8) * pixelDepth) & 0x700) >> 3;
+	state->pixel = (pixelDepth > 2) ? 3 : pixelDepth;
+}
+
+void NVLoadStateExt(struct nvidia_par *par, RIVA_HW_STATE * state)
+{
+	int i;
+
+	NV_WR32(par->PMC, 0x0140, 0x00000000);
+	NV_WR32(par->PMC, 0x0200, 0xFFFF00FF);
+	NV_WR32(par->PMC, 0x0200, 0xFFFFFFFF);
+
+	NV_WR32(par->PTIMER, 0x0200 * 4, 0x00000008);
+	NV_WR32(par->PTIMER, 0x0210 * 4, 0x00000003);
+	NV_WR32(par->PTIMER, 0x0140 * 4, 0x00000000);
+	NV_WR32(par->PTIMER, 0x0100 * 4, 0xFFFFFFFF);
+
+	if (par->Architecture == NV_ARCH_04) {
+		NV_WR32(par->PFB, 0x0200, state->config);
+	} else if ((par->Chipset & 0xfff0) == 0x0090) {
+		for (i = 0; i < 15; i++) {
+			NV_WR32(par->PFB, 0x0600 + (i * 0x10), 0);
+			NV_WR32(par->PFB, 0x0604 + (i * 0x10), par->FbMapSize - 1);
+		}
+	} else {
+		for (i = 0; i < 8; i++) {
+			NV_WR32(par->PFB, 0x0240 + (i * 0x10), 0);
+			NV_WR32(par->PFB, 0x0244 + (i * 0x10), par->FbMapSize - 1);
+		}
+	}
+
+	if (par->Architecture >= NV_ARCH_40) {
+		NV_WR32(par->PRAMIN, 0x0000 * 4, 0x80000010);
+		NV_WR32(par->PRAMIN, 0x0001 * 4, 0x00101202);
+		NV_WR32(par->PRAMIN, 0x0002 * 4, 0x80000011);
+		NV_WR32(par->PRAMIN, 0x0003 * 4, 0x00101204);
+		NV_WR32(par->PRAMIN, 0x0004 * 4, 0x80000012);
+		NV_WR32(par->PRAMIN, 0x0005 * 4, 0x00101206);
+		NV_WR32(par->PRAMIN, 0x0006 * 4, 0x80000013);
+		NV_WR32(par->PRAMIN, 0x0007 * 4, 0x00101208);
+		NV_WR32(par->PRAMIN, 0x0008 * 4, 0x80000014);
+		NV_WR32(par->PRAMIN, 0x0009 * 4, 0x0010120A);
+		NV_WR32(par->PRAMIN, 0x000A * 4, 0x80000015);
+		NV_WR32(par->PRAMIN, 0x000B * 4, 0x0010120C);
+		NV_WR32(par->PRAMIN, 0x000C * 4, 0x80000016);
+		NV_WR32(par->PRAMIN, 0x000D * 4, 0x0010120E);
+		NV_WR32(par->PRAMIN, 0x000E * 4, 0x80000017);
+		NV_WR32(par->PRAMIN, 0x000F * 4, 0x00101210);
+		NV_WR32(par->PRAMIN, 0x0800 * 4, 0x00003000);
+		NV_WR32(par->PRAMIN, 0x0801 * 4, par->FbMapSize - 1);
+		NV_WR32(par->PRAMIN, 0x0802 * 4, 0x00000002);
+		NV_WR32(par->PRAMIN, 0x0808 * 4, 0x02080062);
+		NV_WR32(par->PRAMIN, 0x0809 * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x080A * 4, 0x00001200);
+		NV_WR32(par->PRAMIN, 0x080B * 4, 0x00001200);
+		NV_WR32(par->PRAMIN, 0x080C * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x080D * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x0810 * 4, 0x02080043);
+		NV_WR32(par->PRAMIN, 0x0811 * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x0812 * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x0813 * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x0814 * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x0815 * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x0818 * 4, 0x02080044);
+		NV_WR32(par->PRAMIN, 0x0819 * 4, 0x02000000);
+		NV_WR32(par->PRAMIN, 0x081A * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x081B * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x081C * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x081D * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x0820 * 4, 0x02080019);
+		NV_WR32(par->PRAMIN, 0x0821 * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x0822 * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x0823 * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x0824 * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x0825 * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x0828 * 4, 0x020A005C);
+		NV_WR32(par->PRAMIN, 0x0829 * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x082A * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x082B * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x082C * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x082D * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x0830 * 4, 0x0208009F);
+		NV_WR32(par->PRAMIN, 0x0831 * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x0832 * 4, 0x00001200);
+		NV_WR32(par->PRAMIN, 0x0833 * 4, 0x00001200);
+		NV_WR32(par->PRAMIN, 0x0834 * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x0835 * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x0838 * 4, 0x0208004A);
+		NV_WR32(par->PRAMIN, 0x0839 * 4, 0x02000000);
+		NV_WR32(par->PRAMIN, 0x083A * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x083B * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x083C * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x083D * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x0840 * 4, 0x02080077);
+		NV_WR32(par->PRAMIN, 0x0841 * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x0842 * 4, 0x00001200);
+		NV_WR32(par->PRAMIN, 0x0843 * 4, 0x00001200);
+		NV_WR32(par->PRAMIN, 0x0844 * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x0845 * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x084C * 4, 0x00003002);
+		NV_WR32(par->PRAMIN, 0x084D * 4, 0x00007FFF);
+		NV_WR32(par->PRAMIN, 0x084E * 4,
+			par->FbUsableSize | 0x00000002);
+
+#ifdef __BIG_ENDIAN
+		NV_WR32(par->PRAMIN, 0x080A * 4,
+			NV_RD32(par->PRAMIN, 0x080A * 4) | 0x01000000);
+		NV_WR32(par->PRAMIN, 0x0812 * 4,
+			NV_RD32(par->PRAMIN, 0x0812 * 4) | 0x01000000);
+		NV_WR32(par->PRAMIN, 0x081A * 4,
+			NV_RD32(par->PRAMIN, 0x081A * 4) | 0x01000000);
+		NV_WR32(par->PRAMIN, 0x0822 * 4,
+			NV_RD32(par->PRAMIN, 0x0822 * 4) | 0x01000000);
+		NV_WR32(par->PRAMIN, 0x082A * 4,
+			NV_RD32(par->PRAMIN, 0x082A * 4) | 0x01000000);
+		NV_WR32(par->PRAMIN, 0x0832 * 4,
+			NV_RD32(par->PRAMIN, 0x0832 * 4) | 0x01000000);
+		NV_WR32(par->PRAMIN, 0x083A * 4,
+			NV_RD32(par->PRAMIN, 0x083A * 4) | 0x01000000);
+		NV_WR32(par->PRAMIN, 0x0842 * 4,
+			NV_RD32(par->PRAMIN, 0x0842 * 4) | 0x01000000);
+		NV_WR32(par->PRAMIN, 0x0819 * 4, 0x01000000);
+		NV_WR32(par->PRAMIN, 0x0839 * 4, 0x01000000);
+#endif
+	} else {
+		NV_WR32(par->PRAMIN, 0x0000 * 4, 0x80000010);
+		NV_WR32(par->PRAMIN, 0x0001 * 4, 0x80011201);
+		NV_WR32(par->PRAMIN, 0x0002 * 4, 0x80000011);
+		NV_WR32(par->PRAMIN, 0x0003 * 4, 0x80011202);
+		NV_WR32(par->PRAMIN, 0x0004 * 4, 0x80000012);
+		NV_WR32(par->PRAMIN, 0x0005 * 4, 0x80011203);
+		NV_WR32(par->PRAMIN, 0x0006 * 4, 0x80000013);
+		NV_WR32(par->PRAMIN, 0x0007 * 4, 0x80011204);
+		NV_WR32(par->PRAMIN, 0x0008 * 4, 0x80000014);
+		NV_WR32(par->PRAMIN, 0x0009 * 4, 0x80011205);
+		NV_WR32(par->PRAMIN, 0x000A * 4, 0x80000015);
+		NV_WR32(par->PRAMIN, 0x000B * 4, 0x80011206);
+		NV_WR32(par->PRAMIN, 0x000C * 4, 0x80000016);
+		NV_WR32(par->PRAMIN, 0x000D * 4, 0x80011207);
+		NV_WR32(par->PRAMIN, 0x000E * 4, 0x80000017);
+		NV_WR32(par->PRAMIN, 0x000F * 4, 0x80011208);
+		NV_WR32(par->PRAMIN, 0x0800 * 4, 0x00003000);
+		NV_WR32(par->PRAMIN, 0x0801 * 4, par->FbMapSize - 1);
+		NV_WR32(par->PRAMIN, 0x0802 * 4, 0x00000002);
+		NV_WR32(par->PRAMIN, 0x0803 * 4, 0x00000002);
+		if (par->Architecture >= NV_ARCH_10)
+			NV_WR32(par->PRAMIN, 0x0804 * 4, 0x01008062);
+		else
+			NV_WR32(par->PRAMIN, 0x0804 * 4, 0x01008042);
+		NV_WR32(par->PRAMIN, 0x0805 * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x0806 * 4, 0x12001200);
+		NV_WR32(par->PRAMIN, 0x0807 * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x0808 * 4, 0x01008043);
+		NV_WR32(par->PRAMIN, 0x0809 * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x080A * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x080B * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x080C * 4, 0x01008044);
+		NV_WR32(par->PRAMIN, 0x080D * 4, 0x00000002);
+		NV_WR32(par->PRAMIN, 0x080E * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x080F * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x0810 * 4, 0x01008019);
+		NV_WR32(par->PRAMIN, 0x0811 * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x0812 * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x0813 * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x0814 * 4, 0x0100A05C);
+		NV_WR32(par->PRAMIN, 0x0815 * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x0816 * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x0817 * 4, 0x00000000);
+		if (par->WaitVSyncPossible)
+			NV_WR32(par->PRAMIN, 0x0818 * 4, 0x0100809F);
+		else
+			NV_WR32(par->PRAMIN, 0x0818 * 4, 0x0100805F);
+		NV_WR32(par->PRAMIN, 0x0819 * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x081A * 4, 0x12001200);
+		NV_WR32(par->PRAMIN, 0x081B * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x081C * 4, 0x0100804A);
+		NV_WR32(par->PRAMIN, 0x081D * 4, 0x00000002);
+		NV_WR32(par->PRAMIN, 0x081E * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x081F * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x0820 * 4, 0x01018077);
+		NV_WR32(par->PRAMIN, 0x0821 * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x0822 * 4, 0x12001200);
+		NV_WR32(par->PRAMIN, 0x0823 * 4, 0x00000000);
+		NV_WR32(par->PRAMIN, 0x0824 * 4, 0x00003002);
+		NV_WR32(par->PRAMIN, 0x0825 * 4, 0x00007FFF);
+		NV_WR32(par->PRAMIN, 0x0826 * 4,
+			par->FbUsableSize | 0x00000002);
+		NV_WR32(par->PRAMIN, 0x0827 * 4, 0x00000002);
+#ifdef __BIG_ENDIAN
+		NV_WR32(par->PRAMIN, 0x0804 * 4,
+			NV_RD32(par->PRAMIN, 0x0804 * 4) | 0x00080000);
+		NV_WR32(par->PRAMIN, 0x0808 * 4,
+			NV_RD32(par->PRAMIN, 0x0808 * 4) | 0x00080000);
+		NV_WR32(par->PRAMIN, 0x080C * 4,
+			NV_RD32(par->PRAMIN, 0x080C * 4) | 0x00080000);
+		NV_WR32(par->PRAMIN, 0x0810 * 4,
+			NV_RD32(par->PRAMIN, 0x0810 * 4) | 0x00080000);
+		NV_WR32(par->PRAMIN, 0x0814 * 4,
+			NV_RD32(par->PRAMIN, 0x0814 * 4) | 0x00080000);
+		NV_WR32(par->PRAMIN, 0x0818 * 4,
+			NV_RD32(par->PRAMIN, 0x0818 * 4) | 0x00080000);
+		NV_WR32(par->PRAMIN, 0x081C * 4,
+			NV_RD32(par->PRAMIN, 0x081C * 4) | 0x00080000);
+		NV_WR32(par->PRAMIN, 0x0820 * 4,
+			NV_RD32(par->PRAMIN, 0x0820 * 4) | 0x00080000);
+		NV_WR32(par->PRAMIN, 0x080D * 4, 0x00000001);
+		NV_WR32(par->PRAMIN, 0x081D * 4, 0x00000001);
+#endif
+	}
+	if (par->Architecture < NV_ARCH_10) {
+		if ((par->Chipset & 0x0fff) == 0x0020) {
+			NV_WR32(par->PRAMIN, 0x0824 * 4,
+				NV_RD32(par->PRAMIN, 0x0824 * 4) | 0x00020000);
+			NV_WR32(par->PRAMIN, 0x0826 * 4,
+				NV_RD32(par->PRAMIN,
+					0x0826 * 4) + par->FbAddress);
+		}
+		NV_WR32(par->PGRAPH, 0x0080, 0x000001FF);
+		NV_WR32(par->PGRAPH, 0x0080, 0x1230C000);
+		NV_WR32(par->PGRAPH, 0x0084, 0x72111101);
+		NV_WR32(par->PGRAPH, 0x0088, 0x11D5F071);
+		NV_WR32(par->PGRAPH, 0x008C, 0x0004FF31);
+		NV_WR32(par->PGRAPH, 0x008C, 0x4004FF31);
+		NV_WR32(par->PGRAPH, 0x0140, 0x00000000);
+		NV_WR32(par->PGRAPH, 0x0100, 0xFFFFFFFF);
+		NV_WR32(par->PGRAPH, 0x0170, 0x10010100);
+		NV_WR32(par->PGRAPH, 0x0710, 0xFFFFFFFF);
+		NV_WR32(par->PGRAPH, 0x0720, 0x00000001);
+		NV_WR32(par->PGRAPH, 0x0810, 0x00000000);
+		NV_WR32(par->PGRAPH, 0x0608, 0xFFFFFFFF);
+	} else {
+		NV_WR32(par->PGRAPH, 0x0080, 0xFFFFFFFF);
+		NV_WR32(par->PGRAPH, 0x0080, 0x00000000);
+
+		NV_WR32(par->PGRAPH, 0x0140, 0x00000000);
+		NV_WR32(par->PGRAPH, 0x0100, 0xFFFFFFFF);
+		NV_WR32(par->PGRAPH, 0x0144, 0x10010100);
+		NV_WR32(par->PGRAPH, 0x0714, 0xFFFFFFFF);
+		NV_WR32(par->PGRAPH, 0x0720, 0x00000001);
+		NV_WR32(par->PGRAPH, 0x0710,
+			NV_RD32(par->PGRAPH, 0x0710) & 0x0007ff00);
+		NV_WR32(par->PGRAPH, 0x0710,
+			NV_RD32(par->PGRAPH, 0x0710) | 0x00020100);
+
+		if (par->Architecture == NV_ARCH_10) {
+			NV_WR32(par->PGRAPH, 0x0084, 0x00118700);
+			NV_WR32(par->PGRAPH, 0x0088, 0x24E00810);
+			NV_WR32(par->PGRAPH, 0x008C, 0x55DE0030);
+
+			for (i = 0; i < 32; i++)
+				NV_WR32(&par->PGRAPH[(0x0B00 / 4) + i], 0,
+					NV_RD32(&par->PFB[(0x0240 / 4) + i],
+						0));
+
+			NV_WR32(par->PGRAPH, 0x640, 0);
+			NV_WR32(par->PGRAPH, 0x644, 0);
+			NV_WR32(par->PGRAPH, 0x684, par->FbMapSize - 1);
+			NV_WR32(par->PGRAPH, 0x688, par->FbMapSize - 1);
+
+			NV_WR32(par->PGRAPH, 0x0810, 0x00000000);
+			NV_WR32(par->PGRAPH, 0x0608, 0xFFFFFFFF);
+		} else {
+			if (par->Architecture >= NV_ARCH_40) {
+				NV_WR32(par->PGRAPH, 0x0084, 0x401287c0);
+				NV_WR32(par->PGRAPH, 0x008C, 0x60de8051);
+				NV_WR32(par->PGRAPH, 0x0090, 0x00008000);
+				NV_WR32(par->PGRAPH, 0x0610, 0x00be3c5f);
+
+				if ((par->Chipset & 0xfff0) == 0x0040) {
+					NV_WR32(par->PGRAPH, 0x09b0,
+						0x83280fff);
+					NV_WR32(par->PGRAPH, 0x09b4,
+						0x000000a0);
+				} else {
+					NV_WR32(par->PGRAPH, 0x0820,
+						0x83280eff);
+					NV_WR32(par->PGRAPH, 0x0824,
+						0x000000a0);
+				}
+
+				switch (par->Chipset & 0xfff0) {
+				case 0x0040:
+				case 0x0210:
+					NV_WR32(par->PGRAPH, 0x09b8,
+						0x0078e366);
+					NV_WR32(par->PGRAPH, 0x09bc,
+						0x0000014c);
+					NV_WR32(par->PFB, 0x033C,
+						NV_RD32(par->PFB, 0x33C) &
+						0xffff7fff);
+					break;
+				case 0x00C0:
+					NV_WR32(par->PGRAPH, 0x0828,
+						0x007596ff);
+					NV_WR32(par->PGRAPH, 0x082C,
+						0x00000108);
+					break;
+				case 0x0160:
+				case 0x01D0:
+					NV_WR32(par->PMC, 0x1700,
+						NV_RD32(par->PFB, 0x020C));
+					NV_WR32(par->PMC, 0x1704, 0);
+					NV_WR32(par->PMC, 0x1708, 0);
+					NV_WR32(par->PMC, 0x170C,
+						NV_RD32(par->PFB, 0x020C));
+					NV_WR32(par->PGRAPH, 0x0860, 0);
+					NV_WR32(par->PGRAPH, 0x0864, 0);
+					NV_WR32(par->PRAMDAC, 0x0608,
+						NV_RD32(par->PRAMDAC,
+							0x0608) | 0x00100000);
+					break;
+				case 0x0140:
+					NV_WR32(par->PGRAPH, 0x0828,
+						0x0072cb77);
+					NV_WR32(par->PGRAPH, 0x082C,
+						0x00000108);
+					break;
+				case 0x0220:
+				case 0x0230:
+					NV_WR32(par->PGRAPH, 0x0860, 0);
+					NV_WR32(par->PGRAPH, 0x0864, 0);
+					NV_WR32(par->PRAMDAC, 0x0608,
+						NV_RD32(par->PRAMDAC, 0x0608) |
+						0x00100000);
+					break;
+				case 0x0090:
+					NV_WR32(par->PRAMDAC, 0x0608,
+						NV_RD32(par->PRAMDAC, 0x0608) |
+						0x00100000);
+					NV_WR32(par->PGRAPH, 0x0828,
+						0x07830610);
+					NV_WR32(par->PGRAPH, 0x082C,
+						0x0000016A);
+					break;
+				default:
+					break;
+				};
+
+				NV_WR32(par->PGRAPH, 0x0b38, 0x2ffff800);
+				NV_WR32(par->PGRAPH, 0x0b3c, 0x00006000);
+				NV_WR32(par->PGRAPH, 0x032C, 0x01000000);
+				NV_WR32(par->PGRAPH, 0x0220, 0x00001200);
+			} else if (par->Architecture == NV_ARCH_30) {
+				NV_WR32(par->PGRAPH, 0x0084, 0x40108700);
+				NV_WR32(par->PGRAPH, 0x0890, 0x00140000);
+				NV_WR32(par->PGRAPH, 0x008C, 0xf00e0431);
+				NV_WR32(par->PGRAPH, 0x0090, 0x00008000);
+				NV_WR32(par->PGRAPH, 0x0610, 0xf04b1f36);
+				NV_WR32(par->PGRAPH, 0x0B80, 0x1002d888);
+				NV_WR32(par->PGRAPH, 0x0B88, 0x62ff007f);
+			} else {
+				NV_WR32(par->PGRAPH, 0x0084, 0x00118700);
+				NV_WR32(par->PGRAPH, 0x008C, 0xF20E0431);
+				NV_WR32(par->PGRAPH, 0x0090, 0x00000000);
+				NV_WR32(par->PGRAPH, 0x009C, 0x00000040);
+
+				if ((par->Chipset & 0x0ff0) >= 0x0250) {
+					NV_WR32(par->PGRAPH, 0x0890,
+						0x00080000);
+					NV_WR32(par->PGRAPH, 0x0610,
+						0x304B1FB6);
+					NV_WR32(par->PGRAPH, 0x0B80,
+						0x18B82880);
+					NV_WR32(par->PGRAPH, 0x0B84,
+						0x44000000);
+					NV_WR32(par->PGRAPH, 0x0098,
+						0x40000080);
+					NV_WR32(par->PGRAPH, 0x0B88,
+						0x000000ff);
+				} else {
+					NV_WR32(par->PGRAPH, 0x0880,
+						0x00080000);
+					NV_WR32(par->PGRAPH, 0x0094,
+						0x00000005);
+					NV_WR32(par->PGRAPH, 0x0B80,
+						0x45CAA208);
+					NV_WR32(par->PGRAPH, 0x0B84,
+						0x24000000);
+					NV_WR32(par->PGRAPH, 0x0098,
+						0x00000040);
+					NV_WR32(par->PGRAPH, 0x0750,
+						0x00E00038);
+					NV_WR32(par->PGRAPH, 0x0754,
+						0x00000030);
+					NV_WR32(par->PGRAPH, 0x0750,
+						0x00E10038);
+					NV_WR32(par->PGRAPH, 0x0754,
+						0x00000030);
+				}
+			}
+
+			if ((par->Chipset & 0xfff0) == 0x0090) {
+				for (i = 0; i < 60; i++)
+					NV_WR32(par->PGRAPH, 0x0D00 + i,
+						NV_RD32(par->PFB, 0x0600 + i));
+			} else {
+				for (i = 0; i < 32; i++)
+					NV_WR32(par->PGRAPH, 0x0900 + i,
+						NV_RD32(par->PFB, 0x0240 + i));
+			}
+
+			if (par->Architecture >= NV_ARCH_40) {
+				if ((par->Chipset & 0xfff0) == 0x0040) {
+					NV_WR32(par->PGRAPH, 0x09A4,
+						NV_RD32(par->PFB, 0x0200));
+					NV_WR32(par->PGRAPH, 0x09A8,
+						NV_RD32(par->PFB, 0x0204));
+					NV_WR32(par->PGRAPH, 0x69A4,
+						NV_RD32(par->PFB, 0x0200));
+					NV_WR32(par->PGRAPH, 0x69A8,
+						NV_RD32(par->PFB, 0x0204));
+
+					NV_WR32(par->PGRAPH, 0x0820, 0);
+					NV_WR32(par->PGRAPH, 0x0824, 0);
+					NV_WR32(par->PGRAPH, 0x0864,
+						par->FbMapSize - 1);
+					NV_WR32(par->PGRAPH, 0x0868,
+						par->FbMapSize - 1);
+				} else {
+					if((par->Chipset & 0xfff0) == 0x0090) {
+						NV_WR32(par->PGRAPH, 0x0DF0,
+							NV_RD32(par->PFB, 0x0200));
+						NV_WR32(par->PGRAPH, 0x0DF4,
+							NV_RD32(par->PFB, 0x0204));
+					} else {
+						NV_WR32(par->PGRAPH, 0x09F0,
+							NV_RD32(par->PFB, 0x0200));
+						NV_WR32(par->PGRAPH, 0x09F4,
+							NV_RD32(par->PFB, 0x0204));
+					}
+					NV_WR32(par->PGRAPH, 0x69F0,
+						NV_RD32(par->PFB, 0x0200));
+					NV_WR32(par->PGRAPH, 0x69F4,
+						NV_RD32(par->PFB, 0x0204));
+
+					NV_WR32(par->PGRAPH, 0x0840, 0);
+					NV_WR32(par->PGRAPH, 0x0844, 0);
+					NV_WR32(par->PGRAPH, 0x08a0,
+						par->FbMapSize - 1);
+					NV_WR32(par->PGRAPH, 0x08a4,
+						par->FbMapSize - 1);
+				}
+			} else {
+				NV_WR32(par->PGRAPH, 0x09A4,
+					NV_RD32(par->PFB, 0x0200));
+				NV_WR32(par->PGRAPH, 0x09A8,
+					NV_RD32(par->PFB, 0x0204));
+				NV_WR32(par->PGRAPH, 0x0750, 0x00EA0000);
+				NV_WR32(par->PGRAPH, 0x0754,
+					NV_RD32(par->PFB, 0x0200));
+				NV_WR32(par->PGRAPH, 0x0750, 0x00EA0004);
+				NV_WR32(par->PGRAPH, 0x0754,
+					NV_RD32(par->PFB, 0x0204));
+
+				NV_WR32(par->PGRAPH, 0x0820, 0);
+				NV_WR32(par->PGRAPH, 0x0824, 0);
+				NV_WR32(par->PGRAPH, 0x0864,
+					par->FbMapSize - 1);
+				NV_WR32(par->PGRAPH, 0x0868,
+					par->FbMapSize - 1);
+			}
+			NV_WR32(par->PGRAPH, 0x0B20, 0x00000000);
+			NV_WR32(par->PGRAPH, 0x0B04, 0xFFFFFFFF);
+		}
+	}
+	NV_WR32(par->PGRAPH, 0x053C, 0);
+	NV_WR32(par->PGRAPH, 0x0540, 0);
+	NV_WR32(par->PGRAPH, 0x0544, 0x00007FFF);
+	NV_WR32(par->PGRAPH, 0x0548, 0x00007FFF);
+
+	NV_WR32(par->PFIFO, 0x0140 * 4, 0x00000000);
+	NV_WR32(par->PFIFO, 0x0141 * 4, 0x00000001);
+	NV_WR32(par->PFIFO, 0x0480 * 4, 0x00000000);
+	NV_WR32(par->PFIFO, 0x0494 * 4, 0x00000000);
+	if (par->Architecture >= NV_ARCH_40)
+		NV_WR32(par->PFIFO, 0x0481 * 4, 0x00010000);
+	else
+		NV_WR32(par->PFIFO, 0x0481 * 4, 0x00000100);
+	NV_WR32(par->PFIFO, 0x0490 * 4, 0x00000000);
+	NV_WR32(par->PFIFO, 0x0491 * 4, 0x00000000);
+	if (par->Architecture >= NV_ARCH_40)
+		NV_WR32(par->PFIFO, 0x048B * 4, 0x00001213);
+	else
+		NV_WR32(par->PFIFO, 0x048B * 4, 0x00001209);
+	NV_WR32(par->PFIFO, 0x0400 * 4, 0x00000000);
+	NV_WR32(par->PFIFO, 0x0414 * 4, 0x00000000);
+	NV_WR32(par->PFIFO, 0x0084 * 4, 0x03000100);
+	NV_WR32(par->PFIFO, 0x0085 * 4, 0x00000110);
+	NV_WR32(par->PFIFO, 0x0086 * 4, 0x00000112);
+	NV_WR32(par->PFIFO, 0x0143 * 4, 0x0000FFFF);
+	NV_WR32(par->PFIFO, 0x0496 * 4, 0x0000FFFF);
+	NV_WR32(par->PFIFO, 0x0050 * 4, 0x00000000);
+	NV_WR32(par->PFIFO, 0x0040 * 4, 0xFFFFFFFF);
+	NV_WR32(par->PFIFO, 0x0415 * 4, 0x00000001);
+	NV_WR32(par->PFIFO, 0x048C * 4, 0x00000000);
+	NV_WR32(par->PFIFO, 0x04A0 * 4, 0x00000000);
+#ifdef __BIG_ENDIAN
+	NV_WR32(par->PFIFO, 0x0489 * 4, 0x800F0078);
+#else
+	NV_WR32(par->PFIFO, 0x0489 * 4, 0x000F0078);
+#endif
+	NV_WR32(par->PFIFO, 0x0488 * 4, 0x00000001);
+	NV_WR32(par->PFIFO, 0x0480 * 4, 0x00000001);
+	NV_WR32(par->PFIFO, 0x0494 * 4, 0x00000001);
+	NV_WR32(par->PFIFO, 0x0495 * 4, 0x00000001);
+	NV_WR32(par->PFIFO, 0x0140 * 4, 0x00000001);
+	if (par->Architecture >= NV_ARCH_10) {
+		if (par->twoHeads) {
+			NV_WR32(par->PCRTC0, 0x0860, state->head);
+			NV_WR32(par->PCRTC0, 0x2860, state->head2);
+		}
+		NV_WR32(par->PRAMDAC, 0x0404, NV_RD32(par->PRAMDAC, 0x0404) |
+			(1 << 25));
+
+		NV_WR32(par->PMC, 0x8704, 1);
+		NV_WR32(par->PMC, 0x8140, 0);
+		NV_WR32(par->PMC, 0x8920, 0);
+		NV_WR32(par->PMC, 0x8924, 0);
+		NV_WR32(par->PMC, 0x8908, par->FbMapSize - 1);
+		NV_WR32(par->PMC, 0x890C, par->FbMapSize - 1);
+		NV_WR32(par->PMC, 0x1588, 0);
+
+		NV_WR32(par->PCRTC, 0x0810, state->cursorConfig);
+		NV_WR32(par->PCRTC, 0x0830, state->displayV - 3);
+		NV_WR32(par->PCRTC, 0x0834, state->displayV - 1);
+
+		if (par->FlatPanel) {
+			if ((par->Chipset & 0x0ff0) == 0x0110) {
+				NV_WR32(par->PRAMDAC, 0x0528, state->dither);
+			} else if (par->twoHeads) {
+				NV_WR32(par->PRAMDAC, 0x083C, state->dither);
+			}
+
+			VGA_WR08(par->PCIO, 0x03D4, 0x53);
+			VGA_WR08(par->PCIO, 0x03D5, state->timingH);
+			VGA_WR08(par->PCIO, 0x03D4, 0x54);
+			VGA_WR08(par->PCIO, 0x03D5, state->timingV);
+			VGA_WR08(par->PCIO, 0x03D4, 0x21);
+			VGA_WR08(par->PCIO, 0x03D5, 0xfa);
+		}
+
+		VGA_WR08(par->PCIO, 0x03D4, 0x41);
+		VGA_WR08(par->PCIO, 0x03D5, state->extra);
+	}
+
+	VGA_WR08(par->PCIO, 0x03D4, 0x19);
+	VGA_WR08(par->PCIO, 0x03D5, state->repaint0);
+	VGA_WR08(par->PCIO, 0x03D4, 0x1A);
+	VGA_WR08(par->PCIO, 0x03D5, state->repaint1);
+	VGA_WR08(par->PCIO, 0x03D4, 0x25);
+	VGA_WR08(par->PCIO, 0x03D5, state->screen);
+	VGA_WR08(par->PCIO, 0x03D4, 0x28);
+	VGA_WR08(par->PCIO, 0x03D5, state->pixel);
+	VGA_WR08(par->PCIO, 0x03D4, 0x2D);
+	VGA_WR08(par->PCIO, 0x03D5, state->horiz);
+	VGA_WR08(par->PCIO, 0x03D4, 0x1C);
+	VGA_WR08(par->PCIO, 0x03D5, state->fifo);
+	VGA_WR08(par->PCIO, 0x03D4, 0x1B);
+	VGA_WR08(par->PCIO, 0x03D5, state->arbitration0);
+	VGA_WR08(par->PCIO, 0x03D4, 0x20);
+	VGA_WR08(par->PCIO, 0x03D5, state->arbitration1);
+
+	if(par->Architecture >= NV_ARCH_30) {
+		VGA_WR08(par->PCIO, 0x03D4, 0x47);
+		VGA_WR08(par->PCIO, 0x03D5, state->arbitration1 >> 8);
+	}
+
+	VGA_WR08(par->PCIO, 0x03D4, 0x30);
+	VGA_WR08(par->PCIO, 0x03D5, state->cursor0);
+	VGA_WR08(par->PCIO, 0x03D4, 0x31);
+	VGA_WR08(par->PCIO, 0x03D5, state->cursor1);
+	VGA_WR08(par->PCIO, 0x03D4, 0x2F);
+	VGA_WR08(par->PCIO, 0x03D5, state->cursor2);
+	VGA_WR08(par->PCIO, 0x03D4, 0x39);
+	VGA_WR08(par->PCIO, 0x03D5, state->interlace);
+
+	if (!par->FlatPanel) {
+		NV_WR32(par->PRAMDAC0, 0x050C, state->pllsel);
+		NV_WR32(par->PRAMDAC0, 0x0508, state->vpll);
+		if (par->twoHeads)
+			NV_WR32(par->PRAMDAC0, 0x0520, state->vpll2);
+		if (par->twoStagePLL) {
+			NV_WR32(par->PRAMDAC0, 0x0578, state->vpllB);
+			NV_WR32(par->PRAMDAC0, 0x057C, state->vpll2B);
+		}
+	} else {
+		NV_WR32(par->PRAMDAC, 0x0848, state->scale);
+		NV_WR32(par->PRAMDAC, 0x0828, state->crtcSync +
+			par->PanelTweak);
+	}
+
+	NV_WR32(par->PRAMDAC, 0x0600, state->general);
+
+	NV_WR32(par->PCRTC, 0x0140, 0);
+	NV_WR32(par->PCRTC, 0x0100, 1);
+
+	par->CurrentState = state;
+}
+
+void NVUnloadStateExt(struct nvidia_par *par, RIVA_HW_STATE * state) {
+	VGA_WR08(par->PCIO, 0x03D4, 0x19);
+	state->repaint0 = VGA_RD08(par->PCIO, 0x03D5);
+	VGA_WR08(par->PCIO, 0x03D4, 0x1A);
+	state->repaint1 = VGA_RD08(par->PCIO, 0x03D5);
+	VGA_WR08(par->PCIO, 0x03D4, 0x25);
+	state->screen = VGA_RD08(par->PCIO, 0x03D5);
+	VGA_WR08(par->PCIO, 0x03D4, 0x28);
+	state->pixel = VGA_RD08(par->PCIO, 0x03D5);
+	VGA_WR08(par->PCIO, 0x03D4, 0x2D);
+	state->horiz = VGA_RD08(par->PCIO, 0x03D5);
+	VGA_WR08(par->PCIO, 0x03D4, 0x1C);
+	state->fifo         = VGA_RD08(par->PCIO, 0x03D5);
+	VGA_WR08(par->PCIO, 0x03D4, 0x1B);
+	state->arbitration0 = VGA_RD08(par->PCIO, 0x03D5);
+	VGA_WR08(par->PCIO, 0x03D4, 0x20);
+	state->arbitration1 = VGA_RD08(par->PCIO, 0x03D5);
+
+	if(par->Architecture >= NV_ARCH_30) {
+		VGA_WR08(par->PCIO, 0x03D4, 0x47);
+		state->arbitration1 |= (VGA_RD08(par->PCIO, 0x03D5) & 1) << 8;
+	}
+
+	VGA_WR08(par->PCIO, 0x03D4, 0x30);
+	state->cursor0 = VGA_RD08(par->PCIO, 0x03D5);
+	VGA_WR08(par->PCIO, 0x03D4, 0x31);
+	state->cursor1 = VGA_RD08(par->PCIO, 0x03D5);
+	VGA_WR08(par->PCIO, 0x03D4, 0x2F);
+	state->cursor2 = VGA_RD08(par->PCIO, 0x03D5);
+	VGA_WR08(par->PCIO, 0x03D4, 0x39);
+	state->interlace = VGA_RD08(par->PCIO, 0x03D5);
+	state->vpll = NV_RD32(par->PRAMDAC0, 0x0508);
+	if (par->twoHeads)
+		state->vpll2 = NV_RD32(par->PRAMDAC0, 0x0520);
+	if (par->twoStagePLL) {
+		state->vpllB = NV_RD32(par->PRAMDAC0, 0x0578);
+		state->vpll2B = NV_RD32(par->PRAMDAC0, 0x057C);
+	}
+	state->pllsel = NV_RD32(par->PRAMDAC0, 0x050C);
+	state->general = NV_RD32(par->PRAMDAC, 0x0600);
+	state->scale = NV_RD32(par->PRAMDAC, 0x0848);
+	state->config = NV_RD32(par->PFB, 0x0200);
+
+	if (par->Architecture >= NV_ARCH_10) {
+		if (par->twoHeads) {
+			state->head = NV_RD32(par->PCRTC0, 0x0860);
+			state->head2 = NV_RD32(par->PCRTC0, 0x2860);
+			VGA_WR08(par->PCIO, 0x03D4, 0x44);
+			state->crtcOwner = VGA_RD08(par->PCIO, 0x03D5);
+		}
+		VGA_WR08(par->PCIO, 0x03D4, 0x41);
+		state->extra = VGA_RD08(par->PCIO, 0x03D5);
+		state->cursorConfig = NV_RD32(par->PCRTC, 0x0810);
+
+		if ((par->Chipset & 0x0ff0) == 0x0110) {
+			state->dither = NV_RD32(par->PRAMDAC, 0x0528);
+		} else if (par->twoHeads) {
+			state->dither = NV_RD32(par->PRAMDAC, 0x083C);
+		}
+
+		if (par->FlatPanel) {
+			VGA_WR08(par->PCIO, 0x03D4, 0x53);
+			state->timingH = VGA_RD08(par->PCIO, 0x03D5);
+			VGA_WR08(par->PCIO, 0x03D4, 0x54);
+			state->timingV = VGA_RD08(par->PCIO, 0x03D5);
+		}
+	}
+}
+
+void NVSetStartAddress(struct nvidia_par *par, u32 start)
+{
+	NV_WR32(par->PCRTC, 0x800, start);
+}
diff -Nru a/drivers/video/nvidia/nv_i2c.c b/drivers/video/nvidia/nv_i2c.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/video/nvidia/nv_i2c.c	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,217 @@
+/*
+ * linux/drivers/video/nvidia/nvidia-i2c.c - nVidia i2c
+ *
+ * Copyright 2004 Antonino A. Daplas <adaplas @pol.net>
+ *
+ * Based on rivafb-i2c.c
+ *
+ * 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/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/delay.h>
+#include <linux/pci.h>
+#include <linux/fb.h>
+
+#include <asm/io.h>
+
+#include "nv_type.h"
+#include "nv_local.h"
+#include "nv_proto.h"
+
+#include "../edid.h"
+
+static void nvidia_gpio_setscl(void *data, int state)
+{
+	struct nvidia_i2c_chan *chan = data;
+	struct nvidia_par *par = chan->par;
+	u32 val;
+
+	VGA_WR08(par->PCIO, 0x3d4, chan->ddc_base + 1);
+	val = VGA_RD08(par->PCIO, 0x3d5) & 0xf0;
+
+	if (state)
+		val |= 0x20;
+	else
+		val &= ~0x20;
+
+	VGA_WR08(par->PCIO, 0x3d4, chan->ddc_base + 1);
+	VGA_WR08(par->PCIO, 0x3d5, val | 0x1);
+}
+
+static void nvidia_gpio_setsda(void *data, int state)
+{
+	struct nvidia_i2c_chan *chan = (struct nvidia_i2c_chan *)data;
+	struct nvidia_par *par = chan->par;
+	u32 val;
+
+	VGA_WR08(par->PCIO, 0x3d4, chan->ddc_base + 1);
+	val = VGA_RD08(par->PCIO, 0x3d5) & 0xf0;
+
+	if (state)
+		val |= 0x10;
+	else
+		val &= ~0x10;
+
+	VGA_WR08(par->PCIO, 0x3d4, chan->ddc_base + 1);
+	VGA_WR08(par->PCIO, 0x3d5, val | 0x1);
+}
+
+static int nvidia_gpio_getscl(void *data)
+{
+	struct nvidia_i2c_chan *chan = (struct nvidia_i2c_chan *)data;
+	struct nvidia_par *par = chan->par;
+	u32 val = 0;
+
+	VGA_WR08(par->PCIO, 0x3d4, chan->ddc_base);
+	if (VGA_RD08(par->PCIO, 0x3d5) & 0x04)
+		val = 1;
+
+	val = VGA_RD08(par->PCIO, 0x3d5);
+
+	return val;
+}
+
+static int nvidia_gpio_getsda(void *data)
+{
+	struct nvidia_i2c_chan *chan = (struct nvidia_i2c_chan *)data;
+	struct nvidia_par *par = chan->par;
+	u32 val = 0;
+
+	VGA_WR08(par->PCIO, 0x3d4, chan->ddc_base);
+	if (VGA_RD08(par->PCIO, 0x3d5) & 0x08)
+		val = 1;
+
+	return val;
+}
+
+#define I2C_ALGO_NVIDIA   0x0e0000
+static int nvidia_setup_i2c_bus(struct nvidia_i2c_chan *chan, const char *name)
+{
+	int rc;
+
+	strcpy(chan->adapter.name, name);
+	chan->adapter.owner = THIS_MODULE;
+	chan->adapter.id = I2C_ALGO_NVIDIA;
+	chan->adapter.algo_data = &chan->algo;
+	chan->adapter.dev.parent = &chan->par->pci_dev->dev;
+	chan->algo.setsda = nvidia_gpio_setsda;
+	chan->algo.setscl = nvidia_gpio_setscl;
+	chan->algo.getsda = nvidia_gpio_getsda;
+	chan->algo.getscl = nvidia_gpio_getscl;
+	chan->algo.udelay = 40;
+	chan->algo.timeout = msecs_to_jiffies(2);
+	chan->algo.data = chan;
+
+	i2c_set_adapdata(&chan->adapter, chan);
+
+	/* Raise SCL and SDA */
+	nvidia_gpio_setsda(chan, 1);
+	nvidia_gpio_setscl(chan, 1);
+	udelay(20);
+
+	rc = i2c_bit_add_bus(&chan->adapter);
+	if (rc == 0)
+		dev_dbg(&chan->par->pci_dev->dev,
+			"I2C bus %s registered.\n", name);
+	else {
+		dev_warn(&chan->par->pci_dev->dev,
+			 "Failed to register I2C bus %s.\n", name);
+		chan->par = NULL;
+	}
+
+	return rc;
+}
+
+void nvidia_create_i2c_busses(struct nvidia_par *par)
+{
+	par->bus = 3;
+
+	par->chan[0].par = par;
+	par->chan[1].par = par;
+	par->chan[2].par = par;
+
+	par->chan[0].ddc_base = 0x3e;
+	nvidia_setup_i2c_bus(&par->chan[0], "BUS1");
+
+	par->chan[1].ddc_base = 0x36;
+	nvidia_setup_i2c_bus(&par->chan[1], "BUS2");
+
+	par->chan[2].ddc_base = 0x50;
+	nvidia_setup_i2c_bus(&par->chan[2], "BUS3");
+}
+
+#if 0
+void nvidia_delete_i2c_busses(struct nvidia_par *par)
+{
+	if (par->chan[0].par)
+		i2c_bit_del_bus(&par->chan[0].adapter);
+	par->chan[0].par = NULL;
+
+	if (par->chan[1].par)
+		i2c_bit_del_bus(&par->chan[1].adapter);
+	par->chan[1].par = NULL;
+
+	if (par->chan[2].par)
+		i2c_bit_del_bus(&par->chan[2].adapter);
+	par->chan[2].par = NULL;
+
+}
+#endif  /*  0  */
+
+static u8 *nvidia_do_probe_i2c_edid(struct nvidia_i2c_chan *chan)
+{
+	u8 start = 0x0;
+	struct i2c_msg msgs[] = {
+		{
+		 .addr = 0x50,
+		 .len = 1,
+		 .buf = &start,
+		 }, {
+		     .addr = 0x50,
+		     .flags = I2C_M_RD,
+		     .len = EDID_LENGTH,
+		     },
+	};
+	u8 *buf;
+
+	if (!chan->par)
+		return NULL;
+
+	buf = kmalloc(EDID_LENGTH, GFP_KERNEL);
+	if (!buf) {
+		dev_warn(&chan->par->pci_dev->dev, "Out of memory!\n");
+		return NULL;
+	}
+	msgs[1].buf = buf;
+
+	if (i2c_transfer(&chan->adapter, msgs, 2) == 2)
+		return buf;
+	dev_dbg(&chan->par->pci_dev->dev, "Unable to read EDID block.\n");
+	kfree(buf);
+	return NULL;
+}
+
+int nvidia_probe_i2c_connector(struct nvidia_par *par, int conn, u8 **out_edid)
+{
+	u8 *edid = NULL;
+	int i;
+
+	for (i = 0; i < 3; i++) {
+		/* Do the real work */
+		edid = nvidia_do_probe_i2c_edid(&par->chan[conn - 1]);
+		if (edid)
+			break;
+	}
+	if (out_edid)
+		*out_edid = edid;
+	if (!edid)
+		return 1;
+
+	return 0;
+}
diff -Nru a/drivers/video/nvidia/nv_local.h b/drivers/video/nvidia/nv_local.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/video/nvidia/nv_local.h	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,98 @@
+/***************************************************************************\
+|*                                                                           *|
+|*       Copyright 1993-2003 NVIDIA, Corporation.  All rights reserved.      *|
+|*                                                                           *|
+|*     NOTICE TO USER:   The source code  is copyrighted under  U.S. and     *|
+|*     international laws.  Users and possessors of this source code are     *|
+|*     hereby granted a nonexclusive,  royalty-free copyright license to     *|
+|*     use this code in individual and commercial software.                  *|
+|*                                                                           *|
+|*     Any use of this source code must include,  in the user documenta-     *|
+|*     tion and  internal comments to the code,  notices to the end user     *|
+|*     as follows:                                                           *|
+|*                                                                           *|
+|*       Copyright 1993-1999 NVIDIA, Corporation.  All rights reserved.      *|
+|*                                                                           *|
+|*     NVIDIA, CORPORATION MAKES NO REPRESENTATION ABOUT THE SUITABILITY     *|
+|*     OF  THIS SOURCE  CODE  FOR ANY PURPOSE.  IT IS  PROVIDED  "AS IS"     *|
+|*     WITHOUT EXPRESS OR IMPLIED WARRANTY OF ANY KIND.  NVIDIA, CORPOR-     *|
+|*     ATION DISCLAIMS ALL WARRANTIES  WITH REGARD  TO THIS SOURCE CODE,     *|
+|*     INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGE-     *|
+|*     MENT,  AND FITNESS  FOR A PARTICULAR PURPOSE.   IN NO EVENT SHALL     *|
+|*     NVIDIA, CORPORATION  BE LIABLE FOR ANY SPECIAL,  INDIRECT,  INCI-     *|
+|*     DENTAL, OR CONSEQUENTIAL DAMAGES,  OR ANY DAMAGES  WHATSOEVER RE-     *|
+|*     SULTING FROM LOSS OF USE,  DATA OR PROFITS,  WHETHER IN AN ACTION     *|
+|*     OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,  ARISING OUT OF     *|
+|*     OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOURCE CODE.     *|
+|*                                                                           *|
+|*     U.S. Government  End  Users.   This source code  is a "commercial     *|
+|*     item,"  as that  term is  defined at  48 C.F.R. 2.101 (OCT 1995),     *|
+|*     consisting  of "commercial  computer  software"  and  "commercial     *|
+|*     computer  software  documentation,"  as such  terms  are  used in     *|
+|*     48 C.F.R. 12.212 (SEPT 1995)  and is provided to the U.S. Govern-     *|
+|*     ment only as  a commercial end item.   Consistent with  48 C.F.R.     *|
+|*     12.212 and  48 C.F.R. 227.7202-1 through  227.7202-4 (JUNE 1995),     *|
+|*     all U.S. Government End Users  acquire the source code  with only     *|
+|*     those rights set forth herein.                                        *|
+|*                                                                           *|
+ \***************************************************************************/
+
+#ifndef __NV_LOCAL_H__
+#define __NV_LOCAL_H__
+
+/*
+ * This file includes any environment or machine specific values to access the
+ * HW.  Put all affected includes, typdefs, etc. here so the riva_hw.* files
+ * can stay generic in nature.
+ */
+
+/*
+ * HW access macros.  These assume memory-mapped I/O, and not normal I/O space.
+ */
+#define NV_WR08(p,i,d)  (__raw_writeb((d), (void __iomem *)(p) + (i)))
+#define NV_RD08(p,i)    (__raw_readb((void __iomem *)(p) + (i)))
+#define NV_WR16(p,i,d)  (__raw_writew((d), (void __iomem *)(p) + (i)))
+#define NV_RD16(p,i)    (__raw_readw((void __iomem *)(p) + (i)))
+#define NV_WR32(p,i,d)  (__raw_writel((d), (void __iomem *)(p) + (i)))
+#define NV_RD32(p,i)    (__raw_readl((void __iomem *)(p) + (i)))
+
+/* VGA I/O is now always done through MMIO */
+#define VGA_WR08(p,i,d) (writeb((d), (void __iomem *)(p) + (i)))
+#define VGA_RD08(p,i)   (readb((void __iomem *)(p) + (i)))
+
+#define NVDmaNext(par, data) \
+     NV_WR32(&(par)->dmaBase[(par)->dmaCurrent++], 0, (data))
+
+#define NVDmaStart(par, tag, size) {          \
+     if((par)->dmaFree <= (size))             \
+        NVDmaWait(par, size);                 \
+     NVDmaNext(par, ((size) << 18) | (tag));  \
+     (par)->dmaFree -= ((size) + 1);          \
+}
+
+#if defined(__i386__)
+#define _NV_FENCE() outb(0, 0x3D0);
+#else
+#define _NV_FENCE() mb();
+#endif
+
+#define WRITE_PUT(par, data) {                   \
+  volatile u8 scratch;                           \
+  _NV_FENCE()                                    \
+  scratch = NV_RD08((par)->FbStart, 0);          \
+  NV_WR32(&(par)->FIFO[0x0010], 0, (data) << 2); \
+  mb();                                          \
+}
+
+#define READ_GET(par) (NV_RD32(&(par)->FIFO[0x0011], 0) >> 2)
+
+#define reverse_order(l)        \
+do {                            \
+	u8 *a = (u8 *)(l);      \
+	*a = byte_rev[*a], a++; \
+	*a = byte_rev[*a], a++; \
+	*a = byte_rev[*a], a++; \
+	*a = byte_rev[*a];      \
+} while(0)
+
+#endif				/* __NV_LOCAL_H__ */
diff -Nru a/drivers/video/nvidia/nv_of.c b/drivers/video/nvidia/nv_of.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/video/nvidia/nv_of.c	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,58 @@
+/*
+ * linux/drivers/video/nvidia/nv_of.c
+ *
+ * Copyright 2004 Antonino A. Daplas <adaplas @pol.net>
+ *
+ * Based on rivafb-i2c.c
+ *
+ * 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/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/delay.h>
+#include <linux/pci.h>
+#include <linux/fb.h>
+
+#include <asm/io.h>
+
+#include <asm/prom.h>
+#include <asm/pci-bridge.h>
+
+#include "nv_type.h"
+#include "nv_local.h"
+#include "nv_proto.h"
+
+void nvidia_create_i2c_busses(struct nvidia_par *par) {}
+
+int nvidia_probe_i2c_connector(struct nvidia_par *par, int conn, u8 **out_edid)
+{
+	struct device_node *dp;
+	unsigned char *pedid = NULL;
+	unsigned char *disptype = NULL;
+	static char *propnames[] = {
+		"DFP,EDID", "LCD,EDID", "EDID", "EDID1", "EDID,B", "EDID,A", NULL };
+	int i;
+
+	dp = pci_device_to_OF_node(par->pci_dev);
+	for (; dp != NULL; dp = dp->child) {
+		disptype = (unsigned char *)get_property(dp, "display-type", NULL);
+		if (disptype == NULL)
+			continue;
+		if (strncmp(disptype, "LCD", 3) != 0)
+			continue;
+		for (i = 0; propnames[i] != NULL; ++i) {
+			pedid = (unsigned char *)
+				get_property(dp, propnames[i], NULL);
+			if (pedid != NULL) {
+				*out_edid = pedid;
+				return 0;
+			}
+		}
+	}
+	return 1;
+}
diff -Nru a/drivers/video/nvidia/nv_proto.h b/drivers/video/nvidia/nv_proto.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/video/nvidia/nv_proto.h	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,56 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/nv/nv_proto.h,v 1.10 2003/07/31 20:24:29 mvojkovi Exp $ */
+
+#ifndef __NV_PROTO_H__
+#define __NV_PROTO_H__
+
+/* in nv_setup.c */
+void NVCommonSetup(struct fb_info *info);
+void NVWriteCrtc(struct nvidia_par *par, u8 index, u8 value);
+u8 NVReadCrtc(struct nvidia_par *par, u8 index);
+void NVWriteGr(struct nvidia_par *par, u8 index, u8 value);
+u8 NVReadGr(struct nvidia_par *par, u8 index);
+void NVWriteSeq(struct nvidia_par *par, u8 index, u8 value);
+u8 NVReadSeq(struct nvidia_par *par, u8 index);
+void NVWriteAttr(struct nvidia_par *par, u8 index, u8 value);
+u8 NVReadAttr(struct nvidia_par *par, u8 index);
+void NVWriteMiscOut(struct nvidia_par *par, u8 value);
+u8 NVReadMiscOut(struct nvidia_par *par);
+void NVWriteDacMask(struct nvidia_par *par, u8 value);
+void NVWriteDacReadAddr(struct nvidia_par *par, u8 value);
+void NVWriteDacWriteAddr(struct nvidia_par *par, u8 value);
+void NVWriteDacData(struct nvidia_par *par, u8 value);
+u8 NVReadDacData(struct nvidia_par *par);
+
+/* in nv_hw.c */
+void NVCalcStateExt(struct nvidia_par *par, struct _riva_hw_state *,
+		    int, int, int, int, int, int);
+void NVLoadStateExt(struct nvidia_par *par, struct _riva_hw_state *);
+void NVUnloadStateExt(struct nvidia_par *par, struct _riva_hw_state *);
+void NVSetStartAddress(struct nvidia_par *par, u32);
+int NVShowHideCursor(struct nvidia_par *par, int);
+void NVLockUnlock(struct nvidia_par *par, int);
+
+/* in nvidia-i2c.c */
+#if defined(CONFIG_FB_NVIDIA_I2C) || defined (CONFIG_PPC_OF)
+void nvidia_create_i2c_busses(struct nvidia_par *par);
+int nvidia_probe_i2c_connector(struct nvidia_par *par, int conn,
+			       u8 ** out_edid);
+#else
+#define nvidia_create_i2c_busses(...)
+#define nvidia_probe_i2c_connector(p, c, edid) \
+do {                                           \
+	*(edid) = NULL;                        \
+} while(0)
+#endif
+
+/* in nv_accel.c */
+extern void NVResetGraphics(struct fb_info *info);
+extern void nvidiafb_copyarea(struct fb_info *info,
+			      const struct fb_copyarea *region);
+extern void nvidiafb_fillrect(struct fb_info *info,
+			      const struct fb_fillrect *rect);
+extern void nvidiafb_imageblit(struct fb_info *info,
+			       const struct fb_image *image);
+extern int nvidiafb_sync(struct fb_info *info);
+extern u8 byte_rev[256];
+#endif				/* __NV_PROTO_H__ */
diff -Nru a/drivers/video/nvidia/nv_setup.c b/drivers/video/nvidia/nv_setup.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/video/nvidia/nv_setup.c	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,626 @@
+ /***************************************************************************\
+|*                                                                           *|
+|*       Copyright 2003 NVIDIA, Corporation.  All rights reserved.           *|
+|*                                                                           *|
+|*     NOTICE TO USER:   The source code  is copyrighted under  U.S. and     *|
+|*     international laws.  Users and possessors of this source code are     *|
+|*     hereby granted a nonexclusive,  royalty-free copyright license to     *|
+|*     use this code in individual and commercial software.                  *|
+|*                                                                           *|
+|*     Any use of this source code must include,  in the user documenta-     *|
+|*     tion and  internal comments to the code,  notices to the end user     *|
+|*     as follows:                                                           *|
+|*                                                                           *|
+|*       Copyright 2003 NVIDIA, Corporation.  All rights reserved.           *|
+|*                                                                           *|
+|*     NVIDIA, CORPORATION MAKES NO REPRESENTATION ABOUT THE SUITABILITY     *|
+|*     OF  THIS SOURCE  CODE  FOR ANY PURPOSE.  IT IS  PROVIDED  "AS IS"     *|
+|*     WITHOUT EXPRESS OR IMPLIED WARRANTY OF ANY KIND.  NVIDIA, CORPOR-     *|
+|*     ATION DISCLAIMS ALL WARRANTIES  WITH REGARD  TO THIS SOURCE CODE,     *|
+|*     INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGE-     *|
+|*     MENT,  AND FITNESS  FOR A PARTICULAR PURPOSE.   IN NO EVENT SHALL     *|
+|*     NVIDIA, CORPORATION  BE LIABLE FOR ANY SPECIAL,  INDIRECT,  INCI-     *|
+|*     DENTAL, OR CONSEQUENTIAL DAMAGES,  OR ANY DAMAGES  WHATSOEVER RE-     *|
+|*     SULTING FROM LOSS OF USE,  DATA OR PROFITS,  WHETHER IN AN ACTION     *|
+|*     OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,  ARISING OUT OF     *|
+|*     OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOURCE CODE.     *|
+|*                                                                           *|
+|*     U.S. Government  End  Users.   This source code  is a "commercial     *|
+|*     item,"  as that  term is  defined at  48 C.F.R. 2.101 (OCT 1995),     *|
+|*     consisting  of "commercial  computer  software"  and  "commercial     *|
+|*     computer  software  documentation,"  as such  terms  are  used in     *|
+|*     48 C.F.R. 12.212 (SEPT 1995)  and is provided to the U.S. Govern-     *|
+|*     ment only as  a commercial end item.   Consistent with  48 C.F.R.     *|
+|*     12.212 and  48 C.F.R. 227.7202-1 through  227.7202-4 (JUNE 1995),     *|
+|*     all U.S. Government End Users  acquire the source code  with only     *|
+|*     those rights set forth herein.                                        *|
+|*                                                                           *|
+ \***************************************************************************/
+
+#include <video/vga.h>
+#include <linux/delay.h>
+#include <linux/pci.h>
+#include "nv_type.h"
+#include "nv_local.h"
+#include "nv_proto.h"
+/*
+ * Override VGA I/O routines.
+ */
+void NVWriteCrtc(struct nvidia_par *par, u8 index, u8 value)
+{
+	VGA_WR08(par->PCIO, par->IOBase + 0x04, index);
+	VGA_WR08(par->PCIO, par->IOBase + 0x05, value);
+}
+u8 NVReadCrtc(struct nvidia_par *par, u8 index)
+{
+	VGA_WR08(par->PCIO, par->IOBase + 0x04, index);
+	return (VGA_RD08(par->PCIO, par->IOBase + 0x05));
+}
+void NVWriteGr(struct nvidia_par *par, u8 index, u8 value)
+{
+	VGA_WR08(par->PVIO, VGA_GFX_I, index);
+	VGA_WR08(par->PVIO, VGA_GFX_D, value);
+}
+u8 NVReadGr(struct nvidia_par *par, u8 index)
+{
+	VGA_WR08(par->PVIO, VGA_GFX_I, index);
+	return (VGA_RD08(par->PVIO, VGA_GFX_D));
+}
+void NVWriteSeq(struct nvidia_par *par, u8 index, u8 value)
+{
+	VGA_WR08(par->PVIO, VGA_SEQ_I, index);
+	VGA_WR08(par->PVIO, VGA_SEQ_D, value);
+}
+u8 NVReadSeq(struct nvidia_par *par, u8 index)
+{
+	VGA_WR08(par->PVIO, VGA_SEQ_I, index);
+	return (VGA_RD08(par->PVIO, VGA_SEQ_D));
+}
+void NVWriteAttr(struct nvidia_par *par, u8 index, u8 value)
+{
+	volatile u8 tmp;
+
+	tmp = VGA_RD08(par->PCIO, par->IOBase + 0x0a);
+	if (par->paletteEnabled)
+		index &= ~0x20;
+	else
+		index |= 0x20;
+	VGA_WR08(par->PCIO, VGA_ATT_IW, index);
+	VGA_WR08(par->PCIO, VGA_ATT_W, value);
+}
+u8 NVReadAttr(struct nvidia_par *par, u8 index)
+{
+	volatile u8 tmp;
+
+	tmp = VGA_RD08(par->PCIO, par->IOBase + 0x0a);
+	if (par->paletteEnabled)
+		index &= ~0x20;
+	else
+		index |= 0x20;
+	VGA_WR08(par->PCIO, VGA_ATT_IW, index);
+	return (VGA_RD08(par->PCIO, VGA_ATT_R));
+}
+void NVWriteMiscOut(struct nvidia_par *par, u8 value)
+{
+	VGA_WR08(par->PVIO, VGA_MIS_W, value);
+}
+u8 NVReadMiscOut(struct nvidia_par *par)
+{
+	return (VGA_RD08(par->PVIO, VGA_MIS_R));
+}
+#if 0
+void NVEnablePalette(struct nvidia_par *par)
+{
+	volatile u8 tmp;
+
+	tmp = VGA_RD08(par->PCIO, par->IOBase + 0x0a);
+	VGA_WR08(par->PCIO, VGA_ATT_IW, 0x00);
+	par->paletteEnabled = 1;
+}
+void NVDisablePalette(struct nvidia_par *par)
+{
+	volatile u8 tmp;
+
+	tmp = VGA_RD08(par->PCIO, par->IOBase + 0x0a);
+	VGA_WR08(par->PCIO, VGA_ATT_IW, 0x20);
+	par->paletteEnabled = 0;
+}
+#endif  /*  0  */
+void NVWriteDacMask(struct nvidia_par *par, u8 value)
+{
+	VGA_WR08(par->PDIO, VGA_PEL_MSK, value);
+}
+#if 0
+u8 NVReadDacMask(struct nvidia_par *par)
+{
+	return (VGA_RD08(par->PDIO, VGA_PEL_MSK));
+}
+#endif  /*  0  */
+void NVWriteDacReadAddr(struct nvidia_par *par, u8 value)
+{
+	VGA_WR08(par->PDIO, VGA_PEL_IR, value);
+}
+void NVWriteDacWriteAddr(struct nvidia_par *par, u8 value)
+{
+	VGA_WR08(par->PDIO, VGA_PEL_IW, value);
+}
+void NVWriteDacData(struct nvidia_par *par, u8 value)
+{
+	VGA_WR08(par->PDIO, VGA_PEL_D, value);
+}
+u8 NVReadDacData(struct nvidia_par *par)
+{
+	return (VGA_RD08(par->PDIO, VGA_PEL_D));
+}
+
+static int NVIsConnected(struct nvidia_par *par, int output)
+{
+	volatile u32 __iomem *PRAMDAC = par->PRAMDAC0;
+	u32 reg52C, reg608;
+	int present;
+
+	if (output)
+		PRAMDAC += 0x800;
+
+	reg52C = NV_RD32(PRAMDAC, 0x052C);
+	reg608 = NV_RD32(PRAMDAC, 0x0608);
+
+	NV_WR32(PRAMDAC, 0x0608, reg608 & ~0x00010000);
+
+	NV_WR32(PRAMDAC, 0x052C, reg52C & 0x0000FEEE);
+	msleep(1);
+	NV_WR32(PRAMDAC, 0x052C, NV_RD32(PRAMDAC, 0x052C) | 1);
+
+	NV_WR32(par->PRAMDAC0, 0x0610, 0x94050140);
+	NV_WR32(par->PRAMDAC0, 0x0608, NV_RD32(par->PRAMDAC0, 0x0608) |
+		0x00001000);
+
+	msleep(1);
+
+	present = (NV_RD32(PRAMDAC, 0x0608) & (1 << 28)) ? 1 : 0;
+
+	if (present)
+		printk("nvidiafb: CRTC%i found\n", output);
+	else
+		printk("nvidiafb: CRTC%i not found\n", output);
+
+	NV_WR32(par->PRAMDAC0, 0x0608, NV_RD32(par->PRAMDAC0, 0x0608) &
+		0x0000EFFF);
+
+	NV_WR32(PRAMDAC, 0x052C, reg52C);
+	NV_WR32(PRAMDAC, 0x0608, reg608);
+
+	return present;
+}
+
+static void NVSelectHeadRegisters(struct nvidia_par *par, int head)
+{
+	if (head) {
+		par->PCIO = par->PCIO0 + 0x2000;
+		par->PCRTC = par->PCRTC0 + 0x800;
+		par->PRAMDAC = par->PRAMDAC0 + 0x800;
+		par->PDIO = par->PDIO0 + 0x2000;
+	} else {
+		par->PCIO = par->PCIO0;
+		par->PCRTC = par->PCRTC0;
+		par->PRAMDAC = par->PRAMDAC0;
+		par->PDIO = par->PDIO0;
+	}
+}
+
+static void nv4GetConfig(struct nvidia_par *par)
+{
+	if (NV_RD32(par->PFB, 0x0000) & 0x00000100) {
+		par->RamAmountKBytes =
+		    ((NV_RD32(par->PFB, 0x0000) >> 12) & 0x0F) * 1024 * 2 +
+		    1024 * 2;
+	} else {
+		switch (NV_RD32(par->PFB, 0x0000) & 0x00000003) {
+		case 0:
+			par->RamAmountKBytes = 1024 * 32;
+			break;
+		case 1:
+			par->RamAmountKBytes = 1024 * 4;
+			break;
+		case 2:
+			par->RamAmountKBytes = 1024 * 8;
+			break;
+		case 3:
+		default:
+			par->RamAmountKBytes = 1024 * 16;
+			break;
+		}
+	}
+	par->CrystalFreqKHz = (NV_RD32(par->PEXTDEV, 0x0000) & 0x00000040) ?
+	    14318 : 13500;
+	par->CURSOR = &par->PRAMIN[0x1E00];
+	par->MinVClockFreqKHz = 12000;
+	par->MaxVClockFreqKHz = 350000;
+}
+
+static void nv10GetConfig(struct nvidia_par *par)
+{
+	struct pci_dev *dev;
+	u32 implementation = par->Chipset & 0x0ff0;
+
+#ifdef __BIG_ENDIAN
+	/* turn on big endian register access */
+	if (!(NV_RD32(par->PMC, 0x0004) & 0x01000001)) {
+		NV_WR32(par->PMC, 0x0004, 0x01000001);
+		mb();
+	}
+#endif
+
+	dev = pci_find_slot(0, 1);
+	if ((par->Chipset && 0xffff) == 0x01a0) {
+		int amt = 0;
+
+		pci_read_config_dword(dev, 0x7c, &amt);
+		par->RamAmountKBytes = (((amt >> 6) & 31) + 1) * 1024;
+	} else if ((par->Chipset & 0xffff) == 0x01f0) {
+		int amt = 0;
+
+		pci_read_config_dword(dev, 0x84, &amt);
+		par->RamAmountKBytes = (((amt >> 4) & 127) + 1) * 1024;
+	} else {
+		par->RamAmountKBytes =
+		    (NV_RD32(par->PFB, 0x020C) & 0xFFF00000) >> 10;
+	}
+
+	par->CrystalFreqKHz = (NV_RD32(par->PEXTDEV, 0x0000) & (1 << 6)) ?
+	    14318 : 13500;
+
+	if (par->twoHeads && (implementation != 0x0110)) {
+		if (NV_RD32(par->PEXTDEV, 0x0000) & (1 << 22))
+			par->CrystalFreqKHz = 27000;
+	}
+
+	par->CursorStart = (par->RamAmountKBytes - 96) * 1024;
+	par->CURSOR = NULL;	/* can't set this here */
+	par->MinVClockFreqKHz = 12000;
+	par->MaxVClockFreqKHz = par->twoStagePLL ? 400000 : 350000;
+}
+
+void NVCommonSetup(struct fb_info *info)
+{
+	struct nvidia_par *par = info->par;
+	struct fb_var_screeninfo var;
+	u16 implementation = par->Chipset & 0x0ff0;
+	u8 *edidA = NULL, *edidB = NULL;
+	struct fb_monspecs monitorA, monitorB;
+	struct fb_monspecs *monA = NULL, *monB = NULL;
+	int mobile = 0;
+	int tvA = 0;
+	int tvB = 0;
+	int FlatPanel = -1;	/* really means the CRTC is slaved */
+	int Television = 0;
+
+	par->PRAMIN = par->REGS + (0x00710000 / 4);
+	par->PCRTC0 = par->REGS + (0x00600000 / 4);
+	par->PRAMDAC0 = par->REGS + (0x00680000 / 4);
+	par->PFB = par->REGS + (0x00100000 / 4);
+	par->PFIFO = par->REGS + (0x00002000 / 4);
+	par->PGRAPH = par->REGS + (0x00400000 / 4);
+	par->PEXTDEV = par->REGS + (0x00101000 / 4);
+	par->PTIMER = par->REGS + (0x00009000 / 4);
+	par->PMC = par->REGS + (0x00000000 / 4);
+	par->FIFO = par->REGS + (0x00800000 / 4);
+
+	/* 8 bit registers */
+	par->PCIO0 = (u8 __iomem *) par->REGS + 0x00601000;
+	par->PDIO0 = (u8 __iomem *) par->REGS + 0x00681000;
+	par->PVIO = (u8 __iomem *) par->REGS + 0x000C0000;
+
+	par->twoHeads = (par->Architecture >= NV_ARCH_10) &&
+	    (implementation != 0x0100) &&
+	    (implementation != 0x0150) &&
+	    (implementation != 0x01A0) && (implementation != 0x0200);
+
+	par->fpScaler = (par->FpScale && par->twoHeads &&
+			 (implementation != 0x0110));
+
+	par->twoStagePLL = (implementation == 0x0310) ||
+	    (implementation == 0x0340) || (par->Architecture >= NV_ARCH_40);
+
+	par->WaitVSyncPossible = (par->Architecture >= NV_ARCH_10) &&
+	    (implementation != 0x0100);
+
+	par->BlendingPossible = ((par->Chipset & 0xffff) != 0x0020);
+
+	/* look for known laptop chips */
+	switch (par->Chipset & 0xffff) {
+	case 0x0112:
+	case 0x0174:
+	case 0x0175:
+	case 0x0176:
+	case 0x0177:
+	case 0x0179:
+	case 0x017C:
+	case 0x017D:
+	case 0x0186:
+	case 0x0187:
+	case 0x018D:
+	case 0x0286:
+	case 0x028C:
+	case 0x0316:
+	case 0x0317:
+	case 0x031A:
+	case 0x031B:
+	case 0x031C:
+	case 0x031D:
+	case 0x031E:
+	case 0x031F:
+	case 0x0324:
+	case 0x0325:
+	case 0x0328:
+	case 0x0329:
+	case 0x032C:
+	case 0x032D:
+	case 0x0347:
+	case 0x0348:
+	case 0x0349:
+	case 0x034B:
+	case 0x034C:
+	case 0x0160:
+	case 0x0166:
+	case 0x00C8:
+	case 0x00CC:
+	case 0x0144:
+	case 0x0146:
+	case 0x0147:
+	case 0x0148:
+		mobile = 1;
+		break;
+	default:
+		break;
+	}
+
+	if (par->Architecture == NV_ARCH_04)
+		nv4GetConfig(par);
+	else
+		nv10GetConfig(par);
+
+	NVSelectHeadRegisters(par, 0);
+
+	NVLockUnlock(par, 0);
+
+	par->IOBase = (NVReadMiscOut(par) & 0x01) ? 0x3d0 : 0x3b0;
+
+	par->Television = 0;
+
+	nvidia_create_i2c_busses(par);
+	if (!par->twoHeads) {
+		par->CRTCnumber = 0;
+		nvidia_probe_i2c_connector(par, 1, &edidA);
+		if (edidA && !fb_parse_edid(edidA, &var)) {
+			printk("nvidiafb: EDID found from BUS1\n");
+			monA = &monitorA;
+			fb_edid_to_monspecs(edidA, monA);
+			FlatPanel = (monA->input & FB_DISP_DDI) ? 1 : 0;
+
+			/* NV4 doesn't support FlatPanels */
+			if ((par->Chipset & 0x0fff) <= 0x0020)
+				FlatPanel = 0;
+		} else {
+			VGA_WR08(par->PCIO, 0x03D4, 0x28);
+			if (VGA_RD08(par->PCIO, 0x03D5) & 0x80) {
+				VGA_WR08(par->PCIO, 0x03D4, 0x33);
+				if (!(VGA_RD08(par->PCIO, 0x03D5) & 0x01))
+					Television = 1;
+				FlatPanel = 1;
+			} else {
+				FlatPanel = 0;
+			}
+			printk("nvidiafb: HW is currently programmed for %s\n",
+			       FlatPanel ? (Television ? "TV" : "DFP") :
+			       "CRT");
+		}
+
+		if (par->FlatPanel == -1) {
+			par->FlatPanel = FlatPanel;
+			par->Television = Television;
+		} else {
+			printk("nvidiafb: Forcing display type to %s as "
+			       "specified\n", par->FlatPanel ? "DFP" : "CRT");
+		}
+	} else {
+		u8 outputAfromCRTC, outputBfromCRTC;
+		int CRTCnumber = -1;
+		u8 slaved_on_A, slaved_on_B;
+		int analog_on_A, analog_on_B;
+		u32 oldhead;
+		u8 cr44;
+
+		if (implementation != 0x0110) {
+			if (NV_RD32(par->PRAMDAC0, 0x0000052C) & 0x100)
+				outputAfromCRTC = 1;
+			else
+				outputAfromCRTC = 0;
+			if (NV_RD32(par->PRAMDAC0, 0x0000252C) & 0x100)
+				outputBfromCRTC = 1;
+			else
+				outputBfromCRTC = 0;
+			analog_on_A = NVIsConnected(par, 0);
+			analog_on_B = NVIsConnected(par, 1);
+		} else {
+			outputAfromCRTC = 0;
+			outputBfromCRTC = 1;
+			analog_on_A = 0;
+			analog_on_B = 0;
+		}
+
+		VGA_WR08(par->PCIO, 0x03D4, 0x44);
+		cr44 = VGA_RD08(par->PCIO, 0x03D5);
+
+		VGA_WR08(par->PCIO, 0x03D5, 3);
+		NVSelectHeadRegisters(par, 1);
+		NVLockUnlock(par, 0);
+
+		VGA_WR08(par->PCIO, 0x03D4, 0x28);
+		slaved_on_B = VGA_RD08(par->PCIO, 0x03D5) & 0x80;
+		if (slaved_on_B) {
+			VGA_WR08(par->PCIO, 0x03D4, 0x33);
+			tvB = !(VGA_RD08(par->PCIO, 0x03D5) & 0x01);
+		}
+
+		VGA_WR08(par->PCIO, 0x03D4, 0x44);
+		VGA_WR08(par->PCIO, 0x03D5, 0);
+		NVSelectHeadRegisters(par, 0);
+		NVLockUnlock(par, 0);
+
+		VGA_WR08(par->PCIO, 0x03D4, 0x28);
+		slaved_on_A = VGA_RD08(par->PCIO, 0x03D5) & 0x80;
+		if (slaved_on_A) {
+			VGA_WR08(par->PCIO, 0x03D4, 0x33);
+			tvA = !(VGA_RD08(par->PCIO, 0x03D5) & 0x01);
+		}
+
+		oldhead = NV_RD32(par->PCRTC0, 0x00000860);
+		NV_WR32(par->PCRTC0, 0x00000860, oldhead | 0x00000010);
+
+		nvidia_probe_i2c_connector(par, 1, &edidA);
+		if (edidA && !fb_parse_edid(edidA, &var)) {
+			printk("nvidiafb: EDID found from BUS1\n");
+			monA = &monitorA;
+			fb_edid_to_monspecs(edidA, monA);
+		}
+
+		nvidia_probe_i2c_connector(par, 2, &edidB);
+		if (edidB && !fb_parse_edid(edidB, &var)) {
+			printk("nvidiafb: EDID found from BUS2\n");
+			monB = &monitorB;
+			fb_edid_to_monspecs(edidB, monB);
+		}
+
+		if (slaved_on_A && !tvA) {
+			CRTCnumber = 0;
+			FlatPanel = 1;
+			printk("nvidiafb: CRTC 0 is currently programmed for "
+			       "DFP\n");
+		} else if (slaved_on_B && !tvB) {
+			CRTCnumber = 1;
+			FlatPanel = 1;
+			printk("nvidiafb: CRTC 1 is currently programmed "
+			       "for DFP\n");
+		} else if (analog_on_A) {
+			CRTCnumber = outputAfromCRTC;
+			FlatPanel = 0;
+			printk("nvidiafb: CRTC %i appears to have a "
+			       "CRT attached\n", CRTCnumber);
+		} else if (analog_on_B) {
+			CRTCnumber = outputBfromCRTC;
+			FlatPanel = 0;
+			printk("nvidiafb: CRTC %i"
+			       "appears to have a "
+			       "CRT attached\n", CRTCnumber);
+		} else if (slaved_on_A) {
+			CRTCnumber = 0;
+			FlatPanel = 1;
+			Television = 1;
+			printk("nvidiafb: CRTC 0 is currently programmed "
+			       "for TV\n");
+		} else if (slaved_on_B) {
+			CRTCnumber = 1;
+			FlatPanel = 1;
+			Television = 1;
+			printk("nvidiafb: CRTC 1 is currently programmed for "
+			       "TV\n");
+		} else if (monA) {
+			FlatPanel = (monA->input & FB_DISP_DDI) ? 1 : 0;
+		} else if (monB) {
+			FlatPanel = (monB->input & FB_DISP_DDI) ? 1 : 0;
+		}
+
+		if (par->FlatPanel == -1) {
+			if (FlatPanel != -1) {
+				par->FlatPanel = FlatPanel;
+				par->Television = Television;
+			} else {
+				printk("nvidiafb: Unable to detect display "
+				       "type...\n");
+				if (mobile) {
+					printk("...On a laptop, assuming "
+					       "DFP\n");
+					par->FlatPanel = 1;
+				} else {
+					printk("...Using default of CRT\n");
+					par->FlatPanel = 0;
+				}
+			}
+		} else {
+			printk("nvidiafb: Forcing display type to %s as "
+			       "specified\n", par->FlatPanel ? "DFP" : "CRT");
+		}
+
+		if (par->CRTCnumber == -1) {
+			if (CRTCnumber != -1)
+				par->CRTCnumber = CRTCnumber;
+			else {
+				printk("nvidiafb: Unable to detect which "
+				       "CRTCNumber...\n");
+				if (par->FlatPanel)
+					par->CRTCnumber = 1;
+				else
+					par->CRTCnumber = 0;
+				printk("...Defaulting to CRTCNumber %i\n",
+				       par->CRTCnumber);
+			}
+		} else {
+			printk("nvidiafb: Forcing CRTCNumber %i as "
+			       "specified\n", par->CRTCnumber);
+		}
+
+		if (monA) {
+			if (((monA->input & FB_DISP_DDI) &&
+			     par->FlatPanel) ||
+			    ((!(monA->input & FB_DISP_DDI)) &&
+			     !par->FlatPanel)) {
+				if (monB) {
+					fb_destroy_modedb(monB->modedb);
+					monB = NULL;
+				}
+			} else {
+				fb_destroy_modedb(monA->modedb);
+				monA = NULL;
+			}
+		}
+
+		if (monB) {
+			if (((monB->input & FB_DISP_DDI) &&
+			     !par->FlatPanel) ||
+			    ((!(monB->input & FB_DISP_DDI)) &&
+			     par->FlatPanel)) {
+				fb_destroy_modedb(monB->modedb);
+				monB = NULL;
+			} else
+				monA = monB;
+		}
+
+		if (implementation == 0x0110)
+			cr44 = par->CRTCnumber * 0x3;
+
+		NV_WR32(par->PCRTC0, 0x00000860, oldhead);
+
+		VGA_WR08(par->PCIO, 0x03D4, 0x44);
+		VGA_WR08(par->PCIO, 0x03D5, cr44);
+		NVSelectHeadRegisters(par, par->CRTCnumber);
+	}
+
+	printk("nvidiafb: Using %s on CRTC %i\n",
+	       par->FlatPanel ? (par->Television ? "TV" : "DFP") : "CRT",
+	       par->CRTCnumber);
+
+	if (par->FlatPanel && !par->Television) {
+		par->fpWidth = NV_RD32(par->PRAMDAC, 0x0820) + 1;
+		par->fpHeight = NV_RD32(par->PRAMDAC, 0x0800) + 1;
+		par->fpSyncs = NV_RD32(par->PRAMDAC, 0x0848) & 0x30000033;
+
+		printk("Panel size is %i x %i\n", par->fpWidth, par->fpHeight);
+	}
+
+	if (monA)
+		info->monspecs = *monA;
+
+	kfree(edidA);
+	kfree(edidB);
+}
diff -Nru a/drivers/video/nvidia/nv_type.h b/drivers/video/nvidia/nv_type.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/video/nvidia/nv_type.h	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,174 @@
+#ifndef __NV_TYPE_H__
+#define __NV_TYPE_H__
+
+#include <linux/fb.h>
+#include <linux/types.h>
+#include <linux/i2c.h>
+#include <linux/i2c-id.h>
+#include <linux/i2c-algo-bit.h>
+
+#define NV_ARCH_04  0x04
+#define NV_ARCH_10  0x10
+#define NV_ARCH_20  0x20
+#define NV_ARCH_30  0x30
+#define NV_ARCH_40  0x40
+
+#define BITMASK(t,b) (((unsigned)(1U << (((t)-(b)+1)))-1)  << (b))
+#define MASKEXPAND(mask) BITMASK(1?mask,0?mask)
+#define SetBF(mask,value) ((value) << (0?mask))
+#define GetBF(var,mask) (((unsigned)((var) & MASKEXPAND(mask))) >> (0?mask) )
+#define SetBitField(value,from,to) SetBF(to, GetBF(value,from))
+#define SetBit(n) (1<<(n))
+#define Set8Bits(value) ((value)&0xff)
+
+#define V_DBLSCAN  1
+
+typedef struct {
+	int bitsPerPixel;
+	int depth;
+	int displayWidth;
+	int weight;
+} NVFBLayout;
+
+#define NUM_SEQ_REGS		0x05
+#define NUM_CRT_REGS		0x41
+#define NUM_GRC_REGS		0x09
+#define NUM_ATC_REGS		0x15
+
+struct nvidia_par;
+
+struct nvidia_i2c_chan {
+	struct nvidia_par *par;
+	unsigned long ddc_base;
+	struct i2c_adapter adapter;
+	struct i2c_algo_bit_data algo;
+};
+
+typedef struct _riva_hw_state {
+	u8 attr[NUM_ATC_REGS];
+	u8 crtc[NUM_CRT_REGS];
+	u8 gra[NUM_GRC_REGS];
+	u8 seq[NUM_SEQ_REGS];
+	u8 misc_output;
+	u32 bpp;
+	u32 width;
+	u32 height;
+	u32 interlace;
+	u32 repaint0;
+	u32 repaint1;
+	u32 screen;
+	u32 scale;
+	u32 dither;
+	u32 extra;
+	u32 fifo;
+	u32 pixel;
+	u32 horiz;
+	u32 arbitration0;
+	u32 arbitration1;
+	u32 pll;
+	u32 pllB;
+	u32 vpll;
+	u32 vpll2;
+	u32 vpllB;
+	u32 vpll2B;
+	u32 pllsel;
+	u32 general;
+	u32 crtcOwner;
+	u32 head;
+	u32 head2;
+	u32 config;
+	u32 cursorConfig;
+	u32 cursor0;
+	u32 cursor1;
+	u32 cursor2;
+	u32 timingH;
+	u32 timingV;
+	u32 displayV;
+	u32 crtcSync;
+} RIVA_HW_STATE;
+
+struct riva_regs {
+	RIVA_HW_STATE ext;
+};
+
+struct nvidia_par {
+	RIVA_HW_STATE SavedReg;
+	RIVA_HW_STATE ModeReg;
+	RIVA_HW_STATE *CurrentState;
+	u32 pseudo_palette[16];
+	struct pci_dev *pci_dev;
+	u32 Architecture;
+	u32 CursorStart;
+	int Chipset;
+	int bus;
+	unsigned long FbAddress;
+	u8 __iomem *FbStart;
+	u32 FbMapSize;
+	u32 FbUsableSize;
+	u32 ScratchBufferSize;
+	u32 ScratchBufferStart;
+	int FpScale;
+	u32 MinVClockFreqKHz;
+	u32 MaxVClockFreqKHz;
+	u32 CrystalFreqKHz;
+	u32 RamAmountKBytes;
+	u32 IOBase;
+	NVFBLayout CurrentLayout;
+	int cursor_reset;
+	int lockup;
+	int videoKey;
+	int FlatPanel;
+	int FPDither;
+	int Television;
+	int CRTCnumber;
+	int alphaCursor;
+	int twoHeads;
+	int twoStagePLL;
+	int fpScaler;
+	int fpWidth;
+	int fpHeight;
+	int PanelTweak;
+	int paneltweak;
+	u32 crtcSync_read;
+	u32 fpSyncs;
+	u32 dmaPut;
+	u32 dmaCurrent;
+	u32 dmaFree;
+	u32 dmaMax;
+	u32 __iomem *dmaBase;
+	u32 currentRop;
+	int WaitVSyncPossible;
+	int BlendingPossible;
+	u32 paletteEnabled;
+	u32 forceCRTC;
+	u8 DDCBase;
+#ifdef CONFIG_MTRR
+	struct {
+		int vram;
+		int vram_valid;
+	} mtrr;
+#endif
+	struct nvidia_i2c_chan chan[3];
+
+	volatile u32 __iomem *REGS;
+	volatile u32 __iomem *PCRTC0;
+	volatile u32 __iomem *PCRTC;
+	volatile u32 __iomem *PRAMDAC0;
+	volatile u32 __iomem *PFB;
+	volatile u32 __iomem *PFIFO;
+	volatile u32 __iomem *PGRAPH;
+	volatile u32 __iomem *PEXTDEV;
+	volatile u32 __iomem *PTIMER;
+	volatile u32 __iomem *PMC;
+	volatile u32 __iomem *PRAMIN;
+	volatile u32 __iomem *FIFO;
+	volatile u32 __iomem *CURSOR;
+	volatile u8 __iomem *PCIO0;
+	volatile u8 __iomem *PCIO;
+	volatile u8 __iomem *PVIO;
+	volatile u8 __iomem *PDIO0;
+	volatile u8 __iomem *PDIO;
+	volatile u32 __iomem *PRAMDAC;
+};
+
+#endif				/* __NV_TYPE_H__ */
diff -Nru a/drivers/video/nvidia/nvidia.c b/drivers/video/nvidia/nvidia.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/video/nvidia/nvidia.c	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,1726 @@
+/*
+ * linux/drivers/video/nvidia/nvidia.c - nVidia fb driver
+ *
+ * Copyright 2004 Antonino Daplas <adaplas@pol.net>
+ *
+ * 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/config.h>
+#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/init.h>
+#include <linux/pci.h>
+#ifdef CONFIG_MTRR
+#include <asm/mtrr.h>
+#endif
+#ifdef CONFIG_PPC_OF
+#include <asm/prom.h>
+#include <asm/pci-bridge.h>
+#endif
+#ifdef CONFIG_PMAC_BACKLIGHT
+#include <asm/backlight.h>
+#endif
+
+#include "nv_local.h"
+#include "nv_type.h"
+#include "nv_proto.h"
+#include "nv_dma.h"
+
+#ifndef CONFIG_PCI		/* sanity check */
+#error This driver requires PCI support.
+#endif
+
+#undef CONFIG_FB_NVIDIA_DEBUG
+#ifdef CONFIG_FB_NVIDIA_DEBUG
+#define NVTRACE          printk
+#else
+#define NVTRACE          if (0) printk
+#endif
+
+#define NVTRACE_ENTER(...)  NVTRACE("%s START\n", __FUNCTION__)
+#define NVTRACE_LEAVE(...)  NVTRACE("%s END\n", __FUNCTION__)
+
+#ifdef CONFIG_FB_NVIDIA_DEBUG
+#define assert(expr) \
+	if (!(expr)) { \
+	printk( "Assertion failed! %s,%s,%s,line=%d\n",\
+	#expr,__FILE__,__FUNCTION__,__LINE__); \
+	BUG(); \
+	}
+#else
+#define assert(expr)
+#endif
+
+#define PFX "nvidiafb: "
+
+/* HW cursor parameters */
+#define MAX_CURS		32
+
+static struct pci_device_id nvidiafb_pci_tbl[] = {
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_TNT,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_TNT2,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_UTNT2,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_TNT_UNKNOWN,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_VTNT2,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_UVTNT2,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_ITNT2,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_SDR,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_DDR,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE2_MX,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE2_MX2,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE2_GO,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO2_MXR,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE2_GTS,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE2_GTS2,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE2_ULTRA,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO2_PRO,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_460,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_440,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_420,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_440_SE,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_440_GO,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_420_GO,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_460_GO,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_420_GO_M32,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO4_500XGL,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_440_GO_M64,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO4_200,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO4_550XGL,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO4_500_GOGL,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_410_GO_M16,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_440_8X,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_440SE_8X,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_420_8X,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_448_GO,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_488_GO,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO4_580_XGL,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_MAC,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO4_280_NVS,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO4_380_XGL,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_IGEFORCE2,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE3,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE3_1,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE3_2,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO_DDC,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4600,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4400,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4200,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO4_900XGL,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO4_750XGL,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO4_700XGL,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4800,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4800_8X,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4800SE,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_4200_GO,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO4_980_XGL,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO4_780_XGL,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO4_700_GOGL,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5800_ULTRA,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5800,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO_FX_2000,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO_FX_1000,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5600_ULTRA,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5600,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5600SE,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5600,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5650,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO_FX_GO700,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5200,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5200_ULTRA,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5200_1,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5200SE,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5200,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5250,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5250_32,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO_5200,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO_NVS_280_PCI,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO_FX_500,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5300,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5100,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5900_ULTRA,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5900,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5900XT,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5950_ULTRA,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO_FX_3000,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5700_ULTRA,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5700,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5700LE,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5700VE,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5700_1,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5700_2,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO_FX_GO1000,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO_FX_1100,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5500,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5100,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO_FX_700,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5900ZT,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_6800_ULTRA,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_6800,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_6800_LE,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_6800_GT,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO_FX_4000,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_6600_GT,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_6600,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_6610_XL,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO_FX_540,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_6200,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, 0x0252,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, 0x0313,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, 0x0316,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, 0x0317,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, 0x031D,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, 0x031E,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, 0x031F,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, 0x0329,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, 0x032F,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, 0x0345,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, 0x0349,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, 0x034B,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, 0x034F,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, 0x00c0,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_GEFORCE_6800A,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_GEFORCE_6800A_LE,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_GEFORCE_GO_6800,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_GEFORCE_GO_6800_ULTRA,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_QUADRO_FX_GO1400,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, 0x00cd,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_QUADRO_FX_1400,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, 0x0142,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, 0x0143,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, 0x0144,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, 0x0145,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, 0x0146,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, 0x0147,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, 0x0148,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, 0x0149,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, 0x014b,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, 0x14c,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, 0x014d,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, 0x0160,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_6200_TURBOCACHE,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, 0x0162,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, 0x0163,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_GO_6200,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, 0x0165,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_GO_6250,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_GO_6200_1,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_GO_6250_1,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, 0x0169,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, 0x016b,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, 0x016c,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, 0x016d,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, 0x016e,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, 0x0210,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_6800B,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_6800B_LE,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_6800B_GT,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, 0x021d,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, 0x021e,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, 0x0220,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, 0x0221,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, 0x0222,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{PCI_VENDOR_ID_NVIDIA, 0x0228,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+	{0,}			/* terminate list */
+};
+
+MODULE_DEVICE_TABLE(pci, nvidiafb_pci_tbl);
+
+/* command line data, set in nvidiafb_setup() */
+static int flatpanel __initdata = -1;	/* Autodetect later */
+static int forceCRTC __initdata = -1;
+static int hwcur __initdata = 0;
+static int noaccel __initdata = 0;
+static int noscale __initdata = 0;
+static int paneltweak __initdata = 0;
+#ifdef CONFIG_MTRR
+static int nomtrr __initdata = 0;
+#endif
+
+static char *mode_option __initdata = NULL;
+
+static struct fb_fix_screeninfo __initdata nvidiafb_fix = {
+	.type = FB_TYPE_PACKED_PIXELS,
+	.xpanstep = 8,
+	.ypanstep = 1,
+};
+
+static struct fb_var_screeninfo __initdata nvidiafb_default_var = {
+	.xres = 640,
+	.yres = 480,
+	.xres_virtual = 640,
+	.yres_virtual = 480,
+	.bits_per_pixel = 8,
+	.red = {0, 8, 0},
+	.green = {0, 8, 0},
+	.blue = {0, 8, 0},
+	.transp = {0, 0, 0},
+	.activate = FB_ACTIVATE_NOW,
+	.height = -1,
+	.width = -1,
+	.pixclock = 39721,
+	.left_margin = 40,
+	.right_margin = 24,
+	.upper_margin = 32,
+	.lower_margin = 11,
+	.hsync_len = 96,
+	.vsync_len = 2,
+	.vmode = FB_VMODE_NONINTERLACED
+};
+
+/*
+ * Backlight control
+ */
+#ifdef CONFIG_PMAC_BACKLIGHT
+
+static int nvidia_backlight_levels[] = {
+	0x158,
+	0x192,
+	0x1c6,
+	0x200,
+	0x234,
+	0x268,
+	0x2a2,
+	0x2d6,
+	0x310,
+	0x344,
+	0x378,
+	0x3b2,
+	0x3e6,
+	0x41a,
+	0x454,
+	0x534,
+};
+
+/* ------------------------------------------------------------------------- *
+ *
+ * Backlight operations
+ *
+ * ------------------------------------------------------------------------- */
+
+static int nvidia_set_backlight_enable(int on, int level, void *data)
+{
+	struct nvidia_par *par = (struct nvidia_par *)data;
+	u32 tmp_pcrt, tmp_pmc, fpcontrol;
+
+	tmp_pmc = NV_RD32(par->PMC, 0x10F0) & 0x0000FFFF;
+	tmp_pcrt = NV_RD32(par->PCRTC0, 0x081C) & 0xFFFFFFFC;
+	fpcontrol = NV_RD32(par->PRAMDAC, 0x0848) & 0xCFFFFFCC;
+
+	if (on && (level > BACKLIGHT_OFF)) {
+		tmp_pcrt |= 0x1;
+		tmp_pmc |= (1 << 31);	// backlight bit
+		tmp_pmc |= nvidia_backlight_levels[level - 1] << 16;
+	}
+
+	if (on)
+		fpcontrol |= par->fpSyncs;
+	else
+		fpcontrol |= 0x20000022;
+
+	NV_WR32(par->PCRTC0, 0x081C, tmp_pcrt);
+	NV_WR32(par->PMC, 0x10F0, tmp_pmc);
+	NV_WR32(par->PRAMDAC, 0x848, fpcontrol);
+
+	return 0;
+}
+
+static int nvidia_set_backlight_level(int level, void *data)
+{
+	return nvidia_set_backlight_enable(1, level, data);
+}
+
+static struct backlight_controller nvidia_backlight_controller = {
+	nvidia_set_backlight_enable,
+	nvidia_set_backlight_level
+};
+
+#endif				/* CONFIG_PMAC_BACKLIGHT */
+
+static void nvidiafb_load_cursor_image(struct nvidia_par *par, u8 * data8,
+				       u16 bg, u16 fg, u32 w, u32 h)
+{
+	int i, j, k = 0;
+	u32 b, tmp;
+	u32 *data = (u32 *) data8;
+
+	w = (w + 1) & ~1;
+
+	for (i = 0; i < h; i++) {
+		b = *data++;
+		reverse_order(&b);
+
+		for (j = 0; j < w / 2; j++) {
+			tmp = 0;
+#if defined (__BIG_ENDIAN)
+			tmp = (b & (1 << 31)) ? fg << 16 : bg << 16;
+			b <<= 1;
+			tmp |= (b & (1 << 31)) ? fg : bg;
+			b <<= 1;
+#else
+			tmp = (b & 1) ? fg : bg;
+			b >>= 1;
+			tmp |= (b & 1) ? fg << 16 : bg << 16;
+			b >>= 1;
+#endif
+			NV_WR32(&par->CURSOR[k++], 0, tmp);
+		}
+		k += (MAX_CURS - w) / 2;
+	}
+}
+
+static void nvidia_write_clut(struct nvidia_par *par,
+			      u8 regnum, u8 red, u8 green, u8 blue)
+{
+	NVWriteDacMask(par, 0xff);
+	NVWriteDacWriteAddr(par, regnum);
+	NVWriteDacData(par, red);
+	NVWriteDacData(par, green);
+	NVWriteDacData(par, blue);
+}
+
+static void nvidia_read_clut(struct nvidia_par *par,
+			     u8 regnum, u8 * red, u8 * green, u8 * blue)
+{
+	NVWriteDacMask(par, 0xff);
+	NVWriteDacReadAddr(par, regnum);
+	*red = NVReadDacData(par);
+	*green = NVReadDacData(par);
+	*blue = NVReadDacData(par);
+}
+
+static int nvidia_panel_tweak(struct nvidia_par *par,
+			      struct _riva_hw_state *state)
+{
+	int tweak = 0;
+
+   if (par->paneltweak) {
+	   tweak = par->paneltweak;
+   } else {
+	   /* begin flat panel hacks */
+	   /* This is unfortunate, but some chips need this register
+	      tweaked or else you get artifacts where adjacent pixels are
+	      swapped.  There are no hard rules for what to set here so all
+	      we can do is experiment and apply hacks. */
+
+	   if(((par->Chipset & 0xffff) == 0x0328) && (state->bpp == 32)) {
+		   /* At least one NV34 laptop needs this workaround. */
+		   tweak = -1;
+	   }
+
+	   if((par->Chipset & 0xfff0) == 0x0310) {
+		   tweak = 1;
+	   }
+	   /* end flat panel hacks */
+   }
+
+   return tweak;
+}
+
+static void nvidia_save_vga(struct nvidia_par *par,
+			    struct _riva_hw_state *state)
+{
+	int i;
+
+	NVTRACE_ENTER();
+	NVLockUnlock(par, 0);
+
+	NVUnloadStateExt(par, state);
+
+	state->misc_output = NVReadMiscOut(par);
+
+	for (i = 0; i < NUM_CRT_REGS; i++)
+		state->crtc[i] = NVReadCrtc(par, i);
+
+	for (i = 0; i < NUM_ATC_REGS; i++)
+		state->attr[i] = NVReadAttr(par, i);
+
+	for (i = 0; i < NUM_GRC_REGS; i++)
+		state->gra[i] = NVReadGr(par, i);
+
+	for (i = 0; i < NUM_SEQ_REGS; i++)
+		state->seq[i] = NVReadSeq(par, i);
+	NVTRACE_LEAVE();
+}
+
+static void nvidia_write_regs(struct nvidia_par *par)
+{
+	struct _riva_hw_state *state = &par->ModeReg;
+	int i;
+
+	NVTRACE_ENTER();
+	NVWriteCrtc(par, 0x11, 0x00);
+
+	NVLockUnlock(par, 0);
+
+	NVLoadStateExt(par, state);
+
+	NVWriteMiscOut(par, state->misc_output);
+
+	for (i = 0; i < NUM_CRT_REGS; i++) {
+		switch (i) {
+		case 0x19:
+		case 0x20 ... 0x40:
+			break;
+		default:
+			NVWriteCrtc(par, i, state->crtc[i]);
+		}
+	}
+
+	for (i = 0; i < NUM_ATC_REGS; i++)
+		NVWriteAttr(par, i, state->attr[i]);
+
+	for (i = 0; i < NUM_GRC_REGS; i++)
+		NVWriteGr(par, i, state->gra[i]);
+
+	for (i = 0; i < NUM_SEQ_REGS; i++)
+		NVWriteSeq(par, i, state->seq[i]);
+	NVTRACE_LEAVE();
+}
+
+static int nvidia_calc_regs(struct fb_info *info)
+{
+	struct nvidia_par *par = info->par;
+	struct _riva_hw_state *state = &par->ModeReg;
+	int i, depth = fb_get_color_depth(&info->var);
+	int h_display = info->var.xres / 8 - 1;
+	int h_start = (info->var.xres + info->var.right_margin) / 8 - 1;
+	int h_end = (info->var.xres + info->var.right_margin +
+		     info->var.hsync_len) / 8 - 1;
+	int h_total = (info->var.xres + info->var.right_margin +
+		       info->var.hsync_len + info->var.left_margin) / 8 - 5;
+	int h_blank_s = h_display;
+	int h_blank_e = h_total + 4;
+	int v_display = info->var.yres - 1;
+	int v_start = info->var.yres + info->var.lower_margin - 1;
+	int v_end = (info->var.yres + info->var.lower_margin +
+		     info->var.vsync_len) - 1;
+	int v_total = (info->var.yres + info->var.lower_margin +
+		       info->var.vsync_len + info->var.upper_margin) - 2;
+	int v_blank_s = v_display;
+	int v_blank_e = v_total + 1;
+
+	/*
+	 * Set all CRTC values.
+	 */
+
+	if (info->var.vmode & FB_VMODE_INTERLACED)
+		v_total |= 1;
+
+	if (par->FlatPanel == 1) {
+		v_start = v_total - 3;
+		v_end = v_total - 2;
+		v_blank_s = v_start;
+		h_start = h_total - 5;
+		h_end = h_total - 2;
+		h_blank_e = h_total + 4;
+	}
+
+	state->crtc[0x0] = Set8Bits(h_total);
+	state->crtc[0x1] = Set8Bits(h_display);
+	state->crtc[0x2] = Set8Bits(h_blank_s);
+	state->crtc[0x3] = SetBitField(h_blank_e, 4: 0, 4:0)
+		| SetBit(7);
+	state->crtc[0x4] = Set8Bits(h_start);
+	state->crtc[0x5] = SetBitField(h_blank_e, 5: 5, 7:7)
+		| SetBitField(h_end, 4: 0, 4:0);
+	state->crtc[0x6] = SetBitField(v_total, 7: 0, 7:0);
+	state->crtc[0x7] = SetBitField(v_total, 8: 8, 0:0)
+		| SetBitField(v_display, 8: 8, 1:1)
+		| SetBitField(v_start, 8: 8, 2:2)
+		| SetBitField(v_blank_s, 8: 8, 3:3)
+		| SetBit(4)
+		| SetBitField(v_total, 9: 9, 5:5)
+		| SetBitField(v_display, 9: 9, 6:6)
+		| SetBitField(v_start, 9: 9, 7:7);
+	state->crtc[0x9] = SetBitField(v_blank_s, 9: 9, 5:5)
+		| SetBit(6)
+		| ((info->var.vmode & FB_VMODE_DOUBLE) ? 0x80 : 0x00);
+	state->crtc[0x10] = Set8Bits(v_start);
+	state->crtc[0x11] = SetBitField(v_end, 3: 0, 3:0) | SetBit(5);
+	state->crtc[0x12] = Set8Bits(v_display);
+	state->crtc[0x13] = ((info->var.xres_virtual / 8) *
+			     (info->var.bits_per_pixel / 8));
+	state->crtc[0x15] = Set8Bits(v_blank_s);
+	state->crtc[0x16] = Set8Bits(v_blank_e);
+
+	state->attr[0x10] = 0x01;
+
+	if (par->Television)
+		state->attr[0x11] = 0x00;
+
+	state->screen = SetBitField(h_blank_e, 6: 6, 4:4)
+		| SetBitField(v_blank_s, 10: 10, 3:3)
+		| SetBitField(v_start, 10: 10, 2:2)
+		| SetBitField(v_display, 10: 10, 1:1)
+		| SetBitField(v_total, 10: 10, 0:0);
+
+	state->horiz = SetBitField(h_total, 8: 8, 0:0)
+		| SetBitField(h_display, 8: 8, 1:1)
+		| SetBitField(h_blank_s, 8: 8, 2:2)
+		| SetBitField(h_start, 8: 8, 3:3);
+
+	state->extra = SetBitField(v_total, 11: 11, 0:0)
+		| SetBitField(v_display, 11: 11, 2:2)
+		| SetBitField(v_start, 11: 11, 4:4)
+		| SetBitField(v_blank_s, 11: 11, 6:6);
+
+	if (info->var.vmode & FB_VMODE_INTERLACED) {
+		h_total = (h_total >> 1) & ~1;
+		state->interlace = Set8Bits(h_total);
+		state->horiz |= SetBitField(h_total, 8: 8, 4:4);
+	} else {
+		state->interlace = 0xff;	/* interlace off */
+	}
+
+	/*
+	 * Calculate the extended registers.
+	 */
+
+	if (depth < 24)
+		i = depth;
+	else
+		i = 32;
+
+	if (par->Architecture >= NV_ARCH_10)
+		par->CURSOR = (volatile u32 __iomem *)(info->screen_base +
+						       par->CursorStart);
+
+	if (info->var.sync & FB_SYNC_HOR_HIGH_ACT)
+		state->misc_output &= ~0x40;
+	else
+		state->misc_output |= 0x40;
+	if (info->var.sync & FB_SYNC_VERT_HIGH_ACT)
+		state->misc_output &= ~0x80;
+	else
+		state->misc_output |= 0x80;
+
+	NVCalcStateExt(par, state, i, info->var.xres_virtual,
+		       info->var.xres, info->var.yres_virtual,
+		       1000000000 / info->var.pixclock, info->var.vmode);
+
+	state->scale = NV_RD32(par->PRAMDAC, 0x00000848) & 0xfff000ff;
+	if (par->FlatPanel == 1) {
+		state->pixel |= (1 << 7);
+
+		if (!par->fpScaler || (par->fpWidth <= info->var.xres)
+		    || (par->fpHeight <= info->var.yres)) {
+			state->scale |= (1 << 8);
+		}
+
+		if (!par->crtcSync_read) {
+			state->crtcSync = NV_RD32(par->PRAMDAC, 0x0828);
+			par->crtcSync_read = 1;
+		}
+
+		par->PanelTweak = nvidia_panel_tweak(par, state);
+	}
+
+	state->vpll = state->pll;
+	state->vpll2 = state->pll;
+	state->vpllB = state->pllB;
+	state->vpll2B = state->pllB;
+
+	VGA_WR08(par->PCIO, 0x03D4, 0x1C);
+	state->fifo = VGA_RD08(par->PCIO, 0x03D5) & ~(1<<5);
+
+	if (par->CRTCnumber) {
+		state->head = NV_RD32(par->PCRTC0, 0x00000860) & ~0x00001000;
+		state->head2 = NV_RD32(par->PCRTC0, 0x00002860) | 0x00001000;
+		state->crtcOwner = 3;
+		state->pllsel |= 0x20000800;
+		state->vpll = NV_RD32(par->PRAMDAC0, 0x00000508);
+		if (par->twoStagePLL)
+			state->vpllB = NV_RD32(par->PRAMDAC0, 0x00000578);
+	} else if (par->twoHeads) {
+		state->head = NV_RD32(par->PCRTC0, 0x00000860) | 0x00001000;
+		state->head2 = NV_RD32(par->PCRTC0, 0x00002860) & ~0x00001000;
+		state->crtcOwner = 0;
+		state->vpll2 = NV_RD32(par->PRAMDAC0, 0x0520);
+		if (par->twoStagePLL)
+			state->vpll2B = NV_RD32(par->PRAMDAC0, 0x057C);
+	}
+
+	state->cursorConfig = 0x00000100;
+
+	if (info->var.vmode & FB_VMODE_DOUBLE)
+		state->cursorConfig |= (1 << 4);
+
+	if (par->alphaCursor) {
+		if ((par->Chipset & 0x0ff0) != 0x0110)
+			state->cursorConfig |= 0x04011000;
+		else
+			state->cursorConfig |= 0x14011000;
+		state->general |= (1 << 29);
+	} else
+		state->cursorConfig |= 0x02000000;
+
+	if (par->twoHeads) {
+		if ((par->Chipset & 0x0ff0) == 0x0110) {
+			state->dither = NV_RD32(par->PRAMDAC, 0x0528) &
+			    ~0x00010000;
+			if (par->FPDither)
+				state->dither |= 0x00010000;
+		} else {
+			state->dither = NV_RD32(par->PRAMDAC, 0x083C) & ~1;
+			if (par->FPDither)
+				state->dither |= 1;
+		}
+	}
+
+	state->timingH = 0;
+	state->timingV = 0;
+	state->displayV = info->var.xres;
+
+	return 0;
+}
+
+static void nvidia_init_vga(struct fb_info *info)
+{
+	struct nvidia_par *par = info->par;
+	struct _riva_hw_state *state = &par->ModeReg;
+	int i;
+
+	for (i = 0; i < 0x10; i++)
+		state->attr[i] = i;
+	state->attr[0x10] = 0x41;
+	state->attr[0x11] = 0x01;
+	state->attr[0x12] = 0x0f;
+	state->attr[0x13] = 0x00;
+	state->attr[0x14] = 0x00;
+
+	memset(state->crtc, 0x00, NUM_CRT_REGS);
+	state->crtc[0x0a] = 0x20;
+	state->crtc[0x17] = 0xe3;
+	state->crtc[0x18] = 0xff;
+	state->crtc[0x28] = 0x40;
+
+	memset(state->gra, 0x00, NUM_GRC_REGS);
+	state->gra[0x05] = 0x40;
+	state->gra[0x06] = 0x05;
+	state->gra[0x07] = 0x0f;
+	state->gra[0x08] = 0xff;
+
+	state->seq[0x00] = 0x03;
+	state->seq[0x01] = 0x01;
+	state->seq[0x02] = 0x0f;
+	state->seq[0x03] = 0x00;
+	state->seq[0x04] = 0x0e;
+
+	state->misc_output = 0xeb;
+}
+
+static int nvidiafb_cursor(struct fb_info *info, struct fb_cursor *cursor)
+{
+	struct nvidia_par *par = info->par;
+	u8 data[MAX_CURS * MAX_CURS / 8];
+	u16 fg, bg;
+	int i, set = cursor->set;
+
+	if (cursor->image.width > MAX_CURS || cursor->image.height > MAX_CURS)
+		return soft_cursor(info, cursor);
+
+	NVShowHideCursor(par, 0);
+
+	if (par->cursor_reset) {
+		set = FB_CUR_SETALL;
+		par->cursor_reset = 0;
+	}
+
+	if (set & FB_CUR_SETSIZE)
+		memset_io(par->CURSOR, 0, MAX_CURS * MAX_CURS * 2);
+
+	if (set & FB_CUR_SETPOS) {
+		u32 xx, yy, temp;
+
+		yy = cursor->image.dy - info->var.yoffset;
+		xx = cursor->image.dx - info->var.xoffset;
+		temp = xx & 0xFFFF;
+		temp |= yy << 16;
+
+		NV_WR32(par->PRAMDAC, 0x0000300, temp);
+	}
+
+	if (set & (FB_CUR_SETSHAPE | FB_CUR_SETCMAP | FB_CUR_SETIMAGE)) {
+		u32 bg_idx = cursor->image.bg_color;
+		u32 fg_idx = cursor->image.fg_color;
+		u32 s_pitch = (cursor->image.width + 7) >> 3;
+		u32 d_pitch = MAX_CURS / 8;
+		u8 *dat = (u8 *) cursor->image.data;
+		u8 *msk = (u8 *) cursor->mask;
+		u8 *src;
+
+		src = kmalloc(s_pitch * cursor->image.height, GFP_ATOMIC);
+
+		if (src) {
+			switch (cursor->rop) {
+			case ROP_XOR:
+				for (i = 0; i < s_pitch * cursor->image.height;
+				     i++)
+					src[i] = dat[i] ^ msk[i];
+				break;
+			case ROP_COPY:
+			default:
+				for (i = 0; i < s_pitch * cursor->image.height;
+				     i++)
+					src[i] = dat[i] & msk[i];
+				break;
+			}
+
+			fb_sysmove_buf_aligned(info, &info->pixmap, data,
+					       d_pitch, src, s_pitch,
+					       cursor->image.height);
+
+			bg = ((info->cmap.red[bg_idx] & 0xf8) << 7) |
+			    ((info->cmap.green[bg_idx] & 0xf8) << 2) |
+			    ((info->cmap.blue[bg_idx] & 0xf8) >> 3) | 1 << 15;
+
+			fg = ((info->cmap.red[fg_idx] & 0xf8) << 7) |
+			    ((info->cmap.green[fg_idx] & 0xf8) << 2) |
+			    ((info->cmap.blue[fg_idx] & 0xf8) >> 3) | 1 << 15;
+
+			NVLockUnlock(par, 0);
+
+			nvidiafb_load_cursor_image(par, data, bg, fg,
+						   cursor->image.width,
+						   cursor->image.height);
+			kfree(src);
+		}
+	}
+
+	if (cursor->enable)
+		NVShowHideCursor(par, 1);
+
+	return 0;
+}
+
+static int nvidiafb_set_par(struct fb_info *info)
+{
+	struct nvidia_par *par = info->par;
+
+	NVTRACE_ENTER();
+
+	NVLockUnlock(par, 1);
+	if (!par->FlatPanel || (info->var.bits_per_pixel != 24) ||
+	    !par->twoHeads)
+		par->FPDither = 0;
+
+	nvidia_init_vga(info);
+	nvidia_calc_regs(info);
+	nvidia_write_regs(par);
+
+	NVLockUnlock(par, 0);
+	if (par->twoHeads) {
+		VGA_WR08(par->PCIO, 0x03D4, 0x44);
+		VGA_WR08(par->PCIO, 0x03D5, par->ModeReg.crtcOwner);
+		NVLockUnlock(par, 0);
+	}
+
+	NVWriteCrtc(par, 0x11, 0x00);
+	info->fix.line_length = (info->var.xres_virtual *
+				 info->var.bits_per_pixel) >> 3;
+	info->fix.visual = (info->var.bits_per_pixel == 8) ?
+	    FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR;
+
+	if (info->var.accel_flags) {
+		info->fbops->fb_imageblit = nvidiafb_imageblit;
+		info->fbops->fb_fillrect = nvidiafb_fillrect;
+		info->fbops->fb_copyarea = nvidiafb_copyarea;
+		info->fbops->fb_sync = nvidiafb_sync;
+		info->pixmap.scan_align = 4;
+		info->flags &= ~FBINFO_HWACCEL_DISABLED;
+		NVResetGraphics(info);
+	} else {
+		info->fbops->fb_imageblit = cfb_imageblit;
+		info->fbops->fb_fillrect = cfb_fillrect;
+		info->fbops->fb_copyarea = cfb_copyarea;
+		info->fbops->fb_sync = NULL;
+		info->pixmap.scan_align = 1;
+		info->flags |= FBINFO_HWACCEL_DISABLED;
+	}
+
+	par->cursor_reset = 1;
+
+	NVWriteCrtc(par, 0x11, 0xff);
+
+	NVTRACE_LEAVE();
+	return 0;
+}
+
+static int nvidiafb_setcolreg(unsigned regno, unsigned red, unsigned green,
+			      unsigned blue, unsigned transp,
+			      struct fb_info *info)
+{
+	struct nvidia_par *par = info->par;
+	int i;
+
+	NVTRACE_ENTER();
+	if (regno >= (1 << info->var.green.length))
+		return -EINVAL;
+
+	if (info->var.grayscale) {
+		/* gray = 0.30*R + 0.59*G + 0.11*B */
+		red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8;
+	}
+
+	if (regno < 16 && info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
+		((u32 *) info->pseudo_palette)[regno] =
+		    (regno << info->var.red.offset) |
+		    (regno << info->var.green.offset) |
+		    (regno << info->var.blue.offset);
+	}
+
+	switch (info->var.bits_per_pixel) {
+	case 8:
+		/* "transparent" stuff is completely ignored. */
+		nvidia_write_clut(par, regno, red >> 8, green >> 8, blue >> 8);
+		break;
+	case 16:
+		if (info->var.green.length == 5) {
+			for (i = 0; i < 8; i++) {
+				nvidia_write_clut(par, regno * 8 + i, red >> 8,
+						  green >> 8, blue >> 8);
+			}
+		} else {
+			u8 r, g, b;
+
+			if (regno < 32) {
+				for (i = 0; i < 8; i++) {
+					nvidia_write_clut(par, regno * 8 + i,
+							  red >> 8, green >> 8,
+							  blue >> 8);
+				}
+			}
+
+			nvidia_read_clut(par, regno * 4, &r, &g, &b);
+
+			for (i = 0; i < 4; i++)
+				nvidia_write_clut(par, regno * 4 + i, r,
+						  green >> 8, b);
+		}
+		break;
+	case 32:
+		nvidia_write_clut(par, regno, red >> 8, green >> 8, blue >> 8);
+		break;
+	default:
+		/* do nothing */
+		break;
+	}
+
+	NVTRACE_LEAVE();
+	return 0;
+}
+
+static int nvidiafb_check_var(struct fb_var_screeninfo *var,
+			      struct fb_info *info)
+{
+	struct nvidia_par *par = info->par;
+	int memlen, vramlen, mode_valid = 0;
+	int pitch, err = 0;
+
+	NVTRACE_ENTER();
+
+	var->transp.offset = 0;
+	var->transp.length = 0;
+
+	var->xres &= ~7;
+
+	if (var->bits_per_pixel <= 8)
+		var->bits_per_pixel = 8;
+	else if (var->bits_per_pixel <= 16)
+		var->bits_per_pixel = 16;
+	else
+		var->bits_per_pixel = 32;
+
+	switch (var->bits_per_pixel) {
+	case 8:
+		var->red.offset = 0;
+		var->red.length = 8;
+		var->green.offset = 0;
+		var->green.length = 8;
+		var->blue.offset = 0;
+		var->blue.length = 8;
+		var->transp.offset = 0;
+		var->transp.length = 0;
+		break;
+	case 16:
+		var->green.length = (var->green.length < 6) ? 5 : 6;
+		var->red.length = 5;
+		var->blue.length = 5;
+		var->transp.length = 6 - var->green.length;
+		var->blue.offset = 0;
+		var->green.offset = 5;
+		var->red.offset = 5 + var->green.length;
+		var->transp.offset = (5 + var->red.offset) & 15;
+		break;
+	case 32:		/* RGBA 8888 */
+		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.length = 8;
+		var->transp.offset = 24;
+		break;
+	}
+
+	var->red.msb_right = 0;
+	var->green.msb_right = 0;
+	var->blue.msb_right = 0;
+	var->transp.msb_right = 0;
+
+	if (!info->monspecs.hfmax || !info->monspecs.vfmax ||
+	    !info->monspecs.dclkmax || !fb_validate_mode(var, info))
+		mode_valid = 1;
+
+	/* calculate modeline if supported by monitor */
+	if (!mode_valid && info->monspecs.gtf) {
+		if (!fb_get_mode(FB_MAXTIMINGS, 0, var, info))
+			mode_valid = 1;
+	}
+
+	if (!mode_valid) {
+		struct fb_videomode *mode;
+
+		mode = fb_find_best_mode(var, &info->modelist);
+		if (mode) {
+			fb_videomode_to_var(var, mode);
+			mode_valid = 1;
+		}
+	}
+
+	if (!mode_valid && info->monspecs.modedb_len)
+		return -EINVAL;
+
+	if (par->fpWidth && par->fpHeight && (par->fpWidth < var->xres ||
+					      par->fpHeight < var->yres))
+		return -EINVAL;
+
+	if (var->yres_virtual < var->yres)
+		var->yres_virtual = var->yres;
+
+	if (var->xres_virtual < var->xres)
+		var->xres_virtual = var->xres;
+
+	var->xres_virtual = (var->xres_virtual + 63) & ~63;
+
+	vramlen = info->fix.smem_len;
+	pitch = ((var->xres_virtual * var->bits_per_pixel) + 7) / 8;
+	memlen = pitch * var->yres_virtual;
+
+	if (memlen > vramlen) {
+		var->yres_virtual = vramlen / pitch;
+
+		if (var->yres_virtual < var->yres) {
+			var->yres_virtual = var->yres;
+			var->xres_virtual = vramlen / var->yres_virtual;
+			var->xres_virtual /= var->bits_per_pixel / 8;
+			pitch = (var->xres_virtual *
+				 var->bits_per_pixel + 7) / 8;
+			memlen = pitch * var->yres;
+
+			if (var->xres_virtual < var->xres) {
+				printk("nvidiafb: required video memory, "
+				       "%d bytes, for %dx%d-%d (virtual) "
+				       "is out of range\n",
+				       memlen, var->xres_virtual,
+				       var->yres_virtual, var->bits_per_pixel);
+				err = -ENOMEM;
+			}
+		}
+	}
+
+	if (var->accel_flags) {
+		if (var->yres_virtual > 0x7fff)
+			var->yres_virtual = 0x7fff;
+		if (var->xres_virtual > 0x7fff)
+			var->xres_virtual = 0x7fff;
+	}
+
+	var->xres_virtual &= ~63;
+
+	NVTRACE_LEAVE();
+
+	return err;
+}
+
+static int nvidiafb_pan_display(struct fb_var_screeninfo *var,
+				struct fb_info *info)
+{
+	struct nvidia_par *par = info->par;
+	u32 total;
+
+	total = info->var.yoffset * info->fix.line_length + info->var.xoffset;
+
+	NVSetStartAddress(par, total);
+
+	return 0;
+}
+
+static int nvidiafb_blank(int blank, struct fb_info *info)
+{
+	struct nvidia_par *par = info->par;
+	unsigned char tmp, vesa;
+
+	tmp = NVReadSeq(par, 0x01) & ~0x20;	/* screen on/off */
+	vesa = NVReadCrtc(par, 0x1a) & ~0xc0;	/* sync on/off */
+
+	NVTRACE_ENTER();
+
+	if (blank)
+		tmp |= 0x20;
+
+	switch (blank) {
+	case FB_BLANK_UNBLANK:
+	case FB_BLANK_NORMAL:
+		break;
+	case FB_BLANK_VSYNC_SUSPEND:
+		vesa |= 0x80;
+		break;
+	case FB_BLANK_HSYNC_SUSPEND:
+		vesa |= 0x40;
+		break;
+	case FB_BLANK_POWERDOWN:
+		vesa |= 0xc0;
+		break;
+	}
+
+	NVWriteSeq(par, 0x01, tmp);
+	NVWriteCrtc(par, 0x1a, vesa);
+
+#ifdef CONFIG_PMAC_BACKLIGHT
+	if (par->FlatPanel && _machine == _MACH_Pmac) {
+		set_backlight_enable(!blank);
+	}
+#endif
+
+	NVTRACE_LEAVE();
+
+	return 0;
+}
+
+static struct fb_ops nvidia_fb_ops = {
+	.owner          = THIS_MODULE,
+	.fb_check_var   = nvidiafb_check_var,
+	.fb_set_par     = nvidiafb_set_par,
+	.fb_setcolreg   = nvidiafb_setcolreg,
+	.fb_pan_display = nvidiafb_pan_display,
+	.fb_blank       = nvidiafb_blank,
+	.fb_fillrect    = nvidiafb_fillrect,
+	.fb_copyarea    = nvidiafb_copyarea,
+	.fb_imageblit   = nvidiafb_imageblit,
+	.fb_cursor      = nvidiafb_cursor,
+	.fb_sync        = nvidiafb_sync,
+};
+
+static int __devinit nvidia_set_fbinfo(struct fb_info *info)
+{
+	struct fb_monspecs *specs = &info->monspecs;
+	struct fb_videomode modedb;
+	struct nvidia_par *par = info->par;
+	int lpitch;
+
+	NVTRACE_ENTER();
+	info->flags = FBINFO_DEFAULT
+	    | FBINFO_HWACCEL_IMAGEBLIT
+	    | FBINFO_HWACCEL_FILLRECT
+	    | FBINFO_HWACCEL_COPYAREA
+	    | FBINFO_HWACCEL_YPAN | FBINFO_MISC_MODESWITCHLATE;
+
+	fb_videomode_to_modelist(info->monspecs.modedb,
+				 info->monspecs.modedb_len, &info->modelist);
+	fb_var_to_videomode(&modedb, &nvidiafb_default_var);
+
+	if (specs->modedb != NULL) {
+		/* get preferred timing */
+		if (specs->misc & FB_MISC_1ST_DETAIL) {
+			int i;
+
+			for (i = 0; i < specs->modedb_len; i++) {
+				if (specs->modedb[i].flag & FB_MODE_IS_FIRST) {
+					modedb = specs->modedb[i];
+					break;
+				}
+			}
+		} else {
+			/* otherwise, get first mode in database */
+			modedb = specs->modedb[0];
+		}
+
+		fb_videomode_to_var(&nvidiafb_default_var, &modedb);
+		nvidiafb_default_var.bits_per_pixel = 8;
+	}
+
+	if (mode_option)
+		fb_find_mode(&nvidiafb_default_var, info, mode_option,
+			     specs->modedb, specs->modedb_len, &modedb, 8);
+
+	info->var = nvidiafb_default_var;
+	info->fix.visual = (info->var.bits_per_pixel == 8) ?
+		FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR;
+	info->pseudo_palette = par->pseudo_palette;
+	fb_alloc_cmap(&info->cmap, 256, 0);
+	fb_destroy_modedb(info->monspecs.modedb);
+	info->monspecs.modedb = NULL;
+
+	/* maximize virtual vertical length */
+	lpitch = info->var.xres_virtual *
+		((info->var.bits_per_pixel + 7) >> 3);
+	info->var.yres_virtual = info->fix.smem_len / lpitch;
+
+	info->pixmap.scan_align = 4;
+	info->pixmap.buf_align = 4;
+	info->pixmap.size = 8 * 1024;
+	info->pixmap.flags = FB_PIXMAP_SYSTEM;
+
+	if (!hwcur)
+		info->fbops->fb_cursor = soft_cursor;
+	info->var.accel_flags = (!noaccel);
+	par->FpScale = (!noscale);
+	par->paneltweak = paneltweak;
+
+	switch (par->Architecture) {
+	case NV_ARCH_04:
+		info->fix.accel = FB_ACCEL_NV4;
+		break;
+	case NV_ARCH_10:
+		info->fix.accel = FB_ACCEL_NV_10;
+		break;
+	case NV_ARCH_20:
+		info->fix.accel = FB_ACCEL_NV_20;
+		break;
+	case NV_ARCH_30:
+		info->fix.accel = FB_ACCEL_NV_30;
+		break;
+	case NV_ARCH_40:
+		info->fix.accel = FB_ACCEL_NV_40;
+		break;
+	}
+
+	NVTRACE_LEAVE();
+
+	return nvidiafb_check_var(&info->var, info);
+}
+
+static u32 __devinit nvidia_get_arch(struct pci_dev *pd)
+{
+	u32 arch = 0;
+
+	switch (pd->device & 0x0ff0) {
+	case 0x0100:		/* GeForce 256 */
+	case 0x0110:		/* GeForce2 MX */
+	case 0x0150:		/* GeForce2 */
+	case 0x0170:		/* GeForce4 MX */
+	case 0x0180:		/* GeForce4 MX (8x AGP) */
+	case 0x01A0:		/* nForce */
+	case 0x01F0:		/* nForce2 */
+		arch = NV_ARCH_10;
+		break;
+	case 0x0200:		/* GeForce3 */
+	case 0x0250:		/* GeForce4 Ti */
+	case 0x0280:		/* GeForce4 Ti (8x AGP) */
+		arch = NV_ARCH_20;
+		break;
+	case 0x0300:		/* GeForceFX 5800 */
+	case 0x0310:		/* GeForceFX 5600 */
+	case 0x0320:		/* GeForceFX 5200 */
+	case 0x0330:		/* GeForceFX 5900 */
+	case 0x0340:		/* GeForceFX 5700 */
+		arch = NV_ARCH_30;
+		break;
+	case 0x0040:
+	case 0x00C0:
+	case 0x0120:
+	case 0x0130:
+	case 0x0140:
+	case 0x0160:
+	case 0x01D0:
+	case 0x0090:
+	case 0x0210:
+	case 0x0220:
+	case 0x0230:
+		arch = NV_ARCH_40;
+		break;
+	case 0x0020:		/* TNT, TNT2 */
+		arch = NV_ARCH_04;
+		break;
+	default:		/* unknown architecture */
+		break;
+	}
+
+	return arch;
+}
+
+static int __devinit nvidiafb_probe(struct pci_dev *pd,
+				    const struct pci_device_id *ent)
+{
+	struct nvidia_par *par;
+	struct fb_info *info;
+	unsigned short cmd;
+
+
+	NVTRACE_ENTER();
+	assert(pd != NULL);
+
+	info = framebuffer_alloc(sizeof(struct nvidia_par), &pd->dev);
+
+	if (!info)
+		goto err_out;
+
+	par = (struct nvidia_par *)info->par;
+	par->pci_dev = pd;
+
+	info->pixmap.addr = kmalloc(8 * 1024, GFP_KERNEL);
+
+	if (info->pixmap.addr == NULL)
+		goto err_out_kfree;
+
+	memset(info->pixmap.addr, 0, 8 * 1024);
+
+	if (pci_enable_device(pd)) {
+		printk(KERN_ERR PFX "cannot enable PCI device\n");
+		goto err_out_enable;
+	}
+
+	if (pci_request_regions(pd, "nvidiafb")) {
+		printk(KERN_ERR PFX "cannot request PCI regions\n");
+		goto err_out_request;
+	}
+
+	par->Architecture = nvidia_get_arch(pd);
+
+	par->Chipset = (pd->vendor << 16) | pd->device;
+	printk(KERN_INFO PFX "nVidia device/chipset %X\n", par->Chipset);
+
+#ifdef CONFIG_PCI_NAMES
+	printk(KERN_INFO PFX "%s\n", pd->pretty_name);
+#endif
+
+	if (par->Architecture == 0) {
+		printk(KERN_ERR PFX "unknown NV_ARCH\n");
+		goto err_out_free_base0;
+	}
+
+	sprintf(nvidiafb_fix.id, "NV%x", (pd->device & 0x0ff0) >> 4);
+
+	par->FlatPanel = flatpanel;
+
+	if (flatpanel == 1)
+		printk(KERN_INFO PFX "flatpanel support enabled\n");
+
+	par->CRTCnumber = forceCRTC;
+
+	/* enable IO and mem if not already done */
+	pci_read_config_word(pd, PCI_COMMAND, &cmd);
+	cmd |= (PCI_COMMAND_IO | PCI_COMMAND_MEMORY);
+	pci_write_config_word(pd, PCI_COMMAND, cmd);
+
+	nvidiafb_fix.mmio_start = pci_resource_start(pd, 0);
+	nvidiafb_fix.smem_start = pci_resource_start(pd, 1);
+	nvidiafb_fix.mmio_len = pci_resource_len(pd, 0);
+
+	par->REGS = ioremap(nvidiafb_fix.mmio_start, nvidiafb_fix.mmio_len);
+
+	if (!par->REGS) {
+		printk(KERN_ERR PFX "cannot ioremap MMIO base\n");
+		goto err_out_free_base0;
+	}
+
+	NVCommonSetup(info);
+
+	par->FbAddress = nvidiafb_fix.smem_start;
+	par->FbMapSize = par->RamAmountKBytes * 1024;
+	par->FbUsableSize = par->FbMapSize - (128 * 1024);
+	par->ScratchBufferSize = (par->Architecture < NV_ARCH_10) ? 8 * 1024 :
+	    16 * 1024;
+	par->ScratchBufferStart = par->FbUsableSize - par->ScratchBufferSize;
+	info->screen_base = ioremap(nvidiafb_fix.smem_start, par->FbMapSize);
+	nvidiafb_fix.smem_len = par->FbUsableSize;
+
+	if (!info->screen_base) {
+		printk(KERN_ERR PFX "cannot ioremap FB base\n");
+		goto err_out_free_base1;
+	}
+
+	par->FbStart = info->screen_base;
+
+#ifdef CONFIG_MTRR
+	if (!nomtrr) {
+		par->mtrr.vram = mtrr_add(nvidiafb_fix.smem_start,
+					  par->FbMapSize, MTRR_TYPE_WRCOMB, 1);
+		if (par->mtrr.vram < 0) {
+			printk(KERN_ERR PFX "unable to setup MTRR\n");
+		} else {
+			par->mtrr.vram_valid = 1;
+			/* let there be speed */
+			printk(KERN_INFO PFX "MTRR set to ON\n");
+		}
+	}
+#endif				/* CONFIG_MTRR */
+
+	info->fbops = &nvidia_fb_ops;
+	info->fix = nvidiafb_fix;
+
+	if (nvidia_set_fbinfo(info) < 0) {
+		printk(KERN_ERR PFX "error setting initial video mode\n");
+		goto err_out_iounmap_fb;
+	}
+
+	nvidia_save_vga(par, &par->SavedReg);
+
+	if (register_framebuffer(info) < 0) {
+		printk(KERN_ERR PFX "error registering nVidia framebuffer\n");
+		goto err_out_iounmap_fb;
+	}
+
+	pci_set_drvdata(pd, info);
+
+	printk(KERN_INFO PFX
+	       "PCI nVidia %s framebuffer (%dMB @ 0x%lX)\n",
+	       info->fix.id,
+	       par->FbMapSize / (1024 * 1024), info->fix.smem_start);
+#ifdef CONFIG_PMAC_BACKLIGHT
+	if (par->FlatPanel && _machine == _MACH_Pmac)
+		register_backlight_controller(&nvidia_backlight_controller,
+					      par, "mnca");
+#endif
+	NVTRACE_LEAVE();
+	return 0;
+
+      err_out_iounmap_fb:
+	iounmap(info->screen_base);
+      err_out_free_base1:
+	fb_destroy_modedb(info->monspecs.modedb);
+	iounmap(par->REGS);
+      err_out_free_base0:
+	pci_release_regions(pd);
+      err_out_request:
+	pci_disable_device(pd);
+      err_out_enable:
+	kfree(info->pixmap.addr);
+      err_out_kfree:
+	framebuffer_release(info);
+      err_out:
+	return -ENODEV;
+}
+
+static void __exit nvidiafb_remove(struct pci_dev *pd)
+{
+	struct fb_info *info = pci_get_drvdata(pd);
+	struct nvidia_par *par = info->par;
+
+	NVTRACE_ENTER();
+	if (!info)
+		return;
+
+	unregister_framebuffer(info);
+#ifdef CONFIG_MTRR
+	if (par->mtrr.vram_valid)
+		mtrr_del(par->mtrr.vram, info->fix.smem_start,
+			 info->fix.smem_len);
+#endif				/* CONFIG_MTRR */
+
+	fb_destroy_modedb(info->monspecs.modedb);
+	iounmap(par->REGS);
+	iounmap(info->screen_base);
+	pci_release_regions(pd);
+	pci_disable_device(pd);
+	kfree(info->pixmap.addr);
+	framebuffer_release(info);
+	pci_set_drvdata(pd, NULL);
+	NVTRACE_LEAVE();
+}
+
+/* ------------------------------------------------------------------------- *
+ *
+ * initialization
+ *
+ * ------------------------------------------------------------------------- */
+
+#ifndef MODULE
+static int __init nvidiafb_setup(char *options)
+{
+	char *this_opt;
+
+	NVTRACE_ENTER();
+	if (!options || !*options)
+		return 0;
+
+	while ((this_opt = strsep(&options, ",")) != NULL) {
+		if (!strncmp(this_opt, "forceCRTC", 9)) {
+			char *p;
+
+			p = this_opt + 9;
+			if (!*p || !*(++p))
+				continue;
+			forceCRTC = *p - '0';
+			if (forceCRTC < 0 || forceCRTC > 1)
+				forceCRTC = -1;
+		} else if (!strncmp(this_opt, "flatpanel", 9)) {
+			flatpanel = 1;
+		} else if (!strncmp(this_opt, "hwcur", 5)) {
+			hwcur = 1;
+		} else if (!strncmp(this_opt, "noaccel", 6)) {
+			noaccel = 1;
+		} else if (!strncmp(this_opt, "noscale", 7)) {
+			noscale = 1;
+		} else if (!strncmp(this_opt, "paneltweak:", 11)) {
+			paneltweak = simple_strtoul(this_opt+11, NULL, 0);
+#ifdef CONFIG_MTRR
+		} else if (!strncmp(this_opt, "nomtrr", 6)) {
+			nomtrr = 1;
+#endif
+		} else
+			mode_option = this_opt;
+	}
+	NVTRACE_LEAVE();
+	return 0;
+}
+#endif				/* !MODULE */
+
+static struct pci_driver nvidiafb_driver = {
+	.name = "nvidiafb",
+	.id_table = nvidiafb_pci_tbl,
+	.probe = nvidiafb_probe,
+	.remove = __exit_p(nvidiafb_remove),
+};
+
+/* ------------------------------------------------------------------------- *
+ *
+ * modularization
+ *
+ * ------------------------------------------------------------------------- */
+
+static int __devinit nvidiafb_init(void)
+{
+#ifndef MODULE
+	char *option = NULL;
+
+	if (fb_get_options("nvidiafb", &option))
+		return -ENODEV;
+	nvidiafb_setup(option);
+#endif
+	return pci_register_driver(&nvidiafb_driver);
+}
+
+module_init(nvidiafb_init);
+
+#ifdef MODULE
+static void __exit nvidiafb_exit(void)
+{
+	pci_unregister_driver(&nvidiafb_driver);
+}
+
+module_exit(nvidiafb_exit);
+
+module_param(flatpanel, int, 0);
+MODULE_PARM_DESC(flatpanel,
+		 "Enables experimental flat panel support for some chipsets. "
+		 "(0 or 1=enabled) (default=0)");
+module_param(hwcur, int, 0);
+MODULE_PARM_DESC(hwcur,
+		 "Enables hardware cursor implementation. (0 or 1=enabled) "
+		 "(default=0)");
+module_param(noaccel, int, 0);
+MODULE_PARM_DESC(noaccel,
+		 "Disables hardware acceleration. (0 or 1=disable) "
+		 "(default=0)");
+module_param(noscale, int, 0);
+MODULE_PARM_DESC(noscale,
+		 "Disables screen scaleing. (0 or 1=disable) "
+		 "(default=0, do scaling)");
+module_param(paneltweak, int, 0);
+MODULE_PARM_DESC(paneltweak,
+		 "Tweak display settings for flatpanels. "
+		 "(default=0, no tweaks)");
+module_param(forceCRTC, int, 0);
+MODULE_PARM_DESC(forceCRTC,
+		 "Forces usage of a particular CRTC in case autodetection "
+		 "fails. (0 or 1) (default=autodetect)");
+#ifdef CONFIG_MTRR
+module_param(nomtrr, bool, 0);
+MODULE_PARM_DESC(nomtrr, "Disables MTRR support (0 or 1=disabled) "
+		 "(default=0)");
+#endif
+
+MODULE_AUTHOR("Antonino Daplas");
+MODULE_DESCRIPTION("Framebuffer driver for nVidia graphics chipset");
+MODULE_LICENSE("GPL");
+#endif				/* MODULE */
+
diff -Nru a/drivers/video/offb.c b/drivers/video/offb.c
--- a/drivers/video/offb.c	2005-03-11 12:51:51 -08:00
+++ b/drivers/video/offb.c	2005-03-11 12:51:51 -08:00
@@ -29,6 +29,10 @@
 #include <asm/io.h>
 #include <asm/prom.h>
 
+#ifdef CONFIG_PPC64
+#include <asm/pci-bridge.h>
+#endif
+
 #ifdef CONFIG_PPC32
 #include <asm/bootx.h>
 #endif
@@ -322,7 +326,8 @@
 	int *pp, i;
 	unsigned int len;
 	int width = 640, height = 480, depth = 8, pitch;
-	unsigned *up, address;
+	unsigned *up;
+	unsigned long address;
 
 	if ((pp = (int *) get_property(dp, "depth", &len)) != NULL
 	    && len == sizeof(int))
@@ -356,6 +361,10 @@
 		}
 
 		address = (u_long) dp->addrs[i].address;
+
+#ifdef CONFIG_PPC64
+		address += dp->phb->pci_mem_offset;
+#endif
 
 		/* kludge for valkyrie */
 		if (strcmp(dp->name, "valkyrie") == 0)
diff -Nru a/drivers/video/pm2fb.c b/drivers/video/pm2fb.c
--- a/drivers/video/pm2fb.c	2005-03-11 12:51:52 -08:00
+++ b/drivers/video/pm2fb.c	2005-03-11 12:51:52 -08:00
@@ -62,7 +62,7 @@
 /*
  * Driver data 
  */
-static char *mode __initdata = NULL;
+static char *mode __devinitdata = NULL;
 
 /*
  * The XFree GLINT driver will (I think to implement hardware cursor
@@ -73,8 +73,8 @@
  * these flags allow the user to specify that requests for +ve sync
  * should be silently turned in -ve sync.
  */
-static int lowhsync __initdata = 0;
-static int lowvsync __initdata = 0;	
+static int lowhsync __devinitdata = 0;
+static int lowvsync __devinitdata = 0;
 
 /*
  * The hardware state of the graphics card that isn't part of the
@@ -97,7 +97,7 @@
  * Here we define the default structs fb_fix_screeninfo and fb_var_screeninfo
  * if we don't use modedb.
  */
-static struct fb_fix_screeninfo pm2fb_fix __initdata = {
+static struct fb_fix_screeninfo pm2fb_fix __devinitdata = {
 	.id =		"", 
 	.type =		FB_TYPE_PACKED_PIXELS,
 	.visual =	FB_VISUAL_PSEUDOCOLOR,
@@ -110,7 +110,7 @@
 /*
  * Default video mode. In case the modedb doesn't work.
  */
-static struct fb_var_screeninfo pm2fb_var __initdata = {
+static struct fb_var_screeninfo pm2fb_var __devinitdata = {
 	/* "640x480, 8 bpp @ 60 Hz */
 	.xres =		640,
 	.yres =		480,
@@ -1243,47 +1243,13 @@
 MODULE_DEVICE_TABLE(pci, pm2fb_id_table);
 
 
-/*
- *  Initialization
- */
-
-int __init pm2fb_setup(char *options);
-
-int __init pm2fb_init(void)
-{
-#ifndef MODULE
-	char *option = NULL;
-
-	if (fb_get_options("pm2fb", &option))
-		return -ENODEV;
-	pm2fb_setup(option);
-#endif
-
-	return pci_module_init(&pm2fb_driver);
-}
-
-#ifdef MODULE
-/*
- *  Cleanup
- */
-
-static void __exit pm2fb_exit(void)
-{
-	pci_unregister_driver(&pm2fb_driver);
-}
-#endif
-
-/*
- *  Setup
- */
-
 #ifndef MODULE
 /**
  * Parse user speficied options.
  *
  * This is, comma-separated options following `video=pm2fb:'.
  */
-int __init pm2fb_setup(char *options)
+static int __init pm2fb_setup(char *options)
 {
 	char* this_opt;
 
@@ -1306,13 +1272,31 @@
 #endif
 
 
-/* ------------------------------------------------------------------------- */
-
-/* ------------------------------------------------------------------------- */
+static int __init pm2fb_init(void)
+{
+#ifndef MODULE
+	char *option = NULL;
 
+	if (fb_get_options("pm2fb", &option))
+		return -ENODEV;
+	pm2fb_setup(option);
+#endif
 
+	return pci_module_init(&pm2fb_driver);
+}
 
 module_init(pm2fb_init);
+
+#ifdef MODULE
+/*
+ *  Cleanup
+ */
+
+static void __exit pm2fb_exit(void)
+{
+	pci_unregister_driver(&pm2fb_driver);
+}
+#endif
 
 #ifdef MODULE
 module_exit(pm2fb_exit);
diff -Nru a/drivers/video/pvr2fb.c b/drivers/video/pvr2fb.c
--- a/drivers/video/pvr2fb.c	2005-03-11 12:51:41 -08:00
+++ b/drivers/video/pvr2fb.c	2005-03-11 12:51:41 -08:00
@@ -4,7 +4,7 @@
  * Dreamcast.
  *
  * Copyright (c) 2001 M. R. Brown <mrbrown@0xd6.org>
- * Copyright (c) 2001, 2002, 2003, 2004 Paul Mundt <lethal@linux-sh.org>
+ * Copyright (c) 2001, 2002, 2003, 2004, 2005 Paul Mundt <lethal@linux-sh.org>
  *
  * This file is part of the LinuxDC project (linuxdc.sourceforge.net).
  *
@@ -33,7 +33,7 @@
  *  Then, when it's time to convert back to hardware settings, the only
  *  constants are the borderstart_* offsets, all other values are derived from
  *  the fb video mode:
- *  
+ *
  *      // PAL
  *      borderstart_h = 116;
  *      borderstart_v = 44;
@@ -939,7 +939,8 @@
 
 	pvr2_fix.mmio_start	= pci_resource_start(pdev, 1);
 	pvr2_fix.mmio_len	= pci_resource_len(pdev, 1);
-	fbinfo->device = &pdev->dev;
+
+	fb_info->device		= &pdev->dev;
 
 	return pvr2fb_common_init();
 }
@@ -1068,7 +1069,6 @@
 	size = sizeof(struct fb_info) + sizeof(struct pvr2fb_par) + 16 * sizeof(u32);
 
 	fb_info = kmalloc(size, GFP_KERNEL);
-	
 	if (!fb_info) {
 		printk(KERN_ERR "Failed to allocate memory for fb_info\n");
 		return -ENOMEM;
diff -Nru a/drivers/video/radeonfb.c b/drivers/video/radeonfb.c
--- a/drivers/video/radeonfb.c	2005-03-11 12:51:51 -08:00
+++ b/drivers/video/radeonfb.c	2005-03-11 12:51:51 -08:00
@@ -657,14 +657,17 @@
 /*
  * globals
  */
-        
-static char *mode_option __initdata;
+
+#ifndef MODULE
+static char *mode_option;
+#endif
+
 static char noaccel = 0;
 static char mirror = 0;
-static int panel_yres __initdata = 0;
-static char force_dfp __initdata = 0;
+static int panel_yres = 0;
+static char force_dfp = 0;
 static struct radeonfb_info *board_list = NULL;
-static char nomtrr __initdata = 0;
+static char nomtrr = 0;
 
 /*
  * prototypes
@@ -3109,28 +3112,8 @@
 	.remove		= __devexit_p(radeonfb_pci_unregister),
 };
 
-int __init radeonfb_old_setup (char *options);
-
-int __init radeonfb_old_init (void)
-{
 #ifndef MODULE
-	char *option = NULL;
-
-	if (fb_get_options("radeonfb_old", &option))
-		return -ENODEV;
-	radeonfb_old_setup(option);
-#endif
-	return pci_module_init (&radeonfb_driver);
-}
-
-
-void __exit radeonfb_old_exit (void)
-{
-	pci_unregister_driver (&radeonfb_driver);
-}
-
-
-int __init radeonfb_old_setup (char *options)
+static int __init radeonfb_old_setup (char *options)
 {
         char *this_opt;
 
@@ -3156,12 +3139,28 @@
 
 	return 0;
 }
+#endif  /*  MODULE  */
 
-module_init(radeonfb_old_init);
+static int __init radeonfb_old_init (void)
+{
+#ifndef MODULE
+	char *option = NULL;
 
-#ifdef MODULE
-module_exit(radeonfb_old_exit);
+	if (fb_get_options("radeonfb_old", &option))
+		return -ENODEV;
+	radeonfb_old_setup(option);
 #endif
+	return pci_module_init (&radeonfb_driver);
+}
+
+
+static void __exit radeonfb_old_exit (void)
+{
+	pci_unregister_driver (&radeonfb_driver);
+}
+
+module_init(radeonfb_old_init);
+module_exit(radeonfb_old_exit);
 
 
 MODULE_AUTHOR("Ani Joshi");
diff -Nru a/drivers/video/riva/fbdev.c b/drivers/video/riva/fbdev.c
--- a/drivers/video/riva/fbdev.c	2005-03-11 12:51:47 -08:00
+++ b/drivers/video/riva/fbdev.c	2005-03-11 12:51:47 -08:00
@@ -208,23 +208,23 @@
  * ------------------------------------------------------------------------- */
 
 /* command line data, set in rivafb_setup() */
-static int flatpanel __initdata = -1; /* Autodetect later */
-static int forceCRTC __initdata = -1;
-static int noaccel   __initdata = 0;
+static int flatpanel __devinitdata = -1; /* Autodetect later */
+static int forceCRTC __devinitdata = -1;
+static int noaccel   __devinitdata = 0;
 #ifdef CONFIG_MTRR
-static int nomtrr __initdata = 0;
+static int nomtrr __devinitdata = 0;
 #endif
 
-static char *mode_option __initdata = NULL;
+static char *mode_option __devinitdata = NULL;
 static int  strictmode       = 0;
 
-static struct fb_fix_screeninfo __initdata rivafb_fix = {
+static struct fb_fix_screeninfo __devinitdata rivafb_fix = {
 	.type		= FB_TYPE_PACKED_PIXELS,
 	.xpanstep	= 1,
 	.ypanstep	= 1,
 };
 
-static struct fb_var_screeninfo __initdata rivafb_default_var = {
+static struct fb_var_screeninfo __devinitdata rivafb_default_var = {
 	.xres		= 640,
 	.yres		= 480,
 	.xres_virtual	= 640,
@@ -906,7 +906,7 @@
 }
 
 /* acceleration routines */
-inline void wait_for_idle(struct riva_par *par)
+static inline void wait_for_idle(struct riva_par *par)
 {
 	while (par->riva.Busy(&par->riva));
 }
@@ -923,7 +923,7 @@
 
 }
 
-void riva_setup_accel(struct fb_info *info)
+static void riva_setup_accel(struct fb_info *info)
 {
 	struct riva_par *par = (struct riva_par *) info->par;
 
@@ -2139,7 +2139,7 @@
  * ------------------------------------------------------------------------- */
 
 #ifndef MODULE
-int __init rivafb_setup(char *options)
+static int __init rivafb_setup(char *options)
 {
 	char *this_opt;
 
@@ -2189,7 +2189,7 @@
  *
  * ------------------------------------------------------------------------- */
 
-int __devinit rivafb_init(void)
+static int __devinit rivafb_init(void)
 {
 #ifndef MODULE
 	char *option = NULL;
diff -Nru a/drivers/video/riva/rivafb-i2c.c b/drivers/video/riva/rivafb-i2c.c
--- a/drivers/video/riva/rivafb-i2c.c	2005-03-11 12:51:46 -08:00
+++ b/drivers/video/riva/rivafb-i2c.c	2005-03-11 12:51:46 -08:00
@@ -120,8 +120,12 @@
 	rc = i2c_bit_add_bus(&chan->adapter);
 	if (rc == 0)
 		dev_dbg(&chan->par->pdev->dev, "I2C bus %s registered.\n", name);
-	else
-		dev_warn(&chan->par->pdev->dev, "Failed to register I2C bus %s.\n", name);
+	else {
+		dev_warn(&chan->par->pdev->dev,
+			 "Failed to register I2C bus %s.\n", name);
+		chan->par = NULL;
+	}
+
 	return rc;
 }
 
@@ -171,6 +175,9 @@
 		},
 	};
 	u8 *buf;
+
+	if (!chan->par)
+		return NULL;
 
 	buf = kmalloc(EDID_LENGTH, GFP_KERNEL);
 	if (!buf) {
diff -Nru a/drivers/video/savage/Makefile b/drivers/video/savage/Makefile
--- a/drivers/video/savage/Makefile	2005-03-11 12:51:40 -08:00
+++ b/drivers/video/savage/Makefile	2005-03-11 12:51:40 -08:00
@@ -2,7 +2,8 @@
 # Makefile for the S3 Savage framebuffer driver
 #
 
-obj-$(CONFIG_FB_SAVAGE)		+= savagefb.o
-obj-$(CONFIG_FB_SAVAGE_I2C)     += savagefb-i2c.o
-obj-$(CONFIG_FB_SAVAGE_ACCEL)   += savagefb_accel.o
+obj-$(CONFIG_FB_SAVAGE)			+= savagefb.o
 
+savagefb-y				+= savagefb_driver.o
+savagefb-$(CONFIG_FB_SAVAGE_I2C)	+= savagefb-i2c.o
+savagefb-$(CONFIG_FB_SAVAGE_ACCEL)	+= savagefb_accel.o
diff -Nru a/drivers/video/savage/savagefb-i2c.c b/drivers/video/savage/savagefb-i2c.c
--- a/drivers/video/savage/savagefb-i2c.c	2005-03-11 12:51:48 -08:00
+++ b/drivers/video/savage/savagefb-i2c.c	2005-03-11 12:51:48 -08:00
@@ -207,7 +207,6 @@
 
 	savage_setup_i2c_bus(&par->chan, "SAVAGE DDC2");
 }
-EXPORT_SYMBOL(savagefb_create_i2c_busses);
 
 void savagefb_delete_i2c_busses(struct fb_info *info)
 {
@@ -222,7 +221,6 @@
 
 	par->chan.par = NULL;
 }
-EXPORT_SYMBOL(savagefb_delete_i2c_busses);
 
 static u8 *savage_do_probe_i2c_edid(struct savagefb_i2c_chan *chan)
 {
@@ -280,6 +278,5 @@
 
 	return 0;
 }
-EXPORT_SYMBOL(savagefb_probe_i2c_connector);
 
 MODULE_LICENSE("GPL");
diff -Nru a/drivers/video/savage/savagefb.c b/drivers/video/savage/savagefb.c
--- a/drivers/video/savage/savagefb.c	2005-03-11 12:51:46 -08:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,2276 +0,0 @@
-/*
- * linux/drivers/video/savagefb.c -- S3 Savage Framebuffer Driver
- *
- * Copyright (c) 2001-2002  Denis Oliver Kropp <dok@directfb.org>
- *                          Sven Neumann <neo@directfb.org>
- *
- *
- * Card specific code is based on XFree86's savage driver.
- * Framebuffer framework code is based on code of cyber2000fb and tdfxfb.
- *
- * 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.
- *
- * 0.4.0 (neo)
- *  - hardware accelerated clear and move
- *
- * 0.3.2 (dok)
- *  - wait for vertical retrace before writing to cr67
- *    at the beginning of savagefb_set_par
- *  - use synchronization registers cr23 and cr26
- *
- * 0.3.1 (dok)
- *  - reset 3D engine
- *  - don't return alpha bits for 32bit format
- *
- * 0.3.0 (dok)
- *  - added WaitIdle functions for all Savage types
- *  - do WaitIdle before mode switching
- *  - code cleanup
- *
- * 0.2.0 (dok)
- *  - first working version
- *
- *
- * TODO
- * - clock validations in decode_var
- *
- * BUGS
- * - white margin on bootup
- *
- */
-
-#include <linux/config.h>
-#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/pci.h>
-#include <linux/init.h>
-#include <linux/console.h>
-
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/pgtable.h>
-#include <asm/system.h>
-#include <asm/uaccess.h>
-
-#ifdef CONFIG_MTRR
-#include <asm/mtrr.h>
-#endif
-
-#include "savagefb.h"
-
-
-#define SAVAGEFB_VERSION "0.4.0_2.6"
-
-/* --------------------------------------------------------------------- */
-
-
-static char *mode_option __initdata = NULL;
-static int   paletteEnabled = 0;
-
-#ifdef MODULE
-
-MODULE_AUTHOR("(c) 2001-2002  Denis Oliver Kropp <dok@directfb.org>");
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("FBDev driver for S3 Savage PCI/AGP Chips");
-
-#endif
-
-
-/* --------------------------------------------------------------------- */
-
-static void vgaHWSeqReset (struct savagefb_par *par, int start)
-{
-	if (start)
-		VGAwSEQ (0x00, 0x01);		/* Synchronous Reset */
-	else
-		VGAwSEQ (0x00, 0x03);		/* End Reset */
-}
-
-static void vgaHWProtect (struct savagefb_par *par, int on)
-{
-	unsigned char tmp;
-
-	if (on) {
-		/*
-		 * Turn off screen and disable sequencer.
-		 */
-		tmp = VGArSEQ (0x01);
-
-		vgaHWSeqReset (par, 1);	        /* start synchronous reset */
-		VGAwSEQ (0x01, tmp | 0x20);	/* disable the display */
-
-		VGAenablePalette();
-	} else {
-		/*
-		 * Reenable sequencer, then turn on screen.
-		 */
-
-		tmp = VGArSEQ (0x01);
-
-		VGAwSEQ (0x01, tmp & ~0x20);	/* reenable display */
-		vgaHWSeqReset (par, 0);	        /* clear synchronous reset */
-
-		VGAdisablePalette();
-	}
-}
-
-static void vgaHWRestore (struct savagefb_par  *par)
-{
-	int i;
-
-	VGAwMISC (par->MiscOutReg);
-
-	for (i = 1; i < 5; i++)
-		VGAwSEQ (i, par->Sequencer[i]);
-
-	/* Ensure CRTC registers 0-7 are unlocked by clearing bit 7 or
-	   CRTC[17] */
-	VGAwCR (17, par->CRTC[17] & ~0x80);
-
-	for (i = 0; i < 25; i++)
-		VGAwCR (i, par->CRTC[i]);
-
-	for (i = 0; i < 9; i++)
-		VGAwGR (i, par->Graphics[i]);
-
-	VGAenablePalette();
-
-	for (i = 0; i < 21; i++)
-		VGAwATTR (i, par->Attribute[i]);
-
-	VGAdisablePalette();
-}
-
-static void vgaHWInit (struct fb_var_screeninfo *var,
-		       struct savagefb_par            *par,
-		       struct xtimings                *timings)
-{
-	par->MiscOutReg = 0x23;
-
-	if (!(timings->sync & FB_SYNC_HOR_HIGH_ACT))
-		par->MiscOutReg |= 0x40;
-
-	if (!(timings->sync & FB_SYNC_VERT_HIGH_ACT))
-		par->MiscOutReg |= 0x80;
-
-	/*
-	 * Time Sequencer
-	 */
-	par->Sequencer[0x00] = 0x00;
-	par->Sequencer[0x01] = 0x01;
-	par->Sequencer[0x02] = 0x0F;
-	par->Sequencer[0x03] = 0x00;          /* Font select */
-	par->Sequencer[0x04] = 0x0E;          /* Misc */
-
-	/*
-	 * CRTC Controller
-	 */
-	par->CRTC[0x00] = (timings->HTotal >> 3) - 5;
-	par->CRTC[0x01] = (timings->HDisplay >> 3) - 1;
-	par->CRTC[0x02] = (timings->HSyncStart >> 3) - 1;
-	par->CRTC[0x03] = (((timings->HSyncEnd >> 3)  - 1) & 0x1f) | 0x80;
-	par->CRTC[0x04] = (timings->HSyncStart >> 3);
-	par->CRTC[0x05] = ((((timings->HSyncEnd >> 3) - 1) & 0x20) << 2) |
-		(((timings->HSyncEnd >> 3)) & 0x1f);
-	par->CRTC[0x06] = (timings->VTotal - 2) & 0xFF;
-	par->CRTC[0x07] = (((timings->VTotal - 2) & 0x100) >> 8) |
-		(((timings->VDisplay - 1) & 0x100) >> 7) |
-		((timings->VSyncStart & 0x100) >> 6) |
-		(((timings->VSyncStart - 1) & 0x100) >> 5) |
-		0x10 |
-		(((timings->VTotal - 2) & 0x200) >> 4) |
-		(((timings->VDisplay - 1) & 0x200) >> 3) |
-		((timings->VSyncStart & 0x200) >> 2);
-	par->CRTC[0x08] = 0x00;
-	par->CRTC[0x09] = (((timings->VSyncStart - 1) & 0x200) >> 4) | 0x40;
-
-	if (timings->dblscan)
-		par->CRTC[0x09] |= 0x80;
-
-	par->CRTC[0x0a] = 0x00;
-	par->CRTC[0x0b] = 0x00;
-	par->CRTC[0x0c] = 0x00;
-	par->CRTC[0x0d] = 0x00;
-	par->CRTC[0x0e] = 0x00;
-	par->CRTC[0x0f] = 0x00;
-	par->CRTC[0x10] = timings->VSyncStart & 0xff;
-	par->CRTC[0x11] = (timings->VSyncEnd & 0x0f) | 0x20;
-	par->CRTC[0x12] = (timings->VDisplay - 1) & 0xff;
-	par->CRTC[0x13] = var->xres_virtual >> 4;
-	par->CRTC[0x14] = 0x00;
-	par->CRTC[0x15] = (timings->VSyncStart - 1) & 0xff;
-	par->CRTC[0x16] = (timings->VSyncEnd - 1) & 0xff;
-	par->CRTC[0x17] = 0xc3;
-	par->CRTC[0x18] = 0xff;
-
-	/*
-	 * are these unnecessary?
-	 * vgaHWHBlankKGA(mode, regp, 0, KGA_FIX_OVERSCAN|KGA_ENABLE_ON_ZERO);
-	 * vgaHWVBlankKGA(mode, regp, 0, KGA_FIX_OVERSCAN|KGA_ENABLE_ON_ZERO);
-	 */
-
-	/*
-	 * Graphics Display Controller
-	 */
-	par->Graphics[0x00] = 0x00;
-	par->Graphics[0x01] = 0x00;
-	par->Graphics[0x02] = 0x00;
-	par->Graphics[0x03] = 0x00;
-	par->Graphics[0x04] = 0x00;
-	par->Graphics[0x05] = 0x40;
-	par->Graphics[0x06] = 0x05;   /* only map 64k VGA memory !!!! */
-	par->Graphics[0x07] = 0x0F;
-	par->Graphics[0x08] = 0xFF;
-
-
-	par->Attribute[0x00]  = 0x00; /* standard colormap translation */
-	par->Attribute[0x01]  = 0x01;
-	par->Attribute[0x02]  = 0x02;
-	par->Attribute[0x03]  = 0x03;
-	par->Attribute[0x04]  = 0x04;
-	par->Attribute[0x05]  = 0x05;
-	par->Attribute[0x06]  = 0x06;
-	par->Attribute[0x07]  = 0x07;
-	par->Attribute[0x08]  = 0x08;
-	par->Attribute[0x09]  = 0x09;
-	par->Attribute[0x0a] = 0x0A;
-	par->Attribute[0x0b] = 0x0B;
-	par->Attribute[0x0c] = 0x0C;
-	par->Attribute[0x0d] = 0x0D;
-	par->Attribute[0x0e] = 0x0E;
-	par->Attribute[0x0f] = 0x0F;
-	par->Attribute[0x10] = 0x41;
-	par->Attribute[0x11] = 0xFF;
-	par->Attribute[0x12] = 0x0F;
-	par->Attribute[0x13] = 0x00;
-	par->Attribute[0x14] = 0x00;
-}
-
-/* -------------------- Hardware specific routines ------------------------- */
-
-/*
- * Hardware Acceleration for SavageFB
- */
-
-/* Wait for fifo space */
-static void
-savage3D_waitfifo(struct savagefb_par *par, int space)
-{
-	int slots = MAXFIFO - space;
-
-	while ((savage_in32(0x48C00) & 0x0000ffff) > slots);
-}
-
-static void
-savage4_waitfifo(struct savagefb_par *par, int space)
-{
-	int slots = MAXFIFO - space;
-
-	while ((savage_in32(0x48C60) & 0x001fffff) > slots);
-}
-
-static void
-savage2000_waitfifo(struct savagefb_par *par, int space)
-{
-	int slots = MAXFIFO - space;
-
-	while ((savage_in32(0x48C60) & 0x0000ffff) > slots);
-}
-
-/* Wait for idle accelerator */
-static void
-savage3D_waitidle(struct savagefb_par *par)
-{
-	while ((savage_in32(0x48C00) & 0x0008ffff) != 0x80000);
-}
-
-static void
-savage4_waitidle(struct savagefb_par *par)
-{
-	while ((savage_in32(0x48C60) & 0x00a00000) != 0x00a00000);
-}
-
-static void
-savage2000_waitidle(struct savagefb_par *par)
-{
-	while ((savage_in32(0x48C60) & 0x009fffff));
-}
-
-
-static void
-SavageSetup2DEngine (struct savagefb_par  *par)
-{
-	unsigned long GlobalBitmapDescriptor;
-
-	GlobalBitmapDescriptor = 1 | 8 | BCI_BD_BW_DISABLE;
-	BCI_BD_SET_BPP (GlobalBitmapDescriptor, par->depth);
-	BCI_BD_SET_STRIDE (GlobalBitmapDescriptor, par->vwidth);
-
-	switch(par->chip) {
-	case S3_SAVAGE3D:
-	case S3_SAVAGE_MX:
-		/* Disable BCI */
-		savage_out32(0x48C18, savage_in32(0x48C18) & 0x3FF0);
-		/* Setup BCI command overflow buffer */
-		savage_out32(0x48C14, (par->cob_offset >> 11) | (par->cob_index << 29));
-		/* Program shadow status update. */
-		savage_out32(0x48C10, 0x78207220);
-		savage_out32(0x48C0C, 0);
-		/* Enable BCI and command overflow buffer */
-		savage_out32(0x48C18, savage_in32(0x48C18) | 0x0C);
-		break;
-	case S3_SAVAGE4:
-	case S3_PROSAVAGE:
-	case S3_SUPERSAVAGE:
-		/* Disable BCI */
-		savage_out32(0x48C18, savage_in32(0x48C18) & 0x3FF0);
-		/* Program shadow status update */
-		savage_out32(0x48C10, 0x00700040);
-		savage_out32(0x48C0C, 0);
-		/* Enable BCI without the COB */
-		savage_out32(0x48C18, savage_in32(0x48C18) | 0x08);
-		break;
-	case S3_SAVAGE2000:
-		/* Disable BCI */
-		savage_out32(0x48C18, 0);
-		/* Setup BCI command overflow buffer */
-		savage_out32(0x48C18, (par->cob_offset >> 7) | (par->cob_index));
-		/* Disable shadow status update */
-		savage_out32(0x48A30, 0);
-		/* Enable BCI and command overflow buffer */
-		savage_out32(0x48C18, savage_in32(0x48C18) | 0x00280000 );
-		break;
-	    default:
-		break;
-	}
-	/* Turn on 16-bit register access. */
-	vga_out8(0x3d4, 0x31);
-	vga_out8(0x3d5, 0x0c);
-
-	/* Set stride to use GBD. */
-	vga_out8 (0x3d4, 0x50);
-	vga_out8 (0x3d5, vga_in8 (0x3d5 ) | 0xC1);
-
-	/* Enable 2D engine. */
-	vga_out8 (0x3d4, 0x40 );
-	vga_out8 (0x3d5, 0x01 );
-
-	savage_out32 (MONO_PAT_0, ~0);
-	savage_out32 (MONO_PAT_1, ~0);
-
-	/* Setup plane masks */
-	savage_out32 (0x8128, ~0 ); /* enable all write planes */
-	savage_out32 (0x812C, ~0 ); /* enable all read planes */
-	savage_out16 (0x8134, 0x27 );
-	savage_out16 (0x8136, 0x07 );
-
-	/* Now set the GBD */
-	par->bci_ptr = 0;
-	par->SavageWaitFifo (par, 4);
-
-	BCI_SEND( BCI_CMD_SETREG | (1 << 16) | BCI_GBD1 );
-	BCI_SEND( 0 );
-	BCI_SEND( BCI_CMD_SETREG | (1 << 16) | BCI_GBD2 );
-	BCI_SEND( GlobalBitmapDescriptor );
-}
-
-
-static void SavageCalcClock(long freq, int min_m, int min_n1, int max_n1,
-			    int min_n2, int max_n2, long freq_min,
-			    long freq_max, unsigned int *mdiv,
-			    unsigned int *ndiv, unsigned int *r)
-{
-	long diff, best_diff;
-	unsigned int m;
-	unsigned char n1, n2, best_n1=16+2, best_n2=2, best_m=125+2;
-
-	if (freq < freq_min / (1 << max_n2)) {
-		printk (KERN_ERR "invalid frequency %ld Khz\n", freq);
-		freq = freq_min / (1 << max_n2);
-	}
-	if (freq > freq_max / (1 << min_n2)) {
-		printk (KERN_ERR "invalid frequency %ld Khz\n", freq);
-		freq = freq_max / (1 << min_n2);
-	}
-
-	/* work out suitable timings */
-	best_diff = freq;
-
-	for (n2=min_n2; n2<=max_n2; n2++) {
-		for (n1=min_n1+2; n1<=max_n1+2; n1++) {
-			m = (freq * n1 * (1 << n2) + HALF_BASE_FREQ) /
-				BASE_FREQ;
-			if (m < min_m+2 || m > 127+2)
-				continue;
-			if ((m * BASE_FREQ >= freq_min * n1) &&
-			    (m * BASE_FREQ <= freq_max * n1)) {
-				diff = freq * (1 << n2) * n1 - BASE_FREQ * m;
-				if (diff < 0)
-					diff = -diff;
-				if (diff < best_diff) {
-					best_diff = diff;
-					best_m = m;
-					best_n1 = n1;
-					best_n2 = n2;
-				}
-			}
-		}
-	}
-
-	*ndiv = best_n1 - 2;
-	*r = best_n2;
-	*mdiv = best_m - 2;
-}
-
-static int common_calc_clock(long freq, int min_m, int min_n1, int max_n1,
-			     int min_n2, int max_n2, long freq_min,
-			     long freq_max, unsigned char *mdiv,
-			     unsigned char *ndiv)
-{
-	long diff, best_diff;
-	unsigned int m;
-	unsigned char n1, n2;
-	unsigned char best_n1 = 16+2, best_n2 = 2, best_m = 125+2;
-
-	best_diff = freq;
-
-	for (n2 = min_n2; n2 <= max_n2; n2++) {
-		for (n1 = min_n1+2; n1 <= max_n1+2; n1++) {
-			m = (freq * n1 * (1 << n2) + HALF_BASE_FREQ) /
-				BASE_FREQ;
-			if (m < min_m + 2 || m > 127+2)
-				continue;
-			if((m * BASE_FREQ >= freq_min * n1) &&
-			   (m * BASE_FREQ <= freq_max * n1)) {
-				diff = freq * (1 << n2) * n1 - BASE_FREQ * m;
-				if(diff < 0)
-					diff = -diff;
-				if(diff < best_diff) {
-					best_diff = diff;
-					best_m = m;
-					best_n1 = n1;
-					best_n2 = n2;
-				}
-			}
-		}
-	}
-
-	if(max_n1 == 63)
-		*ndiv = (best_n1 - 2) | (best_n2 << 6);
-	else
-		*ndiv = (best_n1 - 2) | (best_n2 << 5);
-
-	*mdiv = best_m - 2;
-
-	return 0;
-}
-
-#ifdef SAVAGEFB_DEBUG
-/* This function is used to debug, it prints out the contents of s3 regs */
-
-static void SavagePrintRegs(void)
-{
-	unsigned char i;
-	int vgaCRIndex = 0x3d4;
-	int vgaCRReg = 0x3d5;
-
-	printk(KERN_DEBUG "SR    x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE "
-	       "xF" );
-
-	for( i = 0; i < 0x70; i++ ) {
-		if( !(i % 16) )
-			printk(KERN_DEBUG "\nSR%xx ", i >> 4 );
-		vga_out8( 0x3c4, i );
-		printk(KERN_DEBUG " %02x", vga_in8(0x3c5) );
-	}
-
-	printk(KERN_DEBUG "\n\nCR    x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC "
-	       "xD xE xF" );
-
-	for( i = 0; i < 0xB7; i++ ) {
-		if( !(i % 16) )
-			printk(KERN_DEBUG "\nCR%xx ", i >> 4 );
-		vga_out8( vgaCRIndex, i );
-		printk(KERN_DEBUG " %02x", vga_in8(vgaCRReg) );
-	}
-
-	printk(KERN_DEBUG "\n\n");
-}
-#endif
-
-/* --------------------------------------------------------------------- */
-
-static void savage_get_default_par(struct savagefb_par *par)
-{
-	unsigned char cr3a, cr53, cr66;
-
-	vga_out16 (0x3d4, 0x4838);
-	vga_out16 (0x3d4, 0xa039);
-	vga_out16 (0x3c4, 0x0608);
-
-	vga_out8 (0x3d4, 0x66);
-	cr66 = vga_in8 (0x3d5);
-	vga_out8 (0x3d5, cr66 | 0x80);
-	vga_out8 (0x3d4, 0x3a);
-	cr3a = vga_in8 (0x3d5);
-	vga_out8 (0x3d5, cr3a | 0x80);
-	vga_out8 (0x3d4, 0x53);
-	cr53 = vga_in8 (0x3d5);
-	vga_out8 (0x3d5, cr53 & 0x7f);
-
-	vga_out8 (0x3d4, 0x66);
-	vga_out8 (0x3d5, cr66);
-	vga_out8 (0x3d4, 0x3a);
-	vga_out8 (0x3d5, cr3a);
-
-	vga_out8 (0x3d4, 0x66);
-	vga_out8 (0x3d5, cr66);
-	vga_out8 (0x3d4, 0x3a);
-	vga_out8 (0x3d5, cr3a);
-
-	/* unlock extended seq regs */
-	vga_out8 (0x3c4, 0x08);
-	par->SR08 = vga_in8 (0x3c5);
-	vga_out8 (0x3c5, 0x06);
-
-	/* now save all the extended regs we need */
-	vga_out8 (0x3d4, 0x31);
-	par->CR31 = vga_in8 (0x3d5);
-	vga_out8 (0x3d4, 0x32);
-	par->CR32 = vga_in8 (0x3d5);
-	vga_out8 (0x3d4, 0x34);
-	par->CR34 = vga_in8 (0x3d5);
-	vga_out8 (0x3d4, 0x36);
-	par->CR36 = vga_in8 (0x3d5);
-	vga_out8 (0x3d4, 0x3a);
-	par->CR3A = vga_in8 (0x3d5);
-	vga_out8 (0x3d4, 0x40);
-	par->CR40 = vga_in8 (0x3d5);
-	vga_out8 (0x3d4, 0x42);
-	par->CR42 = vga_in8 (0x3d5);
-	vga_out8 (0x3d4, 0x45);
-	par->CR45 = vga_in8 (0x3d5);
-	vga_out8 (0x3d4, 0x50);
-	par->CR50 = vga_in8 (0x3d5);
-	vga_out8 (0x3d4, 0x51);
-	par->CR51 = vga_in8 (0x3d5);
-	vga_out8 (0x3d4, 0x53);
-	par->CR53 = vga_in8 (0x3d5);
-	vga_out8 (0x3d4, 0x58);
-	par->CR58 = vga_in8 (0x3d5);
-	vga_out8 (0x3d4, 0x60);
-	par->CR60 = vga_in8 (0x3d5);
-	vga_out8 (0x3d4, 0x66);
-	par->CR66 = vga_in8 (0x3d5);
-	vga_out8 (0x3d4, 0x67);
-	par->CR67 = vga_in8 (0x3d5);
-	vga_out8 (0x3d4, 0x68);
-	par->CR68 = vga_in8 (0x3d5);
-	vga_out8 (0x3d4, 0x69);
-	par->CR69 = vga_in8 (0x3d5);
-	vga_out8 (0x3d4, 0x6f);
-	par->CR6F = vga_in8 (0x3d5);
-
-	vga_out8 (0x3d4, 0x33);
-	par->CR33 = vga_in8 (0x3d5);
-	vga_out8 (0x3d4, 0x86);
-	par->CR86 = vga_in8 (0x3d5);
-	vga_out8 (0x3d4, 0x88);
-	par->CR88 = vga_in8 (0x3d5);
-	vga_out8 (0x3d4, 0x90);
-	par->CR90 = vga_in8 (0x3d5);
-	vga_out8 (0x3d4, 0x91);
-	par->CR91 = vga_in8 (0x3d5);
-	vga_out8 (0x3d4, 0xb0);
-	par->CRB0 = vga_in8 (0x3d5) | 0x80;
-
-	/* extended mode timing regs */
-	vga_out8 (0x3d4, 0x3b);
-	par->CR3B = vga_in8 (0x3d5);
-	vga_out8 (0x3d4, 0x3c);
-	par->CR3C = vga_in8 (0x3d5);
-	vga_out8 (0x3d4, 0x43);
-	par->CR43 = vga_in8 (0x3d5);
-	vga_out8 (0x3d4, 0x5d);
-	par->CR5D = vga_in8 (0x3d5);
-	vga_out8 (0x3d4, 0x5e);
-	par->CR5E = vga_in8 (0x3d5);
-	vga_out8 (0x3d4, 0x65);
-	par->CR65 = vga_in8 (0x3d5);
-
-	/* save seq extended regs for DCLK PLL programming */
-	vga_out8 (0x3c4, 0x0e);
-	par->SR0E = vga_in8 (0x3c5);
-	vga_out8 (0x3c4, 0x0f);
-	par->SR0F = vga_in8 (0x3c5);
-	vga_out8 (0x3c4, 0x10);
-	par->SR10 = vga_in8 (0x3c5);
-	vga_out8 (0x3c4, 0x11);
-	par->SR11 = vga_in8 (0x3c5);
-	vga_out8 (0x3c4, 0x12);
-	par->SR12 = vga_in8 (0x3c5);
-	vga_out8 (0x3c4, 0x13);
-	par->SR13 = vga_in8 (0x3c5);
-	vga_out8 (0x3c4, 0x29);
-	par->SR29 = vga_in8 (0x3c5);
-
-	vga_out8 (0x3c4, 0x15);
-	par->SR15 = vga_in8 (0x3c5);
-	vga_out8 (0x3c4, 0x30);
-	par->SR30 = vga_in8 (0x3c5);
-	vga_out8 (0x3c4, 0x18);
-	par->SR18 = vga_in8 (0x3c5);
-
-	/* Save flat panel expansion regsters. */
-	if (par->chip == S3_SAVAGE_MX) {
-		int i;
-
-		for (i = 0; i < 8; i++) {
-			vga_out8 (0x3c4, 0x54+i);
-			par->SR54[i] = vga_in8 (0x3c5);
-		}
-	}
-
-	vga_out8 (0x3d4, 0x66);
-	cr66 = vga_in8 (0x3d5);
-	vga_out8 (0x3d5, cr66 | 0x80);
-	vga_out8 (0x3d4, 0x3a);
-	cr3a = vga_in8 (0x3d5);
-	vga_out8 (0x3d5, cr3a | 0x80);
-
-	/* now save MIU regs */
-	if (par->chip != S3_SAVAGE_MX) {
-		par->MMPR0 = savage_in32(FIFO_CONTROL_REG);
-		par->MMPR1 = savage_in32(MIU_CONTROL_REG);
-		par->MMPR2 = savage_in32(STREAMS_TIMEOUT_REG);
-		par->MMPR3 = savage_in32(MISC_TIMEOUT_REG);
-	}
-
-	vga_out8 (0x3d4, 0x3a);
-	vga_out8 (0x3d5, cr3a);
-	vga_out8 (0x3d4, 0x66);
-	vga_out8 (0x3d5, cr66);
-}
-
-static void savage_update_var(struct fb_var_screeninfo *var, struct fb_videomode *modedb)
-{
-	var->xres = var->xres_virtual = modedb->xres;
-	var->yres = modedb->yres;
-        if (var->yres_virtual < var->yres)
-	    var->yres_virtual = var->yres;
-        var->xoffset = var->yoffset = 0;
-        var->pixclock = modedb->pixclock;
-        var->left_margin = modedb->left_margin;
-        var->right_margin = modedb->right_margin;
-        var->upper_margin = modedb->upper_margin;
-        var->lower_margin = modedb->lower_margin;
-        var->hsync_len = modedb->hsync_len;
-        var->vsync_len = modedb->vsync_len;
-        var->sync = modedb->sync;
-        var->vmode = modedb->vmode;
-}
-
-static int savagefb_check_var (struct fb_var_screeninfo   *var,
-			       struct fb_info *info)
-{
-	struct savagefb_par *par = (struct savagefb_par *)info->par;
-	int memlen, vramlen, mode_valid = 0;
-
-	DBG("savagefb_check_var");
-
-	var->transp.offset = 0;
-	var->transp.length = 0;
-	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 = var->bits_per_pixel;
-		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;
-		break;
-	case 32:
-		var->transp.offset = 24;
-		var->transp.length = 8;
-		var->red.offset = 16;
-		var->red.length = 8;
-		var->green.offset = 8;
-		var->green.length = 8;
-		var->blue.offset = 0;
-		var->blue.length = 8;
-		break;
-
-	default:
-		return -EINVAL;
-	}
-
-	if (!info->monspecs.hfmax || !info->monspecs.vfmax ||
-	    !info->monspecs.dclkmax || !fb_validate_mode(var, info))
-		mode_valid = 1;
-
-	/* calculate modeline if supported by monitor */
-	if (!mode_valid && info->monspecs.gtf) {
-		if (!fb_get_mode(FB_MAXTIMINGS, 0, var, info))
-			mode_valid = 1;
-	}
-
-	if (!mode_valid) {
-		struct fb_videomode *mode;
-
-		mode = fb_find_best_mode(var, &info->modelist);
-		if (mode) {
-			savage_update_var(var, mode);
-			mode_valid = 1;
-		}
-	}
-
-	if (!mode_valid && info->monspecs.modedb_len)
-		return -EINVAL;
-
-	/* Is the mode larger than the LCD panel? */
-	if (par->SavagePanelWidth &&
-	    (var->xres > par->SavagePanelWidth ||
-	     var->yres > par->SavagePanelHeight)) {
-		printk (KERN_INFO "Mode (%dx%d) larger than the LCD panel "
-			"(%dx%d)\n", var->xres,  var->yres,
-			par->SavagePanelWidth,
-			par->SavagePanelHeight);
-		return -1;
-	}
-
-	if (var->yres_virtual < var->yres)
-		var->yres_virtual = var->yres;
-	if (var->xres_virtual < var->xres)
-		var->xres_virtual = var->xres;
-
-	vramlen = info->fix.smem_len;
-
-	memlen = var->xres_virtual * var->bits_per_pixel *
-		var->yres_virtual / 8;
-	if (memlen > vramlen) {
-		var->yres_virtual = vramlen * 8 /
-			(var->xres_virtual * var->bits_per_pixel);
-		memlen = var->xres_virtual * var->bits_per_pixel *
-			var->yres_virtual / 8;
-	}
-
-	/* we must round yres/xres down, we already rounded y/xres_virtual up
-	   if it was possible. We should return -EINVAL, but I disagree */
-	if (var->yres_virtual < var->yres)
-		var->yres = var->yres_virtual;
-	if (var->xres_virtual < var->xres)
-		var->xres = var->xres_virtual;
-	if (var->xoffset + var->xres > var->xres_virtual)
-		var->xoffset = var->xres_virtual - var->xres;
-	if (var->yoffset + var->yres > var->yres_virtual)
-		var->yoffset = var->yres_virtual - var->yres;
-
-	return 0;
-}
-
-
-static int savagefb_decode_var (struct fb_var_screeninfo   *var,
-				struct savagefb_par        *par)
-{
-	struct xtimings timings;
-	int width, dclk, i, j; /*, refresh; */
-	unsigned int m, n, r;
-	unsigned char tmp = 0;
-	unsigned int pixclock = var->pixclock;
-
-	DBG("savagefb_decode_var");
-
-	memset (&timings, 0, sizeof(timings));
-
-	if (!pixclock) pixclock = 10000;	/* 10ns = 100MHz */
-	timings.Clock = 1000000000 / pixclock;
-	if (timings.Clock < 1) timings.Clock = 1;
-	timings.dblscan = var->vmode & FB_VMODE_DOUBLE;
-	timings.interlaced = var->vmode & FB_VMODE_INTERLACED;
-	timings.HDisplay = var->xres;
-	timings.HSyncStart = timings.HDisplay + var->right_margin;
-	timings.HSyncEnd = timings.HSyncStart + var->hsync_len;
-	timings.HTotal = timings.HSyncEnd + var->left_margin;
-	timings.VDisplay = var->yres;
-	timings.VSyncStart = timings.VDisplay + var->lower_margin;
-	timings.VSyncEnd = timings.VSyncStart + var->vsync_len;
-	timings.VTotal = timings.VSyncEnd + var->upper_margin;
-	timings.sync = var->sync;
-
-
-	par->depth  = var->bits_per_pixel;
-	par->vwidth = var->xres_virtual;
-
-	if (var->bits_per_pixel == 16  &&  par->chip == S3_SAVAGE3D) {
-		timings.HDisplay *= 2;
-		timings.HSyncStart *= 2;
-		timings.HSyncEnd *= 2;
-		timings.HTotal *= 2;
-	}
-
-	/*
-	 * This will allocate the datastructure and initialize all of the
-	 * generic VGA registers.
-	 */
-	vgaHWInit (var, par, &timings);
-
-	/* We need to set CR67 whether or not we use the BIOS. */
-
-	dclk = timings.Clock;
-	par->CR67 = 0x00;
-
-	switch( var->bits_per_pixel ) {
-	case 8:
-		if( (par->chip == S3_SAVAGE2000) && (dclk >= 230000) )
-			par->CR67 = 0x10;	/* 8bpp, 2 pixels/clock */
-		else
-			par->CR67 = 0x00;	/* 8bpp, 1 pixel/clock */
-		break;
-	case 15:
-		if ( S3_SAVAGE_MOBILE_SERIES(par->chip) ||
-		     ((par->chip == S3_SAVAGE2000) && (dclk >= 230000)) )
-			par->CR67 = 0x30;	/* 15bpp, 2 pixel/clock */
-		else
-			par->CR67 = 0x20;	/* 15bpp, 1 pixels/clock */
-		break;
-	case 16:
-		if( S3_SAVAGE_MOBILE_SERIES(par->chip) ||
-		    ((par->chip == S3_SAVAGE2000) && (dclk >= 230000)) )
-			par->CR67 = 0x50;	/* 16bpp, 2 pixel/clock */
-		else
-			par->CR67 = 0x40;	/* 16bpp, 1 pixels/clock */
-		break;
-	case 24:
-		par->CR67 = 0x70;
-		break;
-	case 32:
-		par->CR67 = 0xd0;
-		break;
-	}
-
-	/*
-	 * Either BIOS use is disabled, or we failed to find a suitable
-	 * match.  Fall back to traditional register-crunching.
-	 */
-
-	vga_out8 (0x3d4, 0x3a);
-	tmp = vga_in8 (0x3d5);
-	if (1 /*FIXME:psav->pci_burst*/)
-		par->CR3A = (tmp & 0x7f) | 0x15;
-	else
-		par->CR3A = tmp | 0x95;
-
-	par->CR53 = 0x00;
-	par->CR31 = 0x8c;
-	par->CR66 = 0x89;
-
-	vga_out8 (0x3d4, 0x58);
-	par->CR58 = vga_in8 (0x3d5) & 0x80;
-	par->CR58 |= 0x13;
-
-	par->SR15 = 0x03 | 0x80;
-	par->SR18 = 0x00;
-	par->CR43 = par->CR45 = par->CR65 = 0x00;
-
-	vga_out8 (0x3d4, 0x40);
-	par->CR40 = vga_in8 (0x3d5) & ~0x01;
-
-	par->MMPR0 = 0x010400;
-	par->MMPR1 = 0x00;
-	par->MMPR2 = 0x0808;
-	par->MMPR3 = 0x08080810;
-
-	SavageCalcClock (dclk, 1, 1, 127, 0, 4, 180000, 360000, &m, &n, &r);
-	/* m = 107; n = 4; r = 2; */
-
-	if (par->MCLK <= 0) {
-		par->SR10 = 255;
-		par->SR11 = 255;
-	} else {
-		common_calc_clock (par->MCLK, 1, 1, 31, 0, 3, 135000, 270000,
-				   &par->SR11, &par->SR10);
-		/*      par->SR10 = 80; // MCLK == 286000 */
-		/*      par->SR11 = 125; */
-	}
-
-	par->SR12 = (r << 6) | (n & 0x3f);
-	par->SR13 = m & 0xff;
-	par->SR29 = (r & 4) | (m & 0x100) >> 5 | (n & 0x40) >> 2;
-
-	if (var->bits_per_pixel < 24)
-		par->MMPR0 -= 0x8000;
-	else
-		par->MMPR0 -= 0x4000;
-
-	if (timings.interlaced)
-		par->CR42 = 0x20;
-	else
-		par->CR42 = 0x00;
-
-	par->CR34 = 0x10; /* display fifo */
-
-	i = ((((timings.HTotal >> 3) - 5) & 0x100) >> 8) |
-		((((timings.HDisplay >> 3) - 1) & 0x100) >> 7) |
-		((((timings.HSyncStart >> 3) - 1) & 0x100) >> 6) |
-		((timings.HSyncStart & 0x800) >> 7);
-
-	if ((timings.HSyncEnd >> 3) - (timings.HSyncStart >> 3) > 64)
-		i |= 0x08;
-	if ((timings.HSyncEnd >> 3) - (timings.HSyncStart >> 3) > 32)
-		i |= 0x20;
-
-	j = (par->CRTC[0] + ((i & 0x01) << 8) +
-	     par->CRTC[4] + ((i & 0x10) << 4) + 1) / 2;
-
-	if (j - (par->CRTC[4] + ((i & 0x10) << 4)) < 4) {
-		if (par->CRTC[4] + ((i & 0x10) << 4) + 4 <=
-		    par->CRTC[0] + ((i & 0x01) << 8))
-			j = par->CRTC[4] + ((i & 0x10) << 4) + 4;
-		else
-			j = par->CRTC[0] + ((i & 0x01) << 8) + 1;
-	}
-
-	par->CR3B = j & 0xff;
-	i |= (j & 0x100) >> 2;
-	par->CR3C = (par->CRTC[0] + ((i & 0x01) << 8)) / 2;
-	par->CR5D = i;
-	par->CR5E = (((timings.VTotal - 2) & 0x400) >> 10) |
-		(((timings.VDisplay - 1) & 0x400) >> 9) |
-		(((timings.VSyncStart) & 0x400) >> 8) |
-		(((timings.VSyncStart) & 0x400) >> 6) | 0x40;
-	width = (var->xres_virtual * ((var->bits_per_pixel+7) / 8)) >> 3;
-	par->CR91 = par->CRTC[19] = 0xff & width;
-	par->CR51 = (0x300 & width) >> 4;
-	par->CR90 = 0x80 | (width >> 8);
-	par->MiscOutReg |= 0x0c;
-
-	/* Set frame buffer description. */
-
-	if (var->bits_per_pixel <= 8)
-		par->CR50 = 0;
-	else if (var->bits_per_pixel <= 16)
-		par->CR50 = 0x10;
-	else
-		par->CR50 = 0x30;
-
-	if (var->xres_virtual <= 640)
-		par->CR50 |= 0x40;
-	else if (var->xres_virtual == 800)
-		par->CR50 |= 0x80;
-	else if (var->xres_virtual == 1024)
-		par->CR50 |= 0x00;
-	else if (var->xres_virtual == 1152)
-		par->CR50 |= 0x01;
-	else if (var->xres_virtual == 1280)
-		par->CR50 |= 0xc0;
-	else if (var->xres_virtual == 1600)
-		par->CR50 |= 0x81;
-	else
-		par->CR50 |= 0xc1;	/* Use GBD */
-
-	if( par->chip == S3_SAVAGE2000 )
-		par->CR33 = 0x08;
-	else
-		par->CR33 = 0x20;
-
-	par->CRTC[0x17] = 0xeb;
-
-	par->CR67 |= 1;
-
-	vga_out8(0x3d4, 0x36);
-	par->CR36 = vga_in8 (0x3d5);
-	vga_out8 (0x3d4, 0x68);
-	par->CR68 = vga_in8 (0x3d5);
-	par->CR69 = 0;
-	vga_out8 (0x3d4, 0x6f);
-	par->CR6F = vga_in8 (0x3d5);
-	vga_out8 (0x3d4, 0x86);
-	par->CR86 = vga_in8 (0x3d5);
-	vga_out8 (0x3d4, 0x88);
-	par->CR88 = vga_in8 (0x3d5) | 0x08;
-	vga_out8 (0x3d4, 0xb0);
-	par->CRB0 = vga_in8 (0x3d5) | 0x80;
-
-	return 0;
-}
-
-/* --------------------------------------------------------------------- */
-
-/*
- *    Set a single color register. Return != 0 for invalid regno.
- */
-static int savagefb_setcolreg(unsigned        regno,
-			      unsigned        red,
-			      unsigned        green,
-			      unsigned        blue,
-			      unsigned        transp,
-			      struct fb_info *info)
-{
-	struct savagefb_par *par = (struct savagefb_par *)info->par;
-
-	if (regno >= NR_PALETTE)
-		return -EINVAL;
-
-	par->palette[regno].red    = red;
-	par->palette[regno].green  = green;
-	par->palette[regno].blue   = blue;
-	par->palette[regno].transp = transp;
-
-	switch (info->var.bits_per_pixel) {
-	case 8:
-		vga_out8 (0x3c8, regno);
-
-		vga_out8 (0x3c9, red   >> 10);
-		vga_out8 (0x3c9, green >> 10);
-		vga_out8 (0x3c9, blue  >> 10);
-		break;
-
-	case 16:
-		if (regno < 16)
-			((u32 *)info->pseudo_palette)[regno] =
-				((red   & 0xf800)      ) |
-				((green & 0xfc00) >>  5) |
-				((blue  & 0xf800) >> 11);
-		break;
-
-	case 24:
-		if (regno < 16)
-			((u32 *)info->pseudo_palette)[regno] =
-				((red    & 0xff00) <<  8) |
-				((green  & 0xff00)      ) |
-				((blue   & 0xff00) >>  8);
-		break;
-	case 32:
-		if (regno < 16)
-			((u32 *)info->pseudo_palette)[regno] =
-				((transp & 0xff00) << 16) |
-				((red    & 0xff00) <<  8) |
-				((green  & 0xff00)      ) |
-				((blue   & 0xff00) >>  8);
-		break;
-
-	default:
-		return 1;
-	}
-
-	return 0;
-}
-
-static void savagefb_set_par_int (struct savagefb_par  *par)
-{
-	unsigned char tmp, cr3a, cr66, cr67;
-
-	DBG ("savagefb_set_par_int");
-
-	par->SavageWaitIdle (par);
-
-	vga_out8 (0x3c2, 0x23);
-
-	vga_out16 (0x3d4, 0x4838);
-	vga_out16 (0x3d4, 0xa539);
-	vga_out16 (0x3c4, 0x0608);
-
-	vgaHWProtect (par, 1);
-
-	/*
-	 * Some Savage/MX and /IX systems go nuts when trying to exit the
-	 * server after WindowMaker has displayed a gradient background.  I
-	 * haven't been able to find what causes it, but a non-destructive
-	 * switch to mode 3 here seems to eliminate the issue.
-	 */
-
-	VerticalRetraceWait();
-	vga_out8 (0x3d4, 0x67);
-	cr67 = vga_in8 (0x3d5);
-	vga_out8 (0x3d5, cr67/*par->CR67*/ & ~0x0c); /* no STREAMS yet */
-
-	vga_out8 (0x3d4, 0x23);
-	vga_out8 (0x3d5, 0x00);
-	vga_out8 (0x3d4, 0x26);
-	vga_out8 (0x3d5, 0x00);
-
-	/* restore extended regs */
-	vga_out8 (0x3d4, 0x66);
-	vga_out8 (0x3d5, par->CR66);
-	vga_out8 (0x3d4, 0x3a);
-	vga_out8 (0x3d5, par->CR3A);
-	vga_out8 (0x3d4, 0x31);
-	vga_out8 (0x3d5, par->CR31);
-	vga_out8 (0x3d4, 0x32);
-	vga_out8 (0x3d5, par->CR32);
-	vga_out8 (0x3d4, 0x58);
-	vga_out8 (0x3d5, par->CR58);
-	vga_out8 (0x3d4, 0x53);
-	vga_out8 (0x3d5, par->CR53 & 0x7f);
-
-	vga_out16 (0x3c4, 0x0608);
-
-	/* Restore DCLK registers. */
-
-	vga_out8 (0x3c4, 0x0e);
-	vga_out8 (0x3c5, par->SR0E);
-	vga_out8 (0x3c4, 0x0f);
-	vga_out8 (0x3c5, par->SR0F);
-	vga_out8 (0x3c4, 0x29);
-	vga_out8 (0x3c5, par->SR29);
-	vga_out8 (0x3c4, 0x15);
-	vga_out8 (0x3c5, par->SR15);
-
-	/* Restore flat panel expansion regsters. */
-	if( par->chip == S3_SAVAGE_MX ) {
-		int i;
-
-		for( i = 0; i < 8; i++ ) {
-			vga_out8 (0x3c4, 0x54+i);
-			vga_out8 (0x3c5, par->SR54[i]);
-		}
-	}
-
-	vgaHWRestore (par);
-
-	/* extended mode timing registers */
-	vga_out8 (0x3d4, 0x53);
-	vga_out8 (0x3d5, par->CR53);
-	vga_out8 (0x3d4, 0x5d);
-	vga_out8 (0x3d5, par->CR5D);
-	vga_out8 (0x3d4, 0x5e);
-	vga_out8 (0x3d5, par->CR5E);
-	vga_out8 (0x3d4, 0x3b);
-	vga_out8 (0x3d5, par->CR3B);
-	vga_out8 (0x3d4, 0x3c);
-	vga_out8 (0x3d5, par->CR3C);
-	vga_out8 (0x3d4, 0x43);
-	vga_out8 (0x3d5, par->CR43);
-	vga_out8 (0x3d4, 0x65);
-	vga_out8 (0x3d5, par->CR65);
-
-	/* restore the desired video mode with cr67 */
-	vga_out8 (0x3d4, 0x67);
-	/* following part not present in X11 driver */
-	cr67 = vga_in8 (0x3d5) & 0xf;
-	vga_out8 (0x3d5, 0x50 | cr67);
-	udelay (10000);
-	vga_out8 (0x3d4, 0x67);
-	/* end of part */
-	vga_out8 (0x3d5, par->CR67 & ~0x0c);
-
-	/* other mode timing and extended regs */
-	vga_out8 (0x3d4, 0x34);
-	vga_out8 (0x3d5, par->CR34);
-	vga_out8 (0x3d4, 0x40);
-	vga_out8 (0x3d5, par->CR40);
-	vga_out8 (0x3d4, 0x42);
-	vga_out8 (0x3d5, par->CR42);
-	vga_out8 (0x3d4, 0x45);
-	vga_out8 (0x3d5, par->CR45);
-	vga_out8 (0x3d4, 0x50);
-	vga_out8 (0x3d5, par->CR50);
-	vga_out8 (0x3d4, 0x51);
-	vga_out8 (0x3d5, par->CR51);
-
-	/* memory timings */
-	vga_out8 (0x3d4, 0x36);
-	vga_out8 (0x3d5, par->CR36);
-	vga_out8 (0x3d4, 0x60);
-	vga_out8 (0x3d5, par->CR60);
-	vga_out8 (0x3d4, 0x68);
-	vga_out8 (0x3d5, par->CR68);
-	vga_out8 (0x3d4, 0x69);
-	vga_out8 (0x3d5, par->CR69);
-	vga_out8 (0x3d4, 0x6f);
-	vga_out8 (0x3d5, par->CR6F);
-
-	vga_out8 (0x3d4, 0x33);
-	vga_out8 (0x3d5, par->CR33);
-	vga_out8 (0x3d4, 0x86);
-	vga_out8 (0x3d5, par->CR86);
-	vga_out8 (0x3d4, 0x88);
-	vga_out8 (0x3d5, par->CR88);
-	vga_out8 (0x3d4, 0x90);
-	vga_out8 (0x3d5, par->CR90);
-	vga_out8 (0x3d4, 0x91);
-	vga_out8 (0x3d5, par->CR91);
-
-	if (par->chip == S3_SAVAGE4) {
-		vga_out8 (0x3d4, 0xb0);
-		vga_out8 (0x3d5, par->CRB0);
-	}
-
-	vga_out8 (0x3d4, 0x32);
-	vga_out8 (0x3d5, par->CR32);
-
-	/* unlock extended seq regs */
-	vga_out8 (0x3c4, 0x08);
-	vga_out8 (0x3c5, 0x06);
-
-	/* Restore extended sequencer regs for MCLK. SR10 == 255 indicates
-	 * that we should leave the default SR10 and SR11 values there.
-	 */
-	if (par->SR10 != 255) {
-		vga_out8 (0x3c4, 0x10);
-		vga_out8 (0x3c5, par->SR10);
-		vga_out8 (0x3c4, 0x11);
-		vga_out8 (0x3c5, par->SR11);
-	}
-
-	/* restore extended seq regs for dclk */
-	vga_out8 (0x3c4, 0x0e);
-	vga_out8 (0x3c5, par->SR0E);
-	vga_out8 (0x3c4, 0x0f);
-	vga_out8 (0x3c5, par->SR0F);
-	vga_out8 (0x3c4, 0x12);
-	vga_out8 (0x3c5, par->SR12);
-	vga_out8 (0x3c4, 0x13);
-	vga_out8 (0x3c5, par->SR13);
-	vga_out8 (0x3c4, 0x29);
-	vga_out8 (0x3c5, par->SR29);
-
-	vga_out8 (0x3c4, 0x18);
-	vga_out8 (0x3c5, par->SR18);
-
-	/* load new m, n pll values for dclk & mclk */
-	vga_out8 (0x3c4, 0x15);
-	tmp = vga_in8 (0x3c5) & ~0x21;
-
-	vga_out8 (0x3c5, tmp | 0x03);
-	vga_out8 (0x3c5, tmp | 0x23);
-	vga_out8 (0x3c5, tmp | 0x03);
-	vga_out8 (0x3c5, par->SR15);
-	udelay (100);
-
-	vga_out8 (0x3c4, 0x30);
-	vga_out8 (0x3c5, par->SR30);
-	vga_out8 (0x3c4, 0x08);
-	vga_out8 (0x3c5, par->SR08);
-
-	/* now write out cr67 in full, possibly starting STREAMS */
-	VerticalRetraceWait();
-	vga_out8 (0x3d4, 0x67);
-	vga_out8 (0x3d5, par->CR67);
-
-	vga_out8 (0x3d4, 0x66);
-	cr66 = vga_in8 (0x3d5);
-	vga_out8 (0x3d5, cr66 | 0x80);
-	vga_out8 (0x3d4, 0x3a);
-	cr3a = vga_in8 (0x3d5);
-	vga_out8 (0x3d5, cr3a | 0x80);
-
-	if (par->chip != S3_SAVAGE_MX) {
-		VerticalRetraceWait();
-		savage_out32 (FIFO_CONTROL_REG, par->MMPR0);
-		par->SavageWaitIdle (par);
-		savage_out32 (MIU_CONTROL_REG, par->MMPR1);
-		par->SavageWaitIdle (par);
-		savage_out32 (STREAMS_TIMEOUT_REG, par->MMPR2);
-		par->SavageWaitIdle (par);
-		savage_out32 (MISC_TIMEOUT_REG, par->MMPR3);
-	}
-
-	vga_out8 (0x3d4, 0x66);
-	vga_out8 (0x3d5, cr66);
-	vga_out8 (0x3d4, 0x3a);
-	vga_out8 (0x3d5, cr3a);
-
-	SavageSetup2DEngine (par);
-	vgaHWProtect (par, 0);
-}
-
-static void savagefb_update_start (struct savagefb_par      *par,
-				   struct fb_var_screeninfo *var)
-{
-	int base;
-
-	base = ((var->yoffset * var->xres_virtual + (var->xoffset & ~1))
-		* ((var->bits_per_pixel+7) / 8)) >> 2;
-
-	/* now program the start address registers */
-	vga_out16(0x3d4, (base & 0x00ff00) | 0x0c);
-	vga_out16(0x3d4, ((base & 0x00ff) << 8) | 0x0d);
-	vga_out8 (0x3d4, 0x69);
-	vga_out8 (0x3d5, (base & 0x7f0000) >> 16);
-}
-
-
-static void savagefb_set_fix(struct fb_info *info)
-{
-	info->fix.line_length = info->var.xres_virtual *
-		info->var.bits_per_pixel / 8;
-
-	if (info->var.bits_per_pixel == 8)
-		info->fix.visual      = FB_VISUAL_PSEUDOCOLOR;
-	else
-		info->fix.visual      = FB_VISUAL_TRUECOLOR;
-}
-
-#if defined(CONFIG_FB_SAVAGE_ACCEL)
-static void savagefb_set_clip(struct fb_info *info)
-{
-    struct savagefb_par *par = (struct savagefb_par *)info->par;
-    int cmd;
-
-    cmd = BCI_CMD_NOP | BCI_CMD_CLIP_NEW;
-    par->bci_ptr = 0;
-    par->SavageWaitFifo(par,3);
-    BCI_SEND(cmd);
-    BCI_SEND(BCI_CLIP_TL(0, 0));
-    BCI_SEND(BCI_CLIP_BR(0xfff, 0xfff));
-}
-#endif
-
-static int savagefb_set_par (struct fb_info *info)
-{
-	struct savagefb_par *par = (struct savagefb_par *)info->par;
-	struct fb_var_screeninfo *var = &info->var;
-	int err;
-
-	DBG("savagefb_set_par");
-	err = savagefb_decode_var (var, par);
-	if (err)
-		return err;
-
-	if (par->dacSpeedBpp <= 0) {
-		if (var->bits_per_pixel > 24)
-			par->dacSpeedBpp = par->clock[3];
-		else if (var->bits_per_pixel >= 24)
-			par->dacSpeedBpp = par->clock[2];
-		else if ((var->bits_per_pixel > 8) && (var->bits_per_pixel < 24))
-			par->dacSpeedBpp = par->clock[1];
-		else if (var->bits_per_pixel <= 8)
-			par->dacSpeedBpp = par->clock[0];
-	}
-
-	/* Set ramdac limits */
-	par->maxClock = par->dacSpeedBpp;
-	par->minClock = 10000;
-
-	savagefb_set_par_int (par);
-	savagefb_update_start (par, var);
-	fb_set_cmap (&info->cmap, info);
-	savagefb_set_fix(info);
-	savagefb_set_clip(info);
-
-	SavagePrintRegs();
-	return 0;
-}
-
-/*
- *    Pan or Wrap the Display
- */
-static int savagefb_pan_display (struct fb_var_screeninfo *var,
-				 struct fb_info           *info)
-{
-	struct savagefb_par *par = (struct savagefb_par *)info->par;
-	u_int y_bottom;
-
-	y_bottom = var->yoffset;
-
-	if (!(var->vmode & FB_VMODE_YWRAP))
-		y_bottom += var->yres;
-
-	if (var->xoffset > (var->xres_virtual - var->xres))
-		return -EINVAL;
-	if (y_bottom > info->var.yres_virtual)
-		return -EINVAL;
-
-	savagefb_update_start (par, var);
-
-	info->var.xoffset = var->xoffset;
-	info->var.yoffset = var->yoffset;
-
-	if (var->vmode & FB_VMODE_YWRAP)
-		info->var.vmode |= FB_VMODE_YWRAP;
-	else
-		info->var.vmode &= ~FB_VMODE_YWRAP;
-
-	return 0;
-}
-
-
-static struct fb_ops savagefb_ops = {
-	.owner          = THIS_MODULE,
-	.fb_check_var   = savagefb_check_var,
-	.fb_set_par     = savagefb_set_par,
-	.fb_setcolreg   = savagefb_setcolreg,
-	.fb_pan_display = savagefb_pan_display,
-#if defined(CONFIG_FB_SAVAGE_ACCEL)
-	.fb_fillrect    = savagefb_fillrect,
-	.fb_copyarea    = savagefb_copyarea,
-	.fb_imageblit   = savagefb_imageblit,
-	.fb_sync        = savagefb_sync,
-#else
-	.fb_fillrect    = cfb_fillrect,
-	.fb_copyarea    = cfb_copyarea,
-	.fb_imageblit   = cfb_imageblit,
-#endif
-	.fb_cursor      = soft_cursor,
-};
-
-/* --------------------------------------------------------------------- */
-
-static struct fb_var_screeninfo __devinitdata savagefb_var800x600x8 = {
-	.accel_flags =	FB_ACCELF_TEXT,
-	.xres =		800,
-	.yres =		600,
-	.xres_virtual =  800,
-	.yres_virtual =  600,
-	.bits_per_pixel = 8,
-	.pixclock =	25000,
-	.left_margin =	88,
-	.right_margin =	40,
-	.upper_margin =	23,
-	.lower_margin =	1,
-	.hsync_len =	128,
-	.vsync_len =	4,
-	.sync =		FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-	.vmode =	FB_VMODE_NONINTERLACED
-};
-
-static void savage_enable_mmio (struct savagefb_par *par)
-{
-	unsigned char val;
-
-	DBG ("savage_enable_mmio\n");
-
-	val = vga_in8 (0x3c3);
-	vga_out8 (0x3c3, val | 0x01);
-	val = vga_in8 (0x3cc);
-	vga_out8 (0x3c2, val | 0x01);
-
-	if (par->chip >= S3_SAVAGE4) {
-		vga_out8 (0x3d4, 0x40);
-		val = vga_in8 (0x3d5);
-		vga_out8 (0x3d5, val | 1);
-	}
-}
-
-
-void savage_disable_mmio (struct savagefb_par *par)
-{
-	unsigned char val;
-
-	DBG ("savage_disable_mmio\n");
-
-	if(par->chip >= S3_SAVAGE4 ) {
-		vga_out8 (0x3d4, 0x40);
-		val = vga_in8 (0x3d5);
-		vga_out8 (0x3d5, val | 1);
-	}
-}
-
-
-static int __devinit savage_map_mmio (struct fb_info *info)
-{
-	struct savagefb_par *par = (struct savagefb_par *)info->par;
-	DBG ("savage_map_mmio");
-
-	if (S3_SAVAGE3D_SERIES (par->chip))
-		par->mmio.pbase = pci_resource_start (par->pcidev, 0) +
-			SAVAGE_NEWMMIO_REGBASE_S3;
-	else
-		par->mmio.pbase = pci_resource_start (par->pcidev, 0) +
-			SAVAGE_NEWMMIO_REGBASE_S4;
-
-	par->mmio.len = SAVAGE_NEWMMIO_REGSIZE;
-
-	par->mmio.vbase = ioremap (par->mmio.pbase, par->mmio.len);
-	if (!par->mmio.vbase) {
-		printk ("savagefb: unable to map memory mapped IO\n");
-		return -ENOMEM;
-	} else
-		printk (KERN_INFO "savagefb: mapped io at %p\n",
-			par->mmio.vbase);
-
-	info->fix.mmio_start = par->mmio.pbase;
-	info->fix.mmio_len   = par->mmio.len;
-
-	par->bci_base = (u32 __iomem *)(par->mmio.vbase + BCI_BUFFER_OFFSET);
-	par->bci_ptr  = 0;
-
-	savage_enable_mmio (par);
-
-	return 0;
-}
-
-static void __devinit savage_unmap_mmio (struct fb_info *info)
-{
-	struct savagefb_par *par = (struct savagefb_par *)info->par;
-	DBG ("savage_unmap_mmio");
-
-	savage_disable_mmio(par);
-
-	if (par->mmio.vbase) {
-		iounmap ((void __iomem *)par->mmio.vbase);
-		par->mmio.vbase = NULL;
-	}
-}
-
-static int __devinit savage_map_video (struct fb_info *info,
-				       int video_len)
-{
-	struct savagefb_par *par = (struct savagefb_par *)info->par;
-	int resource;
-
-	DBG("savage_map_video");
-
-	if (S3_SAVAGE3D_SERIES (par->chip))
-		resource = 0;
-	else
-		resource = 1;
-
-	par->video.pbase = pci_resource_start (par->pcidev, resource);
-	par->video.len   = video_len;
-	par->video.vbase = ioremap (par->video.pbase, par->video.len);
-
-	if (!par->video.vbase) {
-		printk ("savagefb: unable to map screen memory\n");
-		return -ENOMEM;
-	} else
-		printk (KERN_INFO "savagefb: mapped framebuffer at %p, "
-			"pbase == %x\n", par->video.vbase, par->video.pbase);
-
-	info->fix.smem_start = par->video.pbase;
-	info->fix.smem_len   = par->video.len - par->cob_size;
-	info->screen_base    = par->video.vbase;
-
-#ifdef CONFIG_MTRR
-	par->video.mtrr = mtrr_add (par->video.pbase, video_len,
-				     MTRR_TYPE_WRCOMB, 1);
-#endif
-	return 0;
-}
-
-static void __devinit savage_unmap_video (struct fb_info *info)
-{
-	struct savagefb_par *par = (struct savagefb_par *)info->par;
-
-	DBG("savage_unmap_video");
-
-	if (par->video.vbase) {
-#ifdef CONFIG_MTRR
-		mtrr_del (par->video.mtrr, par->video.pbase, par->video.len);
-#endif
-
-		iounmap (par->video.vbase);
-		par->video.vbase = NULL;
-		info->screen_base = NULL;
-	}
-}
-
-static int __devinit savage_init_hw (struct savagefb_par *par)
-{
-	unsigned char config1, m, n, n1, n2, sr8, cr3f, cr66 = 0, tmp;
-
-	static unsigned char RamSavage3D[] = { 8, 4, 4, 2 };
-	static unsigned char RamSavage4[] =  { 2, 4, 8, 12, 16, 32, 64, 32 };
-	static unsigned char RamSavageMX[] = { 2, 8, 4, 16, 8, 16, 4, 16 };
-	static unsigned char RamSavageNB[] = { 0, 2, 4, 8, 16, 32, 2, 2 };
-
-	int videoRam, videoRambytes;
-
-	DBG("savage_init_hw");
-
-	/* unprotect CRTC[0-7] */
-	vga_out8(0x3d4, 0x11);
-	tmp = vga_in8(0x3d5);
-	vga_out8(0x3d5, tmp & 0x7f);
-
-	/* unlock extended regs */
-	vga_out16(0x3d4, 0x4838);
-	vga_out16(0x3d4, 0xa039);
-	vga_out16(0x3c4, 0x0608);
-
-	vga_out8(0x3d4, 0x40);
-	tmp = vga_in8(0x3d5);
-	vga_out8(0x3d5, tmp & ~0x01);
-
-	/* unlock sys regs */
-	vga_out8(0x3d4, 0x38);
-	vga_out8(0x3d5, 0x48);
-
-	/* Unlock system registers. */
-	vga_out16(0x3d4, 0x4838);
-
-	/* Next go on to detect amount of installed ram */
-
-	vga_out8(0x3d4, 0x36);            /* for register CR36 (CONFG_REG1), */
-	config1 = vga_in8(0x3d5);           /* get amount of vram installed */
-
-	/* Compute the amount of video memory and offscreen memory. */
-
-	switch  (par->chip) {
-	case S3_SAVAGE3D:
-		videoRam = RamSavage3D[ (config1 & 0xC0) >> 6 ] * 1024;
-		break;
-
-	case S3_SAVAGE4:
-		/*
-		 * The Savage4 has one ugly special case to consider.  On
-		 * systems with 4 banks of 2Mx32 SDRAM, the BIOS says 4MB
-		 * when it really means 8MB.  Why do it the same when you
-		 * can do it different...
-		 */
-		vga_out8(0x3d4, 0x68);	/* memory control 1 */
-		if( (vga_in8(0x3d5) & 0xC0) == (0x01 << 6) )
-			RamSavage4[1] = 8;
-
-		/*FALLTHROUGH*/
-
-	case S3_SAVAGE2000:
-		videoRam = RamSavage4[ (config1 & 0xE0) >> 5 ] * 1024;
-		break;
-
-	case S3_SAVAGE_MX:
-	case S3_SUPERSAVAGE:
-		videoRam = RamSavageMX[ (config1 & 0x0E) >> 1 ] * 1024;
-		break;
-
-	case S3_PROSAVAGE:
-		videoRam = RamSavageNB[ (config1 & 0xE0) >> 5 ] * 1024;
-		break;
-
-	default:
-		/* How did we get here? */
-		videoRam = 0;
-		break;
-	}
-
-	videoRambytes = videoRam * 1024;
-
-	printk (KERN_INFO "savagefb: probed videoram:  %dk\n", videoRam);
-
-	/* reset graphics engine to avoid memory corruption */
-	vga_out8 (0x3d4, 0x66);
-	cr66 = vga_in8 (0x3d5);
-	vga_out8 (0x3d5, cr66 | 0x02);
-	udelay (10000);
-
-	vga_out8 (0x3d4, 0x66);
-	vga_out8 (0x3d5, cr66 & ~0x02);	/* clear reset flag */
-	udelay (10000);
-
-
-	/*
-	 * reset memory interface, 3D engine, AGP master, PCI master,
-	 * master engine unit, motion compensation/LPB
-	 */
-	vga_out8 (0x3d4, 0x3f);
-	cr3f = vga_in8 (0x3d5);
-	vga_out8 (0x3d5, cr3f | 0x08);
-	udelay (10000);
-
-	vga_out8 (0x3d4, 0x3f);
-	vga_out8 (0x3d5, cr3f & ~0x08);	/* clear reset flags */
-	udelay (10000);
-
-	/* Savage ramdac speeds */
-	par->numClocks = 4;
-	par->clock[0] = 250000;
-	par->clock[1] = 250000;
-	par->clock[2] = 220000;
-	par->clock[3] = 220000;
-
-	/* detect current mclk */
-	vga_out8(0x3c4, 0x08);
-	sr8 = vga_in8(0x3c5);
-	vga_out8(0x3c5, 0x06);
-	vga_out8(0x3c4, 0x10);
-	n = vga_in8(0x3c5);
-	vga_out8(0x3c4, 0x11);
-	m = vga_in8(0x3c5);
-	vga_out8(0x3c4, 0x08);
-	vga_out8(0x3c5, sr8);
-	m &= 0x7f;
-	n1 = n & 0x1f;
-	n2 = (n >> 5) & 0x03;
-	par->MCLK = ((1431818 * (m+2)) / (n1+2) / (1 << n2) + 50) / 100;
-	printk (KERN_INFO "savagefb: Detected current MCLK value of %d kHz\n",
-		par->MCLK);
-
-	/* Check LCD panel parrmation */
-
-	if (par->chip == S3_SAVAGE_MX) {
-		unsigned char cr6b = VGArCR( 0x6b );
-
-		int panelX = (VGArSEQ (0x61) +
-			      ((VGArSEQ (0x66) & 0x02) << 7) + 1) * 8;
-		int panelY = (VGArSEQ (0x69) +
-			      ((VGArSEQ (0x6e) & 0x70) << 4) + 1);
-
-		char * sTechnology = "Unknown";
-
-		/* OK, I admit it.  I don't know how to limit the max dot clock
-		 * for LCD panels of various sizes.  I thought I copied the
-		 * formula from the BIOS, but many users have parrmed me of
-		 * my folly.
-		 *
-		 * Instead, I'll abandon any attempt to automatically limit the
-		 * clock, and add an LCDClock option to XF86Config.  Some day,
-		 * I should come back to this.
-		 */
-
-		enum ACTIVE_DISPLAYS { /* These are the bits in CR6B */
-			ActiveCRT = 0x01,
-			ActiveLCD = 0x02,
-			ActiveTV = 0x04,
-			ActiveCRT2 = 0x20,
-			ActiveDUO = 0x80
-		};
-
-		if ((VGArSEQ (0x39) & 0x03) == 0) {
-			sTechnology = "TFT";
-		} else if ((VGArSEQ (0x30) & 0x01) == 0) {
-			sTechnology = "DSTN";
-		} else 	{
-			sTechnology = "STN";
-		}
-
-		printk (KERN_INFO "savagefb: %dx%d %s LCD panel detected %s\n",
-			panelX, panelY, sTechnology,
-			cr6b & ActiveLCD ? "and active" : "but not active");
-
-		if( cr6b & ActiveLCD ) 	{
-			/*
-			 * If the LCD is active and panel expansion is enabled,
-			 * we probably want to kill the HW cursor.
-			 */
-
-			printk (KERN_INFO "savagefb: Limiting video mode to "
-				"%dx%d\n", panelX, panelY );
-
-			par->SavagePanelWidth = panelX;
-			par->SavagePanelHeight = panelY;
-
-		}
-	}
-
-	savage_get_default_par (par);
-
-	if( S3_SAVAGE4_SERIES(par->chip) ) {
-		/*
-		 * The Savage4 and ProSavage have COB coherency bugs which
-		 * render the buffer useless.  We disable it.
-		 */
-		par->cob_index = 2;
-		par->cob_size = 0x8000 << par->cob_index;
-		par->cob_offset = videoRambytes;
-	} else {
-		/* We use 128kB for the COB on all chips. */
-
-		par->cob_index  = 7;
-		par->cob_size   = 0x400 << par->cob_index;
-		par->cob_offset = videoRambytes - par->cob_size;
-	}
-
-	return videoRambytes;
-}
-
-static int __devinit savage_init_fb_info (struct fb_info *info,
-					  struct pci_dev *dev,
-					  const struct pci_device_id *id)
-{
-	struct savagefb_par *par = (struct savagefb_par *)info->par;
-	int err = 0;
-
-	par->pcidev  = dev;
-
-	info->fix.type	   = FB_TYPE_PACKED_PIXELS;
-	info->fix.type_aux	   = 0;
-	info->fix.xpanstep	   = 2;
-	info->fix.ypanstep	   = 1;
-	info->fix.ywrapstep   = 0;
-	info->fix.accel       = id->driver_data;
-
-	switch (info->fix.accel) {
-	case FB_ACCEL_SUPERSAVAGE:
-		par->chip = S3_SUPERSAVAGE;
-		snprintf (info->fix.id, 16, "SuperSavage");
-		break;
-	case FB_ACCEL_SAVAGE4:
-		par->chip = S3_SAVAGE4;
-		snprintf (info->fix.id, 16, "Savage4");
-		break;
-	case FB_ACCEL_SAVAGE3D:
-		par->chip = S3_SAVAGE3D;
-		snprintf (info->fix.id, 16, "Savage3D");
-		break;
-	case FB_ACCEL_SAVAGE3D_MV:
-		par->chip = S3_SAVAGE3D;
-		snprintf (info->fix.id, 16, "Savage3D-MV");
-		break;
-	case FB_ACCEL_SAVAGE2000:
-		par->chip = S3_SAVAGE2000;
-		snprintf (info->fix.id, 16, "Savage2000");
-		break;
-	case FB_ACCEL_SAVAGE_MX_MV:
-		par->chip = S3_SAVAGE_MX;
-		snprintf (info->fix.id, 16, "Savage/MX-MV");
-		break;
-	case FB_ACCEL_SAVAGE_MX:
-		par->chip = S3_SAVAGE_MX;
-		snprintf (info->fix.id, 16, "Savage/MX");
-		break;
-	case FB_ACCEL_SAVAGE_IX_MV:
-		par->chip = S3_SAVAGE_MX;
-		snprintf (info->fix.id, 16, "Savage/IX-MV");
-		break;
-	case FB_ACCEL_SAVAGE_IX:
-		par->chip = S3_SAVAGE_MX;
-		snprintf (info->fix.id, 16, "Savage/IX");
-		break;
-	case FB_ACCEL_PROSAVAGE_PM:
-		par->chip = S3_PROSAVAGE;
-		snprintf (info->fix.id, 16, "ProSavagePM");
-		break;
-	case FB_ACCEL_PROSAVAGE_KM:
-		par->chip = S3_PROSAVAGE;
-		snprintf (info->fix.id, 16, "ProSavageKM");
-		break;
-	case FB_ACCEL_S3TWISTER_P:
-		par->chip = S3_PROSAVAGE;
-		snprintf (info->fix.id, 16, "TwisterP");
-		break;
-	case FB_ACCEL_S3TWISTER_K:
-		par->chip = S3_PROSAVAGE;
-		snprintf (info->fix.id, 16, "TwisterK");
-		break;
-	case FB_ACCEL_PROSAVAGE_DDR:
-		par->chip = S3_PROSAVAGE;
-		snprintf (info->fix.id, 16, "ProSavageDDR");
-		break;
-	case FB_ACCEL_PROSAVAGE_DDRK:
-		par->chip = S3_PROSAVAGE;
-		snprintf (info->fix.id, 16, "ProSavage8");
-		break;
-	}
-
-	if (S3_SAVAGE3D_SERIES(par->chip)) {
-		par->SavageWaitIdle = savage3D_waitidle;
-		par->SavageWaitFifo = savage3D_waitfifo;
-	} else if (S3_SAVAGE4_SERIES(par->chip) ||
-		   S3_SUPERSAVAGE == par->chip) {
-		par->SavageWaitIdle = savage4_waitidle;
-		par->SavageWaitFifo = savage4_waitfifo;
-	} else {
-		par->SavageWaitIdle = savage2000_waitidle;
-		par->SavageWaitFifo = savage2000_waitfifo;
-	}
-
-	info->var.nonstd      = 0;
-	info->var.activate    = FB_ACTIVATE_NOW;
-	info->var.width       = -1;
-	info->var.height      = -1;
-	info->var.accel_flags = 0;
-
-	info->fbops          = &savagefb_ops;
-	info->flags          = FBINFO_DEFAULT |
-		               FBINFO_HWACCEL_YPAN |
-		               FBINFO_HWACCEL_XPAN |
-	                       FBINFO_MISC_MODESWITCHLATE;
-
-	info->pseudo_palette = par->pseudo_palette;
-
-#if defined(CONFIG_FB_SAVAGE_ACCEL)
-	/* FIFO size + padding for commands */
-	info->pixmap.addr = kmalloc(8*1024, GFP_KERNEL);
-
-	err = -ENOMEM;
-	if (info->pixmap.addr) {
-		memset(info->pixmap.addr, 0, 8*1024);
-		info->pixmap.size = 8*1024;
-		info->pixmap.scan_align = 4;
-		info->pixmap.buf_align = 4;
-		info->pixmap.access_align = 4;
-
-		fb_alloc_cmap (&info->cmap, NR_PALETTE, 0);
-		info->flags |= FBINFO_HWACCEL_COPYAREA |
-	                       FBINFO_HWACCEL_FILLRECT |
-		               FBINFO_HWACCEL_IMAGEBLIT;
-
-		err = 0;
-	}
-#endif
-	return err;
-}
-
-/* --------------------------------------------------------------------- */
-
-static int __devinit savagefb_probe (struct pci_dev* dev,
-				     const struct pci_device_id* id)
-{
-	struct fb_info *info;
-	struct savagefb_par *par;
-	u_int h_sync, v_sync;
-	int err, lpitch;
-	int video_len;
-
-	DBG("savagefb_probe");
-	SavagePrintRegs();
-
-	info = framebuffer_alloc(sizeof(struct savagefb_par), &dev->dev);
-	if (!info)
-		return -ENOMEM;
-	par = info->par;
-	err = pci_enable_device(dev);
-	if (err)
-		goto failed_enable;
-
-	if (pci_request_regions(dev, "savagefb")) {
-		printk(KERN_ERR "cannot request PCI regions\n");
-		goto failed_enable;
-	}
-
-	err = -ENOMEM;
-
-	if (savage_init_fb_info(info, dev, id))
-		goto failed_init;
-
-	err = savage_map_mmio(info);
-	if (err)
-		goto failed_mmio;
-
-	video_len = savage_init_hw(par);
-	if (video_len < 0) {
-		err = video_len;
-		goto failed_mmio;
-	}
-
-	err = savage_map_video(info, video_len);
-	if (err)
-		goto failed_video;
-
-	INIT_LIST_HEAD(&info->modelist);
-#if defined(CONFIG_FB_SAVAGE_I2C)
-	savagefb_create_i2c_busses(info);
-	savagefb_probe_i2c_connector(par, &par->edid);
-	fb_edid_to_monspecs(par->edid, &info->monspecs);
-	fb_videomode_to_modelist(info->monspecs.modedb,
-				 info->monspecs.modedb_len,
-				 &info->modelist);
-#endif
-	info->var = savagefb_var800x600x8;
-
-	if (mode_option) {
-		fb_find_mode(&info->var, info, mode_option,
-			     info->monspecs.modedb, info->monspecs.modedb_len,
-			     NULL, 8);
-	} else if (info->monspecs.modedb != NULL) {
-		struct fb_monspecs *specs = &info->monspecs;
-		struct fb_videomode modedb;
-
-		if (info->monspecs.misc & FB_MISC_1ST_DETAIL) {
-			int i;
-
-			for (i = 0; i < specs->modedb_len; i++) {
-				if (specs->modedb[i].flag & FB_MODE_IS_FIRST) {
-					modedb = specs->modedb[i];
-					break;
-				}
-			}
-		} else {
-			/* otherwise, get first mode in database */
-			modedb = specs->modedb[0];
-		}
-
-		savage_update_var(&info->var, &modedb);
-	}
-
-	/* maximize virtual vertical length */
-	lpitch = info->var.xres_virtual*((info->var.bits_per_pixel + 7) >> 3);
-	info->var.yres_virtual = info->fix.smem_len/lpitch;
-
-	if (info->var.yres_virtual < info->var.yres)
-		goto failed;
-
-#if defined(CONFIG_FB_SAVAGE_ACCEL)
-	/*
-	 * The clipping coordinates are masked with 0xFFF, so limit our
-	 * virtual resolutions to these sizes.
-	 */
-	if (info->var.yres_virtual > 0x1000)
-		info->var.yres_virtual = 0x1000;
-
-	if (info->var.xres_virtual > 0x1000)
-		info->var.xres_virtual = 0x1000;
-#endif
-	savagefb_check_var(&info->var, info);
-	savagefb_set_fix(info);
-
-	/*
-	 * Calculate the hsync and vsync frequencies.  Note that
-	 * we split the 1e12 constant up so that we can preserve
-	 * the precision and fit the results into 32-bit registers.
-	 *  (1953125000 * 512 = 1e12)
-	 */
-	h_sync = 1953125000 / info->var.pixclock;
-	h_sync = h_sync * 512 / (info->var.xres + info->var.left_margin +
-				 info->var.right_margin +
-				 info->var.hsync_len);
-	v_sync = h_sync / (info->var.yres + info->var.upper_margin +
-			   info->var.lower_margin + info->var.vsync_len);
-
-	printk(KERN_INFO "savagefb v" SAVAGEFB_VERSION ": "
-	       "%dkB VRAM, using %dx%d, %d.%03dkHz, %dHz\n",
-	       info->fix.smem_len >> 10,
-	       info->var.xres, info->var.yres,
-	       h_sync / 1000, h_sync % 1000, v_sync);
-
-
-	fb_destroy_modedb(info->monspecs.modedb);
-	info->monspecs.modedb = NULL;
-
-	err = register_framebuffer (info);
-	if (err < 0)
-		goto failed;
-
-	printk (KERN_INFO "fb: S3 %s frame buffer device\n",
-		info->fix.id);
-
-	/*
-	 * Our driver data
-	 */
-	pci_set_drvdata(dev, info);
-
-	return 0;
-
- failed:
-#ifdef CONFIG_FB_SAVAGE_I2C
-	savagefb_delete_i2c_busses(info);
-#endif
-	fb_alloc_cmap (&info->cmap, 0, 0);
-	savage_unmap_video(info);
- failed_video:
-	savage_unmap_mmio (info);
- failed_mmio:
-	kfree(info->pixmap.addr);
- failed_init:
-	pci_release_regions(dev);
- failed_enable:
-	framebuffer_release(info);
-
-	return err;
-}
-
-static void __devexit savagefb_remove (struct pci_dev *dev)
-{
-	struct fb_info *info =
-		(struct fb_info *)pci_get_drvdata(dev);
-
-	DBG("savagefb_remove");
-
-	if (info) {
-		/*
-		 * If unregister_framebuffer fails, then
-		 * we will be leaving hooks that could cause
-		 * oopsen laying around.
-		 */
-		if (unregister_framebuffer (info))
-			printk (KERN_WARNING "savagefb: danger danger! "
-				"Oopsen imminent!\n");
-
-#ifdef CONFIG_FB_SAVAGE_I2C
-		savagefb_delete_i2c_busses(info);
-#endif
-		fb_alloc_cmap (&info->cmap, 0, 0);
-		savage_unmap_video (info);
-		savage_unmap_mmio (info);
-		kfree(info->pixmap.addr);
-		pci_release_regions(dev);
-		framebuffer_release(info);
-
-		/*
-		 * Ensure that the driver data is no longer
-		 * valid.
-		 */
-		pci_set_drvdata(dev, NULL);
-	}
-}
-
-static int savagefb_suspend (struct pci_dev* dev, u32 state)
-{
-	struct fb_info *info =
-		(struct fb_info *)pci_get_drvdata(dev);
-	struct savagefb_par *par = (struct savagefb_par *)info->par;
-
-	DBG("savagefb_suspend");
-	printk(KERN_DEBUG "state: %u\n", state);
-
-	acquire_console_sem();
-	fb_set_suspend(info, state);
-	savage_disable_mmio(par);
-	release_console_sem();
-
-	pci_disable_device(dev);
-	pci_set_power_state(dev, state);
-
-	return 0;
-}
-
-static int savagefb_resume (struct pci_dev* dev)
-{
-	struct fb_info *info =
-		(struct fb_info *)pci_get_drvdata(dev);
-	struct savagefb_par *par = (struct savagefb_par *)info->par;
-
-	DBG("savage_resume");
-
-	pci_set_power_state(dev, 0);
-	pci_restore_state(dev);
-	if(pci_enable_device(dev))
-		DBG("err");
-
-	SavagePrintRegs();
-
-	acquire_console_sem();
-
-	savage_enable_mmio(par);
-	savage_init_hw(par);
-	savagefb_set_par (info);
-
-	fb_set_suspend (info, 0);
-	release_console_sem();
-
-	return 0;
-}
-
-
-static struct pci_device_id savagefb_devices[] __devinitdata = {
-	{PCI_VENDOR_ID_S3, PCI_CHIP_SUPSAV_MX128,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_SUPERSAVAGE},
-
-	{PCI_VENDOR_ID_S3, PCI_CHIP_SUPSAV_MX64,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_SUPERSAVAGE},
-
-	{PCI_VENDOR_ID_S3, PCI_CHIP_SUPSAV_MX64C,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_SUPERSAVAGE},
-
-	{PCI_VENDOR_ID_S3, PCI_CHIP_SUPSAV_IX128SDR,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_SUPERSAVAGE},
-
-	{PCI_VENDOR_ID_S3, PCI_CHIP_SUPSAV_IX128DDR,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_SUPERSAVAGE},
-
-	{PCI_VENDOR_ID_S3, PCI_CHIP_SUPSAV_IX64SDR,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_SUPERSAVAGE},
-
-	{PCI_VENDOR_ID_S3, PCI_CHIP_SUPSAV_IX64DDR,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_SUPERSAVAGE},
-
-	{PCI_VENDOR_ID_S3, PCI_CHIP_SUPSAV_IXCSDR,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_SUPERSAVAGE},
-
-	{PCI_VENDOR_ID_S3, PCI_CHIP_SUPSAV_IXCDDR,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_SUPERSAVAGE},
-
-	{PCI_VENDOR_ID_S3, PCI_CHIP_SAVAGE4,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_SAVAGE4},
-
-	{PCI_VENDOR_ID_S3, PCI_CHIP_SAVAGE3D,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_SAVAGE3D},
-
-	{PCI_VENDOR_ID_S3, PCI_CHIP_SAVAGE3D_MV,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_SAVAGE3D_MV},
-
-	{PCI_VENDOR_ID_S3, PCI_CHIP_SAVAGE2000,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_SAVAGE2000},
-
-	{PCI_VENDOR_ID_S3, PCI_CHIP_SAVAGE_MX_MV,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_SAVAGE_MX_MV},
-
-	{PCI_VENDOR_ID_S3, PCI_CHIP_SAVAGE_MX,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_SAVAGE_MX},
-
-	{PCI_VENDOR_ID_S3, PCI_CHIP_SAVAGE_IX_MV,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_SAVAGE_IX_MV},
-
-	{PCI_VENDOR_ID_S3, PCI_CHIP_SAVAGE_IX,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_SAVAGE_IX},
-
-	{PCI_VENDOR_ID_S3, PCI_CHIP_PROSAVAGE_PM,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_PROSAVAGE_PM},
-
-	{PCI_VENDOR_ID_S3, PCI_CHIP_PROSAVAGE_KM,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_PROSAVAGE_KM},
-
-	{PCI_VENDOR_ID_S3, PCI_CHIP_S3TWISTER_P,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_S3TWISTER_P},
-
-	{PCI_VENDOR_ID_S3, PCI_CHIP_S3TWISTER_K,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_S3TWISTER_K},
-
-	{PCI_VENDOR_ID_S3, PCI_CHIP_PROSAVAGE_DDR,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_PROSAVAGE_DDR},
-
-	{PCI_VENDOR_ID_S3, PCI_CHIP_PROSAVAGE_DDRK,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_PROSAVAGE_DDRK},
-
-	{0, 0, 0, 0, 0, 0, 0}
-};
-
-MODULE_DEVICE_TABLE(pci, savagefb_devices);
-
-static struct pci_driver savagefb_driver = {
-	.name =     "savagefb",
-	.id_table = savagefb_devices,
-	.probe =    savagefb_probe,
-	.suspend =  savagefb_suspend,
-	.resume =   savagefb_resume,
-	.remove =   __devexit_p(savagefb_remove)
-};
-
-/* **************************** exit-time only **************************** */
-
-static void __exit savage_done (void)
-{
-	DBG("savage_done");
-	pci_unregister_driver (&savagefb_driver);
-}
-
-
-/* ************************* init in-kernel code ************************** */
-
-int __init savagefb_setup(char *options)
-{
-#ifndef MODULE
-	char *this_opt;
-
-	if (!options || !*options)
-		return 0;
-
-	while ((this_opt = strsep(&options, ",")) != NULL) {
-		mode_option = this_opt;
-	}
-#endif /* !MODULE */
-	return 0;
-}
-
-int __init savagefb_init(void)
-{
-	char *option;
-
-	DBG("savagefb_init");
-
-	if (fb_get_options("savagefb", &option))
-		return -ENODEV;
-
-	savagefb_setup(option);
-	return pci_register_driver (&savagefb_driver);
-
-}
-
-module_init(savagefb_init);
-module_exit(savage_done);
diff -Nru a/drivers/video/savage/savagefb_accel.c b/drivers/video/savage/savagefb_accel.c
--- a/drivers/video/savage/savagefb_accel.c	2005-03-11 12:51:41 -08:00
+++ b/drivers/video/savage/savagefb_accel.c	2005-03-11 12:51:41 -08:00
@@ -26,7 +26,6 @@
 	par->SavageWaitIdle(par);
 	return 0;
 }
-EXPORT_SYMBOL(savagefb_sync);
 
 void savagefb_copyarea(struct fb_info *info, const struct fb_copyarea *region)
 {
@@ -61,7 +60,6 @@
 	BCI_SEND(BCI_X_Y(dx, dy));
 	BCI_SEND(BCI_W_H(region->width, region->height));
 }
-EXPORT_SYMBOL(savagefb_copyarea);
 
 void savagefb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
 {
@@ -89,7 +87,6 @@
 	BCI_SEND( BCI_X_Y(rect->dx, rect->dy) );
 	BCI_SEND( BCI_W_H(rect->width, rect->height) );
 }
-EXPORT_SYMBOL(savagefb_fillrect);
 
 void savagefb_imageblit(struct fb_info *info, const struct fb_image *image)
 {
@@ -135,6 +132,5 @@
 	for (i = 0; i < size; i++)
 		BCI_SEND(src[i]);
 }
-EXPORT_SYMBOL(savagefb_imageblit);
 
 MODULE_LICENSE("GPL");
diff -Nru a/drivers/video/savage/savagefb_driver.c b/drivers/video/savage/savagefb_driver.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/video/savage/savagefb_driver.c	2005-03-11 12:51:46 -08:00
@@ -0,0 +1,2280 @@
+/*
+ * linux/drivers/video/savagefb.c -- S3 Savage Framebuffer Driver
+ *
+ * Copyright (c) 2001-2002  Denis Oliver Kropp <dok@directfb.org>
+ *                          Sven Neumann <neo@directfb.org>
+ *
+ *
+ * Card specific code is based on XFree86's savage driver.
+ * Framebuffer framework code is based on code of cyber2000fb and tdfxfb.
+ *
+ * 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.
+ *
+ * 0.4.0 (neo)
+ *  - hardware accelerated clear and move
+ *
+ * 0.3.2 (dok)
+ *  - wait for vertical retrace before writing to cr67
+ *    at the beginning of savagefb_set_par
+ *  - use synchronization registers cr23 and cr26
+ *
+ * 0.3.1 (dok)
+ *  - reset 3D engine
+ *  - don't return alpha bits for 32bit format
+ *
+ * 0.3.0 (dok)
+ *  - added WaitIdle functions for all Savage types
+ *  - do WaitIdle before mode switching
+ *  - code cleanup
+ *
+ * 0.2.0 (dok)
+ *  - first working version
+ *
+ *
+ * TODO
+ * - clock validations in decode_var
+ *
+ * BUGS
+ * - white margin on bootup
+ *
+ */
+
+#include <linux/config.h>
+#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/pci.h>
+#include <linux/init.h>
+#include <linux/console.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/pgtable.h>
+#include <asm/system.h>
+#include <asm/uaccess.h>
+
+#ifdef CONFIG_MTRR
+#include <asm/mtrr.h>
+#endif
+
+#include "savagefb.h"
+
+
+#define SAVAGEFB_VERSION "0.4.0_2.6"
+
+/* --------------------------------------------------------------------- */
+
+
+static char *mode_option __initdata = NULL;
+static int   paletteEnabled = 0;
+
+#ifdef MODULE
+
+MODULE_AUTHOR("(c) 2001-2002  Denis Oliver Kropp <dok@directfb.org>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("FBDev driver for S3 Savage PCI/AGP Chips");
+
+#endif
+
+
+/* --------------------------------------------------------------------- */
+
+static void vgaHWSeqReset (struct savagefb_par *par, int start)
+{
+	if (start)
+		VGAwSEQ (0x00, 0x01);		/* Synchronous Reset */
+	else
+		VGAwSEQ (0x00, 0x03);		/* End Reset */
+}
+
+static void vgaHWProtect (struct savagefb_par *par, int on)
+{
+	unsigned char tmp;
+
+	if (on) {
+		/*
+		 * Turn off screen and disable sequencer.
+		 */
+		tmp = VGArSEQ (0x01);
+
+		vgaHWSeqReset (par, 1);	        /* start synchronous reset */
+		VGAwSEQ (0x01, tmp | 0x20);	/* disable the display */
+
+		VGAenablePalette();
+	} else {
+		/*
+		 * Reenable sequencer, then turn on screen.
+		 */
+
+		tmp = VGArSEQ (0x01);
+
+		VGAwSEQ (0x01, tmp & ~0x20);	/* reenable display */
+		vgaHWSeqReset (par, 0);	        /* clear synchronous reset */
+
+		VGAdisablePalette();
+	}
+}
+
+static void vgaHWRestore (struct savagefb_par  *par)
+{
+	int i;
+
+	VGAwMISC (par->MiscOutReg);
+
+	for (i = 1; i < 5; i++)
+		VGAwSEQ (i, par->Sequencer[i]);
+
+	/* Ensure CRTC registers 0-7 are unlocked by clearing bit 7 or
+	   CRTC[17] */
+	VGAwCR (17, par->CRTC[17] & ~0x80);
+
+	for (i = 0; i < 25; i++)
+		VGAwCR (i, par->CRTC[i]);
+
+	for (i = 0; i < 9; i++)
+		VGAwGR (i, par->Graphics[i]);
+
+	VGAenablePalette();
+
+	for (i = 0; i < 21; i++)
+		VGAwATTR (i, par->Attribute[i]);
+
+	VGAdisablePalette();
+}
+
+static void vgaHWInit (struct fb_var_screeninfo *var,
+		       struct savagefb_par            *par,
+		       struct xtimings                *timings)
+{
+	par->MiscOutReg = 0x23;
+
+	if (!(timings->sync & FB_SYNC_HOR_HIGH_ACT))
+		par->MiscOutReg |= 0x40;
+
+	if (!(timings->sync & FB_SYNC_VERT_HIGH_ACT))
+		par->MiscOutReg |= 0x80;
+
+	/*
+	 * Time Sequencer
+	 */
+	par->Sequencer[0x00] = 0x00;
+	par->Sequencer[0x01] = 0x01;
+	par->Sequencer[0x02] = 0x0F;
+	par->Sequencer[0x03] = 0x00;          /* Font select */
+	par->Sequencer[0x04] = 0x0E;          /* Misc */
+
+	/*
+	 * CRTC Controller
+	 */
+	par->CRTC[0x00] = (timings->HTotal >> 3) - 5;
+	par->CRTC[0x01] = (timings->HDisplay >> 3) - 1;
+	par->CRTC[0x02] = (timings->HSyncStart >> 3) - 1;
+	par->CRTC[0x03] = (((timings->HSyncEnd >> 3)  - 1) & 0x1f) | 0x80;
+	par->CRTC[0x04] = (timings->HSyncStart >> 3);
+	par->CRTC[0x05] = ((((timings->HSyncEnd >> 3) - 1) & 0x20) << 2) |
+		(((timings->HSyncEnd >> 3)) & 0x1f);
+	par->CRTC[0x06] = (timings->VTotal - 2) & 0xFF;
+	par->CRTC[0x07] = (((timings->VTotal - 2) & 0x100) >> 8) |
+		(((timings->VDisplay - 1) & 0x100) >> 7) |
+		((timings->VSyncStart & 0x100) >> 6) |
+		(((timings->VSyncStart - 1) & 0x100) >> 5) |
+		0x10 |
+		(((timings->VTotal - 2) & 0x200) >> 4) |
+		(((timings->VDisplay - 1) & 0x200) >> 3) |
+		((timings->VSyncStart & 0x200) >> 2);
+	par->CRTC[0x08] = 0x00;
+	par->CRTC[0x09] = (((timings->VSyncStart - 1) & 0x200) >> 4) | 0x40;
+
+	if (timings->dblscan)
+		par->CRTC[0x09] |= 0x80;
+
+	par->CRTC[0x0a] = 0x00;
+	par->CRTC[0x0b] = 0x00;
+	par->CRTC[0x0c] = 0x00;
+	par->CRTC[0x0d] = 0x00;
+	par->CRTC[0x0e] = 0x00;
+	par->CRTC[0x0f] = 0x00;
+	par->CRTC[0x10] = timings->VSyncStart & 0xff;
+	par->CRTC[0x11] = (timings->VSyncEnd & 0x0f) | 0x20;
+	par->CRTC[0x12] = (timings->VDisplay - 1) & 0xff;
+	par->CRTC[0x13] = var->xres_virtual >> 4;
+	par->CRTC[0x14] = 0x00;
+	par->CRTC[0x15] = (timings->VSyncStart - 1) & 0xff;
+	par->CRTC[0x16] = (timings->VSyncEnd - 1) & 0xff;
+	par->CRTC[0x17] = 0xc3;
+	par->CRTC[0x18] = 0xff;
+
+	/*
+	 * are these unnecessary?
+	 * vgaHWHBlankKGA(mode, regp, 0, KGA_FIX_OVERSCAN|KGA_ENABLE_ON_ZERO);
+	 * vgaHWVBlankKGA(mode, regp, 0, KGA_FIX_OVERSCAN|KGA_ENABLE_ON_ZERO);
+	 */
+
+	/*
+	 * Graphics Display Controller
+	 */
+	par->Graphics[0x00] = 0x00;
+	par->Graphics[0x01] = 0x00;
+	par->Graphics[0x02] = 0x00;
+	par->Graphics[0x03] = 0x00;
+	par->Graphics[0x04] = 0x00;
+	par->Graphics[0x05] = 0x40;
+	par->Graphics[0x06] = 0x05;   /* only map 64k VGA memory !!!! */
+	par->Graphics[0x07] = 0x0F;
+	par->Graphics[0x08] = 0xFF;
+
+
+	par->Attribute[0x00]  = 0x00; /* standard colormap translation */
+	par->Attribute[0x01]  = 0x01;
+	par->Attribute[0x02]  = 0x02;
+	par->Attribute[0x03]  = 0x03;
+	par->Attribute[0x04]  = 0x04;
+	par->Attribute[0x05]  = 0x05;
+	par->Attribute[0x06]  = 0x06;
+	par->Attribute[0x07]  = 0x07;
+	par->Attribute[0x08]  = 0x08;
+	par->Attribute[0x09]  = 0x09;
+	par->Attribute[0x0a] = 0x0A;
+	par->Attribute[0x0b] = 0x0B;
+	par->Attribute[0x0c] = 0x0C;
+	par->Attribute[0x0d] = 0x0D;
+	par->Attribute[0x0e] = 0x0E;
+	par->Attribute[0x0f] = 0x0F;
+	par->Attribute[0x10] = 0x41;
+	par->Attribute[0x11] = 0xFF;
+	par->Attribute[0x12] = 0x0F;
+	par->Attribute[0x13] = 0x00;
+	par->Attribute[0x14] = 0x00;
+}
+
+/* -------------------- Hardware specific routines ------------------------- */
+
+/*
+ * Hardware Acceleration for SavageFB
+ */
+
+/* Wait for fifo space */
+static void
+savage3D_waitfifo(struct savagefb_par *par, int space)
+{
+	int slots = MAXFIFO - space;
+
+	while ((savage_in32(0x48C00) & 0x0000ffff) > slots);
+}
+
+static void
+savage4_waitfifo(struct savagefb_par *par, int space)
+{
+	int slots = MAXFIFO - space;
+
+	while ((savage_in32(0x48C60) & 0x001fffff) > slots);
+}
+
+static void
+savage2000_waitfifo(struct savagefb_par *par, int space)
+{
+	int slots = MAXFIFO - space;
+
+	while ((savage_in32(0x48C60) & 0x0000ffff) > slots);
+}
+
+/* Wait for idle accelerator */
+static void
+savage3D_waitidle(struct savagefb_par *par)
+{
+	while ((savage_in32(0x48C00) & 0x0008ffff) != 0x80000);
+}
+
+static void
+savage4_waitidle(struct savagefb_par *par)
+{
+	while ((savage_in32(0x48C60) & 0x00a00000) != 0x00a00000);
+}
+
+static void
+savage2000_waitidle(struct savagefb_par *par)
+{
+	while ((savage_in32(0x48C60) & 0x009fffff));
+}
+
+
+static void
+SavageSetup2DEngine (struct savagefb_par  *par)
+{
+	unsigned long GlobalBitmapDescriptor;
+
+	GlobalBitmapDescriptor = 1 | 8 | BCI_BD_BW_DISABLE;
+	BCI_BD_SET_BPP (GlobalBitmapDescriptor, par->depth);
+	BCI_BD_SET_STRIDE (GlobalBitmapDescriptor, par->vwidth);
+
+	switch(par->chip) {
+	case S3_SAVAGE3D:
+	case S3_SAVAGE_MX:
+		/* Disable BCI */
+		savage_out32(0x48C18, savage_in32(0x48C18) & 0x3FF0);
+		/* Setup BCI command overflow buffer */
+		savage_out32(0x48C14, (par->cob_offset >> 11) | (par->cob_index << 29));
+		/* Program shadow status update. */
+		savage_out32(0x48C10, 0x78207220);
+		savage_out32(0x48C0C, 0);
+		/* Enable BCI and command overflow buffer */
+		savage_out32(0x48C18, savage_in32(0x48C18) | 0x0C);
+		break;
+	case S3_SAVAGE4:
+	case S3_PROSAVAGE:
+	case S3_SUPERSAVAGE:
+		/* Disable BCI */
+		savage_out32(0x48C18, savage_in32(0x48C18) & 0x3FF0);
+		/* Program shadow status update */
+		savage_out32(0x48C10, 0x00700040);
+		savage_out32(0x48C0C, 0);
+		/* Enable BCI without the COB */
+		savage_out32(0x48C18, savage_in32(0x48C18) | 0x08);
+		break;
+	case S3_SAVAGE2000:
+		/* Disable BCI */
+		savage_out32(0x48C18, 0);
+		/* Setup BCI command overflow buffer */
+		savage_out32(0x48C18, (par->cob_offset >> 7) | (par->cob_index));
+		/* Disable shadow status update */
+		savage_out32(0x48A30, 0);
+		/* Enable BCI and command overflow buffer */
+		savage_out32(0x48C18, savage_in32(0x48C18) | 0x00280000 );
+		break;
+	    default:
+		break;
+	}
+	/* Turn on 16-bit register access. */
+	vga_out8(0x3d4, 0x31);
+	vga_out8(0x3d5, 0x0c);
+
+	/* Set stride to use GBD. */
+	vga_out8 (0x3d4, 0x50);
+	vga_out8 (0x3d5, vga_in8 (0x3d5 ) | 0xC1);
+
+	/* Enable 2D engine. */
+	vga_out8 (0x3d4, 0x40 );
+	vga_out8 (0x3d5, 0x01 );
+
+	savage_out32 (MONO_PAT_0, ~0);
+	savage_out32 (MONO_PAT_1, ~0);
+
+	/* Setup plane masks */
+	savage_out32 (0x8128, ~0 ); /* enable all write planes */
+	savage_out32 (0x812C, ~0 ); /* enable all read planes */
+	savage_out16 (0x8134, 0x27 );
+	savage_out16 (0x8136, 0x07 );
+
+	/* Now set the GBD */
+	par->bci_ptr = 0;
+	par->SavageWaitFifo (par, 4);
+
+	BCI_SEND( BCI_CMD_SETREG | (1 << 16) | BCI_GBD1 );
+	BCI_SEND( 0 );
+	BCI_SEND( BCI_CMD_SETREG | (1 << 16) | BCI_GBD2 );
+	BCI_SEND( GlobalBitmapDescriptor );
+}
+
+
+static void SavageCalcClock(long freq, int min_m, int min_n1, int max_n1,
+			    int min_n2, int max_n2, long freq_min,
+			    long freq_max, unsigned int *mdiv,
+			    unsigned int *ndiv, unsigned int *r)
+{
+	long diff, best_diff;
+	unsigned int m;
+	unsigned char n1, n2, best_n1=16+2, best_n2=2, best_m=125+2;
+
+	if (freq < freq_min / (1 << max_n2)) {
+		printk (KERN_ERR "invalid frequency %ld Khz\n", freq);
+		freq = freq_min / (1 << max_n2);
+	}
+	if (freq > freq_max / (1 << min_n2)) {
+		printk (KERN_ERR "invalid frequency %ld Khz\n", freq);
+		freq = freq_max / (1 << min_n2);
+	}
+
+	/* work out suitable timings */
+	best_diff = freq;
+
+	for (n2=min_n2; n2<=max_n2; n2++) {
+		for (n1=min_n1+2; n1<=max_n1+2; n1++) {
+			m = (freq * n1 * (1 << n2) + HALF_BASE_FREQ) /
+				BASE_FREQ;
+			if (m < min_m+2 || m > 127+2)
+				continue;
+			if ((m * BASE_FREQ >= freq_min * n1) &&
+			    (m * BASE_FREQ <= freq_max * n1)) {
+				diff = freq * (1 << n2) * n1 - BASE_FREQ * m;
+				if (diff < 0)
+					diff = -diff;
+				if (diff < best_diff) {
+					best_diff = diff;
+					best_m = m;
+					best_n1 = n1;
+					best_n2 = n2;
+				}
+			}
+		}
+	}
+
+	*ndiv = best_n1 - 2;
+	*r = best_n2;
+	*mdiv = best_m - 2;
+}
+
+static int common_calc_clock(long freq, int min_m, int min_n1, int max_n1,
+			     int min_n2, int max_n2, long freq_min,
+			     long freq_max, unsigned char *mdiv,
+			     unsigned char *ndiv)
+{
+	long diff, best_diff;
+	unsigned int m;
+	unsigned char n1, n2;
+	unsigned char best_n1 = 16+2, best_n2 = 2, best_m = 125+2;
+
+	best_diff = freq;
+
+	for (n2 = min_n2; n2 <= max_n2; n2++) {
+		for (n1 = min_n1+2; n1 <= max_n1+2; n1++) {
+			m = (freq * n1 * (1 << n2) + HALF_BASE_FREQ) /
+				BASE_FREQ;
+			if (m < min_m + 2 || m > 127+2)
+				continue;
+			if((m * BASE_FREQ >= freq_min * n1) &&
+			   (m * BASE_FREQ <= freq_max * n1)) {
+				diff = freq * (1 << n2) * n1 - BASE_FREQ * m;
+				if(diff < 0)
+					diff = -diff;
+				if(diff < best_diff) {
+					best_diff = diff;
+					best_m = m;
+					best_n1 = n1;
+					best_n2 = n2;
+				}
+			}
+		}
+	}
+
+	if(max_n1 == 63)
+		*ndiv = (best_n1 - 2) | (best_n2 << 6);
+	else
+		*ndiv = (best_n1 - 2) | (best_n2 << 5);
+
+	*mdiv = best_m - 2;
+
+	return 0;
+}
+
+#ifdef SAVAGEFB_DEBUG
+/* This function is used to debug, it prints out the contents of s3 regs */
+
+static void SavagePrintRegs(void)
+{
+	unsigned char i;
+	int vgaCRIndex = 0x3d4;
+	int vgaCRReg = 0x3d5;
+
+	printk(KERN_DEBUG "SR    x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE "
+	       "xF" );
+
+	for( i = 0; i < 0x70; i++ ) {
+		if( !(i % 16) )
+			printk(KERN_DEBUG "\nSR%xx ", i >> 4 );
+		vga_out8( 0x3c4, i );
+		printk(KERN_DEBUG " %02x", vga_in8(0x3c5) );
+	}
+
+	printk(KERN_DEBUG "\n\nCR    x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC "
+	       "xD xE xF" );
+
+	for( i = 0; i < 0xB7; i++ ) {
+		if( !(i % 16) )
+			printk(KERN_DEBUG "\nCR%xx ", i >> 4 );
+		vga_out8( vgaCRIndex, i );
+		printk(KERN_DEBUG " %02x", vga_in8(vgaCRReg) );
+	}
+
+	printk(KERN_DEBUG "\n\n");
+}
+#endif
+
+/* --------------------------------------------------------------------- */
+
+static void savage_get_default_par(struct savagefb_par *par)
+{
+	unsigned char cr3a, cr53, cr66;
+
+	vga_out16 (0x3d4, 0x4838);
+	vga_out16 (0x3d4, 0xa039);
+	vga_out16 (0x3c4, 0x0608);
+
+	vga_out8 (0x3d4, 0x66);
+	cr66 = vga_in8 (0x3d5);
+	vga_out8 (0x3d5, cr66 | 0x80);
+	vga_out8 (0x3d4, 0x3a);
+	cr3a = vga_in8 (0x3d5);
+	vga_out8 (0x3d5, cr3a | 0x80);
+	vga_out8 (0x3d4, 0x53);
+	cr53 = vga_in8 (0x3d5);
+	vga_out8 (0x3d5, cr53 & 0x7f);
+
+	vga_out8 (0x3d4, 0x66);
+	vga_out8 (0x3d5, cr66);
+	vga_out8 (0x3d4, 0x3a);
+	vga_out8 (0x3d5, cr3a);
+
+	vga_out8 (0x3d4, 0x66);
+	vga_out8 (0x3d5, cr66);
+	vga_out8 (0x3d4, 0x3a);
+	vga_out8 (0x3d5, cr3a);
+
+	/* unlock extended seq regs */
+	vga_out8 (0x3c4, 0x08);
+	par->SR08 = vga_in8 (0x3c5);
+	vga_out8 (0x3c5, 0x06);
+
+	/* now save all the extended regs we need */
+	vga_out8 (0x3d4, 0x31);
+	par->CR31 = vga_in8 (0x3d5);
+	vga_out8 (0x3d4, 0x32);
+	par->CR32 = vga_in8 (0x3d5);
+	vga_out8 (0x3d4, 0x34);
+	par->CR34 = vga_in8 (0x3d5);
+	vga_out8 (0x3d4, 0x36);
+	par->CR36 = vga_in8 (0x3d5);
+	vga_out8 (0x3d4, 0x3a);
+	par->CR3A = vga_in8 (0x3d5);
+	vga_out8 (0x3d4, 0x40);
+	par->CR40 = vga_in8 (0x3d5);
+	vga_out8 (0x3d4, 0x42);
+	par->CR42 = vga_in8 (0x3d5);
+	vga_out8 (0x3d4, 0x45);
+	par->CR45 = vga_in8 (0x3d5);
+	vga_out8 (0x3d4, 0x50);
+	par->CR50 = vga_in8 (0x3d5);
+	vga_out8 (0x3d4, 0x51);
+	par->CR51 = vga_in8 (0x3d5);
+	vga_out8 (0x3d4, 0x53);
+	par->CR53 = vga_in8 (0x3d5);
+	vga_out8 (0x3d4, 0x58);
+	par->CR58 = vga_in8 (0x3d5);
+	vga_out8 (0x3d4, 0x60);
+	par->CR60 = vga_in8 (0x3d5);
+	vga_out8 (0x3d4, 0x66);
+	par->CR66 = vga_in8 (0x3d5);
+	vga_out8 (0x3d4, 0x67);
+	par->CR67 = vga_in8 (0x3d5);
+	vga_out8 (0x3d4, 0x68);
+	par->CR68 = vga_in8 (0x3d5);
+	vga_out8 (0x3d4, 0x69);
+	par->CR69 = vga_in8 (0x3d5);
+	vga_out8 (0x3d4, 0x6f);
+	par->CR6F = vga_in8 (0x3d5);
+
+	vga_out8 (0x3d4, 0x33);
+	par->CR33 = vga_in8 (0x3d5);
+	vga_out8 (0x3d4, 0x86);
+	par->CR86 = vga_in8 (0x3d5);
+	vga_out8 (0x3d4, 0x88);
+	par->CR88 = vga_in8 (0x3d5);
+	vga_out8 (0x3d4, 0x90);
+	par->CR90 = vga_in8 (0x3d5);
+	vga_out8 (0x3d4, 0x91);
+	par->CR91 = vga_in8 (0x3d5);
+	vga_out8 (0x3d4, 0xb0);
+	par->CRB0 = vga_in8 (0x3d5) | 0x80;
+
+	/* extended mode timing regs */
+	vga_out8 (0x3d4, 0x3b);
+	par->CR3B = vga_in8 (0x3d5);
+	vga_out8 (0x3d4, 0x3c);
+	par->CR3C = vga_in8 (0x3d5);
+	vga_out8 (0x3d4, 0x43);
+	par->CR43 = vga_in8 (0x3d5);
+	vga_out8 (0x3d4, 0x5d);
+	par->CR5D = vga_in8 (0x3d5);
+	vga_out8 (0x3d4, 0x5e);
+	par->CR5E = vga_in8 (0x3d5);
+	vga_out8 (0x3d4, 0x65);
+	par->CR65 = vga_in8 (0x3d5);
+
+	/* save seq extended regs for DCLK PLL programming */
+	vga_out8 (0x3c4, 0x0e);
+	par->SR0E = vga_in8 (0x3c5);
+	vga_out8 (0x3c4, 0x0f);
+	par->SR0F = vga_in8 (0x3c5);
+	vga_out8 (0x3c4, 0x10);
+	par->SR10 = vga_in8 (0x3c5);
+	vga_out8 (0x3c4, 0x11);
+	par->SR11 = vga_in8 (0x3c5);
+	vga_out8 (0x3c4, 0x12);
+	par->SR12 = vga_in8 (0x3c5);
+	vga_out8 (0x3c4, 0x13);
+	par->SR13 = vga_in8 (0x3c5);
+	vga_out8 (0x3c4, 0x29);
+	par->SR29 = vga_in8 (0x3c5);
+
+	vga_out8 (0x3c4, 0x15);
+	par->SR15 = vga_in8 (0x3c5);
+	vga_out8 (0x3c4, 0x30);
+	par->SR30 = vga_in8 (0x3c5);
+	vga_out8 (0x3c4, 0x18);
+	par->SR18 = vga_in8 (0x3c5);
+
+	/* Save flat panel expansion regsters. */
+	if (par->chip == S3_SAVAGE_MX) {
+		int i;
+
+		for (i = 0; i < 8; i++) {
+			vga_out8 (0x3c4, 0x54+i);
+			par->SR54[i] = vga_in8 (0x3c5);
+		}
+	}
+
+	vga_out8 (0x3d4, 0x66);
+	cr66 = vga_in8 (0x3d5);
+	vga_out8 (0x3d5, cr66 | 0x80);
+	vga_out8 (0x3d4, 0x3a);
+	cr3a = vga_in8 (0x3d5);
+	vga_out8 (0x3d5, cr3a | 0x80);
+
+	/* now save MIU regs */
+	if (par->chip != S3_SAVAGE_MX) {
+		par->MMPR0 = savage_in32(FIFO_CONTROL_REG);
+		par->MMPR1 = savage_in32(MIU_CONTROL_REG);
+		par->MMPR2 = savage_in32(STREAMS_TIMEOUT_REG);
+		par->MMPR3 = savage_in32(MISC_TIMEOUT_REG);
+	}
+
+	vga_out8 (0x3d4, 0x3a);
+	vga_out8 (0x3d5, cr3a);
+	vga_out8 (0x3d4, 0x66);
+	vga_out8 (0x3d5, cr66);
+}
+
+static void savage_update_var(struct fb_var_screeninfo *var, struct fb_videomode *modedb)
+{
+	var->xres = var->xres_virtual = modedb->xres;
+	var->yres = modedb->yres;
+        if (var->yres_virtual < var->yres)
+	    var->yres_virtual = var->yres;
+        var->xoffset = var->yoffset = 0;
+        var->pixclock = modedb->pixclock;
+        var->left_margin = modedb->left_margin;
+        var->right_margin = modedb->right_margin;
+        var->upper_margin = modedb->upper_margin;
+        var->lower_margin = modedb->lower_margin;
+        var->hsync_len = modedb->hsync_len;
+        var->vsync_len = modedb->vsync_len;
+        var->sync = modedb->sync;
+        var->vmode = modedb->vmode;
+}
+
+static int savagefb_check_var (struct fb_var_screeninfo   *var,
+			       struct fb_info *info)
+{
+	struct savagefb_par *par = (struct savagefb_par *)info->par;
+	int memlen, vramlen, mode_valid = 0;
+
+	DBG("savagefb_check_var");
+
+	var->transp.offset = 0;
+	var->transp.length = 0;
+	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 = var->bits_per_pixel;
+		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;
+		break;
+	case 32:
+		var->transp.offset = 24;
+		var->transp.length = 8;
+		var->red.offset = 16;
+		var->red.length = 8;
+		var->green.offset = 8;
+		var->green.length = 8;
+		var->blue.offset = 0;
+		var->blue.length = 8;
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	if (!info->monspecs.hfmax || !info->monspecs.vfmax ||
+	    !info->monspecs.dclkmax || !fb_validate_mode(var, info))
+		mode_valid = 1;
+
+	/* calculate modeline if supported by monitor */
+	if (!mode_valid && info->monspecs.gtf) {
+		if (!fb_get_mode(FB_MAXTIMINGS, 0, var, info))
+			mode_valid = 1;
+	}
+
+	if (!mode_valid) {
+		struct fb_videomode *mode;
+
+		mode = fb_find_best_mode(var, &info->modelist);
+		if (mode) {
+			savage_update_var(var, mode);
+			mode_valid = 1;
+		}
+	}
+
+	if (!mode_valid && info->monspecs.modedb_len)
+		return -EINVAL;
+
+	/* Is the mode larger than the LCD panel? */
+	if (par->SavagePanelWidth &&
+	    (var->xres > par->SavagePanelWidth ||
+	     var->yres > par->SavagePanelHeight)) {
+		printk (KERN_INFO "Mode (%dx%d) larger than the LCD panel "
+			"(%dx%d)\n", var->xres,  var->yres,
+			par->SavagePanelWidth,
+			par->SavagePanelHeight);
+		return -1;
+	}
+
+	if (var->yres_virtual < var->yres)
+		var->yres_virtual = var->yres;
+	if (var->xres_virtual < var->xres)
+		var->xres_virtual = var->xres;
+
+	vramlen = info->fix.smem_len;
+
+	memlen = var->xres_virtual * var->bits_per_pixel *
+		var->yres_virtual / 8;
+	if (memlen > vramlen) {
+		var->yres_virtual = vramlen * 8 /
+			(var->xres_virtual * var->bits_per_pixel);
+		memlen = var->xres_virtual * var->bits_per_pixel *
+			var->yres_virtual / 8;
+	}
+
+	/* we must round yres/xres down, we already rounded y/xres_virtual up
+	   if it was possible. We should return -EINVAL, but I disagree */
+	if (var->yres_virtual < var->yres)
+		var->yres = var->yres_virtual;
+	if (var->xres_virtual < var->xres)
+		var->xres = var->xres_virtual;
+	if (var->xoffset + var->xres > var->xres_virtual)
+		var->xoffset = var->xres_virtual - var->xres;
+	if (var->yoffset + var->yres > var->yres_virtual)
+		var->yoffset = var->yres_virtual - var->yres;
+
+	return 0;
+}
+
+
+static int savagefb_decode_var (struct fb_var_screeninfo   *var,
+				struct savagefb_par        *par)
+{
+	struct xtimings timings;
+	int width, dclk, i, j; /*, refresh; */
+	unsigned int m, n, r;
+	unsigned char tmp = 0;
+	unsigned int pixclock = var->pixclock;
+
+	DBG("savagefb_decode_var");
+
+	memset (&timings, 0, sizeof(timings));
+
+	if (!pixclock) pixclock = 10000;	/* 10ns = 100MHz */
+	timings.Clock = 1000000000 / pixclock;
+	if (timings.Clock < 1) timings.Clock = 1;
+	timings.dblscan = var->vmode & FB_VMODE_DOUBLE;
+	timings.interlaced = var->vmode & FB_VMODE_INTERLACED;
+	timings.HDisplay = var->xres;
+	timings.HSyncStart = timings.HDisplay + var->right_margin;
+	timings.HSyncEnd = timings.HSyncStart + var->hsync_len;
+	timings.HTotal = timings.HSyncEnd + var->left_margin;
+	timings.VDisplay = var->yres;
+	timings.VSyncStart = timings.VDisplay + var->lower_margin;
+	timings.VSyncEnd = timings.VSyncStart + var->vsync_len;
+	timings.VTotal = timings.VSyncEnd + var->upper_margin;
+	timings.sync = var->sync;
+
+
+	par->depth  = var->bits_per_pixel;
+	par->vwidth = var->xres_virtual;
+
+	if (var->bits_per_pixel == 16  &&  par->chip == S3_SAVAGE3D) {
+		timings.HDisplay *= 2;
+		timings.HSyncStart *= 2;
+		timings.HSyncEnd *= 2;
+		timings.HTotal *= 2;
+	}
+
+	/*
+	 * This will allocate the datastructure and initialize all of the
+	 * generic VGA registers.
+	 */
+	vgaHWInit (var, par, &timings);
+
+	/* We need to set CR67 whether or not we use the BIOS. */
+
+	dclk = timings.Clock;
+	par->CR67 = 0x00;
+
+	switch( var->bits_per_pixel ) {
+	case 8:
+		if( (par->chip == S3_SAVAGE2000) && (dclk >= 230000) )
+			par->CR67 = 0x10;	/* 8bpp, 2 pixels/clock */
+		else
+			par->CR67 = 0x00;	/* 8bpp, 1 pixel/clock */
+		break;
+	case 15:
+		if ( S3_SAVAGE_MOBILE_SERIES(par->chip) ||
+		     ((par->chip == S3_SAVAGE2000) && (dclk >= 230000)) )
+			par->CR67 = 0x30;	/* 15bpp, 2 pixel/clock */
+		else
+			par->CR67 = 0x20;	/* 15bpp, 1 pixels/clock */
+		break;
+	case 16:
+		if( S3_SAVAGE_MOBILE_SERIES(par->chip) ||
+		    ((par->chip == S3_SAVAGE2000) && (dclk >= 230000)) )
+			par->CR67 = 0x50;	/* 16bpp, 2 pixel/clock */
+		else
+			par->CR67 = 0x40;	/* 16bpp, 1 pixels/clock */
+		break;
+	case 24:
+		par->CR67 = 0x70;
+		break;
+	case 32:
+		par->CR67 = 0xd0;
+		break;
+	}
+
+	/*
+	 * Either BIOS use is disabled, or we failed to find a suitable
+	 * match.  Fall back to traditional register-crunching.
+	 */
+
+	vga_out8 (0x3d4, 0x3a);
+	tmp = vga_in8 (0x3d5);
+	if (1 /*FIXME:psav->pci_burst*/)
+		par->CR3A = (tmp & 0x7f) | 0x15;
+	else
+		par->CR3A = tmp | 0x95;
+
+	par->CR53 = 0x00;
+	par->CR31 = 0x8c;
+	par->CR66 = 0x89;
+
+	vga_out8 (0x3d4, 0x58);
+	par->CR58 = vga_in8 (0x3d5) & 0x80;
+	par->CR58 |= 0x13;
+
+	par->SR15 = 0x03 | 0x80;
+	par->SR18 = 0x00;
+	par->CR43 = par->CR45 = par->CR65 = 0x00;
+
+	vga_out8 (0x3d4, 0x40);
+	par->CR40 = vga_in8 (0x3d5) & ~0x01;
+
+	par->MMPR0 = 0x010400;
+	par->MMPR1 = 0x00;
+	par->MMPR2 = 0x0808;
+	par->MMPR3 = 0x08080810;
+
+	SavageCalcClock (dclk, 1, 1, 127, 0, 4, 180000, 360000, &m, &n, &r);
+	/* m = 107; n = 4; r = 2; */
+
+	if (par->MCLK <= 0) {
+		par->SR10 = 255;
+		par->SR11 = 255;
+	} else {
+		common_calc_clock (par->MCLK, 1, 1, 31, 0, 3, 135000, 270000,
+				   &par->SR11, &par->SR10);
+		/*      par->SR10 = 80; // MCLK == 286000 */
+		/*      par->SR11 = 125; */
+	}
+
+	par->SR12 = (r << 6) | (n & 0x3f);
+	par->SR13 = m & 0xff;
+	par->SR29 = (r & 4) | (m & 0x100) >> 5 | (n & 0x40) >> 2;
+
+	if (var->bits_per_pixel < 24)
+		par->MMPR0 -= 0x8000;
+	else
+		par->MMPR0 -= 0x4000;
+
+	if (timings.interlaced)
+		par->CR42 = 0x20;
+	else
+		par->CR42 = 0x00;
+
+	par->CR34 = 0x10; /* display fifo */
+
+	i = ((((timings.HTotal >> 3) - 5) & 0x100) >> 8) |
+		((((timings.HDisplay >> 3) - 1) & 0x100) >> 7) |
+		((((timings.HSyncStart >> 3) - 1) & 0x100) >> 6) |
+		((timings.HSyncStart & 0x800) >> 7);
+
+	if ((timings.HSyncEnd >> 3) - (timings.HSyncStart >> 3) > 64)
+		i |= 0x08;
+	if ((timings.HSyncEnd >> 3) - (timings.HSyncStart >> 3) > 32)
+		i |= 0x20;
+
+	j = (par->CRTC[0] + ((i & 0x01) << 8) +
+	     par->CRTC[4] + ((i & 0x10) << 4) + 1) / 2;
+
+	if (j - (par->CRTC[4] + ((i & 0x10) << 4)) < 4) {
+		if (par->CRTC[4] + ((i & 0x10) << 4) + 4 <=
+		    par->CRTC[0] + ((i & 0x01) << 8))
+			j = par->CRTC[4] + ((i & 0x10) << 4) + 4;
+		else
+			j = par->CRTC[0] + ((i & 0x01) << 8) + 1;
+	}
+
+	par->CR3B = j & 0xff;
+	i |= (j & 0x100) >> 2;
+	par->CR3C = (par->CRTC[0] + ((i & 0x01) << 8)) / 2;
+	par->CR5D = i;
+	par->CR5E = (((timings.VTotal - 2) & 0x400) >> 10) |
+		(((timings.VDisplay - 1) & 0x400) >> 9) |
+		(((timings.VSyncStart) & 0x400) >> 8) |
+		(((timings.VSyncStart) & 0x400) >> 6) | 0x40;
+	width = (var->xres_virtual * ((var->bits_per_pixel+7) / 8)) >> 3;
+	par->CR91 = par->CRTC[19] = 0xff & width;
+	par->CR51 = (0x300 & width) >> 4;
+	par->CR90 = 0x80 | (width >> 8);
+	par->MiscOutReg |= 0x0c;
+
+	/* Set frame buffer description. */
+
+	if (var->bits_per_pixel <= 8)
+		par->CR50 = 0;
+	else if (var->bits_per_pixel <= 16)
+		par->CR50 = 0x10;
+	else
+		par->CR50 = 0x30;
+
+	if (var->xres_virtual <= 640)
+		par->CR50 |= 0x40;
+	else if (var->xres_virtual == 800)
+		par->CR50 |= 0x80;
+	else if (var->xres_virtual == 1024)
+		par->CR50 |= 0x00;
+	else if (var->xres_virtual == 1152)
+		par->CR50 |= 0x01;
+	else if (var->xres_virtual == 1280)
+		par->CR50 |= 0xc0;
+	else if (var->xres_virtual == 1600)
+		par->CR50 |= 0x81;
+	else
+		par->CR50 |= 0xc1;	/* Use GBD */
+
+	if( par->chip == S3_SAVAGE2000 )
+		par->CR33 = 0x08;
+	else
+		par->CR33 = 0x20;
+
+	par->CRTC[0x17] = 0xeb;
+
+	par->CR67 |= 1;
+
+	vga_out8(0x3d4, 0x36);
+	par->CR36 = vga_in8 (0x3d5);
+	vga_out8 (0x3d4, 0x68);
+	par->CR68 = vga_in8 (0x3d5);
+	par->CR69 = 0;
+	vga_out8 (0x3d4, 0x6f);
+	par->CR6F = vga_in8 (0x3d5);
+	vga_out8 (0x3d4, 0x86);
+	par->CR86 = vga_in8 (0x3d5);
+	vga_out8 (0x3d4, 0x88);
+	par->CR88 = vga_in8 (0x3d5) | 0x08;
+	vga_out8 (0x3d4, 0xb0);
+	par->CRB0 = vga_in8 (0x3d5) | 0x80;
+
+	return 0;
+}
+
+/* --------------------------------------------------------------------- */
+
+/*
+ *    Set a single color register. Return != 0 for invalid regno.
+ */
+static int savagefb_setcolreg(unsigned        regno,
+			      unsigned        red,
+			      unsigned        green,
+			      unsigned        blue,
+			      unsigned        transp,
+			      struct fb_info *info)
+{
+	struct savagefb_par *par = (struct savagefb_par *)info->par;
+
+	if (regno >= NR_PALETTE)
+		return -EINVAL;
+
+	par->palette[regno].red    = red;
+	par->palette[regno].green  = green;
+	par->palette[regno].blue   = blue;
+	par->palette[regno].transp = transp;
+
+	switch (info->var.bits_per_pixel) {
+	case 8:
+		vga_out8 (0x3c8, regno);
+
+		vga_out8 (0x3c9, red   >> 10);
+		vga_out8 (0x3c9, green >> 10);
+		vga_out8 (0x3c9, blue  >> 10);
+		break;
+
+	case 16:
+		if (regno < 16)
+			((u32 *)info->pseudo_palette)[regno] =
+				((red   & 0xf800)      ) |
+				((green & 0xfc00) >>  5) |
+				((blue  & 0xf800) >> 11);
+		break;
+
+	case 24:
+		if (regno < 16)
+			((u32 *)info->pseudo_palette)[regno] =
+				((red    & 0xff00) <<  8) |
+				((green  & 0xff00)      ) |
+				((blue   & 0xff00) >>  8);
+		break;
+	case 32:
+		if (regno < 16)
+			((u32 *)info->pseudo_palette)[regno] =
+				((transp & 0xff00) << 16) |
+				((red    & 0xff00) <<  8) |
+				((green  & 0xff00)      ) |
+				((blue   & 0xff00) >>  8);
+		break;
+
+	default:
+		return 1;
+	}
+
+	return 0;
+}
+
+static void savagefb_set_par_int (struct savagefb_par  *par)
+{
+	unsigned char tmp, cr3a, cr66, cr67;
+
+	DBG ("savagefb_set_par_int");
+
+	par->SavageWaitIdle (par);
+
+	vga_out8 (0x3c2, 0x23);
+
+	vga_out16 (0x3d4, 0x4838);
+	vga_out16 (0x3d4, 0xa539);
+	vga_out16 (0x3c4, 0x0608);
+
+	vgaHWProtect (par, 1);
+
+	/*
+	 * Some Savage/MX and /IX systems go nuts when trying to exit the
+	 * server after WindowMaker has displayed a gradient background.  I
+	 * haven't been able to find what causes it, but a non-destructive
+	 * switch to mode 3 here seems to eliminate the issue.
+	 */
+
+	VerticalRetraceWait();
+	vga_out8 (0x3d4, 0x67);
+	cr67 = vga_in8 (0x3d5);
+	vga_out8 (0x3d5, cr67/*par->CR67*/ & ~0x0c); /* no STREAMS yet */
+
+	vga_out8 (0x3d4, 0x23);
+	vga_out8 (0x3d5, 0x00);
+	vga_out8 (0x3d4, 0x26);
+	vga_out8 (0x3d5, 0x00);
+
+	/* restore extended regs */
+	vga_out8 (0x3d4, 0x66);
+	vga_out8 (0x3d5, par->CR66);
+	vga_out8 (0x3d4, 0x3a);
+	vga_out8 (0x3d5, par->CR3A);
+	vga_out8 (0x3d4, 0x31);
+	vga_out8 (0x3d5, par->CR31);
+	vga_out8 (0x3d4, 0x32);
+	vga_out8 (0x3d5, par->CR32);
+	vga_out8 (0x3d4, 0x58);
+	vga_out8 (0x3d5, par->CR58);
+	vga_out8 (0x3d4, 0x53);
+	vga_out8 (0x3d5, par->CR53 & 0x7f);
+
+	vga_out16 (0x3c4, 0x0608);
+
+	/* Restore DCLK registers. */
+
+	vga_out8 (0x3c4, 0x0e);
+	vga_out8 (0x3c5, par->SR0E);
+	vga_out8 (0x3c4, 0x0f);
+	vga_out8 (0x3c5, par->SR0F);
+	vga_out8 (0x3c4, 0x29);
+	vga_out8 (0x3c5, par->SR29);
+	vga_out8 (0x3c4, 0x15);
+	vga_out8 (0x3c5, par->SR15);
+
+	/* Restore flat panel expansion regsters. */
+	if( par->chip == S3_SAVAGE_MX ) {
+		int i;
+
+		for( i = 0; i < 8; i++ ) {
+			vga_out8 (0x3c4, 0x54+i);
+			vga_out8 (0x3c5, par->SR54[i]);
+		}
+	}
+
+	vgaHWRestore (par);
+
+	/* extended mode timing registers */
+	vga_out8 (0x3d4, 0x53);
+	vga_out8 (0x3d5, par->CR53);
+	vga_out8 (0x3d4, 0x5d);
+	vga_out8 (0x3d5, par->CR5D);
+	vga_out8 (0x3d4, 0x5e);
+	vga_out8 (0x3d5, par->CR5E);
+	vga_out8 (0x3d4, 0x3b);
+	vga_out8 (0x3d5, par->CR3B);
+	vga_out8 (0x3d4, 0x3c);
+	vga_out8 (0x3d5, par->CR3C);
+	vga_out8 (0x3d4, 0x43);
+	vga_out8 (0x3d5, par->CR43);
+	vga_out8 (0x3d4, 0x65);
+	vga_out8 (0x3d5, par->CR65);
+
+	/* restore the desired video mode with cr67 */
+	vga_out8 (0x3d4, 0x67);
+	/* following part not present in X11 driver */
+	cr67 = vga_in8 (0x3d5) & 0xf;
+	vga_out8 (0x3d5, 0x50 | cr67);
+	udelay (10000);
+	vga_out8 (0x3d4, 0x67);
+	/* end of part */
+	vga_out8 (0x3d5, par->CR67 & ~0x0c);
+
+	/* other mode timing and extended regs */
+	vga_out8 (0x3d4, 0x34);
+	vga_out8 (0x3d5, par->CR34);
+	vga_out8 (0x3d4, 0x40);
+	vga_out8 (0x3d5, par->CR40);
+	vga_out8 (0x3d4, 0x42);
+	vga_out8 (0x3d5, par->CR42);
+	vga_out8 (0x3d4, 0x45);
+	vga_out8 (0x3d5, par->CR45);
+	vga_out8 (0x3d4, 0x50);
+	vga_out8 (0x3d5, par->CR50);
+	vga_out8 (0x3d4, 0x51);
+	vga_out8 (0x3d5, par->CR51);
+
+	/* memory timings */
+	vga_out8 (0x3d4, 0x36);
+	vga_out8 (0x3d5, par->CR36);
+	vga_out8 (0x3d4, 0x60);
+	vga_out8 (0x3d5, par->CR60);
+	vga_out8 (0x3d4, 0x68);
+	vga_out8 (0x3d5, par->CR68);
+	vga_out8 (0x3d4, 0x69);
+	vga_out8 (0x3d5, par->CR69);
+	vga_out8 (0x3d4, 0x6f);
+	vga_out8 (0x3d5, par->CR6F);
+
+	vga_out8 (0x3d4, 0x33);
+	vga_out8 (0x3d5, par->CR33);
+	vga_out8 (0x3d4, 0x86);
+	vga_out8 (0x3d5, par->CR86);
+	vga_out8 (0x3d4, 0x88);
+	vga_out8 (0x3d5, par->CR88);
+	vga_out8 (0x3d4, 0x90);
+	vga_out8 (0x3d5, par->CR90);
+	vga_out8 (0x3d4, 0x91);
+	vga_out8 (0x3d5, par->CR91);
+
+	if (par->chip == S3_SAVAGE4) {
+		vga_out8 (0x3d4, 0xb0);
+		vga_out8 (0x3d5, par->CRB0);
+	}
+
+	vga_out8 (0x3d4, 0x32);
+	vga_out8 (0x3d5, par->CR32);
+
+	/* unlock extended seq regs */
+	vga_out8 (0x3c4, 0x08);
+	vga_out8 (0x3c5, 0x06);
+
+	/* Restore extended sequencer regs for MCLK. SR10 == 255 indicates
+	 * that we should leave the default SR10 and SR11 values there.
+	 */
+	if (par->SR10 != 255) {
+		vga_out8 (0x3c4, 0x10);
+		vga_out8 (0x3c5, par->SR10);
+		vga_out8 (0x3c4, 0x11);
+		vga_out8 (0x3c5, par->SR11);
+	}
+
+	/* restore extended seq regs for dclk */
+	vga_out8 (0x3c4, 0x0e);
+	vga_out8 (0x3c5, par->SR0E);
+	vga_out8 (0x3c4, 0x0f);
+	vga_out8 (0x3c5, par->SR0F);
+	vga_out8 (0x3c4, 0x12);
+	vga_out8 (0x3c5, par->SR12);
+	vga_out8 (0x3c4, 0x13);
+	vga_out8 (0x3c5, par->SR13);
+	vga_out8 (0x3c4, 0x29);
+	vga_out8 (0x3c5, par->SR29);
+
+	vga_out8 (0x3c4, 0x18);
+	vga_out8 (0x3c5, par->SR18);
+
+	/* load new m, n pll values for dclk & mclk */
+	vga_out8 (0x3c4, 0x15);
+	tmp = vga_in8 (0x3c5) & ~0x21;
+
+	vga_out8 (0x3c5, tmp | 0x03);
+	vga_out8 (0x3c5, tmp | 0x23);
+	vga_out8 (0x3c5, tmp | 0x03);
+	vga_out8 (0x3c5, par->SR15);
+	udelay (100);
+
+	vga_out8 (0x3c4, 0x30);
+	vga_out8 (0x3c5, par->SR30);
+	vga_out8 (0x3c4, 0x08);
+	vga_out8 (0x3c5, par->SR08);
+
+	/* now write out cr67 in full, possibly starting STREAMS */
+	VerticalRetraceWait();
+	vga_out8 (0x3d4, 0x67);
+	vga_out8 (0x3d5, par->CR67);
+
+	vga_out8 (0x3d4, 0x66);
+	cr66 = vga_in8 (0x3d5);
+	vga_out8 (0x3d5, cr66 | 0x80);
+	vga_out8 (0x3d4, 0x3a);
+	cr3a = vga_in8 (0x3d5);
+	vga_out8 (0x3d5, cr3a | 0x80);
+
+	if (par->chip != S3_SAVAGE_MX) {
+		VerticalRetraceWait();
+		savage_out32 (FIFO_CONTROL_REG, par->MMPR0);
+		par->SavageWaitIdle (par);
+		savage_out32 (MIU_CONTROL_REG, par->MMPR1);
+		par->SavageWaitIdle (par);
+		savage_out32 (STREAMS_TIMEOUT_REG, par->MMPR2);
+		par->SavageWaitIdle (par);
+		savage_out32 (MISC_TIMEOUT_REG, par->MMPR3);
+	}
+
+	vga_out8 (0x3d4, 0x66);
+	vga_out8 (0x3d5, cr66);
+	vga_out8 (0x3d4, 0x3a);
+	vga_out8 (0x3d5, cr3a);
+
+	SavageSetup2DEngine (par);
+	vgaHWProtect (par, 0);
+}
+
+static void savagefb_update_start (struct savagefb_par      *par,
+				   struct fb_var_screeninfo *var)
+{
+	int base;
+
+	base = ((var->yoffset * var->xres_virtual + (var->xoffset & ~1))
+		* ((var->bits_per_pixel+7) / 8)) >> 2;
+
+	/* now program the start address registers */
+	vga_out16(0x3d4, (base & 0x00ff00) | 0x0c);
+	vga_out16(0x3d4, ((base & 0x00ff) << 8) | 0x0d);
+	vga_out8 (0x3d4, 0x69);
+	vga_out8 (0x3d5, (base & 0x7f0000) >> 16);
+}
+
+
+static void savagefb_set_fix(struct fb_info *info)
+{
+	info->fix.line_length = info->var.xres_virtual *
+		info->var.bits_per_pixel / 8;
+
+	if (info->var.bits_per_pixel == 8)
+		info->fix.visual      = FB_VISUAL_PSEUDOCOLOR;
+	else
+		info->fix.visual      = FB_VISUAL_TRUECOLOR;
+}
+
+#if defined(CONFIG_FB_SAVAGE_ACCEL)
+static void savagefb_set_clip(struct fb_info *info)
+{
+    struct savagefb_par *par = (struct savagefb_par *)info->par;
+    int cmd;
+
+    cmd = BCI_CMD_NOP | BCI_CMD_CLIP_NEW;
+    par->bci_ptr = 0;
+    par->SavageWaitFifo(par,3);
+    BCI_SEND(cmd);
+    BCI_SEND(BCI_CLIP_TL(0, 0));
+    BCI_SEND(BCI_CLIP_BR(0xfff, 0xfff));
+}
+#endif
+
+static int savagefb_set_par (struct fb_info *info)
+{
+	struct savagefb_par *par = (struct savagefb_par *)info->par;
+	struct fb_var_screeninfo *var = &info->var;
+	int err;
+
+	DBG("savagefb_set_par");
+	err = savagefb_decode_var (var, par);
+	if (err)
+		return err;
+
+	if (par->dacSpeedBpp <= 0) {
+		if (var->bits_per_pixel > 24)
+			par->dacSpeedBpp = par->clock[3];
+		else if (var->bits_per_pixel >= 24)
+			par->dacSpeedBpp = par->clock[2];
+		else if ((var->bits_per_pixel > 8) && (var->bits_per_pixel < 24))
+			par->dacSpeedBpp = par->clock[1];
+		else if (var->bits_per_pixel <= 8)
+			par->dacSpeedBpp = par->clock[0];
+	}
+
+	/* Set ramdac limits */
+	par->maxClock = par->dacSpeedBpp;
+	par->minClock = 10000;
+
+	savagefb_set_par_int (par);
+	savagefb_update_start (par, var);
+	fb_set_cmap (&info->cmap, info);
+	savagefb_set_fix(info);
+	savagefb_set_clip(info);
+
+	SavagePrintRegs();
+	return 0;
+}
+
+/*
+ *    Pan or Wrap the Display
+ */
+static int savagefb_pan_display (struct fb_var_screeninfo *var,
+				 struct fb_info           *info)
+{
+	struct savagefb_par *par = (struct savagefb_par *)info->par;
+	u_int y_bottom;
+
+	y_bottom = var->yoffset;
+
+	if (!(var->vmode & FB_VMODE_YWRAP))
+		y_bottom += var->yres;
+
+	if (var->xoffset > (var->xres_virtual - var->xres))
+		return -EINVAL;
+	if (y_bottom > info->var.yres_virtual)
+		return -EINVAL;
+
+	savagefb_update_start (par, var);
+
+	info->var.xoffset = var->xoffset;
+	info->var.yoffset = var->yoffset;
+
+	if (var->vmode & FB_VMODE_YWRAP)
+		info->var.vmode |= FB_VMODE_YWRAP;
+	else
+		info->var.vmode &= ~FB_VMODE_YWRAP;
+
+	return 0;
+}
+
+
+static struct fb_ops savagefb_ops = {
+	.owner          = THIS_MODULE,
+	.fb_check_var   = savagefb_check_var,
+	.fb_set_par     = savagefb_set_par,
+	.fb_setcolreg   = savagefb_setcolreg,
+	.fb_pan_display = savagefb_pan_display,
+#if defined(CONFIG_FB_SAVAGE_ACCEL)
+	.fb_fillrect    = savagefb_fillrect,
+	.fb_copyarea    = savagefb_copyarea,
+	.fb_imageblit   = savagefb_imageblit,
+	.fb_sync        = savagefb_sync,
+#else
+	.fb_fillrect    = cfb_fillrect,
+	.fb_copyarea    = cfb_copyarea,
+	.fb_imageblit   = cfb_imageblit,
+#endif
+	.fb_cursor      = soft_cursor,
+};
+
+/* --------------------------------------------------------------------- */
+
+static struct fb_var_screeninfo __devinitdata savagefb_var800x600x8 = {
+	.accel_flags =	FB_ACCELF_TEXT,
+	.xres =		800,
+	.yres =		600,
+	.xres_virtual =  800,
+	.yres_virtual =  600,
+	.bits_per_pixel = 8,
+	.pixclock =	25000,
+	.left_margin =	88,
+	.right_margin =	40,
+	.upper_margin =	23,
+	.lower_margin =	1,
+	.hsync_len =	128,
+	.vsync_len =	4,
+	.sync =		FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+	.vmode =	FB_VMODE_NONINTERLACED
+};
+
+static void savage_enable_mmio (struct savagefb_par *par)
+{
+	unsigned char val;
+
+	DBG ("savage_enable_mmio\n");
+
+	val = vga_in8 (0x3c3);
+	vga_out8 (0x3c3, val | 0x01);
+	val = vga_in8 (0x3cc);
+	vga_out8 (0x3c2, val | 0x01);
+
+	if (par->chip >= S3_SAVAGE4) {
+		vga_out8 (0x3d4, 0x40);
+		val = vga_in8 (0x3d5);
+		vga_out8 (0x3d5, val | 1);
+	}
+}
+
+
+static void savage_disable_mmio (struct savagefb_par *par)
+{
+	unsigned char val;
+
+	DBG ("savage_disable_mmio\n");
+
+	if(par->chip >= S3_SAVAGE4 ) {
+		vga_out8 (0x3d4, 0x40);
+		val = vga_in8 (0x3d5);
+		vga_out8 (0x3d5, val | 1);
+	}
+}
+
+
+static int __devinit savage_map_mmio (struct fb_info *info)
+{
+	struct savagefb_par *par = (struct savagefb_par *)info->par;
+	DBG ("savage_map_mmio");
+
+	if (S3_SAVAGE3D_SERIES (par->chip))
+		par->mmio.pbase = pci_resource_start (par->pcidev, 0) +
+			SAVAGE_NEWMMIO_REGBASE_S3;
+	else
+		par->mmio.pbase = pci_resource_start (par->pcidev, 0) +
+			SAVAGE_NEWMMIO_REGBASE_S4;
+
+	par->mmio.len = SAVAGE_NEWMMIO_REGSIZE;
+
+	par->mmio.vbase = ioremap (par->mmio.pbase, par->mmio.len);
+	if (!par->mmio.vbase) {
+		printk ("savagefb: unable to map memory mapped IO\n");
+		return -ENOMEM;
+	} else
+		printk (KERN_INFO "savagefb: mapped io at %p\n",
+			par->mmio.vbase);
+
+	info->fix.mmio_start = par->mmio.pbase;
+	info->fix.mmio_len   = par->mmio.len;
+
+	par->bci_base = (u32*)(par->mmio.vbase + BCI_BUFFER_OFFSET);
+	par->bci_ptr  = 0;
+
+	savage_enable_mmio (par);
+
+	return 0;
+}
+
+static void __devinit savage_unmap_mmio (struct fb_info *info)
+{
+	struct savagefb_par *par = (struct savagefb_par *)info->par;
+	DBG ("savage_unmap_mmio");
+
+	savage_disable_mmio(par);
+
+	if (par->mmio.vbase) {
+		iounmap ((void *)par->mmio.vbase);
+		par->mmio.vbase = NULL;
+	}
+}
+
+static int __devinit savage_map_video (struct fb_info *info,
+				       int video_len)
+{
+	struct savagefb_par *par = (struct savagefb_par *)info->par;
+	int resource;
+
+	DBG("savage_map_video");
+
+	if (S3_SAVAGE3D_SERIES (par->chip))
+		resource = 0;
+	else
+		resource = 1;
+
+	par->video.pbase = pci_resource_start (par->pcidev, resource);
+	par->video.len   = video_len;
+	par->video.vbase = ioremap (par->video.pbase, par->video.len);
+
+	if (!par->video.vbase) {
+		printk ("savagefb: unable to map screen memory\n");
+		return -ENOMEM;
+	} else
+		printk (KERN_INFO "savagefb: mapped framebuffer at %p, "
+			"pbase == %x\n", par->video.vbase, par->video.pbase);
+
+	info->fix.smem_start = par->video.pbase;
+	info->fix.smem_len   = par->video.len - par->cob_size;
+	info->screen_base    = par->video.vbase;
+
+#ifdef CONFIG_MTRR
+	par->video.mtrr = mtrr_add (par->video.pbase, video_len,
+				     MTRR_TYPE_WRCOMB, 1);
+#endif
+
+	/* Clear framebuffer, it's all white in memory after boot */
+	memset (par->video.vbase, 0, par->video.len);
+
+	return 0;
+}
+
+static void __devinit savage_unmap_video (struct fb_info *info)
+{
+	struct savagefb_par *par = (struct savagefb_par *)info->par;
+
+	DBG("savage_unmap_video");
+
+	if (par->video.vbase) {
+#ifdef CONFIG_MTRR
+		mtrr_del (par->video.mtrr, par->video.pbase, par->video.len);
+#endif
+
+		iounmap (par->video.vbase);
+		par->video.vbase = NULL;
+		info->screen_base = NULL;
+	}
+}
+
+static int __devinit savage_init_hw (struct savagefb_par *par)
+{
+	unsigned char config1, m, n, n1, n2, sr8, cr3f, cr66 = 0, tmp;
+
+	static unsigned char RamSavage3D[] = { 8, 4, 4, 2 };
+	static unsigned char RamSavage4[] =  { 2, 4, 8, 12, 16, 32, 64, 32 };
+	static unsigned char RamSavageMX[] = { 2, 8, 4, 16, 8, 16, 4, 16 };
+	static unsigned char RamSavageNB[] = { 0, 2, 4, 8, 16, 32, 2, 2 };
+
+	int videoRam, videoRambytes;
+
+	DBG("savage_init_hw");
+
+	/* unprotect CRTC[0-7] */
+	vga_out8(0x3d4, 0x11);
+	tmp = vga_in8(0x3d5);
+	vga_out8(0x3d5, tmp & 0x7f);
+
+	/* unlock extended regs */
+	vga_out16(0x3d4, 0x4838);
+	vga_out16(0x3d4, 0xa039);
+	vga_out16(0x3c4, 0x0608);
+
+	vga_out8(0x3d4, 0x40);
+	tmp = vga_in8(0x3d5);
+	vga_out8(0x3d5, tmp & ~0x01);
+
+	/* unlock sys regs */
+	vga_out8(0x3d4, 0x38);
+	vga_out8(0x3d5, 0x48);
+
+	/* Unlock system registers. */
+	vga_out16(0x3d4, 0x4838);
+
+	/* Next go on to detect amount of installed ram */
+
+	vga_out8(0x3d4, 0x36);            /* for register CR36 (CONFG_REG1), */
+	config1 = vga_in8(0x3d5);           /* get amount of vram installed */
+
+	/* Compute the amount of video memory and offscreen memory. */
+
+	switch  (par->chip) {
+	case S3_SAVAGE3D:
+		videoRam = RamSavage3D[ (config1 & 0xC0) >> 6 ] * 1024;
+		break;
+
+	case S3_SAVAGE4:
+		/*
+		 * The Savage4 has one ugly special case to consider.  On
+		 * systems with 4 banks of 2Mx32 SDRAM, the BIOS says 4MB
+		 * when it really means 8MB.  Why do it the same when you
+		 * can do it different...
+		 */
+		vga_out8(0x3d4, 0x68);	/* memory control 1 */
+		if( (vga_in8(0x3d5) & 0xC0) == (0x01 << 6) )
+			RamSavage4[1] = 8;
+
+		/*FALLTHROUGH*/
+
+	case S3_SAVAGE2000:
+		videoRam = RamSavage4[ (config1 & 0xE0) >> 5 ] * 1024;
+		break;
+
+	case S3_SAVAGE_MX:
+	case S3_SUPERSAVAGE:
+		videoRam = RamSavageMX[ (config1 & 0x0E) >> 1 ] * 1024;
+		break;
+
+	case S3_PROSAVAGE:
+		videoRam = RamSavageNB[ (config1 & 0xE0) >> 5 ] * 1024;
+		break;
+
+	default:
+		/* How did we get here? */
+		videoRam = 0;
+		break;
+	}
+
+	videoRambytes = videoRam * 1024;
+
+	printk (KERN_INFO "savagefb: probed videoram:  %dk\n", videoRam);
+
+	/* reset graphics engine to avoid memory corruption */
+	vga_out8 (0x3d4, 0x66);
+	cr66 = vga_in8 (0x3d5);
+	vga_out8 (0x3d5, cr66 | 0x02);
+	udelay (10000);
+
+	vga_out8 (0x3d4, 0x66);
+	vga_out8 (0x3d5, cr66 & ~0x02);	/* clear reset flag */
+	udelay (10000);
+
+
+	/*
+	 * reset memory interface, 3D engine, AGP master, PCI master,
+	 * master engine unit, motion compensation/LPB
+	 */
+	vga_out8 (0x3d4, 0x3f);
+	cr3f = vga_in8 (0x3d5);
+	vga_out8 (0x3d5, cr3f | 0x08);
+	udelay (10000);
+
+	vga_out8 (0x3d4, 0x3f);
+	vga_out8 (0x3d5, cr3f & ~0x08);	/* clear reset flags */
+	udelay (10000);
+
+	/* Savage ramdac speeds */
+	par->numClocks = 4;
+	par->clock[0] = 250000;
+	par->clock[1] = 250000;
+	par->clock[2] = 220000;
+	par->clock[3] = 220000;
+
+	/* detect current mclk */
+	vga_out8(0x3c4, 0x08);
+	sr8 = vga_in8(0x3c5);
+	vga_out8(0x3c5, 0x06);
+	vga_out8(0x3c4, 0x10);
+	n = vga_in8(0x3c5);
+	vga_out8(0x3c4, 0x11);
+	m = vga_in8(0x3c5);
+	vga_out8(0x3c4, 0x08);
+	vga_out8(0x3c5, sr8);
+	m &= 0x7f;
+	n1 = n & 0x1f;
+	n2 = (n >> 5) & 0x03;
+	par->MCLK = ((1431818 * (m+2)) / (n1+2) / (1 << n2) + 50) / 100;
+	printk (KERN_INFO "savagefb: Detected current MCLK value of %d kHz\n",
+		par->MCLK);
+
+	/* Check LCD panel parrmation */
+
+	if (par->chip == S3_SAVAGE_MX) {
+		unsigned char cr6b = VGArCR( 0x6b );
+
+		int panelX = (VGArSEQ (0x61) +
+			      ((VGArSEQ (0x66) & 0x02) << 7) + 1) * 8;
+		int panelY = (VGArSEQ (0x69) +
+			      ((VGArSEQ (0x6e) & 0x70) << 4) + 1);
+
+		char * sTechnology = "Unknown";
+
+		/* OK, I admit it.  I don't know how to limit the max dot clock
+		 * for LCD panels of various sizes.  I thought I copied the
+		 * formula from the BIOS, but many users have parrmed me of
+		 * my folly.
+		 *
+		 * Instead, I'll abandon any attempt to automatically limit the
+		 * clock, and add an LCDClock option to XF86Config.  Some day,
+		 * I should come back to this.
+		 */
+
+		enum ACTIVE_DISPLAYS { /* These are the bits in CR6B */
+			ActiveCRT = 0x01,
+			ActiveLCD = 0x02,
+			ActiveTV = 0x04,
+			ActiveCRT2 = 0x20,
+			ActiveDUO = 0x80
+		};
+
+		if ((VGArSEQ (0x39) & 0x03) == 0) {
+			sTechnology = "TFT";
+		} else if ((VGArSEQ (0x30) & 0x01) == 0) {
+			sTechnology = "DSTN";
+		} else 	{
+			sTechnology = "STN";
+		}
+
+		printk (KERN_INFO "savagefb: %dx%d %s LCD panel detected %s\n",
+			panelX, panelY, sTechnology,
+			cr6b & ActiveLCD ? "and active" : "but not active");
+
+		if( cr6b & ActiveLCD ) 	{
+			/*
+			 * If the LCD is active and panel expansion is enabled,
+			 * we probably want to kill the HW cursor.
+			 */
+
+			printk (KERN_INFO "savagefb: Limiting video mode to "
+				"%dx%d\n", panelX, panelY );
+
+			par->SavagePanelWidth = panelX;
+			par->SavagePanelHeight = panelY;
+
+		}
+	}
+
+	savage_get_default_par (par);
+
+	if( S3_SAVAGE4_SERIES(par->chip) ) {
+		/*
+		 * The Savage4 and ProSavage have COB coherency bugs which
+		 * render the buffer useless.  We disable it.
+		 */
+		par->cob_index = 2;
+		par->cob_size = 0x8000 << par->cob_index;
+		par->cob_offset = videoRambytes;
+	} else {
+		/* We use 128kB for the COB on all chips. */
+
+		par->cob_index  = 7;
+		par->cob_size   = 0x400 << par->cob_index;
+		par->cob_offset = videoRambytes - par->cob_size;
+	}
+
+	return videoRambytes;
+}
+
+static int __devinit savage_init_fb_info (struct fb_info *info,
+					  struct pci_dev *dev,
+					  const struct pci_device_id *id)
+{
+	struct savagefb_par *par = (struct savagefb_par *)info->par;
+	int err = 0;
+
+	par->pcidev  = dev;
+
+	info->fix.type	   = FB_TYPE_PACKED_PIXELS;
+	info->fix.type_aux	   = 0;
+	info->fix.xpanstep	   = 2;
+	info->fix.ypanstep	   = 1;
+	info->fix.ywrapstep   = 0;
+	info->fix.accel       = id->driver_data;
+
+	switch (info->fix.accel) {
+	case FB_ACCEL_SUPERSAVAGE:
+		par->chip = S3_SUPERSAVAGE;
+		snprintf (info->fix.id, 16, "SuperSavage");
+		break;
+	case FB_ACCEL_SAVAGE4:
+		par->chip = S3_SAVAGE4;
+		snprintf (info->fix.id, 16, "Savage4");
+		break;
+	case FB_ACCEL_SAVAGE3D:
+		par->chip = S3_SAVAGE3D;
+		snprintf (info->fix.id, 16, "Savage3D");
+		break;
+	case FB_ACCEL_SAVAGE3D_MV:
+		par->chip = S3_SAVAGE3D;
+		snprintf (info->fix.id, 16, "Savage3D-MV");
+		break;
+	case FB_ACCEL_SAVAGE2000:
+		par->chip = S3_SAVAGE2000;
+		snprintf (info->fix.id, 16, "Savage2000");
+		break;
+	case FB_ACCEL_SAVAGE_MX_MV:
+		par->chip = S3_SAVAGE_MX;
+		snprintf (info->fix.id, 16, "Savage/MX-MV");
+		break;
+	case FB_ACCEL_SAVAGE_MX:
+		par->chip = S3_SAVAGE_MX;
+		snprintf (info->fix.id, 16, "Savage/MX");
+		break;
+	case FB_ACCEL_SAVAGE_IX_MV:
+		par->chip = S3_SAVAGE_MX;
+		snprintf (info->fix.id, 16, "Savage/IX-MV");
+		break;
+	case FB_ACCEL_SAVAGE_IX:
+		par->chip = S3_SAVAGE_MX;
+		snprintf (info->fix.id, 16, "Savage/IX");
+		break;
+	case FB_ACCEL_PROSAVAGE_PM:
+		par->chip = S3_PROSAVAGE;
+		snprintf (info->fix.id, 16, "ProSavagePM");
+		break;
+	case FB_ACCEL_PROSAVAGE_KM:
+		par->chip = S3_PROSAVAGE;
+		snprintf (info->fix.id, 16, "ProSavageKM");
+		break;
+	case FB_ACCEL_S3TWISTER_P:
+		par->chip = S3_PROSAVAGE;
+		snprintf (info->fix.id, 16, "TwisterP");
+		break;
+	case FB_ACCEL_S3TWISTER_K:
+		par->chip = S3_PROSAVAGE;
+		snprintf (info->fix.id, 16, "TwisterK");
+		break;
+	case FB_ACCEL_PROSAVAGE_DDR:
+		par->chip = S3_PROSAVAGE;
+		snprintf (info->fix.id, 16, "ProSavageDDR");
+		break;
+	case FB_ACCEL_PROSAVAGE_DDRK:
+		par->chip = S3_PROSAVAGE;
+		snprintf (info->fix.id, 16, "ProSavage8");
+		break;
+	}
+
+	if (S3_SAVAGE3D_SERIES(par->chip)) {
+		par->SavageWaitIdle = savage3D_waitidle;
+		par->SavageWaitFifo = savage3D_waitfifo;
+	} else if (S3_SAVAGE4_SERIES(par->chip) ||
+		   S3_SUPERSAVAGE == par->chip) {
+		par->SavageWaitIdle = savage4_waitidle;
+		par->SavageWaitFifo = savage4_waitfifo;
+	} else {
+		par->SavageWaitIdle = savage2000_waitidle;
+		par->SavageWaitFifo = savage2000_waitfifo;
+	}
+
+	info->var.nonstd      = 0;
+	info->var.activate    = FB_ACTIVATE_NOW;
+	info->var.width       = -1;
+	info->var.height      = -1;
+	info->var.accel_flags = 0;
+
+	info->fbops          = &savagefb_ops;
+	info->flags          = FBINFO_DEFAULT |
+		               FBINFO_HWACCEL_YPAN |
+		               FBINFO_HWACCEL_XPAN |
+	                       FBINFO_MISC_MODESWITCHLATE;
+
+	info->pseudo_palette = par->pseudo_palette;
+
+#if defined(CONFIG_FB_SAVAGE_ACCEL)
+	/* FIFO size + padding for commands */
+	info->pixmap.addr = kmalloc(8*1024, GFP_KERNEL);
+
+	err = -ENOMEM;
+	if (info->pixmap.addr) {
+		memset(info->pixmap.addr, 0, 8*1024);
+		info->pixmap.size = 8*1024;
+		info->pixmap.scan_align = 4;
+		info->pixmap.buf_align = 4;
+		info->pixmap.access_align = 4;
+
+		fb_alloc_cmap (&info->cmap, NR_PALETTE, 0);
+		info->flags |= FBINFO_HWACCEL_COPYAREA |
+	                       FBINFO_HWACCEL_FILLRECT |
+		               FBINFO_HWACCEL_IMAGEBLIT;
+
+		err = 0;
+	}
+#endif
+	return err;
+}
+
+/* --------------------------------------------------------------------- */
+
+static int __devinit savagefb_probe (struct pci_dev* dev,
+				     const struct pci_device_id* id)
+{
+	struct fb_info *info;
+	struct savagefb_par *par;
+	u_int h_sync, v_sync;
+	int err, lpitch;
+	int video_len;
+
+	DBG("savagefb_probe");
+	SavagePrintRegs();
+
+	info = framebuffer_alloc(sizeof(struct savagefb_par), &dev->dev);
+	if (!info)
+		return -ENOMEM;
+	par = info->par;
+	err = pci_enable_device(dev);
+	if (err)
+		goto failed_enable;
+
+	if (pci_request_regions(dev, "savagefb")) {
+		printk(KERN_ERR "cannot request PCI regions\n");
+		goto failed_enable;
+	}
+
+	err = -ENOMEM;
+
+	if (savage_init_fb_info(info, dev, id))
+		goto failed_init;
+
+	err = savage_map_mmio(info);
+	if (err)
+		goto failed_mmio;
+
+	video_len = savage_init_hw(par);
+	if (video_len < 0) {
+		err = video_len;
+		goto failed_mmio;
+	}
+
+	err = savage_map_video(info, video_len);
+	if (err)
+		goto failed_video;
+
+	INIT_LIST_HEAD(&info->modelist);
+#if defined(CONFIG_FB_SAVAGE_I2C)
+	savagefb_create_i2c_busses(info);
+	savagefb_probe_i2c_connector(par, &par->edid);
+	fb_edid_to_monspecs(par->edid, &info->monspecs);
+	fb_videomode_to_modelist(info->monspecs.modedb,
+				 info->monspecs.modedb_len,
+				 &info->modelist);
+#endif
+	info->var = savagefb_var800x600x8;
+
+	if (mode_option) {
+		fb_find_mode(&info->var, info, mode_option,
+			     info->monspecs.modedb, info->monspecs.modedb_len,
+			     NULL, 8);
+	} else if (info->monspecs.modedb != NULL) {
+		struct fb_monspecs *specs = &info->monspecs;
+		struct fb_videomode modedb;
+
+		if (info->monspecs.misc & FB_MISC_1ST_DETAIL) {
+			int i;
+
+			for (i = 0; i < specs->modedb_len; i++) {
+				if (specs->modedb[i].flag & FB_MODE_IS_FIRST) {
+					modedb = specs->modedb[i];
+					break;
+				}
+			}
+		} else {
+			/* otherwise, get first mode in database */
+			modedb = specs->modedb[0];
+		}
+
+		savage_update_var(&info->var, &modedb);
+	}
+
+	/* maximize virtual vertical length */
+	lpitch = info->var.xres_virtual*((info->var.bits_per_pixel + 7) >> 3);
+	info->var.yres_virtual = info->fix.smem_len/lpitch;
+
+	if (info->var.yres_virtual < info->var.yres)
+		goto failed;
+
+#if defined(CONFIG_FB_SAVAGE_ACCEL)
+	/*
+	 * The clipping coordinates are masked with 0xFFF, so limit our
+	 * virtual resolutions to these sizes.
+	 */
+	if (info->var.yres_virtual > 0x1000)
+		info->var.yres_virtual = 0x1000;
+
+	if (info->var.xres_virtual > 0x1000)
+		info->var.xres_virtual = 0x1000;
+#endif
+	savagefb_check_var(&info->var, info);
+	savagefb_set_fix(info);
+
+	/*
+	 * Calculate the hsync and vsync frequencies.  Note that
+	 * we split the 1e12 constant up so that we can preserve
+	 * the precision and fit the results into 32-bit registers.
+	 *  (1953125000 * 512 = 1e12)
+	 */
+	h_sync = 1953125000 / info->var.pixclock;
+	h_sync = h_sync * 512 / (info->var.xres + info->var.left_margin +
+				 info->var.right_margin +
+				 info->var.hsync_len);
+	v_sync = h_sync / (info->var.yres + info->var.upper_margin +
+			   info->var.lower_margin + info->var.vsync_len);
+
+	printk(KERN_INFO "savagefb v" SAVAGEFB_VERSION ": "
+	       "%dkB VRAM, using %dx%d, %d.%03dkHz, %dHz\n",
+	       info->fix.smem_len >> 10,
+	       info->var.xres, info->var.yres,
+	       h_sync / 1000, h_sync % 1000, v_sync);
+
+
+	fb_destroy_modedb(info->monspecs.modedb);
+	info->monspecs.modedb = NULL;
+
+	err = register_framebuffer (info);
+	if (err < 0)
+		goto failed;
+
+	printk (KERN_INFO "fb: S3 %s frame buffer device\n",
+		info->fix.id);
+
+	/*
+	 * Our driver data
+	 */
+	pci_set_drvdata(dev, info);
+
+	return 0;
+
+ failed:
+#ifdef CONFIG_FB_SAVAGE_I2C
+	savagefb_delete_i2c_busses(info);
+#endif
+	fb_alloc_cmap (&info->cmap, 0, 0);
+	savage_unmap_video(info);
+ failed_video:
+	savage_unmap_mmio (info);
+ failed_mmio:
+	kfree(info->pixmap.addr);
+ failed_init:
+	pci_release_regions(dev);
+ failed_enable:
+	framebuffer_release(info);
+
+	return err;
+}
+
+static void __devexit savagefb_remove (struct pci_dev *dev)
+{
+	struct fb_info *info =
+		(struct fb_info *)pci_get_drvdata(dev);
+
+	DBG("savagefb_remove");
+
+	if (info) {
+		/*
+		 * If unregister_framebuffer fails, then
+		 * we will be leaving hooks that could cause
+		 * oopsen laying around.
+		 */
+		if (unregister_framebuffer (info))
+			printk (KERN_WARNING "savagefb: danger danger! "
+				"Oopsen imminent!\n");
+
+#ifdef CONFIG_FB_SAVAGE_I2C
+		savagefb_delete_i2c_busses(info);
+#endif
+		fb_alloc_cmap (&info->cmap, 0, 0);
+		savage_unmap_video (info);
+		savage_unmap_mmio (info);
+		kfree(info->pixmap.addr);
+		pci_release_regions(dev);
+		framebuffer_release(info);
+
+		/*
+		 * Ensure that the driver data is no longer
+		 * valid.
+		 */
+		pci_set_drvdata(dev, NULL);
+	}
+}
+
+static int savagefb_suspend (struct pci_dev* dev, u32 state)
+{
+	struct fb_info *info =
+		(struct fb_info *)pci_get_drvdata(dev);
+	struct savagefb_par *par = (struct savagefb_par *)info->par;
+
+	DBG("savagefb_suspend");
+	printk(KERN_DEBUG "state: %u\n", state);
+
+	acquire_console_sem();
+	fb_set_suspend(info, state);
+	savage_disable_mmio(par);
+	release_console_sem();
+
+	pci_disable_device(dev);
+	pci_set_power_state(dev, state);
+
+	return 0;
+}
+
+static int savagefb_resume (struct pci_dev* dev)
+{
+	struct fb_info *info =
+		(struct fb_info *)pci_get_drvdata(dev);
+	struct savagefb_par *par = (struct savagefb_par *)info->par;
+
+	DBG("savage_resume");
+
+	pci_set_power_state(dev, 0);
+	pci_restore_state(dev);
+	if(pci_enable_device(dev))
+		DBG("err");
+
+	SavagePrintRegs();
+
+	acquire_console_sem();
+
+	savage_enable_mmio(par);
+	savage_init_hw(par);
+	savagefb_set_par (info);
+
+	fb_set_suspend (info, 0);
+	release_console_sem();
+
+	return 0;
+}
+
+
+static struct pci_device_id savagefb_devices[] __devinitdata = {
+	{PCI_VENDOR_ID_S3, PCI_CHIP_SUPSAV_MX128,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_SUPERSAVAGE},
+
+	{PCI_VENDOR_ID_S3, PCI_CHIP_SUPSAV_MX64,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_SUPERSAVAGE},
+
+	{PCI_VENDOR_ID_S3, PCI_CHIP_SUPSAV_MX64C,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_SUPERSAVAGE},
+
+	{PCI_VENDOR_ID_S3, PCI_CHIP_SUPSAV_IX128SDR,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_SUPERSAVAGE},
+
+	{PCI_VENDOR_ID_S3, PCI_CHIP_SUPSAV_IX128DDR,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_SUPERSAVAGE},
+
+	{PCI_VENDOR_ID_S3, PCI_CHIP_SUPSAV_IX64SDR,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_SUPERSAVAGE},
+
+	{PCI_VENDOR_ID_S3, PCI_CHIP_SUPSAV_IX64DDR,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_SUPERSAVAGE},
+
+	{PCI_VENDOR_ID_S3, PCI_CHIP_SUPSAV_IXCSDR,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_SUPERSAVAGE},
+
+	{PCI_VENDOR_ID_S3, PCI_CHIP_SUPSAV_IXCDDR,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_SUPERSAVAGE},
+
+	{PCI_VENDOR_ID_S3, PCI_CHIP_SAVAGE4,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_SAVAGE4},
+
+	{PCI_VENDOR_ID_S3, PCI_CHIP_SAVAGE3D,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_SAVAGE3D},
+
+	{PCI_VENDOR_ID_S3, PCI_CHIP_SAVAGE3D_MV,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_SAVAGE3D_MV},
+
+	{PCI_VENDOR_ID_S3, PCI_CHIP_SAVAGE2000,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_SAVAGE2000},
+
+	{PCI_VENDOR_ID_S3, PCI_CHIP_SAVAGE_MX_MV,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_SAVAGE_MX_MV},
+
+	{PCI_VENDOR_ID_S3, PCI_CHIP_SAVAGE_MX,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_SAVAGE_MX},
+
+	{PCI_VENDOR_ID_S3, PCI_CHIP_SAVAGE_IX_MV,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_SAVAGE_IX_MV},
+
+	{PCI_VENDOR_ID_S3, PCI_CHIP_SAVAGE_IX,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_SAVAGE_IX},
+
+	{PCI_VENDOR_ID_S3, PCI_CHIP_PROSAVAGE_PM,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_PROSAVAGE_PM},
+
+	{PCI_VENDOR_ID_S3, PCI_CHIP_PROSAVAGE_KM,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_PROSAVAGE_KM},
+
+	{PCI_VENDOR_ID_S3, PCI_CHIP_S3TWISTER_P,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_S3TWISTER_P},
+
+	{PCI_VENDOR_ID_S3, PCI_CHIP_S3TWISTER_K,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_S3TWISTER_K},
+
+	{PCI_VENDOR_ID_S3, PCI_CHIP_PROSAVAGE_DDR,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_PROSAVAGE_DDR},
+
+	{PCI_VENDOR_ID_S3, PCI_CHIP_PROSAVAGE_DDRK,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_PROSAVAGE_DDRK},
+
+	{0, 0, 0, 0, 0, 0, 0}
+};
+
+MODULE_DEVICE_TABLE(pci, savagefb_devices);
+
+static struct pci_driver savagefb_driver = {
+	.name =     "savagefb",
+	.id_table = savagefb_devices,
+	.probe =    savagefb_probe,
+	.suspend =  savagefb_suspend,
+	.resume =   savagefb_resume,
+	.remove =   __devexit_p(savagefb_remove)
+};
+
+/* **************************** exit-time only **************************** */
+
+static void __exit savage_done (void)
+{
+	DBG("savage_done");
+	pci_unregister_driver (&savagefb_driver);
+}
+
+
+/* ************************* init in-kernel code ************************** */
+
+static int __init savagefb_setup(char *options)
+{
+#ifndef MODULE
+	char *this_opt;
+
+	if (!options || !*options)
+		return 0;
+
+	while ((this_opt = strsep(&options, ",")) != NULL) {
+		mode_option = this_opt;
+	}
+#endif /* !MODULE */
+	return 0;
+}
+
+static int __init savagefb_init(void)
+{
+	char *option;
+
+	DBG("savagefb_init");
+
+	if (fb_get_options("savagefb", &option))
+		return -ENODEV;
+
+	savagefb_setup(option);
+	return pci_register_driver (&savagefb_driver);
+
+}
+
+module_init(savagefb_init);
+module_exit(savage_done);
diff -Nru a/drivers/video/sis/sis_main.c b/drivers/video/sis/sis_main.c
--- a/drivers/video/sis/sis_main.c	2005-03-11 12:51:47 -08:00
+++ b/drivers/video/sis/sis_main.c	2005-03-11 12:51:47 -08:00
@@ -50,6 +50,7 @@
 #include <linux/fb.h>
 #include <linux/console.h>
 #include <linux/selection.h>
+#include <linux/smp_lock.h>
 #include <linux/ioport.h>
 #include <linux/init.h>
 #include <linux/pci.h>
@@ -144,7 +145,7 @@
 #endif
 }
 
-static void __init
+static void __devinit
 sisfb_search_vesamode(unsigned int vesamode, BOOLEAN quiet)
 {
 	int i = 0, j = 0;
@@ -5939,7 +5940,7 @@
 #endif
 #endif
 
-int __init sisfb_init_module(void)
+int __devinit sisfb_init_module(void)
 {
 	sisfb_setdefaultparms();
 
diff -Nru a/drivers/video/skeletonfb.c b/drivers/video/skeletonfb.c
--- a/drivers/video/skeletonfb.c	2005-03-11 12:51:41 -08:00
+++ b/drivers/video/skeletonfb.c	2005-03-11 12:51:41 -08:00
@@ -120,7 +120,7 @@
 static struct fb_info info;
 
     /* 
-     * Each one represents the a state of the hardware. Most hardware have 
+     * Each one represents the state of the hardware. Most hardware have
      * just one hardware state. These here represent the default state(s). 
      */
 static struct xxx_par __initdata current_par;
@@ -139,6 +139,8 @@
  *	Usually you don't need to provide this function. The case where it 
  *	is used is to change from a text mode hardware state to a graphics
  * 	mode state. 
+ *
+ *	Returns negative errno on error, or zero on success.
  */
 static int xxxfb_open(const struct fb_info *info, int user)
 {
@@ -156,6 +158,8 @@
  *	console system is released. Usually you don't need this function.
  *	The case where it is usually used is to go from a graphics state
  *	to a text mode state.
+ *
+ *	Returns negative errno on error, or zero on success.
  */
 static int xxxfb_release(const struct fb_info *info, int user)
 {
@@ -201,8 +205,9 @@
  *	fb_info since we are using that data. This means we depend on the
  *	data in var inside fb_info to be supported by the hardware. 
  *	xxxfb_check_var is always called before xxxfb_set_par to ensure this.
- *	Again if you can't can't the resolution you don't need this function.
+ *	Again if you can't change the resolution you don't need this function.
  *
+ *	Returns negative errno on error, or zero on success.
  */
 static int xxxfb_set_par(struct fb_info *info)
 {
@@ -217,14 +222,14 @@
  *      @red: The red value which can be up to 16 bits wide 
  *	@green: The green value which can be up to 16 bits wide 
  *	@blue:  The blue value which can be up to 16 bits wide.
- *	@transp: If supported the alpha value which can be up to 16 bits wide.	
+ *	@transp: If supported, the alpha value which can be up to 16 bits wide.
  *      @info: frame buffer info structure
  * 
  *  	Set a single color register. The values supplied have a 16 bit
  *  	magnitude which needs to be scaled in this function for the hardware. 
  *	Things to take into consideration are how many color registers, if
  *	any, are supported with the current color visual. With truecolor mode
- *	no color palettes are supported. Here a psuedo palette is created 
+ *	no color palettes are supported. Here a pseudo palette is created
  *	which we store the value in pseudo_palette in struct fb_info. For
  *	pseudocolor mode we have a limited color palette. To deal with this
  *	we can program what color is displayed for a particular pixel value.
@@ -238,7 +243,7 @@
 			   const struct fb_info *info)
 {
     if (regno >= 256)  /* no. of hw registers */
-       return 1;
+       return -EINVAL;
     /*
      * Program hardware... do anything you want with transp
      */
@@ -295,7 +300,7 @@
        u32 v;
 
        if (regno >= 16)
-           return 1;
+           return -EINVAL;
 
        v = (red << info->var.red.offset) |
            (green << info->var.green.offset) |
@@ -563,7 +568,7 @@
 #endif
 
     /* 
-     * Here we set the screen_base to the vitrual memory address
+     * Here we set the screen_base to the virtual memory address
      * for the framebuffer. Usually we obtain the resource address
      * from the bus layer and then translate it to virtual memory
      * space via ioremap. Consult ioport.h. 
@@ -621,6 +626,7 @@
      */
 
     unregister_framebuffer(info);
+    fb_dealloc_cmap(&info.cmap);
     /* ... */
 }
 
diff -Nru a/drivers/video/sun3fb.c b/drivers/video/sun3fb.c
--- a/drivers/video/sun3fb.c	2005-03-11 12:51:52 -08:00
+++ b/drivers/video/sun3fb.c	2005-03-11 12:51:52 -08:00
@@ -505,7 +505,7 @@
 			if (fb->restore_palette) {
 				if (enter)
 					fb->restore_palette(fb);
-				else if (vt_cons[i]->vc_mode != KD_GRAPHICS)
+				else if (vc_cons[i].d->vc_mode != KD_GRAPHICS)
 				         vc_cons[i].d->vc_sw->con_set_palette(vc_cons[i].d, color_table);
 			}
 		}
diff -Nru a/drivers/video/tdfxfb.c b/drivers/video/tdfxfb.c
--- a/drivers/video/tdfxfb.c	2005-03-11 12:51:42 -08:00
+++ b/drivers/video/tdfxfb.c	2005-03-11 12:51:42 -08:00
@@ -89,7 +89,7 @@
 #define VOODOO3_MAX_PIXCLOCK 300000
 #define VOODOO5_MAX_PIXCLOCK 350000
 
-static struct fb_fix_screeninfo tdfx_fix __initdata = {
+static struct fb_fix_screeninfo tdfx_fix __devinitdata = {
 	.id =		"3Dfx",
 	.type =		FB_TYPE_PACKED_PIXELS,
 	.visual =	FB_VISUAL_PSEUDOCOLOR, 
@@ -98,7 +98,7 @@
 	.accel =	FB_ACCEL_3DFX_BANSHEE
 };
 
-static struct fb_var_screeninfo tdfx_var __initdata = {
+static struct fb_var_screeninfo tdfx_var __devinitdata = {
 	/* "640x480, 8 bpp @ 60 Hz */
 	.xres =		640,
 	.yres =		480,
@@ -154,9 +154,6 @@
 /*
  *  Frame buffer device API
  */
-int tdfxfb_init(void);
-void tdfxfb_setup(char *options);
-
 static int tdfxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *fb); 
 static int tdfxfb_set_par(struct fb_info *info); 
 static int tdfxfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, 
@@ -202,7 +199,7 @@
  */
 static int  nopan   = 0;
 static int  nowrap  = 1;      // not implemented (yet)
-static char *mode_option __initdata = NULL;
+static char *mode_option __devinitdata = NULL;
 
 /* ------------------------------------------------------------------------- 
  *                      Hardware-specific funcions
@@ -1292,6 +1289,28 @@
 	return -ENXIO;
 }
 
+#ifndef MODULE
+void tdfxfb_setup(char *options)
+{
+	char* this_opt;
+
+	if (!options || !*options)
+		return;
+
+	while ((this_opt = strsep(&options, ",")) != NULL) {
+		if (!*this_opt)
+			continue;
+		if(!strcmp(this_opt, "nopan")) {
+			nopan = 1;
+		} else if(!strcmp(this_opt, "nowrap")) {
+			nowrap = 1;
+		} else {
+			mode_option = this_opt;
+		}
+	}
+}
+#endif
+
 /**
  *      tdfxfb_remove - Device removal
  *
@@ -1321,7 +1340,7 @@
 	framebuffer_release(info);
 }
 
-int __init tdfxfb_init(void)
+static int __init tdfxfb_init(void)
 {
 #ifndef MODULE
 	char *option = NULL;
@@ -1345,27 +1364,3 @@
  
 module_init(tdfxfb_init);
 module_exit(tdfxfb_exit);
-
-
-#ifndef MODULE
-void tdfxfb_setup(char *options)
-{ 
-	char* this_opt;
-
-	if (!options || !*options)
-		return;
-
-	while ((this_opt = strsep(&options, ",")) != NULL) {	
-		if (!*this_opt)
-			continue;
-		if(!strcmp(this_opt, "nopan")) {
-			nopan = 1;
-		} else if(!strcmp(this_opt, "nowrap")) {
-			nowrap = 1;
-		} else {
-			mode_option = this_opt;
-		}
-	} 
-}
-#endif
-
diff -Nru a/drivers/video/tridentfb.c b/drivers/video/tridentfb.c
--- a/drivers/video/tridentfb.c	2005-03-11 12:51:46 -08:00
+++ b/drivers/video/tridentfb.c	2005-03-11 12:51:46 -08:00
@@ -31,7 +31,7 @@
 	void __iomem * io_virt;	//iospace virtual memory address
 };
 
-unsigned char eng_oper;		//engine operation...
+static unsigned char eng_oper;		//engine operation...
 static struct fb_ops tridentfb_ops;
 
 static struct tridentfb_par default_par;
@@ -91,7 +91,7 @@
 static int chip3D;
 static int chipcyber;
 
-int is3Dchip(int id)
+static int is3Dchip(int id)
 {
 	return 	((id == BLADE3D) || (id == CYBERBLADEE4) ||
 		 (id == CYBERBLADEi7) || (id == CYBERBLADEi7D) ||
@@ -104,7 +104,7 @@
 		 (id ==	CYBERBLADEXPAi1));
 }
 
-int iscyber(int id)
+static int iscyber(int id)
 {
 	switch (id) {
 		case CYBER9388:		
@@ -1216,33 +1216,13 @@
 	.remove		= __devexit_p(trident_pci_remove)
 };
 
-int tridentfb_setup(char *options);
-
-int __init tridentfb_init(void)
-{
-#ifndef MODULE
-	char *option = NULL;
-
-	if (fb_get_options("tridentfb", &option))
-		return -ENODEV;
-	tridentfb_setup(option);
-#endif
-	output("Trident framebuffer %s initializing\n", VERSION);
-	return pci_module_init(&tridentfb_pci_driver);
-}
-
-void __exit tridentfb_exit(void)
-{
-	pci_unregister_driver(&tridentfb_pci_driver);
-}
-
-
 /*
  * Parse user specified options (`video=trident:')
  * example:
  * 	video=trident:800x600,bpp=16,noaccel
  */
-int tridentfb_setup(char *options)
+#ifndef MODULE
+static int tridentfb_setup(char *options)
 {
 	char * opt;
 	if (!options || !*options)
@@ -1271,6 +1251,25 @@
 			mode = opt;
 	}
 	return 0;
+}
+#endif
+
+static int __init tridentfb_init(void)
+{
+#ifndef MODULE
+	char *option = NULL;
+
+	if (fb_get_options("tridentfb", &option))
+		return -ENODEV;
+	tridentfb_setup(option);
+#endif
+	output("Trident framebuffer %s initializing\n", VERSION);
+	return pci_module_init(&tridentfb_pci_driver);
+}
+
+static void __exit tridentfb_exit(void)
+{
+	pci_unregister_driver(&tridentfb_pci_driver);
 }
 
 static struct fb_ops tridentfb_ops = {
diff -Nru a/drivers/video/vesafb.c b/drivers/video/vesafb.c
--- a/drivers/video/vesafb.c	2005-03-11 12:51:41 -08:00
+++ b/drivers/video/vesafb.c	2005-03-11 12:51:41 -08:00
@@ -185,7 +185,7 @@
 	.fb_cursor	= soft_cursor,
 };
 
-int __init vesafb_setup(char *options)
+static int __init vesafb_setup(char *options)
 {
 	char *this_opt;
 	
@@ -434,7 +434,7 @@
 	.name	= "vesafb",
 };
 
-int __init vesafb_init(void)
+static int __init vesafb_init(void)
 {
 	int ret;
 	char *option = NULL;
@@ -452,13 +452,5 @@
 	return ret;
 }
 module_init(vesafb_init);
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
 
 MODULE_LICENSE("GPL");
diff -Nru a/drivers/video/vfb.c b/drivers/video/vfb.c
--- a/drivers/video/vfb.c	2005-03-11 12:51:40 -08:00
+++ b/drivers/video/vfb.c	2005-03-11 12:51:40 -08:00
@@ -72,12 +72,6 @@
 static int vfb_enable __initdata = 0;	/* disabled by default */
 module_param(vfb_enable, bool, 0);
 
-    /*
-     *  Interface used by the world
-     */
-int vfb_init(void);
-int vfb_setup(char *);
-
 static int vfb_check_var(struct fb_var_screeninfo *var,
 			 struct fb_info *info);
 static int vfb_set_par(struct fb_info *info);
@@ -379,7 +373,8 @@
 	return -EINVAL;
 }
 
-int __init vfb_setup(char *options)
+#ifndef MODULE
+static int __init vfb_setup(char *options)
 {
 	char *this_opt;
 
@@ -396,6 +391,7 @@
 	}
 	return 1;
 }
+#endif  /*  MODULE  */
 
     /*
      *  Initialisation
@@ -492,7 +488,7 @@
 	}
 };
 
-int __init vfb_init(void)
+static int __init vfb_init(void)
 {
 	int ret = 0;
 
diff -Nru a/drivers/video/w100fb.c b/drivers/video/w100fb.c
--- a/drivers/video/w100fb.c	2005-03-11 12:51:50 -08:00
+++ b/drivers/video/w100fb.c	2005-03-11 12:51:50 -08:00
@@ -22,7 +22,6 @@
 #include <linux/device.h>
 #include <linux/string.h>
 #include <linux/proc_fs.h>
-#include <linux/vmalloc.h>
 #include <asm/io.h>
 #include <asm/uaccess.h>
 #include <video/w100fb.h>
@@ -90,8 +89,6 @@
 
 static struct w100fb_par *current_par;
 
-static u16 *gSaveImagePtr = NULL;
-
 /* Remapped addresses for base cfg, memmapped regs and the frame buffer itself */
 static void *remapped_base;
 static void *remapped_regs;
@@ -494,42 +491,56 @@
 }
 
 
+/* Need to split up the buffers to stay within the limits of kmalloc */
+#define W100_BUF_NUM	6
+static uint32_t *gSaveImagePtr[W100_BUF_NUM] = { NULL };
+
 static void w100fb_save_buffer(void)
 {
-	int i;
+	int i, j, bufsize;
 
-	if (gSaveImagePtr != NULL) {
-		vfree(gSaveImagePtr);
-		gSaveImagePtr = NULL;
-	}
-	gSaveImagePtr = vmalloc(current_par->xres * current_par->yres * BITS_PER_PIXEL / 8);
-	if (gSaveImagePtr != NULL) {
-		for (i = 0; i < (current_par->xres * current_par->yres); i++)
-			*(gSaveImagePtr + i) = readw(remapped_fbuf + (2*i));
-	} else {
-		printk(KERN_WARNING "can't alloc pre-off image buffer\n");
+	bufsize=(current_par->xres * current_par->yres * BITS_PER_PIXEL / 8) / W100_BUF_NUM;
+	for (i = 0; i < W100_BUF_NUM; i++) {
+		if (gSaveImagePtr[i] == NULL)
+			gSaveImagePtr[i] = kmalloc(bufsize, GFP_KERNEL);
+		if (gSaveImagePtr[i] == NULL) {
+			w100fb_clear_buffer();
+			printk(KERN_WARNING "can't alloc pre-off image buffer %d\n", i);
+			break;
+		}
+		for (j = 0; j < bufsize/4; j++)
+			*(gSaveImagePtr[i] + j) = readl(remapped_fbuf + (bufsize*i) + j*4);
 	}
 }
 
 
 static void w100fb_restore_buffer(void)
 {
-	int i;
+	int i, j, bufsize;
 
-	if (gSaveImagePtr != NULL) {
-		for (i = 0; i < (current_par->xres * current_par->yres); i++) {
-				writew(*(gSaveImagePtr + i),remapped_fbuf + (2*i));
-			}
-		vfree(gSaveImagePtr);
-		gSaveImagePtr = NULL;
+	bufsize=(current_par->xres * current_par->yres * BITS_PER_PIXEL / 8) / W100_BUF_NUM;
+	for (i = 0; i < W100_BUF_NUM; i++) {
+		if (gSaveImagePtr[i] == NULL) {
+			printk(KERN_WARNING "can't find pre-off image buffer %d\n", i);
+			w100fb_clear_buffer();
+			break;
+		}
+		for (j = 0; j < (bufsize/4); j++)
+			writel(*(gSaveImagePtr[i] + j),remapped_fbuf + (bufsize*i) + (j*4));
+		kfree(gSaveImagePtr[i]);
+		gSaveImagePtr[i] = NULL;
 	}
 }
 
+
 static void w100fb_clear_buffer(void)
 {
-	if (gSaveImagePtr != NULL) {
-		vfree(gSaveImagePtr);
-		gSaveImagePtr = NULL;
+	int i;
+	for (i = 0; i < W100_BUF_NUM; i++) {
+		if (gSaveImagePtr[i] != NULL) {
+			kfree(gSaveImagePtr[i]);
+			gSaveImagePtr[i] = NULL;
+		}
 	}
 }
 
diff -Nru a/drivers/w1/dscore.c b/drivers/w1/dscore.c
--- a/drivers/w1/dscore.c	2005-03-11 12:51:51 -08:00
+++ b/drivers/w1/dscore.c	2005-03-11 12:51:51 -08:00
@@ -45,9 +45,6 @@
 int ds_reset(struct ds_device *, struct ds_status *);
 int ds_detect(struct ds_device *, struct ds_status *);
 int ds_stop_pulse(struct ds_device *, int);
-int ds_send_data(struct ds_device *, unsigned char *, int);
-int ds_recv_data(struct ds_device *, unsigned char *, int);
-int ds_recv_status(struct ds_device *, struct ds_status *);
 struct ds_device * ds_get_device(void);
 void ds_put_device(struct ds_device *);
 
@@ -84,7 +81,7 @@
 	int err;
 	
 	err = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, dev->ep[EP_CONTROL]), 
-			CONTROL_CMD, 0x40, value, index, NULL, 0, HZ);
+			CONTROL_CMD, 0x40, value, index, NULL, 0, 1000);
 	if (err < 0) {
 		printk(KERN_ERR "Failed to send command control message %x.%x: err=%d.\n", 
 				value, index, err);
@@ -99,7 +96,7 @@
 	int err;
 	
 	err = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, dev->ep[EP_CONTROL]), 
-			MODE_CMD, 0x40, value, index, NULL, 0, HZ);
+			MODE_CMD, 0x40, value, index, NULL, 0, 1000);
 	if (err < 0) {
 		printk(KERN_ERR "Failed to send mode control message %x.%x: err=%d.\n", 
 				value, index, err);
@@ -114,7 +111,7 @@
 	int err;
 	
 	err = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, dev->ep[EP_CONTROL]), 
-			COMM_CMD, 0x40, value, index, NULL, 0, HZ);
+			COMM_CMD, 0x40, value, index, NULL, 0, 1000);
 	if (err < 0) {
 		printk(KERN_ERR "Failed to send control message %x.%x: err=%d.\n", 
 				value, index, err);
@@ -148,7 +145,7 @@
 	return count;
 }
 
-int ds_recv_status(struct ds_device *dev, struct ds_status *st)
+static int ds_recv_status(struct ds_device *dev, struct ds_status *st)
 {
 	unsigned char buf[64];
 	int count, err = 0, i;
@@ -206,14 +203,14 @@
 	return err;
 }
 
-int ds_recv_data(struct ds_device *dev, unsigned char *buf, int size)
+static int ds_recv_data(struct ds_device *dev, unsigned char *buf, int size)
 {
 	int count, err;
 	struct ds_status st;
 	
 	count = 0;
 	err = usb_bulk_msg(dev->udev, usb_rcvbulkpipe(dev->udev, dev->ep[EP_DATA_IN]), 
-				buf, size, &count, HZ);
+				buf, size, &count, 1000);
 	if (err < 0) {
 		printk(KERN_INFO "Clearing ep0x%x.\n", dev->ep[EP_DATA_IN]);
 		usb_clear_halt(dev->udev, usb_rcvbulkpipe(dev->udev, dev->ep[EP_DATA_IN]));
@@ -234,12 +231,12 @@
 	return count;
 }
 
-int ds_send_data(struct ds_device *dev, unsigned char *buf, int len)
+static int ds_send_data(struct ds_device *dev, unsigned char *buf, int len)
 {
 	int count, err;
 	
 	count = 0;
-	err = usb_bulk_msg(dev->udev, usb_sndbulkpipe(dev->udev, dev->ep[EP_DATA_OUT]), buf, len, &count, HZ);
+	err = usb_bulk_msg(dev->udev, usb_sndbulkpipe(dev->udev, dev->ep[EP_DATA_OUT]), buf, len, &count, 1000);
 	if (err < 0) {
 		printk(KERN_ERR "Failed to read 1-wire data from 0x02: err=%d.\n", err);
 		return err;
@@ -774,15 +771,19 @@
 EXPORT_SYMBOL(ds_write_byte);
 EXPORT_SYMBOL(ds_write_bit);
 EXPORT_SYMBOL(ds_write_block);
+EXPORT_SYMBOL(ds_reset);
+EXPORT_SYMBOL(ds_get_device);
+EXPORT_SYMBOL(ds_put_device);
+
+/*
+ * This functions can be used for EEPROM programming, 
+ * when driver will be included into mainline this will 
+ * require uncommenting.
+ */
+#if 0
 EXPORT_SYMBOL(ds_start_pulse);
 EXPORT_SYMBOL(ds_set_speed);
-EXPORT_SYMBOL(ds_reset);
 EXPORT_SYMBOL(ds_detect);
 EXPORT_SYMBOL(ds_stop_pulse);
-EXPORT_SYMBOL(ds_send_data);
-EXPORT_SYMBOL(ds_recv_data);
-EXPORT_SYMBOL(ds_recv_status);
 EXPORT_SYMBOL(ds_search);
-EXPORT_SYMBOL(ds_get_device);
-EXPORT_SYMBOL(ds_put_device);
-
+#endif
diff -Nru a/drivers/w1/dscore.h b/drivers/w1/dscore.h
--- a/drivers/w1/dscore.h	2005-03-11 12:51:46 -08:00
+++ b/drivers/w1/dscore.h	2005-03-11 12:51:46 -08:00
@@ -161,9 +161,6 @@
 int ds_reset(struct ds_device *, struct ds_status *);
 int ds_detect(struct ds_device *, struct ds_status *);
 int ds_stop_pulse(struct ds_device *, int);
-int ds_send_data(struct ds_device *, unsigned char *, int);
-int ds_recv_data(struct ds_device *, unsigned char *, int);
-int ds_recv_status(struct ds_device *, struct ds_status *);
 struct ds_device * ds_get_device(void);
 void ds_put_device(struct ds_device *);
 int ds_write_block(struct ds_device *, u8 *, int);
diff -Nru a/drivers/w1/matrox_w1.c b/drivers/w1/matrox_w1.c
--- a/drivers/w1/matrox_w1.c	2005-03-11 12:51:47 -08:00
+++ b/drivers/w1/matrox_w1.c	2005-03-11 12:51:47 -08:00
@@ -235,7 +235,7 @@
 
 static int __init matrox_w1_init(void)
 {
-	return pci_module_init(&matrox_w1_pci_driver);
+	return pci_register_driver(&matrox_w1_pci_driver);
 }
 
 static void __exit matrox_w1_fini(void)
diff -Nru a/drivers/w1/w1.c b/drivers/w1/w1.c
--- a/drivers/w1/w1.c	2005-03-11 12:51:42 -08:00
+++ b/drivers/w1/w1.c	2005-03-11 12:51:42 -08:00
@@ -19,8 +19,6 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  */
 
-#include <asm/atomic.h>
-
 #include <linux/delay.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
@@ -33,6 +31,8 @@
 #include <linux/slab.h>
 #include <linux/sched.h>
 
+#include <asm/atomic.h>
+
 #include "w1.h"
 #include "w1_io.h"
 #include "w1_log.h"
@@ -58,7 +58,6 @@
 static pid_t control_thread;
 static int control_needs_exit;
 static DECLARE_COMPLETION(w1_control_complete);
-static DECLARE_WAIT_QUEUE_HEAD(w1_control_wait);
 
 static int w1_master_match(struct device *dev, struct device_driver *drv)
 {
@@ -100,7 +99,7 @@
 	return sprintf(buf, "No family registered.\n");
 }
 
-struct bus_type w1_bus_type = {
+static struct bus_type w1_bus_type = {
 	.name = "w1",
 	.match = w1_master_match,
 };
@@ -138,7 +137,7 @@
 	.show = &w1_default_read_name,
 };
 
-ssize_t w1_master_attribute_show_name(struct device *dev, char *buf)
+static ssize_t w1_master_attribute_show_name(struct device *dev, char *buf)
 {
 	struct w1_master *md = container_of (dev, struct w1_master, dev);
 	ssize_t count;
@@ -153,7 +152,7 @@
 	return count;
 }
 
-ssize_t w1_master_attribute_show_pointer(struct device *dev, char *buf)
+static ssize_t w1_master_attribute_show_pointer(struct device *dev, char *buf)
 {
 	struct w1_master *md = container_of(dev, struct w1_master, dev);
 	ssize_t count;
@@ -167,14 +166,14 @@
 	return count;
 }
 
-ssize_t w1_master_attribute_show_timeout(struct device *dev, char *buf)
+static ssize_t w1_master_attribute_show_timeout(struct device *dev, char *buf)
 {
 	ssize_t count;
 	count = sprintf(buf, "%d\n", w1_timeout);
 	return count;
 }
 
-ssize_t w1_master_attribute_show_max_slave_count(struct device *dev, char *buf)
+static ssize_t w1_master_attribute_show_max_slave_count(struct device *dev, char *buf)
 {
 	struct w1_master *md = container_of(dev, struct w1_master, dev);
 	ssize_t count;
@@ -188,7 +187,7 @@
 	return count;
 }
 
-ssize_t w1_master_attribute_show_attempts(struct device *dev, char *buf)
+static ssize_t w1_master_attribute_show_attempts(struct device *dev, char *buf)
 {
 	struct w1_master *md = container_of(dev, struct w1_master, dev);
 	ssize_t count;
@@ -202,7 +201,7 @@
 	return count;
 }
 
-ssize_t w1_master_attribute_show_slave_count(struct device *dev, char *buf)
+static ssize_t w1_master_attribute_show_slave_count(struct device *dev, char *buf)
 {
 	struct w1_master *md = container_of(dev, struct w1_master, dev);
 	ssize_t count;
@@ -216,7 +215,7 @@
 	return count;
 }
 
-ssize_t w1_master_attribute_show_slaves(struct device *dev, char *buf)
+static ssize_t w1_master_attribute_show_slaves(struct device *dev, char *buf)
 
 {
 	struct w1_master *md = container_of(dev, struct w1_master, dev);
@@ -522,9 +521,10 @@
 		slave_count++;
 	}
 
-	if (slave_count == dev->slave_count &&
-		rn && ((rn >> 56) & 0xff) == w1_calc_crc8((u8 *)&rn, 7)) {
-		w1_attach_slave_device(dev, (struct w1_reg_num *) &rn);
+		if (slave_count == dev->slave_count && rn ) {
+			tmp = cpu_to_le64(rn);
+			if(((rn >> 56) & 0xff) == w1_calc_crc8((u8 *)&tmp, 7))
+				w1_attach_slave_device(dev, (struct w1_reg_num *) &rn);
 	}
 			
 	atomic_dec(&dev->refcnt);
@@ -649,7 +649,7 @@
 	struct w1_slave *sl;
 	struct w1_master *dev;
 	struct list_head *ent, *ment, *n, *mn;
-	int err, have_to_wait = 0, timeout;
+	int err, have_to_wait = 0;
 
 	daemonize("w1_control");
 	allow_signal(SIGTERM);
@@ -657,11 +657,8 @@
 	while (!control_needs_exit || have_to_wait) {
 		have_to_wait = 0;
 
-		timeout = w1_timeout*HZ;
-		do {
-			timeout = interruptible_sleep_on_timeout(&w1_control_wait, timeout);
-			try_to_freeze(PF_FREEZE);
-		} while (!signal_pending(current) && (timeout > 0));
+		try_to_freeze(PF_FREEZE);
+		msleep_interruptible(w1_timeout * 1000);
 
 		if (signal_pending(current))
 			flush_signals(current);
@@ -721,7 +718,6 @@
 int w1_process(void *data)
 {
 	struct w1_master *dev = (struct w1_master *) data;
-	unsigned long timeout;
 	struct list_head *ent, *n;
 	struct w1_slave *sl;
 
@@ -729,11 +725,8 @@
 	allow_signal(SIGTERM);
 
 	while (!dev->need_exit) {
-		timeout = w1_timeout*HZ;
-		do {
-			timeout = interruptible_sleep_on_timeout(&dev->kwait, timeout);
-			try_to_freeze(PF_FREEZE);
-		} while (!signal_pending(current) && (timeout > 0));
+		try_to_freeze(PF_FREEZE);
+		msleep_interruptible(w1_timeout * 1000);
 
 		if (signal_pending(current))
 			flush_signals(current);
@@ -839,6 +832,3 @@
 
 module_init(w1_init);
 module_exit(w1_fini);
-
-EXPORT_SYMBOL(w1_create_master_attributes);
-EXPORT_SYMBOL(w1_destroy_master_attributes);
diff -Nru a/drivers/w1/w1.h b/drivers/w1/w1.h
--- a/drivers/w1/w1.h	2005-03-11 12:51:52 -08:00
+++ b/drivers/w1/w1.h	2005-03-11 12:51:52 -08:00
@@ -24,9 +24,17 @@
 
 struct w1_reg_num
 {
+#if defined(__LITTLE_ENDIAN_BITFIELD)
 	__u64	family:8,
 		id:48,
 		crc:8;
+#elif defined(__BIG_ENDIAN_BITFIELD)
+	__u64	crc:8,
+		id:48,
+		family:8;
+#else
+#error "Please fix <asm/byteorder.h>"
+#endif
 };
 
 #ifdef __KERNEL__
@@ -115,7 +123,6 @@
 
 	int			need_exit;
 	pid_t			kpid;
-	wait_queue_head_t 	kwait;
 	struct semaphore 	mutex;
 
 	struct device_driver	*driver;
diff -Nru a/drivers/w1/w1_family.c b/drivers/w1/w1_family.c
--- a/drivers/w1/w1_family.c	2005-03-11 12:51:47 -08:00
+++ b/drivers/w1/w1_family.c	2005-03-11 12:51:47 -08:00
@@ -138,13 +138,13 @@
 
 void __w1_family_get(struct w1_family *f)
 {
+	smp_mb__before_atomic_inc();
 	atomic_inc(&f->refcnt);
+	smp_mb__after_atomic_inc();
 }
 
 EXPORT_SYMBOL(w1_family_get);
 EXPORT_SYMBOL(w1_family_put);
-EXPORT_SYMBOL(__w1_family_get);
-EXPORT_SYMBOL(__w1_family_put);
 EXPORT_SYMBOL(w1_family_registered);
 EXPORT_SYMBOL(w1_unregister_family);
 EXPORT_SYMBOL(w1_register_family);
diff -Nru a/drivers/w1/w1_int.c b/drivers/w1/w1_int.c
--- a/drivers/w1/w1_int.c	2005-03-11 12:51:51 -08:00
+++ b/drivers/w1/w1_int.c	2005-03-11 12:51:51 -08:00
@@ -74,7 +74,6 @@
 	INIT_LIST_HEAD(&dev->slist);
 	init_MUTEX(&dev->mutex);
 
-	init_waitqueue_head(&dev->kwait);
 	init_completion(&dev->dev_released);
 	init_completion(&dev->dev_exited);
 
@@ -217,8 +216,5 @@
 	__w1_remove_master_device(dev);
 }
 
-EXPORT_SYMBOL(w1_alloc_dev);
-EXPORT_SYMBOL(w1_free_dev);
 EXPORT_SYMBOL(w1_add_master_device);
 EXPORT_SYMBOL(w1_remove_master_device);
-EXPORT_SYMBOL(__w1_remove_master_device);
diff -Nru a/drivers/w1/w1_therm.c b/drivers/w1/w1_therm.c
--- a/drivers/w1/w1_therm.c	2005-03-11 12:51:41 -08:00
+++ b/drivers/w1/w1_therm.c	2005-03-11 12:51:41 -08:00
@@ -26,6 +26,7 @@
 #include <linux/moduleparam.h>
 #include <linux/device.h>
 #include <linux/types.h>
+#include <linux/delay.h>
 
 #include "w1.h"
 #include "w1_io.h"
@@ -103,6 +104,7 @@
 	int i, max_trying = 10;
 
 	atomic_inc(&sl->refcnt);
+	smp_mb__after_atomic_inc();
 	if (down_interruptible(&sl->master->mutex)) {
 		count = 0;
 		goto out_dec;
@@ -128,7 +130,7 @@
 		if (!w1_reset_bus (dev)) {
 			int count = 0;
 			u8 match[9] = {W1_MATCH_ROM, };
-			unsigned long tm;
+			unsigned int tm = 750;
 
 			memcpy(&match[1], (u64 *) & sl->reg_num, 8);
 			
@@ -136,11 +138,8 @@
 
 			w1_write_8(dev, W1_CONVERT_TEMP);
 
-			tm = jiffies + msecs_to_jiffies(750);
-			while(time_before(jiffies, tm)) {
-				set_current_state(TASK_INTERRUPTIBLE);
-				schedule_timeout(tm-jiffies);
-
+			while (tm) {
+				tm = msleep_interruptible(tm);
 				if (signal_pending(current))
 					flush_signals(current);
 			}
@@ -181,6 +180,7 @@
 out:
 	up(&dev->mutex);
 out_dec:
+	smp_mb__before_atomic_inc();
 	atomic_dec(&sl->refcnt);
 
 	return count;
diff -Nru a/fs/afs/main.c b/fs/afs/main.c
--- a/fs/afs/main.c	2005-03-11 12:51:42 -08:00
+++ b/fs/afs/main.c	2005-03-11 12:51:42 -08:00
@@ -29,18 +29,9 @@
 
 struct rxrpc_transport *afs_transport;
 
-static int afs_init(void);
-static void afs_exit(void);
 static int afs_adding_peer(struct rxrpc_peer *peer);
 static void afs_discarding_peer(struct rxrpc_peer *peer);
 
-/* XXX late_initcall is kludgy, but the only alternative seems to create
- * a transport upon the first mount, which is worse. Or is it?
- */
-/* module_init(afs_init); */
-late_initcall(afs_init);	/* must be called after net/ to create socket */
-
-module_exit(afs_exit);
 
 MODULE_DESCRIPTION("AFS Client File System");
 MODULE_AUTHOR("Red Hat, Inc.");
@@ -76,7 +67,7 @@
 /*
  * initialise the AFS client FS module
  */
-static int afs_init(void)
+static int __init afs_init(void)
 {
 	int loop, ret;
 
@@ -156,6 +147,10 @@
 	return ret;
 } /* end afs_init() */
 
+/* XXX late_initcall is kludgy, but the only alternative seems to create
+ * a transport upon the first mount, which is worse. Or is it?
+ */
+late_initcall(afs_init);	/* must be called after net/ to create socket */
 /*****************************************************************************/
 /*
  * clean up on module removal
@@ -178,6 +173,8 @@
 	afs_proc_cleanup();
 
 } /* end afs_exit() */
+
+module_exit(afs_exit);
 
 /*****************************************************************************/
 /*
diff -Nru a/fs/autofs4/root.c b/fs/autofs4/root.c
--- a/fs/autofs4/root.c	2005-03-11 12:51:41 -08:00
+++ b/fs/autofs4/root.c	2005-03-11 12:51:41 -08:00
@@ -605,7 +605,9 @@
 		spin_unlock(&dcache_lock);
 		return -ENOTEMPTY;
 	}
+	spin_lock(&dentry->d_lock);
 	__d_drop(dentry);
+	spin_unlock(&dentry->d_lock);
 	spin_unlock(&dcache_lock);
 
 	dput(ino->dentry);
diff -Nru a/fs/autofs4/waitq.c b/fs/autofs4/waitq.c
--- a/fs/autofs4/waitq.c	2005-03-11 12:51:51 -08:00
+++ b/fs/autofs4/waitq.c	2005-03-11 12:51:51 -08:00
@@ -224,6 +224,7 @@
 	} else {
 		atomic_inc(&wq->wait_ctr);
 		up(&sbi->wq_sem);
+		kfree(name);
 		DPRINTK("existing wait id = 0x%08lx, name = %.*s, nfy=%d",
 			(unsigned long) wq->wait_queue_token, wq->len, wq->name, notify);
 	}
diff -Nru a/fs/binfmt_elf.c b/fs/binfmt_elf.c
--- a/fs/binfmt_elf.c	2005-03-11 12:51:43 -08:00
+++ b/fs/binfmt_elf.c	2005-03-11 12:51:43 -08:00
@@ -37,6 +37,7 @@
 #include <linux/pagemap.h>
 #include <linux/security.h>
 #include <linux/syscalls.h>
+#include <linux/random.h>
 
 #include <asm/uaccess.h>
 #include <asm/param.h>
@@ -165,21 +166,14 @@
 	if (k_platform) {
 		size_t len = strlen(k_platform) + 1;
 
-#ifdef CONFIG_X86_HT
 		/*
 		 * In some cases (e.g. Hyper-Threading), we want to avoid L1
 		 * evictions by the processes running on the same package. One
 		 * thing we can do is to shuffle the initial stack for them.
-		 *
-		 * The conditionals here are unneeded, but kept in to make the
-		 * code behaviour the same as pre change unless we have
-		 * hyperthreaded processors. This should be cleaned up
-		 * before 2.6
 		 */
 	 
-		if (smp_num_siblings > 1)
-			STACK_ALLOC(p, ((current->pid % 64) << 7));
-#endif
+		p = arch_align_stack(p);
+
 		u_platform = (elf_addr_t __user *)STACK_ALLOC(p, len);
 		if (__copy_to_user(u_platform, k_platform, len))
 			return -EFAULT;
@@ -501,6 +495,19 @@
 #define INTERPRETER_ELF 2
 
 
+static unsigned long randomize_stack_top(unsigned long stack_top)
+{
+	unsigned int random_variable = 0;
+
+	if (current->flags & PF_RANDOMIZE)
+		random_variable = get_random_int() % (8*1024*1024);
+#ifdef CONFIG_STACK_GROWSUP
+	return PAGE_ALIGN(stack_top + random_variable);
+#else
+	return PAGE_ALIGN(stack_top - random_variable);
+#endif
+}
+
 static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
 {
 	struct file *interpreter = NULL; /* to shut gcc up */
@@ -760,18 +767,29 @@
 	if (elf_read_implies_exec(loc->elf_ex, executable_stack))
 		current->personality |= READ_IMPLIES_EXEC;
 
+	if ( !(current->personality & ADDR_NO_RANDOMIZE) && randomize_va_space)
+		current->flags |= PF_RANDOMIZE;
 	arch_pick_mmap_layout(current->mm);
 
 	/* Do this so that we can load the interpreter, if need be.  We will
 	   change some of these later */
 	current->mm->rss = 0;
 	current->mm->free_area_cache = current->mm->mmap_base;
-	retval = setup_arg_pages(bprm, STACK_TOP, executable_stack);
+	retval = setup_arg_pages(bprm, randomize_stack_top(STACK_TOP),
+				 executable_stack);
 	if (retval < 0) {
 		send_sig(SIGKILL, current, 0);
 		goto out_free_dentry;
 	}
 	
+#ifdef ARCH_HAS_SETUP_ADDITIONAL_PAGES
+	retval = arch_setup_additional_pages(bprm, executable_stack);
+	if (retval < 0) {
+		send_sig(SIGKILL, current, 0);
+		goto out_free_dentry;
+	}
+#endif /* ARCH_HAS_SETUP_ADDITIONAL_PAGES */
+
 	current->mm->start_stack = bprm->p;
 
 	/* Now we do a little grungy work by mmaping the ELF image into
@@ -1585,7 +1603,7 @@
 					DUMP_SEEK (file->f_pos + PAGE_SIZE);
 				} else {
 					void *kaddr;
-					flush_cache_page(vma, addr);
+					flush_cache_page(vma, addr, page_to_pfn(page));
 					kaddr = kmap(page);
 					if ((size += PAGE_SIZE) > limit ||
 					    !dump_write(file, kaddr,
diff -Nru a/fs/bio.c b/fs/bio.c
--- a/fs/bio.c	2005-03-11 12:51:47 -08:00
+++ b/fs/bio.c	2005-03-11 12:51:47 -08:00
@@ -28,7 +28,6 @@
 
 #define BIO_POOL_SIZE 256
 
-static mempool_t *bio_pool;
 static kmem_cache_t *bio_slab;
 
 #define BIOVEC_NR_POOLS 6
@@ -40,11 +39,10 @@
 #define BIO_SPLIT_ENTRIES 8	
 mempool_t *bio_split_pool;
 
-struct biovec_pool {
+struct biovec_slab {
 	int nr_vecs;
 	char *name; 
 	kmem_cache_t *slab;
-	mempool_t *pool;
 };
 
 /*
@@ -54,15 +52,32 @@
  */
 
 #define BV(x) { .nr_vecs = x, .name = "biovec-"__stringify(x) }
-static struct biovec_pool bvec_array[BIOVEC_NR_POOLS] = {
+static struct biovec_slab bvec_slabs[BIOVEC_NR_POOLS] = {
 	BV(1), BV(4), BV(16), BV(64), BV(128), BV(BIO_MAX_PAGES),
 };
 #undef BV
 
-static inline struct bio_vec *bvec_alloc(int gfp_mask, int nr, unsigned long *idx)
+/*
+ * bio_set is used to allow other portions of the IO system to
+ * allocate their own private memory pools for bio and iovec structures.
+ * These memory pools in turn all allocate from the bio_slab
+ * and the bvec_slabs[].
+ */
+struct bio_set {
+	mempool_t *bio_pool;
+	mempool_t *bvec_pools[BIOVEC_NR_POOLS];
+};
+
+/*
+ * fs_bio_set is the bio_set containing bio and iovec memory pools used by
+ * IO code that does not need private memory pools.
+ */
+static struct bio_set *fs_bio_set;
+
+static inline struct bio_vec *bvec_alloc_bs(int gfp_mask, int nr, unsigned long *idx, struct bio_set *bs)
 {
-	struct biovec_pool *bp;
 	struct bio_vec *bvl;
+	struct biovec_slab *bp;
 
 	/*
 	 * see comment near bvec_array define!
@@ -80,26 +95,27 @@
 	/*
 	 * idx now points to the pool we want to allocate from
 	 */
-	bp = bvec_array + *idx;
 
-	bvl = mempool_alloc(bp->pool, gfp_mask);
+	bp = bvec_slabs + *idx;
+	bvl = mempool_alloc(bs->bvec_pools[*idx], gfp_mask);
 	if (bvl)
 		memset(bvl, 0, bp->nr_vecs * sizeof(struct bio_vec));
+
 	return bvl;
 }
 
 /*
- * default destructor for a bio allocated with bio_alloc()
+ * default destructor for a bio allocated with bio_alloc_bioset()
  */
 static void bio_destructor(struct bio *bio)
 {
 	const int pool_idx = BIO_POOL_IDX(bio);
-	struct biovec_pool *bp = bvec_array + pool_idx;
+	struct bio_set *bs = bio->bi_set;
 
 	BIO_BUG_ON(pool_idx >= BIOVEC_NR_POOLS);
 
-	mempool_free(bio->bi_io_vec, bp->pool);
-	mempool_free(bio, bio_pool);
+	mempool_free(bio->bi_io_vec, bs->bvec_pools[pool_idx]);
+	mempool_free(bio, bs->bio_pool);
 }
 
 inline void bio_init(struct bio *bio)
@@ -121,18 +137,21 @@
 }
 
 /**
- * bio_alloc - allocate a bio for I/O
+ * bio_alloc_bioset - allocate a bio for I/O
  * @gfp_mask:   the GFP_ mask given to the slab allocator
  * @nr_iovecs:	number of iovecs to pre-allocate
  *
  * Description:
- *   bio_alloc will first try it's on mempool to satisfy the allocation.
+ *   bio_alloc_bioset will first try it's on mempool to satisfy the allocation.
  *   If %__GFP_WAIT is set then we will block on the internal pool waiting
  *   for a &struct bio to become free.
+ *
+ *   allocate bio and iovecs from the memory pools specified by the
+ *   bio_set structure.
  **/
-struct bio *bio_alloc(int gfp_mask, int nr_iovecs)
+struct bio *bio_alloc_bioset(int gfp_mask, int nr_iovecs, struct bio_set *bs)
 {
-	struct bio *bio = mempool_alloc(bio_pool, gfp_mask);
+	struct bio *bio = mempool_alloc(bs->bio_pool, gfp_mask);
 
 	if (likely(bio)) {
 		struct bio_vec *bvl = NULL;
@@ -141,22 +160,43 @@
 		if (likely(nr_iovecs)) {
 			unsigned long idx;
 
-			bvl = bvec_alloc(gfp_mask, nr_iovecs, &idx);
+			bvl = bvec_alloc_bs(gfp_mask, nr_iovecs, &idx, bs);
 			if (unlikely(!bvl)) {
-				mempool_free(bio, bio_pool);
+				mempool_free(bio, bs->bio_pool);
 				bio = NULL;
 				goto out;
 			}
 			bio->bi_flags |= idx << BIO_POOL_OFFSET;
-			bio->bi_max_vecs = bvec_array[idx].nr_vecs;
+			bio->bi_max_vecs = bvec_slabs[idx].nr_vecs;
 		}
 		bio->bi_io_vec = bvl;
 		bio->bi_destructor = bio_destructor;
+		bio->bi_set = bs;
 	}
 out:
 	return bio;
 }
 
+struct bio *bio_alloc(int gfp_mask, int nr_iovecs)
+{
+	return bio_alloc_bioset(gfp_mask, nr_iovecs, fs_bio_set);
+}
+
+void zero_fill_bio(struct bio *bio)
+{
+	unsigned long flags;
+	struct bio_vec *bv;
+	int i;
+
+	bio_for_each_segment(bv, bio, i) {
+		char *data = bvec_kmap_irq(bv, &flags);
+		memset(data, 0, bv->bv_len);
+		flush_dcache_page(bv->bv_page);
+		bvec_kunmap_irq(data, &flags);
+	}
+}
+EXPORT_SYMBOL(zero_fill_bio);
+
 /**
  * bio_put - release a reference to a bio
  * @bio:   bio to release reference to
@@ -233,7 +273,7 @@
  */
 struct bio *bio_clone(struct bio *bio, int gfp_mask)
 {
-	struct bio *b = bio_alloc(gfp_mask, bio->bi_max_vecs);
+	struct bio *b = bio_alloc_bioset(gfp_mask, bio->bi_max_vecs, fs_bio_set);
 
 	if (b)
 		__bio_clone(b, bio);
@@ -904,11 +944,99 @@
 	kfree(bp);
 }
 
-static void __init biovec_init_pools(void)
+
+/*
+ * create memory pools for biovec's in a bio_set.
+ * use the global biovec slabs created for general use.
+ */
+static int biovec_create_pools(struct bio_set *bs, int pool_entries, int scale)
+{
+	int i;
+
+	for (i = 0; i < BIOVEC_NR_POOLS; i++) {
+		struct biovec_slab *bp = bvec_slabs + i;
+		mempool_t **bvp = bs->bvec_pools + i;
+
+		if (i >= scale)
+			pool_entries >>= 1;
+
+		*bvp = mempool_create(pool_entries, mempool_alloc_slab,
+					mempool_free_slab, bp->slab);
+		if (!*bvp)
+			return -ENOMEM;
+	}
+	return 0;
+}
+
+static void biovec_free_pools(struct bio_set *bs)
+{
+	int i;
+
+	for (i = 0; i < BIOVEC_NR_POOLS; i++) {
+		mempool_t *bvp = bs->bvec_pools[i];
+
+		if (bvp)
+			mempool_destroy(bvp);
+	}
+
+}
+
+void bioset_free(struct bio_set *bs)
 {
-	int i, size, megabytes, pool_entries = BIO_POOL_SIZE;
+	if (bs->bio_pool)
+		mempool_destroy(bs->bio_pool);
+
+	biovec_free_pools(bs);
+
+	kfree(bs);
+}
+
+struct bio_set *bioset_create(int bio_pool_size, int bvec_pool_size, int scale)
+{
+	struct bio_set *bs = kmalloc(sizeof(*bs), GFP_KERNEL);
+
+	if (!bs)
+		return NULL;
+
+	memset(bs, 0, sizeof(*bs));
+	bs->bio_pool = mempool_create(bio_pool_size, mempool_alloc_slab,
+			mempool_free_slab, bio_slab);
+
+	if (!bs->bio_pool)
+		goto bad;
+
+	if (!biovec_create_pools(bs, bvec_pool_size, scale))
+		return bs;
+
+bad:
+	bioset_free(bs);
+	return NULL;
+}
+
+static void __init biovec_init_slabs(void)
+{
+	int i;
+
+	for (i = 0; i < BIOVEC_NR_POOLS; i++) {
+		int size;
+		struct biovec_slab *bvs = bvec_slabs + i;
+
+		size = bvs->nr_vecs * sizeof(struct bio_vec);
+		bvs->slab = kmem_cache_create(bvs->name, size, 0,
+                                SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL, NULL);
+	}
+}
+
+static int __init init_bio(void)
+{
+	int megabytes, bvec_pool_entries;
 	int scale = BIOVEC_NR_POOLS;
 
+	bio_slab = kmem_cache_create("bio", sizeof(struct bio), 0,
+				SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL, NULL);
+
+	biovec_init_slabs();
+
 	megabytes = nr_free_pages() >> (20 - PAGE_SHIFT);
 
 	/*
@@ -928,38 +1056,13 @@
 	/*
 	 * scale number of entries
 	 */
-	pool_entries = megabytes * 2;
-	if (pool_entries > 256)
-		pool_entries = 256;
-
-	for (i = 0; i < BIOVEC_NR_POOLS; i++) {
-		struct biovec_pool *bp = bvec_array + i;
-
-		size = bp->nr_vecs * sizeof(struct bio_vec);
-
-		bp->slab = kmem_cache_create(bp->name, size, 0,
-				SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL, NULL);
-
-		if (i >= scale)
-			pool_entries >>= 1;
-
-		bp->pool = mempool_create(pool_entries, mempool_alloc_slab,
-					mempool_free_slab, bp->slab);
-		if (!bp->pool)
-			panic("biovec: can't init mempool\n");
-	}
-}
-
-static int __init init_bio(void)
-{
-	bio_slab = kmem_cache_create("bio", sizeof(struct bio), 0,
-				SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL, NULL);
-	bio_pool = mempool_create(BIO_POOL_SIZE, mempool_alloc_slab,
-				mempool_free_slab, bio_slab);
-	if (!bio_pool)
-		panic("bio: can't create mempool\n");
-
-	biovec_init_pools();
+	bvec_pool_entries = megabytes * 2;
+	if (bvec_pool_entries > 256)
+		bvec_pool_entries = 256;
+
+	fs_bio_set = bioset_create(BIO_POOL_SIZE, bvec_pool_entries, scale);
+	if (!fs_bio_set)
+		panic("bio: can't allocate bios\n");
 
 	bio_split_pool = mempool_create(BIO_SPLIT_ENTRIES,
 				bio_pair_alloc, bio_pair_free, NULL);
@@ -988,3 +1091,6 @@
 EXPORT_SYMBOL(bio_split_pool);
 EXPORT_SYMBOL(bio_copy_user);
 EXPORT_SYMBOL(bio_uncopy_user);
+EXPORT_SYMBOL(bioset_create);
+EXPORT_SYMBOL(bioset_free);
+EXPORT_SYMBOL(bio_alloc_bioset);
diff -Nru a/fs/buffer.c b/fs/buffer.c
--- a/fs/buffer.c	2005-03-11 12:51:47 -08:00
+++ b/fs/buffer.c	2005-03-11 12:51:47 -08:00
@@ -39,6 +39,7 @@
 #include <linux/notifier.h>
 #include <linux/cpu.h>
 #include <linux/bitops.h>
+#include <linux/mpage.h>
 
 static int fsync_buffers_list(spinlock_t *lock, struct list_head *list);
 static void invalidate_bh_lrus(void);
@@ -875,7 +876,7 @@
 	spin_unlock(&mapping->private_lock);
 
 	if (!TestSetPageDirty(page)) {
-		spin_lock_irq(&mapping->tree_lock);
+		write_lock_irq(&mapping->tree_lock);
 		if (page->mapping) {	/* Race with truncate? */
 			if (!mapping->backing_dev_info->memory_backed)
 				inc_page_state(nr_dirty);
@@ -883,7 +884,7 @@
 						page_index(page),
 						PAGECACHE_TAG_DIRTY);
 		}
-		spin_unlock_irq(&mapping->tree_lock);
+		write_unlock_irq(&mapping->tree_lock);
 		__mark_inode_dirty(mapping->host, I_DIRTY_PAGES);
 	}
 	
@@ -2507,6 +2508,61 @@
 	return 0;
 }
 EXPORT_SYMBOL(nobh_commit_write);
+
+/*
+ * nobh_writepage() - based on block_full_write_page() except
+ * that it tries to operate without attaching bufferheads to
+ * the page.
+ */
+int nobh_writepage(struct page *page, get_block_t *get_block,
+			struct writeback_control *wbc)
+{
+	struct inode * const inode = page->mapping->host;
+	loff_t i_size = i_size_read(inode);
+	const pgoff_t end_index = i_size >> PAGE_CACHE_SHIFT;
+	unsigned offset;
+	void *kaddr;
+	int ret;
+
+	/* Is the page fully inside i_size? */
+	if (page->index < end_index)
+		goto out;
+
+	/* Is the page fully outside i_size? (truncate in progress) */
+	offset = i_size & (PAGE_CACHE_SIZE-1);
+	if (page->index >= end_index+1 || !offset) {
+		/*
+		 * The page may have dirty, unmapped buffers.  For example,
+		 * they may have been added in ext3_writepage().  Make them
+		 * freeable here, so the page does not leak.
+		 */
+#if 0
+		/* Not really sure about this  - do we need this ? */
+		if (page->mapping->a_ops->invalidatepage)
+			page->mapping->a_ops->invalidatepage(page, offset);
+#endif
+		unlock_page(page);
+		return 0; /* don't care */
+	}
+
+	/*
+	 * The page straddles i_size.  It must be zeroed out on each and every
+	 * writepage invocation because it may be mmapped.  "A file is mapped
+	 * in multiples of the page size.  For a file that is not a multiple of
+	 * the  page size, the remaining memory is zeroed when mapped, and
+	 * writes to that region are not written out to the file."
+	 */
+	kaddr = kmap_atomic(page, KM_USER0);
+	memset(kaddr + offset, 0, PAGE_CACHE_SIZE - offset);
+	flush_dcache_page(page);
+	kunmap_atomic(kaddr, KM_USER0);
+out:
+	ret = mpage_writepage(page, get_block, wbc);
+	if (ret == -EAGAIN)
+		ret = __block_write_full_page(inode, page, get_block, wbc);
+	return ret;
+}
+EXPORT_SYMBOL(nobh_writepage);
 
 /*
  * This function assumes that ->prepare_write() uses nobh_prepare_write().
diff -Nru a/fs/char_dev.c b/fs/char_dev.c
--- a/fs/char_dev.c	2005-03-11 12:51:42 -08:00
+++ b/fs/char_dev.c	2005-03-11 12:51:42 -08:00
@@ -26,9 +26,10 @@
 
 static struct kobj_map *cdev_map;
 
-#define MAX_PROBE_HASH 255	/* random */
+/* degrade to linked list for small systems */
+#define MAX_PROBE_HASH (CONFIG_BASE_SMALL ? 1 : 255)
 
-static DEFINE_RWLOCK(chrdevs_lock);
+static DECLARE_MUTEX(chrdevs_lock);
 
 static struct char_device_struct {
 	struct char_device_struct *next;
@@ -54,13 +55,13 @@
 
 	len = sprintf(page, "Character devices:\n");
 
-	read_lock(&chrdevs_lock);
+	down(&chrdevs_lock);
 	for (i = 0; i < ARRAY_SIZE(chrdevs) ; i++) {
 		for (cd = chrdevs[i]; cd; cd = cd->next)
 			len += sprintf(page+len, "%3d %s\n",
 				       cd->major, cd->name);
 	}
-	read_unlock(&chrdevs_lock);
+	up(&chrdevs_lock);
 
 	return len;
 }
@@ -90,7 +91,7 @@
 
 	memset(cd, 0, sizeof(struct char_device_struct));
 
-	write_lock_irq(&chrdevs_lock);
+	down(&chrdevs_lock);
 
 	/* temporary */
 	if (major == 0) {
@@ -125,10 +126,10 @@
 	}
 	cd->next = *cp;
 	*cp = cd;
-	write_unlock_irq(&chrdevs_lock);
+	up(&chrdevs_lock);
 	return cd;
 out:
-	write_unlock_irq(&chrdevs_lock);
+	up(&chrdevs_lock);
 	kfree(cd);
 	return ERR_PTR(ret);
 }
@@ -139,7 +140,7 @@
 	struct char_device_struct *cd = NULL, **cp;
 	int i = major_to_index(major);
 
-	write_lock_irq(&chrdevs_lock);
+	up(&chrdevs_lock);
 	for (cp = &chrdevs[i]; *cp; cp = &(*cp)->next)
 		if ((*cp)->major == major &&
 		    (*cp)->baseminor == baseminor &&
@@ -149,7 +150,7 @@
 		cd = *cp;
 		*cp = cd->next;
 	}
-	write_unlock_irq(&chrdevs_lock);
+	up(&chrdevs_lock);
 	return cd;
 }
 
@@ -380,8 +381,6 @@
 }
 
 
-static decl_subsys(cdev, NULL, NULL);
-
 static void cdev_default_release(struct kobject *kobj)
 {
 	struct cdev *p = container_of(kobj, struct cdev, kobj);
@@ -434,13 +433,7 @@
 
 void __init chrdev_init(void)
 {
-/*
- * Keep cdev_subsys around because (and only because) the kobj_map code
- * depends on the rwsem it contains.  We don't make it public in sysfs,
- * however.
- */
-	subsystem_init(&cdev_subsys);
-	cdev_map = kobj_map_init(base_probe, &cdev_subsys);
+	cdev_map = kobj_map_init(base_probe, &chrdevs_lock);
 }
 
 
diff -Nru a/fs/compat_ioctl.c b/fs/compat_ioctl.c
--- a/fs/compat_ioctl.c	2005-03-11 12:51:52 -08:00
+++ b/fs/compat_ioctl.c	2005-03-11 12:51:52 -08:00
@@ -1281,35 +1281,9 @@
 };
 #define MTIOCPOS32	_IOR('m', 3, struct mtpos32)
 
-struct mtconfiginfo32 {
-	compat_long_t	mt_type;
-	compat_long_t	ifc_type;
-	unsigned short	irqnr;
-	unsigned short	dmanr;
-	unsigned short	port;
-	compat_ulong_t	debug;
-	compat_uint_t	have_dens:1;
-	compat_uint_t	have_bsf:1;
-	compat_uint_t	have_fsr:1;
-	compat_uint_t	have_bsr:1;
-	compat_uint_t	have_eod:1;
-	compat_uint_t	have_seek:1;
-	compat_uint_t	have_tell:1;
-	compat_uint_t	have_ras1:1;
-	compat_uint_t	have_ras2:1;
-	compat_uint_t	have_ras3:1;
-	compat_uint_t	have_qfa:1;
-	compat_uint_t	pad1:5;
-	char	reserved[10];
-};
-#define	MTIOCGETCONFIG32	_IOR('m', 4, struct mtconfiginfo32)
-#define	MTIOCSETCONFIG32	_IOW('m', 5, struct mtconfiginfo32)
-
 static int mt_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg)
 {
 	mm_segment_t old_fs = get_fs();
-	struct mtconfiginfo info;
-	struct mtconfiginfo32 __user *uinfo32;
 	struct mtget get;
 	struct mtget32 __user *umget32;
 	struct mtpos pos;
@@ -1327,27 +1301,6 @@
 		kcmd = MTIOCGET;
 		karg = &get;
 		break;
-	case MTIOCGETCONFIG32:
-		kcmd = MTIOCGETCONFIG;
-		karg = &info;
-		break;
-	case MTIOCSETCONFIG32:
-		kcmd = MTIOCSETCONFIG;
-		karg = &info;
-		uinfo32 = compat_ptr(arg);
-		err = __get_user(info.mt_type, &uinfo32->mt_type);
-		err |= __get_user(info.ifc_type, &uinfo32->ifc_type);
-		err |= __get_user(info.irqnr, &uinfo32->irqnr);
-		err |= __get_user(info.dmanr, &uinfo32->dmanr);
-		err |= __get_user(info.port, &uinfo32->port);
-		err |= __get_user(info.debug, &uinfo32->debug);
-		err |= __copy_from_user((char *)&info.debug
-				     + sizeof(info.debug),
-				     (char __user *)&uinfo32->debug
-				     + sizeof(uinfo32->debug), sizeof(__u32));
-		if (err)
-			return -EFAULT;
-		break;
 	default:
 		do {
 			static int count;
@@ -1378,20 +1331,6 @@
 		err |= __put_user(get.mt_fileno, &umget32->mt_fileno);
 		err |= __put_user(get.mt_blkno, &umget32->mt_blkno);
 		break;
-	case MTIOCGETCONFIG32:
-		uinfo32 = compat_ptr(arg);
-		err = __put_user(info.mt_type, &uinfo32->mt_type);
-		err |= __put_user(info.ifc_type, &uinfo32->ifc_type);
-		err |= __put_user(info.irqnr, &uinfo32->irqnr);
-		err |= __put_user(info.dmanr, &uinfo32->dmanr);
-		err |= __put_user(info.port, &uinfo32->port);
-		err |= __put_user(info.debug, &uinfo32->debug);
-		err |= __copy_to_user((char __user *)&uinfo32->debug
-			    		   + sizeof(uinfo32->debug),
-					   (char *)&info.debug + sizeof(info.debug), sizeof(__u32));
-		break;
-	case MTIOCSETCONFIG32:
-		break;
 	}
 	return err ? -EFAULT: 0;
 }
@@ -1620,7 +1559,7 @@
 		    get_user(data, &user_cfd->chardata))
 			return -EFAULT;
 		op.data = compat_ptr(data);
-		return con_font_op(fg_console, &op);
+		return con_font_op(vc_cons[fg_console].d, &op);
 	case GIO_FONTX:
 		op.op = KD_FONT_OP_GET;
 		op.flags = 0;
@@ -1632,7 +1571,7 @@
 		if (!data)
 			return 0;
 		op.data = compat_ptr(data);
-		i = con_font_op(fg_console, &op);
+		i = con_font_op(vc_cons[fg_console].d, &op);
 		if (i)
 			return i;
 		if (put_user(op.height, &user_cfd->charheight) ||
@@ -1658,7 +1597,7 @@
 	struct console_font_op op;
 	struct console_font_op32 __user *fontop = compat_ptr(arg);
 	int perm = vt_check(file), i;
-	struct vt_struct *vt;
+	struct vc_data *vc;
 	
 	if (perm < 0) return perm;
 	
@@ -1668,9 +1607,10 @@
 		return -EPERM;
 	op.data = compat_ptr(((struct console_font_op32 *)&op)->data);
 	op.flags |= KD_FONT_FLAG_OLD;
-	vt = (struct vt_struct *)((struct tty_struct *)file->private_data)->driver_data;
-	i = con_font_op(vt->vc_num, &op);
-	if (i) return i;
+	vc = ((struct tty_struct *)file->private_data)->driver_data;
+	i = con_font_op(vc, &op);
+	if (i)
+		return i;
 	((struct console_font_op32 *)&op)->data = (unsigned long)op.data;
 	if (copy_to_user(fontop, &op, sizeof(struct console_font_op32)))
 		return -EFAULT;
@@ -1694,9 +1634,9 @@
 	switch (cmd) {
 	case PIO_UNIMAP:
 		if (!perm) return -EPERM;
-		return con_set_unimap(fg_console, tmp.entry_ct, compat_ptr(tmp.entries));
+		return con_set_unimap(vc_cons[fg_console].d, tmp.entry_ct, compat_ptr(tmp.entries));
 	case GIO_UNIMAP:
-		return con_get_unimap(fg_console, tmp.entry_ct, &(user_ud->entry_ct), compat_ptr(tmp.entries));
+		return con_get_unimap(vc_cons[fg_console].d, tmp.entry_ct, &(user_ud->entry_ct), compat_ptr(tmp.entries));
 	}
 	return 0;
 }
@@ -2575,229 +2515,11 @@
         return sys_ioctl(fd, USBDEVFS_BULK, (unsigned long)p);
 }
 
-/* This needs more work before we can enable it.  Unfortunately
- * because of the fancy asynchronous way URB status/error is written
- * back to userspace, we'll need to fiddle with USB devio internals
- * and/or reimplement entirely the frontend of it ourselves. -DaveM
- *
- * The issue is:
- *
- *	When an URB is submitted via usbdevicefs it is put onto an
- *	asynchronous queue.  When the URB completes, it may be reaped
- *	via another ioctl.  During this reaping the status is written
- *	back to userspace along with the length of the transfer.
- *
- *	We must translate into 64-bit kernel types so we pass in a kernel
- *	space copy of the usbdevfs_urb structure.  This would mean that we
- *	must do something to deal with the async entry reaping.  First we
- *	have to deal somehow with this transitory memory we've allocated.
- *	This is problematic since there are many call sites from which the
- *	async entries can be destroyed (and thus when we'd need to free up
- *	this kernel memory).  One of which is the close() op of usbdevicefs.
- *	To handle that we'd need to make our own file_operations struct which
- *	overrides usbdevicefs's release op with our own which runs usbdevicefs's
- *	real release op then frees up the kernel memory.
- *
- *	But how to keep track of these kernel buffers?  We'd need to either
- *	keep track of them in some table _or_ know about usbdevicefs internals
- *	(ie. the exact layout of its file private, which is actually defined
- *	in linux/usbdevice_fs.h, the layout of the async queues are private to
- *	devio.c)
- *
- * There is one possible other solution I considered, also involving knowledge
- * of usbdevicefs internals:
- *
- *	After an URB is submitted, we "fix up" the address back to the user
- *	space one.  This would work if the status/length fields written back
- *	by the async URB completion lines up perfectly in the 32-bit type with
- *	the 64-bit kernel type.  Unfortunately, it does not because the iso
- *	frame descriptors, at the end of the struct, can be written back.
- *
- * I think we'll just need to simply duplicate the devio URB engine here.
- */
-#if 0
-struct usbdevfs_urb32 {
-	unsigned char type;
-	unsigned char endpoint;
-	compat_int_t status;
-	compat_uint_t flags;
-	compat_caddr_t buffer;
-	compat_int_t buffer_length;
-	compat_int_t actual_length;
-	compat_int_t start_frame;
-	compat_int_t number_of_packets;
-	compat_int_t error_count;
-	compat_uint_t signr;
-	compat_caddr_t usercontext; /* unused */
-	struct usbdevfs_iso_packet_desc iso_frame_desc[0];
-};
-
-#define USBDEVFS_SUBMITURB32       _IOR('U', 10, struct usbdevfs_urb32)
-
-static int get_urb32(struct usbdevfs_urb *kurb,
-		     struct usbdevfs_urb32 *uurb)
-{
-	if (get_user(kurb->type, &uurb->type) ||
-	    __get_user(kurb->endpoint, &uurb->endpoint) ||
-	    __get_user(kurb->status, &uurb->status) ||
-	    __get_user(kurb->flags, &uurb->flags) ||
-	    __get_user(kurb->buffer_length, &uurb->buffer_length) ||
-	    __get_user(kurb->actual_length, &uurb->actual_length) ||
-	    __get_user(kurb->start_frame, &uurb->start_frame) ||
-	    __get_user(kurb->number_of_packets, &uurb->number_of_packets) ||
-	    __get_user(kurb->error_count, &uurb->error_count) ||
-	    __get_user(kurb->signr, &uurb->signr))
-		return -EFAULT;
-
-	kurb->usercontext = 0; /* unused currently */
-
-	return 0;
-}
-
-/* Just put back the values which usbdevfs actually changes. */
-static int put_urb32(struct usbdevfs_urb *kurb,
-		     struct usbdevfs_urb32 *uurb)
-{
-	if (put_user(kurb->status, &uurb->status) ||
-	    __put_user(kurb->actual_length, &uurb->actual_length) ||
-	    __put_user(kurb->error_count, &uurb->error_count))
-		return -EFAULT;
-
-	if (kurb->number_of_packets != 0) {
-		int i;
-
-		for (i = 0; i < kurb->number_of_packets; i++) {
-			if (__put_user(kurb->iso_frame_desc[i].actual_length,
-				       &uurb->iso_frame_desc[i].actual_length) ||
-			    __put_user(kurb->iso_frame_desc[i].status,
-				       &uurb->iso_frame_desc[i].status))
-				return -EFAULT;
-		}
-	}
-
-	return 0;
-}
-
-static int get_urb32_isoframes(struct usbdevfs_urb *kurb,
-			       struct usbdevfs_urb32 *uurb)
-{
-	unsigned int totlen;
-	int i;
 
-	if (kurb->type != USBDEVFS_URB_TYPE_ISO) {
-		kurb->number_of_packets = 0;
-		return 0;
-	}
-
-	if (kurb->number_of_packets < 1 ||
-	    kurb->number_of_packets > 128)
-		return -EINVAL;
-
-	if (copy_from_user(&kurb->iso_frame_desc[0],
-			   &uurb->iso_frame_desc[0],
-			   sizeof(struct usbdevfs_iso_packet_desc) *
-			   kurb->number_of_packets))
-		return -EFAULT;
-
-	totlen = 0;
-	for (i = 0; i < kurb->number_of_packets; i++) {
-		unsigned int this_len;
-
-		this_len = kurb->iso_frame_desc[i].length;
-		if (this_len > 1023)
-			return -EINVAL;
-
-		totlen += this_len;
-	}
-
-	if (totlen > 32768)
-		return -EINVAL;
-
-	kurb->buffer_length = totlen;
-
-	return 0;
-}
-
-static int do_usbdevfs_urb(unsigned int fd, unsigned int cmd, unsigned long arg)
-{
-	struct usbdevfs_urb *kurb;
-	struct usbdevfs_urb32 *uurb;
-	mm_segment_t old_fs;
-	__u32 udata;
-	void *uptr, *kptr;
-	unsigned int buflen;
-	int err;
-
-	uurb = compat_ptr(arg);
-
-	err = -ENOMEM;
-	kurb = kmalloc(sizeof(struct usbdevfs_urb) +
-		       (sizeof(struct usbdevfs_iso_packet_desc) * 128),
-		       GFP_KERNEL);
-	if (!kurb)
-		goto out;
-
-	err = -EFAULT;
-	if (get_urb32(kurb, uurb))
-		goto out;
-
-	err = get_urb32_isoframes(kurb, uurb);
-	if (err)
-		goto out;
-
-	err = -EFAULT;
-	if (__get_user(udata, &uurb->buffer))
-		goto out;
-	uptr = compat_ptr(udata);
-
-	buflen = kurb->buffer_length;
-	err = verify_area(VERIFY_WRITE, uptr, buflen);
-	if (err)
-		goto out;
-
-
-	old_fs = get_fs();
-	set_fs(KERNEL_DS);
-	err = sys_ioctl(fd, USBDEVFS_SUBMITURB, (unsigned long) kurb);
-	set_fs(old_fs);
-
-	if (err >= 0) {
-		/* RED-PEN Shit, this doesn't work for async URBs :-( XXX */
-		if (put_urb32(kurb, uurb)) {
-			err = -EFAULT;
-		}
-	}
-
-out:
-	kfree(kurb);
-	return err;
-}
-#endif
-
-#define USBDEVFS_REAPURB32         _IOW('U', 12, u32)
-#define USBDEVFS_REAPURBNDELAY32   _IOW('U', 13, u32)
-
-static int do_usbdevfs_reapurb(unsigned int fd, unsigned int cmd, unsigned long arg)
-{
-        mm_segment_t old_fs;
-        void *kptr;
-        int err;
-
-        old_fs = get_fs();
-        set_fs(KERNEL_DS);
-        err = sys_ioctl(fd,
-                        (cmd == USBDEVFS_REAPURB32 ?
-                         USBDEVFS_REAPURB :
-                         USBDEVFS_REAPURBNDELAY),
-                        (unsigned long) &kptr);
-        set_fs(old_fs);
-
-        if (err >= 0 &&
-            put_user((u32)(u64)kptr, (u32 __user *)compat_ptr(arg)))
-                err = -EFAULT;
-
-        return err;
-}
+/*
+ *  USBDEVFS_SUBMITURB, USBDEVFS_REAPURB and USBDEVFS_REAPURBNDELAY
+ *  are handled in usbdevfs core.			-Christopher Li
+ */
 
 struct usbdevfs_disconnectsignal32 {
         compat_int_t signr;
@@ -3259,8 +2981,6 @@
 HANDLE_IOCTL(PPPIOCSACTIVE32, ppp_sock_fprog_ioctl_trans)
 HANDLE_IOCTL(MTIOCGET32, mt_ioctl_trans)
 HANDLE_IOCTL(MTIOCPOS32, mt_ioctl_trans)
-HANDLE_IOCTL(MTIOCGETCONFIG32, mt_ioctl_trans)
-HANDLE_IOCTL(MTIOCSETCONFIG32, mt_ioctl_trans)
 HANDLE_IOCTL(CDROMREADAUDIO, cdrom_ioctl_trans)
 HANDLE_IOCTL(CDROM_SEND_PACKET, cdrom_ioctl_trans)
 HANDLE_IOCTL(LOOP_SET_STATUS, loop_status)
@@ -3331,9 +3051,6 @@
 /* Usbdevfs */
 HANDLE_IOCTL(USBDEVFS_CONTROL32, do_usbdevfs_control)
 HANDLE_IOCTL(USBDEVFS_BULK32, do_usbdevfs_bulk)
-/*HANDLE_IOCTL(USBDEVFS_SUBMITURB32, do_usbdevfs_urb)*/
-HANDLE_IOCTL(USBDEVFS_REAPURB32, do_usbdevfs_reapurb)
-HANDLE_IOCTL(USBDEVFS_REAPURBNDELAY32, do_usbdevfs_reapurb)
 HANDLE_IOCTL(USBDEVFS_DISCSIGNAL32, do_usbdevfs_discsignal)
 /* i2c */
 HANDLE_IOCTL(I2C_FUNCS, w_long)
diff -Nru a/fs/cramfs/inode.c b/fs/cramfs/inode.c
--- a/fs/cramfs/inode.c	2005-03-11 12:51:41 -08:00
+++ b/fs/cramfs/inode.c	2005-03-11 12:51:41 -08:00
@@ -70,6 +70,7 @@
 			inode->i_data.a_ops = &cramfs_aops;
 		} else {
 			inode->i_size = 0;
+			inode->i_blocks = 0;
 			init_special_inode(inode, inode->i_mode,
 				old_decode_dev(cramfs_inode->size));
 		}
diff -Nru a/fs/dcache.c b/fs/dcache.c
--- a/fs/dcache.c	2005-03-11 12:51:41 -08:00
+++ b/fs/dcache.c	2005-03-11 12:51:41 -08:00
@@ -340,13 +340,16 @@
 	tmp = head;
 	while ((tmp = tmp->next) != head) {
 		struct dentry *dentry = list_entry(tmp, struct dentry, d_alias);
+		spin_lock(&dentry->d_lock);
 		if (!atomic_read(&dentry->d_count)) {
 			__dget_locked(dentry);
 			__d_drop(dentry);
+			spin_unlock(&dentry->d_lock);
 			spin_unlock(&dcache_lock);
 			dput(dentry);
 			goto restart;
 		}
+		spin_unlock(&dentry->d_lock);
 	}
 	spin_unlock(&dcache_lock);
 }
diff -Nru a/fs/debugfs/file.c b/fs/debugfs/file.c
--- a/fs/debugfs/file.c	2005-03-11 12:51:46 -08:00
+++ b/fs/debugfs/file.c	2005-03-11 12:51:46 -08:00
@@ -52,7 +52,7 @@
 	char buf[32];								\
 	type *val = file->private_data;						\
 										\
-	snprintf(buf, sizeof(buf), format, *val);				\
+	snprintf(buf, sizeof(buf), format "\n", *val);				\
 	return simple_read_from_buffer(user_buf, count, ppos, buf, strlen(buf));\
 }										\
 static ssize_t write_file_##type(struct file *file, const char __user *user_buf,\
@@ -186,7 +186,7 @@
 	char buf[3];
 	u32 *val = file->private_data;
 	
-	if (val)
+	if (*val)
 		buf[0] = 'Y';
 	else
 		buf[0] = 'N';
diff -Nru a/fs/direct-io.c b/fs/direct-io.c
--- a/fs/direct-io.c	2005-03-11 12:51:47 -08:00
+++ b/fs/direct-io.c	2005-03-11 12:51:47 -08:00
@@ -1206,7 +1206,8 @@
 	 */
 	dio->lock_type = dio_lock_type;
 	if (dio_lock_type != DIO_NO_LOCKING) {
-		if (rw == READ) {
+		/* watch out for a 0 len io from a tricksy fs */
+		if (rw == READ && end > offset) {
 			struct address_space *mapping;
 
 			mapping = iocb->ki_filp->f_mapping;
@@ -1214,7 +1215,9 @@
 				down(&inode->i_sem);
 				reader_with_isem = 1;
 			}
-			retval = filemap_write_and_wait(mapping);
+
+			retval = filemap_write_and_wait_range(mapping, offset,
+							      end - 1);
 			if (retval) {
 				kfree(dio);
 				goto out;
diff -Nru a/fs/eventpoll.c b/fs/eventpoll.c
--- a/fs/eventpoll.c	2005-03-11 12:51:42 -08:00
+++ b/fs/eventpoll.c	2005-03-11 12:51:42 -08:00
@@ -619,6 +619,7 @@
 	return error;
 }
 
+#define MAX_EVENTS (INT_MAX / sizeof(struct epoll_event))
 
 /*
  * Implement the event wait interface for the eventpoll file. It is the kernel
@@ -635,7 +636,7 @@
 		     current, epfd, events, maxevents, timeout));
 
 	/* The maximum number of event must be greater than zero */
-	if (maxevents <= 0)
+	if (maxevents <= 0 || maxevents > MAX_EVENTS)
 		return -EINVAL;
 
 	/* Verify that the area passed by the user is writeable */
diff -Nru a/fs/exec.c b/fs/exec.c
--- a/fs/exec.c	2005-03-11 12:51:42 -08:00
+++ b/fs/exec.c	2005-03-11 12:51:42 -08:00
@@ -328,7 +328,7 @@
 	}
 	mm->rss++;
 	lru_cache_add_active(page);
-	set_pte(pte, pte_mkdirty(pte_mkwrite(mk_pte(
+	set_pte_at(mm, address, pte, pte_mkdirty(pte_mkwrite(mk_pte(
 					page, vma->vm_page_prot))));
 	page_add_anon_rmap(page, vma, address);
 	pte_unmap(pte);
@@ -400,7 +400,8 @@
 	while (i < MAX_ARG_PAGES)
 		bprm->page[i++] = NULL;
 #else
-	stack_base = stack_top - MAX_ARG_PAGES * PAGE_SIZE;
+	stack_base = arch_align_stack(stack_top - MAX_ARG_PAGES*PAGE_SIZE);
+	stack_base = PAGE_ALIGN(stack_base);
 	bprm->p += stack_base;
 	mm->arg_start = bprm->p;
 	arg_size = stack_top - (PAGE_MASK & (unsigned long) mm->arg_start);
@@ -877,6 +878,7 @@
 	tcomm[i] = '\0';
 	set_task_comm(current, tcomm);
 
+	current->flags &= ~PF_RANDOMIZE;
 	flush_thread();
 
 	if (bprm->e_uid != current->euid || bprm->e_gid != current->egid || 
@@ -1191,8 +1193,8 @@
 
 		/* execve success */
 		security_bprm_free(bprm);
-		acct_update_integrals();
-		update_mem_hiwater();
+		acct_update_integrals(current);
+		update_mem_hiwater(current);
 		kfree(bprm);
 		return retval;
 	}
diff -Nru a/fs/exportfs/expfs.c b/fs/exportfs/expfs.c
--- a/fs/exportfs/expfs.c	2005-03-11 12:51:51 -08:00
+++ b/fs/exportfs/expfs.c	2005-03-11 12:51:51 -08:00
@@ -55,7 +55,7 @@
 	struct list_head *le, *head;
 	struct dentry *toput = NULL;
 	int noprogress;
-
+	char nbuf[NAME_MAX+1];
 
 	/*
 	 * Attempt to find the inode.
@@ -176,7 +176,6 @@
 			 */
 			struct dentry *ppd;
 			struct dentry *npd;
-			char nbuf[NAME_MAX+1];
 
 			down(&pd->d_inode->i_sem);
 			ppd = CALL(nops,get_parent)(pd);
@@ -241,7 +240,6 @@
 	/* if we weren't after a directory, have one more step to go */
 	if (result != target_dir) {
 		struct dentry *nresult;
-		char nbuf[NAME_MAX+1];
 		err = CALL(nops,get_name)(target_dir, nbuf, result);
 		if (!err) {
 			down(&target_dir->d_inode->i_sem);
diff -Nru a/fs/ext2/inode.c b/fs/ext2/inode.c
--- a/fs/ext2/inode.c	2005-03-11 12:51:41 -08:00
+++ b/fs/ext2/inode.c	2005-03-11 12:51:41 -08:00
@@ -626,6 +626,12 @@
 	return nobh_prepare_write(page,from,to,ext2_get_block);
 }
 
+static int ext2_nobh_writepage(struct page *page,
+			struct writeback_control *wbc)
+{
+	return nobh_writepage(page, ext2_get_block, wbc);
+}
+
 static sector_t ext2_bmap(struct address_space *mapping, sector_t block)
 {
 	return generic_block_bmap(mapping,block,ext2_get_block);
@@ -675,7 +681,7 @@
 struct address_space_operations ext2_nobh_aops = {
 	.readpage		= ext2_readpage,
 	.readpages		= ext2_readpages,
-	.writepage		= ext2_writepage,
+	.writepage		= ext2_nobh_writepage,
 	.sync_page		= block_sync_page,
 	.prepare_write		= ext2_nobh_prepare_write,
 	.commit_write		= nobh_commit_write,
diff -Nru a/fs/ext3/balloc.c b/fs/ext3/balloc.c
--- a/fs/ext3/balloc.c	2005-03-11 12:51:41 -08:00
+++ b/fs/ext3/balloc.c	2005-03-11 12:51:41 -08:00
@@ -43,34 +43,34 @@
 					     struct buffer_head ** bh)
 {
 	unsigned long group_desc;
-	unsigned long desc;
-	struct ext3_group_desc * gdp;
+	unsigned long offset;
+	struct ext3_group_desc * desc;
+	struct ext3_sb_info *sbi = EXT3_SB(sb);
 
-	if (block_group >= EXT3_SB(sb)->s_groups_count) {
+	if (block_group >= sbi->s_groups_count) {
 		ext3_error (sb, "ext3_get_group_desc",
 			    "block_group >= groups_count - "
 			    "block_group = %d, groups_count = %lu",
-			    block_group, EXT3_SB(sb)->s_groups_count);
+			    block_group, sbi->s_groups_count);
 
 		return NULL;
 	}
 	smp_rmb();
 
 	group_desc = block_group >> EXT3_DESC_PER_BLOCK_BITS(sb);
-	desc = block_group & (EXT3_DESC_PER_BLOCK(sb) - 1);
-	if (!EXT3_SB(sb)->s_group_desc[group_desc]) {
+	offset = block_group & (EXT3_DESC_PER_BLOCK(sb) - 1);
+	if (!sbi->s_group_desc[group_desc]) {
 		ext3_error (sb, "ext3_get_group_desc",
 			    "Group descriptor not loaded - "
 			    "block_group = %d, group_desc = %lu, desc = %lu",
-			     block_group, group_desc, desc);
+			     block_group, group_desc, offset);
 		return NULL;
 	}
 
-	gdp = (struct ext3_group_desc *) 
-	      EXT3_SB(sb)->s_group_desc[group_desc]->b_data;
+	desc = (struct ext3_group_desc *) sbi->s_group_desc[group_desc]->b_data;
 	if (bh)
-		*bh = EXT3_SB(sb)->s_group_desc[group_desc];
-	return gdp + desc;
+		*bh = sbi->s_group_desc[group_desc];
+	return desc + offset;
 }
 
 /*
@@ -268,7 +268,8 @@
 
 	if (!rsv_is_empty(&rsv->rsv_window)) {
 		spin_lock(rsv_lock);
-		rsv_window_remove(inode->i_sb, rsv);
+		if (!rsv_is_empty(&rsv->rsv_window))
+			rsv_window_remove(inode->i_sb, rsv);
 		spin_unlock(rsv_lock);
 	}
 }
@@ -284,14 +285,15 @@
 	unsigned long bit;
 	unsigned long i;
 	unsigned long overflow;
-	struct ext3_group_desc * gdp;
+	struct ext3_group_desc * desc;
 	struct ext3_super_block * es;
 	struct ext3_sb_info *sbi;
 	int err = 0, ret;
+	unsigned group_freed;
 
 	*pdquot_freed_blocks = 0;
 	sbi = EXT3_SB(sb);
-	es = EXT3_SB(sb)->s_es;
+	es = sbi->s_es;
 	if (block < le32_to_cpu(es->s_first_data_block) ||
 	    block + count < block ||
 	    block + count > le32_to_cpu(es->s_blocks_count)) {
@@ -301,7 +303,7 @@
 		goto error_return;
 	}
 
-	ext3_debug ("freeing block %lu\n", block);
+	ext3_debug ("freeing block(s) %lu-%lu\n", block, block + count - 1);
 
 do_more:
 	overflow = 0;
@@ -321,16 +323,16 @@
 	bitmap_bh = read_block_bitmap(sb, block_group);
 	if (!bitmap_bh)
 		goto error_return;
-	gdp = ext3_get_group_desc (sb, block_group, &gd_bh);
-	if (!gdp)
+	desc = ext3_get_group_desc (sb, block_group, &gd_bh);
+	if (!desc)
 		goto error_return;
 
-	if (in_range (le32_to_cpu(gdp->bg_block_bitmap), block, count) ||
-	    in_range (le32_to_cpu(gdp->bg_inode_bitmap), block, count) ||
-	    in_range (block, le32_to_cpu(gdp->bg_inode_table),
-		      EXT3_SB(sb)->s_itb_per_group) ||
-	    in_range (block + count - 1, le32_to_cpu(gdp->bg_inode_table),
-		      EXT3_SB(sb)->s_itb_per_group))
+	if (in_range (le32_to_cpu(desc->bg_block_bitmap), block, count) ||
+	    in_range (le32_to_cpu(desc->bg_inode_bitmap), block, count) ||
+	    in_range (block, le32_to_cpu(desc->bg_inode_table),
+		      sbi->s_itb_per_group) ||
+	    in_range (block + count - 1, le32_to_cpu(desc->bg_inode_table),
+		      sbi->s_itb_per_group))
 		ext3_error (sb, "ext3_free_blocks",
 			    "Freeing blocks in system zones - "
 			    "Block = %lu, count = %lu",
@@ -342,7 +344,7 @@
 	 */
 	/* @@@ check errors */
 	BUFFER_TRACE(bitmap_bh, "getting undo access");
-	err = ext3_journal_get_undo_access(handle, bitmap_bh, NULL);
+	err = ext3_journal_get_undo_access(handle, bitmap_bh);
 	if (err)
 		goto error_return;
 
@@ -358,7 +360,7 @@
 
 	jbd_lock_bh_state(bitmap_bh);
 
-	for (i = 0; i < count; i++) {
+	for (i = 0, group_freed = 0; i < count; i++) {
 		/*
 		 * An HJ special.  This is expensive...
 		 */
@@ -421,15 +423,15 @@
 			jbd_lock_bh_state(bitmap_bh);
 			BUFFER_TRACE(bitmap_bh, "bit already cleared");
 		} else {
-			(*pdquot_freed_blocks)++;
+			group_freed++;
 		}
 	}
 	jbd_unlock_bh_state(bitmap_bh);
 
 	spin_lock(sb_bgl_lock(sbi, block_group));
-	gdp->bg_free_blocks_count =
-		cpu_to_le16(le16_to_cpu(gdp->bg_free_blocks_count) +
-			*pdquot_freed_blocks);
+	desc->bg_free_blocks_count =
+		cpu_to_le16(le16_to_cpu(desc->bg_free_blocks_count) +
+			group_freed);
 	spin_unlock(sb_bgl_lock(sbi, block_group));
 	percpu_counter_mod(&sbi->s_freeblocks_counter, count);
 
@@ -441,6 +443,7 @@
 	BUFFER_TRACE(gd_bh, "dirtied group descriptor block");
 	ret = ext3_journal_dirty_metadata(handle, gd_bh);
 	if (!err) err = ret;
+	*pdquot_freed_blocks += group_freed;
 
 	if (overflow && !err) {
 		block += count;
@@ -991,7 +994,6 @@
 	unsigned long group_first_block;
 	int ret = 0;
 	int fatal;
-	int credits = 0;
 
 	*errp = 0;
 
@@ -1001,7 +1003,7 @@
 	 * if the buffer is in BJ_Forget state in the committing transaction.
 	 */
 	BUFFER_TRACE(bitmap_bh, "get undo access for new block");
-	fatal = ext3_journal_get_undo_access(handle, bitmap_bh, &credits);
+	fatal = ext3_journal_get_undo_access(handle, bitmap_bh);
 	if (fatal) {
 		*errp = fatal;
 		return -1;
@@ -1092,7 +1094,7 @@
 	}
 
 	BUFFER_TRACE(bitmap_bh, "journal_release_buffer");
-	ext3_journal_release_buffer(handle, bitmap_bh, credits);
+	ext3_journal_release_buffer(handle, bitmap_bh);
 	return ret;
 }
 
@@ -1429,9 +1431,8 @@
 #endif
 }
 
-static inline int block_in_use(unsigned long block,
-				struct super_block * sb,
-				unsigned char * map)
+static inline int
+block_in_use(unsigned long block, struct super_block *sb, unsigned char *map)
 {
 	return ext3_test_bit ((block -
 		le32_to_cpu(EXT3_SB(sb)->s_es->s_first_data_block)) %
@@ -1451,8 +1452,10 @@
 {
 	if (group <= 1)
 		return 1;
-	return (test_root(group, 3) || test_root(group, 5) ||
-		test_root(group, 7));
+	if (!(group & 1))
+		return 0;
+	return (test_root(group, 7) || test_root(group, 5) ||
+		test_root(group, 3));
 }
 
 /**
diff -Nru a/fs/ext3/hash.c b/fs/ext3/hash.c
--- a/fs/ext3/hash.c	2005-03-11 12:51:46 -08:00
+++ b/fs/ext3/hash.c	2005-03-11 12:51:46 -08:00
@@ -13,6 +13,7 @@
 #include <linux/jbd.h>
 #include <linux/sched.h>
 #include <linux/ext3_fs.h>
+#include <linux/cryptohash.h>
 
 #define DELTA 0x9E3779B9
 
@@ -33,73 +34,6 @@
 	buf[1] += b1;
 }
 
-/* F, G and H are basic MD4 functions: selection, majority, parity */
-#define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))
-#define G(x, y, z) (((x) & (y)) + (((x) ^ (y)) & (z)))
-#define H(x, y, z) ((x) ^ (y) ^ (z))
-
-/*
- * The generic round function.  The application is so specific that
- * we don't bother protecting all the arguments with parens, as is generally
- * good macro practice, in favor of extra legibility.
- * Rotation is separate from addition to prevent recomputation
- */
-#define ROUND(f, a, b, c, d, x, s)	\
-	(a += f(b, c, d) + x, a = (a << s) | (a >> (32-s)))
-#define K1 0
-#define K2 013240474631UL
-#define K3 015666365641UL
-
-/*
- * Basic cut-down MD4 transform.  Returns only 32 bits of result.
- */
-static void halfMD4Transform (__u32 buf[4], __u32 const in[])
-{
-	__u32	a = buf[0], b = buf[1], c = buf[2], d = buf[3];
-
-	/* Round 1 */
-	ROUND(F, a, b, c, d, in[0] + K1,  3);
-	ROUND(F, d, a, b, c, in[1] + K1,  7);
-	ROUND(F, c, d, a, b, in[2] + K1, 11);
-	ROUND(F, b, c, d, a, in[3] + K1, 19);
-	ROUND(F, a, b, c, d, in[4] + K1,  3);
-	ROUND(F, d, a, b, c, in[5] + K1,  7);
-	ROUND(F, c, d, a, b, in[6] + K1, 11);
-	ROUND(F, b, c, d, a, in[7] + K1, 19);
-
-	/* Round 2 */
-	ROUND(G, a, b, c, d, in[1] + K2,  3);
-	ROUND(G, d, a, b, c, in[3] + K2,  5);
-	ROUND(G, c, d, a, b, in[5] + K2,  9);
-	ROUND(G, b, c, d, a, in[7] + K2, 13);
-	ROUND(G, a, b, c, d, in[0] + K2,  3);
-	ROUND(G, d, a, b, c, in[2] + K2,  5);
-	ROUND(G, c, d, a, b, in[4] + K2,  9);
-	ROUND(G, b, c, d, a, in[6] + K2, 13);
-
-	/* Round 3 */
-	ROUND(H, a, b, c, d, in[3] + K3,  3);
-	ROUND(H, d, a, b, c, in[7] + K3,  9);
-	ROUND(H, c, d, a, b, in[2] + K3, 11);
-	ROUND(H, b, c, d, a, in[6] + K3, 15);
-	ROUND(H, a, b, c, d, in[1] + K3,  3);
-	ROUND(H, d, a, b, c, in[5] + K3,  9);
-	ROUND(H, c, d, a, b, in[0] + K3, 11);
-	ROUND(H, b, c, d, a, in[4] + K3, 15);
-
-	buf[0] += a;
-	buf[1] += b;
-	buf[2] += c;
-	buf[3] += d;
-}
-
-#undef ROUND
-#undef F
-#undef G
-#undef H
-#undef K1
-#undef K2
-#undef K3
 
 /* The old legacy hash */
 static __u32 dx_hack_hash (const char *name, int len)
@@ -187,7 +121,7 @@
 		p = name;
 		while (len > 0) {
 			str2hashbuf(p, len, in, 8);
-			halfMD4Transform(buf, in);
+			half_md4_transform(buf, in);
 			len -= 32;
 			p += 32;
 		}
diff -Nru a/fs/ext3/ialloc.c b/fs/ext3/ialloc.c
--- a/fs/ext3/ialloc.c	2005-03-11 12:51:46 -08:00
+++ b/fs/ext3/ialloc.c	2005-03-11 12:51:46 -08:00
@@ -460,9 +460,12 @@
 		goto out;
 
 	for (i = 0; i < sbi->s_groups_count; i++) {
+		err = -EIO;
+
 		gdp = ext3_get_group_desc(sb, group, &bh2);
+		if (!gdp)
+			goto fail;
 
-		err = -EIO;
 		brelse(bitmap_bh);
 		bitmap_bh = read_inode_bitmap(sb, group);
 		if (!bitmap_bh)
@@ -474,11 +477,9 @@
 		ino = ext3_find_next_zero_bit((unsigned long *)
 				bitmap_bh->b_data, EXT3_INODES_PER_GROUP(sb), ino);
 		if (ino < EXT3_INODES_PER_GROUP(sb)) {
-			int credits = 0;
 
 			BUFFER_TRACE(bitmap_bh, "get_write_access");
-			err = ext3_journal_get_write_access_credits(handle,
-							bitmap_bh, &credits);
+			err = ext3_journal_get_write_access(handle, bitmap_bh);
 			if (err)
 				goto fail;
 
@@ -494,7 +495,7 @@
 				goto got;
 			}
 			/* we lost it */
-			journal_release_buffer(handle, bitmap_bh, credits);
+			journal_release_buffer(handle, bitmap_bh);
 
 			if (++ino < EXT3_INODES_PER_GROUP(sb))
 				goto repeat_in_this_group;
diff -Nru a/fs/fat/Makefile b/fs/fat/Makefile
--- a/fs/fat/Makefile	2005-03-11 12:51:52 -08:00
+++ b/fs/fat/Makefile	2005-03-11 12:51:52 -08:00
@@ -4,4 +4,4 @@
 
 obj-$(CONFIG_FAT_FS) += fat.o
 
-fat-objs := cache.o dir.o file.o inode.o misc.o
+fat-objs := cache.o dir.o fatent.o file.o inode.o misc.o
diff -Nru a/fs/fat/cache.c b/fs/fat/cache.c
--- a/fs/fat/cache.c	2005-03-11 12:51:51 -08:00
+++ b/fs/fat/cache.c	2005-03-11 12:51:51 -08:00
@@ -203,124 +203,6 @@
 	spin_unlock(&MSDOS_I(inode)->cache_lru_lock);
 }
 
-static int __fat_access(struct super_block *sb, int nr, int new_value)
-{
-	struct msdos_sb_info *sbi = MSDOS_SB(sb);
-	struct buffer_head *bh, *bh2, *c_bh, *c_bh2;
-	unsigned char *p_first, *p_last;
-	int copy, first, last, next, b;
-
-	if (sbi->fat_bits == 32) {
-		first = last = nr*4;
-	} else if (sbi->fat_bits == 16) {
-		first = last = nr*2;
-	} else {
-		first = nr*3/2;
-		last = first+1;
-	}
-	b = sbi->fat_start + (first >> sb->s_blocksize_bits);
-	if (!(bh = sb_bread(sb, b))) {
-		printk(KERN_ERR "FAT: bread(block %d) in"
-		       " fat_access failed\n", b);
-		return -EIO;
-	}
-	if ((first >> sb->s_blocksize_bits) == (last >> sb->s_blocksize_bits)) {
-		bh2 = bh;
-	} else {
-		if (!(bh2 = sb_bread(sb, b + 1))) {
-			brelse(bh);
-			printk(KERN_ERR "FAT: bread(block %d) in"
-			       " fat_access failed\n", b + 1);
-			return -EIO;
-		}
-	}
-	if (sbi->fat_bits == 32) {
-		p_first = p_last = NULL; /* GCC needs that stuff */
-		next = le32_to_cpu(((__le32 *) bh->b_data)[(first &
-		    (sb->s_blocksize - 1)) >> 2]);
-		/* Fscking Microsoft marketing department. Their "32" is 28. */
-		next &= 0x0fffffff;
-	} else if (sbi->fat_bits == 16) {
-		p_first = p_last = NULL; /* GCC needs that stuff */
-		next = le16_to_cpu(((__le16 *) bh->b_data)[(first &
-		    (sb->s_blocksize - 1)) >> 1]);
-	} else {
-		p_first = &((__u8 *)bh->b_data)[first & (sb->s_blocksize - 1)];
-		p_last = &((__u8 *)bh2->b_data)[(first + 1) & (sb->s_blocksize - 1)];
-		if (nr & 1)
-			next = ((*p_first >> 4) | (*p_last << 4)) & 0xfff;
-		else
-			next = (*p_first+(*p_last << 8)) & 0xfff;
-	}
-	if (new_value != -1) {
-		if (sbi->fat_bits == 32) {
-			((__le32 *)bh->b_data)[(first & (sb->s_blocksize - 1)) >> 2]
-				= cpu_to_le32(new_value);
-		} else if (sbi->fat_bits == 16) {
-			((__le16 *)bh->b_data)[(first & (sb->s_blocksize - 1)) >> 1]
-				= cpu_to_le16(new_value);
-		} else {
-			if (nr & 1) {
-				*p_first = (*p_first & 0xf) | (new_value << 4);
-				*p_last = new_value >> 4;
-			}
-			else {
-				*p_first = new_value & 0xff;
-				*p_last = (*p_last & 0xf0) | (new_value >> 8);
-			}
-			mark_buffer_dirty(bh2);
-		}
-		mark_buffer_dirty(bh);
-		for (copy = 1; copy < sbi->fats; copy++) {
-			b = sbi->fat_start + (first >> sb->s_blocksize_bits)
-				+ sbi->fat_length * copy;
-			if (!(c_bh = sb_bread(sb, b)))
-				break;
-			if (bh != bh2) {
-				if (!(c_bh2 = sb_bread(sb, b+1))) {
-					brelse(c_bh);
-					break;
-				}
-				memcpy(c_bh2->b_data, bh2->b_data, sb->s_blocksize);
-				mark_buffer_dirty(c_bh2);
-				brelse(c_bh2);
-			}
-			memcpy(c_bh->b_data, bh->b_data, sb->s_blocksize);
-			mark_buffer_dirty(c_bh);
-			brelse(c_bh);
-		}
-	}
-	brelse(bh);
-	if (bh != bh2)
-		brelse(bh2);
-	return next;
-}
-
-/*
- * Returns the this'th FAT entry, -1 if it is an end-of-file entry. If
- * new_value is != -1, that FAT entry is replaced by it.
- */
-int fat_access(struct super_block *sb, int nr, int new_value)
-{
-	int next;
-
-	next = -EIO;
-	if (nr < FAT_START_ENT || MSDOS_SB(sb)->max_cluster <= nr) {
-		fat_fs_panic(sb, "invalid access to FAT (entry 0x%08x)", nr);
-		goto out;
-	}
-	if (new_value == FAT_ENT_EOF)
-		new_value = EOF_FAT(sb);
-
-	next = __fat_access(sb, nr, new_value);
-	if (next < 0)
-		goto out;
-	if (next >= BAD_FAT(sb))
-		next = FAT_ENT_EOF;
-out:
-	return next;
-}
-
 static inline int cache_contiguous(struct fat_cache_id *cid, int dclus)
 {
 	cid->nr_contig++;
@@ -339,6 +221,7 @@
 {
 	struct super_block *sb = inode->i_sb;
 	const int limit = sb->s_maxbytes >> MSDOS_SB(sb)->cluster_bits;
+	struct fat_entry fatent;
 	struct fat_cache_id cid;
 	int nr;
 
@@ -357,34 +240,40 @@
 		cache_init(&cid, -1, -1);
 	}
 
+	fatent_init(&fatent);
 	while (*fclus < cluster) {
 		/* prevent the infinite loop of cluster chain */
 		if (*fclus > limit) {
 			fat_fs_panic(sb, "%s: detected the cluster chain loop"
 				     " (i_pos %lld)", __FUNCTION__,
 				     MSDOS_I(inode)->i_pos);
-			return -EIO;
+			nr = -EIO;
+			goto out;
 		}
 
-		nr = fat_access(sb, *dclus, -1);
+		nr = fat_ent_read(inode, &fatent, *dclus);
 		if (nr < 0)
-			return nr;
+			goto out;
 		else if (nr == FAT_ENT_FREE) {
 			fat_fs_panic(sb, "%s: invalid cluster chain"
 				     " (i_pos %lld)", __FUNCTION__,
 				     MSDOS_I(inode)->i_pos);
-			return -EIO;
+			nr = -EIO;
+			goto out;
 		} else if (nr == FAT_ENT_EOF) {
 			fat_cache_add(inode, &cid);
-			return FAT_ENT_EOF;
+			goto out;
 		}
 		(*fclus)++;
 		*dclus = nr;
 		if (!cache_contiguous(&cid, *dclus))
 			cache_init(&cid, *fclus, *dclus);
 	}
+	nr = 0;
 	fat_cache_add(inode, &cid);
-	return 0;
+out:
+	fatent_brelse(&fatent);
+	return nr;
 }
 
 static int fat_bmap_cluster(struct inode *inode, int cluster)
@@ -414,9 +303,7 @@
 	int cluster, offset;
 
 	*phys = 0;
-	if ((sbi->fat_bits != 32) &&
-	    (inode->i_ino == MSDOS_ROOT_INO || (S_ISDIR(inode->i_mode) &&
-	     !MSDOS_I(inode)->i_start))) {
+	if ((sbi->fat_bits != 32) && (inode->i_ino == MSDOS_ROOT_INO)) {
 		if (sector < (sbi->dir_entries >> sbi->dir_per_block_bits))
 			*phys = sector + sbi->dir_start;
 		return 0;
diff -Nru a/fs/fat/dir.c b/fs/fat/dir.c
--- a/fs/fat/dir.c	2005-03-11 12:51:52 -08:00
+++ b/fs/fat/dir.c	2005-03-11 12:51:52 -08:00
@@ -22,6 +22,72 @@
 #include <linux/buffer_head.h>
 #include <asm/uaccess.h>
 
+static inline loff_t fat_make_i_pos(struct super_block *sb,
+				    struct buffer_head *bh,
+				    struct msdos_dir_entry *de)
+{
+	return ((loff_t)bh->b_blocknr << MSDOS_SB(sb)->dir_per_block_bits)
+		| (de - (struct msdos_dir_entry *)bh->b_data);
+}
+
+/* Returns the inode number of the directory entry at offset pos. If bh is
+   non-NULL, it is brelse'd before. Pos is incremented. The buffer header is
+   returned in bh.
+   AV. Most often we do it item-by-item. Makes sense to optimize.
+   AV. OK, there we go: if both bh and de are non-NULL we assume that we just
+   AV. want the next entry (took one explicit de=NULL in vfat/namei.c).
+   AV. It's done in fat_get_entry() (inlined), here the slow case lives.
+   AV. Additionally, when we return -1 (i.e. reached the end of directory)
+   AV. we make bh NULL.
+ */
+static int fat__get_entry(struct inode *dir, loff_t *pos,
+			  struct buffer_head **bh, struct msdos_dir_entry **de)
+{
+	struct super_block *sb = dir->i_sb;
+	sector_t phys, iblock;
+	int offset;
+	int err;
+
+next:
+	if (*bh)
+		brelse(*bh);
+
+	*bh = NULL;
+	iblock = *pos >> sb->s_blocksize_bits;
+	err = fat_bmap(dir, iblock, &phys);
+	if (err || !phys)
+		return -1;	/* beyond EOF or error */
+
+	*bh = sb_bread(sb, phys);
+	if (*bh == NULL) {
+		printk(KERN_ERR "FAT: Directory bread(block %llu) failed\n",
+		       (unsigned long long)phys);
+		/* skip this block */
+		*pos = (iblock + 1) << sb->s_blocksize_bits;
+		goto next;
+	}
+
+	offset = *pos & (sb->s_blocksize - 1);
+	*pos += sizeof(struct msdos_dir_entry);
+	*de = (struct msdos_dir_entry *)((*bh)->b_data + offset);
+
+	return 0;
+}
+
+static inline int fat_get_entry(struct inode *dir, loff_t *pos,
+				struct buffer_head **bh,
+				struct msdos_dir_entry **de)
+{
+	/* Fast stuff first */
+	if (*bh && *de &&
+	    (*de - (struct msdos_dir_entry *)(*bh)->b_data) < MSDOS_SB(dir->i_sb)->dir_per_block - 1) {
+		*pos += sizeof(struct msdos_dir_entry);
+		(*de)++;
+		return 0;
+	}
+	return fat__get_entry(dir, pos, bh, de);
+}
+
 /*
  * Convert Unicode 16 to UTF8, translated Unicode, or ASCII.
  * If uni_xlate is enabled and we can't get a 1:1 conversion, use a
@@ -136,28 +202,31 @@
  * value is the total amount of slots, including the shortname entry.
  */
 int fat_search_long(struct inode *inode, const unsigned char *name,
-		    int name_len, int anycase, loff_t *spos, loff_t *lpos)
+		    int name_len, struct fat_slot_info *sinfo)
 {
 	struct super_block *sb = inode->i_sb;
+	struct msdos_sb_info *sbi = MSDOS_SB(sb);
 	struct buffer_head *bh = NULL;
 	struct msdos_dir_entry *de;
-	struct nls_table *nls_io = MSDOS_SB(sb)->nls_io;
-	struct nls_table *nls_disk = MSDOS_SB(sb)->nls_disk;
+	struct nls_table *nls_io = sbi->nls_io;
+	struct nls_table *nls_disk = sbi->nls_disk;
 	wchar_t bufuname[14];
-	unsigned char xlate_len, long_slots;
+	unsigned char xlate_len, nr_slots;
 	wchar_t *unicode = NULL;
 	unsigned char work[8], bufname[260];	/* 256 + 4 */
-	int uni_xlate = MSDOS_SB(sb)->options.unicode_xlate;
-	int utf8 = MSDOS_SB(sb)->options.utf8;
-	unsigned short opt_shortname = MSDOS_SB(sb)->options.shortname;
-	int chl, i, j, last_u, res = 0;
-	loff_t i_pos, cpos = 0;
+	int uni_xlate = sbi->options.unicode_xlate;
+	int utf8 = sbi->options.utf8;
+	int anycase = (sbi->options.name_check != 's');
+	unsigned short opt_shortname = sbi->options.shortname;
+	loff_t cpos = 0;
+	int chl, i, j, last_u, err;
 
+	err = -ENOENT;
 	while(1) {
-		if (fat_get_entry(inode,&cpos,&bh,&de,&i_pos) == -1)
+		if (fat_get_entry(inode, &cpos, &bh, &de) == -1)
 			goto EODir;
 parse_record:
-		long_slots = 0;
+		nr_slots = 0;
 		if (de->name[0] == DELETED_FLAG)
 			continue;
 		if (de->attr != ATTR_EXT && (de->attr & ATTR_VOLUME))
@@ -189,7 +258,7 @@
 			slots = id & ~0x40;
 			if (slots > 20 || !slots)	/* ceil(256 * 2 / 26) */
 				continue;
-			long_slots = slots;
+			nr_slots = slots;
 			alias_checksum = ds->alias_checksum;
 
 			slot = slots;
@@ -205,7 +274,7 @@
 				if (ds->id & 0x40) {
 					unicode[offset + 13] = 0;
 				}
-				if (fat_get_entry(inode,&cpos,&bh,&de,&i_pos)<0)
+				if (fat_get_entry(inode, &cpos, &bh, &de) < 0)
 					goto EODir;
 				if (slot == 0)
 					break;
@@ -226,7 +295,7 @@
 			for (sum = 0, i = 0; i < 11; i++)
 				sum = (((sum&1)<<7)|((sum&0xfe)>>1)) + de->name[i];
 			if (sum != alias_checksum)
-				long_slots = 0;
+				nr_slots = 0;
 		}
 
 		memcpy(work, de->name, sizeof(de->name));
@@ -274,7 +343,7 @@
 								xlate_len)))
 				goto Found;
 
-		if (long_slots) {
+		if (nr_slots) {
 			xlate_len = utf8
 				?utf8_wcstombs(bufname, unicode, sizeof(bufname))
 				:uni16_to_x8(bufname, unicode, uni_xlate, nls_io);
@@ -288,15 +357,18 @@
 	}
 
 Found:
-	res = long_slots + 1;
-	*spos = cpos - sizeof(struct msdos_dir_entry);
-	*lpos = cpos - res*sizeof(struct msdos_dir_entry);
+	nr_slots++;	/* include the de */
+	sinfo->slot_off = cpos - nr_slots * sizeof(*de);
+	sinfo->nr_slots = nr_slots;
+	sinfo->de = de;
+	sinfo->bh = bh;
+	sinfo->i_pos = fat_make_i_pos(sb, sinfo->bh, sinfo->de);
+	err = 0;
 EODir:
-	brelse(bh);
-	if (unicode) {
-		free_page((unsigned long) unicode);
-	}
-	return res;
+	if (unicode)
+		free_page((unsigned long)unicode);
+
+	return err;
 }
 
 EXPORT_SYMBOL(fat_search_long);
@@ -315,10 +387,11 @@
 			filldir_t filldir, int short_only, int both)
 {
 	struct super_block *sb = inode->i_sb;
+	struct msdos_sb_info *sbi = MSDOS_SB(sb);
 	struct buffer_head *bh;
 	struct msdos_dir_entry *de;
-	struct nls_table *nls_io = MSDOS_SB(sb)->nls_io;
-	struct nls_table *nls_disk = MSDOS_SB(sb)->nls_disk;
+	struct nls_table *nls_io = sbi->nls_io;
+	struct nls_table *nls_disk = sbi->nls_disk;
 	unsigned char long_slots;
 	const char *fill_name;
 	int fill_len;
@@ -326,14 +399,14 @@
 	wchar_t *unicode = NULL;
 	unsigned char c, work[8], bufname[56], *ptname = bufname;
 	unsigned long lpos, dummy, *furrfu = &lpos;
-	int uni_xlate = MSDOS_SB(sb)->options.unicode_xlate;
-	int isvfat = MSDOS_SB(sb)->options.isvfat;
-	int utf8 = MSDOS_SB(sb)->options.utf8;
-	int nocase = MSDOS_SB(sb)->options.nocase;
-	unsigned short opt_shortname = MSDOS_SB(sb)->options.shortname;
+	int uni_xlate = sbi->options.unicode_xlate;
+	int isvfat = sbi->options.isvfat;
+	int utf8 = sbi->options.utf8;
+	int nocase = sbi->options.nocase;
+	unsigned short opt_shortname = sbi->options.shortname;
 	unsigned long inum;
 	int chi, chl, i, i2, j, last, last_u, dotoffset = 0;
-	loff_t i_pos, cpos;
+	loff_t cpos;
 	int ret = 0;
 
 	lock_kernel();
@@ -361,7 +434,7 @@
 	bh = NULL;
 GetNew:
 	long_slots = 0;
-	if (fat_get_entry(inode,&cpos,&bh,&de,&i_pos) == -1)
+	if (fat_get_entry(inode, &cpos, &bh, &de) == -1)
 		goto EODir;
 	/* Check for long filename entry */
 	if (isvfat) {
@@ -418,7 +491,7 @@
 			if (ds->id & 0x40) {
 				unicode[offset + 13] = 0;
 			}
-			if (fat_get_entry(inode,&cpos,&bh,&de,&i_pos) == -1)
+			if (fat_get_entry(inode, &cpos, &bh, &de) == -1)
 				goto EODir;
 			if (slot == 0)
 				break;
@@ -442,9 +515,13 @@
 			long_slots = 0;
 	}
 
-	if ((de->attr & ATTR_HIDDEN) && MSDOS_SB(sb)->options.dotsOK) {
-		*ptname++ = '.';
-		dotoffset = 1;
+	if (sbi->options.dotsOK) {
+		ptname = bufname;
+		dotoffset = 0;
+		if (de->attr & ATTR_HIDDEN) {
+			*ptname++ = '.';
+			dotoffset = 1;
+		}
 	}
 
 	memcpy(work, de->name, sizeof(de->name));
@@ -501,11 +578,12 @@
 	j = last_u;
 
 	lpos = cpos - (long_slots+1)*sizeof(struct msdos_dir_entry);
-	if (!memcmp(de->name,MSDOS_DOT,11))
+	if (!memcmp(de->name, MSDOS_DOT, MSDOS_NAME))
 		inum = inode->i_ino;
-	else if (!memcmp(de->name,MSDOS_DOTDOT,11)) {
+	else if (!memcmp(de->name, MSDOS_DOTDOT, MSDOS_NAME)) {
 		inum = parent_ino(filp->f_dentry);
 	} else {
+		loff_t i_pos = fat_make_i_pos(sb, bh, de);
 		struct inode *tmp = fat_iget(sb, i_pos);
 		if (tmp) {
 			inum = tmp->i_ino;
@@ -639,7 +717,7 @@
 		both = 1;
 		break;
 	default:
-		return -EINVAL;
+		return fat_generic_ioctl(inode, filp, cmd, arg);
 	}
 
 	d1 = (struct dirent __user *)arg;
@@ -676,9 +754,9 @@
 
 static int fat_get_short_entry(struct inode *dir, loff_t *pos,
 			       struct buffer_head **bh,
-			       struct msdos_dir_entry **de, loff_t *i_pos)
+			       struct msdos_dir_entry **de)
 {
-	while (fat_get_entry(dir, pos, bh, de, i_pos) >= 0) {
+	while (fat_get_entry(dir, pos, bh, de) >= 0) {
 		/* free entry or long name entry or volume label */
 		if (!IS_FREE((*de)->name) && !((*de)->attr & ATTR_VOLUME))
 			return 0;
@@ -686,17 +764,39 @@
 	return -ENOENT;
 }
 
+/*
+ * The ".." entry can not provide the "struct fat_slot_info" informations
+ * for inode. So, this function provide the some informations only.
+ */
+int fat_get_dotdot_entry(struct inode *dir, struct buffer_head **bh,
+			 struct msdos_dir_entry **de, loff_t *i_pos)
+{
+	loff_t offset;
+
+	offset = 0;
+	*bh = NULL;
+	while (fat_get_short_entry(dir, &offset, bh, de) >= 0) {
+		if (!strncmp((*de)->name, MSDOS_DOTDOT, MSDOS_NAME)) {
+			*i_pos = fat_make_i_pos(dir->i_sb, *bh, *de);
+			return 0;
+		}
+	}
+	return -ENOENT;
+}
+
+EXPORT_SYMBOL(fat_get_dotdot_entry);
+
 /* See if directory is empty */
 int fat_dir_empty(struct inode *dir)
 {
 	struct buffer_head *bh;
 	struct msdos_dir_entry *de;
-	loff_t cpos, i_pos;
+	loff_t cpos;
 	int result = 0;
 
 	bh = NULL;
 	cpos = 0;
-	while (fat_get_short_entry(dir, &cpos, &bh, &de, &i_pos) >= 0) {
+	while (fat_get_short_entry(dir, &cpos, &bh, &de) >= 0) {
 		if (strncmp(de->name, MSDOS_DOT   , MSDOS_NAME) &&
 		    strncmp(de->name, MSDOS_DOTDOT, MSDOS_NAME)) {
 			result = -ENOTEMPTY;
@@ -717,12 +817,12 @@
 {
 	struct buffer_head *bh;
 	struct msdos_dir_entry *de;
-	loff_t cpos, i_pos;
+	loff_t cpos;
 	int count = 0;
 
 	bh = NULL;
 	cpos = 0;
-	while (fat_get_short_entry(dir, &cpos, &bh, &de, &i_pos) >= 0) {
+	while (fat_get_short_entry(dir, &cpos, &bh, &de) >= 0) {
 		if (de->attr & ATTR_DIR)
 			count++;
 	}
@@ -735,140 +835,437 @@
  * Returns an error code or zero.
  */
 int fat_scan(struct inode *dir, const unsigned char *name,
-	     struct buffer_head **bh, struct msdos_dir_entry **de,
-	     loff_t *i_pos)
+	     struct fat_slot_info *sinfo)
 {
-	loff_t cpos;
+	struct super_block *sb = dir->i_sb;
 
-	*bh = NULL;
-	cpos = 0;
-	while (fat_get_short_entry(dir, &cpos, bh, de, i_pos) >= 0) {
-		if (!strncmp((*de)->name, name, MSDOS_NAME))
+	sinfo->slot_off = 0;
+	sinfo->bh = NULL;
+	while (fat_get_short_entry(dir, &sinfo->slot_off, &sinfo->bh,
+				   &sinfo->de) >= 0) {
+		if (!strncmp(sinfo->de->name, name, MSDOS_NAME)) {
+			sinfo->slot_off -= sizeof(*sinfo->de);
+			sinfo->nr_slots = 1;
+			sinfo->i_pos = fat_make_i_pos(sb, sinfo->bh, sinfo->de);
 			return 0;
+		}
 	}
 	return -ENOENT;
 }
 
 EXPORT_SYMBOL(fat_scan);
 
-static struct buffer_head *fat_extend_dir(struct inode *inode)
+static int __fat_remove_entries(struct inode *dir, loff_t pos, int nr_slots)
 {
-	struct super_block *sb = inode->i_sb;
-	struct buffer_head *bh, *res = NULL;
-	int nr, sec_per_clus = MSDOS_SB(sb)->sec_per_clus;
-	sector_t sector, last_sector;
-
-	if (MSDOS_SB(sb)->fat_bits != 32) {
-		if (inode->i_ino == MSDOS_ROOT_INO)
-			return ERR_PTR(-ENOSPC);
-	}
-
-	nr = fat_add_cluster(inode);
-	if (nr < 0)
-		return ERR_PTR(nr);
-
-	sector = fat_clus_to_blknr(MSDOS_SB(sb), nr);
-	last_sector = sector + sec_per_clus;
-	for ( ; sector < last_sector; sector++) {
-		if ((bh = sb_getblk(sb, sector))) {
-			memset(bh->b_data, 0, sb->s_blocksize);
-			set_buffer_uptodate(bh);
-			mark_buffer_dirty(bh);
-			if (!res)
-				res = bh;
-			else
-				brelse(bh);
+	struct super_block *sb = dir->i_sb;
+	struct buffer_head *bh;
+	struct msdos_dir_entry *de, *endp;
+	int err = 0, orig_slots;
+
+	while (nr_slots) {
+		bh = NULL;
+		if (fat_get_entry(dir, &pos, &bh, &de) < 0) {
+			err = -EIO;
+			break;
 		}
+
+		orig_slots = nr_slots;
+		endp = (struct msdos_dir_entry *)(bh->b_data + sb->s_blocksize);
+		while (nr_slots && de < endp) {
+			de->name[0] = DELETED_FLAG;
+			de++;
+			nr_slots--;
+		}
+		mark_buffer_dirty(bh);
+		if (IS_DIRSYNC(dir))
+			err = sync_dirty_buffer(bh);
+		brelse(bh);
+		if (err)
+			break;
+
+		/* pos is *next* de's position, so this does `- sizeof(de)' */
+		pos += ((orig_slots - nr_slots) * sizeof(*de)) - sizeof(*de);
 	}
-	if (res == NULL)
-		res = ERR_PTR(-EIO);
-	if (inode->i_size & (sb->s_blocksize - 1)) {
-		fat_fs_panic(sb, "Odd directory size");
-		inode->i_size = (inode->i_size + sb->s_blocksize)
-			& ~((loff_t)sb->s_blocksize - 1);
+
+	return err;
+}
+
+int fat_remove_entries(struct inode *dir, struct fat_slot_info *sinfo)
+{
+	struct msdos_dir_entry *de;
+	struct buffer_head *bh;
+	int err = 0, nr_slots;
+
+	/*
+	 * First stage: Remove the shortname. By this, the directory
+	 * entry is removed.
+	 */
+	nr_slots = sinfo->nr_slots;
+	de = sinfo->de;
+	sinfo->de = NULL;
+	bh = sinfo->bh;
+	sinfo->bh = NULL;
+	while (nr_slots && de >= (struct msdos_dir_entry *)bh->b_data) {
+		de->name[0] = DELETED_FLAG;
+		de--;
+		nr_slots--;
+	}
+	mark_buffer_dirty(bh);
+	if (IS_DIRSYNC(dir))
+		err = sync_dirty_buffer(bh);
+	brelse(bh);
+	if (err)
+		return err;
+	dir->i_version++;
+
+	if (nr_slots) {
+		/*
+		 * Second stage: remove the remaining longname slots.
+		 * (This directory entry is already removed, and so return
+		 * the success)
+		 */
+		err = __fat_remove_entries(dir, sinfo->slot_off, nr_slots);
+		if (err) {
+			printk(KERN_WARNING
+			       "FAT: Couldn't remove the long name slots\n");
+		}
 	}
-	inode->i_size += MSDOS_SB(sb)->cluster_size;
-	MSDOS_I(inode)->mmu_private += MSDOS_SB(sb)->cluster_size;
 
-	return res;
+	dir->i_mtime = dir->i_atime = CURRENT_TIME_SEC;
+	if (IS_DIRSYNC(dir))
+		(void)fat_sync_inode(dir);
+	else
+		mark_inode_dirty(dir);
+
+	return 0;
 }
 
-/* This assumes that size of cluster is above the 32*slots */
+EXPORT_SYMBOL(fat_remove_entries);
 
-int fat_add_entries(struct inode *dir,int slots, struct buffer_head **bh,
-		  struct msdos_dir_entry **de, loff_t *i_pos)
+static int fat_zeroed_cluster(struct inode *dir, sector_t blknr, int nr_used,
+			      struct buffer_head **bhs, int nr_bhs)
 {
 	struct super_block *sb = dir->i_sb;
-	loff_t offset, curr;
-	int row;
-	struct buffer_head *new_bh;
+	sector_t last_blknr = blknr + MSDOS_SB(sb)->sec_per_clus;
+	int err, i, n;
 
-	offset = curr = 0;
-	*bh = NULL;
-	row = 0;
-	while (fat_get_entry(dir, &curr, bh, de, i_pos) > -1) {
-		/* check the maximum size of directory */
-		if (curr >= FAT_MAX_DIR_SIZE) {
-			brelse(*bh);
-			return -ENOSPC;
+	/* Zeroing the unused blocks on this cluster */
+	blknr += nr_used;
+	n = nr_used;
+	while (blknr < last_blknr) {
+		bhs[n] = sb_getblk(sb, blknr);
+		if (!bhs[n]) {
+			err = -ENOMEM;
+			goto error;
 		}
-
-		if (IS_FREE((*de)->name)) {
-			if (++row == slots)
-				return offset;
-		} else {
-			row = 0;
-			offset = curr;
+		memset(bhs[n]->b_data, 0, sb->s_blocksize);
+		set_buffer_uptodate(bhs[n]);
+		mark_buffer_dirty(bhs[n]);
+
+		n++;
+		blknr++;
+		if (n == nr_bhs) {
+			if (IS_DIRSYNC(dir)) {
+				err = fat_sync_bhs(bhs, n);
+				if (err)
+					goto error;
+			}
+			for (i = 0; i < n; i++)
+				brelse(bhs[i]);
+			n = 0;
 		}
 	}
-	if ((dir->i_ino == MSDOS_ROOT_INO) && (MSDOS_SB(sb)->fat_bits != 32))
-		return -ENOSPC;
-	new_bh = fat_extend_dir(dir);
-	if (IS_ERR(new_bh))
-		return PTR_ERR(new_bh);
-	brelse(new_bh);
-	do {
-		fat_get_entry(dir, &curr, bh, de, i_pos);
-	} while (++row < slots);
+	if (IS_DIRSYNC(dir)) {
+		err = fat_sync_bhs(bhs, n);
+		if (err)
+			goto error;
+	}
+	for (i = 0; i < n; i++)
+		brelse(bhs[i]);
 
-	return offset;
-}
+	return 0;
 
-EXPORT_SYMBOL(fat_add_entries);
+error:
+	for (i = 0; i < n; i++)
+		bforget(bhs[i]);
+	return err;
+}
 
-int fat_new_dir(struct inode *dir, struct inode *parent, int is_vfat)
+int fat_alloc_new_dir(struct inode *dir, struct timespec *ts)
 {
-	struct buffer_head *bh;
+	struct super_block *sb = dir->i_sb;
+	struct msdos_sb_info *sbi = MSDOS_SB(sb);
+	struct buffer_head *bhs[MAX_BUF_PER_PAGE];
 	struct msdos_dir_entry *de;
+	sector_t blknr;
 	__le16 date, time;
+	int err, cluster;
 
-	bh = fat_extend_dir(dir);
-	if (IS_ERR(bh))
-		return PTR_ERR(bh);
-
-	/* zeroed out, so... */
-	fat_date_unix2dos(dir->i_mtime.tv_sec,&time,&date);
-	de = (struct msdos_dir_entry*)&bh->b_data[0];
-	memcpy(de[0].name,MSDOS_DOT,MSDOS_NAME);
-	memcpy(de[1].name,MSDOS_DOTDOT,MSDOS_NAME);
-	de[0].attr = de[1].attr = ATTR_DIR;
+	err = fat_alloc_clusters(dir, &cluster, 1);
+	if (err)
+		goto error;
+
+	blknr = fat_clus_to_blknr(sbi, cluster);
+	bhs[0] = sb_getblk(sb, blknr);
+	if (!bhs[0]) {
+		err = -ENOMEM;
+		goto error_free;
+	}
+
+	fat_date_unix2dos(ts->tv_sec, &time, &date);
+
+	de = (struct msdos_dir_entry *)bhs[0]->b_data;
+	/* filling the new directory slots ("." and ".." entries) */
+	memcpy(de[0].name, MSDOS_DOT, MSDOS_NAME);
+	memcpy(de[1].name, MSDOS_DOTDOT, MSDOS_NAME);
+	de->attr = de[1].attr = ATTR_DIR;
+	de[0].lcase = de[1].lcase = 0;
 	de[0].time = de[1].time = time;
 	de[0].date = de[1].date = date;
-	if (is_vfat) {	/* extra timestamps */
+	de[0].ctime_cs = de[1].ctime_cs = 0;
+	if (sbi->options.isvfat) {
+		/* extra timestamps */
 		de[0].ctime = de[1].ctime = time;
-		de[0].adate = de[0].cdate =
-			de[1].adate = de[1].cdate = date;
+		de[0].adate = de[0].cdate = de[1].adate = de[1].cdate = date;
+	} else {
+		de[0].ctime = de[1].ctime = 0;
+		de[0].adate = de[0].cdate = de[1].adate = de[1].cdate = 0;
 	}
-	de[0].start = cpu_to_le16(MSDOS_I(dir)->i_logstart);
-	de[0].starthi = cpu_to_le16(MSDOS_I(dir)->i_logstart>>16);
-	de[1].start = cpu_to_le16(MSDOS_I(parent)->i_logstart);
-	de[1].starthi = cpu_to_le16(MSDOS_I(parent)->i_logstart>>16);
-	mark_buffer_dirty(bh);
-	brelse(bh);
-	dir->i_atime = dir->i_ctime = dir->i_mtime = CURRENT_TIME_SEC;
-	mark_inode_dirty(dir);
+	de[0].start = cpu_to_le16(cluster);
+	de[0].starthi = cpu_to_le16(cluster >> 16);
+	de[1].start = cpu_to_le16(MSDOS_I(dir)->i_logstart);
+	de[1].starthi = cpu_to_le16(MSDOS_I(dir)->i_logstart >> 16);
+	de[0].size = de[1].size = 0;
+	memset(de + 2, 0, sb->s_blocksize - 2 * sizeof(*de));
+	set_buffer_uptodate(bhs[0]);
+	mark_buffer_dirty(bhs[0]);
+
+	err = fat_zeroed_cluster(dir, blknr, 1, bhs, MAX_BUF_PER_PAGE);
+	if (err)
+		goto error_free;
+
+	return cluster;
+
+error_free:
+	fat_free_clusters(dir, cluster);
+error:
+	return err;
+}
+
+EXPORT_SYMBOL(fat_alloc_new_dir);
+
+static int fat_add_new_entries(struct inode *dir, void *slots, int nr_slots,
+			       int *nr_cluster, struct msdos_dir_entry **de,
+			       struct buffer_head **bh, loff_t *i_pos)
+{
+	struct super_block *sb = dir->i_sb;
+	struct msdos_sb_info *sbi = MSDOS_SB(sb);
+	struct buffer_head *bhs[MAX_BUF_PER_PAGE];
+	sector_t blknr, start_blknr, last_blknr;
+	unsigned long size, copy;
+	int err, i, n, offset, cluster[2];
+
+	/*
+	 * The minimum cluster size is 512bytes, and maximum entry
+	 * size is 32*slots (672bytes).  So, iff the cluster size is
+	 * 512bytes, we may need two clusters.
+	 */
+	size = nr_slots * sizeof(struct msdos_dir_entry);
+	*nr_cluster = (size + (sbi->cluster_size - 1)) >> sbi->cluster_bits;
+	BUG_ON(*nr_cluster > 2);
+
+	err = fat_alloc_clusters(dir, cluster, *nr_cluster);
+	if (err)
+		goto error;
+
+	/*
+	 * First stage: Fill the directory entry.  NOTE: This cluster
+	 * is not referenced from any inode yet, so updates order is
+	 * not important.
+	 */
+	i = n = copy = 0;
+	do {
+		start_blknr = blknr = fat_clus_to_blknr(sbi, cluster[i]);
+		last_blknr = start_blknr + sbi->sec_per_clus;
+		while (blknr < last_blknr) {
+			bhs[n] = sb_getblk(sb, blknr);
+			if (!bhs[n]) {
+				err = -ENOMEM;
+				goto error_nomem;
+			}
+
+			/* fill the directory entry */
+			copy = min(size, sb->s_blocksize);
+			memcpy(bhs[n]->b_data, slots, copy);
+			slots += copy;
+			size -= copy;
+			set_buffer_uptodate(bhs[n]);
+			mark_buffer_dirty(bhs[n]);
+			if (!size)
+				break;
+			n++;
+			blknr++;
+		}
+	} while (++i < *nr_cluster);
+
+	memset(bhs[n]->b_data + copy, 0, sb->s_blocksize - copy);
+	offset = copy - sizeof(struct msdos_dir_entry);
+	get_bh(bhs[n]);
+	*bh = bhs[n];
+	*de = (struct msdos_dir_entry *)((*bh)->b_data + offset);
+	*i_pos = fat_make_i_pos(sb, *bh, *de);
+
+	/* Second stage: clear the rest of cluster, and write outs */
+	err = fat_zeroed_cluster(dir, start_blknr, ++n, bhs, MAX_BUF_PER_PAGE);
+	if (err)
+		goto error_free;
+
+	return cluster[0];
+
+error_free:
+	brelse(*bh);
+	*bh = NULL;
+	n = 0;
+error_nomem:
+	for (i = 0; i < n; i++)
+		bforget(bhs[i]);
+	fat_free_clusters(dir, cluster[0]);
+error:
+	return err;
+}
+
+int fat_add_entries(struct inode *dir, void *slots, int nr_slots,
+		    struct fat_slot_info *sinfo)
+{
+	struct super_block *sb = dir->i_sb;
+	struct msdos_sb_info *sbi = MSDOS_SB(sb);
+	struct buffer_head *bh, *prev, *bhs[3]; /* 32*slots (672bytes) */
+	struct msdos_dir_entry *de;
+	int err, free_slots, i, nr_bhs;
+	loff_t pos, i_pos;
+
+	sinfo->nr_slots = nr_slots;
+
+	/* First stage: search free direcotry entries */
+	free_slots = nr_bhs = 0;
+	bh = prev = NULL;
+	pos = 0;
+	err = -ENOSPC;
+	while (fat_get_entry(dir, &pos, &bh, &de) > -1) {
+		/* check the maximum size of directory */
+		if (pos >= FAT_MAX_DIR_SIZE)
+			goto error;
+
+		if (IS_FREE(de->name)) {
+			if (prev != bh) {
+				get_bh(bh);
+				bhs[nr_bhs] = prev = bh;
+				nr_bhs++;
+			}
+			free_slots++;
+			if (free_slots == nr_slots)
+				goto found;
+		} else {
+			for (i = 0; i < nr_bhs; i++)
+				brelse(bhs[i]);
+			prev = NULL;
+			free_slots = nr_bhs = 0;
+		}
+	}
+	if (dir->i_ino == MSDOS_ROOT_INO) {
+		if (sbi->fat_bits != 32)
+			goto error;
+	} else if (MSDOS_I(dir)->i_start == 0) {
+		printk(KERN_ERR "FAT: Corrupted directory (i_pos %lld)\n",
+		       MSDOS_I(dir)->i_pos);
+		err = -EIO;
+		goto error;
+	}
+
+found:
+	err = 0;
+	pos -= free_slots * sizeof(*de);
+	nr_slots -= free_slots;
+	if (free_slots) {
+		/*
+		 * Second stage: filling the free entries with new entries.
+		 * NOTE: If this slots has shortname, first, we write
+		 * the long name slots, then write the short name.
+		 */
+		int size = free_slots * sizeof(*de);
+		int offset = pos & (sb->s_blocksize - 1);
+		int long_bhs = nr_bhs - (nr_slots == 0);
+
+		/* Fill the long name slots. */
+		for (i = 0; i < long_bhs; i++) {
+			int copy = min_t(int, sb->s_blocksize - offset, size);
+			memcpy(bhs[i]->b_data + offset, slots, copy);
+			mark_buffer_dirty(bhs[i]);
+			offset = 0;
+			slots += copy;
+			size -= copy;
+		}
+		if (long_bhs && IS_DIRSYNC(dir))
+			err = fat_sync_bhs(bhs, long_bhs);
+		if (!err && i < nr_bhs) {
+			/* Fill the short name slot. */
+			int copy = min_t(int, sb->s_blocksize - offset, size);
+			memcpy(bhs[i]->b_data + offset, slots, copy);
+			mark_buffer_dirty(bhs[i]);
+			if (IS_DIRSYNC(dir))
+				err = sync_dirty_buffer(bhs[i]);
+		}
+		for (i = 0; i < nr_bhs; i++)
+			brelse(bhs[i]);
+		if (err)
+			goto error_remove;
+	}
+
+	if (nr_slots) {
+		int cluster, nr_cluster;
+
+		/*
+		 * Third stage: allocate the cluster for new entries.
+		 * And initialize the cluster with new entries, then
+		 * add the cluster to dir.
+		 */
+		cluster = fat_add_new_entries(dir, slots, nr_slots, &nr_cluster,
+					      &de, &bh, &i_pos);
+		if (cluster < 0) {
+			err = cluster;
+			goto error_remove;
+		}
+		err = fat_chain_add(dir, cluster, nr_cluster);
+		if (err) {
+			fat_free_clusters(dir, cluster);
+			goto error_remove;
+		}
+		if (dir->i_size & (sbi->cluster_size - 1)) {
+			fat_fs_panic(sb, "Odd directory size");
+			dir->i_size = (dir->i_size + sbi->cluster_size - 1)
+				& ~((loff_t)sbi->cluster_size - 1);
+		}
+		dir->i_size += nr_cluster << sbi->cluster_bits;
+		MSDOS_I(dir)->mmu_private += nr_cluster << sbi->cluster_bits;
+	}
+	sinfo->slot_off = pos;
+	sinfo->de = de;
+	sinfo->bh = bh;
+	sinfo->i_pos = fat_make_i_pos(sb, sinfo->bh, sinfo->de);
 
 	return 0;
+
+error:
+	brelse(bh);
+	for (i = 0; i < nr_bhs; i++)
+		brelse(bhs[i]);
+	return err;
+
+error_remove:
+	brelse(bh);
+	if (free_slots)
+		__fat_remove_entries(dir, pos, free_slots);
+	return err;
 }
 
-EXPORT_SYMBOL(fat_new_dir);
+EXPORT_SYMBOL(fat_add_entries);
diff -Nru a/fs/fat/fatent.c b/fs/fat/fatent.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/fs/fat/fatent.c	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,612 @@
+/*
+ * Copyright (C) 2004, OGAWA Hirofumi
+ * Released under GPL v2.
+ */
+
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/msdos_fs.h>
+
+struct fatent_operations {
+	void (*ent_blocknr)(struct super_block *, int, int *, sector_t *);
+	void (*ent_set_ptr)(struct fat_entry *, int);
+	int (*ent_bread)(struct super_block *, struct fat_entry *,
+			 int, sector_t);
+	int (*ent_get)(struct fat_entry *);
+	void (*ent_put)(struct fat_entry *, int);
+	int (*ent_next)(struct fat_entry *);
+};
+
+static void fat12_ent_blocknr(struct super_block *sb, int entry,
+			      int *offset, sector_t *blocknr)
+{
+	struct msdos_sb_info *sbi = MSDOS_SB(sb);
+	int bytes = entry + (entry >> 1);
+	WARN_ON(entry < FAT_START_ENT || sbi->max_cluster <= entry);
+	*offset = bytes & (sb->s_blocksize - 1);
+	*blocknr = sbi->fat_start + (bytes >> sb->s_blocksize_bits);
+}
+
+static void fat_ent_blocknr(struct super_block *sb, int entry,
+			    int *offset, sector_t *blocknr)
+{
+	struct msdos_sb_info *sbi = MSDOS_SB(sb);
+	int bytes = (entry << sbi->fatent_shift);
+	WARN_ON(entry < FAT_START_ENT || sbi->max_cluster <= entry);
+	*offset = bytes & (sb->s_blocksize - 1);
+	*blocknr = sbi->fat_start + (bytes >> sb->s_blocksize_bits);
+}
+
+static void fat12_ent_set_ptr(struct fat_entry *fatent, int offset)
+{
+	struct buffer_head **bhs = fatent->bhs;
+	if (fatent->nr_bhs == 1) {
+		WARN_ON(offset >= (bhs[0]->b_size - 1));
+		fatent->u.ent12_p[0] = bhs[0]->b_data + offset;
+		fatent->u.ent12_p[1] = bhs[0]->b_data + (offset + 1);
+	} else {
+		WARN_ON(offset != (bhs[0]->b_size - 1));
+		fatent->u.ent12_p[0] = bhs[0]->b_data + offset;
+		fatent->u.ent12_p[1] = bhs[1]->b_data;
+	}
+}
+
+static void fat16_ent_set_ptr(struct fat_entry *fatent, int offset)
+{
+	WARN_ON(offset & (2 - 1));
+	fatent->u.ent16_p = (__le16 *)(fatent->bhs[0]->b_data + offset);
+}
+
+static void fat32_ent_set_ptr(struct fat_entry *fatent, int offset)
+{
+	WARN_ON(offset & (4 - 1));
+	fatent->u.ent32_p = (__le32 *)(fatent->bhs[0]->b_data + offset);
+}
+
+static int fat12_ent_bread(struct super_block *sb, struct fat_entry *fatent,
+			   int offset, sector_t blocknr)
+{
+	struct buffer_head **bhs = fatent->bhs;
+
+	WARN_ON(blocknr < MSDOS_SB(sb)->fat_start);
+	bhs[0] = sb_bread(sb, blocknr);
+	if (!bhs[0])
+		goto err;
+
+	if ((offset + 1) < sb->s_blocksize)
+		fatent->nr_bhs = 1;
+	else {
+		/* This entry is block boundary, it needs the next block */
+		blocknr++;
+		bhs[1] = sb_bread(sb, blocknr);
+		if (!bhs[1])
+			goto err_brelse;
+		fatent->nr_bhs = 2;
+	}
+	fat12_ent_set_ptr(fatent, offset);
+	return 0;
+
+err_brelse:
+	brelse(bhs[0]);
+err:
+	printk(KERN_ERR "FAT: FAT read failed (blocknr %llu)\n",
+	       (unsigned long long)blocknr);
+	return -EIO;
+}
+
+static int fat_ent_bread(struct super_block *sb, struct fat_entry *fatent,
+			 int offset, sector_t blocknr)
+{
+	struct fatent_operations *ops = MSDOS_SB(sb)->fatent_ops;
+
+	WARN_ON(blocknr < MSDOS_SB(sb)->fat_start);
+	fatent->bhs[0] = sb_bread(sb, blocknr);
+	if (!fatent->bhs[0]) {
+		printk(KERN_ERR "FAT: FAT read failed (blocknr %llu)\n",
+		       (unsigned long long)blocknr);
+		return -EIO;
+	}
+	fatent->nr_bhs = 1;
+	ops->ent_set_ptr(fatent, offset);
+	return 0;
+}
+
+static int fat12_ent_get(struct fat_entry *fatent)
+{
+	u8 **ent12_p = fatent->u.ent12_p;
+	int next;
+
+	if (fatent->entry & 1)
+		next = (*ent12_p[0] >> 4) | (*ent12_p[1] << 4);
+	else
+		next = (*ent12_p[1] << 8) | *ent12_p[0];
+	next &= 0x0fff;
+	if (next >= BAD_FAT12)
+		next = FAT_ENT_EOF;
+	return next;
+}
+
+static int fat16_ent_get(struct fat_entry *fatent)
+{
+	int next = le16_to_cpu(*fatent->u.ent16_p);
+	WARN_ON((unsigned long)fatent->u.ent16_p & (2 - 1));
+	if (next >= BAD_FAT16)
+		next = FAT_ENT_EOF;
+	return next;
+}
+
+static int fat32_ent_get(struct fat_entry *fatent)
+{
+	int next = le32_to_cpu(*fatent->u.ent32_p) & 0x0fffffff;
+	WARN_ON((unsigned long)fatent->u.ent32_p & (4 - 1));
+	if (next >= BAD_FAT32)
+		next = FAT_ENT_EOF;
+	return next;
+}
+
+static void fat12_ent_put(struct fat_entry *fatent, int new)
+{
+	u8 **ent12_p = fatent->u.ent12_p;
+
+	if (new == FAT_ENT_EOF)
+		new = EOF_FAT12;
+
+	if (fatent->entry & 1) {
+		*ent12_p[0] = (new << 4) | (*ent12_p[0] & 0x0f);
+		*ent12_p[1] = new >> 4;
+	} else {
+		*ent12_p[0] = new & 0xff;
+		*ent12_p[1] = (*ent12_p[1] & 0xf0) | (new >> 8);
+	}
+
+	mark_buffer_dirty(fatent->bhs[0]);
+	if (fatent->nr_bhs == 2)
+		mark_buffer_dirty(fatent->bhs[1]);
+}
+
+static void fat16_ent_put(struct fat_entry *fatent, int new)
+{
+	if (new == FAT_ENT_EOF)
+		new = EOF_FAT16;
+
+	*fatent->u.ent16_p = cpu_to_le16(new);
+	mark_buffer_dirty(fatent->bhs[0]);
+}
+
+static void fat32_ent_put(struct fat_entry *fatent, int new)
+{
+	if (new == FAT_ENT_EOF)
+		new = EOF_FAT32;
+
+	WARN_ON(new & 0xf0000000);
+	new |= le32_to_cpu(*fatent->u.ent32_p) & ~0x0fffffff;
+	*fatent->u.ent32_p = cpu_to_le32(new);
+	mark_buffer_dirty(fatent->bhs[0]);
+}
+
+static int fat12_ent_next(struct fat_entry *fatent)
+{
+	u8 **ent12_p = fatent->u.ent12_p;
+	struct buffer_head **bhs = fatent->bhs;
+	u8 *nextp = ent12_p[1] + 1 + (fatent->entry & 1);
+
+	fatent->entry++;
+	if (fatent->nr_bhs == 1) {
+		WARN_ON(ent12_p[0] > (u8 *)(bhs[0]->b_data + (bhs[0]->b_size - 2)));
+		WARN_ON(ent12_p[1] > (u8 *)(bhs[0]->b_data + (bhs[0]->b_size - 1)));
+		if (nextp < (u8 *)(bhs[0]->b_data + (bhs[0]->b_size - 1))) {
+			ent12_p[0] = nextp - 1;
+			ent12_p[1] = nextp;
+			return 1;
+		}
+	} else {
+		WARN_ON(ent12_p[0] != (u8 *)(bhs[0]->b_data + (bhs[0]->b_size - 1)));
+		WARN_ON(ent12_p[1] != (u8 *)bhs[1]->b_data);
+		ent12_p[0] = nextp - 1;
+		ent12_p[1] = nextp;
+		brelse(bhs[0]);
+		bhs[0] = bhs[1];
+		fatent->nr_bhs = 1;
+		return 1;
+	}
+	ent12_p[0] = NULL;
+	ent12_p[1] = NULL;
+	return 0;
+}
+
+static int fat16_ent_next(struct fat_entry *fatent)
+{
+	const struct buffer_head *bh = fatent->bhs[0];
+	fatent->entry++;
+	if (fatent->u.ent16_p < (__le16 *)(bh->b_data + (bh->b_size - 2))) {
+		fatent->u.ent16_p++;
+		return 1;
+	}
+	fatent->u.ent16_p = NULL;
+	return 0;
+}
+
+static int fat32_ent_next(struct fat_entry *fatent)
+{
+	const struct buffer_head *bh = fatent->bhs[0];
+	fatent->entry++;
+	if (fatent->u.ent32_p < (__le32 *)(bh->b_data + (bh->b_size - 4))) {
+		fatent->u.ent32_p++;
+		return 1;
+	}
+	fatent->u.ent32_p = NULL;
+	return 0;
+}
+
+static struct fatent_operations fat12_ops = {
+	.ent_blocknr	= fat12_ent_blocknr,
+	.ent_set_ptr	= fat12_ent_set_ptr,
+	.ent_bread	= fat12_ent_bread,
+	.ent_get	= fat12_ent_get,
+	.ent_put	= fat12_ent_put,
+	.ent_next	= fat12_ent_next,
+};
+
+static struct fatent_operations fat16_ops = {
+	.ent_blocknr	= fat_ent_blocknr,
+	.ent_set_ptr	= fat16_ent_set_ptr,
+	.ent_bread	= fat_ent_bread,
+	.ent_get	= fat16_ent_get,
+	.ent_put	= fat16_ent_put,
+	.ent_next	= fat16_ent_next,
+};
+
+static struct fatent_operations fat32_ops = {
+	.ent_blocknr	= fat_ent_blocknr,
+	.ent_set_ptr	= fat32_ent_set_ptr,
+	.ent_bread	= fat_ent_bread,
+	.ent_get	= fat32_ent_get,
+	.ent_put	= fat32_ent_put,
+	.ent_next	= fat32_ent_next,
+};
+
+static inline void lock_fat(struct msdos_sb_info *sbi)
+{
+	down(&sbi->fat_lock);
+}
+
+static inline void unlock_fat(struct msdos_sb_info *sbi)
+{
+	up(&sbi->fat_lock);
+}
+
+void fat_ent_access_init(struct super_block *sb)
+{
+	struct msdos_sb_info *sbi = MSDOS_SB(sb);
+
+	init_MUTEX(&sbi->fat_lock);
+
+	switch (sbi->fat_bits) {
+	case 32:
+		sbi->fatent_shift = 2;
+		sbi->fatent_ops = &fat32_ops;
+		break;
+	case 16:
+		sbi->fatent_shift = 1;
+		sbi->fatent_ops = &fat16_ops;
+		break;
+	case 12:
+		sbi->fatent_shift = -1;
+		sbi->fatent_ops = &fat12_ops;
+		break;
+	}
+}
+
+static inline int fat_ent_update_ptr(struct super_block *sb,
+				     struct fat_entry *fatent,
+				     int offset, sector_t blocknr)
+{
+	struct msdos_sb_info *sbi = MSDOS_SB(sb);
+	struct fatent_operations *ops = sbi->fatent_ops;
+	struct buffer_head **bhs = fatent->bhs;
+
+	/* Is this fatent's blocks including this entry? */
+	if (!fatent->nr_bhs || bhs[0]->b_blocknr != blocknr)
+		return 0;
+	/* Does this entry need the next block? */
+	if (sbi->fat_bits == 12 && (offset + 1) >= sb->s_blocksize) {
+		if (fatent->nr_bhs != 2 || bhs[1]->b_blocknr != (blocknr + 1))
+			return 0;
+	}
+	ops->ent_set_ptr(fatent, offset);
+	return 1;
+}
+
+int fat_ent_read(struct inode *inode, struct fat_entry *fatent, int entry)
+{
+	struct super_block *sb = inode->i_sb;
+	struct msdos_sb_info *sbi = MSDOS_SB(inode->i_sb);
+	struct fatent_operations *ops = sbi->fatent_ops;
+	int err, offset;
+	sector_t blocknr;
+
+	if (entry < FAT_START_ENT || sbi->max_cluster <= entry) {
+		fatent_brelse(fatent);
+		fat_fs_panic(sb, "invalid access to FAT (entry 0x%08x)", entry);
+		return -EIO;
+	}
+
+	fatent_set_entry(fatent, entry);
+	ops->ent_blocknr(sb, entry, &offset, &blocknr);
+
+	if (!fat_ent_update_ptr(sb, fatent, offset, blocknr)) {
+		fatent_brelse(fatent);
+		err = ops->ent_bread(sb, fatent, offset, blocknr);
+		if (err)
+			return err;
+	}
+	return ops->ent_get(fatent);
+}
+
+/* FIXME: We can write the blocks as more big chunk. */
+static int fat_mirror_bhs(struct super_block *sb, struct buffer_head **bhs,
+			  int nr_bhs)
+{
+	struct msdos_sb_info *sbi = MSDOS_SB(sb);
+	struct buffer_head *c_bh;
+	int err, n, copy;
+
+	err = 0;
+	for (copy = 1; copy < sbi->fats; copy++) {
+		sector_t backup_fat = sbi->fat_length * copy;
+
+		for (n = 0; n < nr_bhs; n++) {
+			c_bh = sb_getblk(sb, backup_fat + bhs[n]->b_blocknr);
+			if (!c_bh) {
+				err = -ENOMEM;
+				goto error;
+			}
+			memcpy(c_bh->b_data, bhs[n]->b_data, sb->s_blocksize);
+			set_buffer_uptodate(c_bh);
+			mark_buffer_dirty(c_bh);
+			if (sb->s_flags & MS_SYNCHRONOUS)
+				err = sync_dirty_buffer(c_bh);
+			brelse(c_bh);
+			if (err)
+				goto error;
+		}
+	}
+error:
+	return err;
+}
+
+int fat_ent_write(struct inode *inode, struct fat_entry *fatent,
+		  int new, int wait)
+{
+	struct super_block *sb = inode->i_sb;
+	struct fatent_operations *ops = MSDOS_SB(sb)->fatent_ops;
+	int err;
+
+	ops->ent_put(fatent, new);
+	if (wait) {
+		err = fat_sync_bhs(fatent->bhs, fatent->nr_bhs);
+		if (err)
+			return err;
+	}
+	return fat_mirror_bhs(sb, fatent->bhs, fatent->nr_bhs);
+}
+
+static inline int fat_ent_next(struct msdos_sb_info *sbi,
+			       struct fat_entry *fatent)
+{
+	if (sbi->fatent_ops->ent_next(fatent)) {
+		if (fatent->entry < sbi->max_cluster)
+			return 1;
+	}
+	return 0;
+}
+
+static inline int fat_ent_read_block(struct super_block *sb,
+				     struct fat_entry *fatent)
+{
+	struct fatent_operations *ops = MSDOS_SB(sb)->fatent_ops;
+	sector_t blocknr;
+	int offset;
+
+	fatent_brelse(fatent);
+	ops->ent_blocknr(sb, fatent->entry, &offset, &blocknr);
+	return ops->ent_bread(sb, fatent, offset, blocknr);
+}
+
+static void fat_collect_bhs(struct buffer_head **bhs, int *nr_bhs,
+			    struct fat_entry *fatent)
+{
+	int n, i;
+
+	for (n = 0; n < fatent->nr_bhs; n++) {
+		for (i = 0; i < *nr_bhs; i++) {
+			if (fatent->bhs[n] == bhs[i])
+				break;
+		}
+		if (i == *nr_bhs) {
+			get_bh(fatent->bhs[n]);
+			bhs[i] = fatent->bhs[n];
+			(*nr_bhs)++;
+		}
+	}
+}
+
+int fat_alloc_clusters(struct inode *inode, int *cluster, int nr_cluster)
+{
+	struct super_block *sb = inode->i_sb;
+	struct msdos_sb_info *sbi = MSDOS_SB(sb);
+	struct fatent_operations *ops = sbi->fatent_ops;
+	struct fat_entry fatent, prev_ent;
+	struct buffer_head *bhs[MAX_BUF_PER_PAGE];
+	int i, count, err, nr_bhs, idx_clus;
+
+	BUG_ON(nr_cluster > (MAX_BUF_PER_PAGE / 2));	/* fixed limit */
+
+	lock_fat(sbi);
+	if (sbi->free_clusters != -1 && sbi->free_clusters < nr_cluster) {
+		unlock_fat(sbi);
+		return -ENOSPC;
+	}
+
+	err = nr_bhs = idx_clus = 0;
+	count = FAT_START_ENT;
+	fatent_init(&prev_ent);
+	fatent_init(&fatent);
+	fatent_set_entry(&fatent, sbi->prev_free + 1);
+	while (count < sbi->max_cluster) {
+		if (fatent.entry >= sbi->max_cluster)
+			fatent.entry = FAT_START_ENT;
+		fatent_set_entry(&fatent, fatent.entry);
+		err = fat_ent_read_block(sb, &fatent);
+		if (err)
+			goto out;
+
+		/* Find the free entries in a block */
+		do {
+			if (ops->ent_get(&fatent) == FAT_ENT_FREE) {
+				int entry = fatent.entry;
+
+				/* make the cluster chain */
+				ops->ent_put(&fatent, FAT_ENT_EOF);
+				if (prev_ent.nr_bhs)
+					ops->ent_put(&prev_ent, entry);
+
+				fat_collect_bhs(bhs, &nr_bhs, &fatent);
+
+				sbi->prev_free = entry;
+				if (sbi->free_clusters != -1)
+					sbi->free_clusters--;
+
+				cluster[idx_clus] = entry;
+				idx_clus++;
+				if (idx_clus == nr_cluster)
+					goto out;
+
+				/*
+				 * fat_collect_bhs() gets ref-count of bhs,
+				 * so we can still use the prev_ent.
+				 */
+				prev_ent = fatent;
+			}
+			count++;
+			if (count == sbi->max_cluster)
+				break;
+		} while (fat_ent_next(sbi, &fatent));
+	}
+
+	/* Couldn't allocate the free entries */
+	sbi->free_clusters = 0;
+	err = -ENOSPC;
+
+out:
+	unlock_fat(sbi);
+	fatent_brelse(&fatent);
+	if (!err) {
+		if (inode_needs_sync(inode))
+			err = fat_sync_bhs(bhs, nr_bhs);
+		if (!err)
+			err = fat_mirror_bhs(sb, bhs, nr_bhs);
+	}
+	for (i = 0; i < nr_bhs; i++)
+		brelse(bhs[i]);
+	fat_clusters_flush(sb);
+
+	if (err && idx_clus)
+		fat_free_clusters(inode, cluster[0]);
+
+	return err;
+}
+
+int fat_free_clusters(struct inode *inode, int cluster)
+{
+	struct super_block *sb = inode->i_sb;
+	struct msdos_sb_info *sbi = MSDOS_SB(sb);
+	struct fatent_operations *ops = sbi->fatent_ops;
+	struct fat_entry fatent;
+	struct buffer_head *bhs[MAX_BUF_PER_PAGE];
+	int i, err, nr_bhs;
+
+	nr_bhs = 0;
+	fatent_init(&fatent);
+	lock_fat(sbi);
+	do {
+		cluster = fat_ent_read(inode, &fatent, cluster);
+		if (cluster < 0) {
+			err = cluster;
+			goto error;
+		} else if (cluster == FAT_ENT_FREE) {
+			fat_fs_panic(sb, "%s: deleting FAT entry beyond EOF",
+				     __FUNCTION__);
+			err = -EIO;
+			goto error;
+		}
+
+		ops->ent_put(&fatent, FAT_ENT_FREE);
+		if (sbi->free_clusters != -1)
+			sbi->free_clusters++;
+
+		if (nr_bhs + fatent.nr_bhs > MAX_BUF_PER_PAGE) {
+			if (sb->s_flags & MS_SYNCHRONOUS) {
+				err = fat_sync_bhs(bhs, nr_bhs);
+				if (err)
+					goto error;
+			}
+			err = fat_mirror_bhs(sb, bhs, nr_bhs);
+			if (err)
+				goto error;
+			for (i = 0; i < nr_bhs; i++)
+				brelse(bhs[i]);
+			nr_bhs = 0;
+		}
+		fat_collect_bhs(bhs, &nr_bhs, &fatent);
+	} while (cluster != FAT_ENT_EOF);
+
+	if (sb->s_flags & MS_SYNCHRONOUS) {
+		err = fat_sync_bhs(bhs, nr_bhs);
+		if (err)
+			goto error;
+	}
+	err = fat_mirror_bhs(sb, bhs, nr_bhs);
+error:
+	fatent_brelse(&fatent);
+	for (i = 0; i < nr_bhs; i++)
+		brelse(bhs[i]);
+	unlock_fat(sbi);
+
+	fat_clusters_flush(sb);
+
+	return err;
+}
+
+EXPORT_SYMBOL(fat_free_clusters);
+
+int fat_count_free_clusters(struct super_block *sb)
+{
+	struct msdos_sb_info *sbi = MSDOS_SB(sb);
+	struct fatent_operations *ops = sbi->fatent_ops;
+	struct fat_entry fatent;
+	int err = 0, free;
+
+	lock_fat(sbi);
+	if (sbi->free_clusters != -1)
+		goto out;
+
+	free = 0;
+	fatent_init(&fatent);
+	fatent_set_entry(&fatent, FAT_START_ENT);
+	while (fatent.entry < sbi->max_cluster) {
+		err = fat_ent_read_block(sb, &fatent);
+		if (err)
+			goto out;
+
+		do {
+			if (ops->ent_get(&fatent) == FAT_ENT_FREE)
+				free++;
+		} while (fat_ent_next(sbi, &fatent));
+	}
+	sbi->free_clusters = free;
+	fatent_brelse(&fatent);
+out:
+	unlock_fat(sbi);
+	return err;
+}
diff -Nru a/fs/fat/file.c b/fs/fat/file.c
--- a/fs/fat/file.c	2005-03-11 12:51:42 -08:00
+++ b/fs/fat/file.c	2005-03-11 12:51:42 -08:00
@@ -12,13 +12,31 @@
 #include <linux/smp_lock.h>
 #include <linux/buffer_head.h>
 
-static ssize_t fat_file_write(struct file *filp, const char __user *buf,
-			      size_t count, loff_t *ppos)
+static ssize_t fat_file_aio_write(struct kiocb *iocb, const char __user *buf,
+				  size_t count, loff_t pos)
+{
+	struct inode *inode = iocb->ki_filp->f_dentry->d_inode;
+	int retval;
+
+	retval = generic_file_aio_write(iocb, buf, count, pos);
+	if (retval > 0) {
+		inode->i_mtime = inode->i_ctime = CURRENT_TIME_SEC;
+		MSDOS_I(inode)->i_attrs |= ATTR_ARCH;
+		mark_inode_dirty(inode);
+//		check the locking rules
+//		if (IS_SYNC(inode))
+//			fat_sync_inode(inode);
+	}
+	return retval;
+}
+
+static ssize_t fat_file_writev(struct file *filp, const struct iovec *iov,
+			       unsigned long nr_segs, loff_t *ppos)
 {
 	struct inode *inode = filp->f_dentry->d_inode;
 	int retval;
 
-	retval = generic_file_write(filp, buf, count, ppos);
+	retval = generic_file_writev(filp, iov, nr_segs, ppos);
 	if (retval > 0) {
 		inode->i_mtime = inode->i_ctime = CURRENT_TIME_SEC;
 		MSDOS_I(inode)->i_attrs |= ATTR_ARCH;
@@ -27,14 +45,115 @@
 	return retval;
 }
 
+int fat_generic_ioctl(struct inode *inode, struct file *filp,
+		      unsigned int cmd, unsigned long arg)
+{
+	struct msdos_sb_info *sbi = MSDOS_SB(inode->i_sb);
+	u32 __user *user_attr = (u32 __user *)arg;
+
+	switch (cmd) {
+	case FAT_IOCTL_GET_ATTRIBUTES:
+	{
+		u32 attr;
+
+		if (inode->i_ino == MSDOS_ROOT_INO)
+			attr = ATTR_DIR;
+		else
+			attr = fat_attr(inode);
+
+		return put_user(attr, user_attr);
+	}
+	case FAT_IOCTL_SET_ATTRIBUTES:
+	{
+		u32 attr, oldattr;
+		int err, is_dir = S_ISDIR(inode->i_mode);
+		struct iattr ia;
+
+		err = get_user(attr, user_attr);
+		if (err)
+			return err;
+
+		down(&inode->i_sem);
+
+		if (IS_RDONLY(inode)) {
+			err = -EROFS;
+			goto up;
+		}
+
+		/*
+		 * ATTR_VOLUME and ATTR_DIR cannot be changed; this also
+		 * prevents the user from turning us into a VFAT
+		 * longname entry.  Also, we obviously can't set
+		 * any of the NTFS attributes in the high 24 bits.
+		 */
+		attr &= 0xff & ~(ATTR_VOLUME | ATTR_DIR);
+		/* Merge in ATTR_VOLUME and ATTR_DIR */
+		attr |= (MSDOS_I(inode)->i_attrs & ATTR_VOLUME) |
+			(is_dir ? ATTR_DIR : 0);
+		oldattr = fat_attr(inode);
+
+		/* Equivalent to a chmod() */
+		ia.ia_valid = ATTR_MODE | ATTR_CTIME;
+		if (is_dir) {
+			ia.ia_mode = MSDOS_MKMODE(attr,
+				S_IRWXUGO & ~sbi->options.fs_dmask)
+				| S_IFDIR;
+		} else {
+			ia.ia_mode = MSDOS_MKMODE(attr,
+				(S_IRUGO | S_IWUGO | (inode->i_mode & S_IXUGO))
+				& ~sbi->options.fs_fmask)
+				| S_IFREG;
+		}
+
+		/* The root directory has no attributes */
+		if (inode->i_ino == MSDOS_ROOT_INO && attr != ATTR_DIR) {
+			err = -EINVAL;
+			goto up;
+		}
+
+		if (sbi->options.sys_immutable) {
+			if ((attr | oldattr) & ATTR_SYS) {
+				if (!capable(CAP_LINUX_IMMUTABLE)) {
+					err = -EPERM;
+					goto up;
+				}
+			}
+		}
+
+		/* This MUST be done before doing anything irreversible... */
+		err = notify_change(filp->f_dentry, &ia);
+		if (err)
+			goto up;
+
+		if (sbi->options.sys_immutable) {
+			if (attr & ATTR_SYS)
+				inode->i_flags |= S_IMMUTABLE;
+			else
+				inode->i_flags &= S_IMMUTABLE;
+		}
+
+		MSDOS_I(inode)->i_attrs = attr & ATTR_UNUSED;
+		mark_inode_dirty(inode);
+	up:
+		up(&inode->i_sem);
+		return err;
+	}
+	default:
+		return -ENOTTY;	/* Inappropriate ioctl for device */
+	}
+}
+
 struct file_operations fat_file_operations = {
 	.llseek		= generic_file_llseek,
-	.read		= generic_file_read,
-	.write		= fat_file_write,
+	.read		= do_sync_read,
+	.write		= do_sync_write,
+	.readv		= generic_file_readv,
+	.writev		= fat_file_writev,
+	.aio_read	= generic_file_aio_read,
+	.aio_write	= fat_file_aio_write,
 	.mmap		= generic_file_mmap,
+	.ioctl		= fat_generic_ioctl,
 	.fsync		= file_fsync,
-	.readv		= generic_file_readv,
-	.writev		= generic_file_writev,
 	.sendfile	= generic_file_sendfile,
 };
 
@@ -93,62 +212,74 @@
 static int fat_free(struct inode *inode, int skip)
 {
 	struct super_block *sb = inode->i_sb;
-	int nr, ret, fclus, dclus;
+	int err, wait, free_start, i_start, i_logstart;
 
 	if (MSDOS_I(inode)->i_start == 0)
 		return 0;
 
+	/*
+	 * Write a new EOF, and get the remaining cluster chain for freeing.
+	 */
+	wait = IS_DIRSYNC(inode);
 	if (skip) {
+		struct fat_entry fatent;
+		int ret, fclus, dclus;
+
 		ret = fat_get_cluster(inode, skip - 1, &fclus, &dclus);
 		if (ret < 0)
 			return ret;
 		else if (ret == FAT_ENT_EOF)
 			return 0;
 
-		nr = fat_access(sb, dclus, -1);
-		if (nr == FAT_ENT_EOF)
+		fatent_init(&fatent);
+		ret = fat_ent_read(inode, &fatent, dclus);
+		if (ret == FAT_ENT_EOF) {
+			fatent_brelse(&fatent);
 			return 0;
-		else if (nr > 0) {
-			/*
-			 * write a new EOF, and get the remaining cluster
-			 * chain for freeing.
-			 */
-			nr = fat_access(sb, dclus, FAT_ENT_EOF);
+		} else if (ret == FAT_ENT_FREE) {
+			fat_fs_panic(sb,
+				     "%s: invalid cluster chain (i_pos %lld)",
+				     __FUNCTION__, MSDOS_I(inode)->i_pos);
+			ret = -EIO;
+		} else if (ret > 0) {
+			err = fat_ent_write(inode, &fatent, FAT_ENT_EOF, wait);
+			if (err)
+				ret = err;
 		}
-		if (nr < 0)
-			return nr;
+		fatent_brelse(&fatent);
+		if (ret < 0)
+			return ret;
 
+		free_start = ret;
+		i_start = i_logstart = 0;
 		fat_cache_inval_inode(inode);
 	} else {
 		fat_cache_inval_inode(inode);
 
-		nr = MSDOS_I(inode)->i_start;
+		i_start = free_start = MSDOS_I(inode)->i_start;
+		i_logstart = MSDOS_I(inode)->i_logstart;
 		MSDOS_I(inode)->i_start = 0;
 		MSDOS_I(inode)->i_logstart = 0;
-		mark_inode_dirty(inode);
 	}
-
-	lock_fat(sb);
-	do {
-		nr = fat_access(sb, nr, FAT_ENT_FREE);
-		if (nr < 0)
-			goto error;
-		else if (nr == FAT_ENT_FREE) {
-			fat_fs_panic(sb, "%s: deleting beyond EOF (i_pos %lld)",
-				     __FUNCTION__, MSDOS_I(inode)->i_pos);
-			nr = -EIO;
+	MSDOS_I(inode)->i_attrs |= ATTR_ARCH;
+	inode->i_ctime = inode->i_mtime = CURRENT_TIME_SEC;
+	if (wait) {
+		err = fat_sync_inode(inode);
+		if (err)
 			goto error;
-		}
-		if (MSDOS_SB(sb)->free_clusters != -1)
-			MSDOS_SB(sb)->free_clusters++;
-		inode->i_blocks -= MSDOS_SB(sb)->cluster_size >> 9;
-	} while (nr != FAT_ENT_EOF);
-	fat_clusters_flush(sb);
-	nr = 0;
-error:
-	unlock_fat(sb);
+	} else
+		mark_inode_dirty(inode);
+	inode->i_blocks = skip << (MSDOS_SB(sb)->cluster_bits - 9);
+
+	/* Freeing the remained cluster chain */
+	return fat_free_clusters(inode, free_start);
 
-	return nr;
+error:
+	if (i_start) {
+		MSDOS_I(inode)->i_start = i_start;
+		MSDOS_I(inode)->i_logstart = i_logstart;
+	}
+	return err;
 }
 
 void fat_truncate(struct inode *inode)
@@ -168,10 +299,7 @@
 
 	lock_kernel();
 	fat_free(inode, nr_clusters);
-	MSDOS_I(inode)->i_attrs |= ATTR_ARCH;
 	unlock_kernel();
-	inode->i_ctime = inode->i_mtime = CURRENT_TIME_SEC;
-	mark_inode_dirty(inode);
 }
 
 struct inode_operations fat_file_inode_operations = {
diff -Nru a/fs/fat/inode.c b/fs/fat/inode.c
--- a/fs/fat/inode.c	2005-03-11 12:51:43 -08:00
+++ b/fs/fat/inode.c	2005-03-11 12:51:43 -08:00
@@ -33,6 +33,21 @@
 static char fat_default_iocharset[] = CONFIG_FAT_DEFAULT_IOCHARSET;
 
 
+static int fat_add_cluster(struct inode *inode)
+{
+	int err, cluster;
+
+	err = fat_alloc_clusters(inode, &cluster, 1);
+	if (err)
+		return err;
+	/* FIXME: this cluster should be added after data of this
+	 * cluster is writed */
+	err = fat_chain_add(inode, cluster, 1);
+	if (err)
+		fat_free_clusters(inode, cluster);
+	return err;
+}
+
 static int fat_get_block(struct inode *inode, sector_t iblock,
 			 struct buffer_head *bh_result, int create)
 {
@@ -55,11 +70,9 @@
 		return -EIO;
 	}
 	if (!((unsigned long)iblock & (MSDOS_SB(sb)->sec_per_clus - 1))) {
-		int error;
-
-		error = fat_add_cluster(inode);
-		if (error < 0)
-			return error;
+		err = fat_add_cluster(inode);
+		if (err)
+			return err;
 	}
 	MSDOS_I(inode)->mmu_private += sb->s_blocksize;
 	err = fat_bmap(inode, iblock, &phys);
@@ -220,8 +233,7 @@
 /* doesn't deal with root inode */
 static int fat_fill_inode(struct inode *inode, struct msdos_dir_entry *de)
 {
-	struct super_block *sb = inode->i_sb;
-	struct msdos_sb_info *sbi = MSDOS_SB(sb);
+	struct msdos_sb_info *sbi = MSDOS_SB(inode->i_sb);
 	int error;
 
 	MSDOS_I(inode)->i_pos = 0;
@@ -266,9 +278,10 @@
 		inode->i_mapping->a_ops = &fat_aops;
 		MSDOS_I(inode)->mmu_private = inode->i_size;
 	}
-	if(de->attr & ATTR_SYS)
+	if (de->attr & ATTR_SYS) {
 		if (sbi->options.sys_immutable)
 			inode->i_flags |= S_IMMUTABLE;
+	}
 	MSDOS_I(inode)->i_attrs = de->attr & ATTR_UNUSED;
 	/* this is as close to the truth as we can get ... */
 	inode->i_blksize = sbi->cluster_size;
@@ -277,34 +290,39 @@
 	inode->i_mtime.tv_sec = inode->i_atime.tv_sec =
 		date_dos2unix(le16_to_cpu(de->time), le16_to_cpu(de->date));
 	inode->i_mtime.tv_nsec = inode->i_atime.tv_nsec = 0;
-	inode->i_ctime.tv_sec =
-		MSDOS_SB(sb)->options.isvfat
-		? date_dos2unix(le16_to_cpu(de->ctime), le16_to_cpu(de->cdate))
-		: inode->i_mtime.tv_sec;
-	inode->i_ctime.tv_nsec = de->ctime_ms * 1000000;
-	MSDOS_I(inode)->i_ctime_ms = de->ctime_ms;
+	if (sbi->options.isvfat) {
+		int secs = de->ctime_cs / 100;
+		int csecs = de->ctime_cs % 100;
+		inode->i_ctime.tv_sec  =
+			date_dos2unix(le16_to_cpu(de->ctime),
+				      le16_to_cpu(de->cdate)) + secs;
+		inode->i_ctime.tv_nsec = csecs * 10000000;
+	} else
+		inode->i_ctime = inode->i_mtime;
 
 	return 0;
 }
 
 struct inode *fat_build_inode(struct super_block *sb,
-			struct msdos_dir_entry *de, loff_t i_pos, int *res)
+			struct msdos_dir_entry *de, loff_t i_pos)
 {
 	struct inode *inode;
-	*res = 0;
+	int err;
+
 	inode = fat_iget(sb, i_pos);
 	if (inode)
 		goto out;
 	inode = new_inode(sb);
-	*res = -ENOMEM;
-	if (!inode)
+	if (!inode) {
+		inode = ERR_PTR(-ENOMEM);
 		goto out;
+	}
 	inode->i_ino = iunique(sb, MSDOS_ROOT_INO);
 	inode->i_version = 1;
-	*res = fat_fill_inode(inode, de);
-	if (*res < 0) {
+	err = fat_fill_inode(inode, de);
+	if (err) {
 		iput(inode);
-		inode = NULL;
+		inode = ERR_PTR(err);
 		goto out;
 	}
 	fat_attach(inode, i_pos);
@@ -420,34 +438,19 @@
 static int fat_statfs(struct super_block *sb, struct kstatfs *buf)
 {
 	struct msdos_sb_info *sbi = MSDOS_SB(sb);
-	int free, nr, ret;
 
-	if (sbi->free_clusters != -1)
-		free = sbi->free_clusters;
-	else {
-		lock_fat(sb);
-		if (sbi->free_clusters != -1)
-			free = sbi->free_clusters;
-		else {
-			free = 0;
-			for (nr = FAT_START_ENT; nr < sbi->max_cluster; nr++) {
-				ret = fat_access(sb, nr, -1);
-				if (ret < 0) {
-					unlock_fat(sb);
-					return ret;
-				} else if (ret == FAT_ENT_FREE)
-					free++;
-			}
-			sbi->free_clusters = free;
-		}
-		unlock_fat(sb);
+	/* If the count of free cluster is still unknown, counts it here. */
+	if (sbi->free_clusters == -1) {
+		int err = fat_count_free_clusters(sb);
+		if (err)
+			return err;
 	}
 
 	buf->f_type = sb->s_magic;
 	buf->f_bsize = sbi->cluster_size;
 	buf->f_blocks = sbi->max_cluster - FAT_START_ENT;
-	buf->f_bfree = free;
-	buf->f_bavail = free;
+	buf->f_bfree = sbi->free_clusters;
+	buf->f_bavail = sbi->free_clusters;
 	buf->f_namelen = sbi->options.isvfat ? 260 : 12;
 
 	return 0;
@@ -460,18 +463,20 @@
 	struct buffer_head *bh;
 	struct msdos_dir_entry *raw_entry;
 	loff_t i_pos;
+	int err = 0;
 
 retry:
 	i_pos = MSDOS_I(inode)->i_pos;
-	if (inode->i_ino == MSDOS_ROOT_INO || !i_pos) {
+	if (inode->i_ino == MSDOS_ROOT_INO || !i_pos)
 		return 0;
-	}
+
 	lock_kernel();
-	if (!(bh = sb_bread(sb, i_pos >> sbi->dir_per_block_bits))) {
+	bh = sb_bread(sb, i_pos >> sbi->dir_per_block_bits);
+	if (!bh) {
 		printk(KERN_ERR "FAT: unable to read inode block "
 		       "for updating (i_pos %lld)\n", i_pos);
-		unlock_kernel();
-		return -EIO;
+		err = -EIO;
+		goto out;
 	}
 	spin_lock(&sbi->inode_hash_lock);
 	if (i_pos != MSDOS_I(inode)->i_pos) {
@@ -483,30 +488,36 @@
 
 	raw_entry = &((struct msdos_dir_entry *) (bh->b_data))
 	    [i_pos & (sbi->dir_per_block - 1)];
-	if (S_ISDIR(inode->i_mode)) {
-		raw_entry->attr = ATTR_DIR;
+	if (S_ISDIR(inode->i_mode))
 		raw_entry->size = 0;
-	}
-	else {
-		raw_entry->attr = ATTR_NONE;
+	else
 		raw_entry->size = cpu_to_le32(inode->i_size);
-	}
-	raw_entry->attr |= MSDOS_MKATTR(inode->i_mode) |
-	    MSDOS_I(inode)->i_attrs;
+	raw_entry->attr = fat_attr(inode);
 	raw_entry->start = cpu_to_le16(MSDOS_I(inode)->i_logstart);
 	raw_entry->starthi = cpu_to_le16(MSDOS_I(inode)->i_logstart >> 16);
 	fat_date_unix2dos(inode->i_mtime.tv_sec, &raw_entry->time, &raw_entry->date);
 	if (sbi->options.isvfat) {
 		fat_date_unix2dos(inode->i_ctime.tv_sec,&raw_entry->ctime,&raw_entry->cdate);
-		raw_entry->ctime_ms = MSDOS_I(inode)->i_ctime_ms; /* use i_ctime.tv_nsec? */
+		raw_entry->ctime_cs = (inode->i_ctime.tv_sec & 1) * 100 +
+			inode->i_ctime.tv_nsec / 10000000;
 	}
 	spin_unlock(&sbi->inode_hash_lock);
 	mark_buffer_dirty(bh);
+	if (wait)
+		err = sync_dirty_buffer(bh);
 	brelse(bh);
+out:
 	unlock_kernel();
-	return 0;
+	return err;
 }
 
+int fat_sync_inode(struct inode *inode)
+{
+	return fat_write_inode(inode, 1);
+}
+
+EXPORT_SYMBOL(fat_sync_inode);
+
 static int fat_show_options(struct seq_file *m, struct vfsmount *mnt);
 static struct super_operations fat_sops = {
 	.alloc_inode	= fat_alloc_inode,
@@ -636,39 +647,35 @@
 
 static struct dentry *fat_get_parent(struct dentry *child)
 {
-	struct buffer_head *bh=NULL;
-	struct msdos_dir_entry *de = NULL;
-	struct dentry *parent = NULL;
-	int res;
-	loff_t i_pos = 0;
+	struct buffer_head *bh;
+	struct msdos_dir_entry *de;
+	loff_t i_pos;
+	struct dentry *parent;
 	struct inode *inode;
+	int err;
 
 	lock_kernel();
-	res = fat_scan(child->d_inode, MSDOS_DOTDOT, &bh, &de, &i_pos);
 
-	if (res < 0)
+	err = fat_get_dotdot_entry(child->d_inode, &bh, &de, &i_pos);
+	if (err) {
+		parent = ERR_PTR(err);
 		goto out;
-	inode = fat_build_inode(child->d_sb, de, i_pos, &res);
-	if (res)
+	}
+	inode = fat_build_inode(child->d_sb, de, i_pos);
+	brelse(bh);
+	if (IS_ERR(inode)) {
+		parent = ERR_PTR(PTR_ERR(inode));
 		goto out;
-	if (!inode)
-		res = -EACCES;
-	else {
-		parent = d_alloc_anon(inode);
-		if (!parent) {
-			iput(inode);
-			res = -ENOMEM;
-		}
 	}
-
- out:
-	if(bh)
-		brelse(bh);
+	parent = d_alloc_anon(inode);
+	if (!parent) {
+		iput(inode);
+		parent = ERR_PTR(-ENOMEM);
+	}
+out:
 	unlock_kernel();
-	if (res)
-		return ERR_PTR(res);
-	else
-		return parent;
+
+	return parent;
 }
 
 static struct export_operations fat_export_ops = {
@@ -1026,10 +1033,9 @@
 	MSDOS_I(inode)->i_logstart = 0;
 	MSDOS_I(inode)->mmu_private = inode->i_size;
 
-	MSDOS_I(inode)->i_attrs = 0;
+	MSDOS_I(inode)->i_attrs = ATTR_NONE;
 	inode->i_mtime.tv_sec = inode->i_atime.tv_sec = inode->i_ctime.tv_sec = 0;
 	inode->i_mtime.tv_nsec = inode->i_atime.tv_nsec = inode->i_ctime.tv_nsec = 0;
-	MSDOS_I(inode)->i_ctime_ms = 0;
 	inode->i_nlink = fat_subdirs(inode)+2;
 
 	return 0;
@@ -1068,10 +1074,6 @@
 	if (error)
 		goto out_fail;
 
-	/* set up enough so that it can read an inode */
-	fat_hash_init(sb);
-	init_MUTEX(&sbi->fat_lock);
-
 	error = -EIO;
 	sb_min_blocksize(sb, 512);
 	bh = sb_bread(sb, 0);
@@ -1161,7 +1163,7 @@
 	sbi->fat_length = le16_to_cpu(b->fat_length);
 	sbi->root_cluster = 0;
 	sbi->free_clusters = -1;	/* Don't know yet */
-	sbi->prev_free = -1;
+	sbi->prev_free = FAT_START_ENT;
 
 	if (!sbi->fat_length && b->fat32_length) {
 		struct fat_boot_fsinfo *fsinfo;
@@ -1245,8 +1247,16 @@
 	/* check the free_clusters, it's not necessarily correct */
 	if (sbi->free_clusters != -1 && sbi->free_clusters > total_clusters)
 		sbi->free_clusters = -1;
+	/* check the prev_free, it's not necessarily correct */
+	sbi->prev_free %= sbi->max_cluster;
+	if (sbi->prev_free < FAT_START_ENT)
+		sbi->prev_free = FAT_START_ENT;
 
 	brelse(bh);
+
+	/* set up enough so that it can read an inode */
+	fat_hash_init(sb);
+	fat_ent_access_init(sb);
 
 	/*
 	 * The low byte of FAT's first entry must have same value with
diff -Nru a/fs/fat/misc.c b/fs/fat/misc.c
--- a/fs/fat/misc.c	2005-03-11 12:51:51 -08:00
+++ b/fs/fat/misc.c	2005-03-11 12:51:51 -08:00
@@ -33,15 +33,7 @@
 	}
 }
 
-void lock_fat(struct super_block *sb)
-{
-	down(&(MSDOS_SB(sb)->fat_lock));
-}
-
-void unlock_fat(struct super_block *sb)
-{
-	up(&(MSDOS_SB(sb)->fat_lock));
-}
+EXPORT_SYMBOL(fat_fs_panic);
 
 /* Flushes the number of free clusters on FAT32 */
 /* XXX: Need to write one per FSINFO block.  Currently only writes 1 */
@@ -56,7 +48,7 @@
 
 	bh = sb_bread(sb, sbi->fsinfo_sector);
 	if (bh == NULL) {
-		printk(KERN_ERR "FAT bread failed in fat_clusters_flush\n");
+		printk(KERN_ERR "FAT: bread failed in fat_clusters_flush\n");
 		return;
 	}
 
@@ -75,31 +67,29 @@
 		if (sbi->prev_free != -1)
 			fsinfo->next_cluster = cpu_to_le32(sbi->prev_free);
 		mark_buffer_dirty(bh);
+		if (sb->s_flags & MS_SYNCHRONOUS)
+			sync_dirty_buffer(bh);
 	}
 	brelse(bh);
 }
 
 /*
- * fat_add_cluster tries to allocate a new cluster and adds it to the
- * file represented by inode.
+ * fat_chain_add() adds a new cluster to the chain of clusters represented
+ * by inode.
  */
-int fat_add_cluster(struct inode *inode)
+int fat_chain_add(struct inode *inode, int new_dclus, int nr_cluster)
 {
 	struct super_block *sb = inode->i_sb;
 	struct msdos_sb_info *sbi = MSDOS_SB(sb);
-	int ret, count, limit, new_dclus, new_fclus, last;
-	int cluster_bits = sbi->cluster_bits;
+	int ret, new_fclus, last;
 
 	/*
 	 * We must locate the last cluster of the file to add this new
 	 * one (new_dclus) to the end of the link list (the FAT).
-	 *
-	 * In order to confirm that the cluster chain is valid, we
-	 * find out EOF first.
 	 */
 	last = new_fclus = 0;
 	if (MSDOS_I(inode)->i_start) {
-		int ret, fclus, dclus;
+		int fclus, dclus;
 
 		ret = fat_get_cluster(inode, FAT_ENT_EOF, &fclus, &dclus);
 		if (ret < 0)
@@ -108,66 +98,42 @@
 		last = dclus;
 	}
 
-	/* find free FAT entry */
-	lock_fat(sb);
-
-	if (sbi->free_clusters == 0) {
-		unlock_fat(sb);
-		return -ENOSPC;
-	}
-
-	limit = sbi->max_cluster;
-	new_dclus = sbi->prev_free + 1;
-	for (count = FAT_START_ENT; count < limit; count++, new_dclus++) {
-		new_dclus = new_dclus % limit;
-		if (new_dclus < FAT_START_ENT)
-			new_dclus = FAT_START_ENT;
-
-		ret = fat_access(sb, new_dclus, -1);
-		if (ret < 0) {
-			unlock_fat(sb);
-			return ret;
-		} else if (ret == FAT_ENT_FREE)
-			break;
-	}
-	if (count >= limit) {
-		sbi->free_clusters = 0;
-		unlock_fat(sb);
-		return -ENOSPC;
-	}
-
-	ret = fat_access(sb, new_dclus, FAT_ENT_EOF);
-	if (ret < 0) {
-		unlock_fat(sb);
-		return ret;
-	}
-
-	sbi->prev_free = new_dclus;
-	if (sbi->free_clusters != -1)
-		sbi->free_clusters--;
-	fat_clusters_flush(sb);
-
-	unlock_fat(sb);
-
 	/* add new one to the last of the cluster chain */
 	if (last) {
-		ret = fat_access(sb, last, new_dclus);
+		struct fat_entry fatent;
+
+		fatent_init(&fatent);
+		ret = fat_ent_read(inode, &fatent, last);
+		if (ret >= 0) {
+			int wait = inode_needs_sync(inode);
+			ret = fat_ent_write(inode, &fatent, new_dclus, wait);
+			fatent_brelse(&fatent);
+		}
 		if (ret < 0)
 			return ret;
 //		fat_cache_add(inode, new_fclus, new_dclus);
 	} else {
 		MSDOS_I(inode)->i_start = new_dclus;
 		MSDOS_I(inode)->i_logstart = new_dclus;
-		mark_inode_dirty(inode);
+		/*
+		 * Since generic_osync_inode() synchronize later if
+		 * this is not directory, we don't here.
+		 */
+		if (S_ISDIR(inode->i_mode) && IS_DIRSYNC(inode)) {
+			ret = fat_sync_inode(inode);
+			if (ret)
+				return ret;
+		} else
+			mark_inode_dirty(inode);
 	}
-	if (new_fclus != (inode->i_blocks >> (cluster_bits - 9))) {
+	if (new_fclus != (inode->i_blocks >> (sbi->cluster_bits - 9))) {
 		fat_fs_panic(sb, "clusters badly computed (%d != %lu)",
-			new_fclus, inode->i_blocks >> (cluster_bits - 9));
+			new_fclus, inode->i_blocks >> (sbi->cluster_bits - 9));
 		fat_cache_inval_inode(inode);
 	}
-	inode->i_blocks += sbi->cluster_size >> 9;
+	inode->i_blocks += nr_cluster << (sbi->cluster_bits - 9);
 
-	return new_dclus;
+	return 0;
 }
 
 extern struct timezone sys_tz;
@@ -230,52 +196,30 @@
 
 EXPORT_SYMBOL(fat_date_unix2dos);
 
-/* Returns the inode number of the directory entry at offset pos. If bh is
-   non-NULL, it is brelse'd before. Pos is incremented. The buffer header is
-   returned in bh.
-   AV. Most often we do it item-by-item. Makes sense to optimize.
-   AV. OK, there we go: if both bh and de are non-NULL we assume that we just
-   AV. want the next entry (took one explicit de=NULL in vfat/namei.c).
-   AV. It's done in fat_get_entry() (inlined), here the slow case lives.
-   AV. Additionally, when we return -1 (i.e. reached the end of directory)
-   AV. we make bh NULL.
- */
-
-int fat__get_entry(struct inode *dir, loff_t *pos, struct buffer_head **bh,
-		   struct msdos_dir_entry **de, loff_t *i_pos)
+int fat_sync_bhs(struct buffer_head **bhs, int nr_bhs)
 {
-	struct super_block *sb = dir->i_sb;
-	struct msdos_sb_info *sbi = MSDOS_SB(sb);
-	sector_t phys, iblock;
-	loff_t offset;
-	int err;
-
-next:
-	offset = *pos;
-	if (*bh)
-		brelse(*bh);
-
-	*bh = NULL;
-	iblock = *pos >> sb->s_blocksize_bits;
-	err = fat_bmap(dir, iblock, &phys);
-	if (err || !phys)
-		return -1;	/* beyond EOF or error */
-
-	*bh = sb_bread(sb, phys);
-	if (*bh == NULL) {
-		printk(KERN_ERR "FAT: Directory bread(block %llu) failed\n",
-		       (unsigned long long)phys);
-		/* skip this block */
-		*pos = (iblock + 1) << sb->s_blocksize_bits;
-		goto next;
-	}
-
-	offset &= sb->s_blocksize - 1;
-	*pos += sizeof(struct msdos_dir_entry);
-	*de = (struct msdos_dir_entry *)((*bh)->b_data + offset);
-	*i_pos = ((loff_t)phys << sbi->dir_per_block_bits) + (offset >> MSDOS_DIR_BITS);
+	int i, e, err = 0;
 
-	return 0;
+	for (i = 0; i < nr_bhs; i++) {
+		lock_buffer(bhs[i]);
+		if (test_clear_buffer_dirty(bhs[i])) {
+			get_bh(bhs[i]);
+			bhs[i]->b_end_io = end_buffer_write_sync;
+			e = submit_bh(WRITE, bhs[i]);
+			if (!err && e)
+				err = e;
+		} else
+			unlock_buffer(bhs[i]);
+	}
+	for (i = 0; i < nr_bhs; i++) {
+		wait_on_buffer(bhs[i]);
+		if (buffer_eopnotsupp(bhs[i])) {
+			clear_buffer_eopnotsupp(bhs[i]);
+			err = -EOPNOTSUPP;
+		} else if (!err && !buffer_uptodate(bhs[i]))
+			err = -EIO;
+	}
+	return err;
 }
 
-EXPORT_SYMBOL(fat__get_entry);
+EXPORT_SYMBOL(fat_sync_bhs);
diff -Nru a/fs/hostfs/Makefile b/fs/hostfs/Makefile
--- a/fs/hostfs/Makefile	2005-03-11 12:51:42 -08:00
+++ b/fs/hostfs/Makefile	2005-03-11 12:51:42 -08:00
@@ -3,13 +3,6 @@
 # Licensed under the GPL
 #
 
-# struct stat64 changed the inode field name between 2.2 and 2.4 from st_ino
-# to __st_ino.  It stayed in the same place, so as long as the correct name
-# is used, hostfs compiled on 2.2 should work on 2.4 and vice versa.
-
-STAT64_INO_FIELD := $(shell grep -q __st_ino /usr/include/bits/stat.h && \
-				echo __)st_ino
-
 hostfs-objs := hostfs_kern.o hostfs_user.o
 
 obj-y =
@@ -19,8 +12,6 @@
 
 USER_OBJS := $(filter %_user.o,$(obj-y) $(obj-m) $(SINGLE_OBJS))
 USER_OBJS := $(foreach file,$(USER_OBJS),$(obj)/$(file))
-
-USER_CFLAGS += -DSTAT64_INO_FIELD=$(STAT64_INO_FIELD)
 
 $(USER_OBJS) : %.o: %.c
 	$(CC) $(CFLAGS_$(notdir $@)) $(USER_CFLAGS) -c -o $@ $<
diff -Nru a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c
--- a/fs/hostfs/hostfs_kern.c	2005-03-11 12:51:41 -08:00
+++ b/fs/hostfs/hostfs_kern.c	2005-03-11 12:51:41 -08:00
@@ -845,7 +845,7 @@
 	if(attr->ia_valid & ATTR_GID){
 		if((dentry->d_inode->i_sb->s_dev == ROOT_DEV) &&
 		   (attr->ia_gid == 0))
-			attr->ia_gid = getuid();
+			attr->ia_gid = getgid();
 		attrs.ia_valid |= HOSTFS_ATTR_GID;
 		attrs.ia_gid = attr->ia_gid;
 	}
diff -Nru a/fs/hostfs/hostfs_user.c b/fs/hostfs/hostfs_user.c
--- a/fs/hostfs/hostfs_user.c	2005-03-11 12:51:47 -08:00
+++ b/fs/hostfs/hostfs_user.c	2005-03-11 12:51:47 -08:00
@@ -28,10 +28,7 @@
 	if(lstat64(path, &buf) < 0)
 		return(-errno);
 
-	/* See the Makefile for why STAT64_INO_FIELD is passed in
-	 * by the build
-	 */
-	if(inode_out != NULL) *inode_out = buf.STAT64_INO_FIELD;
+	if(inode_out != NULL) *inode_out = buf.st_ino;
 	if(mode_out != NULL) *mode_out = buf.st_mode;
 	if(nlink_out != NULL) *nlink_out = buf.st_nlink;
 	if(uid_out != NULL) *uid_out = buf.st_uid;
diff -Nru a/fs/inode.c b/fs/inode.c
--- a/fs/inode.c	2005-03-11 12:51:51 -08:00
+++ b/fs/inode.c	2005-03-11 12:51:51 -08:00
@@ -196,7 +196,7 @@
 	sema_init(&inode->i_sem, 1);
 	init_rwsem(&inode->i_alloc_sem);
 	INIT_RADIX_TREE(&inode->i_data.page_tree, GFP_ATOMIC);
-	spin_lock_init(&inode->i_data.tree_lock);
+	rwlock_init(&inode->i_data.tree_lock);
 	spin_lock_init(&inode->i_data.i_mmap_lock);
 	INIT_LIST_HEAD(&inode->i_data.private_list);
 	spin_lock_init(&inode->i_data.private_lock);
diff -Nru a/fs/jbd/commit.c b/fs/jbd/commit.c
--- a/fs/jbd/commit.c	2005-03-11 12:51:51 -08:00
+++ b/fs/jbd/commit.c	2005-03-11 12:51:51 -08:00
@@ -93,6 +93,73 @@
 	return 1;
 }
 
+/* Done it all: now write the commit record.  We should have
+ * cleaned up our previous buffers by now, so if we are in abort
+ * mode we can now just skip the rest of the journal write
+ * entirely.
+ *
+ * Returns 1 if the journal needs to be aborted or 0 on success
+ */
+static int journal_write_commit_record(journal_t *journal,
+					transaction_t *commit_transaction)
+{
+	struct journal_head *descriptor;
+	struct buffer_head *bh;
+	int i, ret;
+	int barrier_done = 0;
+
+	if (is_journal_aborted(journal))
+		return 0;
+
+	descriptor = journal_get_descriptor_buffer(journal);
+	if (!descriptor)
+		return 1;
+
+	bh = jh2bh(descriptor);
+
+	/* AKPM: buglet - add `i' to tmp! */
+	for (i = 0; i < bh->b_size; i += 512) {
+		journal_header_t *tmp = (journal_header_t*)bh->b_data;
+		tmp->h_magic = cpu_to_be32(JFS_MAGIC_NUMBER);
+		tmp->h_blocktype = cpu_to_be32(JFS_COMMIT_BLOCK);
+		tmp->h_sequence = cpu_to_be32(commit_transaction->t_tid);
+	}
+
+	JBUFFER_TRACE(descriptor, "write commit block");
+	set_buffer_dirty(bh);
+	if (journal->j_flags & JFS_BARRIER) {
+		set_buffer_ordered(bh);
+		barrier_done = 1;
+	}
+	ret = sync_dirty_buffer(bh);
+	/* is it possible for another commit to fail at roughly
+	 * the same time as this one?  If so, we don't want to
+	 * trust the barrier flag in the super, but instead want
+	 * to remember if we sent a barrier request
+	 */
+	if (ret == -EOPNOTSUPP && barrier_done) {
+		char b[BDEVNAME_SIZE];
+
+		printk(KERN_WARNING
+			"JBD: barrier-based sync failed on %s - "
+			"disabling barriers\n",
+			bdevname(journal->j_dev, b));
+		spin_lock(&journal->j_state_lock);
+		journal->j_flags &= ~JFS_BARRIER;
+		spin_unlock(&journal->j_state_lock);
+
+		/* And try again, without the barrier */
+		clear_buffer_ordered(bh);
+		set_buffer_uptodate(bh);
+		set_buffer_dirty(bh);
+		ret = sync_dirty_buffer(bh);
+	}
+	put_bh(bh);		/* One for getblk() */
+	journal_put_journal_head(descriptor);
+
+	return (ret == -EIO);
+}
+
 /*
  * journal_commit_transaction
  *
@@ -103,7 +170,7 @@
 {
 	transaction_t *commit_transaction;
 	struct journal_head *jh, *new_jh, *descriptor;
-	struct buffer_head *wbuf[64];
+	struct buffer_head **wbuf = journal->j_wbuf;
 	int bufs;
 	int flags;
 	int err;
@@ -229,6 +296,22 @@
 	jbd_debug (3, "JBD: commit phase 2\n");
 
 	/*
+	 * First, drop modified flag: all accesses to the buffers
+	 * will be tracked for a new trasaction only -bzzz
+	 */
+	spin_lock(&journal->j_list_lock);
+	if (commit_transaction->t_buffers) {
+		new_jh = jh = commit_transaction->t_buffers->b_tnext;
+		do {
+			J_ASSERT_JH(new_jh, new_jh->b_modified == 1 ||
+					new_jh->b_modified == 0);
+			new_jh->b_modified = 0;
+			new_jh = new_jh->b_tnext;
+		} while (new_jh != jh);
+	}
+	spin_unlock(&journal->j_list_lock);
+
+	/*
 	 * Now start flushing things to disk, in the order they appear
 	 * on the transaction lists.  Data blocks go first.
 	 */
@@ -271,7 +354,7 @@
 				BUFFER_TRACE(bh, "start journal writeout");
 				get_bh(bh);
 				wbuf[bufs++] = bh;
-				if (bufs == ARRAY_SIZE(wbuf)) {
+				if (bufs == journal->j_wbufsize) {
 					jbd_debug(2, "submit %d writes\n",
 							bufs);
 					spin_unlock(&journal->j_list_lock);
@@ -487,7 +570,7 @@
 		/* If there's no more to do, or if the descriptor is full,
 		   let the IO rip! */
 
-		if (bufs == ARRAY_SIZE(wbuf) ||
+		if (bufs == journal->j_wbufsize ||
 		    commit_transaction->t_buffers == NULL ||
 		    space_left < sizeof(journal_block_tag_t) + 16) {
 
@@ -616,78 +699,16 @@
 
 	jbd_debug(3, "JBD: commit phase 6\n");
 
-	if (is_journal_aborted(journal))
-		goto skip_commit;
-
-	/* Done it all: now write the commit record.  We should have
-	 * cleaned up our previous buffers by now, so if we are in abort
-	 * mode we can now just skip the rest of the journal write
-	 * entirely. */
+	if (journal_write_commit_record(journal, commit_transaction))
+		err = -EIO;
 
-	descriptor = journal_get_descriptor_buffer(journal);
-	if (!descriptor) {
+	if (err)
 		__journal_abort_hard(journal);
-		goto skip_commit;
-	}
-
-	/* AKPM: buglet - add `i' to tmp! */
-	for (i = 0; i < jh2bh(descriptor)->b_size; i += 512) {
-		journal_header_t *tmp =
-			(journal_header_t*)jh2bh(descriptor)->b_data;
-		tmp->h_magic = cpu_to_be32(JFS_MAGIC_NUMBER);
-		tmp->h_blocktype = cpu_to_be32(JFS_COMMIT_BLOCK);
-		tmp->h_sequence = cpu_to_be32(commit_transaction->t_tid);
-	}
-
-	JBUFFER_TRACE(descriptor, "write commit block");
-	{
-		struct buffer_head *bh = jh2bh(descriptor);
-		int ret;
-		int barrier_done = 0;
-
-		set_buffer_dirty(bh);
-		if (journal->j_flags & JFS_BARRIER) {
-			set_buffer_ordered(bh);
-			barrier_done = 1;
-		}
-		ret = sync_dirty_buffer(bh);
-		/* is it possible for another commit to fail at roughly
-		 * the same time as this one?  If so, we don't want to
-		 * trust the barrier flag in the super, but instead want
-		 * to remember if we sent a barrier request
-		 */
-		if (ret == -EOPNOTSUPP && barrier_done) {
-			char b[BDEVNAME_SIZE];
-
-			printk(KERN_WARNING
-				"JBD: barrier-based sync failed on %s - "
-				"disabling barriers\n",
-				bdevname(journal->j_dev, b));
-			spin_lock(&journal->j_state_lock);
-			journal->j_flags &= ~JFS_BARRIER;
-			spin_unlock(&journal->j_state_lock);
-
-			/* And try again, without the barrier */
-			clear_buffer_ordered(bh);
-			set_buffer_uptodate(bh);
-			set_buffer_dirty(bh);
-			ret = sync_dirty_buffer(bh);
-		}
-		if (unlikely(ret == -EIO))
-			err = -EIO;
-		put_bh(bh);		/* One for getblk() */
-		journal_put_journal_head(descriptor);
-	}
 
 	/* End of a transaction!  Finally, we can do checkpoint
            processing: any buffers committed as a result of this
            transaction can be removed from any checkpoint list it was on
            before. */
-
-skip_commit: /* The journal should be unlocked by now. */
-
-	if (err)
-		__journal_abort_hard(journal);
 
 	jbd_debug(3, "JBD: commit phase 7\n");
 
diff -Nru a/fs/jbd/journal.c b/fs/jbd/journal.c
--- a/fs/jbd/journal.c	2005-03-11 12:51:41 -08:00
+++ b/fs/jbd/journal.c	2005-03-11 12:51:41 -08:00
@@ -721,6 +721,7 @@
 {
 	journal_t *journal = journal_init_common();
 	struct buffer_head *bh;
+	int n;
 
 	if (!journal)
 		return NULL;
@@ -736,6 +737,17 @@
 	journal->j_sb_buffer = bh;
 	journal->j_superblock = (journal_superblock_t *)bh->b_data;
 
+	/* journal descriptor can store up to n blocks -bzzz */
+	n = journal->j_blocksize / sizeof(journal_block_tag_t);
+	journal->j_wbufsize = n;
+	journal->j_wbuf = kmalloc(n * sizeof(struct buffer_head*), GFP_KERNEL);
+	if (!journal->j_wbuf) {
+		printk(KERN_ERR "%s: Cant allocate bhs for commit thread\n",
+			__FUNCTION__);
+		kfree(journal);
+		journal = NULL;
+	}
+
 	return journal;
 }
  
@@ -752,6 +764,7 @@
 	struct buffer_head *bh;
 	journal_t *journal = journal_init_common();
 	int err;
+	int n;
 	unsigned long blocknr;
 
 	if (!journal)
@@ -768,6 +781,17 @@
 	journal->j_maxlen = inode->i_size >> inode->i_sb->s_blocksize_bits;
 	journal->j_blocksize = inode->i_sb->s_blocksize;
 
+	/* journal descriptor can store up to n blocks -bzzz */
+	n = journal->j_blocksize / sizeof(journal_block_tag_t);
+	journal->j_wbufsize = n;
+	journal->j_wbuf = kmalloc(n * sizeof(struct buffer_head*), GFP_KERNEL);
+	if (!journal->j_wbuf) {
+		printk(KERN_ERR "%s: Cant allocate bhs for commit thread\n",
+			__FUNCTION__);
+		kfree(journal);
+		return NULL;
+	}
+
 	err = journal_bmap(journal, 0, &blocknr);
 	/* If that failed, give up */
 	if (err) {
@@ -1141,6 +1165,7 @@
 		iput(journal->j_inode);
 	if (journal->j_revoke)
 		journal_destroy_revoke(journal);
+	kfree(journal->j_wbuf);
 	kfree(journal);
 }
 
diff -Nru a/fs/jbd/transaction.c b/fs/jbd/transaction.c
--- a/fs/jbd/transaction.c	2005-03-11 12:51:42 -08:00
+++ b/fs/jbd/transaction.c	2005-03-11 12:51:42 -08:00
@@ -522,7 +522,7 @@
  */
 static int
 do_get_write_access(handle_t *handle, struct journal_head *jh,
-			int force_copy, int *credits) 
+			int force_copy)
 {
 	struct buffer_head *bh;
 	transaction_t *transaction;
@@ -604,11 +604,6 @@
 		JBUFFER_TRACE(jh, "has frozen data");
 		J_ASSERT_JH(jh, jh->b_next_transaction == NULL);
 		jh->b_next_transaction = transaction;
-
-		J_ASSERT_JH(jh, handle->h_buffer_credits > 0);
-		handle->h_buffer_credits--;
-		if (credits)
-			(*credits)++;
 		goto done;
 	}
 
@@ -688,10 +683,6 @@
 		jh->b_next_transaction = transaction;
 	}
 
-	J_ASSERT(handle->h_buffer_credits > 0);
-	handle->h_buffer_credits--;
-	if (credits)
-		(*credits)++;
 
 	/*
 	 * Finally, if the buffer is not journaled right now, we need to make
@@ -749,8 +740,7 @@
  * because we're write()ing a buffer which is also part of a shared mapping.
  */
 
-int journal_get_write_access(handle_t *handle,
-			struct buffer_head *bh, int *credits)
+int journal_get_write_access(handle_t *handle, struct buffer_head *bh)
 {
 	struct journal_head *jh = journal_add_journal_head(bh);
 	int rc;
@@ -758,7 +748,7 @@
 	/* We do not want to get caught playing with fields which the
 	 * log thread also manipulates.  Make sure that the buffer
 	 * completes any outstanding IO before proceeding. */
-	rc = do_get_write_access(handle, jh, 0, credits);
+	rc = do_get_write_access(handle, jh, 0);
 	journal_put_journal_head(jh);
 	return rc;
 }
@@ -814,9 +804,6 @@
 	J_ASSERT_JH(jh, jh->b_next_transaction == NULL);
 	J_ASSERT_JH(jh, buffer_locked(jh2bh(jh)));
 
-	J_ASSERT_JH(jh, handle->h_buffer_credits > 0);
-	handle->h_buffer_credits--;
-
 	if (jh->b_transaction == NULL) {
 		jh->b_transaction = transaction;
 		JBUFFER_TRACE(jh, "file as BJ_Reserved");
@@ -869,8 +856,7 @@
  *
  * Returns error number or 0 on success.
  */
-int journal_get_undo_access(handle_t *handle, struct buffer_head *bh,
-				int *credits)
+int journal_get_undo_access(handle_t *handle, struct buffer_head *bh)
 {
 	int err;
 	struct journal_head *jh = journal_add_journal_head(bh);
@@ -883,7 +869,7 @@
 	 * make sure that obtaining the committed_data is done
 	 * atomically wrt. completion of any outstanding commits.
 	 */
-	err = do_get_write_access(handle, jh, 1, credits);
+	err = do_get_write_access(handle, jh, 1);
 	if (err)
 		goto out;
 
@@ -1111,6 +1097,17 @@
 
 	jbd_lock_bh_state(bh);
 
+	if (jh->b_modified == 0) {
+		/*
+		 * This buffer's got modified and becoming part
+		 * of the transaction. This needs to be done
+		 * once a transaction -bzzz
+		 */
+		jh->b_modified = 1;
+		J_ASSERT_JH(jh, handle->h_buffer_credits > 0);
+		handle->h_buffer_credits--;
+	}
+
 	/*
 	 * fastpath, to avoid expensive locking.  If this buffer is already
 	 * on the running transaction's metadata list there is nothing to do.
@@ -1161,24 +1158,11 @@
  * journal_release_buffer: undo a get_write_access without any buffer
  * updates, if the update decided in the end that it didn't need access.
  *
- * The caller passes in the number of credits which should be put back for
- * this buffer (zero or one).
- *
- * We leave the buffer attached to t_reserved_list because even though this
- * handle doesn't want it, some other concurrent handle may want to journal
- * this buffer.  If that handle is curently in between get_write_access() and
- * journal_dirty_metadata() then it expects the buffer to be reserved.  If
- * we were to rip it off t_reserved_list here, the other handle will explode
- * when journal_dirty_metadata is presented with a non-reserved buffer.
- *
- * If nobody really wants to journal this buffer then it will be thrown
- * away at the start of commit.
  */
 void
-journal_release_buffer(handle_t *handle, struct buffer_head *bh, int credits)
+journal_release_buffer(handle_t *handle, struct buffer_head *bh)
 {
 	BUFFER_TRACE(bh, "entry");
-	handle->h_buffer_credits += credits;
 }
 
 /** 
@@ -1203,6 +1187,7 @@
 	transaction_t *transaction = handle->h_transaction;
 	journal_t *journal = transaction->t_journal;
 	struct journal_head *jh;
+	int drop_reserve = 0;
 	int err = 0;
 
 	BUFFER_TRACE(bh, "entry");
@@ -1222,6 +1207,12 @@
 		goto not_jbd;
 	}
 
+	/*
+	 * The buffer's going from the transaction, we must drop
+	 * all references -bzzz
+	 */
+	jh->b_modified = 0;
+
 	if (jh->b_transaction == handle->h_transaction) {
 		J_ASSERT_JH(jh, !jh->b_frozen_data);
 
@@ -1234,6 +1225,7 @@
 		JBUFFER_TRACE(jh, "belongs to current transaction: unfile");
 
 		__journal_unfile_buffer(jh);
+		drop_reserve = 1;
 
 		/* 
 		 * We are no longer going to journal this buffer.
@@ -1256,7 +1248,7 @@
 				spin_unlock(&journal->j_list_lock);
 				jbd_unlock_bh_state(bh);
 				__bforget(bh);
-				return 0;
+				goto drop;
 			}
 		}
 	} else if (jh->b_transaction) {
@@ -1271,6 +1263,7 @@
 		if (jh->b_next_transaction) {
 			J_ASSERT(jh->b_next_transaction == transaction);
 			jh->b_next_transaction = NULL;
+			drop_reserve = 1;
 		}
 	}
 
@@ -1278,6 +1271,11 @@
 	spin_unlock(&journal->j_list_lock);
 	jbd_unlock_bh_state(bh);
 	__brelse(bh);
+drop:
+	if (drop_reserve) {
+		/* no need to reserve log space for this block -bzzz */
+		handle->h_buffer_credits++;
+	}
 	return err;
 }
 
diff -Nru a/fs/jfs/inode.c b/fs/jfs/inode.c
--- a/fs/jfs/inode.c	2005-03-11 12:51:40 -08:00
+++ b/fs/jfs/inode.c	2005-03-11 12:51:40 -08:00
@@ -286,7 +286,7 @@
 
 static int jfs_writepage(struct page *page, struct writeback_control *wbc)
 {
-	return block_write_full_page(page, jfs_get_block, wbc);
+	return nobh_writepage(page, jfs_get_block, wbc);
 }
 
 static int jfs_writepages(struct address_space *mapping,
diff -Nru a/fs/jfs/jfs_logmgr.c b/fs/jfs/jfs_logmgr.c
--- a/fs/jfs/jfs_logmgr.c	2005-03-11 12:51:46 -08:00
+++ b/fs/jfs/jfs_logmgr.c	2005-03-11 12:51:46 -08:00
@@ -67,6 +67,7 @@
 #include <linux/buffer_head.h>		/* for sync_blockdev() */
 #include <linux/bio.h>
 #include <linux/suspend.h>
+#include <linux/delay.h>
 #include "jfs_incore.h"
 #include "jfs_filsys.h"
 #include "jfs_metapage.h"
@@ -1612,8 +1613,7 @@
 	 */
 	if ((!list_empty(&log->cqueue)) || !list_empty(&log->synclist)) {
 		for (i = 0; i < 800; i++) {	/* Too much? */
-			current->state = TASK_INTERRUPTIBLE;
-			schedule_timeout(HZ / 4);
+			msleep(250);
 			if (list_empty(&log->cqueue) &&
 			    list_empty(&log->synclist))
 				break;
diff -Nru a/fs/jfs/jfs_metapage.c b/fs/jfs/jfs_metapage.c
--- a/fs/jfs/jfs_metapage.c	2005-03-11 12:51:42 -08:00
+++ b/fs/jfs/jfs_metapage.c	2005-03-11 12:51:42 -08:00
@@ -21,6 +21,7 @@
 #include <linux/init.h>
 #include <linux/buffer_head.h>
 #include <linux/mempool.h>
+#include <linux/delay.h>
 #include "jfs_incore.h"
 #include "jfs_superblock.h"
 #include "jfs_filsys.h"
@@ -242,14 +243,14 @@
 	mp = search_hash(hash_ptr, mapping, lblock);
 	if (mp) {
 	      page_found:
-		mp->count++;
-		lock_metapage(mp);
-		spin_unlock(&meta_lock);
 		if (test_bit(META_stale, &mp->flag)) {
-			release_metapage(mp);
-			yield();	/* Let other waiters release it, too */
+			spin_unlock(&meta_lock);
+			msleep(1);
 			goto again;
 		}
+		mp->count++;
+		lock_metapage(mp);
+		spin_unlock(&meta_lock);
 		if (test_bit(META_discard, &mp->flag)) {
 			if (!new) {
 				jfs_error(inode->i_sb,
@@ -461,7 +462,6 @@
 	}
 
 	if (mp->page) {
-		/* Releasing spinlock, we have to check mp->count later */
 		set_bit(META_stale, &mp->flag);
 		spin_unlock(&meta_lock);
 		kunmap(mp->page);
@@ -498,12 +498,6 @@
 		list_del(&mp->synclist);
 		LOGSYNC_UNLOCK(log);
 	}
-	if (mp->count) {
-		/* Someone else is trying to get this metpage */
-		unlock_metapage(mp);
-		spin_unlock(&meta_lock);
-		return;
-	}
 	remove_from_hash(mp, meta_hash(mp->mapping, mp->index));
 	spin_unlock(&meta_lock);
 
@@ -532,12 +526,8 @@
 		mp = search_hash(hash_ptr, mapping, lblock);
 		if (mp) {
 			if (test_bit(META_stale, &mp->flag)) {
-				/* Racing with release_metapage */
-				mp->count++;
-				lock_metapage(mp);
 				spin_unlock(&meta_lock);
-				/* racing release_metapage should be done now */
-				release_metapage(mp);
+				msleep(1);
 				goto again;
 			}
 
diff -Nru a/fs/jfs/jfs_txnmgr.c b/fs/jfs/jfs_txnmgr.c
--- a/fs/jfs/jfs_txnmgr.c	2005-03-11 12:51:47 -08:00
+++ b/fs/jfs/jfs_txnmgr.c	2005-03-11 12:51:47 -08:00
@@ -93,15 +93,15 @@
 } TxStat;
 #endif
 
-static int nTxBlock = 512;	/* number of transaction blocks */
+static int nTxBlock = -1;	/* number of transaction blocks */
 module_param(nTxBlock, int, 0);
 MODULE_PARM_DESC(nTxBlock,
-		 "Number of transaction blocks (default:512, max:65536)");
+		 "Number of transaction blocks (max:65536)");
 
-static int nTxLock = 4096;	/* number of transaction locks */
+static int nTxLock = -1;	/* number of transaction locks */
 module_param(nTxLock, int, 0);
 MODULE_PARM_DESC(nTxLock,
-		 "Number of transaction locks (default:4096, max:65536)");
+		 "Number of transaction locks (max:65536)");
 
 struct tblock *TxBlock;	        /* transaction block table */
 static int TxLockLWM;		/* Low water mark for number of txLocks used */
@@ -124,6 +124,7 @@
 
 DECLARE_WAIT_QUEUE_HEAD(jfs_sync_thread_wait);
 DECLARE_WAIT_QUEUE_HEAD(jfs_commit_thread_wait);
+static int jfs_commit_thread_waking;
 
 /*
  * Retry logic exist outside these macros to protect from spurrious wakeups.
@@ -249,6 +250,25 @@
 int txInit(void)
 {
 	int k, size;
+	struct sysinfo si;
+
+	/* Set defaults for nTxLock and nTxBlock if unset */
+
+	if (nTxLock == -1) {
+		if (nTxBlock == -1) {
+			/* Base default on memory size */
+			si_meminfo(&si);
+			if (si.totalram > (256 * 1024)) /* 1 GB */
+				nTxLock = 64 * 1024;
+			else
+				nTxLock = si.totalram >> 2;
+		} else if (nTxBlock > (8 * 1024))
+			nTxLock = 64 * 1024;
+		else
+			nTxLock = nTxBlock << 3;
+	}
+	if (nTxBlock == -1)
+		nTxBlock = nTxLock >> 3;
 
 	/* Verify tunable parameters */
 	if (nTxBlock < 16)
@@ -259,6 +279,9 @@
 		nTxLock = 256;	/* No one should set it this low */
 	if (nTxLock > 65536)
 		nTxLock = 65536;
+
+	printk(KERN_INFO "JFS: nTxBlock = %d, nTxLock = %d\n",
+	       nTxBlock, nTxLock);
 	/*
 	 * initialize transaction block (tblock) table
 	 *
@@ -266,8 +289,8 @@
 	 * tid = 0 is reserved.
 	 */
 	TxLockLWM = (nTxLock * 4) / 10;
-	TxLockHWM = (nTxLock * 8) / 10;
-	TxLockVHWM = (nTxLock * 9) / 10;
+	TxLockHWM = (nTxLock * 7) / 10;
+	TxLockVHWM = (nTxLock * 8) / 10;
 
 	size = sizeof(struct tblock) * nTxBlock;
 	TxBlock = (struct tblock *) vmalloc(size);
@@ -2732,6 +2755,7 @@
 
 	do {
 		LAZY_LOCK(flags);
+		jfs_commit_thread_waking = 0;	/* OK to wake another thread */
 		while (!list_empty(&TxAnchor.unlock_queue)) {
 			WorkDone = 0;
 			list_for_each_entry(tblk, &TxAnchor.unlock_queue,
@@ -2804,10 +2828,13 @@
 	list_add_tail(&tblk->cqueue, &TxAnchor.unlock_queue);
 	/*
 	 * Don't wake up a commit thread if there is already one servicing
-	 * this superblock.
+	 * this superblock, or if the last one we woke up hasn't started yet.
 	 */
-	if (!(JFS_SBI(tblk->sb)->commit_state & IN_LAZYCOMMIT))
+	if (!(JFS_SBI(tblk->sb)->commit_state & IN_LAZYCOMMIT) &&
+	    !jfs_commit_thread_waking) {
+		jfs_commit_thread_waking = 1;
 		wake_up(&jfs_commit_thread_wait);
+	}
 	LAZY_UNLOCK(flags);
 }
 
diff -Nru a/fs/jfs/super.c b/fs/jfs/super.c
--- a/fs/jfs/super.c	2005-03-11 12:51:43 -08:00
+++ b/fs/jfs/super.c	2005-03-11 12:51:43 -08:00
@@ -235,7 +235,7 @@
 static int parse_options(char *options, struct super_block *sb, s64 *newLVSize,
 			 int *flag)
 {
-	void *nls_map = NULL;
+	void *nls_map = (void *)-1;	/* -1: no change;  NULL: none */
 	char *p;
 	struct jfs_sb_info *sbi = JFS_SBI(sb);
 
@@ -263,12 +263,17 @@
 			/* Don't do anything ;-) */
 			break;
 		case Opt_iocharset:
-			if (nls_map)	/* specified iocharset twice! */
+			if (nls_map && nls_map != (void *) -1)
 				unload_nls(nls_map);
-			nls_map = load_nls(args[0].from);
-			if (!nls_map) {
-				printk(KERN_ERR "JFS: charset not found\n");
-				goto cleanup;
+			if (!strcmp(args[0].from, "none"))
+				nls_map = NULL;
+			else {
+				nls_map = load_nls(args[0].from);
+				if (!nls_map) {
+					printk(KERN_ERR
+					       "JFS: charset not found\n");
+					goto cleanup;
+				}
 			}
 			break;
 		case Opt_resize:
@@ -318,7 +323,7 @@
 		}
 	}
 
-	if (nls_map) {
+	if (nls_map != (void *) -1) {
 		/* Discard old (if remount) */
 		if (sbi->nls_tab)
 			unload_nls(sbi->nls_tab);
@@ -327,7 +332,7 @@
 	return 1;
 
 cleanup:
-	if (nls_map)
+	if (nls_map && nls_map != (void *) -1)
 		unload_nls(nls_map);
 	return 0;
 }
@@ -622,7 +627,7 @@
 
 	if (commit_threads < 1)
 		commit_threads = num_online_cpus();
-	else if (commit_threads > MAX_COMMIT_THREADS)
+	if (commit_threads > MAX_COMMIT_THREADS)
 		commit_threads = MAX_COMMIT_THREADS;
 
 	for (i = 0; i < commit_threads; i++) {
diff -Nru a/fs/lockd/clntproc.c b/fs/lockd/clntproc.c
--- a/fs/lockd/clntproc.c	2005-03-11 12:51:52 -08:00
+++ b/fs/lockd/clntproc.c	2005-03-11 12:51:52 -08:00
@@ -322,14 +322,13 @@
 /*
  * Generic NLM call
  */
-int
+static int
 nlmclnt_call(struct nlm_rqst *req, u32 proc)
 {
 	struct nlm_host	*host = req->a_host;
 	struct rpc_clnt	*clnt;
 	struct nlm_args	*argp = &req->a_args;
 	struct nlm_res	*resp = &req->a_res;
-	struct file	*filp = argp->lock.fl.fl_file;
 	struct rpc_message msg = {
 		.rpc_argp	= argp,
 		.rpc_resp	= resp,
@@ -339,9 +338,6 @@
 	dprintk("lockd: call procedure %d on %s\n",
 			(int)proc, host->h_name);
 
-	if (filp)
-		msg.rpc_cred = nfs_file_cred(filp);
-
 	do {
 		if (host->h_reclaiming && !argp->reclaim)
 			goto in_grace_period;
@@ -428,14 +424,13 @@
 	return status;
 }
 
-int
+static int
 nlmclnt_async_call(struct nlm_rqst *req, u32 proc, rpc_action callback)
 {
 	struct nlm_host	*host = req->a_host;
 	struct rpc_clnt	*clnt;
 	struct nlm_args	*argp = &req->a_args;
 	struct nlm_res	*resp = &req->a_res;
-	struct file	*file = argp->lock.fl.fl_file;
 	struct rpc_message msg = {
 		.rpc_argp	= argp,
 		.rpc_resp	= resp,
@@ -450,11 +445,9 @@
 		return -ENOLCK;
 	msg.rpc_proc = &clnt->cl_procinfo[proc];
 
-        /* bootstrap and kick off the async RPC call */
-	if (file)
-		msg.rpc_cred = nfs_file_cred(file);
 	/* Increment host refcount */
 	nlm_get_host(host);
+        /* bootstrap and kick off the async RPC call */
         status = rpc_call_async(clnt, &msg, RPC_TASK_ASYNC, callback, req);
 	if (status < 0)
 		nlm_release_host(host);
@@ -516,6 +509,24 @@
 	fl->fl_ops = &nlmclnt_lock_ops;
 }
 
+static void do_vfs_lock(struct file_lock *fl)
+{
+	int res = 0;
+	switch (fl->fl_flags & (FL_POSIX|FL_FLOCK)) {
+		case FL_POSIX:
+			res = posix_lock_file_wait(fl->fl_file, fl);
+			break;
+		case FL_FLOCK:
+			res = flock_lock_file_wait(fl->fl_file, fl);
+			break;
+		default:
+			BUG();
+	}
+	if (res < 0)
+		printk(KERN_WARNING "%s: VFS is out of sync with lock manager!\n",
+				__FUNCTION__);
+}
+
 /*
  * LOCK: Try to create a lock
  *
@@ -564,9 +575,7 @@
 		fl->fl_u.nfs_fl.state = host->h_state;
 		fl->fl_u.nfs_fl.flags |= NFS_LCK_GRANTED;
 		fl->fl_flags |= FL_SLEEP;
-		if (posix_lock_file_wait(fl->fl_file, fl) < 0)
-				printk(KERN_WARNING "%s: VFS is out of sync with lock manager!\n",
-						__FUNCTION__);
+		do_vfs_lock(fl);
 	}
 	status = nlm_stat_to_errno(resp->status);
 out:
@@ -635,7 +644,7 @@
 					nlmclnt_unlock_callback);
 		/* Hrmf... Do the unlock early since locks_remove_posix()
 		 * really expects us to free the lock synchronously */
-		posix_lock_file(fl->fl_file, fl);
+		do_vfs_lock(fl);
 		if (status < 0) {
 			nlmclnt_release_lockargs(req);
 			kfree(req);
@@ -648,7 +657,7 @@
 	if (status < 0)
 		return status;
 
-	posix_lock_file(fl->fl_file, fl);
+	do_vfs_lock(fl);
 	if (resp->status == NLM_LCK_GRANTED)
 		return 0;
 
diff -Nru a/fs/lockd/host.c b/fs/lockd/host.c
--- a/fs/lockd/host.c	2005-03-11 12:51:46 -08:00
+++ b/fs/lockd/host.c	2005-03-11 12:51:46 -08:00
@@ -110,7 +110,6 @@
 	host->h_addr.sin_port = 0;	/* ouch! */
 	host->h_version    = version;
 	host->h_proto      = proto;
-	host->h_authflavor = RPC_AUTH_UNIX;
 	host->h_rpcclnt    = NULL;
 	init_MUTEX(&host->h_sema);
 	host->h_nextrebind = jiffies + NLM_HOST_REBIND;
@@ -191,8 +190,9 @@
 
 		xprt_set_timeout(&xprt->timeout, 5, nlmsvc_timeout);
 
+		/* Existing NLM servers accept AUTH_UNIX only */
 		clnt = rpc_create_client(xprt, host->h_name, &nlm_program,
-					host->h_version, host->h_authflavor);
+					host->h_version, RPC_AUTH_UNIX);
 		if (IS_ERR(clnt)) {
 			xprt_destroy(xprt);
 			goto forgetit;
diff -Nru a/fs/lockd/svc.c b/fs/lockd/svc.c
--- a/fs/lockd/svc.c	2005-03-11 12:51:47 -08:00
+++ b/fs/lockd/svc.c	2005-03-11 12:51:47 -08:00
@@ -403,6 +403,38 @@
 	return 0;							\
 }
 
+static inline int is_callback(u32 proc)
+{
+	return proc == NLMPROC_GRANTED
+		|| proc == NLMPROC_GRANTED_MSG
+		|| proc == NLMPROC_TEST_RES
+		|| proc == NLMPROC_LOCK_RES
+		|| proc == NLMPROC_CANCEL_RES
+		|| proc == NLMPROC_UNLOCK_RES
+		|| proc == NLMPROC_NSM_NOTIFY;
+}
+
+
+static int lockd_authenticate(struct svc_rqst *rqstp)
+{
+	rqstp->rq_client = NULL;
+	switch (rqstp->rq_authop->flavour) {
+		case RPC_AUTH_NULL:
+		case RPC_AUTH_UNIX:
+			if (rqstp->rq_proc == 0)
+				return SVC_OK;
+			if (is_callback(rqstp->rq_proc)) {
+				/* Leave it to individual procedures to
+				 * call nlmsvc_lookup_host(rqstp)
+				 */
+				return SVC_OK;
+			}
+			return svc_set_client(rqstp);
+	}
+	return SVC_DENIED;
+}
+
+
 param_set_min_max(port, int, simple_strtol, 0, 65535)
 param_set_min_max(grace_period, unsigned long, simple_strtoul,
 		  nlm_grace_period_min, nlm_grace_period_max)
@@ -483,4 +515,5 @@
 	.pg_name		= "lockd",		/* service name */
 	.pg_class		= "nfsd",		/* share authentication with nfsd */
 	.pg_stats		= &nlmsvc_stats,	/* stats table */
+	.pg_authenticate = &lockd_authenticate	/* export authentication */
 };
diff -Nru a/fs/locks.c b/fs/locks.c
--- a/fs/locks.c	2005-03-11 12:51:51 -08:00
+++ b/fs/locks.c	2005-03-11 12:51:51 -08:00
@@ -406,9 +406,16 @@
 	fl->fl_file->f_owner.signum = 0;
 }
 
+int lease_mylease_callback(struct file_lock *fl, struct file_lock *try)
+{
+	return fl->fl_file == try->fl_file;
+}
+
 struct lock_manager_operations lease_manager_ops = {
 	.fl_break = lease_break_callback,
 	.fl_release_private = lease_release_private_callback,
+	.fl_mylease = lease_mylease_callback,
+	.fl_change = lease_modify,
 };
 
 /*
@@ -1058,7 +1065,7 @@
 EXPORT_SYMBOL(locks_mandatory_area);
 
 /* We already had a lease on this file; just change its type */
-static int lease_modify(struct file_lock **before, int arg)
+int lease_modify(struct file_lock **before, int arg)
 {
 	struct file_lock *fl = *before;
 	int error = assign_type(fl, arg);
@@ -1071,6 +1078,8 @@
 	return 0;
 }
 
+EXPORT_SYMBOL(lease_modify);
+
 static void time_out_leases(struct inode *inode)
 {
 	struct file_lock **before;
@@ -1090,24 +1099,6 @@
 	}
 }
 
- /**
-*	remove_lease - let time_out_leases remove the lease.
-*	@@file_lock: the lease to remove
-*/
-void remove_lease(struct file_lock *fl)
-{
-	lock_kernel();
-	if (!fl || !IS_LEASE(fl))
-		goto out;
-	fl->fl_type = F_UNLCK | F_INPROGRESS;
-	fl->fl_break_time = jiffies - 10;
-	time_out_leases(fl->fl_file->f_dentry->d_inode);
-out:
-	unlock_kernel();
-}
-
-EXPORT_SYMBOL(remove_lease);
-
 /**
  *	__break_lease	-	revoke all outstanding leases on file
  *	@inode: the inode of the file to return
@@ -1172,10 +1163,8 @@
 		if (fl->fl_type != future) {
 			fl->fl_type = future;
 			fl->fl_break_time = break_time;
-			if (fl->fl_lmops && fl->fl_lmops->fl_break)
-				fl->fl_lmops->fl_break(fl);
-			else    /* lease must have lmops break callback */
-				BUG();
+			/* lease must have lmops break callback */
+			fl->fl_lmops->fl_break(fl);
 		}
 	}
 
@@ -1317,7 +1306,7 @@
 	for (before = &inode->i_flock;
 			((fl = *before) != NULL) && IS_LEASE(fl);
 			before = &fl->fl_next) {
-		if (fl->fl_file == filp)
+		if (lease->fl_lmops->fl_mylease(fl, lease))
 			my_before = before;
 		else if (fl->fl_type == (F_INPROGRESS | F_UNLCK))
 			/*
@@ -1335,7 +1324,7 @@
 		goto out;
 
 	if (my_before != NULL) {
-		error = lease_modify(my_before, arg);
+		error = lease->fl_lmops->fl_change(my_before, arg);
 		goto out;
 	}
 
@@ -1876,8 +1865,13 @@
 		return;
 
 	if (filp->f_op && filp->f_op->flock) {
-		struct file_lock fl = { .fl_flags = FL_FLOCK,
-					.fl_type = F_UNLCK };
+		struct file_lock fl = {
+			.fl_pid = current->tgid,
+			.fl_file = filp,
+			.fl_flags = FL_FLOCK,
+			.fl_type = F_UNLCK,
+			.fl_end = OFFSET_MAX,
+		};
 		filp->f_op->flock(filp, F_SETLKW, &fl);
 	}
 
diff -Nru a/fs/mpage.c b/fs/mpage.c
--- a/fs/mpage.c	2005-03-11 12:51:42 -08:00
+++ b/fs/mpage.c	2005-03-11 12:51:42 -08:00
@@ -386,8 +386,9 @@
  * just allocate full-size (16-page) BIOs.
  */
 static struct bio *
-mpage_writepage(struct bio *bio, struct page *page, get_block_t get_block,
-	sector_t *last_block_in_bio, int *ret, struct writeback_control *wbc)
+__mpage_writepage(struct bio *bio, struct page *page, get_block_t get_block,
+	sector_t *last_block_in_bio, int *ret, struct writeback_control *wbc,
+	writepage_t writepage_fn)
 {
 	struct address_space *mapping = page->mapping;
 	struct inode *inode = page->mapping->host;
@@ -580,7 +581,13 @@
 confused:
 	if (bio)
 		bio = mpage_bio_submit(WRITE, bio);
-	*ret = page->mapping->a_ops->writepage(page, wbc);
+
+	if (writepage_fn) {
+		*ret = (*writepage_fn)(page, wbc);
+	} else {
+		*ret = -EAGAIN;
+		goto out;
+	}
 	/*
 	 * The caller has a ref on the inode, so *mapping is stable
 	 */
@@ -706,8 +713,9 @@
 							&mapping->flags);
 				}
 			} else {
-				bio = mpage_writepage(bio, page, get_block,
-						&last_block_in_bio, &ret, wbc);
+				bio = __mpage_writepage(bio, page, get_block,
+						&last_block_in_bio, &ret, wbc,
+						page->mapping->a_ops->writepage);
 			}
 			if (ret || (--(wbc->nr_to_write) <= 0))
 				done = 1;
@@ -735,3 +743,19 @@
 	return ret;
 }
 EXPORT_SYMBOL(mpage_writepages);
+
+int mpage_writepage(struct page *page, get_block_t get_block,
+	struct writeback_control *wbc)
+{
+	int ret = 0;
+	struct bio *bio;
+	sector_t last_block_in_bio = 0;
+
+	bio = __mpage_writepage(NULL, page, get_block,
+			&last_block_in_bio, &ret, wbc, NULL);
+	if (bio)
+		mpage_bio_submit(WRITE, bio);
+
+	return ret;
+}
+EXPORT_SYMBOL(mpage_writepage);
diff -Nru a/fs/msdos/namei.c b/fs/msdos/namei.c
--- a/fs/msdos/namei.c	2005-03-11 12:51:52 -08:00
+++ b/fs/msdos/namei.c	2005-03-11 12:51:52 -08:00
@@ -137,29 +137,29 @@
 
 /***** Locates a directory entry.  Uses unformatted name. */
 static int msdos_find(struct inode *dir, const unsigned char *name, int len,
-		      struct buffer_head **bh, struct msdos_dir_entry **de,
-		      loff_t *i_pos)
+		      struct fat_slot_info *sinfo)
 {
+	struct msdos_sb_info *sbi = MSDOS_SB(dir->i_sb);
 	unsigned char msdos_name[MSDOS_NAME];
-	char dotsOK;
-	int res;
+	int err;
 
-	dotsOK = MSDOS_SB(dir->i_sb)->options.dotsOK;
-	res = msdos_format_name(name, len, msdos_name,
-				&MSDOS_SB(dir->i_sb)->options);
-	if (res < 0)
+	err = msdos_format_name(name, len, msdos_name, &sbi->options);
+	if (err)
 		return -ENOENT;
-	res = fat_scan(dir, msdos_name, bh, de, i_pos);
-	if (!res && dotsOK) {
+
+	err = fat_scan(dir, msdos_name, sinfo);
+	if (!err && sbi->options.dotsOK) {
 		if (name[0] == '.') {
-			if (!((*de)->attr & ATTR_HIDDEN))
-				res = -ENOENT;
+			if (!(sinfo->de->attr & ATTR_HIDDEN))
+				err = -ENOENT;
 		} else {
-			if ((*de)->attr & ATTR_HIDDEN)
-				res = -ENOENT;
+			if (sinfo->de->attr & ATTR_HIDDEN)
+				err = -ENOENT;
 		}
+		if (err)
+			brelse(sinfo->bh);
 	}
-	return res;
+	return err;
 }
 
 /*
@@ -221,31 +221,30 @@
 				   struct nameidata *nd)
 {
 	struct super_block *sb = dir->i_sb;
+	struct fat_slot_info sinfo;
 	struct inode *inode = NULL;
-	struct msdos_dir_entry *de;
-	struct buffer_head *bh = NULL;
-	loff_t i_pos;
 	int res;
 
 	dentry->d_op = &msdos_dentry_operations;
 
 	lock_kernel();
-	res = msdos_find(dir, dentry->d_name.name, dentry->d_name.len, &bh,
-			 &de, &i_pos);
+	res = msdos_find(dir, dentry->d_name.name, dentry->d_name.len, &sinfo);
 	if (res == -ENOENT)
 		goto add;
 	if (res < 0)
 		goto out;
-	inode = fat_build_inode(sb, de, i_pos, &res);
-	if (res)
+	inode = fat_build_inode(sb, sinfo.de, sinfo.i_pos);
+	brelse(sinfo.bh);
+	if (IS_ERR(inode)) {
+		res = PTR_ERR(inode);
 		goto out;
+	}
 add:
 	res = 0;
 	dentry = d_splice_alias(inode, dentry);
 	if (dentry)
 		dentry->d_op = &msdos_dentry_operations;
 out:
-	brelse(bh);
 	unlock_kernel();
 	if (!res)
 		return dentry;
@@ -254,31 +253,36 @@
 
 /***** Creates a directory entry (name is already formatted). */
 static int msdos_add_entry(struct inode *dir, const unsigned char *name,
-			   struct buffer_head **bh,
-			   struct msdos_dir_entry **de,
-			   loff_t *i_pos, int is_dir, int is_hid)
+			   int is_dir, int is_hid, int cluster,
+			   struct timespec *ts, struct fat_slot_info *sinfo)
 {
-	int res;
-
-	res = fat_add_entries(dir, 1, bh, de, i_pos);
-	if (res < 0)
-		return res;
+	struct msdos_dir_entry de;
+	__le16 time, date;
+	int err;
 
-	/*
-	 * XXX all times should be set by caller upon successful completion.
-	 */
-	dir->i_ctime = dir->i_mtime = CURRENT_TIME_SEC;
-	mark_inode_dirty(dir);
-
-	memcpy((*de)->name, name, MSDOS_NAME);
-	(*de)->attr = is_dir ? ATTR_DIR : ATTR_ARCH;
+	memcpy(de.name, name, MSDOS_NAME);
+	de.attr = is_dir ? ATTR_DIR : ATTR_ARCH;
 	if (is_hid)
-		(*de)->attr |= ATTR_HIDDEN;
-	(*de)->start = 0;
-	(*de)->starthi = 0;
-	fat_date_unix2dos(dir->i_mtime.tv_sec, &(*de)->time, &(*de)->date);
-	(*de)->size = 0;
-	mark_buffer_dirty(*bh);
+		de.attr |= ATTR_HIDDEN;
+	de.lcase = 0;
+	fat_date_unix2dos(ts->tv_sec, &time, &date);
+	de.time = de.ctime = time;
+	de.date = de.cdate = de.adate = date;
+	de.ctime_cs = 0;
+	de.start = cpu_to_le16(cluster);
+	de.starthi = cpu_to_le16(cluster >> 16);
+	de.size = 0;
+
+	err = fat_add_entries(dir, &de, 1, sinfo);
+	if (err)
+		return err;
+
+	dir->i_ctime = dir->i_mtime = *ts;
+	if (IS_DIRSYNC(dir))
+		(void)fat_sync_inode(dir);
+	else
+		mark_inode_dirty(dir);
+
 	return 0;
 }
 
@@ -287,320 +291,366 @@
 			struct nameidata *nd)
 {
 	struct super_block *sb = dir->i_sb;
-	struct buffer_head *bh;
-	struct msdos_dir_entry *de;
 	struct inode *inode;
-	loff_t i_pos;
-	int res, is_hid;
+	struct fat_slot_info sinfo;
+	struct timespec ts;
 	unsigned char msdos_name[MSDOS_NAME];
+	int err, is_hid;
 
 	lock_kernel();
-	res = msdos_format_name(dentry->d_name.name, dentry->d_name.len,
+
+	err = msdos_format_name(dentry->d_name.name, dentry->d_name.len,
 				msdos_name, &MSDOS_SB(sb)->options);
-	if (res < 0) {
-		unlock_kernel();
-		return res;
-	}
+	if (err)
+		goto out;
 	is_hid = (dentry->d_name.name[0] == '.') && (msdos_name[0] != '.');
 	/* Have to do it due to foo vs. .foo conflicts */
-	if (fat_scan(dir, msdos_name, &bh, &de, &i_pos) >= 0) {
-		brelse(bh);
-		unlock_kernel();
-		return -EINVAL;
-	}
-	inode = NULL;
-	res = msdos_add_entry(dir, msdos_name, &bh, &de, &i_pos, 0, is_hid);
-	if (res) {
-		unlock_kernel();
-		return res;
-	}
-	inode = fat_build_inode(dir->i_sb, de, i_pos, &res);
-	brelse(bh);
-	if (!inode) {
-		unlock_kernel();
-		return res;
+	if (!fat_scan(dir, msdos_name, &sinfo)) {
+		brelse(sinfo.bh);
+		err = -EINVAL;
+		goto out;
 	}
-	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC;
-	mark_inode_dirty(inode);
+
+	ts = CURRENT_TIME_SEC;
+	err = msdos_add_entry(dir, msdos_name, 0, is_hid, 0, &ts, &sinfo);
+	if (err)
+		goto out;
+	inode = fat_build_inode(sb, sinfo.de, sinfo.i_pos);
+	brelse(sinfo.bh);
+	if (IS_ERR(inode)) {
+		err = PTR_ERR(inode);
+		goto out;
+	}
+	inode->i_mtime = inode->i_atime = inode->i_ctime = ts;
+	/* timestamp is already written, so mark_inode_dirty() is unneeded. */
+
 	d_instantiate(dentry, inode);
+out:
 	unlock_kernel();
-	return 0;
+	return err;
 }
 
 /***** Remove a directory */
 static int msdos_rmdir(struct inode *dir, struct dentry *dentry)
 {
 	struct inode *inode = dentry->d_inode;
-	loff_t i_pos;
-	int res;
-	struct buffer_head *bh;
-	struct msdos_dir_entry *de;
+	struct fat_slot_info sinfo;
+	int err;
 
-	bh = NULL;
 	lock_kernel();
-	res = msdos_find(dir, dentry->d_name.name, dentry->d_name.len,
-			 &bh, &de, &i_pos);
-	if (res < 0)
-		goto rmdir_done;
 	/*
 	 * Check whether the directory is not in use, then check
 	 * whether it is empty.
 	 */
-	res = fat_dir_empty(inode);
-	if (res)
-		goto rmdir_done;
+	err = fat_dir_empty(inode);
+	if (err)
+		goto out;
+	err = msdos_find(dir, dentry->d_name.name, dentry->d_name.len, &sinfo);
+	if (err)
+		goto out;
 
-	de->name[0] = DELETED_FLAG;
-	mark_buffer_dirty(bh);
-	fat_detach(inode);
-	inode->i_nlink = 0;
-	inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME_SEC;
+	err = fat_remove_entries(dir, &sinfo);	/* and releases bh */
+	if (err)
+		goto out;
 	dir->i_nlink--;
-	mark_inode_dirty(inode);
-	mark_inode_dirty(dir);
-	res = 0;
 
-rmdir_done:
-	brelse(bh);
+	inode->i_nlink = 0;
+	inode->i_ctime = CURRENT_TIME_SEC;
+	fat_detach(inode);
+out:
 	unlock_kernel();
-	return res;
+
+	return err;
 }
 
 /***** Make a directory */
 static int msdos_mkdir(struct inode *dir, struct dentry *dentry, int mode)
 {
 	struct super_block *sb = dir->i_sb;
-	struct buffer_head *bh;
-	struct msdos_dir_entry *de;
+	struct fat_slot_info sinfo;
 	struct inode *inode;
-	int res, is_hid;
 	unsigned char msdos_name[MSDOS_NAME];
-	loff_t i_pos;
+	struct timespec ts;
+	int err, is_hid, cluster;
 
 	lock_kernel();
-	res = msdos_format_name(dentry->d_name.name, dentry->d_name.len,
+
+	err = msdos_format_name(dentry->d_name.name, dentry->d_name.len,
 				msdos_name, &MSDOS_SB(sb)->options);
-	if (res < 0) {
-		unlock_kernel();
-		return res;
-	}
+	if (err)
+		goto out;
 	is_hid = (dentry->d_name.name[0] == '.') && (msdos_name[0] != '.');
 	/* foo vs .foo situation */
-	if (fat_scan(dir, msdos_name, &bh, &de, &i_pos) >= 0)
-		goto out_exist;
-
-	res = msdos_add_entry(dir, msdos_name, &bh, &de, &i_pos, 1, is_hid);
-	if (res)
-		goto out_unlock;
-	inode = fat_build_inode(dir->i_sb, de, i_pos, &res);
-	if (!inode) {
-		brelse(bh);
-		goto out_unlock;
+	if (!fat_scan(dir, msdos_name, &sinfo)) {
+		brelse(sinfo.bh);
+		err = -EINVAL;
+		goto out;
 	}
-	res = 0;
 
+	ts = CURRENT_TIME_SEC;
+	cluster = fat_alloc_new_dir(dir, &ts);
+	if (cluster < 0) {
+		err = cluster;
+		goto out;
+	}
+	err = msdos_add_entry(dir, msdos_name, 1, is_hid, cluster, &ts, &sinfo);
+	if (err)
+		goto out_free;
 	dir->i_nlink++;
-	inode->i_nlink = 2;	/* no need to mark them dirty */
 
-	res = fat_new_dir(inode, dir, 0);
-	if (res)
-		goto mkdir_error;
+	inode = fat_build_inode(sb, sinfo.de, sinfo.i_pos);
+	brelse(sinfo.bh);
+	if (IS_ERR(inode)) {
+		err = PTR_ERR(inode);
+		/* the directory was completed, just return a error */
+		goto out;
+	}
+	inode->i_nlink = 2;
+	inode->i_mtime = inode->i_atime = inode->i_ctime = ts;
+	/* timestamp is already written, so mark_inode_dirty() is unneeded. */
 
-	brelse(bh);
 	d_instantiate(dentry, inode);
-	res = 0;
 
-out_unlock:
 	unlock_kernel();
-	return res;
-
-mkdir_error:
-	inode->i_nlink = 0;
-	inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME_SEC;
-	dir->i_nlink--;
-	mark_inode_dirty(inode);
-	mark_inode_dirty(dir);
-	de->name[0] = DELETED_FLAG;
-	mark_buffer_dirty(bh);
-	brelse(bh);
-	fat_detach(inode);
-	iput(inode);
-	goto out_unlock;
+	return 0;
 
-out_exist:
-	brelse(bh);
-	res = -EINVAL;
-	goto out_unlock;
+out_free:
+	fat_free_clusters(dir, cluster);
+out:
+	unlock_kernel();
+	return err;
 }
 
 /***** Unlink a file */
 static int msdos_unlink(struct inode *dir, struct dentry *dentry)
 {
 	struct inode *inode = dentry->d_inode;
-	loff_t i_pos;
-	int res;
-	struct buffer_head *bh;
-	struct msdos_dir_entry *de;
+	struct fat_slot_info sinfo;
+	int err;
 
-	bh = NULL;
 	lock_kernel();
-	res = msdos_find(dir, dentry->d_name.name, dentry->d_name.len,
-			 &bh, &de, &i_pos);
-	if (res < 0)
-		goto unlink_done;
+	err = msdos_find(dir, dentry->d_name.name, dentry->d_name.len, &sinfo);
+	if (err)
+		goto out;
 
-	de->name[0] = DELETED_FLAG;
-	mark_buffer_dirty(bh);
-	fat_detach(inode);
-	brelse(bh);
+	err = fat_remove_entries(dir, &sinfo);	/* and releases bh */
+	if (err)
+		goto out;
 	inode->i_nlink = 0;
-	inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME_SEC;
-	mark_inode_dirty(inode);
-	mark_inode_dirty(dir);
-	res = 0;
-unlink_done:
+	inode->i_ctime = CURRENT_TIME_SEC;
+	fat_detach(inode);
+out:
 	unlock_kernel();
-	return res;
+
+	return err;
 }
 
 static int do_msdos_rename(struct inode *old_dir, unsigned char *old_name,
 			   struct dentry *old_dentry,
 			   struct inode *new_dir, unsigned char *new_name,
-			   struct dentry *new_dentry,
-			   struct buffer_head *old_bh,
-			   struct msdos_dir_entry *old_de, loff_t old_i_pos,
-			   int is_hid)
+			   struct dentry *new_dentry, int is_hid)
 {
-	struct buffer_head *new_bh = NULL, *dotdot_bh = NULL;
-	struct msdos_dir_entry *new_de, *dotdot_de;
+	struct buffer_head *dotdot_bh;
+	struct msdos_dir_entry *dotdot_de;
+	loff_t dotdot_i_pos;
 	struct inode *old_inode, *new_inode;
-	loff_t new_i_pos, dotdot_i_pos;
-	int error;
-	int is_dir;
+	struct fat_slot_info old_sinfo, sinfo;
+	struct timespec ts;
+	int err, old_attrs, is_dir, update_dotdot, corrupt = 0;
 
+	old_sinfo.bh = sinfo.bh = dotdot_bh = NULL;
 	old_inode = old_dentry->d_inode;
 	new_inode = new_dentry->d_inode;
+
+	err = fat_scan(old_dir, old_name, &old_sinfo);
+	if (err) {
+		err = -EIO;
+		goto out;
+	}
+
 	is_dir = S_ISDIR(old_inode->i_mode);
+	update_dotdot = (is_dir && old_dir != new_dir);
+	if (update_dotdot) {
+		if (fat_get_dotdot_entry(old_inode, &dotdot_bh, &dotdot_de,
+					 &dotdot_i_pos) < 0) {
+			err = -EIO;
+			goto out;
+		}
+	}
 
-	if (fat_scan(new_dir, new_name, &new_bh, &new_de, &new_i_pos) >= 0 &&
-	    !new_inode)
-		goto degenerate_case;
-	if (is_dir) {
-		if (new_inode) {
-			error = fat_dir_empty(new_inode);
-			if (error)
+	old_attrs = MSDOS_I(old_inode)->i_attrs;
+	err = fat_scan(new_dir, new_name, &sinfo);
+	if (!err) {
+		if (!new_inode) {
+			/* "foo" -> ".foo" case. just change the ATTR_HIDDEN */
+			if (sinfo.de != old_sinfo.de) {
+				err = -EINVAL;
 				goto out;
-		}
-		if (fat_scan(old_inode, MSDOS_DOTDOT, &dotdot_bh,
-			     &dotdot_de, &dotdot_i_pos) < 0) {
-			error = -EIO;
+			}
+			if (is_hid)
+				MSDOS_I(old_inode)->i_attrs |= ATTR_HIDDEN;
+			else
+				MSDOS_I(old_inode)->i_attrs &= ~ATTR_HIDDEN;
+			if (IS_DIRSYNC(old_dir)) {
+				err = fat_sync_inode(old_inode);
+				if (err) {
+					MSDOS_I(old_inode)->i_attrs = old_attrs;
+					goto out;
+				}
+			} else
+				mark_inode_dirty(old_inode);
+
+			old_dir->i_version++;
+			old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME_SEC;
+			if (IS_DIRSYNC(old_dir))
+				(void)fat_sync_inode(old_dir);
+			else
+				mark_inode_dirty(old_dir);
 			goto out;
 		}
 	}
-	if (!new_bh) {
-		error = msdos_add_entry(new_dir, new_name, &new_bh, &new_de,
-					&new_i_pos, is_dir, is_hid);
-		if (error)
+
+	ts = CURRENT_TIME_SEC;
+	if (new_inode) {
+		if (err)
+			goto out;
+		if (MSDOS_I(new_inode)->i_pos != sinfo.i_pos) {
+			/* WTF??? Cry and fail. */
+			printk(KERN_WARNING "msdos_rename: fs corrupted\n");
+			goto out;
+		}
+
+		if (is_dir) {
+			err = fat_dir_empty(new_inode);
+			if (err)
+				goto out;
+		}
+		fat_detach(new_inode);
+	} else {
+		err = msdos_add_entry(new_dir, new_name, is_dir, is_hid, 0,
+				      &ts, &sinfo);
+		if (err)
 			goto out;
 	}
 	new_dir->i_version++;
 
-	/* There we go */
-
-	if (new_inode)
-		fat_detach(new_inode);
-	old_de->name[0] = DELETED_FLAG;
-	mark_buffer_dirty(old_bh);
 	fat_detach(old_inode);
-	fat_attach(old_inode, new_i_pos);
+	fat_attach(old_inode, sinfo.i_pos);
 	if (is_hid)
 		MSDOS_I(old_inode)->i_attrs |= ATTR_HIDDEN;
 	else
 		MSDOS_I(old_inode)->i_attrs &= ~ATTR_HIDDEN;
-	mark_inode_dirty(old_inode);
-	old_dir->i_version++;
-	old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME_SEC;
-	mark_inode_dirty(old_dir);
-	if (new_inode) {
-		new_inode->i_nlink--;
-		new_inode->i_ctime = CURRENT_TIME_SEC;
-		mark_inode_dirty(new_inode);
-	}
-	if (dotdot_bh) {
-		dotdot_de->start = cpu_to_le16(MSDOS_I(new_dir)->i_logstart);
-		dotdot_de->starthi =
-			cpu_to_le16((MSDOS_I(new_dir)->i_logstart) >> 16);
+	if (IS_DIRSYNC(new_dir)) {
+		err = fat_sync_inode(old_inode);
+		if (err)
+			goto error_inode;
+	} else
+		mark_inode_dirty(old_inode);
+
+	if (update_dotdot) {
+		int start = MSDOS_I(new_dir)->i_logstart;
+		dotdot_de->start = cpu_to_le16(start);
+		dotdot_de->starthi = cpu_to_le16(start >> 16);
 		mark_buffer_dirty(dotdot_bh);
+		if (IS_DIRSYNC(new_dir)) {
+			err = sync_dirty_buffer(dotdot_bh);
+			if (err)
+				goto error_dotdot;
+		}
 		old_dir->i_nlink--;
+		if (!new_inode)
+			new_dir->i_nlink++;
+	}
+
+	err = fat_remove_entries(old_dir, &old_sinfo);	/* and releases bh */
+	old_sinfo.bh = NULL;
+	if (err)
+		goto error_dotdot;
+	old_dir->i_version++;
+	old_dir->i_ctime = old_dir->i_mtime = ts;
+	if (IS_DIRSYNC(old_dir))
+		(void)fat_sync_inode(old_dir);
+	else
 		mark_inode_dirty(old_dir);
-		if (new_inode) {
+
+	if (new_inode) {
+		if (is_dir)
+			new_inode->i_nlink -= 2;
+		else
 			new_inode->i_nlink--;
-			mark_inode_dirty(new_inode);
-		} else {
-			new_dir->i_nlink++;
-			mark_inode_dirty(new_dir);
-		}
+		new_inode->i_ctime = ts;
 	}
-	error = 0;
 out:
-	brelse(new_bh);
+	brelse(sinfo.bh);
 	brelse(dotdot_bh);
-	return error;
+	brelse(old_sinfo.bh);
+	return err;
 
-degenerate_case:
-	error = -EINVAL;
-	if (new_de != old_de)
-		goto out;
-	if (is_hid)
-		MSDOS_I(old_inode)->i_attrs |= ATTR_HIDDEN;
-	else
-		MSDOS_I(old_inode)->i_attrs &= ~ATTR_HIDDEN;
-	mark_inode_dirty(old_inode);
-	old_dir->i_version++;
-	old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME_SEC;
-	mark_inode_dirty(old_dir);
-	return 0;
+error_dotdot:
+	/* data cluster is shared, serious corruption */
+	corrupt = 1;
+
+	if (update_dotdot) {
+		int start = MSDOS_I(old_dir)->i_logstart;
+		dotdot_de->start = cpu_to_le16(start);
+		dotdot_de->starthi = cpu_to_le16(start >> 16);
+		mark_buffer_dirty(dotdot_bh);
+		corrupt |= sync_dirty_buffer(dotdot_bh);
+	}
+error_inode:
+	fat_detach(old_inode);
+	fat_attach(old_inode, old_sinfo.i_pos);
+	MSDOS_I(old_inode)->i_attrs = old_attrs;
+	if (new_inode) {
+		fat_attach(new_inode, sinfo.i_pos);
+		if (corrupt)
+			corrupt |= fat_sync_inode(new_inode);
+	} else {
+		/*
+		 * If new entry was not sharing the data cluster, it
+		 * shouldn't be serious corruption.
+		 */
+		int err2 = fat_remove_entries(new_dir, &sinfo);
+		if (corrupt)
+			corrupt |= err2;
+		sinfo.bh = NULL;
+	}
+	if (corrupt < 0) {
+		fat_fs_panic(new_dir->i_sb,
+			     "%s: Filesystem corrupted (i_pos %lld)",
+			     __FUNCTION__, sinfo.i_pos);
+	}
+	goto out;
 }
 
 /***** Rename, a wrapper for rename_same_dir & rename_diff_dir */
 static int msdos_rename(struct inode *old_dir, struct dentry *old_dentry,
 			struct inode *new_dir, struct dentry *new_dentry)
 {
-	struct buffer_head *old_bh;
-	struct msdos_dir_entry *old_de;
-	loff_t old_i_pos;
-	int error, is_hid, old_hid; /* if new file and old file are hidden */
 	unsigned char old_msdos_name[MSDOS_NAME], new_msdos_name[MSDOS_NAME];
+	int err, is_hid;
 
 	lock_kernel();
-	error = msdos_format_name(old_dentry->d_name.name,
-				  old_dentry->d_name.len, old_msdos_name,
-				  &MSDOS_SB(old_dir->i_sb)->options);
-	if (error < 0)
-		goto rename_done;
-	error = msdos_format_name(new_dentry->d_name.name,
-				  new_dentry->d_name.len, new_msdos_name,
-				  &MSDOS_SB(new_dir->i_sb)->options);
-	if (error < 0)
-		goto rename_done;
+
+	err = msdos_format_name(old_dentry->d_name.name,
+				old_dentry->d_name.len, old_msdos_name,
+				&MSDOS_SB(old_dir->i_sb)->options);
+	if (err)
+		goto out;
+	err = msdos_format_name(new_dentry->d_name.name,
+				new_dentry->d_name.len, new_msdos_name,
+				&MSDOS_SB(new_dir->i_sb)->options);
+	if (err)
+		goto out;
 
 	is_hid =
 	     (new_dentry->d_name.name[0] == '.') && (new_msdos_name[0] != '.');
-	old_hid =
-	     (old_dentry->d_name.name[0] == '.') && (old_msdos_name[0] != '.');
 
-	error = fat_scan(old_dir, old_msdos_name, &old_bh, &old_de, &old_i_pos);
-	if (error < 0)
-		goto rename_done;
-
-	error = do_msdos_rename(old_dir, old_msdos_name, old_dentry,
-				new_dir, new_msdos_name, new_dentry,
-				old_bh, old_de, old_i_pos, is_hid);
-	brelse(old_bh);
-
-rename_done:
+	err = do_msdos_rename(old_dir, old_msdos_name, old_dentry,
+			      new_dir, new_msdos_name, new_dentry, is_hid);
+out:
 	unlock_kernel();
-	return error;
+	return err;
 }
 
 static struct inode_operations msdos_dir_inode_operations = {
diff -Nru a/fs/namei.c b/fs/namei.c
--- a/fs/namei.c	2005-03-11 12:51:42 -08:00
+++ b/fs/namei.c	2005-03-11 12:51:42 -08:00
@@ -681,7 +681,7 @@
  *
  * We expect 'base' to be positive and a directory.
  */
-int fastcall link_path_walk(const char * name, struct nameidata *nd)
+static fastcall int __link_path_walk(const char * name, struct nameidata *nd)
 {
 	struct path next;
 	struct inode *inode;
@@ -881,6 +881,37 @@
 	return err;
 }
 
+/*
+ * Wrapper to retry pathname resolution whenever the underlying
+ * file system returns an ESTALE.
+ *
+ * Retry the whole path once, forcing real lookup requests
+ * instead of relying on the dcache.
+ */
+int fastcall link_path_walk(const char *name, struct nameidata *nd)
+{
+	struct nameidata save = *nd;
+	int result;
+
+	/* make sure the stuff we saved doesn't go away */
+	dget(save.dentry);
+	mntget(save.mnt);
+
+	result = __link_path_walk(name, nd);
+	if (result == -ESTALE) {
+		*nd = save;
+		dget(nd->dentry);
+		mntget(nd->mnt);
+		nd->flags |= LOOKUP_REVAL;
+		result = __link_path_walk(name, nd);
+	}
+
+	dput(save.dentry);
+	mntput(save.mnt);
+
+	return result;
+}
+
 int fastcall path_walk(const char * name, struct nameidata *nd)
 {
 	current->total_link_count = 0;
@@ -1685,17 +1716,13 @@
 void dentry_unhash(struct dentry *dentry)
 {
 	dget(dentry);
-	spin_lock(&dcache_lock);
-	switch (atomic_read(&dentry->d_count)) {
-	default:
-		spin_unlock(&dcache_lock);
+	if (atomic_read(&dentry->d_count))
 		shrink_dcache_parent(dentry);
-		spin_lock(&dcache_lock);
-		if (atomic_read(&dentry->d_count) != 2)
-			break;
-	case 2:
+	spin_lock(&dcache_lock);
+	spin_lock(&dentry->d_lock);
+	if (atomic_read(&dentry->d_count) == 2)
 		__d_drop(dentry);
-	}
+	spin_unlock(&dentry->d_lock);
 	spin_unlock(&dcache_lock);
 }
 
diff -Nru a/fs/namespace.c b/fs/namespace.c
--- a/fs/namespace.c	2005-03-11 12:51:47 -08:00
+++ b/fs/namespace.c	2005-03-11 12:51:47 -08:00
@@ -1392,16 +1392,14 @@
 void __init mnt_init(unsigned long mempages)
 {
 	struct list_head *d;
-	unsigned long order;
 	unsigned int nr_hash;
 	int i;
 
 	mnt_cache = kmem_cache_create("mnt_cache", sizeof(struct vfsmount),
 			0, SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL, NULL);
 
-	order = 0; 
 	mount_hashtable = (struct list_head *)
-		__get_free_pages(GFP_ATOMIC, order);
+		__get_free_page(GFP_ATOMIC);
 
 	if (!mount_hashtable)
 		panic("Failed to allocate mount hash table\n");
@@ -1411,7 +1409,7 @@
 	 * We don't guarantee that "sizeof(struct list_head)" is necessarily
 	 * a power-of-two.
 	 */
-	nr_hash = (1UL << order) * PAGE_SIZE / sizeof(struct list_head);
+	nr_hash = PAGE_SIZE / sizeof(struct list_head);
 	hash_bits = 0;
 	do {
 		hash_bits++;
@@ -1425,8 +1423,7 @@
 	nr_hash = 1UL << hash_bits;
 	hash_mask = nr_hash-1;
 
-	printk("Mount-cache hash table entries: %d (order: %ld, %ld bytes)\n",
-			nr_hash, order, (PAGE_SIZE << order));
+	printk("Mount-cache hash table entries: %d\n", nr_hash);
 
 	/* And initialize the newly allocated array */
 	d = mount_hashtable;
diff -Nru a/fs/ncpfs/ncpsign_kernel.c b/fs/ncpfs/ncpsign_kernel.c
--- a/fs/ncpfs/ncpsign_kernel.c	2005-03-11 12:51:42 -08:00
+++ b/fs/ncpfs/ncpsign_kernel.c	2005-03-11 12:51:42 -08:00
@@ -11,10 +11,9 @@
 
 #include <linux/string.h>
 #include <linux/ncp.h>
+#include <linux/bitops.h>
 #include "ncpsign_kernel.h"
 
-#define rol32(i,c) (((((i)&0xffffffff)<<c)&0xffffffff)| \
-                    (((i)&0xffffffff)>>(32-c)))
 /* i386: 32-bit, little endian, handles mis-alignment */
 #ifdef __i386__
 #define GET_LE32(p) (*(int *)(p))
diff -Nru a/fs/nfs/callback.c b/fs/nfs/callback.c
--- a/fs/nfs/callback.c	2005-03-11 12:51:46 -08:00
+++ b/fs/nfs/callback.c	2005-03-11 12:51:46 -08:00
@@ -139,133 +139,10 @@
 	return ret;
 }
 
-/*
- * AUTH_NULL authentication
- */
-static int nfs_callback_null_accept(struct svc_rqst *rqstp, u32 *authp)
-{
-	struct kvec    *argv = &rqstp->rq_arg.head[0];
-	struct kvec    *resv = &rqstp->rq_res.head[0];
-
-	if (argv->iov_len < 3*4)
-		return SVC_GARBAGE;
-
-	if (svc_getu32(argv) != 0) {
-		dprintk("svc: bad null cred\n");
-		*authp = rpc_autherr_badcred;
-		return SVC_DENIED;
-	}
-	if (svc_getu32(argv) != RPC_AUTH_NULL || svc_getu32(argv) != 0) {
-		dprintk("svc: bad null verf\n");
-		 *authp = rpc_autherr_badverf;
-		 return SVC_DENIED;
-	}
-
-	/* Signal that mapping to nobody uid/gid is required */
-	rqstp->rq_cred.cr_uid = (uid_t) -1;
-	rqstp->rq_cred.cr_gid = (gid_t) -1;
-	rqstp->rq_cred.cr_group_info = groups_alloc(0);
-	if (rqstp->rq_cred.cr_group_info == NULL)
-		return SVC_DROP; /* kmalloc failure - client must retry */
-
-	/* Put NULL verifier */
-	svc_putu32(resv, RPC_AUTH_NULL);
-	svc_putu32(resv, 0);
-	dprintk("%s: success, returning %d!\n", __FUNCTION__, SVC_OK);
-	return SVC_OK;
-}
-
-static int nfs_callback_null_release(struct svc_rqst *rqstp)
-{
-	if (rqstp->rq_cred.cr_group_info)
-		put_group_info(rqstp->rq_cred.cr_group_info);
-	rqstp->rq_cred.cr_group_info = NULL;
-	return 0; /* don't drop */
-}
-
-static struct auth_ops nfs_callback_auth_null = {
-	.name = "null",
-	.flavour = RPC_AUTH_NULL,
-	.accept = nfs_callback_null_accept,
-	.release = nfs_callback_null_release,
-};
-
-/*
- * AUTH_SYS authentication
- */
-static int nfs_callback_unix_accept(struct svc_rqst *rqstp, u32 *authp)
-{
-	struct kvec    *argv = &rqstp->rq_arg.head[0];
-	struct kvec    *resv = &rqstp->rq_res.head[0];
-	struct svc_cred *cred = &rqstp->rq_cred;
-	u32 slen, i;
-	int len = argv->iov_len;
-
-	dprintk("%s: start\n", __FUNCTION__);
-	cred->cr_group_info = NULL;
-	rqstp->rq_client = NULL;
-	if ((len -= 3*4) < 0)
-		return SVC_GARBAGE;
-
-	/* Get length, time stamp and machine name */
-	svc_getu32(argv);
-	svc_getu32(argv);
-	slen = XDR_QUADLEN(ntohl(svc_getu32(argv)));
-	if (slen > 64 || (len -= (slen + 3)*4) < 0)
-		goto badcred;
-	argv->iov_base = (void*)((u32*)argv->iov_base + slen);
-	argv->iov_len -= slen*4;
-
-	cred->cr_uid = ntohl(svc_getu32(argv));
-	cred->cr_gid = ntohl(svc_getu32(argv));
-	slen = ntohl(svc_getu32(argv));
-	if (slen > 16 || (len -= (slen + 2)*4) < 0)
-		goto badcred;
-	cred->cr_group_info = groups_alloc(slen);
-	if (cred->cr_group_info == NULL)
-		return SVC_DROP;
-	for (i = 0; i < slen; i++)
-		GROUP_AT(cred->cr_group_info, i) = ntohl(svc_getu32(argv));
-
-	if (svc_getu32(argv) != RPC_AUTH_NULL || svc_getu32(argv) != 0) {
-		*authp = rpc_autherr_badverf;
-		return SVC_DENIED;
-	}
-	/* Put NULL verifier */
-	svc_putu32(resv, RPC_AUTH_NULL);
-	svc_putu32(resv, 0);
-	dprintk("%s: success, returning %d!\n", __FUNCTION__, SVC_OK);
-	return SVC_OK;
-badcred:
-	*authp = rpc_autherr_badcred;
-	return SVC_DENIED;
-}
-
-static int nfs_callback_unix_release(struct svc_rqst *rqstp)
-{
-	if (rqstp->rq_cred.cr_group_info)
-		put_group_info(rqstp->rq_cred.cr_group_info);
-	rqstp->rq_cred.cr_group_info = NULL;
-	return 0;
-}
-
-static struct auth_ops nfs_callback_auth_unix = {
-	.name = "unix",
-	.flavour = RPC_AUTH_UNIX,
-	.accept = nfs_callback_unix_accept,
-	.release = nfs_callback_unix_release,
-};
-
-/*
- * Hook the authentication protocol
- */
-static int nfs_callback_auth(struct svc_rqst *rqstp, u32 *authp)
+static int nfs_callback_authenticate(struct svc_rqst *rqstp)
 {
 	struct in_addr *addr = &rqstp->rq_addr.sin_addr;
 	struct nfs4_client *clp;
-	struct kvec *argv = &rqstp->rq_arg.head[0];
-	int flavour;
-	int retval;
 
 	/* Don't talk to strangers */
 	clp = nfs4_find_client(addr);
@@ -273,34 +150,19 @@
 		return SVC_DROP;
 	dprintk("%s: %u.%u.%u.%u NFSv4 callback!\n", __FUNCTION__, NIPQUAD(addr));
 	nfs4_put_client(clp);
-	flavour = ntohl(svc_getu32(argv));
-	switch(flavour) {
+	switch (rqstp->rq_authop->flavour) {
 		case RPC_AUTH_NULL:
-			if (rqstp->rq_proc != CB_NULL) {
-				*authp = rpc_autherr_tooweak;
-				retval = SVC_DENIED;
-				break;
-			}
-			rqstp->rq_authop = &nfs_callback_auth_null;
-			retval = nfs_callback_null_accept(rqstp, authp);
+			if (rqstp->rq_proc != CB_NULL)
+				return SVC_DENIED;
 			break;
 		case RPC_AUTH_UNIX:
-			/* Eat the authentication flavour */
-			rqstp->rq_authop = &nfs_callback_auth_unix;
-			retval = nfs_callback_unix_accept(rqstp, authp);
 			break;
+		case RPC_AUTH_GSS:
+			/* FIXME: RPCSEC_GSS handling? */
 		default:
-			/* FIXME: need to add RPCSEC_GSS upcalls */
-#if 0
-			svc_ungetu32(argv);
-			retval = svc_authenticate(rqstp, authp);
-#else
-			*authp = rpc_autherr_rejectedcred;
-			retval = SVC_DENIED;
-#endif
+			return SVC_DENIED;
 	}
-	dprintk("%s: flavour %d returning error %d\n", __FUNCTION__, flavour, retval);
-	return retval;
+	return SVC_OK;
 }
 
 /*
@@ -321,5 +183,5 @@
 	.pg_name = "NFSv4 callback",			/* service name */
 	.pg_class = "nfs",				/* authentication class */
 	.pg_stats = &nfs4_callback_stats,
-	.pg_authenticate = nfs_callback_auth,
+	.pg_authenticate = nfs_callback_authenticate,
 };
diff -Nru a/fs/nfs/dir.c b/fs/nfs/dir.c
--- a/fs/nfs/dir.c	2005-03-11 12:51:46 -08:00
+++ b/fs/nfs/dir.c	2005-03-11 12:51:46 -08:00
@@ -529,13 +529,24 @@
 }
 
 static inline
-int nfs_lookup_verify_inode(struct inode *inode, int isopen)
+int nfs_lookup_verify_inode(struct inode *inode, struct nameidata *nd)
 {
 	struct nfs_server *server = NFS_SERVER(inode);
 
-	if (isopen && !(server->flags & NFS_MOUNT_NOCTO))
-		return __nfs_revalidate_inode(server, inode);
+	if (nd != NULL) {
+		int ndflags = nd->flags;
+		/* VFS wants an on-the-wire revalidation */
+		if (ndflags & LOOKUP_REVAL)
+			goto out_force;
+		/* This is an open(2) */
+		if ((ndflags & LOOKUP_OPEN) &&
+				!(ndflags & LOOKUP_CONTINUE) &&
+				!(server->flags & NFS_MOUNT_NOCTO))
+			goto out_force;
+	}
 	return nfs_revalidate_inode(server, inode);
+out_force:
+	return __nfs_revalidate_inode(server, inode);
 }
 
 /*
@@ -579,16 +590,12 @@
 	struct nfs_fh fhandle;
 	struct nfs_fattr fattr;
 	unsigned long verifier;
-	int isopen = 0;
 
 	parent = dget_parent(dentry);
 	lock_kernel();
 	dir = parent->d_inode;
 	inode = dentry->d_inode;
 
-	if (nd && !(nd->flags & LOOKUP_CONTINUE) && (nd->flags & LOOKUP_OPEN))
-		isopen = 1;
-
 	if (!inode) {
 		if (nfs_neg_need_reval(dir, dentry, nd))
 			goto out_bad;
@@ -602,11 +609,12 @@
 	}
 
 	/* Revalidate parent directory attribute cache */
-	nfs_revalidate_inode(NFS_SERVER(dir), dir);
+	if (nfs_revalidate_inode(NFS_SERVER(dir), dir) < 0)
+		goto out_zap_parent;
 
 	/* Force a full look up iff the parent directory has changed */
 	if (nfs_check_verifier(dir, dentry)) {
-		if (nfs_lookup_verify_inode(inode, isopen))
+		if (nfs_lookup_verify_inode(inode, nd))
 			goto out_zap_parent;
 		goto out_valid;
 	}
@@ -722,7 +730,11 @@
 
 	lock_kernel();
 	/* Revalidate parent directory attribute cache */
-	nfs_revalidate_inode(NFS_SERVER(dir), dir);
+	error = nfs_revalidate_inode(NFS_SERVER(dir), dir);
+	if (error < 0) {
+		res = ERR_PTR(error);
+		goto out_unlock;
+	}
 
 	/* If we're doing an exclusive create, optimize away the lookup */
 	if (nfs_is_exclusive_create(dir, nd))
@@ -780,6 +792,7 @@
 {
 	struct dentry *res = NULL;
 	struct inode *inode = NULL;
+	int error;
 
 	/* Check that we are indeed trying to open this file */
 	if (!is_atomic_open(dir, nd))
@@ -798,7 +811,11 @@
 	/* Open the file on the server */
 	lock_kernel();
 	/* Revalidate parent directory attribute cache */
-	nfs_revalidate_inode(NFS_SERVER(dir), dir);
+	error = nfs_revalidate_inode(NFS_SERVER(dir), dir);
+	if (error < 0) {
+		res = ERR_PTR(error);
+		goto out;
+	}
 
 	if (nd->intent.open.flags & O_CREAT) {
 		nfs_begin_data_update(dir);
@@ -808,7 +825,7 @@
 		inode = nfs4_atomic_open(dir, dentry, nd);
 	unlock_kernel();
 	if (IS_ERR(inode)) {
-		int error = PTR_ERR(inode);
+		error = PTR_ERR(inode);
 		switch (error) {
 			/* Make a negative dentry */
 			case -ENOENT:
@@ -938,7 +955,7 @@
 /*
  * Code common to create, mkdir, and mknod.
  */
-static int nfs_instantiate(struct dentry *dentry, struct nfs_fh *fhandle,
+int nfs_instantiate(struct dentry *dentry, struct nfs_fh *fhandle,
 				struct nfs_fattr *fattr)
 {
 	struct inode *inode;
@@ -959,14 +976,12 @@
 		if (error < 0)
 			goto out_err;
 	}
-	inode = nfs_fhget(dentry->d_sb, fhandle, fattr);
-	if (inode) {
-		d_instantiate(dentry, inode);
-		nfs_renew_times(dentry);
-		nfs_set_verifier(dentry, nfs_save_change_attribute(dentry->d_parent->d_inode));
-		return 0;
-	}
 	error = -ENOMEM;
+	inode = nfs_fhget(dentry->d_sb, fhandle, fattr);
+	if (inode == NULL)
+		goto out_err;
+	d_instantiate(dentry, inode);
+	return 0;
 out_err:
 	d_drop(dentry);
 	return error;
@@ -982,7 +997,6 @@
 		struct nameidata *nd)
 {
 	struct iattr attr;
-	struct inode *inode;
 	int error;
 	int open_flags = 0;
 
@@ -997,18 +1011,17 @@
 
 	lock_kernel();
 	nfs_begin_data_update(dir);
-	inode = NFS_PROTO(dir)->create(dir, dentry, &attr, open_flags);
+	error = NFS_PROTO(dir)->create(dir, dentry, &attr, open_flags);
 	nfs_end_data_update(dir);
-	if (!IS_ERR(inode)) {
-		d_instantiate(dentry, inode);
-		nfs_renew_times(dentry);
-		nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
-		error = 0;
-	} else {
-		error = PTR_ERR(inode);
-		d_drop(dentry);
-	}
+	if (error != 0)
+		goto out_err;
+	nfs_renew_times(dentry);
+	nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
+	unlock_kernel();
+	return 0;
+out_err:
 	unlock_kernel();
+	d_drop(dentry);
 	return error;
 }
 
@@ -1019,9 +1032,7 @@
 nfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev)
 {
 	struct iattr attr;
-	struct nfs_fattr fattr;
-	struct nfs_fh fhandle;
-	int error;
+	int status;
 
 	dfprintk(VFS, "NFS: mknod(%s/%ld, %s\n", dir->i_sb->s_id,
 		dir->i_ino, dentry->d_name.name);
@@ -1034,15 +1045,18 @@
 
 	lock_kernel();
 	nfs_begin_data_update(dir);
-	error = NFS_PROTO(dir)->mknod(dir, &dentry->d_name, &attr, rdev,
-					&fhandle, &fattr);
+	status = NFS_PROTO(dir)->mknod(dir, dentry, &attr, rdev);
 	nfs_end_data_update(dir);
-	if (!error)
-		error = nfs_instantiate(dentry, &fhandle, &fattr);
-	else
-		d_drop(dentry);
+	if (status != 0)
+		goto out_err;
+	nfs_renew_times(dentry);
+	nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
 	unlock_kernel();
-	return error;
+	return 0;
+out_err:
+	unlock_kernel();
+	d_drop(dentry);
+	return status;
 }
 
 /*
@@ -1051,8 +1065,6 @@
 static int nfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
 {
 	struct iattr attr;
-	struct nfs_fattr fattr;
-	struct nfs_fh fhandle;
 	int error;
 
 	dfprintk(VFS, "NFS: mkdir(%s/%ld, %s\n", dir->i_sb->s_id,
@@ -1062,23 +1074,17 @@
 	attr.ia_mode = mode | S_IFDIR;
 
 	lock_kernel();
-#if 0
-	/*
-	 * Always drop the dentry, we can't always depend on
-	 * the fattr returned by the server (AIX seems to be
-	 * broken). We're better off doing another lookup than
-	 * depending on potentially bogus information.
-	 */
-	d_drop(dentry);
-#endif
 	nfs_begin_data_update(dir);
-	error = NFS_PROTO(dir)->mkdir(dir, &dentry->d_name, &attr, &fhandle,
-					&fattr);
+	error = NFS_PROTO(dir)->mkdir(dir, dentry, &attr);
 	nfs_end_data_update(dir);
-	if (!error)
-		error = nfs_instantiate(dentry, &fhandle, &fattr);
-	else
-		d_drop(dentry);
+	if (error != 0)
+		goto out_err;
+	nfs_renew_times(dentry);
+	nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
+	unlock_kernel();
+	return 0;
+out_err:
+	d_drop(dentry);
 	unlock_kernel();
 	return error;
 }
@@ -1107,7 +1113,7 @@
 	static unsigned int sillycounter;
 	const int      i_inosize  = sizeof(dir->i_ino)*2;
 	const int      countersize = sizeof(sillycounter)*2;
-	const int      slen       = strlen(".nfs") + i_inosize + countersize;
+	const int      slen       = sizeof(".nfs") + i_inosize + countersize - 1;
 	char           silly[slen+1];
 	struct qstr    qsilly;
 	struct dentry *sdentry;
@@ -1498,34 +1504,52 @@
 int nfs_permission(struct inode *inode, int mask, struct nameidata *nd)
 {
 	struct rpc_cred *cred;
-	int res;
+	int res = 0;
 
 	if (mask == 0)
-		return 0;
+		goto out;
+	/* Is this sys_access() ? */
+	if (nd != NULL && (nd->flags & LOOKUP_ACCESS))
+		goto force_lookup;
 
-	/* Are we checking permissions on anything other than lookup/execute? */
-	if ((mask & MAY_EXEC) == 0) {
-		/* We only need to check permissions on file open() and access() */
-		if (!nd || !(nd->flags & (LOOKUP_OPEN|LOOKUP_ACCESS)))
-			return 0;
-		/* NFSv4 has atomic_open... */
-		if (NFS_PROTO(inode)->version > 3 && (nd->flags & LOOKUP_OPEN))
-			return 0;
+	switch (inode->i_mode & S_IFMT) {
+		case S_IFLNK:
+			goto out;
+		case S_IFREG:
+			/* NFSv4 has atomic_open... */
+			if (nfs_server_capable(inode, NFS_CAP_ATOMIC_OPEN)
+					&& nd != NULL
+					&& (nd->flags & LOOKUP_OPEN))
+				goto out;
+			break;
+		case S_IFDIR:
+			/*
+			 * Optimize away all write operations, since the server
+			 * will check permissions when we perform the op.
+			 */
+			if ((mask & MAY_WRITE) && !(mask & MAY_READ))
+				goto out;
 	}
 
+force_lookup:
 	lock_kernel();
 
 	if (!NFS_PROTO(inode)->access)
 		goto out_notsup;
 
 	cred = rpcauth_lookupcred(NFS_CLIENT(inode)->cl_auth, 0);
-	res = nfs_do_access(inode, cred, mask);
-	put_rpccred(cred);
+	if (!IS_ERR(cred)) {
+		res = nfs_do_access(inode, cred, mask);
+		put_rpccred(cred);
+	} else
+		res = PTR_ERR(cred);
 	unlock_kernel();
+out:
 	return res;
 out_notsup:
-	nfs_revalidate_inode(NFS_SERVER(inode), inode);
-	res = generic_permission(inode, mask, NULL);
+	res = nfs_revalidate_inode(NFS_SERVER(inode), inode);
+	if (res == 0)
+		res = generic_permission(inode, mask, NULL);
 	unlock_kernel();
 	return res;
 }
diff -Nru a/fs/nfs/file.c b/fs/nfs/file.c
--- a/fs/nfs/file.c	2005-03-11 12:51:52 -08:00
+++ b/fs/nfs/file.c	2005-03-11 12:51:52 -08:00
@@ -44,6 +44,8 @@
 static int  nfs_file_flush(struct file *);
 static int  nfs_fsync(struct file *, struct dentry *dentry, int datasync);
 static int nfs_check_flags(int flags);
+static int nfs_lock(struct file *filp, int cmd, struct file_lock *fl);
+static int nfs_flock(struct file *filp, int cmd, struct file_lock *fl);
 
 struct file_operations nfs_file_operations = {
 	.llseek		= remote_llseek,
@@ -57,6 +59,7 @@
 	.release	= nfs_file_release,
 	.fsync		= nfs_fsync,
 	.lock		= nfs_lock,
+	.flock		= nfs_flock,
 	.sendfile	= nfs_file_sendfile,
 	.check_flags	= nfs_check_flags,
 };
@@ -312,6 +315,25 @@
 	return status;
 }
 
+static int do_vfs_lock(struct file *file, struct file_lock *fl)
+{
+	int res = 0;
+	switch (fl->fl_flags & (FL_POSIX|FL_FLOCK)) {
+		case FL_POSIX:
+			res = posix_lock_file_wait(file, fl);
+			break;
+		case FL_FLOCK:
+			res = flock_lock_file_wait(file, fl);
+			break;
+		default:
+			BUG();
+	}
+	if (res < 0)
+		printk(KERN_WARNING "%s: VFS is out of sync with lock manager!\n",
+				__FUNCTION__);
+	return res;
+}
+
 static int do_unlk(struct file *filp, int cmd, struct file_lock *fl)
 {
 	struct inode *inode = filp->f_mapping->host;
@@ -338,7 +360,7 @@
 	if (!(NFS_SERVER(inode)->flags & NFS_MOUNT_NONLM))
 		status = NFS_PROTO(inode)->lock(filp, cmd, fl);
 	else
-		status = posix_lock_file_wait(filp, fl);
+		status = do_vfs_lock(filp, fl);
 	unlock_kernel();
 	rpc_clnt_sigunmask(NFS_CLIENT(inode), &oldset);
 	return status;
@@ -377,9 +399,9 @@
 		 * the process exits.
 		 */
 		if (status == -EINTR || status == -ERESTARTSYS)
-			posix_lock_file_wait(filp, fl);
+			do_vfs_lock(filp, fl);
 	} else
-		status = posix_lock_file_wait(filp, fl);
+		status = do_vfs_lock(filp, fl);
 	unlock_kernel();
 	if (status < 0)
 		goto out;
@@ -401,8 +423,7 @@
 /*
  * Lock a (portion of) a file
  */
-int
-nfs_lock(struct file *filp, int cmd, struct file_lock *fl)
+static int nfs_lock(struct file *filp, int cmd, struct file_lock *fl)
 {
 	struct inode * inode = filp->f_mapping->host;
 
@@ -418,6 +439,27 @@
 	if ((inode->i_mode & (S_ISGID | S_IXGRP)) == S_ISGID)
 		return -ENOLCK;
 
+	if (IS_GETLK(cmd))
+		return do_getlk(filp, cmd, fl);
+	if (fl->fl_type == F_UNLCK)
+		return do_unlk(filp, cmd, fl);
+	return do_setlk(filp, cmd, fl);
+}
+
+/*
+ * Lock a (portion of) a file
+ */
+static int nfs_flock(struct file *filp, int cmd, struct file_lock *fl)
+{
+	struct inode * inode = filp->f_mapping->host;
+
+	dprintk("NFS: nfs_flock(f=%s/%ld, t=%x, fl=%x)\n",
+			inode->i_sb->s_id, inode->i_ino,
+			fl->fl_type, fl->fl_flags);
+
+	if (!inode)
+		return -EINVAL;
+
 	/*
 	 * No BSD flocks over NFS allowed.
 	 * Note: we could try to fake a POSIX lock request here by
@@ -425,11 +467,14 @@
 	 * Not sure whether that would be unique, though, or whether
 	 * that would break in other places.
 	 */
-	if (!fl->fl_owner || !(fl->fl_flags & FL_POSIX))
+	if (!(fl->fl_flags & FL_FLOCK))
 		return -ENOLCK;
 
-	if (IS_GETLK(cmd))
-		return do_getlk(filp, cmd, fl);
+	/* We're simulating flock() locks using posix locks on the server */
+	fl->fl_owner = (fl_owner_t)filp;
+	fl->fl_start = 0;
+	fl->fl_end = OFFSET_MAX;
+
 	if (fl->fl_type == F_UNLCK)
 		return do_unlk(filp, cmd, fl);
 	return do_setlk(filp, cmd, fl);
diff -Nru a/fs/nfs/inode.c b/fs/nfs/inode.c
--- a/fs/nfs/inode.c	2005-03-11 12:51:50 -08:00
+++ b/fs/nfs/inode.c	2005-03-11 12:51:50 -08:00
@@ -64,6 +64,8 @@
 static int  nfs_statfs(struct super_block *, struct kstatfs *);
 static int  nfs_show_options(struct seq_file *, struct vfsmount *);
 
+static struct rpc_program	nfs_program;
+
 static struct super_operations nfs_sops = { 
 	.alloc_inode	= nfs_alloc_inode,
 	.destroy_inode	= nfs_destroy_inode,
@@ -78,7 +80,7 @@
 /*
  * RPC cruft for NFS
  */
-struct rpc_stat			nfs_rpcstat = {
+static struct rpc_stat		nfs_rpcstat = {
 	.program		= &nfs_program
 };
 static struct rpc_version *	nfs_version[] = {
@@ -95,7 +97,7 @@
 #endif
 };
 
-struct rpc_program		nfs_program = {
+static struct rpc_program	nfs_program = {
 	.name			= "nfs",
 	.number			= NFS_PROGRAM,
 	.nrvers			= sizeof(nfs_version) / sizeof(nfs_version[0]),
@@ -247,6 +249,7 @@
 			.fattr = &fattr,
 	};
 	int no_root_error = 0;
+	unsigned long max_rpc_payload;
 
 	/* We probably want something more informative here */
 	snprintf(sb->s_id, sizeof(sb->s_id), "%x:%x", MAJOR(sb->s_dev), MINOR(sb->s_dev));
@@ -283,6 +286,12 @@
 	if (fsinfo.wtmax >= 512 && server->wsize > fsinfo.wtmax)
 		server->wsize = nfs_block_size(fsinfo.wtmax, NULL);
 
+	max_rpc_payload = nfs_block_size(rpc_max_payload(server->client), NULL);
+	if (server->rsize > max_rpc_payload)
+		server->rsize = max_rpc_payload;
+	if (server->wsize > max_rpc_payload)
+		server->wsize = max_rpc_payload;
+
 	server->rpages = (server->rsize + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
 	if (server->rpages > NFS_READ_MAXIOV) {
 		server->rpages = NFS_READ_MAXIOV;
@@ -317,6 +326,9 @@
 	if (sb->s_maxbytes > MAX_LFS_FILESIZE) 
 		sb->s_maxbytes = MAX_LFS_FILESIZE; 
 
+	server->client->cl_intr = (server->flags & NFS_MOUNT_INTR) ? 1 : 0;
+	server->client->cl_softrtry = (server->flags & NFS_MOUNT_SOFT) ? 1 : 0;
+
 	/* We're airborne Set socket buffersize */
 	rpc_setbufsize(server->client, server->wsize + 100, server->rsize + 100);
 	return 0;
@@ -364,9 +376,8 @@
 		goto out_fail;
 	}
 
-	clnt->cl_intr     = (server->flags & NFS_MOUNT_INTR) ? 1 : 0;
-	clnt->cl_softrtry = (server->flags & NFS_MOUNT_SOFT) ? 1 : 0;
-	clnt->cl_droppriv = (server->flags & NFS_MOUNT_BROKEN_SUID) ? 1 : 0;
+	clnt->cl_intr     = 1;
+	clnt->cl_softrtry = 1;
 	clnt->cl_chatty   = 1;
 
 	return clnt;
@@ -538,7 +549,6 @@
 		{ NFS_MOUNT_NOCTO, ",nocto", "" },
 		{ NFS_MOUNT_NOAC, ",noac", "" },
 		{ NFS_MOUNT_NONLM, ",nolock", ",lock" },
-		{ NFS_MOUNT_BROKEN_SUID, ",broken_suid", "" },
 		{ 0, NULL, NULL }
 	};
 	struct proc_nfs_info *nfs_infop;
@@ -792,7 +802,7 @@
  * Wait for the inode to get unlocked.
  * (Used for NFS_INO_LOCKED and NFS_INO_REVALIDATING).
  */
-int
+static int
 nfs_wait_on_inode(struct inode *inode, int flag)
 {
 	struct rpc_clnt	*clnt = NFS_CLIENT(inode);
@@ -856,6 +866,12 @@
 void put_nfs_open_context(struct nfs_open_context *ctx)
 {
 	if (atomic_dec_and_test(&ctx->count)) {
+		if (!list_empty(&ctx->list)) {
+			struct inode *inode = ctx->dentry->d_inode;
+			spin_lock(&inode->i_lock);
+			list_del(&ctx->list);
+			spin_unlock(&inode->i_lock);
+		}
 		if (ctx->state != NULL)
 			nfs4_close_state(ctx->state, ctx->mode);
 		if (ctx->cred != NULL)
@@ -904,7 +920,7 @@
 	if (ctx) {
 		filp->private_data = NULL;
 		spin_lock(&inode->i_lock);
-		list_del(&ctx->list);
+		list_move_tail(&ctx->list, &NFS_I(inode)->open_files);
 		spin_unlock(&inode->i_lock);
 		put_nfs_open_context(ctx);
 	}
@@ -918,8 +934,9 @@
 	struct nfs_open_context *ctx;
 	struct rpc_cred *cred;
 
-	if ((cred = rpcauth_lookupcred(NFS_CLIENT(inode)->cl_auth, 0)) == NULL)
-		return -ENOMEM;
+	cred = rpcauth_lookupcred(NFS_CLIENT(inode)->cl_auth, 0);
+	if (IS_ERR(cred))
+		return PTR_ERR(cred);
 	ctx = alloc_nfs_open_context(filp->f_dentry, cred);
 	put_rpccred(cred);
 	if (ctx == NULL)
@@ -1542,6 +1559,7 @@
 	if (data->wsize != 0)
 		server->wsize = nfs_block_size(data->wsize, NULL);
 	server->flags = data->flags & NFS_MOUNT_FLAGMASK;
+	server->caps = NFS_CAP_ATOMIC_OPEN;
 
 	server->acregmin = data->acregmin*HZ;
 	server->acregmax = data->acregmax*HZ;
@@ -1609,9 +1627,17 @@
 			err = PTR_ERR(clnt);
 			goto out_fail;
 		}
+		clnt->cl_intr     = 1;
+		clnt->cl_softrtry = 1;
 		clnt->cl_chatty   = 1;
 		clp->cl_rpcclient = clnt;
 		clp->cl_cred = rpcauth_lookupcred(clnt->cl_auth, 0);
+		if (IS_ERR(clp->cl_cred)) {
+			up_write(&clp->cl_sem);
+			err = PTR_ERR(clp->cl_cred);
+			clp->cl_cred = NULL;
+			goto out_fail;
+		}
 		memcpy(clp->cl_ipaddr, server->ip_addr, sizeof(clp->cl_ipaddr));
 		nfs_idmap_new(clp);
 	}
@@ -1634,8 +1660,6 @@
 		return PTR_ERR(clnt);
 	}
 
-	clnt->cl_intr     = (server->flags & NFS4_MOUNT_INTR) ? 1 : 0;
-	clnt->cl_softrtry = (server->flags & NFS4_MOUNT_SOFT) ? 1 : 0;
 	server->client    = clnt;
 
 	if (server->nfs4_state->cl_idmap == NULL) {
diff -Nru a/fs/nfs/mount_clnt.c b/fs/nfs/mount_clnt.c
--- a/fs/nfs/mount_clnt.c	2005-03-11 12:51:41 -08:00
+++ b/fs/nfs/mount_clnt.c	2005-03-11 12:51:41 -08:00
@@ -31,7 +31,7 @@
 
 static struct rpc_clnt *	mnt_create(char *, struct sockaddr_in *,
 								int, int);
-struct rpc_program		mnt_program;
+static struct rpc_program	mnt_program;
 
 struct mnt_fhstatus {
 	unsigned int		status;
@@ -174,7 +174,7 @@
 
 static struct rpc_stat		mnt_stats;
 
-struct rpc_program	mnt_program = {
+static struct rpc_program	mnt_program = {
 	.name		= "mount",
 	.number		= NFS_MNT_PROGRAM,
 	.nrvers		= sizeof(mnt_version)/sizeof(mnt_version[0]),
diff -Nru a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c
--- a/fs/nfs/nfs3proc.c	2005-03-11 12:51:46 -08:00
+++ b/fs/nfs/nfs3proc.c	2005-03-11 12:51:46 -08:00
@@ -295,7 +295,7 @@
  * Create a regular file.
  * For now, we don't implement O_EXCL.
  */
-static struct inode *
+static int
 nfs3_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
 		 int flags)
 {
@@ -342,29 +342,19 @@
 				break;
 
 			case NFS3_CREATE_UNCHECKED:
-				goto exit;
+				goto out;
 		}
 		goto again;
 	}
 
-exit:
-	dprintk("NFS reply create: %d\n", status);
-
+	if (status == 0)
+		status = nfs_instantiate(dentry, &fhandle, &fattr);
 	if (status != 0)
 		goto out;
-	if (fhandle.size == 0 || !(fattr.valid & NFS_ATTR_FATTR)) {
-		status = nfs3_proc_lookup(dir, &dentry->d_name, &fhandle, &fattr);
-		if (status != 0)
-			goto out;
-	}
 
 	/* When we created the file with exclusive semantics, make
 	 * sure we set the attributes afterwards. */
 	if (arg.createmode == NFS3_CREATE_EXCLUSIVE) {
-		struct nfs3_sattrargs	arg = {
-			.fh		= &fhandle,
-			.sattr		= sattr,
-		};
 		dprintk("NFS call  setattr (post-create)\n");
 
 		if (!(sattr->ia_valid & ATTR_ATIME_SET))
@@ -375,20 +365,13 @@
 		/* Note: we could use a guarded setattr here, but I'm
 		 * not sure this buys us anything (and I'd have
 		 * to revamp the NFSv3 XDR code) */
-		fattr.valid = 0;
-		status = rpc_call(NFS_CLIENT(dir), NFS3PROC_SETATTR,
-						&arg, &fattr, 0);
+		status = nfs3_proc_setattr(dentry, &fattr, sattr);
+		nfs_refresh_inode(dentry->d_inode, &fattr);
 		dprintk("NFS reply setattr (post-create): %d\n", status);
 	}
-	if (status == 0) {
-		struct inode *inode;
-		inode = nfs_fhget(dir->i_sb, &fhandle, &fattr);
-		if (inode)
-			return inode;
-		status = -ENOMEM;
-	}
 out:
-	return ERR_PTR(status);
+	dprintk("NFS reply create: %d\n", status);
+	return status;
 }
 
 static int
@@ -540,28 +523,30 @@
 }
 
 static int
-nfs3_proc_mkdir(struct inode *dir, struct qstr *name, struct iattr *sattr,
-		struct nfs_fh *fhandle, struct nfs_fattr *fattr)
+nfs3_proc_mkdir(struct inode *dir, struct dentry *dentry, struct iattr *sattr)
 {
-	struct nfs_fattr	dir_attr;
+	struct nfs_fh fhandle;
+	struct nfs_fattr fattr, dir_attr;
 	struct nfs3_mkdirargs	arg = {
 		.fh		= NFS_FH(dir),
-		.name		= name->name,
-		.len		= name->len,
+		.name		= dentry->d_name.name,
+		.len		= dentry->d_name.len,
 		.sattr		= sattr
 	};
 	struct nfs3_diropres	res = {
 		.dir_attr	= &dir_attr,
-		.fh		= fhandle,
-		.fattr		= fattr
+		.fh		= &fhandle,
+		.fattr		= &fattr
 	};
 	int			status;
 
-	dprintk("NFS call  mkdir %s\n", name->name);
+	dprintk("NFS call  mkdir %s\n", dentry->d_name.name);
 	dir_attr.valid = 0;
-	fattr->valid = 0;
+	fattr.valid = 0;
 	status = rpc_call(NFS_CLIENT(dir), NFS3PROC_MKDIR, &arg, &res, 0);
 	nfs_refresh_inode(dir, &dir_attr);
+	if (status == 0)
+		status = nfs_instantiate(dentry, &fhandle, &fattr);
 	dprintk("NFS reply mkdir: %d\n", status);
 	return status;
 }
@@ -639,23 +624,24 @@
 }
 
 static int
-nfs3_proc_mknod(struct inode *dir, struct qstr *name, struct iattr *sattr,
-		dev_t rdev, struct nfs_fh *fh, struct nfs_fattr *fattr)
+nfs3_proc_mknod(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
+		dev_t rdev)
 {
-	struct nfs_fattr	dir_attr;
+	struct nfs_fh fh;
+	struct nfs_fattr fattr, dir_attr;
 	struct nfs3_mknodargs	arg = {
 		.fh		= NFS_FH(dir),
-		.name		= name->name,
-		.len		= name->len,
+		.name		= dentry->d_name.name,
+		.len		= dentry->d_name.len,
 		.sattr		= sattr,
 		.rdev		= rdev
 	};
 	struct nfs3_diropres	res = {
 		.dir_attr	= &dir_attr,
-		.fh		= fh,
-		.fattr		= fattr
+		.fh		= &fh,
+		.fattr		= &fattr
 	};
-	int			status;
+	int status;
 
 	switch (sattr->ia_mode & S_IFMT) {
 	case S_IFBLK:	arg.type = NF3BLK;  break;
@@ -665,12 +651,14 @@
 	default:	return -EINVAL;
 	}
 
-	dprintk("NFS call  mknod %s %u:%u\n", name->name,
+	dprintk("NFS call  mknod %s %u:%u\n", dentry->d_name.name,
 			MAJOR(rdev), MINOR(rdev));
 	dir_attr.valid = 0;
-	fattr->valid = 0;
+	fattr.valid = 0;
 	status = rpc_call(NFS_CLIENT(dir), NFS3PROC_MKNOD, &arg, &res, 0);
 	nfs_refresh_inode(dir, &dir_attr);
+	if (status == 0)
+		status = nfs_instantiate(dentry, &fh, &fattr);
 	dprintk("NFS reply mknod: %d\n", status);
 	return status;
 }
diff -Nru a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
--- a/fs/nfs/nfs4proc.c	2005-03-11 12:51:48 -08:00
+++ b/fs/nfs/nfs4proc.c	2005-03-11 12:51:48 -08:00
@@ -37,6 +37,7 @@
 
 #include <linux/mm.h>
 #include <linux/utsname.h>
+#include <linux/delay.h>
 #include <linux/errno.h>
 #include <linux/string.h>
 #include <linux/sunrpc/clnt.h>
@@ -57,16 +58,17 @@
 static int nfs4_do_fsinfo(struct nfs_server *, struct nfs_fh *, struct nfs_fsinfo *);
 static int nfs4_async_handle_error(struct rpc_task *, struct nfs_server *);
 static int _nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry);
+static int nfs4_handle_exception(struct nfs_server *server, int errorcode, struct nfs4_exception *exception);
 extern u32 *nfs4_decode_dirent(u32 *p, struct nfs_entry *entry, int plus);
 extern struct rpc_procinfo nfs4_procedures[];
 
 extern nfs4_stateid zero_stateid;
 
 /* Prevent leaks of NFSv4 errors into userland */
-static inline int nfs4_map_errors(int err)
+int nfs4_map_errors(int err)
 {
 	if (err < -1000) {
-		printk(KERN_WARNING "%s could not handle NFSv4 error %d\n",
+		dprintk("%s could not handle NFSv4 error %d\n",
 				__FUNCTION__, -err);
 		return -EIO;
 	}
@@ -188,6 +190,23 @@
 		nfsi->change_attr = cinfo->after;
 }
 
+static void update_open_stateid(struct nfs4_state *state, nfs4_stateid *stateid, int open_flags)
+{
+	struct inode *inode = state->inode;
+
+	open_flags &= (FMODE_READ|FMODE_WRITE);
+	/* Protect against nfs4_find_state() */
+	spin_lock(&inode->i_lock);
+	state->state |= open_flags;
+	/* NB! List reordering - see the reclaim code for why.  */
+	if ((open_flags & FMODE_WRITE) && 0 == state->nwriters++)
+		list_move(&state->open_states, &state->owner->so_states);
+	if (open_flags & FMODE_READ)
+		state->nreaders++;
+	memcpy(&state->stateid, stateid, sizeof(state->stateid));
+	spin_unlock(&inode->i_lock);
+}
+
 /*
  * OPEN_RECLAIM:
  * 	reclaim state on the server after a reboot.
@@ -244,7 +263,7 @@
 	return status;
 }
 
-int nfs4_open_reclaim(struct nfs4_state_owner *sp, struct nfs4_state *state)
+static int nfs4_open_reclaim(struct nfs4_state_owner *sp, struct nfs4_state *state)
 {
 	struct nfs_server *server = NFS_SERVER(state->inode);
 	struct nfs4_exception exception = { };
@@ -332,7 +351,7 @@
 	return err;
 }
 
-static int _nfs4_proc_open_confirm(struct rpc_clnt *clnt, const struct nfs_fh *fh, struct nfs4_state_owner *sp, nfs4_stateid *stateid)
+static inline int _nfs4_proc_open_confirm(struct rpc_clnt *clnt, const struct nfs_fh *fh, struct nfs4_state_owner *sp, nfs4_stateid *stateid)
 {
 	struct nfs_open_confirmargs arg = {
 		.fh             = fh,
@@ -355,11 +374,49 @@
 	return status;
 }
 
-static int _nfs4_do_access(struct inode *inode, struct rpc_cred *cred, int mask)
+static int _nfs4_proc_open(struct inode *dir, struct nfs4_state_owner  *sp, struct nfs_openargs *o_arg, struct nfs_openres *o_res)
+{
+	struct nfs_server *server = NFS_SERVER(dir);
+	struct rpc_message msg = {
+		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN],
+		.rpc_argp = o_arg,
+		.rpc_resp = o_res,
+		.rpc_cred = sp->so_cred,
+	};
+	int status;
+
+	/* Update sequence id. The caller must serialize! */
+	o_arg->seqid = sp->so_seqid;
+	o_arg->id = sp->so_id;
+	o_arg->clientid = sp->so_client->cl_clientid;
+
+	status = rpc_call_sync(server->client, &msg, RPC_TASK_NOINTR);
+	nfs4_increment_seqid(status, sp);
+	if (status != 0)
+		goto out;
+	update_changeattr(dir, &o_res->cinfo);
+	if(o_res->rflags & NFS4_OPEN_RESULT_CONFIRM) {
+		status = _nfs4_proc_open_confirm(server->client, &o_res->fh,
+				sp, &o_res->stateid);
+		if (status != 0)
+			goto out;
+	}
+	if (!(o_res->f_attr->valid & NFS_ATTR_FATTR))
+		status = server->rpc_ops->getattr(server, &o_res->fh, o_res->f_attr);
+out:
+	return status;
+}
+
+static int _nfs4_do_access(struct inode *inode, struct rpc_cred *cred, int openflags)
 {
 	struct nfs_access_entry cache;
+	int mask = 0;
 	int status;
 
+	if (openflags & FMODE_READ)
+		mask |= MAY_READ;
+	if (openflags & FMODE_WRITE)
+		mask |= MAY_WRITE;
 	status = nfs_access_get_cached(inode, cred, &cache);
 	if (status == 0)
 		goto out;
@@ -379,9 +436,103 @@
 }
 
 /*
+ * OPEN_EXPIRED:
+ * 	reclaim state on the server after a network partition.
+ * 	Assumes caller holds the appropriate lock
+ */
+static int _nfs4_open_expired(struct nfs4_state_owner *sp, struct nfs4_state *state, struct dentry *dentry)
+{
+	struct dentry *parent = dget_parent(dentry);
+	struct inode *dir = parent->d_inode;
+	struct inode *inode = state->inode;
+	struct nfs_server *server = NFS_SERVER(dir);
+	struct nfs_delegation *delegation = NFS_I(inode)->delegation;
+	struct nfs_fattr        f_attr = {
+		.valid = 0,
+	};
+	struct nfs_openargs o_arg = {
+		.fh = NFS_FH(dir),
+		.open_flags = state->state,
+		.name = &dentry->d_name,
+		.bitmask = server->attr_bitmask,
+		.claim = NFS4_OPEN_CLAIM_NULL,
+	};
+	struct nfs_openres o_res = {
+		.f_attr = &f_attr,
+		.server = server,
+	};
+	int status = 0;
+
+	if (delegation != NULL && !(delegation->flags & NFS_DELEGATION_NEED_RECLAIM)) {
+		status = _nfs4_do_access(inode, sp->so_cred, state->state);
+		if (status < 0)
+			goto out;
+		memcpy(&state->stateid, &delegation->stateid, sizeof(state->stateid));
+		set_bit(NFS_DELEGATED_STATE, &state->flags);
+		goto out;
+	}
+	status = _nfs4_proc_open(dir, sp, &o_arg, &o_res);
+	if (status != 0)
+		goto out_nodeleg;
+	/* Check if files differ */
+	if ((f_attr.mode & S_IFMT) != (inode->i_mode & S_IFMT))
+		goto out_stale;
+	/* Has the file handle changed? */
+	if (nfs_compare_fh(&o_res.fh, NFS_FH(inode)) != 0) {
+		/* Verify if the change attributes are the same */
+		if (f_attr.change_attr != NFS_I(inode)->change_attr)
+			goto out_stale;
+		if (nfs_size_to_loff_t(f_attr.size) != inode->i_size)
+			goto out_stale;
+		/* Lets just pretend that this is the same file */
+		nfs_copy_fh(NFS_FH(inode), &o_res.fh);
+		NFS_I(inode)->fileid = f_attr.fileid;
+	}
+	memcpy(&state->stateid, &o_res.stateid, sizeof(state->stateid));
+	if (o_res.delegation_type != 0) {
+		if (!(delegation->flags & NFS_DELEGATION_NEED_RECLAIM))
+			nfs_inode_set_delegation(inode, sp->so_cred, &o_res);
+		else
+			nfs_inode_reclaim_delegation(inode, sp->so_cred, &o_res);
+	}
+out_nodeleg:
+	clear_bit(NFS_DELEGATED_STATE, &state->flags);
+out:
+	dput(parent);
+	return status;
+out_stale:
+	status = -ESTALE;
+	/* Invalidate the state owner so we don't ever use it again */
+	nfs4_drop_state_owner(sp);
+	d_drop(dentry);
+	/* Should we be trying to close that stateid? */
+	goto out_nodeleg;
+}
+
+static int nfs4_open_expired(struct nfs4_state_owner *sp, struct nfs4_state *state)
+{
+	struct nfs_inode *nfsi = NFS_I(state->inode);
+	struct nfs_open_context *ctx;
+	int status;
+
+	spin_lock(&state->inode->i_lock);
+	list_for_each_entry(ctx, &nfsi->open_files, list) {
+		if (ctx->state != state)
+			continue;
+		get_nfs_open_context(ctx);
+		spin_unlock(&state->inode->i_lock);
+		status = _nfs4_open_expired(sp, state, ctx->dentry);
+		put_nfs_open_context(ctx);
+		return status;
+	}
+	spin_unlock(&state->inode->i_lock);
+	return -ENOENT;
+}
+
+/*
  * Returns an nfs4_state + an extra reference to the inode
  */
-int _nfs4_open_delegated(struct inode *inode, int flags, struct rpc_cred *cred, struct nfs4_state **res)
+static int _nfs4_open_delegated(struct inode *inode, int flags, struct rpc_cred *cred, struct nfs4_state **res)
 {
 	struct nfs_delegation *delegation;
 	struct nfs_server *server = NFS_SERVER(inode);
@@ -390,7 +541,6 @@
 	struct nfs4_state_owner *sp = NULL;
 	struct nfs4_state *state = NULL;
 	int open_flags = flags & (FMODE_READ|FMODE_WRITE);
-	int mask = 0;
 	int err;
 
 	/* Protect against reboot recovery - NOTE ORDER! */
@@ -424,20 +574,12 @@
 		goto out_err;
 
 	lock_kernel();
-	err = _nfs4_do_access(inode, cred, mask);
+	err = _nfs4_do_access(inode, cred, open_flags);
 	unlock_kernel();
 	if (err != 0)
 		goto out_err;
-	spin_lock(&inode->i_lock);
-	memcpy(state->stateid.data, delegation->stateid.data,
-			sizeof(state->stateid.data));
-	state->state |= open_flags;
-	if (open_flags & FMODE_READ)
-		state->nreaders++;
-	if (open_flags & FMODE_WRITE)
-		state->nwriters++;
 	set_bit(NFS_DELEGATED_STATE, &state->flags);
-	spin_unlock(&inode->i_lock);
+	update_open_stateid(state, &delegation->stateid, open_flags);
 out_ok:
 	up(&sp->so_sema);
 	nfs4_put_state_owner(sp);
@@ -500,12 +642,6 @@
 		.f_attr         = &f_attr,
 		.server         = server,
 	};
-	struct rpc_message msg = {
-		.rpc_proc       = &nfs4_procedures[NFSPROC4_CLNT_OPEN],
-		.rpc_argp       = &o_arg,
-		.rpc_resp       = &o_res,
-		.rpc_cred	= cred,
-	};
 
 	/* Protect against reboot recovery conflicts */
 	down_read(&clp->cl_sem);
@@ -522,26 +658,10 @@
 		o_arg.u.attrs = sattr;
 	/* Serialization for the sequence id */
 	down(&sp->so_sema);
-	o_arg.seqid = sp->so_seqid;
-	o_arg.id = sp->so_id;
-	o_arg.clientid = clp->cl_clientid,
 
-	status = rpc_call_sync(server->client, &msg, RPC_TASK_NOINTR);
-	nfs4_increment_seqid(status, sp);
-	if (status)
+	status = _nfs4_proc_open(dir, sp, &o_arg, &o_res);
+	if (status != 0)
 		goto out_err;
-	update_changeattr(dir, &o_res.cinfo);
-	if(o_res.rflags & NFS4_OPEN_RESULT_CONFIRM) {
-		status = _nfs4_proc_open_confirm(server->client, &o_res.fh,
-				sp, &o_res.stateid);
-		if (status != 0)
-			goto out_err;
-	}
-	if (!(f_attr.valid & NFS_ATTR_FATTR)) {
-		status = server->rpc_ops->getattr(server, &o_res.fh, &f_attr);
-		if (status < 0)
-			goto out_err;
-	}
 
 	status = -ENOMEM;
 	inode = nfs_fhget(dir->i_sb, &o_res.fh, &f_attr);
@@ -550,14 +670,7 @@
 	state = nfs4_get_open_state(inode, sp);
 	if (!state)
 		goto out_err;
-	memcpy(&state->stateid, &o_res.stateid, sizeof(state->stateid));
-	spin_lock(&inode->i_lock);
-	if (flags & FMODE_READ)
-		state->nreaders++;
-	if (flags & FMODE_WRITE)
-		state->nwriters++;
-	state->state |= flags & (FMODE_READ|FMODE_WRITE);
-	spin_unlock(&inode->i_lock);
+	update_open_stateid(state, &o_res.stateid, flags);
 	if (o_res.delegation_type != 0)
 		nfs_inode_set_delegation(inode, cred, &o_res);
 	up(&sp->so_sema);
@@ -581,7 +694,7 @@
 }
 
 
-struct nfs4_state *nfs4_do_open(struct inode *dir, struct dentry *dentry, int flags, struct iattr *sattr, struct rpc_cred *cred)
+static struct nfs4_state *nfs4_do_open(struct inode *dir, struct dentry *dentry, int flags, struct iattr *sattr, struct rpc_cred *cred)
 {
 	struct nfs4_exception exception = { };
 	struct nfs4_state *res;
@@ -645,7 +758,7 @@
 	return rpc_call_sync(server->client, &msg, 0);
 }
 
-int nfs4_do_setattr(struct nfs_server *server, struct nfs_fattr *fattr,
+static int nfs4_do_setattr(struct nfs_server *server, struct nfs_fattr *fattr,
                 struct nfs_fh *fhandle, struct iattr *sattr,
                 struct nfs4_state *state)
 {
@@ -680,7 +793,6 @@
 	nfs4_increment_seqid(task->tk_status, sp);
 	switch (task->tk_status) {
 		case 0:
-			state->state = calldata->arg.open_flags;
 			memcpy(&state->stateid, &calldata->res.stateid,
 					sizeof(state->stateid));
 			break;
@@ -695,6 +807,7 @@
 				return;
 			}
 	}
+	state->state = calldata->arg.open_flags;
 	nfs4_put_open_state(state);
 	up(&sp->so_sema);
 	nfs4_put_state_owner(sp);
@@ -774,6 +887,8 @@
 	}
 
 	cred = rpcauth_lookupcred(NFS_SERVER(dir)->client->cl_auth, 0);
+	if (IS_ERR(cred))
+		return (struct inode *)cred;
 	state = nfs4_do_open(dir, dentry, nd->intent.open.flags, &attr, cred);
 	put_rpccred(cred);
 	if (IS_ERR(state))
@@ -789,6 +904,8 @@
 	struct inode *inode;
 
 	cred = rpcauth_lookupcred(NFS_SERVER(dir)->client->cl_auth, 0);
+	if (IS_ERR(cred))
+		return PTR_ERR(cred);
 	state = nfs4_open_delegated(dentry->d_inode, openflags, cred);
 	if (IS_ERR(state))
 		state = nfs4_do_open(dir, dentry, openflags, NULL, cred);
@@ -1009,6 +1126,8 @@
 	
 	if (size_change) {
 		struct rpc_cred *cred = rpcauth_lookupcred(NFS_SERVER(inode)->client->cl_auth, 0);
+		if (IS_ERR(cred))
+			return PTR_ERR(cred);
 		state = nfs4_find_state(inode, cred, FMODE_WRITE);
 		if (state == NULL) {
 			state = nfs4_open_delegated(dentry->d_inode,
@@ -1315,33 +1434,37 @@
  * opens the file O_RDONLY. This will all be resolved with the VFS changes.
  */
 
-static struct inode *
+static int
 nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
                  int flags)
 {
-	struct inode *inode;
-	struct nfs4_state *state = NULL;
+	struct nfs4_state *state;
 	struct rpc_cred *cred;
+	int status = 0;
 
 	cred = rpcauth_lookupcred(NFS_SERVER(dir)->client->cl_auth, 0);
+	if (IS_ERR(cred)) {
+		status = PTR_ERR(cred);
+		goto out;
+	}
 	state = nfs4_do_open(dir, dentry, flags, sattr, cred);
 	put_rpccred(cred);
-	if (!IS_ERR(state)) {
-		inode = state->inode;
-		if (flags & O_EXCL) {
-			struct nfs_fattr fattr;
-			int status;
-			status = nfs4_do_setattr(NFS_SERVER(dir), &fattr,
-			                     NFS_FH(inode), sattr, state);
-			if (status != 0) {
-				nfs4_close_state(state, flags);
-				iput(inode);
-				inode = ERR_PTR(status);
-			}
-		}
-	} else
-		inode = (struct inode *)state;
-	return inode;
+	if (IS_ERR(state)) {
+		status = PTR_ERR(state);
+		goto out;
+	}
+	d_instantiate(dentry, state->inode);
+	if (flags & O_EXCL) {
+		struct nfs_fattr fattr;
+		status = nfs4_do_setattr(NFS_SERVER(dir), &fattr,
+		                     NFS_FH(state->inode), sattr, state);
+		if (status == 0)
+			goto out;
+	} else if (flags != 0)
+		goto out;
+	nfs4_close_state(state, flags);
+out:
+	return status;
 }
 
 static int _nfs4_proc_remove(struct inode *dir, struct qstr *name)
@@ -1539,23 +1662,24 @@
 	return err;
 }
 
-static int _nfs4_proc_mkdir(struct inode *dir, struct qstr *name,
-		struct iattr *sattr, struct nfs_fh *fhandle,
-		struct nfs_fattr *fattr)
+static int _nfs4_proc_mkdir(struct inode *dir, struct dentry *dentry,
+		struct iattr *sattr)
 {
 	struct nfs_server *server = NFS_SERVER(dir);
+	struct nfs_fh fhandle;
+	struct nfs_fattr fattr;
 	struct nfs4_create_arg arg = {
 		.dir_fh = NFS_FH(dir),
 		.server = server,
-		.name = name,
+		.name = &dentry->d_name,
 		.attrs = sattr,
 		.ftype = NF4DIR,
 		.bitmask = server->attr_bitmask,
 	};
 	struct nfs4_create_res res = {
 		.server = server,
-		.fh = fhandle,
-		.fattr = fattr,
+		.fh = &fhandle,
+		.fattr = &fattr,
 	};
 	struct rpc_message msg = {
 		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_CREATE],
@@ -1564,24 +1688,24 @@
 	};
 	int			status;
 
-	fattr->valid = 0;
+	fattr.valid = 0;
 	
 	status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
-	if (!status)
+	if (!status) {
 		update_changeattr(dir, &res.dir_cinfo);
+		status = nfs_instantiate(dentry, &fhandle, &fattr);
+	}
 	return status;
 }
 
-static int nfs4_proc_mkdir(struct inode *dir, struct qstr *name,
-		struct iattr *sattr, struct nfs_fh *fhandle,
-		struct nfs_fattr *fattr)
+static int nfs4_proc_mkdir(struct inode *dir, struct dentry *dentry,
+		struct iattr *sattr)
 {
 	struct nfs4_exception exception = { };
 	int err;
 	do {
 		err = nfs4_handle_exception(NFS_SERVER(dir),
-				_nfs4_proc_mkdir(dir, name, sattr,
-					fhandle, fattr),
+				_nfs4_proc_mkdir(dir, dentry, sattr),
 				&exception);
 	} while (exception.retry);
 	return err;
@@ -1596,6 +1720,7 @@
 		.pages = &page,
 		.pgbase = 0,
 		.count = count,
+		.bitmask = NFS_SERVER(dentry->d_inode)->attr_bitmask,
 	};
 	struct nfs4_readdir_res res;
 	struct rpc_message msg = {
@@ -1630,22 +1755,23 @@
 	return err;
 }
 
-static int _nfs4_proc_mknod(struct inode *dir, struct qstr *name,
-		struct iattr *sattr, dev_t rdev, struct nfs_fh *fh,
-		struct nfs_fattr *fattr)
+static int _nfs4_proc_mknod(struct inode *dir, struct dentry *dentry,
+		struct iattr *sattr, dev_t rdev)
 {
 	struct nfs_server *server = NFS_SERVER(dir);
+	struct nfs_fh fh;
+	struct nfs_fattr fattr;
 	struct nfs4_create_arg arg = {
 		.dir_fh = NFS_FH(dir),
 		.server = server,
-		.name = name,
+		.name = &dentry->d_name,
 		.attrs = sattr,
 		.bitmask = server->attr_bitmask,
 	};
 	struct nfs4_create_res res = {
 		.server = server,
-		.fh = fh,
-		.fattr = fattr,
+		.fh = &fh,
+		.fattr = &fattr,
 	};
 	struct rpc_message msg = {
 		.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_CREATE],
@@ -1655,7 +1781,7 @@
 	int			status;
 	int                     mode = sattr->ia_mode;
 
-	fattr->valid = 0;
+	fattr.valid = 0;
 
 	BUG_ON(!(sattr->ia_valid & ATTR_MODE));
 	BUG_ON(!S_ISFIFO(mode) && !S_ISBLK(mode) && !S_ISCHR(mode) && !S_ISSOCK(mode));
@@ -1675,21 +1801,21 @@
 		arg.ftype = NF4SOCK;
 	
 	status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
-	if (!status)
+	if (status == 0) {
 		update_changeattr(dir, &res.dir_cinfo);
+		status = nfs_instantiate(dentry, &fh, &fattr);
+	}
 	return status;
 }
 
-static int nfs4_proc_mknod(struct inode *dir, struct qstr *name,
-		struct iattr *sattr, dev_t rdev, struct nfs_fh *fh,
-		struct nfs_fattr *fattr)
+static int nfs4_proc_mknod(struct inode *dir, struct dentry *dentry,
+		struct iattr *sattr, dev_t rdev)
 {
 	struct nfs4_exception exception = { };
 	int err;
 	do {
 		err = nfs4_handle_exception(NFS_SERVER(dir),
-				_nfs4_proc_mknod(dir, name, sattr, rdev,
-					fh, fattr),
+				_nfs4_proc_mknod(dir, dentry, sattr, rdev),
 				&exception);
 	} while (exception.retry);
 	return err;
@@ -2001,8 +2127,8 @@
 
 	/* Find our open stateid */
 	cred = rpcauth_lookupcred(NFS_SERVER(inode)->client->cl_auth, 0);
-	if (unlikely(cred == NULL))
-		return -ENOMEM;
+	if (IS_ERR(cred))
+		return PTR_ERR(cred);
 	ctx = alloc_nfs_open_context(dentry, cred);
 	put_rpccred(cred);
 	if (unlikely(ctx == NULL))
@@ -2067,7 +2193,7 @@
 	return 0;
 }
 
-int nfs4_wait_clnt_recover(struct rpc_clnt *clnt, struct nfs4_client *clp)
+static int nfs4_wait_clnt_recover(struct rpc_clnt *clnt, struct nfs4_client *clp)
 {
 	DEFINE_WAIT(wait);
 	sigset_t oldset;
@@ -2151,9 +2277,7 @@
 
 int nfs4_proc_setclientid(struct nfs4_client *clp, u32 program, unsigned short port)
 {
-	static nfs4_verifier sc_verifier;
-	static int initialized;
-	
+	nfs4_verifier sc_verifier;
 	struct nfs4_setclientid setclientid = {
 		.sc_verifier = &sc_verifier,
 		.sc_prog = program,
@@ -2164,27 +2288,38 @@
 		.rpc_resp = clp,
 		.rpc_cred = clp->cl_cred,
 	};
+	u32 *p;
+	int loop = 0;
+	int status;
 
-	if (!initialized) {
-		struct timespec boot_time;
-		u32 *p;
-
-		initialized = 1;
-		boot_time = CURRENT_TIME;
-		p = (u32*)sc_verifier.data;
-		*p++ = htonl((u32)boot_time.tv_sec);
-		*p = htonl((u32)boot_time.tv_nsec);
-	}
-	setclientid.sc_name_len = scnprintf(setclientid.sc_name,
-			sizeof(setclientid.sc_name), "%s/%u.%u.%u.%u",
-			clp->cl_ipaddr, NIPQUAD(clp->cl_addr.s_addr));
-	setclientid.sc_netid_len = scnprintf(setclientid.sc_netid,
-			sizeof(setclientid.sc_netid), "tcp");
-	setclientid.sc_uaddr_len = scnprintf(setclientid.sc_uaddr,
-			sizeof(setclientid.sc_uaddr), "%s.%d.%d",
-			clp->cl_ipaddr, port >> 8, port & 255);
+	p = (u32*)sc_verifier.data;
+	*p++ = htonl((u32)clp->cl_boot_time.tv_sec);
+	*p = htonl((u32)clp->cl_boot_time.tv_nsec);
+
+	for(;;) {
+		setclientid.sc_name_len = scnprintf(setclientid.sc_name,
+				sizeof(setclientid.sc_name), "%s/%u.%u.%u.%u %s %u",
+				clp->cl_ipaddr, NIPQUAD(clp->cl_addr.s_addr),
+				clp->cl_cred->cr_ops->cr_name,
+				clp->cl_id_uniquifier);
+		setclientid.sc_netid_len = scnprintf(setclientid.sc_netid,
+				sizeof(setclientid.sc_netid), "tcp");
+		setclientid.sc_uaddr_len = scnprintf(setclientid.sc_uaddr,
+				sizeof(setclientid.sc_uaddr), "%s.%d.%d",
+				clp->cl_ipaddr, port >> 8, port & 255);
 
-	return rpc_call_sync(clp->cl_rpcclient, &msg, 0);
+		status = rpc_call_sync(clp->cl_rpcclient, &msg, 0);
+		if (status != -NFS4ERR_CLID_INUSE)
+			break;
+		if (signalled())
+			break;
+		if (loop++ & 1)
+			ssleep(clp->cl_lease_time + 1);
+		else
+			if (++clp->cl_id_uniquifier == 0)
+				break;
+	}
+	return status;
 }
 
 int
@@ -2361,6 +2496,25 @@
 	return err;
 }
 
+static int do_vfs_lock(struct file *file, struct file_lock *fl)
+{
+	int res = 0;
+	switch (fl->fl_flags & (FL_POSIX|FL_FLOCK)) {
+		case FL_POSIX:
+			res = posix_lock_file_wait(file, fl);
+			break;
+		case FL_FLOCK:
+			res = flock_lock_file_wait(file, fl);
+			break;
+		default:
+			BUG();
+	}
+	if (res < 0)
+		printk(KERN_WARNING "%s: VFS is out of sync with lock manager!\n",
+				__FUNCTION__);
+	return res;
+}
+
 static int _nfs4_proc_unlck(struct nfs4_state *state, int cmd, struct file_lock *request)
 {
 	struct inode *inode = state->inode;
@@ -2408,7 +2562,7 @@
 out:
 	up(&state->lock_sema);
 	if (status == 0)
-		posix_lock_file(request->fl_file, request);
+		do_vfs_lock(request->fl_file, request);
 	up_read(&clp->cl_sem);
 	return status;
 }
@@ -2500,11 +2654,16 @@
 	return status;
 }
 
-int nfs4_lock_reclaim(struct nfs4_state *state, struct file_lock *request)
+static int nfs4_lock_reclaim(struct nfs4_state *state, struct file_lock *request)
 {
 	return _nfs4_do_setlk(state, F_SETLK, request, 1);
 }
 
+static int nfs4_lock_expired(struct nfs4_state *state, struct file_lock *request)
+{
+	return _nfs4_do_setlk(state, F_SETLK, request, 0);
+}
+
 static int _nfs4_proc_setlk(struct nfs4_state *state, int cmd, struct file_lock *request)
 {
 	struct nfs4_client *clp = state->owner->so_client;
@@ -2517,7 +2676,7 @@
 	if (status == 0) {
 		/* Note: we always want to sleep here! */
 		request->fl_flags |= FL_SLEEP;
-		if (posix_lock_file_wait(request->fl_file, request) < 0)
+		if (do_vfs_lock(request->fl_file, request) < 0)
 			printk(KERN_WARNING "%s: VFS is out of sync with lock manager!\n", __FUNCTION__);
 	}
 	up_read(&clp->cl_sem);
@@ -2573,6 +2732,16 @@
 
 	return status;
 }
+
+struct nfs4_state_recovery_ops nfs4_reboot_recovery_ops = {
+	.recover_open	= nfs4_open_reclaim,
+	.recover_lock	= nfs4_lock_reclaim,
+};
+
+struct nfs4_state_recovery_ops nfs4_network_partition_recovery_ops = {
+	.recover_open	= nfs4_open_expired,
+	.recover_lock	= nfs4_lock_expired,
+};
 
 struct nfs_rpc_ops	nfs_v4_clientops = {
 	.version	= 4,			/* protocol version */
diff -Nru a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c
--- a/fs/nfs/nfs4state.c	2005-03-11 12:51:40 -08:00
+++ b/fs/nfs/nfs4state.c	2005-03-11 12:51:40 -08:00
@@ -116,6 +116,7 @@
 	INIT_LIST_HEAD(&clp->cl_superblocks);
 	init_waitqueue_head(&clp->cl_waitq);
 	rpc_init_wait_queue(&clp->cl_rpcwaitq, "NFS4 client");
+	clp->cl_boot_time = CURRENT_TIME;
 	clp->cl_state = 1 << NFS4CLNT_OK;
 	return clp;
 }
@@ -205,7 +206,7 @@
 	nfs4_free_client(clp);
 }
 
-int nfs4_init_client(struct nfs4_client *clp)
+static int __nfs4_init_client(struct nfs4_client *clp)
 {
 	int status = nfs4_proc_setclientid(clp, NFS4_CALLBACK, nfs_callback_tcpport);
 	if (status == 0)
@@ -215,6 +216,11 @@
 	return status;
 }
 
+int nfs4_init_client(struct nfs4_client *clp)
+{
+	return nfs4_map_errors(__nfs4_init_client(clp));
+}
+
 u32
 nfs4_alloc_lockowner_id(struct nfs4_client *clp)
 {
@@ -274,8 +280,8 @@
 	return sp;
 }
 
-static void
-nfs4_unhash_state_owner(struct nfs4_state_owner *sp)
+void
+nfs4_drop_state_owner(struct nfs4_state_owner *sp)
 {
 	struct nfs4_client *clp = sp->so_client;
 	spin_lock(&clp->cl_lock);
@@ -441,7 +447,9 @@
 	if (state == NULL && new != NULL) {
 		state = new;
 		/* Caller *must* be holding owner->so_sem */
-		list_add(&state->open_states, &owner->so_states);
+		/* Note: The reclaim code dictates that we add stateless
+		 * and read-only stateids to the end of the list */
+		list_add_tail(&state->open_states, &owner->so_states);
 		state->owner = owner;
 		atomic_inc(&owner->so_count);
 		list_add(&state->inode_states, &nfsi->open_states);
@@ -497,8 +505,12 @@
 		state->nreaders--;
 	if (mode & FMODE_WRITE)
 		state->nwriters--;
-	if (state->nwriters == 0 && state->nreaders == 0)
-		list_del_init(&state->inode_states);
+	if (state->nwriters == 0) {
+		if (state->nreaders == 0)
+			list_del_init(&state->inode_states);
+		/* See reclaim code */
+		list_move_tail(&state->open_states, &owner->so_states);
+	}
 	spin_unlock(&inode->i_lock);
 	newstate = 0;
 	if (state->state != 0) {
@@ -708,7 +720,7 @@
 		sp->so_seqid++;
 	/* If the server returns BAD_SEQID, unhash state_owner here */
 	if (status == -NFS4ERR_BAD_SEQID)
-		nfs4_unhash_state_owner(sp);
+		nfs4_drop_state_owner(sp);
 }
 
 static int reclaimer(void *);
@@ -753,7 +765,7 @@
 		schedule_work(&clp->cl_recoverd);
 }
 
-static int nfs4_reclaim_locks(struct nfs4_state *state)
+static int nfs4_reclaim_locks(struct nfs4_state_recovery_ops *ops, struct nfs4_state *state)
 {
 	struct inode *inode = state->inode;
 	struct file_lock *fl;
@@ -764,7 +776,7 @@
 			continue;
 		if (((struct nfs_open_context *)fl->fl_file->private_data)->state != state)
 			continue;
-		status = nfs4_lock_reclaim(state, fl);
+		status = ops->recover_lock(state, fl);
 		if (status >= 0)
 			continue;
 		switch (status) {
@@ -786,20 +798,28 @@
 	return status;
 }
 
-static int nfs4_reclaim_open_state(struct nfs4_state_owner *sp)
+static int nfs4_reclaim_open_state(struct nfs4_state_recovery_ops *ops, struct nfs4_state_owner *sp)
 {
 	struct nfs4_state *state;
 	struct nfs4_lock_state *lock;
 	int status = 0;
 
+	/* Note: we rely on the sp->so_states list being ordered 
+	 * so that we always reclaim open(O_RDWR) and/or open(O_WRITE)
+	 * states first.
+	 * This is needed to ensure that the server won't give us any
+	 * read delegations that we have to return if, say, we are
+	 * recovering after a network partition or a reboot from a
+	 * server that doesn't support a grace period.
+	 */
 	list_for_each_entry(state, &sp->so_states, open_states) {
 		if (state->state == 0)
 			continue;
-		status = nfs4_open_reclaim(sp, state);
+		status = ops->recover_open(sp, state);
 		list_for_each_entry(lock, &state->lock_states, ls_locks)
 			lock->ls_flags &= ~NFS_LOCK_INITIALIZED;
 		if (status >= 0) {
-			status = nfs4_reclaim_locks(state);
+			status = nfs4_reclaim_locks(ops, state);
 			if (status < 0)
 				goto out_err;
 			list_for_each_entry(lock, &state->lock_states, ls_locks) {
@@ -813,8 +833,7 @@
 			default:
 				printk(KERN_ERR "%s: unhandled error %d. Zeroing state\n",
 						__FUNCTION__, status);
-			case -NFS4ERR_EXPIRED:
-			case -NFS4ERR_NO_GRACE:
+			case -ENOENT:
 			case -NFS4ERR_RECLAIM_BAD:
 			case -NFS4ERR_RECLAIM_CONFLICT:
 				/*
@@ -826,6 +845,8 @@
 				/* Mark the file as being 'closed' */
 				state->state = 0;
 				break;
+			case -NFS4ERR_EXPIRED:
+			case -NFS4ERR_NO_GRACE:
 			case -NFS4ERR_STALE_CLIENTID:
 				goto out_err;
 		}
@@ -840,6 +861,7 @@
 	struct reclaimer_args *args = (struct reclaimer_args *)ptr;
 	struct nfs4_client *clp = args->clp;
 	struct nfs4_state_owner *sp;
+	struct nfs4_state_recovery_ops *ops;
 	int status = 0;
 
 	daemonize("%u.%u.%u.%u-reclaim", NIPQUAD(clp->cl_addr));
@@ -856,20 +878,34 @@
 		goto out;
 restart_loop:
 	status = nfs4_proc_renew(clp);
-	if (status == 0 || status == -NFS4ERR_CB_PATH_DOWN)
-		goto out;
-	status = nfs4_init_client(clp);
+	switch (status) {
+		case 0:
+		case -NFS4ERR_CB_PATH_DOWN:
+			goto out;
+		case -NFS4ERR_STALE_CLIENTID:
+		case -NFS4ERR_LEASE_MOVED:
+			ops = &nfs4_reboot_recovery_ops;
+			break;
+		default:
+			ops = &nfs4_network_partition_recovery_ops;
+	};
+	status = __nfs4_init_client(clp);
 	if (status)
 		goto out_error;
-	/* Mark all delagations for reclaim */
+	/* Mark all delegations for reclaim */
 	nfs_delegation_mark_reclaim(clp);
 	/* Note: list is protected by exclusive lock on cl->cl_sem */
 	list_for_each_entry(sp, &clp->cl_state_owners, so_list) {
-		status = nfs4_reclaim_open_state(sp);
+		status = nfs4_reclaim_open_state(ops, sp);
 		if (status < 0) {
+			if (status == -NFS4ERR_NO_GRACE) {
+				ops = &nfs4_network_partition_recovery_ops;
+				status = nfs4_reclaim_open_state(ops, sp);
+			}
 			if (status == -NFS4ERR_STALE_CLIENTID)
 				goto restart_loop;
-			goto out_error;
+			if (status == -NFS4ERR_EXPIRED)
+				goto restart_loop;
 		}
 	}
 	nfs_delegation_reap_unclaimed(clp);
diff -Nru a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
--- a/fs/nfs/nfs4xdr.c	2005-03-11 12:51:52 -08:00
+++ b/fs/nfs/nfs4xdr.c	2005-03-11 12:51:52 -08:00
@@ -1010,8 +1010,13 @@
 	WRITE32(readdir->count >> 1);  /* We're not doing readdirplus */
 	WRITE32(readdir->count);
 	WRITE32(2);
-	WRITE32(FATTR4_WORD0_FILEID);
-	WRITE32(0);
+	if (readdir->bitmask[1] & FATTR4_WORD1_MOUNTED_ON_FILEID) {
+		WRITE32(0);
+		WRITE32(FATTR4_WORD1_MOUNTED_ON_FILEID);
+	} else {
+		WRITE32(FATTR4_WORD0_FILEID);
+		WRITE32(0);
+	}
 
 	/* set up reply kvec
 	 *    toplevel_status + taglen + rescount + OP_PUTFH + status
@@ -3175,7 +3180,7 @@
 		READ_BUF(4);
 		READ32(len);
 		READ_BUF(len);
-		return -EEXIST;
+		return -NFSERR_CLID_INUSE;
 	} else
 		return -nfs_stat_to_errno(nfserr);
 
@@ -3857,7 +3862,7 @@
 
 uint32_t *nfs4_decode_dirent(uint32_t *p, struct nfs_entry *entry, int plus)
 {
-	uint32_t bitmap[1] = {0};
+	uint32_t bitmap[2] = {0};
 	uint32_t len;
 
 	if (!*p++) {
@@ -3881,13 +3886,18 @@
 	entry->ino = 1;
 
 	len = ntohl(*p++);		/* bitmap length */
-	if (len > 0) {
-		bitmap[0] = ntohl(*p);
-		p += len;
+	if (len-- > 0) {
+		bitmap[0] = ntohl(*p++);
+		if (len-- > 0) {
+			bitmap[1] = ntohl(*p++);
+			p += len;
+		}
 	}
 	len = XDR_QUADLEN(ntohl(*p++));	/* attribute buffer length */
 	if (len > 0) {
-		if (bitmap[0] == FATTR4_WORD0_FILEID)
+		if (bitmap[0] == 0 && bitmap[1] == FATTR4_WORD1_MOUNTED_ON_FILEID)
+			xdr_decode_hyper(p, &entry->ino);
+		else if (bitmap[0] == FATTR4_WORD0_FILEID)
 			xdr_decode_hyper(p, &entry->ino);
 		p += len;
 	}
diff -Nru a/fs/nfs/nfsroot.c b/fs/nfs/nfsroot.c
--- a/fs/nfs/nfsroot.c	2005-03-11 12:51:47 -08:00
+++ b/fs/nfs/nfsroot.c	2005-03-11 12:51:47 -08:00
@@ -124,7 +124,6 @@
 	Opt_soft, Opt_hard, Opt_intr,
 	Opt_nointr, Opt_posix, Opt_noposix, Opt_cto, Opt_nocto, Opt_ac, 
 	Opt_noac, Opt_lock, Opt_nolock, Opt_v2, Opt_v3, Opt_udp, Opt_tcp,
-	Opt_broken_suid,
 	/* Error token */
 	Opt_err
 };
@@ -159,7 +158,6 @@
 	{Opt_udp, "udp"},
 	{Opt_tcp, "proto=tcp"},
 	{Opt_tcp, "tcp"},
-	{Opt_broken_suid, "broken_suid"},
 	{Opt_err, NULL}
 	
 };
@@ -268,9 +266,6 @@
 			case Opt_tcp:
 				nfs_data.flags |= NFS_MOUNT_TCP;
 				break;
-			case Opt_broken_suid:
-				nfs_data.flags |= NFS_MOUNT_BROKEN_SUID;
-				break;
 			default : 
 				return 0;
 		}
@@ -351,7 +346,7 @@
 #endif
 
 
-int __init root_nfs_init(void)
+static int __init root_nfs_init(void)
 {
 #ifdef NFSROOT_DEBUG
 	nfs_debug |= NFSDBG_ROOT;
@@ -379,15 +374,15 @@
  *  Parse NFS server and directory information passed on the kernel
  *  command line.
  */
-int __init nfs_root_setup(char *line)
+static int __init nfs_root_setup(char *line)
 {
 	ROOT_DEV = Root_NFS;
 	if (line[0] == '/' || line[0] == ',' || (line[0] >= '0' && line[0] <= '9')) {
 		strlcpy(nfs_root_name, line, sizeof(nfs_root_name));
 	} else {
-		int n = strlen(line) + strlen(NFS_ROOT);
+		int n = strlen(line) + sizeof(NFS_ROOT) - 1;
 		if (n >= sizeof(nfs_root_name))
-			line[sizeof(nfs_root_name) - strlen(NFS_ROOT) - 1] = '\0';
+			line[sizeof(nfs_root_name) - sizeof(NFS_ROOT) - 2] = '\0';
 		sprintf(nfs_root_name, NFS_ROOT, line);
 	}
 	root_server_addr = root_nfs_parse_addr(nfs_root_name);
diff -Nru a/fs/nfs/proc.c b/fs/nfs/proc.c
--- a/fs/nfs/proc.c	2005-03-11 12:51:51 -08:00
+++ b/fs/nfs/proc.c	2005-03-11 12:51:51 -08:00
@@ -212,7 +212,7 @@
 	return status < 0? status : wdata->res.count;
 }
 
-static struct inode *
+static int
 nfs_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
 		int flags)
 {
@@ -233,37 +233,34 @@
 	fattr.valid = 0;
 	dprintk("NFS call  create %s\n", dentry->d_name.name);
 	status = rpc_call(NFS_CLIENT(dir), NFSPROC_CREATE, &arg, &res, 0);
+	if (status == 0)
+		status = nfs_instantiate(dentry, &fhandle, &fattr);
 	dprintk("NFS reply create: %d\n", status);
-	if (status == 0) {
-		struct inode *inode;
-		inode = nfs_fhget(dir->i_sb, &fhandle, &fattr);
-		if (inode)
-			return inode;
-		status = -ENOMEM;
-	}
-	return ERR_PTR(status);
+	return status;
 }
 
 /*
  * In NFSv2, mknod is grafted onto the create call.
  */
 static int
-nfs_proc_mknod(struct inode *dir, struct qstr *name, struct iattr *sattr,
-	       dev_t rdev, struct nfs_fh *fhandle, struct nfs_fattr *fattr)
+nfs_proc_mknod(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
+	       dev_t rdev)
 {
+	struct nfs_fh fhandle;
+	struct nfs_fattr fattr;
 	struct nfs_createargs	arg = {
 		.fh		= NFS_FH(dir),
-		.name		= name->name,
-		.len		= name->len,
+		.name		= dentry->d_name.name,
+		.len		= dentry->d_name.len,
 		.sattr		= sattr
 	};
 	struct nfs_diropok	res = {
-		.fh		= fhandle,
-		.fattr		= fattr
+		.fh		= &fhandle,
+		.fattr		= &fattr
 	};
-	int			status, mode;
+	int status, mode;
 
-	dprintk("NFS call  mknod %s\n", name->name);
+	dprintk("NFS call  mknod %s\n", dentry->d_name.name);
 
 	mode = sattr->ia_mode;
 	if (S_ISFIFO(mode)) {
@@ -274,14 +271,16 @@
 		sattr->ia_size = new_encode_dev(rdev);/* get out your barf bag */
 	}
 
-	fattr->valid = 0;
+	fattr.valid = 0;
 	status = rpc_call(NFS_CLIENT(dir), NFSPROC_CREATE, &arg, &res, 0);
 
 	if (status == -EINVAL && S_ISFIFO(mode)) {
 		sattr->ia_mode = mode;
-		fattr->valid = 0;
+		fattr.valid = 0;
 		status = rpc_call(NFS_CLIENT(dir), NFSPROC_CREATE, &arg, &res, 0);
 	}
+	if (status == 0)
+		status = nfs_instantiate(dentry, &fhandle, &fattr);
 	dprintk("NFS reply mknod: %d\n", status);
 	return status;
 }
@@ -398,24 +397,27 @@
 }
 
 static int
-nfs_proc_mkdir(struct inode *dir, struct qstr *name, struct iattr *sattr,
-	       struct nfs_fh *fhandle, struct nfs_fattr *fattr)
+nfs_proc_mkdir(struct inode *dir, struct dentry *dentry, struct iattr *sattr)
 {
+	struct nfs_fh fhandle;
+	struct nfs_fattr fattr;
 	struct nfs_createargs	arg = {
 		.fh		= NFS_FH(dir),
-		.name		= name->name,
-		.len		= name->len,
+		.name		= dentry->d_name.name,
+		.len		= dentry->d_name.len,
 		.sattr		= sattr
 	};
 	struct nfs_diropok	res = {
-		.fh		= fhandle,
-		.fattr		= fattr
+		.fh		= &fhandle,
+		.fattr		= &fattr
 	};
 	int			status;
 
-	dprintk("NFS call  mkdir %s\n", name->name);
-	fattr->valid = 0;
+	dprintk("NFS call  mkdir %s\n", dentry->d_name.name);
+	fattr.valid = 0;
 	status = rpc_call(NFS_CLIENT(dir), NFSPROC_MKDIR, &arg, &res, 0);
+	if (status == 0)
+		status = nfs_instantiate(dentry, &fhandle, &fattr);
 	dprintk("NFS reply mkdir: %d\n", status);
 	return status;
 }
diff -Nru a/fs/nfs/read.c b/fs/nfs/read.c
--- a/fs/nfs/read.c	2005-03-11 12:51:40 -08:00
+++ b/fs/nfs/read.c	2005-03-11 12:51:40 -08:00
@@ -370,7 +370,7 @@
 	return -ENOMEM;
 }
 
-int
+static int
 nfs_pagein_list(struct list_head *head, int rpages)
 {
 	LIST_HEAD(one_request);
diff -Nru a/fs/nfs/unlink.c b/fs/nfs/unlink.c
--- a/fs/nfs/unlink.c	2005-03-11 12:51:51 -08:00
+++ b/fs/nfs/unlink.c	2005-03-11 12:51:51 -08:00
@@ -167,6 +167,11 @@
 		goto out;
 	memset(data, 0, sizeof(*data));
 
+	data->cred = rpcauth_lookupcred(clnt->cl_auth, 0);
+	if (IS_ERR(data->cred)) {
+		status = PTR_ERR(data->cred);
+		goto out_free;
+	}
 	data->dir = dget(dir);
 	data->dentry = dentry;
 
@@ -183,11 +188,13 @@
 	spin_lock(&dentry->d_lock);
 	dentry->d_flags |= DCACHE_NFSFS_RENAMED;
 	spin_unlock(&dentry->d_lock);
-	data->cred = rpcauth_lookupcred(clnt->cl_auth, 0);
 
 	rpc_sleep_on(&nfs_delete_queue, task, NULL, NULL);
 	status = 0;
  out:
+	return status;
+out_free:
+	kfree(data);
 	return status;
 }
 
diff -Nru a/fs/nfs/write.c b/fs/nfs/write.c
--- a/fs/nfs/write.c	2005-03-11 12:51:47 -08:00
+++ b/fs/nfs/write.c	2005-03-11 12:51:47 -08:00
@@ -80,14 +80,31 @@
 static void nfs_writeback_done_full(struct nfs_write_data *, int);
 static int nfs_wait_on_write_congestion(struct address_space *, int);
 static int nfs_wait_on_requests(struct inode *, unsigned long, unsigned int);
+static int nfs_flush_inode(struct inode *inode, unsigned long idx_start,
+			   unsigned int npages, int how);
 
 static kmem_cache_t *nfs_wdata_cachep;
 mempool_t *nfs_wdata_mempool;
-mempool_t *nfs_commit_mempool;
+static mempool_t *nfs_commit_mempool;
 
 static DECLARE_WAIT_QUEUE_HEAD(nfs_write_congestion);
 
-void nfs_writedata_release(struct rpc_task *task)
+static inline struct nfs_write_data *nfs_commit_alloc(void)
+{
+	struct nfs_write_data *p = mempool_alloc(nfs_commit_mempool, SLAB_NOFS);
+	if (p) {
+		memset(p, 0, sizeof(*p));
+		INIT_LIST_HEAD(&p->pages);
+	}
+	return p;
+}
+
+static inline void nfs_commit_free(struct nfs_write_data *p)
+{
+	mempool_free(p, nfs_commit_mempool);
+}
+
+static void nfs_writedata_release(struct rpc_task *task)
 {
 	struct nfs_write_data	*wdata = (struct nfs_write_data *)task->tk_calldata;
 	nfs_writedata_free(wdata);
@@ -990,7 +1007,7 @@
 	return -ENOMEM;
 }
 
-int
+static int
 nfs_flush_list(struct list_head *head, int wpages, int how)
 {
 	LIST_HEAD(one_request);
@@ -1240,7 +1257,7 @@
 /*
  * Commit dirty pages
  */
-int
+static int
 nfs_commit_list(struct list_head *head, int how)
 {
 	struct nfs_write_data	*data;
@@ -1314,8 +1331,8 @@
 }
 #endif
 
-int nfs_flush_inode(struct inode *inode, unsigned long idx_start,
-		   unsigned int npages, int how)
+static int nfs_flush_inode(struct inode *inode, unsigned long idx_start,
+			   unsigned int npages, int how)
 {
 	struct nfs_inode *nfsi = NFS_I(inode);
 	LIST_HEAD(head);
diff -Nru a/fs/nfsd/export.c b/fs/nfsd/export.c
--- a/fs/nfsd/export.c	2005-03-11 12:51:47 -08:00
+++ b/fs/nfsd/export.c	2005-03-11 12:51:47 -08:00
@@ -79,9 +79,9 @@
 	}
 }
 
-void expkey_request(struct cache_detail *cd,
-		    struct cache_head *h,
-		    char **bpp, int *blen)
+static void expkey_request(struct cache_detail *cd,
+			   struct cache_head *h,
+			   char **bpp, int *blen)
 {
 	/* client fsidtype \xfsid */
 	struct svc_expkey *ek = container_of(h, struct svc_expkey, h);
@@ -95,7 +95,7 @@
 }
 
 static struct svc_expkey *svc_expkey_lookup(struct svc_expkey *, int);
-int expkey_parse(struct cache_detail *cd, char *mesg, int mlen)
+static int expkey_parse(struct cache_detail *cd, char *mesg, int mlen)
 {
 	/* client fsidtype fsid [path] */
 	char *buf;
@@ -284,9 +284,9 @@
 	}
 }
 
-void svc_export_request(struct cache_detail *cd,
-			struct cache_head *h,
-			char **bpp, int *blen)
+static void svc_export_request(struct cache_detail *cd,
+			       struct cache_head *h,
+			       char **bpp, int *blen)
 {
 	/*  client path */
 	struct svc_export *exp = container_of(h, struct svc_export, h);
@@ -340,7 +340,7 @@
 
 }
 
-int svc_export_parse(struct cache_detail *cd, char *mesg, int mlen)
+static int svc_export_parse(struct cache_detail *cd, char *mesg, int mlen)
 {
 	/* client path expiry [flags anonuid anongid fsid] */
 	char *buf;
@@ -510,8 +510,8 @@
 	return ek;
 }
 
-int exp_set_key(svc_client *clp, int fsid_type, u32 *fsidv, 
-		struct svc_export *exp)
+static int exp_set_key(svc_client *clp, int fsid_type, u32 *fsidv,
+		       struct svc_export *exp)
 {
 	struct svc_expkey key, *ek;
 
@@ -999,7 +999,7 @@
 	exp_readunlock();
 }
 
-struct flags {
+static struct flags {
 	int flag;
 	char *name[2];
 } expflags[] = {
diff -Nru a/fs/nfsd/lockd.c b/fs/nfsd/lockd.c
--- a/fs/nfsd/lockd.c	2005-03-11 12:51:50 -08:00
+++ b/fs/nfsd/lockd.c	2005-03-11 12:51:50 -08:00
@@ -60,7 +60,7 @@
 	fput(filp);
 }
 
-struct nlmsvc_binding		nfsd_nlm_ops = {
+static struct nlmsvc_binding	nfsd_nlm_ops = {
 	.fopen		= nlm_fopen,		/* open file for locking */
 	.fclose		= nlm_fclose,		/* close file */
 };
diff -Nru a/fs/nfsd/nfs3proc.c b/fs/nfsd/nfs3proc.c
--- a/fs/nfsd/nfs3proc.c	2005-03-11 12:51:52 -08:00
+++ b/fs/nfsd/nfs3proc.c	2005-03-11 12:51:52 -08:00
@@ -171,7 +171,7 @@
 	svc_reserve(rqstp, ((1 + NFS3_POST_OP_ATTR_WORDS + 3)<<2) + resp->count +4);
 
 	fh_copy(&resp->fh, &argp->fh);
-	nfserr = nfsd_read(rqstp, &resp->fh,
+	nfserr = nfsd_read(rqstp, &resp->fh, NULL,
 				  argp->offset,
 			   	  argp->vec, argp->vlen,
 				  &resp->count);
@@ -201,7 +201,7 @@
 
 	fh_copy(&resp->fh, &argp->fh);
 	resp->committed = argp->stable;
-	nfserr = nfsd_write(rqstp, &resp->fh,
+	nfserr = nfsd_write(rqstp, &resp->fh, NULL,
 				   argp->offset,
 				   argp->vec, argp->vlen,
 				   argp->len,
diff -Nru a/fs/nfsd/nfs3xdr.c b/fs/nfsd/nfs3xdr.c
--- a/fs/nfsd/nfs3xdr.c	2005-03-11 12:51:40 -08:00
+++ b/fs/nfsd/nfs3xdr.c	2005-03-11 12:51:40 -08:00
@@ -801,6 +801,11 @@
 	if (isdotent(name, namlen)) {
 		if (namlen == 2) {
 			dchild = dget_parent(dparent);
+			if (dchild == dparent) {
+				/* filesystem root - cannot return filehandle for ".." */
+				dput(dchild);
+				return 1;
+			}
 		} else
 			dchild = dget(dparent);
 	} else
diff -Nru a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
--- a/fs/nfsd/nfs4callback.c	2005-03-11 12:51:52 -08:00
+++ b/fs/nfsd/nfs4callback.c	2005-03-11 12:51:52 -08:00
@@ -38,6 +38,7 @@
 #include <linux/list.h>
 #include <linux/inet.h>
 #include <linux/errno.h>
+#include <linux/delay.h>
 #include <linux/sunrpc/xdr.h>
 #include <linux/sunrpc/svc.h>
 #include <linux/sunrpc/clnt.h>
@@ -246,6 +247,7 @@
 {
 	struct xdr_stream xdr;
 	struct nfs4_cb_compound_hdr hdr = {
+		.ident = args->cbr_ident,
 		.nops   = 1,
 	};
 
@@ -308,7 +310,7 @@
 	if (status)
 		goto out;
 	status = decode_cb_op_hdr(&xdr, OP_CB_RECALL);
-out	:
+out:
 	return status;
 }
 
@@ -351,10 +353,8 @@
 {
         struct auth_cred acred;
 	struct rpc_clnt *clnt = clp->cl_callback.cb_client;
-        struct rpc_cred *ret = NULL;
+	struct rpc_cred *ret;
 
-	if (!clnt)
-		goto out;
         get_group_info(clp->cl_cred.cr_group_info);
         acred.uid = clp->cl_cred.cr_uid;
         acred.gid = clp->cl_cred.cr_gid;
@@ -364,7 +364,6 @@
                 clnt->cl_auth->au_ops->au_name);
         ret = rpcauth_lookup_credcache(clnt->cl_auth, &acred, taskflags);
         put_group_info(clp->cl_cred.cr_group_info);
-out:
         return ret;
 }
 
@@ -401,7 +400,7 @@
 
 	/* Initialize timeout */
 	timeparms.to_initval = (NFSD_LEASE_TIME/4) * HZ;
-	timeparms.to_retries = 5;
+	timeparms.to_retries = 0;
 	timeparms.to_maxval = (NFSD_LEASE_TIME/2) * HZ;
 	timeparms.to_exponential = 1;
 
@@ -431,10 +430,9 @@
 		dprintk("NFSD: couldn't create callback client\n");
 		goto out_xprt;
 	}
-	clnt->cl_intr = 1;
+	clnt->cl_intr = 0;
 	clnt->cl_softrtry = 1;
 	clnt->cl_chatty = 1;
-	cb->cb_client = clnt;
 
 	/* Kick rpciod, put the call on the wire. */
 
@@ -444,10 +442,14 @@
 	}
 
 	/* the task holds a reference to the nfs4_client struct */
+	cb->cb_client = clnt;
 	atomic_inc(&clp->cl_count);
 
 	msg.rpc_cred = nfsd4_lookupcred(clp,0);
+	if (IS_ERR(msg.rpc_cred))
+		goto out_rpciod;
 	status = rpc_call_async(clnt, &msg, RPC_TASK_ASYNC, nfs4_cb_null, NULL);
+	put_rpccred(msg.rpc_cred);
 
 	if (status != 0) {
 		dprintk("NFSD: asynchronous NFSPROC4_CB_NULL failed!\n");
@@ -456,6 +458,7 @@
 	return;
 
 out_rpciod:
+	atomic_dec(&clp->cl_count);
 	rpciod_down();
 out_clnt:
 	rpc_shutdown_client(clnt);
@@ -489,95 +492,56 @@
 }
 
 /*
- *  Called with dp->dl_count incremented
- */
-static void
-nfs4_cb_recall_done(struct rpc_task *task)
-{
-	struct nfs4_cb_recall *cbr = (struct nfs4_cb_recall *)task->tk_calldata;
-	struct nfs4_delegation *dp = cbr->cbr_dp;
-	int status;
-
-	/* all is well... */
-	if (task->tk_status == 0)
-		goto out;
-
-	/* network partition, retry nfsd4_cb_recall once.  */
-	if (task->tk_status == -EIO) {
-		if (atomic_read(&dp->dl_recall_cnt) == 0)
-			goto retry;
-		else
-			/* callback channel no longer available */
-			atomic_set(&dp->dl_client->cl_callback.cb_set, 0);
-	}
-
-	/* Race: a recall occurred miliseconds after a delegation was granted.
-	* Client may have received recall prior to delegation. retry recall
-	* once.
-	*/
-	if ((task->tk_status == -EBADHANDLE) || (task->tk_status == -NFS4ERR_BAD_STATEID)){
-		if (atomic_read(&dp->dl_recall_cnt) == 0)
-			goto retry;
-	}
-	atomic_set(&dp->dl_state, NFS4_RECALL_COMPLETE);
-
-out:
-	if (atomic_dec_and_test(&dp->dl_count))
-		atomic_set(&dp->dl_state, NFS4_REAP_DELEG);
-	BUG_ON(atomic_read(&dp->dl_count) < 0);
-	dprintk("NFSD: nfs4_cb_recall_done: dp %p dl_flock %p dl_count %d\n",dp, dp->dl_flock, atomic_read(&dp->dl_count));
-	return;
-
-retry:
-	atomic_inc(&dp->dl_recall_cnt);
-	/* sleep 2 seconds before retrying recall */
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	schedule_timeout(2*HZ);
-	status = nfsd4_cb_recall(dp);
-	dprintk("NFSD: nfs4_cb_recall_done: retry status: %d  dp %p dl_flock %p\n",status,dp, dp->dl_flock);
-}
-
-/*
  * called with dp->dl_count inc'ed.
  * nfs4_lock_state() may or may not have been called.
  */
-int
+void
 nfsd4_cb_recall(struct nfs4_delegation *dp)
 {
-	struct nfs4_client *clp;
-	struct rpc_clnt *clnt;
+	struct nfs4_client *clp = dp->dl_client;
+	struct rpc_clnt *clnt = clp->cl_callback.cb_client;
+	struct nfs4_cb_recall *cbr = &dp->dl_recall;
 	struct rpc_message msg = {
 		.rpc_proc = &nfs4_cb_procedures[NFSPROC4_CLNT_CB_RECALL],
+		.rpc_argp = cbr,
 	};
-	struct nfs4_cb_recall *cbr = &dp->dl_recall;
-	int status;
+	int retries = 1;
+	int status = 0;
 
-	dprintk("NFSD: nfsd4_cb_recall NFS4_enc_cb_recall_sz %d NFS4_dec_cb_recall_sz %d \n",NFS4_enc_cb_recall_sz,NFS4_dec_cb_recall_sz);
-
-	clp = dp->dl_client;
-	clnt = clp->cl_callback.cb_client;
-	status = EIO;
 	if ((!atomic_read(&clp->cl_callback.cb_set)) || !clnt)
-		goto out_free;
+		return;
 
-	msg.rpc_argp = cbr;
-	msg.rpc_resp = cbr;
-	msg.rpc_cred = nfsd4_lookupcred(clp,0);
+	msg.rpc_cred = nfsd4_lookupcred(clp, 0);
+	if (IS_ERR(msg.rpc_cred))
+		goto out;
 
 	cbr->cbr_trunc = 0; /* XXX need to implement truncate optimization */
 	cbr->cbr_dp = dp;
 
-	if ((status = rpc_call_async(clnt, &msg, RPC_TASK_SOFT,
-		nfs4_cb_recall_done, cbr ))) {
-		dprintk("NFSD: recall_delegation: rpc_call_async failed %d\n",
-			status);
-		goto out_fail;
+	status = rpc_call_sync(clnt, &msg, RPC_TASK_SOFT);
+	while (retries--) {
+		switch (status) {
+			case -EIO:
+				/* Network partition? */
+			case -EBADHANDLE:
+			case -NFS4ERR_BAD_STATEID:
+				/* Race: client probably got cb_recall
+				 * before open reply granting delegation */
+				break;
+			default:
+				goto out_put_cred;
+		}
+		ssleep(2);
+		status = rpc_call_sync(clnt, &msg, RPC_TASK_SOFT);
 	}
+out_put_cred:
+	put_rpccred(msg.rpc_cred);
 out:
-	return status;
-out_fail:
-	status = nfserrno(status);
-	out_free:
-	kfree(cbr);
-	goto out;
+	if (status == -EIO)
+		atomic_set(&clp->cl_callback.cb_set, 0);
+	/* Success or failure, now we're either waiting for lease expiration
+	 * or deleg_return. */
+	nfs4_put_delegation(dp);
+	dprintk("NFSD: nfs4_cb_recall: dp %p dl_flock %p dl_count %d\n",dp, dp->dl_flock, atomic_read(&dp->dl_count));
+	return;
 }
diff -Nru a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
--- a/fs/nfsd/nfs4proc.c	2005-03-11 12:51:52 -08:00
+++ b/fs/nfsd/nfs4proc.c	2005-03-11 12:51:52 -08:00
@@ -117,7 +117,6 @@
 
 		/* set reply cache */
 		fh_dup2(current_fh, &resfh);
-		/* XXXJBF: keep a saved svc_fh struct instead?? */
 		open->op_stateowner->so_replay.rp_openfh_len =
 			resfh.fh_handle.fh_size;
 		memcpy(open->op_stateowner->so_replay.rp_openfh,
@@ -153,7 +152,7 @@
 		current_fh->fh_handle.fh_size);
 
 	open->op_truncate = (open->op_iattr.ia_valid & ATTR_SIZE) &&
-	!open->op_iattr.ia_size;
+		(open->op_iattr.ia_size == 0);
 
 	status = do_open_permission(rqstp, current_fh, open);
 
@@ -464,37 +463,17 @@
 nfsd4_read(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_read *read)
 {
 	int status;
+	struct file *filp = NULL;
 
 	/* no need to check permission - this will be done in nfsd_read() */
-	if (nfs4_in_grace())
-		return nfserr_grace;
 
 	if (read->rd_offset >= OFFSET_MAX)
 		return nfserr_inval;
 
 	nfs4_lock_state();
-	status = nfs_ok;
-	/* For stateid -1, we don't check share reservations.  */
-	if (ONE_STATEID(&read->rd_stateid)) {
-		dprintk("NFSD: nfsd4_read: -1 stateid...\n");
-		goto out;
-	}
-	/*
-	* For stateid 0, the client doesn't have to have the file open, but
-	* we still check for share reservation conflicts. 
-	*/
-	if (ZERO_STATEID(&read->rd_stateid)) {
-		dprintk("NFSD: nfsd4_read: zero stateid...\n");
-		if ((status = nfs4_share_conflict(current_fh, NFS4_SHARE_DENY_READ))) {
-			dprintk("NFSD: nfsd4_read: conflicting share reservation!\n");
-			goto out;
-		}
-		status = nfs_ok;
-		goto out;
-	}
 	/* check stateid */
-	if ((status = nfs4_preprocess_stateid_op(current_fh, &read->rd_stateid, 
-					CHECK_FH | RD_STATE))) {
+	if ((status = nfs4_preprocess_stateid_op(current_fh, &read->rd_stateid,
+					CHECK_FH | RD_STATE, &filp))) {
 		dprintk("NFSD: nfsd4_read: couldn't process stateid!\n");
 		goto out;
 	}
@@ -503,6 +482,7 @@
 	nfs4_unlock_state();
 	read->rd_rqstp = rqstp;
 	read->rd_fhp = current_fh;
+	read->rd_filp = filp;
 	return status;
 }
 
@@ -587,25 +567,15 @@
 {
 	int status = nfs_ok;
 
-	if (nfs4_in_grace())
-		return nfserr_grace;
-
 	if (!current_fh->fh_dentry)
 		return nfserr_nofilehandle;
 
 	status = nfs_ok;
 	if (setattr->sa_iattr.ia_valid & ATTR_SIZE) {
-
-		status = nfserr_bad_stateid;
-		if (ZERO_STATEID(&setattr->sa_stateid) || ONE_STATEID(&setattr->sa_stateid)) {
-			dprintk("NFSD: nfsd4_setattr: magic stateid!\n");
-			goto out;
-		}
-
 		nfs4_lock_state();
 		if ((status = nfs4_preprocess_stateid_op(current_fh, 
 						&setattr->sa_stateid, 
-						CHECK_FH | WR_STATE))) {
+						CHECK_FH | WR_STATE, NULL))) {
 			dprintk("NFSD: nfsd4_setattr: couldn't process stateid!\n");
 			goto out_unlock;
 		}
@@ -629,44 +599,33 @@
 nfsd4_write(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_write *write)
 {
 	stateid_t *stateid = &write->wr_stateid;
+	struct file *filp = NULL;
 	u32 *p;
 	int status = nfs_ok;
 
-	if (nfs4_in_grace())
-		return nfserr_grace;
-
 	/* no need to check permission - this will be done in nfsd_write() */
 
 	if (write->wr_offset >= OFFSET_MAX)
 		return nfserr_inval;
 
 	nfs4_lock_state();
-	if (ZERO_STATEID(stateid) || ONE_STATEID(stateid)) {
-		dprintk("NFSD: nfsd4_write: zero stateid...\n");
-		if ((status = nfs4_share_conflict(current_fh, NFS4_SHARE_DENY_WRITE))) {
-			dprintk("NFSD: nfsd4_write: conflicting share reservation!\n");
-			goto out;
-		}
-		goto zero_stateid;
-	}
 	if ((status = nfs4_preprocess_stateid_op(current_fh, stateid, 
-					CHECK_FH | WR_STATE))) {
+					CHECK_FH | WR_STATE, &filp))) {
 		dprintk("NFSD: nfsd4_write: couldn't process stateid!\n");
 		goto out;
 	}
-
-zero_stateid:
-
 	nfs4_unlock_state();
+
 	write->wr_bytes_written = write->wr_buflen;
 	write->wr_how_written = write->wr_stable_how;
 	p = (u32 *)write->wr_verifier.data;
 	*p++ = nfssvc_boot.tv_sec;
 	*p++ = nfssvc_boot.tv_usec;
 
-	status =  nfsd_write(rqstp, current_fh, write->wr_offset,
-			  write->wr_vec, write->wr_vlen, write->wr_buflen,
-			  &write->wr_how_written);
+	status =  nfsd_write(rqstp, current_fh, filp, write->wr_offset,
+			write->wr_vec, write->wr_vlen, write->wr_buflen,
+			&write->wr_how_written);
+
 	if (status == nfserr_symlink)
 		status = nfserr_inval;
 	return status;
diff -Nru a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
--- a/fs/nfsd/nfs4state.c	2005-03-11 12:51:47 -08:00
+++ b/fs/nfsd/nfs4state.c	2005-03-11 12:51:47 -08:00
@@ -72,19 +72,15 @@
 u32 del_perclient = 0;
 u32 alloc_file = 0;
 u32 free_file = 0;
-u32 alloc_sowner = 0;
-u32 free_sowner = 0;
 u32 vfsopen = 0;
 u32 vfsclose = 0;
-u32 alloc_lsowner= 0;
 u32 alloc_delegation= 0;
 u32 free_delegation= 0;
 
 /* forward declarations */
 struct nfs4_stateid * find_stateid(stateid_t *stid, int flags);
 static struct nfs4_delegation * find_delegation_stateid(struct inode *ino, stateid_t *stid);
-static void release_delegation(struct nfs4_delegation *dp);
-static void release_stateid_lockowner(struct nfs4_stateid *open_stp);
+static void release_stateid_lockowners(struct nfs4_stateid *open_stp);
 
 /* Locking:
  *
@@ -133,9 +129,11 @@
 static struct list_head del_recall_lru;
 
 static struct nfs4_delegation *
-alloc_init_deleg(struct nfs4_client *clp, struct nfs4_file *fp, struct svc_fh *current_fh, u32 type)
+alloc_init_deleg(struct nfs4_client *clp, struct nfs4_stateid *stp, struct svc_fh *current_fh, u32 type)
 {
 	struct nfs4_delegation *dp;
+	struct nfs4_file *fp = stp->st_file;
+	struct nfs4_callback *cb = &stp->st_stateowner->so_client->cl_callback;
 
 	dprintk("NFSD alloc_init_deleg\n");
 	if ((dp = kmalloc(sizeof(struct nfs4_delegation),
@@ -147,10 +145,11 @@
 	dp->dl_client = clp;
 	dp->dl_file = fp;
 	dp->dl_flock = NULL;
-	dp->dl_stp = NULL;
+	get_file(stp->st_vfs_file);
+	dp->dl_vfs_file = stp->st_vfs_file;
 	dp->dl_type = type;
 	dp->dl_recall.cbr_dp = NULL;
-	dp->dl_recall.cbr_ident = 0;
+	dp->dl_recall.cbr_ident = cb->cb_ident;
 	dp->dl_recall.cbr_trunc = 0;
 	dp->dl_stateid.si_boot = boot_time;
 	dp->dl_stateid.si_stateownerid = current_delegid++;
@@ -160,26 +159,21 @@
 	memcpy(dp->dl_fhval, &current_fh->fh_handle.fh_base,
 		        current_fh->fh_handle.fh_size);
 	dp->dl_time = 0;
-	atomic_set(&dp->dl_state, NFS4_NO_RECALL);
 	atomic_set(&dp->dl_count, 1);
-	atomic_set(&dp->dl_recall_cnt, 0);
 	list_add(&dp->dl_del_perfile, &fp->fi_del_perfile);
 	list_add(&dp->dl_del_perclnt, &clp->cl_del_perclnt);
 	alloc_delegation++;
 	return dp;
 }
 
-/*
- * Free the delegation structure.
- * Called with the recall_lock held.
- */
-static void
-nfs4_free_delegation(struct nfs4_delegation *dp)
+void
+nfs4_put_delegation(struct nfs4_delegation *dp)
 {
-	dprintk("NFSD: nfs4_free_delegation freeing dp %p\n",dp);
-	list_del(&dp->dl_recall_lru);
-	kfree(dp);
-	free_delegation++;
+	if (atomic_dec_and_test(&dp->dl_count)) {
+		dprintk("NFSD: freeing dp %p\n",dp);
+		kfree(dp);
+		free_delegation++;
+	}
 }
 
 /* release_delegation:
@@ -189,45 +183,33 @@
  * the i_flock list, eventually calling nfsd's lock_manager
  * fl_release_callback.
  *
- * call either:
- *   nfsd_close : if last close, locks_remove_flock calls lease_modify.
- *                otherwise, recalled state set to NFS4_RECALL_COMPLETE
- *                so that it will be reaped by the laundromat service.
- * or
- *   remove_lease (calls time_out_lease which calls lease_modify).
- *   and nfs4_free_delegation.
- *
- * Called with nfs_lock_state() held.
- * Called with the recall_lock held.
  */
 
 static void
+nfs4_close_delegation(struct nfs4_delegation *dp)
+{
+	struct file *filp = dp->dl_vfs_file;
+
+	dprintk("NFSD: close_delegation dp %p\n",dp);
+	dp->dl_vfs_file = NULL;
+	/* The following nfsd_close may not actually close the file,
+	 * but we want to remove the lease in any case. */
+	setlease(filp, F_UNLCK, &dp->dl_flock);
+	nfsd_close(filp);
+	vfsclose++;
+}
+
+/* Called under the state lock. */
+static void
 release_delegation(struct nfs4_delegation *dp)
 {
-	/* delayed nfsd_close */
-	if (dp->dl_stp) {
-		struct file *filp = dp->dl_stp->st_vfs_file;
-
-		dprintk("NFSD: release_delegation CLOSE\n");
-		release_stateid_lockowner(dp->dl_stp);
-		kfree(dp->dl_stp);
-		dp->dl_stp = NULL;
-		atomic_set(&dp->dl_state, NFS4_RECALL_COMPLETE);
-		nfsd_close(filp);
-		vfsclose++;
-	} else {
-		dprintk("NFSD: release_delegation remove lease dl_flock %p\n",
-			dp->dl_flock);
-		remove_lease(dp->dl_flock);
-		list_del_init(&dp->dl_del_perfile);
-		list_del_init(&dp->dl_del_perclnt);
-		/* dl_count > 0 => outstanding recall rpc */
-		dprintk("NFSD: release_delegation free deleg dl_count %d\n",
-			           atomic_read(&dp->dl_count));
-		if ((atomic_read(&dp->dl_state) == NFS4_REAP_DELEG)
-		     || atomic_dec_and_test(&dp->dl_count))
-			nfs4_free_delegation(dp);
-	}
+	list_del_init(&dp->dl_del_perfile);
+	list_del_init(&dp->dl_del_perclnt);
+	spin_lock(&recall_lock);
+	list_del_init(&dp->dl_recall_lru);
+	spin_unlock(&recall_lock);
+	nfs4_close_delegation(dp);
+	nfs4_put_delegation(dp);
 }
 
 /* 
@@ -260,7 +242,7 @@
  * for last close replay.
  */
 static struct list_head	reclaim_str_hashtbl[CLIENT_HASH_SIZE];
-static int reclaim_str_hashtbl_size;
+static int reclaim_str_hashtbl_size = 0;
 static struct list_head	conf_id_hashtbl[CLIENT_HASH_SIZE];
 static struct list_head	conf_str_hashtbl[CLIENT_HASH_SIZE];
 static struct list_head	unconf_str_hashtbl[CLIENT_HASH_SIZE];
@@ -339,6 +321,7 @@
 	struct nfs4_delegation *dp;
 	struct nfs4_callback *cb = &clp->cl_callback;
 	struct rpc_clnt *clnt = clp->cl_callback.cb_client;
+	struct list_head reaplist;
 
 	dprintk("NFSD: expire_client cl_count %d\n",
 	                    atomic_read(&clp->cl_count));
@@ -348,17 +331,22 @@
 		rpc_shutdown_client(clnt);
 		clnt = clp->cl_callback.cb_client = NULL;
 	}
+
+	INIT_LIST_HEAD(&reaplist);
 	spin_lock(&recall_lock);
 	while (!list_empty(&clp->cl_del_perclnt)) {
 		dp = list_entry(clp->cl_del_perclnt.next, struct nfs4_delegation, dl_del_perclnt);
-		dprintk("NFSD: expire client. dp %p, dl_state %d, fp %p\n",
-				dp, atomic_read(&dp->dl_state), dp->dl_flock);
-
-		/* force release of delegation. */
-		atomic_set(&dp->dl_state, NFS4_RECALL_COMPLETE);
-		release_delegation(dp);
+		dprintk("NFSD: expire client. dp %p, fp %p\n", dp,
+				dp->dl_flock);
+		list_del_init(&dp->dl_del_perclnt);
+		list_move(&dp->dl_recall_lru, &reaplist);
 	}
 	spin_unlock(&recall_lock);
+	while (!list_empty(&reaplist)) {
+		dp = list_entry(reaplist.next, struct nfs4_delegation, dl_recall_lru);
+		list_del_init(&dp->dl_recall_lru);
+		release_delegation(dp);
+	}
 	list_del(&clp->cl_idhash);
 	list_del(&clp->cl_strhash);
 	list_del(&clp->cl_lru);
@@ -474,8 +462,9 @@
 }
 
 void
-move_to_confirmed(struct nfs4_client *clp, unsigned int idhashval)
+move_to_confirmed(struct nfs4_client *clp)
 {
+	unsigned int idhashval = clientid_hashval(clp->cl_clientid.cl_id);
 	unsigned int strhashval;
 
 	dprintk("NFSD: move_to_confirm nfs4_client %p\n", clp);
@@ -488,6 +477,31 @@
 	renew_client(clp);
 }
 
+static struct nfs4_client *
+find_confirmed_client(clientid_t *clid)
+{
+	struct nfs4_client *clp;
+	unsigned int idhashval = clientid_hashval(clid->cl_id);
+
+	list_for_each_entry(clp, &conf_id_hashtbl[idhashval], cl_idhash) {
+		if (cmp_clid(&clp->cl_clientid, clid))
+			return clp;
+	}
+	return NULL;
+}
+
+static struct nfs4_client *
+find_unconfirmed_client(clientid_t *clid)
+{
+	struct nfs4_client *clp;
+	unsigned int idhashval = clientid_hashval(clid->cl_id);
+
+	list_for_each_entry(clp, &unconf_id_hashtbl[idhashval], cl_idhash) {
+		if (cmp_clid(&clp->cl_clientid, clid))
+			return clp;
+	}
+	return NULL;
+}
 
 /* a helper function for parse_callback */
 static int
@@ -796,7 +810,6 @@
 nfsd4_setclientid_confirm(struct svc_rqst *rqstp, struct nfsd4_setclientid_confirm *setclientid_confirm)
 {
 	u32 ip_addr = rqstp->rq_addr.sin_addr.s_addr;
-	unsigned int idhashval;
 	struct nfs4_client *clp, *conf = NULL, *unconf = NULL;
 	nfs4_verifier confirm = setclientid_confirm->sc_confirm; 
 	clientid_t * clid = &setclientid_confirm->sc_clientid;
@@ -809,12 +822,9 @@
 	 * We get here on a DRC miss.
 	 */
 
-	idhashval = clientid_hashval(clid->cl_id);
 	nfs4_lock_state();
-	list_for_each_entry(clp, &conf_id_hashtbl[idhashval], cl_idhash) {
-		if (!cmp_clid(&clp->cl_clientid, clid))
-			continue;
-
+	clp = find_confirmed_client(clid);
+	if (clp) {
 		status = nfserr_inval;
 		/* 
 		 * Found a record for this clientid. If the IP addresses
@@ -828,11 +838,9 @@
 			goto out;
 		}
 		conf = clp;
-		break;
 	}
-	list_for_each_entry(clp, &unconf_id_hashtbl[idhashval], cl_idhash) {
-		if (!cmp_clid(&clp->cl_clientid, clid))
-			continue;
+	clp = find_unconfirmed_client(clid);
+	if (clp) {
 		status = nfserr_inval;
 		if (clp->cl_addr != ip_addr) { 
 			printk("NFSD: setclientid: string in use by client"
@@ -841,7 +849,6 @@
 			goto out;
 		}
 		unconf = clp;
-		break;
 	}
 	/* CASE 1: 
 	* unconf record that matches input clientid and input confirm.
@@ -858,7 +865,7 @@
 		else {
 			expire_client(conf);
 			clp = unconf;
-			move_to_confirmed(unconf, idhashval);
+			move_to_confirmed(unconf);
 			status = nfs_ok;
 		}
 		goto out;
@@ -891,7 +898,7 @@
 		} else {
 			status = nfs_ok;
 			clp = unconf;
-			move_to_confirmed(unconf, idhashval);
+			move_to_confirmed(unconf);
 		}
 		goto out;
 	}
@@ -952,8 +959,11 @@
 
 /* OPEN Share state helper functions */
 static inline struct nfs4_file *
-alloc_init_file(unsigned int hashval, struct inode *ino) {
+alloc_init_file(struct inode *ino)
+{
 	struct nfs4_file *fp;
+	unsigned int hashval = file_hashval(ino);
+
 	if ((fp = kmalloc(sizeof(struct nfs4_file),GFP_KERNEL))) {
 		INIT_LIST_HEAD(&fp->fi_hash);
 		INIT_LIST_HEAD(&fp->fi_perfile);
@@ -985,15 +995,38 @@
 	}
 }
 
-/* should use a slab cache */
+kmem_cache_t *stateowner_slab = NULL;
+
+static int
+nfsd4_init_slabs(void)
+{
+	stateowner_slab = kmem_cache_create("nfsd4_stateowners",
+			sizeof(struct nfs4_stateowner), 0, 0, NULL, NULL);
+	if (stateowner_slab == NULL) {
+		dprintk("nfsd4: out of memory while initializing nfsv4\n");
+		return -ENOMEM;
+	}
+	return 0;
+}
+
+static void
+nfsd4_free_slabs(void)
+{
+	int status = 0;
+
+	if (stateowner_slab)
+		status = kmem_cache_destroy(stateowner_slab);
+	stateowner_slab = NULL;
+	BUG_ON(status);
+}
+
 void
 nfs4_free_stateowner(struct kref *kref)
 {
 	struct nfs4_stateowner *sop =
 		container_of(kref, struct nfs4_stateowner, so_ref);
 	kfree(sop->so_owner.data);
-	kfree(sop);
-	free_sowner++;
+	kmem_cache_free(stateowner_slab, sop);
 }
 
 static inline struct nfs4_stateowner *
@@ -1001,14 +1034,14 @@
 {
 	struct nfs4_stateowner *sop;
 
-	if ((sop = kmalloc(sizeof(struct nfs4_stateowner),GFP_KERNEL))) {
+	if ((sop = kmem_cache_alloc(stateowner_slab, GFP_KERNEL))) {
 		if ((sop->so_owner.data = kmalloc(owner->len, GFP_KERNEL))) {
 			memcpy(sop->so_owner.data, owner->data, owner->len);
 			sop->so_owner.len = owner->len;
 			kref_init(&sop->so_ref);
 			return sop;
 		} 
-		kfree(sop);
+		kmem_cache_free(stateowner_slab, sop);
 	}
 	return NULL;
 }
@@ -1042,12 +1075,11 @@
 	rp->rp_status = NFSERR_SERVERFAULT;
 	rp->rp_buflen = 0;
 	rp->rp_buf = rp->rp_ibuf;
-	alloc_sowner++;
 	return sop;
 }
 
 static void
-release_stateid_lockowner(struct nfs4_stateid *open_stp)
+release_stateid_lockowners(struct nfs4_stateid *open_stp)
 {
 	struct nfs4_stateowner *lock_sop;
 
@@ -1067,9 +1099,11 @@
 
 	list_del(&sop->so_idhash);
 	list_del(&sop->so_strhash);
-	list_del(&sop->so_perclient);
+	if (sop->so_is_open_owner) {
+		list_del(&sop->so_perclient);
+		del_perclient++;
+	}
 	list_del(&sop->so_perlockowner);
-	del_perclient++;
 	while (!list_empty(&sop->so_perfilestate)) {
 		stp = list_entry(sop->so_perfilestate.next, 
 			struct nfs4_stateid, st_perfilestate);
@@ -1112,37 +1146,22 @@
 	__set_bit(open->op_share_deny, &stp->st_deny_bmap);
 }
 
-/*
-* Because nfsd_close() can call locks_remove_flock() which removes leases,
-* delay nfsd_close() for delegations from the nfsd_open() clientid
-* until the delegation is reaped.
-*/
 static void
 release_stateid(struct nfs4_stateid *stp, int flags)
 {
-	struct nfs4_delegation *dp;
-	struct nfs4_file *fp = stp->st_file;
+	struct file *filp = stp->st_vfs_file;
 
 	list_del(&stp->st_hash);
 	list_del_perfile++;
 	list_del(&stp->st_perfile);
 	list_del(&stp->st_perfilestate);
-	if ((stp->st_vfs_set) && (flags & OPEN_STATE)) {
-		list_for_each_entry(dp, &fp->fi_del_perfile, dl_del_perfile) {
-			if(cmp_clid(&dp->dl_client->cl_clientid,
-			    &stp->st_stateowner->so_client->cl_clientid)) {
-				dp->dl_stp = stp;
-				return;
-			}
-		}
-		release_stateid_lockowner(stp);
-		nfsd_close(stp->st_vfs_file);
+	if (flags & OPEN_STATE) {
+		release_stateid_lockowners(stp);
+		stp->st_vfs_file = NULL;
+		nfsd_close(filp);
 		vfsclose++;
-	} else if ((stp->st_vfs_set) && (flags & LOCK_STATE)) {
-		struct file *filp = stp->st_vfs_file;
-
+	} else if (flags & LOCK_STATE)
 		locks_remove_posix(filp, (fl_owner_t) stp->st_stateowner);
-	}
 	kfree(stp);
 	stp = NULL;
 }
@@ -1167,8 +1186,7 @@
 }
 
 void
-release_state_owner(struct nfs4_stateid *stp, struct nfs4_stateowner **sopp,
-		int flag)
+release_state_owner(struct nfs4_stateid *stp, int flag)
 {
 	struct nfs4_stateowner *sop = stp->st_stateowner;
 	struct nfs4_file *fp = stp->st_file;
@@ -1195,49 +1213,30 @@
 	  (sop->so_client->cl_clientid.cl_id == clid->cl_id));
 }
 
-/* search ownerstr_hashtbl[] for owner */
-static int
-find_openstateowner_str(unsigned int hashval, struct nfsd4_open *open, struct nfs4_stateowner **op) {
-	struct nfs4_stateowner *local = NULL;
-
-	list_for_each_entry(local, &ownerstr_hashtbl[hashval], so_strhash) {
-		if (!cmp_owner_str(local, &open->op_owner, &open->op_clientid))
-			continue;
-		*op = local;
-		return(1);
-	}
-	return 0;
-}
-
-/* see if clientid is in confirmed hash table */
-static int
-verify_clientid(struct nfs4_client **client, clientid_t *clid) {
-
-	struct nfs4_client *clp;
-	unsigned int idhashval = clientid_hashval(clid->cl_id);
+static struct nfs4_stateowner *
+find_openstateowner_str(unsigned int hashval, struct nfsd4_open *open)
+{
+	struct nfs4_stateowner *so = NULL;
 
-	list_for_each_entry(clp, &conf_id_hashtbl[idhashval], cl_idhash) {
-		if (!cmp_clid(&clp->cl_clientid, clid))
-			continue;
-		*client = clp;
-		return 1;
+	list_for_each_entry(so, &ownerstr_hashtbl[hashval], so_strhash) {
+		if (cmp_owner_str(so, &open->op_owner, &open->op_clientid))
+			return so;
 	}
-	*client = NULL;
-	return 0;
+	return NULL;
 }
 
 /* search file_hashtbl[] for file */
-static int
-find_file(unsigned int hashval, struct inode *ino, struct nfs4_file **fp) {
-	struct nfs4_file *local = NULL;
+static struct nfs4_file *
+find_file(struct inode *ino)
+{
+	unsigned int hashval = file_hashval(ino);
+	struct nfs4_file *fp;
 
-	list_for_each_entry(local, &file_hashtbl[hashval], fi_hash) {
-		if (local->fi_inode == ino) {
-			*fp = local;
-			return(1);
-		}
+	list_for_each_entry(fp, &file_hashtbl[hashval], fi_hash) {
+		if (fp->fi_inode == ino)
+			return fp;
 	}
-	return 0;
+	return NULL;
 }
 
 #define TEST_ACCESS(x) ((x > 0 || x < 4)?1:0)
@@ -1284,14 +1283,13 @@
 nfs4_share_conflict(struct svc_fh *current_fh, unsigned int deny_type)
 {
 	struct inode *ino = current_fh->fh_dentry->d_inode;
-	unsigned int fi_hashval;
 	struct nfs4_file *fp;
 	struct nfs4_stateid *stp;
 
 	dprintk("NFSD: nfs4_share_conflict\n");
 
-	fi_hashval = file_hashval(ino);
-	if (find_file(fi_hashval, ino, &fp)) {
+	fp = find_file(ino);
+	if (fp) {
 	/* Search for conflicting share reservations */
 		list_for_each_entry(stp, &fp->fi_perfile, st_perfile) {
 			if (test_bit(deny_type, &stp->st_deny_bmap) ||
@@ -1321,7 +1319,6 @@
 
 	daemonize("nfsv4-recall");
 
-	atomic_inc(&dp->dl_count);
 	nfsd4_cb_recall(dp);
 	return 0;
 }
@@ -1330,8 +1327,9 @@
  * Spawn a thread to perform a recall on the delegation represented
  * by the lease (file_lock)
  *
- * Called from break_lease() with lock_kernel() held,
- *
+ * Called from break_lease() with lock_kernel() held.
+ * Note: we assume break_lease will only call this *once* for any given
+ * lease.
  */
 static
 void nfsd_break_deleg_cb(struct file_lock *fl)
@@ -1343,9 +1341,14 @@
 	if (!dp)
 		return;
 
-	/* schedule delegation for recall */
+	/* We're assuming the state code never drops its reference
+	 * without first removing the lease.  Since we're in this lease
+	 * callback (and since the lease code is serialized by the kernel
+	 * lock) we know the server hasn't removed the lease yet, we know
+	 * it's safe to take a reference: */
+	atomic_inc(&dp->dl_count);
+
 	spin_lock(&recall_lock);
-	atomic_set(&dp->dl_state, NFS4_RECALL_IN_PROGRESS);
 	list_add_tail(&dp->dl_recall_lru, &del_recall_lru);
 	spin_unlock(&recall_lock);
 
@@ -1362,6 +1365,7 @@
 		printk(KERN_INFO "NFSD: Callback thread failed for "
 			"for client (clientid %08x/%08x)\n",
 			clp->cl_clientid.cl_boot, clp->cl_clientid.cl_id);
+		nfs4_put_delegation(dp);
 	}
 }
 
@@ -1375,11 +1379,10 @@
 {
 	struct nfs4_delegation *dp = (struct nfs4_delegation *)fl->fl_owner;
 
-	dprintk("NFSD nfsd_release_deleg_cb: fl %p dp %p dl_count %d, dl_state %d\n", fl,dp, atomic_read(&dp->dl_count), atomic_read(&dp->dl_state));
+	dprintk("NFSD nfsd_release_deleg_cb: fl %p dp %p dl_count %d\n", fl,dp, atomic_read(&dp->dl_count));
 
 	if (!(fl->fl_flags & FL_LEASE) || !dp)
 		return;
-	atomic_set(&dp->dl_state,NFS4_RECALL_COMPLETE);
 	dp->dl_flock = NULL;
 }
 
@@ -1399,14 +1402,42 @@
 	dp->dl_flock = new;
 }
 
+/*
+ * Called from __setlease() with lock_kernel() held
+ */
+static
+int nfsd_same_client_deleg_cb(struct file_lock *onlist, struct file_lock *try)
+{
+	struct nfs4_delegation *onlistd =
+		(struct nfs4_delegation *)onlist->fl_owner;
+	struct nfs4_delegation *tryd =
+		(struct nfs4_delegation *)try->fl_owner;
+
+	if (onlist->fl_lmops != try->fl_lmops)
+		return 0;
+
+	return onlistd->dl_client == tryd->dl_client;
+}
+
+
+static
+int nfsd_change_deleg_cb(struct file_lock **onlist, int arg)
+{
+	if (arg & F_UNLCK)
+		return lease_modify(onlist, arg);
+	else
+		return -EAGAIN;
+}
+
 struct lock_manager_operations nfsd_lease_mng_ops = {
-        .fl_break = nfsd_break_deleg_cb,
-        .fl_release_private = nfsd_release_deleg_cb,
-        .fl_copy_lock = nfsd_copy_lock_deleg_cb,
+	.fl_break = nfsd_break_deleg_cb,
+	.fl_release_private = nfsd_release_deleg_cb,
+	.fl_copy_lock = nfsd_copy_lock_deleg_cb,
+	.fl_mylease = nfsd_same_client_deleg_cb,
+	.fl_change = nfsd_change_deleg_cb,
 };
 
 
-
 /*
  * nfsd4_process_open1()
  * 	lookup stateowner.
@@ -1436,65 +1467,60 @@
 	if (!check_name(open->op_owner))
 		goto out;
 
-	status = nfserr_stale_clientid;
 	if (STALE_CLIENTID(&open->op_clientid))
-		return status;
+		return nfserr_stale_clientid;
 
 	strhashval = ownerstr_hashval(clientid->cl_id, open->op_owner);
-	if (find_openstateowner_str(strhashval, open, &sop)) {
+	sop = find_openstateowner_str(strhashval, open);
+	if (sop) {
 		open->op_stateowner = sop;
 		/* check for replay */
 		if (open->op_seqid == sop->so_seqid){
-			if (!sop->so_replay.rp_buflen) {
-			/*
-			* The original OPEN failed in so spectacularly that we
-			* don't even have replay data saved!  Therefore, we
-			* have no choice but to continue processing
-			* this OPEN; presumably, we'll fail again for the same
-			* reason.
-			*/
-				dprintk("nfsd4_process_open1: replay with no replay cache\n");
-				status = NFS_OK;
+			if (sop->so_replay.rp_buflen)
+				return NFSERR_REPLAY_ME;
+			else {
+				/* The original OPEN failed so spectacularly
+				 * that we don't even have replay data saved!
+				 * Therefore, we have no choice but to continue
+				 * processing this OPEN; presumably, we'll
+				 * fail again for the same reason.
+				 */
+				dprintk("nfsd4_process_open1:"
+					" replay with no replay cache\n");
 				goto renew;
 			}
-			/* replay: indicate to calling function */
-			status = NFSERR_REPLAY_ME;
-			return status;
-		}
-		if (sop->so_confirmed) {
-			if (open->op_seqid == sop->so_seqid + 1) { 
-				status = nfs_ok;
+		} else if (sop->so_confirmed) {
+			if (open->op_seqid == sop->so_seqid + 1)
 				goto renew;
-			} 
 			status = nfserr_bad_seqid;
 			goto out;
+		} else {
+			/* If we get here, we received an OPEN for an
+			 * unconfirmed nfs4_stateowner. Since the seqid's are
+			 * different, purge the existing nfs4_stateowner, and
+			 * instantiate a new one.
+			 */
+			clp = sop->so_client;
+			release_stateowner(sop);
 		}
-		/* If we get here, we received and OPEN for an unconfirmed
-		 * nfs4_stateowner. 
-		 * Since the sequid's are different, purge the 
-		 * existing nfs4_stateowner, and instantiate a new one.
+	} else {
+		/* nfs4_stateowner not found.
+		 * Verify clientid and instantiate new nfs4_stateowner.
+		 * If verify fails this is presumably the result of the
+		 * client's lease expiring.
 		 */
-		clp = sop->so_client;
-		release_stateowner(sop);
-		goto instantiate_new_owner;
-	} 
-	/* nfs4_stateowner not found. 
-	* verify clientid and instantiate new nfs4_stateowner
-	* if verify fails this is presumably the result of the 
-	* client's lease expiring.
-	*
-	* XXX compare clp->cl_addr with rqstp addr? 
-	*/
-	status = nfserr_expired;
-	if (!verify_clientid(&clp, clientid))
-		goto out;
-instantiate_new_owner:
+		status = nfserr_expired;
+		clp = find_confirmed_client(clientid);
+		if (clp == NULL)
+			goto out;
+	}
 	status = nfserr_resource;
-	if (!(sop = alloc_init_open_stateowner(strhashval, clp, open))) 
+	sop = alloc_init_open_stateowner(strhashval, clp, open);
+	if (sop == NULL)
 		goto out;
 	open->op_stateowner = sop;
-	status = nfs_ok;
 renew:
+	status = nfs_ok;
 	renew_client(sop->so_client);
 out:
 	if (status && open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS)
@@ -1503,43 +1529,6 @@
 }
 
 static int
-nfs4_deleg_conflict(u32 share, u32 dtype)
-{
-	return (((share & NFS4_SHARE_ACCESS_WRITE) &&
-		dtype == NFS4_OPEN_DELEGATE_READ) ||
-		((share & NFS4_SHARE_ACCESS_READ) &&
-		dtype == NFS4_OPEN_DELEGATE_WRITE));
-}
-
-#define DONT_DELEGATE  8
-
-/*
- * nfs4_check_deleg_recall()
- *
- * Test any delegation that is currently within an incompleted recalled
- * state, and return NFSERR_DELAY for conflicting open share.
- * flag is set to DONT_DELEGATE for shares that match the deleg type.
- */
-static int
-nfs4_check_deleg_recall(struct nfs4_file *fp, struct nfsd4_open *op, int *flag)
-{
-	struct nfs4_delegation *dp;
-	int status = 0;
-
-	list_for_each_entry(dp, &fp->fi_del_perfile, dl_del_perfile) {
-		dprintk("NFSD: found delegation %p with dl_state %d\n",
-		 	                 dp, atomic_read(&dp->dl_state));
-		if (atomic_read(&dp->dl_state) == NFS4_RECALL_IN_PROGRESS) {
-			if(nfs4_deleg_conflict(op->op_share_access, dp->dl_type))
-				status = nfserr_jukebox;
-			else
-				*flag = DONT_DELEGATE;
-		}
-	}
-	return status;
-}
-
-static int
 nfs4_check_open(struct nfs4_file *fp, struct nfs4_stateowner *sop, struct nfsd4_open *open, struct nfs4_stateid **stpp)
 {
 	struct nfs4_stateid *local;
@@ -1582,7 +1571,6 @@
 		return status;
 	}
 	vfsopen++;
-	stp->st_vfs_set = 1;
 	*stpp = stp;
 	return 0;
 }
@@ -1644,33 +1632,29 @@
  * Attempt to hand out a delegation.
  */
 static void
-nfs4_open_delegation(struct svc_fh *fh, struct nfsd4_open *open, struct nfs4_stateid *stp, int *flag)
+nfs4_open_delegation(struct svc_fh *fh, struct nfsd4_open *open, struct nfs4_stateid *stp)
 {
 	struct nfs4_delegation *dp;
 	struct nfs4_stateowner *sop = stp->st_stateowner;
 	struct nfs4_callback *cb = &sop->so_client->cl_callback;
 	struct file_lock fl, *flp = &fl;
-	int status;
+	int status, flag = 0;
 
-	if (*flag == DONT_DELEGATE) {
-		*flag = NFS4_OPEN_DELEGATE_NONE;
-		return;
-	}
-
-	/* set flag */
-	*flag = NFS4_OPEN_DELEGATE_NONE;
+	flag = NFS4_OPEN_DELEGATE_NONE;
 	if (open->op_claim_type != NFS4_OPEN_CLAIM_NULL
 	     || !atomic_read(&cb->cb_set) || !sop->so_confirmed)
-		return;
-
-	if (!(open->op_share_access & NFS4_SHARE_ACCESS_WRITE))
-		*flag = NFS4_OPEN_DELEGATE_READ;
+		goto out;
 
-	else if (!(open->op_share_access & NFS4_SHARE_ACCESS_READ))
-		*flag = NFS4_OPEN_DELEGATE_WRITE;
+	if (open->op_share_access & NFS4_SHARE_ACCESS_WRITE)
+		flag = NFS4_OPEN_DELEGATE_WRITE;
+	else
+		flag = NFS4_OPEN_DELEGATE_READ;
 
-	if (!(dp = alloc_init_deleg(sop->so_client, stp->st_file, fh, *flag)))
-		return;
+	dp = alloc_init_deleg(sop->so_client, stp, fh, flag);
+	if (dp == NULL) {
+		flag = NFS4_OPEN_DELEGATE_NONE;
+		goto out;
+	}
 	locks_init_lock(&fl);
 	fl.fl_lmops = &nfsd_lease_mng_ops;
 	fl.fl_flags = FL_LEASE;
@@ -1679,15 +1663,18 @@
 	fl.fl_file = stp->st_vfs_file;
 	fl.fl_pid = current->tgid;
 
+	/* setlease checks to see if delegation should be handed out.
+	 * the lock_manager callbacks fl_mylease and fl_change are used
+	 */
 	if ((status = setlease(stp->st_vfs_file,
-		*flag == NFS4_OPEN_DELEGATE_READ? F_RDLCK: F_WRLCK, &flp))) {
+		flag == NFS4_OPEN_DELEGATE_READ? F_RDLCK: F_WRLCK, &flp))) {
 		dprintk("NFSD: setlease failed [%d], no delegation\n", status);
 		list_del(&dp->dl_del_perfile);
 		list_del(&dp->dl_del_perclnt);
-		kfree(dp);
+		nfs4_put_delegation(dp);
 		free_delegation++;
-		*flag = NFS4_OPEN_DELEGATE_NONE;
-		return;
+		flag = NFS4_OPEN_DELEGATE_NONE;
+		goto out;
 	}
 
 	memcpy(&open->op_delegate_stateid, &dp->dl_stateid, sizeof(dp->dl_stateid));
@@ -1697,6 +1684,8 @@
 	             dp->dl_stateid.si_stateownerid,
 	             dp->dl_stateid.si_fileid,
 	             dp->dl_stateid.si_generation);
+out:
+	open->op_delegate_type = flag;
 }
 
 /*
@@ -1708,9 +1697,8 @@
 	struct nfs4_stateowner *sop = open->op_stateowner;
 	struct nfs4_file *fp = NULL;
 	struct inode *ino = current_fh->fh_dentry->d_inode;
-	unsigned int fi_hashval;
 	struct nfs4_stateid *stp = NULL;
-	int status, delegflag = 0;
+	int status;
 
 	status = nfserr_inval;
 	if (!TEST_ACCESS(open->op_share_access) || !TEST_DENY(open->op_share_deny))
@@ -1720,15 +1708,14 @@
 	 * and check for delegations in the process of being recalled.
 	 * If not found, create the nfs4_file struct
 	 */
-	fi_hashval = file_hashval(ino);
-	if (find_file(fi_hashval, ino, &fp)) {
+	fp = find_file(ino);
+	if (fp) {
 		if ((status = nfs4_check_open(fp, sop, open, &stp)))
 			goto out;
-		if ((status = nfs4_check_deleg_recall(fp, open, &delegflag)))
-			goto out;
 	} else {
 		status = nfserr_resource;
-		if ((fp = alloc_init_file(fi_hashval, ino)) == NULL)
+		fp = alloc_init_file(ino);
+		if (fp == NULL)
 			goto out;
 	}
 
@@ -1770,8 +1757,7 @@
 	* Attempt to hand out a delegation. No error return, because the
 	* OPEN succeeds even if we fail.
 	*/
-	nfs4_open_delegation(current_fh, open, stp, &delegflag);
-	open->op_delegate_type = delegflag;
+	nfs4_open_delegation(current_fh, open, stp);
 
 	status = nfs_ok;
 
@@ -1780,7 +1766,7 @@
 	            stp->st_stateid.si_fileid, stp->st_stateid.si_generation);
 out:
 	/* take the opportunity to clean up unused state */
-	if (fp && list_empty(&fp->fi_perfile))
+	if (fp && list_empty(&fp->fi_perfile) && list_empty(&fp->fi_del_perfile))
 		release_file(fp);
 
 	/* CLAIM_PREVIOUS has different error returns */
@@ -1803,7 +1789,6 @@
 nfsd4_renew(clientid_t *clid)
 {
 	struct nfs4_client *clp;
-	unsigned int idhashval;
 	int status;
 
 	nfs4_lock_state();
@@ -1812,27 +1797,19 @@
 	status = nfserr_stale_clientid;
 	if (STALE_CLIENTID(clid))
 		goto out;
-	status = nfs_ok;
-	idhashval = clientid_hashval(clid->cl_id);
-	list_for_each_entry(clp, &conf_id_hashtbl[idhashval], cl_idhash) {
-		if (!cmp_clid(&clp->cl_clientid, clid))
-			continue;
-		renew_client(clp);
+	clp = find_confirmed_client(clid);
+	status = nfserr_expired;
+	if (clp == NULL) {
+		/* We assume the client took too long to RENEW. */
+		dprintk("nfsd4_renew: clientid not found!\n");
 		goto out;
 	}
-	list_for_each_entry(clp, &unconf_id_hashtbl[idhashval], cl_idhash) {
-		if (!cmp_clid(&clp->cl_clientid, clid))
-			continue;
-		renew_client(clp);
-	goto out;
-	}
-	/*
-	* Couldn't find an nfs4_client for this clientid.  
-	* Presumably this is because the client took too long to 
-	* RENEW, so return NFS4ERR_EXPIRED.
-	*/
-	dprintk("nfsd4_renew: clientid not found!\n");
-	status = nfserr_expired;
+	renew_client(clp);
+	status = nfserr_cb_path_down;
+	if (!list_empty(&clp->cl_del_perclnt)
+			&& !atomic_read(&clp->cl_callback.cb_set))
+		goto out;
+	status = nfs_ok;
 out:
 	nfs4_unlock_state();
 	return status;
@@ -1844,7 +1821,7 @@
 	struct nfs4_client *clp;
 	struct nfs4_stateowner *sop;
 	struct nfs4_delegation *dp;
-	struct list_head *pos, *next;
+	struct list_head *pos, *next, reaplist;
 	time_t cutoff = get_seconds() - NFSD_LEASE_TIME;
 	time_t t, clientid_val = NFSD_LEASE_TIME;
 	time_t u, test_val = NFSD_LEASE_TIME;
@@ -1864,23 +1841,26 @@
 			clp->cl_clientid.cl_id);
 		expire_client(clp);
 	}
+	INIT_LIST_HEAD(&reaplist);
 	spin_lock(&recall_lock);
 	list_for_each_safe(pos, next, &del_recall_lru) {
 		dp = list_entry (pos, struct nfs4_delegation, dl_recall_lru);
-		if (atomic_read(&dp->dl_state) == NFS4_RECALL_COMPLETE)
-			goto reap;
 		if (time_after((unsigned long)dp->dl_time, (unsigned long)cutoff)) {
 			u = dp->dl_time - cutoff;
 			if (test_val > u)
 				test_val = u;
 			break;
 		}
-reap:
 		dprintk("NFSD: purging unused delegation dp %p, fp %p\n",
 			            dp, dp->dl_flock);
-		release_delegation(dp);
+		list_move(&dp->dl_recall_lru, &reaplist);
 	}
 	spin_unlock(&recall_lock);
+	list_for_each_safe(pos, next, &reaplist) {
+		dp = list_entry (pos, struct nfs4_delegation, dl_recall_lru);
+		list_del_init(&dp->dl_recall_lru);
+		release_delegation(dp);
+	}
 	test_val = NFSD_LEASE_TIME;
 	list_for_each_safe(pos, next, &close_lru) {
 		sop = list_entry(pos, struct nfs4_stateowner, so_close_lru);
@@ -1931,8 +1911,7 @@
 static inline int
 nfs4_check_fh(struct svc_fh *fhp, struct nfs4_stateid *stp)
 {
-	return (stp->st_vfs_set == 0 ||
-		fhp->fh_dentry->d_inode != stp->st_vfs_file->f_dentry->d_inode);
+	return fhp->fh_dentry->d_inode != stp->st_vfs_file->f_dentry->d_inode;
 }
 
 static int
@@ -1974,34 +1953,69 @@
 	return status;
 }
 
-static int
+static inline int
 nfs4_check_delegmode(struct nfs4_delegation *dp, int flags)
 {
-	int status = nfserr_openmode;
+	if ((flags & WR_STATE) && (dp->dl_type == NFS4_OPEN_DELEGATE_READ))
+		return nfserr_openmode;
+	else
+		return nfs_ok;
+}
 
-	if ((flags & WR_STATE) & (dp->dl_type == NFS4_OPEN_DELEGATE_READ))
-		goto out;
-	if ((flags & RD_STATE) & (dp->dl_type == NFS4_OPEN_DELEGATE_WRITE))
-		goto out;
-	status = nfs_ok;
-out:
-	return status;
+static inline int
+check_special_stateids(svc_fh *current_fh, stateid_t *stateid, int flags)
+{
+	/* Trying to call delegreturn with a special stateid? Yuch: */
+	if (!(flags & (RD_STATE | WR_STATE)))
+		return nfserr_bad_stateid;
+	else if (ONE_STATEID(stateid) && (flags & RD_STATE))
+		return nfs_ok;
+	else if (nfs4_in_grace()) {
+		/* Answer in remaining cases depends on existance of
+		 * conflicting state; so we must wait out the grace period. */
+		return nfserr_grace;
+	} else if (flags & WR_STATE)
+		return nfs4_share_conflict(current_fh,
+				NFS4_SHARE_DENY_WRITE);
+	else /* (flags & RD_STATE) && ZERO_STATEID(stateid) */
+		return nfs4_share_conflict(current_fh,
+				NFS4_SHARE_DENY_READ);
+}
+
+/*
+ * Allow READ/WRITE during grace period on recovered state only for files
+ * that are not able to provide mandatory locking.
+ */
+static inline int
+io_during_grace_disallowed(struct inode *inode, int flags)
+{
+	return nfs4_in_grace() && (flags & (RD_STATE | WR_STATE))
+		&& MANDATORY_LOCK(inode);
 }
 
 /*
 * Checks for stateid operations
 */
 int
-nfs4_preprocess_stateid_op(struct svc_fh *current_fh, stateid_t *stateid, int flags)
+nfs4_preprocess_stateid_op(struct svc_fh *current_fh, stateid_t *stateid, int flags, struct file **filpp)
 {
 	struct nfs4_stateid *stp = NULL;
 	struct nfs4_delegation *dp = NULL;
 	stateid_t *stidp;
+	struct inode *ino = current_fh->fh_dentry->d_inode;
 	int status;
 
 	dprintk("NFSD: preprocess_stateid_op: stateid = (%08x/%08x/%08x/%08x)\n",
 		stateid->si_boot, stateid->si_stateownerid, 
 		stateid->si_fileid, stateid->si_generation); 
+	if (filpp)
+		*filpp = NULL;
+
+	if (io_during_grace_disallowed(ino, flags))
+		return nfserr_grace;
+
+	if (ZERO_STATEID(stateid) || ONE_STATEID(stateid))
+		return check_special_stateids(current_fh, stateid, flags);
 
 	/* STALE STATEID */
 	status = nfserr_stale_stateid;
@@ -2011,16 +2025,18 @@
 	/* BAD STATEID */
 	status = nfserr_bad_stateid;
 	if (!stateid->si_fileid) { /* delegation stateid */
-		struct inode *ino = current_fh->fh_dentry->d_inode;
-
 		if(!(dp = find_delegation_stateid(ino, stateid))) {
 			dprintk("NFSD: delegation stateid not found\n");
+			if (nfs4_in_grace())
+				status = nfserr_grace;
 			goto out;
 		}
 		stidp = &dp->dl_stateid;
 	} else { /* open or lock stateid */
 		if (!(stp = find_stateid(stateid, flags))) {
 			dprintk("NFSD: open or lock stateid not found\n");
+			if (nfs4_in_grace())
+				status = nfserr_grace;
 			goto out;
 		}
 		if ((flags & CHECK_FH) && nfs4_check_fh(current_fh, stp))
@@ -2040,16 +2056,16 @@
 		if ((status = nfs4_check_openmode(stp,flags)))
 			goto out;
 		renew_client(stp->st_stateowner->so_client);
+		if (filpp)
+			*filpp = stp->st_vfs_file;
 	} else if (dp) {
 		if ((status = nfs4_check_delegmode(dp, flags)))
 			goto out;
 		renew_client(dp->dl_client);
-		if (flags & DELEG_RET) {
-			atomic_set(&dp->dl_state,NFS4_RECALL_COMPLETE);
-			spin_lock(&recall_lock);
+		if (flags & DELEG_RET)
 			release_delegation(dp);
-			spin_unlock(&recall_lock);
-		}
+		if (filpp)
+			*filpp = dp->dl_vfs_file;
 	}
 	status = nfs_ok;
 out:
@@ -2117,7 +2133,6 @@
 
 	if ((flags & CHECK_FH) && nfs4_check_fh(current_fh, stp)) {
 		printk("NFSD: preprocess_seqid_op: fh-stateid mismatch!\n");
-		stp->st_vfs_set = 0;
 		goto out;
 	}
 
@@ -2188,17 +2203,6 @@
 	goto out;
 }
 
-/*
- * eventually, this will perform an upcall to the 'state daemon' as well as
- * set the cl_first_state field.
- */
-void
-first_state(struct nfs4_client *clp)
-{
-	if (!clp->cl_first_state)
-		clp->cl_first_state = get_seconds();
-}
-
 int
 nfsd4_open_confirm(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open_confirm *oc)
 {
@@ -2231,8 +2235,6 @@
 		         stp->st_stateid.si_stateownerid,
 		         stp->st_stateid.si_fileid,
 		         stp->st_stateid.si_generation);
-	status = nfs_ok;
-	first_state(sop->so_client);
 out:
 	if (oc->oc_stateowner)
 		nfs4_get_stateowner(oc->oc_stateowner);
@@ -2342,7 +2344,7 @@
 	memcpy(&close->cl_stateid, &stp->st_stateid, sizeof(stateid_t));
 
 	/* release_state_owner() calls nfsd_close() if needed */
-	release_state_owner(stp, &close->cl_stateowner, OPEN_STATE);
+	release_state_owner(stp, OPEN_STATE);
 out:
 	if (close->cl_stateowner)
 		nfs4_get_stateowner(close->cl_stateowner);
@@ -2359,7 +2361,7 @@
 		goto out;
 
 	nfs4_lock_state();
-	status = nfs4_preprocess_stateid_op(current_fh, &dr->dr_stateid, DELEG_RET);
+	status = nfs4_preprocess_stateid_op(current_fh, &dr->dr_stateid, DELEG_RET, NULL);
 	nfs4_unlock_state();
 out:
 	return status;
@@ -2376,8 +2378,15 @@
 
 #define lockownerid_hashval(id) \
         ((id) & LOCK_HASH_MASK)
-#define lock_ownerstr_hashval(x, clientid, ownername) \
-        ((file_hashval(x) + (clientid) + opaque_hashval((ownername.data), (ownername.len))) & LOCK_HASH_MASK)
+
+static inline unsigned int
+lock_ownerstr_hashval(struct inode *inode, u32 cl_id,
+		struct xdr_netobj *ownername)
+{
+	return (file_hashval(inode) + cl_id
+			+ opaque_hashval(ownername->data, ownername->len))
+		& LOCK_HASH_MASK;
+}
 
 static struct list_head lock_ownerid_hashtbl[LOCK_HASH_SIZE];
 static struct list_head	lock_ownerstr_hashtbl[LOCK_HASH_SIZE];
@@ -2418,17 +2427,14 @@
 	struct nfs4_delegation *dp = NULL;
 	struct nfs4_file *fp = NULL;
 	u32 st_id;
-	unsigned int fi_hashval;
 
 	dprintk("NFSD:find_delegation_stateid stateid=(%08x/%08x/%08x/%08x)\n",
                     stid->si_boot, stid->si_stateownerid,
                     stid->si_fileid, stid->si_generation);
 
-	if(!ino || !stid)
-		return NULL;
 	st_id = stid->si_stateownerid;
-	fi_hashval = file_hashval(ino);
-	if (find_file(fi_hashval, ino, &fp)) {
+	fp = find_file(ino);
+	if (fp) {
 		list_for_each_entry(dp, &fp->fi_del_perfile, dl_del_perfile) {
 			if(dp->dl_stateid.si_stateownerid == st_id) {
 				dprintk("NFSD: find_delegation dp %p\n",dp);
@@ -2512,18 +2518,18 @@
 	return NULL;
 }
 
-static int
-find_lockstateowner_str(unsigned int hashval, struct xdr_netobj *owner, clientid_t *clid, struct nfs4_stateowner **op) {
-	struct nfs4_stateowner *local = NULL;
+static struct nfs4_stateowner *
+find_lockstateowner_str(struct inode *inode, clientid_t *clid,
+		struct xdr_netobj *owner)
+{
+	unsigned int hashval = lock_ownerstr_hashval(inode, clid->cl_id, owner);
+	struct nfs4_stateowner *op;
 
-	list_for_each_entry(local, &lock_ownerstr_hashtbl[hashval], so_strhash) {
-		if (!cmp_owner_str(local, owner, clid))
-			continue;
-		*op = local;
-		return(1);
+	list_for_each_entry(op, &lock_ownerstr_hashtbl[hashval], so_strhash) {
+		if (cmp_owner_str(op, owner, clid))
+			return op;
 	}
-	*op = NULL;
-	return 0;
+	return NULL;
 }
 
 /*
@@ -2553,9 +2559,7 @@
 	sop->so_time = 0;
 	list_add(&sop->so_idhash, &lock_ownerid_hashtbl[idhashval]);
 	list_add(&sop->so_strhash, &lock_ownerstr_hashtbl[strhashval]);
-	list_add(&sop->so_perclient, &clp->cl_perclient);
 	list_add(&sop->so_perlockowner, &open_stp->st_perlockowner);
-	add_perclient++;
 	sop->so_is_open_owner = 0;
 	sop->so_id = current_ownerid++;
 	sop->so_client = clp;
@@ -2565,7 +2569,6 @@
 	rp->rp_status = NFSERR_SERVERFAULT;
 	rp->rp_buflen = 0;
 	rp->rp_buf = rp->rp_ibuf;
-	alloc_lsowner++;
 	return sop;
 }
 
@@ -2593,7 +2596,6 @@
 	stp->st_stateid.si_fileid = fp->fi_id;
 	stp->st_stateid.si_generation = 0;
 	stp->st_vfs_file = open_stp->st_vfs_file; /* FIXME refcount?? */
-	stp->st_vfs_set = open_stp->st_vfs_set;
 	stp->st_access_bmap = open_stp->st_access_bmap;
 	stp->st_deny_bmap = open_stp->st_deny_bmap;
 
@@ -2672,7 +2674,7 @@
 		fp = open_stp->st_file;
 		strhashval = lock_ownerstr_hashval(fp->fi_inode, 
 				open_sop->so_client->cl_clientid.cl_id, 
-				lock->v.new.owner);
+				&lock->v.new.owner);
 		/* 
 		 * If we already have this lock owner, the client is in 
 		 * error (or our bookeeping is wrong!) 
@@ -2785,7 +2787,7 @@
 		if (!seqid_mutating_err(status))
 			open_sop->so_seqid--;
 
-		release_state_owner(lock_stp, &lock->lk_stateowner, LOCK_STATE);
+		release_state_owner(lock_stp, LOCK_STATE);
 	}
 out:
 	if (lock->lk_stateowner)
@@ -2804,7 +2806,6 @@
 	struct file file;
 	struct file_lock file_lock;
 	struct file_lock *conflicting_lock;
-	unsigned int strhashval;
 	int status;
 
 	if (nfs4_in_grace())
@@ -2846,12 +2847,8 @@
 		goto out;
 	}
 
-	strhashval = lock_ownerstr_hashval(inode, 
-			lockt->lt_clientid.cl_id, lockt->lt_owner);
-
-	find_lockstateowner_str(strhashval, &lockt->lt_owner,
-					&lockt->lt_clientid, 
-					&lockt->lt_stateowner);
+	lockt->lt_stateowner = find_lockstateowner_str(inode,
+			&lockt->lt_clientid, &lockt->lt_owner);
 	if (lockt->lt_stateowner)
 		file_lock.fl_owner = (fl_owner_t)lockt->lt_stateowner;
 	file_lock.fl_pid = current->tgid;
@@ -3005,10 +3002,8 @@
 		status = nfserr_locks_held;
 		list_for_each_entry(stp, &local->so_perfilestate,
 				st_perfilestate) {
-			if (stp->st_vfs_set) {
-				if (check_for_locks(stp->st_vfs_file, local))
-					goto out;
-			}
+			if (check_for_locks(stp->st_vfs_file, local))
+				goto out;
 		}
 		/* no locks held by (lock) stateowner */
 		status = nfs_ok;
@@ -3039,21 +3034,21 @@
  * failure => all reset bets are off, nfserr_no_grace...
  */
 static int
-nfs4_client_to_reclaim(struct nfs4_client *clp)
+nfs4_client_to_reclaim(char *name, int namlen)
 {
 	unsigned int strhashval;
 	struct nfs4_client_reclaim *crp = NULL;
 
-	crp = alloc_reclaim(clp->cl_name.len);
+	dprintk("NFSD nfs4_client_to_reclaim NAME: %.*s\n", namlen, name);
+	crp = alloc_reclaim(namlen);
 	if (!crp)
 		return 0;
-	strhashval = clientstr_hashval(clp->cl_name.data, clp->cl_name.len);
+	strhashval = clientstr_hashval(name, namlen);
 	INIT_LIST_HEAD(&crp->cr_strhash);
 	list_add(&crp->cr_strhash, &reclaim_str_hashtbl[strhashval]);
-	memcpy(crp->cr_name.data, clp->cl_name.data, clp->cl_name.len);
-	crp->cr_name.len = clp->cl_name.len;
-	crp->cr_first_state = clp->cl_first_state;
-	crp->cr_expired = 0;
+	memcpy(crp->cr_name.data, name, namlen);
+	crp->cr_name.len = namlen;
+	reclaim_str_hashtbl_size++;
 	return 1;
 }
 
@@ -3082,27 +3077,23 @@
 struct nfs4_client_reclaim *
 nfs4_find_reclaim_client(clientid_t *clid)
 {
-	unsigned int idhashval = clientid_hashval(clid->cl_id);
 	unsigned int strhashval;
-	struct nfs4_client *clp, *client = NULL;
+	struct nfs4_client *clp;
 	struct nfs4_client_reclaim *crp = NULL;
 
 
 	/* find clientid in conf_id_hashtbl */
-	list_for_each_entry(clp, &conf_id_hashtbl[idhashval], cl_idhash) {
-		if (cmp_clid(&clp->cl_clientid, clid)) {
-			client = clp;
-			break;
-		}
-	}
-	if (!client)
+	clp = find_confirmed_client(clid);
+	if (clp == NULL)
 		return NULL;
 
+	dprintk("NFSD: nfs4_find_reclaim_client for %.*s\n",
+		            clp->cl_name.len, clp->cl_name.data);
+
 	/* find clp->cl_name in reclaim_str_hashtbl */
-	strhashval = clientstr_hashval(client->cl_name.data,
-	                              client->cl_name.len);
+	strhashval = clientstr_hashval(clp->cl_name.data, clp->cl_name.len);
 	list_for_each_entry(crp, &reclaim_str_hashtbl[strhashval], cr_strhash) {
-		if (cmp_name(&crp->cr_name, &client->cl_name)) {
+		if (cmp_name(&crp->cr_name, &clp->cl_name)) {
 			return crp;
 		}
 	}
@@ -3119,8 +3110,6 @@
 
 	if ((crp = nfs4_find_reclaim_client(clid)) == NULL)
 		return nfserr_reclaim_bad;
-	if (crp->cr_expired)
-		return nfserr_no_grace;
 	return nfs_ok;
 }
 
@@ -3129,14 +3118,12 @@
  * Start and stop routines
  */
 
-void 
-nfs4_state_init(void)
+static void
+__nfs4_state_init(void)
 {
 	int i;
 	time_t grace_time;
 
-	if (nfs4_init)
-		return;
 	if (!nfs4_reclaim_init) {
 		for (i = 0; i < CLIENT_HASH_SIZE; i++)
 			INIT_LIST_HEAD(&reclaim_str_hashtbl[i]);
@@ -3180,7 +3167,21 @@
 	grace_end = boot_time + grace_time;
 	INIT_WORK(&laundromat_work,laundromat_main, NULL);
 	schedule_delayed_work(&laundromat_work, NFSD_LEASE_TIME*HZ);
+}
+
+int
+nfs4_state_init(void)
+{
+	int status;
+
+	if (nfs4_init)
+		return 0;
+	status = nfsd4_init_slabs();
+	if (status)
+		return status;
+	__nfs4_state_init();
 	nfs4_init = 1;
+	return 0;
 }
 
 int
@@ -3208,7 +3209,14 @@
 	int i;
 	struct nfs4_client *clp = NULL;
 	struct nfs4_delegation *dp = NULL;
-	struct list_head *pos, *next;
+	struct nfs4_stateowner *sop = NULL;
+	struct list_head *pos, *next, reaplist;
+
+	list_for_each_safe(pos, next, &close_lru) {
+		sop = list_entry(pos, struct nfs4_stateowner, so_close_lru);
+		list_del(&sop->so_close_lru);
+		nfs4_put_stateowner(sop);
+	}
 
 	for (i = 0; i < CLIENT_HASH_SIZE; i++) {
 		while (!list_empty(&conf_id_hashtbl[i])) {
@@ -3220,13 +3228,18 @@
 			expire_client(clp);
 		}
 	}
+	INIT_LIST_HEAD(&reaplist);
 	spin_lock(&recall_lock);
 	list_for_each_safe(pos, next, &del_recall_lru) {
 		dp = list_entry (pos, struct nfs4_delegation, dl_recall_lru);
-		atomic_set(&dp->dl_state, NFS4_RECALL_COMPLETE);
-		release_delegation(dp);
+		list_move(&dp->dl_recall_lru, &reaplist);
 	}
 	spin_unlock(&recall_lock);
+	list_for_each_safe(pos, next, &reaplist) {
+		dp = list_entry (pos, struct nfs4_delegation, dl_recall_lru);
+		list_del_init(&dp->dl_recall_lru);
+		release_delegation(dp);
+	}
 
 	release_all_files();
 	cancel_delayed_work(&laundromat_work);
@@ -3238,8 +3251,6 @@
 			add_perclient, del_perclient);
 	dprintk("NFSD: alloc_file %d free_file %d\n",
 			alloc_file, free_file);
-	dprintk("NFSD: alloc_sowner %d alloc_lsowner %d free_sowner %d\n",
-			alloc_sowner, alloc_lsowner, free_sowner);
 	dprintk("NFSD: vfsopen %d vfsclose %d\n",
 			vfsopen, vfsclose);
 	dprintk("NFSD: alloc_delegation %d free_delegation %d\n",
@@ -3253,6 +3264,7 @@
 	nfs4_lock_state();
 	nfs4_release_reclaim();
 	__nfs4_state_shutdown();
+	nfsd4_free_slabs();
 	nfs4_unlock_state();
 }
 
@@ -3296,16 +3308,16 @@
 	/* populate reclaim_str_hashtbl with current confirmed nfs4_clientid */
 	for (i = 0; i < CLIENT_HASH_SIZE; i++) {
 		list_for_each_entry(clp, &conf_id_hashtbl[i], cl_idhash) {
-			if (!nfs4_client_to_reclaim(clp)) {
+			if (!nfs4_client_to_reclaim(clp->cl_name.data,
+						clp->cl_name.len)) {
 				nfs4_release_reclaim();
 				goto init_state;
 			}
-			reclaim_str_hashtbl_size++;
 		}
 	}
 init_state:
 	__nfs4_state_shutdown();
-	nfs4_state_init();
+	__nfs4_state_init();
 	nfs4_unlock_state();
 }
 
diff -Nru a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
--- a/fs/nfsd/nfs4xdr.c	2005-03-11 12:51:51 -08:00
+++ b/fs/nfsd/nfs4xdr.c	2005-03-11 12:51:51 -08:00
@@ -60,121 +60,6 @@
 
 #define NFSDDBG_FACILITY		NFSDDBG_XDR
 
-static const char utf8_byte_len[256] = {
-	1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
-	1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
-	1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
-	1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
-	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-	0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
-	3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, 4,4,4,4,4,4,4,4,5,5,5,5,6,6,0,0
-};
-
-static inline int
-is_legal_utf8_sequence(unsigned char *source, int length)
-{
-	unsigned char *ptr;
-	unsigned char c;
-
-	if (length==1) return 1;
-
-	/* Check for overlong sequence, and check second byte */
-	c = *(source + 1);
-	switch (*source) {
-	case 0xE0: /* 3 bytes */
-		if ( c < 0xA0 ) return 0;
-		break;
-	case 0xF0: /* 4 bytes */
-		if ( c < 0x90 ) return 0;
-		break;
-	case 0xF8: /* 5 bytes */
-		if ( c < 0xC8 ) return 0;
-		break;
-	case 0xFC: /* 6 bytes */
-		if ( c < 0x84 ) return 0;
-		break;
-	default:
-		if ( (c & 0xC0) != 0x80) return 0;
-	}
-
-	/* Check that trailing bytes look like 10xxxxxx */
-	for (ptr = source++ + length - 1; ptr>source; ptr--)
-		if ( ((*ptr) & 0xC0) != 0x80 ) return 0;
-	return 1;
-}
-
-/* This does some screening on disallowed unicode characters.  It is NOT
- * comprehensive.
- */
-static int
-is_allowed_utf8_char(unsigned char *source, int length)
-{
-	/* We assume length and source point to a valid utf8 sequence */
-	unsigned char c;
-
-	/* Disallow F0000 and up (in utf8, F3B08080) */
-	if (*source > 0xF3 ) return 0;
-	c = *(source + 1);
-	switch (*source) {
-	case 0xF3:
-		if (c >= 0xB0) return 0;
-		break;
-	/* Disallow D800-F8FF (in utf8, EDA080-EFA3BF */
-	case 0xED:
-		if (c >= 0xA0) return 0;
-		break;
-	case 0xEE:
-		return 0;
-		break;
-	case 0xEF:
-		if (c <= 0xA3) return 0;
-	/* Disallow FFF9-FFFF (EFBFB9-EFBFBF) */
-		if (c==0xBF)
-			/* Don't need to check <=0xBF, since valid utf8 */
-			if ( *(source+2) >= 0xB9) return 0;
-		break;
-	}
-	return 1;
-}
-
-/* This routine should really check to see that the proper stringprep
- * mappings have been applied.  Instead, we do a simple screen of some
- * of the more obvious illegal values by calling is_allowed_utf8_char.
- * This will allow many illegal strings through, but if a client behaves,
- * it will get full functionality.  The other option (apart from full
- * stringprep checking) is to limit everything to an easily handled subset,
- * such as 7-bit ascii.
- *
- * Note - currently calling routines ignore return value except as boolean.
- */
-static int
-check_utf8(char *str, int len)
-{
-	unsigned char *chunk, *sourceend;
-	int chunklen;
-
-	chunk = str;
-	sourceend = str + len;
-
-	while (chunk < sourceend) {
-		chunklen = utf8_byte_len[*chunk];
-		if (!chunklen)
-			return nfserr_inval;
-		if (chunk + chunklen > sourceend)
-			return nfserr_inval;
-		if (!is_legal_utf8_sequence(chunk, chunklen))
-			return nfserr_inval;
-		if (!is_allowed_utf8_char(chunk, chunklen))
-			return nfserr_inval;
-		if ( (chunklen==1) && (!*chunk) )
-			return nfserr_inval; /* Disallow embedded nulls */
-		chunk += chunklen;
-	}
-
-	return 0;
-}
-
 static int
 check_filename(char *str, int len, int err)
 {
@@ -187,7 +72,7 @@
 	for (i = 0; i < len; i++)
 		if (str[i] == '/')
 			return err;
-	return check_utf8(str, len);
+	return 0;
 }
 
 /*
@@ -403,8 +288,6 @@
 			READ_BUF(dummy32);
 			len += XDR_QUADLEN(dummy32) << 2;
 			READMEM(buf, dummy32);
-			if (check_utf8(buf, dummy32))
-				return nfserr_inval;
 			ace.whotype = nfs4_acl_get_whotype(buf, dummy32);
 			status = 0;
 			if (ace.whotype != NFS4_ACL_WHO_NAMED)
@@ -439,8 +322,6 @@
 		READ_BUF(dummy32);
 		len += (XDR_QUADLEN(dummy32) << 2);
 		READMEM(buf, dummy32);
-		if (check_utf8(buf, dummy32))
-			return nfserr_inval;
 		if ((status = nfsd_map_name_to_uid(argp->rqstp, buf, dummy32, &iattr->ia_uid)))
 			goto out_nfserr;
 		iattr->ia_valid |= ATTR_UID;
@@ -452,8 +333,6 @@
 		READ_BUF(dummy32);
 		len += (XDR_QUADLEN(dummy32) << 2);
 		READMEM(buf, dummy32);
-		if (check_utf8(buf, dummy32))
-			return nfserr_inval;
 		if ((status = nfsd_map_name_to_gid(argp->rqstp, buf, dummy32, &iattr->ia_gid)))
 			goto out_nfserr;
 		iattr->ia_valid |= ATTR_GID;
@@ -585,8 +464,6 @@
 		READ32(create->cr_linklen);
 		READ_BUF(create->cr_linklen);
 		SAVEMEM(create->cr_linkname, create->cr_linklen);
-		if (check_utf8(create->cr_linkname, create->cr_linklen))
-			return nfserr_inval;
 		break;
 	case NF4BLK:
 	case NF4CHR:
@@ -2191,10 +2068,10 @@
 	}
 	read->rd_vlen = v;
 
-	nfserr = nfsd_read(read->rd_rqstp, read->rd_fhp,
-			   read->rd_offset,
-			   read->rd_iov, read->rd_vlen,
-			   &maxcount);
+	nfserr = nfsd_read(read->rd_rqstp, read->rd_fhp, read->rd_filp,
+			read->rd_offset, read->rd_iov, read->rd_vlen,
+			&maxcount);
+
 	if (nfserr == nfserr_symlink)
 		nfserr = nfserr_inval;
 	if (nfserr)
diff -Nru a/fs/nfsd/nfscache.c b/fs/nfsd/nfscache.c
--- a/fs/nfsd/nfscache.c	2005-03-11 12:51:52 -08:00
+++ b/fs/nfsd/nfscache.c	2005-03-11 12:51:52 -08:00
@@ -15,6 +15,7 @@
 #include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/spinlock.h>
+#include <linux/list.h>
 
 #include <linux/sunrpc/svc.h>
 #include <linux/nfsd/nfsd.h>
@@ -30,15 +31,8 @@
 #define HASHSIZE		64
 #define REQHASH(xid)		((((xid) >> 24) ^ (xid)) & (HASHSIZE-1))
 
-struct nfscache_head {
-	struct svc_cacherep *	next;
-	struct svc_cacherep *	prev;
-};
-
-static struct nfscache_head *	hash_list;
-static struct svc_cacherep *	lru_head;
-static struct svc_cacherep *	lru_tail;
-static struct svc_cacherep *	nfscache;
+static struct hlist_head *	hash_list;
+static struct list_head 	lru_head;
 static int			cache_disabled = 1;
 
 static int	nfsd_cache_append(struct svc_rqst *rqstp, struct kvec *vec);
@@ -54,46 +48,32 @@
 nfsd_cache_init(void)
 {
 	struct svc_cacherep	*rp;
-	struct nfscache_head	*rh;
-	size_t			i;
-	unsigned long		order;
+	int			i;
 
-
-	i = CACHESIZE * sizeof (struct svc_cacherep);
-	for (order = 0; (PAGE_SIZE << order) < i; order++)
-		;
-	nfscache = (struct svc_cacherep *)
-		__get_free_pages(GFP_KERNEL, order);
-	if (!nfscache) {
-		printk (KERN_ERR "nfsd: cannot allocate %Zd bytes for reply cache\n", i);
-		return;
+	INIT_LIST_HEAD(&lru_head);
+	i = CACHESIZE;
+	while(i) {
+		rp = kmalloc(sizeof(*rp), GFP_KERNEL);
+		if (!rp) break;
+		list_add(&rp->c_lru, &lru_head);
+		rp->c_state = RC_UNUSED;
+		rp->c_type = RC_NOCACHE;
+		INIT_HLIST_NODE(&rp->c_hash);
+		i--;
 	}
-	memset(nfscache, 0, i);
 
-	i = HASHSIZE * sizeof (struct nfscache_head);
-	hash_list = kmalloc (i, GFP_KERNEL);
+	if (i)
+		printk (KERN_ERR "nfsd: cannot allocate all %d cache entries, only got %d\n",
+			CACHESIZE, CACHESIZE-i);
+
+	hash_list = kmalloc (HASHSIZE * sizeof(struct hlist_head), GFP_KERNEL);
 	if (!hash_list) {
-		free_pages ((unsigned long)nfscache, order);
-		nfscache = NULL;
-		printk (KERN_ERR "nfsd: cannot allocate %Zd bytes for hash list\n", i);
+		nfsd_cache_shutdown();
+		printk (KERN_ERR "nfsd: cannot allocate %Zd bytes for hash list\n",
+			HASHSIZE * sizeof(struct hlist_head));
 		return;
 	}
-
-	for (i = 0, rh = hash_list; i < HASHSIZE; i++, rh++)
-		rh->next = rh->prev = (struct svc_cacherep *) rh;
-
-	for (i = 0, rp = nfscache; i < CACHESIZE; i++, rp++) {
-		rp->c_state = RC_UNUSED;
-		rp->c_type = RC_NOCACHE;
-		rp->c_hash_next =
-		rp->c_hash_prev = rp;
-		rp->c_lru_next = rp + 1;
-		rp->c_lru_prev = rp - 1;
-	}
-	lru_head = nfscache;
-	lru_tail = nfscache + CACHESIZE - 1;
-	lru_head->c_lru_prev = NULL;
-	lru_tail->c_lru_next = NULL;
+	memset(hash_list, 0, HASHSIZE * sizeof(struct hlist_head));
 
 	cache_disabled = 0;
 }
@@ -102,48 +82,30 @@
 nfsd_cache_shutdown(void)
 {
 	struct svc_cacherep	*rp;
-	size_t			i;
-	unsigned long		order;
 
-	for (rp = lru_head; rp; rp = rp->c_lru_next) {
+	while (!list_empty(&lru_head)) {
+		rp = list_entry(lru_head.next, struct svc_cacherep, c_lru);
 		if (rp->c_state == RC_DONE && rp->c_type == RC_REPLBUFF)
 			kfree(rp->c_replvec.iov_base);
+		list_del(&rp->c_lru);
+		kfree(rp);
 	}
 
 	cache_disabled = 1;
 
-	i = CACHESIZE * sizeof (struct svc_cacherep);
-	for (order = 0; (PAGE_SIZE << order) < i; order++)
-		;
-	free_pages ((unsigned long)nfscache, order);
-	nfscache = NULL;
-	kfree (hash_list);
+	if (hash_list)
+		kfree (hash_list);
 	hash_list = NULL;
 }
 
 /*
- * Move cache entry to front of LRU list
+ * Move cache entry to end of LRU list
  */
 static void
-lru_put_front(struct svc_cacherep *rp)
+lru_put_end(struct svc_cacherep *rp)
 {
-	struct svc_cacherep	*prev = rp->c_lru_prev,
-				*next = rp->c_lru_next;
-
-	if (prev)
-		prev->c_lru_next = next;
-	else
-		lru_head = next;
-	if (next)
-		next->c_lru_prev = prev;
-	else
-		lru_tail = prev;
-
-	rp->c_lru_next = lru_head;
-	rp->c_lru_prev = NULL;
-	if (lru_head)
-		lru_head->c_lru_prev = rp;
-	lru_head = rp;
+	list_del(&rp->c_lru);
+	list_add_tail(&rp->c_lru, &lru_head);
 }
 
 /*
@@ -152,17 +114,8 @@
 static void
 hash_refile(struct svc_cacherep *rp)
 {
-	struct svc_cacherep	*prev = rp->c_hash_prev,
-				*next = rp->c_hash_next;
-	struct nfscache_head	*head = hash_list + REQHASH(rp->c_xid);
-
-	prev->c_hash_next = next;
-	next->c_hash_prev = prev;
-
-	rp->c_hash_next = head->next;
-	rp->c_hash_prev = (struct svc_cacherep *) head;
-	head->next->c_hash_prev = rp;
-	head->next = rp;
+	hlist_del_init(&rp->c_hash);
+	hlist_add_head(&rp->c_hash, hash_list + REQHASH(rp->c_xid));
 }
 
 /*
@@ -173,7 +126,9 @@
 int
 nfsd_cache_lookup(struct svc_rqst *rqstp, int type)
 {
-	struct svc_cacherep	*rh, *rp;
+	struct hlist_node	*hn;
+	struct hlist_head 	*rh;
+	struct svc_cacherep	*rp;
 	u32			xid = rqstp->rq_xid,
 				proto =  rqstp->rq_prot,
 				vers = rqstp->rq_vers,
@@ -190,8 +145,8 @@
 	spin_lock(&cache_lock);
 	rtn = RC_DOIT;
 
-	rp = rh = (struct svc_cacherep *) &hash_list[REQHASH(xid)];
-	while ((rp = rp->c_hash_next) != rh) {
+	rh = &hash_list[REQHASH(xid)];
+	hlist_for_each_entry(rp, hn, rh, c_hash) {
 		if (rp->c_state != RC_UNUSED &&
 		    xid == rp->c_xid && proc == rp->c_proc &&
 		    proto == rp->c_prot && vers == rp->c_vers &&
@@ -206,7 +161,7 @@
 	/* This loop shouldn't take more than a few iterations normally */
 	{
 	int	safe = 0;
-	for (rp = lru_tail; rp; rp = rp->c_lru_prev) {
+	list_for_each_entry(rp, &lru_head, c_lru) {
 		if (rp->c_state != RC_INPROG)
 			break;
 		if (safe++ > CACHESIZE) {
@@ -254,7 +209,7 @@
 	/* We found a matching entry which is either in progress or done. */
 	age = jiffies - rp->c_timestamp;
 	rp->c_timestamp = jiffies;
-	lru_put_front(rp);
+	lru_put_end(rp);
 
 	rtn = RC_DROPIT;
 	/* Request being processed or excessive rexmits */
@@ -343,7 +298,7 @@
 		break;
 	}
 	spin_lock(&cache_lock);
-	lru_put_front(rp);
+	lru_put_end(rp);
 	rp->c_secure = rqstp->rq_secure;
 	rp->c_type = cachetype;
 	rp->c_state = RC_DONE;
diff -Nru a/fs/nfsd/nfsfh.c b/fs/nfsd/nfsfh.c
--- a/fs/nfsd/nfsfh.c	2005-03-11 12:51:42 -08:00
+++ b/fs/nfsd/nfsfh.c	2005-03-11 12:51:42 -08:00
@@ -41,7 +41,7 @@
  * if not, require that we can walk up to exp->ex_dentry
  * doing some checks on the 'x' bits
  */
-int nfsd_acceptable(void *expv, struct dentry *dentry)
+static int nfsd_acceptable(void *expv, struct dentry *dentry)
 {
 	struct svc_export *exp = expv;
 	int rv;
@@ -280,8 +280,8 @@
  * an inode.  In this case a call to fh_update should be made
  * before the fh goes out on the wire ...
  */
-inline int _fh_update(struct dentry *dentry, struct svc_export *exp,
-		      __u32 *datap, int *maxsize)
+static inline int _fh_update(struct dentry *dentry, struct svc_export *exp,
+			     __u32 *datap, int *maxsize)
 {
 	struct export_operations *nop = exp->ex_mnt->mnt_sb->s_export_op;
 	
@@ -297,8 +297,9 @@
 /*
  * for composing old style file handles
  */
-inline void _fh_update_old(struct dentry *dentry, struct svc_export *exp,
-			   struct knfsd_fh *fh)
+static inline void _fh_update_old(struct dentry *dentry,
+				  struct svc_export *exp,
+				  struct knfsd_fh *fh)
 {
 	fh->ofh_ino = ino_t_to_u32(dentry->d_inode->i_ino);
 	fh->ofh_generation = dentry->d_inode->i_generation;
diff -Nru a/fs/nfsd/nfsproc.c b/fs/nfsd/nfsproc.c
--- a/fs/nfsd/nfsproc.c	2005-03-11 12:51:42 -08:00
+++ b/fs/nfsd/nfsproc.c	2005-03-11 12:51:42 -08:00
@@ -137,7 +137,7 @@
 	svc_reserve(rqstp, (19<<2) + argp->count + 4);
 
 	resp->count = argp->count;
-	nfserr = nfsd_read(rqstp, fh_copy(&resp->fh, &argp->fh),
+	nfserr = nfsd_read(rqstp, fh_copy(&resp->fh, &argp->fh), NULL,
 				  argp->offset,
 			   	  argp->vec, argp->vlen,
 				  &resp->count);
@@ -160,7 +160,7 @@
 		SVCFH_fmt(&argp->fh),
 		argp->len, argp->offset);
 
-	nfserr = nfsd_write(rqstp, fh_copy(&resp->fh, &argp->fh),
+	nfserr = nfsd_write(rqstp, fh_copy(&resp->fh, &argp->fh), NULL,
 				   argp->offset,
 				   argp->vec, argp->vlen,
 				   argp->len,
@@ -590,6 +590,7 @@
 		{ nfserr_dropit, -EAGAIN },
 		{ nfserr_dropit, -ENOMEM },
 		{ nfserr_badname, -ESRCH },
+		{ nfserr_io, -ETXTBSY },
 		{ -1, -EIO }
 	};
 	int	i;
diff -Nru a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c
--- a/fs/nfsd/nfssvc.c	2005-03-11 12:51:46 -08:00
+++ b/fs/nfsd/nfssvc.c	2005-03-11 12:51:46 -08:00
@@ -60,7 +60,7 @@
 	struct list_head 	list;
 	struct task_struct	*task;
 };
-struct list_head nfsd_list = LIST_HEAD_INIT(nfsd_list);
+static struct list_head nfsd_list = LIST_HEAD_INIT(nfsd_list);
 
 /*
  * Maximum number of nfsd processes
@@ -92,7 +92,9 @@
 	
 	/* Readahead param cache - will no-op if it already exists */
 	error =	nfsd_racache_init(2*nrservs);
-	nfs4_state_init();
+	if (error<0)
+		goto out;
+	error = nfs4_state_init();
 	if (error<0)
 		goto out;
 	if (!nfsd_serv) {
@@ -378,4 +380,6 @@
 	.pg_name		= "nfsd",		/* program name */
 	.pg_class		= "nfsd",		/* authentication class */
 	.pg_stats		= &nfsd_svcstats,	/* version table */
+	.pg_authenticate	= &svc_set_client,	/* export authentication */
+
 };
diff -Nru a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
--- a/fs/nfsd/vfs.c	2005-03-11 12:51:42 -08:00
+++ b/fs/nfsd/vfs.c	2005-03-11 12:51:42 -08:00
@@ -36,6 +36,7 @@
 #include <linux/module.h>
 #include <linux/namei.h>
 #include <linux/vfs.h>
+#include <linux/delay.h>
 #include <linux/sunrpc/svc.h>
 #include <linux/nfsd/nfsd.h>
 #ifdef CONFIG_NFSD_V3
@@ -707,8 +708,8 @@
  * As this calls fsync (not fdatasync) there is no need for a write_inode
  * after it.
  */
-inline void nfsd_dosync(struct file *filp, struct dentry *dp, 
-			struct file_operations *fop)
+static inline void nfsd_dosync(struct file *filp, struct dentry *dp,
+			       struct file_operations *fop)
 {
 	struct inode *inode = dp->d_inode;
 	int (*fsync) (struct file *, struct dentry *, int);
@@ -720,7 +721,7 @@
 }
 	
 
-void
+static void
 nfsd_sync(struct file *filp)
 {
 	struct inode *inode = filp->f_dentry->d_inode;
@@ -730,7 +731,7 @@
 	up(&inode->i_sem);
 }
 
-void
+static void
 nfsd_sync_dir(struct dentry *dp)
 {
 	nfsd_dosync(NULL, dp, dp->d_inode->i_fop);
@@ -810,30 +811,21 @@
 	return size;
 }
 
-/*
- * Read data from a file. count must contain the requested read count
- * on entry. On return, *count contains the number of bytes actually read.
- * N.B. After this call fhp needs an fh_put
- */
-int
-nfsd_read(struct svc_rqst *rqstp, struct svc_fh *fhp, loff_t offset,
-          struct kvec *vec, int vlen, unsigned long *count)
+static inline int
+nfsd_vfs_read(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
+              loff_t offset, struct kvec *vec, int vlen, unsigned long *count)
 {
+	struct inode *inode;
 	struct raparms	*ra;
 	mm_segment_t	oldfs;
 	int		err;
-	struct file	*file;
-	struct inode	*inode;
 
-	err = nfsd_open(rqstp, fhp, S_IFREG, MAY_READ, &file);
-	if (err)
-		goto out;
 	err = nfserr_perm;
 	inode = file->f_dentry->d_inode;
 #ifdef MSNFS
 	if ((fhp->fh_export->ex_flags & NFSEXP_MSNFS) &&
 		(!lock_may_read(inode, offset, *count)))
-		goto out_close;
+		goto out;
 #endif
 
 	/* Get readahead parameters */
@@ -869,41 +861,28 @@
 		dnotify_parent(file->f_dentry, DN_ACCESS);
 	} else 
 		err = nfserrno(err);
-out_close:
-	nfsd_close(file);
 out:
 	return err;
 }
 
-/*
- * Write data to a file.
- * The stable flag requests synchronous writes.
- * N.B. After this call fhp needs an fh_put
- */
-int
-nfsd_write(struct svc_rqst *rqstp, struct svc_fh *fhp, loff_t offset,
-				struct kvec *vec, int vlen,
+static inline int
+nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
+				loff_t offset, struct kvec *vec, int vlen,
 	   			unsigned long cnt, int *stablep)
 {
 	struct svc_export	*exp;
-	struct file		*file;
 	struct dentry		*dentry;
 	struct inode		*inode;
 	mm_segment_t		oldfs;
 	int			err = 0;
 	int			stable = *stablep;
 
-	err = nfsd_open(rqstp, fhp, S_IFREG, MAY_WRITE, &file);
-	if (err)
-		goto out;
-	if (!cnt)
-		goto out_close;
 	err = nfserr_perm;
 
 #ifdef MSNFS
 	if ((fhp->fh_export->ex_flags & NFSEXP_MSNFS) &&
 		(!lock_may_write(file->f_dentry->d_inode, offset, cnt)))
-		goto out_close;
+		goto out;
 #endif
 
 	dentry = file->f_dentry;
@@ -968,8 +947,7 @@
 			if (atomic_read(&inode->i_writecount) > 1
 			    || (last_ino == inode->i_ino && last_dev == inode->i_sb->s_dev)) {
 				dprintk("nfsd: write defer %d\n", current->pid);
-				set_current_state(TASK_UNINTERRUPTIBLE);
-				schedule_timeout((HZ+99)/100);
+				msleep(10);
 				dprintk("nfsd: write resume %d\n", current->pid);
 			}
 
@@ -990,12 +968,71 @@
 		err = 0;
 	else 
 		err = nfserrno(err);
-out_close:
-	nfsd_close(file);
 out:
 	return err;
 }
 
+/*
+ * Read data from a file. count must contain the requested read count
+ * on entry. On return, *count contains the number of bytes actually read.
+ * N.B. After this call fhp needs an fh_put
+ */
+int
+nfsd_read(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
+		loff_t offset, struct kvec *vec, int vlen,
+		unsigned long *count)
+{
+	int		err;
+
+	if (file) {
+		err = nfsd_permission(fhp->fh_export, fhp->fh_dentry,
+				MAY_READ|MAY_OWNER_OVERRIDE);
+		if (err)
+			goto out;
+		err = nfsd_vfs_read(rqstp, fhp, file, offset, vec, vlen, count);
+	} else {
+		err = nfsd_open(rqstp, fhp, S_IFREG, MAY_READ, &file);
+		if (err)
+			goto out;
+		err = nfsd_vfs_read(rqstp, fhp, file, offset, vec, vlen, count);
+		nfsd_close(file);
+	}
+out:
+	return err;
+}
+
+/*
+ * Write data to a file.
+ * The stable flag requests synchronous writes.
+ * N.B. After this call fhp needs an fh_put
+ */
+int
+nfsd_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
+		loff_t offset, struct kvec *vec, int vlen, unsigned long cnt,
+		int *stablep)
+{
+	int			err = 0;
+
+	if (file) {
+		err = nfsd_permission(fhp->fh_export, fhp->fh_dentry,
+				MAY_WRITE|MAY_OWNER_OVERRIDE);
+		if (err)
+			goto out;
+		err = nfsd_vfs_write(rqstp, fhp, file, offset, vec, vlen, cnt,
+				stablep);
+	} else {
+		err = nfsd_open(rqstp, fhp, S_IFREG, MAY_WRITE, &file);
+		if (err)
+			goto out;
+
+		if (cnt)
+			err = nfsd_vfs_write(rqstp, fhp, file, offset, vec, vlen,
+					     cnt, stablep);
+		nfsd_close(file);
+	}
+out:
+	return err;
+}
 
 #ifdef CONFIG_NFSD_V3
 /*
diff -Nru a/fs/partitions/msdos.c b/fs/partitions/msdos.c
--- a/fs/partitions/msdos.c	2005-03-11 12:51:47 -08:00
+++ b/fs/partitions/msdos.c	2005-03-11 12:51:47 -08:00
@@ -114,6 +114,9 @@
 		 */
 		for (i=0; i<4; i++, p++) {
 			u32 offs, size, next;
+
+			if (SYS_IND(p) == 0)
+				continue;
 			if (!NR_SECTS(p) || is_extended_partition(p))
 				continue;
 
@@ -430,6 +433,8 @@
 	for (slot = 1 ; slot <= 4 ; slot++, p++) {
 		u32 start = START_SECT(p)*sector_size;
 		u32 size = NR_SECTS(p)*sector_size;
+		if (SYS_IND(p) == 0)
+			continue;
 		if (!size)
 			continue;
 		if (is_extended_partition(p)) {
diff -Nru a/fs/proc/array.c b/fs/proc/array.c
--- a/fs/proc/array.c	2005-03-11 12:51:47 -08:00
+++ b/fs/proc/array.c	2005-03-11 12:51:47 -08:00
@@ -73,6 +73,7 @@
 #include <linux/highmem.h>
 #include <linux/file.h>
 #include <linux/times.h>
+#include <linux/cpuset.h>
 
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
@@ -239,6 +240,8 @@
 {
 	sigset_t pending, shpending, blocked, ignored, caught;
 	int num_threads = 0;
+	unsigned long qsize = 0;
+	unsigned long qlim = 0;
 
 	sigemptyset(&pending);
 	sigemptyset(&shpending);
@@ -255,11 +258,14 @@
 		blocked = p->blocked;
 		collect_sigign_sigcatch(p, &ignored, &caught);
 		num_threads = atomic_read(&p->signal->count);
+		qsize = atomic_read(&p->user->sigpending);
+		qlim = p->signal->rlim[RLIMIT_SIGPENDING].rlim_cur;
 		spin_unlock_irq(&p->sighand->siglock);
 	}
 	read_unlock(&tasklist_lock);
 
 	buffer += sprintf(buffer, "Threads:\t%d\n", num_threads);
+	buffer += sprintf(buffer, "SigQ:\t%lu/%lu\n", qsize, qlim);
 
 	/* render them all */
 	buffer = render_sigset_t("SigPnd:\t", &pending, buffer);
@@ -295,6 +301,7 @@
 	}
 	buffer = task_sig(task, buffer);
 	buffer = task_cap(task, buffer);
+	buffer = cpuset_task_status_allowed(task, buffer);
 #if defined(CONFIG_ARCH_S390)
 	buffer = task_show_regs(task, buffer);
 #endif
@@ -317,6 +324,7 @@
 	unsigned long  min_flt = 0,  maj_flt = 0;
 	cputime_t cutime, cstime, utime, stime;
 	unsigned long rsslim = 0;
+	unsigned long it_real_value = 0;
 	struct task_struct *t;
 	char tcomm[sizeof(task->comm)];
 
@@ -372,6 +380,7 @@
 			utime = cputime_add(utime, task->signal->utime);
 			stime = cputime_add(stime, task->signal->stime);
 		}
+		it_real_value = task->signal->it_real_value;
 	}
 	ppid = pid_alive(task) ? task->group_leader->real_parent->tgid : 0;
 	read_unlock(&tasklist_lock);
@@ -420,7 +429,7 @@
 		priority,
 		nice,
 		num_threads,
-		jiffies_to_clock_t(task->it_real_value),
+		jiffies_to_clock_t(it_real_value),
 		start_time,
 		vsize,
 		mm ? mm->rss : 0, /* you might want to shift this left 3 */
diff -Nru a/fs/proc/base.c b/fs/proc/base.c
--- a/fs/proc/base.c	2005-03-11 12:51:47 -08:00
+++ b/fs/proc/base.c	2005-03-11 12:51:47 -08:00
@@ -32,6 +32,8 @@
 #include <linux/mount.h>
 #include <linux/security.h>
 #include <linux/ptrace.h>
+#include <linux/seccomp.h>
+#include <linux/cpuset.h>
 #include "internal.h"
 
 /*
@@ -49,6 +51,9 @@
 	PROC_TGID_TASK,
 	PROC_TGID_STATUS,
 	PROC_TGID_MEM,
+#ifdef CONFIG_SECCOMP
+	PROC_TGID_SECCOMP,
+#endif
 	PROC_TGID_CWD,
 	PROC_TGID_ROOT,
 	PROC_TGID_EXE,
@@ -64,6 +69,9 @@
 #ifdef CONFIG_SCHEDSTATS
 	PROC_TGID_SCHEDSTAT,
 #endif
+#ifdef CONFIG_CPUSETS
+	PROC_TGID_CPUSET,
+#endif
 #ifdef CONFIG_SECURITY
 	PROC_TGID_ATTR,
 	PROC_TGID_ATTR_CURRENT,
@@ -80,6 +88,9 @@
 	PROC_TID_INO,
 	PROC_TID_STATUS,
 	PROC_TID_MEM,
+#ifdef CONFIG_SECCOMP
+	PROC_TID_SECCOMP,
+#endif
 	PROC_TID_CWD,
 	PROC_TID_ROOT,
 	PROC_TID_EXE,
@@ -95,6 +106,9 @@
 #ifdef CONFIG_SCHEDSTATS
 	PROC_TID_SCHEDSTAT,
 #endif
+#ifdef CONFIG_CPUSETS
+	PROC_TID_CPUSET,
+#endif
 #ifdef CONFIG_SECURITY
 	PROC_TID_ATTR,
 	PROC_TID_ATTR_CURRENT,
@@ -130,6 +144,9 @@
 	E(PROC_TGID_STATM,     "statm",   S_IFREG|S_IRUGO),
 	E(PROC_TGID_MAPS,      "maps",    S_IFREG|S_IRUGO),
 	E(PROC_TGID_MEM,       "mem",     S_IFREG|S_IRUSR|S_IWUSR),
+#ifdef CONFIG_SECCOMP
+	E(PROC_TGID_SECCOMP,   "seccomp", S_IFREG|S_IRUSR|S_IWUSR),
+#endif
 	E(PROC_TGID_CWD,       "cwd",     S_IFLNK|S_IRWXUGO),
 	E(PROC_TGID_ROOT,      "root",    S_IFLNK|S_IRWXUGO),
 	E(PROC_TGID_EXE,       "exe",     S_IFLNK|S_IRWXUGO),
@@ -143,6 +160,9 @@
 #ifdef CONFIG_SCHEDSTATS
 	E(PROC_TGID_SCHEDSTAT, "schedstat", S_IFREG|S_IRUGO),
 #endif
+#ifdef CONFIG_CPUSETS
+	E(PROC_TGID_CPUSET,    "cpuset",  S_IFREG|S_IRUGO),
+#endif
 	E(PROC_TGID_OOM_SCORE, "oom_score",S_IFREG|S_IRUGO),
 	E(PROC_TGID_OOM_ADJUST,"oom_adj", S_IFREG|S_IRUGO|S_IWUSR),
 #ifdef CONFIG_AUDITSYSCALL
@@ -160,6 +180,9 @@
 	E(PROC_TID_STATM,      "statm",   S_IFREG|S_IRUGO),
 	E(PROC_TID_MAPS,       "maps",    S_IFREG|S_IRUGO),
 	E(PROC_TID_MEM,        "mem",     S_IFREG|S_IRUSR|S_IWUSR),
+#ifdef CONFIG_SECCOMP
+	E(PROC_TID_SECCOMP,    "seccomp", S_IFREG|S_IRUSR|S_IWUSR),
+#endif
 	E(PROC_TID_CWD,        "cwd",     S_IFLNK|S_IRWXUGO),
 	E(PROC_TID_ROOT,       "root",    S_IFLNK|S_IRWXUGO),
 	E(PROC_TID_EXE,        "exe",     S_IFLNK|S_IRWXUGO),
@@ -173,6 +196,9 @@
 #ifdef CONFIG_SCHEDSTATS
 	E(PROC_TID_SCHEDSTAT, "schedstat",S_IFREG|S_IRUGO),
 #endif
+#ifdef CONFIG_CPUSETS
+	E(PROC_TID_CPUSET,     "cpuset",  S_IFREG|S_IRUGO),
+#endif
 	E(PROC_TID_OOM_SCORE,  "oom_score",S_IFREG|S_IRUGO),
 	E(PROC_TID_OOM_ADJUST, "oom_adj", S_IFREG|S_IRUGO|S_IWUSR),
 #ifdef CONFIG_AUDITSYSCALL
@@ -808,6 +834,61 @@
 };
 #endif
 
+#ifdef CONFIG_SECCOMP
+static ssize_t seccomp_read(struct file *file, char __user *buf,
+			    size_t count, loff_t *ppos)
+{
+	struct task_struct *tsk = proc_task(file->f_dentry->d_inode);
+	char __buf[20];
+	loff_t __ppos = *ppos;
+	size_t len;
+
+	/* no need to print the trailing zero, so use only len */
+	len = sprintf(__buf, "%u\n", tsk->seccomp.mode);
+	if (__ppos >= len)
+		return 0;
+	if (count > len - __ppos)
+		count = len - __ppos;
+	if (copy_to_user(buf, __buf + __ppos, count))
+		return -EFAULT;
+	*ppos = __ppos + count;
+	return count;
+}
+
+static ssize_t seccomp_write(struct file *file, const char __user *buf,
+			     size_t count, loff_t *ppos)
+{
+	struct task_struct *tsk = proc_task(file->f_dentry->d_inode);
+	char __buf[20], *end;
+	unsigned int seccomp_mode;
+
+	/* can set it only once to be even more secure */
+	if (unlikely(tsk->seccomp.mode))
+		return -EPERM;
+
+	memset(__buf, 0, sizeof(__buf));
+	count = min(count, sizeof(__buf) - 1);
+	if (copy_from_user(__buf, buf, count))
+		return -EFAULT;
+	seccomp_mode = simple_strtoul(__buf, &end, 0);
+	if (*end == '\n')
+		end++;
+	if (seccomp_mode && seccomp_mode <= NR_SECCOMP_MODES) {
+		tsk->seccomp.mode = seccomp_mode;
+		set_tsk_thread_flag(tsk, TIF_SECCOMP);
+	} else
+		return -EINVAL;
+	if (unlikely(!(end - __buf)))
+		return -EIO;
+	return end - __buf;
+}
+
+static struct file_operations proc_seccomp_operations = {
+	.read		= seccomp_read,
+	.write		= seccomp_write,
+};
+#endif /* CONFIG_SECCOMP */
+
 static int proc_pid_follow_link(struct dentry *dentry, struct nameidata *nd)
 {
 	struct inode *inode = dentry->d_inode;
@@ -1443,6 +1524,12 @@
 			inode->i_op = &proc_mem_inode_operations;
 			inode->i_fop = &proc_mem_operations;
 			break;
+#ifdef CONFIG_SECCOMP
+		case PROC_TID_SECCOMP:
+		case PROC_TGID_SECCOMP:
+			inode->i_fop = &proc_seccomp_operations;
+			break;
+#endif /* CONFIG_SECCOMP */
 		case PROC_TID_MOUNTS:
 		case PROC_TGID_MOUNTS:
 			inode->i_fop = &proc_mounts_operations;
@@ -1483,6 +1570,12 @@
 			ei->op.proc_read = proc_pid_schedstat;
 			break;
 #endif
+#ifdef CONFIG_CPUSETS
+		case PROC_TID_CPUSET:
+		case PROC_TGID_CPUSET:
+			inode->i_fop = &proc_cpuset_operations;
+			break;
+#endif
 		case PROC_TID_OOM_SCORE:
 		case PROC_TGID_OOM_SCORE:
 			inode->i_fop = &proc_info_file_operations;
@@ -1630,11 +1723,15 @@
 	if (proc_dentry != NULL) {
 
 		spin_lock(&dcache_lock);
+		spin_lock(&proc_dentry->d_lock);
 		if (!d_unhashed(proc_dentry)) {
 			dget_locked(proc_dentry);
 			__d_drop(proc_dentry);
-		} else
+			spin_unlock(&proc_dentry->d_lock);
+		} else {
+			spin_unlock(&proc_dentry->d_lock);
 			proc_dentry = NULL;
+		}
 		spin_unlock(&dcache_lock);
 	}
 	return proc_dentry;
diff -Nru a/fs/proc/inode.c b/fs/proc/inode.c
--- a/fs/proc/inode.c	2005-03-11 12:51:51 -08:00
+++ b/fs/proc/inode.c	2005-03-11 12:51:51 -08:00
@@ -14,7 +14,6 @@
 #include <linux/limits.h>
 #include <linux/init.h>
 #include <linux/module.h>
-#include <linux/parser.h>
 #include <linux/smp_lock.h>
 
 #include <asm/system.h>
@@ -143,51 +142,6 @@
 	.remount_fs	= proc_remount,
 };
 
-enum {
-	Opt_uid, Opt_gid, Opt_err
-};
-
-static match_table_t tokens = {
-	{Opt_uid, "uid=%u"},
-	{Opt_gid, "gid=%u"},
-	{Opt_err, NULL}
-};
-
-static int parse_options(char *options,uid_t *uid,gid_t *gid)
-{
-	char *p;
-	int option;
-
-	*uid = current->uid;
-	*gid = current->gid;
-	if (!options)
-		return 1;
-
-	while ((p = strsep(&options, ",")) != NULL) {
-		substring_t args[MAX_OPT_ARGS];
-		int token;
-		if (!*p)
-			continue;
-
-		token = match_token(p, tokens, args);
-		switch (token) {
-		case Opt_uid:
-			if (match_int(args, &option))
-				return 0;
-			*uid = option;
-			break;
-		case Opt_gid:
-			if (match_int(args, &option))
-				return 0;
-			*gid = option;
-			break;
-		default:
-			return 0;
-		}
-	}
-	return 1;
-}
-
 struct inode *proc_get_inode(struct super_block *sb, unsigned int ino,
 				struct proc_dir_entry *de)
 {
@@ -249,10 +203,11 @@
 	 * Fixup the root inode's nlink value
 	 */
 	root_inode->i_nlink += nr_processes();
+	root_inode->i_uid = 0;
+	root_inode->i_gid = 0;
 	s->s_root = d_alloc_root(root_inode);
 	if (!s->s_root)
 		goto out_no_root;
-	parse_options(data, &root_inode->i_uid, &root_inode->i_gid);
 	return 0;
 
 out_no_root:
diff -Nru a/fs/proc/kcore.c b/fs/proc/kcore.c
--- a/fs/proc/kcore.c	2005-03-11 12:51:46 -08:00
+++ b/fs/proc/kcore.c	2005-03-11 12:51:46 -08:00
@@ -84,7 +84,7 @@
 	}
 	*elf_buflen =	sizeof(struct elfhdr) + 
 			(*nphdr + 2)*sizeof(struct elf_phdr) + 
-			3 * sizeof(struct memelfnote) +
+			3 * (sizeof(struct elf_note) + 4) +
 			sizeof(struct elf_prstatus) +
 			sizeof(struct elf_prpsinfo) +
 			sizeof(struct task_struct);
diff -Nru a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
--- a/fs/proc/task_mmu.c	2005-03-11 12:51:41 -08:00
+++ b/fs/proc/task_mmu.c	2005-03-11 12:51:41 -08:00
@@ -77,9 +77,19 @@
 	return result;
 }
 
+static void pad_len_spaces(struct seq_file *m, int len)
+{
+	len = 25 + sizeof(void*) * 6 - len;
+	if (len < 1)
+		len = 1;
+	seq_printf(m, "%*c", len, ' ');
+}
+
 static int show_map(struct seq_file *m, void *v)
 {
+	struct task_struct *task = m->private;
 	struct vm_area_struct *map = v;
+	struct mm_struct *mm = map->vm_mm;
 	struct file *file = map->vm_file;
 	int flags = map->vm_flags;
 	unsigned long ino = 0;
@@ -102,38 +112,93 @@
 			map->vm_pgoff << PAGE_SHIFT,
 			MAJOR(dev), MINOR(dev), ino, &len);
 
+	/*
+	 * Print the dentry name for named mappings, and a
+	 * special [heap] marker for the heap:
+	 */
 	if (map->vm_file) {
-		len = 25 + sizeof(void*) * 6 - len;
-		if (len < 1)
-			len = 1;
-		seq_printf(m, "%*c", len, ' ');
+		pad_len_spaces(m, len);
 		seq_path(m, file->f_vfsmnt, file->f_dentry, "");
+	} else {
+		if (mm) {
+			if (map->vm_start <= mm->start_brk &&
+						map->vm_end >= mm->brk) {
+				pad_len_spaces(m, len);
+				seq_puts(m, "[heap]");
+			} else {
+				if (map->vm_start <= mm->start_stack &&
+					map->vm_end >= mm->start_stack) {
+
+					pad_len_spaces(m, len);
+					seq_puts(m, "[stack]");
+				}
+			}
+		} else {
+			pad_len_spaces(m, len);
+			seq_puts(m, "[vdso]");
+		}
 	}
 	seq_putc(m, '\n');
+	if (m->count < m->size)  /* map is copied successfully */
+		m->version = (map != get_gate_vma(task))? map->vm_start: 0;
 	return 0;
 }
 
 static void *m_start(struct seq_file *m, loff_t *pos)
 {
 	struct task_struct *task = m->private;
-	struct mm_struct *mm = get_task_mm(task);
-	struct vm_area_struct * map;
+	unsigned long last_addr = m->version;
+	struct mm_struct *mm;
+	struct vm_area_struct *map, *tail_map;
 	loff_t l = *pos;
 
+	/*
+	 * We remember last_addr rather than next_addr to hit with
+	 * mmap_cache most of the time. We have zero last_addr at
+	 * the begining and also after lseek. We will have -1 last_addr
+	 * after the end of the maps.
+	 */
+
+	if (last_addr == -1UL)
+		return NULL;
+
+	mm = get_task_mm(task);
 	if (!mm)
 		return NULL;
 
+	tail_map = get_gate_vma(task);
 	down_read(&mm->mmap_sem);
-	map = mm->mmap;
-	while (l-- && map)
+
+	/* Start with last addr hint */
+	if (last_addr && (map = find_vma(mm, last_addr))) {
 		map = map->vm_next;
-	if (!map) {
-		up_read(&mm->mmap_sem);
-		mmput(mm);
-		if (l == -1)
-			map = get_gate_vma(task);
+		goto out;
+	}
+
+	/*
+	 * Check the map index is within the range and do
+	 * sequential scan until m_index.
+	 */
+	map = NULL;
+	if ((unsigned long)l < mm->map_count) {
+		map = mm->mmap;
+		while (l-- && map)
+			map = map->vm_next;
+		goto out;
 	}
-	return map;
+
+	if (l != mm->map_count)
+		tail_map = NULL; /* After gate map */
+
+out:
+	if (map)
+		return map;
+
+	/* End of maps has reached */
+	m->version = (tail_map != NULL)? 0: -1UL;
+	up_read(&mm->mmap_sem);
+	mmput(mm);
+	return tail_map;
 }
 
 static void m_stop(struct seq_file *m, void *v)
@@ -151,13 +216,13 @@
 {
 	struct task_struct *task = m->private;
 	struct vm_area_struct *map = v;
+	struct vm_area_struct *tail_map = get_gate_vma(task);
+
 	(*pos)++;
-	if (map->vm_next)
+	if (map && (map != tail_map) && map->vm_next)
 		return map->vm_next;
 	m_stop(m, v);
-	if (map != get_gate_vma(task))
-		return get_gate_vma(task);
-	return NULL;
+	return (map != tail_map)? tail_map: NULL;
 }
 
 struct seq_operations proc_pid_maps_op = {
diff -Nru a/fs/quota.c b/fs/quota.c
--- a/fs/quota.c	2005-03-11 12:51:51 -08:00
+++ b/fs/quota.c	2005-03-11 12:51:51 -08:00
@@ -16,8 +16,8 @@
 #include <linux/syscalls.h>
 #include <linux/buffer_head.h>
 
-/* Check validity of quotactl */
-static int check_quotactl_valid(struct super_block *sb, int type, int cmd, qid_t id)
+/* Check validity of generic quotactl commands */
+static int generic_quotactl_valid(struct super_block *sb, int type, int cmd, qid_t id)
 {
 	if (type >= MAXQUOTAS)
 		return -EINVAL;
@@ -58,6 +58,48 @@
 			if (sb && !sb->s_qcop->quota_sync)
 				return -ENOSYS;
 			break;
+		default:
+			return -EINVAL;
+	}
+
+	/* Is quota turned on for commands which need it? */
+	switch (cmd) {
+		case Q_GETFMT:
+		case Q_GETINFO:
+		case Q_QUOTAOFF:
+		case Q_SETINFO:
+		case Q_SETQUOTA:
+		case Q_GETQUOTA:
+			/* This is just informative test so we are satisfied without a lock */
+			if (!sb_has_quota_enabled(sb, type))
+				return -ESRCH;
+	}
+
+	/* Check privileges */
+	if (cmd == Q_GETQUOTA) {
+		if (((type == USRQUOTA && current->euid != id) ||
+		     (type == GRPQUOTA && !in_egroup_p(id))) &&
+		    !capable(CAP_SYS_ADMIN))
+			return -EPERM;
+	}
+	else if (cmd != Q_GETFMT && cmd != Q_SYNC && cmd != Q_GETINFO)
+		if (!capable(CAP_SYS_ADMIN))
+			return -EPERM;
+
+	return 0;
+}
+
+/* Check validity of XFS Quota Manager commands */
+static int xqm_quotactl_valid(struct super_block *sb, int type, int cmd, qid_t id)
+{
+	if (type >= XQM_MAXQUOTAS)
+		return -EINVAL;
+	if (!sb)
+		return -ENODEV;
+	if (!sb->s_qcop)
+		return -ENOSYS;
+
+	switch (cmd) {
 		case Q_XQUOTAON:
 		case Q_XQUOTAOFF:
 		case Q_XQUOTARM:
@@ -80,30 +122,31 @@
 			return -EINVAL;
 	}
 
-	/* Is quota turned on for commands which need it? */
-	switch (cmd) {
-		case Q_GETFMT:
-		case Q_GETINFO:
-		case Q_QUOTAOFF:
-		case Q_SETINFO:
-		case Q_SETQUOTA:
-		case Q_GETQUOTA:
-			/* This is just informative test so we are satisfied without a lock */
-			if (!sb_has_quota_enabled(sb, type))
-				return -ESRCH;
-	}
 	/* Check privileges */
-	if (cmd == Q_GETQUOTA || cmd == Q_XGETQUOTA) {
-		if (((type == USRQUOTA && current->euid != id) ||
-		     (type == GRPQUOTA && !in_egroup_p(id))) &&
-		    !capable(CAP_SYS_ADMIN))
+	if (cmd == Q_XGETQUOTA) {
+		if (((type == XQM_USRQUOTA && current->euid != id) ||
+		     (type == XQM_GRPQUOTA && !in_egroup_p(id))) &&
+		     !capable(CAP_SYS_ADMIN))
 			return -EPERM;
-	}
-	else if (cmd != Q_GETFMT && cmd != Q_SYNC && cmd != Q_GETINFO && cmd != Q_XGETQSTAT)
+	} else if (cmd != Q_XGETQSTAT) {
 		if (!capable(CAP_SYS_ADMIN))
 			return -EPERM;
+	}
+
+	return 0;
+}
+
+static int check_quotactl_valid(struct super_block *sb, int type, int cmd, qid_t id)
+{
+	int error;
 
-	return security_quotactl (cmd, type, id, sb);
+	if (XQM_COMMAND(cmd))
+		error = xqm_quotactl_valid(sb, type, cmd, id);
+	else
+		error = generic_quotactl_valid(sb, type, cmd, id);
+	if (!error)
+		error = security_quotactl(cmd, type, id, sb);
+	return error;
 }
 
 static struct super_block *get_super_to_sync(int type)
diff -Nru a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c
--- a/fs/reiserfs/inode.c	2005-03-11 12:51:42 -08:00
+++ b/fs/reiserfs/inode.c	2005-03-11 12:51:42 -08:00
@@ -1843,6 +1843,8 @@
     } else if (inode->i_sb->s_flags & MS_POSIXACL) {
 	reiserfs_warning (inode->i_sb, "ACLs aren't enabled in the fs, "
 			  "but vfs thinks they are!");
+    } else if (is_reiserfs_priv_object (dir)) {
+	reiserfs_mark_inode_private (inode);
     }
 
     insert_inode_hash (inode);
diff -Nru a/fs/reiserfs/namei.c b/fs/reiserfs/namei.c
--- a/fs/reiserfs/namei.c	2005-03-11 12:51:47 -08:00
+++ b/fs/reiserfs/namei.c	2005-03-11 12:51:47 -08:00
@@ -353,7 +353,7 @@
 
 	/* Propogate the priv_object flag so we know we're in the priv tree */
 	if (is_reiserfs_priv_object (dir))
-	    REISERFS_I(inode)->i_flags |= i_priv_object;
+	    reiserfs_mark_inode_private (inode);
     }
     reiserfs_write_unlock(dir->i_sb);
     if ( retval == IO_ERROR ) {
@@ -1255,7 +1255,6 @@
         return retval;
     }
 
-
     /* add new entry (or find the existing one) */
     retval = reiserfs_add_entry (&th, new_dir, new_dentry->d_name.name, new_dentry->d_name.len, 
 				 old_inode, 0);
@@ -1283,8 +1282,13 @@
 
     while (1) {
 	// look for old name using corresponding entry key (found by reiserfs_find_entry)
-	if (search_by_entry_key (new_dir->i_sb, &old_de.de_entry_key, &old_entry_path, &old_de) != NAME_FOUND)
-	    BUG ();
+	if ((retval = search_by_entry_key (new_dir->i_sb, &old_de.de_entry_key,
+					   &old_entry_path, &old_de)) != NAME_FOUND) {
+	    pathrelse(&old_entry_path);
+	    journal_end(&th, old_dir->i_sb, jbegin_count);
+	    reiserfs_write_unlock(old_dir->i_sb);
+	    return -EIO;
+	}
 
 	copy_item_head(&old_entry_ih, get_ih(&old_entry_path)) ;
 
@@ -1296,16 +1300,28 @@
 				      &new_entry_path, &new_de);
 	// reiserfs_add_entry should not return IO_ERROR, because it is called with essentially same parameters from
         // reiserfs_add_entry above, and we'll catch any i/o errors before we get here.
-	if (retval != NAME_FOUND_INVISIBLE && retval != NAME_FOUND)
-	    BUG ();
+	if (retval != NAME_FOUND_INVISIBLE && retval != NAME_FOUND) {
+	    pathrelse(&new_entry_path);
+	    pathrelse(&old_entry_path);
+	    journal_end(&th, old_dir->i_sb, jbegin_count);
+	    reiserfs_write_unlock(old_dir->i_sb);
+	    return -EIO;
+	}
 
 	copy_item_head(&new_entry_ih, get_ih(&new_entry_path)) ;
 
 	reiserfs_prepare_for_journal(old_inode->i_sb, new_de.de_bh, 1) ;
 
 	if (S_ISDIR(old_inode->i_mode)) {
-	    if (search_by_entry_key (new_dir->i_sb, &dot_dot_de.de_entry_key, &dot_dot_entry_path, &dot_dot_de) != NAME_FOUND)
-		BUG ();
+	    if ((retval = search_by_entry_key (new_dir->i_sb, &dot_dot_de.de_entry_key,
+					       &dot_dot_entry_path, &dot_dot_de)) != NAME_FOUND) {
+		pathrelse(&dot_dot_entry_path);
+		pathrelse(&new_entry_path);
+		pathrelse(&old_entry_path);
+		journal_end(&th, old_dir->i_sb, jbegin_count);
+		reiserfs_write_unlock(old_dir->i_sb);
+		return -EIO;
+	    }
 	    copy_item_head(&dot_dot_ih, get_ih(&dot_dot_entry_path)) ;
 	    // node containing ".." gets into transaction
 	    reiserfs_prepare_for_journal(old_inode->i_sb, dot_dot_de.de_bh, 1) ;
diff -Nru a/fs/reiserfs/xattr.c b/fs/reiserfs/xattr.c
--- a/fs/reiserfs/xattr.c	2005-03-11 12:51:51 -08:00
+++ b/fs/reiserfs/xattr.c	2005-03-11 12:51:51 -08:00
@@ -181,8 +181,6 @@
             dput (xadir);
             return ERR_PTR (-ENODATA);
         }
-        /* Newly created object.. Need to mark it private */
-        REISERFS_I(xadir->d_inode)->i_flags |= i_priv_object;
     }
 
     dput (xaroot);
@@ -230,8 +228,6 @@
             dput (xafile);
             goto out;
         }
-        /* Newly created object.. Need to mark it private */
-        REISERFS_I(xafile->d_inode)->i_flags |= i_priv_object;
     }
 
 out:
@@ -1316,7 +1312,7 @@
 
       if (!err && dentry) {
           s->s_root->d_op = &xattr_lookup_poison_ops;
-          REISERFS_I(dentry->d_inode)->i_flags |= i_priv_object;
+          reiserfs_mark_inode_private (dentry->d_inode);
           REISERFS_SB(s)->priv_root = dentry;
       } else if (!(mount_flags & MS_RDONLY)) { /* xattrs are unavailable */
           /* If we're read-only it just means that the dir hasn't been
diff -Nru a/fs/reiserfs/xattr_acl.c b/fs/reiserfs/xattr_acl.c
--- a/fs/reiserfs/xattr_acl.c	2005-03-11 12:51:48 -08:00
+++ b/fs/reiserfs/xattr_acl.c	2005-03-11 12:51:48 -08:00
@@ -339,7 +339,7 @@
      * would be useless since permissions are ignored, and a pain because
      * it introduces locking cycles */
     if (is_reiserfs_priv_object (dir)) {
-        REISERFS_I(inode)->i_flags |= i_priv_object;
+        reiserfs_mark_inode_private (inode);
         goto apply_umask;
     }
 
diff -Nru a/fs/seq_file.c b/fs/seq_file.c
--- a/fs/seq_file.c	2005-03-11 12:51:47 -08:00
+++ b/fs/seq_file.c	2005-03-11 12:51:47 -08:00
@@ -36,6 +36,13 @@
 	p->op = op;
 	file->private_data = p;
 
+	/*
+	 * Wrappers around seq_open(e.g. swaps_open) need to be
+	 * aware of this. If they set f_version themselves, they
+	 * should call seq_open first and then set f_version.
+	 */
+	file->f_version = 0;
+
 	/* SEQ files support lseek, but not pread/pwrite */
 	file->f_mode &= ~(FMODE_PREAD | FMODE_PWRITE);
 	return 0;
@@ -58,6 +65,18 @@
 	int err = 0;
 
 	down(&m->sem);
+	/*
+	 * seq_file->op->..m_start/m_stop/m_next may do special actions
+	 * or optimisations based on the file->f_version, so we want to
+	 * pass the file->f_version to those methods.
+	 *
+	 * seq_file->version is just copy of f_version, and seq_file
+	 * methods can treat it simply as file version.
+	 * It is copied in first and copied out after all operations.
+	 * It is convenient to have it as  part of structure to avoid the
+	 * need of passing another argument to all the seq_file methods.
+	 */
+	m->version = file->f_version;
 	/* grab buffer if we didn't have one */
 	if (!m->buf) {
 		m->buf = kmalloc(m->size = PAGE_SIZE, GFP_KERNEL);
@@ -98,6 +117,7 @@
 		if (!m->buf)
 			goto Enomem;
 		m->count = 0;
+		m->version = 0;
 	}
 	m->op->stop(m, p);
 	m->count = 0;
@@ -136,6 +156,7 @@
 		copied = err;
 	else
 		*ppos += copied;
+	file->f_version = m->version;
 	up(&m->sem);
 	return copied;
 Enomem:
@@ -153,6 +174,7 @@
 	int error = 0;
 	void *p;
 
+	m->version = 0;
 	m->index = 0;
 	m->count = m->from = 0;
 	if (!offset)
@@ -207,6 +229,7 @@
 	long long retval = -EINVAL;
 
 	down(&m->sem);
+	m->version = file->f_version;
 	switch (origin) {
 		case 1:
 			offset += file->f_pos;
@@ -220,6 +243,7 @@
 				if (retval) {
 					/* with extreme prejudice... */
 					file->f_pos = 0;
+					m->version = 0;
 					m->index = 0;
 					m->count = 0;
 				} else {
@@ -228,6 +252,7 @@
 			}
 	}
 	up(&m->sem);
+	file->f_version = m->version;
 	return retval;
 }
 EXPORT_SYMBOL(seq_lseek);
diff -Nru a/fs/sysfs/inode.c b/fs/sysfs/inode.c
--- a/fs/sysfs/inode.c	2005-03-11 12:51:51 -08:00
+++ b/fs/sysfs/inode.c	2005-03-11 12:51:51 -08:00
@@ -129,13 +129,17 @@
 
 	if (dentry) {
 		spin_lock(&dcache_lock);
+		spin_lock(&dentry->d_lock);
 		if (!(d_unhashed(dentry) && dentry->d_inode)) {
 			dget_locked(dentry);
 			__d_drop(dentry);
+			spin_unlock(&dentry->d_lock);
 			spin_unlock(&dcache_lock);
 			simple_unlink(parent->d_inode, dentry);
-		} else
+		} else {
+			spin_unlock(&dentry->d_lock);
 			spin_unlock(&dcache_lock);
+		}
 	}
 }
 
diff -Nru a/fs/ufs/super.c b/fs/ufs/super.c
--- a/fs/ufs/super.c	2005-03-11 12:51:40 -08:00
+++ b/fs/ufs/super.c	2005-03-11 12:51:40 -08:00
@@ -1196,6 +1196,11 @@
 		printk(KERN_INFO "ufs_inode_cache: not all structures were freed\n");
 }
 
+#ifdef CONFIG_QUOTA
+static ssize_t ufs_quota_read(struct super_block *, int, char *,size_t, loff_t);
+static ssize_t ufs_quota_write(struct super_block *, int, const char *, size_t, loff_t);
+#endif
+
 static struct super_operations ufs_super_ops = {
 	.alloc_inode	= ufs_alloc_inode,
 	.destroy_inode	= ufs_destroy_inode,
@@ -1206,7 +1211,101 @@
 	.write_super	= ufs_write_super,
 	.statfs		= ufs_statfs,
 	.remount_fs	= ufs_remount,
+#ifdef CONFIG_QUOTA
+	.quota_read	= ufs_quota_read,
+	.quota_write	= ufs_quota_write,
+#endif
 };
+
+#ifdef CONFIG_QUOTA
+
+/* Read data from quotafile - avoid pagecache and such because we cannot afford
+ * acquiring the locks... As quota files are never truncated and quota code
+ * itself serializes the operations (and noone else should touch the files)
+ * we don't have to be afraid of races */
+static ssize_t ufs_quota_read(struct super_block *sb, int type, char *data,
+			       size_t len, loff_t off)
+{
+	struct inode *inode = sb_dqopt(sb)->files[type];
+	sector_t blk = off >> sb->s_blocksize_bits;
+	int err = 0;
+	int offset = off & (sb->s_blocksize - 1);
+	int tocopy;
+	size_t toread;
+	struct buffer_head *bh;
+	loff_t i_size = i_size_read(inode);
+
+	if (off > i_size)
+		return 0;
+	if (off+len > i_size)
+		len = i_size-off;
+	toread = len;
+	while (toread > 0) {
+		tocopy = sb->s_blocksize - offset < toread ?
+				sb->s_blocksize - offset : toread;
+
+		bh = ufs_bread(inode, blk, 0, &err);
+		if (err)
+			return err;
+		if (!bh)	/* A hole? */
+			memset(data, 0, tocopy);
+		else {
+			memcpy(data, bh->b_data+offset, tocopy);
+			brelse(bh);
+		}
+		offset = 0;
+		toread -= tocopy;
+		data += tocopy;
+		blk++;
+	}
+	return len;
+}
+
+/* Write to quotafile */
+static ssize_t ufs_quota_write(struct super_block *sb, int type,
+				const char *data, size_t len, loff_t off)
+{
+	struct inode *inode = sb_dqopt(sb)->files[type];
+	sector_t blk = off >> sb->s_blocksize_bits;
+	int err = 0;
+	int offset = off & (sb->s_blocksize - 1);
+	int tocopy;
+	size_t towrite = len;
+	struct buffer_head *bh;
+
+	down(&inode->i_sem);
+	while (towrite > 0) {
+		tocopy = sb->s_blocksize - offset < towrite ?
+				sb->s_blocksize - offset : towrite;
+
+		bh = ufs_bread(inode, blk, 1, &err);
+		if (!bh)
+			goto out;
+		lock_buffer(bh);
+		memcpy(bh->b_data+offset, data, tocopy);
+		flush_dcache_page(bh->b_page);
+		set_buffer_uptodate(bh);
+		mark_buffer_dirty(bh);
+		unlock_buffer(bh);
+		brelse(bh);
+		offset = 0;
+		towrite -= tocopy;
+		data += tocopy;
+		blk++;
+	}
+out:
+	if (len == towrite)
+		return err;
+	if (inode->i_size < off+len-towrite)
+		i_size_write(inode, off+len-towrite);
+	inode->i_version++;
+	inode->i_mtime = inode->i_ctime = CURRENT_TIME_SEC;
+	mark_inode_dirty(inode);
+	up(&inode->i_sem);
+	return len - towrite;
+}
+
+#endif
 
 static struct super_block *ufs_get_sb(struct file_system_type *fs_type,
 	int flags, const char *dev_name, void *data)
diff -Nru a/fs/vfat/namei.c b/fs/vfat/namei.c
--- a/fs/vfat/namei.c	2005-03-11 12:51:47 -08:00
+++ b/fs/vfat/namei.c	2005-03-11 12:51:47 -08:00
@@ -208,15 +208,11 @@
 
 static int vfat_find_form(struct inode *dir, unsigned char *name)
 {
-	struct msdos_dir_entry *de;
-	struct buffer_head *bh = NULL;
-	loff_t i_pos;
-	int res;
-
-	res = fat_scan(dir, name, &bh, &de, &i_pos);
-	brelse(bh);
-	if (res < 0)
+	struct fat_slot_info sinfo;
+	int err = fat_scan(dir, name, &sinfo);
+	if (err)
 		return -ENOENT;
+	brelse(sinfo.bh);
 	return 0;
 }
 
@@ -305,6 +301,7 @@
 				 wchar_t *uname, int ulen,
 				 unsigned char *name_res, unsigned char *lcase)
 {
+	struct fat_mount_options *opts = &MSDOS_SB(dir->i_sb)->options;
 	wchar_t *ip, *ext_start, *end, *name_start;
 	unsigned char base[9], ext[4], buf[8], *p;
 	unsigned char charbuf[NLS_MAX_CHARSET_SIZE];
@@ -312,7 +309,6 @@
 	int sz = 0, extlen, baselen, i, numtail_baselen, numtail2_baselen;
 	int is_shortname;
 	struct shortname_info base_info, ext_info;
-	unsigned short opt_shortname = MSDOS_SB(dir->i_sb)->options.shortname;
 
 	is_shortname = 1;
 	INIT_SHORTNAME_INFO(&base_info);
@@ -425,9 +421,9 @@
 		if (vfat_find_form(dir, name_res) == 0)
 			return -EEXIST;
 
-		if (opt_shortname & VFAT_SFN_CREATE_WIN95) {
+		if (opts->shortname & VFAT_SFN_CREATE_WIN95) {
 			return (base_info.upper && ext_info.upper);
-		} else if (opt_shortname & VFAT_SFN_CREATE_WINNT) {
+		} else if (opts->shortname & VFAT_SFN_CREATE_WINNT) {
 			if ((base_info.upper || base_info.lower) &&
 			    (ext_info.upper || ext_info.lower)) {
 				if (!base_info.upper && base_info.lower)
@@ -442,7 +438,7 @@
 		}
 	}
 
-	if (MSDOS_SB(dir->i_sb)->options.numtail == 0)
+	if (opts->numtail == 0)
 		if (vfat_find_form(dir, name_res) < 0)
 			return 0;
 
@@ -579,8 +575,9 @@
 }
 
 static int vfat_build_slots(struct inode *dir, const unsigned char *name,
-			    int len, struct msdos_dir_slot *ds,
-			    int *slots, int is_dir)
+			    int len, int is_dir, int cluster,
+			    struct timespec *ts,
+			    struct msdos_dir_slot *slots, int *nr_slots)
 {
 	struct msdos_sb_info *sbi = MSDOS_SB(dir->i_sb);
 	struct fat_mount_options *opts = &sbi->options;
@@ -590,193 +587,144 @@
 	unsigned char cksum, lcase;
 	unsigned char msdos_name[MSDOS_NAME];
 	wchar_t *uname;
-	int res, slot, ulen, usize, i;
+	__le16 time, date;
+	int err, ulen, usize, i;
 	loff_t offset;
 
-	*slots = 0;
-	res = vfat_valid_longname(name, len);
-	if (res)
-		return res;
+	*nr_slots = 0;
+	err = vfat_valid_longname(name, len);
+	if (err)
+		return err;
 
 	page = __get_free_page(GFP_KERNEL);
 	if (!page)
 		return -ENOMEM;
 
 	uname = (wchar_t *)page;
-	res = xlate_to_uni(name, len, (unsigned char *)uname, &ulen, &usize,
+	err = xlate_to_uni(name, len, (unsigned char *)uname, &ulen, &usize,
 			   opts->unicode_xlate, opts->utf8, sbi->nls_io);
-	if (res < 0)
+	if (err)
 		goto out_free;
 
-	res = vfat_is_used_badchars(uname, ulen);
-	if (res < 0)
+	err = vfat_is_used_badchars(uname, ulen);
+	if (err)
 		goto out_free;
 
-	res = vfat_create_shortname(dir, sbi->nls_disk, uname, ulen,
+	err = vfat_create_shortname(dir, sbi->nls_disk, uname, ulen,
 				    msdos_name, &lcase);
-	if (res < 0)
+	if (err < 0)
 		goto out_free;
-	else if (res == 1) {
-		de = (struct msdos_dir_entry *)ds;
-		res = 0;
+	else if (err == 1) {
+		de = (struct msdos_dir_entry *)slots;
+		err = 0;
 		goto shortname;
 	}
 
 	/* build the entry of long file name */
-	*slots = usize / 13;
 	for (cksum = i = 0; i < 11; i++)
 		cksum = (((cksum&1)<<7)|((cksum&0xfe)>>1)) + msdos_name[i];
 
-	for (ps = ds, slot = *slots; slot > 0; slot--, ps++) {
-		ps->id = slot;
+	*nr_slots = usize / 13;
+	for (ps = slots, i = *nr_slots; i > 0; i--, ps++) {
+		ps->id = i;
 		ps->attr = ATTR_EXT;
 		ps->reserved = 0;
 		ps->alias_checksum = cksum;
 		ps->start = 0;
-		offset = (slot - 1) * 13;
+		offset = (i - 1) * 13;
 		fatwchar_to16(ps->name0_4, uname + offset, 5);
 		fatwchar_to16(ps->name5_10, uname + offset + 5, 6);
 		fatwchar_to16(ps->name11_12, uname + offset + 11, 2);
 	}
-	ds[0].id |= 0x40;
+	slots[0].id |= 0x40;
 	de = (struct msdos_dir_entry *)ps;
 
 shortname:
 	/* build the entry of 8.3 alias name */
-	(*slots)++;
+	(*nr_slots)++;
 	memcpy(de->name, msdos_name, MSDOS_NAME);
 	de->attr = is_dir ? ATTR_DIR : ATTR_ARCH;
 	de->lcase = lcase;
-	de->adate = de->cdate = de->date = 0;
-	de->ctime = de->time = 0;
-	de->ctime_ms = 0;
-	de->start = 0;
-	de->starthi = 0;
+	fat_date_unix2dos(ts->tv_sec, &time, &date);
+	de->time = de->ctime = time;
+	de->date = de->cdate = de->adate = date;
+	de->ctime_cs = 0;
+	de->start = cpu_to_le16(cluster);
+	de->starthi = cpu_to_le16(cluster >> 16);
 	de->size = 0;
-
 out_free:
 	free_page(page);
-	return res;
+	return err;
 }
 
-static int vfat_add_entry(struct inode *dir, struct qstr *qname,
-			  int is_dir, struct vfat_slot_info *sinfo_out,
-			  struct buffer_head **bh, struct msdos_dir_entry **de)
+static int vfat_add_entry(struct inode *dir, struct qstr *qname, int is_dir,
+			  int cluster, struct timespec *ts,
+			  struct fat_slot_info *sinfo)
 {
-	struct msdos_dir_slot *dir_slots;
-	loff_t offset;
-	int res, slots, slot;
+	struct msdos_dir_slot *slots;
 	unsigned int len;
-	struct msdos_dir_entry *dummy_de;
-	struct buffer_head *dummy_bh;
-	loff_t dummy_i_pos;
+	int err, nr_slots;
 
 	len = vfat_striptail_len(qname);
 	if (len == 0)
 		return -ENOENT;
 
-	dir_slots = kmalloc(sizeof(*dir_slots) * MSDOS_SLOTS, GFP_KERNEL);
-	if (dir_slots == NULL)
+	slots = kmalloc(sizeof(*slots) * MSDOS_SLOTS, GFP_KERNEL);
+	if (slots == NULL)
 		return -ENOMEM;
 
-	res = vfat_build_slots(dir, qname->name, len,
-			       dir_slots, &slots, is_dir);
-	if (res < 0)
+	err = vfat_build_slots(dir, qname->name, len, is_dir, cluster, ts,
+			       slots, &nr_slots);
+	if (err)
 		goto cleanup;
 
-	/* build the empty directory entry of number of slots */
-	offset =
-	    fat_add_entries(dir, slots, &dummy_bh, &dummy_de, &dummy_i_pos);
-	if (offset < 0) {
-		res = offset;
+	err = fat_add_entries(dir, slots, nr_slots, sinfo);
+	if (err)
 		goto cleanup;
-	}
-	brelse(dummy_bh);
-
-	/* Now create the new entry */
-	*bh = NULL;
-	for (slot = 0; slot < slots; slot++) {
-		if (fat_get_entry(dir, &offset, bh, de, &sinfo_out->i_pos) < 0) {
-			res = -EIO;
-			goto cleanup;
-		}
-		memcpy(*de, dir_slots + slot, sizeof(struct msdos_dir_slot));
-		mark_buffer_dirty(*bh);
-	}
 
-	res = 0;
 	/* update timestamp */
-	dir->i_ctime = dir->i_mtime = dir->i_atime = CURRENT_TIME_SEC;
-	mark_inode_dirty(dir);
-
-	fat_date_unix2dos(dir->i_mtime.tv_sec, &(*de)->time, &(*de)->date);
-	dir->i_mtime.tv_nsec = 0;
-	(*de)->ctime = (*de)->time;
-	(*de)->adate = (*de)->cdate = (*de)->date;
-
-	mark_buffer_dirty(*bh);
-
-	/* slots can't be less than 1 */
-	sinfo_out->long_slots = slots - 1;
-	sinfo_out->longname_offset =
-		offset - sizeof(struct msdos_dir_slot) * slots;
-
+	dir->i_ctime = dir->i_mtime = dir->i_atime = *ts;
+	if (IS_DIRSYNC(dir))
+		(void)fat_sync_inode(dir);
+	else
+		mark_inode_dirty(dir);
 cleanup:
-	kfree(dir_slots);
-	return res;
+	kfree(slots);
+	return err;
 }
 
 static int vfat_find(struct inode *dir, struct qstr *qname,
-		     struct vfat_slot_info *sinfo, struct buffer_head **last_bh,
-		     struct msdos_dir_entry **last_de)
+		     struct fat_slot_info *sinfo)
 {
-	struct super_block *sb = dir->i_sb;
-	loff_t offset;
-	unsigned int len;
-	int res;
-
-	len = vfat_striptail_len(qname);
+	unsigned int len = vfat_striptail_len(qname);
 	if (len == 0)
 		return -ENOENT;
-
-	res = fat_search_long(dir, qname->name, len,
-			      (MSDOS_SB(sb)->options.name_check != 's'),
-			      &offset, &sinfo->longname_offset);
-	if (res > 0) {
-		sinfo->long_slots = res - 1;
-		if (fat_get_entry(dir, &offset, last_bh, last_de, &sinfo->i_pos) >= 0)
-			return 0;
-		res = -EIO;
-	}
-	return res ? res : -ENOENT;
+	return fat_search_long(dir, qname->name, len, sinfo);
 }
 
 static struct dentry *vfat_lookup(struct inode *dir, struct dentry *dentry,
 				  struct nameidata *nd)
 {
-	int res;
-	struct vfat_slot_info sinfo;
-	struct inode *inode;
+	struct super_block *sb = dir->i_sb;
+	struct fat_slot_info sinfo;
+	struct inode *inode = NULL;
 	struct dentry *alias;
-	struct buffer_head *bh = NULL;
-	struct msdos_dir_entry *de;
-	int table;
+	int err, table;
 
 	lock_kernel();
-	table = (MSDOS_SB(dir->i_sb)->options.name_check == 's') ? 2 : 0;
+	table = (MSDOS_SB(sb)->options.name_check == 's') ? 2 : 0;
 	dentry->d_op = &vfat_dentry_ops[table];
 
-	inode = NULL;
-	res = vfat_find(dir, &dentry->d_name, &sinfo, &bh, &de);
-	if (res < 0) {
+	err = vfat_find(dir, &dentry->d_name, &sinfo);
+	if (err) {
 		table++;
 		goto error;
 	}
-	inode = fat_build_inode(dir->i_sb, de, sinfo.i_pos, &res);
-	brelse(bh);
-	if (res) {
+	inode = fat_build_inode(sb, sinfo.de, sinfo.i_pos);
+	brelse(sinfo.bh);
+	if (IS_ERR(inode)) {
 		unlock_kernel();
-		return ERR_PTR(res);
+		return ERR_PTR(PTR_ERR(inode));
 	}
 	alias = d_find_alias(inode);
 	if (alias) {
@@ -805,245 +753,274 @@
 		       struct nameidata *nd)
 {
 	struct super_block *sb = dir->i_sb;
-	struct inode *inode = NULL;
-	struct buffer_head *bh = NULL;
-	struct msdos_dir_entry *de;
-	struct vfat_slot_info sinfo;
-	int res;
+	struct inode *inode;
+	struct fat_slot_info sinfo;
+	struct timespec ts;
+	int err;
 
 	lock_kernel();
-	res = vfat_add_entry(dir, &dentry->d_name, 0, &sinfo, &bh, &de);
-	if (res < 0)
+
+	ts = CURRENT_TIME_SEC;
+	err = vfat_add_entry(dir, &dentry->d_name, 0, 0, &ts, &sinfo);
+	if (err)
 		goto out;
-	inode = fat_build_inode(sb, de, sinfo.i_pos, &res);
-	brelse(bh);
-	if (!inode)
+	dir->i_version++;
+
+	inode = fat_build_inode(sb, sinfo.de, sinfo.i_pos);
+	brelse(sinfo.bh);
+	if (IS_ERR(inode)) {
+		err = PTR_ERR(inode);
 		goto out;
-	res = 0;
-	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC;
-	mark_inode_dirty(inode);
+	}
 	inode->i_version++;
-	dir->i_version++;
+	inode->i_mtime = inode->i_atime = inode->i_ctime = ts;
+	/* timestamp is already written, so mark_inode_dirty() is unneeded. */
+
 	dentry->d_time = dentry->d_parent->d_inode->i_version;
 	d_instantiate(dentry, inode);
 out:
 	unlock_kernel();
-	return res;
-}
-
-static void vfat_remove_entry(struct inode *dir, struct vfat_slot_info *sinfo,
-			      struct buffer_head *bh,
-			      struct msdos_dir_entry *de)
-{
-	loff_t offset, i_pos;
-	int i;
-
-	/* remove the shortname */
-	dir->i_mtime = dir->i_atime = CURRENT_TIME_SEC;
-	dir->i_version++;
-	mark_inode_dirty(dir);
-	de->name[0] = DELETED_FLAG;
-	mark_buffer_dirty(bh);
-	/* remove the longname */
-	offset = sinfo->longname_offset;
-	de = NULL;
-	for (i = sinfo->long_slots; i > 0; --i) {
-		if (fat_get_entry(dir, &offset, &bh, &de, &i_pos) < 0)
-			continue;
-		de->name[0] = DELETED_FLAG;
-		de->attr = ATTR_NONE;
-		mark_buffer_dirty(bh);
-	}
-	brelse(bh);
+	return err;
 }
 
 static int vfat_rmdir(struct inode *dir, struct dentry *dentry)
 {
 	struct inode *inode = dentry->d_inode;
-	struct vfat_slot_info sinfo;
-	struct buffer_head *bh = NULL;
-	struct msdos_dir_entry *de;
-	int res;
+	struct fat_slot_info sinfo;
+	int err;
 
 	lock_kernel();
-	res = fat_dir_empty(inode);
-	if (res)
+
+	err = fat_dir_empty(inode);
+	if (err)
+		goto out;
+	err = vfat_find(dir, &dentry->d_name, &sinfo);
+	if (err)
 		goto out;
 
-	res = vfat_find(dir, &dentry->d_name, &sinfo, &bh, &de);
-	if (res < 0)
+	err = fat_remove_entries(dir, &sinfo);	/* and releases bh */
+	if (err)
 		goto out;
+	dir->i_nlink--;
 
-	res = 0;
 	inode->i_nlink = 0;
 	inode->i_mtime = inode->i_atime = CURRENT_TIME_SEC;
 	fat_detach(inode);
-	mark_inode_dirty(inode);
-	/* releases bh */
-	vfat_remove_entry(dir, &sinfo, bh, de);
-	dir->i_nlink--;
 out:
 	unlock_kernel();
-	return res;
+
+	return err;
 }
 
 static int vfat_unlink(struct inode *dir, struct dentry *dentry)
 {
 	struct inode *inode = dentry->d_inode;
-	struct vfat_slot_info sinfo;
-	struct buffer_head *bh = NULL;
-	struct msdos_dir_entry *de;
-	int res;
+	struct fat_slot_info sinfo;
+	int err;
 
 	lock_kernel();
-	res = vfat_find(dir, &dentry->d_name, &sinfo, &bh, &de);
-	if (res < 0)
+
+	err = vfat_find(dir, &dentry->d_name, &sinfo);
+	if (err)
+		goto out;
+
+	err = fat_remove_entries(dir, &sinfo);	/* and releases bh */
+	if (err)
 		goto out;
 	inode->i_nlink = 0;
 	inode->i_mtime = inode->i_atime = CURRENT_TIME_SEC;
 	fat_detach(inode);
-	mark_inode_dirty(inode);
-	/* releases bh */
-	vfat_remove_entry(dir, &sinfo, bh, de);
 out:
 	unlock_kernel();
 
-	return res;
+	return err;
 }
 
 static int vfat_mkdir(struct inode *dir, struct dentry *dentry, int mode)
 {
 	struct super_block *sb = dir->i_sb;
-	struct inode *inode = NULL;
-	struct vfat_slot_info sinfo;
-	struct buffer_head *bh = NULL;
-	struct msdos_dir_entry *de;
-	int res;
+	struct inode *inode;
+	struct fat_slot_info sinfo;
+	struct timespec ts;
+	int err, cluster;
 
 	lock_kernel();
-	res = vfat_add_entry(dir, &dentry->d_name, 1, &sinfo, &bh, &de);
-	if (res < 0)
+
+	ts = CURRENT_TIME_SEC;
+	cluster = fat_alloc_new_dir(dir, &ts);
+	if (cluster < 0) {
+		err = cluster;
 		goto out;
-	inode = fat_build_inode(sb, de, sinfo.i_pos, &res);
-	if (!inode)
-		goto out_brelse;
-	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC;
-	mark_inode_dirty(inode);
-	inode->i_version++;
+	}
+	err = vfat_add_entry(dir, &dentry->d_name, 1, cluster, &ts, &sinfo);
+	if (err)
+		goto out_free;
 	dir->i_version++;
 	dir->i_nlink++;
-	inode->i_nlink = 2;	/* no need to mark them dirty */
-	res = fat_new_dir(inode, dir, 1);
-	if (res < 0)
-		goto mkdir_failed;
+
+	inode = fat_build_inode(sb, sinfo.de, sinfo.i_pos);
+	brelse(sinfo.bh);
+	if (IS_ERR(inode)) {
+		err = PTR_ERR(inode);
+		/* the directory was completed, just return a error */
+		goto out;
+	}
+	inode->i_version++;
+	inode->i_nlink = 2;
+	inode->i_mtime = inode->i_atime = inode->i_ctime = ts;
+	/* timestamp is already written, so mark_inode_dirty() is unneeded. */
+
 	dentry->d_time = dentry->d_parent->d_inode->i_version;
 	d_instantiate(dentry, inode);
-out_brelse:
-	brelse(bh);
-out:
+
 	unlock_kernel();
-	return res;
+	return 0;
 
-mkdir_failed:
-	inode->i_nlink = 0;
-	inode->i_mtime = inode->i_atime = CURRENT_TIME_SEC;
-	fat_detach(inode);
-	mark_inode_dirty(inode);
-	/* releases bh */
-	vfat_remove_entry(dir, &sinfo, bh, de);
-	iput(inode);
-	dir->i_nlink--;
-	goto out;
+out_free:
+	fat_free_clusters(dir, cluster);
+out:
+	unlock_kernel();
+	return err;
 }
 
 static int vfat_rename(struct inode *old_dir, struct dentry *old_dentry,
 		       struct inode *new_dir, struct dentry *new_dentry)
 {
-	struct buffer_head *old_bh, *new_bh, *dotdot_bh;
-	struct msdos_dir_entry *old_de, *new_de, *dotdot_de;
+	struct buffer_head *dotdot_bh;
+	struct msdos_dir_entry *dotdot_de;
 	loff_t dotdot_i_pos;
 	struct inode *old_inode, *new_inode;
-	int res, is_dir;
-	struct vfat_slot_info old_sinfo, sinfo;
+	struct fat_slot_info old_sinfo, sinfo;
+	struct timespec ts;
+	int err, is_dir, update_dotdot, corrupt = 0;
 
-	old_bh = new_bh = dotdot_bh = NULL;
+	old_sinfo.bh = sinfo.bh = dotdot_bh = NULL;
 	old_inode = old_dentry->d_inode;
 	new_inode = new_dentry->d_inode;
 	lock_kernel();
-	res = vfat_find(old_dir, &old_dentry->d_name, &old_sinfo, &old_bh,
-			&old_de);
-	if (res < 0)
-		goto rename_done;
+	err = vfat_find(old_dir, &old_dentry->d_name, &old_sinfo);
+	if (err)
+		goto out;
 
 	is_dir = S_ISDIR(old_inode->i_mode);
-
-	if (is_dir) {
-		if (fat_scan(old_inode, MSDOS_DOTDOT, &dotdot_bh,
-			     &dotdot_de, &dotdot_i_pos) < 0) {
-			res = -EIO;
-			goto rename_done;
+	update_dotdot = (is_dir && old_dir != new_dir);
+	if (update_dotdot) {
+		if (fat_get_dotdot_entry(old_inode, &dotdot_bh, &dotdot_de,
+					 &dotdot_i_pos) < 0) {
+			err = -EIO;
+			goto out;
 		}
 	}
 
-	if (new_dentry->d_inode) {
-		res = vfat_find(new_dir, &new_dentry->d_name, &sinfo, &new_bh,
-				&new_de);
-		if (res < 0 || MSDOS_I(new_inode)->i_pos != sinfo.i_pos) {
+	ts = CURRENT_TIME_SEC;
+	if (new_inode) {
+		err = vfat_find(new_dir, &new_dentry->d_name, &sinfo);
+		if (err)
+			goto out;
+		if (MSDOS_I(new_inode)->i_pos != sinfo.i_pos) {
 			/* WTF??? Cry and fail. */
 			printk(KERN_WARNING "vfat_rename: fs corrupted\n");
-			goto rename_done;
+			goto out;
 		}
 
 		if (is_dir) {
-			res = fat_dir_empty(new_inode);
-			if (res)
-				goto rename_done;
+			err = fat_dir_empty(new_inode);
+			if (err)
+				goto out;
 		}
 		fat_detach(new_inode);
 	} else {
-		res = vfat_add_entry(new_dir, &new_dentry->d_name, is_dir,
-				     &sinfo, &new_bh, &new_de);
-		if (res < 0)
-			goto rename_done;
+		err = vfat_add_entry(new_dir, &new_dentry->d_name, is_dir, 0,
+				     &ts, &sinfo);
+		if (err)
+			goto out;
 	}
-
 	new_dir->i_version++;
 
-	/* releases old_bh */
-	vfat_remove_entry(old_dir, &old_sinfo, old_bh, old_de);
-	old_bh = NULL;
 	fat_detach(old_inode);
 	fat_attach(old_inode, sinfo.i_pos);
-	mark_inode_dirty(old_inode);
-
-	old_dir->i_version++;
-	old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME_SEC;
-	mark_inode_dirty(old_dir);
-	if (new_inode) {
-		new_inode->i_nlink--;
-		new_inode->i_ctime = CURRENT_TIME_SEC;
-	}
+	if (IS_DIRSYNC(new_dir)) {
+		err = fat_sync_inode(old_inode);
+		if (err)
+			goto error_inode;
+	} else
+		mark_inode_dirty(old_inode);
 
-	if (is_dir) {
+	if (update_dotdot) {
 		int start = MSDOS_I(new_dir)->i_logstart;
 		dotdot_de->start = cpu_to_le16(start);
-		dotdot_de->starthi = cpu_to_le16(start>>16);
+		dotdot_de->starthi = cpu_to_le16(start >> 16);
 		mark_buffer_dirty(dotdot_bh);
-		old_dir->i_nlink--;
-		if (new_inode) {
-			new_inode->i_nlink--;
-		} else {
-			new_dir->i_nlink++;
-			mark_inode_dirty(new_dir);
+		if (IS_DIRSYNC(new_dir)) {
+			err = sync_dirty_buffer(dotdot_bh);
+			if (err)
+				goto error_dotdot;
 		}
+		old_dir->i_nlink--;
+		if (!new_inode)
+ 			new_dir->i_nlink++;
 	}
 
-rename_done:
+	err = fat_remove_entries(old_dir, &old_sinfo);	/* and releases bh */
+	old_sinfo.bh = NULL;
+	if (err)
+		goto error_dotdot;
+	old_dir->i_version++;
+	old_dir->i_ctime = old_dir->i_mtime = ts;
+	if (IS_DIRSYNC(old_dir))
+		(void)fat_sync_inode(old_dir);
+	else
+		mark_inode_dirty(old_dir);
+
+	if (new_inode) {
+		if (is_dir)
+			new_inode->i_nlink -= 2;
+		else
+			new_inode->i_nlink--;
+		new_inode->i_ctime = ts;
+	}
+out:
+	brelse(sinfo.bh);
 	brelse(dotdot_bh);
-	brelse(old_bh);
-	brelse(new_bh);
+	brelse(old_sinfo.bh);
 	unlock_kernel();
-	return res;
+
+	return err;
+
+error_dotdot:
+	/* data cluster is shared, serious corruption */
+	corrupt = 1;
+
+	if (update_dotdot) {
+		int start = MSDOS_I(old_dir)->i_logstart;
+		dotdot_de->start = cpu_to_le16(start);
+		dotdot_de->starthi = cpu_to_le16(start >> 16);
+		mark_buffer_dirty(dotdot_bh);
+		corrupt |= sync_dirty_buffer(dotdot_bh);
+	}
+error_inode:
+	fat_detach(old_inode);
+	fat_attach(old_inode, old_sinfo.i_pos);
+	if (new_inode) {
+		fat_attach(new_inode, sinfo.i_pos);
+		if (corrupt)
+			corrupt |= fat_sync_inode(new_inode);
+	} else {
+		/*
+		 * If new entry was not sharing the data cluster, it
+		 * shouldn't be serious corruption.
+		 */
+		int err2 = fat_remove_entries(new_dir, &sinfo);
+		if (corrupt)
+			corrupt |= err2;
+		sinfo.bh = NULL;
+	}
+	if (corrupt < 0) {
+		fat_fs_panic(new_dir->i_sb,
+			     "%s: Filesystem corrupted (i_pos %lld)",
+			     __FUNCTION__, sinfo.i_pos);
+	}
+	goto out;
 }
 
 static struct inode_operations vfat_dir_inode_operations = {
diff -Nru a/fs/xfs/linux-2.6/xfs_linux.h b/fs/xfs/linux-2.6/xfs_linux.h
--- a/fs/xfs/linux-2.6/xfs_linux.h	2005-03-11 12:51:52 -08:00
+++ b/fs/xfs/linux-2.6/xfs_linux.h	2005-03-11 12:51:52 -08:00
@@ -88,6 +88,7 @@
 #include <linux/list.h>
 #include <linux/proc_fs.h>
 #include <linux/version.h>
+#include <linux/sort.h>
 
 #include <asm/page.h>
 #include <asm/div64.h>
@@ -367,5 +368,7 @@
 	do_div(x, y);
 	return(x * y);
 }
+
+#define qsort(a, n, s, cmp) sort(a, n, s, cmp, NULL)
 
 #endif /* __XFS_LINUX__ */
diff -Nru a/fs/xfs/xfs_da_btree.c b/fs/xfs/xfs_da_btree.c
--- a/fs/xfs/xfs_da_btree.c	2005-03-11 12:51:50 -08:00
+++ b/fs/xfs/xfs_da_btree.c	2005-03-11 12:51:50 -08:00
@@ -1627,40 +1627,38 @@
 {
 	xfs_dahash_t hash;
 
-#define	ROTL(x,y)	(((x) << (y)) | ((x) >> (32 - (y))))
 #ifdef SLOWVERSION
 	/*
 	 * This is the old one-byte-at-a-time version.
 	 */
-	for (hash = 0; namelen > 0; namelen--) {
-		hash = *name++ ^ ROTL(hash, 7);
-	}
+	for (hash = 0; namelen > 0; namelen--)
+		hash = *name++ ^ rol32(hash, 7);
+
 	return(hash);
 #else
 	/*
 	 * Do four characters at a time as long as we can.
 	 */
-	for (hash = 0; namelen >= 4; namelen -= 4, name += 4) {
+	for (hash = 0; namelen >= 4; namelen -= 4, name += 4)
 		hash = (name[0] << 21) ^ (name[1] << 14) ^ (name[2] << 7) ^
-		       (name[3] << 0) ^ ROTL(hash, 7 * 4);
-	}
+		       (name[3] << 0) ^ rol32(hash, 7 * 4);
+
 	/*
 	 * Now do the rest of the characters.
 	 */
 	switch (namelen) {
 	case 3:
 		return (name[0] << 14) ^ (name[1] << 7) ^ (name[2] << 0) ^
-		       ROTL(hash, 7 * 3);
+		       rol32(hash, 7 * 3);
 	case 2:
-		return (name[0] << 7) ^ (name[1] << 0) ^ ROTL(hash, 7 * 2);
+		return (name[0] << 7) ^ (name[1] << 0) ^ rol32(hash, 7 * 2);
 	case 1:
-		return (name[0] << 0) ^ ROTL(hash, 7 * 1);
+		return (name[0] << 0) ^ rol32(hash, 7 * 1);
 	case 0:
 		return hash;
 	}
 	/* NOTREACHED */
 #endif
-#undef ROTL
 	return 0; /* keep gcc happy */
 }
 
diff -Nru a/include/asm-alpha/cacheflush.h b/include/asm-alpha/cacheflush.h
--- a/include/asm-alpha/cacheflush.h	2005-03-11 12:51:47 -08:00
+++ b/include/asm-alpha/cacheflush.h	2005-03-11 12:51:47 -08:00
@@ -8,7 +8,7 @@
 #define flush_cache_all()			do { } while (0)
 #define flush_cache_mm(mm)			do { } while (0)
 #define flush_cache_range(vma, start, end)	do { } while (0)
-#define flush_cache_page(vma, vmaddr)		do { } while (0)
+#define flush_cache_page(vma, vmaddr, pfn)	do { } while (0)
 #define flush_dcache_page(page)			do { } while (0)
 #define flush_dcache_mmap_lock(mapping)		do { } while (0)
 #define flush_dcache_mmap_unlock(mapping)	do { } while (0)
diff -Nru a/include/asm-alpha/pci.h b/include/asm-alpha/pci.h
--- a/include/asm-alpha/pci.h	2005-03-11 12:51:52 -08:00
+++ b/include/asm-alpha/pci.h	2005-03-11 12:51:52 -08:00
@@ -228,17 +228,10 @@
 
 #define pci_domain_nr(bus) ((struct pci_controller *)(bus)->sysdata)->index
 
-static inline int
-pci_name_bus(char *name, struct pci_bus *bus)
+static inline int pci_proc_domain(struct pci_bus *bus)
 {
 	struct pci_controller *hose = bus->sysdata;
-
-	if (likely(hose->need_domain_info == 0)) {
-		sprintf(name, "%02x", bus->number);
-	} else {
-		sprintf(name, "%04x:%02x", hose->index, bus->number);
-	}
-	return 0;
+	return hose->need_domain_info;
 }
 
 static inline void
diff -Nru a/include/asm-alpha/pgtable.h b/include/asm-alpha/pgtable.h
--- a/include/asm-alpha/pgtable.h	2005-03-11 12:51:42 -08:00
+++ b/include/asm-alpha/pgtable.h	2005-03-11 12:51:42 -08:00
@@ -22,6 +22,7 @@
  * hook is made available.
  */
 #define set_pte(pteptr, pteval) ((*(pteptr)) = (pteval))
+#define set_pte_at(mm,addr,ptep,pteval) set_pte(ptep,pteval)
 
 /* PMD_SHIFT determines the size of the area a second-level page table can map */
 #define PMD_SHIFT	(PAGE_SHIFT + (PAGE_SHIFT-3))
@@ -235,7 +236,10 @@
 
 extern inline int pte_none(pte_t pte)		{ return !pte_val(pte); }
 extern inline int pte_present(pte_t pte)	{ return pte_val(pte) & _PAGE_VALID; }
-extern inline void pte_clear(pte_t *ptep)	{ pte_val(*ptep) = 0; }
+extern inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
+{
+	pte_val(*ptep) = 0;
+}
 
 extern inline int pmd_none(pmd_t pmd)		{ return !pmd_val(pmd); }
 extern inline int pmd_bad(pmd_t pmd)		{ return (pmd_val(pmd) & ~_PFN_MASK) != _PAGE_TABLE; }
diff -Nru a/include/asm-alpha/resource.h b/include/asm-alpha/resource.h
--- a/include/asm-alpha/resource.h	2005-03-11 12:51:41 -08:00
+++ b/include/asm-alpha/resource.h	2005-03-11 12:51:41 -08:00
@@ -2,32 +2,20 @@
 #define _ALPHA_RESOURCE_H
 
 /*
- * Resource limits
+ * Alpha/Linux-specific ordering of these four resource limit IDs,
+ * the rest comes from the generic header:
  */
-
-#define RLIMIT_CPU	0		/* CPU time in ms */
-#define RLIMIT_FSIZE	1		/* Maximum filesize */
-#define RLIMIT_DATA	2		/* max data size */
-#define RLIMIT_STACK	3		/* max stack size */
-#define RLIMIT_CORE	4		/* max core file size */
-#define RLIMIT_RSS	5		/* max resident set size */
-#define RLIMIT_NOFILE	6		/* max number of open files */
-#define RLIMIT_AS	7		/* address space limit(?) */
-#define RLIMIT_NPROC	8		/* max number of processes */
-#define RLIMIT_MEMLOCK	9		/* max locked-in-memory address space */
-#define RLIMIT_LOCKS	10		/* maximum file locks held */
-#define RLIMIT_SIGPENDING 11		/* max number of pending signals */
-#define RLIMIT_MSGQUEUE 12		/* maximum bytes in POSIX mqueues */
-
-#define RLIM_NLIMITS	13
-#define __ARCH_RLIMIT_ORDER
+#define RLIMIT_NOFILE		6	/* max number of open files */
+#define RLIMIT_AS		7	/* address space limit */
+#define RLIMIT_NPROC		8	/* max number of processes */
+#define RLIMIT_MEMLOCK		9	/* max locked-in-memory address space */
 
 /*
  * SuS says limits have to be unsigned.  Fine, it's unsigned, but
  * we retain the old value for compatibility, especially with DU. 
  * When you run into the 2^63 barrier, you call me.
  */
-#define RLIM_INFINITY	0x7ffffffffffffffful
+#define RLIM_INFINITY		0x7ffffffffffffffful
 
 #include <asm-generic/resource.h>
 
diff -Nru a/include/asm-alpha/system.h b/include/asm-alpha/system.h
--- a/include/asm-alpha/system.h	2005-03-11 12:51:47 -08:00
+++ b/include/asm-alpha/system.h	2005-03-11 12:51:47 -08:00
@@ -621,4 +621,6 @@
 
 #endif /* __ASSEMBLY__ */
 
+#define arch_align_stack(x) (x)
+
 #endif
diff -Nru a/include/asm-alpha/unistd.h b/include/asm-alpha/unistd.h
--- a/include/asm-alpha/unistd.h	2005-03-11 12:51:42 -08:00
+++ b/include/asm-alpha/unistd.h	2005-03-11 12:51:42 -08:00
@@ -651,6 +651,6 @@
    have declarations.  If we use no prototype, then we get warnings from
    -Wstrict-prototypes.  Ho hum.  */
 
-#define cond_syscall(x)  asm(".weak\t" #x "\n" #x " = sys_ni_syscall");
+#define cond_syscall(x)  asm(".weak\t" #x "\n" #x " = sys_ni_syscall")
 
 #endif /* _ALPHA_UNISTD_H */
diff -Nru a/include/asm-arm/arch-ixp2000/entry-macro.S b/include/asm-arm/arch-ixp2000/entry-macro.S
--- a/include/asm-arm/arch-ixp2000/entry-macro.S	2005-03-11 12:51:52 -08:00
+++ b/include/asm-arm/arch-ixp2000/entry-macro.S	2005-03-11 12:51:52 -08:00
@@ -15,8 +15,7 @@
 
 		mov	\irqnr, #0x0              @clear out irqnr as default
                 mov	\base, #0xfe000000
-		orr	\base, \base, #0x00ff0000
-		orr	\base, \base, #0x0000a000
+		orr	\base, \base, #0x00e00000
 		orr	\base, \base, #0x08
 		ldr	\irqstat, [\base]         @ get interrupts
 
@@ -35,8 +34,8 @@
 		bne	1001f
 
 		mov	\base, #0xfe000000
-		orr	\base, \base, #0x00fd0000
-		orr	\base, \base, #0x0000e100
+		orr	\base, \base, #0x00c00000
+		orr	\base, \base, #0x00000100
 		orr	\base, \base, #0x00000058
 		ldr	\irqstat, [\base]
 
diff -Nru a/include/asm-arm/arch-ixp2000/io.h b/include/asm-arm/arch-ixp2000/io.h
--- a/include/asm-arm/arch-ixp2000/io.h	2005-03-11 12:51:41 -08:00
+++ b/include/asm-arm/arch-ixp2000/io.h	2005-03-11 12:51:41 -08:00
@@ -1,5 +1,5 @@
 /*
- * linux/include/asm-arm/arch-ixdp2000/io.h
+ * linux/include/asm-arm/arch-ixp2000/io.h
  *
  * Original Author: Naeem M Afzal <naeem.m.afzal@intel.com>
  * Maintainer: Deepak Saxena <dsaxena@plexity.net>
@@ -27,8 +27,8 @@
  * IXP2000 does not do proper byte-lane conversion for PCI addresses,
  * so we need to override standard functions.
  */
-#define alignb(addr)		(((unsigned long)addr & ~3) + (3 - ((unsigned long)addr & 3)))
-#define alignw(addr)		(((unsigned long)addr & ~2) + (2 - ((unsigned long)addr & 2)))
+#define alignb(addr)		(void __iomem *)(((unsigned long)addr & ~3) + (3 - ((unsigned long)addr & 3)))
+#define alignw(addr)		(void __iomem *)(((unsigned long)addr & ~2) + (2 - ((unsigned long)addr & 2)))
 
 #define outb(v,p)		__raw_writeb(v,alignb(___io(p)))
 #define outw(v,p)		__raw_writew((v),alignw(___io(p)))
diff -Nru a/include/asm-arm/arch-ixp2000/ixdp2x00.h b/include/asm-arm/arch-ixp2000/ixdp2x00.h
--- a/include/asm-arm/arch-ixp2000/ixdp2x00.h	2005-03-11 12:51:41 -08:00
+++ b/include/asm-arm/arch-ixp2000/ixdp2x00.h	2005-03-11 12:51:41 -08:00
@@ -21,7 +21,7 @@
  * On board CPLD memory map
  */
 #define IXDP2X00_PHYS_CPLD_BASE		0xc7000000
-#define IXDP2X00_VIRT_CPLD_BASE		0xfefdd000
+#define IXDP2X00_VIRT_CPLD_BASE		0xfafff000
 #define IXDP2X00_CPLD_SIZE		0x00001000
 
 
diff -Nru a/include/asm-arm/arch-ixp2000/ixdp2x01.h b/include/asm-arm/arch-ixp2000/ixdp2x01.h
--- a/include/asm-arm/arch-ixp2000/ixdp2x01.h	2005-03-11 12:51:41 -08:00
+++ b/include/asm-arm/arch-ixp2000/ixdp2x01.h	2005-03-11 12:51:41 -08:00
@@ -1,5 +1,5 @@
 /*
- * include/asm/arch/ixdp2x01.h
+ * include/asm-arm/arch-ixp2000/ixdp2x01.h
  *
  * Platform definitions for IXDP2X01 && IXDP2801 systems
  *
@@ -18,10 +18,10 @@
 #define __IXDP2X01_H__
 
 #define	IXDP2X01_PHYS_CPLD_BASE		0xc6024000
-#define	IXDP2X01_VIRT_CPLD_BASE		0xfefdd000
-#define	IXDP2X01_CPLD_REGION_SIZE	0x1000
+#define	IXDP2X01_VIRT_CPLD_BASE		0xfafff000
+#define	IXDP2X01_CPLD_REGION_SIZE	0x00001000
 
-#define IXDP2X01_CPLD_VIRT_REG(reg) (volatile u32*)(IXDP2X01_VIRT_CPLD_BASE | reg)
+#define IXDP2X01_CPLD_VIRT_REG(reg) (volatile unsigned long*)(IXDP2X01_VIRT_CPLD_BASE | reg)
 #define IXDP2X01_CPLD_PHYS_REG(reg) (volatile u32*)(IXDP2X01_PHYS_CPLD_BASE | reg)
 
 #define IXDP2X01_UART1_VIRT_BASE	IXDP2X01_CPLD_VIRT_REG(0x40)
diff -Nru a/include/asm-arm/arch-ixp2000/ixp2000-regs.h b/include/asm-arm/arch-ixp2000/ixp2000-regs.h
--- a/include/asm-arm/arch-ixp2000/ixp2000-regs.h	2005-03-11 12:51:40 -08:00
+++ b/include/asm-arm/arch-ixp2000/ixp2000-regs.h	2005-03-11 12:51:40 -08:00
@@ -19,41 +19,49 @@
 #define _IXP2000_REGS_H_
 
 /* 
- * Static I/O regions. The manual defines each region as being several
- * MB in size, but all the registers are within the first 4K, so there's
- * no purpose in mapping the whole region in.
+ * Static I/O regions.
+ *
+ * Most of the registers are clumped in 4K regions spread throughout
+ * the 0xc000000 -> 0xc0100000 address range, but we just map in
+ * the whole range using a single 1 MB section instead of small
+ * 4K pages.  This has two advantages for us:
+ *
+ * 1) We use only one TLB entry for large number of on-chip I/O devices.
+ *
+ * 2) We can easily set the Section attributes to XCB=101 on the IXP2400
+ *    as required per erratum #66.
+ *
+ * CAP stands for CSR Access Proxy
  */
-#define	IXP2000_SLOWPORT_CSR_PHYS_BASE	0xc0080000
-#define	IXP2000_SLOWPORT_CSR_VIRT_BASE	0xfefff000
-#define	IXP2000_SLOWPORT_CSR_SIZE	0x1000
-
-#define	IXP2000_GLOBAL_REG_PHYS_BASE	0xc0004000
-#define	IXP2000_GLOBAL_REG_VIRT_BASE	0xfeffe000
-#define	IXP2000_GLOBAL_REG_SIZE		0x1000
 
+#define	IXP2000_CAP_PHYS_BASE		0xc0000000
+#define	IXP2000_CAP_VIRT_BASE		0xfef00000
+#define	IXP2000_CAP_SIZE		0x00100000
+
+/*
+ * Addresses for specific on-chip peripherals
+ */
+#define	IXP2000_SLOWPORT_CSR_VIRT_BASE	0xfef80000
+#define	IXP2000_GLOBAL_REG_VIRT_BASE	0xfef04000
 #define	IXP2000_UART_PHYS_BASE		0xc0030000
 #define	IXP2000_UART_VIRT_BASE		0xfef30000
-#define IXP2000_UART_SIZE		0x1000
-
-#define	IXP2000_TIMER_PHYS_BASE		0xc0020000
-#define	IXP2000_TIMER_VIRT_BASE		0xfeffc000
-#define	IXP2000_TIMER_SIZE		0x1000
-
-#define	IXP2000_GPIO_PHYS_BASE		0xc0010000
-#define	IXP2000_GPIO_VIRT_BASE		0xfeffb000
-#define	IXP2000_GPIO_SIZE		0x1000
+#define	IXP2000_TIMER_VIRT_BASE		0xfef20000
+#define	IXP2000_GPIO_VIRT_BASE		0Xfef10000
 
+/*
+ * Devices outside of the 0xc0000000 -> 0xc0100000 range
+ */
 #define IXP2000_INTCTL_PHYS_BASE	0xd6000000
-#define	IXP2000_INTCTL_VIRT_BASE	0xfeffa000
-#define	IXP2000_INTCTL_SIZE		0x01000
+#define	IXP2000_INTCTL_VIRT_BASE	0xfee00000
+#define	IXP2000_INTCTL_SIZE		0x00100000
 
 #define IXP2000_PCI_CREG_PHYS_BASE	0xde000000
-#define	IXP2000_PCI_CREG_VIRT_BASE	0xfeff0000
-#define	IXP2000_PCI_CREG_SIZE		0x1000
+#define	IXP2000_PCI_CREG_VIRT_BASE	0xfed00000
+#define	IXP2000_PCI_CREG_SIZE		0x00100000
 
 #define IXP2000_PCI_CSR_PHYS_BASE	0xdf000000
-#define	IXP2000_PCI_CSR_VIRT_BASE	0xfefde000
-#define	IXP2000_PCI_CSR_SIZE		0x1000
+#define	IXP2000_PCI_CSR_VIRT_BASE	0xfec00000
+#define	IXP2000_PCI_CSR_SIZE		0x00100000
 
 #define IXP2000_PCI_IO_PHYS_BASE	0xd8000000
 #define	IXP2000_PCI_IO_VIRT_BASE	0xfd000000
@@ -66,7 +74,6 @@
 #define IXP2000_PCI_CFG1_PHYS_BASE	0xdb000000
 #define IXP2000_PCI_CFG1_VIRT_BASE	0xfb000000
 #define IXP2000_PCI_CFG1_SIZE		0x01000000
-
 
 /* 
  * Timers
diff -Nru a/include/asm-arm/arch-ixp2000/platform.h b/include/asm-arm/arch-ixp2000/platform.h
--- a/include/asm-arm/arch-ixp2000/platform.h	2005-03-11 12:51:41 -08:00
+++ b/include/asm-arm/arch-ixp2000/platform.h	2005-03-11 12:51:41 -08:00
@@ -1,5 +1,5 @@
 /*
- * include/asm-arh/arch-ixp2000/platform.h
+ * include/asm-arm/arch-ixp2000/platform.h
  *
  * Various bits of code used by platform-level code.
  *
@@ -50,7 +50,7 @@
  * Boards may multiplex different devices on the 2nd channel of 
  * the slowport interface that each need different configuration 
  * settings.  For example, the IXDP2400 uses channel 2 on the interface 
- * to access the CPLD, the switch fabric card, and te media card.  Each 
+ * to access the CPLD, the switch fabric card, and the media card.  Each
  * one needs a different mode so drivers must save/restore the mode 
  * before and after each operation.  
  *
diff -Nru a/include/asm-arm/arch-ixp2000/system.h b/include/asm-arm/arch-ixp2000/system.h
--- a/include/asm-arm/arch-ixp2000/system.h	2005-03-11 12:51:52 -08:00
+++ b/include/asm-arm/arch-ixp2000/system.h	2005-03-11 12:51:52 -08:00
@@ -19,7 +19,7 @@
 
 static inline void arch_reset(char mode)
 {
-	cli();
+	local_irq_disable();
 
 	/*
 	 * Reset flash banking register so that we are pointing at
diff -Nru a/include/asm-arm/arch-ixp2000/vmalloc.h b/include/asm-arm/arch-ixp2000/vmalloc.h
--- a/include/asm-arm/arch-ixp2000/vmalloc.h	2005-03-11 12:51:40 -08:00
+++ b/include/asm-arm/arch-ixp2000/vmalloc.h	2005-03-11 12:51:40 -08:00
@@ -20,4 +20,4 @@
 #define VMALLOC_OFFSET	    (8*1024*1024)
 #define VMALLOC_START	    (((unsigned long)high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1))
 #define VMALLOC_VMADDR(x)   ((unsigned long)(x))
-#define VMALLOC_END	    0xfb000000
+#define VMALLOC_END	    0xfaffefff
diff -Nru a/include/asm-arm/arch-ixp4xx/platform.h b/include/asm-arm/arch-ixp4xx/platform.h
--- a/include/asm-arm/arch-ixp4xx/platform.h	2005-03-11 12:51:41 -08:00
+++ b/include/asm-arm/arch-ixp4xx/platform.h	2005-03-11 12:51:41 -08:00
@@ -15,6 +15,12 @@
 
 #include <asm/types.h>
 
+#ifndef	__ARMEB__
+#define	REG_OFFSET	0
+#else
+#define	REG_OFFSET	3
+#endif
+
 /*
  * Expansion bus memory regions
  */
diff -Nru a/include/asm-arm/arch-pxa/corgi.h b/include/asm-arm/arch-pxa/corgi.h
--- a/include/asm-arm/arch-pxa/corgi.h	2005-03-11 12:51:41 -08:00
+++ b/include/asm-arm/arch-pxa/corgi.h	2005-03-11 12:51:41 -08:00
@@ -133,6 +133,10 @@
   unsigned int phadadj;
 };
 
+/*
+ * Shared data structures
+ */
+extern struct platform_device corgiscoop_device;
 
 /*
  * External Functions
diff -Nru a/include/asm-arm/arch-pxa/idp.h b/include/asm-arm/arch-pxa/idp.h
--- a/include/asm-arm/arch-pxa/idp.h	2005-03-11 12:51:52 -08:00
+++ b/include/asm-arm/arch-pxa/idp.h	2005-03-11 12:51:52 -08:00
@@ -10,20 +10,20 @@
  * 2001-09-13: Cliff Brake <cbrake@accelent.com>
  *             Initial code
  *
+ * 2005-02-15: Cliff Brake <cliff.brake@gmail.com>
+ *             <http://www.vibren.com> <http://bec-systems.com>
+ *             Changes for 2.6 kernel.
  */
 
 #include <linux/config.h>
 
 /*
  * Note: this file must be safe to include in assembly files
+ *
+ * Support for the Vibren PXA255 IDP requires rev04 or later
+ * IDP hardware.
  */
 
-/* comment out following if you have a rev01 board */
-#define PXA_IDP_REV02	1
-
-#ifdef PXA_IDP_REV02
-//Use this as well for 0017-x004 and greater pcb's:
-#define PXA_IDP_REV04 1
 
 #define IDP_FLASH_PHYS		(PXA_CS0_PHYS)
 #define IDP_ALT_FLASH_PHYS	(PXA_CS1_PHYS)
@@ -38,26 +38,18 @@
  * virtual memory map
  */
 
-#define IDP_IDE_BASE		(0xf0000000)
-#define IDP_IDE_SIZE		(1*1024*1024)
-#define IDE_REG_STRIDE		4
-
-#define IDP_ETH_BASE		(IDP_IDE_BASE + IDP_IDE_SIZE)
-#define IDP_ETH_SIZE		(1*1024*1024)
-#define ETH_BASE		IDP_ETH_BASE //smc9194 driver compatibility issue
-
-#define IDP_COREVOLT_BASE	(IDP_ETH_BASE + IDP_ETH_SIZE)
+#define IDP_COREVOLT_VIRT	(0xf0000000)
 #define IDP_COREVOLT_SIZE	(1*1024*1024)
 
-#define IDP_CPLD_BASE		(IDP_COREVOLT_BASE + IDP_COREVOLT_SIZE)
+#define IDP_CPLD_VIRT		(IDP_COREVOLT_VIRT + IDP_COREVOLT_SIZE)
 #define IDP_CPLD_SIZE		(1*1024*1024)
 
-#if (IDP_CPLD_BASE + IDP_CPLD_SIZE) > 0xfc000000
+#if (IDP_CPLD_VIRT + IDP_CPLD_SIZE) > 0xfc000000
 #error Your custom IO space is getting a bit large !!
 #endif
 
-#define CPLD_P2V(x)		((x) - IDP_CPLD_PHYS + IDP_CPLD_BASE)
-#define CPLD_V2P(x)		((x) - IDP_CPLD_BASE + IDP_CPLD_PHYS)
+#define CPLD_P2V(x)		((x) - IDP_CPLD_PHYS + IDP_CPLD_VIRT)
+#define CPLD_V2P(x)		((x) - IDP_CPLD_VIRT + IDP_CPLD_PHYS)
 
 #ifndef __ASSEMBLY__
 #  define __CPLD_REG(x)		(*((volatile unsigned long *)CPLD_P2V(x)))
@@ -65,7 +57,7 @@
 #  define __CPLD_REG(x)		CPLD_P2V(x)
 #endif
 
-/* board level registers in the CPLD: (offsets from CPLD_BASE) */
+/* board level registers in the CPLD: (offsets from CPLD_VIRT) */
 
 #define _IDP_CPLD_REV			(IDP_CPLD_PHYS + 0x00)
 #define _IDP_CPLD_PERIPH_PWR		(IDP_CPLD_PHYS + 0x04)
@@ -142,32 +134,10 @@
 
 #define PCC_DETECT(x)	(GPLR(7 + (x)) & GPIO_bit(7 + (x)))
 
-/*
- * Macros for LCD Driver
- */
-
-#ifdef CONFIG_FB_PXA
-
-#define FB_BACKLIGHT_ON()	(IDP_CPLD_LCD |= (1<<1))
-#define FB_BACKLIGHT_OFF() 	(IDP_CPLD_LCD &= ~(1<<1))
-
-#define FB_PWR_ON() 		(IDP_CPLD_LCD |= (1<< 0))
-#define FB_PWR_OFF() 		(IDP_CPLD_LCD &= ~(1<<0))
-
-#define FB_VLCD_ON()		(IDP_CPLD_LCD |= (1<<2))
-#define FB_VLCD_OFF() 		(IDP_CPLD_LCD &= ~(1<<2))
-
-#endif
-
 /* A listing of interrupts used by external hardware devices */
 
-#ifdef PXA_IDP_REV04
 #define TOUCH_PANEL_IRQ			IRQ_GPIO(5)
 #define IDE_IRQ				IRQ_GPIO(21)
-#else
-#define TOUCH_PANEL_IRQ			IRQ_GPIO(21)
-#define IDE_IRQ				IRQ_GPIO(5)
-#endif
 
 #define TOUCH_PANEL_IRQ_EDGE		IRQT_FALLING
 
@@ -196,7 +166,7 @@
 
 #define IDP_LEDS_MASK	(IDP_HB_LED | IDP_BUSY_LED)
 
-#define IDP_WRITE_LEDS(value)	(IDP_CPLD_LED_CONTROL = (IDP_CPLD_LED_CONTROL & (~(IDP_LEDS_MASK)) | value))
+#define IDP_WRITE_LEDS(value)	(IDP_CPLD_LED_CONTROL = (IDP_CPLD_LED_CONTROL & ((~(IDP_LEDS_MASK)) | value)))
 
 /*
  * macros for MTD driver
@@ -229,238 +199,4 @@
 	inputs = (IDP_CPLD_KB_ROW & 0x7f);\
 }
 
-#else
-
-/*
- * following is for rev01 boards only
- */
-
-#define IDP_FLASH_PHYS		(PXA_CS0_PHYS)
-#define IDP_ALT_FLASH_PHYS	(PXA_CS1_PHYS)
-#define IDP_MEDIAQ_PHYS		(PXA_CS3_PHYS)
-#define IDP_CTRL_PORT_PHYS	(PXA_CS5_PHYS + 0x02C00000)
-#define IDP_IDE_PHYS		(PXA_CS5_PHYS + 0x03000000)
-#define IDP_ETH_PHYS		(PXA_CS5_PHYS + 0x03400000)
-#define IDP_COREVOLT_PHYS	(PXA_CS5_PHYS + 0x03800000)
-#define IDP_CPLD_PHYS		(PXA_CS5_PHYS + 0x03C00000)
-
-
-/*
- * virtual memory map
- */
-
-#define IDP_CTRL_PORT_BASE	(0xf0000000)
-#define IDP_CTRL_PORT_SIZE	(1*1024*1024)
-
-#define IDP_IDE_BASE		(IDP_CTRL_PORT_BASE + IDP_CTRL_PORT_SIZE)
-#define IDP_IDE_SIZE		(1*1024*1024)
-
-#define IDP_ETH_BASE		(IDP_IDE_BASE + IDP_IDE_SIZE)
-#define IDP_ETH_SIZE		(1*1024*1024)
-
-#define IDP_COREVOLT_BASE	(IDP_ETH_BASE + IDP_ETH_SIZE)
-#define IDP_COREVOLT_SIZE	(1*1024*1024)
-
-#define IDP_CPLD_BASE		(IDP_COREVOLT_BASE + IDP_COREVOLT_SIZE)
-#define IDP_CPLD_SIZE		(1*1024*1024)
-
-#if (IDP_CPLD_BASE + IDP_CPLD_SIZE) > 0xfc000000
-#error Your custom IO space is getting a bit large !!
-#endif
-
-#define CPLD_P2V(x)		((x) - IDP_CPLD_PHYS + IDP_CPLD_BASE)
-#define CPLD_V2P(x)		((x) - IDP_CPLD_BASE + IDP_CPLD_PHYS)
-
-#ifndef __ASSEMBLY__
-#  define __CPLD_REG(x)		(*((volatile unsigned long *)CPLD_P2V(x)))
-#else
-#  define __CPLD_REG(x)		CPLD_P2V(x)
-#endif
-
-/* board level registers in the CPLD: (offsets from CPLD_BASE) */
-
-#define _IDP_CPLD_LED_CONTROL		(IDP_CPLD_PHYS + 0x00)
-#define _IDP_CPLD_PERIPH_PWR		(IDP_CPLD_PHYS + 0x04)
-#define _IDP_CPLD_CIR			(IDP_CPLD_PHYS + 0x08)
-#define _IDP_CPLD_KB_COL_HIGH		(IDP_CPLD_PHYS + 0x0C)
-#define _IDP_CPLD_KB_COL_LOW		(IDP_CPLD_PHYS + 0x10)
-#define _IDP_CPLD_PCCARD_EN		(IDP_CPLD_PHYS + 0x14)
-#define _IDP_CPLD_GPIOH_DIR		(IDP_CPLD_PHYS + 0x18)
-#define _IDP_CPLD_GPIOH_VALUE		(IDP_CPLD_PHYS + 0x1C)
-#define _IDP_CPLD_GPIOL_DIR		(IDP_CPLD_PHYS + 0x20)
-#define _IDP_CPLD_GPIOL_VALUE		(IDP_CPLD_PHYS + 0x24)
-#define _IDP_CPLD_MISC			(IDP_CPLD_PHYS + 0x28)
-#define _IDP_CPLD_PCCARD0_STATUS	(IDP_CPLD_PHYS + 0x2C)
-#define _IDP_CPLD_PCCARD1_STATUS	(IDP_CPLD_PHYS + 0x30)
-
-/* FPGA register virtual addresses */
-#define IDP_CPLD_LED_CONTROL		__CPLD_REG(_IDP_CPLD_LED_CONTROL)	/* write only */
-#define IDP_CPLD_PERIPH_PWR		__CPLD_REG(_IDP_CPLD_PERIPH_PWR)	/* write only */
-#define IDP_CPLD_CIR			__CPLD_REG(_IDP_CPLD_CIR)		/* write only */
-#define IDP_CPLD_KB_COL_HIGH		__CPLD_REG(_IDP_CPLD_KB_COL_HIGH)	/* write only */
-#define IDP_CPLD_KB_COL_LOW		__CPLD_REG(_IDP_CPLD_KB_COL_LOW)	/* write only */
-#define IDP_CPLD_PCCARD_EN		__CPLD_REG(_IDP_CPLD_PCCARD_EN)		/* write only */
-#define IDP_CPLD_GPIOH_DIR		__CPLD_REG(_IDP_CPLD_GPIOH_DIR)		/* write only */
-#define IDP_CPLD_GPIOH_VALUE		__CPLD_REG(_IDP_CPLD_GPIOH_VALUE)	/* write only */
-#define IDP_CPLD_GPIOL_DIR		__CPLD_REG(_IDP_CPLD_GPIOL_DIR)		/* write only */
-#define IDP_CPLD_GPIOL_VALUE		__CPLD_REG(_IDP_CPLD_GPIOL_VALUE)	/* write only */
-#define IDP_CPLD_MISC			__CPLD_REG(_IDP_CPLD_MISC)		/* read only */
-#define IDP_CPLD_PCCARD0_STATUS		__CPLD_REG(_IDP_CPLD_PCCARD0_STATUS)	/* read only */
-#define IDP_CPLD_PCCARD1_STATUS		__CPLD_REG(_IDP_CPLD_PCCARD1_STATUS)	/* read only */
-
-
-#ifndef __ASSEMBLY__
-
-/* shadow registers for write only registers */
-extern unsigned int idp_cpld_led_control_shadow;
-extern unsigned int idp_cpld_periph_pwr_shadow;
-extern unsigned int idp_cpld_cir_shadow;
-extern unsigned int idp_cpld_kb_col_high_shadow;
-extern unsigned int idp_cpld_kb_col_low_shadow;
-extern unsigned int idp_cpld_pccard_en_shadow;
-extern unsigned int idp_cpld_gpioh_dir_shadow;
-extern unsigned int idp_cpld_gpioh_value_shadow;
-extern unsigned int idp_cpld_gpiol_dir_shadow;
-extern unsigned int idp_cpld_gpiol_value_shadow;
-
-extern unsigned int idp_control_port_shadow;
-
-/*
- * macros to write to write only register
- *
- * none of these macros are protected from
- * multiple drivers using them in interrupt context.
- */
-
-#define WRITE_IDP_CPLD_LED_CONTROL(value, mask) \
-{\
-	idp_cpld_led_control_shadow = (((value & mask) | (idp_cpld_led_control_shadow & ~mask)));\
-	IDP_CPLD_LED_CONTROL = idp_cpld_led_control_shadow;\
-}
-#define WRITE_IDP_CPLD_PERIPH_PWR(value, mask) \
-{\
-	idp_cpld_periph_pwr_shadow = ((value & mask) | (idp_cpld_periph_pwr_shadow & ~mask));\
-	IDP_CPLD_PERIPH_PWR = idp_cpld_periph_pwr_shadow;\
-}
-#define WRITE_IDP_CPLD_CIR(value, mask) \
-{\
-	idp_cpld_cir_shadow = ((value & mask) | (idp_cpld_cir_shadow & ~mask));\
-	IDP_CPLD_CIR = idp_cpld_cir_shadow;\
-}
-#define WRITE_IDP_CPLD_KB_COL_HIGH(value, mask) \
-{\
-	idp_cpld_kb_col_high_shadow = ((value & mask) | (idp_cpld_kb_col_high_shadow & ~mask));\
-	IDP_CPLD_KB_COL_HIGH = idp_cpld_kb_col_high_shadow;\
-}
-#define WRITE_IDP_CPLD_KB_COL_LOW(value, mask) \
-{\
-	idp_cpld_kb_col_low_shadow = ((value & mask) | (idp_cpld_kb_col_low_shadow & ~mask));\
-	IDP_CPLD_KB_COL_LOW = idp_cpld_kb_col_low_shadow;\
-}
-#define WRITE_IDP_CPLD_PCCARD_EN(value, mask) \
-{\
-	idp_cpld_ = ((value & mask) | (idp_cpld_led_control_shadow & ~mask));\
-	IDP_CPLD_LED_CONTROL = idp_cpld_led_control_shadow;\
-}
-#define WRITE_IDP_CPLD_GPIOH_DIR(value, mask) \
-{\
-	idp_cpld_gpioh_dir_shadow = ((value & mask) | (idp_cpld_gpioh_dir_shadow & ~mask));\
-	IDP_CPLD_GPIOH_DIR = idp_cpld_gpioh_dir_shadow;\
-}
-#define WRITE_IDP_CPLD_GPIOH_VALUE(value, mask) \
-{\
-	idp_cpld_gpioh_value_shadow = ((value & mask) | (idp_cpld_gpioh_value_shadow & ~mask));\
-	IDP_CPLD_GPIOH_VALUE = idp_cpld_gpioh_value_shadow;\
-}
-#define WRITE_IDP_CPLD_GPIOL_DIR(value, mask) \
-{\
-	idp_cpld_gpiol_dir_shadow = ((value & mask) | (idp_cpld_gpiol_dir_shadow & ~mask));\
-	IDP_CPLD_GPIOL_DIR = idp_cpld_gpiol_dir_shadow;\
-}
-#define WRITE_IDP_CPLD_GPIOL_VALUE(value, mask) \
-{\
-	idp_cpld_gpiol_value_shadow = ((value & mask) | (idp_cpld_gpiol_value_shadow & ~mask));\
-	IDP_CPLD_GPIOL_VALUE = idp_cpld_gpiol_value_shadow;\
-}
-
-#define WRITE_IDP_CONTROL_PORT(value, mask) \
-{\
-	idp_control_port_shadow = ((value & mask) | (idp_control_port_shadow & ~mask));\
-	(*((volatile unsigned long *)IDP_CTRL_PORT_BASE)) = idp_control_port_shadow;\
-}
-
-#endif
-
-/* A listing of interrupts used by external hardware devices */
-
-#define TOUCH_PANEL_IRQ			IRQ_GPIO(21)
-#define TOUCH_PANEL_IRQ_EGDE		IRQT_FALLING
-
-#define ETHERNET_IRQ			IRQ_GPIO(4)
-#define ETHERNET_IRQ_EDGE		IRQT_RISING
-
-/*
- * Bit masks for various registers
- */
-
-
-/* control port */
-#define IDP_CONTROL_PORT_PCSLOT0_0	(1 << 0)
-#define IDP_CONTROL_PORT_PCSLOT0_1	(1 << 1)
-#define IDP_CONTROL_PORT_PCSLOT0_2	(1 << 2)
-#define IDP_CONTROL_PORT_PCSLOT0_3	(1 << 3)
-#define IDP_CONTROL_PORT_PCSLOT1_1	(1 << 4)
-#define IDP_CONTROL_PORT_PCSLOT1_2	(1 << 5)
-#define IDP_CONTROL_PORT_PCSLOT1_3	(1 << 6)
-#define IDP_CONTROL_PORT_PCSLOT1_4	(1 << 7)
-#define IDP_CONTROL_PORT_SERIAL1_EN	(1 << 9)
-#define IDP_CONTROL_PORT_SERIAL2_EN	(1 << 10)
-#define IDP_CONTROL_PORT_SERIAL3_EN	(1 << 11)
-#define IDP_CONTROL_PORT_IRDA_FIR	(1 << 12)
-#define IDP_CONTROL_PORT_IRDA_M0	(1 << 13)
-#define IDP_CONTROL_PORT_IRDA_M1	(1 << 14)
-#define IDP_CONTROL_PORT_I2S_PWR	(1 << 15)
-#define IDP_CONTROL_PORT_FLASH_WP	(1 << 19)
-#define IDP_CONTROL_PORT_MILL_EN	(1 << 20)
-#define IDP_CONTROL_PORT_LCD_PWR	(1 << 21)
-#define IDP_CONTROL_PORT_LCD_BKLEN	(1 << 22)
-#define IDP_CONTROL_PORT_LCD_ENAVLCD	(1 << 23)
-
-/*
- * Macros for LCD Driver
- */
-
-#ifdef CONFIG_FB_PXA
-
-#define FB_BACKLIGHT_ON() WRITE_IDP_CONTROL_PORT(IDP_CONTROL_PORT_LCD_BKLEN, IDP_CONTROL_PORT_LCD_BKLEN)
-#define FB_BACKLIGHT_OFF() WRITE_IDP_CONTROL_PORT(0, IDP_CONTROL_PORT_LCD_BKLEN)
-
-#define FB_PWR_ON() WRITE_IDP_CONTROL_PORT(IDP_CONTROL_PORT_LCD_PWR, IDP_CONTROL_PORT_LCD_PWR)
-#define FB_PWR_OFF() WRITE_IDP_CONTROL_PORT(0, IDP_CONTROL_PORT_LCD_PWR)
-
-#define FB_VLCD_ON() WRITE_IDP_CONTROL_PORT(IDP_CONTROL_PORT_LCD_ENAVLCD, IDP_CONTROL_PORT_LCD_ENAVLCD)
-#define FB_VLCD_OFF() WRITE_IDP_CONTROL_PORT(0, IDP_CONTROL_PORT_LCD_ENAVLCD)
-
-#endif
 
-
-/*
- * Macros for LED Driver
- */
-
-/* leds 0 = ON */
-#define IDP_HB_LED	0x1
-#define IDP_BUSY_LED	0x2
-
-#define IDP_LEDS_MASK	(IDP_HB_LED | IDP_BUSY_LED)
-
-#define IDP_WRITE_LEDS(value) 	WRITE_IDP_CPLD_LED_CONTROL(value, IDP_LEDS_MASK)
-
-/*
- * macros for MTD driver
- */
-
-#define FLASH_WRITE_PROTECT_DISABLE()	WRITE_IDP_CONTROL_PORT(0, IDP_CONTROL_PORT_FLASH_WP)
-#define FLASH_WRITE_PROTECT_ENABLE()	WRITE_IDP_CONTROL_PORT(IDP_CONTROL_PORT_FLASH_WP, IDP_CONTROL_PORT_FLASH_WP)
-
-#endif
diff -Nru a/include/asm-arm/arch-pxa/irqs.h b/include/asm-arm/arch-pxa/irqs.h
--- a/include/asm-arm/arch-pxa/irqs.h	2005-03-11 12:51:41 -08:00
+++ b/include/asm-arm/arch-pxa/irqs.h	2005-03-11 12:51:41 -08:00
@@ -140,14 +140,41 @@
 #define IRQ_S0_BVD1_STSCHG	(IRQ_BOARD_END + 53)
 #define IRQ_S1_BVD1_STSCHG	(IRQ_BOARD_END + 54)
 
+#define IRQ_LOCOMO_START	(IRQ_BOARD_END)
+#define IRQ_LOCOMO_KEY		(IRQ_BOARD_END + 0)
+#define IRQ_LOCOMO_GPIO0	(IRQ_BOARD_END + 1)
+#define IRQ_LOCOMO_GPIO1	(IRQ_BOARD_END + 2)
+#define IRQ_LOCOMO_GPIO2	(IRQ_BOARD_END + 3)
+#define IRQ_LOCOMO_GPIO3	(IRQ_BOARD_END + 4)
+#define IRQ_LOCOMO_GPIO4	(IRQ_BOARD_END + 5)
+#define IRQ_LOCOMO_GPIO5	(IRQ_BOARD_END + 6)
+#define IRQ_LOCOMO_GPIO6	(IRQ_BOARD_END + 7)
+#define IRQ_LOCOMO_GPIO7	(IRQ_BOARD_END + 8)
+#define IRQ_LOCOMO_GPIO8	(IRQ_BOARD_END + 9)
+#define IRQ_LOCOMO_GPIO9	(IRQ_BOARD_END + 10)
+#define IRQ_LOCOMO_GPIO10	(IRQ_BOARD_END + 11)
+#define IRQ_LOCOMO_GPIO11	(IRQ_BOARD_END + 12)
+#define IRQ_LOCOMO_GPIO12	(IRQ_BOARD_END + 13)
+#define IRQ_LOCOMO_GPIO13	(IRQ_BOARD_END + 14)
+#define IRQ_LOCOMO_GPIO14	(IRQ_BOARD_END + 15)
+#define IRQ_LOCOMO_GPIO15	(IRQ_BOARD_END + 16)
+#define IRQ_LOCOMO_LT		(IRQ_BOARD_END + 17)
+#define IRQ_LOCOMO_SPI_RFR	(IRQ_BOARD_END + 18)
+#define IRQ_LOCOMO_SPI_RFW	(IRQ_BOARD_END + 19)
+#define IRQ_LOCOMO_SPI_OVRN	(IRQ_BOARD_END + 20)
+#define IRQ_LOCOMO_SPI_TEND	(IRQ_BOARD_END + 21)
+
 /*
  * Figure out the MAX IRQ number.
  *
  * If we have an SA1111, the max IRQ is S1_BVD1_STSCHG+1.
+ * If we have an LoCoMo, the max IRQ is IRQ_LOCOMO_SPI_TEND+1
  * Otherwise, we have the standard IRQs only.
  */
 #ifdef CONFIG_SA1111
 #define NR_IRQS			(IRQ_S1_BVD1_STSCHG + 1)
+#elif defined(CONFIG_SHARP_LOCOMO)
+#define NR_IRQS			(IRQ_LOCOMO_SPI_TEND + 1)
 #elif defined(CONFIG_ARCH_LUBBOCK) || \
       defined(CONFIG_MACH_MAINSTONE)
 #define NR_IRQS			(IRQ_BOARD_END)
@@ -185,3 +212,8 @@
 #define MAINSTONE_S1_STSCHG_IRQ	MAINSTONE_IRQ(14)
 #define MAINSTONE_S1_IRQ	MAINSTONE_IRQ(15)
 
+/* LoCoMo Interrupts (CONFIG_SHARP_LOCOMO) */
+#define IRQ_LOCOMO_KEY_BASE	(IRQ_BOARD_START + 0)
+#define IRQ_LOCOMO_GPIO_BASE	(IRQ_BOARD_START + 1)
+#define IRQ_LOCOMO_LT_BASE	(IRQ_BOARD_START + 2)
+#define IRQ_LOCOMO_SPI_BASE	(IRQ_BOARD_START + 3)
diff -Nru a/include/asm-arm/arch-pxa/poodle.h b/include/asm-arm/arch-pxa/poodle.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-arm/arch-pxa/poodle.h	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,111 @@
+/*
+ * linux/include/asm-arm/arch-pxa/poodle.h
+ *
+ * May be copied or modified under the terms of the GNU General Public
+ * License.  See linux/COPYING for more information.
+ *
+ * Based on:
+ *   linux/include/asm-arm/arch-sa1100/collie.h
+ *
+ * ChangeLog:
+ *   04-06-2001 Lineo Japan, Inc.
+ *   04-16-2001 SHARP Corporation
+ *   Update to 2.6 John Lenz
+ */
+#ifndef __ASM_ARCH_POODLE_H
+#define __ASM_ARCH_POODLE_H  1
+
+/*
+ * GPIOs
+ */
+/* PXA GPIOs */
+#define POODLE_GPIO_ON_KEY		(0)
+#define POODLE_GPIO_AC_IN		(1)
+#define POODLE_GPIO_CO			16
+#define POODLE_GPIO_TP_INT		(5)
+#define POODLE_GPIO_WAKEUP		(11)	/* change battery */
+#define POODLE_GPIO_GA_INT		(10)
+#define POODLE_GPIO_IR_ON		(22)
+#define POODLE_GPIO_HP_IN		(4)
+#define POODLE_GPIO_CF_IRQ		(17)
+#define POODLE_GPIO_CF_CD		(14)
+#define POODLE_GPIO_CF_STSCHG		(14)
+#define POODLE_GPIO_SD_PWR		(33)
+#define POODLE_GPIO_nSD_CLK		(6)
+#define POODLE_GPIO_nSD_WP		(7)
+#define POODLE_GPIO_nSD_INT		(8)
+#define POODLE_GPIO_nSD_DETECT		(9)
+#define POODLE_GPIO_MAIN_BAT_LOW	(13)
+#define POODLE_GPIO_BAT_COVER		(13)
+#define POODLE_GPIO_ADC_TEMP_ON		(21)
+#define POODLE_GPIO_BYPASS_ON		(36)
+#define POODLE_GPIO_CHRG_ON		(38)
+#define POODLE_GPIO_CHRG_FULL		(16)
+
+/* PXA GPIOs */
+#define POODLE_IRQ_GPIO_ON_KEY		IRQ_GPIO0
+#define POODLE_IRQ_GPIO_AC_IN		IRQ_GPIO1
+#define POODLE_IRQ_GPIO_HP_IN		IRQ_GPIO4
+#define POODLE_IRQ_GPIO_CO		IRQ_GPIO16
+#define POODLE_IRQ_GPIO_TP_INT		IRQ_GPIO5
+#define POODLE_IRQ_GPIO_WAKEUP		IRQ_GPIO11
+#define POODLE_IRQ_GPIO_GA_INT		IRQ_GPIO10
+#define POODLE_IRQ_GPIO_CF_IRQ		IRQ_GPIO17
+#define POODLE_IRQ_GPIO_CF_CD		IRQ_GPIO14
+#define POODLE_IRQ_GPIO_nSD_INT		IRQ_GPIO8
+#define POODLE_IRQ_GPIO_nSD_DETECT	IRQ_GPIO9
+#define POODLE_IRQ_GPIO_MAIN_BAT_LOW	IRQ_GPIO13
+
+/* SCOOP GPIOs */
+#define POODLE_SCOOP_CHARGE_ON	SCOOP_GPCR_PA11
+#define POODLE_SCOOP_CP401	SCOOP_GPCR_PA13
+#define POODLE_SCOOP_VPEN	SCOOP_GPCR_PA18
+#define POODLE_SCOOP_L_PCLK	SCOOP_GPCR_PA20
+#define POODLE_SCOOP_L_LCLK	SCOOP_GPCR_PA21
+#define POODLE_SCOOP_HS_OUT	SCOOP_GPCR_PA22
+
+#define POODLE_SCOOP_IO_DIR	( POODLE_SCOOP_VPEN | POODLE_SCOOP_HS_OUT )
+#define POODLE_SCOOP_IO_OUT	( 0 )
+
+/*
+ * Flash Memory mappings
+ *
+ * We have the following mapping:
+ *                      phys            virt
+ *      boot ROM        00000000        ef800000
+ */
+#define FLASH_MEM_BASE	0xa0000a00
+#define	FLASH_DATA(adr) (*(volatile unsigned int*)(FLASH_MEM_BASE+(adr)))
+#define	FLASH_DATA_F(adr) (*(volatile float32 *)(FLASH_MEM_BASE+(adr)))
+#define FLASH_MAGIC_CHG(a,b,c,d) ( ( d << 24 ) | ( c << 16 )  | ( b << 8 ) | a )
+
+/* COMADJ */
+#define FLASH_COMADJ_MAJIC	FLASH_MAGIC_CHG('C','M','A','D')
+#define	FLASH_COMADJ_MAGIC_ADR	0x00
+#define	FLASH_COMADJ_DATA_ADR	0x04
+
+/* UUID */
+#define FLASH_UUID_MAJIC	FLASH_MAGIC_CHG('U','U','I','D')
+#define	FLASH_UUID_MAGIC_ADR	0x08
+#define	FLASH_UUID_DATA_ADR	0x0C
+
+/* TOUCH PANEL */
+#define FLASH_TOUCH_MAJIC	FLASH_MAGIC_CHG('T','U','C','H')
+#define	FLASH_TOUCH_MAGIC_ADR	0x1C
+#define	FLASH_TOUCH_XP_DATA_ADR	0x20
+#define	FLASH_TOUCH_YP_DATA_ADR	0x24
+#define	FLASH_TOUCH_XD_DATA_ADR	0x28
+#define	FLASH_TOUCH_YD_DATA_ADR	0x2C
+
+/* AD */
+#define FLASH_AD_MAJIC	FLASH_MAGIC_CHG('B','V','A','D')
+#define	FLASH_AD_MAGIC_ADR	0x30
+#define	FLASH_AD_DATA_ADR	0x34
+
+/* PHAD */
+#define FLASH_PHAD_MAJIC	FLASH_MAGIC_CHG('P','H','A','D')
+#define	FLASH_PHAD_MAGIC_ADR	0x38
+#define	FLASH_PHAD_DATA_ADR	0x3C
+
+
+#endif /* __ASM_ARCH_POODLE_H  */
diff -Nru a/include/asm-arm/arch-s3c2410/debug-macro.S b/include/asm-arm/arch-s3c2410/debug-macro.S
--- a/include/asm-arm/arch-s3c2410/debug-macro.S	2005-03-11 12:51:41 -08:00
+++ b/include/asm-arm/arch-s3c2410/debug-macro.S	2005-03-11 12:51:41 -08:00
@@ -11,6 +11,8 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  *
+ * Modifications:
+ *     10-Mar-2005 LCVR  Changed S3C2410_VA to S3C24XX_VA
 */
 
 #include <asm/arch/map.h>
@@ -24,7 +26,7 @@
 		mrc	p15, 0, \rx, c1, c0
 		tst	\rx, #1
 		ldreq	\rx, = S3C2410_PA_UART
-		ldrne	\rx, = S3C2410_VA_UART
+		ldrne	\rx, = S3C24XX_VA_UART
 #if CONFIG_DEBUG_S3C2410_UART != 0
 		add	\rx, \rx, #(S3C2410_UART1_OFF * CONFIG_DEBUG_S3C2410_UART)
 #endif
@@ -43,7 +45,7 @@
 		mrc	p15, 0, \rd, c1, c0
 		tst	\rd, #1
 		addeq	\rd, \rx, #(S3C2410_PA_GPIO - S3C2410_PA_UART)
-		addne	\rd, \rx, #(S3C2410_VA_GPIO - S3C2410_VA_UART)
+		addne	\rd, \rx, #(S3C24XX_VA_GPIO - S3C24XX_VA_UART)
 		bic	\rd, \rd, #0xff000
 		ldr	\rd, [ \rd, # S3C2410_GSTATUS1 - S3C2410_GPIOREG(0) ]
 		and	\rd, \rd, #0x00ff0000
@@ -74,7 +76,7 @@
 		mrc	p15, 0, \rd, c1, c0
 		tst	\rd, #1
 		addeq	\rd, \rx, #(S3C2410_PA_GPIO - S3C2410_PA_UART)
-		addne	\rd, \rx, #(S3C2410_VA_GPIO - S3C2410_VA_UART)
+		addne	\rd, \rx, #(S3C24XX_VA_GPIO - S3C24XX_VA_UART)
 		bic	\rd, \rd, #0xff000
 		ldr	\rd, [ \rd, # S3C2410_GSTATUS1 - S3C2410_GPIOREG(0) ]
 		and	\rd, \rd, #0x00ff0000
diff -Nru a/include/asm-arm/arch-s3c2410/entry-macro.S b/include/asm-arm/arch-s3c2410/entry-macro.S
--- a/include/asm-arm/arch-s3c2410/entry-macro.S	2005-03-11 12:51:41 -08:00
+++ b/include/asm-arm/arch-s3c2410/entry-macro.S	2005-03-11 12:51:41 -08:00
@@ -6,12 +6,15 @@
  * This file is licensed under  the terms of the GNU General Public
  * License version 2. This program is licensed "as is" without any
  * warranty of any kind, whether express or implied.
+
+ * Modifications:
+ *     10-Mar-2005 LCVR  Changed S3C2410_VA to S3C24XX_VA
  */
 
 
 	.macro	get_irqnr_and_base, irqnr, irqstat, base, tmp
 
-		mov	\tmp, #S3C2410_VA_IRQ
+		mov	\tmp, #S3C24XX_VA_IRQ
 		ldr	\irqnr, [ \tmp, #0x14 ]		@ get irq no
 30000:
 		teq	\irqnr, #4
@@ -45,7 +48,7 @@
 		.align	4
 20004:
 		mov	r1, #1
-		mov	\tmp, #S3C2410_VA_IRQ
+		mov	\tmp, #S3C24XX_VA_IRQ
 		ldmfd	r13!, { r0 - r4 , r8-r12, r14 }
 #endif
 
@@ -83,7 +86,7 @@
 
 		@ we get here from no main or external interrupts pending
 1002:
-		add	\tmp, \tmp, #S3C2410_VA_GPIO - S3C2410_VA_IRQ
+		add	\tmp, \tmp, #S3C24XX_VA_GPIO - S3C24XX_VA_IRQ
 		ldr	\irqstat, [ \tmp, # 0xa8 ]	@ EXTINTPEND
 		ldr	\irqnr, [ \tmp, # 0xa4 ]	@ EXTINTMASK
 
diff -Nru a/include/asm-arm/arch-s3c2410/hardware.h b/include/asm-arm/arch-s3c2410/hardware.h
--- a/include/asm-arm/arch-s3c2410/hardware.h	2005-03-11 12:51:42 -08:00
+++ b/include/asm-arm/arch-s3c2410/hardware.h	2005-03-11 12:51:42 -08:00
@@ -97,11 +97,7 @@
 #include <asm/sizes.h>
 #include <asm/arch/map.h>
 
-/* machine specific includes, such as the BAST */
-
-#if defined(CONFIG_ARCH_BAST)
-#include <asm/arch/bast-cpld.h>
-#endif
+/* machine specific hardware definitions should go after this */
 
 /* currently here until moved into config (todo) */
 #define CONFIG_NO_MULTIWORD_IO
diff -Nru a/include/asm-arm/arch-s3c2410/io.h b/include/asm-arm/arch-s3c2410/io.h
--- a/include/asm-arm/arch-s3c2410/io.h	2005-03-11 12:51:51 -08:00
+++ b/include/asm-arm/arch-s3c2410/io.h	2005-03-11 12:51:51 -08:00
@@ -8,6 +8,7 @@
  * Modifications:
  *  06-Dec-1997	RMK	Created.
  *  02-Sep-2003 BJD	Modified for S3C2410
+ *  10-Mar-2005 LCVR	Changed S3C2410_VA to S3C24XX_VA
  *
  */
 
@@ -26,10 +27,10 @@
 
 #define __PORT_PCIO(x)	((x) < (1<<28))
 
-#define PCIO_BASE	 (S3C2410_VA_ISA_WORD)
-#define PCIO_BASE_b	 (S3C2410_VA_ISA_BYTE)
-#define PCIO_BASE_w	 (S3C2410_VA_ISA_WORD)
-#define PCIO_BASE_l	 (S3C2410_VA_ISA_WORD)
+#define PCIO_BASE	 (S3C24XX_VA_ISA_WORD)
+#define PCIO_BASE_b	 (S3C24XX_VA_ISA_BYTE)
+#define PCIO_BASE_w	 (S3C24XX_VA_ISA_WORD)
+#define PCIO_BASE_l	 (S3C24XX_VA_ISA_WORD)
 /*
  * Dynamic IO functions - let the compiler
  * optimize the expressions
diff -Nru a/include/asm-arm/arch-s3c2410/irqs.h b/include/asm-arm/arch-s3c2410/irqs.h
--- a/include/asm-arm/arch-s3c2410/irqs.h	2005-03-11 12:51:52 -08:00
+++ b/include/asm-arm/arch-s3c2410/irqs.h	2005-03-11 12:51:52 -08:00
@@ -1,6 +1,6 @@
 /* linux/include/asm-arm/arch-s3c2410/irqs.h
  *
- * Copyright (c) 2003 Simtec Electronics
+ * Copyright (c) 2003-2005 Simtec Electronics
  *   Ben Dooks <ben@simtec.co.uk>
  *
  * This program is free software; you can redistribute it and/or modify
@@ -11,6 +11,8 @@
  *  12-May-2003 BJD  Created file
  *  08-Jan-2003 BJD  Linux 2.6.0 version, moved BAST bits out
  *  12-Mar-2004 BJD  Fixed bug in header protection
+ *  10-Feb-2005 BJD  Added camera IRQ from guillaume.gourat@nexvision.tv
+ *  28-Feb-2005 BJD  Updated s3c2440 IRQs
  */
 
 
@@ -35,7 +37,8 @@
 #define IRQ_EINT3      S3C2410_IRQ(3)
 #define IRQ_EINT4t7    S3C2410_IRQ(4)	    /* 20 */
 #define IRQ_EINT8t23   S3C2410_IRQ(5)
-#define IRQ_RESERVED6  S3C2410_IRQ(6)
+#define IRQ_RESERVED6  S3C2410_IRQ(6)	    /* for s3c2410 */
+#define IRQ_CAM        S3C2410_IRQ(6)	    /* for s3c2440 */
 #define IRQ_BATT_FLT   S3C2410_IRQ(7)
 #define IRQ_TICK       S3C2410_IRQ(8)	    /* 24 */
 #define IRQ_WDT	       S3C2410_IRQ(9)
@@ -54,6 +57,7 @@
 #define IRQ_SPI0       S3C2410_IRQ(22)
 #define IRQ_UART1      S3C2410_IRQ(23)
 #define IRQ_RESERVED24 S3C2410_IRQ(24)	    /* 40 */
+#define IRQ_NFCON      S3C2410_IRQ(24)	    /* for s3c2440 */
 #define IRQ_USBD       S3C2410_IRQ(25)
 #define IRQ_USBH       S3C2410_IRQ(26)
 #define IRQ_IIC	       S3C2410_IRQ(27)
@@ -109,7 +113,14 @@
 #define IRQ_TC		 S3C2410_IRQ(63)
 #define IRQ_ADC		 S3C2410_IRQ(64)
 
-#define NR_IRQS (IRQ_ADC+1)
+/* extra irqs for s3c2440 */
+
+#define IRQ_S3C2440_CAM_C	S3C2410_IRQ(65)
+#define IRQ_S3C2440_CAM_P	S3C2410_IRQ(66)
+#define IRQ_S3C2440_WDT		S3C2410_IRQ(67)
+#define IRQ_S3C2440_AC97	S3C2410_IRQ(68)
+
+#define NR_IRQS (IRQ_S3C2440_AC97+1)
 
 
 #endif /* __ASM_ARCH_IRQ_H */
diff -Nru a/include/asm-arm/arch-s3c2410/map.h b/include/asm-arm/arch-s3c2410/map.h
--- a/include/asm-arm/arch-s3c2410/map.h	2005-03-11 12:51:51 -08:00
+++ b/include/asm-arm/arch-s3c2410/map.h	2005-03-11 12:51:51 -08:00
@@ -10,8 +10,10 @@
  * published by the Free Software Foundation.
  *
  * Changelog:
- *  12-May-2003 BJD  Created file
- *  06-Jan-2003 BJD  Linux 2.6.0 version, moved bast specifics out
+ *  12-May-2003 BJD   Created file
+ *  06-Jan-2003 BJD   Linux 2.6.0 version, moved bast specifics out
+ *  10-Feb-2005 BJD   Added CAMIF definition from guillaume.gourat@nexvision.tv
+ *  10-Mar-2005 LCVR  Added support to S3C2400, changed {VA,SZ} names
 */
 
 #ifndef __ASM_ARCH_MAP_H
@@ -29,107 +31,133 @@
  */
 
 #define S3C2410_ADDR(x)	  (0xF0000000 + (x))
+#define S3C2400_ADDR(x)	  S3C2410_ADDR(x)
 
 /* interrupt controller is the first thing we put in, to make
  * the assembly code for the irq detection easier
  */
-#define S3C2410_VA_IRQ	   S3C2410_ADDR(0x00000000)
+#define S3C24XX_VA_IRQ	   S3C2410_ADDR(0x00000000)
+#define S3C2400_PA_IRQ	   (0x14400000)
 #define S3C2410_PA_IRQ	   (0x4A000000)
-#define S3C2410_SZ_IRQ	   SZ_1M
+#define S3C24XX_SZ_IRQ	   SZ_1M
 
 /* memory controller registers */
-#define S3C2410_VA_MEMCTRL S3C2410_ADDR(0x00100000)
+#define S3C24XX_VA_MEMCTRL S3C2410_ADDR(0x00100000)
+#define S3C2400_PA_MEMCTRL (0x14000000)
 #define S3C2410_PA_MEMCTRL (0x48000000)
-#define S3C2410_SZ_MEMCTRL SZ_1M
+#define S3C24XX_SZ_MEMCTRL SZ_1M
 
 /* USB host controller */
-#define S3C2410_VA_USBHOST S3C2410_ADDR(0x00200000)
+#define S3C24XX_VA_USBHOST S3C2410_ADDR(0x00200000)
+#define S3C2400_PA_USBHOST (0x14200000)
 #define S3C2410_PA_USBHOST (0x49000000)
-#define S3C2410_SZ_USBHOST SZ_1M
+#define S3C24XX_SZ_USBHOST SZ_1M
 
 /* DMA controller */
-#define S3C2410_VA_DMA	   S3C2410_ADDR(0x00300000)
+#define S3C24XX_VA_DMA	   S3C2410_ADDR(0x00300000)
+#define S3C2400_PA_DMA	   (0x14600000)
 #define S3C2410_PA_DMA	   (0x4B000000)
-#define S3C2410_SZ_DMA	   SZ_1M
+#define S3C24XX_SZ_DMA	   SZ_1M
 
 /* Clock and Power management */
-#define S3C2410_VA_CLKPWR  S3C2410_ADDR(0x00400000)
+#define S3C24XX_VA_CLKPWR  S3C2410_ADDR(0x00400000)
+#define S3C2400_PA_CLKPWR  (0x14800000)
 #define S3C2410_PA_CLKPWR  (0x4C000000)
-#define S3C2410_SZ_CLKPWR  SZ_1M
+#define S3C24XX_SZ_CLKPWR  SZ_1M
 
 /* LCD controller */
-#define S3C2410_VA_LCD	   S3C2410_ADDR(0x00600000)
+#define S3C24XX_VA_LCD	   S3C2410_ADDR(0x00600000)
+#define S3C2400_PA_LCD	   (0x14A00000)
 #define S3C2410_PA_LCD	   (0x4D000000)
-#define S3C2410_SZ_LCD	   SZ_1M
+#define S3C24XX_SZ_LCD	   SZ_1M
 
 /* NAND flash controller */
-#define S3C2410_VA_NAND	   S3C2410_ADDR(0x00700000)
+#define S3C24XX_VA_NAND	   S3C2410_ADDR(0x00700000)
 #define S3C2410_PA_NAND	   (0x4E000000)
-#define S3C2410_SZ_NAND	   SZ_1M
+#define S3C24XX_SZ_NAND	   SZ_1M
+
+/* MMC controller - available on the S3C2400 */
+#define S3C2400_VA_MMC 	   S3C2400_ADDR(0x00700000)
+#define S3C2400_PA_MMC 	   (0x15A00000)
+#define S3C2400_SZ_MMC 	   SZ_1M
 
 /* UARTs */
-#define S3C2410_VA_UART	   S3C2410_ADDR(0x00800000)
+#define S3C24XX_VA_UART	   S3C2410_ADDR(0x00800000)
+#define S3C2400_PA_UART	   (0x15000000)
 #define S3C2410_PA_UART	   (0x50000000)
-#define S3C2410_SZ_UART	   SZ_1M
+#define S3C24XX_SZ_UART	   SZ_1M
 
 /* Timers */
-#define S3C2410_VA_TIMER   S3C2410_ADDR(0x00900000)
+#define S3C24XX_VA_TIMER   S3C2410_ADDR(0x00900000)
+#define S3C2400_PA_TIMER   (0x15100000)
 #define S3C2410_PA_TIMER   (0x51000000)
-#define S3C2410_SZ_TIMER   SZ_1M
+#define S3C24XX_SZ_TIMER   SZ_1M
 
 /* USB Device port */
-#define S3C2410_VA_USBDEV  S3C2410_ADDR(0x00A00000)
+#define S3C24XX_VA_USBDEV  S3C2410_ADDR(0x00A00000)
+#define S3C2400_PA_USBDEV  (0x15200140)
 #define S3C2410_PA_USBDEV  (0x52000000)
-#define S3C2410_SZ_USBDEV  SZ_1M
+#define S3C24XX_SZ_USBDEV  SZ_1M
 
 /* Watchdog */
-#define S3C2410_VA_WATCHDOG S3C2410_ADDR(0x00B00000)
+#define S3C24XX_VA_WATCHDOG S3C2410_ADDR(0x00B00000)
+#define S3C2400_PA_WATCHDOG (0x15300000)
 #define S3C2410_PA_WATCHDOG (0x53000000)
-#define S3C2410_SZ_WATCHDOG SZ_1M
+#define S3C24XX_SZ_WATCHDOG SZ_1M
 
 /* IIC hardware controller */
-#define S3C2410_VA_IIC	   S3C2410_ADDR(0x00C00000)
+#define S3C24XX_VA_IIC	   S3C2410_ADDR(0x00C00000)
+#define S3C2400_PA_IIC	   (0x15400000)
 #define S3C2410_PA_IIC	   (0x54000000)
-#define S3C2410_SZ_IIC	   SZ_1M
+#define S3C24XX_SZ_IIC	   SZ_1M
 
-#define VA_IIC_BASE	   (S3C2410_VA_IIC)
+#define VA_IIC_BASE	   (S3C24XX_VA_IIC)
 
 /* IIS controller */
-#define S3C2410_VA_IIS	   S3C2410_ADDR(0x00D00000)
+#define S3C24XX_VA_IIS	   S3C2410_ADDR(0x00D00000)
+#define S3C2400_PA_IIS	   (0x15508000)
 #define S3C2410_PA_IIS	   (0x55000000)
-#define S3C2410_SZ_IIS	   SZ_1M
+#define S3C24XX_SZ_IIS	   SZ_1M
 
 /* GPIO ports */
-#define S3C2410_VA_GPIO	   S3C2410_ADDR(0x00E00000)
+#define S3C24XX_VA_GPIO	   S3C2410_ADDR(0x00E00000)
+#define S3C2400_PA_GPIO	   (0x15600000)
 #define S3C2410_PA_GPIO	   (0x56000000)
-#define S3C2410_SZ_GPIO	   SZ_1M
+#define S3C24XX_SZ_GPIO	   SZ_1M
 
 /* RTC */
-#define S3C2410_VA_RTC	   S3C2410_ADDR(0x00F00000)
+#define S3C24XX_VA_RTC	   S3C2410_ADDR(0x00F00000)
+#define S3C2400_PA_RTC	   (0x15700040)
 #define S3C2410_PA_RTC	   (0x57000000)
-#define S3C2410_SZ_RTC	   SZ_1M
+#define S3C24XX_SZ_RTC	   SZ_1M
 
 /* ADC */
-#define S3C2410_VA_ADC	   S3C2410_ADDR(0x01000000)
+#define S3C24XX_VA_ADC	   S3C2410_ADDR(0x01000000)
+#define S3C2400_PA_ADC	   (0x15800000)
 #define S3C2410_PA_ADC	   (0x58000000)
-#define S3C2410_SZ_ADC	   SZ_1M
+#define S3C24XX_SZ_ADC	   SZ_1M
 
 /* SPI */
-#define S3C2410_VA_SPI	   S3C2410_ADDR(0x01100000)
+#define S3C24XX_VA_SPI	   S3C2410_ADDR(0x01100000)
+#define S3C2400_PA_SPI	   (0x15900000)
 #define S3C2410_PA_SPI	   (0x59000000)
-#define S3C2410_SZ_SPI	   SZ_1M
+#define S3C24XX_SZ_SPI	   SZ_1M
 
 /* SDI */
-#define S3C2410_VA_SDI	   S3C2410_ADDR(0x01200000)
+#define S3C24XX_VA_SDI	   S3C2410_ADDR(0x01200000)
 #define S3C2410_PA_SDI	   (0x5A000000)
-#define S3C2410_SZ_SDI	   SZ_1M
+#define S3C24XX_SZ_SDI	   SZ_1M
+
+/* CAMIF */
+#define S3C2440_PA_CAMIF   (0x4F000000)
+#define S3C2440_SZ_CAMIF   SZ_1M
 
 /* ISA style IO, for each machine to sort out mappings for, if it
  * implements it. We reserve two 16M regions for ISA.
  */
 
-#define S3C2410_VA_ISA_WORD  S3C2410_ADDR(0x02000000)
-#define S3C2410_VA_ISA_BYTE  S3C2410_ADDR(0x03000000)
+#define S3C24XX_VA_ISA_WORD  S3C2410_ADDR(0x02000000)
+#define S3C24XX_VA_ISA_BYTE  S3C2410_ADDR(0x03000000)
 
 /* physical addresses of all the chip-select areas */
 
@@ -143,6 +171,17 @@
 #define S3C2410_CS7 (0x38000000)
 
 #define S3C2410_SDRAM_PA    (S3C2410_CS6)
+
+#define S3C2400_CS0 (0x00000000)
+#define S3C2400_CS1 (0x02000000)
+#define S3C2400_CS2 (0x04000000)
+#define S3C2400_CS3 (0x06000000)
+#define S3C2400_CS4 (0x08000000)
+#define S3C2400_CS5 (0x0A000000)
+#define S3C2400_CS6 (0x0C000000)
+#define S3C2400_CS7 (0x0E000000)
+
+#define S3C2400_SDRAM_PA    (S3C2400_CS6)
 
 
 #endif /* __ASM_ARCH_MAP_H */
diff -Nru a/include/asm-arm/arch-s3c2410/regs-adc.h b/include/asm-arm/arch-s3c2410/regs-adc.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-arm/arch-s3c2410/regs-adc.h	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,63 @@
+/* linux/include/asm/arch-s3c2410/regs-adc.h
+ *
+ * Copyright (c) 2004 Shannon Holland <holland@loser.net>
+ *
+ * This program is free software; yosu 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.
+ *
+ * S3C2410 ADC registers
+ *
+ *  Changelog:
+ *    27-09-2004     SAH     Created file
+*/
+
+#ifndef __ASM_ARCH_REGS_ADC_H
+#define __ASM_ARCH_REGS_ADC_H "regs-adc.h"
+
+#define S3C2410_ADCREG(x) (x)
+
+#define S3C2410_ADCCON	   S3C2410_ADCREG(0x00)
+#define S3C2410_ADCTSC	   S3C2410_ADCREG(0x04)
+#define S3C2410_ADCDLY	   S3C2410_ADCREG(0x08)
+#define S3C2410_ADCDAT0	   S3C2410_ADCREG(0x0C)
+#define S3C2410_ADCDAT1	   S3C2410_ADCREG(0x10)
+
+
+/* ADCCON Register Bits */
+#define S3C2410_ADCCON_ECFLG		(1<<15)
+#define S3C2410_ADCCON_PRSCEN		(1<<14)
+#define S3C2410_ADCCON_PRSCVL(x)	(((x)&0xFF)<<6)
+#define S3C2410_ADCCON_PRSCVLMASK	(0xFF<<6)
+#define S3C2410_ADCCON_SELMUX(x)	(((x)&0x7)<<3)
+#define S3C2410_ADCCON_MUXMASK		(0x7<<3)
+#define S3C2410_ADCCON_STDBM		(1<<2)
+#define S3C2410_ADCCON_READ_START	(1<<1)
+#define S3C2410_ADCCON_ENABLE_START	(1<<0)
+#define S3C2410_ADCCON_STARTMASK	(0x3<<0)
+
+
+/* ADCTSC Register Bits */
+#define S3C2410_ADCTSC_YM_SEN		(1<<7)
+#define S3C2410_ADCTSC_YP_SEN		(1<<6)
+#define S3C2410_ADCTSC_XM_SEN		(1<<5)
+#define S3C2410_ADCTSC_XP_SEN		(1<<4)
+#define S3C2410_ADCTSC_PULL_UP_DISABLE	(1<<3)
+#define S3C2410_ADCTSC_AUTO_PST		(1<<2)
+#define S3C2410_ADCTSC_XY_PST		(0x3<<0)
+
+/* ADCDAT0 Bits */
+#define S3C2410_ADCDAT0_UPDOWN		(1<<15)
+#define S3C2410_ADCDAT0_AUTO_PST	(1<<14)
+#define S3C2410_ADCDAT0_XY_PST		(0x3<<12)
+#define S3C2410_ADCDAT0_XPDATA_MASK	(0x03FF)
+
+/* ADCDAT1 Bits */
+#define S3C2410_ADCDAT1_UPDOWN		(1<<15)
+#define S3C2410_ADCDAT1_AUTO_PST	(1<<14)
+#define S3C2410_ADCDAT1_XY_PST		(0x3<<12)
+#define S3C2410_ADCDAT1_YPDATA_MASK	(0x03FF)
+
+#endif /* __ASM_ARCH_REGS_ADC_H */
+
+
diff -Nru a/include/asm-arm/arch-s3c2410/regs-clock.h b/include/asm-arm/arch-s3c2410/regs-clock.h
--- a/include/asm-arm/arch-s3c2410/regs-clock.h	2005-03-11 12:51:41 -08:00
+++ b/include/asm-arm/arch-s3c2410/regs-clock.h	2005-03-11 12:51:41 -08:00
@@ -10,18 +10,19 @@
  * S3C2410 clock register definitions
  *
  *  Changelog:
- *    18-Aug-2004 Ben Dooks      Added 2440 definitions
- *    08-Aug-2004 Herbert Pötzl  Added CLKCON definitions
- *    19-06-2003  Ben Dooks      Created file
- *    12-03-2004  Ben Dooks      Updated include protection
- *    29-Sep-2004 Ben Dooks	 Fixed usage for assembly inclusion
- *    10-Feb-2005 Ben Dooks	 Fixed CAMDIVN address (Guillaume Gourat)
+ *    18-Aug-2004 Ben Dooks         Added 2440 definitions
+ *    08-Aug-2004 Herbert Pötzl     Added CLKCON definitions
+ *    19-06-2003  Ben Dooks         Created file
+ *    12-03-2004  Ben Dooks         Updated include protection
+ *    29-Sep-2004 Ben Dooks	    Fixed usage for assembly inclusion
+ *    10-Feb-2005 Ben Dooks	    Fixed CAMDIVN address (Guillaume Gourat)
+ *    10-Mar-2005 Lucas Villa Real  Changed S3C2410_VA to S3C24XX_VA
  */
 
 #ifndef __ASM_ARM_REGS_CLOCK
 #define __ASM_ARM_REGS_CLOCK "$Id: clock.h,v 1.4 2003/04/30 14:50:51 ben Exp $"
 
-#define S3C2410_CLKREG(x) ((x) + S3C2410_VA_CLKPWR)
+#define S3C2410_CLKREG(x) ((x) + S3C24XX_VA_CLKPWR)
 
 #define S3C2410_PLLVAL(_m,_p,_s) ((_m) << 12 | ((_p) << 4) | ((_s)))
 
diff -Nru a/include/asm-arm/arch-s3c2410/regs-gpio.h b/include/asm-arm/arch-s3c2410/regs-gpio.h
--- a/include/asm-arm/arch-s3c2410/regs-gpio.h	2005-03-11 12:51:47 -08:00
+++ b/include/asm-arm/arch-s3c2410/regs-gpio.h	2005-03-11 12:51:47 -08:00
@@ -18,6 +18,7 @@
  *    17-10-2004     BJD     Added GSTATUS1 register definitions
  *    18-11-2004     BJD     Fixed definitions of GPE3, GPE4, GPE5 and GPE6
  *    18-11-2004     BJD     Added S3C2440 AC97 controls
+ *    10-Mar-2005    LCVR    Changed S3C2410_VA to S3C24XX_VA
 */
 
 
@@ -35,7 +36,7 @@
 #define S3C2410_GPIO_BANKG   (32*6)
 #define S3C2410_GPIO_BANKH   (32*7)
 
-#define S3C2410_GPIO_BASE(pin)   ((((pin) & ~31) >> 1) + S3C2410_VA_GPIO)
+#define S3C2410_GPIO_BASE(pin)   ((((pin) & ~31) >> 1) + S3C24XX_VA_GPIO)
 #define S3C2410_GPIO_OFFSET(pin) ((pin) & 31)
 
 /* general configuration options */
@@ -44,7 +45,7 @@
 
 /* configure GPIO ports A..G */
 
-#define S3C2410_GPIOREG(x) ((x) + S3C2410_VA_GPIO)
+#define S3C2410_GPIOREG(x) ((x) + S3C24XX_VA_GPIO)
 
 /* port A - 22bits, zero in bit X makes pin X output
  * 1 makes port special function, this is default
diff -Nru a/include/asm-arm/arch-s3c2410/regs-iis.h b/include/asm-arm/arch-s3c2410/regs-iis.h
--- a/include/asm-arm/arch-s3c2410/regs-iis.h	2005-03-11 12:51:42 -08:00
+++ b/include/asm-arm/arch-s3c2410/regs-iis.h	2005-03-11 12:51:42 -08:00
@@ -13,6 +13,7 @@
  *    19-06-2003     BJD     Created file
  *    26-06-2003     BJD     Finished off definitions for register addresses
  *    12-03-2004     BJD     Updated include protection
+ *    07-03-2005     BJD     Added FIFO size flags and S3C2440 MPLL
  */
 
 #ifndef __ASM_ARCH_REGS_IIS_H
@@ -20,6 +21,7 @@
 
 #define S3C2410_IISCON	 (0x00)
 
+#define S3C2440_IISCON_MPLL	  (1<<9)
 #define S3C2410_IISCON_LRINDEX	  (1<<8)
 #define S3C2410_IISCON_TXFIFORDY  (1<<7)
 #define S3C2410_IISCON_RXFIFORDY  (1<<6)
@@ -42,6 +44,7 @@
 #define S3C2410_IISMOD_MSB	  (1<<4)
 #define S3C2410_IISMOD_8BIT	  (0<<3)
 #define S3C2410_IISMOD_16BIT	  (1<<3)
+#define S3C2410_IISMOD_BITMASK	  (1<<3)
 #define S3C2410_IISMOD_256FS	  (0<<1)
 #define S3C2410_IISMOD_384FS	  (1<<1)
 #define S3C2410_IISMOD_16FS	  (0<<0)
@@ -50,7 +53,7 @@
 
 #define S3C2410_IISPSR		(0x08)
 #define S3C2410_IISPSR_INTMASK	(31<<5)
-#define S3C2410_IISPSR_INTSHFIT	(5)
+#define S3C2410_IISPSR_INTSHIFT	(5)
 #define S3C2410_IISPSR_EXTMASK	(31<<0)
 #define S3C2410_IISPSR_EXTSHFIT	(0)
 
@@ -60,8 +63,10 @@
 #define S3C2410_IISFCON_RXDMA	  (1<<14)
 #define S3C2410_IISFCON_TXENABLE  (1<<13)
 #define S3C2410_IISFCON_RXENABLE  (1<<12)
+#define S3C2410_IISFCON_TXMASK	  (0x3f << 6)
+#define S3C2410_IISFCON_TXSHIFT	  (6)
+#define S3C2410_IISFCON_RXMASK	  (0x3f)
+#define S3C2410_IISFCON_RXSHIFT	  (0)
 
 #define S3C2410_IISFIFO  (0x10)
-
 #endif /* __ASM_ARCH_REGS_IIS_H */
-
diff -Nru a/include/asm-arm/arch-s3c2410/regs-irq.h b/include/asm-arm/arch-s3c2410/regs-irq.h
--- a/include/asm-arm/arch-s3c2410/regs-irq.h	2005-03-11 12:51:46 -08:00
+++ b/include/asm-arm/arch-s3c2410/regs-irq.h	2005-03-11 12:51:46 -08:00
@@ -12,6 +12,7 @@
  *  Changelog:
  *    19-06-2003     BJD     Created file
  *    12-03-2004     BJD     Updated include protection
+ *    10-03-2005     LCVR    Changed S3C2410_VA to S3C24XX_VA
  */
 
 
@@ -20,8 +21,8 @@
 
 /* interrupt controller */
 
-#define S3C2410_IRQREG(x)   ((x) + S3C2410_VA_IRQ)
-#define S3C2410_EINTREG(x)  ((x) + S3C2410_VA_GPIO)
+#define S3C2410_IRQREG(x)   ((x) + S3C24XX_VA_IRQ)
+#define S3C2410_EINTREG(x)  ((x) + S3C24XX_VA_GPIO)
 
 #define S3C2410_SRCPND	       S3C2410_IRQREG(0x000)
 #define S3C2410_INTMOD	       S3C2410_IRQREG(0x004)
diff -Nru a/include/asm-arm/arch-s3c2410/regs-lcd.h b/include/asm-arm/arch-s3c2410/regs-lcd.h
--- a/include/asm-arm/arch-s3c2410/regs-lcd.h	2005-03-11 12:51:52 -08:00
+++ b/include/asm-arm/arch-s3c2410/regs-lcd.h	2005-03-11 12:51:52 -08:00
@@ -13,13 +13,14 @@
  *    12-06-2003     BJD     Created file
  *    26-06-2003     BJD     Updated LCDCON register definitions
  *    12-03-2004     BJD     Updated include protection
+ *    10-03-2005     LCVR    Changed S3C2410_VA to S3C24XX_VA
 */
 
 
 #ifndef ___ASM_ARCH_REGS_LCD_H
 #define ___ASM_ARCH_REGS_LCD_H "$Id: lcd.h,v 1.3 2003/06/26 13:25:06 ben Exp $"
 
-#define S3C2410_LCDREG(x) ((x) + S3C2410_VA_LCD)
+#define S3C2410_LCDREG(x) ((x) + S3C24XX_VA_LCD)
 
 /* LCD control registers */
 #define S3C2410_LCDCON1	    S3C2410_LCDREG(0x00)
diff -Nru a/include/asm-arm/arch-s3c2410/regs-mem.h b/include/asm-arm/arch-s3c2410/regs-mem.h
--- a/include/asm-arm/arch-s3c2410/regs-mem.h	2005-03-11 12:51:41 -08:00
+++ b/include/asm-arm/arch-s3c2410/regs-mem.h	2005-03-11 12:51:41 -08:00
@@ -11,6 +11,7 @@
  *
  *  Changelog:
  *	29-Sep-2004  BJD  Initial include for Linux
+ *      10-Mar-2005  LCVR Changed S3C2410_VA to S3C24XX_VA
  *
 */
 
@@ -18,7 +19,7 @@
 #define __ASM_ARM_MEMREGS_H "$Id: regs.h,v 1.8 2003/05/01 15:55:41 ben Exp $"
 
 #ifndef S3C2410_MEMREG
-#define S3C2410_MEMREG(x) (S3C2410_VA_MEMCTRL + (x))
+#define S3C2410_MEMREG(x) (S3C24XX_VA_MEMCTRL + (x))
 #endif
 
 /* bus width, and wait state control */
diff -Nru a/include/asm-arm/arch-s3c2410/regs-rtc.h b/include/asm-arm/arch-s3c2410/regs-rtc.h
--- a/include/asm-arm/arch-s3c2410/regs-rtc.h	2005-03-11 12:51:51 -08:00
+++ b/include/asm-arm/arch-s3c2410/regs-rtc.h	2005-03-11 12:51:51 -08:00
@@ -12,12 +12,13 @@
  *  Changelog:
  *    19-06-2003     BJD     Created file
  *    12-03-2004     BJD     Updated include protection
+ *    15-01-2005     LCVR    Changed S3C2410_VA to S3C24XX_VA (s3c2400 support)
 */
 
 #ifndef __ASM_ARCH_REGS_RTC_H
 #define __ASM_ARCH_REGS_RTC_H __FILE__
 
-#define S3C2410_RTCREG(x) ((x) + S3C2410_VA_RTC)
+#define S3C2410_RTCREG(x) ((x) + S3C24XX_VA_RTC)
 
 #define S3C2410_RTCCON	      S3C2410_RTCREG(0x40)
 #define S3C2410_RTCCON_RTCEN  (1<<0)
diff -Nru a/include/asm-arm/arch-s3c2410/regs-serial.h b/include/asm-arm/arch-s3c2410/regs-serial.h
--- a/include/asm-arm/arch-s3c2410/regs-serial.h	2005-03-11 12:51:46 -08:00
+++ b/include/asm-arm/arch-s3c2410/regs-serial.h	2005-03-11 12:51:46 -08:00
@@ -27,14 +27,17 @@
  * 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
+ *
+ * Modifications:
+ *     10-Mar-2005 LCVR  Changed S3C2410_VA to S3C24XX_VA (s3c2400 support)
  */
 
 #ifndef __ASM_ARM_REGS_SERIAL_H
 #define __ASM_ARM_REGS_SERIAL_H
 
-#define S3C2410_VA_UART0      (S3C2410_VA_UART)
-#define S3C2410_VA_UART1      (S3C2410_VA_UART + 0x4000 )
-#define S3C2410_VA_UART2      (S3C2410_VA_UART + 0x8000 )
+#define S3C24XX_VA_UART0      (S3C24XX_VA_UART)
+#define S3C24XX_VA_UART1      (S3C24XX_VA_UART + 0x4000 )
+#define S3C24XX_VA_UART2      (S3C24XX_VA_UART + 0x8000 )
 
 #define S3C2410_PA_UART0      (S3C2410_PA_UART)
 #define S3C2410_PA_UART1      (S3C2410_PA_UART + 0x4000 )
@@ -73,6 +76,11 @@
 #define S3C2440_UCON_UCLK	  (1<<10)
 #define S3C2440_UCON_PCLK2	  (2<<10)
 #define S3C2440_UCON_FCLK	  (3<<10)
+#define S3C2440_UCON2_FCLK_EN	  (1<<15)
+#define S3C2440_UCON0_DIVMASK	  (15 << 12)
+#define S3C2440_UCON1_DIVMASK	  (15 << 12)
+#define S3C2440_UCON2_DIVMASK	  (7 << 12)
+#define S3C2440_UCON_DIVSHIFT	  (12)
 
 #define S3C2410_UCON_UCLK	  (1<<10)
 #define S3C2410_UCON_SBREAK	  (1<<4)
diff -Nru a/include/asm-arm/arch-s3c2410/regs-timer.h b/include/asm-arm/arch-s3c2410/regs-timer.h
--- a/include/asm-arm/arch-s3c2410/regs-timer.h	2005-03-11 12:51:52 -08:00
+++ b/include/asm-arm/arch-s3c2410/regs-timer.h	2005-03-11 12:51:52 -08:00
@@ -13,13 +13,15 @@
  *    05-06-2003     BJD     Created file
  *    26-06-2003     BJD     Added more timer definitions to mux / control
  *    12-03-2004     BJD     Updated include protection
+ *    10-02-2005     BJD     Added S3C2410_TCFG1_MUX4_SHIFT (Guillaume Gourat)
+ *    10-03-2005     LCVR    Changed S3C2410_VA to S3C24XX_VA
 */
 
 
 #ifndef __ASM_ARCH_REGS_TIMER_H
 #define __ASM_ARCH_REGS_TIMER_H "$Id: timer.h,v 1.4 2003/05/06 19:30:50 ben Exp $"
 
-#define S3C2410_TIMERREG(x) (S3C2410_VA_TIMER + (x))
+#define S3C2410_TIMERREG(x) (S3C24XX_VA_TIMER + (x))
 #define S3C2410_TIMERREG2(tmr,reg) S3C2410_TIMERREG((reg)+0x0c+((tmr)*0x0c))
 
 #define S3C2410_TCFG0	      S3C2410_TIMERREG(0x00)
@@ -38,6 +40,7 @@
 #define S3C2410_TCFG1_MUX4_DIV16  (3<<16)
 #define S3C2410_TCFG1_MUX4_TCLK1  (4<<16)
 #define S3C2410_TCFG1_MUX4_MASK	  (15<<16)
+#define S3C2410_TCFG1_MUX4_SHIFT  (16)
 
 #define S3C2410_TCFG1_MUX3_DIV2	  (0<<12)
 #define S3C2410_TCFG1_MUX3_DIV4	  (1<<12)
diff -Nru a/include/asm-arm/arch-s3c2410/regs-udc.h b/include/asm-arm/arch-s3c2410/regs-udc.h
--- a/include/asm-arm/arch-s3c2410/regs-udc.h	2005-03-11 12:51:52 -08:00
+++ b/include/asm-arm/arch-s3c2410/regs-udc.h	2005-03-11 12:51:52 -08:00
@@ -11,13 +11,14 @@
  *    01-08-2004	Initial creation
  *    12-09-2004	Cleanup for submission
  *    24-10-2004	Fixed S3C2410_UDC_MAXP_REG definition
+ *    10-03-2005	Changed S3C2410_VA to S3C24XX_VA
  */
 
 #ifndef __ASM_ARCH_REGS_UDC_H
 #define __ASM_ARCH_REGS_UDC_H
 
 
-#define S3C2410_USBDREG(x) ((x) + S3C2410_VA_USBDEV)
+#define S3C2410_USBDREG(x) ((x) + S3C24XX_VA_USBDEV)
 
 #define S3C2410_UDC_FUNC_ADDR_REG	S3C2410_USBDREG(0x0140)
 #define S3C2410_UDC_PWR_REG		S3C2410_USBDREG(0x0144)
diff -Nru a/include/asm-arm/arch-s3c2410/regs-watchdog.h b/include/asm-arm/arch-s3c2410/regs-watchdog.h
--- a/include/asm-arm/arch-s3c2410/regs-watchdog.h	2005-03-11 12:51:41 -08:00
+++ b/include/asm-arm/arch-s3c2410/regs-watchdog.h	2005-03-11 12:51:41 -08:00
@@ -12,13 +12,14 @@
  *  Changelog:
  *    21-06-2003     BJD     Created file
  *    12-03-2004     BJD     Updated include protection
+ *    10-03-2005     LCVR    Changed S3C2410_VA to S3C24XX_VA
 */
 
 
 #ifndef __ASM_ARCH_REGS_WATCHDOG_H
 #define __ASM_ARCH_REGS_WATCHDOG_H "$Id: watchdog.h,v 1.2 2003/04/29 13:31:09 ben Exp $"
 
-#define S3C2410_WDOGREG(x) ((x) + S3C2410_VA_WATCHDOG)
+#define S3C2410_WDOGREG(x) ((x) + S3C24XX_VA_WATCHDOG)
 
 #define S3C2410_WTCON	   S3C2410_WDOGREG(0x00)
 #define S3C2410_WTDAT	   S3C2410_WDOGREG(0x04)
diff -Nru a/include/asm-arm/arch-s3c2410/uncompress.h b/include/asm-arm/arch-s3c2410/uncompress.h
--- a/include/asm-arm/arch-s3c2410/uncompress.h	2005-03-11 12:51:52 -08:00
+++ b/include/asm-arm/arch-s3c2410/uncompress.h	2005-03-11 12:51:52 -08:00
@@ -15,6 +15,7 @@
  *  12-Mar-2004 BJD  Updated header protection
  *  12-Oct-2004 BJD  Take account of debug uart configuration
  *  15-Nov-2004 BJD  Fixed uart configuration
+ *  22-Feb-2005 BJD  Added watchdog to uncompress
 */
 
 #ifndef __ASM_ARCH_UNCOMPRESS_H
@@ -25,12 +26,16 @@
 /* defines for UART registers */
 #include "asm/arch/regs-serial.h"
 #include "asm/arch/regs-gpio.h"
+#include "asm/arch/regs-watchdog.h"
 
 #include <asm/arch/map.h>
 
 /* working in physical space... */
 #undef S3C2410_GPIOREG
+#undef S3C2410_WDOGREG
+
 #define S3C2410_GPIOREG(x) ((S3C2410_PA_GPIO + (x)))
+#define S3C2410_WDOGREG(x) ((S3C2410_PA_WATCHDOG + (x)))
 
 /* how many bytes we allow into the FIFO at a time in FIFO mode */
 #define FIFO_MAX	 (14)
@@ -56,21 +61,6 @@
 }
 
 
-/* currently we do not need the watchdog... */
-#define arch_decomp_wdog()
-
-
-static void error(char *err);
-
-static void
-arch_decomp_setup(void)
-{
-	/* we may need to setup the uart(s) here if we are not running
-	 * on an BAST... the BAST will have left the uarts configured
-	 * after calling linux.
-	 */
-}
-
 /* we can deal with the case the UARTs are being run
  * in FIFO mode, so that we don't hold up our execution
  * waiting for tx to happen...
@@ -121,5 +111,48 @@
 		putc(*ptr);
 	}
 }
+
+/* CONFIG_S3C2410_BOOT_WATCHDOG
+ *
+ * Simple boot-time watchdog setup, to reboot the system if there is
+ * any problem with the boot process
+*/
+
+#ifdef CONFIG_S3C2410_BOOT_WATCHDOG
+
+#define WDOG_COUNT (0xff00)
+
+#define __raw_writel(d,ad) do { *((volatile unsigned int *)(ad)) = (d); } while(0)
+
+static inline void arch_decomp_wdog(void)
+{
+	__raw_writel(WDOG_COUNT, S3C2410_WTCNT);
+}
+
+static void arch_decomp_wdog_start(void)
+{
+	__raw_writel(WDOG_COUNT, S3C2410_WTDAT);
+	__raw_writel(WDOG_COUNT, S3C2410_WTCNT);
+	__raw_writel(S3C2410_WTCON_ENABLE | S3C2410_WTCON_DIV128 | S3C2410_WTCON_RSTEN | S3C2410_WTCON_PRESCALE(0x40), S3C2410_WTCON);
+}
+
+#else
+#define arch_decomp_wdog_start()
+#define arch_decomp_wdog()
+#endif
+
+static void error(char *err);
+
+static void
+arch_decomp_setup(void)
+{
+	/* we may need to setup the uart(s) here if we are not running
+	 * on an BAST... the BAST will have left the uarts configured
+	 * after calling linux.
+	 */
+
+	arch_decomp_wdog_start();
+}
+
 
 #endif /* __ASM_ARCH_UNCOMPRESS_H */
diff -Nru a/include/asm-arm/cacheflush.h b/include/asm-arm/cacheflush.h
--- a/include/asm-arm/cacheflush.h	2005-03-11 12:51:51 -08:00
+++ b/include/asm-arm/cacheflush.h	2005-03-11 12:51:51 -08:00
@@ -237,16 +237,16 @@
  * space" model to handle this.
  */
 #define copy_to_user_page(vma, page, vaddr, dst, src, len) \
-	do {					\
-		flush_cache_page(vma, vaddr);	\
-		memcpy(dst, src, len);		\
-		flush_dcache_page(page);	\
+	do {							\
+		flush_cache_page(vma, vaddr, page_to_pfn(page));\
+		memcpy(dst, src, len);				\
+		flush_dcache_page(page);			\
 	} while (0)
 
 #define copy_from_user_page(vma, page, vaddr, dst, src, len) \
-	do {					\
-		flush_cache_page(vma, vaddr);	\
-		memcpy(dst, src, len);		\
+	do {							\
+		flush_cache_page(vma, vaddr, page_to_pfn(page));\
+		memcpy(dst, src, len);				\
 	} while (0)
 
 /*
@@ -269,7 +269,7 @@
 }
 
 static inline void
-flush_cache_page(struct vm_area_struct *vma, unsigned long user_addr)
+flush_cache_page(struct vm_area_struct *vma, unsigned long user_addr, unsigned long pfn)
 {
 	if (cpu_isset(smp_processor_id(), vma->vm_mm->cpu_vm_mask)) {
 		unsigned long addr = user_addr & PAGE_MASK;
@@ -312,9 +312,9 @@
 extern void flush_dcache_page(struct page *);
 
 #define flush_dcache_mmap_lock(mapping) \
-	spin_lock_irq(&(mapping)->tree_lock)
+	write_lock_irq(&(mapping)->tree_lock)
 #define flush_dcache_mmap_unlock(mapping) \
-	spin_unlock_irq(&(mapping)->tree_lock)
+	write_unlock_irq(&(mapping)->tree_lock)
 
 #define flush_icache_user_range(vma,page,addr,len) \
 	flush_dcache_page(page)
diff -Nru a/include/asm-arm/ecard.h b/include/asm-arm/ecard.h
--- a/include/asm-arm/ecard.h	2005-03-11 12:51:51 -08:00
+++ b/include/asm-arm/ecard.h	2005-03-11 12:51:51 -08:00
@@ -155,8 +155,8 @@
 	struct resource		resource[ECARD_NUM_RESOURCES];
 
 	/* Public data */
-	volatile unsigned char *irqaddr;	/* address of IRQ register	*/
-	volatile unsigned char *fiqaddr;	/* address of FIQ register	*/
+	void __iomem		*irqaddr;	/* address of IRQ register	*/
+	void __iomem		*fiqaddr;	/* address of FIQ register	*/
 	unsigned char		irqmask;	/* IRQ mask			*/
 	unsigned char		fiqmask;	/* FIQ mask			*/
 	unsigned char  		claimed;	/* Card claimed?		*/
@@ -207,9 +207,16 @@
 extern int ecard_readchunk (struct in_chunk_dir *cd, struct expansion_card *ec, int id, int num);
 
 /*
- * Obtain the address of a card
+ * Obtain the address of a card.  This returns the "old style" address
+ * and should no longer be used.
  */
-extern __deprecated unsigned int ecard_address (struct expansion_card *ec, card_type_t card_type, card_speed_t speed);
+static inline unsigned int __deprecated
+ecard_address(struct expansion_card *ec, card_type_t type, card_speed_t speed)
+{
+	extern unsigned int __ecard_address(struct expansion_card *,
+					    card_type_t, card_speed_t);
+	return __ecard_address(ec, type, speed);
+}
 
 /*
  * Request and release ecard resources
diff -Nru a/include/asm-arm/hardware/locomo.h b/include/asm-arm/hardware/locomo.h
--- a/include/asm-arm/hardware/locomo.h	2005-03-11 12:51:42 -08:00
+++ b/include/asm-arm/hardware/locomo.h	2005-03-11 12:51:42 -08:00
@@ -35,146 +35,139 @@
 #define LOCOMO_MCSX3	0x1c
 
 /* Touch panel controller */
-#define LOCOMO_ASD	0x20	/* AD start delay */
-#define LOCOMO_HSD	0x28	/* HSYS delay */
-#define LOCOMO_HSC	0x2c	/* HSYS period */
-#define LOCOMO_TADC	0x30	/* tablet ADC clock */
-
-/* TFT signal */
-#define LOCOMO_TC	0x38	/* TFT control signal */
-#define LOCOMO_CPSD	0x3c	/* CPS delay */
-
-/* Key controller */
-#define LOCOMO_KIB	0x40	/* KIB level */
-#define LOCOMO_KSC	0x44	/* KSTRB control */
-#define LOCOMO_KCMD	0x48	/* KSTRB command */
-#define LOCOMO_KIC	0x4c	/* Key interrupt */
+#define LOCOMO_ASD	0x20		/* AD start delay */
+#define LOCOMO_HSD	0x28		/* HSYS delay */
+#define LOCOMO_HSC	0x2c		/* HSYS period */
+#define LOCOMO_TADC	0x30		/* tablet ADC clock */
 
-/* Audio clock */
-#define LOCOMO_ACC	0x54
-
-/* SPI interface */
-#define LOCOMO_SPIMD	0x60	/* SPI mode setting */
-#define LOCOMO_SPICT	0x64	/* SPI mode control */
-#define LOCOMO_SPIST	0x68	/* SPI status */
-#define LOCOMO_SPIIS	0x70	/* SPI interrupt status */
-#define LOCOMO_SPIWE	0x74	/* SPI interrupt status write enable */
-#define LOCOMO_SPIIE	0x78	/* SPI interrupt enable */
-#define LOCOMO_SPIIR	0x7c	/* SPI interrupt request */
-#define LOCOMO_SPITD	0x80	/* SPI transfer data write */
-#define LOCOMO_SPIRD	0x84	/* SPI receive data read */
-#define LOCOMO_SPITS	0x88	/* SPI transfer data shift */
-#define LOCOMO_SPIRS	0x8C	/* SPI receive data shift */
-
-#define	LOCOMO_SPI_TEND	(1 << 3)	/* Transfer end bit */
-#define	LOCOMO_SPI_OVRN	(1 << 2)	/* Over Run bit */
-#define	LOCOMO_SPI_RFW	(1 << 1)	/* write buffer bit */
-#define	LOCOMO_SPI_RFR	(1)		/* read buffer bit */
-
-/* GPIO */
-#define LOCOMO_GPD	0x90	/* GPIO direction */
-#define LOCOMO_GPE	0x94	/* GPIO input enable */
-#define LOCOMO_GPL	0x98	/* GPIO level */
-#define LOCOMO_GPO	0x9c	/* GPIO out data setteing */
-#define LOCOMO_GRIE	0xa0	/* GPIO rise detection */
-#define LOCOMO_GFIE	0xa4	/* GPIO fall detection */
-#define LOCOMO_GIS	0xa8	/* GPIO edge detection status */
-#define LOCOMO_GWE	0xac	/* GPIO status write enable */
-#define LOCOMO_GIE	0xb0	/* GPIO interrupt enable */
-#define LOCOMO_GIR	0xb4	/* GPIO interrupt request */
-
-#define LOCOMO_GPIO0	(1<<0)
-#define LOCOMO_GPIO1	(1<<1)
-#define LOCOMO_GPIO2	(1<<2)
-#define LOCOMO_GPIO3	(1<<3)
-#define LOCOMO_GPIO4	(1<<4)
-#define LOCOMO_GPIO5	(1<<5)
-#define LOCOMO_GPIO6	(1<<6)
-#define LOCOMO_GPIO7	(1<<7)
-#define LOCOMO_GPIO8	(1<<8)
-#define LOCOMO_GPIO9	(1<<9)
-#define LOCOMO_GPIO10	(1<<10)
-#define LOCOMO_GPIO11	(1<<11)
-#define LOCOMO_GPIO12	(1<<12)
-#define LOCOMO_GPIO13	(1<<13)
-#define LOCOMO_GPIO14	(1<<14)
-#define LOCOMO_GPIO15	(1<<15)
-
-/* Front light adjustment controller */
-#define LOCOMO_ALS	0xc8	/* Adjust light cycle */
-#define LOCOMO_ALD	0xcc	/* Adjust light duty */
-
-/* PCM audio interface */
-#define LOCOMO_PAIF	0xd0
 
 /* Long time timer */
-#define LOCOMO_LTC	0xd8	/* LTC interrupt setting */
-#define LOCOMO_LTINT	0xdc	/* LTC interrupt */
+#define LOCOMO_LTC	0xd8		/* LTC interrupt setting */
+#define LOCOMO_LTINT	0xdc		/* LTC interrupt */
 
 /* DAC control signal for LCD (COMADJ ) */
-#define LOCOMO_DAC	0xe0
-
+#define LOCOMO_DAC		0xe0
 /* DAC control */
 #define	LOCOMO_DAC_SCLOEB	0x08	/* SCL pin output data       */
 #define	LOCOMO_DAC_TEST		0x04	/* Test bit                  */
 #define	LOCOMO_DAC_SDA		0x02	/* SDA pin level (read-only) */
 #define	LOCOMO_DAC_SDAOEB	0x01	/* SDA pin output data       */
 
-/* LED controller */
-#define LOCOMO_LPT0		0xe8	/* LEDPWM0 timer */
-#define LOCOMO_LPT1		0xec	/* LEDPWM1 timer */
+/* SPI interface */
+#define LOCOMO_SPIMD	0x60		/* SPI mode setting */
+#define LOCOMO_SPICT	0x64		/* SPI mode control */
+#define LOCOMO_SPIST	0x68		/* SPI status */
+#define LOCOMO_SPIIS	0x70		/* SPI interrupt status */
+#define LOCOMO_SPIWE	0x74		/* SPI interrupt status write enable */
+#define LOCOMO_SPIIE	0x78		/* SPI interrupt enable */
+#define LOCOMO_SPIIR	0x7c		/* SPI interrupt request */
+#define LOCOMO_SPITD	0x80		/* SPI transfer data write */
+#define LOCOMO_SPIRD	0x84		/* SPI receive data read */
+#define LOCOMO_SPITS	0x88		/* SPI transfer data shift */
+#define LOCOMO_SPIRS	0x8C		/* SPI receive data shift */
+#define	LOCOMO_SPI_TEND	(1 << 3)	/* Transfer end bit */
+#define	LOCOMO_SPI_OVRN	(1 << 2)	/* Over Run bit */
+#define	LOCOMO_SPI_RFW	(1 << 1)	/* write buffer bit */
+#define	LOCOMO_SPI_RFR	(1)		/* read buffer bit */
 
-#define LOCOMO_LPT_TOFH		0x80			/* */
-#define LOCOMO_LPT_TOFL		0x08			/* */
-#define LOCOMO_LPT_TOH(TOH)	((TOH & 0x7) << 4)	/* */
-#define LOCOMO_LPT_TOL(TOL)	((TOL & 0x7))		/* */
+/* GPIO */
+#define LOCOMO_GPD		0x90	/* GPIO direction */
+#define LOCOMO_GPE		0x94	/* GPIO input enable */
+#define LOCOMO_GPL		0x98	/* GPIO level */
+#define LOCOMO_GPO		0x9c	/* GPIO out data setteing */
+#define LOCOMO_GRIE		0xa0	/* GPIO rise detection */
+#define LOCOMO_GFIE		0xa4	/* GPIO fall detection */
+#define LOCOMO_GIS		0xa8	/* GPIO edge detection status */
+#define LOCOMO_GWE		0xac	/* GPIO status write enable */
+#define LOCOMO_GIE		0xb0	/* GPIO interrupt enable */
+#define LOCOMO_GIR		0xb4	/* GPIO interrupt request */
+#define	LOCOMO_GPIO(Nb)		(0x01 << (Nb))
+#define LOCOMO_GPIO_RTS		LOCOMO_GPIO(0)
+#define LOCOMO_GPIO_CTS		LOCOMO_GPIO(1)
+#define LOCOMO_GPIO_DSR		LOCOMO_GPIO(2)
+#define LOCOMO_GPIO_DTR		LOCOMO_GPIO(3)
+#define LOCOMO_GPIO_LCD_VSHA_ON	LOCOMO_GPIO(4)
+#define LOCOMO_GPIO_LCD_VSHD_ON	LOCOMO_GPIO(5)
+#define LOCOMO_GPIO_LCD_VEE_ON	LOCOMO_GPIO(6)
+#define LOCOMO_GPIO_LCD_MOD	LOCOMO_GPIO(7)
+#define LOCOMO_GPIO_DAC_ON	LOCOMO_GPIO(8)
+#define LOCOMO_GPIO_FL_VR	LOCOMO_GPIO(9)
+#define LOCOMO_GPIO_DAC_SDATA	LOCOMO_GPIO(10)
+#define LOCOMO_GPIO_DAC_SCK	LOCOMO_GPIO(11)
+#define LOCOMO_GPIO_DAC_SLOAD	LOCOMO_GPIO(12)
+
+/* Start the definitions of the devices.  Each device has an initial
+ * base address and a series of offsets from that base address. */
+
+/* Keyboard controller */
+#define LOCOMO_KEYBOARD		0x40
+#define LOCOMO_KIB		0x00	/* KIB level */
+#define LOCOMO_KSC		0x04	/* KSTRB control */
+#define LOCOMO_KCMD		0x08	/* KSTRB command */
+#define LOCOMO_KIC		0x0c	/* Key interrupt */
 
+/* Front light adjustment controller */
+#define LOCOMO_FRONTLIGHT	0xc8
+#define LOCOMO_ALS		0x00	/* Adjust light cycle */
+#define LOCOMO_ALD		0x04	/* Adjust light duty */
+
+/* Backlight controller: TFT signal */
+#define LOCOMO_BACKLIGHT	0x38
+#define LOCOMO_TC		0x00		/* TFT control signal */
+#define LOCOMO_CPSD		0x04		/* CPS delay */
+
+/* Audio controller */
+#define LOCOMO_AUDIO		0x54
+#define LOCOMO_ACC		0x00	/* Audio clock */
+#define LOCOMO_PAIF		0x7C	/* PCM audio interface */
 /* Audio clock */
-#define	LOCOMO_ACC_XON		0x80	/*  */
-#define	LOCOMO_ACC_XEN		0x40	/*  */
-#define	LOCOMO_ACC_XSEL0	0x00	/*  */
-#define	LOCOMO_ACC_XSEL1	0x20	/*  */
-#define	LOCOMO_ACC_MCLKEN	0x10	/*  */
-#define	LOCOMO_ACC_64FSEN	0x08	/*  */
+#define	LOCOMO_ACC_XON		0x80
+#define	LOCOMO_ACC_XEN		0x40
+#define	LOCOMO_ACC_XSEL0	0x00
+#define	LOCOMO_ACC_XSEL1	0x20
+#define	LOCOMO_ACC_MCLKEN	0x10
+#define	LOCOMO_ACC_64FSEN	0x08
 #define	LOCOMO_ACC_CLKSEL000	0x00	/* mclk  2 */
 #define	LOCOMO_ACC_CLKSEL001	0x01	/* mclk  3 */
 #define	LOCOMO_ACC_CLKSEL010	0x02	/* mclk  4 */
 #define	LOCOMO_ACC_CLKSEL011	0x03	/* mclk  6 */
 #define	LOCOMO_ACC_CLKSEL100	0x04	/* mclk  8 */
 #define	LOCOMO_ACC_CLKSEL101	0x05	/* mclk 12 */
-
 /* PCM audio interface */
-#define	LOCOMO_PAIF_SCINV	0x20	/*  */
-#define	LOCOMO_PAIF_SCEN	0x10	/*  */
-#define	LOCOMO_PAIF_LRCRST	0x08	/*  */
-#define	LOCOMO_PAIF_LRCEVE	0x04	/*  */
-#define	LOCOMO_PAIF_LRCINV	0x02	/*  */
-#define	LOCOMO_PAIF_LRCEN	0x01	/*  */
+#define	LOCOMO_PAIF_SCINV	0x20
+#define	LOCOMO_PAIF_SCEN	0x10
+#define	LOCOMO_PAIF_LRCRST	0x08
+#define	LOCOMO_PAIF_LRCEVE	0x04
+#define	LOCOMO_PAIF_LRCINV	0x02
+#define	LOCOMO_PAIF_LRCEN	0x01
 
-/* GPIO */
-#define	LOCOMO_GPIO(Nb)		(0x01 << (Nb))	/* LoCoMo GPIO [0...15] */
-#define LOCOMO_GPIO_RTS		LOCOMO_GPIO(0)	/* LoCoMo GPIO  [0] */
-#define LOCOMO_GPIO_CTS		LOCOMO_GPIO(1)	/* LoCoMo GPIO  [1] */
-#define LOCOMO_GPIO_DSR		LOCOMO_GPIO(2)	/* LoCoMo GPIO  [2] */
-#define LOCOMO_GPIO_DTR		LOCOMO_GPIO(3)	/* LoCoMo GPIO  [3] */
-#define LOCOMO_GPIO_LCD_VSHA_ON	LOCOMO_GPIO(4)	/* LoCoMo GPIO  [4] */
-#define LOCOMO_GPIO_LCD_VSHD_ON	LOCOMO_GPIO(5)	/* LoCoMo GPIO  [5] */
-#define LOCOMO_GPIO_LCD_VEE_ON	LOCOMO_GPIO(6)	/* LoCoMo GPIO  [6] */
-#define LOCOMO_GPIO_LCD_MOD	LOCOMO_GPIO(7)	/* LoCoMo GPIO  [7] */
-#define LOCOMO_GPIO_DAC_ON	LOCOMO_GPIO(8)	/* LoCoMo GPIO  [8] */
-#define LOCOMO_GPIO_FL_VR	LOCOMO_GPIO(9)	/* LoCoMo GPIO  [9] */
-#define LOCOMO_GPIO_DAC_SDATA	LOCOMO_GPIO(10)	/* LoCoMo GPIO [10] */
-#define LOCOMO_GPIO_DAC_SCK	LOCOMO_GPIO(11)	/* LoCoMo GPIO [11] */
-#define LOCOMO_GPIO_DAC_SLOAD	LOCOMO_GPIO(12)	/* LoCoMo GPIO [12] */
+/* LED controller */
+#define LOCOMO_LED		0xe8
+#define LOCOMO_LPT0		0x00
+#define LOCOMO_LPT1		0x04
+/* LED control */
+#define LOCOMO_LPT_TOFH		0x80
+#define LOCOMO_LPT_TOFL		0x08
+#define LOCOMO_LPT_TOH(TOH)	((TOH & 0x7) << 4)
+#define LOCOMO_LPT_TOL(TOL)	((TOL & 0x7))
 
 extern struct bus_type locomo_bus_type;
 
+#define LOCOMO_DEVID_KEYBOARD	0
+#define LOCOMO_DEVID_FRONTLIGHT	1
+#define LOCOMO_DEVID_BACKLIGHT	2
+#define LOCOMO_DEVID_AUDIO	3
+#define LOCOMO_DEVID_LED	4
+#define LOCOMO_DEVID_UART	5
+
 struct locomo_dev {
 	struct device	dev;
 	unsigned int	devid;
-	struct resource	res;
-	void		*mapbase;
 	unsigned int	irq[1];
+
+	void		*mapbase;
+	unsigned long	length;
+
 	u64		dma_mask;
 };
 
@@ -200,5 +193,14 @@
 
 int locomo_driver_register(struct locomo_driver *);
 void locomo_driver_unregister(struct locomo_driver *);
+
+/* GPIO control functions */
+void locomo_gpio_set_dir(struct locomo_dev *ldev, unsigned int bits, unsigned int dir);
+unsigned int locomo_gpio_read_level(struct locomo_dev *ldev, unsigned int bits);
+unsigned int locomo_gpio_read_output(struct locomo_dev *ldev, unsigned int bits);
+void locomo_gpio_write(struct locomo_dev *ldev, unsigned int bits, unsigned int set);
+
+/* M62332 control function */
+void locomo_m62332_senddata(struct locomo_dev *ldev, unsigned int dac_data, int channel);
 
 #endif
diff -Nru a/include/asm-arm/hardware/scoop.h b/include/asm-arm/hardware/scoop.h
--- a/include/asm-arm/hardware/scoop.h	2005-03-11 12:51:46 -08:00
+++ b/include/asm-arm/hardware/scoop.h	2005-03-11 12:51:46 -08:00
@@ -40,8 +40,8 @@
 	unsigned short io_dir;
 };
 
-void reset_scoop(void);
-unsigned short set_scoop_gpio(unsigned short bit);
-unsigned short reset_scoop_gpio(unsigned short bit);
-unsigned short read_scoop_reg(unsigned short reg);
-void write_scoop_reg(unsigned short reg, unsigned short data);
+void reset_scoop(struct device *dev);
+unsigned short set_scoop_gpio(struct device *dev, unsigned short bit);
+unsigned short reset_scoop_gpio(struct device *dev, unsigned short bit);
+unsigned short read_scoop_reg(struct device *dev, unsigned short reg);
+void write_scoop_reg(struct device *dev, unsigned short reg, unsigned short data);
diff -Nru a/include/asm-arm/io.h b/include/asm-arm/io.h
--- a/include/asm-arm/io.h	2005-03-11 12:51:42 -08:00
+++ b/include/asm-arm/io.h	2005-03-11 12:51:42 -08:00
@@ -47,13 +47,13 @@
 extern void __raw_readsw(void __iomem *addr, void *data, int wordlen);
 extern void __raw_readsl(void __iomem *addr, void *data, int longlen);
 
-#define __raw_writeb(v,a)	(*(volatile unsigned char __force  *)(a) = (v))
-#define __raw_writew(v,a)	(*(volatile unsigned short __force *)(a) = (v))
-#define __raw_writel(v,a)	(*(volatile unsigned int __force   *)(a) = (v))
+#define __raw_writeb(v,a)	(__chk_io_ptr(a), *(volatile unsigned char __force  *)(a) = (v))
+#define __raw_writew(v,a)	(__chk_io_ptr(a), *(volatile unsigned short __force *)(a) = (v))
+#define __raw_writel(v,a)	(__chk_io_ptr(a), *(volatile unsigned int __force   *)(a) = (v))
 
-#define __raw_readb(a)		(*(volatile unsigned char __force  *)(a))
-#define __raw_readw(a)		(*(volatile unsigned short __force *)(a))
-#define __raw_readl(a)		(*(volatile unsigned int __force   *)(a))
+#define __raw_readb(a)		(__chk_io_ptr(a), *(volatile unsigned char __force  *)(a))
+#define __raw_readw(a)		(__chk_io_ptr(a), *(volatile unsigned short __force *)(a))
+#define __raw_readl(a)		(__chk_io_ptr(a), *(volatile unsigned int __force   *)(a))
 
 /*
  * Bad read/write accesses...
diff -Nru a/include/asm-arm/pgtable.h b/include/asm-arm/pgtable.h
--- a/include/asm-arm/pgtable.h	2005-03-11 12:51:42 -08:00
+++ b/include/asm-arm/pgtable.h	2005-03-11 12:51:42 -08:00
@@ -106,6 +106,13 @@
 #define USER_PTRS_PER_PGD	((TASK_SIZE/PGDIR_SIZE) - FIRST_USER_PGD_NR)
 
 /*
+ * ARMv6 supersection address mask and size definitions.
+ */
+#define SUPERSECTION_SHIFT	24
+#define SUPERSECTION_SIZE	(1UL << SUPERSECTION_SHIFT)
+#define SUPERSECTION_MASK	(~(SUPERSECTION_SIZE-1))
+
+/*
  * Hardware page table definitions.
  *
  * + Level 1 descriptor (PMD)
@@ -129,6 +136,7 @@
 #define PMD_SECT_APX		(1 << 15)	/* v6 */
 #define PMD_SECT_S		(1 << 16)	/* v6 */
 #define PMD_SECT_nG		(1 << 17)	/* v6 */
+#define PMD_SECT_SUPER		(1 << 18)	/* v6 */
 
 #define PMD_SECT_UNCACHED	(0)
 #define PMD_SECT_BUFFERED	(PMD_SECT_BUFFERABLE)
@@ -254,7 +262,7 @@
 #define pfn_pte(pfn,prot)	(__pte(((pfn) << PAGE_SHIFT) | pgprot_val(prot)))
 
 #define pte_none(pte)		(!pte_val(pte))
-#define pte_clear(ptep)		set_pte((ptep), __pte(0))
+#define pte_clear(mm,addr,ptep)	set_pte_at((mm),(addr),(ptep), __pte(0))
 #define pte_page(pte)		(pfn_to_page(pte_pfn(pte)))
 #define pte_offset_kernel(dir,addr)	(pmd_page_kernel(*(dir)) + __pte_index(addr))
 #define pte_offset_map(dir,addr)	(pmd_page_kernel(*(dir)) + __pte_index(addr))
@@ -263,6 +271,7 @@
 #define pte_unmap_nested(pte)	do { } while (0)
 
 #define set_pte(ptep, pte)	cpu_set_pte(ptep,pte)
+#define set_pte_at(mm,addr,ptep,pteval) set_pte(ptep,pteval)
 
 /*
  * The following only work if pte_present() is true.
@@ -307,12 +316,6 @@
 #define pmd_none(pmd)		(!pmd_val(pmd))
 #define pmd_present(pmd)	(pmd_val(pmd))
 #define pmd_bad(pmd)		(pmd_val(pmd) & 2)
-
-#define set_pmd(pmdp,pmd)		\
-	do {				\
-		*(pmdp) = pmd;		\
-		flush_pmd_entry(pmdp);	\
-	} while (0)
 
 #define copy_pmd(pmdpd,pmdps)		\
 	do {				\
diff -Nru a/include/asm-arm/rtc.h b/include/asm-arm/rtc.h
--- a/include/asm-arm/rtc.h	2005-03-11 12:51:47 -08:00
+++ b/include/asm-arm/rtc.h	2005-03-11 12:51:47 -08:00
@@ -27,6 +27,7 @@
 
 void rtc_time_to_tm(unsigned long, struct rtc_time *);
 int rtc_tm_to_time(struct rtc_time *, unsigned long *);
+int rtc_valid_tm(struct rtc_time *);
 void rtc_next_alarm_time(struct rtc_time *, struct rtc_time *, struct rtc_time *);
 void rtc_update(unsigned long, unsigned long);
 int register_rtc(struct rtc_ops *);
diff -Nru a/include/asm-arm/system.h b/include/asm-arm/system.h
--- a/include/asm-arm/system.h	2005-03-11 12:51:41 -08:00
+++ b/include/asm-arm/system.h	2005-03-11 12:51:41 -08:00
@@ -383,6 +383,8 @@
 
 #endif /* __ASSEMBLY__ */
 
+#define arch_align_stack(x) (x)
+
 #endif /* __KERNEL__ */
 
 #endif
diff -Nru a/include/asm-arm/unistd.h b/include/asm-arm/unistd.h
--- a/include/asm-arm/unistd.h	2005-03-11 12:51:51 -08:00
+++ b/include/asm-arm/unistd.h	2005-03-11 12:51:51 -08:00
@@ -1,7 +1,7 @@
 /*
  *  linux/include/asm-arm/unistd.h
  *
- *  Copyright (C) 2001-2003 Russell King
+ *  Copyright (C) 2001-2005 Russell King
  *
  * 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
@@ -307,6 +307,44 @@
 #define __NR_mq_getsetattr		(__NR_SYSCALL_BASE+279)
 #define __NR_waitid			(__NR_SYSCALL_BASE+280)
 
+#if 0 /* reserve these for un-muxing socketcall */
+#define __NR_socket			(__NR_SYSCALL_BASE+281)
+#define __NR_bind			(__NR_SYSCALL_BASE+282)
+#define __NR_connect			(__NR_SYSCALL_BASE+283)
+#define __NR_listen			(__NR_SYSCALL_BASE+284)
+#define __NR_accept			(__NR_SYSCALL_BASE+285)
+#define __NR_getsockname		(__NR_SYSCALL_BASE+286)
+#define __NR_getpeername		(__NR_SYSCALL_BASE+287)
+#define __NR_socketpair			(__NR_SYSCALL_BASE+288)
+#define __NR_send			(__NR_SYSCALL_BASE+289)
+#define __NR_sendto			(__NR_SYSCALL_BASE+290)
+#define __NR_recv			(__NR_SYSCALL_BASE+291)
+#define __NR_recvfrom			(__NR_SYSCALL_BASE+292)
+#define __NR_shutdown			(__NR_SYSCALL_BASE+293)
+#define __NR_setsockopt			(__NR_SYSCALL_BASE+294)
+#define __NR_getsockopt			(__NR_SYSCALL_BASE+295)
+#define __NR_sendmsg			(__NR_SYSCALL_BASE+296)
+#define __NR_recvmsg			(__NR_SYSCALL_BASE+297)
+#endif
+
+#if 0 /* reserve these for un-muxing ipc */
+#define __NR_semop			(__NR_SYSCALL_BASE+298)
+#define __NR_semget			(__NR_SYSCALL_BASE+299)
+#define __NR_semctl			(__NR_SYSCALL_BASE+300)
+#define __NR_msgsnd			(__NR_SYSCALL_BASE+301)
+#define __NR_msgrcv			(__NR_SYSCALL_BASE+302)
+#define __NR_msgget			(__NR_SYSCALL_BASE+303)
+#define __NR_msgctl			(__NR_SYSCALL_BASE+304)
+#define __NR_shmat			(__NR_SYSCALL_BASE+305)
+#define __NR_shmdt			(__NR_SYSCALL_BASE+306)
+#define __NR_shmget			(__NR_SYSCALL_BASE+307)
+#define __NR_shmctl			(__NR_SYSCALL_BASE+308)
+#endif
+
+#define __NR_add_key			(__NR_SYSCALL_BASE+309)
+#define __NR_request_key		(__NR_SYSCALL_BASE+310)
+#define __NR_keyctl			(__NR_SYSCALL_BASE+311)
+
 /*
  * The following SWIs are ARM private.
  */
@@ -335,7 +373,7 @@
 
 #define __syscall_return(type, res)					\
 do {									\
-	if ((unsigned long)(res) >= (unsigned long)(-125)) {		\
+	if ((unsigned long)(res) >= (unsigned long)(-129)) {		\
 		errno = -(res);						\
 		res = -1;						\
 	}								\
@@ -509,6 +547,6 @@
  * What we want is __attribute__((weak,alias("sys_ni_syscall"))),
  * but it doesn't work on all toolchains, so we just do it by hand
  */
-#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall");
+#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall")
 
 #endif /* __ASM_ARM_UNISTD_H */
diff -Nru a/include/asm-arm26/cacheflush.h b/include/asm-arm26/cacheflush.h
--- a/include/asm-arm26/cacheflush.h	2005-03-11 12:51:47 -08:00
+++ b/include/asm-arm26/cacheflush.h	2005-03-11 12:51:47 -08:00
@@ -23,7 +23,7 @@
 #define flush_cache_all()                       do { } while (0)
 #define flush_cache_mm(mm)                      do { } while (0)
 #define flush_cache_range(vma,start,end)        do { } while (0)
-#define flush_cache_page(vma,vmaddr)            do { } while (0)
+#define flush_cache_page(vma,vmaddr,pfn)        do { } while (0)
 #define flush_cache_vmap(start, end)		do { } while (0)
 #define flush_cache_vunmap(start, end)		do { } while (0)
 
diff -Nru a/include/asm-arm26/pgtable.h b/include/asm-arm26/pgtable.h
--- a/include/asm-arm26/pgtable.h	2005-03-11 12:51:41 -08:00
+++ b/include/asm-arm26/pgtable.h	2005-03-11 12:51:41 -08:00
@@ -154,7 +154,8 @@
 #define pte_none(pte)           (!pte_val(pte))
 #define pte_present(pte)        (pte_val(pte) & _PAGE_PRESENT)
 #define set_pte(pte_ptr, pte)   ((*(pte_ptr)) = (pte))
-#define pte_clear(ptep)         set_pte((ptep), __pte(0))
+#define set_pte_at(mm,addr,ptep,pteval) set_pte(ptep,pteval)
+#define pte_clear(mm,addr,ptep)	set_pte_at((mm),(addr),(ptep), __pte(0))
 
 /* macros to ease the getting of pointers to stuff... */
 #define pgd_offset(mm, addr)	((pgd_t *)(mm)->pgd        + __pgd_index(addr))
diff -Nru a/include/asm-arm26/system.h b/include/asm-arm26/system.h
--- a/include/asm-arm26/system.h	2005-03-11 12:51:51 -08:00
+++ b/include/asm-arm26/system.h	2005-03-11 12:51:51 -08:00
@@ -245,6 +245,8 @@
 
 #endif /* __ASSEMBLY__ */
 
+#define arch_align_stack(x) (x)
+
 #endif /* __KERNEL__ */
 
 #endif
diff -Nru a/include/asm-arm26/unistd.h b/include/asm-arm26/unistd.h
--- a/include/asm-arm26/unistd.h	2005-03-11 12:51:52 -08:00
+++ b/include/asm-arm26/unistd.h	2005-03-11 12:51:52 -08:00
@@ -495,6 +495,6 @@
  * What we want is __attribute__((weak,alias("sys_ni_syscall"))),
  * but it doesn't work on all toolchains, so we just do it by hand
  */
-#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall");
+#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall")
 
 #endif /* __ASM_ARM_UNISTD_H */
diff -Nru a/include/asm-cris/cacheflush.h b/include/asm-cris/cacheflush.h
--- a/include/asm-cris/cacheflush.h	2005-03-11 12:51:40 -08:00
+++ b/include/asm-cris/cacheflush.h	2005-03-11 12:51:40 -08:00
@@ -10,7 +10,7 @@
 #define flush_cache_all()			do { } while (0)
 #define flush_cache_mm(mm)			do { } while (0)
 #define flush_cache_range(vma, start, end)	do { } while (0)
-#define flush_cache_page(vma, vmaddr)		do { } while (0)
+#define flush_cache_page(vma, vmaddr, pfn)	do { } while (0)
 #define flush_dcache_page(page)			do { } while (0)
 #define flush_dcache_mmap_lock(mapping)		do { } while (0)
 #define flush_dcache_mmap_unlock(mapping)	do { } while (0)
diff -Nru a/include/asm-cris/pgtable.h b/include/asm-cris/pgtable.h
--- a/include/asm-cris/pgtable.h	2005-03-11 12:51:41 -08:00
+++ b/include/asm-cris/pgtable.h	2005-03-11 12:51:41 -08:00
@@ -34,6 +34,8 @@
  * hook is made available.
  */
 #define set_pte(pteptr, pteval) ((*(pteptr)) = (pteval))
+#define set_pte_at(mm,addr,ptep,pteval) set_pte(ptep,pteval)
+
 /*
  * (pmds are folded into pgds so this doesn't get actually called,
  * but the define is needed for a generic inline function.)
@@ -101,7 +103,7 @@
 
 #define pte_none(x)	(!pte_val(x))
 #define pte_present(x)	(pte_val(x) & _PAGE_PRESENT)
-#define pte_clear(xp)	do { pte_val(*(xp)) = 0; } while (0)
+#define pte_clear(mm,addr,xp)	do { pte_val(*(xp)) = 0; } while (0)
 
 #define pmd_none(x)	(!pmd_val(x))
 /* by removing the _PAGE_KERNEL bit from the comparision, the same pmd_bad
diff -Nru a/include/asm-cris/system.h b/include/asm-cris/system.h
--- a/include/asm-cris/system.h	2005-03-11 12:51:46 -08:00
+++ b/include/asm-cris/system.h	2005-03-11 12:51:46 -08:00
@@ -69,4 +69,6 @@
   return x;
 }
 
+#define arch_align_stack(x) (x)
+
 #endif
diff -Nru a/include/asm-cris/unistd.h b/include/asm-cris/unistd.h
--- a/include/asm-cris/unistd.h	2005-03-11 12:51:51 -08:00
+++ b/include/asm-cris/unistd.h	2005-03-11 12:51:51 -08:00
@@ -387,6 +387,6 @@
  * What we want is __attribute__((weak,alias("sys_ni_syscall"))),
  * but it doesn't work on all toolchains, so we just do it by hand
  */
-#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall");
+#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall")
 
 #endif /* _ASM_CRIS_UNISTD_H_ */
diff -Nru a/include/asm-frv/cacheflush.h b/include/asm-frv/cacheflush.h
--- a/include/asm-frv/cacheflush.h	2005-03-11 12:51:52 -08:00
+++ b/include/asm-frv/cacheflush.h	2005-03-11 12:51:52 -08:00
@@ -21,7 +21,7 @@
 #define flush_cache_all()			do {} while(0)
 #define flush_cache_mm(mm)			do {} while(0)
 #define flush_cache_range(mm, start, end)	do {} while(0)
-#define flush_cache_page(vma, vmaddr)		do {} while(0)
+#define flush_cache_page(vma, vmaddr, pfn)	do {} while(0)
 #define flush_cache_vmap(start, end)		do {} while(0)
 #define flush_cache_vunmap(start, end)		do {} while(0)
 #define flush_dcache_mmap_lock(mapping)		do {} while(0)
diff -Nru a/include/asm-frv/pgtable.h b/include/asm-frv/pgtable.h
--- a/include/asm-frv/pgtable.h	2005-03-11 12:51:40 -08:00
+++ b/include/asm-frv/pgtable.h	2005-03-11 12:51:40 -08:00
@@ -173,6 +173,7 @@
 	*(pteptr) = (pteval);				\
 	asm volatile("dcf %M0" :: "U"(*pteptr));	\
 } while(0)
+#define set_pte_at(mm,addr,ptep,pteval) set_pte(ptep,pteval)
 
 #define set_pte_atomic(pteptr, pteval)		set_pte((pteptr), (pteval))
 
@@ -353,7 +354,7 @@
 #undef TEST_VERIFY_AREA
 
 #define pte_present(x)	(pte_val(x) & _PAGE_PRESENT)
-#define pte_clear(xp)	do { set_pte(xp, __pte(0)); } while (0)
+#define pte_clear(mm,addr,xp)	do { set_pte_at(mm, addr, xp, __pte(0)); } while (0)
 
 #define pmd_none(x)	(!pmd_val(x))
 #define pmd_present(x)	(pmd_val(x) & _PAGE_PRESENT)
@@ -390,39 +391,33 @@
 static inline pte_t pte_mkyoung(pte_t pte)	{ (pte).pte |= _PAGE_ACCESSED; return pte; }
 static inline pte_t pte_mkwrite(pte_t pte)	{ (pte).pte &= ~_PAGE_WP; return pte; }
 
-static inline int ptep_test_and_clear_dirty(pte_t *ptep)
+static inline int ptep_test_and_clear_dirty(struct vm_area_struct *vma, unsigned long addr, pte_t *ptep)
 {
 	int i = test_and_clear_bit(_PAGE_BIT_DIRTY, ptep);
 	asm volatile("dcf %M0" :: "U"(*ptep));
 	return i;
 }
 
-static inline int ptep_test_and_clear_young(pte_t *ptep)
+static inline int ptep_test_and_clear_young(struct vm_area_struct *vma, unsigned long addr, pte_t *ptep)
 {
 	int i = test_and_clear_bit(_PAGE_BIT_ACCESSED, ptep);
 	asm volatile("dcf %M0" :: "U"(*ptep));
 	return i;
 }
 
-static inline pte_t ptep_get_and_clear(pte_t *ptep)
+static inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
 {
 	unsigned long x = xchg(&ptep->pte, 0);
 	asm volatile("dcf %M0" :: "U"(*ptep));
 	return __pte(x);
 }
 
-static inline void ptep_set_wrprotect(pte_t *ptep)
+static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
 {
 	set_bit(_PAGE_BIT_WP, ptep);
 	asm volatile("dcf %M0" :: "U"(*ptep));
 }
 
-static inline void ptep_mkdirty(pte_t *ptep)
-{
-	set_bit(_PAGE_BIT_DIRTY, ptep);
-	asm volatile("dcf %M0" :: "U"(*ptep));
-}
-
 /*
  * Conversion functions: convert a page and protection to a page entry,
  * and a page entry and page directory to the page they refer to.
@@ -512,7 +507,6 @@
 #define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_DIRTY
 #define __HAVE_ARCH_PTEP_GET_AND_CLEAR
 #define __HAVE_ARCH_PTEP_SET_WRPROTECT
-#define __HAVE_ARCH_PTEP_MKDIRTY
 #define __HAVE_ARCH_PTE_SAME
 #include <asm-generic/pgtable.h>
 
diff -Nru a/include/asm-frv/system.h b/include/asm-frv/system.h
--- a/include/asm-frv/system.h	2005-03-11 12:51:50 -08:00
+++ b/include/asm-frv/system.h	2005-03-11 12:51:50 -08:00
@@ -123,4 +123,6 @@
 extern void die_if_kernel(const char *, ...) __attribute__((format(printf, 1, 2)));
 extern void free_initmem(void);
 
+#define arch_align_stack(x) (x)
+
 #endif /* _ASM_SYSTEM_H */
diff -Nru a/include/asm-frv/unistd.h b/include/asm-frv/unistd.h
--- a/include/asm-frv/unistd.h	2005-03-11 12:51:41 -08:00
+++ b/include/asm-frv/unistd.h	2005-03-11 12:51:41 -08:00
@@ -495,7 +495,7 @@
  * but it doesn't work on all toolchains, so we just do it by hand
  */
 #ifndef cond_syscall
-#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall");
+#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall")
 #endif
 
 #endif /* _ASM_UNISTD_H_ */
diff -Nru a/include/asm-generic/pgtable.h b/include/asm-generic/pgtable.h
--- a/include/asm-generic/pgtable.h	2005-03-11 12:51:42 -08:00
+++ b/include/asm-generic/pgtable.h	2005-03-11 12:51:42 -08:00
@@ -16,7 +16,7 @@
 #ifndef __HAVE_ARCH_SET_PTE_ATOMIC
 #define ptep_establish(__vma, __address, __ptep, __entry)		\
 do {				  					\
-	set_pte(__ptep, __entry);					\
+	set_pte_at((__vma)->vm_mm, (__address), __ptep, __entry);	\
 	flush_tlb_page(__vma, __address);				\
 } while (0)
 #else /* __HAVE_ARCH_SET_PTE_ATOMIC */
@@ -37,26 +37,30 @@
  */
 #define ptep_set_access_flags(__vma, __address, __ptep, __entry, __dirty) \
 do {				  					  \
-	set_pte(__ptep, __entry);					  \
+	set_pte_at((__vma)->vm_mm, (__address), __ptep, __entry);	  \
 	flush_tlb_page(__vma, __address);				  \
 } while (0)
 #endif
 
 #ifndef __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
-static inline int ptep_test_and_clear_young(pte_t *ptep)
-{
-	pte_t pte = *ptep;
-	if (!pte_young(pte))
-		return 0;
-	set_pte(ptep, pte_mkold(pte));
-	return 1;
-}
+#define ptep_test_and_clear_young(__vma, __address, __ptep)		\
+({									\
+	pte_t __pte = *(__ptep);					\
+	int r = 1;							\
+	if (!pte_young(__pte))						\
+		r = 0;							\
+	else								\
+		set_pte_at((__vma)->vm_mm, (__address),			\
+			   (__ptep), pte_mkold(__pte));			\
+	r;								\
+})
 #endif
 
 #ifndef __HAVE_ARCH_PTEP_CLEAR_YOUNG_FLUSH
 #define ptep_clear_flush_young(__vma, __address, __ptep)		\
 ({									\
-	int __young = ptep_test_and_clear_young(__ptep);		\
+	int __young;							\
+	__young = ptep_test_and_clear_young(__vma, __address, __ptep);	\
 	if (__young)							\
 		flush_tlb_page(__vma, __address);			\
 	__young;							\
@@ -64,20 +68,24 @@
 #endif
 
 #ifndef __HAVE_ARCH_PTEP_TEST_AND_CLEAR_DIRTY
-static inline int ptep_test_and_clear_dirty(pte_t *ptep)
-{
-	pte_t pte = *ptep;
-	if (!pte_dirty(pte))
-		return 0;
-	set_pte(ptep, pte_mkclean(pte));
-	return 1;
-}
+#define ptep_test_and_clear_dirty(__vma, __address, __ptep)		\
+({									\
+	pte_t __pte = *__ptep;						\
+	int r = 1;							\
+	if (!pte_dirty(__pte))						\
+		r = 0;							\
+	else								\
+		set_pte_at((__vma)->vm_mm, (__address), (__ptep),	\
+			   pte_mkclean(__pte));				\
+	r;								\
+})
 #endif
 
 #ifndef __HAVE_ARCH_PTEP_CLEAR_DIRTY_FLUSH
 #define ptep_clear_flush_dirty(__vma, __address, __ptep)		\
 ({									\
-	int __dirty = ptep_test_and_clear_dirty(__ptep);		\
+	int __dirty;							\
+	__dirty = ptep_test_and_clear_dirty(__vma, __address, __ptep);	\
 	if (__dirty)							\
 		flush_tlb_page(__vma, __address);			\
 	__dirty;							\
@@ -85,36 +93,29 @@
 #endif
 
 #ifndef __HAVE_ARCH_PTEP_GET_AND_CLEAR
-static inline pte_t ptep_get_and_clear(pte_t *ptep)
-{
-	pte_t pte = *ptep;
-	pte_clear(ptep);
-	return pte;
-}
+#define ptep_get_and_clear(__mm, __address, __ptep)			\
+({									\
+	pte_t __pte = *(__ptep);					\
+	pte_clear((__mm), (__address), (__ptep));			\
+	__pte;								\
+})
 #endif
 
 #ifndef __HAVE_ARCH_PTEP_CLEAR_FLUSH
 #define ptep_clear_flush(__vma, __address, __ptep)			\
 ({									\
-	pte_t __pte = ptep_get_and_clear(__ptep);			\
+	pte_t __pte;							\
+	__pte = ptep_get_and_clear((__vma)->vm_mm, __address, __ptep);	\
 	flush_tlb_page(__vma, __address);				\
 	__pte;								\
 })
 #endif
 
 #ifndef __HAVE_ARCH_PTEP_SET_WRPROTECT
-static inline void ptep_set_wrprotect(pte_t *ptep)
-{
-	pte_t old_pte = *ptep;
-	set_pte(ptep, pte_wrprotect(old_pte));
-}
-#endif
-
-#ifndef __HAVE_ARCH_PTEP_MKDIRTY
-static inline void ptep_mkdirty(pte_t *ptep)
+static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long address, pte_t *ptep)
 {
 	pte_t old_pte = *ptep;
-	set_pte(ptep, pte_mkdirty(old_pte));
+	set_pte_at(mm, address, ptep, pte_wrprotect(old_pte));
 }
 #endif
 
diff -Nru a/include/asm-generic/resource.h b/include/asm-generic/resource.h
--- a/include/asm-generic/resource.h	2005-03-11 12:51:48 -08:00
+++ b/include/asm-generic/resource.h	2005-03-11 12:51:48 -08:00
@@ -2,57 +2,85 @@
 #define _ASM_GENERIC_RESOURCE_H
 
 /*
- * Resource limits
+ * Resource limit IDs
+ *
+ * ( Compatibility detail: there are architectures that have
+ *   a different rlimit ID order in the 5-9 range and want
+ *   to keep that order for binary compatibility. The reasons
+ *   are historic and all new rlimits are identical across all
+ *   arches. If an arch has such special order for some rlimits
+ *   then it defines them prior including asm-generic/resource.h. )
  */
 
-/* Allow arch to control resource order */
-#ifndef __ARCH_RLIMIT_ORDER
 #define RLIMIT_CPU		0	/* CPU time in ms */
 #define RLIMIT_FSIZE		1	/* Maximum filesize */
 #define RLIMIT_DATA		2	/* max data size */
 #define RLIMIT_STACK		3	/* max stack size */
 #define RLIMIT_CORE		4	/* max core file size */
-#define RLIMIT_RSS		5	/* max resident set size */
-#define RLIMIT_NPROC		6	/* max number of processes */
-#define RLIMIT_NOFILE		7	/* max number of open files */
-#define RLIMIT_MEMLOCK		8	/* max locked-in-memory address space */
-#define RLIMIT_AS		9	/* address space limit */
+
+#ifndef RLIMIT_RSS
+# define RLIMIT_RSS		5	/* max resident set size */
+#endif
+
+#ifndef RLIMIT_NPROC
+# define RLIMIT_NPROC		6	/* max number of processes */
+#endif
+
+#ifndef RLIMIT_NOFILE
+# define RLIMIT_NOFILE		7	/* max number of open files */
+#endif
+
+#ifndef RLIMIT_MEMLOCK
+# define RLIMIT_MEMLOCK		8	/* max locked-in-memory address space */
+#endif
+
+#ifndef RLIMIT_AS
+# define RLIMIT_AS		9	/* address space limit */
+#endif
+
 #define RLIMIT_LOCKS		10	/* maximum file locks held */
 #define RLIMIT_SIGPENDING	11	/* max number of pending signals */
 #define RLIMIT_MSGQUEUE		12	/* maximum bytes in POSIX mqueues */
 
 #define RLIM_NLIMITS		13
-#endif
 
 /*
  * SuS says limits have to be unsigned.
  * Which makes a ton more sense anyway.
+ *
+ * Some architectures override this (for compatibility reasons):
  */
 #ifndef RLIM_INFINITY
-#define RLIM_INFINITY	(~0UL)
+# define RLIM_INFINITY		(~0UL)
 #endif
 
+/*
+ * RLIMIT_STACK default maximum - some architectures override it:
+ */
 #ifndef _STK_LIM_MAX
-#define _STK_LIM_MAX	RLIM_INFINITY
+# define _STK_LIM_MAX		RLIM_INFINITY
 #endif
 
 #ifdef __KERNEL__
 
+/*
+ * boot-time rlimit defaults for the init task:
+ */
 #define INIT_RLIMITS							\
 {									\
-	[RLIMIT_CPU]		= { RLIM_INFINITY, RLIM_INFINITY },	\
-	[RLIMIT_FSIZE]		= { RLIM_INFINITY, RLIM_INFINITY },	\
-	[RLIMIT_DATA]		= { RLIM_INFINITY, RLIM_INFINITY },	\
-	[RLIMIT_STACK]		= {      _STK_LIM, _STK_LIM_MAX  },	\
-	[RLIMIT_CORE]		= {             0, RLIM_INFINITY },	\
-	[RLIMIT_RSS]		= { RLIM_INFINITY, RLIM_INFINITY },	\
-	[RLIMIT_NPROC]		= {             0,             0 },	\
-	[RLIMIT_NOFILE]		= {      INR_OPEN,     INR_OPEN  },	\
-	[RLIMIT_MEMLOCK]	= {   MLOCK_LIMIT,   MLOCK_LIMIT },	\
-	[RLIMIT_AS]		= { RLIM_INFINITY, RLIM_INFINITY },	\
-	[RLIMIT_LOCKS]		= { RLIM_INFINITY, RLIM_INFINITY },	\
-	[RLIMIT_SIGPENDING]	= { MAX_SIGPENDING, MAX_SIGPENDING },	\
-	[RLIMIT_MSGQUEUE]	= { MQ_BYTES_MAX, MQ_BYTES_MAX },	\
+	[RLIMIT_CPU]		= {  RLIM_INFINITY,  RLIM_INFINITY },	\
+	[RLIMIT_FSIZE]		= {  RLIM_INFINITY,  RLIM_INFINITY },	\
+	[RLIMIT_DATA]		= {  RLIM_INFINITY,  RLIM_INFINITY },	\
+	[RLIMIT_STACK]		= {       _STK_LIM,   _STK_LIM_MAX },	\
+	[RLIMIT_CORE]		= {              0,  RLIM_INFINITY },	\
+	[RLIMIT_RSS]		= {  RLIM_INFINITY,  RLIM_INFINITY },	\
+	[RLIMIT_NPROC]		= {              0,              0 },	\
+	[RLIMIT_NOFILE]		= {       INR_OPEN,       INR_OPEN },	\
+	[RLIMIT_MEMLOCK]	= {    MLOCK_LIMIT,    MLOCK_LIMIT },	\
+	[RLIMIT_AS]		= {  RLIM_INFINITY,  RLIM_INFINITY },	\
+	[RLIMIT_LOCKS]		= {  RLIM_INFINITY,  RLIM_INFINITY },	\
+	[RLIMIT_SIGPENDING]	= { 		0,	       0 },	\
+	[RLIMIT_MSGQUEUE]	= {   MQ_BYTES_MAX,   MQ_BYTES_MAX },	\
 }
 
 #endif	/* __KERNEL__ */
diff -Nru a/include/asm-h8300/cacheflush.h b/include/asm-h8300/cacheflush.h
--- a/include/asm-h8300/cacheflush.h	2005-03-11 12:51:42 -08:00
+++ b/include/asm-h8300/cacheflush.h	2005-03-11 12:51:42 -08:00
@@ -13,7 +13,7 @@
 #define flush_cache_all()
 #define	flush_cache_mm(mm)
 #define	flush_cache_range(vma,a,b)
-#define	flush_cache_page(vma,p)
+#define	flush_cache_page(vma,p,pfn)
 #define	flush_dcache_page(page)
 #define	flush_dcache_mmap_lock(mapping)
 #define	flush_dcache_mmap_unlock(mapping)
diff -Nru a/include/asm-h8300/system.h b/include/asm-h8300/system.h
--- a/include/asm-h8300/system.h	2005-03-11 12:51:43 -08:00
+++ b/include/asm-h8300/system.h	2005-03-11 12:51:43 -08:00
@@ -144,4 +144,6 @@
         asm("jmp @@0");			\
 })
 
+#define arch_align_stack(x) (x)
+
 #endif /* _H8300_SYSTEM_H */
diff -Nru a/include/asm-i386/cacheflush.h b/include/asm-i386/cacheflush.h
--- a/include/asm-i386/cacheflush.h	2005-03-11 12:51:46 -08:00
+++ b/include/asm-i386/cacheflush.h	2005-03-11 12:51:46 -08:00
@@ -8,7 +8,7 @@
 #define flush_cache_all()			do { } while (0)
 #define flush_cache_mm(mm)			do { } while (0)
 #define flush_cache_range(vma, start, end)	do { } while (0)
-#define flush_cache_page(vma, vmaddr)		do { } while (0)
+#define flush_cache_page(vma, vmaddr, pfn)	do { } while (0)
 #define flush_dcache_page(page)			do { } while (0)
 #define flush_dcache_mmap_lock(mapping)		do { } while (0)
 #define flush_dcache_mmap_unlock(mapping)	do { } while (0)
diff -Nru a/include/asm-i386/mach-default/mach_traps.h b/include/asm-i386/mach-default/mach_traps.h
--- a/include/asm-i386/mach-default/mach_traps.h	2005-03-11 12:51:46 -08:00
+++ b/include/asm-i386/mach-default/mach_traps.h	2005-03-11 12:51:46 -08:00
@@ -7,6 +7,8 @@
 #ifndef _MACH_TRAPS_H
 #define _MACH_TRAPS_H
 
+#include <asm/mc146818rtc.h>
+
 static inline void clear_mem_error(unsigned char reason)
 {
 	reason = (reason & 0xf) | 4;
@@ -20,10 +22,20 @@
 
 static inline void reassert_nmi(void)
 {
+	int old_reg = -1;
+
+	if (do_i_have_lock_cmos())
+		old_reg = current_lock_cmos_reg();
+	else
+		lock_cmos(0); /* register doesn't matter here */
 	outb(0x8f, 0x70);
 	inb(0x71);		/* dummy */
 	outb(0x0f, 0x70);
 	inb(0x71);		/* dummy */
+	if (old_reg >= 0)
+		outb(old_reg, 0x70);
+	else
+		unlock_cmos();
 }
 
 #endif /* !_MACH_TRAPS_H */
diff -Nru a/include/asm-i386/mc146818rtc.h b/include/asm-i386/mc146818rtc.h
--- a/include/asm-i386/mc146818rtc.h	2005-03-11 12:51:47 -08:00
+++ b/include/asm-i386/mc146818rtc.h	2005-03-11 12:51:47 -08:00
@@ -5,24 +5,89 @@
 #define _ASM_MC146818RTC_H
 
 #include <asm/io.h>
+#include <asm/system.h>
+#include <linux/mc146818rtc.h>
 
 #ifndef RTC_PORT
 #define RTC_PORT(x)	(0x70 + (x))
 #define RTC_ALWAYS_BCD	1	/* RTC operates in binary mode */
 #endif
 
+#ifdef __HAVE_ARCH_CMPXCHG
+/*
+ * This lock provides nmi access to the CMOS/RTC registers.  It has some
+ * special properties.  It is owned by a CPU and stores the index register
+ * currently being accessed (if owned).  The idea here is that it works
+ * like a normal lock (normally).  However, in an NMI, the NMI code will
+ * first check to see if its CPU owns the lock, meaning that the NMI
+ * interrupted during the read/write of the device.  If it does, it goes ahead
+ * and performs the access and then restores the index register.  If it does
+ * not, it locks normally.
+ *
+ * Note that since we are working with NMIs, we need this lock even in
+ * a non-SMP machine just to mark that the lock is owned.
+ *
+ * This only works with compare-and-swap.  There is no other way to
+ * atomically claim the lock and set the owner.
+ */
+#include <linux/smp.h>
+extern volatile unsigned long cmos_lock;
+
+/*
+ * All of these below must be called with interrupts off, preempt
+ * disabled, etc.
+ */
+
+static inline void lock_cmos(unsigned char reg)
+{
+	unsigned long new;
+	new = ((smp_processor_id()+1) << 8) | reg;
+	for (;;) {
+		if (cmos_lock)
+			continue;
+		if (__cmpxchg(&cmos_lock, 0, new, sizeof(cmos_lock)) == 0)
+			return;
+	}
+}
+
+static inline void unlock_cmos(void)
+{
+	cmos_lock = 0;
+}
+static inline int do_i_have_lock_cmos(void)
+{
+	return (cmos_lock >> 8) == (smp_processor_id()+1);
+}
+static inline unsigned char current_lock_cmos_reg(void)
+{
+	return cmos_lock & 0xff;
+}
+#define lock_cmos_prefix(reg) \
+	do {					\
+		unsigned long cmos_flags;	\
+		local_irq_save(cmos_flags);	\
+		lock_cmos(reg)
+#define lock_cmos_suffix(reg) \
+		unlock_cmos();			\
+		local_irq_restore(cmos_flags);	\
+	} while (0)
+#else
+#define lock_cmos_prefix(reg) do {} while (0)
+#define lock_cmos_suffix(reg) do {} while (0)
+#define lock_cmos(reg)
+#define unlock_cmos()
+#define do_i_have_lock_cmos() 0
+#define current_lock_cmos_reg() 0
+#endif
+
 /*
  * The yet supported machines all access the RTC index register via
  * an ISA port access but the way to access the date register differs ...
  */
-#define CMOS_READ(addr) ({ \
-outb_p((addr),RTC_PORT(0)); \
-inb_p(RTC_PORT(1)); \
-})
-#define CMOS_WRITE(val, addr) ({ \
-outb_p((addr),RTC_PORT(0)); \
-outb_p((val),RTC_PORT(1)); \
-})
+#define CMOS_READ(addr) rtc_cmos_read(addr)
+#define CMOS_WRITE(val, addr) rtc_cmos_write(val, addr)
+unsigned char rtc_cmos_read(unsigned char addr);
+void rtc_cmos_write(unsigned char val, unsigned char addr);
 
 #define RTC_IRQ 8
 
diff -Nru a/include/asm-i386/module.h b/include/asm-i386/module.h
--- a/include/asm-i386/module.h	2005-03-11 12:51:41 -08:00
+++ b/include/asm-i386/module.h	2005-03-11 12:51:41 -08:00
@@ -52,6 +52,8 @@
 #define MODULE_PROC_FAMILY "CYRIXIII "
 #elif defined CONFIG_MVIAC3_2
 #define MODULE_PROC_FAMILY "VIAC3-2 "
+#elif CONFIG_MGEODE
+#define MODULE_PROC_FAMILY "GEODE "
 #else
 #error unknown processor family
 #endif
diff -Nru a/include/asm-i386/pgtable-2level.h b/include/asm-i386/pgtable-2level.h
--- a/include/asm-i386/pgtable-2level.h	2005-03-11 12:51:46 -08:00
+++ b/include/asm-i386/pgtable-2level.h	2005-03-11 12:51:46 -08:00
@@ -14,10 +14,11 @@
  * hook is made available.
  */
 #define set_pte(pteptr, pteval) (*(pteptr) = pteval)
+#define set_pte_at(mm,addr,ptep,pteval) set_pte(ptep,pteval)
 #define set_pte_atomic(pteptr, pteval) set_pte(pteptr,pteval)
 #define set_pmd(pmdptr, pmdval) (*(pmdptr) = (pmdval))
 
-#define ptep_get_and_clear(xp)	__pte(xchg(&(xp)->pte_low, 0))
+#define ptep_get_and_clear(mm,addr,xp)	__pte(xchg(&(xp)->pte_low, 0))
 #define pte_same(a, b)		((a).pte_low == (b).pte_low)
 #define pte_page(x)		pfn_to_page(pte_pfn(x))
 #define pte_none(x)		(!(x).pte_low)
diff -Nru a/include/asm-i386/pgtable-3level.h b/include/asm-i386/pgtable-3level.h
--- a/include/asm-i386/pgtable-3level.h	2005-03-11 12:51:50 -08:00
+++ b/include/asm-i386/pgtable-3level.h	2005-03-11 12:51:50 -08:00
@@ -56,6 +56,8 @@
 	smp_wmb();
 	ptep->pte_low = pte.pte_low;
 }
+#define set_pte_at(mm,addr,ptep,pteval) set_pte(ptep,pteval)
+
 #define __HAVE_ARCH_SET_PTE_ATOMIC
 #define set_pte_atomic(pteptr,pteval) \
 		set_64bit((unsigned long long *)(pteptr),pte_val(pteval))
@@ -88,7 +90,7 @@
 #define pmd_offset(pud, address) ((pmd_t *) pud_page(*(pud)) + \
 			pmd_index(address))
 
-static inline pte_t ptep_get_and_clear(pte_t *ptep)
+static inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
 {
 	pte_t res;
 
diff -Nru a/include/asm-i386/pgtable.h b/include/asm-i386/pgtable.h
--- a/include/asm-i386/pgtable.h	2005-03-11 12:51:52 -08:00
+++ b/include/asm-i386/pgtable.h	2005-03-11 12:51:52 -08:00
@@ -201,7 +201,7 @@
 extern unsigned long pg0[];
 
 #define pte_present(x)	((x).pte_low & (_PAGE_PRESENT | _PAGE_PROTNONE))
-#define pte_clear(xp)	do { set_pte(xp, __pte(0)); } while (0)
+#define pte_clear(mm,addr,xp)	do { set_pte_at(mm, addr, xp, __pte(0)); } while (0)
 
 #define pmd_none(x)	(!pmd_val(x))
 #define pmd_present(x)	(pmd_val(x) & _PAGE_PRESENT)
@@ -243,22 +243,24 @@
 # include <asm/pgtable-2level.h>
 #endif
 
-static inline int ptep_test_and_clear_dirty(pte_t *ptep)
+static inline int ptep_test_and_clear_dirty(struct vm_area_struct *vma, unsigned long addr, pte_t *ptep)
 {
 	if (!pte_dirty(*ptep))
 		return 0;
 	return test_and_clear_bit(_PAGE_BIT_DIRTY, &ptep->pte_low);
 }
 
-static inline int ptep_test_and_clear_young(pte_t *ptep)
+static inline int ptep_test_and_clear_young(struct vm_area_struct *vma, unsigned long addr, pte_t *ptep)
 {
 	if (!pte_young(*ptep))
 		return 0;
 	return test_and_clear_bit(_PAGE_BIT_ACCESSED, &ptep->pte_low);
 }
 
-static inline void ptep_set_wrprotect(pte_t *ptep)		{ clear_bit(_PAGE_BIT_RW, &ptep->pte_low); }
-static inline void ptep_mkdirty(pte_t *ptep)			{ set_bit(_PAGE_BIT_DIRTY, &ptep->pte_low); }
+static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
+{
+	clear_bit(_PAGE_BIT_RW, &ptep->pte_low);
+}
 
 /*
  * Macro to mark a page protection value as "uncacheable".  On processors which do not support
@@ -407,7 +409,6 @@
 #define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_DIRTY
 #define __HAVE_ARCH_PTEP_GET_AND_CLEAR
 #define __HAVE_ARCH_PTEP_SET_WRPROTECT
-#define __HAVE_ARCH_PTEP_MKDIRTY
 #define __HAVE_ARCH_PTE_SAME
 #include <asm-generic/pgtable.h>
 
diff -Nru a/include/asm-i386/processor.h b/include/asm-i386/processor.h
--- a/include/asm-i386/processor.h	2005-03-11 12:51:41 -08:00
+++ b/include/asm-i386/processor.h	2005-03-11 12:51:41 -08:00
@@ -137,7 +137,7 @@
  * clear %ecx since some cpus (Cyrix MII) do not set or clear %ecx
  * resulting in stale register contents being returned.
  */
-static inline void cpuid(int op, int *eax, int *ebx, int *ecx, int *edx)
+static inline void cpuid(unsigned int op, unsigned int *eax, unsigned int *ebx, unsigned int *ecx, unsigned int *edx)
 {
 	__asm__("cpuid"
 		: "=a" (*eax),
diff -Nru a/include/asm-i386/suspend.h b/include/asm-i386/suspend.h
--- a/include/asm-i386/suspend.h	2005-03-11 12:51:51 -08:00
+++ b/include/asm-i386/suspend.h	2005-03-11 12:51:51 -08:00
@@ -10,10 +10,12 @@
 arch_prepare_suspend(void)
 {
 	/* If you want to make non-PSE machine work, turn off paging
-           in do_magic. swsusp_pg_dir should have identity mapping, so
+           in swsusp_arch_suspend. swsusp_pg_dir should have identity mapping, so
            it could work...  */
-	if (!cpu_has_pse)
+	if (!cpu_has_pse) {
+		printk(KERN_ERR "PSE is required for swsusp.\n");
 		return -EPERM;
+	}
 	return 0;
 }
 
diff -Nru a/include/asm-i386/system.h b/include/asm-i386/system.h
--- a/include/asm-i386/system.h	2005-03-11 12:51:40 -08:00
+++ b/include/asm-i386/system.h	2005-03-11 12:51:40 -08:00
@@ -468,4 +468,6 @@
 extern int es7000_plat;
 void cpu_idle_wait(void);
 
+extern unsigned long arch_align_stack(unsigned long sp);
+
 #endif
diff -Nru a/include/asm-i386/thread_info.h b/include/asm-i386/thread_info.h
--- a/include/asm-i386/thread_info.h	2005-03-11 12:51:41 -08:00
+++ b/include/asm-i386/thread_info.h	2005-03-11 12:51:41 -08:00
@@ -140,6 +140,7 @@
 #define TIF_SINGLESTEP		4	/* restore singlestep on return to user mode */
 #define TIF_IRET		5	/* return with iret */
 #define TIF_SYSCALL_AUDIT	7	/* syscall auditing active */
+#define TIF_SECCOMP		8	/* secure computing */
 #define TIF_POLLING_NRFLAG	16	/* true if poll_idle() is polling TIF_NEED_RESCHED */
 #define TIF_MEMDIE		17
 
@@ -150,12 +151,14 @@
 #define _TIF_SINGLESTEP		(1<<TIF_SINGLESTEP)
 #define _TIF_IRET		(1<<TIF_IRET)
 #define _TIF_SYSCALL_AUDIT	(1<<TIF_SYSCALL_AUDIT)
+#define _TIF_SECCOMP		(1<<TIF_SECCOMP)
 #define _TIF_POLLING_NRFLAG	(1<<TIF_POLLING_NRFLAG)
 
 /* work to do on interrupt/exception return */
 #define _TIF_WORK_MASK \
-  (0x0000FFFF & ~(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SINGLESTEP))
-#define _TIF_ALLWORK_MASK	0x0000FFFF	/* work to do on any return to u-space */
+  (0x0000FFFF & ~(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SINGLESTEP|_TIF_SECCOMP))
+/* work to do on any return to u-space */
+#define _TIF_ALLWORK_MASK	(0x0000FFFF & ~_TIF_SECCOMP)
 
 /*
  * Thread-synchronous status.
diff -Nru a/include/asm-i386/topology.h b/include/asm-i386/topology.h
--- a/include/asm-i386/topology.h	2005-03-11 12:51:41 -08:00
+++ b/include/asm-i386/topology.h	2005-03-11 12:51:41 -08:00
@@ -88,6 +88,12 @@
 	.nr_balance_failed	= 0,			\
 }
 
+extern unsigned long node_start_pfn[];
+extern unsigned long node_end_pfn[];
+extern unsigned long node_remap_size[];
+
+#define node_has_online_mem(nid) (node_start_pfn[nid] != node_end_pfn[nid])
+
 #else /* !CONFIG_NUMA */
 /*
  * Other i386 platforms should define their own version of the 
diff -Nru a/include/asm-i386/uaccess.h b/include/asm-i386/uaccess.h
--- a/include/asm-i386/uaccess.h	2005-03-11 12:51:41 -08:00
+++ b/include/asm-i386/uaccess.h	2005-03-11 12:51:41 -08:00
@@ -185,6 +185,21 @@
 
 extern void __put_user_bad(void);
 
+/*
+ * Strange magic calling convention: pointer in %ecx,
+ * value in %eax(:%edx), return value in %eax, no clobbers.
+ */
+extern void __put_user_1(void);
+extern void __put_user_2(void);
+extern void __put_user_4(void);
+extern void __put_user_8(void);
+
+#define __put_user_1(x, ptr) __asm__ __volatile__("call __put_user_1":"=a" (__ret_pu):"0" ((typeof(*(ptr)))(x)), "c" (ptr))
+#define __put_user_2(x, ptr) __asm__ __volatile__("call __put_user_2":"=a" (__ret_pu):"0" ((typeof(*(ptr)))(x)), "c" (ptr))
+#define __put_user_4(x, ptr) __asm__ __volatile__("call __put_user_4":"=a" (__ret_pu):"0" ((typeof(*(ptr)))(x)), "c" (ptr))
+#define __put_user_8(x, ptr) __asm__ __volatile__("call __put_user_8":"=a" (__ret_pu):"A" ((typeof(*(ptr)))(x)), "c" (ptr))
+#define __put_user_X(x, ptr) __asm__ __volatile__("call __put_user_X":"=a" (__ret_pu):"c" (ptr))
+
 /**
  * put_user: - Write a simple value into user space.
  * @x:   Value to copy to user space.
@@ -201,9 +216,18 @@
  *
  * Returns zero on success, or -EFAULT on error.
  */
-#define put_user(x,ptr)							\
-  __put_user_check((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr)))
-
+#define put_user(x,ptr)						\
+({	int __ret_pu;						\
+	__chk_user_ptr(ptr);					\
+	switch(sizeof(*(ptr))) {				\
+	case 1: __put_user_1(x, ptr); break;			\
+	case 2: __put_user_2(x, ptr); break;			\
+	case 4: __put_user_4(x, ptr); break;			\
+	case 8: __put_user_8(x, ptr); break;			\
+	default:__put_user_X(x, ptr); break;			\
+	}							\
+	__ret_pu;						\
+})
 
 /**
  * __get_user: - Get a simple variable from user space, with less checking.
@@ -258,16 +282,6 @@
 	__pu_err;						\
 })
 
-
-#define __put_user_check(x,ptr,size)					\
-({									\
-	long __pu_err = -EFAULT;					\
-	__typeof__(*(ptr)) __user *__pu_addr = (ptr);			\
-	might_sleep();						\
-	if (access_ok(VERIFY_WRITE,__pu_addr,size))			\
-		__put_user_size((x),__pu_addr,(size),__pu_err,-EFAULT);	\
-	__pu_err;							\
-})							
 
 #define __put_user_u64(x, addr, err)				\
 	__asm__ __volatile__(					\
diff -Nru a/include/asm-i386/unistd.h b/include/asm-i386/unistd.h
--- a/include/asm-i386/unistd.h	2005-03-11 12:51:47 -08:00
+++ b/include/asm-i386/unistd.h	2005-03-11 12:51:47 -08:00
@@ -460,7 +460,7 @@
  * but it doesn't work on all toolchains, so we just do it by hand
  */
 #ifndef cond_syscall
-#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall");
+#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall")
 #endif
 
 #endif /* _ASM_I386_UNISTD_H_ */
diff -Nru a/include/asm-ia64/cacheflush.h b/include/asm-ia64/cacheflush.h
--- a/include/asm-ia64/cacheflush.h	2005-03-11 12:51:41 -08:00
+++ b/include/asm-ia64/cacheflush.h	2005-03-11 12:51:41 -08:00
@@ -19,7 +19,7 @@
 #define flush_cache_all()			do { } while (0)
 #define flush_cache_mm(mm)			do { } while (0)
 #define flush_cache_range(vma, start, end)	do { } while (0)
-#define flush_cache_page(vma, vmaddr)		do { } while (0)
+#define flush_cache_page(vma, vmaddr, pfn)	do { } while (0)
 #define flush_icache_page(vma,page)		do { } while (0)
 #define flush_cache_vmap(start, end)		do { } while (0)
 #define flush_cache_vunmap(start, end)		do { } while (0)
diff -Nru a/include/asm-ia64/pci.h b/include/asm-ia64/pci.h
--- a/include/asm-ia64/pci.h	2005-03-11 12:51:51 -08:00
+++ b/include/asm-ia64/pci.h	2005-03-11 12:51:51 -08:00
@@ -121,14 +121,9 @@
 
 extern struct pci_ops pci_root_ops;
 
-static inline int pci_name_bus(char *name, struct pci_bus *bus)
+static inline int pci_proc_domain(struct pci_bus *bus)
 {
-	if (pci_domain_nr(bus) == 0) {
-		sprintf(name, "%02x", bus->number);
-	} else {
-		sprintf(name, "%04x:%02x", pci_domain_nr(bus), bus->number);
-	}
-	return 0;
+	return (pci_domain_nr(bus) != 0);
 }
 
 static inline void pcibios_add_platform_entries(struct pci_dev *dev)
diff -Nru a/include/asm-ia64/pgtable.h b/include/asm-ia64/pgtable.h
--- a/include/asm-ia64/pgtable.h	2005-03-11 12:51:42 -08:00
+++ b/include/asm-ia64/pgtable.h	2005-03-11 12:51:42 -08:00
@@ -202,6 +202,7 @@
  * the PTE in a page table.  Nothing special needs to be on IA-64.
  */
 #define set_pte(ptep, pteval)	(*(ptep) = (pteval))
+#define set_pte_at(mm,addr,ptep,pteval) set_pte(ptep,pteval)
 
 #define RGN_SIZE	(1UL << 61)
 #define RGN_KERNEL	7
@@ -243,7 +244,7 @@
 
 #define pte_none(pte) 			(!pte_val(pte))
 #define pte_present(pte)		(pte_val(pte) & (_PAGE_P | _PAGE_PROTNONE))
-#define pte_clear(pte)			(pte_val(*(pte)) = 0UL)
+#define pte_clear(mm,addr,pte)		(pte_val(*(pte)) = 0UL)
 /* pte_page() returns the "struct page *" corresponding to the PTE: */
 #define pte_page(pte)			virt_to_page(((pte_val(pte) & _PFN_MASK) + PAGE_OFFSET))
 
@@ -345,7 +346,7 @@
 /* atomic versions of the some PTE manipulations: */
 
 static inline int
-ptep_test_and_clear_young (pte_t *ptep)
+ptep_test_and_clear_young (struct vm_area_struct *vma, unsigned long addr, pte_t *ptep)
 {
 #ifdef CONFIG_SMP
 	if (!pte_young(*ptep))
@@ -355,13 +356,13 @@
 	pte_t pte = *ptep;
 	if (!pte_young(pte))
 		return 0;
-	set_pte(ptep, pte_mkold(pte));
+	set_pte_at(vma->vm_mm, addr, ptep, pte_mkold(pte));
 	return 1;
 #endif
 }
 
 static inline int
-ptep_test_and_clear_dirty (pte_t *ptep)
+ptep_test_and_clear_dirty (struct vm_area_struct *vma, unsigned long addr, pte_t *ptep)
 {
 #ifdef CONFIG_SMP
 	if (!pte_dirty(*ptep))
@@ -371,25 +372,25 @@
 	pte_t pte = *ptep;
 	if (!pte_dirty(pte))
 		return 0;
-	set_pte(ptep, pte_mkclean(pte));
+	set_pte_at(vma->vm_mm, addr, ptep, pte_mkclean(pte));
 	return 1;
 #endif
 }
 
 static inline pte_t
-ptep_get_and_clear (pte_t *ptep)
+ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
 {
 #ifdef CONFIG_SMP
 	return __pte(xchg((long *) ptep, 0));
 #else
 	pte_t pte = *ptep;
-	pte_clear(ptep);
+	pte_clear(mm, addr, ptep);
 	return pte;
 #endif
 }
 
 static inline void
-ptep_set_wrprotect (pte_t *ptep)
+ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
 {
 #ifdef CONFIG_SMP
 	unsigned long new, old;
@@ -400,18 +401,7 @@
 	} while (cmpxchg((unsigned long *) ptep, old, new) != old);
 #else
 	pte_t old_pte = *ptep;
-	set_pte(ptep, pte_wrprotect(old_pte));
-#endif
-}
-
-static inline void
-ptep_mkdirty (pte_t *ptep)
-{
-#ifdef CONFIG_SMP
-	set_bit(_PAGE_D_BIT, ptep);
-#else
-	pte_t old_pte = *ptep;
-	set_pte(ptep, pte_mkdirty(old_pte));
+	set_pte_at(mm, addr, ptep, pte_wrprotect(old_pte));
 #endif
 }
 
@@ -558,7 +548,6 @@
 #define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_DIRTY
 #define __HAVE_ARCH_PTEP_GET_AND_CLEAR
 #define __HAVE_ARCH_PTEP_SET_WRPROTECT
-#define __HAVE_ARCH_PTEP_MKDIRTY
 #define __HAVE_ARCH_PTE_SAME
 #define __HAVE_ARCH_PGD_OFFSET_GATE
 #include <asm-generic/pgtable.h>
diff -Nru a/include/asm-ia64/system.h b/include/asm-ia64/system.h
--- a/include/asm-ia64/system.h	2005-03-11 12:51:42 -08:00
+++ b/include/asm-ia64/system.h	2005-03-11 12:51:42 -08:00
@@ -285,6 +285,9 @@
 #define ia64_platform_is(x) (strcmp(x, platform_name) == 0)
 
 void cpu_idle_wait(void);
+
+#define arch_align_stack(x) (x)
+
 #endif /* __KERNEL__ */
 
 #endif /* __ASSEMBLY__ */
diff -Nru a/include/asm-ia64/unistd.h b/include/asm-ia64/unistd.h
--- a/include/asm-ia64/unistd.h	2005-03-11 12:51:41 -08:00
+++ b/include/asm-ia64/unistd.h	2005-03-11 12:51:41 -08:00
@@ -392,7 +392,7 @@
  * proper prototype, but we can't use __typeof__ either, because not all cond_syscall()
  * declarations have prototypes at the moment.
  */
-#define cond_syscall(x) asmlinkage long x (void) __attribute__((weak,alias("sys_ni_syscall")));
+#define cond_syscall(x) asmlinkage long x (void) __attribute__((weak,alias("sys_ni_syscall")))
 
 #endif /* !__ASSEMBLY__ */
 #endif /* __KERNEL__ */
diff -Nru a/include/asm-m32r/bug.h b/include/asm-m32r/bug.h
--- a/include/asm-m32r/bug.h	2005-03-11 12:51:41 -08:00
+++ b/include/asm-m32r/bug.h	2005-03-11 12:51:41 -08:00
@@ -1,22 +1,4 @@
 #ifndef _M32R_BUG_H
 #define _M32R_BUG_H
-
-#define BUG()	do { \
-	printk("kernel BUG at %s:%d!\n", __FILE__, __LINE__); \
-} while (0)
-
-#define PAGE_BUG(page)	do { BUG(); } while (0)
-
-#define BUG_ON(condition) \
-	do { if (unlikely((condition)!=0)) BUG(); } while(0)
-
-#define WARN_ON(condition) do { \
-	if (unlikely((condition)!=0)) { \
-		printk("Badness in %s at %s:%d\n", __FUNCTION__, \
-		__FILE__, __LINE__); \
-		dump_stack(); \
-	} \
-} while (0)
-
-#endif /* _M32R_BUG_H */
-
+#include <asm-generic/bug.h>
+#endif
diff -Nru a/include/asm-m32r/cacheflush.h b/include/asm-m32r/cacheflush.h
--- a/include/asm-m32r/cacheflush.h	2005-03-11 12:51:46 -08:00
+++ b/include/asm-m32r/cacheflush.h	2005-03-11 12:51:46 -08:00
@@ -11,7 +11,7 @@
 #define flush_cache_all()			do { } while (0)
 #define flush_cache_mm(mm)			do { } while (0)
 #define flush_cache_range(vma, start, end)	do { } while (0)
-#define flush_cache_page(vma, vmaddr)		do { } while (0)
+#define flush_cache_page(vma, vmaddr, pfn)	do { } while (0)
 #define flush_dcache_page(page)			do { } while (0)
 #define flush_dcache_mmap_lock(mapping)		do { } while (0)
 #define flush_dcache_mmap_unlock(mapping)	do { } while (0)
@@ -31,7 +31,7 @@
 #define flush_cache_all()			do { } while (0)
 #define flush_cache_mm(mm)			do { } while (0)
 #define flush_cache_range(vma, start, end)	do { } while (0)
-#define flush_cache_page(vma, vmaddr)		do { } while (0)
+#define flush_cache_page(vma, vmaddr, pfn)	do { } while (0)
 #define flush_dcache_page(page)			do { } while (0)
 #define flush_dcache_mmap_lock(mapping)		do { } while (0)
 #define flush_dcache_mmap_unlock(mapping)	do { } while (0)
@@ -43,7 +43,7 @@
 #define flush_cache_all()			do { } while (0)
 #define flush_cache_mm(mm)			do { } while (0)
 #define flush_cache_range(vma, start, end)	do { } while (0)
-#define flush_cache_page(vma, vmaddr)		do { } while (0)
+#define flush_cache_page(vma, vmaddr, pfn)	do { } while (0)
 #define flush_dcache_page(page)			do { } while (0)
 #define flush_dcache_mmap_lock(mapping)		do { } while (0)
 #define flush_dcache_mmap_unlock(mapping)	do { } while (0)
diff -Nru a/include/asm-m32r/pgtable-2level.h b/include/asm-m32r/pgtable-2level.h
--- a/include/asm-m32r/pgtable-2level.h	2005-03-11 12:51:42 -08:00
+++ b/include/asm-m32r/pgtable-2level.h	2005-03-11 12:51:42 -08:00
@@ -44,6 +44,7 @@
  * hook is made available.
  */
 #define set_pte(pteptr, pteval) (*(pteptr) = pteval)
+#define set_pte_at(mm,addr,ptep,pteval) set_pte(ptep,pteval)
 #define set_pte_atomic(pteptr, pteval)	set_pte(pteptr, pteval)
 /*
  * (pmds are folded into pgds so this doesnt get actually called,
@@ -60,7 +61,7 @@
 	return (pmd_t *) dir;
 }
 
-#define ptep_get_and_clear(xp)	__pte(xchg(&(xp)->pte, 0))
+#define ptep_get_and_clear(mm,addr,xp)	__pte(xchg(&(xp)->pte, 0))
 #define pte_same(a, b)		(pte_val(a) == pte_val(b))
 #define pte_page(x)		pfn_to_page(pte_pfn(x))
 #define pte_none(x)		(!pte_val(x))
diff -Nru a/include/asm-m32r/pgtable.h b/include/asm-m32r/pgtable.h
--- a/include/asm-m32r/pgtable.h	2005-03-11 12:51:40 -08:00
+++ b/include/asm-m32r/pgtable.h	2005-03-11 12:51:40 -08:00
@@ -176,7 +176,7 @@
 /* page table for 0-4MB for everybody */
 
 #define pte_present(x)	(pte_val(x) & (_PAGE_PRESENT | _PAGE_PROTNONE))
-#define pte_clear(xp)	do { set_pte(xp, __pte(0)); } while (0)
+#define pte_clear(mm,addr,xp)	do { set_pte_at(mm, addr, xp, __pte(0)); } while (0)
 
 #define pmd_none(x)	(!pmd_val(x))
 #define pmd_present(x)	(pmd_val(x) & _PAGE_PRESENT)
@@ -282,26 +282,21 @@
 	return pte;
 }
 
-static inline  int ptep_test_and_clear_dirty(pte_t *ptep)
+static inline  int ptep_test_and_clear_dirty(struct vm_area_struct *vma, unsigned long addr, pte_t *ptep)
 {
 	return test_and_clear_bit(_PAGE_BIT_DIRTY, ptep);
 }
 
-static inline  int ptep_test_and_clear_young(pte_t *ptep)
+static inline  int ptep_test_and_clear_young(struct vm_area_struct *vma, unsigned long addr, pte_t *ptep)
 {
 	return test_and_clear_bit(_PAGE_BIT_ACCESSED, ptep);
 }
 
-static inline void ptep_set_wrprotect(pte_t *ptep)
+static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
 {
 	clear_bit(_PAGE_BIT_WRITE, ptep);
 }
 
-static inline void ptep_mkdirty(pte_t *ptep)
-{
-	set_bit(_PAGE_BIT_DIRTY, ptep);
-}
-
 /*
  * Macro and implementation to make a page protection as uncachable.
  */
@@ -390,7 +385,6 @@
 #define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_DIRTY
 #define __HAVE_ARCH_PTEP_GET_AND_CLEAR
 #define __HAVE_ARCH_PTEP_SET_WRPROTECT
-#define __HAVE_ARCH_PTEP_MKDIRTY
 #define __HAVE_ARCH_PTE_SAME
 #include <asm-generic/pgtable.h>
 
diff -Nru a/include/asm-m32r/system.h b/include/asm-m32r/system.h
--- a/include/asm-m32r/system.h	2005-03-11 12:51:41 -08:00
+++ b/include/asm-m32r/system.h	2005-03-11 12:51:41 -08:00
@@ -294,4 +294,6 @@
 #define set_mb(var, value) do { xchg(&var, value); } while (0)
 #define set_wmb(var, value) do { var = value; wmb(); } while (0)
 
+#define arch_align_stack(x) (x)
+
 #endif  /* _ASM_M32R_SYSTEM_H */
diff -Nru a/include/asm-m32r/unistd.h b/include/asm-m32r/unistd.h
--- a/include/asm-m32r/unistd.h	2005-03-11 12:51:47 -08:00
+++ b/include/asm-m32r/unistd.h	2005-03-11 12:51:47 -08:00
@@ -468,7 +468,7 @@
  * but it doesn't work on all toolchains, so we just do it by hand
  */
 #ifndef cond_syscall
-#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall");
+#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall")
 #endif
 
 #endif /* _ASM_M32R_UNISTD_H */
diff -Nru a/include/asm-m68k/cacheflush.h b/include/asm-m68k/cacheflush.h
--- a/include/asm-m68k/cacheflush.h	2005-03-11 12:51:47 -08:00
+++ b/include/asm-m68k/cacheflush.h	2005-03-11 12:51:47 -08:00
@@ -99,8 +99,7 @@
 	        __flush_cache_030();
 }
 
-static inline void flush_cache_page(struct vm_area_struct *vma,
-				    unsigned long vmaddr)
+static inline void flush_cache_page(struct vm_area_struct *vma, unsigned long vmaddr, unsigned long pfn)
 {
 	if (vma->vm_mm == current->mm)
 	        __flush_cache_030();
@@ -134,15 +133,15 @@
 #define flush_icache_user_range(vma,pg,adr,len)	do { } while (0)
 
 #define copy_to_user_page(vma, page, vaddr, dst, src, len) \
-	do {					\
-		flush_cache_page(vma, vaddr);	\
-		memcpy(dst, src, len);		\
+	do {							\
+		flush_cache_page(vma, vaddr, page_to_pfn(page));\
+		memcpy(dst, src, len);				\
 	} while (0)
 
 #define copy_from_user_page(vma, page, vaddr, dst, src, len) \
-	do {					\
-		flush_cache_page(vma, vaddr);	\
-		memcpy(dst, src, len);		\
+	do {							\
+		flush_cache_page(vma, vaddr, page_to_pfn(page));\
+		memcpy(dst, src, len);				\
 	} while (0)
 
 extern void flush_icache_range(unsigned long address, unsigned long endaddr);
diff -Nru a/include/asm-m68k/motorola_pgtable.h b/include/asm-m68k/motorola_pgtable.h
--- a/include/asm-m68k/motorola_pgtable.h	2005-03-11 12:51:47 -08:00
+++ b/include/asm-m68k/motorola_pgtable.h	2005-03-11 12:51:47 -08:00
@@ -129,7 +129,7 @@
 
 #define pte_none(pte)		(!pte_val(pte))
 #define pte_present(pte)	(pte_val(pte) & (_PAGE_PRESENT | _PAGE_PROTNONE))
-#define pte_clear(ptep)		({ pte_val(*(ptep)) = 0; })
+#define pte_clear(mm,addr,ptep)		({ pte_val(*(ptep)) = 0; })
 
 #define pte_page(pte)		(mem_map + ((unsigned long)(__va(pte_val(pte)) - PAGE_OFFSET) >> PAGE_SHIFT))
 #define pte_pfn(pte)		(pte_val(pte) >> PAGE_SHIFT)
diff -Nru a/include/asm-m68k/pgtable.h b/include/asm-m68k/pgtable.h
--- a/include/asm-m68k/pgtable.h	2005-03-11 12:51:51 -08:00
+++ b/include/asm-m68k/pgtable.h	2005-03-11 12:51:51 -08:00
@@ -26,6 +26,7 @@
 	do{							\
 		*(pteptr) = (pteval);				\
 	} while(0)
+#define set_pte_at(mm,addr,ptep,pteval) set_pte(ptep,pteval)
 
 
 /* PMD_SHIFT determines the size of the area a second-level page table can map */
diff -Nru a/include/asm-m68k/sun3_pgtable.h b/include/asm-m68k/sun3_pgtable.h
--- a/include/asm-m68k/sun3_pgtable.h	2005-03-11 12:51:47 -08:00
+++ b/include/asm-m68k/sun3_pgtable.h	2005-03-11 12:51:47 -08:00
@@ -123,7 +123,10 @@
 
 static inline int pte_none (pte_t pte) { return !pte_val (pte); }
 static inline int pte_present (pte_t pte) { return pte_val (pte) & SUN3_PAGE_VALID; }
-static inline void pte_clear (pte_t *ptep) { pte_val (*ptep) = 0; }
+static inline void pte_clear (struct mm_struct *mm, unsigned long addr, pte_t *ptep)
+{
+	pte_val (*ptep) = 0;
+}
 
 #define pte_pfn(pte)            (pte_val(pte) & SUN3_PAGE_PGNUM_MASK)
 #define pfn_pte(pfn, pgprot) \
diff -Nru a/include/asm-m68k/system.h b/include/asm-m68k/system.h
--- a/include/asm-m68k/system.h	2005-03-11 12:51:47 -08:00
+++ b/include/asm-m68k/system.h	2005-03-11 12:51:47 -08:00
@@ -194,6 +194,8 @@
 					(unsigned long)(n),sizeof(*(ptr))))
 #endif
 
+#define arch_align_stack(x) (x)
+
 #endif /* __KERNEL__ */
 
 #endif /* _M68K_SYSTEM_H */
diff -Nru a/include/asm-m68k/unistd.h b/include/asm-m68k/unistd.h
--- a/include/asm-m68k/unistd.h	2005-03-11 12:51:46 -08:00
+++ b/include/asm-m68k/unistd.h	2005-03-11 12:51:46 -08:00
@@ -460,6 +460,6 @@
  * What we want is __attribute__((weak,alias("sys_ni_syscall"))),
  * but it doesn't work on all toolchains, so we just do it by hand
  */
-#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall");
+#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall")
 
 #endif /* _ASM_M68K_UNISTD_H_ */
diff -Nru a/include/asm-m68knommu/cacheflush.h b/include/asm-m68knommu/cacheflush.h
--- a/include/asm-m68knommu/cacheflush.h	2005-03-11 12:51:51 -08:00
+++ b/include/asm-m68knommu/cacheflush.h	2005-03-11 12:51:51 -08:00
@@ -9,7 +9,7 @@
 #define flush_cache_all()			__flush_cache_all()
 #define flush_cache_mm(mm)			do { } while (0)
 #define flush_cache_range(vma, start, end)	do { } while (0)
-#define flush_cache_page(vma, vmaddr)		do { } while (0)
+#define flush_cache_page(vma, vmaddr, pfn)	do { } while (0)
 #define flush_dcache_range(start,len)		do { } while (0)
 #define flush_dcache_page(page)			do { } while (0)
 #define flush_dcache_mmap_lock(mapping)		do { } while (0)
diff -Nru a/include/asm-m68knommu/system.h b/include/asm-m68knommu/system.h
--- a/include/asm-m68knommu/system.h	2005-03-11 12:51:47 -08:00
+++ b/include/asm-m68knommu/system.h	2005-03-11 12:51:47 -08:00
@@ -281,5 +281,6 @@
 })
 #endif
 #endif
+#define arch_align_stack(x) (x)
 
 #endif /* _M68KNOMMU_SYSTEM_H */
diff -Nru a/include/asm-m68knommu/unistd.h b/include/asm-m68knommu/unistd.h
--- a/include/asm-m68knommu/unistd.h	2005-03-11 12:51:46 -08:00
+++ b/include/asm-m68knommu/unistd.h	2005-03-11 12:51:46 -08:00
@@ -524,6 +524,6 @@
  * What we want is __attribute__((weak,alias("sys_ni_syscall"))),
  * but it doesn't work on all toolchains, so we just do it by hand
  */
-#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall");
+#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall")
 
 #endif /* _ASM_M68K_UNISTD_H_ */
diff -Nru a/include/asm-mips/cacheflush.h b/include/asm-mips/cacheflush.h
--- a/include/asm-mips/cacheflush.h	2005-03-11 12:51:50 -08:00
+++ b/include/asm-mips/cacheflush.h	2005-03-11 12:51:50 -08:00
@@ -17,7 +17,7 @@
  *
  *  - flush_cache_all() flushes entire cache
  *  - flush_cache_mm(mm) flushes the specified mm context's cache lines
- *  - flush_cache_page(mm, vmaddr) flushes a single page
+ *  - flush_cache_page(mm, vmaddr, pfn) flushes a single page
  *  - flush_cache_range(vma, start, end) flushes a range of pages
  *  - flush_icache_range(start, end) flush a range of instructions
  *  - flush_dcache_page(pg) flushes(wback&invalidates) a page for dcache
@@ -34,8 +34,7 @@
 extern void (*flush_cache_mm)(struct mm_struct *mm);
 extern void (*flush_cache_range)(struct vm_area_struct *vma,
 	unsigned long start, unsigned long end);
-extern void (*flush_cache_page)(struct vm_area_struct *vma,
-	unsigned long page);
+extern void (*flush_cache_page)(struct vm_area_struct *vma, unsigned long page, unsigned long pfn);
 extern void __flush_dcache_page(struct page *page);
 
 static inline void flush_dcache_page(struct page *page)
diff -Nru a/include/asm-mips/pci.h b/include/asm-mips/pci.h
--- a/include/asm-mips/pci.h	2005-03-11 12:51:47 -08:00
+++ b/include/asm-mips/pci.h	2005-03-11 12:51:47 -08:00
@@ -137,17 +137,10 @@
 
 #define pci_domain_nr(bus) ((struct pci_controller *)(bus)->sysdata)->index
 
-static inline int
-pci_name_bus(char *name, struct pci_bus *bus)
+static inline int pci_proc_domain(struct pci_bus *bus)
 {
 	struct pci_controller *hose = bus->sysdata;
-
-	if (likely(hose->need_domain_info == 0)) {
-		sprintf(name, "%02x", bus->number);
-	} else {
-		sprintf(name, "%04x:%02x", hose->index, bus->number);
-	}
-	return 0;
+	return hose->need_domain_info;
 }
 
 #endif /* CONFIG_PCI_DOMAINS */
diff -Nru a/include/asm-mips/pgtable.h b/include/asm-mips/pgtable.h
--- a/include/asm-mips/pgtable.h	2005-03-11 12:51:42 -08:00
+++ b/include/asm-mips/pgtable.h	2005-03-11 12:51:42 -08:00
@@ -100,14 +100,15 @@
 			buddy->pte_low |= _PAGE_GLOBAL;
 	}
 }
+#define set_pte_at(mm,addr,ptep,pteval) set_pte(ptep,pteval)
 
-static inline void pte_clear(pte_t *ptep)
+static inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
 {
 	/* Preserve global status for the pair */
 	if (pte_val(*ptep_buddy(ptep)) & _PAGE_GLOBAL)
-		set_pte(ptep, __pte(_PAGE_GLOBAL));
+		set_pte_at(mm, addr, ptep, __pte(_PAGE_GLOBAL));
 	else
-		set_pte(ptep, __pte(0));
+		set_pte_at(mm, addr, ptep, __pte(0));
 }
 #else
 /*
@@ -130,16 +131,17 @@
 	}
 #endif
 }
+#define set_pte_at(mm,addr,ptep,pteval) set_pte(ptep,pteval)
 
-static inline void pte_clear(pte_t *ptep)
+static inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
 {
 #if !defined(CONFIG_CPU_R3000) && !defined(CONFIG_CPU_TX39XX)
 	/* Preserve global status for the pair */
 	if (pte_val(*ptep_buddy(ptep)) & _PAGE_GLOBAL)
-		set_pte(ptep, __pte(_PAGE_GLOBAL));
+		set_pte_at(mm, addr, ptep, __pte(_PAGE_GLOBAL));
 	else
 #endif
-		set_pte(ptep, __pte(0));
+		set_pte_at(mm, addr, ptep, __pte(0));
 }
 #endif
 
diff -Nru a/include/asm-mips/resource.h b/include/asm-mips/resource.h
--- a/include/asm-mips/resource.h	2005-03-11 12:51:51 -08:00
+++ b/include/asm-mips/resource.h	2005-03-11 12:51:51 -08:00
@@ -9,36 +9,26 @@
 #ifndef _ASM_RESOURCE_H
 #define _ASM_RESOURCE_H
 
+#include <linux/config.h>
+
 /*
- * Resource limits
+ * These five resource limit IDs have a MIPS/Linux-specific ordering,
+ * the rest comes from the generic header:
  */
-#define RLIMIT_CPU 0			/* CPU time in ms */
-#define RLIMIT_FSIZE 1			/* Maximum filesize */
-#define RLIMIT_DATA 2			/* max data size */
-#define RLIMIT_STACK 3			/* max stack size */
-#define RLIMIT_CORE 4			/* max core file size */
-#define RLIMIT_NOFILE 5			/* max number of open files */
-#define RLIMIT_AS 6			/* mapped memory */
-#define RLIMIT_RSS 7			/* max resident set size */
-#define RLIMIT_NPROC 8			/* max number of processes */
-#define RLIMIT_MEMLOCK 9		/* max locked-in-memory address space */
-#define RLIMIT_LOCKS 10			/* maximum file locks held */
-#define RLIMIT_SIGPENDING 11		/* max number of pending signals */
-#define RLIMIT_MSGQUEUE 12		/* maximum bytes in POSIX mqueues */
-
-#define RLIM_NLIMITS 13			/* Number of limit flavors.  */
-#define __ARCH_RLIMIT_ORDER
+#define RLIMIT_NOFILE		5	/* max number of open files */
+#define RLIMIT_AS		6	/* address space limit */
+#define RLIMIT_RSS		7	/* max resident set size */
+#define RLIMIT_NPROC		8	/* max number of processes */
+#define RLIMIT_MEMLOCK		9	/* max locked-in-memory address space */
 
 /*
  * SuS says limits have to be unsigned.
- * Which makes a ton more sense anyway.
+ * Which makes a ton more sense anyway,
+ * but we keep the old value on MIPS32,
+ * for compatibility:
  */
-#include <linux/config.h>
 #ifdef CONFIG_MIPS32
-#define RLIM_INFINITY	0x7fffffffUL
-#endif
-#ifdef CONFIG_MIPS64
-#define RLIM_INFINITY	(~0UL)
+# define RLIM_INFINITY		0x7fffffffUL
 #endif
 
 #include <asm-generic/resource.h>
diff -Nru a/include/asm-mips/system.h b/include/asm-mips/system.h
--- a/include/asm-mips/system.h	2005-03-11 12:51:42 -08:00
+++ b/include/asm-mips/system.h	2005-03-11 12:51:42 -08:00
@@ -433,4 +433,6 @@
 #define finish_arch_switch(rq, prev)	spin_unlock_irq(&(prev)->switch_lock)
 #define task_running(rq, p) 		((rq)->curr == (p) || spin_is_locked(&(p)->switch_lock))
 
+#define arch_align_stack(x) (x)
+
 #endif /* _ASM_SYSTEM_H */
diff -Nru a/include/asm-mips/unistd.h b/include/asm-mips/unistd.h
--- a/include/asm-mips/unistd.h	2005-03-11 12:51:41 -08:00
+++ b/include/asm-mips/unistd.h	2005-03-11 12:51:41 -08:00
@@ -1180,6 +1180,6 @@
  * What we want is __attribute__((weak,alias("sys_ni_syscall"))),
  * but it doesn't work on all toolchains, so we just do it by hand
  */
-#define cond_syscall(x) asm(".weak\t" #x "\n" #x "\t=\tsys_ni_syscall");
+#define cond_syscall(x) asm(".weak\t" #x "\n" #x "\t=\tsys_ni_syscall")
 
 #endif /* _ASM_UNISTD_H */
diff -Nru a/include/asm-mips/vr41xx/siu.h b/include/asm-mips/vr41xx/siu.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-mips/vr41xx/siu.h	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,50 @@
+/*
+ *  Include file for NEC VR4100 series Serial Interface Unit.
+ *
+ *  Copyright (C) 2005  Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#ifndef __NEC_VR41XX_SIU_H
+#define __NEC_VR41XX_SIU_H
+
+typedef enum {
+	SIU_INTERFACE_RS232C,
+	SIU_INTERFACE_IRDA,
+} siu_interface_t;
+
+extern void vr41xx_select_siu_interface(siu_interface_t interface);
+
+typedef enum {
+	SIU_USE_IRDA,
+	FIR_USE_IRDA,
+} irda_use_t;
+
+extern void vr41xx_use_irda(irda_use_t use);
+
+typedef enum {
+	SHARP_IRDA,
+	TEMIC_IRDA,
+	HP_IRDA,
+} irda_module_t;
+
+typedef enum {
+	IRDA_TX_1_5MBPS,
+	IRDA_TX_4MBPS,
+} irda_speed_t;
+
+extern void vr41xx_select_irda_module(irda_module_t module, irda_speed_t speed);
+
+#endif /* __NEC_VR41XX_SIU_H */
diff -Nru a/include/asm-mips/vr41xx/vr41xx.h b/include/asm-mips/vr41xx/vr41xx.h
--- a/include/asm-mips/vr41xx/vr41xx.h	2005-03-11 12:51:42 -08:00
+++ b/include/asm-mips/vr41xx/vr41xx.h	2005-03-11 12:51:42 -08:00
@@ -45,6 +45,7 @@
 /*
  * Bus Control Uint
  */
+extern unsigned long vr41xx_calculate_clock_frequency(void);
 extern unsigned long vr41xx_get_vtclock_frequency(void);
 extern unsigned long vr41xx_get_tclock_frequency(void);
 
@@ -83,7 +84,7 @@
 #define INT2_CASCADE_IRQ	MIPS_CPU_IRQ(4)
 #define INT3_CASCADE_IRQ	MIPS_CPU_IRQ(5)
 #define INT4_CASCADE_IRQ	MIPS_CPU_IRQ(6)
-#define MIPS_COUNTER_IRQ	MIPS_CPU_IRQ(7)
+#define TIMER_IRQ		MIPS_CPU_IRQ(7)
 
 /* SYINT1 Interrupt Numbers */
 #define SYSINT1_IRQ_BASE	8
@@ -245,34 +246,6 @@
 	DATA_LOW,
 	DATA_HIGH
 };
-
-/*
- * Serial Interface Unit
- */
-extern void vr41xx_siu_init(void);
-extern int vr41xx_serial_ports;
-
-/* SIU interfaces */
-typedef enum {
-	SIU_RS232C,
-	SIU_IRDA
-} siu_interface_t;
-
-/* IrDA interfaces */
-typedef enum {
-	IRDA_NONE,
-	IRDA_SHARP,
-	IRDA_TEMIC,
-	IRDA_HP
-} irda_module_t;
-
-extern void vr41xx_select_siu_interface(siu_interface_t interface,
-                                        irda_module_t module);
-
-/*
- * Debug Serial Interface Unit
- */
-extern void vr41xx_dsiu_init(void);
 
 /*
  * PCI Control Unit
diff -Nru a/include/asm-parisc/assembly.h b/include/asm-parisc/assembly.h
--- a/include/asm-parisc/assembly.h	2005-03-11 12:51:46 -08:00
+++ b/include/asm-parisc/assembly.h	2005-03-11 12:51:46 -08:00
@@ -37,6 +37,7 @@
 #define LDREGX  ldwx,s
 #define LDREGM	ldwm
 #define STREGM	stwm
+#define SHRREG  shr
 #define RP_OFFSET	20
 #define FRAME_SIZE	64
 #define CALLEE_SAVE_FRAME_SIZE	128
@@ -44,7 +45,7 @@
 
 #ifdef CONFIG_PA20
 #define BL		b,l
-# ifdef CONFIG_PARISC64
+# ifdef CONFIG_64BIT
 #  define LEVEL		2.0w
 # else
 #  define LEVEL		2.0
diff -Nru a/include/asm-parisc/bitops.h b/include/asm-parisc/bitops.h
--- a/include/asm-parisc/bitops.h	2005-03-11 12:51:40 -08:00
+++ b/include/asm-parisc/bitops.h	2005-03-11 12:51:40 -08:00
@@ -446,14 +446,14 @@
  * disabling interrupts.
  */
 #ifdef __LP64__
-#define ext2_set_bit(nr, addr)		test_and_set_bit((nr) ^ 0x38, (unsigned long *)addr)
+#define ext2_set_bit(nr, addr)		__test_and_set_bit((nr) ^ 0x38, (unsigned long *)addr)
 #define ext2_set_bit_atomic(l,nr,addr)  test_and_set_bit((nr) ^ 0x38, (unsigned long *)addr)
-#define ext2_clear_bit(nr, addr)	test_and_clear_bit((nr) ^ 0x38, (unsigned long *)addr)
+#define ext2_clear_bit(nr, addr)	__test_and_clear_bit((nr) ^ 0x38, (unsigned long *)addr)
 #define ext2_clear_bit_atomic(l,nr,addr) test_and_clear_bit((nr) ^ 0x38, (unsigned long *)addr)
 #else
-#define ext2_set_bit(nr, addr)		test_and_set_bit((nr) ^ 0x18, (unsigned long *)addr)
+#define ext2_set_bit(nr, addr)		__test_and_set_bit((nr) ^ 0x18, (unsigned long *)addr)
 #define ext2_set_bit_atomic(l,nr,addr)  test_and_set_bit((nr) ^ 0x18, (unsigned long *)addr)
-#define ext2_clear_bit(nr, addr)	test_and_clear_bit((nr) ^ 0x18, (unsigned long *)addr)
+#define ext2_clear_bit(nr, addr)	__test_and_clear_bit((nr) ^ 0x18, (unsigned long *)addr)
 #define ext2_clear_bit_atomic(l,nr,addr) test_and_clear_bit((nr) ^ 0x18, (unsigned long *)addr)
 #endif
 
diff -Nru a/include/asm-parisc/cacheflush.h b/include/asm-parisc/cacheflush.h
--- a/include/asm-parisc/cacheflush.h	2005-03-11 12:51:51 -08:00
+++ b/include/asm-parisc/cacheflush.h	2005-03-11 12:51:51 -08:00
@@ -57,9 +57,9 @@
 extern void flush_dcache_page(struct page *page);
 
 #define flush_dcache_mmap_lock(mapping) \
-	spin_lock_irq(&(mapping)->tree_lock)
+	write_lock_irq(&(mapping)->tree_lock)
 #define flush_dcache_mmap_unlock(mapping) \
-	spin_unlock_irq(&(mapping)->tree_lock)
+	write_unlock_irq(&(mapping)->tree_lock)
 
 #define flush_icache_page(vma,page)	do { flush_kernel_dcache_page(page_address(page)); flush_kernel_icache_page(page_address(page)); } while (0)
 
@@ -67,14 +67,14 @@
 
 #define copy_to_user_page(vma, page, vaddr, dst, src, len) \
 do { \
-	flush_cache_page(vma, vaddr); \
+	flush_cache_page(vma, vaddr, page_to_pfn(page)); \
 	memcpy(dst, src, len); \
 	flush_kernel_dcache_range_asm((unsigned long)dst, (unsigned long)dst + len); \
 } while (0)
 
 #define copy_from_user_page(vma, page, vaddr, dst, src, len) \
 do { \
-	flush_cache_page(vma, vaddr); \
+	flush_cache_page(vma, vaddr, page_to_pfn(page)); \
 	memcpy(dst, src, len); \
 } while (0)
 
@@ -170,7 +170,7 @@
 }
 
 static inline void
-flush_cache_page(struct vm_area_struct *vma, unsigned long vmaddr)
+flush_cache_page(struct vm_area_struct *vma, unsigned long vmaddr, unsigned long pfn)
 {
 	BUG_ON(!vma->vm_mm->context);
 
diff -Nru a/include/asm-parisc/checksum.h b/include/asm-parisc/checksum.h
--- a/include/asm-parisc/checksum.h	2005-03-11 12:51:41 -08:00
+++ b/include/asm-parisc/checksum.h	2005-03-11 12:51:41 -08:00
@@ -30,8 +30,8 @@
  * this is a new version of the above that records errors it finds in *errp,
  * but continues and zeros the rest of the buffer.
  */
-extern unsigned int csum_partial_copy_from_user(const unsigned char *src, unsigned char *dst,
-						int len, unsigned int sum, int *errp);
+extern unsigned int csum_partial_copy_from_user(const unsigned char __user *src,
+		unsigned char *dst, int len, unsigned int sum, int *errp);
 
 /*
  *	Optimized for IP headers, which always checksum on 4 octet boundaries.
diff -Nru a/include/asm-parisc/compat.h b/include/asm-parisc/compat.h
--- a/include/asm-parisc/compat.h	2005-03-11 12:51:52 -08:00
+++ b/include/asm-parisc/compat.h	2005-03-11 12:51:52 -08:00
@@ -131,15 +131,15 @@
  */
 typedef	u32		compat_uptr_t;
 
-static inline void *compat_ptr(compat_uptr_t uptr)
+static inline void __user *compat_ptr(compat_uptr_t uptr)
 {
-	return (void *)(unsigned long)uptr;
+	return (void __user *)(unsigned long)uptr;
 }
 
-static __inline__ void *compat_alloc_user_space(long len)
+static __inline__ void __user *compat_alloc_user_space(long len)
 {
 	struct pt_regs *regs = &current->thread.regs;
-	return (void *)regs->gr[30];
+	return (void __user *)regs->gr[30];
 }
 
 #endif /* _ASM_PARISC_COMPAT_H */
diff -Nru a/include/asm-parisc/dma-mapping.h b/include/asm-parisc/dma-mapping.h
--- a/include/asm-parisc/dma-mapping.h	2005-03-11 12:51:42 -08:00
+++ b/include/asm-parisc/dma-mapping.h	2005-03-11 12:51:42 -08:00
@@ -1,8 +1,8 @@
 #ifndef _PARISC_DMA_MAPPING_H
 #define _PARISC_DMA_MAPPING_H
 
-#include <linux/mm.h>
 #include <linux/config.h>
+#include <linux/mm.h>
 #include <asm/cacheflush.h>
 #include <asm/scatterlist.h>
 
diff -Nru a/include/asm-parisc/dma.h b/include/asm-parisc/dma.h
--- a/include/asm-parisc/dma.h	2005-03-11 12:51:52 -08:00
+++ b/include/asm-parisc/dma.h	2005-03-11 12:51:52 -08:00
@@ -38,9 +38,11 @@
 ** won't compile :-(
 */
 #define MAX_DMA_CHANNELS 8
-#define DMA_MODE_READ    1
-#define DMA_MODE_WRITE   2
-#define DMA_AUTOINIT     0x10
+#define DMA_MODE_READ	0x44	/* I/O to memory, no autoinit, increment, single mode */
+#define DMA_MODE_WRITE	0x48	/* memory to I/O, no autoinit, increment, single mode */
+#define DMA_MODE_CASCADE 0xC0	/* pass thru DREQ->HRQ, DACK<-HLDA only */
+
+#define DMA_AUTOINIT	0x10
 
 /* 8237 DMA controllers */
 #define IO_DMA1_BASE	0x00	/* 8 bit slave DMA, channels 0..3 */
diff -Nru a/include/asm-parisc/eisa_eeprom.h b/include/asm-parisc/eisa_eeprom.h
--- a/include/asm-parisc/eisa_eeprom.h	2005-03-11 12:51:47 -08:00
+++ b/include/asm-parisc/eisa_eeprom.h	2005-03-11 12:51:47 -08:00
@@ -13,6 +13,8 @@
 #ifndef ASM_EISA_EEPROM_H
 #define ASM_EISA_EEPROM_H
 
+extern void __iomem *eisa_eeprom_addr;
+
 #define HPEE_MAX_LENGTH       0x2000	/* maximum eeprom length */
 
 #define HPEE_SLOT_INFO(slot) (20+(48*slot))
diff -Nru a/include/asm-parisc/hardirq.h b/include/asm-parisc/hardirq.h
--- a/include/asm-parisc/hardirq.h	2005-03-11 12:51:51 -08:00
+++ b/include/asm-parisc/hardirq.h	2005-03-11 12:51:51 -08:00
@@ -15,9 +15,7 @@
 #ifndef _PARISC_HARDIRQ_H
 #define _PARISC_HARDIRQ_H
 
-#include <linux/config.h>
 #include <linux/threads.h>
-#include <linux/cache.h>
 #include <linux/irq.h>
 
 typedef struct {
@@ -25,16 +23,6 @@
 } ____cacheline_aligned irq_cpustat_t;
 
 #include <linux/irq_cpustat.h>	/* Standard mappings for irq_cpustat_t above */
-
-#define HARDIRQ_BITS	16
-
-/*
- * The hardirq mask has to be large enough to have space for potentially all
- * IRQ sources in the system nesting on a single CPU:
- */
-#if (1 << HARDIRQ_BITS) < NR_IRQS
-# error HARDIRQ_BITS is too low!
-#endif
 
 void ack_bad_irq(unsigned int irq);
 
diff -Nru a/include/asm-parisc/hardware.h b/include/asm-parisc/hardware.h
--- a/include/asm-parisc/hardware.h	2005-03-11 12:51:48 -08:00
+++ b/include/asm-parisc/hardware.h	2005-03-11 12:51:48 -08:00
@@ -122,6 +122,7 @@
 extern void get_pci_node_path(struct pci_dev *dev, struct hardware_path *path);
 extern void init_parisc_bus(void);
 extern struct device *hwpath_to_device(struct hardware_path *modpath);
+extern void device_to_hwpath(struct device *dev, struct hardware_path *path);
 
 
 /* inventory.c: */
diff -Nru a/include/asm-parisc/ide.h b/include/asm-parisc/ide.h
--- a/include/asm-parisc/ide.h	2005-03-11 12:51:42 -08:00
+++ b/include/asm-parisc/ide.h	2005-03-11 12:51:42 -08:00
@@ -13,8 +13,6 @@
 
 #ifdef __KERNEL__
 
-#include <linux/config.h>
-
 #ifndef MAX_HWIFS
 #define MAX_HWIFS	2
 #endif
diff -Nru a/include/asm-parisc/io.h b/include/asm-parisc/io.h
--- a/include/asm-parisc/io.h	2005-03-11 12:51:41 -08:00
+++ b/include/asm-parisc/io.h	2005-03-11 12:51:41 -08:00
@@ -273,10 +273,11 @@
 }
 #endif /* !USE_HPPA_IOREMAP */
 
+/* readb can never be const, so use __fswab instead of le*_to_cpu */
 #define readb(addr) __raw_readb(addr)
-#define readw(addr) le16_to_cpu(__raw_readw(addr))
-#define readl(addr) le32_to_cpu(__raw_readl(addr))
-#define readq(addr) le64_to_cpu(__raw_readq(addr))
+#define readw(addr) __fswab16(__raw_readw(addr))
+#define readl(addr) __fswab32(__raw_readl(addr))
+#define readq(addr) __fswab64(__raw_readq(addr))
 #define writeb(b, addr) __raw_writeb(b, addr)
 #define writew(b, addr) __raw_writew(cpu_to_le16(b), addr)
 #define writel(b, addr) __raw_writel(cpu_to_le32(b), addr)
diff -Nru a/include/asm-parisc/irq.h b/include/asm-parisc/irq.h
--- a/include/asm-parisc/irq.h	2005-03-11 12:51:42 -08:00
+++ b/include/asm-parisc/irq.h	2005-03-11 12:51:42 -08:00
@@ -40,10 +40,12 @@
 void no_ack_irq(unsigned int irq);
 void no_end_irq(unsigned int irq);
 
-extern int txn_alloc_irq(void);
+extern int txn_alloc_irq(unsigned int nbits);
 extern int txn_claim_irq(int);
-extern unsigned int txn_alloc_data(int, unsigned int);
-extern unsigned long txn_alloc_addr(int);
+extern unsigned int txn_alloc_data(unsigned int);
+extern unsigned long txn_alloc_addr(unsigned int);
+
+extern int cpu_claim_irq(unsigned int irq, struct hw_interrupt_type *, void *);
 
 extern int cpu_claim_irq(unsigned int irq, struct hw_interrupt_type *, void *);
 
diff -Nru a/include/asm-parisc/module.h b/include/asm-parisc/module.h
--- a/include/asm-parisc/module.h	2005-03-11 12:51:41 -08:00
+++ b/include/asm-parisc/module.h	2005-03-11 12:51:41 -08:00
@@ -17,12 +17,16 @@
 #define Elf_Rela Elf32_Rela
 #endif
 
+struct unwind_table;
+
 struct mod_arch_specific
 {
 	unsigned long got_offset, got_count, got_max;
 	unsigned long fdesc_offset, fdesc_count, fdesc_max;
 	unsigned long stub_offset, stub_count, stub_max;
 	unsigned long init_stub_offset, init_stub_count, init_stub_max;
+	int unwind_section;
+	struct unwind_table *unwind;
 };
 
 #endif /* _ASM_PARISC_MODULE_H */
diff -Nru a/include/asm-parisc/numnodes.h b/include/asm-parisc/numnodes.h
--- a/include/asm-parisc/numnodes.h	2005-03-11 12:51:42 -08:00
+++ b/include/asm-parisc/numnodes.h	2005-03-11 12:51:42 -08:00
@@ -1,8 +1,6 @@
 #ifndef _ASM_MAX_NUMNODES_H
 #define _ASM_MAX_NUMNODES_H
 
-#include <linux/config.h>
-
 /* Max 8 Nodes */
 #define NODES_SHIFT	3
 
diff -Nru a/include/asm-parisc/parport_gsc.h b/include/asm-parisc/parport_gsc.h
--- a/include/asm-parisc/parport_gsc.h	2005-03-11 12:51:51 -08:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,193 +0,0 @@
-#ifndef __LINUX_PARPORT_GSC_H
-#define __LINUX_PARPORT_GSC_H
-
-#include <asm/io.h>
-#include <linux/delay.h>
-
-#undef	DEBUG_PARPORT	/* undefine for production */
-#define DELAY_TIME 	0
-
-#if DELAY_TIME == 0
-#define parport_readb	gsc_readb
-#define parport_writeb	gsc_writeb
-#else
-static __inline__ unsigned char parport_readb( unsigned long port )
-{
-    udelay(DELAY_TIME);
-    return gsc_readb(port);
-}
-
-static __inline__ void parport_writeb( unsigned char value, unsigned long port )
-{
-    gsc_writeb(value,port);
-    udelay(DELAY_TIME);
-}
-#endif
-
-/* --- register definitions ------------------------------- */
-
-#define EPPDATA(p)  ((p)->base    + 0x4)
-#define EPPADDR(p)  ((p)->base    + 0x3)
-#define CONTROL(p)  ((p)->base    + 0x2)
-#define STATUS(p)   ((p)->base    + 0x1)
-#define DATA(p)     ((p)->base    + 0x0)
-
-struct parport_gsc_private {
-	/* Contents of CTR. */
-	unsigned char ctr;
-
-	/* Bitmask of writable CTR bits. */
-	unsigned char ctr_writable;
-
-	/* Number of bytes per portword. */
-	int pword;
-
-	/* Not used yet. */
-	int readIntrThreshold;
-	int writeIntrThreshold;
-
-	/* buffer suitable for DMA, if DMA enabled */
-	char *dma_buf;
-	dma_addr_t dma_handle;
-	struct pci_dev *dev;
-};
-
-extern __inline__ void parport_gsc_write_data(struct parport *p, unsigned char d)
-{
-#ifdef DEBUG_PARPORT
-	printk (KERN_DEBUG "parport_gsc_write_data(%p,0x%02x)\n", p, d);
-#endif
-	parport_writeb(d, DATA(p));
-}
-
-extern __inline__ unsigned char parport_gsc_read_data(struct parport *p)
-{
-	unsigned char val = parport_readb (DATA (p));
-#ifdef DEBUG_PARPORT
-	printk (KERN_DEBUG "parport_gsc_read_data(%p) = 0x%02x\n",
-		p, val);
-#endif
-	return val;
-}
-
-/* __parport_gsc_frob_control differs from parport_gsc_frob_control in that
- * it doesn't do any extra masking. */
-static __inline__ unsigned char __parport_gsc_frob_control (struct parport *p,
-							   unsigned char mask,
-							   unsigned char val)
-{
-	struct parport_gsc_private *priv = p->physport->private_data;
-	unsigned char ctr = priv->ctr;
-#ifdef DEBUG_PARPORT
-	printk (KERN_DEBUG
-		"__parport_gsc_frob_control(%02x,%02x): %02x -> %02x\n",
-		mask, val, ctr, ((ctr & ~mask) ^ val) & priv->ctr_writable);
-#endif
-	ctr = (ctr & ~mask) ^ val;
-	ctr &= priv->ctr_writable; /* only write writable bits. */
-	parport_writeb (ctr, CONTROL (p));
-	priv->ctr = ctr;	/* Update soft copy */
-	return ctr;
-}
-
-extern __inline__ void parport_gsc_data_reverse (struct parport *p)
-{
-	__parport_gsc_frob_control (p, 0x20, 0x20);
-}
-
-extern __inline__ void parport_gsc_data_forward (struct parport *p)
-{
-	__parport_gsc_frob_control (p, 0x20, 0x00);
-}
-
-extern __inline__ void parport_gsc_write_control (struct parport *p,
-						 unsigned char d)
-{
-	const unsigned char wm = (PARPORT_CONTROL_STROBE |
-				  PARPORT_CONTROL_AUTOFD |
-				  PARPORT_CONTROL_INIT |
-				  PARPORT_CONTROL_SELECT);
-
-	/* Take this out when drivers have adapted to newer interface. */
-	if (d & 0x20) {
-		printk (KERN_DEBUG "%s (%s): use data_reverse for this!\n",
-			p->name, p->cad->name);
-		parport_gsc_data_reverse (p);
-	}
-
-	__parport_gsc_frob_control (p, wm, d & wm);
-}
-
-extern __inline__ unsigned char parport_gsc_read_control(struct parport *p)
-{
-	const unsigned char rm = (PARPORT_CONTROL_STROBE |
-				  PARPORT_CONTROL_AUTOFD |
-				  PARPORT_CONTROL_INIT |
-				  PARPORT_CONTROL_SELECT);
-	const struct parport_gsc_private *priv = p->physport->private_data;
-	return priv->ctr & rm; /* Use soft copy */
-}
-
-extern __inline__ unsigned char parport_gsc_frob_control (struct parport *p,
-							 unsigned char mask,
-							 unsigned char val)
-{
-	const unsigned char wm = (PARPORT_CONTROL_STROBE |
-				  PARPORT_CONTROL_AUTOFD |
-				  PARPORT_CONTROL_INIT |
-				  PARPORT_CONTROL_SELECT);
-
-	/* Take this out when drivers have adapted to newer interface. */
-	if (mask & 0x20) {
-		printk (KERN_DEBUG "%s (%s): use data_%s for this!\n",
-			p->name, p->cad->name,
-			(val & 0x20) ? "reverse" : "forward");
-		if (val & 0x20)
-			parport_gsc_data_reverse (p);
-		else
-			parport_gsc_data_forward (p);
-	}
-
-	/* Restrict mask and val to control lines. */
-	mask &= wm;
-	val &= wm;
-
-	return __parport_gsc_frob_control (p, mask, val);
-}
-
-extern __inline__ unsigned char parport_gsc_read_status(struct parport *p)
-{
-	return parport_readb (STATUS(p));
-}
-
-
-extern __inline__ void parport_gsc_disable_irq(struct parport *p)
-{
-	__parport_gsc_frob_control (p, 0x10, 0x00);
-}
-
-extern __inline__ void parport_gsc_enable_irq(struct parport *p)
-{
-	__parport_gsc_frob_control (p, 0x10, 0x10);
-}
-
-extern void parport_gsc_release_resources(struct parport *p);
-
-extern int parport_gsc_claim_resources(struct parport *p);
-
-extern void parport_gsc_init_state(struct pardevice *, struct parport_state *s);
-
-extern void parport_gsc_save_state(struct parport *p, struct parport_state *s);
-
-extern void parport_gsc_restore_state(struct parport *p, struct parport_state *s);
-
-extern void parport_gsc_inc_use_count(void);
-
-extern void parport_gsc_dec_use_count(void);
-
-extern struct parport *parport_gsc_probe_port (unsigned long base,
-					      unsigned long base_hi,
-					      int irq, int dma,
-					      struct pci_dev *dev);
-
-#endif
diff -Nru a/include/asm-parisc/pci.h b/include/asm-parisc/pci.h
--- a/include/asm-parisc/pci.h	2005-03-11 12:51:47 -08:00
+++ b/include/asm-parisc/pci.h	2005-03-11 12:51:47 -08:00
@@ -106,11 +106,28 @@
 struct pci_bus;
 struct pci_dev;
 
-/* The PCI address space does equal the physical memory
- * address space.  The networking and block device layers use
+/*
+ * If the PCI device's view of memory is the same as the CPU's view of memory,
+ * PCI_DMA_BUS_IS_PHYS is true.  The networking and block device layers use
  * this boolean for bounce buffer decisions.
  */
-#define PCI_DMA_BUS_IS_PHYS     (1)
+#ifdef CONFIG_PA20
+/* All PA-2.0 machines have an IOMMU. */
+#define PCI_DMA_BUS_IS_PHYS	0
+#define parisc_has_iommu()	do { } while (0)
+#else
+
+#if defined(CONFIG_IOMMU_CCIO) || defined(CONFIG_IOMMU_SBA)
+extern int parisc_bus_is_phys; 	/* in arch/parisc/kernel/setup.c */
+#define PCI_DMA_BUS_IS_PHYS	parisc_bus_is_phys
+#define parisc_has_iommu()	do { parisc_bus_is_phys = 0; } while (0)
+#else
+#define PCI_DMA_BUS_IS_PHYS	1
+#define parisc_has_iommu()	do { } while (0)
+#endif
+
+#endif	/* !CONFIG_PA20 */
+
 
 /*
 ** Most PCI devices (eg Tulip, NCR720) also export the same registers
diff -Nru a/include/asm-parisc/pdc_chassis.h b/include/asm-parisc/pdc_chassis.h
--- a/include/asm-parisc/pdc_chassis.h	2005-03-11 12:51:41 -08:00
+++ b/include/asm-parisc/pdc_chassis.h	2005-03-11 12:51:41 -08:00
@@ -1,8 +1,8 @@
 /*
- *		include/asm-parisc/pdc_chassis.h
+ *	include/asm-parisc/pdc_chassis.h
  *
- *		Copyright (C) 2002 Laurent Canet <canetl@esiee.fr>
- *		Copyright (C) 2002 Thibaut Varene <varenet@esiee.fr>
+ *	Copyright (C) 2002 Laurent Canet <canetl@esiee.fr>
+ *	Copyright (C) 2002 Thibaut Varene <varenet@parisc-linux.org>
  *
  *
  *      This program is free software; you can redistribute it and/or modify
diff -Nru a/include/asm-parisc/pdcpat.h b/include/asm-parisc/pdcpat.h
--- a/include/asm-parisc/pdcpat.h	2005-03-11 12:51:52 -08:00
+++ b/include/asm-parisc/pdcpat.h	2005-03-11 12:51:52 -08:00
@@ -190,16 +190,16 @@
 #ifndef __ASSEMBLY__
 #include <linux/types.h>
 
-#ifdef CONFIG_PARISC64
+#ifdef CONFIG_64BIT
 #define is_pdc_pat()	(PDC_TYPE_PAT == pdc_type)
 extern int pdc_pat_get_irt_size(unsigned long *num_entries, unsigned long cell_num);
 extern int pdc_pat_get_irt(void *r_addr, unsigned long cell_num);
-#else	/* ! CONFIG_PARISC64 */
+#else	/* ! CONFIG_64BIT */
 /* No PAT support for 32-bit kernels...sorry */
 #define is_pdc_pat()	(0)
 #define pdc_pat_get_irt_size(num_entries, cell_numn)	PDC_BAD_PROC
 #define pdc_pat_get_irt(r_addr, cell_num)		PDC_BAD_PROC
-#endif	/* ! CONFIG_PARISC64 */
+#endif	/* ! CONFIG_64BIT */
 
 
 struct pdc_pat_cell_num {
diff -Nru a/include/asm-parisc/pgtable.h b/include/asm-parisc/pgtable.h
--- a/include/asm-parisc/pgtable.h	2005-03-11 12:51:51 -08:00
+++ b/include/asm-parisc/pgtable.h	2005-03-11 12:51:51 -08:00
@@ -39,6 +39,7 @@
         do{                                                     \
                 *(pteptr) = (pteval);                           \
         } while(0)
+#define set_pte_at(mm,addr,ptep,pteval) set_pte(ptep,pteval)
 
 #endif /* !__ASSEMBLY__ */
 
@@ -263,7 +264,7 @@
 
 #define pte_none(x)     ((pte_val(x) == 0) || (pte_val(x) & _PAGE_FLUSH))
 #define pte_present(x)	(pte_val(x) & _PAGE_PRESENT)
-#define pte_clear(xp)	do { pte_val(*(xp)) = 0; } while (0)
+#define pte_clear(mm,addr,xp)	do { pte_val(*(xp)) = 0; } while (0)
 
 #define pmd_flag(x)	(pmd_val(x) & PxD_FLAG_MASK)
 #define pmd_address(x)	((unsigned long)(pmd_val(x) &~ PxD_FLAG_MASK) << PxD_VALUE_SHIFT)
@@ -431,7 +432,7 @@
 #define __pte_to_swp_entry(pte)		((swp_entry_t) { pte_val(pte) })
 #define __swp_entry_to_pte(x)		((pte_t) { (x).val })
 
-static inline int ptep_test_and_clear_young(pte_t *ptep)
+static inline int ptep_test_and_clear_young(struct vm_area_struct *vma, unsigned long addr, pte_t *ptep)
 {
 #ifdef CONFIG_SMP
 	if (!pte_young(*ptep))
@@ -441,12 +442,12 @@
 	pte_t pte = *ptep;
 	if (!pte_young(pte))
 		return 0;
-	set_pte(ptep, pte_mkold(pte));
+	set_pte_at(vma->vm_mm, addr, ptep, pte_mkold(pte));
 	return 1;
 #endif
 }
 
-static inline int ptep_test_and_clear_dirty(pte_t *ptep)
+static inline int ptep_test_and_clear_dirty(struct vm_area_struct *vma, unsigned long addr, pte_t *ptep)
 {
 #ifdef CONFIG_SMP
 	if (!pte_dirty(*ptep))
@@ -456,14 +457,14 @@
 	pte_t pte = *ptep;
 	if (!pte_dirty(pte))
 		return 0;
-	set_pte(ptep, pte_mkclean(pte));
+	set_pte_at(vma->vm_mm, addr, ptep, pte_mkclean(pte));
 	return 1;
 #endif
 }
 
 extern spinlock_t pa_dbit_lock;
 
-static inline pte_t ptep_get_and_clear(pte_t *ptep)
+static inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
 {
 	pte_t old_pte;
 	pte_t pte;
@@ -472,13 +473,13 @@
 	pte = old_pte = *ptep;
 	pte_val(pte) &= ~_PAGE_PRESENT;
 	pte_val(pte) |= _PAGE_FLUSH;
-	set_pte(ptep,pte);
+	set_pte_at(mm,addr,ptep,pte);
 	spin_unlock(&pa_dbit_lock);
 
 	return old_pte;
 }
 
-static inline void ptep_set_wrprotect(pte_t *ptep)
+static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
 {
 #ifdef CONFIG_SMP
 	unsigned long new, old;
@@ -489,17 +490,7 @@
 	} while (cmpxchg((unsigned long *) ptep, old, new) != old);
 #else
 	pte_t old_pte = *ptep;
-	set_pte(ptep, pte_wrprotect(old_pte));
-#endif
-}
-
-static inline void ptep_mkdirty(pte_t *ptep)
-{
-#ifdef CONFIG_SMP
-	set_bit(xlate_pabit(_PAGE_DIRTY_BIT), &pte_val(*ptep));
-#else
-	pte_t old_pte = *ptep;
-	set_pte(ptep, pte_mkdirty(old_pte));
+	set_pte_at(mm, addr, ptep, pte_wrprotect(old_pte));
 #endif
 }
 
@@ -518,7 +509,6 @@
 #define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_DIRTY
 #define __HAVE_ARCH_PTEP_GET_AND_CLEAR
 #define __HAVE_ARCH_PTEP_SET_WRPROTECT
-#define __HAVE_ARCH_PTEP_MKDIRTY
 #define __HAVE_ARCH_PTE_SAME
 #include <asm-generic/pgtable.h>
 
diff -Nru a/include/asm-parisc/serial.h b/include/asm-parisc/serial.h
--- a/include/asm-parisc/serial.h	2005-03-11 12:51:52 -08:00
+++ b/include/asm-parisc/serial.h	2005-03-11 12:51:52 -08:00
@@ -2,8 +2,6 @@
  * include/asm-parisc/serial.h
  */
 
-#include <linux/config.h>
-
 /*
  * This assumes you have a 7.272727 MHz clock for your UART.
  * The documentation implies a 40Mhz clock, and elsewhere a 7Mhz clock
diff -Nru a/include/asm-parisc/signal.h b/include/asm-parisc/signal.h
--- a/include/asm-parisc/signal.h	2005-03-11 12:51:51 -08:00
+++ b/include/asm-parisc/signal.h	2005-03-11 12:51:51 -08:00
@@ -123,13 +123,14 @@
  * compiler doesn't support code which changes or tests the address of
  * the function in the little struct.  This is really ugly -PB
  */
-typedef __kernel_caddr_t __sighandler_t;
+typedef char __user *__sighandler_t;
 #else
-typedef void (*__sighandler_t)(int);
+typedef void __signalfn_t(int);
+typedef __signalfn_t __user *__sighandler_t;
 #endif
 
 typedef struct sigaltstack {
-	void *ss_sp;
+	void __user *ss_sp;
 	int ss_flags;
 	size_t ss_size;
 } stack_t;
diff -Nru a/include/asm-parisc/spinlock.h b/include/asm-parisc/spinlock.h
--- a/include/asm-parisc/spinlock.h	2005-03-11 12:51:52 -08:00
+++ b/include/asm-parisc/spinlock.h	2005-03-11 12:51:52 -08:00
@@ -226,7 +226,7 @@
 }
 
 #ifdef CONFIG_DEBUG_RWLOCK
-extern void _dbg_write_trylock(rwlock_t * rw, const char *bfile, int bline);
+extern int _dbg_write_trylock(rwlock_t * rw, const char *bfile, int bline);
 #define _raw_write_trylock(rw) _dbg_write_trylock(rw, __FILE__, __LINE__)
 #else
 static  __inline__ int _raw_write_trylock(rwlock_t *rw)
diff -Nru a/include/asm-parisc/system.h b/include/asm-parisc/system.h
--- a/include/asm-parisc/system.h	2005-03-11 12:51:47 -08:00
+++ b/include/asm-parisc/system.h	2005-03-11 12:51:47 -08:00
@@ -125,7 +125,7 @@
 ** The __asm__ op below simple prevents gcc/ld from reordering
 ** instructions across the mb() "call".
 */
-#define mb()		__asm__ __volatile__("":::"memory");	/* barrier() */
+#define mb()		__asm__ __volatile__("":::"memory")	/* barrier() */
 #define rmb()		mb()
 #define wmb()		mb()
 #define smp_mb()	mb()
@@ -204,5 +204,7 @@
 #define purge_tlb_end(x) do { } while (0)
 
 #endif
+
+#define arch_align_stack(x) (x)
 
 #endif
diff -Nru a/include/asm-parisc/thread_info.h b/include/asm-parisc/thread_info.h
--- a/include/asm-parisc/thread_info.h	2005-03-11 12:51:42 -08:00
+++ b/include/asm-parisc/thread_info.h	2005-03-11 12:51:42 -08:00
@@ -23,7 +23,7 @@
 	.flags		= 0,			\
 	.cpu		= 0,			\
 	.addr_limit	= KERNEL_DS,		\
-	.preempt_count	= 0,			\
+	.preempt_count	= 1,			\
   	.restart_block	= {			\
 		.fn = do_no_restart_syscall	\
 	}					\
@@ -52,7 +52,7 @@
 
 #endif /* !__ASSEMBLY */
 
-#define PREEMPT_ACTIVE          0x4000000
+#define PREEMPT_ACTIVE          0x10000000
 
 /*
  * thread information flags
diff -Nru a/include/asm-parisc/uaccess.h b/include/asm-parisc/uaccess.h
--- a/include/asm-parisc/uaccess.h	2005-03-11 12:51:42 -08:00
+++ b/include/asm-parisc/uaccess.h	2005-03-11 12:51:42 -08:00
@@ -34,7 +34,12 @@
 extern int __put_kernel_bad(void);
 extern int __put_user_bad(void);
 
-#define access_ok(type,addr,size)   (1)
+static inline long access_ok(int type, const void __user * addr,
+		unsigned long size)
+{
+	return 1;
+}
+
 #define verify_area(type,addr,size) (0)
 
 #define put_user __put_user
diff -Nru a/include/asm-parisc/unistd.h b/include/asm-parisc/unistd.h
--- a/include/asm-parisc/unistd.h	2005-03-11 12:51:40 -08:00
+++ b/include/asm-parisc/unistd.h	2005-03-11 12:51:40 -08:00
@@ -1024,6 +1024,6 @@
  * What we want is __attribute__((weak,alias("sys_ni_syscall"))),
  * but it doesn't work on all toolchains, so we just do it by hand
  */
-#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall");
+#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall")
 
 #endif /* _ASM_PARISC_UNISTD_H_ */
diff -Nru a/include/asm-parisc/unwind.h b/include/asm-parisc/unwind.h
--- a/include/asm-parisc/unwind.h	2005-03-11 12:51:52 -08:00
+++ b/include/asm-parisc/unwind.h	2005-03-11 12:51:52 -08:00
@@ -1,6 +1,8 @@
 #ifndef _UNWIND_H_
 #define _UNWIND_H_
 
+#include <linux/list.h>
+
 /* From ABI specifications */
 struct unwind_table_entry {
 	unsigned int region_start;
@@ -39,7 +41,7 @@
 };
 
 struct unwind_table {
-	struct unwind_table *next;
+	struct list_head list;
 	const char *name;
 	unsigned long gp;
 	unsigned long base_addr;
@@ -55,15 +57,18 @@
 	   available; but for now we only try to get the sp and ip for each
 	   frame */
 	/* struct pt_regs regs; */
-	unsigned long sp, ip, rp;
+	unsigned long sp, ip, rp, r31;
 	unsigned long prev_sp, prev_ip;
 };
 
-void * unwind_table_add(const char *name, unsigned long base_addr, 
-		 unsigned long gp,
-                 void *start, void *end);
+struct unwind_table *
+unwind_table_add(const char *name, unsigned long base_addr, 
+		 unsigned long gp, void *start, void *end);
+void
+unwind_table_remove(struct unwind_table *table);
+
 void unwind_frame_init(struct unwind_frame_info *info, struct task_struct *t, 
-		       unsigned long sp, unsigned long ip, unsigned long rp);
+		       struct pt_regs *regs);
 void unwind_frame_init_from_blocked_task(struct unwind_frame_info *info, struct task_struct *t);
 void unwind_frame_init_running(struct unwind_frame_info *info, struct pt_regs *regs);
 int unwind_once(struct unwind_frame_info *info);
diff -Nru a/include/asm-ppc/cacheflush.h b/include/asm-ppc/cacheflush.h
--- a/include/asm-ppc/cacheflush.h	2005-03-11 12:51:48 -08:00
+++ b/include/asm-ppc/cacheflush.h	2005-03-11 12:51:48 -08:00
@@ -22,7 +22,7 @@
 #define flush_cache_all()		do { } while (0)
 #define flush_cache_mm(mm)		do { } while (0)
 #define flush_cache_range(vma, a, b)	do { } while (0)
-#define flush_cache_page(vma, p)	do { } while (0)
+#define flush_cache_page(vma, p, pfn)	do { } while (0)
 #define flush_icache_page(vma, page)	do { } while (0)
 #define flush_cache_vmap(start, end)	do { } while (0)
 #define flush_cache_vunmap(start, end)	do { } while (0)
diff -Nru a/include/asm-ppc/cpm2.h b/include/asm-ppc/cpm2.h
--- a/include/asm-ppc/cpm2.h	2005-03-11 12:51:43 -08:00
+++ b/include/asm-ppc/cpm2.h	2005-03-11 12:51:43 -08:00
@@ -531,7 +531,7 @@
 #define SCU_PSMR_RPM		((ushort)0x000c)
 #define SCU_PSMR_REVP		((ushort)0x0008)
 #define SCU_PSMR_TPM		((ushort)0x0003)
-#define SCU_PSMR_TEVP		((ushort)0x0003)
+#define SCU_PSMR_TEVP		((ushort)0x0002)
 
 /* CPM Transparent mode SCC.
  */
diff -Nru a/include/asm-ppc/cputable.h b/include/asm-ppc/cputable.h
--- a/include/asm-ppc/cputable.h	2005-03-11 12:51:42 -08:00
+++ b/include/asm-ppc/cputable.h	2005-03-11 12:51:42 -08:00
@@ -61,6 +61,11 @@
 extern struct cpu_spec		cpu_specs[];
 extern struct cpu_spec		*cur_cpu_spec[];
 
+static inline unsigned int cpu_has_feature(unsigned int feature)
+{
+	return cur_cpu_spec[0]->cpu_features & feature;
+}
+
 #endif /* __ASSEMBLY__ */
 
 /* CPU kernel features */
diff -Nru a/include/asm-ppc/highmem.h b/include/asm-ppc/highmem.h
--- a/include/asm-ppc/highmem.h	2005-03-11 12:51:51 -08:00
+++ b/include/asm-ppc/highmem.h	2005-03-11 12:51:51 -08:00
@@ -90,7 +90,7 @@
 #ifdef HIGHMEM_DEBUG
 	BUG_ON(!pte_none(*(kmap_pte+idx)));
 #endif
-	set_pte(kmap_pte+idx, mk_pte(page, kmap_prot));
+	set_pte_at(&init_mm, vaddr, kmap_pte+idx, mk_pte(page, kmap_prot));
 	flush_tlb_page(NULL, vaddr);
 
 	return (void*) vaddr;
@@ -114,7 +114,7 @@
 	 * force other mappings to Oops if they'll try to access
 	 * this pte without first remap it
 	 */
-	pte_clear(kmap_pte+idx);
+	pte_clear(&init_mm, vaddr, kmap_pte+idx);
 	flush_tlb_page(NULL, vaddr);
 #endif
 	dec_preempt_count();
diff -Nru a/include/asm-ppc/io.h b/include/asm-ppc/io.h
--- a/include/asm-ppc/io.h	2005-03-11 12:51:51 -08:00
+++ b/include/asm-ppc/io.h	2005-03-11 12:51:51 -08:00
@@ -30,6 +30,8 @@
 #include <asm/mpc8xx.h>
 #elif defined(CONFIG_8260)
 #include <asm/mpc8260.h>
+#elif defined(CONFIG_83xx)
+#include <asm/mpc83xx.h>
 #elif defined(CONFIG_85xx)
 #include <asm/mpc85xx.h>
 #elif defined(CONFIG_APUS)
diff -Nru a/include/asm-ppc/ipic.h b/include/asm-ppc/ipic.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-ppc/ipic.h	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,85 @@
+/*
+ * include/asm-ppc/ipic.h
+ *
+ * IPIC external definitions and structure.
+ *
+ * Maintainer: Kumar Gala <kumar.gala@freescale.com>
+ *
+ * Copyright 2005 Freescale Semiconductor, Inc
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+#ifdef __KERNEL__
+#ifndef __ASM_IPIC_H__
+#define __ASM_IPIC_H__
+
+#include <linux/irq.h>
+
+/* Flags when we init the IPIC */
+#define IPIC_SPREADMODE_GRP_A	0x00000001
+#define IPIC_SPREADMODE_GRP_D	0x00000002
+#define IPIC_SPREADMODE_MIX_A	0x00000004
+#define IPIC_SPREADMODE_MIX_B	0x00000008
+#define IPIC_DISABLE_MCP_OUT	0x00000010
+#define IPIC_IRQ0_MCP		0x00000020
+
+/* IPIC registers offsets */
+#define IPIC_SICFR	0x00	/* System Global Interrupt Configuration Register */
+#define IPIC_SIVCR	0x04	/* System Global Interrupt Vector Register */
+#define IPIC_SIPNR_H	0x08	/* System Internal Interrupt Pending Register (HIGH) */
+#define IPIC_SIPNR_L	0x0C	/* System Internal Interrupt Pending Register (LOW) */
+#define IPIC_SIPRR_A	0x10	/* System Internal Interrupt group A Priority Register */
+#define IPIC_SIPRR_B	0x14	/* System Internal Interrupt group B Priority Register */
+#define IPIC_SIPRR_C	0x18	/* System Internal Interrupt group C Priority Register */
+#define IPIC_SIPRR_D	0x1C	/* System Internal Interrupt group D Priority Register */
+#define IPIC_SIMSR_H	0x20	/* System Internal Interrupt Mask Register (HIGH) */
+#define IPIC_SIMSR_L	0x24	/* System Internal Interrupt Mask Register (LOW) */
+#define IPIC_SICNR	0x28	/* System Internal Interrupt Control Register */
+#define IPIC_SEPNR	0x2C	/* System External Interrupt Pending Register */
+#define IPIC_SMPRR_A	0x30	/* System Mixed Interrupt group A Priority Register */
+#define IPIC_SMPRR_B	0x34	/* System Mixed Interrupt group B Priority Register */
+#define IPIC_SEMSR	0x38	/* System External Interrupt Mask Register */
+#define IPIC_SECNR	0x3C	/* System External Interrupt Control Register */
+#define IPIC_SERSR	0x40	/* System Error Status Register */
+#define IPIC_SERMR	0x44	/* System Error Mask Register */
+#define IPIC_SERCR	0x48	/* System Error Control Register */
+#define IPIC_SIFCR_H	0x50	/* System Internal Interrupt Force Register (HIGH) */
+#define IPIC_SIFCR_L	0x54	/* System Internal Interrupt Force Register (LOW) */
+#define IPIC_SEFCR	0x58	/* System External Interrupt Force Register */
+#define IPIC_SERFR	0x5C	/* System Error Force Register */
+#define IPIC_SCVCR	0x60	/* System Critical Interrupt Vector Register */
+#define IPIC_SMVCR	0x64	/* System Management Interrupt Vector Register */
+
+enum ipic_prio_grp {
+	IPIC_INT_GRP_A = IPIC_SIPRR_A,
+	IPIC_INT_GRP_D = IPIC_SIPRR_D,
+	IPIC_MIX_GRP_A = IPIC_SMPRR_A,
+	IPIC_MIX_GRP_B = IPIC_SMPRR_B,
+};
+
+enum ipic_mcp_irq {
+	IPIC_MCP_IRQ0 = 0,
+	IPIC_MCP_WDT  = 1,
+	IPIC_MCP_SBA  = 2,
+	IPIC_MCP_PCI1 = 5,
+	IPIC_MCP_PCI2 = 6,
+	IPIC_MCP_MU   = 7,
+};
+
+extern void ipic_init(phys_addr_t phys_addr, unsigned int flags,
+		unsigned int irq_offset,
+		unsigned char *senses, unsigned int senses_count);
+extern int ipic_set_priority(unsigned int irq, unsigned int priority);
+extern void ipic_set_highest_priority(unsigned int irq);
+extern void ipic_set_default_priority(void);
+extern void ipic_enable_mcp(enum ipic_mcp_irq mcp_irq);
+extern void ipic_disable_mcp(enum ipic_mcp_irq mcp_irq);
+extern u32 ipic_get_mcp_status(void);
+extern void ipic_clear_mcp_status(u32 mask);
+extern int ipic_get_irq(struct pt_regs *regs);
+
+#endif /* __ASM_IPIC_H__ */
+#endif /* __KERNEL__ */
diff -Nru a/include/asm-ppc/irq.h b/include/asm-ppc/irq.h
--- a/include/asm-ppc/irq.h	2005-03-11 12:51:41 -08:00
+++ b/include/asm-ppc/irq.h	2005-03-11 12:51:41 -08:00
@@ -161,6 +161,16 @@
 	return irq;
 }
 
+#elif defined(CONFIG_83xx)
+#include <asm/mpc83xx.h>
+
+static __inline__ int irq_canonicalize(int irq)
+{
+	return irq;
+}
+
+#define	NR_IRQS	(NR_IPIC_INTS)
+
 #elif defined(CONFIG_CPM2) && defined(CONFIG_85xx)
 /* Now include the board configuration specific associations.
 */
diff -Nru a/include/asm-ppc/mpc83xx.h b/include/asm-ppc/mpc83xx.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-ppc/mpc83xx.h	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,114 @@
+/*
+ * include/asm-ppc/mpc83xx.h
+ *
+ * MPC83xx definitions
+ *
+ * Maintainer: Kumar Gala <kumar.gala@freescale.com>
+ *
+ * Copyright 2005 Freescale Semiconductor, Inc
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#ifdef __KERNEL__
+#ifndef __ASM_MPC83xx_H__
+#define __ASM_MPC83xx_H__
+
+#include <linux/config.h>
+#include <asm/mmu.h>
+
+#ifdef CONFIG_83xx
+
+#ifdef CONFIG_MPC834x_SYS
+#include <platforms/83xx/mpc834x_sys.h>
+#endif
+
+#define _IO_BASE        isa_io_base
+#define _ISA_MEM_BASE   isa_mem_base
+#ifdef CONFIG_PCI
+#define PCI_DRAM_OFFSET pci_dram_offset
+#else
+#define PCI_DRAM_OFFSET 0
+#endif
+
+/*
+ * The "residual" board information structure the boot loader passes
+ * into the kernel.
+ */
+extern unsigned char __res[];
+
+/* Internal IRQs on MPC83xx OpenPIC */
+/* Not all of these exist on all MPC83xx implementations */
+
+#ifndef MPC83xx_IPIC_IRQ_OFFSET
+#define MPC83xx_IPIC_IRQ_OFFSET	0
+#endif
+
+#define NR_IPIC_INTS 128
+
+#define MPC83xx_IRQ_UART1	( 9 + MPC83xx_IPIC_IRQ_OFFSET)
+#define MPC83xx_IRQ_UART2	(10 + MPC83xx_IPIC_IRQ_OFFSET)
+#define MPC83xx_IRQ_SEC2	(11 + MPC83xx_IPIC_IRQ_OFFSET)
+#define MPC83xx_IRQ_IIC1	(14 + MPC83xx_IPIC_IRQ_OFFSET)
+#define MPC83xx_IRQ_IIC2	(15 + MPC83xx_IPIC_IRQ_OFFSET)
+#define MPC83xx_IRQ_SPI		(16 + MPC83xx_IPIC_IRQ_OFFSET)
+#define MPC83xx_IRQ_EXT1	(17 + MPC83xx_IPIC_IRQ_OFFSET)
+#define MPC83xx_IRQ_EXT2	(18 + MPC83xx_IPIC_IRQ_OFFSET)
+#define MPC83xx_IRQ_EXT3	(19 + MPC83xx_IPIC_IRQ_OFFSET)
+#define MPC83xx_IRQ_EXT4	(20 + MPC83xx_IPIC_IRQ_OFFSET)
+#define MPC83xx_IRQ_EXT5	(21 + MPC83xx_IPIC_IRQ_OFFSET)
+#define MPC83xx_IRQ_EXT6	(22 + MPC83xx_IPIC_IRQ_OFFSET)
+#define MPC83xx_IRQ_EXT7	(23 + MPC83xx_IPIC_IRQ_OFFSET)
+#define MPC83xx_IRQ_TSEC1_TX	(32 + MPC83xx_IPIC_IRQ_OFFSET)
+#define MPC83xx_IRQ_TSEC1_RX	(33 + MPC83xx_IPIC_IRQ_OFFSET)
+#define MPC83xx_IRQ_TSEC1_ERROR	(34 + MPC83xx_IPIC_IRQ_OFFSET)
+#define MPC83xx_IRQ_TSEC2_TX	(35 + MPC83xx_IPIC_IRQ_OFFSET)
+#define MPC83xx_IRQ_TSEC2_RX	(36 + MPC83xx_IPIC_IRQ_OFFSET)
+#define MPC83xx_IRQ_TSEC2_ERROR	(37 + MPC83xx_IPIC_IRQ_OFFSET)
+#define MPC83xx_IRQ_USB2_DR	(38 + MPC83xx_IPIC_IRQ_OFFSET)
+#define MPC83xx_IRQ_USB2_MPH	(39 + MPC83xx_IPIC_IRQ_OFFSET)
+#define MPC83xx_IRQ_EXT0	(48 + MPC83xx_IPIC_IRQ_OFFSET)
+#define MPC83xx_IRQ_RTC_SEC	(64 + MPC83xx_IPIC_IRQ_OFFSET)
+#define MPC83xx_IRQ_PIT		(65 + MPC83xx_IPIC_IRQ_OFFSET)
+#define MPC83xx_IRQ_PCI1	(66 + MPC83xx_IPIC_IRQ_OFFSET)
+#define MPC83xx_IRQ_PCI2	(67 + MPC83xx_IPIC_IRQ_OFFSET)
+#define MPC83xx_IRQ_RTC_ALR	(68 + MPC83xx_IPIC_IRQ_OFFSET)
+#define MPC83xx_IRQ_MU		(69 + MPC83xx_IPIC_IRQ_OFFSET)
+#define MPC83xx_IRQ_SBA		(70 + MPC83xx_IPIC_IRQ_OFFSET)
+#define MPC83xx_IRQ_DMA		(71 + MPC83xx_IPIC_IRQ_OFFSET)
+#define MPC83xx_IRQ_GTM4	(72 + MPC83xx_IPIC_IRQ_OFFSET)
+#define MPC83xx_IRQ_GTM8	(73 + MPC83xx_IPIC_IRQ_OFFSET)
+#define MPC83xx_IRQ_GPIO1	(74 + MPC83xx_IPIC_IRQ_OFFSET)
+#define MPC83xx_IRQ_GPIO2	(75 + MPC83xx_IPIC_IRQ_OFFSET)
+#define MPC83xx_IRQ_DDR		(76 + MPC83xx_IPIC_IRQ_OFFSET)
+#define MPC83xx_IRQ_LBC		(77 + MPC83xx_IPIC_IRQ_OFFSET)
+#define MPC83xx_IRQ_GTM2	(78 + MPC83xx_IPIC_IRQ_OFFSET)
+#define MPC83xx_IRQ_GTM6	(79 + MPC83xx_IPIC_IRQ_OFFSET)
+#define MPC83xx_IRQ_PMC		(80 + MPC83xx_IPIC_IRQ_OFFSET)
+#define MPC83xx_IRQ_GTM3	(84 + MPC83xx_IPIC_IRQ_OFFSET)
+#define MPC83xx_IRQ_GTM7	(85 + MPC83xx_IPIC_IRQ_OFFSET)
+#define MPC83xx_IRQ_GTM1	(90 + MPC83xx_IPIC_IRQ_OFFSET)
+#define MPC83xx_IRQ_GTM5	(91 + MPC83xx_IPIC_IRQ_OFFSET)
+
+#define MPC83xx_CCSRBAR_SIZE	(1024*1024)
+
+/* Let modules/drivers get at immrbar (physical) */
+extern phys_addr_t immrbar;
+
+enum ppc_sys_devices {
+	MPC83xx_TSEC1,
+	MPC83xx_TSEC2,
+	MPC83xx_IIC1,
+	MPC83xx_IIC2,
+	MPC83xx_DUART,
+	MPC83xx_SEC2,
+	MPC83xx_USB2_DR,
+	MPC83xx_USB2_MPH,
+};
+
+#endif /* CONFIG_83xx */
+#endif /* __ASM_MPC83xx_H__ */
+#endif /* __KERNEL__ */
diff -Nru a/include/asm-ppc/mv64x60_defs.h b/include/asm-ppc/mv64x60_defs.h
--- a/include/asm-ppc/mv64x60_defs.h	2005-03-11 12:51:50 -08:00
+++ b/include/asm-ppc/mv64x60_defs.h	2005-03-11 12:51:50 -08:00
@@ -36,6 +36,8 @@
 #define GT64260_WINDOW_SIZE_MIN			0x00100000
 #define MV64360_WINDOW_SIZE_MIN			0x00010000
 
+#define	MV64x60_TCLK_FREQ_MAX			133333333U
+
 /* IRQ's for embedded controllers */
 #define	MV64x60_IRQ_DEV				1
 #define	MV64x60_IRQ_CPU_ERR			3
@@ -43,6 +45,11 @@
 #define	MV64x60_IRQ_TIMER_2_3			9
 #define	MV64x60_IRQ_TIMER_4_5			10
 #define	MV64x60_IRQ_TIMER_6_7			11
+#define	MV64x60_IRQ_P1_GPP_0_7			24
+#define	MV64x60_IRQ_P1_GPP_8_15			25
+#define	MV64x60_IRQ_P1_GPP_16_23		26
+#define	MV64x60_IRQ_P1_GPP_24_31		27
+#define	MV64x60_IRQ_DOORBELL			28
 #define	MV64x60_IRQ_ETH_0			32
 #define	MV64x60_IRQ_ETH_1			33
 #define	MV64x60_IRQ_ETH_2			34
@@ -52,12 +59,49 @@
 #define	MV64x60_IRQ_MPSC_0			40
 #define	MV64x60_IRQ_MPSC_1			42
 #define	MV64x60_IRQ_COMM			43
+#define	MV64x60_IRQ_P0_GPP_0_7			56
+#define	MV64x60_IRQ_P0_GPP_8_15			57
+#define	MV64x60_IRQ_P0_GPP_16_23		58
+#define	MV64x60_IRQ_P0_GPP_24_31		59
 
 #define	MV64360_IRQ_PCI0			12
 #define	MV64360_IRQ_SRAM_PAR_ERR		13
 #define	MV64360_IRQ_PCI1			16
 #define	MV64360_IRQ_SDMA_1			38
 
+#define	MV64x60_IRQ_GPP0			64
+#define	MV64x60_IRQ_GPP1			65
+#define	MV64x60_IRQ_GPP2			66
+#define	MV64x60_IRQ_GPP3			67
+#define	MV64x60_IRQ_GPP4			68
+#define	MV64x60_IRQ_GPP5			69
+#define	MV64x60_IRQ_GPP6			70
+#define	MV64x60_IRQ_GPP7			71
+#define	MV64x60_IRQ_GPP8			72
+#define	MV64x60_IRQ_GPP9			73
+#define	MV64x60_IRQ_GPP10			74
+#define	MV64x60_IRQ_GPP11			75
+#define	MV64x60_IRQ_GPP12			76
+#define	MV64x60_IRQ_GPP13			77
+#define	MV64x60_IRQ_GPP14			78
+#define	MV64x60_IRQ_GPP15			79
+#define	MV64x60_IRQ_GPP16			80
+#define	MV64x60_IRQ_GPP17			81
+#define	MV64x60_IRQ_GPP18			82
+#define	MV64x60_IRQ_GPP19			83
+#define	MV64x60_IRQ_GPP20			84
+#define	MV64x60_IRQ_GPP21			85
+#define	MV64x60_IRQ_GPP22			86
+#define	MV64x60_IRQ_GPP23			87
+#define	MV64x60_IRQ_GPP24			88
+#define	MV64x60_IRQ_GPP25			89
+#define	MV64x60_IRQ_GPP26			90
+#define	MV64x60_IRQ_GPP27			91
+#define	MV64x60_IRQ_GPP28			92
+#define	MV64x60_IRQ_GPP29			93
+#define	MV64x60_IRQ_GPP30			94
+#define	MV64x60_IRQ_GPP31			95
+
 /* Offsets for register blocks */
 #define	GT64260_ENET_PHY_ADDR			0x2000
 #define	GT64260_ENET_ESMIR			0x2010
@@ -303,7 +347,7 @@
 #define	MV64360_SRAM_ERR_DATA_HI		0x03a0
 #define	MV64360_SRAM_ERR_PARITY			0x03a8
 
-#define	MV64360_SRAM_SIZE			0x00040000 /* 256 KB of SRAM */
+#define	MV64360_SRAM_SIZE			0x00200000 /* 2 MB of SRAM */
 
 /*
  *****************************************************************************
diff -Nru a/include/asm-ppc/pci.h b/include/asm-ppc/pci.h
--- a/include/asm-ppc/pci.h	2005-03-11 12:51:47 -08:00
+++ b/include/asm-ppc/pci.h	2005-03-11 12:51:47 -08:00
@@ -79,9 +79,8 @@
 #define pci_domain_nr(bus) ((struct pci_controller *)(bus)->sysdata)->index
 
 /* Set the name of the bus as it appears in /proc/bus/pci */
-static inline int pci_name_bus(char *name, struct pci_bus *bus)
+static inline int pci_proc_domain(struct pci_bus *bus)
 {
-	sprintf(name, "%02x", bus->number);
 	return 0;
 }
 
diff -Nru a/include/asm-ppc/pgtable.h b/include/asm-ppc/pgtable.h
--- a/include/asm-ppc/pgtable.h	2005-03-11 12:51:52 -08:00
+++ b/include/asm-ppc/pgtable.h	2005-03-11 12:51:52 -08:00
@@ -448,7 +448,7 @@
 
 #define pte_none(pte)		((pte_val(pte) & ~_PTE_NONE_MASK) == 0)
 #define pte_present(pte)	(pte_val(pte) & _PAGE_PRESENT)
-#define pte_clear(ptep)		do { set_pte((ptep), __pte(0)); } while (0)
+#define pte_clear(mm,addr,ptep)	do { set_pte_at((mm), (addr), (ptep), __pte(0)); } while (0)
 
 #define pmd_none(pmd)		(!pmd_val(pmd))
 #define	pmd_bad(pmd)		(pmd_val(pmd) & _PMD_BAD)
@@ -512,6 +512,17 @@
 }
 
 /*
+ * When flushing the tlb entry for a page, we also need to flush the hash
+ * table entry.  flush_hash_pages is assembler (for speed) in hashtable.S.
+ */
+extern int flush_hash_pages(unsigned context, unsigned long va,
+			    unsigned long pmdval, int count);
+
+/* Add an HPTE to the hash table */
+extern void add_hash_page(unsigned context, unsigned long va,
+			  unsigned long pmdval);
+
+/*
  * Atomic PTE updates.
  *
  * pte_update clears and sets bit atomically, and returns
@@ -542,7 +553,8 @@
  * On machines which use an MMU hash table we avoid changing the
  * _PAGE_HASHPTE bit.
  */
-static inline void set_pte(pte_t *ptep, pte_t pte)
+static inline void set_pte_at(struct mm_struct *mm, unsigned long addr,
+			      pte_t *ptep, pte_t pte)
 {
 #if _PAGE_HASHPTE != 0
 	pte_update(ptep, ~_PAGE_HASHPTE, pte_val(pte) & ~_PAGE_HASHPTE);
@@ -551,43 +563,47 @@
 #endif
 }
 
-extern void flush_hash_one_pte(pte_t *ptep);
-
 /*
  * 2.6 calles this without flushing the TLB entry, this is wrong
  * for our hash-based implementation, we fix that up here
  */
-static inline int ptep_test_and_clear_young(pte_t *ptep)
+#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
+static inline int __ptep_test_and_clear_young(unsigned int context, unsigned long addr, pte_t *ptep)
 {
 	unsigned long old;
 	old = pte_update(ptep, _PAGE_ACCESSED, 0);
 #if _PAGE_HASHPTE != 0
-	if (old & _PAGE_HASHPTE)
-		flush_hash_one_pte(ptep);
+	if (old & _PAGE_HASHPTE) {
+		unsigned long ptephys = __pa(ptep) & PAGE_MASK;
+		flush_hash_pages(context, addr, ptephys, 1);
+	}
 #endif
 	return (old & _PAGE_ACCESSED) != 0;
 }
+#define ptep_test_and_clear_young(__vma, __addr, __ptep) \
+	__ptep_test_and_clear_young((__vma)->vm_mm->context, __addr, __ptep)
 
-static inline int ptep_test_and_clear_dirty(pte_t *ptep)
+#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_DIRTY
+static inline int ptep_test_and_clear_dirty(struct vm_area_struct *vma,
+					    unsigned long addr, pte_t *ptep)
 {
 	return (pte_update(ptep, (_PAGE_DIRTY | _PAGE_HWWRITE), 0) & _PAGE_DIRTY) != 0;
 }
 
-static inline pte_t ptep_get_and_clear(pte_t *ptep)
+#define __HAVE_ARCH_PTEP_GET_AND_CLEAR
+static inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr,
+				       pte_t *ptep)
 {
 	return __pte(pte_update(ptep, ~_PAGE_HASHPTE, 0));
 }
 
-static inline void ptep_set_wrprotect(pte_t *ptep)
+#define __HAVE_ARCH_PTEP_SET_WRPROTECT
+static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr,
+				      pte_t *ptep)
 {
 	pte_update(ptep, (_PAGE_RW | _PAGE_HWWRITE), 0);
 }
 
-static inline void ptep_mkdirty(pte_t *ptep)
-{
-	pte_update(ptep, 0, _PAGE_DIRTY);
-}
-
 #define __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS
 static inline void __ptep_set_access_flags(pte_t *ptep, pte_t entry, int dirty)
 {
@@ -607,6 +623,7 @@
  */
 #define pgprot_noncached(prot)	(__pgprot(pgprot_val(prot) | _PAGE_NO_CACHE | _PAGE_GUARDED))
 
+#define __HAVE_ARCH_PTE_SAME
 #define pte_same(A,B)	(((pte_val(A) ^ pte_val(B)) & ~_PAGE_HASHPTE) == 0)
 
 /*
@@ -659,17 +676,6 @@
 extern void paging_init(void);
 
 /*
- * When flushing the tlb entry for a page, we also need to flush the hash
- * table entry.  flush_hash_pages is assembler (for speed) in hashtable.S.
- */
-extern int flush_hash_pages(unsigned context, unsigned long va,
-			    unsigned long pmdval, int count);
-
-/* Add an HPTE to the hash table */
-extern void add_hash_page(unsigned context, unsigned long va,
-			  unsigned long pmdval);
-
-/*
  * Encode and decode a swap entry.
  * Note that the bits we use in a PTE for representing a swap entry
  * must not include the _PAGE_PRESENT bit, the _PAGE_FILE bit, or the
@@ -741,15 +747,9 @@
 
 extern int get_pteptr(struct mm_struct *mm, unsigned long addr, pte_t **ptep);
 
-#endif /* !__ASSEMBLY__ */
-
-#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
-#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_DIRTY
-#define __HAVE_ARCH_PTEP_GET_AND_CLEAR
-#define __HAVE_ARCH_PTEP_SET_WRPROTECT
-#define __HAVE_ARCH_PTEP_MKDIRTY
-#define __HAVE_ARCH_PTE_SAME
 #include <asm-generic/pgtable.h>
+
+#endif /* !__ASSEMBLY__ */
 
 #endif /* _PPC_PGTABLE_H */
 #endif /* __KERNEL__ */
diff -Nru a/include/asm-ppc/ppc4xx_pic.h b/include/asm-ppc/ppc4xx_pic.h
--- a/include/asm-ppc/ppc4xx_pic.h	2005-03-11 12:51:52 -08:00
+++ b/include/asm-ppc/ppc4xx_pic.h	2005-03-11 12:51:52 -08:00
@@ -43,11 +43,11 @@
  *
  */
 struct ppc4xx_uic_settings {
-	u32 	polarity;
-	u32 	triggering;
-	u32	ext_irq_mask;
+	u32 polarity;
+	u32 triggering;
+	u32 ext_irq_mask;
 };
 
 extern void ppc4xx_pic_init(void);
 
-#endif	/* __PPC4XX_PIC_H__ */
+#endif				/* __PPC4XX_PIC_H__ */
diff -Nru a/include/asm-ppc/ppc_sys.h b/include/asm-ppc/ppc_sys.h
--- a/include/asm-ppc/ppc_sys.h	2005-03-11 12:51:41 -08:00
+++ b/include/asm-ppc/ppc_sys.h	2005-03-11 12:51:41 -08:00
@@ -21,7 +21,9 @@
 #include <linux/device.h>
 #include <linux/types.h>
 
-#if defined(CONFIG_85xx)
+#if defined(CONFIG_83xx)
+#include <asm/mpc83xx.h>
+#elif defined(CONFIG_85xx)
 #include <asm/mpc85xx.h>
 #else
 #error "need definition of ppc_sys_devices"
diff -Nru a/include/asm-ppc/ppcboot.h b/include/asm-ppc/ppcboot.h
--- a/include/asm-ppc/ppcboot.h	2005-03-11 12:51:51 -08:00
+++ b/include/asm-ppc/ppcboot.h	2005-03-11 12:51:51 -08:00
@@ -38,7 +38,8 @@
 	unsigned long	bi_flashoffset; /* reserved area for startup monitor */
 	unsigned long	bi_sramstart;	/* start of SRAM memory */
 	unsigned long	bi_sramsize;	/* size	 of SRAM memory */
-#if defined(CONFIG_8xx) || defined(CONFIG_CPM2) || defined(CONFIG_85xx)
+#if defined(CONFIG_8xx) || defined(CONFIG_CPM2) || defined(CONFIG_85xx) ||\
+	defined(CONFIG_83xx)
 	unsigned long	bi_immr_base;	/* base of IMMR register */
 #endif
 #if defined(CONFIG_PPC_MPC52xx)
@@ -72,7 +73,8 @@
 #if defined(CONFIG_HYMOD)
 	hymod_conf_t	bi_hymod_conf;	/* hymod configuration information */
 #endif
-#if defined(CONFIG_EVB64260) || defined(CONFIG_44x) || defined(CONFIG_85xx)
+#if defined(CONFIG_EVB64260) || defined(CONFIG_44x) || defined(CONFIG_85xx) ||\
+	defined(CONFIG_83xx)
 	/* second onboard ethernet port */
 	unsigned char	bi_enet1addr[6];
 #endif
diff -Nru a/include/asm-ppc/reg.h b/include/asm-ppc/reg.h
--- a/include/asm-ppc/reg.h	2005-03-11 12:51:52 -08:00
+++ b/include/asm-ppc/reg.h	2005-03-11 12:51:52 -08:00
@@ -488,12 +488,6 @@
 #define PVR_8245	0x80811014
 #define PVR_8260	PVR_8240
 
-/* System Version Numbers */
-#define SVR_8540	0x80300000
-#define SVR_8541E	0x807A0000
-#define SVR_8555E	0x80790000
-#define SVR_8560	0x80700000
-
 #if 0
 /* Segment Registers */
 #define SR0	0
diff -Nru a/include/asm-ppc/serial.h b/include/asm-ppc/serial.h
--- a/include/asm-ppc/serial.h	2005-03-11 12:51:51 -08:00
+++ b/include/asm-ppc/serial.h	2005-03-11 12:51:51 -08:00
@@ -32,8 +32,12 @@
 #include <platforms/spruce.h>
 #elif defined(CONFIG_4xx)
 #include <asm/ibm4xx.h>
+#elif defined(CONFIG_83xx)
+#include <asm/mpc83xx.h>
 #elif defined(CONFIG_85xx)
 #include <asm/mpc85xx.h>
+#elif defined(CONFIG_RADSTONE_PPC7D)
+#include <platforms/radstone_ppc7d.h>
 #else
 
 /*
diff -Nru a/include/asm-ppc/system.h b/include/asm-ppc/system.h
--- a/include/asm-ppc/system.h	2005-03-11 12:51:42 -08:00
+++ b/include/asm-ppc/system.h	2005-03-11 12:51:42 -08:00
@@ -152,9 +152,9 @@
 #define __HAVE_ARCH_CMPXCHG	1
 
 static __inline__ unsigned long
-__cmpxchg_u32(volatile int *p, int old, int new)
+__cmpxchg_u32(volatile unsigned int *p, unsigned int old, unsigned int new)
 {
-	int prev;
+	unsigned int prev;
 
 	__asm__ __volatile__ ("\n\
 1:	lwarx	%0,0,%2 \n\
@@ -200,6 +200,8 @@
      (__typeof__(*(ptr))) __cmpxchg((ptr), (unsigned long)_o_,		 \
 				    (unsigned long)_n_, sizeof(*(ptr))); \
   })
+
+#define arch_align_stack(x) (x)
 
 #endif /* __KERNEL__ */
 #endif /* __PPC_SYSTEM_H */
diff -Nru a/include/asm-ppc/todc.h b/include/asm-ppc/todc.h
--- a/include/asm-ppc/todc.h	2005-03-11 12:51:52 -08:00
+++ b/include/asm-ppc/todc.h	2005-03-11 12:51:52 -08:00
@@ -98,6 +98,7 @@
 #define TODC_TYPE_PC97307		10	/* PC97307 internal RTC */
 #define TODC_TYPE_DS1557		11	/* Dallas DS1557 RTC */
 #define TODC_TYPE_DS17285		12	/* Dallas DS17285 RTC */
+#define TODC_TYPE_DS1553		13	/* Dallas DS1553 RTC */
 #define	TODC_TYPE_MC146818		100	/* Leave room for m48txx's */
 
 /*
@@ -207,6 +208,28 @@
 #define	TODC_TYPE_DS1501_FLAGS		(TODC_TYPE_DS1501_NVRAM_SIZE + 0xff)
 #define	TODC_TYPE_DS1501_NVRAM_ADDR_REG	0x10
 #define	TODC_TYPE_DS1501_NVRAM_DATA_REG	0x13
+
+#define	TODC_TYPE_DS1553_NVRAM_SIZE		0x1ff0
+#define	TODC_TYPE_DS1553_SW_FLAGS		0
+#define	TODC_TYPE_DS1553_YEAR			0x1fff
+#define	TODC_TYPE_DS1553_MONTH			0x1ffe
+#define	TODC_TYPE_DS1553_DOM			0x1ffd	/* Day of Month */
+#define	TODC_TYPE_DS1553_DOW			0x1ffc	/* Day of Week */
+#define	TODC_TYPE_DS1553_HOURS			0x1ffb
+#define	TODC_TYPE_DS1553_MINUTES		0x1ffa
+#define	TODC_TYPE_DS1553_SECONDS		0x1ff9
+#define	TODC_TYPE_DS1553_CNTL_B			0x1ff9
+#define	TODC_TYPE_DS1553_CNTL_A			0x1ff8	/* control_a R/W regs */
+#define	TODC_TYPE_DS1553_WATCHDOG		0x1ff7
+#define	TODC_TYPE_DS1553_INTERRUPTS		0x1ff6
+#define	TODC_TYPE_DS1553_ALARM_DATE		0x1ff5
+#define	TODC_TYPE_DS1553_ALARM_HOUR		0x1ff4
+#define	TODC_TYPE_DS1553_ALARM_MINUTES		0x1ff3
+#define	TODC_TYPE_DS1553_ALARM_SECONDS		0x1ff2
+#define	TODC_TYPE_DS1553_CENTURY		0x1ff8
+#define	TODC_TYPE_DS1553_FLAGS			0x1ff0
+#define	TODC_TYPE_DS1553_NVRAM_ADDR_REG		0
+#define	TODC_TYPE_DS1553_NVRAM_DATA_REG		0
 
 #define	TODC_TYPE_DS1557_NVRAM_SIZE		0x7fff0
 #define	TODC_TYPE_DS1557_SW_FLAGS		0
diff -Nru a/include/asm-ppc/uninorth.h b/include/asm-ppc/uninorth.h
--- a/include/asm-ppc/uninorth.h	2005-03-11 12:51:51 -08:00
+++ b/include/asm-ppc/uninorth.h	2005-03-11 12:51:51 -08:00
@@ -27,13 +27,18 @@
 #define UNI_N_CFG_AGP_BASE		0x90
 #define UNI_N_CFG_GART_CTRL		0x94
 #define UNI_N_CFG_INTERNAL_STATUS	0x98
+#define UNI_N_CFG_GART_DUMMY_PAGE	0xa4
 
 /* UNI_N_CFG_GART_CTRL bits definitions */
-/* Not U3 */
 #define UNI_N_CFG_GART_INVAL		0x00000001
 #define UNI_N_CFG_GART_ENABLE		0x00000100
 #define UNI_N_CFG_GART_2xRESET		0x00010000
 #define UNI_N_CFG_GART_DISSBADET	0x00020000
+/* The following seems to only be used only on U3 <j.glisse@gmail.com> */
+#define U3_N_CFG_GART_SYNCMODE		0x00040000
+#define U3_N_CFG_GART_PERFRD		0x00080000
+#define U3_N_CFG_GART_B2BGNT		0x00200000
+#define U3_N_CFG_GART_FASTDDR		0x00400000
 
 /* My understanding of UniNorth AGP as of UniNorth rev 1.0x,
  * revision 1.5 (x4 AGP) may need further changes.
diff -Nru a/include/asm-ppc/unistd.h b/include/asm-ppc/unistd.h
--- a/include/asm-ppc/unistd.h	2005-03-11 12:51:41 -08:00
+++ b/include/asm-ppc/unistd.h	2005-03-11 12:51:41 -08:00
@@ -276,8 +276,9 @@
 #define __NR_add_key		269
 #define __NR_request_key	270
 #define __NR_keyctl		271
+#define __NR_waitid		272
 
-#define __NR_syscalls		272
+#define __NR_syscalls		273
 
 #define __NR(n)	#n
 
@@ -468,7 +469,7 @@
  * but it doesn't work on all toolchains, so we just do it by hand
  */
 #ifndef cond_syscall
-#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall");
+#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall")
 #endif
 
 #endif /* __KERNEL__ */
diff -Nru a/include/asm-ppc64/a.out.h b/include/asm-ppc64/a.out.h
--- a/include/asm-ppc64/a.out.h	2005-03-11 12:51:41 -08:00
+++ b/include/asm-ppc64/a.out.h	2005-03-11 12:51:41 -08:00
@@ -30,14 +30,11 @@
 
 #ifdef __KERNEL__
 
-#define STACK_TOP_USER64 (TASK_SIZE_USER64)
+#define STACK_TOP_USER64 TASK_SIZE_USER64
+#define STACK_TOP_USER32 TASK_SIZE_USER32
 
-/* Give 32-bit user space a full 4G address space to live in. */
-#define STACK_TOP_USER32 (TASK_SIZE_USER32)
-
-#define STACK_TOP ((test_thread_flag(TIF_32BIT) || \
-		(ppcdebugset(PPCDBG_BINFMT_32ADDR))) ? \
-		STACK_TOP_USER32 : STACK_TOP_USER64)
+#define STACK_TOP (test_thread_flag(TIF_32BIT) ? \
+		   STACK_TOP_USER32 : STACK_TOP_USER64)
 
 #endif /* __KERNEL__ */
 
diff -Nru a/include/asm-ppc64/agp.h b/include/asm-ppc64/agp.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-ppc64/agp.h	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,13 @@
+#ifndef AGP_H
+#define AGP_H 1
+
+#include <asm/io.h>
+
+/* nothing much needed here */
+
+#define map_page_into_agp(page)
+#define unmap_page_from_agp(page)
+#define flush_agp_mappings()
+#define flush_agp_cache() mb()
+
+#endif
diff -Nru a/include/asm-ppc64/cacheflush.h b/include/asm-ppc64/cacheflush.h
--- a/include/asm-ppc64/cacheflush.h	2005-03-11 12:51:41 -08:00
+++ b/include/asm-ppc64/cacheflush.h	2005-03-11 12:51:41 -08:00
@@ -12,7 +12,7 @@
 #define flush_cache_all()			do { } while (0)
 #define flush_cache_mm(mm)			do { } while (0)
 #define flush_cache_range(vma, start, end)	do { } while (0)
-#define flush_cache_page(vma, vmaddr)		do { } while (0)
+#define flush_cache_page(vma, vmaddr, pfn)	do { } while (0)
 #define flush_icache_page(vma, page)		do { } while (0)
 #define flush_cache_vmap(start, end)		do { } while (0)
 #define flush_cache_vunmap(start, end)		do { } while (0)
@@ -40,7 +40,7 @@
 
 static inline void flush_icache_range(unsigned long start, unsigned long stop)
 {
-	if (!(cur_cpu_spec->cpu_features & CPU_FTR_COHERENT_ICACHE))
+	if (!cpu_has_feature(CPU_FTR_COHERENT_ICACHE))
 		__flush_icache_range(start, stop);
 }
 
diff -Nru a/include/asm-ppc64/cputable.h b/include/asm-ppc64/cputable.h
--- a/include/asm-ppc64/cputable.h	2005-03-11 12:51:47 -08:00
+++ b/include/asm-ppc64/cputable.h	2005-03-11 12:51:47 -08:00
@@ -66,6 +66,11 @@
 extern struct cpu_spec		cpu_specs[];
 extern struct cpu_spec		*cur_cpu_spec;
 
+static inline unsigned long cpu_has_feature(unsigned long feature)
+{
+	return cur_cpu_spec->cpu_features & feature;
+}
+
 
 /* firmware feature bitmask values */
 #define FIRMWARE_MAX_FEATURES 63
diff -Nru a/include/asm-ppc64/dma-mapping.h b/include/asm-ppc64/dma-mapping.h
--- a/include/asm-ppc64/dma-mapping.h	2005-03-11 12:51:51 -08:00
+++ b/include/asm-ppc64/dma-mapping.h	2005-03-11 12:51:51 -08:00
@@ -113,4 +113,24 @@
 	/* nothing to do */
 }
 
+/*
+ * DMA operations are abstracted for G5 vs. i/pSeries, PCI vs. VIO
+ */
+struct dma_mapping_ops {
+	void *		(*alloc_coherent)(struct device *dev, size_t size,
+				dma_addr_t *dma_handle, int flag);
+	void		(*free_coherent)(struct device *dev, size_t size,
+				void *vaddr, dma_addr_t dma_handle);
+	dma_addr_t	(*map_single)(struct device *dev, void *ptr,
+				size_t size, enum dma_data_direction direction);
+	void		(*unmap_single)(struct device *dev, dma_addr_t dma_addr,
+				size_t size, enum dma_data_direction direction);
+	int		(*map_sg)(struct device *dev, struct scatterlist *sg,
+				int nents, enum dma_data_direction direction);
+	void		(*unmap_sg)(struct device *dev, struct scatterlist *sg,
+				int nents, enum dma_data_direction direction);
+	int		(*dma_supported)(struct device *dev, u64 mask);
+	int		(*dac_dma_supported)(struct device *dev, u64 mask);
+};
+
 #endif	/* _ASM_DMA_MAPPING_H */
diff -Nru a/include/asm-ppc64/eeh.h b/include/asm-ppc64/eeh.h
--- a/include/asm-ppc64/eeh.h	2005-03-11 12:51:52 -08:00
+++ b/include/asm-ppc64/eeh.h	2005-03-11 12:51:52 -08:00
@@ -104,17 +104,30 @@
  */
 #define EEH_IO_ERROR_VALUE(size)	(~0U >> ((4 - (size)) * 8))
 
-#else
-#define eeh_init()
-#define eeh_check_failure(token, val) (val)
-#define eeh_dn_check_failure(dn, dev) (0)
-#define pci_addr_cache_build()
-#define eeh_add_device_early(dn)
-#define eeh_add_device_late(dev)
-#define eeh_remove_device(dev)
+#else /* !CONFIG_EEH */
+static inline void eeh_init(void) { }
+
+static inline unsigned long eeh_check_failure(const volatile void __iomem *token, unsigned long val)
+{
+	return val;
+}
+
+static inline int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev)
+{
+	return 0;
+}
+
+static inline void pci_addr_cache_build(void) { }
+
+static inline void eeh_add_device_early(struct device_node *dn) { }
+
+static inline void eeh_add_device_late(struct pci_dev *dev) { }
+
+static inline void eeh_remove_device(struct pci_dev *dev) { }
+
 #define EEH_POSSIBLE_ERROR(val, type) (0)
 #define EEH_IO_ERROR_VALUE(size) (-1UL)
-#endif
+#endif /* CONFIG_EEH */
 
 /* 
  * MMIO read/write operations with EEH support.
diff -Nru a/include/asm-ppc64/elf.h b/include/asm-ppc64/elf.h
--- a/include/asm-ppc64/elf.h	2005-03-11 12:51:47 -08:00
+++ b/include/asm-ppc64/elf.h	2005-03-11 12:51:47 -08:00
@@ -238,10 +238,20 @@
 /* A special ignored type value for PPC, for glibc compatibility.  */
 #define AT_IGNOREPPC		22
 
+/* The vDSO location. We have to use the same value as x86 for glibc's
+ * sake :-)
+ */
+#define AT_SYSINFO_EHDR		33
+
 extern int dcache_bsize;
 extern int icache_bsize;
 extern int ucache_bsize;
 
+/* We do have an arch_setup_additional_pages for vDSO matters */
+#define ARCH_HAS_SETUP_ADDITIONAL_PAGES
+struct linux_binprm;
+extern int arch_setup_additional_pages(struct linux_binprm *bprm, int executable_stack);
+
 /*
  * The requirements here are:
  * - keep the final alignment of sp (sp & 0xf)
@@ -260,6 +270,8 @@
 	NEW_AUX_ENT(AT_DCACHEBSIZE, dcache_bsize);			\
 	NEW_AUX_ENT(AT_ICACHEBSIZE, icache_bsize);			\
 	NEW_AUX_ENT(AT_UCACHEBSIZE, ucache_bsize);			\
+	/* vDSO base */							\
+	NEW_AUX_ENT(AT_SYSINFO_EHDR, current->thread.vdso_base);       	\
  } while (0)
 
 /* PowerPC64 relocations defined by the ABIs */
diff -Nru a/include/asm-ppc64/iommu.h b/include/asm-ppc64/iommu.h
--- a/include/asm-ppc64/iommu.h	2005-03-11 12:51:47 -08:00
+++ b/include/asm-ppc64/iommu.h	2005-03-11 12:51:47 -08:00
@@ -145,9 +145,9 @@
 extern void iommu_unmap_sg(struct iommu_table *tbl, struct scatterlist *sglist,
 		int nelems, enum dma_data_direction direction);
 
-extern void *iommu_alloc_consistent(struct iommu_table *tbl, size_t size,
-		dma_addr_t *dma_handle);
-extern void iommu_free_consistent(struct iommu_table *tbl, size_t size,
+extern void *iommu_alloc_coherent(struct iommu_table *tbl, size_t size,
+		dma_addr_t *dma_handle, int flag);
+extern void iommu_free_coherent(struct iommu_table *tbl, size_t size,
 		void *vaddr, dma_addr_t dma_handle);
 extern dma_addr_t iommu_map_single(struct iommu_table *tbl, void *vaddr,
 		size_t size, enum dma_data_direction direction);
diff -Nru a/include/asm-ppc64/kprobes.h b/include/asm-ppc64/kprobes.h
--- a/include/asm-ppc64/kprobes.h	2005-03-11 12:51:43 -08:00
+++ b/include/asm-ppc64/kprobes.h	2005-03-11 12:51:43 -08:00
@@ -35,6 +35,11 @@
 #define BREAKPOINT_INSTRUCTION	0x7fe00008	/* trap */
 #define MAX_INSN_SIZE 1
 
+#define IS_TW(instr)		(((instr) & 0xfc0007fe) == 0x7c000008)
+#define IS_TD(instr)		(((instr) & 0xfc0007fe) == 0x7c000088)
+#define IS_TDI(instr)		(((instr) & 0xfc000000) == 0x08000000)
+#define IS_TWI(instr)		(((instr) & 0xfc000000) == 0x0c000000)
+
 #define JPROBE_ENTRY(pentry)	(kprobe_opcode_t *)((func_descr_t *)pentry)
 
 /* Architecture specific copy of original instruction */
diff -Nru a/include/asm-ppc64/lmb.h b/include/asm-ppc64/lmb.h
--- a/include/asm-ppc64/lmb.h	2005-03-11 12:51:51 -08:00
+++ b/include/asm-ppc64/lmb.h	2005-03-11 12:51:51 -08:00
@@ -16,8 +16,6 @@
 #include <linux/init.h>
 #include <asm/prom.h>
 
-extern unsigned long reloc_offset(void);
-
 #define MAX_LMB_REGIONS 128
 
 #define LMB_ALLOC_ANYWHERE	0
diff -Nru a/include/asm-ppc64/machdep.h b/include/asm-ppc64/machdep.h
--- a/include/asm-ppc64/machdep.h	2005-03-11 12:51:42 -08:00
+++ b/include/asm-ppc64/machdep.h	2005-03-11 12:51:42 -08:00
@@ -30,6 +30,7 @@
 	void  (*setup_cpu)(int nr);
 	void  (*take_timebase)(void);
 	void  (*give_timebase)(void);
+	int   (*cpu_enable)(unsigned int nr);
 	int   (*cpu_disable)(void);
 	void  (*cpu_die)(unsigned int nr);
 };
diff -Nru a/include/asm-ppc64/mmu_context.h b/include/asm-ppc64/mmu_context.h
--- a/include/asm-ppc64/mmu_context.h	2005-03-11 12:51:42 -08:00
+++ b/include/asm-ppc64/mmu_context.h	2005-03-11 12:51:42 -08:00
@@ -59,11 +59,11 @@
 		return;
 
 #ifdef CONFIG_ALTIVEC
-	if (cur_cpu_spec->cpu_features & CPU_FTR_ALTIVEC)
+	if (cpu_has_feature(CPU_FTR_ALTIVEC))
 		asm volatile ("dssall");
 #endif /* CONFIG_ALTIVEC */
 
-	if (cur_cpu_spec->cpu_features & CPU_FTR_SLB)
+	if (cpu_has_feature(CPU_FTR_SLB))
 		switch_slb(tsk, next);
 	else
 		switch_stab(tsk, next);
diff -Nru a/include/asm-ppc64/page.h b/include/asm-ppc64/page.h
--- a/include/asm-ppc64/page.h	2005-03-11 12:51:40 -08:00
+++ b/include/asm-ppc64/page.h	2005-03-11 12:51:40 -08:00
@@ -67,7 +67,7 @@
 #define HAVE_ARCH_HUGETLB_UNMAPPED_AREA
 
 #define in_hugepage_area(context, addr) \
-	((cur_cpu_spec->cpu_features & CPU_FTR_16M_PAGE) && \
+	(cpu_has_feature(CPU_FTR_16M_PAGE) && \
 	 ( (((addr) >= TASK_HPAGE_BASE) && ((addr) < TASK_HPAGE_END)) || \
 	   ( ((addr) < 0x100000000L) && \
 	     ((1 << GET_ESID(addr)) & (context).htlb_segs) ) ) )
@@ -184,6 +184,9 @@
 extern int page_is_ram(unsigned long pfn);
 
 extern u64 ppc64_pft_size;		/* Log 2 of page table size */
+
+/* We do define AT_SYSINFO_EHDR but don't use the gate mecanism */
+#define __HAVE_ARCH_GATE_AREA		1
 
 #endif /* __ASSEMBLY__ */
 
diff -Nru a/include/asm-ppc64/pci.h b/include/asm-ppc64/pci.h
--- a/include/asm-ppc64/pci.h	2005-03-11 12:51:42 -08:00
+++ b/include/asm-ppc64/pci.h	2005-03-11 12:51:42 -08:00
@@ -13,11 +13,14 @@
 #include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/dma-mapping.h>
+
 #include <asm/machdep.h>
 #include <asm/scatterlist.h>
 #include <asm/io.h>
 #include <asm/prom.h>
 
+#include <asm-generic/pci-dma-compat.h>
+
 #define PCIBIOS_MIN_IO		0x1000
 #define PCIBIOS_MIN_MEM		0x10000000
 
@@ -63,135 +66,22 @@
 
 extern unsigned int pcibios_assign_all_busses(void);
 
-/*
- * PCI DMA operations are abstracted for G5 vs. i/pSeries
- */
-struct pci_dma_ops {
-	void *		(*pci_alloc_consistent)(struct pci_dev *hwdev, size_t size,
-					dma_addr_t *dma_handle);
-	void		(*pci_free_consistent)(struct pci_dev *hwdev, size_t size,
-				       void *vaddr, dma_addr_t dma_handle);
-
-	dma_addr_t	(*pci_map_single)(struct pci_dev *hwdev, void *ptr,
-					  size_t size, enum dma_data_direction direction);
-	void		(*pci_unmap_single)(struct pci_dev *hwdev, dma_addr_t dma_addr,
-					    size_t size, enum dma_data_direction direction);
-	int		(*pci_map_sg)(struct pci_dev *hwdev, struct scatterlist *sg,
-				      int nents, enum dma_data_direction direction);
-	void		(*pci_unmap_sg)(struct pci_dev *hwdev, struct scatterlist *sg,
-					int nents, enum dma_data_direction direction);
-	int		(*pci_dma_supported)(struct pci_dev *hwdev, u64 mask);
-	int		(*pci_dac_dma_supported)(struct pci_dev *hwdev, u64 mask);
-};
-
-extern struct pci_dma_ops pci_dma_ops;
-
-static inline void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size,
-					 dma_addr_t *dma_handle)
-{
-	return pci_dma_ops.pci_alloc_consistent(hwdev, size, dma_handle);
-}
-
-static inline void pci_free_consistent(struct pci_dev *hwdev, size_t size,
-				       void *vaddr, dma_addr_t dma_handle)
-{
-	pci_dma_ops.pci_free_consistent(hwdev, size, vaddr, dma_handle);
-}
-
-static inline dma_addr_t pci_map_single(struct pci_dev *hwdev, void *ptr,
-					size_t size, int direction)
-{
-	return pci_dma_ops.pci_map_single(hwdev, ptr, size,
-			(enum dma_data_direction)direction);
-}
-
-static inline void pci_unmap_single(struct pci_dev *hwdev, dma_addr_t dma_addr,
-				    size_t size, int direction)
-{
-	pci_dma_ops.pci_unmap_single(hwdev, dma_addr, size,
-			(enum dma_data_direction)direction);
-}
-
-static inline int pci_map_sg(struct pci_dev *hwdev, struct scatterlist *sg,
-			     int nents, int direction)
-{
-	return pci_dma_ops.pci_map_sg(hwdev, sg, nents,
-			(enum dma_data_direction)direction);
-}
-
-static inline void pci_unmap_sg(struct pci_dev *hwdev, struct scatterlist *sg,
-				int nents, int direction)
-{
-	pci_dma_ops.pci_unmap_sg(hwdev, sg, nents,
-			(enum dma_data_direction)direction);
-}
-
-static inline void pci_dma_sync_single_for_cpu(struct pci_dev *hwdev,
-					       dma_addr_t dma_handle,
-					       size_t size, int direction)
-{
-	BUG_ON(direction == PCI_DMA_NONE);
-	/* nothing to do */
-}
-
-static inline void pci_dma_sync_single_for_device(struct pci_dev *hwdev,
-						  dma_addr_t dma_handle,
-						  size_t size, int direction)
-{
-	BUG_ON(direction == PCI_DMA_NONE);
-	/* nothing to do */
-}
-
-static inline void pci_dma_sync_sg_for_cpu(struct pci_dev *hwdev,
-					   struct scatterlist *sg,
-					   int nelems, int direction)
-{
-	BUG_ON(direction == PCI_DMA_NONE);
-	/* nothing to do */
-}
-
-static inline void pci_dma_sync_sg_for_device(struct pci_dev *hwdev,
-					      struct scatterlist *sg,
-					      int nelems, int direction)
-{
-	BUG_ON(direction == PCI_DMA_NONE);
-	/* nothing to do */
-}
-
-/* Return whether the given PCI device DMA address mask can
- * be supported properly.  For example, if your device can
- * only drive the low 24-bits during PCI bus mastering, then
- * you would pass 0x00ffffff as the mask to this function.
- * We default to supporting only 32 bits DMA unless we have
- * an explicit override of this function in pci_dma_ops for
- * the platform
- */
-static inline int pci_dma_supported(struct pci_dev *hwdev, u64 mask)
-{
-	if (pci_dma_ops.pci_dma_supported)
-		return pci_dma_ops.pci_dma_supported(hwdev, mask);
-	return (mask < 0x100000000ull);
-}
+extern struct dma_mapping_ops pci_dma_ops;
 
 /* For DAC DMA, we currently don't support it by default, but
  * we let the platform override this
  */
 static inline int pci_dac_dma_supported(struct pci_dev *hwdev,u64 mask)
 {
-	if (pci_dma_ops.pci_dac_dma_supported)
-		return pci_dma_ops.pci_dac_dma_supported(hwdev, mask);
+	if (pci_dma_ops.dac_dma_supported)
+		return pci_dma_ops.dac_dma_supported(&hwdev->dev, mask);
 	return 0;
 }
 
-static inline int pci_dma_mapping_error(dma_addr_t dma_addr)
-{
-	return dma_mapping_error(dma_addr);
-}
-
 extern int pci_domain_nr(struct pci_bus *bus);
 
-/* Set the name of the bus as it appears in /proc/bus/pci */
-extern int pci_name_bus(char *name, struct pci_bus *bus);
+/* Decide whether to display the domain number in /proc */
+extern int pci_proc_domain(struct pci_bus *bus);
 
 struct vm_area_struct;
 /* Map a range of PCI memory or I/O space for a device into user space */
@@ -200,10 +90,6 @@
 
 /* Tell drivers/pci/proc.c that we have pci_mmap_page_range() */
 #define HAVE_PCI_MMAP	1
-
-#define pci_map_page(dev, page, off, size, dir) \
-		pci_map_single(dev, (page_address(page) + (off)), size, dir)
-#define pci_unmap_page(dev,addr,sz,dir) pci_unmap_single(dev,addr,sz,dir)
 
 /* pci_unmap_{single,page} is not a nop, thus... */
 #define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME)	\
diff -Nru a/include/asm-ppc64/pgalloc.h b/include/asm-ppc64/pgalloc.h
--- a/include/asm-ppc64/pgalloc.h	2005-03-11 12:51:41 -08:00
+++ b/include/asm-ppc64/pgalloc.h	2005-03-11 12:51:41 -08:00
@@ -48,42 +48,26 @@
 #define pmd_populate(mm, pmd, pte_page) \
 	pmd_populate_kernel(mm, pmd, page_address(pte_page))
 
-static inline pte_t *
-pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
+static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
 {
-	pte_t *pte;
-	pte = kmem_cache_alloc(zero_cache, GFP_KERNEL|__GFP_REPEAT);
-	if (pte) {
-		struct page *ptepage = virt_to_page(pte);
-		ptepage->mapping = (void *) mm;
-		ptepage->index = address & PMD_MASK;
-	}
-	return pte;
+	return kmem_cache_alloc(zero_cache, GFP_KERNEL|__GFP_REPEAT);
 }
 
-static inline struct page *
-pte_alloc_one(struct mm_struct *mm, unsigned long address)
+static inline struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address)
 {
-	pte_t *pte;
-	pte = kmem_cache_alloc(zero_cache, GFP_KERNEL|__GFP_REPEAT);
-	if (pte) {
-		struct page *ptepage = virt_to_page(pte);
-		ptepage->mapping = (void *) mm;
-		ptepage->index = address & PMD_MASK;
-		return ptepage;
-	}
+	pte_t *pte = kmem_cache_alloc(zero_cache, GFP_KERNEL|__GFP_REPEAT);
+	if (pte)
+		return virt_to_page(pte);
 	return NULL;
 }
 		
 static inline void pte_free_kernel(pte_t *pte)
 {
-	virt_to_page(pte)->mapping = NULL;
 	kmem_cache_free(zero_cache, pte);
 }
 
 static inline void pte_free(struct page *ptepage)
 {
-	ptepage->mapping = NULL;
 	kmem_cache_free(zero_cache, page_address(ptepage));
 }
 
diff -Nru a/include/asm-ppc64/pgtable.h b/include/asm-ppc64/pgtable.h
--- a/include/asm-ppc64/pgtable.h	2005-03-11 12:51:51 -08:00
+++ b/include/asm-ppc64/pgtable.h	2005-03-11 12:51:51 -08:00
@@ -315,9 +315,10 @@
  * batch, doesn't actually triggers the hash flush immediately,
  * you need to call flush_tlb_pending() to do that.
  */
-extern void hpte_update(pte_t *ptep, unsigned long pte, int wrprot);
+extern void hpte_update(struct mm_struct *mm, unsigned long addr, unsigned long pte,
+			int wrprot);
 
-static inline int ptep_test_and_clear_young(pte_t *ptep)
+static inline int __ptep_test_and_clear_young(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
 {
 	unsigned long old;
 
@@ -325,18 +326,25 @@
 		return 0;
 	old = pte_update(ptep, _PAGE_ACCESSED);
 	if (old & _PAGE_HASHPTE) {
-		hpte_update(ptep, old, 0);
+		hpte_update(mm, addr, old, 0);
 		flush_tlb_pending();
 	}
 	return (old & _PAGE_ACCESSED) != 0;
 }
+#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
+#define ptep_test_and_clear_young(__vma, __addr, __ptep)		   \
+({									   \
+	int __r;							   \
+	__r = __ptep_test_and_clear_young((__vma)->vm_mm, __addr, __ptep); \
+	__r;								   \
+})
 
 /*
  * On RW/DIRTY bit transitions we can avoid flushing the hpte. For the
  * moment we always flush but we need to fix hpte_update and test if the
  * optimisation is worth it.
  */
-static inline int ptep_test_and_clear_dirty(pte_t *ptep)
+static inline int __ptep_test_and_clear_dirty(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
 {
 	unsigned long old;
 
@@ -344,11 +352,19 @@
 		return 0;
 	old = pte_update(ptep, _PAGE_DIRTY);
 	if (old & _PAGE_HASHPTE)
-		hpte_update(ptep, old, 0);
+		hpte_update(mm, addr, old, 0);
 	return (old & _PAGE_DIRTY) != 0;
 }
+#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_DIRTY
+#define ptep_test_and_clear_dirty(__vma, __addr, __ptep)		   \
+({									   \
+	int __r;							   \
+	__r = __ptep_test_and_clear_dirty((__vma)->vm_mm, __addr, __ptep); \
+	__r;								   \
+})
 
-static inline void ptep_set_wrprotect(pte_t *ptep)
+#define __HAVE_ARCH_PTEP_SET_WRPROTECT
+static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
 {
 	unsigned long old;
 
@@ -356,7 +372,7 @@
        		return;
 	old = pte_update(ptep, _PAGE_RW);
 	if (old & _PAGE_HASHPTE)
-		hpte_update(ptep, old, 0);
+		hpte_update(mm, addr, old, 0);
 }
 
 /*
@@ -370,42 +386,46 @@
 #define __HAVE_ARCH_PTEP_CLEAR_YOUNG_FLUSH
 #define ptep_clear_flush_young(__vma, __address, __ptep)		\
 ({									\
-	int __young = ptep_test_and_clear_young(__ptep);		\
+	int __young = __ptep_test_and_clear_young((__vma)->vm_mm, __address, \
+						  __ptep);		\
 	__young;							\
 })
 
 #define __HAVE_ARCH_PTEP_CLEAR_DIRTY_FLUSH
 #define ptep_clear_flush_dirty(__vma, __address, __ptep)		\
 ({									\
-	int __dirty = ptep_test_and_clear_dirty(__ptep);		\
+	int __dirty = __ptep_test_and_clear_dirty((__vma)->vm_mm, __address, \
+						  __ptep); 		\
 	flush_tlb_page(__vma, __address);				\
 	__dirty;							\
 })
 
-static inline pte_t ptep_get_and_clear(pte_t *ptep)
+#define __HAVE_ARCH_PTEP_GET_AND_CLEAR
+static inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
 {
 	unsigned long old = pte_update(ptep, ~0UL);
 
 	if (old & _PAGE_HASHPTE)
-		hpte_update(ptep, old, 0);
+		hpte_update(mm, addr, old, 0);
 	return __pte(old);
 }
 
-static inline void pte_clear(pte_t * ptep)
+static inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t * ptep)
 {
 	unsigned long old = pte_update(ptep, ~0UL);
 
 	if (old & _PAGE_HASHPTE)
-		hpte_update(ptep, old, 0);
+		hpte_update(mm, addr, old, 0);
 }
 
 /*
  * set_pte stores a linux PTE into the linux page table.
  */
-static inline void set_pte(pte_t *ptep, pte_t pte)
+static inline void set_pte_at(struct mm_struct *mm, unsigned long addr,
+			      pte_t *ptep, pte_t pte)
 {
 	if (pte_present(*ptep)) {
-		pte_clear(ptep);
+		pte_clear(mm, addr, ptep);
 		flush_tlb_pending();
 	}
 	*ptep = __pte(pte_val(pte)) & ~_PAGE_HPTEFLAGS;
@@ -443,6 +463,7 @@
  */
 #define pgprot_noncached(prot)	(__pgprot(pgprot_val(prot) | _PAGE_NO_CACHE | _PAGE_GUARDED))
 
+#define __HAVE_ARCH_PTE_SAME
 #define pte_same(A,B)	(((pte_val(A) ^ pte_val(B)) & ~_PAGE_HPTEFLAGS) == 0)
 
 extern unsigned long ioremap_bot, ioremap_base;
@@ -550,14 +571,8 @@
 	return pt;
 }
 
-#endif /* __ASSEMBLY__ */
-
-#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
-#define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_DIRTY
-#define __HAVE_ARCH_PTEP_GET_AND_CLEAR
-#define __HAVE_ARCH_PTEP_SET_WRPROTECT
-#define __HAVE_ARCH_PTEP_MKDIRTY
-#define __HAVE_ARCH_PTE_SAME
 #include <asm-generic/pgtable.h>
+
+#endif /* __ASSEMBLY__ */
 
 #endif /* _PPC64_PGTABLE_H */
diff -Nru a/include/asm-ppc64/pmc.h b/include/asm-ppc64/pmc.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-ppc64/pmc.h	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,29 @@
+/*
+ * pmc.h
+ * Copyright (C) 2004  David Gibson, IBM Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ */
+#ifndef _PPC64_PMC_H
+#define _PPC64_PMC_H
+
+#include <asm/ptrace.h>
+
+typedef void (*perf_irq_t)(struct pt_regs *);
+
+int reserve_pmc_hardware(perf_irq_t new_perf_irq);
+void release_pmc_hardware(void);
+
+#endif /* _PPC64_PMC_H */
diff -Nru a/include/asm-ppc64/processor.h b/include/asm-ppc64/processor.h
--- a/include/asm-ppc64/processor.h	2005-03-11 12:51:52 -08:00
+++ b/include/asm-ppc64/processor.h	2005-03-11 12:51:52 -08:00
@@ -544,8 +544,8 @@
 /* This decides where the kernel will search for a free chunk of vm
  * space during mmap's.
  */
-#define TASK_UNMAPPED_BASE_USER32 (PAGE_ALIGN(STACK_TOP_USER32 / 4))
-#define TASK_UNMAPPED_BASE_USER64 (PAGE_ALIGN(STACK_TOP_USER64 / 4))
+#define TASK_UNMAPPED_BASE_USER32 (PAGE_ALIGN(TASK_SIZE_USER32 / 4))
+#define TASK_UNMAPPED_BASE_USER64 (PAGE_ALIGN(TASK_SIZE_USER64 / 4))
 
 #define TASK_UNMAPPED_BASE ((test_thread_flag(TIF_32BIT)||(ppcdebugset(PPCDBG_BINFMT_32ADDR))) ? \
 		TASK_UNMAPPED_BASE_USER32 : TASK_UNMAPPED_BASE_USER64 )
@@ -562,7 +562,9 @@
 	double		fpr[32];	/* Complete floating point set */
 	unsigned long	fpscr;		/* Floating point status (plus pad) */
 	unsigned long	fpexc_mode;	/* Floating-point exception mode */
-	unsigned long	pad[3];		/* was saved_msr, saved_softe */
+	unsigned long	start_tb;	/* Start purr when proc switched in */
+	unsigned long	accum_tb;	/* Total accumilated purr for process */
+	unsigned long	vdso_base;	/* base of the vDSO library */
 #ifdef CONFIG_ALTIVEC
 	/* Complete AltiVec register set */
 	vector128	vr[32] __attribute((aligned(16)));
diff -Nru a/include/asm-ppc64/prom.h b/include/asm-ppc64/prom.h
--- a/include/asm-ppc64/prom.h	2005-03-11 12:51:52 -08:00
+++ b/include/asm-ppc64/prom.h	2005-03-11 12:51:52 -08:00
@@ -137,6 +137,7 @@
 	int	devfn;			/* for pci devices */
 	int	eeh_mode;		/* See eeh.h for possible EEH_MODEs */
 	int	eeh_config_addr;
+	int	pci_ext_config_space;	/* for pci devices */
 	struct  pci_controller *phb;	/* for pci devices */
 	struct	iommu_table *iommu_table;	/* for phb's or bridges */
 
diff -Nru a/include/asm-ppc64/rtas.h b/include/asm-ppc64/rtas.h
--- a/include/asm-ppc64/rtas.h	2005-03-11 12:51:51 -08:00
+++ b/include/asm-ppc64/rtas.h	2005-03-11 12:51:51 -08:00
@@ -24,11 +24,8 @@
 
 /* RTAS return status codes */
 #define RTAS_BUSY		-2    /* RTAS Busy */
-#define RTAS_NO_SUCH_INDICATOR	-3    /* No such indicator implemented */
 #define RTAS_EXTENDED_DELAY_MIN	9900
 #define RTAS_EXTENDED_DELAY_MAX	9905
-
-#define RTAS_UNKNOWN_OP		-1099 /* Unknown RTAS Token */
 
 /*
  * In general to call RTAS use rtas_token("string") to lookup
diff -Nru a/include/asm-ppc64/smp.h b/include/asm-ppc64/smp.h
--- a/include/asm-ppc64/smp.h	2005-03-11 12:51:40 -08:00
+++ b/include/asm-ppc64/smp.h	2005-03-11 12:51:40 -08:00
@@ -29,7 +29,7 @@
 extern int boot_cpuid;
 extern int boot_cpuid_phys;
 
-extern void cpu_die(void) __attribute__((noreturn));
+extern void cpu_die(void);
 
 #ifdef CONFIG_SMP
 
@@ -37,6 +37,13 @@
 struct pt_regs;
 extern void smp_message_recv(int, struct pt_regs *);
 
+#ifdef CONFIG_HOTPLUG_CPU
+extern void fixup_irqs(cpumask_t map);
+int generic_cpu_disable(void);
+int generic_cpu_enable(unsigned int cpu);
+void generic_cpu_die(unsigned int cpu);
+void generic_mach_cpu_die(void);
+#endif
 
 #define __smp_processor_id() (get_paca()->paca_index)
 #define hard_smp_processor_id() (get_paca()->hw_cpu_id)
diff -Nru a/include/asm-ppc64/system.h b/include/asm-ppc64/system.h
--- a/include/asm-ppc64/system.h	2005-03-11 12:51:52 -08:00
+++ b/include/asm-ppc64/system.h	2005-03-11 12:51:52 -08:00
@@ -300,5 +300,7 @@
  */
 #define NET_IP_ALIGN   0
 
+#define arch_align_stack(x) (x)
+
 #endif /* __KERNEL__ */
 #endif
diff -Nru a/include/asm-ppc64/systemcfg.h b/include/asm-ppc64/systemcfg.h
--- a/include/asm-ppc64/systemcfg.h	2005-03-11 12:51:46 -08:00
+++ b/include/asm-ppc64/systemcfg.h	2005-03-11 12:51:46 -08:00
@@ -20,10 +20,14 @@
  * Minor version changes are a hint.
  */
 #define SYSTEMCFG_MAJOR 1
-#define SYSTEMCFG_MINOR 0
+#define SYSTEMCFG_MINOR 1
 
 #ifndef __ASSEMBLY__
 
+#include <linux/unistd.h>
+
+#define SYSCALL_MAP_SIZE      ((__NR_syscalls + 31) / 32)
+
 struct systemcfg {
 	__u8  eye_catcher[16];		/* Eyecatcher: SYSTEMCFG:PPC64	0x00 */
 	struct {			/* Systemcfg version numbers	     */
@@ -47,7 +51,8 @@
 	__u32 dcache_line_size;		/* L1 d-cache line size		0x64 */
 	__u32 icache_size;		/* L1 i-cache size		0x68 */
 	__u32 icache_line_size;		/* L1 i-cache line size		0x6C */
-	__u8  reserved0[3984];		/* Reserve rest of page		0x70 */
+   	__u32 syscall_map_64[SYSCALL_MAP_SIZE]; /* map of available syscalls 0x70 */
+   	__u32 syscall_map_32[SYSCALL_MAP_SIZE]; /* map of available syscalls */
 };
 
 #ifdef __KERNEL__
@@ -55,9 +60,5 @@
 #endif
 
 #endif /* __ASSEMBLY__ */
-
-#define SYSTEMCFG_PAGE      0x5
-#define SYSTEMCFG_PHYS_ADDR (SYSTEMCFG_PAGE<<PAGE_SHIFT)
-#define SYSTEMCFG_VIRT_ADDR (KERNELBASE+SYSTEMCFG_PHYS_ADDR)
 
 #endif /* _SYSTEMCFG_H */
diff -Nru a/include/asm-ppc64/time.h b/include/asm-ppc64/time.h
--- a/include/asm-ppc64/time.h	2005-03-11 12:51:43 -08:00
+++ b/include/asm-ppc64/time.h	2005-03-11 12:51:43 -08:00
@@ -43,10 +43,10 @@
 struct gettimeofday_vars {
 	unsigned long tb_to_xs;
 	unsigned long stamp_xsec;
+	unsigned long tb_orig_stamp;
 };
 
 struct gettimeofday_struct {
-	unsigned long tb_orig_stamp;
 	unsigned long tb_ticks_per_sec;
 	struct gettimeofday_vars vars[2];
 	struct gettimeofday_vars * volatile varp;
@@ -102,5 +102,14 @@
 unsigned mulhwu_scale_factor(unsigned, unsigned);
 void div128_by_32( unsigned long dividend_high, unsigned long dividend_low,
 		   unsigned divisor, struct div_result *dr );
+
+/* Used to store Processor Utilization register (purr) values */
+
+struct cpu_usage {
+        u64 current_tb;  /* Holds the current purr register values */
+};
+
+DECLARE_PER_CPU(struct cpu_usage, cpu_usage_array);
+
 #endif /* __KERNEL__ */
 #endif /* __PPC64_TIME_H */
diff -Nru a/include/asm-ppc64/unistd.h b/include/asm-ppc64/unistd.h
--- a/include/asm-ppc64/unistd.h	2005-03-11 12:51:40 -08:00
+++ b/include/asm-ppc64/unistd.h	2005-03-11 12:51:40 -08:00
@@ -282,8 +282,9 @@
 #define __NR_add_key		269
 #define __NR_request_key	270
 #define __NR_keyctl		271
+#define __NR_waitid		272
 
-#define __NR_syscalls		272
+#define __NR_syscalls		273
 #ifdef __KERNEL__
 #define NR_syscalls	__NR_syscalls
 #endif
@@ -472,7 +473,7 @@
  * What we want is __attribute__((weak,alias("sys_ni_syscall"))),
  * but it doesn't work on all toolchains, so we just do it by hand
  */
-#define cond_syscall(x) asm(".weak\t." #x "\n\t.set\t." #x ",.sys_ni_syscall");
+#define cond_syscall(x) asm(".weak\t." #x "\n\t.set\t." #x ",.sys_ni_syscall")
 
 #endif		/* __KERNEL__ */
 
diff -Nru a/include/asm-ppc64/vdso.h b/include/asm-ppc64/vdso.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-ppc64/vdso.h	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,83 @@
+#ifndef __PPC64_VDSO_H__
+#define __PPC64_VDSO_H__
+
+#ifdef __KERNEL__
+
+/* Default link addresses for the vDSOs */
+#define VDSO32_LBASE	0
+#define VDSO64_LBASE	0
+
+/* Default map addresses */
+#define VDSO32_MBASE	0x100000
+#define VDSO64_MBASE	0x100000
+
+#define VDSO_VERSION_STRING	LINUX_2.6.11
+
+/* Define if 64 bits VDSO has procedure descriptors */
+#undef VDS64_HAS_DESCRIPTORS
+
+#ifndef __ASSEMBLY__
+
+extern unsigned int vdso64_pages;
+extern unsigned int vdso32_pages;
+
+/* Offsets relative to thread->vdso_base */
+extern unsigned long vdso64_rt_sigtramp;
+extern unsigned long vdso32_sigtramp;
+extern unsigned long vdso32_rt_sigtramp;
+
+extern void vdso_init(void);
+
+#else /* __ASSEMBLY__ */
+
+#ifdef __VDSO64__
+#ifdef VDS64_HAS_DESCRIPTORS
+#define V_FUNCTION_BEGIN(name)		\
+	.globl name;			\
+        .section ".opd","a";		\
+        .align 3;			\
+	name:				\
+	.quad .name,.TOC.@tocbase,0;	\
+	.previous;			\
+	.globl .name;			\
+	.type .name,@function; 		\
+	.name:				\
+
+#define V_FUNCTION_END(name)		\
+	.size .name,.-.name;
+
+#define V_LOCAL_FUNC(name) (.name)
+
+#else /* VDS64_HAS_DESCRIPTORS */
+
+#define V_FUNCTION_BEGIN(name)		\
+	.globl name;			\
+	name:				\
+
+#define V_FUNCTION_END(name)		\
+	.size name,.-name;
+
+#define V_LOCAL_FUNC(name) (name)
+
+#endif /* VDS64_HAS_DESCRIPTORS */
+#endif /* __VDSO64__ */
+
+#ifdef __VDSO32__
+
+#define V_FUNCTION_BEGIN(name)		\
+	.globl name;			\
+	.type name,@function; 		\
+	name:				\
+
+#define V_FUNCTION_END(name)		\
+	.size name,.-name;
+
+#define V_LOCAL_FUNC(name) (name)
+
+#endif /* __VDSO32__ */
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* __KERNEL__ */
+
+#endif /* __PPC64_VDSO_H__ */
diff -Nru a/include/asm-ppc64/vio.h b/include/asm-ppc64/vio.h
--- a/include/asm-ppc64/vio.h	2005-03-11 12:51:47 -08:00
+++ b/include/asm-ppc64/vio.h	2005-03-11 12:51:47 -08:00
@@ -57,32 +57,7 @@
 int vio_enable_interrupts(struct vio_dev *dev);
 int vio_disable_interrupts(struct vio_dev *dev);
 
-dma_addr_t vio_map_single(struct vio_dev *dev, void *vaddr, 
-			  size_t size, enum dma_data_direction direction);
-void vio_unmap_single(struct vio_dev *dev, dma_addr_t dma_handle, 
-		      size_t size, enum dma_data_direction direction);
-int vio_map_sg(struct vio_dev *vdev, struct scatterlist *sglist, 
-	       int nelems, enum dma_data_direction direction);
-void vio_unmap_sg(struct vio_dev *vdev, struct scatterlist *sglist, 
-		  int nelems, enum dma_data_direction direction);
-void *vio_alloc_consistent(struct vio_dev *dev, size_t size, 
-			   dma_addr_t *dma_handle);
-void vio_free_consistent(struct vio_dev *dev, size_t size, void *vaddr, 
-			 dma_addr_t dma_handle);
-
-static inline int vio_dma_supported(struct vio_dev *hwdev, u64 mask)
-{
-	return 1;
-}
-
-#define vio_map_page(dev, page, off, size, dir) \
-		vio_map_single(dev, (page_address(page) + (off)), size, dir)
-#define vio_unmap_page(dev,addr,sz,dir) vio_unmap_single(dev,addr,sz,dir)
-
-static inline int vio_set_dma_mask(struct vio_dev *dev, u64 mask)
-{
-	return -EIO;
-}
+extern struct dma_mapping_ops vio_dma_ops;
 
 extern struct bus_type vio_bus_type;
 
diff -Nru a/include/asm-s390/cacheflush.h b/include/asm-s390/cacheflush.h
--- a/include/asm-s390/cacheflush.h	2005-03-11 12:51:52 -08:00
+++ b/include/asm-s390/cacheflush.h	2005-03-11 12:51:52 -08:00
@@ -8,7 +8,7 @@
 #define flush_cache_all()			do { } while (0)
 #define flush_cache_mm(mm)			do { } while (0)
 #define flush_cache_range(vma, start, end)	do { } while (0)
-#define flush_cache_page(vma, vmaddr)		do { } while (0)
+#define flush_cache_page(vma, vmaddr, pfn)	do { } while (0)
 #define flush_dcache_page(page)			do { } while (0)
 #define flush_dcache_mmap_lock(mapping)		do { } while (0)
 #define flush_dcache_mmap_unlock(mapping)	do { } while (0)
diff -Nru a/include/asm-s390/pgalloc.h b/include/asm-s390/pgalloc.h
--- a/include/asm-s390/pgalloc.h	2005-03-11 12:51:47 -08:00
+++ b/include/asm-s390/pgalloc.h	2005-03-11 12:51:47 -08:00
@@ -130,8 +130,10 @@
 
 	pte = (pte_t *)__get_free_page(GFP_KERNEL|__GFP_REPEAT);
 	if (pte != NULL) {
-		for (i=0; i < PTRS_PER_PTE; i++)
-			pte_clear(pte+i);
+		for (i=0; i < PTRS_PER_PTE; i++) {
+			pte_clear(mm, vmaddr, pte+i);
+			vmaddr += PAGE_SIZE;
+		}
 	}
 	return pte;
 }
diff -Nru a/include/asm-s390/pgtable.h b/include/asm-s390/pgtable.h
--- a/include/asm-s390/pgtable.h	2005-03-11 12:51:50 -08:00
+++ b/include/asm-s390/pgtable.h	2005-03-11 12:51:50 -08:00
@@ -322,6 +322,7 @@
 {
 	*pteptr = pteval;
 }
+#define set_pte_at(mm,addr,ptep,pteval) set_pte(ptep,pteval)
 
 /*
  * pgd/pmd/pte query functions
@@ -457,7 +458,7 @@
 
 #endif /* __s390x__ */
 
-extern inline void pte_clear(pte_t *ptep)
+extern inline void pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
 {
 	pte_val(*ptep) = _PAGE_INVALID_EMPTY;
 }
@@ -521,7 +522,7 @@
 	return pte;
 }
 
-static inline int ptep_test_and_clear_young(pte_t *ptep)
+static inline int ptep_test_and_clear_young(struct vm_area_struct *vma, unsigned long addr, pte_t *ptep)
 {
 	return 0;
 }
@@ -531,10 +532,10 @@
 			unsigned long address, pte_t *ptep)
 {
 	/* No need to flush TLB; bits are in storage key */
-	return ptep_test_and_clear_young(ptep);
+	return ptep_test_and_clear_young(vma, address, ptep);
 }
 
-static inline int ptep_test_and_clear_dirty(pte_t *ptep)
+static inline int ptep_test_and_clear_dirty(struct vm_area_struct *vma, unsigned long addr, pte_t *ptep)
 {
 	return 0;
 }
@@ -544,13 +545,13 @@
 			unsigned long address, pte_t *ptep)
 {
 	/* No need to flush TLB; bits are in storage key */
-	return ptep_test_and_clear_dirty(ptep);
+	return ptep_test_and_clear_dirty(vma, address, ptep);
 }
 
-static inline pte_t ptep_get_and_clear(pte_t *ptep)
+static inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
 {
 	pte_t pte = *ptep;
-	pte_clear(ptep);
+	pte_clear(mm, addr, ptep);
 	return pte;
 }
 
@@ -573,19 +574,14 @@
 				      : "=m" (*ptep) : "m" (*ptep),
 				        "a" (ptep), "a" (address) );
 #endif /* __s390x__ */
-	pte_clear(ptep);
+	pte_val(*ptep) = _PAGE_INVALID_EMPTY;
 	return pte;
 }
 
-static inline void ptep_set_wrprotect(pte_t *ptep)
+static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
 {
 	pte_t old_pte = *ptep;
-	set_pte(ptep, pte_wrprotect(old_pte));
-}
-
-static inline void ptep_mkdirty(pte_t *ptep)
-{
-	pte_mkdirty(*ptep);
+	set_pte_at(mm, addr, ptep, pte_wrprotect(old_pte));
 }
 
 static inline void
@@ -756,11 +752,17 @@
  *  0000000000111111111122222222223333333333444444444455 5555 5 55566 66
  *  0123456789012345678901234567890123456789012345678901 2345 6 78901 23
  */
+#ifndef __s390x__
+#define __SWP_OFFSET_MASK (~0UL >> 12)
+#else
+#define __SWP_OFFSET_MASK (~0UL >> 11)
+#endif
 extern inline pte_t mk_swap_pte(unsigned long type, unsigned long offset)
 {
 	pte_t pte;
+	offset &= __SWP_OFFSET_MASK;
 	pte_val(pte) = _PAGE_INVALID_SWAP | ((type & 0x1f) << 2) |
-		((offset & 1) << 7) | ((offset & 0xffffe) << 11);
+		((offset & 1UL) << 7) | ((offset & ~1UL) << 11);
 	return pte;
 }
 
@@ -802,7 +804,6 @@
 #define __HAVE_ARCH_PTEP_GET_AND_CLEAR
 #define __HAVE_ARCH_PTEP_CLEAR_FLUSH
 #define __HAVE_ARCH_PTEP_SET_WRPROTECT
-#define __HAVE_ARCH_PTEP_MKDIRTY
 #define __HAVE_ARCH_PTE_SAME
 #define __HAVE_ARCH_PAGE_TEST_AND_CLEAR_DIRTY
 #define __HAVE_ARCH_PAGE_TEST_AND_CLEAR_YOUNG
diff -Nru a/include/asm-s390/posix_types.h b/include/asm-s390/posix_types.h
--- a/include/asm-s390/posix_types.h	2005-03-11 12:51:40 -08:00
+++ b/include/asm-s390/posix_types.h	2005-03-11 12:51:40 -08:00
@@ -83,16 +83,16 @@
 #endif
 
 #undef  __FD_SET
-#define __FD_SET(fd,fdsetp)  set_bit(fd,fdsetp->fds_bits)
+#define __FD_SET(fd,fdsetp)  set_bit((fd),(fdsetp)->fds_bits)
 
 #undef  __FD_CLR
-#define __FD_CLR(fd,fdsetp)  clear_bit(fd,fdsetp->fds_bits)
+#define __FD_CLR(fd,fdsetp)  clear_bit((fd),(fdsetp)->fds_bits)
 
 #undef  __FD_ISSET
-#define __FD_ISSET(fd,fdsetp)  test_bit(fd,fdsetp->fds_bits)
+#define __FD_ISSET(fd,fdsetp)  test_bit((fd),(fdsetp)->fds_bits)
 
 #undef  __FD_ZERO
-#define __FD_ZERO(fdsetp) (memset (fdsetp, 0, sizeof(*(fd_set *)fdsetp)))
+#define __FD_ZERO(fdsetp) (memset ((fdsetp), 0, sizeof(*(fd_set *)(fdsetp))))
 
 #endif     /* defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2)*/
 
diff -Nru a/include/asm-s390/smp.h b/include/asm-s390/smp.h
--- a/include/asm-s390/smp.h	2005-03-11 12:51:46 -08:00
+++ b/include/asm-s390/smp.h	2005-03-11 12:51:46 -08:00
@@ -18,6 +18,7 @@
 #if defined(__KERNEL__) && defined(CONFIG_SMP) && !defined(__ASSEMBLY__)
 
 #include <asm/lowcore.h>
+#include <asm/sigp.h>
 
 /*
   s390 specific smp.c headers
@@ -57,6 +58,30 @@
  
         __asm__ ("stap %0\n" : "=m" (cpu_address));
         return cpu_address;
+}
+
+/*
+ * returns 1 if cpu is in stopped/check stopped state or not operational
+ * returns 0 otherwise
+ */
+static inline int
+smp_cpu_not_running(int cpu)
+{
+	__u32 status;
+
+	switch (signal_processor_ps(&status, 0, cpu, sigp_sense)) {
+	case sigp_order_code_accepted:
+	case sigp_status_stored:
+		/* Check for stopped and check stop state */
+		if (status & 0x50)
+			return 1;
+		break;
+	case sigp_not_operational:
+		return 1;
+	default:
+		break;
+	}
+	return 0;
 }
 
 #define cpu_logical_map(cpu) (cpu)
diff -Nru a/include/asm-s390/system.h b/include/asm-s390/system.h
--- a/include/asm-s390/system.h	2005-03-11 12:51:52 -08:00
+++ b/include/asm-s390/system.h	2005-03-11 12:51:52 -08:00
@@ -335,19 +335,23 @@
         __asm__ __volatile__("lpswe 0(%0)" : : "a" (&psw), "m" (psw) : "cc" );
 
 #define __ctl_load(array, low, high) ({ \
+	typedef struct { char _[sizeof(array)]; } addrtype; \
 	__asm__ __volatile__ ( \
 		"   bras  1,0f\n" \
                 "   lctlg 0,0,0(%0)\n" \
 		"0: ex    %1,0(1)" \
-		: : "a" (&array), "a" (((low)<<4)+(high)) : "1" ); \
+		: : "a" (&array), "a" (((low)<<4)+(high)), \
+		    "m" (*(addrtype *)(array)) : "1" ); \
 	})
 
 #define __ctl_store(array, low, high) ({ \
+	typedef struct { char _[sizeof(array)]; } addrtype; \
 	__asm__ __volatile__ ( \
 		"   bras  1,0f\n" \
 		"   stctg 0,0,0(%1)\n" \
 		"0: ex    %2,0(1)" \
-		: "=m" (array) : "a" (&array), "a" (((low)<<4)+(high)) : "1" ); \
+		: "=m" (*(addrtype *)(array)) \
+		: "a" (&array), "a" (((low)<<4)+(high)) : "1" ); \
 	})
 
 #define __ctl_set_bit(cr, bit) ({ \
@@ -390,19 +394,23 @@
 	__asm__ __volatile__("lpsw 0(%0)" : : "a" (&psw) : "cc" );
 
 #define __ctl_load(array, low, high) ({ \
+	typedef struct { char _[sizeof(array)]; } addrtype; \
 	__asm__ __volatile__ ( \
 		"   bras  1,0f\n" \
                 "   lctl 0,0,0(%0)\n" \
 		"0: ex    %1,0(1)" \
-		: : "a" (&array), "a" (((low)<<4)+(high)) : "1" ); \
+		: : "a" (&array), "a" (((low)<<4)+(high)), \
+		    "m" (*(addrtype *)(array)) : "1" ); \
 	})
 
 #define __ctl_store(array, low, high) ({ \
+	typedef struct { char _[sizeof(array)]; } addrtype; \
 	__asm__ __volatile__ ( \
 		"   bras  1,0f\n" \
 		"   stctl 0,0,0(%1)\n" \
 		"0: ex    %2,0(1)" \
-		: "=m" (array) : "a" (&array), "a" (((low)<<4)+(high)): "1" ); \
+		: "=m" (*(addrtype *)(array)) \
+		: "a" (&array), "a" (((low)<<4)+(high)): "1" ); \
 	})
 
 #define __ctl_set_bit(cr, bit) ({ \
@@ -460,6 +468,8 @@
 extern void (*_machine_restart)(char *command);
 extern void (*_machine_halt)(void);
 extern void (*_machine_power_off)(void);
+
+#define arch_align_stack(x) (x)
 
 #endif /* __KERNEL__ */
 
diff -Nru a/include/asm-s390/uaccess.h b/include/asm-s390/uaccess.h
--- a/include/asm-s390/uaccess.h	2005-03-11 12:51:41 -08:00
+++ b/include/asm-s390/uaccess.h	2005-03-11 12:51:41 -08:00
@@ -161,7 +161,7 @@
 		__put_user_asm(__x, ptr, __pu_err);		\
 		break;						\
 	default:						\
-		__pu_err = __put_user_bad();			\
+		__put_user_bad();				\
 		break;						\
 	 }							\
 	__pu_err;						\
@@ -182,7 +182,7 @@
 })
 
 
-extern int __put_user_bad(void);
+extern int __put_user_bad(void) __attribute__((noreturn));
 
 #if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ > 2)
 #define __get_user_asm(x, ptr, err) \
@@ -225,8 +225,7 @@
 		__get_user_asm(__x, ptr, __gu_err);		\
 		break;						\
 	default:						\
-		__x = 0;					\
-		__gu_err = __get_user_bad();			\
+		__get_user_bad();				\
 		break;						\
 	}							\
 	(x) = __x;						\
@@ -248,7 +247,7 @@
 	__get_user(x, ptr);					\
 })
 
-extern int __get_user_bad(void);
+extern int __get_user_bad(void) __attribute__((noreturn));
 
 #define __put_user_unaligned __put_user
 #define __get_user_unaligned __get_user
diff -Nru a/include/asm-s390/unistd.h b/include/asm-s390/unistd.h
--- a/include/asm-s390/unistd.h	2005-03-11 12:51:52 -08:00
+++ b/include/asm-s390/unistd.h	2005-03-11 12:51:52 -08:00
@@ -270,8 +270,11 @@
 #define __NR_mq_notify		275
 #define __NR_mq_getsetattr	276
 /* Number 277 is reserved for new sys_kexec_load */
+#define __NR_add_key		278
+#define __NR_request_key	279
+#define __NR_keyctl		280
 
-#define NR_syscalls 278
+#define NR_syscalls 281
 
 /* 
  * There are some system calls that are not present on 64 bit, some
@@ -597,6 +600,6 @@
  * What we want is __attribute__((weak,alias("sys_ni_syscall"))),
  * but it doesn't work on all toolchains, so we just do it by hand
  */
-#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall");
+#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall")
 
 #endif /* _ASM_S390_UNISTD_H_ */
diff -Nru a/include/asm-sh/bitops.h b/include/asm-sh/bitops.h
--- a/include/asm-sh/bitops.h	2005-03-11 12:51:40 -08:00
+++ b/include/asm-sh/bitops.h	2005-03-11 12:51:40 -08:00
@@ -262,9 +262,9 @@
 #define find_first_bit(addr, size) \
 	find_next_bit((addr), (size), 0)
 
-static __inline__ int find_next_zero_bit(void *addr, int size, int offset)
+static __inline__ int find_next_zero_bit(const unsigned long *addr, int size, int offset)
 {
-	unsigned long *p = ((unsigned long *) addr) + (offset >> 5);
+	const unsigned long *p = ((unsigned long *) addr) + (offset >> 5);
 	unsigned long result = offset & ~31UL;
 	unsigned long tmp;
 
@@ -325,7 +325,7 @@
  * bits is cleared.
  */
 
-static inline int sched_find_first_bit(unsigned long *b)
+static inline int sched_find_first_bit(const unsigned long *b)
 {
 	if (unlikely(b[0]))
 		return __ffs(b[0]);
diff -Nru a/include/asm-sh/bug.h b/include/asm-sh/bug.h
--- a/include/asm-sh/bug.h	2005-03-11 12:51:51 -08:00
+++ b/include/asm-sh/bug.h	2005-03-11 12:51:51 -08:00
@@ -8,7 +8,7 @@
  */
 #define BUG() do { \
 	printk("kernel BUG at %s:%d!\n", __FILE__, __LINE__); \
-	asm volatile("nop"); \
+	*(volatile int *)0 = 0; \
 } while (0)
 
 #define HAVE_ARCH_BUG
diff -Nru a/include/asm-sh/cacheflush.h b/include/asm-sh/cacheflush.h
--- a/include/asm-sh/cacheflush.h	2005-03-11 12:51:42 -08:00
+++ b/include/asm-sh/cacheflush.h	2005-03-11 12:51:42 -08:00
@@ -1,5 +1,6 @@
 #ifndef __ASM_SH_CACHEFLUSH_H
 #define __ASM_SH_CACHEFLUSH_H
+#ifdef __KERNEL__
 
 #include <asm/cpu/cacheflush.h>
 
@@ -15,15 +16,16 @@
 
 #define copy_to_user_page(vma, page, vaddr, dst, src, len) \
 	do {							\
-		flush_cache_page(vma, vaddr);			\
+		flush_cache_page(vma, vaddr, page_to_pfn(page));\
 		memcpy(dst, src, len);				\
 		flush_icache_user_range(vma, page, vaddr, len);	\
 	} while (0)
 
 #define copy_from_user_page(vma, page, vaddr, dst, src, len) \
 	do {							\
-		flush_cache_page(vma, vaddr);			\
+		flush_cache_page(vma, vaddr, page_to_pfn(page));\
 		memcpy(dst, src, len);				\
 	} while (0)
 
+#endif /* __KERNEL__ */
 #endif /* __ASM_SH_CACHEFLUSH_H */
diff -Nru a/include/asm-sh/cpu-sh2/cacheflush.h b/include/asm-sh/cpu-sh2/cacheflush.h
--- a/include/asm-sh/cpu-sh2/cacheflush.h	2005-03-11 12:51:52 -08:00
+++ b/include/asm-sh/cpu-sh2/cacheflush.h	2005-03-11 12:51:52 -08:00
@@ -15,7 +15,7 @@
  *
  *  - flush_cache_all() flushes entire cache
  *  - flush_cache_mm(mm) flushes the specified mm context's cache lines
- *  - flush_cache_page(mm, vmaddr) flushes a single page
+ *  - flush_cache_page(mm, vmaddr, pfn) flushes a single page
  *  - flush_cache_range(vma, start, end) flushes a range of pages
  *
  *  - flush_dcache_page(pg) flushes(wback&invalidates) a page for dcache
@@ -28,7 +28,7 @@
 #define flush_cache_all()			do { } while (0)
 #define flush_cache_mm(mm)			do { } while (0)
 #define flush_cache_range(vma, start, end)	do { } while (0)
-#define flush_cache_page(vma, vmaddr)		do { } while (0)
+#define flush_cache_page(vma, vmaddr, pfn)	do { } while (0)
 #define flush_dcache_page(page)			do { } while (0)
 #define flush_dcache_mmap_lock(mapping)		do { } while (0)
 #define flush_dcache_mmap_unlock(mapping)	do { } while (0)
diff -Nru a/include/asm-sh/cpu-sh3/cacheflush.h b/include/asm-sh/cpu-sh3/cacheflush.h
--- a/include/asm-sh/cpu-sh3/cacheflush.h	2005-03-11 12:51:42 -08:00
+++ b/include/asm-sh/cpu-sh3/cacheflush.h	2005-03-11 12:51:42 -08:00
@@ -15,7 +15,7 @@
  *
  *  - flush_cache_all() flushes entire cache
  *  - flush_cache_mm(mm) flushes the specified mm context's cache lines
- *  - flush_cache_page(mm, vmaddr) flushes a single page
+ *  - flush_cache_page(mm, vmaddr, pfn) flushes a single page
  *  - flush_cache_range(vma, start, end) flushes a range of pages
  *
  *  - flush_dcache_page(pg) flushes(wback&invalidates) a page for dcache
@@ -43,7 +43,7 @@
 extern void flush_cache_mm(struct mm_struct *mm);
 extern void flush_cache_range(struct vm_area_struct *vma, unsigned long start,
                               unsigned long end);
-extern void flush_cache_page(struct vm_area_struct *vma, unsigned long addr);
+extern void flush_cache_page(struct vm_area_struct *vma, unsigned long addr, unsigned long pfn);
 extern void flush_dcache_page(struct page *pg);
 extern void flush_icache_range(unsigned long start, unsigned long end);
 extern void flush_icache_page(struct vm_area_struct *vma, struct page *page);
@@ -68,7 +68,7 @@
 #define flush_cache_all()			do { } while (0)
 #define flush_cache_mm(mm)			do { } while (0)
 #define flush_cache_range(vma, start, end)	do { } while (0)
-#define flush_cache_page(vma, vmaddr)		do { } while (0)
+#define flush_cache_page(vma, vmaddr, pfn)	do { } while (0)
 #define flush_dcache_page(page)			do { } while (0)
 #define flush_dcache_mmap_lock(mapping)		do { } while (0)
 #define flush_dcache_mmap_unlock(mapping)	do { } while (0)
diff -Nru a/include/asm-sh/cpu-sh3/freq.h b/include/asm-sh/cpu-sh3/freq.h
--- a/include/asm-sh/cpu-sh3/freq.h	2005-03-11 12:51:51 -08:00
+++ b/include/asm-sh/cpu-sh3/freq.h	2005-03-11 12:51:51 -08:00
@@ -10,7 +10,11 @@
 #ifndef __ASM_CPU_SH3_FREQ_H
 #define __ASM_CPU_SH3_FREQ_H
 
+#if defined(CONFIG_CPU_SUBTYPE_SH7300)
+#define FRQCR			0xa415ff80
+#else
 #define FRQCR			0xffffff80
+#endif
 #define MIN_DIVISOR_NR		0
 #define MAX_DIVISOR_NR		4
 
diff -Nru a/include/asm-sh/cpu-sh3/timer.h b/include/asm-sh/cpu-sh3/timer.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-sh/cpu-sh3/timer.h	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,64 @@
+/*
+ * include/asm-sh/cpu-sh3/timer.h
+ *
+ * Copyright (C) 2004 Lineo Solutions, 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.
+ */
+#ifndef __ASM_CPU_SH3_TIMER_H
+#define __ASM_CPU_SH3_TIMER_H
+
+/*
+ * ---------------------------------------------------------------------------
+ * TMU Common definitions for SH3 processors
+ *	SH7706
+ *	SH7709S
+ *	SH7727
+ *	SH7729R
+ *	SH7710
+ *	SH7720
+ *	SH7300
+ * ---------------------------------------------------------------------------
+ */
+
+#if defined(CONFIG_CPU_SUBTYPE_SH7300) || defined(CONFIG_CPU_SUBTYPE_SH7710)
+#define TMU_TSTR	0xa412fe92	/* Byte access */
+
+#define TMU0_TCOR	0xa412fe94	/* Long access */
+#define TMU0_TCNT	0xa412fe98	/* Long access */
+#define TMU0_TCR	0xa412fe9c	/* Word access */
+
+#define TMU1_TCOR	0xa412fea0	/* Long access */
+#define TMU1_TCNT	0xa412fea4	/* Long access */
+#define TMU1_TCR	0xa412fea8	/* Word access */
+
+#define TMU2_TCOR	0xa412feac	/* Long access */
+#define TMU2_TCNT	0xa412feb0	/* Long access */
+#define TMU2_TCR	0xa412feb4	/* Word access */
+
+#else
+#if !defined(CONFIG_CPU_SUBTYPE_SH7727)
+#define TMU_TOCR	0xfffffe90	/* Byte access */
+#endif
+#define TMU_TSTR	0xfffffe92	/* Byte access */
+
+#define TMU0_TCOR	0xfffffe94	/* Long access */
+#define TMU0_TCNT	0xfffffe98	/* Long access */
+#define TMU0_TCR	0xfffffe9c	/* Word access */
+
+#define TMU1_TCOR	0xfffffea0	/* Long access */
+#define TMU1_TCNT	0xfffffea4	/* Long access */
+#define TMU1_TCR	0xfffffea8	/* Word access */
+
+#define TMU2_TCOR	0xfffffeac	/* Long access */
+#define TMU2_TCNT	0xfffffeb0	/* Long access */
+#define TMU2_TCR	0xfffffeb4	/* Word access */
+#if !defined(CONFIG_CPU_SUBTYPE_SH7727)
+#define TMU2_TCPR2	0xfffffeb8	/* Long access */
+#endif
+#endif
+
+#endif /* __ASM_CPU_SH3_TIMER_H */
+
diff -Nru a/include/asm-sh/cpu-sh4/cacheflush.h b/include/asm-sh/cpu-sh4/cacheflush.h
--- a/include/asm-sh/cpu-sh4/cacheflush.h	2005-03-11 12:51:42 -08:00
+++ b/include/asm-sh/cpu-sh4/cacheflush.h	2005-03-11 12:51:42 -08:00
@@ -28,7 +28,7 @@
 extern void flush_cache_mm(struct mm_struct *mm);
 extern void flush_cache_range(struct vm_area_struct *vma, unsigned long start,
 			      unsigned long end);
-extern void flush_cache_page(struct vm_area_struct *vma, unsigned long addr);
+extern void flush_cache_page(struct vm_area_struct *vma, unsigned long addr, unsigned long pfn);
 extern void flush_dcache_page(struct page *pg);
 
 #define flush_dcache_mmap_lock(mapping)		do { } while (0)
diff -Nru a/include/asm-sh/cpu-sh4/timer.h b/include/asm-sh/cpu-sh4/timer.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-sh/cpu-sh4/timer.h	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,51 @@
+/*
+ * include/asm-sh/cpu-sh4/timer.h
+ *
+ * Copyright (C) 2004 Lineo Solutions, 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.
+ */
+#ifndef __ASM_CPU_SH4_TIMER_H
+#define __ASM_CPU_SH4_TIMER_H
+
+/*
+ * ---------------------------------------------------------------------------
+ * TMU Common definitions for SH4 processors
+ *	SH7750S/SH7750R
+ *	SH7751/SH7751R
+ *	SH7760
+ * ---------------------------------------------------------------------------
+ */
+
+#if !defined(CONFIG_CPU_SUBTYPE_SH7760)
+#define TMU_TOCR        0xffd80000      /* Byte access */
+#endif
+#define TMU_TSTR        0xffd80004      /* Byte access */
+
+#define TMU0_TCOR       0xffd80008      /* Long access */
+#define TMU0_TCNT       0xffd8000c      /* Long access */
+#define TMU0_TCR        0xffd80010      /* Word access */
+
+#define TMU1_TCOR       0xffd80014      /* Long access */
+#define TMU1_TCNT       0xffd80018      /* Long access */
+#define TMU1_TCR        0xffd8001c      /* Word access */
+
+#define TMU2_TCOR       0xffd80020      /* Long access */
+#define TMU2_TCNT       0xffd80024      /* Long access */
+#define TMU2_TCR        0xffd80028      /* Word access */
+#define TMU2_TCPR	0xffd8002c	/* Long access */
+
+#if !defined(CONFIG_CPU_SUBTYPE_SH7760)
+#define TMU3_TCOR       0xfe100008      /* Long access */
+#define TMU3_TCNT       0xfe10000c      /* Long access */
+#define TMU3_TCR        0xfe100010      /* Word access */
+
+#define TMU4_TCOR       0xfe100014      /* Long access */
+#define TMU4_TCNT       0xfe100018      /* Long access */
+#define TMU4_TCR        0xfe10001c      /* Word access */
+#endif
+
+#endif /* __ASM_CPU_SH4_TIMER_H */
+
diff -Nru a/include/asm-sh/dma-mapping.h b/include/asm-sh/dma-mapping.h
--- a/include/asm-sh/dma-mapping.h	2005-03-11 12:51:52 -08:00
+++ b/include/asm-sh/dma-mapping.h	2005-03-11 12:51:52 -08:00
@@ -3,7 +3,6 @@
 
 #include <linux/config.h>
 #include <linux/mm.h>
-#include <linux/device.h>
 #include <asm/scatterlist.h>
 #include <asm/io.h>
 
diff -Nru a/include/asm-sh/hardirq.h b/include/asm-sh/hardirq.h
--- a/include/asm-sh/hardirq.h	2005-03-11 12:51:42 -08:00
+++ b/include/asm-sh/hardirq.h	2005-03-11 12:51:42 -08:00
@@ -12,15 +12,6 @@
 
 #include <linux/irq_cpustat.h>	/* Standard mappings for irq_cpustat_t above */
 
-#define HARDIRQ_BITS	8
-
-/*
- * The hardirq mask has to be large enough to have
- * space for potentially all IRQ sources in the system
- * nesting on a single CPU:
- */
-#if (1 << HARDIRQ_BITS) < NR_IRQS
-# error HARDIRQ_BITS is too low!
-#endif
+extern void ack_bad_irq(unsigned int irq);
 
 #endif /* __ASM_SH_HARDIRQ_H */
diff -Nru a/include/asm-sh/irq.h b/include/asm-sh/irq.h
--- a/include/asm-sh/irq.h	2005-03-11 12:51:41 -08:00
+++ b/include/asm-sh/irq.h	2005-03-11 12:51:41 -08:00
@@ -17,7 +17,8 @@
 
 #if defined(CONFIG_SH_HP600) || \
     defined(CONFIG_SH_RTS7751R2D) || \
-    defined(CONFIG_SH_HS7751RVOIP)
+    defined(CONFIG_SH_HS7751RVOIP) || \
+    defined(CONFIG_SH_SH03)
 #include <asm/mach/ide.h>
 #endif
 
diff -Nru a/include/asm-sh/mc146818rtc.h b/include/asm-sh/mc146818rtc.h
--- a/include/asm-sh/mc146818rtc.h	2005-03-11 12:51:51 -08:00
+++ b/include/asm-sh/mc146818rtc.h	2005-03-11 12:51:51 -08:00
@@ -16,6 +16,7 @@
 
 /* FIXME:RTC Interrupt feature is not implemented yet. */
 #undef  RTC_IRQ
+#define RTC_IRQ		0
 
 #if defined(CONFIG_CPU_SH3)
 #define RTC_PORT(n)		(R64CNT+(n)*2)
diff -Nru a/include/asm-sh/pgtable-2level.h b/include/asm-sh/pgtable-2level.h
--- a/include/asm-sh/pgtable-2level.h	2005-03-11 12:51:51 -08:00
+++ b/include/asm-sh/pgtable-2level.h	2005-03-11 12:51:51 -08:00
@@ -41,6 +41,8 @@
  * hook is made available.
  */
 #define set_pte(pteptr, pteval) (*(pteptr) = pteval)
+#define set_pte_at(mm,addr,ptep,pteval) set_pte(ptep,pteval)
+
 /*
  * (pmds are folded into pgds so this doesn't get actually called,
  * but the define is needed for a generic inline function.)
diff -Nru a/include/asm-sh/pgtable.h b/include/asm-sh/pgtable.h
--- a/include/asm-sh/pgtable.h	2005-03-11 12:51:52 -08:00
+++ b/include/asm-sh/pgtable.h	2005-03-11 12:51:52 -08:00
@@ -164,7 +164,7 @@
 
 #define pte_none(x)	(!pte_val(x))
 #define pte_present(x)	(pte_val(x) & (_PAGE_PRESENT | _PAGE_PROTNONE))
-#define pte_clear(xp)	do { set_pte(xp, __pte(0)); } while (0)
+#define pte_clear(mm,addr,xp)	do { set_pte_at(mm, addr, xp, __pte(0)); } while (0)
 
 #define pmd_none(x)	(!pmd_val(x))
 #define pmd_present(x)	(pmd_val(x) & _PAGE_PRESENT)
@@ -290,7 +290,7 @@
 
 #if defined(CONFIG_CPU_SH4) || defined(CONFIG_SH7705_CACHE_32KB)
 #define __HAVE_ARCH_PTEP_GET_AND_CLEAR
-extern pte_t ptep_get_and_clear(pte_t *ptep);
+extern pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep);
 #endif
 
 #include <asm-generic/pgtable.h>
diff -Nru a/include/asm-sh/sh03/ide.h b/include/asm-sh/sh03/ide.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/asm-sh/sh03/ide.h	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,7 @@
+#ifndef __ASM_SH_SH03_IDE_H
+#define __ASM_SH_SH03_IDE_H
+
+#define IRQ_CFCARD	8
+#define IRQ_PCMCIA	8
+
+#endif /* __ASM_SH_SH03_IDE_H */
diff -Nru a/include/asm-sh/system.h b/include/asm-sh/system.h
--- a/include/asm-sh/system.h	2005-03-11 12:51:51 -08:00
+++ b/include/asm-sh/system.h	2005-03-11 12:51:51 -08:00
@@ -259,4 +259,6 @@
 void disable_hlt(void);
 void enable_hlt(void);
 
+#define arch_align_stack(x) (x)
+
 #endif
diff -Nru a/include/asm-sh/unistd.h b/include/asm-sh/unistd.h
--- a/include/asm-sh/unistd.h	2005-03-11 12:51:51 -08:00
+++ b/include/asm-sh/unistd.h	2005-03-11 12:51:51 -08:00
@@ -517,7 +517,7 @@
  * but it doesn't work on all toolchains, so we just do it by hand
  */
 #ifndef cond_syscall
-#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall");
+#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall")
 #endif
 
 #endif /* __ASM_SH_UNISTD_H */
diff -Nru a/include/asm-sh64/bug.h b/include/asm-sh64/bug.h
--- a/include/asm-sh64/bug.h	2005-03-11 12:51:51 -08:00
+++ b/include/asm-sh64/bug.h	2005-03-11 12:51:51 -08:00
@@ -1,7 +1,32 @@
 #ifndef __ASM_SH64_BUG_H
 #define __ASM_SH64_BUG_H
 
-#include <asm-sh/bug.h>
+#include <linux/config.h>
+
+/*
+ * Tell the user there is some problem, then force a segfault (in process
+ * context) or a panic (interrupt context).
+ */
+#define BUG() do { \
+	printk("kernel BUG at %s:%d!\n", __FILE__, __LINE__); \
+	*(volatile int *)0 = 0; \
+} while (0)
+
+#define BUG_ON(condition) do { \
+	if (unlikely((condition)!=0)) \
+		BUG(); \
+} while(0)
+
+#define PAGE_BUG(page) do { \
+	BUG(); \
+} while (0)
+
+#define WARN_ON(condition) do { \
+	if (unlikely((condition)!=0)) { \
+		printk("Badness in %s at %s:%d\n", __FUNCTION__, __FILE__, __LINE__); \
+		dump_stack(); \
+	} \
+} while (0)
 
 #endif /* __ASM_SH64_BUG_H */
 
diff -Nru a/include/asm-sh64/cacheflush.h b/include/asm-sh64/cacheflush.h
--- a/include/asm-sh64/cacheflush.h	2005-03-11 12:51:42 -08:00
+++ b/include/asm-sh64/cacheflush.h	2005-03-11 12:51:42 -08:00
@@ -14,7 +14,7 @@
 extern void flush_cache_sigtramp(unsigned long start, unsigned long end);
 extern void flush_cache_range(struct vm_area_struct *vma, unsigned long start,
 			      unsigned long end);
-extern void flush_cache_page(struct vm_area_struct *vma, unsigned long addr);
+extern void flush_cache_page(struct vm_area_struct *vma, unsigned long addr, unsigned long pfn);
 extern void flush_dcache_page(struct page *pg);
 extern void flush_icache_range(unsigned long start, unsigned long end);
 extern void flush_icache_user_range(struct vm_area_struct *vma,
@@ -31,14 +31,14 @@
 
 #define copy_to_user_page(vma, page, vaddr, dst, src, len) \
 	do {							\
-		flush_cache_page(vma, vaddr);			\
+		flush_cache_page(vma, vaddr, page_to_pfn(page));\
 		memcpy(dst, src, len);				\
 		flush_icache_user_range(vma, page, vaddr, len);	\
 	} while (0)
 
 #define copy_from_user_page(vma, page, vaddr, dst, src, len) \
 	do {							\
-		flush_cache_page(vma, vaddr);			\
+		flush_cache_page(vma, vaddr, page_to_pfn(page));\
 		memcpy(dst, src, len);				\
 	} while (0)
 
diff -Nru a/include/asm-sh64/elf.h b/include/asm-sh64/elf.h
--- a/include/asm-sh64/elf.h	2005-03-11 12:51:47 -08:00
+++ b/include/asm-sh64/elf.h	2005-03-11 12:51:47 -08:00
@@ -53,6 +53,12 @@
 
 #define ELF_ET_DYN_BASE         (2 * TASK_SIZE / 3)
 
+#define	R_SH_DIR32		1
+#define	R_SH_REL32		2
+#define	R_SH_IMM_LOW16		246
+#define	R_SH_IMM_LOW16_PCREL	247
+#define	R_SH_IMM_MEDLOW16	248
+#define	R_SH_IMM_MEDLOW16_PCREL	249
 
 #define ELF_CORE_COPY_REGS(_dest,_regs)				\
 	memcpy((char *) &_dest, (char *) _regs,			\
diff -Nru a/include/asm-sh64/hardirq.h b/include/asm-sh64/hardirq.h
--- a/include/asm-sh64/hardirq.h	2005-03-11 12:51:51 -08:00
+++ b/include/asm-sh64/hardirq.h	2005-03-11 12:51:51 -08:00
@@ -1,7 +1,19 @@
 #ifndef __ASM_SH64_HARDIRQ_H
 #define __ASM_SH64_HARDIRQ_H
 
-#include <asm-sh/hardirq.h>
+#include <linux/config.h>
+#include <linux/threads.h>
+#include <linux/irq.h>
+
+/* entry.S is sensitive to the offsets of these fields */
+typedef struct {
+	unsigned int __softirq_pending;
+} ____cacheline_aligned irq_cpustat_t;
+
+#include <linux/irq_cpustat.h>	/* Standard mappings for irq_cpustat_t above */
+
+/* arch/sh64/kernel/irq.c */
+extern void ack_bad_irq(unsigned int irq);
 
 #endif /* __ASM_SH64_HARDIRQ_H */
 
diff -Nru a/include/asm-sh64/hardware.h b/include/asm-sh64/hardware.h
--- a/include/asm-sh64/hardware.h	2005-03-11 12:51:47 -08:00
+++ b/include/asm-sh64/hardware.h	2005-03-11 12:51:47 -08:00
@@ -17,29 +17,6 @@
 #define	PHYS_PERIPHERAL_BLOCK	0x09000000
 #define PHYS_DMAC_BLOCK		0x0e000000
 #define PHYS_PCI_BLOCK		0x60000000
-
-#ifndef __ASSEMBLY__
-#include <linux/types.h>
-#include <asm/io.h>
-
-struct vcr_info {
-	u8	perr_flags;	/* P-port Error flags */
-	u8	merr_flags;	/* Module Error flags */
-	u16	mod_vers;	/* Module Version */
-	u16	mod_id;		/* Module ID */
-	u8	bot_mb;		/* Bottom Memory block */
-	u8	top_mb;		/* Top Memory block */
-};
-
-static inline struct vcr_info sh64_get_vcr_info(unsigned long base)
-{
-	unsigned long long tmp;
-
-	tmp = sh64_in64(base);
-
-	return *((struct vcr_info *)&tmp);
-}
-
-#endif /* __ASSEMBLY__ */
+#define PHYS_EMI_BLOCK		0xff000000
 
 #endif /* __ASM_SH64_HARDWARE_H */
diff -Nru a/include/asm-sh64/ide.h b/include/asm-sh64/ide.h
--- a/include/asm-sh64/ide.h	2005-03-11 12:51:46 -08:00
+++ b/include/asm-sh64/ide.h	2005-03-11 12:51:46 -08:00
@@ -21,7 +21,12 @@
 #define MAX_HWIFS	CONFIG_IDE_MAX_HWIFS
 #endif
 
+/* Without this, the initialisation of PCI IDE cards end up calling
+ * ide_init_hwif_ports, which won't work. */
+#ifdef CONFIG_BLK_DEV_IDEPCI
+#define IDE_ARCH_OBSOLETE_INIT 1
 #define ide_default_io_ctl(base)	(0)
+#endif
 
 #include <asm-generic/ide_iops.h>
 
diff -Nru a/include/asm-sh64/io.h b/include/asm-sh64/io.h
--- a/include/asm-sh64/io.h	2005-03-11 12:51:42 -08:00
+++ b/include/asm-sh64/io.h	2005-03-11 12:51:42 -08:00
@@ -25,9 +25,11 @@
  * onchip_remap();
  */
 
+#include <linux/compiler.h>
 #include <asm/cache.h>
 #include <asm/system.h>
 #include <asm/page.h>
+#include <asm-generic/iomap.h>
 
 #define virt_to_bus virt_to_phys
 #define bus_to_virt phys_to_virt
@@ -39,75 +41,90 @@
  * with an implicit size. The traditional read{b,w,l}/write{b,w,l}
  * mess is wrapped to this, as are the SH-specific ctrl_in/out routines.
  */
-static inline unsigned char sh64_in8(unsigned long addr)
+static inline unsigned char sh64_in8(const volatile void __iomem *addr)
 {
-	return *(volatile unsigned char *)addr;
+	return *(volatile unsigned char __force *)addr;
 }
 
-static inline unsigned short sh64_in16(unsigned long addr)
+static inline unsigned short sh64_in16(const volatile void __iomem *addr)
 {
-	return *(volatile unsigned short *)addr;
+	return *(volatile unsigned short __force *)addr;
 }
 
-static inline unsigned long sh64_in32(unsigned long addr)
+static inline unsigned int sh64_in32(const volatile void __iomem *addr)
 {
-	return *(volatile unsigned long *)addr;
+	return *(volatile unsigned int __force *)addr;
 }
 
-static inline unsigned long long sh64_in64(unsigned long addr)
+static inline unsigned long long sh64_in64(const volatile void __iomem *addr)
 {
-	return *(volatile unsigned long long *)addr;
+	return *(volatile unsigned long long __force *)addr;
 }
 
-static inline void sh64_out8(unsigned char b, unsigned long addr)
+static inline void sh64_out8(unsigned char b, volatile void __iomem *addr)
 {
-	*(volatile unsigned char *)addr = b;
+	*(volatile unsigned char __force *)addr = b;
 	wmb();
 }
 
-static inline void sh64_out16(unsigned short b, unsigned long addr)
+static inline void sh64_out16(unsigned short b, volatile void __iomem *addr)
 {
-	*(volatile unsigned short *)addr = b;
+	*(volatile unsigned short __force *)addr = b;
 	wmb();
 }
 
-static inline void sh64_out32(unsigned long b, unsigned long addr)
+static inline void sh64_out32(unsigned int b, volatile void __iomem *addr)
 {
-	*(volatile unsigned long *)addr = b;
+	*(volatile unsigned int __force *)addr = b;
 	wmb();
 }
 
-static inline void sh64_out64(unsigned long long b, unsigned long addr)
+static inline void sh64_out64(unsigned long long b, volatile void __iomem *addr)
 {
-	*(volatile unsigned long long *)addr = b;
+	*(volatile unsigned long long __force *)addr = b;
 	wmb();
 }
 
 #define readb(addr)		sh64_in8(addr)
 #define readw(addr)		sh64_in16(addr)
 #define readl(addr)		sh64_in32(addr)
-#define readb_relaxed(addr)		sh64_in8(addr)
-#define readw_relaxed(addr)		sh64_in16(addr)
-#define readl_relaxed(addr)		sh64_in32(addr)
+#define readb_relaxed(addr)	sh64_in8(addr)
+#define readw_relaxed(addr)	sh64_in16(addr)
+#define readl_relaxed(addr)	sh64_in32(addr)
 
 #define writeb(b, addr)		sh64_out8(b, addr)
 #define writew(b, addr)		sh64_out16(b, addr)
 #define writel(b, addr)		sh64_out32(b, addr)
 
-#define ctrl_inb(addr)		sh64_in8(addr)
-#define ctrl_inw(addr)		sh64_in16(addr)
-#define ctrl_inl(addr)		sh64_in32(addr)
-
-#define ctrl_outb(b, addr)	sh64_out8(b, addr)
-#define ctrl_outw(b, addr)	sh64_out16(b, addr)
-#define ctrl_outl(b, addr)	sh64_out32(b, addr)
-
-unsigned long inb(unsigned long port);
-unsigned long inw(unsigned long port);
-unsigned long inl(unsigned long port);
-void outb(unsigned long value, unsigned long port);
-void outw(unsigned long value, unsigned long port);
-void outl(unsigned long value, unsigned long port);
+#define ctrl_inb(addr)		sh64_in8(ioport_map(addr, 1))
+#define ctrl_inw(addr)		sh64_in16(ioport_map(addr, 2))
+#define ctrl_inl(addr)		sh64_in32(ioport_map(addr, 4))
+
+#define ctrl_outb(b, addr)	sh64_out8(b, ioport_map(addr, 1))
+#define ctrl_outw(b, addr)	sh64_out16(b, ioport_map(addr, 2))
+#define ctrl_outl(b, addr)	sh64_out32(b, ioport_map(addr, 4))
+
+#define ioread8(addr)		sh64_in8(addr)
+#define ioread16(addr)		sh64_in16(addr)
+#define ioread32(addr)		sh64_in32(addr)
+#define iowrite8(b, addr)	sh64_out8(b, addr)
+#define iowrite16(b, addr)	sh64_out16(b, addr)
+#define iowrite32(b, addr)	sh64_out32(b, addr)
+
+#define inb(addr)		ctrl_inb(addr)
+#define inw(addr)		ctrl_inw(addr)
+#define inl(addr)		ctrl_inl(addr)
+#define outb(b, addr)		ctrl_outb(b, addr)
+#define outw(b, addr)		ctrl_outw(b, addr)
+#define outl(b, addr)		ctrl_outl(b, addr)
+
+void outsw(unsigned long port, const void *addr, unsigned long count);
+void insw(unsigned long port, void *addr, unsigned long count);
+void outsl(unsigned long port, const void *addr, unsigned long count);
+void insl(unsigned long port, void *addr, unsigned long count);
+
+void memcpy_toio(void __iomem *to, const void *from, long count);
+void memcpy_fromio(void *to, void __iomem *from, long count);
 
 #define mmiowb()
 
@@ -154,7 +171,7 @@
 unsigned long onchip_remap(unsigned long addr, unsigned long size, const char* name);
 extern void onchip_unmap(unsigned long vaddr);
 
-static __inline__ int check_signature(unsigned long io_addr,
+static __inline__ int check_signature(volatile void __iomem *io_addr,
 			const unsigned char *signature, int length)
 {
 	int retval = 0;
diff -Nru a/include/asm-sh64/ioctls.h b/include/asm-sh64/ioctls.h
--- a/include/asm-sh64/ioctls.h	2005-03-11 12:51:46 -08:00
+++ b/include/asm-sh64/ioctls.h	2005-03-11 12:51:46 -08:00
@@ -9,103 +9,108 @@
  * include/asm-sh64/ioctls.h
  *
  * Copyright (C) 2000, 2001  Paolo Alberelli
+ * Copyright (C) 2004  Richard Curnow
  *
  */
 
 #include <asm/ioctl.h>
 
-#define FIOCLEX		_IO('f', 1)
-#define FIONCLEX	_IO('f', 2)
-#define FIOASYNC	_IOW('f', 125, int)
-#define FIONBIO		_IOW('f', 126, int)
-#define FIONREAD	_IOR('f', 127, int)
+#define FIOCLEX		0x6601		/* _IO('f', 1) */
+#define FIONCLEX	0x6602		/* _IO('f', 2) */
+#define FIOASYNC	0x4004667d	/* _IOW('f', 125, int) */
+#define FIONBIO		0x4004667e	/* _IOW('f', 126, int) */
+#define FIONREAD	0x8004667f	/* _IOW('f', 127, int) */
 #define TIOCINQ		FIONREAD
-#define FIOQSIZE	_IOR('f', 128, loff_t)
+#define FIOQSIZE	0x80086680	/* _IOR('f', 128, loff_t) */
 
 #define TCGETS		0x5401
 #define TCSETS		0x5402
 #define TCSETSW		0x5403
 #define TCSETSF		0x5404
 
-#define TCGETA		_IOR('t', 23, struct termio)
-#define TCSETA		_IOW('t', 24, struct termio)
-#define TCSETAW		_IOW('t', 25, struct termio)
-#define TCSETAF		_IOW('t', 28, struct termio)
-
-#define TCSBRK		_IO('t', 29)
-#define TCXONC		_IO('t', 30)
-#define TCFLSH		_IO('t', 31)
-
-#define TIOCSWINSZ	_IOW('t', 103, struct winsize)
-#define TIOCGWINSZ	_IOR('t', 104, struct winsize)
-#define	TIOCSTART	_IO('t', 110)		/* start output, like ^Q */
-#define	TIOCSTOP	_IO('t', 111)		/* stop output, like ^S */
-#define TIOCOUTQ        _IOR('t', 115, int)     /* output queue size */
-
-#define TIOCSPGRP	_IOW('t', 118, int)
-#define TIOCGPGRP	_IOR('t', 119, int)
-
-#define TIOCEXCL	_IO('T', 12) /* 0x540C */
-#define TIOCNXCL	_IO('T', 13) /* 0x540D */
-#define TIOCSCTTY	_IO('T', 14) /* 0x540E */
-
-#define TIOCSTI		_IOW('T', 18, char) /* 0x5412 */
-#define TIOCMGET	_IOR('T', 21, unsigned int) /* 0x5415 */
-#define TIOCMBIS	_IOW('T', 22, unsigned int) /* 0x5416 */
-#define TIOCMBIC	_IOW('T', 23, unsigned int) /* 0x5417 */
-#define TIOCMSET	_IOW('T', 24, unsigned int) /* 0x5418 */
-# define TIOCM_LE	0x001
-# define TIOCM_DTR	0x002
-# define TIOCM_RTS	0x004
-# define TIOCM_ST	0x008
-# define TIOCM_SR	0x010
-# define TIOCM_CTS	0x020
-# define TIOCM_CAR	0x040
-# define TIOCM_RNG	0x080
-# define TIOCM_DSR	0x100
-# define TIOCM_CD	TIOCM_CAR
-# define TIOCM_RI	TIOCM_RNG
-
-#define TIOCGSOFTCAR	_IOR('T', 25, unsigned int) /* 0x5419 */
-#define TIOCSSOFTCAR	_IOW('T', 26, unsigned int) /* 0x541A */
-#define TIOCLINUX	_IOW('T', 28, char) /* 0x541C */
-#define TIOCCONS	_IO('T', 29) /* 0x541D */
-#define TIOCGSERIAL	_IOR('T', 30, struct serial_struct) /* 0x541E */
-#define TIOCSSERIAL	_IOW('T', 31, struct serial_struct) /* 0x541F */
-#define TIOCPKT		_IOW('T', 32, int) /* 0x5420 */
-# define TIOCPKT_DATA		 0
-# define TIOCPKT_FLUSHREAD	 1
-# define TIOCPKT_FLUSHWRITE	 2
-# define TIOCPKT_STOP		 4
-# define TIOCPKT_START		 8
-# define TIOCPKT_NOSTOP		16
-# define TIOCPKT_DOSTOP		32
-
-
-#define TIOCNOTTY	_IO('T', 34) /* 0x5422 */
-#define TIOCSETD	_IOW('T', 35, int) /* 0x5423 */
-#define TIOCGETD	_IOR('T', 36, int) /* 0x5424 */
-#define TCSBRKP		_IOW('T', 37, int) /* 0x5425 */	/* Needed for POSIX tcsendbreak() */
-#define TIOCTTYGSTRUCT	_IOR('T', 38, struct tty_struct) /* 0x5426 */ /* For debugging only */
-#define TIOCSBRK	_IO('T', 39) /* 0x5427 */ /* BSD compatibility */
-#define TIOCCBRK	_IO('T', 40) /* 0x5428 */ /* BSD compatibility */
-#define TIOCGSID	_IOR('T', 41, pid_t) /* 0x5429 */ /* Return the session ID of FD */
-#define TIOCGPTN	_IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
-#define TIOCSPTLCK	_IOW('T',0x31, int)  /* Lock/unlock Pty */
-
-#define TIOCSERCONFIG	_IO('T', 83) /* 0x5453 */
-#define TIOCSERGWILD	_IOR('T', 84,  int) /* 0x5454 */
-#define TIOCSERSWILD	_IOW('T', 85,  int) /* 0x5455 */
+#define TCGETA		0x80127417	/* _IOR('t', 23, struct termio) */
+#define TCSETA		0x40127418	/* _IOW('t', 24, struct termio) */
+#define TCSETAW		0x40127419	/* _IOW('t', 25, struct termio) */
+#define TCSETAF		0x4012741c	/* _IOW('t', 28, struct termio) */
+
+#define TCSBRK		0x741d		/* _IO('t', 29) */
+#define TCXONC		0x741e		/* _IO('t', 30) */
+#define TCFLSH		0x741f		/* _IO('t', 31) */
+
+#define TIOCSWINSZ	0x40087467	/* _IOW('t', 103, struct winsize) */
+#define TIOCGWINSZ	0x80087468	/* _IOR('t', 104, struct winsize) */
+#define	TIOCSTART	0x746e		/* _IO('t', 110)  start output, like ^Q */
+#define	TIOCSTOP	0x746f		/* _IO('t', 111)  stop output, like ^S */
+#define TIOCOUTQ        0x80047473	/* _IOR('t', 115, int) output queue size */
+
+#define TIOCSPGRP	0x40047476	/* _IOW('t', 118, int) */
+#define TIOCGPGRP	0x80047477	/* _IOR('t', 119, int) */
+
+#define TIOCEXCL	0x540c		/* _IO('T', 12) */
+#define TIOCNXCL	0x540d		/* _IO('T', 13) */
+#define TIOCSCTTY	0x540e		/* _IO('T', 14) */
+
+#define TIOCSTI		0x40015412	/* _IOW('T', 18, char) 0x5412 */
+#define TIOCMGET	0x80045415	/* _IOR('T', 21, unsigned int) 0x5415 */
+#define TIOCMBIS	0x40045416	/* _IOW('T', 22, unsigned int) 0x5416 */
+#define TIOCMBIC	0x40045417	/* _IOW('T', 23, unsigned int) 0x5417 */
+#define TIOCMSET	0x40045418	/* _IOW('T', 24, unsigned int) 0x5418 */
+
+#define TIOCM_LE	0x001
+#define TIOCM_DTR	0x002
+#define TIOCM_RTS	0x004
+#define TIOCM_ST	0x008
+#define TIOCM_SR	0x010
+#define TIOCM_CTS	0x020
+#define TIOCM_CAR	0x040
+#define TIOCM_RNG	0x080
+#define TIOCM_DSR	0x100
+#define TIOCM_CD	TIOCM_CAR
+#define TIOCM_RI	TIOCM_RNG
+
+#define TIOCGSOFTCAR	0x80045419	/* _IOR('T', 25, unsigned int) 0x5419 */
+#define TIOCSSOFTCAR	0x4004541a	/* _IOW('T', 26, unsigned int) 0x541A */
+#define TIOCLINUX	0x4004541c	/* _IOW('T', 28, char) 0x541C */
+#define TIOCCONS	0x541d		/* _IO('T', 29) */
+#define TIOCGSERIAL	0x803c541e	/* _IOR('T', 30, struct serial_struct) 0x541E */
+#define TIOCSSERIAL	0x403c541f	/* _IOW('T', 31, struct serial_struct) 0x541F */
+#define TIOCPKT		0x40045420	/* _IOW('T', 32, int) 0x5420 */
+
+#define TIOCPKT_DATA		 0
+#define TIOCPKT_FLUSHREAD	 1
+#define TIOCPKT_FLUSHWRITE	 2
+#define TIOCPKT_STOP		 4
+#define TIOCPKT_START		 8
+#define TIOCPKT_NOSTOP		16
+#define TIOCPKT_DOSTOP		32
+
+
+#define TIOCNOTTY	0x5422		/* _IO('T', 34) */
+#define TIOCSETD	0x40045423	/* _IOW('T', 35, int) 0x5423 */
+#define TIOCGETD	0x80045424	/* _IOR('T', 36, int) 0x5424 */
+#define TCSBRKP		0x40045424	/* _IOW('T', 37, int) 0x5425 */	/* Needed for POSIX tcsendbreak() */
+#define TIOCTTYGSTRUCT	0x8c105426	/* _IOR('T', 38, struct tty_struct) 0x5426 */ /* For debugging only */
+#define TIOCSBRK	0x5427		/* _IO('T', 39) */ /* BSD compatibility */
+#define TIOCCBRK	0x5428		/* _IO('T', 40) */ /* BSD compatibility */
+#define TIOCGSID	0x80045429	/* _IOR('T', 41, pid_t) 0x5429 */ /* Return the session ID of FD */
+#define TIOCGPTN	0x80045430	/* _IOR('T',0x30, unsigned int) 0x5430 Get Pty Number (of pty-mux device) */
+#define TIOCSPTLCK	0x40045431	/* _IOW('T',0x31, int) Lock/unlock Pty */
+
+#define TIOCSERCONFIG	0x5453		/* _IO('T', 83) */
+#define TIOCSERGWILD	0x80045454	/* _IOR('T', 84,  int) 0x5454 */
+#define TIOCSERSWILD	0x40045455	/* _IOW('T', 85,  int) 0x5455 */
 #define TIOCGLCKTRMIOS	0x5456
 #define TIOCSLCKTRMIOS	0x5457
-#define TIOCSERGSTRUCT	_IOR('T', 88, struct async_struct) /* 0x5458 */ /* For debugging only */
-#define TIOCSERGETLSR   _IOR('T', 89, unsigned int) /* 0x5459 */ /* Get line status register */
-  /* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */
-# define TIOCSER_TEMT    0x01	/* Transmitter physically empty */
-#define TIOCSERGETMULTI _IOR('T', 90, struct serial_multiport_struct) /* 0x545A */ /* Get multiport config  */
-#define TIOCSERSETMULTI _IOW('T', 91, struct serial_multiport_struct) /* 0x545B */ /* Set multiport config */
+#define TIOCSERGSTRUCT	0x80d85458	/* _IOR('T', 88, struct async_struct) 0x5458 */ /* For debugging only */
+#define TIOCSERGETLSR   0x80045459	/* _IOR('T', 89, unsigned int) 0x5459 */ /* Get line status register */
 
-#define TIOCMIWAIT	_IO('T', 92) /* 0x545C */	/* wait for a change on serial input line(s) */
-#define TIOCGICOUNT	_IOR('T', 93, struct async_icount) /* 0x545D */	/* read serial port inline interrupt counts */
+/* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */
+#define TIOCSER_TEMT    0x01	/* Transmitter physically empty */
+
+#define TIOCSERGETMULTI 0x80a8545a	/* _IOR('T', 90, struct serial_multiport_struct) 0x545A */ /* Get multiport config  */
+#define TIOCSERSETMULTI 0x40a8545b	/* _IOW('T', 91, struct serial_multiport_struct) 0x545B */ /* Set multiport config */
+
+#define TIOCMIWAIT	0x545c		/* _IO('T', 92) wait for a change on serial input line(s) */
+#define TIOCGICOUNT	0x802c545d	/* _IOR('T', 93, struct async_icount) 0x545D */	/* read serial port inline interrupt counts */
 
 #endif /* __ASM_SH64_IOCTLS_H */
diff -Nru a/include/asm-sh64/irq.h b/include/asm-sh64/irq.h
--- a/include/asm-sh64/irq.h	2005-03-11 12:51:41 -08:00
+++ b/include/asm-sh64/irq.h	2005-03-11 12:51:41 -08:00
@@ -83,10 +83,11 @@
 #define IRQ_P2INTC      (START_EXT_IRQS + (3*8) + 2)
 #define IRQ_P2INTD      (START_EXT_IRQS + (3*8) + 3)
 
-#define START_EXT_IRQS  64
-
 #define I8042_KBD_IRQ	(START_EXT_IRQS + 2)
 #define I8042_AUX_IRQ	(START_EXT_IRQS + 6)
+
+#define IRQ_CFCARD	(START_EXT_IRQS + 7)
+#define IRQ_PCMCIA	(0)
 
 #else
 #define NR_EXT_IRQS	0
diff -Nru a/include/asm-sh64/module.h b/include/asm-sh64/module.h
--- a/include/asm-sh64/module.h	2005-03-11 12:51:51 -08:00
+++ b/include/asm-sh64/module.h	2005-03-11 12:51:51 -08:00
@@ -4,6 +4,14 @@
  * This file contains the SH architecture specific module code.
  */
 
+struct mod_arch_specific {
+	/* empty */
+};
+
+#define Elf_Shdr		Elf32_Shdr
+#define Elf_Sym			Elf32_Sym
+#define Elf_Ehdr		Elf32_Ehdr
+
 #define module_map(x)		vmalloc(x)
 #define module_unmap(x)		vfree(x)
 #define module_arch_init(x)	(0)
diff -Nru a/include/asm-sh64/pgtable.h b/include/asm-sh64/pgtable.h
--- a/include/asm-sh64/pgtable.h	2005-03-11 12:51:47 -08:00
+++ b/include/asm-sh64/pgtable.h	2005-03-11 12:51:47 -08:00
@@ -136,6 +136,7 @@
 	 */
 	*(xp) = (x & NPHYS_SIGN) ? (x | NPHYS_MASK) : x;
 }
+#define set_pte_at(mm,addr,ptep,pteval) set_pte(ptep,pteval)
 
 static __inline__ void pmd_set(pmd_t *pmdp,pte_t *ptep)
 {
@@ -280,8 +281,6 @@
 
 /* Mask which drops software flags */
 #define _PAGE_FLAGS_HARDWARE_MASK	0xfffffffffffff3dbLL
-/* Flags default: 4KB, Read, Not write, Not execute, Not user */
-#define _PAGE_FLAGS_HARDWARE_DEFAULT	0x0000000000000040LL
 
 /*
  * HugeTLB support
@@ -383,7 +382,7 @@
  */
 #define _PTE_EMPTY	0x0
 #define pte_present(x)	(pte_val(x) & _PAGE_PRESENT)
-#define pte_clear(xp)	(set_pte(xp, __pte(_PTE_EMPTY)))
+#define pte_clear(mm,addr,xp)	(set_pte_at(mm, addr, xp, __pte(_PTE_EMPTY)))
 #define pte_none(x)	(pte_val(x) == _PTE_EMPTY)
 
 /*
diff -Nru a/include/asm-sh64/system.h b/include/asm-sh64/system.h
--- a/include/asm-sh64/system.h	2005-03-11 12:51:47 -08:00
+++ b/include/asm-sh64/system.h	2005-03-11 12:51:47 -08:00
@@ -15,7 +15,6 @@
  */
 
 #include <linux/config.h>
-#include <linux/kernel.h>
 #include <asm/registers.h>
 #include <asm/processor.h>
 
@@ -190,5 +189,7 @@
 #endif	/* CONFIG_SH_ALPHANUMERIC */
 
 #define PL() printk("@ <%s,%s:%d>\n",__FILE__,__FUNCTION__,__LINE__)
+
+#define arch_align_stack(x) (x)
 
 #endif /* __ASM_SH64_SYSTEM_H */
diff -Nru a/include/asm-sh64/thread_info.h b/include/asm-sh64/thread_info.h
--- a/include/asm-sh64/thread_info.h	2005-03-11 12:51:42 -08:00
+++ b/include/asm-sh64/thread_info.h	2005-03-11 12:51:42 -08:00
@@ -61,13 +61,18 @@
 }
 
 /* thread information allocation */
-#define alloc_thread_info(ti) ((struct thread_info *) __get_free_pages(GFP_KERNEL,2))
+
+
+
+#define alloc_thread_info(ti) ((struct thread_info *) __get_free_pages(GFP_KERNEL,1))
 #define free_thread_info(ti) free_pages((unsigned long) (ti), 1)
 #define get_thread_info(ti) get_task_struct((ti)->task)
 #define put_thread_info(ti) put_task_struct((ti)->task)
 
 #endif /* __ASSEMBLY__ */
 
+#define THREAD_SIZE  8192
+
 #define PREEMPT_ACTIVE		0x4000000
 
 /* thread information flags */
@@ -76,7 +81,6 @@
 #define TIF_NEED_RESCHED	3	/* rescheduling necessary */
 #define TIF_MEMDIE		4
 
-#define THREAD_SIZE	16384
 
 #endif /* __KERNEL__ */
 
diff -Nru a/include/asm-sh64/uaccess.h b/include/asm-sh64/uaccess.h
--- a/include/asm-sh64/uaccess.h	2005-03-11 12:51:42 -08:00
+++ b/include/asm-sh64/uaccess.h	2005-03-11 12:51:42 -08:00
@@ -313,6 +313,12 @@
    sh64 at the moment). */
 #define ARCH_KMALLOC_MINALIGN 8
 
+/*
+ * We want 8-byte alignment for the slab caches as well, otherwise we have
+ * the same BYTES_PER_WORD (sizeof(void *)) min align in kmem_cache_create().
+ */
+#define ARCH_SLAB_MINALIGN 8
+
 /* Returns 0 if exception not found and fixup.unit otherwise.  */
 extern unsigned long search_exception_table(unsigned long addr);
 extern const struct exception_table_entry *search_exception_tables (unsigned long addr);
diff -Nru a/include/asm-sh64/unistd.h b/include/asm-sh64/unistd.h
--- a/include/asm-sh64/unistd.h	2005-03-11 12:51:40 -08:00
+++ b/include/asm-sh64/unistd.h	2005-03-11 12:51:40 -08:00
@@ -333,8 +333,13 @@
 #define __NR_mq_timedreceive    (__NR_mq_open+3)
 #define __NR_mq_notify          (__NR_mq_open+4)
 #define __NR_mq_getsetattr      (__NR_mq_open+5)
+#define __NR_sys_kexec_load	311
+#define __NR_waitid		312
+#define __NR_add_key		313
+#define __NR_request_key	314
+#define __NR_keyctl		315
 
-#define NR_syscalls 311
+#define NR_syscalls 316
 
 /* user-visible error numbers are in the range -1 - -125: see <asm-sh64/errno.h> */
 
@@ -549,7 +554,7 @@
  * but it doesn't work on all toolchains, so we just do it by hand
  */
 #ifndef cond_syscall
-#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall");
+#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall")
 #endif
 
 #endif /* __ASM_SH64_UNISTD_H */
diff -Nru a/include/asm-sparc/cacheflush.h b/include/asm-sparc/cacheflush.h
--- a/include/asm-sparc/cacheflush.h	2005-03-11 12:51:42 -08:00
+++ b/include/asm-sparc/cacheflush.h	2005-03-11 12:51:42 -08:00
@@ -50,21 +50,21 @@
 #define flush_cache_all() BTFIXUP_CALL(flush_cache_all)()
 #define flush_cache_mm(mm) BTFIXUP_CALL(flush_cache_mm)(mm)
 #define flush_cache_range(vma,start,end) BTFIXUP_CALL(flush_cache_range)(vma,start,end)
-#define flush_cache_page(vma,addr) BTFIXUP_CALL(flush_cache_page)(vma,addr)
+#define flush_cache_page(vma,addr,pfn) BTFIXUP_CALL(flush_cache_page)(vma,addr)
 #define flush_icache_range(start, end)		do { } while (0)
 #define flush_icache_page(vma, pg)		do { } while (0)
 
 #define flush_icache_user_range(vma,pg,adr,len)	do { } while (0)
 
 #define copy_to_user_page(vma, page, vaddr, dst, src, len) \
-	do {					\
-		flush_cache_page(vma, vaddr);	\
-		memcpy(dst, src, len);		\
+	do {							\
+		flush_cache_page(vma, vaddr, page_to_pfn(page));\
+		memcpy(dst, src, len);				\
 	} while (0)
 #define copy_from_user_page(vma, page, vaddr, dst, src, len) \
-	do {					\
-		flush_cache_page(vma, vaddr);	\
-		memcpy(dst, src, len);		\
+	do {							\
+		flush_cache_page(vma, vaddr, page_to_pfn(page));\
+		memcpy(dst, src, len);				\
 	} while (0)
 
 BTFIXUPDEF_CALL(void, __flush_page_to_ram, unsigned long)
diff -Nru a/include/asm-sparc/mostek.h b/include/asm-sparc/mostek.h
--- a/include/asm-sparc/mostek.h	2005-03-11 12:51:51 -08:00
+++ b/include/asm-sparc/mostek.h	2005-03-11 12:51:51 -08:00
@@ -128,7 +128,6 @@
 	char offset[6*1024];         /* Magic things may be here, who knows? */
 	struct mostek48t02 regs;     /* Here is what we are interested in.   */
 };
-extern struct mostek48t08 *mstk48t08_regs;
 
 extern enum sparc_clock_type sp_clock_typ;
 
diff -Nru a/include/asm-sparc/pgtable.h b/include/asm-sparc/pgtable.h
--- a/include/asm-sparc/pgtable.h	2005-03-11 12:51:46 -08:00
+++ b/include/asm-sparc/pgtable.h	2005-03-11 12:51:46 -08:00
@@ -157,7 +157,7 @@
 }
 
 #define pte_present(pte) BTFIXUP_CALL(pte_present)(pte)
-#define pte_clear(pte) BTFIXUP_CALL(pte_clear)(pte)
+#define pte_clear(mm,addr,pte) BTFIXUP_CALL(pte_clear)(pte)
 
 BTFIXUPDEF_CALL_CONST(int, pmd_bad, pmd_t)
 BTFIXUPDEF_CALL_CONST(int, pmd_present, pmd_t)
@@ -339,6 +339,7 @@
 BTFIXUPDEF_CALL(void, set_pte, pte_t *, pte_t)
 
 #define set_pte(ptep,pteval) BTFIXUP_CALL(set_pte)(ptep,pteval)
+#define set_pte_at(mm,addr,ptep,pteval) set_pte(ptep,pteval)
 
 struct seq_file;
 BTFIXUPDEF_CALL(void, mmu_info, struct seq_file *)
diff -Nru a/include/asm-sparc/resource.h b/include/asm-sparc/resource.h
--- a/include/asm-sparc/resource.h	2005-03-11 12:51:41 -08:00
+++ b/include/asm-sparc/resource.h	2005-03-11 12:51:41 -08:00
@@ -8,32 +8,18 @@
 #define _SPARC_RESOURCE_H
 
 /*
- * Resource limits
+ * These two resource limit IDs have a Sparc/Linux-specific ordering,
+ * the rest comes from the generic header:
  */
-
-#define RLIMIT_CPU	0		/* CPU time in ms */
-#define RLIMIT_FSIZE	1		/* Maximum filesize */
-#define RLIMIT_DATA	2		/* max data size */
-#define RLIMIT_STACK	3		/* max stack size */
-#define RLIMIT_CORE	4		/* max core file size */
-#define RLIMIT_RSS	5		/* max resident set size */
-#define RLIMIT_NOFILE	6		/* max number of open files */
-#define RLIMIT_NPROC	7		/* max number of processes */
-#define RLIMIT_MEMLOCK	8		/* max locked-in-memory address space */
-#define RLIMIT_AS	9		/* address space limit */
-#define RLIMIT_LOCKS	10		/* maximum file locks held */
-#define RLIMIT_SIGPENDING 11		/* max number of pending signals */
-#define RLIMIT_MSGQUEUE 12		/* maximum bytes in POSIX mqueues */
-
-#define RLIM_NLIMITS	13
-#define __ARCH_RLIMIT_ORDER
+#define RLIMIT_NOFILE		6	/* max number of open files */
+#define RLIMIT_NPROC		7	/* max number of processes */
 
 /*
  * SuS says limits have to be unsigned.
  * We make this unsigned, but keep the
- * old value.
+ * old value for compatibility:
  */
-#define RLIM_INFINITY	0x7fffffff
+#define RLIM_INFINITY		0x7fffffff
 
 #include <asm-generic/resource.h>
 
diff -Nru a/include/asm-sparc/system.h b/include/asm-sparc/system.h
--- a/include/asm-sparc/system.h	2005-03-11 12:51:47 -08:00
+++ b/include/asm-sparc/system.h	2005-03-11 12:51:47 -08:00
@@ -257,4 +257,6 @@
 
 #endif /* __ASSEMBLY__ */
 
+#define arch_align_stack(x) (x)
+
 #endif /* !(__SPARC_SYSTEM_H) */
diff -Nru a/include/asm-sparc/unistd.h b/include/asm-sparc/unistd.h
--- a/include/asm-sparc/unistd.h	2005-03-11 12:51:41 -08:00
+++ b/include/asm-sparc/unistd.h	2005-03-11 12:51:41 -08:00
@@ -513,6 +513,6 @@
  * What we want is __attribute__((weak,alias("sys_ni_syscall"))),
  * but it doesn't work on all toolchains, so we just do it by hand
  */
-#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall");
+#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall")
 
 #endif /* _SPARC_UNISTD_H */
diff -Nru a/include/asm-sparc64/cacheflush.h b/include/asm-sparc64/cacheflush.h
--- a/include/asm-sparc64/cacheflush.h	2005-03-11 12:51:51 -08:00
+++ b/include/asm-sparc64/cacheflush.h	2005-03-11 12:51:51 -08:00
@@ -11,7 +11,7 @@
 	do { if ((__mm) == current->mm) flushw_user(); } while(0)
 #define flush_cache_range(vma, start, end) \
 	flush_cache_mm((vma)->vm_mm)
-#define flush_cache_page(vma, page) \
+#define flush_cache_page(vma, page, pfn) \
 	flush_cache_mm((vma)->vm_mm)
 
 /* 
@@ -38,15 +38,15 @@
 #define flush_icache_user_range(vma,pg,adr,len)	do { } while (0)
 
 #define copy_to_user_page(vma, page, vaddr, dst, src, len) \
-	do {					\
-		flush_cache_page(vma, vaddr);	\
-		memcpy(dst, src, len);		\
+	do {							\
+		flush_cache_page(vma, vaddr, page_to_pfn(page));\
+		memcpy(dst, src, len);				\
 	} while (0)
 
 #define copy_from_user_page(vma, page, vaddr, dst, src, len) \
-	do {					\
-		flush_cache_page(vma, vaddr);	\
-		memcpy(dst, src, len);		\
+	do {							\
+		flush_cache_page(vma, vaddr, page_to_pfn(page));\
+		memcpy(dst, src, len);				\
 	} while (0)
 
 extern void flush_dcache_page(struct page *page);
diff -Nru a/include/asm-sparc64/mostek.h b/include/asm-sparc64/mostek.h
--- a/include/asm-sparc64/mostek.h	2005-03-11 12:51:47 -08:00
+++ b/include/asm-sparc64/mostek.h	2005-03-11 12:51:47 -08:00
@@ -134,13 +134,11 @@
  */
 #define MOSTEK_48T08_OFFSET	0x0000UL	/* Lower NVRAM portions */
 #define MOSTEK_48T08_48T02	0x1800UL	/* Offset to 48T02 chip */
-extern unsigned long mstk48t08_regs;
 
 /* SUN5 systems usually have 48t59 model clock chipsets.  But we keep the older
  * clock chip definitions around just in case.
  */
 #define MOSTEK_48T59_OFFSET	0x0000UL	/* Lower NVRAM portions */
 #define MOSTEK_48T59_48T02	0x1800UL	/* Offset to 48T02 chip */
-extern unsigned long mstk48t59_regs;
 
 #endif /* !(_SPARC64_MOSTEK_H) */
diff -Nru a/include/asm-sparc64/pci.h b/include/asm-sparc64/pci.h
--- a/include/asm-sparc64/pci.h	2005-03-11 12:51:41 -08:00
+++ b/include/asm-sparc64/pci.h	2005-03-11 12:51:41 -08:00
@@ -223,7 +223,10 @@
 /* Return the index of the PCI controller for device PDEV. */
 
 extern int pci_domain_nr(struct pci_bus *bus);
-extern int pci_name_bus(char *name, struct pci_bus *bus);
+static inline int pci_proc_domain(struct pci_bus *bus)
+{
+	return 1;
+}
 
 /* Platform support for /proc/bus/pci/X/Y mmap()s. */
 
diff -Nru a/include/asm-sparc64/pgalloc.h b/include/asm-sparc64/pgalloc.h
--- a/include/asm-sparc64/pgalloc.h	2005-03-11 12:51:51 -08:00
+++ b/include/asm-sparc64/pgalloc.h	2005-03-11 12:51:51 -08:00
@@ -191,25 +191,17 @@
 
 static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
 {
-	pte_t *pte = __pte_alloc_one_kernel(mm, address);
-	if (pte) {
-		struct page *page = virt_to_page(pte);
-		page->mapping = (void *) mm;
-		page->index = address & PMD_MASK;
-	}
-	return pte;
+	return __pte_alloc_one_kernel(mm, address);
 }
 
 static inline struct page *
 pte_alloc_one(struct mm_struct *mm, unsigned long addr)
 {
 	pte_t *pte = __pte_alloc_one_kernel(mm, addr);
-	if (pte) {
-		struct page *page = virt_to_page(pte);
-		page->mapping = (void *) mm;
-		page->index = addr & PMD_MASK;
-		return page;
-	}
+
+	if (pte)
+		return virt_to_page(pte);
+
 	return NULL;
 }
 
@@ -246,13 +238,11 @@
 
 static inline void pte_free_kernel(pte_t *pte)
 {
-	virt_to_page(pte)->mapping = NULL;
 	free_pte_fast(pte);
 }
 
 static inline void pte_free(struct page *ptepage)
 {
-	ptepage->mapping = NULL;
 	free_pte_fast(page_address(ptepage));
 }
 
diff -Nru a/include/asm-sparc64/pgtable.h b/include/asm-sparc64/pgtable.h
--- a/include/asm-sparc64/pgtable.h	2005-03-11 12:51:41 -08:00
+++ b/include/asm-sparc64/pgtable.h	2005-03-11 12:51:41 -08:00
@@ -15,6 +15,7 @@
 #include <asm-generic/pgtable-nopud.h>
 
 #include <linux/config.h>
+#include <linux/compiler.h>
 #include <asm/spitfire.h>
 #include <asm/asi.h>
 #include <asm/system.h>
@@ -333,18 +334,23 @@
 #define pte_unmap_nested(pte)		do { } while (0)
 
 /* Actual page table PTE updates.  */
-extern void tlb_batch_add(pte_t *ptep, pte_t orig);
+extern void tlb_batch_add(struct mm_struct *mm, unsigned long vaddr, pte_t *ptep, pte_t orig);
 
-static inline void set_pte(pte_t *ptep, pte_t pte)
+static inline void set_pte_at(struct mm_struct *mm, unsigned long addr, pte_t *ptep, pte_t pte)
 {
 	pte_t orig = *ptep;
 
 	*ptep = pte;
-	if (pte_present(orig))
-		tlb_batch_add(ptep, orig);
+
+	/* It is more efficient to let flush_tlb_kernel_range()
+	 * handle init_mm tlb flushes.
+	 */
+	if (likely(mm != &init_mm) && (pte_val(orig) & _PAGE_VALID))
+		tlb_batch_add(mm, addr, ptep, orig);
 }
 
-#define pte_clear(ptep)		set_pte((ptep), __pte(0UL))
+#define pte_clear(mm,addr,ptep)		\
+	set_pte_at((mm), (addr), (ptep), __pte(0UL))
 
 extern pgd_t swapper_pg_dir[1];
 
diff -Nru a/include/asm-sparc64/resource.h b/include/asm-sparc64/resource.h
--- a/include/asm-sparc64/resource.h	2005-03-11 12:51:41 -08:00
+++ b/include/asm-sparc64/resource.h	2005-03-11 12:51:41 -08:00
@@ -8,25 +8,11 @@
 #define _SPARC64_RESOURCE_H
 
 /*
- * Resource limits
+ * These two resource limit IDs have a Sparc/Linux-specific ordering,
+ * the rest comes from the generic header:
  */
-
-#define RLIMIT_CPU	0		/* CPU time in ms */
-#define RLIMIT_FSIZE	1		/* Maximum filesize */
-#define RLIMIT_DATA	2		/* max data size */
-#define RLIMIT_STACK	3		/* max stack size */
-#define RLIMIT_CORE	4		/* max core file size */
-#define RLIMIT_RSS	5		/* max resident set size */
-#define RLIMIT_NOFILE	6		/* max number of open files */
-#define RLIMIT_NPROC	7		/* max number of processes */
-#define RLIMIT_MEMLOCK	8		/* max locked-in-memory address space */
-#define RLIMIT_AS	9		/* address space limit */
-#define RLIMIT_LOCKS	10		/* maximum file locks held */
-#define RLIMIT_SIGPENDING 11		/* max number of pending signals */
-#define RLIMIT_MSGQUEUE 12		/* maximum bytes in POSIX mqueues */
-
-#define RLIM_NLIMITS	13
-#define __ARCH_RLIMIT_ORDER
+#define RLIMIT_NOFILE		6	/* max number of open files */
+#define RLIMIT_NPROC		7	/* max number of processes */
 
 #include <asm-generic/resource.h>
 
diff -Nru a/include/asm-sparc64/siginfo.h b/include/asm-sparc64/siginfo.h
--- a/include/asm-sparc64/siginfo.h	2005-03-11 12:51:47 -08:00
+++ b/include/asm-sparc64/siginfo.h	2005-03-11 12:51:47 -08:00
@@ -4,7 +4,6 @@
 #define SI_PAD_SIZE32	((SI_MAX_SIZE/sizeof(int)) - 3)
 
 #define SIGEV_PAD_SIZE	((SIGEV_MAX_SIZE/sizeof(int)) - 4)
-#define SIGEV_PAD_SIZE32 ((SIGEV_MAX_SIZE/sizeof(int)) - 3)
 
 #define __ARCH_SI_PREAMBLE_SIZE	(4 * sizeof(int))
 #define __ARCH_SI_TRAPNO
@@ -19,11 +18,6 @@
 
 #ifdef CONFIG_COMPAT
 
-typedef union sigval32 {
-	int sival_int;
-	u32 sival_ptr;
-} sigval_t32;
-
 struct compat_siginfo;
 
 #endif /* CONFIG_COMPAT */
@@ -37,27 +31,5 @@
  */
 #define EMT_TAGOVF	(__SI_FAULT|1)	/* tag overflow */
 #define NSIGEMT		1
-
-#ifdef __KERNEL__
-
-#ifdef CONFIG_COMPAT
-
-typedef struct sigevent32 {
-	sigval_t32 sigev_value;
-	int sigev_signo;
-	int sigev_notify;
-	union {
-		int _pad[SIGEV_PAD_SIZE32];
-
-		struct {
-			u32 _function;
-			u32 _attribute;	/* really pthread_attr_t */
-		} _sigev_thread;
-	} _sigev_un;
-} sigevent_t32;
-
-#endif /* CONFIG_COMPAT */
-
-#endif /* __KERNEL__ */
 
 #endif
diff -Nru a/include/asm-sparc64/smp.h b/include/asm-sparc64/smp.h
--- a/include/asm-sparc64/smp.h	2005-03-11 12:51:42 -08:00
+++ b/include/asm-sparc64/smp.h	2005-03-11 12:51:42 -08:00
@@ -30,8 +30,6 @@
 #include <asm/bitops.h>
 #include <asm/atomic.h>
 
-extern unsigned char boot_cpu_id;
-
 extern cpumask_t phys_cpu_present_map;
 #define cpu_possible_map phys_cpu_present_map
 
diff -Nru a/include/asm-sparc64/system.h b/include/asm-sparc64/system.h
--- a/include/asm-sparc64/system.h	2005-03-11 12:51:40 -08:00
+++ b/include/asm-sparc64/system.h	2005-03-11 12:51:40 -08:00
@@ -341,4 +341,6 @@
 
 #endif /* !(__ASSEMBLY__) */
 
+#define arch_align_stack(x) (x)
+
 #endif /* !(__SPARC64_SYSTEM_H) */
diff -Nru a/include/asm-sparc64/uaccess.h b/include/asm-sparc64/uaccess.h
--- a/include/asm-sparc64/uaccess.h	2005-03-11 12:51:52 -08:00
+++ b/include/asm-sparc64/uaccess.h	2005-03-11 12:51:52 -08:00
@@ -49,10 +49,15 @@
 	__asm__ __volatile__ ("wr %%g0, %0, %%asi" : : "r" ((val).seg));	\
 } while(0)
 
-#define __user_ok(addr,size) ((void)(addr), (void)(size), 1)
-#define __kernel_ok (segment_eq(get_fs(), KERNEL_DS))
-#define __access_ok(addr,size) ((void)(addr), (void)(size), 1)
-#define access_ok(type,addr,size) ((void)(type), (void)(addr), (void)(size), 1)
+static inline int __access_ok(const void __user * addr, unsigned long size)
+{
+	return 1;
+}
+
+static inline int access_ok(int type, const void __user * addr, unsigned long size)
+{
+	return 1;
+}
 
 static inline int verify_area(int type, const void __user * addr, unsigned long size)
 {
diff -Nru a/include/asm-sparc64/unistd.h b/include/asm-sparc64/unistd.h
--- a/include/asm-sparc64/unistd.h	2005-03-11 12:51:41 -08:00
+++ b/include/asm-sparc64/unistd.h	2005-03-11 12:51:41 -08:00
@@ -509,6 +509,6 @@
  * What we want is __attribute__((weak,alias("sys_ni_syscall"))),
  * but it doesn't work on all toolchains, so we just do it by hand
  */
-#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall");
+#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall")
 
 #endif /* _SPARC64_UNISTD_H */
diff -Nru a/include/asm-um/pgtable-2level.h b/include/asm-um/pgtable-2level.h
--- a/include/asm-um/pgtable-2level.h	2005-03-11 12:51:42 -08:00
+++ b/include/asm-um/pgtable-2level.h	2005-03-11 12:51:42 -08:00
@@ -21,7 +21,6 @@
  * we don't really have any PMD directory physically.
  */
 #define PTRS_PER_PTE	1024
-#define PTRS_PER_PMD	1
 #define USER_PTRS_PER_PGD ((TASK_SIZE + (PGDIR_SIZE - 1)) / PGDIR_SIZE)
 #define PTRS_PER_PGD	1024
 #define FIRST_USER_PGD_NR       0
@@ -59,6 +58,7 @@
 	*pteptr = pte_mknewpage(pteval);
 	if(pte_present(*pteptr)) *pteptr = pte_mknewprot(*pteptr);
 }
+#define set_pte_at(mm,addr,ptep,pteval) set_pte(ptep,pteval)
 
 #define set_pmd(pmdptr, pmdval) (*(pmdptr) = (pmdval))
 
diff -Nru a/include/asm-um/pgtable-3level.h b/include/asm-um/pgtable-3level.h
--- a/include/asm-um/pgtable-3level.h	2005-03-11 12:51:41 -08:00
+++ b/include/asm-um/pgtable-3level.h	2005-03-11 12:51:41 -08:00
@@ -84,6 +84,7 @@
 	*pteptr = pte_mknewpage(*pteptr);
 	if(pte_present(*pteptr)) *pteptr = pte_mknewprot(*pteptr);
 }
+#define set_pte_at(mm,addr,ptep,pteval) set_pte(ptep,pteval)
 
 #define set_pmd(pmdptr, pmdval) set_64bit((phys_t *) (pmdptr), pmd_val(pmdval))
 
diff -Nru a/include/asm-um/pgtable.h b/include/asm-um/pgtable.h
--- a/include/asm-um/pgtable.h	2005-03-11 12:51:52 -08:00
+++ b/include/asm-um/pgtable.h	2005-03-11 12:51:52 -08:00
@@ -142,7 +142,7 @@
 #define PAGE_PTR(address) \
 ((unsigned long)(address)>>(PAGE_SHIFT-SIZEOF_PTR_LOG2)&PTR_MASK&~PAGE_MASK)
 
-#define pte_clear(xp) pte_set_val(*(xp), (phys_t) 0, __pgprot(_PAGE_NEWPAGE))
+#define pte_clear(mm,addr,xp) pte_set_val(*(xp), (phys_t) 0, __pgprot(_PAGE_NEWPAGE))
 
 #define pmd_none(x)	(!(pmd_val(x) & ~_PAGE_NEWPAGE))
 #define	pmd_bad(x)	((pmd_val(x) & (~PAGE_MASK & ~_PAGE_USER)) != _KERNPG_TABLE)
diff -Nru a/include/asm-v850/cacheflush.h b/include/asm-v850/cacheflush.h
--- a/include/asm-v850/cacheflush.h	2005-03-11 12:51:42 -08:00
+++ b/include/asm-v850/cacheflush.h	2005-03-11 12:51:42 -08:00
@@ -25,7 +25,7 @@
 #define flush_cache_all()			((void)0)
 #define flush_cache_mm(mm)			((void)0)
 #define flush_cache_range(vma, start, end)	((void)0)
-#define flush_cache_page(vma, vmaddr)		((void)0)
+#define flush_cache_page(vma, vmaddr, pfn)	((void)0)
 #define flush_dcache_page(page)			((void)0)
 #define flush_dcache_mmap_lock(mapping)		((void)0)
 #define flush_dcache_mmap_unlock(mapping)	((void)0)
diff -Nru a/include/asm-v850/system.h b/include/asm-v850/system.h
--- a/include/asm-v850/system.h	2005-03-11 12:51:48 -08:00
+++ b/include/asm-v850/system.h	2005-03-11 12:51:48 -08:00
@@ -108,4 +108,6 @@
 	return tmp;
 }
 
+#define arch_align_stack(x) (x)
+
 #endif /* __V850_SYSTEM_H__ */
diff -Nru a/include/asm-v850/unistd.h b/include/asm-v850/unistd.h
--- a/include/asm-v850/unistd.h	2005-03-11 12:51:51 -08:00
+++ b/include/asm-v850/unistd.h	2005-03-11 12:51:51 -08:00
@@ -466,7 +466,7 @@
  */
 #define cond_syscall(name)						      \
   asm (".weak\t" C_SYMBOL_STRING(name) ";"				      \
-       ".set\t" C_SYMBOL_STRING(name) "," C_SYMBOL_STRING(sys_ni_syscall));
+       ".set\t" C_SYMBOL_STRING(name) "," C_SYMBOL_STRING(sys_ni_syscall))
 #if 0
 /* This doesn't work if there's a function prototype for NAME visible,
    because the argument types probably won't match.  */
diff -Nru a/include/asm-x86_64/cacheflush.h b/include/asm-x86_64/cacheflush.h
--- a/include/asm-x86_64/cacheflush.h	2005-03-11 12:51:41 -08:00
+++ b/include/asm-x86_64/cacheflush.h	2005-03-11 12:51:41 -08:00
@@ -8,7 +8,7 @@
 #define flush_cache_all()			do { } while (0)
 #define flush_cache_mm(mm)			do { } while (0)
 #define flush_cache_range(vma, start, end)	do { } while (0)
-#define flush_cache_page(vma, vmaddr)		do { } while (0)
+#define flush_cache_page(vma, vmaddr, pfn)	do { } while (0)
 #define flush_dcache_page(page)			do { } while (0)
 #define flush_dcache_mmap_lock(mapping)		do { } while (0)
 #define flush_dcache_mmap_unlock(mapping)	do { } while (0)
diff -Nru a/include/asm-x86_64/pgtable.h b/include/asm-x86_64/pgtable.h
--- a/include/asm-x86_64/pgtable.h	2005-03-11 12:51:47 -08:00
+++ b/include/asm-x86_64/pgtable.h	2005-03-11 12:51:47 -08:00
@@ -73,6 +73,7 @@
 {
 	pte_val(*dst) = pte_val(val);
 } 
+#define set_pte_at(mm,addr,ptep,pteval) set_pte(ptep,pteval)
 
 static inline void set_pmd(pmd_t *dst, pmd_t val)
 {
@@ -102,7 +103,7 @@
 #define pud_page(pud) \
 ((unsigned long) __va(pud_val(pud) & PHYSICAL_PAGE_MASK))
 
-#define ptep_get_and_clear(xp)	__pte(xchg(&(xp)->pte, 0))
+#define ptep_get_and_clear(mm,addr,xp)	__pte(xchg(&(xp)->pte, 0))
 #define pte_same(a, b)		((a).pte == (b).pte)
 
 #define PMD_SIZE	(1UL << PMD_SHIFT)
@@ -224,7 +225,7 @@
 
 #define pte_none(x)	(!pte_val(x))
 #define pte_present(x)	(pte_val(x) & (_PAGE_PRESENT | _PAGE_PROTNONE))
-#define pte_clear(xp)	do { set_pte(xp, __pte(0)); } while (0)
+#define pte_clear(mm,addr,xp)	do { set_pte_at(mm, addr, xp, __pte(0)); } while (0)
 
 #define pages_to_mb(x) ((x) >> (20-PAGE_SHIFT))	/* FIXME: is this
 						   right? */
@@ -263,22 +264,26 @@
 extern inline pte_t pte_mkyoung(pte_t pte)	{ set_pte(&pte, __pte(pte_val(pte) | _PAGE_ACCESSED)); return pte; }
 extern inline pte_t pte_mkwrite(pte_t pte)	{ set_pte(&pte, __pte(pte_val(pte) | _PAGE_RW)); return pte; }
 
-static inline int ptep_test_and_clear_dirty(pte_t *ptep)
+struct vm_area_struct;
+
+static inline int ptep_test_and_clear_dirty(struct vm_area_struct *vma, unsigned long addr, pte_t *ptep)
 {
 	if (!pte_dirty(*ptep))
 		return 0;
 	return test_and_clear_bit(_PAGE_BIT_DIRTY, ptep);
 }
 
-static inline int ptep_test_and_clear_young(pte_t *ptep)
+static inline int ptep_test_and_clear_young(struct vm_area_struct *vma, unsigned long addr, pte_t *ptep)
 {
 	if (!pte_young(*ptep))
 		return 0;
 	return test_and_clear_bit(_PAGE_BIT_ACCESSED, ptep);
 }
 
-static inline void ptep_set_wrprotect(pte_t *ptep)		{ clear_bit(_PAGE_BIT_RW, ptep); }
-static inline void ptep_mkdirty(pte_t *ptep)			{ set_bit(_PAGE_BIT_DIRTY, ptep); }
+static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
+{
+	clear_bit(_PAGE_BIT_RW, ptep);
+}
 
 /*
  * Macro to mark a page protection value as "uncacheable".
@@ -419,7 +424,6 @@
 #define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_DIRTY
 #define __HAVE_ARCH_PTEP_GET_AND_CLEAR
 #define __HAVE_ARCH_PTEP_SET_WRPROTECT
-#define __HAVE_ARCH_PTEP_MKDIRTY
 #define __HAVE_ARCH_PTE_SAME
 #include <asm-generic/pgtable.h>
 
diff -Nru a/include/asm-x86_64/system.h b/include/asm-x86_64/system.h
--- a/include/asm-x86_64/system.h	2005-03-11 12:51:51 -08:00
+++ b/include/asm-x86_64/system.h	2005-03-11 12:51:51 -08:00
@@ -338,4 +338,6 @@
 #define HAVE_EAT_KEY
 void eat_key(void);
 
+extern unsigned long arch_align_stack(unsigned long sp);
+
 #endif
diff -Nru a/include/asm-x86_64/thread_info.h b/include/asm-x86_64/thread_info.h
--- a/include/asm-x86_64/thread_info.h	2005-03-11 12:51:47 -08:00
+++ b/include/asm-x86_64/thread_info.h	2005-03-11 12:51:47 -08:00
@@ -102,6 +102,7 @@
 #define TIF_SINGLESTEP		4	/* reenable singlestep on user return*/
 #define TIF_IRET		5	/* force IRET */
 #define TIF_SYSCALL_AUDIT	7	/* syscall auditing active */
+#define TIF_SECCOMP		8	/* secure computing */
 #define TIF_POLLING_NRFLAG	16	/* true if poll_idle() is polling TIF_NEED_RESCHED */
 #define TIF_IA32		17	/* 32bit process */ 
 #define TIF_FORK		18	/* ret_from_fork */
@@ -115,6 +116,7 @@
 #define _TIF_NEED_RESCHED	(1<<TIF_NEED_RESCHED)
 #define _TIF_IRET		(1<<TIF_IRET)
 #define _TIF_SYSCALL_AUDIT	(1<<TIF_SYSCALL_AUDIT)
+#define _TIF_SECCOMP		(1<<TIF_SECCOMP)
 #define _TIF_POLLING_NRFLAG	(1<<TIF_POLLING_NRFLAG)
 #define _TIF_IA32		(1<<TIF_IA32)
 #define _TIF_FORK		(1<<TIF_FORK)
@@ -122,9 +124,9 @@
 
 /* work to do on interrupt/exception return */
 #define _TIF_WORK_MASK \
-  (0x0000FFFF & ~(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SINGLESTEP))
+  (0x0000FFFF & ~(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SINGLESTEP|_TIF_SECCOMP))
 /* work to do on any return to user space */
-#define _TIF_ALLWORK_MASK 0x0000FFFF	
+#define _TIF_ALLWORK_MASK (0x0000FFFF & ~_TIF_SECCOMP)
 
 #define PREEMPT_ACTIVE     0x10000000
 
diff -Nru a/include/asm-x86_64/uaccess.h b/include/asm-x86_64/uaccess.h
--- a/include/asm-x86_64/uaccess.h	2005-03-11 12:51:52 -08:00
+++ b/include/asm-x86_64/uaccess.h	2005-03-11 12:51:52 -08:00
@@ -73,6 +73,7 @@
 	unsigned long insn, fixup;
 };
 
+#define ARCH_HAS_SEARCH_EXTABLE
 
 /*
  * These are the main single-value transfer routines.  They automatically
diff -Nru a/include/asm-x86_64/unistd.h b/include/asm-x86_64/unistd.h
--- a/include/asm-x86_64/unistd.h	2005-03-11 12:51:47 -08:00
+++ b/include/asm-x86_64/unistd.h	2005-03-11 12:51:47 -08:00
@@ -792,6 +792,6 @@
  * What we want is __attribute__((weak,alias("sys_ni_syscall"))),
  * but it doesn't work on all toolchains, so we just do it by hand
  */
-#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall");
+#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall")
 
 #endif
diff -Nru a/include/linux/ac97_codec.h b/include/linux/ac97_codec.h
--- a/include/linux/ac97_codec.h	2005-03-11 12:51:41 -08:00
+++ b/include/linux/ac97_codec.h	2005-03-11 12:51:41 -08:00
@@ -323,6 +323,7 @@
 	
 #define AC97_DELUDED_MODEM	1	/* Audio codec reports its a modem */
 #define AC97_NO_PCM_VOLUME	2	/* Volume control is missing 	   */
+#define AC97_DEFAULT_POWER_OFF 4 /* Needs warm reset to power up */
 };
 
 extern int ac97_read_proc (char *page_out, char **start, off_t off,
diff -Nru a/include/linux/acct.h b/include/linux/acct.h
--- a/include/linux/acct.h	2005-03-11 12:51:52 -08:00
+++ b/include/linux/acct.h	2005-03-11 12:51:52 -08:00
@@ -120,12 +120,12 @@
 struct super_block;
 extern void acct_auto_close(struct super_block *sb);
 extern void acct_process(long exitcode);
-extern void acct_update_integrals(void);
+extern void acct_update_integrals(struct task_struct *tsk);
 extern void acct_clear_integrals(struct task_struct *tsk);
 #else
 #define acct_auto_close(x)	do { } while (0)
 #define acct_process(x)		do { } while (0)
-#define acct_update_integrals()		do { } while (0)
+#define acct_update_integrals(x)		do { } while (0)
 #define acct_clear_integrals(task)	do { } while (0)
 #endif
 
diff -Nru a/include/linux/agp_backend.h b/include/linux/agp_backend.h
--- a/include/linux/agp_backend.h	2005-03-11 12:51:50 -08:00
+++ b/include/linux/agp_backend.h	2005-03-11 12:51:50 -08:00
@@ -1,6 +1,7 @@
 /*
  * AGPGART backend specific includes. Not for userspace consumption.
  *
+ * Copyright (C) 2004 Silicon Graphics, Inc.
  * Copyright (C) 2002-2003 Dave Jones
  * Copyright (C) 1999 Jeff Hartmann
  * Copyright (C) 1999 Precision Insight, Inc.
@@ -63,21 +64,24 @@
 	struct vm_operations_struct *vm_ops;
 };
 
-/* 
+/*
  * The agp_memory structure has information about the block of agp memory
  * allocated.  A caller may manipulate the next and prev pointers to link
  * each allocated item into a list.  These pointers are ignored by the backend.
  * Everything else should never be written to, but the caller may read any of
- * the items to detrimine the status of this block of agp memory. 
+ * the items to determine the status of this block of agp memory.
  */
 
+struct agp_bridge_data;
+
 struct agp_memory {
-	int key;
 	struct agp_memory *next;
 	struct agp_memory *prev;
+	struct agp_bridge_data *bridge;
+	unsigned long *memory;
 	size_t page_count;
+	int key;
 	int num_scratch_pages;
-	unsigned long *memory;
 	off_t pg_start;
 	u32 type;
 	u32 physical;
@@ -87,14 +91,19 @@
 
 #define AGP_NORMAL_MEMORY 0
 
+extern struct agp_bridge_data *agp_bridge;
+extern struct list_head agp_bridges;
+
+extern struct agp_bridge_data *(*agp_find_bridge)(struct pci_dev *);
+
 extern void agp_free_memory(struct agp_memory *);
-extern struct agp_memory *agp_allocate_memory(size_t, u32);
-extern int agp_copy_info(struct agp_kern_info *);
+extern struct agp_memory *agp_allocate_memory(struct agp_bridge_data *, size_t, u32);
+extern int agp_copy_info(struct agp_bridge_data *, struct agp_kern_info *);
 extern int agp_bind_memory(struct agp_memory *, off_t);
 extern int agp_unbind_memory(struct agp_memory *);
-extern void agp_enable(u32);
-extern int agp_backend_acquire(void);
-extern void agp_backend_release(void);
+extern void agp_enable(struct agp_bridge_data *, u32);
+extern struct agp_bridge_data *agp_backend_acquire(struct pci_dev *);
+extern void agp_backend_release(struct agp_bridge_data *);
 
 #endif				/* __KERNEL__ */
 #endif				/* _AGP_BACKEND_H */
diff -Nru a/include/linux/atalk.h b/include/linux/atalk.h
--- a/include/linux/atalk.h	2005-03-11 12:51:50 -08:00
+++ b/include/linux/atalk.h	2005-03-11 12:51:50 -08:00
@@ -1,5 +1,8 @@
 #ifndef __LINUX_ATALK_H__
 #define __LINUX_ATALK_H__
+
+#include <net/sock.h>
+
 /*
  * AppleTalk networking structures
  *
@@ -63,6 +66,8 @@
 };
 	
 struct atalk_sock {
+	/* struct sock has to be the first member of atalk_sock */
+	struct sock	sk;
 	unsigned short	dest_net;
 	unsigned short	src_net;
 	unsigned char	dest_node;
@@ -71,6 +76,11 @@
 	unsigned char	src_port;
 };
 
+static inline struct atalk_sock *at_sk(struct sock *sk)
+{
+	return (struct atalk_sock *)sk;
+}
+
 #ifdef __KERNEL__
 
 #include <asm/byteorder.h>
@@ -196,8 +206,6 @@
 					   struct atalk_addr *sa);
 
 extern void		aarp_cleanup_module(void);
-
-#define at_sk(__sk) ((struct atalk_sock *)(__sk)->sk_protinfo)
 
 extern struct hlist_head atalk_sockets;
 extern rwlock_t atalk_sockets_lock;
diff -Nru a/include/linux/atmdev.h b/include/linux/atmdev.h
--- a/include/linux/atmdev.h	2005-03-11 12:51:51 -08:00
+++ b/include/linux/atmdev.h	2005-03-11 12:51:51 -08:00
@@ -30,9 +30,6 @@
 #define ATM_DS3_PCR	(8000*12)
 			/* DS3: 12 cells in a 125 usec time slot */
 
-#define atm_sk(__sk) ((struct atm_vcc *)(__sk)->sk_protinfo)
-#define ATM_SD(s)	(atm_sk((s)->sk))
-
 
 #define __AAL_STAT_ITEMS \
     __HANDLE_ITEM(tx);			/* TX okay */ \
@@ -281,6 +278,8 @@
 #define ATM_ATMOPT_CLP	1	/* set CLP bit */
 
 struct atm_vcc {
+	/* struct sock has to be the first member of atm_vcc */
+	struct sock	sk;
 	unsigned long	flags;		/* VCC flags (ATM_VF_*) */
 	short		vpi;		/* VPI and VCI (types must be equal */
 					/* with sockaddr) */
@@ -297,7 +296,6 @@
 	void		*dev_data;	/* per-device data */
 	void		*proto_data;	/* per-protocol data */
 	struct k_atm_aal_stats *stats;	/* pointer to AAL stats group */
-	struct sock	*sk;		/* socket backpointer */
 	/* SVC part --- may move later ------------------------------------- */
 	short		itf;		/* interface number */
 	struct sockaddr_atmsvc local;
@@ -310,6 +308,20 @@
 					/* by CLIP and sch_atm. */
 };
 
+static inline struct atm_vcc *atm_sk(struct sock *sk)
+{
+	return (struct atm_vcc *)sk;
+}
+
+static inline struct atm_vcc *ATM_SD(struct socket *sock)
+{
+	return atm_sk(sock->sk);
+}
+
+static inline struct sock *sk_atm(struct atm_vcc *vcc)
+{
+	return (struct sock *)vcc;
+}
 
 struct atm_dev_addr {
 	struct sockaddr_atmsvc addr;	/* ATM address */
@@ -410,20 +422,20 @@
 
 static inline void atm_force_charge(struct atm_vcc *vcc,int truesize)
 {
-	atomic_add(truesize, &vcc->sk->sk_rmem_alloc);
+	atomic_add(truesize, &sk_atm(vcc)->sk_rmem_alloc);
 }
 
 
 static inline void atm_return(struct atm_vcc *vcc,int truesize)
 {
-	atomic_sub(truesize, &vcc->sk->sk_rmem_alloc);
+	atomic_sub(truesize, &sk_atm(vcc)->sk_rmem_alloc);
 }
 
 
 static inline int atm_may_send(struct atm_vcc *vcc,unsigned int size)
 {
-	return (size + atomic_read(&vcc->sk->sk_wmem_alloc)) <
-	       vcc->sk->sk_sndbuf;
+	return (size + atomic_read(&sk_atm(vcc)->sk_wmem_alloc)) <
+	       sk_atm(vcc)->sk_sndbuf;
 }
 
 
diff -Nru a/include/linux/bio.h b/include/linux/bio.h
--- a/include/linux/bio.h	2005-03-11 12:51:50 -08:00
+++ b/include/linux/bio.h	2005-03-11 12:51:50 -08:00
@@ -59,6 +59,7 @@
 	unsigned int	bv_offset;
 };
 
+struct bio_set;
 struct bio;
 typedef int (bio_end_io_t) (struct bio *, unsigned int, int);
 typedef void (bio_destructor_t) (struct bio *);
@@ -109,6 +110,7 @@
 	void			*bi_private;
 
 	bio_destructor_t	*bi_destructor;	/* destructor */
+	struct bio_set		*bi_set;	/* memory pools set */
 };
 
 /*
@@ -258,7 +260,11 @@
 extern mempool_t *bio_split_pool;
 extern void bio_pair_release(struct bio_pair *dbio);
 
+extern struct bio_set *bioset_create(int, int, int);
+extern void bioset_free(struct bio_set *);
+
 extern struct bio *bio_alloc(int, int);
+extern struct bio *bio_alloc_bioset(int, int, struct bio_set *);
 extern void bio_put(struct bio *);
 
 extern void bio_endio(struct bio *, unsigned int, int);
@@ -280,6 +286,7 @@
 extern void bio_check_pages_dirty(struct bio *bio);
 extern struct bio *bio_copy_user(struct request_queue *, unsigned long, unsigned int, int);
 extern int bio_uncopy_user(struct bio *);
+void zero_fill_bio(struct bio *bio);
 
 #ifdef CONFIG_HIGHMEM
 /*
diff -Nru a/include/linux/bitmap.h b/include/linux/bitmap.h
--- a/include/linux/bitmap.h	2005-03-11 12:51:52 -08:00
+++ b/include/linux/bitmap.h	2005-03-11 12:51:52 -08:00
@@ -41,7 +41,9 @@
  * bitmap_shift_right(dst, src, n, nbits)	*dst = *src >> n
  * bitmap_shift_left(dst, src, n, nbits)	*dst = *src << n
  * bitmap_scnprintf(buf, len, src, nbits)	Print bitmap src to buf
- * bitmap_parse(ubuf, ulen, dst, nbits)		Parse bitmap dst from buf
+ * bitmap_parse(ubuf, ulen, dst, nbits)		Parse bitmap dst from user buf
+ * bitmap_scnlistprintf(buf, len, src, nbits)	Print bitmap src as list to buf
+ * bitmap_parselist(buf, dst, nbits)		Parse bitmap dst from list
  */
 
 /*
@@ -98,6 +100,10 @@
 			const unsigned long *src, int nbits);
 extern int bitmap_parse(const char __user *ubuf, unsigned int ulen,
 			unsigned long *dst, int nbits);
+extern int bitmap_scnlistprintf(char *buf, unsigned int len,
+			const unsigned long *src, int nbits);
+extern int bitmap_parselist(const char *buf, unsigned long *maskp,
+			int nmaskbits);
 extern int bitmap_find_free_region(unsigned long *bitmap, int bits, int order);
 extern void bitmap_release_region(unsigned long *bitmap, int pos, int order);
 extern int bitmap_allocate_region(unsigned long *bitmap, int pos, int order);
diff -Nru a/include/linux/bitops.h b/include/linux/bitops.h
--- a/include/linux/bitops.h	2005-03-11 12:51:51 -08:00
+++ b/include/linux/bitops.h	2005-03-11 12:51:51 -08:00
@@ -134,4 +134,26 @@
 	return sizeof(w) == 4 ? generic_hweight32(w) : generic_hweight64(w);
 }
 
+/*
+ * rol32 - rotate a 32-bit value left
+ *
+ * @word: value to rotate
+ * @shift: bits to roll
+ */
+static inline __u32 rol32(__u32 word, int shift)
+{
+	return (word << shift) | (word >> (32 - shift));
+}
+
+/*
+ * ror32 - rotate a 32-bit value right
+ *
+ * @word: value to rotate
+ * @shift: bits to roll
+ */
+static inline __u32 ror32(__u32 word, int shift)
+{
+	return (word >> shift) | (word << (32 - shift));
+}
+
 #endif
diff -Nru a/include/linux/blkdev.h b/include/linux/blkdev.h
--- a/include/linux/blkdev.h	2005-03-11 12:51:41 -08:00
+++ b/include/linux/blkdev.h	2005-03-11 12:51:41 -08:00
@@ -93,6 +93,9 @@
 void copy_io_context(struct io_context **pdst, struct io_context **psrc);
 void swap_io_context(struct io_context **ioc1, struct io_context **ioc2);
 
+struct request;
+typedef void (rq_end_io_fn)(struct request *);
+
 struct request_list {
 	int count[2];
 	int starved[2];
@@ -176,6 +179,12 @@
 	 * For Power Management requests
 	 */
 	struct request_pm_state *pm;
+
+	/*
+	 * completion callback. end_io_data should be folded in with waiting
+	 */
+	rq_end_io_fn *end_io;
+	void *end_io_data;
 };
 
 /*
@@ -210,6 +219,7 @@
 	__REQ_PM_SHUTDOWN,	/* shutdown request */
 	__REQ_BAR_PREFLUSH,	/* barrier pre-flush done */
 	__REQ_BAR_POSTFLUSH,	/* barrier post-flush */
+	__REQ_BAR_FLUSH,	/* rq is the flush request */
 	__REQ_NR_BITS,		/* stops here */
 };
 
@@ -237,6 +247,7 @@
 #define REQ_PM_SHUTDOWN	(1 << __REQ_PM_SHUTDOWN)
 #define REQ_BAR_PREFLUSH	(1 << __REQ_BAR_PREFLUSH)
 #define REQ_BAR_POSTFLUSH	(1 << __REQ_BAR_POSTFLUSH)
+#define REQ_BAR_FLUSH	(1 << __REQ_BAR_FLUSH)
 
 /*
  * State information carried for REQ_PM_SUSPEND and REQ_PM_RESUME
@@ -266,6 +277,8 @@
 typedef int (merge_bvec_fn) (request_queue_t *, struct bio *, struct bio_vec *);
 typedef void (activity_fn) (void *data, int rw);
 typedef int (issue_flush_fn) (request_queue_t *, struct gendisk *, sector_t *);
+typedef int (prepare_flush_fn) (request_queue_t *, struct request *);
+typedef void (end_flush_fn) (request_queue_t *, struct request *);
 
 enum blk_queue_state {
 	Queue_down,
@@ -309,6 +322,8 @@
 	merge_bvec_fn		*merge_bvec_fn;
 	activity_fn		*activity_fn;
 	issue_flush_fn		*issue_flush_fn;
+	prepare_flush_fn	*prepare_flush_fn;
+	end_flush_fn		*end_flush_fn;
 
 	/*
 	 * Auto-unplugging state
@@ -380,6 +395,18 @@
 	unsigned int		sg_reserved_size;
 
 	struct list_head	drain_list;
+
+	/*
+	 * reserved for flush operations
+	 */
+	struct request		*flush_rq;
+	unsigned char		ordered;
+};
+
+enum {
+	QUEUE_ORDERED_NONE,
+	QUEUE_ORDERED_TAG,
+	QUEUE_ORDERED_FLUSH,
 };
 
 #define RQ_INACTIVE		(-1)
@@ -396,12 +423,13 @@
 #define QUEUE_FLAG_DEAD		5	/* queue being torn down */
 #define QUEUE_FLAG_REENTER	6	/* Re-entrancy avoidance */
 #define QUEUE_FLAG_PLUGGED	7	/* queue is plugged */
-#define QUEUE_FLAG_ORDERED	8	/* supports ordered writes */
-#define QUEUE_FLAG_DRAIN	9	/* draining queue for sched switch */
+#define QUEUE_FLAG_DRAIN	8	/* draining queue for sched switch */
+#define QUEUE_FLAG_FLUSH	9	/* doing barrier flush sequence */
 
 #define blk_queue_plugged(q)	test_bit(QUEUE_FLAG_PLUGGED, &(q)->queue_flags)
 #define blk_queue_tagged(q)	test_bit(QUEUE_FLAG_QUEUED, &(q)->queue_flags)
 #define blk_queue_stopped(q)	test_bit(QUEUE_FLAG_STOPPED, &(q)->queue_flags)
+#define blk_queue_flushing(q)	test_bit(QUEUE_FLAG_FLUSH, &(q)->queue_flags)
 
 #define blk_fs_request(rq)	((rq)->flags & REQ_CMD)
 #define blk_pc_request(rq)	((rq)->flags & REQ_BLOCK_PC)
@@ -509,10 +537,10 @@
 extern void register_disk(struct gendisk *dev);
 extern void generic_make_request(struct bio *bio);
 extern void blk_put_request(struct request *);
+extern void blk_end_sync_rq(struct request *rq);
 extern void blk_attempt_remerge(request_queue_t *, struct request *);
 extern void __blk_attempt_remerge(request_queue_t *, struct request *);
 extern struct request *blk_get_request(request_queue_t *, int, int);
-extern void blk_put_request(struct request *);
 extern void blk_insert_request(request_queue_t *, struct request *, int, void *, int);
 extern void blk_requeue_request(request_queue_t *, struct request *);
 extern void blk_plug_device(request_queue_t *);
@@ -602,6 +630,9 @@
 extern void blk_queue_ordered(request_queue_t *, int);
 extern void blk_queue_issue_flush_fn(request_queue_t *, issue_flush_fn *);
 extern int blkdev_scsi_issue_flush_fn(request_queue_t *, struct gendisk *, sector_t *);
+extern struct request *blk_start_pre_flush(request_queue_t *,struct request *);
+extern int blk_complete_barrier_rq(request_queue_t *, struct request *, int);
+extern int blk_complete_barrier_rq_locked(request_queue_t *, struct request *, int);
 
 extern int blk_rq_map_sg(request_queue_t *, struct request *, struct scatterlist *);
 extern void blk_dump_rq_flags(struct request *, char *);
diff -Nru a/include/linux/buffer_head.h b/include/linux/buffer_head.h
--- a/include/linux/buffer_head.h	2005-03-11 12:51:41 -08:00
+++ b/include/linux/buffer_head.h	2005-03-11 12:51:41 -08:00
@@ -203,6 +203,9 @@
 int nobh_prepare_write(struct page*, unsigned, unsigned, get_block_t*);
 int nobh_commit_write(struct file *, struct page *, unsigned, unsigned);
 int nobh_truncate_page(struct address_space *, loff_t);
+int nobh_writepage(struct page *page, get_block_t *get_block,
+                        struct writeback_control *wbc);
+
 
 /*
  * inline definitions
diff -Nru a/include/linux/compat.h b/include/linux/compat.h
--- a/include/linux/compat.h	2005-03-11 12:51:46 -08:00
+++ b/include/linux/compat.h	2005-03-11 12:51:46 -08:00
@@ -83,6 +83,12 @@
 
 extern int put_compat_rusage(const struct rusage *, struct compat_rusage __user *);
 
+struct compat_siginfo;
+
+extern asmlinkage long compat_sys_waitid(int, compat_pid_t,
+		struct compat_siginfo __user *, int,
+		struct compat_rusage __user *);
+
 struct compat_dirent {
 	u32		d_ino;
 	compat_off_t	d_off;
@@ -95,12 +101,14 @@
 	compat_uptr_t	sival_ptr;
 } compat_sigval_t;
 
+#define COMPAT_SIGEV_PAD_SIZE	((SIGEV_MAX_SIZE/sizeof(int)) - 3)
+
 typedef struct compat_sigevent {
 	compat_sigval_t sigev_value;
 	compat_int_t sigev_signo;
 	compat_int_t sigev_notify;
 	union {
-		compat_int_t _pad[SIGEV_PAD_SIZE];
+		compat_int_t _pad[COMPAT_SIGEV_PAD_SIZE];
 		compat_int_t _tid;
 
 		struct {
@@ -145,8 +153,10 @@
 		       unsigned long bitmap_size);
 long compat_put_bitmap(compat_ulong_t __user *umask, unsigned long *mask,
 		       unsigned long bitmap_size);
-struct compat_siginfo;
 int copy_siginfo_from_user32(siginfo_t *to, struct compat_siginfo __user *from);
 int copy_siginfo_to_user32(struct compat_siginfo __user *to, siginfo_t *from);
+int get_compat_sigevent(struct sigevent *event,
+		const struct compat_sigevent __user *u_event);
+
 #endif /* CONFIG_COMPAT */
 #endif /* _LINUX_COMPAT_H */
diff -Nru a/include/linux/compat_ioctl.h b/include/linux/compat_ioctl.h
--- a/include/linux/compat_ioctl.h	2005-03-11 12:51:51 -08:00
+++ b/include/linux/compat_ioctl.h	2005-03-11 12:51:51 -08:00
@@ -16,6 +16,7 @@
 COMPATIBLE_IOCTL(TCSETAW)
 COMPATIBLE_IOCTL(TCSETAF)
 COMPATIBLE_IOCTL(TCSBRK)
+ULONG_IOCTL(TCSBRKP)
 COMPATIBLE_IOCTL(TCXONC)
 COMPATIBLE_IOCTL(TCFLSH)
 COMPATIBLE_IOCTL(TCGETS)
@@ -692,6 +693,9 @@
 COMPATIBLE_IOCTL(USBDEVFS_CONNECTINFO)
 COMPATIBLE_IOCTL(USBDEVFS_HUB_PORTINFO)
 COMPATIBLE_IOCTL(USBDEVFS_RESET)
+COMPATIBLE_IOCTL(USBDEVFS_SUBMITURB32)
+COMPATIBLE_IOCTL(USBDEVFS_REAPURB32)
+COMPATIBLE_IOCTL(USBDEVFS_REAPURBNDELAY32)
 COMPATIBLE_IOCTL(USBDEVFS_CLEAR_HALT)
 /* MTD */
 COMPATIBLE_IOCTL(MEMGETINFO)
diff -Nru a/include/linux/compiler-gcc+.h b/include/linux/compiler-gcc+.h
--- a/include/linux/compiler-gcc+.h	2005-03-11 12:51:51 -08:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,16 +0,0 @@
-/* Never include this file directly.  Include <linux/compiler.h> instead.  */
-
-/*
- * These definitions are for Ueber-GCC: always newer than the latest
- * version and hence sporting everything plus a kitchen-sink.
- */
-#include <linux/compiler-gcc.h>
-
-#define inline			inline		__attribute__((always_inline))
-#define __inline__		__inline__	__attribute__((always_inline))
-#define __inline		__inline	__attribute__((always_inline))
-#define __deprecated		__attribute__((deprecated))
-#define __attribute_used__	__attribute__((__used__))
-#define __attribute_pure__	__attribute__((pure))
-#define __attribute_const__	__attribute__((__const__))
-#define __must_check 		__attribute__((warn_unused_result))
diff -Nru a/include/linux/compiler-gcc3.h b/include/linux/compiler-gcc3.h
--- a/include/linux/compiler-gcc3.h	2005-03-11 12:51:40 -08:00
+++ b/include/linux/compiler-gcc3.h	2005-03-11 12:51:40 -08:00
@@ -10,7 +10,7 @@
 #endif
 
 #if __GNUC_MINOR__ > 0
-# define __deprecated	__attribute__((deprecated))
+# define __deprecated		__attribute__((deprecated))
 #endif
 
 #if __GNUC_MINOR__ >= 3
@@ -23,12 +23,10 @@
 #define __attribute_const__	__attribute__((__const__))
 
 #if __GNUC_MINOR__ >= 1
-#define  noinline __attribute__((noinline))
+#define  noinline		__attribute__((noinline))
 #endif
+
 #if __GNUC_MINOR__ >= 4
-#define __must_check __attribute__((warn_unused_result))
+#define __must_check		__attribute__((warn_unused_result))
 #endif
 
-#if __GNUC_MINOR__ >= 5
-#define __compiler_offsetof(a,b) __builtin_offsetof(a,b)
-#endif
diff -Nru a/include/linux/compiler-gcc4.h b/include/linux/compiler-gcc4.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/linux/compiler-gcc4.h	2005-03-11 12:51:51 -08:00
@@ -0,0 +1,16 @@
+/* Never include this file directly.  Include <linux/compiler.h> instead.  */
+
+/* These definitions are for GCC v4.x.  */
+#include <linux/compiler-gcc.h>
+
+#define inline			inline		__attribute__((always_inline))
+#define __inline__		__inline__	__attribute__((always_inline))
+#define __inline		__inline	__attribute__((always_inline))
+#define __deprecated		__attribute__((deprecated))
+#define __attribute_used__	__attribute__((__used__))
+#define __attribute_pure__	__attribute__((pure))
+#define __attribute_const__	__attribute__((__const__))
+#define  noinline		__attribute__((noinline))
+#define __must_check 		__attribute__((warn_unused_result))
+#define __compiler_offsetof(a,b) __builtin_offsetof(a,b)
+
diff -Nru a/include/linux/compiler.h b/include/linux/compiler.h
--- a/include/linux/compiler.h	2005-03-11 12:51:47 -08:00
+++ b/include/linux/compiler.h	2005-03-11 12:51:47 -08:00
@@ -34,8 +34,10 @@
 
 #ifdef __KERNEL__
 
-#if __GNUC__ > 3
-# include <linux/compiler-gcc+.h>	/* catch-all for GCC 4, 5, etc. */
+#if __GNUC__ > 4
+#error no compiler-gcc.h file for this gcc version
+#elif __GNUC__ == 4
+# include <linux/compiler-gcc4.h>
 #elif __GNUC__ == 3
 # include <linux/compiler-gcc3.h>
 #elif __GNUC__ == 2
diff -Nru a/include/linux/console_struct.h b/include/linux/console_struct.h
--- a/include/linux/console_struct.h	2005-03-11 12:51:40 -08:00
+++ b/include/linux/console_struct.h	2005-03-11 12:51:40 -08:00
@@ -26,6 +26,7 @@
 	const struct consw *vc_sw;
 	unsigned short	*vc_screenbuf;		/* In-memory character/attribute buffer */
 	unsigned int	vc_screenbuf_size;
+	unsigned char	vc_mode;		/* KD_TEXT, ... */
 	/* attributes for all characters on screen */
 	unsigned char	vc_attr;		/* Current attributes */
 	unsigned char	vc_def_color;		/* Default colors */
@@ -48,6 +49,11 @@
 	unsigned int	vc_state;		/* Escape sequence parser state */
 	unsigned int	vc_npar,vc_par[NPAR];	/* Parameters of current escape sequence */
 	struct tty_struct *vc_tty;		/* TTY we are attached to */
+	/* data for manual vt switching */
+	struct vt_mode	vt_mode;
+	int		vt_pid;
+	int		vt_newvt;
+	wait_queue_head_t paste_wait;
 	/* mode flags */
 	unsigned int	vc_charset	: 1;	/* Character set G0 / G1 */
 	unsigned int	vc_s_charset	: 1;	/* Saved character set */
@@ -89,7 +95,6 @@
 	struct vc_data **vc_display_fg;		/* [!] Ptr to var holding fg console for this display */
 	unsigned long	vc_uni_pagedir;
 	unsigned long	*vc_uni_pagedir_loc;  /* [!] Location of uni_pagedir variable for this console */
-	struct vt_struct *vc_vt;
 	/* additional information is in vt_kern.h */
 };
 
diff -Nru a/include/linux/consolemap.h b/include/linux/consolemap.h
--- a/include/linux/consolemap.h	2005-03-11 12:51:51 -08:00
+++ b/include/linux/consolemap.h	2005-03-11 12:51:51 -08:00
@@ -11,5 +11,5 @@
 struct vc_data;
 
 extern unsigned char inverse_translate(struct vc_data *conp, int glyph);
-extern unsigned short *set_translate(int m,int currcons);
+extern unsigned short *set_translate(int m, struct vc_data *vc);
 extern int conv_uni_to_pc(struct vc_data *conp, long ucs);
diff -Nru a/include/linux/cpumask.h b/include/linux/cpumask.h
--- a/include/linux/cpumask.h	2005-03-11 12:51:42 -08:00
+++ b/include/linux/cpumask.h	2005-03-11 12:51:42 -08:00
@@ -10,6 +10,8 @@
  *
  * For details of cpumask_scnprintf() and cpumask_parse(),
  * see bitmap_scnprintf() and bitmap_parse() in lib/bitmap.c.
+ * For details of cpulist_scnprintf() and cpulist_parse(), see
+ * bitmap_scnlistprintf() and bitmap_parselist(), also in bitmap.c.
  *
  * The available cpumask operations are:
  *
@@ -46,6 +48,8 @@
  *
  * int cpumask_scnprintf(buf, len, mask) Format cpumask for printing
  * int cpumask_parse(ubuf, ulen, mask)	Parse ascii string as cpumask
+ * int cpulist_scnprintf(buf, len, mask) Format cpumask as list for printing
+ * int cpulist_parse(buf, map)		Parse ascii string as cpulist
  *
  * for_each_cpu_mask(cpu, mask)		for-loop cpu over mask
  *
@@ -268,12 +272,26 @@
 	return bitmap_scnprintf(buf, len, srcp->bits, nbits);
 }
 
-#define cpumask_parse(ubuf, ulen, src) \
-			__cpumask_parse((ubuf), (ulen), &(src), NR_CPUS)
+#define cpumask_parse(ubuf, ulen, dst) \
+			__cpumask_parse((ubuf), (ulen), &(dst), NR_CPUS)
 static inline int __cpumask_parse(const char __user *buf, int len,
 					cpumask_t *dstp, int nbits)
 {
 	return bitmap_parse(buf, len, dstp->bits, nbits);
+}
+
+#define cpulist_scnprintf(buf, len, src) \
+			__cpulist_scnprintf((buf), (len), &(src), NR_CPUS)
+static inline int __cpulist_scnprintf(char *buf, int len,
+					const cpumask_t *srcp, int nbits)
+{
+	return bitmap_scnlistprintf(buf, len, srcp->bits, nbits);
+}
+
+#define cpulist_parse(buf, dst) __cpulist_parse((buf), &(dst), NR_CPUS)
+static inline int __cpulist_parse(const char *buf, cpumask_t *dstp, int nbits)
+{
+	return bitmap_parselist(buf, dstp->bits, nbits);
 }
 
 #if NR_CPUS > 1
diff -Nru a/include/linux/cpuset.h b/include/linux/cpuset.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/linux/cpuset.h	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,64 @@
+#ifndef _LINUX_CPUSET_H
+#define _LINUX_CPUSET_H
+/*
+ *  cpuset interface
+ *
+ *  Copyright (C) 2003 BULL SA
+ *  Copyright (C) 2004 Silicon Graphics, Inc.
+ *
+ */
+
+#include <linux/sched.h>
+#include <linux/cpumask.h>
+#include <linux/nodemask.h>
+
+#ifdef CONFIG_CPUSETS
+
+extern int cpuset_init(void);
+extern void cpuset_init_smp(void);
+extern void cpuset_fork(struct task_struct *p);
+extern void cpuset_exit(struct task_struct *p);
+extern const cpumask_t cpuset_cpus_allowed(const struct task_struct *p);
+void cpuset_init_current_mems_allowed(void);
+void cpuset_update_current_mems_allowed(void);
+void cpuset_restrict_to_mems_allowed(unsigned long *nodes);
+int cpuset_zonelist_valid_mems_allowed(struct zonelist *zl);
+int cpuset_zone_allowed(struct zone *z);
+extern struct file_operations proc_cpuset_operations;
+extern char *cpuset_task_status_allowed(struct task_struct *task, char *buffer);
+
+#else /* !CONFIG_CPUSETS */
+
+static inline int cpuset_init(void) { return 0; }
+static inline void cpuset_init_smp(void) {}
+static inline void cpuset_fork(struct task_struct *p) {}
+static inline void cpuset_exit(struct task_struct *p) {}
+
+static inline const cpumask_t cpuset_cpus_allowed(struct task_struct *p)
+{
+	return cpu_possible_map;
+}
+
+static inline void cpuset_init_current_mems_allowed(void) {}
+static inline void cpuset_update_current_mems_allowed(void) {}
+static inline void cpuset_restrict_to_mems_allowed(unsigned long *nodes) {}
+
+static inline int cpuset_zonelist_valid_mems_allowed(struct zonelist *zl)
+{
+	return 1;
+}
+
+static inline int cpuset_zone_allowed(struct zone *z)
+{
+	return 1;
+}
+
+static inline char *cpuset_task_status_allowed(struct task_struct *task,
+							char *buffer)
+{
+	return buffer;
+}
+
+#endif /* !CONFIG_CPUSETS */
+
+#endif /* _LINUX_CPUSET_H */
diff -Nru a/include/linux/cryptohash.h b/include/linux/cryptohash.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/linux/cryptohash.h	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,12 @@
+#ifndef __CRYPTOHASH_H
+#define __CRYPTOHASH_H
+
+#define SHA_DIGEST_WORDS 5
+#define SHA_WORKSPACE_WORDS 80
+
+void sha_init(__u32 *buf);
+void sha_transform(__u32 *digest, const char *data, __u32 *W);
+
+__u32 half_md4_transform(__u32 buf[4], __u32 const in[8]);
+
+#endif
diff -Nru a/include/linux/dcache.h b/include/linux/dcache.h
--- a/include/linux/dcache.h	2005-03-11 12:51:52 -08:00
+++ b/include/linux/dcache.h	2005-03-11 12:51:52 -08:00
@@ -162,17 +162,16 @@
  * d_drop - drop a dentry
  * @dentry: dentry to drop
  *
- * d_drop() unhashes the entry from the parent
- * dentry hashes, so that it won't be found through
- * a VFS lookup any more. Note that this is different
- * from deleting the dentry - d_delete will try to
- * mark the dentry negative if possible, giving a
- * successful _negative_ lookup, while d_drop will
+ * d_drop() unhashes the entry from the parent dentry hashes, so that it won't
+ * be found through a VFS lookup any more. Note that this is different from
+ * deleting the dentry - d_delete will try to mark the dentry negative if
+ * possible, giving a successful _negative_ lookup, while d_drop will
  * just make the cache lookup fail.
  *
- * d_drop() is used mainly for stuff that wants
- * to invalidate a dentry for some reason (NFS
- * timeouts or autofs deletes).
+ * d_drop() is used mainly for stuff that wants to invalidate a dentry for some
+ * reason (NFS timeouts or autofs deletes).
+ *
+ * __d_drop requires dentry->d_lock.
  */
 
 static inline void __d_drop(struct dentry *dentry)
@@ -186,7 +185,9 @@
 static inline void d_drop(struct dentry *dentry)
 {
 	spin_lock(&dcache_lock);
+	spin_lock(&dentry->d_lock);
  	__d_drop(dentry);
+	spin_unlock(&dentry->d_lock);
 	spin_unlock(&dcache_lock);
 }
 
diff -Nru a/include/linux/device.h b/include/linux/device.h
--- a/include/linux/device.h	2005-03-11 12:51:51 -08:00
+++ b/include/linux/device.h	2005-03-11 12:51:51 -08:00
@@ -15,7 +15,6 @@
 #include <linux/ioport.h>
 #include <linux/kobject.h>
 #include <linux/list.h>
-#include <linux/spinlock.h>
 #include <linux/types.h>
 #include <linux/module.h>
 #include <linux/pm.h>
@@ -102,7 +101,7 @@
 	char			* name;
 	struct bus_type		* bus;
 
-	struct semaphore	unload_sem;
+	struct completion	unloaded;
 	struct kobject		kobj;
 	struct list_head	devices;
 
@@ -148,6 +147,7 @@
 	struct subsystem	subsys;
 	struct list_head	children;
 	struct list_head	interfaces;
+	struct semaphore	sem;	/* locks both the children and interfaces lists */
 
 	struct class_attribute		* class_attrs;
 	struct class_device_attribute	* class_dev_attrs;
@@ -184,6 +184,7 @@
 
 	struct kobject		kobj;
 	struct class		* class;	/* required */
+	dev_t			devt;		/* dev_t, creates the sysfs "dev" */
 	struct device		* dev;		/* not necessary, but nice to have */
 	void			* class_data;	/* class-specific data */
 
diff -Nru a/include/linux/dp83840.h b/include/linux/dp83840.h
--- a/include/linux/dp83840.h	2005-03-11 12:51:47 -08:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,41 +0,0 @@
-/*
- * linux/dp83840.h: definitions for DP83840 MII-compatible transceivers
- *
- * Copyright (C) 1996, 1999 David S. Miller (davem@redhat.com)
- */
-#ifndef __LINUX_DP83840_H
-#define __LINUX_DP83840_H
-
-#include <linux/mii.h>
-
-/*
- * Data sheets and programming docs for the DP83840 are available at
- * from http://www.national.com/
- *
- * The DP83840 is capable of both 10 and 100Mbps ethernet, in both
- * half and full duplex mode.  It also supports auto negotiation.
- *
- * But.... THIS THING IS A PAIN IN THE ASS TO PROGRAM!
- * Debugging eeprom burnt code is more fun than programming this chip!
- */
-
-/* First, the MII register numbers (actually DP83840 register numbers). */
-#define MII_CSCONFIG        0x17        /* CS configuration            */
-
-/* The Carrier Sense config register. */
-#define CSCONFIG_RESV1          0x0001  /* Unused...                   */
-#define CSCONFIG_LED4           0x0002  /* Pin for full-dplx LED4      */
-#define CSCONFIG_LED1           0x0004  /* Pin for conn-status LED1    */
-#define CSCONFIG_RESV2          0x0008  /* Unused...                   */
-#define CSCONFIG_TCVDISAB       0x0010  /* Turns off the transceiver   */
-#define CSCONFIG_DFBYPASS       0x0020  /* Bypass disconnect function  */
-#define CSCONFIG_GLFORCE        0x0040  /* Good link force for 100mbps */
-#define CSCONFIG_CLKTRISTATE    0x0080  /* Tristate 25m clock          */
-#define CSCONFIG_RESV3          0x0700  /* Unused...                   */
-#define CSCONFIG_ENCODE         0x0800  /* 1=MLT-3, 0=binary           */
-#define CSCONFIG_RENABLE        0x1000  /* Repeater mode enable        */
-#define CSCONFIG_TCDISABLE      0x2000  /* Disable timeout counter     */
-#define CSCONFIG_RESV4          0x4000  /* Unused...                   */
-#define CSCONFIG_NDISABLE       0x8000  /* Disable NRZI                */
-
-#endif /* __LINUX_DP83840_H */
diff -Nru a/include/linux/dqblk_xfs.h b/include/linux/dqblk_xfs.h
--- a/include/linux/dqblk_xfs.h	2005-03-11 12:51:47 -08:00
+++ b/include/linux/dqblk_xfs.h	2005-03-11 12:51:47 -08:00
@@ -28,6 +28,12 @@
  */
 
 #define XQM_CMD(x)	(('X'<<8)+(x))	/* note: forms first QCMD argument */
+#define XQM_COMMAND(x)	(((x) & (0xff<<8)) == ('X'<<8))	/* test if for XFS */
+
+#define XQM_USRQUOTA	0	/* system call user quota type */
+#define XQM_GRPQUOTA	1	/* system call group quota type */
+#define XQM_MAXQUOTAS	2
+
 #define Q_XQUOTAON	XQM_CMD(1)	/* enable accounting/enforcement */
 #define Q_XQUOTAOFF	XQM_CMD(2)	/* disable accounting/enforcement */
 #define Q_XGETQUOTA	XQM_CMD(3)	/* get disk limits and usage */
diff -Nru a/include/linux/elevator.h b/include/linux/elevator.h
--- a/include/linux/elevator.h	2005-03-11 12:51:41 -08:00
+++ b/include/linux/elevator.h	2005-03-11 12:51:41 -08:00
@@ -20,6 +20,7 @@
 
 typedef int (elevator_set_req_fn) (request_queue_t *, struct request *, int);
 typedef void (elevator_put_req_fn) (request_queue_t *, struct request *);
+typedef void (elevator_deactivate_req_fn) (request_queue_t *, struct request *);
 
 typedef int (elevator_init_fn) (request_queue_t *, elevator_t *);
 typedef void (elevator_exit_fn) (elevator_t *);
@@ -34,6 +35,7 @@
 	elevator_add_req_fn *elevator_add_req_fn;
 	elevator_remove_req_fn *elevator_remove_req_fn;
 	elevator_requeue_req_fn *elevator_requeue_req_fn;
+	elevator_deactivate_req_fn *elevator_deactivate_req_fn;
 
 	elevator_queue_empty_fn *elevator_queue_empty_fn;
 	elevator_completed_req_fn *elevator_completed_req_fn;
@@ -87,6 +89,7 @@
 extern void elv_merged_request(request_queue_t *, struct request *);
 extern void elv_remove_request(request_queue_t *, struct request *);
 extern void elv_requeue_request(request_queue_t *, struct request *);
+extern void elv_deactivate_request(request_queue_t *, struct request *);
 extern int elv_queue_empty(request_queue_t *);
 extern struct request *elv_next_request(struct request_queue *q);
 extern struct request *elv_former_request(request_queue_t *, struct request *);
diff -Nru a/include/linux/etherdevice.h b/include/linux/etherdevice.h
--- a/include/linux/etherdevice.h	2005-03-11 12:51:51 -08:00
+++ b/include/linux/etherdevice.h	2005-03-11 12:51:51 -08:00
@@ -47,6 +47,15 @@
 }
 
 /**
+ * is_zero_ether_addr - Determine if give Ethernet address is all
+ * zeros.
+ */
+static inline int is_zero_ether_addr(const u8 *addr)
+{
+	return !(addr[0] | addr[1] | addr[2] | addr[3] | addr[4] | addr[5]);
+}
+
+/**
  * is_valid_ether_addr - Determine if the given Ethernet address is valid
  * @addr: Pointer to a six-byte array containing the Ethernet address
  *
@@ -56,11 +65,9 @@
  *
  * Return true if the address is valid.
  */
-static inline int is_valid_ether_addr( const u8 *addr )
+static inline int is_valid_ether_addr(const u8 *addr)
 {
-	const char zaddr[6] = {0,};
-
-	return !(addr[0]&1) && memcmp( addr, zaddr, 6);
+	return !(addr[0]&1) && !is_zero_ether_addr(addr);
 }
 
 /**
diff -Nru a/include/linux/ext3_jbd.h b/include/linux/ext3_jbd.h
--- a/include/linux/ext3_jbd.h	2005-03-11 12:51:41 -08:00
+++ b/include/linux/ext3_jbd.h	2005-03-11 12:51:41 -08:00
@@ -111,9 +111,9 @@
 
 static inline int
 __ext3_journal_get_undo_access(const char *where, handle_t *handle,
-				struct buffer_head *bh, int *credits)
+				struct buffer_head *bh)
 {
-	int err = journal_get_undo_access(handle, bh, credits);
+	int err = journal_get_undo_access(handle, bh);
 	if (err)
 		ext3_journal_abort_handle(where, __FUNCTION__, bh, handle,err);
 	return err;
@@ -121,19 +121,18 @@
 
 static inline int
 __ext3_journal_get_write_access(const char *where, handle_t *handle,
-				struct buffer_head *bh, int *credits)
+				struct buffer_head *bh)
 {
-	int err = journal_get_write_access(handle, bh, credits);
+	int err = journal_get_write_access(handle, bh);
 	if (err)
 		ext3_journal_abort_handle(where, __FUNCTION__, bh, handle,err);
 	return err;
 }
 
 static inline void
-ext3_journal_release_buffer(handle_t *handle, struct buffer_head *bh,
-				int credits)
+ext3_journal_release_buffer(handle_t *handle, struct buffer_head *bh)
 {
-	journal_release_buffer(handle, bh, credits);
+	journal_release_buffer(handle, bh);
 }
 
 static inline int
@@ -176,12 +175,10 @@
 }
 
 
-#define ext3_journal_get_undo_access(handle, bh, credits) \
-	__ext3_journal_get_undo_access(__FUNCTION__, (handle), (bh), (credits))
+#define ext3_journal_get_undo_access(handle, bh) \
+	__ext3_journal_get_undo_access(__FUNCTION__, (handle), (bh))
 #define ext3_journal_get_write_access(handle, bh) \
-	__ext3_journal_get_write_access(__FUNCTION__, (handle), (bh), NULL)
-#define ext3_journal_get_write_access_credits(handle, bh, credits) \
-	__ext3_journal_get_write_access(__FUNCTION__, (handle), (bh), (credits))
+	__ext3_journal_get_write_access(__FUNCTION__, (handle), (bh))
 #define ext3_journal_revoke(handle, blocknr, bh) \
 	__ext3_journal_revoke(__FUNCTION__, (handle), (blocknr), (bh))
 #define ext3_journal_get_create_access(handle, bh) \
diff -Nru a/include/linux/fb.h b/include/linux/fb.h
--- a/include/linux/fb.h	2005-03-11 12:51:42 -08:00
+++ b/include/linux/fb.h	2005-03-11 12:51:42 -08:00
@@ -103,7 +103,10 @@
 #define FB_ACCEL_SIS_GLAMOUR_2  40	/* SiS 315, 650, 740		*/
 #define FB_ACCEL_SIS_XABRE      41	/* SiS 330 ("Xabre")		*/
 #define FB_ACCEL_I830           42      /* Intel 830M/845G/85x/865G     */
-
+#define FB_ACCEL_NV_10          43      /* nVidia Arch 10               */
+#define FB_ACCEL_NV_20          44      /* nVidia Arch 20               */
+#define FB_ACCEL_NV_30          45      /* nVidia Arch 30               */
+#define FB_ACCEL_NV_40          46      /* nVidia Arch 40               */
 #define FB_ACCEL_NEOMAGIC_NM2070 90	/* NeoMagic NM2070              */
 #define FB_ACCEL_NEOMAGIC_NM2090 91	/* NeoMagic NM2090              */
 #define FB_ACCEL_NEOMAGIC_NM2093 92	/* NeoMagic NM2093              */
@@ -490,6 +493,8 @@
 #define FB_EVENT_SET_CONSOLE_MAP        0x07
 /*      A display blank is requested       */
 #define FB_EVENT_BLANK                  0x08
+/*      Private modelist is to be replaced */
+#define FB_EVENT_NEW_MODELIST           0x09
 
 struct fb_event {
 	struct fb_info *info;
@@ -585,7 +590,7 @@
 			unsigned long arg, struct fb_info *info);
 
 	/* Handle 32bit compat ioctl (optional) */
-	int (*fb_compat_ioctl)(struct file *f, unsigned cmd, unsigned long arg,
+	long (*fb_compat_ioctl)(struct file *f, unsigned cmd, unsigned long arg,
 			       struct fb_info *info);
 
 	/* perform fb specific mmap */
@@ -712,8 +717,10 @@
 	struct fb_pixmap sprite;	/* Cursor hardware mapper */
 	struct fb_cmap cmap;		/* Current cmap */
 	struct list_head modelist;      /* mode list */
+	struct fb_videomode *mode;	/* current mode */
 	struct fb_ops *fbops;
 	struct device *device;
+	struct class_device *class_device; /* sysfs per device attrs */
 #ifdef CONFIG_FB_TILEBLITTING
 	struct fb_tile_ops *tileops;    /* Tile Blitting */
 #endif
@@ -821,8 +828,9 @@
 				u8 *dst, u32 d_pitch, u8 *src, u32 s_pitch,
 				u32 height);
 extern void fb_set_suspend(struct fb_info *info, int state);
-extern int fb_get_color_depth(struct fb_info *info);
+extern int fb_get_color_depth(struct fb_var_screeninfo *var);
 extern int fb_get_options(char *name, char **option);
+extern int fb_new_modelist(struct fb_info *info);
 
 extern struct fb_info *registered_fb[FB_MAX];
 extern int num_registered_fb;
@@ -830,6 +838,8 @@
 /* drivers/video/fbsysfs.c */
 extern struct fb_info *framebuffer_alloc(size_t size, struct device *dev);
 extern void framebuffer_release(struct fb_info *info);
+extern int fb_init_class_device(struct fb_info *fb_info);
+extern void fb_cleanup_class_device(struct fb_info *head);
 
 /* drivers/video/fbmon.c */
 #define FB_MAXTIMINGS		0
@@ -854,10 +864,7 @@
 extern int fb_validate_mode(const struct fb_var_screeninfo *var,
 			    struct fb_info *info);
 extern int fb_parse_edid(unsigned char *edid, struct fb_var_screeninfo *var);
-extern int fb_get_monitor_limits(unsigned char *edid, struct fb_monspecs *specs);
 extern void fb_edid_to_monspecs(unsigned char *edid, struct fb_monspecs *specs);
-extern int fb_get_monitor_limits(unsigned char *edid, struct fb_monspecs *specs);
-extern struct fb_videomode *fb_create_modedb(unsigned char *edid, int *dbsize);
 extern void fb_destroy_modedb(struct fb_videomode *modedb);
 
 /* drivers/video/modedb.c */
@@ -875,6 +882,8 @@
 					  struct list_head *head);
 extern struct fb_videomode *fb_find_best_mode(struct fb_var_screeninfo *var,
 					      struct list_head *head);
+extern struct fb_videomode *fb_find_nearest_mode(struct fb_var_screeninfo *var,
+						 struct list_head *head);
 extern void fb_destroy_modelist(struct list_head *head);
 extern void fb_videomode_to_modelist(struct fb_videomode *modedb, int num,
 				     struct list_head *head);
diff -Nru a/include/linux/fs.h b/include/linux/fs.h
--- a/include/linux/fs.h	2005-03-11 12:51:42 -08:00
+++ b/include/linux/fs.h	2005-03-11 12:51:42 -08:00
@@ -129,6 +129,7 @@
 #define S_DIRSYNC	64	/* Directory modifications are synchronous */
 #define S_NOCMTIME	128	/* Do not update file c/mtime */
 #define S_SWAPFILE	256	/* Do not truncate: swapon got its bmaps */
+#define S_PRIVATE	512	/* Inode is fs-internal */
 
 /*
  * Note that nosuid etc flags are inode-specific: setting some file-system
@@ -162,6 +163,7 @@
 #define IS_DEADDIR(inode)	((inode)->i_flags & S_DEAD)
 #define IS_NOCMTIME(inode)	((inode)->i_flags & S_NOCMTIME)
 #define IS_SWAPFILE(inode)	((inode)->i_flags & S_SWAPFILE)
+#define IS_PRIVATE(inode)	((inode)->i_flags & S_PRIVATE)
 
 /* the read-only stuff doesn't really belong here, but any other place is
    probably as bad and I don't want to create yet another include file. */
@@ -335,7 +337,7 @@
 struct address_space {
 	struct inode		*host;		/* owner: inode, block_device */
 	struct radix_tree_root	page_tree;	/* radix tree of all pages */
-	spinlock_t		tree_lock;	/* and spinlock protecting it */
+	rwlock_t		tree_lock;	/* and rwlock protecting it */
 	unsigned int		i_mmap_writable;/* count VM_SHARED mappings */
 	struct prio_tree_root	i_mmap;		/* tree of private and shared mappings */
 	struct list_head	i_mmap_nonlinear;/*list VM_NONLINEAR mappings */
@@ -647,6 +649,8 @@
 	void (*fl_copy_lock)(struct file_lock *, struct file_lock *);
 	void (*fl_release_private)(struct file_lock *);
 	void (*fl_break)(struct file_lock *);
+	int (*fl_mylease)(struct file_lock *, struct file_lock *);
+	int (*fl_change)(struct file_lock **, int);
 };
 
 /* that will die - we need it for nfs_lock_info */
@@ -713,7 +717,7 @@
 extern int __break_lease(struct inode *inode, unsigned int flags);
 extern void lease_get_mtime(struct inode *, struct timespec *time);
 extern int setlease(struct file *, long, struct file_lock **);
-extern void remove_lease(struct file_lock *);
+extern int lease_modify(struct file_lock **, int);
 extern int lock_may_read(struct inode *, loff_t start, unsigned long count);
 extern int lock_may_write(struct inode *, loff_t start, unsigned long count);
 extern void steal_locks(fl_owner_t from);
@@ -1353,11 +1357,15 @@
 		invalidate_inode_pages(inode->i_mapping);
 }
 extern int invalidate_inode_pages2(struct address_space *mapping);
+extern int invalidate_inode_pages2_range(struct address_space *mapping,
+					 pgoff_t start, pgoff_t end);
 extern int write_inode_now(struct inode *, int);
 extern int filemap_fdatawrite(struct address_space *);
 extern int filemap_flush(struct address_space *);
 extern int filemap_fdatawait(struct address_space *);
 extern int filemap_write_and_wait(struct address_space *mapping);
+extern int filemap_write_and_wait_range(struct address_space *mapping,
+				        loff_t lstart, loff_t lend);
 extern void sync_supers(void);
 extern void sync_filesystems(int wait);
 extern void emergency_sync(void);
diff -Nru a/include/linux/gameport.h b/include/linux/gameport.h
--- a/include/linux/gameport.h	2005-03-11 12:51:52 -08:00
+++ b/include/linux/gameport.h	2005-03-11 12:51:52 -08:00
@@ -10,19 +10,14 @@
  */
 
 #include <asm/io.h>
-#include <linux/input.h>
 #include <linux/list.h>
-
-struct gameport;
+#include <linux/device.h>
 
 struct gameport {
 
-	void *private;	/* Private pointer for joystick drivers */
-	void *driver;	/* Private pointer for gameport drivers */
-	char *name;
-	char *phys;
-
-	struct input_id id;
+	void *port_data;	/* Private pointer for gameport drivers */
+	char name[32];
+	char phys[32];
 
 	int io;
 	int speed;
@@ -35,36 +30,105 @@
 	int (*open)(struct gameport *, int);
 	void (*close)(struct gameport *);
 
-	struct gameport_dev *dev;
+	struct timer_list poll_timer;
+	unsigned int poll_interval;	/* in msecs */
+	spinlock_t timer_lock;
+	unsigned int poll_cnt;
+	void (*poll_handler)(struct gameport *);
+
+	struct gameport *parent, *child;
+
+	struct gameport_driver *drv;
+	struct semaphore drv_sem;	/* protects serio->drv so attributes can pin driver */
+
+	struct device dev;
+	unsigned int registered;	/* port has been fully registered with driver core */
 
 	struct list_head node;
 };
+#define to_gameport_port(d)	container_of(d, struct gameport, dev)
 
-struct gameport_dev {
+struct gameport_driver {
 
 	void *private;
-	char *name;
+	char *description;
 
-	void (*connect)(struct gameport *, struct gameport_dev *dev);
+	int (*connect)(struct gameport *, struct gameport_driver *drv);
+	int (*reconnect)(struct gameport *);
 	void (*disconnect)(struct gameport *);
 
-	struct list_head node;
+	struct device_driver driver;
+
+	unsigned int ignore;
 };
+#define to_gameport_driver(d)	container_of(d, struct gameport_driver, driver)
 
-int gameport_open(struct gameport *gameport, struct gameport_dev *dev, int mode);
+int gameport_open(struct gameport *gameport, struct gameport_driver *drv, int mode);
 void gameport_close(struct gameport *gameport);
 void gameport_rescan(struct gameport *gameport);
 
-#if defined(CONFIG_GAMEPORT) || defined(CONFIG_GAMEPORT_MODULE)
-void gameport_register_port(struct gameport *gameport);
+void __gameport_register_port(struct gameport *gameport, struct module *owner);
+static inline void gameport_register_port(struct gameport *gameport)
+{
+	__gameport_register_port(gameport, THIS_MODULE);
+}
+
 void gameport_unregister_port(struct gameport *gameport);
-#else
-static inline void gameport_register_port(struct gameport *gameport) { return; }
-static inline void gameport_unregister_port(struct gameport *gameport) { return; }
-#endif
 
-void gameport_register_device(struct gameport_dev *dev);
-void gameport_unregister_device(struct gameport_dev *dev);
+static inline struct gameport *gameport_allocate_port(void)
+{
+	struct gameport *gameport = kcalloc(1, sizeof(struct gameport), GFP_KERNEL);
+
+	return gameport;
+}
+
+static inline void gameport_free_port(struct gameport *gameport)
+{
+	kfree(gameport);
+}
+
+static inline void gameport_set_name(struct gameport *gameport, const char *name)
+{
+	strlcpy(gameport->name, name, sizeof(gameport->name));
+}
+
+void gameport_set_phys(struct gameport *gameport, const char *fmt, ...)
+	__attribute__ ((format (printf, 2, 3)));
+
+/*
+ * Use the following fucntions to manipulate gameport's per-port
+ * driver-specific data.
+ */
+static inline void *gameport_get_drvdata(struct gameport *gameport)
+{
+	return dev_get_drvdata(&gameport->dev);
+}
+
+static inline void gameport_set_drvdata(struct gameport *gameport, void *data)
+{
+	dev_set_drvdata(&gameport->dev, data);
+}
+
+/*
+ * Use the following fucntions to pin gameport's driver in process context
+ */
+static inline int gameport_pin_driver(struct gameport *gameport)
+{
+	return down_interruptible(&gameport->drv_sem);
+}
+
+static inline void gameport_unpin_driver(struct gameport *gameport)
+{
+	up(&gameport->drv_sem);
+}
+
+void __gameport_register_driver(struct gameport_driver *drv, struct module *owner);
+static inline void gameport_register_driver(struct gameport_driver *drv)
+{
+	__gameport_register_driver(drv, THIS_MODULE);
+}
+
+void gameport_unregister_driver(struct gameport_driver *drv);
 
 #define GAMEPORT_MODE_DISABLED		0
 #define GAMEPORT_MODE_RAW		1
@@ -81,7 +145,7 @@
 #define GAMEPORT_ID_VENDOR_GRAVIS	0x0009
 #define GAMEPORT_ID_VENDOR_GUILLEMOT	0x000a
 
-static __inline__ void gameport_trigger(struct gameport *gameport)
+static inline void gameport_trigger(struct gameport *gameport)
 {
 	if (gameport->trigger)
 		gameport->trigger(gameport);
@@ -89,7 +153,7 @@
 		outb(0xff, gameport->io);
 }
 
-static __inline__ unsigned char gameport_read(struct gameport *gameport)
+static inline unsigned char gameport_read(struct gameport *gameport)
 {
 	if (gameport->read)
 		return gameport->read(gameport);
@@ -97,7 +161,7 @@
 		return inb(gameport->io);
 }
 
-static __inline__ int gameport_cooked_read(struct gameport *gameport, int *axes, int *buttons)
+static inline int gameport_cooked_read(struct gameport *gameport, int *axes, int *buttons)
 {
 	if (gameport->cooked_read)
 		return gameport->cooked_read(gameport, axes, buttons);
@@ -105,7 +169,7 @@
 		return -1;
 }
 
-static __inline__ int gameport_calibrate(struct gameport *gameport, int *axes, int *max)
+static inline int gameport_calibrate(struct gameport *gameport, int *axes, int *max)
 {
 	if (gameport->calibrate)
 		return gameport->calibrate(gameport, axes, max);
@@ -113,9 +177,22 @@
 		return -1;
 }
 
-static __inline__ int gameport_time(struct gameport *gameport, int time)
+static inline int gameport_time(struct gameport *gameport, int time)
 {
 	return (time * gameport->speed) / 1000;
 }
+
+static inline void gameport_set_poll_handler(struct gameport *gameport, void (*handler)(struct gameport *))
+{
+	gameport->poll_handler = handler;
+}
+
+static inline void gameport_set_poll_interval(struct gameport *gameport, unsigned int msecs)
+{
+	gameport->poll_interval = msecs;
+}
+
+void gameport_start_polling(struct gameport *gameport);
+void gameport_stop_polling(struct gameport *gameport);
 
 #endif
diff -Nru a/include/linux/hiddev.h b/include/linux/hiddev.h
--- a/include/linux/hiddev.h	2005-03-11 12:51:42 -08:00
+++ b/include/linux/hiddev.h	2005-03-11 12:51:42 -08:00
@@ -201,8 +201,8 @@
  *		ioctl(fd, HIDIOCGUSAGE, &uref);
  *          }
  *	}
- *	uref.report_id |= HID_REPORT_ID_NEXT;
- *	ret = ioctl(fd, HIDIOCGREPORTINFO, &uref);
+ *	rinfo.report_id |= HID_REPORT_ID_NEXT;
+ *	ret = ioctl(fd, HIDIOCGREPORTINFO, &rinfo);
  *  }
  */
 
diff -Nru a/include/linux/i2c-id.h b/include/linux/i2c-id.h
--- a/include/linux/i2c-id.h	2005-03-11 12:51:52 -08:00
+++ b/include/linux/i2c-id.h	2005-03-11 12:51:52 -08:00
@@ -20,8 +20,6 @@
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.		     */
 /* ------------------------------------------------------------------------- */
 
-/* $Id: i2c-id.h,v 1.68 2003/02/25 02:55:18 mds Exp $ */
-
 #ifndef LINUX_I2C_ID_H
 #define LINUX_I2C_ID_H
 
@@ -196,11 +194,15 @@
 #define I2C_ALGO_OCP    0x120000	/* IBM or otherwise On-chip I2C algorithm */
 #define I2C_ALGO_BITHS	0x130000	/* enhanced bit style adapters	*/
 #define I2C_ALGO_IOP3XX	0x140000	/* XSCALE IOP3XX On-chip I2C alg */
-#define I2C_ALGO_PCA	0x150000	/* PCA 9564 style adapters	*/
-
 #define I2C_ALGO_SIBYTE 0x150000	/* Broadcom SiByte SOCs		*/
-#define I2C_ALGO_SGI	0x160000        /* SGI algorithm                */
-#define I2C_ALGO_AU1550	0x170000        /* Au1550 PSC algorithm		*/
+#define I2C_ALGO_SGI	0x160000	/* SGI algorithm		*/
+
+#define I2C_ALGO_USB	0x170000	/* USB algorithm		*/
+#define I2C_ALGO_VIRT	0x180000	/* Virtual bus adapter		*/
+
+#define I2C_ALGO_MV64XXX 0x190000	/* Marvell mv64xxx i2c ctlr	*/
+#define I2C_ALGO_PCA	0x1a0000	/* PCA 9564 style adapters	*/
+#define I2C_ALGO_AU1550	0x1b0000        /* Au1550 PSC algorithm		*/
 
 #define I2C_ALGO_EXP	0x800000	/* experimental			*/
 
@@ -240,6 +242,7 @@
 #define I2C_HW_B_IXP4XX 0x17	/* GPIO on IXP4XX systems		*/
 #define I2C_HW_B_S3VIA	0x18	/* S3Via ProSavage adapter		*/
 #define I2C_HW_B_ZR36067 0x19	/* Zoran-36057/36067 based boards	*/
+#define I2C_HW_B_PCILYNX 0x1a	/* TI PCILynx I2C adapter		*/
 #define I2C_HW_B_CX2388x 0x1b	/* connexant 2388x based tv cards	*/
 
 /* --- PCF 8584 based algorithms					*/
@@ -309,5 +312,8 @@
 
 /* --- MCP107 adapter */
 #define I2C_HW_MPC107 0x00
+
+/* --- Marvell mv64xxx i2c adapter */
+#define I2C_HW_MV64XXX 0x00
 
 #endif /* LINUX_I2C_ID_H */
diff -Nru a/include/linux/i2c.h b/include/linux/i2c.h
--- a/include/linux/i2c.h	2005-03-11 12:51:41 -08:00
+++ b/include/linux/i2c.h	2005-03-11 12:51:41 -08:00
@@ -55,7 +55,7 @@
 
 /* Transfer num messages.
  */
-extern int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[],int num);
+extern int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num);
 
 /*
  * Some adapter types (i.e. PCF 8584 based ones) may support slave behaviuor. 
@@ -134,8 +134,6 @@
 };
 #define to_i2c_driver(d) container_of(d, struct i2c_driver, driver)
 
-extern struct bus_type i2c_bus_type;
-
 #define I2C_NAME_SIZE	50
 
 /*
@@ -144,7 +142,6 @@
  * function is mainly used for lookup & other admin. functions.
  */
 struct i2c_client {
-	int id;
 	unsigned int flags;		/* div., see below		*/
 	unsigned int addr;		/* chip address - NOTE: 7bit 	*/
 					/* addresses are stored in the	*/
@@ -190,11 +187,11 @@
 	char name[32];				/* textual description 	*/
 	unsigned int id;
 
-	/* If an adapter algorithm can't to I2C-level access, set master_xfer
+	/* If an adapter algorithm can't do I2C-level access, set master_xfer
 	   to NULL. If an adapter algorithm can do SMBus access, set 
 	   smbus_xfer. If set to NULL, the SMBus protocol is simulated
 	   using common I2C messages */
-	int (*master_xfer)(struct i2c_adapter *adap,struct i2c_msg msgs[], 
+	int (*master_xfer)(struct i2c_adapter *adap,struct i2c_msg *msgs, 
 	                   int num);
 	int (*smbus_xfer) (struct i2c_adapter *adap, u16 addr, 
 	                   unsigned short flags, char read_write,
@@ -302,8 +299,8 @@
 };
 
 /* Internal numbers to terminate lists */
-#define I2C_CLIENT_END		0xfffe
-#define I2C_CLIENT_ISA_END	0xfffefffe
+#define I2C_CLIENT_END		0xfffeU
+#define I2C_CLIENT_ISA_END	0xfffefffeU
 
 /* The numbers to use to set I2C bus address */
 #define ANY_I2C_BUS		0xffff
@@ -423,22 +420,22 @@
 #define I2C_FUNC_SMBUS_READ_BLOCK_DATA_PEC  0x40000000 /* SMBus 2.0 */
 #define I2C_FUNC_SMBUS_WRITE_BLOCK_DATA_PEC 0x80000000 /* SMBus 2.0 */
 
-#define I2C_FUNC_SMBUS_BYTE I2C_FUNC_SMBUS_READ_BYTE | \
-                            I2C_FUNC_SMBUS_WRITE_BYTE
-#define I2C_FUNC_SMBUS_BYTE_DATA I2C_FUNC_SMBUS_READ_BYTE_DATA | \
-                                 I2C_FUNC_SMBUS_WRITE_BYTE_DATA
-#define I2C_FUNC_SMBUS_WORD_DATA I2C_FUNC_SMBUS_READ_WORD_DATA | \
-                                 I2C_FUNC_SMBUS_WRITE_WORD_DATA
-#define I2C_FUNC_SMBUS_BLOCK_DATA I2C_FUNC_SMBUS_READ_BLOCK_DATA | \
-                                  I2C_FUNC_SMBUS_WRITE_BLOCK_DATA
-#define I2C_FUNC_SMBUS_I2C_BLOCK I2C_FUNC_SMBUS_READ_I2C_BLOCK | \
-                                  I2C_FUNC_SMBUS_WRITE_I2C_BLOCK
-#define I2C_FUNC_SMBUS_I2C_BLOCK_2 I2C_FUNC_SMBUS_READ_I2C_BLOCK_2 | \
-                                   I2C_FUNC_SMBUS_WRITE_I2C_BLOCK_2
-#define I2C_FUNC_SMBUS_BLOCK_DATA_PEC I2C_FUNC_SMBUS_READ_BLOCK_DATA_PEC | \
-                                      I2C_FUNC_SMBUS_WRITE_BLOCK_DATA_PEC
-#define I2C_FUNC_SMBUS_WORD_DATA_PEC  I2C_FUNC_SMBUS_READ_WORD_DATA_PEC | \
-                                      I2C_FUNC_SMBUS_WRITE_WORD_DATA_PEC
+#define I2C_FUNC_SMBUS_BYTE (I2C_FUNC_SMBUS_READ_BYTE | \
+                             I2C_FUNC_SMBUS_WRITE_BYTE)
+#define I2C_FUNC_SMBUS_BYTE_DATA (I2C_FUNC_SMBUS_READ_BYTE_DATA | \
+                                  I2C_FUNC_SMBUS_WRITE_BYTE_DATA)
+#define I2C_FUNC_SMBUS_WORD_DATA (I2C_FUNC_SMBUS_READ_WORD_DATA | \
+                                  I2C_FUNC_SMBUS_WRITE_WORD_DATA)
+#define I2C_FUNC_SMBUS_BLOCK_DATA (I2C_FUNC_SMBUS_READ_BLOCK_DATA | \
+                                   I2C_FUNC_SMBUS_WRITE_BLOCK_DATA)
+#define I2C_FUNC_SMBUS_I2C_BLOCK (I2C_FUNC_SMBUS_READ_I2C_BLOCK | \
+                                  I2C_FUNC_SMBUS_WRITE_I2C_BLOCK)
+#define I2C_FUNC_SMBUS_I2C_BLOCK_2 (I2C_FUNC_SMBUS_READ_I2C_BLOCK_2 | \
+                                    I2C_FUNC_SMBUS_WRITE_I2C_BLOCK_2)
+#define I2C_FUNC_SMBUS_BLOCK_DATA_PEC (I2C_FUNC_SMBUS_READ_BLOCK_DATA_PEC | \
+                                       I2C_FUNC_SMBUS_WRITE_BLOCK_DATA_PEC)
+#define I2C_FUNC_SMBUS_WORD_DATA_PEC  (I2C_FUNC_SMBUS_READ_WORD_DATA_PEC | \
+                                       I2C_FUNC_SMBUS_WRITE_WORD_DATA_PEC)
 
 #define I2C_FUNC_SMBUS_READ_BYTE_PEC		I2C_FUNC_SMBUS_READ_BYTE_DATA
 #define I2C_FUNC_SMBUS_WRITE_BYTE_PEC		I2C_FUNC_SMBUS_WRITE_BYTE_DATA
@@ -447,14 +444,14 @@
 #define I2C_FUNC_SMBUS_BYTE_PEC			I2C_FUNC_SMBUS_BYTE_DATA
 #define I2C_FUNC_SMBUS_BYTE_DATA_PEC		I2C_FUNC_SMBUS_WORD_DATA
 
-#define I2C_FUNC_SMBUS_EMUL I2C_FUNC_SMBUS_QUICK | \
-                            I2C_FUNC_SMBUS_BYTE | \
-                            I2C_FUNC_SMBUS_BYTE_DATA | \
-                            I2C_FUNC_SMBUS_WORD_DATA | \
-                            I2C_FUNC_SMBUS_PROC_CALL | \
-                            I2C_FUNC_SMBUS_WRITE_BLOCK_DATA | \
-                            I2C_FUNC_SMBUS_WRITE_BLOCK_DATA_PEC | \
-                            I2C_FUNC_SMBUS_I2C_BLOCK
+#define I2C_FUNC_SMBUS_EMUL (I2C_FUNC_SMBUS_QUICK | \
+                             I2C_FUNC_SMBUS_BYTE | \
+                             I2C_FUNC_SMBUS_BYTE_DATA | \
+                             I2C_FUNC_SMBUS_WORD_DATA | \
+                             I2C_FUNC_SMBUS_PROC_CALL | \
+                             I2C_FUNC_SMBUS_WRITE_BLOCK_DATA | \
+                             I2C_FUNC_SMBUS_WRITE_BLOCK_DATA_PEC | \
+                             I2C_FUNC_SMBUS_I2C_BLOCK)
 
 /* 
  * Data for SMBus Messages 
diff -Nru a/include/linux/ibmtr.h b/include/linux/ibmtr.h
--- a/include/linux/ibmtr.h	2005-03-11 12:51:42 -08:00
+++ b/include/linux/ibmtr.h	2005-03-11 12:51:42 -08:00
@@ -169,7 +169,7 @@
 
 struct tok_info {
 	unsigned char irq;
-	void *mmio;
+	void __iomem *mmio;
 	unsigned char hw_address[32];
 	unsigned char adapter_type;
 	unsigned char data_rate;
@@ -192,12 +192,13 @@
 	/* Additions by Peter De Schrijver */
 	unsigned char page_mask;          /* mask to select RAM page to Map*/
 	unsigned char mapped_ram_size;    /* size of RAM page */
-	__u32 sram_virt;                  /* Shared memory base address */
-	__u32 init_srb;               /* Initial System Request Block address */
-	__u32 srb;                        /* System Request Block address */
-	__u32 ssb;                        /* System Status Block address */
-	__u32 arb;                        /* Adapter Request Block address */
-	__u32 asb;                        /* Adapter Status Block address */
+	__u32 sram_phys;          /* Shared memory base address */
+	void __iomem *sram_virt;          /* Shared memory base address */
+	void __iomem *init_srb;   /* Initial System Request Block address */
+	void __iomem *srb;                /* System Request Block address */
+	void __iomem *ssb;                /* System Status Block address */
+	void __iomem *arb;                /* Adapter Request Block address */
+	void __iomem *asb;                /* Adapter Status Block address */
         __u8  init_srb_page;
         __u8  srb_page;
         __u8  ssb_page;
diff -Nru a/include/linux/ide.h b/include/linux/ide.h
--- a/include/linux/ide.h	2005-03-11 12:51:42 -08:00
+++ b/include/linux/ide.h	2005-03-11 12:51:42 -08:00
@@ -718,6 +718,7 @@
 					 */
 	unsigned scsi		: 1;	/* 0=default, 1=ide-scsi emulation */
 	unsigned sleeping	: 1;	/* 1=sleeping & sleep field valid */
+	unsigned post_reset	: 1;
 
         u8	quirk_list;	/* considered quirky, set for a specific host */
         u8	init_speed;	/* transfer rate set at boot */
@@ -740,7 +741,6 @@
 	u8	sect;		/* "real" sectors per track */
 	u8	bios_head;	/* BIOS/fdisk/LILO number of heads */
 	u8	bios_sect;	/* BIOS/fdisk/LILO sectors per track */
-	u8	doing_barrier;	/* state, 1=currently doing flush */
 
 	unsigned int	bios_cyl;	/* BIOS/fdisk/LILO number of cyls */
 	unsigned int	cyl;		/* "real" number of cyls */
@@ -1098,15 +1098,10 @@
 	ide_startstop_t	(*error)(ide_drive_t *, struct request *rq, u8, u8);
 	ide_startstop_t	(*abort)(ide_drive_t *, struct request *rq);
 	int		(*ioctl)(ide_drive_t *, struct inode *, struct file *, unsigned int, unsigned long);
-	void		(*pre_reset)(ide_drive_t *);
-	sector_t	(*capacity)(ide_drive_t *);
-	ide_startstop_t	(*special)(ide_drive_t *);
 	ide_proc_entry_t	*proc;
 	int		(*attach)(ide_drive_t *);
 	void		(*ata_prebuilder)(ide_drive_t *);
 	void		(*atapi_prebuilder)(ide_drive_t *);
-	ide_startstop_t	(*start_power_step)(ide_drive_t *, struct request *);
-	void		(*complete_power_step)(ide_drive_t *, struct request *, u8, u8);
 	struct device_driver	gen_driver;
 	struct list_head drives;
 	struct list_head drivers;
@@ -1130,6 +1125,7 @@
 extern int noautodma;
 
 extern int ide_end_request (ide_drive_t *drive, int uptodate, int nrsecs);
+extern int __ide_end_request (ide_drive_t *drive, struct request *rq, int uptodate, int nrsecs);
 
 /*
  * This is used on exit from the driver to designate the next irq handler
diff -Nru a/include/linux/if_ec.h b/include/linux/if_ec.h
--- a/include/linux/if_ec.h	2005-03-11 12:51:41 -08:00
+++ b/include/linux/if_ec.h	2005-03-11 12:51:41 -08:00
@@ -47,8 +47,9 @@
   unsigned char port;
 };
 
-struct econet_opt
-{
+struct econet_sock {
+  /* struct sock has to be the first member of econet_sock */
+  struct sock	sk;
   unsigned char cb;
   unsigned char port;
   unsigned char station;
@@ -56,7 +57,10 @@
   unsigned short num;
 };
 
-#define ec_sk(__sk) ((struct econet_opt *)(__sk)->sk_protinfo)
+static inline struct econet_sock *ec_sk(const struct sock *sk)
+{
+	return (struct econet_sock *)sk;
+}
 
 struct ec_device
 {
diff -Nru a/include/linux/if_pppox.h b/include/linux/if_pppox.h
--- a/include/linux/if_pppox.h	2005-03-11 12:51:41 -08:00
+++ b/include/linux/if_pppox.h	2005-03-11 12:51:41 -08:00
@@ -119,10 +119,13 @@
 					     relayed to (PPPoE relaying) */
 };
 
-struct pppox_opt {
+#include <net/sock.h>
+
+struct pppox_sock {
+	/* struct sock must be the first member of pppox_sock */
+	struct sock		sk;
 	struct ppp_channel	chan;
-	struct sock		*sk;
-	struct pppox_opt	*next;	  /* for hash table */
+	struct pppox_sock	*next;	  /* for hash table */
 	union {
 		struct pppoe_opt pppoe;
 	} proto;
@@ -132,7 +135,15 @@
 #define pppoe_pa	proto.pppoe.pa
 #define pppoe_relay	proto.pppoe.relay
 
-#define pppox_sk(__sk) ((struct pppox_opt *)(__sk)->sk_protinfo)
+static inline struct pppox_sock *pppox_sk(struct sock *sk)
+{
+	return (struct pppox_sock *)sk;
+}
+
+static inline struct sock *sk_pppox(struct pppox_sock *po)
+{
+	return (struct sock *)po;
+}
 
 struct module;
 
diff -Nru a/include/linux/init_task.h b/include/linux/init_task.h
--- a/include/linux/init_task.h	2005-03-11 12:51:41 -08:00
+++ b/include/linux/init_task.h	2005-03-11 12:51:41 -08:00
@@ -51,6 +51,7 @@
 		.list = LIST_HEAD_INIT(sig.shared_pending.list),	\
 		.signal =  {{0}}}, \
 	.posix_timers	 = LIST_HEAD_INIT(sig.posix_timers),		\
+	.cpu_timers	= INIT_CPU_TIMERS(sig.cpu_timers),		\
 	.rlim		= INIT_RLIMITS,					\
 }
 
@@ -89,9 +90,6 @@
 	.children	= LIST_HEAD_INIT(tsk.children),			\
 	.sibling	= LIST_HEAD_INIT(tsk.sibling),			\
 	.group_leader	= &tsk,						\
-	.real_timer	= {						\
-		.function	= it_real_fn				\
-	},								\
 	.group_info	= &init_groups,					\
 	.cap_effective	= CAP_INIT_EFF_SET,				\
 	.cap_inheritable = CAP_INIT_INH_SET,				\
@@ -112,8 +110,16 @@
 	.proc_lock	= SPIN_LOCK_UNLOCKED,				\
 	.switch_lock	= SPIN_LOCK_UNLOCKED,				\
 	.journal_info	= NULL,						\
+	.cpu_timers	= INIT_CPU_TIMERS(tsk.cpu_timers),		\
 }
 
+
+#define INIT_CPU_TIMERS(cpu_timers)					\
+{									\
+	LIST_HEAD_INIT(cpu_timers[0]),					\
+	LIST_HEAD_INIT(cpu_timers[1]),					\
+	LIST_HEAD_INIT(cpu_timers[2]),					\
+}
 
 
 #endif
diff -Nru a/include/linux/input.h b/include/linux/input.h
--- a/include/linux/input.h	2005-03-11 12:51:43 -08:00
+++ b/include/linux/input.h	2005-03-11 12:51:43 -08:00
@@ -771,7 +771,7 @@
 #include <linux/fs.h>
 #include <linux/timer.h>
 
-#define NBITS(x) ((((x)-1)/BITS_PER_LONG)+1)
+#define NBITS(x) (((x)/BITS_PER_LONG)+1)
 #define BIT(x)	(1UL<<((x)%BITS_PER_LONG))
 #define LONG(x) ((x)/BITS_PER_LONG)
 
diff -Nru a/include/linux/ioc4_common.h b/include/linux/ioc4_common.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/linux/ioc4_common.h	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,21 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (c) 2005 Silicon Graphics, Inc.  All Rights Reserved.
+ */
+
+#ifndef _LINUX_IOC4_COMMON_H
+#define _LINUX_IOC4_COMMON_H
+
+/* prototypes */
+
+int ioc4_serial_init(void);
+
+int ioc4_serial_attach_one(struct pci_dev *pdev, const struct
+				pci_device_id *pci_id);
+int ioc4_ide_attach_one(struct pci_dev *pdev, const struct
+				pci_device_id *pci_id);
+
+#endif	/* _LINUX_IOC4_COMMON_H */
diff -Nru a/include/linux/ip.h b/include/linux/ip.h
--- a/include/linux/ip.h	2005-03-11 12:51:42 -08:00
+++ b/include/linux/ip.h	2005-03-11 12:51:42 -08:00
@@ -152,6 +152,7 @@
 };
 
 #define IPCORK_OPT	1	/* ip-options has been held in ipcork.opt */
+#define IPCORK_ALLFRAG	2	/* always fragment (for ipv6 for now) */
 
 static inline struct inet_sock *inet_sk(const struct sock *sk)
 {
diff -Nru a/include/linux/ipmi_smi.h b/include/linux/ipmi_smi.h
--- a/include/linux/ipmi_smi.h	2005-03-11 12:51:52 -08:00
+++ b/include/linux/ipmi_smi.h	2005-03-11 12:51:52 -08:00
@@ -104,13 +104,22 @@
 	/* Called to poll for work to do.  This is so upper layers can
 	   poll for operations during things like crash dumps. */
 	void (*poll)(void *send_info);
+
+	/* Tell the handler that we are using it/not using it.  The
+	   message handler get the modules that this handler belongs
+	   to; this function lets the SMI claim any modules that it
+	   uses.  These may be NULL if this is not required. */
+	int (*inc_usecount)(void *send_info);
+	void (*dec_usecount)(void *send_info);
 };
 
-/* Add a low-level interface to the IPMI driver. */
+/* Add a low-level interface to the IPMI driver.  Note that if the
+   interface doesn't know its slave address, it should pass in zero. */
 int ipmi_register_smi(struct ipmi_smi_handlers *handlers,
 		      void                     *send_info,
 		      unsigned char            version_major,
 		      unsigned char            version_minor,
+		      unsigned char            slave_addr,
 		      ipmi_smi_t               *intf);
 
 /*
diff -Nru a/include/linux/jbd.h b/include/linux/jbd.h
--- a/include/linux/jbd.h	2005-03-11 12:51:50 -08:00
+++ b/include/linux/jbd.h	2005-03-11 12:51:50 -08:00
@@ -789,6 +789,12 @@
 	struct jbd_revoke_table_s *j_revoke_table[2];
 
 	/*
+	 * array of bhs for journal_commit_transaction
+	 */
+	struct buffer_head	**j_wbuf;
+	int			j_wbufsize;
+
+	/*
 	 * An opaque pointer to fs-private information.  ext3 puts its
 	 * superblock pointer here
 	 */
@@ -867,15 +873,12 @@
 extern handle_t *journal_start(journal_t *, int nblocks);
 extern int	 journal_restart (handle_t *, int nblocks);
 extern int	 journal_extend (handle_t *, int nblocks);
-extern int	 journal_get_write_access(handle_t *, struct buffer_head *,
-						int *credits);
+extern int	 journal_get_write_access(handle_t *, struct buffer_head *);
 extern int	 journal_get_create_access (handle_t *, struct buffer_head *);
-extern int	 journal_get_undo_access(handle_t *, struct buffer_head *,
-						int *credits);
+extern int	 journal_get_undo_access(handle_t *, struct buffer_head *);
 extern int	 journal_dirty_data (handle_t *, struct buffer_head *);
 extern int	 journal_dirty_metadata (handle_t *, struct buffer_head *);
-extern void	 journal_release_buffer (handle_t *, struct buffer_head *,
-						int credits);
+extern void	 journal_release_buffer (handle_t *, struct buffer_head *);
 extern int	 journal_forget (handle_t *, struct buffer_head *);
 extern void	 journal_sync_buffer (struct buffer_head *);
 extern int	 journal_invalidatepage(journal_t *,
diff -Nru a/include/linux/journal-head.h b/include/linux/journal-head.h
--- a/include/linux/journal-head.h	2005-03-11 12:51:51 -08:00
+++ b/include/linux/journal-head.h	2005-03-11 12:51:51 -08:00
@@ -32,6 +32,13 @@
 	unsigned b_jlist;
 
 	/*
+	 * This flag signals the buffer has been modified by
+	 * the currently running transaction
+	 * [jbd_lock_bh_state()]
+	 */
+	unsigned b_modified;
+
+	/*
 	 * Copy of the buffer data frozen for writing to the log.
 	 * [jbd_lock_bh_state()]
 	 */
diff -Nru a/include/linux/joystick.h b/include/linux/joystick.h
--- a/include/linux/joystick.h	2005-03-11 12:51:47 -08:00
+++ b/include/linux/joystick.h	2005-03-11 12:51:47 -08:00
@@ -66,10 +66,10 @@
 #define JSIOCSCORR		_IOW('j', 0x21, struct js_corr)			/* set correction values */
 #define JSIOCGCORR		_IOR('j', 0x22, struct js_corr)			/* get correction values */
 
-#define JSIOCSAXMAP		_IOW('j', 0x31, __u8[ABS_MAX])			/* set axis mapping */
-#define JSIOCGAXMAP		_IOR('j', 0x32, __u8[ABS_MAX])			/* get axis mapping */
-#define JSIOCSBTNMAP		_IOW('j', 0x33, __u16[KEY_MAX - BTN_MISC])	/* set button mapping */
-#define JSIOCGBTNMAP		_IOR('j', 0x34, __u16[KEY_MAX - BTN_MISC])	/* get button mapping */
+#define JSIOCSAXMAP		_IOW('j', 0x31, __u8[ABS_MAX + 1])		/* set axis mapping */
+#define JSIOCGAXMAP		_IOR('j', 0x32, __u8[ABS_MAX + 1])		/* get axis mapping */
+#define JSIOCSBTNMAP		_IOW('j', 0x33, __u16[KEY_MAX - BTN_MISC + 1])	/* set button mapping */
+#define JSIOCGBTNMAP		_IOR('j', 0x34, __u16[KEY_MAX - BTN_MISC + 1])	/* get button mapping */
 
 /*
  * Types and constants for get/set correction
diff -Nru a/include/linux/kernel.h b/include/linux/kernel.h
--- a/include/linux/kernel.h	2005-03-11 12:51:40 -08:00
+++ b/include/linux/kernel.h	2005-03-11 12:51:40 -08:00
@@ -278,6 +278,12 @@
 extern void BUILD_BUG(void);
 #define BUILD_BUG_ON(condition) do { if (condition) BUILD_BUG(); } while(0)
 
+#ifdef CONFIG_SYSCTL
+extern int randomize_va_space;
+#else
+#define randomize_va_space 1
+#endif
+
 /* Trap pasters of __FUNCTION__ at compile-time */
 #if __GNUC__ > 2 || __GNUC_MINOR__ >= 95
 #define __FUNCTION__ (__func__)
diff -Nru a/include/linux/key.h b/include/linux/key.h
--- a/include/linux/key.h	2005-03-11 12:51:47 -08:00
+++ b/include/linux/key.h	2005-03-11 12:51:47 -08:00
@@ -58,6 +58,7 @@
 
 struct seq_file;
 struct user_struct;
+struct signal_struct;
 
 struct key_type;
 struct key_owner;
@@ -258,7 +259,9 @@
 extern int alloc_uid_keyring(struct user_struct *user);
 extern void switch_uid_keyring(struct user_struct *new_user);
 extern int copy_keys(unsigned long clone_flags, struct task_struct *tsk);
+extern int copy_thread_group_keys(struct task_struct *tsk);
 extern void exit_keys(struct task_struct *tsk);
+extern void exit_thread_group_keys(struct signal_struct *tg);
 extern int suid_keys(struct task_struct *tsk);
 extern int exec_keys(struct task_struct *tsk);
 extern void key_fsuid_changed(struct task_struct *tsk);
@@ -274,7 +277,9 @@
 #define alloc_uid_keyring(u)		0
 #define switch_uid_keyring(u)		do { } while(0)
 #define copy_keys(f,t)			0
+#define copy_thread_group_keys(t)	0
 #define exit_keys(t)			do { } while(0)
+#define exit_thread_group_keys(tg)	do { } while(0)
 #define suid_keys(t)			do { } while(0)
 #define exec_keys(t)			do { } while(0)
 #define key_fsuid_changed(t)		do { } while(0)
diff -Nru a/include/linux/keyboard.h b/include/linux/keyboard.h
--- a/include/linux/keyboard.h	2005-03-11 12:51:41 -08:00
+++ b/include/linux/keyboard.h	2005-03-11 12:51:41 -08:00
@@ -16,7 +16,7 @@
 
 #define NR_SHIFT	9
 
-#define NR_KEYS		255
+#define NR_KEYS		256
 #define MAX_NR_KEYMAPS	256
 /* This means 128Kb if all keymaps are allocated. Only the superuser
 	may increase the number of keymaps beyond MAX_NR_OF_USER_KEYMAPS. */
diff -Nru a/include/linux/kobj_map.h b/include/linux/kobj_map.h
--- a/include/linux/kobj_map.h	2005-03-11 12:51:47 -08:00
+++ b/include/linux/kobj_map.h	2005-03-11 12:51:47 -08:00
@@ -7,6 +7,6 @@
 	     kobj_probe_t *, int (*)(dev_t, void *), void *);
 void kobj_unmap(struct kobj_map *, dev_t, unsigned long);
 struct kobject *kobj_lookup(struct kobj_map *, dev_t, int *);
-struct kobj_map *kobj_map_init(kobj_probe_t *, struct subsystem *);
+struct kobj_map *kobj_map_init(kobj_probe_t *, struct semaphore *);
 
 #endif
diff -Nru a/include/linux/kobject.h b/include/linux/kobject.h
--- a/include/linux/kobject.h	2005-03-11 12:51:41 -08:00
+++ b/include/linux/kobject.h	2005-03-11 12:51:41 -08:00
@@ -20,6 +20,7 @@
 #include <linux/types.h>
 #include <linux/list.h>
 #include <linux/sysfs.h>
+#include <linux/spinlock.h>
 #include <linux/rwsem.h>
 #include <linux/kref.h>
 #include <linux/kobject_uevent.h>
@@ -102,6 +103,7 @@
 	struct subsystem	* subsys;
 	struct kobj_type	* ktype;
 	struct list_head	list;
+	spinlock_t		list_lock;
 	struct kobject		kobj;
 	struct kset_hotplug_ops	* hotplug_ops;
 };
diff -Nru a/include/linux/kref.h b/include/linux/kref.h
--- a/include/linux/kref.h	2005-03-11 12:51:41 -08:00
+++ b/include/linux/kref.h	2005-03-11 12:51:41 -08:00
@@ -26,7 +26,7 @@
 
 void kref_init(struct kref *kref);
 void kref_get(struct kref *kref);
-void kref_put(struct kref *kref, void (*release) (struct kref *kref));
+int kref_put(struct kref *kref, void (*release) (struct kref *kref));
 
 #endif /* __KERNEL__ */
 #endif /* _KREF_H_ */
diff -Nru a/include/linux/lockd/lockd.h b/include/linux/lockd/lockd.h
--- a/include/linux/lockd/lockd.h	2005-03-11 12:51:41 -08:00
+++ b/include/linux/lockd/lockd.h	2005-03-11 12:51:41 -08:00
@@ -42,7 +42,6 @@
 	struct rpc_clnt	*	h_rpcclnt;	/* RPC client to talk to peer */
 	char			h_name[20];	/* remote hostname */
 	u32			h_version;	/* interface version */
-	rpc_authflavor_t	h_authflavor;	/* RPC authentication type */
 	unsigned short		h_proto;	/* transport proto */
 	unsigned short		h_reclaiming : 1,
 				h_server     : 1, /* server side, not client side */
@@ -143,8 +142,6 @@
  * Lockd client functions
  */
 struct nlm_rqst * nlmclnt_alloc_call(void);
-int		  nlmclnt_call(struct nlm_rqst *, u32);
-int		  nlmclnt_async_call(struct nlm_rqst *, u32, rpc_action);
 int		  nlmclnt_block(struct nlm_host *, struct file_lock *, u32 *);
 int		  nlmclnt_cancel(struct nlm_host *, struct file_lock *);
 u32		  nlmclnt_grant(struct nlm_lock *);
diff -Nru a/include/linux/loop.h b/include/linux/loop.h
--- a/include/linux/loop.h	2005-03-11 12:51:52 -08:00
+++ b/include/linux/loop.h	2005-03-11 12:51:52 -08:00
@@ -71,7 +71,10 @@
 /*
  * Loop flags
  */
-#define LO_FLAGS_READ_ONLY	1
+enum {
+	LO_FLAGS_READ_ONLY	= 1,
+	LO_FLAGS_USE_AOPS	= 2,
+};
 
 #include <asm/posix_types.h>	/* for __kernel_old_dev_t */
 #include <asm/types.h>		/* for __u64 */
diff -Nru a/include/linux/major.h b/include/linux/major.h
--- a/include/linux/major.h	2005-03-11 12:51:42 -08:00
+++ b/include/linux/major.h	2005-03-11 12:51:42 -08:00
@@ -25,7 +25,6 @@
 #define MISC_MAJOR		10
 #define SCSI_CDROM_MAJOR	11
 #define MUX_MAJOR		11	/* PA-RISC only */
-#define QIC02_TAPE_MAJOR	12
 #define XT_DISK_MAJOR		13
 #define INPUT_MAJOR		13
 #define SOUND_MAJOR		14
diff -Nru a/include/linux/mii.h b/include/linux/mii.h
--- a/include/linux/mii.h	2005-03-11 12:51:40 -08:00
+++ b/include/linux/mii.h	2005-03-11 12:51:40 -08:00
@@ -20,6 +20,8 @@
 #define MII_ADVERTISE       0x04        /* Advertisement control reg   */
 #define MII_LPA             0x05        /* Link partner ability reg    */
 #define MII_EXPANSION       0x06        /* Expansion register          */
+#define MII_CTRL1000        0x09        /* 1000BASE-T control          */
+#define MII_STAT1000        0x0a        /* 1000BASE-T status           */
 #define MII_DCOUNTER        0x12        /* Disconnect counter          */
 #define MII_FCSCOUNTER      0x13        /* False carrier counter       */
 #define MII_NWAYTEST        0x14        /* N-way auto-neg test reg     */
@@ -67,7 +69,9 @@
 #define ADVERTISE_100HALF       0x0080  /* Try for 100mbps half-duplex */
 #define ADVERTISE_100FULL       0x0100  /* Try for 100mbps full-duplex */
 #define ADVERTISE_100BASE4      0x0200  /* Try for 100mbps 4k packets  */
-#define ADVERTISE_RESV          0x1c00  /* Unused...                   */
+#define ADVERTISE_PAUSE_CAP     0x0400  /* Try for pause               */
+#define ADVERTISE_PAUSE_ASYM    0x0800  /* Try for asymetric pause     */
+#define ADVERTISE_RESV          0x1000  /* Unused...                   */
 #define ADVERTISE_RFAULT        0x2000  /* Say we can detect faults    */
 #define ADVERTISE_LPACK         0x4000  /* Ack link partners response  */
 #define ADVERTISE_NPAGE         0x8000  /* Next page bit               */
@@ -84,7 +88,9 @@
 #define LPA_100HALF             0x0080  /* Can do 100mbps half-duplex  */
 #define LPA_100FULL             0x0100  /* Can do 100mbps full-duplex  */
 #define LPA_100BASE4            0x0200  /* Can do 100mbps 4k packets   */
-#define LPA_RESV                0x1c00  /* Unused...                   */
+#define LPA_PAUSE_CAP           0x0400  /* Can pause                   */
+#define LPA_PAUSE_ASYM          0x0800  /* Can pause asymetrically     */
+#define LPA_RESV                0x1000  /* Unused...                   */
 #define LPA_RFAULT              0x2000  /* Link partner faulted        */
 #define LPA_LPACK               0x4000  /* Link partner acked us       */
 #define LPA_NPAGE               0x8000  /* Next page bit               */
@@ -105,6 +111,15 @@
 #define NWAYTEST_LOOPBACK       0x0100  /* Enable loopback for N-way   */
 #define NWAYTEST_RESV2          0xfe00  /* Unused...                   */
 
+/* 1000BASE-T Control register */
+#define ADVERTISE_1000FULL      0x0200  /* Advertise 1000BASE-T full duplex */
+#define ADVERTISE_1000HALF      0x0100  /* Advertise 1000BASE-T half duplex */
+
+/* 1000BASE-T Status register */
+#define LPA_1000LOCALRXOK       0x2000  /* Link partner local receiver status */
+#define LPA_1000REMRXOK         0x1000  /* Link partner remote receiver status */
+#define LPA_1000FULL            0x0800  /* Link partner 1000BASE-T full duplex */
+#define LPA_1000HALF            0x0400  /* Link partner 1000BASE-T half duplex */
 
 struct mii_if_info {
 	int phy_id;
@@ -114,6 +129,7 @@
 
 	unsigned int full_duplex : 1;	/* is full duplex? */
 	unsigned int force_media : 1;	/* is autoneg. disabled? */
+	unsigned int supports_gmii : 1; /* are GMII registers supported? */
 
 	struct net_device *dev;
 	int (*mdio_read) (struct net_device *dev, int phy_id, int location);
diff -Nru a/include/linux/mm.h b/include/linux/mm.h
--- a/include/linux/mm.h	2005-03-11 12:51:41 -08:00
+++ b/include/linux/mm.h	2005-03-11 12:51:41 -08:00
@@ -838,7 +838,7 @@
 }
 
 /* update per process rss and vm hiwater data */
-extern void update_mem_hiwater(void);
+extern void update_mem_hiwater(struct task_struct *tsk);
 
 #ifndef CONFIG_DEBUG_PAGEALLOC
 static inline void
diff -Nru a/include/linux/mmzone.h b/include/linux/mmzone.h
--- a/include/linux/mmzone.h	2005-03-11 12:51:46 -08:00
+++ b/include/linux/mmzone.h	2005-03-11 12:51:46 -08:00
@@ -11,6 +11,7 @@
 #include <linux/cache.h>
 #include <linux/threads.h>
 #include <linux/numa.h>
+#include <linux/init.h>
 #include <asm/atomic.h>
 
 /* Free memory management - zoned buddy allocator.  */
@@ -277,6 +278,16 @@
 void wakeup_kswapd(struct zone *zone, int order);
 int zone_watermark_ok(struct zone *z, int order, unsigned long mark,
 		int alloc_type, int can_try_harder, int gfp_high);
+
+#ifdef CONFIG_HAVE_MEMORY_PRESENT
+void memory_present(int nid, unsigned long start, unsigned long end);
+#else
+static inline void memory_present(int nid, unsigned long start, unsigned long end) {}
+#endif
+
+#ifdef CONFIG_NEED_NODE_MEMMAP_SIZE
+unsigned long __init node_memmap_size_bytes(int, unsigned long, unsigned long);
+#endif
 
 /*
  * zone_idx() returns 0 for the ZONE_DMA zone, 1 for the ZONE_NORMAL zone, etc.
diff -Nru a/include/linux/mod_devicetable.h b/include/linux/mod_devicetable.h
--- a/include/linux/mod_devicetable.h	2005-03-11 12:51:51 -08:00
+++ b/include/linux/mod_devicetable.h	2005-03-11 12:51:51 -08:00
@@ -165,4 +165,14 @@
 };
 
 
+#define SERIO_ANY	0xff
+
+struct serio_device_id {
+	__u8 type;
+	__u8 extra;
+	__u8 id;
+	__u8 proto;
+};
+
+
 #endif /* LINUX_MOD_DEVICETABLE_H */
diff -Nru a/include/linux/mpage.h b/include/linux/mpage.h
--- a/include/linux/mpage.h	2005-03-11 12:51:42 -08:00
+++ b/include/linux/mpage.h	2005-03-11 12:51:42 -08:00
@@ -11,12 +11,15 @@
  */
 
 struct writeback_control;
+typedef int (writepage_t)(struct page *page, struct writeback_control *wbc);
 
 int mpage_readpages(struct address_space *mapping, struct list_head *pages,
 				unsigned nr_pages, get_block_t get_block);
 int mpage_readpage(struct page *page, get_block_t get_block);
 int mpage_writepages(struct address_space *mapping,
 		struct writeback_control *wbc, get_block_t get_block);
+int mpage_writepage(struct page *page, get_block_t *get_block,
+		struct writeback_control *wbc);
 
 static inline int
 generic_writepages(struct address_space *mapping, struct writeback_control *wbc)
diff -Nru a/include/linux/msdos_fs.h b/include/linux/msdos_fs.h
--- a/include/linux/msdos_fs.h	2005-03-11 12:51:50 -08:00
+++ b/include/linux/msdos_fs.h	2005-03-11 12:51:50 -08:00
@@ -50,8 +50,6 @@
 #define MSDOS_VALID_MODE (S_IFREG | S_IFDIR | S_IRWXU | S_IRWXG | S_IRWXO)
 /* Convert attribute bits and a mask to the UNIX mode. */
 #define MSDOS_MKMODE(a, m) (m & (a & ATTR_RO ? S_IRUGO|S_IXUGO : S_IRWXUGO))
-/* Convert the UNIX mode to MS-DOS attribute bits. */
-#define MSDOS_MKATTR(m)	((m & S_IWUGO) ? ATTR_NONE : ATTR_RO)
 
 #define MSDOS_NAME	11	/* maximum name length */
 #define MSDOS_LONGNAME	256	/* maximum name length */
@@ -78,15 +76,11 @@
 #define BAD_FAT12	0xFF7
 #define BAD_FAT16	0xFFF7
 #define BAD_FAT32	0x0FFFFFF7
-#define BAD_FAT(s)	(MSDOS_SB(s)->fat_bits == 32 ? BAD_FAT32 : \
-	MSDOS_SB(s)->fat_bits == 16 ? BAD_FAT16 : BAD_FAT12)
 
 /* standard EOF */
 #define EOF_FAT12	0xFFF
 #define EOF_FAT16	0xFFFF
 #define EOF_FAT32	0x0FFFFFFF
-#define EOF_FAT(s)	(MSDOS_SB(s)->fat_bits == 32 ? EOF_FAT32 : \
-	MSDOS_SB(s)->fat_bits == 16 ? EOF_FAT16 : EOF_FAT12)
 
 #define FAT_ENT_FREE	(0)
 #define FAT_ENT_BAD	(BAD_FAT32)
@@ -100,8 +94,11 @@
 /*
  * ioctl commands
  */
-#define	VFAT_IOCTL_READDIR_BOTH		_IOR('r', 1, struct dirent [2])
-#define	VFAT_IOCTL_READDIR_SHORT	_IOR('r', 2, struct dirent [2])
+#define VFAT_IOCTL_READDIR_BOTH		_IOR('r', 1, struct dirent [2])
+#define VFAT_IOCTL_READDIR_SHORT	_IOR('r', 2, struct dirent [2])
+/* <linux/videotext.h> has used 0x72 ('r') in collision, so skip a few */
+#define FAT_IOCTL_GET_ATTRIBUTES	_IOR('r', 0x10, __u32)
+#define FAT_IOCTL_SET_ATTRIBUTES	_IOW('r', 0x11, __u32)
 
 /*
  * vfat shortname flags
@@ -152,7 +149,7 @@
 	__u8	name[8],ext[3];	/* name and extension */
 	__u8	attr;		/* attribute bits */
 	__u8    lcase;		/* Case for base and extension */
-	__u8	ctime_ms;	/* Creation time, milliseconds */
+	__u8	ctime_cs;	/* Creation time, centiseconds (0-199) */
 	__le16	ctime;		/* Creation time */
 	__le16	cdate;		/* Creation date */
 	__le16	adate;		/* Last access date */
@@ -173,10 +170,12 @@
 	__u8    name11_12[4];	/* last 2 characters in name */
 };
 
-struct vfat_slot_info {
-	int long_slots;		/* number of long slots in filename */
-	loff_t longname_offset;	/* dir offset for longname start */
+struct fat_slot_info {
 	loff_t i_pos;		/* on-disk position of directory entry */
+	loff_t slot_off;	/* offset for slot or de start */
+	int nr_slots;		/* number of slots + 1(de) in filename */
+	struct msdos_dir_entry *de;
+	struct buffer_head *bh;
 };
 
 #ifdef __KERNEL__
@@ -228,8 +227,8 @@
 	unsigned long root_cluster;  /* first cluster of the root directory */
 	unsigned long fsinfo_sector; /* sector number of FAT32 fsinfo */
 	struct semaphore fat_lock;
-	int prev_free;               /* previously allocated cluster number */
-	int free_clusters;           /* -1 if undefined */
+	unsigned int prev_free;      /* previously allocated cluster number */
+	unsigned int free_clusters;  /* -1 if undefined */
 	struct fat_mount_options options;
 	struct nls_table *nls_disk;  /* Codepage used on disk */
 	struct nls_table *nls_io;    /* Charset used for input and display */
@@ -237,6 +236,9 @@
 	int dir_per_block;	     /* dir entries per block */
 	int dir_per_block_bits;	     /* log2(dir_per_block) */
 
+	int fatent_shift;
+	struct fatent_operations *fatent_ops;
+
 	spinlock_t inode_hash_lock;
 	struct hlist_head inode_hashtable[FAT_HASH_SIZE];
 };
@@ -257,7 +259,6 @@
 	int i_start;		/* first cluster or 0 */
 	int i_logstart;		/* logical first cluster */
 	int i_attrs;		/* unused attribute bits */
-	int i_ctime_ms;		/* unused change time in milliseconds */
 	loff_t i_pos;		/* on-disk position of directory entry or 0 */
 	struct hlist_node i_fat_hash;	/* hash by i_location */
 	struct inode vfs_inode;
@@ -273,6 +274,14 @@
 	return container_of(inode, struct msdos_inode_info, vfs_inode);
 }
 
+/* Return the FAT attribute byte for this inode */
+static inline u8 fat_attr(struct inode *inode)
+{
+	return ((inode->i_mode & S_IWUGO) ? ATTR_NONE : ATTR_RO) |
+		(S_ISDIR(inode->i_mode) ? ATTR_DIR : ATTR_NONE) |
+		MSDOS_I(inode)->i_attrs;
+}
+
 static inline sector_t fat_clus_to_blknr(struct msdos_sb_info *sbi, int clus)
 {
 	return ((sector_t)clus - FAT_START_ENT) * sbi->sec_per_clus
@@ -307,7 +316,6 @@
 
 /* fat/cache.c */
 extern void fat_cache_inval_inode(struct inode *inode);
-extern int fat_access(struct super_block *sb, int nr, int new_value);
 extern int fat_get_cluster(struct inode *inode, int cluster,
 			   int *fclus, int *dclus);
 extern int fat_bmap(struct inode *inode, sector_t sector, sector_t *phys);
@@ -315,19 +323,67 @@
 /* fat/dir.c */
 extern struct file_operations fat_dir_operations;
 extern int fat_search_long(struct inode *inode, const unsigned char *name,
-			   int name_len, int anycase,
-			   loff_t *spos, loff_t *lpos);
-extern int fat_add_entries(struct inode *dir, int slots,
-			   struct buffer_head **bh,
-			   struct msdos_dir_entry **de, loff_t *i_pos);
-extern int fat_new_dir(struct inode *dir, struct inode *parent, int is_vfat);
+			   int name_len, struct fat_slot_info *sinfo);
 extern int fat_dir_empty(struct inode *dir);
 extern int fat_subdirs(struct inode *dir);
 extern int fat_scan(struct inode *dir, const unsigned char *name,
-		    struct buffer_head **res_bh,
-		    struct msdos_dir_entry **res_de, loff_t *i_pos);
+		    struct fat_slot_info *sinfo);
+extern int fat_get_dotdot_entry(struct inode *dir, struct buffer_head **bh,
+				struct msdos_dir_entry **de, loff_t *i_pos);
+extern int fat_alloc_new_dir(struct inode *dir, struct timespec *ts);
+extern int fat_add_entries(struct inode *dir, void *slots, int nr_slots,
+			   struct fat_slot_info *sinfo);
+extern int fat_remove_entries(struct inode *dir, struct fat_slot_info *sinfo);
+
+/* fat/fatent.c */
+struct fat_entry {
+	int entry;
+	union {
+		u8 *ent12_p[2];
+		__le16 *ent16_p;
+		__le32 *ent32_p;
+	} u;
+	int nr_bhs;
+	struct buffer_head *bhs[2];
+};
+
+static inline void fatent_init(struct fat_entry *fatent)
+{
+	fatent->nr_bhs = 0;
+	fatent->entry = 0;
+	fatent->u.ent32_p = NULL;
+	fatent->bhs[0] = fatent->bhs[1] = NULL;
+}
+
+static inline void fatent_set_entry(struct fat_entry *fatent, int entry)
+{
+	fatent->entry = entry;
+	fatent->u.ent32_p = NULL;
+}
+
+static inline void fatent_brelse(struct fat_entry *fatent)
+{
+	int i;
+	fatent->u.ent32_p = NULL;
+	for (i = 0; i < fatent->nr_bhs; i++)
+		brelse(fatent->bhs[i]);
+	fatent->nr_bhs = 0;
+	fatent->bhs[0] = fatent->bhs[1] = NULL;
+}
+
+extern void fat_ent_access_init(struct super_block *sb);
+extern int fat_ent_read(struct inode *inode, struct fat_entry *fatent,
+			int entry);
+extern int fat_ent_write(struct inode *inode, struct fat_entry *fatent,
+			 int new, int wait);
+extern int fat_alloc_clusters(struct inode *inode, int *cluster,
+			      int nr_cluster);
+extern int fat_free_clusters(struct inode *inode, int cluster);
+extern int fat_count_free_clusters(struct super_block *sb);
 
 /* fat/file.c */
+extern int fat_generic_ioctl(struct inode *inode, struct file *filp,
+			     unsigned int cmd, unsigned long arg);
 extern struct file_operations fat_file_operations;
 extern struct inode_operations fat_file_inode_operations;
 extern int fat_notify_change(struct dentry * dentry, struct iattr * attr);
@@ -338,35 +394,18 @@
 extern void fat_detach(struct inode *inode);
 extern struct inode *fat_iget(struct super_block *sb, loff_t i_pos);
 extern struct inode *fat_build_inode(struct super_block *sb,
-			struct msdos_dir_entry *de, loff_t i_pos, int *res);
-int fat_fill_super(struct super_block *sb, void *data, int silent,
-		   struct inode_operations *fs_dir_inode_ops, int isvfat);
+			struct msdos_dir_entry *de, loff_t i_pos);
+extern int fat_sync_inode(struct inode *inode);
+extern int fat_fill_super(struct super_block *sb, void *data, int silent,
+			struct inode_operations *fs_dir_inode_ops, int isvfat);
 
 /* fat/misc.c */
 extern void fat_fs_panic(struct super_block *s, const char *fmt, ...);
-extern void lock_fat(struct super_block *sb);
-extern void unlock_fat(struct super_block *sb);
 extern void fat_clusters_flush(struct super_block *sb);
-extern int fat_add_cluster(struct inode *inode);
+extern int fat_chain_add(struct inode *inode, int new_dclus, int nr_cluster);
 extern int date_dos2unix(unsigned short time, unsigned short date);
 extern void fat_date_unix2dos(int unix_date, __le16 *time, __le16 *date);
-extern int fat__get_entry(struct inode *dir, loff_t *pos,
-			  struct buffer_head **bh,
-			  struct msdos_dir_entry **de, loff_t *i_pos);
-static __inline__ int fat_get_entry(struct inode *dir, loff_t *pos,
-				    struct buffer_head **bh,
-				    struct msdos_dir_entry **de, loff_t *i_pos)
-{
-	/* Fast stuff first */
-	if (*bh && *de &&
-	    (*de - (struct msdos_dir_entry *)(*bh)->b_data) < MSDOS_SB(dir->i_sb)->dir_per_block - 1) {
-		*pos += sizeof(struct msdos_dir_entry);
-		(*de)++;
-		(*i_pos)++;
-		return 0;
-	}
-	return fat__get_entry(dir, pos, bh, de, i_pos);
-}
+extern int fat_sync_bhs(struct buffer_head **bhs, int nr_bhs);
 
 #endif /* __KERNEL__ */
 
diff -Nru a/include/linux/mtio.h b/include/linux/mtio.h
--- a/include/linux/mtio.h	2005-03-11 12:51:40 -08:00
+++ b/include/linux/mtio.h	2005-03-11 12:51:40 -08:00
@@ -150,34 +150,6 @@
 };
 
 
-/* structure for MTIOCGETCONFIG/MTIOCSETCONFIG primarily intended
- * as an interim solution for QIC-02 until DDI is fully implemented.
- */
-struct mtconfiginfo {
-	long	mt_type;	/* drive type */
-	long	ifc_type;	/* interface card type */
-	unsigned short	irqnr;	/* IRQ number to use */
-	unsigned short	dmanr;	/* DMA channel to use */
-	unsigned short	port;	/* IO port base address */
-
-	unsigned long	debug;	/* debugging flags */
-
-	unsigned	have_dens:1;
-	unsigned	have_bsf:1;
-	unsigned	have_fsr:1;
-	unsigned	have_bsr:1;
-	unsigned	have_eod:1;
-	unsigned	have_seek:1;
-	unsigned	have_tell:1;
-	unsigned	have_ras1:1;
-	unsigned	have_ras2:1;
-	unsigned	have_ras3:1;
-	unsigned	have_qfa:1;
-
-	unsigned	pad1:5;
-	char		reserved[10];
-};
-
 /*  structure for MTIOCVOLINFO, query information about the volume
  *  currently positioned at (zftape)
  */
diff -Nru a/include/linux/mv643xx.h b/include/linux/mv643xx.h
--- a/include/linux/mv643xx.h	2005-03-11 12:51:50 -08:00
+++ b/include/linux/mv643xx.h	2005-03-11 12:51:50 -08:00
@@ -1,5 +1,5 @@
 /*
- * mv64340.h - MV-64340 Internal registers definition file.
+ * mv643xx.h - MV-643XX Internal registers definition file.
  *
  * Copyright 2002 Momentum Computer, Inc.
  * 	Author: Matthew Dharm <mdharm@momenco.com>
@@ -10,8 +10,8 @@
  * Free Software Foundation;  either version 2 of the  License, or (at your
  * option) any later version.
  */
-#ifndef __ASM_MV64340_H
-#define __ASM_MV64340_H
+#ifndef __ASM_MV643XX_H
+#define __ASM_MV643XX_H
 
 #ifdef __MIPS__
 #include <asm/addrspace.h>
@@ -662,116 +662,119 @@
 /*        Ethernet Unit Registers  		*/
 /****************************************/
 
-#define MV64340_ETH_PHY_ADDR_REG                                    0x2000
-#define MV64340_ETH_SMI_REG                                         0x2004
-#define MV64340_ETH_UNIT_DEFAULT_ADDR_REG                           0x2008
-#define MV64340_ETH_UNIT_DEFAULTID_REG                              0x200c
-#define MV64340_ETH_UNIT_INTERRUPT_CAUSE_REG                        0x2080
-#define MV64340_ETH_UNIT_INTERRUPT_MASK_REG                         0x2084
-#define MV64340_ETH_UNIT_INTERNAL_USE_REG                           0x24fc
-#define MV64340_ETH_UNIT_ERROR_ADDR_REG                             0x2094
-#define MV64340_ETH_BAR_0                                           0x2200
-#define MV64340_ETH_BAR_1                                           0x2208
-#define MV64340_ETH_BAR_2                                           0x2210
-#define MV64340_ETH_BAR_3                                           0x2218
-#define MV64340_ETH_BAR_4                                           0x2220
-#define MV64340_ETH_BAR_5                                           0x2228
-#define MV64340_ETH_SIZE_REG_0                                      0x2204
-#define MV64340_ETH_SIZE_REG_1                                      0x220c
-#define MV64340_ETH_SIZE_REG_2                                      0x2214
-#define MV64340_ETH_SIZE_REG_3                                      0x221c
-#define MV64340_ETH_SIZE_REG_4                                      0x2224
-#define MV64340_ETH_SIZE_REG_5                                      0x222c
-#define MV64340_ETH_HEADERS_RETARGET_BASE_REG                       0x2230
-#define MV64340_ETH_HEADERS_RETARGET_CONTROL_REG                    0x2234
-#define MV64340_ETH_HIGH_ADDR_REMAP_REG_0                           0x2280
-#define MV64340_ETH_HIGH_ADDR_REMAP_REG_1                           0x2284
-#define MV64340_ETH_HIGH_ADDR_REMAP_REG_2                           0x2288
-#define MV64340_ETH_HIGH_ADDR_REMAP_REG_3                           0x228c
-#define MV64340_ETH_BASE_ADDR_ENABLE_REG                            0x2290
-#define MV64340_ETH_ACCESS_PROTECTION_REG(port)                    (0x2294 + (port<<2))
-#define MV64340_ETH_MIB_COUNTERS_BASE(port)                        (0x3000 + (port<<7))
-#define MV64340_ETH_PORT_CONFIG_REG(port)                          (0x2400 + (port<<10))
-#define MV64340_ETH_PORT_CONFIG_EXTEND_REG(port)                   (0x2404 + (port<<10))
-#define MV64340_ETH_MII_SERIAL_PARAMETRS_REG(port)                 (0x2408 + (port<<10))
-#define MV64340_ETH_GMII_SERIAL_PARAMETRS_REG(port)                (0x240c + (port<<10))
-#define MV64340_ETH_VLAN_ETHERTYPE_REG(port)                       (0x2410 + (port<<10))
-#define MV64340_ETH_MAC_ADDR_LOW(port)                             (0x2414 + (port<<10))
-#define MV64340_ETH_MAC_ADDR_HIGH(port)                            (0x2418 + (port<<10))
-#define MV64340_ETH_SDMA_CONFIG_REG(port)                          (0x241c + (port<<10))
-#define MV64340_ETH_DSCP_0(port)                                   (0x2420 + (port<<10))
-#define MV64340_ETH_DSCP_1(port)                                   (0x2424 + (port<<10))
-#define MV64340_ETH_DSCP_2(port)                                   (0x2428 + (port<<10))
-#define MV64340_ETH_DSCP_3(port)                                   (0x242c + (port<<10))
-#define MV64340_ETH_DSCP_4(port)                                   (0x2430 + (port<<10))
-#define MV64340_ETH_DSCP_5(port)                                   (0x2434 + (port<<10))
-#define MV64340_ETH_DSCP_6(port)                                   (0x2438 + (port<<10))
-#define MV64340_ETH_PORT_SERIAL_CONTROL_REG(port)                  (0x243c + (port<<10))
-#define MV64340_ETH_VLAN_PRIORITY_TAG_TO_PRIORITY(port)            (0x2440 + (port<<10))
-#define MV64340_ETH_PORT_STATUS_REG(port)                          (0x2444 + (port<<10))
-#define MV64340_ETH_TRANSMIT_QUEUE_COMMAND_REG(port)               (0x2448 + (port<<10))
-#define MV64340_ETH_TX_QUEUE_FIXED_PRIORITY(port)                  (0x244c + (port<<10))
-#define MV64340_ETH_PORT_TX_TOKEN_BUCKET_RATE_CONFIG(port)         (0x2450 + (port<<10))
-#define MV64340_ETH_MAXIMUM_TRANSMIT_UNIT(port)                    (0x2458 + (port<<10))
-#define MV64340_ETH_PORT_MAXIMUM_TOKEN_BUCKET_SIZE(port)           (0x245c + (port<<10))
-#define MV64340_ETH_INTERRUPT_CAUSE_REG(port)                      (0x2460 + (port<<10))
-#define MV64340_ETH_INTERRUPT_CAUSE_EXTEND_REG(port)               (0x2464 + (port<<10))
-#define MV64340_ETH_INTERRUPT_MASK_REG(port)                       (0x2468 + (port<<10))
-#define MV64340_ETH_INTERRUPT_EXTEND_MASK_REG(port)                (0x246c + (port<<10))
-#define MV64340_ETH_RX_FIFO_URGENT_THRESHOLD_REG(port)             (0x2470 + (port<<10))
-#define MV64340_ETH_TX_FIFO_URGENT_THRESHOLD_REG(port)             (0x2474 + (port<<10))
-#define MV64340_ETH_RX_MINIMAL_FRAME_SIZE_REG(port)                (0x247c + (port<<10))
-#define MV64340_ETH_RX_DISCARDED_FRAMES_COUNTER(port)              (0x2484 + (port<<10)
-#define MV64340_ETH_PORT_DEBUG_0_REG(port)                         (0x248c + (port<<10))
-#define MV64340_ETH_PORT_DEBUG_1_REG(port)                         (0x2490 + (port<<10))
-#define MV64340_ETH_PORT_INTERNAL_ADDR_ERROR_REG(port)             (0x2494 + (port<<10))
-#define MV64340_ETH_INTERNAL_USE_REG(port)                         (0x24fc + (port<<10))
-#define MV64340_ETH_RECEIVE_QUEUE_COMMAND_REG(port)                (0x2680 + (port<<10))
-#define MV64340_ETH_CURRENT_SERVED_TX_DESC_PTR(port)               (0x2684 + (port<<10))      
-#define MV64340_ETH_RX_CURRENT_QUEUE_DESC_PTR_0(port)              (0x260c + (port<<10))     
-#define MV64340_ETH_RX_CURRENT_QUEUE_DESC_PTR_1(port)              (0x261c + (port<<10))     
-#define MV64340_ETH_RX_CURRENT_QUEUE_DESC_PTR_2(port)              (0x262c + (port<<10))     
-#define MV64340_ETH_RX_CURRENT_QUEUE_DESC_PTR_3(port)              (0x263c + (port<<10))     
-#define MV64340_ETH_RX_CURRENT_QUEUE_DESC_PTR_4(port)              (0x264c + (port<<10))     
-#define MV64340_ETH_RX_CURRENT_QUEUE_DESC_PTR_5(port)              (0x265c + (port<<10))     
-#define MV64340_ETH_RX_CURRENT_QUEUE_DESC_PTR_6(port)              (0x266c + (port<<10))     
-#define MV64340_ETH_RX_CURRENT_QUEUE_DESC_PTR_7(port)              (0x267c + (port<<10))     
-#define MV64340_ETH_TX_CURRENT_QUEUE_DESC_PTR_0(port)              (0x26c0 + (port<<10))     
-#define MV64340_ETH_TX_CURRENT_QUEUE_DESC_PTR_1(port)              (0x26c4 + (port<<10))     
-#define MV64340_ETH_TX_CURRENT_QUEUE_DESC_PTR_2(port)              (0x26c8 + (port<<10))     
-#define MV64340_ETH_TX_CURRENT_QUEUE_DESC_PTR_3(port)              (0x26cc + (port<<10))     
-#define MV64340_ETH_TX_CURRENT_QUEUE_DESC_PTR_4(port)              (0x26d0 + (port<<10))     
-#define MV64340_ETH_TX_CURRENT_QUEUE_DESC_PTR_5(port)              (0x26d4 + (port<<10))     
-#define MV64340_ETH_TX_CURRENT_QUEUE_DESC_PTR_6(port)              (0x26d8 + (port<<10))     
-#define MV64340_ETH_TX_CURRENT_QUEUE_DESC_PTR_7(port)              (0x26dc + (port<<10))     
-#define MV64340_ETH_TX_QUEUE_0_TOKEN_BUCKET_COUNT(port)            (0x2700 + (port<<10))
-#define MV64340_ETH_TX_QUEUE_1_TOKEN_BUCKET_COUNT(port)            (0x2710 + (port<<10))
-#define MV64340_ETH_TX_QUEUE_2_TOKEN_BUCKET_COUNT(port)            (0x2720 + (port<<10))
-#define MV64340_ETH_TX_QUEUE_3_TOKEN_BUCKET_COUNT(port)            (0x2730 + (port<<10))
-#define MV64340_ETH_TX_QUEUE_4_TOKEN_BUCKET_COUNT(port)            (0x2740 + (port<<10))
-#define MV64340_ETH_TX_QUEUE_5_TOKEN_BUCKET_COUNT(port)            (0x2750 + (port<<10))
-#define MV64340_ETH_TX_QUEUE_6_TOKEN_BUCKET_COUNT(port)            (0x2760 + (port<<10))
-#define MV64340_ETH_TX_QUEUE_7_TOKEN_BUCKET_COUNT(port)            (0x2770 + (port<<10))
-#define MV64340_ETH_TX_QUEUE_0_TOKEN_BUCKET_CONFIG(port)           (0x2704 + (port<<10))
-#define MV64340_ETH_TX_QUEUE_1_TOKEN_BUCKET_CONFIG(port)           (0x2714 + (port<<10))
-#define MV64340_ETH_TX_QUEUE_2_TOKEN_BUCKET_CONFIG(port)           (0x2724 + (port<<10))
-#define MV64340_ETH_TX_QUEUE_3_TOKEN_BUCKET_CONFIG(port)           (0x2734 + (port<<10))
-#define MV64340_ETH_TX_QUEUE_4_TOKEN_BUCKET_CONFIG(port)           (0x2744 + (port<<10))
-#define MV64340_ETH_TX_QUEUE_5_TOKEN_BUCKET_CONFIG(port)           (0x2754 + (port<<10))
-#define MV64340_ETH_TX_QUEUE_6_TOKEN_BUCKET_CONFIG(port)           (0x2764 + (port<<10))
-#define MV64340_ETH_TX_QUEUE_7_TOKEN_BUCKET_CONFIG(port)           (0x2774 + (port<<10))
-#define MV64340_ETH_TX_QUEUE_0_ARBITER_CONFIG(port)                (0x2708 + (port<<10))
-#define MV64340_ETH_TX_QUEUE_1_ARBITER_CONFIG(port)                (0x2718 + (port<<10))
-#define MV64340_ETH_TX_QUEUE_2_ARBITER_CONFIG(port)                (0x2728 + (port<<10))
-#define MV64340_ETH_TX_QUEUE_3_ARBITER_CONFIG(port)                (0x2738 + (port<<10))
-#define MV64340_ETH_TX_QUEUE_4_ARBITER_CONFIG(port)                (0x2748 + (port<<10))
-#define MV64340_ETH_TX_QUEUE_5_ARBITER_CONFIG(port)                (0x2758 + (port<<10))
-#define MV64340_ETH_TX_QUEUE_6_ARBITER_CONFIG(port)                (0x2768 + (port<<10))
-#define MV64340_ETH_TX_QUEUE_7_ARBITER_CONFIG(port)                (0x2778 + (port<<10))
-#define MV64340_ETH_PORT_TX_TOKEN_BUCKET_COUNT(port)               (0x2780 + (port<<10))
-#define MV64340_ETH_DA_FILTER_SPECIAL_MULTICAST_TABLE_BASE(port)   (0x3400 + (port<<10))
-#define MV64340_ETH_DA_FILTER_OTHER_MULTICAST_TABLE_BASE(port)     (0x3500 + (port<<10))
-#define MV64340_ETH_DA_FILTER_UNICAST_TABLE_BASE(port)             (0x3600 + (port<<10))
+#define MV643XX_ETH_SHARED_REGS                                     0x2000
+#define MV643XX_ETH_SHARED_REGS_SIZE                                0x2000
+
+#define MV643XX_ETH_PHY_ADDR_REG                                    0x2000
+#define MV643XX_ETH_SMI_REG                                         0x2004
+#define MV643XX_ETH_UNIT_DEFAULT_ADDR_REG                           0x2008
+#define MV643XX_ETH_UNIT_DEFAULTID_REG                              0x200c
+#define MV643XX_ETH_UNIT_INTERRUPT_CAUSE_REG                        0x2080
+#define MV643XX_ETH_UNIT_INTERRUPT_MASK_REG                         0x2084
+#define MV643XX_ETH_UNIT_INTERNAL_USE_REG                           0x24fc
+#define MV643XX_ETH_UNIT_ERROR_ADDR_REG                             0x2094
+#define MV643XX_ETH_BAR_0                                           0x2200
+#define MV643XX_ETH_BAR_1                                           0x2208
+#define MV643XX_ETH_BAR_2                                           0x2210
+#define MV643XX_ETH_BAR_3                                           0x2218
+#define MV643XX_ETH_BAR_4                                           0x2220
+#define MV643XX_ETH_BAR_5                                           0x2228
+#define MV643XX_ETH_SIZE_REG_0                                      0x2204
+#define MV643XX_ETH_SIZE_REG_1                                      0x220c
+#define MV643XX_ETH_SIZE_REG_2                                      0x2214
+#define MV643XX_ETH_SIZE_REG_3                                      0x221c
+#define MV643XX_ETH_SIZE_REG_4                                      0x2224
+#define MV643XX_ETH_SIZE_REG_5                                      0x222c
+#define MV643XX_ETH_HEADERS_RETARGET_BASE_REG                       0x2230
+#define MV643XX_ETH_HEADERS_RETARGET_CONTROL_REG                    0x2234
+#define MV643XX_ETH_HIGH_ADDR_REMAP_REG_0                           0x2280
+#define MV643XX_ETH_HIGH_ADDR_REMAP_REG_1                           0x2284
+#define MV643XX_ETH_HIGH_ADDR_REMAP_REG_2                           0x2288
+#define MV643XX_ETH_HIGH_ADDR_REMAP_REG_3                           0x228c
+#define MV643XX_ETH_BASE_ADDR_ENABLE_REG                            0x2290
+#define MV643XX_ETH_ACCESS_PROTECTION_REG(port)                    (0x2294 + (port<<2))
+#define MV643XX_ETH_MIB_COUNTERS_BASE(port)                        (0x3000 + (port<<7))
+#define MV643XX_ETH_PORT_CONFIG_REG(port)                          (0x2400 + (port<<10))
+#define MV643XX_ETH_PORT_CONFIG_EXTEND_REG(port)                   (0x2404 + (port<<10))
+#define MV643XX_ETH_MII_SERIAL_PARAMETRS_REG(port)                 (0x2408 + (port<<10))
+#define MV643XX_ETH_GMII_SERIAL_PARAMETRS_REG(port)                (0x240c + (port<<10))
+#define MV643XX_ETH_VLAN_ETHERTYPE_REG(port)                       (0x2410 + (port<<10))
+#define MV643XX_ETH_MAC_ADDR_LOW(port)                             (0x2414 + (port<<10))
+#define MV643XX_ETH_MAC_ADDR_HIGH(port)                            (0x2418 + (port<<10))
+#define MV643XX_ETH_SDMA_CONFIG_REG(port)                          (0x241c + (port<<10))
+#define MV643XX_ETH_DSCP_0(port)                                   (0x2420 + (port<<10))
+#define MV643XX_ETH_DSCP_1(port)                                   (0x2424 + (port<<10))
+#define MV643XX_ETH_DSCP_2(port)                                   (0x2428 + (port<<10))
+#define MV643XX_ETH_DSCP_3(port)                                   (0x242c + (port<<10))
+#define MV643XX_ETH_DSCP_4(port)                                   (0x2430 + (port<<10))
+#define MV643XX_ETH_DSCP_5(port)                                   (0x2434 + (port<<10))
+#define MV643XX_ETH_DSCP_6(port)                                   (0x2438 + (port<<10))
+#define MV643XX_ETH_PORT_SERIAL_CONTROL_REG(port)                  (0x243c + (port<<10))
+#define MV643XX_ETH_VLAN_PRIORITY_TAG_TO_PRIORITY(port)            (0x2440 + (port<<10))
+#define MV643XX_ETH_PORT_STATUS_REG(port)                          (0x2444 + (port<<10))
+#define MV643XX_ETH_TRANSMIT_QUEUE_COMMAND_REG(port)               (0x2448 + (port<<10))
+#define MV643XX_ETH_TX_QUEUE_FIXED_PRIORITY(port)                  (0x244c + (port<<10))
+#define MV643XX_ETH_PORT_TX_TOKEN_BUCKET_RATE_CONFIG(port)         (0x2450 + (port<<10))
+#define MV643XX_ETH_MAXIMUM_TRANSMIT_UNIT(port)                    (0x2458 + (port<<10))
+#define MV643XX_ETH_PORT_MAXIMUM_TOKEN_BUCKET_SIZE(port)           (0x245c + (port<<10))
+#define MV643XX_ETH_INTERRUPT_CAUSE_REG(port)                      (0x2460 + (port<<10))
+#define MV643XX_ETH_INTERRUPT_CAUSE_EXTEND_REG(port)               (0x2464 + (port<<10))
+#define MV643XX_ETH_INTERRUPT_MASK_REG(port)                       (0x2468 + (port<<10))
+#define MV643XX_ETH_INTERRUPT_EXTEND_MASK_REG(port)                (0x246c + (port<<10))
+#define MV643XX_ETH_RX_FIFO_URGENT_THRESHOLD_REG(port)             (0x2470 + (port<<10))
+#define MV643XX_ETH_TX_FIFO_URGENT_THRESHOLD_REG(port)             (0x2474 + (port<<10))
+#define MV643XX_ETH_RX_MINIMAL_FRAME_SIZE_REG(port)                (0x247c + (port<<10))
+#define MV643XX_ETH_RX_DISCARDED_FRAMES_COUNTER(port)              (0x2484 + (port<<10)
+#define MV643XX_ETH_PORT_DEBUG_0_REG(port)                         (0x248c + (port<<10))
+#define MV643XX_ETH_PORT_DEBUG_1_REG(port)                         (0x2490 + (port<<10))
+#define MV643XX_ETH_PORT_INTERNAL_ADDR_ERROR_REG(port)             (0x2494 + (port<<10))
+#define MV643XX_ETH_INTERNAL_USE_REG(port)                         (0x24fc + (port<<10))
+#define MV643XX_ETH_RECEIVE_QUEUE_COMMAND_REG(port)                (0x2680 + (port<<10))
+#define MV643XX_ETH_CURRENT_SERVED_TX_DESC_PTR(port)               (0x2684 + (port<<10))      
+#define MV643XX_ETH_RX_CURRENT_QUEUE_DESC_PTR_0(port)              (0x260c + (port<<10))     
+#define MV643XX_ETH_RX_CURRENT_QUEUE_DESC_PTR_1(port)              (0x261c + (port<<10))     
+#define MV643XX_ETH_RX_CURRENT_QUEUE_DESC_PTR_2(port)              (0x262c + (port<<10))     
+#define MV643XX_ETH_RX_CURRENT_QUEUE_DESC_PTR_3(port)              (0x263c + (port<<10))     
+#define MV643XX_ETH_RX_CURRENT_QUEUE_DESC_PTR_4(port)              (0x264c + (port<<10))     
+#define MV643XX_ETH_RX_CURRENT_QUEUE_DESC_PTR_5(port)              (0x265c + (port<<10))     
+#define MV643XX_ETH_RX_CURRENT_QUEUE_DESC_PTR_6(port)              (0x266c + (port<<10))     
+#define MV643XX_ETH_RX_CURRENT_QUEUE_DESC_PTR_7(port)              (0x267c + (port<<10))     
+#define MV643XX_ETH_TX_CURRENT_QUEUE_DESC_PTR_0(port)              (0x26c0 + (port<<10))     
+#define MV643XX_ETH_TX_CURRENT_QUEUE_DESC_PTR_1(port)              (0x26c4 + (port<<10))     
+#define MV643XX_ETH_TX_CURRENT_QUEUE_DESC_PTR_2(port)              (0x26c8 + (port<<10))     
+#define MV643XX_ETH_TX_CURRENT_QUEUE_DESC_PTR_3(port)              (0x26cc + (port<<10))     
+#define MV643XX_ETH_TX_CURRENT_QUEUE_DESC_PTR_4(port)              (0x26d0 + (port<<10))     
+#define MV643XX_ETH_TX_CURRENT_QUEUE_DESC_PTR_5(port)              (0x26d4 + (port<<10))     
+#define MV643XX_ETH_TX_CURRENT_QUEUE_DESC_PTR_6(port)              (0x26d8 + (port<<10))     
+#define MV643XX_ETH_TX_CURRENT_QUEUE_DESC_PTR_7(port)              (0x26dc + (port<<10))     
+#define MV643XX_ETH_TX_QUEUE_0_TOKEN_BUCKET_COUNT(port)            (0x2700 + (port<<10))
+#define MV643XX_ETH_TX_QUEUE_1_TOKEN_BUCKET_COUNT(port)            (0x2710 + (port<<10))
+#define MV643XX_ETH_TX_QUEUE_2_TOKEN_BUCKET_COUNT(port)            (0x2720 + (port<<10))
+#define MV643XX_ETH_TX_QUEUE_3_TOKEN_BUCKET_COUNT(port)            (0x2730 + (port<<10))
+#define MV643XX_ETH_TX_QUEUE_4_TOKEN_BUCKET_COUNT(port)            (0x2740 + (port<<10))
+#define MV643XX_ETH_TX_QUEUE_5_TOKEN_BUCKET_COUNT(port)            (0x2750 + (port<<10))
+#define MV643XX_ETH_TX_QUEUE_6_TOKEN_BUCKET_COUNT(port)            (0x2760 + (port<<10))
+#define MV643XX_ETH_TX_QUEUE_7_TOKEN_BUCKET_COUNT(port)            (0x2770 + (port<<10))
+#define MV643XX_ETH_TX_QUEUE_0_TOKEN_BUCKET_CONFIG(port)           (0x2704 + (port<<10))
+#define MV643XX_ETH_TX_QUEUE_1_TOKEN_BUCKET_CONFIG(port)           (0x2714 + (port<<10))
+#define MV643XX_ETH_TX_QUEUE_2_TOKEN_BUCKET_CONFIG(port)           (0x2724 + (port<<10))
+#define MV643XX_ETH_TX_QUEUE_3_TOKEN_BUCKET_CONFIG(port)           (0x2734 + (port<<10))
+#define MV643XX_ETH_TX_QUEUE_4_TOKEN_BUCKET_CONFIG(port)           (0x2744 + (port<<10))
+#define MV643XX_ETH_TX_QUEUE_5_TOKEN_BUCKET_CONFIG(port)           (0x2754 + (port<<10))
+#define MV643XX_ETH_TX_QUEUE_6_TOKEN_BUCKET_CONFIG(port)           (0x2764 + (port<<10))
+#define MV643XX_ETH_TX_QUEUE_7_TOKEN_BUCKET_CONFIG(port)           (0x2774 + (port<<10))
+#define MV643XX_ETH_TX_QUEUE_0_ARBITER_CONFIG(port)                (0x2708 + (port<<10))
+#define MV643XX_ETH_TX_QUEUE_1_ARBITER_CONFIG(port)                (0x2718 + (port<<10))
+#define MV643XX_ETH_TX_QUEUE_2_ARBITER_CONFIG(port)                (0x2728 + (port<<10))
+#define MV643XX_ETH_TX_QUEUE_3_ARBITER_CONFIG(port)                (0x2738 + (port<<10))
+#define MV643XX_ETH_TX_QUEUE_4_ARBITER_CONFIG(port)                (0x2748 + (port<<10))
+#define MV643XX_ETH_TX_QUEUE_5_ARBITER_CONFIG(port)                (0x2758 + (port<<10))
+#define MV643XX_ETH_TX_QUEUE_6_ARBITER_CONFIG(port)                (0x2768 + (port<<10))
+#define MV643XX_ETH_TX_QUEUE_7_ARBITER_CONFIG(port)                (0x2778 + (port<<10))
+#define MV643XX_ETH_PORT_TX_TOKEN_BUCKET_COUNT(port)               (0x2780 + (port<<10))
+#define MV643XX_ETH_DA_FILTER_SPECIAL_MULTICAST_TABLE_BASE(port)   (0x3400 + (port<<10))
+#define MV643XX_ETH_DA_FILTER_OTHER_MULTICAST_TABLE_BASE(port)     (0x3500 + (port<<10))
+#define MV643XX_ETH_DA_FILTER_UNICAST_TABLE_BASE(port)             (0x3600 + (port<<10))
 
 /*******************************************/
 /*          CUNIT  Registers               */
@@ -977,12 +980,9 @@
 /* I2C Registers                        */
 /****************************************/
 
-#define MV64340_I2C_SLAVE_ADDR                                      0xc000
-#define MV64340_I2C_EXTENDED_SLAVE_ADDR                             0xc010
-#define MV64340_I2C_DATA                                            0xc004
-#define MV64340_I2C_CONTROL                                         0xc008
-#define MV64340_I2C_STATUS_BAUDE_RATE                               0xc00C
-#define MV64340_I2C_SOFT_RESET                                      0xc01c
+#define MV64XXX_I2C_CTLR_NAME					"mv64xxx i2c"
+#define MV64XXX_I2C_OFFSET                                          0xc000
+#define MV64XXX_I2C_REG_BLOCK_SIZE                                  0x0020
 
 /****************************************/
 /* GPP Interface Registers              */
@@ -1085,4 +1085,229 @@
 	u32	brg_clk_freq;
 };
 
-#endif /* __ASM_MV64340_H */
+/* i2c Platform Device, Driver Data */
+struct mv64xxx_i2c_pdata {
+	u32	freq_m;
+	u32	freq_n;
+	u32	timeout;	/* In milliseconds */
+	u32	retries;
+};
+
+/* These macros describe Ethernet Port configuration reg (Px_cR) bits */
+#define MV643XX_ETH_UNICAST_NORMAL_MODE		0
+#define MV643XX_ETH_UNICAST_PROMISCUOUS_MODE	(1<<0)
+#define MV643XX_ETH_DEFAULT_RX_QUEUE_0		0
+#define MV643XX_ETH_DEFAULT_RX_QUEUE_1		(1<<1)
+#define MV643XX_ETH_DEFAULT_RX_QUEUE_2		(1<<2)
+#define MV643XX_ETH_DEFAULT_RX_QUEUE_3		((1<<2) | (1<<1))
+#define MV643XX_ETH_DEFAULT_RX_QUEUE_4		(1<<3)
+#define MV643XX_ETH_DEFAULT_RX_QUEUE_5		((1<<3) | (1<<1))
+#define MV643XX_ETH_DEFAULT_RX_QUEUE_6		((1<<3) | (1<<2))
+#define MV643XX_ETH_DEFAULT_RX_QUEUE_7		((1<<3) | (1<<2) | (1<<1))
+#define MV643XX_ETH_DEFAULT_RX_ARP_QUEUE_0	0
+#define MV643XX_ETH_DEFAULT_RX_ARP_QUEUE_1	(1<<4)
+#define MV643XX_ETH_DEFAULT_RX_ARP_QUEUE_2	(1<<5)
+#define MV643XX_ETH_DEFAULT_RX_ARP_QUEUE_3	((1<<5) | (1<<4))
+#define MV643XX_ETH_DEFAULT_RX_ARP_QUEUE_4	(1<<6)
+#define MV643XX_ETH_DEFAULT_RX_ARP_QUEUE_5	((1<<6) | (1<<4))
+#define MV643XX_ETH_DEFAULT_RX_ARP_QUEUE_6	((1<<6) | (1<<5))
+#define MV643XX_ETH_DEFAULT_RX_ARP_QUEUE_7	((1<<6) | (1<<5) | (1<<4))
+#define MV643XX_ETH_RECEIVE_BC_IF_NOT_IP_OR_ARP	0
+#define MV643XX_ETH_REJECT_BC_IF_NOT_IP_OR_ARP	(1<<7)
+#define MV643XX_ETH_RECEIVE_BC_IF_IP		0
+#define MV643XX_ETH_REJECT_BC_IF_IP		(1<<8)
+#define MV643XX_ETH_RECEIVE_BC_IF_ARP		0
+#define MV643XX_ETH_REJECT_BC_IF_ARP		(1<<9)
+#define MV643XX_ETH_TX_AM_NO_UPDATE_ERROR_SUMMARY (1<<12)
+#define MV643XX_ETH_CAPTURE_TCP_FRAMES_DIS	0
+#define MV643XX_ETH_CAPTURE_TCP_FRAMES_EN	(1<<14)
+#define MV643XX_ETH_CAPTURE_UDP_FRAMES_DIS	0
+#define MV643XX_ETH_CAPTURE_UDP_FRAMES_EN	(1<<15)
+#define MV643XX_ETH_DEFAULT_RX_TCP_QUEUE_0	0
+#define MV643XX_ETH_DEFAULT_RX_TCP_QUEUE_1	(1<<16)
+#define MV643XX_ETH_DEFAULT_RX_TCP_QUEUE_2	(1<<17)
+#define MV643XX_ETH_DEFAULT_RX_TCP_QUEUE_3	((1<<17) | (1<<16))
+#define MV643XX_ETH_DEFAULT_RX_TCP_QUEUE_4	(1<<18)
+#define MV643XX_ETH_DEFAULT_RX_TCP_QUEUE_5	((1<<18) | (1<<16))
+#define MV643XX_ETH_DEFAULT_RX_TCP_QUEUE_6	((1<<18) | (1<<17))
+#define MV643XX_ETH_DEFAULT_RX_TCP_QUEUE_7	((1<<18) | (1<<17) | (1<<16))
+#define MV643XX_ETH_DEFAULT_RX_UDP_QUEUE_0	0
+#define MV643XX_ETH_DEFAULT_RX_UDP_QUEUE_1	(1<<19)
+#define MV643XX_ETH_DEFAULT_RX_UDP_QUEUE_2	(1<<20)
+#define MV643XX_ETH_DEFAULT_RX_UDP_QUEUE_3	((1<<20) | (1<<19))
+#define MV643XX_ETH_DEFAULT_RX_UDP_QUEUE_4	((1<<21)
+#define MV643XX_ETH_DEFAULT_RX_UDP_QUEUE_5	((1<<21) | (1<<19))
+#define MV643XX_ETH_DEFAULT_RX_UDP_QUEUE_6	((1<<21) | (1<<20))
+#define MV643XX_ETH_DEFAULT_RX_UDP_QUEUE_7	((1<<21) | (1<<20) | (1<<19))
+#define MV643XX_ETH_DEFAULT_RX_BPDU_QUEUE_0	0
+#define MV643XX_ETH_DEFAULT_RX_BPDU_QUEUE_1	(1<<22)
+#define MV643XX_ETH_DEFAULT_RX_BPDU_QUEUE_2	(1<<23)
+#define MV643XX_ETH_DEFAULT_RX_BPDU_QUEUE_3	((1<<23) | (1<<22))
+#define MV643XX_ETH_DEFAULT_RX_BPDU_QUEUE_4	(1<<24)
+#define MV643XX_ETH_DEFAULT_RX_BPDU_QUEUE_5	((1<<24) | (1<<22))
+#define MV643XX_ETH_DEFAULT_RX_BPDU_QUEUE_6	((1<<24) | (1<<23))
+#define MV643XX_ETH_DEFAULT_RX_BPDU_QUEUE_7	((1<<24) | (1<<23) | (1<<22))
+
+#define	MV643XX_ETH_PORT_CONFIG_DEFAULT_VALUE			\
+		MV643XX_ETH_UNICAST_NORMAL_MODE		|	\
+		MV643XX_ETH_DEFAULT_RX_QUEUE_0		|	\
+		MV643XX_ETH_DEFAULT_RX_ARP_QUEUE_0	|	\
+		MV643XX_ETH_RECEIVE_BC_IF_NOT_IP_OR_ARP	|	\
+		MV643XX_ETH_RECEIVE_BC_IF_IP		|	\
+		MV643XX_ETH_RECEIVE_BC_IF_ARP		|	\
+		MV643XX_ETH_CAPTURE_TCP_FRAMES_DIS	|	\
+		MV643XX_ETH_CAPTURE_UDP_FRAMES_DIS	|	\
+		MV643XX_ETH_DEFAULT_RX_TCP_QUEUE_0	|	\
+		MV643XX_ETH_DEFAULT_RX_UDP_QUEUE_0	|	\
+		MV643XX_ETH_DEFAULT_RX_BPDU_QUEUE_0
+
+/* These macros describe Ethernet Port configuration extend reg (Px_cXR) bits*/
+#define MV643XX_ETH_CLASSIFY_EN				(1<<0)
+#define MV643XX_ETH_SPAN_BPDU_PACKETS_AS_NORMAL		0
+#define MV643XX_ETH_SPAN_BPDU_PACKETS_TO_RX_QUEUE_7	(1<<1)
+#define MV643XX_ETH_PARTITION_DISABLE			0
+#define MV643XX_ETH_PARTITION_ENABLE			(1<<2)
+
+#define	MV643XX_ETH_PORT_CONFIG_EXTEND_DEFAULT_VALUE		\
+		MV643XX_ETH_SPAN_BPDU_PACKETS_AS_NORMAL	|	\
+		MV643XX_ETH_PARTITION_DISABLE
+
+/* These macros describe Ethernet Port Sdma configuration reg (SDCR) bits */
+#define MV643XX_ETH_RIFB			(1<<0)
+#define MV643XX_ETH_RX_BURST_SIZE_1_64BIT		0
+#define MV643XX_ETH_RX_BURST_SIZE_2_64BIT		(1<<1)
+#define MV643XX_ETH_RX_BURST_SIZE_4_64BIT		(1<<2)
+#define MV643XX_ETH_RX_BURST_SIZE_8_64BIT		((1<<2) | (1<<1))
+#define MV643XX_ETH_RX_BURST_SIZE_16_64BIT		(1<<3)
+#define MV643XX_ETH_BLM_RX_NO_SWAP			(1<<4)
+#define MV643XX_ETH_BLM_RX_BYTE_SWAP			0
+#define MV643XX_ETH_BLM_TX_NO_SWAP			(1<<5)
+#define MV643XX_ETH_BLM_TX_BYTE_SWAP			0
+#define MV643XX_ETH_DESCRIPTORS_BYTE_SWAP		(1<<6)
+#define MV643XX_ETH_DESCRIPTORS_NO_SWAP			0
+#define MV643XX_ETH_TX_BURST_SIZE_1_64BIT		0
+#define MV643XX_ETH_TX_BURST_SIZE_2_64BIT		(1<<22)
+#define MV643XX_ETH_TX_BURST_SIZE_4_64BIT		(1<<23)
+#define MV643XX_ETH_TX_BURST_SIZE_8_64BIT		((1<<23) | (1<<22))
+#define MV643XX_ETH_TX_BURST_SIZE_16_64BIT		(1<<24)
+
+#define	MV643XX_ETH_IPG_INT_RX(value) ((value & 0x3fff) << 8)
+
+#define	MV643XX_ETH_PORT_SDMA_CONFIG_DEFAULT_VALUE		\
+		MV643XX_ETH_RX_BURST_SIZE_4_64BIT	|	\
+		MV643XX_ETH_IPG_INT_RX(0)		|	\
+		MV643XX_ETH_TX_BURST_SIZE_4_64BIT
+
+/* These macros describe Ethernet Port serial control reg (PSCR) bits */
+#define MV643XX_ETH_SERIAL_PORT_DISABLE			0
+#define MV643XX_ETH_SERIAL_PORT_ENABLE			(1<<0)
+#define MV643XX_ETH_FORCE_LINK_PASS			(1<<1)
+#define MV643XX_ETH_DO_NOT_FORCE_LINK_PASS		0
+#define MV643XX_ETH_ENABLE_AUTO_NEG_FOR_DUPLX		0
+#define MV643XX_ETH_DISABLE_AUTO_NEG_FOR_DUPLX		(1<<2)
+#define MV643XX_ETH_ENABLE_AUTO_NEG_FOR_FLOW_CTRL	0
+#define MV643XX_ETH_DISABLE_AUTO_NEG_FOR_FLOW_CTRL	(1<<3)
+#define MV643XX_ETH_ADV_NO_FLOW_CTRL			0
+#define MV643XX_ETH_ADV_SYMMETRIC_FLOW_CTRL		(1<<4)
+#define MV643XX_ETH_FORCE_FC_MODE_NO_PAUSE_DIS_TX	0
+#define MV643XX_ETH_FORCE_FC_MODE_TX_PAUSE_DIS		(1<<5)
+#define MV643XX_ETH_FORCE_BP_MODE_NO_JAM		0
+#define MV643XX_ETH_FORCE_BP_MODE_JAM_TX		(1<<7)
+#define MV643XX_ETH_FORCE_BP_MODE_JAM_TX_ON_RX_ERR	(1<<8)
+#define MV643XX_ETH_FORCE_LINK_FAIL			0
+#define MV643XX_ETH_DO_NOT_FORCE_LINK_FAIL		(1<<10)
+#define MV643XX_ETH_RETRANSMIT_16_ATTEMPTS		0
+#define MV643XX_ETH_RETRANSMIT_FOREVER			(1<<11)
+#define MV643XX_ETH_DISABLE_AUTO_NEG_SPEED_GMII		(1<<13)
+#define MV643XX_ETH_ENABLE_AUTO_NEG_SPEED_GMII		0
+#define MV643XX_ETH_DTE_ADV_0				0
+#define MV643XX_ETH_DTE_ADV_1				(1<<14)
+#define MV643XX_ETH_DISABLE_AUTO_NEG_BYPASS		0
+#define MV643XX_ETH_ENABLE_AUTO_NEG_BYPASS		(1<<15)
+#define MV643XX_ETH_AUTO_NEG_NO_CHANGE			0
+#define MV643XX_ETH_RESTART_AUTO_NEG			(1<<16)
+#define MV643XX_ETH_MAX_RX_PACKET_1518BYTE		0
+#define MV643XX_ETH_MAX_RX_PACKET_1522BYTE		(1<<17)
+#define MV643XX_ETH_MAX_RX_PACKET_1552BYTE		(1<<18)
+#define MV643XX_ETH_MAX_RX_PACKET_9022BYTE		((1<<18) | (1<<17))
+#define MV643XX_ETH_MAX_RX_PACKET_9192BYTE		(1<<19)
+#define MV643XX_ETH_MAX_RX_PACKET_9700BYTE		((1<<19) | (1<<17))
+#define MV643XX_ETH_SET_EXT_LOOPBACK			(1<<20)
+#define MV643XX_ETH_CLR_EXT_LOOPBACK			0
+#define MV643XX_ETH_SET_FULL_DUPLEX_MODE		(1<<21)
+#define MV643XX_ETH_SET_HALF_DUPLEX_MODE		0
+#define MV643XX_ETH_ENABLE_FLOW_CTRL_TX_RX_IN_FULL_DUPLEX (1<<22)
+#define MV643XX_ETH_DISABLE_FLOW_CTRL_TX_RX_IN_FULL_DUPLEX 0
+#define MV643XX_ETH_SET_GMII_SPEED_TO_10_100		0
+#define MV643XX_ETH_SET_GMII_SPEED_TO_1000		(1<<23)
+#define MV643XX_ETH_SET_MII_SPEED_TO_10			0
+#define MV643XX_ETH_SET_MII_SPEED_TO_100		(1<<24)
+
+#define	MV643XX_ETH_PORT_SERIAL_CONTROL_DEFAULT_VALUE		\
+		MV643XX_ETH_DO_NOT_FORCE_LINK_PASS	|	\
+		MV643XX_ETH_ENABLE_AUTO_NEG_FOR_DUPLX	|	\
+		MV643XX_ETH_DISABLE_AUTO_NEG_FOR_FLOW_CTRL |	\
+		MV643XX_ETH_ADV_SYMMETRIC_FLOW_CTRL	|	\
+		MV643XX_ETH_FORCE_FC_MODE_NO_PAUSE_DIS_TX |	\
+		MV643XX_ETH_FORCE_BP_MODE_NO_JAM	|	\
+		(1<<9)	/* reserved */			|	\
+		MV643XX_ETH_DO_NOT_FORCE_LINK_FAIL	|	\
+		MV643XX_ETH_RETRANSMIT_16_ATTEMPTS	|	\
+		MV643XX_ETH_ENABLE_AUTO_NEG_SPEED_GMII	|	\
+		MV643XX_ETH_DTE_ADV_0			|	\
+		MV643XX_ETH_DISABLE_AUTO_NEG_BYPASS	|	\
+		MV643XX_ETH_AUTO_NEG_NO_CHANGE		|	\
+		MV643XX_ETH_MAX_RX_PACKET_9700BYTE	|	\
+		MV643XX_ETH_CLR_EXT_LOOPBACK		|	\
+		MV643XX_ETH_SET_FULL_DUPLEX_MODE	|	\
+		MV643XX_ETH_ENABLE_FLOW_CTRL_TX_RX_IN_FULL_DUPLEX
+
+/* These macros describe Ethernet Serial Status reg (PSR) bits */
+#define MV643XX_ETH_PORT_STATUS_MODE_10_BIT		(1<<0)
+#define MV643XX_ETH_PORT_STATUS_LINK_UP			(1<<1)
+#define MV643XX_ETH_PORT_STATUS_FULL_DUPLEX		(1<<2)
+#define MV643XX_ETH_PORT_STATUS_FLOW_CONTROL		(1<<3)
+#define MV643XX_ETH_PORT_STATUS_GMII_1000		(1<<4)
+#define MV643XX_ETH_PORT_STATUS_MII_100			(1<<5)
+/* PSR bit 6 is undocumented */
+#define MV643XX_ETH_PORT_STATUS_TX_IN_PROGRESS		(1<<7)
+#define MV643XX_ETH_PORT_STATUS_AUTONEG_BYPASSED	(1<<8)
+#define MV643XX_ETH_PORT_STATUS_PARTITION		(1<<9)
+#define MV643XX_ETH_PORT_STATUS_TX_FIFO_EMPTY		(1<<10)
+/* PSR bits 11-31 are reserved */
+
+#define	MV643XX_ETH_PORT_DEFAULT_TRANSMIT_QUEUE_SIZE	800
+#define	MV643XX_ETH_PORT_DEFAULT_RECEIVE_QUEUE_SIZE	400
+
+#define MV643XX_ETH_DESC_SIZE				64
+
+#define MV643XX_ETH_SHARED_NAME	"mv643xx_eth_shared"
+#define MV643XX_ETH_NAME	"mv643xx_eth"
+
+struct mv643xx_eth_platform_data {
+	/* 
+	 * Non-values for mac_addr, phy_addr, port_config, etc.
+	 * override the default value.  Setting the corresponding
+	 * force_* field, causes the default value to be overridden
+	 * even when zero.
+	 */
+	unsigned int	force_phy_addr:1;
+	unsigned int	force_port_config:1;
+	unsigned int	force_port_config_extend:1;
+	unsigned int	force_port_sdma_config:1;
+	unsigned int	force_port_serial_control:1;
+	int		phy_addr;
+	char		*mac_addr;	/* pointer to mac address */
+	u32		port_config;
+	u32		port_config_extend;
+	u32		port_sdma_config;
+	u32		port_serial_control;
+	u32		tx_queue_size;
+	u32		rx_queue_size;
+	u32		tx_sram_addr;
+	u32		tx_sram_size;
+	u32		rx_sram_addr;
+	u32		rx_sram_size;
+};
+
+#endif /* __ASM_MV643XX_H */
diff -Nru a/include/linux/namei.h b/include/linux/namei.h
--- a/include/linux/namei.h	2005-03-11 12:51:42 -08:00
+++ b/include/linux/namei.h	2005-03-11 12:51:42 -08:00
@@ -39,12 +39,14 @@
  *  - ending slashes ok even for nonexistent files
  *  - internal "there are more path compnents" flag
  *  - locked when lookup done with dcache_lock held
+ *  - dentry cache is untrusted; force a real lookup
  */
 #define LOOKUP_FOLLOW		 1
 #define LOOKUP_DIRECTORY	 2
 #define LOOKUP_CONTINUE		 4
 #define LOOKUP_PARENT		16
 #define LOOKUP_NOALT		32
+#define LOOKUP_REVAL		64
 /*
  * Intent data
  */
diff -Nru a/include/linux/net.h b/include/linux/net.h
--- a/include/linux/net.h	2005-03-11 12:51:42 -08:00
+++ b/include/linux/net.h	2005-03-11 12:51:42 -08:00
@@ -61,6 +61,7 @@
 #define SOCK_ASYNC_NOSPACE	0
 #define SOCK_ASYNC_WAITDATA	1
 #define SOCK_NOSPACE		2
+#define SOCK_PASSCRED		3
 
 #ifndef ARCH_HAS_SOCKET_TYPES
 /** sock_type - Socket types
@@ -111,7 +112,6 @@
 	struct sock		*sk;
 	wait_queue_head_t	wait;
 	short			type;
-	unsigned char		passcred;
 };
 
 struct vm_area_struct;
diff -Nru a/include/linux/netdevice.h b/include/linux/netdevice.h
--- a/include/linux/netdevice.h	2005-03-11 12:51:51 -08:00
+++ b/include/linux/netdevice.h	2005-03-11 12:51:51 -08:00
@@ -328,9 +328,7 @@
 	unsigned short		flags;	/* interface flags (a la BSD)	*/
 	unsigned short		gflags;
         unsigned short          priv_flags; /* Like 'flags' but invisible to userspace. */
-        unsigned short          unused_alignment_fixer; /* Because we need priv_flags,
-                                                         * and we want to be 32-bit aligned.
-                                                         */
+	unsigned short		padded;	/* How much padding added by alloc_netdev() */
 
 	unsigned		mtu;	/* interface MTU value		*/
 	unsigned short		type;	/* interface hardware type	*/
@@ -469,7 +467,6 @@
 	int			(*hard_header_parse)(struct sk_buff *skb,
 						     unsigned char *haddr);
 	int			(*neigh_setup)(struct net_device *dev, struct neigh_parms *);
-	int			(*accept_fastpath)(struct net_device *, struct dst_entry*);
 #ifdef CONFIG_NETPOLL
 	int			netpoll_rx;
 #endif
@@ -487,8 +484,6 @@
 
 	/* class/net/name entry */
 	struct class_device	class_dev;
-	/* how much padding had been added by alloc_netdev() */
-	int padded;
 };
 
 #define	NETDEV_ALIGN		32
@@ -678,6 +673,8 @@
 extern int		dev_change_flags(struct net_device *, unsigned);
 extern int		dev_change_name(struct net_device *, char *);
 extern int		dev_set_mtu(struct net_device *, int);
+extern int		dev_set_mac_address(struct net_device *,
+					    struct sockaddr *);
 extern void		dev_queue_xmit_nit(struct sk_buff *skb, struct net_device *dev);
 
 extern void		dev_init(void);
@@ -921,8 +918,6 @@
 extern void		dev_mcast_init(void);
 extern int		netdev_max_backlog;
 extern int		weight_p;
-extern unsigned long	netdev_fc_xoff;
-extern atomic_t netdev_dropping;
 extern int		netdev_set_master(struct net_device *dev, struct net_device *master);
 extern int skb_checksum_help(struct sk_buff *skb, int inward);
 /* rx skb timestamps */
diff -Nru a/include/linux/netfilter_ipv4/ip_conntrack_tcp.h b/include/linux/netfilter_ipv4/ip_conntrack_tcp.h
--- a/include/linux/netfilter_ipv4/ip_conntrack_tcp.h	2005-03-11 12:51:42 -08:00
+++ b/include/linux/netfilter_ipv4/ip_conntrack_tcp.h	2005-03-11 12:51:42 -08:00
@@ -23,13 +23,16 @@
 /* SACK is permitted by the sender */
 #define IP_CT_TCP_FLAG_SACK_PERM		0x02
 
+/* This sender sent FIN first */
+#define IP_CT_TCP_FLAG_CLOSE_INIT		0x03
+
 struct ip_ct_tcp_state {
 	u_int32_t	td_end;		/* max of seq + len */
 	u_int32_t	td_maxend;	/* max of ack + max(win, 1) */
 	u_int32_t	td_maxwin;	/* max(win) */
 	u_int8_t	td_scale;	/* window scale factor */
 	u_int8_t	loose;		/* used when connection picked up from the middle */
-	u_int8_t	flags;		/* per direction state flags */
+	u_int8_t	flags;		/* per direction options */
 };
 
 struct ip_ct_tcp
diff -Nru a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h
--- a/include/linux/nfs_fs.h	2005-03-11 12:51:42 -08:00
+++ b/include/linux/nfs_fs.h	2005-03-11 12:51:42 -08:00
@@ -345,17 +345,14 @@
 extern struct file_operations nfs_dir_operations;
 extern struct dentry_operations nfs_dentry_operations;
 
+extern int nfs_instantiate(struct dentry *dentry, struct nfs_fh *fh, struct nfs_fattr *fattr);
+
 /*
  * linux/fs/nfs/symlink.c
  */
 extern struct inode_operations nfs_symlink_inode_operations;
 
 /*
- * linux/fs/nfs/locks.c
- */
-extern int nfs_lock(struct file *, int, struct file_lock *);
-
-/*
  * linux/fs/nfs/unlink.c
  */
 extern int  nfs_async_unlink(struct dentry *);
@@ -379,11 +376,8 @@
  * return value!)
  */
 extern int  nfs_sync_inode(struct inode *, unsigned long, unsigned int, int);
-extern int  nfs_flush_inode(struct inode *, unsigned long, unsigned int, int);
-extern int  nfs_flush_list(struct list_head *, int, int);
 #if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4)
 extern int  nfs_commit_inode(struct inode *, unsigned long, unsigned int, int);
-extern int  nfs_commit_list(struct list_head *, int);
 #else
 static inline int
 nfs_commit_inode(struct inode *inode, unsigned long idx_start, unsigned int npages, int how)
@@ -424,7 +418,6 @@
  * Allocate and free nfs_write_data structures
  */
 extern mempool_t *nfs_wdata_mempool;
-extern mempool_t *nfs_commit_mempool;
 
 static inline struct nfs_write_data *nfs_writedata_alloc(void)
 {
@@ -441,23 +434,6 @@
 	mempool_free(p, nfs_wdata_mempool);
 }
 
-extern void  nfs_writedata_release(struct rpc_task *task);
-
-static inline struct nfs_write_data *nfs_commit_alloc(void)
-{
-	struct nfs_write_data *p = mempool_alloc(nfs_commit_mempool, SLAB_NOFS);
-	if (p) {
-		memset(p, 0, sizeof(*p));
-		INIT_LIST_HEAD(&p->pages);
-	}
-	return p;
-}
-
-static inline void nfs_commit_free(struct nfs_write_data *p)
-{
-	mempool_free(p, nfs_commit_mempool);
-}
-
 /* Hack for future NFS swap support */
 #ifndef IS_SWAPFILE
 # define IS_SWAPFILE(inode)	(0)
@@ -469,7 +445,6 @@
 extern int  nfs_readpage(struct file *, struct page *);
 extern int  nfs_readpages(struct file *, struct address_space *,
 		struct list_head *, unsigned);
-extern int  nfs_pagein_list(struct list_head *, int);
 extern void nfs_readpage_result(struct rpc_task *);
 
 /*
@@ -610,6 +585,9 @@
 	wait_queue_head_t	cl_waitq;
 	struct rpc_wait_queue	cl_rpcwaitq;
 
+	/* used for the setclientid verifier */
+	struct timespec		cl_boot_time;
+
 	/* idmapper */
 	struct idmap *		cl_idmap;
 
@@ -617,6 +595,7 @@
 	 * This is used to generate the clientid, and the callback address.
 	 */
 	char			cl_ipaddr[16];
+	unsigned char		cl_id_uniquifier;
 };
 
 /*
@@ -696,21 +675,26 @@
 	int retry;
 };
 
+struct nfs4_state_recovery_ops {
+	int (*recover_open)(struct nfs4_state_owner *, struct nfs4_state *);
+	int (*recover_lock)(struct nfs4_state *, struct file_lock *);
+};
+
 extern struct dentry_operations nfs4_dentry_operations;
 extern struct inode_operations nfs4_dir_inode_operations;
 
 /* nfs4proc.c */
+extern int nfs4_map_errors(int err);
 extern int nfs4_proc_setclientid(struct nfs4_client *, u32, unsigned short);
 extern int nfs4_proc_setclientid_confirm(struct nfs4_client *);
-extern int nfs4_open_reclaim(struct nfs4_state_owner *, struct nfs4_state *);
 extern int nfs4_proc_async_renew(struct nfs4_client *);
 extern int nfs4_proc_renew(struct nfs4_client *);
 extern int nfs4_do_close(struct inode *inode, struct nfs4_state *state, mode_t mode);
-extern int nfs4_wait_clnt_recover(struct rpc_clnt *, struct nfs4_client *);
 extern struct inode *nfs4_atomic_open(struct inode *, struct dentry *, struct nameidata *);
 extern int nfs4_open_revalidate(struct inode *, struct dentry *, int);
-extern int nfs4_handle_exception(struct nfs_server *, int, struct nfs4_exception *);
-extern int nfs4_lock_reclaim(struct nfs4_state *state, struct file_lock *request);
+
+extern struct nfs4_state_recovery_ops nfs4_reboot_recovery_ops;
+extern struct nfs4_state_recovery_ops nfs4_network_partition_recovery_ops;
 
 /* nfs4renewd.c */
 extern void nfs4_schedule_state_renewal(struct nfs4_client *);
@@ -728,6 +712,7 @@
 
 extern struct nfs4_state_owner * nfs4_get_state_owner(struct nfs_server *, struct rpc_cred *);
 extern void nfs4_put_state_owner(struct nfs4_state_owner *);
+extern void nfs4_drop_state_owner(struct nfs4_state_owner *);
 extern struct nfs4_state * nfs4_get_open_state(struct inode *, struct nfs4_state_owner *);
 extern void nfs4_put_open_state(struct nfs4_state *);
 extern void nfs4_close_state(struct nfs4_state *, mode_t);
diff -Nru a/include/linux/nfs_fs_sb.h b/include/linux/nfs_fs_sb.h
--- a/include/linux/nfs_fs_sb.h	2005-03-11 12:51:52 -08:00
+++ b/include/linux/nfs_fs_sb.h	2005-03-11 12:51:52 -08:00
@@ -53,5 +53,6 @@
 #define NFS_CAP_HARDLINKS	(1U << 1)
 #define NFS_CAP_SYMLINKS	(1U << 2)
 #define NFS_CAP_ACLS		(1U << 3)
+#define NFS_CAP_ATOMIC_OPEN	(1U << 4)
 
 #endif
diff -Nru a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
--- a/include/linux/nfs_xdr.h	2005-03-11 12:51:51 -08:00
+++ b/include/linux/nfs_xdr.h	2005-03-11 12:51:51 -08:00
@@ -563,6 +563,7 @@
 	u32				count;
 	struct page **			pages;	/* zero-copy data */
 	unsigned int			pgbase;	/* zero-copy data */
+	const u32 *			bitmask;
 };
 
 struct nfs4_readdir_res {
@@ -681,7 +682,7 @@
 	int	(*read)    (struct nfs_read_data *);
 	int	(*write)   (struct nfs_write_data *);
 	int	(*commit)  (struct nfs_write_data *);
-	struct inode *	(*create)  (struct inode *, struct dentry *,
+	int	(*create)  (struct inode *, struct dentry *,
 			    struct iattr *, int);
 	int	(*remove)  (struct inode *, struct qstr *);
 	int	(*unlink_setup)  (struct rpc_message *,
@@ -693,13 +694,12 @@
 	int	(*symlink) (struct inode *, struct qstr *, struct qstr *,
 			    struct iattr *, struct nfs_fh *,
 			    struct nfs_fattr *);
-	int	(*mkdir)   (struct inode *, struct qstr *, struct iattr *,
-			    struct nfs_fh *, struct nfs_fattr *);
+	int	(*mkdir)   (struct inode *, struct dentry *, struct iattr *);
 	int	(*rmdir)   (struct inode *, struct qstr *);
 	int	(*readdir) (struct dentry *, struct rpc_cred *,
 			    u64, struct page *, unsigned int, int);
-	int	(*mknod)   (struct inode *, struct qstr *, struct iattr *,
-			    dev_t, struct nfs_fh *, struct nfs_fattr *);
+	int	(*mknod)   (struct inode *, struct dentry *, struct iattr *,
+			    dev_t);
 	int	(*statfs)  (struct nfs_server *, struct nfs_fh *,
 			    struct nfs_fsstat *);
 	int	(*fsinfo)  (struct nfs_server *, struct nfs_fh *,
@@ -731,7 +731,5 @@
 extern struct rpc_version	nfs_version2;
 extern struct rpc_version	nfs_version3;
 extern struct rpc_version	nfs_version4;
-extern struct rpc_program	nfs_program;
-extern struct rpc_stat		nfs_rpcstat;
 
 #endif
diff -Nru a/include/linux/nfsd/cache.h b/include/linux/nfsd/cache.h
--- a/include/linux/nfsd/cache.h	2005-03-11 12:51:41 -08:00
+++ b/include/linux/nfsd/cache.h	2005-03-11 12:51:41 -08:00
@@ -19,10 +19,9 @@
  * be hash_next and hash_prev.
  */
 struct svc_cacherep {
-	struct svc_cacherep *	c_hash_next;
-	struct svc_cacherep *	c_hash_prev;
-	struct svc_cacherep *	c_lru_next;
-	struct svc_cacherep *	c_lru_prev;
+	struct hlist_node	c_hash;
+	struct list_head	c_lru;
+
 	unsigned char		c_state,	/* unused, inprog, done */
 				c_type,		/* status, buffer */
 				c_secure : 1;	/* req came from port < 1024 */
diff -Nru a/include/linux/nfsd/nfsd.h b/include/linux/nfsd/nfsd.h
--- a/include/linux/nfsd/nfsd.h	2005-03-11 12:51:51 -08:00
+++ b/include/linux/nfsd/nfsd.h	2005-03-11 12:51:51 -08:00
@@ -96,9 +96,9 @@
 int		nfsd_open(struct svc_rqst *, struct svc_fh *, int,
 				int, struct file **);
 void		nfsd_close(struct file *);
-int		nfsd_read(struct svc_rqst *, struct svc_fh *,
-				loff_t, struct kvec *,int, unsigned long *);
-int		nfsd_write(struct svc_rqst *, struct svc_fh *,
+int 		nfsd_read(struct svc_rqst *, struct svc_fh *, struct file *,
+				loff_t, struct kvec *, int, unsigned long *);
+int 		nfsd_write(struct svc_rqst *, struct svc_fh *,struct file *,
 				loff_t, struct kvec *,int, unsigned long, int *);
 int		nfsd_readlink(struct svc_rqst *, struct svc_fh *,
 				char *, int *);
@@ -129,12 +129,12 @@
  * NFSv4 State
  */
 #ifdef CONFIG_NFSD_V4
-void nfs4_state_init(void);
+int nfs4_state_init(void);
 void nfs4_state_shutdown(void);
 time_t nfs4_lease_time(void);
 void nfs4_reset_lease(time_t leasetime);
 #else
-void static inline nfs4_state_init(void){}
+int static inline nfs4_state_init(void){return 0;}
 void static inline nfs4_state_shutdown(void){}
 time_t static inline nfs4_lease_time(void){return 0;}
 void static inline nfs4_reset_lease(time_t leasetime){}
@@ -209,6 +209,7 @@
 #define	nfserr_no_grace		__constant_htonl(NFSERR_NO_GRACE)
 #define	nfserr_reclaim_bad	__constant_htonl(NFSERR_RECLAIM_BAD)
 #define	nfserr_badname		__constant_htonl(NFSERR_BADNAME)
+#define	nfserr_cb_path_down	__constant_htonl(NFSERR_CB_PATH_DOWN)
 
 /* error codes for internal use */
 /* if a request fails due to kmalloc failure, it gets dropped.
diff -Nru a/include/linux/nfsd/state.h b/include/linux/nfsd/state.h
--- a/include/linux/nfsd/state.h	2005-03-11 12:51:41 -08:00
+++ b/include/linux/nfsd/state.h	2005-03-11 12:51:41 -08:00
@@ -67,12 +67,6 @@
 #define ZERO_STATEID(stateid)       (!memcmp((stateid), &zerostateid, sizeof(stateid_t)))
 #define ONE_STATEID(stateid)        (!memcmp((stateid), &onestateid, sizeof(stateid_t)))
 
-/* Delegation recall states */
-#define NFS4_NO_RECALL			0x000
-#define NFS4_RECALL_IN_PROGRESS		0x001
-#define NFS4_RECALL_COMPLETE		0x002
-#define NFS4_REAP_DELEG			0x004
-
 struct nfs4_cb_recall {
 	u32			cbr_ident;
 	int			cbr_trunc;
@@ -86,13 +80,11 @@
 	struct list_head	dl_del_perfile; /* nfs4_file->fi_del_perfile */
 	struct list_head	dl_del_perclnt; /* nfs4_client->cl_del_perclnt*/
 	struct list_head	dl_recall_lru;  /* delegation recalled */
-	atomic_t		dl_recall_cnt;  /* resend cb_recall only once */
 	atomic_t		dl_count;       /* ref count */
-	atomic_t		dl_state;       /* recall state */
 	struct nfs4_client	*dl_client;
 	struct nfs4_file	*dl_file;
 	struct file_lock	*dl_flock;
-	struct nfs4_stateid	*dl_stp;
+	struct file		*dl_vfs_file;
 	u32			dl_type;
 	time_t			dl_time;
 	struct nfs4_cb_recall	dl_recall;
@@ -141,7 +133,6 @@
 	clientid_t		cl_clientid;	/* generated by server */
 	nfs4_verifier		cl_confirm;	/* generated by server */
 	struct nfs4_callback	cl_callback;    /* callback info */
-	time_t			cl_first_state; /* first state aquisition*/
 	atomic_t		cl_count;	/* ref count */
 };
 
@@ -153,8 +144,6 @@
 struct nfs4_client_reclaim {
 	struct list_head	cr_strhash;	/* hash by cr_name */
 	struct xdr_netobj 	cr_name; 	/* id generated by client */
-	time_t			cr_first_state; /* first state aquisition */
-	u32			cr_expired;     /* boolean: lease expired? */
 };
 
 static inline void
@@ -258,7 +247,6 @@
 	struct nfs4_file            * st_file;
 	stateid_t                     st_stateid;
 	struct file                 * st_vfs_file;
-	int                           st_vfs_set;
 	unsigned long                 st_access_bmap;
 	unsigned long                 st_deny_bmap;
 };
@@ -282,7 +270,7 @@
 extern time_t nfs4_laundromat(void);
 extern int nfsd4_renew(clientid_t *clid);
 extern int nfs4_preprocess_stateid_op(struct svc_fh *current_fh, 
-		stateid_t *stateid, int flags);
+		stateid_t *stateid, int flags, struct file **filp);
 extern int nfs4_share_conflict(struct svc_fh *current_fh, 
 		unsigned int deny_type);
 extern void nfs4_lock_state(void);
@@ -292,7 +280,8 @@
 extern void put_nfs4_client(struct nfs4_client *clp);
 extern void nfs4_free_stateowner(struct kref *kref);
 extern void nfsd4_probe_callback(struct nfs4_client *clp);
-extern int nfsd4_cb_recall(struct nfs4_delegation *dp);
+extern void nfsd4_cb_recall(struct nfs4_delegation *dp);
+extern void nfs4_put_delegation(struct nfs4_delegation *dp);
 
 static inline void
 nfs4_put_stateowner(struct nfs4_stateowner *so)
diff -Nru a/include/linux/nfsd/xdr4.h b/include/linux/nfsd/xdr4.h
--- a/include/linux/nfsd/xdr4.h	2005-03-11 12:51:41 -08:00
+++ b/include/linux/nfsd/xdr4.h	2005-03-11 12:51:41 -08:00
@@ -241,6 +241,7 @@
 	u32		rd_length;          /* request */
 	struct kvec	rd_iov[RPCSVC_MAXPAGES];
 	int		rd_vlen;
+	struct file     *rd_filp;
 	
 	struct svc_rqst *rd_rqstp;          /* response */
 	struct svc_fh * rd_fhp;             /* response */
diff -Nru a/include/linux/nodemask.h b/include/linux/nodemask.h
--- a/include/linux/nodemask.h	2005-03-11 12:51:41 -08:00
+++ b/include/linux/nodemask.h	2005-03-11 12:51:41 -08:00
@@ -10,6 +10,8 @@
  *
  * For details of nodemask_scnprintf() and nodemask_parse(),
  * see bitmap_scnprintf() and bitmap_parse() in lib/bitmap.c.
+ * For details of nodelist_scnprintf() and nodelist_parse(), see
+ * bitmap_scnlistprintf() and bitmap_parselist(), also in bitmap.c.
  *
  * The available nodemask operations are:
  *
@@ -48,6 +50,8 @@
  *
  * int nodemask_scnprintf(buf, len, mask) Format nodemask for printing
  * int nodemask_parse(ubuf, ulen, mask)	Parse ascii string as nodemask
+ * int nodelist_scnprintf(buf, len, mask) Format nodemask as list for printing
+ * int nodelist_parse(buf, map)		Parse ascii string as nodelist
  *
  * for_each_node_mask(node, mask)	for-loop node over mask
  *
@@ -281,12 +285,26 @@
 	return bitmap_scnprintf(buf, len, srcp->bits, nbits);
 }
 
-#define nodemask_parse(ubuf, ulen, src) \
-			__nodemask_parse((ubuf), (ulen), &(src), MAX_NUMNODES)
+#define nodemask_parse(ubuf, ulen, dst) \
+			__nodemask_parse((ubuf), (ulen), &(dst), MAX_NUMNODES)
 static inline int __nodemask_parse(const char __user *buf, int len,
 					nodemask_t *dstp, int nbits)
 {
 	return bitmap_parse(buf, len, dstp->bits, nbits);
+}
+
+#define nodelist_scnprintf(buf, len, src) \
+			__nodelist_scnprintf((buf), (len), &(src), MAX_NUMNODES)
+static inline int __nodelist_scnprintf(char *buf, int len,
+					const nodemask_t *srcp, int nbits)
+{
+	return bitmap_scnlistprintf(buf, len, srcp->bits, nbits);
+}
+
+#define nodelist_parse(buf, dst) __nodelist_parse((buf), &(dst), MAX_NUMNODES)
+static inline int __nodelist_parse(const char *buf, nodemask_t *dstp, int nbits)
+{
+	return bitmap_parselist(buf, dstp->bits, nbits);
 }
 
 #if MAX_NUMNODES > 1
diff -Nru a/include/linux/pci.h b/include/linux/pci.h
--- a/include/linux/pci.h	2005-03-11 12:51:46 -08:00
+++ b/include/linux/pci.h	2005-03-11 12:51:46 -08:00
@@ -549,8 +549,6 @@
 	unsigned int	irq;
 	struct resource resource[DEVICE_COUNT_RESOURCE]; /* I/O and memory regions + expansion ROMs */
 
-	char *		slot_name;	/* pointer to dev.bus_id */
-
 	/* These fields are used by common fixups */
 	unsigned int	transparent:1;	/* Transparent PCI bridge */
 	unsigned int	multifunction:1;/* Part of multi-function device */
@@ -642,8 +640,10 @@
 };
 
 struct pci_raw_ops {
-	int (*read)(int dom, int bus, int devfn, int reg, int len, u32 *val);
-	int (*write)(int dom, int bus, int devfn, int reg, int len, u32 val);
+	int (*read)(unsigned int domain, unsigned int bus, unsigned int devfn,
+		    int reg, int len, u32 *val);
+	int (*write)(unsigned int domain, unsigned int bus, unsigned int devfn,
+		     int reg, int len, u32 val);
 };
 
 extern struct pci_raw_ops *raw_pci_ops;
@@ -966,9 +966,8 @@
  */
 #ifndef CONFIG_PCI_DOMAINS
 static inline int pci_domain_nr(struct pci_bus *bus) { return 0; }
-static inline int pci_name_bus(char *name, struct pci_bus *bus)
+static inline int pci_proc_domain(struct pci_bus *bus)
 {
-	sprintf(name, "%02x", bus->number);
 	return 0;
 }
 #endif
diff -Nru a/include/linux/pci_ids.h b/include/linux/pci_ids.h
--- a/include/linux/pci_ids.h	2005-03-11 12:51:52 -08:00
+++ b/include/linux/pci_ids.h	2005-03-11 12:51:52 -08:00
@@ -352,10 +352,21 @@
 #define PCI_DEVICE_ID_ATI_RS300_133	0x5831
 #define PCI_DEVICE_ID_ATI_RS300_166	0x5832
 #define PCI_DEVICE_ID_ATI_RS300_200	0x5833
+#define PCI_DEVICE_ID_ATI_RS350_100     0x7830
+#define PCI_DEVICE_ID_ATI_RS350_133     0x7831
+#define PCI_DEVICE_ID_ATI_RS350_166     0x7832
+#define PCI_DEVICE_ID_ATI_RS350_200     0x7833
+#define PCI_DEVICE_ID_ATI_RS400_100     0x5a30
+#define PCI_DEVICE_ID_ATI_RS400_133     0x5a31
+#define PCI_DEVICE_ID_ATI_RS400_166     0x5a32
+#define PCI_DEVICE_ID_ATI_RS400_200     0x5a33
+#define PCI_DEVICE_ID_ATI_RS480         0x5950
 /* ATI IXP Chipset */
 #define PCI_DEVICE_ID_ATI_IXP200_IDE	0x4349
 #define PCI_DEVICE_ID_ATI_IXP300_IDE	0x4369
+#define PCI_DEVICE_ID_ATI_IXP300_SATA   0x436e
 #define PCI_DEVICE_ID_ATI_IXP400_IDE	0x4376
+#define PCI_DEVICE_ID_ATI_IXP400_SATA   0x4379
 
 #define PCI_VENDOR_ID_VLSI		0x1004
 #define PCI_DEVICE_ID_VLSI_82C592	0x0005
@@ -386,6 +397,8 @@
 #define PCI_DEVICE_ID_NS_SCx200_VIDEO	0x0504
 #define PCI_DEVICE_ID_NS_SCx200_XBUS	0x0505
 #define PCI_DEVICE_ID_NS_SC1100_BRIDGE	0x0510
+#define PCI_DEVICE_ID_NS_SC1100_SMI	0x0511
+#define PCI_DEVICE_ID_NS_SC1100_XBUS	0x0515
 #define PCI_DEVICE_ID_NS_87410		0xd001
 
 #define PCI_VENDOR_ID_TSENG		0x100c
@@ -506,6 +519,7 @@
 #define PCI_DEVICE_ID_AMD_OPUS_7449	0x7449
 #	define PCI_DEVICE_ID_AMD_VIPER_7449	PCI_DEVICE_ID_AMD_OPUS_7449
 #define PCI_DEVICE_ID_AMD_8111_LAN	0x7462
+#define PCI_DEVICE_ID_AMD_8111_LPC	0x7468
 #define PCI_DEVICE_ID_AMD_8111_IDE	0x7469
 #define PCI_DEVICE_ID_AMD_8111_SMBUS2	0x746a
 #define PCI_DEVICE_ID_AMD_8111_SMBUS	0x746b
@@ -696,6 +710,7 @@
 #define PCI_DEVICE_ID_HP_DIVA_EVEREST	0x1282
 #define PCI_DEVICE_ID_HP_DIVA_AUX	0x1290
 #define PCI_DEVICE_ID_HP_CISSA		0x3220
+#define PCI_DEVICE_ID_HP_CISSB		0x3230
 
 #define PCI_VENDOR_ID_PCTECH		0x1042
 #define PCI_DEVICE_ID_PCTECH_RZ1000	0x1000
@@ -861,7 +876,13 @@
 #define PCI_DEVICE_ID_APPLE_IPID_ATA100	0x003b
 #define PCI_DEVICE_ID_APPLE_KEYLARGO_I	0x003e
 #define PCI_DEVICE_ID_APPLE_K2_ATA100	0x0043
+#define PCI_DEVICE_ID_APPLE_U3_AGP	0x004b
 #define PCI_DEVICE_ID_APPLE_K2_GMAC	0x004c
+#define PCI_DEVICE_ID_APPLE_SH_ATA      0x0050
+#define PCI_DEVICE_ID_APPLE_SH_SUNGEM   0x0051
+#define PCI_DEVICE_ID_APPLE_SH_FW       0x0052
+#define PCI_DEVICE_ID_APPLE_U3L_AGP	0x0058
+#define PCI_DEVICE_ID_APPLE_U3H_AGP	0x0059
 #define PCI_DEVICE_ID_APPLE_TIGON3	0x1645
 
 #define PCI_VENDOR_ID_YAMAHA		0x1073
@@ -1091,6 +1112,7 @@
 #define PCI_DEVICE_ID_NVIDIA_TNT		0x0020
 #define PCI_DEVICE_ID_NVIDIA_TNT2		0x0028
 #define PCI_DEVICE_ID_NVIDIA_UTNT2		0x0029
+#define PCI_DEVICE_ID_NVIDIA_TNT_UNKNOWN        0x002a
 #define PCI_DEVICE_ID_NVIDIA_VTNT2		0x002C
 #define PCI_DEVICE_ID_NVIDIA_UVTNT2		0x002D
 #define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_IDE	0x0035
@@ -1098,6 +1120,12 @@
 #define PCI_DEVICE_ID_NVIDIA_NVENET_10		0x0037
 #define PCI_DEVICE_ID_NVIDIA_NVENET_11		0x0038
 #define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SATA2	0x003e
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_6800_ULTRA 0x0040
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_6800       0x0041
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_6800_LE    0x0042
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_6800_GT    0x0045
+#define PCI_DEVICE_ID_NVIDIA_QUADRO_FX_4000     0x004E
+#define PCI_DEVICE_ID_NVIDIA_NFORCE4_SMBUS	0x0052
 #define PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_IDE	0x0053
 #define PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_SATA	0x0054
 #define PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_SATA2	0x0055
@@ -1114,6 +1142,12 @@
 #define PCI_DEVICE_ID_NVIDIA_NVENET_5		0x008c
 #define PCI_DEVICE_ID_NVIDIA_NFORCE2S_SATA	0x008e
 #define PCI_DEVICE_ID_NVIDIA_ITNT2		0x00A0
+#define PCI_DEVICE_ID_GEFORCE_6800A             0x00c1
+#define PCI_DEVICE_ID_GEFORCE_6800A_LE          0x00c2
+#define PCI_DEVICE_ID_GEFORCE_GO_6800           0x00c8
+#define PCI_DEVICE_ID_GEFORCE_GO_6800_ULTRA     0x00c9
+#define PCI_DEVICE_ID_QUADRO_FX_GO1400          0x00cc
+#define PCI_DEVICE_ID_QUADRO_FX_1400            0x00ce
 #define PCI_DEVICE_ID_NVIDIA_NFORCE3		0x00d1
 #define PCI_DEVICE_ID_NVIDIA_MCP3_AUDIO		0x00da
 #define PCI_DEVICE_ID_NVIDIA_NFORCE3_SMBUS	0x00d4
@@ -1134,21 +1168,43 @@
 #define PCI_DEVICE_ID_NVIDIA_GEFORCE2_MX2	0x0111
 #define PCI_DEVICE_ID_NVIDIA_GEFORCE2_GO	0x0112
 #define PCI_DEVICE_ID_NVIDIA_QUADRO2_MXR	0x0113
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_6600_GT	0x0140
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_6600	0x0141
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_6610_XL	0x0145
+#define PCI_DEVICE_ID_NVIDIA_QUADRO_FX_540	0x014E
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_6200	0x014F
 #define PCI_DEVICE_ID_NVIDIA_GEFORCE2_GTS	0x0150
 #define PCI_DEVICE_ID_NVIDIA_GEFORCE2_GTS2	0x0151
 #define PCI_DEVICE_ID_NVIDIA_GEFORCE2_ULTRA	0x0152
 #define PCI_DEVICE_ID_NVIDIA_QUADRO2_PRO	0x0153
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_6200_TURBOCACHE 0x0161
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_GO_6200    0x0164
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_GO_6250    0x0166
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_GO_6200_1  0x0167
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_GO_6250_1  0x0168
 #define PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_460	0x0170
 #define PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_440	0x0171
 #define PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_420	0x0172
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_440_SE	0x0173
 #define PCI_DEVICE_ID_NVIDIA_GEFORCE4_440_GO	0x0174
 #define PCI_DEVICE_ID_NVIDIA_GEFORCE4_420_GO	0x0175
 #define PCI_DEVICE_ID_NVIDIA_GEFORCE4_420_GO_M32 0x0176
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_460_GO    0x0177
 #define PCI_DEVICE_ID_NVIDIA_QUADRO4_500XGL	0x0178
 #define PCI_DEVICE_ID_NVIDIA_GEFORCE4_440_GO_M64 0x0179
 #define PCI_DEVICE_ID_NVIDIA_QUADRO4_200	0x017A
 #define PCI_DEVICE_ID_NVIDIA_QUADRO4_550XGL	0x017B
 #define PCI_DEVICE_ID_NVIDIA_QUADRO4_500_GOGL	0x017C
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_410_GO_M16 0x017D
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_440_8X 0x0181
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_440SE_8X 0x0182
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_420_8X 0x0183
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_448_GO    0x0186
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_488_GO    0x0187
+#define PCI_DEVICE_ID_NVIDIA_QUADRO4_580_XGL    0x0188
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_MAC    0x0189
+#define PCI_DEVICE_ID_NVIDIA_QUADRO4_280_NVS    0x018A
+#define PCI_DEVICE_ID_NVIDIA_QUADRO4_380_XGL    0x018B
 #define PCI_DEVICE_ID_NVIDIA_IGEFORCE2		0x01a0
 #define PCI_DEVICE_ID_NVIDIA_NFORCE		0x01a4
 #define PCI_DEVICE_ID_NVIDIA_MCP1_AUDIO		0x01b1
@@ -1160,13 +1216,61 @@
 #define PCI_DEVICE_ID_NVIDIA_GEFORCE3_1		0x0201
 #define PCI_DEVICE_ID_NVIDIA_GEFORCE3_2		0x0202
 #define PCI_DEVICE_ID_NVIDIA_QUADRO_DDC		0x0203
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_6800B      0x0211
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_6800B_LE   0x0212
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_6800B_GT   0x0215
 #define PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4600	0x0250
 #define PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4400	0x0251
 #define PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4200	0x0253
 #define PCI_DEVICE_ID_NVIDIA_QUADRO4_900XGL	0x0258
 #define PCI_DEVICE_ID_NVIDIA_QUADRO4_750XGL	0x0259
 #define PCI_DEVICE_ID_NVIDIA_QUADRO4_700XGL	0x025B
-#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO_5200	0x0329
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4800	0x0280
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4800_8X    0x0281
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4800SE     0x0282
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_4200_GO       0x0286
+#define PCI_DEVICE_ID_NVIDIA_QUADRO4_980_XGL        0x0288
+#define PCI_DEVICE_ID_NVIDIA_QUADRO4_780_XGL        0x0289
+#define PCI_DEVICE_ID_NVIDIA_QUADRO4_700_GOGL       0x028C
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5800_ULTRA  0x0301
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5800        0x0302
+#define PCI_DEVICE_ID_NVIDIA_QUADRO_FX_2000         0x0308
+#define PCI_DEVICE_ID_NVIDIA_QUADRO_FX_1000         0x0309
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5600_ULTRA  0x0311
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5600        0x0312
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5600SE      0x0314
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5600      0x031A
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5650      0x031B
+#define PCI_DEVICE_ID_NVIDIA_QUADRO_FX_GO700        0x031C
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5200        0x0320
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5200_ULTRA  0x0321
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5200_1      0x0322
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5200SE      0x0323
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5200      0x0324
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5250      0x0325
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5500        0x0326
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5100        0x0327
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5250_32   0x0328
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO_5200	    0x0329
+#define PCI_DEVICE_ID_NVIDIA_QUADRO_NVS_280_PCI     0x032A
+#define PCI_DEVICE_ID_NVIDIA_QUADRO_FX_500          0x032B
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5300      0x032C
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5100      0x032D
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5900_ULTRA  0x0330
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5900        0x0331
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5900XT      0x0332
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5950_ULTRA  0x0333
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5900ZT      0x0334
+#define PCI_DEVICE_ID_NVIDIA_QUADRO_FX_3000         0x0338
+#define PCI_DEVICE_ID_NVIDIA_QUADRO_FX_700          0x033F
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5700_ULTRA  0x0341
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5700        0x0342
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5700LE      0x0343
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5700VE      0x0344
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5700_1    0x0347
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5700_2    0x0348
+#define PCI_DEVICE_ID_NVIDIA_QUADRO_FX_GO1000       0x034C
+#define PCI_DEVICE_ID_NVIDIA_QUADRO_FX_1100         0x034E
 
 #define PCI_VENDOR_ID_IMS		0x10e0
 #define PCI_DEVICE_ID_IMS_8849		0x8849
@@ -1497,6 +1601,9 @@
 #define PCI_DEVICE_ID_ARTOP_AEC7612D	0x8040
 #define PCI_DEVICE_ID_ARTOP_AEC7612SUW	0x8050
 #define PCI_DEVICE_ID_ARTOP_8060	0x8060
+#define PCI_DEVICE_ID_ARTOP_AEC67160	0x8080
+#define PCI_DEVICE_ID_ARTOP_AEC67160_2	0x8081
+#define PCI_DEVICE_ID_ARTOP_AEC67162	0x808a
 
 #define PCI_VENDOR_ID_ZEITNET		0x1193
 #define PCI_DEVICE_ID_ZEITNET_1221	0x0001
@@ -1609,6 +1716,10 @@
 #define PCI_DEVICE_ID_PC300_TE_M_2	0x0320
 #define PCI_DEVICE_ID_PC300_TE_M_1	0x0321
 
+/* Allied Telesyn */
+#define PCI_VENDOR_ID_AT    		0x1259
+#define PCI_SUBDEVICE_ID_AT_2701FX	0x2703
+
 #define PCI_VENDOR_ID_ESSENTIAL		0x120f
 #define PCI_DEVICE_ID_ESSENTIAL_ROADRUNNER	0x0001
 
@@ -1652,6 +1763,11 @@
 #define PCI_DEVICE_ID_OPTIBASE_VPLEXCC	0x2120
 #define PCI_DEVICE_ID_OPTIBASE_VQUEST	0x2130
 
+/* Allied Telesyn */
+#define PCI_VENDOR_ID_AT    		0x1259
+#define PCI_SUBDEVICE_ID_AT_2700FX	0x2701
+#define PCI_SUBDEVICE_ID_AT_2701FX	0x2703
+
 #define PCI_VENDOR_ID_ESS		0x125d
 #define PCI_DEVICE_ID_ESS_ESS1968	0x1968
 #define PCI_DEVICE_ID_ESS_AUDIOPCI	0x1969
@@ -1905,6 +2021,8 @@
 #define PCI_DEVICE_ID_OXSEMI_16PCI954PP	0x9513
 #define PCI_DEVICE_ID_OXSEMI_16PCI952	0x9521
 
+#define PCI_VENDOR_ID_SAMSUNG		0x144d
+
 #define PCI_VENDOR_ID_AIRONET		0x14b9
 #define PCI_DEVICE_ID_AIRONET_4800_1	0x0001
 #define PCI_DEVICE_ID_AIRONET_4800	0x4500 // values switched?  see
@@ -2037,8 +2155,8 @@
 
 #define PCI_VENDOR_ID_TOPSPIN		0x1867
 
-#define PCI_VENDOR_ID_ARC               0x192E
-#define PCI_DEVICE_ID_ARC_EHCI          0x0101
+#define PCI_VENDOR_ID_TDI               0x192E
+#define PCI_DEVICE_ID_TDI_EHCI          0x0101
 
 #define PCI_VENDOR_ID_SYMPHONY		0x1c1c
 #define PCI_DEVICE_ID_SYMPHONY_101	0x0001
diff -Nru a/include/linux/personality.h b/include/linux/personality.h
--- a/include/linux/personality.h	2005-03-11 12:51:46 -08:00
+++ b/include/linux/personality.h	2005-03-11 12:51:46 -08:00
@@ -18,6 +18,7 @@
  * These occupy the top three bytes.
  */
 enum {
+	ADDR_NO_RANDOMIZE = 	0x0040000,	/* disable randomization of VA space */
 	FDPIC_FUNCPTRS =	0x0080000,	/* userspace function ptrs point to descriptors
 						 * (signal handling)
 						 */
@@ -35,7 +36,7 @@
  * Security-relevant compatibility flags that must be
  * cleared upon setuid or setgid exec:
  */
-#define PER_CLEAR_ON_SETID (READ_IMPLIES_EXEC)
+#define PER_CLEAR_ON_SETID (READ_IMPLIES_EXEC|ADDR_NO_RANDOMIZE)
 
 /*
  * Personality types.
diff -Nru a/include/linux/pkt_cls.h b/include/linux/pkt_cls.h
--- a/include/linux/pkt_cls.h	2005-03-11 12:51:41 -08:00
+++ b/include/linux/pkt_cls.h	2005-03-11 12:51:41 -08:00
@@ -221,14 +221,20 @@
 	struct tc_u32_key	keys[0];
 };
 
-#ifdef CONFIG_CLS_U32_PERF
+struct tc_u32_mark
+{
+	__u32		val;
+	__u32		mask;
+	__u32		success;
+};
+
 struct tc_u32_pcnt
 {
 	__u64 rcnt;
 	__u64 rhit;
 	__u64 kcnts[0];
 };
-#endif
+
 /* Flags */
 
 #define TC_U32_TERMINAL		1
@@ -318,5 +324,102 @@
 };
 
 #define TCA_TCINDEX_MAX     (__TCA_TCINDEX_MAX - 1)
+
+/* Basic filter */
+
+enum
+{
+	TCA_BASIC_UNSPEC,
+	TCA_BASIC_CLASSID,
+	TCA_BASIC_EMATCHES,
+	TCA_BASIC_ACT,
+	TCA_BASIC_POLICE,
+	__TCA_BASIC_MAX
+};
+
+#define TCA_BASIC_MAX (__TCA_BASIC_MAX - 1)
+
+/* Extended Matches */
+
+struct tcf_ematch_tree_hdr
+{
+	__u16		nmatches;
+	__u16		progid;
+};
+
+enum
+{
+	TCA_EMATCH_TREE_UNSPEC,
+	TCA_EMATCH_TREE_HDR,
+	TCA_EMATCH_TREE_LIST,
+	__TCA_EMATCH_TREE_MAX
+};
+#define TCA_EMATCH_TREE_MAX (__TCA_EMATCH_TREE_MAX - 1)
+
+struct tcf_ematch_hdr
+{
+	__u16		matchid;
+	__u16		kind;
+	__u16		flags;
+	__u16		pad; /* currently unused */
+};
+
+/*  0                   1
+ *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 
+ * +-----------------------+-+-+---+
+ * |         Unused        |S|I| R |
+ * +-----------------------+-+-+---+
+ *
+ * R(2) ::= relation to next ematch
+ *          where: 0 0 END (last ematch)
+ *                 0 1 AND
+ *                 1 0 OR
+ *                 1 1 Unused (invalid)
+ * I(1) ::= invert result
+ * S(1) ::= simple payload
+ */
+#define TCF_EM_REL_END	0
+#define TCF_EM_REL_AND	(1<<0)
+#define TCF_EM_REL_OR	(1<<1)
+#define TCF_EM_INVERT	(1<<2)
+#define TCF_EM_SIMPLE	(1<<3)
+
+#define TCF_EM_REL_MASK	3
+#define TCF_EM_REL_VALID(v) (((v) & TCF_EM_REL_MASK) != TCF_EM_REL_MASK)
+
+enum
+{
+	TCF_LAYER_LINK,
+	TCF_LAYER_NETWORK,
+	TCF_LAYER_TRANSPORT,
+	__TCF_LAYER_MAX
+};
+#define TCF_LAYER_MAX (__TCF_LAYER_MAX - 1)
+
+/* Ematch type assignments
+ *   1..32767		Reserved for ematches inside kernel tree
+ *   32768..65535	Free to use, not reliable
+ */
+enum
+{
+	TCF_EM_CONTAINER,
+	TCF_EM_CMP,
+	TCF_EM_NBYTE,
+	TCF_EM_U32,
+	TCF_EM_META,
+	__TCF_EM_MAX
+};
+
+enum
+{
+	TCF_EM_PROG_TC
+};
+
+enum
+{
+	TCF_EM_OPND_EQ,
+	TCF_EM_OPND_GT,
+	TCF_EM_OPND_LT
+};
 
 #endif
diff -Nru a/include/linux/posix-timers.h b/include/linux/posix-timers.h
--- a/include/linux/posix-timers.h	2005-03-11 12:51:46 -08:00
+++ b/include/linux/posix-timers.h	2005-03-11 12:51:46 -08:00
@@ -3,6 +3,36 @@
 
 #include <linux/spinlock.h>
 #include <linux/list.h>
+#include <linux/sched.h>
+
+union cpu_time_count {
+	cputime_t cpu;
+	unsigned long long sched;
+};
+
+struct cpu_timer_list {
+	struct list_head entry;
+	union cpu_time_count expires, incr;
+	struct task_struct *task;
+	int firing;
+};
+
+#define CPUCLOCK_PID(clock)		((pid_t) ~((clock) >> 3))
+#define CPUCLOCK_PERTHREAD(clock) \
+	(((clock) & (clockid_t) CPUCLOCK_PERTHREAD_MASK) != 0)
+#define CPUCLOCK_PID_MASK	7
+#define CPUCLOCK_PERTHREAD_MASK	4
+#define CPUCLOCK_WHICH(clock)	((clock) & (clockid_t) CPUCLOCK_CLOCK_MASK)
+#define CPUCLOCK_CLOCK_MASK	3
+#define CPUCLOCK_PROF		0
+#define CPUCLOCK_VIRT		1
+#define CPUCLOCK_SCHED		2
+#define CPUCLOCK_MAX		3
+
+#define MAKE_PROCESS_CPUCLOCK(pid, clock) \
+	((~(clockid_t) (pid) << 3) | (clockid_t) (clock))
+#define MAKE_THREAD_CPUCLOCK(tid, clock) \
+	MAKE_PROCESS_CPUCLOCK((tid), (clock) | CPUCLOCK_PERTHREAD_MASK)
 
 /* POSIX.1b interval timer structure. */
 struct k_itimer {
@@ -13,15 +43,27 @@
 	int it_overrun;			/* overrun on pending signal  */
 	int it_overrun_last;		/* overrun on last delivered signal */
 	int it_requeue_pending;         /* waiting to requeue this timer */
+#define REQUEUE_PENDING 1
 	int it_sigev_notify;		/* notify word of sigevent struct */
 	int it_sigev_signo;		/* signo word of sigevent struct */
 	sigval_t it_sigev_value;	/* value word of sigevent struct */
-	unsigned long it_incr;		/* interval specified in jiffies */
 	struct task_struct *it_process;	/* process to send signal to */
-	struct timer_list it_timer;
 	struct sigqueue *sigq;		/* signal queue entry. */
-	struct list_head abs_timer_entry; /* clock abs_timer_list */
-	struct timespec wall_to_prev;   /* wall_to_monotonic used when set */
+	union {
+		struct {
+			struct timer_list timer;
+			struct list_head abs_timer_entry; /* clock abs_timer_list */
+			struct timespec wall_to_prev;   /* wall_to_monotonic used when set */
+			unsigned long incr; /* interval in jiffies */
+		} real;
+		struct cpu_timer_list cpu;
+		struct {
+			unsigned int clock;
+			unsigned int node;
+			unsigned long incr;
+			unsigned long expires;
+		} mmtimer;
+	} it;
 };
 
 struct k_clock_abs {
@@ -30,26 +72,27 @@
 };
 struct k_clock {
 	int res;		/* in nano seconds */
+	int (*clock_getres) (clockid_t which_clock, struct timespec *tp);
 	struct k_clock_abs *abs_struct;
-	int (*clock_set) (struct timespec * tp);
-	int (*clock_get) (struct timespec * tp);
+	int (*clock_set) (clockid_t which_clock, struct timespec * tp);
+	int (*clock_get) (clockid_t which_clock, struct timespec * tp);
 	int (*timer_create) (struct k_itimer *timer);
-	int (*nsleep) (int which_clock, int flags,
-		       struct timespec * t);
+	int (*nsleep) (clockid_t which_clock, int flags, struct timespec *);
 	int (*timer_set) (struct k_itimer * timr, int flags,
 			  struct itimerspec * new_setting,
 			  struct itimerspec * old_setting);
 	int (*timer_del) (struct k_itimer * timr);
+#define TIMER_RETRY 1
 	void (*timer_get) (struct k_itimer * timr,
 			   struct itimerspec * cur_setting);
 };
 
-void register_posix_clock(int clock_id, struct k_clock *new_clock);
+void register_posix_clock(clockid_t clock_id, struct k_clock *new_clock);
 
 /* Error handlers for timer_create, nanosleep and settime */
 int do_posix_clock_notimer_create(struct k_itimer *timer);
-int do_posix_clock_nonanosleep(int which_clock, int flags, struct timespec * t);
-int do_posix_clock_nosettime(struct timespec *tp);
+int do_posix_clock_nonanosleep(clockid_t, int flags, struct timespec *);
+int do_posix_clock_nosettime(clockid_t, struct timespec *tp);
 
 /* function to call to trigger timer event */
 int posix_timer_event(struct k_itimer *timr, int si_private);
@@ -65,12 +108,32 @@
 #define posix_bump_timer(timr, now)					\
          do {								\
               long delta, orun;						\
-	      delta = now.jiffies - (timr)->it_timer.expires;		\
+	      delta = now.jiffies - (timr)->it.real.timer.expires;	\
               if (delta >= 0) {						\
-	           orun = 1 + (delta / (timr)->it_incr);		\
-	          (timr)->it_timer.expires += orun * (timr)->it_incr;	\
+	           orun = 1 + (delta / (timr)->it.real.incr);		\
+	          (timr)->it.real.timer.expires +=			\
+			 orun * (timr)->it.real.incr;			\
                   (timr)->it_overrun += orun;				\
               }								\
             }while (0)
-#endif
 
+int posix_cpu_clock_getres(clockid_t which_clock, struct timespec *);
+int posix_cpu_clock_get(clockid_t which_clock, struct timespec *);
+int posix_cpu_clock_set(clockid_t which_clock, const struct timespec *tp);
+int posix_cpu_timer_create(struct k_itimer *);
+int posix_cpu_nsleep(clockid_t, int, struct timespec *);
+int posix_cpu_timer_set(struct k_itimer *, int,
+			struct itimerspec *, struct itimerspec *);
+int posix_cpu_timer_del(struct k_itimer *);
+void posix_cpu_timer_get(struct k_itimer *, struct itimerspec *);
+
+void posix_cpu_timer_schedule(struct k_itimer *);
+
+void run_posix_cpu_timers(struct task_struct *);
+void posix_cpu_timers_exit(struct task_struct *);
+void posix_cpu_timers_exit_group(struct task_struct *);
+
+void set_process_cpu_timer(struct task_struct *, unsigned int,
+			   cputime_t *, cputime_t *);
+
+#endif
diff -Nru a/include/linux/random.h b/include/linux/random.h
--- a/include/linux/random.h	2005-03-11 12:51:52 -08:00
+++ b/include/linux/random.h	2005-03-11 12:51:52 -08:00
@@ -53,22 +53,19 @@
 
 extern __u32 secure_ip_id(__u32 daddr);
 extern u32 secure_tcp_port_ephemeral(__u32 saddr, __u32 daddr, __u16 dport);
+extern u32 secure_tcpv6_port_ephemeral(const __u32 *saddr, const __u32 *daddr, 
+				       __u16 dport);
 extern __u32 secure_tcp_sequence_number(__u32 saddr, __u32 daddr,
 					__u16 sport, __u16 dport);
-extern __u32 secure_tcp_syn_cookie(__u32 saddr, __u32 daddr,
-				   __u16 sport, __u16 dport,
-				   __u32 sseq, __u32 count,
-				   __u32 data);
-extern __u32 check_tcp_syn_cookie(__u32 cookie, __u32 saddr,
-				  __u32 daddr, __u16 sport,
-				  __u16 dport, __u32 sseq,
-				  __u32 count, __u32 maxdiff);
 extern __u32 secure_tcpv6_sequence_number(__u32 *saddr, __u32 *daddr,
 					  __u16 sport, __u16 dport);
 
 #ifndef MODULE
 extern struct file_operations random_fops, urandom_fops;
 #endif
+
+unsigned int get_random_int(void);
+unsigned long randomize_range(unsigned long start, unsigned long end, unsigned long len);
 
 #endif /* __KERNEL___ */
 
diff -Nru a/include/linux/reiserfs_fs_i.h b/include/linux/reiserfs_fs_i.h
--- a/include/linux/reiserfs_fs_i.h	2005-03-11 12:51:51 -08:00
+++ b/include/linux/reiserfs_fs_i.h	2005-03-11 12:51:51 -08:00
@@ -23,9 +23,8 @@
       space on crash with some files open, but unlinked. */
     i_link_saved_unlink_mask   =  0x0010,
     i_link_saved_truncate_mask =  0x0020,
-    i_priv_object              =  0x0080,
-    i_has_xattr_dir            =  0x0100,
-    i_data_log	               =  0x0200,
+    i_has_xattr_dir            =  0x0040,
+    i_data_log	               =  0x0080,
 } reiserfs_inode_flags;
 
 
diff -Nru a/include/linux/reiserfs_xattr.h b/include/linux/reiserfs_xattr.h
--- a/include/linux/reiserfs_xattr.h	2005-03-11 12:51:52 -08:00
+++ b/include/linux/reiserfs_xattr.h	2005-03-11 12:51:52 -08:00
@@ -31,7 +31,7 @@
 
 
 #ifdef CONFIG_REISERFS_FS_XATTR
-#define is_reiserfs_priv_object(inode) (REISERFS_I(inode)->i_flags & i_priv_object)
+#define is_reiserfs_priv_object(inode) IS_PRIVATE(inode)
 #define has_xattr_dir(inode) (REISERFS_I(inode)->i_flags & i_has_xattr_dir)
 ssize_t reiserfs_getxattr (struct dentry *dentry, const char *name,
 			   void *buffer, size_t size);
@@ -103,9 +103,16 @@
     up_read (&REISERFS_I(inode)->xattr_sem);
 }
 
+static inline void
+reiserfs_mark_inode_private(struct inode *inode)
+{
+    inode->i_flags |= S_PRIVATE;
+}
+
 #else
 
 #define is_reiserfs_priv_object(inode) 0
+#define reiserfs_mark_inode_private(inode)
 #define reiserfs_getxattr NULL
 #define reiserfs_setxattr NULL
 #define reiserfs_listxattr NULL
diff -Nru a/include/linux/rtnetlink.h b/include/linux/rtnetlink.h
--- a/include/linux/rtnetlink.h	2005-03-11 12:51:50 -08:00
+++ b/include/linux/rtnetlink.h	2005-03-11 12:51:50 -08:00
@@ -346,6 +346,7 @@
 #define RTAX_FEATURE_ECN	0x00000001
 #define RTAX_FEATURE_SACK	0x00000002
 #define RTAX_FEATURE_TIMESTAMP	0x00000004
+#define RTAX_FEATURE_ALLFRAG	0x00000008
 
 struct rta_session
 {
@@ -446,6 +447,7 @@
 	NDA_DST,
 	NDA_LLADDR,
 	NDA_CACHEINFO,
+	NDA_PROBES,
 	__NDA_MAX
 };
 
@@ -779,6 +781,11 @@
 		 goto rtattr_failure; \
    	__rta_fill(skb, attrtype, attrlen, data); }) 
 
+#define RTA_PUT_NOHDR(skb, attrlen, data) \
+({	if (unlikely(skb_tailroom(skb) < (int)(attrlen))) \
+		goto rtattr_failure; \
+	memcpy(skb_put(skb, RTA_ALIGN(attrlen)), data, attrlen); })
+		
 static inline struct rtattr *
 __rta_reserve(struct sk_buff *skb, int attrtype, int attrlen)
 {
diff -Nru a/include/linux/sched.h b/include/linux/sched.h
--- a/include/linux/sched.h	2005-03-11 12:51:41 -08:00
+++ b/include/linux/sched.h	2005-03-11 12:51:41 -08:00
@@ -14,6 +14,7 @@
 #include <linux/thread_info.h>
 #include <linux/cpumask.h>
 #include <linux/errno.h>
+#include <linux/nodemask.h>
 
 #include <asm/system.h>
 #include <asm/semaphore.h>
@@ -32,6 +33,7 @@
 #include <linux/pid.h>
 #include <linux/percpu.h>
 #include <linux/topology.h>
+#include <linux/seccomp.h>
 
 struct exec_domain;
 
@@ -300,6 +302,14 @@
 	/* POSIX.1b Interval Timers */
 	struct list_head posix_timers;
 
+	/* ITIMER_REAL timer for the process */
+	struct timer_list real_timer;
+	unsigned long it_real_value, it_real_incr;
+
+	/* ITIMER_PROF and ITIMER_VIRTUAL timers for the process */
+	cputime_t it_prof_expires, it_virt_expires;
+	cputime_t it_prof_incr, it_virt_incr;
+
 	/* job control IDs */
 	pid_t pgrp;
 	pid_t tty_old_pgrp;
@@ -320,6 +330,14 @@
 	unsigned long min_flt, maj_flt, cmin_flt, cmaj_flt;
 
 	/*
+	 * Cumulative ns of scheduled CPU time for dead threads in the
+	 * group, not including a zombie group leader.  (This only differs
+	 * from jiffies_to_ns(utime + stime) if sched_clock uses something
+	 * other than jiffies.)
+	 */
+	unsigned long long sched_time;
+
+	/*
 	 * We don't bother to synchronize most readers of this at all,
 	 * because there is no reader checking a limit that actually needs
 	 * to get both rlim_cur and rlim_max atomically, and either one
@@ -329,6 +347,15 @@
 	 * have no need to disable irqs.
 	 */
 	struct rlimit rlim[RLIM_NLIMITS];
+
+	struct list_head cpu_timers[3];
+
+	/* keep the process-shared keyrings here so that they do the right
+	 * thing in threads created with CLONE_THREAD */
+#ifdef CONFIG_KEYS
+	struct key *session_keyring;	/* keyring inherited over fork */
+	struct key *process_keyring;	/* keyring private to this process */
+#endif
 };
 
 /*
@@ -488,6 +515,7 @@
 
 struct io_context;			/* See blkdev.h */
 void exit_io_context(void);
+struct cpuset;
 
 #define NGROUPS_SMALL		32
 #define NGROUPS_PER_BLOCK	((int)(PAGE_SIZE / sizeof(gid_t)))
@@ -540,6 +568,7 @@
 
 	unsigned long sleep_avg;
 	unsigned long long timestamp, last_ran;
+	unsigned long long sched_time; /* sched_clock time spent running */
 	int activated;
 
 	unsigned long policy;
@@ -593,15 +622,16 @@
 	int __user *clear_child_tid;		/* CLONE_CHILD_CLEARTID */
 
 	unsigned long rt_priority;
-	unsigned long it_real_value, it_real_incr;
-	cputime_t it_virt_value, it_virt_incr;
-	cputime_t it_prof_value, it_prof_incr;
-	struct timer_list real_timer;
 	cputime_t utime, stime;
 	unsigned long nvcsw, nivcsw; /* context switch counts */
 	struct timespec start_time;
 /* mm fault and swap info: this can arguably be seen as either mm-specific or thread-specific */
 	unsigned long min_flt, maj_flt;
+
+  	cputime_t it_prof_expires, it_virt_expires;
+	unsigned long long it_sched_expires;
+	struct list_head cpu_timers[3];
+
 /* process credentials */
 	uid_t uid,euid,suid,fsuid;
 	gid_t gid,egid,sgid,fsgid;
@@ -610,8 +640,6 @@
 	unsigned keep_capabilities:1;
 	struct user_struct *user;
 #ifdef CONFIG_KEYS
-	struct key *session_keyring;	/* keyring inherited over fork */
-	struct key *process_keyring;	/* keyring private to this process (CLONE_THREAD) */
 	struct key *thread_keyring;	/* keyring private to this thread */
 #endif
 	int oomkilladj; /* OOM kill score adjustment (bit shift). */
@@ -643,6 +671,7 @@
 	
 	void *security;
 	struct audit_context *audit_context;
+	seccomp_t seccomp;
 
 /* Thread group tracking */
    	u32 parent_exec_id;
@@ -685,6 +714,11 @@
   	struct mempolicy *mempolicy;
 	short il_next;
 #endif
+#ifdef CONFIG_CPUSETS
+	struct cpuset *cpuset;
+	nodemask_t mems_allowed;
+	int cpuset_mems_generation;
+#endif
 };
 
 static inline pid_t process_group(struct task_struct *tsk)
@@ -735,6 +769,7 @@
 #define PF_LESS_THROTTLE 0x00100000	/* Throttle me less: I clean memory */
 #define PF_SYNCWRITE	0x00200000	/* I am doing a sync write */
 #define PF_BORROWED_MM	0x00400000	/* I am a kthread doing use_mm */
+#define PF_RANDOMIZE	0x00800000	/* randomize virtual address space */
 
 /*
  * Only the _current_ task can read/write to tsk->flags, but other
@@ -773,6 +808,7 @@
 #endif
 
 extern unsigned long long sched_clock(void);
+extern unsigned long long current_sched_time(const task_t *current_task);
 
 /* sched_exec is called by processes performing an exec */
 #ifdef CONFIG_SMP
diff -Nru a/include/linux/scx200.h b/include/linux/scx200.h
--- a/include/linux/scx200.h	2005-03-11 12:51:47 -08:00
+++ b/include/linux/scx200.h	2005-03-11 12:51:47 -08:00
@@ -7,6 +7,10 @@
 
 /* Interesting stuff for the National Semiconductor SCx200 CPU */
 
+extern unsigned scx200_cb_base;
+
+#define scx200_cb_present() (scx200_cb_base!=0)
+
 /* F0 PCI Header/Bridge Configuration Registers */
 #define SCx200_DOCCS_BASE 0x78	/* DOCCS Base Address Register */
 #define SCx200_DOCCS_CTRL 0x7c	/* DOCCS Control Register */
@@ -15,7 +19,7 @@
 #define SCx200_GPIO_SIZE 0x2c	/* Size of GPIO register block */
 
 /* General Configuration Block */
-#define SCx200_CB_BASE 0x9000	/* Base fixed at 0x9000 according to errata */
+#define SCx200_CB_BASE_FIXED 0x9000	/* Base fixed at 0x9000 according to errata? */
 
 /* Watchdog Timer */
 #define SCx200_WDT_OFFSET 0x00	/* offset within configuration block */
@@ -44,9 +48,7 @@
 #define SCx200_IID 0x3c		/* IA On a Chip Identification Number Reg */
 #define SCx200_REV 0x3d		/* Revision Register */
 #define SCx200_CBA 0x3e		/* Configuration Base Address Register */
-
-/* Verify that the configuration block really is there */
-#define scx200_cb_probe(base) (inw((base) + SCx200_CBA) == (base))
+#define SCx200_CBA_SCRATCH 0x64	/* Configuration Base Address Scratchpad */
 
 /*
     Local variables:
diff -Nru a/include/linux/seccomp.h b/include/linux/seccomp.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/linux/seccomp.h	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,33 @@
+#ifndef _LINUX_SECCOMP_H
+#define _LINUX_SECCOMP_H
+
+#include <linux/config.h>
+
+#ifdef CONFIG_SECCOMP
+
+#define NR_SECCOMP_MODES 1
+
+#include <linux/thread_info.h>
+
+typedef struct { int mode; } seccomp_t;
+
+extern void __secure_computing(int);
+static inline void secure_computing(int this_syscall)
+{
+	if (unlikely(test_thread_flag(TIF_SECCOMP)))
+		__secure_computing(this_syscall);
+}
+
+#else /* CONFIG_SECCOMP */
+
+#if (__GNUC__ > 2)
+  typedef struct { } seccomp_t;
+#else
+  typedef struct { int gcc_is_buggy; } seccomp_t;
+#endif
+
+#define secure_computing(x) do { } while (0)
+
+#endif /* CONFIG_SECCOMP */
+
+#endif /* _LINUX_SECCOMP_H */
diff -Nru a/include/linux/security.h b/include/linux/security.h
--- a/include/linux/security.h	2005-03-11 12:51:47 -08:00
+++ b/include/linux/security.h	2005-03-11 12:51:47 -08:00
@@ -458,13 +458,15 @@
  *	Check permissions for a mmap operation.  The @file may be NULL, e.g.
  *	if mapping anonymous memory.
  *	@file contains the file structure for file to map (may be NULL).
- *	@prot contains the requested permissions.
+ *	@reqprot contains the protection requested by the application.
+ *	@prot contains the protection that will be applied by the kernel.
  *	@flags contains the operational flags.
  *	Return 0 if permission is granted.
  * @file_mprotect:
  *	Check permissions before changing memory access permissions.
  *	@vma contains the memory region to modify.
- *	@prot contains the requested permissions.
+ *	@reqprot contains the protection requested by the application.
+ *	@prot contains the protection that will be applied by the kernel.
  *	Return 0 if permission is granted.
  * @file_lock:
  *	Check permission before performing file locking operations.
@@ -1129,8 +1131,11 @@
 	int (*file_ioctl) (struct file * file, unsigned int cmd,
 			   unsigned long arg);
 	int (*file_mmap) (struct file * file,
+			  unsigned long reqprot,
 			  unsigned long prot, unsigned long flags);
-	int (*file_mprotect) (struct vm_area_struct * vma, unsigned long prot);
+	int (*file_mprotect) (struct vm_area_struct * vma,
+			      unsigned long reqprot,
+			      unsigned long prot);
 	int (*file_lock) (struct file * file, unsigned int cmd);
 	int (*file_fcntl) (struct file * file, unsigned int cmd,
 			   unsigned long arg);
@@ -1426,11 +1431,15 @@
 
 static inline int security_inode_alloc (struct inode *inode)
 {
+	if (unlikely (IS_PRIVATE (inode)))
+		return 0;
 	return security_ops->inode_alloc_security (inode);
 }
 
 static inline void security_inode_free (struct inode *inode)
 {
+	if (unlikely (IS_PRIVATE (inode)))
+		return;
 	security_ops->inode_free_security (inode);
 }
 	
@@ -1438,6 +1447,8 @@
 					 struct dentry *dentry,
 					 int mode)
 {
+	if (unlikely (IS_PRIVATE (dir)))
+		return 0;
 	return security_ops->inode_create (dir, dentry, mode);
 }
 
@@ -1445,6 +1456,8 @@
 					       struct dentry *dentry,
 					       int mode)
 {
+	if (dentry->d_inode && unlikely (IS_PRIVATE (dentry->d_inode)))
+		return;
 	security_ops->inode_post_create (dir, dentry, mode);
 }
 
@@ -1452,6 +1465,8 @@
 				       struct inode *dir,
 				       struct dentry *new_dentry)
 {
+	if (unlikely (IS_PRIVATE (old_dentry->d_inode)))
+		return 0;
 	return security_ops->inode_link (old_dentry, dir, new_dentry);
 }
 
@@ -1459,12 +1474,16 @@
 					     struct inode *dir,
 					     struct dentry *new_dentry)
 {
+	if (new_dentry->d_inode && unlikely (IS_PRIVATE (new_dentry->d_inode)))
+		return;
 	security_ops->inode_post_link (old_dentry, dir, new_dentry);
 }
 
 static inline int security_inode_unlink (struct inode *dir,
 					 struct dentry *dentry)
 {
+	if (unlikely (IS_PRIVATE (dentry->d_inode)))
+		return 0;
 	return security_ops->inode_unlink (dir, dentry);
 }
 
@@ -1472,6 +1491,8 @@
 					  struct dentry *dentry,
 					  const char *old_name)
 {
+	if (unlikely (IS_PRIVATE (dir)))
+		return 0;
 	return security_ops->inode_symlink (dir, dentry, old_name);
 }
 
@@ -1479,6 +1500,8 @@
 						struct dentry *dentry,
 						const char *old_name)
 {
+	if (dentry->d_inode && unlikely (IS_PRIVATE (dentry->d_inode)))
+		return;
 	security_ops->inode_post_symlink (dir, dentry, old_name);
 }
 
@@ -1486,6 +1509,8 @@
 					struct dentry *dentry,
 					int mode)
 {
+	if (unlikely (IS_PRIVATE (dir)))
+		return 0;
 	return security_ops->inode_mkdir (dir, dentry, mode);
 }
 
@@ -1493,12 +1518,16 @@
 					      struct dentry *dentry,
 					      int mode)
 {
+	if (dentry->d_inode && unlikely (IS_PRIVATE (dentry->d_inode)))
+		return;
 	security_ops->inode_post_mkdir (dir, dentry, mode);
 }
 
 static inline int security_inode_rmdir (struct inode *dir,
 					struct dentry *dentry)
 {
+	if (unlikely (IS_PRIVATE (dentry->d_inode)))
+		return 0;
 	return security_ops->inode_rmdir (dir, dentry);
 }
 
@@ -1506,6 +1535,8 @@
 					struct dentry *dentry,
 					int mode, dev_t dev)
 {
+	if (unlikely (IS_PRIVATE (dir)))
+		return 0;
 	return security_ops->inode_mknod (dir, dentry, mode, dev);
 }
 
@@ -1513,6 +1544,8 @@
 					      struct dentry *dentry,
 					      int mode, dev_t dev)
 {
+	if (dentry->d_inode && unlikely (IS_PRIVATE (dentry->d_inode)))
+		return;
 	security_ops->inode_post_mknod (dir, dentry, mode, dev);
 }
 
@@ -1521,6 +1554,9 @@
 					 struct inode *new_dir,
 					 struct dentry *new_dentry)
 {
+        if (unlikely (IS_PRIVATE (old_dentry->d_inode) ||
+            (new_dentry->d_inode && IS_PRIVATE (new_dentry->d_inode))))
+		return 0;
 	return security_ops->inode_rename (old_dir, old_dentry,
 					   new_dir, new_dentry);
 }
@@ -1530,83 +1566,114 @@
 					       struct inode *new_dir,
 					       struct dentry *new_dentry)
 {
+	if (unlikely (IS_PRIVATE (old_dentry->d_inode) ||
+	    (new_dentry->d_inode && IS_PRIVATE (new_dentry->d_inode))))
+		return;
 	security_ops->inode_post_rename (old_dir, old_dentry,
 						new_dir, new_dentry);
 }
 
 static inline int security_inode_readlink (struct dentry *dentry)
 {
+	if (unlikely (IS_PRIVATE (dentry->d_inode)))
+		return 0;
 	return security_ops->inode_readlink (dentry);
 }
 
 static inline int security_inode_follow_link (struct dentry *dentry,
 					      struct nameidata *nd)
 {
+	if (unlikely (IS_PRIVATE (dentry->d_inode)))
+		return 0;
 	return security_ops->inode_follow_link (dentry, nd);
 }
 
 static inline int security_inode_permission (struct inode *inode, int mask,
 					     struct nameidata *nd)
 {
+	if (unlikely (IS_PRIVATE (inode)))
+		return 0;
 	return security_ops->inode_permission (inode, mask, nd);
 }
 
 static inline int security_inode_setattr (struct dentry *dentry,
 					  struct iattr *attr)
 {
+	if (unlikely (IS_PRIVATE (dentry->d_inode)))
+		return 0;
 	return security_ops->inode_setattr (dentry, attr);
 }
 
 static inline int security_inode_getattr (struct vfsmount *mnt,
 					  struct dentry *dentry)
 {
+	if (unlikely (IS_PRIVATE (dentry->d_inode)))
+		return 0;
 	return security_ops->inode_getattr (mnt, dentry);
 }
 
 static inline void security_inode_delete (struct inode *inode)
 {
+	if (unlikely (IS_PRIVATE (inode)))
+		return;
 	security_ops->inode_delete (inode);
 }
 
 static inline int security_inode_setxattr (struct dentry *dentry, char *name,
 					   void *value, size_t size, int flags)
 {
+	if (unlikely (IS_PRIVATE (dentry->d_inode)))
+		return 0;
 	return security_ops->inode_setxattr (dentry, name, value, size, flags);
 }
 
 static inline void security_inode_post_setxattr (struct dentry *dentry, char *name,
 						void *value, size_t size, int flags)
 {
+	if (unlikely (IS_PRIVATE (dentry->d_inode)))
+		return;
 	security_ops->inode_post_setxattr (dentry, name, value, size, flags);
 }
 
 static inline int security_inode_getxattr (struct dentry *dentry, char *name)
 {
+	if (unlikely (IS_PRIVATE (dentry->d_inode)))
+		return 0;
 	return security_ops->inode_getxattr (dentry, name);
 }
 
 static inline int security_inode_listxattr (struct dentry *dentry)
 {
+	if (unlikely (IS_PRIVATE (dentry->d_inode)))
+		return 0;
 	return security_ops->inode_listxattr (dentry);
 }
 
 static inline int security_inode_removexattr (struct dentry *dentry, char *name)
 {
+	if (unlikely (IS_PRIVATE (dentry->d_inode)))
+		return 0;
 	return security_ops->inode_removexattr (dentry, name);
 }
 
 static inline int security_inode_getsecurity(struct inode *inode, const char *name, void *buffer, size_t size)
 {
+	if (unlikely (IS_PRIVATE (inode)))
+		return 0;
 	return security_ops->inode_getsecurity(inode, name, buffer, size);
 }
 
 static inline int security_inode_setsecurity(struct inode *inode, const char *name, const void *value, size_t size, int flags)
 {
+	if (unlikely (IS_PRIVATE (inode)))
+		return 0;
 	return security_ops->inode_setsecurity(inode, name, value, size, flags);
 }
 
 static inline int security_inode_listsecurity(struct inode *inode, char *buffer, size_t buffer_size)
 {
+	if (unlikely (IS_PRIVATE (inode)))
+		return 0;
 	return security_ops->inode_listsecurity(inode, buffer, buffer_size);
 }
 
@@ -1631,16 +1698,18 @@
 	return security_ops->file_ioctl (file, cmd, arg);
 }
 
-static inline int security_file_mmap (struct file *file, unsigned long prot,
+static inline int security_file_mmap (struct file *file, unsigned long reqprot,
+				      unsigned long prot,
 				      unsigned long flags)
 {
-	return security_ops->file_mmap (file, prot, flags);
+	return security_ops->file_mmap (file, reqprot, prot, flags);
 }
 
 static inline int security_file_mprotect (struct vm_area_struct *vma,
+					  unsigned long reqprot,
 					  unsigned long prot)
 {
-	return security_ops->file_mprotect (vma, prot);
+	return security_ops->file_mprotect (vma, reqprot, prot);
 }
 
 static inline int security_file_lock (struct file *file, unsigned int cmd)
@@ -1883,6 +1952,8 @@
 
 static inline void security_d_instantiate (struct dentry *dentry, struct inode *inode)
 {
+	if (unlikely (inode && IS_PRIVATE (inode)))
+		return;
 	security_ops->d_instantiate (dentry, inode);
 }
 
@@ -2278,13 +2349,15 @@
 	return 0;
 }
 
-static inline int security_file_mmap (struct file *file, unsigned long prot,
+static inline int security_file_mmap (struct file *file, unsigned long reqprot,
+				      unsigned long prot,
 				      unsigned long flags)
 {
 	return 0;
 }
 
 static inline int security_file_mprotect (struct vm_area_struct *vma,
+					  unsigned long reqprot,
 					  unsigned long prot)
 {
 	return 0;
diff -Nru a/include/linux/seq_file.h b/include/linux/seq_file.h
--- a/include/linux/seq_file.h	2005-03-11 12:51:52 -08:00
+++ b/include/linux/seq_file.h	2005-03-11 12:51:52 -08:00
@@ -18,6 +18,7 @@
 	size_t from;
 	size_t count;
 	loff_t index;
+	loff_t version;
 	struct semaphore sem;
 	struct seq_operations *op;
 	void *private;
diff -Nru a/include/linux/serial_core.h b/include/linux/serial_core.h
--- a/include/linux/serial_core.h	2005-03-11 12:51:41 -08:00
+++ b/include/linux/serial_core.h	2005-03-11 12:51:41 -08:00
@@ -106,6 +106,13 @@
 /* TXX9 type number */
 #define PORT_TXX9       64
 
+/* NEC VR4100 series SIU/DSIU */
+#define PORT_VR41XX_SIU		65
+#define PORT_VR41XX_DSIU	66
+
+/* Samsung S3C2400 SoC */
+#define PORT_S3C2400	67
+
 #ifdef __KERNEL__
 
 #include <linux/config.h>
diff -Nru a/include/linux/serio.h b/include/linux/serio.h
--- a/include/linux/serio.h	2005-03-11 12:51:47 -08:00
+++ b/include/linux/serio.h	2005-03-11 12:51:47 -08:00
@@ -10,18 +10,18 @@
  */
 
 #include <linux/ioctl.h>
-#include <linux/interrupt.h>
 
 #define SPIOCSTYPE	_IOW('q', 0x01, unsigned long)
 
 #ifdef __KERNEL__
 
+#include <linux/interrupt.h>
 #include <linux/list.h>
 #include <linux/spinlock.h>
 #include <linux/device.h>
+#include <linux/mod_devicetable.h>
 
 struct serio {
-	void *private;
 	void *port_data;
 
 	char name[32];
@@ -29,19 +29,15 @@
 
 	unsigned int manual_bind;
 
-	unsigned short idbus;
-	unsigned short idvendor;
-	unsigned short idproduct;
-	unsigned short idversion;
-
-	unsigned long type;
-	unsigned long event;
+	struct serio_device_id id;
 
 	spinlock_t lock;		/* protects critical sections from port's interrupt handler */
 
 	int (*write)(struct serio *, unsigned char);
 	int (*open)(struct serio *);
 	void (*close)(struct serio *);
+	int (*start)(struct serio *);
+	void (*stop)(struct serio *);
 
 	struct serio *parent, *child;
 
@@ -49,6 +45,7 @@
 	struct semaphore drv_sem;	/* protects serio->drv so attributes can pin driver */
 
 	struct device dev;
+	unsigned int registered;	/* port has been fully registered with driver core */
 
 	struct list_head node;
 };
@@ -58,19 +55,18 @@
 	void *private;
 	char *description;
 
+	struct serio_device_id *id_table;
 	unsigned int manual_bind;
 
 	void (*write_wakeup)(struct serio *);
 	irqreturn_t (*interrupt)(struct serio *, unsigned char,
 			unsigned int, struct pt_regs *);
-	void (*connect)(struct serio *, struct serio_driver *drv);
+	int  (*connect)(struct serio *, struct serio_driver *drv);
 	int  (*reconnect)(struct serio *);
 	void (*disconnect)(struct serio *);
 	void (*cleanup)(struct serio *);
 
 	struct device_driver driver;
-
-	struct list_head node;
 };
 #define to_serio_driver(d)	container_of(d, struct serio_driver, driver)
 
@@ -80,15 +76,28 @@
 void serio_reconnect(struct serio *serio);
 irqreturn_t serio_interrupt(struct serio *serio, unsigned char data, unsigned int flags, struct pt_regs *regs);
 
-void serio_register_port(struct serio *serio);
-void serio_register_port_delayed(struct serio *serio);
+void __serio_register_port(struct serio *serio, struct module *owner);
+static inline void serio_register_port(struct serio *serio)
+{
+	__serio_register_port(serio, THIS_MODULE);
+}
+
 void serio_unregister_port(struct serio *serio);
-void serio_unregister_port_delayed(struct serio *serio);
+void __serio_unregister_port_delayed(struct serio *serio, struct module *owner);
+static inline void serio_unregister_port_delayed(struct serio *serio)
+{
+	__serio_unregister_port_delayed(serio, THIS_MODULE);
+}
+
+void __serio_register_driver(struct serio_driver *drv, struct module *owner);
+static inline void serio_register_driver(struct serio_driver *drv)
+{
+	__serio_register_driver(drv, THIS_MODULE);
+}
 
-void serio_register_driver(struct serio_driver *drv);
 void serio_unregister_driver(struct serio_driver *drv);
 
-static __inline__ int serio_write(struct serio *serio, unsigned char data)
+static inline int serio_write(struct serio *serio, unsigned char data)
 {
 	if (serio->write)
 		return serio->write(serio, data);
@@ -96,29 +105,42 @@
 		return -1;
 }
 
-static __inline__ void serio_drv_write_wakeup(struct serio *serio)
+static inline void serio_drv_write_wakeup(struct serio *serio)
 {
 	if (serio->drv && serio->drv->write_wakeup)
 		serio->drv->write_wakeup(serio);
 }
 
-static __inline__ void serio_cleanup(struct serio *serio)
+static inline void serio_cleanup(struct serio *serio)
 {
 	if (serio->drv && serio->drv->cleanup)
 		serio->drv->cleanup(serio);
 }
 
+/*
+ * Use the following fucntions to manipulate serio's per-port
+ * driver-specific data.
+ */
+static inline void *serio_get_drvdata(struct serio *serio)
+{
+	return dev_get_drvdata(&serio->dev);
+}
+
+static inline void serio_set_drvdata(struct serio *serio, void *data)
+{
+	dev_set_drvdata(&serio->dev, data);
+}
 
 /*
  * Use the following fucntions to protect critical sections in
  * driver code from port's interrupt handler
  */
-static __inline__ void serio_pause_rx(struct serio *serio)
+static inline void serio_pause_rx(struct serio *serio)
 {
 	spin_lock_irq(&serio->lock);
 }
 
-static __inline__ void serio_continue_rx(struct serio *serio)
+static inline void serio_continue_rx(struct serio *serio)
 {
 	spin_unlock_irq(&serio->lock);
 }
@@ -126,12 +148,12 @@
 /*
  * Use the following fucntions to pin serio's driver in process context
  */
-static __inline__ int serio_pin_driver(struct serio *serio)
+static inline int serio_pin_driver(struct serio *serio)
 {
 	return down_interruptible(&serio->drv_sem);
 }
 
-static __inline__ void serio_unpin_driver(struct serio *serio)
+static inline void serio_unpin_driver(struct serio *serio)
 {
 	up(&serio->drv_sem);
 }
@@ -146,15 +168,20 @@
 #define SERIO_PARITY	2
 #define SERIO_FRAME	4
 
-#define SERIO_TYPE	0xff000000UL
-#define SERIO_XT	0x00000000UL
-#define SERIO_8042	0x01000000UL
-#define SERIO_RS232	0x02000000UL
-#define SERIO_HIL_MLC	0x03000000UL
-#define SERIO_PS_PSTHRU	0x05000000UL
-#define SERIO_8042_XL	0x06000000UL
+/*
+ * Serio types
+ */
+#define SERIO_XT	0x00
+#define SERIO_8042	0x01
+#define SERIO_RS232	0x02
+#define SERIO_HIL_MLC	0x03
+#define SERIO_PS_PSTHRU	0x05
+#define SERIO_8042_XL	0x06
 
-#define SERIO_PROTO	0xFFUL
+/*
+ * Serio types
+ */
+#define SERIO_UNKNOWN	0x00
 #define SERIO_MSC	0x01
 #define SERIO_SUN	0x02
 #define SERIO_MS	0x03
@@ -181,8 +208,7 @@
 #define SERIO_SNES232	0x26
 #define SERIO_SEMTECH	0x27
 #define SERIO_LKKBD	0x28
-
-#define SERIO_ID	0xff00UL
-#define SERIO_EXTRA	0xff0000UL
+#define SERIO_ELO	0x29
+#define SERIO_MICROTOUCH	0x30
 
 #endif
diff -Nru a/include/linux/signal.h b/include/linux/signal.h
--- a/include/linux/signal.h	2005-03-11 12:51:41 -08:00
+++ b/include/linux/signal.h	2005-03-11 12:51:41 -08:00
@@ -8,8 +8,6 @@
 
 #ifdef __KERNEL__
 
-#define MAX_SIGPENDING	1024
-
 /*
  * Real Time signals may be queued.
  */
@@ -212,6 +210,7 @@
 }
 
 extern int group_send_sig_info(int sig, struct siginfo *info, struct task_struct *p);
+extern int __group_send_sig_info(int, struct siginfo *, struct task_struct *);
 extern long do_sigpending(void __user *, unsigned long);
 extern int sigprocmask(int, sigset_t *, sigset_t *);
 
diff -Nru a/include/linux/skbuff.h b/include/linux/skbuff.h
--- a/include/linux/skbuff.h	2005-03-11 12:51:52 -08:00
+++ b/include/linux/skbuff.h	2005-03-11 12:51:52 -08:00
@@ -146,6 +146,20 @@
 	skb_frag_t	frags[MAX_SKB_FRAGS];
 };
 
+/* We divide dataref into two halves.  The higher 16 bits hold references
+ * to the payload part of skb->data.  The lower 16 bits hold references to
+ * the entire skb->data.  It is up to the users of the skb to agree on
+ * where the payload starts.
+ *
+ * All users must obey the rule that the skb->data reference count must be
+ * greater than or equal to the payload reference count.
+ *
+ * Holding a reference to the payload part means that the user does not
+ * care about modifications to the header part of skb->data.
+ */
+#define SKB_DATAREF_SHIFT 16
+#define SKB_DATAREF_MASK ((1 << SKB_DATAREF_SHIFT) - 1)
+
 /** 
  *	struct sk_buff - socket buffer
  *	@next: Next buffer in list
@@ -167,6 +181,7 @@
  *	@csum: Checksum
  *	@__unused: Dead field, may be reused
  *	@cloned: Head may be cloned (check refcnt to be sure)
+ *	@nohdr: Payload reference only, must not modify header
  *	@pkt_type: Packet class
  *	@ip_summed: Driver fed us an IP checksum
  *	@priority: Packet queueing priority
@@ -238,7 +253,8 @@
 				mac_len,
 				csum;
 	unsigned char		local_df,
-				cloned,
+				cloned:1,
+				nohdr:1,
 				pkt_type,
 				ip_summed;
 	__u32			priority;
@@ -370,7 +386,42 @@
  */
 static inline int skb_cloned(const struct sk_buff *skb)
 {
-	return skb->cloned && atomic_read(&skb_shinfo(skb)->dataref) != 1;
+	return skb->cloned &&
+	       (atomic_read(&skb_shinfo(skb)->dataref) & SKB_DATAREF_MASK) != 1;
+}
+
+/**
+ *	skb_header_cloned - is the header a clone
+ *	@skb: buffer to check
+ *
+ *	Returns true if modifying the header part of the buffer requires
+ *	the data to be copied.
+ */
+static inline int skb_header_cloned(const struct sk_buff *skb)
+{
+	int dataref;
+
+	if (!skb->cloned)
+		return 0;
+
+	dataref = atomic_read(&skb_shinfo(skb)->dataref);
+	dataref = (dataref & SKB_DATAREF_MASK) - (dataref >> SKB_DATAREF_SHIFT);
+	return dataref != 1;
+}
+
+/**
+ *	skb_header_release - release reference to header
+ *	@skb: buffer to operate on
+ *
+ *	Drop a reference to the header part of the buffer.  This is done
+ *	by acquiring a payload reference.  You must not read from the header
+ *	part of skb->data after this.
+ */
+static inline void skb_header_release(struct sk_buff *skb)
+{
+	BUG_ON(skb->nohdr);
+	skb->nohdr = 1;
+	atomic_add(1 << SKB_DATAREF_SHIFT, &skb_shinfo(skb)->dataref);
 }
 
 /**
@@ -1054,6 +1105,42 @@
 	return __skb_linearize(skb, gfp);
 }
 
+/**
+ *	skb_postpull_rcsum - update checksum for received skb after pull
+ *	@skb: buffer to update
+ *	@start: start of data before pull
+ *	@len: length of data pulled
+ *
+ *	After doing a pull on a received packet, you need to call this to
+ *	update the CHECKSUM_HW checksum, or set ip_summed to CHECKSUM_NONE
+ *	so that it can be recomputed from scratch.
+ */
+
+static inline void skb_postpull_rcsum(struct sk_buff *skb,
+					 const void *start, int len)
+{
+	if (skb->ip_summed == CHECKSUM_HW)
+		skb->csum = csum_sub(skb->csum, csum_partial(start, len, 0));
+}
+
+/**
+ *	pskb_trim_rcsum - trim received skb and update checksum
+ *	@skb: buffer to trim
+ *	@len: new length
+ *
+ *	This is exactly the same as pskb_trim except that it ensures the
+ *	checksum of received packets are still valid after the operation.
+ */
+
+static inline int pskb_trim_rcsum(struct sk_buff *skb, unsigned int len)
+{
+	if (len >= skb->len)
+		return 0;
+	if (skb->ip_summed == CHECKSUM_HW)
+		skb->ip_summed = CHECKSUM_NONE;
+	return __pskb_trim(skb, len);
+}
+
 static inline void *kmap_skb_frag(const skb_frag_t *frag)
 {
 #ifdef CONFIG_HIGHMEM
@@ -1117,22 +1204,6 @@
 
 extern void skb_init(void);
 extern void skb_add_mtu(int mtu);
-
-struct skb_iter {
-	/* Iteration functions set these */
-	unsigned char *data;
-	unsigned int len;
-
-	/* Private to iteration */
-	unsigned int nextfrag;
-	struct sk_buff *fraglist;
-};
-
-/* Keep iterating until skb_iter_next returns false. */
-extern void skb_iter_first(const struct sk_buff *skb, struct skb_iter *i);
-extern int skb_iter_next(const struct sk_buff *skb, struct skb_iter *i);
-/* Call this if aborting loop before !skb_iter_next */
-extern void skb_iter_abort(const struct sk_buff *skb, struct skb_iter *i);
 
 #ifdef CONFIG_NETFILTER
 static inline void nf_conntrack_put(struct nf_conntrack *nfct)
diff -Nru a/include/linux/sort.h b/include/linux/sort.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/linux/sort.h	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,10 @@
+#ifndef _LINUX_SORT_H
+#define _LINUX_SORT_H
+
+#include <linux/types.h>
+
+void sort(void *base, size_t num, size_t size,
+	  int (*cmp)(const void *, const void *),
+	  void (*swap)(void *, void *, int));
+
+#endif
diff -Nru a/include/linux/stallion.h b/include/linux/stallion.h
--- a/include/linux/stallion.h	2005-03-11 12:51:51 -08:00
+++ b/include/linux/stallion.h	2005-03-11 12:51:51 -08:00
@@ -126,7 +126,7 @@
 	int		nrbnks;
 	int		irq;
 	int		irqtype;
-	void		(*isr)(struct stlbrd *brdp);
+	int		(*isr)(struct stlbrd *brdp);
 	unsigned int	ioaddr1;
 	unsigned int	ioaddr2;
 	unsigned int	iosize1;
diff -Nru a/include/linux/stop_machine.h b/include/linux/stop_machine.h
--- a/include/linux/stop_machine.h	2005-03-11 12:51:40 -08:00
+++ b/include/linux/stop_machine.h	2005-03-11 12:51:40 -08:00
@@ -8,7 +8,7 @@
 #include <linux/cpu.h>
 #include <asm/system.h>
 
-#ifdef CONFIG_SMP
+#if defined(CONFIG_STOP_MACHINE) && defined(CONFIG_SMP)
 /**
  * stop_machine_run: freeze the machine on all CPUs and run this function
  * @fn: the function to run
diff -Nru a/include/linux/sunrpc/auth.h b/include/linux/sunrpc/auth.h
--- a/include/linux/sunrpc/auth.h	2005-03-11 12:51:46 -08:00
+++ b/include/linux/sunrpc/auth.h	2005-03-11 12:51:46 -08:00
@@ -35,8 +35,7 @@
  * Client user credentials
  */
 struct rpc_cred {
-	struct list_head	cr_hash;	/* hash chain */
-	struct rpc_auth *	cr_auth;
+	struct hlist_node	cr_hash;	/* hash chain */
 	struct rpc_credops *	cr_ops;
 	unsigned long		cr_expire;	/* when to gc */
 	atomic_t		cr_count;	/* ref count */
@@ -59,10 +58,13 @@
  */
 #define RPC_CREDCACHE_NR	8
 #define RPC_CREDCACHE_MASK	(RPC_CREDCACHE_NR - 1)
+struct rpc_cred_cache {
+	struct hlist_head	hashtable[RPC_CREDCACHE_NR];
+	unsigned long		nextgc;		/* next garbage collection */
+	unsigned long		expire;		/* cache expiry interval */
+};
+
 struct rpc_auth {
-	struct list_head	au_credcache[RPC_CREDCACHE_NR];
-	unsigned long		au_expire;	/* cache expiry interval */
-	unsigned long		au_nextgc;	/* next garbage collection */
 	unsigned int		au_cslack;	/* call cred size estimate */
 	unsigned int		au_rslack;	/* reply verf size guess */
 	unsigned int		au_flags;	/* various flags */
@@ -73,6 +75,7 @@
 						 * case) */
 	atomic_t		au_count;	/* Reference counter */
 
+	struct rpc_cred_cache *	au_credcache;
 	/* per-flavor data */
 };
 #define RPC_AUTH_PROC_CREDS	0x0010		/* process creds (including
@@ -91,14 +94,16 @@
 	struct rpc_auth *	(*create)(struct rpc_clnt *, rpc_authflavor_t);
 	void			(*destroy)(struct rpc_auth *);
 
+	struct rpc_cred *	(*lookup_cred)(struct rpc_auth *, struct auth_cred *, int);
 	struct rpc_cred *	(*crcreate)(struct rpc_auth*, struct auth_cred *, int);
 };
 
 struct rpc_credops {
+	const char *		cr_name;	/* Name of the auth flavour */
 	void			(*crdestroy)(struct rpc_cred *);
 
 	int			(*crmatch)(struct auth_cred *, struct rpc_cred *, int);
-	u32 *			(*crmarshal)(struct rpc_task *, u32 *, int);
+	u32 *			(*crmarshal)(struct rpc_task *, u32 *);
 	int			(*crrefresh)(struct rpc_task *);
 	u32 *			(*crvalidate)(struct rpc_task *, u32 *);
 	int			(*crwrap_req)(struct rpc_task *, kxdrproc_t,
@@ -130,7 +135,7 @@
 int			rpcauth_refreshcred(struct rpc_task *);
 void			rpcauth_invalcred(struct rpc_task *);
 int			rpcauth_uptodatecred(struct rpc_task *);
-void			rpcauth_init_credcache(struct rpc_auth *);
+int			rpcauth_init_credcache(struct rpc_auth *, unsigned long);
 void			rpcauth_free_credcache(struct rpc_auth *);
 
 static inline
diff -Nru a/include/linux/sunrpc/auth_gss.h b/include/linux/sunrpc/auth_gss.h
--- a/include/linux/sunrpc/auth_gss.h	2005-03-11 12:51:41 -08:00
+++ b/include/linux/sunrpc/auth_gss.h	2005-03-11 12:51:41 -08:00
@@ -68,18 +68,21 @@
 
 struct gss_cl_ctx {
 	atomic_t		count;
-	u32			gc_proc;
+	enum rpc_gss_proc	gc_proc;
 	u32			gc_seq;
 	spinlock_t		gc_seq_lock;
 	struct gss_ctx		*gc_gss_ctx;
 	struct xdr_netobj	gc_wire_ctx;
 	u32			gc_win;
+	unsigned long		gc_expiry;
 };
 
+struct gss_upcall_msg;
 struct gss_cred {
 	struct rpc_cred		gc_base;
-	u32			gc_flavor;
+	enum rpc_gss_svc	gc_service;
 	struct gss_cl_ctx	*gc_ctx;
+	struct gss_upcall_msg	*gc_upcall;
 };
 
 #define gc_uid			gc_base.cr_uid
diff -Nru a/include/linux/sunrpc/cache.h b/include/linux/sunrpc/cache.h
--- a/include/linux/sunrpc/cache.h	2005-03-11 12:51:46 -08:00
+++ b/include/linux/sunrpc/cache.h	2005-03-11 12:51:46 -08:00
@@ -37,8 +37,7 @@
  * Entries have a ref count and a 'hashed' flag which counts the existance
  * in the hash table.
  * We only expire entries when refcount is zero.
- * Existance in the cache is not measured in refcount but rather in
- * CACHE_HASHED flag.
+ * Existance in the cache is counted  the refcount.
  */
 
 /* Every cache item has a common header that is used
@@ -57,7 +56,6 @@
 #define	CACHE_VALID	0	/* Entry contains valid data */
 #define	CACHE_NEGATIVE	1	/* Negative entry - there is no match for the key */
 #define	CACHE_PENDING	2	/* An upcall has been sent but no reply received yet*/
-#define	CACHE_HASHED	3	/* Entry is in a hash table */
 
 #define	CACHE_NEW_EXPIRY 120	/* keep new things pending confirmation for 120 seconds */
 
@@ -185,7 +183,6 @@
 											\
 			if (new)							\
 				{INIT;}							\
-			cache_get(&tmp->MEMBER);					\
 			if (set) {							\
 				if (!INPLACE && test_bit(CACHE_VALID, &tmp->MEMBER.flags))\
 				{ /* need to swap in new */				\
@@ -194,8 +191,6 @@
 					new->MEMBER.next = tmp->MEMBER.next;		\
 					*hp = &new->MEMBER;				\
 					tmp->MEMBER.next = NULL;			\
-					set_bit(CACHE_HASHED, &new->MEMBER.flags);	\
-					clear_bit(CACHE_HASHED, &tmp->MEMBER.flags);	\
 					t2 = tmp; tmp = new; new = t2;			\
 				}							\
 				if (test_bit(CACHE_NEGATIVE,  &item->MEMBER.flags))	\
@@ -205,6 +200,7 @@
 					clear_bit(CACHE_NEGATIVE, &tmp->MEMBER.flags);	\
 				}							\
 			}								\
+			cache_get(&tmp->MEMBER);					\
 			if (set||new) write_unlock(&(DETAIL)->hash_lock);		\
 			else read_unlock(&(DETAIL)->hash_lock);				\
 			if (set)							\
@@ -220,7 +216,7 @@
 		new->MEMBER.next = *head;						\
 		*head = &new->MEMBER;							\
 		(DETAIL)->entries ++;							\
-		set_bit(CACHE_HASHED, &new->MEMBER.flags);				\
+		cache_get(&new->MEMBER);						\
 		if (set) {								\
 			tmp = new;							\
 			if (test_bit(CACHE_NEGATIVE, &item->MEMBER.flags))		\
@@ -268,15 +264,10 @@
 
 static inline int cache_put(struct cache_head *h, struct cache_detail *cd)
 {
-	atomic_dec(&h->refcnt);
-	if (!atomic_read(&h->refcnt) &&
+	if (atomic_read(&h->refcnt) <= 2 &&
 	    h->expiry_time < cd->nextcheck)
 		cd->nextcheck = h->expiry_time;
-	if (!test_bit(CACHE_HASHED, &h->flags) &&
-	    !atomic_read(&h->refcnt))
-		return 1;
-
-	return 0;
+	return atomic_dec_and_test(&h->refcnt);
 }
 
 extern void cache_init(struct cache_head *h);
diff -Nru a/include/linux/sunrpc/clnt.h b/include/linux/sunrpc/clnt.h
--- a/include/linux/sunrpc/clnt.h	2005-03-11 12:51:47 -08:00
+++ b/include/linux/sunrpc/clnt.h	2005-03-11 12:51:47 -08:00
@@ -51,7 +51,6 @@
 				cl_intr     : 1,/* interruptible */
 				cl_chatty   : 1,/* be verbose */
 				cl_autobind : 1,/* use getport() */
-				cl_droppriv : 1,/* enable NFS suid hack */
 				cl_oneshot  : 1,/* dispose after use */
 				cl_dead     : 1;/* abandoned */
 
@@ -129,6 +128,7 @@
 void		rpc_clnt_sigmask(struct rpc_clnt *clnt, sigset_t *oldset);
 void		rpc_clnt_sigunmask(struct rpc_clnt *clnt, sigset_t *oldset);
 void		rpc_setbufsize(struct rpc_clnt *, unsigned int, unsigned int);
+size_t		rpc_max_payload(struct rpc_clnt *);
 
 static __inline__
 int rpc_call(struct rpc_clnt *clnt, u32 proc, void *argp, void *resp, int flags)
diff -Nru a/include/linux/sunrpc/gss_api.h b/include/linux/sunrpc/gss_api.h
--- a/include/linux/sunrpc/gss_api.h	2005-03-11 12:51:51 -08:00
+++ b/include/linux/sunrpc/gss_api.h	2005-03-11 12:51:51 -08:00
@@ -33,8 +33,9 @@
 
 /* gss-api prototypes; note that these are somewhat simplified versions of
  * the prototypes specified in RFC 2744. */
-u32 gss_import_sec_context(
-		struct xdr_netobj	*input_token,
+int gss_import_sec_context(
+		const void*		input_token,
+		size_t			bufsize,
 		struct gss_api_mech	*mech,
 		struct gss_ctx		**ctx_id);
 u32 gss_get_mic(
@@ -50,8 +51,6 @@
 u32 gss_delete_sec_context(
 		struct gss_ctx		**ctx_id);
 
-struct gss_api_mech * gss_mech_get_by_name(char *name);
-struct gss_api_mech * gss_mech_get_by_pseudoflavor(u32 pseudoflavor);
 u32 gss_pseudoflavor_to_service(struct gss_api_mech *, u32 pseudoflavor);
 char *gss_service_to_auth_domain_name(struct gss_api_mech *, u32 service);
 
@@ -80,8 +79,9 @@
 
 /* and must provide the following operations: */
 struct gss_api_ops {
-	u32 (*gss_import_sec_context)(
-			struct xdr_netobj	*input_token,
+	int (*gss_import_sec_context)(
+			const void		*input_token,
+			size_t			bufsize,
 			struct gss_ctx		*ctx_id);
 	u32 (*gss_get_mic)(
 			struct gss_ctx		*ctx_id,
@@ -105,7 +105,7 @@
 struct gss_api_mech * gss_mech_get_by_OID(struct xdr_netobj *);
 
 /* Returns a reference to a mechanism, given a name like "krb5" etc. */
-struct gss_api_mech *gss_mech_get_by_name(char *);
+struct gss_api_mech *gss_mech_get_by_name(const char *);
 
 /* Similar, but get by pseudoflavor. */
 struct gss_api_mech *gss_mech_get_by_pseudoflavor(u32);
diff -Nru a/include/linux/sunrpc/sched.h b/include/linux/sunrpc/sched.h
--- a/include/linux/sunrpc/sched.h	2005-03-11 12:51:47 -08:00
+++ b/include/linux/sunrpc/sched.h	2005-03-11 12:51:47 -08:00
@@ -53,9 +53,8 @@
 	struct rpc_message	tk_msg;		/* RPC call info */
 	__u32 *			tk_buffer;	/* XDR buffer */
 	size_t			tk_bufsize;
-	__u8			tk_garb_retry,
-				tk_cred_retry,
-				tk_suid_retry;
+	__u8			tk_garb_retry;
+	__u8			tk_cred_retry;
 
 	unsigned long		tk_cookie;	/* Cookie for batching tasks */
 
@@ -118,9 +117,7 @@
  */
 #define RPC_TASK_ASYNC		0x0001		/* is an async task */
 #define RPC_TASK_SWAPPER	0x0002		/* is swapping in/out */
-#define RPC_TASK_SETUID		0x0004		/* is setuid process */
 #define RPC_TASK_CHILD		0x0008		/* is child of other task */
-#define RPC_CALL_REALUID	0x0010		/* try using real uid */
 #define RPC_CALL_MAJORSEEN	0x0020		/* major timeout seen */
 #define RPC_TASK_ROOTCREDS	0x0040		/* force root creds */
 #define RPC_TASK_DYNAMIC	0x0080		/* task was kmalloc'ed */
@@ -129,7 +126,6 @@
 #define RPC_TASK_NOINTR		0x0400		/* uninterruptible task */
 
 #define RPC_IS_ASYNC(t)		((t)->tk_flags & RPC_TASK_ASYNC)
-#define RPC_IS_SETUID(t)	((t)->tk_flags & RPC_TASK_SETUID)
 #define RPC_IS_CHILD(t)		((t)->tk_flags & RPC_TASK_CHILD)
 #define RPC_IS_SWAPPER(t)	((t)->tk_flags & RPC_TASK_SWAPPER)
 #define RPC_DO_ROOTOVERRIDE(t)	((t)->tk_flags & RPC_TASK_ROOTCREDS)
diff -Nru a/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h
--- a/include/linux/sunrpc/svc.h	2005-03-11 12:51:46 -08:00
+++ b/include/linux/sunrpc/svc.h	2005-03-11 12:51:46 -08:00
@@ -251,8 +251,7 @@
 	char *			pg_name;	/* service name */
 	char *			pg_class;	/* class name: services sharing authentication */
 	struct svc_stat *	pg_stats;	/* rpc statistics */
-	/* Override authentication. NULL means use default */
-	int			(*pg_authenticate)(struct svc_rqst *, u32 *);
+	int			(*pg_authenticate)(struct svc_rqst *);
 };
 
 /*
diff -Nru a/include/linux/sunrpc/svcauth.h b/include/linux/sunrpc/svcauth.h
--- a/include/linux/sunrpc/svcauth.h	2005-03-11 12:51:42 -08:00
+++ b/include/linux/sunrpc/svcauth.h	2005-03-11 12:51:42 -08:00
@@ -92,6 +92,7 @@
 	int	(*accept)(struct svc_rqst *rq, u32 *authp);
 	int	(*release)(struct svc_rqst *rq);
 	void	(*domain_release)(struct auth_domain *);
+	int	(*set_client)(struct svc_rqst *rq);
 };
 
 #define	SVC_GARBAGE	1
@@ -107,6 +108,7 @@
 
 extern int	svc_authenticate(struct svc_rqst *rqstp, u32 *authp);
 extern int	svc_authorise(struct svc_rqst *rqstp);
+extern int	svc_set_client(struct svc_rqst *rqstp);
 extern int	svc_auth_register(rpc_authflavor_t flavor, struct auth_ops *aops);
 extern void	svc_auth_unregister(rpc_authflavor_t flavor);
 
diff -Nru a/include/linux/sunrpc/xprt.h b/include/linux/sunrpc/xprt.h
--- a/include/linux/sunrpc/xprt.h	2005-03-11 12:51:47 -08:00
+++ b/include/linux/sunrpc/xprt.h	2005-03-11 12:51:47 -08:00
@@ -140,6 +140,9 @@
 	unsigned int		rcvsize,	/* socket receive buffer size */
 				sndsize;	/* socket send buffer size */
 
+	size_t			max_payload;	/* largest RPC payload size,
+						   in bytes */
+
 	struct rpc_wait_queue	sending;	/* requests waiting to send */
 	struct rpc_wait_queue	resend;		/* requests waiting to resend */
 	struct rpc_wait_queue	pending;	/* requests in flight */
diff -Nru a/include/linux/superhyway.h b/include/linux/superhyway.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/linux/superhyway.h	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,79 @@
+/*
+ * include/linux/superhyway.h
+ *
+ * SuperHyway Bus definitions
+ *
+ * Copyright (C) 2004, 2005  Paul Mundt <lethal@linux-sh.org>
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#ifndef __LINUX_SUPERHYWAY_H
+#define __LINUX_SUPERHYWAY_H
+
+#include <linux/device.h>
+
+/*
+ * SuperHyway IDs
+ */
+#define SUPERHYWAY_DEVICE_ID_SH5_DMAC	0x0183
+
+struct vcr_info {
+	u8	perr_flags;	/* P-port Error flags */
+	u8	merr_flags;	/* Module Error flags */
+	u16	mod_vers;	/* Module Version */
+	u16	mod_id;		/* Module ID */
+	u8	bot_mb;		/* Bottom Memory block */
+	u8	top_mb;		/* Top Memory block */
+};
+
+struct superhyway_device_id {
+	unsigned int id;
+	unsigned long driver_data;
+};
+
+struct superhyway_device;
+extern struct bus_type superhyway_bus_type;
+
+struct superhyway_driver {
+	char *name;
+
+	const struct superhyway_device_id *id_table;
+	struct device_driver drv;
+
+	int (*probe)(struct superhyway_device *dev, const struct superhyway_device_id *id);
+	void (*remove)(struct superhyway_device *dev);
+};
+
+#define to_superhyway_driver(d)	container_of((d), struct superhyway_driver, drv)
+
+struct superhyway_device {
+	char name[32];
+
+	struct device dev;
+
+	struct superhyway_device_id id;
+	struct superhyway_driver *drv;
+
+	struct resource resource;
+	struct vcr_info vcr;
+};
+
+#define to_superhyway_device(d)	container_of((d), struct superhyway_device, dev)
+
+#define superhyway_get_drvdata(d)	dev_get_drvdata(&(d)->dev)
+#define superhyway_set_drvdata(d,p)	dev_set_drvdata(&(d)->dev, (p))
+
+extern int superhyway_scan_bus(void);
+
+/* drivers/sh/superhyway/superhyway.c */
+int superhyway_register_driver(struct superhyway_driver *);
+void superhyway_unregister_driver(struct superhyway_driver *);
+int superhyway_add_device(unsigned int, unsigned long, unsigned long long);
+
+/* drivers/sh/superhyway/superhyway-sysfs.c */
+extern struct device_attribute superhyway_dev_attrs[];
+
+#endif /* __LINUX_SUPERHYWAY_H */
+
diff -Nru a/include/linux/suspend.h b/include/linux/suspend.h
--- a/include/linux/suspend.h	2005-03-11 12:51:42 -08:00
+++ b/include/linux/suspend.h	2005-03-11 12:51:42 -08:00
@@ -15,10 +15,21 @@
 	unsigned long address;		/* address of the copy */
 	unsigned long orig_address;	/* original address of page */
 	swp_entry_t swap_address;	
-	swp_entry_t dummy;		/* we need scratch space at 
-					 * end of page (see link, diskpage)
-					 */
+
+	struct pbe *next;	/* also used as scratch space at
+				 * end of page (see link, diskpage)
+				 */
 } suspend_pagedir_t;
+
+#define for_each_pbe(pbe, pblist) \
+	for (pbe = pblist ; pbe ; pbe = pbe->next)
+
+#define PBES_PER_PAGE      (PAGE_SIZE/sizeof(struct pbe))
+#define PB_PAGE_SKIP       (PBES_PER_PAGE-1)
+
+#define for_each_pb_page(pbe, pblist) \
+	for (pbe = pblist ; pbe ; pbe = (pbe+PB_PAGE_SKIP)->next)
+
 
 #define SWAP_FILENAME_MAXLENGTH	32
 
diff -Nru a/include/linux/sysctl.h b/include/linux/sysctl.h
--- a/include/linux/sysctl.h	2005-03-11 12:51:46 -08:00
+++ b/include/linux/sysctl.h	2005-03-11 12:51:46 -08:00
@@ -135,6 +135,7 @@
 	KERN_HZ_TIMER=65,	/* int: hz timer on or off */
 	KERN_UNKNOWN_NMI_PANIC=66, /* int: unknown nmi panic flag */
 	KERN_BOOTLOADER_TYPE=67, /* int: boot loader type */
+	KERN_RANDOMIZE=68, /* int: randomize virtual address space */
 };
 
 
@@ -398,6 +399,7 @@
 	NET_IPV4_CONF_FORCE_IGMP_VERSION=17,
 	NET_IPV4_CONF_ARP_ANNOUNCE=18,
 	NET_IPV4_CONF_ARP_IGNORE=19,
+	__NET_IPV4_CONF_MAX
 };
 
 /* /proc/sys/net/ipv4/netfilter */
@@ -455,7 +457,8 @@
 	NET_IPV6_ROUTE_GC_INTERVAL=6,
 	NET_IPV6_ROUTE_GC_ELASTICITY=7,
 	NET_IPV6_ROUTE_MTU_EXPIRES=8,
-	NET_IPV6_ROUTE_MIN_ADVMSS=9
+	NET_IPV6_ROUTE_MIN_ADVMSS=9,
+	NET_IPV6_ROUTE_GC_MIN_INTERVAL_MS=10
 };
 
 enum {
@@ -475,7 +478,8 @@
 	NET_IPV6_REGEN_MAX_RETRY=14,
 	NET_IPV6_MAX_DESYNC_FACTOR=15,
 	NET_IPV6_MAX_ADDRESSES=16,
-	NET_IPV6_FORCE_MLD_VERSION=17
+	NET_IPV6_FORCE_MLD_VERSION=17,
+	__NET_IPV6_MAX
 };
 
 /* /proc/sys/net/ipv6/icmp */
@@ -500,7 +504,10 @@
 	NET_NEIGH_GC_INTERVAL=13,
 	NET_NEIGH_GC_THRESH1=14,
 	NET_NEIGH_GC_THRESH2=15,
-	NET_NEIGH_GC_THRESH3=16
+	NET_NEIGH_GC_THRESH3=16,
+	NET_NEIGH_RETRANS_TIME_MS=17,
+	NET_NEIGH_REACHABLE_TIME_MS=18,
+	__NET_NEIGH_MAX
 };
 
 /* /proc/sys/net/ipx */
diff -Nru a/include/linux/tc_ematch/tc_em_cmp.h b/include/linux/tc_ematch/tc_em_cmp.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/linux/tc_ematch/tc_em_cmp.h	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,26 @@
+#ifndef __LINUX_TC_EM_CMP_H
+#define __LINUX_TC_EM_CMP_H
+
+#include <linux/pkt_cls.h>
+
+struct tcf_em_cmp
+{
+	__u32		val;
+	__u32		mask;
+	__u16		off;
+	__u8		align:4;
+	__u8		flags:4;
+	__u8		layer:4;
+	__u8		opnd:4;
+};
+
+enum
+{
+	TCF_EM_ALIGN_U8  = 1,
+	TCF_EM_ALIGN_U16 = 2,
+	TCF_EM_ALIGN_U32 = 4
+};
+
+#define TCF_EM_CMP_TRANS	1
+
+#endif
diff -Nru a/include/linux/tc_ematch/tc_em_meta.h b/include/linux/tc_ematch/tc_em_meta.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/linux/tc_ematch/tc_em_meta.h	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,69 @@
+#ifndef __LINUX_TC_EM_META_H
+#define __LINUX_TC_EM_META_H
+
+#include <linux/pkt_cls.h>
+
+enum
+{
+	TCA_EM_META_UNSPEC,
+	TCA_EM_META_HDR,
+	TCA_EM_META_LVALUE,
+	TCA_EM_META_RVALUE,
+	__TCA_EM_META_MAX
+};
+#define TCA_EM_META_MAX (__TCA_EM_META_MAX - 1)
+
+struct tcf_meta_val
+{
+	__u16			kind;
+	__u8			shift;
+	__u8			op;
+};
+
+#define TCF_META_TYPE_MASK	(0xf << 12)
+#define TCF_META_TYPE(kind)	(((kind) & TCF_META_TYPE_MASK) >> 12)
+#define TCF_META_ID_MASK	0x7ff
+#define TCF_META_ID(kind)	((kind) & TCF_META_ID_MASK)
+
+enum
+{
+	TCF_META_TYPE_VAR,
+	TCF_META_TYPE_INT,
+	__TCF_META_TYPE_MAX
+};
+#define TCF_META_TYPE_MAX (__TCF_META_TYPE_MAX - 1)
+
+enum
+{
+	TCF_META_ID_VALUE,
+	TCF_META_ID_RANDOM,
+	TCF_META_ID_LOADAVG_0,
+	TCF_META_ID_LOADAVG_1,
+	TCF_META_ID_LOADAVG_2,
+	TCF_META_ID_DEV,
+	TCF_META_ID_INDEV,
+	TCF_META_ID_REALDEV,
+	TCF_META_ID_PRIORITY,
+	TCF_META_ID_PROTOCOL,
+	TCF_META_ID_SECURITY,
+	TCF_META_ID_PKTTYPE,
+	TCF_META_ID_PKTLEN,
+	TCF_META_ID_DATALEN,
+	TCF_META_ID_MACLEN,
+	TCF_META_ID_NFMARK,
+	TCF_META_ID_TCINDEX,
+	TCF_META_ID_TCVERDICT,
+	TCF_META_ID_TCCLASSID,
+	TCF_META_ID_RTCLASSID,
+	TCF_META_ID_RTIIF,
+	__TCF_META_ID_MAX
+};
+#define TCF_META_ID_MAX (__TCF_META_ID_MAX - 1)
+
+struct tcf_meta_hdr
+{
+	struct tcf_meta_val	left;
+	struct tcf_meta_val	right;
+};
+
+#endif
diff -Nru a/include/linux/tc_ematch/tc_em_nbyte.h b/include/linux/tc_ematch/tc_em_nbyte.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/linux/tc_ematch/tc_em_nbyte.h	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,13 @@
+#ifndef __LINUX_TC_EM_NBYTE_H
+#define __LINUX_TC_EM_NBYTE_H
+
+#include <linux/pkt_cls.h>
+
+struct tcf_em_nbyte
+{
+	__u16		off;
+	__u16		len:12;
+	__u8		layer:4;
+};
+
+#endif
diff -Nru a/include/linux/tcp.h b/include/linux/tcp.h
--- a/include/linux/tcp.h	2005-03-11 12:51:46 -08:00
+++ b/include/linux/tcp.h	2005-03-11 12:51:46 -08:00
@@ -284,10 +284,13 @@
 	__u32	mss_cache;	/* Cached effective mss, not including SACKS */
 	__u16	mss_cache_std;	/* Like mss_cache, but without TSO */
 	__u16	ext_header_len;	/* Network protocol overhead (IP/IPv6 options) */
-	__u16	ext2_header_len;/* Options depending on route */
 	__u8	ca_state;	/* State of fast-retransmit machine 	*/
 	__u8	retransmits;	/* Number of unrecovered RTO timeouts.	*/
 
+	__u16	advmss;		/* Advertised MSS			*/
+	__u32	window_clamp;	/* Maximal window to advertise		*/
+	__u32	rcv_ssthresh;	/* Current window clamp			*/
+
 	__u32	frto_highmark;	/* snd_nxt when RTO occurred */
 	__u8	reordering;	/* Packet reordering metric.		*/
 	__u8	frto_counter;	/* Number of new acks after RTO */
@@ -345,14 +348,9 @@
 	struct tcp_sack_block duplicate_sack[1]; /* D-SACK block */
 	struct tcp_sack_block selective_acks[4]; /* The SACKS themselves*/
 
-	__u32	window_clamp;	/* Maximal window to advertise		*/
-	__u32	rcv_ssthresh;	/* Current window clamp			*/
-	__u16	advmss;		/* Advertised MSS			*/
-
 	__u8	syn_retries;	/* num of allowed syn retries */
 	__u8	ecn_flags;	/* ECN status bits.			*/
 	__u16	prior_ssthresh; /* ssthresh saved at recovery start	*/
-	__u16	__pad1;
 	__u32	lost_out;	/* Lost packets			*/
 	__u32	sacked_out;	/* SACK'd packets			*/
 	__u32	fackets_out;	/* FACK'd packets			*/
diff -Nru a/include/linux/threads.h b/include/linux/threads.h
--- a/include/linux/threads.h	2005-03-11 12:51:41 -08:00
+++ b/include/linux/threads.h	2005-03-11 12:51:41 -08:00
@@ -7,7 +7,7 @@
  * The default limit for the nr of threads is now in
  * /proc/sys/kernel/threads-max.
  */
- 
+
 /*
  * Maximum supported processors that can run under SMP.  This value is
  * set via configure setting.  The maximum is equal to the size of the
@@ -25,11 +25,12 @@
 /*
  * This controls the default maximum pid allocated to a process
  */
-#define PID_MAX_DEFAULT 0x8000
+#define PID_MAX_DEFAULT (CONFIG_BASE_SMALL ? 0x1000 : 0x8000)
 
 /*
  * A maximum of 4 million PIDs should be enough for a while:
  */
-#define PID_MAX_LIMIT (sizeof(long) > 4 ? 4*1024*1024 : PID_MAX_DEFAULT)
+#define PID_MAX_LIMIT (CONFIG_BASE_SMALL ? PAGE_SIZE * 8 : \
+	(sizeof(long) > 4 ? 4 * 1024 * 1024 : PID_MAX_DEFAULT))
 
 #endif
diff -Nru a/include/linux/topology.h b/include/linux/topology.h
--- a/include/linux/topology.h	2005-03-11 12:51:47 -08:00
+++ b/include/linux/topology.h	2005-03-11 12:51:47 -08:00
@@ -31,8 +31,11 @@
 #include <linux/bitops.h>
 #include <linux/mmzone.h>
 #include <linux/smp.h>
-
 #include <asm/topology.h>
+
+#ifndef node_has_online_mem
+#define node_has_online_mem(nid) (1)
+#endif
 
 #ifndef nr_cpus_node
 #define nr_cpus_node(node)							\
diff -Nru a/include/linux/tpqic02.h b/include/linux/tpqic02.h
--- a/include/linux/tpqic02.h	2005-03-11 12:51:41 -08:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,738 +0,0 @@
-/* $Id: tpqic02.h,v 1.5 1996/12/14 23:01:38 root Exp root $
- *
- * Include file for QIC-02 driver for Linux.
- *
- * Copyright (c) 1992--1995 by H. H. Bergman. All rights reserved.
- *
- * ******* USER CONFIG SECTION BELOW (Near line 70) *******
- */
-
-#ifndef _LINUX_TPQIC02_H
-#define _LINUX_TPQIC02_H
-
-#include <linux/config.h>
-
-#if defined(CONFIG_QIC02_TAPE) || defined(CONFIG_QIC02_TAPE_MODULE)
-
-/* need to have QIC02_TAPE_DRIVE and QIC02_TAPE_IFC expand to something */
-#include <linux/mtio.h>
-
-
-/* Make QIC02_TAPE_IFC expand to something.
- *
- * The only difference between WANGTEK and EVEREX is in the 
- * handling of the DMA channel 3.
- * Note that the driver maps EVEREX to WANGTEK internally for speed
- * reasons. Externally WANGTEK==1, EVEREX==2, ARCHIVE==3.
- * These must correspond to the values used in qic02config(1).
- *
- * Support for Mountain controllers was added by Erik Jacobson
- * and severely hacked by me.   -- hhb
- * 
- * Support for Emerald controllers by Alan Bain <afrb2@chiark.chu.cam.ac.uk>
- * with more hacks by me.   -- hhb
- */
-#define WANGTEK		1		   /* don't know about Wangtek QIC-36 */
-#define EVEREX		(WANGTEK+1)  /* I heard *some* of these are identical */
-#define EVEREX_811V	EVEREX			      /* With TEAC MT 2ST 45D */
-#define EVEREX_831V	EVEREX
-#define ARCHIVE		3
-#define ARCHIVE_SC400	ARCHIVE	       /* rumoured to be from the pre-SMD-age */
-#define ARCHIVE_SC402	ARCHIVE		       /* don't know much about SC400 */
-#define ARCHIVE_SC499	ARCHIVE       /* SC402 and SC499R should be identical */
-
-#define MOUNTAIN	5		       /* Mountain Computer Interface */
-#define EMERALD		6		       /* Emerald Interface card */
-
-
-
-#define QIC02_TAPE_PORT_RANGE 	8	 /* number of IO locations to reserve */
-
-
-/*********** START OF USER CONFIGURABLE SECTION ************/
-
-/* Tape configuration: Select DRIVE, IFC, PORT, IRQ and DMA below.
- * Runtime (re)configuration is not supported yet.
- *
- * Tape drive configuration:	(MT_IS* constants are defined in mtio.h)
- *
- * QIC02_TAPE_DRIVE = MT_ISWT5150
- *	- Wangtek 5150, format: up to QIC-150.
- * QIC02_TAPE_DRIVE = MT_ISQIC02_ALL_FEATURES
- *	- Enables some optional QIC02 commands that some drives may lack.
- *	  It is provided so you can check which are supported by your drive.
- *	  Refer to tpqic02.h for others.
- *
- * Supported interface cards: QIC02_TAPE_IFC =
- *	WANGTEK,
- *	ARCHIVE_SC402, ARCHIVE_SC499.	(both same programming interface)
- *
- * Make sure you have the I/O ports/DMA channels 
- * and IRQ stuff configured properly!
- * NOTE: There may be other device drivers using the same major
- *       number. This must be avoided. Check for timer.h conflicts too.
- *
- * If you have an EVEREX EV-831 card and you are using DMA channel 3,
- * you will probably have to ``#define QIC02_TAPE_DMA3_FIX'' below.
- */
-
-/* CONFIG_QIC02_DYNCONF can be defined in autoconf.h, by `make config' */
-
-/*** #undef CONFIG_QIC02_DYNCONF ***/
-
-#ifndef CONFIG_QIC02_DYNCONF
-
-#define QIC02_TAPE_DRIVE	MT_ISQIC02_ALL_FEATURES	 /* drive type */
-/* #define QIC02_TAPE_DRIVE	MT_ISWT5150 */
-/* #define QIC02_TAPE_DRIVE	MT_ISARCHIVE_5945L2 */
-/* #define QIC02_TAPE_DRIVE	MT_ISTEAC_MT2ST */
-/* #define QIC02_TAPE_DRIVE	MT_ISARCHIVE_2150L */
-/* #define QIC02_TAPE_DRIVE	MT_ISARCHIVESC499 */
-
-/* Either WANGTEK, ARCHIVE or MOUNTAIN. Not EVEREX. 
- * If you have an EVEREX, use WANGTEK and try the DMA3_FIX below.
- */
-#define QIC02_TAPE_IFC		WANGTEK	/* interface card type */
-/* #define QIC02_TAPE_IFC		ARCHIVE */
-/* #define QIC02_TAPE_IFC		MOUNTAIN */
-
-#define QIC02_TAPE_PORT 	0x300	/* controller port address */
-#define QIC02_TAPE_IRQ		5	/* For IRQ2, use 9 here, others normal. */
-#define QIC02_TAPE_DMA		1	/* either 1 or 3, because 2 is used by the floppy */
-
-/* If DMA3 doesn't work, but DMA1 does, and you have a 
- * Wangtek/Everex card, you can try #define-ing the flag
- * below. Note that you should also change the DACK jumper
- * for Wangtek/Everex cards when changing the DMA channel.
- */
-#undef QIC02_TAPE_DMA3_FIX
-
-/************ END OF USER CONFIGURABLE SECTION *************/
-
-/* I put the stuff above in config.in, but a few recompiles, to
- * verify different configurations, and several days later I decided
- * to change it back again.
- */
-
-
-
-/* NOTE: TP_HAVE_DENS should distinguish between available densities (?)
- * NOTE: Drive select is not implemented -- I have only one tape streamer,
- *	 so I'm unable and unmotivated to test and implement that. ;-) ;-)
- */
-#if QIC02_TAPE_DRIVE == MT_ISWT5150
-#define TP_HAVE_DENS	1
-#define TP_HAVE_BSF	0	/* nope */
-#define TP_HAVE_FSR	0	/* nope */
-#define TP_HAVE_BSR	0	/* nope */
-#define TP_HAVE_EOD	0	/* most of the time */
-#define TP_HAVE_SEEK	0
-#define TP_HAVE_TELL	0
-#define TP_HAVE_RAS1	1
-#define TP_HAVE_RAS2	1
-
-#elif QIC02_TAPE_DRIVE == MT_ISARCHIVESC499	/* Archive SC-499 QIC-36 controller */
-#define TP_HAVE_DENS	1	/* can do set density (QIC-11 / QIC-24) */
-#define TP_HAVE_BSF	0
-#define TP_HAVE_FSR	1	/* can skip one block forwards */
-#define TP_HAVE_BSR	1	/* can skip one block backwards */
-#define TP_HAVE_EOD	1	/* can seek to end of recorded data */
-#define TP_HAVE_SEEK	0
-#define TP_HAVE_TELL	0
-#define TP_HAVE_RAS1	1	/* can run selftest 1 */
-#define TP_HAVE_RAS2	1	/* can run selftest 2 */
-/* These last two selftests shouldn't be used yet! */
-
-#elif (QIC02_TAPE_DRIVE == MT_ISARCHIVE_2060L) || (QIC02_TAPE_DRIVE == MT_ISARCHIVE_2150L)
-#define TP_HAVE_DENS	1	/* can do set density (QIC-24 / QIC-120 / QIC-150) */
-#define TP_HAVE_BSF	0
-#define TP_HAVE_FSR	1	/* can skip one block forwards */
-#define TP_HAVE_BSR	1	/* can skip one block backwards */
-#define TP_HAVE_EOD	1	/* can seek to end of recorded data */
-#define TP_HAVE_TELL	1	/* can read current block address */
-#define TP_HAVE_SEEK	1	/* can seek to block */
-#define TP_HAVE_RAS1	1	/* can run selftest 1 */
-#define TP_HAVE_RAS2	1	/* can run selftest 2 */
-/* These last two selftests shouldn't be used yet! */
-
-#elif QIC02_TAPE_DRIVE == MT_ISARCHIVE_5945L2
-/* can anyone verify this entry?? */
-#define TP_HAVE_DENS	1	/* can do set density?? (QIC-24??) */
-#define TP_HAVE_BSF	0
-#define TP_HAVE_FSR	1	/* can skip one block forwards */
-#define TP_HAVE_BSR	1	/* can skip one block backwards */
-#define TP_HAVE_EOD	1	/* can seek to end of recorded data */
-#define TP_HAVE_TELL	1	/* can read current block address */
-#define TP_HAVE_SEEK	1	/* can seek to block */
-#define TP_HAVE_RAS1	1	/* can run selftest 1 */
-#define TP_HAVE_RAS2	1	/* can run selftest 2 */
-/* These last two selftests shouldn't be used yet! */
-
-#elif QIC02_TAPE_DRIVE == MT_ISTEAC_MT2ST
-/* can anyone verify this entry?? */
-#define TP_HAVE_DENS	0	/* cannot do set density?? (QIC-150?) */
-#define TP_HAVE_BSF	0
-#define TP_HAVE_FSR	1	/* can skip one block forwards */
-#define TP_HAVE_BSR	1	/* can skip one block backwards */
-#define TP_HAVE_EOD	1	/* can seek to end of recorded data */
-#define TP_HAVE_SEEK	1	/* can seek to block */
-#define TP_HAVE_TELL	1	/* can read current block address */
-#define TP_HAVE_RAS1	1	/* can run selftest 1 */
-#define TP_HAVE_RAS2	1	/* can run selftest 2 */
-/* These last two selftests shouldn't be used yet! */
-
-#elif QIC02_TAPE_DRIVE == MT_ISQIC02_ALL_FEATURES
-#define TP_HAVE_DENS	1	/* can do set density */
-#define TP_HAVE_BSF	1	/* can search filemark backwards */
-#define TP_HAVE_FSR	1	/* can skip one block forwards */
-#define TP_HAVE_BSR	1	/* can skip one block backwards */
-#define TP_HAVE_EOD	1	/* can seek to end of recorded data */
-#define TP_HAVE_SEEK	1	/* seek to block address */
-#define TP_HAVE_TELL	1	/* tell current block address */
-#define TP_HAVE_RAS1	1	/* can run selftest 1 */
-#define TP_HAVE_RAS2	1	/* can run selftest 2 */
-/* These last two selftests shouldn't be used yet! */
-
-
-#else
-#error No QIC-02 tape drive type defined!
-/* If your drive is not listed above, first try the 'ALL_FEATURES',
- * to see what commands are supported, then create your own entry in
- * the list above. You may want to mail it to me, so that I can include
- * it in the next release.
- */
-#endif
-
-#endif /* !CONFIG_QIC02_DYNCONF */
-
-
-/* WANGTEK interface card specifics */
-#define WT_QIC02_STAT_PORT	(QIC02_TAPE_PORT)
-#define WT_QIC02_CTL_PORT	(QIC02_TAPE_PORT)
-#define WT_QIC02_CMD_PORT	(QIC02_TAPE_PORT+1)
-#define WT_QIC02_DATA_PORT	(QIC02_TAPE_PORT+1)
-
-/* status register bits (Active LOW!) */
-#define WT_QIC02_STAT_POLARITY	0
-#define WT_QIC02_STAT_READY	0x01
-#define WT_QIC02_STAT_EXCEPTION	0x02
-#define WT_QIC02_STAT_MASK	(WT_QIC02_STAT_READY|WT_QIC02_STAT_EXCEPTION)
-
-#define WT_QIC02_STAT_RESETMASK	0x07
-#define WT_QIC02_STAT_RESETVAL	(WT_QIC02_STAT_RESETMASK & ~WT_QIC02_STAT_EXCEPTION)
-
-/* controller register (QIC02_CTL_PORT) bits */
-#define WT_QIC02_CTL_RESET	0x02
-#define WT_QIC02_CTL_REQUEST	0x04
-#define WT_CTL_ONLINE		0x01
-#define WT_CTL_CMDOFF		0xC0 
-
-#define WT_CTL_DMA3		0x10			  /* enable dma chan3 */
-#define WT_CTL_DMA1		0x08	         /* enable dma chan1 or chan2 */
-
-/* EMERALD interface card specifics
- * Much like Wangtek, only different polarity and bit locations
- */
-#define EMR_QIC02_STAT_PORT	(QIC02_TAPE_PORT)
-#define EMR_QIC02_CTL_PORT	(QIC02_TAPE_PORT)
-#define EMR_QIC02_CMD_PORT	(QIC02_TAPE_PORT+1)
-#define EMR_QIC02_DATA_PORT	(QIC02_TAPE_PORT+1)
-
-/* status register bits (Active High!) */
-#define EMR_QIC02_STAT_POLARITY		1
-#define EMR_QIC02_STAT_READY		0x01
-#define EMR_QIC02_STAT_EXCEPTION	0x02
-#define EMR_QIC02_STAT_MASK	(EMR_QIC02_STAT_READY|EMR_QIC02_STAT_EXCEPTION)
-
-#define EMR_QIC02_STAT_RESETMASK	0x07
-#define EMR_QIC02_STAT_RESETVAL	(EMR_QIC02_STAT_RESETMASK & ~EMR_QIC02_STAT_EXCEPTION)
-
-/* controller register (QIC02_CTL_PORT) bits */
-#define EMR_QIC02_CTL_RESET	0x02
-#define EMR_QIC02_CTL_REQUEST	0x04
-#define EMR_CTL_ONLINE		0x01
-#define EMR_CTL_CMDOFF		0xC0 
-
-#define EMR_CTL_DMA3		0x10			  /* enable dma chan3 */
-#define EMR_CTL_DMA1		0x08	         /* enable dma chan1 or chan2 */
-
-
-
-/* ARCHIVE interface card specifics */
-#define AR_QIC02_STAT_PORT	(QIC02_TAPE_PORT+1)
-#define AR_QIC02_CTL_PORT	(QIC02_TAPE_PORT+1)
-#define AR_QIC02_CMD_PORT	(QIC02_TAPE_PORT)
-#define AR_QIC02_DATA_PORT	(QIC02_TAPE_PORT)
-
-#define AR_START_DMA_PORT	(QIC02_TAPE_PORT+2)
-#define AR_RESET_DMA_PORT	(QIC02_TAPE_PORT+3)
-
-/* STAT port bits */
-#define AR_QIC02_STAT_POLARITY	0
-#define AR_STAT_IRQF		0x80	/* active high, interrupt request flag */
-#define AR_QIC02_STAT_READY	0x40	/* active low */
-#define AR_QIC02_STAT_EXCEPTION	0x20	/* active low */
-#define AR_QIC02_STAT_MASK	(AR_QIC02_STAT_READY|AR_QIC02_STAT_EXCEPTION)
-#define AR_STAT_DMADONE		0x10	/* active high, DMA done */
-#define AR_STAT_DIRC		0x08	/* active high, direction */
-
-#define AR_QIC02_STAT_RESETMASK	0x70	/* check RDY,EXC,DMADONE */
-#define AR_QIC02_STAT_RESETVAL	((AR_QIC02_STAT_RESETMASK & ~AR_STAT_IRQF & ~AR_QIC02_STAT_EXCEPTION) | AR_STAT_DMADONE)
-
-/* CTL port bits */
-#define AR_QIC02_CTL_RESET	0x80	/* drive reset */
-#define AR_QIC02_CTL_REQUEST	0x40	/* notify of new command */
-#define AR_CTL_IEN		0x20	/* interrupt enable */
-#define AR_CTL_DNIEN		0x10	/* done-interrupt enable */
-  /* Note: All of these bits are cleared automatically when writing to
-   * AR_RESET_DMA_PORT. So AR_CTL_IEN and AR_CTL_DNIEN must be
-   * reprogrammed before the write to AR_START_DMA_PORT.
-   */
-
-
-/* MOUNTAIN interface specifics */
-#define MTN_QIC02_STAT_PORT	(QIC02_TAPE_PORT+1)
-#define MTN_QIC02_CTL_PORT	(QIC02_TAPE_PORT+1)
-#define MTN_QIC02_CMD_PORT	(QIC02_TAPE_PORT)
-#define MTN_QIC02_DATA_PORT	(QIC02_TAPE_PORT)
-
-#define MTN_W_SELECT_DMA_PORT	(QIC02_TAPE_PORT+2)
-#define MTN_R_DESELECT_DMA_PORT	(QIC02_TAPE_PORT+2)
-#define MTN_W_DMA_WRITE_PORT	(QIC02_TAPE_PORT+3)
-
-/* STAT port bits */
-#define MTN_QIC02_STAT_POLARITY	 0
-#define MTN_QIC02_STAT_READY	 0x02	/* active low */
-#define MTN_QIC02_STAT_EXCEPTION 0x04	/* active low */
-#define MTN_QIC02_STAT_MASK	 (MTN_QIC02_STAT_READY|MTN_QIC02_STAT_EXCEPTION)
-#define MTN_STAT_DMADONE	 0x01	/* active high, DMA done */
-
-#define MTN_QIC02_STAT_RESETMASK 0x07	/* check RDY,EXC,DMADONE */
-#define MTN_QIC02_STAT_RESETVAL	 ((MTN_QIC02_STAT_RESETMASK & ~MTN_QIC02_STAT_EXCEPTION) | MTN_STAT_DMADONE)
-
-/* CTL port bits */
-#define MTN_QIC02_CTL_RESET_NOT	 0x80	/* drive reset, active low */
-#define MTN_QIC02_CTL_RESET	 0x80	/* Fodder #definition to keep gcc happy */
-
-#define MTN_QIC02_CTL_ONLINE	 0x40	/* Put drive on line  */
-#define MTN_QIC02_CTL_REQUEST	 0x20	/* notify of new command */
-#define MTN_QIC02_CTL_IRQ_DRIVER 0x10	/* Enable IRQ tristate driver */
-#define MTN_QIC02_CTL_DMA_DRIVER 0x08	/* Enable DMA tristate driver */
-#define MTN_CTL_EXC_IEN		 0x04	/* Exception interrupt enable */
-#define MTN_CTL_RDY_IEN		 0x02	/* Ready interrupt enable */
-#define MTN_CTL_DNIEN		 0x01	/* done-interrupt enable */
-
-#define MTN_CTL_ONLINE		(MTN_QIC02_CTL_RESET_NOT | MTN_QIC02_CTL_IRQ_DRIVER | MTN_QIC02_CTL_DMA_DRIVER)
-
-
-#ifndef CONFIG_QIC02_DYNCONF
-
-# define QIC02_TAPE_DEBUG	(qic02_tape_debug)
-
-# if QIC02_TAPE_IFC == WANGTEK	
-#  define QIC02_STAT_POLARITY	WT_QIC02_STAT_POLARITY
-#  define QIC02_STAT_PORT	WT_QIC02_STAT_PORT
-#  define QIC02_CTL_PORT	WT_QIC02_CTL_PORT
-#  define QIC02_CMD_PORT	WT_QIC02_CMD_PORT
-#  define QIC02_DATA_PORT	WT_QIC02_DATA_PORT
-
-#  define QIC02_STAT_READY	WT_QIC02_STAT_READY
-#  define QIC02_STAT_EXCEPTION	WT_QIC02_STAT_EXCEPTION
-#  define QIC02_STAT_MASK	WT_QIC02_STAT_MASK
-#  define QIC02_STAT_RESETMASK	WT_QIC02_STAT_RESETMASK
-#  define QIC02_STAT_RESETVAL	WT_QIC02_STAT_RESETVAL
-
-#  define QIC02_CTL_RESET	WT_QIC02_CTL_RESET
-#  define QIC02_CTL_REQUEST	WT_QIC02_CTL_REQUEST
-
-#  if QIC02_TAPE_DMA == 3
-#   ifdef QIC02_TAPE_DMA3_FIX
-#    define WT_CTL_DMA		WT_CTL_DMA1
-#   else
-#    define WT_CTL_DMA		WT_CTL_DMA3
-#   endif
-#  elif QIC02_TAPE_DMA == 1
-#    define WT_CTL_DMA		WT_CTL_DMA1
-#  else
-#   error Unsupported or incorrect DMA configuration.
-#  endif
-
-# elif QIC02_TAPE_IFC == EMERALD
-#  define QIC02_STAT_POLARITY	EMR_QIC02_STAT_POLARITY
-#  define QIC02_STAT_PORT	EMR_QIC02_STAT_PORT
-#  define QIC02_CTL_PORT	EMR_QIC02_CTL_PORT
-#  define QIC02_CMD_PORT	EMR_QIC02_CMD_PORT
-#  define QIC02_DATA_PORT	EMR_QIC02_DATA_PORT
-
-#  define QIC02_STAT_READY	EMR_QIC02_STAT_READY
-#  define QIC02_STAT_EXCEPTION	EMR_QIC02_STAT_EXCEPTION
-#  define QIC02_STAT_MASK	EMR_QIC02_STAT_MASK
-#  define QIC02_STAT_RESETMASK	EMR_QIC02_STAT_RESETMASK
-#  define QIC02_STAT_RESETVAL	EMR_QIC02_STAT_RESETVAL
-
-#  define QIC02_CTL_RESET	EMR_QIC02_CTL_RESET
-#  define QIC02_CTL_REQUEST	EMR_QIC02_CTL_REQUEST
-
-#  if QIC02_TAPE_DMA == 3
-#   ifdef QIC02_TAPE_DMA3_FIX
-#    define EMR_CTL_DMA		EMR_CTL_DMA1
-#   else
-#    define EMR_CTL_DMA		EMR_CTL_DMA3
-#   endif
-#  elif QIC02_TAPE_DMA == 1
-#    define EMR_CTL_DMA		EMR_CTL_DMA1
-#  else
-#   error Unsupported or incorrect DMA configuration.
-#  endif
-
-# elif QIC02_TAPE_IFC == ARCHIVE
-#  define QIC02_STAT_POLARITY	AR_QIC02_STAT_POLARITY
-#  define QIC02_STAT_PORT	AR_QIC02_STAT_PORT
-#  define QIC02_CTL_PORT	AR_QIC02_CTL_PORT
-#  define QIC02_CMD_PORT	AR_QIC02_CMD_PORT
-#  define QIC02_DATA_PORT	AR_QIC02_DATA_PORT
-
-#  define QIC02_STAT_READY	AR_QIC02_STAT_READY
-#  define QIC02_STAT_EXCEPTION	AR_QIC02_STAT_EXCEPTION
-#  define QIC02_STAT_MASK	AR_QIC02_STAT_MASK
-#  define QIC02_STAT_RESETMASK	AR_QIC02_STAT_RESETMASK
-#  define QIC02_STAT_RESETVAL	AR_QIC02_STAT_RESETVAL
-
-#  define QIC02_CTL_RESET	AR_QIC02_CTL_RESET
-#  define QIC02_CTL_REQUEST	AR_QIC02_CTL_REQUEST
-
-#  if QIC02_TAPE_DMA > 3	/* channel 2 is used by the floppy driver */
-#   error DMA channels other than 1 and 3 are not supported.
-#  endif
-
-# elif QIC02_TAPE_IFC == MOUNTAIN
-#  define QIC02_STAT_POLARITY	MTN_QIC02_STAT_POLARITY
-#  define QIC02_STAT_PORT	MTN_QIC02_STAT_PORT
-#  define QIC02_CTL_PORT	MTN_QIC02_CTL_PORT
-#  define QIC02_CMD_PORT	MTN_QIC02_CMD_PORT
-#  define QIC02_DATA_PORT	MTN_QIC02_DATA_PORT
-
-#  define QIC02_STAT_READY	MTN_QIC02_STAT_READY
-#  define QIC02_STAT_EXCEPTION	MTN_QIC02_STAT_EXCEPTION
-#  define QIC02_STAT_MASK	MTN_QIC02_STAT_MASK
-#  define QIC02_STAT_RESETMASK	MTN_QIC02_STAT_RESETMASK
-#  define QIC02_STAT_RESETVAL	MTN_QIC02_STAT_RESETVAL
-
-#  define QIC02_CTL_RESET	MTN_QIC02_CTL_RESET
-#  define QIC02_CTL_REQUEST	MTN_QIC02_CTL_REQUEST
-
-#  if QIC02_TAPE_DMA > 3	/* channel 2 is used by the floppy driver */
-#   error DMA channels other than 1 and 3 are not supported.
-#  endif
-
-# else
-#  error No valid interface card specified!
-# endif /* QIC02_TAPE_IFC */
-
-
-  /* An ugly hack to make sure WT_CTL_DMA is defined even for the
-   * static, non-Wangtek case. The alternative was even worse.
-   */ 
-# ifndef WT_CTL_DMA
-#  define WT_CTL_DMA		WT_CTL_DMA1
-# endif
-
-/*******************/
-
-#else /* !CONFIG_QIC02_DYNCONF */
-
-/* Now the runtime config version, using variables instead of constants.
- *
- * qic02_tape_dynconf is R/O for the kernel, set from userspace.
- * qic02_tape_ccb is private to the driver, R/W.
- */
-
-# define QIC02_TAPE_DRIVE	(qic02_tape_dynconf.mt_type)
-# define QIC02_TAPE_IFC		(qic02_tape_ccb.ifc_type)
-# define QIC02_TAPE_IRQ		(qic02_tape_dynconf.irqnr)
-# define QIC02_TAPE_DMA		(qic02_tape_dynconf.dmanr)
-# define QIC02_TAPE_PORT	(qic02_tape_dynconf.port)
-# define WT_CTL_DMA		(qic02_tape_ccb.dma_enable_value)
-# define QIC02_TAPE_DEBUG	(qic02_tape_dynconf.debug)
-
-# define QIC02_STAT_PORT	(qic02_tape_ccb.port_stat)
-# define QIC02_CTL_PORT 	(qic02_tape_ccb.port_ctl)
-# define QIC02_CMD_PORT 	(qic02_tape_ccb.port_cmd)
-# define QIC02_DATA_PORT 	(qic02_tape_ccb.port_data)
-
-# define QIC02_STAT_POLARITY	(qic02_tape_ccb.stat_polarity)
-# define QIC02_STAT_READY	(qic02_tape_ccb.stat_ready)
-# define QIC02_STAT_EXCEPTION	(qic02_tape_ccb.stat_exception)
-# define QIC02_STAT_MASK	(qic02_tape_ccb.stat_mask)
-
-# define QIC02_STAT_RESETMASK	(qic02_tape_ccb.stat_resetmask)
-# define QIC02_STAT_RESETVAL	(qic02_tape_ccb.stat_resetval)
-
-# define QIC02_CTL_RESET	(qic02_tape_ccb.ctl_reset)
-# define QIC02_CTL_REQUEST	(qic02_tape_ccb.ctl_request)
-
-# define TP_HAVE_DENS		(qic02_tape_dynconf.have_dens)
-# define TP_HAVE_BSF		(qic02_tape_dynconf.have_bsf)
-# define TP_HAVE_FSR		(qic02_tape_dynconf.have_fsr)
-# define TP_HAVE_BSR		(qic02_tape_dynconf.have_bsr)
-# define TP_HAVE_EOD		(qic02_tape_dynconf.have_eod)
-# define TP_HAVE_SEEK		(qic02_tape_dynconf.have_seek)
-# define TP_HAVE_TELL		(qic02_tape_dynconf.have_tell)
-# define TP_HAVE_RAS1		(qic02_tape_dynconf.have_ras1)
-# define TP_HAVE_RAS2		(qic02_tape_dynconf.have_ras2)
-
-#endif /* CONFIG_QIC02_DYNCONF */
-
-
-/* "Vendor Unique" codes */
-/* Archive seek & tell stuff */
-#define AR_QCMDV_TELL_BLK	0xAE	/* read current block address */
-#define AR_QCMDV_SEEK_BLK	0xAD	/* seek to specific block */
-#define AR_SEEK_BUF_SIZE	3	/* address is 3 bytes */
-
-
-
-/*
- * Misc common stuff
- */
-
-/* Standard QIC-02 commands -- rev F.  All QIC-02 drives must support these */
-#define QCMD_SEL_1	0x01		/* select drive 1 */
-#define QCMD_SEL_2	0x02		/* select drive 2 */
-#define QCMD_SEL_3	0x04		/* select drive 3 */
-#define QCMD_SEL_4	0x08		/* select drive 4 */
-#define	QCMD_REWIND	0x21		/* rewind tape */
-#define QCMD_ERASE	0x22		/* erase tape */
-#define QCMD_RETEN	0x24		/* retension tape */
-#define	QCMD_WRT_DATA	0x40		/* write data */
-#define	QCMD_WRT_FM	0x60		/* write file mark */
-#define	QCMD_RD_DATA	0x80		/* read data */
-#define	QCMD_RD_FM	0xA0		/* read file mark (forward direction) */
-#define	QCMD_RD_STAT	0xC0		/* read status */
-
-/* Other (optional/vendor unique) commands */
- /* Density commands are only valid when TP_BOM is set! */
-#define QCMD_DENS_11	0x26		/* QIC-11 */
-#define QCMD_DENS_24	0x27		/* QIC-24: 9 track 60MB */
-#define QCMD_DENS_120	0x28		/* QIC-120: 15 track 120MB */
-#define QCMD_DENS_150	0x29		/* QIC-150: 18 track 150MB */
-#define QCMD_DENS_300	0x2A		/* QIC-300/QIC-2100 */
-#define QCMD_DENS_600	0x2B		/* QIC-600/QIC-2200 */
-/* don't know about QIC-1000 and QIC-1350 */
-
-#define	QCMD_WRTNU_DATA	0x40		/* write data, no underruns, insert filler. */
-#define QCMD_SPACE_FWD	0x81		/* skip next block */
-#define QCMD_SPACE_BCK	0x89		/* move tape head one block back -- very useful! */
-#define QCMD_RD_FM_BCK	0xA8		/* read filemark (backwards) */
-#define QCMD_SEEK_EOD	0xA3		/* skip to EOD */
-#define	QCMD_RD_STAT_X1	0xC1		/* read extended status 1 */
-#define	QCMD_RD_STAT_X2	0xC4		/* read extended status 2 */
-#define	QCMD_RD_STAT_X3	0xE0		/* read extended status 3 */
-#define QCMD_SELF_TST1	0xC2		/* run self test 1 (nondestructive) */
-#define QCMD_SELF_TST2	0xCA		/* run self test 2 (destructive) */
-
-
-
-/* Optional, QFA (Quick File Access) commands.
- * Not all drives support this, but those that do could use these commands
- * to implement semi-non-sequential access. `mt fsf` would benefit from this.
- * QFA divides the tape into 2 partitions, a data and a directory partition,
- * causing some incompatibility problems wrt std QIC-02 data exchange.
- * It would be useful to cache the directory info, but that might be tricky
- * to do in kernel-space. [Size constraints.]
- * Refer to the QIC-02 specs, appendix A for more information.
- * I have no idea how other *nix variants implement QFA.
- * I have no idea which drives support QFA and which don't.
- */
-#define QFA_ENABLE	0x2D		/* enter QFA mode, give @ BOT only */
-#define QFA_DATA	0x20		/* select data partition */
-#define QFA_DIR		0x23		/* select directory partition */
-#define QFA_RD_POS	0xCF		/* read position+status bytes */
-#define QFA_SEEK_EOD	0xA1		/* seek EOD within current partition */
-#define QFA_SEEK_BLK	0xAF		/* seek to a block within current partition */
-
-
-
-
-/*
- * Debugging flags
- */
-#define TPQD_SENSE_TEXT	0x0001
-#define TPQD_SENSE_CNTS 0x0002
-#define TPQD_REWIND	0x0004
-#define TPQD_TERM_CYCLE	0x0008
-#define TPQD_IOCTLS	0x0010
-#define TPQD_DMAX	0x0020
-#define TPQD_BLKSZ	0x0040
-#define TPQD_MISC	0x0080
-
-#define TPQD_DEBUG	0x0100
-
-#define TPQD_DIAGS	0x1000
-
-#define TPQD_ALWAYS	0x8000
-
-#define TPQD_DEFAULT_FLAGS	0x00fc
-
-
-#define TPQDBG(f)	((QIC02_TAPE_DEBUG) & (TPQD_##f))
-
-
-/* Minor device codes for tapes:
- * |7|6|5|4|3|2|1|0|
- *  | \ | / \ | / |_____ 1=rewind on close, 0=no rewind on close
- *  |  \|/    |_________ Density: 000=none, 001=QIC-11, 010=24, 011=120,
- *  |   |                100=QIC-150, 101..111 reserved.
- *  |   |_______________ Reserved for unit numbers.
- *  |___________________ Reserved for diagnostics during debugging.
- */
-
-#define	TP_REWCLOSE(d)	((d)&1)	   		/* rewind bit */
-			   /* rewind is only done if data has been transferred */
-#define	TP_DENS(d)	(((d) >> 1) & 0x07) 	      /* tape density */
-#define TP_UNIT(d)	(((d) >> 4) & 0x07)	       /* unit number */
-
-/* print excessive diagnostics */
-#define TP_DIAGS(dev)	(QIC02_TAPE_DEBUG & TPQD_DIAGS)
-
-/* status codes returned by a WTS_RDSTAT call */
-struct tpstatus {	/* sizeof(short)==2), LSB first */
-	unsigned short	exs;	/* Drive exception flags */
-	unsigned short	dec;	/* data error count: nr of blocks rewritten/soft read errors */
-	unsigned short	urc;	/* underrun count: nr of times streaming was interrupted */
-};
-#define TPSTATSIZE	sizeof(struct tpstatus)
-
-
-/* defines for tpstatus.exs -- taken from 386BSD wt driver */
-#define	TP_POR		0x100	/* Power on or reset occurred */
-#define	TP_EOR		0x200	/* REServed for end of RECORDED media */
-#define	TP_PAR		0x400	/* REServed for bus parity */
-#define	TP_BOM		0x800	/* Beginning of media */
-#define	TP_MBD		0x1000	/* Marginal block detected */
-#define	TP_NDT		0x2000	/* No data detected */
-#define	TP_ILL		0x4000	/* Illegal command */
-#define	TP_ST1		0x8000	/* Status byte 1 flag */
-#define	TP_FIL		0x01	/* File mark detected */
-#define	TP_BNL		0x02	/* Bad block not located */
-#define	TP_UDA		0x04	/* Unrecoverable data error */
-#define	TP_EOM		0x08	/* End of media */
-#define	TP_WRP		0x10	/* Write protected cartridge */
-#define	TP_USL		0x20	/* Unselected drive */
-#define	TP_CNI		0x40	/* Cartridge not in place */
-#define	TP_ST0		0x80	/* Status byte 0 flag */
-
-#define REPORT_ERR0	(TP_CNI|TP_USL|TP_WRP|TP_EOM|TP_UDA|TP_BNL|TP_FIL)
-#define REPORT_ERR1	(TP_ILL|TP_NDT|TP_MBD|TP_PAR)
-
-
-/* exception numbers */
-#define EXC_UNKNOWN	0	/* (extra) Unknown exception code */
-#define EXC_NDRV	1	/* No drive */
-#define EXC_NCART	2	/* No cartridge */
-#define EXC_WP		3	/* Write protected */
-#define EXC_EOM		4	/* EOM */
-#define EXC_RWA		5	/* read/write abort */
-#define EXC_XBAD	6	/* read error, bad block transferred */
-#define EXC_XFILLER	7	/* read error, filler block transferred */
-#define EXC_NDT		8	/* read error, no data */
-#define EXC_NDTEOM	9	/* read error, no data & EOM */
-#define EXC_NDTBOM	10	/* read error, no data & BOM */
-#define EXC_FM		11	/* Read a filemark */
-#define EXC_ILL		12	/* Illegal command */
-#define EXC_POR		13	/* Power on/reset */
-#define EXC_MARGINAL	14	/* Marginal block detected */
-#define EXC_EOR		15	/* (extra, for SEEKEOD) End Of Recorded data reached */
-#define EXC_BOM		16	/* (extra) BOM reached */
-
-
-#define TAPE_NOTIFY_TIMEOUT	1000000
-
-/* internal function return codes */
-#define TE_OK	0		/* everything is fine */
-#define TE_EX	1		/* exception detected */
-#define TE_ERR	2		/* some error */
-#define TE_NS	3		/* can't read status */
-#define TE_TIM	4		/* timed out */
-#define TE_DEAD	5		/* tape drive doesn't respond */
-#define TE_END	6		/******** Archive hack *****/
-
-/* timeout timer values -- check these! */
-#define TIM_S	(4*HZ)		/* 4 seconds (normal cmds) */
-#define TIM_M	(30*HZ)		/* 30 seconds (write FM) */
-#define TIM_R	(8*60*HZ)	/* 8 minutes (retensioning) */
-#define TIM_F	(2*3600*HZ)	/* est. 1.2hr for full tape read/write+2 retens */
-
-#define TIMERON(t)	mod_timer(&tp_timer, jiffies + (t))
-#define TIMEROFF	del_timer_sync(&tp_timer);
-#define TIMERCONT	add_timer(&tp_timer);
-
-
-typedef char flag;
-#define NO	0	/* NO must be 0 */
-#define YES	1	/* YES must be != 0 */
-
-
-#ifdef TDEBUG
-# define TPQDEB(s)	s
-# define TPQPUTS(s)	tpqputs(s)
-#else
-# define TPQDEB(s)
-# define TPQPUTS(s)
-#endif
-
-
-/* NR_BLK_BUF is a `tuneable parameter'. If you're really low on
- * kernel space, you could decrease it to 1, or if you got a very
- * slow machine, you could increase it up to 127 blocks. Less kernel
- * buffer blocks result in more context-switching.
- */
-#define NR_BLK_BUF	20				    /* max 127 blocks */
-#define TAPE_BLKSIZE	512		  /* streamer tape block size (fixed) */
-#define TPQBUF_SIZE	(TAPE_BLKSIZE*NR_BLK_BUF)	       /* buffer size */
-
-
-#define BLOCKS_BEYOND_EW	2	/* nr of blocks after Early Warning hole */
-#define BOGUS_IRQ		32009
-
-
-/* This is internal data, filled in based on the ifc_type field given
- * by the user. Everex is mapped to Wangtek with a different
- * `dma_enable_value', if dmanr==3.
- */
-struct qic02_ccb {
-	long	ifc_type;
-
-	unsigned short	port_stat;	/* Status port address */
-	unsigned short	port_ctl;	/* Control port address */
-	unsigned short	port_cmd;	/* Command port address */
-	unsigned short	port_data;	/* Data port address */
-
-	/* status register bits */
-	unsigned short	stat_polarity;	/* invert status bits or not */
-	unsigned short	stat_ready;	/* drive ready */
-	unsigned short	stat_exception;	/* drive signals exception */
-	unsigned short	stat_mask;
-	unsigned short	stat_resetmask;
-	unsigned short	stat_resetval;
-
-	/* control register bits */
-	unsigned short	ctl_reset;	/* reset drive */
-	unsigned short	ctl_request;	/* latch command */
-	
-	/* This is used to change the DMA3 behaviour */
-	unsigned short	dma_enable_value;
-};
-
-#if MODULE
-static int qic02_tape_init(void);
-#else
-extern int qic02_tape_init(void);			  /* for mem.c */
-#endif
-
-
-
-#endif /* CONFIG_QIC02_TAPE */
-
-#endif /* _LINUX_TPQIC02_H */
-
diff -Nru a/include/linux/uinput.h b/include/linux/uinput.h
--- a/include/linux/uinput.h	2005-03-11 12:51:47 -08:00
+++ b/include/linux/uinput.h	2005-03-11 12:51:47 -08:00
@@ -22,6 +22,9 @@
  * Author: Aristeu Sergio Rozanski Filho <aris@cathedrallabs.org>
  * 
  * Changes/Revisions:
+ *	0.2	16/10/2004 (Micah Dowty <micah@navi.cx>)
+ *		- added force feedback support
+ *             - added UI_SET_PHYS
  *	0.1	20/06/2002
  *		- first public version
  */
@@ -29,10 +32,25 @@
 #define UINPUT_MINOR		223
 #define UINPUT_NAME		"uinput"
 #define UINPUT_BUFFER_SIZE	16
+#define UINPUT_NUM_REQUESTS	16
 
 /* state flags => bit index for {set|clear|test}_bit ops */
 #define UIST_CREATED		0
 
+struct uinput_request {
+	int			id;
+	int			code;	/* UI_FF_UPLOAD, UI_FF_ERASE */
+
+	int			retval;
+	wait_queue_head_t	waitq;
+	int			completed;
+
+	union {
+		int		effect_id;
+		struct ff_effect* effect;
+	} u;
+};
+
 struct uinput_device {
 	struct input_dev	*dev;
 	unsigned long		state;
@@ -41,13 +59,30 @@
 				head,
 				tail;
 	struct input_event	buff[UINPUT_BUFFER_SIZE];
+
+	struct uinput_request	*requests[UINPUT_NUM_REQUESTS];
+	wait_queue_head_t	requests_waitq;
+	struct semaphore	requests_sem;
 };
 #endif	/* __KERNEL__ */
 
+struct uinput_ff_upload {
+	int			request_id;
+	int			retval;
+	struct ff_effect	effect;
+};
+
+struct uinput_ff_erase {
+	int			request_id;
+	int			retval;
+	int			effect_id;
+};
+
 /* ioctl */
 #define UINPUT_IOCTL_BASE	'U'
 #define UI_DEV_CREATE		_IO(UINPUT_IOCTL_BASE, 1)
 #define UI_DEV_DESTROY		_IO(UINPUT_IOCTL_BASE, 2)
+
 #define UI_SET_EVBIT		_IOW(UINPUT_IOCTL_BASE, 100, int)
 #define UI_SET_KEYBIT		_IOW(UINPUT_IOCTL_BASE, 101, int)
 #define UI_SET_RELBIT		_IOW(UINPUT_IOCTL_BASE, 102, int)
@@ -56,6 +91,63 @@
 #define UI_SET_LEDBIT		_IOW(UINPUT_IOCTL_BASE, 105, int)
 #define UI_SET_SNDBIT		_IOW(UINPUT_IOCTL_BASE, 106, int)
 #define UI_SET_FFBIT		_IOW(UINPUT_IOCTL_BASE, 107, int)
+#define UI_SET_PHYS		_IOW(UINPUT_IOCTL_BASE, 108, char*)
+
+#define UI_BEGIN_FF_UPLOAD	_IOWR(UINPUT_IOCTL_BASE, 200, struct uinput_ff_upload)
+#define UI_END_FF_UPLOAD	_IOW(UINPUT_IOCTL_BASE, 201, struct uinput_ff_upload)
+#define UI_BEGIN_FF_ERASE	_IOWR(UINPUT_IOCTL_BASE, 202, struct uinput_ff_erase)
+#define UI_END_FF_ERASE		_IOW(UINPUT_IOCTL_BASE, 203, struct uinput_ff_erase)
+
+/* To write a force-feedback-capable driver, the upload_effect
+ * and erase_effect callbacks in input_dev must be implemented.
+ * The uinput driver will generate a fake input event when one of
+ * these callbacks are invoked. The userspace code then uses
+ * ioctls to retrieve additional parameters and send the return code.
+ * The callback blocks until this return code is sent.
+ *
+ * The described callback mechanism is only used if EV_FF is set.
+ * Otherwise, default implementations of upload_effect and erase_effect
+ * are used.
+ *
+ * To implement upload_effect():
+ *   1. Wait for an event with type==EV_UINPUT and code==UI_FF_UPLOAD.
+ *      A request ID will be given in 'value'.
+ *   2. Allocate a uinput_ff_upload struct, fill in request_id with
+ *      the 'value' from the EV_UINPUT event.
+ *   3. Issue a UI_BEGIN_FF_UPLOAD ioctl, giving it the
+ *      uinput_ff_upload struct. It will be filled in with the
+ *      ff_effect passed to upload_effect().
+ *   4. Perform the effect upload, and place the modified ff_effect
+ *      and a return code back into the uinput_ff_upload struct.
+ *   5. Issue a UI_END_FF_UPLOAD ioctl, also giving it the
+ *      uinput_ff_upload_effect struct. This will complete execution
+ *      of our upload_effect() handler.
+ *
+ * To implement erase_effect():
+ *   1. Wait for an event with type==EV_UINPUT and code==UI_FF_ERASE.
+ *      A request ID will be given in 'value'.
+ *   2. Allocate a uinput_ff_erase struct, fill in request_id with
+ *      the 'value' from the EV_UINPUT event.
+ *   3. Issue a UI_BEGIN_FF_ERASE ioctl, giving it the
+ *      uinput_ff_erase struct. It will be filled in with the
+ *      effect ID passed to erase_effect().
+ *   4. Perform the effect erasure, and place a return code back
+ *      into the uinput_ff_erase struct.
+ *      and a return code back into the uinput_ff_erase struct.
+ *   5. Issue a UI_END_FF_ERASE ioctl, also giving it the
+ *      uinput_ff_erase_effect struct. This will complete execution
+ *      of our erase_effect() handler.
+ */
+
+/* This is the new event type, used only by uinput.
+ * 'code' is UI_FF_UPLOAD or UI_FF_ERASE, and 'value'
+ * is the unique request ID. This number was picked
+ * arbitrarily, above EV_MAX (since the input system
+ * never sees it) but in the range of a 16-bit int.
+ */
+#define EV_UINPUT		0x0101
+#define UI_FF_UPLOAD		1
+#define UI_FF_ERASE		2
 
 #ifndef NBITS
 #define NBITS(x) ((((x)-1)/(sizeof(long)*8))+1)
diff -Nru a/include/linux/usb.h b/include/linux/usb.h
--- a/include/linux/usb.h	2005-03-11 12:51:42 -08:00
+++ b/include/linux/usb.h	2005-03-11 12:51:42 -08:00
@@ -70,6 +70,7 @@
 	 */
 	struct usb_host_endpoint *endpoint;
 
+	char *string;		/* iInterface string, if present */
 	unsigned char *extra;   /* Extra descriptors */
 	int extralen;
 };
@@ -189,6 +190,8 @@
 /**
  * struct usb_host_config - representation of a device's configuration
  * @desc: the device's configuration descriptor.
+ * @string: pointer to the cached version of the iConfiguration string, if
+ *	present for this configuration.
  * @interface: array of pointers to usb_interface structures, one for each
  *	interface in the configuration.  The number of interfaces is stored
  *	in desc.bNumInterfaces.  These pointers are valid only while the
@@ -225,6 +228,7 @@
 struct usb_host_config {
 	struct usb_config_descriptor	desc;
 
+	char *string;
 	/* the interfaces associated with this configuration,
 	 * stored in no particular order */
 	struct usb_interface *interface[USB_MAXINTERFACES];
@@ -285,6 +289,10 @@
 
 	struct class_device class_dev;	/* class device for this bus */
 	void (*release)(struct usb_bus *bus);	/* function to destroy this bus's memory */
+#if defined(CONFIG_USB_MON) || defined(CONFIG_USB_MON_MODULE)
+	struct mon_bus *mon_bus;	/* non-null when associated */
+	int monitored;			/* non-zero when monitored */
+#endif
 };
 #define	to_usb_bus(d) container_of(d, struct usb_bus, class_dev)
 
@@ -338,6 +346,9 @@
 	int have_langid;		/* whether string_langid is valid yet */
 	int string_langid;		/* language ID for strings */
 
+	char *product;
+	char *manufacturer;
+	char *serial;			/* static strings from the device */
 	struct list_head filelist;
 	struct dentry *usbfs_dentry;	/* usbfs dentry entry for the device */
 
@@ -986,13 +997,13 @@
 extern int usb_set_interface(struct usb_device *dev, int ifnum, int alternate);
 
 /*
- * timeouts, in seconds, used for sending/receiving control messages
+ * timeouts, in milliseconds, used for sending/receiving control messages
  * they typically complete within a few frames (msec) after they're issued
  * USB identifies 5 second timeouts, maybe more in a few cases, and a few
  * slow devices (like some MGE Ellipse UPSes) actually push that limit.
  */
-#define USB_CTRL_GET_TIMEOUT	5
-#define USB_CTRL_SET_TIMEOUT	5
+#define USB_CTRL_GET_TIMEOUT	5000
+#define USB_CTRL_SET_TIMEOUT	5000
 
 
 /**
diff -Nru a/include/linux/usb_cdc.h b/include/linux/usb_cdc.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/linux/usb_cdc.h	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,162 @@
+/*
+ * USB Communications Device Class (CDC) definitions
+ *
+ * CDC says how to talk to lots of different types of network adapters,
+ * notably ethernet adapters and various modems.  It's used mostly with
+ * firmware based USB peripherals.
+ */
+
+#define USB_CDC_SUBCLASS_ACM			2
+#define USB_CDC_SUBCLASS_ETHERNET		6
+
+#define USB_CDC_PROTO_NONE			0
+
+#define USB_CDC_ACM_PROTO_AT_V25TER		1
+#define USB_CDC_ACM_PROTO_AT_PCCA101		2
+#define USB_CDC_ACM_PROTO_AT_PCCA101_WAKE	3
+#define USB_CDC_ACM_PROTO_AT_GSM		4
+#define USB_CDC_ACM_PROTO_AT_3G			5
+#define USB_CDC_ACM_PROTO_AT_CDMA		6
+#define USB_CDC_ACM_PROTO_VENDOR		0xff
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * Class-Specific descriptors ... there are a couple dozen of them
+ */
+
+#define USB_CDC_HEADER_TYPE		0x00		/* header_desc */
+#define USB_CDC_CALL_MANAGEMENT_TYPE	0x01		/* call_mgmt_descriptor */
+#define USB_CDC_ACM_TYPE		0x02		/* acm_descriptor */
+#define USB_CDC_UNION_TYPE		0x06		/* union_desc */
+#define USB_CDC_COUNTRY_TYPE		0x07
+#define USB_CDC_ETHERNET_TYPE		0x0f		/* ether_desc */
+
+/* "Header Functional Descriptor" from CDC spec  5.2.3.1 */
+struct usb_cdc_header_desc {
+	__u8	bLength;
+	__u8	bDescriptorType;
+	__u8	bDescriptorSubType;
+
+	__le16	bcdCDC;
+} __attribute__ ((packed));
+
+/* "Call Management Descriptor" from CDC spec  5.2.3.2 */
+struct usb_cdc_call_mgmt_descriptor {
+	__u8	bLength;
+	__u8	bDescriptorType;
+	__u8	bDescriptorSubType;
+
+	__u8	bmCapabilities;
+#define USB_CDC_CALL_MGMT_CAP_CALL_MGMT		0x01
+#define USB_CDC_CALL_MGMT_CAP_DATA_INTF		0x02
+
+	__u8	bDataInterface;
+} __attribute__ ((packed));
+
+/* "Abstract Control Management Descriptor" from CDC spec  5.2.3.3 */
+struct usb_cdc_acm_descriptor {
+	__u8	bLength;
+	__u8	bDescriptorType;
+	__u8	bDescriptorSubType;
+
+	__u8	bmCapabilities;
+} __attribute__ ((packed));
+
+/* "Union Functional Descriptor" from CDC spec 5.2.3.8 */
+struct usb_cdc_union_desc {
+	__u8	bLength;
+	__u8	bDescriptorType;
+	__u8	bDescriptorSubType;
+
+	__u8	bMasterInterface0;
+	__u8	bSlaveInterface0;
+	/* ... and there could be other slave interfaces */
+} __attribute__ ((packed));
+
+/* "Ethernet Networking Functional Descriptor" from CDC spec 5.2.3.16 */
+struct usb_cdc_ether_desc {
+	__u8	bLength;
+	__u8	bDescriptorType;
+	__u8	bDescriptorSubType;
+
+	__u8	iMACAddress;
+	__le32	bmEthernetStatistics;
+	__le16	wMaxSegmentSize;
+	__le16	wNumberMCFilters;
+	__u8	bNumberPowerFilters;
+} __attribute__ ((packed));
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * Class-Specific Control Requests (6.2)
+ *
+ * section 3.6.2.1 table 4 has the ACM profile, for modems.
+ * section 3.8.2 table 10 has the ethernet profile.
+ *
+ * Microsoft's RNDIS stack for Ethernet is a vendor-specific CDC ACM variant,
+ * heavily dependent on the encapsulated (proprietary) command mechanism.
+ */
+
+#define USB_CDC_SEND_ENCAPSULATED_COMMAND	0x00
+#define USB_CDC_GET_ENCAPSULATED_RESPONSE	0x01
+#define USB_CDC_REQ_SET_LINE_CODING		0x20
+#define USB_CDC_REQ_GET_LINE_CODING		0x21
+#define USB_CDC_REQ_SET_CONTROL_LINE_STATE	0x22
+#define USB_CDC_REQ_SEND_BREAK			0x23
+#define USB_CDC_SET_ETHERNET_MULTICAST_FILTERS	0x40
+#define USB_CDC_SET_ETHERNET_PM_PATTERN_FILTER	0x41
+#define USB_CDC_GET_ETHERNET_PM_PATTERN_FILTER	0x42
+#define USB_CDC_SET_ETHERNET_PACKET_FILTER	0x43
+#define USB_CDC_GET_ETHERNET_STATISTIC		0x44
+
+/* Line Coding Structure from CDC spec 6.2.13 */
+struct usb_cdc_line_coding {
+	__le32	dwDTERate;
+	__u8	bCharFormat;
+#define USB_CDC_1_STOP_BITS			0
+#define USB_CDC_1_5_STOP_BITS			1
+#define USB_CDC_2_STOP_BITS			2
+
+	__u8	bParityType;
+#define USB_CDC_NO_PARITY			0
+#define USB_CDC_ODD_PARITY			1
+#define USB_CDC_EVEN_PARITY			2
+#define USB_CDC_MARK_PARITY			3
+#define USB_CDC_SPACE_PARITY			4
+
+	__u8	bDataBits;
+} __attribute__ ((packed));
+
+/* table 62; bits in multicast filter */
+#define	USB_CDC_PACKET_TYPE_PROMISCUOUS		(1 << 0)
+#define	USB_CDC_PACKET_TYPE_ALL_MULTICAST	(1 << 1) /* no filter */
+#define	USB_CDC_PACKET_TYPE_DIRECTED		(1 << 2)
+#define	USB_CDC_PACKET_TYPE_BROADCAST		(1 << 3)
+#define	USB_CDC_PACKET_TYPE_MULTICAST		(1 << 4) /* filtered */
+
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * Class-Specific Notifications (6.3) sent by interrupt transfers
+ *
+ * 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
+ * RNDIS also defines its own bit-incompatible notifications
+ */
+
+#define USB_CDC_NOTIFY_NETWORK_CONNECTION	0x00
+#define USB_CDC_NOTIFY_RESPONSE_AVAILABLE	0x01
+#define USB_CDC_NOTIFY_SERIAL_STATE		0x20
+#define USB_CDC_NOTIFY_SPEED_CHANGE		0x2a
+
+struct usb_cdc_notification {
+	__u8	bmRequestType;
+	__u8	bNotificationType;
+	__le16	wValue;
+	__le16	wIndex;
+	__le16	wLength;
+} __attribute__ ((packed));
+
diff -Nru a/include/linux/usbdevice_fs.h b/include/linux/usbdevice_fs.h
--- a/include/linux/usbdevice_fs.h	2005-03-11 12:51:41 -08:00
+++ b/include/linux/usbdevice_fs.h	2005-03-11 12:51:41 -08:00
@@ -32,6 +32,7 @@
 #define _LINUX_USBDEVICE_FS_H
 
 #include <linux/types.h>
+#include <linux/compat.h>
 
 /* --------------------------------------------------------------------- */
 
@@ -123,6 +124,24 @@
 	char port [127];	/* e.g. port 3 connects to device 27 */
 };
 
+#ifdef CONFIG_COMPAT
+struct usbdevfs_urb32 {
+	unsigned char type;
+	unsigned char endpoint;
+	compat_int_t status;
+	compat_uint_t flags;
+	compat_caddr_t buffer;
+	compat_int_t buffer_length;
+	compat_int_t actual_length;
+	compat_int_t start_frame;
+	compat_int_t number_of_packets;
+	compat_int_t error_count;
+	compat_uint_t signr;
+	compat_caddr_t usercontext; /* unused */
+	struct usbdevfs_iso_packet_desc iso_frame_desc[0];
+};
+#endif
+
 #define USBDEVFS_CONTROL           _IOWR('U', 0, struct usbdevfs_ctrltransfer)
 #define USBDEVFS_BULK              _IOWR('U', 2, struct usbdevfs_bulktransfer)
 #define USBDEVFS_RESETEP           _IOR('U', 3, unsigned int)
@@ -130,9 +149,12 @@
 #define USBDEVFS_SETCONFIGURATION  _IOR('U', 5, unsigned int)
 #define USBDEVFS_GETDRIVER         _IOW('U', 8, struct usbdevfs_getdriver)
 #define USBDEVFS_SUBMITURB         _IOR('U', 10, struct usbdevfs_urb)
+#define USBDEVFS_SUBMITURB32       _IOR('U', 10, struct usbdevfs_urb32)
 #define USBDEVFS_DISCARDURB        _IO('U', 11)
 #define USBDEVFS_REAPURB           _IOW('U', 12, void *)
+#define USBDEVFS_REAPURB32         _IOW('U', 12, u32)
 #define USBDEVFS_REAPURBNDELAY     _IOW('U', 13, void *)
+#define USBDEVFS_REAPURBNDELAY32   _IOW('U', 13, u32)
 #define USBDEVFS_DISCSIGNAL        _IOR('U', 14, struct usbdevfs_disconnectsignal)
 #define USBDEVFS_CLAIMINTERFACE    _IOR('U', 15, unsigned int)
 #define USBDEVFS_RELEASEINTERFACE  _IOR('U', 16, unsigned int)
@@ -143,5 +165,4 @@
 #define USBDEVFS_CLEAR_HALT        _IOR('U', 21, unsigned int)
 #define USBDEVFS_DISCONNECT        _IO('U', 22)
 #define USBDEVFS_CONNECT           _IO('U', 23)
-
 #endif /* _LINUX_USBDEVICE_FS_H */
diff -Nru a/include/linux/vt_kern.h b/include/linux/vt_kern.h
--- a/include/linux/vt_kern.h	2005-03-11 12:51:51 -08:00
+++ b/include/linux/vt_kern.h	2005-03-11 12:51:51 -08:00
@@ -25,15 +25,6 @@
 #define BROKEN_GRAPHICS_PROGRAMS 1
 #endif
 
-extern struct vt_struct {
-	int vc_num;				/* The console number */
-	unsigned char	vc_mode;		/* KD_TEXT, ... */
-	struct vt_mode	vt_mode;
-	int		vt_pid;
-	int		vt_newvt;
-	wait_queue_head_t paste_wait;
-} *vt_cons[MAX_NR_CONSOLES];
-
 extern void kd_mksound(unsigned int hz, unsigned int ticks);
 extern int kbd_rate(struct kbd_repeat *rep);
 
@@ -41,25 +32,25 @@
 
 int vc_allocate(unsigned int console);
 int vc_cons_allocated(unsigned int console);
-int vc_resize(int currcons, unsigned int cols, unsigned int lines);
+int vc_resize(struct vc_data *vc, unsigned int cols, unsigned int lines);
 void vc_disallocate(unsigned int console);
-void reset_palette(int currcons);
-void set_palette(int currcons);
+void reset_palette(struct vc_data *vc);
+void set_palette(struct vc_data *vc);
 void do_blank_screen(int entering_gfx);
 void do_unblank_screen(int leaving_gfx);
 void unblank_screen(void);
 void poke_blanked_console(void);
-int con_font_op(int currcons, struct console_font_op *op);
-int con_font_set(int currcons, struct console_font_op *op);
-int con_font_get(int currcons, struct console_font_op *op);
-int con_font_default(int currcons, struct console_font_op *op);
-int con_font_copy(int currcons, struct console_font_op *op);
+int con_font_op(struct vc_data *vc, struct console_font_op *op);
+int con_font_set(struct vc_data *vc, struct console_font_op *op);
+int con_font_get(struct vc_data *vc, struct console_font_op *op);
+int con_font_default(struct vc_data *vc, struct console_font_op *op);
+int con_font_copy(struct vc_data *vc, struct console_font_op *op);
 int con_set_cmap(unsigned char __user *cmap);
 int con_get_cmap(unsigned char __user *cmap);
-void scrollback(int);
-void scrollfront(int);
-void update_region(int currcons, unsigned long start, int count);
-void redraw_screen(int new_console, int is_switch);
+void scrollback(struct vc_data *vc, int lines);
+void scrollfront(struct vc_data *vc, int lines);
+void update_region(struct vc_data *vc, unsigned long start, int count);
+void redraw_screen(struct vc_data *vc, int is_switch);
 #define update_screen(x) redraw_screen(x, 0)
 #define switch_screen(x) redraw_screen(x, 1)
 
@@ -75,25 +66,26 @@
 int con_get_trans_old(unsigned char __user * table);
 int con_set_trans_new(unsigned short __user * table);
 int con_get_trans_new(unsigned short __user * table);
-int con_clear_unimap(int currcons, struct unimapinit *ui);
-int con_set_unimap(int currcons, ushort ct, struct unipair __user *list);
-int con_get_unimap(int currcons, ushort ct, ushort __user *uct, struct unipair __user *list);
-int con_set_default_unimap(int currcons);
-void con_free_unimap(int currcons);
-void con_protect_unimap(int currcons, int rdonly);
-int con_copy_unimap(int dstcons, int srccons);
+int con_clear_unimap(struct vc_data *vc, struct unimapinit *ui);
+int con_set_unimap(struct vc_data *vc, ushort ct, struct unipair __user *list);
+int con_get_unimap(struct vc_data *vc, ushort ct, ushort __user *uct, struct unipair __user *list);
+int con_set_default_unimap(struct vc_data *vc);
+void con_free_unimap(struct vc_data *vc);
+void con_protect_unimap(struct vc_data *vc, int rdonly);
+int con_copy_unimap(struct vc_data *dst_vc, struct vc_data *src_vc);
 
 /* vt.c */
-void complete_change_console(unsigned int new_console);
+void complete_change_console(struct vc_data *vc);
 int vt_waitactive(int vt);
-void change_console(unsigned int);
-void reset_vc(unsigned int new_console);
+void change_console(struct vc_data *new_vc);
+void reset_vc(struct vc_data *vc);
 
 /*
  * vc_screen.c shares this temporary buffer with the console write code so that
  * we can easily avoid touching user space while holding the console spinlock.
  */
-#define CON_BUF_SIZE	PAGE_SIZE
+
+#define CON_BUF_SIZE (CONFIG_BASE_SMALL ? 256 : PAGE_SIZE)
 extern char con_buf[CON_BUF_SIZE];
 extern struct semaphore con_buf_sem;
 
diff -Nru a/include/linux/workqueue.h b/include/linux/workqueue.h
--- a/include/linux/workqueue.h	2005-03-11 12:51:48 -08:00
+++ b/include/linux/workqueue.h	2005-03-11 12:51:48 -08:00
@@ -70,6 +70,7 @@
 extern int keventd_up(void);
 
 extern void init_workqueues(void);
+void cancel_rearming_delayed_work(struct work_struct *work);
 
 /*
  * Kill off a pending schedule_delayed_work().  Note that the work callback
diff -Nru a/include/linux/writeback.h b/include/linux/writeback.h
--- a/include/linux/writeback.h	2005-03-11 12:51:41 -08:00
+++ b/include/linux/writeback.h	2005-03-11 12:51:41 -08:00
@@ -86,6 +86,7 @@
 int wakeup_bdflush(long nr_pages);
 void laptop_io_completion(void);
 void laptop_sync_completion(void);
+void throttle_vm_writeout(void);
 
 /* These are exported to sysctl. */
 extern int dirty_background_ratio;
diff -Nru a/include/media/saa7146.h b/include/media/saa7146.h
--- a/include/media/saa7146.h	2005-03-11 12:51:41 -08:00
+++ b/include/media/saa7146.h	2005-03-11 12:51:41 -08:00
@@ -157,7 +157,7 @@
 
 /* from saa7146_i2c.c */
 int saa7146_i2c_adapter_prepare(struct saa7146_dev *dev, struct i2c_adapter *i2c_adapter, u32 bitrate);
-int saa7146_i2c_transfer(struct saa7146_dev *saa, const struct i2c_msg msgs[], int num,  int retries);
+int saa7146_i2c_transfer(struct saa7146_dev *saa, const struct i2c_msg *msgs, int num,  int retries);
 
 /* from saa7146_core.c */
 extern struct list_head saa7146_devices;
diff -Nru a/include/media/tuner.h b/include/media/tuner.h
--- a/include/media/tuner.h	2005-03-11 12:51:47 -08:00
+++ b/include/media/tuner.h	2005-03-11 12:51:47 -08:00
@@ -29,55 +29,70 @@
 #define TUNER_PHILIPS_PAL_I 1
 #define TUNER_PHILIPS_NTSC  2
 #define TUNER_PHILIPS_SECAM 3		/* you must actively select B/G, L, L` */
+
 #define TUNER_ABSENT        4
 #define TUNER_PHILIPS_PAL   5
 #define TUNER_TEMIC_NTSC    6        /* 4032 FY5 (3X 7004, 9498, 9789)  */
 #define TUNER_TEMIC_PAL_I   7        /* 4062 FY5 (3X 8501, 9957)        */
+
 #define TUNER_TEMIC_4036FY5_NTSC 8   /* 4036 FY5 (3X 1223, 1981, 7686)  */
 #define TUNER_ALPS_TSBH1_NTSC 	 9
 #define TUNER_ALPS_TSBE1_PAL 	10
 #define TUNER_ALPS_TSBB5_PAL_I 	11
+
 #define TUNER_ALPS_TSBE5_PAL 	12
 #define TUNER_ALPS_TSBC5_PAL 	13
 #define TUNER_TEMIC_4006FH5_PAL	14   /* 4006 FH5 (3X 9500, 9501, 7291)     */
 #define TUNER_ALPS_TSHC6_NTSC 	15
+
 #define TUNER_TEMIC_PAL_DK	16   /* 4016 FY5 (3X 1392, 1393)     */
 #define TUNER_PHILIPS_NTSC_M	17
 #define TUNER_TEMIC_4066FY5_PAL_I       18  /* 4066 FY5 (3X 7032, 7035) */
 #define TUNER_TEMIC_4006FN5_MULTI_PAL   19  /* B/G, I and D/K autodetected (3X 7595, 7606, 7657)*/
+
 #define TUNER_TEMIC_4009FR5_PAL         20  /* incl. FM radio (3X 7607, 7488, 7711)*/
 #define TUNER_TEMIC_4039FR5_NTSC        21  /* incl. FM radio (3X 7246, 7578, 7732)*/
 #define TUNER_TEMIC_4046FM5             22  /* you must actively select B/G, D/K, I, L, L` !  (3X 7804, 7806, 8103, 8104)*/
 #define TUNER_PHILIPS_PAL_DK		23
+
 #define TUNER_PHILIPS_FQ1216ME		24  /* you must actively select B/G/D/K, I, L, L` */
 #define TUNER_LG_PAL_I_FM	25
 #define TUNER_LG_PAL_I		26
 #define TUNER_LG_NTSC_FM	27
+
 #define TUNER_LG_PAL_FM		28
 #define TUNER_LG_PAL		29
 #define TUNER_TEMIC_4009FN5_MULTI_PAL_FM	30  /* B/G, I and D/K autodetected (3X 8155, 8160, 8163)*/
 #define TUNER_SHARP_2U5JF5540_NTSC  31
+
 #define TUNER_Samsung_PAL_TCPM9091PD27 32
 #define TUNER_MT2032 33
 #define TUNER_TEMIC_4106FH5 	34	/* 4106 FH5 (3X 7808, 7865)*/
 #define TUNER_TEMIC_4012FY5	35	/* 4012 FY5 (3X 0971, 1099)*/
+
 #define TUNER_TEMIC_4136FY5	36	/* 4136 FY5 (3X 7708, 7746)*/
 #define TUNER_LG_PAL_NEW_TAPC   37
 #define TUNER_PHILIPS_FM1216ME_MK3  38
 #define TUNER_LG_NTSC_NEW_TAPC   39
+
 #define TUNER_HITACHI_NTSC       40
 #define TUNER_PHILIPS_PAL_MK     41
 #define TUNER_PHILIPS_ATSC       42
 #define TUNER_PHILIPS_FM1236_MK3 43
+
 #define TUNER_PHILIPS_4IN1       44	/* ATI TV Wonder Pro - Conexant */
 /* Microtune mergeged with Temic 12/31/1999 partially financed by Alps - these may be similar to Temic */
 #define TUNER_MICROTUNE_4049FM5  45
 #define TUNER_LG_NTSC_TAPE       47
+
 #define TUNER_TNF_8831BGFF       48
 #define TUNER_MICROTUNE_4042FI5  49	/* FusionHDTV 3 Gold - 4042 FI5 (3X 8147) */
 #define TUNER_TCL_2002N          50
 #define TUNER_PHILIPS_FM1256_IH3   51
+
 #define TUNER_THOMSON_DTT7610    52
+#define TUNER_PHILIPS_FQ1286     53
+#define TUNER_PHILIPS_TDA8290    54
 
 #define NOTUNER 0
 #define PAL     1	/* PAL_BG */
@@ -102,10 +117,6 @@
 
 #define TUNER_SET_TYPE               _IOW('t',1,int)    /* set tuner type */
 #define TUNER_SET_TVFREQ             _IOW('t',2,int)    /* set tv freq */
-#if 0 /* obsolete */
-# define TUNER_SET_RADIOFREQ         _IOW('t',3,int)    /* set radio freq */
-# define TUNER_SET_MODE              _IOW('t',4,int)    /* set tuner mode */
-#endif
 
 #define  TDA9887_SET_CONFIG          _IOW('t',5,int)
 /* tv card specific */
@@ -123,4 +134,62 @@
 # define TDA9887_DEEMPHASIS_75       (3<<16)
 # define TDA9887_AUTOMUTE            (1<<18)
 
+#ifdef __KERNEL__
+
+#define I2C_ADDR_TDA8290        0x4b
+#define I2C_ADDR_TDA8275        0x61
+
+struct tuner {
+	/* device */
+	struct i2c_client i2c;
+
+	/* state + config */
+	unsigned int initialized;
+	unsigned int type;            /* chip type */
+	unsigned int freq;            /* keep track of the current settings */
+	v4l2_std_id  std;
+	int          using_v4l2;
+
+	enum v4l2_tuner_type mode;
+	unsigned int input;
+
+	/* used by MT2032 */
+	unsigned int xogc;
+	unsigned int radio_if2;
+
+	/* used by tda8290 */
+	unsigned char i2c_easy_mode[2];
+	unsigned char i2c_set_freq[8];
+
+	/* function ptrs */
+	void (*tv_freq)(struct i2c_client *c, unsigned int freq);
+	void (*radio_freq)(struct i2c_client *c, unsigned int freq);
+	int  (*has_signal)(struct i2c_client *c);
+	int  (*is_stereo)(struct i2c_client *c);
+};
+
+extern unsigned int tuner_debug;
+extern unsigned const int tuner_count;
+
+extern int microtune_init(struct i2c_client *c);
+extern int tda8290_init(struct i2c_client *c);
+extern int default_tuner_init(struct i2c_client *c);
+
+#define tuner_warn(fmt, arg...) \
+	dev_printk(KERN_WARNING , &t->i2c.dev , fmt , ## arg)
+#define tuner_info(fmt, arg...) \
+	dev_printk(KERN_INFO , &t->i2c.dev , fmt , ## arg)
+#define tuner_dbg(fmt, arg...) \
+	if (tuner_debug) dev_printk(KERN_DEBUG , &t->i2c.dev , fmt , ## arg)
+
+#endif /* __KERNEL__ */
+
 #endif
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff -Nru a/include/net/addrconf.h b/include/net/addrconf.h
--- a/include/net/addrconf.h	2005-03-11 12:51:50 -08:00
+++ b/include/net/addrconf.h	2005-03-11 12:51:50 -08:00
@@ -49,7 +49,7 @@
 
 #define IN6_ADDR_HSIZE		16
 
-extern void			addrconf_init(void);
+extern int			addrconf_init(void);
 extern void			addrconf_cleanup(void);
 
 extern int			addrconf_add_ifaddr(void __user *arg);
@@ -101,6 +101,8 @@
 extern int ipv6_is_mld(struct sk_buff *skb, int nexthdr);
 
 extern void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len);
+
+extern int ipv6_get_hoplimit(struct net_device *dev);
 
 /*
  *	anycast prototypes (anycast.c)
diff -Nru a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
--- a/include/net/bluetooth/hci_core.h	2005-03-11 12:51:46 -08:00
+++ b/include/net/bluetooth/hci_core.h	2005-03-11 12:51:46 -08:00
@@ -217,7 +217,8 @@
 /* ----- HCI Connections ----- */
 enum {
 	HCI_CONN_AUTH_PEND,
-	HCI_CONN_ENCRYPT_PEND
+	HCI_CONN_ENCRYPT_PEND,
+	HCI_CONN_RSWITCH_PEND
 };
 
 static inline void hci_conn_hash_init(struct hci_dev *hdev)
@@ -290,6 +291,7 @@
 int hci_conn_auth(struct hci_conn *conn);
 int hci_conn_encrypt(struct hci_conn *conn);
 int hci_conn_change_link_key(struct hci_conn *conn);
+int hci_conn_switch_role(struct hci_conn *conn, uint8_t role);
 
 static inline void hci_conn_set_timer(struct hci_conn *conn, unsigned long timeout)
 {
@@ -515,6 +517,8 @@
 
 	void (*auth_cfm)	(struct hci_conn *conn, __u8 status);
 	void (*encrypt_cfm)	(struct hci_conn *conn, __u8 status, __u8 encrypt);
+	void (*key_change_cfm)	(struct hci_conn *conn, __u8 status);
+	void (*role_switch_cfm)	(struct hci_conn *conn, __u8 status, __u8 role);
 };
 
 static inline void hci_auth_cfm(struct hci_conn *conn, __u8 status)
@@ -543,6 +547,32 @@
 		struct hci_cb *cb = list_entry(p, struct hci_cb, list);
 		if (cb->encrypt_cfm)
 			cb->encrypt_cfm(conn, status, encrypt);
+	}
+	read_unlock_bh(&hci_cb_list_lock);
+}
+
+static inline void hci_key_change_cfm(struct hci_conn *conn, __u8 status)
+{
+	struct list_head *p;
+
+	read_lock_bh(&hci_cb_list_lock);
+	list_for_each(p, &hci_cb_list) {
+		struct hci_cb *cb = list_entry(p, struct hci_cb, list);
+		if (cb->key_change_cfm)
+			cb->key_change_cfm(conn, status);
+	}
+	read_unlock_bh(&hci_cb_list_lock);
+}
+
+static inline void hci_role_switch_cfm(struct hci_conn *conn, __u8 status, __u8 role)
+{
+	struct list_head *p;
+
+	read_lock_bh(&hci_cb_list_lock);
+	list_for_each(p, &hci_cb_list) {
+		struct hci_cb *cb = list_entry(p, struct hci_cb, list);
+		if (cb->role_switch_cfm)
+			cb->role_switch_cfm(conn, status, role);
 	}
 	read_unlock_bh(&hci_cb_list_lock);
 }
diff -Nru a/include/net/dn.h b/include/net/dn.h
--- a/include/net/dn.h	2005-03-11 12:51:47 -08:00
+++ b/include/net/dn.h	2005-03-11 12:51:47 -08:00
@@ -2,6 +2,7 @@
 #define _NET_DN_H
 
 #include <linux/dn.h>
+#include <net/sock.h>
 #include <asm/byteorder.h>
 
 typedef unsigned short dn_address;
@@ -133,7 +134,10 @@
 
 };
 
-#define DN_SK(__sk) ((struct dn_scp *)(__sk)->sk_protinfo)
+static inline struct dn_scp *DN_SK(struct sock *sk)
+{
+	return (struct dn_scp *)(sk + 1);
+}
 
 /*
  * src,dst : Source and Destination DECnet addresses
diff -Nru a/include/net/dst.h b/include/net/dst.h
--- a/include/net/dst.h	2005-03-11 12:51:52 -08:00
+++ b/include/net/dst.h	2005-03-11 12:51:52 -08:00
@@ -124,6 +124,25 @@
 	return mtu;
 }
 
+static inline u32 dst_mtu(const struct dst_entry *dst)
+{
+	u32 mtu = dst_metric(dst, RTAX_MTU);
+	/*
+	 * Alexey put it here, so ask him about it :)
+	 */
+	barrier();
+	return mtu;
+}
+
+static inline u32
+dst_allfrag(const struct dst_entry *dst)
+{
+	int ret = dst_path_metric(dst, RTAX_FEATURES) & RTAX_FEATURE_ALLFRAG;
+	/* Yes, _exactly_. This is paranoia. */
+	barrier();
+	return ret;
+}
+
 static inline int
 dst_metric_locked(struct dst_entry *dst, int metric)
 {
@@ -247,6 +266,13 @@
 		if (unlikely(err != NET_XMIT_BYPASS))
 			return err;
 	}
+}
+
+static inline struct dst_entry *dst_check(struct dst_entry *dst, u32 cookie)
+{
+	if (dst->obsolete)
+		dst = dst->ops->check(dst, cookie);
+	return dst;
 }
 
 extern void		dst_init(void);
diff -Nru a/include/net/ipv6.h b/include/net/ipv6.h
--- a/include/net/ipv6.h	2005-03-11 12:51:50 -08:00
+++ b/include/net/ipv6.h	2005-03-11 12:51:50 -08:00
@@ -305,6 +305,32 @@
 		a1->s6_addr32[3] == a2->s6_addr32[3]);
 }
 
+static inline int __ipv6_prefix_equal(const u32 *a1, const u32 *a2,
+				      unsigned int prefixlen)
+{
+	unsigned pdw, pbi;
+
+	/* check complete u32 in prefix */
+	pdw = prefixlen >> 5;
+	if (pdw && memcmp(a1, a2, pdw << 2))
+		return 0;
+
+	/* check incomplete u32 in prefix */
+	pbi = prefixlen & 0x1f;
+	if (pbi && ((a1[pdw] ^ a2[pdw]) & htonl((0xffffffff) << (32 - pbi))))
+		return 0;
+
+	return 1;
+}
+
+static inline int ipv6_prefix_equal(const struct in6_addr *a1,
+				    const struct in6_addr *a2,
+				    unsigned int prefixlen)
+{
+	return __ipv6_prefix_equal(a1->s6_addr32, a2->s6_addr32,
+				   prefixlen);
+}
+
 static inline int ipv6_addr_any(const struct in6_addr *a)
 {
 	return ((a->s6_addr32[0] | a->s6_addr32[1] | 
diff -Nru a/include/net/irda/af_irda.h b/include/net/irda/af_irda.h
--- a/include/net/irda/af_irda.h	2005-03-11 12:51:51 -08:00
+++ b/include/net/irda/af_irda.h	2005-03-11 12:51:51 -08:00
@@ -33,9 +33,12 @@
 #include <net/irda/irlmp.h>		/* struct lsap_cb */
 #include <net/irda/irttp.h>		/* struct tsap_cb */
 #include <net/irda/discovery.h>		/* struct discovery_t */
+#include <net/sock.h>
 
 /* IrDA Socket */
 struct irda_sock {
+	/* struct sock has to be the first member of irda_sock */
+	struct sock sk;
 	__u32 saddr;          /* my local address */
 	__u32 daddr;          /* peer address */
 
@@ -69,7 +72,6 @@
 
 	int errno;            /* status of the IAS query */
 
-	struct sock *sk;
 	wait_queue_head_t query_wait;	/* Wait for the answer to a query */
 	struct timer_list watchdog;	/* Timeout for discovery */
 
@@ -77,6 +79,9 @@
 	LOCAL_FLOW rx_flow;
 };
 
-#define irda_sk(__sk) ((struct irda_sock *)(__sk)->sk_protinfo)
+static inline struct irda_sock *irda_sk(struct sock *sk)
+{
+	return (struct irda_sock *)sk;
+}
 
 #endif /* AF_IRDA_H */
diff -Nru a/include/net/llc_conn.h b/include/net/llc_conn.h
--- a/include/net/llc_conn.h	2005-03-11 12:51:51 -08:00
+++ b/include/net/llc_conn.h	2005-03-11 12:51:51 -08:00
@@ -13,6 +13,7 @@
  */
 #include <linux/timer.h>
 #include <net/llc_if.h>
+#include <net/sock.h>
 #include <linux/llc.h>
 
 #define LLC_EVENT                1
@@ -28,8 +29,9 @@
 	u16		  expire;	/* timer expire time */
 };
 
-struct llc_opt {
-	struct sock	    *sk;		/* sock that has this llc_opt */
+struct llc_sock {
+	/* struct sock must be the first member of llc_sock */
+	struct sock	    sk;
 	struct sockaddr_llc addr;		/* address sock is bound to */
 	u8		    state;		/* state of connection */
 	struct llc_sap	    *sap;		/* pointer to parent SAP */
@@ -75,7 +77,10 @@
 					      Used for resending FRMR */
 };
 
-#define llc_sk(__sk) ((struct llc_opt *)(__sk)->sk_protinfo)
+static inline struct llc_sock *llc_sk(const struct sock *sk)
+{
+	return (struct llc_sock *)sk;
+}
 
 static __inline__ void llc_set_backlog_type(struct sk_buff *skb, char type)
 {
diff -Nru a/include/net/ndisc.h b/include/net/ndisc.h
--- a/include/net/ndisc.h	2005-03-11 12:51:50 -08:00
+++ b/include/net/ndisc.h	2005-03-11 12:51:50 -08:00
@@ -15,11 +15,15 @@
  *	ndisc options
  */
 
-#define ND_OPT_SOURCE_LL_ADDR		1
-#define ND_OPT_TARGET_LL_ADDR		2
-#define ND_OPT_PREFIX_INFO		3
-#define ND_OPT_REDIRECT_HDR		4
-#define ND_OPT_MTU			5
+enum {
+	__ND_OPT_PREFIX_INFO_END = 0,
+	ND_OPT_SOURCE_LL_ADDR = 1,	/* RFC2461 */
+	ND_OPT_TARGET_LL_ADDR = 2,	/* RFC2461 */
+	ND_OPT_PREFIX_INFO = 3,		/* RFC2461 */
+	ND_OPT_REDIRECT_HDR = 4,	/* RFC2461 */
+	ND_OPT_MTU = 5,			/* RFC2461 */
+	__ND_OPT_MAX
+};
 
 #define MAX_RTR_SOLICITATION_DELAY	HZ
 
diff -Nru a/include/net/neighbour.h b/include/net/neighbour.h
--- a/include/net/neighbour.h	2005-03-11 12:51:51 -08:00
+++ b/include/net/neighbour.h	2005-03-11 12:51:51 -08:00
@@ -274,7 +274,8 @@
 						      struct neigh_parms *p,
 						      int p_id, int pdev_id,
 						      char *p_name,
-						      proc_handler *proc_handler);
+						      proc_handler *proc_handler,
+						      ctl_handler *strategy);
 extern void			neigh_sysctl_unregister(struct neigh_parms *p);
 
 static inline void __neigh_parms_put(struct neigh_parms *parms)
diff -Nru a/include/net/netrom.h b/include/net/netrom.h
--- a/include/net/netrom.h	2005-03-11 12:51:46 -08:00
+++ b/include/net/netrom.h	2005-03-11 12:51:46 -08:00
@@ -221,6 +221,7 @@
 extern void nr_disconnect(struct sock *, int);
 
 /* nr_timer.c */
+extern void nr_init_timers(struct sock *sk);
 extern void nr_start_heartbeat(struct sock *);
 extern void nr_start_t1timer(struct sock *);
 extern void nr_start_t2timer(struct sock *);
diff -Nru a/include/net/pkt_cls.h b/include/net/pkt_cls.h
--- a/include/net/pkt_cls.h	2005-03-11 12:51:47 -08:00
+++ b/include/net/pkt_cls.h	2005-03-11 12:51:47 -08:00
@@ -148,6 +148,198 @@
 extern int tcf_exts_dump_stats(struct sk_buff *skb, struct tcf_exts *exts,
 	                       struct tcf_ext_map *map);
 
+/**
+ * struct tcf_pkt_info - packet information
+ */
+struct tcf_pkt_info
+{
+	unsigned char *		ptr;
+	int			nexthdr;
+};
+
+#ifdef CONFIG_NET_EMATCH
+
+struct tcf_ematch_ops;
+
+/**
+ * struct tcf_ematch - extended match (ematch)
+ * 
+ * @matchid: identifier to allow userspace to reidentify a match
+ * @flags: flags specifying attributes and the relation to other matches
+ * @ops: the operations lookup table of the corresponding ematch module
+ * @datalen: length of the ematch specific configuration data
+ * @data: ematch specific data
+ */
+struct tcf_ematch
+{
+	struct tcf_ematch_ops * ops;
+	unsigned long		data;
+	unsigned int		datalen;
+	u16			matchid;
+	u16			flags;
+};
+
+static inline int tcf_em_is_container(struct tcf_ematch *em)
+{
+	return !em->ops;
+}
+
+static inline int tcf_em_is_simple(struct tcf_ematch *em)
+{
+	return em->flags & TCF_EM_SIMPLE;
+}
+
+static inline int tcf_em_is_inverted(struct tcf_ematch *em)
+{
+	return em->flags & TCF_EM_INVERT;
+}
+
+static inline int tcf_em_last_match(struct tcf_ematch *em)
+{
+	return (em->flags & TCF_EM_REL_MASK) == TCF_EM_REL_END;
+}
+
+static inline int tcf_em_early_end(struct tcf_ematch *em, int result)
+{
+	if (tcf_em_last_match(em))
+		return 1;
+
+	if (result == 0 && em->flags & TCF_EM_REL_AND)
+		return 1;
+
+	if (result != 0 && em->flags & TCF_EM_REL_OR)
+		return 1;
+
+	return 0;
+}
+	
+/**
+ * struct tcf_ematch_tree - ematch tree handle
+ *
+ * @hdr: ematch tree header supplied by userspace
+ * @matches: array of ematches
+ */
+struct tcf_ematch_tree
+{
+	struct tcf_ematch_tree_hdr hdr;
+	struct tcf_ematch *	matches;
+	
+};
+
+/**
+ * struct tcf_ematch_ops - ematch module operations
+ * 
+ * @kind: identifier (kind) of this ematch module
+ * @datalen: length of expected configuration data (optional)
+ * @change: called during validation (optional)
+ * @match: called during ematch tree evaluation, must return 1/0
+ * @destroy: called during destroyage (optional)
+ * @dump: called during dumping process (optional)
+ * @owner: owner, must be set to THIS_MODULE
+ * @link: link to previous/next ematch module (internal use)
+ */
+struct tcf_ematch_ops
+{
+	int			kind;
+	int			datalen;
+	int			(*change)(struct tcf_proto *, void *,
+					  int, struct tcf_ematch *);
+	int			(*match)(struct sk_buff *, struct tcf_ematch *,
+					 struct tcf_pkt_info *);
+	void			(*destroy)(struct tcf_proto *,
+					   struct tcf_ematch *);
+	int			(*dump)(struct sk_buff *, struct tcf_ematch *);
+	struct module		*owner;
+	struct list_head	link;
+};
+
+extern int tcf_em_register(struct tcf_ematch_ops *);
+extern int tcf_em_unregister(struct tcf_ematch_ops *);
+extern int tcf_em_tree_validate(struct tcf_proto *, struct rtattr *,
+				struct tcf_ematch_tree *);
+extern void tcf_em_tree_destroy(struct tcf_proto *, struct tcf_ematch_tree *);
+extern int tcf_em_tree_dump(struct sk_buff *, struct tcf_ematch_tree *, int);
+extern int __tcf_em_tree_match(struct sk_buff *, struct tcf_ematch_tree *,
+			       struct tcf_pkt_info *);
+
+/**
+ * tcf_em_tree_change - replace ematch tree of a running classifier
+ *
+ * @tp: classifier kind handle
+ * @dst: destination ematch tree variable
+ * @src: source ematch tree (temporary tree from tcf_em_tree_validate)
+ *
+ * This functions replaces the ematch tree in @dst with the ematch
+ * tree in @src. The classifier in charge of the ematch tree may be
+ * running.
+ */
+static inline void tcf_em_tree_change(struct tcf_proto *tp,
+				      struct tcf_ematch_tree *dst,
+				      struct tcf_ematch_tree *src)
+{
+	tcf_tree_lock(tp);
+	memcpy(dst, src, sizeof(*dst));
+	tcf_tree_unlock(tp);
+}
+
+/**
+ * tcf_em_tree_match - evaulate an ematch tree
+ *
+ * @skb: socket buffer of the packet in question
+ * @tree: ematch tree to be used for evaluation
+ * @info: packet information examined by classifier
+ *
+ * This function matches @skb against the ematch tree in @tree by going
+ * through all ematches respecting their logic relations returning
+ * as soon as the result is obvious.
+ *
+ * Returns 1 if the ematch tree as-one matches, no ematches are configured
+ * or ematch is not enabled in the kernel, otherwise 0 is returned.
+ */
+static inline int tcf_em_tree_match(struct sk_buff *skb,
+				    struct tcf_ematch_tree *tree,
+				    struct tcf_pkt_info *info)
+{
+	if (tree->hdr.nmatches)
+		return __tcf_em_tree_match(skb, tree, info);
+	else
+		return 1;
+}
+
+#else /* CONFIG_NET_EMATCH */
+
+struct tcf_ematch_tree
+{
+};
+
+#define tcf_em_tree_validate(tp, tb, t) ((void)(t), 0)
+#define tcf_em_tree_destroy(tp, t) do { (void)(t); } while(0)
+#define tcf_em_tree_dump(skb, t, tlv) (0)
+#define tcf_em_tree_change(tp, dst, src) do { } while(0)
+#define tcf_em_tree_match(skb, t, info) ((void)(info), 1)
+
+#endif /* CONFIG_NET_EMATCH */
+
+static inline unsigned char * tcf_get_base_ptr(struct sk_buff *skb, int layer)
+{
+	switch (layer) {
+		case TCF_LAYER_LINK:
+			return skb->data;
+		case TCF_LAYER_NETWORK:
+			return skb->nh.raw;
+		case TCF_LAYER_TRANSPORT:
+			return skb->h.raw;
+	}
+
+	return NULL;
+}
+
+static inline int tcf_valid_offset(struct sk_buff *skb, unsigned char *ptr,
+				   int len)
+{
+	return unlikely((ptr + len) < skb->tail && ptr > skb->head);
+}
+
 #ifdef CONFIG_NET_CLS_IND
 static inline int
 tcf_change_indev(struct tcf_proto *tp, char *indev, struct rtattr *indev_tlv)
diff -Nru a/include/net/scm.h b/include/net/scm.h
--- a/include/net/scm.h	2005-03-11 12:51:52 -08:00
+++ b/include/net/scm.h	2005-03-11 12:51:52 -08:00
@@ -51,13 +51,13 @@
 {
 	if (!msg->msg_control)
 	{
-		if (sock->passcred || scm->fp)
+		if (test_bit(SOCK_PASSCRED, &sock->flags) || scm->fp)
 			msg->msg_flags |= MSG_CTRUNC;
 		scm_destroy(scm);
 		return;
 	}
 
-	if (sock->passcred)
+	if (test_bit(SOCK_PASSCRED, &sock->flags))
 		put_cmsg(msg, SOL_SOCKET, SCM_CREDENTIALS, sizeof(scm->creds), &scm->creds);
 
 	if (!scm->fp)
diff -Nru a/include/net/slhc_vj.h b/include/net/slhc_vj.h
--- a/include/net/slhc_vj.h	2005-03-11 12:51:47 -08:00
+++ b/include/net/slhc_vj.h	2005-03-11 12:51:47 -08:00
@@ -185,7 +185,4 @@
 			  int isize));
 int slhc_toss __ARGS((struct slcompress *comp));
 
-void slhc_i_status __ARGS((struct slcompress *comp));
-void slhc_o_status __ARGS((struct slcompress *comp));
-
 #endif	/* _SLHC_H */
diff -Nru a/include/net/sock.h b/include/net/sock.h
--- a/include/net/sock.h	2005-03-11 12:51:47 -08:00
+++ b/include/net/sock.h	2005-03-11 12:51:47 -08:00
@@ -983,6 +983,7 @@
 
 	if (dst && dst->obsolete && dst->ops->check(dst, cookie) == NULL) {
 		sk->sk_dst_cache = NULL;
+		dst_release(dst);
 		return NULL;
 	}
 
@@ -996,6 +997,7 @@
 
 	if (dst && dst->obsolete && dst->ops->check(dst, cookie) == NULL) {
 		sk_dst_reset(sk);
+		dst_release(dst);
 		return NULL;
 	}
 
diff -Nru a/include/net/x25.h b/include/net/x25.h
--- a/include/net/x25.h	2005-03-11 12:51:47 -08:00
+++ b/include/net/x25.h	2005-03-11 12:51:47 -08:00
@@ -10,6 +10,7 @@
 #ifndef _X25_H
 #define _X25_H 
 #include <linux/x25.h>
+#include <net/sock.h>
 
 #define	X25_ADDR_LEN			16
 
@@ -129,7 +130,8 @@
 	atomic_t		refcnt;
 };
 
-struct x25_opt {
+struct x25_sock {
+	struct sock		sk;
 	struct x25_address	source_addr, dest_addr;
 	struct x25_neigh	*neighbour;
 	unsigned int		lci;
@@ -141,7 +143,6 @@
 	struct sk_buff_head	fragment_queue;
 	struct sk_buff_head	interrupt_in_queue;
 	struct sk_buff_head	interrupt_out_queue;
-	struct sock		*sk;		/* Backlink to socket */
 	struct timer_list	timer;
 	struct x25_causediag	causediag;
 	struct x25_facilities	facilities;
@@ -149,7 +150,10 @@
 	unsigned long 		vc_facil_mask;	/* inc_call facilities mask */
 };
 
-#define x25_sk(__sk) ((struct x25_opt *)(__sk)->sk_protinfo)
+static inline struct x25_sock *x25_sk(const struct sock *sk)
+{
+	return (struct x25_sock *)sk;
+}
 
 /* af_x25.c */
 extern int  sysctl_x25_restart_request_timeout;
diff -Nru a/include/net/xfrm.h b/include/net/xfrm.h
--- a/include/net/xfrm.h	2005-03-11 12:51:51 -08:00
+++ b/include/net/xfrm.h	2005-03-11 12:51:51 -08:00
@@ -212,7 +212,7 @@
 	void			(*destructor)(struct xfrm_state *);
 	int			(*input)(struct xfrm_state *, struct xfrm_decap_state *, struct sk_buff *skb);
 	int			(*post_input)(struct xfrm_state *, struct xfrm_decap_state *, struct sk_buff *skb);
-	int			(*output)(struct sk_buff *pskb);
+	int			(*output)(struct xfrm_state *, struct sk_buff *pskb);
 	/* Estimate maximal size of result of transformation of a dgram */
 	u32			(*get_max_size)(struct xfrm_state *, int size);
 };
@@ -511,6 +511,9 @@
 		struct rtable		rt;
 		struct rt6_info		rt6;
 	} u;
+	struct dst_entry *route;
+	u32 route_mtu_cached;
+	u32 child_mtu_cached;
 };
 
 /* Decapsulation state, used by the input to store data during
@@ -807,6 +810,7 @@
 extern int xfrm_replay_check(struct xfrm_state *x, u32 seq);
 extern void xfrm_replay_advance(struct xfrm_state *x, u32 seq);
 extern int xfrm_state_check(struct xfrm_state *x, struct sk_buff *skb);
+extern int xfrm_state_mtu(struct xfrm_state *x, int mtu);
 extern int xfrm4_rcv(struct sk_buff *skb);
 extern int xfrm4_output(struct sk_buff *skb);
 extern int xfrm4_tunnel_register(struct xfrm_tunnel *handler);
@@ -857,6 +861,8 @@
 extern void xfrm_policy_flush(void);
 extern int xfrm_sk_policy_insert(struct sock *sk, int dir, struct xfrm_policy *pol);
 extern int xfrm_flush_bundles(void);
+extern int xfrm_bundle_ok(struct xfrm_dst *xdst, struct flowi *fl, int family);
+extern void xfrm_init_pmtu(struct dst_entry *dst);
 
 extern wait_queue_head_t km_waitq;
 extern int km_new_mapping(struct xfrm_state *x, xfrm_address_t *ipaddr, u16 sport);
diff -Nru a/include/scsi/scsi_driver.h b/include/scsi/scsi_driver.h
--- a/include/scsi/scsi_driver.h	2005-03-11 12:51:47 -08:00
+++ b/include/scsi/scsi_driver.h	2005-03-11 12:51:47 -08:00
@@ -14,6 +14,8 @@
 	int (*init_command)(struct scsi_cmnd *);
 	void (*rescan)(struct device *);
 	int (*issue_flush)(struct device *, sector_t *);
+	int (*prepare_flush)(struct request_queue *, struct request *);
+	void (*end_flush)(struct request_queue *, struct request *);
 };
 #define to_scsi_driver(drv) \
 	container_of((drv), struct scsi_driver, gendrv)
diff -Nru a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h
--- a/include/scsi/scsi_host.h	2005-03-11 12:51:41 -08:00
+++ b/include/scsi/scsi_host.h	2005-03-11 12:51:41 -08:00
@@ -363,6 +363,12 @@
 	unsigned skip_settle_delay:1;
 
 	/*
+	 * ordered write support
+	 */
+	unsigned ordered_flush:1;
+	unsigned ordered_tag:1;
+
+	/*
 	 * Countdown for host blocking with no commands outstanding
 	 */
 	unsigned int max_host_blocked;
@@ -500,6 +506,12 @@
 	 * the spec ;)
 	 */
 	unsigned reverse_ordering:1;
+
+	/*
+	 * ordered write support
+	 */
+	unsigned ordered_flush:1;
+	unsigned ordered_tag:1;
 
 	/*
 	 * Host has rejected a command because it was busy.
diff -Nru a/include/sound/ac97_codec.h b/include/sound/ac97_codec.h
--- a/include/sound/ac97_codec.h	2005-03-11 12:51:46 -08:00
+++ b/include/sound/ac97_codec.h	2005-03-11 12:51:46 -08:00
@@ -366,6 +366,13 @@
 #define AC97_DOUBLE_RATE	(1<<5)	/* supports double rate playback */
 #define AC97_HAS_NO_MASTER_VOL	(1<<6)	/* no Master volume */
 #define AC97_HAS_NO_PCM_VOL	(1<<7)	/* no PCM volume */
+#define AC97_DEFAULT_POWER_OFF	(1<<8)	/* no RESET write */
+#define AC97_MODEM_PATCH	(1<<9)	/* modem patch */
+#define AC97_HAS_NO_REC_GAIN	(1<<10) /* no Record gain */
+#define AC97_HAS_NO_PHONE	(1<<11) /* no PHONE volume */
+#define AC97_HAS_NO_PC_BEEP	(1<<12) /* no PC Beep volume */
+#define AC97_HAS_NO_VIDEO	(1<<13) /* no Video volume */
+#define AC97_HAS_NO_CD		(1<<14) /* no CD volume */
 
 /* rates indexes */
 #define AC97_RATES_FRONT_DAC	0
@@ -580,4 +587,11 @@
 int snd_ac97_pcm_close(struct ac97_pcm *pcm);
 int snd_ac97_pcm_double_rate_rules(snd_pcm_runtime_t *runtime);
 
+struct ac97_enum {
+	unsigned char reg;
+	unsigned char shift_l;
+	unsigned char shift_r;
+	unsigned short mask;
+	const char **texts;
+};
 #endif /* __SOUND_AC97_CODEC_H */
diff -Nru a/include/sound/ak4114.h b/include/sound/ak4114.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/include/sound/ak4114.h	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,205 @@
+#ifndef __SOUND_AK4114_H
+#define __SOUND_AK4114_H
+
+/*
+ *  Routines for Asahi Kasei AK4114
+ *  Copyright (c) by Jaroslav Kysela <perex@suse.cz>,
+ *
+ *
+ *   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
+ *
+ */
+
+/* AK4114 registers */
+#define AK4114_REG_PWRDN	0x00	/* power down */
+#define AK4114_REG_FORMAT	0x01	/* format control */
+#define AK4114_REG_IO0		0x02	/* input/output control */
+#define AK4114_REG_IO1		0x03	/* input/output control */
+#define AK4114_REG_INT0_MASK	0x04	/* interrupt0 mask */
+#define AK4114_REG_INT1_MASK	0x05	/* interrupt1 mask */
+#define AK4114_REG_RCS0		0x06	/* receiver status 0 */
+#define AK4114_REG_RCS1		0x07	/* receiver status 1 */
+#define AK4114_REG_RXCSB0	0x08	/* RX channel status byte 0 */
+#define AK4114_REG_RXCSB1	0x09	/* RX channel status byte 1 */
+#define AK4114_REG_RXCSB2	0x0a	/* RX channel status byte 2 */
+#define AK4114_REG_RXCSB3	0x0b	/* RX channel status byte 3 */
+#define AK4114_REG_RXCSB4	0x0c	/* RX channel status byte 4 */
+#define AK4114_REG_TXCSB0	0x0d	/* TX channel status byte 0 */
+#define AK4114_REG_TXCSB1	0x0e	/* TX channel status byte 1 */
+#define AK4114_REG_TXCSB2	0x0f	/* TX channel status byte 2 */
+#define AK4114_REG_TXCSB3	0x10	/* TX channel status byte 3 */
+#define AK4114_REG_TXCSB4	0x11	/* TX channel status byte 4 */
+#define AK4114_REG_Pc0		0x12	/* burst preamble Pc byte 0 */
+#define AK4114_REG_Pc1		0x13	/* burst preamble Pc byte 1 */
+#define AK4114_REG_Pd0		0x14	/* burst preamble Pd byte 0 */
+#define AK4114_REG_Pd1		0x15	/* burst preamble Pd byte 1 */
+#define AK4114_REG_QSUB_ADDR	0x16	/* Q-subcode address + control */
+#define AK4114_REG_QSUB_TRACK	0x17	/* Q-subcode track */
+#define AK4114_REG_QSUB_INDEX	0x18	/* Q-subcode index */
+#define AK4114_REG_QSUB_MINUTE	0x19	/* Q-subcode minute */
+#define AK4114_REG_QSUB_SECOND	0x1a	/* Q-subcode second */
+#define AK4114_REG_QSUB_FRAME	0x1b	/* Q-subcode frame */
+#define AK4114_REG_QSUB_ZERO	0x1c	/* Q-subcode zero */
+#define AK4114_REG_QSUB_ABSMIN	0x1d	/* Q-subcode absolute minute */
+#define AK4114_REG_QSUB_ABSSEC	0x1e	/* Q-subcode absolute second */
+#define AK4114_REG_QSUB_ABSFRM	0x1f	/* Q-subcode absolute frame */
+
+/* sizes */
+#define AK4114_REG_RXCSB_SIZE	((AK4114_REG_RXCSB4-AK4114_REG_RXCSB0)+1)
+#define AK4114_REG_TXCSB_SIZE	((AK4114_REG_TXCSB4-AK4114_REG_TXCSB0)+1)
+#define AK4114_REG_QSUB_SIZE	((AK4114_REG_QSUB_ABSFRM-AK4114_REG_QSUB_ADDR)+1)
+
+/* AK4117_REG_PWRDN bits */
+#define AK4114_CS12		(1<<7)	/* Channel Status Select */
+#define AK4114_BCU		(1<<6)	/* Block Start & C/U Output Mode */
+#define AK4114_CM1		(1<<5)	/* Master Clock Operation Select */
+#define AK4114_CM0		(1<<4)	/* Master Clock Operation Select */
+#define AK4114_OCKS1		(1<<3)	/* Master Clock Frequency Select */
+#define AK4114_OCKS0		(1<<2)	/* Master Clock Frequency Select */
+#define AK4114_PWN		(1<<1)	/* 0 = power down, 1 = normal operation */
+#define AK4114_RST		(1<<0)	/* 0 = reset & initialize (except this register), 1 = normal operation */
+
+/* AK4114_REQ_FORMAT bits */
+#define AK4114_MONO		(1<<7)	/* Double Sampling Frequency Mode: 0 = stereo, 1 = mono */
+#define AK4114_DIF2		(1<<5)	/* Audio Data Control */
+#define AK4114_DIF1		(1<<5)	/* Audio Data Control */
+#define AK4114_DIF0		(1<<4)	/* Audio Data Control */
+#define AK4114_DIF_16R		(0)				/* STDO: 16-bit, right justified */
+#define AK4114_DIF_18R		(AK4114_DIF0)			/* STDO: 18-bit, right justified */
+#define AK4114_DIF_20R		(AK4114_DIF1)			/* STDO: 20-bit, right justified */
+#define AK4114_DIF_24R		(AK4114_DIF1|AK4114_DIF0)	/* STDO: 24-bit, right justified */
+#define AK4114_DIF_24L		(AK4114_DIF2)			/* STDO: 24-bit, left justified */
+#define AK4114_DIF_24I2S	(AK4114_DIF2|AK4114_DIF0)	/* STDO: I2S */
+#define AK4114_DIF_I24L		(AK4114_DIF2|AK4114_DIF1)	/* STDO: 24-bit, left justified; LRCLK, BICK = Input */
+#define AK4114_DIF_I24I2S	(AK4114_DIF2|AK4114_DIF1|AK4114_DIF0) /* STDO: I2S;  LRCLK, BICK = Input */
+#define AK4114_DEAU		(1<<3)	/* Deemphasis Autodetect Enable (1 = enable) */
+#define AK4114_DEM1		(1<<2)	/* 32kHz-48kHz Deemphasis Control */
+#define AK4114_DEM0		(1<<1)	/* 32kHz-48kHz Deemphasis Control */
+#define AK4114_DEM_44KHZ	(0)
+#define AK4114_DEM_48KHZ	(AK4114_DEM1)
+#define AK4114_DEM_32KHZ	(AK4114_DEM0|AK4114_DEM1)
+#define AK4114_DEM_96KHZ	(AK4114_DEM1)	/* DFS must be set */
+#define AK4114_DFS		(1<<0)	/* 96kHz Deemphasis Control */
+
+/* AK4114_REG_IO0 */
+#define AK4114_TX1E		(1<<7)	/* TX1 Output Enable (1 = enable) */
+#define AK4114_OPS12		(1<<2)	/* Output Though Data Selector for TX1 pin */
+#define AK4114_OPS11		(1<<1)	/* Output Though Data Selector for TX1 pin */
+#define AK4114_OPS10		(1<<0)	/* Output Though Data Selector for TX1 pin */
+#define AK4114_TX0E		(1<<3)	/* TX0 Output Enable (1 = enable) */
+#define AK4114_OPS02		(1<<2)	/* Output Though Data Selector for TX0 pin */
+#define AK4114_OPS01		(1<<1)	/* Output Though Data Selector for TX0 pin */
+#define AK4114_OPS00		(1<<0)	/* Output Though Data Selector for TX0 pin */
+
+/* AK4114_REG_IO1 */
+#define AK4114_EFH1		(1<<7)	/* Interrupt 0 pin Hold */
+#define AK4114_EFH0		(1<<6)	/* Interrupt 0 pin Hold */
+#define AK4114_EFH_512		(0)
+#define AK4114_EFH_1024		(AK4114_EFH0)
+#define AK4114_EFH_2048		(AK4114_EFH1)
+#define AK4114_EFH_4096		(AK4114_EFH1|AK4114_EFH0)
+#define AK4114_UDIT		(1<<5)	/* U-bit Control for DIT (0 = fixed '0', 1 = recovered) */
+#define AK4114_TLR		(1<<4)	/* Double Sampling Frequency Select for DIT (0 = L channel, 1 = R channel) */
+#define AK4114_DIT		(1<<3)	/* TX1 out: 0 = Through Data (RX data), 1 = Transmit Data (DAUX data) */
+#define AK4114_IPS2		(1<<2)	/* Input Recovery Data Select */
+#define AK4114_IPS1		(1<<1)	/* Input Recovery Data Select */
+#define AK4114_IPS0		(1<<0)	/* Input Recovery Data Select */
+#define AK4114_IPS(x)		((x)&7)
+
+/* AK4114_REG_INT0_MASK && AK4114_REG_INT1_MASK*/
+#define AK4117_MQI              (1<<7)  /* mask enable for QINT bit */
+#define AK4117_MAT              (1<<6)  /* mask enable for AUTO bit */
+#define AK4117_MCI              (1<<5)  /* mask enable for CINT bit */
+#define AK4117_MUL              (1<<4)  /* mask enable for UNLOCK bit */
+#define AK4117_MDTS             (1<<3)  /* mask enable for DTSCD bit */
+#define AK4117_MPE              (1<<2)  /* mask enable for PEM bit */
+#define AK4117_MAN              (1<<1)  /* mask enable for AUDN bit */
+#define AK4117_MPR              (1<<0)  /* mask enable for PAR bit */
+
+/* AK4114_REG_RCS0 */
+#define AK4114_QINT		(1<<7)	/* Q-subcode buffer interrupt, 0 = no change, 1 = changed */
+#define AK4114_AUTO		(1<<6)	/* Non-PCM or DTS stream auto detection, 0 = no detect, 1 = detect */
+#define AK4114_CINT		(1<<5)	/* channel status buffer interrupt, 0 = no change, 1 = change */
+#define AK4114_UNLCK		(1<<4)	/* PLL lock status, 0 = lock, 1 = unlock */
+#define AK4114_DTSCD		(1<<3)	/* DTS-CD Detect, 0 = No detect, 1 = Detect */
+#define AK4114_PEM		(1<<2)	/* Pre-emphasis Detect, 0 = OFF, 1 = ON */
+#define AK4114_AUDION		(1<<1)	/* audio bit output, 0 = audio, 1 = non-audio */
+#define AK4114_PAR		(1<<0)	/* parity error or biphase error status, 0 = no error, 1 = error */
+
+/* AK4114_REG_RCS1 */
+#define AK4114_FS3		(1<<7)	/* sampling frequency detection */
+#define AK4114_FS2		(1<<6)
+#define AK4114_FS1		(1<<5)
+#define AK4114_FS0		(1<<4)
+#define AK4114_FS_44100HZ	(0)
+#define AK4114_FS_48000HZ	(AK4114_FS1)
+#define AK4114_FS_32000HZ	(AK4114_FS1|AK4114_FS0)
+#define AK4114_FS_88200HZ	(AK4114_FS3)
+#define AK4114_FS_96000HZ	(AK4114_FS3|AK4114_FS1)
+#define AK4114_FS_176400HZ	(AK4114_FS3|AK4114_FS2)
+#define AK4114_FS_192000HZ	(AK4114_FS3|AK4114_FS2|AK4114_FS1)
+#define AK4114_V		(1<<3)	/* Validity of Channel Status, 0 = Valid, 1 = Invalid */
+#define AK4114_QCRC		(1<<1)	/* CRC for Q-subcode, 0 = no error, 1 = error */
+#define AK4114_CCRC		(1<<0)	/* CRC for channel status, 0 = no error, 1 = error */
+
+/* flags for snd_ak4114_check_rate_and_errors() */
+#define AK4114_CHECK_NO_STAT	(1<<0)	/* no statistics */
+#define AK4114_CHECK_NO_RATE	(1<<1)	/* no rate check */
+
+#define AK4114_CONTROLS		14
+
+typedef void (ak4114_write_t)(void *private_data, unsigned char addr, unsigned char data);
+typedef unsigned char (ak4114_read_t)(void *private_data, unsigned char addr);
+
+typedef struct ak4114 ak4114_t;
+
+struct ak4114 {
+	snd_card_t * card;
+	ak4114_write_t * write;
+	ak4114_read_t * read;
+	void * private_data;
+	unsigned int init: 1;
+	spinlock_t lock;
+	unsigned char regmap[7];
+	unsigned char txcsb[5];
+	snd_kcontrol_t *kctls[AK4114_CONTROLS];
+	snd_pcm_substream_t *playback_substream;
+	snd_pcm_substream_t *capture_substream;
+	unsigned long parity_errors;
+	unsigned long v_bit_errors;
+	unsigned long qcrc_errors;
+	unsigned long ccrc_errors;
+	unsigned char rcs0;
+	unsigned char rcs1;
+	struct workqueue_struct *workqueue;
+	struct work_struct work;
+	void *change_callback_private;
+	void (*change_callback)(ak4114_t *ak4114, unsigned char c0, unsigned char c1);
+};
+
+int snd_ak4114_create(snd_card_t *card,
+		      ak4114_read_t *read, ak4114_write_t *write,
+		      unsigned char pgm[7], unsigned char txcsb[5],
+		      void *private_data, ak4114_t **r_ak4114);
+void snd_ak4114_reg_write(ak4114_t *ak4114, unsigned char reg, unsigned char mask, unsigned char val);
+void snd_ak4114_reinit(ak4114_t *ak4114);
+int snd_ak4114_build(ak4114_t *ak4114,
+		     snd_pcm_substream_t *playback_substream,
+                     snd_pcm_substream_t *capture_substream);
+int snd_ak4114_external_rate(ak4114_t *ak4114);
+int snd_ak4114_check_rate_and_errors(ak4114_t *ak4114, unsigned int flags);
+
+#endif /* __SOUND_AK4114_H */
+
diff -Nru a/include/sound/ak4117.h b/include/sound/ak4117.h
--- a/include/sound/ak4117.h	2005-03-11 12:51:47 -08:00
+++ b/include/sound/ak4117.h	2005-03-11 12:51:47 -08:00
@@ -106,7 +106,7 @@
 #define AK4117_DIF_24L		(AK4117_DIF2)			/* STDO: 24-bit, left justified */
 #define AK4117_DIF_24I2S	(AK4117_DIF2|AK4117_DIF0)	/* STDO: I2S */
 
-/* AK4117_REG_INT0_MASK & AK4117_INT1_MASK */
+/* AK4117_REG_INT0_MASK & AK4117_REG_INT1_MASK */
 #define AK4117_MULK		(1<<7)	/* mask enable for UNLOCK bit */
 #define AK4117_MPAR		(1<<6)	/* mask enable for PAR bit */
 #define AK4117_MAUTO		(1<<5)	/* mask enable for AUTO bit */
@@ -181,8 +181,8 @@
 
 int snd_ak4117_create(snd_card_t *card, ak4117_read_t *read, ak4117_write_t *write,
 		      unsigned char pgm[5], void *private_data, ak4117_t **r_ak4117);
-void snd_ak4117_reg_write(ak4117_t *chip, unsigned char reg, unsigned char mask, unsigned char val);
-void snd_ak4117_reinit(ak4117_t *chip);
+void snd_ak4117_reg_write(ak4117_t *ak4117, unsigned char reg, unsigned char mask, unsigned char val);
+void snd_ak4117_reinit(ak4117_t *ak4117);
 int snd_ak4117_build(ak4117_t *ak4117, snd_pcm_substream_t *capture_substream);
 int snd_ak4117_external_rate(ak4117_t *ak4117);
 int snd_ak4117_check_rate_and_errors(ak4117_t *ak4117, unsigned int flags);
diff -Nru a/include/sound/ak4xxx-adda.h b/include/sound/ak4xxx-adda.h
--- a/include/sound/ak4xxx-adda.h	2005-03-11 12:51:48 -08:00
+++ b/include/sound/ak4xxx-adda.h	2005-03-11 12:51:48 -08:00
@@ -50,7 +50,8 @@
 	/* template should fill the following fields */
 	unsigned int idx_offset;			/* control index offset */
 	enum {
-		SND_AK4524, SND_AK4528, SND_AK4529, SND_AK4355, SND_AK4381
+		SND_AK4524, SND_AK4528, SND_AK4529,
+		SND_AK4355, SND_AK4358, SND_AK4381
 	} type;
 	struct snd_ak4xxx_ops ops;
 };
diff -Nru a/include/sound/control.h b/include/sound/control.h
--- a/include/sound/control.h	2005-03-11 12:51:46 -08:00
+++ b/include/sound/control.h	2005-03-11 12:51:46 -08:00
@@ -119,6 +119,13 @@
 
 int snd_ctl_register_ioctl(snd_kctl_ioctl_func_t fcn);
 int snd_ctl_unregister_ioctl(snd_kctl_ioctl_func_t fcn);
+#ifdef CONFIG_COMPAT
+int snd_ctl_register_ioctl_compat(snd_kctl_ioctl_func_t fcn);
+int snd_ctl_unregister_ioctl_compat(snd_kctl_ioctl_func_t fcn);
+#else
+#define snd_ctl_register_ioctl_compat(fcn)
+#define snd_ctl_unregister_ioctl_compat(fcn)
+#endif
 
 int snd_ctl_elem_read(snd_card_t *card, snd_ctl_elem_value_t *control);
 int snd_ctl_elem_write(snd_card_t *card, snd_ctl_file_t *file, snd_ctl_elem_value_t *control);
diff -Nru a/include/sound/core.h b/include/sound/core.h
--- a/include/sound/core.h	2005-03-11 12:51:52 -08:00
+++ b/include/sound/core.h	2005-03-11 12:51:52 -08:00
@@ -26,6 +26,7 @@
 #include <asm/semaphore.h>		/* struct semaphore */
 #include <linux/rwsem.h>		/* struct rw_semaphore */
 #include <linux/workqueue.h>		/* struct workqueue_struct */
+#include <linux/pm.h>			/* pm_message_t */
 
 /* Typedef's */
 typedef struct timespec snd_timestamp_t;
@@ -167,13 +168,15 @@
 	struct device *dev;
 
 #ifdef CONFIG_PM
-	int (*pm_suspend)(snd_card_t *card, unsigned int state);
-	int (*pm_resume)(snd_card_t *card, unsigned int state);
-	struct pm_dev *pm_dev;		/* for ISA */
+	int (*pm_suspend)(snd_card_t *card, pm_message_t state);
+	int (*pm_resume)(snd_card_t *card);
 	void *pm_private_data;
 	unsigned int power_state;	/* power state */
 	struct semaphore power_lock;	/* power lock */
 	wait_queue_head_t power_sleep;
+#ifdef CONFIG_SND_GENERIC_PM
+	struct snd_generic_device *pm_dev;	/* for ISA */
+#endif
 #endif
 
 #if defined(CONFIG_SND_MIXER_OSS) || defined(CONFIG_SND_MIXER_OSS_MODULE)
@@ -206,36 +209,34 @@
 	wake_up(&card->power_sleep);
 }
 int snd_card_set_pm_callback(snd_card_t *card,
-			     int (*suspend)(snd_card_t *, unsigned int),
-			     int (*resume)(snd_card_t *, unsigned int),
+			     int (*suspend)(snd_card_t *, pm_message_t),
+			     int (*resume)(snd_card_t *),
 			     void *private_data);
-int snd_card_set_dev_pm_callback(snd_card_t *card, int type,
-				 int (*suspend)(snd_card_t *, unsigned int),
-				 int (*resume)(snd_card_t *, unsigned int),
-				 void *private_data);
+int snd_card_set_generic_pm_callback(snd_card_t *card,
+				     int (*suspend)(snd_card_t *, pm_message_t),
+				     int (*resume)(snd_card_t *),
+				     void *private_data);
 #define snd_card_set_isa_pm_callback(card,suspend,resume,data) \
-	snd_card_set_dev_pm_callback(card, PM_ISA_DEV, suspend, resume, data)
-#ifdef CONFIG_PCI
-#ifndef SND_PCI_PM_CALLBACKS
-int snd_card_pci_suspend(struct pci_dev *dev, u32 state);
+	snd_card_set_generic_pm_callback(card, suspend, resume, data)
+struct pci_dev;
+int snd_card_pci_suspend(struct pci_dev *dev, pm_message_t state);
 int snd_card_pci_resume(struct pci_dev *dev);
 #define SND_PCI_PM_CALLBACKS \
 	.suspend = snd_card_pci_suspend,  .resume = snd_card_pci_resume
-#endif
-#endif
-#else
+
+#else /* ! CONFIG_PM */
+
 #define snd_power_lock(card)		do { (void)(card); } while (0)
 #define snd_power_unlock(card)		do { (void)(card); } while (0)
 static inline int snd_power_wait(snd_card_t *card, unsigned int state, struct file *file) { return 0; }
 #define snd_power_get_state(card)	SNDRV_CTL_POWER_D0
 #define snd_power_change_state(card, state)	do { (void)(card); } while (0)
 #define snd_card_set_pm_callback(card,suspend,resume,data)
-#define snd_card_set_dev_pm_callback(card,suspend,resume,data)
+#define snd_card_set_generic_pm_callback(card,suspend,resume,data)
 #define snd_card_set_isa_pm_callback(card,suspend,resume,data)
-#ifdef CONFIG_PCI
 #define SND_PCI_PM_CALLBACKS
-#endif
-#endif
+
+#endif /* CONFIG_PM */
 
 /* device.c */
 
diff -Nru a/include/sound/cs46xx.h b/include/sound/cs46xx.h
--- a/include/sound/cs46xx.h	2005-03-11 12:51:42 -08:00
+++ b/include/sound/cs46xx.h	2005-03-11 12:51:42 -08:00
@@ -1720,7 +1720,7 @@
 	snd_kcontrol_t *eapd_switch; /* for amplifier hack */
 	int accept_valid;	/* accept mmap valid (for OSS) */
 
-	struct snd_cs46xx_gameport *gameport;
+	struct gameport *gameport;
 
 #ifdef CONFIG_SND_CS46XX_DEBUG_GPIO
 	int current_gpio;
@@ -1751,6 +1751,6 @@
 int snd_cs46xx_mixer(cs46xx_t *chip);
 int snd_cs46xx_midi(cs46xx_t *chip, int device, snd_rawmidi_t **rmidi);
 int snd_cs46xx_start_dsp(cs46xx_t *chip);
-void snd_cs46xx_gameport(cs46xx_t *chip);
+int snd_cs46xx_gameport(cs46xx_t *chip);
 
 #endif /* __SOUND_CS46XX_H */
diff -Nru a/include/sound/emu10k1.h b/include/sound/emu10k1.h
--- a/include/sound/emu10k1.h	2005-03-11 12:51:42 -08:00
+++ b/include/sound/emu10k1.h	2005-03-11 12:51:42 -08:00
@@ -51,7 +51,9 @@
 #define NUM_MIDI        16
 #define NUM_G           64              /* use all channels */
 #define NUM_FXSENDS     4
+#define NUM_EFX_PLAYBACK    16
 
+/* FIXME? - according to the OSS driver the EMU10K1 needs a 29 bit DMA mask */
 #define EMU10K1_DMA_MASK	0x7fffffffUL	/* 31bit */
 #define AUDIGY_DMA_MASK		0xffffffffUL	/* 32bit */
 
@@ -82,10 +84,16 @@
 						/* Clear pending interrupts by writing a 1 to	*/
 						/* the relevant bits and zero to the other bits	*/
 
+#define IPR_GPIOMSG		0x20000000	/* GPIO message interrupt (RE'd, still not sure 
+						   which INTE bits enable it)			*/
+
 /* The next two interrupts are for the midi port on the Audigy Drive (A_MPU1)			*/
 #define IPR_A_MIDITRANSBUFEMPTY2 0x10000000	/* MIDI UART transmit buffer empty		*/
 #define IPR_A_MIDIRECVBUFEMPTY2	0x08000000	/* MIDI UART receive buffer empty		*/
 
+#define IPR_SPDIFBUFFULL	0x04000000	/* SPDIF capture related, 10k2 only? (RE)	*/
+#define IPR_SPDIFBUFHALFFULL	0x02000000	/* SPDIF capture related? (RE)			*/
+
 #define IPR_SAMPLERATETRACKER	0x01000000	/* Sample rate tracker lock status change	*/
 #define IPR_FXDSP		0x00800000	/* Enable FX DSP interrupts			*/
 #define IPR_FORCEINT		0x00400000	/* Force Sound Blaster interrupt		*/
@@ -104,12 +112,12 @@
 #define IPR_INTERVALTIMER	0x00000200	/* Interval timer terminal count		*/
 #define IPR_MIDITRANSBUFEMPTY	0x00000100	/* MIDI UART transmit buffer empty		*/
 #define IPR_MIDIRECVBUFEMPTY	0x00000080	/* MIDI UART receive buffer empty		*/
-#define IPR_CHANNELLOOP		0x00000040	/* One or more channel loop interrupts pending	*/
+#define IPR_CHANNELLOOP		0x00000040	/* Channel (half) loop interrupt(s) pending	*/
 #define IPR_CHANNELNUMBERMASK	0x0000003f	/* When IPR_CHANNELLOOP is set, indicates the	*/
-						/* Highest set channel in CLIPL or CLIPH.  When	*/
-						/* IP is written with CL set, the bit in CLIPL	*/
-						/* or CLIPH corresponding to the CIN value 	*/
-						/* written will be cleared.			*/
+						/* highest set channel in CLIPL, CLIPH, HLIPL,  */
+						/* or HLIPH.  When IP is written with CL set,	*/
+						/* the bit in H/CLIPL or H/CLIPH corresponding	*/
+						/* to the CIN value written will be cleared.	*/
 
 #define INTE			0x0c		/* Interrupt enable register			*/
 #define INTE_VIRTUALSB_MASK	0xc0000000	/* Virtual Soundblaster I/O port capture	*/
@@ -236,9 +244,27 @@
 #define A_IOCFG			0x18		/* GPIO on Audigy card (16bits)			*/
 #define A_GPINPUT_MASK		0xff00
 #define A_GPOUTPUT_MASK		0x00ff
-#define A_IOCFG_GPOUT0		0x0044		/* analog/digital? */
-#define A_IOCFG_GPOUT1		0x0002		/* IR */
+
+// Audigy output/GPIO stuff taken from the kX drivers
+#define A_IOCFG_GPOUT0		0x0044		/* analog/digital				*/
+#define A_IOCFG_DISABLE_ANALOG	0x0040		/* = 'enable' for Audigy2 (chiprev=4)		*/
+#define A_IOCFG_ENABLE_DIGITAL	0x0004
+#define A_IOCFG_UNKNOWN_20      0x0020
+#define A_IOCFG_DISABLE_AC97_FRONT      0x0080  /* turn off ac97 front -> front (10k2.1)	*/
+#define A_IOCFG_GPOUT1		0x0002		/* IR? drive's internal bypass (?)		*/
 #define A_IOCFG_GPOUT2		0x0001		/* IR */
+#define A_IOCFG_MULTIPURPOSE_JACK	0x2000  /* center+lfe+rear_center (a2/a2ex)		*/
+                                                /* + digital for generic 10k2			*/
+#define A_IOCFG_DIGITAL_JACK    0x1000          /* digital for a2 platinum			*/
+#define A_IOCFG_FRONT_JACK      0x4000
+#define A_IOCFG_REAR_JACK       0x8000
+#define A_IOCFG_PHONES_JACK     0x0100          /* LiveDrive					*/
+
+/* outputs:
+ *	for audigy2 platinum:	0xa00
+ *	for a2 platinum ex:	0x1c00
+ *	for a1 platinum:	0x0
+ */
 
 #define TIMER			0x1a		/* Timer terminal count register		*/
 						/* NOTE: After the rate is changed, a maximum	*/
@@ -464,6 +490,8 @@
 						/* NOTE: All channels contain internal variables; do	*/
 						/* not write to these locations.			*/
 
+/* 1f something */
+
 #define CD0			0x20		/* Cache data 0 register				*/
 #define CD1			0x21		/* Cache data 1 register				*/
 #define CD2			0x22		/* Cache data 2 register				*/
@@ -481,6 +509,8 @@
 #define CDE			0x2e		/* Cache data E register				*/
 #define CDF			0x2f		/* Cache data F register				*/
 
+/* 0x30-3f seem to be the same as 0x20-2f */
+
 #define PTB			0x40		/* Page table base register				*/
 #define PTB_MASK		0xfffff000	/* Physical address of the page table in host memory	*/
 
@@ -511,7 +541,11 @@
 
 #define FXWC			0x43		/* FX output write channels register			*/
 						/* When set, each bit enables the writing of the	*/
-						/* corresponding FX output channel into host memory	*/
+						/* corresponding FX output channel (internal registers  */
+						/* 0x20-0x3f) to host memory.  This mode of recording   */
+						/* is 16bit, 48KHz only. All 32 channels can be enabled */
+						/* simultaneously.					*/
+
 #define FXWC_DEFAULTROUTE_C     (1<<0)		/* left emu out? */
 #define FXWC_DEFAULTROUTE_B     (1<<1)		/* right emu out? */
 #define FXWC_DEFAULTROUTE_A     (1<<12)
@@ -546,12 +580,16 @@
 #define FXBA			0x47		/* FX Buffer Address */
 #define FXBA_MASK		0xfffff000	/* 20 bit base address					*/
 
+/* 0x48 something - word access, defaults to 3f */
+
 #define MICBS			0x49		/* Microphone buffer size register			*/
 
 #define ADCBS			0x4a		/* ADC buffer size register				*/
 
 #define FXBS			0x4b		/* FX buffer size register				*/
 
+/* register: 0x4c..4f: ffff-ffff current amounts, per-channel */
+
 /* The following mask values define the size of the ADC, MIX and FX buffers in bytes */
 #define ADCBS_BUFSIZE_NONE	0x00000000
 #define ADCBS_BUFSIZE_384	0x00000001
@@ -602,6 +640,7 @@
 #define A_DBG_SATURATION_OCCURED 0x20000000
 #define A_DBG_SATURATION_ADDR	 0x0ffc0000
 
+// NOTE: 0x54,55,56: 64-bit
 #define SPCS0			0x54		/* SPDIF output Channel Status 0 register	*/
 
 #define SPCS1			0x55		/* SPDIF output Channel Status 1 register	*/
@@ -657,6 +696,7 @@
 #define AC97SLOT_CNTR		0x10            /* Center enable */
 #define AC97SLOT_LFE		0x20            /* LFE enable */
 
+// NOTE: 0x60,61,62: 64-bit
 #define CDSRCS			0x60		/* CD-ROM Sample Rate Converter status register	*/
 
 #define GPSRCS			0x61		/* General Purpose SPDIF sample rate cvt status */
@@ -693,6 +733,19 @@
 #define FXIDX_MASK		0x0000ffff	/* 16-bit value					*/
 #define FXIDX_IDX		0x10000065
 
+/* The 32-bit HLIx and HLIPx registers all have one bit per channel control/status      		*/
+#define HLIEL			0x66		/* Channel half loop interrupt enable low register	*/
+
+#define HLIEH			0x67		/* Channel half loop interrupt enable high register	*/
+
+#define HLIPL			0x68		/* Channel half loop interrupt pending low register	*/
+
+#define HLIPH			0x69		/* Channel half loop interrupt pending high register	*/
+
+// 0x6a,6b,6c used for some recording
+// 0x6d unused
+// 0x6e,6f - tanktable base / offset
+
 /* This is the MPU port on the card (via the game port)						*/
 #define A_MUDATA1		0x70
 #define A_MUCMD1		0x71
@@ -710,10 +763,14 @@
 #define A_FXWC2			0x75		/* Selects 0x9f-0x80 for FX recording           */
 
 #define A_SPDIF_SAMPLERATE	0x76		/* Set the sample rate of SPDIF output		*/
-#define A_SPDIF_48000		0x00000080
-#define A_SPDIF_44100		0x00000000
+#define A_SPDIF_RATE_MASK	0x000000c0
+#define A_SPDIF_48000		0x00000000
+#define A_SPDIF_44100		0x00000080
 #define A_SPDIF_96000		0x00000040
 
+/* 0x77,0x78,0x79 "something i2s-related" - default to 0x01080000 on my audigy 2 ZS --rlrevell	*/
+/* 0x7a, 0x7b - lookup tables */
+
 #define A_FXRT2			0x7c
 #define A_FXRT_CHANNELE		0x0000003f	/* Effects send bus number for channel's effects send E	*/
 #define A_FXRT_CHANNELF		0x00003f00	/* Effects send bus number for channel's effects send F	*/
@@ -725,7 +782,8 @@
 #define A_FXSENDAMOUNT_F_MASK	0x00FF0000
 #define A_FXSENDAMOUNT_G_MASK	0x0000FF00
 #define A_FXSENDAMOUNT_H_MASK	0x000000FF
-
+/* 0x7c, 0x7e "high bit is used for filtering" */
+ 
 /* The send amounts for this one are the same as used with the emu10k1 */
 #define A_FXRT1			0x7e
 #define A_FXRT_CHANNELA		0x0000003f
@@ -782,6 +840,7 @@
 typedef struct _snd_emu10k1_pcm emu10k1_pcm_t;
 
 typedef enum {
+	EMU10K1_EFX,
 	EMU10K1_PCM,
 	EMU10K1_SYNTH,
 	EMU10K1_MIDI
@@ -790,8 +849,9 @@
 struct _snd_emu10k1_voice {
 	emu10k1_t *emu;
 	int number;
-	int use: 1,
+	unsigned int use: 1,
 	    pcm: 1,
+	    efx: 1,
 	    synth: 1,
 	    midi: 1;
 	void (*interrupt)(emu10k1_t *emu, emu10k1_voice_t *pvoice);
@@ -801,6 +861,7 @@
 
 typedef enum {
 	PLAYBACK_EMUVOICE,
+	PLAYBACK_EFX,
 	CAPTURE_AC97ADC,
 	CAPTURE_AC97MIC,
 	CAPTURE_EFX
@@ -810,7 +871,7 @@
 	emu10k1_t *emu;
 	snd_emu10k1_pcm_type_t type;
 	snd_pcm_substream_t *substream;
-	emu10k1_voice_t *voices[2];
+	emu10k1_voice_t *voices[NUM_EFX_PLAYBACK];
 	emu10k1_voice_t *extra;
 	unsigned short running;
 	unsigned short first_ptr;
@@ -938,7 +999,7 @@
 	int irq;
 
 	unsigned long port;			/* I/O port number */
-	int APS: 1,				/* APS flag */
+	unsigned int APS: 1,			/* APS flag */
 	    no_ac97: 1,				/* no AC'97 */
 	    tos_link: 1,			/* tos link detected */
 	    rear_ac97: 1,			/* rear channels are on AC'97 */
@@ -984,23 +1045,27 @@
 	spinlock_t voice_lock;
 	struct semaphore ptb_lock;
 
-	emu10k1_voice_t voices[64];
+	emu10k1_voice_t voices[NUM_G];
 	emu10k1_pcm_mixer_t pcm_mixer[32];
+	emu10k1_pcm_mixer_t efx_pcm_mixer[NUM_EFX_PLAYBACK];
 	snd_kcontrol_t *ctl_send_routing;
 	snd_kcontrol_t *ctl_send_volume;
 	snd_kcontrol_t *ctl_attn;
+	snd_kcontrol_t *ctl_efx_send_routing;
+	snd_kcontrol_t *ctl_efx_send_volume;
+	snd_kcontrol_t *ctl_efx_attn;
 
 	void (*hwvol_interrupt)(emu10k1_t *emu, unsigned int status);
 	void (*capture_interrupt)(emu10k1_t *emu, unsigned int status);
 	void (*capture_mic_interrupt)(emu10k1_t *emu, unsigned int status);
 	void (*capture_efx_interrupt)(emu10k1_t *emu, unsigned int status);
-	void (*timer_interrupt)(emu10k1_t *emu);
 	void (*spdif_interrupt)(emu10k1_t *emu, unsigned int status);
 	void (*dsp_interrupt)(emu10k1_t *emu);
 
 	snd_pcm_substream_t *pcm_capture_substream;
 	snd_pcm_substream_t *pcm_capture_mic_substream;
 	snd_pcm_substream_t *pcm_capture_efx_substream;
+	snd_pcm_substream_t *pcm_playback_efx_substream;
 
 	snd_timer_t *timer;
 
@@ -1008,6 +1073,7 @@
 	emu10k1_midi_t midi2; /* for audigy */
 
 	unsigned int efx_voices_mask[2];
+	unsigned int next_free_voice;
 };
 
 int snd_emu10k1_create(snd_card_t * card,
@@ -1021,6 +1087,7 @@
 int snd_emu10k1_pcm(emu10k1_t * emu, int device, snd_pcm_t ** rpcm);
 int snd_emu10k1_pcm_mic(emu10k1_t * emu, int device, snd_pcm_t ** rpcm);
 int snd_emu10k1_pcm_efx(emu10k1_t * emu, int device, snd_pcm_t ** rpcm);
+int snd_emu10k1_pcm_multi(emu10k1_t * emu, int device, snd_pcm_t ** rpcm);
 int snd_emu10k1_fx8010_pcm(emu10k1_t * emu, int device, snd_pcm_t ** rpcm);
 int snd_emu10k1_mixer(emu10k1_t * emu);
 int snd_emu10k1_timer(emu10k1_t * emu, int device);
@@ -1043,6 +1110,9 @@
 void snd_emu10k1_voice_intr_enable(emu10k1_t *emu, unsigned int voicenum);
 void snd_emu10k1_voice_intr_disable(emu10k1_t *emu, unsigned int voicenum);
 void snd_emu10k1_voice_intr_ack(emu10k1_t *emu, unsigned int voicenum);
+void snd_emu10k1_voice_half_loop_intr_enable(emu10k1_t *emu, unsigned int voicenum);
+void snd_emu10k1_voice_half_loop_intr_disable(emu10k1_t *emu, unsigned int voicenum);
+void snd_emu10k1_voice_half_loop_intr_ack(emu10k1_t *emu, unsigned int voicenum);
 void snd_emu10k1_voice_set_loop_stop(emu10k1_t *emu, unsigned int voicenum);
 void snd_emu10k1_voice_clear_loop_stop(emu10k1_t *emu, unsigned int voicenum);
 void snd_emu10k1_wait(emu10k1_t *emu, unsigned int wait);
@@ -1112,7 +1182,10 @@
 /* GPRs */
 #define FXBUS(x)	(0x00 + (x))	/* x = 0x00 - 0x0f */
 #define EXTIN(x)	(0x10 + (x))	/* x = 0x00 - 0x0f */
-#define EXTOUT(x)	(0x20 + (x))	/* x = 0x00 - 0x0f */
+#define EXTOUT(x)	(0x20 + (x))	/* x = 0x00 - 0x0f physical outs -> FXWC low 16 bits */
+#define FXBUS2(x)	(0x30 + (x))	/* x = 0x00 - 0x0f copies of fx buses for capture -> FXWC high 16 bits */
+					/* NB: 0x31 and 0x32 are shared with Center/LFE on SB live 5.1 */
+
 #define C_00000000	0x40
 #define C_00000001	0x41
 #define C_00000002	0x42
@@ -1154,9 +1227,13 @@
 #define A_ITRAM_CTL(x)	(A_TANKMEMCTLREGBASE + 0x00 + (x)) /* x = 0x00 - 0xbf */
 #define A_ETRAM_CTL(x)	(A_TANKMEMCTLREGBASE + 0xc0 + (x)) /* x = 0x00 - 0x3f */
 
-#define A_FXBUS(x)	(0x00 + (x))	/* x = 0x00 - 0x3f? */
-#define A_EXTIN(x)	(0x40 + (x))	/* x = 0x00 - 0x1f? */
-#define A_EXTOUT(x)	(0x60 + (x))	/* x = 0x00 - 0x1f? */
+#define A_FXBUS(x)	(0x00 + (x))	/* x = 0x00 - 0x3f FX buses */
+#define A_EXTIN(x)	(0x40 + (x))	/* x = 0x00 - 0x0f physical ins */
+#define A_P16VIN(x)	(0x50 + (x))	/* x = 0x00 - 0x0f p16v ins (A2 only) "EMU32 inputs" */
+#define A_EXTOUT(x)	(0x60 + (x))	/* x = 0x00 - 0x1f physical outs -> A_FXWC1 0x79-7f unknown   */
+#define A_FXBUS2(x)	(0x80 + (x))	/* x = 0x00 - 0x1f extra outs used for EFX capture -> A_FXWC2 */
+#define A_EMU32OUTH(x)	(0xa0 + (x))	/* x = 0x00 - 0x0f "EMU32_OUT_10 - _1F" - ??? */
+#define A_EMU32OUTL(x)	(0xb0 + (x))	/* x = 0x00 - 0x0f "EMU32_OUT_1 - _F" - ??? */
 #define A_GPR(x)	(A_FXGPREGBASE + (x))
 
 /* cc_reg constants */
diff -Nru a/include/sound/gus.h b/include/sound/gus.h
--- a/include/sound/gus.h	2005-03-11 12:51:41 -08:00
+++ b/include/sound/gus.h	2005-03-11 12:51:41 -08:00
@@ -230,7 +230,7 @@
 	int mode;		/* operation mode */
 	int client;		/* sequencer client number */
 	int port;		/* sequencer port number */
-	int midi_has_voices: 1;
+	unsigned int midi_has_voices: 1;
 } snd_gus_port_t;
 
 typedef struct _snd_gus_voice snd_gus_voice_t;
@@ -264,7 +264,7 @@
 
 struct _snd_gus_voice {
 	int number;
-	int use: 1,
+	unsigned int use: 1,
 	    pcm: 1,
 	    synth:1,
 	    midi: 1;
diff -Nru a/include/sound/hwdep.h b/include/sound/hwdep.h
--- a/include/sound/hwdep.h	2005-03-11 12:51:42 -08:00
+++ b/include/sound/hwdep.h	2005-03-11 12:51:42 -08:00
@@ -38,6 +38,7 @@
 	int (*release) (snd_hwdep_t * hw, struct file * file);
 	unsigned int (*poll) (snd_hwdep_t * hw, struct file * file, poll_table * wait);
 	int (*ioctl) (snd_hwdep_t * hw, struct file * file, unsigned int cmd, unsigned long arg);
+	int (*ioctl_compat) (snd_hwdep_t * hw, struct file * file, unsigned int cmd, unsigned long arg);
 	int (*mmap) (snd_hwdep_t * hw, struct file * file, struct vm_area_struct * vma);
 	int (*dsp_status) (snd_hwdep_t * hw, snd_hwdep_dsp_status_t * status);
 	int (*dsp_load) (snd_hwdep_t * hw, snd_hwdep_dsp_image_t * image);
diff -Nru a/include/sound/mixer_oss.h b/include/sound/mixer_oss.h
--- a/include/sound/mixer_oss.h	2005-03-11 12:51:47 -08:00
+++ b/include/sound/mixer_oss.h	2005-03-11 12:51:47 -08:00
@@ -38,7 +38,7 @@
 
 struct _snd_oss_mixer_slot {
 	int number;
-	int stereo: 1;
+	unsigned int stereo: 1;
 	snd_mixer_oss_get_volume_t get_volume;
 	snd_mixer_oss_put_volume_t put_volume;
 	snd_mixer_oss_get_recsrc_t get_recsrc;
diff -Nru a/include/sound/mpu401.h b/include/sound/mpu401.h
--- a/include/sound/mpu401.h	2005-03-11 12:51:51 -08:00
+++ b/include/sound/mpu401.h	2005-03-11 12:51:51 -08:00
@@ -86,9 +86,6 @@
 	spinlock_t output_lock;
 	spinlock_t timer_lock;
 	
-	atomic_t rx_loop;
-	atomic_t tx_loop;
-
 	struct timer_list timer;
 
 	void (*write) (mpu401_t * mpu, unsigned char data, unsigned long addr);
diff -Nru a/include/sound/rawmidi.h b/include/sound/rawmidi.h
--- a/include/sound/rawmidi.h	2005-03-11 12:51:51 -08:00
+++ b/include/sound/rawmidi.h	2005-03-11 12:51:51 -08:00
@@ -23,6 +23,7 @@
  */
 
 #include <sound/asound.h>
+#include <linux/interrupt.h>
 #include <linux/spinlock.h>
 #include <linux/wait.h>
 #include <asm/semaphore.h>
@@ -65,8 +66,7 @@
 } snd_rawmidi_global_ops_t;
 
 struct _snd_rawmidi_runtime {
-	unsigned int trigger: 1, /* transfer is running */
-		     drain: 1,	/* drain stage */
+	unsigned int drain: 1,	/* drain stage */
 		     oss: 1;	/* OSS compatible mode */
 	/* midi stream buffer */
 	unsigned char *buffer;	/* buffer for MIDI data */
@@ -80,6 +80,7 @@
 	spinlock_t lock;
 	wait_queue_head_t sleep;
 	/* event handler (room [output] or new bytes [input]) */
+	struct tasklet_struct event_tasklet;
 	void (*event)(snd_rawmidi_substream_t *substream);
 	/* private data */
 	void *private_data;
diff -Nru a/include/sound/seq_virmidi.h b/include/sound/seq_virmidi.h
--- a/include/sound/seq_virmidi.h	2005-03-11 12:51:51 -08:00
+++ b/include/sound/seq_virmidi.h	2005-03-11 12:51:51 -08:00
@@ -38,7 +38,7 @@
 	int seq_mode;
 	int client;
 	int port;
-	int trigger: 1;
+	unsigned int trigger: 1;
 	snd_midi_event_t *parser;
 	snd_seq_event_t event;
 	snd_virmidi_dev_t *rdev;
diff -Nru a/include/sound/trident.h b/include/sound/trident.h
--- a/include/sound/trident.h	2005-03-11 12:51:47 -08:00
+++ b/include/sound/trident.h	2005-03-11 12:51:47 -08:00
@@ -290,7 +290,7 @@
 	int mode;		/* operation mode */
 	int client;		/* sequencer client number */
 	int port;		/* sequencer port number */
-	int midi_has_voices: 1;
+	unsigned int midi_has_voices: 1;
 } snd_trident_port_t;
 
 typedef struct snd_trident_memblk_arg {
@@ -308,7 +308,7 @@
 
 struct _snd_trident_voice {
 	unsigned int number;
-	int use: 1,
+	unsigned int use: 1,
 	    pcm: 1,
 	    synth:1,
 	    midi: 1;
@@ -347,7 +347,7 @@
 	trident_t *trident;
 	snd_pcm_substream_t *substream;
 	snd_trident_voice_t *extra;	/* extra PCM voice (acts as interrupt generator) */
-	int running: 1,
+	unsigned int running: 1,
             capture: 1,
             spdif: 1,
             foldback: 1,
@@ -448,7 +448,7 @@
 
 	spinlock_t reg_lock;
 
-	struct snd_trident_gameport *gameport;
+	struct gameport *gameport;
 };
 
 int snd_trident_create(snd_card_t * card,
@@ -457,7 +457,7 @@
 		       int pcm_spdif_device,
 		       int max_wavetable_size,
 		       trident_t ** rtrident);
-void snd_trident_gameport(trident_t *trident);
+int snd_trident_create_gameport(trident_t *trident);
 
 int snd_trident_pcm(trident_t * trident, int device, snd_pcm_t **rpcm);
 int snd_trident_foldback_pcm(trident_t * trident, int device, snd_pcm_t **rpcm);
diff -Nru a/include/sound/ymfpci.h b/include/sound/ymfpci.h
--- a/include/sound/ymfpci.h	2005-03-11 12:51:42 -08:00
+++ b/include/sound/ymfpci.h	2005-03-11 12:51:42 -08:00
@@ -198,6 +198,10 @@
 #define YMFPCI_LEGACY2_IMOD	(1 << 15)	/* legacy IRQ mode */
 /* SIEN:IMOD 0:0 = legacy irq, 0:1 = INTA, 1:0 = serialized IRQ */
 
+#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))
+#define SUPPORT_JOYSTICK
+#endif
+
 /*
  *
  */
@@ -262,7 +266,7 @@
 struct _snd_ymfpci_voice {
 	ymfpci_t *chip;
 	int number;
-	int use: 1,
+	unsigned int use: 1,
 	    pcm: 1,
 	    synth: 1,
 	    midi: 1;
@@ -288,9 +292,9 @@
 	snd_ymfpci_pcm_type_t type;
 	snd_pcm_substream_t *substream;
 	ymfpci_voice_t *voices[2];	/* playback only */
-	int running: 1;
-	int output_front: 1;
-	int output_rear: 1;
+	unsigned int running: 1;
+	unsigned int output_front: 1;
+	unsigned int output_rear: 1;
 	u32 period_size;		/* cached from runtime->period_size */
 	u32 buffer_size;		/* cached from runtime->buffer_size */
 	u32 period_pos;
@@ -311,9 +315,8 @@
 	struct resource *mpu_res;
 
 	unsigned short old_legacy_ctrl;
-#if defined(CONFIG_GAMEPORT) || defined(CONFIG_GAMEPORT_MODULE)
-	struct resource *joystick_res;
-	struct gameport gameport;
+#ifdef SUPPORT_JOYSTICK
+	struct gameport *gameport;
 #endif
 
 	struct snd_dma_buffer work_ptr;
@@ -381,6 +384,7 @@
 		      struct pci_dev *pci,
 		      unsigned short old_legacy_ctrl,
 		      ymfpci_t ** rcodec);
+void snd_ymfpci_free_gameport(ymfpci_t *chip);
 
 int snd_ymfpci_pcm(ymfpci_t *chip, int device, snd_pcm_t **rpcm);
 int snd_ymfpci_pcm2(ymfpci_t *chip, int device, snd_pcm_t **rpcm);
@@ -388,9 +392,5 @@
 int snd_ymfpci_pcm_4ch(ymfpci_t *chip, int device, snd_pcm_t **rpcm);
 int snd_ymfpci_mixer(ymfpci_t *chip, int rear_switch);
 int snd_ymfpci_timer(ymfpci_t *chip, int device);
-
-#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))
-#define SUPPORT_JOYSTICK
-#endif
 
 #endif /* __SOUND_YMFPCI_H */
diff -Nru a/include/sound/yss225.h b/include/sound/yss225.h
--- a/include/sound/yss225.h	2005-03-11 12:51:51 -08:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,23 +0,0 @@
-#ifndef __SOUND_YSS225_H
-#define __SOUND_YSS225_H
-
-extern unsigned char page_zero[256];
-extern unsigned char page_one[256];
-extern unsigned char page_two[128];
-extern unsigned char page_three[128];
-extern unsigned char page_four[128];
-extern unsigned char page_six[192];
-extern unsigned char page_seven[256];
-extern unsigned char page_zero_v2[96];
-extern unsigned char page_one_v2[96];
-extern unsigned char page_two_v2[48];
-extern unsigned char page_three_v2[48];
-extern unsigned char page_four_v2[48];
-extern unsigned char page_seven_v2[96];
-extern unsigned char mod_v2[304];
-extern unsigned char coefficients[364];
-extern unsigned char coefficients2[56];
-extern unsigned char coefficients3[404];
-
-
-#endif /* __SOUND_YSS225_H  */
diff -Nru a/init/Kconfig b/init/Kconfig
--- a/init/Kconfig	2005-03-11 12:51:50 -08:00
+++ b/init/Kconfig	2005-03-11 12:51:50 -08:00
@@ -237,6 +237,16 @@
 	  This option enables access to the kernel configuration file
 	  through /proc/config.gz.
 
+config CPUSETS
+	bool "Cpuset support"
+	depends on SMP
+	help
+	  This options will let you create and manage CPUSET's which
+	  allow dynamically partitioning a system into sets of CPUs and
+	  Memory Nodes and assigning tasks to run only within those sets.
+	  This is primarily useful on large SMP or NUMA systems.
+
+	  Say N if unsure.
 
 menuconfig EMBEDDED
 	bool "Configure standard kernel features (for small systems)"
@@ -276,6 +286,13 @@
 	   reported.  KALLSYMS_EXTRA_PASS is only a temporary workaround while
 	   you wait for kallsyms to be fixed.
 
+config BASE_FULL
+	default y
+	bool "Enable full-sized data structures for core" if EMBEDDED
+	help
+	  Disabling this option reduces the size of miscellaneous core
+	  kernel data structures.
+
 config FUTEX
 	bool "Enable futex support" if EMBEDDED
 	default y
@@ -357,6 +374,11 @@
 config TINY_SHMEM
 	default !SHMEM
 	bool
+
+config BASE_SMALL
+	int
+	default 0 if BASE_FULL
+	default 1 if !BASE_FULL
 
 menu "Loadable module support"
 
diff -Nru a/init/main.c b/init/main.c
--- a/init/main.c	2005-03-11 12:51:41 -08:00
+++ b/init/main.c	2005-03-11 12:51:41 -08:00
@@ -41,6 +41,7 @@
 #include <linux/kallsyms.h>
 #include <linux/writeback.h>
 #include <linux/cpu.h>
+#include <linux/cpuset.h>
 #include <linux/efi.h>
 #include <linux/unistd.h>
 #include <linux/rmap.h>
@@ -209,6 +210,14 @@
 __setup("debug", debug_kernel);
 __setup("quiet", quiet_kernel);
 
+static int __init loglevel(char *str)
+{
+	get_option(&str, &console_loglevel);
+	return 1;
+}
+
+__setup("loglevel=", loglevel);
+
 /*
  * Unknown boot options get handed to init, unless they look like
  * failed parameters
@@ -497,6 +506,7 @@
 	proc_caches_init();
 	buffer_init();
 	unnamed_dev_init();
+	key_init();
 	security_init();
 	vfs_caches_init(num_physpages);
 	radix_tree_init();
@@ -506,6 +516,8 @@
 #ifdef CONFIG_PROC_FS
 	proc_root_init();
 #endif
+	cpuset_init();
+
 	check_bugs();
 
 	acpi_early_init(); /* before LAPIC and SMP init */
@@ -574,7 +586,6 @@
 	/* drivers will send hotplug events */
 	init_workqueues();
 	usermodehelper_init();
-	key_init();
 	driver_init();
 
 #ifdef CONFIG_SYSCTL
@@ -626,6 +637,10 @@
 {
 	lock_kernel();
 	/*
+	 * init can run on any cpu.
+	 */
+	set_cpus_allowed(current, CPU_MASK_ALL);
+	/*
 	 * Tell the world that we're going to be the grim
 	 * reaper of innocent orphaned children.
 	 *
@@ -643,6 +658,8 @@
 	fixup_cpu_present_map();
 	smp_init();
 	sched_init_smp();
+
+	cpuset_init_smp();
 
 	/*
 	 * Do this before initcalls, because some drivers want to access
diff -Nru a/ipc/compat_mq.c b/ipc/compat_mq.c
--- a/ipc/compat_mq.c	2005-03-11 12:51:42 -08:00
+++ b/ipc/compat_mq.c	2005-03-11 12:51:42 -08:00
@@ -102,20 +102,6 @@
 			u_msg_prio, u_ts);
 }
 
-static int get_compat_sigevent(struct sigevent *event,
-		const struct compat_sigevent __user *u_event)
-{
-	if (verify_area(VERIFY_READ, u_event, sizeof(*u_event)))
-		return -EFAULT;
-
-	return __get_user(event->sigev_value.sival_int,
-			  &u_event->sigev_value.sival_int)
-	     | __get_user(event->sigev_signo, &u_event->sigev_signo)
-	     | __get_user(event->sigev_notify, &u_event->sigev_notify)
-	     | __get_user(event->sigev_notify_thread_id,
-			  &u_event->sigev_notify_thread_id);
-}
-
 asmlinkage long compat_sys_mq_notify(mqd_t mqdes,
 			const struct compat_sigevent __user *u_notification)
 {
diff -Nru a/kernel/Makefile b/kernel/Makefile
--- a/kernel/Makefile	2005-03-11 12:51:41 -08:00
+++ b/kernel/Makefile	2005-03-11 12:51:41 -08:00
@@ -7,7 +7,7 @@
 	    sysctl.o capability.o ptrace.o timer.o user.o \
 	    signal.o sys.o kmod.o workqueue.o pid.o \
 	    rcupdate.o intermodule.o extable.o params.o posix-timers.o \
-	    kthread.o wait.o kfifo.o sys_ni.o
+	    kthread.o wait.o kfifo.o sys_ni.o posix-cpu-timers.o
 
 obj-$(CONFIG_FUTEX) += futex.o
 obj-$(CONFIG_GENERIC_ISA_DMA) += dma.o
@@ -18,6 +18,7 @@
 obj-$(CONFIG_PM) += power/
 obj-$(CONFIG_BSD_PROCESS_ACCT) += acct.o
 obj-$(CONFIG_COMPAT) += compat.o
+obj-$(CONFIG_CPUSETS) += cpuset.o
 obj-$(CONFIG_IKCONFIG) += configs.o
 obj-$(CONFIG_IKCONFIG_PROC) += configs.o
 obj-$(CONFIG_STOP_MACHINE) += stop_machine.o
@@ -26,6 +27,7 @@
 obj-$(CONFIG_KPROBES) += kprobes.o
 obj-$(CONFIG_SYSFS) += ksysfs.o
 obj-$(CONFIG_GENERIC_HARDIRQS) += irq/
+obj-$(CONFIG_SECCOMP) += seccomp.o
 
 ifneq ($(CONFIG_IA64),y)
 # According to Alan Modra <alan@linuxcare.com.au>, the -fno-omit-frame-pointer is
diff -Nru a/kernel/acct.c b/kernel/acct.c
--- a/kernel/acct.c	2005-03-11 12:51:46 -08:00
+++ b/kernel/acct.c	2005-03-11 12:51:46 -08:00
@@ -534,10 +534,8 @@
  * acct_update_integrals
  *    -  update mm integral fields in task_struct
  */
-void acct_update_integrals(void)
+void acct_update_integrals(struct task_struct *tsk)
 {
-	struct task_struct *tsk = current;
-
 	if (likely(tsk->mm)) {
 		long delta = tsk->stime - tsk->acct_stimexpd;
 
diff -Nru a/kernel/compat.c b/kernel/compat.c
--- a/kernel/compat.c	2005-03-11 12:51:46 -08:00
+++ b/kernel/compat.c	2005-03-11 12:51:46 -08:00
@@ -23,6 +23,7 @@
 #include <linux/security.h>
 
 #include <asm/uaccess.h>
+#include <asm/bug.h>
 
 int get_compat_timespec(struct timespec *ts, const struct compat_timespec __user *cts)
 {
@@ -413,6 +414,36 @@
 	}
 }
 
+asmlinkage long compat_sys_waitid(int which, compat_pid_t pid,
+		struct compat_siginfo __user *uinfo, int options,
+		struct compat_rusage __user *uru)
+{
+	siginfo_t info;
+	struct rusage ru;
+	long ret;
+	mm_segment_t old_fs = get_fs();
+
+	memset(&info, 0, sizeof(info));
+
+	set_fs(KERNEL_DS);
+	ret = sys_waitid(which, pid, (siginfo_t __user *)&info, options,
+			 uru ? (struct rusage __user *)&ru : NULL);
+	set_fs(old_fs);
+
+	if ((ret < 0) || (info.si_signo == 0))
+		return ret;
+
+	if (uru) {
+		ret = put_compat_rusage(&ru, uru);
+		if (ret)
+			return ret;
+	}
+
+	BUG_ON(info.si_code & __SI_MASK);
+	info.si_code |= __SI_CHLD;
+	return copy_siginfo_to_user32(uinfo, &info);
+}
+
 static int compat_get_user_cpu_mask(compat_ulong_t __user *user_mask_ptr,
 				    unsigned len, cpumask_t *new_mask)
 {
@@ -598,6 +629,27 @@
 		return -EFAULT;
 	return err;	
 } 
+
+/*
+ * We currently only need the following fields from the sigevent
+ * structure: sigev_value, sigev_signo, sig_notify and (sometimes
+ * sigev_notify_thread_id).  The others are handled in user mode.
+ * We also assume that copying sigev_value.sival_int is sufficient
+ * to keep all the bits of sigev_value.sival_ptr intact.
+ */
+int get_compat_sigevent(struct sigevent *event,
+		const struct compat_sigevent __user *u_event)
+{
+	memset(&event, 0, sizeof(*event));
+	return (!access_ok(VERIFY_READ, u_event, sizeof(*u_event)) ||
+		__get_user(event->sigev_value.sival_int,
+			&u_event->sigev_value.sival_int) ||
+		__get_user(event->sigev_signo, &u_event->sigev_signo) ||
+		__get_user(event->sigev_notify, &u_event->sigev_notify) ||
+		__get_user(event->sigev_notify_thread_id,
+			&u_event->sigev_notify_thread_id))
+		? -EFAULT : 0;
+}
 
 /* timer_create is architecture specific because it needs sigevent conversion */
 
diff -Nru a/kernel/cpuset.c b/kernel/cpuset.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/kernel/cpuset.c	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,1534 @@
+/*
+ *  kernel/cpuset.c
+ *
+ *  Processor and Memory placement constraints for sets of tasks.
+ *
+ *  Copyright (C) 2003 BULL SA.
+ *  Copyright (C) 2004 Silicon Graphics, Inc.
+ *
+ *  Portions derived from Patrick Mochel's sysfs code.
+ *  sysfs is Copyright (c) 2001-3 Patrick Mochel
+ *  Portions Copyright (c) 2004 Silicon Graphics, Inc.
+ *
+ *  2003-10-10 Written by Simon Derr <simon.derr@bull.net>
+ *  2003-10-22 Updates by Stephen Hemminger.
+ *  2004 May-July Rework by Paul Jackson <pj@sgi.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 the Linux
+ *  distribution for more details.
+ */
+
+#include <linux/config.h>
+#include <linux/cpu.h>
+#include <linux/cpumask.h>
+#include <linux/cpuset.h>
+#include <linux/err.h>
+#include <linux/errno.h>
+#include <linux/file.h>
+#include <linux/fs.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/kmod.h>
+#include <linux/list.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/mount.h>
+#include <linux/namei.h>
+#include <linux/pagemap.h>
+#include <linux/proc_fs.h>
+#include <linux/sched.h>
+#include <linux/seq_file.h>
+#include <linux/slab.h>
+#include <linux/smp_lock.h>
+#include <linux/spinlock.h>
+#include <linux/stat.h>
+#include <linux/string.h>
+#include <linux/time.h>
+#include <linux/backing-dev.h>
+#include <linux/sort.h>
+
+#include <asm/uaccess.h>
+#include <asm/atomic.h>
+#include <asm/semaphore.h>
+
+#define CPUSET_SUPER_MAGIC 		0x27e0eb
+
+struct cpuset {
+	unsigned long flags;		/* "unsigned long" so bitops work */
+	cpumask_t cpus_allowed;		/* CPUs allowed to tasks in cpuset */
+	nodemask_t mems_allowed;	/* Memory Nodes allowed to tasks */
+
+	atomic_t count;			/* count tasks using this cpuset */
+
+	/*
+	 * We link our 'sibling' struct into our parents 'children'.
+	 * Our children link their 'sibling' into our 'children'.
+	 */
+	struct list_head sibling;	/* my parents children */
+	struct list_head children;	/* my children */
+
+	struct cpuset *parent;		/* my parent */
+	struct dentry *dentry;		/* cpuset fs entry */
+
+	/*
+	 * Copy of global cpuset_mems_generation as of the most
+	 * recent time this cpuset changed its mems_allowed.
+	 */
+	 int mems_generation;
+};
+
+/* bits in struct cpuset flags field */
+typedef enum {
+	CS_CPU_EXCLUSIVE,
+	CS_MEM_EXCLUSIVE,
+	CS_REMOVED,
+	CS_NOTIFY_ON_RELEASE
+} cpuset_flagbits_t;
+
+/* convenient tests for these bits */
+static inline int is_cpu_exclusive(const struct cpuset *cs)
+{
+	return !!test_bit(CS_CPU_EXCLUSIVE, &cs->flags);
+}
+
+static inline int is_mem_exclusive(const struct cpuset *cs)
+{
+	return !!test_bit(CS_MEM_EXCLUSIVE, &cs->flags);
+}
+
+static inline int is_removed(const struct cpuset *cs)
+{
+	return !!test_bit(CS_REMOVED, &cs->flags);
+}
+
+static inline int notify_on_release(const struct cpuset *cs)
+{
+	return !!test_bit(CS_NOTIFY_ON_RELEASE, &cs->flags);
+}
+
+/*
+ * Increment this atomic integer everytime any cpuset changes its
+ * mems_allowed value.  Users of cpusets can track this generation
+ * number, and avoid having to lock and reload mems_allowed unless
+ * the cpuset they're using changes generation.
+ *
+ * A single, global generation is needed because attach_task() could
+ * reattach a task to a different cpuset, which must not have its
+ * generation numbers aliased with those of that tasks previous cpuset.
+ *
+ * Generations are needed for mems_allowed because one task cannot
+ * modify anothers memory placement.  So we must enable every task,
+ * on every visit to __alloc_pages(), to efficiently check whether
+ * its current->cpuset->mems_allowed has changed, requiring an update
+ * of its current->mems_allowed.
+ */
+static atomic_t cpuset_mems_generation = ATOMIC_INIT(1);
+
+static struct cpuset top_cpuset = {
+	.flags = ((1 << CS_CPU_EXCLUSIVE) | (1 << CS_MEM_EXCLUSIVE)),
+	.cpus_allowed = CPU_MASK_ALL,
+	.mems_allowed = NODE_MASK_ALL,
+	.count = ATOMIC_INIT(0),
+	.sibling = LIST_HEAD_INIT(top_cpuset.sibling),
+	.children = LIST_HEAD_INIT(top_cpuset.children),
+	.parent = NULL,
+	.dentry = NULL,
+	.mems_generation = 0,
+};
+
+static struct vfsmount *cpuset_mount;
+static struct super_block *cpuset_sb = NULL;
+
+/*
+ * cpuset_sem should be held by anyone who is depending on the children
+ * or sibling lists of any cpuset, or performing non-atomic operations
+ * on the flags or *_allowed values of a cpuset, such as raising the
+ * CS_REMOVED flag bit iff it is not already raised, or reading and
+ * conditionally modifying the *_allowed values.  One kernel global
+ * cpuset semaphore should be sufficient - these things don't change
+ * that much.
+ *
+ * The code that modifies cpusets holds cpuset_sem across the entire
+ * operation, from cpuset_common_file_write() down, single threading
+ * all cpuset modifications (except for counter manipulations from
+ * fork and exit) across the system.  This presumes that cpuset
+ * modifications are rare - better kept simple and safe, even if slow.
+ *
+ * The code that reads cpusets, such as in cpuset_common_file_read()
+ * and below, only holds cpuset_sem across small pieces of code, such
+ * as when reading out possibly multi-word cpumasks and nodemasks, as
+ * the risks are less, and the desire for performance a little greater.
+ * The proc_cpuset_show() routine needs to hold cpuset_sem to insure
+ * that no cs->dentry is NULL, as it walks up the cpuset tree to root.
+ *
+ * The hooks from fork and exit, cpuset_fork() and cpuset_exit(), don't
+ * (usually) grab cpuset_sem.  These are the two most performance
+ * critical pieces of code here.  The exception occurs on exit(),
+ * if the last task using a cpuset exits, and the cpuset was marked
+ * notify_on_release.  In that case, the cpuset_sem is taken, the
+ * path to the released cpuset calculated, and a usermode call made
+ * to /sbin/cpuset_release_agent with the name of the cpuset (path
+ * relative to the root of cpuset file system) as the argument.
+ *
+ * A cpuset can only be deleted if both its 'count' of using tasks is
+ * zero, and its list of 'children' cpusets is empty.  Since all tasks
+ * in the system use _some_ cpuset, and since there is always at least
+ * one task in the system (init, pid == 1), therefore, top_cpuset
+ * always has either children cpusets and/or using tasks.  So no need
+ * for any special hack to ensure that top_cpuset cannot be deleted.
+ */
+
+static DECLARE_MUTEX(cpuset_sem);
+
+/*
+ * A couple of forward declarations required, due to cyclic reference loop:
+ *  cpuset_mkdir -> cpuset_create -> cpuset_populate_dir -> cpuset_add_file
+ *  -> cpuset_create_file -> cpuset_dir_inode_operations -> cpuset_mkdir.
+ */
+
+static int cpuset_mkdir(struct inode *dir, struct dentry *dentry, int mode);
+static int cpuset_rmdir(struct inode *unused_dir, struct dentry *dentry);
+
+static struct backing_dev_info cpuset_backing_dev_info = {
+	.ra_pages = 0,		/* No readahead */
+	.memory_backed = 1,	/* Does not contribute to dirty memory */
+};
+
+static struct inode *cpuset_new_inode(mode_t mode)
+{
+	struct inode *inode = new_inode(cpuset_sb);
+
+	if (inode) {
+		inode->i_mode = mode;
+		inode->i_uid = current->fsuid;
+		inode->i_gid = current->fsgid;
+		inode->i_blksize = PAGE_CACHE_SIZE;
+		inode->i_blocks = 0;
+		inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+		inode->i_mapping->backing_dev_info = &cpuset_backing_dev_info;
+	}
+	return inode;
+}
+
+static void cpuset_diput(struct dentry *dentry, struct inode *inode)
+{
+	/* is dentry a directory ? if so, kfree() associated cpuset */
+	if (S_ISDIR(inode->i_mode)) {
+		struct cpuset *cs = dentry->d_fsdata;
+		BUG_ON(!(is_removed(cs)));
+		kfree(cs);
+	}
+	iput(inode);
+}
+
+static struct dentry_operations cpuset_dops = {
+	.d_iput = cpuset_diput,
+};
+
+static struct dentry *cpuset_get_dentry(struct dentry *parent, const char *name)
+{
+	struct qstr qstr;
+	struct dentry *d;
+
+	qstr.name = name;
+	qstr.len = strlen(name);
+	qstr.hash = full_name_hash(name, qstr.len);
+	d = lookup_hash(&qstr, parent);
+	if (!IS_ERR(d))
+		d->d_op = &cpuset_dops;
+	return d;
+}
+
+static void remove_dir(struct dentry *d)
+{
+	struct dentry *parent = dget(d->d_parent);
+
+	d_delete(d);
+	simple_rmdir(parent->d_inode, d);
+	dput(parent);
+}
+
+/*
+ * NOTE : the dentry must have been dget()'ed
+ */
+static void cpuset_d_remove_dir(struct dentry *dentry)
+{
+	struct list_head *node;
+
+	spin_lock(&dcache_lock);
+	node = dentry->d_subdirs.next;
+	while (node != &dentry->d_subdirs) {
+		struct dentry *d = list_entry(node, struct dentry, d_child);
+		list_del_init(node);
+		if (d->d_inode) {
+			d = dget_locked(d);
+			spin_unlock(&dcache_lock);
+			d_delete(d);
+			simple_unlink(dentry->d_inode, d);
+			dput(d);
+			spin_lock(&dcache_lock);
+		}
+		node = dentry->d_subdirs.next;
+	}
+	list_del_init(&dentry->d_child);
+	spin_unlock(&dcache_lock);
+	remove_dir(dentry);
+}
+
+static struct super_operations cpuset_ops = {
+	.statfs = simple_statfs,
+	.drop_inode = generic_delete_inode,
+};
+
+static int cpuset_fill_super(struct super_block *sb, void *unused_data,
+							int unused_silent)
+{
+	struct inode *inode;
+	struct dentry *root;
+
+	sb->s_blocksize = PAGE_CACHE_SIZE;
+	sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
+	sb->s_magic = CPUSET_SUPER_MAGIC;
+	sb->s_op = &cpuset_ops;
+	cpuset_sb = sb;
+
+	inode = cpuset_new_inode(S_IFDIR | S_IRUGO | S_IXUGO | S_IWUSR);
+	if (inode) {
+		inode->i_op = &simple_dir_inode_operations;
+		inode->i_fop = &simple_dir_operations;
+		/* directories start off with i_nlink == 2 (for "." entry) */
+		inode->i_nlink++;
+	} else {
+		return -ENOMEM;
+	}
+
+	root = d_alloc_root(inode);
+	if (!root) {
+		iput(inode);
+		return -ENOMEM;
+	}
+	sb->s_root = root;
+	return 0;
+}
+
+static struct super_block *cpuset_get_sb(struct file_system_type *fs_type,
+					int flags, const char *unused_dev_name,
+					void *data)
+{
+	return get_sb_single(fs_type, flags, data, cpuset_fill_super);
+}
+
+static struct file_system_type cpuset_fs_type = {
+	.name = "cpuset",
+	.get_sb = cpuset_get_sb,
+	.kill_sb = kill_litter_super,
+};
+
+/* struct cftype:
+ *
+ * The files in the cpuset filesystem mostly have a very simple read/write
+ * handling, some common function will take care of it. Nevertheless some cases
+ * (read tasks) are special and therefore I define this structure for every
+ * kind of file.
+ *
+ *
+ * When reading/writing to a file:
+ *	- the cpuset to use in file->f_dentry->d_parent->d_fsdata
+ *	- the 'cftype' of the file is file->f_dentry->d_fsdata
+ */
+
+struct cftype {
+	char *name;
+	int private;
+	int (*open) (struct inode *inode, struct file *file);
+	ssize_t (*read) (struct file *file, char __user *buf, size_t nbytes,
+							loff_t *ppos);
+	int (*write) (struct file *file, const char *buf, size_t nbytes,
+							loff_t *ppos);
+	int (*release) (struct inode *inode, struct file *file);
+};
+
+static inline struct cpuset *__d_cs(struct dentry *dentry)
+{
+	return dentry->d_fsdata;
+}
+
+static inline struct cftype *__d_cft(struct dentry *dentry)
+{
+	return dentry->d_fsdata;
+}
+
+/*
+ * Call with cpuset_sem held.  Writes path of cpuset into buf.
+ * Returns 0 on success, -errno on error.
+ */
+
+static int cpuset_path(const struct cpuset *cs, char *buf, int buflen)
+{
+	char *start;
+
+	start = buf + buflen;
+
+	*--start = '\0';
+	for (;;) {
+		int len = cs->dentry->d_name.len;
+		if ((start -= len) < buf)
+			return -ENAMETOOLONG;
+		memcpy(start, cs->dentry->d_name.name, len);
+		cs = cs->parent;
+		if (!cs)
+			break;
+		if (!cs->parent)
+			continue;
+		if (--start < buf)
+			return -ENAMETOOLONG;
+		*start = '/';
+	}
+	memmove(buf, start, buf + buflen - start);
+	return 0;
+}
+
+/*
+ * Notify userspace when a cpuset is released, by running
+ * /sbin/cpuset_release_agent with the name of the cpuset (path
+ * relative to the root of cpuset file system) as the argument.
+ *
+ * Most likely, this user command will try to rmdir this cpuset.
+ *
+ * This races with the possibility that some other task will be
+ * attached to this cpuset before it is removed, or that some other
+ * user task will 'mkdir' a child cpuset of this cpuset.  That's ok.
+ * The presumed 'rmdir' will fail quietly if this cpuset is no longer
+ * unused, and this cpuset will be reprieved from its death sentence,
+ * to continue to serve a useful existence.  Next time it's released,
+ * we will get notified again, if it still has 'notify_on_release' set.
+ *
+ * Note final arg to call_usermodehelper() is 0 - that means
+ * don't wait.  Since we are holding the global cpuset_sem here,
+ * and we are asking another thread (started from keventd) to rmdir a
+ * cpuset, we can't wait - or we'd deadlock with the removing thread
+ * on cpuset_sem.
+ */
+
+static int cpuset_release_agent(char *cpuset_str)
+{
+	char *argv[3], *envp[3];
+	int i;
+
+	i = 0;
+	argv[i++] = "/sbin/cpuset_release_agent";
+	argv[i++] = cpuset_str;
+	argv[i] = NULL;
+
+	i = 0;
+	/* minimal command environment */
+	envp[i++] = "HOME=/";
+	envp[i++] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
+	envp[i] = NULL;
+
+	return call_usermodehelper(argv[0], argv, envp, 0);
+}
+
+/*
+ * Either cs->count of using tasks transitioned to zero, or the
+ * cs->children list of child cpusets just became empty.  If this
+ * cs is notify_on_release() and now both the user count is zero and
+ * the list of children is empty, send notice to user land.
+ */
+
+static void check_for_release(struct cpuset *cs)
+{
+	if (notify_on_release(cs) && atomic_read(&cs->count) == 0 &&
+	    list_empty(&cs->children)) {
+		char *buf;
+
+		buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
+		if (!buf)
+			return;
+		if (cpuset_path(cs, buf, PAGE_SIZE) < 0)
+			goto out;
+		cpuset_release_agent(buf);
+out:
+		kfree(buf);
+	}
+}
+
+/*
+ * Return in *pmask the portion of a cpusets's cpus_allowed that
+ * are online.  If none are online, walk up the cpuset hierarchy
+ * until we find one that does have some online cpus.  If we get
+ * all the way to the top and still haven't found any online cpus,
+ * return cpu_online_map.  Or if passed a NULL cs from an exit'ing
+ * task, return cpu_online_map.
+ *
+ * One way or another, we guarantee to return some non-empty subset
+ * of cpu_online_map.
+ *
+ * Call with cpuset_sem held.
+ */
+
+static void guarantee_online_cpus(const struct cpuset *cs, cpumask_t *pmask)
+{
+	while (cs && !cpus_intersects(cs->cpus_allowed, cpu_online_map))
+		cs = cs->parent;
+	if (cs)
+		cpus_and(*pmask, cs->cpus_allowed, cpu_online_map);
+	else
+		*pmask = cpu_online_map;
+	BUG_ON(!cpus_intersects(*pmask, cpu_online_map));
+}
+
+/*
+ * Return in *pmask the portion of a cpusets's mems_allowed that
+ * are online.  If none are online, walk up the cpuset hierarchy
+ * until we find one that does have some online mems.  If we get
+ * all the way to the top and still haven't found any online mems,
+ * return node_online_map.
+ *
+ * One way or another, we guarantee to return some non-empty subset
+ * of node_online_map.
+ *
+ * Call with cpuset_sem held.
+ */
+
+static void guarantee_online_mems(const struct cpuset *cs, nodemask_t *pmask)
+{
+	while (cs && !nodes_intersects(cs->mems_allowed, node_online_map))
+		cs = cs->parent;
+	if (cs)
+		nodes_and(*pmask, cs->mems_allowed, node_online_map);
+	else
+		*pmask = node_online_map;
+	BUG_ON(!nodes_intersects(*pmask, node_online_map));
+}
+
+/*
+ * is_cpuset_subset(p, q) - Is cpuset p a subset of cpuset q?
+ *
+ * One cpuset is a subset of another if all its allowed CPUs and
+ * Memory Nodes are a subset of the other, and its exclusive flags
+ * are only set if the other's are set.
+ */
+
+static int is_cpuset_subset(const struct cpuset *p, const struct cpuset *q)
+{
+	return	cpus_subset(p->cpus_allowed, q->cpus_allowed) &&
+		nodes_subset(p->mems_allowed, q->mems_allowed) &&
+		is_cpu_exclusive(p) <= is_cpu_exclusive(q) &&
+		is_mem_exclusive(p) <= is_mem_exclusive(q);
+}
+
+/*
+ * validate_change() - Used to validate that any proposed cpuset change
+ *		       follows the structural rules for cpusets.
+ *
+ * If we replaced the flag and mask values of the current cpuset
+ * (cur) with those values in the trial cpuset (trial), would
+ * our various subset and exclusive rules still be valid?  Presumes
+ * cpuset_sem held.
+ *
+ * 'cur' is the address of an actual, in-use cpuset.  Operations
+ * such as list traversal that depend on the actual address of the
+ * cpuset in the list must use cur below, not trial.
+ *
+ * 'trial' is the address of bulk structure copy of cur, with
+ * perhaps one or more of the fields cpus_allowed, mems_allowed,
+ * or flags changed to new, trial values.
+ *
+ * Return 0 if valid, -errno if not.
+ */
+
+static int validate_change(const struct cpuset *cur, const struct cpuset *trial)
+{
+	struct cpuset *c, *par;
+
+	/* Each of our child cpusets must be a subset of us */
+	list_for_each_entry(c, &cur->children, sibling) {
+		if (!is_cpuset_subset(c, trial))
+			return -EBUSY;
+	}
+
+	/* Remaining checks don't apply to root cpuset */
+	if ((par = cur->parent) == NULL)
+		return 0;
+
+	/* We must be a subset of our parent cpuset */
+	if (!is_cpuset_subset(trial, par))
+		return -EACCES;
+
+	/* If either I or some sibling (!= me) is exclusive, we can't overlap */
+	list_for_each_entry(c, &par->children, sibling) {
+		if ((is_cpu_exclusive(trial) || is_cpu_exclusive(c)) &&
+		    c != cur &&
+		    cpus_intersects(trial->cpus_allowed, c->cpus_allowed))
+			return -EINVAL;
+		if ((is_mem_exclusive(trial) || is_mem_exclusive(c)) &&
+		    c != cur &&
+		    nodes_intersects(trial->mems_allowed, c->mems_allowed))
+			return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int update_cpumask(struct cpuset *cs, char *buf)
+{
+	struct cpuset trialcs;
+	int retval;
+
+	trialcs = *cs;
+	retval = cpulist_parse(buf, trialcs.cpus_allowed);
+	if (retval < 0)
+		return retval;
+	cpus_and(trialcs.cpus_allowed, trialcs.cpus_allowed, cpu_online_map);
+	if (cpus_empty(trialcs.cpus_allowed))
+		return -ENOSPC;
+	retval = validate_change(cs, &trialcs);
+	if (retval == 0)
+		cs->cpus_allowed = trialcs.cpus_allowed;
+	return retval;
+}
+
+static int update_nodemask(struct cpuset *cs, char *buf)
+{
+	struct cpuset trialcs;
+	int retval;
+
+	trialcs = *cs;
+	retval = nodelist_parse(buf, trialcs.mems_allowed);
+	if (retval < 0)
+		return retval;
+	nodes_and(trialcs.mems_allowed, trialcs.mems_allowed, node_online_map);
+	if (nodes_empty(trialcs.mems_allowed))
+		return -ENOSPC;
+	retval = validate_change(cs, &trialcs);
+	if (retval == 0) {
+		cs->mems_allowed = trialcs.mems_allowed;
+		atomic_inc(&cpuset_mems_generation);
+		cs->mems_generation = atomic_read(&cpuset_mems_generation);
+	}
+	return retval;
+}
+
+/*
+ * update_flag - read a 0 or a 1 in a file and update associated flag
+ * bit:	the bit to update (CS_CPU_EXCLUSIVE, CS_MEM_EXCLUSIVE,
+ *						CS_NOTIFY_ON_RELEASE)
+ * cs:	the cpuset to update
+ * buf:	the buffer where we read the 0 or 1
+ */
+
+static int update_flag(cpuset_flagbits_t bit, struct cpuset *cs, char *buf)
+{
+	int turning_on;
+	struct cpuset trialcs;
+	int err;
+
+	turning_on = (simple_strtoul(buf, NULL, 10) != 0);
+
+	trialcs = *cs;
+	if (turning_on)
+		set_bit(bit, &trialcs.flags);
+	else
+		clear_bit(bit, &trialcs.flags);
+
+	err = validate_change(cs, &trialcs);
+	if (err == 0) {
+		if (turning_on)
+			set_bit(bit, &cs->flags);
+		else
+			clear_bit(bit, &cs->flags);
+	}
+	return err;
+}
+
+static int attach_task(struct cpuset *cs, char *buf)
+{
+	pid_t pid;
+	struct task_struct *tsk;
+	struct cpuset *oldcs;
+	cpumask_t cpus;
+
+	if (sscanf(buf, "%d", &pid) != 1)
+		return -EIO;
+	if (cpus_empty(cs->cpus_allowed) || nodes_empty(cs->mems_allowed))
+		return -ENOSPC;
+
+	if (pid) {
+		read_lock(&tasklist_lock);
+
+		tsk = find_task_by_pid(pid);
+		if (!tsk) {
+			read_unlock(&tasklist_lock);
+			return -ESRCH;
+		}
+
+		get_task_struct(tsk);
+		read_unlock(&tasklist_lock);
+
+		if ((current->euid) && (current->euid != tsk->uid)
+		    && (current->euid != tsk->suid)) {
+			put_task_struct(tsk);
+			return -EACCES;
+		}
+	} else {
+		tsk = current;
+		get_task_struct(tsk);
+	}
+
+	task_lock(tsk);
+	oldcs = tsk->cpuset;
+	if (!oldcs) {
+		task_unlock(tsk);
+		put_task_struct(tsk);
+		return -ESRCH;
+	}
+	atomic_inc(&cs->count);
+	tsk->cpuset = cs;
+	task_unlock(tsk);
+
+	guarantee_online_cpus(cs, &cpus);
+	set_cpus_allowed(tsk, cpus);
+
+	put_task_struct(tsk);
+	if (atomic_dec_and_test(&oldcs->count))
+		check_for_release(oldcs);
+	return 0;
+}
+
+/* The various types of files and directories in a cpuset file system */
+
+typedef enum {
+	FILE_ROOT,
+	FILE_DIR,
+	FILE_CPULIST,
+	FILE_MEMLIST,
+	FILE_CPU_EXCLUSIVE,
+	FILE_MEM_EXCLUSIVE,
+	FILE_NOTIFY_ON_RELEASE,
+	FILE_TASKLIST,
+} cpuset_filetype_t;
+
+static ssize_t cpuset_common_file_write(struct file *file, const char *userbuf,
+					size_t nbytes, loff_t *unused_ppos)
+{
+	struct cpuset *cs = __d_cs(file->f_dentry->d_parent);
+	struct cftype *cft = __d_cft(file->f_dentry);
+	cpuset_filetype_t type = cft->private;
+	char *buffer;
+	int retval = 0;
+
+	/* Crude upper limit on largest legitimate cpulist user might write. */
+	if (nbytes > 100 + 6 * NR_CPUS)
+		return -E2BIG;
+
+	/* +1 for nul-terminator */
+	if ((buffer = kmalloc(nbytes + 1, GFP_KERNEL)) == 0)
+		return -ENOMEM;
+
+	if (copy_from_user(buffer, userbuf, nbytes)) {
+		retval = -EFAULT;
+		goto out1;
+	}
+	buffer[nbytes] = 0;	/* nul-terminate */
+
+	down(&cpuset_sem);
+
+	if (is_removed(cs)) {
+		retval = -ENODEV;
+		goto out2;
+	}
+
+	switch (type) {
+	case FILE_CPULIST:
+		retval = update_cpumask(cs, buffer);
+		break;
+	case FILE_MEMLIST:
+		retval = update_nodemask(cs, buffer);
+		break;
+	case FILE_CPU_EXCLUSIVE:
+		retval = update_flag(CS_CPU_EXCLUSIVE, cs, buffer);
+		break;
+	case FILE_MEM_EXCLUSIVE:
+		retval = update_flag(CS_MEM_EXCLUSIVE, cs, buffer);
+		break;
+	case FILE_NOTIFY_ON_RELEASE:
+		retval = update_flag(CS_NOTIFY_ON_RELEASE, cs, buffer);
+		break;
+	case FILE_TASKLIST:
+		retval = attach_task(cs, buffer);
+		break;
+	default:
+		retval = -EINVAL;
+		goto out2;
+	}
+
+	if (retval == 0)
+		retval = nbytes;
+out2:
+	up(&cpuset_sem);
+out1:
+	kfree(buffer);
+	return retval;
+}
+
+static ssize_t cpuset_file_write(struct file *file, const char *buf,
+						size_t nbytes, loff_t *ppos)
+{
+	ssize_t retval = 0;
+	struct cftype *cft = __d_cft(file->f_dentry);
+	if (!cft)
+		return -ENODEV;
+
+	/* special function ? */
+	if (cft->write)
+		retval = cft->write(file, buf, nbytes, ppos);
+	else
+		retval = cpuset_common_file_write(file, buf, nbytes, ppos);
+
+	return retval;
+}
+
+/*
+ * These ascii lists should be read in a single call, by using a user
+ * buffer large enough to hold the entire map.  If read in smaller
+ * chunks, there is no guarantee of atomicity.  Since the display format
+ * used, list of ranges of sequential numbers, is variable length,
+ * and since these maps can change value dynamically, one could read
+ * gibberish by doing partial reads while a list was changing.
+ * A single large read to a buffer that crosses a page boundary is
+ * ok, because the result being copied to user land is not recomputed
+ * across a page fault.
+ */
+
+static int cpuset_sprintf_cpulist(char *page, struct cpuset *cs)
+{
+	cpumask_t mask;
+
+	down(&cpuset_sem);
+	mask = cs->cpus_allowed;
+	up(&cpuset_sem);
+
+	return cpulist_scnprintf(page, PAGE_SIZE, mask);
+}
+
+static int cpuset_sprintf_memlist(char *page, struct cpuset *cs)
+{
+	nodemask_t mask;
+
+	down(&cpuset_sem);
+	mask = cs->mems_allowed;
+	up(&cpuset_sem);
+
+	return nodelist_scnprintf(page, PAGE_SIZE, mask);
+}
+
+static ssize_t cpuset_common_file_read(struct file *file, char __user *buf,
+				size_t nbytes, loff_t *ppos)
+{
+	struct cftype *cft = __d_cft(file->f_dentry);
+	struct cpuset *cs = __d_cs(file->f_dentry->d_parent);
+	cpuset_filetype_t type = cft->private;
+	char *page;
+	ssize_t retval = 0;
+	char *s;
+	char *start;
+	size_t n;
+
+	if (!(page = (char *)__get_free_page(GFP_KERNEL)))
+		return -ENOMEM;
+
+	s = page;
+
+	switch (type) {
+	case FILE_CPULIST:
+		s += cpuset_sprintf_cpulist(s, cs);
+		break;
+	case FILE_MEMLIST:
+		s += cpuset_sprintf_memlist(s, cs);
+		break;
+	case FILE_CPU_EXCLUSIVE:
+		*s++ = is_cpu_exclusive(cs) ? '1' : '0';
+		break;
+	case FILE_MEM_EXCLUSIVE:
+		*s++ = is_mem_exclusive(cs) ? '1' : '0';
+		break;
+	case FILE_NOTIFY_ON_RELEASE:
+		*s++ = notify_on_release(cs) ? '1' : '0';
+		break;
+	default:
+		retval = -EINVAL;
+		goto out;
+	}
+	*s++ = '\n';
+	*s = '\0';
+
+	start = page + *ppos;
+	n = s - start;
+	retval = n - copy_to_user(buf, start, min(n, nbytes));
+	*ppos += retval;
+out:
+	free_page((unsigned long)page);
+	return retval;
+}
+
+static ssize_t cpuset_file_read(struct file *file, char *buf, size_t nbytes,
+								loff_t *ppos)
+{
+	ssize_t retval = 0;
+	struct cftype *cft = __d_cft(file->f_dentry);
+	if (!cft)
+		return -ENODEV;
+
+	/* special function ? */
+	if (cft->read)
+		retval = cft->read(file, buf, nbytes, ppos);
+	else
+		retval = cpuset_common_file_read(file, buf, nbytes, ppos);
+
+	return retval;
+}
+
+static int cpuset_file_open(struct inode *inode, struct file *file)
+{
+	int err;
+	struct cftype *cft;
+
+	err = generic_file_open(inode, file);
+	if (err)
+		return err;
+
+	cft = __d_cft(file->f_dentry);
+	if (!cft)
+		return -ENODEV;
+	if (cft->open)
+		err = cft->open(inode, file);
+	else
+		err = 0;
+
+	return err;
+}
+
+static int cpuset_file_release(struct inode *inode, struct file *file)
+{
+	struct cftype *cft = __d_cft(file->f_dentry);
+	if (cft->release)
+		return cft->release(inode, file);
+	return 0;
+}
+
+static struct file_operations cpuset_file_operations = {
+	.read = cpuset_file_read,
+	.write = cpuset_file_write,
+	.llseek = generic_file_llseek,
+	.open = cpuset_file_open,
+	.release = cpuset_file_release,
+};
+
+static struct inode_operations cpuset_dir_inode_operations = {
+	.lookup = simple_lookup,
+	.mkdir = cpuset_mkdir,
+	.rmdir = cpuset_rmdir,
+};
+
+static int cpuset_create_file(struct dentry *dentry, int mode)
+{
+	struct inode *inode;
+
+	if (!dentry)
+		return -ENOENT;
+	if (dentry->d_inode)
+		return -EEXIST;
+
+	inode = cpuset_new_inode(mode);
+	if (!inode)
+		return -ENOMEM;
+
+	if (S_ISDIR(mode)) {
+		inode->i_op = &cpuset_dir_inode_operations;
+		inode->i_fop = &simple_dir_operations;
+
+		/* start off with i_nlink == 2 (for "." entry) */
+		inode->i_nlink++;
+	} else if (S_ISREG(mode)) {
+		inode->i_size = 0;
+		inode->i_fop = &cpuset_file_operations;
+	}
+
+	d_instantiate(dentry, inode);
+	dget(dentry);	/* Extra count - pin the dentry in core */
+	return 0;
+}
+
+/*
+ *	cpuset_create_dir - create a directory for an object.
+ *	cs: 	the cpuset we create the directory for.
+ *		It must have a valid ->parent field
+ *		And we are going to fill its ->dentry field.
+ *	name:	The name to give to the cpuset directory. Will be copied.
+ *	mode:	mode to set on new directory.
+ */
+
+static int cpuset_create_dir(struct cpuset *cs, const char *name, int mode)
+{
+	struct dentry *dentry = NULL;
+	struct dentry *parent;
+	int error = 0;
+
+	parent = cs->parent->dentry;
+	dentry = cpuset_get_dentry(parent, name);
+	if (IS_ERR(dentry))
+		return PTR_ERR(dentry);
+	error = cpuset_create_file(dentry, S_IFDIR | mode);
+	if (!error) {
+		dentry->d_fsdata = cs;
+		parent->d_inode->i_nlink++;
+		cs->dentry = dentry;
+	}
+	dput(dentry);
+
+	return error;
+}
+
+static int cpuset_add_file(struct dentry *dir, const struct cftype *cft)
+{
+	struct dentry *dentry;
+	int error;
+
+	down(&dir->d_inode->i_sem);
+	dentry = cpuset_get_dentry(dir, cft->name);
+	if (!IS_ERR(dentry)) {
+		error = cpuset_create_file(dentry, 0644 | S_IFREG);
+		if (!error)
+			dentry->d_fsdata = (void *)cft;
+		dput(dentry);
+	} else
+		error = PTR_ERR(dentry);
+	up(&dir->d_inode->i_sem);
+	return error;
+}
+
+/*
+ * Stuff for reading the 'tasks' file.
+ *
+ * Reading this file can return large amounts of data if a cpuset has
+ * *lots* of attached tasks. So it may need several calls to read(),
+ * but we cannot guarantee that the information we produce is correct
+ * unless we produce it entirely atomically.
+ *
+ * Upon tasks file open(), a struct ctr_struct is allocated, that
+ * will have a pointer to an array (also allocated here).  The struct
+ * ctr_struct * is stored in file->private_data.  Its resources will
+ * be freed by release() when the file is closed.  The array is used
+ * to sprintf the PIDs and then used by read().
+ */
+
+/* cpusets_tasks_read array */
+
+struct ctr_struct {
+	char *buf;
+	int bufsz;
+};
+
+/*
+ * Load into 'pidarray' up to 'npids' of the tasks using cpuset 'cs'.
+ * Return actual number of pids loaded.
+ */
+static inline int pid_array_load(pid_t *pidarray, int npids, struct cpuset *cs)
+{
+	int n = 0;
+	struct task_struct *g, *p;
+
+	read_lock(&tasklist_lock);
+
+	do_each_thread(g, p) {
+		if (p->cpuset == cs) {
+			pidarray[n++] = p->pid;
+			if (unlikely(n == npids))
+				goto array_full;
+		}
+	} while_each_thread(g, p);
+
+array_full:
+	read_unlock(&tasklist_lock);
+	return n;
+}
+
+static int cmppid(const void *a, const void *b)
+{
+	return *(pid_t *)a - *(pid_t *)b;
+}
+
+/*
+ * Convert array 'a' of 'npids' pid_t's to a string of newline separated
+ * decimal pids in 'buf'.  Don't write more than 'sz' chars, but return
+ * count 'cnt' of how many chars would be written if buf were large enough.
+ */
+static int pid_array_to_buf(char *buf, int sz, pid_t *a, int npids)
+{
+	int cnt = 0;
+	int i;
+
+	for (i = 0; i < npids; i++)
+		cnt += snprintf(buf + cnt, max(sz - cnt, 0), "%d\n", a[i]);
+	return cnt;
+}
+
+static int cpuset_tasks_open(struct inode *unused, struct file *file)
+{
+	struct cpuset *cs = __d_cs(file->f_dentry->d_parent);
+	struct ctr_struct *ctr;
+	pid_t *pidarray;
+	int npids;
+	char c;
+
+	if (!(file->f_mode & FMODE_READ))
+		return 0;
+
+	ctr = kmalloc(sizeof(*ctr), GFP_KERNEL);
+	if (!ctr)
+		goto err0;
+
+	/*
+	 * If cpuset gets more users after we read count, we won't have
+	 * enough space - tough.  This race is indistinguishable to the
+	 * caller from the case that the additional cpuset users didn't
+	 * show up until sometime later on.
+	 */
+	npids = atomic_read(&cs->count);
+	pidarray = kmalloc(npids * sizeof(pid_t), GFP_KERNEL);
+	if (!pidarray)
+		goto err1;
+
+	npids = pid_array_load(pidarray, npids, cs);
+	sort(pidarray, npids, sizeof(pid_t), cmppid, NULL);
+
+	/* Call pid_array_to_buf() twice, first just to get bufsz */
+	ctr->bufsz = pid_array_to_buf(&c, sizeof(c), pidarray, npids) + 1;
+	ctr->buf = kmalloc(ctr->bufsz, GFP_KERNEL);
+	if (!ctr->buf)
+		goto err2;
+	ctr->bufsz = pid_array_to_buf(ctr->buf, ctr->bufsz, pidarray, npids);
+
+	kfree(pidarray);
+	file->private_data = ctr;
+	return 0;
+
+err2:
+	kfree(pidarray);
+err1:
+	kfree(ctr);
+err0:
+	return -ENOMEM;
+}
+
+static ssize_t cpuset_tasks_read(struct file *file, char __user *buf,
+						size_t nbytes, loff_t *ppos)
+{
+	struct ctr_struct *ctr = file->private_data;
+
+	if (*ppos + nbytes > ctr->bufsz)
+		nbytes = ctr->bufsz - *ppos;
+	if (copy_to_user(buf, ctr->buf + *ppos, nbytes))
+		return -EFAULT;
+	*ppos += nbytes;
+	return nbytes;
+}
+
+static int cpuset_tasks_release(struct inode *unused_inode, struct file *file)
+{
+	struct ctr_struct *ctr;
+
+	if (file->f_mode & FMODE_READ) {
+		ctr = file->private_data;
+		kfree(ctr->buf);
+		kfree(ctr);
+	}
+	return 0;
+}
+
+/*
+ * for the common functions, 'private' gives the type of file
+ */
+
+static struct cftype cft_tasks = {
+	.name = "tasks",
+	.open = cpuset_tasks_open,
+	.read = cpuset_tasks_read,
+	.release = cpuset_tasks_release,
+	.private = FILE_TASKLIST,
+};
+
+static struct cftype cft_cpus = {
+	.name = "cpus",
+	.private = FILE_CPULIST,
+};
+
+static struct cftype cft_mems = {
+	.name = "mems",
+	.private = FILE_MEMLIST,
+};
+
+static struct cftype cft_cpu_exclusive = {
+	.name = "cpu_exclusive",
+	.private = FILE_CPU_EXCLUSIVE,
+};
+
+static struct cftype cft_mem_exclusive = {
+	.name = "mem_exclusive",
+	.private = FILE_MEM_EXCLUSIVE,
+};
+
+static struct cftype cft_notify_on_release = {
+	.name = "notify_on_release",
+	.private = FILE_NOTIFY_ON_RELEASE,
+};
+
+static int cpuset_populate_dir(struct dentry *cs_dentry)
+{
+	int err;
+
+	if ((err = cpuset_add_file(cs_dentry, &cft_cpus)) < 0)
+		return err;
+	if ((err = cpuset_add_file(cs_dentry, &cft_mems)) < 0)
+		return err;
+	if ((err = cpuset_add_file(cs_dentry, &cft_cpu_exclusive)) < 0)
+		return err;
+	if ((err = cpuset_add_file(cs_dentry, &cft_mem_exclusive)) < 0)
+		return err;
+	if ((err = cpuset_add_file(cs_dentry, &cft_notify_on_release)) < 0)
+		return err;
+	if ((err = cpuset_add_file(cs_dentry, &cft_tasks)) < 0)
+		return err;
+	return 0;
+}
+
+/*
+ *	cpuset_create - create a cpuset
+ *	parent:	cpuset that will be parent of the new cpuset.
+ *	name:		name of the new cpuset. Will be strcpy'ed.
+ *	mode:		mode to set on new inode
+ *
+ *	Must be called with the semaphore on the parent inode held
+ */
+
+static long cpuset_create(struct cpuset *parent, const char *name, int mode)
+{
+	struct cpuset *cs;
+	int err;
+
+	cs = kmalloc(sizeof(*cs), GFP_KERNEL);
+	if (!cs)
+		return -ENOMEM;
+
+	down(&cpuset_sem);
+	cs->flags = 0;
+	if (notify_on_release(parent))
+		set_bit(CS_NOTIFY_ON_RELEASE, &cs->flags);
+	cs->cpus_allowed = CPU_MASK_NONE;
+	cs->mems_allowed = NODE_MASK_NONE;
+	atomic_set(&cs->count, 0);
+	INIT_LIST_HEAD(&cs->sibling);
+	INIT_LIST_HEAD(&cs->children);
+	atomic_inc(&cpuset_mems_generation);
+	cs->mems_generation = atomic_read(&cpuset_mems_generation);
+
+	cs->parent = parent;
+
+	list_add(&cs->sibling, &cs->parent->children);
+
+	err = cpuset_create_dir(cs, name, mode);
+	if (err < 0)
+		goto err;
+
+	/*
+	 * Release cpuset_sem before cpuset_populate_dir() because it
+	 * will down() this new directory's i_sem and if we race with
+	 * another mkdir, we might deadlock.
+	 */
+	up(&cpuset_sem);
+
+	err = cpuset_populate_dir(cs->dentry);
+	/* If err < 0, we have a half-filled directory - oh well ;) */
+	return 0;
+err:
+	list_del(&cs->sibling);
+	up(&cpuset_sem);
+	kfree(cs);
+	return err;
+}
+
+static int cpuset_mkdir(struct inode *dir, struct dentry *dentry, int mode)
+{
+	struct cpuset *c_parent = dentry->d_parent->d_fsdata;
+
+	/* the vfs holds inode->i_sem already */
+	return cpuset_create(c_parent, dentry->d_name.name, mode | S_IFDIR);
+}
+
+static int cpuset_rmdir(struct inode *unused_dir, struct dentry *dentry)
+{
+	struct cpuset *cs = dentry->d_fsdata;
+	struct dentry *d;
+	struct cpuset *parent;
+
+	/* the vfs holds both inode->i_sem already */
+
+	down(&cpuset_sem);
+	if (atomic_read(&cs->count) > 0) {
+		up(&cpuset_sem);
+		return -EBUSY;
+	}
+	if (!list_empty(&cs->children)) {
+		up(&cpuset_sem);
+		return -EBUSY;
+	}
+	spin_lock(&cs->dentry->d_lock);
+	parent = cs->parent;
+	set_bit(CS_REMOVED, &cs->flags);
+	list_del(&cs->sibling);	/* delete my sibling from parent->children */
+	if (list_empty(&parent->children))
+		check_for_release(parent);
+	d = dget(cs->dentry);
+	cs->dentry = NULL;
+	spin_unlock(&d->d_lock);
+	cpuset_d_remove_dir(d);
+	dput(d);
+	up(&cpuset_sem);
+	return 0;
+}
+
+/**
+ * cpuset_init - initialize cpusets at system boot
+ *
+ * Description: Initialize top_cpuset and the cpuset internal file system,
+ **/
+
+int __init cpuset_init(void)
+{
+	struct dentry *root;
+	int err;
+
+	top_cpuset.cpus_allowed = CPU_MASK_ALL;
+	top_cpuset.mems_allowed = NODE_MASK_ALL;
+
+	atomic_inc(&cpuset_mems_generation);
+	top_cpuset.mems_generation = atomic_read(&cpuset_mems_generation);
+
+	init_task.cpuset = &top_cpuset;
+
+	err = register_filesystem(&cpuset_fs_type);
+	if (err < 0)
+		goto out;
+	cpuset_mount = kern_mount(&cpuset_fs_type);
+	if (IS_ERR(cpuset_mount)) {
+		printk(KERN_ERR "cpuset: could not mount!\n");
+		err = PTR_ERR(cpuset_mount);
+		cpuset_mount = NULL;
+		goto out;
+	}
+	root = cpuset_mount->mnt_sb->s_root;
+	root->d_fsdata = &top_cpuset;
+	root->d_inode->i_nlink++;
+	top_cpuset.dentry = root;
+	root->d_inode->i_op = &cpuset_dir_inode_operations;
+	err = cpuset_populate_dir(root);
+out:
+	return err;
+}
+
+/**
+ * cpuset_init_smp - initialize cpus_allowed
+ *
+ * Description: Finish top cpuset after cpu, node maps are initialized
+ **/
+
+void __init cpuset_init_smp(void)
+{
+	top_cpuset.cpus_allowed = cpu_online_map;
+	top_cpuset.mems_allowed = node_online_map;
+}
+
+/**
+ * cpuset_fork - attach newly forked task to its parents cpuset.
+ * @p: pointer to task_struct of forking parent process.
+ *
+ * Description: By default, on fork, a task inherits its
+ * parents cpuset.  The pointer to the shared cpuset is
+ * automatically copied in fork.c by dup_task_struct().
+ * This cpuset_fork() routine need only increment the usage
+ * counter in that cpuset.
+ **/
+
+void cpuset_fork(struct task_struct *tsk)
+{
+	atomic_inc(&tsk->cpuset->count);
+}
+
+/**
+ * cpuset_exit - detach cpuset from exiting task
+ * @tsk: pointer to task_struct of exiting process
+ *
+ * Description: Detach cpuset from @tsk and release it.
+ *
+ **/
+
+void cpuset_exit(struct task_struct *tsk)
+{
+	struct cpuset *cs;
+
+	task_lock(tsk);
+	cs = tsk->cpuset;
+	tsk->cpuset = NULL;
+	task_unlock(tsk);
+
+	if (atomic_dec_and_test(&cs->count)) {
+		down(&cpuset_sem);
+		check_for_release(cs);
+		up(&cpuset_sem);
+	}
+}
+
+/**
+ * cpuset_cpus_allowed - return cpus_allowed mask from a tasks cpuset.
+ * @tsk: pointer to task_struct from which to obtain cpuset->cpus_allowed.
+ *
+ * Description: Returns the cpumask_t cpus_allowed of the cpuset
+ * attached to the specified @tsk.  Guaranteed to return some non-empty
+ * subset of cpu_online_map, even if this means going outside the
+ * tasks cpuset.
+ **/
+
+const cpumask_t cpuset_cpus_allowed(const struct task_struct *tsk)
+{
+	cpumask_t mask;
+
+	down(&cpuset_sem);
+	task_lock((struct task_struct *)tsk);
+	guarantee_online_cpus(tsk->cpuset, &mask);
+	task_unlock((struct task_struct *)tsk);
+	up(&cpuset_sem);
+
+	return mask;
+}
+
+void cpuset_init_current_mems_allowed(void)
+{
+	current->mems_allowed = NODE_MASK_ALL;
+}
+
+/*
+ * If the current tasks cpusets mems_allowed changed behind our backs,
+ * update current->mems_allowed and mems_generation to the new value.
+ * Do not call this routine if in_interrupt().
+ */
+
+void cpuset_update_current_mems_allowed()
+{
+	struct cpuset *cs = current->cpuset;
+
+	if (!cs)
+		return;		/* task is exiting */
+	if (current->cpuset_mems_generation != cs->mems_generation) {
+		down(&cpuset_sem);
+		guarantee_online_mems(cs, &current->mems_allowed);
+		current->cpuset_mems_generation = cs->mems_generation;
+		up(&cpuset_sem);
+	}
+}
+
+void cpuset_restrict_to_mems_allowed(unsigned long *nodes)
+{
+	bitmap_and(nodes, nodes, nodes_addr(current->mems_allowed),
+							MAX_NUMNODES);
+}
+
+/*
+ * Are any of the nodes on zonelist zl allowed in current->mems_allowed?
+ */
+int cpuset_zonelist_valid_mems_allowed(struct zonelist *zl)
+{
+	int i;
+
+	for (i = 0; zl->zones[i]; i++) {
+		int nid = zl->zones[i]->zone_pgdat->node_id;
+
+		if (node_isset(nid, current->mems_allowed))
+			return 1;
+	}
+	return 0;
+}
+
+/*
+ * Is 'current' valid, and is zone z allowed in current->mems_allowed?
+ */
+int cpuset_zone_allowed(struct zone *z)
+{
+	return in_interrupt() ||
+		node_isset(z->zone_pgdat->node_id, current->mems_allowed);
+}
+
+/*
+ * proc_cpuset_show()
+ *  - Print tasks cpuset path into seq_file.
+ *  - Used for /proc/<pid>/cpuset.
+ */
+
+static int proc_cpuset_show(struct seq_file *m, void *v)
+{
+	struct cpuset *cs;
+	struct task_struct *tsk;
+	char *buf;
+	int retval = 0;
+
+	buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+
+	tsk = m->private;
+	down(&cpuset_sem);
+	task_lock(tsk);
+	cs = tsk->cpuset;
+	task_unlock(tsk);
+	if (!cs) {
+		retval = -EINVAL;
+		goto out;
+	}
+
+	retval = cpuset_path(cs, buf, PAGE_SIZE);
+	if (retval < 0)
+		goto out;
+	seq_puts(m, buf);
+	seq_putc(m, '\n');
+out:
+	up(&cpuset_sem);
+	kfree(buf);
+	return retval;
+}
+
+static int cpuset_open(struct inode *inode, struct file *file)
+{
+	struct task_struct *tsk = PROC_I(inode)->task;
+	return single_open(file, proc_cpuset_show, tsk);
+}
+
+struct file_operations proc_cpuset_operations = {
+	.open		= cpuset_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
+/* Display task cpus_allowed, mems_allowed in /proc/<pid>/status file. */
+char *cpuset_task_status_allowed(struct task_struct *task, char *buffer)
+{
+	buffer += sprintf(buffer, "Cpus_allowed:\t");
+	buffer += cpumask_scnprintf(buffer, PAGE_SIZE, task->cpus_allowed);
+	buffer += sprintf(buffer, "\n");
+	buffer += sprintf(buffer, "Mems_allowed:\t");
+	buffer += nodemask_scnprintf(buffer, PAGE_SIZE, task->mems_allowed);
+	buffer += sprintf(buffer, "\n");
+	return buffer;
+}
diff -Nru a/kernel/exit.c b/kernel/exit.c
--- a/kernel/exit.c	2005-03-11 12:51:51 -08:00
+++ b/kernel/exit.c	2005-03-11 12:51:51 -08:00
@@ -25,6 +25,7 @@
 #include <linux/mount.h>
 #include <linux/proc_fs.h>
 #include <linux/mempolicy.h>
+#include <linux/cpuset.h>
 #include <linux/syscalls.h>
 
 #include <asm/uaccess.h>
@@ -753,13 +754,6 @@
 		state = EXIT_DEAD;
 	tsk->exit_state = state;
 
-	/*
-	 * Clear these here so that update_process_times() won't try to deliver
-	 * itimer, profile or rlimit signals to this task while it is in late exit.
-	 */
-	tsk->it_virt_value = cputime_zero;
-	tsk->it_prof_value = cputime_zero;
-
 	write_unlock_irq(&tasklist_lock);
 
 	list_for_each_safe(_p, _n, &ptrace_dead) {
@@ -799,18 +793,27 @@
 	}
 
 	tsk->flags |= PF_EXITING;
-	del_timer_sync(&tsk->real_timer);
+
+	/*
+	 * Make sure we don't try to process any timer firings
+	 * while we are already exiting.
+	 */
+ 	tsk->it_virt_expires = cputime_zero;
+ 	tsk->it_prof_expires = cputime_zero;
+	tsk->it_sched_expires = 0;
 
 	if (unlikely(in_atomic()))
 		printk(KERN_INFO "note: %s[%d] exited with preempt_count %d\n",
 				current->comm, current->pid,
 				preempt_count());
 
-	acct_update_integrals();
-	update_mem_hiwater();
+	acct_update_integrals(tsk);
+	update_mem_hiwater(tsk);
 	group_dead = atomic_dec_and_test(&tsk->signal->live);
-	if (group_dead)
+	if (group_dead) {
+ 		del_timer_sync(&tsk->signal->real_timer);
 		acct_process(code);
+	}
 	exit_mm(tsk);
 
 	exit_sem(tsk);
@@ -818,6 +821,7 @@
 	__exit_fs(tsk);
 	exit_namespace(tsk);
 	exit_thread();
+	cpuset_exit(tsk);
 	exit_keys(tsk);
 
 	if (group_dead && tsk->signal->leader)
diff -Nru a/kernel/fork.c b/kernel/fork.c
--- a/kernel/fork.c	2005-03-11 12:51:41 -08:00
+++ b/kernel/fork.c	2005-03-11 12:51:41 -08:00
@@ -29,6 +29,7 @@
 #include <linux/mman.h>
 #include <linux/fs.h>
 #include <linux/cpu.h>
+#include <linux/cpuset.h>
 #include <linux/security.h>
 #include <linux/swap.h>
 #include <linux/syscalls.h>
@@ -129,6 +130,8 @@
 
 	init_task.signal->rlim[RLIMIT_NPROC].rlim_cur = max_threads/2;
 	init_task.signal->rlim[RLIMIT_NPROC].rlim_max = max_threads/2;
+	init_task.signal->rlim[RLIMIT_SIGPENDING] =
+		init_task.signal->rlim[RLIMIT_NPROC];
 }
 
 static struct task_struct *dup_task_struct(struct task_struct *orig)
@@ -719,6 +722,7 @@
 static inline int copy_signal(unsigned long clone_flags, struct task_struct * tsk)
 {
 	struct signal_struct *sig;
+	int ret;
 
 	if (clone_flags & CLONE_THREAD) {
 		atomic_inc(&current->signal->count);
@@ -729,6 +733,13 @@
 	tsk->signal = sig;
 	if (!sig)
 		return -ENOMEM;
+
+	ret = copy_thread_group_keys(tsk);
+	if (ret < 0) {
+		kmem_cache_free(signal_cachep, sig);
+		return ret;
+	}
+
 	atomic_set(&sig->count, 1);
 	atomic_set(&sig->live, 1);
 	init_waitqueue_head(&sig->wait_chldexit);
@@ -740,6 +751,16 @@
 	init_sigpending(&sig->shared_pending);
 	INIT_LIST_HEAD(&sig->posix_timers);
 
+	sig->it_real_value = sig->it_real_incr = 0;
+	sig->real_timer.function = it_real_fn;
+	sig->real_timer.data = (unsigned long) tsk;
+	init_timer(&sig->real_timer);
+
+	sig->it_virt_expires = cputime_zero;
+	sig->it_virt_incr = cputime_zero;
+	sig->it_prof_expires = cputime_zero;
+	sig->it_prof_incr = cputime_zero;
+
 	sig->tty = current->signal->tty;
 	sig->pgrp = process_group(current);
 	sig->session = current->signal->session;
@@ -749,11 +770,24 @@
 	sig->utime = sig->stime = sig->cutime = sig->cstime = cputime_zero;
 	sig->nvcsw = sig->nivcsw = sig->cnvcsw = sig->cnivcsw = 0;
 	sig->min_flt = sig->maj_flt = sig->cmin_flt = sig->cmaj_flt = 0;
+	sig->sched_time = 0;
+	INIT_LIST_HEAD(&sig->cpu_timers[0]);
+	INIT_LIST_HEAD(&sig->cpu_timers[1]);
+	INIT_LIST_HEAD(&sig->cpu_timers[2]);
 
 	task_lock(current->group_leader);
 	memcpy(sig->rlim, current->signal->rlim, sizeof sig->rlim);
 	task_unlock(current->group_leader);
 
+	if (sig->rlim[RLIMIT_CPU].rlim_cur != RLIM_INFINITY) {
+		/*
+		 * New sole thread in the process gets an expiry time
+		 * of the whole CPU time limit.
+		 */
+		tsk->it_prof_expires =
+			secs_to_cputime(sig->rlim[RLIMIT_CPU].rlim_cur);
+	}
+
 	return 0;
 }
 
@@ -866,23 +900,22 @@
 	clear_tsk_thread_flag(p, TIF_SIGPENDING);
 	init_sigpending(&p->pending);
 
-	p->it_real_value = 0;
-	p->it_real_incr = 0;
-	p->it_virt_value = cputime_zero;
-	p->it_virt_incr = cputime_zero;
-	p->it_prof_value = cputime_zero;
-	p->it_prof_incr = cputime_zero;
-	init_timer(&p->real_timer);
-	p->real_timer.data = (unsigned long) p;
-
 	p->utime = cputime_zero;
 	p->stime = cputime_zero;
+ 	p->sched_time = 0;
 	p->rchar = 0;		/* I/O counter: bytes read */
 	p->wchar = 0;		/* I/O counter: bytes written */
 	p->syscr = 0;		/* I/O counter: read syscalls */
 	p->syscw = 0;		/* I/O counter: write syscalls */
 	acct_clear_integrals(p);
 
+ 	p->it_virt_expires = cputime_zero;
+	p->it_prof_expires = cputime_zero;
+ 	p->it_sched_expires = 0;
+ 	INIT_LIST_HEAD(&p->cpu_timers[0]);
+ 	INIT_LIST_HEAD(&p->cpu_timers[1]);
+ 	INIT_LIST_HEAD(&p->cpu_timers[2]);
+
 	p->lock_depth = -1;		/* -1 = no lock */
 	do_posix_clock_monotonic_gettime(&p->start_time);
 	p->security = NULL;
@@ -1015,12 +1048,29 @@
 			set_tsk_thread_flag(p, TIF_SIGPENDING);
 		}
 
+		if (!cputime_eq(current->signal->it_virt_expires,
+				cputime_zero) ||
+		    !cputime_eq(current->signal->it_prof_expires,
+				cputime_zero) ||
+		    current->signal->rlim[RLIMIT_CPU].rlim_cur != RLIM_INFINITY ||
+		    !list_empty(&current->signal->cpu_timers[0]) ||
+		    !list_empty(&current->signal->cpu_timers[1]) ||
+		    !list_empty(&current->signal->cpu_timers[2])) {
+			/*
+			 * Have child wake up on its first tick to check
+			 * for process CPU timers.
+			 */
+			p->it_prof_expires = jiffies_to_cputime(1);
+		}
+
 		spin_unlock(&current->sighand->siglock);
 	}
 
 	SET_LINKS(p);
 	if (unlikely(p->ptrace & PT_PTRACED))
 		__ptrace_link(p, current->parent);
+
+	cpuset_fork(p);
 
 	attach_pid(p, PIDTYPE_PID, p->pid);
 	attach_pid(p, PIDTYPE_TGID, p->tgid);
diff -Nru a/kernel/futex.c b/kernel/futex.c
--- a/kernel/futex.c	2005-03-11 12:51:42 -08:00
+++ b/kernel/futex.c	2005-03-11 12:51:42 -08:00
@@ -40,7 +40,7 @@
 #include <linux/pagemap.h>
 #include <linux/syscalls.h>
 
-#define FUTEX_HASHBITS 8
+#define FUTEX_HASHBITS (CONFIG_BASE_SMALL ? 4 : 8)
 
 /*
  * Futexes are matched on equal values of this key.
diff -Nru a/kernel/itimer.c b/kernel/itimer.c
--- a/kernel/itimer.c	2005-03-11 12:51:42 -08:00
+++ b/kernel/itimer.c	2005-03-11 12:51:42 -08:00
@@ -11,36 +11,86 @@
 #include <linux/interrupt.h>
 #include <linux/syscalls.h>
 #include <linux/time.h>
+#include <linux/posix-timers.h>
 
 #include <asm/uaccess.h>
 
+static unsigned long it_real_value(struct signal_struct *sig)
+{
+	unsigned long val = 0;
+	if (timer_pending(&sig->real_timer)) {
+		val = sig->real_timer.expires - jiffies;
+
+		/* look out for negative/zero itimer.. */
+		if ((long) val <= 0)
+			val = 1;
+	}
+	return val;
+}
+
 int do_getitimer(int which, struct itimerval *value)
 {
-	register unsigned long val;
+	struct task_struct *tsk = current;
+	unsigned long interval, val;
+	cputime_t cinterval, cval;
 
 	switch (which) {
 	case ITIMER_REAL:
-		val = 0;
-		/* 
-		 * FIXME! This needs to be atomic, in case the kernel timer happens!
-		 */
-		if (timer_pending(&current->real_timer)) {
-			val = current->real_timer.expires - jiffies;
-
-			/* look out for negative/zero itimer.. */
-			if ((long) val <= 0)
-				val = 1;
-		}
+		spin_lock_irq(&tsk->sighand->siglock);
+		interval = tsk->signal->it_real_incr;
+		val = it_real_value(tsk->signal);
+		spin_unlock_irq(&tsk->sighand->siglock);
 		jiffies_to_timeval(val, &value->it_value);
-		jiffies_to_timeval(current->it_real_incr, &value->it_interval);
+		jiffies_to_timeval(interval, &value->it_interval);
 		break;
 	case ITIMER_VIRTUAL:
-		cputime_to_timeval(current->it_virt_value, &value->it_value);
-		cputime_to_timeval(current->it_virt_incr, &value->it_interval);
+		read_lock(&tasklist_lock);
+		spin_lock_irq(&tsk->sighand->siglock);
+		cval = tsk->signal->it_virt_expires;
+		cinterval = tsk->signal->it_virt_incr;
+		if (!cputime_eq(cval, cputime_zero)) {
+			struct task_struct *t = tsk;
+			cputime_t utime = tsk->signal->utime;
+			do {
+				utime = cputime_add(utime, t->utime);
+				t = next_thread(t);
+			} while (t != tsk);
+			if (cputime_le(cval, utime)) { /* about to fire */
+				cval = jiffies_to_cputime(1);
+			} else {
+				cval = cputime_sub(cval, utime);
+			}
+		}
+		spin_unlock_irq(&tsk->sighand->siglock);
+		read_unlock(&tasklist_lock);
+		cputime_to_timeval(cval, &value->it_value);
+		cputime_to_timeval(cinterval, &value->it_interval);
 		break;
 	case ITIMER_PROF:
-		cputime_to_timeval(current->it_prof_value, &value->it_value);
-		cputime_to_timeval(current->it_prof_incr, &value->it_interval);
+		read_lock(&tasklist_lock);
+		spin_lock_irq(&tsk->sighand->siglock);
+		cval = tsk->signal->it_prof_expires;
+		cinterval = tsk->signal->it_prof_incr;
+		if (!cputime_eq(cval, cputime_zero)) {
+			struct task_struct *t = tsk;
+			cputime_t ptime = cputime_add(tsk->signal->utime,
+						      tsk->signal->stime);
+			do {
+				ptime = cputime_add(ptime,
+						    cputime_add(t->utime,
+								t->stime));
+				t = next_thread(t);
+			} while (t != tsk);
+			if (cputime_le(cval, ptime)) { /* about to fire */
+				cval = jiffies_to_cputime(1);
+			} else {
+				cval = cputime_sub(cval, ptime);
+			}
+		}
+		spin_unlock_irq(&tsk->sighand->siglock);
+		read_unlock(&tasklist_lock);
+		cputime_to_timeval(cval, &value->it_value);
+		cputime_to_timeval(cinterval, &value->it_interval);
 		break;
 	default:
 		return(-EINVAL);
@@ -48,7 +98,6 @@
 	return 0;
 }
 
-/* SMP: Only we modify our itimer values. */
 asmlinkage long sys_getitimer(int which, struct itimerval __user *value)
 {
 	int error = -EFAULT;
@@ -63,70 +112,112 @@
 	return error;
 }
 
+/*
+ * Called with P->sighand->siglock held and P->signal->real_timer inactive.
+ * If interval is nonzero, arm the timer for interval ticks from now.
+ */
+static inline void it_real_arm(struct task_struct *p, unsigned long interval)
+{
+	p->signal->it_real_value = interval; /* XXX unnecessary field?? */
+	if (interval == 0)
+		return;
+	if (interval > (unsigned long) LONG_MAX)
+		interval = LONG_MAX;
+	p->signal->real_timer.expires = jiffies + interval;
+	add_timer(&p->signal->real_timer);
+}
+
 void it_real_fn(unsigned long __data)
 {
 	struct task_struct * p = (struct task_struct *) __data;
-	unsigned long interval;
 
 	send_group_sig_info(SIGALRM, SEND_SIG_PRIV, p);
-	interval = p->it_real_incr;
-	if (interval) {
-		if (interval > (unsigned long) LONG_MAX)
-			interval = LONG_MAX;
-		p->real_timer.expires = jiffies + interval;
-		add_timer(&p->real_timer);
-	}
+
+	/*
+	 * Now restart the timer if necessary.  We don't need any locking
+	 * here because do_setitimer makes sure we have finished running
+	 * before it touches anything.
+	 */
+	it_real_arm(p, p->signal->it_real_incr);
 }
 
 int do_setitimer(int which, struct itimerval *value, struct itimerval *ovalue)
 {
-	unsigned long expire;
-	cputime_t cputime;
-	int k;
+	struct task_struct *tsk = current;
+ 	unsigned long val, interval;
+	cputime_t cval, cinterval, nval, ninterval;
 
-	if (ovalue && (k = do_getitimer(which, ovalue)) < 0)
-		return k;
 	switch (which) {
-		case ITIMER_REAL:
-			del_timer_sync(&current->real_timer);
-			expire = timeval_to_jiffies(&value->it_value);
-			current->it_real_value = expire;
-			current->it_real_incr =
-				timeval_to_jiffies(&value->it_interval);
-			if (!expire)
-				break;
-			if (expire > (unsigned long) LONG_MAX)
-				expire = LONG_MAX;
-			current->real_timer.expires = jiffies + expire;
-			add_timer(&current->real_timer);
-			break;
-		case ITIMER_VIRTUAL:
-			cputime = timeval_to_cputime(&value->it_value);
-			if (cputime_gt(cputime, cputime_zero))
-				cputime = cputime_add(cputime,
-						      jiffies_to_cputime(1));
-			current->it_virt_value = cputime;
-			cputime = timeval_to_cputime(&value->it_interval);
-			current->it_virt_incr = cputime;
-			break;
-		case ITIMER_PROF:
-			cputime = timeval_to_cputime(&value->it_value);
-			if (cputime_gt(cputime, cputime_zero))
-				cputime = cputime_add(cputime,
-						      jiffies_to_cputime(1));
-			current->it_prof_value = cputime;
-			cputime = timeval_to_cputime(&value->it_interval);
-			current->it_prof_incr = cputime;
-			break;
-		default:
-			return -EINVAL;
+	case ITIMER_REAL:
+		spin_lock_irq(&tsk->sighand->siglock);
+		interval = tsk->signal->it_real_incr;
+		val = it_real_value(tsk->signal);
+		if (val)
+			del_timer_sync(&tsk->signal->real_timer);
+		tsk->signal->it_real_incr =
+			timeval_to_jiffies(&value->it_interval);
+		it_real_arm(tsk, timeval_to_jiffies(&value->it_value));
+		spin_unlock_irq(&tsk->sighand->siglock);
+		if (ovalue) {
+			jiffies_to_timeval(val, &ovalue->it_value);
+			jiffies_to_timeval(interval,
+					   &ovalue->it_interval);
+		}
+		break;
+	case ITIMER_VIRTUAL:
+		nval = timeval_to_cputime(&value->it_value);
+		ninterval = timeval_to_cputime(&value->it_interval);
+		read_lock(&tasklist_lock);
+		spin_lock_irq(&tsk->sighand->siglock);
+		cval = tsk->signal->it_virt_expires;
+		cinterval = tsk->signal->it_virt_incr;
+		if (!cputime_eq(cval, cputime_zero) ||
+		    !cputime_eq(nval, cputime_zero)) {
+			if (cputime_gt(nval, cputime_zero))
+				nval = cputime_add(nval,
+						   jiffies_to_cputime(1));
+			set_process_cpu_timer(tsk, CPUCLOCK_VIRT,
+					      &nval, &cval);
+		}
+		tsk->signal->it_virt_expires = nval;
+		tsk->signal->it_virt_incr = ninterval;
+		spin_unlock_irq(&tsk->sighand->siglock);
+		read_unlock(&tasklist_lock);
+		if (ovalue) {
+			cputime_to_timeval(cval, &ovalue->it_value);
+			cputime_to_timeval(cinterval, &ovalue->it_interval);
+		}
+		break;
+	case ITIMER_PROF:
+		nval = timeval_to_cputime(&value->it_value);
+		ninterval = timeval_to_cputime(&value->it_interval);
+		read_lock(&tasklist_lock);
+		spin_lock_irq(&tsk->sighand->siglock);
+		cval = tsk->signal->it_prof_expires;
+		cinterval = tsk->signal->it_prof_incr;
+		if (!cputime_eq(cval, cputime_zero) ||
+		    !cputime_eq(nval, cputime_zero)) {
+			if (cputime_gt(nval, cputime_zero))
+				nval = cputime_add(nval,
+						   jiffies_to_cputime(1));
+			set_process_cpu_timer(tsk, CPUCLOCK_PROF,
+					      &nval, &cval);
+		}
+		tsk->signal->it_prof_expires = nval;
+		tsk->signal->it_prof_incr = ninterval;
+		spin_unlock_irq(&tsk->sighand->siglock);
+		read_unlock(&tasklist_lock);
+		if (ovalue) {
+			cputime_to_timeval(cval, &ovalue->it_value);
+			cputime_to_timeval(cinterval, &ovalue->it_interval);
+		}
+		break;
+	default:
+		return -EINVAL;
 	}
 	return 0;
 }
 
-/* SMP: Again, only we play with our itimers, and signals are SMP safe
- *      now so that is not an issue at all anymore.
- */
 asmlinkage long sys_setitimer(int which,
 			      struct itimerval __user *value,
 			      struct itimerval __user *ovalue)
diff -Nru a/kernel/kallsyms.c b/kernel/kallsyms.c
--- a/kernel/kallsyms.c	2005-03-11 12:51:51 -08:00
+++ b/kernel/kallsyms.c	2005-03-11 12:51:51 -08:00
@@ -145,14 +145,22 @@
 	}
 	return module_kallsyms_lookup_name(name);
 }
+EXPORT_SYMBOL_GPL(kallsyms_lookup_name);
 
-/* Lookup an address.  modname is set to NULL if it's in the kernel. */
+/*
+ * Lookup an address
+ * - modname is set to NULL if it's in the kernel
+ * - we guarantee that the returned name is valid until we reschedule even if
+ *   it resides in a module
+ * - we also guarantee that modname will be valid until rescheduled
+ */
 const char *kallsyms_lookup(unsigned long addr,
 			    unsigned long *symbolsize,
 			    unsigned long *offset,
 			    char **modname, char *namebuf)
 {
 	unsigned long i, low, high, mid;
+	const char *msym;
 
 	/* This kernel should never had been booted. */
 	BUG_ON(!kallsyms_addresses);
@@ -204,7 +212,12 @@
 		return namebuf;
 	}
 
-	return module_address_lookup(addr, symbolsize, offset, modname);
+	/* see if it's in a module */
+	msym = module_address_lookup(addr, symbolsize, offset, modname);
+	if (msym)
+		return strncpy(namebuf, msym, KSYM_NAME_LEN);
+
+	return NULL;
 }
 
 /* Replace "%s" in format with address, or returns -errno. */
diff -Nru a/kernel/module.c b/kernel/module.c
--- a/kernel/module.c	2005-03-11 12:51:47 -08:00
+++ b/kernel/module.c	2005-03-11 12:51:47 -08:00
@@ -472,7 +472,7 @@
 };
 
 /* Whole machine is stopped with interrupts off when this runs. */
-static inline int __try_stop_module(void *_sref)
+static int __try_stop_module(void *_sref)
 {
 	struct stopref *sref = _sref;
 
@@ -1072,14 +1072,22 @@
 	kobject_unregister(&mod->mkobj.kobj);
 }
 
+/*
+ * unlink the module with the whole machine is stopped with interrupts off
+ * - this defends against kallsyms not taking locks
+ */
+static int __unlink_module(void *_mod)
+{
+	struct module *mod = _mod;
+	list_del(&mod->list);
+	return 0;
+}
+
 /* Free a module, remove from lists, etc (must hold module mutex). */
 static void free_module(struct module *mod)
 {
 	/* Delete from various lists */
-	spin_lock_irq(&modlist_lock);
-	list_del(&mod->list);
-	spin_unlock_irq(&modlist_lock);
-
+	stop_machine_run(__unlink_module, mod, NR_CPUS);
 	remove_sect_attrs(mod);
 	mod_kobject_remove(mod);
 
@@ -1732,6 +1740,17 @@
 	goto free_hdr;
 }
 
+/*
+ * link the module with the whole machine is stopped with interrupts off
+ * - this defends against kallsyms not taking locks
+ */
+static int __link_module(void *_mod)
+{
+	struct module *mod = _mod;
+	list_add(&mod->list, &modules);
+	return 0;
+}
+
 /* This is where the real work happens */
 asmlinkage long
 sys_init_module(void __user *umod,
@@ -1766,9 +1785,7 @@
 
 	/* Now sew it into the lists.  They won't access us, since
            strong_try_module_get() will fail. */
-	spin_lock_irq(&modlist_lock);
-	list_add(&mod->list, &modules);
-	spin_unlock_irq(&modlist_lock);
+	stop_machine_run(__link_module, mod, NR_CPUS);
 
 	/* Drop lock so they can recurse */
 	up(&module_mutex);
diff -Nru a/kernel/posix-cpu-timers.c b/kernel/posix-cpu-timers.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/kernel/posix-cpu-timers.c	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,1531 @@
+/*
+ * Implement CPU time clocks for the POSIX clock interface.
+ */
+
+#include <linux/sched.h>
+#include <linux/posix-timers.h>
+#include <asm/uaccess.h>
+#include <linux/errno.h>
+
+static int check_clock(clockid_t which_clock)
+{
+	int error = 0;
+	struct task_struct *p;
+	const pid_t pid = CPUCLOCK_PID(which_clock);
+
+	if (CPUCLOCK_WHICH(which_clock) >= CPUCLOCK_MAX)
+		return -EINVAL;
+
+	if (pid == 0)
+		return 0;
+
+	read_lock(&tasklist_lock);
+	p = find_task_by_pid(pid);
+	if (!p || (CPUCLOCK_PERTHREAD(which_clock) ?
+		   p->tgid != current->tgid : p->tgid != pid)) {
+		error = -EINVAL;
+	}
+	read_unlock(&tasklist_lock);
+
+	return error;
+}
+
+static inline union cpu_time_count
+timespec_to_sample(clockid_t which_clock, const struct timespec *tp)
+{
+	union cpu_time_count ret;
+	ret.sched = 0;		/* high half always zero when .cpu used */
+	if (CPUCLOCK_WHICH(which_clock) == CPUCLOCK_SCHED) {
+		ret.sched = tp->tv_sec * NSEC_PER_SEC + tp->tv_nsec;
+	} else {
+		ret.cpu = timespec_to_jiffies(tp);
+	}
+	return ret;
+}
+
+static void sample_to_timespec(clockid_t which_clock,
+			       union cpu_time_count cpu,
+			       struct timespec *tp)
+{
+	if (CPUCLOCK_WHICH(which_clock) == CPUCLOCK_SCHED) {
+		tp->tv_sec = div_long_long_rem(cpu.sched,
+					       NSEC_PER_SEC, &tp->tv_nsec);
+	} else {
+		cputime_to_timespec(cpu.cpu, tp);
+	}
+}
+
+static inline int cpu_time_before(clockid_t which_clock,
+				  union cpu_time_count now,
+				  union cpu_time_count then)
+{
+	if (CPUCLOCK_WHICH(which_clock) == CPUCLOCK_SCHED) {
+		return now.sched < then.sched;
+	}  else {
+		return cputime_lt(now.cpu, then.cpu);
+	}
+}
+static inline void cpu_time_add(clockid_t which_clock,
+				union cpu_time_count *acc,
+			        union cpu_time_count val)
+{
+	if (CPUCLOCK_WHICH(which_clock) == CPUCLOCK_SCHED) {
+		acc->sched += val.sched;
+	}  else {
+		acc->cpu = cputime_add(acc->cpu, val.cpu);
+	}
+}
+static inline union cpu_time_count cpu_time_sub(clockid_t which_clock,
+						union cpu_time_count a,
+						union cpu_time_count b)
+{
+	if (CPUCLOCK_WHICH(which_clock) == CPUCLOCK_SCHED) {
+		a.sched -= b.sched;
+	}  else {
+		a.cpu = cputime_sub(a.cpu, b.cpu);
+	}
+	return a;
+}
+
+/*
+ * Update expiry time from increment, and increase overrun count,
+ * given the current clock sample.
+ */
+static inline void bump_cpu_timer(struct k_itimer *timer,
+				  union cpu_time_count now)
+{
+	if (timer->it.cpu.incr.sched == 0)
+		return;
+
+	if (CPUCLOCK_WHICH(timer->it_clock) == CPUCLOCK_SCHED) {
+		long long delta;
+		delta = now.sched - timer->it.cpu.expires.sched;
+		if (delta >= 0) {
+			do_div(delta, timer->it.cpu.incr.sched);
+			delta++;
+			timer->it.cpu.expires.sched +=
+				delta * timer->it.cpu.incr.sched;
+			timer->it_overrun += (int) delta;
+		}
+	} else if (cputime_le(now.cpu, timer->it.cpu.expires.cpu)) {
+		cputime_t delta = cputime_sub(now.cpu,
+					      timer->it.cpu.expires.cpu);
+		if (cputime_ge(delta, cputime_zero)) {
+			long orun = 1 + (delta / timer->it.cpu.incr.cpu);
+			timer->it.cpu.expires.cpu =
+				cputime_add(timer->it.cpu.expires.cpu,
+					    orun * timer->it.cpu.incr.cpu);
+			timer->it_overrun += orun;
+		}
+	}
+}
+
+static inline cputime_t prof_ticks(struct task_struct *p)
+{
+	return cputime_add(p->utime, p->stime);
+}
+static inline cputime_t virt_ticks(struct task_struct *p)
+{
+	return p->utime;
+}
+static inline unsigned long long sched_ns(struct task_struct *p)
+{
+	return (p == current) ? current_sched_time(p) : p->sched_time;
+}
+
+int posix_cpu_clock_getres(clockid_t which_clock, struct timespec *tp)
+{
+	int error = check_clock(which_clock);
+	if (!error) {
+		tp->tv_sec = 0;
+		tp->tv_nsec = ((NSEC_PER_SEC + HZ - 1) / HZ);
+		if (CPUCLOCK_WHICH(which_clock) == CPUCLOCK_SCHED) {
+			/*
+			 * If sched_clock is using a cycle counter, we
+			 * don't have any idea of its true resolution
+			 * exported, but it is much more than 1s/HZ.
+			 */
+			tp->tv_nsec = 1;
+		}
+	}
+	return error;
+}
+
+int posix_cpu_clock_set(clockid_t which_clock, const struct timespec *tp)
+{
+	/*
+	 * You can never reset a CPU clock, but we check for other errors
+	 * in the call before failing with EPERM.
+	 */
+	int error = check_clock(which_clock);
+	if (error == 0) {
+		error = -EPERM;
+	}
+	return error;
+}
+
+
+/*
+ * Sample a per-thread clock for the given task.
+ */
+static int cpu_clock_sample(clockid_t which_clock, struct task_struct *p,
+			    union cpu_time_count *cpu)
+{
+	switch (CPUCLOCK_WHICH(which_clock)) {
+	default:
+		return -EINVAL;
+	case CPUCLOCK_PROF:
+		cpu->cpu = prof_ticks(p);
+		break;
+	case CPUCLOCK_VIRT:
+		cpu->cpu = virt_ticks(p);
+		break;
+	case CPUCLOCK_SCHED:
+		cpu->sched = sched_ns(p);
+		break;
+	}
+	return 0;
+}
+
+/*
+ * Sample a process (thread group) clock for the given group_leader task.
+ * Must be called with tasklist_lock held for reading.
+ * Must be called with tasklist_lock held for reading, and p->sighand->siglock.
+ */
+static int cpu_clock_sample_group_locked(unsigned int clock_idx,
+					 struct task_struct *p,
+					 union cpu_time_count *cpu)
+{
+	struct task_struct *t = p;
+ 	switch (clock_idx) {
+	default:
+		return -EINVAL;
+	case CPUCLOCK_PROF:
+		cpu->cpu = cputime_add(p->signal->utime, p->signal->stime);
+		do {
+			cpu->cpu = cputime_add(cpu->cpu, prof_ticks(t));
+			t = next_thread(t);
+		} while (t != p);
+		break;
+	case CPUCLOCK_VIRT:
+		cpu->cpu = p->signal->utime;
+		do {
+			cpu->cpu = cputime_add(cpu->cpu, virt_ticks(t));
+			t = next_thread(t);
+		} while (t != p);
+		break;
+	case CPUCLOCK_SCHED:
+		cpu->sched = p->signal->sched_time;
+		/* Add in each other live thread.  */
+		while ((t = next_thread(t)) != p) {
+			cpu->sched += t->sched_time;
+		}
+		if (p->tgid == current->tgid) {
+			/*
+			 * We're sampling ourselves, so include the
+			 * cycles not yet banked.  We still omit
+			 * other threads running on other CPUs,
+			 * so the total can always be behind as
+			 * much as max(nthreads-1,ncpus) * (NSEC_PER_SEC/HZ).
+			 */
+			cpu->sched += current_sched_time(current);
+		} else {
+			cpu->sched += p->sched_time;
+		}
+		break;
+	}
+	return 0;
+}
+
+/*
+ * Sample a process (thread group) clock for the given group_leader task.
+ * Must be called with tasklist_lock held for reading.
+ */
+static int cpu_clock_sample_group(clockid_t which_clock,
+				  struct task_struct *p,
+				  union cpu_time_count *cpu)
+{
+	int ret;
+	unsigned long flags;
+	spin_lock_irqsave(&p->sighand->siglock, flags);
+	ret = cpu_clock_sample_group_locked(CPUCLOCK_WHICH(which_clock), p,
+					    cpu);
+	spin_unlock_irqrestore(&p->sighand->siglock, flags);
+	return ret;
+}
+
+
+int posix_cpu_clock_get(clockid_t which_clock, struct timespec *tp)
+{
+	const pid_t pid = CPUCLOCK_PID(which_clock);
+	int error = -EINVAL;
+	union cpu_time_count rtn;
+
+	if (pid == 0) {
+		/*
+		 * Special case constant value for our own clocks.
+		 * We don't have to do any lookup to find ourselves.
+		 */
+		if (CPUCLOCK_PERTHREAD(which_clock)) {
+			/*
+			 * Sampling just ourselves we can do with no locking.
+			 */
+			error = cpu_clock_sample(which_clock,
+						 current, &rtn);
+		} else {
+			read_lock(&tasklist_lock);
+			error = cpu_clock_sample_group(which_clock,
+						       current, &rtn);
+			read_unlock(&tasklist_lock);
+		}
+	} else {
+		/*
+		 * Find the given PID, and validate that the caller
+		 * should be able to see it.
+		 */
+		struct task_struct *p;
+		read_lock(&tasklist_lock);
+		p = find_task_by_pid(pid);
+		if (p) {
+			if (CPUCLOCK_PERTHREAD(which_clock)) {
+				if (p->tgid == current->tgid) {
+					error = cpu_clock_sample(which_clock,
+								 p, &rtn);
+				}
+			} else if (p->tgid == pid && p->signal) {
+				error = cpu_clock_sample_group(which_clock,
+							       p, &rtn);
+			}
+		}
+		read_unlock(&tasklist_lock);
+	}
+
+	if (error)
+		return error;
+	sample_to_timespec(which_clock, rtn, tp);
+	return 0;
+}
+
+
+/*
+ * Validate the clockid_t for a new CPU-clock timer, and initialize the timer.
+ * This is called from sys_timer_create with the new timer already locked.
+ */
+int posix_cpu_timer_create(struct k_itimer *new_timer)
+{
+	int ret = 0;
+	const pid_t pid = CPUCLOCK_PID(new_timer->it_clock);
+	struct task_struct *p;
+
+	if (CPUCLOCK_WHICH(new_timer->it_clock) >= CPUCLOCK_MAX)
+		return -EINVAL;
+
+	INIT_LIST_HEAD(&new_timer->it.cpu.entry);
+	new_timer->it.cpu.incr.sched = 0;
+	new_timer->it.cpu.expires.sched = 0;
+
+	read_lock(&tasklist_lock);
+	if (CPUCLOCK_PERTHREAD(new_timer->it_clock)) {
+		if (pid == 0) {
+			p = current;
+		} else {
+			p = find_task_by_pid(pid);
+			if (p && p->tgid != current->tgid)
+				p = NULL;
+		}
+	} else {
+		if (pid == 0) {
+			p = current->group_leader;
+		} else {
+			p = find_task_by_pid(pid);
+			if (p && p->tgid != pid)
+				p = NULL;
+		}
+	}
+	new_timer->it.cpu.task = p;
+	if (p) {
+		get_task_struct(p);
+	} else {
+		ret = -EINVAL;
+	}
+	read_unlock(&tasklist_lock);
+
+	return ret;
+}
+
+/*
+ * Clean up a CPU-clock timer that is about to be destroyed.
+ * This is called from timer deletion with the timer already locked.
+ * If we return TIMER_RETRY, it's necessary to release the timer's lock
+ * and try again.  (This happens when the timer is in the middle of firing.)
+ */
+int posix_cpu_timer_del(struct k_itimer *timer)
+{
+	struct task_struct *p = timer->it.cpu.task;
+
+	if (timer->it.cpu.firing)
+		return TIMER_RETRY;
+
+	if (unlikely(p == NULL))
+		return 0;
+
+	if (!list_empty(&timer->it.cpu.entry)) {
+		read_lock(&tasklist_lock);
+		if (unlikely(p->signal == NULL)) {
+			/*
+			 * We raced with the reaping of the task.
+			 * The deletion should have cleared us off the list.
+			 */
+			BUG_ON(!list_empty(&timer->it.cpu.entry));
+		} else {
+			/*
+			 * Take us off the task's timer list.
+			 */
+			spin_lock(&p->sighand->siglock);
+			list_del(&timer->it.cpu.entry);
+			spin_unlock(&p->sighand->siglock);
+		}
+		read_unlock(&tasklist_lock);
+	}
+	put_task_struct(p);
+
+	return 0;
+}
+
+/*
+ * Clean out CPU timers still ticking when a thread exited.  The task
+ * pointer is cleared, and the expiry time is replaced with the residual
+ * time for later timer_gettime calls to return.
+ * This must be called with the siglock held.
+ */
+static void cleanup_timers(struct list_head *head,
+			   cputime_t utime, cputime_t stime,
+			   unsigned long long sched_time)
+{
+	struct cpu_timer_list *timer, *next;
+	cputime_t ptime = cputime_add(utime, stime);
+
+	list_for_each_entry_safe(timer, next, head, entry) {
+		timer->task = NULL;
+		list_del_init(&timer->entry);
+		if (cputime_lt(timer->expires.cpu, ptime)) {
+			timer->expires.cpu = cputime_zero;
+		} else {
+			timer->expires.cpu = cputime_sub(timer->expires.cpu,
+							 ptime);
+		}
+	}
+
+	++head;
+	list_for_each_entry_safe(timer, next, head, entry) {
+		timer->task = NULL;
+		list_del_init(&timer->entry);
+		if (cputime_lt(timer->expires.cpu, utime)) {
+			timer->expires.cpu = cputime_zero;
+		} else {
+			timer->expires.cpu = cputime_sub(timer->expires.cpu,
+							 utime);
+		}
+	}
+
+	++head;
+	list_for_each_entry_safe(timer, next, head, entry) {
+		timer->task = NULL;
+		list_del_init(&timer->entry);
+		if (timer->expires.sched < sched_time) {
+			timer->expires.sched = 0;
+		} else {
+			timer->expires.sched -= sched_time;
+		}
+	}
+}
+
+/*
+ * These are both called with the siglock held, when the current thread
+ * is being reaped.  When the final (leader) thread in the group is reaped,
+ * posix_cpu_timers_exit_group will be called after posix_cpu_timers_exit.
+ */
+void posix_cpu_timers_exit(struct task_struct *tsk)
+{
+	cleanup_timers(tsk->cpu_timers,
+		       tsk->utime, tsk->stime, tsk->sched_time);
+
+}
+void posix_cpu_timers_exit_group(struct task_struct *tsk)
+{
+	cleanup_timers(tsk->signal->cpu_timers,
+		       cputime_add(tsk->utime, tsk->signal->utime),
+		       cputime_add(tsk->stime, tsk->signal->stime),
+		       tsk->sched_time + tsk->signal->sched_time);
+}
+
+
+/*
+ * Set the expiry times of all the threads in the process so one of them
+ * will go off before the process cumulative expiry total is reached.
+ */
+static void process_timer_rebalance(struct task_struct *p,
+				    unsigned int clock_idx,
+				    union cpu_time_count expires,
+				    union cpu_time_count val)
+{
+	cputime_t ticks, left;
+	unsigned long long ns, nsleft;
+ 	struct task_struct *t = p;
+	unsigned int nthreads = atomic_read(&p->signal->live);
+
+	switch (clock_idx) {
+	default:
+		BUG();
+		break;
+	case CPUCLOCK_PROF:
+		left = cputime_sub(expires.cpu, val.cpu)
+			/ nthreads;
+		do {
+			if (!unlikely(t->exit_state)) {
+				ticks = cputime_add(prof_ticks(t), left);
+				if (cputime_eq(t->it_prof_expires,
+					       cputime_zero) ||
+				    cputime_gt(t->it_prof_expires, ticks)) {
+					t->it_prof_expires = ticks;
+				}
+			}
+			t = next_thread(t);
+		} while (t != p);
+		break;
+	case CPUCLOCK_VIRT:
+		left = cputime_sub(expires.cpu, val.cpu)
+			/ nthreads;
+		do {
+			if (!unlikely(t->exit_state)) {
+				ticks = cputime_add(virt_ticks(t), left);
+				if (cputime_eq(t->it_virt_expires,
+					       cputime_zero) ||
+				    cputime_gt(t->it_virt_expires, ticks)) {
+					t->it_virt_expires = ticks;
+				}
+			}
+			t = next_thread(t);
+		} while (t != p);
+		break;
+	case CPUCLOCK_SCHED:
+		nsleft = expires.sched - val.sched;
+		do_div(nsleft, nthreads);
+		do {
+			if (!unlikely(t->exit_state)) {
+				ns = t->sched_time + nsleft;
+				if (t->it_sched_expires == 0 ||
+				    t->it_sched_expires > ns) {
+					t->it_sched_expires = ns;
+				}
+			}
+			t = next_thread(t);
+		} while (t != p);
+		break;
+	}
+}
+
+static void clear_dead_task(struct k_itimer *timer, union cpu_time_count now)
+{
+	/*
+	 * That's all for this thread or process.
+	 * We leave our residual in expires to be reported.
+	 */
+	put_task_struct(timer->it.cpu.task);
+	timer->it.cpu.task = NULL;
+	timer->it.cpu.expires = cpu_time_sub(timer->it_clock,
+					     timer->it.cpu.expires,
+					     now);
+}
+
+/*
+ * Insert the timer on the appropriate list before any timers that
+ * expire later.  This must be called with the tasklist_lock held
+ * for reading, and interrupts disabled.
+ */
+static void arm_timer(struct k_itimer *timer, union cpu_time_count now)
+{
+	struct task_struct *p = timer->it.cpu.task;
+	struct list_head *head, *listpos;
+	struct cpu_timer_list *const nt = &timer->it.cpu;
+	struct cpu_timer_list *next;
+	unsigned long i;
+
+	head = (CPUCLOCK_PERTHREAD(timer->it_clock) ?
+		p->cpu_timers : p->signal->cpu_timers);
+	head += CPUCLOCK_WHICH(timer->it_clock);
+
+	BUG_ON(!irqs_disabled());
+	spin_lock(&p->sighand->siglock);
+
+	listpos = head;
+	if (CPUCLOCK_WHICH(timer->it_clock) == CPUCLOCK_SCHED) {
+		list_for_each_entry(next, head, entry) {
+			if (next->expires.sched > nt->expires.sched) {
+				listpos = &next->entry;
+				break;
+			}
+		}
+	} else {
+		list_for_each_entry(next, head, entry) {
+			if (cputime_gt(next->expires.cpu, nt->expires.cpu)) {
+				listpos = &next->entry;
+				break;
+			}
+		}
+	}
+	list_add(&nt->entry, listpos);
+
+	if (listpos == head) {
+		/*
+		 * We are the new earliest-expiring timer.
+		 * If we are a thread timer, there can always
+		 * be a process timer telling us to stop earlier.
+		 */
+
+		if (CPUCLOCK_PERTHREAD(timer->it_clock)) {
+			switch (CPUCLOCK_WHICH(timer->it_clock)) {
+			default:
+				BUG();
+#define UPDATE_CLOCK(WHICH, c, n)			      		      \
+			case CPUCLOCK_##WHICH: 				      \
+				if (p->it_##c##_expires == 0 ||		      \
+				    p->it_##c##_expires > nt->expires.n) {    \
+					p->it_##c##_expires = nt->expires.n;  \
+				}					      \
+				break
+			UPDATE_CLOCK(PROF, prof, cpu);
+			UPDATE_CLOCK(VIRT, virt, cpu);
+			UPDATE_CLOCK(SCHED, sched, sched);
+#undef UPDATE_CLOCK
+			}
+		} else {
+			/*
+			 * For a process timer, we must balance
+			 * all the live threads' expirations.
+			 */
+			switch (CPUCLOCK_WHICH(timer->it_clock)) {
+			default:
+				BUG();
+			case CPUCLOCK_VIRT:
+				if (!cputime_eq(p->signal->it_virt_expires,
+						cputime_zero) &&
+				    cputime_lt(p->signal->it_virt_expires,
+					       timer->it.cpu.expires.cpu))
+					break;
+				goto rebalance;
+			case CPUCLOCK_PROF:
+				if (!cputime_eq(p->signal->it_prof_expires,
+						cputime_zero) &&
+				    cputime_lt(p->signal->it_prof_expires,
+					       timer->it.cpu.expires.cpu))
+					break;
+				i = p->signal->rlim[RLIMIT_CPU].rlim_cur;
+				if (i != RLIM_INFINITY &&
+				    i <= cputime_to_secs(timer->it.cpu.expires.cpu))
+					break;
+				goto rebalance;
+			case CPUCLOCK_SCHED:
+			rebalance:
+				process_timer_rebalance(
+					timer->it.cpu.task,
+					CPUCLOCK_WHICH(timer->it_clock),
+					timer->it.cpu.expires, now);
+				break;
+			}
+		}
+	}
+
+	spin_unlock(&p->sighand->siglock);
+}
+
+/*
+ * The timer is locked, fire it and arrange for its reload.
+ */
+static void cpu_timer_fire(struct k_itimer *timer)
+{
+	if (unlikely(timer->sigq == NULL)) {
+		/*
+		 * This a special case for clock_nanosleep,
+		 * not a normal timer from sys_timer_create.
+		 */
+		wake_up_process(timer->it_process);
+		timer->it.cpu.expires.sched = 0;
+	} else if (timer->it.cpu.incr.sched == 0) {
+		/*
+		 * One-shot timer.  Clear it as soon as it's fired.
+		 */
+		posix_timer_event(timer, 0);
+		timer->it.cpu.expires.sched = 0;
+	} else if (posix_timer_event(timer, ++timer->it_requeue_pending)) {
+		/*
+		 * The signal did not get queued because the signal
+		 * was ignored, so we won't get any callback to
+		 * reload the timer.  But we need to keep it
+		 * ticking in case the signal is deliverable next time.
+		 */
+		posix_cpu_timer_schedule(timer);
+	}
+}
+
+/*
+ * Guts of sys_timer_settime for CPU timers.
+ * This is called with the timer locked and interrupts disabled.
+ * If we return TIMER_RETRY, it's necessary to release the timer's lock
+ * and try again.  (This happens when the timer is in the middle of firing.)
+ */
+int posix_cpu_timer_set(struct k_itimer *timer, int flags,
+			struct itimerspec *new, struct itimerspec *old)
+{
+	struct task_struct *p = timer->it.cpu.task;
+	union cpu_time_count old_expires, new_expires, val;
+	int ret;
+
+	if (unlikely(p == NULL)) {
+		/*
+		 * Timer refers to a dead task's clock.
+		 */
+		return -ESRCH;
+	}
+
+	new_expires = timespec_to_sample(timer->it_clock, &new->it_value);
+
+	read_lock(&tasklist_lock);
+	/*
+	 * We need the tasklist_lock to protect against reaping that
+	 * clears p->signal.  If p has just been reaped, we can no
+	 * longer get any information about it at all.
+	 */
+	if (unlikely(p->signal == NULL)) {
+		read_unlock(&tasklist_lock);
+		put_task_struct(p);
+		timer->it.cpu.task = NULL;
+		return -ESRCH;
+	}
+
+	/*
+	 * Disarm any old timer after extracting its expiry time.
+	 */
+	BUG_ON(!irqs_disabled());
+	spin_lock(&p->sighand->siglock);
+	old_expires = timer->it.cpu.expires;
+	list_del_init(&timer->it.cpu.entry);
+	spin_unlock(&p->sighand->siglock);
+
+	/*
+	 * We need to sample the current value to convert the new
+	 * value from to relative and absolute, and to convert the
+	 * old value from absolute to relative.  To set a process
+	 * timer, we need a sample to balance the thread expiry
+	 * times (in arm_timer).  With an absolute time, we must
+	 * check if it's already passed.  In short, we need a sample.
+	 */
+	if (CPUCLOCK_PERTHREAD(timer->it_clock)) {
+		cpu_clock_sample(timer->it_clock, p, &val);
+	} else {
+		cpu_clock_sample_group(timer->it_clock, p, &val);
+	}
+
+	if (old) {
+		if (old_expires.sched == 0) {
+			old->it_value.tv_sec = 0;
+			old->it_value.tv_nsec = 0;
+		} else {
+			/*
+			 * Update the timer in case it has
+			 * overrun already.  If it has,
+			 * we'll report it as having overrun
+			 * and with the next reloaded timer
+			 * already ticking, though we are
+			 * swallowing that pending
+			 * notification here to install the
+			 * new setting.
+			 */
+			bump_cpu_timer(timer, val);
+			if (cpu_time_before(timer->it_clock, val,
+					    timer->it.cpu.expires)) {
+				old_expires = cpu_time_sub(
+					timer->it_clock,
+					timer->it.cpu.expires, val);
+				sample_to_timespec(timer->it_clock,
+						   old_expires,
+						   &old->it_value);
+			} else {
+				old->it_value.tv_nsec = 1;
+				old->it_value.tv_sec = 0;
+			}
+		}
+	}
+
+	if (unlikely(timer->it.cpu.firing)) {
+		/*
+		 * We are colliding with the timer actually firing.
+		 * Punt after filling in the timer's old value, and
+		 * disable this firing since we are already reporting
+		 * it as an overrun (thanks to bump_cpu_timer above).
+		 */
+		read_unlock(&tasklist_lock);
+		timer->it.cpu.firing = -1;
+		ret = TIMER_RETRY;
+		goto out;
+	}
+
+	if (new_expires.sched != 0 && !(flags & TIMER_ABSTIME)) {
+		cpu_time_add(timer->it_clock, &new_expires, val);
+	}
+
+	/*
+	 * Install the new expiry time (or zero).
+	 * For a timer with no notification action, we don't actually
+	 * arm the timer (we'll just fake it for timer_gettime).
+	 */
+	timer->it.cpu.expires = new_expires;
+	if (new_expires.sched != 0 &&
+	    (timer->it_sigev_notify & ~SIGEV_THREAD_ID) != SIGEV_NONE &&
+	    cpu_time_before(timer->it_clock, val, new_expires)) {
+		arm_timer(timer, val);
+	}
+
+	read_unlock(&tasklist_lock);
+
+	/*
+	 * Install the new reload setting, and
+	 * set up the signal and overrun bookkeeping.
+	 */
+	timer->it.cpu.incr = timespec_to_sample(timer->it_clock,
+						&new->it_interval);
+
+	/*
+	 * This acts as a modification timestamp for the timer,
+	 * so any automatic reload attempt will punt on seeing
+	 * that we have reset the timer manually.
+	 */
+	timer->it_requeue_pending = (timer->it_requeue_pending + 2) &
+		~REQUEUE_PENDING;
+	timer->it_overrun_last = 0;
+	timer->it_overrun = -1;
+
+	if (new_expires.sched != 0 &&
+	    (timer->it_sigev_notify & ~SIGEV_THREAD_ID) != SIGEV_NONE &&
+	    !cpu_time_before(timer->it_clock, val, new_expires)) {
+		/*
+		 * The designated time already passed, so we notify
+		 * immediately, even if the thread never runs to
+		 * accumulate more time on this clock.
+		 */
+		cpu_timer_fire(timer);
+	}
+
+	ret = 0;
+ out:
+	if (old) {
+		sample_to_timespec(timer->it_clock,
+				   timer->it.cpu.incr, &old->it_interval);
+	}
+	return ret;
+}
+
+void posix_cpu_timer_get(struct k_itimer *timer, struct itimerspec *itp)
+{
+	union cpu_time_count now;
+	struct task_struct *p = timer->it.cpu.task;
+	int clear_dead;
+
+	/*
+	 * Easy part: convert the reload time.
+	 */
+	sample_to_timespec(timer->it_clock,
+			   timer->it.cpu.incr, &itp->it_interval);
+
+	if (timer->it.cpu.expires.sched == 0) {	/* Timer not armed at all.  */
+		itp->it_value.tv_sec = itp->it_value.tv_nsec = 0;
+		return;
+	}
+
+	if (unlikely(p == NULL)) {
+		/*
+		 * This task already died and the timer will never fire.
+		 * In this case, expires is actually the dead value.
+		 */
+	dead:
+		sample_to_timespec(timer->it_clock, timer->it.cpu.expires,
+				   &itp->it_value);
+		return;
+	}
+
+	/*
+	 * Sample the clock to take the difference with the expiry time.
+	 */
+	if (CPUCLOCK_PERTHREAD(timer->it_clock)) {
+		cpu_clock_sample(timer->it_clock, p, &now);
+		clear_dead = p->exit_state;
+	} else {
+		read_lock(&tasklist_lock);
+		if (unlikely(p->signal == NULL)) {
+			/*
+			 * The process has been reaped.
+			 * We can't even collect a sample any more.
+			 * Call the timer disarmed, nothing else to do.
+			 */
+			put_task_struct(p);
+			timer->it.cpu.task = NULL;
+			timer->it.cpu.expires.sched = 0;
+			read_unlock(&tasklist_lock);
+			goto dead;
+		} else {
+			cpu_clock_sample_group(timer->it_clock, p, &now);
+			clear_dead = (unlikely(p->exit_state) &&
+				      thread_group_empty(p));
+		}
+		read_unlock(&tasklist_lock);
+	}
+
+	if ((timer->it_sigev_notify & ~SIGEV_THREAD_ID) == SIGEV_NONE) {
+		if (timer->it.cpu.incr.sched == 0 &&
+		    cpu_time_before(timer->it_clock,
+				    timer->it.cpu.expires, now)) {
+			/*
+			 * Do-nothing timer expired and has no reload,
+			 * so it's as if it was never set.
+			 */
+			timer->it.cpu.expires.sched = 0;
+			itp->it_value.tv_sec = itp->it_value.tv_nsec = 0;
+			return;
+		}
+		/*
+		 * Account for any expirations and reloads that should
+		 * have happened.
+		 */
+		bump_cpu_timer(timer, now);
+	}
+
+	if (unlikely(clear_dead)) {
+		/*
+		 * We've noticed that the thread is dead, but
+		 * not yet reaped.  Take this opportunity to
+		 * drop our task ref.
+		 */
+		clear_dead_task(timer, now);
+		goto dead;
+	}
+
+	if (cpu_time_before(timer->it_clock, now, timer->it.cpu.expires)) {
+		sample_to_timespec(timer->it_clock,
+				   cpu_time_sub(timer->it_clock,
+						timer->it.cpu.expires, now),
+				   &itp->it_value);
+	} else {
+		/*
+		 * The timer should have expired already, but the firing
+		 * hasn't taken place yet.  Say it's just about to expire.
+		 */
+		itp->it_value.tv_nsec = 1;
+		itp->it_value.tv_sec = 0;
+	}
+}
+
+/*
+ * Check for any per-thread CPU timers that have fired and move them off
+ * the tsk->cpu_timers[N] list onto the firing list.  Here we update the
+ * tsk->it_*_expires values to reflect the remaining thread CPU timers.
+ */
+static void check_thread_timers(struct task_struct *tsk,
+				struct list_head *firing)
+{
+	struct list_head *timers = tsk->cpu_timers;
+
+	tsk->it_prof_expires = 0;
+	while (!list_empty(timers)) {
+		struct cpu_timer_list *t = list_entry(timers->next,
+						      struct cpu_timer_list,
+						      entry);
+		if (cputime_lt(prof_ticks(tsk), t->expires.cpu)) {
+			tsk->it_prof_expires = t->expires.cpu;
+			break;
+		}
+		t->firing = 1;
+		list_move_tail(&t->entry, firing);
+	}
+
+	++timers;
+	tsk->it_virt_expires = 0;
+	while (!list_empty(timers)) {
+		struct cpu_timer_list *t = list_entry(timers->next,
+						      struct cpu_timer_list,
+						      entry);
+		if (cputime_lt(virt_ticks(tsk), t->expires.cpu)) {
+			tsk->it_virt_expires = t->expires.cpu;
+			break;
+		}
+		t->firing = 1;
+		list_move_tail(&t->entry, firing);
+	}
+
+	++timers;
+	tsk->it_sched_expires = 0;
+	while (!list_empty(timers)) {
+		struct cpu_timer_list *t = list_entry(timers->next,
+						      struct cpu_timer_list,
+						      entry);
+		if (tsk->sched_time < t->expires.sched) {
+			tsk->it_sched_expires = t->expires.sched;
+			break;
+		}
+		t->firing = 1;
+		list_move_tail(&t->entry, firing);
+	}
+}
+
+/*
+ * Check for any per-thread CPU timers that have fired and move them
+ * off the tsk->*_timers list onto the firing list.  Per-thread timers
+ * have already been taken off.
+ */
+static void check_process_timers(struct task_struct *tsk,
+				 struct list_head *firing)
+{
+	struct signal_struct *const sig = tsk->signal;
+	cputime_t utime, stime, ptime, virt_expires, prof_expires;
+	unsigned long long sched_time, sched_expires;
+	struct task_struct *t;
+	struct list_head *timers = sig->cpu_timers;
+
+	/*
+	 * Don't sample the current process CPU clocks if there are no timers.
+	 */
+	if (list_empty(&timers[CPUCLOCK_PROF]) &&
+	    cputime_eq(sig->it_prof_expires, cputime_zero) &&
+	    sig->rlim[RLIMIT_CPU].rlim_cur == RLIM_INFINITY &&
+	    list_empty(&timers[CPUCLOCK_VIRT]) &&
+	    cputime_eq(sig->it_virt_expires, cputime_zero) &&
+	    list_empty(&timers[CPUCLOCK_SCHED]))
+		return;
+
+	/*
+	 * Collect the current process totals.
+	 */
+	utime = sig->utime;
+	stime = sig->stime;
+	sched_time = sig->sched_time;
+	t = tsk;
+	do {
+		utime = cputime_add(utime, t->utime);
+		stime = cputime_add(stime, t->stime);
+		sched_time += t->sched_time;
+		t = next_thread(t);
+	} while (t != tsk);
+	ptime = cputime_add(utime, stime);
+
+	prof_expires = cputime_zero;
+	while (!list_empty(timers)) {
+		struct cpu_timer_list *t = list_entry(timers->next,
+						      struct cpu_timer_list,
+						      entry);
+		if (cputime_lt(ptime, t->expires.cpu)) {
+			prof_expires = t->expires.cpu;
+			break;
+		}
+		t->firing = 1;
+		list_move_tail(&t->entry, firing);
+	}
+
+	++timers;
+	virt_expires = cputime_zero;
+	while (!list_empty(timers)) {
+		struct cpu_timer_list *t = list_entry(timers->next,
+						      struct cpu_timer_list,
+						      entry);
+		if (cputime_lt(utime, t->expires.cpu)) {
+			virt_expires = t->expires.cpu;
+			break;
+		}
+		t->firing = 1;
+		list_move_tail(&t->entry, firing);
+	}
+
+	++timers;
+	sched_expires = cputime_zero;
+	while (!list_empty(timers)) {
+		struct cpu_timer_list *t = list_entry(timers->next,
+						      struct cpu_timer_list,
+						      entry);
+		if (sched_time < t->expires.sched) {
+			sched_expires = t->expires.sched;
+			break;
+		}
+		t->firing = 1;
+		list_move_tail(&t->entry, firing);
+	}
+
+	/*
+	 * Check for the special case process timers.
+	 */
+	if (!cputime_eq(sig->it_prof_expires, cputime_zero)) {
+		if (cputime_ge(ptime, sig->it_prof_expires)) {
+			/* ITIMER_PROF fires and reloads.  */
+			sig->it_prof_expires = sig->it_prof_incr;
+			if (!cputime_eq(sig->it_prof_expires, cputime_zero)) {
+				sig->it_prof_expires = cputime_add(
+					sig->it_prof_expires, ptime);
+			}
+			__group_send_sig_info(SIGPROF, SEND_SIG_PRIV, tsk);
+		}
+		if (!cputime_eq(sig->it_prof_expires, cputime_zero) &&
+		    (cputime_eq(prof_expires, cputime_zero) ||
+		     cputime_lt(sig->it_prof_expires, prof_expires))) {
+			prof_expires = sig->it_prof_expires;
+		}
+	}
+	if (!cputime_eq(sig->it_virt_expires, cputime_zero)) {
+		if (cputime_ge(utime, sig->it_virt_expires)) {
+			/* ITIMER_VIRTUAL fires and reloads.  */
+			sig->it_virt_expires = sig->it_virt_incr;
+			if (!cputime_eq(sig->it_virt_expires, cputime_zero)) {
+				sig->it_virt_expires = cputime_add(
+					sig->it_virt_expires, utime);
+			}
+			__group_send_sig_info(SIGVTALRM, SEND_SIG_PRIV, tsk);
+		}
+		if (!cputime_eq(sig->it_virt_expires, cputime_zero) &&
+		    (cputime_eq(virt_expires, cputime_zero) ||
+		     cputime_lt(sig->it_virt_expires, virt_expires))) {
+			virt_expires = sig->it_virt_expires;
+		}
+	}
+	if (sig->rlim[RLIMIT_CPU].rlim_cur != RLIM_INFINITY) {
+		unsigned long psecs = cputime_to_secs(ptime);
+		cputime_t x;
+		if (psecs >= sig->rlim[RLIMIT_CPU].rlim_max) {
+			/*
+			 * At the hard limit, we just die.
+			 * No need to calculate anything else now.
+			 */
+			__group_send_sig_info(SIGKILL, SEND_SIG_PRIV, tsk);
+			return;
+		}
+		if (psecs >= sig->rlim[RLIMIT_CPU].rlim_cur) {
+			/*
+			 * At the soft limit, send a SIGXCPU every second.
+			 */
+			__group_send_sig_info(SIGXCPU, SEND_SIG_PRIV, tsk);
+			if (sig->rlim[RLIMIT_CPU].rlim_cur
+			    < sig->rlim[RLIMIT_CPU].rlim_max) {
+				sig->rlim[RLIMIT_CPU].rlim_cur++;
+			}
+		}
+		x = secs_to_cputime(sig->rlim[RLIMIT_CPU].rlim_cur);
+		if (cputime_eq(prof_expires, cputime_zero) ||
+		    cputime_lt(x, prof_expires)) {
+			prof_expires = x;
+		}
+	}
+
+	if (!cputime_eq(prof_expires, cputime_zero) ||
+	    !cputime_eq(virt_expires, cputime_zero) ||
+	    sched_expires != 0) {
+		/*
+		 * Rebalance the threads' expiry times for the remaining
+		 * process CPU timers.
+		 */
+
+		cputime_t prof_left, virt_left, ticks;
+		unsigned long long sched_left, sched;
+		const unsigned int nthreads = atomic_read(&sig->live);
+
+		prof_left = cputime_sub(prof_expires,
+					cputime_add(utime, stime)) / nthreads;
+		virt_left = cputime_sub(virt_expires, utime) / nthreads;
+		if (sched_expires) {
+			sched_left = sched_expires - sched_time;
+			do_div(sched_left, nthreads);
+		} else {
+			sched_left = 0;
+		}
+		t = tsk;
+		do {
+			ticks = cputime_add(cputime_add(t->utime, t->stime),
+					    prof_left);
+			if (!cputime_eq(prof_expires, cputime_zero) &&
+			    (cputime_eq(t->it_prof_expires, cputime_zero) ||
+			     cputime_gt(t->it_prof_expires, ticks))) {
+				t->it_prof_expires = ticks;
+			}
+
+			ticks = cputime_add(t->utime, virt_left);
+			if (!cputime_eq(virt_expires, cputime_zero) &&
+			    (cputime_eq(t->it_virt_expires, cputime_zero) ||
+			     cputime_gt(t->it_virt_expires, ticks))) {
+				t->it_virt_expires = ticks;
+			}
+
+			sched = t->sched_time + sched_left;
+			if (sched_expires && (t->it_sched_expires == 0 ||
+					      t->it_sched_expires > sched)) {
+				t->it_sched_expires = sched;
+			}
+
+			do {
+				t = next_thread(t);
+			} while (unlikely(t->exit_state));
+		} while (t != tsk);
+	}
+}
+
+/*
+ * This is called from the signal code (via do_schedule_next_timer)
+ * when the last timer signal was delivered and we have to reload the timer.
+ */
+void posix_cpu_timer_schedule(struct k_itimer *timer)
+{
+	struct task_struct *p = timer->it.cpu.task;
+	union cpu_time_count now;
+
+	if (unlikely(p == NULL))
+		/*
+		 * The task was cleaned up already, no future firings.
+		 */
+		return;
+
+	/*
+	 * Fetch the current sample and update the timer's expiry time.
+	 */
+	if (CPUCLOCK_PERTHREAD(timer->it_clock)) {
+		cpu_clock_sample(timer->it_clock, p, &now);
+		bump_cpu_timer(timer, now);
+		if (unlikely(p->exit_state)) {
+			clear_dead_task(timer, now);
+			return;
+		}
+		read_lock(&tasklist_lock); /* arm_timer needs it.  */
+	} else {
+		read_lock(&tasklist_lock);
+		if (unlikely(p->signal == NULL)) {
+			/*
+			 * The process has been reaped.
+			 * We can't even collect a sample any more.
+			 */
+			put_task_struct(p);
+			timer->it.cpu.task = p = NULL;
+			timer->it.cpu.expires.sched = 0;
+			read_unlock(&tasklist_lock);
+			return;
+		} else if (unlikely(p->exit_state) && thread_group_empty(p)) {
+			/*
+			 * We've noticed that the thread is dead, but
+			 * not yet reaped.  Take this opportunity to
+			 * drop our task ref.
+			 */
+			clear_dead_task(timer, now);
+			read_unlock(&tasklist_lock);
+			return;
+		}
+		cpu_clock_sample_group(timer->it_clock, p, &now);
+		bump_cpu_timer(timer, now);
+		/* Leave the tasklist_lock locked for the call below.  */
+	}
+
+	/*
+	 * Now re-arm for the new expiry time.
+	 */
+	arm_timer(timer, now);
+
+	read_unlock(&tasklist_lock);
+}
+
+/*
+ * This is called from the timer interrupt handler.  The irq handler has
+ * already updated our counts.  We need to check if any timers fire now.
+ * Interrupts are disabled.
+ */
+void run_posix_cpu_timers(struct task_struct *tsk)
+{
+	LIST_HEAD(firing);
+	struct k_itimer *timer, *next;
+
+	BUG_ON(!irqs_disabled());
+
+#define UNEXPIRED(clock) \
+		(tsk->it_##clock##_expires == 0 || \
+		 cputime_lt(clock##_ticks(tsk), tsk->it_##clock##_expires))
+
+	if (UNEXPIRED(prof) && UNEXPIRED(virt) &&
+	    (tsk->it_sched_expires == 0 ||
+	     tsk->sched_time < tsk->it_sched_expires))
+		return;
+
+#undef	UNEXPIRED
+
+	BUG_ON(tsk->exit_state);
+
+	/*
+	 * Double-check with locks held.
+	 */
+	read_lock(&tasklist_lock);
+	spin_lock(&tsk->sighand->siglock);
+
+	/*
+	 * Here we take off tsk->cpu_timers[N] and tsk->signal->cpu_timers[N]
+	 * all the timers that are firing, and put them on the firing list.
+	 */
+	check_thread_timers(tsk, &firing);
+	check_process_timers(tsk, &firing);
+
+	/*
+	 * We must release these locks before taking any timer's lock.
+	 * There is a potential race with timer deletion here, as the
+	 * siglock now protects our private firing list.  We have set
+	 * the firing flag in each timer, so that a deletion attempt
+	 * that gets the timer lock before we do will give it up and
+	 * spin until we've taken care of that timer below.
+	 */
+	spin_unlock(&tsk->sighand->siglock);
+	read_unlock(&tasklist_lock);
+
+	/*
+	 * Now that all the timers on our list have the firing flag,
+	 * noone will touch their list entries but us.  We'll take
+	 * each timer's lock before clearing its firing flag, so no
+	 * timer call will interfere.
+	 */
+	list_for_each_entry_safe(timer, next, &firing, it.cpu.entry) {
+		int firing;
+		spin_lock(&timer->it_lock);
+		list_del_init(&timer->it.cpu.entry);
+		firing = timer->it.cpu.firing;
+		timer->it.cpu.firing = 0;
+		/*
+		 * The firing flag is -1 if we collided with a reset
+		 * of the timer, which already reported this
+		 * almost-firing as an overrun.  So don't generate an event.
+		 */
+		if (likely(firing >= 0)) {
+			cpu_timer_fire(timer);
+		}
+		spin_unlock(&timer->it_lock);
+	}
+}
+
+/*
+ * Set one of the process-wide special case CPU timers.
+ * The tasklist_lock and tsk->sighand->siglock must be held by the caller.
+ * The oldval argument is null for the RLIMIT_CPU timer, where *newval is
+ * absolute; non-null for ITIMER_*, where *newval is relative and we update
+ * it to be absolute, *oldval is absolute and we update it to be relative.
+ */
+void set_process_cpu_timer(struct task_struct *tsk, unsigned int clock_idx,
+			   cputime_t *newval, cputime_t *oldval)
+{
+	union cpu_time_count now;
+	struct list_head *head;
+
+	BUG_ON(clock_idx == CPUCLOCK_SCHED);
+	cpu_clock_sample_group_locked(clock_idx, tsk, &now);
+
+	if (oldval) {
+		if (!cputime_eq(*oldval, cputime_zero)) {
+			if (cputime_le(*oldval, now.cpu)) {
+				/* Just about to fire. */
+				*oldval = jiffies_to_cputime(1);
+			} else {
+				*oldval = cputime_sub(*oldval, now.cpu);
+			}
+		}
+
+		if (cputime_eq(*newval, cputime_zero))
+			return;
+		*newval = cputime_add(*newval, now.cpu);
+
+		/*
+		 * If the RLIMIT_CPU timer will expire before the
+		 * ITIMER_PROF timer, we have nothing else to do.
+		 */
+		if (tsk->signal->rlim[RLIMIT_CPU].rlim_cur
+		    < cputime_to_secs(*newval))
+			return;
+	}
+
+	/*
+	 * Check whether there are any process timers already set to fire
+	 * before this one.  If so, we don't have anything more to do.
+	 */
+	head = &tsk->signal->cpu_timers[clock_idx];
+	if (list_empty(head) ||
+	    cputime_ge(list_entry(head->next,
+				  struct cpu_timer_list, entry)->expires.cpu,
+		       *newval)) {
+		/*
+		 * Rejigger each thread's expiry time so that one will
+		 * notice before we hit the process-cumulative expiry time.
+		 */
+		union cpu_time_count expires = { .sched = 0 };
+		expires.cpu = *newval;
+		process_timer_rebalance(tsk, clock_idx, expires, now);
+	}
+}
+
+static long posix_cpu_clock_nanosleep_restart(struct restart_block *);
+
+int posix_cpu_nsleep(clockid_t which_clock, int flags,
+		     struct timespec *rqtp)
+{
+	struct restart_block *restart_block =
+	    &current_thread_info()->restart_block;
+	struct k_itimer timer;
+	int error;
+
+	/*
+	 * Diagnose required errors first.
+	 */
+	if (CPUCLOCK_PERTHREAD(which_clock) &&
+	    (CPUCLOCK_PID(which_clock) == 0 ||
+	     CPUCLOCK_PID(which_clock) == current->pid))
+		return -EINVAL;
+
+	/*
+	 * Set up a temporary timer and then wait for it to go off.
+	 */
+	memset(&timer, 0, sizeof timer);
+	spin_lock_init(&timer.it_lock);
+	timer.it_clock = which_clock;
+	timer.it_overrun = -1;
+	error = posix_cpu_timer_create(&timer);
+	timer.it_process = current;
+	if (!error) {
+		struct timespec __user *rmtp;
+		static struct itimerspec zero_it;
+		struct itimerspec it = { .it_value = *rqtp,
+					 .it_interval = {} };
+
+		spin_lock_irq(&timer.it_lock);
+		error = posix_cpu_timer_set(&timer, flags, &it, NULL);
+		if (error) {
+			spin_unlock_irq(&timer.it_lock);
+			return error;
+		}
+
+		while (!signal_pending(current)) {
+			if (timer.it.cpu.expires.sched == 0) {
+				/*
+				 * Our timer fired and was reset.
+				 */
+				spin_unlock_irq(&timer.it_lock);
+				return 0;
+			}
+
+			/*
+			 * Block until cpu_timer_fire (or a signal) wakes us.
+			 */
+			__set_current_state(TASK_INTERRUPTIBLE);
+			spin_unlock_irq(&timer.it_lock);
+			schedule();
+			spin_lock_irq(&timer.it_lock);
+		}
+
+		/*
+		 * We were interrupted by a signal.
+		 */
+		sample_to_timespec(which_clock, timer.it.cpu.expires, rqtp);
+		posix_cpu_timer_set(&timer, 0, &zero_it, &it);
+		spin_unlock_irq(&timer.it_lock);
+
+		if ((it.it_value.tv_sec | it.it_value.tv_nsec) == 0) {
+			/*
+			 * It actually did fire already.
+			 */
+			return 0;
+		}
+
+		/*
+		 * Report back to the user the time still remaining.
+		 */
+		rmtp = (struct timespec __user *) restart_block->arg1;
+		if (rmtp != NULL && !(flags & TIMER_ABSTIME) &&
+		    copy_to_user(rmtp, &it.it_value, sizeof *rmtp))
+			return -EFAULT;
+
+		restart_block->fn = posix_cpu_clock_nanosleep_restart;
+		/* Caller already set restart_block->arg1 */
+		restart_block->arg0 = which_clock;
+		restart_block->arg2 = rqtp->tv_sec;
+		restart_block->arg3 = rqtp->tv_nsec;
+
+		error = -ERESTART_RESTARTBLOCK;
+	}
+
+	return error;
+}
+
+static long
+posix_cpu_clock_nanosleep_restart(struct restart_block *restart_block)
+{
+	clockid_t which_clock = restart_block->arg0;
+	struct timespec t = { .tv_sec = restart_block->arg2,
+			      .tv_nsec = restart_block->arg3 };
+	restart_block->fn = do_no_restart_syscall;
+	return posix_cpu_nsleep(which_clock, TIMER_ABSTIME, &t);
+}
+
+
+#define PROCESS_CLOCK	MAKE_PROCESS_CPUCLOCK(0, CPUCLOCK_SCHED)
+#define THREAD_CLOCK	MAKE_THREAD_CPUCLOCK(0, CPUCLOCK_SCHED)
+
+static int process_cpu_clock_getres(clockid_t which_clock, struct timespec *tp)
+{
+	return posix_cpu_clock_getres(PROCESS_CLOCK, tp);
+}
+static int process_cpu_clock_get(clockid_t which_clock, struct timespec *tp)
+{
+	return posix_cpu_clock_get(PROCESS_CLOCK, tp);
+}
+static int process_cpu_timer_create(struct k_itimer *timer)
+{
+	timer->it_clock = PROCESS_CLOCK;
+	return posix_cpu_timer_create(timer);
+}
+static int process_cpu_nsleep(clockid_t which_clock, int flags,
+			      struct timespec *rqtp)
+{
+	return posix_cpu_nsleep(PROCESS_CLOCK, flags, rqtp);
+}
+static int thread_cpu_clock_getres(clockid_t which_clock, struct timespec *tp)
+{
+	return posix_cpu_clock_getres(THREAD_CLOCK, tp);
+}
+static int thread_cpu_clock_get(clockid_t which_clock, struct timespec *tp)
+{
+	return posix_cpu_clock_get(THREAD_CLOCK, tp);
+}
+static int thread_cpu_timer_create(struct k_itimer *timer)
+{
+	timer->it_clock = THREAD_CLOCK;
+	return posix_cpu_timer_create(timer);
+}
+static int thread_cpu_nsleep(clockid_t which_clock, int flags,
+			      struct timespec *rqtp)
+{
+	return -EINVAL;
+}
+
+static __init int init_posix_cpu_timers(void)
+{
+	struct k_clock process = {
+		.clock_getres = process_cpu_clock_getres,
+		.clock_get = process_cpu_clock_get,
+		.clock_set = do_posix_clock_nosettime,
+		.timer_create = process_cpu_timer_create,
+		.nsleep = process_cpu_nsleep,
+	};
+	struct k_clock thread = {
+		.clock_getres = thread_cpu_clock_getres,
+		.clock_get = thread_cpu_clock_get,
+		.clock_set = do_posix_clock_nosettime,
+		.timer_create = thread_cpu_timer_create,
+		.nsleep = thread_cpu_nsleep,
+	};
+
+	register_posix_clock(CLOCK_PROCESS_CPUTIME_ID, &process);
+	register_posix_clock(CLOCK_THREAD_CPUTIME_ID, &thread);
+
+	return 0;
+}
+__initcall(init_posix_cpu_timers);
diff -Nru a/kernel/posix-timers.c b/kernel/posix-timers.c
--- a/kernel/posix-timers.c	2005-03-11 12:51:46 -08:00
+++ b/kernel/posix-timers.c	2005-03-11 12:51:46 -08:00
@@ -92,14 +92,13 @@
  * inactive.  It could be in the "fire" routine getting a new expire time.
  */
 #define TIMER_INACTIVE 1
-#define TIMER_RETRY 1
 
 #ifdef CONFIG_SMP
 # define timer_active(tmr) \
-		((tmr)->it_timer.entry.prev != (void *)TIMER_INACTIVE)
+		((tmr)->it.real.timer.entry.prev != (void *)TIMER_INACTIVE)
 # define set_timer_inactive(tmr) \
 		do { \
-			(tmr)->it_timer.entry.prev = (void *)TIMER_INACTIVE; \
+			(tmr)->it.real.timer.entry.prev = (void *)TIMER_INACTIVE; \
 		} while (0)
 #else
 # define timer_active(tmr) BARFY	// error to use outside of SMP
@@ -115,7 +114,6 @@
 #endif
 
 
-#define REQUEUE_PENDING 1
 /*
  * The timer ID is turned into a timer address by idr_find().
  * Verifying a valid ID consists of:
@@ -173,22 +171,12 @@
 static struct k_clock_abs abs_list = {.list = LIST_HEAD_INIT(abs_list.list),
 				      .lock = SPIN_LOCK_UNLOCKED};
 
-#define if_clock_do(clock_fun,alt_fun,parms) \
-		(!clock_fun) ? alt_fun parms : clock_fun parms
-
-#define p_timer_get(clock,a,b) \
-	       	if_clock_do((clock)->timer_get,do_timer_gettime, (a,b))
-
-#define p_nsleep(clock,a,b,c) \
-		if_clock_do((clock)->nsleep, do_nsleep, (a,b,c))
-
-#define p_timer_del(clock,a) \
-		if_clock_do((clock)->timer_del, do_timer_delete, (a))
-
-static int do_posix_gettime(struct k_clock *clock, struct timespec *tp);
+static void posix_timer_fn(unsigned long);
 static u64 do_posix_clock_monotonic_gettime_parts(
 	struct timespec *tp, struct timespec *mo);
 int do_posix_clock_monotonic_gettime(struct timespec *tp);
+static int do_posix_clock_monotonic_get(clockid_t, struct timespec *tp);
+
 static struct k_itimer *lock_timer(timer_t timer_id, unsigned long *flags);
 
 static inline void unlock_timer(struct k_itimer *timr, unsigned long flags)
@@ -197,6 +185,79 @@
 }
 
 /*
+ * Call the k_clock hook function if non-null, or the default function.
+ */
+#define CLOCK_DISPATCH(clock, call, arglist) \
+ 	((clock) < 0 ? posix_cpu_##call arglist : \
+ 	 (posix_clocks[clock].call != NULL \
+ 	  ? (*posix_clocks[clock].call) arglist : common_##call arglist))
+
+/*
+ * Default clock hook functions when the struct k_clock passed
+ * to register_posix_clock leaves a function pointer null.
+ *
+ * The function common_CALL is the default implementation for
+ * the function pointer CALL in struct k_clock.
+ */
+
+static inline int common_clock_getres(clockid_t which_clock,
+				      struct timespec *tp)
+{
+	tp->tv_sec = 0;
+	tp->tv_nsec = posix_clocks[which_clock].res;
+	return 0;
+}
+
+static inline int common_clock_get(clockid_t which_clock, struct timespec *tp)
+{
+	getnstimeofday(tp);
+	return 0;
+}
+
+static inline int common_clock_set(clockid_t which_clock, struct timespec *tp)
+{
+	return do_sys_settimeofday(tp, NULL);
+}
+
+static inline int common_timer_create(struct k_itimer *new_timer)
+{
+	INIT_LIST_HEAD(&new_timer->it.real.abs_timer_entry);
+	init_timer(&new_timer->it.real.timer);
+	new_timer->it.real.timer.data = (unsigned long) new_timer;
+	new_timer->it.real.timer.function = posix_timer_fn;
+	set_timer_inactive(new_timer);
+	return 0;
+}
+
+/*
+ * These ones are defined below.
+ */
+static int common_nsleep(clockid_t, int flags, struct timespec *t);
+static void common_timer_get(struct k_itimer *, struct itimerspec *);
+static int common_timer_set(struct k_itimer *, int,
+			    struct itimerspec *, struct itimerspec *);
+static int common_timer_del(struct k_itimer *timer);
+
+/*
+ * Return nonzero iff we know a priori this clockid_t value is bogus.
+ */
+static inline int invalid_clockid(clockid_t which_clock)
+{
+	if (which_clock < 0)	/* CPU clock, posix_cpu_* will check it */
+		return 0;
+	if ((unsigned) which_clock >= MAX_CLOCKS)
+		return 1;
+	if (posix_clocks[which_clock].clock_getres != NULL)
+		return 0;
+#ifndef CLOCK_DISPATCH_DIRECT
+	if (posix_clocks[which_clock].res != 0)
+		return 0;
+#endif
+	return 1;
+}
+
+
+/*
  * Initialize everything, well, just everything in Posix clocks/timers ;)
  */
 static __init int init_posix_timers(void)
@@ -206,7 +267,7 @@
 	};
 	struct k_clock clock_monotonic = {.res = CLOCK_REALTIME_RES,
 		.abs_struct = NULL,
-		.clock_get = do_posix_clock_monotonic_gettime,
+		.clock_get = do_posix_clock_monotonic_get,
 		.clock_set = do_posix_clock_nosettime
 	};
 
@@ -263,9 +324,9 @@
 
 	set_normalized_timespec(&delta,
 				new_wall_to->tv_sec -
-				timr->wall_to_prev.tv_sec,
+				timr->it.real.wall_to_prev.tv_sec,
 				new_wall_to->tv_nsec -
-				timr->wall_to_prev.tv_nsec);
+				timr->it.real.wall_to_prev.tv_nsec);
 	if (likely(!(delta.tv_sec | delta.tv_nsec)))
 		return 0;
 	if (delta.tv_sec < 0) {
@@ -276,16 +337,16 @@
 		sign++;
 	}
 	tstojiffie(&delta, posix_clocks[timr->it_clock].res, &exp);
-	timr->wall_to_prev = *new_wall_to;
-	timr->it_timer.expires += (sign ? -exp : exp);
+	timr->it.real.wall_to_prev = *new_wall_to;
+	timr->it.real.timer.expires += (sign ? -exp : exp);
 	return 1;
 }
 
 static void remove_from_abslist(struct k_itimer *timr)
 {
-	if (!list_empty(&timr->abs_timer_entry)) {
+	if (!list_empty(&timr->it.real.abs_timer_entry)) {
 		spin_lock(&abs_list.lock);
-		list_del_init(&timr->abs_timer_entry);
+		list_del_init(&timr->it.real.abs_timer_entry);
 		spin_unlock(&abs_list.lock);
 	}
 }
@@ -299,7 +360,7 @@
 	/*
 	 * Set up the timer for the next interval (if there is one).
 	 * Note: this code uses the abs_timer_lock to protect
-	 * wall_to_prev and must hold it until exp is set, not exactly
+	 * it.real.wall_to_prev and must hold it until exp is set, not exactly
 	 * obvious...
 
 	 * This function is used for CLOCK_REALTIME* and
@@ -309,7 +370,7 @@
 	 * "other" CLOCKs "next timer" code (which, I suppose should
 	 * also be added to the k_clock structure).
 	 */
-	if (!timr->it_incr) 
+	if (!timr->it.real.incr)
 		return;
 
 	do {
@@ -318,7 +379,7 @@
 		posix_get_now(&now);
 	} while (read_seqretry(&xtime_lock, seq));
 
-	if (!list_empty(&timr->abs_timer_entry)) {
+	if (!list_empty(&timr->it.real.abs_timer_entry)) {
 		spin_lock(&abs_list.lock);
 		add_clockset_delta(timr, &new_wall_to);
 
@@ -331,7 +392,7 @@
 	timr->it_overrun_last = timr->it_overrun;
 	timr->it_overrun = -1;
 	++timr->it_requeue_pending;
-	add_timer(&timr->it_timer);
+	add_timer(&timr->it.real.timer);
 }
 
 /*
@@ -355,7 +416,10 @@
 	if (!timr || timr->it_requeue_pending != info->si_sys_private)
 		goto exit;
 
-	schedule_next_timer(timr);
+	if (timr->it_clock < 0)	/* CPU clock */
+		posix_cpu_timer_schedule(timr);
+	else
+		schedule_next_timer(timr);
 	info->si_overrun = timr->it_overrun_last;
 exit:
 	if (timr)
@@ -415,7 +479,7 @@
 
 	spin_lock_irqsave(&timr->it_lock, flags);
  	set_timer_inactive(timr);
-	if (!list_empty(&timr->abs_timer_entry)) {
+	if (!list_empty(&timr->it.real.abs_timer_entry)) {
 		spin_lock(&abs_list.lock);
 		do {
 			seq = read_seqbegin(&xtime_lock);
@@ -423,9 +487,9 @@
 		} while (read_seqretry(&xtime_lock, seq));
 		set_normalized_timespec(&delta,
 					new_wall_to.tv_sec -
-					timr->wall_to_prev.tv_sec,
+					timr->it.real.wall_to_prev.tv_sec,
 					new_wall_to.tv_nsec -
-					timr->wall_to_prev.tv_nsec);
+					timr->it.real.wall_to_prev.tv_nsec);
 		if (likely((delta.tv_sec | delta.tv_nsec ) == 0)) {
 			/* do nothing, timer is on time */
 		} else if (delta.tv_sec < 0) {
@@ -435,9 +499,9 @@
 			tstojiffie(&delta,
 				   posix_clocks[timr->it_clock].res,
 				   &exp);
-			timr->wall_to_prev = new_wall_to;
-			timr->it_timer.expires += exp;
-			add_timer(&timr->it_timer);
+			timr->it.real.wall_to_prev = new_wall_to;
+			timr->it.real.timer.expires += exp;
+			add_timer(&timr->it.real.timer);
 			do_notify = 0;
 		}
 		spin_unlock(&abs_list.lock);
@@ -446,7 +510,7 @@
 	if (do_notify)  {
 		int si_private=0;
 
-		if (timr->it_incr)
+		if (timr->it.real.incr)
 			si_private = ++timr->it_requeue_pending;
 		else {
 			remove_from_abslist(timr);
@@ -481,13 +545,14 @@
 	return rtn;
 }
 
-void register_posix_clock(int clock_id, struct k_clock *new_clock)
+void register_posix_clock(clockid_t clock_id, struct k_clock *new_clock)
 {
 	if ((unsigned) clock_id >= MAX_CLOCKS) {
 		printk("POSIX clock register failed for clock_id %d\n",
 		       clock_id);
 		return;
 	}
+
 	posix_clocks[clock_id] = *new_clock;
 }
 
@@ -498,7 +563,6 @@
 	if (!tmr)
 		return tmr;
 	memset(tmr, 0, sizeof (struct k_itimer));
-	INIT_LIST_HEAD(&tmr->abs_timer_entry);
 	if (unlikely(!(tmr->sigq = sigqueue_alloc()))) {
 		kmem_cache_free(posix_timers_cache, tmr);
 		tmr = NULL;
@@ -538,8 +602,7 @@
 	sigevent_t event;
 	int it_id_set = IT_ID_NOT_SET;
 
-	if ((unsigned) which_clock >= MAX_CLOCKS ||
-				!posix_clocks[which_clock].res)
+	if (invalid_clockid(which_clock))
 		return -EINVAL;
 
 	new_timer = alloc_posix_timer();
@@ -571,19 +634,10 @@
 	it_id_set = IT_ID_SET;
 	new_timer->it_id = (timer_t) new_timer_id;
 	new_timer->it_clock = which_clock;
-	new_timer->it_incr = 0;
 	new_timer->it_overrun = -1;
-	if (posix_clocks[which_clock].timer_create) {
-		error =  posix_clocks[which_clock].timer_create(new_timer);
-		if (error)
-			goto out;
-	} else {
-		init_timer(&new_timer->it_timer);
-		new_timer->it_timer.expires = 0;
-		new_timer->it_timer.data = (unsigned long) new_timer;
-		new_timer->it_timer.function = posix_timer_fn;
-		set_timer_inactive(new_timer);
-	}
+	error = CLOCK_DISPATCH(which_clock, timer_create, (new_timer));
+	if (error)
+		goto out;
 
 	/*
 	 * return the timer_id now.  The next step is hard to
@@ -734,36 +788,36 @@
  * report.
  */
 static void
-do_timer_gettime(struct k_itimer *timr, struct itimerspec *cur_setting)
+common_timer_get(struct k_itimer *timr, struct itimerspec *cur_setting)
 {
 	unsigned long expires;
 	struct now_struct now;
 
 	do
-		expires = timr->it_timer.expires;
-	while ((volatile long) (timr->it_timer.expires) != expires);
+		expires = timr->it.real.timer.expires;
+	while ((volatile long) (timr->it.real.timer.expires) != expires);
 
 	posix_get_now(&now);
 
 	if (expires &&
 	    ((timr->it_sigev_notify & ~SIGEV_THREAD_ID) == SIGEV_NONE) &&
-	    !timr->it_incr &&
-	    posix_time_before(&timr->it_timer, &now))
-		timr->it_timer.expires = expires = 0;
+	    !timr->it.real.incr &&
+	    posix_time_before(&timr->it.real.timer, &now))
+		timr->it.real.timer.expires = expires = 0;
 	if (expires) {
 		if (timr->it_requeue_pending & REQUEUE_PENDING ||
 		    (timr->it_sigev_notify & ~SIGEV_THREAD_ID) == SIGEV_NONE) {
 			posix_bump_timer(timr, now);
-			expires = timr->it_timer.expires;
+			expires = timr->it.real.timer.expires;
 		}
 		else
-			if (!timer_pending(&timr->it_timer))
+			if (!timer_pending(&timr->it.real.timer))
 				expires = 0;
 		if (expires)
 			expires -= now.jiffies;
 	}
 	jiffies_to_timespec(expires, &cur_setting->it_value);
-	jiffies_to_timespec(timr->it_incr, &cur_setting->it_interval);
+	jiffies_to_timespec(timr->it.real.incr, &cur_setting->it_interval);
 
 	if (cur_setting->it_value.tv_sec < 0) {
 		cur_setting->it_value.tv_nsec = 1;
@@ -783,7 +837,7 @@
 	if (!timr)
 		return -EINVAL;
 
-	p_timer_get(&posix_clocks[timr->it_clock], timr, &cur_setting);
+	CLOCK_DISPATCH(timr->it_clock, timer_get, (timr, &cur_setting));
 
 	unlock_timer(timr, flags);
 
@@ -854,7 +908,7 @@
 			/*
 			 * Not one of the basic clocks
 			 */
-			do_posix_gettime(clock, &now);	
+			clock->clock_get(clock - posix_clocks, &now);
 			jiffies_64_f = get_jiffies_64();
 		}
 		/*
@@ -907,23 +961,23 @@
 /* Set a POSIX.1b interval timer. */
 /* timr->it_lock is taken. */
 static inline int
-do_timer_settime(struct k_itimer *timr, int flags,
+common_timer_set(struct k_itimer *timr, int flags,
 		 struct itimerspec *new_setting, struct itimerspec *old_setting)
 {
 	struct k_clock *clock = &posix_clocks[timr->it_clock];
 	u64 expire_64;
 
 	if (old_setting)
-		do_timer_gettime(timr, old_setting);
+		common_timer_get(timr, old_setting);
 
 	/* disable the timer */
-	timr->it_incr = 0;
+	timr->it.real.incr = 0;
 	/*
 	 * careful here.  If smp we could be in the "fire" routine which will
 	 * be spinning as we hold the lock.  But this is ONLY an SMP issue.
 	 */
 #ifdef CONFIG_SMP
-	if (timer_active(timr) && !del_timer(&timr->it_timer))
+	if (timer_active(timr) && !del_timer(&timr->it.real.timer))
 		/*
 		 * It can only be active if on an other cpu.  Since
 		 * we have cleared the interval stuff above, it should
@@ -936,7 +990,7 @@
 
 	set_timer_inactive(timr);
 #else
-	del_timer(&timr->it_timer);
+	del_timer(&timr->it.real.timer);
 #endif
 	remove_from_abslist(timr);
 
@@ -948,29 +1002,29 @@
 	 *switch off the timer when it_value is zero
 	 */
 	if (!new_setting->it_value.tv_sec && !new_setting->it_value.tv_nsec) {
-		timr->it_timer.expires = 0;
+		timr->it.real.timer.expires = 0;
 		return 0;
 	}
 
 	if (adjust_abs_time(clock,
 			    &new_setting->it_value, flags & TIMER_ABSTIME, 
-			    &expire_64, &(timr->wall_to_prev))) {
+			    &expire_64, &(timr->it.real.wall_to_prev))) {
 		return -EINVAL;
 	}
-	timr->it_timer.expires = (unsigned long)expire_64;	
+	timr->it.real.timer.expires = (unsigned long)expire_64;
 	tstojiffie(&new_setting->it_interval, clock->res, &expire_64);
-	timr->it_incr = (unsigned long)expire_64;
+	timr->it.real.incr = (unsigned long)expire_64;
 
 	/*
 	 * We do not even queue SIGEV_NONE timers!  But we do put them
 	 * in the abs list so we can do that right.
 	 */
 	if (((timr->it_sigev_notify & ~SIGEV_THREAD_ID) != SIGEV_NONE))
-		add_timer(&timr->it_timer);
+		add_timer(&timr->it.real.timer);
 
 	if (flags & TIMER_ABSTIME && clock->abs_struct) {
 		spin_lock(&clock->abs_struct->lock);
-		list_add_tail(&(timr->abs_timer_entry),
+		list_add_tail(&(timr->it.real.abs_timer_entry),
 			      &(clock->abs_struct->list));
 		spin_unlock(&clock->abs_struct->lock);
 	}
@@ -1003,12 +1057,9 @@
 	if (!timr)
 		return -EINVAL;
 
-	if (!posix_clocks[timr->it_clock].timer_set)
-		error = do_timer_settime(timr, flags, &new_spec, rtn);
-	else
-	        error = posix_clocks[timr->it_clock].timer_set(timr,
-							       flags,
-							       &new_spec, rtn);
+	error = CLOCK_DISPATCH(timr->it_clock, timer_set,
+			       (timr, flags, &new_spec, rtn));
+
 	unlock_timer(timr, flag);
 	if (error == TIMER_RETRY) {
 		rtn = NULL;	// We already got the old time...
@@ -1022,11 +1073,11 @@
 	return error;
 }
 
-static inline int do_timer_delete(struct k_itimer *timer)
+static inline int common_timer_del(struct k_itimer *timer)
 {
-	timer->it_incr = 0;
+	timer->it.real.incr = 0;
 #ifdef CONFIG_SMP
-	if (timer_active(timer) && !del_timer(&timer->it_timer))
+	if (timer_active(timer) && !del_timer(&timer->it.real.timer))
 		/*
 		 * It can only be active if on an other cpu.  Since
 		 * we have cleared the interval stuff above, it should
@@ -1037,13 +1088,18 @@
 		 */
 		return TIMER_RETRY;
 #else
-	del_timer(&timer->it_timer);
+	del_timer(&timer->it.real.timer);
 #endif
 	remove_from_abslist(timer);
 
 	return 0;
 }
 
+static inline int timer_delete_hook(struct k_itimer *timer)
+{
+	return CLOCK_DISPATCH(timer->it_clock, timer_del, (timer));
+}
+
 /* Delete a POSIX.1b interval timer. */
 asmlinkage long
 sys_timer_delete(timer_t timer_id)
@@ -1060,14 +1116,14 @@
 		return -EINVAL;
 
 #ifdef CONFIG_SMP
-	error = p_timer_del(&posix_clocks[timer->it_clock], timer);
+	error = timer_delete_hook(timer);
 
 	if (error == TIMER_RETRY) {
 		unlock_timer(timer, flags);
 		goto retry_delete;
 	}
 #else
-	p_timer_del(&posix_clocks[timer->it_clock], timer);
+	timer_delete_hook(timer);
 #endif
 	spin_lock(&current->sighand->siglock);
 	list_del(&timer->list);
@@ -1099,14 +1155,14 @@
 	spin_lock_irqsave(&timer->it_lock, flags);
 
 #ifdef CONFIG_SMP
-	error = p_timer_del(&posix_clocks[timer->it_clock], timer);
+	error = timer_delete_hook(timer);
 
 	if (error == TIMER_RETRY) {
 		unlock_timer(timer, flags);
 		goto retry_delete;
 	}
 #else
-	p_timer_del(&posix_clocks[timer->it_clock], timer);
+	timer_delete_hook(timer);
 #endif
 	list_del(&timer->list);
 	/*
@@ -1143,14 +1199,6 @@
  * spin_lock_irq() held and from clock calls with no locking.	They must
  * use the save flags versions of locks.
  */
-static int do_posix_gettime(struct k_clock *clock, struct timespec *tp)
-{
-	if (clock->clock_get)
-		return clock->clock_get(tp);
-
-	getnstimeofday(tp);
-	return 0;
-}
 
 /*
  * We do ticks here to avoid the irq lock ( they take sooo long).
@@ -1177,7 +1225,7 @@
 	return jiff;
 }
 
-int do_posix_clock_monotonic_gettime(struct timespec *tp)
+static int do_posix_clock_monotonic_get(clockid_t clock, struct timespec *tp)
 {
 	struct timespec wall_to_mono;
 
@@ -1193,7 +1241,13 @@
 	return 0;
 }
 
-int do_posix_clock_nosettime(struct timespec *tp)
+int do_posix_clock_monotonic_gettime(struct timespec *tp)
+{
+	return do_posix_clock_monotonic_get(CLOCK_MONOTONIC, tp);
+}
+
+
+int do_posix_clock_nosettime(clockid_t clockid, struct timespec *tp)
 {
 	return -EINVAL;
 }
@@ -1203,7 +1257,7 @@
 	return -EINVAL;
 }
 
-int do_posix_clock_nonanosleep(int which_clock, int flags, struct timespec *t)
+int do_posix_clock_nonanosleep(clockid_t clock, int flags, struct timespec *t)
 {
 #ifndef ENOTSUP
 	return -EOPNOTSUPP;	/* aka ENOTSUP in userland for POSIX */
@@ -1217,24 +1271,12 @@
 {
 	struct timespec new_tp;
 
-	if ((unsigned) which_clock >= MAX_CLOCKS ||
-					!posix_clocks[which_clock].res)
+	if (invalid_clockid(which_clock))
 		return -EINVAL;
 	if (copy_from_user(&new_tp, tp, sizeof (*tp)))
 		return -EFAULT;
-	if (posix_clocks[which_clock].clock_set)
-		return posix_clocks[which_clock].clock_set(&new_tp);
-
-	return do_sys_settimeofday(&new_tp, NULL);
-}
 
-static int do_clock_gettime(clockid_t which_clock, struct timespec *tp)
-{
-	if ((unsigned) which_clock >= MAX_CLOCKS ||
-					!posix_clocks[which_clock].res)
-		return -EINVAL;
-
-	return do_posix_gettime(&posix_clocks[which_clock], tp);
+	return CLOCK_DISPATCH(which_clock, clock_set, (which_clock, &new_tp));
 }
 
 asmlinkage long
@@ -1243,7 +1285,10 @@
 	struct timespec kernel_tp;
 	int error;
 
-	error = do_clock_gettime(which_clock, &kernel_tp);
+	if (invalid_clockid(which_clock))
+		return -EINVAL;
+	error = CLOCK_DISPATCH(which_clock, clock_get,
+			       (which_clock, &kernel_tp));
 	if (!error && copy_to_user(tp, &kernel_tp, sizeof (kernel_tp)))
 		error = -EFAULT;
 
@@ -1255,18 +1300,19 @@
 sys_clock_getres(clockid_t which_clock, struct timespec __user *tp)
 {
 	struct timespec rtn_tp;
+	int error;
 
-	if ((unsigned) which_clock >= MAX_CLOCKS ||
-					!posix_clocks[which_clock].res)
+	if (invalid_clockid(which_clock))
 		return -EINVAL;
 
-	rtn_tp.tv_sec = 0;
-	rtn_tp.tv_nsec = posix_clocks[which_clock].res;
-	if (tp && copy_to_user(tp, &rtn_tp, sizeof (rtn_tp)))
-		return -EFAULT;
+	error = CLOCK_DISPATCH(which_clock, clock_getres,
+			       (which_clock, &rtn_tp));
 
-	return 0;
+	if (!error && tp && copy_to_user(tp, &rtn_tp, sizeof (rtn_tp))) {
+		error = -EFAULT;
+	}
 
+	return error;
 }
 
 static void nanosleep_wake_up(unsigned long __data)
@@ -1364,13 +1410,13 @@
 			break;
 		}
 		timr = list_entry(cws_list.next, struct k_itimer,
-				   abs_timer_entry);
+				  it.real.abs_timer_entry);
 
-		list_del_init(&timr->abs_timer_entry);
+		list_del_init(&timr->it.real.abs_timer_entry);
 		if (add_clockset_delta(timr, &new_wall_to) &&
-		    del_timer(&timr->it_timer))  /* timer run yet? */
-			add_timer(&timr->it_timer);
-		list_add(&timr->abs_timer_entry, &abs_list.list);
+		    del_timer(&timr->it.real.timer))  /* timer run yet? */
+			add_timer(&timr->it.real.timer);
+		list_add(&timr->it.real.abs_timer_entry, &abs_list.list);
 		spin_unlock_irq(&abs_list.lock);
 	} while (1);
 
@@ -1379,9 +1425,6 @@
 
 long clock_nanosleep_restart(struct restart_block *restart_block);
 
-extern long do_clock_nanosleep(clockid_t which_clock, int flags,
-			       struct timespec *t);
-
 asmlinkage long
 sys_clock_nanosleep(clockid_t which_clock, int flags,
 		    const struct timespec __user *rqtp,
@@ -1392,8 +1435,7 @@
 	    &(current_thread_info()->restart_block);
 	int ret;
 
-	if ((unsigned) which_clock >= MAX_CLOCKS ||
-					!posix_clocks[which_clock].res)
+	if (invalid_clockid(which_clock))
 		return -EINVAL;
 
 	if (copy_from_user(&t, rqtp, sizeof (struct timespec)))
@@ -1402,23 +1444,22 @@
 	if ((unsigned) t.tv_nsec >= NSEC_PER_SEC || t.tv_sec < 0)
 		return -EINVAL;
 
-	if (posix_clocks[which_clock].nsleep)
-		ret = posix_clocks[which_clock].nsleep(which_clock, flags, &t);
-	else
-		ret = do_clock_nanosleep(which_clock, flags, &t);
 	/*
-	 * Do this here as do_clock_nanosleep does not have the real address
+	 * Do this here as nsleep function does not have the real address.
 	 */
 	restart_block->arg1 = (unsigned long)rmtp;
 
+	ret = CLOCK_DISPATCH(which_clock, nsleep, (which_clock, flags, &t));
+
 	if ((ret == -ERESTART_RESTARTBLOCK) && rmtp &&
 					copy_to_user(rmtp, &t, sizeof (t)))
 		return -EFAULT;
 	return ret;
 }
 
-long
-do_clock_nanosleep(clockid_t which_clock, int flags, struct timespec *tsave)
+
+static int common_nsleep(clockid_t which_clock,
+			 int flags, struct timespec *tsave)
 {
 	struct timespec t, dum;
 	struct timer_list new_timer;
@@ -1525,7 +1566,7 @@
 clock_nanosleep_restart(struct restart_block *restart_block)
 {
 	struct timespec t;
-	int ret = do_clock_nanosleep(restart_block->arg0, 0, &t);
+	int ret = common_nsleep(restart_block->arg0, 0, &t);
 
 	if ((ret == -ERESTART_RESTARTBLOCK) && restart_block->arg1 &&
 	    copy_to_user((struct timespec __user *)(restart_block->arg1), &t,
diff -Nru a/kernel/power/disk.c b/kernel/power/disk.c
--- a/kernel/power/disk.c	2005-03-11 12:51:41 -08:00
+++ b/kernel/power/disk.c	2005-03-11 12:51:41 -08:00
@@ -233,7 +233,6 @@
 	if ((error = prepare()))
 		goto Free;
 
-	barrier();
 	mb();
 
 	pr_debug("PM: Restoring saved image.\n");
diff -Nru a/kernel/power/swsusp.c b/kernel/power/swsusp.c
--- a/kernel/power/swsusp.c	2005-03-11 12:51:42 -08:00
+++ b/kernel/power/swsusp.c	2005-03-11 12:51:42 -08:00
@@ -76,7 +76,6 @@
 extern const void __nosave_begin, __nosave_end;
 
 /* Variables to be preserved over suspend */
-static int pagedir_order_check;
 static int nr_copy_pages_check;
 
 extern char resume_file[];
@@ -225,8 +224,6 @@
 	swap_list_unlock();
 }
 
-
-
 /**
  *	write_swap_page - Write one page to a fresh swap location.
  *	@addr:	Address we're writing.
@@ -239,7 +236,6 @@
  *	This is a partial improvement, since we will at least return other
  *	errors, though we need to eventually fix the damn code.
  */
-
 static int write_page(unsigned long addr, swp_entry_t * loc)
 {
 	swp_entry_t entry;
@@ -259,14 +255,12 @@
 	return error;
 }
 
-
 /**
  *	data_free - Free the swap entries used by the saved image.
  *
  *	Walk the list of used swap entries and free each one. 
  *	This is only used for cleanup when suspend fails.
  */
-
 static void data_free(void)
 {
 	swp_entry_t entry;
@@ -282,28 +276,27 @@
 	}
 }
 
-
 /**
  *	data_write - Write saved image to swap.
  *
  *	Walk the list of pages in the image and sync each one to swap.
  */
-
 static int data_write(void)
 {
-	int error = 0;
-	int i;
+	int error = 0, i = 0;
 	unsigned int mod = nr_copy_pages / 100;
+	struct pbe *p;
 
 	if (!mod)
 		mod = 1;
 
 	printk( "Writing data to swap (%d pages)...     ", nr_copy_pages );
-	for (i = 0; i < nr_copy_pages && !error; i++) {
+	for_each_pbe(p, pagedir_nosave) {
 		if (!(i%mod))
 			printk( "\b\b\b\b%3d%%", i / mod );
-		error = write_page((pagedir_nosave+i)->address,
-					  &((pagedir_nosave+i)->swap_address));
+		if ((error = write_page(p->address, &(p->swap_address))))
+			return error;
+		i++;
 	}
 	printk("\b\b\b\bdone\n");
 	return error;
@@ -326,15 +319,14 @@
 
 static void init_header(void)
 {
-	memset(&swsusp_info,0,sizeof(swsusp_info));
+	memset(&swsusp_info, 0, sizeof(swsusp_info));
 	swsusp_info.version_code = LINUX_VERSION_CODE;
 	swsusp_info.num_physpages = num_physpages;
-	memcpy(&swsusp_info.uts,&system_utsname,sizeof(system_utsname));
+	memcpy(&swsusp_info.uts, &system_utsname, sizeof(system_utsname));
 
 	swsusp_info.suspend_pagedir = pagedir_nosave;
 	swsusp_info.cpus = num_online_cpus();
 	swsusp_info.image_pages = nr_copy_pages;
-	dump_info();
 }
 
 static int close_swap(void)
@@ -342,7 +334,8 @@
 	swp_entry_t entry;
 	int error;
 
-	error = write_page((unsigned long)&swsusp_info,&entry);
+	dump_info();
+	error = write_page((unsigned long)&swsusp_info, &entry);
 	if (!error) { 
 		printk( "S" );
 		error = mark_swapfiles(entry);
@@ -373,15 +366,18 @@
 
 static int write_pagedir(void)
 {
-	unsigned long addr = (unsigned long)pagedir_nosave;
 	int error = 0;
-	int n = SUSPEND_PD_PAGES(nr_copy_pages);
-	int i;
+	unsigned n = 0;
+	struct pbe * pbe;
+
+	printk( "Writing pagedir...");
+	for_each_pb_page(pbe, pagedir_nosave) {
+		if ((error = write_page((unsigned long)pbe, &swsusp_info.pagedir[n++])))
+			return error;
+	}
 
 	swsusp_info.pagedir_pages = n;
-	printk( "Writing pagedir (%d pages)\n", n);
-	for (i = 0; i < n && !error; i++, addr += PAGE_SIZE)
-		error = write_page(addr, &swsusp_info.pagedir[i]);
+	printk("done (%u pages)\n", n);
 	return error;
 }
 
@@ -567,8 +563,8 @@
 	struct zone *zone;
 	unsigned long zone_pfn;
 	struct pbe * pbe = pagedir_nosave;
-	int to_copy = nr_copy_pages;
 	
+	pr_debug("copy_data_pages(): pages to copy: %d\n", nr_copy_pages);
 	for_each_zone(zone) {
 		if (is_highmem(zone))
 			continue;
@@ -577,78 +573,94 @@
 			if (saveable(zone, &zone_pfn)) {
 				struct page * page;
 				page = pfn_to_page(zone_pfn + zone->zone_start_pfn);
+				BUG_ON(!pbe);
 				pbe->orig_address = (long) page_address(page);
 				/* copy_page is not usable for copying task structs. */
 				memcpy((void *)pbe->address, (void *)pbe->orig_address, PAGE_SIZE);
-				pbe++;
-				to_copy--;
+				pbe = pbe->next;
 			}
 		}
 	}
-	BUG_ON(to_copy);
+	BUG_ON(pbe);
 }
 
 
 /**
- *	calc_order - Determine the order of allocation needed for pagedir_save.
- *
- *	This looks tricky, but is just subtle. Please fix it some time.
- *	Since there are %nr_copy_pages worth of pages in the snapshot, we need
- *	to allocate enough contiguous space to hold 
- *		(%nr_copy_pages * sizeof(struct pbe)), 
- *	which has the saved/orig locations of the page.. 
- *
- *	SUSPEND_PD_PAGES() tells us how many pages we need to hold those 
- *	structures, then we call get_bitmask_order(), which will tell us the
- *	last bit set in the number, starting with 1. (If we need 30 pages, that
- *	is 0x0000001e in hex. The last bit is the 5th, which is the order we 
- *	would use to allocate 32 contiguous pages).
- *
- *	Since we also need to save those pages, we add the number of pages that
- *	we need to nr_copy_pages, and in case of an overflow, do the 
- *	calculation again to update the number of pages needed. 
- *
- *	With this model, we will tend to waste a lot of memory if we just cross
- *	an order boundary. Plus, the higher the order of allocation that we try
- *	to do, the more likely we are to fail in a low-memory situtation 
- *	(though	we're unlikely to get this far in such a case, since swsusp 
- *	requires half of memory to be free anyway).
+ *	calc_nr - Determine the number of pages needed for a pbe list.
  */
 
-
-static void calc_order(void)
+static int calc_nr(int nr_copy)
 {
-	int diff = 0;
-	int order = 0;
+	int extra = 0;
+	int mod = !!(nr_copy % PBES_PER_PAGE);
+	int diff = (nr_copy / PBES_PER_PAGE) + mod;
 
 	do {
-		diff = get_bitmask_order(SUSPEND_PD_PAGES(nr_copy_pages)) - order;
-		if (diff) {
-			order += diff;
-			nr_copy_pages += 1 << diff;
-		}
-	} while(diff);
-	pagedir_order = order;
+		extra += diff;
+		nr_copy += diff;
+		mod = !!(nr_copy % PBES_PER_PAGE);
+		diff = (nr_copy / PBES_PER_PAGE) + mod - extra;
+	} while (diff > 0);
+
+	return nr_copy;
 }
 
+/**
+ *	free_pagedir - free pages allocated with alloc_pagedir()
+ */
+
+static inline void free_pagedir(struct pbe *pblist)
+{
+	struct pbe *pbe;
+
+	while (pblist) {
+		pbe = (pblist + PB_PAGE_SKIP)->next;
+		free_page((unsigned long)pblist);
+		pblist = pbe;
+	}
+}
 
 /**
  *	alloc_pagedir - Allocate the page directory.
  *
- *	First, determine exactly how many contiguous pages we need and
+ *	First, determine exactly how many pages we need and
  *	allocate them.
- */
-
-static int alloc_pagedir(void)
-{
-	calc_order();
-	pagedir_save = (suspend_pagedir_t *)__get_free_pages(GFP_ATOMIC | __GFP_COLD,
-							     pagedir_order);
-	if (!pagedir_save)
-		return -ENOMEM;
-	memset(pagedir_save, 0, (1 << pagedir_order) * PAGE_SIZE);
-	pagedir_nosave = pagedir_save;
-	return 0;
+ *
+ *	We arrange the pages in a chain: each page is an array of PBES_PER_PAGE
+ *	struct pbe elements (pbes) and the last element in the page points
+ *	to the next page.
+ *
+ *	On each page we set up a list of struct_pbe elements.
+ */
+
+static struct pbe * alloc_pagedir(unsigned nr_pages)
+{
+	unsigned num;
+	struct pbe *pblist, *pbe, *p;
+
+	if (!nr_pages)
+		return NULL;
+
+	pr_debug("alloc_pagedir(): nr_pages = %d\n", nr_pages);
+	pblist = (struct pbe *)get_zeroed_page(GFP_ATOMIC | __GFP_COLD);
+	for (pbe = pblist, num = PBES_PER_PAGE; pbe && num < nr_pages;
+        		pbe = pbe->next, num += PBES_PER_PAGE) {
+		p = pbe;
+		pbe += PB_PAGE_SKIP;
+		do
+			p->next = p + 1;
+		while (p++ < pbe);
+		pbe->next = (struct pbe *)get_zeroed_page(GFP_ATOMIC | __GFP_COLD);
+	}
+	if (pbe) {
+		for (num -= PBES_PER_PAGE - 1, p = pbe; num < nr_pages; p++, num++)
+			p->next = p + 1;
+	} else { /* get_zeroed_page() failed */
+		free_pagedir(pblist);
+		pblist = NULL;
+        }
+	pr_debug("alloc_pagedir(): allocated %d PBEs\n", num);
+	return pblist;
 }
 
 /**
@@ -658,10 +670,8 @@
 static void free_image_pages(void)
 {
 	struct pbe * p;
-	int i;
 
-	p = pagedir_save;
-	for (i = 0, p = pagedir_save; i < nr_copy_pages; i++, p++) {
+	for_each_pbe(p, pagedir_save) {
 		if (p->address) {
 			ClearPageNosave(virt_to_page(p->address));
 			free_page(p->address);
@@ -672,15 +682,13 @@
 
 /**
  *	alloc_image_pages - Allocate pages for the snapshot.
- *
  */
 
 static int alloc_image_pages(void)
 {
 	struct pbe * p;
-	int i;
 
-	for (i = 0, p = pagedir_save; i < nr_copy_pages; i++, p++) {
+	for_each_pbe(p, pagedir_save) {
 		p->address = get_zeroed_page(GFP_ATOMIC | __GFP_COLD);
 		if (!p->address)
 			return -ENOMEM;
@@ -694,7 +702,7 @@
 	BUG_ON(PageNosave(virt_to_page(pagedir_save)));
 	BUG_ON(PageNosaveFree(virt_to_page(pagedir_save)));
 	free_image_pages();
-	free_pages((unsigned long) pagedir_save, pagedir_order);
+	free_pagedir(pagedir_save);
 }
 
 
@@ -752,10 +760,13 @@
 	if (!enough_swap())
 		return -ENOSPC;
 
-	if ((error = alloc_pagedir())) {
+	nr_copy_pages = calc_nr(nr_copy_pages);
+
+	if (!(pagedir_save = alloc_pagedir(nr_copy_pages))) {
 		printk(KERN_ERR "suspend: Allocating pagedir failed.\n");
-		return error;
+		return -ENOMEM;
 	}
+	pagedir_nosave = pagedir_save;
 	if ((error = alloc_image_pages())) {
 		printk(KERN_ERR "suspend: Allocating image pages failed.\n");
 		swsusp_free();
@@ -763,7 +774,6 @@
 	}
 
 	nr_copy_pages_check = nr_copy_pages;
-	pagedir_order_check = pagedir_order;
 	return 0;
 }
 
@@ -780,7 +790,7 @@
 
 	drain_local_pages();
 	count_data_pages();
-	printk("swsusp: Need to copy %u pages\n",nr_copy_pages);
+	printk("swsusp: Need to copy %u pages\n", nr_copy_pages);
 
 	error = swsusp_alloc();
 	if (error)
@@ -867,7 +877,6 @@
 asmlinkage int swsusp_restore(void)
 {
 	BUG_ON (nr_copy_pages_check != nr_copy_pages);
-	BUG_ON (pagedir_order_check != pagedir_order);
 	
 	/* Even mappings of "global" things (vmalloc) need to be fixed */
 	__flush_tlb_global();
diff -Nru a/kernel/printk.c b/kernel/printk.c
--- a/kernel/printk.c	2005-03-11 12:51:52 -08:00
+++ b/kernel/printk.c	2005-03-11 12:51:52 -08:00
@@ -499,6 +499,22 @@
 	init_MUTEX(&console_sem);
 }
 
+#if defined(CONFIG_PRINTK_TIME)
+static int printk_time = 1;
+#else
+static int printk_time = 0;
+#endif
+
+static int __init printk_time_setup(char *str)
+{
+	if (*str)
+		return 0;
+	printk_time = 1;
+	return 1;
+}
+
+__setup("time", printk_time_setup);
+
 /*
  * This is printk.  It can be called from any context.  We want it to work.
  * 
@@ -547,12 +563,51 @@
 	 */
 	for (p = printk_buf; *p; p++) {
 		if (log_level_unknown) {
-			if (p[0] != '<' || p[1] < '0' || p[1] > '7' || p[2] != '>') {
-				emit_log_char('<');
-				emit_log_char(default_message_loglevel + '0');
-				emit_log_char('>');
+                        /* log_level_unknown signals the start of a new line */
+			if (printk_time) {
+				int loglev_char;
+				char tbuf[50], *tp;
+				unsigned tlen;
+				unsigned long long t;
+				unsigned long nanosec_rem;
+
+				/*
+				 * force the log level token to be
+				 * before the time output.
+				 */
+				if (p[0] == '<' && p[1] >='0' &&
+				   p[1] <= '7' && p[2] == '>') {
+					loglev_char = p[1];
+					p += 3;
+					printed_len += 3;
+				} else {
+					loglev_char = default_message_loglevel
+						+ '0';
+				}
+				t = sched_clock();
+				nanosec_rem = do_div(t, 1000000000);
+				tlen = sprintf(tbuf,
+						"<%c>[%5lu.%06lu] ",
+						loglev_char,
+						(unsigned long)t,
+						nanosec_rem/1000);
+
+				for (tp = tbuf; tp < tbuf + tlen; tp++)
+					emit_log_char(*tp);
+				printed_len += tlen - 3;
+			} else {
+				if (p[0] != '<' || p[1] < '0' ||
+				   p[1] > '7' || p[2] != '>') {
+					emit_log_char('<');
+					emit_log_char(default_message_loglevel
+						+ '0');
+					emit_log_char('>');
+				}
+				printed_len += 3;
 			}
 			log_level_unknown = 0;
+			if (!*p)
+				break;
 		}
 		emit_log_char(*p);
 		if (*p == '\n')
diff -Nru a/kernel/sched.c b/kernel/sched.c
--- a/kernel/sched.c	2005-03-11 12:51:50 -08:00
+++ b/kernel/sched.c	2005-03-11 12:51:50 -08:00
@@ -40,11 +40,13 @@
 #include <linux/timer.h>
 #include <linux/rcupdate.h>
 #include <linux/cpu.h>
+#include <linux/cpuset.h>
 #include <linux/percpu.h>
 #include <linux/kthread.h>
 #include <linux/seq_file.h>
 #include <linux/syscalls.h>
 #include <linux/times.h>
+#include <linux/acct.h>
 #include <asm/tlb.h>
 
 #include <asm/unistd.h>
@@ -2241,6 +2243,32 @@
 EXPORT_PER_CPU_SYMBOL(kstat);
 
 /*
+ * This is called on clock ticks and on context switches.
+ * Bank in p->sched_time the ns elapsed since the last tick or switch.
+ */
+static inline void update_cpu_clock(task_t *p, runqueue_t *rq,
+				    unsigned long long now)
+{
+	unsigned long long last = max(p->timestamp, rq->timestamp_last_tick);
+	p->sched_time += now - last;
+}
+
+/*
+ * Return current->sched_time plus any more ns on the sched_clock
+ * that have not yet been banked.
+ */
+unsigned long long current_sched_time(const task_t *tsk)
+{
+	unsigned long long ns;
+	unsigned long flags;
+	local_irq_save(flags);
+	ns = max(tsk->timestamp, task_rq(tsk)->timestamp_last_tick);
+	ns = tsk->sched_time + (sched_clock() - ns);
+	local_irq_restore(flags);
+	return ns;
+}
+
+/*
  * We place interactive tasks back into the active array, if possible.
  *
  * To guarantee that this does not starve expired tasks we ignore the
@@ -2257,70 +2285,6 @@
 			((rq)->curr->static_prio > (rq)->best_expired_prio))
 
 /*
- * Do the virtual cpu time signal calculations.
- * @p: the process that the cpu time gets accounted to
- * @cputime: the cpu time spent in user space since the last update
- */
-static inline void account_it_virt(struct task_struct * p, cputime_t cputime)
-{
-	cputime_t it_virt = p->it_virt_value;
-
-	if (cputime_gt(it_virt, cputime_zero) &&
-	    cputime_gt(cputime, cputime_zero)) {
-		if (cputime_ge(cputime, it_virt)) {
-			it_virt = cputime_add(it_virt, p->it_virt_incr);
-			send_sig(SIGVTALRM, p, 1);
-		}
-		it_virt = cputime_sub(it_virt, cputime);
-		p->it_virt_value = it_virt;
-	}
-}
-
-/*
- * Do the virtual profiling signal calculations.
- * @p: the process that the cpu time gets accounted to
- * @cputime: the cpu time spent in user and kernel space since the last update
- */
-static void account_it_prof(struct task_struct *p, cputime_t cputime)
-{
-	cputime_t it_prof = p->it_prof_value;
-
-	if (cputime_gt(it_prof, cputime_zero) &&
-	    cputime_gt(cputime, cputime_zero)) {
-		if (cputime_ge(cputime, it_prof)) {
-			it_prof = cputime_add(it_prof, p->it_prof_incr);
-			send_sig(SIGPROF, p, 1);
-		}
-		it_prof = cputime_sub(it_prof, cputime);
-		p->it_prof_value = it_prof;
-	}
-}
-
-/*
- * Check if the process went over its cputime resource limit after
- * some cpu time got added to utime/stime.
- * @p: the process that the cpu time gets accounted to
- * @cputime: the cpu time spent in user and kernel space since the last update
- */
-static void check_rlimit(struct task_struct *p, cputime_t cputime)
-{
-	cputime_t total, tmp;
-	unsigned long secs;
-
-	total = cputime_add(p->utime, p->stime);
-	secs = cputime_to_secs(total);
-	if (unlikely(secs >= p->signal->rlim[RLIMIT_CPU].rlim_cur)) {
-		/* Send SIGXCPU every second. */
-		tmp = cputime_sub(total, cputime);
-		if (cputime_to_secs(tmp) < secs)
-			send_sig(SIGXCPU, p, 1);
-		/* and SIGKILL when we go over max.. */
-		if (secs >= p->signal->rlim[RLIMIT_CPU].rlim_max)
-			send_sig(SIGKILL, p, 1);
-	}
-}
-
-/*
  * Account user cpu time to a process.
  * @p: the process that the cpu time gets accounted to
  * @hardirq_offset: the offset to subtract from hardirq_count()
@@ -2333,11 +2297,6 @@
 
 	p->utime = cputime_add(p->utime, cputime);
 
-	/* Check for signals (SIGVTALRM, SIGPROF, SIGXCPU & SIGKILL). */
-	check_rlimit(p, cputime);
-	account_it_virt(p, cputime);
-	account_it_prof(p, cputime);
-
 	/* Add user time to cpustat. */
 	tmp = cputime_to_cputime64(cputime);
 	if (TASK_NICE(p) > 0)
@@ -2361,12 +2320,6 @@
 
 	p->stime = cputime_add(p->stime, cputime);
 
-	/* Check for signals (SIGPROF, SIGXCPU & SIGKILL). */
-	if (likely(p->signal && p->exit_state < EXIT_ZOMBIE)) {
-		check_rlimit(p, cputime);
-		account_it_prof(p, cputime);
-	}
-
 	/* Add system time to cpustat. */
 	tmp = cputime_to_cputime64(cputime);
 	if (hardirq_count() - hardirq_offset)
@@ -2379,6 +2332,10 @@
 		cpustat->iowait = cputime64_add(cpustat->iowait, tmp);
 	else
 		cpustat->idle = cputime64_add(cpustat->idle, tmp);
+	/* Account for system time used */
+	acct_update_integrals(p);
+	/* Update rss highwater mark */
+	update_mem_hiwater(p);
 }
 
 /*
@@ -2414,8 +2371,11 @@
 	int cpu = smp_processor_id();
 	runqueue_t *rq = this_rq();
 	task_t *p = current;
+	unsigned long long now = sched_clock();
 
-	rq->timestamp_last_tick = sched_clock();
+	update_cpu_clock(p, rq, now);
+
+	rq->timestamp_last_tick = now;
 
 	if (p == rq->idle) {
 		if (wake_priority_sleeper(rq))
@@ -2799,6 +2759,8 @@
 	clear_tsk_need_resched(prev);
 	rcu_qsctr_inc(task_cpu(prev));
 
+	update_cpu_clock(prev, rq, now);
+
 	prev->sleep_avg -= run_time;
 	if ((long)prev->sleep_avg <= 0)
 		prev->sleep_avg = 0;
@@ -3578,6 +3540,7 @@
 {
 	task_t *p;
 	int retval;
+	cpumask_t cpus_allowed;
 
 	lock_cpu_hotplug();
 	read_lock(&tasklist_lock);
@@ -3602,6 +3565,8 @@
 			!capable(CAP_SYS_NICE))
 		goto out_unlock;
 
+	cpus_allowed = cpuset_cpus_allowed(p);
+	cpus_and(new_mask, new_mask, cpus_allowed);
 	retval = set_cpus_allowed(p, new_mask);
 
 out_unlock:
@@ -4058,6 +4023,7 @@
 	idle->array = NULL;
 	idle->prio = MAX_PRIO;
 	idle->state = TASK_RUNNING;
+	idle->cpus_allowed = cpumask_of_cpu(cpu);
 	set_task_cpu(idle, cpu);
 
 	spin_lock_irqsave(&rq->lock, flags);
@@ -4278,7 +4244,7 @@
 
 	/* No more Mr. Nice Guy. */
 	if (dest_cpu == NR_CPUS) {
-		cpus_setall(tsk->cpus_allowed);
+		tsk->cpus_allowed = cpuset_cpus_allowed(tsk);
 		dest_cpu = any_online_cpu(tsk->cpus_allowed);
 
 		/*
diff -Nru a/kernel/seccomp.c b/kernel/seccomp.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/kernel/seccomp.c	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,74 @@
+/*
+ * linux/kernel/seccomp.c
+ *
+ * Copyright 2004-2005  Andrea Arcangeli <andrea@cpushare.com>
+ *
+ * This defines a simple but solid secure-computing mode.
+ */
+
+#include <linux/seccomp.h>
+#include <linux/sched.h>
+#include <asm/unistd.h>
+#ifdef TIF_IA32
+#include <asm/ia32_unistd.h>
+#endif
+
+/* #define SECCOMP_DEBUG 1 */
+
+/*
+ * Secure computing mode 1 allows only read/write/exit/sigreturn.
+ * To be fully secure this must be combined with rlimit
+ * to limit the stack allocations too.
+ */
+static int mode1_syscalls[] = {
+	__NR_read, __NR_write, __NR_exit,
+	/*
+	 * Allow either sigreturn or rt_sigreturn, newer archs
+	 * like x86-64 only defines __NR_rt_sigreturn.
+	 */
+#ifdef __NR_sigreturn
+	__NR_sigreturn,
+#else
+	__NR_rt_sigreturn,
+#endif
+	0, /* null terminated */
+};
+
+#ifdef TIF_IA32
+static int mode1_syscalls_32bit[] = {
+	__NR_ia32_read, __NR_ia32_write, __NR_ia32_exit,
+	/*
+	 * Allow either sigreturn or rt_sigreturn, newer archs
+	 * like x86-64 only defines __NR_rt_sigreturn.
+	 */
+	__NR_ia32_sigreturn,
+	0, /* null terminated */
+};
+#endif
+
+void __secure_computing(int this_syscall)
+{
+	int mode = current->seccomp.mode;
+	int * syscall;
+
+	switch (mode) {
+	case 1:
+		syscall = mode1_syscalls;
+#ifdef TIF_IA32
+		if (test_thread_flag(TIF_IA32))
+			syscall = mode1_syscalls_32bit;
+#endif
+		do {
+			if (*syscall == this_syscall)
+				return;
+		} while (*++syscall);
+		break;
+	default:
+		BUG();
+	}
+
+#ifdef SECCOMP_DEBUG
+	dump_stack();
+#endif
+	do_exit(SIGKILL);
+}
diff -Nru a/kernel/signal.c b/kernel/signal.c
--- a/kernel/signal.c	2005-03-11 12:51:42 -08:00
+++ b/kernel/signal.c	2005-03-11 12:51:42 -08:00
@@ -22,6 +22,7 @@
 #include <linux/security.h>
 #include <linux/syscalls.h>
 #include <linux/ptrace.h>
+#include <linux/posix-timers.h>
 #include <asm/param.h>
 #include <asm/uaccess.h>
 #include <asm/unistd.h>
@@ -260,19 +261,23 @@
 	return sig;
 }
 
-static struct sigqueue *__sigqueue_alloc(struct task_struct *t, int flags)
+static struct sigqueue *__sigqueue_alloc(struct task_struct *t, int flags,
+					 int override_rlimit)
 {
 	struct sigqueue *q = NULL;
 
-	if (atomic_read(&t->user->sigpending) <
+	atomic_inc(&t->user->sigpending);
+	if (override_rlimit ||
+	    atomic_read(&t->user->sigpending) <=
 			t->signal->rlim[RLIMIT_SIGPENDING].rlim_cur)
 		q = kmem_cache_alloc(sigqueue_cachep, flags);
-	if (q) {
+	if (unlikely(q == NULL)) {
+		atomic_dec(&t->user->sigpending);
+	} else {
 		INIT_LIST_HEAD(&q->list);
 		q->flags = 0;
 		q->lock = NULL;
 		q->user = get_uid(t->user);
-		atomic_inc(&q->user->sigpending);
 	}
 	return(q);
 }
@@ -347,7 +352,9 @@
 	if (!atomic_read(&sig->count))
 		BUG();
 	spin_lock(&sighand->siglock);
+	posix_cpu_timers_exit(tsk);
 	if (atomic_dec_and_test(&sig->count)) {
+		posix_cpu_timers_exit_group(tsk);
 		if (tsk == sig->curr_target)
 			sig->curr_target = next_thread(tsk);
 		tsk->signal = NULL;
@@ -381,6 +388,7 @@
 		sig->maj_flt += tsk->maj_flt;
 		sig->nvcsw += tsk->nvcsw;
 		sig->nivcsw += tsk->nivcsw;
+		sig->sched_time += tsk->sched_time;
 		spin_unlock(&sighand->siglock);
 		sig = NULL;	/* Marker for below.  */
 	}
@@ -402,6 +410,7 @@
 		 * signals are constrained to threads inside the group.
 		 */
 		exit_itimers(sig);
+		exit_thread_group_keys(sig);
 		kmem_cache_free(signal_cachep, sig);
 	}
 }
@@ -564,7 +573,15 @@
 	if ( signr &&
 	     ((info->si_code & __SI_MASK) == __SI_TIMER) &&
 	     info->si_sys_private){
+		/*
+		 * Release the siglock to ensure proper locking order
+		 * of timer locks outside of siglocks.  Note, we leave
+		 * irqs disabled here, since the posix-timers code is
+		 * about to disable them again anyway.
+		 */
+		spin_unlock(&tsk->sighand->siglock);
 		do_schedule_next_timer(info);
+		spin_lock(&tsk->sighand->siglock);
 	}
 	return signr;
 }
@@ -793,7 +810,9 @@
 	   make sure at least one signal gets delivered and don't
 	   pass on the info struct.  */
 
-	q = __sigqueue_alloc(t, GFP_ATOMIC);
+	q = __sigqueue_alloc(t, GFP_ATOMIC, (sig < SIGRTMIN &&
+					     ((unsigned long) info < 2 ||
+					      info->si_code >= 0)));
 	if (q) {
 		list_add_tail(&q->list, &signals->list);
 		switch ((unsigned long) info) {
@@ -1036,7 +1055,7 @@
 	return;
 }
 
-static int
+int
 __group_send_sig_info(int sig, struct siginfo *info, struct task_struct *p)
 {
 	int ret = 0;
@@ -1316,7 +1335,7 @@
 {
 	struct sigqueue *q;
 
-	if ((q = __sigqueue_alloc(current, GFP_KERNEL)))
+	if ((q = __sigqueue_alloc(current, GFP_KERNEL, 0)))
 		q->flags |= SIGQUEUE_PREALLOC;
 	return(q);
 }
diff -Nru a/kernel/softirq.c b/kernel/softirq.c
--- a/kernel/softirq.c	2005-03-11 12:51:42 -08:00
+++ b/kernel/softirq.c	2005-03-11 12:51:42 -08:00
@@ -355,8 +355,12 @@
 	set_current_state(TASK_INTERRUPTIBLE);
 
 	while (!kthread_should_stop()) {
-		if (!local_softirq_pending())
+		preempt_disable();
+		if (!local_softirq_pending()) {
+			preempt_enable_no_resched();
 			schedule();
+			preempt_disable();
+		}
 
 		__set_current_state(TASK_RUNNING);
 
@@ -364,14 +368,14 @@
 			/* Preempt disable stops cpu going offline.
 			   If already offline, we'll be on wrong CPU:
 			   don't process */
-			preempt_disable();
 			if (cpu_is_offline((long)__bind_cpu))
 				goto wait_to_die;
 			do_softirq();
-			preempt_enable();
+			preempt_enable_no_resched();
 			cond_resched();
+			preempt_disable();
 		}
-
+		preempt_enable();
 		set_current_state(TASK_INTERRUPTIBLE);
 	}
 	__set_current_state(TASK_RUNNING);
diff -Nru a/kernel/sys.c b/kernel/sys.c
--- a/kernel/sys.c	2005-03-11 12:51:41 -08:00
+++ b/kernel/sys.c	2005-03-11 12:51:41 -08:00
@@ -20,6 +20,7 @@
 #include <linux/device.h>
 #include <linux/key.h>
 #include <linux/times.h>
+#include <linux/posix-timers.h>
 #include <linux/security.h>
 #include <linux/dcookies.h>
 #include <linux/suspend.h>
@@ -216,12 +217,13 @@
 }
 
 EXPORT_SYMBOL(unregister_reboot_notifier);
+
 static int set_one_prio(struct task_struct *p, int niceval, int error)
 {
 	int no_nice;
 
 	if (p->uid != current->euid &&
-		p->uid != current->uid && !capable(CAP_SYS_NICE)) {
+		p->euid != current->euid && !capable(CAP_SYS_NICE)) {
 		error = -EPERM;
 		goto out;
 	}
@@ -1501,6 +1503,20 @@
 	task_lock(current->group_leader);
 	*old_rlim = new_rlim;
 	task_unlock(current->group_leader);
+
+	if (resource == RLIMIT_CPU && new_rlim.rlim_cur != RLIM_INFINITY &&
+	    (cputime_eq(current->signal->it_prof_expires, cputime_zero) ||
+	     new_rlim.rlim_cur <= cputime_to_secs(
+		     current->signal->it_prof_expires))) {
+		cputime_t cputime = secs_to_cputime(new_rlim.rlim_cur);
+		read_lock(&tasklist_lock);
+		spin_lock_irq(&current->sighand->siglock);
+		set_process_cpu_timer(current, CPUCLOCK_PROF,
+				      &cputime, NULL);
+		spin_unlock_irq(&current->sighand->siglock);
+		read_unlock(&tasklist_lock);
+	}
+
 	return 0;
 }
 
diff -Nru a/kernel/sys_ni.c b/kernel/sys_ni.c
--- a/kernel/sys_ni.c	2005-03-11 12:51:50 -08:00
+++ b/kernel/sys_ni.c	2005-03-11 12:51:50 -08:00
@@ -12,74 +12,74 @@
 	return -ENOSYS;
 }
 
-cond_syscall(sys_nfsservctl)
-cond_syscall(sys_quotactl)
-cond_syscall(sys_acct)
-cond_syscall(sys_lookup_dcookie)
-cond_syscall(sys_swapon)
-cond_syscall(sys_swapoff)
-cond_syscall(sys_init_module)
-cond_syscall(sys_delete_module)
-cond_syscall(sys_socketpair)
-cond_syscall(sys_bind)
-cond_syscall(sys_listen)
-cond_syscall(sys_accept)
-cond_syscall(sys_connect)
-cond_syscall(sys_getsockname)
-cond_syscall(sys_getpeername)
-cond_syscall(sys_sendto)
-cond_syscall(sys_send)
-cond_syscall(sys_recvfrom)
-cond_syscall(sys_recv)
-cond_syscall(sys_socket)
-cond_syscall(sys_setsockopt)
-cond_syscall(sys_getsockopt)
-cond_syscall(sys_shutdown)
-cond_syscall(sys_sendmsg)
-cond_syscall(sys_recvmsg)
-cond_syscall(sys_socketcall)
-cond_syscall(sys_futex)
-cond_syscall(compat_sys_futex)
-cond_syscall(sys_epoll_create)
-cond_syscall(sys_epoll_ctl)
-cond_syscall(sys_epoll_wait)
-cond_syscall(sys_semget)
-cond_syscall(sys_semop)
-cond_syscall(sys_semtimedop)
-cond_syscall(sys_semctl)
-cond_syscall(sys_msgget)
-cond_syscall(sys_msgsnd)
-cond_syscall(sys_msgrcv)
-cond_syscall(sys_msgctl)
-cond_syscall(sys_shmget)
-cond_syscall(sys_shmdt)
-cond_syscall(sys_shmctl)
-cond_syscall(sys_mq_open)
-cond_syscall(sys_mq_unlink)
-cond_syscall(sys_mq_timedsend)
-cond_syscall(sys_mq_timedreceive)
-cond_syscall(sys_mq_notify)
-cond_syscall(sys_mq_getsetattr)
-cond_syscall(compat_sys_mq_open)
-cond_syscall(compat_sys_mq_timedsend)
-cond_syscall(compat_sys_mq_timedreceive)
-cond_syscall(compat_sys_mq_notify)
-cond_syscall(compat_sys_mq_getsetattr)
-cond_syscall(sys_mbind)
-cond_syscall(sys_get_mempolicy)
-cond_syscall(sys_set_mempolicy)
-cond_syscall(compat_sys_mbind)
-cond_syscall(compat_sys_get_mempolicy)
-cond_syscall(compat_sys_set_mempolicy)
-cond_syscall(sys_add_key)
-cond_syscall(sys_request_key)
-cond_syscall(sys_keyctl)
-cond_syscall(compat_sys_keyctl)
-cond_syscall(compat_sys_socketcall)
+cond_syscall(sys_nfsservctl);
+cond_syscall(sys_quotactl);
+cond_syscall(sys_acct);
+cond_syscall(sys_lookup_dcookie);
+cond_syscall(sys_swapon);
+cond_syscall(sys_swapoff);
+cond_syscall(sys_init_module);
+cond_syscall(sys_delete_module);
+cond_syscall(sys_socketpair);
+cond_syscall(sys_bind);
+cond_syscall(sys_listen);
+cond_syscall(sys_accept);
+cond_syscall(sys_connect);
+cond_syscall(sys_getsockname);
+cond_syscall(sys_getpeername);
+cond_syscall(sys_sendto);
+cond_syscall(sys_send);
+cond_syscall(sys_recvfrom);
+cond_syscall(sys_recv);
+cond_syscall(sys_socket);
+cond_syscall(sys_setsockopt);
+cond_syscall(sys_getsockopt);
+cond_syscall(sys_shutdown);
+cond_syscall(sys_sendmsg);
+cond_syscall(sys_recvmsg);
+cond_syscall(sys_socketcall);
+cond_syscall(sys_futex);
+cond_syscall(compat_sys_futex);
+cond_syscall(sys_epoll_create);
+cond_syscall(sys_epoll_ctl);
+cond_syscall(sys_epoll_wait);
+cond_syscall(sys_semget);
+cond_syscall(sys_semop);
+cond_syscall(sys_semtimedop);
+cond_syscall(sys_semctl);
+cond_syscall(sys_msgget);
+cond_syscall(sys_msgsnd);
+cond_syscall(sys_msgrcv);
+cond_syscall(sys_msgctl);
+cond_syscall(sys_shmget);
+cond_syscall(sys_shmdt);
+cond_syscall(sys_shmctl);
+cond_syscall(sys_mq_open);
+cond_syscall(sys_mq_unlink);
+cond_syscall(sys_mq_timedsend);
+cond_syscall(sys_mq_timedreceive);
+cond_syscall(sys_mq_notify);
+cond_syscall(sys_mq_getsetattr);
+cond_syscall(compat_sys_mq_open);
+cond_syscall(compat_sys_mq_timedsend);
+cond_syscall(compat_sys_mq_timedreceive);
+cond_syscall(compat_sys_mq_notify);
+cond_syscall(compat_sys_mq_getsetattr);
+cond_syscall(sys_mbind);
+cond_syscall(sys_get_mempolicy);
+cond_syscall(sys_set_mempolicy);
+cond_syscall(compat_sys_mbind);
+cond_syscall(compat_sys_get_mempolicy);
+cond_syscall(compat_sys_set_mempolicy);
+cond_syscall(sys_add_key);
+cond_syscall(sys_request_key);
+cond_syscall(sys_keyctl);
+cond_syscall(compat_sys_keyctl);
+cond_syscall(compat_sys_socketcall);
 
 /* arch-specific weak syscall entries */
-cond_syscall(sys_pciconfig_read)
-cond_syscall(sys_pciconfig_write)
-cond_syscall(sys_pciconfig_iobase)
-cond_syscall(sys32_ipc)
-cond_syscall(sys32_sysctl)
+cond_syscall(sys_pciconfig_read);
+cond_syscall(sys_pciconfig_write);
+cond_syscall(sys_pciconfig_iobase);
+cond_syscall(sys32_ipc);
+cond_syscall(sys32_sysctl);
diff -Nru a/kernel/sysctl.c b/kernel/sysctl.c
--- a/kernel/sysctl.c	2005-03-11 12:51:41 -08:00
+++ b/kernel/sysctl.c	2005-03-11 12:51:41 -08:00
@@ -121,6 +121,8 @@
 extern int acct_parm[];
 #endif
 
+int randomize_va_space = 1;
+
 static int parse_table(int __user *, int, void __user *, size_t __user *, void __user *, size_t,
 		       ctl_table *, void **);
 static int proc_doutsstring(ctl_table *table, int write, struct file *filp,
@@ -632,6 +634,15 @@
 		.proc_handler	= &proc_dointvec,
 	},
 #endif
+	{
+		.ctl_name	= KERN_RANDOMIZE,
+		.procname	= "randomize_va_space",
+		.data		= &randomize_va_space,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec,
+	},
+
 	{ .ctl_name = 0 }
 };
 
diff -Nru a/kernel/timer.c b/kernel/timer.c
--- a/kernel/timer.c	2005-03-11 12:51:51 -08:00
+++ b/kernel/timer.c	2005-03-11 12:51:51 -08:00
@@ -30,6 +30,7 @@
 #include <linux/thread_info.h>
 #include <linux/time.h>
 #include <linux/jiffies.h>
+#include <linux/posix-timers.h>
 #include <linux/cpu.h>
 #include <linux/syscalls.h>
 
@@ -48,8 +49,9 @@
 /*
  * per-CPU timer vector definitions:
  */
-#define TVN_BITS 6
-#define TVR_BITS 8
+
+#define TVN_BITS (CONFIG_BASE_SMALL ? 4 : 6)
+#define TVR_BITS (CONFIG_BASE_SMALL ? 6 : 8)
 #define TVN_SIZE (1 << TVN_BITS)
 #define TVR_SIZE (1 << TVR_BITS)
 #define TVN_MASK (TVN_SIZE - 1)
@@ -824,6 +826,7 @@
 	if (rcu_pending(cpu))
 		rcu_check_callbacks(cpu, user_tick);
 	scheduler_tick();
+ 	run_posix_cpu_timers(p);
 }
 
 /*
@@ -843,6 +846,8 @@
  * Requires xtime_lock to access.
  */
 unsigned long avenrun[3];
+
+EXPORT_SYMBOL(avenrun);
 
 /*
  * calc_load - given tick count, update the avenrun load estimates.
diff -Nru a/kernel/user.c b/kernel/user.c
--- a/kernel/user.c	2005-03-11 12:51:42 -08:00
+++ b/kernel/user.c	2005-03-11 12:51:42 -08:00
@@ -18,7 +18,8 @@
  * UID task count cache, to get fast user lookup in "alloc_uid"
  * when changing user ID's (ie setuid() and friends).
  */
-#define UIDHASH_BITS		8
+
+#define UIDHASH_BITS (CONFIG_BASE_SMALL ? 3 : 8)
 #define UIDHASH_SZ		(1 << UIDHASH_BITS)
 #define UIDHASH_MASK		(UIDHASH_SZ - 1)
 #define __uidhashfn(uid)	(((uid >> UIDHASH_BITS) + uid) & UIDHASH_MASK)
diff -Nru a/kernel/workqueue.c b/kernel/workqueue.c
--- a/kernel/workqueue.c	2005-03-11 12:51:51 -08:00
+++ b/kernel/workqueue.c	2005-03-11 12:51:51 -08:00
@@ -423,6 +423,30 @@
 	flush_workqueue(keventd_wq);
 }
 
+/**
+ * cancel_rearming_delayed_workqueue - reliably kill off a delayed
+ *			work whose handler rearms the delayed work.
+ * @wq:   the controlling workqueue structure
+ * @work: the delayed work struct
+ */
+static void cancel_rearming_delayed_workqueue(struct workqueue_struct *wq,
+					struct work_struct *work)
+{
+	while (!cancel_delayed_work(work))
+		flush_workqueue(wq);
+}
+
+/**
+ * cancel_rearming_delayed_work - reliably kill off a delayed keventd
+ *			work whose handler rearms the delayed work.
+ * @work: the delayed work struct
+ */
+void cancel_rearming_delayed_work(struct work_struct *work)
+{
+	cancel_rearming_delayed_workqueue(keventd_wq, work);
+}
+EXPORT_SYMBOL(cancel_rearming_delayed_work);
+
 int keventd_up(void)
 {
 	return keventd_wq != NULL;
diff -Nru a/lib/Kconfig.debug b/lib/Kconfig.debug
--- a/lib/Kconfig.debug	2005-03-11 12:51:50 -08:00
+++ b/lib/Kconfig.debug	2005-03-11 12:51:50 -08:00
@@ -27,6 +27,15 @@
 	  Enables console device to interpret special characters as
 	  commands to dump state information.
 
+config PRINTK_TIME
+	bool "Show timing information on printks"
+	help
+	  Selecting this option causes timing information to be
+	  included in printk output.  This allows you to measure
+	  the interval between kernel operations, including bootup
+	  operations.  This is useful for identifying long delays
+	  in kernel startup.
+
 config SCHEDSTATS
 	bool "Collect scheduler statistics"
 	depends on DEBUG_KERNEL && PROC_FS
diff -Nru a/lib/Makefile b/lib/Makefile
--- a/lib/Makefile	2005-03-11 12:51:41 -08:00
+++ b/lib/Makefile	2005-03-11 12:51:41 -08:00
@@ -4,8 +4,11 @@
 
 lib-y := errno.o ctype.o string.o vsprintf.o cmdline.o \
 	 bust_spinlocks.o rbtree.o radix-tree.o dump_stack.o \
-	 kobject.o kref.o idr.o div64.o parser.o int_sqrt.o \
-	 bitmap.o extable.o kobject_uevent.o prio_tree.o
+	 kobject.o kref.o idr.o div64.o int_sqrt.o \
+	 bitmap.o extable.o kobject_uevent.o prio_tree.o sha1.o \
+	 halfmd4.o
+
+obj-y += sort.o parser.o
 
 ifeq ($(CONFIG_DEBUG_KOBJECT),y)
 CFLAGS_kobject.o += -DDEBUG
diff -Nru a/lib/bitmap.c b/lib/bitmap.c
--- a/lib/bitmap.c	2005-03-11 12:51:50 -08:00
+++ b/lib/bitmap.c	2005-03-11 12:51:50 -08:00
@@ -291,6 +291,7 @@
 #define nbits_to_hold_value(val)	fls(val)
 #define roundup_power2(val,modulus)	(((val) + (modulus) - 1) & ~((modulus) - 1))
 #define unhex(c)			(isdigit(c) ? (c - '0') : (toupper(c) - 'A' + 10))
+#define BASEDEC 10		/* fancier cpuset lists input in decimal */
 
 /**
  * bitmap_scnprintf - convert bitmap to an ASCII hex string.
@@ -408,6 +409,108 @@
 	return 0;
 }
 EXPORT_SYMBOL(bitmap_parse);
+
+/*
+ * bscnl_emit(buf, buflen, rbot, rtop, bp)
+ *
+ * Helper routine for bitmap_scnlistprintf().  Write decimal number
+ * or range to buf, suppressing output past buf+buflen, with optional
+ * comma-prefix.  Return len of what would be written to buf, if it
+ * all fit.
+ */
+static inline int bscnl_emit(char *buf, int buflen, int rbot, int rtop, int len)
+{
+	if (len > 0)
+		len += scnprintf(buf + len, buflen - len, ",");
+	if (rbot == rtop)
+		len += scnprintf(buf + len, buflen - len, "%d", rbot);
+	else
+		len += scnprintf(buf + len, buflen - len, "%d-%d", rbot, rtop);
+	return len;
+}
+
+/**
+ * bitmap_scnlistprintf - convert bitmap to list format ASCII string
+ * @buf: byte buffer into which string is placed
+ * @buflen: reserved size of @buf, in bytes
+ * @maskp: pointer to bitmap to convert
+ * @nmaskbits: size of bitmap, in bits
+ *
+ * Output format is a comma-separated list of decimal numbers and
+ * ranges.  Consecutively set bits are shown as two hyphen-separated
+ * decimal numbers, the smallest and largest bit numbers set in
+ * the range.  Output format is compatible with the format
+ * accepted as input by bitmap_parselist().
+ *
+ * The return value is the number of characters which would be
+ * generated for the given input, excluding the trailing '\0', as
+ * per ISO C99.
+ */
+int bitmap_scnlistprintf(char *buf, unsigned int buflen,
+	const unsigned long *maskp, int nmaskbits)
+{
+	int len = 0;
+	/* current bit is 'cur', most recently seen range is [rbot, rtop] */
+	int cur, rbot, rtop;
+
+	rbot = cur = find_first_bit(maskp, nmaskbits);
+	while (cur < nmaskbits) {
+		rtop = cur;
+		cur = find_next_bit(maskp, nmaskbits, cur+1);
+		if (cur >= nmaskbits || cur > rtop + 1) {
+			len = bscnl_emit(buf, buflen, rbot, rtop, len);
+			rbot = cur;
+		}
+	}
+	return len;
+}
+EXPORT_SYMBOL(bitmap_scnlistprintf);
+
+/**
+ * bitmap_parselist - convert list format ASCII string to bitmap
+ * @buf: read nul-terminated user string from this buffer
+ * @mask: write resulting mask here
+ * @nmaskbits: number of bits in mask to be written
+ *
+ * Input format is a comma-separated list of decimal numbers and
+ * ranges.  Consecutively set bits are shown as two hyphen-separated
+ * decimal numbers, the smallest and largest bit numbers set in
+ * the range.
+ *
+ * Returns 0 on success, -errno on invalid input strings:
+ *    -EINVAL:   second number in range smaller than first
+ *    -EINVAL:   invalid character in string
+ *    -ERANGE:   bit number specified too large for mask
+ */
+int bitmap_parselist(const char *bp, unsigned long *maskp, int nmaskbits)
+{
+	unsigned a, b;
+
+	bitmap_zero(maskp, nmaskbits);
+	do {
+		if (!isdigit(*bp))
+			return -EINVAL;
+		b = a = simple_strtoul(bp, (char **)&bp, BASEDEC);
+		if (*bp == '-') {
+			bp++;
+			if (!isdigit(*bp))
+				return -EINVAL;
+			b = simple_strtoul(bp, (char **)&bp, BASEDEC);
+		}
+		if (!(a <= b))
+			return -EINVAL;
+		if (b >= nmaskbits)
+			return -ERANGE;
+		while (a <= b) {
+			set_bit(a, maskp);
+			a++;
+		}
+		if (*bp == ',')
+			bp++;
+	} while (*bp != '\0' && *bp != '\n');
+	return 0;
+}
+EXPORT_SYMBOL(bitmap_parselist);
 
 /**
  *	bitmap_find_free_region - find a contiguous aligned mem region
diff -Nru a/lib/extable.c b/lib/extable.c
--- a/lib/extable.c	2005-03-11 12:51:52 -08:00
+++ b/lib/extable.c	2005-03-11 12:51:52 -08:00
@@ -13,6 +13,7 @@
 #include <linux/config.h>
 #include <linux/module.h>
 #include <linux/init.h>
+#include <linux/sort.h>
 #include <asm/uaccess.h>
 
 extern struct exception_table_entry __start___ex_table[];
@@ -25,26 +26,23 @@
  * This is used both for the kernel exception table and for
  * the exception tables of modules that get loaded.
  */
+static int cmp_ex(const void *a, const void *b)
+{
+	const struct exception_table_entry *x = a, *y = b;
+
+	/* avoid overflow */
+	if (x->insn > y->insn)
+		return 1;
+	if (x->insn < y->insn)
+		return -1;
+	return 0;
+}
+
 void sort_extable(struct exception_table_entry *start,
 		  struct exception_table_entry *finish)
 {
-	struct exception_table_entry el, *p, *q;
-
-	/* insertion sort */
-	for (p = start + 1; p < finish; ++p) {
-		/* start .. p-1 is sorted */
-		if (p[0].insn < p[-1].insn) {
-			/* move element p down to its right place */
-			el = *p;
-			q = p;
-			do {
-				/* el comes before q[-1], move q[-1] up one */
-				q[0] = q[-1];
-				--q;
-			} while (q > start && el.insn < q[-1].insn);
-			*q = el;
-		}
-	}
+	sort(start, finish - start, sizeof(struct exception_table_entry),
+	     cmp_ex, NULL);
 }
 #endif
 
diff -Nru a/lib/halfmd4.c b/lib/halfmd4.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/lib/halfmd4.c	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,66 @@
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/cryptohash.h>
+
+/* F, G and H are basic MD4 functions: selection, majority, parity */
+#define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))
+#define G(x, y, z) (((x) & (y)) + (((x) ^ (y)) & (z)))
+#define H(x, y, z) ((x) ^ (y) ^ (z))
+
+/*
+ * The generic round function.  The application is so specific that
+ * we don't bother protecting all the arguments with parens, as is generally
+ * good macro practice, in favor of extra legibility.
+ * Rotation is separate from addition to prevent recomputation
+ */
+#define ROUND(f, a, b, c, d, x, s)	\
+	(a += f(b, c, d) + x, a = (a << s) | (a >> (32 - s)))
+#define K1 0
+#define K2 013240474631UL
+#define K3 015666365641UL
+
+/*
+ * Basic cut-down MD4 transform.  Returns only 32 bits of result.
+ */
+__u32 half_md4_transform(__u32 buf[4], __u32 const in[8])
+{
+	__u32 a = buf[0], b = buf[1], c = buf[2], d = buf[3];
+
+	/* Round 1 */
+	ROUND(F, a, b, c, d, in[0] + K1,  3);
+	ROUND(F, d, a, b, c, in[1] + K1,  7);
+	ROUND(F, c, d, a, b, in[2] + K1, 11);
+	ROUND(F, b, c, d, a, in[3] + K1, 19);
+	ROUND(F, a, b, c, d, in[4] + K1,  3);
+	ROUND(F, d, a, b, c, in[5] + K1,  7);
+	ROUND(F, c, d, a, b, in[6] + K1, 11);
+	ROUND(F, b, c, d, a, in[7] + K1, 19);
+
+	/* Round 2 */
+	ROUND(G, a, b, c, d, in[1] + K2,  3);
+	ROUND(G, d, a, b, c, in[3] + K2,  5);
+	ROUND(G, c, d, a, b, in[5] + K2,  9);
+	ROUND(G, b, c, d, a, in[7] + K2, 13);
+	ROUND(G, a, b, c, d, in[0] + K2,  3);
+	ROUND(G, d, a, b, c, in[2] + K2,  5);
+	ROUND(G, c, d, a, b, in[4] + K2,  9);
+	ROUND(G, b, c, d, a, in[6] + K2, 13);
+
+	/* Round 3 */
+	ROUND(H, a, b, c, d, in[3] + K3,  3);
+	ROUND(H, d, a, b, c, in[7] + K3,  9);
+	ROUND(H, c, d, a, b, in[2] + K3, 11);
+	ROUND(H, b, c, d, a, in[6] + K3, 15);
+	ROUND(H, a, b, c, d, in[1] + K3,  3);
+	ROUND(H, d, a, b, c, in[5] + K3,  9);
+	ROUND(H, c, d, a, b, in[0] + K3, 11);
+	ROUND(H, b, c, d, a, in[4] + K3, 15);
+
+	buf[0] += a;
+	buf[1] += b;
+	buf[2] += c;
+	buf[3] += d;
+
+	return buf[1]; /* "most hashed" word */
+}
+EXPORT_SYMBOL(half_md4_transform);
diff -Nru a/lib/kobject.c b/lib/kobject.c
--- a/lib/kobject.c	2005-03-11 12:51:51 -08:00
+++ b/lib/kobject.c	2005-03-11 12:51:51 -08:00
@@ -140,9 +140,9 @@
 static void unlink(struct kobject * kobj)
 {
 	if (kobj->kset) {
-		down_write(&kobj->kset->subsys->rwsem);
+		spin_lock(&kobj->kset->list_lock);
 		list_del_init(&kobj->entry);
-		up_write(&kobj->kset->subsys->rwsem);
+		spin_unlock(&kobj->kset->list_lock);
 	}
 	kobject_put(kobj);
 }
@@ -168,13 +168,13 @@
 		 kobj->kset ? kobj->kset->kobj.name : "<NULL>" );
 
 	if (kobj->kset) {
-		down_write(&kobj->kset->subsys->rwsem);
+		spin_lock(&kobj->kset->list_lock);
 
 		if (!parent)
 			parent = kobject_get(&kobj->kset->kobj);
 
 		list_add_tail(&kobj->entry,&kobj->kset->list);
-		up_write(&kobj->kset->subsys->rwsem);
+		spin_unlock(&kobj->kset->list_lock);
 	}
 	kobj->parent = parent;
 
@@ -380,6 +380,7 @@
 {
 	kobject_init(&k->kobj);
 	INIT_LIST_HEAD(&k->list);
+	spin_lock_init(&k->list_lock);
 }
 
 
@@ -444,7 +445,7 @@
 	struct list_head * entry;
 	struct kobject * ret = NULL;
 
-	down_read(&kset->subsys->rwsem);
+	spin_lock(&kset->list_lock);
 	list_for_each(entry,&kset->list) {
 		struct kobject * k = to_kobj(entry);
 		if (kobject_name(k) && !strcmp(kobject_name(k),name)) {
@@ -452,7 +453,7 @@
 			break;
 		}
 	}
-	up_read(&kset->subsys->rwsem);
+	spin_unlock(&kset->list_lock);
 	return ret;
 }
 
@@ -524,7 +525,6 @@
 	}
 }
 
-EXPORT_SYMBOL(kobject_get_path);
 EXPORT_SYMBOL(kobject_init);
 EXPORT_SYMBOL(kobject_register);
 EXPORT_SYMBOL(kobject_unregister);
@@ -532,7 +532,6 @@
 EXPORT_SYMBOL(kobject_put);
 EXPORT_SYMBOL(kobject_add);
 EXPORT_SYMBOL(kobject_del);
-EXPORT_SYMBOL(kobject_rename);
 
 EXPORT_SYMBOL(kset_register);
 EXPORT_SYMBOL(kset_unregister);
diff -Nru a/lib/kref.c b/lib/kref.c
--- a/lib/kref.c	2005-03-11 12:51:52 -08:00
+++ b/lib/kref.c	2005-03-11 12:51:52 -08:00
@@ -42,14 +42,21 @@
  *	     in as this function.
  *
  * Decrement the refcount, and if 0, call release().
+ * Return 1 if the object was removed, otherwise return 0.  Beware, if this
+ * function returns 0, you still can not count on the kref from remaining in
+ * memory.  Only use the return value if you want to see if the kref is now
+ * gone, not present.
  */
-void kref_put(struct kref *kref, void (*release) (struct kref *kref))
+int kref_put(struct kref *kref, void (*release)(struct kref *kref))
 {
 	WARN_ON(release == NULL);
 	WARN_ON(release == (void (*)(struct kref *))kfree);
 
-	if (atomic_dec_and_test(&kref->refcount))
+	if (atomic_dec_and_test(&kref->refcount)) {
 		release(kref);
+		return 1;
+	}
+	return 0;
 }
 
 EXPORT_SYMBOL(kref_init);
diff -Nru a/lib/rwsem-spinlock.c b/lib/rwsem-spinlock.c
--- a/lib/rwsem-spinlock.c	2005-03-11 12:51:52 -08:00
+++ b/lib/rwsem-spinlock.c	2005-03-11 12:51:52 -08:00
@@ -140,12 +140,12 @@
 
 	rwsemtrace(sem, "Entering __down_read");
 
-	spin_lock(&sem->wait_lock);
+	spin_lock_irq(&sem->wait_lock);
 
 	if (sem->activity >= 0 && list_empty(&sem->wait_list)) {
 		/* granted */
 		sem->activity++;
-		spin_unlock(&sem->wait_lock);
+		spin_unlock_irq(&sem->wait_lock);
 		goto out;
 	}
 
@@ -160,7 +160,7 @@
 	list_add_tail(&waiter.list, &sem->wait_list);
 
 	/* we don't need to touch the semaphore struct anymore */
-	spin_unlock(&sem->wait_lock);
+	spin_unlock_irq(&sem->wait_lock);
 
 	/* wait to be given the lock */
 	for (;;) {
@@ -181,10 +181,12 @@
  */
 int fastcall __down_read_trylock(struct rw_semaphore *sem)
 {
+	unsigned long flags;
 	int ret = 0;
+
 	rwsemtrace(sem, "Entering __down_read_trylock");
 
-	spin_lock(&sem->wait_lock);
+	spin_lock_irqsave(&sem->wait_lock, flags);
 
 	if (sem->activity >= 0 && list_empty(&sem->wait_list)) {
 		/* granted */
@@ -192,7 +194,7 @@
 		ret = 1;
 	}
 
-	spin_unlock(&sem->wait_lock);
+	spin_unlock_irqrestore(&sem->wait_lock, flags);
 
 	rwsemtrace(sem, "Leaving __down_read_trylock");
 	return ret;
@@ -209,12 +211,12 @@
 
 	rwsemtrace(sem, "Entering __down_write");
 
-	spin_lock(&sem->wait_lock);
+	spin_lock_irq(&sem->wait_lock);
 
 	if (sem->activity == 0 && list_empty(&sem->wait_list)) {
 		/* granted */
 		sem->activity = -1;
-		spin_unlock(&sem->wait_lock);
+		spin_unlock_irq(&sem->wait_lock);
 		goto out;
 	}
 
@@ -229,7 +231,7 @@
 	list_add_tail(&waiter.list, &sem->wait_list);
 
 	/* we don't need to touch the semaphore struct anymore */
-	spin_unlock(&sem->wait_lock);
+	spin_unlock_irq(&sem->wait_lock);
 
 	/* wait to be given the lock */
 	for (;;) {
@@ -250,10 +252,12 @@
  */
 int fastcall __down_write_trylock(struct rw_semaphore *sem)
 {
+	unsigned long flags;
 	int ret = 0;
+
 	rwsemtrace(sem, "Entering __down_write_trylock");
 
-	spin_lock(&sem->wait_lock);
+	spin_lock_irqsave(&sem->wait_lock, flags);
 
 	if (sem->activity == 0 && list_empty(&sem->wait_list)) {
 		/* granted */
@@ -261,7 +265,7 @@
 		ret = 1;
 	}
 
-	spin_unlock(&sem->wait_lock);
+	spin_unlock_irqrestore(&sem->wait_lock, flags);
 
 	rwsemtrace(sem, "Leaving __down_write_trylock");
 	return ret;
@@ -272,14 +276,16 @@
  */
 void fastcall __up_read(struct rw_semaphore *sem)
 {
+	unsigned long flags;
+
 	rwsemtrace(sem, "Entering __up_read");
 
-	spin_lock(&sem->wait_lock);
+	spin_lock_irqsave(&sem->wait_lock, flags);
 
 	if (--sem->activity == 0 && !list_empty(&sem->wait_list))
 		sem = __rwsem_wake_one_writer(sem);
 
-	spin_unlock(&sem->wait_lock);
+	spin_unlock_irqrestore(&sem->wait_lock, flags);
 
 	rwsemtrace(sem, "Leaving __up_read");
 }
@@ -289,15 +295,17 @@
  */
 void fastcall __up_write(struct rw_semaphore *sem)
 {
+	unsigned long flags;
+
 	rwsemtrace(sem, "Entering __up_write");
 
-	spin_lock(&sem->wait_lock);
+	spin_lock_irqsave(&sem->wait_lock, flags);
 
 	sem->activity = 0;
 	if (!list_empty(&sem->wait_list))
 		sem = __rwsem_do_wake(sem, 1);
 
-	spin_unlock(&sem->wait_lock);
+	spin_unlock_irqrestore(&sem->wait_lock, flags);
 
 	rwsemtrace(sem, "Leaving __up_write");
 }
@@ -308,15 +316,17 @@
  */
 void fastcall __downgrade_write(struct rw_semaphore *sem)
 {
+	unsigned long flags;
+
 	rwsemtrace(sem, "Entering __downgrade_write");
 
-	spin_lock(&sem->wait_lock);
+	spin_lock_irqsave(&sem->wait_lock, flags);
 
 	sem->activity = 1;
 	if (!list_empty(&sem->wait_list))
 		sem = __rwsem_do_wake(sem, 0);
 
-	spin_unlock(&sem->wait_lock);
+	spin_unlock_irqrestore(&sem->wait_lock, flags);
 
 	rwsemtrace(sem, "Leaving __downgrade_write");
 }
diff -Nru a/lib/rwsem.c b/lib/rwsem.c
--- a/lib/rwsem.c	2005-03-11 12:51:52 -08:00
+++ b/lib/rwsem.c	2005-03-11 12:51:52 -08:00
@@ -150,7 +150,7 @@
 	set_task_state(tsk, TASK_UNINTERRUPTIBLE);
 
 	/* set up my own style of waitqueue */
-	spin_lock(&sem->wait_lock);
+	spin_lock_irq(&sem->wait_lock);
 	waiter->task = tsk;
 	get_task_struct(tsk);
 
@@ -163,7 +163,7 @@
 	if (!(count & RWSEM_ACTIVE_MASK))
 		sem = __rwsem_do_wake(sem, 0);
 
-	spin_unlock(&sem->wait_lock);
+	spin_unlock_irq(&sem->wait_lock);
 
 	/* wait to be given the lock */
 	for (;;) {
@@ -219,15 +219,17 @@
  */
 struct rw_semaphore fastcall *rwsem_wake(struct rw_semaphore *sem)
 {
+	unsigned long flags;
+
 	rwsemtrace(sem, "Entering rwsem_wake");
 
-	spin_lock(&sem->wait_lock);
+	spin_lock_irqsave(&sem->wait_lock, flags);
 
 	/* do nothing if list empty */
 	if (!list_empty(&sem->wait_list))
 		sem = __rwsem_do_wake(sem, 0);
 
-	spin_unlock(&sem->wait_lock);
+	spin_unlock_irqrestore(&sem->wait_lock, flags);
 
 	rwsemtrace(sem, "Leaving rwsem_wake");
 
@@ -241,15 +243,17 @@
  */
 struct rw_semaphore fastcall *rwsem_downgrade_wake(struct rw_semaphore *sem)
 {
+	unsigned long flags;
+
 	rwsemtrace(sem, "Entering rwsem_downgrade_wake");
 
-	spin_lock(&sem->wait_lock);
+	spin_lock_irqsave(&sem->wait_lock, flags);
 
 	/* do nothing if list empty */
 	if (!list_empty(&sem->wait_list))
 		sem = __rwsem_do_wake(sem, 1);
 
-	spin_unlock(&sem->wait_lock);
+	spin_unlock_irqrestore(&sem->wait_lock, flags);
 
 	rwsemtrace(sem, "Leaving rwsem_downgrade_wake");
 	return sem;
diff -Nru a/lib/sha1.c b/lib/sha1.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/lib/sha1.c	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,96 @@
+/*
+ * SHA transform algorithm, originally taken from code written by
+ * Peter Gutmann, and placed in the public domain.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/cryptohash.h>
+
+/* The SHA f()-functions.  */
+
+#define f1(x,y,z)   (z ^ (x & (y ^ z)))		/* x ? y : z */
+#define f2(x,y,z)   (x ^ y ^ z)			/* XOR */
+#define f3(x,y,z)   ((x & y) + (z & (x ^ y)))	/* majority */
+
+/* The SHA Mysterious Constants */
+
+#define K1  0x5A827999L			/* Rounds  0-19: sqrt(2) * 2^30 */
+#define K2  0x6ED9EBA1L			/* Rounds 20-39: sqrt(3) * 2^30 */
+#define K3  0x8F1BBCDCL			/* Rounds 40-59: sqrt(5) * 2^30 */
+#define K4  0xCA62C1D6L			/* Rounds 60-79: sqrt(10) * 2^30 */
+
+/*
+ * sha_transform: single block SHA1 transform
+ *
+ * @digest: 160 bit digest to update
+ * @data:   512 bits of data to hash
+ * @W:      80 words of workspace (see note)
+ *
+ * This function generates a SHA1 digest for a single 512-bit block.
+ * Be warned, it does not handle padding and message digest, do not
+ * confuse it with the full FIPS 180-1 digest algorithm for variable
+ * length messages.
+ *
+ * Note: If the hash is security sensitive, the caller should be sure
+ * to clear the workspace. This is left to the caller to avoid
+ * unnecessary clears between chained hashing operations.
+ */
+void sha_transform(__u32 *digest, const char *in, __u32 *W)
+{
+	__u32 a, b, c, d, e, t, i;
+
+	for (i = 0; i < 16; i++)
+		W[i] = be32_to_cpu(((const __u32 *)in)[i]);
+
+	for (i = 0; i < 64; i++)
+		W[i+16] = rol32(W[i+13] ^ W[i+8] ^ W[i+2] ^ W[i], 1);
+
+	a = digest[0];
+	b = digest[1];
+	c = digest[2];
+	d = digest[3];
+	e = digest[4];
+
+	for (i = 0; i < 20; i++) {
+		t = f1(b, c, d) + K1 + rol32(a, 5) + e + W[i];
+		e = d; d = c; c = rol32(b, 30); b = a; a = t;
+	}
+
+	for (; i < 40; i ++) {
+		t = f2(b, c, d) + K2 + rol32(a, 5) + e + W[i];
+		e = d; d = c; c = rol32(b, 30); b = a; a = t;
+	}
+
+	for (; i < 60; i ++) {
+		t = f3(b, c, d) + K3 + rol32(a, 5) + e + W[i];
+		e = d; d = c; c = rol32(b, 30); b = a; a = t;
+	}
+
+	for (; i < 80; i ++) {
+		t = f2(b, c, d) + K4 + rol32(a, 5) + e + W[i];
+		e = d; d = c; c = rol32(b, 30); b = a; a = t;
+	}
+
+	digest[0] += a;
+	digest[1] += b;
+	digest[2] += c;
+	digest[3] += d;
+	digest[4] += e;
+}
+EXPORT_SYMBOL(sha_transform);
+
+/*
+ * sha_init: initialize the vectors for a SHA1 digest
+ *
+ * @buf: vector to initialize
+ */
+void sha_init(__u32 *buf)
+{
+	buf[0] = 0x67452301;
+	buf[1] = 0xefcdab89;
+	buf[2] = 0x98badcfe;
+	buf[3] = 0x10325476;
+	buf[4] = 0xc3d2e1f0;
+}
+
diff -Nru a/lib/sort.c b/lib/sort.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/lib/sort.c	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,119 @@
+/*
+ * A fast, small, non-recursive O(nlog n) sort for the Linux kernel
+ *
+ * Jan 23 2005  Matt Mackall <mpm@selenic.com>
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+
+void u32_swap(void *a, void *b, int size)
+{
+	u32 t = *(u32 *)a;
+	*(u32 *)a = *(u32 *)b;
+	*(u32 *)b = t;
+}
+
+void generic_swap(void *a, void *b, int size)
+{
+	char t;
+
+	do {
+		t = *(char *)a;
+		*(char *)a++ = *(char *)b;
+		*(char *)b++ = t;
+	} while (--size > 0);
+}
+
+/*
+ * sort - sort an array of elements
+ * @base: pointer to data to sort
+ * @num: number of elements
+ * @size: size of each element
+ * @cmp: pointer to comparison function
+ * @swap: pointer to swap function or NULL
+ *
+ * This function does a heapsort on the given array. You may provide a
+ * swap function optimized to your element type.
+ *
+ * Sorting time is O(n log n) both on average and worst-case. While
+ * qsort is about 20% faster on average, it suffers from exploitable
+ * O(n*n) worst-case behavior and extra memory requirements that make
+ * it less suitable for kernel use.
+ */
+
+void sort(void *base, size_t num, size_t size,
+	  int (*cmp)(const void *, const void *),
+	  void (*swap)(void *, void *, int size))
+{
+	/* pre-scale counters for performance */
+	int i = (num/2) * size, n = num * size, c, r;
+
+	if (!swap)
+		swap = (size == 4 ? u32_swap : generic_swap);
+
+	/* heapify */
+	for ( ; i >= 0; i -= size) {
+		for (r = i; r * 2 < n; r  = c) {
+			c = r * 2;
+			if (c < n - size && cmp(base + c, base + c + size) < 0)
+				c += size;
+			if (cmp(base + r, base + c) >= 0)
+				break;
+			swap(base + r, base + c, size);
+		}
+	}
+
+	/* sort */
+	for (i = n - size; i >= 0; i -= size) {
+		swap(base, base + i, size);
+		for (r = 0; r * 2 < i; r = c) {
+			c = r * 2;
+			if (c < i - size && cmp(base + c, base + c + size) < 0)
+				c += size;
+			if (cmp(base + r, base + c) >= 0)
+				break;
+			swap(base + r, base + c, size);
+		}
+	}
+}
+
+EXPORT_SYMBOL(sort);
+
+#if 0
+/* a simple boot-time regression test */
+
+int cmpint(const void *a, const void *b)
+{
+	return *(int *)a - *(int *)b;
+}
+
+static int sort_test(void)
+{
+	int *a, i, r = 0;
+
+	a = kmalloc(1000 * sizeof(int), GFP_KERNEL);
+	BUG_ON(!a);
+
+	printk("testing sort()\n");
+
+	for (i = 0; i < 1000; i++) {
+		r = (r * 725861) % 6599;
+		a[i] = r;
+	}
+
+	sort(a, 1000, sizeof(int), cmpint, NULL);
+
+	for (i = 0; i < 999; i++)
+		if (a[i] > a[i+1]) {
+			printk("sort() failed!\n");
+			break;
+		}
+
+	kfree(a);
+
+	return 0;
+}
+
+module_init(sort_test);
+#endif
diff -Nru a/mm/filemap.c b/mm/filemap.c
--- a/mm/filemap.c	2005-03-11 12:51:52 -08:00
+++ b/mm/filemap.c	2005-03-11 12:51:52 -08:00
@@ -126,9 +126,9 @@
 	if (unlikely(!PageLocked(page)))
 		PAGE_BUG(page);
 
-	spin_lock_irq(&mapping->tree_lock);
+	write_lock_irq(&mapping->tree_lock);
 	__remove_from_page_cache(page);
-	spin_unlock_irq(&mapping->tree_lock);
+	write_unlock_irq(&mapping->tree_lock);
 }
 
 static int sync_page(void *word)
@@ -336,6 +336,22 @@
 	return retval;
 }
 
+int filemap_write_and_wait_range(struct address_space *mapping,
+				 loff_t lstart, loff_t lend)
+{
+	int retval = 0;
+
+	if (mapping->nrpages) {
+		retval = __filemap_fdatawrite_range(mapping, lstart, lend,
+						    WB_SYNC_ALL);
+		if (retval == 0)
+			retval = wait_on_page_writeback_range(mapping,
+						    lstart >> PAGE_CACHE_SHIFT,
+						    lend >> PAGE_CACHE_SHIFT);
+	}
+	return retval;
+}
+
 /*
  * This function is used to add newly allocated pagecache pages:
  * the page is new, so we can just run SetPageLocked() against it.
@@ -349,7 +365,7 @@
 	int error = radix_tree_preload(gfp_mask & ~__GFP_HIGHMEM);
 
 	if (error == 0) {
-		spin_lock_irq(&mapping->tree_lock);
+		write_lock_irq(&mapping->tree_lock);
 		error = radix_tree_insert(&mapping->page_tree, offset, page);
 		if (!error) {
 			page_cache_get(page);
@@ -359,7 +375,7 @@
 			mapping->nrpages++;
 			pagecache_acct(1);
 		}
-		spin_unlock_irq(&mapping->tree_lock);
+		write_unlock_irq(&mapping->tree_lock);
 		radix_tree_preload_end();
 	}
 	return error;
@@ -472,11 +488,11 @@
 {
 	struct page *page;
 
-	spin_lock_irq(&mapping->tree_lock);
+	read_lock_irq(&mapping->tree_lock);
 	page = radix_tree_lookup(&mapping->page_tree, offset);
 	if (page)
 		page_cache_get(page);
-	spin_unlock_irq(&mapping->tree_lock);
+	read_unlock_irq(&mapping->tree_lock);
 	return page;
 }
 
@@ -489,11 +505,11 @@
 {
 	struct page *page;
 
-	spin_lock_irq(&mapping->tree_lock);
+	read_lock_irq(&mapping->tree_lock);
 	page = radix_tree_lookup(&mapping->page_tree, offset);
 	if (page && TestSetPageLocked(page))
 		page = NULL;
-	spin_unlock_irq(&mapping->tree_lock);
+	read_unlock_irq(&mapping->tree_lock);
 	return page;
 }
 
@@ -515,15 +531,15 @@
 {
 	struct page *page;
 
-	spin_lock_irq(&mapping->tree_lock);
+	read_lock_irq(&mapping->tree_lock);
 repeat:
 	page = radix_tree_lookup(&mapping->page_tree, offset);
 	if (page) {
 		page_cache_get(page);
 		if (TestSetPageLocked(page)) {
-			spin_unlock_irq(&mapping->tree_lock);
+			read_unlock_irq(&mapping->tree_lock);
 			lock_page(page);
-			spin_lock_irq(&mapping->tree_lock);
+			read_lock_irq(&mapping->tree_lock);
 
 			/* Has the page been truncated while we slept? */
 			if (page->mapping != mapping || page->index != offset) {
@@ -533,7 +549,7 @@
 			}
 		}
 	}
-	spin_unlock_irq(&mapping->tree_lock);
+	read_unlock_irq(&mapping->tree_lock);
 	return page;
 }
 
@@ -607,12 +623,12 @@
 	unsigned int i;
 	unsigned int ret;
 
-	spin_lock_irq(&mapping->tree_lock);
+	read_lock_irq(&mapping->tree_lock);
 	ret = radix_tree_gang_lookup(&mapping->page_tree,
 				(void **)pages, start, nr_pages);
 	for (i = 0; i < ret; i++)
 		page_cache_get(pages[i]);
-	spin_unlock_irq(&mapping->tree_lock);
+	read_unlock_irq(&mapping->tree_lock);
 	return ret;
 }
 
@@ -626,14 +642,14 @@
 	unsigned int i;
 	unsigned int ret;
 
-	spin_lock_irq(&mapping->tree_lock);
+	read_lock_irq(&mapping->tree_lock);
 	ret = radix_tree_gang_lookup_tag(&mapping->page_tree,
 				(void **)pages, *index, nr_pages, tag);
 	for (i = 0; i < ret; i++)
 		page_cache_get(pages[i]);
 	if (ret)
 		*index = pages[ret - 1]->index + 1;
-	spin_unlock_irq(&mapping->tree_lock);
+	read_unlock_irq(&mapping->tree_lock);
 	return ret;
 }
 
@@ -691,7 +707,7 @@
 	unsigned long index;
 	unsigned long end_index;
 	unsigned long offset;
-	unsigned long req_size;
+	unsigned long last_index;
 	unsigned long next_index;
 	unsigned long prev_index;
 	loff_t isize;
@@ -703,7 +719,7 @@
 	index = *ppos >> PAGE_CACHE_SHIFT;
 	next_index = index;
 	prev_index = ra.prev_page;
-	req_size = (desc->count + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
+	last_index = (*ppos + desc->count + PAGE_CACHE_SIZE-1) >> PAGE_CACHE_SHIFT;
 	offset = *ppos & ~PAGE_CACHE_MASK;
 
 	isize = i_size_read(inode);
@@ -713,7 +729,7 @@
 	end_index = (isize - 1) >> PAGE_CACHE_SHIFT;
 	for (;;) {
 		struct page *page;
-		unsigned long ret_size, nr, ret;
+		unsigned long nr, ret;
 
 		/* nr is the maximum number of bytes to copy from this page */
 		nr = PAGE_CACHE_SIZE;
@@ -728,12 +744,9 @@
 		nr = nr - offset;
 
 		cond_resched();
-		if (index == next_index && req_size) {
-			ret_size = page_cache_readahead(mapping, &ra,
-					filp, index, req_size);
-			next_index += ret_size;
-			req_size -= ret_size;
-		}
+		if (index == next_index)
+			next_index = page_cache_readahead(mapping, &ra, filp,
+					index, last_index - index);
 
 find_page:
 		page = find_get_page(mapping, index);
@@ -2269,21 +2282,28 @@
 	struct file *file = iocb->ki_filp;
 	struct address_space *mapping = file->f_mapping;
 	ssize_t retval;
+	size_t write_len = 0;
 
 	/*
 	 * If it's a write, unmap all mmappings of the file up-front.  This
 	 * will cause any pte dirty bits to be propagated into the pageframes
 	 * for the subsequent filemap_write_and_wait().
 	 */
-	if (rw == WRITE && mapping_mapped(mapping))
-		unmap_mapping_range(mapping, 0, -1, 0);
+	if (rw == WRITE) {
+		write_len = iov_length(iov, nr_segs);
+	       	if (mapping_mapped(mapping))
+			unmap_mapping_range(mapping, offset, write_len, 0);
+	}
 
 	retval = filemap_write_and_wait(mapping);
 	if (retval == 0) {
 		retval = mapping->a_ops->direct_IO(rw, iocb, iov,
 						offset, nr_segs);
 		if (rw == WRITE && mapping->nrpages) {
-			int err = invalidate_inode_pages2(mapping);
+			pgoff_t end = (offset + write_len - 1)
+						>> PAGE_CACHE_SHIFT;
+			int err = invalidate_inode_pages2_range(mapping,
+					offset >> PAGE_CACHE_SHIFT, end);
 			if (err)
 				retval = err;
 		}
diff -Nru a/mm/fremap.c b/mm/fremap.c
--- a/mm/fremap.c	2005-03-11 12:51:41 -08:00
+++ b/mm/fremap.c	2005-03-11 12:51:41 -08:00
@@ -30,7 +30,7 @@
 	if (pte_present(pte)) {
 		unsigned long pfn = pte_pfn(pte);
 
-		flush_cache_page(vma, addr);
+		flush_cache_page(vma, addr, pfn);
 		pte = ptep_clear_flush(vma, addr, ptep);
 		if (pfn_valid(pfn)) {
 			struct page *page = pfn_to_page(pfn);
@@ -45,7 +45,7 @@
 	} else {
 		if (!pte_file(pte))
 			free_swap_and_cache(pte_to_swp_entry(pte));
-		pte_clear(ptep);
+		pte_clear(mm, addr, ptep);
 	}
 }
 
@@ -94,7 +94,7 @@
 
 	mm->rss++;
 	flush_icache_page(vma, page);
-	set_pte(pte, mk_pte(page, prot));
+	set_pte_at(mm, addr, pte, mk_pte(page, prot));
 	page_add_file_rmap(page);
 	pte_val = *pte;
 	pte_unmap(pte);
@@ -139,7 +139,7 @@
 
 	zap_pte(mm, vma, addr, pte);
 
-	set_pte(pte, pgoff_to_pte(pgoff));
+	set_pte_at(mm, addr, pte, pgoff_to_pte(pgoff));
 	pte_val = *pte;
 	pte_unmap(pte);
 	update_mmu_cache(vma, addr, pte_val);
diff -Nru a/mm/highmem.c b/mm/highmem.c
--- a/mm/highmem.c	2005-03-11 12:51:47 -08:00
+++ b/mm/highmem.c	2005-03-11 12:51:47 -08:00
@@ -90,7 +90,8 @@
 		 * So no dangers, even with speculative execution.
 		 */
 		page = pte_page(pkmap_page_table[i]);
-		pte_clear(&pkmap_page_table[i]);
+		pte_clear(&init_mm, (unsigned long)page_address(page),
+			  &pkmap_page_table[i]);
 
 		set_page_address(page, NULL);
 	}
@@ -138,7 +139,8 @@
 		}
 	}
 	vaddr = PKMAP_ADDR(last_pkmap_nr);
-	set_pte(&(pkmap_page_table[last_pkmap_nr]), mk_pte(page, kmap_prot));
+	set_pte_at(&init_mm, vaddr,
+		   &(pkmap_page_table[last_pkmap_nr]), mk_pte(page, kmap_prot));
 
 	pkmap_count[last_pkmap_nr] = 1;
 	set_page_address(page, (void *)vaddr);
diff -Nru a/mm/memory.c b/mm/memory.c
--- a/mm/memory.c	2005-03-11 12:51:43 -08:00
+++ b/mm/memory.c	2005-03-11 12:51:43 -08:00
@@ -46,7 +46,6 @@
 #include <linux/highmem.h>
 #include <linux/pagemap.h>
 #include <linux/rmap.h>
-#include <linux/acct.h>
 #include <linux/module.h>
 #include <linux/init.h>
 
@@ -278,7 +277,7 @@
 	/* pte contains position in swap, so copy. */
 	if (!pte_present(pte)) {
 		copy_swap_pte(dst_mm, src_mm, pte);
-		set_pte(dst_pte, pte);
+		set_pte_at(dst_mm, addr, dst_pte, pte);
 		return;
 	}
 	pfn = pte_pfn(pte);
@@ -292,7 +291,7 @@
 		page = pfn_to_page(pfn);
 
 	if (!page || PageReserved(page)) {
-		set_pte(dst_pte, pte);
+		set_pte_at(dst_mm, addr, dst_pte, pte);
 		return;
 	}
 
@@ -301,7 +300,7 @@
 	 * in the parent and the child
 	 */
 	if ((vm_flags & (VM_SHARED | VM_MAYWRITE)) == VM_MAYWRITE) {
-		ptep_set_wrprotect(src_pte);
+		ptep_set_wrprotect(src_mm, addr, src_pte);
 		pte = *src_pte;
 	}
 
@@ -316,7 +315,7 @@
 	dst_mm->rss++;
 	if (PageAnon(page))
 		dst_mm->anon_rss++;
-	set_pte(dst_pte, pte);
+	set_pte_at(dst_mm, addr, dst_pte, pte);
 	page_dup_rmap(page);
 }
 
@@ -328,21 +327,33 @@
 	pte_t *s, *d;
 	unsigned long vm_flags = vma->vm_flags;
 
+again:
 	d = dst_pte = pte_alloc_map(dst_mm, dst_pmd, addr);
 	if (!dst_pte)
 		return -ENOMEM;
 
 	spin_lock(&src_mm->page_table_lock);
 	s = src_pte = pte_offset_map_nested(src_pmd, addr);
-	for (; addr < end; addr += PAGE_SIZE, s++, d++) {
-		if (pte_none(*s))
-			continue;
-		copy_one_pte(dst_mm, src_mm, d, s, vm_flags, addr);
+	for (; addr < end; s++, d++) {
+		if (!pte_none(*s))
+			copy_one_pte(dst_mm, src_mm, d, s, vm_flags, addr);
+		addr += PAGE_SIZE;
+		/*
+		 * We are holding two locks at this point - either of them
+		 * could generate latencies in another task on another CPU.
+		 */
+		if (need_resched() ||
+		    need_lockbreak(&src_mm->page_table_lock) ||
+		    need_lockbreak(&dst_mm->page_table_lock))
+			break;
 	}
 	pte_unmap_nested(src_pte);
 	pte_unmap(dst_pte);
 	spin_unlock(&src_mm->page_table_lock);
+
 	cond_resched_lock(&dst_mm->page_table_lock);
+	if (addr < end)
+		goto again;
 	return 0;
 }
 
@@ -502,14 +513,15 @@
 				     page->index > details->last_index))
 					continue;
 			}
-			pte = ptep_get_and_clear(ptep);
+			pte = ptep_get_and_clear(tlb->mm, address+offset, ptep);
 			tlb_remove_tlb_entry(tlb, ptep, address+offset);
 			if (unlikely(!page))
 				continue;
 			if (unlikely(details) && details->nonlinear_vma
 			    && linear_page_index(details->nonlinear_vma,
 					address+offset) != page->index)
-				set_pte(ptep, pgoff_to_pte(page->index));
+				set_pte_at(tlb->mm, address+offset,
+					   ptep, pgoff_to_pte(page->index));
 			if (pte_dirty(pte))
 				set_page_dirty(page);
 			if (PageAnon(page))
@@ -529,7 +541,7 @@
 			continue;
 		if (!pte_file(pte))
 			free_swap_and_cache(pte_to_swp_entry(pte));
-		pte_clear(ptep);
+		pte_clear(tlb->mm, address+offset, ptep);
 	}
 	pte_unmap(ptep-1);
 }
@@ -735,7 +747,6 @@
 	tlb = tlb_gather_mmu(mm, 0);
 	unmap_vmas(&tlb, mm, vma, address, end, &nr_accounted, details);
 	tlb_finish_mmu(tlb, address, end);
-	acct_update_integrals();
 	spin_unlock(&mm->page_table_lock);
 }
 
@@ -987,19 +998,21 @@
 
 EXPORT_SYMBOL(get_user_pages);
 
-static void zeromap_pte_range(pte_t * pte, unsigned long address,
-                                     unsigned long size, pgprot_t prot)
+static void zeromap_pte_range(struct mm_struct *mm, pte_t * pte,
+			      unsigned long address,
+			      unsigned long size, pgprot_t prot)
 {
-	unsigned long end;
+	unsigned long base, end;
 
+	base = address & PMD_MASK;
 	address &= ~PMD_MASK;
 	end = address + size;
 	if (end > PMD_SIZE)
 		end = PMD_SIZE;
 	do {
-		pte_t zero_pte = pte_wrprotect(mk_pte(ZERO_PAGE(address), prot));
+		pte_t zero_pte = pte_wrprotect(mk_pte(ZERO_PAGE(base+address), prot));
 		BUG_ON(!pte_none(*pte));
-		set_pte(pte, zero_pte);
+		set_pte_at(mm, base+address, pte, zero_pte);
 		address += PAGE_SIZE;
 		pte++;
 	} while (address && (address < end));
@@ -1019,7 +1032,7 @@
 		pte_t * pte = pte_alloc_map(mm, pmd, base + address);
 		if (!pte)
 			return -ENOMEM;
-		zeromap_pte_range(pte, base + address, end - address, prot);
+		zeromap_pte_range(mm, pte, base + address, end - address, prot);
 		pte_unmap(pte);
 		address = (address + PMD_SIZE) & PMD_MASK;
 		pmd++;
@@ -1100,11 +1113,13 @@
  * in null mappings (currently treated as "copy-on-access")
  */
 static inline void
-remap_pte_range(pte_t * pte, unsigned long address, unsigned long size,
+remap_pte_range(struct mm_struct *mm, pte_t * pte,
+		unsigned long address, unsigned long size,
 		unsigned long pfn, pgprot_t prot)
 {
-	unsigned long end;
+	unsigned long base, end;
 
+	base = address & PMD_MASK;
 	address &= ~PMD_MASK;
 	end = address + size;
 	if (end > PMD_SIZE)
@@ -1112,7 +1127,7 @@
 	do {
 		BUG_ON(!pte_none(*pte));
 		if (!pfn_valid(pfn) || PageReserved(pfn_to_page(pfn)))
- 			set_pte(pte, pfn_pte(pfn, prot));
+			set_pte_at(mm, base+address, pte, pfn_pte(pfn, prot));
 		address += PAGE_SIZE;
 		pfn++;
 		pte++;
@@ -1135,7 +1150,7 @@
 		pte_t * pte = pte_alloc_map(mm, pmd, base + address);
 		if (!pte)
 			return -ENOMEM;
-		remap_pte_range(pte, base + address, end - address,
+		remap_pte_range(mm, pte, base + address, end - address,
 				(address >> PAGE_SHIFT) + pfn, prot);
 		pte_unmap(pte);
 		address = (address + PMD_SIZE) & PMD_MASK;
@@ -1247,7 +1262,6 @@
 {
 	pte_t entry;
 
-	flush_cache_page(vma, address);
 	entry = maybe_mkwrite(pte_mkdirty(mk_pte(new_page, vma->vm_page_prot)),
 			      vma);
 	ptep_establish(vma, address, page_table, entry);
@@ -1299,7 +1313,7 @@
 		int reuse = can_share_swap_page(old_page);
 		unlock_page(old_page);
 		if (reuse) {
-			flush_cache_page(vma, address);
+			flush_cache_page(vma, address, pfn);
 			entry = maybe_mkwrite(pte_mkyoung(pte_mkdirty(pte)),
 					      vma);
 			ptep_set_access_flags(vma, address, page_table, entry, 1);
@@ -1338,12 +1352,11 @@
 	if (likely(pte_same(*page_table, pte))) {
 		if (PageAnon(old_page))
 			mm->anon_rss--;
-		if (PageReserved(old_page)) {
+		if (PageReserved(old_page))
 			++mm->rss;
-			acct_update_integrals();
-			update_mem_hiwater();
-		} else
+		else
 			page_remove_rmap(old_page);
+		flush_cache_page(vma, address, pfn);
 		break_cow(vma, new_page, address, page_table);
 		lru_cache_add_active(new_page);
 		page_add_anon_rmap(new_page, vma, address);
@@ -1747,9 +1760,6 @@
 		remove_exclusive_swap_page(page);
 
 	mm->rss++;
-	acct_update_integrals();
-	update_mem_hiwater();
-
 	pte = mk_pte(page, vma->vm_page_prot);
 	if (write_access && can_share_swap_page(page)) {
 		pte = maybe_mkwrite(pte_mkdirty(pte), vma);
@@ -1758,7 +1768,7 @@
 	unlock_page(page);
 
 	flush_icache_page(vma, page);
-	set_pte(page_table, pte);
+	set_pte_at(mm, address, page_table, pte);
 	page_add_anon_rmap(page, vma, address);
 
 	if (write_access) {
@@ -1814,8 +1824,6 @@
 			goto out;
 		}
 		mm->rss++;
-		acct_update_integrals();
-		update_mem_hiwater();
 		entry = maybe_mkwrite(pte_mkdirty(mk_pte(page,
 							 vma->vm_page_prot)),
 				      vma);
@@ -1824,7 +1832,7 @@
 		page_add_anon_rmap(page, vma, addr);
 	}
 
-	set_pte(page_table, entry);
+	set_pte_at(mm, addr, page_table, entry);
 	pte_unmap(page_table);
 
 	/* No need to invalidate - it was non-present before */
@@ -1932,14 +1940,12 @@
 	if (pte_none(*page_table)) {
 		if (!PageReserved(new_page))
 			++mm->rss;
-		acct_update_integrals();
-		update_mem_hiwater();
 
 		flush_icache_page(vma, new_page);
 		entry = mk_pte(new_page, vma->vm_page_prot);
 		if (write_access)
 			entry = maybe_mkwrite(pte_mkdirty(entry), vma);
-		set_pte(page_table, entry);
+		set_pte_at(mm, address, page_table, entry);
 		if (anon) {
 			lru_cache_add_active(new_page);
 			page_add_anon_rmap(new_page, vma, address);
@@ -1983,7 +1989,7 @@
 	 */
 	if (!vma->vm_ops || !vma->vm_ops->populate || 
 			(write_access && !(vma->vm_flags & VM_SHARED))) {
-		pte_clear(pte);
+		pte_clear(mm, address, pte);
 		return do_no_page(mm, vma, address, write_access, pte, pmd);
 	}
 
@@ -2253,10 +2259,8 @@
  * update_mem_hiwater
  *	- update per process rss and vm high water data
  */
-void update_mem_hiwater(void)
+void update_mem_hiwater(struct task_struct *tsk)
 {
-	struct task_struct *tsk = current;
-
 	if (tsk->mm) {
 		if (tsk->mm->hiwater_rss < tsk->mm->rss)
 			tsk->mm->hiwater_rss = tsk->mm->rss;
diff -Nru a/mm/mempolicy.c b/mm/mempolicy.c
--- a/mm/mempolicy.c	2005-03-11 12:51:52 -08:00
+++ b/mm/mempolicy.c	2005-03-11 12:51:52 -08:00
@@ -67,6 +67,7 @@
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/nodemask.h>
+#include <linux/cpuset.h>
 #include <linux/gfp.h>
 #include <linux/slab.h>
 #include <linux/string.h>
@@ -167,6 +168,10 @@
 	if (copy_from_user(nodes, nmask, nlongs*sizeof(unsigned long)))
 		return -EFAULT;
 	nodes[nlongs-1] &= endmask;
+	/* Update current mems_allowed */
+	cpuset_update_current_mems_allowed();
+	/* Ignore nodes not set in current->mems_allowed */
+	cpuset_restrict_to_mems_allowed(nodes);
 	return mpol_check_policy(mode, nodes);
 }
 
@@ -655,8 +660,10 @@
 		break;
 	case MPOL_BIND:
 		/* Lower zones don't get a policy applied */
+		/* Careful: current->mems_allowed might have moved */
 		if (gfp >= policy_zone)
-			return policy->v.zonelist;
+			if (cpuset_zonelist_valid_mems_allowed(policy->v.zonelist))
+				return policy->v.zonelist;
 		/*FALL THROUGH*/
 	case MPOL_INTERLEAVE: /* should not happen */
 	case MPOL_DEFAULT:
@@ -747,6 +754,8 @@
 {
 	struct mempolicy *pol = get_vma_policy(vma, addr);
 
+	cpuset_update_current_mems_allowed();
+
 	if (unlikely(pol->policy == MPOL_INTERLEAVE)) {
 		unsigned nid;
 		if (vma) {
@@ -784,6 +793,8 @@
 {
 	struct mempolicy *pol = current->mempolicy;
 
+	if (!in_interrupt())
+		cpuset_update_current_mems_allowed();
 	if (!pol || in_interrupt())
 		pol = &default_policy;
 	if (pol->policy == MPOL_INTERLEAVE)
diff -Nru a/mm/mempool.c b/mm/mempool.c
--- a/mm/mempool.c	2005-03-11 12:51:47 -08:00
+++ b/mm/mempool.c	2005-03-11 12:51:47 -08:00
@@ -114,8 +114,8 @@
 	BUG_ON(new_min_nr <= 0);
 
 	spin_lock_irqsave(&pool->lock, flags);
-	if (new_min_nr < pool->min_nr) {
-		while (pool->curr_nr > new_min_nr) {
+	if (new_min_nr <= pool->min_nr) {
+		while (new_min_nr < pool->curr_nr) {
 			element = remove_element(pool);
 			spin_unlock_irqrestore(&pool->lock, flags);
 			pool->free(element, pool->pool_data);
@@ -132,6 +132,12 @@
 		return -ENOMEM;
 
 	spin_lock_irqsave(&pool->lock, flags);
+	if (unlikely(new_min_nr <= pool->min_nr)) {
+		/* Raced, other resize will do our work */
+		spin_unlock_irqrestore(&pool->lock, flags);
+		kfree(new_elements);
+		goto out;
+	}
 	memcpy(new_elements, pool->elements,
 			pool->curr_nr * sizeof(*new_elements));
 	kfree(pool->elements);
@@ -149,7 +155,7 @@
 		} else {
 			spin_unlock_irqrestore(&pool->lock, flags);
 			pool->free(element, pool->pool_data);	/* Raced */
-			spin_lock_irqsave(&pool->lock, flags);
+			goto out;
 		}
 	}
 out_unlock:
diff -Nru a/mm/mincore.c b/mm/mincore.c
--- a/mm/mincore.c	2005-03-11 12:51:51 -08:00
+++ b/mm/mincore.c	2005-03-11 12:51:51 -08:00
@@ -97,8 +97,7 @@
  * return values:
  *  zero    - success
  *  -EFAULT - vec points to an illegal address
- *  -EINVAL - addr is not a multiple of PAGE_CACHE_SIZE,
- *		or len has a nonpositive value
+ *  -EINVAL - addr is not a multiple of PAGE_CACHE_SIZE
  *  -ENOMEM - Addresses in the range [addr, addr + len] are
  *		invalid for the address space of this process, or
  *		specify one or more pages which are not currently
@@ -126,10 +125,13 @@
 	if (start >= limit)
 		goto enomem;
 
+	if (!len)
+		return 0;
+
 	max = limit - start;
 	len = PAGE_CACHE_ALIGN(len);
-	if (len > max)
-		goto einval;
+	if (len > max || !len)
+		goto enomem;
 
 	end = start + len;
 
diff -Nru a/mm/mmap.c b/mm/mmap.c
--- a/mm/mmap.c	2005-03-11 12:51:47 -08:00
+++ b/mm/mmap.c	2005-03-11 12:51:47 -08:00
@@ -21,7 +21,6 @@
 #include <linux/hugetlb.h>
 #include <linux/profile.h>
 #include <linux/module.h>
-#include <linux/acct.h>
 #include <linux/mount.h>
 #include <linux/mempolicy.h>
 #include <linux/rmap.h>
@@ -873,7 +872,7 @@
 	int error;
 	struct rb_node ** rb_link, * rb_parent;
 	int accountable = 1;
-	unsigned long charged = 0;
+	unsigned long charged = 0, reqprot = prot;
 
 	if (file) {
 		if (is_file_hugepages(file))
@@ -991,7 +990,7 @@
 		}
 	}
 
-	error = security_file_mmap(file, prot, flags);
+	error = security_file_mmap(file, reqprot, prot, flags);
 	if (error)
 		return error;
 		
@@ -1121,8 +1120,6 @@
 					pgoff, flags & MAP_NONBLOCK);
 		down_write(&mm->mmap_sem);
 	}
-	acct_update_integrals();
-	update_mem_hiwater();
 	return addr;
 
 unmap_and_free_vma:
@@ -1221,19 +1218,14 @@
 			  const unsigned long len, const unsigned long pgoff,
 			  const unsigned long flags)
 {
-	struct vm_area_struct *vma, *prev_vma;
+	struct vm_area_struct *vma;
 	struct mm_struct *mm = current->mm;
-	unsigned long base = mm->mmap_base, addr = addr0;
-	int first_time = 1;
+	unsigned long addr = addr0;
 
 	/* requested length too big for entire address space */
 	if (len > TASK_SIZE)
 		return -ENOMEM;
 
-	/* dont allow allocations above current base */
-	if (mm->free_area_cache > base)
-		mm->free_area_cache = base;
-
 	/* requesting a specific address */
 	if (addr) {
 		addr = PAGE_ALIGN(addr);
@@ -1243,48 +1235,34 @@
 			return addr;
 	}
 
-try_again:
+	/* either no address requested or can't fit in requested address hole */
+	addr = mm->free_area_cache;
+
 	/* make sure it can fit in the remaining address space */
-	if (mm->free_area_cache < len)
-		goto fail;
+	if (addr >= len) {
+		vma = find_vma(mm, addr-len);
+		if (!vma || addr <= vma->vm_start)
+			/* remember the address as a hint for next time */
+			return (mm->free_area_cache = addr-len);
+	}
+
+	addr = mm->mmap_base-len;
 
-	/* either no address requested or cant fit in requested address hole */
-	addr = (mm->free_area_cache - len) & PAGE_MASK;
 	do {
 		/*
 		 * Lookup failure means no vma is above this address,
-		 * i.e. return with success:
-		 */
- 	 	if (!(vma = find_vma_prev(mm, addr, &prev_vma)))
-			return addr;
-
-		/*
-		 * new region fits between prev_vma->vm_end and
-		 * vma->vm_start, use it:
+		 * else if new region fits below vma->vm_start,
+		 * return with success:
 		 */
-		if (addr+len <= vma->vm_start &&
-				(!prev_vma || (addr >= prev_vma->vm_end)))
+		vma = find_vma(mm, addr);
+		if (!vma || addr+len <= vma->vm_start)
 			/* remember the address as a hint for next time */
 			return (mm->free_area_cache = addr);
-		else
-			/* pull free_area_cache down to the first hole */
-			if (mm->free_area_cache == vma->vm_end)
-				mm->free_area_cache = vma->vm_start;
 
 		/* try just below the current vma->vm_start */
 		addr = vma->vm_start-len;
 	} while (len <= vma->vm_start);
 
-fail:
-	/*
-	 * if hint left us with no space for the requested
-	 * mapping then try again:
-	 */
-	if (first_time) {
-		mm->free_area_cache = base;
-		first_time = 0;
-		goto try_again;
-	}
 	/*
 	 * A failed mmap() very likely causes application failure,
 	 * so fall back to the bottom-up function here. This scenario
@@ -1296,7 +1274,7 @@
 	/*
 	 * Restore the topdown base:
 	 */
-	mm->free_area_cache = base;
+	mm->free_area_cache = mm->mmap_base;
 
 	return addr;
 }
@@ -1309,6 +1287,10 @@
 	 */
 	if (area->vm_end > area->vm_mm->free_area_cache)
 		area->vm_mm->free_area_cache = area->vm_end;
+
+	/* dont allow allocations above current base */
+	if (area->vm_mm->free_area_cache > area->vm_mm->mmap_base)
+		area->vm_mm->free_area_cache = area->vm_mm->mmap_base;
 }
 
 unsigned long
@@ -1463,8 +1445,6 @@
 	if (vma->vm_flags & VM_LOCKED)
 		mm->locked_vm += grow;
 	__vm_stat_account(mm, vma->vm_flags, vma->vm_file, grow);
-	acct_update_integrals();
-	update_mem_hiwater();
 	return 0;
 }
 
@@ -1968,8 +1948,6 @@
 		mm->locked_vm += len >> PAGE_SHIFT;
 		make_pages_present(addr, addr + len);
 	}
-	acct_update_integrals();
-	update_mem_hiwater();
 	return addr;
 }
 
diff -Nru a/mm/mprotect.c b/mm/mprotect.c
--- a/mm/mprotect.c	2005-03-11 12:51:52 -08:00
+++ b/mm/mprotect.c	2005-03-11 12:51:52 -08:00
@@ -26,11 +26,11 @@
 #include <asm/tlbflush.h>
 
 static inline void
-change_pte_range(pmd_t *pmd, unsigned long address,
+change_pte_range(struct mm_struct *mm, pmd_t *pmd, unsigned long address,
 		unsigned long size, pgprot_t newprot)
 {
 	pte_t * pte;
-	unsigned long end;
+	unsigned long base, end;
 
 	if (pmd_none(*pmd))
 		return;
@@ -40,6 +40,7 @@
 		return;
 	}
 	pte = pte_offset_map(pmd, address);
+	base = address & PMD_MASK;
 	address &= ~PMD_MASK;
 	end = address + size;
 	if (end > PMD_SIZE)
@@ -52,8 +53,8 @@
 			 * bits by wiping the pte and then setting the new pte
 			 * into place.
 			 */
-			entry = ptep_get_and_clear(pte);
-			set_pte(pte, pte_modify(entry, newprot));
+			entry = ptep_get_and_clear(mm, base + address, pte);
+			set_pte_at(mm, base + address, pte, pte_modify(entry, newprot));
 		}
 		address += PAGE_SIZE;
 		pte++;
@@ -62,11 +63,11 @@
 }
 
 static inline void
-change_pmd_range(pud_t *pud, unsigned long address,
-		unsigned long size, pgprot_t newprot)
+change_pmd_range(struct mm_struct *mm, pud_t *pud, unsigned long address,
+		 unsigned long size, pgprot_t newprot)
 {
 	pmd_t * pmd;
-	unsigned long end;
+	unsigned long base, end;
 
 	if (pud_none(*pud))
 		return;
@@ -76,23 +77,24 @@
 		return;
 	}
 	pmd = pmd_offset(pud, address);
+	base = address & PUD_MASK;
 	address &= ~PUD_MASK;
 	end = address + size;
 	if (end > PUD_SIZE)
 		end = PUD_SIZE;
 	do {
-		change_pte_range(pmd, address, end - address, newprot);
+		change_pte_range(mm, pmd, base + address, end - address, newprot);
 		address = (address + PMD_SIZE) & PMD_MASK;
 		pmd++;
 	} while (address && (address < end));
 }
 
 static inline void
-change_pud_range(pgd_t *pgd, unsigned long address,
-		unsigned long size, pgprot_t newprot)
+change_pud_range(struct mm_struct *mm, pgd_t *pgd, unsigned long address,
+		 unsigned long size, pgprot_t newprot)
 {
 	pud_t * pud;
-	unsigned long end;
+	unsigned long base, end;
 
 	if (pgd_none(*pgd))
 		return;
@@ -102,12 +104,13 @@
 		return;
 	}
 	pud = pud_offset(pgd, address);
+	base = address & PGDIR_MASK;
 	address &= ~PGDIR_MASK;
 	end = address + size;
 	if (end > PGDIR_SIZE)
 		end = PGDIR_SIZE;
 	do {
-		change_pmd_range(pud, address, end - address, newprot);
+		change_pmd_range(mm, pud, base + address, end - address, newprot);
 		address = (address + PUD_SIZE) & PUD_MASK;
 		pud++;
 	} while (address && (address < end));
@@ -130,7 +133,7 @@
 		next = (start + PGDIR_SIZE) & PGDIR_MASK;
 		if (next <= start || next > end)
 			next = end;
-		change_pud_range(pgd, start, next - start, newprot);
+		change_pud_range(mm, pgd, start, next - start, newprot);
 		start = next;
 		pgd++;
 	}
@@ -222,7 +225,7 @@
 asmlinkage long
 sys_mprotect(unsigned long start, size_t len, unsigned long prot)
 {
-	unsigned long vm_flags, nstart, end, tmp;
+	unsigned long vm_flags, nstart, end, tmp, reqprot;
 	struct vm_area_struct *vma, *prev;
 	int error = -EINVAL;
 	const int grows = prot & (PROT_GROWSDOWN|PROT_GROWSUP);
@@ -240,6 +243,8 @@
 		return -EINVAL;
 	if (end == start)
 		return 0;
+
+	reqprot = prot;
 	/*
 	 * Does the application expect PROT_READ to imply PROT_EXEC:
 	 */
@@ -293,7 +298,7 @@
 			goto out;
 		}
 
-		error = security_file_mprotect(vma, prot);
+		error = security_file_mprotect(vma, reqprot, prot);
 		if (error)
 			goto out;
 
diff -Nru a/mm/mremap.c b/mm/mremap.c
--- a/mm/mremap.c	2005-03-11 12:51:46 -08:00
+++ b/mm/mremap.c	2005-03-11 12:51:46 -08:00
@@ -16,7 +16,6 @@
 #include <linux/fs.h>
 #include <linux/highmem.h>
 #include <linux/security.h>
-#include <linux/acct.h>
 #include <linux/syscalls.h>
 
 #include <asm/uaccess.h>
@@ -150,7 +149,7 @@
 			if (dst) {
 				pte_t pte;
 				pte = ptep_clear_flush(vma, old_addr, src);
-				set_pte(dst, pte);
+				set_pte_at(mm, new_addr, dst, pte);
 			} else
 				error = -ENOMEM;
 			pte_unmap_nested(src);
@@ -255,9 +254,6 @@
 					   new_addr + new_len);
 	}
 
-	acct_update_integrals();
-	update_mem_hiwater();
-
 	return new_addr;
 }
 
@@ -394,8 +390,6 @@
 				make_pages_present(addr + old_len,
 						   addr + new_len);
 			}
-			acct_update_integrals();
-			update_mem_hiwater();
 			ret = addr;
 			goto out;
 		}
diff -Nru a/mm/nommu.c b/mm/nommu.c
--- a/mm/nommu.c	2005-03-11 12:51:51 -08:00
+++ b/mm/nommu.c	2005-03-11 12:51:51 -08:00
@@ -959,10 +959,8 @@
 {
 }
 
-void update_mem_hiwater(void)
+void update_mem_hiwater(struct task_struct *tsk)
 {
-	struct task_struct *tsk = current;
-
 	if (likely(tsk->mm)) {
 		if (tsk->mm->hiwater_rss < tsk->mm->rss)
 			tsk->mm->hiwater_rss = tsk->mm->rss;
diff -Nru a/mm/page-writeback.c b/mm/page-writeback.c
--- a/mm/page-writeback.c	2005-03-11 12:51:47 -08:00
+++ b/mm/page-writeback.c	2005-03-11 12:51:47 -08:00
@@ -289,6 +289,28 @@
 }
 EXPORT_SYMBOL(balance_dirty_pages_ratelimited);
 
+void throttle_vm_writeout(void)
+{
+	struct writeback_state wbs;
+	long background_thresh;
+	long dirty_thresh;
+
+        for ( ; ; ) {
+		get_dirty_limits(&wbs, &background_thresh, &dirty_thresh, NULL);
+
+                /*
+                 * Boost the allowable dirty threshold a bit for page
+                 * allocators so they don't get DoS'ed by heavy writers
+                 */
+                dirty_thresh += dirty_thresh / 10;      /* wheeee... */
+
+                if (wbs.nr_unstable + wbs.nr_writeback <= dirty_thresh)
+                        break;
+                blk_congestion_wait(WRITE, HZ/10);
+        }
+}
+
+
 /*
  * writeback at least _min_pages, and keep writing until the amount of dirty
  * memory is less than the background threshold, or until we're all clean.
@@ -601,7 +623,7 @@
 		struct address_space *mapping2;
 
 		if (mapping) {
-			spin_lock_irq(&mapping->tree_lock);
+			write_lock_irq(&mapping->tree_lock);
 			mapping2 = page_mapping(page);
 			if (mapping2) { /* Race with truncate? */
 				BUG_ON(mapping2 != mapping);
@@ -610,7 +632,7 @@
 				radix_tree_tag_set(&mapping->page_tree,
 					page_index(page), PAGECACHE_TAG_DIRTY);
 			}
-			spin_unlock_irq(&mapping->tree_lock);
+			write_unlock_irq(&mapping->tree_lock);
 			if (mapping->host) {
 				/* !PageAnon && !swapper_space */
 				__mark_inode_dirty(mapping->host,
@@ -685,17 +707,17 @@
 	unsigned long flags;
 
 	if (mapping) {
-		spin_lock_irqsave(&mapping->tree_lock, flags);
+		write_lock_irqsave(&mapping->tree_lock, flags);
 		if (TestClearPageDirty(page)) {
 			radix_tree_tag_clear(&mapping->page_tree,
 						page_index(page),
 						PAGECACHE_TAG_DIRTY);
-			spin_unlock_irqrestore(&mapping->tree_lock, flags);
+			write_unlock_irqrestore(&mapping->tree_lock, flags);
 			if (!mapping->backing_dev_info->memory_backed)
 				dec_page_state(nr_dirty);
 			return 1;
 		}
-		spin_unlock_irqrestore(&mapping->tree_lock, flags);
+		write_unlock_irqrestore(&mapping->tree_lock, flags);
 		return 0;
 	}
 	return TestClearPageDirty(page);
@@ -742,15 +764,15 @@
 	if (mapping) {
 		unsigned long flags;
 
-		spin_lock_irqsave(&mapping->tree_lock, flags);
+		write_lock_irqsave(&mapping->tree_lock, flags);
 		if (TestClearPageDirty(page)) {
 			radix_tree_tag_clear(&mapping->page_tree,
 						page_index(page),
 						PAGECACHE_TAG_DIRTY);
-			spin_unlock_irqrestore(&mapping->tree_lock, flags);
+			write_unlock_irqrestore(&mapping->tree_lock, flags);
 			return 1;
 		}
-		spin_unlock_irqrestore(&mapping->tree_lock, flags);
+		write_unlock_irqrestore(&mapping->tree_lock, flags);
 		return 0;
 	}
 	return TestClearPageDirty(page);
@@ -764,13 +786,13 @@
 	if (mapping) {
 		unsigned long flags;
 
-		spin_lock_irqsave(&mapping->tree_lock, flags);
+		write_lock_irqsave(&mapping->tree_lock, flags);
 		ret = TestClearPageWriteback(page);
 		if (ret)
 			radix_tree_tag_clear(&mapping->page_tree,
 						page_index(page),
 						PAGECACHE_TAG_WRITEBACK);
-		spin_unlock_irqrestore(&mapping->tree_lock, flags);
+		write_unlock_irqrestore(&mapping->tree_lock, flags);
 	} else {
 		ret = TestClearPageWriteback(page);
 	}
@@ -785,7 +807,7 @@
 	if (mapping) {
 		unsigned long flags;
 
-		spin_lock_irqsave(&mapping->tree_lock, flags);
+		write_lock_irqsave(&mapping->tree_lock, flags);
 		ret = TestSetPageWriteback(page);
 		if (!ret)
 			radix_tree_tag_set(&mapping->page_tree,
@@ -795,7 +817,7 @@
 			radix_tree_tag_clear(&mapping->page_tree,
 						page_index(page),
 						PAGECACHE_TAG_DIRTY);
-		spin_unlock_irqrestore(&mapping->tree_lock, flags);
+		write_unlock_irqrestore(&mapping->tree_lock, flags);
 	} else {
 		ret = TestSetPageWriteback(page);
 	}
@@ -813,9 +835,9 @@
 	unsigned long flags;
 	int ret;
 
-	spin_lock_irqsave(&mapping->tree_lock, flags);
+	read_lock_irqsave(&mapping->tree_lock, flags);
 	ret = radix_tree_tagged(&mapping->page_tree, tag);
-	spin_unlock_irqrestore(&mapping->tree_lock, flags);
+	read_unlock_irqrestore(&mapping->tree_lock, flags);
 	return ret;
 }
 EXPORT_SYMBOL(mapping_tagged);
diff -Nru a/mm/page_alloc.c b/mm/page_alloc.c
--- a/mm/page_alloc.c	2005-03-11 12:51:52 -08:00
+++ b/mm/page_alloc.c	2005-03-11 12:51:52 -08:00
@@ -31,19 +31,24 @@
 #include <linux/topology.h>
 #include <linux/sysctl.h>
 #include <linux/cpu.h>
+#include <linux/cpuset.h>
 #include <linux/nodemask.h>
 #include <linux/vmalloc.h>
 
 #include <asm/tlbflush.h>
 #include "internal.h"
 
-/* MCD - HACK: Find somewhere to initialize this EARLY, or make this initializer cleaner */
+/*
+ * MCD - HACK: Find somewhere to initialize this EARLY, or make this
+ * initializer cleaner
+ */
 nodemask_t node_online_map = { { [0] = 1UL } };
 nodemask_t node_possible_map = NODE_MASK_ALL;
 struct pglist_data *pgdat_list;
 unsigned long totalram_pages;
 unsigned long totalhigh_pages;
 long nr_swap_pages;
+
 /*
  * results with 256, 32 in the lowmem_reserve sysctl:
  *	1G machine -> (16M dma, 800M-16M normal, 1G-800M high)
@@ -191,6 +196,37 @@
 }
 
 /*
+ * Locate the struct page for both the matching buddy in our
+ * pair (buddy1) and the combined O(n+1) page they form (page).
+ *
+ * 1) Any buddy B1 will have an order O twin B2 which satisfies
+ * the following equation:
+ *     B2 = B1 ^ (1 << O)
+ * For example, if the starting buddy (buddy2) is #8 its order
+ * 1 buddy is #10:
+ *     B2 = 8 ^ (1 << 1) = 8 ^ 2 = 10
+ *
+ * 2) Any buddy B will have an order O+1 parent P which
+ * satisfies the following equation:
+ *     P = B & ~(1 << O)
+ *
+ * Assumption: *_mem_map is contigious at least up to MAX_ORDER
+ */
+static inline struct page *
+__page_find_buddy(struct page *page, unsigned long page_idx, unsigned int order)
+{
+	unsigned long buddy_idx = page_idx ^ (1 << order);
+
+	return page + (buddy_idx - page_idx);
+}
+
+static inline unsigned long
+__find_combined_index(unsigned long page_idx, unsigned int order)
+{
+	return (page_idx & ~(1 << order));
+}
+
+/*
  * This function checks whether a page is free && is the buddy
  * we can do coalesce a page and its buddy if
  * (a) the buddy is free &&
@@ -233,50 +269,49 @@
  * -- wli
  */
 
-static inline void __free_pages_bulk (struct page *page, struct page *base,
+static inline void __free_pages_bulk (struct page *page,
 		struct zone *zone, unsigned int order)
 {
 	unsigned long page_idx;
-	struct page *coalesced;
 	int order_size = 1 << order;
 
 	if (unlikely(order))
 		destroy_compound_page(page, order);
 
-	page_idx = page - base;
+	page_idx = page_to_pfn(page) & ((1 << MAX_ORDER) - 1);
 
 	BUG_ON(page_idx & (order_size - 1));
 	BUG_ON(bad_range(zone, page));
 
 	zone->free_pages += order_size;
 	while (order < MAX_ORDER-1) {
+		unsigned long combined_idx;
 		struct free_area *area;
 		struct page *buddy;
-		int buddy_idx;
 
-		buddy_idx = (page_idx ^ (1 << order));
-		buddy = base + buddy_idx;
+		combined_idx = __find_combined_index(page_idx, order);
+		buddy = __page_find_buddy(page, page_idx, order);
+
 		if (bad_range(zone, buddy))
 			break;
 		if (!page_is_buddy(buddy, order))
-			break;
-		/* Move the buddy up one level. */
+			break;		/* Move the buddy up one level. */
 		list_del(&buddy->lru);
 		area = zone->free_area + order;
 		area->nr_free--;
 		rmv_page_order(buddy);
-		page_idx &= buddy_idx;
+		page = page + (combined_idx - page_idx);
+		page_idx = combined_idx;
 		order++;
 	}
-	coalesced = base + page_idx;
-	set_page_order(coalesced, order);
-	list_add(&coalesced->lru, &zone->free_area[order].free_list);
+	set_page_order(page, order);
+	list_add(&page->lru, &zone->free_area[order].free_list);
 	zone->free_area[order].nr_free++;
 }
 
 static inline void free_pages_check(const char *function, struct page *page)
 {
-	if (	page_mapped(page) ||
+	if (	page_mapcount(page) ||
 		page->mapping != NULL ||
 		page_count(page) != 0 ||
 		(page->flags & (
@@ -309,10 +344,9 @@
 		struct list_head *list, unsigned int order)
 {
 	unsigned long flags;
-	struct page *base, *page = NULL;
+	struct page *page = NULL;
 	int ret = 0;
 
-	base = zone->zone_mem_map;
 	spin_lock_irqsave(&zone->lock, flags);
 	zone->all_unreclaimable = 0;
 	zone->pages_scanned = 0;
@@ -320,7 +354,7 @@
 		page = list_entry(list->prev, struct page, lru);
 		/* have to delete it as __free_pages_bulk list manipulates */
 		list_del(&page->lru);
-		__free_pages_bulk(page, base, zone, order);
+		__free_pages_bulk(page, zone, order);
 		ret++;
 	}
 	spin_unlock_irqrestore(&zone->lock, flags);
@@ -404,7 +438,7 @@
  */
 static void prep_new_page(struct page *page, int order)
 {
-	if (page->mapping || page_mapped(page) ||
+	if (page->mapping || page_mapcount(page) ||
 	    (page->flags & (
 			1 << PG_private	|
 			1 << PG_locked	|
@@ -732,6 +766,9 @@
 				       classzone_idx, 0, 0))
 			continue;
 
+		if (!cpuset_zone_allowed(z))
+			continue;
+
 		page = buffered_rmqueue(z, order, gfp_mask);
 		if (page)
 			goto got_pg;
@@ -750,6 +787,9 @@
 				       gfp_mask & __GFP_HIGH))
 			continue;
 
+		if (!cpuset_zone_allowed(z))
+			continue;
+
 		page = buffered_rmqueue(z, order, gfp_mask);
 		if (page)
 			goto got_pg;
@@ -759,6 +799,8 @@
 	if (((p->flags & PF_MEMALLOC) || unlikely(test_thread_flag(TIF_MEMDIE))) && !in_interrupt()) {
 		/* go through the zonelist yet again, ignoring mins */
 		for (i = 0; (z = zones[i]) != NULL; i++) {
+			if (!cpuset_zone_allowed(z))
+				continue;
 			page = buffered_rmqueue(z, order, gfp_mask);
 			if (page)
 				goto got_pg;
@@ -798,6 +840,9 @@
 					       gfp_mask & __GFP_HIGH))
 				continue;
 
+			if (!cpuset_zone_allowed(z))
+				continue;
+
 			page = buffered_rmqueue(z, order, gfp_mask);
 			if (page)
 				goto got_pg;
@@ -814,6 +859,9 @@
 					       classzone_idx, 0, 0))
 				continue;
 
+			if (!cpuset_zone_allowed(z))
+				continue;
+
 			page = buffered_rmqueue(z, order, gfp_mask);
 			if (page)
 				goto got_pg;
@@ -1370,7 +1418,6 @@
 	/* initialize zonelists */
 	for (i = 0; i < GFP_ZONETYPES; i++) {
 		zonelist = pgdat->node_zonelists + i;
-		memset(zonelist, 0, sizeof(*zonelist));
 		zonelist->zones[0] = NULL;
 	}
 
@@ -1417,7 +1464,6 @@
 		struct zonelist *zonelist;
 
 		zonelist = pgdat->node_zonelists + i;
-		memset(zonelist, 0, sizeof(*zonelist));
 
 		j = 0;
 		k = ZONE_NORMAL;
@@ -1459,6 +1505,7 @@
 	for_each_online_node(i)
 		build_zonelists(NODE_DATA(i));
 	printk("Built %i zonelists\n", num_online_nodes());
+	cpuset_init_current_mems_allowed();
 }
 
 /*
@@ -1924,15 +1971,20 @@
 
 	for_each_pgdat(pgdat) {
 		for (j = 0; j < MAX_NR_ZONES; j++) {
-			struct zone * zone = pgdat->node_zones + j;
+			struct zone *zone = pgdat->node_zones + j;
 			unsigned long present_pages = zone->present_pages;
 
 			zone->lowmem_reserve[j] = 0;
 
 			for (idx = j-1; idx >= 0; idx--) {
-				struct zone * lower_zone = pgdat->node_zones + idx;
+				struct zone *lower_zone;
+
+				if (sysctl_lowmem_reserve_ratio[idx] < 1)
+					sysctl_lowmem_reserve_ratio[idx] = 1;
 
-				lower_zone->lowmem_reserve[j] = present_pages / sysctl_lowmem_reserve_ratio[idx];
+				lower_zone = pgdat->node_zones + idx;
+				lower_zone->lowmem_reserve[j] = present_pages /
+					sysctl_lowmem_reserve_ratio[idx];
 				present_pages += lower_zone->present_pages;
 			}
 		}
@@ -2039,7 +2091,7 @@
  *	changes.
  */
 int min_free_kbytes_sysctl_handler(ctl_table *table, int write, 
-		struct file *file, void __user *buffer, size_t *length, loff_t *ppos)
+	struct file *file, void __user *buffer, size_t *length, loff_t *ppos)
 {
 	proc_dointvec(table, write, file, buffer, length, ppos);
 	setup_per_zone_pages_min();
@@ -2056,7 +2108,7 @@
  * if in function of the boot time zone sizes.
  */
 int lowmem_reserve_ratio_sysctl_handler(ctl_table *table, int write,
-		 struct file *file, void __user *buffer, size_t *length, loff_t *ppos)
+	struct file *file, void __user *buffer, size_t *length, loff_t *ppos)
 {
 	proc_dointvec_minmax(table, write, file, buffer, length, ppos);
 	setup_per_zone_lowmem_reserve();
diff -Nru a/mm/readahead.c b/mm/readahead.c
--- a/mm/readahead.c	2005-03-11 12:51:52 -08:00
+++ b/mm/readahead.c	2005-03-11 12:51:52 -08:00
@@ -55,7 +55,7 @@
 {
 	ra->start = 0;
 	ra->flags = 0;
-	ra->size = -1;
+	ra->size = 0;
 	ra->ahead_start = 0;
 	ra->ahead_size = 0;
 	return;
@@ -85,14 +85,16 @@
  * not for each call to readahead.  If a cache miss occured, reduce next I/O
  * size, else increase depending on how close to max we are.
  */
-static unsigned long get_next_ra_size(unsigned long cur, unsigned long max,
-				unsigned long min, unsigned long * flags)
+static inline unsigned long get_next_ra_size(struct file_ra_state *ra)
 {
+	unsigned long max = get_max_readahead(ra);
+	unsigned long min = get_min_readahead(ra);
+	unsigned long cur = ra->size;
 	unsigned long newsize;
 
-	if (*flags & RA_FLAG_MISS) {
+	if (ra->flags & RA_FLAG_MISS) {
+		ra->flags &= ~RA_FLAG_MISS;
 		newsize = max((cur - 2), min);
-		*flags &= ~RA_FLAG_MISS;
 	} else if (cur < max / 16) {
 		newsize = 4 * cur;
 	} else {
@@ -190,18 +192,16 @@
  * size:	Number of pages in that read
  *              Together, these form the "current window".
  *              Together, start and size represent the `readahead window'.
- * next_size:   The number of pages to read on the next readahead miss.
- *              Has the magical value -1UL if readahead has been disabled.
  * prev_page:   The page which the readahead algorithm most-recently inspected.
- *              prev_page is mainly an optimisation: if page_cache_readahead
- *		sees that it is again being called for a page which it just
- *		looked at, it can return immediately without making any state
- *		changes.
+ *              It is mainly used to detect sequential file reading.
+ *              If page_cache_readahead sees that it is again being called for
+ *              a page which it just looked at, it can return immediately without
+ *              making any state changes.
  * ahead_start,
  * ahead_size:  Together, these form the "ahead window".
  * ra_pages:	The externally controlled max readahead for this fd.
  *
- * When readahead is in the off state (size == -1UL), readahead is disabled.
+ * When readahead is in the off state (size == 0), readahead is disabled.
  * In this state, prev_page is used to detect the resumption of sequential I/O.
  *
  * The readahead code manages two windows - the "current" and the "ahead"
@@ -222,7 +222,7 @@
  *           ahead window.
  *
  * A `readahead hit' occurs when a read request is made against a page which is
- * the next sequential page. Ahead windowe calculations are done only when it
+ * the next sequential page. Ahead window calculations are done only when it
  * is time to submit a new IO.  The code ramps up the size agressively at first,
  * but slow down as it approaches max_readhead.
  *
@@ -233,12 +233,9 @@
  * read happens to be the first page of the file, it is assumed that a linear
  * read is about to happen and the window is immediately set to the initial size
  * based on I/O request size and the max_readahead.
- * 
- * A page request at (start + size) is not a miss at all - it's just a part of
- * sequential file reading.
  *
  * This function is to be called for every read request, rather than when
- * it is time to perform readahead.  It is called only oce for the entire I/O
+ * it is time to perform readahead.  It is called only once for the entire I/O
  * regardless of size unless readahead is unable to start enough I/O to satisfy
  * the request (I/O request > max_readahead).
  */
@@ -274,7 +271,7 @@
 	/*
 	 * Preallocate as many pages as we will need.
 	 */
-	spin_lock_irq(&mapping->tree_lock);
+	read_lock_irq(&mapping->tree_lock);
 	for (page_idx = 0; page_idx < nr_to_read; page_idx++) {
 		unsigned long page_offset = offset + page_idx;
 		
@@ -285,16 +282,16 @@
 		if (page)
 			continue;
 
-		spin_unlock_irq(&mapping->tree_lock);
+		read_unlock_irq(&mapping->tree_lock);
 		page = page_cache_alloc_cold(mapping);
-		spin_lock_irq(&mapping->tree_lock);
+		read_lock_irq(&mapping->tree_lock);
 		if (!page)
 			break;
 		page->index = page_offset;
 		list_add(&page->lru, &page_pool);
 		ret++;
 	}
-	spin_unlock_irq(&mapping->tree_lock);
+	read_unlock_irq(&mapping->tree_lock);
 
 	/*
 	 * Now start the IO.  We ignore I/O errors - if the page is not
@@ -346,8 +343,8 @@
  * readahead isn't helping.
  *
  */
-int check_ra_success(struct file_ra_state *ra, unsigned long nr_to_read,
-				 unsigned long actual)
+static inline int check_ra_success(struct file_ra_state *ra,
+			unsigned long nr_to_read, unsigned long actual)
 {
 	if (actual == 0) {
 		ra->cache_hit += nr_to_read;
@@ -392,18 +389,46 @@
 {
 	int actual;
 
-	if (block) {
-		actual = __do_page_cache_readahead(mapping, filp,
-						offset, nr_to_read);
-	} else {
-		actual = do_page_cache_readahead(mapping, filp,
-						offset, nr_to_read);
-		if (actual == -1)
-			return 0;
-	}
+	if (!block && bdi_read_congested(mapping->backing_dev_info))
+		return 0;
+
+	actual = __do_page_cache_readahead(mapping, filp, offset, nr_to_read);
+
 	return check_ra_success(ra, nr_to_read, actual);
 }
 
+static int make_ahead_window(struct address_space *mapping, struct file *filp,
+				struct file_ra_state *ra, int force)
+{
+	int block, ret;
+
+	ra->ahead_size = get_next_ra_size(ra);
+	ra->ahead_start = ra->start + ra->size;
+
+	block = force || (ra->prev_page >= ra->ahead_start);
+	ret = blockable_page_cache_readahead(mapping, filp,
+			ra->ahead_start, ra->ahead_size, ra, block);
+
+	if (!ret && !force) {
+		/* A read failure in blocking mode, implies pages are
+		 * all cached. So we can safely assume we have taken
+		 * care of all the pages requested in this call.
+		 * A read failure in non-blocking mode, implies we are
+		 * reading more pages than requested in this call.  So
+		 * we safely assume we have taken care of all the pages
+		 * requested in this call.
+		 *
+		 * Just reset the ahead window in case we failed due to
+		 * congestion.  The ahead window will any way be closed
+		 * in case we failed due to excessive page cache hits.
+		 */
+		ra->ahead_start = 0;
+		ra->ahead_size = 0;
+	}
+
+	return ret;
+}
+
 /*
  * page_cache_readahead is the main function.  If performs the adaptive
  * readahead window size management and submits the readahead I/O.
@@ -413,37 +438,35 @@
 		     struct file *filp, unsigned long offset,
 		     unsigned long req_size)
 {
-	unsigned long max, min;
-	unsigned long newsize = req_size;
-	unsigned long block;
+	unsigned long max, newsize;
+	int sequential;
 
 	/*
-	 * Here we detect the case where the application is performing
-	 * sub-page sized reads.  We avoid doing extra work and bogusly
-	 * perturbing the readahead window expansion logic.
-	 * If size is zero, there is no read ahead window so we need one
+	 * We avoid doing extra work and bogusly perturbing the readahead
+	 * window expansion logic.
 	 */
-	if (offset == ra->prev_page && req_size == 1 && ra->size != 0)
-		goto out;
+	if (offset == ra->prev_page && --req_size)
+		++offset;
+
+	/* Note that prev_page == -1 if it is a first read */
+	sequential = (offset == ra->prev_page + 1);
+	ra->prev_page = offset;
 
 	max = get_max_readahead(ra);
-	min = get_min_readahead(ra);
 	newsize = min(req_size, max);
 
-	if (newsize == 0 || (ra->flags & RA_FLAG_INCACHE)) {
-		newsize = 1;
-		ra->prev_page = offset;
-		goto out;	/* No readahead or file already in cache */
-	}
+	/* No readahead or sub-page sized read or file already in cache */
+	if (newsize == 0 || (ra->flags & RA_FLAG_INCACHE))
+		goto out;
+
+	ra->prev_page += newsize - 1;
+
 	/*
-	 * Special case - first read.  We'll assume it's a whole-file read if
-	 * at start of file, and grow the window fast.  Or detect first
+	 * Special case - first read at start of file. We'll assume it's
+	 * a whole-file read and grow the window fast.  Or detect first
 	 * sequential access
 	 */
-	if ((ra->size == 0 && offset == 0)	/* first io and start of file */
-	    || (ra->size == -1 && ra->prev_page == offset - 1)) {
-		/* First sequential */
-		ra->prev_page  = offset + newsize - 1;
+	if (sequential && ra->size == 0) {
 		ra->size = get_init_ra_size(newsize, max);
 		ra->start = offset;
 		if (!blockable_page_cache_readahead(mapping, filp, offset,
@@ -458,13 +481,9 @@
 		 * IOs,* thus preventing stalls. so issue the ahead window
 		 * immediately.
 		 */
-		if (req_size >= max) {
-			ra->ahead_size = get_next_ra_size(ra->size, max, min,
-							  &ra->flags);
-			ra->ahead_start = ra->start + ra->size;
-			blockable_page_cache_readahead(mapping, filp,
-				 ra->ahead_start, ra->ahead_size, ra, 1);
-		}
+		if (req_size >= max)
+			make_ahead_window(mapping, filp, ra, 1);
+
 		goto out;
 	}
 
@@ -473,9 +492,8 @@
 	 * partial page reads and first access were handled above,
 	 * so this must be the next page otherwise it is random
 	 */
-	if ((offset != (ra->prev_page+1) || (ra->size == 0))) {
+	if (!sequential) {
 		ra_off(ra);
-		ra->prev_page  = offset + newsize - 1;
 		blockable_page_cache_readahead(mapping, filp, offset,
 				 newsize, ra, 1);
 		goto out;
@@ -487,28 +505,8 @@
 	 */
 
 	if (ra->ahead_start == 0) {	 /* no ahead window yet */
-		ra->ahead_size = get_next_ra_size(ra->size, max, min,
-						  &ra->flags);
-		ra->ahead_start = ra->start + ra->size;
-		block = ((offset + newsize -1) >= ra->ahead_start);
-		if (!blockable_page_cache_readahead(mapping, filp,
-		    ra->ahead_start, ra->ahead_size, ra, block)) {
-			/* A read failure in blocking mode, implies pages are
-			 * all cached. So we can safely assume we have taken
-			 * care of all the pages requested in this call. A read
-			 * failure in non-blocking mode, implies we are reading
-			 * more pages than requested in this call.  So we safely
-			 * assume we have taken care of all the pages requested
-			 * in this call.
-			 *
-			 * Just reset the ahead window in case we failed due to
-			 * congestion.  The ahead window will any way be closed
-			 * in case we failed due to exessive page cache hits.
-			 */
-			ra->ahead_start = 0;
-			ra->ahead_size = 0;
+		if (!make_ahead_window(mapping, filp, ra, 0))
 			goto out;
-		}
 	}
 	/*
 	 * Already have an ahead window, check if we crossed into it.
@@ -517,35 +515,14 @@
 	 * we get called back on the first page of the ahead window which
 	 * will allow us to submit more IO.
 	 */
-	if ((offset + newsize - 1) >= ra->ahead_start) {
+	if (ra->prev_page >= ra->ahead_start) {
 		ra->start = ra->ahead_start;
 		ra->size = ra->ahead_size;
-		ra->ahead_start = ra->ahead_start + ra->ahead_size;
-		ra->ahead_size = get_next_ra_size(ra->ahead_size,
-						  max, min, &ra->flags);
-		block = ((offset + newsize - 1) >= ra->ahead_start);
-		if (!blockable_page_cache_readahead(mapping, filp,
-			ra->ahead_start, ra->ahead_size, ra, block)) {
-			/* A read failure in blocking mode, implies pages are
-			 * all cached. So we can safely assume we have taken
-			 * care of all the pages requested in this call.
-			 * A read failure in non-blocking mode, implies we are
-			 * reading more pages than requested in this call.  So
-			 * we safely assume we have taken care of all the pages
-			 * requested in this call.
-			 *
-			 * Just reset the ahead window in case we failed due to
-			 * congestion.  The ahead window will any way be closed
-			 * in case we failed due to excessive page cache hits.
-			 */
-			ra->ahead_start = 0;
-			ra->ahead_size = 0;
-		}
+		make_ahead_window(mapping, filp, ra, 0);
 	}
 
 out:
-	ra->prev_page = offset + newsize - 1;
-	return(newsize);
+	return ra->prev_page + 1;
 }
 
 /*
diff -Nru a/mm/rmap.c b/mm/rmap.c
--- a/mm/rmap.c	2005-03-11 12:51:52 -08:00
+++ b/mm/rmap.c	2005-03-11 12:51:52 -08:00
@@ -51,7 +51,6 @@
 #include <linux/swapops.h>
 #include <linux/slab.h>
 #include <linux/init.h>
-#include <linux/acct.h>
 #include <linux/rmap.h>
 #include <linux/rcupdate.h>
 
@@ -574,7 +573,7 @@
 	}
 
 	/* Nuke the page table entry. */
-	flush_cache_page(vma, address);
+	flush_cache_page(vma, address, page_to_pfn(page));
 	pteval = ptep_clear_flush(vma, address, pte);
 
 	/* Move the dirty bit to the physical page now the pte is gone. */
@@ -594,13 +593,12 @@
 			list_add(&mm->mmlist, &init_mm.mmlist);
 			spin_unlock(&mmlist_lock);
 		}
-		set_pte(pte, swp_entry_to_pte(entry));
+		set_pte_at(mm, address, pte, swp_entry_to_pte(entry));
 		BUG_ON(pte_file(*pte));
 		mm->anon_rss--;
 	}
 
 	mm->rss--;
-	acct_update_integrals();
 	page_remove_rmap(page);
 	page_cache_release(page);
 
@@ -692,12 +690,12 @@
 			continue;
 
 		/* Nuke the page table entry. */
-		flush_cache_page(vma, address);
+		flush_cache_page(vma, address, pfn);
 		pteval = ptep_clear_flush(vma, address, pte);
 
 		/* If nonlinear, store the file page offset in the pte. */
 		if (page->index != linear_page_index(vma, address))
-			set_pte(pte, pgoff_to_pte(page->index));
+			set_pte_at(mm, address, pte, pgoff_to_pte(page->index));
 
 		/* Move the dirty bit to the physical page now the pte is gone. */
 		if (pte_dirty(pteval))
@@ -705,7 +703,6 @@
 
 		page_remove_rmap(page);
 		page_cache_release(page);
-		acct_update_integrals();
 		mm->rss--;
 		(*mapcount)--;
 	}
diff -Nru a/mm/slab.c b/mm/slab.c
--- a/mm/slab.c	2005-03-11 12:51:52 -08:00
+++ b/mm/slab.c	2005-03-11 12:51:52 -08:00
@@ -665,8 +665,10 @@
 	struct array_cache *nc = NULL;
 
 	if (cpu != -1) {
-		nc = kmem_cache_alloc_node(kmem_find_general_cachep(memsize,
-					GFP_KERNEL), cpu_to_node(cpu));
+		kmem_cache_t *cachep;
+		cachep = kmem_find_general_cachep(memsize, GFP_KERNEL);
+		if (cachep)
+			nc = kmem_cache_alloc_node(cachep, cpu_to_node(cpu));
 	}
 	if (!nc)
 		nc = kmalloc(memsize, GFP_KERNEL);
diff -Nru a/mm/swap_state.c b/mm/swap_state.c
--- a/mm/swap_state.c	2005-03-11 12:51:42 -08:00
+++ b/mm/swap_state.c	2005-03-11 12:51:42 -08:00
@@ -35,7 +35,7 @@
 
 struct address_space swapper_space = {
 	.page_tree	= RADIX_TREE_INIT(GFP_ATOMIC|__GFP_NOWARN),
-	.tree_lock	= SPIN_LOCK_UNLOCKED,
+	.tree_lock	= RW_LOCK_UNLOCKED,
 	.a_ops		= &swap_aops,
 	.i_mmap_nonlinear = LIST_HEAD_INIT(swapper_space.i_mmap_nonlinear),
 	.backing_dev_info = &swap_backing_dev_info,
@@ -76,7 +76,7 @@
 	BUG_ON(PagePrivate(page));
 	error = radix_tree_preload(gfp_mask);
 	if (!error) {
-		spin_lock_irq(&swapper_space.tree_lock);
+		write_lock_irq(&swapper_space.tree_lock);
 		error = radix_tree_insert(&swapper_space.page_tree,
 						entry.val, page);
 		if (!error) {
@@ -87,7 +87,7 @@
 			total_swapcache_pages++;
 			pagecache_acct(1);
 		}
-		spin_unlock_irq(&swapper_space.tree_lock);
+		write_unlock_irq(&swapper_space.tree_lock);
 		radix_tree_preload_end();
 	}
 	return error;
@@ -214,9 +214,9 @@
   
 	entry.val = page->private;
 
-	spin_lock_irq(&swapper_space.tree_lock);
+	write_lock_irq(&swapper_space.tree_lock);
 	__delete_from_swap_cache(page);
-	spin_unlock_irq(&swapper_space.tree_lock);
+	write_unlock_irq(&swapper_space.tree_lock);
 
 	swap_free(entry);
 	page_cache_release(page);
@@ -315,13 +315,11 @@
 {
 	struct page *page;
 
-	spin_lock_irq(&swapper_space.tree_lock);
-	page = radix_tree_lookup(&swapper_space.page_tree, entry.val);
-	if (page) {
-		page_cache_get(page);
+	page = find_get_page(&swapper_space, entry.val);
+
+	if (page)
 		INC_CACHE_INFO(find_success);
-	}
-	spin_unlock_irq(&swapper_space.tree_lock);
+
 	INC_CACHE_INFO(find_total);
 	return page;
 }
@@ -344,12 +342,7 @@
 		 * called after lookup_swap_cache() failed, re-calling
 		 * that would confuse statistics.
 		 */
-		spin_lock_irq(&swapper_space.tree_lock);
-		found_page = radix_tree_lookup(&swapper_space.page_tree,
-						entry.val);
-		if (found_page)
-			page_cache_get(found_page);
-		spin_unlock_irq(&swapper_space.tree_lock);
+		found_page = find_get_page(&swapper_space, entry.val);
 		if (found_page)
 			break;
 
diff -Nru a/mm/swapfile.c b/mm/swapfile.c
--- a/mm/swapfile.c	2005-03-11 12:51:41 -08:00
+++ b/mm/swapfile.c	2005-03-11 12:51:41 -08:00
@@ -24,7 +24,6 @@
 #include <linux/module.h>
 #include <linux/rmap.h>
 #include <linux/security.h>
-#include <linux/acct.h>
 #include <linux/backing-dev.h>
 #include <linux/syscalls.h>
 
@@ -292,10 +291,10 @@
 		/* Is the only swap cache user the cache itself? */
 		if (p->swap_map[swp_offset(entry)] == 1) {
 			/* Recheck the page count with the swapcache lock held.. */
-			spin_lock_irq(&swapper_space.tree_lock);
+			write_lock_irq(&swapper_space.tree_lock);
 			if (page_count(page) == 2)
 				retval = 1;
-			spin_unlock_irq(&swapper_space.tree_lock);
+			write_unlock_irq(&swapper_space.tree_lock);
 		}
 		swap_info_put(p);
 	}
@@ -363,13 +362,13 @@
 	retval = 0;
 	if (p->swap_map[swp_offset(entry)] == 1) {
 		/* Recheck the page count with the swapcache lock held.. */
-		spin_lock_irq(&swapper_space.tree_lock);
+		write_lock_irq(&swapper_space.tree_lock);
 		if ((page_count(page) == 2) && !PageWriteback(page)) {
 			__delete_from_swap_cache(page);
 			SetPageDirty(page);
 			retval = 1;
 		}
-		spin_unlock_irq(&swapper_space.tree_lock);
+		write_unlock_irq(&swapper_space.tree_lock);
 	}
 	swap_info_put(p);
 
@@ -392,14 +391,8 @@
 
 	p = swap_info_get(entry);
 	if (p) {
-		if (swap_entry_free(p, swp_offset(entry)) == 1) {
-			spin_lock_irq(&swapper_space.tree_lock);
-			page = radix_tree_lookup(&swapper_space.page_tree,
-				entry.val);
-			if (page && TestSetPageLocked(page))
-				page = NULL;
-			spin_unlock_irq(&swapper_space.tree_lock);
-		}
+		if (swap_entry_free(p, swp_offset(entry)) == 1)
+			page = find_trylock_page(&swapper_space, entry.val);
 		swap_info_put(p);
 	}
 	if (page) {
@@ -434,11 +427,10 @@
 {
 	vma->vm_mm->rss++;
 	get_page(page);
-	set_pte(dir, pte_mkold(mk_pte(page, vma->vm_page_prot)));
+	set_pte_at(vma->vm_mm, address, dir,
+		   pte_mkold(mk_pte(page, vma->vm_page_prot)));
 	page_add_anon_rmap(page, vma, address);
 	swap_free(entry);
-	acct_update_integrals();
-	update_mem_hiwater();
 }
 
 /* vma->vm_mm->page_table_lock is held */
diff -Nru a/mm/truncate.c b/mm/truncate.c
--- a/mm/truncate.c	2005-03-11 12:51:51 -08:00
+++ b/mm/truncate.c	2005-03-11 12:51:51 -08:00
@@ -76,15 +76,15 @@
 	if (PagePrivate(page) && !try_to_release_page(page, 0))
 		return 0;
 
-	spin_lock_irq(&mapping->tree_lock);
+	write_lock_irq(&mapping->tree_lock);
 	if (PageDirty(page)) {
-		spin_unlock_irq(&mapping->tree_lock);
+		write_unlock_irq(&mapping->tree_lock);
 		return 0;
 	}
 
 	BUG_ON(PagePrivate(page));
 	__remove_from_page_cache(page);
-	spin_unlock_irq(&mapping->tree_lock);
+	write_unlock_irq(&mapping->tree_lock);
 	ClearPageUptodate(page);
 	page_cache_release(page);	/* pagecache ref */
 	return 1;
@@ -241,54 +241,68 @@
 EXPORT_SYMBOL(invalidate_inode_pages);
 
 /**
- * invalidate_inode_pages2 - remove all pages from an address_space
+ * invalidate_inode_pages2_range - remove range of pages from an address_space
  * @mapping - the address_space
+ * @start: the page offset 'from' which to invalidate
+ * @end: the page offset 'to' which to invalidate (inclusive)
  *
  * Any pages which are found to be mapped into pagetables are unmapped prior to
  * invalidation.
  *
  * Returns -EIO if any pages could not be invalidated.
  */
-int invalidate_inode_pages2(struct address_space *mapping)
+int invalidate_inode_pages2_range(struct address_space *mapping,
+				  pgoff_t start, pgoff_t end)
 {
 	struct pagevec pvec;
-	pgoff_t next = 0;
+	pgoff_t next;
 	int i;
 	int ret = 0;
-	int did_full_unmap = 0;
+	int did_range_unmap = 0;
+	int wrapped = 0;
 
 	pagevec_init(&pvec, 0);
-	while (!ret && pagevec_lookup(&pvec, mapping, next, PAGEVEC_SIZE)) {
+	next = start;
+	while (next <= end && !ret && !wrapped &&
+		pagevec_lookup(&pvec, mapping, next,
+			min(end - next, (pgoff_t)PAGEVEC_SIZE - 1) + 1)) {
 		for (i = 0; !ret && i < pagevec_count(&pvec); i++) {
 			struct page *page = pvec.pages[i];
+			pgoff_t page_index;
 			int was_dirty;
 
 			lock_page(page);
-			if (page->mapping != mapping) {	/* truncate race? */
+			if (page->mapping != mapping) {
 				unlock_page(page);
 				continue;
 			}
+			page_index = page->index;
+			next = page_index + 1;
+			if (next == 0)
+				wrapped = 1;
+			if (page_index > end) {
+				unlock_page(page);
+				break;
+			}
 			wait_on_page_writeback(page);
-			next = page->index + 1;
 			while (page_mapped(page)) {
-				if (!did_full_unmap) {
+				if (!did_range_unmap) {
 					/*
 					 * Zap the rest of the file in one hit.
-					 * FIXME: invalidate_inode_pages2()
-					 * should take start/end offsets.
 					 */
 					unmap_mapping_range(mapping,
-						page->index << PAGE_CACHE_SHIFT,
-					  	-1, 0);
-					did_full_unmap = 1;
+					    page_index << PAGE_CACHE_SHIFT,
+					    (end - page_index + 1)
+							<< PAGE_CACHE_SHIFT,
+					    0);
+					did_range_unmap = 1;
 				} else {
 					/*
 					 * Just zap this page
 					 */
 					unmap_mapping_range(mapping,
-					  page->index << PAGE_CACHE_SHIFT,
-					  (page->index << PAGE_CACHE_SHIFT)+1,
-					  0);
+					  page_index << PAGE_CACHE_SHIFT,
+					  PAGE_CACHE_SIZE, 0);
 				}
 			}
 			was_dirty = test_clear_page_dirty(page);
@@ -303,5 +317,20 @@
 		cond_resched();
 	}
 	return ret;
+}
+EXPORT_SYMBOL_GPL(invalidate_inode_pages2_range);
+
+/**
+ * invalidate_inode_pages2 - remove all pages from an address_space
+ * @mapping - the address_space
+ *
+ * Any pages which are found to be mapped into pagetables are unmapped prior to
+ * invalidation.
+ *
+ * Returns -EIO if any pages could not be invalidated.
+ */
+int invalidate_inode_pages2(struct address_space *mapping)
+{
+	return invalidate_inode_pages2_range(mapping, 0, -1);
 }
 EXPORT_SYMBOL_GPL(invalidate_inode_pages2);
diff -Nru a/mm/vmalloc.c b/mm/vmalloc.c
--- a/mm/vmalloc.c	2005-03-11 12:51:47 -08:00
+++ b/mm/vmalloc.c	2005-03-11 12:51:47 -08:00
@@ -26,7 +26,7 @@
 static void unmap_area_pte(pmd_t *pmd, unsigned long address,
 				  unsigned long size)
 {
-	unsigned long end;
+	unsigned long base, end;
 	pte_t *pte;
 
 	if (pmd_none(*pmd))
@@ -38,6 +38,7 @@
 	}
 
 	pte = pte_offset_kernel(pmd, address);
+	base = address & PMD_MASK;
 	address &= ~PMD_MASK;
 	end = address + size;
 	if (end > PMD_SIZE)
@@ -45,7 +46,7 @@
 
 	do {
 		pte_t page;
-		page = ptep_get_and_clear(pte);
+		page = ptep_get_and_clear(&init_mm, base + address, pte);
 		address += PAGE_SIZE;
 		pte++;
 		if (pte_none(page))
@@ -59,7 +60,7 @@
 static void unmap_area_pmd(pud_t *pud, unsigned long address,
 				  unsigned long size)
 {
-	unsigned long end;
+	unsigned long base, end;
 	pmd_t *pmd;
 
 	if (pud_none(*pud))
@@ -71,13 +72,14 @@
 	}
 
 	pmd = pmd_offset(pud, address);
+	base = address & PUD_MASK;
 	address &= ~PUD_MASK;
 	end = address + size;
 	if (end > PUD_SIZE)
 		end = PUD_SIZE;
 
 	do {
-		unmap_area_pte(pmd, address, end - address);
+		unmap_area_pte(pmd, base + address, end - address);
 		address = (address + PMD_SIZE) & PMD_MASK;
 		pmd++;
 	} while (address < end);
@@ -87,7 +89,7 @@
 			   unsigned long size)
 {
 	pud_t *pud;
-	unsigned long end;
+	unsigned long base, end;
 
 	if (pgd_none(*pgd))
 		return;
@@ -98,13 +100,14 @@
 	}
 
 	pud = pud_offset(pgd, address);
+	base = address & PGDIR_MASK;
 	address &= ~PGDIR_MASK;
 	end = address + size;
 	if (end > PGDIR_SIZE)
 		end = PGDIR_SIZE;
 
 	do {
-		unmap_area_pmd(pud, address, end - address);
+		unmap_area_pmd(pud, base + address, end - address);
 		address = (address + PUD_SIZE) & PUD_MASK;
 		pud++;
 	} while (address && (address < end));
@@ -114,8 +117,9 @@
 			       unsigned long size, pgprot_t prot,
 			       struct page ***pages)
 {
-	unsigned long end;
+	unsigned long base, end;
 
+	base = address & PMD_MASK;
 	address &= ~PMD_MASK;
 	end = address + size;
 	if (end > PMD_SIZE)
@@ -127,7 +131,7 @@
 		if (!page)
 			return -ENOMEM;
 
-		set_pte(pte, mk_pte(page, prot));
+		set_pte_at(&init_mm, base + address, pte, mk_pte(page, prot));
 		address += PAGE_SIZE;
 		pte++;
 		(*pages)++;
@@ -151,7 +155,7 @@
 		pte_t * pte = pte_alloc_kernel(&init_mm, pmd, base + address);
 		if (!pte)
 			return -ENOMEM;
-		if (map_area_pte(pte, address, end - address, prot, pages))
+		if (map_area_pte(pte, base + address, end - address, prot, pages))
 			return -ENOMEM;
 		address = (address + PMD_SIZE) & PMD_MASK;
 		pmd++;
@@ -252,20 +256,22 @@
 		align = 1ul << bit;
 	}
 	addr = ALIGN(start, align);
+	size = PAGE_ALIGN(size);
 
 	area = kmalloc(sizeof(*area), GFP_KERNEL);
 	if (unlikely(!area))
 		return NULL;
 
-	/*
-	 * We always allocate a guard page.
-	 */
-	size += PAGE_SIZE;
 	if (unlikely(!size)) {
 		kfree (area);
 		return NULL;
 	}
 
+	/*
+	 * We always allocate a guard page.
+	 */
+	size += PAGE_SIZE;
+
 	write_lock(&vmlist_lock);
 	for (p = &vmlist; (tmp = *p) != NULL ;p = &tmp->next) {
 		if ((unsigned long)tmp->addr < addr) {
@@ -345,6 +351,11 @@
 	unmap_vm_area(tmp);
 	*p = tmp->next;
 	write_unlock(&vmlist_lock);
+
+	/*
+	 * Remove the guard page.
+	 */
+	tmp->size -= PAGE_SIZE;
 	return tmp;
 }
 
diff -Nru a/mm/vmscan.c b/mm/vmscan.c
--- a/mm/vmscan.c	2005-03-11 12:51:41 -08:00
+++ b/mm/vmscan.c	2005-03-11 12:51:41 -08:00
@@ -30,6 +30,7 @@
 #include <linux/rmap.h>
 #include <linux/topology.h>
 #include <linux/cpu.h>
+#include <linux/cpuset.h>
 #include <linux/notifier.h>
 #include <linux/rwsem.h>
 
@@ -72,6 +73,12 @@
 	unsigned int gfp_mask;
 
 	int may_writepage;
+
+	/* This context's SWAP_CLUSTER_MAX. If freeing memory for
+	 * suspend, we effectively ignore SWAP_CLUSTER_MAX.
+	 * In this context, it doesn't matter that we scan the
+	 * whole list at once. */
+	int swap_cluster_max;
 };
 
 /*
@@ -137,7 +144,7 @@
 	        shrinker->seeks = seeks;
 	        shrinker->nr = 0;
 	        down_write(&shrinker_rwsem);
-	        list_add(&shrinker->list, &shrinker_list);
+	        list_add_tail(&shrinker->list, &shrinker_list);
 	        up_write(&shrinker_rwsem);
 	}
 	return shrinker;
@@ -475,7 +482,7 @@
 		if (!mapping)
 			goto keep_locked;	/* truncate got there first */
 
-		spin_lock_irq(&mapping->tree_lock);
+		write_lock_irq(&mapping->tree_lock);
 
 		/*
 		 * The non-racy check for busy page.  It is critical to check
@@ -483,7 +490,7 @@
 		 * not in use by anybody. 	(pagecache + us == 2)
 		 */
 		if (page_count(page) != 2 || PageDirty(page)) {
-			spin_unlock_irq(&mapping->tree_lock);
+			write_unlock_irq(&mapping->tree_lock);
 			goto keep_locked;
 		}
 
@@ -491,7 +498,7 @@
 		if (PageSwapCache(page)) {
 			swp_entry_t swap = { .val = page->private };
 			__delete_from_swap_cache(page);
-			spin_unlock_irq(&mapping->tree_lock);
+			write_unlock_irq(&mapping->tree_lock);
 			swap_free(swap);
 			__put_page(page);	/* The pagecache ref */
 			goto free_it;
@@ -499,7 +506,7 @@
 #endif /* CONFIG_SWAP */
 
 		__remove_from_page_cache(page);
-		spin_unlock_irq(&mapping->tree_lock);
+		write_unlock_irq(&mapping->tree_lock);
 		__put_page(page);
 
 free_it:
@@ -552,7 +559,7 @@
 		int nr_scan = 0;
 		int nr_freed;
 
-		while (nr_scan++ < SWAP_CLUSTER_MAX &&
+		while (nr_scan++ < sc->swap_cluster_max &&
 				!list_empty(&zone->inactive_list)) {
 			page = lru_to_page(&zone->inactive_list);
 
@@ -797,37 +804,39 @@
 	 */
 	zone->nr_scan_active += (zone->nr_active >> sc->priority) + 1;
 	nr_active = zone->nr_scan_active;
-	if (nr_active >= SWAP_CLUSTER_MAX)
+	if (nr_active >= sc->swap_cluster_max)
 		zone->nr_scan_active = 0;
 	else
 		nr_active = 0;
 
 	zone->nr_scan_inactive += (zone->nr_inactive >> sc->priority) + 1;
 	nr_inactive = zone->nr_scan_inactive;
-	if (nr_inactive >= SWAP_CLUSTER_MAX)
+	if (nr_inactive >= sc->swap_cluster_max)
 		zone->nr_scan_inactive = 0;
 	else
 		nr_inactive = 0;
 
-	sc->nr_to_reclaim = SWAP_CLUSTER_MAX;
+	sc->nr_to_reclaim = sc->swap_cluster_max;
 
 	while (nr_active || nr_inactive) {
 		if (nr_active) {
 			sc->nr_to_scan = min(nr_active,
-					(unsigned long)SWAP_CLUSTER_MAX);
+					(unsigned long)sc->swap_cluster_max);
 			nr_active -= sc->nr_to_scan;
 			refill_inactive_zone(zone, sc);
 		}
 
 		if (nr_inactive) {
 			sc->nr_to_scan = min(nr_inactive,
-					(unsigned long)SWAP_CLUSTER_MAX);
+					(unsigned long)sc->swap_cluster_max);
 			nr_inactive -= sc->nr_to_scan;
 			shrink_cache(zone, sc);
 			if (sc->nr_to_reclaim <= 0)
 				break;
 		}
 	}
+
+	throttle_vm_writeout();
 }
 
 /*
@@ -857,6 +866,9 @@
 		if (zone->present_pages == 0)
 			continue;
 
+		if (!cpuset_zone_allowed(zone))
+			continue;
+
 		zone->temp_priority = sc->priority;
 		if (zone->prev_priority > sc->priority)
 			zone->prev_priority = sc->priority;
@@ -900,6 +912,9 @@
 	for (i = 0; zones[i] != NULL; i++) {
 		struct zone *zone = zones[i];
 
+		if (!cpuset_zone_allowed(zone))
+			continue;
+
 		zone->temp_priority = DEF_PRIORITY;
 		lru_pages += zone->nr_active + zone->nr_inactive;
 	}
@@ -909,18 +924,19 @@
 		sc.nr_scanned = 0;
 		sc.nr_reclaimed = 0;
 		sc.priority = priority;
+		sc.swap_cluster_max = SWAP_CLUSTER_MAX;
 		shrink_caches(zones, &sc);
 		shrink_slab(sc.nr_scanned, gfp_mask, lru_pages);
 		if (reclaim_state) {
 			sc.nr_reclaimed += reclaim_state->reclaimed_slab;
 			reclaim_state->reclaimed_slab = 0;
 		}
-		if (sc.nr_reclaimed >= SWAP_CLUSTER_MAX) {
+		total_scanned += sc.nr_scanned;
+		total_reclaimed += sc.nr_reclaimed;
+		if (total_reclaimed >= sc.swap_cluster_max) {
 			ret = 1;
 			goto out;
 		}
-		total_scanned += sc.nr_scanned;
-		total_reclaimed += sc.nr_reclaimed;
 
 		/*
 		 * Try to write back as many pages as we just scanned.  This
@@ -929,7 +945,7 @@
 		 * that's undesirable in laptop mode, where we *want* lumpy
 		 * writeout.  So in laptop mode, write out the whole world.
 		 */
-		if (total_scanned > SWAP_CLUSTER_MAX + SWAP_CLUSTER_MAX/2) {
+		if (total_scanned > sc.swap_cluster_max + sc.swap_cluster_max/2) {
 			wakeup_bdflush(laptop_mode ? 0 : total_scanned);
 			sc.may_writepage = 1;
 		}
@@ -939,8 +955,14 @@
 			blk_congestion_wait(WRITE, HZ/10);
 	}
 out:
-	for (i = 0; zones[i] != 0; i++)
-		zones[i]->prev_priority = zones[i]->temp_priority;
+	for (i = 0; zones[i] != 0; i++) {
+		struct zone *zone = zones[i];
+
+		if (!cpuset_zone_allowed(zone))
+			continue;
+
+		zone->prev_priority = zone->temp_priority;
+	}
 	return ret;
 }
 
@@ -1061,6 +1083,7 @@
 			sc.nr_scanned = 0;
 			sc.nr_reclaimed = 0;
 			sc.priority = priority;
+			sc.swap_cluster_max = nr_pages? nr_pages : SWAP_CLUSTER_MAX;
 			shrink_zone(zone, &sc);
 			reclaim_state->reclaimed_slab = 0;
 			shrink_slab(sc.nr_scanned, GFP_KERNEL, lru_pages);
@@ -1098,7 +1121,7 @@
 		 * matches the direct reclaim path behaviour in terms of impact
 		 * on zone->*_priority.
 		 */
-		if (total_reclaimed >= SWAP_CLUSTER_MAX)
+		if ((total_reclaimed >= SWAP_CLUSTER_MAX) && (!nr_pages))
 			break;
 	}
 out:
@@ -1200,6 +1223,8 @@
 		return;
 	if (pgdat->kswapd_max_order < order)
 		pgdat->kswapd_max_order = order;
+	if (!cpuset_zone_allowed(zone))
+		return;
 	if (!waitqueue_active(&zone->zone_pgdat->kswapd_wait))
 		return;
 	wake_up_interruptible(&zone->zone_pgdat->kswapd_wait);
diff -Nru a/net/Kconfig b/net/Kconfig
--- a/net/Kconfig	2005-03-11 12:51:52 -08:00
+++ b/net/Kconfig	2005-03-11 12:51:52 -08:00
@@ -107,27 +107,23 @@
 
 #   IPv6 as module will cause a CRASH if you try to unload it
 config IPV6
-	tristate "The IPv6 protocol (EXPERIMENTAL)"
-	depends on INET && EXPERIMENTAL
+	tristate "The IPv6 protocol"
+	depends on INET
+	default m
 	select CRYPTO if IPV6_PRIVACY
 	select CRYPTO_MD5 if IPV6_PRIVACY
 	---help---
-	  This is experimental support for the IP version 6 (formerly called
-	  IPng "IP next generation").  You will still be able to do
-	  regular IPv4 networking as well.
+	  This is complemental support for the IP version 6.
+	  You will still be able to do traditional IPv4 networking as well.
 
-	  Features of this new protocol include: expanded address space,
-	  authentication and privacy, and seamless interoperability with the
-	  current version of IP (IP version 4). For general information about
-	  IPv6, see <http://playground.sun.com/pub/ipng/html/ipng-main.html>;
-	  for specific information about IPv6 under Linux read the HOWTO at
-	  <http://www.bieringer.de/linux/IPv6/> and the file net/ipv6/README
-	  in the kernel source.
+	  For general information about IPv6, see
+	  <http://playground.sun.com/pub/ipng/html/ipng-main.html>.
+	  For Linux IPv6 development information, see <http://www.linux-ipv6.org>.
+	  For specific information about IPv6 under Linux, read the HOWTO at
+	  <http://www.bieringer.de/linux/IPv6/>.
 
 	  To compile this protocol support as a module, choose M here: the 
 	  module will be called ipv6.
-
-	  It is safe to say N here for now.
 
 source "net/ipv6/Kconfig"
 
diff -Nru a/net/appletalk/ddp.c b/net/appletalk/ddp.c
--- a/net/appletalk/ddp.c	2005-03-11 12:51:52 -08:00
+++ b/net/appletalk/ddp.c	2005-03-11 12:51:52 -08:00
@@ -1022,7 +1022,6 @@
 static int atalk_create(struct socket *sock, int protocol)
 {
 	struct sock *sk;
-	struct atalk_sock *at;
 	int rc = -ESOCKTNOSUPPORT;
 
 	/*
@@ -1032,13 +1031,10 @@
 	if (sock->type != SOCK_RAW && sock->type != SOCK_DGRAM)
 		goto out;
 	rc = -ENOMEM;
-	sk = sk_alloc(PF_APPLETALK, GFP_KERNEL, 1, NULL);
+	sk = sk_alloc(PF_APPLETALK, GFP_KERNEL,
+		      sizeof(struct atalk_sock), NULL);
 	if (!sk)
 		goto out;
-	at = sk->sk_protinfo = kmalloc(sizeof(*at), GFP_KERNEL);
-	if (!at)
-		goto outsk;
-	memset(at, 0, sizeof(*at));
 	rc = 0;
 	sock->ops = &atalk_dgram_ops;
 	sock_init_data(sock, sk);
@@ -1048,9 +1044,6 @@
 	sk->sk_zapped = 1;
 out:
 	return rc;
-outsk:
-	sk_free(sk);
-	goto out;
 }
 
 /* Free a socket. No work needed */
diff -Nru a/net/atm/atm_misc.c b/net/atm/atm_misc.c
--- a/net/atm/atm_misc.c	2005-03-11 12:51:41 -08:00
+++ b/net/atm/atm_misc.c	2005-03-11 12:51:41 -08:00
@@ -16,7 +16,7 @@
 int atm_charge(struct atm_vcc *vcc,int truesize)
 {
 	atm_force_charge(vcc,truesize);
-	if (atomic_read(&vcc->sk->sk_rmem_alloc) <= vcc->sk->sk_rcvbuf)
+	if (atomic_read(&sk_atm(vcc)->sk_rmem_alloc) <= sk_atm(vcc)->sk_rcvbuf)
 		return 1;
 	atm_return(vcc,truesize);
 	atomic_inc(&vcc->stats->rx_drop);
@@ -27,15 +27,16 @@
 struct sk_buff *atm_alloc_charge(struct atm_vcc *vcc,int pdu_size,
     int gfp_flags)
 {
+	struct sock *sk = sk_atm(vcc);
 	int guess = atm_guess_pdu2truesize(pdu_size);
 
 	atm_force_charge(vcc,guess);
-	if (atomic_read(&vcc->sk->sk_rmem_alloc) <= vcc->sk->sk_rcvbuf) {
+	if (atomic_read(&sk->sk_rmem_alloc) <= sk->sk_rcvbuf) {
 		struct sk_buff *skb = alloc_skb(pdu_size,gfp_flags);
 
 		if (skb) {
 			atomic_add(skb->truesize-guess,
-				   &vcc->sk->sk_rmem_alloc);
+				   &sk->sk_rmem_alloc);
 			return skb;
 		}
 	}
diff -Nru a/net/atm/br2684.c b/net/atm/br2684.c
--- a/net/atm/br2684.c	2005-03-11 12:51:52 -08:00
+++ b/net/atm/br2684.c	2005-03-11 12:51:52 -08:00
@@ -190,7 +190,7 @@
 		dev_kfree_skb(skb);
 		return 0;
 		}
-	atomic_add(skb->truesize, &atmvcc->sk->sk_wmem_alloc);
+	atomic_add(skb->truesize, &sk_atm(atmvcc)->sk_wmem_alloc);
 	ATM_SKB(skb)->atm_options = atmvcc->atm_options;
 	brdev->stats.tx_packets++;
 	brdev->stats.tx_bytes += skb->len;
@@ -557,7 +557,7 @@
 	barrier();
 	atmvcc->push = br2684_push;
 	skb_queue_head_init(&copy);
-	skb_migrate(&atmvcc->sk->sk_receive_queue, &copy);
+	skb_migrate(&sk_atm(atmvcc)->sk_receive_queue, &copy);
 	while ((skb = skb_dequeue(&copy)) != NULL) {
 		BRPRIV(skb->dev)->stats.rx_bytes -= skb->len;
 		BRPRIV(skb->dev)->stats.rx_packets--;
diff -Nru a/net/atm/clip.c b/net/atm/clip.c
--- a/net/atm/clip.c	2005-03-11 12:51:51 -08:00
+++ b/net/atm/clip.c	2005-03-11 12:51:51 -08:00
@@ -58,6 +58,7 @@
 
 static int to_atmarpd(enum atmarp_ctrl_type type,int itf,unsigned long ip)
 {
+	struct sock *sk;
 	struct atmarp_ctrl *ctrl;
 	struct sk_buff *skb;
 
@@ -70,8 +71,10 @@
 	ctrl->itf_num = itf;
 	ctrl->ip = ip;
 	atm_force_charge(atmarpd,skb->truesize);
-	skb_queue_tail(&atmarpd->sk->sk_receive_queue, skb);
-	atmarpd->sk->sk_data_ready(atmarpd->sk, skb->len);
+
+	sk = sk_atm(atmarpd);
+	skb_queue_tail(&sk->sk_receive_queue, skb);
+	sk->sk_data_ready(sk, skb->len);
 	return 0;
 }
 
@@ -434,7 +437,7 @@
 		memcpy(here,llc_oui,sizeof(llc_oui));
 		((u16 *) here)[3] = skb->protocol;
 	}
-	atomic_add(skb->truesize, &vcc->sk->sk_wmem_alloc);
+	atomic_add(skb->truesize, &sk_atm(vcc)->sk_wmem_alloc);
 	ATM_SKB(skb)->atm_options = vcc->atm_options;
 	entry->vccs->last_use = jiffies;
 	DPRINTK("atm_skb(%p)->vcc(%p)->dev(%p)\n",skb,vcc,vcc->dev);
@@ -493,7 +496,7 @@
 	vcc->push = clip_push;
 	vcc->pop = clip_pop;
 	skb_queue_head_init(&copy);
-	skb_migrate(&vcc->sk->sk_receive_queue, &copy);
+	skb_migrate(&sk_atm(vcc)->sk_receive_queue, &copy);
 	/* re-process everything received between connection setup and MKIP */
 	while ((skb = skb_dequeue(&copy)) != NULL)
 		if (!clip_devs) {
@@ -686,10 +689,10 @@
 	barrier();
 	unregister_inetaddr_notifier(&clip_inet_notifier);
 	unregister_netdevice_notifier(&clip_dev_notifier);
-	if (skb_peek(&vcc->sk->sk_receive_queue))
+	if (skb_peek(&sk_atm(vcc)->sk_receive_queue))
 		printk(KERN_ERR "atmarpd_close: closing with requests "
 		    "pending\n");
-	skb_queue_purge(&vcc->sk->sk_receive_queue);
+	skb_queue_purge(&sk_atm(vcc)->sk_receive_queue);
 	DPRINTK("(done)\n");
 	module_put(THIS_MODULE);
 }
@@ -723,7 +726,7 @@
 	set_bit(ATM_VF_READY,&vcc->flags);
 	    /* allow replies and avoid getting closed if signaling dies */
 	vcc->dev = &atmarpd_dev;
-	vcc_insert_socket(vcc->sk);
+	vcc_insert_socket(sk_atm(vcc));
 	vcc->push = NULL;
 	vcc->pop = NULL; /* crash */
 	vcc->push_oam = NULL; /* crash */
@@ -822,7 +825,7 @@
 	int svc, llc, off;
 
 	svc = ((clip_vcc == SEQ_NO_VCC_TOKEN) ||
-	       (clip_vcc->vcc->sk->sk_family == AF_ATMSVC));
+	       (sk_atm(clip_vcc->vcc)->sk_family == AF_ATMSVC));
 
 	llc = ((clip_vcc == SEQ_NO_VCC_TOKEN) ||
 	       clip_vcc->encap);
diff -Nru a/net/atm/common.c b/net/atm/common.c
--- a/net/atm/common.c	2005-03-11 12:51:52 -08:00
+++ b/net/atm/common.c	2005-03-11 12:51:52 -08:00
@@ -68,17 +68,18 @@
 static struct sk_buff *alloc_tx(struct atm_vcc *vcc,unsigned int size)
 {
 	struct sk_buff *skb;
+	struct sock *sk = sk_atm(vcc);
 
-	if (atomic_read(&vcc->sk->sk_wmem_alloc) && !atm_may_send(vcc, size)) {
+	if (atomic_read(&sk->sk_wmem_alloc) && !atm_may_send(vcc, size)) {
 		DPRINTK("Sorry: wmem_alloc = %d, size = %d, sndbuf = %d\n",
-			atomic_read(&vcc->sk->sk_wmem_alloc), size,
-			vcc->sk->sk_sndbuf);
+			atomic_read(&sk->sk_wmem_alloc), size,
+			sk->sk_sndbuf);
 		return NULL;
 	}
 	while (!(skb = alloc_skb(size,GFP_KERNEL))) schedule();
-	DPRINTK("AlTx %d += %d\n", atomic_read(&vcc->sk->sk_wmem_alloc),
+	DPRINTK("AlTx %d += %d\n", atomic_read(&sk->sk_wmem_alloc),
 		skb->truesize);
-	atomic_add(skb->truesize, &vcc->sk->sk_wmem_alloc);
+	atomic_add(skb->truesize, &sk->sk_wmem_alloc);
 	return skb;
 }
 
@@ -89,15 +90,11 @@
 
 static void vcc_sock_destruct(struct sock *sk)
 {
-	struct atm_vcc *vcc = atm_sk(sk);
-
-	if (atomic_read(&vcc->sk->sk_rmem_alloc))
+	if (atomic_read(&sk->sk_rmem_alloc))
 		printk(KERN_DEBUG "vcc_sock_destruct: rmem leakage (%d bytes) detected.\n", atomic_read(&sk->sk_rmem_alloc));
 
-	if (atomic_read(&vcc->sk->sk_wmem_alloc))
+	if (atomic_read(&sk->sk_wmem_alloc))
 		printk(KERN_DEBUG "vcc_sock_destruct: wmem leakage (%d bytes) detected.\n", atomic_read(&sk->sk_wmem_alloc));
-
-	kfree(sk->sk_protinfo);
 }
 
 static void vcc_def_wakeup(struct sock *sk)
@@ -139,7 +136,7 @@
 	sock->sk = NULL;
 	if (sock->type == SOCK_STREAM)
 		return -EINVAL;
-	sk = sk_alloc(family, GFP_KERNEL, 1, NULL);
+	sk = sk_alloc(family, GFP_KERNEL, sizeof(struct atm_vcc), NULL);
 	if (!sk)
 		return -ENOMEM;
 	sock_init_data(sock, sk);
@@ -147,20 +144,13 @@
 	sk->sk_state_change = vcc_def_wakeup;
 	sk->sk_write_space = vcc_write_space;
 
-	vcc = sk->sk_protinfo = kmalloc(sizeof(*vcc), GFP_KERNEL);
-	if (!vcc) {
-		sk_free(sk);
-		return -ENOMEM;
-	}
-
-	memset(vcc, 0, sizeof(*vcc));
-	vcc->sk = sk;
+	vcc = atm_sk(sk);
 	vcc->dev = NULL;
 	memset(&vcc->local,0,sizeof(struct sockaddr_atmsvc));
 	memset(&vcc->remote,0,sizeof(struct sockaddr_atmsvc));
 	vcc->qos.txtp.max_sdu = 1 << 16; /* for meta VCs */
-	atomic_set(&vcc->sk->sk_wmem_alloc, 0);
-	atomic_set(&vcc->sk->sk_rmem_alloc, 0);
+	atomic_set(&sk->sk_wmem_alloc, 0);
+	atomic_set(&sk->sk_rmem_alloc, 0);
 	vcc->push = NULL;
 	vcc->pop = NULL;
 	vcc->push_oam = NULL;
@@ -187,7 +177,7 @@
 
 		vcc_remove_socket(sk);	/* no more receive */
 
-		while ((skb = skb_dequeue(&vcc->sk->sk_receive_queue)) != NULL) {
+		while ((skb = skb_dequeue(&sk->sk_receive_queue)) != NULL) {
 			atm_return(vcc,skb->truesize);
 			kfree_skb(skb);
 		}
@@ -215,11 +205,13 @@
 
 void vcc_release_async(struct atm_vcc *vcc, int reply)
 {
+	struct sock *sk = sk_atm(vcc);
+
 	set_bit(ATM_VF_CLOSE, &vcc->flags);
-	vcc->sk->sk_shutdown |= RCV_SHUTDOWN;
-	vcc->sk->sk_err = -reply;
+	sk->sk_shutdown |= RCV_SHUTDOWN;
+	sk->sk_err = -reply;
 	clear_bit(ATM_VF_WAITING, &vcc->flags);
-	vcc->sk->sk_state_change(vcc->sk);
+	sk->sk_state_change(sk);
 }
 
 
@@ -328,6 +320,7 @@
 static int __vcc_connect(struct atm_vcc *vcc, struct atm_dev *dev, short vpi,
 			 int vci)
 {
+	struct sock *sk = sk_atm(vcc);
 	int error;
 
 	if ((vpi != ATM_VPI_UNSPEC && vpi != ATM_VPI_ANY &&
@@ -347,7 +340,7 @@
 	}
 	vcc->vpi = vpi;
 	vcc->vci = vci;
-	__vcc_insert_socket(vcc->sk);
+	__vcc_insert_socket(sk);
 	write_unlock_irq(&vcc_sklist_lock);
 	switch (vcc->qos.aal) {
 		case ATM_AAL0:
@@ -386,7 +379,7 @@
 	return 0;
 
 fail:
-	vcc_remove_socket(vcc->sk);
+	vcc_remove_socket(sk);
 fail_module_put:
 	module_put(dev->ops->owner);
 	/* ensure we get dev module ref count correct */
@@ -495,7 +488,7 @@
         if (error)
                 return error;
         sock_recv_timestamp(msg, sk, skb);
-        DPRINTK("RcvM %d -= %d\n", atomic_read(&vcc->sk->rmem_alloc), skb->truesize);
+        DPRINTK("RcvM %d -= %d\n", atomic_read(&sk->rmem_alloc), skb->truesize);
         atm_return(vcc, skb->truesize);
         skb_free_datagram(sk, skb);
         return copied;
@@ -615,7 +608,7 @@
 		return mask;
 
 	if (vcc->qos.txtp.traffic_class != ATM_NONE &&
-	    vcc_writable(vcc->sk))
+	    vcc_writable(sk))
 		mask |= POLLOUT | POLLWRNORM | POLLWRBAND;
 
 	return mask;
@@ -638,7 +631,7 @@
 	if (!error) error = adjust_tp(&qos->rxtp,qos->aal);
 	if (error) return error;
 	if (!vcc->dev->ops->change_qos) return -EOPNOTSUPP;
-	if (vcc->sk->sk_family == AF_ATMPVC)
+	if (sk_atm(vcc)->sk_family == AF_ATMPVC)
 		return vcc->dev->ops->change_qos(vcc,qos,ATM_MF_SET);
 	return svc_change_qos(vcc,qos);
 }
diff -Nru a/net/atm/ioctl.c b/net/atm/ioctl.c
--- a/net/atm/ioctl.c	2005-03-11 12:51:50 -08:00
+++ b/net/atm/ioctl.c	2005-03-11 12:51:50 -08:00
@@ -46,6 +46,7 @@
 
 int vcc_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
 {
+	struct sock *sk = sock->sk;
 	struct atm_vcc *vcc;
 	int error;
 	struct list_head * pos;
@@ -59,8 +60,8 @@
 				error =  -EINVAL;
 				goto done;
 			}
-			error = put_user(vcc->sk->sk_sndbuf -
-					 atomic_read(&vcc->sk->sk_wmem_alloc),
+			error = put_user(sk->sk_sndbuf -
+					 atomic_read(&sk->sk_wmem_alloc),
 					 (int __user *) argp) ? -EFAULT : 0;
 			goto done;
 		case SIOCINQ:
@@ -71,13 +72,13 @@
 					error = -EINVAL;
 					goto done;
 				}
-				skb = skb_peek(&vcc->sk->sk_receive_queue);
+				skb = skb_peek(&sk->sk_receive_queue);
 				error = put_user(skb ? skb->len : 0,
 					 	 (int __user *)argp) ? -EFAULT : 0;
 				goto done;
 			}
 		case SIOCGSTAMP: /* borrowed from IP */
-			error = sock_get_timestamp(vcc->sk, argp);
+			error = sock_get_timestamp(sk, argp);
 			goto done;
 		case ATM_SETSC:
 			printk(KERN_WARNING "ATM_SETSC is obsolete\n");
diff -Nru a/net/atm/lec.c b/net/atm/lec.c
--- a/net/atm/lec.c	2005-03-11 12:51:47 -08:00
+++ b/net/atm/lec.c	2005-03-11 12:51:47 -08:00
@@ -122,6 +122,7 @@
         eth = (struct ethhdr *)skb->data;
         buff = skb->data + skb->dev->hard_header_len;
         if (*buff++ == 0x42 && *buff++ == 0x42 && *buff++ == 0x03) {
+		struct sock *sk;
                 struct sk_buff *skb2;
                 struct atmlec_msg *mesg;
 
@@ -135,8 +136,9 @@
 
                 priv = (struct lec_priv *)dev->priv;
                 atm_force_charge(priv->lecd, skb2->truesize);
-                skb_queue_tail(&priv->lecd->sk->sk_receive_queue, skb2);
-                priv->lecd->sk->sk_data_ready(priv->lecd->sk, skb2->len);
+		sk = sk_atm(priv->lecd);
+                skb_queue_tail(&sk->sk_receive_queue, skb2);
+                sk->sk_data_ready(sk, skb2->len);
         }
 
         return;
@@ -214,7 +216,7 @@
 	ATM_SKB(skb)->vcc = vcc;
 	ATM_SKB(skb)->atm_options = vcc->atm_options;
 
-	atomic_add(skb->truesize, &vcc->sk->sk_wmem_alloc);
+	atomic_add(skb->truesize, &sk_atm(vcc)->sk_wmem_alloc);
 	if (vcc->send(vcc, skb) < 0) {
 		priv->stats.tx_dropped++;
 		return;
@@ -430,7 +432,7 @@
         int i;
         char *tmp; /* FIXME */
 
-	atomic_sub(skb->truesize, &vcc->sk->sk_wmem_alloc);
+	atomic_sub(skb->truesize, &sk_atm(vcc)->sk_wmem_alloc);
         mesg = (struct atmlec_msg *)skb->data;
         tmp = skb->data;
         tmp += sizeof(struct atmlec_msg);
@@ -528,6 +530,7 @@
                     f->dst->state == BR_STATE_FORWARDING) {
                                 /* hit from bridge table, send LE_ARP_RESPONSE */
                         struct sk_buff *skb2;
+			struct sock *sk;
 
                         DPRINTK("%s: entry found, responding to zeppelin\n", dev->name);
                         skb2 = alloc_skb(sizeof(struct atmlec_msg), GFP_ATOMIC);
@@ -538,8 +541,9 @@
                         skb2->len = sizeof(struct atmlec_msg);
                         memcpy(skb2->data, mesg, sizeof(struct atmlec_msg));
                         atm_force_charge(priv->lecd, skb2->truesize);
-                        skb_queue_tail(&priv->lecd->sk->sk_receive_queue, skb2);
-                        priv->lecd->sk->sk_data_ready(priv->lecd->sk, skb2->len);
+			sk = sk_atm(priv->lecd);
+                        skb_queue_tail(&sk->sk_receive_queue, skb2);
+                        sk->sk_data_ready(sk, skb2->len);
                 }
                 if (f != NULL) br_fdb_put_hook(f);
 #endif /* defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) */
@@ -567,10 +571,10 @@
         netif_stop_queue(dev);
         lec_arp_destroy(priv);
 
-        if (skb_peek(&vcc->sk->sk_receive_queue))
+        if (skb_peek(&sk_atm(vcc)->sk_receive_queue))
 		printk("%s lec_atm_close: closing with messages pending\n",
                        dev->name);
-        while ((skb = skb_dequeue(&vcc->sk->sk_receive_queue)) != NULL) {
+        while ((skb = skb_dequeue(&sk_atm(vcc)->sk_receive_queue)) != NULL) {
                 atm_return(vcc, skb->truesize);
 		dev_kfree_skb(skb);
         }
@@ -600,6 +604,7 @@
              unsigned char *mac_addr, unsigned char *atm_addr,
              struct sk_buff *data)
 {
+	struct sock *sk;
 	struct sk_buff *skb;
 	struct atmlec_msg *mesg;
 
@@ -623,14 +628,15 @@
 		memcpy(&mesg->content.normal.atm_addr, atm_addr, ATM_ESA_LEN);
 
         atm_force_charge(priv->lecd, skb->truesize);
-	skb_queue_tail(&priv->lecd->sk->sk_receive_queue, skb);
-        priv->lecd->sk->sk_data_ready(priv->lecd->sk, skb->len);
+	sk = sk_atm(priv->lecd);
+	skb_queue_tail(&sk->sk_receive_queue, skb);
+        sk->sk_data_ready(sk, skb->len);
 
         if (data != NULL) {
                 DPRINTK("lec: about to send %d bytes of data\n", data->len);
                 atm_force_charge(priv->lecd, data->truesize);
-                skb_queue_tail(&priv->lecd->sk->sk_receive_queue, data);
-                priv->lecd->sk->sk_data_ready(priv->lecd->sk, skb->len);
+                skb_queue_tail(&sk->sk_receive_queue, data);
+                sk->sk_data_ready(sk, skb->len);
         }
 
         return 0;
@@ -711,9 +717,11 @@
                 printk("%s...\n",buf);
 #endif /* DUMP_PACKETS > 0 */
         if (memcmp(skb->data, lec_ctrl_magic, 4) ==0) { /* Control frame, to daemon*/
+		struct sock *sk = sk_atm(vcc);
+
                 DPRINTK("%s: To daemon\n",dev->name);
-                skb_queue_tail(&vcc->sk->sk_receive_queue, skb);
-                vcc->sk->sk_data_ready(vcc->sk, skb->len);
+                skb_queue_tail(&sk->sk_receive_queue, skb);
+                sk->sk_data_ready(sk, skb->len);
         } else { /* Data frame, queue to protocol handlers */
                 unsigned char *dst;
 
@@ -866,7 +874,7 @@
 	priv->itfnum = i;  /* LANE2 addition */
         priv->lecd = vcc;
         vcc->dev = &lecatm_dev;
-        vcc_insert_socket(vcc->sk);
+        vcc_insert_socket(sk_atm(vcc));
         
         vcc->proto_data = dev_lec[i];
 	set_bit(ATM_VF_META,&vcc->flags);
diff -Nru a/net/atm/mpc.c b/net/atm/mpc.c
--- a/net/atm/mpc.c	2005-03-11 12:51:51 -08:00
+++ b/net/atm/mpc.c	2005-03-11 12:51:51 -08:00
@@ -522,7 +522,7 @@
 		memcpy(skb->data, &llc_snap_mpoa_data, sizeof(struct llc_snap_hdr));
 	}
 
-	atomic_add(skb->truesize, &entry->shortcut->sk->sk_wmem_alloc);
+	atomic_add(skb->truesize, &sk_atm(entry->shortcut)->sk_wmem_alloc);
 	ATM_SKB(skb)->atm_options = entry->shortcut->atm_options;
 	entry->shortcut->send(entry->shortcut, skb);
 	entry->packets_fwded++;
@@ -665,10 +665,12 @@
 	
 	skb->dev = dev;
 	if (memcmp(skb->data, &llc_snap_mpoa_ctrl, sizeof(struct llc_snap_hdr)) == 0) {
+		struct sock *sk = sk_atm(vcc);
+
 		dprintk("mpoa: (%s) mpc_push: control packet arrived\n", dev->name);
 		/* Pass control packets to daemon */
-		skb_queue_tail(&vcc->sk->sk_receive_queue, skb);
-		vcc->sk->sk_data_ready(vcc->sk, skb->len);
+		skb_queue_tail(&sk->sk_receive_queue, skb);
+		sk->sk_data_ready(sk, skb->len);
 		return;
 	}
 
@@ -794,7 +796,7 @@
 
 	mpc->mpoad_vcc = vcc;
 	vcc->dev = &mpc_dev;
-	vcc_insert_socket(vcc->sk);
+	vcc_insert_socket(sk_atm(vcc));
 	set_bit(ATM_VF_META,&vcc->flags);
 	set_bit(ATM_VF_READY,&vcc->flags);
 
@@ -853,7 +855,7 @@
 	mpc->in_ops->destroy_cache(mpc);
 	mpc->eg_ops->destroy_cache(mpc);
 
-	while ((skb = skb_dequeue(&vcc->sk->sk_receive_queue))) {
+	while ((skb = skb_dequeue(&sk_atm(vcc)->sk_receive_queue))) {
 		atm_return(vcc, skb->truesize);
 		kfree_skb(skb);
 	}
@@ -873,7 +875,7 @@
 	
 	struct mpoa_client *mpc = find_mpc_by_vcc(vcc);
 	struct k_message *mesg = (struct k_message*)skb->data;
-	atomic_sub(skb->truesize, &vcc->sk->sk_wmem_alloc);
+	atomic_sub(skb->truesize, &sk_atm(vcc)->sk_wmem_alloc);
 	
 	if (mpc == NULL) {
 		printk("mpoa: msg_from_mpoad: no mpc found\n");
@@ -938,6 +940,7 @@
 int msg_to_mpoad(struct k_message *mesg, struct mpoa_client *mpc)
 {
 	struct sk_buff *skb;
+	struct sock *sk;
 
 	if (mpc == NULL || !mpc->mpoad_vcc) {
 		printk("mpoa: msg_to_mpoad: mesg %d to a non-existent mpoad\n", mesg->type);
@@ -950,8 +953,10 @@
 	skb_put(skb, sizeof(struct k_message));
 	memcpy(skb->data, mesg, sizeof(struct k_message));
 	atm_force_charge(mpc->mpoad_vcc, skb->truesize);
-	skb_queue_tail(&mpc->mpoad_vcc->sk->sk_receive_queue, skb);
-	mpc->mpoad_vcc->sk->sk_data_ready(mpc->mpoad_vcc->sk, skb->len);
+	
+	sk = sk_atm(mpc->mpoad_vcc);
+	skb_queue_tail(&sk->sk_receive_queue, skb);
+	sk->sk_data_ready(sk, skb->len);
 
 	return 0;
 }
@@ -1206,6 +1211,7 @@
 
 static void purge_egress_shortcut(struct atm_vcc *vcc, eg_cache_entry *entry)
 {
+	struct sock *sk;
 	struct k_message *purge_msg;
 	struct sk_buff *skb;
 
@@ -1229,8 +1235,10 @@
 		purge_msg->content.eg_info = entry->ctrl_info;
 
 	atm_force_charge(vcc, skb->truesize);
-	skb_queue_tail(&vcc->sk->sk_receive_queue, skb);
-	vcc->sk->sk_data_ready(vcc->sk, skb->len);
+
+	sk = sk_atm(vcc);
+	skb_queue_tail(&sk->sk_receive_queue, skb);
+	sk->sk_data_ready(sk, skb->len);
 	dprintk("mpoa: purge_egress_shortcut: exiting:\n");
 
 	return;
diff -Nru a/net/atm/pppoatm.c b/net/atm/pppoatm.c
--- a/net/atm/pppoatm.c	2005-03-11 12:51:47 -08:00
+++ b/net/atm/pppoatm.c	2005-03-11 12:51:47 -08:00
@@ -233,7 +233,8 @@
 		kfree_skb(skb);
 		return 1;
 	}
-	atomic_add(skb->truesize, &ATM_SKB(skb)->vcc->sk->sk_wmem_alloc);
+
+	atomic_add(skb->truesize, &sk_atm(ATM_SKB(skb)->vcc)->sk_wmem_alloc);
 	ATM_SKB(skb)->atm_options = ATM_SKB(skb)->vcc->atm_options;
 	DPRINTK("(unit %d): atm_skb(%p)->vcc(%p)->dev(%p)\n",
 	    pvcc->chan.unit, skb, ATM_SKB(skb)->vcc,
diff -Nru a/net/atm/proc.c b/net/atm/proc.c
--- a/net/atm/proc.c	2005-03-11 12:51:42 -08:00
+++ b/net/atm/proc.c	2005-03-11 12:51:42 -08:00
@@ -71,9 +71,7 @@
 
 static inline int compare_family(struct sock *sk, int family)
 {
-	struct atm_vcc *vcc = atm_sk(sk);
-
-	return !family || (vcc->sk->sk_family == family);
+	return !family || (sk->sk_family == family);
 }
 
 static int __vcc_walk(struct sock **sock, int family, int *bucket, loff_t l)
@@ -203,13 +201,15 @@
 
 static void vcc_info(struct seq_file *seq, struct atm_vcc *vcc)
 {
+	struct sock *sk = sk_atm(vcc);
+
 	seq_printf(seq, "%p ", vcc);
 	if (!vcc->dev)
 		seq_printf(seq, "Unassigned    ");
 	else 
 		seq_printf(seq, "%3d %3d %5d ", vcc->dev->number, vcc->vpi,
 			vcc->vci);
-	switch (vcc->sk->sk_family) {
+	switch (sk->sk_family) {
 		case AF_ATMPVC:
 			seq_printf(seq, "PVC");
 			break;
@@ -217,12 +217,12 @@
 			seq_printf(seq, "SVC");
 			break;
 		default:
-			seq_printf(seq, "%3d", vcc->sk->sk_family);
+			seq_printf(seq, "%3d", sk->sk_family);
 	}
-	seq_printf(seq, " %04lx  %5d %7d/%7d %7d/%7d [%d]\n", vcc->flags, vcc->sk->sk_err,
-		atomic_read(&vcc->sk->sk_wmem_alloc),vcc->sk->sk_sndbuf,
-		atomic_read(&vcc->sk->sk_rmem_alloc),vcc->sk->sk_rcvbuf,
-		atomic_read(&vcc->sk->sk_refcnt));
+	seq_printf(seq, " %04lx  %5d %7d/%7d %7d/%7d [%d]\n", vcc->flags, sk->sk_err,
+		  atomic_read(&sk->sk_wmem_alloc), sk->sk_sndbuf,
+		  atomic_read(&sk->sk_rmem_alloc), sk->sk_rcvbuf,
+		  atomic_read(&sk->sk_refcnt));
 }
 
 static void svc_info(struct seq_file *seq, struct atm_vcc *vcc)
diff -Nru a/net/atm/raw.c b/net/atm/raw.c
--- a/net/atm/raw.c	2005-03-11 12:51:51 -08:00
+++ b/net/atm/raw.c	2005-03-11 12:51:51 -08:00
@@ -28,19 +28,23 @@
 void atm_push_raw(struct atm_vcc *vcc,struct sk_buff *skb)
 {
 	if (skb) {
-		skb_queue_tail(&vcc->sk->sk_receive_queue, skb);
-		vcc->sk->sk_data_ready(vcc->sk, skb->len);
+		struct sock *sk = sk_atm(vcc);
+
+		skb_queue_tail(&sk->sk_receive_queue, skb);
+		sk->sk_data_ready(sk, skb->len);
 	}
 }
 
 
 static void atm_pop_raw(struct atm_vcc *vcc,struct sk_buff *skb)
 {
-	DPRINTK("APopR (%d) %d -= %d\n", vcc->vci, vcc->sk->sk_wmem_alloc,
+	struct sock *sk = sk_atm(vcc);
+
+	DPRINTK("APopR (%d) %d -= %d\n", vcc->vci, sk->sk_wmem_alloc,
 		skb->truesize);
-	atomic_sub(skb->truesize, &vcc->sk->sk_wmem_alloc);
+	atomic_sub(skb->truesize, &sk->sk_wmem_alloc);
 	dev_kfree_skb_any(skb);
-	vcc->sk->sk_write_space(vcc->sk);
+	sk->sk_write_space(sk);
 }
 
 
diff -Nru a/net/atm/signaling.c b/net/atm/signaling.c
--- a/net/atm/signaling.c	2005-03-11 12:51:50 -08:00
+++ b/net/atm/signaling.c	2005-03-11 12:51:50 -08:00
@@ -62,8 +62,8 @@
 	}
 #endif
 	atm_force_charge(sigd,skb->truesize);
-	skb_queue_tail(&sigd->sk->sk_receive_queue,skb);
-	sigd->sk->sk_data_ready(sigd->sk, skb->len);
+	skb_queue_tail(&sk_atm(sigd)->sk_receive_queue,skb);
+	sk_atm(sigd)->sk_data_ready(sk_atm(sigd), skb->len);
 }
 
 
@@ -97,15 +97,18 @@
 {
 	struct atmsvc_msg *msg;
 	struct atm_vcc *session_vcc;
+	struct sock *sk;
 
 	msg = (struct atmsvc_msg *) skb->data;
-	atomic_sub(skb->truesize, &vcc->sk->sk_wmem_alloc);
+	atomic_sub(skb->truesize, &sk_atm(vcc)->sk_wmem_alloc);
 	DPRINTK("sigd_send %d (0x%lx)\n",(int) msg->type,
 	  (unsigned long) msg->vcc);
 	vcc = *(struct atm_vcc **) &msg->vcc;
+	sk = sk_atm(vcc);
+
 	switch (msg->type) {
 		case as_okay:
-			vcc->sk->sk_err = -msg->reply;
+			sk->sk_err = -msg->reply;
 			clear_bit(ATM_VF_WAITING, &vcc->flags);
 			if (!*vcc->local.sas_addr.prv &&
 			    !*vcc->local.sas_addr.pub) {
@@ -126,25 +129,25 @@
 		case as_error:
 			clear_bit(ATM_VF_REGIS,&vcc->flags);
 			clear_bit(ATM_VF_READY,&vcc->flags);
-			vcc->sk->sk_err = -msg->reply;
+			sk->sk_err = -msg->reply;
 			clear_bit(ATM_VF_WAITING, &vcc->flags);
 			break;
 		case as_indicate:
 			vcc = *(struct atm_vcc **) &msg->listen_vcc;
 			DPRINTK("as_indicate!!!\n");
-			lock_sock(vcc->sk);
-			if (vcc->sk->sk_ack_backlog ==
-			    vcc->sk->sk_max_ack_backlog) {
+			lock_sock(sk);
+			if (sk->sk_ack_backlog ==
+			    sk->sk_max_ack_backlog) {
 				sigd_enq(NULL,as_reject,vcc,NULL,NULL);
 				dev_kfree_skb(skb);
 				goto as_indicate_complete;
 			}
-			vcc->sk->sk_ack_backlog++;
-			skb_queue_tail(&vcc->sk->sk_receive_queue, skb);
-			DPRINTK("waking vcc->sk->sk_sleep 0x%p\n", vcc->sk->sk_sleep);
-			vcc->sk->sk_state_change(vcc->sk);
+			sk->sk_ack_backlog++;
+			skb_queue_tail(&sk->sk_receive_queue, skb);
+			DPRINTK("waking sk->sk_sleep 0x%p\n", sk->sk_sleep);
+			sk->sk_state_change(sk);
 as_indicate_complete:
-			release_sock(vcc->sk);
+			release_sock(sk);
 			return 0;
 		case as_close:
 			set_bit(ATM_VF_RELEASED,&vcc->flags);
@@ -155,7 +158,7 @@
 			break;
 		case as_addparty:
 		case as_dropparty:
-			vcc->sk->sk_err_soft = msg->reply;	/* < 0 failure, otherwise ep_ref */
+			sk->sk_err_soft = msg->reply;	/* < 0 failure, otherwise ep_ref */
 			clear_bit(ATM_VF_WAITING, &vcc->flags);
 			break;
 		default:
@@ -163,7 +166,7 @@
 			    (int) msg->type);
 			return -EINVAL;
 	}
-	vcc->sk->sk_state_change(vcc->sk);
+	sk->sk_state_change(sk);
 out:
 	dev_kfree_skb(skb);
 	return 0;
@@ -213,7 +216,7 @@
 
 static void purge_vcc(struct atm_vcc *vcc)
 {
-	if (vcc->sk->sk_family == PF_ATMSVC &&
+	if (sk_atm(vcc)->sk_family == PF_ATMSVC &&
 	    !test_bit(ATM_VF_META,&vcc->flags)) {
 		set_bit(ATM_VF_RELEASED,&vcc->flags);
 		vcc_release_async(vcc, -EUNATCH);
@@ -229,9 +232,9 @@
 
 	DPRINTK("sigd_close\n");
 	sigd = NULL;
-	if (skb_peek(&vcc->sk->sk_receive_queue))
+	if (skb_peek(&sk_atm(vcc)->sk_receive_queue))
 		printk(KERN_ERR "sigd_close: closing with requests pending\n");
-	skb_queue_purge(&vcc->sk->sk_receive_queue);
+	skb_queue_purge(&sk_atm(vcc)->sk_receive_queue);
 
 	read_lock(&vcc_sklist_lock);
 	for(i = 0; i < VCC_HTABLE_SIZE; ++i) {
@@ -268,7 +271,7 @@
 	DPRINTK("sigd_attach\n");
 	sigd = vcc;
 	vcc->dev = &sigd_dev;
-	vcc_insert_socket(vcc->sk);
+	vcc_insert_socket(sk_atm(vcc));
 	set_bit(ATM_VF_META,&vcc->flags);
 	set_bit(ATM_VF_READY,&vcc->flags);
 #ifdef WAIT_FOR_DEMON
diff -Nru a/net/atm/svc.c b/net/atm/svc.c
--- a/net/atm/svc.c	2005-03-11 12:51:47 -08:00
+++ b/net/atm/svc.c	2005-03-11 12:51:47 -08:00
@@ -53,20 +53,21 @@
 {
 	DEFINE_WAIT(wait);
 	struct sk_buff *skb;
+	struct sock *sk = sk_atm(vcc);
 
 	DPRINTK("svc_disconnect %p\n",vcc);
 	if (test_bit(ATM_VF_REGIS,&vcc->flags)) {
-		prepare_to_wait(vcc->sk->sk_sleep, &wait, TASK_UNINTERRUPTIBLE);
+		prepare_to_wait(sk->sk_sleep, &wait, TASK_UNINTERRUPTIBLE);
 		sigd_enq(vcc,as_close,NULL,NULL,NULL);
 		while (!test_bit(ATM_VF_RELEASED,&vcc->flags) && sigd) {
 			schedule();
-			prepare_to_wait(vcc->sk->sk_sleep, &wait, TASK_UNINTERRUPTIBLE);
+			prepare_to_wait(sk->sk_sleep, &wait, TASK_UNINTERRUPTIBLE);
 		}
-		finish_wait(vcc->sk->sk_sleep, &wait);
+		finish_wait(sk->sk_sleep, &wait);
 	}
 	/* beware - socket is still in use by atmsigd until the last
 	   as_indicate has been answered */
-	while ((skb = skb_dequeue(&vcc->sk->sk_receive_queue)) != NULL) {
+	while ((skb = skb_dequeue(&sk->sk_receive_queue)) != NULL) {
 		atm_return(vcc, skb->truesize);
 		DPRINTK("LISTEN REL\n");
 		sigd_enq2(NULL,as_reject,vcc,NULL,NULL,&vcc->qos,0);
@@ -318,8 +319,7 @@
 		goto out;
 	}
 	set_bit(ATM_VF_LISTEN,&vcc->flags);
-	vcc->sk->sk_max_ack_backlog = backlog > 0 ? backlog :
-						    ATM_BACKLOG_DEFAULT;
+	sk->sk_max_ack_backlog = backlog > 0 ? backlog : ATM_BACKLOG_DEFAULT;
 	error = -sk->sk_err;
 out:
 	release_sock(sk);
@@ -348,8 +348,8 @@
 	while (1) {
 		DEFINE_WAIT(wait);
 
-		prepare_to_wait(old_vcc->sk->sk_sleep, &wait, TASK_INTERRUPTIBLE);
-		while (!(skb = skb_dequeue(&old_vcc->sk->sk_receive_queue)) &&
+		prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE);
+		while (!(skb = skb_dequeue(&sk->sk_receive_queue)) &&
 		       sigd) {
 			if (test_bit(ATM_VF_RELEASED,&old_vcc->flags)) break;
 			if (test_bit(ATM_VF_CLOSE,&old_vcc->flags)) {
@@ -367,9 +367,9 @@
 				error = -ERESTARTSYS;
 				break;
 			}
-			prepare_to_wait(old_vcc->sk->sk_sleep, &wait, TASK_INTERRUPTIBLE);
+			prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE);
 		}
-		finish_wait(old_vcc->sk->sk_sleep, &wait);
+		finish_wait(sk->sk_sleep, &wait);
 		if (error)
 			goto out;
 		if (!skb) {
@@ -385,7 +385,7 @@
 		error = vcc_connect(newsock, msg->pvc.sap_addr.itf,
 				    msg->pvc.sap_addr.vpi, msg->pvc.sap_addr.vci);
 		dev_kfree_skb(skb);
-		old_vcc->sk->sk_ack_backlog--;
+		sk->sk_ack_backlog--;
 		if (error) {
 			sigd_enq2(NULL,as_reject,old_vcc,NULL,NULL,
 			    &old_vcc->qos,error);
@@ -394,23 +394,23 @@
 		}
 		/* wait should be short, so we ignore the non-blocking flag */
 		set_bit(ATM_VF_WAITING, &new_vcc->flags);
-		prepare_to_wait(new_vcc->sk->sk_sleep, &wait, TASK_UNINTERRUPTIBLE);
+		prepare_to_wait(sk_atm(new_vcc)->sk_sleep, &wait, TASK_UNINTERRUPTIBLE);
 		sigd_enq(new_vcc,as_accept,old_vcc,NULL,NULL);
 		while (test_bit(ATM_VF_WAITING, &new_vcc->flags) && sigd) {
 			release_sock(sk);
 			schedule();
 			lock_sock(sk);
-			prepare_to_wait(new_vcc->sk->sk_sleep, &wait, TASK_UNINTERRUPTIBLE);
+			prepare_to_wait(sk_atm(new_vcc)->sk_sleep, &wait, TASK_UNINTERRUPTIBLE);
 		}
-		finish_wait(new_vcc->sk->sk_sleep, &wait);
+		finish_wait(sk_atm(new_vcc)->sk_sleep, &wait);
 		if (!sigd) {
 			error = -EUNATCH;
 			goto out;
 		}
-		if (!new_vcc->sk->sk_err)
+		if (!sk_atm(new_vcc)->sk_err)
 			break;
-		if (new_vcc->sk->sk_err != ERESTARTSYS) {
-			error = -new_vcc->sk->sk_err;
+		if (sk_atm(new_vcc)->sk_err != ERESTARTSYS) {
+			error = -sk_atm(new_vcc)->sk_err;
 			goto out;
 		}
 	}
@@ -436,19 +436,20 @@
 
 int svc_change_qos(struct atm_vcc *vcc,struct atm_qos *qos)
 {
+	struct sock *sk = sk_atm(vcc);
 	DEFINE_WAIT(wait);
 
 	set_bit(ATM_VF_WAITING, &vcc->flags);
-	prepare_to_wait(vcc->sk->sk_sleep, &wait, TASK_UNINTERRUPTIBLE);
+	prepare_to_wait(sk->sk_sleep, &wait, TASK_UNINTERRUPTIBLE);
 	sigd_enq2(vcc,as_modify,NULL,NULL,&vcc->local,qos,0);
 	while (test_bit(ATM_VF_WAITING, &vcc->flags) &&
 	       !test_bit(ATM_VF_RELEASED, &vcc->flags) && sigd) {
 		schedule();
-		prepare_to_wait(vcc->sk->sk_sleep, &wait, TASK_UNINTERRUPTIBLE);
+		prepare_to_wait(sk->sk_sleep, &wait, TASK_UNINTERRUPTIBLE);
 	}
-	finish_wait(vcc->sk->sk_sleep, &wait);
+	finish_wait(sk->sk_sleep, &wait);
 	if (!sigd) return -EUNATCH;
-	return -vcc->sk->sk_err;
+	return -sk->sk_err;
 }
 
 
@@ -533,28 +534,29 @@
 			int sockaddr_len, int flags)
 {
 	DEFINE_WAIT(wait);
+	struct sock *sk = sock->sk;
 	struct atm_vcc *vcc = ATM_SD(sock);
 	int error;
 
-	lock_sock(vcc->sk);
+	lock_sock(sk);
 	set_bit(ATM_VF_WAITING, &vcc->flags);
-	prepare_to_wait(vcc->sk->sk_sleep, &wait, TASK_INTERRUPTIBLE);
+	prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE);
 	sigd_enq(vcc, as_addparty, NULL, NULL,
 	         (struct sockaddr_atmsvc *) sockaddr);
 	if (flags & O_NONBLOCK) {
-		finish_wait(vcc->sk->sk_sleep, &wait);
+		finish_wait(sk->sk_sleep, &wait);
 		error = -EINPROGRESS;
 		goto out;
 	}
 	DPRINTK("svc_addparty added wait queue\n");
 	while (test_bit(ATM_VF_WAITING, &vcc->flags) && sigd) {
 		schedule();
-		prepare_to_wait(vcc->sk->sk_sleep, &wait, TASK_INTERRUPTIBLE);
+		prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE);
 	}
-	finish_wait(vcc->sk->sk_sleep, &wait);
-	error = xchg(&vcc->sk->sk_err_soft, 0);
+	finish_wait(sk->sk_sleep, &wait);
+	error = xchg(&sk->sk_err_soft, 0);
 out:
-	release_sock(vcc->sk);
+	release_sock(sk);
 	return error;
 }
 
@@ -562,25 +564,26 @@
 static int svc_dropparty(struct socket *sock, int ep_ref)
 {
 	DEFINE_WAIT(wait);
+	struct sock *sk = sock->sk;
 	struct atm_vcc *vcc = ATM_SD(sock);
 	int error;
 
-	lock_sock(vcc->sk);
+	lock_sock(sk);
 	set_bit(ATM_VF_WAITING, &vcc->flags);
-	prepare_to_wait(vcc->sk->sk_sleep, &wait, TASK_INTERRUPTIBLE);
+	prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE);
 	sigd_enq2(vcc, as_dropparty, NULL, NULL, NULL, NULL, ep_ref);
 	while (test_bit(ATM_VF_WAITING, &vcc->flags) && sigd) {
 		schedule();
-		prepare_to_wait(vcc->sk->sk_sleep, &wait, TASK_INTERRUPTIBLE);
+		prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE);
 	}
-	finish_wait(vcc->sk->sk_sleep, &wait);
+	finish_wait(sk->sk_sleep, &wait);
 	if (!sigd) {
 		error = -EUNATCH;
 		goto out;
 	}
-	error = xchg(&vcc->sk->sk_err_soft, 0);
+	error = xchg(&sk->sk_err_soft, 0);
 out:
-	release_sock(vcc->sk);
+	release_sock(sk);
 	return error;
 }
 
diff -Nru a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
--- a/net/bluetooth/hci_conn.c	2005-03-11 12:51:52 -08:00
+++ b/net/bluetooth/hci_conn.c	2005-03-11 12:51:52 -08:00
@@ -348,6 +348,24 @@
 }
 EXPORT_SYMBOL(hci_conn_change_link_key);
 
+/* Switch role */
+int hci_conn_switch_role(struct hci_conn *conn, uint8_t role)
+{
+	BT_DBG("conn %p", conn);
+
+	if (!role && conn->link_mode & HCI_LM_MASTER)
+		return 1;
+
+	if (!test_and_set_bit(HCI_CONN_RSWITCH_PEND, &conn->pend)) {
+		struct hci_cp_switch_role cp;
+		bacpy(&cp.bdaddr, &conn->dst);
+		cp.role = role;
+		hci_send_cmd(conn->hdev, OGF_LINK_POLICY, OCF_SWITCH_ROLE, sizeof(cp), &cp);
+	}
+	return 0;
+}
+EXPORT_SYMBOL(hci_conn_switch_role);
+
 /* Drop all connection on the device */
 void hci_conn_hash_flush(struct hci_dev *hdev)
 {
diff -Nru a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
--- a/net/bluetooth/hci_event.c	2005-03-11 12:51:40 -08:00
+++ b/net/bluetooth/hci_event.c	2005-03-11 12:51:40 -08:00
@@ -718,17 +718,20 @@
 
 	BT_DBG("%s status %d", hdev->name, ev->status);
 
-	if (ev->status)
-		return;
-
 	hci_dev_lock(hdev);
 
 	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
 	if (conn) {
-		if (ev->role)
-			conn->link_mode &= ~HCI_LM_MASTER;
-		else
-			conn->link_mode |= HCI_LM_MASTER;
+		if (!ev->status) {
+			if (ev->role)
+				conn->link_mode &= ~HCI_LM_MASTER;
+			else
+				conn->link_mode |= HCI_LM_MASTER;
+		}
+
+		clear_bit(HCI_CONN_RSWITCH_PEND, &conn->pend);
+
+		hci_role_switch_cfm(conn, ev->status, ev->role);
 	}
 
 	hci_dev_unlock(hdev);
@@ -749,6 +752,7 @@
 	if (conn) {
 		if (!ev->status)
 			conn->link_mode |= HCI_LM_AUTH;
+
 		clear_bit(HCI_CONN_AUTH_PEND, &conn->pend);
 
 		hci_auth_cfm(conn, ev->status);
@@ -790,6 +794,7 @@
 			else
 				conn->link_mode &= ~HCI_LM_ENCRYPT;
 		}
+
 		clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend);
 
 		hci_encrypt_cfm(conn, ev->status, ev->encrypt);
@@ -801,6 +806,25 @@
 /* Change Connection Link Key Complete */
 static inline void hci_change_conn_link_key_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
 {
+	struct hci_ev_change_conn_link_key_complete *ev = (struct hci_ev_change_conn_link_key_complete *) skb->data;
+	struct hci_conn *conn = NULL;
+	__u16 handle = __le16_to_cpu(ev->handle);
+
+	BT_DBG("%s status %d", hdev->name, ev->status);
+
+	hci_dev_lock(hdev);
+
+	conn = hci_conn_hash_lookup_handle(hdev, handle);
+	if (conn) {
+		if (!ev->status)
+			conn->link_mode |= HCI_LM_SECURE;
+
+		clear_bit(HCI_CONN_AUTH_PEND, &conn->pend);
+
+		hci_key_change_cfm(conn, ev->status);
+	}
+
+	hci_dev_unlock(hdev);
 }
 
 /* Pin Code Request*/
diff -Nru a/net/bluetooth/hci_sysfs.c b/net/bluetooth/hci_sysfs.c
--- a/net/bluetooth/hci_sysfs.c	2005-03-11 12:51:48 -08:00
+++ b/net/bluetooth/hci_sysfs.c	2005-03-11 12:51:48 -08:00
@@ -55,7 +55,7 @@
 				batostr(&bdaddr),
 				data->pscan_rep_mode, data->pscan_period_mode, data->pscan_mode,
 				data->dev_class[2], data->dev_class[1], data->dev_class[0],
-				data->clock_offset, data->rssi, e->timestamp);
+				__le16_to_cpu(data->clock_offset), data->rssi, e->timestamp);
 	}
 
 	hci_dev_unlock_bh(hdev);
diff -Nru a/net/bridge/br.c b/net/bridge/br.c
--- a/net/bridge/br.c	2005-03-11 12:51:41 -08:00
+++ b/net/bridge/br.c	2005-03-11 12:51:41 -08:00
@@ -16,7 +16,6 @@
 #include <linux/config.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/miscdevice.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/init.h>
diff -Nru a/net/bridge/br_device.c b/net/bridge/br_device.c
--- a/net/bridge/br_device.c	2005-03-11 12:51:40 -08:00
+++ b/net/bridge/br_device.c	2005-03-11 12:51:40 -08:00
@@ -83,11 +83,6 @@
 	return 0;
 }
 
-static int br_dev_accept_fastpath(struct net_device *dev, struct dst_entry *dst)
-{
-	return -1;
-}
-
 void br_dev_setup(struct net_device *dev)
 {
 	memset(dev->dev_addr, 0, ETH_ALEN);
@@ -103,7 +98,6 @@
 	dev->destructor = free_netdev;
 	SET_MODULE_OWNER(dev);
 	dev->stop = br_dev_stop;
-	dev->accept_fastpath = br_dev_accept_fastpath;
 	dev->tx_queue_len = 0;
 	dev->set_mac_address = NULL;
 	dev->priv_flags = IFF_EBRIDGE;
diff -Nru a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c
--- a/net/bridge/br_fdb.c	2005-03-11 12:51:41 -08:00
+++ b/net/bridge/br_fdb.c	2005-03-11 12:51:41 -08:00
@@ -19,12 +19,13 @@
 #include <linux/times.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
+#include <linux/jhash.h>
 #include <asm/atomic.h>
 #include "br_private.h"
 
 static kmem_cache_t *br_fdb_cache;
 static int fdb_insert(struct net_bridge *br, struct net_bridge_port *source,
-		      const unsigned char *addr, int is_local);
+		      const unsigned char *addr);
 
 void __init br_fdb_init(void)
 {
@@ -57,26 +58,12 @@
 
 static __inline__ int br_mac_hash(const unsigned char *mac)
 {
-	unsigned long x;
-
-	x = mac[0];
-	x = (x << 2) ^ mac[1];
-	x = (x << 2) ^ mac[2];
-	x = (x << 2) ^ mac[3];
-	x = (x << 2) ^ mac[4];
-	x = (x << 2) ^ mac[5];
-
-	x ^= x >> 8;
-
-	return x & (BR_HASH_SIZE - 1);
+	return jhash(mac, ETH_ALEN, 0) & (BR_HASH_SIZE - 1);
 }
 
 static __inline__ void fdb_delete(struct net_bridge_fdb_entry *f)
 {
 	hlist_del_rcu(&f->hlist);
-	if (!f->is_static)
-		list_del(&f->u.age_list);
-
 	br_fdb_put(f);
 }
 
@@ -114,8 +101,7 @@
 	}
  insert:
 	/* insert new address,  may fail if invalid address or dup. */
-	fdb_insert(br, p, newaddr, 1);
-
+	fdb_insert(br, p, newaddr);
 
 	spin_unlock_bh(&br->hash_lock);
 }
@@ -123,30 +109,23 @@
 void br_fdb_cleanup(unsigned long _data)
 {
 	struct net_bridge *br = (struct net_bridge *)_data;
-	struct list_head *l, *n;
-	unsigned long delay;
+	unsigned long delay = hold_time(br);
+	int i;
 
 	spin_lock_bh(&br->hash_lock);
-	delay = hold_time(br);
-
-	list_for_each_safe(l, n, &br->age_list) {
+	for (i = 0; i < BR_HASH_SIZE; i++) {
 		struct net_bridge_fdb_entry *f;
-		unsigned long expires;
-
-		f = list_entry(l, struct net_bridge_fdb_entry, u.age_list);
-		expires = f->ageing_timer + delay;
+		struct hlist_node *h, *n;
 
-		if (time_before_eq(expires, jiffies)) {
-			WARN_ON(f->is_static);
-			pr_debug("expire age %lu jiffies %lu\n",
-				 f->ageing_timer, jiffies);
-			fdb_delete(f);
-		} else {
-			mod_timer(&br->gc_timer, expires);
-			break;
+		hlist_for_each_entry_safe(f, h, n, &br->hash[i], hlist) {
+			if (!f->is_static && 
+			    time_before_eq(f->ageing_timer + delay, jiffies)) 
+				fdb_delete(f);
 		}
 	}
 	spin_unlock_bh(&br->hash_lock);
+
+	mod_timer(&br->gc_timer, jiffies + HZ/10);
 }
 
 void br_fdb_delete_by_port(struct net_bridge *br, struct net_bridge_port *p)
@@ -222,7 +201,7 @@
 static void fdb_rcu_free(struct rcu_head *head)
 {
 	struct net_bridge_fdb_entry *ent
-		= container_of(head, struct net_bridge_fdb_entry, u.rcu);
+		= container_of(head, struct net_bridge_fdb_entry, rcu);
 	kmem_cache_free(br_fdb_cache, ent);
 }
 
@@ -230,7 +209,7 @@
 void br_fdb_put(struct net_bridge_fdb_entry *ent)
 {
 	if (atomic_dec_and_test(&ent->use_count))
-		call_rcu(&ent->u.rcu, fdb_rcu_free);
+		call_rcu(&ent->rcu, fdb_rcu_free);
 }
 
 /*
@@ -278,80 +257,108 @@
 	return num;
 }
 
-static int fdb_insert(struct net_bridge *br, struct net_bridge_port *source,
-		  const unsigned char *addr, int is_local)
+static inline struct net_bridge_fdb_entry *fdb_find(struct hlist_head *head,
+						    const unsigned char *addr)
 {
 	struct hlist_node *h;
 	struct net_bridge_fdb_entry *fdb;
-	int hash = br_mac_hash(addr);
-
-	if (!is_valid_ether_addr(addr))
-		return -EADDRNOTAVAIL;
-
-	hlist_for_each_entry(fdb, h, &br->hash[hash], hlist) {
-		if (!memcmp(fdb->addr.addr, addr, ETH_ALEN)) {
-			/* attempt to update an entry for a local interface */
-			if (fdb->is_local) {
-				/* it is okay to have multiple ports with same 
-				 * address, just don't allow to be spoofed.
-				 */
-				if (is_local) 
-					return 0;
-
-				if (net_ratelimit()) 
-					printk(KERN_WARNING "%s: received packet with "
-					       " own address as source address\n",
-					       source->dev->name);
-				return -EEXIST;
-			}
 
-			if (is_local) {
-				printk(KERN_WARNING "%s adding interface with same address "
-				       "as a received packet\n",
-				       source->dev->name);
-				goto update;
-			}
+	hlist_for_each_entry_rcu(fdb, h, head, hlist) {
+		if (!memcmp(fdb->addr.addr, addr, ETH_ALEN))
+			return fdb;
+	}
+	return NULL;
+}
 
-			if (fdb->is_static)
-				return 0;
+static struct net_bridge_fdb_entry *fdb_create(struct hlist_head *head,
+					       struct net_bridge_port *source,
+					       const unsigned char *addr, 
+					       int is_local)
+{
+	struct net_bridge_fdb_entry *fdb;
 
-			/* move to end of age list */
-			list_del(&fdb->u.age_list);
-			goto update;
-		}
+	fdb = kmem_cache_alloc(br_fdb_cache, GFP_ATOMIC);
+	if (fdb) {
+		memcpy(fdb->addr.addr, addr, ETH_ALEN);
+		atomic_set(&fdb->use_count, 1);
+		hlist_add_head_rcu(&fdb->hlist, head);
+
+		fdb->dst = source;
+		fdb->is_local = is_local;
+		fdb->is_static = is_local;
+		fdb->ageing_timer = jiffies;
 	}
+	return fdb;
+}
 
-	fdb = kmem_cache_alloc(br_fdb_cache, GFP_ATOMIC);
-	if (!fdb)
-		return ENOMEM;
+static int fdb_insert(struct net_bridge *br, struct net_bridge_port *source,
+		  const unsigned char *addr)
+{
+	struct hlist_head *head = &br->hash[br_mac_hash(addr)];
+	struct net_bridge_fdb_entry *fdb;
 
-	memcpy(fdb->addr.addr, addr, ETH_ALEN);
-	atomic_set(&fdb->use_count, 1);
-	hlist_add_head_rcu(&fdb->hlist, &br->hash[hash]);
-
-	if (!timer_pending(&br->gc_timer)) {
-		br->gc_timer.expires = jiffies + hold_time(br);
-		add_timer(&br->gc_timer);
-	}
+	if (!is_valid_ether_addr(addr))
+		return -EINVAL;
 
- update:
-	fdb->dst = source;
-	fdb->is_local = is_local;
-	fdb->is_static = is_local;
-	fdb->ageing_timer = jiffies;
-	if (!is_local) 
-		list_add_tail(&fdb->u.age_list, &br->age_list);
+	fdb = fdb_find(head, addr);
+	if (fdb) {
+		/* it is okay to have multiple ports with same 
+		 * address, just use the first one.
+		 */
+		if (fdb->is_local) 
+			return 0;
+
+		printk(KERN_WARNING "%s adding interface with same address "
+		       "as a received packet\n",
+		       source->dev->name);
+		fdb_delete(fdb);
+ 	}
+
+	if (!fdb_create(head, source, addr, 1))
+		return -ENOMEM;
 
 	return 0;
 }
 
 int br_fdb_insert(struct net_bridge *br, struct net_bridge_port *source,
-		  const unsigned char *addr, int is_local)
+		  const unsigned char *addr)
 {
 	int ret;
 
 	spin_lock_bh(&br->hash_lock);
-	ret = fdb_insert(br, source, addr, is_local);
+	ret = fdb_insert(br, source, addr);
 	spin_unlock_bh(&br->hash_lock);
 	return ret;
+}
+
+void br_fdb_update(struct net_bridge *br, struct net_bridge_port *source,
+		   const unsigned char *addr)
+{
+	struct hlist_head *head = &br->hash[br_mac_hash(addr)];
+	struct net_bridge_fdb_entry *fdb;
+
+	rcu_read_lock();
+	fdb = fdb_find(head, addr);
+	if (likely(fdb)) {
+		/* attempt to update an entry for a local interface */
+		if (unlikely(fdb->is_local)) {
+			if (net_ratelimit()) 
+				printk(KERN_WARNING "%s: received packet with "
+				       " own address as source address\n",
+				       source->dev->name);
+		} else {
+			/* fastpath: update of existing entry */
+			fdb->dst = source;
+			fdb->ageing_timer = jiffies;
+		}
+	} else {
+		spin_lock_bh(&br->hash_lock);
+		if (!fdb_find(head, addr))
+			fdb_create(head, source, addr, 0);
+		/* else  we lose race and someone else inserts
+		 * it first, don't bother updating
+		 */
+		spin_unlock_bh(&br->hash_lock);
+	}
+	rcu_read_unlock();
 }
diff -Nru a/net/bridge/br_if.c b/net/bridge/br_if.c
--- a/net/bridge/br_if.c	2005-03-11 12:51:52 -08:00
+++ b/net/bridge/br_if.c	2005-03-11 12:51:52 -08:00
@@ -332,7 +332,7 @@
 	if (IS_ERR(p = new_nbp(br, dev, br_initial_port_cost(dev))))
 		return PTR_ERR(p);
 
- 	if ((err = br_fdb_insert(br, p, dev->dev_addr, 1)))
+ 	if ((err = br_fdb_insert(br, p, dev->dev_addr)))
 		destroy_nbp(p);
  
 	else if ((err = br_sysfs_addif(p)))
diff -Nru a/net/bridge/br_input.c b/net/bridge/br_input.c
--- a/net/bridge/br_input.c	2005-03-11 12:51:42 -08:00
+++ b/net/bridge/br_input.c	2005-03-11 12:51:42 -08:00
@@ -105,12 +105,12 @@
 	if (p->state == BR_STATE_DISABLED)
 		goto err;
 
-	if (eth_hdr(skb)->h_source[0] & 1)
+	if (!is_valid_ether_addr(eth_hdr(skb)->h_source))
 		goto err;
 
 	if (p->state == BR_STATE_LEARNING ||
 	    p->state == BR_STATE_FORWARDING)
-		br_fdb_insert(p->br, p, eth_hdr(skb)->h_source, 0);
+		br_fdb_update(p->br, p, eth_hdr(skb)->h_source);
 
 	if (p->br->stp_enabled &&
 	    !memcmp(dest, bridge_ula, 5) &&
diff -Nru a/net/bridge/br_private.h b/net/bridge/br_private.h
--- a/net/bridge/br_private.h	2005-03-11 12:51:41 -08:00
+++ b/net/bridge/br_private.h	2005-03-11 12:51:41 -08:00
@@ -46,10 +46,8 @@
 {
 	struct hlist_node		hlist;
 	struct net_bridge_port		*dst;
-	union {
-		struct list_head	age_list;
-		struct rcu_head		rcu;
-	} u;
+
+	struct rcu_head			rcu;
 	atomic_t			use_count;
 	unsigned long			ageing_timer;
 	mac_addr			addr;
@@ -148,8 +146,10 @@
 			  unsigned long count, unsigned long off);
 extern int br_fdb_insert(struct net_bridge *br,
 			 struct net_bridge_port *source,
-			 const unsigned char *addr,
-			 int is_local);
+			 const unsigned char *addr);
+extern void br_fdb_update(struct net_bridge *br,
+			  struct net_bridge_port *source,
+			  const unsigned char *addr);
 
 /* br_forward.c */
 extern void br_deliver(const struct net_bridge_port *to,
diff -Nru a/net/bridge/br_stp_if.c b/net/bridge/br_stp_if.c
--- a/net/bridge/br_stp_if.c	2005-03-11 12:51:51 -08:00
+++ b/net/bridge/br_stp_if.c	2005-03-11 12:51:51 -08:00
@@ -49,6 +49,8 @@
 
 	spin_lock_bh(&br->lock);
 	mod_timer(&br->hello_timer, jiffies + br->hello_time);
+	mod_timer(&br->gc_timer, jiffies + HZ/10);
+	
 	br_config_bpdu_generation(br);
 
 	list_for_each_entry(p, &br->port_list, list) {
@@ -78,6 +80,7 @@
 	del_timer_sync(&br->hello_timer);
 	del_timer_sync(&br->topology_change_timer);
 	del_timer_sync(&br->tcn_timer);
+	del_timer_sync(&br->gc_timer);
 }
 
 /* called under bridge lock */
diff -Nru a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c
--- a/net/bridge/netfilter/ebtables.c	2005-03-11 12:51:42 -08:00
+++ b/net/bridge/netfilter/ebtables.c	2005-03-11 12:51:42 -08:00
@@ -822,10 +822,10 @@
 		/* this will get free'd in do_replace()/ebt_register_table()
 		   if an error occurs */
 		newinfo->chainstack = (struct ebt_chainstack **)
-		   vmalloc(NR_CPUS * sizeof(struct ebt_chainstack));
+		   vmalloc(num_possible_cpus() * sizeof(struct ebt_chainstack));
 		if (!newinfo->chainstack)
 			return -ENOMEM;
-		for (i = 0; i < NR_CPUS; i++) {
+		for (i = 0; i < num_possible_cpus(); i++) {
 			newinfo->chainstack[i] =
 			   vmalloc(udc_cnt * sizeof(struct ebt_chainstack));
 			if (!newinfo->chainstack[i]) {
@@ -898,7 +898,7 @@
 	memcpy(counters, oldcounters,
 	   sizeof(struct ebt_counter) * nentries);
 	/* add other counters to those of cpu 0 */
-	for (cpu = 1; cpu < NR_CPUS; cpu++) {
+	for (cpu = 1; cpu < num_possible_cpus(); cpu++) {
 		counter_base = COUNTER_BASE(oldcounters, nentries, cpu);
 		for (i = 0; i < nentries; i++) {
 			counters[i].pcnt += counter_base[i].pcnt;
@@ -930,7 +930,7 @@
 		BUGPRINT("Entries_size never zero\n");
 		return -EINVAL;
 	}
-	countersize = COUNTER_OFFSET(tmp.nentries) * NR_CPUS;
+	countersize = COUNTER_OFFSET(tmp.nentries) * num_possible_cpus();
 	newinfo = (struct ebt_table_info *)
 	   vmalloc(sizeof(struct ebt_table_info) + countersize);
 	if (!newinfo)
@@ -1023,7 +1023,7 @@
 
 	vfree(table->entries);
 	if (table->chainstack) {
-		for (i = 0; i < NR_CPUS; i++)
+		for (i = 0; i < num_possible_cpus(); i++)
 			vfree(table->chainstack[i]);
 		vfree(table->chainstack);
 	}
@@ -1043,7 +1043,7 @@
 		vfree(counterstmp);
 	/* can be initialized in translate_table() */
 	if (newinfo->chainstack) {
-		for (i = 0; i < NR_CPUS; i++)
+		for (i = 0; i < num_possible_cpus(); i++)
 			vfree(newinfo->chainstack[i]);
 		vfree(newinfo->chainstack);
 	}
@@ -1137,7 +1137,7 @@
 		return -EINVAL;
 	}
 
-	countersize = COUNTER_OFFSET(table->table->nentries) * NR_CPUS;
+	countersize = COUNTER_OFFSET(table->table->nentries) * num_possible_cpus();
 	newinfo = (struct ebt_table_info *)
 	   vmalloc(sizeof(struct ebt_table_info) + countersize);
 	ret = -ENOMEM;
@@ -1191,7 +1191,7 @@
 	up(&ebt_mutex);
 free_chainstack:
 	if (newinfo->chainstack) {
-		for (i = 0; i < NR_CPUS; i++)
+		for (i = 0; i < num_possible_cpus(); i++)
 			vfree(newinfo->chainstack[i]);
 		vfree(newinfo->chainstack);
 	}
@@ -1215,7 +1215,7 @@
 	if (table->private->entries)
 		vfree(table->private->entries);
 	if (table->private->chainstack) {
-		for (i = 0; i < NR_CPUS; i++)
+		for (i = 0; i < num_possible_cpus(); i++)
 			vfree(table->private->chainstack[i]);
 		vfree(table->private->chainstack);
 	}
diff -Nru a/net/core/dev.c b/net/core/dev.c
--- a/net/core/dev.c	2005-03-11 12:51:46 -08:00
+++ b/net/core/dev.c	2005-03-11 12:51:46 -08:00
@@ -2300,6 +2300,21 @@
 	return err;
 }
 
+int dev_set_mac_address(struct net_device *dev, struct sockaddr *sa)
+{
+	int err;
+
+	if (!dev->set_mac_address)
+		return -EOPNOTSUPP;
+	if (sa->sa_family != dev->type)
+		return -EINVAL;
+	if (!netif_device_present(dev))
+		return -ENODEV;
+	err = dev->set_mac_address(dev, sa);
+	if (!err)
+		notifier_call_chain(&netdev_chain, NETDEV_CHANGEADDR, dev);
+	return err;
+}
 
 /*
  *	Perform the SIOCxIFxxx calls.
@@ -2346,17 +2361,7 @@
 			return 0;
 
 		case SIOCSIFHWADDR:
-			if (!dev->set_mac_address)
-				return -EOPNOTSUPP;
-			if (ifr->ifr_hwaddr.sa_family != dev->type)
-				return -EINVAL;
-			if (!netif_device_present(dev))
-				return -ENODEV;
-			err = dev->set_mac_address(dev, &ifr->ifr_hwaddr);
-			if (!err)
-				notifier_call_chain(&netdev_chain,
-						    NETDEV_CHANGEADDR, dev);
-			return err;
+			return dev_set_mac_address(dev, &ifr->ifr_hwaddr);
 
 		case SIOCSIFHWBROADCAST:
 			if (ifr->ifr_hwaddr.sa_family != dev->type)
@@ -3322,6 +3327,7 @@
 EXPORT_SYMBOL(dev_set_promiscuity);
 EXPORT_SYMBOL(dev_change_flags);
 EXPORT_SYMBOL(dev_set_mtu);
+EXPORT_SYMBOL(dev_set_mac_address);
 EXPORT_SYMBOL(free_netdev);
 EXPORT_SYMBOL(netdev_boot_setup_check);
 EXPORT_SYMBOL(netdev_set_master);
diff -Nru a/net/core/neighbour.c b/net/core/neighbour.c
--- a/net/core/neighbour.c	2005-03-11 12:51:41 -08:00
+++ b/net/core/neighbour.c	2005-03-11 12:51:41 -08:00
@@ -1430,6 +1430,7 @@
 
 	read_lock(&neigh_tbl_lock);
 	for (tbl = neigh_tables; tbl; tbl = tbl->next) {
+		struct rtattr *dst_attr = nda[NDA_DST - 1];
 		struct neighbour *n;
 
 		if (tbl->family != ndm->ndm_family)
@@ -1437,20 +1438,18 @@
 		read_unlock(&neigh_tbl_lock);
 
 		err = -EINVAL;
-		if (!nda[NDA_DST - 1] ||
-		    nda[NDA_DST - 1]->rta_len != RTA_LENGTH(tbl->key_len))
+		if (!dst_attr || RTA_PAYLOAD(dst_attr) < tbl->key_len)
 			goto out_dev_put;
 
 		if (ndm->ndm_flags & NTF_PROXY) {
-			err = pneigh_delete(tbl,
-					    RTA_DATA(nda[NDA_DST - 1]), dev);
+			err = pneigh_delete(tbl, RTA_DATA(dst_attr), dev);
 			goto out_dev_put;
 		}
 
 		if (!dev)
 			goto out;
 
-		n = neigh_lookup(tbl, RTA_DATA(nda[NDA_DST - 1]), dev);
+		n = neigh_lookup(tbl, RTA_DATA(dst_attr), dev);
 		if (n) {
 			err = neigh_update(n, NULL, NUD_FAILED, 
 					   NEIGH_UPDATE_F_OVERRIDE|
@@ -1482,6 +1481,8 @@
 
 	read_lock(&neigh_tbl_lock);
 	for (tbl = neigh_tables; tbl; tbl = tbl->next) {
+		struct rtattr *lladdr_attr = nda[NDA_LLADDR - 1];
+		struct rtattr *dst_attr = nda[NDA_DST - 1];
 		int override = 1;
 		struct neighbour *n;
 
@@ -1490,48 +1491,49 @@
 		read_unlock(&neigh_tbl_lock);
 
 		err = -EINVAL;
-		if (!nda[NDA_DST - 1] ||
-		    nda[NDA_DST - 1]->rta_len != RTA_LENGTH(tbl->key_len))
+		if (!dst_attr || RTA_PAYLOAD(dst_attr) < tbl->key_len)
 			goto out_dev_put;
+
 		if (ndm->ndm_flags & NTF_PROXY) {
 			err = -ENOBUFS;
-			if (pneigh_lookup(tbl,
-					  RTA_DATA(nda[NDA_DST - 1]), dev, 1))
+			if (pneigh_lookup(tbl, RTA_DATA(dst_attr), dev, 1))
 				err = 0;
 			goto out_dev_put;
 		}
+
 		err = -EINVAL;
 		if (!dev)
 			goto out;
-		if (nda[NDA_LLADDR - 1] &&
-		    nda[NDA_LLADDR - 1]->rta_len != RTA_LENGTH(dev->addr_len))
+		if (lladdr_attr && RTA_PAYLOAD(lladdr_attr) < dev->addr_len)
 			goto out_dev_put;
-		err = 0;
-		n = neigh_lookup(tbl, RTA_DATA(nda[NDA_DST - 1]), dev);
+	
+		n = neigh_lookup(tbl, RTA_DATA(dst_attr), dev);
 		if (n) {
-			if (nlh->nlmsg_flags & NLM_F_EXCL)
+			if (nlh->nlmsg_flags & NLM_F_EXCL) {
 				err = -EEXIST;
+				neigh_release(n);
+				goto out_dev_put;
+			}
+			
 			override = nlh->nlmsg_flags & NLM_F_REPLACE;
-		} else if (!(nlh->nlmsg_flags & NLM_F_CREATE))
+		} else if (!(nlh->nlmsg_flags & NLM_F_CREATE)) {
 			err = -ENOENT;
-		else {
-			n = __neigh_lookup_errno(tbl, RTA_DATA(nda[NDA_DST - 1]),
-						 dev);
+			goto out_dev_put;
+		} else {
+			n = __neigh_lookup_errno(tbl, RTA_DATA(dst_attr), dev);
 			if (IS_ERR(n)) {
 				err = PTR_ERR(n);
-				n = NULL;
+				goto out_dev_put;
 			}
 		}
-		if (!err) {
-			err = neigh_update(n, nda[NDA_LLADDR - 1] ?
-						RTA_DATA(nda[NDA_LLADDR - 1]) :
-						NULL,
-					   ndm->ndm_state,
-					   (override ? NEIGH_UPDATE_F_OVERRIDE : 0) |
-					   NEIGH_UPDATE_F_ADMIN);
-		}
-		if (n)
-			neigh_release(n);
+
+		err = neigh_update(n,
+				   lladdr_attr ? RTA_DATA(lladdr_attr) : NULL,
+				   ndm->ndm_state,
+				   (override ? NEIGH_UPDATE_F_OVERRIDE : 0) |
+				   NEIGH_UPDATE_F_ADMIN);
+
+		neigh_release(n);
 		goto out_dev_put;
 	}
 
@@ -1552,6 +1554,7 @@
 	unsigned char *b = skb->tail;
 	struct nda_cacheinfo ci;
 	int locked = 0;
+	u32 probes;
 	struct nlmsghdr *nlh = NLMSG_PUT(skb, pid, seq, event,
 					 sizeof(struct ndmsg));
 	struct ndmsg *ndm = NLMSG_DATA(nlh);
@@ -1571,9 +1574,11 @@
 	ci.ndm_confirmed = now - n->confirmed;
 	ci.ndm_updated	 = now - n->updated;
 	ci.ndm_refcnt	 = atomic_read(&n->refcnt) - 1;
+	probes = atomic_read(&n->probes);
 	read_unlock_bh(&n->lock);
 	locked		 = 0;
 	RTA_PUT(skb, NDA_CACHEINFO, sizeof(ci), &ci);
+	RTA_PUT(skb, NDA_PROBES, sizeof(probes), &probes);
 	nlh->nlmsg_len	 = skb->tail - b;
 	return skb->len;
 
@@ -2047,7 +2052,7 @@
 
 static struct neigh_sysctl_table {
 	struct ctl_table_header *sysctl_header;
-	ctl_table		neigh_vars[17];
+	ctl_table		neigh_vars[__NET_NEIGH_MAX];
 	ctl_table		neigh_dev[2];
 	ctl_table		neigh_neigh_dir[2];
 	ctl_table		neigh_proto_dir[2];
@@ -2170,6 +2175,22 @@
 			.mode		= 0644,
 			.proc_handler	= &proc_dointvec,
 		},
+		{
+			.ctl_name	= NET_NEIGH_RETRANS_TIME_MS,
+			.procname	= "retrans_time_ms",
+			.maxlen		= sizeof(int),
+			.mode		= 0644,
+			.proc_handler	= &proc_dointvec_ms_jiffies,
+			.strategy	= &sysctl_ms_jiffies,
+		},
+		{
+			.ctl_name	= NET_NEIGH_REACHABLE_TIME_MS,
+			.procname	= "base_reachable_time_ms",
+			.maxlen		= sizeof(int),
+			.mode		= 0644,
+			.proc_handler	= &proc_dointvec_ms_jiffies,
+			.strategy	= &sysctl_ms_jiffies,
+		},
 	},
 	.neigh_dev = {
 		{
@@ -2200,7 +2221,7 @@
 
 int neigh_sysctl_register(struct net_device *dev, struct neigh_parms *p,
 			  int p_id, int pdev_id, char *p_name, 
-			  proc_handler *handler)
+			  proc_handler *handler, ctl_handler *strategy)
 {
 	struct neigh_sysctl_table *t = kmalloc(sizeof(*t), GFP_KERNEL);
 	const char *dev_name_source = NULL;
@@ -2214,10 +2235,6 @@
 	t->neigh_vars[1].data  = &p->ucast_probes;
 	t->neigh_vars[2].data  = &p->app_probes;
 	t->neigh_vars[3].data  = &p->retrans_time;
-	if (handler) {
-		t->neigh_vars[3].proc_handler = handler;
-		t->neigh_vars[3].extra1 = dev;
-	}
 	t->neigh_vars[4].data  = &p->base_reachable_time;
 	t->neigh_vars[5].data  = &p->delay_probe_time;
 	t->neigh_vars[6].data  = &p->gc_staletime;
@@ -2227,16 +2244,41 @@
 	t->neigh_vars[10].data = &p->proxy_delay;
 	t->neigh_vars[11].data = &p->locktime;
 
- 	dev_name_source = t->neigh_dev[0].procname;
 	if (dev) {
 		dev_name_source = dev->name;
 		t->neigh_dev[0].ctl_name = dev->ifindex;
-		memset(&t->neigh_vars[12], 0, sizeof(ctl_table));
+		t->neigh_vars[12].procname = NULL;
+		t->neigh_vars[13].procname = NULL;
+		t->neigh_vars[14].procname = NULL;
+		t->neigh_vars[15].procname = NULL;
 	} else {
+ 		dev_name_source = t->neigh_dev[0].procname;
 		t->neigh_vars[12].data = (int *)(p + 1);
 		t->neigh_vars[13].data = (int *)(p + 1) + 1;
 		t->neigh_vars[14].data = (int *)(p + 1) + 2;
 		t->neigh_vars[15].data = (int *)(p + 1) + 3;
+	}
+
+	t->neigh_vars[16].data  = &p->retrans_time;
+	t->neigh_vars[17].data  = &p->base_reachable_time;
+
+	if (handler || strategy) {
+		/* RetransTime */
+		t->neigh_vars[3].proc_handler = handler;
+		t->neigh_vars[3].strategy = strategy;
+		t->neigh_vars[3].extra1 = dev;
+		/* ReachableTime */
+		t->neigh_vars[4].proc_handler = handler;
+		t->neigh_vars[4].strategy = strategy;
+		t->neigh_vars[4].extra1 = dev;
+		/* RetransTime (in milliseconds)*/
+		t->neigh_vars[16].proc_handler = handler;
+		t->neigh_vars[16].strategy = strategy;
+		t->neigh_vars[16].extra1 = dev;
+		/* ReachableTime (in milliseconds) */
+		t->neigh_vars[17].proc_handler = handler;
+		t->neigh_vars[17].strategy = strategy;
+		t->neigh_vars[17].extra1 = dev;
 	}
 
 	dev_name = net_sysctl_strdup(dev_name_source);
diff -Nru a/net/core/netfilter.c b/net/core/netfilter.c
--- a/net/core/netfilter.c	2005-03-11 12:51:46 -08:00
+++ b/net/core/netfilter.c	2005-03-11 12:51:46 -08:00
@@ -678,7 +678,6 @@
 int skb_ip_make_writable(struct sk_buff **pskb, unsigned int writable_len)
 {
 	struct sk_buff *nskb;
-	unsigned int iplen;
 
 	if (writable_len > (*pskb)->len)
 		return 0;
@@ -687,35 +686,7 @@
 	if (skb_shared(*pskb) || skb_cloned(*pskb))
 		goto copy_skb;
 
-	/* Alexey says IP hdr is always modifiable and linear, so ok. */
-	if (writable_len <= (*pskb)->nh.iph->ihl*4)
-		return 1;
-
-	iplen = writable_len - (*pskb)->nh.iph->ihl*4;
-
-	/* DaveM says protocol headers are also modifiable. */
-	switch ((*pskb)->nh.iph->protocol) {
-	case IPPROTO_TCP: {
-		struct tcphdr _hdr, *hp;
-		hp = skb_header_pointer(*pskb, (*pskb)->nh.iph->ihl*4,
-					sizeof(_hdr), &_hdr);
-		if (hp == NULL)
-			goto copy_skb;
-		if (writable_len <= (*pskb)->nh.iph->ihl*4 + hp->doff*4)
-			goto pull_skb;
-		goto copy_skb;
-	}
-	case IPPROTO_UDP:
-		if (writable_len<=(*pskb)->nh.iph->ihl*4+sizeof(struct udphdr))
-			goto pull_skb;
-		goto copy_skb;
-	case IPPROTO_ICMP:
-		if (writable_len
-		    <= (*pskb)->nh.iph->ihl*4 + sizeof(struct icmphdr))
-			goto pull_skb;
-		goto copy_skb;
-	/* Insert other cases here as desired */
-	}
+	return pskb_may_pull(*pskb, writable_len);
 
 copy_skb:
 	nskb = skb_copy(*pskb, GFP_ATOMIC);
@@ -730,9 +701,6 @@
 	kfree_skb(*pskb);
 	*pskb = nskb;
 	return 1;
-
-pull_skb:
-	return pskb_may_pull(*pskb, writable_len);
 }
 EXPORT_SYMBOL(skb_ip_make_writable);
 #endif /*CONFIG_INET*/
diff -Nru a/net/core/pktgen.c b/net/core/pktgen.c
--- a/net/core/pktgen.c	2005-03-11 12:51:52 -08:00
+++ b/net/core/pktgen.c	2005-03-11 12:51:52 -08:00
@@ -151,7 +151,7 @@
 #include <asm/timex.h>
 
 
-#define VERSION  "pktgen v2.58: Packet Generator for packet performance testing.\n"
+#define VERSION  "pktgen v2.59: Packet Generator for packet performance testing.\n"
 
 /* #define PG_DEBUG(a) a */
 #define PG_DEBUG(a) 
@@ -1682,7 +1682,7 @@
 					pkt_dev->saddr_min = in_dev->ifa_list->ifa_address;
 					pkt_dev->saddr_max = pkt_dev->saddr_min;
 				}
-				in_dev_put(in_dev);	
+				__in_dev_put(in_dev);	
 			}
 			rcu_read_unlock();
 		}
diff -Nru a/net/core/skbuff.c b/net/core/skbuff.c
--- a/net/core/skbuff.c	2005-03-11 12:51:47 -08:00
+++ b/net/core/skbuff.c	2005-03-11 12:51:47 -08:00
@@ -241,7 +241,8 @@
 void skb_release_data(struct sk_buff *skb)
 {
 	if (!skb->cloned ||
-	    atomic_dec_and_test(&(skb_shinfo(skb)->dataref))) {
+	    !atomic_sub_return(skb->nohdr ? (1 << SKB_DATAREF_SHIFT) + 1 : 1,
+			       &skb_shinfo(skb)->dataref)) {
 		if (skb_shinfo(skb)->nr_frags) {
 			int i;
 			for (i = 0; i < skb_shinfo(skb)->nr_frags; i++)
@@ -353,6 +354,7 @@
 	C(csum);
 	C(local_df);
 	n->cloned = 1;
+	n->nohdr = 0;
 	C(pkt_type);
 	C(ip_summed);
 	C(priority);
@@ -604,6 +606,7 @@
 	skb->h.raw   += off;
 	skb->nh.raw  += off;
 	skb->cloned   = 0;
+	skb->nohdr    = 0;
 	atomic_set(&skb_shinfo(skb)->dataref, 1);
 	return 0;
 
@@ -982,70 +985,6 @@
 	return -EFAULT;
 }
 
-/* Keep iterating until skb_iter_next returns false. */
-void skb_iter_first(const struct sk_buff *skb, struct skb_iter *i)
-{
-	i->len = skb_headlen(skb);
-	i->data = (unsigned char *)skb->data;
-	i->nextfrag = 0;
-	i->fraglist = NULL;
-}
-
-int skb_iter_next(const struct sk_buff *skb, struct skb_iter *i)
-{
-	/* Unmap previous, if not head fragment. */
-	if (i->nextfrag)
-		kunmap_skb_frag(i->data);
-
-	if (i->fraglist) {
-	fraglist:
-		/* We're iterating through fraglist. */
-		if (i->nextfrag < skb_shinfo(i->fraglist)->nr_frags) {
-			i->data = kmap_skb_frag(&skb_shinfo(i->fraglist)
-						->frags[i->nextfrag]);
-			i->len = skb_shinfo(i->fraglist)->frags[i->nextfrag]
-				.size;
-			i->nextfrag++;
-			return 1;
-		}
-		/* Fragments with fragments?  Too hard! */
-		BUG_ON(skb_shinfo(i->fraglist)->frag_list);
-		i->fraglist = i->fraglist->next;
-		if (!i->fraglist)
-			goto end;
-
-		i->len = skb_headlen(i->fraglist);
-		i->data = i->fraglist->data;
-		i->nextfrag = 0;
-		return 1;
-	}
-
-	if (i->nextfrag < skb_shinfo(skb)->nr_frags) {
-		i->data = kmap_skb_frag(&skb_shinfo(skb)->frags[i->nextfrag]);
-		i->len = skb_shinfo(skb)->frags[i->nextfrag].size;
-		i->nextfrag++;
-		return 1;
-	}
-
-	i->fraglist = skb_shinfo(skb)->frag_list;
-	if (i->fraglist)
-		goto fraglist;
-
-end:
-	/* Bug trap for callers */
-	i->data = NULL;
-	return 0;
-}
-
-void skb_iter_abort(const struct sk_buff *skb, struct skb_iter *i)
-{
-	/* Unmap previous, if not head fragment. */
-	if (i->data && i->nextfrag)
-		kunmap_skb_frag(i->data);
-	/* Bug trap for callers */
-	i->data = NULL;
-}
-
 /* Checksum skb data. */
 
 unsigned int skb_checksum(const struct sk_buff *skb, int offset,
@@ -1516,6 +1455,3 @@
 EXPORT_SYMBOL(skb_unlink);
 EXPORT_SYMBOL(skb_append);
 EXPORT_SYMBOL(skb_split);
-EXPORT_SYMBOL(skb_iter_first);
-EXPORT_SYMBOL(skb_iter_next);
-EXPORT_SYMBOL(skb_iter_abort);
diff -Nru a/net/core/sock.c b/net/core/sock.c
--- a/net/core/sock.c	2005-03-11 12:51:47 -08:00
+++ b/net/core/sock.c	2005-03-11 12:51:47 -08:00
@@ -333,7 +333,10 @@
 			break;
 
 		case SO_PASSCRED:
-			sock->passcred = valbool;
+			if (valbool)
+				set_bit(SOCK_PASSCRED, &sock->flags);
+			else
+				clear_bit(SOCK_PASSCRED, &sock->flags);
 			break;
 
 		case SO_TIMESTAMP:
@@ -557,7 +560,7 @@
 			break; 
 
 		case SO_PASSCRED:
-			v.val = sock->passcred;
+			v.val = test_bit(SOCK_PASSCRED, &sock->flags) ? 1 : 0;
 			break;
 
 		case SO_PEERCRED:
@@ -621,9 +624,17 @@
 {
 	struct sock *sk = NULL;
 
-	if (!slab)
+	/*
+	 * Transitional, this test will be removed when sk_cachep is killed
+	 */
+	if (slab == NULL && zero_it == 1)
 		slab = sk_cachep;
-	sk = kmem_cache_alloc(slab, priority);
+
+	if (slab != NULL)
+		sk = kmem_cache_alloc(slab, priority);
+	else
+		sk = kmalloc(zero_it, priority);
+
 	if (sk) {
 		if (zero_it) {
 			memset(sk, 0,
@@ -662,7 +673,10 @@
 		       __FUNCTION__, atomic_read(&sk->sk_omem_alloc));
 
 	security_sk_free(sk);
-	kmem_cache_free(sk->sk_slab, sk);
+	if (sk->sk_slab != NULL)
+		kmem_cache_free(sk->sk_slab, sk);
+	else
+		kfree(sk);
 	module_put(owner);
 }
 
diff -Nru a/net/decnet/af_decnet.c b/net/decnet/af_decnet.c
--- a/net/decnet/af_decnet.c	2005-03-11 12:51:46 -08:00
+++ b/net/decnet/af_decnet.c	2005-03-11 12:51:46 -08:00
@@ -456,8 +456,6 @@
 	if  (!sk)
 		goto out;
 
-	sk->sk_protinfo = scp = (struct dn_scp *)(sk + 1);
-
 	if (sock)
 		sock->ops = &dn_proto_ops;
 	sock_init_data(sock, sk);
@@ -471,6 +469,7 @@
 	sk->sk_allocation  = gfp;
 
 	/* Initialization of DECnet Session Control Port		*/
+	scp = DN_SK(sk);
 	scp->state	= DN_O;		/* Open			*/
 	scp->numdat	= 1;		/* Next data seg to tx	*/
 	scp->numoth	= 1;		/* Next oth data to tx  */
diff -Nru a/net/decnet/dn_route.c b/net/decnet/dn_route.c
--- a/net/decnet/dn_route.c	2005-03-11 12:51:51 -08:00
+++ b/net/decnet/dn_route.c	2005-03-11 12:51:51 -08:00
@@ -253,7 +253,6 @@
  */
 static struct dst_entry *dn_dst_check(struct dst_entry *dst, __u32 cookie)
 {
-	dst_release(dst);
 	return NULL;
 }
 
diff -Nru a/net/econet/af_econet.c b/net/econet/af_econet.c
--- a/net/econet/af_econet.c	2005-03-11 12:51:46 -08:00
+++ b/net/econet/af_econet.c	2005-03-11 12:51:46 -08:00
@@ -184,7 +184,7 @@
 {
 	struct sockaddr_ec *sec = (struct sockaddr_ec *)uaddr;
 	struct sock *sk=sock->sk;
-	struct econet_opt *eo = ec_sk(sk);
+	struct econet_sock *eo = ec_sk(sk);
 	
 	/*
 	 *	Check legality
@@ -284,7 +284,7 @@
 	 */
 	 
 	if (saddr == NULL) {
-		struct econet_opt *eo = ec_sk(sk);
+		struct econet_sock *eo = ec_sk(sk);
 
 		addr.station = eo->station;
 		addr.net     = eo->net;
@@ -485,7 +485,7 @@
 			  int *uaddr_len, int peer)
 {
 	struct sock *sk = sock->sk;
-	struct econet_opt *eo = ec_sk(sk);
+	struct econet_sock *eo = ec_sk(sk);
 	struct sockaddr_ec *sec = (struct sockaddr_ec *)uaddr;
 
 	if (peer)
@@ -562,7 +562,7 @@
 static int econet_create(struct socket *sock, int protocol)
 {
 	struct sock *sk;
-	struct econet_opt *eo;
+	struct econet_sock *eo;
 	int err;
 
 	/* Econet only provides datagram services. */
@@ -572,7 +572,8 @@
 	sock->state = SS_UNCONNECTED;
 
 	err = -ENOBUFS;
-	sk = sk_alloc(PF_ECONET, GFP_KERNEL, 1, NULL);
+	sk = sk_alloc(PF_ECONET, GFP_KERNEL,
+		      sizeof(struct econet_sock), NULL);
 	if (sk == NULL)
 		goto out;
 
@@ -581,19 +582,13 @@
 	sock_init_data(sock,sk);
 	sk_set_owner(sk, THIS_MODULE);
 
-	eo = sk->sk_protinfo = kmalloc(sizeof(*eo), GFP_KERNEL);
-	if (!eo)
-		goto out_free;
-	memset(eo, 0, sizeof(*eo));
+	eo = ec_sk(sk);
 	sk->sk_zapped = 0;
 	sk->sk_family = PF_ECONET;
 	eo->num = protocol;
 
 	econet_insert_socket(&econet_sklist, sk);
 	return(0);
-
-out_free:
-	sk_free(sk);
 out:
 	return err;
 }
@@ -735,7 +730,7 @@
 	struct hlist_node *node;
 
 	sk_for_each(sk, node, &econet_sklist) {
-		struct econet_opt *opt = ec_sk(sk);
+		struct econet_sock *opt = ec_sk(sk);
 		if ((opt->port == port || opt->port == 0) && 
 		    (opt->station == station || opt->station == 0) &&
 		    (opt->net == net || opt->net == 0))
diff -Nru a/net/ipv4/ah4.c b/net/ipv4/ah4.c
--- a/net/ipv4/ah4.c	2005-03-11 12:51:51 -08:00
+++ b/net/ipv4/ah4.c	2005-03-11 12:51:51 -08:00
@@ -53,11 +53,9 @@
 	return 0;
 }
 
-static int ah_output(struct sk_buff *skb)
+static int ah_output(struct xfrm_state *x, struct sk_buff *skb)
 {
 	int err;
-	struct dst_entry *dst = skb->dst;
-	struct xfrm_state *x  = dst->xfrm;
 	struct iphdr *iph, *top_iph;
 	struct ip_auth_hdr *ah;
 	struct ah_data *ahp;
diff -Nru a/net/ipv4/arp.c b/net/ipv4/arp.c
--- a/net/ipv4/arp.c	2005-03-11 12:51:51 -08:00
+++ b/net/ipv4/arp.c	2005-03-11 12:51:51 -08:00
@@ -1243,7 +1243,7 @@
 	arp_proc_init();
 #ifdef CONFIG_SYSCTL
 	neigh_sysctl_register(NULL, &arp_tbl.parms, NET_IPV4,
-			      NET_IPV4_NEIGH, "ipv4", NULL);
+			      NET_IPV4_NEIGH, "ipv4", NULL, NULL);
 #endif
 	register_netdevice_notifier(&arp_netdev_notifier);
 }
diff -Nru a/net/ipv4/devinet.c b/net/ipv4/devinet.c
--- a/net/ipv4/devinet.c	2005-03-11 12:51:42 -08:00
+++ b/net/ipv4/devinet.c	2005-03-11 12:51:42 -08:00
@@ -153,7 +153,7 @@
 	dev_hold(dev);
 #ifdef CONFIG_SYSCTL
 	neigh_sysctl_register(dev, in_dev->arp_parms, NET_IPV4,
-			      NET_IPV4_NEIGH, "ipv4", NULL);
+			      NET_IPV4_NEIGH, "ipv4", NULL, NULL);
 #endif
 
 	/* Account for reference dev->ip_ptr */
@@ -187,6 +187,10 @@
 
 	ASSERT_RTNL();
 
+	dev = in_dev->dev;
+	if (dev == &loopback_dev)
+		return;
+
 	in_dev->dead = 1;
 
 	ip_mc_destroy_dev(in_dev);
@@ -200,7 +204,6 @@
 	devinet_sysctl_unregister(&in_dev->cnf);
 #endif
 
-	dev = in_dev->dev;
 	dev->ip_ptr = NULL;
 
 #ifdef CONFIG_SYSCTL
@@ -943,8 +946,16 @@
 
 	ASSERT_RTNL();
 
-	if (!in_dev)
+	if (!in_dev) {
+		if (event == NETDEV_REGISTER && dev == &loopback_dev) {
+			in_dev = inetdev_init(dev);
+			if (!in_dev)
+				panic("devinet: Failed to create loopback\n");
+			in_dev->cnf.no_xfrm = 1;
+			in_dev->cnf.no_policy = 1;
+		}
 		goto out;
+	}
 
 	switch (event) {
 	case NETDEV_REGISTER:
@@ -967,8 +978,6 @@
 				memcpy(ifa->ifa_label, dev->name, IFNAMSIZ);
 				inet_insert_ifa(ifa);
 			}
-			in_dev->cnf.no_xfrm = 1;
-			in_dev->cnf.no_policy = 1;
 		}
 		ip_mc_up(in_dev);
 		break;
@@ -992,7 +1001,7 @@
 		devinet_sysctl_unregister(&in_dev->cnf);
 		neigh_sysctl_unregister(in_dev->arp_parms);
 		neigh_sysctl_register(dev, in_dev->arp_parms, NET_IPV4,
-				      NET_IPV4_NEIGH, "ipv4", NULL);
+				      NET_IPV4_NEIGH, "ipv4", NULL, NULL);
 		devinet_sysctl_register(in_dev, &in_dev->cnf);
 #endif
 		break;
@@ -1212,7 +1221,7 @@
 
 static struct devinet_sysctl_table {
 	struct ctl_table_header *sysctl_header;
-	ctl_table		devinet_vars[20];
+	ctl_table		devinet_vars[__NET_IPV4_CONF_MAX];
 	ctl_table		devinet_dev[2];
 	ctl_table		devinet_conf_dir[2];
 	ctl_table		devinet_proto_dir[2];
diff -Nru a/net/ipv4/esp4.c b/net/ipv4/esp4.c
--- a/net/ipv4/esp4.c	2005-03-11 12:51:47 -08:00
+++ b/net/ipv4/esp4.c	2005-03-11 12:51:47 -08:00
@@ -17,11 +17,9 @@
 	__u8		proto;
 };
 
-static int esp_output(struct sk_buff *skb)
+static int esp_output(struct xfrm_state *x, struct sk_buff *skb)
 {
 	int err;
-	struct dst_entry *dst = skb->dst;
-	struct xfrm_state *x  = dst->xfrm;
 	struct iphdr *top_iph;
 	struct ip_esp_hdr *esph;
 	struct crypto_tfm *tfm;
diff -Nru a/net/ipv4/fib_hash.c b/net/ipv4/fib_hash.c
--- a/net/ipv4/fib_hash.c	2005-03-11 12:51:46 -08:00
+++ b/net/ipv4/fib_hash.c	2005-03-11 12:51:46 -08:00
@@ -93,6 +93,7 @@
 }
 
 static DEFINE_RWLOCK(fib_hash_lock);
+static unsigned int fib_hash_genid;
 
 #define FZ_MAX_DIVISOR ((PAGE_SIZE<<MAX_ORDER) / sizeof(struct hlist_head))
 
@@ -181,6 +182,7 @@
 		fz->fz_hashmask = new_hashmask;
 		fz->fz_divisor = new_divisor;
 		fn_rebuild_zone(fz, old_ht, old_divisor);
+		fib_hash_genid++;
 		write_unlock_bh(&fib_hash_lock);
 
 		fz_hash_free(old_ht, old_divisor);
@@ -236,6 +238,7 @@
 		table->fn_zones[i]->fz_next = fz;
 	}
 	table->fn_zones[z] = fz;
+	fib_hash_genid++;
 	write_unlock_bh(&fib_hash_lock);
 	return fz;
 }
@@ -451,6 +454,7 @@
 			fa->fa_scope = r->rtm_scope;
 			state = fa->fa_state;
 			fa->fa_state &= ~FA_S_ACCESSED;
+			fib_hash_genid++;
 			write_unlock_bh(&fib_hash_lock);
 
 			fib_release_info(fi_drop);
@@ -515,6 +519,7 @@
 		fib_insert_node(fz, new_f);
 	list_add_tail(&new_fa->fa_list,
 		 (fa ? &fa->fa_list : &f->fn_alias));
+	fib_hash_genid++;
 	write_unlock_bh(&fib_hash_lock);
 
 	if (new_f)
@@ -600,6 +605,7 @@
 			hlist_del(&f->fn_hash);
 			kill_fn = 1;
 		}
+		fib_hash_genid++;
 		write_unlock_bh(&fib_hash_lock);
 
 		if (fa->fa_state & FA_S_ACCESSED)
@@ -637,6 +643,7 @@
 					hlist_del(&f->fn_hash);
 					kill_f = 1;
 				}
+				fib_hash_genid++;
 				write_unlock_bh(&fib_hash_lock);
 
 				fn_free_alias(fa);
@@ -801,6 +808,9 @@
 	struct hlist_head *hash_head;
 	struct fib_node *fn;
 	struct fib_alias *fa;
+	loff_t pos;
+	unsigned int genid;
+	int valid;
 };
 
 static struct fib_alias *fib_get_first(struct seq_file *seq)
@@ -812,6 +822,9 @@
 	iter->hash_head = NULL;
 	iter->fn        = NULL;
 	iter->fa        = NULL;
+	iter->pos	= 0;
+	iter->genid	= fib_hash_genid;
+	iter->valid	= 1;
 
 	for (iter->zone = table->fn_zone_list; iter->zone;
 	     iter->zone = iter->zone->fz_next) {
@@ -916,16 +929,34 @@
 		}
 	}
 out:
+	iter->pos++;
 	return fa;
 }
 
+static struct fib_alias *fib_get_idx(struct seq_file *seq, loff_t pos)
+{
+	struct fib_iter_state *iter = seq->private;
+	struct fib_alias *fa;
+	
+	if (iter->valid && pos >= iter->pos && iter->genid == fib_hash_genid) {
+		fa   = iter->fa;
+		pos -= iter->pos;
+	} else
+		fa = fib_get_first(seq);
+
+	if (fa)
+		while (pos && (fa = fib_get_next(seq)))
+			--pos;
+	return pos ? NULL : fa;
+}
+
 static void *fib_seq_start(struct seq_file *seq, loff_t *pos)
 {
 	void *v = NULL;
 
 	read_lock(&fib_hash_lock);
 	if (ip_fib_main_table)
-		v = *pos ? fib_get_next(seq) : SEQ_START_TOKEN;
+		v = *pos ? fib_get_idx(seq, *pos - 1) : SEQ_START_TOKEN;
 	return v;
 }
 
diff -Nru a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c
--- a/net/ipv4/ip_gre.c	2005-03-11 12:51:52 -08:00
+++ b/net/ipv4/ip_gre.c	2005-03-11 12:51:52 -08:00
@@ -618,10 +618,8 @@
 
 		skb->mac.raw = skb->nh.raw;
 		skb->nh.raw = __pskb_pull(skb, offset);
+		skb_postpull_rcsum(skb, skb->mac.raw, offset);
 		memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options));
-		if (skb->ip_summed == CHECKSUM_HW)
-			skb->csum = csum_sub(skb->csum,
-					     csum_partial(skb->mac.raw, skb->nh.raw-skb->mac.raw, 0));
 		skb->pkt_type = PACKET_HOST;
 #ifdef CONFIG_NET_IPGRE_BROADCAST
 		if (MULTICAST(iph->daddr)) {
diff -Nru a/net/ipv4/ip_input.c b/net/ipv4/ip_input.c
--- a/net/ipv4/ip_input.c	2005-03-11 12:51:41 -08:00
+++ b/net/ipv4/ip_input.c	2005-03-11 12:51:41 -08:00
@@ -410,10 +410,9 @@
 		 * is IP we can trim to the true length of the frame.
 		 * Note this now means skb->len holds ntohs(iph->tot_len).
 		 */
-		if (skb->len > len) {
-			__pskb_trim(skb, len);
-			if (skb->ip_summed == CHECKSUM_HW)
-				skb->ip_summed = CHECKSUM_NONE;
+		if (pskb_trim_rcsum(skb, len)) {
+			IP_INC_STATS_BH(IPSTATS_MIB_INDISCARDS);
+			goto drop;
 		}
 	}
 
diff -Nru a/net/ipv4/ipcomp.c b/net/ipv4/ipcomp.c
--- a/net/ipv4/ipcomp.c	2005-03-11 12:51:51 -08:00
+++ b/net/ipv4/ipcomp.c	2005-03-11 12:51:51 -08:00
@@ -154,11 +154,9 @@
 	return err;
 }
 
-static int ipcomp_output(struct sk_buff *skb)
+static int ipcomp_output(struct xfrm_state *x, struct sk_buff *skb)
 {
 	int err;
-	struct dst_entry *dst = skb->dst;
-	struct xfrm_state *x = dst->xfrm;
 	struct iphdr *iph;
 	struct ip_comp_hdr *ipch;
 	struct ipcomp_data *ipcd = x->data;
diff -Nru a/net/ipv4/ipvs/ip_vs_core.c b/net/ipv4/ipvs/ip_vs_core.c
--- a/net/ipv4/ipvs/ip_vs_core.c	2005-03-11 12:51:40 -08:00
+++ b/net/ipv4/ipvs/ip_vs_core.c	2005-03-11 12:51:40 -08:00
@@ -1003,7 +1003,7 @@
 
 	/* Check the server status */
 	if (cp->dest && !(cp->dest->flags & IP_VS_DEST_F_AVAILABLE)) {
-		/* the destination server is not availabe */
+		/* the destination server is not available */
 
 		if (sysctl_ip_vs_expire_nodest_conn) {
 			/* try to expire the connection immediately */
diff -Nru a/net/ipv4/ipvs/ip_vs_ctl.c b/net/ipv4/ipvs/ip_vs_ctl.c
--- a/net/ipv4/ipvs/ip_vs_ctl.c	2005-03-11 12:51:51 -08:00
+++ b/net/ipv4/ipvs/ip_vs_ctl.c	2005-03-11 12:51:51 -08:00
@@ -26,7 +26,7 @@
 #include <linux/fs.h>
 #include <linux/sysctl.h>
 #include <linux/proc_fs.h>
-#include <linux/timer.h>
+#include <linux/workqueue.h>
 #include <linux/swap.h>
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
@@ -90,7 +90,7 @@
 #endif
 
 /*
- *	update_defense_level is called from timer bh and from sysctl.
+ *	update_defense_level is called from keventd and from sysctl.
  */
 static void update_defense_level(void)
 {
@@ -212,19 +212,19 @@
 /*
  *	Timer for checking the defense
  */
-static struct timer_list defense_timer;
 #define DEFENSE_TIMER_PERIOD	1*HZ
+static void defense_work_handler(void *data);
+static DECLARE_WORK(defense_work, defense_work_handler, NULL);
 
-static void defense_timer_handler(unsigned long data)
+static void defense_work_handler(void *data)
 {
 	update_defense_level();
 	if (atomic_read(&ip_vs_dropentry))
 		ip_vs_random_dropentry();
 
-	mod_timer(&defense_timer, jiffies + DEFENSE_TIMER_PERIOD);
+	schedule_delayed_work(&defense_work, DEFENSE_TIMER_PERIOD);
 }
 
-
 int
 ip_vs_use_count_inc(void)
 {
@@ -2370,10 +2370,7 @@
 	ip_vs_new_estimator(&ip_vs_stats);
 
 	/* Hook the defense timer */
-	init_timer(&defense_timer);
-	defense_timer.function = defense_timer_handler;
-	defense_timer.expires = jiffies + DEFENSE_TIMER_PERIOD;
-	add_timer(&defense_timer);
+	schedule_delayed_work(&defense_work, DEFENSE_TIMER_PERIOD);
 
 	LeaveFunction(2);
 	return 0;
@@ -2384,7 +2381,7 @@
 {
 	EnterFunction(2);
 	ip_vs_trash_cleanup();
-	del_timer_sync(&defense_timer);
+	cancel_rearming_delayed_work(&defense_work);
 	ip_vs_kill_estimator(&ip_vs_stats);
 	unregister_sysctl_table(sysctl_header);
 	proc_net_remove("ip_vs_stats");
diff -Nru a/net/ipv4/ipvs/ip_vs_wrr.c b/net/ipv4/ipvs/ip_vs_wrr.c
--- a/net/ipv4/ipvs/ip_vs_wrr.c	2005-03-11 12:51:41 -08:00
+++ b/net/ipv4/ipvs/ip_vs_wrr.c	2005-03-11 12:51:41 -08:00
@@ -126,6 +126,8 @@
 	mark->cl = &svc->destinations;
 	mark->mw = ip_vs_wrr_max_weight(svc);
 	mark->di = ip_vs_wrr_gcd_weight(svc);
+	if (mark->cw > mark->mw)
+		mark->cw = 0;
 	return 0;
 }
 
@@ -163,7 +165,7 @@
 			if (mark->cw <= 0) {
 				mark->cw = mark->mw;
 				/*
-				 * Still zero, which means no availabe servers.
+				 * Still zero, which means no available servers.
 				 */
 				if (mark->cw == 0) {
 					mark->cl = &svc->destinations;
@@ -186,7 +188,7 @@
 			}
 		}
 
-		if (mark->cl == p) {
+		if (mark->cl == p && mark->cw == mark->di) {
 			/* back to the start, and no dest is found.
 			   It is only possible when all dests are OVERLOADED */
 			dest = NULL;
diff -Nru a/net/ipv4/ipvs/ip_vs_xmit.c b/net/ipv4/ipvs/ip_vs_xmit.c
--- a/net/ipv4/ipvs/ip_vs_xmit.c	2005-03-11 12:51:51 -08:00
+++ b/net/ipv4/ipvs/ip_vs_xmit.c	2005-03-11 12:51:51 -08:00
@@ -52,6 +52,7 @@
 	if ((dst->obsolete || rtos != dest->dst_rtos) &&
 	    dst->ops->check(dst, cookie) == NULL) {
 		dest->dst_cache = NULL;
+		dst_release(dst);
 		return NULL;
 	}
 	dst_hold(dst);
diff -Nru a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c
--- a/net/ipv4/netfilter/arp_tables.c	2005-03-11 12:51:52 -08:00
+++ b/net/ipv4/netfilter/arp_tables.c	2005-03-11 12:51:52 -08:00
@@ -717,7 +717,7 @@
 	}
 
 	/* And one copy for every other CPU */
-	for (i = 1; i < NR_CPUS; i++) {
+	for (i = 1; i < num_possible_cpus(); i++) {
 		memcpy(newinfo->entries + SMP_ALIGN(newinfo->size)*i,
 		       newinfo->entries,
 		       SMP_ALIGN(newinfo->size));
@@ -768,7 +768,7 @@
 	unsigned int cpu;
 	unsigned int i;
 
-	for (cpu = 0; cpu < NR_CPUS; cpu++) {
+	for (cpu = 0; cpu < num_possible_cpus(); cpu++) {
 		i = 0;
 		ARPT_ENTRY_ITERATE(t->entries + TABLE_OFFSET(t, cpu),
 				   t->size,
@@ -886,7 +886,7 @@
 		return -ENOMEM;
 
 	newinfo = vmalloc(sizeof(struct arpt_table_info)
-			  + SMP_ALIGN(tmp.size) * NR_CPUS);
+			  + SMP_ALIGN(tmp.size) * num_possible_cpus());
 	if (!newinfo)
 		return -ENOMEM;
 
@@ -1159,7 +1159,7 @@
 		= { 0, 0, 0, { 0 }, { 0 }, { } };
 
 	newinfo = vmalloc(sizeof(struct arpt_table_info)
-			  + SMP_ALIGN(repl->size) * NR_CPUS);
+			  + SMP_ALIGN(repl->size) * num_possible_cpus());
 	if (!newinfo) {
 		ret = -ENOMEM;
 		return ret;
diff -Nru a/net/ipv4/netfilter/ip_conntrack_proto_sctp.c b/net/ipv4/netfilter/ip_conntrack_proto_sctp.c
--- a/net/ipv4/netfilter/ip_conntrack_proto_sctp.c	2005-03-11 12:51:51 -08:00
+++ b/net/ipv4/netfilter/ip_conntrack_proto_sctp.c	2005-03-11 12:51:51 -08:00
@@ -400,8 +400,8 @@
 					return -1;
 			}
 			DEBUGP("Setting vtag %x for dir %d\n", 
-					ih->init_tag, CTINFO2DIR(ctinfo));
-			conntrack->proto.sctp.vtag[IP_CT_DIR_ORIGINAL] = ih->init_tag;
+					ih->init_tag, !CTINFO2DIR(ctinfo));
+			conntrack->proto.sctp.vtag[!CTINFO2DIR(ctinfo)] = ih->init_tag;
 		}
 
 		conntrack->proto.sctp.state = newconntrack;
diff -Nru a/net/ipv4/netfilter/ip_conntrack_proto_tcp.c b/net/ipv4/netfilter/ip_conntrack_proto_tcp.c
--- a/net/ipv4/netfilter/ip_conntrack_proto_tcp.c	2005-03-11 12:51:51 -08:00
+++ b/net/ipv4/netfilter/ip_conntrack_proto_tcp.c	2005-03-11 12:51:51 -08:00
@@ -254,7 +254,7 @@
  *	sSS -> sSR	Standard open.
  *	sSR -> sSR	Retransmitted SYN/ACK.
  *	sES -> sIG	Late retransmitted SYN/ACK?
- *	sFW -> sIG
+ *	sFW -> sIG	Might be SYN/ACK answering ignored SYN
  *	sCW -> sIG
  *	sLA -> sIG
  *	sTW -> sIG
@@ -273,10 +273,10 @@
  *	sCL -> sCL
  */
 /* 	     sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sLI	*/
-/*ack*/	   { sIV, sIG, sIV, sES, sCW, sCW, sTW, sTW, sCL, sIV },
+/*ack*/	   { sIV, sIV, sSR, sES, sCW, sCW, sTW, sTW, sCL, sIV },
 /*
- *	sSS -> sIG	Might be a half-open connection.
- *	sSR -> sIV	Simultaneous open.
+ *	sSS -> sIV	Might be a half-open connection.
+ *	sSR -> sSR	Might answer late resent SYN.
  *	sES -> sES	:-)
  *	sFW -> sCW	Normal close request answered by ACK.
  *	sCW -> sCW
@@ -352,14 +352,19 @@
    http://www.nluug.nl/events/sane2000/papers.html
    http://www.iae.nl/users/guido/papers/tcp_filtering.ps.gz
    
-   The boundaries and the conditions are slightly changed:
-   
+   The boundaries and the conditions are changed according to RFC793:
+   the packet must intersect the window (i.e. segments may be
+   after the right or before the left edge) and thus receivers may ACK
+   segments after the right edge of the window.
+
    	td_maxend = max(sack + max(win,1)) seen in reply packets
 	td_maxwin = max(max(win, 1)) + (sack - ack) seen in sent packets
+	td_maxwin += seq + len - sender.td_maxend
+			if seq + len > sender.td_maxend
 	td_end    = max(seq + len) seen in sent packets
    
-   I. 	Upper bound for valid data:	seq + len <= sender.td_maxend
-   II. 	Lower bound for valid data:	seq >= sender.td_end - receiver.td_maxwin
+   I.   Upper bound for valid data:	seq <= sender.td_maxend
+   II.  Lower bound for valid data:	seq + len >= sender.td_end - receiver.td_maxwin
    III.	Upper bound for valid ack:      sack <= receiver.td_end
    IV.	Lower bound for valid ack:	ack >= receiver.td_end - MAXACKWINDOW
    	
@@ -373,7 +378,7 @@
 					 size_t len,
 					 struct iphdr *iph,
 					 struct tcphdr *tcph)
-  {
+{
 	return (seq + len - (iph->ihl + tcph->doff)*4
 		+ (tcph->syn ? 1 : 0) + (tcph->fin ? 1 : 0));
 }
@@ -444,22 +449,33 @@
 	}
 }
 
-static void tcp_sack(struct tcphdr *tcph, __u32 *sack)
+static void tcp_sack(const struct sk_buff *skb,
+		     struct iphdr *iph,
+		     struct tcphdr *tcph,
+		     __u32 *sack)
 {
-	__u32 tmp;
+	unsigned char buff[(15 * 4) - sizeof(struct tcphdr)];
 	unsigned char *ptr;
 	int length = (tcph->doff*4) - sizeof(struct tcphdr);
-	
+	__u32 tmp;
+
+	if (!length)
+		return;
+
+	ptr = skb_header_pointer(skb,
+				 (iph->ihl * 4) + sizeof(struct tcphdr),
+				 length, buff);
+	BUG_ON(ptr == NULL);
+
 	/* Fast path for timestamp-only option */
 	if (length == TCPOLEN_TSTAMP_ALIGNED*4
-	    && *(__u32 *)(tcph + 1) ==
+	    && *(__u32 *)ptr ==
 	        __constant_ntohl((TCPOPT_NOP << 24) 
 	        		 | (TCPOPT_NOP << 16)
 	        		 | (TCPOPT_TIMESTAMP << 8)
 	        		 | TCPOLEN_TIMESTAMP))
 		return;
 		
-	ptr = (unsigned char *)(tcph + 1);
 	while (length > 0) {
 		int opcode=*ptr++;
 		int opsize, i;
@@ -500,7 +516,7 @@
 
 static int tcp_in_window(struct ip_ct_tcp *state, 
                          enum ip_conntrack_dir dir,
-                         unsigned int *index,
+                         unsigned int index,
                          const struct sk_buff *skb,
                          struct iphdr *iph,
                          struct tcphdr *tcph)
@@ -519,7 +535,7 @@
 	end = segment_seq_plus_len(seq, skb->len, iph, tcph);
 	
 	if (receiver->flags & IP_CT_TCP_FLAG_SACK_PERM)
-		tcp_sack(tcph, &sack);
+		tcp_sack(skb, iph, tcph, &sack);
 		
 	DEBUGP("tcp_in_window: START\n");
 	DEBUGP("tcp_in_window: src=%u.%u.%u.%u:%hu dst=%u.%u.%u.%u:%hu "
@@ -598,20 +614,23 @@
 		ack = sack = receiver->td_end;
 	}
 
-	if (seq == end)
+	if (seq == end
+	    && (!tcph->rst 
+	        || (seq == 0 && state->state == TCP_CONNTRACK_SYN_SENT)))
 		/*
 		 * Packets contains no data: we assume it is valid
 		 * and check the ack value only.
+		 * However RST segments are always validated by their
+		 * SEQ number, except when seq == 0 (reset sent answering
+		 * SYN.
 		 */
 		seq = end = sender->td_end;
 		
 	DEBUGP("tcp_in_window: src=%u.%u.%u.%u:%hu dst=%u.%u.%u.%u:%hu "
-	       "seq=%u ack=%u sack =%u win=%u end=%u trim=%u\n",
+	       "seq=%u ack=%u sack =%u win=%u end=%u\n",
 		NIPQUAD(iph->saddr), ntohs(tcph->source),
 		NIPQUAD(iph->daddr), ntohs(tcph->dest),
-		seq, ack, sack, win, end, 
-		after(end, sender->td_maxend) && before(seq, sender->td_maxend)
-		? sender->td_maxend : end);
+		seq, ack, sack, win, end);
 	DEBUGP("tcp_in_window: sender end=%u maxend=%u maxwin=%u scale=%i "
 	       "receiver end=%u maxend=%u maxwin=%u scale=%i\n",
 		sender->td_end, sender->td_maxend, sender->td_maxwin,
@@ -619,24 +638,15 @@
 		receiver->td_end, receiver->td_maxend, receiver->td_maxwin,
 		receiver->td_scale);
 	
-	/* Ignore data over the right edge of the receiver's window. */
-	if (after(end, sender->td_maxend) &&
-	    before(seq, sender->td_maxend)) {
-		end = sender->td_maxend;
-		if (*index == TCP_FIN_SET)
-			*index = TCP_ACK_SET;
-	}
 	DEBUGP("tcp_in_window: I=%i II=%i III=%i IV=%i\n",
-		before(end, sender->td_maxend + 1) 
-		    || before(seq, sender->td_maxend + 1),
-	    	after(seq, sender->td_end - receiver->td_maxwin - 1) 
-	    	    || after(end, sender->td_end - receiver->td_maxwin - 1),
+		before(seq, sender->td_maxend + 1),
+	    	after(end, sender->td_end - receiver->td_maxwin - 1),
 	    	before(sack, receiver->td_end + 1),
 	    	after(ack, receiver->td_end - MAXACKWINDOW(sender)));
 	
 	if (sender->loose || receiver->loose ||
-	    (before(end, sender->td_maxend + 1) &&
-	     after(seq, sender->td_end - receiver->td_maxwin - 1) &&
+	    (before(seq, sender->td_maxend + 1) &&
+	     after(end, sender->td_end - receiver->td_maxwin - 1) &&
 	     before(sack, receiver->td_end + 1) &&
 	     after(ack, receiver->td_end - MAXACKWINDOW(sender)))) {
 	    	/*
@@ -653,6 +663,11 @@
 			sender->td_maxwin = swin;
 		if (after(end, sender->td_end))
 			sender->td_end = end;
+		/*
+		 * Update receiver data.
+		 */
+		if (after(end, sender->td_maxend))
+			receiver->td_maxwin += end - sender->td_maxend;
 		if (after(sack + win, receiver->td_maxend - 1)) {
 			receiver->td_maxend = sack + win;
 			if (win == 0)
@@ -662,7 +677,7 @@
 		/* 
 		 * Check retransmissions.
 		 */
-		if (*index == TCP_ACK_SET) {
+		if (index == TCP_ACK_SET) {
 			if (state->last_dir == dir
 			    && state->last_seq == seq
 			    && state->last_ack == ack
@@ -687,16 +702,16 @@
 		if (LOG_INVALID(IPPROTO_TCP))
 			nf_log_packet(PF_INET, 0, skb, NULL, NULL,
 			"ip_ct_tcp: %s ",
-			before(end, sender->td_maxend + 1) ?
-			after(seq, sender->td_end - receiver->td_maxwin - 1) ?
+			before(seq, sender->td_maxend + 1) ?
+			after(end, sender->td_end - receiver->td_maxwin - 1) ?
 			before(sack, receiver->td_end + 1) ?
 			after(ack, receiver->td_end - MAXACKWINDOW(sender)) ? "BUG"
-			: "ACK is under the lower bound (possibly overly delayed ACK)"
-			: "ACK is over the upper bound (ACKed data has never seen yet)"
-			: "SEQ is under the lower bound (retransmitted already ACKed data)"
+			: "ACK is under the lower bound (possible overly delayed ACK)"
+			: "ACK is over the upper bound (ACKed data not seen yet)"
+			: "SEQ is under the lower bound (already ACKed data retransmitted)"
 			: "SEQ is over the upper bound (over the window of the receiver)");
 
-		res = ip_ct_tcp_be_liberal && !tcph->rst;
+		res = ip_ct_tcp_be_liberal;
   	}
   
 	DEBUGP("tcp_in_window: res=%i sender end=%u maxend=%u maxwin=%u "
@@ -849,13 +864,12 @@
 	switch (new_state) {
 	case TCP_CONNTRACK_IGNORE:
 		/* Either SYN in ORIGINAL
-		 * or SYN/ACK in REPLY
-		 * or ACK in REPLY direction (half-open connection). */
+		 * or SYN/ACK in REPLY. */
 		if (index == TCP_SYNACK_SET
 		    && conntrack->proto.tcp.last_index == TCP_SYN_SET
 		    && conntrack->proto.tcp.last_dir != dir
-		    && after(ntohl(th->ack_seq),
-		    	     conntrack->proto.tcp.last_seq)) {
+		    && ntohl(th->ack_seq) ==
+		    	     conntrack->proto.tcp.last_end) {
 			/* This SYN/ACK acknowledges a SYN that we earlier 
 			 * ignored as invalid. This means that the client and
 			 * the server are both in sync, while the firewall is
@@ -875,6 +889,8 @@
 		conntrack->proto.tcp.last_index = index;
 		conntrack->proto.tcp.last_dir = dir;
 		conntrack->proto.tcp.last_seq = ntohl(th->seq);
+		conntrack->proto.tcp.last_end = 
+		    segment_seq_plus_len(ntohl(th->seq), skb->len, iph, th);
 		
 		WRITE_UNLOCK(&tcp_lock);
 		if (LOG_INVALID(IPPROTO_TCP))
@@ -892,7 +908,12 @@
 				  "ip_ct_tcp: invalid state ");
 		return -NF_ACCEPT;
 	case TCP_CONNTRACK_SYN_SENT:
-		if (old_state >= TCP_CONNTRACK_TIME_WAIT) {	
+		if (old_state < TCP_CONNTRACK_TIME_WAIT)
+			break;
+		if ((conntrack->proto.tcp.seen[dir].flags &
+		         IP_CT_TCP_FLAG_CLOSE_INIT)
+		    || after(ntohl(th->seq),
+		    	     conntrack->proto.tcp.seen[dir].td_end)) {	
 		    	/* Attempt to reopen a closed connection.
 		    	* Delete this connection and look up again. */
 		    	WRITE_UNLOCK(&tcp_lock);
@@ -900,23 +921,23 @@
 		    		conntrack->timeout.function((unsigned long)
 		    					    conntrack);
 		    	return -NF_REPEAT;
+		} else {
+			WRITE_UNLOCK(&tcp_lock);
+			if (LOG_INVALID(IPPROTO_TCP))
+				nf_log_packet(PF_INET, 0, skb, NULL, NULL,
+				              "ip_ct_tcp: invalid SYN");
+			return -NF_ACCEPT;
 		}
-		break;
 	case TCP_CONNTRACK_CLOSE:
 		if (index == TCP_RST_SET
-		    && ((test_bit(IPS_SEEN_REPLY_BIT, &conntrack->status)
-		         && conntrack->proto.tcp.last_index <= TCP_SYNACK_SET)
-		        || (!test_bit(IPS_ASSURED_BIT, &conntrack->status)
-			 && conntrack->proto.tcp.last_index == TCP_ACK_SET))
-		    && after(ntohl(th->ack_seq),
-		    	     conntrack->proto.tcp.last_seq)) {
-			/* Ignore RST closing down invalid SYN or ACK
-			   we had let trough. */ 
-		    	WRITE_UNLOCK(&tcp_lock);
-			if (LOG_INVALID(IPPROTO_TCP))
-				nf_log_packet(PF_INET, 0, skb, NULL, NULL, 
-					  "ip_ct_tcp: invalid RST (ignored) ");
-			return NF_ACCEPT;
+		    && test_bit(IPS_SEEN_REPLY_BIT, &conntrack->status)
+		    && conntrack->proto.tcp.last_index == TCP_SYN_SET
+		    && ntohl(th->ack_seq) == conntrack->proto.tcp.last_end) {
+			/* RST sent to invalid SYN we had let trough
+			 * SYN was in window then, tear down connection.
+			 * We skip window checking, because packet might ACK
+			 * segments we ignored in the SYN. */
+			goto in_window;
 		}
 		/* Just fall trough */
 	default:
@@ -924,16 +945,14 @@
 		break;
 	}
 
-	if (!tcp_in_window(&conntrack->proto.tcp, dir, &index, 
+	if (!tcp_in_window(&conntrack->proto.tcp, dir, index, 
 			   skb, iph, th)) {
 		WRITE_UNLOCK(&tcp_lock);
 		return -NF_ACCEPT;
 	}
-	/* From now on we have got in-window packets */
-	
-	/* If FIN was trimmed off, we don't change state. */
+    in_window:
+	/* From now on we have got in-window packets */	
 	conntrack->proto.tcp.last_index = index;
-	new_state = tcp_conntracks[dir][index][old_state];
 
 	DEBUGP("tcp_conntracks: src=%u.%u.%u.%u:%hu dst=%u.%u.%u.%u:%hu "
 	       "syn=%i ack=%i fin=%i rst=%i old=%i new=%i\n",
@@ -944,6 +963,10 @@
 		old_state, new_state);
 
 	conntrack->proto.tcp.state = new_state;
+	if (old_state != new_state 
+	    && (new_state == TCP_CONNTRACK_FIN_WAIT
+	    	|| new_state == TCP_CONNTRACK_CLOSE))
+		conntrack->proto.tcp.seen[dir].flags |= IP_CT_TCP_FLAG_CLOSE_INIT;
 	timeout = conntrack->proto.tcp.retrans >= ip_ct_tcp_max_retrans
 		  && *tcp_timeouts[new_state] > ip_ct_tcp_timeout_max_retrans
 		  ? ip_ct_tcp_timeout_max_retrans : *tcp_timeouts[new_state];
@@ -974,7 +997,7 @@
 	return NF_ACCEPT;
 }
  
-  /* Called when a new connection for this protocol found. */
+/* Called when a new connection for this protocol found. */
 static int tcp_new(struct ip_conntrack *conntrack,
 		   const struct sk_buff *skb)
 {
diff -Nru a/net/ipv4/netfilter/ip_conntrack_standalone.c b/net/ipv4/netfilter/ip_conntrack_standalone.c
--- a/net/ipv4/netfilter/ip_conntrack_standalone.c	2005-03-11 12:51:43 -08:00
+++ b/net/ipv4/netfilter/ip_conntrack_standalone.c	2005-03-11 12:51:43 -08:00
@@ -77,34 +77,70 @@
 #define seq_print_counters(x, y)	0
 #endif
 
-static void *ct_seq_start(struct seq_file *s, loff_t *pos)
+struct ct_iter_state {
+	unsigned int bucket;
+};
+
+static struct list_head *ct_get_first(struct seq_file *seq)
 {
-	if (*pos >= ip_conntrack_htable_size)
-		return NULL;
-	return &ip_conntrack_hash[*pos];
+	struct ct_iter_state *st = seq->private;
+
+	for (st->bucket = 0;
+	     st->bucket < ip_conntrack_htable_size;
+	     st->bucket++) {
+		if (!list_empty(&ip_conntrack_hash[st->bucket]))
+			return ip_conntrack_hash[st->bucket].next;
+	}
+	return NULL;
 }
-  
-static void ct_seq_stop(struct seq_file *s, void *v)
+
+static struct list_head *ct_get_next(struct seq_file *seq, struct list_head *head)
+{
+	struct ct_iter_state *st = seq->private;
+
+	head = head->next;
+	while (head == &ip_conntrack_hash[st->bucket]) {
+		if (++st->bucket >= ip_conntrack_htable_size)
+			return NULL;
+		head = ip_conntrack_hash[st->bucket].next;
+	}
+	return head;
+}
+
+static struct list_head *ct_get_idx(struct seq_file *seq, loff_t pos)
 {
+	struct list_head *head = ct_get_first(seq);
+
+	if (head)
+		while (pos && (head = ct_get_next(seq, head)))
+			pos--;
+	return pos ? NULL : head;
+}
+
+static void *ct_seq_start(struct seq_file *seq, loff_t *pos)
+{
+	READ_LOCK(&ip_conntrack_lock);
+	return ct_get_idx(seq, *pos);
 }
 
 static void *ct_seq_next(struct seq_file *s, void *v, loff_t *pos)
 {
 	(*pos)++;
-	if (*pos >= ip_conntrack_htable_size)
-		return NULL;
-	return &ip_conntrack_hash[*pos];
+	return ct_get_next(s, v);
 }
   
-/* return 0 on success, 1 in case of error */
-static int ct_seq_real_show(const struct ip_conntrack_tuple_hash *hash,
-			    struct seq_file *s)
+static void ct_seq_stop(struct seq_file *s, void *v)
 {
+	READ_UNLOCK(&ip_conntrack_lock);
+}
+ 
+static int ct_seq_show(struct seq_file *s, void *v)
+{
+	const struct ip_conntrack_tuple_hash *hash = v;
 	const struct ip_conntrack *conntrack = tuplehash_to_ctrack(hash);
 	struct ip_conntrack_protocol *proto;
 
 	MUST_BE_READ_LOCKED(&ip_conntrack_lock);
-
 	IP_NF_ASSERT(conntrack);
 
 	/* we only want to print DIR_ORIGINAL */
@@ -115,63 +151,50 @@
 			       .tuple.dst.protonum);
 	IP_NF_ASSERT(proto);
 
-	if (seq_printf(s, "%-8s %u %lu ",
+	if (seq_printf(s, "%-8s %u %ld ",
 		      proto->name,
 		      conntrack->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum,
 		      timer_pending(&conntrack->timeout)
-		      ? (conntrack->timeout.expires - jiffies)/HZ : 0) != 0)
-		return 1;
+		      ? (long)(conntrack->timeout.expires - jiffies)/HZ
+		      : 0) != 0)
+		return -ENOSPC;
 
 	if (proto->print_conntrack(s, conntrack))
-		return 1;
+		return -ENOSPC;
   
 	if (print_tuple(s, &conntrack->tuplehash[IP_CT_DIR_ORIGINAL].tuple,
 			proto))
-		return 1;
+		return -ENOSPC;
 
  	if (seq_print_counters(s, &conntrack->counters[IP_CT_DIR_ORIGINAL]))
-		return 1;
+		return -ENOSPC;
 
 	if (!(test_bit(IPS_SEEN_REPLY_BIT, &conntrack->status)))
 		if (seq_printf(s, "[UNREPLIED] "))
-			return 1;
+			return -ENOSPC;
 
 	if (print_tuple(s, &conntrack->tuplehash[IP_CT_DIR_REPLY].tuple,
 			proto))
-		return 1;
+		return -ENOSPC;
 
  	if (seq_print_counters(s, &conntrack->counters[IP_CT_DIR_REPLY]))
-		return 1;
+		return -ENOSPC;
 
 	if (test_bit(IPS_ASSURED_BIT, &conntrack->status))
 		if (seq_printf(s, "[ASSURED] "))
-			return 1;
+			return -ENOSPC;
 
 #if defined(CONFIG_IP_NF_CONNTRACK_MARK)
-	if (seq_printf(s, "mark=%ld ", conntrack->mark))
-		return 1;
+	if (seq_printf(s, "mark=%lu ", conntrack->mark))
+		return -ENOSPC;
 #endif
 
 	if (seq_printf(s, "use=%u\n", atomic_read(&conntrack->ct_general.use)))
-		return 1;
+		return -ENOSPC;
 
 	return 0;
 }
 
-static int ct_seq_show(struct seq_file *s, void *v)
-{
-	struct list_head *list = v;
-	int ret = 0;
-
-	/* FIXME: Simply truncates if hash chain too long. */
-	READ_LOCK(&ip_conntrack_lock);
-	if (LIST_FIND(list, ct_seq_real_show,
-		      struct ip_conntrack_tuple_hash *, s))
-		ret = -ENOSPC;
-	READ_UNLOCK(&ip_conntrack_lock);
-	return ret;
-}
-	
 static struct seq_operations ct_seq_ops = {
 	.start = ct_seq_start,
 	.next  = ct_seq_next,
@@ -181,7 +204,23 @@
   
 static int ct_open(struct inode *inode, struct file *file)
 {
-	return seq_open(file, &ct_seq_ops);
+	struct seq_file *seq;
+	struct ct_iter_state *st;
+	int ret;
+
+	st = kmalloc(sizeof(struct ct_iter_state), GFP_KERNEL);
+	if (st == NULL)
+		return -ENOMEM;
+	ret = seq_open(file, &ct_seq_ops);
+	if (ret)
+		goto out_free;
+	seq          = file->private_data;
+	seq->private = st;
+	memset(st, 0, sizeof(struct ct_iter_state));
+	return ret;
+out_free:
+	kfree(st);
+	return ret;
 }
 
 static struct file_operations ct_file_ops = {
@@ -189,7 +228,7 @@
 	.open    = ct_open,
 	.read    = seq_read,
 	.llseek  = seq_lseek,
-	.release = seq_release
+	.release = seq_release_private,
 };
   
 /* expects */
@@ -235,8 +274,8 @@
 	struct ip_conntrack_expect *expect = v;
 
 	if (expect->timeout.function)
-		seq_printf(s, "%lu ", timer_pending(&expect->timeout)
-			   ? (expect->timeout.expires - jiffies)/HZ : 0);
+		seq_printf(s, "%ld ", timer_pending(&expect->timeout)
+			   ? (long)(expect->timeout.expires - jiffies)/HZ : 0);
 	else
 		seq_printf(s, "- ");
 
diff -Nru a/net/ipv4/netfilter/ip_queue.c b/net/ipv4/netfilter/ip_queue.c
--- a/net/ipv4/netfilter/ip_queue.c	2005-03-11 12:51:52 -08:00
+++ b/net/ipv4/netfilter/ip_queue.c	2005-03-11 12:51:52 -08:00
@@ -14,6 +14,9 @@
  *             Zander).
  * 2000-08-01: Added Nick Williams' MAC support.
  * 2002-06-25: Code cleanup.
+ * 2005-01-10: Added /proc counter for dropped packets; fixed so
+ *             packets aren't delivered to user space if they're going 
+ *             to be dropped. 
  *
  */
 #include <linux/module.h>
@@ -59,6 +62,8 @@
 static int peer_pid;
 static unsigned int copy_range;
 static unsigned int queue_total;
+static unsigned int queue_dropped = 0;
+static unsigned int queue_user_dropped = 0;
 static struct sock *ipqnl;
 static LIST_HEAD(queue_list);
 static DECLARE_MUTEX(ipqnl_sem);
@@ -70,18 +75,11 @@
 	kfree(entry);
 }
 
-static inline int
+static inline void
 __ipq_enqueue_entry(struct ipq_queue_entry *entry)
 {
-       if (queue_total >= queue_maxlen) {
-               if (net_ratelimit()) 
-                       printk(KERN_WARNING "ip_queue: full at %d entries, "
-                              "dropping packet(s).\n", queue_total);
-               return -ENOSPC;
-       }
        list_add(&entry->list, &queue_list);
        queue_total++;
-       return 0;
 }
 
 /*
@@ -308,14 +306,24 @@
 	if (!peer_pid)
 		goto err_out_free_nskb; 
 
+	if (queue_total >= queue_maxlen) {
+                queue_dropped++;
+		status = -ENOSPC;
+		if (net_ratelimit())
+		          printk (KERN_WARNING "ip_queue: full at %d entries, "
+				  "dropping packets(s). Dropped: %d\n", queue_total,
+				  queue_dropped);
+		goto err_out_free_nskb;
+	}
+
  	/* netlink_unicast will either free the nskb or attach it to a socket */ 
 	status = netlink_unicast(ipqnl, nskb, peer_pid, MSG_DONTWAIT);
-	if (status < 0)
-		goto err_out_unlock;
-	
-	status = __ipq_enqueue_entry(entry);
-	if (status < 0)
+	if (status < 0) {
+	        queue_user_dropped++;
 		goto err_out_unlock;
+	}
+
+	__ipq_enqueue_entry(entry);
 
 	write_unlock_bh(&queue_lock);
 	return status;
@@ -637,12 +645,16 @@
 	              "Copy mode         : %hu\n"
 	              "Copy range        : %u\n"
 	              "Queue length      : %u\n"
-	              "Queue max. length : %u\n",
+	              "Queue max. length : %u\n"
+		      "Queue dropped     : %u\n"
+		      "Netlink dropped   : %u\n",
 	              peer_pid,
 	              copy_mode,
 	              copy_range,
 	              queue_total,
-	              queue_maxlen);
+	              queue_maxlen,
+		      queue_dropped,
+		      queue_user_dropped);
 
 	read_unlock_bh(&queue_lock);
 	
diff -Nru a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c
--- a/net/ipv4/netfilter/ip_tables.c	2005-03-11 12:51:42 -08:00
+++ b/net/ipv4/netfilter/ip_tables.c	2005-03-11 12:51:42 -08:00
@@ -923,7 +923,7 @@
 	}
 
 	/* And one copy for every other CPU */
-	for (i = 1; i < NR_CPUS; i++) {
+	for (i = 1; i < num_possible_cpus(); i++) {
 		memcpy(newinfo->entries + SMP_ALIGN(newinfo->size)*i,
 		       newinfo->entries,
 		       SMP_ALIGN(newinfo->size));
@@ -945,7 +945,7 @@
 		struct ipt_entry *table_base;
 		unsigned int i;
 
-		for (i = 0; i < NR_CPUS; i++) {
+		for (i = 0; i < num_possible_cpus(); i++) {
 			table_base =
 				(void *)newinfo->entries
 				+ TABLE_OFFSET(newinfo, i);
@@ -992,7 +992,7 @@
 	unsigned int cpu;
 	unsigned int i;
 
-	for (cpu = 0; cpu < NR_CPUS; cpu++) {
+	for (cpu = 0; cpu < num_possible_cpus(); cpu++) {
 		i = 0;
 		IPT_ENTRY_ITERATE(t->entries + TABLE_OFFSET(t, cpu),
 				  t->size,
@@ -1130,7 +1130,7 @@
 		return -ENOMEM;
 
 	newinfo = vmalloc(sizeof(struct ipt_table_info)
-			  + SMP_ALIGN(tmp.size) * NR_CPUS);
+			  + SMP_ALIGN(tmp.size) * num_possible_cpus());
 	if (!newinfo)
 		return -ENOMEM;
 
@@ -1460,7 +1460,7 @@
 		= { 0, 0, 0, { 0 }, { 0 }, { } };
 
 	newinfo = vmalloc(sizeof(struct ipt_table_info)
-			  + SMP_ALIGN(repl->size) * NR_CPUS);
+			  + SMP_ALIGN(repl->size) * num_possible_cpus());
 	if (!newinfo)
 		return -ENOMEM;
 
diff -Nru a/net/ipv4/netfilter/ipt_LOG.c b/net/ipv4/netfilter/ipt_LOG.c
--- a/net/ipv4/netfilter/ipt_LOG.c	2005-03-11 12:51:51 -08:00
+++ b/net/ipv4/netfilter/ipt_LOG.c	2005-03-11 12:51:51 -08:00
@@ -198,16 +198,16 @@
 		static size_t required_len[NR_ICMP_TYPES+1]
 			= { [ICMP_ECHOREPLY] = 4,
 			    [ICMP_DEST_UNREACH]
-			    = 8 + sizeof(struct iphdr) + 8,
+			    = 8 + sizeof(struct iphdr),
 			    [ICMP_SOURCE_QUENCH]
-			    = 8 + sizeof(struct iphdr) + 8,
+			    = 8 + sizeof(struct iphdr),
 			    [ICMP_REDIRECT]
-			    = 8 + sizeof(struct iphdr) + 8,
+			    = 8 + sizeof(struct iphdr),
 			    [ICMP_ECHO] = 4,
 			    [ICMP_TIME_EXCEEDED]
-			    = 8 + sizeof(struct iphdr) + 8,
+			    = 8 + sizeof(struct iphdr),
 			    [ICMP_PARAMETERPROB]
-			    = 8 + sizeof(struct iphdr) + 8,
+			    = 8 + sizeof(struct iphdr),
 			    [ICMP_TIMESTAMP] = 20,
 			    [ICMP_TIMESTAMPREPLY] = 20,
 			    [ICMP_ADDRESS] = 12,
diff -Nru a/net/ipv4/netfilter/ipt_REJECT.c b/net/ipv4/netfilter/ipt_REJECT.c
--- a/net/ipv4/netfilter/ipt_REJECT.c	2005-03-11 12:51:51 -08:00
+++ b/net/ipv4/netfilter/ipt_REJECT.c	2005-03-11 12:51:51 -08:00
@@ -252,10 +252,6 @@
 	if (iph->frag_off&htons(IP_OFFSET))
 		return;
 
-	/* Ensure we have at least 8 bytes of proto header. */
-	if (skb_in->len < skb_in->nh.iph->ihl*4 + 8)
-		return;
-
 	/* If we send an ICMP error to an ICMP error a mess would result.. */
 	if (iph->protocol == IPPROTO_ICMP) {
 		struct icmphdr ihdr;
diff -Nru a/net/ipv4/netfilter/ipt_hashlimit.c b/net/ipv4/netfilter/ipt_hashlimit.c
--- a/net/ipv4/netfilter/ipt_hashlimit.c	2005-03-11 12:51:46 -08:00
+++ b/net/ipv4/netfilter/ipt_hashlimit.c	2005-03-11 12:51:46 -08:00
@@ -33,11 +33,7 @@
 #include <linux/sctp.h>
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
-
-#define ASSERT_READ_LOCK(x) 
-#define ASSERT_WRITE_LOCK(x) 
-#include <linux/netfilter_ipv4/lockhelp.h>
-#include <linux/netfilter_ipv4/listhelp.h>
+#include <linux/list.h>
 
 #include <linux/netfilter_ipv4/ip_tables.h>
 #include <linux/netfilter_ipv4/ipt_hashlimit.h>
@@ -67,7 +63,7 @@
 
 struct dsthash_ent {
 	/* static / read-only parts in the beginning */
-	struct list_head list;
+	struct hlist_node node;
 	struct dsthash_dst dst;
 
 	/* modified structure members in the end */
@@ -80,7 +76,7 @@
 };
 
 struct ipt_hashlimit_htable {
-	struct list_head list;		/* global list of all htables */
+	struct hlist_node node;		/* global list of all htables */
 	atomic_t use;
 
 	struct hashlimit_cfg cfg;	/* config */
@@ -94,12 +90,12 @@
 	/* seq_file stuff */
 	struct proc_dir_entry *pde;
 
-	struct list_head hash[0];	/* hashtable itself */
+	struct hlist_head hash[0];	/* hashtable itself */
 };
 
-static DECLARE_RWLOCK(hashlimit_lock);	/* protects htables list */
+static DECLARE_LOCK(hashlimit_lock);	/* protects htables list */
 static DECLARE_MUTEX(hlimit_mutex);	/* additional checkentry protection */
-static LIST_HEAD(hashlimit_htables);
+static HLIST_HEAD(hashlimit_htables);
 static kmem_cache_t *hashlimit_cachep;
 
 static inline int dst_cmp(const struct dsthash_ent *ent, struct dsthash_dst *b)
@@ -120,9 +116,17 @@
 static inline struct dsthash_ent *
 __dsthash_find(const struct ipt_hashlimit_htable *ht, struct dsthash_dst *dst)
 {
-	struct dsthash_ent *ent;
+	struct dsthash_ent *ent = NULL;
+	struct hlist_node *pos;
 	u_int32_t hash = hash_dst(ht, dst);
-	ent = LIST_FIND(&ht->hash[hash], dst_cmp, struct dsthash_ent *, dst);
+
+	if (!hlist_empty(&ht->hash[hash]))
+		hlist_for_each_entry(ent, pos, &ht->hash[hash], node) {
+			if (dst_cmp(ent, dst)) {
+				break;
+			}
+		}
+	
 	return ent;
 }
 
@@ -162,7 +166,7 @@
 	ent->dst.src_ip = dst->src_ip;
 	ent->dst.src_port = dst->src_port;
 
-	list_add(&ent->list, &ht->hash[hash_dst(ht, dst)]);
+	hlist_add_head(&ent->node, &ht->hash[hash_dst(ht, dst)]);
 
 	return ent;
 }
@@ -170,7 +174,7 @@
 static inline void 
 __dsthash_free(struct ipt_hashlimit_htable *ht, struct dsthash_ent *ent)
 {
-	list_del(&ent->list);
+	hlist_del(&ent->node);
 	kmem_cache_free(hashlimit_cachep, ent);
 	atomic_dec(&ht->count);
 }
@@ -210,7 +214,7 @@
 		hinfo->cfg.max = hinfo->cfg.size;
 
 	for (i = 0; i < hinfo->cfg.size; i++)
-		INIT_LIST_HEAD(&hinfo->hash[i]);
+		INIT_HLIST_HEAD(&hinfo->hash[i]);
 
 	atomic_set(&hinfo->count, 0);
 	atomic_set(&hinfo->use, 1);
@@ -230,9 +234,9 @@
 	hinfo->timer.function = htable_gc;
 	add_timer(&hinfo->timer);
 
-	WRITE_LOCK(&hashlimit_lock);
-	list_add(&hinfo->list, &hashlimit_htables);
-	WRITE_UNLOCK(&hashlimit_lock);
+	LOCK_BH(&hashlimit_lock);
+	hlist_add_head(&hinfo->node, &hashlimit_htables);
+	UNLOCK_BH(&hashlimit_lock);
 
 	return 0;
 }
@@ -258,8 +262,9 @@
 	/* lock hash table and iterate over it */
 	spin_lock_bh(&ht->lock);
 	for (i = 0; i < ht->cfg.size; i++) {
-		struct dsthash_ent *dh, *n;
-		list_for_each_entry_safe(dh, n, &ht->hash[i], list) {
+		struct dsthash_ent *dh;
+		struct hlist_node *pos, *n;
+		hlist_for_each_entry_safe(dh, pos, n, &ht->hash[i], node) {
 			if ((*select)(ht, dh))
 				__dsthash_free(ht, dh);
 		}
@@ -295,16 +300,17 @@
 static struct ipt_hashlimit_htable *htable_find_get(char *name)
 {
 	struct ipt_hashlimit_htable *hinfo;
+	struct hlist_node *pos;
 
-	READ_LOCK(&hashlimit_lock);
-	list_for_each_entry(hinfo, &hashlimit_htables, list) {
+	LOCK_BH(&hashlimit_lock);
+	hlist_for_each_entry(hinfo, pos, &hashlimit_htables, node) {
 		if (!strcmp(name, hinfo->pde->name)) {
 			atomic_inc(&hinfo->use);
-			READ_UNLOCK(&hashlimit_lock);
+			UNLOCK_BH(&hashlimit_lock);
 			return hinfo;
 		}
 	}
-	READ_UNLOCK(&hashlimit_lock);
+	UNLOCK_BH(&hashlimit_lock);
 
 	return NULL;
 }
@@ -312,9 +318,9 @@
 static void htable_put(struct ipt_hashlimit_htable *hinfo)
 {
 	if (atomic_dec_and_test(&hinfo->use)) {
-		WRITE_LOCK(&hashlimit_lock);
-		list_del(&hinfo->list);
-		WRITE_UNLOCK(&hashlimit_lock);
+		LOCK_BH(&hashlimit_lock);
+		hlist_del(&hinfo->node);
+		UNLOCK_BH(&hashlimit_lock);
 		htable_destroy(hinfo);
 	}
 }
@@ -619,7 +625,7 @@
 	rateinfo_recalc(ent, jiffies);
 
 	return seq_printf(s, "%ld %u.%u.%u.%u:%u->%u.%u.%u.%u:%u %u %u %u\n",
-			(ent->expires - jiffies)/HZ,
+			(long)(ent->expires - jiffies)/HZ,
 			NIPQUAD(ent->dst.src_ip), ntohs(ent->dst.src_port),
 			NIPQUAD(ent->dst.dst_ip), ntohs(ent->dst.dst_port),
 			ent->rateinfo.credit, ent->rateinfo.credit_cap,
@@ -631,12 +637,17 @@
 	struct proc_dir_entry *pde = s->private;
 	struct ipt_hashlimit_htable *htable = pde->data;
 	unsigned int *bucket = (unsigned int *)v;
+	struct dsthash_ent *ent;
+	struct hlist_node *pos;
 
-	if (LIST_FIND_W(&htable->hash[*bucket], dl_seq_real_show,
-		      struct dsthash_ent *, s)) {
-		/* buffer was filled and unable to print that tuple */
-		return 1;
-	}
+	if (!hlist_empty(&htable->hash[*bucket]))
+		hlist_for_each_entry(ent, pos, &htable->hash[*bucket], node) {
+			if (dl_seq_real_show(ent, s)) {
+				/* buffer was filled and unable to print that tuple */
+				return 1;
+			}
+		}
+	
 	return 0;
 }
 
diff -Nru a/net/ipv4/route.c b/net/ipv4/route.c
--- a/net/ipv4/route.c	2005-03-11 12:51:52 -08:00
+++ b/net/ipv4/route.c	2005-03-11 12:51:52 -08:00
@@ -104,6 +104,9 @@
 #include <linux/sysctl.h>
 #endif
 
+#define RT_FL_TOS(oldflp) \
+    ((u32)(oldflp->fl4_tos & (IPTOS_RT_MASK | RTO_ONLINK)))
+
 #define IP_MAX_MTU	0xFFF0
 
 #define RT_GC_TIMEOUT (300*HZ)
@@ -144,6 +147,7 @@
 static void		 ipv4_link_failure(struct sk_buff *skb);
 static void		 ip_rt_update_pmtu(struct dst_entry *dst, u32 mtu);
 static int rt_garbage_collect(void);
+static inline int compare_keys(struct flowi *fl1, struct flowi *fl2);
 
 
 static struct dst_ops ipv4_dst_ops = {
@@ -1322,7 +1326,6 @@
 
 static struct dst_entry *ipv4_dst_check(struct dst_entry *dst, u32 cookie)
 {
-	dst_release(dst);
 	return NULL;
 }
 
@@ -1535,6 +1538,169 @@
 	return -EINVAL;
 }
 
+
+static void ip_handle_martian_source(struct net_device *dev,
+				     struct in_device *in_dev,
+				     struct sk_buff *skb,
+				     u32 daddr,
+				     u32 saddr) 
+{
+	RT_CACHE_STAT_INC(in_martian_src);
+#ifdef CONFIG_IP_ROUTE_VERBOSE
+	if (IN_DEV_LOG_MARTIANS(in_dev) && net_ratelimit()) {
+		/*
+		 *	RFC1812 recommendation, if source is martian,
+		 *	the only hint is MAC header.
+		 */
+		printk(KERN_WARNING "martian source %u.%u.%u.%u from "
+			"%u.%u.%u.%u, on dev %s\n",
+			NIPQUAD(daddr), NIPQUAD(saddr), dev->name);
+		if (dev->hard_header_len) {
+			int i;
+			unsigned char *p = skb->mac.raw;
+			printk(KERN_WARNING "ll header: ");
+			for (i = 0; i < dev->hard_header_len; i++, p++) {
+				printk("%02x", *p);
+				if (i < (dev->hard_header_len - 1))
+					printk(":");
+			}
+			printk("\n");
+		}
+	}
+#endif
+}
+
+static inline int __mkroute_input(struct sk_buff *skb, 
+				  struct fib_result* res, 
+				  struct in_device *in_dev, 
+				  u32 daddr, u32 saddr, u32 tos, 
+				  struct rtable **result) 
+{
+
+	struct rtable *rth;
+	int err;
+	struct in_device *out_dev;
+	unsigned flags = 0;
+	u32 spec_dst, itag;
+
+	/* get a working reference to the output device */
+	out_dev = in_dev_get(FIB_RES_DEV(*res));
+	if (out_dev == NULL) {
+		if (net_ratelimit())
+			printk(KERN_CRIT "Bug in ip_route_input" \
+			       "_slow(). Please, report\n");
+		return -EINVAL;
+	}
+
+
+	err = fib_validate_source(saddr, daddr, tos, FIB_RES_OIF(*res), 
+				  in_dev->dev, &spec_dst, &itag);
+	if (err < 0) {
+		ip_handle_martian_source(in_dev->dev, in_dev, skb, daddr, 
+					 saddr);
+		
+		err = -EINVAL;
+		goto cleanup;
+	}
+
+	if (err)
+		flags |= RTCF_DIRECTSRC;
+
+	if (out_dev == in_dev && err && !(flags & (RTCF_NAT | RTCF_MASQ)) &&
+	    (IN_DEV_SHARED_MEDIA(out_dev) ||
+	     inet_addr_onlink(out_dev, saddr, FIB_RES_GW(*res))))
+		flags |= RTCF_DOREDIRECT;
+
+	if (skb->protocol != htons(ETH_P_IP)) {
+		/* Not IP (i.e. ARP). Do not create route, if it is
+		 * invalid for proxy arp. DNAT routes are always valid.
+		 */
+		if (out_dev == in_dev && !(flags & RTCF_DNAT)) {
+			err = -EINVAL;
+			goto cleanup;
+		}
+	}
+
+
+	rth = dst_alloc(&ipv4_dst_ops);
+	if (!rth) {
+		err = -ENOBUFS;
+		goto cleanup;
+	}
+
+	rth->u.dst.flags= DST_HOST;
+	if (in_dev->cnf.no_policy)
+		rth->u.dst.flags |= DST_NOPOLICY;
+	if (in_dev->cnf.no_xfrm)
+		rth->u.dst.flags |= DST_NOXFRM;
+	rth->fl.fl4_dst	= daddr;
+	rth->rt_dst	= daddr;
+	rth->fl.fl4_tos	= tos;
+#ifdef CONFIG_IP_ROUTE_FWMARK
+	rth->fl.fl4_fwmark= skb->nfmark;
+#endif
+	rth->fl.fl4_src	= saddr;
+	rth->rt_src	= saddr;
+	rth->rt_gateway	= daddr;
+	rth->rt_iif 	=
+		rth->fl.iif	= in_dev->dev->ifindex;
+	rth->u.dst.dev	= (out_dev)->dev;
+	dev_hold(rth->u.dst.dev);
+	rth->idev	= in_dev_get(rth->u.dst.dev);
+	rth->fl.oif 	= 0;
+	rth->rt_spec_dst= spec_dst;
+
+	rth->u.dst.input = ip_forward;
+	rth->u.dst.output = ip_output;
+
+	rt_set_nexthop(rth, res, itag);
+
+	rth->rt_flags = flags;
+
+	*result = rth;
+	err = 0;
+ cleanup:
+	/* release the working reference to the output device */
+	in_dev_put(out_dev);
+	return err;
+}						
+
+static inline int ip_mkroute_input_def(struct sk_buff *skb, 
+				       struct fib_result* res, 
+				       const struct flowi *fl,
+				       struct in_device *in_dev,
+				       u32 daddr, u32 saddr, u32 tos)
+{
+	struct rtable* rth;
+	int err;
+	unsigned hash;
+
+#ifdef CONFIG_IP_ROUTE_MULTIPATH
+	if (res->fi->fib_nhs > 1 && fl->oif == 0)
+		fib_select_multipath(fl, res);
+#endif
+
+	/* create a routing cache entry */
+	err = __mkroute_input(skb, res, in_dev, daddr, saddr, tos, &rth);
+	if (err)
+		return err;
+	atomic_set(&rth->u.dst.__refcnt, 1);
+
+	/* put it into the cache */
+	hash = rt_hash_code(daddr, saddr ^ (fl->iif << 5), tos);
+	return rt_intern_hash(hash, rth, (struct rtable**)&skb->dst);	
+}
+
+static inline int ip_mkroute_input(struct sk_buff *skb, 
+				   struct fib_result* res, 
+				   const struct flowi *fl,
+				   struct in_device *in_dev,
+				   u32 daddr, u32 saddr, u32 tos)
+{
+	return ip_mkroute_input_def(skb, res, fl, in_dev, daddr, saddr, tos);
+}
+
+
 /*
  *	NOTE. We drop all the packets that has local source
  *	addresses, because every properly looped back packet
@@ -1546,11 +1712,10 @@
  */
 
 static int ip_route_input_slow(struct sk_buff *skb, u32 daddr, u32 saddr,
-			u8 tos, struct net_device *dev)
+			       u8 tos, struct net_device *dev)
 {
 	struct fib_result res;
 	struct in_device *in_dev = in_dev_get(dev);
-	struct in_device *out_dev = NULL;
 	struct flowi fl = { .nl_u = { .ip4_u =
 				      { .daddr = daddr,
 					.saddr = saddr,
@@ -1574,8 +1739,6 @@
 	if (!in_dev)
 		goto out;
 
-	hash = rt_hash_code(daddr, saddr ^ (fl.iif << 5), tos);
-
 	/* Check for the most weird martians, which can be not detected
 	   by fib_lookup.
 	 */
@@ -1628,79 +1791,14 @@
 	if (res.type != RTN_UNICAST)
 		goto martian_destination;
 
-#ifdef CONFIG_IP_ROUTE_MULTIPATH
-	if (res.fi->fib_nhs > 1 && fl.oif == 0)
-		fib_select_multipath(&fl, &res);
-#endif
-	out_dev = in_dev_get(FIB_RES_DEV(res));
-	if (out_dev == NULL) {
-		if (net_ratelimit())
-			printk(KERN_CRIT "Bug in ip_route_input_slow(). "
-					 "Please, report\n");
-		goto e_inval;
-	}
-
-	err = fib_validate_source(saddr, daddr, tos, FIB_RES_OIF(res), dev,
-				  &spec_dst, &itag);
-	if (err < 0)
-		goto martian_source;
-
-	if (err)
-		flags |= RTCF_DIRECTSRC;
-
-	if (out_dev == in_dev && err && !(flags & (RTCF_NAT | RTCF_MASQ)) &&
-	    (IN_DEV_SHARED_MEDIA(out_dev) ||
-	     inet_addr_onlink(out_dev, saddr, FIB_RES_GW(res))))
-		flags |= RTCF_DOREDIRECT;
-
-	if (skb->protocol != htons(ETH_P_IP)) {
-		/* Not IP (i.e. ARP). Do not create route, if it is
-		 * invalid for proxy arp. DNAT routes are always valid.
-		 */
-		if (out_dev == in_dev && !(flags & RTCF_DNAT))
-			goto e_inval;
-	}
-
-	rth = dst_alloc(&ipv4_dst_ops);
-	if (!rth)
+	err = ip_mkroute_input(skb, &res, &fl, in_dev, daddr, saddr, tos);
+	if (err == -ENOBUFS)
 		goto e_nobufs;
-
-	atomic_set(&rth->u.dst.__refcnt, 1);
-	rth->u.dst.flags= DST_HOST;
-	if (in_dev->cnf.no_policy)
-		rth->u.dst.flags |= DST_NOPOLICY;
-	if (in_dev->cnf.no_xfrm)
-		rth->u.dst.flags |= DST_NOXFRM;
-	rth->fl.fl4_dst	= daddr;
-	rth->rt_dst	= daddr;
-	rth->fl.fl4_tos	= tos;
-#ifdef CONFIG_IP_ROUTE_FWMARK
-	rth->fl.fl4_fwmark= skb->nfmark;
-#endif
-	rth->fl.fl4_src	= saddr;
-	rth->rt_src	= saddr;
-	rth->rt_gateway	= daddr;
-	rth->rt_iif 	=
-	rth->fl.iif	= dev->ifindex;
-	rth->u.dst.dev	= out_dev->dev;
-	dev_hold(rth->u.dst.dev);
-	rth->idev	= in_dev_get(rth->u.dst.dev);
-	rth->fl.oif 	= 0;
-	rth->rt_spec_dst= spec_dst;
-
-	rth->u.dst.input = ip_forward;
-	rth->u.dst.output = ip_output;
-
-	rt_set_nexthop(rth, &res, itag);
-
-	rth->rt_flags = flags;
-
-intern:
-	err = rt_intern_hash(hash, rth, (struct rtable**)&skb->dst);
+	if (err == -EINVAL)
+		goto e_inval;
+	
 done:
 	in_dev_put(in_dev);
-	if (out_dev)
-		in_dev_put(out_dev);
 	if (free_res)
 		fib_res_put(&res);
 out:	return err;
@@ -1760,7 +1858,9 @@
 		rth->rt_flags 	&= ~RTCF_LOCAL;
 	}
 	rth->rt_type	= res.type;
-	goto intern;
+	hash = rt_hash_code(daddr, saddr ^ (fl.iif << 5), tos);
+	err = rt_intern_hash(hash, rth, (struct rtable**)&skb->dst);
+	goto done;
 
 no_route:
 	RT_CACHE_STAT_INC(in_no_route);
@@ -1788,30 +1888,7 @@
 	goto done;
 
 martian_source:
-
-	RT_CACHE_STAT_INC(in_martian_src);
-#ifdef CONFIG_IP_ROUTE_VERBOSE
-	if (IN_DEV_LOG_MARTIANS(in_dev) && net_ratelimit()) {
-		/*
-		 *	RFC1812 recommendation, if source is martian,
-		 *	the only hint is MAC header.
-		 */
-		printk(KERN_WARNING "martian source %u.%u.%u.%u from "
-			"%u.%u.%u.%u, on dev %s\n",
-			NIPQUAD(daddr), NIPQUAD(saddr), dev->name);
-		if (dev->hard_header_len) {
-			int i;
-			unsigned char *p = skb->mac.raw;
-			printk(KERN_WARNING "ll header: ");
-			for (i = 0; i < dev->hard_header_len; i++, p++) {
-				printk("%02x", *p);
-				if (i < (dev->hard_header_len - 1))
-					printk(":");
-			}
-			printk("\n");
-		}
-	}
-#endif
+	ip_handle_martian_source(dev, in_dev, skb, daddr, saddr);
 	goto e_inval;
 }
 
@@ -1882,13 +1959,166 @@
 	return ip_route_input_slow(skb, daddr, saddr, tos, dev);
 }
 
+static inline int __mkroute_output(struct rtable **result,
+				   struct fib_result* res, 
+				   const struct flowi *fl,
+				   const struct flowi *oldflp, 
+				   struct net_device *dev_out, 
+				   unsigned flags) 
+{
+	struct rtable *rth;
+	struct in_device *in_dev;
+	u32 tos = RT_FL_TOS(oldflp);
+	int err = 0;
+
+	if (LOOPBACK(fl->fl4_src) && !(dev_out->flags&IFF_LOOPBACK))
+		return -EINVAL;
+
+	if (fl->fl4_dst == 0xFFFFFFFF)
+		res->type = RTN_BROADCAST;
+	else if (MULTICAST(fl->fl4_dst))
+		res->type = RTN_MULTICAST;
+	else if (BADCLASS(fl->fl4_dst) || ZERONET(fl->fl4_dst))
+		return -EINVAL;
+
+	if (dev_out->flags & IFF_LOOPBACK)
+		flags |= RTCF_LOCAL;
+
+	/* get work reference to inet device */
+	in_dev = in_dev_get(dev_out);
+	if (!in_dev)
+		return -EINVAL;
+
+	if (res->type == RTN_BROADCAST) {
+		flags |= RTCF_BROADCAST | RTCF_LOCAL;
+		if (res->fi) {
+			fib_info_put(res->fi);
+			res->fi = NULL;
+		}
+	} else if (res->type == RTN_MULTICAST) {
+		flags |= RTCF_MULTICAST|RTCF_LOCAL;
+		if (!ip_check_mc(in_dev, oldflp->fl4_dst, oldflp->fl4_src, 
+				 oldflp->proto))
+			flags &= ~RTCF_LOCAL;
+		/* If multicast route do not exist use
+		   default one, but do not gateway in this case.
+		   Yes, it is hack.
+		 */
+		if (res->fi && res->prefixlen < 4) {
+			fib_info_put(res->fi);
+			res->fi = NULL;
+		}
+	}
+
+
+	rth = dst_alloc(&ipv4_dst_ops);
+	if (!rth) {
+		err = -ENOBUFS;
+		goto cleanup;
+	}		
+
+	rth->u.dst.flags= DST_HOST;
+	if (in_dev->cnf.no_xfrm)
+		rth->u.dst.flags |= DST_NOXFRM;
+	if (in_dev->cnf.no_policy)
+		rth->u.dst.flags |= DST_NOPOLICY;
+
+	rth->fl.fl4_dst	= oldflp->fl4_dst;
+	rth->fl.fl4_tos	= tos;
+	rth->fl.fl4_src	= oldflp->fl4_src;
+	rth->fl.oif	= oldflp->oif;
+#ifdef CONFIG_IP_ROUTE_FWMARK
+	rth->fl.fl4_fwmark= oldflp->fl4_fwmark;
+#endif
+	rth->rt_dst	= fl->fl4_dst;
+	rth->rt_src	= fl->fl4_src;
+	rth->rt_iif	= oldflp->oif ? : dev_out->ifindex;
+	/* get references to the devices that are to be hold by the routing 
+	   cache entry */
+	rth->u.dst.dev	= dev_out;
+	dev_hold(dev_out);
+	rth->idev	= in_dev_get(dev_out);
+	rth->rt_gateway = fl->fl4_dst;
+	rth->rt_spec_dst= fl->fl4_src;
+
+	rth->u.dst.output=ip_output;
+
+	RT_CACHE_STAT_INC(out_slow_tot);
+
+	if (flags & RTCF_LOCAL) {
+		rth->u.dst.input = ip_local_deliver;
+		rth->rt_spec_dst = fl->fl4_dst;
+	}
+	if (flags & (RTCF_BROADCAST | RTCF_MULTICAST)) {
+		rth->rt_spec_dst = fl->fl4_src;
+		if (flags & RTCF_LOCAL && 
+		    !(dev_out->flags & IFF_LOOPBACK)) {
+			rth->u.dst.output = ip_mc_output;
+			RT_CACHE_STAT_INC(out_slow_mc);
+		}
+#ifdef CONFIG_IP_MROUTE
+		if (res->type == RTN_MULTICAST) {
+			if (IN_DEV_MFORWARD(in_dev) &&
+			    !LOCAL_MCAST(oldflp->fl4_dst)) {
+				rth->u.dst.input = ip_mr_input;
+				rth->u.dst.output = ip_mc_output;
+			}
+		}
+#endif
+	}
+
+	rt_set_nexthop(rth, res, 0);
+
+	rth->rt_flags = flags;
+
+	*result = rth;
+ cleanup:
+	/* release work reference to inet device */
+	in_dev_put(in_dev);
+
+	return err;
+}
+
+static inline int ip_mkroute_output_def(struct rtable **rp,
+					struct fib_result* res,
+					const struct flowi *fl,
+					const struct flowi *oldflp,
+					struct net_device *dev_out,
+					unsigned flags)
+{
+	struct rtable *rth;
+	int err = __mkroute_output(&rth, res, fl, oldflp, dev_out, flags);
+	unsigned hash;
+	if (err == 0) {
+		u32 tos = RT_FL_TOS(oldflp);
+
+		atomic_set(&rth->u.dst.__refcnt, 1);
+		
+		hash = rt_hash_code(oldflp->fl4_dst, 
+				    oldflp->fl4_src ^ (oldflp->oif << 5), tos);
+		err = rt_intern_hash(hash, rth, rp);
+	}
+	
+	return err;
+}
+
+static inline int ip_mkroute_output(struct rtable** rp,
+				    struct fib_result* res,
+				    const struct flowi *fl,
+				    const struct flowi *oldflp,
+				    struct net_device *dev_out,
+				    unsigned flags)
+{
+	return ip_mkroute_output_def(rp, res, fl, oldflp, dev_out, flags);
+}
+
 /*
  * Major route resolver routine.
  */
 
 static int ip_route_output_slow(struct rtable **rp, const struct flowi *oldflp)
 {
-	u32 tos	= oldflp->fl4_tos & (IPTOS_RT_MASK | RTO_ONLINK);
+	u32 tos	= RT_FL_TOS(oldflp);
 	struct flowi fl = { .nl_u = { .ip4_u =
 				      { .daddr = oldflp->fl4_dst,
 					.saddr = oldflp->fl4_src,
@@ -1904,10 +2134,7 @@
 			    .oif = oldflp->oif };
 	struct fib_result res;
 	unsigned flags = 0;
-	struct rtable *rth;
 	struct net_device *dev_out = NULL;
-	struct in_device *in_dev = NULL;
-	unsigned hash;
 	int free_res = 0;
 	int err;
 
@@ -2067,116 +2294,13 @@
 	fl.oif = dev_out->ifindex;
 
 make_route:
-	if (LOOPBACK(fl.fl4_src) && !(dev_out->flags&IFF_LOOPBACK))
-		goto e_inval;
+	err = ip_mkroute_output(rp, &res, &fl, oldflp, dev_out, flags);
 
-	if (fl.fl4_dst == 0xFFFFFFFF)
-		res.type = RTN_BROADCAST;
-	else if (MULTICAST(fl.fl4_dst))
-		res.type = RTN_MULTICAST;
-	else if (BADCLASS(fl.fl4_dst) || ZERONET(fl.fl4_dst))
-		goto e_inval;
-
-	if (dev_out->flags & IFF_LOOPBACK)
-		flags |= RTCF_LOCAL;
-
-	in_dev = in_dev_get(dev_out);
-	if (!in_dev)
-		goto e_inval;
-
-	if (res.type == RTN_BROADCAST) {
-		flags |= RTCF_BROADCAST | RTCF_LOCAL;
-		if (res.fi) {
-			fib_info_put(res.fi);
-			res.fi = NULL;
-		}
-	} else if (res.type == RTN_MULTICAST) {
-		flags |= RTCF_MULTICAST|RTCF_LOCAL;
-		if (!ip_check_mc(in_dev, oldflp->fl4_dst, oldflp->fl4_src, oldflp->proto))
-			flags &= ~RTCF_LOCAL;
-		/* If multicast route do not exist use
-		   default one, but do not gateway in this case.
-		   Yes, it is hack.
-		 */
-		if (res.fi && res.prefixlen < 4) {
-			fib_info_put(res.fi);
-			res.fi = NULL;
-		}
-	}
-
-	rth = dst_alloc(&ipv4_dst_ops);
-	if (!rth)
-		goto e_nobufs;
-
-	atomic_set(&rth->u.dst.__refcnt, 1);
-	rth->u.dst.flags= DST_HOST;
-	if (in_dev->cnf.no_xfrm)
-		rth->u.dst.flags |= DST_NOXFRM;
-	if (in_dev->cnf.no_policy)
-		rth->u.dst.flags |= DST_NOPOLICY;
-	rth->fl.fl4_dst	= oldflp->fl4_dst;
-	rth->fl.fl4_tos	= tos;
-	rth->fl.fl4_src	= oldflp->fl4_src;
-	rth->fl.oif	= oldflp->oif;
-#ifdef CONFIG_IP_ROUTE_FWMARK
-	rth->fl.fl4_fwmark= oldflp->fl4_fwmark;
-#endif
-	rth->rt_dst	= fl.fl4_dst;
-	rth->rt_src	= fl.fl4_src;
-	rth->rt_iif	= oldflp->oif ? : dev_out->ifindex;
-	rth->u.dst.dev	= dev_out;
-	dev_hold(dev_out);
-	rth->idev	= in_dev_get(dev_out);
-	rth->rt_gateway = fl.fl4_dst;
-	rth->rt_spec_dst= fl.fl4_src;
-
-	rth->u.dst.output=ip_output;
-
-	RT_CACHE_STAT_INC(out_slow_tot);
-
-	if (flags & RTCF_LOCAL) {
-		rth->u.dst.input = ip_local_deliver;
-		rth->rt_spec_dst = fl.fl4_dst;
-	}
-	if (flags & (RTCF_BROADCAST | RTCF_MULTICAST)) {
-		rth->rt_spec_dst = fl.fl4_src;
-		if (flags & RTCF_LOCAL && !(dev_out->flags & IFF_LOOPBACK)) {
-			rth->u.dst.output = ip_mc_output;
-			RT_CACHE_STAT_INC(out_slow_mc);
-		}
-#ifdef CONFIG_IP_MROUTE
-		if (res.type == RTN_MULTICAST) {
-			if (IN_DEV_MFORWARD(in_dev) &&
-			    !LOCAL_MCAST(oldflp->fl4_dst)) {
-				rth->u.dst.input = ip_mr_input;
-				rth->u.dst.output = ip_mc_output;
-			}
-		}
-#endif
-	}
-
-	rt_set_nexthop(rth, &res, 0);
-	
-
-	rth->rt_flags = flags;
-
-	hash = rt_hash_code(oldflp->fl4_dst, oldflp->fl4_src ^ (oldflp->oif << 5), tos);
-	err = rt_intern_hash(hash, rth, rp);
-done:
 	if (free_res)
 		fib_res_put(&res);
 	if (dev_out)
 		dev_put(dev_out);
-	if (in_dev)
-		in_dev_put(in_dev);
 out:	return err;
-
-e_inval:
-	err = -EINVAL;
-	goto done;
-e_nobufs:
-	err = -ENOBUFS;
-	goto done;
 }
 
 int __ip_route_output_key(struct rtable **rp, const struct flowi *flp)
diff -Nru a/net/ipv4/syncookies.c b/net/ipv4/syncookies.c
--- a/net/ipv4/syncookies.c	2005-03-11 12:51:52 -08:00
+++ b/net/ipv4/syncookies.c	2005-03-11 12:51:52 -08:00
@@ -17,10 +17,87 @@
 #include <linux/tcp.h>
 #include <linux/slab.h>
 #include <linux/random.h>
+#include <linux/cryptohash.h>
 #include <linux/kernel.h>
 #include <net/tcp.h>
 
 extern int sysctl_tcp_syncookies;
+
+static __u32 syncookie_secret[2][16-3+SHA_DIGEST_WORDS];
+
+static __init int init_syncookies(void)
+{
+	get_random_bytes(syncookie_secret, sizeof(syncookie_secret));
+	return 0;
+}
+module_init(init_syncookies);
+
+#define COOKIEBITS 24	/* Upper bits store count */
+#define COOKIEMASK (((__u32)1 << COOKIEBITS) - 1)
+
+static u32 cookie_hash(u32 saddr, u32 daddr, u32 sport, u32 dport,
+		       u32 count, int c)
+{
+	__u32 tmp[16 + 5 + SHA_WORKSPACE_WORDS];
+
+	memcpy(tmp + 3, syncookie_secret[c], sizeof(syncookie_secret[c]));
+	tmp[0] = saddr;
+	tmp[1] = daddr;
+	tmp[2] = (sport << 16) + dport;
+	tmp[3] = count;
+	sha_transform(tmp + 16, (__u8 *)tmp, tmp + 16 + 5);
+
+	return tmp[17];
+}
+
+static __u32 secure_tcp_syn_cookie(__u32 saddr, __u32 daddr, __u16 sport,
+				   __u16 dport, __u32 sseq, __u32 count,
+				   __u32 data)
+{
+	/*
+	 * Compute the secure sequence number.
+	 * The output should be:
+   	 *   HASH(sec1,saddr,sport,daddr,dport,sec1) + sseq + (count * 2^24)
+	 *      + (HASH(sec2,saddr,sport,daddr,dport,count,sec2) % 2^24).
+	 * Where sseq is their sequence number and count increases every
+	 * minute by 1.
+	 * As an extra hack, we add a small "data" value that encodes the
+	 * MSS into the second hash value.
+	 */
+
+	return (cookie_hash(saddr, daddr, sport, dport, 0, 0) +
+		sseq + (count << COOKIEBITS) +
+		((cookie_hash(saddr, daddr, sport, dport, count, 1) + data)
+		 & COOKIEMASK));
+}
+
+/*
+ * This retrieves the small "data" value from the syncookie.
+ * If the syncookie is bad, the data returned will be out of
+ * range.  This must be checked by the caller.
+ *
+ * The count value used to generate the cookie must be within
+ * "maxdiff" if the current (passed-in) "count".  The return value
+ * is (__u32)-1 if this test fails.
+ */
+static __u32 check_tcp_syn_cookie(__u32 cookie, __u32 saddr, __u32 daddr,
+				  __u16 sport, __u16 dport, __u32 sseq,
+				  __u32 count, __u32 maxdiff)
+{
+	__u32 diff;
+
+	/* Strip away the layers from the cookie */
+	cookie -= cookie_hash(saddr, daddr, sport, dport, 0, 0) + sseq;
+
+	/* Cookie is now reduced to (count * 2^24) ^ (hash % 2^24) */
+	diff = (count - (cookie >> COOKIEBITS)) & ((__u32) - 1 >> COOKIEBITS);
+	if (diff >= maxdiff)
+		return (__u32)-1;
+
+	return (cookie -
+		cookie_hash(saddr, daddr, sport, dport, count - diff, 1))
+		& COOKIEMASK;	/* Leaving the data behind */
+}
 
 /* 
  * This table has to be sorted and terminated with (__u16)-1.
diff -Nru a/net/ipv4/tcp.c b/net/ipv4/tcp.c
--- a/net/ipv4/tcp.c	2005-03-11 12:51:42 -08:00
+++ b/net/ipv4/tcp.c	2005-03-11 12:51:42 -08:00
@@ -598,6 +598,7 @@
 	TCP_SKB_CB(skb)->end_seq = tp->write_seq;
 	TCP_SKB_CB(skb)->flags = TCPCB_FLAG_ACK;
 	TCP_SKB_CB(skb)->sacked = 0;
+	skb_header_release(skb);
 	__skb_queue_tail(&sk->sk_write_queue, skb);
 	sk_charge_skb(sk, skb);
 	if (!sk->sk_send_head)
diff -Nru a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
--- a/net/ipv4/tcp_ipv4.c	2005-03-11 12:51:42 -08:00
+++ b/net/ipv4/tcp_ipv4.c	2005-03-11 12:51:42 -08:00
@@ -831,7 +831,6 @@
 	/* OK, now commit destination to socket.  */
 	__sk_dst_set(sk, &rt->u.dst);
 	tcp_v4_setup_caps(sk, &rt->u.dst);
-	tp->ext2_header_len = rt->u.dst.header_len;
 
 	if (!tp->write_seq)
 		tp->write_seq = secure_tcp_sequence_number(inet->saddr,
@@ -941,10 +940,10 @@
 	/* Something is about to be wrong... Remember soft error
 	 * for the case, if this connection will not able to recover.
 	 */
-	if (mtu < dst_pmtu(dst) && ip_dont_fragment(sk, dst))
+	if (mtu < dst_mtu(dst) && ip_dont_fragment(sk, dst))
 		sk->sk_err_soft = EMSGSIZE;
 
-	mtu = dst_pmtu(dst);
+	mtu = dst_mtu(dst);
 
 	if (inet->pmtudisc != IP_PMTUDISC_DONT &&
 	    tp->pmtu_cookie > mtu) {
@@ -1578,10 +1577,9 @@
 	newtp->ext_header_len = 0;
 	if (newinet->opt)
 		newtp->ext_header_len = newinet->opt->optlen;
-	newtp->ext2_header_len = dst->header_len;
 	newinet->id = newtp->write_seq ^ jiffies;
 
-	tcp_sync_mss(newsk, dst_pmtu(dst));
+	tcp_sync_mss(newsk, dst_mtu(dst));
 	newtp->advmss = dst_metric(dst, RTAX_ADVMSS);
 	tcp_initialize_rcv_mss(newsk);
 
@@ -1877,7 +1875,6 @@
 
 	__sk_dst_set(sk, &rt->u.dst);
 	tcp_v4_setup_caps(sk, &rt->u.dst);
-	tcp_sk(sk)->ext2_header_len = rt->u.dst.header_len;
 
 	new_saddr = rt->rt_src;
 
@@ -1937,7 +1934,6 @@
 	if (!err) {
 		__sk_dst_set(sk, &rt->u.dst);
 		tcp_v4_setup_caps(sk, &rt->u.dst);
-		tcp_sk(sk)->ext2_header_len = rt->u.dst.header_len;
 		return 0;
 	}
 
@@ -2663,4 +2659,5 @@
 EXPORT_SYMBOL(sysctl_local_port_range);
 EXPORT_SYMBOL(sysctl_max_syn_backlog);
 EXPORT_SYMBOL(sysctl_tcp_low_latency);
+EXPORT_SYMBOL(sysctl_tcp_tw_reuse);
 
diff -Nru a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
--- a/net/ipv4/tcp_output.c	2005-03-11 12:51:52 -08:00
+++ b/net/ipv4/tcp_output.c	2005-03-11 12:51:52 -08:00
@@ -400,6 +400,7 @@
 
 	/* Advance write_seq and place onto the write_queue. */
 	tp->write_seq = TCP_SKB_CB(skb)->end_seq;
+	skb_header_release(skb);
 	__skb_queue_tail(&sk->sk_write_queue, skb);
 	sk_charge_skb(sk, skb);
 
@@ -631,12 +632,8 @@
 unsigned int tcp_sync_mss(struct sock *sk, u32 pmtu)
 {
 	struct tcp_sock *tp = tcp_sk(sk);
-	struct dst_entry *dst = __sk_dst_get(sk);
 	int mss_now;
 
-	if (dst && dst->ops->get_mss)
-		pmtu = dst->ops->get_mss(dst, pmtu);
-
 	/* Calculate base mss without TCP options:
 	   It is MMS_S - sizeof(tcphdr) of rfc1122
 	 */
@@ -647,7 +644,7 @@
 		mss_now = tp->rx_opt.mss_clamp;
 
 	/* Now subtract optional transport overhead */
-	mss_now -= tp->ext_header_len + tp->ext2_header_len;
+	mss_now -= tp->ext_header_len;
 
 	/* Then reserve room for full set of TCP options and 8 bytes of data */
 	if (mss_now < 48)
@@ -683,9 +680,8 @@
 
 	mss_now = tp->mss_cache_std;
 	if (dst) {
-		u32 mtu = dst_pmtu(dst);
-		if (mtu != tp->pmtu_cookie ||
-		    tp->ext2_header_len != dst->header_len)
+		u32 mtu = dst_mtu(dst);
+		if (mtu != tp->pmtu_cookie)
 			mss_now = tcp_sync_mss(sk, mtu);
 	}
 
@@ -697,8 +693,7 @@
 		unsigned int large_mss, factor, limit;
 
 		large_mss = 65535 - tp->af_specific->net_header_len -
-			tp->ext_header_len - tp->ext2_header_len -
-			tp->tcp_header_len;
+			tp->ext_header_len - tp->tcp_header_len;
 
 		if (tp->max_window && large_mss > (tp->max_window>>1))
 			large_mss = max((tp->max_window>>1),
@@ -1340,6 +1335,7 @@
 			if (nskb == NULL)
 				return -ENOMEM;
 			__skb_unlink(skb, &sk->sk_write_queue);
+			skb_header_release(nskb);
 			__skb_queue_head(&sk->sk_write_queue, nskb);
 			sk_stream_free_skb(sk, skb);
 			sk_charge_skb(sk, nskb);
@@ -1442,7 +1438,7 @@
 	if (tp->rx_opt.user_mss)
 		tp->rx_opt.mss_clamp = tp->rx_opt.user_mss;
 	tp->max_window = 0;
-	tcp_sync_mss(sk, dst_pmtu(dst));
+	tcp_sync_mss(sk, dst_mtu(dst));
 
 	if (!tp->window_clamp)
 		tp->window_clamp = dst_metric(dst, RTAX_WINDOW);
@@ -1506,6 +1502,7 @@
 	/* Send it off. */
 	TCP_SKB_CB(buff)->when = tcp_time_stamp;
 	tp->retrans_stamp = TCP_SKB_CB(buff)->when;
+	skb_header_release(buff);
 	__skb_queue_tail(&sk->sk_write_queue, buff);
 	sk_charge_skb(sk, buff);
 	tp->packets_out += tcp_skb_pcount(buff);
diff -Nru a/net/ipv4/tcp_timer.c b/net/ipv4/tcp_timer.c
--- a/net/ipv4/tcp_timer.c	2005-03-11 12:51:51 -08:00
+++ b/net/ipv4/tcp_timer.c	2005-03-11 12:51:51 -08:00
@@ -38,6 +38,7 @@
 
 #ifdef TCP_DEBUG
 const char tcp_timer_bug_msg[] = KERN_DEBUG "tcpbug: unknown timer value\n";
+EXPORT_SYMBOL(tcp_timer_bug_msg);
 #endif
 
 /*
diff -Nru a/net/ipv4/xfrm4_output.c b/net/ipv4/xfrm4_output.c
--- a/net/ipv4/xfrm4_output.c	2005-03-11 12:51:42 -08:00
+++ b/net/ipv4/xfrm4_output.c	2005-03-11 12:51:42 -08:00
@@ -82,7 +82,7 @@
 		goto out;
 
 	dst = skb->dst;
-	mtu = dst_pmtu(dst) - dst->header_len - dst->trailer_len;
+	mtu = dst_mtu(dst);
 	if (skb->len > mtu) {
 		icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, htonl(mtu));
 		ret = -EMSGSIZE;
@@ -116,7 +116,7 @@
 
 	xfrm4_encap(skb);
 
-	err = x->type->output(skb);
+	err = x->type->output(x, skb);
 	if (err)
 		goto error;
 
diff -Nru a/net/ipv4/xfrm4_policy.c b/net/ipv4/xfrm4_policy.c
--- a/net/ipv4/xfrm4_policy.c	2005-03-11 12:51:48 -08:00
+++ b/net/ipv4/xfrm4_policy.c	2005-03-11 12:51:48 -08:00
@@ -22,26 +22,6 @@
 	return __ip_route_output_key((struct rtable**)dst, fl);
 }
 
-/* Check that the bundle accepts the flow and its components are
- * still valid.
- */
-
-static int __xfrm4_bundle_ok(struct xfrm_dst *xdst, struct flowi *fl)
-{
-	do {
-		if (xdst->u.dst.ops != &xfrm4_dst_ops)
-			return 1;
-
-		if (!xfrm_selector_match(&xdst->u.dst.xfrm->sel, fl, AF_INET))
-			return 0;
-		if (xdst->u.dst.xfrm->km.state != XFRM_STATE_VALID ||
-		    xdst->u.dst.path->obsolete > 0)
-			return 0;
-		xdst = (struct xfrm_dst*)xdst->u.dst.child;
-	} while (xdst);
-	return 0;
-}
-
 static struct dst_entry *
 __xfrm4_find_bundle(struct flowi *fl, struct xfrm_policy *policy)
 {
@@ -53,7 +33,7 @@
 		if (xdst->u.rt.fl.oif == fl->oif &&	/*XXX*/
 		    xdst->u.rt.fl.fl4_dst == fl->fl4_dst &&
 	    	    xdst->u.rt.fl.fl4_src == fl->fl4_src &&
-		    __xfrm4_bundle_ok(xdst, fl)) {
+		    xfrm_bundle_ok(xdst, fl, AF_INET)) {
 			dst_clone(dst);
 			break;
 		}
@@ -75,18 +55,30 @@
 	struct rtable *rt = rt0;
 	u32 remote = fl->fl4_dst;
 	u32 local  = fl->fl4_src;
+	struct flowi fl_tunnel = {
+		.nl_u = {
+			.ip4_u = {
+				.saddr = local,
+				.daddr = remote
+			}
+		}
+	};
 	int i;
 	int err;
 	int header_len = 0;
 	int trailer_len = 0;
 
 	dst = dst_prev = NULL;
+	dst_hold(&rt->u.dst);
 
 	for (i = 0; i < nx; i++) {
 		struct dst_entry *dst1 = dst_alloc(&xfrm4_dst_ops);
+		struct xfrm_dst *xdst;
+		int tunnel = 0;
 
 		if (unlikely(dst1 == NULL)) {
 			err = -ENOBUFS;
+			dst_release(&rt->u.dst);
 			goto error;
 		}
 
@@ -97,30 +89,40 @@
 			dst1->flags |= DST_NOHASH;
 			dst_clone(dst1);
 		}
+
+		xdst = (struct xfrm_dst *)dst1;
+		xdst->route = &rt->u.dst;
+
+		dst1->next = dst_prev;
 		dst_prev = dst1;
 		if (xfrm[i]->props.mode) {
 			remote = xfrm[i]->id.daddr.a4;
 			local  = xfrm[i]->props.saddr.a4;
+			tunnel = 1;
 		}
 		header_len += xfrm[i]->props.header_len;
 		trailer_len += xfrm[i]->props.trailer_len;
-	}
 
-	if (remote != fl->fl4_dst) {
-		struct flowi fl_tunnel = { .nl_u = { .ip4_u =
-						     { .daddr = remote,
-						       .saddr = local }
-					           }
-				         };
-		err = xfrm_dst_lookup((struct xfrm_dst**)&rt, &fl_tunnel, AF_INET);
-		if (err)
-			goto error;
-	} else {
-		dst_hold(&rt->u.dst);
+		if (tunnel) {
+			fl_tunnel.fl4_src = local;
+			fl_tunnel.fl4_dst = remote;
+			err = xfrm_dst_lookup((struct xfrm_dst **)&rt,
+					      &fl_tunnel, AF_INET);
+			if (err)
+				goto error;
+		} else
+			dst_hold(&rt->u.dst);
 	}
+
 	dst_prev->child = &rt->u.dst;
+	dst->path = &rt->u.dst;
+
+	*dst_p = dst;
+	dst = dst_prev;
+
+	dst_prev = *dst_p;
 	i = 0;
-	for (dst_prev = dst; dst_prev != &rt->u.dst; dst_prev = dst_prev->child) {
+	for (; dst_prev != &rt->u.dst; dst_prev = dst_prev->child) {
 		struct xfrm_dst *x = (struct xfrm_dst*)dst_prev;
 		x->u.rt.fl = *fl;
 
@@ -133,8 +135,7 @@
 		dst_prev->lastuse	= jiffies;
 		dst_prev->header_len	= header_len;
 		dst_prev->trailer_len	= trailer_len;
-		memcpy(&dst_prev->metrics, &rt->u.dst.metrics, sizeof(dst_prev->metrics));
-		dst_prev->path		= &rt->u.dst;
+		memcpy(&dst_prev->metrics, &x->route->metrics, sizeof(dst_prev->metrics));
 
 		/* Copy neighbout for reachability confirmation */
 		dst_prev->neighbour	= neigh_clone(rt->u.dst.neighbour);
@@ -154,7 +155,8 @@
 		header_len -= x->u.dst.xfrm->props.header_len;
 		trailer_len -= x->u.dst.xfrm->props.trailer_len;
 	}
-	*dst_p = dst;
+
+	xfrm_init_pmtu(dst);
 	return 0;
 
 error:
@@ -235,10 +237,8 @@
 
 static void xfrm4_update_pmtu(struct dst_entry *dst, u32 mtu)
 {
-	struct dst_entry *path = dst->path;
-
-	if (mtu < 68 + dst->header_len)
-		return;
+	struct xfrm_dst *xdst = (struct xfrm_dst *)dst;
+	struct dst_entry *path = xdst->route;
 
 	path->ops->update_pmtu(path, mtu);
 }
diff -Nru a/net/ipv4/xfrm4_state.c b/net/ipv4/xfrm4_state.c
--- a/net/ipv4/xfrm4_state.c	2005-03-11 12:51:41 -08:00
+++ b/net/ipv4/xfrm4_state.c	2005-03-11 12:51:41 -08:00
@@ -20,9 +20,9 @@
 {
 	x->sel.daddr.a4 = fl->fl4_dst;
 	x->sel.saddr.a4 = fl->fl4_src;
-	x->sel.dport = fl->fl_ip_dport;
+	x->sel.dport = xfrm_flowi_dport(fl);
 	x->sel.dport_mask = ~0;
-	x->sel.sport = fl->fl_ip_sport;
+	x->sel.sport = xfrm_flowi_sport(fl);
 	x->sel.sport_mask = ~0;
 	x->sel.prefixlen_d = 32;
 	x->sel.prefixlen_s = 32;
diff -Nru a/net/ipv4/xfrm4_tunnel.c b/net/ipv4/xfrm4_tunnel.c
--- a/net/ipv4/xfrm4_tunnel.c	2005-03-11 12:51:41 -08:00
+++ b/net/ipv4/xfrm4_tunnel.c	2005-03-11 12:51:41 -08:00
@@ -9,7 +9,7 @@
 #include <net/ip.h>
 #include <net/protocol.h>
 
-static int ipip_output(struct sk_buff *skb)
+static int ipip_output(struct xfrm_state *x, struct sk_buff *skb)
 {
 	struct iphdr *iph;
 	
diff -Nru a/net/ipv6/README b/net/ipv6/README
--- a/net/ipv6/README	2005-03-11 12:51:42 -08:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,8 +0,0 @@
-To join in the work on Linux IPv6 send mail to:
-
-        majordomo@oss.sgi.com
-
-and in the body of the message include:
-
-subscribe netdev
-
diff -Nru a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
--- a/net/ipv6/addrconf.c	2005-03-11 12:51:51 -08:00
+++ b/net/ipv6/addrconf.c	2005-03-11 12:51:51 -08:00
@@ -391,7 +391,9 @@
 		ndev->tstamp = jiffies;
 #ifdef CONFIG_SYSCTL
 		neigh_sysctl_register(dev, ndev->nd_parms, NET_IPV6, 
-			NET_IPV6_NEIGH, "ipv6", &ndisc_ifinfo_sysctl_change);
+				      NET_IPV6_NEIGH, "ipv6",
+				      &ndisc_ifinfo_sysctl_change,
+				      NULL);
 		addrconf_sysctl_register(ndev, &ndev->cnf);
 #endif
 	}
@@ -589,6 +591,8 @@
 	struct inet6_ifaddr *ifa, **ifap;
 	struct inet6_dev *idev = ifp->idev;
 	int hash;
+	int deleted = 0, onlink = 0;
+	unsigned long expires = jiffies;
 
 	hash = ipv6_addr_hash(&ifp->addr);
 
@@ -631,7 +635,31 @@
 			*ifap = ifa->if_next;
 			__in6_ifa_put(ifp);
 			ifa->if_next = NULL;
-			break;
+			if (!(ifp->flags & IFA_F_PERMANENT) || onlink > 0)
+				break;
+			deleted = 1;
+		} else if (ifp->flags & IFA_F_PERMANENT) {
+			if (ipv6_prefix_equal(&ifa->addr, &ifp->addr,
+					      ifp->prefix_len)) {
+				if (ifa->flags & IFA_F_PERMANENT) {
+					onlink = 1;
+					if (deleted)
+						break;
+				} else {
+					unsigned long lifetime;
+
+					if (!onlink)
+						onlink = -1;
+
+					spin_lock(&ifa->lock);
+					lifetime = min_t(unsigned long,
+							 ifa->valid_lft, 0x7fffffffUL/HZ);
+					if (time_before(expires,
+							ifa->tstamp + lifetime * HZ))
+						expires = ifa->tstamp + lifetime * HZ;
+					spin_unlock(&ifa->lock);
+				}
+			}
 		}
 	}
 	write_unlock_bh(&idev->lock);
@@ -642,6 +670,40 @@
 
 	addrconf_del_timer(ifp);
 
+	/*
+	 * Purge or update corresponding prefix
+	 *
+	 * 1) we don't purge prefix here if address was not permanent.
+	 *    prefix is managed by its own lifetime.
+	 * 2) if there're no addresses, delete prefix.
+	 * 3) if there're still other permanent address(es),
+	 *    corresponding prefix is still permanent.
+	 * 4) otherwise, update prefix lifetime to the
+	 *    longest valid lifetime among the corresponding
+	 *    addresses on the device.
+	 *    Note: subsequent RA will update lifetime.
+	 *
+	 * --yoshfuji
+	 */
+	if ((ifp->flags & IFA_F_PERMANENT) && onlink < 1) {
+		struct in6_addr prefix;
+		struct rt6_info *rt;
+
+		ipv6_addr_prefix(&prefix, &ifp->addr, ifp->prefix_len);
+		rt = rt6_lookup(&prefix, NULL, ifp->idev->dev->ifindex, 1);
+
+		if (rt && ((rt->rt6i_flags & (RTF_GATEWAY | RTF_DEFAULT)) == 0)) {
+			if (onlink == 0) {
+				ip6_del_rt(rt, NULL, NULL);
+				rt = NULL;
+			} else if (!(rt->rt6i_flags & RTF_EXPIRES)) {
+				rt->rt6i_expires = expires;
+				rt->rt6i_flags |= RTF_EXPIRES;
+			}
+		}
+		dst_release(&rt->u.dst);
+	}
+
 	in6_ifa_put(ifp);
 }
 
@@ -1982,7 +2044,10 @@
 		if (idev) {
 			addrconf_sysctl_unregister(&idev->cnf);
 			neigh_sysctl_unregister(idev->nd_parms);
-			neigh_sysctl_register(dev, idev->nd_parms, NET_IPV6, NET_IPV6_NEIGH, "ipv6", &ndisc_ifinfo_sysctl_change);
+			neigh_sysctl_register(dev, idev->nd_parms,
+					      NET_IPV6, NET_IPV6_NEIGH, "ipv6",
+					      &ndisc_ifinfo_sysctl_change,
+					      NULL);
 			addrconf_sysctl_register(idev, &idev->cnf);
 		}
 #endif
@@ -2008,6 +2073,9 @@
 
 	ASSERT_RTNL();
 
+	if (dev == &loopback_dev && how == 1)
+		how = 0;
+
 	rt6_ifdown(dev);
 	neigh_ifdown(&nd_tbl, dev);
 
@@ -3147,7 +3215,7 @@
 static struct addrconf_sysctl_table
 {
 	struct ctl_table_header *sysctl_header;
-	ctl_table addrconf_vars[18];
+	ctl_table addrconf_vars[__NET_IPV6_MAX];
 	ctl_table addrconf_dev[2];
 	ctl_table addrconf_conf_dir[2];
 	ctl_table addrconf_proto_dir[2];
@@ -3438,8 +3506,10 @@
  *	Init / cleanup code
  */
 
-void __init addrconf_init(void)
+int __init addrconf_init(void)
 {
+	int err = 0;
+
 	/* The addrconf netdev notifier requires that loopback_dev
 	 * has it's ipv6 private information allocated and setup
 	 * before it can bring up and give link-local addresses
@@ -3453,15 +3523,17 @@
 	 * first, then loopback_dev, which cases all the non-loopback_dev
 	 * devices to fail to get a link-local address.
 	 *
-	 * So, as a temporary fix, register loopback_dev first by hand.
+	 * So, as a temporary fix, allocate the ipv6 structure for
+	 * loopback_dev first by hand.
 	 * Longer term, all of the dependencies ipv6 has upon the loopback
 	 * device and it being up should be removed.
 	 */
 	rtnl_lock();
-	addrconf_notify(&ipv6_dev_notf, NETDEV_REGISTER, &loopback_dev);
-	if (loopback_dev.flags & IFF_UP)
-		addrconf_notify(&ipv6_dev_notf, NETDEV_UP, &loopback_dev);
+	if (!ipv6_add_dev(&loopback_dev))
+		err = -ENOMEM;
 	rtnl_unlock();
+	if (err)
+		return err;
 
 	register_netdevice_notifier(&ipv6_dev_notf);
 
@@ -3479,6 +3551,8 @@
 		register_sysctl_table(addrconf_sysctl.addrconf_root_dir, 0);
 	addrconf_sysctl_register(NULL, &ipv6_devconf_dflt);
 #endif
+
+	return 0;
 }
 
 void __exit addrconf_cleanup(void)
@@ -3507,6 +3581,7 @@
 			continue;
 		addrconf_ifdown(dev, 1);
 	}
+	addrconf_ifdown(&loopback_dev, 2);
 
 	/*
 	 *	Check hash table.
diff -Nru a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
--- a/net/ipv6/af_inet6.c	2005-03-11 12:51:46 -08:00
+++ b/net/ipv6/af_inet6.c	2005-03-11 12:51:46 -08:00
@@ -784,7 +784,9 @@
 	ipv6_packet_init();
 	ip6_route_init();
 	ip6_flowlabel_init();
-	addrconf_init();
+	err = addrconf_init();
+	if (err)
+		goto addrconf_fail;
 	sit_init();
 
 	/* Init v6 extension headers. */
@@ -800,7 +802,12 @@
 out:
 	return err;
 
+addrconf_fail:
+	ip6_flowlabel_cleanup();
+	ip6_route_cleanup();
+	ipv6_packet_cleanup();
 #ifdef CONFIG_PROC_FS
+	if6_proc_exit();
 proc_if6_fail:
 	ac6_proc_exit();
 proc_anycast6_fail:
@@ -812,8 +819,8 @@
 proc_tcp6_fail:
 	raw6_proc_exit();
 proc_raw6_fail:
-	igmp6_cleanup();
 #endif
+	igmp6_cleanup();
 igmp_fail:
 	ndisc_cleanup();
 ndisc_fail:
diff -Nru a/net/ipv6/ah6.c b/net/ipv6/ah6.c
--- a/net/ipv6/ah6.c	2005-03-11 12:51:52 -08:00
+++ b/net/ipv6/ah6.c	2005-03-11 12:51:52 -08:00
@@ -154,12 +154,10 @@
 	return 0;
 }
 
-static int ah6_output(struct sk_buff *skb)
+static int ah6_output(struct xfrm_state *x, struct sk_buff *skb)
 {
 	int err;
 	int extlen;
-	struct dst_entry *dst = skb->dst;
-	struct xfrm_state *x  = dst->xfrm;
 	struct ipv6hdr *top_iph;
 	struct ip_auth_hdr *ah;
 	struct ah_data *ahp;
diff -Nru a/net/ipv6/anycast.c b/net/ipv6/anycast.c
--- a/net/ipv6/anycast.c	2005-03-11 12:51:52 -08:00
+++ b/net/ipv6/anycast.c	2005-03-11 12:51:52 -08:00
@@ -48,32 +48,6 @@
 /* Big ac list lock for all the sockets */
 static DEFINE_RWLOCK(ipv6_sk_ac_lock);
 
-/* XXX ip6_addr_match() and ip6_onlink() really belong in net/core.c */
-
-static int
-ip6_addr_match(struct in6_addr *addr1, struct in6_addr *addr2, int prefix)
-{
-	__u32	mask;
-	int	i;
-
-	if (prefix > 128 || prefix < 0)
-		return 0;
-	if (prefix == 0)
-		return 1;
-	for (i=0; i<4; ++i) {
-		if (prefix >= 32)
-			mask = ~0;
-		else
-			mask = htonl(~0 << (32 - prefix));
-		if ((addr1->s6_addr32[i] ^ addr2->s6_addr32[i]) & mask)
-			return 0;
-		prefix -= 32;
-		if (prefix <= 0)
-			break;
-	}
-	return 1;
-}
-
 static int
 ip6_onlink(struct in6_addr *addr, struct net_device *dev)
 {
@@ -87,8 +61,8 @@
 	if (idev) {
 		read_lock_bh(&idev->lock);
 		for (ifa=idev->addr_list; ifa; ifa=ifa->if_next) {
-			onlink = ip6_addr_match(addr, &ifa->addr,
-					ifa->prefix_len);
+			onlink = ipv6_prefix_equal(addr, &ifa->addr,
+						   ifa->prefix_len);
 			if (onlink)
 				break;
 		}
diff -Nru a/net/ipv6/esp6.c b/net/ipv6/esp6.c
--- a/net/ipv6/esp6.c	2005-03-11 12:51:47 -08:00
+++ b/net/ipv6/esp6.c	2005-03-11 12:51:47 -08:00
@@ -37,12 +37,10 @@
 #include <net/ipv6.h>
 #include <linux/icmpv6.h>
 
-static int esp6_output(struct sk_buff *skb)
+static int esp6_output(struct xfrm_state *x, struct sk_buff *skb)
 {
 	int err;
 	int hdr_len;
-	struct dst_entry *dst = skb->dst;
-	struct xfrm_state *x  = dst->xfrm;
 	struct ipv6hdr *top_iph;
 	struct ipv6_esp_hdr *esph;
 	struct crypto_tfm *tfm;
diff -Nru a/net/ipv6/icmp.c b/net/ipv6/icmp.c
--- a/net/ipv6/icmp.c	2005-03-11 12:51:42 -08:00
+++ b/net/ipv6/icmp.c	2005-03-11 12:51:42 -08:00
@@ -381,6 +381,8 @@
 		hlimit = np->hop_limit;
 	if (hlimit < 0)
 		hlimit = dst_metric(dst, RTAX_HOPLIMIT);
+	if (hlimit < 0)
+		hlimit = ipv6_get_hoplimit(dst->dev);
 
 	msg.skb = skb;
 	msg.offset = skb->nh.raw - skb->data;
@@ -467,6 +469,8 @@
 		hlimit = np->hop_limit;
 	if (hlimit < 0)
 		hlimit = dst_metric(dst, RTAX_HOPLIMIT);
+	if (hlimit < 0)
+		hlimit = ipv6_get_hoplimit(dst->dev);
 
 	idev = in6_dev_get(skb->dev);
 
diff -Nru a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c
--- a/net/ipv6/ip6_fib.c	2005-03-11 12:51:50 -08:00
+++ b/net/ipv6/ip6_fib.c	2005-03-11 12:51:50 -08:00
@@ -117,36 +117,6 @@
  */
 
 /*
- *	compare "prefix length" bits of an address
- */
-
-static __inline__ int addr_match(void *token1, void *token2, int prefixlen)
-{
-	__u32 *a1 = token1;
-	__u32 *a2 = token2;
-	int pdw;
-	int pbi;
-
-	pdw = prefixlen >> 5;	  /* num of whole __u32 in prefix */
-	pbi = prefixlen &  0x1f;  /* num of bits in incomplete u32 in prefix */
-
-	if (pdw)
-		if (memcmp(a1, a2, pdw << 2))
-			return 0;
-
-	if (pbi) {
-		__u32 mask;
-
-		mask = htonl((0xffffffff) << (32 - pbi));
-
-		if ((a1[pdw] ^ a2[pdw]) & mask)
-			return 0;
-	}
-
-	return 1;
-}
-
-/*
  *	test bit
  */
 
@@ -261,7 +231,7 @@
 		 *	Prefix match
 		 */
 		if (plen < fn->fn_bit ||
-		    !addr_match(&key->addr, addr, fn->fn_bit))
+		    !ipv6_prefix_equal(&key->addr, addr, fn->fn_bit))
 			goto insert_above;
 		
 		/*
@@ -667,7 +637,7 @@
 			key = (struct rt6key *) ((u8 *) fn->leaf +
 						 args->offset);
 
-			if (addr_match(&key->addr, args->addr, key->plen))
+			if (ipv6_prefix_equal(&key->addr, args->addr, key->plen))
 				return fn;
 		}
 
@@ -718,7 +688,7 @@
 		 *	Prefix match
 		 */
 		if (plen < fn->fn_bit ||
-		    !addr_match(&key->addr, addr, fn->fn_bit))
+		    !ipv6_prefix_equal(&key->addr, addr, fn->fn_bit))
 			return NULL;
 
 		if (plen == fn->fn_bit)
@@ -1211,7 +1181,7 @@
 {
 	if (dummy != ~0UL) {
 		spin_lock_bh(&fib6_gc_lock);
-		gc_args.timeout = (int)dummy;
+		gc_args.timeout = dummy ? (int)dummy : ip6_rt_gc_interval;
 	} else {
 		local_bh_disable();
 		if (!spin_trylock(&fib6_gc_lock)) {
diff -Nru a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c
--- a/net/ipv6/ip6_input.c	2005-03-11 12:51:47 -08:00
+++ b/net/ipv6/ip6_input.c	2005-03-11 12:51:47 -08:00
@@ -95,15 +95,11 @@
 	if (pkt_len || hdr->nexthdr != NEXTHDR_HOP) {
 		if (pkt_len + sizeof(struct ipv6hdr) > skb->len)
 			goto truncated;
-		if (pkt_len + sizeof(struct ipv6hdr) < skb->len) {
-			if (__pskb_trim(skb, pkt_len + sizeof(struct ipv6hdr))){
-				IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS);
-				goto drop;
-			}
-			hdr = skb->nh.ipv6h;
-			if (skb->ip_summed == CHECKSUM_HW)
-				skb->ip_summed = CHECKSUM_NONE;
+		if (pskb_trim_rcsum(skb, pkt_len + sizeof(struct ipv6hdr))) {
+			IP6_INC_STATS_BH(IPSTATS_MIB_INHDRERRORS);
+			goto drop;
 		}
+		hdr = skb->nh.ipv6h;
 	}
 
 	if (hdr->nexthdr == NEXTHDR_HOP) {
@@ -138,7 +134,6 @@
 	unsigned int nhoff;
 	int nexthdr;
 	u8 hash;
-	int cksum_sub = 0;
 
 	skb->h.raw = skb->nh.raw + sizeof(struct ipv6hdr);
 
@@ -173,11 +168,8 @@
 		if (ipprot->flags & INET6_PROTO_FINAL) {
 			struct ipv6hdr *hdr;	
 
-			if (!cksum_sub && skb->ip_summed == CHECKSUM_HW) {
-				skb->csum = csum_sub(skb->csum,
-						     csum_partial(skb->nh.raw, skb->h.raw-skb->nh.raw, 0));
-				cksum_sub++;
-			}
+			skb_postpull_rcsum(skb, skb->nh.raw,
+					   skb->h.raw - skb->nh.raw);
 			hdr = skb->nh.ipv6h;
 			if (ipv6_addr_is_multicast(&hdr->daddr) &&
 			    !ipv6_chk_mcast_addr(skb->dev, &hdr->daddr,
diff -Nru a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
--- a/net/ipv6/ip6_output.c	2005-03-11 12:51:41 -08:00
+++ b/net/ipv6/ip6_output.c	2005-03-11 12:51:41 -08:00
@@ -147,7 +147,7 @@
 
 int ip6_output(struct sk_buff *skb)
 {
-	if (skb->len > dst_pmtu(skb->dst))
+	if (skb->len > dst_pmtu(skb->dst) || dst_allfrag(skb->dst))
 		return ip6_fragment(skb, ip6_output2);
 	else
 		return ip6_output2(skb);
@@ -253,6 +253,8 @@
 		hlimit = np->hop_limit;
 	if (hlimit < 0)
 		hlimit = dst_metric(dst, RTAX_HOPLIMIT);
+	if (hlimit < 0)
+		hlimit = ipv6_get_hoplimit(dst->dev);
 
 	hdr->payload_len = htons(seg_len);
 	hdr->nexthdr = proto;
@@ -848,6 +850,8 @@
 		inet->cork.fl = *fl;
 		np->cork.hop_limit = hlimit;
 		inet->cork.fragsize = mtu = dst_pmtu(&rt->u.dst);
+		if (dst_allfrag(&rt->u.dst))
+			inet->cork.flags |= IPCORK_ALLFRAG;
 		inet->cork.length = 0;
 		sk->sk_sndmsg_page = NULL;
 		sk->sk_sndmsg_off = 0;
@@ -899,7 +903,7 @@
 
 	while (length > 0) {
 		/* Check if the remaining data fits into current packet. */
-		copy = mtu - skb->len;
+		copy = (inet->cork.length <= mtu && !(inet->cork.flags & IPCORK_ALLFRAG) ? mtu : maxfraglen) - skb->len;
 		if (copy < length)
 			copy = maxfraglen - skb->len;
 
@@ -924,7 +928,7 @@
 			 * we know we need more fragment(s).
 			 */
 			datalen = length + fraggap;
-			if (datalen > mtu - fragheaderlen)
+			if (datalen > (inet->cork.length <= mtu && !(inet->cork.flags & IPCORK_ALLFRAG) ? mtu : maxfraglen) - fragheaderlen)
 				datalen = maxfraglen - fragheaderlen;
 
 			fraglen = datalen + fragheaderlen;
@@ -1158,6 +1162,7 @@
 	if (np->cork.rt) {
 		dst_release(&np->cork.rt->u.dst);
 		np->cork.rt = NULL;
+		inet->cork.flags &= ~IPCORK_ALLFRAG;
 	}
 	memset(&inet->cork.fl, 0, sizeof(inet->cork.fl));
 	return err;
@@ -1185,6 +1190,7 @@
 	if (np->cork.rt) {
 		dst_release(&np->cork.rt->u.dst);
 		np->cork.rt = NULL;
+		inet->cork.flags &= ~IPCORK_ALLFRAG;
 	}
 	memset(&inet->cork.fl, 0, sizeof(inet->cork.fl));
 }
diff -Nru a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c
--- a/net/ipv6/ip6_tunnel.c	2005-03-11 12:51:41 -08:00
+++ b/net/ipv6/ip6_tunnel.c	2005-03-11 12:51:41 -08:00
@@ -94,6 +94,7 @@
 	if (dst && dst->obsolete && 
 	    dst->ops->check(dst, t->dst_cookie) == NULL) {
 		t->dst_cache = NULL;
+		dst_release(dst);
 		return NULL;
 	}
 
diff -Nru a/net/ipv6/ipcomp6.c b/net/ipv6/ipcomp6.c
--- a/net/ipv6/ipcomp6.c	2005-03-11 12:51:46 -08:00
+++ b/net/ipv6/ipcomp6.c	2005-03-11 12:51:46 -08:00
@@ -139,11 +139,9 @@
 	return err;
 }
 
-static int ipcomp6_output(struct sk_buff *skb)
+static int ipcomp6_output(struct xfrm_state *x, struct sk_buff *skb)
 {
 	int err;
-	struct dst_entry *dst = skb->dst;
-	struct xfrm_state *x = dst->xfrm;
 	struct ipv6hdr *top_iph;
 	int hdr_len;
 	struct ipv6_comp_hdr *ipch;
diff -Nru a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
--- a/net/ipv6/ndisc.c	2005-03-11 12:51:47 -08:00
+++ b/net/ipv6/ndisc.c	2005-03-11 12:51:47 -08:00
@@ -156,14 +156,13 @@
 
 /* ND options */
 struct ndisc_options {
-	struct nd_opt_hdr *nd_opt_array[7];
-	struct nd_opt_hdr *nd_opt_piend;
+	struct nd_opt_hdr *nd_opt_array[__ND_OPT_MAX];
 };
 
 #define nd_opts_src_lladdr	nd_opt_array[ND_OPT_SOURCE_LL_ADDR]
 #define nd_opts_tgt_lladdr	nd_opt_array[ND_OPT_TARGET_LL_ADDR]
 #define nd_opts_pi		nd_opt_array[ND_OPT_PREFIX_INFO]
-#define nd_opts_pi_end		nd_opt_piend
+#define nd_opts_pi_end		nd_opt_array[__ND_OPT_PREFIX_INFO_END]
 #define nd_opts_rh		nd_opt_array[ND_OPT_REDIRECT_HDR]
 #define nd_opts_mtu		nd_opt_array[ND_OPT_MTU]
 
@@ -183,6 +182,11 @@
 	}
 }
 
+static inline int ndisc_opt_addr_space(struct net_device *dev)
+{
+	return NDISC_OPT_SPACE(dev->addr_len + ndisc_addr_option_pad(dev->type));
+}
+
 static u8 *ndisc_fill_addr_option(u8 *opt, int type, void *data, int data_len,
 				  unsigned short addr_type)
 {
@@ -267,6 +271,17 @@
 	return ndopts;
 }
 
+static inline u8 *ndisc_opt_addr_data(struct nd_opt_hdr *p,
+				      struct net_device *dev)
+{
+	u8 *lladdr = (u8 *)(p + 1);
+	int lladdrlen = p->nd_opt_len << 3;
+	int prepad = ndisc_addr_option_pad(dev->type);
+	if (lladdrlen != NDISC_OPT_SPACE(dev->addr_len + prepad))
+		return NULL;
+	return (lladdr + prepad);
+}
+
 int ndisc_mc_map(struct in6_addr *addr, char *buf, struct net_device *dev, int dir)
 {
 	switch (dev->type) {
@@ -439,7 +454,7 @@
 
 	if (inc_opt) {
 		if (dev->addr_len)
-			len += NDISC_OPT_SPACE(dev->addr_len);
+			len += ndisc_opt_addr_space(dev);
 		else
 			inc_opt = 0;
 	}
@@ -532,7 +547,7 @@
 	len = sizeof(struct icmp6hdr) + sizeof(struct in6_addr);
 	send_llinfo = dev->addr_len && !ipv6_addr_any(saddr);
 	if (send_llinfo)
-		len += NDISC_OPT_SPACE(dev->addr_len);
+		len += ndisc_opt_addr_space(dev);
 
 	skb = sock_alloc_send_skb(sk, MAX_HEADER + len + LL_RESERVED_SPACE(dev),
 				  1, &err);
@@ -608,7 +623,7 @@
 
 	len = sizeof(struct icmp6hdr);
 	if (dev->addr_len)
-		len += NDISC_OPT_SPACE(dev->addr_len);
+		len += ndisc_opt_addr_space(dev);
 
         skb = sock_alloc_send_skb(sk, MAX_HEADER + len + LL_RESERVED_SPACE(dev),
 				  1, &err);
@@ -704,7 +719,6 @@
 	struct in6_addr *saddr = &skb->nh.ipv6h->saddr;
 	struct in6_addr *daddr = &skb->nh.ipv6h->daddr;
 	u8 *lladdr = NULL;
-	int lladdrlen = 0;
 	u32 ndoptlen = skb->tail - msg->opt;
 	struct ndisc_options ndopts;
 	struct net_device *dev = skb->dev;
@@ -741,10 +755,8 @@
 	}
 
 	if (ndopts.nd_opts_src_lladdr) {
-		lladdr = (u8*)(ndopts.nd_opts_src_lladdr + 1) +
-			ndisc_addr_option_pad(dev->type);
-		lladdrlen = ndopts.nd_opts_src_lladdr->nd_opt_len << 3;
-		if (lladdrlen != NDISC_OPT_SPACE(dev->addr_len)) {
+		lladdr = ndisc_opt_addr_data(ndopts.nd_opts_src_lladdr, dev);
+		if (!lladdr) {
 			ND_PRINTK2(KERN_WARNING
 				   "ICMPv6 NS: invalid link-layer address length\n");
 			return;
@@ -867,7 +879,6 @@
 	struct in6_addr *saddr = &skb->nh.ipv6h->saddr;
 	struct in6_addr *daddr = &skb->nh.ipv6h->daddr;
 	u8 *lladdr = NULL;
-	int lladdrlen = 0;
 	u32 ndoptlen = skb->tail - msg->opt;
 	struct ndisc_options ndopts;
 	struct net_device *dev = skb->dev;
@@ -899,10 +910,8 @@
 		return;
 	}
 	if (ndopts.nd_opts_tgt_lladdr) {
-		lladdr = (u8*)(ndopts.nd_opts_tgt_lladdr + 1) +
-			ndisc_addr_option_pad(dev->type);
-		lladdrlen = ndopts.nd_opts_tgt_lladdr->nd_opt_len << 3;
-		if (lladdrlen != NDISC_OPT_SPACE(dev->addr_len)) {
+		lladdr = ndisc_opt_addr_data(ndopts.nd_opts_tgt_lladdr, dev);
+		if (!lladdr) {
 			ND_PRINTK2(KERN_WARNING
 				   "ICMPv6 NA: invalid link-layer address length\n");
 			return;
@@ -963,7 +972,6 @@
 	struct in6_addr *saddr = &skb->nh.ipv6h->saddr;
 	struct ndisc_options ndopts;
 	u8 *lladdr = NULL;
-	int lladdrlen = 0;
 
 	if (skb->len < sizeof(*rs_msg))
 		return;
@@ -994,10 +1002,9 @@
 	}
 
 	if (ndopts.nd_opts_src_lladdr) {
-		lladdr = (u8 *)(ndopts.nd_opts_src_lladdr + 1) +
-			ndisc_addr_option_pad(skb->dev->type);
-		lladdrlen = ndopts.nd_opts_src_lladdr->nd_opt_len << 3;
-		if (lladdrlen != NDISC_OPT_SPACE(skb->dev->addr_len))
+		lladdr = ndisc_opt_addr_data(ndopts.nd_opts_src_lladdr,
+					     skb->dev);
+		if (!lladdr)
 			goto out;
 	}
 
@@ -1121,8 +1128,11 @@
 	if (rt)
 		rt->rt6i_expires = jiffies + (HZ * lifetime);
 
-	if (ra_msg->icmph.icmp6_hop_limit)
+	if (ra_msg->icmph.icmp6_hop_limit) {
 		in6_dev->cnf.hop_limit = ra_msg->icmph.icmp6_hop_limit;
+		if (rt)
+			rt->u.dst.metrics[RTAX_HOPLIMIT-1] = ra_msg->icmph.icmp6_hop_limit;
+	}
 
 	/*
 	 *	Update Reachable Time and Retrans Timer
@@ -1166,12 +1176,10 @@
 				       skb->dev, 1);
 	if (neigh) {
 		u8 *lladdr = NULL;
-		int lladdrlen;
 		if (ndopts.nd_opts_src_lladdr) {
-			lladdr = (u8*)((ndopts.nd_opts_src_lladdr)+1) +
-				ndisc_addr_option_pad(skb->dev->type);
-			lladdrlen = ndopts.nd_opts_src_lladdr->nd_opt_len << 3;
-			if (lladdrlen != NDISC_OPT_SPACE(skb->dev->addr_len)) {
+			lladdr = ndisc_opt_addr_data(ndopts.nd_opts_src_lladdr,
+						     skb->dev);
+			if (!lladdr) {
 				ND_PRINTK2(KERN_WARNING
 					   "ICMPv6 RA: invalid link-layer address length\n");
 				goto out;
@@ -1236,7 +1244,6 @@
 	struct ndisc_options ndopts;
 	int optlen;
 	u8 *lladdr = NULL;
-	int lladdrlen;
 
 	if (!(ipv6_addr_type(&skb->nh.ipv6h->saddr) & IPV6_ADDR_LINKLOCAL)) {
 		ND_PRINTK2(KERN_WARNING
@@ -1291,10 +1298,9 @@
 		return;
 	}
 	if (ndopts.nd_opts_tgt_lladdr) {
-		lladdr = (u8*)(ndopts.nd_opts_tgt_lladdr + 1) +
-			ndisc_addr_option_pad(skb->dev->type);
-		lladdrlen = ndopts.nd_opts_tgt_lladdr->nd_opt_len << 3;
-		if (lladdrlen != NDISC_OPT_SPACE(skb->dev->addr_len)) {
+		lladdr = ndisc_opt_addr_data(ndopts.nd_opts_tgt_lladdr,
+					     skb->dev);
+		if (!lladdr) {
 			ND_PRINTK2(KERN_WARNING
 				   "ICMPv6 Redirect: invalid link-layer address length\n");
 			in6_dev_put(in6_dev);
@@ -1329,6 +1335,7 @@
 	int rd_len;
 	int err;
 	int hlen;
+	u8 ha_buf[MAX_ADDR_LEN], *ha = NULL;
 
 	dev = skb->dev;
 
@@ -1341,10 +1348,9 @@
 
 	ndisc_flow_init(&fl, NDISC_REDIRECT, &saddr_buf, &skb->nh.ipv6h->saddr);
 
-	rt = rt6_lookup(&skb->nh.ipv6h->saddr, NULL, dev->ifindex, 1);
-	if (rt == NULL)
+	dst = ip6_route_output(NULL, &fl);
+	if (dst == NULL)
 		return;
-	dst = &rt->u.dst;
 
 	err = xfrm_lookup(&dst, &fl, NULL, 0);
 	if (err) {
@@ -1366,16 +1372,14 @@
 	}
 
 	if (dev->addr_len) {
-		if (neigh->nud_state&NUD_VALID) {
-			len  += NDISC_OPT_SPACE(dev->addr_len);
-		} else {
-			/* If nexthop is not valid, do not redirect!
-			   We will make it later, when will be sure,
-			   that it is alive.
-			 */
-			dst_release(dst);
-			return;
-		}
+		read_lock_bh(&neigh->lock);
+		if (neigh->nud_state & NUD_VALID) {
+			memcpy(ha_buf, neigh->ha, dev->addr_len);
+			read_unlock_bh(&neigh->lock);
+			ha = ha_buf;
+			len += ndisc_opt_addr_space(dev);
+		} else
+			read_unlock_bh(&neigh->lock);
 	}
 
 	rd_len = min_t(unsigned int,
@@ -1420,8 +1424,8 @@
 	 *	include target_address option
 	 */
 
-	if (dev->addr_len)
-		opt = ndisc_fill_addr_option(opt, ND_OPT_TARGET_LL_ADDR, neigh->ha,
+	if (ha)
+		opt = ndisc_fill_addr_option(opt, ND_OPT_TARGET_LL_ADDR, ha,
 					     dev->addr_len, dev->type);
 
 	/*
@@ -1515,11 +1519,11 @@
 	switch (event) {
 	case NETDEV_CHANGEADDR:
 		neigh_changeaddr(&nd_tbl, dev);
-		fib6_run_gc(0);
+		fib6_run_gc(~0UL);
 		break;
 	case NETDEV_DOWN:
 		neigh_ifdown(&nd_tbl, dev);
-		fib6_run_gc(0);
+		fib6_run_gc(~0UL);
 		break;
 	default:
 		break;
@@ -1533,18 +1537,105 @@
 };
 
 #ifdef CONFIG_SYSCTL
+static void ndisc_warn_deprecated_sysctl(struct ctl_table *ctl,
+					 const char *func, const char *dev_name)
+{
+	static char warncomm[TASK_COMM_LEN];
+	static int warned;
+	if (strcmp(warncomm, current->comm) && warned < 5) {
+		strcpy(warncomm, current->comm);
+		printk(KERN_WARNING
+			"process `%s' is using deprecated sysctl (%s) "
+			"net.ipv6.neigh.%s.%s; "
+			"Use net.ipv6.neigh.%s.%s_ms "
+			"instead.\n",
+			warncomm, func,
+			dev_name, ctl->procname,
+			dev_name, ctl->procname);
+		warned++;
+	}
+}
+
 int ndisc_ifinfo_sysctl_change(struct ctl_table *ctl, int write, struct file * filp, void __user *buffer, size_t *lenp, loff_t *ppos)
 {
 	struct net_device *dev = ctl->extra1;
 	struct inet6_dev *idev;
+	int ret;
 
-	if (write && dev && (idev = in6_dev_get(dev)) != NULL) {
+	if (ctl->ctl_name == NET_NEIGH_RETRANS_TIME ||
+	    ctl->ctl_name == NET_NEIGH_REACHABLE_TIME)
+		ndisc_warn_deprecated_sysctl(ctl, "syscall", dev ? dev->name : "default");
+
+	switch (ctl->ctl_name) {
+	case NET_NEIGH_RETRANS_TIME:
+		ret = proc_dointvec(ctl, write, filp, buffer, lenp, ppos);
+		break;
+	case NET_NEIGH_REACHABLE_TIME:
+		ret = proc_dointvec_jiffies(ctl, write,
+					    filp, buffer, lenp, ppos);
+		break;
+	case NET_NEIGH_RETRANS_TIME_MS:
+	case NET_NEIGH_REACHABLE_TIME_MS:
+		ret = proc_dointvec_ms_jiffies(ctl, write,
+					       filp, buffer, lenp, ppos);
+		break;
+	default:
+		ret = -1;
+	}
+
+	if (write && ret == 0 && dev && (idev = in6_dev_get(dev)) != NULL) {
+		if (ctl->ctl_name == NET_NEIGH_REACHABLE_TIME ||
+		    ctl->ctl_name == NET_NEIGH_REACHABLE_TIME_MS)
+			idev->nd_parms->reachable_time = neigh_rand_reach_time(idev->nd_parms->base_reachable_time);
 		idev->tstamp = jiffies;
 		inet6_ifinfo_notify(RTM_NEWLINK, idev);
 		in6_dev_put(idev);
 	}
-	return proc_dointvec(ctl, write, filp, buffer, lenp, ppos);
+	return ret;
 }
+
+int ndisc_ifinfo_sysctl_strategy(ctl_table *ctl, int __user *name, int nlen,
+				 void __user *oldval, size_t __user *oldlenp,
+				 void __user *newval, size_t newlen,
+				 void **context)
+{
+	struct net_device *dev = ctl->extra1;
+	struct inet6_dev *idev;
+	int ret;
+
+	if (ctl->ctl_name == NET_NEIGH_RETRANS_TIME ||
+	    ctl->ctl_name == NET_NEIGH_REACHABLE_TIME)
+		ndisc_warn_deprecated_sysctl(ctl, "procfs", dev ? dev->name : "default");
+
+	switch (ctl->ctl_name) {
+	case NET_NEIGH_REACHABLE_TIME:
+		ret = sysctl_jiffies(ctl, name, nlen,
+				     oldval, oldlenp, newval, newlen,
+				     context);
+		break;
+	case NET_NEIGH_RETRANS_TIME_MS:
+	case NET_NEIGH_REACHABLE_TIME_MS:
+		 ret = sysctl_ms_jiffies(ctl, name, nlen,
+					 oldval, oldlenp, newval, newlen,
+					 context);
+		 break;
+	default:
+		ret = 0;
+	}
+
+	if (newval && newlen && ret > 0 &&
+	    dev && (idev = in6_dev_get(dev)) != NULL) {
+		if (ctl->ctl_name == NET_NEIGH_REACHABLE_TIME ||
+		    ctl->ctl_name == NET_NEIGH_REACHABLE_TIME_MS)
+			idev->nd_parms->reachable_time = neigh_rand_reach_time(idev->nd_parms->base_reachable_time);
+		idev->tstamp = jiffies;
+		inet6_ifinfo_notify(RTM_NEWLINK, idev);
+		in6_dev_put(idev);
+	}
+
+	return ret;
+}
+
 #endif
 
 int __init ndisc_init(struct net_proto_family *ops)
@@ -1578,7 +1669,9 @@
 
 #ifdef CONFIG_SYSCTL
 	neigh_sysctl_register(NULL, &nd_tbl.parms, NET_IPV6, NET_IPV6_NEIGH, 
-			      "ipv6", &ndisc_ifinfo_sysctl_change);
+			      "ipv6",
+			      &ndisc_ifinfo_sysctl_change,
+			      &ndisc_ifinfo_sysctl_strategy);
 #endif
 
 	register_netdevice_notifier(&ndisc_netdev_notifier);
diff -Nru a/net/ipv6/netfilter/Kconfig b/net/ipv6/netfilter/Kconfig
--- a/net/ipv6/netfilter/Kconfig	2005-03-11 12:51:51 -08:00
+++ b/net/ipv6/netfilter/Kconfig	2005-03-11 12:51:51 -08:00
@@ -2,8 +2,8 @@
 # IP netfilter configuration
 #
 
-menu "IPv6: Netfilter Configuration"
-	depends on INET && IPV6 && NETFILTER
+menu "IPv6: Netfilter Configuration (EXPERIMENTAL)"
+	depends on INET && IPV6 && NETFILTER && EXPERIMENTAL
 
 #tristate 'Connection tracking (required for masq/NAT)' CONFIG_IP6_NF_CONNTRACK
 #if [ "$CONFIG_IP6_NF_CONNTRACK" != "n" ]; then
diff -Nru a/net/ipv6/netfilter/ip6_queue.c b/net/ipv6/netfilter/ip6_queue.c
--- a/net/ipv6/netfilter/ip6_queue.c	2005-03-11 12:51:42 -08:00
+++ b/net/ipv6/netfilter/ip6_queue.c	2005-03-11 12:51:42 -08:00
@@ -20,6 +20,9 @@
  *             Few changes needed, mainly the hard_routing code and
  *             the netlink socket protocol (we're NETLINK_IP6_FW).
  * 2002-06-25: Code cleanup. [JM: ported cleanup over from ip_queue.c]
+ * 2005-02-04: Added /proc counter for dropped packets; fixed so
+ *             packets aren't delivered to user space if they're going
+ *             to be dropped.
  */
 #include <linux/module.h>
 #include <linux/skbuff.h>
@@ -64,6 +67,8 @@
 static int peer_pid;
 static unsigned int copy_range;
 static unsigned int queue_total;
+static unsigned int queue_dropped = 0;
+static unsigned int queue_user_dropped = 0;
 static struct sock *ipqnl;
 static LIST_HEAD(queue_list);
 static DECLARE_MUTEX(ipqnl_sem);
@@ -75,18 +80,11 @@
 	kfree(entry);
 }
 
-static inline int
+static inline void
 __ipq_enqueue_entry(struct ipq_queue_entry *entry)
 {
-       if (queue_total >= queue_maxlen) {
-               if (net_ratelimit()) 
-                       printk(KERN_WARNING "ip6_queue: full at %d entries, "
-                              "dropping packet(s).\n", queue_total);
-               return -ENOSPC;
-       }
        list_add(&entry->list, &queue_list);
        queue_total++;
-       return 0;
 }
 
 /*
@@ -312,14 +310,24 @@
 	if (!peer_pid)
 		goto err_out_free_nskb; 
 
+	if (queue_total >= queue_maxlen) {
+                queue_dropped++;
+		status = -ENOSPC;
+		if (net_ratelimit())
+		        printk (KERN_WARNING "ip6_queue: fill at %d entries, "
+				"dropping packet(s).  Dropped: %d\n", queue_total,
+				queue_dropped);
+		goto err_out_free_nskb;
+	}
+
  	/* netlink_unicast will either free the nskb or attach it to a socket */ 
 	status = netlink_unicast(ipqnl, nskb, peer_pid, MSG_DONTWAIT);
-	if (status < 0)
+	if (status < 0) {
+ 	        queue_user_dropped++;
 		goto err_out_unlock;
+	}
 	
-	status = __ipq_enqueue_entry(entry);
-	if (status < 0)
-		goto err_out_unlock;
+	__ipq_enqueue_entry(entry);
 
 	write_unlock_bh(&queue_lock);
 	return status;
@@ -639,12 +647,16 @@
 	              "Copy mode         : %hu\n"
 	              "Copy range        : %u\n"
 	              "Queue length      : %u\n"
-	              "Queue max. length : %u\n",
+	              "Queue max. length : %u\n"
+		      "Queue dropped     : %u\n"
+		      "Netfilter dropped : %u\n",
 	              peer_pid,
 	              copy_mode,
 	              copy_range,
 	              queue_total,
-	              queue_maxlen);
+	              queue_maxlen,
+		      queue_dropped,
+		      queue_user_dropped);
 
 	read_unlock_bh(&queue_lock);
 	
diff -Nru a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
--- a/net/ipv6/netfilter/ip6_tables.c	2005-03-11 12:51:51 -08:00
+++ b/net/ipv6/netfilter/ip6_tables.c	2005-03-11 12:51:51 -08:00
@@ -952,7 +952,7 @@
 	}
 
 	/* And one copy for every other CPU */
-	for (i = 1; i < NR_CPUS; i++) {
+	for (i = 1; i < num_possible_cpus(); i++) {
 		memcpy(newinfo->entries + SMP_ALIGN(newinfo->size)*i,
 		       newinfo->entries,
 		       SMP_ALIGN(newinfo->size));
@@ -974,7 +974,7 @@
 		struct ip6t_entry *table_base;
 		unsigned int i;
 
-		for (i = 0; i < NR_CPUS; i++) {
+		for (i = 0; i < num_possible_cpus(); i++) {
 			table_base =
 				(void *)newinfo->entries
 				+ TABLE_OFFSET(newinfo, i);
@@ -1021,7 +1021,7 @@
 	unsigned int cpu;
 	unsigned int i;
 
-	for (cpu = 0; cpu < NR_CPUS; cpu++) {
+	for (cpu = 0; cpu < num_possible_cpus(); cpu++) {
 		i = 0;
 		IP6T_ENTRY_ITERATE(t->entries + TABLE_OFFSET(t, cpu),
 				  t->size,
@@ -1155,7 +1155,7 @@
 		return -ENOMEM;
 
 	newinfo = vmalloc(sizeof(struct ip6t_table_info)
-			  + SMP_ALIGN(tmp.size) * NR_CPUS);
+			  + SMP_ALIGN(tmp.size) * num_possible_cpus());
 	if (!newinfo)
 		return -ENOMEM;
 
@@ -1469,7 +1469,7 @@
 		= { 0, 0, 0, { 0 }, { 0 }, { } };
 
 	newinfo = vmalloc(sizeof(struct ip6t_table_info)
-			  + SMP_ALIGN(repl->size) * NR_CPUS);
+			  + SMP_ALIGN(repl->size) * num_possible_cpus());
 	if (!newinfo)
 		return -ENOMEM;
 
diff -Nru a/net/ipv6/raw.c b/net/ipv6/raw.c
--- a/net/ipv6/raw.c	2005-03-11 12:51:42 -08:00
+++ b/net/ipv6/raw.c	2005-03-11 12:51:42 -08:00
@@ -756,6 +756,8 @@
 			hlimit = np->hop_limit;
 		if (hlimit < 0)
 			hlimit = dst_metric(dst, RTAX_HOPLIMIT);
+		if (hlimit < 0)
+			hlimit = ipv6_get_hoplimit(dst->dev);
 	}
 
 	if (msg->msg_flags&MSG_CONFIRM)
diff -Nru a/net/ipv6/route.c b/net/ipv6/route.c
--- a/net/ipv6/route.c	2005-03-11 12:51:48 -08:00
+++ b/net/ipv6/route.c	2005-03-11 12:51:48 -08:00
@@ -589,7 +589,6 @@
 	if (rt && rt->rt6i_node && (rt->rt6i_node->fn_sernum == cookie))
 		return dst;
 
-	dst_release(dst);
 	return NULL;
 }
 
@@ -628,8 +627,10 @@
 
 	if (mtu < dst_pmtu(dst) && rt6->rt6i_dst.plen == 128) {
 		rt6->rt6i_flags |= RTF_MODIFIED;
-		if (mtu < IPV6_MIN_MTU)
+		if (mtu < IPV6_MIN_MTU) {
 			mtu = IPV6_MIN_MTU;
+			dst->metrics[RTAX_FEATURES-1] |= RTAX_FEATURE_ALLFRAG;
+		}
 		dst->metrics[RTAX_MTU-1] = mtu;
 	}
 }
@@ -769,7 +770,7 @@
 	return mtu;
 }
 
-static int ipv6_get_hoplimit(struct net_device *dev)
+int ipv6_get_hoplimit(struct net_device *dev)
 {
 	int hoplimit = ipv6_devconf.hop_limit;
 	struct inet6_dev *idev;
@@ -965,15 +966,8 @@
 		}
 	}
 
-	if (rt->u.dst.metrics[RTAX_HOPLIMIT-1] == 0) {
-		if (ipv6_addr_is_multicast(&rt->rt6i_dst.addr))
-			rt->u.dst.metrics[RTAX_HOPLIMIT-1] =
-				IPV6_DEFAULT_MCASTHOPS;
-		else
-			rt->u.dst.metrics[RTAX_HOPLIMIT-1] =
-				ipv6_get_hoplimit(dev);
-	}
-
+	if (rt->u.dst.metrics[RTAX_HOPLIMIT-1] == 0)
+		rt->u.dst.metrics[RTAX_HOPLIMIT-1] = -1;
 	if (!rt->u.dst.metrics[RTAX_MTU-1])
 		rt->u.dst.metrics[RTAX_MTU-1] = ipv6_get_mtu(dev);
 	if (!rt->u.dst.metrics[RTAX_ADVMSS-1])
@@ -1164,26 +1158,26 @@
 			struct net_device *dev, u32 pmtu)
 {
 	struct rt6_info *rt, *nrt;
-
-	if (pmtu < IPV6_MIN_MTU) {
-		if (net_ratelimit())
-			printk(KERN_DEBUG "rt6_pmtu_discovery: invalid MTU value %d\n",
-			       pmtu);
-		/* According to RFC1981, the PMTU is set to the IPv6 minimum
-		   link MTU if the node receives a Packet Too Big message
-		   reporting next-hop MTU that is less than the IPv6 minimum MTU.
-		   */
-		pmtu = IPV6_MIN_MTU;
-	}
+	int allfrag = 0;
 
 	rt = rt6_lookup(daddr, saddr, dev->ifindex, 0);
-
 	if (rt == NULL)
 		return;
 
 	if (pmtu >= dst_pmtu(&rt->u.dst))
 		goto out;
 
+	if (pmtu < IPV6_MIN_MTU) {
+		/*
+		 * According to RFC2460, PMTU is set to the IPv6 Minimum Link 
+		 * MTU (1280) and a fragment header should always be included
+		 * after a node receiving Too Big message reporting PMTU is
+		 * less than the IPv6 Minimum Link MTU.
+		 */
+		pmtu = IPV6_MIN_MTU;
+		allfrag = 1;
+	}
+
 	/* New mtu received -> path was valid.
 	   They are sent only in response to data packets,
 	   so that this nexthop apparently is reachable. --ANK
@@ -1197,6 +1191,8 @@
 	 */
 	if (rt->rt6i_flags & RTF_CACHE) {
 		rt->u.dst.metrics[RTAX_MTU-1] = pmtu;
+		if (allfrag)
+			rt->u.dst.metrics[RTAX_FEATURES-1] |= RTAX_FEATURE_ALLFRAG;
 		dst_set_expires(&rt->u.dst, ip6_rt_mtu_expires);
 		rt->rt6i_flags |= RTF_MODIFIED|RTF_EXPIRES;
 		goto out;
@@ -1211,6 +1207,8 @@
 		nrt = rt6_cow(rt, daddr, saddr);
 		if (!nrt->u.dst.error) {
 			nrt->u.dst.metrics[RTAX_MTU-1] = pmtu;
+			if (allfrag)
+				nrt->u.dst.metrics[RTAX_FEATURES-1] |= RTAX_FEATURE_ALLFRAG;
 			/* According to RFC 1981, detecting PMTU increase shouldn't be
 			   happened within 5 mins, the recommended timer is 10 mins.
 			   Here this route expiration time is set to ip6_rt_mtu_expires
@@ -1232,6 +1230,8 @@
 		dst_set_expires(&nrt->u.dst, ip6_rt_mtu_expires);
 		nrt->rt6i_flags |= RTF_DYNAMIC|RTF_CACHE|RTF_EXPIRES;
 		nrt->u.dst.metrics[RTAX_MTU-1] = pmtu;
+		if (allfrag)
+			nrt->u.dst.metrics[RTAX_FEATURES-1] |= RTAX_FEATURE_ALLFRAG;
 		ip6_ins_rt(nrt, NULL, NULL);
 	}
 
@@ -1406,7 +1406,7 @@
 	rt->rt6i_idev = idev;
 	rt->u.dst.metrics[RTAX_MTU-1] = ipv6_get_mtu(rt->rt6i_dev);
 	rt->u.dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(dst_pmtu(&rt->u.dst));
-	rt->u.dst.metrics[RTAX_HOPLIMIT-1] = ipv6_get_hoplimit(rt->rt6i_dev);
+	rt->u.dst.metrics[RTAX_HOPLIMIT-1] = -1;
 	rt->u.dst.obsolete = -1;
 
 	rt->rt6i_flags = RTF_UP | RTF_NONEXTHOP;
@@ -1993,9 +1993,7 @@
 {
 	if (write) {
 		proc_dointvec(ctl, write, filp, buffer, lenp, ppos);
-		if (flush_delay < 0)
-			flush_delay = 0;
-		fib6_run_gc((unsigned long)flush_delay);
+		fib6_run_gc(flush_delay <= 0 ? ~0UL : (unsigned long)flush_delay);
 		return 0;
 	} else
 		return -EINVAL;
@@ -2079,6 +2077,15 @@
 		.mode		=	0644,
          	.proc_handler	=	&proc_dointvec_jiffies,
 		.strategy	=	&sysctl_jiffies,
+	},
+	{
+		.ctl_name	=	NET_IPV6_ROUTE_GC_MIN_INTERVAL_MS,
+		.procname	=	"gc_min_interval_ms",
+         	.data		=	&ip6_rt_gc_min_interval,
+		.maxlen		=	sizeof(int),
+		.mode		=	0644,
+         	.proc_handler	=	&proc_dointvec_ms_jiffies,
+		.strategy	=	&sysctl_ms_jiffies,
 	},
 	{ .ctl_name = 0 }
 };
diff -Nru a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
--- a/net/ipv6/tcp_ipv6.c	2005-03-11 12:51:46 -08:00
+++ b/net/ipv6/tcp_ipv6.c	2005-03-11 12:51:46 -08:00
@@ -441,21 +441,22 @@
 	}
 }
 
-static int tcp_v6_check_established(struct sock *sk)
+static int __tcp_v6_check_established(struct sock *sk, __u16 lport,
+				      struct tcp_tw_bucket **twp)
 {
 	struct inet_sock *inet = inet_sk(sk);
 	struct ipv6_pinfo *np = inet6_sk(sk);
 	struct in6_addr *daddr = &np->rcv_saddr;
 	struct in6_addr *saddr = &np->daddr;
 	int dif = sk->sk_bound_dev_if;
-	u32 ports = TCP_COMBINED_PORTS(inet->dport, inet->num);
+	u32 ports = TCP_COMBINED_PORTS(inet->dport, lport);
 	int hash = tcp_v6_hashfn(daddr, inet->num, saddr, inet->dport);
 	struct tcp_ehash_bucket *head = &tcp_ehash[hash];
 	struct sock *sk2;
 	struct hlist_node *node;
 	struct tcp_tw_bucket *tw;
 
-	write_lock_bh(&head->lock);
+	write_lock(&head->lock);
 
 	/* Check TIME-WAIT sockets first. */
 	sk_for_each(sk2, node, &(head + tcp_ehash_size)->chain) {
@@ -468,7 +469,10 @@
 		   sk2->sk_bound_dev_if == sk->sk_bound_dev_if) {
 			struct tcp_sock *tp = tcp_sk(sk);
 
-			if (tw->tw_ts_recent_stamp) {
+			if (tw->tw_ts_recent_stamp &&
+			    (!twp || (sysctl_tcp_tw_reuse &&
+				      xtime.tv_sec - 
+				      tw->tw_ts_recent_stamp > 1))) {
 				/* See comment in tcp_ipv4.c */
 				tp->write_seq = tw->tw_snd_nxt + 65535 + 2;
 				if (!tp->write_seq)
@@ -494,40 +498,113 @@
 	__sk_add_node(sk, &head->chain);
 	sk->sk_hashent = hash;
 	sock_prot_inc_use(sk->sk_prot);
-	write_unlock_bh(&head->lock);
+	write_unlock(&head->lock);
 
-	if (tw) {
+	if (twp) {
+		*twp = tw;
+		NET_INC_STATS_BH(LINUX_MIB_TIMEWAITRECYCLED);
+	} else if (tw) {
 		/* Silly. Should hash-dance instead... */
-		local_bh_disable();
 		tcp_tw_deschedule(tw);
 		NET_INC_STATS_BH(LINUX_MIB_TIMEWAITRECYCLED);
-		local_bh_enable();
 
 		tcp_tw_put(tw);
 	}
 	return 0;
 
 not_unique:
-	write_unlock_bh(&head->lock);
+	write_unlock(&head->lock);
 	return -EADDRNOTAVAIL;
 }
 
+static inline u32 tcpv6_port_offset(const struct sock *sk)
+{
+	const struct inet_sock *inet = inet_sk(sk);
+	const struct ipv6_pinfo *np = inet6_sk(sk);
+
+	return secure_tcpv6_port_ephemeral(np->rcv_saddr.s6_addr32,
+					   np->daddr.s6_addr32,
+					   inet->dport);
+}
+
 static int tcp_v6_hash_connect(struct sock *sk)
 {
-	struct tcp_bind_hashbucket *head;
-	struct tcp_bind_bucket *tb;
+	unsigned short snum = inet_sk(sk)->num;
+ 	struct tcp_bind_hashbucket *head;
+ 	struct tcp_bind_bucket *tb;
+	int ret;
 
-	/* XXX */
-	if (inet_sk(sk)->num == 0) { 
-		int err = tcp_v6_get_port(sk, inet_sk(sk)->num);
-		if (err)
-			return err;
-		inet_sk(sk)->sport = htons(inet_sk(sk)->num);
-	}
+ 	if (!snum) {
+ 		int low = sysctl_local_port_range[0];
+ 		int high = sysctl_local_port_range[1];
+		int range = high - low;
+ 		int i;
+		int port;
+		static u32 hint;
+		u32 offset = hint + tcpv6_port_offset(sk);
+		struct hlist_node *node;
+ 		struct tcp_tw_bucket *tw = NULL;
+
+ 		local_bh_disable();
+		for (i = 1; i <= range; i++) {
+			port = low + (i + offset) % range;
+ 			head = &tcp_bhash[tcp_bhashfn(port)];
+ 			spin_lock(&head->lock);
+
+ 			/* Does not bother with rcv_saddr checks,
+ 			 * because the established check is already
+ 			 * unique enough.
+ 			 */
+			tb_for_each(tb, node, &head->chain) {
+ 				if (tb->port == port) {
+ 					BUG_TRAP(!hlist_empty(&tb->owners));
+ 					if (tb->fastreuse >= 0)
+ 						goto next_port;
+ 					if (!__tcp_v6_check_established(sk,
+									port,
+									&tw))
+ 						goto ok;
+ 					goto next_port;
+ 				}
+ 			}
+
+ 			tb = tcp_bucket_create(head, port);
+ 			if (!tb) {
+ 				spin_unlock(&head->lock);
+ 				break;
+ 			}
+ 			tb->fastreuse = -1;
+ 			goto ok;
+
+ 		next_port:
+ 			spin_unlock(&head->lock);
+ 		}
+ 		local_bh_enable();
+
+ 		return -EADDRNOTAVAIL;
+
+ok:
+		hint += i;
+
+ 		/* Head lock still held and bh's disabled */
+ 		tcp_bind_hash(sk, tb, port);
+		if (sk_unhashed(sk)) {
+ 			inet_sk(sk)->sport = htons(port);
+ 			__tcp_v6_hash(sk);
+ 		}
+ 		spin_unlock(&head->lock);
+
+ 		if (tw) {
+ 			tcp_tw_deschedule(tw);
+ 			tcp_tw_put(tw);
+ 		}
 
-	head = &tcp_bhash[tcp_bhashfn(inet_sk(sk)->num)];
-	tb = tb_head(head);
+		ret = 0;
+		goto out;
+ 	}
 
+ 	head  = &tcp_bhash[tcp_bhashfn(snum)];
+ 	tb  = tcp_sk(sk)->bind_hash;
 	spin_lock_bh(&head->lock);
 
 	if (sk_head(&tb->owners) == sk && !sk->sk_bind_node.next) {
@@ -535,8 +612,12 @@
 		spin_unlock_bh(&head->lock);
 		return 0;
 	} else {
-		spin_unlock_bh(&head->lock);
-		return tcp_v6_check_established(sk);
+		spin_unlock(&head->lock);
+		/* No definite answer... Walk to established hash table */
+		ret = __tcp_v6_check_established(sk, snum, NULL);
+out:
+		local_bh_enable();
+		return ret;
 	}
 }
 
@@ -701,7 +782,6 @@
 	tp->ext_header_len = 0;
 	if (np->opt)
 		tp->ext_header_len = np->opt->opt_flen + np->opt->opt_nflen;
-	tp->ext2_header_len = dst->header_len;
 
 	tp->rx_opt.mss_clamp = IPV6_MIN_MTU - sizeof(struct tcphdr) - sizeof(struct ipv6hdr);
 
@@ -813,8 +893,8 @@
 		} else
 			dst_hold(dst);
 
-		if (tp->pmtu_cookie > dst_pmtu(dst)) {
-			tcp_sync_mss(sk, dst_pmtu(dst));
+		if (tp->pmtu_cookie > dst_mtu(dst)) {
+			tcp_sync_mss(sk, dst_mtu(dst));
 			tcp_simple_retransmit(sk);
 		} /* else let the usual retransmit timer handle it */
 		dst_release(dst);
@@ -1443,9 +1523,8 @@
 	if (newnp->opt)
 		newtp->ext_header_len = newnp->opt->opt_nflen +
 					newnp->opt->opt_flen;
-	newtp->ext2_header_len = dst->header_len;
 
-	tcp_sync_mss(newsk, dst_pmtu(dst));
+	tcp_sync_mss(newsk, dst_mtu(dst));
 	newtp->advmss = dst_metric(dst, RTAX_ADVMSS);
 	tcp_initialize_rcv_mss(newsk);
 
@@ -1792,7 +1871,6 @@
 		ip6_dst_store(sk, dst, NULL);
 		sk->sk_route_caps = dst->dev->features &
 			~(NETIF_F_IP_CSUM | NETIF_F_TSO);
-		tcp_sk(sk)->ext2_header_len = dst->header_len;
 	}
 
 	return 0;
@@ -1846,7 +1924,6 @@
 		ip6_dst_store(sk, dst, NULL);
 		sk->sk_route_caps = dst->dev->features &
 			~(NETIF_F_IP_CSUM | NETIF_F_TSO);
-		tcp_sk(sk)->ext2_header_len = dst->header_len;
 	}
 
 	skb->dst = dst_clone(dst);
diff -Nru a/net/ipv6/udp.c b/net/ipv6/udp.c
--- a/net/ipv6/udp.c	2005-03-11 12:51:51 -08:00
+++ b/net/ipv6/udp.c	2005-03-11 12:51:51 -08:00
@@ -811,6 +811,8 @@
 			hlimit = np->hop_limit;
 		if (hlimit < 0)
 			hlimit = dst_metric(dst, RTAX_HOPLIMIT);
+		if (hlimit < 0)
+			hlimit = ipv6_get_hoplimit(dst->dev);
 	}
 
 	if (msg->msg_flags&MSG_CONFIRM)
diff -Nru a/net/ipv6/xfrm6_output.c b/net/ipv6/xfrm6_output.c
--- a/net/ipv6/xfrm6_output.c	2005-03-11 12:51:51 -08:00
+++ b/net/ipv6/xfrm6_output.c	2005-03-11 12:51:51 -08:00
@@ -79,7 +79,7 @@
 	int mtu, ret = 0;
 	struct dst_entry *dst = skb->dst;
 
-	mtu = dst_pmtu(dst) - dst->header_len - dst->trailer_len;
+	mtu = dst_mtu(dst);
 	if (mtu < IPV6_MIN_MTU)
 		mtu = IPV6_MIN_MTU;
 
@@ -116,7 +116,7 @@
 
 	xfrm6_encap(skb);
 
-	err = x->type->output(skb);
+	err = x->type->output(x, skb);
 	if (err)
 		goto error;
 
diff -Nru a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c
--- a/net/ipv6/xfrm6_policy.c	2005-03-11 12:51:41 -08:00
+++ b/net/ipv6/xfrm6_policy.c	2005-03-11 12:51:41 -08:00
@@ -31,26 +31,6 @@
 	return err;
 }
 
-/* Check that the bundle accepts the flow and its components are
- * still valid.
- */
-
-static int __xfrm6_bundle_ok(struct xfrm_dst *xdst, struct flowi *fl)
-{
-	do {
-		if (xdst->u.dst.ops != &xfrm6_dst_ops)
-			return 1;
-
-		if (!xfrm_selector_match(&xdst->u.dst.xfrm->sel, fl, AF_INET6))
-			return 0;
-		if (xdst->u.dst.xfrm->km.state != XFRM_STATE_VALID ||
-		    xdst->u.dst.path->obsolete > 0)
-			return 0;
-		xdst = (struct xfrm_dst*)xdst->u.dst.child;
-	} while (xdst);
-	return 0;
-}
-
 static struct dst_entry *
 __xfrm6_find_bundle(struct flowi *fl, struct xfrm_policy *policy)
 {
@@ -70,7 +50,7 @@
 				 xdst->u.rt6.rt6i_src.plen);
 		if (ipv6_addr_equal(&xdst->u.rt6.rt6i_dst.addr, &fl_dst_prefix) &&
 		    ipv6_addr_equal(&xdst->u.rt6.rt6i_src.addr, &fl_src_prefix) &&
-		    __xfrm6_bundle_ok(xdst, fl)) {
+		    xfrm_bundle_ok(xdst, fl, AF_INET6)) {
 			dst_clone(dst);
 			break;
 		}
@@ -92,18 +72,30 @@
 	struct rt6_info *rt  = rt0;
 	struct in6_addr *remote = &fl->fl6_dst;
 	struct in6_addr *local  = &fl->fl6_src;
+	struct flowi fl_tunnel = {
+		.nl_u = {
+			.ip6_u = {
+				.saddr = *local,
+				.daddr = *remote
+			}
+		}
+	};
 	int i;
 	int err = 0;
 	int header_len = 0;
 	int trailer_len = 0;
 
 	dst = dst_prev = NULL;
+	dst_hold(&rt->u.dst);
 
 	for (i = 0; i < nx; i++) {
 		struct dst_entry *dst1 = dst_alloc(&xfrm6_dst_ops);
+		struct xfrm_dst *xdst;
+		int tunnel = 0;
 
 		if (unlikely(dst1 == NULL)) {
 			err = -ENOBUFS;
+			dst_release(&rt->u.dst);
 			goto error;
 		}
 
@@ -114,32 +106,40 @@
 			dst1->flags |= DST_NOHASH;
 			dst_clone(dst1);
 		}
+
+		xdst = (struct xfrm_dst *)dst1;
+		xdst->route = &rt->u.dst;
+
+		dst1->next = dst_prev;
 		dst_prev = dst1;
 		if (xfrm[i]->props.mode) {
 			remote = (struct in6_addr*)&xfrm[i]->id.daddr;
 			local  = (struct in6_addr*)&xfrm[i]->props.saddr;
+			tunnel = 1;
 		}
 		header_len += xfrm[i]->props.header_len;
 		trailer_len += xfrm[i]->props.trailer_len;
-	}
-
-	if (!ipv6_addr_equal(remote, &fl->fl6_dst)) {
-		struct flowi fl_tunnel;
 
-		memset(&fl_tunnel, 0, sizeof(fl_tunnel));
-		ipv6_addr_copy(&fl_tunnel.fl6_dst, remote);
-		ipv6_addr_copy(&fl_tunnel.fl6_src, local);
-
-		err = xfrm_dst_lookup((struct xfrm_dst **) &rt,
-				      &fl_tunnel, AF_INET6);
-		if (err)
-			goto error;
-	} else {
-		dst_hold(&rt->u.dst);
+		if (tunnel) {
+			ipv6_addr_copy(&fl_tunnel.fl6_dst, remote);
+			ipv6_addr_copy(&fl_tunnel.fl6_src, local);
+			err = xfrm_dst_lookup((struct xfrm_dst **) &rt,
+					      &fl_tunnel, AF_INET6);
+			if (err)
+				goto error;
+		} else
+			dst_hold(&rt->u.dst);
 	}
+
 	dst_prev->child = &rt->u.dst;
+	dst->path = &rt->u.dst;
+
+	*dst_p = dst;
+	dst = dst_prev;
+
+	dst_prev = *dst_p;
 	i = 0;
-	for (dst_prev = dst; dst_prev != &rt->u.dst; dst_prev = dst_prev->child) {
+	for (; dst_prev != &rt->u.dst; dst_prev = dst_prev->child) {
 		struct xfrm_dst *x = (struct xfrm_dst*)dst_prev;
 
 		dst_prev->xfrm = xfrm[i++];
@@ -151,8 +151,7 @@
 		dst_prev->lastuse	= jiffies;
 		dst_prev->header_len	= header_len;
 		dst_prev->trailer_len	= trailer_len;
-		memcpy(&dst_prev->metrics, &rt->u.dst.metrics, sizeof(dst_prev->metrics));
-		dst_prev->path		= &rt->u.dst;
+		memcpy(&dst_prev->metrics, &x->route->metrics, sizeof(dst_prev->metrics));
 
 		/* Copy neighbour for reachability confirmation */
 		dst_prev->neighbour	= neigh_clone(rt->u.dst.neighbour);
@@ -170,7 +169,8 @@
 		header_len -= x->u.dst.xfrm->props.header_len;
 		trailer_len -= x->u.dst.xfrm->props.trailer_len;
 	}
-	*dst_p = dst;
+
+	xfrm_init_pmtu(dst);
 	return 0;
 
 error:
@@ -245,12 +245,10 @@
 
 static void xfrm6_update_pmtu(struct dst_entry *dst, u32 mtu)
 {
-	struct dst_entry *path = dst->path;
+	struct xfrm_dst *xdst = (struct xfrm_dst *)dst;
+	struct dst_entry *path = xdst->route;
 
-	if (mtu >= IPV6_MIN_MTU && mtu < dst_pmtu(dst))
-		path->ops->update_pmtu(path, mtu);
-	
-	return;
+	path->ops->update_pmtu(path, mtu);
 }
 
 static struct dst_ops xfrm6_dst_ops = {
diff -Nru a/net/ipv6/xfrm6_state.c b/net/ipv6/xfrm6_state.c
--- a/net/ipv6/xfrm6_state.c	2005-03-11 12:51:42 -08:00
+++ b/net/ipv6/xfrm6_state.c	2005-03-11 12:51:42 -08:00
@@ -27,9 +27,9 @@
 	 * to current session. */
 	ipv6_addr_copy((struct in6_addr *)&x->sel.daddr, &fl->fl6_dst);
 	ipv6_addr_copy((struct in6_addr *)&x->sel.saddr, &fl->fl6_src);
-	x->sel.dport = fl->fl_ip_dport;
+	x->sel.dport = xfrm_flowi_dport(fl);
 	x->sel.dport_mask = ~0;
-	x->sel.sport = fl->fl_ip_sport;
+	x->sel.sport = xfrm_flowi_sport(fl);
 	x->sel.sport_mask = ~0;
 	x->sel.prefixlen_d = 128;
 	x->sel.prefixlen_s = 128;
diff -Nru a/net/ipv6/xfrm6_tunnel.c b/net/ipv6/xfrm6_tunnel.c
--- a/net/ipv6/xfrm6_tunnel.c	2005-03-11 12:51:47 -08:00
+++ b/net/ipv6/xfrm6_tunnel.c	2005-03-11 12:51:47 -08:00
@@ -343,7 +343,7 @@
 
 EXPORT_SYMBOL(xfrm6_tunnel_free_spi);
 
-static int xfrm6_tunnel_output(struct sk_buff *skb)
+static int xfrm6_tunnel_output(struct xfrm_state *x, struct sk_buff *skb)
 {
 	struct ipv6hdr *top_iph;
 
diff -Nru a/net/irda/af_irda.c b/net/irda/af_irda.c
--- a/net/irda/af_irda.c	2005-03-11 12:51:42 -08:00
+++ b/net/irda/af_irda.c	2005-03-11 12:51:42 -08:00
@@ -87,10 +87,10 @@
 
 	IRDA_DEBUG(3, "%s()\n", __FUNCTION__);
 
-	self = (struct irda_sock *) instance;
+	self = instance;
 	ASSERT(self != NULL, return -1;);
 
-	sk = self->sk;
+	sk = instance;
 	ASSERT(sk != NULL, return -1;);
 
 	err = sock_queue_rcv_skb(sk, skb);
@@ -117,7 +117,7 @@
 	struct irda_sock *self;
 	struct sock *sk;
 
-	self = (struct irda_sock *) instance;
+	self = instance;
 
 	IRDA_DEBUG(2, "%s(%p)\n", __FUNCTION__, self);
 
@@ -125,7 +125,7 @@
 	if(skb)
 		dev_kfree_skb(skb);
 
-	sk = self->sk;
+	sk = instance;
 	if (sk == NULL) {
 		IRDA_DEBUG(0, "%s(%p) : BUG : sk is NULL\n",
 			   __FUNCTION__, self);
@@ -183,11 +183,11 @@
 	struct irda_sock *self;
 	struct sock *sk;
 
-	self = (struct irda_sock *) instance;
+	self = instance;
 
 	IRDA_DEBUG(2, "%s(%p)\n", __FUNCTION__, self);
 
-	sk = self->sk;
+	sk = instance;
 	if (sk == NULL) {
 		dev_kfree_skb(skb);
 		return;
@@ -245,11 +245,11 @@
 	struct irda_sock *self;
 	struct sock *sk;
 
-	self = (struct irda_sock *) instance;
+	self = instance;
 
 	IRDA_DEBUG(2, "%s(%p)\n", __FUNCTION__, self);
 
-	sk = self->sk;
+	sk = instance;
 	if (sk == NULL) {
 		dev_kfree_skb(skb);
 		return;
@@ -332,10 +332,10 @@
 
 	IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
 
-	self = (struct irda_sock *) instance;
+	self = instance;
 	ASSERT(self != NULL, return;);
 
-	sk = self->sk;
+	sk = instance;
 	ASSERT(sk != NULL, return;);
 
 	switch (flow) {
@@ -1012,11 +1012,23 @@
 		self->daddr = addr->sir_addr;
 		IRDA_DEBUG(1, "%s(), daddr = %08x\n", __FUNCTION__, self->daddr);
 
-		/* Query remote LM-IAS */
-		err = irda_find_lsap_sel(self, addr->sir_name);
-		if (err) {
-			IRDA_DEBUG(0, "%s(), connect failed!\n", __FUNCTION__);
-			return err;
+		/* If we don't have a valid service name, we assume the
+		 * user want to connect on a specific LSAP. Prevent
+		 * the use of invalid LSAPs (IrLMP 1.1 p10). Jean II */
+		if((addr->sir_name[0] != '\0') ||
+		   (addr->sir_lsap_sel >= 0x70)) {
+			/* Query remote LM-IAS using service name */
+			err = irda_find_lsap_sel(self, addr->sir_name);
+			if (err) {
+				IRDA_DEBUG(0, "%s(), connect failed!\n", __FUNCTION__);
+				return err;
+			}
+		} else {
+			/* Directly connect to the remote LSAP
+			 * specified by the sir_lsap field.
+			 * Please use with caution, in IrDA LSAPs are
+			 * dynamic and there is no "well-known" LSAP. */
+			self->dtsap_sel = addr->sir_lsap_sel;
 		}
 	}
 
@@ -1082,17 +1094,12 @@
 	}
 
 	/* Allocate networking socket */
-	if ((sk = sk_alloc(PF_IRDA, GFP_ATOMIC, 1, NULL)) == NULL)
+	sk = sk_alloc(PF_IRDA, GFP_ATOMIC,
+		      sizeof(struct irda_sock), NULL);
+	if (sk == NULL)
 		return -ENOMEM;
 
-	/* Allocate IrDA socket */
-	self = sk->sk_protinfo = kmalloc(sizeof(struct irda_sock), GFP_ATOMIC);
-	if (self == NULL) {
-		sk_free(sk);
-		return -ENOMEM;
-	}
-	memset(self, 0, sizeof(struct irda_sock));
-
+	self = irda_sk(sk);
 	IRDA_DEBUG(2, "%s() : self is %p\n", __FUNCTION__, self);
 
 	init_waitqueue_head(&self->query_wait);
@@ -1102,8 +1109,6 @@
 	sk_set_owner(sk, THIS_MODULE);
 	sk->sk_family = PF_IRDA;
 	sk->sk_protocol = protocol;
-	/* Link networking socket and IrDA socket structs together */
-	self->sk = sk;
 
 	switch (sock->type) {
 	case SOCK_STREAM:
@@ -1187,7 +1192,6 @@
 		self->lsap = NULL;
 	}
 #endif /* CONFIG_IRDA_ULTRA */
-	kfree(self);
 }
 
 /*
@@ -1208,8 +1212,6 @@
 
 	/* Destroy IrDA socket */
 	irda_destroy_socket(irda_sk(sk));
-	/* Prevent sock_def_destruct() to create havoc */
-	sk->sk_protinfo = NULL;
 
 	sock_orphan(sk);
 	sock->sk   = NULL;
diff -Nru a/net/irda/ircomm/ircomm_tty.c b/net/irda/ircomm/ircomm_tty.c
--- a/net/irda/ircomm/ircomm_tty.c	2005-03-11 12:51:42 -08:00
+++ b/net/irda/ircomm/ircomm_tty.c	2005-03-11 12:51:42 -08:00
@@ -671,10 +671,9 @@
  *    accepted for writing. This routine is mandatory.
  */
 static int ircomm_tty_write(struct tty_struct *tty,
-			    const unsigned char *ubuf, int count)
+			    const unsigned char *buf, int count)
 {
 	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data;
-	unsigned char *kbuf;		/* Buffer in kernel space */
 	unsigned long flags;
 	struct sk_buff *skb;
 	int tailroom = 0;
@@ -714,9 +713,6 @@
 	if (count < 1)
 		return 0;
 
-	/* The buffer is already in kernel space */
-	kbuf = (unsigned char *) ubuf;
-
 	/* Protect our manipulation of self->tx_skb and related */
 	spin_lock_irqsave(&self->spinlock, flags);
 
@@ -779,7 +775,7 @@
 		}
 
 		/* Copy data */
-		memcpy(skb_put(skb,size), kbuf + len, size);
+		memcpy(skb_put(skb,size), buf + len, size);
 
 		count -= size;
 		len += size;
diff -Nru a/net/irda/irnet/irnet_irda.c b/net/irda/irnet/irnet_irda.c
--- a/net/irda/irnet/irnet_irda.c	2005-03-11 12:51:52 -08:00
+++ b/net/irda/irnet/irnet_irda.c	2005-03-11 12:51:52 -08:00
@@ -632,7 +632,7 @@
       self->iriap = NULL;
     }
 
-  /* Cleanup eventual discoveries from connection attempt */
+  /* Cleanup eventual discoveries from connection attempt or control channel */
   if(self->discoveries != NULL)
     {
       /* Cleanup our copy of the discovery log */
diff -Nru a/net/irda/irnet/irnet_ppp.c b/net/irda/irnet/irnet_ppp.c
--- a/net/irda/irnet/irnet_ppp.c	2005-03-11 12:51:47 -08:00
+++ b/net/irda/irnet/irnet_ppp.c	2005-03-11 12:51:47 -08:00
@@ -171,18 +171,44 @@
 #ifdef INITIAL_DISCOVERY
 /*------------------------------------------------------------------*/
 /*
- * Function irnet_read_discovery_log (self)
+ * Function irnet_get_discovery_log (self)
+ *
+ *    Query the content on the discovery log if not done
+ *
+ * This function query the current content of the discovery log
+ * at the startup of the event channel and save it in the internal struct.
+ */
+static void
+irnet_get_discovery_log(irnet_socket *	ap)
+{
+  __u16		mask = irlmp_service_to_hint(S_LAN);
+
+  /* Ask IrLMP for the current discovery log */
+  ap->discoveries = irlmp_get_discoveries(&ap->disco_number, mask,
+					  DISCOVERY_DEFAULT_SLOTS);
+
+  /* Check if the we got some results */
+  if(ap->discoveries == NULL)
+    ap->disco_number = -1;
+
+  DEBUG(CTRL_INFO, "Got the log (0x%p), size is %d\n",
+	ap->discoveries, ap->disco_number);
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Function irnet_read_discovery_log (self, event)
  *
  *    Read the content on the discovery log
  *
  * This function dump the current content of the discovery log
  * at the startup of the event channel.
- * Return 1 if written on the control channel...
+ * Return 1 if wrote an event on the control channel...
  *
  * State of the ap->disco_XXX variables :
- *	at socket creation :	disco_index = 0 ; disco_number = 0
- *	while reading :		disco_index = X ; disco_number = Y
- *	After reading :		disco_index = Y ; disco_number = -1
+ * Socket creation :  discoveries = NULL ; disco_index = 0 ; disco_number = 0
+ * While reading :    discoveries = ptr  ; disco_index = X ; disco_number = Y
+ * After reading :    discoveries = NULL ; disco_index = Y ; disco_number = -1
  */
 static inline int
 irnet_read_discovery_log(irnet_socket *	ap,
@@ -201,19 +227,8 @@
     }
 
   /* Test if it's the first time and therefore we need to get the log */
-  if(ap->disco_index == 0)
-    {
-      __u16		mask = irlmp_service_to_hint(S_LAN);
-
-      /* Ask IrLMP for the current discovery log */
-      ap->discoveries = irlmp_get_discoveries(&ap->disco_number, mask,
-					      DISCOVERY_DEFAULT_SLOTS);
-      /* Check if the we got some results */
-      if(ap->discoveries == NULL)
-	ap->disco_number = -1;
-      DEBUG(CTRL_INFO, "Got the log (0x%p), size is %d\n",
-	    ap->discoveries, ap->disco_number);
-    }
+  if(ap->discoveries == NULL)
+    irnet_get_discovery_log(ap);
 
   /* Check if we have more item to dump */
   if(ap->disco_index < ap->disco_number)
@@ -417,7 +432,14 @@
     mask |= POLLIN | POLLRDNORM;
 #ifdef INITIAL_DISCOVERY
   if(ap->disco_number != -1)
-    mask |= POLLIN | POLLRDNORM;
+    {
+      /* Test if it's the first time and therefore we need to get the log */
+      if(ap->discoveries == NULL)
+	irnet_get_discovery_log(ap);
+      /* Recheck */
+      if(ap->disco_number != -1)
+	mask |= POLLIN | POLLRDNORM;
+    }
 #endif /* INITIAL_DISCOVERY */
 
   DEXIT(CTRL_TRACE, " - mask=0x%X\n", mask);
diff -Nru a/net/key/af_key.c b/net/key/af_key.c
--- a/net/key/af_key.c	2005-03-11 12:51:52 -08:00
+++ b/net/key/af_key.c	2005-03-11 12:51:52 -08:00
@@ -42,11 +42,17 @@
 
 static atomic_t pfkey_socks_nr = ATOMIC_INIT(0);
 
-struct pfkey_opt {
-	int	registered;
-	int	promisc;
+struct pfkey_sock {
+	/* struct sock must be the first member of struct pfkey_sock */
+	struct sock	sk;
+	int		registered;
+	int		promisc;
 };
-#define pfkey_sk(__sk) ((struct pfkey_opt *)(__sk)->sk_protinfo)
+
+static inline struct pfkey_sock *pfkey_sk(struct sock *sk)
+{
+	return (struct pfkey_sock *)sk;
+}
 
 static void pfkey_sock_destruct(struct sock *sk)
 {
@@ -60,8 +66,6 @@
 	BUG_TRAP(!atomic_read(&sk->sk_rmem_alloc));
 	BUG_TRAP(!atomic_read(&sk->sk_wmem_alloc));
 
-	kfree(pfkey_sk(sk));
-
 	atomic_dec(&pfkey_socks_nr);
 }
 
@@ -128,7 +132,6 @@
 static int pfkey_create(struct socket *sock, int protocol)
 {
 	struct sock *sk;
-	struct pfkey_opt *pfk;
 	int err;
 
 	if (!capable(CAP_NET_ADMIN))
@@ -139,7 +142,7 @@
 		return -EPROTONOSUPPORT;
 
 	err = -ENOMEM;
-	sk = sk_alloc(PF_KEY, GFP_KERNEL, 1, NULL);
+	sk = sk_alloc(PF_KEY, GFP_KERNEL, sizeof(struct pfkey_sock), NULL);
 	if (sk == NULL)
 		goto out;
 	
@@ -147,14 +150,6 @@
 	sock_init_data(sock, sk);
 	sk_set_owner(sk, THIS_MODULE);
 
-	err = -ENOMEM;
-	pfk = sk->sk_protinfo = kmalloc(sizeof(*pfk), GFP_KERNEL);
-	if (!pfk) {
-		sk_free(sk);
-		goto out;
-	}
-	memset(pfk, 0, sizeof(*pfk));
-
 	sk->sk_family = PF_KEY;
 	sk->sk_destruct = pfkey_sock_destruct;
 
@@ -233,7 +228,7 @@
 
 	pfkey_lock_table();
 	sk_for_each(sk, node, &pfkey_table) {
-		struct pfkey_opt *pfk = pfkey_sk(sk);
+		struct pfkey_sock *pfk = pfkey_sk(sk);
 		int err2;
 
 		/* Yes, it means that if you are meant to receive this
@@ -1418,7 +1413,7 @@
 
 static int pfkey_register(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, void **ext_hdrs)
 {
-	struct pfkey_opt *pfk = pfkey_sk(sk);
+	struct pfkey_sock *pfk = pfkey_sk(sk);
 	struct sk_buff *supp_skb;
 
 	if (hdr->sadb_msg_satype > SADB_SATYPE_MAX)
@@ -1514,7 +1509,7 @@
 
 static int pfkey_promisc(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, void **ext_hdrs)
 {
-	struct pfkey_opt *pfk = pfkey_sk(sk);
+	struct pfkey_sock *pfk = pfkey_sk(sk);
 	int satype = hdr->sadb_msg_satype;
 
 	if (hdr->sadb_msg_len == (sizeof(*hdr) / sizeof(uint64_t))) {
diff -Nru a/net/llc/af_llc.c b/net/llc/af_llc.c
--- a/net/llc/af_llc.c	2005-03-11 12:51:40 -08:00
+++ b/net/llc/af_llc.c	2005-03-11 12:51:40 -08:00
@@ -113,7 +113,7 @@
  */
 static int llc_ui_send_data(struct sock* sk, struct sk_buff *skb, int noblock)
 {
-	struct llc_opt* llc = llc_sk(sk);
+	struct llc_sock* llc = llc_sk(sk);
 	int rc = 0;
 
 	if (llc_data_accept_state(llc->state) || llc->p_flag) {
@@ -169,7 +169,7 @@
 static int llc_ui_release(struct socket *sock)
 {
 	struct sock *sk = sock->sk;
-	struct llc_opt *llc;
+	struct llc_sock *llc;
 
 	if (!sk)
 		goto out;
@@ -244,7 +244,7 @@
 static int llc_ui_autobind(struct socket *sock, struct sockaddr_llc *addr)
 {
 	struct sock *sk = sock->sk;
-	struct llc_opt *llc = llc_sk(sk);
+	struct llc_sock *llc = llc_sk(sk);
 	struct llc_sap *sap;
 	int rc = -EINVAL;
 
@@ -293,7 +293,7 @@
 {
 	struct sockaddr_llc *addr = (struct sockaddr_llc *)uaddr;
 	struct sock *sk = sock->sk;
-	struct llc_opt *llc = llc_sk(sk);
+	struct llc_sock *llc = llc_sk(sk);
 	struct llc_sap *sap;
 	int rc = -EINVAL;
 
@@ -394,7 +394,7 @@
 			  int addrlen, int flags)
 {
 	struct sock *sk = sock->sk;
-	struct llc_opt *llc = llc_sk(sk);
+	struct llc_sock *llc = llc_sk(sk);
 	struct sockaddr_llc *addr = (struct sockaddr_llc *)uaddr;
 	struct net_device *dev;
 	int rc = -EINVAL;
@@ -571,7 +571,7 @@
 static int llc_ui_wait_for_busy_core(struct sock *sk, int timeout)
 {
 	DECLARE_WAITQUEUE(wait, current);
-	struct llc_opt *llc = llc_sk(sk);
+	struct llc_sock *llc = llc_sk(sk);
 	int rc;
 
 	add_wait_queue_exclusive(sk->sk_sleep, &wait);
@@ -612,7 +612,7 @@
 static int llc_ui_accept(struct socket *sock, struct socket *newsock, int flags)
 {
 	struct sock *sk = sock->sk, *newsk;
-	struct llc_opt *llc, *newllc;
+	struct llc_sock *llc, *newllc;
 	struct sk_buff *skb;
 	int rc = -EOPNOTSUPP;
 
@@ -728,7 +728,7 @@
 			  struct msghdr *msg, size_t len)
 {
 	struct sock *sk = sock->sk;
-	struct llc_opt *llc = llc_sk(sk);
+	struct llc_sock *llc = llc_sk(sk);
 	struct sockaddr_llc *addr = (struct sockaddr_llc *)msg->msg_name;
 	int flags = msg->msg_flags;
 	int noblock = flags & MSG_DONTWAIT;
@@ -819,7 +819,7 @@
 {
 	struct sockaddr_llc sllc;
 	struct sock *sk = sock->sk;
-	struct llc_opt *llc = llc_sk(sk);
+	struct llc_sock *llc = llc_sk(sk);
 	int rc = 0;
 
 	lock_sock(sk);
@@ -883,7 +883,7 @@
 			     char __user *optval, int optlen)
 {
 	struct sock *sk = sock->sk;
-	struct llc_opt *llc = llc_sk(sk);
+	struct llc_sock *llc = llc_sk(sk);
 	int rc = -EINVAL, opt;
 
 	lock_sock(sk);
@@ -958,7 +958,7 @@
 			     char __user *optval, int __user *optlen)
 {
 	struct sock *sk = sock->sk;
-	struct llc_opt *llc = llc_sk(sk);
+	struct llc_sock *llc = llc_sk(sk);
 	int val = 0, len = 0, rc = -EINVAL;
 
 	lock_sock(sk);
diff -Nru a/net/llc/llc_c_ac.c b/net/llc/llc_c_ac.c
--- a/net/llc/llc_c_ac.c	2005-03-11 12:51:51 -08:00
+++ b/net/llc/llc_c_ac.c	2005-03-11 12:51:51 -08:00
@@ -44,7 +44,7 @@
 
 int llc_conn_ac_clear_remote_busy(struct sock *sk, struct sk_buff *skb)
 {
-	struct llc_opt *llc = llc_sk(sk);
+	struct llc_sock *llc = llc_sk(sk);
 
 	if (llc->remote_busy_flag) {
 		u8 nr;
@@ -68,7 +68,7 @@
 	sap = llc_sap_find(dsap);
 	if (sap) {
 		struct llc_conn_state_ev *ev = llc_conn_ev(skb);
-		struct llc_opt *llc = llc_sk(sk);
+		struct llc_sock *llc = llc_sk(sk);
 
 		llc_pdu_decode_sa(skb, llc->daddr.mac);
 		llc_pdu_decode_da(skb, llc->laddr.mac);
@@ -146,7 +146,7 @@
 	int rc = 1;
 	struct llc_conn_state_ev *ev = llc_conn_ev(skb);
 	struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb);
-	struct llc_opt *llc = llc_sk(sk);
+	struct llc_sock *llc = llc_sk(sk);
 
 	switch (ev->type) {
 	case LLC_CONN_EV_TYPE_PDU:
@@ -207,7 +207,7 @@
 int llc_conn_ac_stop_rej_tmr_if_data_flag_eq_2(struct sock *sk,
 					       struct sk_buff *skb)
 {
-	struct llc_opt *llc = llc_sk(sk);
+	struct llc_sock *llc = llc_sk(sk);
 
 	if (llc->data_flag == 2)
 		del_timer(&llc->rej_sent_timer.timer);
@@ -220,7 +220,7 @@
 	struct sk_buff *nskb = llc_alloc_frame();
 
 	if (nskb) {
-		struct llc_opt *llc = llc_sk(sk);
+		struct llc_sock *llc = llc_sk(sk);
 		struct llc_sap *sap = llc->sap;
 
 		nskb->dev = llc->dev;
@@ -246,7 +246,7 @@
 	struct sk_buff *nskb = llc_alloc_frame();
 
 	if (nskb) {
-		struct llc_opt *llc = llc_sk(sk);
+		struct llc_sock *llc = llc_sk(sk);
 		struct llc_sap *sap = llc->sap;
 		u8 f_bit;
 
@@ -273,7 +273,7 @@
 	struct sk_buff *nskb = llc_alloc_frame();
 
 	if (nskb) {
-		struct llc_opt *llc = llc_sk(sk);
+		struct llc_sock *llc = llc_sk(sk);
 		struct llc_sap *sap = llc->sap;
 		u8 f_bit = 1;
 
@@ -299,7 +299,7 @@
 	int rc = -ENOBUFS;
 	struct sk_buff *nskb;
 	struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
-	struct llc_opt *llc = llc_sk(sk);
+	struct llc_sock *llc = llc_sk(sk);
 
 	llc->rx_pdu_hdr = *((u32 *)pdu);
 	if (LLC_PDU_IS_CMD(pdu))
@@ -334,7 +334,7 @@
 
 	if (nskb) {
 		u8 f_bit = 0;
-		struct llc_opt *llc = llc_sk(sk);
+		struct llc_sock *llc = llc_sk(sk);
 		struct llc_sap *sap = llc->sap;
 		struct llc_pdu_sn *pdu = (struct llc_pdu_sn *)&llc->rx_pdu_hdr;
 
@@ -364,7 +364,7 @@
 	llc_pdu_decode_pf_bit(skb, &f_bit);
 	nskb = llc_alloc_frame();
 	if (nskb) {
-		struct llc_opt *llc = llc_sk(sk);
+		struct llc_sock *llc = llc_sk(sk);
 		struct llc_sap *sap = llc->sap;
 		struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
 
@@ -388,7 +388,7 @@
 int llc_conn_ac_send_i_cmd_p_set_1(struct sock *sk, struct sk_buff *skb)
 {
 	int rc;
-	struct llc_opt *llc = llc_sk(sk);
+	struct llc_sock *llc = llc_sk(sk);
 	struct llc_sap *sap = llc->sap;
 
 	llc_pdu_header_init(skb, LLC_PDU_TYPE_I, sap->laddr.lsap,
@@ -405,7 +405,7 @@
 static int llc_conn_ac_send_i_cmd_p_set_0(struct sock *sk, struct sk_buff *skb)
 {
 	int rc;
-	struct llc_opt *llc = llc_sk(sk);
+	struct llc_sock *llc = llc_sk(sk);
 	struct llc_sap *sap = llc->sap;
 
 	llc_pdu_header_init(skb, LLC_PDU_TYPE_I, sap->laddr.lsap,
@@ -422,7 +422,7 @@
 int llc_conn_ac_send_i_xxx_x_set_0(struct sock *sk, struct sk_buff *skb)
 {
 	int rc;
-	struct llc_opt *llc = llc_sk(sk);
+	struct llc_sock *llc = llc_sk(sk);
 	struct llc_sap *sap = llc->sap;
 
 	llc_pdu_header_init(skb, LLC_PDU_TYPE_I, sap->laddr.lsap,
@@ -454,7 +454,7 @@
 	struct sk_buff *nskb = llc_alloc_frame();
 
 	if (nskb) {
-		struct llc_opt *llc = llc_sk(sk);
+		struct llc_sock *llc = llc_sk(sk);
 		struct llc_sap *sap = llc->sap;
 
 		nskb->dev = llc->dev;
@@ -490,7 +490,7 @@
 	struct sk_buff *nskb = llc_alloc_frame();
 
 	if (nskb) {
-		struct llc_opt *llc = llc_sk(sk);
+		struct llc_sock *llc = llc_sk(sk);
 		struct llc_sap *sap = llc->sap;
 
 		nskb->dev = llc->dev;
@@ -516,7 +516,7 @@
 
 	if (nskb) {
 		u8 f_bit = 1;
-		struct llc_opt *llc = llc_sk(sk);
+		struct llc_sock *llc = llc_sk(sk);
 		struct llc_sap *sap = llc->sap;
 
 		nskb->dev = llc->dev;
@@ -541,7 +541,7 @@
 	struct sk_buff *nskb = llc_alloc_frame();
 
 	if (nskb) {
-		struct llc_opt *llc = llc_sk(sk);
+		struct llc_sock *llc = llc_sk(sk);
 		struct llc_sap *sap = llc->sap;
 		u8 f_bit = 0;
 
@@ -567,7 +567,7 @@
 	struct sk_buff *nskb = llc_alloc_frame();
 
 	if (nskb) {
-		struct llc_opt *llc = llc_sk(sk);
+		struct llc_sock *llc = llc_sk(sk);
 		struct llc_sap *sap = llc->sap;
 
 		nskb->dev = llc->dev;
@@ -592,7 +592,7 @@
 	struct sk_buff *nskb = llc_alloc_frame();
 
 	if (nskb) {
-		struct llc_opt *llc = llc_sk(sk);
+		struct llc_sock *llc = llc_sk(sk);
 		struct llc_sap *sap = llc->sap;
 		u8 f_bit = 1;
 
@@ -619,7 +619,7 @@
 
 	if (nskb) {
 		u8 f_bit = 0;
-		struct llc_opt *llc = llc_sk(sk);
+		struct llc_sock *llc = llc_sk(sk);
 		struct llc_sap *sap = llc->sap;
 
 		nskb->dev = llc->dev;
@@ -640,7 +640,7 @@
 
 int llc_conn_ac_set_remote_busy(struct sock *sk, struct sk_buff *skb)
 {
-	struct llc_opt *llc = llc_sk(sk);
+	struct llc_sock *llc = llc_sk(sk);
 
 	if (!llc->remote_busy_flag) {
 		llc->remote_busy_flag = 1;
@@ -656,7 +656,7 @@
 	struct sk_buff *nskb = llc_alloc_frame();
 
 	if (nskb) {
-		struct llc_opt *llc = llc_sk(sk);
+		struct llc_sock *llc = llc_sk(sk);
 		struct llc_sap *sap = llc->sap;
 
 		nskb->dev = llc->dev;
@@ -681,7 +681,7 @@
 	struct sk_buff *nskb = llc_alloc_frame();
 
 	if (nskb) {
-		struct llc_opt *llc = llc_sk(sk);
+		struct llc_sock *llc = llc_sk(sk);
 		struct llc_sap *sap = llc->sap;
 
 		nskb->dev = llc->dev;
@@ -706,7 +706,7 @@
 	struct sk_buff *nskb = llc_alloc_frame();
 
 	if (nskb) {
-		struct llc_opt *llc = llc_sk(sk);
+		struct llc_sock *llc = llc_sk(sk);
 		struct llc_sap *sap = llc->sap;
 		u8 f_bit = 1;
 
@@ -732,7 +732,7 @@
 	struct sk_buff *nskb = llc_alloc_frame();
 
 	if (nskb) {
-		struct llc_opt *llc = llc_sk(sk);
+		struct llc_sock *llc = llc_sk(sk);
 		struct llc_sap *sap = llc->sap;
 		u8 f_bit = 1;
 
@@ -758,7 +758,7 @@
 	struct sk_buff *nskb = llc_alloc_frame();
 
 	if (nskb) {
-		struct llc_opt *llc = llc_sk(sk);
+		struct llc_sock *llc = llc_sk(sk);
 		struct llc_sap *sap = llc->sap;
 
 		nskb->dev = llc->dev;
@@ -783,7 +783,7 @@
 	struct sk_buff *nskb = llc_alloc_frame();
 
 	if (nskb) {
-		struct llc_opt *llc = llc_sk(sk);
+		struct llc_sock *llc = llc_sk(sk);
 		struct llc_sap *sap = llc->sap;
 
 		nskb->dev = llc->dev;
@@ -816,7 +816,7 @@
 {
 	int rc = -ENOBUFS;
 	struct sk_buff *nskb = llc_alloc_frame();
-	struct llc_opt *llc = llc_sk(sk);
+	struct llc_sock *llc = llc_sk(sk);
 
 	if (nskb) {
 		struct llc_sap *sap = llc->sap;
@@ -849,7 +849,7 @@
 
 	llc_pdu_decode_pf_bit(skb, &f_bit);
 	if (nskb) {
-		struct llc_opt *llc = llc_sk(sk);
+		struct llc_sock *llc = llc_sk(sk);
 		struct llc_sap *sap = llc->sap;
 
 		nskb->dev = llc->dev;
@@ -882,7 +882,7 @@
 
 int llc_conn_ac_start_p_timer(struct sock *sk, struct sk_buff *skb)
 {
-	struct llc_opt *llc = llc_sk(sk);
+	struct llc_sock *llc = llc_sk(sk);
 
 	llc_conn_set_p_flag(sk, 1);
 	mod_timer(&llc->pf_cycle_timer.timer,
@@ -903,7 +903,7 @@
 int llc_conn_ac_send_ack_if_needed(struct sock *sk, struct sk_buff *skb)
 {
 	u8 pf_bit;
-	struct llc_opt *llc = llc_sk(sk);
+	struct llc_sock *llc = llc_sk(sk);
 
 	llc_pdu_decode_pf_bit(skb, &pf_bit);
 	llc->ack_pf |= pf_bit & 1;
@@ -950,7 +950,7 @@
 					      struct sk_buff *skb)
 {
 	int rc;
-	struct llc_opt *llc = llc_sk(sk);
+	struct llc_sock *llc = llc_sk(sk);
 	struct llc_sap *sap = llc->sap;
 
 	llc_pdu_header_init(skb, LLC_PDU_TYPE_I, sap->laddr.lsap,
@@ -976,7 +976,7 @@
  */
 int llc_conn_ac_send_i_as_ack(struct sock *sk, struct sk_buff *skb)
 {
-	struct llc_opt *llc = llc_sk(sk);
+	struct llc_sock *llc = llc_sk(sk);
 
 	if (llc->ack_must_be_send) {
 		llc_conn_ac_send_i_rsp_f_set_ackpf(sk, skb);
@@ -1004,7 +1004,7 @@
 	struct sk_buff *nskb = llc_alloc_frame();
 
 	if (nskb) {
-		struct llc_opt *llc = llc_sk(sk);
+		struct llc_sock *llc = llc_sk(sk);
 		struct llc_sap *sap = llc->sap;
 
 		nskb->dev = llc->dev;
@@ -1035,7 +1035,7 @@
  */
 static int llc_conn_ac_inc_npta_value(struct sock *sk, struct sk_buff *skb)
 {
-	struct llc_opt *llc = llc_sk(sk);
+	struct llc_sock *llc = llc_sk(sk);
 
 	if (!llc->inc_cntr) {
 		llc->dec_step = 0;
@@ -1058,7 +1058,7 @@
  */
 int llc_conn_ac_adjust_npta_by_rr(struct sock *sk, struct sk_buff *skb)
 {
-	struct llc_opt *llc = llc_sk(sk);
+	struct llc_sock *llc = llc_sk(sk);
 
 	if (!llc->connect_step && !llc->remote_busy_flag) {
 		if (!llc->dec_step) {
@@ -1084,7 +1084,7 @@
  */
 int llc_conn_ac_adjust_npta_by_rnr(struct sock *sk, struct sk_buff *skb)
 {
-	struct llc_opt *llc = llc_sk(sk);
+	struct llc_sock *llc = llc_sk(sk);
 
 	if (llc->remote_busy_flag)
 		if (!llc->dec_step) {
@@ -1109,7 +1109,7 @@
  */
 int llc_conn_ac_dec_tx_win_size(struct sock *sk, struct sk_buff *skb)
 {
-	struct llc_opt *llc = llc_sk(sk);
+	struct llc_sock *llc = llc_sk(sk);
 	u8 unacked_pdu = skb_queue_len(&llc->pdu_unack_q);
 
 	llc->k -= unacked_pdu;
@@ -1128,7 +1128,7 @@
  */
 int llc_conn_ac_inc_tx_win_size(struct sock *sk, struct sk_buff *skb)
 {
-	struct llc_opt *llc = llc_sk(sk);
+	struct llc_sock *llc = llc_sk(sk);
 
 	llc->k += 1;
 	if (llc->k > 128)
@@ -1138,7 +1138,7 @@
 
 int llc_conn_ac_stop_all_timers(struct sock *sk, struct sk_buff *skb)
 {
-	struct llc_opt *llc = llc_sk(sk);
+	struct llc_sock *llc = llc_sk(sk);
 
 	del_timer(&llc->pf_cycle_timer.timer);
 	del_timer(&llc->ack_timer.timer);
@@ -1151,7 +1151,7 @@
 
 int llc_conn_ac_stop_other_timers(struct sock *sk, struct sk_buff *skb)
 {
-	struct llc_opt *llc = llc_sk(sk);
+	struct llc_sock *llc = llc_sk(sk);
 
 	del_timer(&llc->rej_sent_timer.timer);
 	del_timer(&llc->pf_cycle_timer.timer);
@@ -1163,7 +1163,7 @@
 
 int llc_conn_ac_start_ack_timer(struct sock *sk, struct sk_buff *skb)
 {
-	struct llc_opt *llc = llc_sk(sk);
+	struct llc_sock *llc = llc_sk(sk);
 
 	mod_timer(&llc->ack_timer.timer, jiffies + llc->ack_timer.expire * HZ);
 	return 0;
@@ -1171,7 +1171,7 @@
 
 int llc_conn_ac_start_rej_timer(struct sock *sk, struct sk_buff *skb)
 {
-	struct llc_opt *llc = llc_sk(sk);
+	struct llc_sock *llc = llc_sk(sk);
 
 	mod_timer(&llc->rej_sent_timer.timer,
 		  jiffies + llc->rej_sent_timer.expire * HZ);
@@ -1181,7 +1181,7 @@
 int llc_conn_ac_start_ack_tmr_if_not_running(struct sock *sk,
 					     struct sk_buff *skb)
 {
-	struct llc_opt *llc = llc_sk(sk);
+	struct llc_sock *llc = llc_sk(sk);
 
 	if (!timer_pending(&llc->ack_timer.timer))
 		mod_timer(&llc->ack_timer.timer,
@@ -1197,7 +1197,7 @@
 
 int llc_conn_ac_stop_p_timer(struct sock *sk, struct sk_buff *skb)
 {
-	struct llc_opt *llc = llc_sk(sk);
+	struct llc_sock *llc = llc_sk(sk);
 
 	del_timer(&llc->pf_cycle_timer.timer);
 	llc_conn_set_p_flag(sk, 0);
@@ -1215,7 +1215,7 @@
 	int acked;
 	u16 unacked = 0;
 	struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
-	struct llc_opt *llc = llc_sk(sk);
+	struct llc_sock *llc = llc_sk(sk);
 
 	llc->last_nr = PDU_SUPV_GET_Nr(pdu);
 	acked = llc_conn_remove_acked_pdus(sk, llc->last_nr, &unacked);
diff -Nru a/net/llc/llc_c_ev.c b/net/llc/llc_c_ev.c
--- a/net/llc/llc_c_ev.c	2005-03-11 12:51:41 -08:00
+++ b/net/llc/llc_c_ev.c	2005-03-11 12:51:41 -08:00
@@ -78,7 +78,7 @@
 	u8 nr1, nr2;
 	struct sk_buff *skb;
 	struct llc_pdu_sn *pdu;
-	struct llc_opt *llc = llc_sk(sk);
+	struct llc_sock *llc = llc_sk(sk);
 	int rc = 0;
 
 	if (llc->dev->flags & IFF_LOOPBACK)
diff -Nru a/net/llc/llc_conn.c b/net/llc/llc_conn.c
--- a/net/llc/llc_conn.c	2005-03-11 12:51:41 -08:00
+++ b/net/llc/llc_conn.c	2005-03-11 12:51:41 -08:00
@@ -53,7 +53,7 @@
 int llc_conn_state_process(struct sock *sk, struct sk_buff *skb)
 {
 	int rc;
-	struct llc_opt *llc = llc_sk(sk);
+	struct llc_sock *llc = llc_sk(sk);
 	struct llc_conn_state_ev *ev = llc_conn_ev(skb);
 
 	/*
@@ -221,7 +221,7 @@
 	struct sk_buff *skb;
 	struct llc_pdu_sn *pdu;
 	u16 nbr_unack_pdus;
-	struct llc_opt *llc;
+	struct llc_sock *llc;
 	u8 howmany_resend = 0;
 
 	llc_conn_remove_acked_pdus(sk, nr, &nbr_unack_pdus);
@@ -263,7 +263,7 @@
 {
 	struct sk_buff *skb;
 	u16 nbr_unack_pdus;
-	struct llc_opt *llc = llc_sk(sk);
+	struct llc_sock *llc = llc_sk(sk);
 	u8 howmany_resend = 0;
 
 	llc_conn_remove_acked_pdus(sk, nr, &nbr_unack_pdus);
@@ -305,7 +305,7 @@
 	struct sk_buff *skb;
 	struct llc_pdu_sn *pdu;
 	int nbr_acked = 0;
-	struct llc_opt *llc = llc_sk(sk);
+	struct llc_sock *llc = llc_sk(sk);
 	int q_len = skb_queue_len(&llc->pdu_unack_q);
 
 	if (!q_len)
@@ -366,7 +366,7 @@
 static int llc_conn_service(struct sock *sk, struct sk_buff *skb)
 {
 	int rc = 1;
-	struct llc_opt *llc = llc_sk(sk);
+	struct llc_sock *llc = llc_sk(sk);
 	struct llc_conn_state_trans *trans;
 
 	if (llc->state > NBR_CONN_STATES)
@@ -399,7 +399,7 @@
 	struct llc_conn_state_trans **next_trans;
 	llc_conn_ev_qfyr_t *next_qualifier;
 	struct llc_conn_state_ev *ev = llc_conn_ev(skb);
-	struct llc_opt *llc = llc_sk(sk);
+	struct llc_sock *llc = llc_sk(sk);
 	struct llc_conn_state *curr_state =
 					&llc_conn_state_table[llc->state - 1];
 
@@ -478,7 +478,7 @@
 
 	read_lock_bh(&sap->sk_list.lock);
 	sk_for_each(rc, node, &sap->sk_list.list) {
-		struct llc_opt *llc = llc_sk(rc);
+		struct llc_sock *llc = llc_sk(rc);
 
 		if (llc->laddr.lsap == laddr->lsap &&
 		    llc->daddr.lsap == daddr->lsap &&
@@ -511,7 +511,7 @@
 
 	read_lock_bh(&sap->sk_list.lock);
 	sk_for_each(rc, node, &sap->sk_list.list) {
-		struct llc_opt *llc = llc_sk(rc);
+		struct llc_sock *llc = llc_sk(rc);
 
 		if (rc->sk_type == SOCK_STREAM && rc->sk_state == TCP_LISTEN &&
 		    llc->laddr.lsap == laddr->lsap &&
@@ -650,7 +650,7 @@
 static int llc_conn_rcv(struct sock* sk, struct sk_buff *skb)
 {
 	struct llc_conn_state_ev *ev = llc_conn_ev(skb);
-	struct llc_opt *llc = llc_sk(sk);
+	struct llc_sock *llc = llc_sk(sk);
 
 	if (!llc->dev)
 		llc->dev = skb->dev;
@@ -675,7 +675,7 @@
 		 * Didn't find an active connection; verify if there
 		 * is a listening socket for this llc addr
 		 */
-		struct llc_opt *llc;
+		struct llc_sock *llc;
 		struct sock *parent = llc_lookup_listener(sap, &daddr);
 
 		if (!parent) {
@@ -756,7 +756,7 @@
 static int llc_backlog_rcv(struct sock *sk, struct sk_buff *skb)
 {
 	int rc = 0;
-	struct llc_opt *llc = llc_sk(sk);
+	struct llc_sock *llc = llc_sk(sk);
 
 	if (llc_backlog_type(skb) == LLC_PACKET) {
 		if (llc->state > 1) /* not closed */
@@ -786,17 +786,10 @@
  *
  *     Initializes a socket with default llc values.
  */
-static int llc_sk_init(struct sock* sk)
+static void llc_sk_init(struct sock* sk)
 {
-	struct llc_opt *llc = kmalloc(sizeof(*llc), GFP_ATOMIC);
-	int rc = -ENOMEM;
+	struct llc_sock *llc = llc_sk(sk);
 
-	if (!llc)
-		goto out;
-	memset(llc, 0, sizeof(*llc));
-	rc = 0;
-
-	llc->sk	      = sk;
 	llc->state    = LLC_CONN_STATE_ADM;
 	llc->inc_cntr = llc->dec_cntr = 2;
 	llc->dec_step = llc->connect_step = 1;
@@ -827,9 +820,6 @@
 		        * tx_win of remote LLC) */
 	skb_queue_head_init(&llc->pdu_unack_q);
 	sk->sk_backlog_rcv = llc_backlog_rcv;
-	sk->sk_protinfo = llc;
-out:
-	return rc;
 }
 
 /**
@@ -842,12 +832,12 @@
  */
 struct sock *llc_sk_alloc(int family, int priority)
 {
-	struct sock *sk = sk_alloc(family, priority, 1, NULL);
+	struct sock *sk = sk_alloc(family, priority,
+				   sizeof(struct llc_sock), NULL);
 
 	if (!sk)
 		goto out;
-	if (llc_sk_init(sk))
-		goto outsk;
+	llc_sk_init(sk);
 	sock_init_data(NULL, sk);
 	sk_set_owner(sk, THIS_MODULE);
 #ifdef LLC_REFCNT_DEBUG
@@ -857,10 +847,6 @@
 #endif
 out:
 	return sk;
-outsk:
-	sk_free(sk);
-	sk = NULL;
-	goto out;
 }
 
 /**
@@ -871,7 +857,7 @@
  */
 void llc_sk_free(struct sock *sk)
 {
-	struct llc_opt *llc = llc_sk(sk);
+	struct llc_sock *llc = llc_sk(sk);
 
 	llc->state = LLC_CONN_OUT_OF_SVC;
 	/* Stop all (possibly) running timers */
@@ -908,7 +894,7 @@
  */
 void llc_sk_reset(struct sock *sk)
 {
-	struct llc_opt *llc = llc_sk(sk);
+	struct llc_sock *llc = llc_sk(sk);
 
 	llc_conn_ac_stop_all_timers(sk, NULL);
 	skb_queue_purge(&sk->sk_write_queue);
diff -Nru a/net/llc/llc_if.c b/net/llc/llc_if.c
--- a/net/llc/llc_if.c	2005-03-11 12:51:46 -08:00
+++ b/net/llc/llc_if.c	2005-03-11 12:51:46 -08:00
@@ -45,7 +45,7 @@
 {
 	struct llc_conn_state_ev *ev;
 	int rc = -ECONNABORTED;
-	struct llc_opt *llc = llc_sk(sk);
+	struct llc_sock *llc = llc_sk(sk);
 
 	if (llc->state == LLC_CONN_STATE_ADM)
 		goto out;
@@ -86,7 +86,7 @@
 	int rc = -EISCONN;
 	struct llc_addr laddr, daddr;
 	struct sk_buff *skb;
-	struct llc_opt *llc = llc_sk(sk);
+	struct llc_sock *llc = llc_sk(sk);
 	struct sock *existing;
 
 	laddr.lsap = llc->sap->laddr.lsap;
diff -Nru a/net/llc/llc_proc.c b/net/llc/llc_proc.c
--- a/net/llc/llc_proc.c	2005-03-11 12:51:41 -08:00
+++ b/net/llc/llc_proc.c	2005-03-11 12:51:41 -08:00
@@ -65,7 +65,7 @@
 static void *llc_seq_next(struct seq_file *seq, void *v, loff_t *pos)
 {
 	struct sock* sk, *next;
-	struct llc_opt *llc;
+	struct llc_sock *llc;
 	struct llc_sap *sap;
 
 	++*pos;
@@ -102,7 +102,7 @@
 {
 	if (v && v != SEQ_START_TOKEN) {
 		struct sock *sk = v;
-		struct llc_opt *llc = llc_sk(sk);
+		struct llc_sock *llc = llc_sk(sk);
 		struct llc_sap *sap = llc->sap;
 
 		read_unlock_bh(&sap->sk_list.lock);
@@ -113,7 +113,7 @@
 static int llc_seq_socket_show(struct seq_file *seq, void *v)
 {
 	struct sock* sk;
-	struct llc_opt *llc;
+	struct llc_sock *llc;
 
 	if (v == SEQ_START_TOKEN) {
 		seq_puts(seq, "SKt Mc local_mac_sap        remote_mac_sap   "
@@ -160,7 +160,7 @@
 static int llc_seq_core_show(struct seq_file *seq, void *v)
 {
 	struct sock* sk;
-	struct llc_opt *llc;
+	struct llc_sock *llc;
 
 	if (v == SEQ_START_TOKEN) {
 		seq_puts(seq, "Connection list:\n"
diff -Nru a/net/llc/llc_sap.c b/net/llc/llc_sap.c
--- a/net/llc/llc_sap.c	2005-03-11 12:51:50 -08:00
+++ b/net/llc/llc_sap.c	2005-03-11 12:51:50 -08:00
@@ -283,7 +283,7 @@
 
 	read_lock_bh(&sap->sk_list.lock);
 	sk_for_each(rc, node, &sap->sk_list.list) {
-		struct llc_opt *llc = llc_sk(rc);
+		struct llc_sock *llc = llc_sk(rc);
 
 		if (rc->sk_type == SOCK_DGRAM &&
 		    llc->laddr.lsap == laddr->lsap &&
diff -Nru a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
--- a/net/netlink/af_netlink.c	2005-03-11 12:51:46 -08:00
+++ b/net/netlink/af_netlink.c	2005-03-11 12:51:46 -08:00
@@ -59,8 +59,9 @@
 #define NL_EMULATE_DEV
 #endif
 
-struct netlink_opt
-{
+struct netlink_sock {
+	/* struct sock has to be the first member of netlink_sock */
+	struct sock		sk;
 	u32			pid;
 	unsigned int		groups;
 	u32			dst_pid;
@@ -73,7 +74,10 @@
 	void			(*data_ready)(struct sock *sk, int bytes);
 };
 
-#define nlk_sk(__sk) ((struct netlink_opt *)(__sk)->sk_protinfo)
+static inline struct netlink_sock *nlk_sk(struct sock *sk)
+{
+	return (struct netlink_sock *)sk;
+}
 
 struct nl_pid_hash {
 	struct hlist_head *table;
@@ -122,8 +126,6 @@
 	BUG_TRAP(!atomic_read(&sk->sk_rmem_alloc));
 	BUG_TRAP(!atomic_read(&sk->sk_wmem_alloc));
 	BUG_TRAP(!nlk_sk(sk)->cb);
-
-	kfree(nlk_sk(sk));
 }
 
 /* This lock without WQ_FLAG_EXCLUSIVE is good on UP and it is _very_ bad on SMP.
@@ -327,7 +329,7 @@
 static int netlink_create(struct socket *sock, int protocol)
 {
 	struct sock *sk;
-	struct netlink_opt *nlk;
+	struct netlink_sock *nlk;
 
 	sock->state = SS_UNCONNECTED;
 
@@ -339,19 +341,15 @@
 
 	sock->ops = &netlink_ops;
 
-	sk = sk_alloc(PF_NETLINK, GFP_KERNEL, 1, NULL);
+	sk = sk_alloc(PF_NETLINK, GFP_KERNEL,
+		      sizeof(struct netlink_sock), NULL);
 	if (!sk)
 		return -ENOMEM;
 
 	sock_init_data(sock,sk);
 	sk_set_owner(sk, THIS_MODULE);
 
-	nlk = sk->sk_protinfo = kmalloc(sizeof(*nlk), GFP_KERNEL);
-	if (!nlk) {
-		sk_free(sk);
-		return -ENOMEM;
-	}
-	memset(nlk, 0, sizeof(*nlk));
+	nlk = nlk_sk(sk);
 
 	spin_lock_init(&nlk->cb_lock);
 	init_waitqueue_head(&nlk->wait);
@@ -364,7 +362,7 @@
 static int netlink_release(struct socket *sock)
 {
 	struct sock *sk = sock->sk;
-	struct netlink_opt *nlk;
+	struct netlink_sock *nlk;
 
 	if (!sk)
 		return 0;
@@ -445,7 +443,7 @@
 static int netlink_bind(struct socket *sock, struct sockaddr *addr, int addr_len)
 {
 	struct sock *sk = sock->sk;
-	struct netlink_opt *nlk = nlk_sk(sk);
+	struct netlink_sock *nlk = nlk_sk(sk);
 	struct sockaddr_nl *nladdr = (struct sockaddr_nl *)addr;
 	int err;
 	
@@ -486,7 +484,7 @@
 {
 	int err = 0;
 	struct sock *sk = sock->sk;
-	struct netlink_opt *nlk = nlk_sk(sk);
+	struct netlink_sock *nlk = nlk_sk(sk);
 	struct sockaddr_nl *nladdr=(struct sockaddr_nl*)addr;
 
 	if (addr->sa_family == AF_UNSPEC) {
@@ -517,7 +515,7 @@
 static int netlink_getname(struct socket *sock, struct sockaddr *addr, int *addr_len, int peer)
 {
 	struct sock *sk = sock->sk;
-	struct netlink_opt *nlk = nlk_sk(sk);
+	struct netlink_sock *nlk = nlk_sk(sk);
 	struct sockaddr_nl *nladdr=(struct sockaddr_nl *)addr;
 	
 	nladdr->nl_family = AF_NETLINK;
@@ -546,7 +544,7 @@
 {
 	int protocol = ssk->sk_protocol;
 	struct sock *sock;
-	struct netlink_opt *nlk;
+	struct netlink_sock *nlk;
 
 	sock = netlink_lookup(protocol, pid);
 	if (!sock)
@@ -592,7 +590,7 @@
  */
 int netlink_attachskb(struct sock *sk, struct sk_buff *skb, int nonblock, long timeo)
 {
-	struct netlink_opt *nlk;
+	struct netlink_sock *nlk;
 
 	nlk = nlk_sk(sk);
 
@@ -635,7 +633,7 @@
 
 int netlink_sendskb(struct sock *sk, struct sk_buff *skb, int protocol)
 {
-	struct netlink_opt *nlk;
+	struct netlink_sock *nlk;
 	int len = skb->len;
 
 	nlk = nlk_sk(sk);
@@ -710,7 +708,7 @@
 
 static __inline__ int netlink_broadcast_deliver(struct sock *sk, struct sk_buff *skb)
 {
-	struct netlink_opt *nlk = nlk_sk(sk);
+	struct netlink_sock *nlk = nlk_sk(sk);
 #ifdef NL_EMULATE_DEV
 	if (nlk->handler) {
 		nlk->handler(sk->sk_protocol, skb);
@@ -741,7 +739,7 @@
 static inline int do_one_broadcast(struct sock *sk,
 				   struct netlink_broadcast_data *p)
 {
-	struct netlink_opt *nlk = nlk_sk(sk);
+	struct netlink_sock *nlk = nlk_sk(sk);
 	int val;
 
 	if (p->exclude_sk == sk)
@@ -833,7 +831,7 @@
 static inline int do_one_set_err(struct sock *sk,
 				 struct netlink_set_err_data *p)
 {
-	struct netlink_opt *nlk = nlk_sk(sk);
+	struct netlink_sock *nlk = nlk_sk(sk);
 
 	if (sk == p->exclude_sk)
 		goto out;
@@ -868,7 +866,7 @@
 
 static inline void netlink_rcv_wake(struct sock *sk)
 {
-	struct netlink_opt *nlk = nlk_sk(sk);
+	struct netlink_sock *nlk = nlk_sk(sk);
 
 	if (!skb_queue_len(&sk->sk_receive_queue))
 		clear_bit(0, &nlk->state);
@@ -881,7 +879,7 @@
 {
 	struct sock_iocb *siocb = kiocb_to_siocb(kiocb);
 	struct sock *sk = sock->sk;
-	struct netlink_opt *nlk = nlk_sk(sk);
+	struct netlink_sock *nlk = nlk_sk(sk);
 	struct sockaddr_nl *addr=msg->msg_name;
 	u32 dst_pid;
 	u32 dst_groups;
@@ -965,7 +963,7 @@
 	struct sock_iocb *siocb = kiocb_to_siocb(kiocb);
 	struct scm_cookie scm;
 	struct sock *sk = sock->sk;
-	struct netlink_opt *nlk = nlk_sk(sk);
+	struct netlink_sock *nlk = nlk_sk(sk);
 	int noblock = flags&MSG_DONTWAIT;
 	size_t copied;
 	struct sk_buff *skb;
@@ -1019,7 +1017,7 @@
 
 static void netlink_data_ready(struct sock *sk, int len)
 {
-	struct netlink_opt *nlk = nlk_sk(sk);
+	struct netlink_sock *nlk = nlk_sk(sk);
 
 	if (nlk->data_ready)
 		nlk->data_ready(sk, len);
@@ -1083,7 +1081,7 @@
 
 static int netlink_dump(struct sock *sk)
 {
-	struct netlink_opt *nlk = nlk_sk(sk);
+	struct netlink_sock *nlk = nlk_sk(sk);
 	struct netlink_callback *cb;
 	struct sk_buff *skb;
 	struct nlmsghdr *nlh;
@@ -1133,7 +1131,7 @@
 {
 	struct netlink_callback *cb;
 	struct sock *sk;
-	struct netlink_opt *nlk;
+	struct netlink_sock *nlk;
 
 	cb = kmalloc(sizeof(*cb), GFP_KERNEL);
 	if (cb == NULL)
@@ -1290,7 +1288,7 @@
 			 "Rmem     Wmem     Dump     Locks\n");
 	else {
 		struct sock *s = v;
-		struct netlink_opt *nlk = nlk_sk(s);
+		struct netlink_sock *nlk = nlk_sk(s);
 
 		seq_printf(seq, "%p %-3d %-6d %08x %-8d %-8d %p %d\n",
 			   s,
diff -Nru a/net/netrom/af_netrom.c b/net/netrom/af_netrom.c
--- a/net/netrom/af_netrom.c	2005-03-11 12:51:46 -08:00
+++ b/net/netrom/af_netrom.c	2005-03-11 12:51:46 -08:00
@@ -63,7 +63,6 @@
 static DEFINE_SPINLOCK(nr_list_lock);
 
 static struct proto_ops nr_proto_ops;
-void nr_init_timers(struct sock *sk);
 
 static struct sock *nr_alloc_sock(void)
 {
diff -Nru a/net/netrom/nr_in.c b/net/netrom/nr_in.c
--- a/net/netrom/nr_in.c	2005-03-11 12:51:42 -08:00
+++ b/net/netrom/nr_in.c	2005-03-11 12:51:42 -08:00
@@ -74,7 +74,6 @@
 static int nr_state1_machine(struct sock *sk, struct sk_buff *skb,
 	int frametype)
 {
-	bh_lock_sock(sk);
 	switch (frametype) {
 	case NR_CONNACK: {
 		nr_cb *nr = nr_sk(sk);
@@ -103,8 +102,6 @@
 	default:
 		break;
 	}
-	bh_unlock_sock(sk);
-
 	return 0;
 }
 
@@ -116,7 +113,6 @@
 static int nr_state2_machine(struct sock *sk, struct sk_buff *skb,
 	int frametype)
 {
-	bh_lock_sock(sk);
 	switch (frametype) {
 	case NR_CONNACK | NR_CHOKE_FLAG:
 		nr_disconnect(sk, ECONNRESET);
@@ -132,8 +128,6 @@
 	default:
 		break;
 	}
-	bh_unlock_sock(sk);
-
 	return 0;
 }
 
@@ -154,7 +148,6 @@
 	nr = skb->data[18];
 	ns = skb->data[17];
 
-	bh_lock_sock(sk);
 	switch (frametype) {
 	case NR_CONNREQ:
 		nr_write_internal(sk, NR_CONNACK);
@@ -265,12 +258,10 @@
 	default:
 		break;
 	}
-	bh_unlock_sock(sk);
-
 	return queued;
 }
 
-/* Higher level upcall for a LAPB frame */
+/* Higher level upcall for a LAPB frame - called with sk locked */
 int nr_process_rx_frame(struct sock *sk, struct sk_buff *skb)
 {
 	nr_cb *nr = nr_sk(sk);
diff -Nru a/net/packet/af_packet.c b/net/packet/af_packet.c
--- a/net/packet/af_packet.c	2005-03-11 12:51:47 -08:00
+++ b/net/packet/af_packet.c	2005-03-11 12:51:47 -08:00
@@ -170,8 +170,9 @@
 
 static void packet_flush_mclist(struct sock *sk);
 
-struct packet_opt
-{
+struct packet_sock {
+	/* struct sock has to be the first member of packet_sock */
+	struct sock		sk;
 	struct tpacket_stats	stats;
 #ifdef CONFIG_PACKET_MMAP
 	char *			*pg_vec;
@@ -199,7 +200,7 @@
 
 #ifdef CONFIG_PACKET_MMAP
 
-static inline char *packet_lookup_frame(struct packet_opt *po, unsigned int position)
+static inline char *packet_lookup_frame(struct packet_sock *po, unsigned int position)
 {
 	unsigned int pg_vec_pos, frame_offset;
 	char *frame;
@@ -213,7 +214,10 @@
 }
 #endif
 
-#define pkt_sk(__sk) ((struct packet_opt *)(__sk)->sk_protinfo)
+static inline struct packet_sock *pkt_sk(struct sock *sk)
+{
+	return (struct packet_sock *)sk;
+}
 
 static void packet_sock_destruct(struct sock *sk)
 {
@@ -225,8 +229,6 @@
 		return;
 	}
 
-	if (pkt_sk(sk))
-		kfree(pkt_sk(sk));
 	atomic_dec(&packet_socks_nr);
 #ifdef PACKET_REFCNT_DEBUG
 	printk(KERN_DEBUG "PACKET socket %p is free, %d are alive\n", sk, atomic_read(&packet_socks_nr));
@@ -440,7 +442,7 @@
 {
 	struct sock *sk;
 	struct sockaddr_ll *sll;
-	struct packet_opt *po;
+	struct packet_sock *po;
 	u8 * skb_head = skb->data;
 	int skb_len = skb->len;
 	unsigned snaplen;
@@ -541,7 +543,7 @@
 static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev,  struct packet_type *pt)
 {
 	struct sock *sk;
-	struct packet_opt *po;
+	struct packet_sock *po;
 	struct sockaddr_ll *sll;
 	struct tpacket_hdr *h;
 	u8 * skb_head = skb->data;
@@ -699,7 +701,7 @@
 	 */
 	 
 	if (saddr == NULL) {
-		struct packet_opt *po = pkt_sk(sk);
+		struct packet_sock *po = pkt_sk(sk);
 
 		ifindex	= po->ifindex;
 		proto	= po->num;
@@ -786,7 +788,7 @@
 static int packet_release(struct socket *sock)
 {
 	struct sock *sk = sock->sk;
-	struct packet_opt *po;
+	struct packet_sock *po;
 
 	if (!sk)
 		return 0;
@@ -844,7 +846,7 @@
 
 static int packet_do_bind(struct sock *sk, struct net_device *dev, int protocol)
 {
-	struct packet_opt *po = pkt_sk(sk);
+	struct packet_sock *po = pkt_sk(sk);
 	/*
 	 *	Detach an existing hook if present.
 	 */
@@ -961,7 +963,7 @@
 static int packet_create(struct socket *sock, int protocol)
 {
 	struct sock *sk;
-	struct packet_opt *po;
+	struct packet_sock *po;
 	int err;
 
 	if (!capable(CAP_NET_RAW))
@@ -976,7 +978,8 @@
 	sock->state = SS_UNCONNECTED;
 
 	err = -ENOBUFS;
-	sk = sk_alloc(PF_PACKET, GFP_KERNEL, 1, NULL);
+	sk = sk_alloc(PF_PACKET, GFP_KERNEL,
+		      sizeof(struct packet_sock), NULL);
 	if (sk == NULL)
 		goto out;
 
@@ -988,10 +991,7 @@
 	sock_init_data(sock,sk);
 	sk_set_owner(sk, THIS_MODULE);
 
-	po = sk->sk_protinfo = kmalloc(sizeof(*po), GFP_KERNEL);
-	if (!po)
-		goto out_free;
-	memset(po, 0, sizeof(*po));
+	po = pkt_sk(sk);
 	sk->sk_family = PF_PACKET;
 	po->num = protocol;
 
@@ -1021,9 +1021,6 @@
 	sk_add_node(sk, &packet_sklist);
 	write_unlock_bh(&packet_sklist_lock);
 	return(0);
-
-out_free:
-	sk_free(sk);
 out:
 	return err;
 }
@@ -1141,7 +1138,7 @@
 {
 	struct net_device *dev;
 	struct sock *sk = sock->sk;
-	struct packet_opt *po = pkt_sk(sk);
+	struct packet_sock *po = pkt_sk(sk);
 	struct sockaddr_ll *sll = (struct sockaddr_ll*)uaddr;
 
 	if (peer)
@@ -1195,7 +1192,7 @@
 
 static int packet_mc_add(struct sock *sk, struct packet_mreq *mreq)
 {
-	struct packet_opt *po = pkt_sk(sk);
+	struct packet_sock *po = pkt_sk(sk);
 	struct packet_mclist *ml, *i;
 	struct net_device *dev;
 	int err;
@@ -1274,7 +1271,7 @@
 
 static void packet_flush_mclist(struct sock *sk)
 {
-	struct packet_opt *po = pkt_sk(sk);
+	struct packet_sock *po = pkt_sk(sk);
 	struct packet_mclist *ml;
 
 	if (!po->mclist)
@@ -1355,7 +1352,7 @@
 {
 	int len;
 	struct sock *sk = sock->sk;
-	struct packet_opt *po = pkt_sk(sk);
+	struct packet_sock *po = pkt_sk(sk);
 
 	if (level != SOL_PACKET)
 		return -ENOPROTOOPT;
@@ -1401,7 +1398,7 @@
 
 	read_lock(&packet_sklist_lock);
 	sk_for_each(sk, node, &packet_sklist) {
-		struct packet_opt *po = pkt_sk(sk);
+		struct packet_sock *po = pkt_sk(sk);
 
 		switch (msg) {
 		case NETDEV_UNREGISTER:
@@ -1504,7 +1501,7 @@
 				poll_table *wait)
 {
 	struct sock *sk = sock->sk;
-	struct packet_opt *po = pkt_sk(sk);
+	struct packet_sock *po = pkt_sk(sk);
 	unsigned int mask = datagram_poll(file, sock, wait);
 
 	spin_lock_bh(&sk->sk_receive_queue.lock);
@@ -1579,7 +1576,7 @@
 static int packet_set_ring(struct sock *sk, struct tpacket_req *req, int closing)
 {
 	char **pg_vec = NULL;
-	struct packet_opt *po = pkt_sk(sk);
+	struct packet_sock *po = pkt_sk(sk);
 	int was_running, num, order = 0;
 	int err = 0;
 	
@@ -1709,7 +1706,7 @@
 static int packet_mmap(struct file *file, struct socket *sock, struct vm_area_struct *vma)
 {
 	struct sock *sk = sock->sk;
-	struct packet_opt *po = pkt_sk(sk);
+	struct packet_sock *po = pkt_sk(sk);
 	unsigned long size;
 	unsigned long start;
 	int err = -EINVAL;
@@ -1839,7 +1836,7 @@
 		seq_puts(seq, "sk       RefCnt Type Proto  Iface R Rmem   User   Inode\n");
 	else {
 		struct sock *s = v;
-		const struct packet_opt *po = pkt_sk(s);
+		const struct packet_sock *po = pkt_sk(s);
 
 		seq_printf(seq,
 			   "%p %-6d %-4d %04x   %-5d %1d %-6u %-6u %-6lu\n",
diff -Nru a/net/rose/rose_route.c b/net/rose/rose_route.c
--- a/net/rose/rose_route.c	2005-03-11 12:51:51 -08:00
+++ b/net/rose/rose_route.c	2005-03-11 12:51:51 -08:00
@@ -727,7 +727,8 @@
 		}
 		if (rose_route.mask > 10) /* Mask can't be more than 10 digits */
 			return -EINVAL;
-
+		if (rose_route.ndigis > 8) /* No more than 8 digipeats */
+			return -EINVAL;
 		err = rose_add_node(&rose_route, dev);
 		dev_put(dev);
 		return err;
diff -Nru a/net/rxrpc/main.c b/net/rxrpc/main.c
--- a/net/rxrpc/main.c	2005-03-11 12:51:51 -08:00
+++ b/net/rxrpc/main.c	2005-03-11 12:51:51 -08:00
@@ -22,12 +22,6 @@
 #include <rxrpc/message.h>
 #include "internal.h"
 
-static int rxrpc_initialise(void);
-static void rxrpc_cleanup(void);
-
-module_init(rxrpc_initialise);
-module_exit(rxrpc_cleanup);
-
 MODULE_DESCRIPTION("Rx RPC implementation");
 MODULE_AUTHOR("Red Hat, Inc.");
 MODULE_LICENSE("GPL");
@@ -38,7 +32,7 @@
 /*
  * initialise the Rx module
  */
-static int rxrpc_initialise(void)
+static int __init rxrpc_initialise(void)
 {
 	int ret;
 
@@ -93,6 +87,8 @@
 	return ret;
 } /* end rxrpc_initialise() */
 
+module_init(rxrpc_initialise);
+
 /*****************************************************************************/
 /*
  * clean up the Rx module
@@ -135,6 +131,8 @@
 
 	kleave("");
 } /* end rxrpc_cleanup() */
+
+module_exit(rxrpc_cleanup);
 
 /*****************************************************************************/
 /*
diff -Nru a/net/sched/Kconfig b/net/sched/Kconfig
--- a/net/sched/Kconfig	2005-03-11 12:51:51 -08:00
+++ b/net/sched/Kconfig	2005-03-11 12:51:51 -08:00
@@ -269,6 +269,16 @@
 	  Documentation and software is at
 	  <http://diffserv.sourceforge.net/>.
 
+config NET_CLS_BASIC
+	tristate "Basic classifier"
+	depends on NET_CLS
+	---help---
+	  Say Y here if you want to be able to classify packets using
+	  only extended matches and actions.
+
+	  To compile this code as a module, choose M here: the
+	  module will be called cls_basic.
+
 config NET_CLS_TCINDEX
 	tristate "TC index classifier"
 	depends on NET_CLS
@@ -374,6 +384,70 @@
 
 	  To compile this code as a module, choose M here: the
 	  module will be called cls_rsvp6.
+
+config NET_EMATCH
+	bool "Extended Matches"
+	depends on NET_CLS
+	---help---
+	  Say Y here if you want to use extended matches on top of classifiers
+	  and select the extended matches below.
+
+	  Extended matches are small classification helpers not worth writing
+	  a separate classifier.
+
+	  You must have a recent version of the iproute2 tools in order to use
+	  extended matches.
+
+config NET_EMATCH_STACK
+	int "Stack size"
+	depends on NET_EMATCH
+	default "32"
+	---help---
+	  Size of the local stack variable used while evaluating the tree of
+	  ematches. Limits the depth of the tree, i.e. the number of
+	  encapsulated precedences. Every level requires 4 bytes of addtional
+	  stack space.
+
+config NET_EMATCH_CMP
+	tristate "Simple packet data comparison"
+	depends on NET_EMATCH
+	---help---
+	  Say Y here if you want to be able to classify packets based on
+	  simple packet data comparisons for 8, 16, and 32bit values.
+
+	  To compile this code as a module, choose M here: the
+	  module will be called em_cmp.
+
+config NET_EMATCH_NBYTE
+	tristate "Multi byte comparison"
+	depends on NET_EMATCH
+	---help---
+	  Say Y here if you want to be able to classify packets based on
+	  multiple byte comparisons mainly useful for IPv6 address comparisons.
+
+	  To compile this code as a module, choose M here: the
+	  module will be called em_nbyte.
+
+config NET_EMATCH_U32
+	tristate "U32 hashing key"
+	depends on NET_EMATCH
+	---help---
+	  Say Y here if you want to be able to classify packets using
+	  the famous u32 key in combination with logic relations.
+
+	  To compile this code as a module, choose M here: the
+	  module will be called em_u32.
+
+config NET_EMATCH_META
+	tristate "Metadata"
+	depends on NET_EMATCH
+	---help---
+	  Say Y here if you want to be ablt to classify packets based on
+	  metadata such as load average, netfilter attributes, socket
+	  attributes and routing decisions.
+
+	  To compile this code as a module, choose M here: the
+	  module will be called em_meta.
 
 config NET_CLS_ACT
 	bool "Packet ACTION"
diff -Nru a/net/sched/Makefile b/net/sched/Makefile
--- a/net/sched/Makefile	2005-03-11 12:51:46 -08:00
+++ b/net/sched/Makefile	2005-03-11 12:51:46 -08:00
@@ -33,3 +33,9 @@
 obj-$(CONFIG_NET_CLS_RSVP)	+= cls_rsvp.o
 obj-$(CONFIG_NET_CLS_TCINDEX)	+= cls_tcindex.o
 obj-$(CONFIG_NET_CLS_RSVP6)	+= cls_rsvp6.o
+obj-$(CONFIG_NET_CLS_BASIC)	+= cls_basic.o
+obj-$(CONFIG_NET_EMATCH)	+= ematch.o
+obj-$(CONFIG_NET_EMATCH_CMP)	+= em_cmp.o
+obj-$(CONFIG_NET_EMATCH_NBYTE)	+= em_nbyte.o
+obj-$(CONFIG_NET_EMATCH_U32)	+= em_u32.o
+obj-$(CONFIG_NET_EMATCH_META)	+= em_meta.o
diff -Nru a/net/sched/cls_basic.c b/net/sched/cls_basic.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/net/sched/cls_basic.c	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,303 @@
+/*
+ * net/sched/cls_basic.c	Basic Packet Classifier.
+ *
+ *		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.
+ *
+ * Authors:	Thomas Graf <tgraf@suug.ch>
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/errno.h>
+#include <linux/rtnetlink.h>
+#include <linux/skbuff.h>
+#include <net/act_api.h>
+#include <net/pkt_cls.h>
+
+struct basic_head
+{
+	u32			hgenerator;
+	struct list_head	flist;
+};
+
+struct basic_filter
+{
+	u32			handle;
+	struct tcf_exts		exts;
+	struct tcf_ematch_tree	ematches;
+	struct tcf_result	res;
+	struct list_head	link;
+};
+
+static struct tcf_ext_map basic_ext_map = {
+	.action = TCA_BASIC_ACT,
+	.police = TCA_BASIC_POLICE
+};
+
+static int basic_classify(struct sk_buff *skb, struct tcf_proto *tp,
+			  struct tcf_result *res)
+{
+	int r;
+	struct basic_head *head = (struct basic_head *) tp->root;
+	struct basic_filter *f;
+
+	list_for_each_entry(f, &head->flist, link) {
+		if (!tcf_em_tree_match(skb, &f->ematches, NULL))
+			continue;
+		*res = f->res;
+		r = tcf_exts_exec(skb, &f->exts, res);
+		if (r < 0)
+			continue;
+		return r;
+	}
+	return -1;
+}
+
+static unsigned long basic_get(struct tcf_proto *tp, u32 handle)
+{
+	unsigned long l = 0UL;
+	struct basic_head *head = (struct basic_head *) tp->root;
+	struct basic_filter *f;
+
+	if (head == NULL)
+		return 0UL;
+
+	list_for_each_entry(f, &head->flist, link)
+		if (f->handle == handle)
+			l = (unsigned long) f;
+
+	return l;
+}
+
+static void basic_put(struct tcf_proto *tp, unsigned long f)
+{
+}
+
+static int basic_init(struct tcf_proto *tp)
+{
+	return 0;
+}
+
+static inline void basic_delete_filter(struct tcf_proto *tp,
+				       struct basic_filter *f)
+{
+	tcf_unbind_filter(tp, &f->res);
+	tcf_exts_destroy(tp, &f->exts);
+	tcf_em_tree_destroy(tp, &f->ematches);
+	kfree(f);
+}
+
+static void basic_destroy(struct tcf_proto *tp)
+{
+	struct basic_head *head = (struct basic_head *) xchg(&tp->root, NULL);
+	struct basic_filter *f, *n;
+	
+	list_for_each_entry_safe(f, n, &head->flist, link) {
+		list_del(&f->link);
+		basic_delete_filter(tp, f);
+	}
+}
+
+static int basic_delete(struct tcf_proto *tp, unsigned long arg)
+{
+	struct basic_head *head = (struct basic_head *) tp->root;
+	struct basic_filter *t, *f = (struct basic_filter *) arg;
+
+	list_for_each_entry(t, &head->flist, link)
+		if (t == f) {
+			tcf_tree_lock(tp);
+			list_del(&t->link);
+			tcf_tree_unlock(tp);
+			basic_delete_filter(tp, t);
+			return 0;
+		}
+
+	return -ENOENT;
+}
+
+static inline int basic_set_parms(struct tcf_proto *tp, struct basic_filter *f,
+				  unsigned long base, struct rtattr **tb,
+				  struct rtattr *est)
+{
+	int err = -EINVAL;
+	struct tcf_exts e;
+	struct tcf_ematch_tree t;
+
+	if (tb[TCA_BASIC_CLASSID-1])
+		if (RTA_PAYLOAD(tb[TCA_BASIC_CLASSID-1]) < sizeof(u32))
+			return err;
+
+	err = tcf_exts_validate(tp, tb, est, &e, &basic_ext_map);
+	if (err < 0)
+		return err;
+
+	err = tcf_em_tree_validate(tp, tb[TCA_BASIC_EMATCHES-1], &t);
+	if (err < 0)
+		goto errout;
+
+	if (tb[TCA_BASIC_CLASSID-1]) {
+		f->res.classid = *(u32*)RTA_DATA(tb[TCA_BASIC_CLASSID-1]);
+		tcf_bind_filter(tp, &f->res, base);
+	}
+
+	tcf_exts_change(tp, &f->exts, &e);
+	tcf_em_tree_change(tp, &f->ematches, &t);
+
+	return 0;
+errout:
+	tcf_exts_destroy(tp, &e);
+	return err;
+}
+
+static int basic_change(struct tcf_proto *tp, unsigned long base, u32 handle,
+		        struct rtattr **tca, unsigned long *arg)
+{
+	int err = -EINVAL;
+	struct basic_head *head = (struct basic_head *) tp->root;
+	struct rtattr *tb[TCA_BASIC_MAX];
+	struct basic_filter *f = (struct basic_filter *) *arg;
+
+	if (tca[TCA_OPTIONS-1] == NULL)
+		return -EINVAL;
+
+	if (rtattr_parse_nested(tb, TCA_BASIC_MAX, tca[TCA_OPTIONS-1]) < 0)
+		return -EINVAL;
+
+	if (f != NULL) {
+		if (handle && f->handle != handle)
+			return -EINVAL;
+		return basic_set_parms(tp, f, base, tb, tca[TCA_RATE-1]);
+	}
+
+	err = -ENOBUFS;
+	if (head == NULL) {
+		head = kmalloc(sizeof(*head), GFP_KERNEL);
+		if (head == NULL)
+			goto errout;
+
+		memset(head, 0, sizeof(*head));
+		INIT_LIST_HEAD(&head->flist);
+		tp->root = head;
+	}
+
+	f = kmalloc(sizeof(*f), GFP_KERNEL);
+	if (f == NULL)
+		goto errout;
+	memset(f, 0, sizeof(*f));
+
+	err = -EINVAL;
+	if (handle)
+		f->handle = handle;
+	else {
+		int i = 0x80000000;
+		do {
+			if (++head->hgenerator == 0x7FFFFFFF)
+				head->hgenerator = 1;
+		} while (--i > 0 && basic_get(tp, head->hgenerator));
+
+		if (i <= 0) {
+			printk(KERN_ERR "Insufficient number of handles\n");
+			goto errout;
+		}
+
+		f->handle = head->hgenerator;
+	}
+
+	err = basic_set_parms(tp, f, base, tb, tca[TCA_RATE-1]);
+	if (err < 0)
+		goto errout;
+
+	tcf_tree_lock(tp);
+	list_add(&f->link, &head->flist);
+	tcf_tree_unlock(tp);
+	*arg = (unsigned long) f;
+
+	return 0;
+errout:
+	if (*arg == 0UL && f)
+		kfree(f);
+
+	return err;
+}
+
+static void basic_walk(struct tcf_proto *tp, struct tcf_walker *arg)
+{
+	struct basic_head *head = (struct basic_head *) tp->root;
+	struct basic_filter *f;
+
+	list_for_each_entry(f, &head->flist, link) {
+		if (arg->count < arg->skip)
+			goto skip;
+
+		if (arg->fn(tp, (unsigned long) f, arg) < 0) {
+			arg->stop = 1;
+			break;
+		}
+skip:
+		arg->count++;
+	}
+}
+
+static int basic_dump(struct tcf_proto *tp, unsigned long fh,
+		      struct sk_buff *skb, struct tcmsg *t)
+{
+	struct basic_filter *f = (struct basic_filter *) fh;
+	unsigned char *b = skb->tail;
+	struct rtattr *rta;
+
+	if (f == NULL)
+		return skb->len;
+
+	t->tcm_handle = f->handle;
+
+	rta = (struct rtattr *) b;
+	RTA_PUT(skb, TCA_OPTIONS, 0, NULL);
+
+	if (tcf_exts_dump(skb, &f->exts, &basic_ext_map) < 0 ||
+	    tcf_em_tree_dump(skb, &f->ematches, TCA_BASIC_EMATCHES) < 0)
+		goto rtattr_failure;
+
+	rta->rta_len = (skb->tail - b);
+	return skb->len;
+
+rtattr_failure:
+	skb_trim(skb, b - skb->data);
+	return -1;
+}
+
+static struct tcf_proto_ops cls_basic_ops = {
+	.kind		=	"basic",
+	.classify	=	basic_classify,
+	.init		=	basic_init,
+	.destroy	=	basic_destroy,
+	.get		=	basic_get,
+	.put		=	basic_put,
+	.change		=	basic_change,
+	.delete		=	basic_delete,
+	.walk		=	basic_walk,
+	.dump		=	basic_dump,
+	.owner		=	THIS_MODULE,
+};
+
+static int __init init_basic(void)
+{
+	return register_tcf_proto_ops(&cls_basic_ops);
+}
+
+static void __exit exit_basic(void) 
+{
+	unregister_tcf_proto_ops(&cls_basic_ops);
+}
+
+module_init(init_basic)
+module_exit(exit_basic)
+MODULE_LICENSE("GPL");
+
diff -Nru a/net/sched/cls_u32.c b/net/sched/cls_u32.c
--- a/net/sched/cls_u32.c	2005-03-11 12:51:42 -08:00
+++ b/net/sched/cls_u32.c	2005-03-11 12:51:42 -08:00
@@ -58,14 +58,6 @@
 #include <net/act_api.h>
 #include <net/pkt_cls.h>
 
-
-struct tc_u32_mark
-{
-	u32		val;
-	u32		mask;
-	u32		success;
-};
-
 struct tc_u_knode
 {
 	struct tc_u_knode	*next;
diff -Nru a/net/sched/em_cmp.c b/net/sched/em_cmp.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/net/sched/em_cmp.c	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,101 @@
+/*
+ * net/sched/em_cmp.c	Simple packet data comparison ematch
+ *
+ *		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.
+ *
+ * Authors:	Thomas Graf <tgraf@suug.ch>
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/skbuff.h>
+#include <linux/tc_ematch/tc_em_cmp.h>
+#include <net/pkt_cls.h>
+
+static inline int cmp_needs_transformation(struct tcf_em_cmp *cmp)
+{
+	return unlikely(cmp->flags & TCF_EM_CMP_TRANS);
+}
+
+static int em_cmp_match(struct sk_buff *skb, struct tcf_ematch *em,
+			struct tcf_pkt_info *info)
+{
+	struct tcf_em_cmp *cmp = (struct tcf_em_cmp *) em->data;
+	unsigned char *ptr = tcf_get_base_ptr(skb, cmp->layer) + cmp->off;
+	u32 val = 0;
+
+	if (!tcf_valid_offset(skb, ptr, cmp->align))
+		return 0;
+
+	switch (cmp->align) {
+		case TCF_EM_ALIGN_U8:
+			val = *ptr;
+			break;
+
+		case TCF_EM_ALIGN_U16:
+			val = *ptr << 8;
+			val |= *(ptr+1);
+
+			if (cmp_needs_transformation(cmp))
+				val = be16_to_cpu(val);
+			break;
+
+		case TCF_EM_ALIGN_U32:
+			/* Worth checking boundries? The branching seems
+			 * to get worse. Visit again. */
+			val = *ptr << 24;
+			val |= *(ptr+1) << 16;
+			val |= *(ptr+2) << 8;
+			val |= *(ptr+3);
+
+			if (cmp_needs_transformation(cmp))
+				val = be32_to_cpu(val);
+			break;
+
+		default:
+			return 0;
+	}
+
+	if (cmp->mask)
+		val &= cmp->mask;
+
+	switch (cmp->opnd) {
+		case TCF_EM_OPND_EQ:
+			return val == cmp->val;
+		case TCF_EM_OPND_LT:
+			return val < cmp->val;
+		case TCF_EM_OPND_GT:
+			return val > cmp->val;
+	}
+
+	return 0;
+}
+
+static struct tcf_ematch_ops em_cmp_ops = {
+	.kind	  = TCF_EM_CMP,
+	.datalen  = sizeof(struct tcf_em_cmp),
+	.match	  = em_cmp_match,
+	.owner	  = THIS_MODULE,
+	.link	  = LIST_HEAD_INIT(em_cmp_ops.link)
+};
+
+static int __init init_em_cmp(void)
+{
+	return tcf_em_register(&em_cmp_ops);
+}
+
+static void __exit exit_em_cmp(void) 
+{
+	tcf_em_unregister(&em_cmp_ops);
+}
+
+MODULE_LICENSE("GPL");
+
+module_init(init_em_cmp);
+module_exit(exit_em_cmp);
+
diff -Nru a/net/sched/em_meta.c b/net/sched/em_meta.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/net/sched/em_meta.c	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,661 @@
+/*
+ * net/sched/em_meta.c	Metadata ematch
+ *
+ *		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.
+ *
+ * Authors:	Thomas Graf <tgraf@suug.ch>
+ *
+ * ==========================================================================
+ * 
+ * 	The metadata ematch compares two meta objects where each object
+ * 	represents either a meta value stored in the kernel or a static
+ * 	value provided by userspace. The objects are not provided by
+ * 	userspace itself but rather a definition providing the information
+ * 	to build them. Every object is of a certain type which must be
+ * 	equal to the object it is being compared to.
+ *
+ * 	The definition of a objects conists of the type (meta type), a
+ * 	identifier (meta id) and additional type specific information.
+ * 	The meta id is either TCF_META_TYPE_VALUE for values provided by
+ * 	userspace or a index to the meta operations table consisting of
+ * 	function pointers to type specific meta data collectors returning
+ * 	the value of the requested meta value.
+ *
+ * 	         lvalue                                   rvalue
+ * 	      +-----------+                           +-----------+
+ * 	      | type: INT |                           | type: INT |
+ * 	 def  | id: INDEV |                           | id: VALUE |
+ * 	      | data:     |                           | data: 3   |
+ * 	      +-----------+                           +-----------+
+ * 	            |                                       |
+ * 	            ---> meta_ops[INT][INDEV](...)          |
+ *                            |                            |
+ * 	            -----------                             |
+ * 	            V                                       V
+ * 	      +-----------+                           +-----------+
+ * 	      | type: INT |                           | type: INT |
+ * 	 obj  | id: INDEV |                           | id: VALUE |
+ * 	      | data: 2   |<--data got filled out     | data: 3   |
+ * 	      +-----------+                           +-----------+
+ * 	            |                                         |
+ * 	            --------------> 2  equals 3 <--------------
+ *
+ * 	This is a simplified schema, the complexity varies depending
+ * 	on the meta type. Obviously, the length of the data must also
+ * 	be provided for non-numeric types.
+ *
+ * 	Additionaly, type dependant modifiers such as shift operators
+ * 	or mask may be applied to extend the functionaliy. As of now,
+ * 	the variable length type supports shifting the byte string to
+ * 	the right, eating up any number of octets and thus supporting
+ * 	wildcard interface name comparisons such as "ppp%" matching
+ * 	ppp0..9.
+ *
+ * 	NOTE: Certain meta values depend on other subsystems and are
+ * 	      only available if that subsytem is enabled in the kernel.
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/skbuff.h>
+#include <linux/random.h>
+#include <linux/tc_ematch/tc_em_meta.h>
+#include <net/dst.h>
+#include <net/route.h>
+#include <net/pkt_cls.h>
+
+struct meta_obj
+{
+	unsigned long		value;
+	unsigned int		len;
+};
+
+struct meta_value
+{
+	struct tcf_meta_val	hdr;
+	unsigned long		val;
+	unsigned int		len;
+};
+
+struct meta_match
+{
+	struct meta_value	lvalue;
+	struct meta_value	rvalue;
+};
+
+static inline int meta_id(struct meta_value *v)
+{
+	return TCF_META_ID(v->hdr.kind);
+}
+
+static inline int meta_type(struct meta_value *v)
+{
+	return TCF_META_TYPE(v->hdr.kind);
+}
+
+#define META_COLLECTOR(FUNC) static void meta_##FUNC(struct sk_buff *skb, \
+	struct tcf_pkt_info *info, struct meta_value *v, \
+	struct meta_obj *dst, int *err)
+
+/**************************************************************************
+ * System status & misc
+ **************************************************************************/
+
+META_COLLECTOR(int_random)
+{
+	get_random_bytes(&dst->value, sizeof(dst->value));
+}
+
+static inline unsigned long fixed_loadavg(int load)
+{
+	int rnd_load = load + (FIXED_1/200);
+	int rnd_frac = ((rnd_load & (FIXED_1-1)) * 100) >> FSHIFT;
+
+	return ((rnd_load >> FSHIFT) * 100) + rnd_frac;
+}
+
+META_COLLECTOR(int_loadavg_0)
+{
+	dst->value = fixed_loadavg(avenrun[0]);
+}
+
+META_COLLECTOR(int_loadavg_1)
+{
+	dst->value = fixed_loadavg(avenrun[1]);
+}
+
+META_COLLECTOR(int_loadavg_2)
+{
+	dst->value = fixed_loadavg(avenrun[2]);
+}
+
+/**************************************************************************
+ * Device names & indices
+ **************************************************************************/
+
+static inline int int_dev(struct net_device *dev, struct meta_obj *dst)
+{
+	if (unlikely(dev == NULL))
+		return -1;
+
+	dst->value = dev->ifindex;
+	return 0;
+}
+
+static inline int var_dev(struct net_device *dev, struct meta_obj *dst)
+{
+	if (unlikely(dev == NULL))
+		return -1;
+
+	dst->value = (unsigned long) dev->name;
+	dst->len = strlen(dev->name);
+	return 0;
+}
+
+META_COLLECTOR(int_dev)
+{
+	*err = int_dev(skb->dev, dst);
+}
+
+META_COLLECTOR(var_dev)
+{
+	*err = var_dev(skb->dev, dst);
+}
+
+META_COLLECTOR(int_indev)
+{
+	*err = int_dev(skb->input_dev, dst);
+}
+
+META_COLLECTOR(var_indev)
+{
+	*err = var_dev(skb->input_dev, dst);
+}
+
+META_COLLECTOR(int_realdev)
+{
+	*err = int_dev(skb->real_dev, dst);
+}
+
+META_COLLECTOR(var_realdev)
+{
+	*err = var_dev(skb->real_dev, dst);
+}
+
+/**************************************************************************
+ * skb attributes
+ **************************************************************************/
+
+META_COLLECTOR(int_priority)
+{
+	dst->value = skb->priority;
+}
+
+META_COLLECTOR(int_protocol)
+{
+	/* Let userspace take care of the byte ordering */
+	dst->value = skb->protocol;
+}
+
+META_COLLECTOR(int_security)
+{
+	dst->value = skb->security;
+}
+
+META_COLLECTOR(int_pkttype)
+{
+	dst->value = skb->pkt_type;
+}
+
+META_COLLECTOR(int_pktlen)
+{
+	dst->value = skb->len;
+}
+
+META_COLLECTOR(int_datalen)
+{
+	dst->value = skb->data_len;
+}
+
+META_COLLECTOR(int_maclen)
+{
+	dst->value = skb->mac_len;
+}
+
+/**************************************************************************
+ * Netfilter
+ **************************************************************************/
+
+#ifdef CONFIG_NETFILTER
+META_COLLECTOR(int_nfmark)
+{
+	dst->value = skb->nfmark;
+}
+#endif
+
+/**************************************************************************
+ * Traffic Control
+ **************************************************************************/
+
+META_COLLECTOR(int_tcindex)
+{
+	dst->value = skb->tc_index;
+}
+
+#ifdef CONFIG_NET_CLS_ACT
+META_COLLECTOR(int_tcverd)
+{
+	dst->value = skb->tc_verd;
+}
+
+META_COLLECTOR(int_tcclassid)
+{
+	dst->value = skb->tc_classid;
+}
+#endif
+
+/**************************************************************************
+ * Routing
+ **************************************************************************/
+
+#ifdef CONFIG_NET_CLS_ROUTE
+META_COLLECTOR(int_rtclassid)
+{
+	if (unlikely(skb->dst == NULL))
+		*err = -1;
+	else
+		dst->value = skb->dst->tclassid;
+}
+#endif
+
+META_COLLECTOR(int_rtiif)
+{
+	if (unlikely(skb->dst == NULL))
+		*err = -1;
+	else
+		dst->value = ((struct rtable*) skb->dst)->fl.iif;
+}
+
+/**************************************************************************
+ * Meta value collectors assignment table
+ **************************************************************************/
+
+struct meta_ops
+{
+	void		(*get)(struct sk_buff *, struct tcf_pkt_info *,
+			       struct meta_value *, struct meta_obj *, int *);
+};
+
+/* Meta value operations table listing all meta value collectors and
+ * assigns them to a type and meta id. */
+static struct meta_ops __meta_ops[TCF_META_TYPE_MAX+1][TCF_META_ID_MAX+1] = {
+	[TCF_META_TYPE_VAR] = {
+		[TCF_META_ID_DEV]	= { .get = meta_var_dev },
+		[TCF_META_ID_INDEV]	= { .get = meta_var_indev },
+		[TCF_META_ID_REALDEV]	= { .get = meta_var_realdev }
+	},
+	[TCF_META_TYPE_INT] = {
+		[TCF_META_ID_RANDOM]	= { .get = meta_int_random },
+		[TCF_META_ID_LOADAVG_0]	= { .get = meta_int_loadavg_0 },
+		[TCF_META_ID_LOADAVG_1]	= { .get = meta_int_loadavg_1 },
+		[TCF_META_ID_LOADAVG_2]	= { .get = meta_int_loadavg_2 },
+		[TCF_META_ID_DEV]	= { .get = meta_int_dev },
+		[TCF_META_ID_INDEV]	= { .get = meta_int_indev },
+		[TCF_META_ID_REALDEV]	= { .get = meta_int_realdev },
+		[TCF_META_ID_PRIORITY]	= { .get = meta_int_priority },
+		[TCF_META_ID_PROTOCOL]	= { .get = meta_int_protocol },
+		[TCF_META_ID_SECURITY]	= { .get = meta_int_security },
+		[TCF_META_ID_PKTTYPE]	= { .get = meta_int_pkttype },
+		[TCF_META_ID_PKTLEN]	= { .get = meta_int_pktlen },
+		[TCF_META_ID_DATALEN]	= { .get = meta_int_datalen },
+		[TCF_META_ID_MACLEN]	= { .get = meta_int_maclen },
+#ifdef CONFIG_NETFILTER
+		[TCF_META_ID_NFMARK]	= { .get = meta_int_nfmark },
+#endif
+		[TCF_META_ID_TCINDEX]	= { .get = meta_int_tcindex },
+#ifdef CONFIG_NET_CLS_ACT
+		[TCF_META_ID_TCVERDICT]	= { .get = meta_int_tcverd },
+		[TCF_META_ID_TCCLASSID]	= { .get = meta_int_tcclassid },
+#endif
+#ifdef CONFIG_NET_CLS_ROUTE
+		[TCF_META_ID_RTCLASSID]	= { .get = meta_int_rtclassid },
+#endif
+		[TCF_META_ID_RTIIF]	= { .get = meta_int_rtiif }
+	}
+};
+
+static inline struct meta_ops * meta_ops(struct meta_value *val)
+{
+	return &__meta_ops[meta_type(val)][meta_id(val)];
+}
+
+/**************************************************************************
+ * Type specific operations for TCF_META_TYPE_VAR
+ **************************************************************************/
+
+static int meta_var_compare(struct meta_obj *a, struct meta_obj *b)
+{
+	int r = a->len - b->len;
+
+	if (r == 0)
+		r = memcmp((void *) a->value, (void *) b->value, a->len);
+
+	return r;
+}
+
+static int meta_var_change(struct meta_value *dst, struct rtattr *rta)
+{
+	int len = RTA_PAYLOAD(rta);
+
+	dst->val = (unsigned long) kmalloc(len, GFP_KERNEL);
+	if (dst->val == 0UL)
+		return -ENOMEM;
+	memcpy((void *) dst->val, RTA_DATA(rta), len);
+	dst->len = len;
+	return 0;
+}
+
+static void meta_var_destroy(struct meta_value *v)
+{
+	if (v->val)
+		kfree((void *) v->val);
+}
+
+static void meta_var_apply_extras(struct meta_value *v,
+				  struct meta_obj *dst)
+{
+	int shift = v->hdr.shift;
+
+	if (shift && shift < dst->len)
+		dst->len -= shift;
+}
+
+static int meta_var_dump(struct sk_buff *skb, struct meta_value *v, int tlv)
+{
+	if (v->val && v->len)
+		RTA_PUT(skb, tlv, v->len, (void *) v->val);
+	return 0;
+
+rtattr_failure:
+	return -1;
+}
+
+/**************************************************************************
+ * Type specific operations for TCF_META_TYPE_INT
+ **************************************************************************/
+
+static int meta_int_compare(struct meta_obj *a, struct meta_obj *b)
+{
+	/* Let gcc optimize it, the unlikely is not really based on
+	 * some numbers but jump free code for mismatches seems
+	 * more logical. */
+	if (unlikely(a == b))
+		return 0;
+	else if (a < b)
+		return -1;
+	else
+		return 1;
+}
+
+static int meta_int_change(struct meta_value *dst, struct rtattr *rta)
+{
+	if (RTA_PAYLOAD(rta) >= sizeof(unsigned long)) {
+		dst->val = *(unsigned long *) RTA_DATA(rta);
+		dst->len = sizeof(unsigned long);
+	} else if (RTA_PAYLOAD(rta) == sizeof(u32)) {
+		dst->val = *(u32 *) RTA_DATA(rta);
+		dst->len = sizeof(u32);
+	} else
+		return -EINVAL;
+
+	return 0;
+}
+
+static void meta_int_apply_extras(struct meta_value *v,
+				  struct meta_obj *dst)
+{
+	if (v->hdr.shift)
+		dst->value >>= v->hdr.shift;
+
+	if (v->val)
+		dst->value &= v->val;
+}
+
+static int meta_int_dump(struct sk_buff *skb, struct meta_value *v, int tlv)
+{
+	if (v->len == sizeof(unsigned long))
+		RTA_PUT(skb, tlv, sizeof(unsigned long), &v->val);
+	else if (v->len == sizeof(u32)) {
+		u32 d = v->val;
+		RTA_PUT(skb, tlv, sizeof(d), &d);
+	}
+
+	return 0;
+
+rtattr_failure:
+	return -1;
+}
+
+/**************************************************************************
+ * Type specific operations table
+ **************************************************************************/
+
+struct meta_type_ops
+{
+	void	(*destroy)(struct meta_value *);
+	int	(*compare)(struct meta_obj *, struct meta_obj *);
+	int	(*change)(struct meta_value *, struct rtattr *);
+	void	(*apply_extras)(struct meta_value *, struct meta_obj *);
+	int	(*dump)(struct sk_buff *, struct meta_value *, int);
+};
+
+static struct meta_type_ops __meta_type_ops[TCF_META_TYPE_MAX+1] = {
+	[TCF_META_TYPE_VAR] = {
+		.destroy = meta_var_destroy,
+		.compare = meta_var_compare,
+		.change = meta_var_change,
+		.apply_extras = meta_var_apply_extras,
+		.dump = meta_var_dump
+	},
+	[TCF_META_TYPE_INT] = {
+		.compare = meta_int_compare,
+		.change = meta_int_change,
+		.apply_extras = meta_int_apply_extras,
+		.dump = meta_int_dump
+	}
+};
+
+static inline struct meta_type_ops * meta_type_ops(struct meta_value *v)
+{
+	return &__meta_type_ops[meta_type(v)];
+}
+
+/**************************************************************************
+ * Core
+ **************************************************************************/
+
+static inline int meta_get(struct sk_buff *skb, struct tcf_pkt_info *info, 
+			   struct meta_value *v, struct meta_obj *dst)
+{
+	int err = 0;
+
+	if (meta_id(v) == TCF_META_ID_VALUE) {
+		dst->value = v->val;
+		dst->len = v->len;
+		return 0;
+	}
+
+	meta_ops(v)->get(skb, info, v, dst, &err);
+	if (err < 0)
+		return err;
+
+	if (meta_type_ops(v)->apply_extras)
+	    meta_type_ops(v)->apply_extras(v, dst);
+
+	return 0;
+}
+
+static int em_meta_match(struct sk_buff *skb, struct tcf_ematch *m,
+			 struct tcf_pkt_info *info)
+{
+	int r;
+	struct meta_match *meta = (struct meta_match *) m->data;
+	struct meta_obj l_value, r_value;
+
+	if (meta_get(skb, info, &meta->lvalue, &l_value) < 0 ||
+	    meta_get(skb, info, &meta->rvalue, &r_value) < 0)
+		return 0;
+
+	r = meta_type_ops(&meta->lvalue)->compare(&l_value, &r_value);
+
+	switch (meta->lvalue.hdr.op) {
+		case TCF_EM_OPND_EQ:
+			return !r;
+		case TCF_EM_OPND_LT:
+			return r < 0;
+		case TCF_EM_OPND_GT:
+			return r > 0;
+	}
+
+	return 0;
+}
+
+static inline void meta_delete(struct meta_match *meta)
+{
+	struct meta_type_ops *ops = meta_type_ops(&meta->lvalue);
+
+	if (ops && ops->destroy) {
+		ops->destroy(&meta->lvalue);
+		ops->destroy(&meta->rvalue);
+	}
+
+	kfree(meta);
+}
+
+static inline int meta_change_data(struct meta_value *dst, struct rtattr *rta)
+{
+	if (rta) {
+		if (RTA_PAYLOAD(rta) == 0)
+			return -EINVAL;
+
+		return meta_type_ops(dst)->change(dst, rta);
+	}
+
+	return 0;
+}
+
+static inline int meta_is_supported(struct meta_value *val)
+{
+	return (!meta_id(val) || meta_ops(val)->get);
+}
+
+static int em_meta_change(struct tcf_proto *tp, void *data, int len,
+			  struct tcf_ematch *m)
+{
+	int err = -EINVAL;
+	struct rtattr *tb[TCA_EM_META_MAX];
+	struct tcf_meta_hdr *hdr;
+	struct meta_match *meta = NULL;
+	
+	if (rtattr_parse(tb, TCA_EM_META_MAX, data, len) < 0)
+		goto errout;
+
+	if (tb[TCA_EM_META_HDR-1] == NULL ||
+	    RTA_PAYLOAD(tb[TCA_EM_META_HDR-1]) < sizeof(*hdr))
+		goto errout;
+	hdr = RTA_DATA(tb[TCA_EM_META_HDR-1]);
+
+	if (TCF_META_TYPE(hdr->left.kind) != TCF_META_TYPE(hdr->right.kind) ||
+	    TCF_META_TYPE(hdr->left.kind) > TCF_META_TYPE_MAX ||
+	    TCF_META_ID(hdr->left.kind) > TCF_META_ID_MAX ||
+	    TCF_META_ID(hdr->right.kind) > TCF_META_ID_MAX)
+		goto errout;
+
+	meta = kmalloc(sizeof(*meta), GFP_KERNEL);
+	if (meta == NULL)
+		goto errout;
+	memset(meta, 0, sizeof(*meta));
+
+	memcpy(&meta->lvalue.hdr, &hdr->left, sizeof(hdr->left));
+	memcpy(&meta->rvalue.hdr, &hdr->right, sizeof(hdr->right));
+
+	if (!meta_is_supported(&meta->lvalue) ||
+	    !meta_is_supported(&meta->rvalue)) {
+		err = -EOPNOTSUPP;
+		goto errout;
+	}
+
+	if (meta_change_data(&meta->lvalue, tb[TCA_EM_META_LVALUE-1]) < 0 ||
+	    meta_change_data(&meta->rvalue, tb[TCA_EM_META_RVALUE-1]) < 0)
+		goto errout;
+
+	m->datalen = sizeof(*meta);
+	m->data = (unsigned long) meta;
+
+	err = 0;
+errout:
+	if (err && meta)
+		meta_delete(meta);
+	return err;
+}
+
+static void em_meta_destroy(struct tcf_proto *tp, struct tcf_ematch *m)
+{
+	if (m)
+		meta_delete((struct meta_match *) m->data);
+}
+
+static int em_meta_dump(struct sk_buff *skb, struct tcf_ematch *em)
+{
+	struct meta_match *meta = (struct meta_match *) em->data;
+	struct tcf_meta_hdr hdr;
+	struct meta_type_ops *ops;
+
+	memset(&hdr, 0, sizeof(hdr));
+	memcpy(&hdr.left, &meta->lvalue.hdr, sizeof(hdr.left));
+	memcpy(&hdr.right, &meta->rvalue.hdr, sizeof(hdr.right));
+
+	RTA_PUT(skb, TCA_EM_META_HDR, sizeof(hdr), &hdr);
+
+	ops = meta_type_ops(&meta->lvalue);
+	if (ops->dump(skb, &meta->lvalue, TCA_EM_META_LVALUE) < 0 ||
+	    ops->dump(skb, &meta->rvalue, TCA_EM_META_RVALUE) < 0)
+		goto rtattr_failure;
+
+	return 0;
+
+rtattr_failure:
+	return -1;
+}		
+
+static struct tcf_ematch_ops em_meta_ops = {
+	.kind	  = TCF_EM_META,
+	.change	  = em_meta_change,
+	.match	  = em_meta_match,
+	.destroy  = em_meta_destroy,
+	.dump	  = em_meta_dump,
+	.owner	  = THIS_MODULE,
+	.link	  = LIST_HEAD_INIT(em_meta_ops.link)
+};
+
+static int __init init_em_meta(void)
+{
+	return tcf_em_register(&em_meta_ops);
+}
+
+static void __exit exit_em_meta(void) 
+{
+	tcf_em_unregister(&em_meta_ops);
+}
+
+MODULE_LICENSE("GPL");
+
+module_init(init_em_meta);
+module_exit(exit_em_meta);
diff -Nru a/net/sched/em_nbyte.c b/net/sched/em_nbyte.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/net/sched/em_nbyte.c	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,82 @@
+/*
+ * net/sched/em_nbyte.c	N-Byte ematch
+ *
+ *		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.
+ *
+ * Authors:	Thomas Graf <tgraf@suug.ch>
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/skbuff.h>
+#include <linux/tc_ematch/tc_em_nbyte.h>
+#include <net/pkt_cls.h>
+
+struct nbyte_data
+{
+	struct tcf_em_nbyte	hdr;
+	char			pattern[0];
+};
+	
+static int em_nbyte_change(struct tcf_proto *tp, void *data, int data_len,
+			   struct tcf_ematch *em)
+{
+	struct tcf_em_nbyte *nbyte = data;
+
+	if (data_len < sizeof(*nbyte) ||
+	    data_len < (sizeof(*nbyte) + nbyte->len))
+		return -EINVAL;
+
+	em->datalen = sizeof(*nbyte) + nbyte->len;
+	em->data = (unsigned long) kmalloc(em->datalen, GFP_KERNEL);
+	if (em->data == 0UL)
+		return -ENOBUFS;
+
+	memcpy((void *) em->data, data, em->datalen);
+
+	return 0;
+}
+
+static int em_nbyte_match(struct sk_buff *skb, struct tcf_ematch *em,
+			  struct tcf_pkt_info *info)
+{
+	struct nbyte_data *nbyte = (struct nbyte_data *) em->data;
+	unsigned char *ptr = tcf_get_base_ptr(skb, nbyte->hdr.layer);
+
+	ptr += nbyte->hdr.off;
+
+	if (!tcf_valid_offset(skb, ptr, nbyte->hdr.len))
+		return 0;
+
+	return !memcmp(ptr + nbyte->hdr.off, nbyte->pattern, nbyte->hdr.len);
+}
+
+static struct tcf_ematch_ops em_nbyte_ops = {
+	.kind	  = TCF_EM_NBYTE,
+	.change	  = em_nbyte_change,
+	.match	  = em_nbyte_match,
+	.owner	  = THIS_MODULE,
+	.link	  = LIST_HEAD_INIT(em_nbyte_ops.link)
+};
+
+static int __init init_em_nbyte(void)
+{
+	return tcf_em_register(&em_nbyte_ops);
+}
+
+static void __exit exit_em_nbyte(void) 
+{
+	tcf_em_unregister(&em_nbyte_ops);
+}
+
+MODULE_LICENSE("GPL");
+
+module_init(init_em_nbyte);
+module_exit(exit_em_nbyte);
diff -Nru a/net/sched/em_u32.c b/net/sched/em_u32.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/net/sched/em_u32.c	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,63 @@
+/*
+ * net/sched/em_u32.c	U32 Ematch
+ *
+ *		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.
+ *
+ * Authors:	Thomas Graf <tgraf@suug.ch>
+ *		Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
+ *
+ * Based on net/sched/cls_u32.c
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/skbuff.h>
+#include <net/pkt_cls.h>
+
+static int em_u32_match(struct sk_buff *skb, struct tcf_ematch *em,
+			struct tcf_pkt_info *info)
+{
+	struct tc_u32_key *key = (struct tc_u32_key *) em->data;
+	unsigned char *ptr = skb->nh.raw;
+	
+	if (info) {
+		if (info->ptr)
+			ptr = info->ptr;
+		ptr += (info->nexthdr & key->offmask);
+	}
+
+	ptr += key->off;
+
+	if (!tcf_valid_offset(skb, ptr, sizeof(u32)))
+		return 0;
+	
+	return !(((*(u32*) ptr)  ^ key->val) & key->mask);
+}
+
+static struct tcf_ematch_ops em_u32_ops = {
+	.kind	  = TCF_EM_U32,
+	.datalen  = sizeof(struct tc_u32_key),
+	.match	  = em_u32_match,
+	.owner	  = THIS_MODULE,
+	.link	  = LIST_HEAD_INIT(em_u32_ops.link)
+};
+
+static int __init init_em_u32(void)
+{
+	return tcf_em_register(&em_u32_ops);
+}
+
+static void __exit exit_em_u32(void) 
+{
+	tcf_em_unregister(&em_u32_ops);
+}
+
+MODULE_LICENSE("GPL");
+
+module_init(init_em_u32);
+module_exit(exit_em_u32);
diff -Nru a/net/sched/ematch.c b/net/sched/ematch.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/net/sched/ematch.c	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,524 @@
+/*
+ * net/sched/ematch.c		Extended Match API
+ *
+ *		This program is free software; you can redistribute it and/or
+ *		modify it under the terms of the GNU General Public License
+ *		as published by the Free Software Foundation; either version
+ *		2 of the License, or (at your option) any later version.
+ *
+ * Authors:	Thomas Graf <tgraf@suug.ch>
+ *
+ * ==========================================================================
+ *
+ * An extended match (ematch) is a small classification tool not worth
+ * writing a full classifier for. Ematches can be interconnected to form
+ * a logic expression and get attached to classifiers to extend their
+ * functionatlity.
+ *
+ * The userspace part transforms the logic expressions into an array
+ * consisting of multiple sequences of interconnected ematches separated
+ * by markers. Precedence is implemented by a special ematch kind
+ * referencing a sequence beyond the marker of the current sequence
+ * causing the current position in the sequence to be pushed onto a stack
+ * to allow the current position to be overwritten by the position referenced
+ * in the special ematch. Matching continues in the new sequence until a
+ * marker is reached causing the position to be restored from the stack.
+ *
+ * Example:
+ *          A AND (B1 OR B2) AND C AND D
+ *
+ *              ------->-PUSH-------
+ *    -->--    /         -->--      \   -->--
+ *   /     \  /         /     \      \ /     \
+ * +-------+-------+-------+-------+-------+--------+
+ * | A AND | B AND | C AND | D END | B1 OR | B2 END |
+ * +-------+-------+-------+-------+-------+--------+
+ *                    \                      /
+ *                     --------<-POP---------
+ *
+ * where B is a virtual ematch referencing to sequence starting with B1.
+ * 
+ * ==========================================================================
+ *
+ * How to write an ematch in 60 seconds
+ * ------------------------------------
+ * 
+ *   1) Provide a matcher function:
+ *      static int my_match(struct sk_buff *skb, struct tcf_ematch *m,
+ *                          struct tcf_pkt_info *info)
+ *      {
+ *      	struct mydata *d = (struct mydata *) m->data;
+ *
+ *      	if (...matching goes here...)
+ *      		return 1;
+ *      	else
+ *      		return 0;
+ *      }
+ *
+ *   2) Fill out a struct tcf_ematch_ops:
+ *      static struct tcf_ematch_ops my_ops = {
+ *      	.kind = unique id,
+ *      	.datalen = sizeof(struct mydata),
+ *      	.match = my_match,
+ *      	.owner = THIS_MODULE,
+ *      };
+ *
+ *   3) Register/Unregister your ematch:
+ *      static int __init init_my_ematch(void)
+ *      {
+ *      	return tcf_em_register(&my_ops);
+ *      }
+ *
+ *      static void __exit exit_my_ematch(void)
+ *      {
+ *      	return tcf_em_unregister(&my_ops);
+ *      }
+ *
+ *      module_init(init_my_ematch);
+ *      module_exit(exit_my_ematch);
+ *
+ *   4) By now you should have two more seconds left, barely enough to
+ *      open up a beer to watch the compilation going.
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/rtnetlink.h>
+#include <linux/skbuff.h>
+#include <net/pkt_cls.h>
+#include <config/net/ematch/stack.h>
+
+static LIST_HEAD(ematch_ops);
+static DEFINE_RWLOCK(ematch_mod_lock);
+
+static inline struct tcf_ematch_ops * tcf_em_lookup(u16 kind)
+{
+	struct tcf_ematch_ops *e = NULL;
+
+	read_lock(&ematch_mod_lock);
+	list_for_each_entry(e, &ematch_ops, link) {
+		if (kind == e->kind) {
+			if (!try_module_get(e->owner))
+				e = NULL;
+			read_unlock(&ematch_mod_lock);
+			return e;
+		}
+	}
+	read_unlock(&ematch_mod_lock);
+
+	return NULL;
+}
+
+/**
+ * tcf_em_register - register an extended match
+ * 
+ * @ops: ematch operations lookup table
+ *
+ * This function must be called by ematches to announce their presence.
+ * The given @ops must have kind set to a unique identifier and the
+ * callback match() must be implemented. All other callbacks are optional
+ * and a fallback implementation is used instead.
+ *
+ * Returns -EEXISTS if an ematch of the same kind has already registered.
+ */
+int tcf_em_register(struct tcf_ematch_ops *ops)
+{
+	int err = -EEXIST;
+	struct tcf_ematch_ops *e;
+
+	if (ops->match == NULL)
+		return -EINVAL;
+
+	write_lock(&ematch_mod_lock);
+	list_for_each_entry(e, &ematch_ops, link)
+		if (ops->kind == e->kind)
+			goto errout;
+
+	list_add_tail(&ops->link, &ematch_ops);
+	err = 0;
+errout:
+	write_unlock(&ematch_mod_lock);
+	return err;
+}
+
+/**
+ * tcf_em_unregister - unregster and extended match
+ *
+ * @ops: ematch operations lookup table
+ *
+ * This function must be called by ematches to announce their disappearance
+ * for examples when the module gets unloaded. The @ops parameter must be
+ * the same as the one used for registration.
+ *
+ * Returns -ENOENT if no matching ematch was found.
+ */
+int tcf_em_unregister(struct tcf_ematch_ops *ops)
+{
+	int err = 0;
+	struct tcf_ematch_ops *e;
+
+	write_lock(&ematch_mod_lock);
+	list_for_each_entry(e, &ematch_ops, link) {
+		if (e == ops) {
+			list_del(&e->link);
+			goto out;
+		}
+	}
+
+	err = -ENOENT;
+out:
+	write_unlock(&ematch_mod_lock);
+	return err;
+}
+
+static inline struct tcf_ematch * tcf_em_get_match(struct tcf_ematch_tree *tree,
+						   int index)
+{
+	return &tree->matches[index];
+}
+
+
+static int tcf_em_validate(struct tcf_proto *tp,
+			   struct tcf_ematch_tree_hdr *tree_hdr,
+			   struct tcf_ematch *em, struct rtattr *rta, int idx)
+{
+	int err = -EINVAL;
+	struct tcf_ematch_hdr *em_hdr = RTA_DATA(rta);
+	int data_len = RTA_PAYLOAD(rta) - sizeof(*em_hdr);
+	void *data = (void *) em_hdr + sizeof(*em_hdr);
+
+	if (!TCF_EM_REL_VALID(em_hdr->flags))
+		goto errout;
+
+	if (em_hdr->kind == TCF_EM_CONTAINER) {
+		/* Special ematch called "container", carries an index
+		 * referencing an external ematch sequence. */
+		u32 ref;
+
+		if (data_len < sizeof(ref))
+			goto errout;
+		ref = *(u32 *) data;
+
+		if (ref >= tree_hdr->nmatches)
+			goto errout;
+
+		/* We do not allow backward jumps to avoid loops and jumps
+		 * to our own position are of course illegal. */
+		if (ref <= idx)
+			goto errout;
+
+		
+		em->data = ref;
+	} else {
+		/* Note: This lookup will increase the module refcnt
+		 * of the ematch module referenced. In case of a failure,
+		 * a destroy function is called by the underlying layer
+		 * which automatically releases the reference again, therefore
+		 * the module MUST not be given back under any circumstances
+		 * here. Be aware, the destroy function assumes that the
+		 * module is held if the ops field is non zero. */
+		em->ops = tcf_em_lookup(em_hdr->kind);
+
+		if (em->ops == NULL) {
+			err = -ENOENT;
+			goto errout;
+		}
+
+		/* ematch module provides expected length of data, so we
+		 * can do a basic sanity check. */
+		if (em->ops->datalen && data_len < em->ops->datalen)
+			goto errout;
+
+		if (em->ops->change) {
+			err = em->ops->change(tp, data, data_len, em);
+			if (err < 0)
+				goto errout;
+		} else if (data_len > 0) {
+			/* ematch module doesn't provide an own change
+			 * procedure and expects us to allocate and copy
+			 * the ematch data.
+			 *
+			 * TCF_EM_SIMPLE may be specified stating that the
+			 * data only consists of a u32 integer and the module
+			 * does not expected a memory reference but rather
+			 * the value carried. */
+			if (em_hdr->flags & TCF_EM_SIMPLE) {
+				if (data_len < sizeof(u32))
+					goto errout;
+				em->data = *(u32 *) data;
+			} else {
+				void *v = kmalloc(data_len, GFP_KERNEL);
+				if (v == NULL) {
+					err = -ENOBUFS;
+					goto errout;
+				}
+				memcpy(v, data, data_len);
+				em->data = (unsigned long) v;
+			}
+		}
+	}
+
+	em->matchid = em_hdr->matchid;
+	em->flags = em_hdr->flags;
+	em->datalen = data_len;
+
+	err = 0;
+errout:
+	return err;
+}
+
+/**
+ * tcf_em_tree_validate - validate ematch config TLV and build ematch tree
+ *
+ * @tp: classifier kind handle
+ * @rta: ematch tree configuration TLV
+ * @tree: destination ematch tree variable to store the resulting
+ *        ematch tree.
+ *
+ * This function validates the given configuration TLV @rta and builds an
+ * ematch tree in @tree. The resulting tree must later be copied into
+ * the private classifier data using tcf_em_tree_change(). You MUST NOT
+ * provide the ematch tree variable of the private classifier data directly,
+ * the changes would not be locked properly.
+ *
+ * Returns a negative error code if the configuration TLV contains errors.
+ */
+int tcf_em_tree_validate(struct tcf_proto *tp, struct rtattr *rta,
+			 struct tcf_ematch_tree *tree)
+{
+	int idx, list_len, matches_len, err = -EINVAL;
+	struct rtattr *tb[TCA_EMATCH_TREE_MAX];
+	struct rtattr *rt_match, *rt_hdr, *rt_list;
+	struct tcf_ematch_tree_hdr *tree_hdr;
+	struct tcf_ematch *em;
+
+	if (rtattr_parse_nested(tb, TCA_EMATCH_TREE_MAX, rta) < 0)
+		goto errout;
+
+	rt_hdr = tb[TCA_EMATCH_TREE_HDR-1];
+	rt_list = tb[TCA_EMATCH_TREE_LIST-1];
+
+	if (rt_hdr == NULL || rt_list == NULL)
+		goto errout;
+
+	if (RTA_PAYLOAD(rt_hdr) < sizeof(*tree_hdr) ||
+	    RTA_PAYLOAD(rt_list) < sizeof(*rt_match))
+		goto errout;
+
+	tree_hdr = RTA_DATA(rt_hdr);
+	memcpy(&tree->hdr, tree_hdr, sizeof(*tree_hdr));
+
+	rt_match = RTA_DATA(rt_list);
+	list_len = RTA_PAYLOAD(rt_list);
+	matches_len = tree_hdr->nmatches * sizeof(*em);
+
+	tree->matches = kmalloc(matches_len, GFP_KERNEL);
+	if (tree->matches == NULL)
+		goto errout;
+	memset(tree->matches, 0, matches_len);
+
+	/* We do not use rtattr_parse_nested here because the maximum
+	 * number of attributes is unknown. This saves us the allocation
+	 * for a tb buffer which would serve no purpose at all.
+	 * 
+	 * The array of rt attributes is parsed in the order as they are
+	 * provided, their type must be incremental from 1 to n. Even
+	 * if it does not serve any real purpose, a failure of sticking
+	 * to this policy will result in parsing failure. */
+	for (idx = 0; RTA_OK(rt_match, list_len); idx++) {
+		err = -EINVAL;
+
+		if (rt_match->rta_type != (idx + 1))
+			goto errout_abort;
+
+		if (idx >= tree_hdr->nmatches)
+			goto errout_abort;
+
+		if (RTA_PAYLOAD(rt_match) < sizeof(struct tcf_ematch_hdr))
+			goto errout_abort;
+
+		em = tcf_em_get_match(tree, idx);
+
+		err = tcf_em_validate(tp, tree_hdr, em, rt_match, idx);
+		if (err < 0)
+			goto errout_abort;
+
+		rt_match = RTA_NEXT(rt_match, list_len);
+	}
+
+	/* Check if the number of matches provided by userspace actually
+	 * complies with the array of matches. The number was used for
+	 * the validation of references and a mismatch could lead to
+	 * undefined references during the matching process. */
+	if (idx != tree_hdr->nmatches) {
+		err = -EINVAL;
+		goto errout_abort;
+	}
+
+	err = 0;
+errout:
+	return err;
+
+errout_abort:
+	tcf_em_tree_destroy(tp, tree);
+	return err;
+}
+
+/**
+ * tcf_em_tree_destroy - destroy an ematch tree
+ *
+ * @tp: classifier kind handle
+ * @tree: ematch tree to be deleted
+ *
+ * This functions destroys an ematch tree previously created by
+ * tcf_em_tree_validate()/tcf_em_tree_change(). You must ensure that
+ * the ematch tree is not in use before calling this function.
+ */
+void tcf_em_tree_destroy(struct tcf_proto *tp, struct tcf_ematch_tree *tree)
+{
+	int i;
+
+	if (tree->matches == NULL)
+		return;
+
+	for (i = 0; i < tree->hdr.nmatches; i++) {
+		struct tcf_ematch *em = tcf_em_get_match(tree, i);
+
+		if (em->ops) {
+			if (em->ops->destroy)
+				em->ops->destroy(tp, em);
+			else if (!tcf_em_is_simple(em) && em->data)
+				kfree((void *) em->data);
+			module_put(em->ops->owner);
+		}
+	}
+	
+	tree->hdr.nmatches = 0;
+	kfree(tree->matches);
+}
+
+/**
+ * tcf_em_tree_dump - dump ematch tree into a rtnl message
+ *
+ * @skb: skb holding the rtnl message
+ * @t: ematch tree to be dumped
+ * @tlv: TLV type to be used to encapsulate the tree
+ *
+ * This function dumps a ematch tree into a rtnl message. It is valid to
+ * call this function while the ematch tree is in use.
+ *
+ * Returns -1 if the skb tailroom is insufficient.
+ */
+int tcf_em_tree_dump(struct sk_buff *skb, struct tcf_ematch_tree *tree, int tlv)
+{
+	int i;
+	struct rtattr * top_start = (struct rtattr*) skb->tail;
+	struct rtattr * list_start;
+
+	RTA_PUT(skb, tlv, 0, NULL);
+	RTA_PUT(skb, TCA_EMATCH_TREE_HDR, sizeof(tree->hdr), &tree->hdr);
+
+	list_start = (struct rtattr *) skb->tail;
+	RTA_PUT(skb, TCA_EMATCH_TREE_LIST, 0, NULL);
+
+	for (i = 0; i < tree->hdr.nmatches; i++) {
+		struct rtattr *match_start = (struct rtattr*) skb->tail;
+		struct tcf_ematch *em = tcf_em_get_match(tree, i);
+		struct tcf_ematch_hdr em_hdr = {
+			.kind = em->ops ? em->ops->kind : TCF_EM_CONTAINER,
+			.matchid = em->matchid,
+			.flags = em->flags
+		};
+
+		RTA_PUT(skb, i+1, sizeof(em_hdr), &em_hdr);
+
+		if (em->ops && em->ops->dump) {
+			if (em->ops->dump(skb, em) < 0)
+				goto rtattr_failure;
+		} else if (tcf_em_is_container(em) || tcf_em_is_simple(em)) {
+			u32 u = em->data;
+			RTA_PUT_NOHDR(skb, sizeof(u), &u);
+		} else if (em->datalen > 0)
+			RTA_PUT_NOHDR(skb, em->datalen, (void *) em->data);
+
+		match_start->rta_len = skb->tail - (u8*) match_start;
+	}
+
+	list_start->rta_len = skb->tail - (u8 *) list_start;
+	top_start->rta_len = skb->tail - (u8 *) top_start;
+
+	return 0;
+
+rtattr_failure:
+	return -1;
+}
+
+static inline int tcf_em_match(struct sk_buff *skb, struct tcf_ematch *em,
+			       struct tcf_pkt_info *info)
+{
+	int r = em->ops->match(skb, em, info);
+	return tcf_em_is_inverted(em) ? !r : r;
+}
+
+/* Do not use this function directly, use tcf_em_tree_match instead */
+int __tcf_em_tree_match(struct sk_buff *skb, struct tcf_ematch_tree *tree,
+			struct tcf_pkt_info *info)
+{
+	int stackp = 0, match_idx = 0, res = 0;
+	struct tcf_ematch *cur_match;
+	int stack[CONFIG_NET_EMATCH_STACK];
+
+proceed:
+	while (match_idx < tree->hdr.nmatches) {
+		cur_match = tcf_em_get_match(tree, match_idx);
+
+		if (tcf_em_is_container(cur_match)) {
+			if (unlikely(stackp >= CONFIG_NET_EMATCH_STACK))
+				goto stack_overflow;
+
+			stack[stackp++] = match_idx;
+			match_idx = cur_match->data;
+			goto proceed;
+		}
+
+		res = tcf_em_match(skb, cur_match, info);
+
+		if (tcf_em_early_end(cur_match, res))
+			break;
+
+		match_idx++;
+	}
+
+pop_stack:
+	if (stackp > 0) {
+		match_idx = stack[--stackp];
+		cur_match = tcf_em_get_match(tree, match_idx);
+
+		if (tcf_em_early_end(cur_match, res))
+			goto pop_stack;
+		else {
+			match_idx++;
+			goto proceed;
+		}
+	}
+
+	return res;
+
+stack_overflow:
+	if (net_ratelimit())
+		printk("Local stack overflow, increase NET_EMATCH_STACK\n");
+	return -1;
+}
+
+EXPORT_SYMBOL(tcf_em_register);
+EXPORT_SYMBOL(tcf_em_unregister);
+EXPORT_SYMBOL(tcf_em_tree_validate);
+EXPORT_SYMBOL(tcf_em_tree_destroy);
+EXPORT_SYMBOL(tcf_em_tree_dump);
+EXPORT_SYMBOL(__tcf_em_tree_match);
diff -Nru a/net/sched/sch_atm.c b/net/sched/sch_atm.c
--- a/net/sched/sch_atm.c	2005-03-11 12:51:43 -08:00
+++ b/net/sched/sch_atm.c	2005-03-11 12:51:43 -08:00
@@ -519,7 +519,7 @@
 			memcpy(skb_push(skb,flow->hdr_len),flow->hdr,
 			    flow->hdr_len);
 			atomic_add(skb->truesize,
-				   &flow->vcc->sk->sk_wmem_alloc);
+				   &sk_atm(flow->vcc)->sk_wmem_alloc);
 			/* atm.atm_options are already set by atm_tc_enqueue */
 			(void) flow->vcc->send(flow->vcc,skb);
 		}
diff -Nru a/net/sctp/input.c b/net/sctp/input.c
--- a/net/sctp/input.c	2005-03-11 12:51:52 -08:00
+++ b/net/sctp/input.c	2005-03-11 12:51:52 -08:00
@@ -100,6 +100,21 @@
 	return 0;
 }
 
+/* The free routine for skbuffs that sctp receives */
+static void sctp_rfree(struct sk_buff *skb)
+{
+	atomic_sub(sizeof(struct sctp_chunk),&skb->sk->sk_rmem_alloc);
+	sock_rfree(skb);
+}
+
+/* The ownership wrapper routine to do receive buffer accounting */
+static void sctp_rcv_set_owner_r(struct sk_buff *skb, struct sock *sk)
+{
+	skb_set_owner_r(skb,sk);
+	skb->destructor = sctp_rfree;
+	atomic_add(sizeof(struct sctp_chunk),&sk->sk_rmem_alloc);
+}
+
 /*
  * This is the routine which IP calls when receiving an SCTP packet.
  */
@@ -183,6 +198,11 @@
 	rcvr = asoc ? &asoc->base : &ep->base;
 	sk = rcvr->sk;
 
+	if ((sk) && (atomic_read(&sk->sk_rmem_alloc) >= sk->sk_rcvbuf)) {
+		goto discard_release;
+	}
+
+
 	/* SCTP seems to always need a timestamp right now (FIXME) */
 	if (skb->stamp.tv_sec == 0) {
 		do_gettimeofday(&skb->stamp);
@@ -202,6 +222,8 @@
 		ret = -ENOMEM;
 		goto discard_release;
 	}
+
+	sctp_rcv_set_owner_r(skb,sk);
 
 	/* Remember what endpoint is to handle this packet. */
 	chunk->rcvr = rcvr;
diff -Nru a/net/socket.c b/net/socket.c
--- a/net/socket.c	2005-03-11 12:51:42 -08:00
+++ b/net/socket.c	2005-03-11 12:51:42 -08:00
@@ -287,7 +287,7 @@
 	ei->socket.ops = NULL;
 	ei->socket.sk = NULL;
 	ei->socket.file = NULL;
-	ei->socket.passcred = 0;
+	ei->socket.flags = 0;
 
 	return &ei->vfs_inode;
 }
diff -Nru a/net/sunrpc/auth.c b/net/sunrpc/auth.c
--- a/net/sunrpc/auth.c	2005-03-11 12:51:46 -08:00
+++ b/net/sunrpc/auth.c	2005-03-11 12:51:46 -08:00
@@ -67,12 +67,9 @@
 
 	if (flavor >= RPC_AUTH_MAXFLAVOR || !(ops = auth_flavors[flavor]))
 		return NULL;
-	if (!try_module_get(ops->owner))
-		return NULL;
 	auth = ops->create(clnt, pseudoflavor);
 	if (!auth)
 		return NULL;
-	atomic_set(&auth->au_count, 1);
 	if (clnt->cl_auth)
 		rpcauth_destroy(clnt->cl_auth);
 	clnt->cl_auth = auth;
@@ -85,8 +82,6 @@
 	if (!atomic_dec_and_test(&auth->au_count))
 		return;
 	auth->au_ops->destroy(auth);
-	module_put(auth->au_ops->owner);
-	kfree(auth);
 }
 
 static DEFINE_SPINLOCK(rpc_credcache_lock);
@@ -94,42 +89,35 @@
 /*
  * Initialize RPC credential cache
  */
-void
-rpcauth_init_credcache(struct rpc_auth *auth)
+int
+rpcauth_init_credcache(struct rpc_auth *auth, unsigned long expire)
 {
+	struct rpc_cred_cache *new;
 	int i;
-	for (i = 0; i < RPC_CREDCACHE_NR; i++)
-		INIT_LIST_HEAD(&auth->au_credcache[i]);
-	auth->au_nextgc = jiffies + (auth->au_expire >> 1);
-}
 
-/*
- * Destroy an unreferenced credential
- */
-static inline void
-rpcauth_crdestroy(struct rpc_cred *cred)
-{
-#ifdef RPC_DEBUG
-	BUG_ON(cred->cr_magic != RPCAUTH_CRED_MAGIC ||
-			atomic_read(&cred->cr_count) ||
-			!list_empty(&cred->cr_hash));
-	cred->cr_magic = 0;
-#endif
-	cred->cr_ops->crdestroy(cred);
+	new = (struct rpc_cred_cache *)kmalloc(sizeof(*new), GFP_KERNEL);
+	if (!new)
+		return -ENOMEM;
+	for (i = 0; i < RPC_CREDCACHE_NR; i++)
+		INIT_HLIST_HEAD(&new->hashtable[i]);
+	new->expire = expire;
+	new->nextgc = jiffies + (expire >> 1);
+	auth->au_credcache = new;
+	return 0;
 }
 
 /*
  * Destroy a list of credentials
  */
 static inline
-void rpcauth_destroy_credlist(struct list_head *head)
+void rpcauth_destroy_credlist(struct hlist_head *head)
 {
 	struct rpc_cred *cred;
 
-	while (!list_empty(head)) {
-		cred = list_entry(head->next, struct rpc_cred, cr_hash);
-		list_del_init(&cred->cr_hash);
-		rpcauth_crdestroy(cred);
+	while (!hlist_empty(head)) {
+		cred = hlist_entry(head->first, struct rpc_cred, cr_hash);
+		hlist_del_init(&cred->cr_hash);
+		put_rpccred(cred);
 	}
 }
 
@@ -140,56 +128,56 @@
 void
 rpcauth_free_credcache(struct rpc_auth *auth)
 {
-	LIST_HEAD(free);
-	struct list_head *pos, *next;
+	struct rpc_cred_cache *cache = auth->au_credcache;
+	HLIST_HEAD(free);
+	struct hlist_node *pos, *next;
 	struct rpc_cred	*cred;
 	int		i;
 
 	spin_lock(&rpc_credcache_lock);
 	for (i = 0; i < RPC_CREDCACHE_NR; i++) {
-		list_for_each_safe(pos, next, &auth->au_credcache[i]) {
-			cred = list_entry(pos, struct rpc_cred, cr_hash);
-			cred->cr_auth = NULL;
-			list_del_init(&cred->cr_hash);
-			if (atomic_read(&cred->cr_count) == 0)
-				list_add(&cred->cr_hash, &free);
+		hlist_for_each_safe(pos, next, &cache->hashtable[i]) {
+			cred = hlist_entry(pos, struct rpc_cred, cr_hash);
+			__hlist_del(&cred->cr_hash);
+			hlist_add_head(&cred->cr_hash, &free);
 		}
 	}
 	spin_unlock(&rpc_credcache_lock);
 	rpcauth_destroy_credlist(&free);
 }
 
-static inline int
-rpcauth_prune_expired(struct rpc_cred *cred, struct list_head *free)
+static void
+rpcauth_prune_expired(struct rpc_auth *auth, struct rpc_cred *cred, struct hlist_head *free)
 {
-	if (atomic_read(&cred->cr_count) != 0)
-	       return 0;
-	if (time_before(jiffies, cred->cr_expire))
-		return 0;
-	cred->cr_auth = NULL;
-	list_del(&cred->cr_hash);
-	list_add(&cred->cr_hash, free);
-	return 1;
+	if (atomic_read(&cred->cr_count) != 1)
+	       return;
+	if (time_after(jiffies, cred->cr_expire + auth->au_credcache->expire))
+		cred->cr_flags &= ~RPCAUTH_CRED_UPTODATE;
+	if (!(cred->cr_flags & RPCAUTH_CRED_UPTODATE)) {
+		__hlist_del(&cred->cr_hash);
+		hlist_add_head(&cred->cr_hash, free);
+	}
 }
 
 /*
  * Remove stale credentials. Avoid sleeping inside the loop.
  */
 static void
-rpcauth_gc_credcache(struct rpc_auth *auth, struct list_head *free)
+rpcauth_gc_credcache(struct rpc_auth *auth, struct hlist_head *free)
 {
-	struct list_head *pos, *next;
+	struct rpc_cred_cache *cache = auth->au_credcache;
+	struct hlist_node *pos, *next;
 	struct rpc_cred	*cred;
 	int		i;
 
 	dprintk("RPC: gc'ing RPC credentials for auth %p\n", auth);
 	for (i = 0; i < RPC_CREDCACHE_NR; i++) {
-		list_for_each_safe(pos, next, &auth->au_credcache[i]) {
-			cred = list_entry(pos, struct rpc_cred, cr_hash);
-			rpcauth_prune_expired(cred, free);
+		hlist_for_each_safe(pos, next, &cache->hashtable[i]) {
+			cred = hlist_entry(pos, struct rpc_cred, cr_hash);
+			rpcauth_prune_expired(auth, cred, free);
 		}
 	}
-	auth->au_nextgc = jiffies + auth->au_expire;
+	cache->nextgc = jiffies + cache->expire;
 }
 
 /*
@@ -199,8 +187,9 @@
 rpcauth_lookup_credcache(struct rpc_auth *auth, struct auth_cred * acred,
 		int taskflags)
 {
-	LIST_HEAD(free);
-	struct list_head *pos, *next;
+	struct rpc_cred_cache *cache = auth->au_credcache;
+	HLIST_HEAD(free);
+	struct hlist_node *pos, *next;
 	struct rpc_cred	*new = NULL,
 			*cred = NULL;
 	int		nr = 0;
@@ -209,28 +198,26 @@
 		nr = acred->uid & RPC_CREDCACHE_MASK;
 retry:
 	spin_lock(&rpc_credcache_lock);
-	if (time_before(auth->au_nextgc, jiffies))
+	if (time_before(cache->nextgc, jiffies))
 		rpcauth_gc_credcache(auth, &free);
-	list_for_each_safe(pos, next, &auth->au_credcache[nr]) {
+	hlist_for_each_safe(pos, next, &cache->hashtable[nr]) {
 		struct rpc_cred *entry;
-	       	entry = list_entry(pos, struct rpc_cred, cr_hash);
-		if (rpcauth_prune_expired(entry, &free))
-			continue;
+	       	entry = hlist_entry(pos, struct rpc_cred, cr_hash);
 		if (entry->cr_ops->crmatch(acred, entry, taskflags)) {
-			list_del(&entry->cr_hash);
+			hlist_del(&entry->cr_hash);
 			cred = entry;
 			break;
 		}
+		rpcauth_prune_expired(auth, entry, &free);
 	}
 	if (new) {
 		if (cred)
-			list_add(&new->cr_hash, &free);
+			hlist_add_head(&new->cr_hash, &free);
 		else
 			cred = new;
 	}
 	if (cred) {
-		list_add(&cred->cr_hash, &auth->au_credcache[nr]);
-		cred->cr_auth = auth;
+		hlist_add_head(&cred->cr_hash, &cache->hashtable[nr]);
 		get_rpccred(cred);
 	}
 	spin_unlock(&rpc_credcache_lock);
@@ -239,12 +226,13 @@
 
 	if (!cred) {
 		new = auth->au_ops->crcreate(auth, acred, taskflags);
-		if (new) {
+		if (!IS_ERR(new)) {
 #ifdef RPC_DEBUG
 			new->cr_magic = RPCAUTH_CRED_MAGIC;
 #endif
 			goto retry;
-		}
+		} else
+			cred = new;
 	}
 
 	return (struct rpc_cred *) cred;
@@ -253,18 +241,18 @@
 struct rpc_cred *
 rpcauth_lookupcred(struct rpc_auth *auth, int taskflags)
 {
-	struct auth_cred acred;
+	struct auth_cred acred = {
+		.uid = current->fsuid,
+		.gid = current->fsgid,
+		.group_info = current->group_info,
+	};
 	struct rpc_cred *ret;
 
-	get_group_info(current->group_info);
-	acred.uid = current->fsuid;
-	acred.gid = current->fsgid;
-	acred.group_info = current->group_info;
-
 	dprintk("RPC:     looking up %s cred\n",
 		auth->au_ops->au_name);
-	ret = rpcauth_lookup_credcache(auth, &acred, taskflags);
-	put_group_info(current->group_info);
+	get_group_info(acred.group_info);
+	ret = auth->au_ops->lookup_cred(auth, &acred, taskflags);
+	put_group_info(acred.group_info);
 	return ret;
 }
 
@@ -272,21 +260,22 @@
 rpcauth_bindcred(struct rpc_task *task)
 {
 	struct rpc_auth *auth = task->tk_auth;
-	struct auth_cred acred;
+	struct auth_cred acred = {
+		.uid = current->fsuid,
+		.gid = current->fsgid,
+		.group_info = current->group_info,
+	};
 	struct rpc_cred *ret;
 
-	get_group_info(current->group_info);
-	acred.uid = current->fsuid;
-	acred.gid = current->fsgid;
-	acred.group_info = current->group_info;
-
 	dprintk("RPC: %4d looking up %s cred\n",
 		task->tk_pid, task->tk_auth->au_ops->au_name);
-	task->tk_msg.rpc_cred = rpcauth_lookup_credcache(auth, &acred, task->tk_flags);
-	if (task->tk_msg.rpc_cred == 0)
-		task->tk_status = -ENOMEM;
-	ret = task->tk_msg.rpc_cred;
-	put_group_info(current->group_info);
+	get_group_info(acred.group_info);
+	ret = auth->au_ops->lookup_cred(auth, &acred, task->tk_flags);
+	if (!IS_ERR(ret))
+		task->tk_msg.rpc_cred = ret;
+	else
+		task->tk_status = PTR_ERR(ret);
+	put_group_info(acred.group_info);
 	return ret;
 }
 
@@ -302,16 +291,10 @@
 void
 put_rpccred(struct rpc_cred *cred)
 {
-	if (!atomic_dec_and_lock(&cred->cr_count, &rpc_credcache_lock))
+	cred->cr_expire = jiffies;
+	if (!atomic_dec_and_test(&cred->cr_count))
 		return;
-
-	if (list_empty(&cred->cr_hash)) {
-		spin_unlock(&rpc_credcache_lock);
-		rpcauth_crdestroy(cred);
-		return;
-	}
-	cred->cr_expire = jiffies + cred->cr_auth->au_expire;
-	spin_unlock(&rpc_credcache_lock);
+	cred->cr_ops->crdestroy(cred);
 }
 
 void
@@ -335,8 +318,7 @@
 
 	dprintk("RPC: %4d marshaling %s cred %p\n",
 		task->tk_pid, auth->au_ops->au_name, cred);
-	return cred->cr_ops->crmarshal(task, p,
-				task->tk_flags & RPC_CALL_REALUID);
+	return cred->cr_ops->crmarshal(task, p);
 }
 
 u32 *
@@ -357,7 +339,7 @@
 	struct rpc_cred *cred = task->tk_msg.rpc_cred;
 
 	dprintk("RPC: %4d using %s cred %p to wrap rpc data\n",
-			task->tk_pid, cred->cr_auth->au_ops->au_name, cred);
+			task->tk_pid, cred->cr_ops->cr_name, cred);
 	if (cred->cr_ops->crwrap_req)
 		return cred->cr_ops->crwrap_req(task, encode, rqstp, data, obj);
 	/* By default, we encode the arguments normally. */
@@ -371,7 +353,7 @@
 	struct rpc_cred *cred = task->tk_msg.rpc_cred;
 
 	dprintk("RPC: %4d using %s cred %p to unwrap rpc data\n",
-			task->tk_pid, cred->cr_auth->au_ops->au_name, cred);
+			task->tk_pid, cred->cr_ops->cr_name, cred);
 	if (cred->cr_ops->crunwrap_resp)
 		return cred->cr_ops->crunwrap_resp(task, decode, rqstp,
 						   data, obj);
@@ -384,11 +366,14 @@
 {
 	struct rpc_auth	*auth = task->tk_auth;
 	struct rpc_cred	*cred = task->tk_msg.rpc_cred;
+	int err;
 
 	dprintk("RPC: %4d refreshing %s cred %p\n",
 		task->tk_pid, auth->au_ops->au_name, cred);
-	task->tk_status = cred->cr_ops->crrefresh(task);
-	return task->tk_status;
+	err = cred->cr_ops->crrefresh(task);
+	if (err < 0)
+		task->tk_status = err;
+	return err;
 }
 
 void
diff -Nru a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c
--- a/net/sunrpc/auth_gss/auth_gss.c	2005-03-11 12:51:43 -08:00
+++ b/net/sunrpc/auth_gss/auth_gss.c	2005-03-11 12:51:43 -08:00
@@ -85,7 +85,9 @@
 struct gss_auth {
 	struct rpc_auth rpc_auth;
 	struct gss_api_mech *mech;
+	enum rpc_gss_svc service;
 	struct list_head upcalls;
+	struct rpc_clnt *client;
 	struct dentry *dentry;
 	char path[48];
 	spinlock_t lock;
@@ -175,42 +177,34 @@
 	return res;
 }
 
-static inline int
-simple_get_bytes(char **ptr, const char *end, void *res, int len)
+static const void *
+simple_get_bytes(const void *p, const void *end, void *res, size_t len)
 {
-	char *p, *q;
-	p = *ptr;
-	q = p + len;
-	if (q > end || q < p)
-		return -1;
+	const void *q = (const void *)((const char *)p + len);
+	if (unlikely(q > end || q < p))
+		return ERR_PTR(-EFAULT);
 	memcpy(res, p, len);
-	*ptr = q;
-	return 0;
+	return q;
 }
 
-static inline int
-simple_get_netobj(char **ptr, const char *end, struct xdr_netobj *res)
+static inline const void *
+simple_get_netobj(const void *p, const void *end, struct xdr_netobj *dest)
 {
-	char *p, *q;
-	p = *ptr;
-	if (simple_get_bytes(&p, end, &res->len, sizeof(res->len)))
-		return -1;
-	q = p + res->len;
-	if (q > end || q < p)
-		return -1;
-	res->data = p;
-	*ptr = q;
-	return 0;
-}
+	const void *q;
+	unsigned int len;
 
-static int
-dup_netobj(struct xdr_netobj *source, struct xdr_netobj *dest)
-{
-	dest->len = source->len;
-	if (!(dest->data = kmalloc(dest->len, GFP_KERNEL)))
-		return -1;
-	memcpy(dest->data, source->data, dest->len);
-	return 0;
+	p = simple_get_bytes(p, end, &len, sizeof(len));
+	if (IS_ERR(p))
+		return p;
+	q = (const void *)((const char *)p + len);
+	if (unlikely(q > end || q < p))
+		return ERR_PTR(-EFAULT);
+	dest->data = kmalloc(len, GFP_KERNEL);
+	if (unlikely(dest->data == NULL))
+		return ERR_PTR(-ENOMEM);
+	dest->len = len;
+	memcpy(dest->data, p, len);
+	return q;
 }
 
 static struct gss_cl_ctx *
@@ -226,74 +220,84 @@
 	return ctx;
 }
 
-static int
-gss_parse_init_downcall(struct gss_api_mech *gm, struct xdr_netobj *buf,
-		struct gss_cl_ctx **gc, uid_t *uid, int *gss_err)
+static struct gss_cl_ctx *
+gss_alloc_context(void)
 {
-	char *end = buf->data + buf->len;
-	char *p = buf->data;
 	struct gss_cl_ctx *ctx;
-	struct xdr_netobj tmp_buf;
+
+	ctx = kmalloc(sizeof(*ctx), GFP_KERNEL);
+	if (ctx != NULL) {
+		memset(ctx, 0, sizeof(*ctx));
+		ctx->gc_proc = RPC_GSS_PROC_DATA;
+		ctx->gc_seq = 1;	/* NetApp 6.4R1 doesn't accept seq. no. 0 */
+		spin_lock_init(&ctx->gc_seq_lock);
+		atomic_set(&ctx->count,1);
+	}
+	return ctx;
+}
+
+#define GSSD_MIN_TIMEOUT (60 * 60)
+static const void *
+gss_fill_context(const void *p, const void *end, struct gss_cl_ctx *ctx, struct gss_api_mech *gm)
+{
+	const void *q;
+	unsigned int seclen;
 	unsigned int timeout;
-	int err = -EIO;
+	u32 window_size;
+	int ret;
 
-	if (!(ctx = kmalloc(sizeof(*ctx), GFP_KERNEL))) {
-		err = -ENOMEM;
+	/* First unsigned int gives the lifetime (in seconds) of the cred */
+	p = simple_get_bytes(p, end, &timeout, sizeof(timeout));
+	if (IS_ERR(p))
 		goto err;
-	}
-	ctx->gc_proc = RPC_GSS_PROC_DATA;
-	ctx->gc_seq = 1;	/* NetApp 6.4R1 doesn't accept seq. no. 0 */
-	spin_lock_init(&ctx->gc_seq_lock);
-	atomic_set(&ctx->count,1);
-
-	if (simple_get_bytes(&p, end, uid, sizeof(*uid)))
-		goto err_free_ctx;
-	/* FIXME: discarded timeout for now */
-	if (simple_get_bytes(&p, end, &timeout, sizeof(timeout)))
-		goto err_free_ctx;
-	*gss_err = 0;
-	if (simple_get_bytes(&p, end, &ctx->gc_win, sizeof(ctx->gc_win)))
-		goto err_free_ctx;
+	if (timeout == 0)
+		timeout = GSSD_MIN_TIMEOUT;
+	ctx->gc_expiry = jiffies + (unsigned long)timeout * HZ * 3 / 4;
+	/* Sequence number window. Determines the maximum number of simultaneous requests */
+	p = simple_get_bytes(p, end, &window_size, sizeof(window_size));
+	if (IS_ERR(p))
+		goto err;
+	ctx->gc_win = window_size;
 	/* gssd signals an error by passing ctx->gc_win = 0: */
-	if (!ctx->gc_win) {
-		/* in which case the next int is an error code: */
-		if (simple_get_bytes(&p, end, gss_err, sizeof(*gss_err)))
-			goto err_free_ctx;
-		err = 0;
-		goto err_free_ctx;
-	}
-	if (simple_get_netobj(&p, end, &tmp_buf))
-		goto err_free_ctx;
-	if (dup_netobj(&tmp_buf, &ctx->gc_wire_ctx)) {
-		err = -ENOMEM;
-		goto err_free_ctx;
-	}
-	if (simple_get_netobj(&p, end, &tmp_buf))
-		goto err_free_wire_ctx;
-	if (p != end)
-		goto err_free_wire_ctx;
-	if (gss_import_sec_context(&tmp_buf, gm, &ctx->gc_gss_ctx))
-		goto err_free_wire_ctx;
-	*gc = ctx;
-	return 0;
-err_free_wire_ctx:
-	kfree(ctx->gc_wire_ctx.data);
-err_free_ctx:
-	kfree(ctx);
+	if (ctx->gc_win == 0) {
+		/* in which case, p points to  an error code which we ignore */
+		p = ERR_PTR(-EACCES);
+		goto err;
+	}
+	/* copy the opaque wire context */
+	p = simple_get_netobj(p, end, &ctx->gc_wire_ctx);
+	if (IS_ERR(p))
+		goto err;
+	/* import the opaque security context */
+	p  = simple_get_bytes(p, end, &seclen, sizeof(seclen));
+	if (IS_ERR(p))
+		goto err;
+	q = (const void *)((const char *)p + seclen);
+	if (unlikely(q > end || q < p)) {
+		p = ERR_PTR(-EFAULT);
+		goto err;
+	}
+	ret = gss_import_sec_context(p, seclen, gm, &ctx->gc_gss_ctx);
+	if (ret < 0) {
+		p = ERR_PTR(ret);
+		goto err;
+	}
+	return q;
 err:
-	*gc = NULL;
-	dprintk("RPC:      gss_parse_init_downcall returning %d\n", err);
-	return err;
+	dprintk("RPC:      gss_fill_context returning %ld\n", -PTR_ERR(p));
+	return p;
 }
 
 
 struct gss_upcall_msg {
+	atomic_t count;
+	uid_t	uid;
 	struct rpc_pipe_msg msg;
 	struct list_head list;
 	struct gss_auth *auth;
-	struct rpc_wait_queue waitq;
-	uid_t	uid;
-	atomic_t count;
+	struct rpc_wait_queue rpc_waitqueue;
+	wait_queue_head_t waitqueue;
+	struct gss_cl_ctx *ctx;
 };
 
 static void
@@ -302,6 +306,8 @@
 	if (!atomic_dec_and_test(&gss_msg->count))
 		return;
 	BUG_ON(!list_empty(&gss_msg->list));
+	if (gss_msg->ctx != NULL)
+		gss_put_ctx(gss_msg->ctx);
 	kfree(gss_msg);
 }
 
@@ -320,16 +326,34 @@
 	return NULL;
 }
 
+/* Try to add a upcall to the pipefs queue.
+ * If an upcall owned by our uid already exists, then we return a reference
+ * to that upcall instead of adding the new upcall.
+ */
+static inline struct gss_upcall_msg *
+gss_add_msg(struct gss_auth *gss_auth, struct gss_upcall_msg *gss_msg)
+{
+	struct gss_upcall_msg *old;
+
+	spin_lock(&gss_auth->lock);
+	old = __gss_find_upcall(gss_auth, gss_msg->uid);
+	if (old == NULL) {
+		atomic_inc(&gss_msg->count);
+		list_add(&gss_msg->list, &gss_auth->upcalls);
+	} else
+		gss_msg = old;
+	spin_unlock(&gss_auth->lock);
+	return gss_msg;
+}
+
 static void
 __gss_unhash_msg(struct gss_upcall_msg *gss_msg)
 {
 	if (list_empty(&gss_msg->list))
 		return;
 	list_del_init(&gss_msg->list);
-	if (gss_msg->msg.errno < 0)
-		rpc_wake_up_status(&gss_msg->waitq, gss_msg->msg.errno);
-	else
-		rpc_wake_up(&gss_msg->waitq);
+	rpc_wake_up_status(&gss_msg->rpc_waitqueue, gss_msg->msg.errno);
+	wake_up_all(&gss_msg->waitqueue);
 	atomic_dec(&gss_msg->count);
 }
 
@@ -343,76 +367,139 @@
 	spin_unlock(&gss_auth->lock);
 }
 
-static int
-gss_upcall(struct rpc_clnt *clnt, struct rpc_task *task, struct rpc_cred *cred)
+static void
+gss_upcall_callback(struct rpc_task *task)
 {
-	struct gss_auth *gss_auth = container_of(clnt->cl_auth,
-			struct gss_auth, rpc_auth);
-	struct gss_upcall_msg *gss_msg, *gss_new = NULL;
-	struct rpc_pipe_msg *msg;
-	struct dentry *dentry = gss_auth->dentry;
-	uid_t uid = cred->cr_uid;
-	int res = 0;
+	struct gss_cred *gss_cred = container_of(task->tk_msg.rpc_cred,
+			struct gss_cred, gc_base);
+	struct gss_upcall_msg *gss_msg = gss_cred->gc_upcall;
+
+	BUG_ON(gss_msg == NULL);
+	if (gss_msg->ctx)
+		gss_cred_set_ctx(task->tk_msg.rpc_cred, gss_get_ctx(gss_msg->ctx));
+	else
+		task->tk_status = gss_msg->msg.errno;
+	spin_lock(&gss_msg->auth->lock);
+	gss_cred->gc_upcall = NULL;
+	rpc_wake_up_status(&gss_msg->rpc_waitqueue, gss_msg->msg.errno);
+	spin_unlock(&gss_msg->auth->lock);
+	gss_release_msg(gss_msg);
+}
 
-	dprintk("RPC: %4u gss_upcall for uid %u\n", task->tk_pid, uid);
+static inline struct gss_upcall_msg *
+gss_alloc_msg(struct gss_auth *gss_auth, uid_t uid)
+{
+	struct gss_upcall_msg *gss_msg;
 
-retry:
-	spin_lock(&gss_auth->lock);
-	gss_msg = __gss_find_upcall(gss_auth, uid);
-	if (gss_msg)
-		goto out_sleep;
-	if (gss_new == NULL) {
-		spin_unlock(&gss_auth->lock);
-		gss_new = kmalloc(sizeof(*gss_new), GFP_KERNEL);
-		if (!gss_new) {
-			dprintk("RPC: %4u gss_upcall -ENOMEM\n", task->tk_pid);
-			return -ENOMEM;
+	gss_msg = kmalloc(sizeof(*gss_msg), GFP_KERNEL);
+	if (gss_msg != NULL) {
+		memset(gss_msg, 0, sizeof(*gss_msg));
+		INIT_LIST_HEAD(&gss_msg->list);
+		rpc_init_wait_queue(&gss_msg->rpc_waitqueue, "RPCSEC_GSS upcall waitq");
+		init_waitqueue_head(&gss_msg->waitqueue);
+		atomic_set(&gss_msg->count, 1);
+		gss_msg->msg.data = &gss_msg->uid;
+		gss_msg->msg.len = sizeof(gss_msg->uid);
+		gss_msg->uid = uid;
+		gss_msg->auth = gss_auth;
+	}
+	return gss_msg;
+}
+
+static struct gss_upcall_msg *
+gss_setup_upcall(struct rpc_clnt *clnt, struct gss_auth *gss_auth, struct rpc_cred *cred)
+{
+	struct gss_upcall_msg *gss_new, *gss_msg;
+
+	gss_new = gss_alloc_msg(gss_auth, cred->cr_uid);
+	if (gss_new == NULL)
+		return ERR_PTR(-ENOMEM);
+	gss_msg = gss_add_msg(gss_auth, gss_new);
+	if (gss_msg == gss_new) {
+		int res = rpc_queue_upcall(gss_auth->dentry->d_inode, &gss_new->msg);
+		if (res) {
+			gss_unhash_msg(gss_new);
+			gss_msg = ERR_PTR(res);
 		}
-		goto retry;
+	} else
+		gss_release_msg(gss_new);
+	return gss_msg;
+}
+
+static inline int
+gss_refresh_upcall(struct rpc_task *task)
+{
+	struct rpc_cred *cred = task->tk_msg.rpc_cred;
+	struct gss_auth *gss_auth = container_of(task->tk_client->cl_auth,
+			struct gss_auth, rpc_auth);
+	struct gss_cred *gss_cred = container_of(cred,
+			struct gss_cred, gc_base);
+	struct gss_upcall_msg *gss_msg;
+	int err = 0;
+
+	dprintk("RPC: %4u gss_refresh_upcall for uid %u\n", task->tk_pid, cred->cr_uid);
+	gss_msg = gss_setup_upcall(task->tk_client, gss_auth, cred);
+	if (IS_ERR(gss_msg)) {
+		err = PTR_ERR(gss_msg);
+		goto out;
 	}
-	gss_msg = gss_new;
-	memset(gss_new, 0, sizeof(*gss_new));
-	INIT_LIST_HEAD(&gss_new->list);
-	rpc_init_wait_queue(&gss_new->waitq, "RPCSEC_GSS upcall waitq");
-	atomic_set(&gss_new->count, 2);
-	msg = &gss_new->msg;
-	msg->data = &gss_new->uid;
-	msg->len = sizeof(gss_new->uid);
-	gss_new->uid = uid;
-	gss_new->auth = gss_auth;
-	list_add(&gss_new->list, &gss_auth->upcalls);
-	gss_new = NULL;
-	/* Has someone updated the credential behind our back? */
-	if (!gss_cred_is_uptodate_ctx(cred)) {
-		/* No, so do upcall and sleep */
+	spin_lock(&gss_auth->lock);
+	if (gss_cred->gc_upcall != NULL)
+		rpc_sleep_on(&gss_cred->gc_upcall->rpc_waitqueue, task, NULL, NULL);
+	else if (gss_msg->ctx == NULL && gss_msg->msg.errno >= 0) {
 		task->tk_timeout = 0;
-		rpc_sleep_on(&gss_msg->waitq, task, NULL, NULL);
-		spin_unlock(&gss_auth->lock);
-		res = rpc_queue_upcall(dentry->d_inode, msg);
-		if (res)
-			gss_unhash_msg(gss_msg);
-	} else {
-		/* Yes, so cancel upcall */
-		__gss_unhash_msg(gss_msg);
+		gss_cred->gc_upcall = gss_msg;
+		/* gss_upcall_callback will release the reference to gss_upcall_msg */
+		atomic_inc(&gss_msg->count);
+		rpc_sleep_on(&gss_msg->rpc_waitqueue, task, gss_upcall_callback, NULL);
+	} else
+		err = gss_msg->msg.errno;
+	spin_unlock(&gss_auth->lock);
+	gss_release_msg(gss_msg);
+out:
+	dprintk("RPC: %4u gss_refresh_upcall for uid %u result %d\n", task->tk_pid,
+			cred->cr_uid, err);
+	return err;
+}
+
+static inline int
+gss_create_upcall(struct gss_auth *gss_auth, struct gss_cred *gss_cred)
+{
+	struct rpc_cred *cred = &gss_cred->gc_base;
+	struct gss_upcall_msg *gss_msg;
+	DEFINE_WAIT(wait);
+	int err = 0;
+
+	dprintk("RPC: gss_upcall for uid %u\n", cred->cr_uid);
+	gss_msg = gss_setup_upcall(gss_auth->client, gss_auth, cred);
+	if (IS_ERR(gss_msg)) {
+		err = PTR_ERR(gss_msg);
+		goto out;
+	}
+	for (;;) {
+		prepare_to_wait(&gss_msg->waitqueue, &wait, TASK_INTERRUPTIBLE);
+		spin_lock(&gss_auth->lock);
+		if (gss_msg->ctx != NULL || gss_msg->msg.errno < 0) {
+			spin_unlock(&gss_auth->lock);
+			break;
+		}
 		spin_unlock(&gss_auth->lock);
+		if (signalled()) {
+			err = -ERESTARTSYS;
+			goto out_intr;
+		}
+		schedule();
 	}
+	if (gss_msg->ctx)
+		gss_cred_set_ctx(cred, gss_get_ctx(gss_msg->ctx));
+	else
+		err = gss_msg->msg.errno;
+out_intr:
+	finish_wait(&gss_msg->waitqueue, &wait);
 	gss_release_msg(gss_msg);
-	dprintk("RPC: %4u gss_upcall for uid %u result %d\n", task->tk_pid,
-			uid, res);
-	return res;
-out_sleep:
-	task->tk_timeout = 0;
-	rpc_sleep_on(&gss_msg->waitq, task, NULL, NULL);
-	spin_unlock(&gss_auth->lock);
-	dprintk("RPC: %4u gss_upcall  sleeping\n", task->tk_pid);
-	if (gss_new)
-		kfree(gss_new);
-	/* Note: we drop the reference here: we are automatically removed
-	 * from the queue when we're woken up, and we should in any case
-	 * have no further responsabilities w.r.t. the upcall.
-	 */
-	gss_release_msg(gss_msg);
-	return 0;
+out:
+	dprintk("RPC: gss_create_upcall for uid %u result %d\n", cred->cr_uid, err);
+	return err;
 }
 
 static ssize_t
@@ -441,68 +528,75 @@
 static ssize_t
 gss_pipe_downcall(struct file *filp, const char __user *src, size_t mlen)
 {
-	struct xdr_netobj obj = {
-		.len	= mlen,
-	};
-	struct inode *inode = filp->f_dentry->d_inode;
-	struct rpc_inode *rpci = RPC_I(inode);
+	const void *p, *end;
+	void *buf;
 	struct rpc_clnt *clnt;
-	struct rpc_auth *auth;
 	struct gss_auth *gss_auth;
-	struct gss_api_mech *mech;
-	struct auth_cred acred = { 0 };
 	struct rpc_cred *cred;
 	struct gss_upcall_msg *gss_msg;
-	struct gss_cl_ctx *ctx = NULL;
-	ssize_t left;
-	int err;
-	int gss_err;
+	struct gss_cl_ctx *ctx;
+	uid_t uid;
+	int err = -EFBIG;
 
 	if (mlen > MSG_BUF_MAXSIZE)
-		return -EFBIG;
-	obj.data = kmalloc(mlen, GFP_KERNEL);
-	if (!obj.data)
-		return -ENOMEM;
-	left = copy_from_user(obj.data, src, mlen);
-	if (left) {
-		err = -EFAULT;
 		goto out;
-	}
-	clnt = rpci->private;
-	atomic_inc(&clnt->cl_users);
-	auth = clnt->cl_auth;
-	gss_auth = container_of(auth, struct gss_auth, rpc_auth);
-	mech = gss_auth->mech;
-	err = gss_parse_init_downcall(mech, &obj, &ctx, &acred.uid, &gss_err);
-	if (err)
+	err = -ENOMEM;
+	buf = kmalloc(mlen, GFP_KERNEL);
+	if (!buf)
+		goto out;
+
+	clnt = RPC_I(filp->f_dentry->d_inode)->private;
+	err = -EFAULT;
+	if (copy_from_user(buf, src, mlen))
 		goto err;
-	cred = rpcauth_lookup_credcache(auth, &acred, 0);
-	if (!cred)
+
+	end = (const void *)((char *)buf + mlen);
+	p = simple_get_bytes(buf, end, &uid, sizeof(uid));
+	if (IS_ERR(p)) {
+		err = PTR_ERR(p);
 		goto err;
-	if (gss_err)
-		cred->cr_flags &= ~RPCAUTH_CRED_UPTODATE;
-	else
-		gss_cred_set_ctx(cred, ctx);
+	}
+
+	err = -ENOMEM;
+	ctx = gss_alloc_context();
+	if (ctx == NULL)
+		goto err;
+	err = 0;
+	gss_auth = container_of(clnt->cl_auth, struct gss_auth, rpc_auth);
+	p = gss_fill_context(p, end, ctx, gss_auth->mech);
+	if (IS_ERR(p)) {
+		err = PTR_ERR(p);
+		if (err != -EACCES)
+			goto err_put_ctx;
+	}
 	spin_lock(&gss_auth->lock);
-	gss_msg = __gss_find_upcall(gss_auth, acred.uid);
+	gss_msg = __gss_find_upcall(gss_auth, uid);
 	if (gss_msg) {
-		if (gss_err)
-			gss_msg->msg.errno = -EACCES;
+		if (err == 0 && gss_msg->ctx == NULL)
+			gss_msg->ctx = gss_get_ctx(ctx);
+		gss_msg->msg.errno = err;
 		__gss_unhash_msg(gss_msg);
 		spin_unlock(&gss_auth->lock);
 		gss_release_msg(gss_msg);
-	} else
+	} else {
+		struct auth_cred acred = { .uid = uid };
 		spin_unlock(&gss_auth->lock);
-	rpc_release_client(clnt);
-	kfree(obj.data);
+		cred = rpcauth_lookup_credcache(clnt->cl_auth, &acred, 0);
+		if (IS_ERR(cred)) {
+			err = PTR_ERR(cred);
+			goto err_put_ctx;
+		}
+		gss_cred_set_ctx(cred, gss_get_ctx(ctx));
+	}
+	gss_put_ctx(ctx);
+	kfree(buf);
 	dprintk("RPC:      gss_pipe_downcall returning length %Zu\n", mlen);
 	return mlen;
+err_put_ctx:
+	gss_put_ctx(ctx);
 err:
-	if (ctx)
-		gss_destroy_ctx(ctx);
-	rpc_release_client(clnt);
+	kfree(buf);
 out:
-	kfree(obj.data);
 	dprintk("RPC:      gss_pipe_downcall returning %d\n", err);
 	return err;
 }
@@ -569,24 +663,32 @@
 
 	dprintk("RPC:      creating GSS authenticator for client %p\n",clnt);
 
+	if (!try_module_get(THIS_MODULE))
+		return NULL;
 	if (!(gss_auth = kmalloc(sizeof(*gss_auth), GFP_KERNEL)))
 		goto out_dec;
+	gss_auth->client = clnt;
 	gss_auth->mech = gss_mech_get_by_pseudoflavor(flavor);
 	if (!gss_auth->mech) {
 		printk(KERN_WARNING "%s: Pseudoflavor %d not found!",
 				__FUNCTION__, flavor);
 		goto err_free;
 	}
+	gss_auth->service = gss_pseudoflavor_to_service(gss_auth->mech, flavor);
+	/* FIXME: Will go away once privacy support is merged in */
+	if (gss_auth->service == RPC_GSS_SVC_PRIVACY)
+		gss_auth->service = RPC_GSS_SVC_INTEGRITY;
 	INIT_LIST_HEAD(&gss_auth->upcalls);
 	spin_lock_init(&gss_auth->lock);
 	auth = &gss_auth->rpc_auth;
 	auth->au_cslack = GSS_CRED_SLACK >> 2;
 	auth->au_rslack = GSS_VERF_SLACK >> 2;
-	auth->au_expire = GSS_CRED_EXPIRE;
 	auth->au_ops = &authgss_ops;
 	auth->au_flavor = flavor;
+	atomic_set(&auth->au_count, 1);
 
-	rpcauth_init_credcache(auth);
+	if (rpcauth_init_credcache(auth, GSS_CRED_EXPIRE) < 0)
+		goto err_put_mech;
 
 	snprintf(gss_auth->path, sizeof(gss_auth->path), "%s/%s",
 			clnt->cl_pathname,
@@ -601,6 +703,7 @@
 err_free:
 	kfree(gss_auth);
 out_dec:
+	module_put(THIS_MODULE);
 	return NULL;
 }
 
@@ -617,6 +720,8 @@
 	gss_mech_put(gss_auth->mech);
 
 	rpcauth_free_credcache(auth);
+	kfree(gss_auth);
+	module_put(THIS_MODULE);
 }
 
 /* gss_destroy_cred (and gss_destroy_ctx) are used to clean up after failure
@@ -630,19 +735,14 @@
 	if (ctx->gc_gss_ctx)
 		gss_delete_sec_context(&ctx->gc_gss_ctx);
 
-	if (ctx->gc_wire_ctx.len > 0) {
-		kfree(ctx->gc_wire_ctx.data);
-		ctx->gc_wire_ctx.len = 0;
-	}
-
+	kfree(ctx->gc_wire_ctx.data);
 	kfree(ctx);
-
 }
 
 static void
 gss_destroy_cred(struct rpc_cred *rc)
 {
-	struct gss_cred *cred = (struct gss_cred *)rc;
+	struct gss_cred *cred = container_of(rc, struct gss_cred, gc_base);
 
 	dprintk("RPC:      gss_destroy_cred \n");
 
@@ -651,10 +751,21 @@
 	kfree(cred);
 }
 
+/*
+ * Lookup RPCSEC_GSS cred for the current process
+ */
+static struct rpc_cred *
+gss_lookup_cred(struct rpc_auth *auth, struct auth_cred *acred, int taskflags)
+{
+	return rpcauth_lookup_credcache(auth, acred, taskflags);
+}
+
 static struct rpc_cred *
 gss_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int taskflags)
 {
+	struct gss_auth *gss_auth = container_of(auth, struct gss_auth, rpc_auth);
 	struct gss_cred	*cred = NULL;
+	int err = -ENOMEM;
 
 	dprintk("RPC:      gss_create_cred for uid %d, flavor %d\n",
 		acred->uid, auth->au_flavor);
@@ -663,7 +774,7 @@
 		goto out_err;
 
 	memset(cred, 0, sizeof(*cred));
-	atomic_set(&cred->gc_count, 0);
+	atomic_set(&cred->gc_count, 1);
 	cred->gc_uid = acred->uid;
 	/*
 	 * Note: in order to force a call to call_refresh(), we deliberately
@@ -671,19 +782,27 @@
 	 */
 	cred->gc_flags = 0;
 	cred->gc_base.cr_ops = &gss_credops;
-	cred->gc_flavor = auth->au_flavor;
+	cred->gc_service = gss_auth->service;
+	err = gss_create_upcall(gss_auth, cred);
+	if (err < 0)
+		goto out_err;
 
-	return (struct rpc_cred *) cred;
+	return &cred->gc_base;
 
 out_err:
-	dprintk("RPC:      gss_create_cred failed\n");
-	if (cred) gss_destroy_cred((struct rpc_cred *)cred);
-	return NULL;
+	dprintk("RPC:      gss_create_cred failed with error %d\n", err);
+	if (cred) gss_destroy_cred(&cred->gc_base);
+	return ERR_PTR(err);
 }
 
 static int
 gss_match(struct auth_cred *acred, struct rpc_cred *rc, int taskflags)
 {
+	struct gss_cred *gss_cred = container_of(rc, struct gss_cred, gc_base);
+
+	/* Don't match with creds that have expired. */
+	if (gss_cred->gc_ctx && time_after(jiffies, gss_cred->gc_ctx->gc_expiry))
+		return 0;
 	return (rc->cr_uid == acred->uid);
 }
 
@@ -692,7 +811,7 @@
 * Maybe we should keep a cached credential for performance reasons.
 */
 static u32 *
-gss_marshal(struct rpc_task *task, u32 *p, int ruid)
+gss_marshal(struct rpc_task *task, u32 *p)
 {
 	struct rpc_cred *cred = task->tk_msg.rpc_cred;
 	struct gss_cred	*gss_cred = container_of(cred, struct gss_cred,
@@ -704,20 +823,12 @@
 	struct xdr_netobj mic;
 	struct kvec	iov;
 	struct xdr_buf	verf_buf;
-	u32		service;
 
 	dprintk("RPC: %4u gss_marshal\n", task->tk_pid);
 
 	*p++ = htonl(RPC_AUTH_GSS);
 	cred_len = p++;
 
-	service = gss_pseudoflavor_to_service(ctx->gc_gss_ctx->mech_type,
-						gss_cred->gc_flavor);
-	if (service == 0) {
-		dprintk("RPC: %4u Bad pseudoflavor %d in gss_marshal\n",
-			task->tk_pid, gss_cred->gc_flavor);
-		goto out_put_ctx;
-	}
 	spin_lock(&ctx->gc_seq_lock);
 	req->rq_seqno = ctx->gc_seq++;
 	spin_unlock(&ctx->gc_seq_lock);
@@ -725,7 +836,7 @@
 	*p++ = htonl((u32) RPC_GSS_VERSION);
 	*p++ = htonl((u32) ctx->gc_proc);
 	*p++ = htonl((u32) req->rq_seqno);
-	*p++ = htonl((u32) service);
+	*p++ = htonl((u32) gss_cred->gc_service);
 	p = xdr_encode_netobj(p, &ctx->gc_wire_ctx);
 	*cred_len = htonl((p - (cred_len + 1)) << 2);
 
@@ -765,11 +876,9 @@
 static int
 gss_refresh(struct rpc_task *task)
 {
-	struct rpc_clnt *clnt = task->tk_client;
-	struct rpc_cred *cred = task->tk_msg.rpc_cred;
 
-	if (!gss_cred_is_uptodate_ctx(cred))
-		return gss_upcall(clnt, task, cred);
+	if (!gss_cred_is_uptodate_ctx(task->tk_msg.rpc_cred))
+		return gss_refresh_upcall(task);
 	return 0;
 }
 
@@ -785,7 +894,6 @@
 	struct xdr_buf	verf_buf;
 	struct xdr_netobj mic;
 	u32		flav,len;
-	u32		service;
 	u32		maj_stat;
 
 	dprintk("RPC: %4u gss_validate\n", task->tk_pid);
@@ -807,9 +915,7 @@
 		cred->cr_flags &= ~RPCAUTH_CRED_UPTODATE;
 	if (maj_stat)
 		goto out_bad;
-       service = gss_pseudoflavor_to_service(ctx->gc_gss_ctx->mech_type,
-					gss_cred->gc_flavor);
-       switch (service) {
+       switch (gss_cred->gc_service) {
        case RPC_GSS_SVC_NONE:
 	       /* verifier data, flavor, length: */
 	       task->tk_auth->au_rslack = XDR_QUADLEN(len) + 2;
@@ -818,7 +924,7 @@
 	       /* verifier data, flavor, length, length, sequence number: */
 	       task->tk_auth->au_rslack = XDR_QUADLEN(len) + 4;
 	       break;
-       default:
+       case RPC_GSS_SVC_PRIVACY:
 	       goto out_bad;
        }
 	gss_put_ctx(ctx);
@@ -889,7 +995,6 @@
 			gc_base);
 	struct gss_cl_ctx *ctx = gss_cred_get_ctx(cred);
 	int             status = -EIO;
-	u32		service;
 
 	dprintk("RPC: %4u gss_wrap_req\n", task->tk_pid);
 	if (ctx->gc_proc != RPC_GSS_PROC_DATA) {
@@ -899,19 +1004,16 @@
 		status = encode(rqstp, p, obj);
 		goto out;
 	}
-	service = gss_pseudoflavor_to_service(ctx->gc_gss_ctx->mech_type,
-						gss_cred->gc_flavor);
-	switch (service) {
+	switch (gss_cred->gc_service) {
 		case RPC_GSS_SVC_NONE:
 			status = encode(rqstp, p, obj);
-			goto out;
+			break;
 		case RPC_GSS_SVC_INTEGRITY:
 			status = gss_wrap_req_integ(cred, ctx, encode,
 								rqstp, p, obj);
-			goto out;
-		case RPC_GSS_SVC_PRIVACY:
-		default:
-			goto out;
+			break;
+       		case RPC_GSS_SVC_PRIVACY:
+			break;
 	}
 out:
 	gss_put_ctx(ctx);
@@ -966,23 +1068,19 @@
 			gc_base);
 	struct gss_cl_ctx *ctx = gss_cred_get_ctx(cred);
 	int             status = -EIO;
-	u32		service;
 
 	if (ctx->gc_proc != RPC_GSS_PROC_DATA)
 		goto out_decode;
-	service = gss_pseudoflavor_to_service(ctx->gc_gss_ctx->mech_type,
-						gss_cred->gc_flavor);
-	switch (service) {
+	switch (gss_cred->gc_service) {
 		case RPC_GSS_SVC_NONE:
-			goto out_decode;
+			break;
 		case RPC_GSS_SVC_INTEGRITY:
 			status = gss_unwrap_resp_integ(cred, ctx, rqstp, &p);
 			if (status)
 				goto out;
 			break;
-		case RPC_GSS_SVC_PRIVACY:
-		default:
-			goto out;
+       		case RPC_GSS_SVC_PRIVACY:
+			break;
 	}
 out_decode:
 	status = decode(rqstp, p, obj);
@@ -1001,10 +1099,12 @@
 #endif
 	.create		= gss_create,
 	.destroy	= gss_destroy,
+	.lookup_cred	= gss_lookup_cred,
 	.crcreate	= gss_create_cred
 };
 
 static struct rpc_credops gss_credops = {
+	.cr_name	= "AUTH_GSS",
 	.crdestroy	= gss_destroy_cred,
 	.crmatch	= gss_match,
 	.crmarshal	= gss_marshal,
diff -Nru a/net/sunrpc/auth_gss/gss_krb5_mech.c b/net/sunrpc/auth_gss/gss_krb5_mech.c
--- a/net/sunrpc/auth_gss/gss_krb5_mech.c	2005-03-11 12:51:47 -08:00
+++ b/net/sunrpc/auth_gss/gss_krb5_mech.c	2005-03-11 12:51:47 -08:00
@@ -48,46 +48,48 @@
 # define RPCDBG_FACILITY	RPCDBG_AUTH
 #endif
 
-static inline int
-get_bytes(char **ptr, const char *end, void *res, int len)
+static const void *
+simple_get_bytes(const void *p, const void *end, void *res, int len)
 {
-	char *p, *q;
-	p = *ptr;
-	q = p + len;
-	if (q > end || q < p)
-		return -1;
+	const void *q = (const void *)((const char *)p + len);
+	if (unlikely(q > end || q < p))
+		return ERR_PTR(-EFAULT);
 	memcpy(res, p, len);
-	*ptr = q;
-	return 0;
+	return q;
 }
 
-static inline int
-get_netobj(char **ptr, const char *end, struct xdr_netobj *res)
+static const void *
+simple_get_netobj(const void *p, const void *end, struct xdr_netobj *res)
 {
-	char *p, *q;
-	p = *ptr;
-	if (get_bytes(&p, end, &res->len, sizeof(res->len)))
-		return -1;
-	q = p + res->len;
-	if (q > end || q < p)
-		return -1;
-	if (!(res->data = kmalloc(res->len, GFP_KERNEL)))
-		return -1;
-	memcpy(res->data, p, res->len);
-	*ptr = q;
-	return 0;
+	const void *q;
+	unsigned int len;
+
+	p = simple_get_bytes(p, end, &len, sizeof(len));
+	if (IS_ERR(p))
+		return p;
+	q = (const void *)((const char *)p + len);
+	if (unlikely(q > end || q < p))
+		return ERR_PTR(-EFAULT);
+	res->data = kmalloc(len, GFP_KERNEL);
+	if (unlikely(res->data == NULL))
+		return ERR_PTR(-ENOMEM);
+	memcpy(res->data, p, len);
+	res->len = len;
+	return q;
 }
 
-static inline int
-get_key(char **p, char *end, struct crypto_tfm **res)
+static inline const void *
+get_key(const void *p, const void *end, struct crypto_tfm **res)
 {
 	struct xdr_netobj	key;
 	int			alg, alg_mode;
 	char			*alg_name;
 
-	if (get_bytes(p, end, &alg, sizeof(alg)))
+	p = simple_get_bytes(p, end, &alg, sizeof(alg));
+	if (IS_ERR(p))
 		goto out_err;
-	if ((get_netobj(p, end, &key)))
+	p = simple_get_netobj(p, end, &key);
+	if (IS_ERR(p))
 		goto out_err;
 
 	switch (alg) {
@@ -105,50 +107,63 @@
 		goto out_err_free_tfm;
 
 	kfree(key.data);
-	return 0;
+	return p;
 
 out_err_free_tfm:
 	crypto_free_tfm(*res);
 out_err_free_key:
 	kfree(key.data);
+	p = ERR_PTR(-EINVAL);
 out_err:
-	return -1;
+	return p;
 }
 
-static u32
-gss_import_sec_context_kerberos(struct xdr_netobj *inbuf,
+static int
+gss_import_sec_context_kerberos(const void *p,
+				size_t len,
 				struct gss_ctx *ctx_id)
 {
-	char	*p = inbuf->data;
-	char	*end = inbuf->data + inbuf->len;
+	const void *end = (const void *)((const char *)p + len);
 	struct	krb5_ctx *ctx;
 
 	if (!(ctx = kmalloc(sizeof(*ctx), GFP_KERNEL)))
 		goto out_err;
 	memset(ctx, 0, sizeof(*ctx));
 
-	if (get_bytes(&p, end, &ctx->initiate, sizeof(ctx->initiate)))
+	p = simple_get_bytes(p, end, &ctx->initiate, sizeof(ctx->initiate));
+	if (IS_ERR(p))
 		goto out_err_free_ctx;
-	if (get_bytes(&p, end, &ctx->seed_init, sizeof(ctx->seed_init)))
+	p = simple_get_bytes(p, end, &ctx->seed_init, sizeof(ctx->seed_init));
+	if (IS_ERR(p))
 		goto out_err_free_ctx;
-	if (get_bytes(&p, end, ctx->seed, sizeof(ctx->seed)))
+	p = simple_get_bytes(p, end, ctx->seed, sizeof(ctx->seed));
+	if (IS_ERR(p))
 		goto out_err_free_ctx;
-	if (get_bytes(&p, end, &ctx->signalg, sizeof(ctx->signalg)))
+	p = simple_get_bytes(p, end, &ctx->signalg, sizeof(ctx->signalg));
+	if (IS_ERR(p))
 		goto out_err_free_ctx;
-	if (get_bytes(&p, end, &ctx->sealalg, sizeof(ctx->sealalg)))
+	p = simple_get_bytes(p, end, &ctx->sealalg, sizeof(ctx->sealalg));
+	if (IS_ERR(p))
 		goto out_err_free_ctx;
-	if (get_bytes(&p, end, &ctx->endtime, sizeof(ctx->endtime)))
+	p = simple_get_bytes(p, end, &ctx->endtime, sizeof(ctx->endtime));
+	if (IS_ERR(p))
 		goto out_err_free_ctx;
-	if (get_bytes(&p, end, &ctx->seq_send, sizeof(ctx->seq_send)))
+	p = simple_get_bytes(p, end, &ctx->seq_send, sizeof(ctx->seq_send));
+	if (IS_ERR(p))
 		goto out_err_free_ctx;
-	if (get_netobj(&p, end, &ctx->mech_used))
+	p = simple_get_netobj(p, end, &ctx->mech_used);
+	if (IS_ERR(p))
 		goto out_err_free_ctx;
-	if (get_key(&p, end, &ctx->enc))
+	p = get_key(p, end, &ctx->enc);
+	if (IS_ERR(p))
 		goto out_err_free_mech;
-	if (get_key(&p, end, &ctx->seq))
+	p = get_key(p, end, &ctx->seq);
+	if (IS_ERR(p))
 		goto out_err_free_key1;
-	if (p != end)
+	if (p != end) {
+		p = ERR_PTR(-EFAULT);
 		goto out_err_free_key2;
+	}
 
 	ctx_id->internal_ctx_id = ctx;
 	dprintk("RPC:      Succesfully imported new context.\n");
@@ -163,7 +178,7 @@
 out_err_free_ctx:
 	kfree(ctx);
 out_err:
-	return GSS_S_FAILURE;
+	return PTR_ERR(p);
 }
 
 static void
diff -Nru a/net/sunrpc/auth_gss/gss_mech_switch.c b/net/sunrpc/auth_gss/gss_mech_switch.c
--- a/net/sunrpc/auth_gss/gss_mech_switch.c	2005-03-11 12:51:47 -08:00
+++ b/net/sunrpc/auth_gss/gss_mech_switch.c	2005-03-11 12:51:47 -08:00
@@ -143,7 +143,7 @@
 EXPORT_SYMBOL(gss_mech_get);
 
 struct gss_api_mech *
-gss_mech_get_by_name(char *name)
+gss_mech_get_by_name(const char *name)
 {
 	struct gss_api_mech	*pos, *gm = NULL;
 
@@ -233,8 +233,8 @@
 
 /* The mech could probably be determined from the token instead, but it's just
  * as easy for now to pass it in. */
-u32
-gss_import_sec_context(struct xdr_netobj	*input_token,
+int
+gss_import_sec_context(const void *input_token, size_t bufsize,
 		       struct gss_api_mech	*mech,
 		       struct gss_ctx		**ctx_id)
 {
@@ -244,7 +244,7 @@
 	(*ctx_id)->mech_type = gss_mech_get(mech);
 
 	return mech->gm_ops
-		->gss_import_sec_context(input_token, *ctx_id);
+		->gss_import_sec_context(input_token, bufsize, *ctx_id);
 }
 
 /* gss_get_mic: compute a mic over message and return mic_token. */
diff -Nru a/net/sunrpc/auth_gss/gss_spkm3_mech.c b/net/sunrpc/auth_gss/gss_spkm3_mech.c
--- a/net/sunrpc/auth_gss/gss_spkm3_mech.c	2005-03-11 12:51:50 -08:00
+++ b/net/sunrpc/auth_gss/gss_spkm3_mech.c	2005-03-11 12:51:50 -08:00
@@ -49,52 +49,51 @@
 # define RPCDBG_FACILITY	RPCDBG_AUTH
 #endif
 
-static inline int
-get_bytes(char **ptr, const char *end, void *res, int len)
+static const void *
+simple_get_bytes(const void *p, const void *end, void *res, int len)
 {
-	char *p, *q;
-	p = *ptr;
-	q = p + len;
-	if (q > end || q < p)
-		return -1;
+	const void *q = (const void *)((const char *)p + len);
+	if (unlikely(q > end || q < p))
+		return ERR_PTR(-EFAULT);
 	memcpy(res, p, len);
-	*ptr = q;
-	return 0;
+	return q;
 }
 
-static inline int
-get_netobj(char **ptr, const char *end, struct xdr_netobj *res)
+static const void *
+simple_get_netobj(const void *p, const void *end, struct xdr_netobj *res)
 {
-	char *p, *q;
-	p = *ptr;
-	if (get_bytes(&p, end, &res->len, sizeof(res->len)))
-		return -1;
-	q = p + res->len;
-	if(res->len == 0)
-		goto out_nocopy;
-	if (q > end || q < p)
-		return -1;
-	if (!(res->data = kmalloc(res->len, GFP_KERNEL)))
-		return -1;
-	memcpy(res->data, p, res->len);
-out_nocopy:
-	*ptr = q;
-	return 0;
+	const void *q;
+	unsigned int len;
+	p = simple_get_bytes(p, end, &len, sizeof(len));
+	if (IS_ERR(p))
+		return p;
+	res->len = len;
+	if (len == 0) {
+		res->data = NULL;
+		return p;
+	}
+	q = (const void *)((const char *)p + len);
+	if (unlikely(q > end || q < p))
+		return ERR_PTR(-EFAULT);
+	res->data = kmalloc(len, GFP_KERNEL);
+	if (unlikely(res->data == NULL))
+		return ERR_PTR(-ENOMEM);
+	memcpy(res->data, p, len);
+	return q;
 }
 
-static inline int
-get_key(char **p, char *end, struct crypto_tfm **res, int *resalg)
+static inline const void *
+get_key(const void *p, const void *end, struct crypto_tfm **res, int *resalg)
 {
-	struct xdr_netobj	key = {
-		.len = 0,
-		.data = NULL,
-	};
+	struct xdr_netobj	key = { 0 };
 	int			alg_mode,setkey = 0;
 	char			*alg_name;
 
-	if (get_bytes(p, end, resalg, sizeof(int)))
+	p = simple_get_bytes(p, end, resalg, sizeof(*resalg));
+	if (IS_ERR(p))
 		goto out_err;
-	if ((get_netobj(p, end, &key)))
+	p = simple_get_netobj(p, end, &key);
+	if (IS_ERR(p))
 		goto out_err;
 
 	switch (*resalg) {
@@ -111,10 +110,6 @@
 			alg_mode = 0;
 			setkey = 0;
 			break;
-		case NID_cast5_cbc:
-			dprintk("RPC: SPKM3 get_key: case cast5_cbc, UNSUPPORTED \n");
-			goto out_err;
-			break;
 		default:
 			dprintk("RPC: SPKM3 get_key: unsupported algorithm %d", *resalg);
 			goto out_err_free_key;
@@ -128,69 +123,81 @@
 
 	if(key.len > 0)
 		kfree(key.data);
-	return 0;
+	return p;
 
 out_err_free_tfm:
 	crypto_free_tfm(*res);
 out_err_free_key:
 	if(key.len > 0)
 		kfree(key.data);
+	p = ERR_PTR(-EINVAL);
 out_err:
-	return -1;
+	return p;
 }
 
-static u32
-gss_import_sec_context_spkm3(struct xdr_netobj *inbuf,
+static int
+gss_import_sec_context_spkm3(const void *p, size_t len,
 				struct gss_ctx *ctx_id)
 {
-	char	*p = inbuf->data;
-	char	*end = inbuf->data + inbuf->len;
+	const void *end = (const void *)((const char *)p + len);
 	struct	spkm3_ctx *ctx;
 
 	if (!(ctx = kmalloc(sizeof(*ctx), GFP_KERNEL)))
 		goto out_err;
 	memset(ctx, 0, sizeof(*ctx));
 
-	if (get_netobj(&p, end, &ctx->ctx_id))
+	p = simple_get_netobj(p, end, &ctx->ctx_id);
+	if (IS_ERR(p))
 		goto out_err_free_ctx;
 
-	if (get_bytes(&p, end, &ctx->qop, sizeof(ctx->qop)))
+	p = simple_get_bytes(p, end, &ctx->qop, sizeof(ctx->qop));
+	if (IS_ERR(p))
 		goto out_err_free_ctx_id;
 
-	if (get_netobj(&p, end, &ctx->mech_used))
+	p = simple_get_netobj(p, end, &ctx->mech_used);
+	if (IS_ERR(p))
 		goto out_err_free_mech;
 
-	if (get_bytes(&p, end, &ctx->ret_flags, sizeof(ctx->ret_flags)))
+	p = simple_get_bytes(p, end, &ctx->ret_flags, sizeof(ctx->ret_flags));
+	if (IS_ERR(p))
 		goto out_err_free_mech;
 
-	if (get_bytes(&p, end, &ctx->req_flags, sizeof(ctx->req_flags)))
+	p = simple_get_bytes(p, end, &ctx->req_flags, sizeof(ctx->req_flags));
+	if (IS_ERR(p))
 		goto out_err_free_mech;
 
-	if (get_netobj(&p, end, &ctx->share_key))
+	p = simple_get_netobj(p, end, &ctx->share_key);
+	if (IS_ERR(p))
 		goto out_err_free_s_key;
 
-	if (get_key(&p, end, &ctx->derived_conf_key, &ctx->conf_alg)) {
-		dprintk("RPC: SPKM3 confidentiality key will be NULL\n");
-	}
-
-	if (get_key(&p, end, &ctx->derived_integ_key, &ctx->intg_alg)) {
-		dprintk("RPC: SPKM3 integrity key will be NULL\n");
-	}
-
-	if (get_bytes(&p, end, &ctx->owf_alg, sizeof(ctx->owf_alg)))
+	p = get_key(p, end, &ctx->derived_conf_key, &ctx->conf_alg);
+	if (IS_ERR(p))
 		goto out_err_free_s_key;
 
-	if (get_bytes(&p, end, &ctx->owf_alg, sizeof(ctx->owf_alg)))
-		goto out_err_free_s_key;
+	p = get_key(p, end, &ctx->derived_integ_key, &ctx->intg_alg);
+	if (IS_ERR(p))
+		goto out_err_free_key1;
+
+	p = simple_get_bytes(p, end, &ctx->keyestb_alg, sizeof(ctx->keyestb_alg));
+	if (IS_ERR(p))
+		goto out_err_free_key2;
+
+	p = simple_get_bytes(p, end, &ctx->owf_alg, sizeof(ctx->owf_alg));
+	if (IS_ERR(p))
+		goto out_err_free_key2;
 
 	if (p != end)
-		goto out_err_free_s_key;
+		goto out_err_free_key2;
 
 	ctx_id->internal_ctx_id = ctx;
 
 	dprintk("Succesfully imported new spkm context.\n");
 	return 0;
 
+out_err_free_key2:
+	crypto_free_tfm(ctx->derived_integ_key);
+out_err_free_key1:
+	crypto_free_tfm(ctx->derived_conf_key);
 out_err_free_s_key:
 	kfree(ctx->share_key.data);
 out_err_free_mech:
@@ -200,7 +207,7 @@
 out_err_free_ctx:
 	kfree(ctx);
 out_err:
-	return GSS_S_FAILURE;
+	return PTR_ERR(p);
 }
 
 static void
diff -Nru a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c
--- a/net/sunrpc/auth_gss/svcauth_gss.c	2005-03-11 12:51:46 -08:00
+++ b/net/sunrpc/auth_gss/svcauth_gss.c	2005-03-11 12:51:46 -08:00
@@ -381,7 +381,6 @@
 	else {
 		int N, i;
 		struct gss_api_mech *gm;
-		struct xdr_netobj tmp_buf;
 
 		/* gid */
 		if (get_int(&mesg, &rsci.cred.cr_gid))
@@ -420,9 +419,7 @@
 			gss_mech_put(gm);
 			goto out;
 		}
-		tmp_buf.len = len;
-		tmp_buf.data = buf;
-		if (gss_import_sec_context(&tmp_buf, gm, &rsci.mechctx)) {
+		if (gss_import_sec_context(buf, len, gm, &rsci.mechctx)) {
 			gss_mech_put(gm);
 			goto out;
 		}
@@ -730,6 +727,19 @@
 	struct rsc			*rsci;
 };
 
+static int
+svcauth_gss_set_client(struct svc_rqst *rqstp)
+{
+	struct gss_svc_data *svcdata = rqstp->rq_auth_data;
+	struct rsc *rsci = svcdata->rsci;
+	struct rpc_gss_wire_cred *gc = &svcdata->clcred;
+
+	rqstp->rq_client = find_gss_auth_domain(rsci->mechctx, gc->gc_svc);
+	if (rqstp->rq_client == NULL)
+		return SVC_DENIED;
+	return SVC_OK;
+}
+
 /*
  * Accept an rpcsec packet.
  * If context establishment, punt to user space
@@ -893,11 +903,6 @@
 		svc_putu32(resv, rpc_success);
 		goto complete;
 	case RPC_GSS_PROC_DATA:
-		*authp = rpc_autherr_badcred;
-		rqstp->rq_client =
-			find_gss_auth_domain(rsci->mechctx, gc->gc_svc);
-		if (rqstp->rq_client == NULL)
-			goto auth_err;
 		*authp = rpcsec_gsserr_ctxproblem;
 		if (gss_write_verf(rqstp, rsci->mechctx, gc->gc_seq))
 			goto auth_err;
@@ -911,8 +916,6 @@
 			if (unwrap_integ_data(&rqstp->rq_arg,
 					gc->gc_seq, rsci->mechctx))
 				goto auth_err;
-			svcdata->rsci = rsci;
-			cache_get(&rsci->h);
 			/* placeholders for length and seq. number: */
 			svcdata->body_start = resv->iov_base + resv->iov_len;
 			svc_putu32(resv, 0);
@@ -923,6 +926,8 @@
 		default:
 			goto auth_err;
 		}
+		svcdata->rsci = rsci;
+		cache_get(&rsci->h);
 		ret = SVC_OK;
 		goto out;
 	}
@@ -1052,6 +1057,7 @@
 	.accept		= svcauth_gss_accept,
 	.release	= svcauth_gss_release,
 	.domain_release = svcauth_gss_domain_release,
+	.set_client	= svcauth_gss_set_client,
 };
 
 int
diff -Nru a/net/sunrpc/auth_null.c b/net/sunrpc/auth_null.c
--- a/net/sunrpc/auth_null.c	2005-03-11 12:51:52 -08:00
+++ b/net/sunrpc/auth_null.c	2005-03-11 12:51:52 -08:00
@@ -18,48 +18,29 @@
 # define RPCDBG_FACILITY	RPCDBG_AUTH
 #endif
 
-static struct rpc_credops	null_credops;
+static struct rpc_auth null_auth;
+static struct rpc_cred null_cred;
 
 static struct rpc_auth *
 nul_create(struct rpc_clnt *clnt, rpc_authflavor_t flavor)
 {
-	struct rpc_auth	*auth;
-
-	dprintk("RPC: creating NULL authenticator for client %p\n", clnt);
-	if (!(auth = (struct rpc_auth *) kmalloc(sizeof(*auth),GFP_KERNEL)))
-		return NULL;
-	auth->au_cslack = 4;
-	auth->au_rslack = 2;
-	auth->au_ops = &authnull_ops;
-	auth->au_expire = 1800 * HZ;
-	rpcauth_init_credcache(auth);
-
-	return (struct rpc_auth *) auth;
+	atomic_inc(&null_auth.au_count);
+	return &null_auth;
 }
 
 static void
 nul_destroy(struct rpc_auth *auth)
 {
-	dprintk("RPC: destroying NULL authenticator %p\n", auth);
-	rpcauth_free_credcache(auth);
+	atomic_dec(&null_auth.au_count);
 }
 
 /*
- * Create NULL creds for current process
+ * Lookup NULL creds for current process
  */
 static struct rpc_cred *
-nul_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags)
+nul_lookup_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags)
 {
-	struct rpc_cred	*cred;
-
-	if (!(cred = (struct rpc_cred *) kmalloc(sizeof(*cred),GFP_KERNEL)))
-		return NULL;
-	atomic_set(&cred->cr_count, 0);
-	cred->cr_flags = RPCAUTH_CRED_UPTODATE;
-	cred->cr_uid = acred->uid;
-	cred->cr_ops = &null_credops;
-
-	return cred;
+	return get_rpccred(&null_cred);
 }
 
 /*
@@ -68,7 +49,6 @@
 static void
 nul_destroy_cred(struct rpc_cred *cred)
 {
-	kfree(cred);
 }
 
 /*
@@ -84,7 +64,7 @@
  * Marshal credential.
  */
 static u32 *
-nul_marshal(struct rpc_task *task, u32 *p, int ruid)
+nul_marshal(struct rpc_task *task, u32 *p)
 {
 	*p++ = htonl(RPC_AUTH_NULL);
 	*p++ = 0;
@@ -125,7 +105,7 @@
 	return p;
 }
 
-struct rpc_authops	authnull_ops = {
+struct rpc_authops authnull_ops = {
 	.owner		= THIS_MODULE,
 	.au_flavor	= RPC_AUTH_NULL,
 #ifdef RPC_DEBUG
@@ -133,14 +113,32 @@
 #endif
 	.create		= nul_create,
 	.destroy	= nul_destroy,
-	.crcreate	= nul_create_cred,
+	.lookup_cred	= nul_lookup_cred,
+};
+
+static
+struct rpc_auth null_auth = {
+	.au_cslack	= 4,
+	.au_rslack	= 2,
+	.au_ops		= &authnull_ops,
 };
 
 static
 struct rpc_credops	null_credops = {
+	.cr_name	= "AUTH_NULL",
 	.crdestroy	= nul_destroy_cred,
 	.crmatch	= nul_match,
 	.crmarshal	= nul_marshal,
 	.crrefresh	= nul_refresh,
 	.crvalidate	= nul_validate,
+};
+
+static
+struct rpc_cred null_cred = {
+	.cr_ops		= &null_credops,
+	.cr_count	= ATOMIC_INIT(1),
+	.cr_flags	= RPCAUTH_CRED_UPTODATE,
+#ifdef RPC_DEBUG
+	.cr_magic	= RPCAUTH_CRED_MAGIC,
+#endif
 };
diff -Nru a/net/sunrpc/auth_unix.c b/net/sunrpc/auth_unix.c
--- a/net/sunrpc/auth_unix.c	2005-03-11 12:51:47 -08:00
+++ b/net/sunrpc/auth_unix.c	2005-03-11 12:51:47 -08:00
@@ -19,8 +19,6 @@
 struct unx_cred {
 	struct rpc_cred		uc_base;
 	gid_t			uc_gid;
-	uid_t			uc_puid;		/* process uid */
-	gid_t			uc_pgid;		/* process gid */
 	gid_t			uc_gids[NFS_NGROUPS];
 };
 #define uc_uid			uc_base.cr_uid
@@ -36,24 +34,17 @@
 # define RPCDBG_FACILITY	RPCDBG_AUTH
 #endif
 
+static struct rpc_auth		unix_auth;
+static struct rpc_cred_cache	unix_cred_cache;
 static struct rpc_credops	unix_credops;
 
 static struct rpc_auth *
 unx_create(struct rpc_clnt *clnt, rpc_authflavor_t flavor)
 {
-	struct rpc_auth	*auth;
-
 	dprintk("RPC: creating UNIX authenticator for client %p\n", clnt);
-	if (!(auth = (struct rpc_auth *) kmalloc(sizeof(*auth), GFP_KERNEL)))
-		return NULL;
-	auth->au_cslack = UNX_WRITESLACK;
-	auth->au_rslack = 2;	/* assume AUTH_NULL verf */
-	auth->au_expire = UNX_CRED_EXPIRE;
-	auth->au_ops = &authunix_ops;
-
-	rpcauth_init_credcache(auth);
-
-	return auth;
+	if (atomic_inc_return(&unix_auth.au_count) == 0)
+		unix_cred_cache.nextgc = jiffies + (unix_cred_cache.expire >> 1);
+	return &unix_auth;
 }
 
 static void
@@ -63,6 +54,15 @@
 	rpcauth_free_credcache(auth);
 }
 
+/*
+ * Lookup AUTH_UNIX creds for current process
+ */
+static struct rpc_cred *
+unx_lookup_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags)
+{
+	return rpcauth_lookup_credcache(auth, acred, flags);
+}
+
 static struct rpc_cred *
 unx_create_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags)
 {
@@ -73,13 +73,13 @@
 				acred->uid, acred->gid);
 
 	if (!(cred = (struct unx_cred *) kmalloc(sizeof(*cred), GFP_KERNEL)))
-		return NULL;
+		return ERR_PTR(-ENOMEM);
 
-	atomic_set(&cred->uc_count, 0);
+	atomic_set(&cred->uc_count, 1);
 	cred->uc_flags = RPCAUTH_CRED_UPTODATE;
 	if (flags & RPC_TASK_ROOTCREDS) {
-		cred->uc_uid = cred->uc_puid = 0;
-		cred->uc_gid = cred->uc_pgid = 0;
+		cred->uc_uid = 0;
+		cred->uc_gid = 0;
 		cred->uc_gids[0] = NOGROUP;
 	} else {
 		int groups = acred->group_info->ngroups;
@@ -88,8 +88,6 @@
 
 		cred->uc_uid = acred->uid;
 		cred->uc_gid = acred->gid;
-		cred->uc_puid = current->uid;
-		cred->uc_pgid = current->gid;
 		for (i = 0; i < groups; i++)
 			cred->uc_gids[i] = GROUP_AT(acred->group_info, i);
 		if (i < NFS_NGROUPS)
@@ -121,9 +119,7 @@
 		int groups;
 
 		if (cred->uc_uid != acred->uid
-		 || cred->uc_gid != acred->gid
-		 || cred->uc_puid != current->uid
-		 || cred->uc_pgid != current->gid)
+		 || cred->uc_gid != acred->gid)
 			return 0;
 
 		groups = acred->group_info->ngroups;
@@ -134,8 +130,8 @@
 				return 0;
 		return 1;
 	}
-	return (cred->uc_uid == 0 && cred->uc_puid == 0
-	     && cred->uc_gid == 0 && cred->uc_pgid == 0
+	return (cred->uc_uid == 0
+	     && cred->uc_gid == 0
 	     && cred->uc_gids[0] == (gid_t) NOGROUP);
 }
 
@@ -144,7 +140,7 @@
  * Maybe we should keep a cached credential for performance reasons.
  */
 static u32 *
-unx_marshal(struct rpc_task *task, u32 *p, int ruid)
+unx_marshal(struct rpc_task *task, u32 *p)
 {
 	struct rpc_clnt	*clnt = task->tk_client;
 	struct unx_cred	*cred = (struct unx_cred *) task->tk_msg.rpc_cred;
@@ -160,14 +156,8 @@
 	 */
 	p = xdr_encode_array(p, clnt->cl_nodename, clnt->cl_nodelen);
 
-	/* Note: we don't use real uid if it involves raising privilege */
-	if (ruid && cred->uc_puid != 0 && cred->uc_pgid != 0) {
-		*p++ = htonl((u32) cred->uc_puid);
-		*p++ = htonl((u32) cred->uc_pgid);
-	} else {
-		*p++ = htonl((u32) cred->uc_uid);
-		*p++ = htonl((u32) cred->uc_gid);
-	}
+	*p++ = htonl((u32) cred->uc_uid);
+	*p++ = htonl((u32) cred->uc_gid);
 	hold = p++;
 	for (i = 0; i < 16 && cred->uc_gids[i] != (gid_t) NOGROUP; i++)
 		*p++ = htonl((u32) cred->uc_gids[i]);
@@ -223,11 +213,27 @@
 #endif
 	.create		= unx_create,
 	.destroy	= unx_destroy,
+	.lookup_cred	= unx_lookup_cred,
 	.crcreate	= unx_create_cred,
 };
 
 static
+struct rpc_cred_cache	unix_cred_cache = {
+	.expire		= UNX_CRED_EXPIRE,
+};
+
+static
+struct rpc_auth		unix_auth = {
+	.au_cslack	= UNX_WRITESLACK,
+	.au_rslack	= 2,			/* assume AUTH_NULL verf */
+	.au_ops		= &authunix_ops,
+	.au_count	= ATOMIC_INIT(0),
+	.au_credcache	= &unix_cred_cache,
+};
+
+static
 struct rpc_credops	unix_credops = {
+	.cr_name	= "AUTH_UNIX",
 	.crdestroy	= unx_destroy_cred,
 	.crmatch	= unx_match,
 	.crmarshal	= unx_marshal,
diff -Nru a/net/sunrpc/cache.c b/net/sunrpc/cache.c
--- a/net/sunrpc/cache.c	2005-03-11 12:51:47 -08:00
+++ b/net/sunrpc/cache.c	2005-03-11 12:51:47 -08:00
@@ -321,12 +321,10 @@
 			if (test_and_clear_bit(CACHE_PENDING, &ch->flags))
 				queue_loose(current_detail, ch);
 
-			if (!atomic_read(&ch->refcnt))
+			if (atomic_read(&ch->refcnt) == 1)
 				break;
 		}
 		if (ch) {
-			cache_get(ch);
-			clear_bit(CACHE_HASHED, &ch->flags);
 			*cp = ch->next;
 			ch->next = NULL;
 			current_detail->entries--;
diff -Nru a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
--- a/net/sunrpc/clnt.c	2005-03-11 12:51:42 -08:00
+++ b/net/sunrpc/clnt.c	2005-03-11 12:51:42 -08:00
@@ -23,6 +23,7 @@
 
 #include <asm/system.h>
 
+#include <linux/module.h>
 #include <linux/types.h>
 #include <linux/mm.h>
 #include <linux/slab.h>
@@ -406,12 +407,11 @@
 	rpc_call_setup(task, msg, 0);
 
 	/* Set up the call info struct and execute the task */
-	if (task->tk_status == 0)
-		status = rpc_execute(task);
-	else {
-		status = task->tk_status;
+	status = task->tk_status;
+	if (status == 0)
+		rpc_execute(task);
+	else
 		rpc_release_task(task);
-	}
 
 out:
 	rpc_clnt_sigunmask(clnt, &oldset);		
@@ -426,9 +426,9 @@
 	task->tk_msg   = *msg;
 	task->tk_flags |= flags;
 	/* Bind the user cred */
-	if (task->tk_msg.rpc_cred != NULL) {
+	if (task->tk_msg.rpc_cred != NULL)
 		rpcauth_holdcred(task);
-	} else
+	else
 		rpcauth_bindcred(task);
 
 	if (task->tk_status == 0)
@@ -453,6 +453,20 @@
 }
 
 /*
+ * Return size of largest payload RPC client can support, in bytes
+ *
+ * For stream transports, this is one RPC record fragment (see RFC
+ * 1831), as we don't support multi-record requests yet.  For datagram
+ * transports, this is the size of an IP packet minus the IP, UDP, and
+ * RPC header sizes.
+ */
+size_t rpc_max_payload(struct rpc_clnt *clnt)
+{
+	return clnt->cl_xprt->max_payload;
+}
+EXPORT_SYMBOL(rpc_max_payload);
+
+/*
  * Restart an (async) RPC call. Usually called from within the
  * exit handler.
  */
@@ -869,21 +883,6 @@
 		if (task->tk_action == NULL)
 			return;
 		goto out_retry;
-	}
-
-	/*
-	 * The following is an NFS-specific hack to cater for setuid
-	 * processes whose uid is mapped to nobody on the server.
-	 */
-	if (task->tk_client->cl_droppriv && 
-            (ntohl(*p) == NFSERR_ACCES || ntohl(*p) == NFSERR_PERM)) {
-		if (RPC_IS_SETUID(task) && task->tk_suid_retry) {
-			dprintk("RPC: %4d retry squashed uid\n", task->tk_pid);
-			task->tk_flags ^= RPC_CALL_REALUID;
-			task->tk_action = call_bind;
-			task->tk_suid_retry--;
-			goto out_retry;
-		}
 	}
 
 	task->tk_action = NULL;
diff -Nru a/net/sunrpc/pmap_clnt.c b/net/sunrpc/pmap_clnt.c
--- a/net/sunrpc/pmap_clnt.c	2005-03-11 12:51:46 -08:00
+++ b/net/sunrpc/pmap_clnt.c	2005-03-11 12:51:46 -08:00
@@ -3,9 +3,6 @@
  *
  * Portmapper client.
  *
- * FIXME: In a secure environment, we may want to use an authentication
- * flavor other than AUTH_NULL.
- *
  * Copyright (C) 1996, Olaf Kirch <okir@monad.swb.de>
  */
 
@@ -212,7 +209,7 @@
 	/* printk("pmap: create clnt\n"); */
 	clnt = rpc_create_client(xprt, hostname,
 				&pmap_program, RPC_PMAP_VERSION,
-				RPC_AUTH_NULL);
+				RPC_AUTH_UNIX);
 	if (IS_ERR(clnt)) {
 		xprt_destroy(xprt);
 	} else {
diff -Nru a/net/sunrpc/sched.c b/net/sunrpc/sched.c
--- a/net/sunrpc/sched.c	2005-03-11 12:51:46 -08:00
+++ b/net/sunrpc/sched.c	2005-03-11 12:51:46 -08:00
@@ -132,9 +132,11 @@
  * Delete any timer for the current task. Because we use del_timer_sync(),
  * this function should never be called while holding queue->lock.
  */
-static inline void
+static void
 rpc_delete_timer(struct rpc_task *task)
 {
+	if (RPC_IS_QUEUED(task))
+		return;
 	if (test_and_clear_bit(RPC_TASK_HAS_TIMER, &task->tk_runstate)) {
 		del_singleshot_timer_sync(&task->tk_timer);
 		dprintk("RPC: %4d deleting timer\n", task->tk_pid);
@@ -747,13 +749,10 @@
 	task->tk_client = clnt;
 	task->tk_flags  = flags;
 	task->tk_exit   = callback;
-	if (current->uid != current->fsuid || current->gid != current->fsgid)
-		task->tk_flags |= RPC_TASK_SETUID;
 
 	/* Initialize retry counters */
 	task->tk_garb_retry = 2;
 	task->tk_cred_retry = 2;
-	task->tk_suid_retry = 1;
 
 	task->tk_priority = RPC_PRIORITY_NORMAL;
 	task->tk_cookie = (unsigned long)current;
diff -Nru a/net/sunrpc/sunrpc_syms.c b/net/sunrpc/sunrpc_syms.c
--- a/net/sunrpc/sunrpc_syms.c	2005-03-11 12:51:51 -08:00
+++ b/net/sunrpc/sunrpc_syms.c	2005-03-11 12:51:51 -08:00
@@ -90,6 +90,7 @@
 EXPORT_SYMBOL(svc_auth_register);
 EXPORT_SYMBOL(auth_domain_lookup);
 EXPORT_SYMBOL(svc_authenticate);
+EXPORT_SYMBOL(svc_set_client);
 
 /* RPC statistics */
 #ifdef CONFIG_PROC_FS
diff -Nru a/net/sunrpc/svc.c b/net/sunrpc/svc.c
--- a/net/sunrpc/svc.c	2005-03-11 12:51:52 -08:00
+++ b/net/sunrpc/svc.c	2005-03-11 12:51:52 -08:00
@@ -264,6 +264,7 @@
 	u32			dir, prog, vers, proc,
 				auth_stat, rpc_stat;
 	int			auth_res;
+	u32			*accept_statp;
 
 	rpc_stat = rpc_success;
 
@@ -299,6 +300,9 @@
 	if (vers != 2)		/* RPC version number */
 		goto err_bad_rpc;
 
+	/* Save position in case we later decide to reject: */
+	accept_statp = resv->iov_base + resv->iov_len;
+
 	svc_putu32(resv, xdr_zero);		/* ACCEPT */
 
 	rqstp->rq_prog = prog = ntohl(svc_getu32(argv));	/* program number */
@@ -311,10 +315,12 @@
 	 * We do this before anything else in order to get a decent
 	 * auth verifier.
 	 */
-	if (progp->pg_authenticate != NULL)
-		auth_res = progp->pg_authenticate(rqstp, &auth_stat);
-	else
-		auth_res = svc_authenticate(rqstp, &auth_stat);
+	auth_res = svc_authenticate(rqstp, &auth_stat);
+	/* Also give the program a chance to reject this call: */
+	if (auth_res == SVC_OK) {
+		auth_stat = rpc_autherr_badcred;
+		auth_res = progp->pg_authenticate(rqstp);
+	}
 	switch (auth_res) {
 	case SVC_OK:
 		break;
@@ -437,7 +443,8 @@
 err_bad_auth:
 	dprintk("svc: authentication failed (%d)\n", ntohl(auth_stat));
 	serv->sv_stats->rpcbadauth++;
-	resv->iov_len -= 4;
+	/* Restore write pointer to location of accept status: */
+	xdr_ressize_check(rqstp, accept_statp);
 	svc_putu32(resv, xdr_one);	/* REJECT */
 	svc_putu32(resv, xdr_one);	/* AUTH_ERROR */
 	svc_putu32(resv, auth_stat);	/* status */
diff -Nru a/net/sunrpc/svcauth.c b/net/sunrpc/svcauth.c
--- a/net/sunrpc/svcauth.c	2005-03-11 12:51:48 -08:00
+++ b/net/sunrpc/svcauth.c	2005-03-11 12:51:48 -08:00
@@ -59,6 +59,11 @@
 	return aops->accept(rqstp, authp);
 }
 
+int svc_set_client(struct svc_rqst *rqstp)
+{
+	return rqstp->rq_authop->set_client(rqstp);
+}
+
 /* A request, which was authenticated, has now executed.
  * Time to finalise the the credentials and verifier
  * and release and resources
@@ -173,12 +178,12 @@
 		tmp = container_of(*hp, struct auth_domain, h);
 		if (!auth_domain_match(tmp, item))
 			continue;
-		cache_get(&tmp->h);
-		if (!set)
+		if (!set) {
+			cache_get(&tmp->h);
 			goto out_noset;
+		}
 		*hp = tmp->h.next;
 		tmp->h.next = NULL;
-		clear_bit(CACHE_HASHED, &tmp->h.flags);
 		auth_domain_drop(&tmp->h, &auth_domain_cache);
 		goto out_set;
 	}
@@ -187,9 +192,9 @@
 		goto out_nada;
 	auth_domain_cache.entries++;
 out_set:
-	set_bit(CACHE_HASHED, &item->h.flags);
 	item->h.next = *head;
 	*head = &item->h;
+	cache_get(&item->h);
 	write_unlock(&auth_domain_cache.hash_lock);
 	cache_fresh(&auth_domain_cache, &item->h, item->h.expiry_time);
 	cache_get(&item->h);
diff -Nru a/net/sunrpc/svcauth_unix.c b/net/sunrpc/svcauth_unix.c
--- a/net/sunrpc/svcauth_unix.c	2005-03-11 12:51:47 -08:00
+++ b/net/sunrpc/svcauth_unix.c	2005-03-11 12:51:47 -08:00
@@ -368,7 +368,6 @@
 	struct kvec	*argv = &rqstp->rq_arg.head[0];
 	struct kvec	*resv = &rqstp->rq_res.head[0];
 	struct svc_cred	*cred = &rqstp->rq_cred;
-	int		rv=0;
 
 	cred->cr_group_info = NULL;
 	rqstp->rq_client = NULL;
@@ -394,19 +393,11 @@
 	if (cred->cr_group_info == NULL)
 		return SVC_DROP; /* kmalloc failure - client must retry */
 
-	rv = svcauth_unix_set_client(rqstp);
-	if (rv == SVC_DENIED)
-		goto badcred;
-
 	/* Put NULL verifier */
 	svc_putu32(resv, RPC_AUTH_NULL);
 	svc_putu32(resv, 0);
 
-	return rv;
-
-badcred:
-	*authp = rpc_autherr_badcred;
-	return SVC_DENIED;
+	return SVC_OK;
 }
 
 static int
@@ -429,6 +420,7 @@
 	.flavour	= RPC_AUTH_NULL,
 	.accept 	= svcauth_null_accept,
 	.release	= svcauth_null_release,
+	.set_client	= svcauth_unix_set_client,
 };
 
 
@@ -440,7 +432,6 @@
 	struct svc_cred	*cred = &rqstp->rq_cred;
 	u32		slen, i;
 	int		len   = argv->iov_len;
-	int		rv=0;
 
 	cred->cr_group_info = NULL;
 	rqstp->rq_client = NULL;
@@ -472,15 +463,11 @@
 		return SVC_DENIED;
 	}
 
-	rv = svcauth_unix_set_client(rqstp);
-	if (rv == SVC_DENIED)
-		goto badcred;
-
 	/* Put NULL verifier */
 	svc_putu32(resv, RPC_AUTH_NULL);
 	svc_putu32(resv, 0);
 
-	return rv;
+	return SVC_OK;
 
 badcred:
 	*authp = rpc_autherr_badcred;
@@ -510,5 +497,6 @@
 	.accept 	= svcauth_unix_accept,
 	.release	= svcauth_unix_release,
 	.domain_release	= svcauth_unix_domain_release,
+	.set_client	= svcauth_unix_set_client,
 };
 
diff -Nru a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c
--- a/net/sunrpc/xprt.c	2005-03-11 12:51:47 -08:00
+++ b/net/sunrpc/xprt.c	2005-03-11 12:51:47 -08:00
@@ -1460,8 +1460,11 @@
 	if (xprt->stream) {
 		xprt->cwnd = RPC_MAXCWND(xprt);
 		xprt->nocong = 1;
-	} else
+		xprt->max_payload = (1U << 31) - 1;
+	} else {
 		xprt->cwnd = RPC_INITCWND;
+		xprt->max_payload = (1U << 16) - (MAX_HEADER << 3);
+	}
 	spin_lock_init(&xprt->sock_lock);
 	spin_lock_init(&xprt->xprt_lock);
 	init_waitqueue_head(&xprt->cong_wait);
diff -Nru a/net/unix/af_unix.c b/net/unix/af_unix.c
--- a/net/unix/af_unix.c	2005-03-11 12:51:47 -08:00
+++ b/net/unix/af_unix.c	2005-03-11 12:51:47 -08:00
@@ -861,8 +861,8 @@
 			goto out;
 		alen = err;
 
-		if (sock->passcred && !unix_sk(sk)->addr &&
-		    (err = unix_autobind(sock)) != 0)
+		if (test_bit(SOCK_PASSCRED, &sock->flags) &&
+		    !unix_sk(sk)->addr && (err = unix_autobind(sock)) != 0)
 			goto out;
 
 		other=unix_find_other(sunaddr, alen, sock->type, hash, &err);
@@ -952,7 +952,8 @@
 		goto out;
 	addr_len = err;
 
-	if (sock->passcred && !u->addr && (err = unix_autobind(sock)) != 0)
+	if (test_bit(SOCK_PASSCRED, &sock->flags)
+		&& !u->addr && (err = unix_autobind(sock)) != 0)
 		goto out;
 
 	timeo = sock_sndtimeo(sk, flags & O_NONBLOCK);
@@ -1286,7 +1287,8 @@
 			goto out;
 	}
 
-	if (sock->passcred && !u->addr && (err = unix_autobind(sock)) != 0)
+	if (test_bit(SOCK_PASSCRED, &sock->flags)
+		&& !u->addr && (err = unix_autobind(sock)) != 0)
 		goto out;
 
 	err = -EMSGSIZE;
diff -Nru a/net/x25/af_x25.c b/net/x25/af_x25.c
--- a/net/x25/af_x25.c	2005-03-11 12:51:51 -08:00
+++ b/net/x25/af_x25.c	2005-03-11 12:51:51 -08:00
@@ -444,33 +444,23 @@
 
 static struct sock *x25_alloc_socket(void)
 {
-	struct x25_opt *x25;
-	struct sock *sk = sk_alloc(AF_X25, GFP_ATOMIC, 1, NULL);
+	struct x25_sock *x25;
+	struct sock *sk = sk_alloc(AF_X25, GFP_ATOMIC,
+				   sizeof(struct x25_sock), NULL);
 
 	if (!sk)
 		goto out;
 
-	x25 = sk->sk_protinfo = kmalloc(sizeof(*x25), GFP_ATOMIC);
-	if (!x25)
-		goto frees;
-
-	memset(x25, 0, sizeof(*x25));
-
-	x25->sk = sk;
-
 	sock_init_data(NULL, sk);
 	sk_set_owner(sk, THIS_MODULE);
 
+	x25 = x25_sk(sk);
 	skb_queue_head_init(&x25->ack_queue);
 	skb_queue_head_init(&x25->fragment_queue);
 	skb_queue_head_init(&x25->interrupt_in_queue);
 	skb_queue_head_init(&x25->interrupt_out_queue);
 out:
 	return sk;
-frees:
-	sk_free(sk);
-	sk = NULL;
-	goto out;
 }
 
 void x25_init_timers(struct sock *sk);
@@ -478,7 +468,7 @@
 static int x25_create(struct socket *sock, int protocol)
 {
 	struct sock *sk;
-	struct x25_opt *x25;
+	struct x25_sock *x25;
 	int rc = -ESOCKTNOSUPPORT;
 
 	if (sock->type != SOCK_SEQPACKET || protocol)
@@ -519,7 +509,7 @@
 static struct sock *x25_make_new(struct sock *osk)
 {
 	struct sock *sk = NULL;
-	struct x25_opt *x25, *ox25;
+	struct x25_sock *x25, *ox25;
 
 	if (osk->sk_type != SOCK_SEQPACKET)
 		goto out;
@@ -557,7 +547,7 @@
 static int x25_release(struct socket *sock)
 {
 	struct sock *sk = sock->sk;
-	struct x25_opt *x25;
+	struct x25_sock *x25;
 
 	if (!sk)
 		goto out;
@@ -644,7 +634,7 @@
 		       int addr_len, int flags)
 {
 	struct sock *sk = sock->sk;
-	struct x25_opt *x25 = x25_sk(sk);
+	struct x25_sock *x25 = x25_sk(sk);
 	struct sockaddr_x25 *addr = (struct sockaddr_x25 *)uaddr;
 	struct x25_route *rt;
 	int rc = 0;
@@ -802,7 +792,7 @@
 {
 	struct sockaddr_x25 *sx25 = (struct sockaddr_x25 *)uaddr;
 	struct sock *sk = sock->sk;
-	struct x25_opt *x25 = x25_sk(sk);
+	struct x25_sock *x25 = x25_sk(sk);
 
 	if (peer) {
 		if (sk->sk_state != TCP_ESTABLISHED)
@@ -822,7 +812,7 @@
 {
 	struct sock *sk;
 	struct sock *make;
-	struct x25_opt *makex25;
+	struct x25_sock *makex25;
 	struct x25_address source_addr, dest_addr;
 	struct x25_facilities facilities;
 	struct x25_calluserdata calluserdata;
@@ -935,7 +925,7 @@
 		       struct msghdr *msg, size_t len)
 {
 	struct sock *sk = sock->sk;
-	struct x25_opt *x25 = x25_sk(sk);
+	struct x25_sock *x25 = x25_sk(sk);
 	struct sockaddr_x25 *usx25 = (struct sockaddr_x25 *)msg->msg_name;
 	struct sockaddr_x25 sx25;
 	struct sk_buff *skb;
@@ -1112,7 +1102,7 @@
 		       int flags)
 {
 	struct sock *sk = sock->sk;
-	struct x25_opt *x25 = x25_sk(sk);
+	struct x25_sock *x25 = x25_sk(sk);
 	struct sockaddr_x25 *sx25 = (struct sockaddr_x25 *)msg->msg_name;
 	size_t copied;
 	int qbit;
@@ -1201,7 +1191,7 @@
 static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
 {
 	struct sock *sk = sock->sk;
-	struct x25_opt *x25 = x25_sk(sk);
+	struct x25_sock *x25 = x25_sk(sk);
 	void __user *argp = (void __user *)arg;
 	int rc;
 
diff -Nru a/net/x25/x25_facilities.c b/net/x25/x25_facilities.c
--- a/net/x25/x25_facilities.c	2005-03-11 12:51:47 -08:00
+++ b/net/x25/x25_facilities.c	2005-03-11 12:51:47 -08:00
@@ -158,7 +158,7 @@
 int x25_negotiate_facilities(struct sk_buff *skb, struct sock *sk,
 			     struct x25_facilities *new)
 {
-	struct x25_opt *x25 = x25_sk(sk);
+	struct x25_sock *x25 = x25_sk(sk);
 	struct x25_facilities *ours = &x25->facilities;
 	struct x25_facilities theirs;
 	int len;
diff -Nru a/net/x25/x25_in.c b/net/x25/x25_in.c
--- a/net/x25/x25_in.c	2005-03-11 12:51:51 -08:00
+++ b/net/x25/x25_in.c	2005-03-11 12:51:51 -08:00
@@ -34,7 +34,7 @@
 static int x25_queue_rx_frame(struct sock *sk, struct sk_buff *skb, int more)
 {
 	struct sk_buff *skbo, *skbn = skb;
-	struct x25_opt *x25 = x25_sk(sk);
+	struct x25_sock *x25 = x25_sk(sk);
 
 	if (more) {
 		x25->fraglen += skb->len;
@@ -89,7 +89,7 @@
 
 	switch (frametype) {
 		case X25_CALL_ACCEPTED: {
-			struct x25_opt *x25 = x25_sk(sk);
+			struct x25_sock *x25 = x25_sk(sk);
 
 			x25_stop_timer(sk);
 			x25->condition = 0x00;
@@ -165,7 +165,7 @@
 {
 	int queued = 0;
 	int modulus;
-	struct x25_opt *x25 = x25_sk(sk);
+	struct x25_sock *x25 = x25_sk(sk);
 	
 	modulus = (x25->neighbour->extended) ? X25_EMODULUS : X25_SMODULUS;
 
@@ -295,7 +295,7 @@
 		case X25_RESET_REQUEST:
 			x25_write_internal(sk, X25_RESET_CONFIRMATION);
 		case X25_RESET_CONFIRMATION: {
-			struct x25_opt *x25 = x25_sk(sk);
+			struct x25_sock *x25 = x25_sk(sk);
 
 			x25_stop_timer(sk);
 			x25->condition = 0x00;
@@ -322,7 +322,7 @@
 /* Higher level upcall for a LAPB frame */
 int x25_process_rx_frame(struct sock *sk, struct sk_buff *skb)
 {
-	struct x25_opt *x25 = x25_sk(sk);
+	struct x25_sock *x25 = x25_sk(sk);
 	int queued = 0, frametype, ns, nr, q, d, m;
 
 	if (x25->state == X25_STATE_0)
diff -Nru a/net/x25/x25_out.c b/net/x25/x25_out.c
--- a/net/x25/x25_out.c	2005-03-11 12:51:41 -08:00
+++ b/net/x25/x25_out.c	2005-03-11 12:51:41 -08:00
@@ -54,7 +54,7 @@
 	unsigned char header[X25_EXT_MIN_LEN];
 	int err, frontlen, len;
 	int sent=0, noblock = X25_SKB_CB(skb)->flags & MSG_DONTWAIT;
-	struct x25_opt *x25 = x25_sk(sk);
+	struct x25_sock *x25 = x25_sk(sk);
 	int header_len = x25->neighbour->extended ? X25_EXT_MIN_LEN :
 						    X25_STD_MIN_LEN;
 	int max_len = x25_pacsize_to_bytes(x25->facilities.pacsize_out);
@@ -116,7 +116,7 @@
  */
 static void x25_send_iframe(struct sock *sk, struct sk_buff *skb)
 {
-	struct x25_opt *x25 = x25_sk(sk);
+	struct x25_sock *x25 = x25_sk(sk);
 
 	if (!skb)
 		return;
@@ -139,7 +139,7 @@
 	struct sk_buff *skb, *skbn;
 	unsigned short start, end;
 	int modulus;
-	struct x25_opt *x25 = x25_sk(sk);
+	struct x25_sock *x25 = x25_sk(sk);
 
 	if (x25->state != X25_STATE_3)
 		return;
@@ -212,7 +212,7 @@
 
 void x25_enquiry_response(struct sock *sk)
 {
-	struct x25_opt *x25 = x25_sk(sk);
+	struct x25_sock *x25 = x25_sk(sk);
 
 	if (x25->condition & X25_COND_OWN_RX_BUSY)
 		x25_write_internal(sk, X25_RNR);
diff -Nru a/net/x25/x25_proc.c b/net/x25/x25_proc.c
--- a/net/x25/x25_proc.c	2005-03-11 12:51:41 -08:00
+++ b/net/x25/x25_proc.c	2005-03-11 12:51:41 -08:00
@@ -134,7 +134,7 @@
 static int x25_seq_socket_show(struct seq_file *seq, void *v)
 {
 	struct sock *s;
-	struct x25_opt *x25;
+	struct x25_sock *x25;
 	struct net_device *dev;
 	const char *devname;
 
diff -Nru a/net/x25/x25_subr.c b/net/x25/x25_subr.c
--- a/net/x25/x25_subr.c	2005-03-11 12:51:42 -08:00
+++ b/net/x25/x25_subr.c	2005-03-11 12:51:42 -08:00
@@ -33,7 +33,7 @@
  */
 void x25_clear_queues(struct sock *sk)
 {
-	struct x25_opt *x25 = x25_sk(sk);
+	struct x25_sock *x25 = x25_sk(sk);
 
 	skb_queue_purge(&sk->sk_write_queue);
 	skb_queue_purge(&x25->ack_queue);
@@ -51,7 +51,7 @@
 void x25_frames_acked(struct sock *sk, unsigned short nr)
 {
 	struct sk_buff *skb;
-	struct x25_opt *x25 = x25_sk(sk);
+	struct x25_sock *x25 = x25_sk(sk);
 	int modulus = x25->neighbour->extended ? X25_EMODULUS : X25_SMODULUS;
 
 	/*
@@ -89,7 +89,7 @@
  */
 int x25_validate_nr(struct sock *sk, unsigned short nr)
 {
-	struct x25_opt *x25 = x25_sk(sk);
+	struct x25_sock *x25 = x25_sk(sk);
 	unsigned short vc = x25->va;
 	int modulus = x25->neighbour->extended ? X25_EMODULUS : X25_SMODULUS;
 
@@ -108,7 +108,7 @@
  */
 void x25_write_internal(struct sock *sk, int frametype)
 {
-	struct x25_opt *x25 = x25_sk(sk);
+	struct x25_sock *x25 = x25_sk(sk);
 	struct sk_buff *skb;
 	unsigned char  *dptr;
 	unsigned char  facilities[X25_MAX_FAC_LEN];
@@ -248,7 +248,7 @@
 int x25_decode(struct sock *sk, struct sk_buff *skb, int *ns, int *nr, int *q,
 	       int *d, int *m)
 {
-	struct x25_opt *x25 = x25_sk(sk);
+	struct x25_sock *x25 = x25_sk(sk);
 	unsigned char *frame = skb->data;
 
 	*ns = *nr = *q = *d = *m = 0;
@@ -315,7 +315,7 @@
 void x25_disconnect(struct sock *sk, int reason, unsigned char cause,
 		    unsigned char diagnostic)
 {
-	struct x25_opt *x25 = x25_sk(sk);
+	struct x25_sock *x25 = x25_sk(sk);
 
 	x25_clear_queues(sk);
 	x25_stop_timer(sk);
@@ -342,7 +342,7 @@
  */
 void x25_check_rbuf(struct sock *sk)
 {
-	struct x25_opt *x25 = x25_sk(sk);
+	struct x25_sock *x25 = x25_sk(sk);
 
 	if (atomic_read(&sk->sk_rmem_alloc) < (sk->sk_rcvbuf / 2) &&
 	    (x25->condition & X25_COND_OWN_RX_BUSY)) {
diff -Nru a/net/x25/x25_timer.c b/net/x25/x25_timer.c
--- a/net/x25/x25_timer.c	2005-03-11 12:51:41 -08:00
+++ b/net/x25/x25_timer.c	2005-03-11 12:51:41 -08:00
@@ -31,7 +31,7 @@
 
 void x25_init_timers(struct sock *sk)
 {
-	struct x25_opt *x25 = x25_sk(sk);
+	struct x25_sock *x25 = x25_sk(sk);
 
 	init_timer(&x25->timer);
 	x25->timer.data     = (unsigned long)sk;
@@ -54,28 +54,28 @@
 
 void x25_start_t2timer(struct sock *sk)
 {
-	struct x25_opt *x25 = x25_sk(sk);
+	struct x25_sock *x25 = x25_sk(sk);
 
 	mod_timer(&x25->timer, jiffies + x25->t2);
 }
 
 void x25_start_t21timer(struct sock *sk)
 {
-	struct x25_opt *x25 = x25_sk(sk);
+	struct x25_sock *x25 = x25_sk(sk);
 
 	mod_timer(&x25->timer, jiffies + x25->t21);
 }
 
 void x25_start_t22timer(struct sock *sk)
 {
-	struct x25_opt *x25 = x25_sk(sk);
+	struct x25_sock *x25 = x25_sk(sk);
 
 	mod_timer(&x25->timer, jiffies + x25->t22);
 }
 
 void x25_start_t23timer(struct sock *sk)
 {
-	struct x25_opt *x25 = x25_sk(sk);
+	struct x25_sock *x25 = x25_sk(sk);
 
 	mod_timer(&x25->timer, jiffies + x25->t23);
 }
@@ -87,7 +87,7 @@
 
 unsigned long x25_display_timer(struct sock *sk)
 {
-	struct x25_opt *x25 = x25_sk(sk);
+	struct x25_sock *x25 = x25_sk(sk);
 
 	if (!timer_pending(&x25->timer))
 		return 0;
@@ -138,7 +138,7 @@
  */
 static inline void x25_do_timer_expiry(struct sock * sk)
 {
-	struct x25_opt *x25 = x25_sk(sk);
+	struct x25_sock *x25 = x25_sk(sk);
 
 	switch (x25->state) {
 
diff -Nru a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
--- a/net/xfrm/xfrm_policy.c	2005-03-11 12:51:46 -08:00
+++ b/net/xfrm/xfrm_policy.c	2005-03-11 12:51:46 -08:00
@@ -1015,28 +1015,20 @@
 	if (!stale_bundle(dst))
 		return dst;
 
-	dst_release(dst);
 	return NULL;
 }
 
 static int stale_bundle(struct dst_entry *dst)
 {
-	struct dst_entry *child = dst;
-
-	while (child) {
-		if (child->obsolete > 0 ||
-		    (child->dev && !netif_running(child->dev)) ||
-		    (child->xfrm && child->xfrm->km.state != XFRM_STATE_VALID)) {
-			return 1;
-		}
-		child = child->child;
-	}
-
-	return 0;
+	return !xfrm_bundle_ok((struct xfrm_dst *)dst, NULL, AF_UNSPEC);
 }
 
 static void xfrm_dst_destroy(struct dst_entry *dst)
 {
+	struct xfrm_dst *xdst = (struct xfrm_dst *)dst;
+
+	dst_release(xdst->route);
+
 	if (!dst->xfrm)
 		return;
 	xfrm_state_put(dst->xfrm);
@@ -1120,6 +1112,94 @@
 	xfrm_prune_bundles(stale_bundle);
 	return 0;
 }
+
+void xfrm_init_pmtu(struct dst_entry *dst)
+{
+	do {
+		struct xfrm_dst *xdst = (struct xfrm_dst *)dst;
+		u32 pmtu, route_mtu_cached;
+
+		pmtu = dst_pmtu(dst->child);
+		xdst->child_mtu_cached = pmtu;
+
+		pmtu = xfrm_state_mtu(dst->xfrm, pmtu);
+
+		route_mtu_cached = dst_pmtu(xdst->route);
+		xdst->route_mtu_cached = route_mtu_cached;
+
+		if (pmtu > route_mtu_cached)
+			pmtu = route_mtu_cached;
+
+		dst->metrics[RTAX_MTU-1] = pmtu;
+	} while ((dst = dst->next));
+}
+
+EXPORT_SYMBOL(xfrm_init_pmtu);
+
+/* Check that the bundle accepts the flow and its components are
+ * still valid.
+ */
+
+int xfrm_bundle_ok(struct xfrm_dst *first, struct flowi *fl, int family)
+{
+	struct dst_entry *dst = &first->u.dst;
+	struct xfrm_dst *last;
+	u32 mtu;
+
+	if (!dst_check(dst->path, 0) ||
+	    (dst->dev && !netif_running(dst->dev)))
+		return 0;
+
+	last = NULL;
+
+	do {
+		struct xfrm_dst *xdst = (struct xfrm_dst *)dst;
+
+		if (fl && !xfrm_selector_match(&dst->xfrm->sel, fl, family))
+			return 0;
+		if (dst->xfrm->km.state != XFRM_STATE_VALID)
+			return 0;
+
+		mtu = dst_pmtu(dst->child);
+		if (xdst->child_mtu_cached != mtu) {
+			last = xdst;
+			xdst->child_mtu_cached = mtu;
+		}
+
+		if (!dst_check(xdst->route, 0))
+			return 0;
+		mtu = dst_pmtu(xdst->route);
+		if (xdst->route_mtu_cached != mtu) {
+			last = xdst;
+			xdst->route_mtu_cached = mtu;
+		}
+
+		dst = dst->child;
+	} while (dst->xfrm);
+
+	if (likely(!last))
+		return 1;
+
+	mtu = last->child_mtu_cached;
+	for (;;) {
+		dst = &last->u.dst;
+
+		mtu = xfrm_state_mtu(dst->xfrm, mtu);
+		if (mtu > last->route_mtu_cached)
+			mtu = last->route_mtu_cached;
+		dst->metrics[RTAX_MTU-1] = mtu;
+
+		if (last == first)
+			break;
+
+		last = last->u.next;
+		last->child_mtu_cached = mtu;
+	}
+
+	return 1;
+}
+
+EXPORT_SYMBOL(xfrm_bundle_ok);
 
 /* Well... that's _TASK_. We need to scan through transformation
  * list and figure out what mss tcp should generate in order to
diff -Nru a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
--- a/net/xfrm/xfrm_state.c	2005-03-11 12:51:47 -08:00
+++ b/net/xfrm/xfrm_state.c	2005-03-11 12:51:47 -08:00
@@ -609,7 +609,7 @@
 
 	for (i = 0; i < XFRM_DST_HSIZE; i++) {
 		list_for_each_entry(x, xfrm_state_bydst+i, bydst) {
-			if (x->km.seq == seq) {
+			if (x->km.seq == seq && x->km.state == XFRM_STATE_ACQ) {
 				xfrm_state_hold(x);
 				return x;
 			}
@@ -966,6 +966,36 @@
 }
 EXPORT_SYMBOL(xfrm_state_delete_tunnel);
 
+int xfrm_state_mtu(struct xfrm_state *x, int mtu)
+{
+	int res = mtu;
+
+	res -= x->props.header_len;
+
+	for (;;) {
+		int m = res;
+
+		if (m < 68)
+			return 68;
+
+		spin_lock_bh(&x->lock);
+		if (x->km.state == XFRM_STATE_VALID &&
+		    x->type && x->type->get_max_size)
+			m = x->type->get_max_size(x, m);
+		else
+			m += x->props.header_len;
+		spin_unlock_bh(&x->lock);
+
+		if (m <= mtu)
+			break;
+		res -= (m - mtu);
+	}
+
+	return res;
+}
+
+EXPORT_SYMBOL(xfrm_state_mtu);
+ 
 void __init xfrm_state_init(void)
 {
 	int i;
diff -Nru a/scripts/checkstack.pl b/scripts/checkstack.pl
--- a/scripts/checkstack.pl	2005-03-11 12:51:42 -08:00
+++ b/scripts/checkstack.pl	2005-03-11 12:51:42 -08:00
@@ -9,6 +9,7 @@
 #	Mips port by Juan Quintela <quintela@mandrakesoft.com>
 #	IA64 port via Andreas Dilger
 #	Arm port by Holger Schurig
+#	sh64 port by Paul Mundt
 #	Random bits by Matt Mackall <mpm@selenic.com>
 #	M68k port by Geert Uytterhoeven and Andreas Schwab
 #
@@ -64,6 +65,12 @@
 	} elsif ($arch =~ /^s390x?$/) {
 		#   11160:       a7 fb ff 60             aghi   %r15,-160
 		$re = qr/.*ag?hi.*\%r15,-(([0-9]{2}|[3-9])[0-9]{2})/o;
+	} elsif ($arch =~ /^sh64$/) {
+		#XXX: we only check for the immediate case presently,
+		#     though we will want to check for the movi/sub
+		#     pair for larger users. -- PFM.
+		#a00048e0:       d4fc40f0        addi.l  r15,-240,r15
+		$re = qr/.*addi\.l.*r15,-(([0-9]{2}|[3-9])[0-9]{2}),r15/o;
 	} else {
 		print("wrong or unknown architecture\n");
 		exit
@@ -90,11 +97,12 @@
 		my $size = $1;
 		$size = hex($size) if ($size =~ /^0x/);
 
-		if ($size > 0x80000000) {
+		if ($size > 0xf0000000) {
 			$size = - $size;
 			$size += 0x80000000;
 			$size += 0x80000000;
 		}
+		next if ($size > 0x10000000);
 
 		next if $line !~ m/^($xs*)/;
 		my $addr = $1;
diff -Nru a/scripts/lxdialog/checklist.c b/scripts/lxdialog/checklist.c
--- a/scripts/lxdialog/checklist.c	2005-03-11 12:51:46 -08:00
+++ b/scripts/lxdialog/checklist.c	2005-03-11 12:51:46 -08:00
@@ -269,7 +269,7 @@
 				    status[scroll + max_choice - 1],
 				    max_choice - 1, FALSE);
 			scrollok (list, TRUE);
-			scroll (list);
+			wscrl (list, 1);
 			scrollok (list, FALSE);
 		    }
 		    scroll++;
diff -Nru a/scripts/lxdialog/colors.h b/scripts/lxdialog/colors.h
--- a/scripts/lxdialog/colors.h	2005-03-11 12:51:41 -08:00
+++ b/scripts/lxdialog/colors.h	2005-03-11 12:51:41 -08:00
@@ -152,10 +152,4 @@
  * Global variables
  */
 
-typedef struct {
-    char name[COLOR_NAME_LEN];
-    int value;
-} color_names_st;
-
-extern color_names_st color_names[];
 extern int color_table[][3];
diff -Nru a/scripts/lxdialog/lxdialog.c b/scripts/lxdialog/lxdialog.c
--- a/scripts/lxdialog/lxdialog.c	2005-03-11 12:51:47 -08:00
+++ b/scripts/lxdialog/lxdialog.c	2005-03-11 12:51:47 -08:00
@@ -56,7 +56,7 @@
 int
 main (int argc, const char * const * argv)
 {
-    int offset = 0, clear_screen = 0, end_common_opts = 0, retval;
+    int offset = 0, opt_clear = 0, end_common_opts = 0, retval;
     const char *title = NULL;
 
 #ifdef LOCALE
@@ -89,7 +89,7 @@
                 offset += 2;
             }
 	} else if (!strcmp (argv[offset + 1], "--clear")) {
-	    if (clear_screen) {	/* Hey, "--clear" can't appear twice! */
+	    if (opt_clear) {		/* Hey, "--clear" can't appear twice! */
 		Usage (argv[0]);
 		exit (-1);
 	    } else if (argc == 2) {	/* we only want to clear the screen */
@@ -98,7 +98,7 @@
 		end_dialog ();
 		return 0;
 	    } else {
-		clear_screen = 1;
+		opt_clear = 1;
 		offset++;
 	    }
 	} else			/* no more common options */
@@ -127,7 +127,7 @@
     init_dialog ();
     retval = (*(modePtr->jumper)) (title, argc - offset, argv + offset);
 
-    if (clear_screen) {		/* clear screen before exit */
+    if (opt_clear) {		/* clear screen before exit */
 	attr_clear (stdscr, LINES, COLS, screen_attr);
 	refresh ();
     }
diff -Nru a/scripts/lxdialog/menubox.c b/scripts/lxdialog/menubox.c
--- a/scripts/lxdialog/menubox.c	2005-03-11 12:51:51 -08:00
+++ b/scripts/lxdialog/menubox.c	2005-03-11 12:51:51 -08:00
@@ -327,7 +327,7 @@
                    ) {
 		    /* Scroll menu up */
 		    scrollok (menu, TRUE);
-                    scroll (menu);
+		    wscrl (menu, 1);
                     scrollok (menu, FALSE);
 
                     scroll++;
@@ -357,7 +357,7 @@
                 for (i=0; (i < max_choice); i++) {
                     if (scroll+max_choice < item_no) {
 			scrollok (menu, TRUE);
-			scroll(menu);
+			wscrl (menu, 1);
 			scrollok (menu, FALSE);
                 	scroll++;
                 	print_item (menu, items[(scroll+max_choice-1)*2+1],
diff -Nru a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c
--- a/scripts/mod/file2alias.c	2005-03-11 12:51:46 -08:00
+++ b/scripts/mod/file2alias.c	2005-03-11 12:51:46 -08:00
@@ -4,7 +4,7 @@
  *
  * Copyright 2002-2003  Rusty Russell, IBM Corporation
  *           2003       Kai Germaschewski
- *           
+ *
  *
  * This software may be used and distributed according to the terms
  * of the GNU General Public License, incorporated herein by reference.
@@ -181,6 +181,24 @@
 	return 1;
 }
 
+/* Looks like: "serio:tyNprNidNexN" */
+static int do_serio_entry(const char *filename,
+			  struct serio_device_id *id, char *alias)
+{
+	id->type = TO_NATIVE(id->type);
+	id->proto = TO_NATIVE(id->proto);
+	id->id = TO_NATIVE(id->id);
+	id->extra = TO_NATIVE(id->extra);
+
+	strcpy(alias, "serio:");
+	ADD(alias, "ty", id->type != SERIO_ANY, id->type);
+	ADD(alias, "pr", id->proto != SERIO_ANY, id->proto);
+	ADD(alias, "id", id->id != SERIO_ANY, id->id);
+	ADD(alias, "ex", id->extra != SERIO_ANY, id->extra);
+
+	return 1;
+}
+
 /* looks like: "pnp:dD" */
 static int do_pnp_entry(const char *filename,
 			struct pnp_device_id *id, char *alias)
@@ -270,6 +288,9 @@
 	else if (sym_is(symname, "__mod_ccw_device_table"))
 		do_table(symval, sym->st_size, sizeof(struct ccw_device_id),
 			 do_ccw_entry, mod);
+	else if (sym_is(symname, "__mod_serio_device_table"))
+		do_table(symval, sym->st_size, sizeof(struct serio_device_id),
+			 do_serio_entry, mod);
 	else if (sym_is(symname, "__mod_pnp_device_table"))
 		do_table(symval, sym->st_size, sizeof(struct pnp_device_id),
 			 do_pnp_entry, mod);
diff -Nru a/scripts/show_delta b/scripts/show_delta
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/scripts/show_delta	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,129 @@
+#!/usr/bin/env python
+#
+# show_deltas: Read list of printk messages instrumented with
+# time data, and format with time deltas.
+#
+# Also, you can show the times relative to a fixed point.
+#
+# Copyright 2003 Sony Corporation
+#
+# GPL 2.0 applies.
+
+import sys
+import string
+
+def usage():
+	print """usage: show_delta [<options>] <filename>
+
+This program parses the output from a set of printk message lines which
+have time data prefixed because the CONFIG_PRINTK_TIME option is set, or
+the kernel command line option "time" is specified. When run with no
+options, the time information is converted to show the time delta between
+each printk line and the next.  When run with the '-b' option, all times
+are relative to a single (base) point in time.
+
+Options:
+  -h            Show this usage help.
+  -b <base>	Specify a base for time references.
+		<base> can be a number or a string.
+		If it is a string, the first message line
+		which matches (at the beginning of the
+		line) is used as the time reference.
+
+ex: $ dmesg >timefile
+    $ show_delta -b NET4 timefile
+
+will show times relative to the line in the kernel output
+starting with "NET4".
+"""
+	sys.exit(1)
+
+# returns a tuple containing the seconds and text for each message line
+# seconds is returned as a float
+# raise an exception if no timing data was found
+def get_time(line):
+	if line[0]!="[":
+		raise ValueError
+
+	# split on closing bracket
+	(time_str, rest) = string.split(line[1:],']',1)
+	time = string.atof(time_str)
+
+	#print "time=", time
+	return (time, rest)
+
+
+# average line looks like:
+# [    0.084282] VFS: Mounted root (romfs filesystem) readonly
+# time data is expressed in seconds.useconds,
+# convert_line adds a delta for each line
+last_time = 0.0
+def convert_line(line, base_time):
+	global last_time
+
+	try:
+		(time, rest) = get_time(line)
+	except:
+		# if any problem parsing time, don't convert anything
+		return line
+
+	if base_time:
+		# show time from base
+		delta = time - base_time
+	else:
+		# just show time from last line
+		delta = time - last_time
+		last_time = time
+
+	return ("[%5.6f < %5.6f >]" % (time, delta)) + rest
+
+def main():
+	base_str = ""
+	filein = ""
+	for arg in sys.argv[1:]:
+		if arg=="-b":
+			base_str = sys.argv[sys.argv.index("-b")+1]
+		elif arg=="-h":
+			usage()
+		else:
+			filein = arg
+
+	if not filein:
+		usage()
+
+	try:
+		lines = open(filein,"r").readlines()
+	except:
+		print "Problem opening file: %s" % filein
+		sys.exit(1)
+
+	if base_str:
+		print 'base= "%s"' % base_str
+		# assume a numeric base.  If that fails, try searching
+		# for a matching line.
+		try:
+			base_time = float(base_str)
+		except:
+			# search for line matching <base> string
+			found = 0
+			for line in lines:
+				try:
+					(time, rest) = get_time(line)
+				except:
+					continue
+				if string.find(rest, base_str)==1:
+					base_time = time
+					found = 1
+					# stop at first match
+					break
+			if not found:
+				print 'Couldn\'t find line matching base pattern "%s"' % base_str
+				sys.exit(1)
+	else:
+		base_time = 0.0
+
+	for line in lines:
+		print convert_line(line, base_time),
+
+main()
+
diff -Nru a/security/dummy.c b/security/dummy.c
--- a/security/dummy.c	2005-03-11 12:51:41 -08:00
+++ b/security/dummy.c	2005-03-11 12:51:41 -08:00
@@ -446,13 +446,16 @@
 	return 0;
 }
 
-static int dummy_file_mmap (struct file *file, unsigned long prot,
+static int dummy_file_mmap (struct file *file, unsigned long reqprot,
+			    unsigned long prot,
 			    unsigned long flags)
 {
 	return 0;
 }
 
-static int dummy_file_mprotect (struct vm_area_struct *vma, unsigned long prot)
+static int dummy_file_mprotect (struct vm_area_struct *vma,
+				unsigned long reqprot,
+				unsigned long prot)
 {
 	return 0;
 }
diff -Nru a/security/keys/key.c b/security/keys/key.c
--- a/security/keys/key.c	2005-03-11 12:51:51 -08:00
+++ b/security/keys/key.c	2005-03-11 12:51:51 -08:00
@@ -57,9 +57,10 @@
 {
 	struct key_user *candidate = NULL, *user;
 	struct rb_node *parent = NULL;
-	struct rb_node **p = &key_user_tree.rb_node;
+	struct rb_node **p;
 
  try_again:
+	p = &key_user_tree.rb_node;
 	spin_lock(&key_user_lock);
 
 	/* search the tree for a user record with a matching UID */
diff -Nru a/security/keys/process_keys.c b/security/keys/process_keys.c
--- a/security/keys/process_keys.c	2005-03-11 12:51:50 -08:00
+++ b/security/keys/process_keys.c	2005-03-11 12:51:50 -08:00
@@ -165,30 +165,36 @@
 
 /*****************************************************************************/
 /*
- * install a fresh process keyring, discarding the old one
+ * make sure a process keyring is installed
  */
 static int install_process_keyring(struct task_struct *tsk)
 {
-	struct key *keyring, *old;
+	unsigned long flags;
+	struct key *keyring;
 	char buf[20];
 	int ret;
 
-	sprintf(buf, "_pid.%u", tsk->tgid);
+	if (!tsk->signal->process_keyring) {
+		sprintf(buf, "_pid.%u", tsk->tgid);
 
-	keyring = keyring_alloc(buf, tsk->uid, tsk->gid, 1, NULL);
-	if (IS_ERR(keyring)) {
-		ret = PTR_ERR(keyring);
-		goto error;
-	}
+		keyring = keyring_alloc(buf, tsk->uid, tsk->gid, 1, NULL);
+		if (IS_ERR(keyring)) {
+			ret = PTR_ERR(keyring);
+			goto error;
+		}
 
-	task_lock(tsk);
-	old = tsk->process_keyring;
-	tsk->process_keyring = keyring;
-	task_unlock(tsk);
+		/* attach or swap keyrings */
+		spin_lock_irqsave(&tsk->sighand->siglock, flags);
+		if (!tsk->signal->process_keyring) {
+			tsk->signal->process_keyring = keyring;
+			keyring = NULL;
+		}
+		spin_unlock_irqrestore(&tsk->sighand->siglock, flags);
 
-	ret = 0;
+		key_put(keyring);
+	}
 
-	key_put(old);
+	ret = 0;
  error:
 	return ret;
 
@@ -202,6 +208,7 @@
 static int install_session_keyring(struct task_struct *tsk,
 				   struct key *keyring)
 {
+	unsigned long flags;
 	struct key *old;
 	char buf[20];
 	int ret;
@@ -221,10 +228,10 @@
 	}
 
 	/* install the keyring */
-	task_lock(tsk);
-	old = tsk->session_keyring;
-	tsk->session_keyring = keyring;
-	task_unlock(tsk);
+	spin_lock_irqsave(&tsk->sighand->siglock, flags);
+	old = tsk->signal->session_keyring;
+	tsk->signal->session_keyring = keyring;
+	spin_unlock_irqrestore(&tsk->sighand->siglock, flags);
 
 	ret = 0;
 
@@ -236,42 +243,59 @@
 
 /*****************************************************************************/
 /*
- * copy the keys for fork
+ * copy the keys in a thread group for fork without CLONE_THREAD
  */
-int copy_keys(unsigned long clone_flags, struct task_struct *tsk)
+int copy_thread_group_keys(struct task_struct *tsk)
 {
-	int ret = 0;
+	unsigned long flags;
 
-	key_check(tsk->session_keyring);
-	key_check(tsk->process_keyring);
-	key_check(tsk->thread_keyring);
+	key_check(current->thread_group->session_keyring);
+	key_check(current->thread_group->process_keyring);
 
-	if (tsk->session_keyring)
-		atomic_inc(&tsk->session_keyring->usage);
+	/* no process keyring yet */
+	tsk->signal->process_keyring = NULL;
 
-	if (tsk->process_keyring) {
-		if (clone_flags & CLONE_THREAD) {
-			atomic_inc(&tsk->process_keyring->usage);
-		}
-		else {
-			tsk->process_keyring = NULL;
-			ret = install_process_keyring(tsk);
-		}
-	}
+	/* same session keyring */
+	spin_lock_irqsave(&current->sighand->siglock, flags);
+	tsk->signal->session_keyring =
+		key_get(current->signal->session_keyring);
+	spin_unlock_irqrestore(&current->sighand->siglock, flags);
+
+	return 0;
+
+} /* end copy_thread_group_keys() */
 
+/*****************************************************************************/
+/*
+ * copy the keys for fork
+ */
+int copy_keys(unsigned long clone_flags, struct task_struct *tsk)
+{
+	key_check(tsk->thread_keyring);
+
+	/* no thread keyring yet */
 	tsk->thread_keyring = NULL;
-	return ret;
+	return 0;
 
 } /* end copy_keys() */
 
 /*****************************************************************************/
 /*
- * dispose of keys upon exit
+ * dispose of thread group keys upon thread group destruction
+ */
+void exit_thread_group_keys(struct signal_struct *tg)
+{
+	key_put(tg->session_keyring);
+	key_put(tg->process_keyring);
+
+} /* end exit_thread_group_keys() */
+
+/*****************************************************************************/
+/*
+ * dispose of keys upon thread exit
  */
 void exit_keys(struct task_struct *tsk)
 {
-	key_put(tsk->session_keyring);
-	key_put(tsk->process_keyring);
 	key_put(tsk->thread_keyring);
 
 } /* end exit_keys() */
@@ -282,6 +306,7 @@
  */
 int exec_keys(struct task_struct *tsk)
 {
+	unsigned long flags;
 	struct key *old;
 
 	/* newly exec'd tasks don't get a thread keyring */
@@ -292,8 +317,15 @@
 
 	key_put(old);
 
-	/* newly exec'd tasks get a fresh process keyring */
-	return install_process_keyring(tsk);
+	/* discard the process keyring from a newly exec'd task */
+	spin_lock_irqsave(&tsk->sighand->siglock, flags);
+	old = tsk->signal->process_keyring;
+	tsk->signal->process_keyring = NULL;
+	spin_unlock_irqrestore(&tsk->sighand->siglock, flags);
+
+	key_put(old);
+
+	return 0;
 
 } /* end exec_keys() */
 
@@ -314,15 +346,6 @@
  */
 void key_fsuid_changed(struct task_struct *tsk)
 {
-	/* update the ownership of the process keyring */
-	if (tsk->process_keyring) {
-		down_write(&tsk->process_keyring->sem);
-		write_lock(&tsk->process_keyring->lock);
-		tsk->process_keyring->uid = tsk->fsuid;
-		write_unlock(&tsk->process_keyring->lock);
-		up_write(&tsk->process_keyring->sem);
-	}
-
 	/* update the ownership of the thread keyring */
 	if (tsk->thread_keyring) {
 		down_write(&tsk->thread_keyring->sem);
@@ -340,15 +363,6 @@
  */
 void key_fsgid_changed(struct task_struct *tsk)
 {
-	/* update the ownership of the process keyring */
-	if (tsk->process_keyring) {
-		down_write(&tsk->process_keyring->sem);
-		write_lock(&tsk->process_keyring->lock);
-		tsk->process_keyring->gid = tsk->fsgid;
-		write_unlock(&tsk->process_keyring->lock);
-		up_write(&tsk->process_keyring->sem);
-	}
-
 	/* update the ownership of the thread keyring */
 	if (tsk->thread_keyring) {
 		down_write(&tsk->thread_keyring->sem);
@@ -373,7 +387,8 @@
 					key_match_func_t match)
 {
 	struct task_struct *tsk = current;
-	struct key *key, *ret, *err, *session;
+	unsigned long flags;
+	struct key *key, *ret, *err, *tmp;
 
 	/* we want to return -EAGAIN or -ENOKEY if any of the keyrings were
 	 * searchable, but we failed to find a key or we found a negative key;
@@ -407,9 +422,9 @@
 	}
 
 	/* search the process keyring second */
-	if (tsk->process_keyring) {
-		key = keyring_search_aux(tsk->process_keyring, type,
-					 description, match);
+	if (tsk->signal->process_keyring) {
+		key = keyring_search_aux(tsk->signal->process_keyring,
+					 type, description, match);
 		if (!IS_ERR(key))
 			goto found;
 
@@ -427,12 +442,17 @@
 	}
 
 	/* search the session keyring last */
-	session = tsk->session_keyring;
-	if (!session)
-		session = tsk->user->session_keyring;
+	spin_lock_irqsave(&tsk->sighand->siglock, flags);
 
-	key = keyring_search_aux(session, type,
-				 description, match);
+	tmp = tsk->signal->session_keyring;
+	if (!tmp)
+		tmp = tsk->user->session_keyring;
+	atomic_inc(&tmp->usage);
+
+	spin_unlock_irqrestore(&tsk->sighand->siglock, flags);
+
+	key = keyring_search_aux(tmp, type, description, match);
+	key_put(tmp);
 	if (!IS_ERR(key))
 		goto found;
 
@@ -479,6 +499,7 @@
 			    key_perm_t perm)
 {
 	struct task_struct *tsk = current;
+	unsigned long flags;
 	struct key *key;
 	int ret;
 
@@ -502,7 +523,7 @@
 		break;
 
 	case KEY_SPEC_PROCESS_KEYRING:
-		if (!tsk->process_keyring) {
+		if (!tsk->signal->process_keyring) {
 			if (!create)
 				goto error;
 
@@ -513,12 +534,12 @@
 			}
 		}
 
-		key = tsk->process_keyring;
+		key = tsk->signal->process_keyring;
 		atomic_inc(&key->usage);
 		break;
 
 	case KEY_SPEC_SESSION_KEYRING:
-		if (!tsk->session_keyring) {
+		if (!tsk->signal->session_keyring) {
 			/* always install a session keyring upon access if one
 			 * doesn't exist yet */
 			ret = install_session_keyring(
@@ -527,8 +548,10 @@
 				goto error;
 		}
 
-		key = tsk->session_keyring;
+		spin_lock_irqsave(&tsk->sighand->siglock, flags);
+		key = tsk->signal->session_keyring;
 		atomic_inc(&key->usage);
+		spin_unlock_irqrestore(&tsk->sighand->siglock, flags);
 		break;
 
 	case KEY_SPEC_USER_KEYRING:
@@ -592,6 +615,7 @@
 long join_session_keyring(const char *name)
 {
 	struct task_struct *tsk = current;
+	unsigned long flags;
 	struct key *keyring;
 	long ret;
 
@@ -601,7 +625,9 @@
 		if (ret < 0)
 			goto error;
 
-		ret = tsk->session_keyring->serial;
+		spin_lock_irqsave(&tsk->sighand->siglock, flags);
+		ret = tsk->signal->session_keyring->serial;
+		spin_unlock_irqrestore(&tsk->sighand->siglock, flags);
 		goto error;
 	}
 
@@ -628,9 +654,8 @@
 	if (ret < 0)
 		goto error2;
 
+	ret = keyring->serial;
 	key_put(keyring);
-
-	ret = tsk->session_keyring->serial;
 
  error2:
 	up(&key_session_sem);
diff -Nru a/security/keys/request_key.c b/security/keys/request_key.c
--- a/security/keys/request_key.c	2005-03-11 12:51:41 -08:00
+++ b/security/keys/request_key.c	2005-03-11 12:51:41 -08:00
@@ -34,6 +34,8 @@
 			    const char *callout_info)
 {
 	struct task_struct *tsk = current;
+	unsigned long flags;
+	key_serial_t prkey, sskey;
 	char *argv[10], *envp[3], uid_str[12], gid_str[12];
 	char key_str[12], keyring_str[3][12];
 	int i;
@@ -46,16 +48,25 @@
 	sprintf(key_str, "%d", key->serial);
 
 	/* we specify the process's default keyrings */
-	task_lock(current);
 	sprintf(keyring_str[0], "%d",
 		tsk->thread_keyring ? tsk->thread_keyring->serial : 0);
-	sprintf(keyring_str[1], "%d",
-		tsk->process_keyring ? tsk->process_keyring->serial : 0);
-	sprintf(keyring_str[2], "%d",
-		(tsk->session_keyring ?
-		 tsk->session_keyring->serial :
-		 tsk->user->session_keyring->serial));
-	task_unlock(tsk);
+
+	prkey = 0;
+	if (tsk->signal->process_keyring)
+		prkey = tsk->signal->process_keyring->serial;
+
+	sskey = 0;
+	spin_lock_irqsave(&tsk->sighand->siglock, flags);
+	if (tsk->signal->session_keyring)
+		sskey = tsk->signal->session_keyring->serial;
+	spin_unlock_irqrestore(&tsk->sighand->siglock, flags);
+
+
+	if (!sskey)
+		sskey = tsk->user->session_keyring->serial;
+
+	sprintf(keyring_str[1], "%d", prkey);
+	sprintf(keyring_str[2], "%d", sskey);
 
 	/* set up a minimal environment */
 	i = 0;
@@ -166,8 +177,19 @@
 	now = current_kernel_time();
 	key->expiry = now.tv_sec + key_negative_timeout;
 
-	if (current->session_keyring)
-		key_link(current->session_keyring, key);
+	if (current->signal->session_keyring) {
+		unsigned long flags;
+		struct key *keyring;
+
+		spin_lock_irqsave(&current->sighand->siglock, flags);
+		keyring = current->signal->session_keyring;
+		atomic_inc(&keyring->usage);
+		spin_unlock_irqrestore(&current->sighand->siglock, flags);
+
+		key_link(keyring, key);
+		key_put(keyring);
+	}
+
 	key_put(key);
 
 	/* notify anyone who was waiting */
@@ -274,8 +296,8 @@
 
 		/* - get hold of the user's construction queue */
 		user = key_user_lookup(current->fsuid);
-		if (IS_ERR(user)) {
-			key = ERR_PTR(PTR_ERR(user));
+		if (!user) {
+			key = ERR_PTR(-ENOMEM);
 			goto error;
 		}
 
diff -Nru a/security/selinux/Kconfig b/security/selinux/Kconfig
--- a/security/selinux/Kconfig	2005-03-11 12:51:41 -08:00
+++ b/security/selinux/Kconfig	2005-03-11 12:51:41 -08:00
@@ -76,12 +76,22 @@
 	  /selinux/avc/cache_stats, which may be monitored via
 	  tools such as avcstat.
 
-config SECURITY_SELINUX_MLS
-	bool "NSA SELinux MLS policy (EXPERIMENTAL)"
-	depends on SECURITY_SELINUX && EXPERIMENTAL
-	default n
+config SECURITY_SELINUX_CHECKREQPROT_VALUE
+	int "NSA SELinux checkreqprot default value"
+	depends on SECURITY_SELINUX
+	range 0 1
+	default 1
 	help
-	  This enables the NSA SELinux Multi-Level Security (MLS) policy in
-	  addition to the default RBAC/TE policy.  This policy is
-	  experimental and has not been configured for use.  Unless you
-	  specifically want to experiment with MLS, say N.
+	  This option sets the default value for the 'checkreqprot' flag
+	  that determines whether SELinux checks the protection requested
+	  by the application or the protection that will be applied by the
+	  kernel (including any implied execute for read-implies-exec) for
+	  mmap and mprotect calls.  If this option is set to 0 (zero),
+	  SELinux will default to checking the protection that will be applied
+	  by the kernel.  If this option is set to 1 (one), SELinux will
+	  default to checking the protection requested by the application.
+	  The checkreqprot flag may be changed from the default via the
+	  'checkreqprot=' boot parameter.  It may also be changed at runtime
+	  via /selinux/checkreqprot if authorized by policy.
+
+	  If you are unsure how to answer this question, answer 1.
diff -Nru a/security/selinux/hooks.c b/security/selinux/hooks.c
--- a/security/selinux/hooks.c	2005-03-11 12:51:51 -08:00
+++ b/security/selinux/hooks.c	2005-03-11 12:51:51 -08:00
@@ -10,6 +10,8 @@
  *
  *  Copyright (C) 2001,2002 Networks Associates Technology, Inc.
  *  Copyright (C) 2003 Red Hat, Inc., James Morris <jmorris@redhat.com>
+ *  Copyright (C) 2004-2005 Trusted Computer Solutions, Inc.
+ *                          <dgoeddel@trustedcs.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,
@@ -589,7 +591,8 @@
 		spin_unlock(&sbsec->isec_lock);
 		inode = igrab(inode);
 		if (inode) {
-			inode_doinit(inode);
+			if (!IS_PRIVATE (inode))
+				inode_doinit(inode);
 			iput(inode);
 		}
 		spin_lock(&sbsec->isec_lock);
@@ -1855,6 +1858,13 @@
 			initrlim = init_task.signal->rlim+i;
 			rlim->rlim_cur = min(rlim->rlim_max,initrlim->rlim_cur);
 		}
+		if (current->signal->rlim[RLIMIT_CPU].rlim_cur != RLIM_INFINITY) {
+			/*
+			 * This will cause RLIMIT_CPU calculations
+			 * to be refigured.
+			 */
+			current->it_prof_expires = jiffies_to_cputime(1);
+		}
 	}
 
 	/* Wake up the parent if it is waiting so that it can
@@ -2203,6 +2213,11 @@
 	if (rc)
 		return rc;
 
+	rc = security_validate_transition(isec->sid, newsid, tsec->sid,
+	                                  isec->sclass);
+	if (rc)
+		return rc;
+
 	return avc_has_perm(newsid,
 			    sbsec->sid,
 			    SECCLASS_FILESYSTEM,
@@ -2407,6 +2422,7 @@
 
 static int file_map_prot_check(struct file *file, unsigned long prot, int shared)
 {
+#ifndef CONFIG_PPC32
 	if ((prot & PROT_EXEC) && (!file || (!shared && (prot & PROT_WRITE)))) {
 		/*
 		 * We are making executable an anonymous mapping or a
@@ -2417,6 +2433,7 @@
 		if (rc)
 			return rc;
 	}
+#endif
 
 	if (file) {
 		/* read access is always possible with a mapping */
@@ -2434,27 +2451,36 @@
 	return 0;
 }
 
-static int selinux_file_mmap(struct file *file, unsigned long prot, unsigned long flags)
+static int selinux_file_mmap(struct file *file, unsigned long reqprot,
+			     unsigned long prot, unsigned long flags)
 {
 	int rc;
 
-	rc = secondary_ops->file_mmap(file, prot, flags);
+	rc = secondary_ops->file_mmap(file, reqprot, prot, flags);
 	if (rc)
 		return rc;
 
+	if (selinux_checkreqprot)
+		prot = reqprot;
+
 	return file_map_prot_check(file, prot,
 				   (flags & MAP_TYPE) == MAP_SHARED);
 }
 
 static int selinux_file_mprotect(struct vm_area_struct *vma,
+				 unsigned long reqprot,
 				 unsigned long prot)
 {
 	int rc;
 
-	rc = secondary_ops->file_mprotect(vma, prot);
+	rc = secondary_ops->file_mprotect(vma, reqprot, prot);
 	if (rc)
 		return rc;
 
+	if (selinux_checkreqprot)
+		prot = reqprot;
+
+#ifndef CONFIG_PPC32
 	if (vma->vm_file != NULL && vma->anon_vma != NULL && (prot & PROT_EXEC)) {
 		/*
 		 * We are making executable a file mapping that has
@@ -2466,6 +2492,7 @@
 		if (rc)
 			return rc;
 	}
+#endif
 
 	return file_map_prot_check(vma->vm_file, prot, vma->vm_flags&VM_SHARED);
 }
@@ -4079,6 +4106,7 @@
 	struct task_security_struct *tsec;
 	u32 sid = 0;
 	int error;
+	char *str = value;
 
 	if (current != p) {
 		/* SELinux only allows a process to change its own
@@ -4103,8 +4131,11 @@
 		return error;
 
 	/* Obtain a SID for the context, if one was specified. */
-	if (size) {
-		int error;
+	if (size && str[1] && str[1] != '\n') {
+		if (str[size-1] == '\n') {
+			str[size-1] = 0;
+			size--;
+		}
 		error = security_context_to_sid(value, size, &sid);
 		if (error)
 			return error;
diff -Nru a/security/selinux/include/av_perm_to_string.h b/security/selinux/include/av_perm_to_string.h
--- a/security/selinux/include/av_perm_to_string.h	2005-03-11 12:51:51 -08:00
+++ b/security/selinux/include/av_perm_to_string.h	2005-03-11 12:51:51 -08:00
@@ -83,6 +83,7 @@
    S_(SECCLASS_SECURITY, SECURITY__SETENFORCE, "setenforce")
    S_(SECCLASS_SECURITY, SECURITY__SETBOOL, "setbool")
    S_(SECCLASS_SECURITY, SECURITY__SETSECPARAM, "setsecparam")
+   S_(SECCLASS_SECURITY, SECURITY__SETCHECKREQPROT, "setcheckreqprot")
    S_(SECCLASS_SYSTEM, SYSTEM__IPC_INFO, "ipc_info")
    S_(SECCLASS_SYSTEM, SYSTEM__SYSLOG_READ, "syslog_read")
    S_(SECCLASS_SYSTEM, SYSTEM__SYSLOG_MOD, "syslog_mod")
diff -Nru a/security/selinux/include/av_permissions.h b/security/selinux/include/av_permissions.h
--- a/security/selinux/include/av_permissions.h	2005-03-11 12:51:52 -08:00
+++ b/security/selinux/include/av_permissions.h	2005-03-11 12:51:52 -08:00
@@ -522,6 +522,7 @@
 #define SECURITY__SETENFORCE                      0x00000080UL
 #define SECURITY__SETBOOL                         0x00000100UL
 #define SECURITY__SETSECPARAM                     0x00000200UL
+#define SECURITY__SETCHECKREQPROT                 0x00000400UL
 
 #define SYSTEM__IPC_INFO                          0x00000001UL
 #define SYSTEM__SYSLOG_READ                       0x00000002UL
diff -Nru a/security/selinux/include/objsec.h b/security/selinux/include/objsec.h
--- a/security/selinux/include/objsec.h	2005-03-11 12:51:42 -08:00
+++ b/security/selinux/include/objsec.h	2005-03-11 12:51:42 -08:00
@@ -109,4 +109,6 @@
 
 extern int inode_security_set_sid(struct inode *inode, u32 sid);
 
+extern unsigned int selinux_checkreqprot;
+
 #endif /* _SELINUX_OBJSEC_H_ */
diff -Nru a/security/selinux/include/security.h b/security/selinux/include/security.h
--- a/security/selinux/include/security.h	2005-03-11 12:51:41 -08:00
+++ b/security/selinux/include/security.h	2005-03-11 12:51:41 -08:00
@@ -21,10 +21,12 @@
 #define POLICYDB_VERSION_BOOL		16
 #define POLICYDB_VERSION_IPV6		17
 #define POLICYDB_VERSION_NLCLASS	18
+#define POLICYDB_VERSION_VALIDATETRANS	19
+#define POLICYDB_VERSION_MLS		19
 
 /* Range of policy versions we understand*/
 #define POLICYDB_VERSION_MIN   POLICYDB_VERSION_BASE
-#define POLICYDB_VERSION_MAX   POLICYDB_VERSION_NLCLASS
+#define POLICYDB_VERSION_MAX   POLICYDB_VERSION_MLS
 
 #ifdef CONFIG_SECURITY_SELINUX_BOOTPARAM
 extern int selinux_enabled;
@@ -32,11 +34,7 @@
 #define selinux_enabled 1
 #endif
 
-#ifdef CONFIG_SECURITY_SELINUX_MLS
-#define selinux_mls_enabled 1
-#else
-#define selinux_mls_enabled 0
-#endif
+extern int selinux_mls_enabled;
 
 int security_load_policy(void * data, size_t len);
 
@@ -78,6 +76,9 @@
 
 int security_node_sid(u16 domain, void *addr, u32 addrlen,
 	u32 *out_sid);
+
+int security_validate_transition(u32 oldsid, u32 newsid, u32 tasksid,
+                                 u16 tclass);
 
 #define SECURITY_FS_USE_XATTR		1 /* use xattr */
 #define SECURITY_FS_USE_TRANS		2 /* use transition SIDs, e.g. devpts/tmpfs */
diff -Nru a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c
--- a/security/selinux/selinuxfs.c	2005-03-11 12:51:52 -08:00
+++ b/security/selinux/selinuxfs.c	2005-03-11 12:51:52 -08:00
@@ -34,6 +34,16 @@
 #include "objsec.h"
 #include "conditional.h"
 
+unsigned int selinux_checkreqprot = CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE;
+
+static int __init checkreqprot_setup(char *str)
+{
+	selinux_checkreqprot = simple_strtoul(str,NULL,0) ? 1 : 0;
+	return 1;
+}
+__setup("checkreqprot=", checkreqprot_setup);
+
+
 static DECLARE_MUTEX(sel_sem);
 
 /* global data for booleans */
@@ -72,6 +82,7 @@
 	SEL_DISABLE,	/* disable SELinux until next reboot */
 	SEL_AVC,	/* AVC management directory */
 	SEL_MEMBER,	/* compute polyinstantiation membership decision */
+	SEL_CHECKREQPROT, /* check requested protection, not kernel-applied one */
 };
 
 #define TMPBUFLEN	12
@@ -300,6 +311,54 @@
 	.write		= sel_write_context,
 };
 
+static ssize_t sel_read_checkreqprot(struct file *filp, char __user *buf,
+				     size_t count, loff_t *ppos)
+{
+	char tmpbuf[TMPBUFLEN];
+	ssize_t length;
+
+	length = scnprintf(tmpbuf, TMPBUFLEN, "%u", selinux_checkreqprot);
+	return simple_read_from_buffer(buf, count, ppos, tmpbuf, length);
+}
+
+static ssize_t sel_write_checkreqprot(struct file * file, const char __user * buf,
+				      size_t count, loff_t *ppos)
+{
+	char *page;
+	ssize_t length;
+	unsigned int new_value;
+
+	length = task_has_security(current, SECURITY__SETCHECKREQPROT);
+	if (length)
+		return length;
+
+	if (count < 0 || count >= PAGE_SIZE)
+		return -ENOMEM;
+	if (*ppos != 0) {
+		/* No partial writes. */
+		return -EINVAL;
+	}
+	page = (char*)get_zeroed_page(GFP_KERNEL);
+	if (!page)
+		return -ENOMEM;
+	length = -EFAULT;
+	if (copy_from_user(page, buf, count))
+		goto out;
+
+	length = -EINVAL;
+	if (sscanf(page, "%u", &new_value) != 1)
+		goto out;
+
+	selinux_checkreqprot = new_value ? 1 : 0;
+	length = count;
+out:
+	free_page((unsigned long) page);
+	return length;
+}
+static struct file_operations sel_checkreqprot_ops = {
+	.read		= sel_read_checkreqprot,
+	.write		= sel_write_checkreqprot,
+};
 
 /*
  * Remaining nodes use transaction based IO methods like nfsd/nfsctl.c
@@ -1182,6 +1241,7 @@
 		[SEL_MLS] = {"mls", &sel_mls_ops, S_IRUGO},
 		[SEL_DISABLE] = {"disable", &sel_disable_ops, S_IWUSR},
 		[SEL_MEMBER] = {"member", &transaction_ops, S_IRUGO|S_IWUGO},
+		[SEL_CHECKREQPROT] = {"checkreqprot", &sel_checkreqprot_ops, S_IRUGO|S_IWUSR},
 		/* last one */ {""}
 	};
 	ret = simple_fill_super(sb, SELINUX_MAGIC, selinux_files);
diff -Nru a/security/selinux/ss/Makefile b/security/selinux/ss/Makefile
--- a/security/selinux/ss/Makefile	2005-03-11 12:51:41 -08:00
+++ b/security/selinux/ss/Makefile	2005-03-11 12:51:41 -08:00
@@ -5,7 +5,5 @@
 EXTRA_CFLAGS += -Isecurity/selinux/include
 obj-y := ss.o
 
-ss-y := ebitmap.o hashtab.o symtab.o sidtab.o avtab.o policydb.o services.o conditional.o
-
-ss-$(CONFIG_SECURITY_SELINUX_MLS) += mls.o
+ss-y := ebitmap.o hashtab.o symtab.o sidtab.o avtab.o policydb.o services.o conditional.o mls.o
 
diff -Nru a/security/selinux/ss/constraint.h b/security/selinux/ss/constraint.h
--- a/security/selinux/ss/constraint.h	2005-03-11 12:51:46 -08:00
+++ b/security/selinux/ss/constraint.h	2005-03-11 12:51:46 -08:00
@@ -31,6 +31,13 @@
 #define CEXPR_ROLE 2		/* role */
 #define CEXPR_TYPE 4		/* type */
 #define CEXPR_TARGET 8		/* target if set, source otherwise */
+#define CEXPR_XTARGET 16	/* special 3rd target for validatetrans rule */
+#define CEXPR_L1L2 32		/* low level 1 vs. low level 2 */
+#define CEXPR_L1H2 64		/* low level 1 vs. high level 2 */
+#define CEXPR_H1L2 128		/* high level 1 vs. low level 2 */
+#define CEXPR_H1H2 256		/* high level 1 vs. high level 2 */
+#define CEXPR_L1H1 512		/* low level 1 vs. high level 1 */
+#define CEXPR_L2H2 1024		/* low level 2 vs. high level 2 */
 	u32 attr;		/* attribute */
 
 #define CEXPR_EQ     1		/* == or eq */
diff -Nru a/security/selinux/ss/context.h b/security/selinux/ss/context.h
--- a/security/selinux/ss/context.h	2005-03-11 12:51:51 -08:00
+++ b/security/selinux/ss/context.h	2005-03-11 12:51:51 -08:00
@@ -17,6 +17,7 @@
 
 #include "ebitmap.h"
 #include "mls_types.h"
+#include "security.h"
 
 /*
  * A security context consists of an authenticated user
@@ -26,13 +27,9 @@
 	u32 user;
 	u32 role;
 	u32 type;
-#ifdef CONFIG_SECURITY_SELINUX_MLS
 	struct mls_range range;
-#endif
 };
 
-#ifdef CONFIG_SECURITY_SELINUX_MLS
-
 static inline void mls_context_init(struct context *c)
 {
 	memset(&c->range, 0, sizeof(c->range));
@@ -42,6 +39,9 @@
 {
 	int rc;
 
+	if (!selinux_mls_enabled)
+		return 0;
+
 	dst->range.level[0].sens = src->range.level[0].sens;
 	rc = ebitmap_cpy(&dst->range.level[0].cat, &src->range.level[0].cat);
 	if (rc)
@@ -57,6 +57,9 @@
 
 static inline int mls_context_cmp(struct context *c1, struct context *c2)
 {
+	if (!selinux_mls_enabled)
+		return 1;
+
 	return ((c1->range.level[0].sens == c2->range.level[0].sens) &&
 		ebitmap_cmp(&c1->range.level[0].cat,&c2->range.level[0].cat) &&
 		(c1->range.level[1].sens == c2->range.level[1].sens) &&
@@ -65,26 +68,13 @@
 
 static inline void mls_context_destroy(struct context *c)
 {
+	if (!selinux_mls_enabled)
+		return;
+
 	ebitmap_destroy(&c->range.level[0].cat);
 	ebitmap_destroy(&c->range.level[1].cat);
 	mls_context_init(c);
 }
-
-#else
-
-static inline void mls_context_init(struct context *c)
-{ }
-
-static inline int mls_context_cpy(struct context *dst, struct context *src)
-{ return 0; }
-
-static inline int mls_context_cmp(struct context *c1, struct context *c2)
-{ return 1; }
-
-static inline void mls_context_destroy(struct context *c)
-{ }
-
-#endif
 
 static inline void context_init(struct context *c)
 {
diff -Nru a/security/selinux/ss/mls.c b/security/selinux/ss/mls.c
--- a/security/selinux/ss/mls.c	2005-03-11 12:51:52 -08:00
+++ b/security/selinux/ss/mls.c	2005-03-11 12:51:52 -08:00
@@ -3,6 +3,14 @@
  *
  * Author : Stephen Smalley, <sds@epoch.ncsc.mil>
  */
+/*
+ * Updated: Trusted Computer Solutions, Inc. <dgoeddel@trustedcs.com>
+ *
+ *	Support for enhanced MLS infrastructure.
+ *
+ * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc.
+ */
+
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/string.h>
@@ -12,79 +20,47 @@
 #include "services.h"
 
 /*
- * Remove any permissions from `allowed' that are
- * denied by the MLS policy.
- */
-void mls_compute_av(struct context *scontext,
-		    struct context *tcontext,
-		    struct class_datum *tclass,
-		    u32 *allowed)
-{
-	unsigned int rel[2];
-	int l;
-
-	for (l = 0; l < 2; l++)
-		rel[l] = mls_level_relation(scontext->range.level[l],
-					    tcontext->range.level[l]);
-
-	if (rel[1] != MLS_RELATION_EQ) {
-		if (rel[1] != MLS_RELATION_DOM &&
-		    !ebitmap_get_bit(&policydb.trustedreaders, scontext->type - 1) &&
-		    !ebitmap_get_bit(&policydb.trustedobjects, tcontext->type - 1)) {
-			/* read(s,t) = (s.high >= t.high) = False */
-			*allowed = (*allowed) & ~(tclass->mlsperms.read);
-		}
-		if (rel[1] != MLS_RELATION_DOMBY &&
-		    !ebitmap_get_bit(&policydb.trustedreaders, tcontext->type - 1) &&
-		    !ebitmap_get_bit(&policydb.trustedobjects, scontext->type - 1)) {
-			/* readby(s,t) = read(t,s) = False */
-			*allowed = (*allowed) & ~(tclass->mlsperms.readby);
-		}
-	}
-	if (((rel[0] != MLS_RELATION_DOMBY && rel[0] != MLS_RELATION_EQ) ||
-	    ((!mls_level_eq(tcontext->range.level[0],
-			    tcontext->range.level[1])) &&
-	     (rel[1] != MLS_RELATION_DOM && rel[1] != MLS_RELATION_EQ))) &&
-	    !ebitmap_get_bit(&policydb.trustedwriters, scontext->type - 1) &&
-	    !ebitmap_get_bit(&policydb.trustedobjects, tcontext->type - 1)) {
-		/*
-		 * write(s,t) = ((s.low <= t.low = t.high) or (s.low
-		 * <= t.low <= t.high <= s.high)) = False
-		 */
-		*allowed = (*allowed) & ~(tclass->mlsperms.write);
-	}
-
-	if (((rel[0] != MLS_RELATION_DOM && rel[0] != MLS_RELATION_EQ) ||
-	    ((!mls_level_eq(scontext->range.level[0],
-			    scontext->range.level[1])) &&
-	     (rel[1] != MLS_RELATION_DOMBY && rel[1] != MLS_RELATION_EQ))) &&
-	    !ebitmap_get_bit(&policydb.trustedwriters, tcontext->type - 1) &&
-	    !ebitmap_get_bit(&policydb.trustedobjects, scontext->type - 1)) {
-		/* writeby(s,t) = write(t,s) = False */
-		*allowed = (*allowed) & ~(tclass->mlsperms.writeby);
-	}
-}
-
-/*
  * Return the length in bytes for the MLS fields of the
  * security context string representation of `context'.
  */
 int mls_compute_context_len(struct context * context)
 {
-	int i, l, len;
+	int i, l, len, range;
 
+	if (!selinux_mls_enabled)
+		return 0;
 
-	len = 0;
+	len = 1; /* for the beginning ":" */
 	for (l = 0; l < 2; l++) {
-		len += strlen(policydb.p_sens_val_to_name[context->range.level[l].sens - 1]) + 1;
+		range = 0;
+		len += strlen(policydb.p_sens_val_to_name[context->range.level[l].sens - 1]);
 
-		for (i = 1; i <= ebitmap_length(&context->range.level[l].cat); i++)
-			if (ebitmap_get_bit(&context->range.level[l].cat, i - 1))
-				len += strlen(policydb.p_cat_val_to_name[i - 1]) + 1;
+		for (i = 1; i <= ebitmap_length(&context->range.level[l].cat); i++) {
+			if (ebitmap_get_bit(&context->range.level[l].cat, i - 1)) {
+				if (range) {
+					range++;
+					continue;
+				}
 
-		if (mls_level_relation(context->range.level[0], context->range.level[1])
-				== MLS_RELATION_EQ)
-			break;
+				len += strlen(policydb.p_cat_val_to_name[i - 1]) + 1;
+				range++;
+			} else {
+				if (range > 1)
+					len += strlen(policydb.p_cat_val_to_name[i - 2]) + 1;
+				range = 0;
+			}
+		}
+		/* Handle case where last category is the end of range */
+		if (range > 1)
+			len += strlen(policydb.p_cat_val_to_name[i - 2]) + 1;
+
+		if (l == 0) {
+			if (mls_level_eq(&context->range.level[0],
+			                 &context->range.level[1]))
+				break;
+			else
+				len++;
+		}
 	}
 
 	return len;
@@ -95,40 +71,81 @@
  * the MLS fields of `context' into the string `*scontext'.
  * Update `*scontext' to point to the end of the MLS fields.
  */
-int mls_sid_to_context(struct context *context,
-		       char **scontext)
+void mls_sid_to_context(struct context *context,
+                        char **scontext)
 {
 	char *scontextp;
-	int i, l;
+	int i, l, range, wrote_sep;
+
+	if (!selinux_mls_enabled)
+		return;
 
 	scontextp = *scontext;
 
+	*scontextp = ':';
+	scontextp++;
+
 	for (l = 0; l < 2; l++) {
+		range = 0;
+		wrote_sep = 0;
 		strcpy(scontextp,
 		       policydb.p_sens_val_to_name[context->range.level[l].sens - 1]);
 		scontextp += strlen(policydb.p_sens_val_to_name[context->range.level[l].sens - 1]);
-		*scontextp = ':';
-		scontextp++;
-		for (i = 1; i <= ebitmap_length(&context->range.level[l].cat); i++)
+
+		/* categories */
+		for (i = 1; i <= ebitmap_length(&context->range.level[l].cat); i++) {
 			if (ebitmap_get_bit(&context->range.level[l].cat, i - 1)) {
+				if (range) {
+					range++;
+					continue;
+				}
+
+				if (!wrote_sep) {
+					*scontextp++ = ':';
+					wrote_sep = 1;
+				} else
+					*scontextp++ = ',';
 				strcpy(scontextp, policydb.p_cat_val_to_name[i - 1]);
 				scontextp += strlen(policydb.p_cat_val_to_name[i - 1]);
-				*scontextp = ',';
-				scontextp++;
+				range++;
+			} else {
+				if (range > 1) {
+					if (range > 2)
+						*scontextp++ = '.';
+					else
+						*scontextp++ = ',';
+
+					strcpy(scontextp, policydb.p_cat_val_to_name[i - 2]);
+					scontextp += strlen(policydb.p_cat_val_to_name[i - 2]);
+				}
+				range = 0;
 			}
-		if (mls_level_relation(context->range.level[0], context->range.level[1])
-				!= MLS_RELATION_EQ) {
-			scontextp--;
-			sprintf(scontextp, "-");
-			scontextp++;
+		}
 
-		} else {
-			break;
+		/* Handle case where last category is the end of range */
+		if (range > 1) {
+			if (range > 2)
+				*scontextp++ = '.';
+			else
+				*scontextp++ = ',';
+
+			strcpy(scontextp, policydb.p_cat_val_to_name[i - 2]);
+			scontextp += strlen(policydb.p_cat_val_to_name[i - 2]);
+		}
+
+		if (l == 0) {
+			if (mls_level_eq(&context->range.level[0],
+			                 &context->range.level[1]))
+				break;
+			else {
+				*scontextp = '-';
+				scontextp++;
+			}
 		}
 	}
 
 	*scontext = scontextp;
-	return 0;
+	return;
 }
 
 /*
@@ -137,20 +154,19 @@
  */
 int mls_context_isvalid(struct policydb *p, struct context *c)
 {
-	unsigned int relation;
 	struct level_datum *levdatum;
 	struct user_datum *usrdatum;
-	struct mls_range_list *rnode;
 	int i, l;
 
+	if (!selinux_mls_enabled)
+		return 1;
+
 	/*
 	 * MLS range validity checks: high must dominate low, low level must
 	 * be valid (category set <-> sensitivity check), and high level must
 	 * be valid (category set <-> sensitivity check)
 	 */
-	relation = mls_level_relation(c->range.level[1],
-				      c->range.level[0]);
-	if (!(relation & (MLS_RELATION_DOM | MLS_RELATION_EQ)))
+	if (!mls_level_dom(&c->range.level[1], &c->range.level[0]))
 		/* High does not dominate low. */
 		return 0;
 
@@ -185,18 +201,12 @@
 	if (!c->user || c->user > p->p_users.nprim)
 		return 0;
 	usrdatum = p->user_val_to_struct[c->user - 1];
-	for (rnode = usrdatum->ranges; rnode; rnode = rnode->next) {
-		if (mls_range_contains(rnode->range, c->range))
-			break;
-	}
-	if (!rnode)
-		/* user may not be associated with range */
-		return 0;
+	if (!mls_range_contains(usrdatum->range, c->range))
+		return 0; /* user may not be associated with range */
 
 	return 1;
 }
 
-
 /*
  * Set the MLS fields in the security context structure
  * `context' based on the string representation in
@@ -213,23 +223,17 @@
 {
 
 	char delim;
-	char *scontextp, *p;
+	char *scontextp, *p, *rngptr;
 	struct level_datum *levdatum;
-	struct cat_datum *catdatum;
+	struct cat_datum *catdatum, *rngdatum;
 	int l, rc = -EINVAL;
 
-	if (!oldc) {
-		/* No MLS component to the security context.  Try
-		   to use a default 'unclassified' value. */
-		levdatum = hashtab_search(policydb.p_levels.table,
-		                          "unclassified");
-		if (!levdatum)
-			goto out;
-		context->range.level[0].sens = levdatum->level->sens;
-		context->range.level[1].sens = context->range.level[0].sens;
-		rc = 0;
+	if (!selinux_mls_enabled)
+		return 0;
+
+	/* No MLS component to the security context. */
+	if (!oldc)
 		goto out;
-	}
 
 	/* Extract low sensitivity. */
 	scontextp = p = *scontext;
@@ -242,13 +246,15 @@
 
 	for (l = 0; l < 2; l++) {
 		levdatum = hashtab_search(policydb.p_levels.table, scontextp);
-		if (!levdatum)
+		if (!levdatum) {
+			rc = -EINVAL;
 			goto out;
+		}
 
 		context->range.level[l].sens = levdatum->level->sens;
 
 		if (delim == ':') {
-			/* Extract low category set. */
+			/* Extract category set. */
 			while (1) {
 				scontextp = p;
 				while (*p && *p != ',' && *p != '-')
@@ -257,15 +263,46 @@
 				if (delim != 0)
 					*p++ = 0;
 
+				/* Separate into range if exists */
+				if ((rngptr = strchr(scontextp, '.')) != NULL) {
+					/* Remove '.' */
+					*rngptr++ = 0;
+				}
+
 				catdatum = hashtab_search(policydb.p_cats.table,
 				                          scontextp);
-				if (!catdatum)
+				if (!catdatum) {
+					rc = -EINVAL;
 					goto out;
+				}
 
 				rc = ebitmap_set_bit(&context->range.level[l].cat,
 				                     catdatum->value - 1, 1);
 				if (rc)
 					goto out;
+
+				/* If range, set all categories in range */
+				if (rngptr) {
+					int i;
+
+					rngdatum = hashtab_search(policydb.p_cats.table, rngptr);
+					if (!rngdatum) {
+						rc = -EINVAL;
+						goto out;
+					}
+
+					if (catdatum->value >= rngdatum->value) {
+						rc = -EINVAL;
+						goto out;
+					}
+
+					for (i = catdatum->value; i < rngdatum->value; i++) {
+						rc = ebitmap_set_bit(&context->range.level[l].cat, i, 1);
+						if (rc)
+							goto out;
+					}
+				}
+
 				if (delim != ',')
 					break;
 			}
@@ -306,7 +343,6 @@
 
 	/* Copy the MLS range from the source context */
 	for (l = 0; l < 2; l++) {
-
 		dst->range.level[l].sens = src->range.level[l].sens;
 		rc = ebitmap_cpy(&dst->range.level[l].cat,
 				 &src->range.level[l].cat);
@@ -318,6 +354,84 @@
 }
 
 /*
+ * Copies the effective MLS range from `src' into `dst'.
+ */
+static inline int mls_scopy_context(struct context *dst,
+                                    struct context *src)
+{
+	int l, rc = 0;
+
+	/* Copy the MLS range from the source context */
+	for (l = 0; l < 2; l++) {
+		dst->range.level[l].sens = src->range.level[0].sens;
+		rc = ebitmap_cpy(&dst->range.level[l].cat,
+				 &src->range.level[0].cat);
+		if (rc)
+			break;
+	}
+
+	return rc;
+}
+
+/*
+ * Copies the MLS range `range' into `context'.
+ */
+static inline int mls_range_set(struct context *context,
+                                struct mls_range *range)
+{
+	int l, rc = 0;
+
+	/* Copy the MLS range into the  context */
+	for (l = 0; l < 2; l++) {
+		context->range.level[l].sens = range->level[l].sens;
+		rc = ebitmap_cpy(&context->range.level[l].cat,
+				 &range->level[l].cat);
+		if (rc)
+			break;
+	}
+
+	return rc;
+}
+
+int mls_setup_user_range(struct context *fromcon, struct user_datum *user,
+                         struct context *usercon)
+{
+	if (selinux_mls_enabled) {
+		struct mls_level *fromcon_sen = &(fromcon->range.level[0]);
+		struct mls_level *fromcon_clr = &(fromcon->range.level[1]);
+		struct mls_level *user_low = &(user->range.level[0]);
+		struct mls_level *user_clr = &(user->range.level[1]);
+		struct mls_level *user_def = &(user->dfltlevel);
+		struct mls_level *usercon_sen = &(usercon->range.level[0]);
+		struct mls_level *usercon_clr = &(usercon->range.level[1]);
+
+		/* Honor the user's default level if we can */
+		if (mls_level_between(user_def, fromcon_sen, fromcon_clr)) {
+			*usercon_sen = *user_def;
+		} else if (mls_level_between(fromcon_sen, user_def, user_clr)) {
+			*usercon_sen = *fromcon_sen;
+		} else if (mls_level_between(fromcon_clr, user_low, user_def)) {
+			*usercon_sen = *user_low;
+		} else
+			return -EINVAL;
+
+		/* Lower the clearance of available contexts
+		   if the clearance of "fromcon" is lower than
+		   that of the user's default clearance (but
+		   only if the "fromcon" clearance dominates
+		   the user's computed sensitivity level) */
+		if (mls_level_dom(user_clr, fromcon_clr)) {
+			*usercon_clr = *fromcon_clr;
+		} else if (mls_level_dom(fromcon_clr, user_clr)) {
+			*usercon_clr = *user_clr;
+		} else
+			return -EINVAL;
+	}
+
+	return 0;
+}
+
+/*
  * Convert the MLS fields in the security context
  * structure `c' from the values specified in the
  * policy `oldp' to the values specified in the policy `newp'.
@@ -331,6 +445,9 @@
 	struct ebitmap bitmap;
 	int l, i;
 
+	if (!selinux_mls_enabled)
+		return 0;
+
 	for (l = 0; l < 2; l++) {
 		levdatum = hashtab_search(newp->p_levels.table,
 			oldp->p_sens_val_to_name[c->range.level[l].sens - 1]);
@@ -366,17 +483,38 @@
 		    u32 specified,
 		    struct context *newcontext)
 {
+	if (!selinux_mls_enabled)
+		return 0;
+
 	switch (specified) {
 	case AVTAB_TRANSITION:
+		if (tclass == SECCLASS_PROCESS) {
+			struct range_trans *rangetr;
+			/* Look for a range transition rule. */
+			for (rangetr = policydb.range_tr; rangetr;
+			     rangetr = rangetr->next) {
+				if (rangetr->dom == scontext->type &&
+				    rangetr->type == tcontext->type) {
+					/* Set the range from the rule */
+					return mls_range_set(newcontext,
+					                     &rangetr->range);
+				}
+			}
+		}
+		/* Fallthrough */
 	case AVTAB_CHANGE:
-		/* Use the process MLS attributes. */
-		return mls_copy_context(newcontext, scontext);
+		if (tclass == SECCLASS_PROCESS)
+			/* Use the process MLS attributes. */
+			return mls_copy_context(newcontext, scontext);
+		else
+			/* Use the process effective MLS attributes. */
+			return mls_scopy_context(newcontext, scontext);
 	case AVTAB_MEMBER:
 		/* Only polyinstantiate the MLS attributes if
 		   the type is being polyinstantiated */
 		if (newcontext->type != tcontext->type) {
-			/* Use the process MLS attributes. */
-			return mls_copy_context(newcontext, scontext);
+			/* Use the process effective MLS attributes. */
+			return mls_scopy_context(newcontext, scontext);
 		} else {
 			/* Use the related object MLS attributes. */
 			return mls_copy_context(newcontext, tcontext);
@@ -387,365 +525,3 @@
 	return -EINVAL;
 }
 
-void mls_user_destroy(struct user_datum *usrdatum)
-{
-	struct mls_range_list *rnode, *rtmp;
-	rnode = usrdatum->ranges;
-	while (rnode) {
-		rtmp = rnode;
-		rnode = rnode->next;
-		ebitmap_destroy(&rtmp->range.level[0].cat);
-		ebitmap_destroy(&rtmp->range.level[1].cat);
-		kfree(rtmp);
-	}
-}
-
-int mls_read_perm(struct perm_datum *perdatum, void *fp)
-{
-	u32 buf[1];
-	int rc;
-
-	rc = next_entry(buf, fp, sizeof buf);
-	if (rc < 0)
-		return -EINVAL;
-	perdatum->base_perms = le32_to_cpu(buf[0]);
-	return 0;
-}
-
-/*
- * Read a MLS level structure from a policydb binary
- * representation file.
- */
-struct mls_level *mls_read_level(void *fp)
-{
-	struct mls_level *l;
-	u32 buf[1];
-	int rc;
-
-	l = kmalloc(sizeof(*l), GFP_ATOMIC);
-	if (!l) {
-		printk(KERN_ERR "security: mls: out of memory\n");
-		return NULL;
-	}
-	memset(l, 0, sizeof(*l));
-
-	rc = next_entry(buf, fp, sizeof buf);
-	if (rc < 0) {
-		printk(KERN_ERR "security: mls: truncated level\n");
-		goto bad;
-	}
-	l->sens = cpu_to_le32(buf[0]);
-
-	if (ebitmap_read(&l->cat, fp)) {
-		printk(KERN_ERR "security: mls:  error reading level "
-		       "categories\n");
-		goto bad;
-	}
-	return l;
-
-bad:
-	kfree(l);
-	return NULL;
-}
-
-
-/*
- * Read a MLS range structure from a policydb binary
- * representation file.
- */
-static int mls_read_range_helper(struct mls_range *r, void *fp)
-{
-	u32 buf[2], items;
-	int rc;
-
-	rc = next_entry(buf, fp, sizeof(u32));
-	if (rc < 0)
-		goto out;
-
-	items = le32_to_cpu(buf[0]);
-	if (items > ARRAY_SIZE(buf)) {
-		printk(KERN_ERR "security: mls:  range overflow\n");
-		rc = -EINVAL;
-		goto out;
-	}
-	rc = next_entry(buf, fp, sizeof(u32) * items);
-	if (rc < 0) {
-		printk(KERN_ERR "security: mls:  truncated range\n");
-		goto out;
-	}
-	r->level[0].sens = le32_to_cpu(buf[0]);
-	if (items > 1) {
-		r->level[1].sens = le32_to_cpu(buf[1]);
-	} else {
-		r->level[1].sens = r->level[0].sens;
-	}
-
-	rc = ebitmap_read(&r->level[0].cat, fp);
-	if (rc) {
-		printk(KERN_ERR "security: mls:  error reading low "
-		       "categories\n");
-		goto out;
-	}
-	if (items > 1) {
-		rc = ebitmap_read(&r->level[1].cat, fp);
-		if (rc) {
-			printk(KERN_ERR "security: mls:  error reading high "
-			       "categories\n");
-			goto bad_high;
-		}
-	} else {
-		rc = ebitmap_cpy(&r->level[1].cat, &r->level[0].cat);
-		if (rc) {
-			printk(KERN_ERR "security: mls:  out of memory\n");
-			goto bad_high;
-		}
-	}
-
-	rc = 0;
-out:
-	return rc;
-bad_high:
-	ebitmap_destroy(&r->level[0].cat);
-	goto out;
-}
-
-int mls_read_range(struct context *c, void *fp)
-{
-	return mls_read_range_helper(&c->range, fp);
-}
-
-
-/*
- * Read a MLS perms structure from a policydb binary
- * representation file.
- */
-int mls_read_class(struct class_datum *cladatum, void *fp)
-{
-	struct mls_perms *p = &cladatum->mlsperms;
-	u32 buf[4];
-	int rc;
-
-	rc = next_entry(buf, fp, sizeof buf);
-	if (rc < 0) {
-		printk(KERN_ERR "security: mls:  truncated mls permissions\n");
-		return -EINVAL;
-	}
-	p->read = le32_to_cpu(buf[0]);
-	p->readby = le32_to_cpu(buf[1]);
-	p->write = le32_to_cpu(buf[2]);
-	p->writeby = le32_to_cpu(buf[3]);
-	return 0;
-}
-
-int mls_read_user(struct user_datum *usrdatum, void *fp)
-{
-	struct mls_range_list *r, *l;
-	int rc;
-	u32 nel, i;
-	u32 buf[1];
-
-	rc = next_entry(buf, fp, sizeof buf);
-	if (rc < 0)
-		goto out;
-	nel = le32_to_cpu(buf[0]);
-	l = NULL;
-	for (i = 0; i < nel; i++) {
-		r = kmalloc(sizeof(*r), GFP_ATOMIC);
-		if (!r) {
-			rc = -ENOMEM;
-			goto out;
-		}
-		memset(r, 0, sizeof(*r));
-
-		rc = mls_read_range_helper(&r->range, fp);
-		if (rc) {
-			kfree(r);
-			goto out;
-		}
-
-		if (l)
-			l->next = r;
-		else
-			usrdatum->ranges = r;
-		l = r;
-	}
-out:
-	return rc;
-}
-
-int mls_read_nlevels(struct policydb *p, void *fp)
-{
-	u32 buf[1];
-	int rc;
-
-	rc = next_entry(buf, fp, sizeof buf);
-	if (rc < 0)
-		return -EINVAL;
-	p->nlevels = le32_to_cpu(buf[0]);
-	return 0;
-}
-
-int mls_read_trusted(struct policydb *p, void *fp)
-{
-	int rc = 0;
-
-	rc = ebitmap_read(&p->trustedreaders, fp);
-	if (rc)
-		goto out;
-	rc = ebitmap_read(&p->trustedwriters, fp);
-	if (rc)
-		goto bad;
-	rc = ebitmap_read(&p->trustedobjects, fp);
-	if (rc)
-		goto bad2;
-out:
-	return rc;
-bad2:
-	ebitmap_destroy(&p->trustedwriters);
-bad:
-	ebitmap_destroy(&p->trustedreaders);
-	goto out;
-}
-
-int sens_index(void *key, void *datum, void *datap)
-{
-	struct policydb *p;
-	struct level_datum *levdatum;
-
-
-	levdatum = datum;
-	p = datap;
-
-	if (!levdatum->isalias)
-		p->p_sens_val_to_name[levdatum->level->sens - 1] = key;
-
-	return 0;
-}
-
-int cat_index(void *key, void *datum, void *datap)
-{
-	struct policydb *p;
-	struct cat_datum *catdatum;
-
-
-	catdatum = datum;
-	p = datap;
-
-
-	if (!catdatum->isalias)
-		p->p_cat_val_to_name[catdatum->value - 1] = key;
-
-	return 0;
-}
-
-int sens_destroy(void *key, void *datum, void *p)
-{
-	struct level_datum *levdatum;
-
-	kfree(key);
-	levdatum = datum;
-	if (!levdatum->isalias) {
-		ebitmap_destroy(&levdatum->level->cat);
-		kfree(levdatum->level);
-	}
-	kfree(datum);
-	return 0;
-}
-
-int cat_destroy(void *key, void *datum, void *p)
-{
-	kfree(key);
-	kfree(datum);
-	return 0;
-}
-
-int sens_read(struct policydb *p, struct hashtab *h, void *fp)
-{
-	char *key = NULL;
-	struct level_datum *levdatum;
-	int rc;
-	u32 buf[2], len;
-
-	levdatum = kmalloc(sizeof(*levdatum), GFP_ATOMIC);
-	if (!levdatum) {
-		rc = -ENOMEM;
-		goto out;
-	}
-	memset(levdatum, 0, sizeof(*levdatum));
-
-	rc = next_entry(buf, fp, sizeof buf);
-	if (rc < 0)
-		goto bad;
-
-	len = le32_to_cpu(buf[0]);
-	levdatum->isalias = le32_to_cpu(buf[1]);
-
-	key = kmalloc(len + 1,GFP_ATOMIC);
-	if (!key) {
-		rc = -ENOMEM;
-		goto bad;
-	}
-	rc = next_entry(key, fp, len);
-	if (rc < 0)
-		goto bad;
-	key[len] = 0;
-
-	levdatum->level = mls_read_level(fp);
-	if (!levdatum->level) {
-		rc = -EINVAL;
-		goto bad;
-	}
-
-	rc = hashtab_insert(h, key, levdatum);
-	if (rc)
-		goto bad;
-out:
-	return rc;
-bad:
-	sens_destroy(key, levdatum, NULL);
-	goto out;
-}
-
-
-int cat_read(struct policydb *p, struct hashtab *h, void *fp)
-{
-	char *key = NULL;
-	struct cat_datum *catdatum;
-	int rc;
-	u32 buf[3], len;
-
-	catdatum = kmalloc(sizeof(*catdatum), GFP_ATOMIC);
-	if (!catdatum) {
-		rc = -ENOMEM;
-		goto out;
-	}
-	memset(catdatum, 0, sizeof(*catdatum));
-
-	rc = next_entry(buf, fp, sizeof buf);
-	if (rc < 0)
-		goto bad;
-
-	len = le32_to_cpu(buf[0]);
-	catdatum->value = le32_to_cpu(buf[1]);
-	catdatum->isalias = le32_to_cpu(buf[2]);
-
-	key = kmalloc(len + 1,GFP_ATOMIC);
-	if (!key) {
-		rc = -ENOMEM;
-		goto bad;
-	}
-	rc = next_entry(key, fp, len);
-	if (rc < 0)
-		goto bad;
-	key[len] = 0;
-
-	rc = hashtab_insert(h, key, catdatum);
-	if (rc)
-		goto bad;
-out:
-	return rc;
-
-bad:
-	cat_destroy(key, catdatum, NULL);
-	goto out;
-}
diff -Nru a/security/selinux/ss/mls.h b/security/selinux/ss/mls.h
--- a/security/selinux/ss/mls.h	2005-03-11 12:51:42 -08:00
+++ b/security/selinux/ss/mls.h	2005-03-11 12:51:42 -08:00
@@ -3,21 +3,22 @@
  *
  * Author : Stephen Smalley, <sds@epoch.ncsc.mil>
  */
+/*
+ * Updated: Trusted Computer Solutions, Inc. <dgoeddel@trustedcs.com>
+ *
+ *	Support for enhanced MLS infrastructure.
+ *
+ * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc.
+ */
+
 #ifndef _SS_MLS_H_
 #define _SS_MLS_H_
 
 #include "context.h"
 #include "policydb.h"
 
-#ifdef CONFIG_SECURITY_SELINUX_MLS
-
-void mls_compute_av(struct context *scontext,
-		    struct context *tcontext,
-		    struct class_datum *tclass,
-		    u32 *allowed);
-
 int mls_compute_context_len(struct context *context);
-int mls_sid_to_context(struct context *context, char **scontext);
+void mls_sid_to_context(struct context *context, char **scontext);
 int mls_context_isvalid(struct policydb *p, struct context *c);
 
 int mls_context_to_sid(char oldc,
@@ -34,66 +35,8 @@
 		    u32 specified,
 		    struct context *newcontext);
 
-int sens_index(void *key, void *datum, void *datap);
-int cat_index(void *key, void *datum, void *datap);
-int sens_destroy(void *key, void *datum, void *p);
-int cat_destroy(void *key, void *datum, void *p);
-int sens_read(struct policydb *p, struct hashtab *h, void *fp);
-int cat_read(struct policydb *p, struct hashtab *h, void *fp);
-
-#define mls_for_user_ranges(user, usercon) { \
-struct mls_range_list *__ranges; \
-for (__ranges = user->ranges; __ranges; __ranges = __ranges->next) { \
-usercon.range = __ranges->range;
-
-#define mls_end_user_ranges } }
-
-#define mls_symtab_names  "levels", "categories",
-#define mls_symtab_sizes  16, 16,
-#define mls_index_f sens_index, cat_index,
-#define mls_destroy_f sens_destroy, cat_destroy,
-#define mls_read_f sens_read, cat_read,
-#define mls_write_f sens_write, cat_write,
-#define mls_policydb_index_others(p) printk(", %d levels", p->nlevels);
-
-#define mls_set_config(config) config |= POLICYDB_CONFIG_MLS
-
-void mls_user_destroy(struct user_datum *usrdatum);
-int mls_read_range(struct context *c, void *fp);
-int mls_read_perm(struct perm_datum *perdatum, void *fp);
-int mls_read_class(struct class_datum *cladatum,  void *fp);
-int mls_read_user(struct user_datum *usrdatum, void *fp);
-int mls_read_nlevels(struct policydb *p, void *fp);
-int mls_read_trusted(struct policydb *p, void *fp);
-
-#else
-
-#define	mls_compute_av(scontext, tcontext, tclass_datum, allowed)
-#define mls_compute_context_len(context) 0
-#define	mls_sid_to_context(context, scontextpp)
-#define mls_context_isvalid(p, c) 1
-#define	mls_context_to_sid(oldc, context_str, context) 0
-#define mls_convert_context(oldp, newp, c) 0
-#define mls_compute_sid(scontext, tcontext, tclass, specified, newcontextp) 0
-#define mls_for_user_ranges(user, usercon)
-#define mls_end_user_ranges
-#define mls_symtab_names
-#define mls_symtab_sizes
-#define mls_index_f
-#define mls_destroy_f
-#define mls_read_f
-#define mls_write_f
-#define mls_policydb_index_others(p)
-#define mls_set_config(config)
-#define mls_user_destroy(usrdatum)
-#define mls_read_range(c, fp) 0
-#define mls_read_perm(p, fp) 0
-#define mls_read_class(c, fp) 0
-#define mls_read_user(u, fp) 0
-#define mls_read_nlevels(p, fp) 0
-#define mls_read_trusted(p, fp) 0
-
-#endif
+int mls_setup_user_range(struct context *fromcon, struct user_datum *user,
+                         struct context *usercon);
 
 #endif	/* _SS_MLS_H */
 
diff -Nru a/security/selinux/ss/mls_types.h b/security/selinux/ss/mls_types.h
--- a/security/selinux/ss/mls_types.h	2005-03-11 12:51:46 -08:00
+++ b/security/selinux/ss/mls_types.h	2005-03-11 12:51:46 -08:00
@@ -3,9 +3,19 @@
  *
  * Author : Stephen Smalley, <sds@epoch.ncsc.mil>
  */
+/*
+ * Updated: Trusted Computer Solutions, Inc. <dgoeddel@trustedcs.com>
+ *
+ *	Support for enhanced MLS infrastructure.
+ *
+ * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc.
+ */
+
 #ifndef _SS_MLS_TYPES_H_
 #define _SS_MLS_TYPES_H_
 
+#include "security.h"
+
 struct mls_level {
 	u32 sens;		/* sensitivity */
 	struct ebitmap cat;	/* category set */
@@ -15,44 +25,32 @@
 	struct mls_level level[2]; /* low == level[0], high == level[1] */
 };
 
-struct mls_range_list {
-	struct mls_range range;
-	struct mls_range_list *next;
-};
-
-#define MLS_RELATION_DOM	1 /* source dominates */
-#define MLS_RELATION_DOMBY	2 /* target dominates */
-#define MLS_RELATION_EQ		4 /* source and target are equivalent */
-#define MLS_RELATION_INCOMP	8 /* source and target are incomparable */
-
-#define mls_level_eq(l1,l2) \
-(((l1).sens == (l2).sens) && ebitmap_cmp(&(l1).cat,&(l2).cat))
-
-#define mls_level_relation(l1,l2) ( \
-(((l1).sens == (l2).sens) && ebitmap_cmp(&(l1).cat,&(l2).cat)) ? \
-				    MLS_RELATION_EQ : \
-(((l1).sens >= (l2).sens) && ebitmap_contains(&(l1).cat, &(l2).cat)) ? \
-				    MLS_RELATION_DOM : \
-(((l2).sens >= (l1).sens) && ebitmap_contains(&(l2).cat, &(l1).cat)) ? \
-				    MLS_RELATION_DOMBY : \
-				    MLS_RELATION_INCOMP )
-
-#define mls_range_contains(r1,r2) \
-((mls_level_relation((r1).level[0], (r2).level[0]) & \
-	  (MLS_RELATION_EQ | MLS_RELATION_DOMBY)) && \
-	 (mls_level_relation((r1).level[1], (r2).level[1]) & \
-	  (MLS_RELATION_EQ | MLS_RELATION_DOM)))
-
-/*
- * Every access vector permission is mapped to a set of MLS base
- * permissions, based on the flow properties of the corresponding
- * operation.
- */
-struct mls_perms {
-	u32 read;     /* permissions that map to `read' */
-	u32 readby;   /* permissions that map to `readby' */
-	u32 write;    /* permissions that map to `write' */
-	u32 writeby;  /* permissions that map to `writeby' */
-};
+static inline int mls_level_eq(struct mls_level *l1, struct mls_level *l2)
+{
+	if (!selinux_mls_enabled)
+		return 1;
+
+	return ((l1->sens == l2->sens) &&
+	        ebitmap_cmp(&l1->cat, &l2->cat));
+}
+
+static inline int mls_level_dom(struct mls_level *l1, struct mls_level *l2)
+{
+	if (!selinux_mls_enabled)
+		return 1;
+
+	return ((l1->sens >= l2->sens) &&
+	        ebitmap_contains(&l1->cat, &l2->cat));
+}
+
+#define mls_level_incomp(l1, l2) \
+(!mls_level_dom((l1), (l2)) && !mls_level_dom((l2), (l1)))
+
+#define mls_level_between(l1, l2, l3) \
+(mls_level_dom((l1), (l2)) && mls_level_dom((l3), (l1)))
+
+#define mls_range_contains(r1, r2) \
+(mls_level_dom(&(r2).level[0], &(r1).level[0]) && \
+ mls_level_dom(&(r1).level[1], &(r2).level[1]))
 
 #endif	/* _SS_MLS_TYPES_H_ */
diff -Nru a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c
--- a/security/selinux/ss/policydb.c	2005-03-11 12:51:42 -08:00
+++ b/security/selinux/ss/policydb.c	2005-03-11 12:51:42 -08:00
@@ -4,10 +4,16 @@
  * Author : Stephen Smalley, <sds@epoch.ncsc.mil>
  */
 
-/* Updated: Frank Mayer <mayerf@tresys.com> and Karl MacMillan <kmacmillan@tresys.com>
+/*
+ * Updated: Trusted Computer Solutions, Inc. <dgoeddel@trustedcs.com>
+ *
+ *	Support for enhanced MLS infrastructure.
+ *
+ * Updated: Frank Mayer <mayerf@tresys.com> and Karl MacMillan <kmacmillan@tresys.com>
  *
  * 	Added conditional policy language extensions
  *
+ * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc.
  * Copyright (C) 2003 - 2004 Tresys Technology, LLC
  *	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
@@ -33,19 +39,23 @@
 	"roles",
 	"types",
 	"users",
-	mls_symtab_names
-	"bools"
+	"bools",
+	"levels",
+	"categories",
 };
 #endif
 
+int selinux_mls_enabled = 0;
+
 static unsigned int symtab_sizes[SYM_NUM] = {
 	2,
 	32,
 	16,
 	512,
 	128,
-	mls_symtab_sizes
-	16
+	16,
+	16,
+	16,
 };
 
 struct policydb_compat_info {
@@ -58,21 +68,26 @@
 static struct policydb_compat_info policydb_compat[] = {
 	{
 		.version        = POLICYDB_VERSION_BASE,
-		.sym_num        = SYM_NUM - 1,
+		.sym_num        = SYM_NUM - 3,
 		.ocon_num       = OCON_NUM - 1,
 	},
 	{
 		.version        = POLICYDB_VERSION_BOOL,
-		.sym_num        = SYM_NUM,
+		.sym_num        = SYM_NUM - 2,
 		.ocon_num       = OCON_NUM - 1,
 	},
 	{
 		.version        = POLICYDB_VERSION_IPV6,
-		.sym_num        = SYM_NUM,
+		.sym_num        = SYM_NUM - 2,
 		.ocon_num       = OCON_NUM,
 	},
 	{
 		.version        = POLICYDB_VERSION_NLCLASS,
+		.sym_num        = SYM_NUM - 2,
+		.ocon_num       = OCON_NUM,
+	},
+	{
+		.version        = POLICYDB_VERSION_MLS,
 		.sym_num        = SYM_NUM,
 		.ocon_num       = OCON_NUM,
 	},
@@ -252,6 +267,41 @@
 	return 0;
 }
 
+static int sens_index(void *key, void *datum, void *datap)
+{
+	struct policydb *p;
+	struct level_datum *levdatum;
+
+	levdatum = datum;
+	p = datap;
+
+	if (!levdatum->isalias) {
+		if (!levdatum->level->sens ||
+		    levdatum->level->sens > p->p_levels.nprim)
+			return -EINVAL;
+		p->p_sens_val_to_name[levdatum->level->sens - 1] = key;
+	}
+
+	return 0;
+}
+
+static int cat_index(void *key, void *datum, void *datap)
+{
+	struct policydb *p;
+	struct cat_datum *catdatum;
+
+	catdatum = datum;
+	p = datap;
+
+	if (!catdatum->isalias) {
+		if (!catdatum->value || catdatum->value > p->p_cats.nprim)
+			return -EINVAL;
+		p->p_cat_val_to_name[catdatum->value - 1] = key;
+	}
+
+	return 0;
+}
+
 static int (*index_f[SYM_NUM]) (void *key, void *datum, void *datap) =
 {
 	common_index,
@@ -259,8 +309,9 @@
 	role_index,
 	type_index,
 	user_index,
-	mls_index_f
-	cond_index_bool
+	cond_index_bool,
+	sens_index,
+	cat_index,
 };
 
 /*
@@ -333,7 +384,9 @@
 
 	printk(KERN_INFO "security:  %d users, %d roles, %d types, %d bools",
 	       p->p_users.nprim, p->p_roles.nprim, p->p_types.nprim, p->p_bools.nprim);
-	mls_policydb_index_others(p);
+	if (selinux_mls_enabled)
+		printk(", %d sens, %d cats", p->p_levels.nprim,
+		       p->p_cats.nprim);
 	printk("\n");
 
 	printk(KERN_INFO "security:  %d classes, %d rules\n",
@@ -429,6 +482,21 @@
 		constraint = constraint->next;
 		kfree(ctemp);
 	}
+
+	constraint = cladatum->validatetrans;
+	while (constraint) {
+		e = constraint->expr;
+		while (e) {
+			ebitmap_destroy(&e->names);
+			etmp = e;
+			e = e->next;
+			kfree(etmp);
+		}
+		ctemp = constraint;
+		constraint = constraint->next;
+		kfree(ctemp);
+	}
+
 	kfree(cladatum->comkey);
 	kfree(datum);
 	return 0;
@@ -460,7 +528,28 @@
 	kfree(key);
 	usrdatum = datum;
 	ebitmap_destroy(&usrdatum->roles);
-	mls_user_destroy(usrdatum);
+	ebitmap_destroy(&usrdatum->range.level[0].cat);
+	ebitmap_destroy(&usrdatum->range.level[1].cat);
+	ebitmap_destroy(&usrdatum->dfltlevel.cat);
+	kfree(datum);
+	return 0;
+}
+
+static int sens_destroy(void *key, void *datum, void *p)
+{
+	struct level_datum *levdatum;
+
+	kfree(key);
+	levdatum = datum;
+	ebitmap_destroy(&levdatum->level->cat);
+	kfree(levdatum->level);
+	kfree(datum);
+	return 0;
+}
+
+static int cat_destroy(void *key, void *datum, void *p)
+{
+	kfree(key);
 	kfree(datum);
 	return 0;
 }
@@ -472,8 +561,9 @@
 	role_destroy,
 	type_destroy,
 	user_destroy,
-	mls_destroy_f
-	cond_destroy_bool
+	cond_destroy_bool,
+	sens_destroy,
+	cat_destroy,
 };
 
 void ocontext_destroy(struct ocontext *c, int i)
@@ -624,6 +714,65 @@
 }
 
 /*
+ * Read a MLS range structure from a policydb binary
+ * representation file.
+ */
+static int mls_read_range_helper(struct mls_range *r, void *fp)
+{
+	u32 buf[2], items;
+	int rc;
+
+	rc = next_entry(buf, fp, sizeof(u32));
+	if (rc < 0)
+		goto out;
+
+	items = le32_to_cpu(buf[0]);
+	if (items > ARRAY_SIZE(buf)) {
+		printk(KERN_ERR "security: mls:  range overflow\n");
+		rc = -EINVAL;
+		goto out;
+	}
+	rc = next_entry(buf, fp, sizeof(u32) * items);
+	if (rc < 0) {
+		printk(KERN_ERR "security: mls:  truncated range\n");
+		goto out;
+	}
+	r->level[0].sens = le32_to_cpu(buf[0]);
+	if (items > 1)
+		r->level[1].sens = le32_to_cpu(buf[1]);
+	else
+		r->level[1].sens = r->level[0].sens;
+
+	rc = ebitmap_read(&r->level[0].cat, fp);
+	if (rc) {
+		printk(KERN_ERR "security: mls:  error reading low "
+		       "categories\n");
+		goto out;
+	}
+	if (items > 1) {
+		rc = ebitmap_read(&r->level[1].cat, fp);
+		if (rc) {
+			printk(KERN_ERR "security: mls:  error reading high "
+			       "categories\n");
+			goto bad_high;
+		}
+	} else {
+		rc = ebitmap_cpy(&r->level[1].cat, &r->level[0].cat);
+		if (rc) {
+			printk(KERN_ERR "security: mls:  out of memory\n");
+			goto bad_high;
+		}
+	}
+
+	rc = 0;
+out:
+	return rc;
+bad_high:
+	ebitmap_destroy(&r->level[0].cat);
+	goto out;
+}
+
+/*
  * Read and validate a security context structure
  * from a policydb binary representation file.
  */
@@ -642,11 +791,13 @@
 	c->user = le32_to_cpu(buf[0]);
 	c->role = le32_to_cpu(buf[1]);
 	c->type = le32_to_cpu(buf[2]);
-	if (mls_read_range(c, fp)) {
-		printk(KERN_ERR "security: error reading MLS range of "
-		       "context\n");
-		rc = -EINVAL;
-		goto out;
+	if (p->policyvers >= POLICYDB_VERSION_MLS) {
+		if (mls_read_range_helper(&c->range, fp)) {
+			printk(KERN_ERR "security: error reading MLS range of "
+			       "context\n");
+			rc = -EINVAL;
+			goto out;
+		}
 	}
 
 	if (!policydb_context_isvalid(p, c)) {
@@ -684,9 +835,6 @@
 
 	len = le32_to_cpu(buf[0]);
 	perdatum->value = le32_to_cpu(buf[1]);
-	rc = mls_read_perm(perdatum, fp);
-	if (rc)
-		goto bad;
 
 	key = kmalloc(len + 1,GFP_KERNEL);
 	if (!key) {
@@ -761,14 +909,97 @@
 	goto out;
 }
 
+static int read_cons_helper(struct constraint_node **nodep, int ncons,
+                            int allowxtarget, void *fp)
+{
+	struct constraint_node *c, *lc;
+	struct constraint_expr *e, *le;
+	u32 buf[3], nexpr;
+	int rc, i, j, depth;
+
+	lc = NULL;
+	for (i = 0; i < ncons; i++) {
+		c = kmalloc(sizeof(*c), GFP_KERNEL);
+		if (!c)
+			return -ENOMEM;
+		memset(c, 0, sizeof(*c));
+
+		if (lc) {
+			lc->next = c;
+		} else {
+			*nodep = c;
+		}
+
+		rc = next_entry(buf, fp, (sizeof(u32) * 2));
+		if (rc < 0)
+			return rc;
+		c->permissions = le32_to_cpu(buf[0]);
+		nexpr = le32_to_cpu(buf[1]);
+		le = NULL;
+		depth = -1;
+		for (j = 0; j < nexpr; j++) {
+			e = kmalloc(sizeof(*e), GFP_KERNEL);
+			if (!e)
+				return -ENOMEM;
+			memset(e, 0, sizeof(*e));
+
+			if (le) {
+				le->next = e;
+			} else {
+				c->expr = e;
+			}
+
+			rc = next_entry(buf, fp, (sizeof(u32) * 3));
+			if (rc < 0)
+				return rc;
+			e->expr_type = le32_to_cpu(buf[0]);
+			e->attr = le32_to_cpu(buf[1]);
+			e->op = le32_to_cpu(buf[2]);
+
+			switch (e->expr_type) {
+			case CEXPR_NOT:
+				if (depth < 0)
+					return -EINVAL;
+				break;
+			case CEXPR_AND:
+			case CEXPR_OR:
+				if (depth < 1)
+					return -EINVAL;
+				depth--;
+				break;
+			case CEXPR_ATTR:
+				if (depth == (CEXPR_MAXDEPTH - 1))
+					return -EINVAL;
+				depth++;
+				break;
+			case CEXPR_NAMES:
+				if (!allowxtarget && (e->attr & CEXPR_XTARGET))
+					return -EINVAL;
+				if (depth == (CEXPR_MAXDEPTH - 1))
+					return -EINVAL;
+				depth++;
+				if (ebitmap_read(&e->names, fp))
+					return -EINVAL;
+				break;
+			default:
+				return -EINVAL;
+			}
+			le = e;
+		}
+		if (depth != 0)
+			return -EINVAL;
+		lc = c;
+	}
+
+	return 0;
+}
+
 static int class_read(struct policydb *p, struct hashtab *h, void *fp)
 {
 	char *key = NULL;
 	struct class_datum *cladatum;
-	struct constraint_node *c, *lc;
-	struct constraint_expr *e, *le;
-	u32 buf[6], len, len2, ncons, nexpr, nel;
-	int i, j, depth, rc;
+	u32 buf[6], len, len2, ncons, nel;
+	int i, rc;
 
 	cladatum = kmalloc(sizeof(*cladatum), GFP_KERNEL);
 	if (!cladatum) {
@@ -829,87 +1060,21 @@
 			goto bad;
 	}
 
-	lc = NULL;
-	for (i = 0; i < ncons; i++) {
-		c = kmalloc(sizeof(*c), GFP_KERNEL);
-		if (!c) {
-			rc = -ENOMEM;
-			goto bad;
-		}
-		memset(c, 0, sizeof(*c));
-
-		if (lc) {
-			lc->next = c;
-		} else {
-			cladatum->constraints = c;
-		}
+	rc = read_cons_helper(&cladatum->constraints, ncons, 0, fp);
+	if (rc)
+		goto bad;
 
-		rc = next_entry(buf, fp, sizeof(u32)*2);
+	if (p->policyvers >= POLICYDB_VERSION_VALIDATETRANS) {
+		/* grab the validatetrans rules */
+		rc = next_entry(buf, fp, sizeof(u32));
 		if (rc < 0)
 			goto bad;
-		c->permissions = le32_to_cpu(buf[0]);
-		nexpr = le32_to_cpu(buf[1]);
-		le = NULL;
-		depth = -1;
-		for (j = 0; j < nexpr; j++) {
-			e = kmalloc(sizeof(*e), GFP_KERNEL);
-			if (!e) {
-				rc = -ENOMEM;
-				goto bad;
-			}
-			memset(e, 0, sizeof(*e));
-
-			if (le) {
-				le->next = e;
-			} else {
-				c->expr = e;
-			}
-
-			rc = next_entry(buf, fp, sizeof(u32)*3);
-			if (rc < 0)
-				goto bad;
-			e->expr_type = le32_to_cpu(buf[0]);
-			e->attr = le32_to_cpu(buf[1]);
-			e->op = le32_to_cpu(buf[2]);
-
-			rc = -EINVAL;
-			switch (e->expr_type) {
-			case CEXPR_NOT:
-				if (depth < 0)
-					goto bad;
-				break;
-			case CEXPR_AND:
-			case CEXPR_OR:
-				if (depth < 1)
-					goto bad;
-				depth--;
-				break;
-			case CEXPR_ATTR:
-				if (depth == (CEXPR_MAXDEPTH-1))
-					goto bad;
-				depth++;
-				break;
-			case CEXPR_NAMES:
-				if (depth == (CEXPR_MAXDEPTH-1))
-					goto bad;
-				depth++;
-				if (ebitmap_read(&e->names, fp))
-					goto bad;
-				break;
-			default:
-				goto bad;
-			}
-			le = e;
-		}
-		if (depth != 0)
+		ncons = le32_to_cpu(buf[0]);
+		rc = read_cons_helper(&cladatum->validatetrans, ncons, 1, fp);
+		if (rc)
 			goto bad;
-		lc = c;
 	}
 
-	rc = mls_read_class(cladatum, fp);
-	if (rc)
-		goto bad;
-
 	rc = hashtab_insert(h, key, cladatum);
 	if (rc)
 		goto bad;
@@ -1024,6 +1189,36 @@
 	goto out;
 }
 
+
+/*
+ * Read a MLS level structure from a policydb binary
+ * representation file.
+ */
+static int mls_read_level(struct mls_level *lp, void *fp)
+{
+	u32 buf[1];
+	int rc;
+
+	memset(lp, 0, sizeof(*lp));
+
+	rc = next_entry(buf, fp, sizeof buf);
+	if (rc < 0) {
+		printk(KERN_ERR "security: mls: truncated level\n");
+		goto bad;
+	}
+	lp->sens = le32_to_cpu(buf[0]);
+
+	if (ebitmap_read(&lp->cat, fp)) {
+		printk(KERN_ERR "security: mls:  error reading level "
+		       "categories\n");
+		goto bad;
+	}
+	return 0;
+
+bad:
+	return -EINVAL;
+}
+
 static int user_read(struct policydb *p, struct hashtab *h, void *fp)
 {
 	char *key = NULL;
@@ -1031,7 +1226,6 @@
 	int rc;
 	u32 buf[2], len;
 
-
 	usrdatum = kmalloc(sizeof(*usrdatum), GFP_KERNEL);
 	if (!usrdatum) {
 		rc = -ENOMEM;
@@ -1060,9 +1254,14 @@
 	if (rc)
 		goto bad;
 
-	rc = mls_read_user(usrdatum, fp);
-	if (rc)
-		goto bad;
+	if (p->policyvers >= POLICYDB_VERSION_MLS) {
+		rc = mls_read_range_helper(&usrdatum->range, fp);
+		if (rc)
+			goto bad;
+		rc = mls_read_level(&usrdatum->dfltlevel, fp);
+		if (rc)
+			goto bad;
+	}
 
 	rc = hashtab_insert(h, key, usrdatum);
 	if (rc)
@@ -1074,6 +1273,100 @@
 	goto out;
 }
 
+static int sens_read(struct policydb *p, struct hashtab *h, void *fp)
+{
+	char *key = NULL;
+	struct level_datum *levdatum;
+	int rc;
+	u32 buf[2], len;
+
+	levdatum = kmalloc(sizeof(*levdatum), GFP_ATOMIC);
+	if (!levdatum) {
+		rc = -ENOMEM;
+		goto out;
+	}
+	memset(levdatum, 0, sizeof(*levdatum));
+
+	rc = next_entry(buf, fp, sizeof buf);
+	if (rc < 0)
+		goto bad;
+
+	len = le32_to_cpu(buf[0]);
+	levdatum->isalias = le32_to_cpu(buf[1]);
+
+	key = kmalloc(len + 1,GFP_ATOMIC);
+	if (!key) {
+		rc = -ENOMEM;
+		goto bad;
+	}
+	rc = next_entry(key, fp, len);
+	if (rc < 0)
+		goto bad;
+	key[len] = 0;
+
+	levdatum->level = kmalloc(sizeof(struct mls_level), GFP_ATOMIC);
+	if (!levdatum->level) {
+		rc = -ENOMEM;
+		goto bad;
+	}
+	if (mls_read_level(levdatum->level, fp)) {
+		rc = -EINVAL;
+		goto bad;
+	}
+
+	rc = hashtab_insert(h, key, levdatum);
+	if (rc)
+		goto bad;
+out:
+	return rc;
+bad:
+	sens_destroy(key, levdatum, NULL);
+	goto out;
+}
+
+static int cat_read(struct policydb *p, struct hashtab *h, void *fp)
+{
+	char *key = NULL;
+	struct cat_datum *catdatum;
+	int rc;
+	u32 buf[3], len;
+
+	catdatum = kmalloc(sizeof(*catdatum), GFP_ATOMIC);
+	if (!catdatum) {
+		rc = -ENOMEM;
+		goto out;
+	}
+	memset(catdatum, 0, sizeof(*catdatum));
+
+	rc = next_entry(buf, fp, sizeof buf);
+	if (rc < 0)
+		goto bad;
+
+	len = le32_to_cpu(buf[0]);
+	catdatum->value = le32_to_cpu(buf[1]);
+	catdatum->isalias = le32_to_cpu(buf[2]);
+
+	key = kmalloc(len + 1,GFP_ATOMIC);
+	if (!key) {
+		rc = -ENOMEM;
+		goto bad;
+	}
+	rc = next_entry(key, fp, len);
+	if (rc < 0)
+		goto bad;
+	key[len] = 0;
+
+	rc = hashtab_insert(h, key, catdatum);
+	if (rc)
+		goto bad;
+out:
+	return rc;
+
+bad:
+	cat_destroy(key, catdatum, NULL);
+	goto out;
+}
+
 static int (*read_f[SYM_NUM]) (struct policydb *p, struct hashtab *h, void *fp) =
 {
 	common_read,
@@ -1081,12 +1374,12 @@
 	role_read,
 	type_read,
 	user_read,
-	mls_read_f
-	cond_read_bool
+	cond_read_bool,
+	sens_read,
+	cat_read,
 };
 
-#define mls_config(x) \
-       ((x) & POLICYDB_CONFIG_MLS) ? "mls" : "no_mls"
+extern int ss_initialized;
 
 /*
  * Read the configuration data from a policy database binary
@@ -1102,9 +1395,9 @@
 	u32 buf[8], len, len2, config, nprim, nel, nel2;
 	char *policydb_str;
 	struct policydb_compat_info *info;
+	struct range_trans *rt, *lrt;
 
 	config = 0;
-	mls_set_config(config);
 
 	rc = policydb_init(p);
 	if (rc)
@@ -1172,14 +1465,27 @@
 	    	goto bad;
 	}
 
-	if (buf[1] != config) {
-		printk(KERN_ERR "security:  policydb configuration (%s) does "
-		       "not match my configuration (%s)\n",
-		       mls_config(buf[1]),
-		       mls_config(config));
-		goto bad;
-	}
+	if ((buf[1] & POLICYDB_CONFIG_MLS)) {
+		if (ss_initialized && !selinux_mls_enabled) {
+			printk(KERN_ERR "Cannot switch between non-MLS and MLS "
+			       "policies\n");
+			goto bad;
+		}
+		selinux_mls_enabled = 1;
+		config |= POLICYDB_CONFIG_MLS;
 
+		if (p->policyvers < POLICYDB_VERSION_MLS) {
+			printk(KERN_ERR "security policydb version %d (MLS) "
+			       "not backwards compatible\n", p->policyvers);
+			goto bad;
+		}
+	} else {
+		if (ss_initialized && selinux_mls_enabled) {
+			printk(KERN_ERR "Cannot switch between MLS and non-MLS "
+			       "policies\n");
+			goto bad;
+		}
+	}
 
 	info = policydb_lookup_compat(p->policyvers);
 	if (!info) {
@@ -1195,10 +1501,6 @@
 		goto bad;
 	}
 
-	rc = mls_read_nlevels(p, fp);
-	if (rc)
-		goto bad;
-
 	for (i = 0; i < info->sym_num; i++) {
 		rc = next_entry(buf, fp, sizeof(u32)*2);
 		if (rc < 0)
@@ -1499,9 +1801,34 @@
 		}
 	}
 
-	rc = mls_read_trusted(p, fp);
-	if (rc)
-		goto bad;
+	if (p->policyvers >= POLICYDB_VERSION_MLS) {
+		rc = next_entry(buf, fp, sizeof(u32));
+		if (rc < 0)
+			goto bad;
+		nel = le32_to_cpu(buf[0]);
+		lrt = NULL;
+		for (i = 0; i < nel; i++) {
+			rt = kmalloc(sizeof(*rt), GFP_KERNEL);
+			if (!rt) {
+				rc = -ENOMEM;
+				goto bad;
+			}
+			memset(rt, 0, sizeof(*rt));
+			if (lrt)
+				lrt->next = rt;
+			else
+				p->range_tr = rt;
+			rc = next_entry(buf, fp, (sizeof(u32) * 2));
+			if (rc < 0)
+				goto bad;
+			rt->dom = le32_to_cpu(buf[0]);
+			rt->type = le32_to_cpu(buf[1]);
+			rc = mls_read_range_helper(&rt->range, fp);
+			if (rc)
+				goto bad;
+			lrt = rt;
+		}
+	}
 
 	rc = 0;
 out:
diff -Nru a/security/selinux/ss/policydb.h b/security/selinux/ss/policydb.h
--- a/security/selinux/ss/policydb.h	2005-03-11 12:51:47 -08:00
+++ b/security/selinux/ss/policydb.h	2005-03-11 12:51:47 -08:00
@@ -5,10 +5,16 @@
  * Author : Stephen Smalley, <sds@epoch.ncsc.mil>
  */
 
-/* Updated: Frank Mayer <mayerf@tresys.com> and Karl MacMillan <kmacmillan@tresys.com>
+/*
+ * Updated: Trusted Computer Solutions, Inc. <dgoeddel@trustedcs.com>
+ *
+ *	Support for enhanced MLS infrastructure.
+ *
+ * Updated: Frank Mayer <mayerf@tresys.com> and Karl MacMillan <kmacmillan@tresys.com>
  *
  * 	Added conditional policy language extensions
  *
+ * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc.
  * Copyright (C) 2003 - 2004 Tresys Technology, LLC
  *	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
@@ -34,13 +40,6 @@
 /* Permission attributes */
 struct perm_datum {
 	u32 value;		/* permission bit + 1 */
-#ifdef CONFIG_SECURITY_SELINUX_MLS
-#define MLS_BASE_READ    1	/* MLS base permission `read' */
-#define MLS_BASE_WRITE   2	/* MLS base permission `write' */
-#define MLS_BASE_READBY  4	/* MLS base permission `readby' */
-#define MLS_BASE_WRITEBY 8	/* MLS base permission `writeby' */
-	u32 base_perms;		/* MLS base permission mask */
-#endif
 };
 
 /* Attributes of a common prefix for access vectors */
@@ -56,9 +55,7 @@
 	struct common_datum *comdatum;	/* common datum */
 	struct symtab permissions;	/* class-specific permission symbol table */
 	struct constraint_node *constraints;	/* constraints on class permissions */
-#ifdef CONFIG_SECURITY_SELINUX_MLS
-	struct mls_perms mlsperms;	/* MLS base permission masks */
-#endif
+	struct constraint_node *validatetrans;	/* special transition rules */
 };
 
 /* Role attributes */
@@ -91,13 +88,11 @@
 struct user_datum {
 	u32 value;			/* internal user value */
 	struct ebitmap roles;		/* set of authorized roles for user */
-#ifdef CONFIG_SECURITY_SELINUX_MLS
-	struct mls_range_list *ranges;	/* list of authorized MLS ranges for user */
-#endif
+	struct mls_range range;		/* MLS range (min - max) for user */
+	struct mls_level dfltlevel;	/* default login MLS level for user */
 };
 
 
-#ifdef CONFIG_SECURITY_SELINUX_MLS
 /* Sensitivity attributes */
 struct level_datum {
 	struct mls_level *level;	/* sensitivity and associated categories */
@@ -109,7 +104,13 @@
 	u32 value;		/* internal category bit + 1 */
 	unsigned char isalias;  /* is this category an alias for another? */
 };
-#endif
+
+struct range_trans {
+	u32 dom;			/* current process domain */
+	u32 type;			/* program executable type */
+	struct mls_range range;		/* new range */
+	struct range_trans *next;
+};
 
 /* Boolean data type */
 struct cond_bool_datum {
@@ -164,15 +165,10 @@
 #define SYM_ROLES   2
 #define SYM_TYPES   3
 #define SYM_USERS   4
-#ifdef CONFIG_SECURITY_SELINUX_MLS
-#define SYM_LEVELS  5
-#define SYM_CATS    6
-#define SYM_BOOLS   7
-#define SYM_NUM     8
-#else
 #define SYM_BOOLS   5
-#define SYM_NUM     6
-#endif
+#define SYM_LEVELS  6
+#define SYM_CATS    7
+#define SYM_NUM     8
 
 /* object context array indices */
 #define OCON_ISID  0	/* initial SIDs */
@@ -193,9 +189,9 @@
 #define p_roles symtab[SYM_ROLES]
 #define p_types symtab[SYM_TYPES]
 #define p_users symtab[SYM_USERS]
+#define p_bools symtab[SYM_BOOLS]
 #define p_levels symtab[SYM_LEVELS]
 #define p_cats symtab[SYM_CATS]
-#define p_bools symtab[SYM_BOOLS]
 
 	/* symbol names indexed by (value - 1) */
 	char **sym_val_to_name[SYM_NUM];
@@ -204,9 +200,9 @@
 #define p_role_val_to_name sym_val_to_name[SYM_ROLES]
 #define p_type_val_to_name sym_val_to_name[SYM_TYPES]
 #define p_user_val_to_name sym_val_to_name[SYM_USERS]
+#define p_bool_val_to_name sym_val_to_name[SYM_BOOLS]
 #define p_sens_val_to_name sym_val_to_name[SYM_LEVELS]
 #define p_cat_val_to_name sym_val_to_name[SYM_CATS]
-#define p_bool_val_to_name sym_val_to_name[SYM_BOOLS]
 
 	/* class, role, and user attributes indexed by (value - 1) */
 	struct class_datum **class_val_to_struct;
@@ -238,14 +234,8 @@
 	   fixed labeling behavior. */
   	struct genfs *genfs;
 
-#ifdef CONFIG_SECURITY_SELINUX_MLS
-	/* number of legitimate MLS levels */
-	u32 nlevels;
-
-	struct ebitmap trustedreaders;
-	struct ebitmap trustedwriters;
-	struct ebitmap trustedobjects;
-#endif
+	/* range transitions */
+	struct range_trans *range_tr;
 
 	unsigned int policyvers;
 };
diff -Nru a/security/selinux/ss/services.c b/security/selinux/ss/services.c
--- a/security/selinux/ss/services.c	2005-03-11 12:51:51 -08:00
+++ b/security/selinux/ss/services.c	2005-03-11 12:51:51 -08:00
@@ -4,17 +4,17 @@
  * Authors : Stephen Smalley, <sds@epoch.ncsc.mil>
  *           James Morris <jmorris@redhat.com>
  *
- *  Copyright (C) 2003 Red Hat, Inc., James Morris <jmorris@redhat.com>
+ * Updated: Trusted Computer Solutions, Inc. <dgoeddel@trustedcs.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.
+ *	Support for enhanced MLS infrastructure.
  *
  * Updated: Frank Mayer <mayerf@tresys.com> and Karl MacMillan <kmacmillan@tresys.com>
  *
  * 	Added conditional policy language extensions
  *
+ * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc.
  * Copyright (C) 2003 - 2004 Tresys Technology, LLC
+ * Copyright (C) 2003 Red Hat, Inc., James Morris <jmorris@redhat.com>
  *	This program is free software; you can redistribute it and/or modify
  *  	it under the terms of the GNU General Public License as published by
  *	the Free Software Foundation, version 2.
@@ -64,18 +64,30 @@
  */
 static u32 latest_granting = 0;
 
+/* Forward declarations. */
+int context_struct_to_string(struct context *context, char **scontext,
+                             u32 *scontext_len);
+
 /*
  * Return the boolean value of a constraint expression
  * when it is applied to the specified source and target
  * security contexts.
+ *
+ * xcontext is a special beast...  It is used by the validatetrans rules
+ * only.  For these rules, scontext is the context before the transition,
+ * tcontext is the context after the transition, and xcontext is the context
+ * of the process performing the transition.  All other callers of
+ * constraint_expr_eval should pass in NULL for xcontext.
  */
-static int constraint_expr_eval(struct context *scontext,
-				struct context *tcontext,
-				struct constraint_expr *cexpr)
+int constraint_expr_eval(struct context *scontext,
+                         struct context *tcontext,
+                         struct context *xcontext,
+                         struct constraint_expr *cexpr)
 {
 	u32 val1, val2;
 	struct context *c;
 	struct role_datum *r1, *r2;
+	struct mls_level *l1, *l2;
 	struct constraint_expr *e;
 	int s[CEXPR_MAXDEPTH];
 	int sp = -1;
@@ -132,6 +144,52 @@
 					break;
 				}
 				break;
+			case CEXPR_L1L2:
+				l1 = &(scontext->range.level[0]);
+				l2 = &(tcontext->range.level[0]);
+				goto mls_ops;
+			case CEXPR_L1H2:
+				l1 = &(scontext->range.level[0]);
+				l2 = &(tcontext->range.level[1]);
+				goto mls_ops;
+			case CEXPR_H1L2:
+				l1 = &(scontext->range.level[1]);
+				l2 = &(tcontext->range.level[0]);
+				goto mls_ops;
+			case CEXPR_H1H2:
+				l1 = &(scontext->range.level[1]);
+				l2 = &(tcontext->range.level[1]);
+				goto mls_ops;
+			case CEXPR_L1H1:
+				l1 = &(scontext->range.level[0]);
+				l2 = &(scontext->range.level[1]);
+				goto mls_ops;
+			case CEXPR_L2H2:
+				l1 = &(tcontext->range.level[0]);
+				l2 = &(tcontext->range.level[1]);
+				goto mls_ops;
+mls_ops:
+			switch (e->op) {
+			case CEXPR_EQ:
+				s[++sp] = mls_level_eq(l1, l2);
+				continue;
+			case CEXPR_NEQ:
+				s[++sp] = !mls_level_eq(l1, l2);
+				continue;
+			case CEXPR_DOM:
+				s[++sp] = mls_level_dom(l1, l2);
+				continue;
+			case CEXPR_DOMBY:
+				s[++sp] = mls_level_dom(l2, l1);
+				continue;
+			case CEXPR_INCOMP:
+				s[++sp] = mls_level_incomp(l2, l1);
+				continue;
+			default:
+				BUG();
+				return 0;
+			}
+			break;
 			default:
 				BUG();
 				return 0;
@@ -155,6 +213,13 @@
 			c = scontext;
 			if (e->attr & CEXPR_TARGET)
 				c = tcontext;
+			else if (e->attr & CEXPR_XTARGET) {
+				c = xcontext;
+				if (!c) {
+					BUG();
+					return 0;
+				}
+			}
 			if (e->attr & CEXPR_USER)
 				val1 = c->user;
 			else if (e->attr & CEXPR_ROLE)
@@ -252,17 +317,13 @@
 	cond_compute_av(&policydb.te_cond_avtab, &avkey, avd);
 
 	/*
-	 * Remove any permissions prohibited by the MLS policy.
-	 */
-	mls_compute_av(scontext, tcontext, tclass_datum, &avd->allowed);
-
-	/*
-	 * Remove any permissions prohibited by a constraint.
+	 * Remove any permissions prohibited by a constraint (this includes
+	 * the MLS policy).
 	 */
 	constraint = tclass_datum->constraints;
 	while (constraint) {
 		if ((constraint->permissions & (avd->allowed)) &&
-		    !constraint_expr_eval(scontext, tcontext,
+		    !constraint_expr_eval(scontext, tcontext, NULL,
 					  constraint->expr)) {
 			avd->allowed = (avd->allowed) & ~(constraint->permissions);
 		}
@@ -290,6 +351,108 @@
 	return 0;
 }
 
+static int security_validtrans_handle_fail(struct context *ocontext,
+                                           struct context *ncontext,
+                                           struct context *tcontext,
+                                           u16 tclass)
+{
+	char *o = NULL, *n = NULL, *t = NULL;
+	u32 olen, nlen, tlen;
+
+	if (context_struct_to_string(ocontext, &o, &olen) < 0)
+		goto out;
+	if (context_struct_to_string(ncontext, &n, &nlen) < 0)
+		goto out;
+	if (context_struct_to_string(tcontext, &t, &tlen) < 0)
+		goto out;
+	audit_log(current->audit_context,
+	          "security_validate_transition:  denied for"
+	          " oldcontext=%s newcontext=%s taskcontext=%s tclass=%s",
+	          o, n, t, policydb.p_class_val_to_name[tclass-1]);
+out:
+	kfree(o);
+	kfree(n);
+	kfree(t);
+
+	if (!selinux_enforcing)
+		return 0;
+	return -EPERM;
+}
+
+int security_validate_transition(u32 oldsid, u32 newsid, u32 tasksid,
+                                 u16 tclass)
+{
+	struct context *ocontext;
+	struct context *ncontext;
+	struct context *tcontext;
+	struct class_datum *tclass_datum;
+	struct constraint_node *constraint;
+	int rc = 0;
+
+	if (!ss_initialized)
+		return 0;
+
+	POLICY_RDLOCK;
+
+	/*
+	 * Remap extended Netlink classes for old policy versions.
+	 * Do this here rather than socket_type_to_security_class()
+	 * in case a newer policy version is loaded, allowing sockets
+	 * to remain in the correct class.
+	 */
+	if (policydb_loaded_version < POLICYDB_VERSION_NLCLASS)
+		if (tclass >= SECCLASS_NETLINK_ROUTE_SOCKET &&
+		    tclass <= SECCLASS_NETLINK_DNRT_SOCKET)
+			tclass = SECCLASS_NETLINK_SOCKET;
+
+	if (!tclass || tclass > policydb.p_classes.nprim) {
+		printk(KERN_ERR "security_validate_transition:  "
+		       "unrecognized class %d\n", tclass);
+		rc = -EINVAL;
+		goto out;
+	}
+	tclass_datum = policydb.class_val_to_struct[tclass - 1];
+
+	ocontext = sidtab_search(&sidtab, oldsid);
+	if (!ocontext) {
+		printk(KERN_ERR "security_validate_transition: "
+		       " unrecognized SID %d\n", oldsid);
+		rc = -EINVAL;
+		goto out;
+	}
+
+	ncontext = sidtab_search(&sidtab, newsid);
+	if (!ncontext) {
+		printk(KERN_ERR "security_validate_transition: "
+		       " unrecognized SID %d\n", newsid);
+		rc = -EINVAL;
+		goto out;
+	}
+
+	tcontext = sidtab_search(&sidtab, tasksid);
+	if (!tcontext) {
+		printk(KERN_ERR "security_validate_transition: "
+		       " unrecognized SID %d\n", tasksid);
+		rc = -EINVAL;
+		goto out;
+	}
+
+	constraint = tclass_datum->validatetrans;
+	while (constraint) {
+		if (!constraint_expr_eval(ocontext, ncontext, tcontext,
+		                          constraint->expr)) {
+			rc = security_validtrans_handle_fail(ocontext, ncontext,
+			                                     tcontext, tclass);
+			goto out;
+		}
+		constraint = constraint->next;
+	}
+
+out:
+	POLICY_RDUNLOCK;
+	return rc;
+}
+
 /**
  * security_compute_av - Compute access vector decisions.
  * @ssid: source security identifier
@@ -366,7 +529,7 @@
 	*scontext_len += mls_compute_context_len(context);
 
 	/* Allocate space for the context; caller must free this space. */
-	scontextp = kmalloc(*scontext_len+1,GFP_ATOMIC);
+	scontextp = kmalloc(*scontext_len, GFP_ATOMIC);
 	if (!scontextp) {
 		return -ENOMEM;
 	}
@@ -375,17 +538,16 @@
 	/*
 	 * Copy the user name, role name and type name into the context.
 	 */
-	sprintf(scontextp, "%s:%s:%s:",
+	sprintf(scontextp, "%s:%s:%s",
 		policydb.p_user_val_to_name[context->user - 1],
 		policydb.p_role_val_to_name[context->role - 1],
 		policydb.p_type_val_to_name[context->type - 1]);
 	scontextp += strlen(policydb.p_user_val_to_name[context->user - 1]) +
 	             1 + strlen(policydb.p_role_val_to_name[context->role - 1]) +
-	             1 + strlen(policydb.p_type_val_to_name[context->type - 1]) + 1;
+	             1 + strlen(policydb.p_type_val_to_name[context->type - 1]);
 
 	mls_sid_to_context(context, &scontextp);
 
-	scontextp--;
 	*scontextp = 0;
 
 	return 0;
@@ -715,23 +877,8 @@
 				}
 			}
 		}
-
-		if (!type_change && !roletr) {
-			/* No change in process role or type. */
-			*out_sid = ssid;
-			goto out_unlock;
-
-		}
 		break;
 	default:
-		if (!type_change &&
-		    (newcontext.user == tcontext->user) &&
-		    mls_context_cmp(scontext, tcontext)) {
-                        /* No change in object type, owner,
-			   or MLS attributes. */
-			*out_sid = tsid;
-			goto out_unlock;
-		}
 		break;
 	}
 
@@ -1363,36 +1510,37 @@
 			if (!ebitmap_get_bit(&role->types, j))
 				continue;
 			usercon.type = j+1;
-			mls_for_user_ranges(user,usercon) {
-				rc = context_struct_compute_av(fromcon, &usercon,
-							       SECCLASS_PROCESS,
-							       PROCESS__TRANSITION,
-							       &avd);
-				if (rc ||  !(avd.allowed & PROCESS__TRANSITION))
-					continue;
-				rc = sidtab_context_to_sid(&sidtab, &usercon, &sid);
-				if (rc) {
+
+			if (mls_setup_user_range(fromcon, user, &usercon))
+				continue;
+
+			rc = context_struct_compute_av(fromcon, &usercon,
+						       SECCLASS_PROCESS,
+						       PROCESS__TRANSITION,
+						       &avd);
+			if (rc ||  !(avd.allowed & PROCESS__TRANSITION))
+				continue;
+			rc = sidtab_context_to_sid(&sidtab, &usercon, &sid);
+			if (rc) {
+				kfree(mysids);
+				goto out_unlock;
+			}
+			if (mynel < maxnel) {
+				mysids[mynel++] = sid;
+			} else {
+				maxnel += SIDS_NEL;
+				mysids2 = kmalloc(maxnel*sizeof(*mysids2), GFP_ATOMIC);
+				if (!mysids2) {
+					rc = -ENOMEM;
 					kfree(mysids);
 					goto out_unlock;
 				}
-				if (mynel < maxnel) {
-					mysids[mynel++] = sid;
-				} else {
-					maxnel += SIDS_NEL;
-					mysids2 = kmalloc(maxnel*sizeof(*mysids2), GFP_ATOMIC);
-					if (!mysids2) {
-						rc = -ENOMEM;
-						kfree(mysids);
-						goto out_unlock;
-					}
-					memset(mysids2, 0, maxnel*sizeof(*mysids2));
-					memcpy(mysids2, mysids, mynel * sizeof(*mysids2));
-					kfree(mysids);
-					mysids = mysids2;
-					mysids[mynel++] = sid;
-				}
+				memset(mysids2, 0, maxnel*sizeof(*mysids2));
+				memcpy(mysids2, mysids, mynel * sizeof(*mysids2));
+				kfree(mysids);
+				mysids = mysids2;
+				mysids[mynel++] = sid;
 			}
-			mls_end_user_ranges;
 		}
 	}
 
diff -Nru a/sound/arm/sa11xx-uda1341.c b/sound/arm/sa11xx-uda1341.c
--- a/sound/arm/sa11xx-uda1341.c	2005-03-11 12:51:52 -08:00
+++ b/sound/arm/sa11xx-uda1341.c	2005-03-11 12:51:52 -08:00
@@ -21,7 +21,7 @@
  *                              merged HAL layer (patches from Brian)
  */
 
-/* $Id: sa11xx-uda1341.c,v 1.19 2004/12/15 15:26:10 tiwai Exp $ */
+/* $Id: sa11xx-uda1341.c,v 1.21 2005/01/28 19:34:04 tiwai Exp $ */
 
 /***************************************************************************************************
 *
@@ -862,7 +862,7 @@
 
 #ifdef CONFIG_PM
 
-static int snd_sa11xx_uda1341_suspend(snd_card_t *card, unsigned int state)
+static int snd_sa11xx_uda1341_suspend(snd_card_t *card, pm_message_t state)
 {
 	sa11xx_uda1341_t *chip = card->pm_private_data;
 
@@ -878,7 +878,7 @@
 	return 0;
 }
 
-static int snd_sa11xx_uda1341_resume(snd_card_t *card, unsigned int state)
+static int snd_sa11xx_uda1341_resume(snd_card_t *card)
 {
 	sa11xx_uda1341_t *chip = card->pm_private_data;
 
@@ -938,7 +938,7 @@
 	if ((err = snd_card_sa11xx_uda1341_pcm(sa11xx_uda1341, 0)) < 0)
 		goto nodev;
         
-	snd_card_set_dev_pm_callback(card, PM_SYS_DEV,
+	snd_card_set_generic_pm_callback(card,
 				     snd_sa11xx_uda1341_suspend, snd_sa11_uda1341_resume,
 				     sa11xx_uda1341);
 
diff -Nru a/sound/core/Kconfig b/sound/core/Kconfig
--- a/sound/core/Kconfig	2005-03-11 12:51:47 -08:00
+++ b/sound/core/Kconfig	2005-03-11 12:51:47 -08:00
@@ -1,16 +1,20 @@
 # ALSA soundcard-configuration
 config SND_TIMER
 	tristate
+	depends on SND
 
 config SND_PCM
 	tristate
 	select SND_TIMER
+	depends on SND
 
 config SND_HWDEP
 	tristate
+	depends on SND
 
 config SND_RAWMIDI
 	tristate
+	depends on SND
 
 config SND_SEQUENCER
 	tristate "Sequencer support"
@@ -40,6 +44,7 @@
 
 config SND_OSSEMUL
 	bool
+	depends on SND
 
 config SND_MIXER_OSS
 	tristate "OSS Mixer API"
@@ -70,7 +75,7 @@
 
 config SND_SEQUENCER_OSS
 	bool "OSS Sequencer API"
-	depends on SND_SEQUENCER
+	depends on SND && SND_SEQUENCER
 	select SND_OSSEMUL
 	help
 	  Say Y here to enable OSS sequencer emulation (both
@@ -81,20 +86,6 @@
 	  To compile this driver as a module, choose M here: the module
 	  will be called snd-seq-oss.
 
-config SND_BIT32_EMUL
-	tristate "Emulation for 32-bit applications"
-	depends on SND && COMPAT
-	select SND_PCM
-	select SND_RAWMIDI
-	select SND_TIMER
-	select SND_HWDEP
-	help
-	  Say Y here to enable the emulation for 32-bit ALSA-native
-	  applications.
-
-	  To compile this driver as a module, choose M here: the module
-	  will be called snd-ioctl32.
-
 config SND_RTCTIMER
 	tristate "RTC Timer support"
 	depends on SND && RTC
@@ -137,3 +128,6 @@
 	  Say Y here to enable extra-verbose log messages printed when
 	  detecting devices.
 
+config SND_GENERIC_PM
+	bool
+	depends on SND
diff -Nru a/sound/core/Makefile b/sound/core/Makefile
--- a/sound/core/Makefile	2005-03-11 12:51:47 -08:00
+++ b/sound/core/Makefile	2005-03-11 12:51:47 -08:00
@@ -31,4 +31,3 @@
 
 obj-$(CONFIG_SND_OSSEMUL)	+= oss/
 obj-$(CONFIG_SND_SEQUENCER)	+= seq/
-obj-$(CONFIG_SND_BIT32_EMUL) += ioctl32/
diff -Nru a/sound/core/control.c b/sound/core/control.c
--- a/sound/core/control.c	2005-03-11 12:51:41 -08:00
+++ b/sound/core/control.c	2005-03-11 12:51:41 -08:00
@@ -43,6 +43,9 @@
 
 static DECLARE_RWSEM(snd_ioctl_rwsem);
 static LIST_HEAD(snd_control_ioctls);
+#ifdef CONFIG_COMPAT
+static LIST_HEAD(snd_control_compat_ioctls);
+#endif
 
 static int snd_ctl_open(struct inode *inode, struct file *file)
 {
@@ -595,43 +598,51 @@
 	return 0;
 }
 
-static int snd_ctl_elem_info(snd_ctl_file_t *ctl, snd_ctl_elem_info_t __user *_info)
+static int snd_ctl_elem_info(snd_ctl_file_t *ctl, snd_ctl_elem_info_t *info)
 {
 	snd_card_t *card = ctl->card;
-	snd_ctl_elem_info_t info;
 	snd_kcontrol_t *kctl;
 	snd_kcontrol_volatile_t *vd;
 	unsigned int index_offset;
 	int result;
 	
-	if (copy_from_user(&info, _info, sizeof(info)))
-		return -EFAULT;
 	down_read(&card->controls_rwsem);
-	kctl = snd_ctl_find_id(card, &info.id);
+	kctl = snd_ctl_find_id(card, &info->id);
 	if (kctl == NULL) {
 		up_read(&card->controls_rwsem);
 		return -ENOENT;
 	}
 #ifdef CONFIG_SND_DEBUG
-	info.access = 0;
+	info->access = 0;
 #endif
-	result = kctl->info(kctl, &info);
+	result = kctl->info(kctl, info);
 	if (result >= 0) {
-		snd_assert(info.access == 0, );
-		index_offset = snd_ctl_get_ioff(kctl, &info.id);
+		snd_assert(info->access == 0, );
+		index_offset = snd_ctl_get_ioff(kctl, &info->id);
 		vd = &kctl->vd[index_offset];
-		snd_ctl_build_ioff(&info.id, kctl, index_offset);
-		info.access = vd->access;
+		snd_ctl_build_ioff(&info->id, kctl, index_offset);
+		info->access = vd->access;
 		if (vd->owner) {
-			info.access |= SNDRV_CTL_ELEM_ACCESS_LOCK;
+			info->access |= SNDRV_CTL_ELEM_ACCESS_LOCK;
 			if (vd->owner == ctl)
-				info.access |= SNDRV_CTL_ELEM_ACCESS_OWNER;
-			info.owner = vd->owner_pid;
+				info->access |= SNDRV_CTL_ELEM_ACCESS_OWNER;
+			info->owner = vd->owner_pid;
 		} else {
-			info.owner = -1;
+			info->owner = -1;
 		}
 	}
 	up_read(&card->controls_rwsem);
+	return result;
+}
+
+static int snd_ctl_elem_info_user(snd_ctl_file_t *ctl, snd_ctl_elem_info_t __user *_info)
+{
+	snd_ctl_elem_info_t info;
+	int result;
+
+	if (copy_from_user(&info, _info, sizeof(info)))
+		return -EFAULT;
+	result = snd_ctl_elem_info(ctl, &info);
 	if (result >= 0)
 		if (copy_to_user(_info, &info, sizeof(info)))
 			return -EFAULT;
@@ -816,14 +827,6 @@
 	struct user_element *ue = kcontrol->private_data;
 
 	*uinfo = ue->info;
-	if (ue->info.type == SNDRV_CTL_ELEM_TYPE_ENUMERATED) {
-		uinfo->value.enumerated.items = ue->info.value.enumerated.items;
-		if (uinfo->value.enumerated.item >= ue->info.value.enumerated.items)
-			uinfo->value.enumerated.item = 0;
-		strlcpy(uinfo->value.enumerated.name,
-			(char *)ue->priv_data + uinfo->value.enumerated.item * 64,
-			64);
-	}
 	return 0;
 }
 
@@ -851,28 +854,25 @@
 	kfree(kcontrol->private_data);
 }
 
-static int snd_ctl_elem_add(snd_ctl_file_t *file, snd_ctl_elem_info_t __user *_info, int replace)
+static int snd_ctl_elem_add(snd_ctl_file_t *file, snd_ctl_elem_info_t *info, int replace)
 {
 	snd_card_t *card = file->card;
-	snd_ctl_elem_info_t info;
 	snd_kcontrol_t kctl, *_kctl;
 	unsigned int access;
-	long private_size, extra_size;
+	long private_size;
 	struct user_element *ue;
 	int idx, err;
 	
 	if (card->user_ctl_count >= MAX_USER_CONTROLS)
 		return -ENOMEM;
-	if (copy_from_user(&info, _info, sizeof(info)))
-		return -EFAULT;
-	if (info.count > 1024)
+	if (info->count > 1024)
 		return -EINVAL;
-	access = info.access == 0 ? SNDRV_CTL_ELEM_ACCESS_READWRITE :
-		(info.access & (SNDRV_CTL_ELEM_ACCESS_READWRITE|SNDRV_CTL_ELEM_ACCESS_INACTIVE));
-	info.id.numid = 0;
+	access = info->access == 0 ? SNDRV_CTL_ELEM_ACCESS_READWRITE :
+		(info->access & (SNDRV_CTL_ELEM_ACCESS_READWRITE|SNDRV_CTL_ELEM_ACCESS_INACTIVE));
+	info->id.numid = 0;
 	memset(&kctl, 0, sizeof(kctl));
 	down_write(&card->controls_rwsem);
-	_kctl = snd_ctl_find_id(card, &info.id);
+	_kctl = snd_ctl_find_id(card, &info->id);
 	err = 0;
 	if (_kctl) {
 		if (replace)
@@ -886,67 +886,50 @@
 	up_write(&card->controls_rwsem);
 	if (err < 0)
 		return err;
-	memcpy(&kctl.id, &info.id, sizeof(info.id));
-	kctl.count = info.owner ? info.owner : 1;
+	memcpy(&kctl.id, &info->id, sizeof(info->id));
+	kctl.count = info->owner ? info->owner : 1;
 	access |= SNDRV_CTL_ELEM_ACCESS_USER;
 	kctl.info = snd_ctl_elem_user_info;
 	if (access & SNDRV_CTL_ELEM_ACCESS_READ)
 		kctl.get = snd_ctl_elem_user_get;
 	if (access & SNDRV_CTL_ELEM_ACCESS_WRITE)
 		kctl.put = snd_ctl_elem_user_put;
-	extra_size = 0;
-	switch (info.type) {
+	switch (info->type) {
 	case SNDRV_CTL_ELEM_TYPE_BOOLEAN:
 		private_size = sizeof(char);
-		if (info.count > 128)
+		if (info->count > 128)
 			return -EINVAL;
 		break;
 	case SNDRV_CTL_ELEM_TYPE_INTEGER:
 		private_size = sizeof(long);
-		if (info.count > 128)
+		if (info->count > 128)
 			return -EINVAL;
 		break;
 	case SNDRV_CTL_ELEM_TYPE_INTEGER64:
 		private_size = sizeof(long long);
-		if (info.count > 64)
+		if (info->count > 64)
 			return -EINVAL;
 		break;
-	case SNDRV_CTL_ELEM_TYPE_ENUMERATED:
-		private_size = sizeof(unsigned int);
-		if (info.count > 128)
-			return -EINVAL;
-		if (info.value.enumerated.items > 128)
-			return -EINVAL;
-		extra_size = info.value.enumerated.items * 64;
-		break;
 	case SNDRV_CTL_ELEM_TYPE_BYTES:
 		private_size = sizeof(unsigned char);
-		if (info.count > 512)
+		if (info->count > 512)
 			return -EINVAL;
 		break;
 	case SNDRV_CTL_ELEM_TYPE_IEC958:
 		private_size = sizeof(struct sndrv_aes_iec958);
-		if (info.count != 1)
+		if (info->count != 1)
 			return -EINVAL;
 		break;
 	default:
 		return -EINVAL;
 	}
-	private_size *= info.count;
-	ue = kcalloc(1, sizeof(struct user_element) + private_size + extra_size, GFP_KERNEL);
+	private_size *= info->count;
+	ue = kcalloc(1, sizeof(struct user_element) + private_size, GFP_KERNEL);
 	if (ue == NULL)
 		return -ENOMEM;
-	ue->info = info;
-	ue->elem_data = (char *)ue + sizeof(ue);
+	ue->info = *info;
+	ue->elem_data = (char *)ue + sizeof(*ue);
 	ue->elem_data_size = private_size;
-	if (extra_size) {
-		ue->priv_data = (char *)ue + sizeof(ue) + private_size;
-		ue->priv_data_size = extra_size;
-		if (ue->info.type == SNDRV_CTL_ELEM_TYPE_ENUMERATED) {
-			if (copy_from_user(ue->priv_data, *(char __user **)info.value.enumerated.name, extra_size))
-				return -EFAULT;
-		}
-	}
 	kctl.private_free = snd_ctl_elem_user_free;
 	_kctl = snd_ctl_new(&kctl, access);
 	if (_kctl == NULL) {
@@ -969,6 +952,14 @@
 	return 0;
 }
 
+static int snd_ctl_elem_add_user(snd_ctl_file_t *file, snd_ctl_elem_info_t __user *_info, int replace)
+{
+	snd_ctl_elem_info_t info;
+	if (copy_from_user(&info, _info, sizeof(info)))
+		return -EFAULT;
+	return snd_ctl_elem_add(file, &info, replace);
+}
+
 static int snd_ctl_elem_remove(snd_ctl_file_t *file, snd_ctl_elem_id_t __user *_id)
 {
 	snd_ctl_elem_id_t id;
@@ -1016,15 +1007,13 @@
 	switch (power_state) {
 	case SNDRV_CTL_POWER_D0:
 		if (card->power_state != power_state) {
-			/* FIXME: pass the correct state value */
-			card->pm_resume(card, 0);
+			card->pm_resume(card);
 			snd_power_change_state(card, power_state);
 		}
 		break;
 	case SNDRV_CTL_POWER_D3hot:
 		if (card->power_state != power_state) {
-			/* FIXME: pass the correct state value */
-			card->pm_suspend(card, 0);
+			card->pm_suspend(card, PMSG_SUSPEND);
 			snd_power_change_state(card, power_state);
 		}
 		break;
@@ -1039,8 +1028,7 @@
 }
 #endif
 
-static inline int _snd_ctl_ioctl(struct inode *inode, struct file *file,
-				 unsigned int cmd, unsigned long arg)
+static long snd_ctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 {
 	snd_ctl_file_t *ctl;
 	snd_card_t *card;
@@ -1061,7 +1049,7 @@
 	case SNDRV_CTL_IOCTL_ELEM_LIST:
 		return snd_ctl_elem_list(ctl->card, argp);
 	case SNDRV_CTL_IOCTL_ELEM_INFO:
-		return snd_ctl_elem_info(ctl, argp);
+		return snd_ctl_elem_info_user(ctl, argp);
 	case SNDRV_CTL_IOCTL_ELEM_READ:
 		return snd_ctl_elem_read_user(ctl->card, argp);
 	case SNDRV_CTL_IOCTL_ELEM_WRITE:
@@ -1071,9 +1059,9 @@
 	case SNDRV_CTL_IOCTL_ELEM_UNLOCK:
 		return snd_ctl_elem_unlock(ctl, argp);
 	case SNDRV_CTL_IOCTL_ELEM_ADD:
-		return snd_ctl_elem_add(ctl, argp, 0);
+		return snd_ctl_elem_add_user(ctl, argp, 0);
 	case SNDRV_CTL_IOCTL_ELEM_REPLACE:
-		return snd_ctl_elem_add(ctl, argp, 1);
+		return snd_ctl_elem_add_user(ctl, argp, 1);
 	case SNDRV_CTL_IOCTL_ELEM_REMOVE:
 		return snd_ctl_elem_remove(ctl, argp);
 	case SNDRV_CTL_IOCTL_SUBSCRIBE_EVENTS:
@@ -1113,17 +1101,6 @@
 	return -ENOTTY;
 }
 
-/* FIXME: need to unlock BKL to allow preemption */
-static int snd_ctl_ioctl(struct inode *inode, struct file *file,
-			 unsigned int cmd, unsigned long arg)
-{
-	int err;
-	unlock_kernel();
-	err = _snd_ctl_ioctl(inode, file, cmd, arg);
-	lock_kernel();
-	return err;
-}
-
 static ssize_t snd_ctl_read(struct file *file, char __user *buffer, size_t count, loff_t * offset)
 {
 	snd_ctl_file_t *ctl;
@@ -1199,7 +1176,7 @@
  * register the device-specific control-ioctls.
  * called from each device manager like pcm.c, hwdep.c, etc.
  */
-int snd_ctl_register_ioctl(snd_kctl_ioctl_func_t fcn)
+static int _snd_ctl_register_ioctl(snd_kctl_ioctl_func_t fcn, struct list_head *lists)
 {
 	snd_kctl_ioctl_t *pn;
 
@@ -1208,22 +1185,34 @@
 		return -ENOMEM;
 	pn->fioctl = fcn;
 	down_write(&snd_ioctl_rwsem);
-	list_add_tail(&pn->list, &snd_control_ioctls);
+	list_add_tail(&pn->list, lists);
 	up_write(&snd_ioctl_rwsem);
 	return 0;
 }
 
+int snd_ctl_register_ioctl(snd_kctl_ioctl_func_t fcn)
+{
+	return _snd_ctl_register_ioctl(fcn, &snd_control_ioctls);
+}
+
+#ifdef CONFIG_COMPAT
+int snd_ctl_register_ioctl_compat(snd_kctl_ioctl_func_t fcn)
+{
+	return _snd_ctl_register_ioctl(fcn, &snd_control_compat_ioctls);
+}
+#endif
+
 /*
  * de-register the device-specific control-ioctls.
  */
-int snd_ctl_unregister_ioctl(snd_kctl_ioctl_func_t fcn)
+static int _snd_ctl_unregister_ioctl(snd_kctl_ioctl_func_t fcn, struct list_head *lists)
 {
 	struct list_head *list;
 	snd_kctl_ioctl_t *p;
 
 	snd_runtime_check(fcn != NULL, return -EINVAL);
 	down_write(&snd_ioctl_rwsem);
-	list_for_each(list, &snd_control_ioctls) {
+	list_for_each(list, lists) {
 		p = list_entry(list, snd_kctl_ioctl_t, list);
 		if (p->fioctl == fcn) {
 			list_del(&p->list);
@@ -1237,6 +1226,19 @@
 	return -EINVAL;
 }
 
+int snd_ctl_unregister_ioctl(snd_kctl_ioctl_func_t fcn)
+{
+	return _snd_ctl_unregister_ioctl(fcn, &snd_control_ioctls);
+}
+
+#ifdef CONFIG_COMPAT
+int snd_ctl_unregister_ioctl_compat(snd_kctl_ioctl_func_t fcn)
+{
+	return _snd_ctl_unregister_ioctl(fcn, &snd_control_compat_ioctls);
+}
+
+#endif
+
 static int snd_ctl_fasync(int fd, struct file * file, int on)
 {
 	snd_ctl_file_t *ctl;
@@ -1249,6 +1251,15 @@
 }
 
 /*
+ * ioctl32 compat
+ */
+#ifdef CONFIG_COMPAT
+#include "control_compat.c"
+#else
+#define snd_ctl_ioctl_compat	NULL
+#endif
+
+/*
  *  INIT PART
  */
 
@@ -1259,7 +1270,8 @@
 	.open =		snd_ctl_open,
 	.release =	snd_ctl_release,
 	.poll =		snd_ctl_poll,
-	.ioctl =	snd_ctl_ioctl,
+	.unlocked_ioctl =	snd_ctl_ioctl,
+	.compat_ioctl =	snd_ctl_ioctl_compat,
 	.fasync =	snd_ctl_fasync,
 };
 
diff -Nru a/sound/core/control_compat.c b/sound/core/control_compat.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/sound/core/control_compat.c	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,412 @@
+/*
+ * compat ioctls for control API
+ *
+ *   Copyright (c) by Takashi Iwai <tiwai@suse.de>
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ */
+
+/* this file included from control.c */
+
+#include <linux/compat.h>
+
+struct sndrv_ctl_elem_list32 {
+	u32 offset;
+	u32 space;
+	u32 used;
+	u32 count;
+	u32 pids;
+	unsigned char reserved[50];
+} /* don't set packed attribute here */;
+
+static int snd_ctl_elem_list_compat(snd_card_t *card, struct sndrv_ctl_elem_list32 __user *data32)
+{
+	struct sndrv_ctl_elem_list __user *data;
+	compat_caddr_t ptr;
+	int err;
+
+	data = compat_alloc_user_space(sizeof(*data));
+
+	/* offset, space, used, count */
+	if (copy_in_user(data, data32, 4 * sizeof(u32)))
+		return -EFAULT;
+	/* pids */
+	if (get_user(ptr, &data32->pids) ||
+	    put_user(compat_ptr(ptr), &data->pids))
+		return -EFAULT;
+	err = snd_ctl_elem_list(card, data);
+	if (err < 0)
+		return err;
+	/* copy the result */
+	if (copy_in_user(data32, data, 4 * sizeof(u32)))
+		return -EFAULT;
+	return 0;
+}
+
+/*
+ * control element info
+ * it uses union, so the things are not easy..
+ */
+
+struct sndrv_ctl_elem_info32 {
+	struct sndrv_ctl_elem_id id; // the size of struct is same
+	s32 type;
+	u32 access;
+	u32 count;
+	s32 owner;
+	union {
+		struct {
+			s32 min;
+			s32 max;
+			s32 step;
+		} integer;
+		struct {
+			u64 min;
+			u64 max;
+			u64 step;
+		} integer64;
+		struct {
+			u32 items;
+			u32 item;
+			char name[64];
+		} enumerated;
+		unsigned char reserved[128];
+	} value;
+	unsigned char reserved[64];
+} __attribute__((packed));
+
+static int snd_ctl_elem_info_compat(snd_ctl_file_t *ctl, struct sndrv_ctl_elem_info32 __user *data32)
+{
+	struct sndrv_ctl_elem_info *data;
+	int err;
+
+	data = kcalloc(1, sizeof(*data), GFP_KERNEL);
+	if (! data)
+		return -ENOMEM;
+
+	err = -EFAULT;
+	/* copy id */
+	if (copy_from_user(&data->id, &data32->id, sizeof(data->id)))
+		goto error;
+	/* we need to copy the item index.
+	 * hope this doesn't break anything..
+	 */
+	if (get_user(data->value.enumerated.item, &data32->value.enumerated.item))
+		goto error;
+	err = snd_ctl_elem_info(ctl, data);
+	if (err < 0)
+		goto error;
+	/* restore info to 32bit */
+	err = -EFAULT;
+	/* id, type, access, count */
+	if (copy_to_user(&data32->id, &data->id, sizeof(data->id)) ||
+	    copy_to_user(&data32->type, &data->type, 3 * sizeof(u32)))
+		goto error;
+	if (put_user(data->owner, &data32->owner))
+		goto error;
+	switch (data->type) {
+	case SNDRV_CTL_ELEM_TYPE_BOOLEAN:
+	case SNDRV_CTL_ELEM_TYPE_INTEGER:
+		if (put_user(data->value.integer.min, &data32->value.integer.min) ||
+		    put_user(data->value.integer.max, &data32->value.integer.max) ||
+		    put_user(data->value.integer.step, &data32->value.integer.step))
+			goto error;
+		break;
+	case SNDRV_CTL_ELEM_TYPE_INTEGER64:
+		if (copy_to_user(&data32->value.integer64,
+				 &data->value.integer64,
+				 sizeof(data->value.integer64)))
+			goto error;
+		break;
+	case SNDRV_CTL_ELEM_TYPE_ENUMERATED:
+		if (copy_to_user(&data32->value.enumerated,
+				 &data->value.enumerated,
+				 sizeof(data->value.enumerated)))
+			goto error;
+		break;
+	default:
+		break;
+	}
+	err = 0;
+ error:
+	kfree(data);
+	return err;
+}
+
+/* read / write */
+struct sndrv_ctl_elem_value32 {
+	struct sndrv_ctl_elem_id id;
+	unsigned int indirect;	/* bit-field causes misalignment */
+        union {
+		s32 integer[128];
+		unsigned char data[512];
+#ifndef CONFIG_X86_64
+		s64 integer64[64];
+#endif
+        } value;
+        unsigned char reserved[128];
+};
+
+
+/* get the value type and count of the control */
+static int get_ctl_type(snd_card_t *card, snd_ctl_elem_id_t *id, int *countp)
+{
+	snd_kcontrol_t *kctl;
+	snd_ctl_elem_info_t info;
+	int err;
+
+	down_read(&card->controls_rwsem);
+	kctl = snd_ctl_find_id(card, id);
+	if (! kctl) {
+		up_read(&card->controls_rwsem);
+		return -ENXIO;
+	}
+	info.id = *id;
+	err = kctl->info(kctl, &info);
+	up_read(&card->controls_rwsem);
+	if (err >= 0) {
+		err = info.type;
+		*countp = info.count;
+	}
+	return err;
+}
+
+static int get_elem_size(int type, int count)
+{
+	switch (type) {
+	case SNDRV_CTL_ELEM_TYPE_INTEGER64:
+		return sizeof(s64) * count;
+	case SNDRV_CTL_ELEM_TYPE_ENUMERATED:
+		return sizeof(int) * count;
+	case SNDRV_CTL_ELEM_TYPE_BYTES:
+		return 512;
+	case SNDRV_CTL_ELEM_TYPE_IEC958:
+		return sizeof(struct sndrv_aes_iec958);
+	default:
+		return -1;
+	}
+}
+
+static int copy_ctl_value_from_user(snd_card_t *card,
+				    struct sndrv_ctl_elem_value *data,
+				    struct sndrv_ctl_elem_value32 __user *data32,
+				    int *typep, int *countp)
+{
+	int i, type, count, size;
+	unsigned int indirect;
+
+	if (copy_from_user(&data->id, &data32->id, sizeof(data->id)))
+		return -EFAULT;
+	if (get_user(indirect, &data32->indirect))
+		return -EFAULT;
+	if (indirect)
+		return -EINVAL;
+	type = get_ctl_type(card, &data->id, &count);
+	if (type < 0)
+		return type;
+
+	if (type == SNDRV_CTL_ELEM_TYPE_BOOLEAN ||
+	    type == SNDRV_CTL_ELEM_TYPE_INTEGER) {
+		for (i = 0; i < count; i++) {
+			int val;
+			if (get_user(val, &data32->value.integer[i]))
+				return -EFAULT;
+			data->value.integer.value[i] = val;
+		}
+	} else {
+		size = get_elem_size(type, count);
+		if (size < 0) {
+			printk(KERN_ERR "snd_ioctl32_ctl_elem_value: unknown type %d\n", type);
+			return -EINVAL;
+		}
+		if (copy_from_user(data->value.bytes.data,
+				   data32->value.data, size))
+			return -EFAULT;
+	}
+
+	*typep = type;
+	*countp = count;
+	return 0;
+}
+
+/* restore the value to 32bit */
+static int copy_ctl_value_to_user(struct sndrv_ctl_elem_value32 __user *data32,
+				  struct sndrv_ctl_elem_value *data,
+				  int type, int count)
+{
+	int i, size;
+
+	if (type == SNDRV_CTL_ELEM_TYPE_BOOLEAN ||
+	    type == SNDRV_CTL_ELEM_TYPE_INTEGER) {
+		for (i = 0; i < count; i++) {
+			int val;
+			val = data->value.integer.value[i];
+			if (put_user(val, &data32->value.integer[i]))
+				return -EFAULT;
+		}
+	} else {
+		size = get_elem_size(type, count);
+		if (copy_to_user(data32->value.data,
+				 data->value.bytes.data, size))
+			return -EFAULT;
+	}
+	return 0;
+}
+
+static int snd_ctl_elem_read_user_compat(snd_card_t *card, 
+					 struct sndrv_ctl_elem_value32 __user *data32)
+{
+	struct sndrv_ctl_elem_value *data;
+	int err, type, count;
+
+	data = kcalloc(1, sizeof(*data), GFP_KERNEL);
+	if (data == NULL)
+		return -ENOMEM;
+
+	if ((err = copy_ctl_value_from_user(card, data, data32, &type, &count)) < 0)
+		goto error;
+	if ((err = snd_ctl_elem_read(card, data)) < 0)
+		goto error;
+	err = copy_ctl_value_to_user(data32, data, type, count);
+ error:
+	kfree(data);
+	return err;
+}
+
+static int snd_ctl_elem_write_user_compat(snd_ctl_file_t *file,
+					  struct sndrv_ctl_elem_value32 __user *data32)
+{
+	struct sndrv_ctl_elem_value *data;
+	int err, type, count;
+
+	data = kcalloc(1, sizeof(*data), GFP_KERNEL);
+	if (data == NULL)
+		return -ENOMEM;
+
+	if ((err = copy_ctl_value_from_user(file->card, data, data32, &type, &count)) < 0)
+		goto error;
+	if ((err = snd_ctl_elem_write(file->card, file, data)) < 0)
+		goto error;
+	err = copy_ctl_value_to_user(data32, data, type, count);
+ error:
+	kfree(data);
+	return err;
+}
+
+/* add or replace a user control */
+static int snd_ctl_elem_add_compat(snd_ctl_file_t *file,
+				   struct sndrv_ctl_elem_info32 __user *data32,
+				   int replace)
+{
+	struct sndrv_ctl_elem_info *data;
+	int err;
+
+	data = kcalloc(1, sizeof(*data), GFP_KERNEL);
+	if (! data)
+		return -ENOMEM;
+
+	err = -EFAULT;
+	/* id, type, access, count */ \
+	if (copy_from_user(&data->id, &data32->id, sizeof(data->id)) ||
+	    copy_from_user(&data->type, &data32->type, 3 * sizeof(u32)))
+		goto error;
+	if (get_user(data->owner, &data32->owner) ||
+	    get_user(data->type, &data32->type))
+		goto error;
+	switch (data->type) {
+	case SNDRV_CTL_ELEM_TYPE_BOOLEAN:
+	case SNDRV_CTL_ELEM_TYPE_INTEGER:
+		if (get_user(data->value.integer.min, &data32->value.integer.min) ||
+		    get_user(data->value.integer.max, &data32->value.integer.max) ||
+		    get_user(data->value.integer.step, &data32->value.integer.step))
+			goto error;
+		break;
+	case SNDRV_CTL_ELEM_TYPE_INTEGER64:
+		if (copy_from_user(&data->value.integer64,
+				   &data32->value.integer64,
+				   sizeof(data->value.integer64)))
+			goto error;
+		break;
+	case SNDRV_CTL_ELEM_TYPE_ENUMERATED:
+		if (copy_from_user(&data->value.enumerated,
+				   &data32->value.enumerated,
+				   sizeof(data->value.enumerated)))
+			goto error;
+		break;
+	default:
+		break;
+	}
+	err = snd_ctl_elem_add(file, data, replace);
+ error:
+	kfree(data);
+	return err;
+}  
+
+enum {
+	SNDRV_CTL_IOCTL_ELEM_LIST32 = _IOWR('U', 0x10, struct sndrv_ctl_elem_list32),
+	SNDRV_CTL_IOCTL_ELEM_INFO32 = _IOWR('U', 0x11, struct sndrv_ctl_elem_info32),
+	SNDRV_CTL_IOCTL_ELEM_READ32 = _IOWR('U', 0x12, struct sndrv_ctl_elem_value32),
+	SNDRV_CTL_IOCTL_ELEM_WRITE32 = _IOWR('U', 0x13, struct sndrv_ctl_elem_value32),
+	SNDRV_CTL_IOCTL_ELEM_ADD32 = _IOWR('U', 0x17, struct sndrv_ctl_elem_info32),
+	SNDRV_CTL_IOCTL_ELEM_REPLACE32 = _IOWR('U', 0x18, struct sndrv_ctl_elem_info32),
+};
+
+static inline long snd_ctl_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg)
+{
+	snd_ctl_file_t *ctl;
+	struct list_head *list;
+	void __user *argp = compat_ptr(arg);
+	int err;
+
+	ctl = file->private_data;
+	snd_assert(ctl && ctl->card, return -ENXIO);
+
+	switch (cmd) {
+	case SNDRV_CTL_IOCTL_PVERSION:
+	case SNDRV_CTL_IOCTL_CARD_INFO:
+	case SNDRV_CTL_IOCTL_SUBSCRIBE_EVENTS:
+	case SNDRV_CTL_IOCTL_POWER:
+	case SNDRV_CTL_IOCTL_POWER_STATE:
+	case SNDRV_CTL_IOCTL_ELEM_LOCK:
+	case SNDRV_CTL_IOCTL_ELEM_UNLOCK:
+		return snd_ctl_ioctl(file, cmd, (unsigned long)argp);
+	case SNDRV_CTL_IOCTL_ELEM_LIST32:
+		return snd_ctl_elem_list_compat(ctl->card, argp);
+	case SNDRV_CTL_IOCTL_ELEM_INFO32:
+		return snd_ctl_elem_info_compat(ctl, argp);
+	case SNDRV_CTL_IOCTL_ELEM_READ32:
+		return snd_ctl_elem_read_user_compat(ctl->card, argp);
+	case SNDRV_CTL_IOCTL_ELEM_WRITE32:
+		return snd_ctl_elem_write_user_compat(ctl, argp);
+	case SNDRV_CTL_IOCTL_ELEM_ADD32:
+		return snd_ctl_elem_add_compat(ctl, argp, 0);
+	case SNDRV_CTL_IOCTL_ELEM_REPLACE32:
+		return snd_ctl_elem_add_compat(ctl, argp, 1);
+	}
+
+	down_read(&snd_ioctl_rwsem);
+	list_for_each(list, &snd_control_compat_ioctls) {
+		snd_kctl_ioctl_t *p = list_entry(list, snd_kctl_ioctl_t, list);
+		if (p->fioctl) {
+			err = p->fioctl(ctl->card, ctl, cmd, arg);
+			if (err != -ENOIOCTLCMD) {
+				up_read(&snd_ioctl_rwsem);
+				return err;
+			}
+		}
+	}
+	up_read(&snd_ioctl_rwsem);
+	return -ENOIOCTLCMD;
+}
diff -Nru a/sound/core/hwdep.c b/sound/core/hwdep.c
--- a/sound/core/hwdep.c	2005-03-11 12:51:52 -08:00
+++ b/sound/core/hwdep.c	2005-03-11 12:51:52 -08:00
@@ -232,8 +232,7 @@
 	return 0;
 }
 
-static inline int _snd_hwdep_ioctl(struct inode *inode, struct file * file,
-				   unsigned int cmd, unsigned long arg)
+static long snd_hwdep_ioctl(struct file * file, unsigned int cmd, unsigned long arg)
 {
 	snd_hwdep_t *hw = file->private_data;
 	void __user *argp = (void __user *)arg;
@@ -252,17 +251,6 @@
 	return -ENOTTY;
 }
 
-/* FIXME: need to unlock BKL to allow preemption */
-static int snd_hwdep_ioctl(struct inode *inode, struct file * file,
-			   unsigned int cmd, unsigned long arg)
-{
-	int err;
-	unlock_kernel();
-	err = _snd_hwdep_ioctl(inode, file, cmd, arg);
-	lock_kernel();
-	return err;
-}
-
 static int snd_hwdep_mmap(struct file * file, struct vm_area_struct * vma)
 {
 	snd_hwdep_t *hw = file->private_data;
@@ -315,6 +303,12 @@
 	return -ENOIOCTLCMD;
 }
 
+#ifdef CONFIG_COMPAT
+#include "hwdep_compat.c"
+#else
+#define snd_hwdep_ioctl_compat	NULL
+#endif
+
 /*
 
  */
@@ -328,7 +322,8 @@
 	.open =		snd_hwdep_open,
 	.release =	snd_hwdep_release,
 	.poll =		snd_hwdep_poll,
-	.ioctl =	snd_hwdep_ioctl,
+	.unlocked_ioctl =	snd_hwdep_ioctl,
+	.compat_ioctl =	snd_hwdep_ioctl_compat,
 	.mmap =		snd_hwdep_mmap,
 };
 
@@ -509,12 +504,14 @@
 	}
 	snd_hwdep_proc_entry = entry;
 	snd_ctl_register_ioctl(snd_hwdep_control_ioctl);
+	snd_ctl_register_ioctl_compat(snd_hwdep_control_ioctl);
 	return 0;
 }
 
 static void __exit alsa_hwdep_exit(void)
 {
 	snd_ctl_unregister_ioctl(snd_hwdep_control_ioctl);
+	snd_ctl_unregister_ioctl_compat(snd_hwdep_control_ioctl);
 	if (snd_hwdep_proc_entry) {
 		snd_info_unregister(snd_hwdep_proc_entry);
 		snd_hwdep_proc_entry = NULL;
diff -Nru a/sound/core/hwdep_compat.c b/sound/core/hwdep_compat.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/sound/core/hwdep_compat.c	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,77 @@
+/*
+ *   32bit -> 64bit ioctl wrapper for hwdep API
+ *   Copyright (c) by Takashi Iwai <tiwai@suse.de>
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+/* This file is included from hwdep.c */
+
+#include <linux/compat.h>
+
+struct sndrv_hwdep_dsp_image32 {
+	u32 index;
+	unsigned char name[64];
+	u32 image;	/* pointer */
+	u32 length;
+	u32 driver_data;
+} /* don't set packed attribute here */;
+
+static int snd_hwdep_dsp_load_compat(snd_hwdep_t *hw,
+				     struct sndrv_hwdep_dsp_image32 __user *src)
+{
+	struct sndrv_hwdep_dsp_image *dst;
+	compat_caddr_t ptr;
+	u32 val;
+
+	dst = compat_alloc_user_space(sizeof(*dst));
+
+	/* index and name */
+	if (copy_in_user(dst, src, 4 + 64))
+		return -EFAULT;
+	if (get_user(ptr, &src->image) ||
+	    put_user(compat_ptr(ptr), &dst->image))
+		return -EFAULT;
+	if (get_user(val, &src->length) ||
+	    put_user(val, &dst->length))
+		return -EFAULT;
+	if (get_user(val, &src->driver_data) ||
+	    put_user(val, &dst->driver_data))
+		return -EFAULT;
+
+	return snd_hwdep_dsp_load(hw, dst);
+}
+
+enum {
+	SNDRV_HWDEP_IOCTL_DSP_LOAD32   = _IOW('H', 0x03, struct sndrv_hwdep_dsp_image32)
+};
+
+static long snd_hwdep_ioctl_compat(struct file * file, unsigned int cmd, unsigned long arg)
+{
+	snd_hwdep_t *hw = file->private_data;
+	void __user *argp = compat_ptr(arg);
+	switch (cmd) {
+	case SNDRV_HWDEP_IOCTL_PVERSION:
+	case SNDRV_HWDEP_IOCTL_INFO:
+	case SNDRV_HWDEP_IOCTL_DSP_STATUS:
+		return snd_hwdep_ioctl(file, cmd, (unsigned long)argp);
+	case SNDRV_HWDEP_IOCTL_DSP_LOAD32:
+		return snd_hwdep_dsp_load_compat(hw, argp);
+	}
+	if (hw->ops.ioctl_compat)
+		return hw->ops.ioctl_compat(hw, file, cmd, arg);
+	return -ENOIOCTLCMD;
+}
diff -Nru a/sound/core/init.c b/sound/core/init.c
--- a/sound/core/init.c	2005-03-11 12:51:41 -08:00
+++ b/sound/core/init.c	2005-03-11 12:51:41 -08:00
@@ -39,7 +39,7 @@
 
 unsigned int snd_cards_lock = 0;	/* locked for registering/using */
 snd_card_t *snd_cards[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = NULL};
-rwlock_t snd_card_rwlock = RW_LOCK_UNLOCKED;
+DEFINE_RWLOCK(snd_card_rwlock);
 
 #if defined(CONFIG_SND_MIXER_OSS) || defined(CONFIG_SND_MIXER_OSS_MODULE)
 int (*snd_mixer_oss_notify_callback)(snd_card_t *card, int free_flag);
@@ -84,16 +84,13 @@
 	write_lock(&snd_card_rwlock);
 	if (idx < 0) {
 		int idx2;
-		for (idx2 = 0; idx2 < snd_ecards_limit; idx2++)
-			if (!(snd_cards_lock & (1 << idx2))) {
+		for (idx2 = 0; idx2 < SNDRV_CARDS; idx2++)
+			if (~snd_cards_lock & idx & 1<<idx2) {
 				idx = idx2;
+				if (idx >= snd_ecards_limit)
+					snd_ecards_limit = idx + 1;
 				break;
 			}
-		if (idx < 0 && snd_ecards_limit < SNDRV_CARDS)
-			/* for dynamically additional devices like hotplug:
-			 * increment the limit if still free slot exists.
-			 */
-			idx = snd_ecards_limit++;
 	} else if (idx < snd_ecards_limit) {
 		if (snd_cards_lock & (1 << idx))
 			err = -ENODEV;	/* invalid */
@@ -229,6 +226,10 @@
 	return 0;	
 }
 
+#if defined(CONFIG_PM) && defined(CONFIG_SND_GENERIC_PM)
+static void snd_generic_device_unregister(struct snd_generic_device *dev);
+#endif
+
 /**
  *  snd_card_free - frees given soundcard structure
  *  @card: soundcard structure
@@ -252,9 +253,9 @@
 
 #ifdef CONFIG_PM
 	wake_up(&card->power_sleep);
-#ifdef CONFIG_ISA
+#ifdef CONFIG_SND_GENERIC_PM
 	if (card->pm_dev) {
-		pm_unregister(card->pm_dev);
+		snd_generic_device_unregister(card->pm_dev);
 		card->pm_dev = NULL;
 	}
 #endif
@@ -374,7 +375,7 @@
 
 	while (1) {
 	      	if (loops-- == 0) {
-      			snd_printk(KERN_ERR "unable to choose default card id (%s)", id);
+      			snd_printk(KERN_ERR "unable to choose default card id (%s)\n", id);
       			strcpy(card->id, card->proc_root->name);
       			return;
       		}
@@ -719,8 +720,8 @@
  * handler and from the control API.
  */
 int snd_card_set_pm_callback(snd_card_t *card,
-			     int (*suspend)(snd_card_t *, unsigned int),
-			     int (*resume)(snd_card_t *, unsigned int),
+			     int (*suspend)(snd_card_t *, pm_message_t),
+			     int (*resume)(snd_card_t *),
 			     void *private_data)
 {
 	card->pm_suspend = suspend;
@@ -729,56 +730,132 @@
 	return 0;
 }
 
-static int snd_generic_pm_callback(struct pm_dev *dev, pm_request_t rqst, void *data)
+#ifdef CONFIG_SND_GENERIC_PM
+/*
+ * use platform_device for generic power-management without a proper bus
+ * (e.g. ISA)
+ */
+struct snd_generic_device {
+	struct platform_device pdev;
+	snd_card_t *card;
+};
+
+#define get_snd_generic_card(dev)	container_of(to_platform_device(dev), struct snd_generic_device, pdev)->card
+
+#define SND_GENERIC_NAME	"snd_generic_pm"
+
+static int snd_generic_suspend(struct device *dev, u32 state, u32 level);
+static int snd_generic_resume(struct device *dev, u32 level);
+
+static struct device_driver snd_generic_driver = {
+	.name		= SND_GENERIC_NAME,
+	.bus		= &platform_bus_type,
+	.suspend	= snd_generic_suspend,
+	.resume		= snd_generic_resume,
+};
+
+static int generic_driver_registered;
+
+static void generic_driver_unregister(void)
+{
+	if (generic_driver_registered) {
+		generic_driver_registered--;
+		if (! generic_driver_registered)
+			driver_unregister(&snd_generic_driver);
+	}
+}
+
+static struct snd_generic_device *snd_generic_device_register(snd_card_t *card)
 {
-	snd_card_t *card = dev->data;
+	struct snd_generic_device *dev;
 
-	switch (rqst) {
-	case PM_SUSPEND:
-		if (card->power_state == SNDRV_CTL_POWER_D3hot)
-			break;
-		/* FIXME: the correct state value? */
-		card->pm_suspend(card, 0);
-		snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
-		break;
-	case PM_RESUME:
-		if (card->power_state == SNDRV_CTL_POWER_D0)
-			break;
-		/* FIXME: the correct state value? */
-		card->pm_resume(card, 0);
-		snd_power_change_state(card, SNDRV_CTL_POWER_D0);
-		break;
+	if (! generic_driver_registered) {
+		if (driver_register(&snd_generic_driver) < 0)
+			return NULL;
+	}
+	generic_driver_registered++;
+
+	dev = kcalloc(1, sizeof(*dev), GFP_KERNEL);
+	if (! dev) {
+		generic_driver_unregister();
+		return NULL;
+	}
+
+	dev->pdev.name = SND_GENERIC_NAME;
+	dev->pdev.id = card->number;
+	dev->card = card;
+	if (platform_device_register(&dev->pdev) < 0) {
+		kfree(dev);
+		generic_driver_unregister();
+		return NULL;
 	}
+	return dev;
+}
+
+static void snd_generic_device_unregister(struct snd_generic_device *dev)
+{
+	platform_device_unregister(&dev->pdev);
+	kfree(dev);
+	generic_driver_unregister();
+}
+
+/* suspend/resume callbacks for snd_generic platform device */
+static int snd_generic_suspend(struct device *dev, u32 state, u32 level)
+{
+	snd_card_t *card;
+
+	if (level != SUSPEND_DISABLE)
+		return 0;
+
+	card = get_snd_generic_card(dev);
+	if (card->power_state == SNDRV_CTL_POWER_D3hot)
+		return 0;
+	card->pm_suspend(card, PMSG_SUSPEND);
+	snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
+	return 0;
+}
+
+static int snd_generic_resume(struct device *dev, u32 level)
+{
+	snd_card_t *card;
+
+	if (level != RESUME_ENABLE)
+		return 0;
+
+	card = get_snd_generic_card(dev);
+	if (card->power_state == SNDRV_CTL_POWER_D0)
+		return 0;
+	card->pm_resume(card);
+	snd_power_change_state(card, SNDRV_CTL_POWER_D0);
 	return 0;
 }
 
 /**
- * snd_card_set_dev_pm_callback - set the generic power-management callbacks
+ * snd_card_set_generic_pm_callback - set the generic power-management callbacks
  * @card: soundcard structure
- * @type: PM device type (PM_XXX)
  * @suspend: suspend callback function
  * @resume: resume callback function
  * @private_data: private data to pass to the callback functions
  *
  * Registers the power-management and sets the lowlevel callbacks for
- * the given card with the given PM type.  These callbacks are called
- * from the ALSA's common PM handler and from the control API.
+ * the given card.  These callbacks are called from the ALSA's common
+ * PM handler and from the control API.
  */
-int snd_card_set_dev_pm_callback(snd_card_t *card, int type,
-				 int (*suspend)(snd_card_t *, unsigned int),
-				 int (*resume)(snd_card_t *, unsigned int),
+int snd_card_set_generic_pm_callback(snd_card_t *card,
+				 int (*suspend)(snd_card_t *, pm_message_t),
+				 int (*resume)(snd_card_t *),
 				 void *private_data)
 {
-	card->pm_dev = pm_register(type, 0, snd_generic_pm_callback);
+	card->pm_dev = snd_generic_device_register(card);
 	if (! card->pm_dev)
 		return -ENOMEM;
-	card->pm_dev->data = card;
 	snd_card_set_pm_callback(card, suspend, resume, private_data);
 	return 0;
 }
+#endif /* CONFIG_SND_GENERIC_PM */
 
 #ifdef CONFIG_PCI
-int snd_card_pci_suspend(struct pci_dev *dev, u32 state)
+int snd_card_pci_suspend(struct pci_dev *dev, pm_message_t state)
 {
 	snd_card_t *card = pci_get_drvdata(dev);
 	int err;
@@ -786,8 +863,7 @@
 		return 0;
 	if (card->power_state == SNDRV_CTL_POWER_D3hot)
 		return 0;
-	/* FIXME: correct state value? */
-	err = card->pm_suspend(card, 0);
+	err = card->pm_suspend(card, PMSG_SUSPEND);
 	pci_save_state(dev);
 	snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
 	return err;
@@ -802,8 +878,7 @@
 		return 0;
 	/* restore the PCI config space */
 	pci_restore_state(dev);
-	/* FIXME: correct state value? */
-	card->pm_resume(card, 0);
+	card->pm_resume(card);
 	snd_power_change_state(card, SNDRV_CTL_POWER_D0);
 	return 0;
 }
diff -Nru a/sound/core/ioctl32/Makefile b/sound/core/ioctl32/Makefile
--- a/sound/core/ioctl32/Makefile	2005-03-11 12:51:47 -08:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,11 +0,0 @@
-#
-# Makefile for ALSA
-# Copyright (c) 1999 by Jaroslav Kysela <perex@suse.cz>
-#
-
-snd-ioctl32-objs := ioctl32.o pcm32.o rawmidi32.o timer32.o hwdep32.o
-ifneq ($(CONFIG_SND_SEQUENCER),n)
-  snd-ioctl32-objs += seq32.o
-endif
-
-obj-$(CONFIG_SND_BIT32_EMUL) += snd-ioctl32.o
diff -Nru a/sound/core/ioctl32/hwdep32.c b/sound/core/ioctl32/hwdep32.c
--- a/sound/core/ioctl32/hwdep32.c	2005-03-11 12:51:51 -08:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,73 +0,0 @@
-/*
- *   32bit -> 64bit ioctl wrapper for hwdep API
- *   Copyright (c) by Takashi Iwai <tiwai@suse.de>
- *
- *   This program is free software; you can redistribute it and/or modify
- *   it under the terms of the GNU General Public License as published by
- *   the Free Software Foundation; either version 2 of the License, or
- *   (at your option) any later version.
- *
- *   This program is distributed in the hope that it will be useful,
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *   GNU General Public License for more details.
- *
- *   You should have received a copy of the GNU General Public License
- *   along with this program; if not, write to the Free Software
- *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
- *
- */
-
-#include <sound/driver.h>
-#include <linux/time.h>
-#include <linux/fs.h>
-#include <sound/core.h>
-#include <sound/hwdep.h>
-#include <asm/uaccess.h>
-#include "ioctl32.h"
-
-struct sndrv_hwdep_dsp_image32 {
-	u32 index;
-	unsigned char name[64];
-	u32 image;	/* pointer */
-	u32 length;
-	u32 driver_data;
-} /* don't set packed attribute here */;
-
-static inline int _snd_ioctl32_hwdep_dsp_image(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *file, unsigned int native_ctl)
-{
-	struct sndrv_hwdep_dsp_image __user *data, *dst;
-	struct sndrv_hwdep_dsp_image32 __user *data32, *src;
-	compat_caddr_t ptr;
-
-	data32 = compat_ptr(arg);
-	data = compat_alloc_user_space(sizeof(*data));
-
-	/* index and name */
-	if (copy_in_user(data, data32, 4 + 64))
-		return -EFAULT;
-	if (__get_user(ptr, &data32->image) ||
-	    __put_user(compat_ptr(ptr), &data->image))
-		return -EFAULT;
-	src = data32;
-	dst = data;
-	COPY_CVT(length);
-	COPY_CVT(driver_data);
-	return file->f_op->ioctl(file->f_dentry->d_inode, file, native_ctl, (unsigned long)data);
-}
-
-DEFINE_ALSA_IOCTL_ENTRY(hwdep_dsp_image, hwdep_dsp_image, SNDRV_HWDEP_IOCTL_DSP_LOAD);
-
-#define AP(x) snd_ioctl32_##x
-
-enum {
-	SNDRV_HWDEP_IOCTL_DSP_LOAD32   = _IOW('H', 0x03, struct sndrv_hwdep_dsp_image32)
-};
-
-struct ioctl32_mapper hwdep_mappers[] = {
-	MAP_COMPAT(SNDRV_HWDEP_IOCTL_PVERSION),
-	MAP_COMPAT(SNDRV_HWDEP_IOCTL_INFO),
-	MAP_COMPAT(SNDRV_HWDEP_IOCTL_DSP_STATUS),
-	{ SNDRV_HWDEP_IOCTL_DSP_LOAD32, AP(hwdep_dsp_image) },
-	{ 0 },
-};
diff -Nru a/sound/core/ioctl32/ioctl32.c b/sound/core/ioctl32/ioctl32.c
--- a/sound/core/ioctl32/ioctl32.c	2005-03-11 12:51:41 -08:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,433 +0,0 @@
-/*
- *   32bit -> 64bit ioctl wrapper for control API
- *   Copyright (c) by Takashi Iwai <tiwai@suse.de>
- *
- *   This program is free software; you can redistribute it and/or modify
- *   it under the terms of the GNU General Public License as published by
- *   the Free Software Foundation; either version 2 of the License, or
- *   (at your option) any later version.
- *
- *   This program is distributed in the hope that it will be useful,
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *   GNU General Public License for more details.
- *
- *   You should have received a copy of the GNU General Public License
- *   along with this program; if not, write to the Free Software
- *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
- *
- */
-
-#include <sound/driver.h>
-#include <linux/sched.h>
-#include <linux/smp_lock.h>
-#include <linux/init.h>
-#include <linux/time.h>
-#include <linux/slab.h>
-#include <linux/fs.h>
-#include <sound/core.h>
-#include <sound/control.h>
-#include <sound/minors.h>
-#include <asm/uaccess.h>
-#include "ioctl32.h"
-
-
-/*
- * register/unregister mappers
- * exported for other modules
- */
-
-MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>");
-MODULE_DESCRIPTION("ioctl32 wrapper for ALSA");
-MODULE_LICENSE("GPL");
-
-int register_ioctl32_conversion(unsigned int cmd, int (*handler)(unsigned int, unsigned int, unsigned long, struct file *));
-int unregister_ioctl32_conversion(unsigned int cmd);
-
-
-int snd_ioctl32_register(struct ioctl32_mapper *mappers)
-{
-	int err;
-	struct ioctl32_mapper *m;
-
-	for (m = mappers; m->cmd; m++) {
-		err = register_ioctl32_conversion(m->cmd, m->handler);
-		if (err >= 0)
-			m->registered++;
-	}
-	return 0;
-}
-
-void snd_ioctl32_unregister(struct ioctl32_mapper *mappers)
-{
-	struct ioctl32_mapper *m;
-
-	for (m = mappers; m->cmd; m++) {
-		if (m->registered) {
-			unregister_ioctl32_conversion(m->cmd);
-			m->registered = 0;
-		}
-	}
-}
-
-
-/*
- * compatible wrapper
- */
-int snd_ioctl32_compat(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *filp)
-{
-	if (! filp->f_op || ! filp->f_op->ioctl)
-		return -ENOTTY;
-	return filp->f_op->ioctl(filp->f_dentry->d_inode, filp, cmd, arg);
-}
-
-
-/*
- * Controls
- */
-
-struct sndrv_ctl_elem_list32 {
-	u32 offset;
-	u32 space;
-	u32 used;
-	u32 count;
-	u32 pids;
-	unsigned char reserved[50];
-} /* don't set packed attribute here */;
-
-static inline int _snd_ioctl32_ctl_elem_list(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *file, unsigned int native_ctl)
-{
-	struct sndrv_ctl_elem_list32 __user *data32;
-	struct sndrv_ctl_elem_list __user *data;
-	compat_caddr_t ptr;
-	int err;
-
-	data32 = compat_ptr(arg);
-	data = compat_alloc_user_space(sizeof(*data));
-
-	/* offset, space, used, count */
-	if (copy_in_user(data, data32, 4 * sizeof(u32)))
-		return -EFAULT;
-	/* pids */
-	if (__get_user(ptr, &data32->pids) ||
-	    __put_user(compat_ptr(ptr), &data->pids))
-		return -EFAULT;
-	err = file->f_op->ioctl(file->f_dentry->d_inode, file, native_ctl, (unsigned long)data);
-	if (err < 0)
-		return err;
-	/* copy the result */
-	if (copy_in_user(data32, data, 4 * sizeof(u32)))
-		return -EFAULT;
-	return 0;
-}
-
-DEFINE_ALSA_IOCTL_ENTRY(ctl_elem_list, ctl_elem_list, SNDRV_CTL_IOCTL_ELEM_LIST);
-
-/*
- * control element info
- * it uses union, so the things are not easy..
- */
-
-struct sndrv_ctl_elem_info32 {
-	struct sndrv_ctl_elem_id id; // the size of struct is same
-	s32 type;
-	u32 access;
-	u32 count;
-	s32 owner;
-	union {
-		struct {
-			s32 min;
-			s32 max;
-			s32 step;
-		} integer;
-		struct {
-			u64 min;
-			u64 max;
-			u64 step;
-		} integer64;
-		struct {
-			u32 items;
-			u32 item;
-			char name[64];
-		} enumerated;
-		unsigned char reserved[128];
-	} value;
-	unsigned char reserved[64];
-} __attribute__((packed));
-
-static inline int _snd_ioctl32_ctl_elem_info(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *file, unsigned int native_ctl)
-{
-	struct sndrv_ctl_elem_info __user *data, *src;
-	struct sndrv_ctl_elem_info32 __user *data32, *dst;
-	unsigned int type;
-	int err;
-
-	data32 = compat_ptr(arg);
-	data = compat_alloc_user_space(sizeof(*data));
-
-	/* copy id */
-	if (copy_in_user(&data->id, &data32->id, sizeof(data->id)))
-		return -EFAULT;
-	/* we need to copy the item index.
-	 * hope this doesn't break anything..
-	 */
-	if (copy_in_user(&data->value.enumerated.item,
-			 &data32->value.enumerated.item,
-			 sizeof(data->value.enumerated.item)))
-		return -EFAULT;
-	err = file->f_op->ioctl(file->f_dentry->d_inode, file, native_ctl, (unsigned long)data);
-	if (err < 0)
-		return err;
-	/* restore info to 32bit */
-	/* for COPY_CVT macro */
-	src = data;
-	dst = data32;
-	/* id, type, access, count */
-	if (copy_in_user(&data32->id, &data->id, sizeof(data->id)) ||
-	    copy_in_user(&data32->type, &data->type, 3 * sizeof(u32)))
-		return -EFAULT;
-	COPY_CVT(owner);
-	__get_user(type, &data->type);
-	switch (type) {
-	case SNDRV_CTL_ELEM_TYPE_BOOLEAN:
-	case SNDRV_CTL_ELEM_TYPE_INTEGER:
-		COPY_CVT(value.integer.min);
-		COPY_CVT(value.integer.max);
-		COPY_CVT(value.integer.step);
-		break;
-	case SNDRV_CTL_ELEM_TYPE_INTEGER64:
-		if (copy_in_user(&data32->value.integer64,
-				 &data->value.integer64,
-				 sizeof(data->value.integer64)))
-			return -EFAULT;
-		break;
-	case SNDRV_CTL_ELEM_TYPE_ENUMERATED:
-		if (copy_in_user(&data32->value.enumerated,
-				 &data->value.enumerated,
-				 sizeof(data->value.enumerated)))
-			return -EFAULT;
-		break;
-	default:
-		break;
-	}
-	return 0;
-}
-
-DEFINE_ALSA_IOCTL_ENTRY(ctl_elem_info, ctl_elem_info, SNDRV_CTL_IOCTL_ELEM_INFO);
-
-struct sndrv_ctl_elem_value32 {
-	struct sndrv_ctl_elem_id id;
-	unsigned int indirect;	/* bit-field causes misalignment */
-        union {
-		s32 integer[128];	/* integer and boolean need conversion */
-#ifndef CONFIG_X86_64
-		s64 integer64[64];	/* for alignment */
-#endif
-		unsigned char data[512];	/* others should be compatible */
-        } value;
-        unsigned char reserved[128];	/* not used */
-};
-
-
-/* hmm, it's so hard to retrieve the value type from the control id.. */
-static int get_ctl_type(snd_card_t *card, snd_ctl_elem_id_t *id)
-{
-	snd_kcontrol_t *kctl;
-	snd_ctl_elem_info_t info;
-	int err;
-
-	down_read(&card->controls_rwsem);
-	kctl = snd_ctl_find_id(card, id);
-	if (! kctl) {
-		up_read(&card->controls_rwsem);
-		return -ENXIO;
-	}
-	info.id = *id;
-	err = kctl->info(kctl, &info);
-	up_read(&card->controls_rwsem);
-	if (err >= 0)
-		err = info.type;
-	return err;
-}
-
-extern int snd_major;
-
-static inline int _snd_ioctl32_ctl_elem_value(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *file, unsigned int native_ctl)
-{
-	struct sndrv_ctl_elem_value *data;
-	struct sndrv_ctl_elem_value32 __user *data32;
-	snd_ctl_file_t *ctl;
-	int err, i, indirect;
-	int type;
-
-	/* sanity check */
-	if (imajor(file->f_dentry->d_inode) != snd_major ||
-	    SNDRV_MINOR_DEVICE(iminor(file->f_dentry->d_inode)) != SNDRV_MINOR_CONTROL)
-		return -ENOTTY;
-
-	if ((ctl = file->private_data) == NULL)
-		return -ENOTTY;
-
-	data32 = compat_ptr(arg);
-	data = kcalloc(1, sizeof(*data), GFP_KERNEL);
-	if (data == NULL)
-		return -ENOMEM;
-
-	if (copy_from_user(&data->id, &data32->id, sizeof(data->id))) {
-		err = -EFAULT;
-		goto __end;
-	}
-	if (__get_user(indirect, &data32->indirect)) {
-		err = -EFAULT;
-		goto __end;
-	}
-	/* FIXME: indirect access is not supported */
-	if (indirect) {
-		err = -EINVAL;
-		goto __end;
-	}
-	type = get_ctl_type(ctl->card, &data->id);
-	if (type < 0) {
-		err = type;
-		goto __end;
-	}
-
-	switch (type) {
-	case SNDRV_CTL_ELEM_TYPE_BOOLEAN:
-	case SNDRV_CTL_ELEM_TYPE_INTEGER:
-		for (i = 0; i < 128; i++) {
-			int val;
-			if (__get_user(val, &data32->value.integer[i])) {
-				err = -EFAULT;
-				goto __end;
-			}
-			data->value.integer.value[i] = val;
-		}
-		break;
-	case SNDRV_CTL_ELEM_TYPE_INTEGER64:
-	case SNDRV_CTL_ELEM_TYPE_ENUMERATED:
-	case SNDRV_CTL_ELEM_TYPE_BYTES:
-	case SNDRV_CTL_ELEM_TYPE_IEC958:
-		if (__copy_from_user(data->value.bytes.data,
-				     data32->value.data,
-				     sizeof(data32->value.data))) {
-			err = -EFAULT;
-			goto __end;
-		}
-		break;
-	default:
-		printk(KERN_ERR "snd_ioctl32_ctl_elem_value: unknown type %d\n", type);
-		err = -EINVAL;
-		goto __end;
-	}
-
-	if (native_ctl == SNDRV_CTL_IOCTL_ELEM_READ)
-		err = snd_ctl_elem_read(ctl->card, data);
-	else
-		err = snd_ctl_elem_write(ctl->card, ctl, data);
-	if (err < 0)
-		goto __end;
-	/* restore info to 32bit */
-	switch (type) {
-	case SNDRV_CTL_ELEM_TYPE_BOOLEAN:
-	case SNDRV_CTL_ELEM_TYPE_INTEGER:
-		for (i = 0; i < 128; i++) {
-			int val;
-			val = data->value.integer.value[i];
-			if (__put_user(val, &data32->value.integer[i])) {
-				err = -EFAULT;
-				goto __end;
-			}
-		}
-		break;
-	default:
-		if (__copy_to_user(data32->value.data,
-				   data->value.bytes.data,
-				   sizeof(data32->value.data))) {
-			err = -EFAULT;
-			goto __end;
-		}
-		break;
-		break;
-	}
-	err = 0;
-      __end:
-	kfree(data);
-	return err;
-}
-
-DEFINE_ALSA_IOCTL_ENTRY(ctl_elem_read, ctl_elem_value, SNDRV_CTL_IOCTL_ELEM_READ);
-DEFINE_ALSA_IOCTL_ENTRY(ctl_elem_write, ctl_elem_value, SNDRV_CTL_IOCTL_ELEM_WRITE);
-
-/*
- */
-
-#define AP(x) snd_ioctl32_##x
-
-enum {
-	SNDRV_CTL_IOCTL_ELEM_LIST32 = _IOWR('U', 0x10, struct sndrv_ctl_elem_list32),
-	SNDRV_CTL_IOCTL_ELEM_INFO32 = _IOWR('U', 0x11, struct sndrv_ctl_elem_info32),
-	SNDRV_CTL_IOCTL_ELEM_READ32 = _IOWR('U', 0x12, struct sndrv_ctl_elem_value32),
-	SNDRV_CTL_IOCTL_ELEM_WRITE32 = _IOWR('U', 0x13, struct sndrv_ctl_elem_value32),
-};
-
-static struct ioctl32_mapper control_mappers[] = {
-	/* controls (without rawmidi, hwdep, timer releated ones) */
-	MAP_COMPAT(SNDRV_CTL_IOCTL_PVERSION),
-	MAP_COMPAT(SNDRV_CTL_IOCTL_CARD_INFO),
-	{ SNDRV_CTL_IOCTL_ELEM_LIST32, AP(ctl_elem_list) },
-	{ SNDRV_CTL_IOCTL_ELEM_INFO32, AP(ctl_elem_info) },
-	{ SNDRV_CTL_IOCTL_ELEM_READ32, AP(ctl_elem_read) },
-	{ SNDRV_CTL_IOCTL_ELEM_WRITE32, AP(ctl_elem_write) },
-	MAP_COMPAT(SNDRV_CTL_IOCTL_ELEM_LOCK),
-	MAP_COMPAT(SNDRV_CTL_IOCTL_ELEM_UNLOCK),
-	MAP_COMPAT(SNDRV_CTL_IOCTL_SUBSCRIBE_EVENTS),
-	MAP_COMPAT(SNDRV_CTL_IOCTL_HWDEP_INFO),
-	MAP_COMPAT(SNDRV_CTL_IOCTL_HWDEP_NEXT_DEVICE),
-	MAP_COMPAT(SNDRV_CTL_IOCTL_PCM_NEXT_DEVICE),
-	MAP_COMPAT(SNDRV_CTL_IOCTL_PCM_INFO),
-	MAP_COMPAT(SNDRV_CTL_IOCTL_PCM_PREFER_SUBDEVICE),
-	MAP_COMPAT(SNDRV_CTL_IOCTL_POWER),
-	MAP_COMPAT(SNDRV_CTL_IOCTL_POWER_STATE),
-	{ 0 }
-};
-
-
-/*
- */
-
-extern struct ioctl32_mapper pcm_mappers[];
-extern struct ioctl32_mapper rawmidi_mappers[];
-extern struct ioctl32_mapper timer_mappers[];
-extern struct ioctl32_mapper hwdep_mappers[];
-#if defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE))
-extern struct ioctl32_mapper seq_mappers[];
-#endif
-
-static void snd_ioctl32_done(void)
-{
-#if defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE))
-	snd_ioctl32_unregister(seq_mappers);
-#endif
-	snd_ioctl32_unregister(hwdep_mappers);
-	snd_ioctl32_unregister(timer_mappers);
-	snd_ioctl32_unregister(rawmidi_mappers);
-	snd_ioctl32_unregister(pcm_mappers);
-	snd_ioctl32_unregister(control_mappers);
-}
-
-static int __init snd_ioctl32_init(void)
-{
-	snd_ioctl32_register(control_mappers);
-	snd_ioctl32_register(pcm_mappers);
-	snd_ioctl32_register(rawmidi_mappers);
-	snd_ioctl32_register(timer_mappers);
-	snd_ioctl32_register(hwdep_mappers);
-#if defined(CONFIG_SND_SEQUENCER) || (defined(MODULE) && defined(CONFIG_SND_SEQUENCER_MODULE))
-	snd_ioctl32_register(seq_mappers);
-#endif
-	return 0;
-}
-
-module_init(snd_ioctl32_init)
-module_exit(snd_ioctl32_done)
diff -Nru a/sound/core/ioctl32/ioctl32.h b/sound/core/ioctl32/ioctl32.h
--- a/sound/core/ioctl32/ioctl32.h	2005-03-11 12:51:42 -08:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,102 +0,0 @@
-/*
- *   32bit -> 64bit ioctl helpers
- *   Copyright (c) by Takashi Iwai <tiwai@suse.de>
- *
- *   This program is free software; you can redistribute it and/or modify
- *   it under the terms of the GNU General Public License as published by
- *   the Free Software Foundation; either version 2 of the License, or
- *   (at your option) any later version.
- *
- *   This program is distributed in the hope that it will be useful,
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *   GNU General Public License for more details.
- *
- *   You should have received a copy of the GNU General Public License
- *   along with this program; if not, write to the Free Software
- *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
- *
- *
- * This file registers the converters from 32-bit ioctls to 64-bit ones.
- * The converter assumes that a 32-bit user-pointer can be casted by compat_ptr(x)
- * macro to a valid 64-bit pointer which is accessible via copy_from/to_user.
- *
- */
-
-#ifndef __ALSA_IOCTL32_H
-#define __ALSA_IOCTL32_H
-
-#include <linux/compat.h>
-
-#define COPY(x) \
-	do { \
-		if (copy_in_user(&dst->x, &src->x, sizeof(dst->x))) \
-			return -EFAULT; \
-	} while (0)
-
-#define COPY_ARRAY(x) \
-	do { \
-		if (copy_in_user(dst->x, src->x, sizeof(dst->x))) \
-			return -EFAULT; \
-	} while (0)
-
-#define COPY_CVT(x) \
-	do { \
-		__typeof__(src->x) __val_tmp; \
-		if (get_user(__val_tmp, &src->x) || \
-		    put_user(__val_tmp, &dst->x))\
-			return -EFAULT; \
-	} while (0)
-
-#define convert_from_32(type, dstp, srcp)\
-{\
-	struct sndrv_##type __user *dst = dstp;\
-	struct sndrv_##type##32 __user *src = srcp;\
-	CVT_##sndrv_##type();\
-}
-
-#define convert_to_32(type, dstp, srcp)\
-{\
-	struct sndrv_##type __user *src = srcp;\
-	struct sndrv_##type##32 __user *dst = dstp;\
-	CVT_##sndrv_##type();\
-}
-
-
-#define DEFINE_ALSA_IOCTL(type) \
-static inline int _snd_ioctl32_##type(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *file, unsigned int native_ctl)\
-{\
-	struct sndrv_##type##32 __user *data32;\
-	struct sndrv_##type __user *data;\
-	int err;\
-	data32 = compat_ptr(arg);\
-	data = compat_alloc_user_space(sizeof(*data));\
-	convert_from_32(type, data, data32);\
-	err = file->f_op->ioctl(file->f_dentry->d_inode, file, native_ctl, (unsigned long)data);\
-	if (err < 0) \
-		return err;\
-	if (native_ctl & (_IOC_READ << _IOC_DIRSHIFT)) {\
-		convert_to_32(type, data32, data);\
-	}\
-	return 0;\
-}
-
-#define DEFINE_ALSA_IOCTL_ENTRY(name,type,native_ctl) \
-static int snd_ioctl32_##name(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *file) {\
-	return _snd_ioctl32_##type(fd, cmd, arg, file, native_ctl);\
-}
-
-#define MAP_COMPAT(ctl) { ctl, snd_ioctl32_compat }
-
-struct ioctl32_mapper {
-	unsigned int cmd;
-	int (*handler)(unsigned int, unsigned int, unsigned long, struct file * filp);
-	int registered;
-};
-
-int snd_ioctl32_compat(unsigned int, unsigned int, unsigned long, struct file *);
-
-int snd_ioctl32_register(struct ioctl32_mapper *mappers);
-void snd_ioctl32_unregister(struct ioctl32_mapper *mappers);
-
-#endif /* __ALSA_IOCTL32_H */
diff -Nru a/sound/core/ioctl32/pcm32.c b/sound/core/ioctl32/pcm32.c
--- a/sound/core/ioctl32/pcm32.c	2005-03-11 12:51:47 -08:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,464 +0,0 @@
-/*
- *   32bit -> 64bit ioctl wrapper for PCM API
- *   Copyright (c) by Takashi Iwai <tiwai@suse.de>
- *
- *   This program is free software; you can redistribute it and/or modify
- *   it under the terms of the GNU General Public License as published by
- *   the Free Software Foundation; either version 2 of the License, or
- *   (at your option) any later version.
- *
- *   This program is distributed in the hope that it will be useful,
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *   GNU General Public License for more details.
- *
- *   You should have received a copy of the GNU General Public License
- *   along with this program; if not, write to the Free Software
- *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
- *
- */
-
-#include <sound/driver.h>
-#include <linux/time.h>
-#include <linux/slab.h>
-#include <linux/compat.h>
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include <sound/minors.h>
-#include "ioctl32.h"
-
-
-/* wrapper for sndrv_pcm_[us]frames */
-struct sndrv_pcm_sframes_str {
-	sndrv_pcm_sframes_t val;
-};
-struct sndrv_pcm_sframes_str32 {
-	s32 val;
-};
-struct sndrv_pcm_uframes_str {
-	sndrv_pcm_uframes_t val;
-};
-struct sndrv_pcm_uframes_str32 {
-	u32 val;
-};
-
-#define CVT_sndrv_pcm_sframes_str() { COPY_CVT(val); }
-#define CVT_sndrv_pcm_uframes_str() { COPY_CVT(val); }
-
-
-struct sndrv_pcm_hw_params32 {
-	u32 flags;
-	struct sndrv_mask masks[SNDRV_PCM_HW_PARAM_LAST_MASK - SNDRV_PCM_HW_PARAM_FIRST_MASK + 1]; /* this must be identical */
-	struct sndrv_mask mres[5];	/* reserved masks */
-	struct sndrv_interval intervals[SNDRV_PCM_HW_PARAM_LAST_INTERVAL - SNDRV_PCM_HW_PARAM_FIRST_INTERVAL + 1];
-	struct sndrv_interval ires[9];	/* reserved intervals */
-	u32 rmask;
-	u32 cmask;
-	u32 info;
-	u32 msbits;
-	u32 rate_num;
-	u32 rate_den;
-	u32 fifo_size;
-	unsigned char reserved[64];
-} __attribute__((packed));
-
-struct sndrv_pcm_sw_params32 {
-	s32 tstamp_mode;
-	u32 period_step;
-	u32 sleep_min;
-	u32 avail_min;
-	u32 xfer_align;
-	u32 start_threshold;
-	u32 stop_threshold;
-	u32 silence_threshold;
-	u32 silence_size;
-	u32 boundary;
-	unsigned char reserved[64];
-} __attribute__((packed));
-
-#define CVT_sndrv_pcm_sw_params()\
-{\
-	COPY(tstamp_mode);\
-	COPY(period_step);\
-	COPY(sleep_min);\
-	COPY_CVT(avail_min);\
-	COPY_CVT(xfer_align);\
-	COPY_CVT(start_threshold);\
-	COPY_CVT(stop_threshold);\
-	COPY_CVT(silence_threshold);\
-	COPY_CVT(silence_size);\
-	COPY_CVT(boundary);\
-}
-
-struct sndrv_pcm_channel_info32 {
-	u32 channel;
-	u32 offset;
-	u32 first;
-	u32 step;
-} __attribute__((packed));
-
-#define CVT_sndrv_pcm_channel_info()\
-{\
-	COPY(channel);\
-	COPY_CVT(offset);\
-	COPY(first);\
-	COPY(step);\
-}
-
-struct sndrv_pcm_status32 {
-	s32 state;
-	struct compat_timespec trigger_tstamp;
-	struct compat_timespec tstamp;
-	u32 appl_ptr;
-	u32 hw_ptr;
-	s32 delay;
-	u32 avail;
-	u32 avail_max;
-	u32 overrange;
-	s32 suspended_state;
-	unsigned char reserved[60];
-} __attribute__((packed));
-
-#define CVT_sndrv_pcm_status()\
-{\
-	COPY(state);\
-	COPY_CVT(trigger_tstamp.tv_sec);\
-	COPY_CVT(trigger_tstamp.tv_nsec);\
-	COPY_CVT(tstamp.tv_sec);\
-	COPY_CVT(tstamp.tv_nsec);\
-	COPY_CVT(appl_ptr);\
-	COPY_CVT(hw_ptr);\
-	COPY_CVT(delay);\
-	COPY_CVT(avail);\
-	COPY_CVT(avail_max);\
-	COPY_CVT(overrange);\
-	COPY(suspended_state);\
-}
-
-DEFINE_ALSA_IOCTL(pcm_uframes_str);
-DEFINE_ALSA_IOCTL(pcm_sframes_str);
-DEFINE_ALSA_IOCTL(pcm_sw_params);
-DEFINE_ALSA_IOCTL(pcm_channel_info);
-DEFINE_ALSA_IOCTL(pcm_status);
-
-/* sanity device check */
-extern int snd_major;
-static int sanity_check_pcm(struct file *file)
-{
-	unsigned short minor;
-	if (imajor(file->f_dentry->d_inode) != snd_major)
-		return -ENOTTY;
-	minor = iminor(file->f_dentry->d_inode);
-	if (minor >= 256 || 
-	    minor % SNDRV_MINOR_DEVICES < SNDRV_MINOR_PCM_PLAYBACK)
-		return -ENOTTY;
-	return 0;
-}
-
-/* recalcuate the boundary within 32bit */
-static void recalculate_boundary(snd_pcm_runtime_t *runtime)
-{
-	if (! runtime->buffer_size)
-		return;
-	runtime->boundary = runtime->buffer_size;
-	while (runtime->boundary * 2 <= 0x7fffffffUL - runtime->buffer_size)
-		runtime->boundary *= 2;
-}
-
-/* both for HW_PARAMS and HW_REFINE */
-static int _snd_ioctl32_pcm_hw_params(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *file, unsigned int native_ctl)
-{
-	struct sndrv_pcm_hw_params32 __user *data32;
-	struct sndrv_pcm_hw_params *data;
-	snd_pcm_file_t *pcm_file;
-	snd_pcm_substream_t *substream;
-	snd_pcm_runtime_t *runtime;
-	int err;
-
-	if (sanity_check_pcm(file))
-		return -ENOTTY;
-	if (! (pcm_file = file->private_data))
-		return -ENOTTY;
-	if (! (substream = pcm_file->substream))
-		return -ENOTTY;
-	if (! (runtime = substream->runtime))
-		return -ENOTTY;
-
-	data32 = compat_ptr(arg);
-	data = kmalloc(sizeof(*data), GFP_KERNEL);
-	if (data == NULL)
-		return -ENOMEM;
-	if (copy_from_user(data, data32, sizeof(*data32))) {
-		err = -EFAULT;
-		goto error;
-	}
-	if (native_ctl == SNDRV_PCM_IOCTL_HW_REFINE)
-		err = snd_pcm_hw_refine(substream, data);
-	else
-		err = snd_pcm_hw_params(substream, data);
-	if (err < 0)
-		goto error;
-	if (copy_to_user(data32, data, sizeof(*data32)) ||
-	    __put_user((u32)data->fifo_size, &data32->fifo_size)) {
-		err = -EFAULT;
-		goto error;
-	}
-
-	if (native_ctl == SNDRV_PCM_IOCTL_HW_PARAMS)
-		recalculate_boundary(runtime);
- error:
-	kfree(data);
-	return err;
-}
-
-
-/*
- */
-struct sndrv_xferi32 {
-	s32 result;
-	u32 buf;
-	u32 frames;
-} __attribute__((packed));
-
-static int _snd_ioctl32_xferi(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *file, unsigned int native_ctl)
-{
-	struct sndrv_xferi32 data32;
-	struct sndrv_xferi __user *data;
-	snd_pcm_sframes_t result;
-	int err;
-
-	if (copy_from_user(&data32, (void __user *)arg, sizeof(data32)))
-		return -EFAULT;
-	data = compat_alloc_user_space(sizeof(*data));
-	if (put_user((snd_pcm_sframes_t)data32.result, &data->result) ||
-	    __put_user(compat_ptr(data32.buf), &data->buf) ||
-	    __put_user((snd_pcm_uframes_t)data32.frames, &data->frames))
-		return -EFAULT;
-	err = file->f_op->ioctl(file->f_dentry->d_inode, file, native_ctl, (unsigned long)data);
-	if (err < 0)
-		return err;
-	/* copy the result */
-	if (__get_user(result, &data->result))
-		return -EFAULT;
-	data32.result = result;
-	if (copy_to_user((void __user *)arg, &data32, sizeof(data32)))
-		return -EFAULT;
-	return 0;
-}
-
-
-/* snd_xfern needs remapping of bufs */
-struct sndrv_xfern32 {
-	s32 result;
-	u32 bufs;  /* this is void **; */
-	u32 frames;
-} __attribute__((packed));
-
-/*
- * xfern ioctl nees to copy (up to) 128 pointers on stack.
- * although we may pass the copied pointers through f_op->ioctl, but the ioctl
- * handler there expands again the same 128 pointers on stack, so it is better
- * to handle the function (calling pcm_readv/writev) directly in this handler.
- */
-static int _snd_ioctl32_xfern(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *file, unsigned int native_ctl)
-{
-	snd_pcm_file_t *pcm_file;
-	snd_pcm_substream_t *substream;
-	struct sndrv_xfern32 __user *srcptr = compat_ptr(arg);
-	struct sndrv_xfern32 data32;
-	void __user **bufs;
-	int err = 0, ch, i;
-	u32 __user *bufptr;
-
-	if (sanity_check_pcm(file))
-		return -ENOTTY;
-	if (! (pcm_file = file->private_data))
-		return -ENOTTY;
-	if (! (substream = pcm_file->substream))
-		return -ENOTTY;
-	if (! substream->runtime)
-		return -ENOTTY;
-
-	/* check validty of the command */
-	switch (native_ctl) {
-	case SNDRV_PCM_IOCTL_WRITEN_FRAMES:
-		if (substream->stream  != SNDRV_PCM_STREAM_PLAYBACK)
-			return -EINVAL;
-		if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN)
-			return -EBADFD;
-		break;
-	case SNDRV_PCM_IOCTL_READN_FRAMES:
-		if (substream->stream  != SNDRV_PCM_STREAM_CAPTURE)
-			return -EINVAL;
-		break;
-	}
-	if ((ch = substream->runtime->channels) > 128)
-		return -EINVAL;
-	if (copy_from_user(&data32, (void __user *)arg, sizeof(data32)))
-		return -EFAULT;
-	bufptr = compat_ptr(data32.bufs);
-	bufs = kmalloc(sizeof(void __user *) * ch, GFP_KERNEL);
-	if (bufs == NULL)
-		return -ENOMEM;
-	for (i = 0; i < ch; i++) {
-		u32 ptr;
-		if (get_user(ptr, bufptr)) {
-			kfree(bufs);
-			return -EFAULT;
-		}
-		bufs[ch] = compat_ptr(ptr);
-		bufptr++;
-	}
-	switch (native_ctl) {
-	case SNDRV_PCM_IOCTL_WRITEN_FRAMES:
-		err = snd_pcm_lib_writev(substream, bufs, data32.frames);
-		break;
-	case SNDRV_PCM_IOCTL_READN_FRAMES:
-		err = snd_pcm_lib_readv(substream, bufs, data32.frames);
-		break;
-	}
-	if (err >= 0) {
-		if (put_user(err, &srcptr->result))
-			err = -EFAULT;
-	}
-	kfree(bufs);
-	return err;
-}
-
-
-struct sndrv_pcm_mmap_status32 {
-	s32 state;
-	s32 pad1;
-	u32 hw_ptr;
-	struct compat_timespec tstamp;
-	s32 suspended_state;
-} __attribute__((packed));
-
-struct sndrv_pcm_mmap_control32 {
-	u32 appl_ptr;
-	u32 avail_min;
-} __attribute__((packed));
-
-struct sndrv_pcm_sync_ptr32 {
-	u32 flags;
-	union {
-		struct sndrv_pcm_mmap_status32 status;
-		unsigned char reserved[64];
-	} s;
-	union {
-		struct sndrv_pcm_mmap_control32 control;
-		unsigned char reserved[64];
-	} c;
-} __attribute__((packed));
-
-#define CVT_sndrv_pcm_sync_ptr()\
-{\
-	COPY(flags);\
-	COPY(s.status.state);\
-	COPY(s.status.pad1);\
-	COPY_CVT(s.status.hw_ptr);\
-	COPY_CVT(s.status.tstamp.tv_sec);\
-	COPY_CVT(s.status.tstamp.tv_nsec);\
-	COPY(s.status.suspended_state);\
-	COPY_CVT(c.control.appl_ptr);\
-	COPY_CVT(c.control.avail_min);\
-}
-
-DEFINE_ALSA_IOCTL(pcm_sync_ptr);
-
-/*
- */
-
-DEFINE_ALSA_IOCTL_ENTRY(pcm_hw_refine, pcm_hw_params, SNDRV_PCM_IOCTL_HW_REFINE);
-DEFINE_ALSA_IOCTL_ENTRY(pcm_hw_params, pcm_hw_params, SNDRV_PCM_IOCTL_HW_PARAMS);
-DEFINE_ALSA_IOCTL_ENTRY(pcm_sw_params, pcm_sw_params, SNDRV_PCM_IOCTL_SW_PARAMS);
-DEFINE_ALSA_IOCTL_ENTRY(pcm_status, pcm_status, SNDRV_PCM_IOCTL_STATUS);
-DEFINE_ALSA_IOCTL_ENTRY(pcm_delay, pcm_sframes_str, SNDRV_PCM_IOCTL_DELAY);
-DEFINE_ALSA_IOCTL_ENTRY(pcm_channel_info, pcm_channel_info, SNDRV_PCM_IOCTL_CHANNEL_INFO);
-DEFINE_ALSA_IOCTL_ENTRY(pcm_rewind, pcm_uframes_str, SNDRV_PCM_IOCTL_REWIND);
-DEFINE_ALSA_IOCTL_ENTRY(pcm_forward, pcm_uframes_str, SNDRV_PCM_IOCTL_FORWARD);
-DEFINE_ALSA_IOCTL_ENTRY(pcm_readi, xferi, SNDRV_PCM_IOCTL_READI_FRAMES);
-DEFINE_ALSA_IOCTL_ENTRY(pcm_writei, xferi, SNDRV_PCM_IOCTL_WRITEI_FRAMES);
-DEFINE_ALSA_IOCTL_ENTRY(pcm_readn, xfern, SNDRV_PCM_IOCTL_READN_FRAMES);
-DEFINE_ALSA_IOCTL_ENTRY(pcm_writen, xfern, SNDRV_PCM_IOCTL_WRITEN_FRAMES);
-DEFINE_ALSA_IOCTL_ENTRY(pcm_sync_ptr, pcm_sync_ptr, SNDRV_PCM_IOCTL_SYNC_PTR);
-
-
-/*
- * When PCM is used on 32bit mode, we need to disable
- * mmap of PCM status/control records because of the size
- * incompatibility.
- * 
- * Since INFO ioctl is always called at first, we mark the
- * mmap-disabling in this ioctl wrapper.
- */
-static int snd_pcm_info_ioctl32(unsigned int fd, unsigned int cmd, unsigned long arg, struct file *filp)
-{
-	snd_pcm_file_t *pcm_file;
-	snd_pcm_substream_t *substream;
-	if (! filp->f_op || ! filp->f_op->ioctl)
-		return -ENOTTY;
-	pcm_file = filp->private_data;
-	if (! pcm_file)
-		return -ENOTTY;
-	substream = pcm_file->substream;
-	if (! substream)
-		return -ENOTTY;
-	substream->no_mmap_ctrl = 1;
-	return filp->f_op->ioctl(filp->f_dentry->d_inode, filp, cmd, arg);
-}
-
-/*
- */
-#define AP(x) snd_ioctl32_##x
-
-enum {
-	SNDRV_PCM_IOCTL_HW_REFINE32 = _IOWR('A', 0x10, struct sndrv_pcm_hw_params32),
-	SNDRV_PCM_IOCTL_HW_PARAMS32 = _IOWR('A', 0x11, struct sndrv_pcm_hw_params32),
-	SNDRV_PCM_IOCTL_SW_PARAMS32 = _IOWR('A', 0x13, struct sndrv_pcm_sw_params32),
-	SNDRV_PCM_IOCTL_STATUS32 = _IOR('A', 0x20, struct sndrv_pcm_status32),
-	SNDRV_PCM_IOCTL_DELAY32 = _IOR('A', 0x21, s32),
-	SNDRV_PCM_IOCTL_CHANNEL_INFO32 = _IOR('A', 0x32, struct sndrv_pcm_channel_info32),
-	SNDRV_PCM_IOCTL_REWIND32 = _IOW('A', 0x46, u32),
-	SNDRV_PCM_IOCTL_FORWARD32 = _IOW('A', 0x49, u32),
-	SNDRV_PCM_IOCTL_WRITEI_FRAMES32 = _IOW('A', 0x50, struct sndrv_xferi32),
-	SNDRV_PCM_IOCTL_READI_FRAMES32 = _IOR('A', 0x51, struct sndrv_xferi32),
-	SNDRV_PCM_IOCTL_WRITEN_FRAMES32 = _IOW('A', 0x52, struct sndrv_xfern32),
-	SNDRV_PCM_IOCTL_READN_FRAMES32 = _IOR('A', 0x53, struct sndrv_xfern32),
-	SNDRV_PCM_IOCTL_SYNC_PTR32 = _IOWR('A', 0x23, struct sndrv_pcm_sync_ptr32),
-
-};
-
-struct ioctl32_mapper pcm_mappers[] = {
-	MAP_COMPAT(SNDRV_PCM_IOCTL_PVERSION),
-	/* MAP_COMPAT(SNDRV_PCM_IOCTL_INFO), */
-	{ SNDRV_PCM_IOCTL_INFO, snd_pcm_info_ioctl32 },
-	MAP_COMPAT(SNDRV_PCM_IOCTL_TSTAMP),
-	{ SNDRV_PCM_IOCTL_HW_REFINE32, AP(pcm_hw_refine) },
-	{ SNDRV_PCM_IOCTL_HW_PARAMS32, AP(pcm_hw_params) },
-	MAP_COMPAT(SNDRV_PCM_IOCTL_HW_FREE),
-	{ SNDRV_PCM_IOCTL_SW_PARAMS32, AP(pcm_sw_params) },
-	{ SNDRV_PCM_IOCTL_STATUS32, AP(pcm_status) },
-	{ SNDRV_PCM_IOCTL_DELAY32, AP(pcm_delay) },
-	MAP_COMPAT(SNDRV_PCM_IOCTL_HWSYNC),
-	{ SNDRV_PCM_IOCTL_SYNC_PTR32, AP(pcm_sync_ptr) },
-	{ SNDRV_PCM_IOCTL_CHANNEL_INFO32, AP(pcm_channel_info) },
-	MAP_COMPAT(SNDRV_PCM_IOCTL_PREPARE),
-	MAP_COMPAT(SNDRV_PCM_IOCTL_RESET),
-	MAP_COMPAT(SNDRV_PCM_IOCTL_START),
-	MAP_COMPAT(SNDRV_PCM_IOCTL_DROP),
-	MAP_COMPAT(SNDRV_PCM_IOCTL_DRAIN),
-	MAP_COMPAT(SNDRV_PCM_IOCTL_PAUSE),
-	{ SNDRV_PCM_IOCTL_REWIND32, AP(pcm_rewind) },
-	MAP_COMPAT(SNDRV_PCM_IOCTL_RESUME),
-	MAP_COMPAT(SNDRV_PCM_IOCTL_XRUN),
-	{ SNDRV_PCM_IOCTL_FORWARD32, AP(pcm_forward) },
-	{ SNDRV_PCM_IOCTL_WRITEI_FRAMES32, AP(pcm_writei) },
-	{ SNDRV_PCM_IOCTL_READI_FRAMES32, AP(pcm_readi) },
-	{ SNDRV_PCM_IOCTL_WRITEN_FRAMES32, AP(pcm_writen) },
-	{ SNDRV_PCM_IOCTL_READN_FRAMES32, AP(pcm_readn) },
-	MAP_COMPAT(SNDRV_PCM_IOCTL_LINK),
-	MAP_COMPAT(SNDRV_PCM_IOCTL_UNLINK),
-
-	{ 0 },
-};
diff -Nru a/sound/core/ioctl32/rawmidi32.c b/sound/core/ioctl32/rawmidi32.c
--- a/sound/core/ioctl32/rawmidi32.c	2005-03-11 12:51:46 -08:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,91 +0,0 @@
-/*
- *   32bit -> 64bit ioctl wrapper for raw MIDI API
- *   Copyright (c) by Takashi Iwai <tiwai@suse.de>
- *
- *   This program is free software; you can redistribute it and/or modify
- *   it under the terms of the GNU General Public License as published by
- *   the Free Software Foundation; either version 2 of the License, or
- *   (at your option) any later version.
- *
- *   This program is distributed in the hope that it will be useful,
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *   GNU General Public License for more details.
- *
- *   You should have received a copy of the GNU General Public License
- *   along with this program; if not, write to the Free Software
- *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
- *
- */
-
-#include <sound/driver.h>
-#include <linux/time.h>
-#include <linux/fs.h>
-#include <linux/compat.h>
-#include <sound/core.h>
-#include <sound/rawmidi.h>
-#include <asm/uaccess.h>
-#include "ioctl32.h"
-
-struct sndrv_rawmidi_params32 {
-	s32 stream;
-	u32 buffer_size;
-	u32 avail_min;
-	unsigned int no_active_sensing; /* avoid bit-field */
-	unsigned char reserved[16];
-} __attribute__((packed));
-
-#define CVT_sndrv_rawmidi_params()\
-{\
-	COPY(stream);\
-	COPY_CVT(buffer_size);\
-	COPY_CVT(avail_min);\
-	if (copy_in_user(((size_t __user *)&dst->avail_min + 1),\
-			 ((size_t __user *)&src->avail_min + 1), 4)) \
-		return -EFAULT;\
-}
-
-struct sndrv_rawmidi_status32 {
-	s32 stream;
-	struct compat_timespec tstamp;
-	u32 avail;
-	u32 xruns;
-	unsigned char reserved[16];
-} __attribute__((packed));
-
-#define CVT_sndrv_rawmidi_status()\
-{\
-	COPY(stream);\
-	COPY_CVT(tstamp.tv_sec);\
-	COPY_CVT(tstamp.tv_nsec);\
-	COPY_CVT(avail);\
-	COPY_CVT(xruns);\
-}
-
-DEFINE_ALSA_IOCTL(rawmidi_params);
-DEFINE_ALSA_IOCTL(rawmidi_status);
-
-DEFINE_ALSA_IOCTL_ENTRY(rawmidi_params, rawmidi_params, SNDRV_RAWMIDI_IOCTL_PARAMS);
-DEFINE_ALSA_IOCTL_ENTRY(rawmidi_status, rawmidi_status, SNDRV_RAWMIDI_IOCTL_STATUS);
-
-#define AP(x) snd_ioctl32_##x
-
-enum {
-	SNDRV_RAWMIDI_IOCTL_PARAMS32 = _IOWR('W', 0x10, struct sndrv_rawmidi_params32),
-	SNDRV_RAWMIDI_IOCTL_STATUS32 = _IOWR('W', 0x20, struct sndrv_rawmidi_status32),
-};
-
-struct ioctl32_mapper rawmidi_mappers[] = {
-	MAP_COMPAT(SNDRV_RAWMIDI_IOCTL_PVERSION),
-	MAP_COMPAT(SNDRV_RAWMIDI_IOCTL_INFO),
-	{ SNDRV_RAWMIDI_IOCTL_PARAMS32, AP(rawmidi_params) },
-	{ SNDRV_RAWMIDI_IOCTL_STATUS32, AP(rawmidi_status) },
-	MAP_COMPAT(SNDRV_RAWMIDI_IOCTL_DROP),
-	MAP_COMPAT(SNDRV_RAWMIDI_IOCTL_DRAIN),
-
-	MAP_COMPAT(SNDRV_CTL_IOCTL_RAWMIDI_NEXT_DEVICE),
-	MAP_COMPAT(SNDRV_CTL_IOCTL_RAWMIDI_INFO),
-	MAP_COMPAT(SNDRV_CTL_IOCTL_RAWMIDI_PREFER_SUBDEVICE),
-
-	{ 0 },
-};
diff -Nru a/sound/core/ioctl32/seq32.c b/sound/core/ioctl32/seq32.c
--- a/sound/core/ioctl32/seq32.c	2005-03-11 12:51:52 -08:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,116 +0,0 @@
-/*
- *   32bit -> 64bit ioctl wrapper for sequencer API
- *   Copyright (c) by Takashi Iwai <tiwai@suse.de>
- *
- *   This program is free software; you can redistribute it and/or modify
- *   it under the terms of the GNU General Public License as published by
- *   the Free Software Foundation; either version 2 of the License, or
- *   (at your option) any later version.
- *
- *   This program is distributed in the hope that it will be useful,
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *   GNU General Public License for more details.
- *
- *   You should have received a copy of the GNU General Public License
- *   along with this program; if not, write to the Free Software
- *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
- *
- */
-
-#include <sound/driver.h>
-#include <linux/time.h>
-#include <linux/fs.h>
-#include <sound/core.h>
-#include <sound/timer.h>
-#include <asm/uaccess.h>
-#include <sound/asequencer.h>
-#include "ioctl32.h"
-
-struct sndrv_seq_port_info32 {
-	struct sndrv_seq_addr addr;	/* client/port numbers */
-	char name[64];			/* port name */
-
-	u32 capability;	/* port capability bits */
-	u32 type;		/* port type bits */
-	s32 midi_channels;		/* channels per MIDI port */
-	s32 midi_voices;		/* voices per MIDI port */
-	s32 synth_voices;		/* voices per SYNTH port */
-
-	s32 read_use;			/* R/O: subscribers for output (from this port) */
-	s32 write_use;			/* R/O: subscribers for input (to this port) */
-
-	u32 kernel;			/* reserved for kernel use (must be NULL) */
-	u32 flags;		/* misc. conditioning */
-	unsigned char time_queue;	/* queue # for timestamping */
-	char reserved[59];		/* for future use */
-};
-
-#define CVT_sndrv_seq_port_info()\
-{\
-	COPY(addr);\
-	COPY_ARRAY(name);\
-	COPY(capability);\
-	COPY(type);\
-	COPY(midi_channels);\
-	COPY(midi_voices);\
-	COPY(synth_voices);\
-	COPY(read_use);\
-	COPY(write_use);\
-	COPY(flags);\
-	COPY(time_queue);\
-}
-
-DEFINE_ALSA_IOCTL(seq_port_info);
-DEFINE_ALSA_IOCTL_ENTRY(create_port, seq_port_info, SNDRV_SEQ_IOCTL_CREATE_PORT);
-DEFINE_ALSA_IOCTL_ENTRY(delete_port, seq_port_info, SNDRV_SEQ_IOCTL_DELETE_PORT);
-DEFINE_ALSA_IOCTL_ENTRY(get_port_info, seq_port_info, SNDRV_SEQ_IOCTL_GET_PORT_INFO);
-DEFINE_ALSA_IOCTL_ENTRY(set_port_info, seq_port_info, SNDRV_SEQ_IOCTL_SET_PORT_INFO);
-DEFINE_ALSA_IOCTL_ENTRY(query_next_port, seq_port_info, SNDRV_SEQ_IOCTL_QUERY_NEXT_PORT);
-
-/*
- */
-#define AP(x) snd_ioctl32_##x
-
-enum {
-  SNDRV_SEQ_IOCTL_CREATE_PORT32 = _IOWR('S', 0x20, struct sndrv_seq_port_info32),
-  SNDRV_SEQ_IOCTL_DELETE_PORT32 = _IOW ('S', 0x21, struct sndrv_seq_port_info32),
-  SNDRV_SEQ_IOCTL_GET_PORT_INFO32 = _IOWR('S', 0x22, struct sndrv_seq_port_info32),
-  SNDRV_SEQ_IOCTL_SET_PORT_INFO32 = _IOW ('S', 0x23, struct sndrv_seq_port_info32),
-  SNDRV_SEQ_IOCTL_QUERY_NEXT_PORT32 = _IOWR('S', 0x52, struct sndrv_seq_port_info32),
-};
-
-struct ioctl32_mapper seq_mappers[] = {
-	MAP_COMPAT(SNDRV_SEQ_IOCTL_PVERSION),
-	MAP_COMPAT(SNDRV_SEQ_IOCTL_CLIENT_ID),
-	MAP_COMPAT(SNDRV_SEQ_IOCTL_SYSTEM_INFO),
-	MAP_COMPAT(SNDRV_SEQ_IOCTL_GET_CLIENT_INFO),
-	MAP_COMPAT(SNDRV_SEQ_IOCTL_SET_CLIENT_INFO),
-	{ SNDRV_SEQ_IOCTL_CREATE_PORT32, AP(create_port) },
-	{ SNDRV_SEQ_IOCTL_DELETE_PORT32, AP(delete_port) },
-	{ SNDRV_SEQ_IOCTL_GET_PORT_INFO32, AP(get_port_info) },
-	{ SNDRV_SEQ_IOCTL_SET_PORT_INFO32, AP(set_port_info) },
-	MAP_COMPAT(SNDRV_SEQ_IOCTL_SUBSCRIBE_PORT),
-	MAP_COMPAT(SNDRV_SEQ_IOCTL_UNSUBSCRIBE_PORT),
-	MAP_COMPAT(SNDRV_SEQ_IOCTL_CREATE_QUEUE),
-	MAP_COMPAT(SNDRV_SEQ_IOCTL_DELETE_QUEUE),
-	MAP_COMPAT(SNDRV_SEQ_IOCTL_GET_QUEUE_INFO),
-	MAP_COMPAT(SNDRV_SEQ_IOCTL_SET_QUEUE_INFO),
-	MAP_COMPAT(SNDRV_SEQ_IOCTL_GET_NAMED_QUEUE),
-	MAP_COMPAT(SNDRV_SEQ_IOCTL_GET_QUEUE_STATUS),
-	MAP_COMPAT(SNDRV_SEQ_IOCTL_GET_QUEUE_TEMPO),
-	MAP_COMPAT(SNDRV_SEQ_IOCTL_SET_QUEUE_TEMPO),
-	MAP_COMPAT(SNDRV_SEQ_IOCTL_GET_QUEUE_TIMER),
-	MAP_COMPAT(SNDRV_SEQ_IOCTL_SET_QUEUE_TIMER),
-	MAP_COMPAT(SNDRV_SEQ_IOCTL_GET_QUEUE_CLIENT),
-	MAP_COMPAT(SNDRV_SEQ_IOCTL_SET_QUEUE_CLIENT),
-	MAP_COMPAT(SNDRV_SEQ_IOCTL_GET_CLIENT_POOL),
-	MAP_COMPAT(SNDRV_SEQ_IOCTL_SET_CLIENT_POOL),
-	MAP_COMPAT(SNDRV_SEQ_IOCTL_REMOVE_EVENTS),
-	MAP_COMPAT(SNDRV_SEQ_IOCTL_QUERY_SUBS),
-	MAP_COMPAT(SNDRV_SEQ_IOCTL_GET_SUBSCRIPTION),
-	MAP_COMPAT(SNDRV_SEQ_IOCTL_QUERY_NEXT_CLIENT),
-	{ SNDRV_SEQ_IOCTL_QUERY_NEXT_PORT32, AP(query_next_port) },
-	MAP_COMPAT(SNDRV_SEQ_IOCTL_RUNNING_MODE),
-	{ 0 },
-};
diff -Nru a/sound/core/ioctl32/timer32.c b/sound/core/ioctl32/timer32.c
--- a/sound/core/ioctl32/timer32.c	2005-03-11 12:51:46 -08:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,105 +0,0 @@
-/*
- *   32bit -> 64bit ioctl wrapper for timer API
- *   Copyright (c) by Takashi Iwai <tiwai@suse.de>
- *
- *   This program is free software; you can redistribute it and/or modify
- *   it under the terms of the GNU General Public License as published by
- *   the Free Software Foundation; either version 2 of the License, or
- *   (at your option) any later version.
- *
- *   This program is distributed in the hope that it will be useful,
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *   GNU General Public License for more details.
- *
- *   You should have received a copy of the GNU General Public License
- *   along with this program; if not, write to the Free Software
- *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
- *
- */
-
-#include <sound/driver.h>
-#include <linux/time.h>
-#include <linux/fs.h>
-#include <linux/compat.h>
-#include <sound/core.h>
-#include <sound/timer.h>
-#include <asm/uaccess.h>
-#include "ioctl32.h"
-
-struct sndrv_timer_info32 {
-	u32 flags;
-	s32 card;
-	unsigned char id[64];
-	unsigned char name[80];
-	u32 reserved0;
-	u32 resolution;
-	unsigned char reserved[64];
-};
-
-#define CVT_sndrv_timer_info()\
-{\
-	COPY(flags);\
-	COPY(card);\
-	COPY_ARRAY(id);\
-	COPY_ARRAY(name);\
-	COPY_CVT(resolution);\
-}
-
-struct sndrv_timer_status32 {
-	struct compat_timespec tstamp;
-	u32 resolution;
-	u32 lost;
-	u32 overrun;
-	u32 queue;
-	unsigned char reserved[64];
-};
-
-#define CVT_sndrv_timer_status()\
-{\
-	COPY_CVT(tstamp.tv_sec);\
-	COPY_CVT(tstamp.tv_nsec);\
-	COPY(resolution);\
-	COPY(lost);\
-	COPY(overrun);\
-	COPY(queue);\
-}
-
-DEFINE_ALSA_IOCTL(timer_info);
-DEFINE_ALSA_IOCTL(timer_status);
-
-DEFINE_ALSA_IOCTL_ENTRY(timer_info, timer_info, SNDRV_TIMER_IOCTL_INFO);
-DEFINE_ALSA_IOCTL_ENTRY(timer_status, timer_status, SNDRV_TIMER_IOCTL_STATUS);
-
-/*
- */
-
-#define AP(x) snd_ioctl32_##x
-
-enum {
-	SNDRV_TIMER_IOCTL_INFO32 = _IOR('T', 0x11, struct sndrv_timer_info32),
-	SNDRV_TIMER_IOCTL_STATUS32 = _IOW('T', 0x14, struct sndrv_timer_status32),
-};
-
-struct ioctl32_mapper timer_mappers[] = {
-	MAP_COMPAT(SNDRV_TIMER_IOCTL_PVERSION),
-	MAP_COMPAT(SNDRV_TIMER_IOCTL_NEXT_DEVICE),
-	MAP_COMPAT(SNDRV_TIMER_IOCTL_SELECT),
-	{ SNDRV_TIMER_IOCTL_INFO32, AP(timer_info) },
-	MAP_COMPAT(SNDRV_TIMER_IOCTL_PARAMS),
-	{ SNDRV_TIMER_IOCTL_STATUS32, AP(timer_status) },
-#if 0
-	/* ** FIXME **
-	 * The following four entries are disabled because they conflict
-	 * with the TCOC* definitions.
-	 * Unfortunately, the current ioctl32 wrapper uses a single
-	 * hash table for all devices.  Once when the wrapper is fixed
-	 * with the table based on devices, they'll be back again.
-	 */
-	MAP_COMPAT(SNDRV_TIMER_IOCTL_START),
-	MAP_COMPAT(SNDRV_TIMER_IOCTL_STOP),
-	MAP_COMPAT(SNDRV_TIMER_IOCTL_CONTINUE),
-	MAP_COMPAT(SNDRV_TIMER_IOCTL_PAUSE),
-#endif
-	{ 0 },
-};
diff -Nru a/sound/core/memory.c b/sound/core/memory.c
--- a/sound/core/memory.c	2005-03-11 12:51:41 -08:00
+++ b/sound/core/memory.c	2005-03-11 12:51:41 -08:00
@@ -50,8 +50,8 @@
 static long snd_alloc_vmalloc;
 static LIST_HEAD(snd_alloc_kmalloc_list);
 static LIST_HEAD(snd_alloc_vmalloc_list);
-static spinlock_t snd_alloc_kmalloc_lock = SPIN_LOCK_UNLOCKED;
-static spinlock_t snd_alloc_vmalloc_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(snd_alloc_kmalloc_lock);
+static DEFINE_SPINLOCK(snd_alloc_vmalloc_lock);
 #define KMALLOC_MAGIC 0x87654321
 #define VMALLOC_MAGIC 0x87654320
 static snd_info_entry_t *snd_memory_info_entry;
diff -Nru a/sound/core/oss/mixer_oss.c b/sound/core/oss/mixer_oss.c
--- a/sound/core/oss/mixer_oss.c	2005-03-11 12:51:47 -08:00
+++ b/sound/core/oss/mixer_oss.c	2005-03-11 12:51:47 -08:00
@@ -359,16 +359,9 @@
 	return -ENXIO;
 }
 
-/* FIXME: need to unlock BKL to allow preemption */
-static int snd_mixer_oss_ioctl(struct inode *inode, struct file *file,
-			       unsigned int cmd, unsigned long arg)
-{
-	int err;
-	/* FIXME: need to unlock BKL to allow preemption */
-	unlock_kernel();
-	err = snd_mixer_oss_ioctl1((snd_mixer_oss_file_t *) file->private_data, cmd, arg);
-	lock_kernel();
-	return err;
+static long snd_mixer_oss_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+	return snd_mixer_oss_ioctl1((snd_mixer_oss_file_t *) file->private_data, cmd, arg);
 }
 
 int snd_mixer_oss_ioctl_card(snd_card_t *card, unsigned int cmd, unsigned long arg)
@@ -384,6 +377,13 @@
 	return snd_mixer_oss_ioctl1(&fmixer, cmd, arg);
 }
 
+#ifdef CONFIG_COMPAT
+/* all compatible */
+#define snd_mixer_oss_ioctl_compat	snd_mixer_oss_ioctl
+#else
+#define snd_mixer_oss_ioctl_compat	NULL
+#endif
+
 /*
  *  REGISTRATION PART
  */
@@ -393,7 +393,8 @@
 	.owner =	THIS_MODULE,
 	.open =		snd_mixer_oss_open,
 	.release =	snd_mixer_oss_release,
-	.ioctl =	snd_mixer_oss_ioctl,
+	.unlocked_ioctl =	snd_mixer_oss_ioctl,
+	.compat_ioctl =	snd_mixer_oss_ioctl_compat,
 };
 
 static snd_minor_t snd_mixer_oss_reg =
@@ -521,7 +522,7 @@
 		goto __unalloc;
 	snd_runtime_check(!kctl->info(kctl, uinfo), goto __unalloc);
 	snd_runtime_check(!kctl->get(kctl, uctl), goto __unalloc);
-	snd_runtime_check(uinfo->type != SNDRV_CTL_ELEM_TYPE_BOOLEAN || uinfo->value.integer.min != 0 || uinfo->value.integer.max != 1, return);
+	snd_runtime_check(uinfo->type != SNDRV_CTL_ELEM_TYPE_BOOLEAN || uinfo->value.integer.min != 0 || uinfo->value.integer.max != 1, goto __unalloc);
 	*left = snd_mixer_oss_conv1(uctl->value.integer.value[0], uinfo->value.integer.min, uinfo->value.integer.max, &pslot->volume[0]);
 	if (uinfo->count > 1)
 		*right = snd_mixer_oss_conv1(uctl->value.integer.value[1], uinfo->value.integer.min, uinfo->value.integer.max, &pslot->volume[1]);
@@ -615,7 +616,7 @@
 	if (uinfo == NULL || uctl == NULL)
 		goto __unalloc;
 	snd_runtime_check(!kctl->info(kctl, uinfo), goto __unalloc);
-	snd_runtime_check(uinfo->type != SNDRV_CTL_ELEM_TYPE_BOOLEAN || uinfo->value.integer.min != 0 || uinfo->value.integer.max != 1, return);
+	snd_runtime_check(uinfo->type != SNDRV_CTL_ELEM_TYPE_BOOLEAN || uinfo->value.integer.min != 0 || uinfo->value.integer.max != 1, goto __unalloc);
 	uctl->value.integer.value[0] = snd_mixer_oss_conv2(left, uinfo->value.integer.min, uinfo->value.integer.max);
 	if (uinfo->count > 1)
 		uctl->value.integer.value[1] = snd_mixer_oss_conv2(right, uinfo->value.integer.min, uinfo->value.integer.max);
diff -Nru a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c
--- a/sound/core/oss/pcm_oss.c	2005-03-11 12:51:51 -08:00
+++ b/sound/core/oss/pcm_oss.c	2005-03-11 12:51:51 -08:00
@@ -636,10 +636,10 @@
 		if (in_kernel) {
 			mm_segment_t fs;
 			fs = snd_enter_user();
-			ret = snd_pcm_lib_write(substream, ptr, frames);
+			ret = snd_pcm_lib_write(substream, (void __user *)ptr, frames);
 			snd_leave_user(fs);
 		} else {
-			ret = snd_pcm_lib_write(substream, ptr, frames);
+			ret = snd_pcm_lib_write(substream, (void __user *)ptr, frames);
 		}
 		if (ret != -EPIPE && ret != -ESTRPIPE)
 			break;
@@ -679,10 +679,10 @@
 		if (in_kernel) {
 			mm_segment_t fs;
 			fs = snd_enter_user();
-			ret = snd_pcm_lib_read(substream, ptr, frames);
+			ret = snd_pcm_lib_read(substream, (void __user *)ptr, frames);
 			snd_leave_user(fs);
 		} else {
-			ret = snd_pcm_lib_read(substream, ptr, frames);
+			ret = snd_pcm_lib_read(substream, (void __user *)ptr, frames);
 		}
 		if (ret == -EPIPE) {
 			if (runtime->status->state == SNDRV_PCM_STATE_DRAINING) {
@@ -718,10 +718,10 @@
 		if (in_kernel) {
 			mm_segment_t fs;
 			fs = snd_enter_user();
-			ret = snd_pcm_lib_writev(substream, bufs, frames);
+			ret = snd_pcm_lib_writev(substream, (void __user **)bufs, frames);
 			snd_leave_user(fs);
 		} else {
-			ret = snd_pcm_lib_writev(substream, bufs, frames);
+			ret = snd_pcm_lib_writev(substream, (void __user **)bufs, frames);
 		}
 		if (ret != -EPIPE && ret != -ESTRPIPE)
 			break;
@@ -758,10 +758,10 @@
 		if (in_kernel) {
 			mm_segment_t fs;
 			fs = snd_enter_user();
-			ret = snd_pcm_lib_readv(substream, bufs, frames);
+			ret = snd_pcm_lib_readv(substream, (void __user **)bufs, frames);
 			snd_leave_user(fs);
 		} else {
-			ret = snd_pcm_lib_readv(substream, bufs, frames);
+			ret = snd_pcm_lib_readv(substream, (void __user **)bufs, frames);
 		}
 		if (ret != -EPIPE && ret != -ESTRPIPE)
 			break;
@@ -777,7 +777,7 @@
 		snd_pcm_plugin_channel_t *channels;
 		size_t oss_frame_bytes = (runtime->oss.plugin_first->src_width * runtime->oss.plugin_first->src_format.channels) / 8;
 		if (!in_kernel) {
-			if (copy_from_user(runtime->oss.buffer, buf, bytes))
+			if (copy_from_user(runtime->oss.buffer, (const char __user *)buf, bytes))
 				return -EFAULT;
 			buf = runtime->oss.buffer;
 		}
@@ -839,7 +839,7 @@
 					return xfer > 0 ? xfer : -EAGAIN;
 			}
 		} else {
-			tmp = snd_pcm_oss_write2(substream, (char *)buf, runtime->oss.period_bytes, 0);
+			tmp = snd_pcm_oss_write2(substream, (const char *)buf, runtime->oss.period_bytes, 0);
 			if (tmp <= 0)
 				return xfer > 0 ? (snd_pcm_sframes_t)xfer : tmp;
 			runtime->oss.bytes += tmp;
@@ -858,7 +858,7 @@
 {
 	snd_pcm_runtime_t *runtime = substream->runtime;
 	snd_pcm_sframes_t frames, frames1;
-	char *final_dst = buf;
+	char __user *final_dst = (char __user *)buf;
 	if (runtime->oss.plugin_first) {
 		snd_pcm_plugin_channel_t *channels;
 		size_t oss_frame_bytes = (runtime->oss.plugin_last->dst_width * runtime->oss.plugin_last->dst_format.channels) / 8;
@@ -1058,6 +1058,7 @@
 			if (runtime->access == SNDRV_PCM_ACCESS_RW_INTERLEAVED) {
 				size = (runtime->frame_bits * size) / 8;
 				while (size > 0) {
+					mm_segment_t fs;
 					size_t size1 = size < runtime->oss.period_bytes ? size : runtime->oss.period_bytes;
 					size -= size1;
 					size1 *= 8;
@@ -1065,7 +1066,9 @@
 					snd_pcm_format_set_silence(runtime->format,
 								   runtime->oss.buffer,
 								   size1);
-					snd_pcm_lib_write(substream, runtime->oss.buffer, size1);
+					fs = snd_enter_user();
+					snd_pcm_lib_write(substream, (void __user *)runtime->oss.buffer, size1);
+					snd_leave_user(fs);
 				}
 			} else if (runtime->access == SNDRV_PCM_ACCESS_RW_NONINTERLEAVED) {
 				void __user *buffers[runtime->channels];
@@ -1913,8 +1916,7 @@
 	return 0;
 }
 
-static inline int _snd_pcm_oss_ioctl(struct inode *inode, struct file *file,
-				     unsigned int cmd, unsigned long arg)
+static long snd_pcm_oss_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 {
 	snd_pcm_oss_file_t *pcm_oss_file;
 	int __user *p = (int __user *)arg;
@@ -2073,16 +2075,12 @@
 	return -EINVAL;
 }
 
-/* FIXME: need to unlock BKL to allow preemption */
-static int snd_pcm_oss_ioctl(struct inode *inode, struct file *file,
-			     unsigned int cmd, unsigned long arg)
-{
-	int err;
-	unlock_kernel();
-	err = _snd_pcm_oss_ioctl(inode, file, cmd, arg);
-	lock_kernel();
-	return err;
-}
+#ifdef CONFIG_COMPAT
+/* all compatible */
+#define snd_pcm_oss_ioctl_compat	snd_pcm_oss_ioctl
+#else
+#define snd_pcm_oss_ioctl_compat	NULL
+#endif
 
 static ssize_t snd_pcm_oss_read(struct file *file, char __user *buf, size_t count, loff_t *offset)
 {
@@ -2410,7 +2408,8 @@
 	.open =		snd_pcm_oss_open,
 	.release =	snd_pcm_oss_release,
 	.poll =		snd_pcm_oss_poll,
-	.ioctl =	snd_pcm_oss_ioctl,
+	.unlocked_ioctl =	snd_pcm_oss_ioctl,
+	.compat_ioctl =	snd_pcm_oss_ioctl_compat,
 	.mmap =		snd_pcm_oss_mmap,
 };
 
diff -Nru a/sound/core/pcm.c b/sound/core/pcm.c
--- a/sound/core/pcm.c	2005-03-11 12:51:52 -08:00
+++ b/sound/core/pcm.c	2005-03-11 12:51:52 -08:00
@@ -1004,6 +1004,7 @@
 	snd_info_entry_t *entry;
 
 	snd_ctl_register_ioctl(snd_pcm_control_ioctl);
+	snd_ctl_register_ioctl_compat(snd_pcm_control_ioctl);
 	if ((entry = snd_info_create_module_entry(THIS_MODULE, "pcm", NULL)) != NULL) {
 		snd_info_set_text_ops(entry, NULL, SNDRV_CARDS * SNDRV_PCM_DEVICES * 128, snd_pcm_proc_read);
 		if (snd_info_register(entry) < 0) {
@@ -1018,6 +1019,7 @@
 static void __exit alsa_pcm_exit(void)
 {
 	snd_ctl_unregister_ioctl(snd_pcm_control_ioctl);
+	snd_ctl_unregister_ioctl_compat(snd_pcm_control_ioctl);
 	if (snd_pcm_proc_entry) {
 		snd_info_unregister(snd_pcm_proc_entry);
 		snd_pcm_proc_entry = NULL;
diff -Nru a/sound/core/pcm_compat.c b/sound/core/pcm_compat.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/sound/core/pcm_compat.c	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,513 @@
+/*
+ *   32bit -> 64bit ioctl wrapper for PCM API
+ *   Copyright (c) by Takashi Iwai <tiwai@suse.de>
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+/* This file included from pcm_native.c */
+
+#include <linux/compat.h>
+
+static int snd_pcm_ioctl_delay_compat(snd_pcm_substream_t *substream,
+				      s32 __user *src)
+{
+	snd_pcm_sframes_t delay;
+	mm_segment_t fs;
+	int err;
+
+	fs = snd_enter_user();
+	err = snd_pcm_delay(substream, &delay);
+	snd_leave_user(fs);
+	if (err < 0)
+		return err;
+	if (put_user(delay, src))
+		return -EFAULT;
+	return err;
+}
+
+static int snd_pcm_ioctl_rewind_compat(snd_pcm_substream_t *substream,
+				       u32 __user *src)
+{
+	snd_pcm_uframes_t frames;
+	int err;
+
+	if (get_user(frames, src))
+		return -EFAULT;
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+		err = snd_pcm_playback_rewind(substream, frames);
+	else
+		err = snd_pcm_capture_rewind(substream, frames);
+	if (put_user(err, src))
+		return -EFAULT;
+	return err < 0 ? err : 0;
+}
+
+static int snd_pcm_ioctl_forward_compat(snd_pcm_substream_t *substream,
+				       u32 __user *src)
+{
+	snd_pcm_uframes_t frames;
+	int err;
+
+	if (get_user(frames, src))
+		return -EFAULT;
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+		err = snd_pcm_playback_forward(substream, frames);
+	else
+		err = snd_pcm_capture_forward(substream, frames);
+	if (put_user(err, src))
+		return -EFAULT;
+	return err < 0 ? err : 0;
+}
+
+struct sndrv_pcm_hw_params32 {
+	u32 flags;
+	struct sndrv_mask masks[SNDRV_PCM_HW_PARAM_LAST_MASK - SNDRV_PCM_HW_PARAM_FIRST_MASK + 1]; /* this must be identical */
+	struct sndrv_mask mres[5];	/* reserved masks */
+	struct sndrv_interval intervals[SNDRV_PCM_HW_PARAM_LAST_INTERVAL - SNDRV_PCM_HW_PARAM_FIRST_INTERVAL + 1];
+	struct sndrv_interval ires[9];	/* reserved intervals */
+	u32 rmask;
+	u32 cmask;
+	u32 info;
+	u32 msbits;
+	u32 rate_num;
+	u32 rate_den;
+	u32 fifo_size;
+	unsigned char reserved[64];
+};
+
+struct sndrv_pcm_sw_params32 {
+	s32 tstamp_mode;
+	u32 period_step;
+	u32 sleep_min;
+	u32 avail_min;
+	u32 xfer_align;
+	u32 start_threshold;
+	u32 stop_threshold;
+	u32 silence_threshold;
+	u32 silence_size;
+	u32 boundary;
+	unsigned char reserved[64];
+};
+
+static int snd_pcm_ioctl_sw_params_compat(snd_pcm_substream_t *substream,
+					  struct sndrv_pcm_sw_params32 __user *src)
+{
+	snd_pcm_sw_params_t params;
+	int err;
+
+	memset(&params, 0, sizeof(params));
+	if (get_user(params.tstamp_mode, &src->tstamp_mode) ||
+	    get_user(params.period_step, &src->period_step) ||
+	    get_user(params.sleep_min, &src->sleep_min) ||
+	    get_user(params.avail_min, &src->avail_min) ||
+	    get_user(params.xfer_align, &src->xfer_align) ||
+	    get_user(params.start_threshold, &src->start_threshold) ||
+	    get_user(params.stop_threshold, &src->stop_threshold) ||
+	    get_user(params.silence_threshold, &src->silence_threshold) ||
+	    get_user(params.silence_size, &src->silence_size))
+		return -EFAULT;
+	err = snd_pcm_sw_params(substream, &params);
+	if (err < 0)
+		return err;
+	if (put_user(params.boundary, &src->boundary))
+		return -EFAULT;
+	return err;
+}
+
+struct sndrv_pcm_channel_info32 {
+	u32 channel;
+	u32 offset;
+	u32 first;
+	u32 step;
+};
+
+static int snd_pcm_ioctl_channel_info_compat(snd_pcm_substream_t *substream,
+					     struct sndrv_pcm_channel_info32 __user *src)
+{
+	snd_pcm_channel_info_t info;
+	int err;
+
+	if (get_user(info.channel, &src->channel) ||
+	    get_user(info.offset, &src->offset) ||
+	    get_user(info.first, &src->first) ||
+	    get_user(info.step, &src->step))
+		return -EFAULT;
+	err = snd_pcm_channel_info(substream, &info);
+	if (err < 0)
+		return err;
+	if (put_user(info.channel, &src->channel) ||
+	    put_user(info.offset, &src->offset) ||
+	    put_user(info.first, &src->first) ||
+	    put_user(info.step, &src->step))
+		return -EFAULT;
+	return err;
+}
+
+struct sndrv_pcm_status32 {
+	s32 state;
+	struct compat_timespec trigger_tstamp;
+	struct compat_timespec tstamp;
+	u32 appl_ptr;
+	u32 hw_ptr;
+	s32 delay;
+	u32 avail;
+	u32 avail_max;
+	u32 overrange;
+	s32 suspended_state;
+	unsigned char reserved[60];
+} __attribute__((packed));
+
+
+static int snd_pcm_status_user_compat(snd_pcm_substream_t *substream,
+				      struct sndrv_pcm_status32 __user *src)
+{
+	snd_pcm_status_t status;
+	int err;
+
+	err = snd_pcm_status(substream, &status);
+	if (err < 0)
+		return err;
+
+	if (put_user(status.state, &src->state) ||
+	    put_user(status.trigger_tstamp.tv_sec, &src->trigger_tstamp.tv_sec) ||
+	    put_user(status.trigger_tstamp.tv_nsec, &src->trigger_tstamp.tv_nsec) ||
+	    put_user(status.tstamp.tv_sec, &src->tstamp.tv_sec) ||
+	    put_user(status.tstamp.tv_nsec, &src->tstamp.tv_nsec) ||
+	    put_user(status.appl_ptr, &src->appl_ptr) ||
+	    put_user(status.hw_ptr, &src->hw_ptr) ||
+	    put_user(status.delay, &src->delay) ||
+	    put_user(status.avail, &src->avail) ||
+	    put_user(status.avail_max, &src->avail_max) ||
+	    put_user(status.overrange, &src->overrange) ||
+	    put_user(status.suspended_state, &src->suspended_state))
+		return -EFAULT;
+
+	return err;
+}
+
+/* recalcuate the boundary within 32bit */
+static void recalculate_boundary(snd_pcm_runtime_t *runtime)
+{
+	if (! runtime->buffer_size)
+		return;
+	runtime->boundary = runtime->buffer_size;
+	while (runtime->boundary * 2 <= 0x7fffffffUL - runtime->buffer_size)
+		runtime->boundary *= 2;
+}
+
+/* both for HW_PARAMS and HW_REFINE */
+static int snd_pcm_ioctl_hw_params_compat(snd_pcm_substream_t *substream,
+					  int refine, 
+					  struct sndrv_pcm_hw_params32 __user *data32)
+{
+	struct sndrv_pcm_hw_params *data;
+	snd_pcm_runtime_t *runtime;
+	int err;
+
+	if (! (runtime = substream->runtime))
+		return -ENOTTY;
+
+	data = kmalloc(sizeof(*data), GFP_KERNEL);
+	if (data == NULL)
+		return -ENOMEM;
+	/* only fifo_size is different, so just copy all */
+	if (copy_from_user(data, data32, sizeof(*data32))) {
+		err = -EFAULT;
+		goto error;
+	}
+	if (refine)
+		err = snd_pcm_hw_refine(substream, data);
+	else
+		err = snd_pcm_hw_params(substream, data);
+	if (err < 0)
+		goto error;
+	if (copy_to_user(data32, data, sizeof(*data32)) ||
+	    put_user(data->fifo_size, &data32->fifo_size)) {
+		err = -EFAULT;
+		goto error;
+	}
+
+	if (! refine)
+		recalculate_boundary(runtime);
+ error:
+	kfree(data);
+	return err;
+}
+
+
+/*
+ */
+struct sndrv_xferi32 {
+	s32 result;
+	u32 buf;
+	u32 frames;
+};
+
+static int snd_pcm_ioctl_xferi_compat(snd_pcm_substream_t *substream,
+				      int dir, struct sndrv_xferi32 __user *data32)
+{
+	compat_caddr_t buf;
+	u32 frames;
+	int err;
+
+	if (! substream->runtime)
+		return -ENOTTY;
+	if (substream->stream != dir)
+		return -EINVAL;
+	if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN)
+		return -EBADFD;
+
+	if (get_user(buf, &data32->buf) ||
+	    get_user(frames, &data32->frames))
+		return -EFAULT;
+
+	if (dir == SNDRV_PCM_STREAM_PLAYBACK)
+		err = snd_pcm_lib_write(substream, compat_ptr(buf), frames);
+	else
+		err = snd_pcm_lib_read(substream, compat_ptr(buf), frames);
+	if (err < 0)
+		return err;
+	/* copy the result */
+	if (put_user(err, &data32->result))
+		return -EFAULT;
+	return 0;
+}
+
+
+/* snd_xfern needs remapping of bufs */
+struct sndrv_xfern32 {
+	s32 result;
+	u32 bufs;  /* this is void **; */
+	u32 frames;
+};
+
+/*
+ * xfern ioctl nees to copy (up to) 128 pointers on stack.
+ * although we may pass the copied pointers through f_op->ioctl, but the ioctl
+ * handler there expands again the same 128 pointers on stack, so it is better
+ * to handle the function (calling pcm_readv/writev) directly in this handler.
+ */
+static int snd_pcm_ioctl_xfern_compat(snd_pcm_substream_t *substream,
+				      int dir, struct sndrv_xfern32 __user *data32)
+{
+	compat_caddr_t buf;
+	compat_caddr_t __user *bufptr;
+	u32 frames;
+	void __user **bufs;
+	int err, ch, i;
+
+	if (! substream->runtime)
+		return -ENOTTY;
+	if (substream->stream != dir)
+		return -EINVAL;
+
+	if ((ch = substream->runtime->channels) > 128)
+		return -EINVAL;
+	if (get_user(buf, &data32->bufs) ||
+	    get_user(frames, &data32->frames))
+		return -EFAULT;
+	bufptr = compat_ptr(buf);
+	bufs = kmalloc(sizeof(void __user *) * ch, GFP_KERNEL);
+	if (bufs == NULL)
+		return -ENOMEM;
+	for (i = 0; i < ch; i++) {
+		u32 ptr;
+		if (get_user(ptr, bufptr)) {
+			kfree(bufs);
+			return -EFAULT;
+		}
+		bufs[ch] = compat_ptr(ptr);
+		bufptr++;
+	}
+	if (dir == SNDRV_PCM_STREAM_PLAYBACK)
+		err = snd_pcm_lib_writev(substream, bufs, frames);
+	else
+		err = snd_pcm_lib_readv(substream, bufs, frames);
+	if (err >= 0) {
+		if (put_user(err, &data32->result))
+			err = -EFAULT;
+	}
+	kfree(bufs);
+	return err;
+}
+
+
+struct sndrv_pcm_mmap_status32 {
+	s32 state;
+	s32 pad1;
+	u32 hw_ptr;
+	struct compat_timespec tstamp;
+	s32 suspended_state;
+} __attribute__((packed));
+
+struct sndrv_pcm_mmap_control32 {
+	u32 appl_ptr;
+	u32 avail_min;
+};
+
+struct sndrv_pcm_sync_ptr32 {
+	u32 flags;
+	union {
+		struct sndrv_pcm_mmap_status32 status;
+		unsigned char reserved[64];
+	} s;
+	union {
+		struct sndrv_pcm_mmap_control32 control;
+		unsigned char reserved[64];
+	} c;
+} __attribute__((packed));
+
+static int snd_pcm_ioctl_sync_ptr_compat(snd_pcm_substream_t *substream,
+					 struct sndrv_pcm_sync_ptr32 __user *src)
+{
+	snd_pcm_runtime_t *runtime = substream->runtime;
+	volatile struct sndrv_pcm_mmap_status *status;
+	volatile struct sndrv_pcm_mmap_control *control;
+	u32 sflags;
+	struct sndrv_pcm_mmap_control scontrol;
+	struct sndrv_pcm_mmap_status sstatus;
+	int err;
+
+	snd_assert(runtime, return -EINVAL);
+
+	if (get_user(sflags, &src->flags) ||
+	    get_user(scontrol.appl_ptr, &src->c.control.appl_ptr) ||
+	    get_user(scontrol.avail_min, &src->c.control.avail_min))
+		return -EFAULT;
+	if (sflags & SNDRV_PCM_SYNC_PTR_HWSYNC) {
+		err = snd_pcm_hwsync(substream);
+		if (err < 0)
+			return err;
+	}
+	status = runtime->status;
+	control = runtime->control;
+	snd_pcm_stream_lock_irq(substream);
+	if (!(sflags & SNDRV_PCM_SYNC_PTR_APPL))
+		control->appl_ptr = scontrol.appl_ptr;
+	else
+		scontrol.appl_ptr = control->appl_ptr;
+	if (!(sflags & SNDRV_PCM_SYNC_PTR_AVAIL_MIN))
+		control->avail_min = scontrol.avail_min;
+	else
+		scontrol.avail_min = control->avail_min;
+	sstatus.state = status->state;
+	sstatus.hw_ptr = status->hw_ptr;
+	sstatus.tstamp = status->tstamp;
+	sstatus.suspended_state = status->suspended_state;
+	snd_pcm_stream_unlock_irq(substream);
+	if (put_user(sstatus.state, &src->s.status.state) ||
+	    put_user(sstatus.hw_ptr, &src->s.status.hw_ptr) ||
+	    put_user(sstatus.tstamp.tv_sec, &src->s.status.tstamp.tv_sec) ||
+	    put_user(sstatus.tstamp.tv_nsec, &src->s.status.tstamp.tv_nsec) ||
+	    put_user(sstatus.suspended_state, &src->s.status.suspended_state) ||
+	    put_user(scontrol.appl_ptr, &src->c.control.appl_ptr) ||
+	    put_user(scontrol.avail_min, &src->c.control.avail_min))
+		return -EFAULT;
+
+	return 0;
+}
+
+
+/*
+ */
+enum {
+	SNDRV_PCM_IOCTL_HW_REFINE32 = _IOWR('A', 0x10, struct sndrv_pcm_hw_params32),
+	SNDRV_PCM_IOCTL_HW_PARAMS32 = _IOWR('A', 0x11, struct sndrv_pcm_hw_params32),
+	SNDRV_PCM_IOCTL_SW_PARAMS32 = _IOWR('A', 0x13, struct sndrv_pcm_sw_params32),
+	SNDRV_PCM_IOCTL_STATUS32 = _IOR('A', 0x20, struct sndrv_pcm_status32),
+	SNDRV_PCM_IOCTL_DELAY32 = _IOR('A', 0x21, s32),
+	SNDRV_PCM_IOCTL_CHANNEL_INFO32 = _IOR('A', 0x32, struct sndrv_pcm_channel_info32),
+	SNDRV_PCM_IOCTL_REWIND32 = _IOW('A', 0x46, u32),
+	SNDRV_PCM_IOCTL_FORWARD32 = _IOW('A', 0x49, u32),
+	SNDRV_PCM_IOCTL_WRITEI_FRAMES32 = _IOW('A', 0x50, struct sndrv_xferi32),
+	SNDRV_PCM_IOCTL_READI_FRAMES32 = _IOR('A', 0x51, struct sndrv_xferi32),
+	SNDRV_PCM_IOCTL_WRITEN_FRAMES32 = _IOW('A', 0x52, struct sndrv_xfern32),
+	SNDRV_PCM_IOCTL_READN_FRAMES32 = _IOR('A', 0x53, struct sndrv_xfern32),
+	SNDRV_PCM_IOCTL_SYNC_PTR32 = _IOWR('A', 0x23, struct sndrv_pcm_sync_ptr32),
+
+};
+
+static long snd_pcm_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg)
+{
+	snd_pcm_file_t *pcm_file;
+	snd_pcm_substream_t *substream;
+	void __user *argp = compat_ptr(arg);
+
+	pcm_file = file->private_data;
+	if (! pcm_file)
+		return -ENOTTY;
+	substream = pcm_file->substream;
+	if (! substream)
+		return -ENOTTY;
+
+	/*
+	 * When PCM is used on 32bit mode, we need to disable
+	 * mmap of PCM status/control records because of the size
+	 * incompatibility.
+	 */
+	substream->no_mmap_ctrl = 1;
+
+	switch (cmd) {
+	case SNDRV_PCM_IOCTL_PVERSION:
+	case SNDRV_PCM_IOCTL_INFO:
+	case SNDRV_PCM_IOCTL_TSTAMP:
+	case SNDRV_PCM_IOCTL_HWSYNC:
+	case SNDRV_PCM_IOCTL_PREPARE:
+	case SNDRV_PCM_IOCTL_RESET:
+	case SNDRV_PCM_IOCTL_START:
+	case SNDRV_PCM_IOCTL_DROP:
+	case SNDRV_PCM_IOCTL_DRAIN:
+	case SNDRV_PCM_IOCTL_PAUSE:
+	case SNDRV_PCM_IOCTL_HW_FREE:
+	case SNDRV_PCM_IOCTL_RESUME:
+	case SNDRV_PCM_IOCTL_XRUN:
+	case SNDRV_PCM_IOCTL_LINK:
+	case SNDRV_PCM_IOCTL_UNLINK:
+		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+			return snd_pcm_playback_ioctl1(substream, cmd, argp);
+		else
+			return snd_pcm_capture_ioctl1(substream, cmd, argp);
+	case SNDRV_PCM_IOCTL_HW_REFINE32:
+		return snd_pcm_ioctl_hw_params_compat(substream, 1, argp);
+	case SNDRV_PCM_IOCTL_HW_PARAMS32:
+		return snd_pcm_ioctl_hw_params_compat(substream, 0, argp);
+	case SNDRV_PCM_IOCTL_SW_PARAMS32:
+		return snd_pcm_ioctl_sw_params_compat(substream, argp);
+	case SNDRV_PCM_IOCTL_STATUS32:
+		return snd_pcm_status_user_compat(substream, argp);
+	case SNDRV_PCM_IOCTL_SYNC_PTR32:
+		return snd_pcm_ioctl_sync_ptr_compat(substream, argp);
+	case SNDRV_PCM_IOCTL_CHANNEL_INFO32:
+		return snd_pcm_ioctl_channel_info_compat(substream, argp);
+	case SNDRV_PCM_IOCTL_WRITEI_FRAMES32:
+		return snd_pcm_ioctl_xferi_compat(substream, SNDRV_PCM_STREAM_PLAYBACK, argp);
+	case SNDRV_PCM_IOCTL_READI_FRAMES32:
+		return snd_pcm_ioctl_xferi_compat(substream, SNDRV_PCM_STREAM_CAPTURE, argp);
+	case SNDRV_PCM_IOCTL_WRITEN_FRAMES32:
+		return snd_pcm_ioctl_xfern_compat(substream, SNDRV_PCM_STREAM_PLAYBACK, argp);
+	case SNDRV_PCM_IOCTL_READN_FRAMES32:
+		return snd_pcm_ioctl_xfern_compat(substream, SNDRV_PCM_STREAM_CAPTURE, argp);
+	case SNDRV_PCM_IOCTL_DELAY32:
+		return snd_pcm_ioctl_delay_compat(substream, argp);
+	case SNDRV_PCM_IOCTL_REWIND32:
+		return snd_pcm_ioctl_rewind_compat(substream, argp);
+	case SNDRV_PCM_IOCTL_FORWARD32:
+		return snd_pcm_ioctl_forward_compat(substream, argp);
+	}
+
+	return -ENOIOCTLCMD;
+}
diff -Nru a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
--- a/sound/core/pcm_lib.c	2005-03-11 12:51:42 -08:00
+++ b/sound/core/pcm_lib.c	2005-03-11 12:51:42 -08:00
@@ -1863,9 +1863,8 @@
 	if (ticks == 0)
 		del_timer(&runtime->tick_timer);
 	else {
+		ticks += (1000000 / HZ) - 1;
 		ticks /= (1000000 / HZ);
-		if (ticks % (1000000 / HZ))
-			ticks++;
 		mod_timer(&runtime->tick_timer, jiffies + ticks);
 	}
 }
@@ -2142,11 +2141,9 @@
 			break;
 		}
 		appl_ptr += frames;
-		if (appl_ptr >= runtime->boundary) {
-			runtime->control->appl_ptr = 0;
-		} else {
-			runtime->control->appl_ptr = appl_ptr;
-		}
+		if (appl_ptr >= runtime->boundary)
+			appl_ptr -= runtime->boundary;
+		runtime->control->appl_ptr = appl_ptr;
 		if (substream->ops->ack)
 			substream->ops->ack(substream);
 
@@ -2441,11 +2438,9 @@
 			break;
 		}
 		appl_ptr += frames;
-		if (appl_ptr >= runtime->boundary) {
-			runtime->control->appl_ptr = 0;
-		} else {
-			runtime->control->appl_ptr = appl_ptr;
-		}
+		if (appl_ptr >= runtime->boundary)
+			appl_ptr -= runtime->boundary;
+		runtime->control->appl_ptr = appl_ptr;
 		if (substream->ops->ack)
 			substream->ops->ack(substream);
 
diff -Nru a/sound/core/pcm_memory.c b/sound/core/pcm_memory.c
--- a/sound/core/pcm_memory.c	2005-03-11 12:51:52 -08:00
+++ b/sound/core/pcm_memory.c	2005-03-11 12:51:52 -08:00
@@ -291,7 +291,7 @@
  * @substream: the substream to allocate the DMA buffer to
  * @size: the requested buffer size in bytes
  *
- * Allocates the DMA buffer on the BUS type given by
+ * Allocates the DMA buffer on the BUS type given earlier to
  * snd_pcm_lib_preallocate_xxx_pages().
  *
  * Returns 1 if the buffer is changed, 0 if not changed, or a negative
diff -Nru a/sound/core/pcm_native.c b/sound/core/pcm_native.c
--- a/sound/core/pcm_native.c	2005-03-11 12:51:42 -08:00
+++ b/sound/core/pcm_native.c	2005-03-11 12:51:42 -08:00
@@ -65,7 +65,7 @@
  *
  */
 
-rwlock_t snd_pcm_link_rwlock = RW_LOCK_UNLOCKED;
+DEFINE_RWLOCK(snd_pcm_link_rwlock);
 static DECLARE_RWSEM(snd_pcm_link_rwsem);
 
 
@@ -602,17 +602,13 @@
 	return 0;
 }
 
-static int snd_pcm_channel_info(snd_pcm_substream_t * substream, snd_pcm_channel_info_t __user * _info)
+static int snd_pcm_channel_info(snd_pcm_substream_t * substream, snd_pcm_channel_info_t * info)
 {
-	snd_pcm_channel_info_t info;
 	snd_pcm_runtime_t *runtime;
-	int res;
 	unsigned int channel;
 	
 	snd_assert(substream != NULL, return -ENXIO);
-	if (copy_from_user(&info, _info, sizeof(info)))
-		return -EFAULT;
-	channel = info.channel;
+	channel = info->channel;
 	runtime = substream->runtime;
 	snd_pcm_stream_lock_irq(substream);
 	if (runtime->status->state == SNDRV_PCM_STATE_OPEN) {
@@ -622,9 +618,19 @@
 	snd_pcm_stream_unlock_irq(substream);
 	if (channel >= runtime->channels)
 		return -EINVAL;
-	memset(&info, 0, sizeof(info));
-	info.channel = channel;
-	res = substream->ops->ioctl(substream, SNDRV_PCM_IOCTL1_CHANNEL_INFO, &info);
+	memset(info, 0, sizeof(*info));
+	info->channel = channel;
+	return substream->ops->ioctl(substream, SNDRV_PCM_IOCTL1_CHANNEL_INFO, info);
+}
+
+static int snd_pcm_channel_info_user(snd_pcm_substream_t * substream, snd_pcm_channel_info_t __user * _info)
+{
+	snd_pcm_channel_info_t info;
+	int res;
+	
+	if (copy_from_user(&info, _info, sizeof(info)))
+		return -EFAULT;
+	res = snd_pcm_channel_info(substream, &info);
 	if (res < 0)
 		return res;
 	if (copy_to_user(_info, &info, sizeof(info)))
@@ -2440,7 +2446,7 @@
 	case SNDRV_PCM_IOCTL_STATUS:
 		return snd_pcm_status_user(substream, arg);
 	case SNDRV_PCM_IOCTL_CHANNEL_INFO:
-		return snd_pcm_channel_info(substream, arg);
+		return snd_pcm_channel_info_user(substream, arg);
 	case SNDRV_PCM_IOCTL_PREPARE:
 		return snd_pcm_prepare(substream);
 	case SNDRV_PCM_IOCTL_RESET:
@@ -2640,40 +2646,28 @@
 	return snd_pcm_common_ioctl1(substream, cmd, arg);
 }
 
-static int snd_pcm_playback_ioctl(struct inode *inode, struct file *file,
-				  unsigned int cmd, unsigned long arg)
+static long snd_pcm_playback_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 {
 	snd_pcm_file_t *pcm_file;
-	int err;
 
 	pcm_file = file->private_data;
 
 	if (((cmd >> 8) & 0xff) != 'A')
 		return -ENOTTY;
 
-	/* FIXME: need to unlock BKL to allow preemption */
-	unlock_kernel();
-	err = snd_pcm_playback_ioctl1(pcm_file->substream, cmd, (void __user *)arg);
-	lock_kernel();
-	return err;
+	return snd_pcm_playback_ioctl1(pcm_file->substream, cmd, (void __user *)arg);
 }
 
-static int snd_pcm_capture_ioctl(struct inode *inode, struct file *file,
-				 unsigned int cmd, unsigned long arg)
+static long snd_pcm_capture_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 {
 	snd_pcm_file_t *pcm_file;
-	int err;
 
 	pcm_file = file->private_data;
 
 	if (((cmd >> 8) & 0xff) != 'A')
 		return -ENOTTY;
 
-	/* FIXME: need to unlock BKL to allow preemption */
-	unlock_kernel();
-	err = snd_pcm_capture_ioctl1(pcm_file->substream, cmd, (void __user *)arg);
-	lock_kernel();
-	return err;
+	return snd_pcm_capture_ioctl1(pcm_file->substream, cmd, (void __user *)arg);
 }
 
 int snd_pcm_kernel_playback_ioctl(snd_pcm_substream_t *substream,
@@ -2683,7 +2677,7 @@
 	int result;
 	
 	fs = snd_enter_user();
-	result = snd_pcm_playback_ioctl1(substream, cmd, arg);
+	result = snd_pcm_playback_ioctl1(substream, cmd, (void __user *)arg);
 	snd_leave_user(fs);
 	return result;
 }
@@ -2695,7 +2689,7 @@
 	int result;
 	
 	fs = snd_enter_user();
-	result = snd_pcm_capture_ioctl1(substream, cmd, arg);
+	result = snd_pcm_capture_ioctl1(substream, cmd, (void __user *)arg);
 	snd_leave_user(fs);
 	return result;
 }
@@ -3198,6 +3192,15 @@
 }
 
 /*
+ * ioctl32 compat
+ */
+#ifdef CONFIG_COMPAT
+#include "pcm_compat.c"
+#else
+#define snd_pcm_ioctl_compat	NULL
+#endif
+
+/*
  *  To be removed helpers to keep binary compatibility
  */
 
@@ -3318,7 +3321,8 @@
 	.open =		snd_pcm_open,
 	.release =	snd_pcm_release,
 	.poll =		snd_pcm_playback_poll,
-	.ioctl =	snd_pcm_playback_ioctl,
+	.unlocked_ioctl =	snd_pcm_playback_ioctl,
+	.compat_ioctl = snd_pcm_ioctl_compat,
 	.mmap =		snd_pcm_mmap,
 	.fasync =	snd_pcm_fasync,
 };
@@ -3330,7 +3334,8 @@
 	.open =		snd_pcm_open,
 	.release =	snd_pcm_release,
 	.poll =		snd_pcm_capture_poll,
-	.ioctl =	snd_pcm_capture_ioctl,
+	.unlocked_ioctl =	snd_pcm_capture_ioctl,
+	.compat_ioctl = snd_pcm_ioctl_compat,
 	.mmap =		snd_pcm_mmap,
 	.fasync =	snd_pcm_fasync,
 };
diff -Nru a/sound/core/rawmidi.c b/sound/core/rawmidi.c
--- a/sound/core/rawmidi.c	2005-03-11 12:51:41 -08:00
+++ b/sound/core/rawmidi.c	2005-03-11 12:51:41 -08:00
@@ -29,6 +29,8 @@
 #include <linux/time.h>
 #include <linux/wait.h>
 #include <linux/moduleparam.h>
+#include <linux/delay.h>
+#include <linux/wait.h>
 #include <sound/rawmidi.h>
 #include <sound/info.h>
 #include <sound/control.h>
@@ -83,11 +85,22 @@
 	       (!substream->append || runtime->avail >= count);
 }
 
-static int snd_rawmidi_init(snd_rawmidi_substream_t *substream)
+static void snd_rawmidi_event_tasklet(unsigned long data)
 {
-	snd_rawmidi_runtime_t *runtime = substream->runtime;
+	snd_rawmidi_substream_t *substream = (snd_rawmidi_substream_t *)data;
+	substream->runtime->event(substream);
+}
+
+static int snd_rawmidi_runtime_create(snd_rawmidi_substream_t * substream)
+{
+	snd_rawmidi_runtime_t *runtime;
+
+	if ((runtime = kcalloc(1, sizeof(*runtime), GFP_KERNEL)) == NULL)
+		return -ENOMEM;
 	spin_lock_init(&runtime->lock);
 	init_waitqueue_head(&runtime->sleep);
+	tasklet_init(&runtime->event_tasklet, snd_rawmidi_event_tasklet,
+		     (unsigned long)substream);
 	runtime->event = NULL;
 	runtime->buffer_size = PAGE_SIZE;
 	runtime->avail_min = 1;
@@ -95,27 +108,37 @@
 		runtime->avail = 0;
 	else
 		runtime->avail = runtime->buffer_size;
-	if ((runtime->buffer = kmalloc(runtime->buffer_size, GFP_KERNEL)) == NULL)
+	if ((runtime->buffer = kmalloc(runtime->buffer_size, GFP_KERNEL)) == NULL) {
+		kfree(runtime);
 		return -ENOMEM;
+	}
 	runtime->appl_ptr = runtime->hw_ptr = 0;
+	substream->runtime = runtime;
 	return 0;
 }
 
-static int snd_rawmidi_done_buffer(snd_rawmidi_runtime_t *runtime)
+static int snd_rawmidi_runtime_free(snd_rawmidi_substream_t * substream)
 {
-	if (runtime->buffer) {
-		kfree(runtime->buffer);
-		runtime->buffer = NULL;
-	}
+	snd_rawmidi_runtime_t *runtime = substream->runtime;
+
+	kfree(runtime->buffer);
+	kfree(runtime);
+	substream->runtime = NULL;
 	return 0;
 }
 
+static void snd_rawmidi_trigger(snd_rawmidi_substream_t * substream, int up)
+{
+	substream->ops->trigger(substream, up);
+	if (!up && substream->runtime->event)
+		tasklet_kill(&substream->runtime->event_tasklet);
+}
+
 int snd_rawmidi_drop_output(snd_rawmidi_substream_t * substream)
 {
 	snd_rawmidi_runtime_t *runtime = substream->runtime;
 
-	substream->ops->trigger(substream, 0);
-	runtime->trigger = 0;
+	snd_rawmidi_trigger(substream, 0);
 	runtime->drain = 0;
 	/* interrupts are not enabled at this moment,
 	   so spinlock is not required */
@@ -132,27 +155,22 @@
 
 	err = 0;
 	runtime->drain = 1;
-	while (runtime->avail < runtime->buffer_size) {
-		timeout = interruptible_sleep_on_timeout(&runtime->sleep, 10 * HZ);
-		if (signal_pending(current)) {
-			err = -ERESTARTSYS;
-			break;
-		}
-		if (runtime->avail < runtime->buffer_size && !timeout) {
-			snd_printk(KERN_WARNING "rawmidi drain error (avail = %li, buffer_size = %li)\n", (long)runtime->avail, (long)runtime->buffer_size);
-			err = -EIO;
-			break;
-		}
+	timeout = wait_event_interruptible_timeout(runtime->sleep,
+				(runtime->avail >= runtime->buffer_size),
+				10*HZ);
+	if (signal_pending(current))
+		err = -ERESTARTSYS;
+	if (runtime->avail < runtime->buffer_size && !timeout) {
+		snd_printk(KERN_WARNING "rawmidi drain error (avail = %li, buffer_size = %li)\n", (long)runtime->avail, (long)runtime->buffer_size);
+		err = -EIO;
 	}
 	runtime->drain = 0;
 	if (err != -ERESTARTSYS) {
 		/* we need wait a while to make sure that Tx FIFOs are empty */
 		if (substream->ops->drain)
 			substream->ops->drain(substream);
-		else {
-			set_current_state(TASK_UNINTERRUPTIBLE);
-			schedule_timeout(HZ / 20);
-		}
+		else
+			msleep(50);
 		snd_rawmidi_drop_output(substream);
 	}
 	return err;
@@ -162,8 +180,7 @@
 {
 	snd_rawmidi_runtime_t *runtime = substream->runtime;
 
-	substream->ops->trigger(substream, 0);
-	runtime->trigger = 0;
+	snd_rawmidi_trigger(substream, 0);
 	runtime->drain = 0;
 	/* interrupts aren't enabled at this moment, so spinlock isn't needed */
 	runtime->appl_ptr = runtime->hw_ptr = 0;
@@ -176,7 +193,7 @@
 {
 	snd_rawmidi_t *rmidi;
 	struct list_head *list1, *list2;
-	snd_rawmidi_substream_t *sinput, *soutput;
+	snd_rawmidi_substream_t *sinput = NULL, *soutput = NULL;
 	snd_rawmidi_runtime_t *input = NULL, *output = NULL;
 	int err;
 
@@ -267,20 +284,11 @@
 		list2 = list2->next;
 	}
 	if (mode & SNDRV_RAWMIDI_LFLG_INPUT) {
-		input = kcalloc(1, sizeof(*input), GFP_KERNEL);
-		if (input == NULL) {
-			err = -ENOMEM;
+		if ((err = snd_rawmidi_runtime_create(sinput)) < 0)
 			goto __error;
-		}
-		sinput->runtime = input;
-		if (snd_rawmidi_init(sinput) < 0) {
-			err = -ENOMEM;
+		input = sinput->runtime;
+		if ((err = sinput->ops->open(sinput)) < 0)
 			goto __error;
-		}
-		if ((err = sinput->ops->open(sinput)) < 0) {
-			sinput->runtime = NULL;
-			goto __error;
-		}
 		sinput->opened = 1;
 		rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT].substream_opened++;
 	} else {
@@ -289,26 +297,15 @@
 	if (mode & SNDRV_RAWMIDI_LFLG_OUTPUT) {
 		if (soutput->opened)
 			goto __skip_output;
-		output = kcalloc(1, sizeof(*output), GFP_KERNEL);
-		if (output == NULL) {
-			err = -ENOMEM;
-			goto __error;
-		}
-		soutput->runtime = output;
-		if (snd_rawmidi_init(soutput) < 0) {
-			if (mode & SNDRV_RAWMIDI_LFLG_INPUT) {
+		if ((err = snd_rawmidi_runtime_create(soutput)) < 0) {
+			if (mode & SNDRV_RAWMIDI_LFLG_INPUT)
 				sinput->ops->close(sinput);
-				sinput->runtime = NULL;
-			}
-			err = -ENOMEM;
 			goto __error;
 		}
+		output = soutput->runtime;
 		if ((err = soutput->ops->open(soutput)) < 0) {
-			if (mode & SNDRV_RAWMIDI_LFLG_INPUT) {
+			if (mode & SNDRV_RAWMIDI_LFLG_INPUT)
 				sinput->ops->close(sinput);
-				sinput->runtime = NULL;
-			}
-			soutput->runtime = NULL;
 			goto __error;
 		}
 	      __skip_output:
@@ -331,14 +328,10 @@
 	return 0;
 
       __error:
-	if (input != NULL) {
-		snd_rawmidi_done_buffer(input);
-		kfree(input);
-	}
-	if (output != NULL) {
-		snd_rawmidi_done_buffer(output);
-		kfree(output);
-	}
+	if (input != NULL)
+		snd_rawmidi_runtime_free(sinput);
+	if (output != NULL)
+		snd_rawmidi_runtime_free(soutput);
 	module_put(rmidi->card->module);
 	if (!(mode & SNDRV_RAWMIDI_LFLG_NOOPENLOCK))
 		up(&rmidi->open_mutex);
@@ -465,14 +458,11 @@
 		substream = rfile->input;
 		rfile->input = NULL;
 		runtime = substream->runtime;
-		runtime->trigger = 0;
-		substream->ops->trigger(substream, 0);
+		snd_rawmidi_trigger(substream, 0);
 		substream->ops->close(substream);
-		snd_rawmidi_done_buffer(runtime);
 		if (runtime->private_free != NULL)
 			runtime->private_free(substream);
-		kfree(runtime);
-		substream->runtime = NULL;
+		snd_rawmidi_runtime_free(substream);
 		substream->opened = 0;
 		rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT].substream_opened--;
 	}
@@ -487,13 +477,11 @@
 				snd_rawmidi_kernel_write(substream, &buf, 1);
 			}
 			if (snd_rawmidi_drain_output(substream) == -ERESTARTSYS)
-				substream->ops->trigger(substream, 0);
+				snd_rawmidi_trigger(substream, 0);
 			substream->ops->close(substream);
-			snd_rawmidi_done_buffer(runtime);
 			if (runtime->private_free != NULL)
 				runtime->private_free(substream);
-			kfree(runtime);
-			substream->runtime = NULL;
+			snd_rawmidi_runtime_free(substream);
 			substream->opened = 0;
 			substream->append = 0;
 		}
@@ -673,8 +661,7 @@
 	return 0;
 }
 
-static inline int _snd_rawmidi_ioctl(struct inode *inode, struct file *file,
-				     unsigned int cmd, unsigned long arg)
+static long snd_rawmidi_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 {
 	snd_rawmidi_file_t *rfile;
 	void __user *argp = (void __user *)arg;
@@ -784,17 +771,6 @@
 	return -ENOTTY;
 }
 
-/* FIXME: need to unlock BKL to allow preemption */
-static int snd_rawmidi_ioctl(struct inode *inode, struct file *file,
-			     unsigned int cmd, unsigned long arg)
-{
-	int err;
-	unlock_kernel();
-	err = _snd_rawmidi_ioctl(inode, file, cmd, arg);
-	lock_kernel();
-	return err;
-}
-
 static int snd_rawmidi_control_ioctl(snd_card_t * card,
 				     snd_ctl_file_t * control,
 				     unsigned int cmd,
@@ -887,7 +863,7 @@
 			count1 = count;
 			if (count1 > (int)(runtime->buffer_size - runtime->avail)) {
 				count1 = runtime->buffer_size - runtime->avail;
-				runtime->xruns = count - count1;
+				runtime->xruns += count - count1;
 			}
 			if (count1 > 0) {
 				memcpy(runtime->buffer, buffer, count1);
@@ -897,13 +873,13 @@
 			}
 		}
 	}
-	if (result > 0 && runtime->event == NULL) {
-		if (snd_rawmidi_ready(substream))
+	if (result > 0) {
+		if (runtime->event)
+			tasklet_hi_schedule(&runtime->event_tasklet);
+		else if (snd_rawmidi_ready(substream))
 			wake_up(&runtime->sleep);
 	}
 	spin_unlock_irqrestore(&runtime->lock, flags);
-	if (result > 0 && runtime->event)
-		runtime->event(substream);
 	return result;
 }
 
@@ -925,7 +901,8 @@
 			memcpy(buf + result, runtime->buffer + runtime->appl_ptr, count1);
 		} else {
 			spin_unlock_irqrestore(&runtime->lock, flags);
-			if (copy_to_user(buf + result, runtime->buffer + runtime->appl_ptr, count1)) {
+			if (copy_to_user((char __user *)buf + result,
+					 runtime->buffer + runtime->appl_ptr, count1)) {
 				return result > 0 ? result : -EFAULT;
 			}
 			spin_lock_irqsave(&runtime->lock, flags);
@@ -942,8 +919,7 @@
 
 long snd_rawmidi_kernel_read(snd_rawmidi_substream_t *substream, unsigned char *buf, long count)
 {
-	substream->runtime->trigger = 1;
-	substream->ops->trigger(substream, 1);
+	snd_rawmidi_trigger(substream, 1);
 	return snd_rawmidi_kernel_read1(substream, buf, count, 1);
 }
 
@@ -960,8 +936,7 @@
 	if (substream == NULL)
 		return -EIO;
 	runtime = substream->runtime;
-	runtime->trigger = 1;
-	substream->ops->trigger(substream, 1);
+	snd_rawmidi_trigger(substream, 1);
 	result = 0;
 	while (count > 0) {
 		spin_lock_irq(&runtime->lock);
@@ -984,7 +959,7 @@
 			spin_lock_irq(&runtime->lock);
 		}
 		spin_unlock_irq(&runtime->lock);
-		count1 = snd_rawmidi_kernel_read1(substream, buf, count, 0);
+		count1 = snd_rawmidi_kernel_read1(substream, (unsigned char *)buf, count, 0);
 		if (count1 < 0)
 			return result > 0 ? result : count1;
 		result += count1;
@@ -1012,8 +987,6 @@
 	}
 	spin_lock_irqsave(&runtime->lock, flags);
 	result = runtime->avail >= runtime->buffer_size;
-	if (result)
-		runtime->trigger = 1;
 	spin_unlock_irqrestore(&runtime->lock, flags);
 	return result;		
 }
@@ -1046,7 +1019,6 @@
 	spin_lock_irqsave(&runtime->lock, flags);
 	if (runtime->avail >= runtime->buffer_size) {
 		/* warning: lowlevel layer MUST trigger down the hardware */
-		runtime->trigger = 0;
 		goto __skip;
 	}
 	if (count == 1) {	/* special case, faster code */
@@ -1061,8 +1033,12 @@
 		memcpy(buffer, runtime->buffer + runtime->hw_ptr, count1);
 		count -= count1;
 		result += count1;
-		if (count > 0)
+		if (count > 0) {
+			if (count > (int)(runtime->buffer_size - runtime->avail - count1))
+				count = runtime->buffer_size - runtime->avail - count1;
 			memcpy(buffer + count1, runtime->buffer, count);
+			result += count;
+		}
 	}
       __skip:
 	spin_unlock_irqrestore(&runtime->lock, flags);
@@ -1095,15 +1071,14 @@
 	runtime->hw_ptr %= runtime->buffer_size;
 	runtime->avail += count;
 	substream->bytes += count;
-	if (runtime->drain)
-		wake_up(&runtime->sleep);
-	else
-		if (count > 0 && runtime->event == NULL)
-			if (snd_rawmidi_ready(substream))
-				wake_up(&runtime->sleep);
+	if (count > 0) {
+		if (runtime->drain ||
+		    (runtime->event == NULL && snd_rawmidi_ready(substream)))
+			wake_up(&runtime->sleep);
+		if (runtime->event)
+			tasklet_hi_schedule(&runtime->event_tasklet);
+	}
 	spin_unlock_irqrestore(&runtime->lock, flags);
-	if (count > 0 && runtime->event)
-		runtime->event(substream);
 	return count;
 }
 
@@ -1152,7 +1127,8 @@
 			memcpy(runtime->buffer + runtime->appl_ptr, buf, count1);
 		} else {
 			spin_unlock_irqrestore(&runtime->lock, flags);
-			if (copy_from_user(runtime->buffer + runtime->appl_ptr, buf, count1)) {
+			if (copy_from_user(runtime->buffer + runtime->appl_ptr,
+					   (char __user *)buf, count1)) {
 				spin_lock_irqsave(&runtime->lock, flags);
 				result = result > 0 ? result : -EFAULT;
 				goto __end;
@@ -1167,12 +1143,10 @@
 		count -= count1;
 	}
       __end:
-	if (result > 0)
-		runtime->trigger = 1;
 	count1 = runtime->avail < runtime->buffer_size;
 	spin_unlock_irqrestore(&runtime->lock, flags);
 	if (count1)
-		substream->ops->trigger(substream, 1);
+		snd_rawmidi_trigger(substream, 1);
 	return result;
 }
 
@@ -1217,7 +1191,7 @@
 			spin_lock_irq(&runtime->lock);
 		}
 		spin_unlock_irq(&runtime->lock);
-		count1 = snd_rawmidi_kernel_write1(substream, buf, count, 0);
+		count1 = snd_rawmidi_kernel_write1(substream, (unsigned char *)buf, count, 0);
 		if (count1 < 0)
 			return result > 0 ? result : count1;
 		result += count1;
@@ -1257,8 +1231,7 @@
 	rfile = file->private_data;
 	if (rfile->input != NULL) {
 		runtime = rfile->input->runtime;
-		runtime->trigger = 1;
-		rfile->input->ops->trigger(rfile->input, 1);
+		snd_rawmidi_trigger(rfile->input, 1);
 		poll_wait(file, &runtime->sleep, wait);
 	}
 	if (rfile->output != NULL) {
@@ -1278,6 +1251,14 @@
 }
 
 /*
+ */
+#ifdef CONFIG_COMPAT
+#include "rawmidi_compat.c"
+#else
+#define snd_rawmidi_ioctl_compat	NULL
+#endif
+
+/*
 
  */
 
@@ -1347,7 +1328,8 @@
 	.open =		snd_rawmidi_open,
 	.release =	snd_rawmidi_release,
 	.poll =		snd_rawmidi_poll,
-	.ioctl =	snd_rawmidi_ioctl,
+	.unlocked_ioctl =	snd_rawmidi_ioctl,
+	.compat_ioctl =	snd_rawmidi_ioctl_compat,
 };
 
 static snd_minor_t snd_rawmidi_reg =
@@ -1628,6 +1610,7 @@
 {
 
 	snd_ctl_register_ioctl(snd_rawmidi_control_ioctl);
+	snd_ctl_register_ioctl_compat(snd_rawmidi_control_ioctl);
 #ifdef CONFIG_SND_OSSEMUL
 	{ int i;
 	/* check device map table */
@@ -1649,6 +1632,7 @@
 static void __exit alsa_rawmidi_exit(void)
 {
 	snd_ctl_unregister_ioctl(snd_rawmidi_control_ioctl);
+	snd_ctl_unregister_ioctl_compat(snd_rawmidi_control_ioctl);
 }
 
 module_init(alsa_rawmidi_init)
diff -Nru a/sound/core/rawmidi_compat.c b/sound/core/rawmidi_compat.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/sound/core/rawmidi_compat.c	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,120 @@
+/*
+ *   32bit -> 64bit ioctl wrapper for raw MIDI API
+ *   Copyright (c) by Takashi Iwai <tiwai@suse.de>
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+/* This file included from rawmidi.c */
+
+#include <linux/compat.h>
+
+struct sndrv_rawmidi_params32 {
+	s32 stream;
+	u32 buffer_size;
+	u32 avail_min;
+	unsigned int no_active_sensing; /* avoid bit-field */
+	unsigned char reserved[16];
+} __attribute__((packed));
+
+static int snd_rawmidi_ioctl_params_compat(snd_rawmidi_file_t *rfile,
+					   struct sndrv_rawmidi_params32 __user *src)
+{
+	snd_rawmidi_params_t params;
+	unsigned int val;
+
+	if (rfile->output == NULL)
+		return -EINVAL;
+	if (get_user(params.stream, &src->stream) ||
+	    get_user(params.buffer_size, &src->buffer_size) ||
+	    get_user(params.avail_min, &src->avail_min) ||
+	    get_user(val, &src->no_active_sensing))
+		return -EFAULT;
+	params.no_active_sensing = val;
+	switch (params.stream) {
+	case SNDRV_RAWMIDI_STREAM_OUTPUT:
+		return snd_rawmidi_output_params(rfile->output, &params);
+	case SNDRV_RAWMIDI_STREAM_INPUT:
+		return snd_rawmidi_input_params(rfile->input, &params);
+	}
+	return -EINVAL;
+}
+
+struct sndrv_rawmidi_status32 {
+	s32 stream;
+	struct compat_timespec tstamp;
+	u32 avail;
+	u32 xruns;
+	unsigned char reserved[16];
+} __attribute__((packed));
+
+static int snd_rawmidi_ioctl_status_compat(snd_rawmidi_file_t *rfile,
+					   struct sndrv_rawmidi_status32 __user *src)
+{
+	int err;
+	snd_rawmidi_status_t status;
+
+	if (rfile->output == NULL)
+		return -EINVAL;
+	if (get_user(status.stream, &src->stream))
+		return -EFAULT;
+
+	switch (status.stream) {
+	case SNDRV_RAWMIDI_STREAM_OUTPUT:
+		err = snd_rawmidi_output_status(rfile->output, &status);
+		break;
+	case SNDRV_RAWMIDI_STREAM_INPUT:
+		err = snd_rawmidi_input_status(rfile->input, &status);
+		break;
+	default:
+		return -EINVAL;
+	}
+	if (err < 0)
+		return err;
+
+	if (put_user(status.tstamp.tv_sec, &src->tstamp.tv_sec) ||
+	    put_user(status.tstamp.tv_nsec, &src->tstamp.tv_nsec) ||
+	    put_user(status.avail, &src->avail) ||
+	    put_user(status.xruns, &src->xruns))
+		return -EFAULT;
+
+	return 0;
+}
+
+enum {
+	SNDRV_RAWMIDI_IOCTL_PARAMS32 = _IOWR('W', 0x10, struct sndrv_rawmidi_params32),
+	SNDRV_RAWMIDI_IOCTL_STATUS32 = _IOWR('W', 0x20, struct sndrv_rawmidi_status32),
+};
+
+static long snd_rawmidi_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg)
+{
+	snd_rawmidi_file_t *rfile;
+	void __user *argp = compat_ptr(arg);
+
+	rfile = file->private_data;
+	switch (cmd) {
+	case SNDRV_RAWMIDI_IOCTL_PVERSION:
+	case SNDRV_RAWMIDI_IOCTL_INFO:
+	case SNDRV_RAWMIDI_IOCTL_DROP:
+	case SNDRV_RAWMIDI_IOCTL_DRAIN:
+		return snd_rawmidi_ioctl(file, cmd, (unsigned long)argp);
+	case SNDRV_RAWMIDI_IOCTL_PARAMS32:
+		return snd_rawmidi_ioctl_params_compat(rfile, argp);
+	case SNDRV_RAWMIDI_IOCTL_STATUS32:
+		return snd_rawmidi_ioctl_status_compat(rfile, argp);
+	}
+	return -ENOIOCTLCMD;
+}
diff -Nru a/sound/core/rtctimer.c b/sound/core/rtctimer.c
--- a/sound/core/rtctimer.c	2005-03-11 12:51:51 -08:00
+++ b/sound/core/rtctimer.c	2005-03-11 12:51:51 -08:00
@@ -183,4 +183,6 @@
 
 MODULE_LICENSE("GPL");
 
+MODULE_ALIAS("snd-timer-" __stringify(SNDRV_TIMER_GLOBAL_RTC));
+
 #endif /* CONFIG_RTC || CONFIG_RTC_MODULE */
diff -Nru a/sound/core/seq/oss/seq_oss.c b/sound/core/seq/oss/seq_oss.c
--- a/sound/core/seq/oss/seq_oss.c	2005-03-11 12:51:50 -08:00
+++ b/sound/core/seq/oss/seq_oss.c	2005-03-11 12:51:50 -08:00
@@ -59,7 +59,7 @@
 static int odev_release(struct inode *inode, struct file *file);
 static ssize_t odev_read(struct file *file, char __user *buf, size_t count, loff_t *offset);
 static ssize_t odev_write(struct file *file, const char __user *buf, size_t count, loff_t *offset);
-static int odev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg);
+static long odev_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
 static unsigned int odev_poll(struct file *file, poll_table * wait);
 #ifdef CONFIG_PROC_FS
 static void info_read(snd_info_entry_t *entry, snd_info_buffer_t *buf);
@@ -177,20 +177,20 @@
 	return snd_seq_oss_write(dp, buf, count, file);
 }
 
-static int
-odev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+static long
+odev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 {
 	seq_oss_devinfo_t *dp;
-	int err;
 	dp = file->private_data;
 	snd_assert(dp != NULL, return -EIO);
-	/* FIXME: need to unlock BKL to allow preemption */
-	unlock_kernel();
-	err = snd_seq_oss_ioctl(dp, cmd, arg);
-	lock_kernel();
-	return err;
+	return snd_seq_oss_ioctl(dp, cmd, arg);
 }
 
+#ifdef CONFIG_COMPAT
+#define odev_ioctl_compat	odev_ioctl
+#else
+#define odev_ioctl_compat	NULL
+#endif
 
 static unsigned int
 odev_poll(struct file *file, poll_table * wait)
@@ -213,7 +213,8 @@
 	.open =		odev_open,
 	.release =	odev_release,
 	.poll =		odev_poll,
-	.ioctl =	odev_ioctl,
+	.unlocked_ioctl =	odev_ioctl,
+	.compat_ioctl =	odev_ioctl_compat,
 };
 
 static snd_minor_t seq_oss_reg = {
diff -Nru a/sound/core/seq/oss/seq_oss_midi.c b/sound/core/seq/oss/seq_oss_midi.c
--- a/sound/core/seq/oss/seq_oss_midi.c	2005-03-11 12:51:40 -08:00
+++ b/sound/core/seq/oss/seq_oss_midi.c	2005-03-11 12:51:40 -08:00
@@ -56,7 +56,7 @@
 static int max_midi_devs;
 static seq_oss_midi_t *midi_devs[SNDRV_SEQ_OSS_MAX_MIDI_DEVS];
 
-static spinlock_t register_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(register_lock);
 
 /*
  * prototypes
diff -Nru a/sound/core/seq/oss/seq_oss_readq.c b/sound/core/seq/oss/seq_oss_readq.c
--- a/sound/core/seq/oss/seq_oss_readq.c	2005-03-11 12:51:42 -08:00
+++ b/sound/core/seq/oss/seq_oss_readq.c	2005-03-11 12:51:42 -08:00
@@ -24,6 +24,7 @@
 #include "seq_oss_event.h"
 #include <sound/seq_oss_legacy.h>
 #include "../seq_lock.h"
+#include <linux/wait.h>
 
 /*
  * constants
@@ -165,7 +166,9 @@
 void
 snd_seq_oss_readq_wait(seq_oss_readq_t *q)
 {
-	interruptible_sleep_on_timeout(&q->midi_sleep, q->pre_event_timeout);
+	wait_event_interruptible_timeout(q->midi_sleep,
+					 (q->qlen > 0 || q->head == q->tail),
+					 q->pre_event_timeout);
 }
 
 /*
diff -Nru a/sound/core/seq/oss/seq_oss_synth.c b/sound/core/seq/oss/seq_oss_synth.c
--- a/sound/core/seq/oss/seq_oss_synth.c	2005-03-11 12:51:41 -08:00
+++ b/sound/core/seq/oss/seq_oss_synth.c	2005-03-11 12:51:41 -08:00
@@ -75,7 +75,7 @@
 	"MIDI", /* name */
 };
 
-static spinlock_t register_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(register_lock);
 
 /*
  * prototypes
diff -Nru a/sound/core/seq/oss/seq_oss_writeq.c b/sound/core/seq/oss/seq_oss_writeq.c
--- a/sound/core/seq/oss/seq_oss_writeq.c	2005-03-11 12:51:51 -08:00
+++ b/sound/core/seq/oss/seq_oss_writeq.c	2005-03-11 12:51:51 -08:00
@@ -26,6 +26,7 @@
 #include <sound/seq_oss_legacy.h>
 #include "../seq_lock.h"
 #include "../seq_clientmgr.h"
+#include <linux/wait.h>
 
 
 /*
@@ -91,7 +92,6 @@
 {
 	seq_oss_devinfo_t *dp = q->dp;
 	abstime_t time;
-	unsigned long flags;
 
 	time = snd_seq_oss_timer_cur_tick(dp->timer);
 	if (q->sync_time >= time)
@@ -115,27 +115,13 @@
 		snd_seq_kernel_client_enqueue_blocking(dp->cseq, &ev, NULL, 0, 0);
 	}
 
-	spin_lock_irqsave(&q->sync_lock, flags);
-	if (! q->sync_event_put) { /* echoback event has been received */
-		spin_unlock_irqrestore(&q->sync_lock, flags);
-		return 0;
-	}
-		
-	/* wait for echo event */
-	spin_unlock(&q->sync_lock);
-	interruptible_sleep_on_timeout(&q->sync_sleep, HZ);
-	spin_lock(&q->sync_lock);
-	if (signal_pending(current)) {
+	wait_event_interruptible_timeout(q->sync_sleep, ! q->sync_event_put, HZ);
+	if (signal_pending(current))
 		/* interrupted - return 0 to finish sync */
 		q->sync_event_put = 0;
-		spin_unlock_irqrestore(&q->sync_lock, flags);
-		return 0;
-	}
-	spin_unlock_irqrestore(&q->sync_lock, flags);
-	if (q->sync_time >= time)
+	if (! q->sync_event_put || q->sync_time >= time)
 		return 0;
-	else
-		return 1;
+	return 1;
 }
 
 /*
diff -Nru a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c
--- a/sound/core/seq/seq_clientmgr.c	2005-03-11 12:51:41 -08:00
+++ b/sound/core/seq/seq_clientmgr.c	2005-03-11 12:51:41 -08:00
@@ -37,8 +37,8 @@
 #include "seq_info.h"
 #include "seq_system.h"
 #include <sound/seq_device.h>
-#if defined(CONFIG_SND_BIT32_EMUL) || defined(CONFIG_SND_BIT32_EMUL_MODULE)
-#include "../ioctl32/ioctl32.h"
+#ifdef CONFIG_COMPAT
+#include <linux/compat.h>
 #endif
 
 /* Client Manager
@@ -51,7 +51,7 @@
 #define SNDRV_SEQ_LFLG_OUTPUT	0x0002
 #define SNDRV_SEQ_LFLG_OPEN	(SNDRV_SEQ_LFLG_INPUT|SNDRV_SEQ_LFLG_OUTPUT)
 
-static spinlock_t clients_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(clients_lock);
 static DECLARE_MUTEX(register_mutex);
 
 /*
@@ -413,7 +413,7 @@
 			}
 			count -= sizeof(snd_seq_event_t);
 			buf += sizeof(snd_seq_event_t);
-			err = snd_seq_expand_var_event(&cell->event, count, buf, 0, sizeof(snd_seq_event_t));
+			err = snd_seq_expand_var_event(&cell->event, count, (char *)buf, 0, sizeof(snd_seq_event_t));
 			if (err < 0)
 				break;
 			result += err;
@@ -1012,7 +1012,7 @@
 			event.data.ext.ptr = (char*)buf + sizeof(snd_seq_event_t);
 			len += extlen; /* increment data length */
 		} else {
-#if defined(CONFIG_SND_BIT32_EMUL) || defined(CONFIG_SND_BIT32_EMUL_MODULE)
+#ifdef CONFIG_COMPAT
 			if (client->convert32 && snd_seq_ev_is_varusr(&event)) {
 				void *ptr = compat_ptr(event.data.raw32.d[1]);
 				event.data.ext.ptr = ptr;
@@ -2131,21 +2131,20 @@
 }
 
 
-static int snd_seq_ioctl(struct inode *inode, struct file *file,
-			 unsigned int cmd, unsigned long arg)
+static long snd_seq_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 {
 	client_t *client = (client_t *) file->private_data;
-	int err;
 
 	snd_assert(client != NULL, return -ENXIO);
 		
-	/* FIXME: need to unlock BKL to allow preemption */
-	unlock_kernel();
-	err = snd_seq_do_ioctl(client, cmd, (void __user *) arg);
-	lock_kernel();
-	return err;
+	return snd_seq_do_ioctl(client, cmd, (void __user *) arg);
 }
 
+#ifdef CONFIG_COMPAT
+#include "seq_compat.c"
+#else
+#define snd_seq_ioctl_compat	NULL
+#endif
 
 /* -------------------------------------------------------- */
 
@@ -2321,7 +2320,7 @@
 	if (client == NULL)
 		return -ENXIO;
 	fs = snd_enter_user();
-	result = snd_seq_do_ioctl(client, cmd, arg);
+	result = snd_seq_do_ioctl(client, cmd, (void __user *)arg);
 	snd_leave_user(fs);
 	return result;
 }
@@ -2462,7 +2461,8 @@
 	.open =		snd_seq_open,
 	.release =	snd_seq_release,
 	.poll =		snd_seq_poll,
-	.ioctl =	snd_seq_ioctl,
+	.unlocked_ioctl =	snd_seq_ioctl,
+	.compat_ioctl =	snd_seq_ioctl_compat,
 };
 
 static snd_minor_t snd_seq_reg =
diff -Nru a/sound/core/seq/seq_compat.c b/sound/core/seq/seq_compat.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/sound/core/seq/seq_compat.c	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,137 @@
+/*
+ *   32bit -> 64bit ioctl wrapper for sequencer API
+ *   Copyright (c) by Takashi Iwai <tiwai@suse.de>
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+/* This file included from seq.c */
+
+#include <linux/compat.h>
+
+struct sndrv_seq_port_info32 {
+	struct sndrv_seq_addr addr;	/* client/port numbers */
+	char name[64];			/* port name */
+
+	u32 capability;	/* port capability bits */
+	u32 type;		/* port type bits */
+	s32 midi_channels;		/* channels per MIDI port */
+	s32 midi_voices;		/* voices per MIDI port */
+	s32 synth_voices;		/* voices per SYNTH port */
+
+	s32 read_use;			/* R/O: subscribers for output (from this port) */
+	s32 write_use;			/* R/O: subscribers for input (to this port) */
+
+	u32 kernel;			/* reserved for kernel use (must be NULL) */
+	u32 flags;		/* misc. conditioning */
+	unsigned char time_queue;	/* queue # for timestamping */
+	char reserved[59];		/* for future use */
+};
+
+static int snd_seq_call_port_info_ioctl(client_t *client, unsigned int cmd,
+					struct sndrv_seq_port_info32 __user *data32)
+{
+	int err = -EFAULT;
+	snd_seq_port_info_t *data;
+	mm_segment_t fs;
+
+	data = kmalloc(sizeof(*data), GFP_KERNEL);
+	if (! data)
+		return -ENOMEM;
+
+	if (copy_from_user(data, data32, sizeof(*data32)) ||
+	    get_user(data->flags, &data32->flags) ||
+	    get_user(data->time_queue, &data32->time_queue))
+		goto error;
+	data->kernel = NULL;
+
+	fs = snd_enter_user();
+	err = snd_seq_do_ioctl(client, cmd, data);
+	snd_leave_user(fs);
+	if (err < 0)
+		goto error;
+
+	if (copy_to_user(data32, data, sizeof(*data32)) ||
+	    put_user(data->flags, &data32->flags) ||
+	    put_user(data->time_queue, &data32->time_queue))
+		err = -EFAULT;
+
+ error:
+	kfree(data);
+	return err;
+}
+
+
+
+/*
+ */
+
+enum {
+	SNDRV_SEQ_IOCTL_CREATE_PORT32 = _IOWR('S', 0x20, struct sndrv_seq_port_info32),
+	SNDRV_SEQ_IOCTL_DELETE_PORT32 = _IOW ('S', 0x21, struct sndrv_seq_port_info32),
+	SNDRV_SEQ_IOCTL_GET_PORT_INFO32 = _IOWR('S', 0x22, struct sndrv_seq_port_info32),
+	SNDRV_SEQ_IOCTL_SET_PORT_INFO32 = _IOW ('S', 0x23, struct sndrv_seq_port_info32),
+	SNDRV_SEQ_IOCTL_QUERY_NEXT_PORT32 = _IOWR('S', 0x52, struct sndrv_seq_port_info32),
+};
+
+static long snd_seq_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg)
+{
+	client_t *client = (client_t *) file->private_data;
+	void __user *argp = compat_ptr(arg);
+
+	snd_assert(client != NULL, return -ENXIO);
+
+	switch (cmd) {
+	case SNDRV_SEQ_IOCTL_PVERSION:
+	case SNDRV_SEQ_IOCTL_CLIENT_ID:
+	case SNDRV_SEQ_IOCTL_SYSTEM_INFO:
+	case SNDRV_SEQ_IOCTL_GET_CLIENT_INFO:
+	case SNDRV_SEQ_IOCTL_SET_CLIENT_INFO:
+	case SNDRV_SEQ_IOCTL_SUBSCRIBE_PORT:
+	case SNDRV_SEQ_IOCTL_UNSUBSCRIBE_PORT:
+	case SNDRV_SEQ_IOCTL_CREATE_QUEUE:
+	case SNDRV_SEQ_IOCTL_DELETE_QUEUE:
+	case SNDRV_SEQ_IOCTL_GET_QUEUE_INFO:
+	case SNDRV_SEQ_IOCTL_SET_QUEUE_INFO:
+	case SNDRV_SEQ_IOCTL_GET_NAMED_QUEUE:
+	case SNDRV_SEQ_IOCTL_GET_QUEUE_STATUS:
+	case SNDRV_SEQ_IOCTL_GET_QUEUE_TEMPO:
+	case SNDRV_SEQ_IOCTL_SET_QUEUE_TEMPO:
+	case SNDRV_SEQ_IOCTL_GET_QUEUE_TIMER:
+	case SNDRV_SEQ_IOCTL_SET_QUEUE_TIMER:
+	case SNDRV_SEQ_IOCTL_GET_QUEUE_CLIENT:
+	case SNDRV_SEQ_IOCTL_SET_QUEUE_CLIENT:
+	case SNDRV_SEQ_IOCTL_GET_CLIENT_POOL:
+	case SNDRV_SEQ_IOCTL_SET_CLIENT_POOL:
+	case SNDRV_SEQ_IOCTL_REMOVE_EVENTS:
+	case SNDRV_SEQ_IOCTL_QUERY_SUBS:
+	case SNDRV_SEQ_IOCTL_GET_SUBSCRIPTION:
+	case SNDRV_SEQ_IOCTL_QUERY_NEXT_CLIENT:
+	case SNDRV_SEQ_IOCTL_RUNNING_MODE:
+		return snd_seq_do_ioctl(client, cmd, argp);
+	case SNDRV_SEQ_IOCTL_CREATE_PORT32:
+		return snd_seq_call_port_info_ioctl(client, SNDRV_SEQ_IOCTL_CREATE_PORT, argp);
+	case SNDRV_SEQ_IOCTL_DELETE_PORT32:
+		return snd_seq_call_port_info_ioctl(client, SNDRV_SEQ_IOCTL_DELETE_PORT, argp);
+	case SNDRV_SEQ_IOCTL_GET_PORT_INFO32:
+		return snd_seq_call_port_info_ioctl(client, SNDRV_SEQ_IOCTL_GET_PORT_INFO, argp);
+	case SNDRV_SEQ_IOCTL_SET_PORT_INFO32:
+		return snd_seq_call_port_info_ioctl(client, SNDRV_SEQ_IOCTL_SET_PORT_INFO, argp);
+	case SNDRV_SEQ_IOCTL_QUERY_NEXT_PORT32:
+		return snd_seq_call_port_info_ioctl(client, SNDRV_SEQ_IOCTL_QUERY_NEXT_PORT, argp);
+	}
+	return -ENOIOCTLCMD;
+}
diff -Nru a/sound/core/seq/seq_dummy.c b/sound/core/seq/seq_dummy.c
--- a/sound/core/seq/seq_dummy.c	2005-03-11 12:51:46 -08:00
+++ b/sound/core/seq/seq_dummy.c	2005-03-11 12:51:46 -08:00
@@ -63,6 +63,7 @@
 MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>");
 MODULE_DESCRIPTION("ALSA sequencer MIDI-through client");
 MODULE_LICENSE("GPL");
+MODULE_ALIAS("snd-seq-client-" __stringify(SNDRV_SEQ_CLIENT_DUMMY));
 
 static int ports = 1;
 static int duplex = 0;
diff -Nru a/sound/core/seq/seq_instr.c b/sound/core/seq/seq_instr.c
--- a/sound/core/seq/seq_instr.c	2005-03-11 12:51:42 -08:00
+++ b/sound/core/seq/seq_instr.c	2005-03-11 12:51:42 -08:00
@@ -430,7 +430,7 @@
 
 	if (ev->data.ext.len < sizeof(snd_seq_instr_header_t))
 		goto __return;
-	if (copy_from_user(&put, ev->data.ext.ptr, sizeof(snd_seq_instr_header_t))) {
+	if (copy_from_user(&put, (void __user *)ev->data.ext.ptr, sizeof(snd_seq_instr_header_t))) {
 		result = -EFAULT;
 		goto __return;
 	}
@@ -466,7 +466,7 @@
 	if (instr->type == SNDRV_SEQ_INSTR_ATYPE_DATA) {
 		result = ops->put(ops->private_data,
 				  instr,
-				  ev->data.ext.ptr + sizeof(snd_seq_instr_header_t),
+				  (void __user *)ev->data.ext.ptr + sizeof(snd_seq_instr_header_t),
 				  ev->data.ext.len - sizeof(snd_seq_instr_header_t),
 				  atomic,
 				  put.cmd);
@@ -513,7 +513,7 @@
 
 	if (ev->data.ext.len < sizeof(snd_seq_instr_header_t))
 		goto __return;
-	if (copy_from_user(&ifree, ev->data.ext.ptr, sizeof(snd_seq_instr_header_t))) {
+	if (copy_from_user(&ifree, (void __user *)ev->data.ext.ptr, sizeof(snd_seq_instr_header_t))) {
 		result = -EFAULT;
 		goto __return;
 	}
diff -Nru a/sound/core/seq/seq_memory.c b/sound/core/seq/seq_memory.c
--- a/sound/core/seq/seq_memory.c	2005-03-11 12:51:41 -08:00
+++ b/sound/core/seq/seq_memory.c	2005-03-11 12:51:41 -08:00
@@ -90,7 +90,7 @@
 
 	if (event->data.ext.len & SNDRV_SEQ_EXT_USRPTR) {
 		char buf[32];
-		char __user *curptr = event->data.ext.ptr;
+		char __user *curptr = (char __user *)event->data.ext.ptr;
 		while (len > 0) {
 			int size = sizeof(buf);
 			if (len < size)
@@ -134,7 +134,7 @@
 	return 0;
 }
 
-static int seq_copy_in_user(char **bufptr, const void *src, int size)
+static int seq_copy_in_user(char __user **bufptr, const void *src, int size)
 {
 	if (copy_to_user(*bufptr, src, size))
 		return -EFAULT;
@@ -158,7 +158,7 @@
 	if (event->data.ext.len & SNDRV_SEQ_EXT_USRPTR) {
 		if (! in_kernel)
 			return -EINVAL;
-		if (copy_from_user(buf, event->data.ext.ptr, len))
+		if (copy_from_user(buf, (void __user *)event->data.ext.ptr, len))
 			return -EFAULT;
 		return newlen;
 	}
@@ -336,7 +336,7 @@
 				tmp->event = src->event;
 				src = src->next;
 			} else if (is_usrptr) {
-				if (copy_from_user(&tmp->event, buf, size)) {
+				if (copy_from_user(&tmp->event, (char __user *)buf, size)) {
 					err = -EFAULT;
 					goto __error;
 				}
diff -Nru a/sound/core/seq/seq_midi_event.c b/sound/core/seq/seq_midi_event.c
--- a/sound/core/seq/seq_midi_event.c	2005-03-11 12:51:40 -08:00
+++ b/sound/core/seq/seq_midi_event.c	2005-03-11 12:51:40 -08:00
@@ -525,3 +525,15 @@
 EXPORT_SYMBOL(snd_midi_event_encode);
 EXPORT_SYMBOL(snd_midi_event_encode_byte);
 EXPORT_SYMBOL(snd_midi_event_decode);
+
+static int __init alsa_seq_midi_event_init(void)
+{
+	return 0;
+}
+
+static void __exit alsa_seq_midi_event_exit(void)
+{
+}
+
+module_init(alsa_seq_midi_event_init)
+module_exit(alsa_seq_midi_event_exit)
diff -Nru a/sound/core/seq/seq_queue.c b/sound/core/seq/seq_queue.c
--- a/sound/core/seq/seq_queue.c	2005-03-11 12:51:50 -08:00
+++ b/sound/core/seq/seq_queue.c	2005-03-11 12:51:50 -08:00
@@ -49,7 +49,7 @@
 
 /* list of allocated queues */
 static queue_t *queue_list[SNDRV_SEQ_MAX_QUEUES];
-static spinlock_t queue_list_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(queue_list_lock);
 /* number of queues allocated */
 static int num_queues;
 
@@ -650,7 +650,7 @@
 /*
  * send events to all subscribed ports
  */
-static void queue_broadcast_event(queue_t *q, snd_seq_event_t *ev, int from_timer_port, int atomic, int hop)
+static void queue_broadcast_event(queue_t *q, snd_seq_event_t *ev, int atomic, int hop)
 {
 	snd_seq_event_t sev;
 
@@ -661,60 +661,58 @@
 	sev.queue = q->queue;
 	sev.data.queue.queue = q->queue;
 
-	if (from_timer_port) {
-		/* broadcast events from Timer port */
-		sev.source.client = SNDRV_SEQ_CLIENT_SYSTEM;
-		sev.source.port = SNDRV_SEQ_PORT_SYSTEM_TIMER;
-		sev.dest.client = SNDRV_SEQ_ADDRESS_SUBSCRIBERS;
-		snd_seq_kernel_client_dispatch(SNDRV_SEQ_CLIENT_SYSTEM, &sev, atomic, hop);
-	}
+	/* broadcast events from Timer port */
+	sev.source.client = SNDRV_SEQ_CLIENT_SYSTEM;
+	sev.source.port = SNDRV_SEQ_PORT_SYSTEM_TIMER;
+	sev.dest.client = SNDRV_SEQ_ADDRESS_SUBSCRIBERS;
+	snd_seq_kernel_client_dispatch(SNDRV_SEQ_CLIENT_SYSTEM, &sev, atomic, hop);
 }
 
 /*
  * process a received queue-control event.
  * this function is exported for seq_sync.c.
  */
-void snd_seq_queue_process_event(queue_t *q, snd_seq_event_t *ev, int from_timer_port, int atomic, int hop)
+void snd_seq_queue_process_event(queue_t *q, snd_seq_event_t *ev, int atomic, int hop)
 {
 	switch (ev->type) {
 	case SNDRV_SEQ_EVENT_START:
 		snd_seq_prioq_leave(q->tickq, ev->source.client, 1);
 		snd_seq_prioq_leave(q->timeq, ev->source.client, 1);
 		if (! snd_seq_timer_start(q->timer))
-			queue_broadcast_event(q, ev, from_timer_port, atomic, hop);
+			queue_broadcast_event(q, ev, atomic, hop);
 		break;
 
 	case SNDRV_SEQ_EVENT_CONTINUE:
 		if (! snd_seq_timer_continue(q->timer))
-			queue_broadcast_event(q, ev, from_timer_port, atomic, hop);
+			queue_broadcast_event(q, ev, atomic, hop);
 		break;
 
 	case SNDRV_SEQ_EVENT_STOP:
 		snd_seq_timer_stop(q->timer);
-		queue_broadcast_event(q, ev, from_timer_port, atomic, hop);
+		queue_broadcast_event(q, ev, atomic, hop);
 		break;
 
 	case SNDRV_SEQ_EVENT_TEMPO:
 		snd_seq_timer_set_tempo(q->timer, ev->data.queue.param.value);
-		queue_broadcast_event(q, ev, from_timer_port, atomic, hop);
+		queue_broadcast_event(q, ev, atomic, hop);
 		break;
 
 	case SNDRV_SEQ_EVENT_SETPOS_TICK:
 		if (snd_seq_timer_set_position_tick(q->timer, ev->data.queue.param.time.tick) == 0) {
-			queue_broadcast_event(q, ev, from_timer_port, atomic, hop);
+			queue_broadcast_event(q, ev, atomic, hop);
 		}
 		break;
 
 	case SNDRV_SEQ_EVENT_SETPOS_TIME:
 		if (snd_seq_timer_set_position_time(q->timer, ev->data.queue.param.time.time) == 0) {
-			queue_broadcast_event(q, ev, from_timer_port, atomic, hop);
+			queue_broadcast_event(q, ev, atomic, hop);
 		}
 		break;
 	case SNDRV_SEQ_EVENT_QUEUE_SKEW:
 		if (snd_seq_timer_set_skew(q->timer,
 					   ev->data.queue.param.skew.value,
 					   ev->data.queue.param.skew.base) == 0) {
-			queue_broadcast_event(q, ev, from_timer_port, atomic, hop);
+			queue_broadcast_event(q, ev, atomic, hop);
 		}
 		break;
 	}
@@ -740,7 +738,7 @@
 		return -EPERM;
 	}
 
-	snd_seq_queue_process_event(q, ev, 1, atomic, hop);
+	snd_seq_queue_process_event(q, ev, atomic, hop);
 
 	queue_access_unlock(q);
 	queuefree(q);
diff -Nru a/sound/core/seq/seq_queue.h b/sound/core/seq/seq_queue.h
--- a/sound/core/seq/seq_queue.h	2005-03-11 12:51:42 -08:00
+++ b/sound/core/seq/seq_queue.h	2005-03-11 12:51:42 -08:00
@@ -111,7 +111,7 @@
 int snd_seq_queue_is_used(int queueid, int client);
 
 int snd_seq_control_queue(snd_seq_event_t *ev, int atomic, int hop);
-void snd_seq_queue_process_event(queue_t *q, snd_seq_event_t *ev, int from_timer_port, int atomic, int hop);
+void snd_seq_queue_process_event(queue_t *q, snd_seq_event_t *ev, int atomic, int hop);
 
 /*
  * 64bit division - for sync stuff..
diff -Nru a/sound/core/sound.c b/sound/core/sound.c
--- a/sound/core/sound.c	2005-03-11 12:51:47 -08:00
+++ b/sound/core/sound.c	2005-03-11 12:51:47 -08:00
@@ -48,7 +48,6 @@
 MODULE_PARM_DESC(major, "Major # for sound driver.");
 module_param(cards_limit, int, 0444);
 MODULE_PARM_DESC(cards_limit, "Count of auto-loadable soundcards.");
-MODULE_ALIAS_CHARDEV_MAJOR(CONFIG_SND_MAJOR);
 #ifdef CONFIG_DEVFS_FS
 module_param(device_mode, int, 0444);
 MODULE_PARM_DESC(device_mode, "Device file permission mask for devfs.");
@@ -420,7 +419,9 @@
 #ifdef CONFIG_PM
 EXPORT_SYMBOL(snd_power_wait);
 EXPORT_SYMBOL(snd_card_set_pm_callback);
-EXPORT_SYMBOL(snd_card_set_dev_pm_callback);
+#if defined(CONFIG_PM) && defined(CONFIG_SND_GENERIC_PM)
+EXPORT_SYMBOL(snd_card_set_generic_pm_callback);
+#endif
 #ifdef CONFIG_PCI
 EXPORT_SYMBOL(snd_card_pci_suspend);
 EXPORT_SYMBOL(snd_card_pci_resume);
@@ -467,6 +468,10 @@
 EXPORT_SYMBOL(snd_ctl_notify);
 EXPORT_SYMBOL(snd_ctl_register_ioctl);
 EXPORT_SYMBOL(snd_ctl_unregister_ioctl);
+#ifdef CONFIG_COMPAT
+EXPORT_SYMBOL(snd_ctl_register_ioctl_compat);
+EXPORT_SYMBOL(snd_ctl_unregister_ioctl_compat);
+#endif
 EXPORT_SYMBOL(snd_ctl_elem_read);
 EXPORT_SYMBOL(snd_ctl_elem_write);
   /* misc.c */
diff -Nru a/sound/core/timer.c b/sound/core/timer.c
--- a/sound/core/timer.c	2005-03-11 12:51:47 -08:00
+++ b/sound/core/timer.c	2005-03-11 12:51:47 -08:00
@@ -76,7 +76,7 @@
 static LIST_HEAD(snd_timer_slave_list);
 
 /* lock for slave active lists */
-static spinlock_t slave_active_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(slave_active_lock);
 
 static DECLARE_MUTEX(register_mutex);
 
@@ -1653,8 +1653,7 @@
 	return (err = snd_timer_continue(tu->timeri)) < 0 ? err : 0;
 }
 
-static inline int _snd_timer_user_ioctl(struct inode *inode, struct file *file,
-					unsigned int cmd, unsigned long arg)
+static long snd_timer_user_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 {
 	snd_timer_user_t *tu;
 	void __user *argp = (void __user *)arg;
@@ -1701,17 +1700,6 @@
 	return -ENOTTY;
 }
 
-/* FIXME: need to unlock BKL to allow preemption */
-static int snd_timer_user_ioctl(struct inode *inode, struct file * file,
-				unsigned int cmd, unsigned long arg)
-{
-	int err;
-	unlock_kernel();
-	err = _snd_timer_user_ioctl(inode, file, cmd, arg);
-	lock_kernel();
-	return err;
-}
-
 static int snd_timer_user_fasync(int fd, struct file * file, int on)
 {
 	snd_timer_user_t *tu;
@@ -1803,6 +1791,12 @@
 	return mask;
 }
 
+#ifdef CONFIG_COMPAT
+#include "timer_compat.c"
+#else
+#define snd_timer_user_ioctl_compat	NULL
+#endif
+
 static struct file_operations snd_timer_f_ops =
 {
 	.owner =	THIS_MODULE,
@@ -1810,7 +1804,8 @@
 	.open =		snd_timer_user_open,
 	.release =	snd_timer_user_release,
 	.poll =		snd_timer_user_poll,
-	.ioctl =	snd_timer_user_ioctl,
+	.unlocked_ioctl =	snd_timer_user_ioctl,
+	.compat_ioctl =	snd_timer_user_ioctl_compat,
 	.fasync = 	snd_timer_user_fasync,
 };
 
diff -Nru a/sound/core/timer_compat.c b/sound/core/timer_compat.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/sound/core/timer_compat.c	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,119 @@
+/*
+ *   32bit -> 64bit ioctl wrapper for timer API
+ *   Copyright (c) by Takashi Iwai <tiwai@suse.de>
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+/* This file included from timer.c */
+
+#include <linux/compat.h>
+
+struct sndrv_timer_info32 {
+	u32 flags;
+	s32 card;
+	unsigned char id[64];
+	unsigned char name[80];
+	u32 reserved0;
+	u32 resolution;
+	unsigned char reserved[64];
+};
+
+static int snd_timer_user_info_compat(struct file *file,
+				      struct sndrv_timer_info32 __user *_info)
+{
+	snd_timer_user_t *tu;
+	struct sndrv_timer_info32 info;
+	snd_timer_t *t;
+
+	tu = file->private_data;
+	snd_assert(tu->timeri != NULL, return -ENXIO);
+	t = tu->timeri->timer;
+	snd_assert(t != NULL, return -ENXIO);
+	memset(&info, 0, sizeof(info));
+	info.card = t->card ? t->card->number : -1;
+	if (t->hw.flags & SNDRV_TIMER_HW_SLAVE)
+		info.flags |= SNDRV_TIMER_FLG_SLAVE;
+	strlcpy(info.id, t->id, sizeof(info.id));
+	strlcpy(info.name, t->name, sizeof(info.name));
+	info.resolution = t->hw.resolution;
+	if (copy_to_user(_info, &info, sizeof(*_info)))
+		return -EFAULT;
+	return 0;
+}
+
+struct sndrv_timer_status32 {
+	struct compat_timespec tstamp;
+	u32 resolution;
+	u32 lost;
+	u32 overrun;
+	u32 queue;
+	unsigned char reserved[64];
+};
+
+static int snd_timer_user_status_compat(struct file *file,
+					struct sndrv_timer_status32 __user *_status)
+{
+	snd_timer_user_t *tu;
+	snd_timer_status_t status;
+	
+	tu = file->private_data;
+	snd_assert(tu->timeri != NULL, return -ENXIO);
+	memset(&status, 0, sizeof(status));
+	status.tstamp = tu->tstamp;
+	status.resolution = snd_timer_resolution(tu->timeri);
+	status.lost = tu->timeri->lost;
+	status.overrun = tu->overrun;
+	spin_lock_irq(&tu->qlock);
+	status.queue = tu->qused;
+	spin_unlock_irq(&tu->qlock);
+	if (copy_to_user(_status, &status, sizeof(status)))
+		return -EFAULT;
+	return 0;
+}
+
+/*
+ */
+
+enum {
+	SNDRV_TIMER_IOCTL_INFO32 = _IOR('T', 0x11, struct sndrv_timer_info32),
+	SNDRV_TIMER_IOCTL_STATUS32 = _IOW('T', 0x14, struct sndrv_timer_status32),
+};
+
+static long snd_timer_user_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg)
+{
+	void __user *argp = compat_ptr(arg);
+
+	switch (cmd) {
+	case SNDRV_TIMER_IOCTL_PVERSION:
+	case SNDRV_TIMER_IOCTL_TREAD:
+	case SNDRV_TIMER_IOCTL_GINFO:
+	case SNDRV_TIMER_IOCTL_GPARAMS:
+	case SNDRV_TIMER_IOCTL_GSTATUS:
+	case SNDRV_TIMER_IOCTL_SELECT:
+	case SNDRV_TIMER_IOCTL_PARAMS:
+	case SNDRV_TIMER_IOCTL_START:
+	case SNDRV_TIMER_IOCTL_STOP:
+	case SNDRV_TIMER_IOCTL_CONTINUE:
+	case SNDRV_TIMER_IOCTL_NEXT_DEVICE:
+		return snd_timer_user_ioctl(file, cmd, (unsigned long)argp);
+	case SNDRV_TIMER_IOCTL_INFO32:
+		return snd_timer_user_info_compat(file, argp);
+	case SNDRV_TIMER_IOCTL_STATUS32:
+		return snd_timer_user_status_compat(file, argp);
+	}
+	return -ENOIOCTLCMD;
+}
diff -Nru a/sound/drivers/mpu401/mpu401.c b/sound/drivers/mpu401/mpu401.c
--- a/sound/drivers/mpu401/mpu401.c	2005-03-11 12:51:47 -08:00
+++ b/sound/drivers/mpu401/mpu401.c	2005-03-11 12:51:47 -08:00
@@ -1,12 +1,7 @@
 /*
  *  Driver for generic MPU-401 boards (UART mode only)
  *  Copyright (c) by Jaroslav Kysela <perex@suse.cz>
- *
- *  ACPI PnP Copyright (c) 2004 by Clemens Ladisch <clemens@ladisch.de>
- *  based on 8250_acpi.c
- *  Copyright (c) 2002-2003 Matthew Wilcox for Hewlett-Packard
- *  Copyright (C) 2004 Hewlett-Packard Co
- *       Bjorn Helgaas <bjorn.helgaas@hp.com>
+ *  Copyright (c) 2004 by Castet Matthieu <castet.matthieu@free.fr>
  *
  *
  *   This program is free software; you can redistribute it and/or modify
@@ -27,27 +22,21 @@
 
 #include <sound/driver.h>
 #include <linux/init.h>
-#ifdef CONFIG_ACPI_BUS
-#include <linux/acpi.h>
-#endif
+#include <linux/pnp.h>
 #include <linux/moduleparam.h>
 #include <sound/core.h>
 #include <sound/mpu401.h>
 #include <sound/initval.h>
 
-#ifdef CONFIG_ACPI_BUS
-#define USE_ACPI_PNP
-#endif
-
 MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
 MODULE_DESCRIPTION("MPU-401 UART");
 MODULE_LICENSE("GPL");
 
-static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;	/* Index 0-MAX */
+static int index[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = -2}; /* exclude the first card */
 static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;	/* ID for this card */
 static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE;	/* Enable this card */
-#ifdef USE_ACPI_PNP
-static int acpipnp[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS-1)] = 1 };
+#ifdef CONFIG_PNP
+static int pnp[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1};
 #endif
 static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;	/* MPU-401 port number */
 static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ;	/* MPU-401 IRQ */
@@ -58,115 +47,36 @@
 MODULE_PARM_DESC(id, "ID string for MPU-401 device.");
 module_param_array(enable, bool, NULL, 0444);
 MODULE_PARM_DESC(enable, "Enable MPU-401 device.");
-#ifdef USE_ACPI_PNP
-module_param_array(acpipnp, bool, NULL, 0444);
-MODULE_PARM_DESC(acpipnp, "ACPI PnP detection for MPU-401 device.");
+#ifdef CONFIG_PNP
+module_param_array(pnp, bool, NULL, 0444);
+MODULE_PARM_DESC(pnp, "PnP detection for MPU-401 device.");
 #endif
 module_param_array(port, long, NULL, 0444);
 MODULE_PARM_DESC(port, "Port # for MPU-401 device.");
 module_param_array(irq, int, NULL, 0444);
 MODULE_PARM_DESC(irq, "IRQ # for MPU-401 device.");
 
-#ifndef CONFIG_ACPI_BUS
-struct acpi_device;
-#endif
-
 static snd_card_t *snd_mpu401_legacy_cards[SNDRV_CARDS] = SNDRV_DEFAULT_PTR;
-static int cards;
-
-#ifdef USE_ACPI_PNP
-
-static int acpi_driver_registered;
-
-struct mpu401_resources {
-	unsigned long port;
-	int irq;
-};
+static int pnp_registered = 0;
 
-static acpi_status __devinit snd_mpu401_acpi_resource(struct acpi_resource *res,
-						      void *data)
-{
-	struct mpu401_resources *resources = (struct mpu401_resources *)data;
-
-	if (res->id == ACPI_RSTYPE_IRQ) {
-		if (res->data.irq.number_of_interrupts > 0) {
-			resources->irq = acpi_register_gsi(res->data.irq.interrupts[0],
-							   res->data.irq.edge_level,
-							   res->data.irq.active_high_low);
-		}
-	} else if (res->id == ACPI_RSTYPE_IO) {
-		if (res->data.io.range_length >= 2) {
-			resources->port = res->data.io.min_base_address;
-		}
-	}
-	return AE_OK;
-}
-
-static int __devinit snd_mpu401_acpi_pnp(int dev, struct acpi_device *device)
-{
-	struct mpu401_resources res;
-	acpi_status status;
-
-	res.port = SNDRV_AUTO_PORT;
-	res.irq = SNDRV_AUTO_IRQ;
-	status = acpi_walk_resources(device->handle, METHOD_NAME__CRS,
-				     snd_mpu401_acpi_resource, &res);
-	if (ACPI_FAILURE(status))
-		return -ENODEV;
-	if (res.port == SNDRV_AUTO_PORT || res.irq == SNDRV_AUTO_IRQ) {
-		snd_printk(KERN_ERR "no port or irq in %s _CRS\n",
-			   acpi_device_bid(device));
-		return -ENODEV;
-	}
-	port[dev] = res.port;
-	irq[dev] = res.irq;
-	return 0;
-}
-
-#endif /* USE_ACPI_PNP */
-
-static int __devinit snd_card_mpu401_probe(int dev, struct acpi_device *device)
+static int snd_mpu401_create(int dev, snd_card_t **rcard)
 {
 	snd_card_t *card;
 	int err;
 
-#ifdef USE_ACPI_PNP
-	if (!device) {
-#endif
-		if (port[dev] == SNDRV_AUTO_PORT) {
-			snd_printk(KERN_ERR "specify port\n");
-			return -EINVAL;
-		}
-		if (irq[dev] == SNDRV_AUTO_IRQ) {
-			snd_printk(KERN_ERR "specify or disable IRQ port\n");
-			return -EINVAL;
-		}
-#ifdef USE_ACPI_PNP
-	}
-#endif
-
-#ifdef USE_ACPI_PNP
-	if (device && (err = snd_mpu401_acpi_pnp(dev, device)) < 0)
-		return err;
-#endif
-
+	*rcard = NULL;
 	card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
 	if (card == NULL)
 		return -ENOMEM;
 	strcpy(card->driver, "MPU-401 UART");
 	strcpy(card->shortname, card->driver);
-	sprintf(card->longname, "%s at 0x%lx, ", card->shortname, port[dev]);
+	sprintf(card->longname, "%s at %#lx, ", card->shortname, port[dev]);
 	if (irq[dev] >= 0) {
-		sprintf(card->longname + strlen(card->longname), "IRQ %d", irq[dev]);
+		sprintf(card->longname + strlen(card->longname), "irq %d", irq[dev]);
 	} else {
 		strcat(card->longname, "polled");
 	}
-#ifdef USE_ACPI_PNP
-	if (device) {
-		strcat(card->longname, ", ACPI id ");
-		strlcat(card->longname, acpi_device_bid(device), sizeof(card->longname));
-	}
-#endif
+
 	if (snd_mpu401_uart_new(card, 0,
 				MPU401_HW_MPU401,
 				port[dev], 0,
@@ -179,89 +89,127 @@
 		snd_card_free(card);
 		return err;
 	}
-#ifdef USE_ACPI_PNP
-	if (device)
-		acpi_driver_data(device) = card;
-	else
-#endif
-		snd_mpu401_legacy_cards[dev] = card;
-	++cards;
+	*rcard = card;
 	return 0;
 }
 
-#ifdef USE_ACPI_PNP
+static int __devinit snd_mpu401_probe(int dev)
+{
+	if (port[dev] == SNDRV_AUTO_PORT) {
+		snd_printk(KERN_ERR "specify port\n");
+		return -EINVAL;
+	}
+	if (irq[dev] == SNDRV_AUTO_IRQ) {
+		snd_printk(KERN_ERR "specify or disable IRQ\n");
+		return -EINVAL;
+	}
+	return snd_mpu401_create(dev, &snd_mpu401_legacy_cards[dev]);
+}
+
+#ifdef CONFIG_PNP
+
+#define IO_EXTENT 2
+
+static struct pnp_device_id snd_mpu401_pnpids[] = {
+	{ .id = "PNPb006" },
+	{ .id = "" }
+};
+
+MODULE_DEVICE_TABLE(pnp, snd_mpu401_pnpids);
+
+static int __init snd_mpu401_pnp(int dev, struct pnp_dev *device,
+				 const struct pnp_device_id *id)
+{
+	if (!pnp_port_valid(device, 0) ||
+	    pnp_port_flags(device, 0) & IORESOURCE_DISABLED) {
+		snd_printk(KERN_ERR "no PnP port\n");
+		return -ENODEV;
+	}
+	if (pnp_port_len(device, 0) < IO_EXTENT) {
+		snd_printk(KERN_ERR "PnP port length is %ld, expected %d\n",
+			   pnp_port_len(device, 0), IO_EXTENT);
+		return -ENODEV;
+	}
+	port[dev] = pnp_port_start(device, 0);
+
+	if (!pnp_irq_valid(device, 0) ||
+	    pnp_irq_flags(device, 0) & IORESOURCE_DISABLED) {
+		snd_printk(KERN_WARNING "no PnP irq, using polling\n");
+		irq[dev] = -1;
+	} else {
+		irq[dev] = pnp_irq(device, 0);
+	}
+	return 0;
+}
 
-static int __devinit snd_mpu401_acpi_add(struct acpi_device *device)
+static int __devinit snd_mpu401_pnp_probe(struct pnp_dev *pnp_dev,
+					  const struct pnp_device_id *id)
 {
 	static int dev;
+	snd_card_t *card;
 	int err;
 
 	for ( ; dev < SNDRV_CARDS; ++dev) {
-		if (!enable[dev] || !acpipnp[dev])
+		if (!enable[dev] || !pnp[dev])
 			continue;
-		err = snd_card_mpu401_probe(dev, device);
+		err = snd_mpu401_pnp(dev, pnp_dev, id);
+		if (err < 0)
+			return err;
+		err = snd_mpu401_create(dev, &card);
 		if (err < 0)
 			return err;
+		snd_card_set_dev(card, &pnp_dev->dev);
+		pnp_set_drvdata(pnp_dev, card);
 		++dev;
 		return 0;
 	}
 	return -ENODEV;
 }
 
-static int __devexit snd_mpu401_acpi_remove(struct acpi_device *device,
-					    int type)
+static void __devexit snd_mpu401_pnp_remove(struct pnp_dev *dev)
 {
-	snd_card_t *card;
-
-	if (!device)
-		return -EINVAL;
-	card = (snd_card_t *)acpi_driver_data(device);
-	if (!card)
-		return -EINVAL;
+	snd_card_t *card = (snd_card_t *) pnp_get_drvdata(dev);
 
 	snd_card_disconnect(card);
 	snd_card_free_in_thread(card);
-	acpi_driver_data(device) = NULL;
-	return 0;
 }
 
-static struct acpi_driver snd_mpu401_acpi_driver = {
-	.name = "MPU-401 Driver",
-	.class = "mpu401",
-	.ids = "PNPB006",
-	.ops = {
-		.add = snd_mpu401_acpi_add,
-		.remove = __devexit_p(snd_mpu401_acpi_remove),
-	},
+static struct pnp_driver snd_mpu401_pnp_driver = {
+	.name = "mpu401",
+	.id_table = snd_mpu401_pnpids,
+	.probe = snd_mpu401_pnp_probe,
+	.remove = __devexit_p(snd_mpu401_pnp_remove),
 };
-
-#endif /* USE_ACPI_PNP */
+#else
+static struct pnp_driver snd_mpu401_pnp_driver;
+#endif
 
 static int __init alsa_card_mpu401_init(void)
 {
-	int dev;
+	int dev, devices = 0;
+	int err;
 
-#ifdef USE_ACPI_PNP
-	if (acpi_bus_register_driver(&snd_mpu401_acpi_driver) >= 0)
-		acpi_driver_registered = 1;
-#endif
 	for (dev = 0; dev < SNDRV_CARDS; dev++) {
 		if (!enable[dev])
 			continue;
-#ifdef USE_ACPI_PNP
-		if (acpipnp[dev] && acpi_driver_registered)
+#ifdef CONFIG_PNP
+		if (pnp[dev])
 			continue;
 #endif
-		snd_card_mpu401_probe(dev, NULL);
+		if (snd_mpu401_probe(dev) >= 0)
+			devices++;
 	}
-	if (!cards) {
+	if ((err = pnp_register_driver(&snd_mpu401_pnp_driver)) >= 0) {
+		pnp_registered = 1;
+		devices += err;
+	}
+
+	if (!devices) {
 #ifdef MODULE
 		printk(KERN_ERR "MPU-401 device not found or device busy\n");
 #endif
-#ifdef USE_ACPI_PNP
-		if (acpi_driver_registered)
-			acpi_bus_unregister_driver(&snd_mpu401_acpi_driver);
-#endif
+		if (pnp_registered)
+			pnp_unregister_driver(&snd_mpu401_pnp_driver);
 		return -ENODEV;
 	}
 	return 0;
@@ -271,10 +219,8 @@
 {
 	int idx;
 
-#ifdef USE_ACPI_PNP
-	if (acpi_driver_registered)
-		acpi_bus_unregister_driver(&snd_mpu401_acpi_driver);
-#endif
+	if (pnp_registered)
+		pnp_unregister_driver(&snd_mpu401_pnp_driver);
 	for (idx = 0; idx < SNDRV_CARDS; idx++)
 		snd_card_free(snd_mpu401_legacy_cards[idx]);
 }
diff -Nru a/sound/drivers/mpu401/mpu401_uart.c b/sound/drivers/mpu401/mpu401_uart.c
--- a/sound/drivers/mpu401/mpu401_uart.c	2005-03-11 12:51:42 -08:00
+++ b/sound/drivers/mpu401/mpu401_uart.c	2005-03-11 12:51:42 -08:00
@@ -92,24 +92,21 @@
 
 static void _snd_mpu401_uart_interrupt(mpu401_t *mpu)
 {
-	spin_lock(&mpu->input_lock);
+	unsigned long flags;
+
+	spin_lock_irqsave(&mpu->input_lock, flags);
 	if (test_bit(MPU401_MODE_BIT_INPUT, &mpu->mode)) {
-		atomic_dec(&mpu->rx_loop);
 		snd_mpu401_uart_input_read(mpu);
-		atomic_inc(&mpu->rx_loop);
 	} else {
 		snd_mpu401_uart_clear_rx(mpu);
 	}
-	spin_unlock(&mpu->input_lock);
+	spin_unlock_irqrestore(&mpu->input_lock, flags);
  	/* ok. for better Tx performance try do some output when input is done */
 	if (test_bit(MPU401_MODE_BIT_OUTPUT, &mpu->mode) &&
 	    test_bit(MPU401_MODE_BIT_OUTPUT_TRIGGER, &mpu->mode)) {
-		if (spin_trylock(&mpu->output_lock)) {
-			atomic_dec(&mpu->tx_loop);
-			snd_mpu401_uart_output_write(mpu);
-			atomic_inc(&mpu->tx_loop);
-			spin_unlock(&mpu->output_lock);
-		}
+		spin_lock_irqsave(&mpu->output_lock, flags);
+		snd_mpu401_uart_output_write(mpu);
+		spin_unlock_irqrestore(&mpu->output_lock, flags);
 	}
 }
 
@@ -137,13 +134,14 @@
  */
 static void snd_mpu401_uart_timer(unsigned long data)
 {
+	unsigned long flags;
 	mpu401_t *mpu = (mpu401_t *)data;
 
-	spin_lock(&mpu->timer_lock);
+	spin_lock_irqsave(&mpu->timer_lock, flags);
 	/*mpu->mode |= MPU401_MODE_TIMER;*/
 	mpu->timer.expires = 1 + jiffies;
 	add_timer(&mpu->timer);
-	spin_unlock(&mpu->timer_lock);
+	spin_unlock_irqrestore(&mpu->timer_lock, flags);
 	if (mpu->rmidi)
 		_snd_mpu401_uart_interrupt(mpu);
 }
@@ -243,7 +241,6 @@
 		snd_mpu401_uart_cmd(mpu, MPU401_ENTER_UART, 1);
 	}
 	mpu->substream_input = substream;
-	atomic_set(&mpu->rx_loop, 1);
 	set_bit(MPU401_MODE_BIT_INPUT, &mpu->mode);
 	return 0;
 }
@@ -261,7 +258,6 @@
 		snd_mpu401_uart_cmd(mpu, MPU401_ENTER_UART, 1);
 	}
 	mpu->substream_output = substream;
-	atomic_set(&mpu->tx_loop, 1);
 	set_bit(MPU401_MODE_BIT_OUTPUT, &mpu->mode);
 	return 0;
 }
@@ -314,16 +310,9 @@
 		}
 		
 		/* read data in advance */
-		/* prevent double enter via rawmidi->event callback */
-		if (atomic_dec_and_test(&mpu->rx_loop)) {
-			local_irq_save(flags);
-			if (spin_trylock(&mpu->input_lock)) {
-				snd_mpu401_uart_input_read(mpu);
-				spin_unlock(&mpu->input_lock);
-			}
-			local_irq_restore(flags);
-		}
-		atomic_inc(&mpu->rx_loop);
+		spin_lock_irqsave(&mpu->input_lock, flags);
+		snd_mpu401_uart_input_read(mpu);
+		spin_unlock_irqrestore(&mpu->input_lock, flags);
 	} else {
 		if (mpu->irq < 0)
 			snd_mpu401_uart_remove_timer(mpu, 1);
@@ -405,16 +394,9 @@
 		snd_mpu401_uart_add_timer(mpu, 0);
 
 		/* output pending data */
-		/* prevent double enter via rawmidi->event callback */
-		if (atomic_dec_and_test(&mpu->tx_loop)) {
-			local_irq_save(flags);
-			if (spin_trylock(&mpu->output_lock)) {
-				snd_mpu401_uart_output_write(mpu);
-				spin_unlock(&mpu->output_lock);
-			}
-			local_irq_restore(flags);
-		}
-		atomic_inc(&mpu->tx_loop);
+		spin_lock_irqsave(&mpu->output_lock, flags);
+		snd_mpu401_uart_output_write(mpu);
+		spin_unlock_irqrestore(&mpu->output_lock, flags);
 	} else {
 		snd_mpu401_uart_remove_timer(mpu, 0);
 		clear_bit(MPU401_MODE_BIT_OUTPUT_TRIGGER, &mpu->mode);
diff -Nru a/sound/drivers/mtpav.c b/sound/drivers/mtpav.c
--- a/sound/drivers/mtpav.c	2005-03-11 12:51:50 -08:00
+++ b/sound/drivers/mtpav.c	2005-03-11 12:51:50 -08:00
@@ -413,10 +413,11 @@
 
 static void snd_mtpav_output_timer(unsigned long data)
 {
+	unsigned long flags;
 	mtpav_t *chip = (mtpav_t *)data;
 	int p;
 
-	spin_lock(&chip->spinlock);
+	spin_lock_irqsave(&chip->spinlock, flags);
 	/* reprogram timer */
 	chip->timer.expires = 1 + jiffies;
 	add_timer(&chip->timer);
@@ -426,7 +427,7 @@
 		if ((portp->mode & MTPAV_MODE_OUTPUT_TRIGGERED) && portp->output)
 			snd_mtpav_output_port_write(portp, portp->output);
 	}
-	spin_unlock(&chip->spinlock);
+	spin_unlock_irqrestore(&chip->spinlock, flags);
 }
 
 /* spinlock held! */
@@ -514,9 +515,7 @@
 
 	portp = &mcrd->ports[mcrd->inmidiport];
 	if (portp->mode & MTPAV_MODE_INPUT_TRIGGERED) {
-		spin_unlock(&mcrd->spinlock);
 		snd_rawmidi_receive(portp->input, &inbyte, 1);
-		spin_lock(&mcrd->spinlock);
 	}
 }
 
@@ -581,12 +580,13 @@
 
 static irqreturn_t snd_mtpav_irqh(int irq, void *dev_id, struct pt_regs *regs)
 {
+	unsigned long flags;
 	mtpav_t *mcard = dev_id;
 
 	//printk("irqh()\n");
-	spin_lock(&mcard->spinlock);
+	spin_lock_irqsave(&mcard->spinlock, flags);
 	snd_mtpav_read_bytes(mcard);
-	spin_unlock(&mcard->spinlock);
+	spin_unlock_irqrestore(&mcard->spinlock, flags);
 	return IRQ_HANDLED;
 }
 
diff -Nru a/sound/drivers/serial-u16550.c b/sound/drivers/serial-u16550.c
--- a/sound/drivers/serial-u16550.c	2005-03-11 12:51:41 -08:00
+++ b/sound/drivers/serial-u16550.c	2005-03-11 12:51:41 -08:00
@@ -232,7 +232,7 @@
 			}
 			else if ((uart->filemode & SERIAL_MODE_INPUT_OPEN) && (uart->midi_input[substream] != NULL)) {
 				snd_rawmidi_receive(uart->midi_input[substream], &c, 1);
-		}
+			}
 		} else if ((uart->filemode & SERIAL_MODE_INPUT_OPEN) && (uart->midi_input[substream] != NULL)) {
 			snd_rawmidi_receive(uart->midi_input[substream], &c, 1);
 		}
@@ -292,30 +292,32 @@
  */
 static irqreturn_t snd_uart16550_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
+	unsigned long flags;
 	snd_uart16550_t *uart;
 
 	uart = (snd_uart16550_t *) dev_id;
-	spin_lock(&uart->open_lock);
+	spin_lock_irqsave(&uart->open_lock, flags);
 	if (uart->filemode == SERIAL_MODE_NOT_OPENED) {
-		spin_unlock(&uart->open_lock);
+		spin_unlock_irqrestore(&uart->open_lock, flags);
 		return IRQ_NONE;
 	}
 	inb(uart->base + UART_IIR);		/* indicate to the UART that the interrupt has been serviced */
 	snd_uart16550_io_loop(uart);
-	spin_unlock(&uart->open_lock);
+	spin_unlock_irqrestore(&uart->open_lock, flags);
 	return IRQ_HANDLED;
 }
 
 /* When the polling mode, this function calls snd_uart16550_io_loop. */
 static void snd_uart16550_buffer_timer(unsigned long data)
 {
+	unsigned long flags;
 	snd_uart16550_t *uart;
 
 	uart = (snd_uart16550_t *)data;
-	spin_lock(&uart->open_lock);
+	spin_lock_irqsave(&uart->open_lock, flags);
 	snd_uart16550_del_timer(uart);
 	snd_uart16550_io_loop(uart);
-	spin_unlock(&uart->open_lock);
+	spin_unlock_irqrestore(&uart->open_lock, flags);
 }
 
 /*
@@ -840,6 +842,16 @@
 	return 0;
 }
 
+static void __init snd_uart16550_substreams(snd_rawmidi_str_t *stream)
+{
+	struct list_head *list;
+
+	list_for_each(list, &stream->substreams) {
+		snd_rawmidi_substream_t *substream = list_entry(list, snd_rawmidi_substream_t, list);
+		sprintf(substream->name, "Serial MIDI %d", substream->number + 1);
+	}
+}
+
 static int __init snd_uart16550_rmidi(snd_uart16550_t *uart, int device, int outs, int ins, snd_rawmidi_t **rmidi)
 {
 	snd_rawmidi_t *rrawmidi;
@@ -849,7 +861,9 @@
 		return err;
 	snd_rawmidi_set_ops(rrawmidi, SNDRV_RAWMIDI_STREAM_INPUT, &snd_uart16550_input);
 	snd_rawmidi_set_ops(rrawmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &snd_uart16550_output);
-	sprintf(rrawmidi->name, "uart16550 MIDI #%d", device);
+	strcpy(rrawmidi->name, "Serial MIDI");
+	snd_uart16550_substreams(&rrawmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT]);
+	snd_uart16550_substreams(&rrawmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT]);
 	rrawmidi->info_flags = SNDRV_RAWMIDI_INFO_OUTPUT |
 			       SNDRV_RAWMIDI_INFO_INPUT |
 			       SNDRV_RAWMIDI_INFO_DUPLEX;
@@ -906,7 +920,7 @@
 		return -ENOMEM;
 
 	strcpy(card->driver, "Serial");
-	strcpy(card->shortname, "Serial midi (uart16550A)");
+	strcpy(card->shortname, "Serial MIDI (UART16550A)");
 
 	if ((err = snd_uart16550_create(card,
 					port[dev],
diff -Nru a/sound/drivers/vx/vx_core.c b/sound/drivers/vx/vx_core.c
--- a/sound/drivers/vx/vx_core.c	2005-03-11 12:51:52 -08:00
+++ b/sound/drivers/vx/vx_core.c	2005-03-11 12:51:52 -08:00
@@ -25,6 +25,7 @@
 #include <linux/slab.h>
 #include <linux/interrupt.h>
 #include <linux/init.h>
+#include <linux/device.h>
 #include <linux/firmware.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
@@ -45,12 +46,10 @@
  */
 void snd_vx_delay(vx_core_t *chip, int xmsec)
 {
-	if (! in_interrupt() && xmsec >= 1000 / HZ) {
-		set_current_state(TASK_UNINTERRUPTIBLE);
-		schedule_timeout((xmsec * HZ + 999) / 1000);
-	} else {
+	if (! in_interrupt() && xmsec >= 1000 / HZ)
+		msleep(xmsec);
+	else
 		mdelay(xmsec);
-	}
 }
 
 /*
@@ -610,6 +609,10 @@
 	static char *uer_type[] = { "Consumer", "Professional", "Not Present" };
 	
 	snd_iprintf(buffer, "%s\n", chip->card->longname);
+	snd_iprintf(buffer, "Xilinx Firmware: %s\n",
+		    chip->chip_status & VX_STAT_XILINX_LOADED ? "Loaded" : "No");
+	snd_iprintf(buffer, "Device Initialized: %s\n",
+		    chip->chip_status & VX_STAT_DEVICE_INIT ? "Yes" : "No");
 	snd_iprintf(buffer, "DSP audio info:");
 	if (chip->audio_info & VX_AUDIO_INFO_REAL_TIME)
 		snd_iprintf(buffer, " realtime");
@@ -718,7 +721,7 @@
 /*
  * suspend
  */
-static int snd_vx_suspend(snd_card_t *card, unsigned int state)
+static int snd_vx_suspend(snd_card_t *card, pm_message_t state)
 {
 	vx_core_t *chip = card->pm_private_data;
 	unsigned int i;
@@ -735,7 +738,7 @@
 /*
  * resume
  */
-static int snd_vx_resume(snd_card_t *card, unsigned int state)
+static int snd_vx_resume(snd_card_t *card)
 {
 	vx_core_t *chip = card->pm_private_data;
 	int i, err;
diff -Nru a/sound/drivers/vx/vx_hwdep.c b/sound/drivers/vx/vx_hwdep.c
--- a/sound/drivers/vx/vx_hwdep.c	2005-03-11 12:51:42 -08:00
+++ b/sound/drivers/vx/vx_hwdep.c	2005-03-11 12:51:42 -08:00
@@ -21,6 +21,7 @@
  */
 
 #include <sound/driver.h>
+#include <linux/device.h>
 #include <linux/firmware.h>
 #include <sound/core.h>
 #include <sound/hwdep.h>
diff -Nru a/sound/i2c/other/Makefile b/sound/i2c/other/Makefile
--- a/sound/i2c/other/Makefile	2005-03-11 12:51:41 -08:00
+++ b/sound/i2c/other/Makefile	2005-03-11 12:51:41 -08:00
@@ -3,6 +3,7 @@
 # Copyright (c) 2003 by Jaroslav Kysela <perex@suse.cz>
 #
 
+snd-ak4114-objs := ak4114.o
 snd-ak4117-objs := ak4117.o
 snd-ak4xxx-adda-objs := ak4xxx-adda.o
 snd-tea575x-tuner-objs := tea575x-tuner.o
@@ -11,4 +12,5 @@
 obj-$(CONFIG_SND_PDAUDIOCF) += snd-ak4117.o
 obj-$(CONFIG_SND_ICE1712) += snd-ak4xxx-adda.o
 obj-$(CONFIG_SND_ICE1724) += snd-ak4xxx-adda.o
+obj-$(CONFIG_SND_ICE1724) += snd-ak4114.o
 obj-$(CONFIG_SND_FM801_TEA575X) += snd-tea575x-tuner.o
diff -Nru a/sound/i2c/other/ak4114.c b/sound/i2c/other/ak4114.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/sound/i2c/other/ak4114.c	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,580 @@
+/*
+ *  Routines for control of the AK4114 via I2C and 4-wire serial interface
+ *  IEC958 (S/PDIF) receiver by Asahi Kasei
+ *  Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ *
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+#include <sound/driver.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <sound/core.h>
+#include <sound/control.h>
+#include <sound/pcm.h>
+#include <sound/ak4114.h>
+#include <sound/asoundef.h>
+
+MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
+MODULE_DESCRIPTION("AK4114 IEC958 (S/PDIF) receiver by Asahi Kasei");
+MODULE_LICENSE("GPL");
+
+#define AK4114_ADDR			0x00 /* fixed address */
+
+static void ak4114_stats(void *);
+
+static void reg_write(ak4114_t *ak4114, unsigned char reg, unsigned char val)
+{
+	ak4114->write(ak4114->private_data, reg, val);
+	if (reg <= AK4114_REG_INT1_MASK)
+		ak4114->regmap[reg] = val;
+	else if (reg >= AK4114_REG_RXCSB0 && reg <= AK4114_REG_TXCSB4)
+		ak4114->txcsb[reg-AK4114_REG_RXCSB0] = val;
+}
+
+static inline unsigned char reg_read(ak4114_t *ak4114, unsigned char reg)
+{
+	return ak4114->read(ak4114->private_data, reg);
+}
+
+#if 0
+static void reg_dump(ak4114_t *ak4114)
+{
+	int i;
+
+	printk("AK4114 REG DUMP:\n");
+	for (i = 0; i < 0x20; i++)
+		printk("reg[%02x] = %02x (%02x)\n", i, reg_read(ak4114, i), i < sizeof(ak4114->regmap) ? ak4114->regmap[i] : 0);
+}
+#endif
+
+static void snd_ak4114_free(ak4114_t *chip)
+{
+	chip->init = 1;	/* don't schedule new work */
+	mb();
+	if (chip->workqueue != NULL) {
+		flush_workqueue(chip->workqueue);
+		destroy_workqueue(chip->workqueue);
+	}
+	kfree(chip);
+}
+
+static int snd_ak4114_dev_free(snd_device_t *device)
+{
+	ak4114_t *chip = device->device_data;
+	snd_ak4114_free(chip);
+	return 0;
+}
+
+int snd_ak4114_create(snd_card_t *card,
+		      ak4114_read_t *read, ak4114_write_t *write,
+		      unsigned char pgm[7], unsigned char txcsb[5],
+		      void *private_data, ak4114_t **r_ak4114)
+{
+	ak4114_t *chip;
+	int err = 0;
+	unsigned char reg;
+	static snd_device_ops_t ops = {
+		.dev_free =     snd_ak4114_dev_free,
+	};
+
+	chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
+	if (chip == NULL)
+		return -ENOMEM;
+	spin_lock_init(&chip->lock);
+	chip->card = card;
+	chip->read = read;
+	chip->write = write;
+	chip->private_data = private_data;
+
+	for (reg = 0; reg < 7; reg++)
+		chip->regmap[reg] = pgm[reg];
+	for (reg = 0; reg < 5; reg++)
+		chip->txcsb[reg] = txcsb[reg];
+
+	chip->workqueue = create_workqueue("snd-ak4114");
+	if (chip->workqueue == NULL) {
+		kfree(chip);
+		return -ENOMEM;
+	}
+
+	snd_ak4114_reinit(chip);
+
+	chip->rcs0 = reg_read(chip, AK4114_REG_RCS0) & ~(AK4114_QINT | AK4114_CINT);
+	chip->rcs1 = reg_read(chip, AK4114_REG_RCS1);
+
+	if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0)
+		goto __fail;
+
+	if (r_ak4114)
+		*r_ak4114 = chip;
+	return 0;
+
+      __fail:
+	snd_ak4114_free(chip);
+	return err < 0 ? err : -EIO;
+}
+
+void snd_ak4114_reg_write(ak4114_t *chip, unsigned char reg, unsigned char mask, unsigned char val)
+{
+	if (reg <= AK4114_REG_INT1_MASK)
+		reg_write(chip, reg, (chip->regmap[reg] & ~mask) | val);
+	else if (reg >= AK4114_REG_TXCSB0 && reg <= AK4114_REG_TXCSB4)
+		reg_write(chip, reg, (chip->txcsb[reg] & ~mask) | val);
+}
+
+void snd_ak4114_reinit(ak4114_t *chip)
+{
+	unsigned char old = chip->regmap[AK4114_REG_PWRDN], reg;
+
+	chip->init = 1;
+	mb();
+	flush_workqueue(chip->workqueue);
+	/* bring the chip to reset state and powerdown state */
+	reg_write(chip, AK4114_REG_PWRDN, old & ~(AK4114_RST|AK4114_PWN));
+	udelay(200);
+	/* release reset, but leave powerdown */
+	reg_write(chip, AK4114_REG_PWRDN, (old | AK4114_RST) & ~AK4114_PWN);
+	udelay(200);
+	for (reg = 1; reg < 7; reg++)
+		reg_write(chip, reg, chip->regmap[reg]);
+	for (reg = 0; reg < 5; reg++)
+		reg_write(chip, reg + AK4114_REG_TXCSB0, chip->txcsb[reg]);
+	/* release powerdown, everything is initialized now */
+	reg_write(chip, AK4114_REG_PWRDN, old | AK4114_RST | AK4114_PWN);
+	/* bring up statistics / event queing */
+	chip->init = 0;
+	INIT_WORK(&chip->work, ak4114_stats, chip);
+	queue_delayed_work(chip->workqueue, &chip->work, 1);
+}
+
+static unsigned int external_rate(unsigned char rcs1)
+{
+	switch (rcs1 & (AK4114_FS0|AK4114_FS1|AK4114_FS2|AK4114_FS3)) {
+	case AK4114_FS_32000HZ: return 32000;
+	case AK4114_FS_44100HZ: return 44100;
+	case AK4114_FS_48000HZ: return 48000;
+	case AK4114_FS_88200HZ: return 88200;
+	case AK4114_FS_96000HZ: return 96000;
+	case AK4114_FS_176400HZ: return 176400;
+	case AK4114_FS_192000HZ: return 192000;
+	default:		return 0;
+	}
+}
+
+static int snd_ak4114_in_error_info(snd_kcontrol_t *kcontrol,
+				    snd_ctl_elem_info_t *uinfo)
+{
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+	uinfo->count = 1;
+	uinfo->value.integer.min = 0;
+	uinfo->value.integer.max = LONG_MAX;
+	return 0;
+}
+
+static int snd_ak4114_in_error_get(snd_kcontrol_t *kcontrol,
+				   snd_ctl_elem_value_t *ucontrol)
+{
+	ak4114_t *chip = snd_kcontrol_chip(kcontrol);
+	long *ptr;
+
+	spin_lock_irq(&chip->lock);
+	ptr = (long *)(((char *)chip) + kcontrol->private_value);
+	ucontrol->value.integer.value[0] = *ptr;
+	*ptr = 0;
+	spin_unlock_irq(&chip->lock);
+	return 0;
+}
+
+static int snd_ak4114_in_bit_info(snd_kcontrol_t *kcontrol,
+				  snd_ctl_elem_info_t *uinfo)
+{
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
+	uinfo->count = 1;
+	uinfo->value.integer.min = 0;
+	uinfo->value.integer.max = 1;
+	return 0;
+}
+
+static int snd_ak4114_in_bit_get(snd_kcontrol_t *kcontrol,
+				 snd_ctl_elem_value_t *ucontrol)
+{
+	ak4114_t *chip = snd_kcontrol_chip(kcontrol);
+	unsigned char reg = kcontrol->private_value & 0xff;
+	unsigned char bit = (kcontrol->private_value >> 8) & 0xff;
+	unsigned char inv = (kcontrol->private_value >> 31) & 1;
+
+	ucontrol->value.integer.value[0] = ((reg_read(chip, reg) & (1 << bit)) ? 1 : 0) ^ inv;
+	return 0;
+}
+
+static int snd_ak4114_rate_info(snd_kcontrol_t *kcontrol,
+				snd_ctl_elem_info_t *uinfo)
+{
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+	uinfo->count = 1;
+	uinfo->value.integer.min = 0;
+	uinfo->value.integer.max = 192000;
+	return 0;
+}
+
+static int snd_ak4114_rate_get(snd_kcontrol_t *kcontrol,
+			       snd_ctl_elem_value_t *ucontrol)
+{
+	ak4114_t *chip = snd_kcontrol_chip(kcontrol);
+
+	ucontrol->value.integer.value[0] = external_rate(reg_read(chip, AK4114_REG_RCS1));
+	return 0;
+}
+
+static int snd_ak4114_spdif_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+{
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
+	uinfo->count = 1;
+	return 0;
+}
+
+static int snd_ak4114_spdif_get(snd_kcontrol_t * kcontrol,
+				snd_ctl_elem_value_t * ucontrol)
+{
+	ak4114_t *chip = snd_kcontrol_chip(kcontrol);
+	unsigned i;
+
+	for (i = 0; i < AK4114_REG_RXCSB_SIZE; i++)
+		ucontrol->value.iec958.status[i] = reg_read(chip, AK4114_REG_RXCSB0 + i);
+	return 0;
+}
+
+static int snd_ak4114_spdif_playback_get(snd_kcontrol_t * kcontrol,
+					 snd_ctl_elem_value_t * ucontrol)
+{
+	ak4114_t *chip = snd_kcontrol_chip(kcontrol);
+	unsigned i;
+
+	for (i = 0; i < AK4114_REG_TXCSB_SIZE; i++)
+		ucontrol->value.iec958.status[i] = chip->txcsb[i];
+	return 0;
+}
+
+static int snd_ak4114_spdif_playback_put(snd_kcontrol_t * kcontrol,
+					 snd_ctl_elem_value_t * ucontrol)
+{
+	ak4114_t *chip = snd_kcontrol_chip(kcontrol);
+	unsigned i;
+
+	for (i = 0; i < AK4114_REG_TXCSB_SIZE; i++)
+		reg_write(chip, AK4114_REG_TXCSB0 + i, ucontrol->value.iec958.status[i]);
+	return 0;
+}
+
+static int snd_ak4114_spdif_mask_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+{
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
+	uinfo->count = 1;
+	return 0;
+}
+
+static int snd_ak4114_spdif_mask_get(snd_kcontrol_t * kcontrol,
+				      snd_ctl_elem_value_t * ucontrol)
+{
+	memset(ucontrol->value.iec958.status, 0xff, AK4114_REG_RXCSB_SIZE);
+	return 0;
+}
+
+static int snd_ak4114_spdif_pinfo(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+{
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+	uinfo->value.integer.min = 0;
+	uinfo->value.integer.max = 0xffff;
+	uinfo->count = 4;
+	return 0;
+}
+
+static int snd_ak4114_spdif_pget(snd_kcontrol_t * kcontrol,
+				 snd_ctl_elem_value_t * ucontrol)
+{
+	ak4114_t *chip = snd_kcontrol_chip(kcontrol);
+	unsigned short tmp;
+
+	ucontrol->value.integer.value[0] = 0xf8f2;
+	ucontrol->value.integer.value[1] = 0x4e1f;
+	tmp = reg_read(chip, AK4114_REG_Pc0) | (reg_read(chip, AK4114_REG_Pc1) << 8);
+	ucontrol->value.integer.value[2] = tmp;
+	tmp = reg_read(chip, AK4114_REG_Pd0) | (reg_read(chip, AK4114_REG_Pd1) << 8);
+	ucontrol->value.integer.value[3] = tmp;
+	return 0;
+}
+
+static int snd_ak4114_spdif_qinfo(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+{
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
+	uinfo->count = AK4114_REG_QSUB_SIZE;
+	return 0;
+}
+
+static int snd_ak4114_spdif_qget(snd_kcontrol_t * kcontrol,
+				 snd_ctl_elem_value_t * ucontrol)
+{
+	ak4114_t *chip = snd_kcontrol_chip(kcontrol);
+	unsigned i;
+
+	for (i = 0; i < AK4114_REG_QSUB_SIZE; i++)
+		ucontrol->value.bytes.data[i] = reg_read(chip, AK4114_REG_QSUB_ADDR + i);
+	return 0;
+}
+
+/* Don't forget to change AK4114_CONTROLS define!!! */
+static snd_kcontrol_new_t snd_ak4114_iec958_controls[] = {
+{
+	.iface =	SNDRV_CTL_ELEM_IFACE_PCM,
+	.name =		"IEC958 Parity Errors",
+	.access =	SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
+	.info =		snd_ak4114_in_error_info,
+	.get =		snd_ak4114_in_error_get,
+	.private_value = offsetof(ak4114_t, parity_errors),
+},
+{
+	.iface =	SNDRV_CTL_ELEM_IFACE_PCM,
+	.name =		"IEC958 V-Bit Errors",
+	.access =	SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
+	.info =		snd_ak4114_in_error_info,
+	.get =		snd_ak4114_in_error_get,
+	.private_value = offsetof(ak4114_t, v_bit_errors),
+},
+{
+	.iface =	SNDRV_CTL_ELEM_IFACE_PCM,
+	.name =		"IEC958 C-CRC Errors",
+	.access =	SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
+	.info =		snd_ak4114_in_error_info,
+	.get =		snd_ak4114_in_error_get,
+	.private_value = offsetof(ak4114_t, ccrc_errors),
+},
+{
+	.iface =	SNDRV_CTL_ELEM_IFACE_PCM,
+	.name =		"IEC958 Q-CRC Errors",
+	.access =	SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
+	.info =		snd_ak4114_in_error_info,
+	.get =		snd_ak4114_in_error_get,
+	.private_value = offsetof(ak4114_t, qcrc_errors),
+},
+{
+	.iface =	SNDRV_CTL_ELEM_IFACE_PCM,
+	.name =		"IEC958 External Rate",
+	.access =	SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
+	.info =		snd_ak4114_rate_info,
+	.get =		snd_ak4114_rate_get,
+},
+{
+	.iface =	SNDRV_CTL_ELEM_IFACE_PCM,
+	.name =		SNDRV_CTL_NAME_IEC958("",PLAYBACK,MASK),
+	.access =	SNDRV_CTL_ELEM_ACCESS_READ,
+	.info =		snd_ak4114_spdif_mask_info,
+	.get =		snd_ak4114_spdif_mask_get,
+},
+{
+	.iface =	SNDRV_CTL_ELEM_IFACE_PCM,
+	.name =		SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
+	.access =	SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
+	.info =		snd_ak4114_spdif_info,
+	.get =		snd_ak4114_spdif_playback_get,
+	.put =		snd_ak4114_spdif_playback_put,
+},
+{
+	.iface =	SNDRV_CTL_ELEM_IFACE_PCM,
+	.name =		SNDRV_CTL_NAME_IEC958("",CAPTURE,MASK),
+	.access =	SNDRV_CTL_ELEM_ACCESS_READ,
+	.info =		snd_ak4114_spdif_mask_info,
+	.get =		snd_ak4114_spdif_mask_get,
+},
+{
+	.iface =	SNDRV_CTL_ELEM_IFACE_PCM,
+	.name =		SNDRV_CTL_NAME_IEC958("",CAPTURE,DEFAULT),
+	.access =	SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
+	.info =		snd_ak4114_spdif_info,
+	.get =		snd_ak4114_spdif_get,
+},
+{
+	.iface =	SNDRV_CTL_ELEM_IFACE_PCM,
+	.name =		"IEC958 Preample Capture Default",
+	.access =	SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
+	.info =		snd_ak4114_spdif_pinfo,
+	.get =		snd_ak4114_spdif_pget,
+},
+{
+	.iface =	SNDRV_CTL_ELEM_IFACE_PCM,
+	.name =		"IEC958 Q-subcode Capture Default",
+	.access =	SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
+	.info =		snd_ak4114_spdif_qinfo,
+	.get =		snd_ak4114_spdif_qget,
+},
+{
+	.iface =	SNDRV_CTL_ELEM_IFACE_PCM,
+	.name =		"IEC958 Audio",
+	.access =	SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
+	.info =		snd_ak4114_in_bit_info,
+	.get =		snd_ak4114_in_bit_get,
+	.private_value = (1<<31) | (1<<8) | AK4114_REG_RCS0,
+},
+{
+	.iface =	SNDRV_CTL_ELEM_IFACE_PCM,
+	.name =		"IEC958 Non-PCM Bitstream",
+	.access =	SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
+	.info =		snd_ak4114_in_bit_info,
+	.get =		snd_ak4114_in_bit_get,
+	.private_value = (6<<8) | AK4114_REG_RCS1,
+},
+{
+	.iface =	SNDRV_CTL_ELEM_IFACE_PCM,
+	.name =		"IEC958 DTS Bitstream",
+	.access =	SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
+	.info =		snd_ak4114_in_bit_info,
+	.get =		snd_ak4114_in_bit_get,
+	.private_value = (3<<8) | AK4114_REG_RCS1,
+}
+};
+
+int snd_ak4114_build(ak4114_t *ak4114,
+		     snd_pcm_substream_t *ply_substream,
+		     snd_pcm_substream_t *cap_substream)
+{
+	snd_kcontrol_t *kctl;
+	unsigned int idx;
+	int err;
+
+	snd_assert(cap_substream, return -EINVAL);
+	ak4114->playback_substream = ply_substream;
+	ak4114->capture_substream = cap_substream;
+	for (idx = 0; idx < AK4114_CONTROLS; idx++) {
+		kctl = snd_ctl_new1(&snd_ak4114_iec958_controls[idx], ak4114);
+		if (kctl == NULL)
+			return -ENOMEM;
+		if (!strstr(kctl->id.name, "Playback")) {
+			if (ply_substream == NULL) {
+				snd_ctl_free_one(kctl);
+				ak4114->kctls[idx] = NULL;
+				continue;
+			}
+			kctl->id.device = ply_substream->pcm->device;
+			kctl->id.subdevice = ply_substream->number;
+		} else {
+			kctl->id.device = cap_substream->pcm->device;
+			kctl->id.subdevice = cap_substream->number;
+		}
+		err = snd_ctl_add(ak4114->card, kctl);
+		if (err < 0)
+			return err;
+		ak4114->kctls[idx] = kctl;
+	}
+	return 0;
+}
+
+int snd_ak4114_external_rate(ak4114_t *ak4114)
+{
+	unsigned char rcs1;
+
+	rcs1 = reg_read(ak4114, AK4114_REG_RCS1);
+	return external_rate(rcs1);
+}
+
+int snd_ak4114_check_rate_and_errors(ak4114_t *ak4114, unsigned int flags)
+{
+	snd_pcm_runtime_t *runtime = ak4114->capture_substream ? ak4114->capture_substream->runtime : NULL;
+	unsigned long _flags;
+	int res = 0;
+	unsigned char rcs0, rcs1;
+	unsigned char c0, c1;
+
+	rcs1 = reg_read(ak4114, AK4114_REG_RCS1);
+	if (flags & AK4114_CHECK_NO_STAT)
+		goto __rate;
+	rcs0 = reg_read(ak4114, AK4114_REG_RCS0);
+	spin_lock_irqsave(&ak4114->lock, _flags);
+	if (rcs0 & AK4114_PAR)
+		ak4114->parity_errors++;
+	if (rcs1 & AK4114_V)
+		ak4114->v_bit_errors++;
+	if (rcs1 & AK4114_CCRC)
+		ak4114->ccrc_errors++;
+	if (rcs1 & AK4114_QCRC)
+		ak4114->qcrc_errors++;
+	c0 = (ak4114->rcs0 & (AK4114_QINT | AK4114_CINT | AK4114_PEM | AK4114_AUDION | AK4114_AUTO | AK4114_UNLCK)) ^
+                     (rcs0 & (AK4114_QINT | AK4114_CINT | AK4114_PEM | AK4114_AUDION | AK4114_AUTO | AK4114_UNLCK));
+	c1 = (ak4114->rcs1 & 0xf0) ^ (rcs1 & 0xf0);
+	ak4114->rcs0 = rcs0 & ~(AK4114_QINT | AK4114_CINT);
+	ak4114->rcs1 = rcs1;
+	spin_unlock_irqrestore(&ak4114->lock, _flags);
+
+	if (rcs0 & AK4114_PAR)
+		snd_ctl_notify(ak4114->card, SNDRV_CTL_EVENT_MASK_VALUE, &ak4114->kctls[0]->id);
+	if (rcs0 & AK4114_V)
+		snd_ctl_notify(ak4114->card, SNDRV_CTL_EVENT_MASK_VALUE, &ak4114->kctls[1]->id);
+	if (rcs1 & AK4114_CCRC)
+		snd_ctl_notify(ak4114->card, SNDRV_CTL_EVENT_MASK_VALUE, &ak4114->kctls[2]->id);
+	if (rcs1 & AK4114_QCRC)
+		snd_ctl_notify(ak4114->card, SNDRV_CTL_EVENT_MASK_VALUE, &ak4114->kctls[3]->id);
+
+	/* rate change */
+	if (c1 & 0xf0)
+		snd_ctl_notify(ak4114->card, SNDRV_CTL_EVENT_MASK_VALUE, &ak4114->kctls[4]->id);
+
+	if ((c0 & AK4114_PEM) | (c0 & AK4114_CINT))
+		snd_ctl_notify(ak4114->card, SNDRV_CTL_EVENT_MASK_VALUE, &ak4114->kctls[9]->id);
+	if (c0 & AK4114_QINT)
+		snd_ctl_notify(ak4114->card, SNDRV_CTL_EVENT_MASK_VALUE, &ak4114->kctls[10]->id);
+
+	if (c0 & AK4114_AUDION)
+		snd_ctl_notify(ak4114->card, SNDRV_CTL_EVENT_MASK_VALUE, &ak4114->kctls[11]->id);
+	if (c0 & AK4114_AUTO)
+		snd_ctl_notify(ak4114->card, SNDRV_CTL_EVENT_MASK_VALUE, &ak4114->kctls[12]->id);
+	if (c0 & AK4114_DTSCD)
+		snd_ctl_notify(ak4114->card, SNDRV_CTL_EVENT_MASK_VALUE, &ak4114->kctls[13]->id);
+
+	if (ak4114->change_callback && (c0 | c1) != 0)
+		ak4114->change_callback(ak4114, c0, c1);
+
+      __rate:
+	/* compare rate */
+	res = external_rate(rcs1);
+	if (!(flags & AK4114_CHECK_NO_RATE) && runtime && runtime->rate != res) {
+		snd_pcm_stream_lock_irqsave(ak4114->capture_substream, _flags);
+		if (snd_pcm_running(ak4114->capture_substream)) {
+			// printk("rate changed (%i <- %i)\n", runtime->rate, res);
+			snd_pcm_stop(ak4114->capture_substream, SNDRV_PCM_STATE_DRAINING);
+			wake_up(&runtime->sleep);
+			res = 1;
+		}
+		snd_pcm_stream_unlock_irqrestore(ak4114->capture_substream, _flags);
+	}
+	return res;
+}
+
+static void ak4114_stats(void *data)
+{
+	ak4114_t *chip = (ak4114_t *)data;
+
+	if (chip->init)
+		return;
+	snd_ak4114_check_rate_and_errors(chip, 0);
+	queue_delayed_work(chip->workqueue, &chip->work, 1);
+}
+
+EXPORT_SYMBOL(snd_ak4114_create);
+EXPORT_SYMBOL(snd_ak4114_reg_write);
+EXPORT_SYMBOL(snd_ak4114_reinit);
+EXPORT_SYMBOL(snd_ak4114_build);
+EXPORT_SYMBOL(snd_ak4114_external_rate);
+EXPORT_SYMBOL(snd_ak4114_check_rate_and_errors);
diff -Nru a/sound/i2c/other/ak4xxx-adda.c b/sound/i2c/other/ak4xxx-adda.c
--- a/sound/i2c/other/ak4xxx-adda.c	2005-03-11 12:51:51 -08:00
+++ b/sound/i2c/other/ak4xxx-adda.c	2005-03-11 12:51:51 -08:00
@@ -1,8 +1,8 @@
 /*
- *   ALSA driver for AK4524 / AK4528 / AK4529 / AK4355 / AK4381
+ *   ALSA driver for AK4524 / AK4528 / AK4529 / AK4355 / AK4358 / AK4381
  *   AD and DA converters
  *
- *	Copyright (c) 2000-2003 Jaroslav Kysela <perex@suse.cz>,
+ *	Copyright (c) 2000-2004 Jaroslav Kysela <perex@suse.cz>,
  *				Takashi Iwai <tiwai@suse.de>
  *
  *   This program is free software; you can redistribute it and/or modify
@@ -84,6 +84,7 @@
 		/* FIXME: needed for ak4529? */
 		break;
 	case SND_AK4355:
+	case SND_AK4358:
 		if (state) {
 			snd_akm4xxx_write(ak, 0, 0x01, 0x02); /* reset and soft-mute */
 			return;
@@ -166,6 +167,24 @@
 		0x01, 0x01, /* 1: un-reset, unmute */
 		0xff, 0xff
 	};
+	static unsigned char inits_ak4358[] = {
+		0x01, 0x02, /* 1: reset and soft-mute */
+		0x00, 0x06, /* 0: mode3(i2s), disable auto-clock detect, disable DZF, sharp roll-off, RSTN#=0 */
+		0x02, 0x0e, /* 2: DA's power up, normal speed, RSTN#=0 */
+		// 0x02, 0x2e, /* quad speed */
+		0x03, 0x01, /* 3: de-emphasis off */
+		0x04, 0x00, /* 4: LOUT1 volume muted */
+		0x05, 0x00, /* 5: ROUT1 volume muted */
+		0x06, 0x00, /* 6: LOUT2 volume muted */
+		0x07, 0x00, /* 7: ROUT2 volume muted */
+		0x08, 0x00, /* 8: LOUT3 volume muted */
+		0x09, 0x00, /* 9: ROUT3 volume muted */
+		0x0b, 0x00, /* b: LOUT4 volume muted */
+		0x0c, 0x00, /* c: ROUT4 volume muted */
+		0x0a, 0x00, /* a: DATT speed=0, ignore DZF */
+		0x01, 0x01, /* 1: un-reset, unmute */
+		0xff, 0xff
+	};
 	static unsigned char inits_ak4381[] = {
 		0x00, 0x0c, /* 0: mode3(i2s), disable auto-clock detect */
 		0x01, 0x02, /* 1: de-emphasis off, normal speed, sharp roll-off, DZF off */
@@ -197,6 +216,10 @@
 		inits = inits_ak4355;
 		num_chips = 1;
 		break;
+	case SND_AK4358:
+		inits = inits_ak4358;
+		num_chips = 1;
+		break;
 	case SND_AK4381:
 		inits = inits_ak4381;
 		num_chips = ak->num_dacs / 2;
@@ -370,6 +393,12 @@
 		case SND_AK4355:
 			ctl.private_value = AK_COMPOSE(0, idx + 4, 0, 255); /* register 4-9, chip #0 only */
 			break;
+		case SND_AK4358:
+			if (idx >= 6)
+				ctl.private_value = AK_COMPOSE(0, idx + 5, 0, 255); /* register 4-9, chip #0 only */
+			else
+				ctl.private_value = AK_COMPOSE(0, idx + 4, 0, 255); /* register 4-9, chip #0 only */
+			break;
 		case SND_AK4381:
 			ctl.private_value = AK_COMPOSE(idx/2, (idx%2) + 3, 0, 255); /* register 3 & 4 */
 			break;
@@ -407,7 +436,7 @@
 		if ((err = snd_ctl_add(ak->card, snd_ctl_new(&ctl, SNDRV_CTL_ELEM_ACCESS_READ|SNDRV_CTL_ELEM_ACCESS_WRITE))) < 0)
 			return err;
 	}
-	if (ak->type == SND_AK4355)
+	if (ak->type == SND_AK4355 || ak->type == SND_AK4358)
 		num_emphs = 1;
 	else
 		num_emphs = ak->num_dacs / 2;
@@ -432,6 +461,7 @@
 			break;
 		}
 		case SND_AK4355:
+		case SND_AK4358:
 			ctl.private_value = AK_COMPOSE(idx, 3, 0, 0);
 			break;
 		case SND_AK4381:
diff -Nru a/sound/i2c/other/tea575x-tuner.c b/sound/i2c/other/tea575x-tuner.c
--- a/sound/i2c/other/tea575x-tuner.c	2005-03-11 12:51:42 -08:00
+++ b/sound/i2c/other/tea575x-tuner.c	2005-03-11 12:51:42 -08:00
@@ -168,6 +168,10 @@
 	}
 }
 
+static void snd_tea575x_release(struct video_device *vfd)
+{
+}
+
 /*
  * initialize all the tea575x chips
  */
@@ -186,6 +190,7 @@
 	strcpy(tea->vd.name, tea->tea5759 ? "TEA5759 radio" : "TEA5757 radio");
 	tea->vd.type = VID_TYPE_TUNER;
 	tea->vd.hardware = VID_HARDWARE_RTRACK;	/* FIXME: assign new number */
+	tea->vd.release = snd_tea575x_release;
 	video_set_drvdata(&tea->vd, tea);
 	tea->vd.fops = &tea->fops;
 	tea->fops.owner = tea->card->module;
diff -Nru a/sound/isa/Kconfig b/sound/isa/Kconfig
--- a/sound/isa/Kconfig	2005-03-11 12:51:51 -08:00
+++ b/sound/isa/Kconfig	2005-03-11 12:51:51 -08:00
@@ -20,6 +20,7 @@
 	tristate "Generic AD1848/CS4248 driver"
 	depends on SND
 	select SND_PCM
+	select SND_GENERIC_PM
 	help
 	  Say Y here to include support for AD1848 (Analog Devices) or
 	  CS4248 (Cirrus Logic - Crystal Semiconductors) chips.
@@ -35,6 +36,7 @@
 	depends on SND
 	select SND_MPU401_UART
 	select SND_PCM
+	select SND_GENERIC_PM
 	help
 	  Say Y here to include support for CS4231 chips from Cirrus
 	  Logic - Crystal Semiconductors.
@@ -48,6 +50,7 @@
 	select SND_OPL3_LIB
 	select SND_MPU401_UART
 	select SND_PCM
+	select SND_GENERIC_PM
 	help
 	  Say Y here to include support for CS4232 chips from Cirrus
 	  Logic - Crystal Semiconductors.
@@ -61,6 +64,7 @@
 	select SND_OPL3_LIB
 	select SND_MPU401_UART
 	select SND_PCM
+	select SND_GENERIC_PM
 	help
 	  Say Y to include support for CS4235,CS4236,CS4237B,CS4238B,
 	  CS4239 chips from Cirrus Logic - Crystal Semiconductors.
@@ -98,6 +102,7 @@
 	select SND_OPL3_LIB
 	select SND_MPU401_UART
 	select SND_PCM
+	select SND_GENERIC_PM
 	help
 	  Say Y here to include support for ESS AudioDrive ES18xx chips.
 
@@ -332,6 +337,7 @@
 	select SND_OPL3_LIB
 	select SND_MPU401_UART
 	select SND_PCM
+	select SND_GENERIC_PM
 	help
 	  Say Y here to include support for Yamaha OPL3-SA2 and OPL3-SA3
 	  chips.
diff -Nru a/sound/isa/ad1848/ad1848_lib.c b/sound/isa/ad1848/ad1848_lib.c
--- a/sound/isa/ad1848/ad1848_lib.c	2005-03-11 12:51:51 -08:00
+++ b/sound/isa/ad1848/ad1848_lib.c	2005-03-11 12:51:51 -08:00
@@ -644,7 +644,7 @@
 }
 
 #ifdef CONFIG_PM
-static int snd_ad1848_suspend(snd_card_t *card, unsigned int state)
+static int snd_ad1848_suspend(snd_card_t *card, pm_message_t state)
 {
 	ad1848_t *chip = card->pm_private_data;
 
@@ -657,7 +657,7 @@
 	return 0;
 }
 
-static int snd_ad1848_resume(snd_card_t *card, unsigned int state)
+static int snd_ad1848_resume(snd_card_t *card)
 {
 	ad1848_t *chip = card->pm_private_data;
 
diff -Nru a/sound/isa/als100.c b/sound/isa/als100.c
--- a/sound/isa/als100.c	2005-03-11 12:51:41 -08:00
+++ b/sound/isa/als100.c	2005-03-11 12:51:41 -08:00
@@ -121,7 +121,7 @@
 		return -ENODEV;
 	}
 	acard->devmpu = pnp_request_card_device(card, id->devs[1].id, acard->dev);
-	acard->devopl = pnp_request_card_device(card, id->devs[2].id, acard->devmpu);
+	acard->devopl = pnp_request_card_device(card, id->devs[2].id, acard->dev);
 
 	pdev = acard->dev;
 
diff -Nru a/sound/isa/cs423x/cs4231_lib.c b/sound/isa/cs423x/cs4231_lib.c
--- a/sound/isa/cs423x/cs4231_lib.c	2005-03-11 12:51:41 -08:00
+++ b/sound/isa/cs423x/cs4231_lib.c	2005-03-11 12:51:41 -08:00
@@ -1394,7 +1394,7 @@
 #endif
 }
 
-static int snd_cs4231_pm_suspend(snd_card_t *card, unsigned int state)
+static int snd_cs4231_pm_suspend(snd_card_t *card, pm_message_t state)
 {
 	cs4231_t *chip = card->pm_private_data;
 	if (chip->suspend)
@@ -1402,7 +1402,7 @@
 	return 0;
 }
 
-static int snd_cs4231_pm_resume(snd_card_t *card, unsigned int state)
+static int snd_cs4231_pm_resume(snd_card_t *card)
 {
 	cs4231_t *chip = card->pm_private_data;
 	if (chip->resume)
diff -Nru a/sound/isa/es18xx.c b/sound/isa/es18xx.c
--- a/sound/isa/es18xx.c	2005-03-11 12:51:42 -08:00
+++ b/sound/isa/es18xx.c	2005-03-11 12:51:42 -08:00
@@ -1612,7 +1612,7 @@
 
 /* Power Management support functions */
 #ifdef CONFIG_PM
-static int snd_es18xx_suspend(snd_card_t *card, unsigned int state)
+static int snd_es18xx_suspend(snd_card_t *card, pm_message_t state)
 {
 	es18xx_t *chip = card->pm_private_data;
 
@@ -1627,7 +1627,7 @@
 	return 0;
 }
 
-static int snd_es18xx_resume(snd_card_t *card, unsigned int state)
+static int snd_es18xx_resume(snd_card_t *card)
 {
 	es18xx_t *chip = card->pm_private_data;
 
diff -Nru a/sound/isa/gus/gus_lfo.c b/sound/isa/gus/gus_lfo.c
--- a/sound/isa/gus/gus_lfo.c	2005-03-11 12:51:51 -08:00
+++ /dev/null	Wed Dec 31 16:00:00 196900
@@ -1,429 +0,0 @@
-/*
- *  Copyright (c) by Jaroslav Kysela <perex@suse.cz>
- *  Routines for control of LFO generators (tremolo & vibrato) for
- *  GF1/InterWave chips...
- *
- *
- *   This program is free software; you can redistribute it and/or modify
- *   it under the terms of the GNU General Public License as published by
- *   the Free Software Foundation; either version 2 of the License, or
- *   (at your option) any later version.
- *
- *   This program is distributed in the hope that it will be useful,
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *   GNU General Public License for more details.
- *
- *   You should have received a copy of the GNU General Public License
- *   along with this program; if not, write to the Free Software
- *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
- *
- */
-
-#include <sound/driver.h>
-#include <sound/core.h>
-#include <sound/gus.h>
-
-/*
- *  called by engine routines
- */
-
-static signed char snd_gf1_lfo_compute_value(snd_gus_card_t * gus,
-					     unsigned char *ptr)
-{
-	unsigned int twaveinc, depth_delta;
-	signed int result;
-	unsigned short control, twave, depth, depth_final;
-	unsigned char *ptr1;
-
-	control = *(unsigned short *) (ptr + 0x00);
-	ptr1 = ptr + ((control & 0x4000) >> 12);
-	/* 1. add TWAVEINC to TWAVE and write the result back */
-	/* LFO update rate is 689Hz, effect timer is in ms */
-	if (gus->gf1.timer_slave)
-		twaveinc = (689 * gus->gf1.timer_master_gus->gf1.effect_timer) / 1000;
-	else
-		twaveinc = (689 * gus->gf1.effect_timer) / 1000;
-	if (!twaveinc)
-		twaveinc++;
-#if 0
-	printk("twaveinc = 0x%x, effect_timer = %i\n", twaveinc, gus->gf1.effect_timer);
-#endif
-
-	depth = *(unsigned short *) (ptr1 + 0x0a);
-	depth_final = *(unsigned char *) (ptr + 0x02) << 5;
-	if (depth != depth_final) {
-		depth_delta = ((twaveinc * *(ptr + 0x03)) + *(unsigned short *) (ptr + 0x04));
-		*(unsigned short *) (ptr + 0x04) = depth_delta % 8000;
-		depth_delta /= 8000;
-		if (depth < depth_final) {
-			if (depth + depth_delta > depth_final)
-				depth = depth_final;
-			else
-				depth += depth_delta;
-		}
-		if (depth > depth_final) {
-			if (depth - depth_delta < depth_final)
-				depth = depth_final;
-			else
-				depth -= depth_delta;
-		}
-		*(unsigned short *) (ptr1 + 0x0a) = depth;
-	}
-	twaveinc *= (unsigned int) control & 0x7ff;
-	twaveinc += *(unsigned short *) (ptr + 0x06);
-	*(unsigned short *) (ptr + 0x06) = twaveinc % 1000;
-
-	twave = *(unsigned short *) (ptr1 + 0x08);
-	twave += (unsigned short) (twaveinc / (unsigned int) 1000);
-	*(unsigned short *) (ptr1 + 0x08) = twave;
-
-	if (!(control & 0x2000)) {
-		/* 2. if shift is low */
-		if (twave & 0x4000) {	/* bit 14 high -> invert TWAVE 13-0 */
-			twave ^= 0x3fff;
-			twave &= ~0x4000;
-		}
-		/* TWAVE bit 15 is exclusive or'd with the invert bit (12) */
-		twave ^= (control & 0x1000) << 3;
-	} else {
-		/* 2. if shift is high */
-		if (twave & 0x8000)	/* bit 15 high -> invert TWAVE 14-0 */
-			twave ^= 0x7fff;
-		/* the invert bit (12) is used as sign bit */
-		if (control & 0x1000)
-			twave |= 0x8000;
-		else
-			twave &= ~0x8000;
-	}
-	/* 3. multiply the 14-bit LFO waveform magnitude by 13-bit DEPTH */
-#if 0
-	printk("c=0x%x,tw=0x%x,to=0x%x,d=0x%x,df=0x%x,di=0x%x,r=0x%x,r1=%i\n",
-	       control, twave,
-	       *(unsigned short *) (ptr1 + 0x08),
-	       depth, depth_final, *(ptr + 0x03),
-	     (twave & 0x7fff) * depth, ((twave & 0x7fff) * depth) >> 21);
-#endif
-	result = (twave & 0x7fff) * depth;
-	if (result) {
-		/* shift */
-		result >>= 21;
-		result &= 0x3f;
-	}
-	/* add sign */
-	if (twave & 0x8000)
-		result = -result;
-#if 0
-	printk("lfo final value = %i\n", result);
-#endif
-	return result;
-}
-
-static void snd_gf1_lfo_register_setup(snd_gus_card_t * gus,
-				       snd_gf1_voice_t * voice,
-				       int lfo_type)
-{
-	unsigned long flags;
-
-	if (gus->gf1.enh_mode) {
-		CLI(&flags);
-		gf1_select_voice(gus, voice->number);
-		if (lfo_type & 1) {
-			snd_gf1_write8(gus, GF1_VB_FREQUENCY_LFO, voice->lfo_fc);
-			voice->lfo_fc = 0;
-		}
-		if (lfo_type & 2) {
-			snd_gf1_write8(gus, GF1_VB_VOLUME_LFO, voice->lfo_volume);
-			voice->lfo_volume = 0;
-		}
-		STI(&flags);
-	} else {
-		/*
-		 * ok.. with old GF1 chip can be only vibrato emulated...
-		 * volume register can be in volume ramp state, so tremolo isn't simple..
-		 */
-		if (!(lfo_type & 1))
-			return;
-#if 0
-		if (voice->lfo_fc)
-			printk("setup - %i = %i\n", voice->number, voice->lfo_fc);
-#endif
-		CLI(&flags);
-		gf1_select_voice(gus, voice->number);
-		snd_gf1_write16(gus, GF1_VW_FREQUENCY, voice->fc_register + voice->lfo_fc);
-		STI(&flags);
-	}
-}
-
-void snd_gf1_lfo_effect_interrupt(snd_gus_card_t * gus, snd_gf1_voice_t * voice)
-{
-	unsigned char *ptr;
-
-#if 0
-	if (voice->number != 0)
-		return;
-#endif
-	ptr = gus->gf1.lfos + ((voice->number) << 5);
-	/* 1. vibrato */
-	if (*(unsigned short *) (ptr + 0x00) & 0x8000)
-		voice->lfo_fc = snd_gf1_lfo_compute_value(gus, ptr);
-	/* 2. tremolo */
-	ptr += 16;
-	if (*(unsigned short *) (ptr + 0x00) & 0x8000)
-		voice->lfo_volume = snd_gf1_lfo_compute_value(gus, ptr);
-	/* 3. register setup */
-	snd_gf1_lfo_register_setup(gus, voice, 3);
-}
-
-/*
-
- */
-
-void snd_gf1_lfo_init(snd_gus_card_t * gus)
-{
-	if (gus->gf1.hw_lfo) {
-		snd_gf1_i_write16(gus, GF1_GW_LFO_BASE, 0x0000);
-		snd_gf1_dram_setmem(gus, 0, 0x0000, 1024);
-		/* now enable LFO */
-		snd_gf1_i_write8(gus, GF1_GB_GLOBAL_MODE, snd_gf1_i_look8(gus, GF1_GB_GLOBAL_MODE) | 0x02);
-	}
-	if (gus->gf1.sw_lfo) {
-#if 1
-		gus->gf1.lfos = snd_calloc(1024);
-		if (!gus->gf1.lfos)
-#endif
-			gus->gf1.sw_lfo = 0;
-	}
-}
-
-void snd_gf1_lfo_done(snd_gus_card_t * gus)
-{
-	if (gus->gf1.sw_lfo) {
-		if (gus->gf1.lfos) {
-			snd_gf1_free(gus->gf1.lfos, 1024);
-			gus->gf1.lfos = NULL;
-		}
-	}
-}
-
-void snd_gf1_lfo_program(snd_gus_card_t * gus, int voice, int lfo_type,
-                         struct ULTRA_STRU_IW_LFO_PROGRAM *program)
-{
-	unsigned int lfo_addr, wave_select;
-
-	wave_select = (program->freq_and_control & 0x4000) >> 12;
-	lfo_addr = (voice << 5) | (lfo_type << 4);
-	if (gus->gf1.hw_lfo) {
-#if 0
-		printk("LMCI = 0x%x\n", snd_gf1_i_look8(gus, 0x53));
-		printk("lfo_program: lfo_addr=0x%x,wave_sel=0x%x,fac=0x%x,df=0x%x,di=0x%x,twave=0x%x,depth=0x%x\n",
-		       lfo_addr, wave_select,
-		       program->freq_and_control,
-		       program->depth_final,
-		       program->depth_inc,
-		       program->twave,
-		       program->depth);
-#endif
-		snd_gf1_poke(gus, lfo_addr + 0x02, program->depth_final);
-		snd_gf1_poke(gus, lfo_addr + 0x03, program->depth_inc);
-		snd_gf1_pokew(gus, lfo_addr + 0x08 + wave_select, program->twave);
-		snd_gf1_pokew(gus, lfo_addr + 0x0a + wave_select, program->depth);
-		snd_gf1_pokew(gus, lfo_addr + 0x00, program->freq_and_control);
-#if 0
-		{
-			int i = 0;
-			for (i = 0; i < 16; i++)
-				printk("%02x:", snd_gf1_peek(gus, lfo_addr + i));
-			printk("\n");
-		}
-#endif
-	}
-	if (gus->gf1.sw_lfo) {
-		unsigned char *ptr = gus->gf1.lfos + lfo_addr;
-
-		*(ptr + 0x02) = program->depth_final;
-		*(ptr + 0x03) = program->depth_inc;
-		*(unsigned short *) (ptr + 0x08 + wave_select) = program->twave;
-		*(unsigned short *) (ptr + 0x0a + wave_select) = program->depth;
-		*(unsigned short *) (ptr + 0x00) = program->freq_and_control;
-	}
-}
-
-void snd_gf1_lfo_enable(snd_gus_card_t * gus, int voice, int lfo_type)
-{
-	unsigned int lfo_addr;
-
-	lfo_addr = (voice << 5) | (lfo_type << 4);
-	if (gus->gf1.hw_lfo)
-		snd_gf1_pokew(gus, lfo_addr + 0x00, snd_gf1_peekw(gus, lfo_addr + 0x00) | 0x8000);
-	if (gus->gf1.sw_lfo) {
-		unsigned char *ptr = gus->gf1.lfos + lfo_addr;
-
-		*(unsigned short *) (ptr + 0x00) |= 0x8000;
-	}
-}
-
-void snd_gf1_lfo_disable(snd_gus_card_t * gus, int voice, int lfo_type)
-{
-	unsigned int lfo_addr;
-
-	lfo_addr = (voice << 5) | (lfo_type << 4);
-	if (gus->gf1.hw_lfo)
-		snd_gf1_pokew(gus, lfo_addr + 0x00,
-				snd_gf1_peekw(gus, lfo_addr + 0x00) & ~0x8000);
-	if (gus->gf1.sw_lfo) {
-		unsigned char *ptr = gus->gf1.lfos + lfo_addr;
-
-		*(unsigned short *) (ptr + 0x00) &= ~0x8000;
-	}
-}
-
-void snd_gf1_lfo_change_freq(snd_gus_card_t * gus, int voice,
-		             int lfo_type, int freq)
-{
-	unsigned int lfo_addr;
-
-	lfo_addr = (voice << 5) | (lfo_type << 4);
-	if (gus->gf1.hw_lfo)
-		snd_gf1_pokew(gus, lfo_addr + 0x00,
-				(snd_gf1_peekw(gus, lfo_addr + 0x00) & ~0x7ff) | (freq & 0x7ff));
-	if (gus->gf1.sw_lfo) {
-		unsigned long flags;
-		unsigned char *ptr = gus->gf1.lfos + lfo_addr;
-
-		CLI(&flags);
-		*(unsigned short *) (ptr + 0x00) &= ~0x7ff;
-		*(unsigned short *) (ptr + 0x00) |= freq & 0x7ff;
-		STI(&flags);
-	}
-}
-
-void snd_gf1_lfo_change_depth(snd_gus_card_t * gus, int voice,
-			      int lfo_type, int depth)
-{
-	unsigned long flags;
-	unsigned int lfo_addr;
-	unsigned short control = 0;
-	unsigned char *ptr;
-
-	lfo_addr = (voice << 5) | (lfo_type << 4);
-	ptr = gus->gf1.lfos + lfo_addr;
-	if (gus->gf1.hw_lfo)
-		control = snd_gf1_peekw(gus, lfo_addr + 0x00);
-	if (gus->gf1.sw_lfo)
-		control = *(unsigned short *) (ptr + 0x00);
-	if (depth < 0) {
-		control |= 0x1000;
-		depth = -depth;
-	} else
-		control &= ~0x1000;
-	if (gus->gf1.hw_lfo) {
-		CLI(&flags);
-		snd_gf1_poke(gus, lfo_addr + 0x02, (unsigned char) depth);
-		snd_gf1_pokew(gus, lfo_addr + 0x0a + ((control & 0x4000) >> 12), depth << 5);
-		snd_gf1_pokew(gus, lfo_addr + 0x00, control);
-		STI(&flags);
-	}
-	if (gus->gf1.sw_lfo) {
-		unsigned char *ptr = gus->gf1.lfos + lfo_addr;
-
-		CLI(&flags);
-		*(ptr + 0x02) = (unsigned char) depth;
-		*(unsigned short *) (ptr + 0x0a + ((control & 0x4000) >> 12)) = depth << 5;
-		*(unsigned short *) (ptr + 0x00) = control;
-		STI(&flags);
-	}
-}
-
-void snd_gf1_lfo_setup(snd_gus_card_t * gus, int voice, int lfo_type,
-		       int freq, int current_depth, int depth, int sweep,
-		       int shape)
-{
-	struct ULTRA_STRU_IW_LFO_PROGRAM program;
-
-	program.freq_and_control = 0x8000 | (freq & 0x7ff);
-	if (shape & ULTRA_STRU_IW_LFO_SHAPE_POSTRIANGLE)
-		program.freq_and_control |= 0x2000;
-	if (depth < 0) {
-		program.freq_and_control |= 0x1000;
-		depth = -depth;
-	}
-	program.twave = 0;
-	program.depth = current_depth;
-	program.depth_final = depth;
-	if (sweep) {
-		program.depth_inc = (unsigned char) (((int) ((depth << 5) - current_depth) << 9) / (sweep * 4410L));
-		if (!program.depth_inc)
-			program.depth_inc++;
-	} else
-		program.depth = (unsigned short) (depth << 5);
-	snd_gf1_lfo_program(gus, voice, lfo_type, &program);
-}
-
-void snd_gf1_lfo_shutdown(snd_gus_card_t * gus, int voice, int lfo_type)
-{
-	unsigned long flags;
-	unsigned int lfo_addr;
-
-	lfo_addr = (voice << 5) | (lfo_type << 4);
-	if (gus->gf1.hw_lfo) {
-		snd_gf1_pokew(gus, lfo_addr + 0x00, 0x0000);
-		CLI(&flags);
-		gf1_select_voice(gus, voice);
-		snd_gf1_write8(gus, lfo_type == ULTRA_LFO_VIBRATO ? GF1_VB_FREQUENCY_LFO : GF1_VB_VOLUME_LFO, 0);
-		STI(&flags);
-	}
-	if (gus->gf1.sw_lfo) {
-		unsigned char *ptr = gus->gf1.lfos + lfo_addr;
-		snd_gf1_voice_t *pvoice;
-
-		*(unsigned short *) (ptr + 0x00) = 0;
-		*(unsigned short *) (ptr + 0x04) = 0;
-		*(unsigned short *) (ptr + 0x06) = 0;
-		if (gus->gf1.syn_voices) {
-			pvoice = gus->gf1.syn_voices + voice;
-			if (lfo_type == ULTRA_LFO_VIBRATO)
-				pvoice->lfo_fc = 0;
-			else
-				pvoice->lfo_volume = 0;
-			snd_gf1_lfo_register_setup(gus, pvoice, lfo_type == ULTRA_LFO_VIBRATO ? 1 : 2);
-		} else if (gus->gf1.enh_mode) {
-			CLI(&flags);
-			gf1_select_voice(gus, voice);
-			snd_gf1_write8(gus, lfo_type == ULTRA_LFO_VIBRATO ? GF1_VB_FREQUENCY_LFO : GF1_VB_VOLUME_LFO, 0);
-			STI(&flags);
-		}
-	}
-}
-
-void snd_gf1_lfo_command(snd_gus_card_t * gus, int voice, unsigned char *data)
-{
-	int lfo_type;
-	int lfo_command;
-	int temp1, temp2;
-
-	lfo_type = *data >> 7;
-	lfo_command = *data & 0x7f;
-	switch (lfo_command) {
-	case ULTRA_LFO_SETUP:	/* setup */
-		temp1 = snd_gf1_get_word(data, 2);
-		temp2 = snd_gf1_get_word(data, 4);
-		snd_gf1_lfo_setup(gus, voice, lfo_type, temp1 & 0x7ff, 0, temp2 > 255 ? 255 : temp2, snd_gf1_get_byte(data, 1), (temp1 & 0x2000) >> 13);
-		break;
-	case ULTRA_LFO_FREQ:	/* freq */
-		snd_gf1_lfo_change_depth(gus, voice, lfo_type, snd_gf1_get_word(data, 2));
-		break;
-	case ULTRA_LFO_DEPTH:	/* depth */
-		snd_gf1_lfo_change_freq(gus, voice, lfo_type, snd_gf1_get_word(data, 2));
-		break;
-	case ULTRA_LFO_ENABLE:	/* enable */
-		snd_gf1_lfo_enable(gus, voice, lfo_type);
-		break;
-	case ULTRA_LFO_DISABLE:	/* disable */
-		snd_gf1_lfo_disable(gus, voice, lfo_type);
-		break;
-	case ULTRA_LFO_SHUTDOWN:	/* shutdown */
-		snd_gf1_lfo_shutdown(gus, voice, lfo_type);
-		break;
-	}
-}
diff -Nru a/sound/isa/gus/gus_pcm.c b/sound/isa/gus/gus_pcm.c
--- a/sound/isa/gus/gus_pcm.c	2005-03-11 12:51:42 -08:00
+++ b/sound/isa/gus/gus_pcm.c	2005-03-11 12:51:42 -08:00
@@ -333,6 +333,7 @@
 			}
 		}
 		if (count > 0 && !in_interrupt()) {
+			set_current_state(TASK_INTERRUPTIBLE);
 			schedule_timeout(1);
 			if (signal_pending(current))
 				return -EAGAIN;
@@ -696,16 +697,10 @@
 	snd_gus_card_t *gus = snd_pcm_substream_chip(substream);
 	snd_pcm_runtime_t *runtime = substream->runtime;
 	gus_pcm_private_t *pcmp = runtime->private_data;
-	unsigned long jiffies_old;
+	
+	if (!wait_event_timeout(pcmp->sleep, (atomic_read(&pcmp->dma_count) <= 0), 2*HZ))
+		snd_printk("gf1 pcm - serious DMA problem\n");
 
-	jiffies_old = jiffies;
-	while (atomic_read(&pcmp->dma_count) > 0) {
-		interruptible_sleep_on_timeout(&pcmp->sleep, 1);
-		if ((signed long)(jiffies - jiffies_old) > 2*HZ) {
-			snd_printk("gf1 pcm - serious DMA problem\n");
-			break;
-		}
-	}
 	snd_gf1_dma_done(gus);	
 	return 0;
 }
diff -Nru a/sound/isa/gus/gus_reset.c b/sound/isa/gus/gus_reset.c
--- a/sound/isa/gus/gus_reset.c	2005-03-11 12:51:41 -08:00
+++ b/sound/isa/gus/gus_reset.c	2005-03-11 12:51:41 -08:00
@@ -207,7 +207,6 @@
 	unsigned long flags;
 	short i, ramp_ok;
 	unsigned short ramp_end;
-	long time;
 
 	if (!in_interrupt()) {	/* this can't be done in interrupt */
 		for (i = v_min, ramp_ok = 0; i <= v_max; i++) {
@@ -227,11 +226,7 @@
 			}
 			spin_unlock_irqrestore(&gus->reg_lock, flags);
 		}
-		time = HZ / 20;
-		while (time > 0 && !signal_pending(current)) {
-			set_current_state(TASK_INTERRUPTIBLE);
-			time = schedule_timeout(time);
-		}
+		msleep_interruptible(50);
 	}
 	snd_gf1_clear_voices(gus, v_min, v_max);
 }
diff -Nru a/sound/isa/gus/interwave.c b/sound/isa/gus/interwave.c
--- a/sound/isa/gus/interwave.c	2005-03-11 12:51:46 -08:00
+++ b/sound/isa/gus/interwave.c	2005-03-11 12:51:46 -08:00
@@ -79,8 +79,10 @@
 MODULE_PARM_DESC(id, "ID string for InterWave soundcard.");
 module_param_array(enable, bool, NULL, 0444);
 MODULE_PARM_DESC(enable, "Enable InterWave soundcard.");
+#ifdef CONFIG_PNP
 module_param_array(isapnp, bool, NULL, 0444);
 MODULE_PARM_DESC(isapnp, "ISA PnP detection for specified soundcard.");
+#endif
 module_param_array(port, long, NULL, 0444);
 MODULE_PARM_DESC(port, "Port # for InterWave driver.");
 #ifdef SNDRV_STB
diff -Nru a/sound/isa/opl3sa2.c b/sound/isa/opl3sa2.c
--- a/sound/isa/opl3sa2.c	2005-03-11 12:51:51 -08:00
+++ b/sound/isa/opl3sa2.c	2005-03-11 12:51:51 -08:00
@@ -529,7 +529,7 @@
 
 /* Power Management support functions */
 #ifdef CONFIG_PM
-static int snd_opl3sa2_suspend(snd_card_t *card, unsigned int state)
+static int snd_opl3sa2_suspend(snd_card_t *card, pm_message_t state)
 {
 	opl3sa2_t *chip = card->pm_private_data;
 
@@ -542,7 +542,7 @@
 	return 0;
 }
 
-static int snd_opl3sa2_resume(snd_card_t *card, unsigned int state)
+static int snd_opl3sa2_resume(snd_card_t *card)
 {
 	opl3sa2_t *chip = card->pm_private_data;
 	int i;
@@ -787,7 +787,7 @@
         int res;
 
         for ( ; dev < SNDRV_CARDS; dev++) {
-                if (!enable[dev] && !isapnp[dev])
+                if (!enable[dev] || !isapnp[dev])
                         continue;
                 res = snd_opl3sa2_probe(dev, card, id);
                 if (res < 0)
diff -Nru a/sound/isa/sb/emu8000.c b/sound/isa/sb/emu8000.c
--- a/sound/isa/sb/emu8000.c	2005-03-11 12:51:42 -08:00
+++ b/sound/isa/sb/emu8000.c	2005-03-11 12:51:42 -08:00
@@ -25,6 +25,7 @@
 #include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/ioport.h>
+#include <linux/delay.h>
 #include <sound/core.h>
 #include <sound/emu8000.h>
 #include <sound/emu8000_reg.h>
@@ -355,8 +356,7 @@
 {
 	send_array(emu, init1, ARRAY_SIZE(init1)/4);
 
-	set_current_state(TASK_INTERRUPTIBLE);
-	schedule_timeout((HZ * (44099 + 1024)) / 44100); /* wait for 1024 clocks */
+	msleep((1024 * 1000) / 44100); /* wait for 1024 clocks */
 	send_array(emu, init2, ARRAY_SIZE(init2)/4);
 	send_array(emu, init3, ARRAY_SIZE(init3)/4);
 
diff -Nru a/sound/isa/sb/sb8_midi.c b/sound/isa/sb/sb8_midi.c
--- a/sound/isa/sb/sb8_midi.c	2005-03-11 12:51:41 -08:00
+++ b/sound/isa/sb/sb8_midi.c	2005-03-11 12:51:41 -08:00
@@ -46,20 +46,16 @@
 		inb(SBP(chip, DATA_AVAIL));	/* ack interrupt */
 		return IRQ_NONE;
 	}
+	spin_lock(&chip->midi_input_lock);
 	while (max-- > 0) {
-		spin_lock(&chip->midi_input_lock);
 		if (inb(SBP(chip, DATA_AVAIL)) & 0x80) {
 			byte = inb(SBP(chip, READ));
 			if (chip->open & SB_OPEN_MIDI_INPUT_TRIGGER) {
-				spin_unlock(&chip->midi_input_lock);
 				snd_rawmidi_receive(chip->midi_substream_input, &byte, 1);
-			} else {
-				spin_unlock(&chip->midi_input_lock);
 			}
-		} else {
-			spin_unlock(&chip->midi_input_lock);
 		}
 	}
+	spin_unlock(&chip->midi_input_lock);
 	return IRQ_HANDLED;
 }
 
diff -Nru a/sound/isa/wavefront/wavefront_midi.c b/sound/isa/wavefront/wavefront_midi.c
--- a/sound/isa/wavefront/wavefront_midi.c	2005-03-11 12:51:51 -08:00
+++ b/sound/isa/wavefront/wavefront_midi.c	2005-03-11 12:51:51 -08:00
@@ -413,8 +413,8 @@
 		return;
 	}
 
+	spin_lock_irqsave (&midi->virtual, flags);
 	while (--max) {
-		spin_lock_irqsave (&midi->virtual, flags);
 
 		if (input_avail (midi)) {
 			byte = read_data (midi);
@@ -433,21 +433,17 @@
 			}
 
 			if (substream == NULL) {
-				spin_unlock_irqrestore (&midi->virtual, flags);
 				continue;
 			}
 
 			if (midi->mode[mpu] & MPU401_MODE_INPUT_TRIGGER) {
-				spin_unlock_irqrestore (&midi->virtual, flags);
 				snd_rawmidi_receive(substream, &byte, 1);
-			} else {
-				spin_unlock_irqrestore (&midi->virtual, flags);
 			}
 		} else {
-			spin_unlock_irqrestore (&midi->virtual, flags);
 			break;
 		}
 	} 
+	spin_unlock_irqrestore (&midi->virtual, flags);
 
 	snd_wavefront_midi_output_write(card);
 }
diff -Nru a/sound/isa/wavefront/wavefront_synth.c b/sound/isa/wavefront/wavefront_synth.c
--- a/sound/isa/wavefront/wavefront_synth.c	2005-03-11 12:51:52 -08:00
+++ b/sound/isa/wavefront/wavefront_synth.c	2005-03-11 12:51:52 -08:00
@@ -1751,6 +1751,7 @@
 	outb (val,port);
 	spin_unlock_irq(&dev->irq_lock);
 	while (1) {
+		set_current_state(TASK_INTERRUPTIBLE);
 		if ((timeout = schedule_timeout(timeout)) == 0)
 			return;
 		if (dev->irq_ok)
@@ -1942,7 +1943,7 @@
 	fs = get_fs();
 	set_fs (get_ds());
 
-	if ((fd = sys_open (path, 0, 0)) < 0) {
+	if ((fd = sys_open ((char __user *) path, 0, 0)) < 0) {
 		snd_printk ("Unable to load \"%s\".\n",
 			path);
 		return 1;
@@ -1951,7 +1952,7 @@
 	while (1) {
 		int x;
 
-		if ((x = sys_read (fd, &section_length, sizeof (section_length))) !=
+		if ((x = sys_read (fd, (char __user *) &section_length, sizeof (section_length))) !=
 		    sizeof (section_length)) {
 			snd_printk ("firmware read error.\n");
 			goto failure;
@@ -1967,7 +1968,7 @@
 			goto failure;
 		}
 
-		if (sys_read (fd, section, section_length) != section_length) {
+		if (sys_read (fd, (char __user *) section, section_length) != section_length) {
 			snd_printk ("firmware section "
 				"read error.\n");
 			goto failure;
diff -Nru a/sound/oss/ac97_codec.c b/sound/oss/ac97_codec.c
--- a/sound/oss/ac97_codec.c	2005-03-11 12:51:41 -08:00
+++ b/sound/oss/ac97_codec.c	2005-03-11 12:51:41 -08:00
@@ -71,6 +71,7 @@
 static int wolfson_init04(struct ac97_codec * codec);
 static int wolfson_init05(struct ac97_codec * codec);
 static int wolfson_init11(struct ac97_codec * codec);
+static int wolfson_init13(struct ac97_codec * codec);
 static int tritech_init(struct ac97_codec * codec);
 static int tritech_maestro_init(struct ac97_codec * codec);
 static int sigmatel_9708_init(struct ac97_codec *codec);
@@ -107,6 +108,7 @@
 static struct ac97_ops wolfson_ops04 = { wolfson_init04, NULL, NULL };
 static struct ac97_ops wolfson_ops05 = { wolfson_init05, NULL, NULL };
 static struct ac97_ops wolfson_ops11 = { wolfson_init11, NULL, NULL };
+static struct ac97_ops wolfson_ops13 = { wolfson_init13, NULL, NULL };
 static struct ac97_ops tritech_ops = { tritech_init, NULL, NULL };
 static struct ac97_ops tritech_m_ops = { tritech_maestro_init, NULL, NULL };
 static struct ac97_ops sigmatel_9708_ops = { sigmatel_9708_init, NULL, NULL };
@@ -171,6 +173,7 @@
 	{0x574D4C05, "Wolfson WM9705/WM9710",   &wolfson_ops05},
 	{0x574D4C09, "Wolfson WM9709",		&null_ops},
 	{0x574D4C12, "Wolfson WM9711/9712",	&wolfson_ops11},
+	{0x574D4C13, "Wolfson WM9713",	&wolfson_ops13, AC97_DEFAULT_POWER_OFF},
 	{0x83847600, "SigmaTel STAC????",	&null_ops},
 	{0x83847604, "SigmaTel STAC9701/3/4/5", &null_ops},
 	{0x83847605, "SigmaTel STAC9704",	&null_ops},
@@ -798,6 +801,9 @@
  *	Currently codec_wait is used to wait for AC97 codec
  *	reset to complete. 
  *
+ *     Some codecs will power down when a register reset is
+ *     performed. We now check for such codecs.
+ *
  *	Returns 1 (true) on success, or 0 (false) on failure.
  */
  
@@ -811,34 +817,17 @@
 	struct list_head *l;
 	struct ac97_driver *d;
 	
-	/* probing AC97 codec, AC97 2.0 says that bit 15 of register 0x00 (reset) should 
-	 * be read zero.
-	 *
-	 * FIXME: is the following comment outdated?  -jgarzik 
-	 * Probing of AC97 in this way is not reliable, it is not even SAFE !!
-	 */
-	codec->codec_write(codec, AC97_RESET, 0L);
-
-	/* also according to spec, we wait for codec-ready state */	
+	/* wait for codec-ready state */
 	if (codec->codec_wait)
 		codec->codec_wait(codec);
 	else
 		udelay(10);
 
-	if ((audio = codec->codec_read(codec, AC97_RESET)) & 0x8000) {
-		printk(KERN_ERR "ac97_codec: %s ac97 codec not present\n",
-		       (codec->id & 0x2) ? (codec->id&1 ? "4th" : "Tertiary") 
-		       : (codec->id&1 ? "Secondary":  "Primary"));
-		return 0;
-	}
-
-	/* probe for Modem Codec */
-	codec->modem = ac97_check_modem(codec);
-	codec->name = NULL;
-	codec->codec_ops = &default_ops;
-
+	/* will the codec power down if register reset ? */
 	id1 = codec->codec_read(codec, AC97_VENDOR_ID1);
 	id2 = codec->codec_read(codec, AC97_VENDOR_ID2);
+	codec->name = NULL;
+	codec->codec_ops = &null_ops;
 	for (i = 0; i < ARRAY_SIZE(ac97_codec_ids); i++) {
 		if (ac97_codec_ids[i].id == ((id1 << 16) | id2)) {
 			codec->type = ac97_codec_ids[i].id;
@@ -850,9 +839,34 @@
 	}
 
 	codec->model = (id1 << 16) | id2;
+	if ((codec->flags & AC97_DEFAULT_POWER_OFF) == 0) {
+		/* reset codec and wait for the ready bit before we continue */
+		codec->codec_write(codec, AC97_RESET, 0L);
+		if (codec->codec_wait)
+			codec->codec_wait(codec);
+		else
+			udelay(10);
+	}
+
+	/* probing AC97 codec, AC97 2.0 says that bit 15 of register 0x00 (reset) should
+	 * be read zero.
+	 *
+	 * FIXME: is the following comment outdated?  -jgarzik
+	 * Probing of AC97 in this way is not reliable, it is not even SAFE !!
+	 */
+	if ((audio = codec->codec_read(codec, AC97_RESET)) & 0x8000) {
+		printk(KERN_ERR "ac97_codec: %s ac97 codec not present\n",
+		       (codec->id & 0x2) ? (codec->id&1 ? "4th" : "Tertiary")
+		       : (codec->id&1 ? "Secondary":  "Primary"));
+		return 0;
+	}
 	
+	/* probe for Modem Codec */
+	codec->modem = ac97_check_modem(codec);
+
+	/* enable SPDIF */
 	f = codec->codec_read(codec, AC97_EXTENDED_STATUS);
-	if(f & 4)
+	if((codec->codec_ops == &null_ops) && (f & 4))
 		codec->codec_ops = &default_digital_ops;
 	
 	/* A device which thinks its a modem but isnt */
@@ -921,11 +935,6 @@
 	codec->recmask_io = ac97_recmask_io;
 	codec->mixer_ioctl = ac97_mixer_ioctl;
 
-	/* codec specific initialization for 4-6 channel output or secondary codec stuff */
-	if (codec->codec_ops->init != NULL) {
-		codec->codec_ops->init(codec);
-	}
-
 	/* initialize mixer channel volumes */
 	for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) {
 		struct mixer_defaults *md = &mixer_defaults[i];
@@ -936,6 +945,11 @@
 		ac97_set_mixer(codec, md->mixer, md->value);
 	}
 
+	/* codec specific initialization for 4-6 channel output or secondary codec stuff */
+	if (codec->codec_ops->init != NULL) {
+		codec->codec_ops->init(codec);
+	}
+
 	/*
 	 *	Volume is MUTE only on this device. We have to initialise
 	 *	it but its useless beyond that.
@@ -1088,6 +1102,19 @@
 
 	/* set out3 volume */
 	codec->codec_write(codec, AC97_WM9711_OUT3VOL, 0x0808);
+	return 0;
+}
+
+/* WM9713 */
+static int wolfson_init13(struct ac97_codec * codec)
+{
+	codec->codec_write(codec, AC97_RECORD_GAIN, 0x00a0);
+	codec->codec_write(codec, AC97_POWER_CONTROL, 0x0000);
+	codec->codec_write(codec, AC97_EXTENDED_MODEM_ID, 0xDA00);
+	codec->codec_write(codec, AC97_EXTEND_MODEM_STAT, 0x3810);
+	codec->codec_write(codec, AC97_PHONE_VOL, 0x0808);
+	codec->codec_write(codec, AC97_PCBEEP_VOL, 0x0808);
+
 	return 0;
 }
 
diff -Nru a/sound/oss/cmpci.c b/sound/oss/cmpci.c
--- a/sound/oss/cmpci.c	2005-03-11 12:51:46 -08:00
+++ b/sound/oss/cmpci.c	2005-03-11 12:51:46 -08:00
@@ -426,7 +426,7 @@
 	struct address_info mpu_data;
 #endif
 #ifdef CONFIG_SOUND_CMPCI_JOYSTICK
-	struct gameport gameport;
+	struct gameport *gameport;
 #endif
 
 	int	chip_version;
@@ -468,17 +468,17 @@
 
 static LIST_HEAD(devs);
 
-static	int	mpuio = 0;
-static	int	fmio = 0;
-static	int	joystick = 0;
-static	int	spdif_inverse = 0;
-static	int	spdif_loop = 0;
-static	int	spdif_out = 0;
-static	int	use_line_as_rear = 0;
-static	int	use_line_as_bass = 0;
-static	int	use_mic_as_bass = 0;
-static	int	mic_boost = 0;
-static	int	hw_copy = 0;
+static	int	mpuio;
+static	int	fmio;
+static	int	joystick;
+static	int	spdif_inverse;
+static	int	spdif_loop;
+static	int	spdif_out;
+static	int	use_line_as_rear;
+static	int	use_line_as_bass;
+static	int	use_mic_as_bass;
+static	int	mic_boost;
+static	int	hw_copy;
 module_param(mpuio, int, 0);
 module_param(fmio, int, 0);
 module_param(joystick, bool, 0);
@@ -2925,7 +2925,7 @@
 static struct initvol {
 	int mixch;
 	int vol;
-} initvol[] __initdata = {
+} initvol[] __devinitdata = {
 	{ SOUND_MIXER_WRITE_CD, 0x4f4f },
 	{ SOUND_MIXER_WRITE_LINE, 0x4f4f },
 	{ SOUND_MIXER_WRITE_MIC, 0x4f4f },
@@ -2984,6 +2984,51 @@
 	return ChipVersion;
 }
 
+#ifdef CONFIG_SOUND_CMPCI_JOYSTICK
+static int __devinit cm_create_gameport(struct cm_state *s, int io_port)
+{
+	struct gameport *gp;
+
+	if (!request_region(io_port, CM_EXTENT_GAME, "cmpci GAME")) {
+		printk(KERN_ERR "cmpci: gameport io ports 0x%#x in use\n", io_port);
+		return -EBUSY;
+	}
+
+	if (!(s->gameport = gp = gameport_allocate_port())) {
+		printk(KERN_ERR "cmpci: can not allocate memory for gameport\n");
+		release_region(io_port, CM_EXTENT_GAME);
+		return -ENOMEM;
+	}
+
+	gameport_set_name(gp, "C-Media GP");
+	gameport_set_phys(gp, "pci%s/gameport0", pci_name(s->dev));
+	gp->dev.parent = &s->dev->dev;
+	gp->io = io_port;
+
+	/* enable joystick */
+	maskb(s->iobase + CODEC_CMI_FUNCTRL1, ~0, 0x02);
+
+	gameport_register_port(gp);
+
+	return 0;
+}
+
+static void __devexit cm_free_gameport(struct cm_state *s)
+{
+	if (s->gameport) {
+		int gpio = s->gameport->io;
+
+		gameport_unregister_port(s->gameport);
+		s->gameport = NULL;
+		maskb(s->iobase + CODEC_CMI_FUNCTRL1, ~0x02, 0);
+		release_region(gpio, CM_EXTENT_GAME);
+	}
+}
+#else
+static inline int cm_create_gameport(struct cm_state *s, int io_port) { return -ENOSYS; }
+static inline void cm_free_gameport(struct cm_state *s) { }
+#endif
+
 #define	echo_option(x)\
 if (x) strcat(options, "" #x " ")
 
@@ -3229,22 +3274,11 @@
 	}
 skip_mpu:
 #endif
-#ifdef CONFIG_SOUND_CMPCI_JOYSTICK
-	/* enable joystick */
-	if (joystick) {
-		s->gameport.io = 0x200;
-		if (!request_region(s->gameport.io, CM_EXTENT_GAME, "cmpci GAME")) {
-			printk(KERN_ERR "cmpci: gameport io ports in use\n");
-			s->gameport.io = 0;
-	       	} else {
-			maskb(s->iobase + CODEC_CMI_FUNCTRL1, ~0, 0x02);
-			gameport_register_port(&s->gameport);
-		}
-	} else {
-		maskb(s->iobase + CODEC_CMI_FUNCTRL1, ~0x02, 0);
-		s->gameport.io = 0;
-	}
-#endif
+	/* disable joystick port */
+	maskb(s->iobase + CODEC_CMI_FUNCTRL1, ~0x02, 0);
+	if (joystick)
+		cm_create_gameport(s, 0x200);
+
 	/* store it in the driver field */
 	pci_set_drvdata(pcidev, s);
 	/* put it into driver list */
@@ -3278,13 +3312,9 @@
 
 	if (!s)
 		return;
-#ifdef CONFIG_SOUND_CMPCI_JOYSTICK
-	if (s->gameport.io) {
-		gameport_unregister_port(&s->gameport);
-		release_region(s->gameport.io, CM_EXTENT_GAME);
-		maskb(s->iobase + CODEC_CMI_FUNCTRL1, ~0x02, 0);
-	}
-#endif
+
+	cm_free_gameport(s);
+
 #ifdef CONFIG_SOUND_CMPCI_FM
 	if (s->iosynth) {
 		/* disable FM */
diff -Nru a/sound/oss/cs4281/cs4281m.c b/sound/oss/cs4281/cs4281m.c
--- a/sound/oss/cs4281/cs4281m.c	2005-03-11 12:51:52 -08:00
+++ b/sound/oss/cs4281/cs4281m.c	2005-03-11 12:51:52 -08:00
@@ -4096,7 +4096,7 @@
 static struct initvol {
 	int mixch;
 	int vol;
-} initvol[] __initdata = {
+} initvol[] __devinitdata = {
 
 	{
 	SOUND_MIXER_WRITE_VOLUME, 0x4040}, {
diff -Nru a/sound/oss/dmasound/dac3550a.c b/sound/oss/dmasound/dac3550a.c
--- a/sound/oss/dmasound/dac3550a.c	2005-03-11 12:51:42 -08:00
+++ b/sound/oss/dmasound/dac3550a.c	2005-03-11 12:51:42 -08:00
@@ -40,9 +40,6 @@
 static int daca_detect_client(struct i2c_adapter *adapter, int address);
 static int daca_detach_client(struct i2c_client *client);
 
-/* Unique ID allocation */
-static int daca_id;
-
 struct i2c_driver daca_driver = {  
 	.owner			= THIS_MODULE,
 	.name			= "DAC3550A driver  V " DACA_VERSION,
@@ -176,7 +173,6 @@
 	new_client->driver = &daca_driver;
 	new_client->flags = 0;
 	strcpy(new_client->name, client_name);
-	new_client->id = daca_id++; /* racy... */
 
 	if (daca_init_client(new_client))
 		goto bail;
diff -Nru a/sound/oss/es1370.c b/sound/oss/es1370.c
--- a/sound/oss/es1370.c	2005-03-11 12:51:52 -08:00
+++ b/sound/oss/es1370.c	2005-03-11 12:51:52 -08:00
@@ -384,7 +384,7 @@
 		unsigned char obuf[MIDIOUTBUF];
 	} midi;
 
-	struct gameport gameport;
+	struct gameport *gameport;
 	struct semaphore sem;
 };
 
@@ -2540,7 +2540,7 @@
 static struct initvol {
 	int mixch;
 	int vol;
-} initvol[] __initdata = {
+} initvol[] __devinitdata = {
 	{ SOUND_MIXER_WRITE_VOLUME, 0x4040 },
 	{ SOUND_MIXER_WRITE_PCM, 0x4040 },
 	{ SOUND_MIXER_WRITE_SYNTH, 0x4040 },
@@ -2556,6 +2556,7 @@
 static int __devinit es1370_probe(struct pci_dev *pcidev, const struct pci_device_id *pciid)
 {
 	struct es1370_state *s;
+	struct gameport *gp = NULL;
 	mm_segment_t fs;
 	int i, val, ret;
 
@@ -2604,12 +2605,17 @@
 	/* note: setting CTRL_SERR_DIS is reported to break
 	 * mic bias setting (by Kim.Berts@fisub.mail.abb.com) */
 	s->ctrl = CTRL_CDC_EN | (DAC2_SRTODIV(8000) << CTRL_SH_PCLKDIV) | (1 << CTRL_SH_WTSRSEL);
-	s->gameport.io = 0;
-	if (!request_region(0x200, JOY_EXTENT, "es1370"))
+	if (!request_region(0x200, JOY_EXTENT, "es1370")) {
 		printk(KERN_ERR "es1370: joystick io port 0x200 in use\n");
-	else {
+	} else if (!(s->gameport = gp = gameport_allocate_port())) {
+		printk(KERN_ERR "es1370: can not allocate memory for gameport\n");
+		release_region(0x200, JOY_EXTENT);
+	} else {
+		gameport_set_name(gp, "ESS1370");
+		gameport_set_phys(gp, "pci%s/gameport0", pci_name(s->dev));
+		gp->dev.parent = &s->dev->dev;
+		gp->io = 0x200;
 		s->ctrl |= CTRL_JYSTK_EN;
-		s->gameport.io = 0x200;
 	}
 	if (lineout[devindex])
 		s->ctrl |= CTRL_XCTL0;
@@ -2665,9 +2671,10 @@
 		mixer_ioctl(s, initvol[i].mixch, (unsigned long)&val);
 	}
 	set_fs(fs);
+
 	/* register gameport */
-	if (s->gameport.io)
-		gameport_register_port(&s->gameport);
+	if (gp)
+		gameport_register_port(gp);
 
 	/* store it in the driver field */
 	pci_set_drvdata(pcidev, s);
@@ -2689,8 +2696,10 @@
  err_dev1:
 	printk(KERN_ERR "es1370: cannot register misc device\n");
 	free_irq(s->irq, s);
-	if (s->gameport.io)
-		release_region(s->gameport.io, JOY_EXTENT);
+	if (s->gameport) {
+		release_region(s->gameport->io, JOY_EXTENT);
+		gameport_free_port(s->gameport);
+	}
  err_irq:
 	release_region(s->io, ES1370_EXTENT);
  err_region:
@@ -2709,9 +2718,10 @@
 	outl(0, s->io+ES1370_REG_SERIAL_CONTROL); /* clear serial interrupts */
 	synchronize_irq(s->irq);
 	free_irq(s->irq, s);
-	if (s->gameport.io) {
-		gameport_unregister_port(&s->gameport);
-		release_region(s->gameport.io, JOY_EXTENT);
+	if (s->gameport) {
+		int gpio = s->gameport->io;
+		gameport_unregister_port(s->gameport);
+		release_region(gpio, JOY_EXTENT);
 	}
 	release_region(s->io, ES1370_EXTENT);
 	unregister_sound_dsp(s->dev_audio);
diff -Nru a/sound/oss/es1371.c b/sound/oss/es1371.c
--- a/sound/oss/es1371.c	2005-03-11 12:51:48 -08:00
+++ b/sound/oss/es1371.c	2005-03-11 12:51:48 -08:00
@@ -453,7 +453,7 @@
 		unsigned char obuf[MIDIOUTBUF];
 	} midi;
 
-	struct gameport gameport;
+	struct gameport *gameport;
 	struct semaphore sem;
 };
 
@@ -2786,12 +2786,12 @@
 	{ PCI_ANY_ID, PCI_ANY_ID }
 };
 
-
 static int __devinit es1371_probe(struct pci_dev *pcidev, const struct pci_device_id *pciid)
 {
 	struct es1371_state *s;
+	struct gameport *gp;
 	mm_segment_t fs;
-	int i, val, res = -1;
+	int i, gpio, val, res = -1;
 	int idx;
 	unsigned long tmo;
 	signed long tmo2;
@@ -2849,8 +2849,8 @@
 		printk(KERN_ERR PFX "irq %u in use\n", s->irq);
 		goto err_irq;
 	}
-	printk(KERN_INFO PFX "found es1371 rev %d at io %#lx irq %u joystick %#x\n",
-	       s->rev, s->io, s->irq, s->gameport.io);
+	printk(KERN_INFO PFX "found es1371 rev %d at io %#lx irq %u\n",
+	       s->rev, s->io, s->irq);
 	/* register devices */
 	if ((res=(s->dev_audio = register_sound_dsp(&es1371_audio_fops,-1)))<0)
 		goto err_dev1;
@@ -2881,16 +2881,23 @@
                     	printk(KERN_INFO PFX "Enabling internal amplifier.\n");
 		}
 	}
-	s->gameport.io = 0;
-	for (i = 0x218; i >= 0x200; i -= 0x08) {
-		if (request_region(i, JOY_EXTENT, "es1371")) {
-			s->ctrl |= CTRL_JYSTK_EN | (((i >> 3) & CTRL_JOY_MASK) << CTRL_JOY_SHIFT);
-			s->gameport.io = i;
+
+	for (gpio = 0x218; gpio >= 0x200; gpio -= 0x08)
+		if (request_region(gpio, JOY_EXTENT, "es1371"))
 			break;
-		}
-	}
-	if (!s->gameport.io)
+
+	if (gpio < 0x200) {
 		printk(KERN_ERR PFX "no free joystick address found\n");
+	} else if (!(s->gameport = gp = gameport_allocate_port())) {
+		printk(KERN_ERR PFX "can not allocate memory for gameport\n");
+		release_region(gpio, JOY_EXTENT);
+	} else {
+		gameport_set_name(gp, "ESS1371 Gameport");
+		gameport_set_phys(gp, "isa%04x/gameport0", gpio);
+		gp->dev.parent = &s->dev->dev;
+		gp->io = gpio;
+		s->ctrl |= CTRL_JYSTK_EN | (((gpio >> 3) & CTRL_JOY_MASK) << CTRL_JOY_SHIFT);
+	}
 
 	s->sctrl = 0;
 	cssr = 0;
@@ -2960,9 +2967,11 @@
 	set_fs(fs);
 	/* turn on S/PDIF output driver if requested */
 	outl(cssr, s->io+ES1371_REG_STATUS);
+
 	/* register gameport */
-	if (s->gameport.io)
-		gameport_register_port(&s->gameport);
+	if (s->gameport)
+		gameport_register_port(s->gameport);
+
 	/* store it in the driver field */
 	pci_set_drvdata(pcidev, s);
 	/* put it into driver list */
@@ -2973,8 +2982,10 @@
        	return 0;
 
  err_gp:
-	if (s->gameport.io)
-		release_region(s->gameport.io, JOY_EXTENT);
+	if (s->gameport) {
+		release_region(s->gameport->io, JOY_EXTENT);
+		gameport_free_port(s->gameport);
+	}
 #ifdef ES1371_DEBUG
 	if (s->ps)
 		remove_proc_entry("es1371", NULL);
@@ -3013,9 +3024,10 @@
 	outl(0, s->io+ES1371_REG_SERIAL_CONTROL); /* clear serial interrupts */
 	synchronize_irq(s->irq);
 	free_irq(s->irq, s);
-	if (s->gameport.io) {
-		gameport_unregister_port(&s->gameport);
-		release_region(s->gameport.io, JOY_EXTENT);
+	if (s->gameport) {
+		int gpio = s->gameport->io;
+		gameport_unregister_port(s->gameport);
+		release_region(gpio, JOY_EXTENT);
 	}
 	release_region(s->io, ES1371_EXTENT);
 	unregister_sound_dsp(s->dev_audio);
diff -Nru a/sound/oss/esssolo1.c b/sound/oss/esssolo1.c
--- a/sound/oss/esssolo1.c	2005-03-11 12:51:41 -08:00
+++ b/sound/oss/esssolo1.c	2005-03-11 12:51:41 -08:00
@@ -226,7 +226,7 @@
 		unsigned char obuf[MIDIOUTBUF];
 	} midi;
 
-	struct gameport gameport;
+	struct gameport *gameport;
 };
 
 /* --------------------------------------------------------------------- */
@@ -2193,7 +2193,7 @@
 static struct initvol {
 	int mixch;
 	int vol;
-} initvol[] __initdata = {
+} initvol[] __devinitdata = {
 	{ SOUND_MIXER_WRITE_VOLUME, 0x4040 },
 	{ SOUND_MIXER_WRITE_PCM, 0x4040 },
 	{ SOUND_MIXER_WRITE_SYNTH, 0x4040 },
@@ -2280,9 +2280,36 @@
 	return 0;
 }
 
+static int __devinit solo1_register_gameport(struct solo1_state *s, int io_port)
+{
+	struct gameport *gp;
+
+	if (!request_region(io_port, GAMEPORT_EXTENT, "ESS Solo1")) {
+		printk(KERN_ERR "solo1: gameport io ports are in use\n");
+		return -EBUSY;
+	}
+
+	s->gameport = gp = gameport_allocate_port();
+	if (!gp) {
+		printk(KERN_ERR "solo1: can not allocate memory for gameport\n");
+		release_region(io_port, GAMEPORT_EXTENT);
+		return -ENOMEM;
+	}
+
+	gameport_set_name(gp, "ESS Solo1 Gameport");
+	gameport_set_phys(gp, "isa%04x/gameport0", io_port);
+	gp->dev.parent = &s->dev->dev;
+	gp->io = io_port;
+
+	gameport_register_port(gp);
+
+	return 0;
+}
+
 static int __devinit solo1_probe(struct pci_dev *pcidev, const struct pci_device_id *pciid)
 {
 	struct solo1_state *s;
+	int gpio;
 	int ret;
 
  	if ((ret=pci_enable_device(pcidev)))
@@ -2323,7 +2350,7 @@
 	s->vcbase = pci_resource_start(pcidev, 2);
 	s->ddmabase = s->vcbase + DDMABASE_OFFSET;
 	s->mpubase = pci_resource_start(pcidev, 3);
-	s->gameport.io = pci_resource_start(pcidev, 4);
+	gpio = pci_resource_start(pcidev, 4);
 	s->irq = pcidev->irq;
 	ret = -EBUSY;
 	if (!request_region(s->iobase, IOBASE_EXTENT, "ESS Solo1")) {
@@ -2342,15 +2369,10 @@
 		printk(KERN_ERR "solo1: io ports in use\n");
 		goto err_region4;
 	}
-	if (s->gameport.io && !request_region(s->gameport.io, GAMEPORT_EXTENT, "ESS Solo1")) {
-		printk(KERN_ERR "solo1: gameport io ports in use\n");
-		s->gameport.io = 0;
-	}
 	if ((ret=request_irq(s->irq,solo1_interrupt,SA_SHIRQ,"ESS Solo1",s))) {
 		printk(KERN_ERR "solo1: irq %u in use\n", s->irq);
 		goto err_irq;
 	}
-	printk(KERN_INFO "solo1: joystick port at %#x\n", s->gameport.io+1);
 	/* register devices */
 	if ((s->dev_audio = register_sound_dsp(&solo1_audio_fops, -1)) < 0) {
 		ret = s->dev_audio;
@@ -2373,7 +2395,7 @@
 		goto err;
 	}
 	/* register gameport */
-	gameport_register_port(&s->gameport);
+	solo1_register_gameport(s, gpio);
 	/* store it in the driver field */
 	pci_set_drvdata(pcidev, s);
 	return 0;
@@ -2390,8 +2412,6 @@
 	printk(KERN_ERR "solo1: initialisation error\n");
 	free_irq(s->irq, s);
  err_irq:
-	if (s->gameport.io)
-		release_region(s->gameport.io, GAMEPORT_EXTENT);
 	release_region(s->mpubase, MPUBASE_EXTENT);
  err_region4:
 	release_region(s->ddmabase, DDMABASE_EXTENT);
@@ -2417,9 +2437,10 @@
 	synchronize_irq(s->irq);
 	pci_write_config_word(s->dev, 0x60, 0); /* turn off DDMA controller address space */
 	free_irq(s->irq, s);
-	if (s->gameport.io) {
-		gameport_unregister_port(&s->gameport);
-		release_region(s->gameport.io, GAMEPORT_EXTENT);
+	if (s->gameport) {
+		int gpio = s->gameport->io;
+		gameport_unregister_port(s->gameport);
+		release_region(gpio, GAMEPORT_EXTENT);
 	}
 	release_region(s->iobase, IOBASE_EXTENT);
 	release_region(s->sbbase+FMSYNTH_EXTENT, SBBASE_EXTENT-FMSYNTH_EXTENT);
diff -Nru a/sound/oss/harmony.c b/sound/oss/harmony.c
--- a/sound/oss/harmony.c	2005-03-11 12:51:50 -08:00
+++ b/sound/oss/harmony.c	2005-03-11 12:51:50 -08:00
@@ -310,7 +310,7 @@
 	case 32000:	newrate = HARMONY_SR_32KHZ;	break; 
 	case 48000:	newrate = HARMONY_SR_48KHZ;	break; 
 	case 9600:	newrate = HARMONY_SR_9KHZ;	break; 
-	case 5125:	newrate = HARMONY_SR_5KHZ;	break; 
+	case 5512:	newrate = HARMONY_SR_5KHZ;	break; 
 	case 11025:	newrate = HARMONY_SR_11KHZ;	break; 
 	case 18900:	newrate = HARMONY_SR_18KHZ;	break; 
 	case 22050:	newrate = HARMONY_SR_22KHZ;	break; 
diff -Nru a/sound/oss/mad16.c b/sound/oss/mad16.c
--- a/sound/oss/mad16.c	2005-03-11 12:51:48 -08:00
+++ b/sound/oss/mad16.c	2005-03-11 12:51:48 -08:00
@@ -52,7 +52,7 @@
 
 static int      mad16_conf;
 static int      mad16_cdsel;
-static struct gameport gameport;
+static struct gameport *gameport;
 static DEFINE_SPINLOCK(lock);
 
 #define C928	1
@@ -902,7 +902,30 @@
 	-1, -1, -1, -1
 };
 
-static int __init init_mad16(void)
+static int __devinit mad16_register_gameport(int io_port)
+{
+	if (!request_region(io_port, 1, "mad16 gameport")) {
+		printk(KERN_ERR "mad16: gameport address 0x%#x already in use\n", io_port);
+		return -EBUSY;
+	}
+
+	gameport = gameport_allocate_port();
+	if (!gameport) {
+		printk(KERN_ERR "mad16: can not allocate memory for gameport\n");
+		release_region(io_port, 1);
+		return -ENOMEM;
+	}
+
+	gameport_set_name(gameport, "MAD16 Gameport");
+	gameport_set_phys(gameport, "isa%04x/gameport0", io_port);
+	gameport->io = io_port;
+
+	gameport_register_port(gameport);
+
+	return 0;
+}
+
+static int __devinit init_mad16(void)
 {
 	int dmatype = 0;
 
@@ -1027,17 +1050,9 @@
 
 	found_mpu = probe_mad16_mpu(&cfg_mpu);
 
-	if (joystick == 1) {
-		/* register gameport */
-		if (!request_region(0x201, 1, "mad16 gameport"))
-			printk(KERN_ERR "mad16: gameport address 0x201 already in use\n");
-		else {
-			printk(KERN_ERR "mad16: gameport enabled at 0x201\n");
-			gameport.io = 0x201;
-			gameport_register_port(&gameport);
-		}
-	}
-	else printk(KERN_ERR "mad16: gameport disabled.\n");
+	if (joystick)
+		mad16_register_gameport(0x201);
+
 	return 0;
 }
 
@@ -1045,10 +1060,10 @@
 {
 	if (found_mpu)
 		unload_mad16_mpu(&cfg_mpu);
-	if (gameport.io) {
+	if (gameport) {
 		/* the gameport was initialized so we must free it up */
-		gameport_unregister_port(&gameport);
-		gameport.io = 0;
+		gameport_unregister_port(gameport);
+		gameport = NULL;
 		release_region(0x201, 1);
 	}
 	unload_mad16(&cfg);
diff -Nru a/sound/oss/nm256_audio.c b/sound/oss/nm256_audio.c
--- a/sound/oss/nm256_audio.c	2005-03-11 12:51:43 -08:00
+++ b/sound/oss/nm256_audio.c	2005-03-11 12:51:43 -08:00
@@ -1047,7 +1047,7 @@
  * VERSTR is a human-readable version string.
  */
 
-static int __init
+static int __devinit
 nm256_install(struct pci_dev *pcidev, enum nm256rev rev, char *verstr)
 {
     struct nm256_info *card;
diff -Nru a/sound/oss/pss.c b/sound/oss/pss.c
--- a/sound/oss/pss.c	2005-03-11 12:51:52 -08:00
+++ b/sound/oss/pss.c	2005-03-11 12:51:52 -08:00
@@ -1149,7 +1149,7 @@
 static int mss_dma __initdata	= -1;
 static int mpu_io __initdata	= -1;
 static int mpu_irq __initdata	= -1;
-static int pss_no_sound __initdata = 0;	/* Just configure non-sound components */
+static int pss_no_sound = 0;	/* Just configure non-sound components */
 static int pss_keep_settings  = 1;	/* Keep hardware settings at module exit */
 static char *pss_firmware = "/etc/sound/pss_synth";
 
diff -Nru a/sound/oss/sonicvibes.c b/sound/oss/sonicvibes.c
--- a/sound/oss/sonicvibes.c	2005-03-11 12:51:43 -08:00
+++ b/sound/oss/sonicvibes.c	2005-03-11 12:51:43 -08:00
@@ -365,7 +365,7 @@
 		unsigned char obuf[MIDIOUTBUF];
 	} midi;
 
-	struct gameport gameport;
+	struct gameport *gameport;
 };
 
 /* --------------------------------------------------------------------- */
@@ -2485,12 +2485,39 @@
 #define RSRCISIOREGION(dev,num) (pci_resource_start((dev), (num)) != 0 && \
 				 (pci_resource_flags((dev), (num)) & IORESOURCE_IO))
 
+static int __devinit sv_register_gameport(struct sv_state *s, int io_port)
+{
+	struct gameport *gp;
+
+	if (!request_region(io_port, SV_EXTENT_GAME, "S3 SonicVibes Gameport")) {
+		printk(KERN_ERR "sv: gameport io ports are in use\n");
+		return -EBUSY;
+	}
+
+	s->gameport = gp = gameport_allocate_port();
+	if (!gp) {
+		printk(KERN_ERR "sv: can not allocate memory for gameport\n");
+		release_region(io_port, SV_EXTENT_GAME);
+		return -ENOMEM;
+	}
+
+	gameport_set_name(gp, "S3 SonicVibes Gameport");
+	gameport_set_phys(gp, "isa%04x/gameport0", io_port);
+	gp->dev.parent = &s->dev->dev;
+	gp->io = io_port;
+
+	gameport_register_port(gp);
+
+	return 0;
+}
+
 static int __devinit sv_probe(struct pci_dev *pcidev, const struct pci_device_id *pciid)
 {
 	static char __devinitdata sv_ddma_name[] = "S3 Inc. SonicVibes DDMA Controller";
        	struct sv_state *s;
 	mm_segment_t fs;
 	int i, val, ret;
+	int gpio;
 	char *ddmaname;
 	unsigned ddmanamelen;
 
@@ -2546,11 +2573,11 @@
 	s->iomidi = pci_resource_start(pcidev, RESOURCE_MIDI);
 	s->iodmaa = pci_resource_start(pcidev, RESOURCE_DDMA);
 	s->iodmac = pci_resource_start(pcidev, RESOURCE_DDMA) + SV_EXTENT_DMA;
-	s->gameport.io = pci_resource_start(pcidev, RESOURCE_GAME);
+	gpio = pci_resource_start(pcidev, RESOURCE_GAME);
 	pci_write_config_dword(pcidev, 0x40, s->iodmaa | 9);  /* enable and use extended mode */
 	pci_write_config_dword(pcidev, 0x48, s->iodmac | 9);  /* enable */
 	printk(KERN_DEBUG "sv: io ports: %#lx %#lx %#lx %#lx %#x %#x %#x\n",
-	       s->iosb, s->ioenh, s->iosynth, s->iomidi, s->gameport.io, s->iodmaa, s->iodmac);
+	       s->iosb, s->ioenh, s->iosynth, s->iomidi, gpio, s->iodmaa, s->iodmac);
 	s->irq = pcidev->irq;
 	
 	/* hack */
@@ -2577,10 +2604,7 @@
 		printk(KERN_ERR "sv: io ports %#lx-%#lx in use\n", s->iosynth, s->iosynth+SV_EXTENT_SYNTH-1);
 		goto err_region1;
 	}
-	if (s->gameport.io && !request_region(s->gameport.io, SV_EXTENT_GAME, "ESS Solo1")) {
-		printk(KERN_ERR "sv: gameport io ports in use\n");
-		s->gameport.io = 0;
-	}
+
 	/* initialize codec registers */
 	outb(0x80, s->ioenh + SV_CODEC_CONTROL); /* assert reset */
 	udelay(50);
@@ -2639,7 +2663,7 @@
 	}
 	set_fs(fs);
 	/* register gameport */
-	gameport_register_port(&s->gameport);
+	sv_register_gameport(s, gpio);
 	/* store it in the driver field */
 	pci_set_drvdata(pcidev, s);
 	/* put it into driver list */
@@ -2659,8 +2683,6 @@
 	printk(KERN_ERR "sv: cannot register misc device\n");
 	free_irq(s->irq, s);
  err_irq:
-	if (s->gameport.io)
-		release_region(s->gameport.io, SV_EXTENT_GAME);
 	release_region(s->iosynth, SV_EXTENT_SYNTH);
  err_region1:
 	release_region(s->iomidi, SV_EXTENT_MIDI);
@@ -2689,9 +2711,10 @@
 	/*outb(0, s->iodmaa + SV_DMA_RESET);*/
 	/*outb(0, s->iodmac + SV_DMA_RESET);*/
 	free_irq(s->irq, s);
-	if (s->gameport.io) {
-		gameport_unregister_port(&s->gameport);
-		release_region(s->gameport.io, SV_EXTENT_GAME);
+	if (s->gameport) {
+		int gpio = s->gameport->io;
+		gameport_unregister_port(s->gameport);
+		release_region(gpio, SV_EXTENT_GAME);
 	}
 	release_region(s->iodmac, SV_EXTENT_DMA);
 	release_region(s->iodmaa, SV_EXTENT_DMA);
diff -Nru a/sound/oss/sscape.c b/sound/oss/sscape.c
--- a/sound/oss/sscape.c	2005-03-11 12:51:47 -08:00
+++ b/sound/oss/sscape.c	2005-03-11 12:51:47 -08:00
@@ -1393,7 +1393,7 @@
 static struct address_info cfg_mpu;
 
 static int __initdata spea = -1;
-static int __initdata mss = 0;
+static int mss = 0;
 static int __initdata dma = -1;
 static int __initdata irq = -1;
 static int __initdata io = -1;
diff -Nru a/sound/oss/trident.c b/sound/oss/trident.c
--- a/sound/oss/trident.c	2005-03-11 12:51:50 -08:00
+++ b/sound/oss/trident.c	2005-03-11 12:51:50 -08:00
@@ -441,7 +441,7 @@
 	struct timer_list timer;
 
 	/* Game port support */
-	struct gameport gameport;
+	struct gameport *gameport;
 };
 
 enum dmabuf_mode {
@@ -4257,21 +4257,21 @@
 static unsigned char
 trident_game_read(struct gameport *gameport)
 {
-	struct trident_card *card = gameport->driver;
+	struct trident_card *card = gameport->port_data;
 	return inb(TRID_REG(card, T4D_GAME_LEG));
 }
 
 static void
 trident_game_trigger(struct gameport *gameport)
 {
-	struct trident_card *card = gameport->driver;
+	struct trident_card *card = gameport->port_data;
 	outb(0xff, TRID_REG(card, T4D_GAME_LEG));
 }
 
 static int
 trident_game_cooked_read(struct gameport *gameport, int *axes, int *buttons)
 {
-	struct trident_card *card = gameport->driver;
+	struct trident_card *card = gameport->port_data;
 	int i;
 
 	*buttons = (~inb(TRID_REG(card, T4D_GAME_LEG)) >> 4) & 0xf;
@@ -4288,7 +4288,7 @@
 static int
 trident_game_open(struct gameport *gameport, int mode)
 {
-	struct trident_card *card = gameport->driver;
+	struct trident_card *card = gameport->port_data;
 
 	switch (mode) {
 	case GAMEPORT_MODE_COOKED:
@@ -4305,6 +4305,31 @@
 	return 0;
 }
 
+static int __devinit
+trident_register_gameport(struct trident_card *card)
+{
+	struct gameport *gp;
+
+	card->gameport = gp = gameport_allocate_port();
+	if (!gp) {
+		printk(KERN_ERR "trident: can not allocate memory for gameport\n");
+		return -ENOMEM;
+	}
+
+	gameport_set_name(gp, "Trident 4DWave");
+	gameport_set_phys(gp, "pci%s/gameport0", pci_name(card->pci_dev));
+	gp->read = trident_game_read;
+	gp->trigger = trident_game_trigger;
+	gp->cooked_read = trident_game_cooked_read;
+	gp->open = trident_game_open;
+	gp->fuzz = 64;
+	gp->port_data = card;
+
+	gameport_register_port(gp);
+
+	return 0;
+}
+
 /* 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) */
@@ -4368,13 +4393,6 @@
 	card->banks[BANK_B].addresses = &bank_b_addrs;
 	card->banks[BANK_B].bitmap = 0UL;
 
-	card->gameport.driver = card;
-	card->gameport.fuzz = 64;
-	card->gameport.read = trident_game_read;
-	card->gameport.trigger = trident_game_trigger;
-	card->gameport.cooked_read = trident_game_cooked_read;
-	card->gameport.open = trident_game_open;
-
 	init_MUTEX(&card->open_sem);
 	spin_lock_init(&card->lock);
 	init_timer(&card->timer);
@@ -4508,7 +4526,7 @@
 	trident_enable_loop_interrupts(card);
 
 	/* Register gameport */
-	gameport_register_port(&card->gameport);
+	trident_register_gameport(card);
 
 out:
 	return rc;
@@ -4551,7 +4569,8 @@
 	}
 
 	/* Unregister gameport */
-	gameport_unregister_port(&card->gameport);
+	if (card->gameport)
+		gameport_unregister_port(card->gameport);
 
 	/* Kill interrupts, and SP/DIF */
 	trident_disable_loop_interrupts(card);
diff -Nru a/sound/parisc/Kconfig b/sound/parisc/Kconfig
--- a/sound/parisc/Kconfig	2005-03-11 12:51:47 -08:00
+++ b/sound/parisc/Kconfig	2005-03-11 12:51:47 -08:00
@@ -1,6 +1,6 @@
 # ALSA PA-RISC drivers
 
-menu "ALSA GSC devices"
+menu "GSC devices"
 	depends on SND!=n && GSC
 
 config SND_HARMONY
diff -Nru a/sound/parisc/harmony.c b/sound/parisc/harmony.c
--- a/sound/parisc/harmony.c	2005-03-11 12:51:42 -08:00
+++ b/sound/parisc/harmony.c	2005-03-11 12:51:42 -08:00
@@ -1,264 +1,88 @@
-/*
- *  Harmony chipset driver
+/* Hewlett-Packard Harmony audio driver
  *
- *	This is a sound driver for ASP's and Lasi's Harmony sound chip
- *	and is unlikely to be used for anything other than on a HP PA-RISC.
+ *   This is a driver for the Harmony audio chipset found
+ *   on the LASI ASIC of various early HP PA-RISC workstations.
  *
- *	Harmony is found in HP 712s, 715/new and many other GSC based machines.
- *	On older 715 machines you'll find the technically identical chip 
- *	called 'Vivace'. Both Harmony and Vivace are supported by this driver.
+ *   Copyright (C) 2004, Kyle McMartin <kyle@{debian.org,parisc-linux.org}>
  *
- *  this ALSA driver is based on OSS driver by:
- *	Copyright 2000 (c) Linuxcare Canada, Alex deVries <alex@linuxcare.com>
- *	Copyright 2000-2002 (c) Helge Deller <deller@gmx.de>
- *	Copyright 2001 (c) Matthieu Delahaye <delahaym@esiee.fr>
+ *     Based on the previous Harmony incarnations by,
+ *       Copyright 2000 (c) Linuxcare Canada, Alex deVries
+ *       Copyright 2000-2003 (c) Helge Deller
+ *       Copyright 2001 (c) Matthieu Delahaye
+ *       Copyright 2001 (c) Jean-Christophe Vaugeois
+ *       Copyright 2003 (c) Laurent Canet
+ *       Copyright 2004 (c) Stuart Brady
  *
- * TODO:
- * - use generic DMA interface and ioremap()/iounmap()
- * - capture is still untested (and probaby non-working)
- * - spin locks
- * - implement non-consistent DMA pages
- * - implement gain meter
- * - module parameters
- * - correct cleaning sequence
- * - better error checking
- * - try to have a better quality.
- *   
- */
-
-/*
- * Harmony chipset 'modus operandi'.
- * - This chipset is found in some HP 32bit workstations, like 712, or B132 class.
- * most of controls are done through registers. Register are found at a fixed offset
- * from the hard physical adress, given in struct dev by register_parisc_driver.
+ *   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.
  *
- * Playback and recording use 4kb pages (dma or not, depending on the machine).
+ *   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.
  *
- * Most of PCM playback & capture is done through interrupt. When harmony needs
- * a new buffer to put recorded data or read played PCM, it sends an interrupt.
- * Bits 2 and 10 of DSTATUS register are '1' when harmony needs respectively
- * a new page for recording and playing. 
- * Interrupt are disabled/enabled by writing to bit 32 of DSTATUS. 
- * Adresses of next page to be played is put in PNXTADD register, next page
- * to be recorded is put in RNXTADD. There is 2 read-only registers, PCURADD and 
- * RCURADD that provides adress of current page.
- * 
- * Harmony has no way to control full duplex or half duplex mode. It means
- * that we always need to provide adresses of playback and capture data, even
- * when this is not needed. That's why we statically alloc one graveyard
- * buffer (to put recorded data in play-only mode) and a silence buffer.
- * 
- * Bitrate, number of channels and data format are controlled with
- * the CNTL register.
+ *   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.
  *
- * Mixer work is done through one register (GAINCTL). Only input gain,
- * output attenuation and general attenuation control is provided. There is
- * also controls for enabling/disabling internal speaker and line
- * input.
+ * Notes:
+ *   - graveyard and silence buffers last for lifetime of
+ *     the driver. playback and capture buffers are allocated
+ *     per _open()/_close().
+ * 
+ * TODO:
  *
- * Buffers used by this driver are all DMA consistent.
  */
 
-#include <linux/delay.h>
-#include <sound/driver.h>
 #include <linux/init.h>
-#include <linux/interrupt.h>
 #include <linux/slab.h>
 #include <linux/time.h>
 #include <linux/wait.h>
-#include <linux/moduleparam.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/dma-mapping.h>
+
+#include <sound/driver.h>
 #include <sound/core.h>
-#include <sound/control.h>
 #include <sound/pcm.h>
+#include <sound/control.h>
 #include <sound/rawmidi.h>
 #include <sound/initval.h>
 #include <sound/info.h>
-#include <asm/hardware.h>
+
 #include <asm/io.h>
+#include <asm/hardware.h>
 #include <asm/parisc-device.h>
 
-MODULE_AUTHOR("Laurent Canet <canetl@esiee.fr>");
-MODULE_DESCRIPTION("ALSA Harmony sound driver");
-MODULE_LICENSE("GPL");
-MODULE_SUPPORTED_DEVICE("{{ALSA,Harmony soundcard}}");
-
-#undef DEBUG
-#ifdef DEBUG
-# define DPRINTK printk 
-#else
-# define DPRINTK(x,...)
-#endif
-
-#define PFX	"harmony: "
-
-#define MAX_PCM_DEVICES		1
-#define MAX_PCM_SUBSTREAMS	4
-#define MAX_MIDI_DEVICES	0
-
-#define HARMONY_BUF_SIZE	4096
-#define MAX_BUFS		10
-#define MAX_BUFFER_SIZE		(MAX_BUFS * HARMONY_BUF_SIZE)
-
-/* number of silence & graveyard buffers */
-#define GRAVEYARD_BUFS		3
-#define SILENCE_BUFS		3
-
-#define HARMONY_CNTL_C		0x80000000
-
-#define HARMONY_DSTATUS_PN	0x00000200
-#define HARMONY_DSTATUS_RN	0x00000002
-#define HARMONY_DSTATUS_IE	0x80000000
-
-#define HARMONY_DF_16BIT_LINEAR	0x00000000
-#define HARMONY_DF_8BIT_ULAW	0x00000001
-#define HARMONY_DF_8BIT_ALAW	0x00000002
-
-#define HARMONY_SS_MONO		0x00000000
-#define HARMONY_SS_STEREO	0x00000001
-
-/*
- * Channels Mask in mixer register
- * try some "reasonable" default gain values
- */
-
-#define HARMONY_GAIN_TOTAL_SILENCE 0x00F00FFF
-
-/* the following should be enough (mixer is 
- * very sensible on harmony)
- */
-#define HARMONY_GAIN_DEFAULT       0x0F2FF082
-
-
-/* useless since only one card is supported ATM */
-static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;	/* Index 0-MAX */
-static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;	/* ID for this card */
-static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE;
-
-module_param_array(index, int, NULL, 0444);
-MODULE_PARM_DESC(index, "Index value for Harmony device.");
-module_param_array(id, charp, NULL, 0444);
-MODULE_PARM_DESC(id, "ID string for Harmony device.");
-module_param_array(enable, bool, NULL, 0444);
-MODULE_PARM_DESC(enable, "Enable Harmony device.");
-
-/* Register offset (from base hpa) */
-#define REG_ID		0x00
-#define REG_RESET	0x04
-#define REG_CNTL	0x08
-#define REG_GAINCTL	0x0C
-#define REG_PNXTADD	0x10
-#define REG_PCURADD	0x14
-#define REG_RNXTADD	0x18
-#define REG_RCURADD	0x1C
-#define REG_DSTATUS	0x20
-#define REG_OV		0x24
-#define REG_PIO		0x28
-#define REG_DIAG	0x3C
-
-/*
- * main harmony structure
- */
+#include "harmony.h"
 
-typedef struct snd_card_harmony {
-
-	/* spinlocks (To be done) */
-	spinlock_t mixer_lock;
-	spinlock_t control_lock;
-
-	/* parameters */	
-	int irq;
-	unsigned long hpa;
-	int id;
-	int rev;
-	
-	u32 current_gain;
-	int data_format;		/* HARMONY_DF_xx_BIT_xxx */
-	int sample_rate;		/* HARMONY_SR_xx_KHZ */
-	int stereo_select;	/* HARMONY_SS_MONO or HARMONY_SS_STEREO */
-	int format_initialized;
-	
-	unsigned long ply_buffer;
-	int ply_buf;
-	int ply_count;
-	int ply_size;
-	int ply_stopped;
-	int ply_total;
-	
-	unsigned long cap_buffer;
-	int cap_buf;
-	int cap_count;
-	int cap_size;
-	int cap_stopped;
-	int cap_total;
-
-	struct parisc_device *pa_dev;
-
-	struct snd_dma_device dma_dev;
-
-	/* the graveyard buffer is used as recording buffer when playback, 
-	 * because harmony always want a buffer to put recorded data */
-	struct snd_dma_buffer graveyard_dma;
-	int graveyard_count;
-	
-	/* same thing for silence buffer */
-	struct snd_dma_buffer silence_dma;
-	int silence_count;
-
-	/* alsa stuff */
-	snd_card_t *card;
-	snd_pcm_t *pcm;
-	snd_pcm_substream_t *playback_substream;
-	snd_pcm_substream_t *capture_substream;
-	snd_info_entry_t *proc_entry;
-} snd_card_harmony_t;
-
-static snd_card_t *snd_harmony_cards[SNDRV_CARDS] = SNDRV_DEFAULT_PTR;
-
-/* wait to be out of control mode */
-static inline void snd_harmony_wait_cntl(snd_card_harmony_t *harmony)
-{
-	int timeout = 5000;
+static struct parisc_device_id snd_harmony_devtable[] = {
+	/* bushmaster / flounder */
+	{ HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x0007A }, 
+	/* 712 / 715 */
+	{ HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x0007B }, 
+	/* pace */
+	{ HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x0007E }, 
+	/* outfield / coral II */
+	{ HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x0007F },
+	{ 0, }
+};
 
-	while ( (gsc_readl(harmony->hpa+REG_CNTL) & HARMONY_CNTL_C) && --timeout)
-	{
-		/* Wait */ ;	
-	}
-	if (timeout == 0) DPRINTK(KERN_DEBUG PFX "Error: wait cntl timeouted\n");
-}
+MODULE_DEVICE_TABLE(parisc, snd_harmony_devtable);
 
+#define NAME "harmony"
+#define PFX  NAME ": "
 
-/*
- * sample rate routines 
- */
-static unsigned int snd_card_harmony_rates[] = {
-	5125, 6615, 8000, 9600,
+static unsigned int snd_harmony_rates[] = {
+	5512, 6615, 8000, 9600,
 	11025, 16000, 18900, 22050,
 	27428, 32000, 33075, 37800,
 	44100, 48000
 };
 
-static snd_pcm_hw_constraint_list_t hw_constraint_rates = {
-	.count = ARRAY_SIZE(snd_card_harmony_rates),
-	.list = snd_card_harmony_rates,
-	.mask = 0,
-};
-
-#define HARMONY_SR_8KHZ		0x08
-#define HARMONY_SR_16KHZ	0x09
-#define HARMONY_SR_27KHZ	0x0A
-#define HARMONY_SR_32KHZ	0x0B
-#define HARMONY_SR_48KHZ	0x0E
-#define HARMONY_SR_9KHZ		0x0F
-#define HARMONY_SR_5KHZ		0x10
-#define HARMONY_SR_11KHZ	0x11
-#define HARMONY_SR_18KHZ	0x12
-#define HARMONY_SR_22KHZ	0x13
-#define HARMONY_SR_37KHZ	0x14
-#define HARMONY_SR_44KHZ	0x15
-#define HARMONY_SR_33KHZ	0x16
-#define HARMONY_SR_6KHZ		0x17
-
-/* bits corresponding to the entries of snd_card_harmony_rates */
 static unsigned int rate_bits[14] = {
 	HARMONY_SR_5KHZ, HARMONY_SR_6KHZ, HARMONY_SR_8KHZ,
 	HARMONY_SR_9KHZ, HARMONY_SR_11KHZ, HARMONY_SR_16KHZ,
@@ -267,642 +91,627 @@
 	HARMONY_SR_44KHZ, HARMONY_SR_48KHZ
 };
 
-/* snd_card_harmony_rate_bits
- * @rate:	index of current data rate in list
- * returns: harmony hex code for registers
- */
-static unsigned int snd_card_harmony_rate_bits(int rate)
+static snd_pcm_hw_constraint_list_t hw_constraint_rates = {
+	.count = ARRAY_SIZE(snd_harmony_rates),
+	.list = snd_harmony_rates,
+	.mask = 0,
+};
+
+inline unsigned long
+harmony_read(harmony_t *h, unsigned r)
 {
-	unsigned int idx;
-	
-	for (idx = 0; idx < ARRAY_SIZE(snd_card_harmony_rates); idx++)
-		if (snd_card_harmony_rates[idx] == rate)
-			return rate_bits[idx];
-	return HARMONY_SR_44KHZ; /* fallback */
+	return __raw_readl(h->iobase + r);
 }
 
-/*
- * update controls (data format, sample rate, number of channels)
- * according to value supplied in data structure
- */
-void snd_harmony_update_control(snd_card_harmony_t *harmony) 
+inline void
+harmony_write(harmony_t *h, unsigned r, unsigned long v)
 {
-	u32 default_cntl;
-	
-	/* Set CNTL */
-	default_cntl = (HARMONY_CNTL_C |  	/* The C bit */
-		(harmony->data_format << 6) |	/* Set the data format */
-		(harmony->stereo_select << 5) |	/* Stereo select */
-		(harmony->sample_rate));		/* Set sample rate */
-	
-	/* initialize CNTL */
- 	snd_harmony_wait_cntl(harmony);
-	
-	gsc_writel(default_cntl, harmony->hpa+REG_CNTL);
-	
+	__raw_writel(v, h->iobase + r);
 }
 
-/*
- * interruption controls routines
- */
+static void
+harmony_wait_for_control(harmony_t *h)
+{
+	while (harmony_read(h, HARMONY_CNTL) & HARMONY_CNTL_C) ;
+}
 
-static void snd_harmony_disable_interrupts(snd_card_harmony_t *chip) 
+inline void
+harmony_reset(harmony_t *h)
 {
- 	snd_harmony_wait_cntl(chip);
-	gsc_writel(0, chip->hpa+REG_DSTATUS); 
+	harmony_write(h, HARMONY_RESET, 1);
+	mdelay(50);
+	harmony_write(h, HARMONY_RESET, 0);
 }
 
-static void snd_harmony_enable_interrupts(snd_card_harmony_t *chip) 
+static void
+harmony_disable_interrupts(harmony_t *h)
 {
- 	snd_harmony_wait_cntl(chip);
-	gsc_writel(HARMONY_DSTATUS_IE, chip->hpa+REG_DSTATUS); 
+	u32 dstatus;
+	harmony_wait_for_control(h);
+	dstatus = harmony_read(h, HARMONY_DSTATUS);
+	dstatus &= ~HARMONY_DSTATUS_IE;
+	harmony_write(h, HARMONY_DSTATUS, dstatus);
 }
 
-/*
- * interruption routine:
- * The interrupt routine must provide adresse of next physical pages 
- * used by harmony
- */
-static int snd_card_harmony_interrupt(int irq, void *dev, struct pt_regs *regs)
+static void
+harmony_enable_interrupts(harmony_t *h)
 {
-	snd_card_harmony_t *harmony = (snd_card_harmony_t *)dev;
-	u32 dstatus = 0;
-	unsigned long hpa = harmony->hpa;
-	
-	/* Turn off interrupts */
-	snd_harmony_disable_interrupts(harmony);
-	
-	/* wait for control to free */
- 	snd_harmony_wait_cntl(harmony);
-	
-	/* Read dstatus and pcuradd (the current address) */
-	dstatus = gsc_readl(hpa+REG_DSTATUS);
-	
-	/* Check if this is a request to get the next play buffer */
+	u32 dstatus;
+	harmony_wait_for_control(h);
+	dstatus = harmony_read(h, HARMONY_DSTATUS);
+	dstatus |= HARMONY_DSTATUS_IE;
+	harmony_write(h, HARMONY_DSTATUS, dstatus);
+}
+
+static void
+harmony_mute(harmony_t *h)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&h->mixer_lock, flags);
+	harmony_wait_for_control(h);
+	harmony_write(h, HARMONY_GAINCTL, HARMONY_GAIN_SILENCE);
+	spin_unlock_irqrestore(&h->mixer_lock, flags);
+}
+
+static void
+harmony_unmute(harmony_t *h)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&h->mixer_lock, flags);
+	harmony_wait_for_control(h);
+	harmony_write(h, HARMONY_GAINCTL, h->st.gain);
+	spin_unlock_irqrestore(&h->mixer_lock, flags);
+}
+
+static void
+harmony_set_control(harmony_t *h)
+{
+	u32 ctrl;
+	unsigned long flags;
+
+	spin_lock_irqsave(&h->lock, flags);
+
+	ctrl = (HARMONY_CNTL_C      |
+		(h->st.format << 6) |
+		(h->st.stereo << 5) |
+		(h->st.rate));
+
+	harmony_wait_for_control(h);
+	harmony_write(h, HARMONY_CNTL, ctrl);
+
+	spin_unlock_irqrestore(&h->lock, flags);
+}
+
+static irqreturn_t
+snd_harmony_interrupt(int irq, void *dev, struct pt_regs *regs)
+{
+	u32 dstatus;
+	harmony_t *h = dev;
+
+	spin_lock(&h->lock);
+	harmony_disable_interrupts(h);
+	harmony_wait_for_control(h);
+	dstatus = harmony_read(h, HARMONY_DSTATUS);
+	spin_unlock(&h->lock);
+
 	if (dstatus & HARMONY_DSTATUS_PN) {
-		if (harmony->playback_substream) {
-			harmony->ply_buf += harmony->ply_count;
-			harmony->ply_buf %= harmony->ply_size;
-		
-			gsc_writel(harmony->ply_buffer + harmony->ply_buf,
-					hpa+REG_PNXTADD);
-		
-			snd_pcm_period_elapsed(harmony->playback_substream);
-			harmony->ply_total++;
+		if (h->psubs) {
+			spin_lock(&h->lock);
+			h->pbuf.buf += h->pbuf.count; /* PAGE_SIZE */
+			h->pbuf.buf %= h->pbuf.size; /* MAX_BUFS*PAGE_SIZE */
+
+			harmony_write(h, HARMONY_PNXTADD, 
+				      h->pbuf.addr + h->pbuf.buf);
+			h->stats.play_intr++;
+			spin_unlock(&h->lock);
+                        snd_pcm_period_elapsed(h->psubs);
 		} else {
-			gsc_writel(harmony->silence_dma.addr + 
-				   (HARMONY_BUF_SIZE*harmony->silence_count),
-				   hpa+REG_PNXTADD);
-			harmony->silence_count++;
-			harmony->silence_count %= SILENCE_BUFS;
+			spin_lock(&h->lock);
+			harmony_write(h, HARMONY_PNXTADD, h->sdma.addr);
+			h->stats.silence_intr++;
+			spin_unlock(&h->lock);
 		}
 	}
-	
-	/* Check if we're being asked to fill in a recording buffer */
+
 	if (dstatus & HARMONY_DSTATUS_RN) {
-		if (harmony->capture_substream) {
-			harmony->cap_buf += harmony->cap_count;
-			harmony->cap_buf %= harmony->cap_size;
-		
-			gsc_writel(harmony->cap_buffer + harmony->cap_buf,
-					hpa+REG_RNXTADD);
-		
-			snd_pcm_period_elapsed(harmony->capture_substream);
-			harmony->cap_total++;
+		if (h->csubs) {
+			spin_lock(&h->lock);
+			h->cbuf.buf += h->cbuf.count;
+			h->cbuf.buf %= h->cbuf.size;
+
+			harmony_write(h, HARMONY_RNXTADD,
+				      h->cbuf.addr + h->cbuf.buf);
+			h->stats.rec_intr++;
+			spin_unlock(&h->lock);
+                        snd_pcm_period_elapsed(h->csubs);
 		} else {
-			/* graveyard buffer */
-			gsc_writel(harmony->graveyard_dma.addr +
-				   (HARMONY_BUF_SIZE*harmony->graveyard_count),
-				   hpa+REG_RNXTADD);
-			harmony->graveyard_count++;
-			harmony->graveyard_count %= GRAVEYARD_BUFS;
+			spin_lock(&h->lock);
+			harmony_write(h, HARMONY_RNXTADD, h->gdma.addr);
+			h->stats.graveyard_intr++;
+			spin_unlock(&h->lock);
 		}
 	}
-	snd_harmony_enable_interrupts(harmony);
+
+	spin_lock(&h->lock);
+	harmony_enable_interrupts(h);
+	spin_unlock(&h->lock);
 
 	return IRQ_HANDLED;
 }
 
-/* 
- * proc entry
- * this proc file will give some debugging info
- */
-
-static void snd_harmony_proc_read(snd_info_entry_t *entry, snd_info_buffer_t *buffer)
+static unsigned int 
+snd_harmony_rate_bits(int rate)
 {
-	snd_card_harmony_t *harmony = (snd_card_harmony_t *)entry->private_data;
-
-	snd_iprintf(buffer, "LASI Harmony driver\nLaurent Canet <canetl@esiee.fr>\n\n");
-	snd_iprintf(buffer, "IRQ %d, hpa %lx, id %d rev %d\n",
-			harmony->irq, harmony->hpa,
-			harmony->id, harmony->rev);
-	snd_iprintf(buffer, "Current gain %lx\n", (unsigned long) harmony->current_gain);
-	snd_iprintf(buffer, "\tsample rate=%d\n", harmony->sample_rate);
-	snd_iprintf(buffer, "\tstereo select=%d\n", harmony->stereo_select);
-	snd_iprintf(buffer, "\tbitperchan=%d\n\n", harmony->data_format);
-	
-	snd_iprintf(buffer, "Play status:\n");
-	snd_iprintf(buffer, "\tstopped %d\n", harmony->ply_stopped);
-	snd_iprintf(buffer, "\tbuffer %lx, count %d\n", harmony->ply_buffer, harmony->ply_count);
-	snd_iprintf(buffer, "\tbuf %d size %d\n\n", harmony->ply_buf, harmony->ply_size);
-	
-	snd_iprintf(buffer, "Capture status:\n");
-	snd_iprintf(buffer, "\tstopped %d\n", harmony->cap_stopped);
-	snd_iprintf(buffer, "\tbuffer %lx, count %d\n", harmony->cap_buffer, harmony->cap_count);
-	snd_iprintf(buffer, "\tbuf %d, size %d\n\n", harmony->cap_buf, harmony->cap_size);
-
-	snd_iprintf(buffer, "Funny stats: total played=%d, recorded=%d\n\n", harmony->ply_total, harmony->cap_total);
-		
-	snd_iprintf(buffer, "Register:\n");
-	snd_iprintf(buffer, "\tgainctl: %lx\n", (unsigned long) gsc_readl(harmony->hpa+REG_GAINCTL));
-	snd_iprintf(buffer, "\tcntl: %lx\n", (unsigned long) gsc_readl(harmony->hpa+REG_CNTL));
-	snd_iprintf(buffer, "\tid: %lx\n", (unsigned long) gsc_readl(harmony->hpa+REG_ID));
-	snd_iprintf(buffer, "\tpcuradd: %lx\n", (unsigned long) gsc_readl(harmony->hpa+REG_PCURADD));
-	snd_iprintf(buffer, "\trcuradd: %lx\n", (unsigned long) gsc_readl(harmony->hpa+REG_RCURADD));
-	snd_iprintf(buffer, "\tpnxtadd: %lx\n", (unsigned long) gsc_readl(harmony->hpa+REG_PNXTADD));
-	snd_iprintf(buffer, "\trnxtadd: %lx\n", (unsigned long) gsc_readl(harmony->hpa+REG_RNXTADD));
-	snd_iprintf(buffer, "\tdstatus: %lx\n", (unsigned long) gsc_readl(harmony->hpa+REG_DSTATUS));
-	snd_iprintf(buffer, "\tov: %lx\n\n", (unsigned long) gsc_readl(harmony->hpa+REG_OV));
+	unsigned int i;
 	
-}
+	for (i = 0; i < ARRAY_SIZE(snd_harmony_rates); i++)
+		if (snd_harmony_rates[i] == rate)
+			return rate_bits[i];
+
+	return HARMONY_SR_44KHZ;
+}
+
+static snd_pcm_hardware_t snd_harmony_playback =
+{
+	.info =	(SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | 
+		 SNDRV_PCM_INFO_JOINT_DUPLEX | SNDRV_PCM_INFO_MMAP_VALID |
+		 SNDRV_PCM_INFO_BLOCK_TRANSFER),
+	.formats = (SNDRV_PCM_FMTBIT_S16_BE | SNDRV_PCM_FMTBIT_MU_LAW |
+		    SNDRV_PCM_FMTBIT_A_LAW),
+	.rates = (SNDRV_PCM_RATE_5512 | SNDRV_PCM_RATE_8000_48000 |
+		  SNDRV_PCM_RATE_KNOT),
+	.rate_min = 5512,
+	.rate_max = 48000,
+	.channels_min =	1,
+	.channels_max =	2,
+	.buffer_bytes_max = MAX_BUF_SIZE,
+	.period_bytes_min = BUF_SIZE,
+	.period_bytes_max = BUF_SIZE,
+	.periods_min = 1,
+	.periods_max = MAX_BUFS,
+	.fifo_size = 0,
+};
 
-static void __devinit snd_harmony_proc_init(snd_card_harmony_t *harmony)
+static snd_pcm_hardware_t snd_harmony_capture =
 {
-	snd_info_entry_t *entry;
-	
-	if (! snd_card_proc_new(harmony->card, "harmony", &entry))
-		snd_info_set_text_ops(entry, harmony, 2048, snd_harmony_proc_read);
-}
-
-/* 
- * PCM Stuff
- */
+        .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
+                 SNDRV_PCM_INFO_JOINT_DUPLEX | SNDRV_PCM_INFO_MMAP_VALID |
+                 SNDRV_PCM_INFO_BLOCK_TRANSFER),
+        .formats = (SNDRV_PCM_FMTBIT_S16_BE | SNDRV_PCM_FMTBIT_MU_LAW |
+                    SNDRV_PCM_FMTBIT_A_LAW),
+        .rates = (SNDRV_PCM_RATE_5512 | SNDRV_PCM_RATE_8000_48000 |
+		  SNDRV_PCM_RATE_KNOT),
+        .rate_min = 5512,
+        .rate_max = 48000,
+        .channels_min = 1,
+        .channels_max = 2,
+        .buffer_bytes_max = MAX_BUF_SIZE,
+        .period_bytes_min = BUF_SIZE,
+        .period_bytes_max = BUF_SIZE,
+        .periods_min = 1,
+        .periods_max = MAX_BUFS,
+        .fifo_size = 0,
+};
 
-static int snd_card_harmony_playback_ioctl(snd_pcm_substream_t * substream,
-				         unsigned int cmd,
-				         void *arg)
+static int
+snd_harmony_playback_trigger(snd_pcm_substream_t *ss, int cmd)
 {
-	return snd_pcm_lib_ioctl(substream, cmd, arg);
-}
+	harmony_t *h = snd_pcm_substream_chip(ss);
+	unsigned long flags;
 
-static int snd_card_harmony_capture_ioctl(snd_pcm_substream_t * substream,
-					unsigned int cmd,
-					void *arg)
-{
-	return snd_pcm_lib_ioctl(substream, cmd, arg);
-}
+	if (h->st.capturing)
+		return -EBUSY;
 
-static int snd_card_harmony_playback_trigger(snd_pcm_substream_t * substream,
-					   int cmd)
-{
-	snd_card_harmony_t *harmony = snd_pcm_substream_chip(substream);
-	
+	spin_lock_irqsave(&h->lock, flags);
 	switch (cmd) {
-		case SNDRV_PCM_TRIGGER_STOP:
-			if (harmony->ply_stopped) 
-				return -EBUSY;
-			harmony->ply_stopped = 1;
-			snd_harmony_disable_interrupts(harmony);
-			break;
-		case SNDRV_PCM_TRIGGER_START:
-			if (!harmony->ply_stopped)
-				return -EBUSY;
-			harmony->ply_stopped = 0;
-			/* write the location of the first buffer to play */
-			gsc_writel(harmony->ply_buffer, harmony->hpa+REG_PNXTADD);
-			snd_harmony_enable_interrupts(harmony);
-			break;
-		case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
-		case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
-		case SNDRV_PCM_TRIGGER_SUSPEND:
-			DPRINTK(KERN_INFO PFX "received unimplemented trigger: %d\n", cmd);
-		default:
-			return -EINVAL;
+	case SNDRV_PCM_TRIGGER_START:
+		h->st.playing = 1;
+		harmony_write(h, HARMONY_PNXTADD, h->pbuf.addr);
+		harmony_write(h, HARMONY_RNXTADD, h->gdma.addr);
+		harmony_unmute(h);
+		harmony_enable_interrupts(h);
+		break;
+	case SNDRV_PCM_TRIGGER_STOP:
+		h->st.playing = 0;
+		harmony_mute(h);
+		harmony_disable_interrupts(h);
+		break;
+	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+	case SNDRV_PCM_TRIGGER_SUSPEND:
+	default:
+		spin_unlock_irqrestore(&h->lock, flags);
+		snd_BUG();
+		return -EINVAL;
 	}
+	spin_unlock_irqrestore(&h->lock, flags);
+	
 	return 0;
 }
 
-static int snd_card_harmony_capture_trigger(snd_pcm_substream_t * substream,
-					  int cmd)
+static int
+snd_harmony_capture_trigger(snd_pcm_substream_t *ss, int cmd)
 {
-	snd_card_harmony_t *harmony = snd_pcm_substream_chip(substream);
-	
-	switch (cmd) {
-		case SNDRV_PCM_TRIGGER_STOP:
-			if (harmony->cap_stopped) 
-				return -EBUSY;
-			harmony->cap_stopped = 1;
-			snd_harmony_disable_interrupts(harmony);
-			break;
-		case SNDRV_PCM_TRIGGER_START:
-			if (!harmony->cap_stopped)
-				return -EBUSY;
-			harmony->cap_stopped = 0;
-			snd_harmony_enable_interrupts(harmony);
-			break;
-		case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
-		case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
-		case SNDRV_PCM_TRIGGER_SUSPEND:
-			DPRINTK(KERN_INFO PFX "Received unimplemented trigger: %d\n", cmd);
-		default:
-			return -EINVAL;
-	}
-	return 0;
+        harmony_t *h = snd_pcm_substream_chip(ss);
+	unsigned long flags;
+
+	if (h->st.playing)
+		return -EBUSY;
+
+	spin_lock_irqsave(&h->lock, flags);
+        switch (cmd) {
+        case SNDRV_PCM_TRIGGER_START:
+		h->st.capturing = 1;
+                harmony_write(h, HARMONY_PNXTADD, h->sdma.addr);
+                harmony_write(h, HARMONY_RNXTADD, h->cbuf.addr);
+		harmony_unmute(h);
+                harmony_enable_interrupts(h);
+		break;
+        case SNDRV_PCM_TRIGGER_STOP:
+		h->st.capturing = 0;
+                harmony_mute(h);
+                harmony_disable_interrupts(h);
+		break;
+        case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+        case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+        case SNDRV_PCM_TRIGGER_SUSPEND:
+	default:
+		spin_unlock_irqrestore(&h->lock, flags);
+		snd_BUG();
+                return -EINVAL;
+        }
+	spin_unlock_irqrestore(&h->lock, flags);
+		
+        return 0;
 }
 
-/* set data format */
-static int snd_harmony_set_data_format(snd_card_harmony_t *harmony, int pcm_format)
+static int
+snd_harmony_set_data_format(harmony_t *h, int fmt, int force)
 {
-	int old_format = harmony->data_format;
-	int new_format = old_format;
-	switch (pcm_format) {
+	int o = h->st.format;
+	int n;
+
+	switch(fmt) {
 	case SNDRV_PCM_FORMAT_S16_BE:
-		new_format = HARMONY_DF_16BIT_LINEAR;
+		n = HARMONY_DF_16BIT_LINEAR;
 		break;
 	case SNDRV_PCM_FORMAT_A_LAW:
-		new_format = HARMONY_DF_8BIT_ALAW;
+		n = HARMONY_DF_8BIT_ALAW;
 		break;
 	case SNDRV_PCM_FORMAT_MU_LAW:
-		new_format = HARMONY_DF_8BIT_ULAW;
+		n = HARMONY_DF_8BIT_ULAW;
+		break;
+	default:
+		n = HARMONY_DF_16BIT_LINEAR;
 		break;
 	}
-	/* re-initialize silence buffer if needed */
-	if (old_format != new_format)
-		snd_pcm_format_set_silence(pcm_format, harmony->silence_dma.area,
-					   (HARMONY_BUF_SIZE * SILENCE_BUFS * 8) / snd_pcm_format_width(pcm_format));
 
-	return new_format;
+	if (force || o != n) {
+		snd_pcm_format_set_silence(fmt, h->sdma.area,
+					   SILENCE_BUFSZ / 
+					   (snd_pcm_format_physical_width(fmt) / 8));
+	}
+
+	return n;
 }
 
-static int snd_card_harmony_playback_prepare(snd_pcm_substream_t * substream)
+static int
+snd_harmony_playback_prepare(snd_pcm_substream_t *ss)
 {
-	snd_card_harmony_t *harmony = snd_pcm_substream_chip(substream);
-	snd_pcm_runtime_t *runtime = substream->runtime;
+	harmony_t *h = snd_pcm_substream_chip(ss);
+	snd_pcm_runtime_t *rt = ss->runtime;
 	
-	harmony->ply_size 			= snd_pcm_lib_buffer_bytes(substream);
-	harmony->ply_count 			= snd_pcm_lib_period_bytes(substream);
-	harmony->ply_buf			= 0;
-	harmony->ply_stopped		= 1;
+	if (h->st.capturing)
+		return -EBUSY;
 	
-	/* initialize given sample rate */
-	harmony->sample_rate = snd_card_harmony_rate_bits(runtime->rate);
+	h->pbuf.size = snd_pcm_lib_buffer_bytes(ss);
+	h->pbuf.count = snd_pcm_lib_period_bytes(ss);
+	h->pbuf.buf = 0;
+	h->st.playing = 0;
 
-	/* data format */
-	harmony->data_format = snd_harmony_set_data_format(harmony, runtime->format);
-
-	/* number of channels */
-	if (runtime->channels == 2)
-		harmony->stereo_select = HARMONY_SS_STEREO;
-	else
-		harmony->stereo_select = HARMONY_SS_MONO;
-	
-	DPRINTK(KERN_INFO PFX "Playback_prepare, sr=%d(%x), df=%x, ss=%x hpa=%lx\n", runtime->rate,
-				harmony->sample_rate, harmony->data_format, harmony->stereo_select, harmony->hpa);
-	snd_harmony_update_control(harmony);
-	harmony->format_initialized = 1;
-	harmony->ply_buffer = runtime->dma_addr;
+	h->st.rate = snd_harmony_rate_bits(rt->rate);
+	h->st.format = snd_harmony_set_data_format(h, rt->format, 0);
 	
+	if (rt->channels == 2)
+		h->st.stereo = HARMONY_SS_STEREO;
+	else
+		h->st.stereo = HARMONY_SS_MONO;
+
+	harmony_set_control(h);
+
+	h->pbuf.addr = rt->dma_addr;
+
 	return 0;
 }
 
-static int snd_card_harmony_capture_prepare(snd_pcm_substream_t * substream)
+static int
+snd_harmony_capture_prepare(snd_pcm_substream_t *ss)
 {
-	snd_pcm_runtime_t *runtime = substream->runtime;
-	snd_card_harmony_t *harmony = snd_pcm_substream_chip(substream);
-	
-	harmony->cap_size 			= snd_pcm_lib_buffer_bytes(substream);
-	harmony->cap_count 			= snd_pcm_lib_period_bytes(substream);
-	harmony->cap_count			= 0;
-	harmony->cap_stopped		= 1;
-
-	/* initialize given sample rate */
-	harmony->sample_rate = snd_card_harmony_rate_bits(runtime->rate);
-	
-	/* data format */
-	harmony->data_format = snd_harmony_set_data_format(harmony, runtime->format);
-	
-	/* number of channels */
-	if (runtime->channels == 1)
-		harmony->stereo_select = HARMONY_SS_MONO;
-	else if (runtime->channels == 2)
-		harmony->stereo_select = HARMONY_SS_STEREO;
-		
-	snd_harmony_update_control(harmony);
-	harmony->format_initialized = 1;
-	
-	harmony->cap_buffer = runtime->dma_addr;
+        harmony_t *h = snd_pcm_substream_chip(ss);
+        snd_pcm_runtime_t *rt = ss->runtime;
 
-	return 0;
+	if (h->st.playing)
+		return -EBUSY;
+
+        h->cbuf.size = snd_pcm_lib_buffer_bytes(ss);
+        h->cbuf.count = snd_pcm_lib_period_bytes(ss);
+        h->cbuf.buf = 0;
+	h->st.capturing = 0;
+
+        h->st.rate = snd_harmony_rate_bits(rt->rate);
+        h->st.format = snd_harmony_set_data_format(h, rt->format, 0);
+
+        if (rt->channels == 2)
+                h->st.stereo = HARMONY_SS_STEREO;
+        else
+                h->st.stereo = HARMONY_SS_MONO;
+
+        harmony_set_control(h);
+
+        h->cbuf.addr = rt->dma_addr;
+
+        return 0;
 }
 
-static snd_pcm_uframes_t snd_card_harmony_capture_pointer(snd_pcm_substream_t * substream)
+static snd_pcm_uframes_t 
+snd_harmony_playback_pointer(snd_pcm_substream_t *ss)
 {
-	snd_pcm_runtime_t *runtime = substream->runtime;
-	snd_card_harmony_t *harmony = snd_pcm_substream_chip(substream);
-	unsigned long rcuradd;
-	int recorded;
-	
-	if (harmony->cap_stopped) return 0;
-	if (harmony->capture_substream == NULL) return 0;
-
-	rcuradd = gsc_readl(harmony->hpa+REG_RCURADD);
-	recorded = (rcuradd - harmony->cap_buffer);
-	recorded %= harmony->cap_size;
-		
-	return bytes_to_frames(runtime, recorded);
-}
+	snd_pcm_runtime_t *rt = ss->runtime;
+	harmony_t *h = snd_pcm_substream_chip(ss);
+	unsigned long pcuradd;
+	unsigned long played;
 
-/*
- */
+	if (!(h->st.playing) || (h->psubs == NULL)) 
+		return 0;
 
-static snd_pcm_uframes_t snd_card_harmony_playback_pointer(snd_pcm_substream_t * substream)
-{
-	snd_pcm_runtime_t *runtime = substream->runtime;
-	snd_card_harmony_t *harmony = snd_pcm_substream_chip(substream);
-	int played;
-	long int pcuradd = gsc_readl(harmony->hpa+REG_PCURADD);
-	
-	if ((harmony->ply_stopped) || (harmony->playback_substream == NULL)) return 0;
-	if ((harmony->ply_buffer == 0) || (harmony->ply_size == 0)) return 0;
-	
-	played = (pcuradd - harmony->ply_buffer);
-	
-	printk(KERN_DEBUG PFX "Pointer is %lx-%lx = %d\n", pcuradd, harmony->ply_buffer, played);	
-
-	if (pcuradd > harmony->ply_buffer + harmony->ply_size) return 0;
-	
-	return bytes_to_frames(runtime, played);
-}
-
-static snd_pcm_hardware_t snd_card_harmony_playback =
-{
-	.info =			(SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | 
-					SNDRV_PCM_INFO_JOINT_DUPLEX | 
-					SNDRV_PCM_INFO_MMAP_VALID |
-					SNDRV_PCM_INFO_BLOCK_TRANSFER),
-	.formats =		(SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_BE | 
-					SNDRV_PCM_FMTBIT_A_LAW | SNDRV_PCM_FMTBIT_MU_LAW),
-	.rates =		SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000,
-	.rate_min =		5500,
-	.rate_max =		48000,
-	.channels_min =		1,
-	.channels_max =		2,
-	.buffer_bytes_max =	MAX_BUFFER_SIZE,
-	.period_bytes_min =	HARMONY_BUF_SIZE,
-	.period_bytes_max =	HARMONY_BUF_SIZE,
-	.periods_min =		1,
-	.periods_max =		MAX_BUFS,
-	.fifo_size =		0,
-};
+	if ((h->pbuf.addr == 0) || (h->pbuf.size == 0))
+		return 0;
+	
+	pcuradd = harmony_read(h, HARMONY_PCURADD);
+	played = pcuradd - h->pbuf.addr;
+
+#ifdef HARMONY_DEBUG
+	printk(KERN_DEBUG PFX "playback_pointer is 0x%lx-0x%lx = %d bytes\n", 
+	       pcuradd, h->pbuf.addr, played);	
+#endif
+
+	if (pcuradd > h->pbuf.addr + h->pbuf.size) {
+		return 0;
+	}
+
+	return bytes_to_frames(rt, played);
+}
 
-static snd_pcm_hardware_t snd_card_harmony_capture =
+static snd_pcm_uframes_t
+snd_harmony_capture_pointer(snd_pcm_substream_t *ss)
 {
-	.info =			(SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | 
-					SNDRV_PCM_INFO_JOINT_DUPLEX | 
-					SNDRV_PCM_INFO_MMAP_VALID |
-					SNDRV_PCM_INFO_BLOCK_TRANSFER),
-	.formats =		(SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_BE | 
-					SNDRV_PCM_FMTBIT_A_LAW | SNDRV_PCM_FMTBIT_MU_LAW),
-	.rates =		SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000,
-	.rate_min =		5500,
-	.rate_max =		48000,
-	.channels_min =		1,
-	.channels_max =		2,
-	.buffer_bytes_max =	MAX_BUFFER_SIZE,
-	.period_bytes_min =	HARMONY_BUF_SIZE,
-	.period_bytes_max =	HARMONY_BUF_SIZE,
-	.periods_min =		1,
-	.periods_max =		MAX_BUFS,
-	.fifo_size =		0,
-};
+        snd_pcm_runtime_t *rt = ss->runtime;
+        harmony_t *h = snd_pcm_substream_chip(ss);
+        unsigned long rcuradd;
+        unsigned long caught;
+
+        if (!(h->st.capturing) || (h->csubs == NULL))
+                return 0;
+
+        if ((h->cbuf.addr == 0) || (h->cbuf.size == 0))
+                return 0;
+
+        rcuradd = harmony_read(h, HARMONY_RCURADD);
+        caught = rcuradd - h->cbuf.addr;
+
+#ifdef HARMONY_DEBUG
+        printk(KERN_DEBUG PFX "capture_pointer is 0x%lx-0x%lx = %d bytes\n",
+               rcuradd, h->cbuf.addr, caught);
+#endif
+
+        if (rcuradd > h->cbuf.addr + h->cbuf.size) {
+		return 0;
+	}
+
+        return bytes_to_frames(rt, caught);
+}
 
-static int snd_card_harmony_playback_open(snd_pcm_substream_t * substream)
+static int 
+snd_harmony_playback_open(snd_pcm_substream_t *ss)
 {
-	snd_card_harmony_t *harmony = snd_pcm_substream_chip(substream);
-	snd_pcm_runtime_t *runtime = substream->runtime;
+	harmony_t *h = snd_pcm_substream_chip(ss);
+	snd_pcm_runtime_t *rt = ss->runtime;
 	int err;
 	
-	harmony->playback_substream = substream;
-	runtime->hw = snd_card_harmony_playback;
-	snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hw_constraint_rates);
+	h->psubs = ss;
+	rt->hw = snd_harmony_playback;
+	snd_pcm_hw_constraint_list(rt, 0, SNDRV_PCM_HW_PARAM_RATE, 
+				   &hw_constraint_rates);
 	
-	if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0)
+	err = snd_pcm_hw_constraint_integer(rt, SNDRV_PCM_HW_PARAM_PERIODS);
+	if (err < 0)
 		return err;
 	
 	return 0;
 }
 
-static int snd_card_harmony_capture_open(snd_pcm_substream_t * substream)
+static int
+snd_harmony_capture_open(snd_pcm_substream_t *ss)
 {
-	snd_card_harmony_t *harmony = snd_pcm_substream_chip(substream);
-	snd_pcm_runtime_t *runtime = substream->runtime;
-	int err;
-	
-	harmony->capture_substream = substream;
-	runtime->hw = snd_card_harmony_capture;
-	snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hw_constraint_rates);
-	if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0)
-		return err;
-	return 0;
+        harmony_t *h = snd_pcm_substream_chip(ss);
+        snd_pcm_runtime_t *rt = ss->runtime;
+        int err;
+
+        h->csubs = ss;
+        rt->hw = snd_harmony_capture;
+        snd_pcm_hw_constraint_list(rt, 0, SNDRV_PCM_HW_PARAM_RATE,
+                                   &hw_constraint_rates);
 
+        err = snd_pcm_hw_constraint_integer(rt, SNDRV_PCM_HW_PARAM_PERIODS);
+        if (err < 0)
+                return err;
+
+        return 0;
 }
 
-static int snd_card_harmony_playback_close(snd_pcm_substream_t * substream)
+static int 
+snd_harmony_playback_close(snd_pcm_substream_t *ss)
 {
-	snd_card_harmony_t *harmony = snd_pcm_substream_chip(substream);
-	
-	harmony->playback_substream = NULL;
-	harmony->ply_size 			= 0;
-	harmony->ply_buf			= 0;
-	harmony->ply_buffer			= 0;
-	harmony->ply_count			= 0;
-	harmony->ply_stopped		= 1;
-	harmony->format_initialized = 0;
-	
+	harmony_t *h = snd_pcm_substream_chip(ss);
+	h->psubs = NULL;
 	return 0;
 }
 
-static int snd_card_harmony_capture_close(snd_pcm_substream_t * substream)
+static int
+snd_harmony_capture_close(snd_pcm_substream_t *ss)
 {
-	snd_card_harmony_t *harmony = snd_pcm_substream_chip(substream);
-	
-	harmony->capture_substream = NULL;
-	harmony->cap_size 			= 0;
-	harmony->cap_buf			= 0;
-	harmony->cap_buffer			= 0;
-	harmony->cap_count			= 0;
-	harmony->cap_stopped		= 1;
-	harmony->format_initialized = 0;
-	
-	return 0;
+        harmony_t *h = snd_pcm_substream_chip(ss);
+        h->csubs = NULL;
+        return 0;
 }
 
-static int snd_card_harmony_hw_params(snd_pcm_substream_t *substream, 
-	                   snd_pcm_hw_params_t * hw_params)
+static int 
+snd_harmony_hw_params(snd_pcm_substream_t *ss,
+		      snd_pcm_hw_params_t *hw)
 {
 	int err;
-	snd_card_harmony_t *harmony = snd_pcm_substream_chip(substream);
+	harmony_t *h = snd_pcm_substream_chip(ss);
+	
+	err = snd_pcm_lib_malloc_pages(ss, params_buffer_bytes(hw));
+	if (err > 0 && h->dma.type == SNDRV_DMA_TYPE_CONTINUOUS)
+		ss->runtime->dma_addr = __pa(ss->runtime->dma_area);
 	
-	err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
-	if (err > 0 && harmony->dma_dev.type == SNDRV_DMA_TYPE_CONTINUOUS)
-		substream->runtime->dma_addr = __pa(substream->runtime->dma_area);
-	DPRINTK(KERN_INFO PFX "HW Params returned %d, dma_addr %lx\n", err,
-			(unsigned long)substream->runtime->dma_addr);
 	return err;
 }
 
-static int snd_card_harmony_hw_free(snd_pcm_substream_t *substream) 
+static int 
+snd_harmony_hw_free(snd_pcm_substream_t *ss) 
 {
-	snd_pcm_lib_free_pages(substream);		
-	return 0;
+	return snd_pcm_lib_free_pages(ss);
 }
 
-static snd_pcm_ops_t snd_card_harmony_playback_ops = {
-	.open =			snd_card_harmony_playback_open,
-	.close =		snd_card_harmony_playback_close,
-	.ioctl =		snd_card_harmony_playback_ioctl,
-	.hw_params = 	snd_card_harmony_hw_params,
-	.hw_free = 		snd_card_harmony_hw_free,
-	.prepare =		snd_card_harmony_playback_prepare,
-	.trigger =		snd_card_harmony_playback_trigger,
- 	.pointer =		snd_card_harmony_playback_pointer,
+static snd_pcm_ops_t snd_harmony_playback_ops = {
+	.open =	snd_harmony_playback_open,
+	.close = snd_harmony_playback_close,
+	.ioctl = snd_pcm_lib_ioctl,
+	.hw_params = snd_harmony_hw_params,
+	.hw_free = snd_harmony_hw_free,
+	.prepare = snd_harmony_playback_prepare,
+	.trigger = snd_harmony_playback_trigger,
+ 	.pointer = snd_harmony_playback_pointer,
 };
 
-static snd_pcm_ops_t snd_card_harmony_capture_ops = {
-	.open =			snd_card_harmony_capture_open,
-	.close =		snd_card_harmony_capture_close,
-	.ioctl =		snd_card_harmony_capture_ioctl,
-	.hw_params = 	snd_card_harmony_hw_params,
-	.hw_free = 		snd_card_harmony_hw_free,
-	.prepare =		snd_card_harmony_capture_prepare,
-	.trigger =		snd_card_harmony_capture_trigger,
-	.pointer =		snd_card_harmony_capture_pointer,
+static snd_pcm_ops_t snd_harmony_capture_ops = {
+        .open = snd_harmony_capture_open,
+        .close = snd_harmony_capture_close,
+        .ioctl = snd_pcm_lib_ioctl,
+        .hw_params = snd_harmony_hw_params,
+        .hw_free = snd_harmony_hw_free,
+        .prepare = snd_harmony_capture_prepare,
+        .trigger = snd_harmony_capture_trigger,
+        .pointer = snd_harmony_capture_pointer,
 };
 
-static int snd_card_harmony_pcm_init(snd_card_harmony_t *harmony)
+static int 
+snd_harmony_pcm_init(harmony_t *h)
 {
 	snd_pcm_t *pcm;
 	int err;
 
-	/* Request that IRQ */
-	if (request_irq(harmony->irq, snd_card_harmony_interrupt, 0 ,"harmony", harmony)) {
-		printk(KERN_ERR PFX "Error requesting irq %d.\n", harmony->irq);
-		return -EFAULT;
-	}
+	harmony_disable_interrupts(h);
 	
-	snd_harmony_disable_interrupts(harmony);
-	
-   	if ((err = snd_pcm_new(harmony->card, "Harmony", 0, 1, 1, &pcm)) < 0)
+   	err = snd_pcm_new(h->card, "harmony", 0, 1, 1, &pcm);
+	if (err < 0)
 		return err;
 	
-	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_card_harmony_playback_ops);
- 	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_card_harmony_capture_ops); 
-	
-	pcm->private_data = harmony;
+	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, 
+			&snd_harmony_playback_ops);
+	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
+			&snd_harmony_capture_ops);
+
+	pcm->private_data = h;
 	pcm->info_flags = 0;
-	strcpy(pcm->name, "Harmony");
-	harmony->pcm = pcm;
+	strcpy(pcm->name, "harmony");
+	h->pcm = pcm;
+
+	h->psubs = NULL;
+	h->csubs = NULL;
 	
 	/* initialize graveyard buffer */
-	harmony->dma_dev.type = SNDRV_DMA_TYPE_DEV;
-	harmony->dma_dev.dev = &harmony->pa_dev->dev;
-	err = snd_dma_alloc_pages(harmony->dma_dev.type,
-				  harmony->dma_dev.dev,
-				  HARMONY_BUF_SIZE*GRAVEYARD_BUFS,
-				  &harmony->graveyard_dma);
-	if (err == -ENOMEM) {
-		/* use continuous buffers */
-		harmony->dma_dev.type = SNDRV_DMA_TYPE_CONTINUOUS;
-		harmony->dma_dev.dev = snd_dma_continuous_data(GFP_KERNEL);
-		err = snd_dma_alloc_pages(harmony->dma_dev.type,
-					  harmony->dma_dev.dev,
-					  HARMONY_BUF_SIZE*GRAVEYARD_BUFS,
-					  &harmony->graveyard_dma);
-	}
+	h->dma.type = SNDRV_DMA_TYPE_DEV;
+	h->dma.dev = &h->dev->dev;
+	err = snd_dma_alloc_pages(h->dma.type,
+				  h->dma.dev,
+				  BUF_SIZE*GRAVEYARD_BUFS,
+				  &h->gdma);
 	if (err < 0) {
-		printk(KERN_ERR PFX "can't allocate graveyard buffer\n");
+		printk(KERN_ERR PFX "cannot allocate graveyard buffer!\n");
 		return err;
 	}
-	harmony->graveyard_count = 0;
 	
 	/* initialize silence buffers */
-	err = snd_dma_alloc_pages(harmony->dma_dev.type,
-				  harmony->dma_dev.dev,
-				  HARMONY_BUF_SIZE*SILENCE_BUFS,
-				  &harmony->silence_dma);
+	err = snd_dma_alloc_pages(h->dma.type,
+				  h->dma.dev,
+				  BUF_SIZE*SILENCE_BUFS,
+				  &h->sdma);
 	if (err < 0) {
-		printk(KERN_ERR PFX "can't allocate silence buffer\n");
+		printk(KERN_ERR PFX "cannot allocate silence buffer!\n");
 		return err;
 	}
-	harmony->silence_count = 0;
 
-	if (harmony->dma_dev.type == SNDRV_DMA_TYPE_CONTINUOUS) {
-		harmony->graveyard_dma.addr = __pa(harmony->graveyard_dma.area);
-		harmony->silence_dma.addr = __pa(harmony->silence_dma.area);
-	}
-
-	harmony->ply_stopped = harmony->cap_stopped = 1;
-	
-	harmony->playback_substream = NULL;
-	harmony->capture_substream = NULL;
-	harmony->graveyard_count = 0;
-
-	err = snd_pcm_lib_preallocate_pages_for_all(pcm, harmony->dma_dev.type,
-						    harmony->dma_dev.dev,
-						    MAX_BUFFER_SIZE, MAX_BUFFER_SIZE);
+	/* pre-allocate space for DMA */
+	err = snd_pcm_lib_preallocate_pages_for_all(pcm, h->dma.type,
+						    h->dma.dev,
+						    MAX_BUF_SIZE, 
+						    MAX_BUF_SIZE);
 	if (err < 0) {
-		printk(KERN_ERR PFX "buffer allocation error %d\n", err);
-		// return err;
+		printk(KERN_ERR PFX "buffer allocation error: %d\n", err);
+		return err;
 	}
 
+	h->st.format = snd_harmony_set_data_format(h,
+		SNDRV_PCM_FORMAT_S16_BE, 1);
+
 	return 0;
 }
 
-/*
- * mixer routines
- */
-
-static void snd_harmony_set_new_gain(snd_card_harmony_t *harmony)
+static void 
+snd_harmony_set_new_gain(harmony_t *h)
 {
-	DPRINTK(KERN_INFO PFX "Setting new gain %x at %lx\n", harmony->current_gain, harmony->hpa+REG_GAINCTL);
-	/* Wait until we're out of control mode */
- 	snd_harmony_wait_cntl(harmony);
-	
-	gsc_writel(harmony->current_gain, harmony->hpa+REG_GAINCTL);
+ 	harmony_wait_for_control(h);
+	harmony_write(h, HARMONY_GAINCTL, h->st.gain);
 }
 
-#define HARMONY_VOLUME(xname, left_shift, right_shift, mask, invert) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
-  .info = snd_harmony_mixercontrol_info, \
-  .get = snd_harmony_volume_get, .put = snd_harmony_volume_put, \
-  .private_value = ((left_shift) | ((right_shift) << 8) | ((mask) << 16) | ((invert) << 24)) }
-
-static int snd_harmony_mixercontrol_info(snd_kcontrol_t * kcontrol, snd_ctl_elem_info_t * uinfo)
-{
-	int mask = (kcontrol->private_value >> 16) & 0xff;
-	int left_shift = (kcontrol->private_value) & 0xff;
-	int right_shift = (kcontrol->private_value >> 8) & 0xff;
+static int 
+snd_harmony_mixercontrol_info(snd_kcontrol_t *kc, 
+			      snd_ctl_elem_info_t *uinfo)
+{
+	int mask = (kc->private_value >> 16) & 0xff;
+	int left_shift = (kc->private_value) & 0xff;
+	int right_shift = (kc->private_value >> 8) & 0xff;
 	
-	uinfo->type = (mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER);
-	uinfo->count = (left_shift == right_shift) ? 1 : 2;
+	uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : 
+		       SNDRV_CTL_ELEM_TYPE_INTEGER;
+	uinfo->count = left_shift == right_shift ? 1 : 2;
 	uinfo->value.integer.min = 0;
 	uinfo->value.integer.max = mask;
+
 	return 0;
 }
- 
-static int snd_harmony_volume_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
-{
-	snd_card_harmony_t *harmony = snd_kcontrol_chip(kcontrol);
-	int shift_left = (kcontrol->private_value) & 0xff;
-	int shift_right = (kcontrol->private_value >> 8) & 0xff;
-	int mask = (kcontrol->private_value >> 16) & 0xff;
-	int invert = (kcontrol->private_value >> 24) & 0xff;
-	unsigned long flags;
+
+static int 
+snd_harmony_volume_get(snd_kcontrol_t *kc, 
+		       snd_ctl_elem_value_t *ucontrol)
+{
+	harmony_t *h = snd_kcontrol_chip(kc);
+	int shift_left = (kc->private_value) & 0xff;
+	int shift_right = (kc->private_value >> 8) & 0xff;
+	int mask = (kc->private_value >> 16) & 0xff;
+	int invert = (kc->private_value >> 24) & 0xff;
 	int left, right;
+	unsigned long flags;
 	
-	spin_lock_irqsave(&harmony->mixer_lock, flags);
-	left = (harmony->current_gain >> shift_left) & mask;
-	right = (harmony->current_gain >> shift_right) & mask;
+	spin_lock_irqsave(&h->mixer_lock, flags);
+
+	left = (h->st.gain >> shift_left) & mask;
+	right = (h->st.gain >> shift_right) & mask;
 
 	if (invert) {
 		left = mask - left;
@@ -910,21 +719,24 @@
 	}
 	ucontrol->value.integer.value[0] = left;
 	ucontrol->value.integer.value[1] = right;
-	spin_unlock_irqrestore(&harmony->mixer_lock, flags);
+
+	spin_unlock_irqrestore(&h->mixer_lock, flags);
 
 	return 0;
 }  
 
-static int snd_harmony_volume_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
-{
-	snd_card_harmony_t *harmony = snd_kcontrol_chip(kcontrol);
-	int shift_left = (kcontrol->private_value) & 0xff;
-	int shift_right = (kcontrol->private_value >> 8) & 0xff;
-	int mask = (kcontrol->private_value >> 16) & 0xff;
-	int invert = (kcontrol->private_value >> 24) & 0xff;
-	unsigned long flags;
+static int 
+snd_harmony_volume_put(snd_kcontrol_t *kc, 
+		       snd_ctl_elem_value_t *ucontrol)
+{
+	harmony_t *h = snd_kcontrol_chip(kc);
+	int shift_left = (kc->private_value) & 0xff;
+	int shift_right = (kc->private_value >> 8) & 0xff;
+	int mask = (kc->private_value >> 16) & 0xff;
+	int invert = (kc->private_value >> 24) & 0xff;
 	int left, right;
-	int old_gain = harmony->current_gain;
+	int old_gain = h->st.gain;
+	unsigned long flags;
 	
 	left = ucontrol->value.integer.value[0] & mask;
 	right = ucontrol->value.integer.value[1] & mask;
@@ -933,213 +745,249 @@
 		right = mask - right;
 	}
 	
-	spin_lock_irqsave(&harmony->mixer_lock, flags);
-	harmony->current_gain = harmony->current_gain & ~( (mask << shift_right) | (mask << shift_left));
- 	harmony->current_gain = harmony->current_gain | ((left << shift_left) | (right << shift_right) );
-	snd_harmony_set_new_gain(harmony);
-	spin_unlock_irqrestore(&harmony->mixer_lock, flags);
+	spin_lock_irqsave(&h->mixer_lock, flags);
+
+	h->st.gain &= ~( (mask << shift_right) | (mask << shift_left) );
+ 	h->st.gain |=  ( (left << shift_left) | (right << shift_right) );
+	snd_harmony_set_new_gain(h);
+
+	spin_unlock_irqrestore(&h->mixer_lock, flags);
 	
-	return (old_gain - harmony->current_gain);
+	return (old_gain - h->st.gain);
 }
 
-#define HARMONY_CONTROLS (sizeof(snd_harmony_controls)/sizeof(snd_kcontrol_new_t))
+#define HARMONY_CONTROLS (sizeof(snd_harmony_controls)/ \
+                          sizeof(snd_kcontrol_new_t))
+
+#define HARMONY_VOLUME(xname, left_shift, right_shift, mask, invert) \
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname,                \
+  .info = snd_harmony_mixercontrol_info,                             \
+  .get = snd_harmony_volume_get, .put = snd_harmony_volume_put,      \
+  .private_value = ((left_shift) | ((right_shift) << 8) |            \
+                   ((mask) << 16) | ((invert) << 24)) }
 
 static snd_kcontrol_new_t snd_harmony_controls[] = {
-HARMONY_VOLUME("PCM Capture Volume", 12, 16, 0x0f, 0),
-HARMONY_VOLUME("Master Volume", 20, 20, 0x0f, 1),
-HARMONY_VOLUME("PCM Playback Volume", 6, 0, 0x3f, 1),
+	HARMONY_VOLUME("Playback Volume", HARMONY_GAIN_LO_SHIFT, 
+		       HARMONY_GAIN_RO_SHIFT, HARMONY_GAIN_OUT, 1),
+	HARMONY_VOLUME("Capture Volume", HARMONY_GAIN_LI_SHIFT,
+		       HARMONY_GAIN_RI_SHIFT, HARMONY_GAIN_IN, 0),
 };
 
-static void __init snd_harmony_reset_codec(snd_card_harmony_t *harmony)
-{
- 	snd_harmony_wait_cntl(harmony);
-	gsc_writel(1, harmony->hpa+REG_RESET);
-	mdelay(50);		/* wait 50 ms */
-	gsc_writel(0, harmony->hpa+REG_RESET);
-}
-
-/*
- * Mute all the output and reset Harmony.
- */
-
-static void __init snd_harmony_mixer_reset(snd_card_harmony_t *harmony)
+static void __init 
+snd_harmony_mixer_reset(harmony_t *h)
 {
-	harmony->current_gain = HARMONY_GAIN_TOTAL_SILENCE;
-	snd_harmony_set_new_gain(harmony);
-	snd_harmony_reset_codec(harmony);
-	harmony->current_gain = HARMONY_GAIN_DEFAULT;
-	snd_harmony_set_new_gain(harmony);
+	harmony_mute(h);
+	harmony_reset(h);
+	h->st.gain = HARMONY_GAIN_DEFAULT;
+	harmony_unmute(h);
 }
 
-
-static int __init snd_card_harmony_mixer_init(snd_card_harmony_t *harmony)
+static int __init 
+snd_harmony_mixer_init(harmony_t *h)
 {
-	snd_card_t *card = harmony->card;
+	snd_card_t *card = h->card;
 	int idx, err;
 
-	snd_assert(harmony != NULL, return -EINVAL);
+	snd_assert(h != NULL, return -EINVAL);
 	strcpy(card->mixername, "Harmony Gain control interface");
 
 	for (idx = 0; idx < HARMONY_CONTROLS; idx++) {
-		if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_harmony_controls[idx], harmony))) < 0)
+		err = snd_ctl_add(card, 
+				  snd_ctl_new1(&snd_harmony_controls[idx], h));
+		if (err < 0)
 			return err;
 	}
 	
-	snd_harmony_mixer_reset(harmony);
+	snd_harmony_mixer_reset(h);
 
 	return 0;
 }
 
-static int snd_card_harmony_create(snd_card_t *card, struct parisc_device *pa_dev, snd_card_harmony_t *harmony)
+static int
+snd_harmony_free(harmony_t *h)
 {
-	u32	cntl;
-	
-	harmony->card = card;
-	
-	harmony->pa_dev = pa_dev;
+        if (h->gdma.addr)
+                snd_dma_free_pages(&h->gdma);
+        if (h->sdma.addr)
+                snd_dma_free_pages(&h->sdma);
 
-	/* Set the HPA of harmony */
-	harmony->hpa = pa_dev->hpa;
-	
-	harmony->irq = pa_dev->irq;
-	if (!harmony->irq) {
-		printk(KERN_ERR PFX "no irq found\n");
-		return -ENODEV;
-	}
+	if (h->irq >= 0)
+		free_irq(h->irq, h);
 
-	/* Grab the ID and revision from the device */
-	harmony->id = (gsc_readl(harmony->hpa+REG_ID)&0x00ff0000) >> 16;
-	if ((harmony->id | 1) != 0x15) {
-		printk(KERN_WARNING PFX "wrong harmony id 0x%02x\n", harmony->id);
-		return -EBUSY;
-	}
-	cntl = gsc_readl(harmony->hpa+REG_CNTL);
-	harmony->rev = (cntl>>20) & 0xff;
+	if (h->iobase)
+		iounmap(h->iobase);
 
-	printk(KERN_INFO "Lasi Harmony Audio driver h/w id %i, rev. %i at 0x%lx, IRQ %i\n",	harmony->id, harmony->rev, pa_dev->hpa, harmony->irq);
-	
-	/* Make sure the control bit isn't set, although I don't think it 
-	   ever is. */
-	if (cntl & HARMONY_CNTL_C) {
-		printk(KERN_WARNING PFX "CNTL busy\n");
-		harmony->hpa = 0;
-		return -EBUSY;
+	parisc_set_drvdata(h->dev, NULL);
+
+	kfree(h);
+	return 0;
+}
+
+static int
+snd_harmony_dev_free(snd_device_t *dev)
+{
+	harmony_t *h = dev->device_data;
+	return snd_harmony_free(h);
+}
+
+static int __devinit
+snd_harmony_create(snd_card_t *card, 
+		   struct parisc_device *padev, 
+		   harmony_t **rchip)
+{
+	int err;
+	harmony_t *h;
+	static snd_device_ops_t ops = {
+		.dev_free = snd_harmony_dev_free,
+	};
+
+	*rchip = NULL;
+
+	h = kmalloc(sizeof(*h), GFP_KERNEL);
+	if (h == NULL)
+		return -ENOMEM;
+
+	memset(&h->st, 0, sizeof(h->st));
+	memset(&h->stats, 0, sizeof(h->stats));
+	memset(&h->pbuf, 0, sizeof(h->pbuf));
+	memset(&h->cbuf, 0, sizeof(h->cbuf));
+
+	h->hpa = padev->hpa;
+	h->card = card;
+	h->dev = padev;
+	h->irq = padev->irq;
+	h->iobase = ioremap_nocache(padev->hpa, HARMONY_SIZE);
+	if (h->iobase == NULL) {
+		printk(KERN_ERR PFX "unable to remap hpa 0x%lx\n",
+		       padev->hpa);
+		err = -EBUSY;
+		goto free_and_ret;
 	}
-	
+		
+	err = request_irq(h->irq, snd_harmony_interrupt, 0,
+			  "harmony", h);
+	if (err) {
+		printk(KERN_ERR PFX "could not obtain interrupt %d",
+		       h->irq);
+		goto free_and_ret;
+	}
+
+	spin_lock_init(&h->mixer_lock);
+	spin_lock_init(&h->lock);
+
+        if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL,
+                                  h, &ops)) < 0) {
+                goto free_and_ret;
+        }
+
+	*rchip = h;
+
 	return 0;
+
+free_and_ret:
+	snd_harmony_free(h);
+	return err;
 }
-	
-static int __init snd_card_harmony_probe(struct parisc_device *pa_dev)
+
+static int __devinit
+snd_harmony_probe(struct parisc_device *padev)
 {
+	int err;
 	static int dev;
-	snd_card_harmony_t *chip;
 	snd_card_t *card;
-	int err;
-	
-	if (dev >= SNDRV_CARDS)
+	harmony_t *h;
+	static int index = SNDRV_DEFAULT_IDX1;
+	static char *id = SNDRV_DEFAULT_STR1;
+
+	h = parisc_get_drvdata(padev);
+	if (h != NULL) {
 		return -ENODEV;
-	if (!enable[dev]) {
-		dev++;
-		return -ENOENT;
 	}
-	
-	snd_harmony_cards[dev] = snd_card_new(index[dev], id[dev], THIS_MODULE,
-			    sizeof(snd_card_harmony_t));
-	card = snd_harmony_cards[dev];
-				
+
+	card = snd_card_new(index, id, THIS_MODULE, 0);
 	if (card == NULL)
 		return -ENOMEM;
-	chip = (struct snd_card_harmony *)card->private_data;
-	spin_lock_init(&chip->control_lock);
-	spin_lock_init(&chip->mixer_lock);
-	
-	if ((err = snd_card_harmony_create(card, pa_dev, chip)) < 0) {
-		printk(KERN_ERR PFX "Creation failed\n");
-		snd_card_free(card);
-		return err;
+
+	err = snd_harmony_create(card, padev, &h);
+	if (err < 0) {
+		goto free_and_ret;
 	}
-	if ((err = snd_card_harmony_pcm_init(chip)) < 0) {
-		printk(KERN_ERR PFX "PCM Init failed\n");
-		snd_card_free(card);
-		return err;
+
+	err = snd_harmony_pcm_init(h);
+	if (err < 0) {
+		goto free_and_ret;
 	}
-	if ((err = snd_card_harmony_mixer_init(chip)) < 0) {
-		printk(KERN_ERR PFX "Mixer init failed\n");
-		snd_card_free(card);
-		return err;
+
+	err = snd_harmony_mixer_init(h);
+	if (err < 0) {
+		goto free_and_ret;
 	}
-	
-	snd_harmony_proc_init(chip);
-	
-	strcpy(card->driver, "Harmony");
-	strcpy(card->shortname, "ALSA driver for LASI Harmony");
-	sprintf(card->longname, "%s at h/w, id %i, rev. %i hpa 0x%lx, IRQ %i\n",card->shortname, chip->id, chip->rev, pa_dev->hpa, chip->irq);
 
-	if ((err = snd_card_register(card)) < 0) {
-		snd_card_free(card);
-		return err;
+	strcpy(card->driver, "harmony");
+	strcpy(card->shortname, "Harmony");
+	sprintf(card->longname, "%s at 0x%lx, irq %i",
+		card->shortname, h->hpa, h->irq);
+
+	err = snd_card_register(card);
+	if (err < 0) {
+		goto free_and_ret;
 	}
 
-	printk(KERN_DEBUG PFX "Successfully registered harmony pcm backend & mixer %d\n", dev);
 	dev++;
-	return 0;
-}
+	parisc_set_drvdata(padev, h);
 
-static struct parisc_device_id snd_card_harmony_devicetbl[] = {
- { HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x0007A }, /* Bushmaster/Flounder */
- { HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x0007B }, /* 712/715 Audio */
- { HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x0007E }, /* Pace Audio */
- { HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x0007F }, /* Outfield / Coral II */
- { 0, }
-};
+	return 0;
 
-MODULE_DEVICE_TABLE(parisc, snd_card_harmony_devicetbl);
+free_and_ret:
+	snd_card_free(card);
+	return err;
+}
 
-/*
- * bloc device parisc. c'est une structure qui definit un device
- * que l'on trouve sur parisc. 
- * On y trouve les differents numeros HVERSION correspondant au device
- * en question (ce qui permet a l'inventory de l'identifier) et la fonction
- * d'initialisation du chose 
- */
+static int __devexit
+snd_harmony_remove(struct parisc_device *padev)
+{
+	harmony_t *h = parisc_get_drvdata(padev);
+	snd_card_free(h->card);
+	return 0;
+}
 
-static struct parisc_driver snd_card_harmony_driver = {
-	.name		= "Lasi ALSA Harmony",
-	.id_table	= snd_card_harmony_devicetbl,
-	.probe		= snd_card_harmony_probe,
+static struct parisc_driver snd_harmony_driver = {
+	.name = "harmony",
+	.id_table = snd_harmony_devtable,
+	.probe = snd_harmony_probe,
+	.remove = snd_harmony_remove,
 };
 
-static int __init alsa_card_harmony_init(void)
+static int __init 
+alsa_harmony_init(void)
 {
 	int err;
-	
-	if ((err = register_parisc_driver(&snd_card_harmony_driver)) < 0) {
-		printk(KERN_ERR "Harmony soundcard not found or device busy\n");
+
+	err = register_parisc_driver(&snd_harmony_driver);
+	if (err < 0) {
+		printk(KERN_ERR PFX "device not found\n");
 		return err;
 	}
 
 	return 0;
 }
 
-static void __exit alsa_card_harmony_exit(void)
+static void __exit
+alsa_harmony_fini(void)
 {
-	int idx;
-	snd_card_harmony_t *harmony;
+	int err;
+
+	err = unregister_parisc_driver(&snd_harmony_driver);
+	if (err < 0) {
+		printk(KERN_ERR PFX "failed to unregister\n");
+	}
 	
-	for (idx = 0; idx < SNDRV_CARDS; idx++)
-	{
-		if (snd_harmony_cards[idx] != NULL)
-		{	
-			DPRINTK(KERN_INFO PFX "Freeing card %d\n", idx);
-			harmony = snd_harmony_cards[idx]->private_data;
-			free_irq(harmony->irq, harmony);
-			printk(KERN_INFO PFX "Card unloaded %d, irq=%d\n", idx, harmony->irq);
-			snd_card_free(snd_harmony_cards[idx]);
-		}
-	}	
-	if (unregister_parisc_driver(&snd_card_harmony_driver) < 0)
-		printk(KERN_ERR PFX "Failed to unregister Harmony driver\n");
+	return;
 }
 
-module_init(alsa_card_harmony_init)
-module_exit(alsa_card_harmony_exit)
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Kyle McMartin <kyle@parisc-linux.org>");
+MODULE_DESCRIPTION("Harmony sound driver");
+
+module_init(alsa_harmony_init);
+module_exit(alsa_harmony_fini);
diff -Nru a/sound/parisc/harmony.h b/sound/parisc/harmony.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/sound/parisc/harmony.h	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,151 @@
+/* Hewlett-Packard Harmony audio driver
+ * Copyright (C) 2004, Kyle McMartin <kyle@parisc-linux.org>
+ */
+
+#ifndef __HARMONY_H__
+#define __HARMONY_H__
+
+struct harmony_buffer {
+        unsigned long addr;
+        int buf;
+        int count;
+        int size;
+        int coherent;
+};
+
+typedef struct snd_card_harmony {
+        int irq;
+
+        unsigned long hpa; /* hard physical address */
+        void __iomem *iobase; /* remapped io address */
+
+        struct parisc_device *dev;
+
+        struct {
+                u32 gain;
+                u32 rate;
+                u32 format;
+                u32 stereo;
+		int playing;
+		int capturing;
+        } st;
+
+        struct snd_dma_device dma; /* playback/capture */
+        struct harmony_buffer pbuf;
+	struct harmony_buffer cbuf;
+
+        struct snd_dma_buffer gdma; /* graveyard */
+        struct snd_dma_buffer sdma; /* silence */
+
+        struct {
+                unsigned long play_intr;
+	        unsigned long rec_intr;
+                unsigned long graveyard_intr;
+                unsigned long silence_intr;
+        } stats;
+
+        snd_pcm_t *pcm;
+        snd_card_t *card;
+        snd_pcm_substream_t *psubs;
+	snd_pcm_substream_t *csubs;
+        snd_info_entry_t *proc;
+
+        spinlock_t lock;
+        spinlock_t mixer_lock;
+} harmony_t;
+
+#define MAX_PCM_DEVICES     1
+#define MAX_PCM_SUBSTREAMS  4
+#define MAX_MIDI_DEVICES    0
+
+#define HARMONY_SIZE       64
+
+#define BUF_SIZE     PAGE_SIZE
+#define MAX_BUFS     10
+#define MAX_BUF_SIZE (MAX_BUFS * BUF_SIZE)
+
+#define PLAYBACK_BUFS    MAX_BUFS
+#define RECORD_BUFS      MAX_BUFS
+#define GRAVEYARD_BUFS   1
+#define GRAVEYARD_BUFSZ  (GRAVEYARD_BUFS*BUF_SIZE)
+#define SILENCE_BUFS     1
+#define SILENCE_BUFSZ    (SILENCE_BUFS*BUF_SIZE)
+
+#define HARMONY_ID       0x000
+#define HARMONY_RESET    0x004
+#define HARMONY_CNTL     0x008
+#define HARMONY_GAINCTL  0x00c
+#define HARMONY_PNXTADD  0x010
+#define HARMONY_PCURADD  0x014
+#define HARMONY_RNXTADD  0x018
+#define HARMONY_RCURADD  0x01c
+#define HARMONY_DSTATUS  0x020
+#define HARMONY_OV       0x024
+#define HARMONY_PIO      0x028
+#define HARMONY_DIAG     0x03c
+
+#define HARMONY_CNTL_C          0x80000000
+#define HARMONY_CNTL_ST         0x00000020
+#define HARMONY_CNTL_44100      0x00000015      /* HARMONY_SR_44KHZ */
+#define HARMONY_CNTL_8000       0x00000008      /* HARMONY_SR_8KHZ */
+
+#define HARMONY_DSTATUS_ID      0x00000000 /* interrupts off */
+#define HARMONY_DSTATUS_PN      0x00000200 /* playback fill */
+#define HARMONY_DSTATUS_RN      0x00000002 /* record fill */
+#define HARMONY_DSTATUS_IE      0x80000000 /* interrupts on */
+
+#define HARMONY_DF_16BIT_LINEAR 0x00000000
+#define HARMONY_DF_8BIT_ULAW    0x00000001
+#define HARMONY_DF_8BIT_ALAW    0x00000002
+
+#define HARMONY_SS_MONO         0x00000000
+#define HARMONY_SS_STEREO       0x00000001
+
+#define HARMONY_GAIN_SILENCE    0x00F00FFF
+#define HARMONY_GAIN_DEFAULT    0x0FF00000
+
+#define HARMONY_GAIN_HE_SHIFT   27
+#define HARMONY_GAIN_HE_MASK    (1 << HARMONY_GAIN_HE_SHIFT)
+#define HARMONY_GAIN_LE_SHIFT   26
+#define HARMONY_GAIN_LE_MASK    (1 << HARMONY_GAIN_LE_SHIFT)
+#define HARMONY_GAIN_SE_SHIFT   25
+#define HARMONY_GAIN_SE_MASK    (1 << HARMONY_GAIN_SE_SHIFT)
+#define HARMONY_GAIN_IS_SHIFT   24
+#define HARMONY_GAIN_IS_MASK    (1 << HARMONY_GAIN_IS_SHIFT)
+
+#define HARMONY_GAIN_MA         0x0f
+#define HARMONY_GAIN_MA_SHIFT   20
+#define HARMONY_GAIN_MA_MASK    (HARMONY_GAIN_MA << HARMONY_GAIN_MA_SHIFT)
+
+#define HARMONY_GAIN_IN         0x0f
+#define HARMONY_GAIN_LI_SHIFT   16
+#define HARMONY_GAIN_LI_MASK    (HARMONY_GAIN_IN << HARMONY_GAIN_LI_SHIFT)
+#define HARMONY_GAIN_RI_SHIFT   12
+#define HARMONY_GAIN_RI_MASK    (HARMONY_GAIN_IN << HARMONY_GAIN_RI_SHIFT)
+
+#define HARMONY_GAIN_OUT        0x3f
+#define HARMONY_GAIN_LO_SHIFT   6
+#define HARMONY_GAIN_LO_MASK    (HARMONY_GAIN_OUT << HARMONY_GAIN_LO_SHIFT)
+#define HARMONY_GAIN_RO_SHIFT   0
+#define HARMONY_GAIN_RO_MASK    (HARMONY_GAIN_OUT << HARMONY_GAIN_RO_SHIFT)
+
+#define HARMONY_MAX_OUT (HARMONY_GAIN_RO_MASK >> HARMONY_GAIN_RO_SHIFT)
+#define HARMONY_MAX_IN  (HARMONY_GAIN_RI_MASK >> HARMONY_GAIN_RI_SHIFT)
+#define HARMONY_MAX_MON (HARMONY_GAIN_MA_MASK >> HARMONY_GAIN_MA_SHIFT)
+
+#define HARMONY_SR_8KHZ         0x08
+#define HARMONY_SR_16KHZ        0x09
+#define HARMONY_SR_27KHZ        0x0A
+#define HARMONY_SR_32KHZ        0x0B
+#define HARMONY_SR_48KHZ        0x0E
+#define HARMONY_SR_9KHZ         0x0F
+#define HARMONY_SR_5KHZ         0x10
+#define HARMONY_SR_11KHZ        0x11
+#define HARMONY_SR_18KHZ        0x12
+#define HARMONY_SR_22KHZ        0x13
+#define HARMONY_SR_37KHZ        0x14
+#define HARMONY_SR_44KHZ        0x15
+#define HARMONY_SR_33KHZ        0x16
+#define HARMONY_SR_6KHZ         0x17
+
+#endif /* __HARMONY_H__ */
diff -Nru a/sound/pci/Kconfig b/sound/pci/Kconfig
--- a/sound/pci/Kconfig	2005-03-11 12:51:42 -08:00
+++ b/sound/pci/Kconfig	2005-03-11 12:51:42 -08:00
@@ -514,5 +514,15 @@
 	  To compile this driver as a module, choose M here: the module
 	  will be called snd-vx222.
 
-endmenu
+config SND_HDA_INTEL
+	tristate "Intel HD Audio"
+	depends on SND
+	select SND_PCM
+	help
+	  Say Y here to include support for Intel "High Definition
+	  Audio" (Azalia) motherboard devices.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called snd-hda-intel.
 
+endmenu
diff -Nru a/sound/pci/Makefile b/sound/pci/Makefile
--- a/sound/pci/Makefile	2005-03-11 12:51:40 -08:00
+++ b/sound/pci/Makefile	2005-03-11 12:51:40 -08:00
@@ -53,6 +53,7 @@
 	ca0106/ \
 	cs46xx/ \
 	emu10k1/ \
+	hda/ \
 	ice1712/ \
 	korg1212/ \
 	mixart/ \
diff -Nru a/sound/pci/ac97/ac97_codec.c b/sound/pci/ac97/ac97_codec.c
--- a/sound/pci/ac97/ac97_codec.c	2005-03-11 12:51:52 -08:00
+++ b/sound/pci/ac97/ac97_codec.c	2005-03-11 12:51:52 -08:00
@@ -56,6 +56,7 @@
 	const char *name;
 	int (*patch)(ac97_t *ac97);
 	int (*mpatch)(ac97_t *ac97);
+	unsigned int flags;
 } ac97_codec_id_t;
 
 static const ac97_codec_id_t snd_ac97_codec_id_vendors[] = {
@@ -103,6 +104,7 @@
 { 0x41445372, 0xffffffff, "AD1981A",		patch_ad1981a,	NULL },
 { 0x41445374, 0xffffffff, "AD1981B",		patch_ad1981b,	NULL },
 { 0x41445375, 0xffffffff, "AD1985",		patch_ad1985,	NULL },
+{ 0x41445378, 0xffffffff, "AD1986",		patch_ad1985,	NULL },
 { 0x414c4300, 0xffffff00, "ALC100/100P", 	NULL,		NULL },
 { 0x414c4710, 0xfffffff0, "ALC200/200P",	NULL,		NULL },
 { 0x414c4721, 0xffffffff, "ALC650D",		NULL,	NULL }, /* already patched */
@@ -161,6 +163,7 @@
 { 0x574d4C05, 0xffffffff, "WM9705/WM9710",	patch_wolfson05, NULL},
 { 0x574d4C09, 0xffffffff, "WM9709",		NULL,		NULL},
 { 0x574d4C12, 0xffffffff, "WM9711/WM9712",	patch_wolfson11, NULL},
+{ 0x574d4c13, 0xffffffff, "WM9713/WM9714",	patch_wolfson13, NULL, AC97_DEFAULT_POWER_OFF},
 { 0x594d4800, 0xffffffff, "YMF743",		NULL,		NULL },
 { 0x594d4802, 0xffffffff, "YMF752",		NULL,		NULL },
 { 0x594d4803, 0xffffffff, "YMF753",		patch_yamaha_ymf753,	NULL },
@@ -438,111 +441,81 @@
 }
 
 /*
- *
+ * Controls
  */
 
-static int snd_ac97_info_mux(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+int snd_ac97_info_enum_double(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
 {
-	static char *texts[8] = {
-		"Mic", "CD", "Video", "Aux", "Line",
-		"Mix", "Mix Mono", "Phone"
-	};
-
+	struct ac97_enum *e = (struct ac97_enum *)kcontrol->private_value;
+	
 	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
-	uinfo->count = 2;
-	uinfo->value.enumerated.items = 8;
-	if (uinfo->value.enumerated.item > 7)
-		uinfo->value.enumerated.item = 7;
-	strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
-	return 0;
-}
-
-static int snd_ac97_get_mux(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
-{
-	ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
-	unsigned short val;
+	uinfo->count = e->shift_l == e->shift_r ? 1 : 2;
+	uinfo->value.enumerated.items = e->mask;
 	
-	val = snd_ac97_read_cache(ac97, AC97_REC_SEL);
-	ucontrol->value.enumerated.item[0] = (val >> 8) & 7;
-	ucontrol->value.enumerated.item[1] = (val >> 0) & 7;
+	if (uinfo->value.enumerated.item > e->mask - 1)
+		uinfo->value.enumerated.item = e->mask - 1;
+	strcpy(uinfo->value.enumerated.name, e->texts[uinfo->value.enumerated.item]);
 	return 0;
 }
 
-static int snd_ac97_put_mux(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+int snd_ac97_get_enum_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
 	ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
+	struct ac97_enum *e = (struct ac97_enum *)kcontrol->private_value;
 	unsigned short val;
 	
-	if (ucontrol->value.enumerated.item[0] > 7 ||
-	    ucontrol->value.enumerated.item[1] > 7)
-		return -EINVAL;
-	val = (ucontrol->value.enumerated.item[0] << 8) |
-	      (ucontrol->value.enumerated.item[1] << 0);
-	return snd_ac97_update(ac97, AC97_REC_SEL, val);
-}
-
-#define AC97_ENUM_DOUBLE(xname, reg, shift, invert) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .info = snd_ac97_info_enum_double, \
-  .get = snd_ac97_get_enum_double, .put = snd_ac97_put_enum_double, \
-  .private_value = reg | (shift << 8) | (invert << 24) }
-
-static int snd_ac97_info_enum_double(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
-{
-	static char *texts1[2] = { "pre 3D", "post 3D" };
-	static char *texts2[2] = { "Mix", "Mic" };
-	static char *texts3[2] = { "Mic1", "Mic2" };
-	char **texts = NULL;
-	int reg = kcontrol->private_value & 0xff;
-	int shift = (kcontrol->private_value >> 8) & 0xff;
+	val = snd_ac97_read_cache(ac97, e->reg);
+	ucontrol->value.enumerated.item[0] = (val >> e->shift_l) & (e->mask - 1);
+	if (e->shift_l != e->shift_r)
+		ucontrol->value.enumerated.item[1] = (val >> e->shift_r) & (e->mask - 1);
 
-	switch (reg) {
-	case AC97_GENERAL_PURPOSE:
-		switch (shift) {
-		case 15: texts = texts1; break;
-		case 9: texts = texts2; break;
-		case 8: texts = texts3; break;
-		}
-	}
-	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
-	uinfo->count = 1;
-	uinfo->value.enumerated.items = 2;
-	if (uinfo->value.enumerated.item > 1)
-		uinfo->value.enumerated.item = 1;
-	strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
 	return 0;
 }
 
-static int snd_ac97_get_enum_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+int snd_ac97_put_enum_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
 	ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
+	struct ac97_enum *e = (struct ac97_enum *)kcontrol->private_value;
 	unsigned short val;
-	int reg = kcontrol->private_value & 0xff;
-	int shift = (kcontrol->private_value >> 8) & 0xff;
-	int invert = (kcontrol->private_value >> 24) & 0xff;
+	unsigned short mask;
 	
-	val = (snd_ac97_read_cache(ac97, reg) >> shift) & 1;
-	if (invert)
-		val ^= 1;
-	ucontrol->value.enumerated.item[0] = val;
-	return 0;
+	if (ucontrol->value.enumerated.item[0] > e->mask - 1)
+		return -EINVAL;
+	val = ucontrol->value.enumerated.item[0] << e->shift_l;
+	mask = (e->mask - 1) << e->shift_l;
+	if (e->shift_l != e->shift_r) {
+		if (ucontrol->value.enumerated.item[1] > e->mask - 1)
+			return -EINVAL;
+		val |= ucontrol->value.enumerated.item[1] << e->shift_r;
+		mask |= (e->mask - 1) << e->shift_r;
+	}
+	return snd_ac97_update_bits(ac97, e->reg, mask, val);
+}
+
+/* save/restore ac97 v2.3 paging */
+static int snd_ac97_page_save(ac97_t *ac97, int reg, snd_kcontrol_t *kcontrol)
+{
+	int page_save = -1;
+	if ((kcontrol->private_value & (1<<25)) &&
+	    (ac97->ext_id & AC97_EI_REV_MASK) >= AC97_EI_REV_23 &&
+	    (reg >= 0x60 && reg < 0x70)) {
+		unsigned short page = (kcontrol->private_value >> 26) & 0x0f;
+		down(&ac97->page_mutex); /* lock paging */
+		page_save = snd_ac97_read(ac97, AC97_INT_PAGING) & AC97_PAGE_MASK;
+		snd_ac97_update_bits(ac97, AC97_INT_PAGING, AC97_PAGE_MASK, page);
+	}
+	return page_save;
 }
 
-static int snd_ac97_put_enum_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static void snd_ac97_page_restore(ac97_t *ac97, int page_save)
 {
-	ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
-	unsigned short val;
-	int reg = kcontrol->private_value & 0xff;
-	int shift = (kcontrol->private_value >> 8) & 0xff;
-	int invert = (kcontrol->private_value >> 24) & 0xff;
-	
-	if (ucontrol->value.enumerated.item[0] > 1)
-		return -EINVAL;
-	val = !!ucontrol->value.enumerated.item[0];
-	if (invert)
-		val = !val;
-	return snd_ac97_update_bits(ac97, reg, 1 << shift, val << shift);
+	if (page_save >= 0) {
+		snd_ac97_update_bits(ac97, AC97_INT_PAGING, AC97_PAGE_MASK, page_save);
+		up(&ac97->page_mutex); /* unlock paging */
+	}
 }
 
+/* volume and switch controls */
 int snd_ac97_info_volsw(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
 {
 	int mask = (kcontrol->private_value >> 16) & 0xff;
@@ -564,7 +537,9 @@
 	int rshift = (kcontrol->private_value >> 12) & 0x0f;
 	int mask = (kcontrol->private_value >> 16) & 0xff;
 	int invert = (kcontrol->private_value >> 24) & 0x01;
-	
+	int page_save;
+
+	page_save = snd_ac97_page_save(ac97, reg, kcontrol);
 	ucontrol->value.integer.value[0] = (snd_ac97_read_cache(ac97, reg) >> shift) & mask;
 	if (shift != rshift)
 		ucontrol->value.integer.value[1] = (snd_ac97_read_cache(ac97, reg) >> rshift) & mask;
@@ -573,6 +548,7 @@
 		if (shift != rshift)
 			ucontrol->value.integer.value[1] = mask - ucontrol->value.integer.value[1];
 	}
+	snd_ac97_page_restore(ac97, page_save);
 	return 0;
 }
 
@@ -584,8 +560,10 @@
 	int rshift = (kcontrol->private_value >> 12) & 0x0f;
 	int mask = (kcontrol->private_value >> 16) & 0xff;
 	int invert = (kcontrol->private_value >> 24) & 0x01;
+	int err, page_save;
 	unsigned short val, val2, val_mask;
 	
+	page_save = snd_ac97_page_save(ac97, reg, kcontrol);
 	val = (ucontrol->value.integer.value[0] & mask);
 	if (invert)
 		val = mask - val;
@@ -598,48 +576,11 @@
 		val_mask |= mask << rshift;
 		val |= val2 << rshift;
 	}
-	return snd_ac97_update_bits(ac97, reg, val_mask, val);
-}
-
-#define AC97_DOUBLE(xname, reg, shift_left, shift_right, mask, invert) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), .info = snd_ac97_info_volsw, \
-  .get = snd_ac97_get_volsw, .put = snd_ac97_put_volsw, \
-  .private_value = (reg) | ((shift_left) << 8) | ((shift_right) << 12) | ((mask) << 16) | ((invert) << 24) }
-
-static int snd_ac97_getput_page(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol,
-			 int (*func)(snd_kcontrol_t *, snd_ctl_elem_value_t *))
-{
-	ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
-	int reg = kcontrol->private_value & 0xff;
-	int err;
-
-	if ((ac97->ext_id & AC97_EI_REV_MASK) >= AC97_EI_REV_23 &&
-	    (reg >= 0x60 && reg < 0x70)) {
-		unsigned short page_save;
-		unsigned short page = (kcontrol->private_value >> 25) & 0x0f;
-		down(&ac97->page_mutex); /* lock paging */
-		page_save = snd_ac97_read(ac97, AC97_INT_PAGING) & AC97_PAGE_MASK;
-		snd_ac97_update_bits(ac97, AC97_INT_PAGING, AC97_PAGE_MASK, page);
-		err = func(kcontrol, ucontrol);
-		snd_ac97_update_bits(ac97, AC97_INT_PAGING, AC97_PAGE_MASK, page_save);
-		up(&ac97->page_mutex); /* unlock paging */
-	} else
-		err = func(kcontrol, ucontrol);
+	err = snd_ac97_update_bits(ac97, reg, val_mask, val);
+	snd_ac97_page_restore(ac97, page_save);
 	return err;
 }
 
-/* for rev2.3 paging */
-int snd_ac97_page_get_volsw(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
-{
-	return snd_ac97_getput_page(kcontrol, ucontrol, snd_ac97_get_volsw);
-}
-
-/* for rev2.3 paging */
-int snd_ac97_page_put_volsw(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
-{
-	return snd_ac97_getput_page(kcontrol, ucontrol, snd_ac97_put_volsw);
-}
-
 static const snd_kcontrol_new_t snd_ac97_controls_master_mono[2] = {
 AC97_SINGLE("Master Mono Playback Switch", AC97_MASTER_MONO, 15, 1, 1),
 AC97_SINGLE("Master Mono Playback Volume", AC97_MASTER_MONO, 0, 31, 1)
@@ -659,14 +600,21 @@
 	AC97_SINGLE("Mic Boost (+20dB)", AC97_MIC, 6, 1, 0);
 
 
-static const snd_kcontrol_new_t snd_ac97_control_capture_src = {
-	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-	.name = "Capture Source",
-	.info = snd_ac97_info_mux,
-	.get = snd_ac97_get_mux,
-	.put = snd_ac97_put_mux,
+static const char* std_rec_sel[] = {"Mic", "CD", "Video", "Aux", "Line", "Mix", "Mix Mono", "Phone"};
+static const char* std_3d_path[] = {"pre 3D", "post 3D"};
+static const char* std_mix[] = {"Mix", "Mic"};
+static const char* std_mic[] = {"Mic1", "Mic2"};
+
+static const struct ac97_enum std_enum[] = {
+AC97_ENUM_DOUBLE(AC97_REC_SEL, 8, 0, 8, std_rec_sel),
+AC97_ENUM_SINGLE(AC97_GENERAL_PURPOSE, 15, 2, std_3d_path),
+AC97_ENUM_SINGLE(AC97_GENERAL_PURPOSE, 9, 2, std_mix),
+AC97_ENUM_SINGLE(AC97_GENERAL_PURPOSE, 8, 2, std_mic),
 };
 
+static const snd_kcontrol_new_t snd_ac97_control_capture_src = 
+AC97_ENUM("Capture Source", std_enum[0]); 
+
 static const snd_kcontrol_new_t snd_ac97_control_capture_vol =
 AC97_DOUBLE("Capture Volume", AC97_REC_GAIN, 8, 0, 15, 0);
 
@@ -686,12 +634,12 @@
 } ac97_general_index_t;
 
 static const snd_kcontrol_new_t snd_ac97_controls_general[7] = {
-AC97_ENUM_DOUBLE("PCM Out Path & Mute", AC97_GENERAL_PURPOSE, 15, 0),
+AC97_ENUM("PCM Out Path & Mute", std_enum[1]),
 AC97_SINGLE("Simulated Stereo Enhancement", AC97_GENERAL_PURPOSE, 14, 1, 0),
 AC97_SINGLE("3D Control - Switch", AC97_GENERAL_PURPOSE, 13, 1, 0),
 AC97_SINGLE("Loudness (bass boost)", AC97_GENERAL_PURPOSE, 12, 1, 0),
-AC97_ENUM_DOUBLE("Mono Output Select", AC97_GENERAL_PURPOSE, 9, 0),
-AC97_ENUM_DOUBLE("Mic Select", AC97_GENERAL_PURPOSE, 8, 0),
+AC97_ENUM("Mono Output Select", std_enum[2]),
+AC97_ENUM("Mic Select", std_enum[3]),
 AC97_SINGLE("ADC/DAC Loopback", AC97_GENERAL_PURPOSE, 7, 1, 0)
 };
 
@@ -1185,7 +1133,7 @@
 /*
  * create mute switch(es) for normal stereo controls
  */
-static int snd_ac97_cmute_new(snd_card_t *card, char *name, int reg, ac97_t *ac97)
+static int snd_ac97_cmute_new_stereo(snd_card_t *card, char *name, int reg, int check_stereo, ac97_t *ac97)
 {
 	snd_kcontrol_t *kctl;
 	int err;
@@ -1196,7 +1144,7 @@
 
 	mute_mask = 0x8000;
 	val = snd_ac97_read(ac97, reg);
-	if (ac97->flags & AC97_STEREO_MUTES) {
+	if (check_stereo || (ac97->flags & AC97_STEREO_MUTES)) {
 		/* check whether both mute bits work */
 		val1 = val | 0x8080;
 		snd_ac97_write(ac97, reg, val1);
@@ -1254,7 +1202,7 @@
 /*
  * create a mute-switch and a volume for normal stereo/mono controls
  */
-static int snd_ac97_cmix_new(snd_card_t *card, const char *pfx, int reg, ac97_t *ac97)
+static int snd_ac97_cmix_new_stereo(snd_card_t *card, const char *pfx, int reg, int check_stereo, ac97_t *ac97)
 {
 	int err;
 	char name[44];
@@ -1265,7 +1213,7 @@
 
 	if (snd_ac97_try_bit(ac97, reg, 15)) {
 		sprintf(name, "%s Switch", pfx);
-		if ((err = snd_ac97_cmute_new(card, name, reg, ac97)) < 0)
+		if ((err = snd_ac97_cmute_new_stereo(card, name, reg, check_stereo, ac97)) < 0)
 			return err;
 	}
 	check_volume_resolution(ac97, reg, &lo_max, &hi_max);
@@ -1277,6 +1225,8 @@
 	return 0;
 }
 
+#define snd_ac97_cmix_new(card, pfx, reg, ac97)	snd_ac97_cmix_new_stereo(card, pfx, reg, 0, ac97)
+#define snd_ac97_cmute_new(card, name, reg, ac97)	snd_ac97_cmute_new_stereo(card, name, reg, 0, ac97)
 
 static unsigned int snd_ac97_determine_spdif_rates(ac97_t *ac97);
 
@@ -1327,7 +1277,8 @@
 
 	/* build surround controls */
 	if (snd_ac97_try_volume_mix(ac97, AC97_SURROUND_MASTER)) {
-		if ((err = snd_ac97_cmix_new(card, "Surround Playback", AC97_SURROUND_MASTER, ac97)) < 0)
+		/* Surround Master (0x38) is with stereo mutes */
+		if ((err = snd_ac97_cmix_new_stereo(card, "Surround Playback", AC97_SURROUND_MASTER, 1, ac97)) < 0)
 			return err;
 	}
 
@@ -1357,8 +1308,9 @@
 	}
 	
 	/* build PC Speaker controls */
-	if ((ac97->flags & AC97_HAS_PC_BEEP) ||
-	    snd_ac97_try_volume_mix(ac97, AC97_PC_BEEP)) {
+	if (!(ac97->flags & AC97_HAS_NO_PC_BEEP) && 
+		((ac97->flags & AC97_HAS_PC_BEEP) ||
+	    snd_ac97_try_volume_mix(ac97, AC97_PC_BEEP))) {
 		for (idx = 0; idx < 2; idx++)
 			if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_pc_beep[idx], ac97))) < 0)
 				return err;
@@ -1367,9 +1319,11 @@
 	}
 	
 	/* build Phone controls */
-	if (snd_ac97_try_volume_mix(ac97, AC97_PHONE)) {
-		if ((err = snd_ac97_cmix_new(card, "Phone Playback", AC97_PHONE, ac97)) < 0)
-			return err;
+	if (!(ac97->flags & AC97_HAS_NO_PHONE)) {
+		if (snd_ac97_try_volume_mix(ac97, AC97_PHONE)) {
+			if ((err = snd_ac97_cmix_new(card, "Phone Playback", AC97_PHONE, ac97)) < 0)
+				return err;
+		}
 	}
 	
 	/* build MIC controls */
@@ -1387,15 +1341,19 @@
 	}
 	
 	/* build CD controls */
-	if (snd_ac97_try_volume_mix(ac97, AC97_CD)) {
-		if ((err = snd_ac97_cmix_new(card, "CD Playback", AC97_CD, ac97)) < 0)
-			return err;
+	if (!(ac97->flags & AC97_HAS_NO_CD)) {
+		if (snd_ac97_try_volume_mix(ac97, AC97_CD)) {
+			if ((err = snd_ac97_cmix_new(card, "CD Playback", AC97_CD, ac97)) < 0)
+				return err;
+		}
 	}
 	
 	/* build Video controls */
-	if (snd_ac97_try_volume_mix(ac97, AC97_VIDEO)) {
-		if ((err = snd_ac97_cmix_new(card, "Video Playback", AC97_VIDEO, ac97)) < 0)
-			return err;
+	if (!(ac97->flags & AC97_HAS_NO_VIDEO)) {
+		if (snd_ac97_try_volume_mix(ac97, AC97_VIDEO)) {
+			if ((err = snd_ac97_cmix_new(card, "Video Playback", AC97_VIDEO, ac97)) < 0)
+				return err;
+		}
 	}
 
 	/* build Aux controls */
@@ -1441,17 +1399,18 @@
 	}
 
 	/* build Capture controls */
-	if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_control_capture_src, ac97))) < 0)
-		return err;
-	if (snd_ac97_try_bit(ac97, AC97_REC_GAIN, 15)) {
-		if ((err = snd_ac97_cmute_new(card, "Capture Switch", AC97_REC_GAIN, ac97)) < 0)
+	if (!(ac97->flags & AC97_HAS_NO_REC_GAIN)) {
+		if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_control_capture_src, ac97))) < 0)
 			return err;
+		if (snd_ac97_try_bit(ac97, AC97_REC_GAIN, 15)) {
+			if ((err = snd_ac97_cmute_new(card, "Capture Switch", AC97_REC_GAIN, ac97)) < 0)
+				return err;
+		}
+		if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_control_capture_vol, ac97))) < 0)
+			return err;
+		snd_ac97_write_cache(ac97, AC97_REC_SEL, 0x0000);
+		snd_ac97_write_cache(ac97, AC97_REC_GAIN, 0x0000);
 	}
-	if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_control_capture_vol, ac97))) < 0)
-		return err;
-	snd_ac97_write_cache(ac97, AC97_REC_SEL, 0x0000);
-	snd_ac97_write_cache(ac97, AC97_REC_GAIN, 0x0000);
-
 	/* build MIC Capture controls */
 	if (snd_ac97_try_volume_mix(ac97, AC97_REC_GAIN_MIC)) {
 		for (idx = 0; idx < 2; idx++)
@@ -1593,6 +1552,7 @@
 static void snd_ac97_determine_rates(ac97_t *ac97, int reg, int shadow_reg, unsigned int *r_result)
 {
 	unsigned int result = 0;
+	unsigned short saved;
 
 	if (ac97->bus->no_vra) {
 		*r_result = SNDRV_PCM_RATE_48000;
@@ -1602,6 +1562,7 @@
 		return;
 	}
 
+	saved = snd_ac97_read(ac97, reg);
 	if ((ac97->ext_id & AC97_EI_DRA) && reg == AC97_PCM_FRONT_DAC_RATE)
 		snd_ac97_update_bits(ac97, AC97_EXTENDED_STATUS,
 				     AC97_EA_DRA, 0);
@@ -1640,6 +1601,10 @@
 		snd_ac97_update_bits(ac97, AC97_EXTENDED_STATUS,
 				     AC97_EA_DRA, 0);
 	}
+	/* restore the default value */
+	snd_ac97_write_cache(ac97, reg, saved);
+	if (shadow_reg)
+		snd_ac97_write_cache(ac97, shadow_reg, saved);
 	*r_result = result;
 }
 
@@ -1663,6 +1628,18 @@
 	return result;
 }
 
+/* look for the codec id table matching with the given id */
+static const ac97_codec_id_t *look_for_codec_id(const ac97_codec_id_t *table,
+						unsigned int id)
+{
+	const ac97_codec_id_t *pid;
+
+	for (pid = table; pid->id; pid++)
+		if (pid->id == (id & pid->mask))
+			return pid;
+	return NULL;
+}
+
 void snd_ac97_get_name(ac97_t *ac97, unsigned int id, char *name, int modem)
 {
 	const ac97_codec_id_t *pid;
@@ -1671,35 +1648,30 @@
 		printable(id >> 24),
 		printable(id >> 16),
 		printable(id >> 8));
-	for (pid = snd_ac97_codec_id_vendors; pid->id; pid++)
-		if (pid->id == (id & pid->mask)) {
-			strcpy(name, pid->name);
-			if (ac97) {
-				if (!modem && pid->patch)
-					pid->patch(ac97);
-				else if (modem && pid->mpatch)
-					pid->mpatch(ac97);
-			} 
-			goto __vendor_ok;
-		}
-	return;
+	pid = look_for_codec_id(snd_ac97_codec_id_vendors, id);
+	if (! pid)
+		return;
 
-      __vendor_ok:
-	for (pid = snd_ac97_codec_ids; pid->id; pid++)
-		if (pid->id == (id & pid->mask)) {
-			strcat(name, " ");
-			strcat(name, pid->name);
-			if (pid->mask != 0xffffffff)
-				sprintf(name + strlen(name), " rev %d", id & ~pid->mask);
-			if (ac97) {
-				if (!modem && pid->patch)
-					pid->patch(ac97);
-				else if (modem && pid->mpatch)
-					pid->mpatch(ac97);
-			}
-			return;
+	strcpy(name, pid->name);
+	if (ac97 && pid->patch) {
+		if ((modem && (pid->flags & AC97_MODEM_PATCH)) ||
+		    (! modem && ! (pid->flags & AC97_MODEM_PATCH)))
+			pid->patch(ac97);
+	} 
+
+	pid = look_for_codec_id(snd_ac97_codec_ids, id);
+	if (pid) {
+		strcat(name, " ");
+		strcat(name, pid->name);
+		if (pid->mask != 0xffffffff)
+			sprintf(name + strlen(name), " rev %d", id & ~pid->mask);
+		if (ac97 && pid->patch) {
+			if ((modem && (pid->flags & AC97_MODEM_PATCH)) ||
+			    (! modem && ! (pid->flags & AC97_MODEM_PATCH)))
+				pid->patch(ac97);
 		}
-	sprintf(name + strlen(name), " id %x", id & 0xff);
+	} else
+		sprintf(name + strlen(name), " id %x", id & 0xff);
 }
 
 /**
@@ -1841,6 +1813,7 @@
 	char name[64];
 	unsigned long end_time;
 	unsigned int reg;
+	const ac97_codec_id_t *pid;
 	static snd_device_ops_t ops = {
 		.dev_free =	snd_ac97_dev_free,
 	};
@@ -1891,6 +1864,14 @@
 		goto __access_ok;
 	}
 
+	ac97->id = snd_ac97_read(ac97, AC97_VENDOR_ID1) << 16;
+	ac97->id |= snd_ac97_read(ac97, AC97_VENDOR_ID2);
+	if (ac97->id && ac97->id != (unsigned int)-1) {
+		pid = look_for_codec_id(snd_ac97_codec_ids, ac97->id);
+		if (pid && (pid->flags & AC97_DEFAULT_POWER_OFF))
+			goto __access_ok;
+	}
+
 	snd_ac97_write(ac97, AC97_RESET, 0);	/* reset to defaults */
 	if (bus->ops->wait)
 		bus->ops->wait(ac97);
@@ -1917,6 +1898,9 @@
 		snd_ac97_free(ac97);
 		return -EIO;
 	}
+	pid = look_for_codec_id(snd_ac97_codec_ids, ac97->id);
+	if (pid)
+		ac97->flags |= pid->flags;
 	
 	/* test for AC'97 */
 	if (!(ac97->scaps & AC97_SCAP_SKIP_AUDIO) && !(ac97->scaps & AC97_SCAP_AUDIO)) {
@@ -1955,10 +1939,12 @@
 	if (ac97_is_audio(ac97)) {
 		/* nothing should be in powerdown mode */
 		snd_ac97_write_cache(ac97, AC97_POWERDOWN, 0);
-		snd_ac97_write_cache(ac97, AC97_RESET, 0);		/* reset to defaults */
-		udelay(100);
+		if (! (ac97->flags & AC97_DEFAULT_POWER_OFF)) {
+			snd_ac97_write_cache(ac97, AC97_RESET, 0); /* reset to defaults */
+			udelay(100);
+			snd_ac97_write_cache(ac97, AC97_POWERDOWN, 0);
+		}
 		/* nothing should be in powerdown mode */
-		snd_ac97_write_cache(ac97, AC97_POWERDOWN, 0);
 		snd_ac97_write_cache(ac97, AC97_GENERAL_PURPOSE, 0);
 		end_time = jiffies + (HZ / 10);
 		do {
@@ -2225,9 +2211,11 @@
 	}
 
 	snd_ac97_write(ac97, AC97_POWERDOWN, 0);
-	snd_ac97_write(ac97, AC97_RESET, 0);
-	udelay(100);
-	snd_ac97_write(ac97, AC97_POWERDOWN, 0);
+	if (! (ac97->flags & AC97_DEFAULT_POWER_OFF)) {
+		snd_ac97_write(ac97, AC97_RESET, 0);
+		udelay(100);
+		snd_ac97_write(ac97, AC97_POWERDOWN, 0);
+	}
 	snd_ac97_write(ac97, AC97_GENERAL_PURPOSE, 0);
 
 	snd_ac97_write(ac97, AC97_POWERDOWN, ac97->regs[AC97_POWERDOWN]);
@@ -2331,6 +2319,35 @@
 	return -ENOENT;
 }
 
+#if 1
+/* bind hp and master controls instead of using only hp control */
+static int bind_hp_volsw_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+	int err = snd_ac97_put_volsw(kcontrol, ucontrol);
+	if (err > 0) {
+		unsigned long priv_saved = kcontrol->private_value;
+		kcontrol->private_value = (kcontrol->private_value & ~0xff) | AC97_HEADPHONE;
+		snd_ac97_put_volsw(kcontrol, ucontrol);
+		kcontrol->private_value = priv_saved;
+	}
+	return err;
+}
+
+/* ac97 tune: bind Master and Headphone controls */
+static int tune_hp_only(ac97_t *ac97)
+{
+	snd_kcontrol_t *msw = ctl_find(ac97, "Master Playback Switch", NULL);
+	snd_kcontrol_t *mvol = ctl_find(ac97, "Master Playback Volume", NULL);
+	if (! msw || ! mvol)
+		return -ENOENT;
+	msw->put = bind_hp_volsw_put;
+	mvol->put = bind_hp_volsw_put;
+	snd_ac97_remove_ctl(ac97, "Headphone Playback", "Switch");
+	snd_ac97_remove_ctl(ac97, "Headphone Playback", "Volume");
+	return 0;
+}
+
+#else
 /* ac97 tune: use Headphone control as master */
 static int tune_hp_only(ac97_t *ac97)
 {
@@ -2341,6 +2358,7 @@
 	snd_ac97_rename_vol_ctl(ac97, "Headphone Playback", "Master Playback");
 	return 0;
 }
+#endif
 
 /* ac97 tune: swap Headphone and Master controls */
 static int tune_swap_hp(ac97_t *ac97)
@@ -2472,7 +2490,7 @@
 	}
 	/* for compatibility, accept the numbers, too */
 	if (*typestr >= '0' && *typestr <= '9')
-		return apply_quirk(ac97, (int)simple_strtol(typestr, NULL, 10));
+		return apply_quirk(ac97, (int)simple_strtoul(typestr, NULL, 10));
 	return -EINVAL;
 }
 
diff -Nru a/sound/pci/ac97/ac97_local.h b/sound/pci/ac97/ac97_local.h
--- a/sound/pci/ac97/ac97_local.h	2005-03-11 12:51:42 -08:00
+++ b/sound/pci/ac97/ac97_local.h	2005-03-11 12:51:42 -08:00
@@ -23,15 +23,28 @@
  */
 
 #define AC97_SINGLE_VALUE(reg,shift,mask,invert) ((reg) | ((shift) << 8) | ((shift) << 12) | ((mask) << 16) | ((invert) << 24))
-#define AC97_PAGE_SINGLE_VALUE(reg,shift,mask,invert,page) (AC97_SINGLE_VALUE(reg,shift,mask,invert) | ((page) << 25))
+#define AC97_PAGE_SINGLE_VALUE(reg,shift,mask,invert,page) (AC97_SINGLE_VALUE(reg,shift,mask,invert) | (1<<25) | ((page) << 26))
 #define AC97_SINGLE(xname, reg, shift, mask, invert) \
 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .info = snd_ac97_info_volsw, \
   .get = snd_ac97_get_volsw, .put = snd_ac97_put_volsw, \
   .private_value =  AC97_SINGLE_VALUE(reg, shift, mask, invert) }
 #define AC97_PAGE_SINGLE(xname, reg, shift, mask, invert, page)		\
 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .info = snd_ac97_info_volsw, \
-  .get = snd_ac97_page_get_volsw, .put = snd_ac97_page_put_volsw, \
+  .get = snd_ac97_get_volsw, .put = snd_ac97_put_volsw, \
   .private_value =  AC97_PAGE_SINGLE_VALUE(reg, shift, mask, invert, page) }
+#define AC97_DOUBLE(xname, reg, shift_left, shift_right, mask, invert) \
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), .info = snd_ac97_info_volsw, \
+  .get = snd_ac97_get_volsw, .put = snd_ac97_put_volsw, \
+  .private_value = (reg) | ((shift_left) << 8) | ((shift_right) << 12) | ((mask) << 16) | ((invert) << 24) }
+#define AC97_ENUM_DOUBLE(xreg, xshift_l, xshift_r, xmask, xtexts) \
+{ .reg = xreg, .shift_l = xshift_l, .shift_r = xshift_r, \
+  .mask = xmask, .texts = xtexts }
+#define AC97_ENUM_SINGLE(xreg, xshift, xmask, xtexts) \
+	AC97_ENUM_DOUBLE(xreg, xshift, xshift, xmask, xtexts)
+#define AC97_ENUM(xname, xenum) \
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .info = snd_ac97_info_enum_double, \
+  .get = snd_ac97_get_enum_double, .put = snd_ac97_put_enum_double, \
+  .private_value = (unsigned long)&xenum }
 
 /* ac97_codec.c */
 extern const char *snd_ac97_stereo_enhancements[];
@@ -42,8 +55,6 @@
 int snd_ac97_info_volsw(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo);
 int snd_ac97_get_volsw(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol);
 int snd_ac97_put_volsw(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol);
-int snd_ac97_page_get_volsw(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol);
-int snd_ac97_page_put_volsw(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol);
 int snd_ac97_try_bit(ac97_t * ac97, int reg, int bit);
 int snd_ac97_remove_ctl(ac97_t *ac97, const char *name, const char *suffix);
 int snd_ac97_rename_ctl(ac97_t *ac97, const char *src, const char *dst, const char *suffix);
@@ -51,6 +62,9 @@
 void snd_ac97_rename_vol_ctl(ac97_t *ac97, const char *src, const char *dst);
 void snd_ac97_restore_status(ac97_t *ac97);
 void snd_ac97_restore_iec958(ac97_t *ac97);
+int snd_ac97_info_enum_double(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo);
+int snd_ac97_get_enum_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol);
+int snd_ac97_put_enum_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol);
 
 int snd_ac97_update_bits_nolock(ac97_t *ac97, unsigned short reg,
 				unsigned short mask, unsigned short value);
diff -Nru a/sound/pci/ac97/ac97_patch.c b/sound/pci/ac97/ac97_patch.c
--- a/sound/pci/ac97/ac97_patch.c	2005-03-11 12:51:51 -08:00
+++ b/sound/pci/ac97/ac97_patch.c	2005-03-11 12:51:51 -08:00
@@ -305,6 +305,136 @@
 	return 0;
 }
 
+static const char* wm9713_mic_mixer[] = {"Stereo", "Mic1", "Mic2", "Mute"};
+static const char* wm9713_rec_mux[] = {"Stereo", "Left", "Right", "Mute"};
+static const char* wm9713_rec_src_l[] = {"Mic1", "Mic2", "Line L", "Mono In", "HP Mix L", "Spk Mix", "Mono Mix", "Zh"};
+static const char* wm9713_rec_src_r[] = {"Mic1", "Mic2", "Line R", "Mono In", "HP Mix R", "Spk Mix", "Mono Mix", "Zh"};
+
+static const struct ac97_enum wm9713_enum[] = {
+AC97_ENUM_SINGLE(AC97_LINE, 3, 4, wm9713_mic_mixer),
+AC97_ENUM_SINGLE(AC97_VIDEO, 14, 4, wm9713_rec_mux),
+AC97_ENUM_SINGLE(AC97_VIDEO, 9, 4, wm9713_rec_mux),
+AC97_ENUM_SINGLE(AC97_VIDEO, 3, 8, wm9713_rec_src_l),
+AC97_ENUM_SINGLE(AC97_VIDEO, 0, 8, wm9713_rec_src_r),
+};
+
+static const snd_kcontrol_new_t wm13_snd_ac97_controls_line_in[] = {
+AC97_DOUBLE("Line In Volume", AC97_PC_BEEP, 8, 0, 31, 1),
+AC97_SINGLE("Line In to Headphone Mute", AC97_PC_BEEP, 15, 1, 1),
+AC97_SINGLE("Line In to Speaker Mute", AC97_PC_BEEP, 14, 1, 1),
+AC97_SINGLE("Line In to Mono Mute", AC97_PC_BEEP, 13, 1, 1),
+};
+
+static const snd_kcontrol_new_t wm13_snd_ac97_controls_dac[] = {
+AC97_DOUBLE("DAC Volume", AC97_PHONE, 8, 0, 31, 1),
+AC97_SINGLE("DAC to Headphone Mute", AC97_PHONE, 15, 1, 1),
+AC97_SINGLE("DAC to Speaker Mute", AC97_PHONE, 14, 1, 1),
+AC97_SINGLE("DAC to Mono Mute", AC97_PHONE, 13, 1, 1),
+};
+
+static const snd_kcontrol_new_t wm13_snd_ac97_controls_mic[] = {
+AC97_SINGLE("MICA Volume", AC97_MIC, 8, 31, 1),
+AC97_SINGLE("MICB Volume", AC97_MIC, 0, 31, 1),
+AC97_SINGLE("MICA to Mono Mute", AC97_LINE, 7, 1, 1),
+AC97_SINGLE("MICB to Mono Mute", AC97_LINE, 6, 1, 1),
+AC97_SINGLE("MIC Boost (+20dB)", AC97_LINE, 5, 1, 1),
+AC97_ENUM("MIC Headphone Routing", wm9713_enum[0]),
+AC97_SINGLE("MIC Headphone Mixer Volume", AC97_LINE, 0, 7, 1)
+};
+
+static const snd_kcontrol_new_t wm13_snd_ac97_controls_adc[] = {
+AC97_SINGLE("ADC Mute", AC97_CD, 15, 1, 1),
+AC97_DOUBLE("Gain Step Size (1.5dB/0.75dB)", AC97_CD, 14, 6, 1, 1),
+AC97_DOUBLE("ADC Volume",AC97_CD, 8, 0, 15, 0),
+AC97_SINGLE("ADC Zero Cross", AC97_CD, 7, 1, 1),
+};
+
+static const snd_kcontrol_new_t wm13_snd_ac97_controls_recsel[] = {
+AC97_ENUM("Record to Headphone Path", wm9713_enum[1]),
+AC97_SINGLE("Record to Headphone Volume", AC97_VIDEO, 11, 7, 0),
+AC97_ENUM("Record to Mono Path", wm9713_enum[2]),
+AC97_SINGLE("Record to Mono Boost (+20dB)", AC97_VIDEO, 8, 1, 0),
+AC97_SINGLE("Record ADC Boost (+20dB)", AC97_VIDEO, 6, 1, 0),
+AC97_ENUM("Record Select Left", wm9713_enum[3]),
+AC97_ENUM("Record Select Right", wm9713_enum[4]),
+};
+
+static int patch_wolfson_wm9713_specific(ac97_t * ac97)
+{
+	int err, i;
+	
+	for (i = 0; i < ARRAY_SIZE(wm13_snd_ac97_controls_line_in); i++) {
+		if ((err = snd_ctl_add(ac97->bus->card, snd_ac97_cnew(&wm13_snd_ac97_controls_line_in[i], ac97))) < 0)
+			return err;
+	}
+	snd_ac97_write_cache(ac97, AC97_PC_BEEP, 0x0808);
+	
+	for (i = 0; i < ARRAY_SIZE(wm13_snd_ac97_controls_dac); i++) {
+		if ((err = snd_ctl_add(ac97->bus->card, snd_ac97_cnew(&wm13_snd_ac97_controls_dac[i], ac97))) < 0)
+			return err;
+	}
+	snd_ac97_write_cache(ac97, AC97_PHONE, 0x0808);
+	
+	for (i = 0; i < ARRAY_SIZE(wm13_snd_ac97_controls_mic); i++) {
+		if ((err = snd_ctl_add(ac97->bus->card, snd_ac97_cnew(&wm13_snd_ac97_controls_mic[i], ac97))) < 0)
+			return err;
+	}
+	snd_ac97_write_cache(ac97, AC97_MIC, 0x0808);
+	snd_ac97_write_cache(ac97, AC97_LINE, 0x00da);
+	
+	for (i = 0; i < ARRAY_SIZE(wm13_snd_ac97_controls_adc); i++) {
+		if ((err = snd_ctl_add(ac97->bus->card, snd_ac97_cnew(&wm13_snd_ac97_controls_adc[i], ac97))) < 0)
+			return err;
+	}
+	snd_ac97_write_cache(ac97, AC97_CD, 0x0808);
+	
+	for (i = 0; i < ARRAY_SIZE(wm13_snd_ac97_controls_recsel); i++) {
+		if ((err = snd_ctl_add(ac97->bus->card, snd_ac97_cnew(&wm13_snd_ac97_controls_recsel[i], ac97))) < 0)
+			return err;
+	}
+	snd_ac97_write_cache(ac97, AC97_VIDEO, 0xd612);
+	snd_ac97_write_cache(ac97, AC97_REC_GAIN, 0x1ba0);
+	
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static void patch_wolfson_wm9713_suspend (ac97_t * ac97)
+{
+	snd_ac97_write_cache(ac97, AC97_EXTENDED_MID, 0xfeff);
+	snd_ac97_write_cache(ac97, AC97_EXTENDED_MSTATUS, 0xffff);
+}
+
+static void patch_wolfson_wm9713_resume (ac97_t * ac97)
+{
+	snd_ac97_write_cache(ac97, AC97_EXTENDED_MID, 0xda00);
+	snd_ac97_write_cache(ac97, AC97_EXTENDED_MSTATUS, 0x3810);
+	snd_ac97_write_cache(ac97, AC97_POWERDOWN, 0x0);
+}
+#endif
+
+static struct snd_ac97_build_ops patch_wolfson_wm9713_ops = {
+	.build_specific = patch_wolfson_wm9713_specific,
+#ifdef CONFIG_PM	
+	.suspend = patch_wolfson_wm9713_suspend,
+	.resume = patch_wolfson_wm9713_resume
+#endif
+};
+
+int patch_wolfson13(ac97_t * ac97)
+{
+	ac97->build_ops = &patch_wolfson_wm9713_ops;
+
+	ac97->flags |= AC97_HAS_NO_REC_GAIN | AC97_STEREO_MUTES | AC97_HAS_NO_PHONE |
+		AC97_HAS_NO_PC_BEEP | AC97_HAS_NO_VIDEO | AC97_HAS_NO_CD;
+
+	snd_ac97_write_cache(ac97, AC97_EXTENDED_MID, 0xda00);
+	snd_ac97_write_cache(ac97, AC97_EXTENDED_MSTATUS, 0x3810);
+	snd_ac97_write_cache(ac97, AC97_POWERDOWN, 0x0);
+
+	return 0;
+}
+
 /*
  * Tritech codec
  */
@@ -392,9 +522,36 @@
 	return 0;
 }
 
+static int snd_ac97_stac9708_put_bias(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+	ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
+	int err;
+
+	down(&ac97->page_mutex);
+	snd_ac97_write(ac97, AC97_SIGMATEL_BIAS1, 0xabba);
+	err = snd_ac97_update_bits(ac97, AC97_SIGMATEL_BIAS2, 0x0010,
+				   (ucontrol->value.integer.value[0] & 1) << 4);
+	snd_ac97_write(ac97, AC97_SIGMATEL_BIAS1, 0);
+	up(&ac97->page_mutex);
+	return err;
+}
+
+static const snd_kcontrol_new_t snd_ac97_stac9708_bias_control = {
+	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+	.name = "Sigmatel Output Bias Switch",
+	.info = snd_ac97_info_volsw,
+	.get = snd_ac97_get_volsw,
+	.put = snd_ac97_stac9708_put_bias,
+	.private_value = AC97_SINGLE_VALUE(AC97_SIGMATEL_BIAS2, 4, 1, 0),
+};
+
 static int patch_sigmatel_stac9708_specific(ac97_t *ac97)
 {
+	int err;
+
 	snd_ac97_rename_vol_ctl(ac97, "Headphone Playback", "Sigmatel Surround Playback");
+	if ((err = patch_build_controls(ac97, &snd_ac97_stac9708_bias_control, 1)) < 0)
+		return err;
 	return patch_sigmatel_stac97xx_specific(ac97);
 }
 
@@ -2009,10 +2166,13 @@
 {
 	unsigned short val;
 
-	/* CM9761 has no Master and PCM volume although the register reacts */
-	ac97->flags |= AC97_HAS_NO_MASTER_VOL | AC97_HAS_NO_PCM_VOL;
-	snd_ac97_write_cache(ac97, AC97_MASTER, 0x8000);
-	snd_ac97_write_cache(ac97, AC97_PCM, 0x8000);
+	/* CM9761 has no PCM volume although the register reacts */
+	/* Master volume seems to have _some_ influence on the analog
+	 * input sounds
+	 */
+	ac97->flags |= /*AC97_HAS_NO_MASTER_VOL |*/ AC97_HAS_NO_PCM_VOL;
+	snd_ac97_write_cache(ac97, AC97_MASTER, 0x8808);
+	snd_ac97_write_cache(ac97, AC97_PCM, 0x8808);
 
 	ac97->spec.dev_flags = 0; /* 1 = model 82 revision B */
 	if (ac97->id == AC97_ID_CM9761_82) {
@@ -2032,7 +2192,8 @@
         ac97->ext_id |= AC97_EI_SPDIF;
 	/* to be sure: we overwrite the ext status bits */
 	snd_ac97_write_cache(ac97, AC97_EXTENDED_STATUS, 0x05c0);
-	snd_ac97_write_cache(ac97, AC97_CM9761_SPDIF_CTRL, 0x0209);
+	/* Don't set 0x0200 here.  This results in the silent analog output */
+	snd_ac97_write_cache(ac97, AC97_CM9761_SPDIF_CTRL, 0x0009);
 	ac97->rates[AC97_RATES_SPDIF] = SNDRV_PCM_RATE_48000; /* 48k only */
 
 	/* set-up multi channel */
@@ -2057,8 +2218,10 @@
 		val = 0x0214;
 	else
 		val = 0x321c;
-	snd_ac97_write_cache(ac97, AC97_CM9761_MULTI_CHAN, val);
 #endif
+	val = snd_ac97_read(ac97, AC97_CM9761_MULTI_CHAN);
+	val |= (1 << 4); /* front on */
+	snd_ac97_write_cache(ac97, AC97_CM9761_MULTI_CHAN, val);
 
 	/* FIXME: set up GPIO */
 	snd_ac97_write_cache(ac97, 0x70, 0x0100);
diff -Nru a/sound/pci/ac97/ac97_patch.h b/sound/pci/ac97/ac97_patch.h
--- a/sound/pci/ac97/ac97_patch.h	2005-03-11 12:51:41 -08:00
+++ b/sound/pci/ac97/ac97_patch.h	2005-03-11 12:51:41 -08:00
@@ -28,6 +28,7 @@
 int patch_wolfson04(ac97_t * ac97);
 int patch_wolfson05(ac97_t * ac97);
 int patch_wolfson11(ac97_t * ac97);
+int patch_wolfson13(ac97_t * ac97);
 int patch_tritech_tr28028(ac97_t * ac97);
 int patch_sigmatel_stac9700(ac97_t * ac97);
 int patch_sigmatel_stac9708(ac97_t * ac97);
diff -Nru a/sound/pci/ac97/ac97_pcm.c b/sound/pci/ac97/ac97_pcm.c
--- a/sound/pci/ac97/ac97_pcm.c	2005-03-11 12:51:41 -08:00
+++ b/sound/pci/ac97/ac97_pcm.c	2005-03-11 12:51:41 -08:00
@@ -553,7 +553,7 @@
 {
 	ac97_bus_t *bus;
 	int i, cidx, r, ok_flag;
-	unsigned int reg_ok = 0;
+	unsigned int reg_ok[4] = {0,0,0,0};
 	unsigned char reg;
 	int err = 0;
 
@@ -602,14 +602,14 @@
 					snd_printk(KERN_ERR "invalid AC97 slot %i?\n", i);
 					continue;
 				}
-				if (reg_ok & (1 << (reg - AC97_PCM_FRONT_DAC_RATE)))
+				if (reg_ok[cidx] & (1 << (reg - AC97_PCM_FRONT_DAC_RATE)))
 					continue;
 				//printk(KERN_DEBUG "setting ac97 reg 0x%x to rate %d\n", reg, rate);
 				err = snd_ac97_set_rate(pcm->r[r].codec[cidx], reg, rate);
 				if (err < 0)
 					snd_printk(KERN_ERR "error in snd_ac97_set_rate: cidx=%d, reg=0x%x, rate=%d, err=%d\n", cidx, reg, rate, err);
 				else
-					reg_ok |= (1 << (reg - AC97_PCM_FRONT_DAC_RATE));
+					reg_ok[cidx] |= (1 << (reg - AC97_PCM_FRONT_DAC_RATE));
 			}
 		}
 	}
diff -Nru a/sound/pci/ali5451/ali5451.c b/sound/pci/ali5451/ali5451.c
--- a/sound/pci/ali5451/ali5451.c	2005-03-11 12:51:51 -08:00
+++ b/sound/pci/ali5451/ali5451.c	2005-03-11 12:51:51 -08:00
@@ -188,7 +188,7 @@
 
 struct snd_ali_stru_voice {
 	unsigned int number;
-	int use: 1,
+	unsigned int use: 1,
 	    pcm: 1,
 	    midi: 1,
 	    mode: 1,
@@ -199,7 +199,7 @@
 	snd_pcm_substream_t *substream;
 	snd_ali_voice_t *extra;
 	
-	int running: 1;
+	unsigned int running: 1;
 
 	int eso;                /* final ESO value for channel */
 	int count;              /* runtime->period_size */
@@ -1894,7 +1894,7 @@
 }
 
 #ifdef CONFIG_PM
-static int ali_suspend(snd_card_t *card, unsigned int state)
+static int ali_suspend(snd_card_t *card, pm_message_t state)
 {
 	ali_t *chip = card->pm_private_data;
 	ali_image_t *im;
@@ -1936,7 +1936,7 @@
 	return 0;
 }
 
-static int ali_resume(snd_card_t *card, unsigned int state)
+static int ali_resume(snd_card_t *card)
 {
 	ali_t *chip = card->pm_private_data;
 	ali_image_t *im;
diff -Nru a/sound/pci/als4000.c b/sound/pci/als4000.c
--- a/sound/pci/als4000.c	2005-03-11 12:51:51 -08:00
+++ b/sound/pci/als4000.c	2005-03-11 12:51:51 -08:00
@@ -104,8 +104,7 @@
 	struct pci_dev *pci;
 	unsigned long gcr;
 #ifdef SUPPORT_JOYSTICK
-	struct gameport gameport;
-	struct resource *res_joystick;
+	struct gameport *gameport;
 #endif
 } snd_card_als4000_t;
 
@@ -566,21 +565,80 @@
 	spin_unlock_irq(&chip->reg_lock);
 }
 
+#ifdef SUPPORT_JOYSTICK
+static int __devinit snd_als4000_create_gameport(snd_card_als4000_t *acard, int dev)
+{
+	struct gameport *gp;
+	struct resource *r;
+	int io_port;
+
+	if (joystick_port[dev] == 0)
+		return -ENODEV;
+
+	if (joystick_port[dev] == 1) { /* auto-detect */
+		for (io_port = 0x200; io_port <= 0x218; io_port += 8) {
+			r = request_region(io_port, 8, "ALS4000 gameport");
+			if (r)
+				break;
+		}
+	} else {
+		io_port = joystick_port[dev];
+		r = request_region(io_port, 8, "ALS4000 gameport");
+	}
+
+	if (!r) {
+		printk(KERN_WARNING "als4000: cannot reserve joystick ports\n");
+		return -EBUSY;
+	}
+
+	acard->gameport = gp = gameport_allocate_port();
+	if (!gp) {
+		printk(KERN_ERR "als4000: cannot allocate memory for gameport\n");
+		release_resource(r);
+		kfree_nocheck(r);
+		return -ENOMEM;
+	}
+
+	gameport_set_name(gp, "ALS4000 Gameport");
+	gameport_set_phys(gp, "pci%s/gameport0", pci_name(acard->pci));
+	gp->dev.parent = &acard->pci->dev;
+	gp->io = io_port;
+	gp->port_data = r;
+
+	/* Enable legacy joystick port */
+	snd_als4000_set_addr(acard->gcr, 0, 0, 0, 1);
+
+	gameport_register_port(acard->gameport);
+
+	return 0;
+}
+
+static void snd_als4000_free_gameport(snd_card_als4000_t *acard)
+{
+	if (acard->gameport) {
+		struct resource *r = acard->gameport->port_data;
+
+		gameport_unregister_port(acard->gameport);
+		acard->gameport = NULL;
+
+		snd_als4000_set_addr(acard->gcr, 0, 0, 0, 0); /* disable joystick */
+		release_resource(r);
+		kfree_nocheck(r);
+	}
+}
+#else
+static inline int snd_als4000_create_gameport(snd_card_als4000_t *acard, int dev) { return -ENOSYS; }
+static inline void snd_als4000_free_gameport(snd_card_als4000_t *acard) { }
+#endif
+
 static void snd_card_als4000_free( snd_card_t *card )
 {
 	snd_card_als4000_t * acard = (snd_card_als4000_t *)card->private_data;
+
 	/* make sure that interrupts are disabled */
 	snd_als4000_gcr_write_addr( acard->gcr, 0x8c, 0);
 	/* free resources */
-#ifdef SUPPORT_JOYSTICK
-	if (acard->res_joystick) {
-		if (acard->gameport.io)
-			gameport_unregister_port(&acard->gameport);
-		snd_als4000_set_addr(acard->gcr, 0, 0, 0, 0); /* disable joystick */
-		release_resource(acard->res_joystick);
-		kfree_nocheck(acard->res_joystick);
-	}
-#endif
+	snd_als4000_free_gameport(acard);
 	pci_release_regions(acard->pci);
 	pci_disable_device(acard->pci);
 }
@@ -596,7 +654,6 @@
 	opl3_t *opl3;
 	unsigned short word;
 	int err;
-	int joystick = 0;
 
 	if (dev >= SNDRV_CARDS)
 		return -ENODEV;
@@ -640,26 +697,9 @@
 	acard->gcr = gcr;
 	card->private_free = snd_card_als4000_free;
 
-	/* disable all legacy ISA stuff except for joystick */
-#ifdef SUPPORT_JOYSTICK
-	if (joystick_port[dev] == 1) {
-		/* auto-detect */
-		long p;
-		for (p = 0x200; p <= 0x218; p += 8) {
-			if ((acard->res_joystick = request_region(p, 8, "ALS4000 gameport")) != NULL) {
-				joystick_port[dev] = p;
-				break;
-			}
-		}
-	} else if (joystick_port[dev] > 0)
-		acard->res_joystick = request_region(joystick_port[dev], 8, "ALS4000 gameport");
-	if (acard->res_joystick)
-		joystick = joystick_port[dev];
-	else
-		joystick = 0;
-#endif
-	snd_als4000_set_addr(gcr, 0, 0, 0, joystick);
-	
+	/* disable all legacy ISA stuff */
+	snd_als4000_set_addr(acard->gcr, 0, 0, 0, 0);
+
 	if ((err = snd_sbdsp_create(card,
 				    gcr + 0x10,
 				    pci->irq,
@@ -711,12 +751,7 @@
 		}
 	}
 
-#ifdef SUPPORT_JOYSTICK
-	if (acard->res_joystick) {
-		acard->gameport.io = joystick;
-		gameport_register_port(&acard->gameport);
-	}
-#endif
+	snd_als4000_create_gameport(acard, dev);
 
 	if ((err = snd_card_register(card)) < 0) {
 		snd_card_free(card);
diff -Nru a/sound/pci/atiixp.c b/sound/pci/atiixp.c
--- a/sound/pci/atiixp.c	2005-03-11 12:51:46 -08:00
+++ b/sound/pci/atiixp.c	2005-03-11 12:51:46 -08:00
@@ -1398,7 +1398,7 @@
 /*
  * power management
  */
-static int snd_atiixp_suspend(snd_card_t *card, unsigned int state)
+static int snd_atiixp_suspend(snd_card_t *card, pm_message_t state)
 {
 	atiixp_t *chip = card->pm_private_data;
 	int i;
@@ -1417,7 +1417,7 @@
 	return 0;
 }
 
-static int snd_atiixp_resume(snd_card_t *card, unsigned int state)
+static int snd_atiixp_resume(snd_card_t *card)
 {
 	atiixp_t *chip = card->pm_private_data;
 	int i;
diff -Nru a/sound/pci/atiixp_modem.c b/sound/pci/atiixp_modem.c
--- a/sound/pci/atiixp_modem.c	2005-03-11 12:51:51 -08:00
+++ b/sound/pci/atiixp_modem.c	2005-03-11 12:51:51 -08:00
@@ -39,7 +39,7 @@
 MODULE_LICENSE("GPL");
 MODULE_SUPPORTED_DEVICE("{{ATI,IXP150/200/250}}");
 
-static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;	/* Index 0-MAX */
+static int index[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = -2}; /* Exclude the first card */
 static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;	/* ID for this card */
 static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;	/* Enable this card */
 static int ac97_clock[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 48000};
@@ -606,21 +606,20 @@
 	snd_pcm_runtime_t *runtime = substream->runtime;
 	atiixp_dma_t *dma = (atiixp_dma_t *)runtime->private_data;
 	unsigned int curptr;
+	int timeout = 1000;
 
-	spin_lock(&chip->reg_lock);
-	curptr = readl(chip->remap_addr + dma->ops->dt_cur);
-	if (curptr < dma->buf_addr) {
-		snd_printdd("curptr = %x, base = %x\n", curptr, dma->buf_addr);
-		curptr = 0;
-	} else {
+	while (timeout--) {
+		curptr = readl(chip->remap_addr + dma->ops->dt_cur);
+		if (curptr < dma->buf_addr)
+			continue;
 		curptr -= dma->buf_addr;
-		if (curptr >= dma->buf_bytes) {
-			snd_printdd("curptr = %x, size = %x\n", curptr, dma->buf_bytes);
-			curptr = 0;
-		}
+		if (curptr >= dma->buf_bytes)
+			continue;
+		return bytes_to_frames(runtime, curptr);
 	}
-	spin_unlock(&chip->reg_lock);
-	return bytes_to_frames(runtime, curptr);
+	snd_printd("atiixp-modem: invalid DMA pointer read 0x%x (buf=%x)\n",
+		   readl(chip->remap_addr + dma->ops->dt_cur), dma->buf_addr);
+	return 0;
 }
 
 /*
@@ -1108,7 +1107,7 @@
 /*
  * power management
  */
-static int snd_atiixp_suspend(snd_card_t *card, unsigned int state)
+static int snd_atiixp_suspend(snd_card_t *card, pm_message_t state)
 {
 	atiixp_t *chip = card->pm_private_data;
 	int i;
@@ -1127,7 +1126,7 @@
 	return 0;
 }
 
-static int snd_atiixp_resume(snd_card_t *card, unsigned int state)
+static int snd_atiixp_resume(snd_card_t *card)
 {
 	atiixp_t *chip = card->pm_private_data;
 	int i;
diff -Nru a/sound/pci/au88x0/au88x0.c b/sound/pci/au88x0/au88x0.c
--- a/sound/pci/au88x0/au88x0.c	2005-03-11 12:51:46 -08:00
+++ b/sound/pci/au88x0/au88x0.c	2005-03-11 12:51:46 -08:00
@@ -290,10 +290,9 @@
 		snd_card_free(card);
 		return err;
 	}
-	if ((err = vortex_gameport_register(chip)) < 0) {
-		snd_card_free(card);
-		return err;
-	}
+
+	vortex_gameport_register(chip);
+
 #if 0
 	if (snd_seq_device_new(card, 1, SNDRV_SEQ_DEV_ID_VORTEX_SYNTH,
 			       sizeof(snd_vortex_synth_arg_t), &wave) < 0
diff -Nru a/sound/pci/au88x0/au88x0.h b/sound/pci/au88x0/au88x0.h
--- a/sound/pci/au88x0/au88x0.h	2005-03-11 12:51:47 -08:00
+++ b/sound/pci/au88x0/au88x0.h	2005-03-11 12:51:47 -08:00
@@ -272,7 +272,7 @@
 
 /* Driver stuff. */
 static int __devinit vortex_gameport_register(vortex_t * card);
-static int __devexit vortex_gameport_unregister(vortex_t * card);
+static void vortex_gameport_unregister(vortex_t * card);
 #ifndef CHIP_AU8820
 static int __devinit vortex_eq_init(vortex_t * vortex);
 static int __devexit vortex_eq_free(vortex_t * vortex);
diff -Nru a/sound/pci/au88x0/au88x0_core.c b/sound/pci/au88x0/au88x0_core.c
--- a/sound/pci/au88x0/au88x0_core.c	2005-03-11 12:51:52 -08:00
+++ b/sound/pci/au88x0/au88x0_core.c	2005-03-11 12:51:52 -08:00
@@ -2480,7 +2480,8 @@
 	int i;
 
 	for (i = 0; i < 32; i++) {
-		hwwrite(vortex->mmio, (VORTEX_CODEC_CHN + (i << 2)), 0);
+		/* the windows driver writes -i, so we write -i */
+		hwwrite(vortex->mmio, (VORTEX_CODEC_CHN + (i << 2)), -i);
 		msleep(2);
 	}
 	if (0) {
@@ -2502,7 +2503,7 @@
 		hwwrite(vortex->mmio, VORTEX_CODEC_CTRL, 0x00e8);
 	}
 	for (i = 0; i < 32; i++) {
-		hwwrite(vortex->mmio, (VORTEX_CODEC_CHN + (i << 2)), 0);
+		hwwrite(vortex->mmio, (VORTEX_CODEC_CHN + (i << 2)), -i);
 		msleep(5);
 	}
 	hwwrite(vortex->mmio, VORTEX_CODEC_CTRL, 0xe8);
diff -Nru a/sound/pci/au88x0/au88x0_game.c b/sound/pci/au88x0/au88x0_game.c
--- a/sound/pci/au88x0/au88x0_game.c	2005-03-11 12:51:41 -08:00
+++ b/sound/pci/au88x0/au88x0_game.c	2005-03-11 12:51:41 -08:00
@@ -44,20 +44,20 @@
 
 static unsigned char vortex_game_read(struct gameport *gameport)
 {
-	vortex_t *vortex = gameport->driver;
+	vortex_t *vortex = gameport->port_data;
 	return hwread(vortex->mmio, VORTEX_GAME_LEGACY);
 }
 
 static void vortex_game_trigger(struct gameport *gameport)
 {
-	vortex_t *vortex = gameport->driver;
+	vortex_t *vortex = gameport->port_data;
 	hwwrite(vortex->mmio, VORTEX_GAME_LEGACY, 0xff);
 }
 
 static int
 vortex_game_cooked_read(struct gameport *gameport, int *axes, int *buttons)
 {
-	vortex_t *vortex = gameport->driver;
+	vortex_t *vortex = gameport->port_data;
 	int i;
 
 	*buttons = (~hwread(vortex->mmio, VORTEX_GAME_LEGACY) >> 4) & 0xf;
@@ -73,7 +73,7 @@
 
 static int vortex_game_open(struct gameport *gameport, int mode)
 {
-	vortex_t *vortex = gameport->driver;
+	vortex_t *vortex = gameport->port_data;
 
 	switch (mode) {
 	case GAMEPORT_MODE_COOKED:
@@ -94,40 +94,42 @@
 	return 0;
 }
 
-static int vortex_gameport_register(vortex_t * vortex)
+static int __devinit vortex_gameport_register(vortex_t * vortex)
 {
-	if ((vortex->gameport = kcalloc(1, sizeof(struct gameport), GFP_KERNEL)) == NULL) {
-		return -1;
+	struct gameport *gp;
+
+	vortex->gameport = gp = gameport_allocate_port();
+	if (!gp) {
+		printk(KERN_ERR "vortex: cannot allocate memory for gameport\n");
+		return -ENOMEM;
 	};
-	
-	vortex->gameport->driver = vortex;
-	vortex->gameport->fuzz = 64;
-
-	vortex->gameport->read = vortex_game_read;
-	vortex->gameport->trigger = vortex_game_trigger;
-	vortex->gameport->cooked_read = vortex_game_cooked_read;
-	vortex->gameport->open = vortex_game_open;
-
-	gameport_register_port((struct gameport *)vortex->gameport);
-
-/*	printk(KERN_INFO "gameport%d: %s at speed %d kHz\n",
-		vortex->gameport->number, vortex->pci_dev->name, vortex->gameport->speed);
-*/
+
+	gameport_set_name(gp, "AU88x0 Gameport");
+	gameport_set_phys(gp, "pci%s/gameport0", pci_name(vortex->pci_dev));
+	gp->dev.parent = &vortex->pci_dev->dev;
+
+	gp->read = vortex_game_read;
+	gp->trigger = vortex_game_trigger;
+	gp->cooked_read = vortex_game_cooked_read;
+	gp->open = vortex_game_open;
+
+	gp->port_data = vortex;
+	gp->fuzz = 64;
+
+	gameport_register_port(gp);
+
 	return 0;
 }
 
-static int vortex_gameport_unregister(vortex_t * vortex)
+static void vortex_gameport_unregister(vortex_t * vortex)
 {
-	if (vortex->gameport != NULL) {
+	if (vortex->gameport) {
 		gameport_unregister_port(vortex->gameport);
-		kfree(vortex->gameport);
+		vortex->gameport = NULL;
 	}
-	return 0;
 }
 
 #else
-
-static inline int vortex_gameport_register(vortex_t * vortex) { return 0; }
-static inline int vortex_gameport_unregister(vortex_t * vortex) { return 0; }
-
+static inline int vortex_gameport_register(vortex_t * vortex) { return -ENOSYS; }
+static inline void vortex_gameport_unregister(vortex_t * vortex) { }
 #endif
diff -Nru a/sound/pci/au88x0/au88x0_pcm.c b/sound/pci/au88x0/au88x0_pcm.c
--- a/sound/pci/au88x0/au88x0_pcm.c	2005-03-11 12:51:46 -08:00
+++ b/sound/pci/au88x0/au88x0_pcm.c	2005-03-11 12:51:46 -08:00
@@ -20,7 +20,7 @@
  * Supports ADB and WT DMA. Unfortunately, WT channels do not run yet.
  * It remains stuck,and DMA transfers do not happen. 
  */
-
+#include <sound/asoundef.h>
 #include <sound/driver.h>
 #include <linux/time.h>
 #include <sound/core.h>
@@ -431,61 +431,77 @@
 };
 
 /* SPDIF kcontrol */
-static int
-snd_vortex_spdif_info(snd_kcontrol_t * kcontrol, snd_ctl_elem_info_t * uinfo)
-{
-	static char *texts[] = { "32000", "44100", "48000" };
 
-	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+static int snd_vortex_spdif_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+{
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
 	uinfo->count = 1;
-	uinfo->value.enumerated.items = 3;
-	if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
-		uinfo->value.enumerated.item =
-		    uinfo->value.enumerated.items - 1;
-	strcpy(uinfo->value.enumerated.name,
-	       texts[uinfo->value.enumerated.item]);
 	return 0;
 }
-static int
-snd_vortex_spdif_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
-{
-	vortex_t *vortex = snd_kcontrol_chip(kcontrol);
 
-	if (vortex->spdif_sr == 32000)
-		ucontrol->value.enumerated.item[0] = 0;
-	if (vortex->spdif_sr == 44100)
-		ucontrol->value.enumerated.item[0] = 1;
-	if (vortex->spdif_sr == 48000)
-		ucontrol->value.enumerated.item[0] = 2;
+static int snd_vortex_spdif_mask_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+{
+	ucontrol->value.iec958.status[0] = 0xff;
+	ucontrol->value.iec958.status[1] = 0xff;
+	ucontrol->value.iec958.status[2] = 0xff;
+	ucontrol->value.iec958.status[3] = IEC958_AES3_CON_FS;
 	return 0;
 }
-static int
-snd_vortex_spdif_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+
+static int snd_vortex_spdif_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
 	vortex_t *vortex = snd_kcontrol_chip(kcontrol);
-	static unsigned int sr[3] = { 32000, 44100, 48000 };
+	ucontrol->value.iec958.status[0] = 0x00;
+	ucontrol->value.iec958.status[1] = IEC958_AES1_CON_ORIGINAL|IEC958_AES1_CON_DIGDIGCONV_ID;
+	ucontrol->value.iec958.status[2] = 0x00;
+	switch (vortex->spdif_sr) {
+	case 32000: ucontrol->value.iec958.status[3] = IEC958_AES3_CON_FS_32000; break;
+	case 44100: ucontrol->value.iec958.status[3] = IEC958_AES3_CON_FS_44100; break;
+	case 48000: ucontrol->value.iec958.status[3] = IEC958_AES3_CON_FS_48000; break;
+	}
+	return 0;
+}
 
-	//printk("vortex: spdif sr = %d\n", ucontrol->value.enumerated.item[0]);
-	vortex->spdif_sr = sr[ucontrol->value.enumerated.item[0] % 3];
-	vortex_spdif_init(vortex,
-			  sr[ucontrol->value.enumerated.item[0] % 3], 1);
+static int snd_vortex_spdif_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+{
+	vortex_t *vortex = snd_kcontrol_chip(kcontrol);
+	int spdif_sr = 48000;
+	switch (ucontrol->value.iec958.status[3] & IEC958_AES3_CON_FS) {
+	case IEC958_AES3_CON_FS_32000: spdif_sr = 32000; break;
+	case IEC958_AES3_CON_FS_44100: spdif_sr = 44100; break;
+	case IEC958_AES3_CON_FS_48000: spdif_sr = 48000; break;
+	}
+	if (spdif_sr == vortex->spdif_sr)
+		return 0;
+	vortex->spdif_sr = spdif_sr;
+	vortex_spdif_init(vortex, vortex->spdif_sr, 1);
 	return 1;
 }
-static snd_kcontrol_new_t vortex_spdif_kcontrol __devinitdata = {
-	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-	.name = "SPDIF SR",
-	.index = 0,
-	.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
-	.private_value = 0,
-	.info = snd_vortex_spdif_info,
-	.get = snd_vortex_spdif_get,
-	.put = snd_vortex_spdif_put
+
+/* spdif controls */
+static snd_kcontrol_new_t snd_vortex_mixer_spdif[] __devinitdata = {
+	{
+		.iface =	SNDRV_CTL_ELEM_IFACE_PCM,
+		.name =		SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
+		.info =		snd_vortex_spdif_info,
+		.get =		snd_vortex_spdif_get,
+		.put =		snd_vortex_spdif_put,
+	},
+	{
+		.access =	SNDRV_CTL_ELEM_ACCESS_READ,
+		.iface =	SNDRV_CTL_ELEM_IFACE_PCM,
+		.name =		SNDRV_CTL_NAME_IEC958("",PLAYBACK,CON_MASK),
+		.info =		snd_vortex_spdif_info,
+		.get =		snd_vortex_spdif_mask_get
+	},
 };
 
 /* create a pcm device */
 static int __devinit snd_vortex_new_pcm(vortex_t * chip, int idx, int nr)
 {
 	snd_pcm_t *pcm;
+	snd_kcontrol_t *kctl;
+	int i;
 	int err, nr_capt;
 
 	if ((chip == 0) || (idx < 0) || (idx > VORTEX_PCM_LAST))
@@ -520,13 +536,13 @@
 					      0x10000, 0x10000);
 
 	if (VORTEX_PCM_TYPE(pcm) == VORTEX_PCM_SPDIF) {
-		snd_kcontrol_t *kcontrol;
-
-		if ((kcontrol =
-		     snd_ctl_new1(&vortex_spdif_kcontrol, chip)) == NULL)
-			return -ENOMEM;
-		if ((err = snd_ctl_add(chip->card, kcontrol)) < 0)
-			return err;
+		for (i = 0; i < ARRAY_SIZE(snd_vortex_mixer_spdif); i++) {
+			kctl = snd_ctl_new1(&snd_vortex_mixer_spdif[i], chip);
+			if (!kctl)
+				return -ENOMEM;
+			if ((err = snd_ctl_add(chip->card, kctl)) < 0)
+				return err;
+		}
 	}
 	return 0;
 }
diff -Nru a/sound/pci/azt3328.c b/sound/pci/azt3328.c
--- a/sound/pci/azt3328.c	2005-03-11 12:51:47 -08:00
+++ b/sound/pci/azt3328.c	2005-03-11 12:51:47 -08:00
@@ -160,19 +160,19 @@
 #endif
 	    
 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;	/* Index 0-MAX */
-static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;	/* ID for this card */
-static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;	/* Enable this card */
-#ifdef SUPPORT_JOYSTICK
-static int joystick[SNDRV_CARDS];
-#endif
-
 module_param_array(index, int, NULL, 0444);
 MODULE_PARM_DESC(index, "Index value for AZF3328 soundcard.");
+
+static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;	/* ID for this card */
 module_param_array(id, charp, NULL, 0444);
 MODULE_PARM_DESC(id, "ID string for AZF3328 soundcard.");
+
+static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;	/* Enable this card */
 module_param_array(enable, bool, NULL, 0444);
 MODULE_PARM_DESC(enable, "Enable AZF3328 soundcard.");
+
 #ifdef SUPPORT_JOYSTICK
+static int joystick[SNDRV_CARDS];
 module_param_array(joystick, bool, NULL, 0444);
 MODULE_PARM_DESC(joystick, "Enable joystick for AZF3328 soundcard.");
 #endif
@@ -189,8 +189,7 @@
 	unsigned long mixer_port;
 
 #ifdef SUPPORT_JOYSTICK
-	struct gameport gameport;
-	struct resource *res_joystick;
+	struct gameport *gameport;
 #endif
 
 	struct pci_dev *pci;
@@ -1222,6 +1221,63 @@
 
 /******************************************************************/
 
+#ifdef SUPPORT_JOYSTICK
+static int __devinit snd_azf3328_config_joystick(azf3328_t *chip, int dev)
+{
+	struct gameport *gp;
+	struct resource *r;
+
+	if (!joystick[dev])
+		return -ENODEV;
+
+	if (!(r = request_region(0x200, 8, "AZF3328 gameport"))) {
+		printk(KERN_WARNING "azt3328: cannot reserve joystick ports\n");
+		return -EBUSY;
+	}
+
+	chip->gameport = gp = gameport_allocate_port();
+	if (!gp) {
+		printk(KERN_ERR "azt3328: cannot allocate memory for gameport\n");
+		release_resource(r);
+		kfree_nocheck(r);
+		return -ENOMEM;
+	}
+
+	gameport_set_name(gp, "AZF3328 Gameport");
+	gameport_set_phys(gp, "pci%s/gameport0", pci_name(chip->pci));
+	gp->dev.parent = &chip->pci->dev;
+	gp->io = 0x200;
+	gp->port_data = r;
+
+	snd_azf3328_io2_write(chip, IDX_IO2_LEGACY_ADDR,
+			      snd_azf3328_io2_read(chip, IDX_IO2_LEGACY_ADDR) | LEGACY_JOY);
+
+	gameport_register_port(chip->gameport);
+
+	return 0;
+}
+
+static void snd_azf3328_free_joystick(azf3328_t *chip)
+{
+	if (chip->gameport) {
+		struct resource *r = chip->gameport->port_data;
+
+		gameport_unregister_port(chip->gameport);
+		chip->gameport = NULL;
+		/* disable gameport */
+		snd_azf3328_io2_write(chip, IDX_IO2_LEGACY_ADDR,
+				      snd_azf3328_io2_read(chip, IDX_IO2_LEGACY_ADDR) & ~LEGACY_JOY);
+		release_resource(r);
+		kfree_nocheck(r);
+	}
+}
+#else
+static inline int snd_azf3328_config_joystick(azf3328_t *chip, int dev) { return -ENOSYS; }
+static inline void snd_azf3328_free_joystick(azf3328_t *chip) { }
+#endif
+
+/******************************************************************/
+
 static int snd_azf3328_free(azf3328_t *chip)
 {
         if (chip->irq < 0)
@@ -1236,16 +1292,7 @@
 
         synchronize_irq(chip->irq);
       __end_hw:
-#ifdef SUPPORT_JOYSTICK
-	if (chip->res_joystick) {
-		gameport_unregister_port(&chip->gameport);
-		/* disable gameport */
-		snd_azf3328_io2_write(chip, IDX_IO2_LEGACY_ADDR,
-				      snd_azf3328_io2_read(chip, IDX_IO2_LEGACY_ADDR) & ~LEGACY_JOY);
-		release_resource(chip->res_joystick);
-		kfree_nocheck(chip->res_joystick);
-	}
-#endif
+	snd_azf3328_free_joystick(chip);
         if (chip->irq >= 0)
 		free_irq(chip->irq, (void *)chip);
 	pci_release_regions(chip->pci);
@@ -1373,28 +1420,6 @@
 	return 0;
 }
 
-#ifdef SUPPORT_JOYSTICK
-static void __devinit snd_azf3328_config_joystick(azf3328_t *chip, int joystick)
-{
-	unsigned char val;
-
-	if (joystick == 1) {
-		if ((chip->res_joystick = request_region(0x200, 8, "AZF3328 gameport")) != NULL)
-			chip->gameport.io = 0x200;
-	}
-
-	val = inb(chip->io2_port + IDX_IO2_LEGACY_ADDR);
-	if (chip->res_joystick)
-		val |= LEGACY_JOY;
-	else
-		val &= ~LEGACY_JOY;
-
-	outb(val, chip->io2_port + IDX_IO2_LEGACY_ADDR);
-	if (chip->res_joystick)
-		gameport_register_port(&chip->gameport);
-}
-#endif
-
 static int __devinit snd_azf3328_probe(struct pci_dev *pci,
 					  const struct pci_device_id *pci_id)
 {
@@ -1465,9 +1490,9 @@
 "azt3328: Feel free to contact hw7oshyuv3001@sneakemail.com for bug reports etc.!\n");
 #endif
 
-#ifdef SUPPORT_JOYSTICK
-	snd_azf3328_config_joystick(chip, joystick[dev]);
-#endif
+	if (snd_azf3328_config_joystick(chip, dev) < 0)
+		snd_azf3328_io2_write(chip, IDX_IO2_LEGACY_ADDR,
+			      snd_azf3328_io2_read(chip, IDX_IO2_LEGACY_ADDR) & ~LEGACY_JOY);
 
 	pci_set_drvdata(pci, card);
 	dev++;
diff -Nru a/sound/pci/bt87x.c b/sound/pci/bt87x.c
--- a/sound/pci/bt87x.c	2005-03-11 12:51:46 -08:00
+++ b/sound/pci/bt87x.c	2005-03-11 12:51:46 -08:00
@@ -41,7 +41,7 @@
 MODULE_SUPPORTED_DEVICE("{{Brooktree,Bt878},"
 		"{Brooktree,Bt879}}");
 
-static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;	/* Index 0-MAX */
+static int index[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = -2}; /* Exclude the first card */
 static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;	/* ID for this card */
 static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;	/* Enable this card */
 static int digital_rate[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS-1)] = 0 }; /* digital input rate */
diff -Nru a/sound/pci/ca0106/ca0106_main.c b/sound/pci/ca0106/ca0106_main.c
--- a/sound/pci/ca0106/ca0106_main.c	2005-03-11 12:51:51 -08:00
+++ b/sound/pci/ca0106/ca0106_main.c	2005-03-11 12:51:51 -08:00
@@ -1,7 +1,7 @@
 /*
  *  Copyright (c) 2004 James Courtier-Dutton <James@superbug.demon.co.uk>
  *  Driver CA0106 chips. e.g. Sound Blaster Audigy LS and Live 24bit
- *  Version: 0.0.21
+ *  Version: 0.0.22
  *
  *  FEATURES currently supported:
  *    Front, Rear and Center/LFE.
@@ -75,6 +75,8 @@
  *  0.0.21
  *    Add 4 capture channels. (SPDIF only comes in on channel 0. )
  *    Add SPDIF capture using optional digital I/O module for SB Live 24bit. (Analog capture does not yet work.)
+ *  0.0.22
+ *    Add support for MSI K8N Diamond Motherboard with onboard SB Live 24bit without AC97. From kiksen, bug #901
  *
  *  BUGS:
  *    Some stability problems when unloading the snd-ca0106 kernel module.
@@ -169,6 +171,7 @@
 	 { 0x10051102, "AudigyLS [SB0310b]"} , /* Unknown AudigyLS that also says SB0310 on it */
 	 { 0x10061102, "Live! 7.1 24bit [SB0410]"} , /* New Sound Blaster Live! 7.1 24bit. This does not have an AC97. 53SB041000001 */
 	 { 0x10071102, "Live! 7.1 24bit [SB0413]"} , /* New Dell Sound Blaster Live! 7.1 24bit. This does not have an AC97.  */
+	 { 0x10091462, "MSI K8N Diamond MB [SB0438]"}, /* MSI K8N Diamond Motherboard with onboard SB Live 24bit without AC97 */
 	 { 0, "AudigyLS [Unknown]" }
 };
 
@@ -1133,7 +1136,9 @@
         snd_ca0106_ptr_write(chip, CAPTURE_SOURCE, 0x0, 0x333300e4); /* Select MIC, Line in, TAD in, AUX in */
 	chip->capture_source = 3; /* Set CAPTURE_SOURCE */
 
-        if ((chip->serial == 0x10061102) || (chip->serial == 0x10071102) ) { /* The SB0410 and SB0413 use GPIO differently. */
+        if ((chip->serial == 0x10061102) || 
+	    (chip->serial == 0x10071102) ||
+	    (chip->serial == 0x10091462)) { /* The SB0410 and SB0413 use GPIO differently. */
 		/* FIXME: Still need to find out what the other GPIO bits do. E.g. For digital spdif out. */
 		outl(0x0, chip->port+GPIO);
 		//outl(0x00f0e000, chip->port+GPIO); /* Analog */
@@ -1200,7 +1205,9 @@
 		snd_card_free(card);
 		return err;
 	}
-        if ((chip->serial != 0x10061102) && (chip->serial != 0x10071102) ) { /* The SB0410 and SB0413 do not have an ac97 chip. */
+        if ((chip->serial != 0x10061102) && 
+	    (chip->serial != 0x10071102) && 
+	    (chip->serial != 0x10091462) ) { /* The SB0410 and SB0413 do not have an ac97 chip. */
 		if ((err = snd_ca0106_ac97(chip)) < 0) {
 			snd_card_free(card);
 			return err;
diff -Nru a/sound/pci/cmipci.c b/sound/pci/cmipci.c
--- a/sound/pci/cmipci.c	2005-03-11 12:51:47 -08:00
+++ b/sound/pci/cmipci.c	2005-03-11 12:51:47 -08:00
@@ -156,6 +156,8 @@
 #define CM_CHIP_MASK2		0xff000000
 #define CM_CHIP_039		0x04000000
 #define CM_CHIP_039_6CH		0x01000000
+#define CM_CHIP_055		0x08000000
+#define CM_CHIP_8768		0x20000000
 #define CM_TDMA_INT_EN		0x00040000
 #define CM_CH1_INT_EN		0x00020000
 #define CM_CH0_INT_EN		0x00010000
@@ -328,6 +330,13 @@
 #define CM_REG_CH0_FRAME2	0x84
 #define CM_REG_CH1_FRAME1	0x88	/* 0-15: count of samples at bus master; buffer size */
 #define CM_REG_CH1_FRAME2	0x8C	/* 16-31: count of samples at codec; fragment size */
+#define CM_REG_MISC_CTRL_8768	0x92	/* reg. name the same as 0x18 */
+#define CM_CHB3D8C		0x20	/* 7.1 channels support */
+#define CM_SPD32FMT		0x10	/* SPDIF/IN 32k */
+#define CM_ADC2SPDIF		0x08	/* ADC output to SPDIF/OUT */
+#define CM_SHAREADC		0x04	/* DAC in ADC as Center/LFE */
+#define CM_REALTCMP		0x02	/* monitor the CMPL/CMPR of ADC */
+#define CM_INVLRCK		0x01	/* invert ZVPORT's LRCK */
 
 /*
  * size of i/o region
@@ -458,7 +467,7 @@
 	int opened[2];	/* open mode */
 	struct semaphore open_mutex;
 
-	int mixer_insensitive: 1;
+	unsigned int mixer_insensitive: 1;
 	snd_kcontrol_t *mixer_res_ctl[CM_SAVED_MIXERS];
 	int mixer_res_status[CM_SAVED_MIXERS];
 
@@ -471,8 +480,7 @@
 	snd_rawmidi_t *rmidi;
 
 #ifdef SUPPORT_JOYSTICK
-	struct gameport gameport;
-	struct resource *res_joystick;
+	struct gameport *gameport;
 #endif
 
 	spinlock_t reg_lock;
@@ -674,7 +682,7 @@
 /*
  */
 
-static unsigned int hw_channels[] = {1, 2, 4, 5, 6};
+static unsigned int hw_channels[] = {1, 2, 4, 5, 6, 8};
 static snd_pcm_hw_constraint_list_t hw_constraints_channels_4 = {
 	.count = 3,
 	.list = hw_channels,
@@ -685,6 +693,11 @@
 	.list = hw_channels,
 	.mask = 0,
 };
+static snd_pcm_hw_constraint_list_t hw_constraints_channels_8 = {
+	.count = 6,
+	.list = hw_channels,
+	.mask = 0,
+};
 
 static int set_dac_channels(cmipci_t *cm, cmipci_pcm_t *rec, int channels)
 {
@@ -704,13 +717,20 @@
 			snd_cmipci_clear_bit(cm, CM_REG_CHFORMAT, CM_CHB3D5C);
 			snd_cmipci_set_bit(cm, CM_REG_CHFORMAT, CM_CHB3D);
 		}
-		if (channels == 6) {
+		if (channels >= 6) {
 			snd_cmipci_set_bit(cm, CM_REG_LEGACY_CTRL, CM_CHB3D6C);
 			snd_cmipci_set_bit(cm, CM_REG_MISC_CTRL, CM_ENCENTER);
 		} else {
 			snd_cmipci_clear_bit(cm, CM_REG_LEGACY_CTRL, CM_CHB3D6C);
 			snd_cmipci_clear_bit(cm, CM_REG_MISC_CTRL, CM_ENCENTER);
 		}
+		if (cm->chip_version == 68) {
+			if (channels == 8) {
+				snd_cmipci_set_bit(cm, CM_REG_MISC_CTRL_8768, CM_CHB3D8C);
+			} else {
+				snd_cmipci_clear_bit(cm, CM_REG_MISC_CTRL_8768, CM_CHB3D8C);
+			}
+		}
 		spin_unlock_irq(&cm->reg_lock);
 
 	} else {
@@ -1504,6 +1524,7 @@
 	if ((err = open_device_check(cm, CM_OPEN_PLAYBACK, substream)) < 0)
 		return err;
 	runtime->hw = snd_cmipci_playback;
+	runtime->hw.channels_max = cm->max_channels;
 	snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 0, 0x10000);
 	cm->dig_pcm_status = cm->dig_status;
 	return 0;
@@ -1518,6 +1539,10 @@
 	if ((err = open_device_check(cm, CM_OPEN_CAPTURE, substream)) < 0)
 		return err;
 	runtime->hw = snd_cmipci_capture;
+	if (cm->chip_version == 68) {	// 8768 only supports 44k/48k recording
+		runtime->hw.rate_min = 41000;
+		runtime->hw.rates = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000;
+	}
 	snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 0, 0x10000);
 	return 0;
 }
@@ -1537,8 +1562,10 @@
 			runtime->hw.channels_max = cm->max_channels;
 			if (cm->max_channels == 4)
 				snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, &hw_constraints_channels_4);
-			else
+			else if (cm->max_channels == 6)
 				snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, &hw_constraints_channels_6);
+			else if (cm->max_channels == 8)
+				snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, &hw_constraints_channels_8);
 		}
 		snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 0, 0x10000);
 	}
@@ -2108,8 +2135,8 @@
 	int reg;		/* register index */
 	unsigned int mask;	/* mask bits */
 	unsigned int mask_on;	/* mask bits to turn on */
-	int is_byte: 1;		/* byte access? */
-	int ac3_sensitive: 1;	/* access forbidden during non-audio operation? */
+	unsigned int is_byte: 1;		/* byte access? */
+	unsigned int ac3_sensitive: 1;	/* access forbidden during non-audio operation? */
 } snd_cmipci_switch_args_t;
 
 static int snd_cmipci_uswitch_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
@@ -2346,6 +2373,11 @@
 	spin_unlock_irq(&cm->reg_lock);
 
 	for (idx = 0; idx < ARRAY_SIZE(snd_cmipci_mixers); idx++) {
+		if (cm->chip_version == 68) {	// 8768 has no PCM volume
+			if (!strcmp(snd_cmipci_mixers[idx].name,
+				"PCM Playback Volume"))
+				continue;
+		}
 		if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_cmipci_mixers[idx], cm))) < 0)
 			return err;
 	}
@@ -2496,32 +2528,98 @@
 		}
 	} else {
 		/* check reg 0Ch, bit 26 */
-		if (detect & CM_CHIP_039) {
+		if (detect & CM_CHIP_8768) {
+			cm->chip_version = 68;
+			cm->max_channels = 8;
+			cm->can_ac3_hw = 1;
+			cm->has_dual_dac = 1;
+			cm->can_multi_ch = 1;
+		} else if (detect & CM_CHIP_055) {
+			cm->chip_version = 55;
+			cm->max_channels = 6;
+			cm->can_ac3_hw = 1;
+			cm->has_dual_dac = 1;
+			cm->can_multi_ch = 1;
+		} else if (detect & CM_CHIP_039) {
 			cm->chip_version = 39;
-			if (detect & CM_CHIP_039_6CH)
-				cm->max_channels  = 6;
+			if (detect & CM_CHIP_039_6CH) /* 4 or 6 channels */
+				cm->max_channels = 6;
 			else
 				cm->max_channels = 4;
 			cm->can_ac3_hw = 1;
 			cm->has_dual_dac = 1;
 			cm->can_multi_ch = 1;
 		} else {
-			cm->chip_version = 55; /* 4 or 6 channels */
-			cm->max_channels  = 6;
-			cm->can_ac3_hw = 1;
-			cm->has_dual_dac = 1;
-			cm->can_multi_ch = 1;
+			printk(KERN_ERR "chip %x version not supported\n", detect);
 		}
 	}
+}
 
-	/* added -MCx suffix for chip supporting multi-channels */
-	if (cm->can_multi_ch)
-		sprintf(cm->card->driver + strlen(cm->card->driver),
-			"-MC%d", cm->max_channels);
-	else if (cm->can_ac3_sw)
-		strcpy(cm->card->driver + strlen(cm->card->driver), "-SWIEC");
+#ifdef SUPPORT_JOYSTICK
+static int __devinit snd_cmipci_create_gameport(cmipci_t *cm, int dev)
+{
+	static int ports[] = { 0x201, 0x200, 0 }; /* FIXME: majority is 0x201? */
+	struct gameport *gp;
+	struct resource *r = NULL;
+	int i, io_port = 0;
+
+	if (joystick_port[dev] == 0)
+		return -ENODEV;
+
+	if (joystick_port[dev] == 1) { /* auto-detect */
+		for (i = 0; ports[i]; i++) {
+			io_port = ports[i];
+			r = request_region(io_port, 1, "CMIPCI gameport");
+			if (r)
+				break;
+		}
+	} else {
+		io_port = joystick_port[dev];
+		r = request_region(io_port, 1, "CMIPCI gameport");
+	}
+
+	if (!r) {
+		printk(KERN_WARNING "cmipci: cannot reserve joystick ports\n");
+		return -EBUSY;
+	}
+
+	cm->gameport = gp = gameport_allocate_port();
+	if (!gp) {
+		printk(KERN_ERR "cmipci: cannot allocate memory for gameport\n");
+		release_resource(r);
+		kfree_nocheck(r);
+		return -ENOMEM;
+	}
+	gameport_set_name(gp, "C-Media Gameport");
+	gameport_set_phys(gp, "pci%s/gameport0", pci_name(cm->pci));
+	gp->dev.parent = &cm->pci->dev;
+	gp->io = io_port;
+	gp->port_data = r;
+
+	snd_cmipci_set_bit(cm, CM_REG_FUNCTRL1, CM_JYSTK_EN);
+
+	gameport_register_port(cm->gameport);
+
+	return 0;
 }
 
+static void snd_cmipci_free_gameport(cmipci_t *cm)
+{
+	if (cm->gameport) {
+		struct resource *r = cm->gameport->port_data;
+
+		gameport_unregister_port(cm->gameport);
+		cm->gameport = NULL;
+
+		snd_cmipci_clear_bit(cm, CM_REG_FUNCTRL1, CM_JYSTK_EN);
+		release_resource(r);
+		kfree_nocheck(r);
+	}
+}
+#else
+static inline int snd_cmipci_create_gameport(cmipci_t *cm, int dev) { return -ENOSYS; }
+static inline void snd_cmipci_free_gameport(cmipci_t *cm) { }
+#endif
 
 static int snd_cmipci_free(cmipci_t *cm)
 {
@@ -2541,14 +2639,8 @@
 
 		free_irq(cm->irq, (void *)cm);
 	}
-#ifdef SUPPORT_JOYSTICK
-	if (cm->res_joystick) {
-		gameport_unregister_port(&cm->gameport);
-		snd_cmipci_clear_bit(cm, CM_REG_FUNCTRL1, CM_JYSTK_EN);
-		release_resource(cm->res_joystick);
-		kfree_nocheck(cm->res_joystick);
-	}
-#endif
+
+	snd_cmipci_free_gameport(cm);
 	pci_release_regions(cm->pci);
 	pci_disable_device(cm->pci);
 	kfree(cm);
@@ -2623,7 +2715,15 @@
 	cm->max_channels = 2;
 	cm->do_soft_ac3 = soft_ac3[dev];
 
-	query_chip(cm);
+	if (pci->device != PCI_DEVICE_ID_CMEDIA_CM8338A &&
+	    pci->device != PCI_DEVICE_ID_CMEDIA_CM8338B)
+		query_chip(cm);
+	/* added -MCx suffix for chip supporting multi-channels */
+	if (cm->can_multi_ch)
+		sprintf(cm->card->driver + strlen(cm->card->driver),
+			"-MC%d", cm->max_channels);
+	else if (cm->can_ac3_sw)
+		strcpy(cm->card->driver + strlen(cm->card->driver), "-SWIEC");
 
 	cm->dig_status = SNDRV_PCM_DEFAULT_CON_SPDIF;
 	cm->dig_pcm_status = SNDRV_PCM_DEFAULT_CON_SPDIF;
@@ -2757,31 +2857,9 @@
 	snd_cmipci_set_bit(cm, CM_REG_MISC_CTRL, CM_SPDIF48K|CM_SPDF_AC97);
 #endif /* USE_VAR48KRATE */
 
-#ifdef SUPPORT_JOYSTICK
-	if (joystick_port[dev] > 0) {
-		if (joystick_port[dev] == 1) { /* auto-detect */
-			static int ports[] = { 0x201, 0x200, 0 }; /* FIXME: majority is 0x201? */
-			int i;
-			for (i = 0; ports[i]; i++) {
-				joystick_port[dev] = ports[i];
-				cm->res_joystick = request_region(ports[i], 1, "CMIPCI gameport");
-				if (cm->res_joystick)
-					break;
-			}
-		} else {
-			cm->res_joystick = request_region(joystick_port[dev], 1, "CMIPCI gameport");
-		}
-	}
-	if (cm->res_joystick) {
-		cm->gameport.io = joystick_port[dev];
-		snd_cmipci_set_bit(cm, CM_REG_FUNCTRL1, CM_JYSTK_EN);
-		gameport_register_port(&cm->gameport);
-	} else {
-		if (joystick_port[dev] > 0)
-			printk(KERN_WARNING "cmipci: cannot reserve joystick ports\n");
+	if (snd_cmipci_create_gameport(cm, dev) < 0)
 		snd_cmipci_clear_bit(cm, CM_REG_FUNCTRL1, CM_JYSTK_EN);
-	}
-#endif
+
 	snd_card_set_dev(card, &pci->dev);
 
 	*rcmipci = cm;
diff -Nru a/sound/pci/cs4281.c b/sound/pci/cs4281.c
--- a/sound/pci/cs4281.c	2005-03-11 12:51:51 -08:00
+++ b/sound/pci/cs4281.c	2005-03-11 12:51:51 -08:00
@@ -495,7 +495,7 @@
 	unsigned int midcr;
 	unsigned int uartm;
 
-	struct snd_cs4281_gameport *gameport;
+	struct gameport *gameport;
 
 #ifdef CONFIG_PM
 	u32 suspend_regs[SUSPEND_REGISTERS];
@@ -697,10 +697,11 @@
 
 static int snd_cs4281_trigger(snd_pcm_substream_t *substream, int cmd)
 {
+	unsigned long flags;
 	cs4281_dma_t *dma = (cs4281_dma_t *)substream->runtime->private_data;
 	cs4281_t *chip = snd_pcm_substream_chip(substream);
 
-	spin_lock(&chip->reg_lock);
+	spin_lock_irqsave(&chip->reg_lock, flags);
 	switch (cmd) {
 	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
 		dma->valDCR |= BA0_DCR_MSK;
@@ -727,13 +728,13 @@
 			dma->valFCR &= ~BA0_FCR_FEN;
 		break;
 	default:
-		spin_unlock(&chip->reg_lock);
+		spin_unlock_irqrestore(&chip->reg_lock, flags);
 		return -EINVAL;
 	}
 	snd_cs4281_pokeBA0(chip, dma->regDMR, dma->valDMR);
 	snd_cs4281_pokeBA0(chip, dma->regFCR, dma->valFCR);
 	snd_cs4281_pokeBA0(chip, dma->regDCR, dma->valDCR);
-	spin_unlock(&chip->reg_lock);
+	spin_unlock_irqrestore(&chip->reg_lock, flags);
 	return 0;
 }
 
@@ -1238,38 +1239,29 @@
 
 #if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))
 
-typedef struct snd_cs4281_gameport {
-	struct gameport info;
-	cs4281_t *chip;
-} cs4281_gameport_t;
-
 static void snd_cs4281_gameport_trigger(struct gameport *gameport)
 {
-	cs4281_gameport_t *gp = (cs4281_gameport_t *)gameport;
-	cs4281_t *chip;
-	snd_assert(gp, return);
-	chip = gp->chip;
+	cs4281_t *chip = gameport->port_data;
+
+	snd_assert(chip, return);
 	snd_cs4281_pokeBA0(chip, BA0_JSPT, 0xff);
 }
 
 static unsigned char snd_cs4281_gameport_read(struct gameport *gameport)
 {
-	cs4281_gameport_t *gp = (cs4281_gameport_t *)gameport;
-	cs4281_t *chip;
-	snd_assert(gp, return 0);
-	chip = gp->chip;
+	cs4281_t *chip = gameport->port_data;
+
+	snd_assert(chip, return 0);
 	return snd_cs4281_peekBA0(chip, BA0_JSPT);
 }
 
 #ifdef COOKED_MODE
 static int snd_cs4281_gameport_cooked_read(struct gameport *gameport, int *axes, int *buttons)
 {
-	cs4281_gameport_t *gp = (cs4281_gameport_t *)gameport;
-	cs4281_t *chip;
+	cs4281_t *chip = gameport->port_data;
 	unsigned js1, js2, jst;
 	
-	snd_assert(gp, return 0);
-	chip = gp->chip;
+	snd_assert(chip, return 0);
 
 	js1 = snd_cs4281_peekBA0(chip, BA0_JSC1);
 	js2 = snd_cs4281_peekBA0(chip, BA0_JSC2);
@@ -1282,10 +1274,12 @@
 	axes[2] = ((js2 & JSC2_Y2V_MASK) >> JSC2_Y2V_SHIFT) & 0xFFFF;
 	axes[3] = ((js2 & JSC2_X2V_MASK) >> JSC2_X2V_SHIFT) & 0xFFFF;
 
-	for(jst=0;jst<4;++jst)
-		if(axes[jst]==0xFFFF) axes[jst] = -1;
+	for (jst = 0; jst < 4; ++jst)
+		if (axes[jst] == 0xFFFF) axes[jst] = -1;
 	return 0;
 }
+#else
+#define snd_cs4281_gameport_cooked_read	NULL
 #endif
 
 static int snd_cs4281_gameport_open(struct gameport *gameport, int mode)
@@ -1303,31 +1297,43 @@
 	return 0;
 }
 
-static void __devinit snd_cs4281_gameport(cs4281_t *chip)
+static int __devinit snd_cs4281_create_gameport(cs4281_t *chip)
 {
-	cs4281_gameport_t *gp;
-	gp = kmalloc(sizeof(*gp), GFP_KERNEL);
-	if (! gp) {
-		snd_printk(KERN_ERR "cannot allocate gameport area\n");
-		return;
-	}
-	memset(gp, 0, sizeof(*gp));
-	gp->info.open = snd_cs4281_gameport_open;
-	gp->info.read = snd_cs4281_gameport_read;
-	gp->info.trigger = snd_cs4281_gameport_trigger;
-#ifdef COOKED_MODE
-	gp->info.cooked_read = snd_cs4281_gameport_cooked_read;
-#endif
-	gp->chip = chip;
-	chip->gameport = gp;
+	struct gameport *gp;
+
+	chip->gameport = gp = gameport_allocate_port();
+	if (!gp) {
+		printk(KERN_ERR "cs4281: cannot allocate memory for gameport\n");
+		return -ENOMEM;
+	}
+
+	gameport_set_name(gp, "CS4281 Gameport");
+	gameport_set_phys(gp, "pci%s/gameport0", pci_name(chip->pci));
+	gp->dev.parent = &chip->pci->dev;
+	gp->open = snd_cs4281_gameport_open;
+	gp->read = snd_cs4281_gameport_read;
+	gp->trigger = snd_cs4281_gameport_trigger;
+	gp->cooked_read = snd_cs4281_gameport_cooked_read;
+	gp->port_data = chip;
 
 	snd_cs4281_pokeBA0(chip, BA0_JSIO, 0xFF); // ?
 	snd_cs4281_pokeBA0(chip, BA0_JSCTL, JSCTL_SP_MEDIUM_SLOW);
-	gameport_register_port(&gp->info);
+
+	gameport_register_port(gp);
+
+	return 0;
 }
 
+static void snd_cs4281_free_gameport(cs4281_t *chip)
+{
+	if (chip->gameport) {
+		gameport_unregister_port(chip->gameport);
+		chip->gameport = NULL;
+	}
+}
 #else
-#define snd_cs4281_gameport(chip) /*NOP*/
+static inline int snd_cs4281_gameport(cs4281_t *chip) { return -ENOSYS; }
+static inline void snd_cs4281_gameport_free(cs4281_t *chip) { }
 #endif /* CONFIG_GAMEPORT || (MODULE && CONFIG_GAMEPORT_MODULE) */
 
 
@@ -1337,12 +1343,8 @@
 
 static int snd_cs4281_free(cs4281_t *chip)
 {
-#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))
-	if (chip->gameport) {
-		gameport_unregister_port(&chip->gameport->info);
-		kfree(chip->gameport);
-	}
-#endif
+	snd_cs4281_free_gameport(chip);
+
 	if (chip->irq >= 0)
 		synchronize_irq(chip->irq);
 
@@ -1376,8 +1378,8 @@
 
 static int snd_cs4281_chip_init(cs4281_t *chip); /* defined below */
 #ifdef CONFIG_PM
-static int cs4281_suspend(snd_card_t *card, unsigned int state);
-static int cs4281_resume(snd_card_t *card, unsigned int state);
+static int cs4281_suspend(snd_card_t *card, pm_message_t state);
+static int cs4281_resume(snd_card_t *card);
 #endif
 
 static int __devinit snd_cs4281_create(snd_card_t * card,
@@ -1847,6 +1849,7 @@
 static irqreturn_t snd_cs4281_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
 	cs4281_t *chip = dev_id;
+	unsigned long flags;
 	unsigned int status, dma, val;
 	cs4281_dma_t *cdma;
 
@@ -1862,7 +1865,7 @@
 		for (dma = 0; dma < 4; dma++)
 			if (status & BA0_HISR_DMA(dma)) {
 				cdma = &chip->dma[dma];
-				spin_lock(&chip->reg_lock);
+				spin_lock_irqsave(&chip->reg_lock, flags);
 				/* ack DMA IRQ */
 				val = snd_cs4281_peekBA0(chip, cdma->regHDSR);
 				/* workaround, sometimes CS4281 acknowledges */
@@ -1871,16 +1874,16 @@
 				if ((val & BA0_HDSR_DHTC) && !(cdma->frag & 1)) {
 					cdma->frag--;
 					chip->spurious_dhtc_irq++;
-					spin_unlock(&chip->reg_lock);
+					spin_unlock_irqrestore(&chip->reg_lock, flags);
 					continue;
 				}
 				if ((val & BA0_HDSR_DTC) && (cdma->frag & 1)) {
 					cdma->frag--;
 					chip->spurious_dtc_irq++;
-					spin_unlock(&chip->reg_lock);
+					spin_unlock_irqrestore(&chip->reg_lock, flags);
 					continue;
 				}
-				spin_unlock(&chip->reg_lock);
+				spin_unlock_irqrestore(&chip->reg_lock, flags);
 				snd_pcm_period_elapsed(cdma->substream);
 			}
 	}
@@ -1888,14 +1891,12 @@
 	if ((status & BA0_HISR_MIDI) && chip->rmidi) {
 		unsigned char c;
 		
-		spin_lock(&chip->reg_lock);
+		spin_lock_irqsave(&chip->reg_lock, flags);
 		while ((snd_cs4281_peekBA0(chip, BA0_MIDSR) & BA0_MIDSR_RBE) == 0) {
 			c = snd_cs4281_peekBA0(chip, BA0_MIDRP);
 			if ((chip->midcr & BA0_MIDCR_RIE) == 0)
 				continue;
-			spin_unlock(&chip->reg_lock);
 			snd_rawmidi_receive(chip->midi_input, &c, 1);
-			spin_lock(&chip->reg_lock);
 		}
 		while ((snd_cs4281_peekBA0(chip, BA0_MIDSR) & BA0_MIDSR_TBF) == 0) {
 			if ((chip->midcr & BA0_MIDCR_TIE) == 0)
@@ -1907,7 +1908,7 @@
 			}
 			snd_cs4281_pokeBA0(chip, BA0_MIDWP, c);
 		}
-		spin_unlock(&chip->reg_lock);
+		spin_unlock_irqrestore(&chip->reg_lock, flags);
 	}
 
 	/* EOI to the PCI part... reenables interrupts */
@@ -1990,7 +1991,7 @@
 		snd_card_free(card);
 		return err;
 	}
-	snd_cs4281_gameport(chip);
+	snd_cs4281_create_gameport(chip);
 	strcpy(card->driver, "CS4281");
 	strcpy(card->shortname, "Cirrus Logic CS4281");
 	sprintf(card->longname, "%s at 0x%lx, irq %d",
@@ -2037,7 +2038,7 @@
 
 #define CLKCR1_CKRA                             0x00010000L
 
-static int cs4281_suspend(snd_card_t *card, unsigned int state)
+static int cs4281_suspend(snd_card_t *card, pm_message_t state)
 {
 	cs4281_t *chip = card->pm_private_data;
 	u32 ulCLK;
@@ -2082,7 +2083,7 @@
 	return 0;
 }
 
-static int cs4281_resume(snd_card_t *card, unsigned int state)
+static int cs4281_resume(snd_card_t *card)
 {
 	cs4281_t *chip = card->pm_private_data;
 	unsigned int i;
diff -Nru a/sound/pci/cs46xx/cs46xx_lib.c b/sound/pci/cs46xx/cs46xx_lib.c
--- a/sound/pci/cs46xx/cs46xx_lib.c	2005-03-11 12:51:41 -08:00
+++ b/sound/pci/cs46xx/cs46xx_lib.c	2005-03-11 12:51:41 -08:00
@@ -765,6 +765,9 @@
 static int snd_cs46xx_playback_trigger(snd_pcm_substream_t * substream,
 				       int cmd)
 {
+#ifndef CONFIG_SND_CS46XX_NEW_DSP
+	unsigned long flags;
+#endif
 	cs46xx_t *chip = snd_pcm_substream_chip(substream);
 	/*snd_pcm_runtime_t *runtime = substream->runtime;*/
 	int result = 0;
@@ -789,7 +792,7 @@
 		if (substream->runtime->periods != CS46XX_FRAGS)
 			snd_cs46xx_playback_transfer(substream);
 #else
-		spin_lock(&chip->reg_lock);
+		spin_lock_irqsave(&chip->reg_lock, flags);
 		if (substream->runtime->periods != CS46XX_FRAGS)
 			snd_cs46xx_playback_transfer(substream);
 		{ unsigned int tmp;
@@ -797,7 +800,7 @@
 		tmp &= 0x0000ffff;
 		snd_cs46xx_poke(chip, BA1_PCTL, chip->play_ctl | tmp);
 		}
-		spin_unlock(&chip->reg_lock);
+		spin_unlock_irqrestore(&chip->reg_lock, flags);
 #endif
 		break;
 	case SNDRV_PCM_TRIGGER_STOP:
@@ -810,13 +813,13 @@
 		if (!cpcm->pcm_channel->unlinked)
 			cs46xx_dsp_pcm_unlink(chip,cpcm->pcm_channel);
 #else
-		spin_lock(&chip->reg_lock);
+		spin_lock_irqsave(&chip->reg_lock, flags);
 		{ unsigned int tmp;
 		tmp = snd_cs46xx_peek(chip, BA1_PCTL);
 		tmp &= 0x0000ffff;
 		snd_cs46xx_poke(chip, BA1_PCTL, tmp);
 		}
-		spin_unlock(&chip->reg_lock);
+		spin_unlock_irqrestore(&chip->reg_lock, flags);
 #endif
 		break;
 	default:
@@ -830,11 +833,12 @@
 static int snd_cs46xx_capture_trigger(snd_pcm_substream_t * substream,
 				      int cmd)
 {
+	unsigned long flags;
 	cs46xx_t *chip = snd_pcm_substream_chip(substream);
 	unsigned int tmp;
 	int result = 0;
 
-	spin_lock(&chip->reg_lock);
+	spin_lock_irqsave(&chip->reg_lock, flags);
 	switch (cmd) {
 	case SNDRV_PCM_TRIGGER_START:
 	case SNDRV_PCM_TRIGGER_RESUME:
@@ -852,7 +856,7 @@
 		result = -EINVAL;
 		break;
 	}
-	spin_unlock(&chip->reg_lock);
+	spin_unlock_irqrestore(&chip->reg_lock, flags);
 
 	return result;
 }
@@ -1149,6 +1153,7 @@
 
 static irqreturn_t snd_cs46xx_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
+	unsigned long flags;
 	cs46xx_t *chip = dev_id;
 	u32 status1;
 #ifdef CONFIG_SND_CS46XX_NEW_DSP
@@ -1212,14 +1217,12 @@
 	if ((status1 & HISR_MIDI) && chip->rmidi) {
 		unsigned char c;
 		
-		spin_lock(&chip->reg_lock);
+		spin_lock_irqsave(&chip->reg_lock, flags);
 		while ((snd_cs46xx_peekBA0(chip, BA0_MIDSR) & MIDSR_RBE) == 0) {
 			c = snd_cs46xx_peekBA0(chip, BA0_MIDRP);
 			if ((chip->midcr & MIDCR_RIE) == 0)
 				continue;
-			spin_unlock(&chip->reg_lock);
 			snd_rawmidi_receive(chip->midi_input, &c, 1);
-			spin_lock(&chip->reg_lock);
 		}
 		while ((snd_cs46xx_peekBA0(chip, BA0_MIDSR) & MIDSR_TBF) == 0) {
 			if ((chip->midcr & MIDCR_TIE) == 0)
@@ -1231,7 +1234,7 @@
 			}
 			snd_cs46xx_pokeBA0(chip, BA0_MIDWP, c);
 		}
-		spin_unlock(&chip->reg_lock);
+		spin_unlock_irqrestore(&chip->reg_lock, flags);
 	}
 	/*
 	 *  EOI to the PCI part....reenables interrupts
@@ -2690,37 +2693,28 @@
 
 #if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))
 
-typedef struct snd_cs46xx_gameport {
-	struct gameport info;
-	cs46xx_t *chip;
-} cs46xx_gameport_t;
-
 static void snd_cs46xx_gameport_trigger(struct gameport *gameport)
 {
-	cs46xx_gameport_t *gp = (cs46xx_gameport_t *)gameport;
-	cs46xx_t *chip;
-	snd_assert(gp, return);
-	chip = gp->chip;
+	cs46xx_t *chip = gameport->port_data;
+
+	snd_assert(chip, return);
 	snd_cs46xx_pokeBA0(chip, BA0_JSPT, 0xFF);  //outb(gameport->io, 0xFF);
 }
 
 static unsigned char snd_cs46xx_gameport_read(struct gameport *gameport)
 {
-	cs46xx_gameport_t *gp = (cs46xx_gameport_t *)gameport;
-	cs46xx_t *chip;
-	snd_assert(gp, return 0);
-	chip = gp->chip;
+	cs46xx_t *chip = gameport->port_data;
+
+	snd_assert(chip, return 0);
 	return snd_cs46xx_peekBA0(chip, BA0_JSPT); //inb(gameport->io);
 }
 
 static int snd_cs46xx_gameport_cooked_read(struct gameport *gameport, int *axes, int *buttons)
 {
-	cs46xx_gameport_t *gp = (cs46xx_gameport_t *)gameport;
-	cs46xx_t *chip;
+	cs46xx_t *chip = gameport->port_data;
 	unsigned js1, js2, jst;
-	
-	snd_assert(gp, return 0);
-	chip = gp->chip;
+
+	snd_assert(chip, return 0);
 
 	js1 = snd_cs46xx_peekBA0(chip, BA0_JSC1);
 	js2 = snd_cs46xx_peekBA0(chip, BA0_JSC2);
@@ -2751,33 +2745,44 @@
 	return 0;
 }
 
-void __devinit snd_cs46xx_gameport(cs46xx_t *chip)
+int __devinit snd_cs46xx_gameport(cs46xx_t *chip)
 {
-	cs46xx_gameport_t *gp;
-	gp = kmalloc(sizeof(*gp), GFP_KERNEL);
-	if (! gp) {
-		snd_printk("cannot allocate gameport area\n");
-		return;
+	struct gameport *gp;
+
+	chip->gameport = gp = gameport_allocate_port();
+	if (!gp) {
+		printk(KERN_ERR "cs46xx: cannot allocate memory for gameport\n");
+		return -ENOMEM;
 	}
-	memset(gp, 0, sizeof(*gp));
-	gp->info.open = snd_cs46xx_gameport_open;
-	gp->info.read = snd_cs46xx_gameport_read;
-	gp->info.trigger = snd_cs46xx_gameport_trigger;
-	gp->info.cooked_read = snd_cs46xx_gameport_cooked_read;
-	gp->chip = chip;
-	chip->gameport = gp;
+
+	gameport_set_name(gp, "CS46xx Gameport");
+	gameport_set_phys(gp, "pci%s/gameport0", pci_name(chip->pci));
+	gp->dev.parent = &chip->pci->dev;
+	gp->port_data = chip;
+
+	gp->open = snd_cs46xx_gameport_open;
+	gp->read = snd_cs46xx_gameport_read;
+	gp->trigger = snd_cs46xx_gameport_trigger;
+	gp->cooked_read = snd_cs46xx_gameport_cooked_read;
 
 	snd_cs46xx_pokeBA0(chip, BA0_JSIO, 0xFF); // ?
 	snd_cs46xx_pokeBA0(chip, BA0_JSCTL, JSCTL_SP_MEDIUM_SLOW);
-	gameport_register_port(&gp->info);
-}
 
-#else
+	gameport_register_port(gp);
 
-void __devinit snd_cs46xx_gameport(cs46xx_t *chip)
-{
+	return 0;
 }
 
+static inline void snd_cs46xx_remove_gameport(cs46xx_t *chip)
+{
+	if (chip->gameport) {
+		gameport_unregister_port(chip->gameport);
+		chip->gameport = NULL;
+	}
+}
+#else
+int __devinit snd_cs46xx_gameport(cs46xx_t *chip) { return -ENOSYS; }
+static inline void snd_cs46xx_remove_gameport(cs46xx_t *chip) { }
 #endif /* CONFIG_GAMEPORT */
 
 /*
@@ -2893,12 +2898,7 @@
 	if (chip->active_ctrl)
 		chip->active_ctrl(chip, 1);
 
-#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))
-	if (chip->gameport) {
-		gameport_unregister_port(&chip->gameport->info);
-		kfree(chip->gameport);
-	}
-#endif
+	snd_cs46xx_remove_gameport(chip);
 
 	if (chip->amplifier_ctrl)
 		chip->amplifier_ctrl(chip, -chip->amplifier); /* force to off */
@@ -3704,7 +3704,7 @@
  * APM support
  */
 #ifdef CONFIG_PM
-static int snd_cs46xx_suspend(snd_card_t *card, unsigned int state)
+static int snd_cs46xx_suspend(snd_card_t *card, pm_message_t state)
 {
 	cs46xx_t *chip = card->pm_private_data;
 	int amp_saved;
@@ -3728,7 +3728,7 @@
 	return 0;
 }
 
-static int snd_cs46xx_resume(snd_card_t *card, unsigned int state)
+static int snd_cs46xx_resume(snd_card_t *card)
 {
 	cs46xx_t *chip = card->pm_private_data;
 	int amp_saved;
diff -Nru a/sound/pci/emu10k1/emu10k1.c b/sound/pci/emu10k1/emu10k1.c
--- a/sound/pci/emu10k1/emu10k1.c	2005-03-11 12:51:40 -08:00
+++ b/sound/pci/emu10k1/emu10k1.c	2005-03-11 12:51:40 -08:00
@@ -149,6 +149,11 @@
 		return err;
 	}
 
+	if ((err = snd_emu10k1_pcm_multi(emu, 3, NULL)) < 0) {
+		snd_card_free(card);
+		return err;
+	}		
+
 	if (emu->audigy) {
 		if ((err = snd_emu10k1_audigy_midi(emu)) < 0) {
 			snd_card_free(card);
diff -Nru a/sound/pci/emu10k1/emu10k1_callback.c b/sound/pci/emu10k1/emu10k1_callback.c
--- a/sound/pci/emu10k1/emu10k1_callback.c	2005-03-11 12:51:42 -08:00
+++ b/sound/pci/emu10k1/emu10k1_callback.c	2005-03-11 12:51:42 -08:00
@@ -291,7 +291,7 @@
 			if (vp->ch < 0) {
 				/* allocate a voice */
 				emu10k1_voice_t *hwvoice;
-				if (snd_emu10k1_voice_alloc(hw, EMU10K1_SYNTH, 0, &hwvoice) < 0 || hwvoice == NULL)
+				if (snd_emu10k1_voice_alloc(hw, EMU10K1_SYNTH, 1, &hwvoice) < 0 || hwvoice == NULL)
 					continue;
 				vp->ch = hwvoice->number;
 				emu->num_voices++;
diff -Nru a/sound/pci/emu10k1/emu10k1_main.c b/sound/pci/emu10k1/emu10k1_main.c
--- a/sound/pci/emu10k1/emu10k1_main.c	2005-03-11 12:51:51 -08:00
+++ b/sound/pci/emu10k1/emu10k1_main.c	2005-03-11 12:51:51 -08:00
@@ -205,6 +205,15 @@
 		/* Setup SRCMulti Input Audio Enable */
 		outl(0x7b0000, emu->port + 0x20);
 		outl(0xFF000000, emu->port + 0x24);
+
+		/* Setup SPDIF Out Audio Enable */
+		/* The Audigy 2 Value has a separate SPDIF out,
+		 * so no need for a mixer switch
+		 */
+		outl(0x7a0000, emu->port + 0x20);
+		outl(0xFF000000, emu->port + 0x24);
+		tmp = inl(emu->port + A_IOCFG) & ~0x8; /* Clear bit 3 */
+		outl(tmp, emu->port + A_IOCFG);
 	}
 
 
diff -Nru a/sound/pci/emu10k1/emu10k1x.c b/sound/pci/emu10k1/emu10k1x.c
--- a/sound/pci/emu10k1/emu10k1x.c	2005-03-11 12:51:46 -08:00
+++ b/sound/pci/emu10k1/emu10k1x.c	2005-03-11 12:51:46 -08:00
@@ -1265,6 +1265,7 @@
 
 static void do_emu10k1x_midi_interrupt(emu10k1x_t *emu, emu10k1x_midi_t *midi, unsigned int status)
 {
+	unsigned long flags;
 	unsigned char byte;
 
 	if (midi->rmidi == NULL) {
@@ -1278,15 +1279,13 @@
 			mpu401_clear_rx(emu, midi);
 		} else {
 			byte = mpu401_read_data(emu, midi);
-			spin_unlock(&midi->input_lock);
 			if (midi->substream_input)
 				snd_rawmidi_receive(midi->substream_input, &byte, 1);
-			spin_lock(&midi->input_lock);
 		}
 	}
 	spin_unlock(&midi->input_lock);
 
-	spin_lock(&midi->output_lock);
+	spin_lock_irqsave(&midi->output_lock, flags);
 	if ((status & midi->ipr_tx) && mpu401_output_ready(emu, midi)) {
 		if (midi->substream_output &&
 		    snd_rawmidi_transmit(midi->substream_output, &byte, 1) == 1) {
@@ -1295,7 +1294,7 @@
 			snd_emu10k1x_intr_disable(emu, midi->tx_enable);
 		}
 	}
-	spin_unlock(&midi->output_lock);
+	spin_unlock_irqrestore(&midi->output_lock, flags);
 }
 
 static void snd_emu10k1x_midi_interrupt(emu10k1x_t *emu, unsigned int status)
diff -Nru a/sound/pci/emu10k1/emufx.c b/sound/pci/emu10k1/emufx.c
--- a/sound/pci/emu10k1/emufx.c	2005-03-11 12:51:46 -08:00
+++ b/sound/pci/emu10k1/emufx.c	2005-03-11 12:51:46 -08:00
@@ -468,10 +468,13 @@
 static void snd_emu10k1_write_op(emu10k1_fx8010_code_t *icode, unsigned int *ptr,
 				 u32 op, u32 r, u32 a, u32 x, u32 y)
 {
+	u_int32_t *code;
 	snd_assert(*ptr < 512, return);
+	code = (u_int32_t *)icode->code + (*ptr) * 2;
 	set_bit(*ptr, icode->code_valid);
-	icode->code[(*ptr)   * 2 + 0] = ((x & 0x3ff) << 10) | (y & 0x3ff);
-	icode->code[(*ptr)++ * 2 + 1] = ((op & 0x0f) << 20) | ((r & 0x3ff) << 10) | (a & 0x3ff);
+	code[0] = ((x & 0x3ff) << 10) | (y & 0x3ff);
+	code[1] = ((op & 0x0f) << 20) | ((r & 0x3ff) << 10) | (a & 0x3ff);
+	(*ptr)++;
 }
 
 #define OP(icode, ptr, op, r, a, x, y) \
@@ -480,10 +483,13 @@
 static void snd_emu10k1_audigy_write_op(emu10k1_fx8010_code_t *icode, unsigned int *ptr,
 					u32 op, u32 r, u32 a, u32 x, u32 y)
 {
+	u_int32_t *code;
 	snd_assert(*ptr < 1024, return);
+	code = (u_int32_t *)icode->code + (*ptr) * 2;
 	set_bit(*ptr, icode->code_valid);
-	icode->code[(*ptr)   * 2 + 0] = ((x & 0x7ff) << 12) | (y & 0x7ff);
-	icode->code[(*ptr)++ * 2 + 1] = ((op & 0x0f) << 24) | ((r & 0x7ff) << 12) | (a & 0x7ff);
+	code[0] = ((x & 0x7ff) << 12) | (y & 0x7ff);
+	code[1] = ((op & 0x0f) << 24) | ((r & 0x7ff) << 12) | (a & 0x7ff);
+	(*ptr)++;
 }
 
 #define A_OP(icode, ptr, op, r, a, x, y) \
@@ -994,17 +1000,19 @@
 	u32 ptr;
 	emu10k1_fx8010_code_t *icode = NULL;
 	emu10k1_fx8010_control_gpr_t *controls = NULL, *ctl;
+	u32 *gpr_map;
 	mm_segment_t seg;
 
 	spin_lock_init(&emu->fx8010.irq_lock);
 	INIT_LIST_HEAD(&emu->fx8010.gpr_ctl);
 
 	if ((icode = kcalloc(1, sizeof(*icode), GFP_KERNEL)) == NULL ||
-	    (icode->gpr_map = kcalloc(512 + 256 + 256 + 2 * 1024, sizeof(u_int32_t), GFP_KERNEL)) == NULL ||
+	    (icode->gpr_map = (u_int32_t __user *)kcalloc(512 + 256 + 256 + 2 * 1024, sizeof(u_int32_t), GFP_KERNEL)) == NULL ||
 	    (controls = kcalloc(SND_EMU10K1_GPR_CONTROLS, sizeof(*controls), GFP_KERNEL)) == NULL) {
 		err = -ENOMEM;
 		goto __err;
 	}
+	gpr_map = (u32 *)icode->gpr_map;
 
 	icode->tram_data_map = icode->gpr_map + 512;
 	icode->tram_addr_map = icode->tram_data_map + 256;
@@ -1065,10 +1073,10 @@
 	snd_emu10k1_init_stereo_control(&controls[nctl++], "Wave Playback Volume", gpr, 100);
 	gpr += 2;
 
-	/* Music Playback */
+	/* Synth Playback */
 	A_OP(icode, &ptr, iMAC0, A_GPR(stereo_mix+0), A_GPR(stereo_mix+0), A_GPR(gpr), A_FXBUS(FXBUS_MIDI_LEFT));
 	A_OP(icode, &ptr, iMAC0, A_GPR(stereo_mix+1), A_GPR(stereo_mix+1), A_GPR(gpr+1), A_FXBUS(FXBUS_MIDI_RIGHT));
-	snd_emu10k1_init_stereo_control(&controls[nctl++], "Music Playback Volume", gpr, 100);
+	snd_emu10k1_init_stereo_control(&controls[nctl++], "Synth Playback Volume", gpr, 100);
 	gpr += 2;
 
 	/* Wave (PCM) Capture */
@@ -1077,10 +1085,10 @@
 	snd_emu10k1_init_stereo_control(&controls[nctl++], "PCM Capture Volume", gpr, 0);
 	gpr += 2;
 
-	/* Music Capture */
+	/* Synth Capture */
 	A_OP(icode, &ptr, iMAC0, A_GPR(capture+0), A_GPR(capture+0), A_GPR(gpr), A_FXBUS(FXBUS_MIDI_LEFT));
 	A_OP(icode, &ptr, iMAC0, A_GPR(capture+1), A_GPR(capture+1), A_GPR(gpr+1), A_FXBUS(FXBUS_MIDI_RIGHT));
-	snd_emu10k1_init_stereo_control(&controls[nctl++], "Music Capture Volume", gpr, 0);
+	snd_emu10k1_init_stereo_control(&controls[nctl++], "Synth Capture Volume", gpr, 0);
 	gpr += 2;
 
 	/*
@@ -1331,8 +1339,8 @@
 	/* A_PUT_STEREO_OUTPUT(A_EXTOUT_FRONT_L, A_EXTOUT_FRONT_R, playback + SND_EMU10K1_PLAYBACK_CHANNELS); */
 
 	/* IEC958 Optical Raw Playback Switch */ 
-	icode->gpr_map[gpr++] = 0x1008;
-	icode->gpr_map[gpr++] = 0xffff0000;
+	gpr_map[gpr++] = 0x1008;
+	gpr_map[gpr++] = 0xffff0000;
 	for (z = 0; z < 2; z++) {
 		A_OP(icode, &ptr, iMAC0, A_GPR(tmp + 2), A_FXBUS(FXBUS_PT_LEFT + z), A_C_00000000, A_C_00000000);
 		A_OP(icode, &ptr, iSKIP, A_GPR_COND, A_GPR_COND, A_GPR(gpr - 2), A_C_00000001);
@@ -1358,6 +1366,11 @@
 	A_PUT_OUTPUT(A_EXTOUT_ADC_CAP_R, capture+1);
 #endif
 
+	/* EFX capture - capture the 16 EXTINs */
+	for (z = 0; z < 16; z++) {
+		A_OP(icode, &ptr, iACC3, A_FXBUS2(z), A_C_00000000, A_C_00000000, A_EXTIN(z));
+	}
+	
 	/*
 	 * ok, set up done..
 	 */
@@ -1373,16 +1386,14 @@
 
 	seg = snd_enter_user();
 	icode->gpr_add_control_count = nctl;
-	icode->gpr_add_controls = controls;
+	icode->gpr_add_controls = (emu10k1_fx8010_control_gpr_t __user *)controls;
 	err = snd_emu10k1_icode_poke(emu, icode);
 	snd_leave_user(seg);
 
  __err:
- 	if (controls != NULL)
-		kfree(controls);
+	kfree(controls);
 	if (icode != NULL) {
-		if (icode->gpr_map != NULL)
-			kfree(icode->gpr_map);
+		kfree((void *)icode->gpr_map);
 		kfree(icode);
 	}
 	return err;
@@ -1448,6 +1459,7 @@
 	emu10k1_fx8010_code_t *icode;
 	emu10k1_fx8010_pcm_t *ipcm = NULL;
 	emu10k1_fx8010_control_gpr_t *controls = NULL, *ctl;
+	u32 *gpr_map;
 	mm_segment_t seg;
 
 	spin_lock_init(&emu->fx8010.irq_lock);
@@ -1455,12 +1467,13 @@
 
 	if ((icode = kcalloc(1, sizeof(*icode), GFP_KERNEL)) == NULL)
 		return -ENOMEM;
-	if ((icode->gpr_map = kcalloc(256 + 160 + 160 + 2 * 512, sizeof(u_int32_t), GFP_KERNEL)) == NULL ||
+	if ((icode->gpr_map = (u_int32_t __user *)kcalloc(256 + 160 + 160 + 2 * 512, sizeof(u_int32_t), GFP_KERNEL)) == NULL ||
             (controls = kcalloc(SND_EMU10K1_GPR_CONTROLS, sizeof(emu10k1_fx8010_control_gpr_t), GFP_KERNEL)) == NULL ||
 	    (ipcm = kcalloc(1, sizeof(*ipcm), GFP_KERNEL)) == NULL) {
 		err = -ENOMEM;
 		goto __err;
 	}
+	gpr_map = (u32 *)icode->gpr_map;
 
 	icode->tram_data_map = icode->gpr_map + 256;
 	icode->tram_addr_map = icode->tram_data_map + 160;
@@ -1515,19 +1528,19 @@
 	ipcm->etram[0] = 0;
 	ipcm->etram[1] = 1;
 
-	icode->gpr_map[gpr + 0] = 0xfffff000;
-	icode->gpr_map[gpr + 1] = 0xffff0000;
-	icode->gpr_map[gpr + 2] = 0x70000000;
-	icode->gpr_map[gpr + 3] = 0x00000007;
-	icode->gpr_map[gpr + 4] = 0x001f << 11;
-	icode->gpr_map[gpr + 5] = 0x001c << 11;
-	icode->gpr_map[gpr + 6] = (0x22  - 0x01) - 1;	/* skip at 01 to 22 */
-	icode->gpr_map[gpr + 7] = (0x22  - 0x06) - 1;	/* skip at 06 to 22 */
-	icode->gpr_map[gpr + 8] = 0x2000000 + (2<<11);
-	icode->gpr_map[gpr + 9] = 0x4000000 + (2<<11);
-	icode->gpr_map[gpr + 10] = 1<<11;
-	icode->gpr_map[gpr + 11] = (0x24 - 0x0a) - 1;	/* skip at 0a to 24 */
-	icode->gpr_map[gpr + 12] = 0;
+	gpr_map[gpr + 0] = 0xfffff000;
+	gpr_map[gpr + 1] = 0xffff0000;
+	gpr_map[gpr + 2] = 0x70000000;
+	gpr_map[gpr + 3] = 0x00000007;
+	gpr_map[gpr + 4] = 0x001f << 11;
+	gpr_map[gpr + 5] = 0x001c << 11;
+	gpr_map[gpr + 6] = (0x22  - 0x01) - 1;	/* skip at 01 to 22 */
+	gpr_map[gpr + 7] = (0x22  - 0x06) - 1;	/* skip at 06 to 22 */
+	gpr_map[gpr + 8] = 0x2000000 + (2<<11);
+	gpr_map[gpr + 9] = 0x4000000 + (2<<11);
+	gpr_map[gpr + 10] = 1<<11;
+	gpr_map[gpr + 11] = (0x24 - 0x0a) - 1;	/* skip at 0a to 24 */
+	gpr_map[gpr + 12] = 0;
 
 	/* if the trigger flag is not set, skip */
 	/* 00: */ OP(icode, &ptr, iMAC0, C_00000000, GPR(ipcm->gpr_trigger), C_00000000, C_00000000);
@@ -1608,19 +1621,19 @@
 	snd_emu10k1_init_stereo_onoff_control(controls + i++, "Wave Capture Switch", gpr + 2, 0);
 	gpr += 4;
 
-	/* Music Playback Volume */
+	/* Synth Playback Volume */
 	for (z = 0; z < 2; z++)
 		VOLUME_ADD(icode, &ptr, playback + z, 2 + z, gpr + z);
-	snd_emu10k1_init_stereo_control(controls + i++, "Music Playback Volume", gpr, 100);
+	snd_emu10k1_init_stereo_control(controls + i++, "Synth Playback Volume", gpr, 100);
 	gpr += 2;
 
-	/* Music Capture Volume + Switch */
+	/* Synth Capture Volume + Switch */
 	for (z = 0; z < 2; z++) {
 		SWITCH(icode, &ptr, tmp + 0, 2 + z, gpr + 2 + z);
 		VOLUME_ADD(icode, &ptr, capture + z, tmp + 0, gpr + z);
 	}
-	snd_emu10k1_init_stereo_control(controls + i++, "Music Capture Volume", gpr, 0);
-	snd_emu10k1_init_stereo_onoff_control(controls + i++, "Music Capture Switch", gpr + 2, 0);
+	snd_emu10k1_init_stereo_control(controls + i++, "Synth Capture Volume", gpr, 0);
+	snd_emu10k1_init_stereo_onoff_control(controls + i++, "Synth Capture Switch", gpr + 2, 0);
 	gpr += 4;
 
 	/* Surround Digital Playback Volume (renamed later without Digital) */
@@ -1930,6 +1943,24 @@
 	if (emu->fx8010.extout_mask & (1<<EXTOUT_MIC_CAP))
 		OP(icode, &ptr, iACC3, EXTOUT(EXTOUT_MIC_CAP), GPR(capture + 2), C_00000000, C_00000000);
 
+	/* EFX capture - capture the 16 EXTINS */
+	OP(icode, &ptr, iACC3, FXBUS2(14), C_00000000, C_00000000, EXTIN(0));
+	OP(icode, &ptr, iACC3, FXBUS2(15), C_00000000, C_00000000, EXTIN(1));
+	OP(icode, &ptr, iACC3, FXBUS2(0), C_00000000, C_00000000, EXTIN(2));
+	OP(icode, &ptr, iACC3, FXBUS2(3), C_00000000, C_00000000, EXTIN(3));
+	/* Dont connect anything to FXBUS2 1 and 2.  These are shared with 
+	 * Center/LFE on the SBLive 5.1.  The kX driver only changes the 
+	 * routing when it detects an SBLive 5.1.
+	 *
+	 * Since only 14 of the 16 EXTINs are used, this is not a big problem.  
+	 * We route AC97L and R to FX capture 14 and 15, SPDIF CD in to FX capture 
+	 * 0 and 3, then the rest of the EXTINs to the corresponding FX capture 
+	 * channel.
+	 */
+	for (z = 4; z < 14; z++) {
+		OP(icode, &ptr, iACC3, FXBUS2(z), C_00000000, C_00000000, EXTIN(z));
+	}
+
 	if (gpr > tmp) {
 		snd_BUG();
 		err = -EIO;
@@ -1949,19 +1980,16 @@
 		goto __err;
 	seg = snd_enter_user();
 	icode->gpr_add_control_count = i;
-	icode->gpr_add_controls = controls;
+	icode->gpr_add_controls = (emu10k1_fx8010_control_gpr_t __user *)controls;
 	err = snd_emu10k1_icode_poke(emu, icode);
 	snd_leave_user(seg);
 	if (err >= 0)
 		err = snd_emu10k1_ipcm_poke(emu, ipcm);
       __err:
-      	if (ipcm != NULL)
-		kfree(ipcm);
-	if (controls != NULL)
-		kfree(controls);
+	kfree(ipcm);
+	kfree(controls);
 	if (icode != NULL) {
-		if (icode->gpr_map != NULL)
-			kfree(icode->gpr_map);
+		kfree((void *)icode->gpr_map);
 		kfree(icode);
 	}
 	return err;
diff -Nru a/sound/pci/emu10k1/emumixer.c b/sound/pci/emu10k1/emumixer.c
--- a/sound/pci/emu10k1/emumixer.c	2005-03-11 12:51:51 -08:00
+++ b/sound/pci/emu10k1/emumixer.c	2005-03-11 12:51:51 -08:00
@@ -67,6 +67,91 @@
 	return 0;
 }
 
+static int snd_audigy_spdif_output_rate_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+{
+	static char *texts[] = {"44100", "48000", "96000"};
+
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+	uinfo->count = 1;
+	uinfo->value.enumerated.items = 3;
+	if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
+		uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
+	strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
+	return 0;
+}
+
+static int snd_audigy_spdif_output_rate_get(snd_kcontrol_t * kcontrol,
+                                 snd_ctl_elem_value_t * ucontrol)
+{
+	emu10k1_t *emu = snd_kcontrol_chip(kcontrol);
+	unsigned int tmp;
+	unsigned long flags;
+	
+
+	spin_lock_irqsave(&emu->reg_lock, flags);
+	tmp = snd_emu10k1_ptr_read(emu, A_SPDIF_SAMPLERATE, 0);
+	switch (tmp & A_SPDIF_RATE_MASK) {
+	case A_SPDIF_44100:
+		ucontrol->value.enumerated.item[0] = 0;
+		break;
+	case A_SPDIF_48000:
+		ucontrol->value.enumerated.item[0] = 1;
+		break;
+	case A_SPDIF_96000:
+		ucontrol->value.enumerated.item[0] = 2;
+		break;
+	default:
+		ucontrol->value.enumerated.item[0] = 1;
+	}
+	spin_unlock_irqrestore(&emu->reg_lock, flags);
+	return 0;
+}
+
+static int snd_audigy_spdif_output_rate_put(snd_kcontrol_t * kcontrol,
+                                 snd_ctl_elem_value_t * ucontrol)
+{
+	emu10k1_t *emu = snd_kcontrol_chip(kcontrol);
+	int change;
+	unsigned int reg, val, tmp;
+	unsigned long flags;
+
+	switch(ucontrol->value.enumerated.item[0]) {
+	case 0:
+		val = A_SPDIF_44100;
+		break;
+	case 1:
+		val = A_SPDIF_48000;
+		break;
+	case 2:
+		val = A_SPDIF_96000;
+		break;
+	default:
+		val = A_SPDIF_48000;
+		break;
+	}
+
+	
+	spin_lock_irqsave(&emu->reg_lock, flags);
+	reg = snd_emu10k1_ptr_read(emu, A_SPDIF_SAMPLERATE, 0);
+	tmp = reg & ~A_SPDIF_RATE_MASK;
+	tmp |= val;
+	if ((change = (tmp != reg)))
+		snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, 0, tmp);
+	spin_unlock_irqrestore(&emu->reg_lock, flags);
+	return change;
+}
+
+static snd_kcontrol_new_t snd_audigy_spdif_output_rate =
+{
+	.access =	SNDRV_CTL_ELEM_ACCESS_READWRITE,
+	.iface =        SNDRV_CTL_ELEM_IFACE_MIXER,
+	.name =         "Audigy SPDIF Output Sample Rate",
+	.count =	1,
+	.info =         snd_audigy_spdif_output_rate_info,
+	.get =          snd_audigy_spdif_output_rate_get,
+	.put =          snd_audigy_spdif_output_rate_put
+};
+
 static int snd_emu10k1_spdif_put(snd_kcontrol_t * kcontrol,
                                  snd_ctl_elem_value_t * ucontrol)
 {
@@ -139,6 +224,8 @@
 	}
 }
 
+/* PCM stream controls */
+
 static int snd_emu10k1_send_routing_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
 {
 	emu10k1_t *emu = snd_kcontrol_chip(kcontrol);
@@ -345,6 +432,190 @@
 	.put =          snd_emu10k1_attn_put
 };
 
+/* Mutichannel PCM stream controls */
+
+static int snd_emu10k1_efx_send_routing_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+{
+	emu10k1_t *emu = snd_kcontrol_chip(kcontrol);
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+	uinfo->count = emu->audigy ? 8 : 4;
+	uinfo->value.integer.min = 0;
+	uinfo->value.integer.max = emu->audigy ? 0x3f : 0x0f;
+	return 0;
+}
+
+static int snd_emu10k1_efx_send_routing_get(snd_kcontrol_t * kcontrol,
+                                        snd_ctl_elem_value_t * ucontrol)
+{
+	unsigned long flags;
+	emu10k1_t *emu = snd_kcontrol_chip(kcontrol);
+	emu10k1_pcm_mixer_t *mix = &emu->efx_pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
+	int idx;
+	int num_efx = emu->audigy ? 8 : 4;
+	int mask = emu->audigy ? 0x3f : 0x0f;
+
+	spin_lock_irqsave(&emu->reg_lock, flags);
+	for (idx = 0; idx < num_efx; idx++)
+		ucontrol->value.integer.value[idx] = 
+			mix->send_routing[0][idx] & mask;
+	spin_unlock_irqrestore(&emu->reg_lock, flags);
+	return 0;
+}
+
+static int snd_emu10k1_efx_send_routing_put(snd_kcontrol_t * kcontrol,
+                                        snd_ctl_elem_value_t * ucontrol)
+{
+	unsigned long flags;
+	emu10k1_t *emu = snd_kcontrol_chip(kcontrol);
+	int ch = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
+	emu10k1_pcm_mixer_t *mix = &emu->efx_pcm_mixer[ch];
+	int change = 0, idx, val;
+	int num_efx = emu->audigy ? 8 : 4;
+	int mask = emu->audigy ? 0x3f : 0x0f;
+
+	spin_lock_irqsave(&emu->reg_lock, flags);
+	for (idx = 0; idx < num_efx; idx++) {
+		val = ucontrol->value.integer.value[idx] & mask;
+		if (mix->send_routing[0][idx] != val) {
+			mix->send_routing[0][idx] = val;
+			change = 1;
+		}
+	}	
+	if (change && mix->epcm->voices[ch])
+		update_emu10k1_fxrt(emu, mix->epcm->voices[ch]->number,
+				    &mix->send_routing[0][0]);
+	spin_unlock_irqrestore(&emu->reg_lock, flags);
+	return change;
+}
+
+static snd_kcontrol_new_t snd_emu10k1_efx_send_routing_control =
+{
+	.access =	SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
+	.iface =        SNDRV_CTL_ELEM_IFACE_PCM,
+	.name =         "Multichannel PCM Send Routing",
+	.count =	16,
+	.info =         snd_emu10k1_efx_send_routing_info,
+	.get =          snd_emu10k1_efx_send_routing_get,
+	.put =          snd_emu10k1_efx_send_routing_put
+};
+
+static int snd_emu10k1_efx_send_volume_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+{
+	emu10k1_t *emu = snd_kcontrol_chip(kcontrol);
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+	uinfo->count = emu->audigy ? 8 : 4;
+	uinfo->value.integer.min = 0;
+	uinfo->value.integer.max = 255;
+	return 0;
+}
+
+static int snd_emu10k1_efx_send_volume_get(snd_kcontrol_t * kcontrol,
+                                       snd_ctl_elem_value_t * ucontrol)
+{
+	unsigned long flags;
+	emu10k1_t *emu = snd_kcontrol_chip(kcontrol);
+	emu10k1_pcm_mixer_t *mix = &emu->efx_pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
+	int idx;
+	int num_efx = emu->audigy ? 8 : 4;
+
+	spin_lock_irqsave(&emu->reg_lock, flags);
+	for (idx = 0; idx < num_efx; idx++)
+		ucontrol->value.integer.value[idx] = mix->send_volume[0][idx];
+	spin_unlock_irqrestore(&emu->reg_lock, flags);
+	return 0;
+}
+
+static int snd_emu10k1_efx_send_volume_put(snd_kcontrol_t * kcontrol,
+                                       snd_ctl_elem_value_t * ucontrol)
+{
+	unsigned long flags;
+	emu10k1_t *emu = snd_kcontrol_chip(kcontrol);
+	int ch = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
+	emu10k1_pcm_mixer_t *mix = &emu->efx_pcm_mixer[ch];
+	int change = 0, idx, val;
+	int num_efx = emu->audigy ? 8 : 4;
+
+	spin_lock_irqsave(&emu->reg_lock, flags);
+	for (idx = 0; idx < num_efx; idx++) {
+		val = ucontrol->value.integer.value[idx] & 255;
+		if (mix->send_volume[0][idx] != val) {
+			mix->send_volume[0][idx] = val;
+			change = 1;
+		}
+	}
+	if (change && mix->epcm->voices[ch])
+		update_emu10k1_send_volume(emu, mix->epcm->voices[ch]->number,
+					   &mix->send_volume[0][0]);
+	spin_unlock_irqrestore(&emu->reg_lock, flags);
+	return change;
+}
+
+
+static snd_kcontrol_new_t snd_emu10k1_efx_send_volume_control =
+{
+	.access =	SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
+	.iface =        SNDRV_CTL_ELEM_IFACE_PCM,
+	.name =         "Multichannel PCM Send Volume",
+	.count =	16,
+	.info =         snd_emu10k1_efx_send_volume_info,
+	.get =          snd_emu10k1_efx_send_volume_get,
+	.put =          snd_emu10k1_efx_send_volume_put
+};
+
+static int snd_emu10k1_efx_attn_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+{
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+	uinfo->count = 1;
+	uinfo->value.integer.min = 0;
+	uinfo->value.integer.max = 0xffff;
+	return 0;
+}
+
+static int snd_emu10k1_efx_attn_get(snd_kcontrol_t * kcontrol,
+                                snd_ctl_elem_value_t * ucontrol)
+{
+	emu10k1_t *emu = snd_kcontrol_chip(kcontrol);
+	emu10k1_pcm_mixer_t *mix = &emu->efx_pcm_mixer[snd_ctl_get_ioffidx(kcontrol, &ucontrol->id)];
+	unsigned long flags;
+
+	spin_lock_irqsave(&emu->reg_lock, flags);
+	ucontrol->value.integer.value[0] = mix->attn[0];
+	spin_unlock_irqrestore(&emu->reg_lock, flags);
+	return 0;
+}
+
+static int snd_emu10k1_efx_attn_put(snd_kcontrol_t * kcontrol,
+				snd_ctl_elem_value_t * ucontrol)
+{
+	unsigned long flags;
+	emu10k1_t *emu = snd_kcontrol_chip(kcontrol);
+	int ch = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
+	emu10k1_pcm_mixer_t *mix = &emu->efx_pcm_mixer[ch];
+	int change = 0, val;
+
+	spin_lock_irqsave(&emu->reg_lock, flags);
+	val = ucontrol->value.integer.value[0] & 0xffff;
+	if (mix->attn[0] != val) {
+		mix->attn[0] = val;
+		change = 1;
+	}
+	if (change && mix->epcm->voices[ch])
+		snd_emu10k1_ptr_write(emu, VTFT_VOLUMETARGET, mix->epcm->voices[ch]->number, mix->attn[0]);
+	spin_unlock_irqrestore(&emu->reg_lock, flags);
+	return change;
+}
+
+static snd_kcontrol_new_t snd_emu10k1_efx_attn_control =
+{
+	.access =	SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_INACTIVE,
+	.iface =        SNDRV_CTL_ELEM_IFACE_PCM,
+	.name =         "Multichannel PCM Volume",
+	.count =	16,
+	.info =         snd_emu10k1_efx_attn_info,
+	.get =          snd_emu10k1_efx_attn_get,
+	.put =          snd_emu10k1_efx_attn_put
+};
+
 static int snd_emu10k1_shared_spdif_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
 {
 	uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
@@ -578,7 +849,22 @@
 	if ((err = snd_ctl_add(card, kctl)))
 		return err;
 
-	/* intiailize the routing and volume table for each pcm playback stream */
+	if ((kctl = emu->ctl_efx_send_routing = snd_ctl_new1(&snd_emu10k1_efx_send_routing_control, emu)) == NULL)
+		return -ENOMEM;
+	if ((err = snd_ctl_add(card, kctl)))
+		return err;
+	
+	if ((kctl = emu->ctl_efx_send_volume = snd_ctl_new1(&snd_emu10k1_efx_send_volume_control, emu)) == NULL)
+		return -ENOMEM;
+	if ((err = snd_ctl_add(card, kctl)))
+		return err;
+	
+	if ((kctl = emu->ctl_efx_attn = snd_ctl_new1(&snd_emu10k1_efx_attn_control, emu)) == NULL)
+		return -ENOMEM;
+	if ((err = snd_ctl_add(card, kctl)))
+		return err;
+
+	/* initialize the routing and volume table for each pcm playback stream */
 	for (pcm = 0; pcm < 32; pcm++) {
 		emu10k1_pcm_mixer_t *mix;
 		int v;
@@ -598,6 +884,28 @@
 		mix->attn[0] = mix->attn[1] = mix->attn[2] = 0xffff;
 	}
 	
+	/* initialize the routing and volume table for the multichannel playback stream */
+	for (pcm = 0; pcm < NUM_EFX_PLAYBACK; pcm++) {
+		emu10k1_pcm_mixer_t *mix;
+		int v;
+		
+		mix = &emu->efx_pcm_mixer[pcm];
+		mix->epcm = NULL;
+
+		mix->send_routing[0][0] = pcm;
+		mix->send_routing[0][1] = (pcm == 0) ? 1 : 0;
+		for (v = 0; v < 2; v++)
+			mix->send_routing[0][2+v] = 13+v;
+		if (emu->audigy)
+			for (v = 0; v < 4; v++)
+				mix->send_routing[0][4+v] = 60+v;
+		
+		memset(&mix->send_volume, 0, sizeof(mix->send_volume));
+		mix->send_volume[0][0]  = 255;
+		
+		mix->attn[0] = 0xffff;
+	}
+	
 	if (! emu->APS) { /* FIXME: APS has these controls? */
 		/* sb live! and audigy */
 		if ((kctl = snd_ctl_new1(&snd_emu10k1_spdif_mask_control, emu)) == NULL)
@@ -617,6 +925,10 @@
 
 	if (emu->audigy) {
 		if ((kctl = snd_ctl_new1(&snd_audigy_shared_spdif, emu)) == NULL)
+			return -ENOMEM;
+		if ((err = snd_ctl_add(card, kctl)))
+			return err;
+		if ((kctl = snd_ctl_new1(&snd_audigy_spdif_output_rate, emu)) == NULL)
 			return -ENOMEM;
 		if ((err = snd_ctl_add(card, kctl)))
 			return err;
diff -Nru a/sound/pci/emu10k1/emumpu401.c b/sound/pci/emu10k1/emumpu401.c
--- a/sound/pci/emu10k1/emumpu401.c	2005-03-11 12:51:41 -08:00
+++ b/sound/pci/emu10k1/emumpu401.c	2005-03-11 12:51:41 -08:00
@@ -73,6 +73,7 @@
 
 static void do_emu10k1_midi_interrupt(emu10k1_t *emu, emu10k1_midi_t *midi, unsigned int status)
 {
+	unsigned long flags;
 	unsigned char byte;
 
 	if (midi->rmidi == NULL) {
@@ -86,15 +87,13 @@
 			mpu401_clear_rx(emu, midi);
 		} else {
 			byte = mpu401_read_data(emu, midi);
-			spin_unlock(&midi->input_lock);
 			if (midi->substream_input)
 				snd_rawmidi_receive(midi->substream_input, &byte, 1);
-			spin_lock(&midi->input_lock);
 		}
 	}
 	spin_unlock(&midi->input_lock);
 
-	spin_lock(&midi->output_lock);
+	spin_lock_irqsave(&midi->output_lock, flags);
 	if ((status & midi->ipr_tx) && mpu401_output_ready(emu, midi)) {
 		if (midi->substream_output &&
 		    snd_rawmidi_transmit(midi->substream_output, &byte, 1) == 1) {
@@ -103,7 +102,7 @@
 			snd_emu10k1_intr_disable(emu, midi->tx_enable);
 		}
 	}
-	spin_unlock(&midi->output_lock);
+	spin_unlock_irqrestore(&midi->output_lock, flags);
 }
 
 static void snd_emu10k1_midi_interrupt(emu10k1_t *emu, unsigned int status)
diff -Nru a/sound/pci/emu10k1/emupcm.c b/sound/pci/emu10k1/emupcm.c
--- a/sound/pci/emu10k1/emupcm.c	2005-03-11 12:51:40 -08:00
+++ b/sound/pci/emu10k1/emupcm.c	2005-03-11 12:51:40 -08:00
@@ -82,11 +82,28 @@
 	}
 #endif
 	snd_pcm_period_elapsed(emu->pcm_capture_efx_substream);
+}	 
+
+static snd_pcm_uframes_t snd_emu10k1_efx_playback_pointer(snd_pcm_substream_t * substream)
+{
+	emu10k1_t *emu = snd_pcm_substream_chip(substream);
+	snd_pcm_runtime_t *runtime = substream->runtime;
+	emu10k1_pcm_t *epcm = runtime->private_data;
+	unsigned int ptr;
+
+	if (!epcm->running)
+		return 0;
+	ptr = snd_emu10k1_ptr_read(emu, CCCA, epcm->voices[0]->number) & 0x00ffffff;
+	ptr += runtime->buffer_size;
+	ptr -= epcm->ccca_start_addr;
+	ptr %= runtime->buffer_size;
+
+	return ptr;
 }
 
 static int snd_emu10k1_pcm_channel_alloc(emu10k1_pcm_t * epcm, int voices)
 {
-	int err;
+	int err, i;
 
 	if (epcm->voices[1] != NULL && voices < 2) {
 		snd_emu10k1_voice_free(epcm->emu, epcm->voices[1]);
@@ -102,23 +119,31 @@
 			epcm->voices[0] = NULL;
 		}
 	}
-	err = snd_emu10k1_voice_alloc(epcm->emu, EMU10K1_PCM, voices > 1, &epcm->voices[0]);
+	err = snd_emu10k1_voice_alloc(epcm->emu,
+				      epcm->type == PLAYBACK_EMUVOICE ? EMU10K1_PCM : EMU10K1_EFX,
+				      voices,
+				      &epcm->voices[0]);
+	
 	if (err < 0)
 		return err;
 	epcm->voices[0]->epcm = epcm;
 	if (voices > 1) {
-		epcm->voices[1] = &epcm->emu->voices[epcm->voices[0]->number + 1];
-		epcm->voices[1]->epcm = epcm;
+		for (i = 1; i < voices; i++) {
+			epcm->voices[i] = &epcm->emu->voices[epcm->voices[0]->number + i];
+			epcm->voices[i]->epcm = epcm;
+		}
 	}
 	if (epcm->extra == NULL) {
-		err = snd_emu10k1_voice_alloc(epcm->emu, EMU10K1_PCM, 0, &epcm->extra);
+		err = snd_emu10k1_voice_alloc(epcm->emu,
+					      epcm->type == PLAYBACK_EMUVOICE ? EMU10K1_PCM : EMU10K1_EFX,
+					      1,
+					      &epcm->extra);
 		if (err < 0) {
 			// printk("pcm_channel_alloc: failed extra: voices=%d, frame=%d\n", voices, frame);
-			snd_emu10k1_voice_free(epcm->emu, epcm->voices[0]);
-			epcm->voices[0] = NULL;
-			if (epcm->voices[1])
-				snd_emu10k1_voice_free(epcm->emu, epcm->voices[1]);
-			epcm->voices[1] = NULL;
+			for (i = 0; i < voices; i++) {
+				snd_emu10k1_voice_free(epcm->emu, epcm->voices[i]);
+				epcm->voices[i] = NULL;
+			}
 			return err;
 		}
 		epcm->extra->epcm = epcm;
@@ -225,6 +250,22 @@
 		return CCCA_INTERPROM_2;
 }
 
+/*
+ * calculate cache invalidate size 
+ *
+ * stereo: channel is stereo
+ * w_16: using 16bit samples
+ *
+ * returns: cache invalidate size in samples
+ */
+static int inline emu10k1_ccis(int stereo, int w_16)
+{
+	if (w_16) {
+		return stereo ? 24 : 26;
+	} else {
+		return stereo ? 24*2 : 26*2;
+	}
+}
 
 static void snd_emu10k1_pcm_init_voice(emu10k1_t *emu,
 				       int master, int extra,
@@ -234,15 +275,21 @@
 {
 	snd_pcm_substream_t *substream = evoice->epcm->substream;
 	snd_pcm_runtime_t *runtime = substream->runtime;
-	emu10k1_pcm_mixer_t *mix = &emu->pcm_mixer[substream->number];
+	emu10k1_pcm_mixer_t *mix;
 	unsigned int silent_page, tmp;
 	int voice, stereo, w_16;
 	unsigned char attn, send_amount[8];
 	unsigned char send_routing[8];
 	unsigned long flags;
 	unsigned int pitch_target;
+	unsigned int ccis;
 
 	voice = evoice->number;
+	if (evoice->epcm->type == PLAYBACK_EFX) 
+		mix = &emu->efx_pcm_mixer[voice - evoice->epcm->voices[0]->number];
+	else
+		mix = &emu->pcm_mixer[substream->number];
+
 	stereo = runtime->channels == 2;
 	w_16 = snd_pcm_format_width(runtime->format) == 16;
 
@@ -273,10 +320,9 @@
 		memcpy(send_amount, &mix->send_volume[tmp][0], 8);
 	}
 
+	ccis = emu10k1_ccis(stereo, w_16);
+	
 	if (master) {
-		unsigned int ccis = stereo ? 28 : 30;
-		if (w_16)
-			ccis *= 2;
 		evoice->epcm->ccca_start_addr = start_addr + ccis;
 		if (extra) {
 			start_addr += ccis;
@@ -310,7 +356,12 @@
 	snd_emu10k1_ptr_write(emu, DSL, voice, end_addr | (send_amount[3] << 24));
 	snd_emu10k1_ptr_write(emu, PSST, voice, start_addr | (send_amount[2] << 24));
 	pitch_target = emu10k1_calc_pitch_target(runtime->rate);
-	snd_emu10k1_ptr_write(emu, CCCA, voice, evoice->epcm->ccca_start_addr |
+	if (extra)
+		snd_emu10k1_ptr_write(emu, CCCA, voice, start_addr |
+			      emu10k1_select_interprom(pitch_target) |
+			      (w_16 ? 0 : CCCA_8BITSELECT));
+	else
+		snd_emu10k1_ptr_write(emu, CCCA, voice, (start_addr + ccis) |
 			      emu10k1_select_interprom(pitch_target) |
 			      (w_16 ? 0 : CCCA_8BITSELECT));
 	// Clear filter delay memory
@@ -398,6 +449,35 @@
 	return 0;
 }
 
+static int snd_emu10k1_efx_playback_hw_free(snd_pcm_substream_t * substream)
+{
+	emu10k1_t *emu = snd_pcm_substream_chip(substream);
+	snd_pcm_runtime_t *runtime = substream->runtime;
+	emu10k1_pcm_t *epcm;
+	int i;
+
+	if (runtime->private_data == NULL)
+		return 0;
+	epcm = runtime->private_data;
+	if (epcm->extra) {
+		snd_emu10k1_voice_free(epcm->emu, epcm->extra);
+		epcm->extra = NULL;
+	}
+	for (i=0; i < NUM_EFX_PLAYBACK; i++) {
+		if (epcm->voices[i]) {
+			snd_emu10k1_voice_free(epcm->emu, epcm->voices[i]);
+			epcm->voices[i] = NULL;
+		}
+	}
+	if (epcm->memblk) {
+		snd_emu10k1_free_pages(emu, epcm->memblk);
+		epcm->memblk = NULL;
+		epcm->start_addr = 0;
+	}
+	snd_pcm_lib_free_pages(substream);
+	return 0;
+}
+
 static int snd_emu10k1_playback_prepare(snd_pcm_substream_t * substream)
 {
 	emu10k1_t *emu = snd_pcm_substream_chip(substream);
@@ -407,11 +487,14 @@
 
 	start_addr = epcm->start_addr;
 	end_addr = snd_pcm_lib_period_bytes(substream);
-	if (runtime->channels == 2)
+	if (runtime->channels == 2) {
+		start_addr >>= 1;
 		end_addr >>= 1;
+	}
 	end_addr += start_addr;
 	snd_emu10k1_pcm_init_voice(emu, 1, 1, epcm->extra,
 				   start_addr, end_addr);
+	start_addr = epcm->start_addr;
 	end_addr = epcm->start_addr + snd_pcm_lib_buffer_bytes(substream);
 	snd_emu10k1_pcm_init_voice(emu, 1, 0, epcm->voices[0],
 				   start_addr, end_addr);
@@ -421,6 +504,59 @@
 	return 0;
 }
 
+static int snd_emu10k1_efx_playback_prepare(snd_pcm_substream_t * substream)
+{
+	emu10k1_t *emu = snd_pcm_substream_chip(substream);
+	snd_pcm_runtime_t *runtime = substream->runtime;
+	emu10k1_pcm_t *epcm = runtime->private_data;
+	unsigned int start_addr, end_addr;
+	unsigned int channel_size;
+	int i;
+
+	start_addr = epcm->start_addr;
+	end_addr = epcm->start_addr + snd_pcm_lib_buffer_bytes(substream);
+
+	/*
+	 * the kX driver leaves some space between voices
+	 */
+	channel_size = ( end_addr - start_addr ) / NUM_EFX_PLAYBACK;
+
+	snd_emu10k1_pcm_init_voice(emu, 1, 1, epcm->extra,
+				   start_addr, start_addr + (channel_size / 2));
+
+	/* only difference with the master voice is we use it for the pointer */
+	snd_emu10k1_pcm_init_voice(emu, 1, 0, epcm->voices[0],
+				   start_addr, start_addr + channel_size);
+
+	start_addr += channel_size;
+	for (i = 1; i < NUM_EFX_PLAYBACK; i++) {
+		snd_emu10k1_pcm_init_voice(emu, 0, 0, epcm->voices[i],
+					   start_addr, start_addr+channel_size);
+		start_addr += channel_size;
+	}
+
+	return 0;
+}
+
+static snd_pcm_hardware_t snd_emu10k1_efx_playback =
+{
+	.info =			(SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_NONINTERLEAVED |
+				 SNDRV_PCM_INFO_BLOCK_TRANSFER |
+				 SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_PAUSE),
+	.formats =		SNDRV_PCM_FMTBIT_S16_LE,
+	.rates =		SNDRV_PCM_RATE_48000,
+	.rate_min =		48000,
+	.rate_max =		48000,
+	.channels_min =		NUM_EFX_PLAYBACK,
+	.channels_max =		NUM_EFX_PLAYBACK,
+	.buffer_bytes_max =	(64*1024),
+	.period_bytes_min =	64,
+	.period_bytes_max =	(64*1024),
+	.periods_min =		2,
+	.periods_max =		2,
+	.fifo_size =		0,
+};
+
 static int snd_emu10k1_capture_hw_params(snd_pcm_substream_t * substream,
 					 snd_pcm_hw_params_t * hw_params)
 {
@@ -439,6 +575,7 @@
 	emu10k1_pcm_t *epcm = runtime->private_data;
 	int idx;
 
+	/* zeroing the buffer size will stop capture */
 	snd_emu10k1_ptr_write(emu, epcm->capture_bs_reg, 0, 0);
 	switch (epcm->type) {
 	case CAPTURE_AC97ADC:
@@ -478,67 +615,88 @@
 	return 0;
 }
 
-static void snd_emu10k1_playback_invalidate_cache(emu10k1_t *emu, emu10k1_voice_t *evoice)
+static void snd_emu10k1_playback_invalidate_cache(emu10k1_t *emu, int extra, emu10k1_voice_t *evoice)
 {
 	snd_pcm_runtime_t *runtime;
-	unsigned int voice, i, ccis, cra = 64, cs, sample;
+	unsigned int voice, stereo, i, ccis, cra = 64, cs, sample;
 
 	if (evoice == NULL)
 		return;
 	runtime = evoice->epcm->substream->runtime;
 	voice = evoice->number;
+	stereo = (!extra && runtime->channels == 2);
 	sample = snd_pcm_format_width(runtime->format) == 16 ? 0 : 0x80808080;
-	if (runtime->channels > 1) {
-		ccis = 28;
-		cs = 4;
-	} else {
-		ccis = 30;
-		cs = 2;
-	}
-	if (sample == 0)	/* 16-bit */
-		ccis *= 2;
-	for (i = 0; i < cs; i++)
+	ccis = emu10k1_ccis(stereo, sample == 0);
+	// set cs to 2 * number of cache registers beside the invalidated
+	cs = (sample == 0) ? (32-ccis) : (64-ccis+1) >> 1;
+	if (cs > 16) cs = 16;
+	for (i = 0; i < cs; i++) {
 		snd_emu10k1_ptr_write(emu, CD0 + i, voice, sample);
+		if (stereo) {
+			snd_emu10k1_ptr_write(emu, CD0 + i, voice + 1, sample);
+		}
+	}
 	// reset cache
 	snd_emu10k1_ptr_write(emu, CCR_CACHEINVALIDSIZE, voice, 0);
 	snd_emu10k1_ptr_write(emu, CCR_READADDRESS, voice, cra);
-	if (runtime->channels > 1) {
+	if (stereo) {
 		snd_emu10k1_ptr_write(emu, CCR_CACHEINVALIDSIZE, voice + 1, 0);
 		snd_emu10k1_ptr_write(emu, CCR_READADDRESS, voice + 1, cra);
 	}
 	// fill cache
 	snd_emu10k1_ptr_write(emu, CCR_CACHEINVALIDSIZE, voice, ccis);
+	if (stereo) {
+		snd_emu10k1_ptr_write(emu, CCR_CACHEINVALIDSIZE, voice+1, ccis);
+	}
 }
 
-static void snd_emu10k1_playback_trigger_voice(emu10k1_t *emu, emu10k1_voice_t *evoice, int master, int extra)
+static void snd_emu10k1_playback_prepare_voice(emu10k1_t *emu, emu10k1_voice_t *evoice, int master, int extra)
 {
 	snd_pcm_substream_t *substream;
 	snd_pcm_runtime_t *runtime;
 	emu10k1_pcm_mixer_t *mix;
-	unsigned int voice, pitch, pitch_target, tmp;
 	unsigned int attn;
+	unsigned int voice, tmp;
 
 	if (evoice == NULL)	/* skip second voice for mono */
 		return;
 	substream = evoice->epcm->substream;
 	runtime = substream->runtime;
-	mix = &emu->pcm_mixer[substream->number];
 	voice = evoice->number;
-	pitch = snd_emu10k1_rate_to_pitch(runtime->rate) >> 8;
-	pitch_target = emu10k1_calc_pitch_target(runtime->rate);
+
+	mix = evoice->epcm->type == PLAYBACK_EFX
+		? &emu->efx_pcm_mixer[voice - evoice->epcm->voices[0]->number]
+		: &emu->pcm_mixer[substream->number];
+
 	attn = extra ? 0 : 0x00ff;
 	tmp = runtime->channels == 2 ? (master ? 1 : 2) : 0;
 	snd_emu10k1_ptr_write(emu, IFATN, voice, attn);
 	snd_emu10k1_ptr_write(emu, VTFT, voice, (mix->attn[tmp] << 16) | 0xffff);
 	snd_emu10k1_ptr_write(emu, CVCF, voice, (mix->attn[tmp] << 16) | 0xffff);
-	snd_emu10k1_voice_clear_loop_stop(emu, voice);		
-	if (extra)
-		snd_emu10k1_voice_intr_enable(emu, voice);
 	snd_emu10k1_ptr_write(emu, DCYSUSV, voice, 0x7f7f);
+	snd_emu10k1_voice_clear_loop_stop(emu, voice);
+}	
+
+static void snd_emu10k1_playback_trigger_voice(emu10k1_t *emu, emu10k1_voice_t *evoice, int master, int extra)
+{
+	snd_pcm_substream_t *substream;
+	snd_pcm_runtime_t *runtime;
+	unsigned int voice, pitch, pitch_target;
+
+	if (evoice == NULL)	/* skip second voice for mono */
+		return;
+	substream = evoice->epcm->substream;
+	runtime = substream->runtime;
+	voice = evoice->number;
+
+	pitch = snd_emu10k1_rate_to_pitch(runtime->rate) >> 8;
+	pitch_target = emu10k1_calc_pitch_target(runtime->rate);
 	snd_emu10k1_ptr_write(emu, PTRX_PITCHTARGET, voice, pitch_target);
-	if (master)
+	if (master || evoice->epcm->type == PLAYBACK_EFX)
 		snd_emu10k1_ptr_write(emu, CPF_CURRENTPITCH, voice, pitch_target);
 	snd_emu10k1_ptr_write(emu, IP, voice, pitch);
+	if (extra)
+		snd_emu10k1_voice_intr_enable(emu, voice);
 }
 
 static void snd_emu10k1_playback_stop_voice(emu10k1_t *emu, emu10k1_voice_t *evoice)
@@ -564,15 +722,17 @@
 	snd_pcm_runtime_t *runtime = substream->runtime;
 	emu10k1_pcm_t *epcm = runtime->private_data;
 	int result = 0;
-
 	// printk("trigger - emu10k1 = 0x%x, cmd = %i, pointer = %i\n", (int)emu, cmd, substream->ops->pointer(substream));
 	spin_lock(&emu->reg_lock);
 	switch (cmd) {
 	case SNDRV_PCM_TRIGGER_START:
-		snd_emu10k1_playback_invalidate_cache(emu, epcm->extra);	/* do we need this? */
-		snd_emu10k1_playback_invalidate_cache(emu, epcm->voices[0]);
+		snd_emu10k1_playback_invalidate_cache(emu, 1, epcm->extra);	/* do we need this? */
+		snd_emu10k1_playback_invalidate_cache(emu, 0, epcm->voices[0]);
 		/* follow thru */
 	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+		snd_emu10k1_playback_prepare_voice(emu, epcm->voices[0], 1, 0);
+		snd_emu10k1_playback_prepare_voice(emu, epcm->voices[1], 0, 0);
+		snd_emu10k1_playback_prepare_voice(emu, epcm->extra, 1, 1);
 		snd_emu10k1_playback_trigger_voice(emu, epcm->voices[0], 1, 0);
 		snd_emu10k1_playback_trigger_voice(emu, epcm->voices[1], 0, 0);
 		snd_emu10k1_playback_trigger_voice(emu, epcm->extra, 1, 1);
@@ -601,10 +761,10 @@
 	emu10k1_pcm_t *epcm = runtime->private_data;
 	int result = 0;
 
-	// printk("trigger - emu10k1 = %p, cmd = %i, pointer = %i\n", emu, cmd, substream->ops->pointer(substream));
 	spin_lock(&emu->reg_lock);
 	switch (cmd) {
 	case SNDRV_PCM_TRIGGER_START:
+		// hmm this should cause full and half full interrupt to be raised?  
 		outl(epcm->capture_ipr, emu->port + IPR);
 		snd_emu10k1_intr_enable(emu, epcm->capture_inte);
 		// printk("adccr = 0x%x, adcbs = 0x%x\n", epcm->adccr, epcm->adcbs);
@@ -680,6 +840,56 @@
 	return ptr;
 }
 
+
+static int snd_emu10k1_efx_playback_trigger(snd_pcm_substream_t * substream,
+				        int cmd)
+{
+	emu10k1_t *emu = snd_pcm_substream_chip(substream);
+	snd_pcm_runtime_t *runtime = substream->runtime;
+	emu10k1_pcm_t *epcm = runtime->private_data;
+	int i = 0;
+	int result = 0;
+
+	spin_lock(&emu->reg_lock);
+	switch (cmd) {
+	case SNDRV_PCM_TRIGGER_START:
+		// prepare voices
+		for (i = 0; i < NUM_EFX_PLAYBACK; i++) {	
+			snd_emu10k1_playback_invalidate_cache(emu, 0, epcm->voices[i]);
+		}
+		snd_emu10k1_playback_invalidate_cache(emu, 1, epcm->extra);
+
+		/* follow thru */
+	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+		snd_emu10k1_playback_prepare_voice(emu, epcm->voices[0], 0, 0);
+		snd_emu10k1_playback_prepare_voice(emu, epcm->extra, 1, 1);
+		for (i = 1; i < NUM_EFX_PLAYBACK; i++) {	
+			snd_emu10k1_playback_prepare_voice(emu, epcm->voices[i], 0, 0);
+		}
+		snd_emu10k1_playback_trigger_voice(emu, epcm->voices[0], 0, 0);
+		snd_emu10k1_playback_trigger_voice(emu, epcm->extra, 1, 1);
+		for (i = 1; i < NUM_EFX_PLAYBACK; i++) {	
+			snd_emu10k1_playback_trigger_voice(emu, epcm->voices[i], 0, 0);
+		}
+		epcm->running = 1;
+		break;
+	case SNDRV_PCM_TRIGGER_STOP:
+	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+		epcm->running = 0;
+		for (i = 0; i < NUM_EFX_PLAYBACK; i++) {	
+			snd_emu10k1_playback_stop_voice(emu, epcm->voices[i]);
+		}
+		snd_emu10k1_playback_stop_voice(emu, epcm->extra);
+		break;
+	default:
+		result = -EINVAL;
+		break;
+	}
+	spin_unlock(&emu->reg_lock);
+	return result;
+}
+
+
 static snd_pcm_uframes_t snd_emu10k1_capture_pointer(snd_pcm_substream_t * substream)
 {
 	emu10k1_t *emu = snd_pcm_substream_chip(substream);
@@ -707,9 +917,9 @@
 				 SNDRV_PCM_INFO_BLOCK_TRANSFER |
 				 SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_PAUSE),
 	.formats =		SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE,
-	.rates =		SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000,
+	.rates =		SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_96000,
 	.rate_min =		4000,
-	.rate_max =		48000,
+	.rate_max =		96000,
 	.channels_min =		1,
 	.channels_max =		2,
 	.buffer_bytes_max =	(128*1024),
@@ -768,6 +978,13 @@
 	snd_emu10k1_pcm_mixer_notify1(emu, emu->ctl_attn, idx, activate);
 }
 
+static void snd_emu10k1_pcm_efx_mixer_notify(emu10k1_t *emu, int idx, int activate)
+{
+	snd_emu10k1_pcm_mixer_notify1(emu, emu->ctl_efx_send_routing, idx, activate);
+	snd_emu10k1_pcm_mixer_notify1(emu, emu->ctl_efx_send_volume, idx, activate);
+	snd_emu10k1_pcm_mixer_notify1(emu, emu->ctl_efx_attn, idx, activate);
+}
+
 static void snd_emu10k1_pcm_free_substream(snd_pcm_runtime_t *runtime)
 {
 	emu10k1_pcm_t *epcm = runtime->private_data;
@@ -775,6 +992,53 @@
 	kfree(epcm);
 }
 
+static int snd_emu10k1_efx_playback_close(snd_pcm_substream_t * substream)
+{
+	emu10k1_t *emu = snd_pcm_substream_chip(substream);
+	emu10k1_pcm_mixer_t *mix;
+	int i;
+
+	for (i=0; i < NUM_EFX_PLAYBACK; i++) {
+		mix = &emu->efx_pcm_mixer[i];
+		mix->epcm = NULL;
+		snd_emu10k1_pcm_efx_mixer_notify(emu, i, 0);
+	}
+	return 0;
+}
+
+static int snd_emu10k1_efx_playback_open(snd_pcm_substream_t * substream)
+{
+	emu10k1_t *emu = snd_pcm_substream_chip(substream);
+	emu10k1_pcm_t *epcm;
+	emu10k1_pcm_mixer_t *mix;
+	snd_pcm_runtime_t *runtime = substream->runtime;
+	int i;
+
+	epcm = kcalloc(1, sizeof(*epcm), GFP_KERNEL);
+	if (epcm == NULL)
+		return -ENOMEM;
+	epcm->emu = emu;
+	epcm->type = PLAYBACK_EFX;
+	epcm->substream = substream;
+	
+	emu->pcm_playback_efx_substream = substream;
+
+	runtime->private_data = epcm;
+	runtime->private_free = snd_emu10k1_pcm_free_substream;
+	runtime->hw = snd_emu10k1_efx_playback;
+	
+	for (i=0; i < NUM_EFX_PLAYBACK; i++) {
+		mix = &emu->efx_pcm_mixer[i];
+		mix->send_routing[0][0] = i;
+		memset(&mix->send_volume, 0, sizeof(mix->send_volume));
+		mix->send_volume[0][0] = 255;
+		mix->attn[0] = 0xffff;
+		mix->epcm = epcm;
+		snd_emu10k1_pcm_efx_mixer_notify(emu, i, 1);
+	}
+	return 0;
+}
+
 static int snd_emu10k1_playback_open(snd_pcm_substream_t * substream)
 {
 	emu10k1_t *emu = snd_pcm_substream_chip(substream);
@@ -969,6 +1233,19 @@
 	.pointer =		snd_emu10k1_capture_pointer,
 };
 
+/* EFX playback */
+static snd_pcm_ops_t snd_emu10k1_efx_playback_ops = {
+	.open =			snd_emu10k1_efx_playback_open,
+	.close =		snd_emu10k1_efx_playback_close,
+	.ioctl =		snd_pcm_lib_ioctl,
+	.hw_params =		snd_emu10k1_playback_hw_params,
+	.hw_free =		snd_emu10k1_efx_playback_hw_free,
+	.prepare =		snd_emu10k1_efx_playback_prepare,
+	.trigger =		snd_emu10k1_efx_playback_trigger,
+	.pointer =		snd_emu10k1_efx_playback_pointer,
+	.page =			snd_pcm_sgbuf_ops_page,
+};
+
 static void snd_emu10k1_pcm_free(snd_pcm_t *pcm)
 {
 	emu10k1_t *emu = pcm->private_data;
@@ -1012,6 +1289,39 @@
 	return 0;
 }
 
+int __devinit snd_emu10k1_pcm_multi(emu10k1_t * emu, int device, snd_pcm_t ** rpcm)
+{
+	snd_pcm_t *pcm;
+	snd_pcm_substream_t *substream;
+	int err;
+
+	if (rpcm)
+		*rpcm = NULL;
+
+	if ((err = snd_pcm_new(emu->card, "emu10k1", device, 1, 0, &pcm)) < 0)
+		return err;
+
+	pcm->private_data = emu;
+	pcm->private_free = snd_emu10k1_pcm_free;
+
+	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_emu10k1_efx_playback_ops);
+
+	pcm->info_flags = 0;
+	pcm->dev_subclass = SNDRV_PCM_SUBCLASS_GENERIC_MIX;
+	strcpy(pcm->name, "EMU10K1 multichannel EFX");
+	emu->pcm = pcm;
+
+	for (substream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream; substream; substream = substream->next)
+		if ((err = snd_pcm_lib_preallocate_pages(substream, SNDRV_DMA_TYPE_DEV_SG, snd_dma_pci_data(emu->pci), 64*1024, 64*1024)) < 0)
+			return err;
+
+	if (rpcm)
+		*rpcm = pcm;
+
+	return 0;
+}
+
+
 static snd_pcm_ops_t snd_emu10k1_capture_mic_ops = {
 	.open =			snd_emu10k1_capture_mic_open,
 	.close =		snd_emu10k1_capture_mic_close,
@@ -1114,7 +1424,7 @@
 
 static snd_kcontrol_new_t snd_emu10k1_pcm_efx_voices_mask = {
 	.iface = SNDRV_CTL_ELEM_IFACE_PCM,
-	.name = "EFX voices mask",
+	.name = "Captured FX8010 Outputs",
 	.info = snd_emu10k1_pcm_efx_voices_mask_info,
 	.get = snd_emu10k1_pcm_efx_voices_mask_get,
 	.put = snd_emu10k1_pcm_efx_voices_mask_put
@@ -1390,8 +1700,18 @@
 	if (rpcm)
 		*rpcm = pcm;
 
-	emu->efx_voices_mask[0] = FXWC_DEFAULTROUTE_C | FXWC_DEFAULTROUTE_A;
-	emu->efx_voices_mask[1] = 0;
+	/* EFX capture - record the "FXBUS2" channels, by default we connect the EXTINs 
+	 * to these
+	 */	
+	
+	/* emu->efx_voices_mask[0] = FXWC_DEFAULTROUTE_C | FXWC_DEFAULTROUTE_A; */
+	if (emu->audigy) {
+		emu->efx_voices_mask[0] = 0;
+		emu->efx_voices_mask[1] = 0xffff;
+	} else {
+		emu->efx_voices_mask[0] = 0xffff0000;
+		emu->efx_voices_mask[1] = 0;
+	}
 	snd_ctl_add(emu->card, snd_ctl_new1(&snd_emu10k1_pcm_efx_voices_mask, emu));
 
 	snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(emu->pci), 64*1024, 64*1024);
diff -Nru a/sound/pci/emu10k1/emuproc.c b/sound/pci/emu10k1/emuproc.c
--- a/sound/pci/emu10k1/emuproc.c	2005-03-11 12:51:42 -08:00
+++ b/sound/pci/emu10k1/emuproc.c	2005-03-11 12:51:42 -08:00
@@ -140,38 +140,38 @@
 		/* 29 */ "???",
 		/* 30 */ "???",
 		/* 31 */ "???",
-		/* 32 */ "???",
-		/* 33 */ "???",
-		/* 34 */ "???",
-		/* 35 */ "???",
-		/* 36 */ "???",
-		/* 37 */ "???",
-		/* 38 */ "???",
-		/* 39 */ "???",
-		/* 40 */ "???",
-		/* 41 */ "???",
-		/* 42 */ "???",
-		/* 43 */ "???",
-		/* 44 */ "???",
-		/* 45 */ "???",
-		/* 46 */ "???",
-		/* 47 */ "???",
-		/* 48 */ "???",
-		/* 49 */ "???",
-		/* 50 */ "???",
-		/* 51 */ "???",
-		/* 52 */ "???",
-		/* 53 */ "???",
-		/* 54 */ "???",
-		/* 55 */ "???",
-		/* 56 */ "???",
-		/* 57 */ "???",
-		/* 58 */ "???",
-		/* 59 */ "???",
-		/* 60 */ "???",
-		/* 61 */ "???",
-		/* 62 */ "???",
-		/* 33 */ "???"
+		/* 32 */ "FXBUS2_0",
+		/* 33 */ "FXBUS2_1",
+		/* 34 */ "FXBUS2_2",
+		/* 35 */ "FXBUS2_3",
+		/* 36 */ "FXBUS2_4",
+		/* 37 */ "FXBUS2_5",
+		/* 38 */ "FXBUS2_6",
+		/* 39 */ "FXBUS2_7",
+		/* 40 */ "FXBUS2_8",
+		/* 41 */ "FXBUS2_9",
+		/* 42 */ "FXBUS2_10",
+		/* 43 */ "FXBUS2_11",
+		/* 44 */ "FXBUS2_12",
+		/* 45 */ "FXBUS2_13",
+		/* 46 */ "FXBUS2_14",
+		/* 47 */ "FXBUS2_15",
+		/* 48 */ "FXBUS2_16",
+		/* 49 */ "FXBUS2_17",
+		/* 50 */ "FXBUS2_18",
+		/* 51 */ "FXBUS2_19",
+		/* 52 */ "FXBUS2_20",
+		/* 53 */ "FXBUS2_21",
+		/* 54 */ "FXBUS2_22",
+		/* 55 */ "FXBUS2_23",
+		/* 56 */ "FXBUS2_24",
+		/* 57 */ "FXBUS2_25",
+		/* 58 */ "FXBUS2_26",
+		/* 59 */ "FXBUS2_27",
+		/* 60 */ "FXBUS2_28",
+		/* 61 */ "FXBUS2_29",
+		/* 62 */ "FXBUS2_30",
+		/* 63 */ "FXBUS2_31"
 	};
 
 	emu10k1_t *emu = entry->private_data;
@@ -221,7 +221,7 @@
 			snd_iprintf(buffer, "  Output %02i [%s]\n", idx, outputs[idx]);
 	}
 	snd_iprintf(buffer, "\nAll FX Outputs        :\n");
-	for (idx = 0; idx < 32; idx++)
+	for (idx = 0; idx < (emu->audigy ? 64 : 32); idx++)
 		snd_iprintf(buffer, "  Output %02i [%s]\n", idx, outputs[idx]);
 	snd_emu10k1_proc_spdif_status(emu, buffer, "S/PDIF Output 0", SPCS0, -1);
 	snd_emu10k1_proc_spdif_status(emu, buffer, "S/PDIF Output 1", SPCS1, -1);
@@ -322,6 +322,26 @@
 	return 0;
 }
 
+static void snd_emu10k1_proc_voices_read(snd_info_entry_t *entry, 
+				  snd_info_buffer_t * buffer)
+{
+	emu10k1_t *emu = entry->private_data;
+	emu10k1_voice_t *voice;
+	int idx;
+	
+	snd_iprintf(buffer, "ch\tuse\tpcm\tefx\tsynth\tmidi\n");
+	for (idx = 0; idx < NUM_G; idx++) {
+		voice = &emu->voices[idx];
+		snd_iprintf(buffer, "%i\t%i\t%i\t%i\t%i\t%i\n",
+			idx,
+			voice->use,
+			voice->pcm,
+			voice->efx,
+			voice->synth,
+			voice->midi);
+	}
+}
+
 #ifdef CONFIG_SND_DEBUG
 static void snd_emu_proc_io_reg_read(snd_info_entry_t *entry,
 				     snd_info_buffer_t * buffer)
@@ -405,7 +425,7 @@
 	snd_iprintf(buffer, "Registers 0x%x\n", iobase);
 	for(i = offset; i < offset+length; i++) {
 		snd_iprintf(buffer, "%02X: ",i);
-		for (j = 0; j < 4; j++) {
+		for (j = 0; j < 64; j++) {
 			if(iobase == 0)
                 		value = snd_ptr_read(emu, 0, i, j);
 			else
@@ -482,22 +502,22 @@
 		entry->c.text.write = snd_emu_proc_io_reg_write;
 	}
 	if (! snd_card_proc_new(emu->card, "ptr_regs00a", &entry)) {
-		snd_info_set_text_ops(entry, emu, 1024, snd_emu_proc_ptr_reg_read00a);
+		snd_info_set_text_ops(entry, emu, 65536, snd_emu_proc_ptr_reg_read00a);
 		entry->c.text.write_size = 64;
 		entry->c.text.write = snd_emu_proc_ptr_reg_write00;
 	}
 	if (! snd_card_proc_new(emu->card, "ptr_regs00b", &entry)) {
-		snd_info_set_text_ops(entry, emu, 1024, snd_emu_proc_ptr_reg_read00b);
+		snd_info_set_text_ops(entry, emu, 65536, snd_emu_proc_ptr_reg_read00b);
 		entry->c.text.write_size = 64;
 		entry->c.text.write = snd_emu_proc_ptr_reg_write00;
 	}
 	if (! snd_card_proc_new(emu->card, "ptr_regs20a", &entry)) {
-		snd_info_set_text_ops(entry, emu, 1024, snd_emu_proc_ptr_reg_read20a);
+		snd_info_set_text_ops(entry, emu, 65536, snd_emu_proc_ptr_reg_read20a);
 		entry->c.text.write_size = 64;
 		entry->c.text.write = snd_emu_proc_ptr_reg_write20;
 	}
 	if (! snd_card_proc_new(emu->card, "ptr_regs20b", &entry)) {
-		snd_info_set_text_ops(entry, emu, 1024, snd_emu_proc_ptr_reg_read20b);
+		snd_info_set_text_ops(entry, emu, 65536, snd_emu_proc_ptr_reg_read20b);
 		entry->c.text.write_size = 64;
 		entry->c.text.write = snd_emu_proc_ptr_reg_write20;
 	}
@@ -505,6 +525,9 @@
 	
 	if (! snd_card_proc_new(emu->card, "emu10k1", &entry))
 		snd_info_set_text_ops(entry, emu, 2048, snd_emu10k1_proc_read);
+
+	if (! snd_card_proc_new(emu->card, "voices", &entry))
+		snd_info_set_text_ops(entry, emu, 2048, snd_emu10k1_proc_voices_read);
 
 	if (! snd_card_proc_new(emu->card, "fx8010_gpr", &entry)) {
 		entry->content = SNDRV_INFO_CONTENT_DATA;
diff -Nru a/sound/pci/emu10k1/io.c b/sound/pci/emu10k1/io.c
--- a/sound/pci/emu10k1/io.c	2005-03-11 12:51:42 -08:00
+++ b/sound/pci/emu10k1/io.c	2005-03-11 12:51:42 -08:00
@@ -170,6 +170,63 @@
 	spin_unlock_irqrestore(&emu->emu_lock, flags);
 }
 
+void snd_emu10k1_voice_half_loop_intr_enable(emu10k1_t *emu, unsigned int voicenum)
+{
+	unsigned long flags;
+	unsigned int val;
+
+	spin_lock_irqsave(&emu->emu_lock, flags);
+	/* voice interrupt */
+	if (voicenum >= 32) {
+		outl(HLIEH << 16, emu->port + PTR);
+		val = inl(emu->port + DATA);
+		val |= 1 << (voicenum - 32);
+	} else {
+		outl(HLIEL << 16, emu->port + PTR);
+		val = inl(emu->port + DATA);
+		val |= 1 << voicenum;
+	}
+	outl(val, emu->port + DATA);
+	spin_unlock_irqrestore(&emu->emu_lock, flags);
+}
+
+void snd_emu10k1_voice_half_loop_intr_disable(emu10k1_t *emu, unsigned int voicenum)
+{
+	unsigned long flags;
+	unsigned int val;
+
+	spin_lock_irqsave(&emu->emu_lock, flags);
+	/* voice interrupt */
+	if (voicenum >= 32) {
+		outl(HLIEH << 16, emu->port + PTR);
+		val = inl(emu->port + DATA);
+		val &= ~(1 << (voicenum - 32));
+	} else {
+		outl(HLIEL << 16, emu->port + PTR);
+		val = inl(emu->port + DATA);
+		val &= ~(1 << voicenum);
+	}
+	outl(val, emu->port + DATA);
+	spin_unlock_irqrestore(&emu->emu_lock, flags);
+}
+
+void snd_emu10k1_voice_half_loop_intr_ack(emu10k1_t *emu, unsigned int voicenum)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&emu->emu_lock, flags);
+	/* voice interrupt */
+	if (voicenum >= 32) {
+		outl(HLIPH << 16, emu->port + PTR);
+		voicenum = 1 << (voicenum - 32);
+	} else {
+		outl(HLIPL << 16, emu->port + PTR);
+		voicenum = 1 << voicenum;
+	}
+	outl(voicenum, emu->port + DATA);
+	spin_unlock_irqrestore(&emu->emu_lock, flags);
+}
+
 void snd_emu10k1_voice_set_loop_stop(emu10k1_t *emu, unsigned int voicenum)
 {
 	unsigned long flags;
diff -Nru a/sound/pci/emu10k1/irq.c b/sound/pci/emu10k1/irq.c
--- a/sound/pci/emu10k1/irq.c	2005-03-11 12:51:47 -08:00
+++ b/sound/pci/emu10k1/irq.c	2005-03-11 12:51:47 -08:00
@@ -73,6 +73,21 @@
 				val >>= 1;
 				pvoice++;
 			}
+			val = snd_emu10k1_ptr_read(emu, HLIPL, 0);
+			for (voice = 0; voice <= voice_max; voice++) {
+				if (voice == 0x20)
+					val = snd_emu10k1_ptr_read(emu, HLIPH, 0);
+				if (val & 1) {
+					if (pvoice->use && pvoice->interrupt != NULL) {
+						pvoice->interrupt(emu, pvoice);
+						snd_emu10k1_voice_half_loop_intr_ack(emu, voice);
+					} else {
+						snd_emu10k1_voice_half_loop_intr_disable(emu, voice);
+					}
+				}
+				val >>= 1;
+				pvoice++;
+			}
 			status &= ~IPR_CHANNELLOOP;
 		}
 		status &= ~IPR_CHANNELNUMBERMASK;
diff -Nru a/sound/pci/emu10k1/voice.c b/sound/pci/emu10k1/voice.c
--- a/sound/pci/emu10k1/voice.c	2005-03-11 12:51:46 -08:00
+++ b/sound/pci/emu10k1/voice.c	2005-03-11 12:51:46 -08:00
@@ -1,8 +1,11 @@
 /*
  *  Copyright (c) by Jaroslav Kysela <perex@suse.cz>
  *                   Creative Labs, Inc.
+ *                   Lee Revell <rlrevell@joe-job.com>
  *  Routines for control of EMU10K1 chips - voice manager
  *
+ *  Rewrote voice allocator for multichannel support - rlrevell 12/2004
+ * 
  *  BUGS:
  *    --
  *
@@ -30,25 +33,68 @@
 #include <sound/core.h>
 #include <sound/emu10k1.h>
 
-static int voice_alloc(emu10k1_t *emu, emu10k1_voice_type_t type, int pair, emu10k1_voice_t **rvoice)
+/* Previously the voice allocator started at 0 every time.  The new voice 
+ * allocator uses a round robin scheme.  The next free voice is tracked in 
+ * the card record and each allocation begins where the last left off.  The 
+ * hardware requires stereo interleaved voices be aligned to an even/odd 
+ * boundary.  For multichannel voice allocation we ensure than the block of 
+ * voices does not cross the 32 voice boundary.  This simplifies the 
+ * multichannel support and ensures we can use a single write to the 
+ * (set|clear)_loop_stop registers.  Otherwise (for example) the voices would 
+ * get out of sync when pausing/resuming a stream.
+ *							--rlrevell
+ */
+
+static int voice_alloc(emu10k1_t *emu, emu10k1_voice_type_t type, int number, emu10k1_voice_t **rvoice)
 {
-	emu10k1_voice_t *voice, *voice2;
-	int idx;
+	emu10k1_voice_t *voice;
+	int i, j, k, first_voice, last_voice, skip;
 
 	*rvoice = NULL;
-	for (idx = 0; idx < 64; idx += pair ? 2 : 1) {
-		voice = &emu->voices[idx];
-		voice2 = pair ? &emu->voices[idx+1] : NULL;
-		if (voice->use || (voice2 && voice2->use))
+	first_voice = last_voice = 0;
+	for (i = emu->next_free_voice, j = 0; j < NUM_G ; i += number, j += number) {
+		// printk("i %d j %d next free %d!\n", i, j, emu->next_free_voice);
+		i %= NUM_G;
+
+		/* stereo voices must be even/odd */
+		if ((number == 2) && (i % 2)) {
+			i++;
 			continue;
+		}
+			
+		/* make sure the block of voices does not cross the 32 voice boundary */
+		//if (((i % 32) + number) > 32)
+		//	continue;
+
+		skip = 0;
+		for (k = 0; k < number; k++) {
+			voice = &emu->voices[(i+k) % NUM_G];
+			if (voice->use)
+				skip = 1;
+		}
+		if (!skip) {
+			// printk("allocated voice %d\n", i);
+			first_voice = i;
+			last_voice = (i + number) % NUM_G;
+			emu->next_free_voice = last_voice;
+			break;
+		}
+	}
+	
+	if (first_voice == last_voice) {
+		printk("BUG (or not enough voices), number %d, next free %d!\n",
+				number,
+				emu->next_free_voice);
+		return -ENOMEM;
+	}	
+	
+	for (i=0; i < number; i++) {
+		voice = &emu->voices[(first_voice + i) % NUM_G];
+		// printk("voice alloc - %i, %i of %i\n", voice->number, idx-first_voice+1, number);
 		voice->use = 1;
-		if (voice2)
-			voice2->use = 1;
 		switch (type) {
 		case EMU10K1_PCM:
 			voice->pcm = 1;
-			if (voice2)
-				voice2->pcm = 1;
 			break;
 		case EMU10K1_SYNTH:
 			voice->synth = 1;
@@ -56,26 +102,27 @@
 		case EMU10K1_MIDI:
 			voice->midi = 1;
 			break;
+		case EMU10K1_EFX:
+			voice->efx = 1;
+			break;
 		}
-		// printk("voice alloc - %i, pair = %i\n", voice->number, pair);
-		*rvoice = voice;
-		return 0;
 	}
-	return -ENOMEM;
+	*rvoice = &emu->voices[first_voice];
+	return 0;
 }
 
-int snd_emu10k1_voice_alloc(emu10k1_t *emu, emu10k1_voice_type_t type, int pair, emu10k1_voice_t **rvoice)
+int snd_emu10k1_voice_alloc(emu10k1_t *emu, emu10k1_voice_type_t type, int number, emu10k1_voice_t **rvoice)
 {
 	unsigned long flags;
 	int result;
 
 	snd_assert(rvoice != NULL, return -EINVAL);
-	snd_assert(!pair || type == EMU10K1_PCM, return -EINVAL);
+	snd_assert(number, return -EINVAL);
 
 	spin_lock_irqsave(&emu->voice_lock, flags);
 	for (;;) {
-		result = voice_alloc(emu, type, pair, rvoice);
-		if (result == 0 || type != EMU10K1_PCM)
+		result = voice_alloc(emu, type, number, rvoice);
+		if (result == 0 || type == EMU10K1_SYNTH || type == EMU10K1_MIDI)
 			break;
 
 		/* free a voice from synth */
@@ -84,7 +131,7 @@
 			if (result >= 0) {
 				emu10k1_voice_t *pvoice = &emu->voices[result];
 				pvoice->interrupt = NULL;
-				pvoice->use = pvoice->pcm = pvoice->synth = pvoice->midi = 0;
+				pvoice->use = pvoice->pcm = pvoice->synth = pvoice->midi = pvoice->efx = 0;
 				pvoice->epcm = NULL;
 			}
 		}
@@ -103,7 +150,7 @@
 	snd_assert(pvoice != NULL, return -EINVAL);
 	spin_lock_irqsave(&emu->voice_lock, flags);
 	pvoice->interrupt = NULL;
-	pvoice->use = pvoice->pcm = pvoice->synth = pvoice->midi = 0;
+	pvoice->use = pvoice->pcm = pvoice->synth = pvoice->midi = pvoice->efx = 0;
 	pvoice->epcm = NULL;
 	snd_emu10k1_voice_init(emu, pvoice->number);
 	spin_unlock_irqrestore(&emu->voice_lock, flags);
diff -Nru a/sound/pci/ens1370.c b/sound/pci/ens1370.c
--- a/sound/pci/ens1370.c	2005-03-11 12:51:51 -08:00
+++ b/sound/pci/ens1370.c	2005-03-11 12:51:51 -08:00
@@ -430,7 +430,7 @@
 #endif
 
 #ifdef SUPPORT_JOYSTICK
-	struct gameport gameport;
+	struct gameport *gameport;
 #endif
 };
 
@@ -754,6 +754,8 @@
 
 static int snd_ensoniq_trigger(snd_pcm_substream_t *substream, int cmd)
 {
+	unsigned long flags;
+
 	ensoniq_t *ensoniq = snd_pcm_substream_chip(substream);
 	switch (cmd) {
 	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
@@ -773,13 +775,13 @@
 			} else if (s == ensoniq->capture_substream)
 				return -EINVAL;
 		}
-		spin_lock(&ensoniq->reg_lock);
+		spin_lock_irqsave(&ensoniq->reg_lock, flags);
 		if (cmd == SNDRV_PCM_TRIGGER_PAUSE_PUSH)
 			ensoniq->sctrl |= what;
 		else
 			ensoniq->sctrl &= ~what;
 		outl(ensoniq->sctrl, ES_REG(ensoniq, SERIAL));
-		spin_unlock(&ensoniq->reg_lock);
+		spin_unlock_irqrestore(&ensoniq->reg_lock, flags);
 		break;
 	}
 	case SNDRV_PCM_TRIGGER_START:
@@ -801,13 +803,13 @@
 				snd_pcm_trigger_done(s, substream);
 			}
 		}
-		spin_lock(&ensoniq->reg_lock);
+		spin_lock_irqsave(&ensoniq->reg_lock, flags);
 		if (cmd == SNDRV_PCM_TRIGGER_START)
 			ensoniq->ctrl |= what;
 		else
 			ensoniq->ctrl &= ~what;
 		outl(ensoniq->ctrl, ES_REG(ensoniq, CONTROL));
-		spin_unlock(&ensoniq->reg_lock);
+		spin_unlock_irqrestore(&ensoniq->reg_lock, flags);
 		break;
 	}
 	default:
@@ -956,10 +958,11 @@
 
 static snd_pcm_uframes_t snd_ensoniq_playback1_pointer(snd_pcm_substream_t * substream)
 {
+	unsigned long flags;
 	ensoniq_t *ensoniq = snd_pcm_substream_chip(substream);
 	size_t ptr;
 
-	spin_lock(&ensoniq->reg_lock);
+	spin_lock_irqsave(&ensoniq->reg_lock, flags);
 	if (inl(ES_REG(ensoniq, CONTROL)) & ES_DAC1_EN) {
 		outl(ES_MEM_PAGEO(ES_PAGE_DAC), ES_REG(ensoniq, MEM_PAGE));
 		ptr = ES_REG_FCURR_COUNTI(inl(ES_REG(ensoniq, DAC1_SIZE)));
@@ -967,16 +970,17 @@
 	} else {
 		ptr = 0;
 	}
-	spin_unlock(&ensoniq->reg_lock);
+	spin_unlock_irqrestore(&ensoniq->reg_lock, flags);
 	return ptr;
 }
 
 static snd_pcm_uframes_t snd_ensoniq_playback2_pointer(snd_pcm_substream_t * substream)
 {
+	unsigned long flags;
 	ensoniq_t *ensoniq = snd_pcm_substream_chip(substream);
 	size_t ptr;
 
-	spin_lock(&ensoniq->reg_lock);
+	spin_lock_irqsave(&ensoniq->reg_lock, flags);
 	if (inl(ES_REG(ensoniq, CONTROL)) & ES_DAC2_EN) {
 		outl(ES_MEM_PAGEO(ES_PAGE_DAC), ES_REG(ensoniq, MEM_PAGE));
 		ptr = ES_REG_FCURR_COUNTI(inl(ES_REG(ensoniq, DAC2_SIZE)));
@@ -984,16 +988,17 @@
 	} else {
 		ptr = 0;
 	}
-	spin_unlock(&ensoniq->reg_lock);
+	spin_unlock_irqrestore(&ensoniq->reg_lock, flags);
 	return ptr;
 }
 
 static snd_pcm_uframes_t snd_ensoniq_capture_pointer(snd_pcm_substream_t * substream)
 {
+	unsigned long flags;
 	ensoniq_t *ensoniq = snd_pcm_substream_chip(substream);
 	size_t ptr;
 
-	spin_lock(&ensoniq->reg_lock);
+	spin_lock_irqsave(&ensoniq->reg_lock, flags);
 	if (inl(ES_REG(ensoniq, CONTROL)) & ES_ADC_EN) {
 		outl(ES_MEM_PAGEO(ES_PAGE_ADC), ES_REG(ensoniq, MEM_PAGE));
 		ptr = ES_REG_FCURR_COUNTI(inl(ES_REG(ensoniq, ADC_SIZE)));
@@ -1001,7 +1006,7 @@
 	} else {
 		ptr = 0;
 	}
-	spin_unlock(&ensoniq->reg_lock);
+	spin_unlock_irqrestore(&ensoniq->reg_lock, flags);
 	return ptr;
 }
 
@@ -1734,43 +1739,99 @@
 #endif /* CHIP1370 */
 
 #ifdef SUPPORT_JOYSTICK
-static int snd_ensoniq_joystick(ensoniq_t *ensoniq, long port)
-{
+
 #ifdef CHIP1371
-	if (port == 1) { /* auto-detect */
-		for (port = 0x200; port <= 0x218; port += 8)
-			if (request_region(port, 8, "ens137x: gameport"))
+static int __devinit snd_ensoniq_get_joystick_port(int dev)
+{
+	switch (joystick_port[dev]) {
+	case 0: /* disabled */
+	case 1: /* auto-detect */
+	case 0x200:
+	case 0x208:
+	case 0x210:
+	case 0x218:
+		return joystick_port[dev];
+
+	default:
+		printk(KERN_ERR "ens1371: invalid joystick port %#x", joystick_port[dev]);
+		return 0;
+	}
+}
+#else
+static inline int snd_ensoniq_get_joystick_port(int dev)
+{
+	return joystick[dev] ? 0x200 : 0;
+}
+#endif
+
+static int __devinit snd_ensoniq_create_gameport(ensoniq_t *ensoniq, int dev)
+{
+	struct gameport *gp;
+	int io_port;
+
+	io_port = snd_ensoniq_get_joystick_port(dev);
+
+	switch (io_port) {
+	case 0:
+		return -ENOSYS;
+
+	case 1: /* auto_detect */
+		for (io_port = 0x200; io_port <= 0x218; io_port += 8)
+			if (request_region(io_port, 8, "ens137x: gameport"))
 				break;
-		if (port > 0x218) {
-			snd_printk("no gameport available\n");
+		if (io_port > 0x218) {
+			printk(KERN_WARNING "ens137x: no gameport ports available\n");
 			return -EBUSY;
 		}
-	} else
-#endif
-	{
-		if (!request_region(port, 8, "ens137x: gameport")) {
-			snd_printk("gameport io port 0x%03x in use", ensoniq->gameport.io);
+		break;
+
+	default:
+		if (!request_region(io_port, 8, "ens137x: gameport")) {
+			printk(KERN_WARNING "ens137x: gameport io port 0x%#x in use\n", io_port);
 			return -EBUSY;
 		}
+		break;
 	}
-	ensoniq->gameport.io = port;
+
+	ensoniq->gameport = gp = gameport_allocate_port();
+	if (!gp) {
+		printk(KERN_ERR "ens137x: cannot allocate memory for gameport\n");
+		release_region(io_port, 8);
+		return -ENOMEM;
+	}
+
+	gameport_set_name(gp, "ES137x");
+	gameport_set_phys(gp, "pci%s/gameport0", pci_name(ensoniq->pci));
+	gp->dev.parent = &ensoniq->pci->dev;
+	gp->io = io_port;
+
 	ensoniq->ctrl |= ES_JYSTK_EN;
 #ifdef CHIP1371
 	ensoniq->ctrl &= ~ES_1371_JOY_ASELM;
-	ensoniq->ctrl |= ES_1371_JOY_ASEL((ensoniq->gameport.io - 0x200) / 8);
+	ensoniq->ctrl |= ES_1371_JOY_ASEL((io_port - 0x200) / 8);
 #endif
 	outl(ensoniq->ctrl, ES_REG(ensoniq, CONTROL));
-	gameport_register_port(&ensoniq->gameport);
+
+	gameport_register_port(ensoniq->gameport);
+
 	return 0;
 }
 
-static void snd_ensoniq_joystick_free(ensoniq_t *ensoniq)
+static void snd_ensoniq_free_gameport(ensoniq_t *ensoniq)
 {
-	gameport_unregister_port(&ensoniq->gameport);
-	ensoniq->ctrl &= ~ES_JYSTK_EN;
-	outl(ensoniq->ctrl, ES_REG(ensoniq, CONTROL));
-	release_region(ensoniq->gameport.io, 8);
+	if (ensoniq->gameport) {
+		int port = ensoniq->gameport->io;
+
+		gameport_unregister_port(ensoniq->gameport);
+		ensoniq->gameport = NULL;
+		ensoniq->ctrl &= ~ES_JYSTK_EN;
+		outl(ensoniq->ctrl, ES_REG(ensoniq, CONTROL));
+		release_region(port, 8);
+	}
 }
+#else
+static inline int snd_ensoniq_create_gameport(ensoniq_t *ensoniq, long port) { return -ENOSYS; }
+static inline void snd_ensoniq_free_gameport(ensoniq_t *ensoniq) { }
 #endif /* SUPPORT_JOYSTICK */
 
 /*
@@ -1810,10 +1871,7 @@
 
 static int snd_ensoniq_free(ensoniq_t *ensoniq)
 {
-#ifdef SUPPORT_JOYSTICK
-	if (ensoniq->ctrl & ES_JYSTK_EN)
-		snd_ensoniq_joystick_free(ensoniq);
-#endif
+	snd_ensoniq_free_gameport(ensoniq);
 	if (ensoniq->irq < 0)
 		goto __hw_end;
 #ifdef CHIP1370
@@ -2030,27 +2088,26 @@
 
 static void snd_ensoniq_midi_interrupt(ensoniq_t * ensoniq)
 {
+	unsigned long flags;
 	snd_rawmidi_t * rmidi = ensoniq->rmidi;
 	unsigned char status, mask, byte;
 
 	if (rmidi == NULL)
 		return;
 	/* do Rx at first */
-	spin_lock(&ensoniq->reg_lock);
+	spin_lock_irqsave(&ensoniq->reg_lock, flags);
 	mask = ensoniq->uartm & ES_MODE_INPUT ? ES_RXRDY : 0;
 	while (mask) {
 		status = inb(ES_REG(ensoniq, UART_STATUS));
 		if ((status & mask) == 0)
 			break;
 		byte = inb(ES_REG(ensoniq, UART_DATA));
-		spin_unlock(&ensoniq->reg_lock);
 		snd_rawmidi_receive(ensoniq->midi_input, &byte, 1);
-		spin_lock(&ensoniq->reg_lock);
 	}
-	spin_unlock(&ensoniq->reg_lock);
+	spin_unlock_irqrestore(&ensoniq->reg_lock, flags);
 
 	/* do Tx at second */
-	spin_lock(&ensoniq->reg_lock);
+	spin_lock_irqsave(&ensoniq->reg_lock, flags);
 	mask = ensoniq->uartm & ES_MODE_OUTPUT ? ES_TXRDY : 0;
 	while (mask) {
 		status = inb(ES_REG(ensoniq, UART_STATUS));
@@ -2064,7 +2121,7 @@
 			outb(byte, ES_REG(ensoniq, UART_DATA));
 		}
 	}
-	spin_unlock(&ensoniq->reg_lock);
+	spin_unlock_irqrestore(&ensoniq->reg_lock, flags);
 }
 
 static int snd_ensoniq_midi_input_open(snd_rawmidi_substream_t * substream)
@@ -2231,6 +2288,7 @@
 
 static irqreturn_t snd_audiopci_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
+	unsigned long flags;
 	ensoniq_t *ensoniq = dev_id;
 	unsigned int status, sctrl;
 
@@ -2241,7 +2299,7 @@
 	if (!(status & ES_INTR))
 		return IRQ_NONE;
 
-	spin_lock(&ensoniq->reg_lock);
+	spin_lock_irqsave(&ensoniq->reg_lock, flags);
 	sctrl = ensoniq->sctrl;
 	if (status & ES_DAC1)
 		sctrl &= ~ES_P1_INT_EN;
@@ -2251,7 +2309,7 @@
 		sctrl &= ~ES_R1_INT_EN;
 	outl(sctrl, ES_REG(ensoniq, SERIAL));
 	outl(ensoniq->sctrl, ES_REG(ensoniq, SERIAL));
-	spin_unlock(&ensoniq->reg_lock);
+	spin_unlock_irqrestore(&ensoniq->reg_lock, flags);
 
 	if (status & ES_UART)
 		snd_ensoniq_midi_interrupt(ensoniq);
@@ -2313,22 +2371,9 @@
 		snd_card_free(card);
 		return err;
 	}
-#ifdef SUPPORT_JOYSTICK
-#ifdef CHIP1371
-	switch (joystick_port[dev]) {
-	case 1: /* auto-detect */
-	case 0x200:
-	case 0x208:
-	case 0x210:
-	case 0x218:
-		snd_ensoniq_joystick(ensoniq, joystick_port[dev]);
-		break;
-	}
-#else
-	if (joystick[dev])
-		snd_ensoniq_joystick(ensoniq, 0x200);
-#endif
-#endif /* SUPPORT_JOYSTICK */
+
+	snd_ensoniq_create_gameport(ensoniq, dev);
+
 	strcpy(card->driver, DRIVER_NAME);
 
 	strcpy(card->shortname, "Ensoniq AudioPCI");
diff -Nru a/sound/pci/es1938.c b/sound/pci/es1938.c
--- a/sound/pci/es1938.c	2005-03-11 12:51:47 -08:00
+++ b/sound/pci/es1938.c	2005-03-11 12:51:47 -08:00
@@ -72,6 +72,10 @@
                 "{ESS,ES1969},"
 		"{TerraTec,128i PCI}}");
 
+#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))
+#define SUPPORT_JOYSTICK 1
+#endif
+
 #ifndef PCI_VENDOR_ID_ESS
 #define PCI_VENDOR_ID_ESS		0x125d
 #endif
@@ -237,8 +241,8 @@
 	spinlock_t mixer_lock;
         snd_info_entry_t *proc_entry;
 
-#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))
-	struct gameport gameport;
+#ifdef SUPPORT_JOYSTICK
+	struct gameport *gameport;
 #endif
 #ifdef CONFIG_PM
 	unsigned char saved_regs[SAVED_REG_SIZE];
@@ -1381,7 +1385,7 @@
 };
 
 
-static int es1938_suspend(snd_card_t *card, unsigned int state)
+static int es1938_suspend(snd_card_t *card, pm_message_t state)
 {
 	es1938_t *chip = card->pm_private_data;
 	unsigned char *s, *d;
@@ -1398,7 +1402,7 @@
 	return 0;
 }
 
-static int es1938_resume(snd_card_t *card, unsigned int state)
+static int es1938_resume(snd_card_t *card)
 {
 	es1938_t *chip = card->pm_private_data;
 	unsigned char *s, *d;
@@ -1418,6 +1422,39 @@
 }
 #endif /* CONFIG_PM */
 
+#ifdef SUPPORT_JOYSTICK
+static int __devinit snd_es1938_create_gameport(es1938_t *chip)
+{
+	struct gameport *gp;
+
+	chip->gameport = gp = gameport_allocate_port();
+	if (!gp) {
+		printk(KERN_ERR "es1938: cannot allocate memory for gameport\n");
+		return -ENOMEM;
+	}
+
+	gameport_set_name(gp, "ES1938");
+	gameport_set_phys(gp, "pci%s/gameport0", pci_name(chip->pci));
+	gp->dev.parent = &chip->pci->dev;
+	gp->io = chip->game_port;
+
+	gameport_register_port(gp);
+
+	return 0;
+}
+
+static void snd_es1938_free_gameport(es1938_t *chip)
+{
+	if (chip->gameport) {
+		gameport_unregister_port(chip->gameport);
+		chip->gameport = NULL;
+	}
+}
+#else
+static inline int snd_es1938_create_gameport(es1938_t *chip) { return -ENOSYS; }
+static inline void snd_es1938_free_gameport(es1938_t *chip) { }
+#endif /* SUPPORT_JOYSTICK */
+
 static int snd_es1938_free(es1938_t *chip)
 {
 	/* disable irqs */
@@ -1425,10 +1462,8 @@
 	if (chip->rmidi)
 		snd_es1938_mixer_bits(chip, ESSSB_IREG_MPU401CONTROL, 0x40, 0);
 
-#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))
-	if (chip->gameport.io)
-		gameport_unregister_port(&chip->gameport);
-#endif
+	snd_es1938_free_gameport(chip);
+
 	if (chip->irq >= 0)
 		free_irq(chip->irq, (void *)chip);
 	pci_release_regions(chip->pci);
@@ -1698,10 +1733,7 @@
 		snd_es1938_mixer_bits(chip, ESSSB_IREG_MPU401CONTROL, 0x40, 0x40);
 	}
 
-#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))
-	chip->gameport.io = chip->game_port;
-	gameport_register_port(&chip->gameport);
-#endif
+	snd_es1938_create_gameport(chip);
 
 	if ((err = snd_card_register(card)) < 0) {
 		snd_card_free(card);
diff -Nru a/sound/pci/es1968.c b/sound/pci/es1968.c
--- a/sound/pci/es1968.c	2005-03-11 12:51:52 -08:00
+++ b/sound/pci/es1968.c	2005-03-11 12:51:52 -08:00
@@ -605,8 +605,7 @@
 #endif
 
 #ifdef SUPPORT_JOYSTICK
-	struct gameport gameport;
-	struct resource *res_joystick;
+	struct gameport *gameport;
 #endif
 };
 
@@ -2404,7 +2403,7 @@
 /*
  * PM support
  */
-static int es1968_suspend(snd_card_t *card, unsigned int state)
+static int es1968_suspend(snd_card_t *card, pm_message_t state)
 {
 	es1968_t *chip = card->pm_private_data;
 
@@ -2419,7 +2418,7 @@
 	return 0;
 }
 
-static int es1968_resume(snd_card_t *card, unsigned int state)
+static int es1968_resume(snd_card_t *card)
 {
 	es1968_t *chip = card->pm_private_data;
 
@@ -2450,6 +2449,59 @@
 }
 #endif /* CONFIG_PM */
 
+#ifdef SUPPORT_JOYSTICK
+#define JOYSTICK_ADDR	0x200
+static int __devinit snd_es1968_create_gameport(es1968_t *chip, int dev)
+{
+	struct gameport *gp;
+	struct resource *r;
+	u16 val;
+
+	if (!joystick[dev])
+		return -ENODEV;
+
+	r = request_region(JOYSTICK_ADDR, 8, "ES1968 gameport");
+	if (!r)
+		return -EBUSY;
+
+	chip->gameport = gp = gameport_allocate_port();
+	if (!gp) {
+		printk(KERN_ERR "es1968: cannot allocate memory for gameport\n");
+		release_resource(r);
+		kfree_nocheck(r);
+		return -ENOMEM;
+	}
+
+	pci_read_config_word(chip->pci, ESM_LEGACY_AUDIO_CONTROL, &val);
+	pci_write_config_word(chip->pci, ESM_LEGACY_AUDIO_CONTROL, val | 0x04);
+
+	gameport_set_name(gp, "ES1968 Gameport");
+	gameport_set_phys(gp, "pci%s/gameport0", pci_name(chip->pci));
+	gp->dev.parent = &chip->pci->dev;
+	gp->io = JOYSTICK_ADDR;
+
+	gameport_register_port(gp);
+
+	return 0;
+}
+
+static void snd_es1968_free_gameport(es1968_t *chip)
+{
+	if (chip->gameport) {
+		struct resource *r = chip->gameport->port_data;
+
+		gameport_unregister_port(chip->gameport);
+		chip->gameport = NULL;
+
+		release_resource(r);
+		kfree_nocheck(r);
+	}
+}
+#else
+static inline int snd_es1968_create_gameport(es1968_t *chip, int dev) { return -ENOSYS; }
+static inline void snd_es1968_free_gameport(es1968_t *chip) { }
+#endif
+
 static int snd_es1968_free(es1968_t *chip)
 {
 	if (chip->io_port) {
@@ -2460,13 +2512,7 @@
 
 	if (chip->irq >= 0)
 		free_irq(chip->irq, (void *)chip);
-#ifdef SUPPORT_JOYSTICK
-	if (chip->res_joystick) {
-		gameport_unregister_port(&chip->gameport);
-		release_resource(chip->res_joystick);
-		kfree_nocheck(chip->res_joystick);
-	}
-#endif
+	snd_es1968_free_gameport(chip);
 	snd_es1968_set_acpi(chip, ACPI_D3);
 	chip->master_switch = NULL;
 	chip->master_volume = NULL;
@@ -2693,17 +2739,7 @@
 		}
 	}
 
-#ifdef SUPPORT_JOYSTICK
-#define JOYSTICK_ADDR	0x200
-	if (joystick[dev] &&
-	    (chip->res_joystick = request_region(JOYSTICK_ADDR, 8, "ES1968 gameport")) != NULL) {
-		u16 val;
-		pci_read_config_word(pci, ESM_LEGACY_AUDIO_CONTROL, &val);
-		pci_write_config_word(pci, ESM_LEGACY_AUDIO_CONTROL, val | 0x04);
-		chip->gameport.io = JOYSTICK_ADDR;
-		gameport_register_port(&chip->gameport);
-	}
-#endif
+	snd_es1968_create_gameport(chip, dev);
 
 	snd_es1968_start_irq(chip);
 
diff -Nru a/sound/pci/fm801.c b/sound/pci/fm801.c
--- a/sound/pci/fm801.c	2005-03-11 12:51:50 -08:00
+++ b/sound/pci/fm801.c	2005-03-11 12:51:50 -08:00
@@ -64,7 +64,7 @@
 MODULE_PARM_DESC(id, "ID string for the FM801 soundcard.");
 module_param_array(enable, bool, NULL, 0444);
 MODULE_PARM_DESC(enable, "Enable FM801 soundcard.");
-module_param_array(tea575x_tuner, bool, NULL, 0444);
+module_param_array(tea575x_tuner, int, NULL, 0444);
 MODULE_PARM_DESC(tea575x_tuner, "Enable TEA575x tuner.");
 
 /*
diff -Nru a/sound/pci/hda/Makefile b/sound/pci/hda/Makefile
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/sound/pci/hda/Makefile	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,7 @@
+snd-hda-intel-objs := hda_intel.o
+snd-hda-codec-objs := hda_codec.o hda_generic.o patch_realtek.o patch_cmedia.o
+ifdef CONFIG_PROC_FS
+snd-hda-codec-objs += hda_proc.o
+endif
+
+obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-intel.o snd-hda-codec.o
diff -Nru a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/sound/pci/hda/hda_codec.c	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,1850 @@
+/*
+ * Universal Interface for Intel High Definition Audio Codec
+ *
+ * Copyright (c) 2004 Takashi Iwai <tiwai@suse.de>
+ *
+ *
+ *  This driver 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 driver is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ */
+
+#include <sound/driver.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/pci.h>
+#include <linux/moduleparam.h>
+#include <sound/core.h>
+#include "hda_codec.h"
+#include <sound/asoundef.h>
+#include <sound/initval.h>
+#include "hda_local.h"
+
+
+MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>");
+MODULE_DESCRIPTION("Universal interface for High Definition Audio Codec");
+MODULE_LICENSE("GPL");
+
+
+/*
+ * vendor / preset table
+ */
+
+struct hda_vendor_id {
+	unsigned int id;
+	const char *name;
+};
+
+/* codec vendor labels */
+static struct hda_vendor_id hda_vendor_ids[] = {
+	{ 0x10ec, "Realtek" },
+	{ 0x434d, "C-Media" },
+	{} /* terminator */
+};
+
+/* codec presets */
+#include "hda_patch.h"
+
+
+/**
+ * snd_hda_codec_read - send a command and get the response
+ * @codec: the HDA codec
+ * @nid: NID to send the command
+ * @direct: direct flag
+ * @verb: the verb to send
+ * @parm: the parameter for the verb
+ *
+ * Send a single command and read the corresponding response.
+ *
+ * Returns the obtained response value, or -1 for an error.
+ */
+unsigned int snd_hda_codec_read(struct hda_codec *codec, hda_nid_t nid, int direct,
+				unsigned int verb, unsigned int parm)
+{
+	unsigned int res;
+	down(&codec->bus->cmd_mutex);
+	if (! codec->bus->ops.command(codec, nid, direct, verb, parm))
+		res = codec->bus->ops.get_response(codec);
+	else
+		res = (unsigned int)-1;
+	up(&codec->bus->cmd_mutex);
+	return res;
+}
+
+/**
+ * snd_hda_codec_write - send a single command without waiting for response
+ * @codec: the HDA codec
+ * @nid: NID to send the command
+ * @direct: direct flag
+ * @verb: the verb to send
+ * @parm: the parameter for the verb
+ *
+ * Send a single command without waiting for response.
+ *
+ * Returns 0 if successful, or a negative error code.
+ */
+int snd_hda_codec_write(struct hda_codec *codec, hda_nid_t nid, int direct,
+			 unsigned int verb, unsigned int parm)
+{
+	int err;
+	down(&codec->bus->cmd_mutex);
+	err = codec->bus->ops.command(codec, nid, direct, verb, parm);
+	up(&codec->bus->cmd_mutex);
+	return err;
+}
+
+/**
+ * snd_hda_sequence_write - sequence writes
+ * @codec: the HDA codec
+ * @seq: VERB array to send
+ *
+ * Send the commands sequentially from the given array.
+ * The array must be terminated with NID=0.
+ */
+void snd_hda_sequence_write(struct hda_codec *codec, const struct hda_verb *seq)
+{
+	for (; seq->nid; seq++)
+		snd_hda_codec_write(codec, seq->nid, 0, seq->verb, seq->param);
+}
+
+/**
+ * snd_hda_get_sub_nodes - get the range of sub nodes
+ * @codec: the HDA codec
+ * @nid: NID to parse
+ * @start_id: the pointer to store the start NID
+ *
+ * Parse the NID and store the start NID of its sub-nodes.
+ * Returns the number of sub-nodes.
+ */
+int snd_hda_get_sub_nodes(struct hda_codec *codec, hda_nid_t nid, hda_nid_t *start_id)
+{
+	unsigned int parm;
+
+	parm = snd_hda_param_read(codec, nid, AC_PAR_NODE_COUNT);
+	*start_id = (parm >> 16) & 0x7fff;
+	return (int)(parm & 0x7fff);
+}
+
+/**
+ * snd_hda_get_connections - get connection list
+ * @codec: the HDA codec
+ * @nid: NID to parse
+ * @conn_list: connection list array
+ * @max_conns: max. number of connections to store
+ *
+ * Parses the connection list of the given widget and stores the list
+ * of NIDs.
+ *
+ * Returns the number of connections, or a negative error code.
+ */
+int snd_hda_get_connections(struct hda_codec *codec, hda_nid_t nid,
+			    hda_nid_t *conn_list, int max_conns)
+{
+	unsigned int parm;
+	int i, j, conn_len, num_tupples, conns;
+	unsigned int shift, num_elems, mask;
+
+	snd_assert(conn_list && max_conns > 0, return -EINVAL);
+
+	parm = snd_hda_param_read(codec, nid, AC_PAR_CONNLIST_LEN);
+	if (parm & AC_CLIST_LONG) {
+		/* long form */
+		shift = 16;
+		num_elems = 2;
+	} else {
+		/* short form */
+		shift = 8;
+		num_elems = 4;
+	}
+	conn_len = parm & AC_CLIST_LENGTH;
+	num_tupples = num_elems / 2;
+	mask = (1 << (shift-1)) - 1;
+
+	if (! conn_len)
+		return 0; /* no connection */
+
+	if (conn_len == 1) {
+		/* single connection */
+		parm = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONNECT_LIST, 0);
+		conn_list[0] = parm & mask;
+		return 1;
+	}
+
+	/* multi connection */
+	conns = 0;
+	for (i = 0; i < conn_len; i += num_elems) {
+		parm = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONNECT_LIST, i);
+		for (j = 0; j < num_tupples; j++) {
+			int range_val;
+			hda_nid_t val1, val2, n;
+			range_val = parm & (1 << (shift-1)); /* ranges */
+			val1 = parm & mask;
+			parm >>= shift;
+			val2 = parm & mask;
+			parm >>= shift;
+			if (range_val) {
+				/* ranges between val1 and val2 */
+				if (val1 > val2) {
+					snd_printk(KERN_WARNING "hda_codec: invalid dep_range_val %x:%x\n", val1, val2);
+					continue;
+				}
+				for (n = val1; n <= val2; n++) {
+					if (conns >= max_conns)
+						return -EINVAL;
+					conn_list[conns++] = n;
+				}
+			} else {
+				if (! val1)
+					break;
+				if (conns >= max_conns)
+					return -EINVAL;
+				conn_list[conns++] = val1;
+				if (! val2)
+					break;
+				if (conns >= max_conns)
+					return -EINVAL;
+				conn_list[conns++] = val2;
+			}
+		}
+	}
+	return conns;
+}
+
+
+/**
+ * snd_hda_queue_unsol_event - add an unsolicited event to queue
+ * @bus: the BUS
+ * @res: unsolicited event (lower 32bit of RIRB entry)
+ * @res_ex: codec addr and flags (upper 32bit or RIRB entry)
+ *
+ * Adds the given event to the queue.  The events are processed in
+ * the workqueue asynchronously.  Call this function in the interrupt
+ * hanlder when RIRB receives an unsolicited event.
+ *
+ * Returns 0 if successful, or a negative error code.
+ */
+int snd_hda_queue_unsol_event(struct hda_bus *bus, u32 res, u32 res_ex)
+{
+	struct hda_bus_unsolicited *unsol;
+	unsigned int wp;
+
+	if ((unsol = bus->unsol) == NULL)
+		return 0;
+
+	wp = (unsol->wp + 1) % HDA_UNSOL_QUEUE_SIZE;
+	unsol->wp = wp;
+
+	wp <<= 1;
+	unsol->queue[wp] = res;
+	unsol->queue[wp + 1] = res_ex;
+
+	queue_work(unsol->workq, &unsol->work);
+
+	return 0;
+}
+
+/*
+ * process queueud unsolicited events
+ */
+static void process_unsol_events(void *data)
+{
+	struct hda_bus *bus = data;
+	struct hda_bus_unsolicited *unsol = bus->unsol;
+	struct hda_codec *codec;
+	unsigned int rp, caddr, res;
+
+	while (unsol->rp != unsol->wp) {
+		rp = (unsol->rp + 1) % HDA_UNSOL_QUEUE_SIZE;
+		unsol->rp = rp;
+		rp <<= 1;
+		res = unsol->queue[rp];
+		caddr = unsol->queue[rp + 1];
+		if (! (caddr & (1 << 4))) /* no unsolicited event? */
+			continue;
+		codec = bus->caddr_tbl[caddr & 0x0f];
+		if (codec && codec->patch_ops.unsol_event)
+			codec->patch_ops.unsol_event(codec, res);
+	}
+}
+
+/*
+ * initialize unsolicited queue
+ */
+static int init_unsol_queue(struct hda_bus *bus)
+{
+	struct hda_bus_unsolicited *unsol;
+
+	unsol = kcalloc(1, sizeof(*unsol), GFP_KERNEL);
+	if (! unsol) {
+		snd_printk(KERN_ERR "hda_codec: can't allocate unsolicited queue\n");
+		return -ENOMEM;
+	}
+	unsol->workq = create_workqueue("hda_codec");
+	if (! unsol->workq) {
+		snd_printk(KERN_ERR "hda_codec: can't create workqueue\n");
+		kfree(unsol);
+		return -ENOMEM;
+	}
+	INIT_WORK(&unsol->work, process_unsol_events, bus);
+	bus->unsol = unsol;
+	return 0;
+}
+
+/*
+ * destructor
+ */
+static void snd_hda_codec_free(struct hda_codec *codec);
+
+static int snd_hda_bus_free(struct hda_bus *bus)
+{
+	struct list_head *p, *n;
+
+	if (! bus)
+		return 0;
+	if (bus->unsol) {
+		destroy_workqueue(bus->unsol->workq);
+		kfree(bus->unsol);
+	}
+	list_for_each_safe(p, n, &bus->codec_list) {
+		struct hda_codec *codec = list_entry(p, struct hda_codec, list);
+		snd_hda_codec_free(codec);
+	}
+	if (bus->ops.private_free)
+		bus->ops.private_free(bus);
+	kfree(bus);
+	return 0;
+}
+
+static int snd_hda_bus_dev_free(snd_device_t *device)
+{
+	struct hda_bus *bus = device->device_data;
+	return snd_hda_bus_free(bus);
+}
+
+/**
+ * snd_hda_bus_new - create a HDA bus
+ * @card: the card entry
+ * @temp: the template for hda_bus information
+ * @busp: the pointer to store the created bus instance
+ *
+ * Returns 0 if successful, or a negative error code.
+ */
+int snd_hda_bus_new(snd_card_t *card, const struct hda_bus_template *temp,
+		    struct hda_bus **busp)
+{
+	struct hda_bus *bus;
+	int err;
+	static snd_device_ops_t dev_ops = {
+		.dev_free = snd_hda_bus_dev_free,
+	};
+
+	snd_assert(temp, return -EINVAL);
+	snd_assert(temp->ops.command && temp->ops.get_response, return -EINVAL);
+
+	if (busp)
+		*busp = NULL;
+
+	bus = kcalloc(1, sizeof(*bus), GFP_KERNEL);
+	if (bus == NULL) {
+		snd_printk(KERN_ERR "can't allocate struct hda_bus\n");
+		return -ENOMEM;
+	}
+
+	bus->card = card;
+	bus->private_data = temp->private_data;
+	bus->pci = temp->pci;
+	bus->modelname = temp->modelname;
+	bus->ops = temp->ops;
+
+	init_MUTEX(&bus->cmd_mutex);
+	INIT_LIST_HEAD(&bus->codec_list);
+
+	init_unsol_queue(bus);
+
+	if ((err = snd_device_new(card, SNDRV_DEV_BUS, bus, &dev_ops)) < 0) {
+		snd_hda_bus_free(bus);
+		return err;
+	}
+	if (busp)
+		*busp = bus;
+	return 0;
+}
+
+
+/*
+ * find a matching codec preset
+ */
+static const struct hda_codec_preset *find_codec_preset(struct hda_codec *codec)
+{
+	const struct hda_codec_preset **tbl, *preset;
+
+	for (tbl = hda_preset_tables; *tbl; tbl++) {
+		for (preset = *tbl; preset->id; preset++) {
+			u32 mask = preset->mask;
+			if (! mask)
+				mask = ~0;
+			if (preset->id == (codec->vendor_id & mask))
+				return preset;
+		}
+	}
+	return NULL;
+}
+
+/*
+ * snd_hda_get_codec_name - store the codec name
+ */
+void snd_hda_get_codec_name(struct hda_codec *codec,
+			    char *name, int namelen)
+{
+	const struct hda_vendor_id *c;
+	const char *vendor = NULL;
+	u16 vendor_id = codec->vendor_id >> 16;
+	char tmp[16];
+
+	for (c = hda_vendor_ids; c->id; c++) {
+		if (c->id == vendor_id) {
+			vendor = c->name;
+			break;
+		}
+	}
+	if (! vendor) {
+		sprintf(tmp, "Generic %04x", vendor_id);
+		vendor = tmp;
+	}
+	if (codec->preset && codec->preset->name)
+		snprintf(name, namelen, "%s %s", vendor, codec->preset->name);
+	else
+		snprintf(name, namelen, "%s ID %x", vendor, codec->vendor_id & 0xffff);
+}
+
+/*
+ * look for an AFG node
+ *
+ * return 0 if not found
+ */
+static int look_for_afg_node(struct hda_codec *codec)
+{
+	int i, total_nodes;
+	hda_nid_t nid;
+
+	total_nodes = snd_hda_get_sub_nodes(codec, AC_NODE_ROOT, &nid);
+	for (i = 0; i < total_nodes; i++, nid++) {
+		if ((snd_hda_param_read(codec, nid, AC_PAR_FUNCTION_TYPE) & 0xff) ==
+		    AC_GRP_AUDIO_FUNCTION)
+			return nid;
+	}
+	return 0;
+}
+
+/*
+ * codec destructor
+ */
+static void snd_hda_codec_free(struct hda_codec *codec)
+{
+	if (! codec)
+		return;
+	list_del(&codec->list);
+	codec->bus->caddr_tbl[codec->addr] = NULL;
+	if (codec->patch_ops.free)
+		codec->patch_ops.free(codec);
+	kfree(codec);
+}
+
+static void init_amp_hash(struct hda_codec *codec);
+
+/**
+ * snd_hda_codec_new - create a HDA codec
+ * @bus: the bus to assign
+ * @codec_addr: the codec address
+ * @codecp: the pointer to store the generated codec
+ *
+ * Returns 0 if successful, or a negative error code.
+ */
+int snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr,
+		      struct hda_codec **codecp)
+{
+	struct hda_codec *codec;
+	char component[13];
+	int err;
+
+	snd_assert(bus, return -EINVAL);
+	snd_assert(codec_addr <= HDA_MAX_CODEC_ADDRESS, return -EINVAL);
+
+	if (bus->caddr_tbl[codec_addr]) {
+		snd_printk(KERN_ERR "hda_codec: address 0x%x is already occupied\n", codec_addr);
+		return -EBUSY;
+	}
+
+	codec = kcalloc(1, sizeof(*codec), GFP_KERNEL);
+	if (codec == NULL) {
+		snd_printk(KERN_ERR "can't allocate struct hda_codec\n");
+		return -ENOMEM;
+	}
+
+	codec->bus = bus;
+	codec->addr = codec_addr;
+	init_MUTEX(&codec->spdif_mutex);
+	init_amp_hash(codec);
+
+	list_add_tail(&codec->list, &bus->codec_list);
+	bus->caddr_tbl[codec_addr] = codec;
+
+	codec->vendor_id = snd_hda_param_read(codec, AC_NODE_ROOT, AC_PAR_VENDOR_ID);
+	codec->subsystem_id = snd_hda_param_read(codec, AC_NODE_ROOT, AC_PAR_SUBSYSTEM_ID);
+	codec->revision_id = snd_hda_param_read(codec, AC_NODE_ROOT, AC_PAR_REV_ID);
+
+	/* FIXME: support for multiple AFGs? */
+	codec->afg = look_for_afg_node(codec);
+	if (! codec->afg) {
+		snd_printk(KERN_ERR "hda_codec: no AFG node found\n");
+		snd_hda_codec_free(codec);
+		return -ENODEV;
+	}
+
+	codec->preset = find_codec_preset(codec);
+	if (! *bus->card->mixername)
+		snd_hda_get_codec_name(codec, bus->card->mixername,
+				       sizeof(bus->card->mixername));
+
+	if (codec->preset && codec->preset->patch)
+		err = codec->preset->patch(codec);
+	else
+		err = snd_hda_parse_generic_codec(codec);
+	if (err < 0) {
+		snd_hda_codec_free(codec);
+		return err;
+	}
+
+	snd_hda_codec_proc_new(codec);
+
+	sprintf(component, "HDA:%08x", codec->vendor_id);
+	snd_component_add(codec->bus->card, component);
+
+	if (codecp)
+		*codecp = codec;
+	return 0;
+}
+
+/**
+ * snd_hda_codec_setup_stream - set up the codec for streaming
+ * @codec: the CODEC to set up
+ * @nid: the NID to set up
+ * @stream_tag: stream tag to pass, it's between 0x1 and 0xf.
+ * @channel_id: channel id to pass, zero based.
+ * @format: stream format.
+ */
+void snd_hda_codec_setup_stream(struct hda_codec *codec, hda_nid_t nid, u32 stream_tag,
+				int channel_id, int format)
+{
+	snd_printdd("hda_codec_setup_stream: NID=0x%x, stream=0x%x, channel=%d, format=0x%x\n",
+		    nid, stream_tag, channel_id, format);
+	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CHANNEL_STREAMID,
+			    (stream_tag << 4) | channel_id);
+	msleep(1);
+	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_STREAM_FORMAT, format);
+}
+
+
+/*
+ * amp access functions
+ */
+
+#define HDA_HASH_KEY(nid,dir,idx) (u32)((nid) + (idx) * 32 + (dir) * 64)
+#define INFO_AMP_CAPS	(1<<0)
+#define INFO_AMP_VOL	(1<<1)
+
+/* initialize the hash table */
+static void init_amp_hash(struct hda_codec *codec)
+{
+	memset(codec->amp_hash, 0xff, sizeof(codec->amp_hash));
+	codec->num_amp_entries = 0;
+}
+
+/* query the hash.  allocate an entry if not found. */
+static struct hda_amp_info *get_alloc_amp_hash(struct hda_codec *codec, u32 key)
+{
+	u16 idx = key % (u16)ARRAY_SIZE(codec->amp_hash);
+	u16 cur = codec->amp_hash[idx];
+	struct hda_amp_info *info;
+
+	while (cur != 0xffff) {
+		info = &codec->amp_info[cur];
+		if (info->key == key)
+			return info;
+		cur = info->next;
+	}
+
+	/* add a new hash entry */
+	if (codec->num_amp_entries >= ARRAY_SIZE(codec->amp_info)) {
+		snd_printk(KERN_ERR "hda_codec: Tooooo many amps!\n");
+		return NULL;
+	}
+	cur = codec->num_amp_entries++;
+	info = &codec->amp_info[cur];
+	info->key = key;
+	info->status = 0; /* not initialized yet */
+	info->next = codec->amp_hash[idx];
+	codec->amp_hash[idx] = cur;
+
+	return info;
+}
+
+/*
+ * query AMP capabilities for the given widget and direction
+ */
+static u32 query_amp_caps(struct hda_codec *codec, hda_nid_t nid, int direction)
+{
+	struct hda_amp_info *info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, direction, 0));
+
+	if (! info)
+		return 0;
+	if (! (info->status & INFO_AMP_CAPS)) {
+		info->amp_caps = snd_hda_param_read(codec, nid, direction == HDA_OUTPUT ?
+						    AC_PAR_AMP_OUT_CAP : AC_PAR_AMP_IN_CAP);
+		info->status |= INFO_AMP_CAPS;
+	}
+	return info->amp_caps;
+}
+
+/*
+ * read the current volume to info
+ * if the cache exists, read from the cache.
+ */
+static void get_vol_mute(struct hda_codec *codec, struct hda_amp_info *info,
+			 hda_nid_t nid, int ch, int direction, int index)
+{
+	u32 val, parm;
+
+	if (info->status & (INFO_AMP_VOL << ch))
+		return;
+
+	parm = ch ? AC_AMP_GET_RIGHT : AC_AMP_GET_LEFT;
+	parm |= direction == HDA_OUTPUT ? AC_AMP_GET_OUTPUT : AC_AMP_GET_INPUT;
+	parm |= index;
+	val = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_AMP_GAIN_MUTE, parm);
+	info->vol[ch] = val & 0xff;
+	info->status |= INFO_AMP_VOL << ch;
+}
+
+/*
+ * write the current volume in info to the h/w
+ */
+static void put_vol_mute(struct hda_codec *codec,
+			 hda_nid_t nid, int ch, int direction, int index, int val)
+{
+	u32 parm;
+
+	parm = ch ? AC_AMP_SET_RIGHT : AC_AMP_SET_LEFT;
+	parm |= direction == HDA_OUTPUT ? AC_AMP_SET_OUTPUT : AC_AMP_SET_INPUT;
+	parm |= index << AC_AMP_SET_INDEX_SHIFT;
+	parm |= val;
+	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, parm);
+}
+
+/*
+ * read/write AMP value.  The volume is between 0 to 0x7f, 0x80 = mute bit.
+ */
+int snd_hda_codec_amp_read(struct hda_codec *codec, hda_nid_t nid, int ch, int direction, int index)
+{
+	struct hda_amp_info *info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, direction, index));
+	if (! info)
+		return 0;
+	get_vol_mute(codec, info, nid, ch, direction, index);
+	return info->vol[ch];
+}
+
+int snd_hda_codec_amp_write(struct hda_codec *codec, hda_nid_t nid, int ch, int direction, int idx, int val)
+{
+	struct hda_amp_info *info = get_alloc_amp_hash(codec, HDA_HASH_KEY(nid, direction, idx));
+	if (! info)
+		return 0;
+	get_vol_mute(codec, info, nid, ch, direction, idx);
+	if (info->vol[ch] == val && ! codec->in_resume)
+		return 0;
+	put_vol_mute(codec, nid, ch, direction, idx, val);
+	info->vol[ch] = val;
+	return 1;
+}
+
+
+/*
+ * AMP control callbacks
+ */
+/* retrieve parameters from private_value */
+#define get_amp_nid(kc)		((kc)->private_value & 0xffff)
+#define get_amp_channels(kc)	(((kc)->private_value >> 16) & 0x3)
+#define get_amp_direction(kc)	(((kc)->private_value >> 18) & 0x1)
+#define get_amp_index(kc)	(((kc)->private_value >> 19) & 0xf)
+
+/* volume */
+int snd_hda_mixer_amp_volume_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+{
+	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+	u16 nid = get_amp_nid(kcontrol);
+	u8 chs = get_amp_channels(kcontrol);
+	int dir = get_amp_direction(kcontrol);
+	u32 caps;
+
+	caps = query_amp_caps(codec, nid, dir);
+	caps = (caps & AC_AMPCAP_NUM_STEPS) >> AC_AMPCAP_NUM_STEPS_SHIFT; /* num steps */
+	if (! caps) {
+		printk(KERN_WARNING "hda_codec: num_steps = 0 for NID=0x%x\n", nid);
+		return -EINVAL;
+	}
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+	uinfo->count = chs == 3 ? 2 : 1;
+	uinfo->value.integer.min = 0;
+	uinfo->value.integer.max = caps;
+	return 0;
+}
+
+int snd_hda_mixer_amp_volume_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+	hda_nid_t nid = get_amp_nid(kcontrol);
+	int chs = get_amp_channels(kcontrol);
+	int dir = get_amp_direction(kcontrol);
+	int idx = get_amp_index(kcontrol);
+	long *valp = ucontrol->value.integer.value;
+
+	if (chs & 1)
+		*valp++ = snd_hda_codec_amp_read(codec, nid, 0, dir, idx) & 0x7f;
+	if (chs & 2)
+		*valp = snd_hda_codec_amp_read(codec, nid, 1, dir, idx) & 0x7f;
+	return 0;
+}
+
+int snd_hda_mixer_amp_volume_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+	hda_nid_t nid = get_amp_nid(kcontrol);
+	int chs = get_amp_channels(kcontrol);
+	int dir = get_amp_direction(kcontrol);
+	int idx = get_amp_index(kcontrol);
+	int val;
+	long *valp = ucontrol->value.integer.value;
+	int change = 0;
+
+	if (chs & 1) {
+		val = *valp & 0x7f;
+		val |= snd_hda_codec_amp_read(codec, nid, 0, dir, idx) & 0x80;
+		change = snd_hda_codec_amp_write(codec, nid, 0, dir, idx, val);
+		valp++;
+	}
+	if (chs & 2) {
+		val = *valp & 0x7f;
+		val |= snd_hda_codec_amp_read(codec, nid, 1, dir, idx) & 0x80;
+		change |= snd_hda_codec_amp_write(codec, nid, 1, dir, idx, val);
+	}
+	return change;
+}
+
+/* switch */
+int snd_hda_mixer_amp_switch_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+{
+	int chs = get_amp_channels(kcontrol);
+
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
+	uinfo->count = chs == 3 ? 2 : 1;
+	uinfo->value.integer.min = 0;
+	uinfo->value.integer.max = 1;
+	return 0;
+}
+
+int snd_hda_mixer_amp_switch_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+	hda_nid_t nid = get_amp_nid(kcontrol);
+	int chs = get_amp_channels(kcontrol);
+	int dir = get_amp_direction(kcontrol);
+	int idx = get_amp_index(kcontrol);
+	long *valp = ucontrol->value.integer.value;
+
+	if (chs & 1)
+		*valp++ = (snd_hda_codec_amp_read(codec, nid, 0, dir, idx) & 0x80) ? 0 : 1;
+	if (chs & 2)
+		*valp = (snd_hda_codec_amp_read(codec, nid, 1, dir, idx) & 0x80) ? 0 : 1;
+	return 0;
+}
+
+int snd_hda_mixer_amp_switch_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+	hda_nid_t nid = get_amp_nid(kcontrol);
+	int chs = get_amp_channels(kcontrol);
+	int dir = get_amp_direction(kcontrol);
+	int idx = get_amp_index(kcontrol);
+	int val;
+	long *valp = ucontrol->value.integer.value;
+	int change = 0;
+
+	if (chs & 1) {
+		val = snd_hda_codec_amp_read(codec, nid, 0, dir, idx) & 0x7f;
+		val |= *valp ? 0 : 0x80;
+		change = snd_hda_codec_amp_write(codec, nid, 0, dir, idx, val);
+		valp++;
+	}
+	if (chs & 2) {
+		val = snd_hda_codec_amp_read(codec, nid, 1, dir, idx) & 0x7f;
+		val |= *valp ? 0 : 0x80;
+		change = snd_hda_codec_amp_write(codec, nid, 1, dir, idx, val);
+	}
+	return change;
+}
+
+/*
+ * SPDIF out controls
+ */
+
+static int snd_hda_spdif_mask_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+{
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
+	uinfo->count = 1;
+	return 0;
+}
+
+static int snd_hda_spdif_cmask_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+	ucontrol->value.iec958.status[0] = IEC958_AES0_PROFESSIONAL |
+					   IEC958_AES0_NONAUDIO |
+					   IEC958_AES0_CON_EMPHASIS_5015 |
+					   IEC958_AES0_CON_NOT_COPYRIGHT;
+	ucontrol->value.iec958.status[1] = IEC958_AES1_CON_CATEGORY |
+					   IEC958_AES1_CON_ORIGINAL;
+	return 0;
+}
+
+static int snd_hda_spdif_pmask_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+	ucontrol->value.iec958.status[0] = IEC958_AES0_PROFESSIONAL |
+					   IEC958_AES0_NONAUDIO |
+					   IEC958_AES0_PRO_EMPHASIS_5015;
+	return 0;
+}
+
+static int snd_hda_spdif_default_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+
+	ucontrol->value.iec958.status[0] = codec->spdif_status & 0xff;
+	ucontrol->value.iec958.status[1] = (codec->spdif_status >> 8) & 0xff;
+	ucontrol->value.iec958.status[2] = (codec->spdif_status >> 16) & 0xff;
+	ucontrol->value.iec958.status[3] = (codec->spdif_status >> 24) & 0xff;
+
+	return 0;
+}
+
+/* convert from SPDIF status bits to HDA SPDIF bits
+ * bit 0 (DigEn) is always set zero (to be filled later)
+ */
+static unsigned short convert_from_spdif_status(unsigned int sbits)
+{
+	unsigned short val = 0;
+
+	if (sbits & IEC958_AES0_PROFESSIONAL)
+		val |= 1 << 6;
+	if (sbits & IEC958_AES0_NONAUDIO)
+		val |= 1 << 5;
+	if (sbits & IEC958_AES0_PROFESSIONAL) {
+		if ((sbits & IEC958_AES0_PRO_EMPHASIS) == IEC958_AES0_PRO_EMPHASIS_5015)
+			val |= 1 << 3;
+	} else {
+		if ((sbits & IEC958_AES0_CON_EMPHASIS) == IEC958_AES0_CON_EMPHASIS_5015)
+			val |= 1 << 3;
+		if (! (sbits & IEC958_AES0_CON_NOT_COPYRIGHT))
+			val |= 1 << 4;
+		if (sbits & (IEC958_AES1_CON_ORIGINAL << 8))
+			val |= 1 << 7;
+		val |= sbits & (IEC958_AES1_CON_CATEGORY << 8);
+	}
+	return val;
+}
+
+/* convert to SPDIF status bits from HDA SPDIF bits
+ */
+static unsigned int convert_to_spdif_status(unsigned short val)
+{
+	unsigned int sbits = 0;
+
+	if (val & (1 << 5))
+		sbits |= IEC958_AES0_NONAUDIO;
+	if (val & (1 << 6))
+		sbits |= IEC958_AES0_PROFESSIONAL;
+	if (sbits & IEC958_AES0_PROFESSIONAL) {
+		if (sbits & (1 << 3))
+			sbits |= IEC958_AES0_PRO_EMPHASIS_5015;
+	} else {
+		if (val & (1 << 3))
+			sbits |= IEC958_AES0_CON_EMPHASIS_5015;
+		if (! (val & (1 << 4)))
+			sbits |= IEC958_AES0_CON_NOT_COPYRIGHT;
+		if (val & (1 << 7))
+			sbits |= (IEC958_AES1_CON_ORIGINAL << 8);
+		sbits |= val & (0x7f << 8);
+	}
+	return sbits;
+}
+
+static int snd_hda_spdif_default_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+	hda_nid_t nid = kcontrol->private_value;
+	unsigned short val;
+	int change;
+
+	down(&codec->spdif_mutex);
+	codec->spdif_status = ucontrol->value.iec958.status[0] |
+		((unsigned int)ucontrol->value.iec958.status[1] << 8) |
+		((unsigned int)ucontrol->value.iec958.status[2] << 16) |
+		((unsigned int)ucontrol->value.iec958.status[3] << 24);
+	val = convert_from_spdif_status(codec->spdif_status);
+	val |= codec->spdif_ctls & 1;
+	change = codec->spdif_ctls != val;
+	codec->spdif_ctls = val;
+
+	if (change || codec->in_resume) {
+		snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_1, val & 0xff);
+		snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_2, val >> 8);
+	}
+
+	up(&codec->spdif_mutex);
+	return change;
+}
+
+static int snd_hda_spdif_out_switch_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+{
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
+	uinfo->count = 1;
+	uinfo->value.integer.min = 0;
+	uinfo->value.integer.max = 1;
+	return 0;
+}
+
+static int snd_hda_spdif_out_switch_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+
+	ucontrol->value.integer.value[0] = codec->spdif_ctls & 1;
+	return 0;
+}
+
+static int snd_hda_spdif_out_switch_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+	hda_nid_t nid = kcontrol->private_value;
+	unsigned short val;
+	int change;
+
+	down(&codec->spdif_mutex);
+	val = codec->spdif_ctls & ~1;
+	if (ucontrol->value.integer.value[0])
+		val |= 1;
+	change = codec->spdif_ctls != val;
+	if (change || codec->in_resume) {
+		codec->spdif_ctls = val;
+		snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_1, val & 0xff);
+	}
+	up(&codec->spdif_mutex);
+	return change;
+}
+
+static snd_kcontrol_new_t dig_mixes[] = {
+	{
+		.access = SNDRV_CTL_ELEM_ACCESS_READ,
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,CON_MASK),
+		.info = snd_hda_spdif_mask_info,
+		.get = snd_hda_spdif_cmask_get,
+	},
+	{
+		.access = SNDRV_CTL_ELEM_ACCESS_READ,
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,PRO_MASK),
+		.info = snd_hda_spdif_mask_info,
+		.get = snd_hda_spdif_pmask_get,
+	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
+		.info = snd_hda_spdif_mask_info,
+		.get = snd_hda_spdif_default_get,
+		.put = snd_hda_spdif_default_put,
+	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,SWITCH),
+		.info = snd_hda_spdif_out_switch_info,
+		.get = snd_hda_spdif_out_switch_get,
+		.put = snd_hda_spdif_out_switch_put,
+	},
+	{ } /* end */
+};
+
+/**
+ * snd_hda_create_spdif_out_ctls - create Output SPDIF-related controls
+ * @codec: the HDA codec
+ * @nid: audio out widget NID
+ *
+ * Creates controls related with the SPDIF output.
+ * Called from each patch supporting the SPDIF out.
+ *
+ * Returns 0 if successful, or a negative error code.
+ */
+int snd_hda_create_spdif_out_ctls(struct hda_codec *codec, hda_nid_t nid)
+{
+	int err;
+	snd_kcontrol_t *kctl;
+	snd_kcontrol_new_t *dig_mix;
+
+	for (dig_mix = dig_mixes; dig_mix->name; dig_mix++) {
+		kctl = snd_ctl_new1(dig_mix, codec);
+		kctl->private_value = nid;
+		if ((err = snd_ctl_add(codec->bus->card, kctl)) < 0)
+			return err;
+	}
+	codec->spdif_ctls = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_DIGI_CONVERT, 0);
+	codec->spdif_status = convert_to_spdif_status(codec->spdif_ctls);
+	return 0;
+}
+
+/*
+ * SPDIF input
+ */
+
+#define snd_hda_spdif_in_switch_info	snd_hda_spdif_out_switch_info
+
+static int snd_hda_spdif_in_switch_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+
+	ucontrol->value.integer.value[0] = codec->spdif_in_enable;
+	return 0;
+}
+
+static int snd_hda_spdif_in_switch_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+	hda_nid_t nid = kcontrol->private_value;
+	unsigned int val = !!ucontrol->value.integer.value[0];
+	int change;
+
+	down(&codec->spdif_mutex);
+	change = codec->spdif_in_enable != val;
+	if (change || codec->in_resume) {
+		codec->spdif_in_enable = val;
+		snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_1, val);
+	}
+	up(&codec->spdif_mutex);
+	return change;
+}
+
+static int snd_hda_spdif_in_status_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+	hda_nid_t nid = kcontrol->private_value;
+	unsigned short val;
+	unsigned int sbits;
+
+	val = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_DIGI_CONVERT, 0);
+	sbits = convert_to_spdif_status(val);
+	ucontrol->value.iec958.status[0] = sbits;
+	ucontrol->value.iec958.status[1] = sbits >> 8;
+	ucontrol->value.iec958.status[2] = sbits >> 16;
+	ucontrol->value.iec958.status[3] = sbits >> 24;
+	return 0;
+}
+
+static snd_kcontrol_new_t dig_in_ctls[] = {
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH),
+		.info = snd_hda_spdif_in_switch_info,
+		.get = snd_hda_spdif_in_switch_get,
+		.put = snd_hda_spdif_in_switch_put,
+	},
+	{
+		.access = SNDRV_CTL_ELEM_ACCESS_READ,
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = SNDRV_CTL_NAME_IEC958("",CAPTURE,DEFAULT),
+		.info = snd_hda_spdif_mask_info,
+		.get = snd_hda_spdif_in_status_get,
+	},
+	{ } /* end */
+};
+
+/**
+ * snd_hda_create_spdif_in_ctls - create Input SPDIF-related controls
+ * @codec: the HDA codec
+ * @nid: audio in widget NID
+ *
+ * Creates controls related with the SPDIF input.
+ * Called from each patch supporting the SPDIF in.
+ *
+ * Returns 0 if successful, or a negative error code.
+ */
+int snd_hda_create_spdif_in_ctls(struct hda_codec *codec, hda_nid_t nid)
+{
+	int err;
+	snd_kcontrol_t *kctl;
+	snd_kcontrol_new_t *dig_mix;
+
+	for (dig_mix = dig_in_ctls; dig_mix->name; dig_mix++) {
+		kctl = snd_ctl_new1(dig_mix, codec);
+		kctl->private_value = nid;
+		if ((err = snd_ctl_add(codec->bus->card, kctl)) < 0)
+			return err;
+	}
+	codec->spdif_in_enable = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_DIGI_CONVERT, 0) & 1;
+	return 0;
+}
+
+
+/**
+ * snd_hda_build_controls - build mixer controls
+ * @bus: the BUS
+ *
+ * Creates mixer controls for each codec included in the bus.
+ *
+ * Returns 0 if successful, otherwise a negative error code.
+ */
+int snd_hda_build_controls(struct hda_bus *bus)
+{
+	struct list_head *p;
+
+	/* build controls */
+	list_for_each(p, &bus->codec_list) {
+		struct hda_codec *codec = list_entry(p, struct hda_codec, list);
+		int err;
+		if (! codec->patch_ops.build_controls)
+			continue;
+		err = codec->patch_ops.build_controls(codec);
+		if (err < 0)
+			return err;
+	}
+
+	/* initialize */
+	list_for_each(p, &bus->codec_list) {
+		struct hda_codec *codec = list_entry(p, struct hda_codec, list);
+		int err;
+		if (! codec->patch_ops.init)
+			continue;
+		err = codec->patch_ops.init(codec);
+		if (err < 0)
+			return err;
+	}
+	return 0;
+}
+
+
+/*
+ * stream formats
+ */
+static unsigned int rate_bits[][3] = {
+	/* rate in Hz, ALSA rate bitmask, HDA format value */
+	{ 8000, SNDRV_PCM_RATE_8000, 0x0500 }, /* 1/6 x 48 */
+	{ 11025, SNDRV_PCM_RATE_11025, 0x4300 }, /* 1/4 x 44 */
+	{ 16000, SNDRV_PCM_RATE_16000, 0x0200 }, /* 1/3 x 48 */
+	{ 22050, SNDRV_PCM_RATE_22050, 0x4100 }, /* 1/2 x 44 */
+	{ 32000, SNDRV_PCM_RATE_32000, 0x0a00 }, /* 2/3 x 48 */
+	{ 44100, SNDRV_PCM_RATE_44100, 0x4000 }, /* 44 */
+	{ 48000, SNDRV_PCM_RATE_48000, 0x0000 }, /* 48 */
+	{ 88200, SNDRV_PCM_RATE_88200, 0x4800 }, /* 2 x 44 */
+	{ 96000, SNDRV_PCM_RATE_96000, 0x0800 }, /* 2 x 48 */
+	{ 176400, SNDRV_PCM_RATE_176400, 0x5800 },/* 4 x 44 */
+	{ 192000, SNDRV_PCM_RATE_192000, 0x1800 }, /* 4 x 48 */
+	{ 0 }
+};
+
+/**
+ * snd_hda_calc_stream_format - calculate format bitset
+ * @rate: the sample rate
+ * @channels: the number of channels
+ * @format: the PCM format (SNDRV_PCM_FORMAT_XXX)
+ * @maxbps: the max. bps
+ *
+ * Calculate the format bitset from the given rate, channels and th PCM format.
+ *
+ * Return zero if invalid.
+ */
+unsigned int snd_hda_calc_stream_format(unsigned int rate,
+					unsigned int channels,
+					unsigned int format,
+					unsigned int maxbps)
+{
+	int i;
+	unsigned int val = 0;
+
+	for (i = 0; rate_bits[i][0]; i++)
+		if (rate_bits[i][0] == rate) {
+			val = rate_bits[i][2];
+			break;
+		}
+	if (! rate_bits[i][0]) {
+		snd_printdd("invalid rate %d\n", rate);
+		return 0;
+	}
+
+	if (channels == 0 || channels > 8) {
+		snd_printdd("invalid channels %d\n", channels);
+		return 0;
+	}
+	val |= channels - 1;
+
+	switch (snd_pcm_format_width(format)) {
+	case 8:  val |= 0x00; break;
+	case 16: val |= 0x10; break;
+	case 20:
+	case 24:
+	case 32:
+		if (maxbps >= 32)
+			val |= 0x40;
+		else if (maxbps >= 24)
+			val |= 0x30;
+		else
+			val |= 0x20;
+		break;
+	default:
+		snd_printdd("invalid format width %d\n", snd_pcm_format_width(format));
+		return 0;
+	}
+
+	return val;
+}
+
+/**
+ * snd_hda_query_supported_pcm - query the supported PCM rates and formats
+ * @codec: the HDA codec
+ * @nid: NID to query
+ * @ratesp: the pointer to store the detected rate bitflags
+ * @formatsp: the pointer to store the detected formats
+ * @bpsp: the pointer to store the detected format widths
+ *
+ * Queries the supported PCM rates and formats.  The NULL @ratesp, @formatsp
+ * or @bsps argument is ignored.
+ *
+ * Returns 0 if successful, otherwise a negative error code.
+ */
+int snd_hda_query_supported_pcm(struct hda_codec *codec, hda_nid_t nid,
+				u32 *ratesp, u64 *formatsp, unsigned int *bpsp)
+{
+	int i;
+	unsigned int val, streams;
+
+	val = 0;
+	if (nid != codec->afg &&
+	    snd_hda_param_read(codec, nid, AC_PAR_AUDIO_WIDGET_CAP) & AC_WCAP_FORMAT_OVRD) {
+		val = snd_hda_param_read(codec, nid, AC_PAR_PCM);
+		if (val == -1)
+			return -EIO;
+	}
+	if (! val)
+		val = snd_hda_param_read(codec, codec->afg, AC_PAR_PCM);
+
+	if (ratesp) {
+		u32 rates = 0;
+		for (i = 0; rate_bits[i][0]; i++) {
+			if (val & (1 << i))
+				rates |= rate_bits[i][1];
+		}
+		*ratesp = rates;
+	}
+
+	if (formatsp || bpsp) {
+		u64 formats = 0;
+		unsigned int bps;
+		unsigned int wcaps;
+
+		wcaps = snd_hda_param_read(codec, nid, AC_PAR_AUDIO_WIDGET_CAP);
+		streams = snd_hda_param_read(codec, nid, AC_PAR_STREAM);
+		if (streams == -1)
+			return -EIO;
+		if (! streams) {
+			streams = snd_hda_param_read(codec, codec->afg, AC_PAR_STREAM);
+			if (streams == -1)
+				return -EIO;
+		}
+
+		bps = 0;
+		if (streams & AC_SUPFMT_PCM) {
+			if (val & AC_SUPPCM_BITS_8) {
+				formats |= SNDRV_PCM_FMTBIT_U8;
+				bps = 8;
+			}
+			if (val & AC_SUPPCM_BITS_16) {
+				formats |= SNDRV_PCM_FMTBIT_S16_LE;
+				bps = 16;
+			}
+			if (wcaps & AC_WCAP_DIGITAL) {
+				if (val & AC_SUPPCM_BITS_32)
+					formats |= SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE;
+				if (val & (AC_SUPPCM_BITS_20|AC_SUPPCM_BITS_24))
+					formats |= SNDRV_PCM_FMTBIT_S32_LE;
+				if (val & AC_SUPPCM_BITS_24)
+					bps = 24;
+				else if (val & AC_SUPPCM_BITS_20)
+					bps = 20;
+			} else if (val & (AC_SUPPCM_BITS_20|AC_SUPPCM_BITS_24|AC_SUPPCM_BITS_32)) {
+				formats |= SNDRV_PCM_FMTBIT_S32_LE;
+				if (val & AC_SUPPCM_BITS_32)
+					bps = 32;
+				else if (val & AC_SUPPCM_BITS_20)
+					bps = 20;
+				else if (val & AC_SUPPCM_BITS_24)
+					bps = 24;
+			}
+		}
+		else if (streams == AC_SUPFMT_FLOAT32) { /* should be exclusive */
+			formats |= SNDRV_PCM_FMTBIT_FLOAT_LE;
+			bps = 32;
+		} else if (streams == AC_SUPFMT_AC3) { /* should be exclusive */
+			/* temporary hack: we have still no proper support
+			 * for the direct AC3 stream...
+			 */
+			formats |= SNDRV_PCM_FMTBIT_U8;
+			bps = 8;
+		}
+		if (formatsp)
+			*formatsp = formats;
+		if (bpsp)
+			*bpsp = bps;
+	}
+
+	return 0;
+}
+
+/**
+ * snd_hda_is_supported_format - check whether the given node supports the format val
+ *
+ * Returns 1 if supported, 0 if not.
+ */
+int snd_hda_is_supported_format(struct hda_codec *codec, hda_nid_t nid,
+				unsigned int format)
+{
+	int i;
+	unsigned int val = 0, rate, stream;
+
+	if (nid != codec->afg &&
+	    snd_hda_param_read(codec, nid, AC_PAR_AUDIO_WIDGET_CAP) & AC_WCAP_FORMAT_OVRD) {
+		val = snd_hda_param_read(codec, nid, AC_PAR_PCM);
+		if (val == -1)
+			return 0;
+	}
+	if (! val) {
+		val = snd_hda_param_read(codec, codec->afg, AC_PAR_PCM);
+		if (val == -1)
+			return 0;
+	}
+
+	rate = format & 0xff00;
+	for (i = 0; rate_bits[i][0]; i++)
+		if (rate_bits[i][2] == rate) {
+			if (val & (1 << i))
+				break;
+			return 0;
+		}
+	if (! rate_bits[i][0])
+		return 0;
+
+	stream = snd_hda_param_read(codec, nid, AC_PAR_STREAM);
+	if (stream == -1)
+		return 0;
+	if (! stream && nid != codec->afg)
+		stream = snd_hda_param_read(codec, codec->afg, AC_PAR_STREAM);
+	if (! stream || stream == -1)
+		return 0;
+
+	if (stream & AC_SUPFMT_PCM) {
+		switch (format & 0xf0) {
+		case 0x00:
+			if (! (val & AC_SUPPCM_BITS_8))
+				return 0;
+			break;
+		case 0x10:
+			if (! (val & AC_SUPPCM_BITS_16))
+				return 0;
+			break;
+		case 0x20:
+			if (! (val & AC_SUPPCM_BITS_20))
+				return 0;
+			break;
+		case 0x30:
+			if (! (val & AC_SUPPCM_BITS_24))
+				return 0;
+			break;
+		case 0x40:
+			if (! (val & AC_SUPPCM_BITS_32))
+				return 0;
+			break;
+		default:
+			return 0;
+		}
+	} else {
+		/* FIXME: check for float32 and AC3? */
+	}
+
+	return 1;
+}
+
+/*
+ * PCM stuff
+ */
+static int hda_pcm_default_open_close(struct hda_pcm_stream *hinfo,
+				      struct hda_codec *codec,
+				      snd_pcm_substream_t *substream)
+{
+	return 0;
+}
+
+static int hda_pcm_default_prepare(struct hda_pcm_stream *hinfo,
+				   struct hda_codec *codec,
+				   unsigned int stream_tag,
+				   unsigned int format,
+				   snd_pcm_substream_t *substream)
+{
+	snd_hda_codec_setup_stream(codec, hinfo->nid, stream_tag, 0, format);
+	return 0;
+}
+
+static int hda_pcm_default_cleanup(struct hda_pcm_stream *hinfo,
+				   struct hda_codec *codec,
+				   snd_pcm_substream_t *substream)
+{
+	snd_hda_codec_setup_stream(codec, hinfo->nid, 0, 0, 0);
+	return 0;
+}
+
+static int set_pcm_default_values(struct hda_codec *codec, struct hda_pcm_stream *info)
+{
+	if (info->nid) {
+		/* query support PCM information from the given NID */
+		if (! info->rates || ! info->formats)
+			snd_hda_query_supported_pcm(codec, info->nid,
+						    info->rates ? NULL : &info->rates,
+						    info->formats ? NULL : &info->formats,
+						    info->maxbps ? NULL : &info->maxbps);
+	}
+	if (info->ops.open == NULL)
+		info->ops.open = hda_pcm_default_open_close;
+	if (info->ops.close == NULL)
+		info->ops.close = hda_pcm_default_open_close;
+	if (info->ops.prepare == NULL) {
+		snd_assert(info->nid, return -EINVAL);
+		info->ops.prepare = hda_pcm_default_prepare;
+	}
+	if (info->ops.prepare == NULL) {
+		snd_assert(info->nid, return -EINVAL);
+		info->ops.prepare = hda_pcm_default_prepare;
+	}
+	if (info->ops.cleanup == NULL) {
+		snd_assert(info->nid, return -EINVAL);
+		info->ops.cleanup = hda_pcm_default_cleanup;
+	}
+	return 0;
+}
+
+/**
+ * snd_hda_build_pcms - build PCM information
+ * @bus: the BUS
+ *
+ * Create PCM information for each codec included in the bus.
+ *
+ * The build_pcms codec patch is requested to set up codec->num_pcms and
+ * codec->pcm_info properly.  The array is referred by the top-level driver
+ * to create its PCM instances.
+ * The allocated codec->pcm_info should be released in codec->patch_ops.free
+ * callback.
+ *
+ * At least, substreams, channels_min and channels_max must be filled for
+ * each stream.  substreams = 0 indicates that the stream doesn't exist.
+ * When rates and/or formats are zero, the supported values are queried
+ * from the given nid.  The nid is used also by the default ops.prepare
+ * and ops.cleanup callbacks.
+ *
+ * The driver needs to call ops.open in its open callback.  Similarly,
+ * ops.close is supposed to be called in the close callback.
+ * ops.prepare should be called in the prepare or hw_params callback
+ * with the proper parameters for set up.
+ * ops.cleanup should be called in hw_free for clean up of streams.
+ *
+ * This function returns 0 if successfull, or a negative error code.
+ */
+int snd_hda_build_pcms(struct hda_bus *bus)
+{
+	struct list_head *p;
+
+	list_for_each(p, &bus->codec_list) {
+		struct hda_codec *codec = list_entry(p, struct hda_codec, list);
+		unsigned int pcm, s;
+		int err;
+		if (! codec->patch_ops.build_pcms)
+			continue;
+		err = codec->patch_ops.build_pcms(codec);
+		if (err < 0)
+			return err;
+		for (pcm = 0; pcm < codec->num_pcms; pcm++) {
+			for (s = 0; s < 2; s++) {
+				struct hda_pcm_stream *info;
+				info = &codec->pcm_info[pcm].stream[s];
+				if (! info->substreams)
+					continue;
+				err = set_pcm_default_values(codec, info);
+				if (err < 0)
+					return err;
+			}
+		}
+	}
+	return 0;
+}
+
+
+/**
+ * snd_hda_check_board_config - compare the current codec with the config table
+ * @codec: the HDA codec
+ * @tbl: configuration table, terminated by null entries
+ *
+ * Compares the modelname or PCI subsystem id of the current codec with the
+ * given configuration table.  If a matching entry is found, returns its
+ * config value (supposed to be 0 or positive).
+ *
+ * If no entries are matching, the function returns a negative value.
+ */
+int snd_hda_check_board_config(struct hda_codec *codec, struct hda_board_config *tbl)
+{
+	struct hda_board_config *c;
+
+	if (codec->bus->modelname) {
+		for (c = tbl; c->modelname || c->pci_vendor; c++) {
+			if (c->modelname &&
+			    ! strcmp(codec->bus->modelname, c->modelname)) {
+				snd_printd(KERN_INFO "hda_codec: model '%s' is selected\n", c->modelname);
+				return c->config;
+			}
+		}
+	}
+
+	if (codec->bus->pci) {
+		u16 subsystem_vendor, subsystem_device;
+		pci_read_config_word(codec->bus->pci, PCI_SUBSYSTEM_VENDOR_ID, &subsystem_vendor);
+		pci_read_config_word(codec->bus->pci, PCI_SUBSYSTEM_ID, &subsystem_device);
+		for (c = tbl; c->modelname || c->pci_vendor; c++) {
+			if (c->pci_vendor == subsystem_vendor &&
+			    c->pci_device == subsystem_device)
+				return c->config;
+		}
+	}
+	return -1;
+}
+
+/**
+ * snd_hda_add_new_ctls - create controls from the array
+ * @codec: the HDA codec
+ * @knew: the array of snd_kcontrol_new_t
+ *
+ * This helper function creates and add new controls in the given array.
+ * The array must be terminated with an empty entry as terminator.
+ *
+ * Returns 0 if successful, or a negative error code.
+ */
+int snd_hda_add_new_ctls(struct hda_codec *codec, snd_kcontrol_new_t *knew)
+{
+	int err;
+
+	for (; knew->name; knew++) {
+		err = snd_ctl_add(codec->bus->card, snd_ctl_new1(knew, codec));
+		if (err < 0)
+			return err;
+	}
+	return 0;
+}
+
+
+/*
+ * input MUX helper
+ */
+int snd_hda_input_mux_info(const struct hda_input_mux *imux, snd_ctl_elem_info_t *uinfo)
+{
+	unsigned int index;
+
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+	uinfo->count = 1;
+	uinfo->value.enumerated.items = imux->num_items;
+	index = uinfo->value.enumerated.item;
+	if (index >= imux->num_items)
+		index = imux->num_items - 1;
+	strcpy(uinfo->value.enumerated.name, imux->items[index].label);
+	return 0;
+}
+
+int snd_hda_input_mux_put(struct hda_codec *codec, const struct hda_input_mux *imux,
+			  snd_ctl_elem_value_t *ucontrol, hda_nid_t nid,
+			  unsigned int *cur_val)
+{
+	unsigned int idx;
+
+	idx = ucontrol->value.enumerated.item[0];
+	if (idx >= imux->num_items)
+		idx = imux->num_items - 1;
+	if (*cur_val == idx && ! codec->in_resume)
+		return 0;
+	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL,
+			    imux->items[idx].index);
+	*cur_val = idx;
+	return 1;
+}
+
+
+/*
+ * Multi-channel / digital-out PCM helper functions
+ */
+
+/*
+ * open the digital out in the exclusive mode
+ */
+int snd_hda_multi_out_dig_open(struct hda_codec *codec, struct hda_multi_out *mout)
+{
+	down(&codec->spdif_mutex);
+	if (mout->dig_out_used) {
+		up(&codec->spdif_mutex);
+		return -EBUSY; /* already being used */
+	}
+	mout->dig_out_used = HDA_DIG_EXCLUSIVE;
+	up(&codec->spdif_mutex);
+	return 0;
+}
+
+/*
+ * release the digital out
+ */
+int snd_hda_multi_out_dig_close(struct hda_codec *codec, struct hda_multi_out *mout)
+{
+	down(&codec->spdif_mutex);
+	mout->dig_out_used = 0;
+	up(&codec->spdif_mutex);
+	return 0;
+}
+
+/*
+ * set up more restrictions for analog out
+ */
+int snd_hda_multi_out_analog_open(struct hda_codec *codec, struct hda_multi_out *mout,
+				  snd_pcm_substream_t *substream)
+{
+	substream->runtime->hw.channels_max = mout->max_channels;
+	return snd_pcm_hw_constraint_step(substream->runtime, 0,
+					  SNDRV_PCM_HW_PARAM_CHANNELS, 2);
+}
+
+/*
+ * set up the i/o for analog out
+ * when the digital out is available, copy the front out to digital out, too.
+ */
+int snd_hda_multi_out_analog_prepare(struct hda_codec *codec, struct hda_multi_out *mout,
+				     unsigned int stream_tag,
+				     unsigned int format,
+				     snd_pcm_substream_t *substream)
+{
+	hda_nid_t *nids = mout->dac_nids;
+	int chs = substream->runtime->channels;
+	int i;
+
+	down(&codec->spdif_mutex);
+	if (mout->dig_out_nid && mout->dig_out_used != HDA_DIG_EXCLUSIVE) {
+		if (chs == 2 &&
+		    snd_hda_is_supported_format(codec, mout->dig_out_nid, format) &&
+		    ! (codec->spdif_status & IEC958_AES0_NONAUDIO)) {
+			mout->dig_out_used = HDA_DIG_ANALOG_DUP;
+			/* setup digital receiver */
+			snd_hda_codec_setup_stream(codec, mout->dig_out_nid,
+						   stream_tag, 0, format);
+		} else {
+			mout->dig_out_used = 0;
+			snd_hda_codec_setup_stream(codec, mout->dig_out_nid, 0, 0, 0);
+		}
+	}
+	up(&codec->spdif_mutex);
+
+	/* front */
+	snd_hda_codec_setup_stream(codec, nids[HDA_FRONT], stream_tag, 0, format);
+	if (mout->hp_nid)
+		/* headphone out will just decode front left/right (stereo) */
+		snd_hda_codec_setup_stream(codec, mout->hp_nid, stream_tag, 0, format);
+	/* surrounds */
+	for (i = 1; i < mout->num_dacs; i++) {
+		if (i == HDA_REAR && chs == 2) /* copy front to rear */
+			snd_hda_codec_setup_stream(codec, nids[i], stream_tag, 0, format);
+		else if (chs >= (i + 1) * 2) /* independent out */
+			snd_hda_codec_setup_stream(codec, nids[i], stream_tag, i * 2,
+						   format);
+	}
+	return 0;
+}
+
+/*
+ * clean up the setting for analog out
+ */
+int snd_hda_multi_out_analog_cleanup(struct hda_codec *codec, struct hda_multi_out *mout)
+{
+	hda_nid_t *nids = mout->dac_nids;
+	int i;
+
+	for (i = 0; i < mout->num_dacs; i++)
+		snd_hda_codec_setup_stream(codec, nids[i], 0, 0, 0);
+	if (mout->hp_nid)
+		snd_hda_codec_setup_stream(codec, mout->hp_nid, 0, 0, 0);
+	down(&codec->spdif_mutex);
+	if (mout->dig_out_nid && mout->dig_out_used == HDA_DIG_ANALOG_DUP) {
+		snd_hda_codec_setup_stream(codec, mout->dig_out_nid, 0, 0, 0);
+		mout->dig_out_used = 0;
+	}
+	up(&codec->spdif_mutex);
+	return 0;
+}
+
+#ifdef CONFIG_PM
+/*
+ * power management
+ */
+
+/**
+ * snd_hda_suspend - suspend the codecs
+ * @bus: the HDA bus
+ * @state: suspsend state
+ *
+ * Returns 0 if successful.
+ */
+int snd_hda_suspend(struct hda_bus *bus, pm_message_t state)
+{
+	struct list_head *p;
+
+	/* FIXME: should handle power widget capabilities */
+	list_for_each(p, &bus->codec_list) {
+		struct hda_codec *codec = list_entry(p, struct hda_codec, list);
+		if (codec->patch_ops.suspend)
+			codec->patch_ops.suspend(codec, state);
+	}
+	return 0;
+}
+
+/**
+ * snd_hda_resume - resume the codecs
+ * @bus: the HDA bus
+ * @state: resume state
+ *
+ * Returns 0 if successful.
+ */
+int snd_hda_resume(struct hda_bus *bus)
+{
+	struct list_head *p;
+
+	list_for_each(p, &bus->codec_list) {
+		struct hda_codec *codec = list_entry(p, struct hda_codec, list);
+		if (codec->patch_ops.resume)
+			codec->patch_ops.resume(codec);
+	}
+	return 0;
+}
+
+/**
+ * snd_hda_resume_ctls - resume controls in the new control list
+ * @codec: the HDA codec
+ * @knew: the array of snd_kcontrol_new_t
+ *
+ * This function resumes the mixer controls in the snd_kcontrol_new_t array,
+ * originally for snd_hda_add_new_ctls().
+ * The array must be terminated with an empty entry as terminator.
+ */
+int snd_hda_resume_ctls(struct hda_codec *codec, snd_kcontrol_new_t *knew)
+{
+	snd_ctl_elem_value_t *val;
+
+	val = kmalloc(sizeof(*val), GFP_KERNEL);
+	if (! val)
+		return -ENOMEM;
+	codec->in_resume = 1;
+	for (; knew->name; knew++) {
+		int i, count;
+		count = knew->count ? knew->count : 1;
+		for (i = 0; i < count; i++) {
+			memset(val, 0, sizeof(*val));
+			val->id.iface = knew->iface;
+			val->id.device = knew->device;
+			val->id.subdevice = knew->subdevice;
+			strcpy(val->id.name, knew->name);
+			val->id.index = knew->index ? knew->index : i;
+			/* Assume that get callback reads only from cache,
+			 * not accessing to the real hardware
+			 */
+			if (snd_ctl_elem_read(codec->bus->card, val) < 0)
+				continue;
+			snd_ctl_elem_write(codec->bus->card, NULL, val);
+		}
+	}
+	codec->in_resume = 0;
+	kfree(val);
+	return 0;
+}
+
+/**
+ * snd_hda_resume_spdif_out - resume the digital out
+ * @codec: the HDA codec
+ */
+int snd_hda_resume_spdif_out(struct hda_codec *codec)
+{
+	return snd_hda_resume_ctls(codec, dig_mixes);
+}
+
+/**
+ * snd_hda_resume_spdif_in - resume the digital in
+ * @codec: the HDA codec
+ */
+int snd_hda_resume_spdif_in(struct hda_codec *codec)
+{
+	return snd_hda_resume_ctls(codec, dig_in_ctls);
+}
+#endif
+
+/*
+ * symbols exported for controller modules
+ */
+EXPORT_SYMBOL(snd_hda_codec_read);
+EXPORT_SYMBOL(snd_hda_codec_write);
+EXPORT_SYMBOL(snd_hda_sequence_write);
+EXPORT_SYMBOL(snd_hda_get_sub_nodes);
+EXPORT_SYMBOL(snd_hda_queue_unsol_event);
+EXPORT_SYMBOL(snd_hda_bus_new);
+EXPORT_SYMBOL(snd_hda_codec_new);
+EXPORT_SYMBOL(snd_hda_codec_setup_stream);
+EXPORT_SYMBOL(snd_hda_calc_stream_format);
+EXPORT_SYMBOL(snd_hda_build_pcms);
+EXPORT_SYMBOL(snd_hda_build_controls);
+#ifdef CONFIG_PM
+EXPORT_SYMBOL(snd_hda_suspend);
+EXPORT_SYMBOL(snd_hda_resume);
+#endif
+
+/*
+ *  INIT part
+ */
+
+static int __init alsa_hda_init(void)
+{
+	return 0;
+}
+
+static void __exit alsa_hda_exit(void)
+{
+}
+
+module_init(alsa_hda_init)
+module_exit(alsa_hda_exit)
diff -Nru a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/sound/pci/hda/hda_codec.h	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,604 @@
+/*
+ * Universal Interface for Intel High Definition Audio Codec
+ *
+ * Copyright (c) 2004 Takashi Iwai <tiwai@suse.de>
+ *
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under the terms of the GNU General Public License as published by the Free
+ *  Software Foundation; either version 2 of the License, or (at your option)
+ *  any later version.
+ *
+ *  This program is distributed in the hope that it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ *  more details.
+ *
+ *  You should have received a copy of the GNU General Public License along with
+ *  this program; if not, write to the Free Software Foundation, Inc., 59
+ *  Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#ifndef __SOUND_HDA_CODEC_H
+#define __SOUND_HDA_CODEC_H
+
+#include <sound/info.h>
+#include <sound/control.h>
+#include <sound/pcm.h>
+
+/*
+ * nodes
+ */
+#define	AC_NODE_ROOT		0x00
+
+/*
+ * function group types
+ */
+enum {
+	AC_GRP_AUDIO_FUNCTION = 0x01,
+	AC_GRP_MODEM_FUNCTION = 0x02,
+};
+	
+/*
+ * widget types
+ */
+enum {
+	AC_WID_AUD_OUT,		/* Audio Out */
+	AC_WID_AUD_IN,		/* Audio In */
+	AC_WID_AUD_MIX,		/* Audio Mixer */
+	AC_WID_AUD_SEL,		/* Audio Selector */
+	AC_WID_PIN,		/* Pin Complex */
+	AC_WID_POWER,		/* Power */
+	AC_WID_VOL_KNB,		/* Volume Knob */
+	AC_WID_BEEP,		/* Beep Generator */
+	AC_WID_VENDOR = 0x0f	/* Vendor specific */
+};
+
+/*
+ * GET verbs
+ */
+#define AC_VERB_GET_STREAM_FORMAT		0x0a00
+#define AC_VERB_GET_AMP_GAIN_MUTE		0x0b00
+#define AC_VERB_GET_PROC_COEF			0x0c00
+#define AC_VERB_GET_COEF_INDEX			0x0d00
+#define AC_VERB_PARAMETERS			0x0f00
+#define AC_VERB_GET_CONNECT_SEL			0x0f01
+#define AC_VERB_GET_CONNECT_LIST		0x0f02
+#define AC_VERB_GET_PROC_STATE			0x0f03
+#define AC_VERB_GET_SDI_SELECT			0x0f04
+#define AC_VERB_GET_POWER_STATE			0x0f05
+#define AC_VERB_GET_CONV			0x0f06
+#define AC_VERB_GET_PIN_WIDGET_CONTROL		0x0f07
+#define AC_VERB_GET_UNSOLICITED_RESPONSE	0x0f08
+#define AC_VERB_GET_PIN_SENSE			0x0f09
+#define AC_VERB_GET_BEEP_CONTROL		0x0f0a
+#define AC_VERB_GET_EAPD_BTLENABLE		0x0f0c
+#define AC_VERB_GET_DIGI_CONVERT		0x0f0d
+#define AC_VERB_GET_VOLUME_KNOB_CONTROL		0x0f0f
+/* f10-f1a: GPIO */
+#define AC_VERB_GET_CONFIG_DEFAULT		0x0f1c
+
+/*
+ * SET verbs
+ */
+#define AC_VERB_SET_STREAM_FORMAT		0x200
+#define AC_VERB_SET_AMP_GAIN_MUTE		0x300
+#define AC_VERB_SET_PROC_COEF			0x400
+#define AC_VERB_SET_COEF_INDEX			0x500
+#define AC_VERB_SET_CONNECT_SEL			0x701
+#define AC_VERB_SET_PROC_STATE			0x703
+#define AC_VERB_SET_SDI_SELECT			0x704
+#define AC_VERB_SET_POWER_STATE			0x705
+#define AC_VERB_SET_CHANNEL_STREAMID		0x706
+#define AC_VERB_SET_PIN_WIDGET_CONTROL		0x707
+#define AC_VERB_SET_UNSOLICITED_ENABLE		0x708
+#define AC_VERB_SET_PIN_SENSE			0x709
+#define AC_VERB_SET_BEEP_CONTROL		0x70a
+#define AC_VERB_SET_EAPD_BTLENALBE		0x70c
+#define AC_VERB_SET_DIGI_CONVERT_1		0x70d
+#define AC_VERB_SET_DIGI_CONVERT_2		0x70e
+#define AC_VERB_SET_VOLUME_KNOB_CONTROL		0x70f
+#define AC_VERB_SET_CONFIG_DEFAULT_BYTES_0	0x71c
+#define AC_VERB_SET_CONFIG_DEFAULT_BYTES_1	0x71d
+#define AC_VERB_SET_CONFIG_DEFAULT_BYTES_2	0x71e
+#define AC_VERB_SET_CONFIG_DEFAULT_BYTES_3	0x71f
+#define AC_VERB_SET_CODEC_RESET			0x7ff
+
+/*
+ * Parameter IDs
+ */
+#define AC_PAR_VENDOR_ID		0x00
+#define AC_PAR_SUBSYSTEM_ID		0x01
+#define AC_PAR_REV_ID			0x02
+#define AC_PAR_NODE_COUNT		0x04
+#define AC_PAR_FUNCTION_TYPE		0x05
+#define AC_PAR_AUDIO_FG_CAP		0x08
+#define AC_PAR_AUDIO_WIDGET_CAP		0x09
+#define AC_PAR_PCM			0x0a
+#define AC_PAR_STREAM			0x0b
+#define AC_PAR_PIN_CAP			0x0c
+#define AC_PAR_AMP_IN_CAP		0x0d
+#define AC_PAR_CONNLIST_LEN		0x0e
+#define AC_PAR_POWER_STATE		0x0f
+#define AC_PAR_PROC_CAP			0x10
+#define AC_PAR_GPIO_CAP			0x11
+#define AC_PAR_AMP_OUT_CAP		0x12
+
+/*
+ * AC_VERB_PARAMETERS results (32bit)
+ */
+
+/* Function Group Type */
+#define AC_FGT_TYPE			(0xff<<0)
+#define AC_FGT_TYPE_SHIFT		0
+#define AC_FGT_UNSOL_CAP		(1<<8)
+
+/* Audio Function Group Capabilities */
+#define AC_AFG_OUT_DELAY		(0xf<<0)
+#define AC_AFG_IN_DELAY			(0xf<<8)
+#define AC_AFG_BEEP_GEN			(1<<16)
+
+/* Audio Widget Capabilities */
+#define AC_WCAP_STEREO			(1<<0)	/* stereo I/O */
+#define AC_WCAP_IN_AMP			(1<<1)	/* AMP-in present */
+#define AC_WCAP_OUT_AMP			(1<<2)	/* AMP-out present */
+#define AC_WCAP_AMP_OVRD		(1<<3)	/* AMP-parameter override */
+#define AC_WCAP_FORMAT_OVRD		(1<<4)	/* format override */
+#define AC_WCAP_STRIPE			(1<<5)	/* stripe */
+#define AC_WCAP_PROC_WID		(1<<6)	/* Proc Widget */
+#define AC_WCAP_UNSOL_CAP		(1<<7)	/* Unsol capable */
+#define AC_WCAP_CONN_LIST		(1<<8)	/* connection list */
+#define AC_WCAP_DIGITAL			(1<<9)	/* digital I/O */
+#define AC_WCAP_POWER			(1<<10)	/* power control */
+#define AC_WCAP_LR_SWAP			(1<<11)	/* L/R swap */
+#define AC_WCAP_DELAY			(0xf<<16)
+#define AC_WCAP_DELAY_SHIFT		16
+#define AC_WCAP_TYPE			(0xf<<20)
+#define AC_WCAP_TYPE_SHIFT		20
+
+/* supported PCM rates and bits */
+#define AC_SUPPCM_RATES			(0xfff << 0)
+#define AC_SUPPCM_BITS_8		(1<<16)
+#define AC_SUPPCM_BITS_16		(1<<17)
+#define AC_SUPPCM_BITS_20		(1<<18)
+#define AC_SUPPCM_BITS_24		(1<<19)
+#define AC_SUPPCM_BITS_32		(1<<20)
+
+/* supported PCM stream format */
+#define AC_SUPFMT_PCM			(1<<0)
+#define AC_SUPFMT_FLOAT32		(1<<1)
+#define AC_SUPFMT_AC3			(1<<2)
+
+/* Pin widget capabilies */
+#define AC_PINCAP_IMP_SENSE		(1<<0)	/* impedance sense capable */
+#define AC_PINCAP_TRIG_REQ		(1<<1)	/* trigger required */
+#define AC_PINCAP_PRES_DETECT		(1<<2)	/* presence detect capable */
+#define AC_PINCAP_HP_DRV		(1<<3)	/* headphone drive capable */
+#define AC_PINCAP_OUT			(1<<4)	/* output capable */
+#define AC_PINCAP_IN			(1<<5)	/* input capable */
+#define AC_PINCAP_BALANCE		(1<<6)	/* balanced I/O capable */
+#define AC_PINCAP_VREF			(7<<8)
+#define AC_PINCAP_VREF_SHIFT		8
+#define AC_PINCAP_EAPD			(1<<16)	/* EAPD capable */
+/* Vref status (used in pin cap and pin ctl) */
+#define AC_PIN_VREF_HIZ			(1<<0)	/* Hi-Z */
+#define AC_PIN_VREF_50			(1<<1)	/* 50% */
+#define AC_PIN_VREF_GRD			(1<<2)	/* ground */
+#define AC_PIN_VREF_80			(1<<4)	/* 80% */
+#define AC_PIN_VREF_100			(1<<5)	/* 100% */
+
+
+/* Amplifier capabilities */
+#define AC_AMPCAP_OFFSET		(0x7f<<0)  /* 0dB offset */
+#define AC_AMPCAP_OFFSET_SHIFT		0
+#define AC_AMPCAP_NUM_STEPS		(0x7f<<8)  /* number of steps */
+#define AC_AMPCAP_NUM_STEPS_SHIFT	8
+#define AC_AMPCAP_STEP_SIZE		(0x7f<<16) /* step size 0-32dB in 0.25dB */
+#define AC_AMPCAP_STEP_SIZE_SHIFT	16
+#define AC_AMPCAP_MUTE			(1<<31)    /* mute capable */
+#define AC_AMPCAP_MUTE_SHIFT		31
+
+/* Connection list */
+#define AC_CLIST_LENGTH			(0x7f<<0)
+#define AC_CLIST_LONG			(1<<7)
+
+/* Supported power status */
+#define AC_PWRST_D0SUP			(1<<0)
+#define AC_PWRST_D1SUP			(1<<1)
+#define AC_PWRST_D2SUP			(1<<2)
+#define AC_PWRST_D3SUP			(1<<3)
+
+/* Processing capabilies */
+#define AC_PCAP_BENIGN			(1<<0)
+#define AC_PCAP_NUM_COEF		(0xff<<8)
+
+/* Volume knobs capabilities */
+#define AC_KNBCAP_NUM_STEPS		(0x7f<<0)
+#define AC_KNBCAP_DELTA			(1<<8)
+
+/*
+ * Control Parameters
+ */
+
+/* Amp gain/mute */
+#define AC_AMP_MUTE			(1<<8)
+#define AC_AMP_GAIN			(0x7f)
+#define AC_AMP_GET_INDEX		(0xf<<0)
+
+#define AC_AMP_GET_LEFT			(1<<13)
+#define AC_AMP_GET_RIGHT		(0<<13)
+#define AC_AMP_GET_OUTPUT		(1<<15)
+#define AC_AMP_GET_INPUT		(0<<15)
+
+#define AC_AMP_SET_INDEX		(0xf<<8)
+#define AC_AMP_SET_INDEX_SHIFT		8
+#define AC_AMP_SET_RIGHT		(1<<12)
+#define AC_AMP_SET_LEFT			(1<<13)
+#define AC_AMP_SET_INPUT		(1<<14)
+#define AC_AMP_SET_OUTPUT		(1<<15)
+
+/* DIGITAL1 bits */
+#define AC_DIG1_ENABLE			(1<<0)
+#define AC_DIG1_V			(1<<1)
+#define AC_DIG1_VCFG			(1<<2)
+#define AC_DIG1_EMPHASIS		(1<<3)
+#define AC_DIG1_COPYRIGHT		(1<<4)
+#define AC_DIG1_NONAUDIO		(1<<5)
+#define AC_DIG1_PROFESSIONAL		(1<<6)
+#define AC_DIG1_LEVEL			(1<<7)
+
+/* Pin widget control - 8bit */
+#define AC_PINCTL_VREFEN		(0x7<<0)
+#define AC_PINCTL_IN_EN			(1<<5)
+#define AC_PINCTL_OUT_EN		(1<<6)
+#define AC_PINCTL_HP_EN			(1<<7)
+
+/* configuration default - 32bit */
+#define AC_DEFCFG_SEQUENCE		(0xf<<0)
+#define AC_DEFCFG_DEF_ASSOC		(0xf<<4)
+#define AC_DEFCFG_MISC			(0xf<<8)
+#define AC_DEFCFG_COLOR			(0xf<<12)
+#define AC_DEFCFG_COLOR_SHIFT		12
+#define AC_DEFCFG_CONN_TYPE		(0xf<<16)
+#define AC_DEFCFG_CONN_TYPE_SHIFT	16
+#define AC_DEFCFG_DEVICE		(0xf<<20)
+#define AC_DEFCFG_DEVICE_SHIFT		20
+#define AC_DEFCFG_LOCATION		(0x3f<<24)
+#define AC_DEFCFG_LOCATION_SHIFT	24
+#define AC_DEFCFG_PORT_CONN		(0x3<<30)
+#define AC_DEFCFG_PORT_CONN_SHIFT	30
+
+/* device device types (0x0-0xf) */
+enum {
+	AC_JACK_LINE_OUT,
+	AC_JACK_SPEAKER,
+	AC_JACK_HP_OUT,
+	AC_JACK_CD,
+	AC_JACK_SPDIF_OUT,
+	AC_JACK_DIG_OTHER_OUT,
+	AC_JACK_MODEM_LINE_SIDE,
+	AC_JACK_MODEM_HAND_SIDE,
+	AC_JACK_LINE_IN,
+	AC_JACK_AUX,
+	AC_JACK_MIC_IN,
+	AC_JACK_TELEPHONY,
+	AC_JACK_SPDIF_IN,
+	AC_JACK_DIG_OTHER_IN,
+	AC_JACK_OTHER = 0xf,
+};
+
+/* jack connection types (0x0-0xf) */
+enum {
+	AC_JACK_CONN_UNKNOWN,
+	AC_JACK_CONN_1_8,
+	AC_JACK_CONN_1_4,
+	AC_JACK_CONN_ATAPI,
+	AC_JACK_CONN_RCA,
+	AC_JACK_CONN_OPTICAL,
+	AC_JACK_CONN_OTHER_DIGITAL,
+	AC_JACK_CONN_OTHER_ANALOG,
+	AC_JACK_CONN_DIN,
+	AC_JACK_CONN_XLR,
+	AC_JACK_CONN_RJ11,
+	AC_JACK_CONN_COMB,
+	AC_JACK_CONN_OTHER = 0xf,
+};
+
+/* jack colors (0x0-0xf) */
+enum {
+	AC_JACK_COLOR_UNKNOWN,
+	AC_JACK_COLOR_BLACK,
+	AC_JACK_COLOR_GREY,
+	AC_JACK_COLOR_BLUE,
+	AC_JACK_COLOR_GREEN,
+	AC_JACK_COLOR_RED,
+	AC_JACK_COLOR_ORANGE,
+	AC_JACK_COLOR_YELLOW,
+	AC_JACK_COLOR_PURPLE,
+	AC_JACK_COLOR_PINK,
+	AC_JACK_COLOR_WHITE = 0xe,
+	AC_JACK_COLOR_OTHER,
+};
+
+/* Jack location (0x0-0x3f) */
+/* common case */
+enum {
+	AC_JACK_LOC_NONE,
+	AC_JACK_LOC_REAR,
+	AC_JACK_LOC_FRONT,
+	AC_JACK_LOC_LEFT,
+	AC_JACK_LOC_RIGHT,
+	AC_JACK_LOC_TOP,
+	AC_JACK_LOC_BOTTOM,
+};
+/* bits 4-5 */
+enum {
+	AC_JACK_LOC_EXTERNAL = 0x00,
+	AC_JACK_LOC_INTERNAL = 0x10,
+	AC_JACK_LOC_SEPARATE = 0x20,
+	AC_JACK_LOC_OTHER    = 0x30,
+};
+enum {
+	/* external on primary chasis */
+	AC_JACK_LOC_REAR_PANEL = 0x07,
+	AC_JACK_LOC_DRIVE_BAY,
+	/* internal */
+	AC_JACK_LOC_RISER = 0x17,
+	AC_JACK_LOC_HDMI,
+	AC_JACK_LOC_ATAPI,
+	/* others */
+	AC_JACK_LOC_MOBILE_IN = 0x37,
+	AC_JACK_LOC_MOBILE_OUT,
+};
+
+/* Port connectivity (0-3) */
+enum {
+	AC_JACK_PORT_COMPLEX,
+	AC_JACK_PORT_NONE,
+	AC_JACK_PORT_FIXED,
+	AC_JACK_PORT_BOTH,
+};
+
+/* max. connections to a widget */
+#define HDA_MAX_CONNECTIONS	16
+
+/* max. codec address */
+#define HDA_MAX_CODEC_ADDRESS	0x0f
+
+/*
+ * Structures
+ */
+
+struct hda_bus;
+struct hda_codec;
+struct hda_pcm;
+struct hda_pcm_stream;
+struct hda_bus_unsolicited;
+
+/* NID type */
+typedef u16 hda_nid_t;
+
+/* bus operators */
+struct hda_bus_ops {
+	/* send a single command */
+	int (*command)(struct hda_codec *codec, hda_nid_t nid, int direct,
+		       unsigned int verb, unsigned int parm);
+	/* get a response from the last command */
+	unsigned int (*get_response)(struct hda_codec *codec);
+	/* free the private data */
+	void (*private_free)(struct hda_bus *);
+};
+
+/* template to pass to the bus constructor */
+struct hda_bus_template {
+	void *private_data;
+	struct pci_dev *pci;
+	const char *modelname;
+	struct hda_bus_ops ops;
+};
+
+/*
+ * codec bus
+ *
+ * each controller needs to creata a hda_bus to assign the accessor.
+ * A hda_bus contains several codecs in the list codec_list.
+ */
+struct hda_bus {
+	snd_card_t *card;
+
+	/* copied from template */
+	void *private_data;
+	struct pci_dev *pci;
+	const char *modelname;
+	struct hda_bus_ops ops;
+
+	/* codec linked list */
+	struct list_head codec_list;
+	struct hda_codec *caddr_tbl[HDA_MAX_CODEC_ADDRESS]; /* caddr -> codec */
+
+	struct semaphore cmd_mutex;
+
+	/* unsolicited event queue */
+	struct hda_bus_unsolicited *unsol;
+
+	snd_info_entry_t *proc;
+};
+
+/*
+ * codec preset
+ *
+ * Known codecs have the patch to build and set up the controls/PCMs
+ * better than the generic parser.
+ */
+struct hda_codec_preset {
+	unsigned int id;
+	unsigned int mask;
+	unsigned int subs;
+	unsigned int subs_mask;
+	unsigned int rev;
+	const char *name;
+	int (*patch)(struct hda_codec *codec);
+};
+	
+/* ops set by the preset patch */
+struct hda_codec_ops {
+	int (*build_controls)(struct hda_codec *codec);
+	int (*build_pcms)(struct hda_codec *codec);
+	int (*init)(struct hda_codec *codec);
+	void (*free)(struct hda_codec *codec);
+	void (*unsol_event)(struct hda_codec *codec, unsigned int res);
+#ifdef CONFIG_PM
+	int (*suspend)(struct hda_codec *codec, pm_message_t state);
+	int (*resume)(struct hda_codec *codec);
+#endif
+};
+
+/* record for amp information cache */
+struct hda_amp_info {
+	u32 key;		/* hash key */
+	u32 amp_caps;		/* amp capabilities */
+	u16 vol[2];		/* current volume & mute*/
+	u16 status;		/* update flag */
+	u16 next;		/* next link */
+};
+
+/* PCM callbacks */
+struct hda_pcm_ops {
+	int (*open)(struct hda_pcm_stream *info, struct hda_codec *codec,
+		    snd_pcm_substream_t *substream);
+	int (*close)(struct hda_pcm_stream *info, struct hda_codec *codec,
+		     snd_pcm_substream_t *substream);
+	int (*prepare)(struct hda_pcm_stream *info, struct hda_codec *codec,
+		       unsigned int stream_tag, unsigned int format,
+		       snd_pcm_substream_t *substream);
+	int (*cleanup)(struct hda_pcm_stream *info, struct hda_codec *codec,
+		       snd_pcm_substream_t *substream);
+};
+
+/* PCM information for each substream */
+struct hda_pcm_stream {
+	unsigned int substreams;	/* number of substreams, 0 = not exist */
+	unsigned int channels_min;	/* min. number of channels */
+	unsigned int channels_max;	/* max. number of channels */
+	hda_nid_t nid;	/* default NID to query rates/formats/bps, or set up */
+	u32 rates;	/* supported rates */
+	u64 formats;	/* supported formats (SNDRV_PCM_FMTBIT_) */
+	unsigned int maxbps;	/* supported max. bit per sample */
+	struct hda_pcm_ops ops;
+};
+
+/* for PCM creation */
+struct hda_pcm {
+	char *name;
+	struct hda_pcm_stream stream[2];
+};
+
+/* codec information */
+struct hda_codec {
+	struct hda_bus *bus;
+	unsigned int addr;	/* codec addr*/
+	struct list_head list;	/* list point */
+
+	hda_nid_t afg;	/* AFG node id */
+
+	/* ids */
+	u32 vendor_id;
+	u32 subsystem_id;
+	u32 revision_id;
+
+	/* detected preset */
+	const struct hda_codec_preset *preset;
+
+	/* set by patch */
+	struct hda_codec_ops patch_ops;
+
+	/* resume phase - all controls should update even if
+	 * the values are not changed
+	 */
+	unsigned int in_resume;
+
+	/* PCM to create, set by patch_ops.build_pcms callback */
+	unsigned int num_pcms;
+	struct hda_pcm *pcm_info;
+
+	/* codec specific info */
+	void *spec;
+
+	/* hash for amp access */
+	u16 amp_hash[32];
+	int num_amp_entries;
+	struct hda_amp_info amp_info[128]; /* big enough? */
+
+	struct semaphore spdif_mutex;
+	unsigned int spdif_status;	/* IEC958 status bits */
+	unsigned short spdif_ctls;	/* SPDIF control bits */
+	unsigned int spdif_in_enable;	/* SPDIF input enable? */
+};
+
+/* direction */
+enum {
+	HDA_INPUT, HDA_OUTPUT
+};
+
+
+/*
+ * constructors
+ */
+int snd_hda_bus_new(snd_card_t *card, const struct hda_bus_template *temp,
+		    struct hda_bus **busp);
+int snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr,
+		      struct hda_codec **codecp);
+
+/*
+ * low level functions
+ */
+unsigned int snd_hda_codec_read(struct hda_codec *codec, hda_nid_t nid, int direct,
+				unsigned int verb, unsigned int parm);
+int snd_hda_codec_write(struct hda_codec *codec, hda_nid_t nid, int direct,
+			unsigned int verb, unsigned int parm);
+#define snd_hda_param_read(codec, nid, param) snd_hda_codec_read(codec, nid, 0, AC_VERB_PARAMETERS, param)
+int snd_hda_get_sub_nodes(struct hda_codec *codec, hda_nid_t nid, hda_nid_t *start_id);
+int snd_hda_get_connections(struct hda_codec *codec, hda_nid_t nid, hda_nid_t *conn_list, int max_conns);
+
+struct hda_verb {
+	hda_nid_t nid;
+	u32 verb;
+	u32 param;
+};
+
+void snd_hda_sequence_write(struct hda_codec *codec, const struct hda_verb *seq);
+
+/* unsolicited event */
+int snd_hda_queue_unsol_event(struct hda_bus *bus, u32 res, u32 res_ex);
+
+/*
+ * Mixer
+ */
+int snd_hda_build_controls(struct hda_bus *bus);
+
+/*
+ * PCM
+ */
+int snd_hda_build_pcms(struct hda_bus *bus);
+void snd_hda_codec_setup_stream(struct hda_codec *codec, hda_nid_t nid, u32 stream_tag,
+				int channel_id, int format);
+unsigned int snd_hda_calc_stream_format(unsigned int rate, unsigned int channels,
+					unsigned int format, unsigned int maxbps);
+int snd_hda_query_supported_pcm(struct hda_codec *codec, hda_nid_t nid,
+				u32 *ratesp, u64 *formatsp, unsigned int *bpsp);
+int snd_hda_is_supported_format(struct hda_codec *codec, hda_nid_t nid,
+				unsigned int format);
+
+/*
+ * Misc
+ */
+void snd_hda_get_codec_name(struct hda_codec *codec, char *name, int namelen);
+
+/*
+ * power management
+ */
+#ifdef CONFIG_PM
+int snd_hda_suspend(struct hda_bus *bus, pm_message_t state);
+int snd_hda_resume(struct hda_bus *bus);
+#endif
+
+#endif /* __SOUND_HDA_CODEC_H */
diff -Nru a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/sound/pci/hda/hda_generic.c	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,909 @@
+/*
+ * Universal Interface for Intel High Definition Audio Codec
+ *
+ * Generic widget tree parser
+ *
+ * Copyright (c) 2004 Takashi Iwai <tiwai@suse.de>
+ *
+ *  This driver 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 driver is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ */
+
+#include <sound/driver.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/pci.h>
+#include <sound/core.h>
+#include "hda_codec.h"
+#include "hda_local.h"
+
+/* widget node for parsing */
+struct hda_gnode {
+	hda_nid_t nid;		/* NID of this widget */
+	unsigned short nconns;	/* number of input connections */
+	hda_nid_t conn_list[HDA_MAX_CONNECTIONS]; /* input connections */
+	unsigned int wid_caps;	/* widget capabilities */
+	unsigned char type;	/* widget type */
+	unsigned char pin_ctl;	/* pin controls */
+	unsigned char checked;	/* the flag indicates that the node is already parsed */
+	unsigned int pin_caps;	/* pin widget capabilities */
+	unsigned int def_cfg;	/* default configuration */
+	unsigned int amp_out_caps;	/* AMP out capabilities */
+	unsigned int amp_in_caps;	/* AMP in capabilities */
+	struct list_head list;
+};
+
+/* pathc-specific record */
+struct hda_gspec {
+	struct hda_gnode *dac_node;	/* DAC node */
+	struct hda_gnode *out_pin_node;	/* Output pin (Line-Out) node */
+	struct hda_gnode *pcm_vol_node;	/* Node for PCM volume */
+	unsigned int pcm_vol_index;	/* connection of PCM volume */
+
+	struct hda_gnode *adc_node;	/* ADC node */
+	struct hda_gnode *cap_vol_node;	/* Node for capture volume */
+	unsigned int cur_cap_src;	/* current capture source */
+	struct hda_input_mux input_mux;
+	char cap_labels[HDA_MAX_NUM_INPUTS][16];
+
+	unsigned int def_amp_in_caps;
+	unsigned int def_amp_out_caps;
+
+	struct hda_pcm pcm_rec;		/* PCM information */
+
+	struct list_head nid_list;	/* list of widgets */
+};
+
+/*
+ * retrieve the default device type from the default config value
+ */
+#define get_defcfg_type(node) (((node)->def_cfg & AC_DEFCFG_DEVICE) >> AC_DEFCFG_DEVICE_SHIFT)
+#define get_defcfg_location(node) (((node)->def_cfg & AC_DEFCFG_LOCATION) >> AC_DEFCFG_LOCATION_SHIFT)
+
+/*
+ * destructor
+ */
+static void snd_hda_generic_free(struct hda_codec *codec)
+{
+	struct hda_gspec *spec = codec->spec;
+	struct list_head *p, *n;
+
+	if (! spec)
+		return;
+	/* free all widgets */
+	list_for_each_safe(p, n, &spec->nid_list) {
+		struct hda_gnode *node = list_entry(p, struct hda_gnode, list);
+		kfree(node);
+	}
+	kfree(spec);
+}
+
+
+/*
+ * add a new widget node and read its attributes
+ */
+static int add_new_node(struct hda_codec *codec, struct hda_gspec *spec, hda_nid_t nid)
+{
+	struct hda_gnode *node;
+	int nconns;
+
+	node = kcalloc(1, sizeof(*node), GFP_KERNEL);
+	if (node == NULL)
+		return -ENOMEM;
+	node->nid = nid;
+	nconns = snd_hda_get_connections(codec, nid, node->conn_list, HDA_MAX_CONNECTIONS);
+	if (nconns < 0) {
+		kfree(node);
+		return nconns;
+	}
+	node->nconns = nconns;
+	node->wid_caps = snd_hda_param_read(codec, nid, AC_PAR_AUDIO_WIDGET_CAP);
+	node->type = (node->wid_caps & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT;
+
+	if (node->type == AC_WID_PIN) {
+		node->pin_caps = snd_hda_param_read(codec, node->nid, AC_PAR_PIN_CAP);
+		node->pin_ctl = snd_hda_codec_read(codec, node->nid, 0, AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
+		node->def_cfg = snd_hda_codec_read(codec, node->nid, 0, AC_VERB_GET_CONFIG_DEFAULT, 0);
+	}
+
+	if (node->wid_caps & AC_WCAP_OUT_AMP) {
+		if (node->wid_caps & AC_WCAP_AMP_OVRD)
+			node->amp_out_caps = snd_hda_param_read(codec, node->nid, AC_PAR_AMP_OUT_CAP);
+		if (! node->amp_out_caps)
+			node->amp_out_caps = spec->def_amp_out_caps;
+	}
+	if (node->wid_caps & AC_WCAP_IN_AMP) {
+		if (node->wid_caps & AC_WCAP_AMP_OVRD)
+			node->amp_in_caps = snd_hda_param_read(codec, node->nid, AC_PAR_AMP_IN_CAP);
+		if (! node->amp_in_caps)
+			node->amp_in_caps = spec->def_amp_in_caps;
+	}
+	list_add_tail(&node->list, &spec->nid_list);
+	return 0;
+}
+
+/*
+ * build the AFG subtree
+ */
+static int build_afg_tree(struct hda_codec *codec)
+{
+	struct hda_gspec *spec = codec->spec;
+	int i, nodes, err;
+	hda_nid_t nid;
+
+	snd_assert(spec, return -EINVAL);
+
+	spec->def_amp_out_caps = snd_hda_param_read(codec, codec->afg, AC_PAR_AMP_OUT_CAP);
+	spec->def_amp_in_caps = snd_hda_param_read(codec, codec->afg, AC_PAR_AMP_IN_CAP);
+
+	nodes = snd_hda_get_sub_nodes(codec, codec->afg, &nid);
+	if (! nid || nodes < 0) {
+		printk(KERN_ERR "Invalid AFG subtree\n");
+		return -EINVAL;
+	}
+
+	/* parse all nodes belonging to the AFG */
+	for (i = 0; i < nodes; i++, nid++) {
+		if ((err = add_new_node(codec, spec, nid)) < 0)
+			return err;
+	}
+
+	return 0;
+}
+
+
+/*
+ * look for the node record for the given NID
+ */
+/* FIXME: should avoid the braindead linear search */
+static struct hda_gnode *hda_get_node(struct hda_gspec *spec, hda_nid_t nid)
+{
+	struct list_head *p;
+	struct hda_gnode *node;
+
+	list_for_each(p, &spec->nid_list) {
+		node = list_entry(p, struct hda_gnode, list);
+		if (node->nid == nid)
+			return node;
+	}
+	return NULL;
+}
+
+/*
+ * unmute (and set max vol) the output amplifier
+ */
+static int unmute_output(struct hda_codec *codec, struct hda_gnode *node)
+{
+	unsigned int val, ofs;
+	snd_printdd("UNMUTE OUT: NID=0x%x\n", node->nid);
+	val = (node->amp_out_caps & AC_AMPCAP_NUM_STEPS) >> AC_AMPCAP_NUM_STEPS_SHIFT;
+	ofs = (node->amp_out_caps & AC_AMPCAP_OFFSET) >> AC_AMPCAP_OFFSET_SHIFT;
+	if (val >= ofs)
+		val -= ofs;
+	val |= AC_AMP_SET_LEFT | AC_AMP_SET_RIGHT;
+	val |= AC_AMP_SET_OUTPUT;
+	return snd_hda_codec_write(codec, node->nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, val);
+}
+
+/*
+ * unmute (and set max vol) the input amplifier
+ */
+static int unmute_input(struct hda_codec *codec, struct hda_gnode *node, unsigned int index)
+{
+	unsigned int val, ofs;
+	snd_printdd("UNMUTE IN: NID=0x%x IDX=0x%x\n", node->nid, index);
+	val = (node->amp_in_caps & AC_AMPCAP_NUM_STEPS) >> AC_AMPCAP_NUM_STEPS_SHIFT;
+	ofs = (node->amp_in_caps & AC_AMPCAP_OFFSET) >> AC_AMPCAP_OFFSET_SHIFT;
+	if (val >= ofs)
+		val -= ofs;
+	val |= AC_AMP_SET_LEFT | AC_AMP_SET_RIGHT;
+	val |= AC_AMP_SET_INPUT;
+	// awk added - fixed to allow unmuting of indexed amps
+	val |= index << AC_AMP_SET_INDEX_SHIFT;
+	return snd_hda_codec_write(codec, node->nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, val);
+}
+
+/*
+ * select the input connection of the given node.
+ */
+static int select_input_connection(struct hda_codec *codec, struct hda_gnode *node,
+				   unsigned int index)
+{
+	snd_printdd("CONNECT: NID=0x%x IDX=0x%x\n", node->nid, index);
+	return snd_hda_codec_write(codec, node->nid, 0, AC_VERB_SET_CONNECT_SEL, index);
+}
+
+/*
+ * clear checked flag of each node in the node list
+ */
+static void clear_check_flags(struct hda_gspec *spec)
+{
+	struct list_head *p;
+	struct hda_gnode *node;
+
+	list_for_each(p, &spec->nid_list) {
+		node = list_entry(p, struct hda_gnode, list);
+		node->checked = 0;
+	}
+}
+
+/*
+ * parse the output path recursively until reach to an audio output widget
+ *
+ * returns 0 if not found, 1 if found, or a negative error code.
+ */
+static int parse_output_path(struct hda_codec *codec, struct hda_gspec *spec,
+			     struct hda_gnode *node)
+{
+	int i, err;
+	struct hda_gnode *child;
+
+	if (node->checked)
+		return 0;
+
+	node->checked = 1;
+	if (node->type == AC_WID_AUD_OUT) {
+		if (node->wid_caps & AC_WCAP_DIGITAL) {
+			snd_printdd("Skip Digital OUT node %x\n", node->nid);
+			return 0;
+		}
+		snd_printdd("AUD_OUT found %x\n", node->nid);
+		if (spec->dac_node) {
+			/* already DAC node is assigned, just unmute & connect */
+			return node == spec->dac_node;
+		}
+		spec->dac_node = node;
+		if (node->wid_caps & AC_WCAP_OUT_AMP) {
+			spec->pcm_vol_node = node;
+			spec->pcm_vol_index = 0;
+		}
+		return 1; /* found */
+	}
+
+	for (i = 0; i < node->nconns; i++) {
+		child = hda_get_node(spec, node->conn_list[i]);
+		if (! child)
+			continue;
+		err = parse_output_path(codec, spec, child);
+		if (err < 0)
+			return err;
+		else if (err > 0) {
+			/* found one,
+			 * select the path, unmute both input and output
+			 */
+			if (node->nconns > 1)
+				select_input_connection(codec, node, i);
+			unmute_input(codec, node, i);
+			unmute_output(codec, node);
+			if (! spec->pcm_vol_node) {
+				if (node->wid_caps & AC_WCAP_IN_AMP) {
+					spec->pcm_vol_node = node;
+					spec->pcm_vol_index = i;
+				} else if (node->wid_caps & AC_WCAP_OUT_AMP) {
+					spec->pcm_vol_node = node;
+					spec->pcm_vol_index = 0;
+				}
+			}
+			return 1;
+		}
+	}
+	return 0;
+}
+
+/*
+ * Look for the output PIN widget with the given jack type
+ * and parse the output path to that PIN.
+ *
+ * Returns the PIN node when the path to DAC is established.
+ */
+static struct hda_gnode *parse_output_jack(struct hda_codec *codec,
+					   struct hda_gspec *spec,
+					   int jack_type)
+{
+	struct list_head *p;
+	struct hda_gnode *node;
+	int err;
+
+	list_for_each(p, &spec->nid_list) {
+		node = list_entry(p, struct hda_gnode, list);
+		if (node->type != AC_WID_PIN)
+			continue;
+		/* output capable? */
+		if (! (node->pin_caps & AC_PINCAP_OUT))
+			continue;
+		if (jack_type >= 0) {
+			if (jack_type != get_defcfg_type(node))
+				continue;
+			if (node->wid_caps & AC_WCAP_DIGITAL)
+				continue; /* skip SPDIF */
+		} else {
+			/* output as default? */
+			if (! (node->pin_ctl & AC_PINCTL_OUT_EN))
+				continue;
+		}
+		clear_check_flags(spec);
+		err = parse_output_path(codec, spec, node);
+		if (err < 0)
+			return NULL;
+		else if (err > 0) {
+			/* unmute the PIN output */
+			unmute_output(codec, node);
+			/* set PIN-Out enable */
+			snd_hda_codec_write(codec, node->nid, 0,
+					    AC_VERB_SET_PIN_WIDGET_CONTROL,
+					    AC_PINCTL_OUT_EN | AC_PINCTL_HP_EN);
+			return node;
+		}
+	}
+	return NULL;
+}
+
+
+/*
+ * parse outputs
+ */
+static int parse_output(struct hda_codec *codec)
+{
+	struct hda_gspec *spec = codec->spec;
+	struct hda_gnode *node;
+
+	/*
+	 * Look for the output PIN widget
+	 */
+	/* first, look for the line-out pin */
+	node = parse_output_jack(codec, spec, AC_JACK_LINE_OUT);
+	if (node) /* found, remember the PIN node */
+		spec->out_pin_node = node;
+	/* look for the HP-out pin */
+	node = parse_output_jack(codec, spec, AC_JACK_HP_OUT);
+	if (node) {
+		if (! spec->out_pin_node)
+			spec->out_pin_node = node;
+	}
+
+	if (! spec->out_pin_node) {
+		/* no line-out or HP pins found,
+		 * then choose for the first output pin
+		 */
+		spec->out_pin_node = parse_output_jack(codec, spec, -1);
+		if (! spec->out_pin_node)
+			snd_printd("hda_generic: no proper output path found\n");
+	}
+
+	return 0;
+}
+
+/*
+ * input MUX
+ */
+
+/* control callbacks */
+static int capture_source_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+{
+	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct hda_gspec *spec = codec->spec;
+	return snd_hda_input_mux_info(&spec->input_mux, uinfo);
+}
+
+static int capture_source_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct hda_gspec *spec = codec->spec;
+
+	ucontrol->value.enumerated.item[0] = spec->cur_cap_src;
+	return 0;
+}
+
+static int capture_source_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct hda_gspec *spec = codec->spec;
+	return snd_hda_input_mux_put(codec, &spec->input_mux, ucontrol,
+				     spec->adc_node->nid, &spec->cur_cap_src);
+}
+
+/*
+ * return the string name of the given input PIN widget
+ */
+static const char *get_input_type(struct hda_gnode *node, unsigned int *pinctl)
+{
+	unsigned int location = get_defcfg_location(node);
+	switch (get_defcfg_type(node)) {
+	case AC_JACK_LINE_IN:
+		if ((location & 0x0f) == AC_JACK_LOC_FRONT)
+			return "Front Line";
+		return "Line";
+	case AC_JACK_CD:
+		if (pinctl)
+			*pinctl |= AC_PIN_VREF_GRD;
+		return "CD";
+	case AC_JACK_AUX:
+		if ((location & 0x0f) == AC_JACK_LOC_FRONT)
+			return "Front Aux";
+		return "Aux";
+	case AC_JACK_MIC_IN:
+		if ((location & 0x0f) == AC_JACK_LOC_FRONT)
+			return "Front Mic";
+		return "Mic";
+	case AC_JACK_SPDIF_IN:
+		return "SPDIF";
+	case AC_JACK_DIG_OTHER_IN:
+		return "Digital";
+	}
+	return NULL;
+}
+
+/*
+ * parse the nodes recursively until reach to the input PIN
+ *
+ * returns 0 if not found, 1 if found, or a negative error code.
+ */
+static int parse_adc_sub_nodes(struct hda_codec *codec, struct hda_gspec *spec,
+			       struct hda_gnode *node)
+{
+	int i, err;
+	unsigned int pinctl;
+	char *label;
+	const char *type;
+
+	if (node->checked)
+		return 0;
+
+	node->checked = 1;
+	if (node->type != AC_WID_PIN) {
+		for (i = 0; i < node->nconns; i++) {
+			struct hda_gnode *child;
+			child = hda_get_node(spec, node->conn_list[i]);
+			if (! child)
+				continue;
+			err = parse_adc_sub_nodes(codec, spec, child);
+			if (err < 0)
+				return err;
+			if (err > 0) {
+				/* found one,
+				 * select the path, unmute both input and output
+				 */
+				if (node->nconns > 1)
+					select_input_connection(codec, node, i);
+				unmute_input(codec, node, i);
+				unmute_output(codec, node);
+				return err;
+			}
+		}
+		return 0;
+	}
+
+	/* input capable? */
+	if (! (node->pin_caps & AC_PINCAP_IN))
+		return 0;
+
+	if (node->wid_caps & AC_WCAP_DIGITAL)
+		return 0; /* skip SPDIF */
+
+	if (spec->input_mux.num_items >= HDA_MAX_NUM_INPUTS) {
+		snd_printk(KERN_ERR "hda_generic: Too many items for capture\n");
+		return -EINVAL;
+	}
+
+	pinctl = AC_PINCTL_IN_EN;
+	/* create a proper capture source label */
+	type = get_input_type(node, &pinctl);
+	if (! type) {
+		/* input as default? */
+		if (! (node->pin_ctl & AC_PINCTL_IN_EN))
+			return 0;
+		type = "Input";
+	}
+	label = spec->cap_labels[spec->input_mux.num_items];
+	strcpy(label, type);
+	spec->input_mux.items[spec->input_mux.num_items].label = label;
+
+	/* unmute the PIN external input */
+	unmute_input(codec, node, 0); /* index = 0? */
+	/* set PIN-In enable */
+	snd_hda_codec_write(codec, node->nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, pinctl);
+
+	return 1; /* found */
+}
+
+/*
+ * parse input
+ */
+static int parse_input_path(struct hda_codec *codec, struct hda_gnode *adc_node)
+{
+	struct hda_gspec *spec = codec->spec;
+	struct hda_gnode *node;
+	int i, err;
+
+	snd_printdd("AUD_IN = %x\n", adc_node->nid);
+	clear_check_flags(spec);
+
+	// awk added - fixed no recording due to muted widget
+	unmute_input(codec, adc_node, 0);
+	
+	/*
+	 * check each connection of the ADC
+	 * if it reaches to a proper input PIN, add the path as the
+	 * input path.
+	 */
+	for (i = 0; i < adc_node->nconns; i++) {
+		node = hda_get_node(spec, adc_node->conn_list[i]);
+		if (! node)
+			continue;
+		err = parse_adc_sub_nodes(codec, spec, node);
+		if (err < 0)
+			return err;
+		else if (err > 0) {
+			struct hda_input_mux_item *csrc = &spec->input_mux.items[spec->input_mux.num_items];
+			char *buf = spec->cap_labels[spec->input_mux.num_items];
+			int ocap;
+			for (ocap = 0; ocap < spec->input_mux.num_items; ocap++) {
+				if (! strcmp(buf, spec->cap_labels[ocap])) {
+					/* same label already exists,
+					 * put the index number to be unique
+					 */
+					sprintf(buf, "%s %d", spec->cap_labels[ocap],
+						spec->input_mux.num_items);
+				}
+			}
+			csrc->index = i;
+			spec->input_mux.num_items++;
+		}
+	}
+
+	if (! spec->input_mux.num_items)
+		return 0; /* no input path found... */
+
+	snd_printdd("[Capture Source] NID=0x%x, #SRC=%d\n", adc_node->nid, spec->input_mux.num_items);
+	for (i = 0; i < spec->input_mux.num_items; i++)
+		snd_printdd("  [%s] IDX=0x%x\n", spec->input_mux.items[i].label,
+			    spec->input_mux.items[i].index);
+
+	spec->adc_node = adc_node;
+	return 1;
+}
+
+/*
+ * parse input
+ */
+static int parse_input(struct hda_codec *codec)
+{
+	struct hda_gspec *spec = codec->spec;
+	struct list_head *p;
+	struct hda_gnode *node;
+	int err;
+
+	/*
+	 * At first we look for an audio input widget.
+	 * If it reaches to certain input PINs, we take it as the
+	 * input path.
+	 */
+	list_for_each(p, &spec->nid_list) {
+		node = list_entry(p, struct hda_gnode, list);
+		if (node->wid_caps & AC_WCAP_DIGITAL)
+			continue; /* skip SPDIF */
+		if (node->type == AC_WID_AUD_IN) {
+			err = parse_input_path(codec, node);
+			if (err < 0)
+				return err;
+			else if (err > 0)
+				return 0;
+		}
+	}
+	snd_printd("hda_generic: no proper input path found\n");
+	return 0;
+}
+
+/*
+ * create mixer controls if possible
+ */
+#define DIR_OUT		0x1
+#define DIR_IN		0x2
+
+static int create_mixer(struct hda_codec *codec, struct hda_gnode *node,
+			unsigned int index, const char *type, const char *dir_sfx)
+{
+	char name[32];
+	int err;
+	int created = 0;
+
+	if (type)
+		sprintf(name, "%s %s Switch", type, dir_sfx);
+	else
+		sprintf(name, "%s Switch", dir_sfx);
+	if ((node->wid_caps & AC_WCAP_IN_AMP) &&
+	    (node->amp_in_caps & AC_AMPCAP_MUTE)) {
+		snd_kcontrol_new_t knew =
+			HDA_CODEC_MUTE(name, node->nid, index, HDA_INPUT);
+		snd_printdd("[%s] NID=0x%x, DIR=IN, IDX=0x%x\n", name, node->nid, index);
+		if ((err = snd_ctl_add(codec->bus->card, snd_ctl_new1(&knew, codec))) < 0)
+			return err;
+		created = 1;
+	} else if ((node->wid_caps & AC_WCAP_OUT_AMP) &&
+		   (node->amp_out_caps & AC_AMPCAP_MUTE)) {
+		snd_kcontrol_new_t knew =
+			HDA_CODEC_MUTE(name, node->nid, 0, HDA_OUTPUT);
+		snd_printdd("[%s] NID=0x%x, DIR=OUT\n", name, node->nid);
+		if ((err = snd_ctl_add(codec->bus->card, snd_ctl_new1(&knew, codec))) < 0)
+			return err;
+		created = 1;
+	}
+
+	if (type)
+		sprintf(name, "%s %s Volume", type, dir_sfx);
+	else
+		sprintf(name, "%s Volume", dir_sfx);
+	if ((node->wid_caps & AC_WCAP_IN_AMP) &&
+	    (node->amp_in_caps & AC_AMPCAP_NUM_STEPS)) {
+		snd_kcontrol_new_t knew =
+			HDA_CODEC_VOLUME(name, node->nid, index, HDA_INPUT);
+		snd_printdd("[%s] NID=0x%x, DIR=IN, IDX=0x%x\n", name, node->nid, index);
+		if ((err = snd_ctl_add(codec->bus->card, snd_ctl_new1(&knew, codec))) < 0)
+			return err;
+		created = 1;
+	} else if ((node->wid_caps & AC_WCAP_OUT_AMP) &&
+		   (node->amp_out_caps & AC_AMPCAP_NUM_STEPS)) {
+		snd_kcontrol_new_t knew =
+			HDA_CODEC_VOLUME(name, node->nid, 0, HDA_OUTPUT);
+		snd_printdd("[%s] NID=0x%x, DIR=OUT\n", name, node->nid);
+		if ((err = snd_ctl_add(codec->bus->card, snd_ctl_new1(&knew, codec))) < 0)
+			return err;
+		created = 1;
+	}
+
+	return created;
+}
+
+/*
+ * check whether the controls with the given name and direction suffix already exist
+ */
+static int check_existing_control(struct hda_codec *codec, const char *type, const char *dir)
+{
+	snd_ctl_elem_id_t id;
+	memset(&id, 0, sizeof(id));
+	sprintf(id.name, "%s %s Volume", type, dir);
+	id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
+	if (snd_ctl_find_id(codec->bus->card, &id))
+		return 1;
+	sprintf(id.name, "%s %s Switch", type, dir);
+	id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
+	if (snd_ctl_find_id(codec->bus->card, &id))
+		return 1;
+	return 0;
+}
+
+/*
+ * build output mixer controls
+ */
+static int build_output_controls(struct hda_codec *codec)
+{
+	struct hda_gspec *spec = codec->spec;
+	int err;
+
+	err = create_mixer(codec, spec->pcm_vol_node, spec->pcm_vol_index,
+			   "PCM", "Playback");
+	if (err < 0)
+		return err;
+	return 0;
+}
+
+/* create capture volume/switch */
+static int build_input_controls(struct hda_codec *codec)
+{
+	struct hda_gspec *spec = codec->spec;
+	struct hda_gnode *adc_node = spec->adc_node;
+	int err;
+
+	if (! adc_node)
+		return 0; /* not found */
+
+	/* create capture volume and switch controls if the ADC has an amp */
+	err = create_mixer(codec, adc_node, 0, NULL, "Capture");
+
+	/* create input MUX if multiple sources are available */
+	if (spec->input_mux.num_items > 1) {
+		static snd_kcontrol_new_t cap_sel = {
+			.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+			.name = "Capture Source",
+			.info = capture_source_info,
+			.get = capture_source_get,
+			.put = capture_source_put,
+		};
+		if ((err = snd_ctl_add(codec->bus->card, snd_ctl_new1(&cap_sel, codec))) < 0)
+			return err;
+		spec->cur_cap_src = 0;
+		select_input_connection(codec, adc_node, spec->input_mux.items[0].index);
+	}
+	return 0;
+}
+
+
+/*
+ * parse the nodes recursively until reach to the output PIN.
+ *
+ * returns 0 - if not found,
+ *         1 - if found, but no mixer is created
+ *         2 - if found and mixer was already created, (just skip)
+ *         a negative error code
+ */
+static int parse_loopback_path(struct hda_codec *codec, struct hda_gspec *spec,
+			       struct hda_gnode *node, struct hda_gnode *dest_node,
+			       const char *type)
+{
+	int i, err;
+
+	if (node->checked)
+		return 0;
+
+	node->checked = 1;
+	if (node == dest_node) {
+		/* loopback connection found */
+		return 1;
+	}
+
+	for (i = 0; i < node->nconns; i++) {
+		struct hda_gnode *child = hda_get_node(spec, node->conn_list[i]);
+		if (! child)
+			continue;
+		err = parse_loopback_path(codec, spec, child, dest_node, type);
+		if (err < 0)
+			return err;
+		else if (err >= 1) {
+			if (err == 1) {
+				err = create_mixer(codec, node, i, type, "Playback");
+				if (err < 0)
+					return err;
+				if (err > 0)
+					return 2; /* ok, created */
+				/* not created, maybe in the lower path */
+				err = 1;
+			}
+			/* connect and unmute */
+			if (node->nconns > 1)
+				select_input_connection(codec, node, i);
+			unmute_input(codec, node, i);
+			unmute_output(codec, node);
+			return err;
+		}
+	}
+	return 0;
+}
+
+/*
+ * parse the tree and build the loopback controls
+ */
+static int build_loopback_controls(struct hda_codec *codec)
+{
+	struct hda_gspec *spec = codec->spec;
+	struct list_head *p;
+	struct hda_gnode *node;
+	int err;
+	const char *type;
+
+	if (! spec->out_pin_node)
+		return 0;
+
+	list_for_each(p, &spec->nid_list) {
+		node = list_entry(p, struct hda_gnode, list);
+		if (node->type != AC_WID_PIN)
+			continue;
+		/* input capable? */
+		if (! (node->pin_caps & AC_PINCAP_IN))
+			return 0;
+		type = get_input_type(node, NULL);
+		if (type) {
+			if (check_existing_control(codec, type, "Playback"))
+				continue;
+			clear_check_flags(spec);
+			err = parse_loopback_path(codec, spec, spec->out_pin_node,
+						  node, type);
+			if (err < 0)
+				return err;
+			if (! err)
+				continue;
+		}
+	}
+	return 0;
+}
+
+/*
+ * build mixer controls
+ */
+static int build_generic_controls(struct hda_codec *codec)
+{
+	int err;
+
+	if ((err = build_input_controls(codec)) < 0 ||
+	    (err = build_output_controls(codec)) < 0 ||
+	    (err = build_loopback_controls(codec)) < 0)
+		return err;
+
+	return 0;
+}
+
+/*
+ * PCM
+ */
+static struct hda_pcm_stream generic_pcm_playback = {
+	.substreams = 1,
+	.channels_min = 2,
+	.channels_max = 2,
+};
+
+static int build_generic_pcms(struct hda_codec *codec)
+{
+	struct hda_gspec *spec = codec->spec;
+	struct hda_pcm *info = &spec->pcm_rec;
+
+	if (! spec->dac_node && ! spec->adc_node) {
+		snd_printd("hda_generic: no PCM found\n");
+		return 0;
+	}
+
+	codec->num_pcms = 1;
+	codec->pcm_info = info;
+
+	info->name = "HDA Generic";
+	if (spec->dac_node) {
+		info->stream[0] = generic_pcm_playback;
+		info->stream[0].nid = spec->dac_node->nid;
+	}
+	if (spec->adc_node) {
+		info->stream[1] = generic_pcm_playback;
+		info->stream[1].nid = spec->adc_node->nid;
+	}
+
+	return 0;
+}
+
+
+/*
+ */
+static struct hda_codec_ops generic_patch_ops = {
+	.build_controls = build_generic_controls,
+	.build_pcms = build_generic_pcms,
+	.free = snd_hda_generic_free,
+};
+
+/*
+ * the generic parser
+ */
+int snd_hda_parse_generic_codec(struct hda_codec *codec)
+{
+	struct hda_gspec *spec;
+	int err;
+
+	spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
+	if (spec == NULL) {
+		printk(KERN_ERR "hda_generic: can't allocate spec\n");
+		return -ENOMEM;
+	}
+	codec->spec = spec;
+	INIT_LIST_HEAD(&spec->nid_list);
+
+	if ((err = build_afg_tree(codec)) < 0)
+		goto error;
+
+	if ((err = parse_input(codec)) < 0 ||
+	    (err = parse_output(codec)) < 0)
+		goto error;
+
+	codec->patch_ops = generic_patch_ops;
+
+	return 0;
+
+ error:
+	snd_hda_generic_free(codec);
+	return err;
+}
diff -Nru a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/sound/pci/hda/hda_intel.c	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,1449 @@
+/*
+ *
+ *  hda_intel.c - Implementation of primary alsa driver code base for Intel HD Audio.
+ *
+ *  Copyright(c) 2004 Intel Corporation. All rights reserved.
+ *
+ *  Copyright (c) 2004 Takashi Iwai <tiwai@suse.de>
+ *                     PeiSen Hou <pshou@realtek.com.tw>
+ *
+ *  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.
+ *
+ *  CONTACTS:
+ *
+ *  Matt Jared		matt.jared@intel.com
+ *  Andy Kopp		andy.kopp@intel.com
+ *  Dan Kogan		dan.d.kogan@intel.com
+ *
+ *  CHANGES:
+ *
+ *  2004.12.01	Major rewrite by tiwai, merged the work of pshou
+ * 
+ */
+
+#include <sound/driver.h>
+#include <asm/io.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/pci.h>
+#include <sound/core.h>
+#include <sound/initval.h>
+#include "hda_codec.h"
+
+
+static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
+static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
+static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
+static char *model[SNDRV_CARDS];
+
+module_param_array(index, int, NULL, 0444);
+MODULE_PARM_DESC(index, "Index value for Intel HD audio interface.");
+module_param_array(id, charp, NULL, 0444);
+MODULE_PARM_DESC(id, "ID string for Intel HD audio interface.");
+module_param_array(enable, bool, NULL, 0444);
+MODULE_PARM_DESC(enable, "Enable Intel HD audio interface.");
+module_param_array(model, charp, NULL, 0444);
+MODULE_PARM_DESC(model, "Use the given board model.");
+
+MODULE_LICENSE("GPL");
+MODULE_SUPPORTED_DEVICE("{{Intel, ICH6},"
+			 "{Intel, ICH6M},"
+			 "{Intel, ICH7}}");
+MODULE_DESCRIPTION("Intel HDA driver");
+
+#define SFX	"hda-intel: "
+
+/*
+ * registers
+ */
+#define ICH6_REG_GCAP			0x00
+#define ICH6_REG_VMIN			0x02
+#define ICH6_REG_VMAJ			0x03
+#define ICH6_REG_OUTPAY			0x04
+#define ICH6_REG_INPAY			0x06
+#define ICH6_REG_GCTL			0x08
+#define ICH6_REG_WAKEEN			0x0c
+#define ICH6_REG_STATESTS		0x0e
+#define ICH6_REG_GSTS			0x10
+#define ICH6_REG_INTCTL			0x20
+#define ICH6_REG_INTSTS			0x24
+#define ICH6_REG_WALCLK			0x30
+#define ICH6_REG_SYNC			0x34	
+#define ICH6_REG_CORBLBASE		0x40
+#define ICH6_REG_CORBUBASE		0x44
+#define ICH6_REG_CORBWP			0x48
+#define ICH6_REG_CORBRP			0x4A
+#define ICH6_REG_CORBCTL		0x4c
+#define ICH6_REG_CORBSTS		0x4d
+#define ICH6_REG_CORBSIZE		0x4e
+
+#define ICH6_REG_RIRBLBASE		0x50
+#define ICH6_REG_RIRBUBASE		0x54
+#define ICH6_REG_RIRBWP			0x58
+#define ICH6_REG_RINTCNT		0x5a
+#define ICH6_REG_RIRBCTL		0x5c
+#define ICH6_REG_RIRBSTS		0x5d
+#define ICH6_REG_RIRBSIZE		0x5e
+
+#define ICH6_REG_IC			0x60
+#define ICH6_REG_IR			0x64
+#define ICH6_REG_IRS			0x68
+#define   ICH6_IRS_VALID	(1<<1)
+#define   ICH6_IRS_BUSY		(1<<0)
+
+#define ICH6_REG_DPLBASE		0x70
+#define ICH6_REG_DPUBASE		0x74
+#define   ICH6_DPLBASE_ENABLE	0x1	/* Enable position buffer */
+
+/* SD offset: SDI0=0x80, SDI1=0xa0, ... SDO3=0x160 */
+enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 };
+
+/* stream register offsets from stream base */
+#define ICH6_REG_SD_CTL			0x00
+#define ICH6_REG_SD_STS			0x03
+#define ICH6_REG_SD_LPIB		0x04
+#define ICH6_REG_SD_CBL			0x08
+#define ICH6_REG_SD_LVI			0x0c
+#define ICH6_REG_SD_FIFOW		0x0e
+#define ICH6_REG_SD_FIFOSIZE		0x10
+#define ICH6_REG_SD_FORMAT		0x12
+#define ICH6_REG_SD_BDLPL		0x18
+#define ICH6_REG_SD_BDLPU		0x1c
+
+/* PCI space */
+#define ICH6_PCIREG_TCSEL	0x44
+
+/*
+ * other constants
+ */
+
+/* max number of SDs */
+#define MAX_ICH6_DEV		8
+/* max number of fragments - we may use more if allocating more pages for BDL */
+#define AZX_MAX_FRAG		(PAGE_SIZE / (MAX_ICH6_DEV * 16))
+/* max buffer size - no h/w limit, you can increase as you like */
+#define AZX_MAX_BUF_SIZE	(1024*1024*1024)
+/* max number of PCM devics per card */
+#define AZX_MAX_PCMS		8
+
+/* RIRB int mask: overrun[2], response[0] */
+#define RIRB_INT_RESPONSE	0x01
+#define RIRB_INT_OVERRUN	0x04
+#define RIRB_INT_MASK		0x05
+
+/* STATESTS int mask: SD2,SD1,SD0 */
+#define STATESTS_INT_MASK	0x07
+#define AZX_MAX_CODECS		3
+
+/* SD_CTL bits */
+#define SD_CTL_STREAM_RESET	0x01	/* stream reset bit */
+#define SD_CTL_DMA_START	0x02	/* stream DMA start bit */
+#define SD_CTL_STREAM_TAG_MASK	(0xf << 20)
+#define SD_CTL_STREAM_TAG_SHIFT	20
+
+/* SD_CTL and SD_STS */
+#define SD_INT_DESC_ERR		0x10	/* descriptor error interrupt */
+#define SD_INT_FIFO_ERR		0x08	/* FIFO error interrupt */
+#define SD_INT_COMPLETE		0x04	/* completion interrupt */
+#define SD_INT_MASK		(SD_INT_DESC_ERR|SD_INT_FIFO_ERR|SD_INT_COMPLETE)
+
+/* SD_STS */
+#define SD_STS_FIFO_READY	0x20	/* FIFO ready */
+
+/* INTCTL and INTSTS */
+#define ICH6_INT_ALL_STREAM	0xff		/* all stream interrupts */
+#define ICH6_INT_CTRL_EN	0x40000000	/* controller interrupt enable bit */
+#define ICH6_INT_GLOBAL_EN	0x80000000	/* global interrupt enable bit */
+
+/* GCTL reset bit */
+#define ICH6_GCTL_RESET		(1<<0)
+
+/* CORB/RIRB control, read/write pointer */
+#define ICH6_RBCTL_DMA_EN	0x02	/* enable DMA */
+#define ICH6_RBCTL_IRQ_EN	0x01	/* enable IRQ */
+#define ICH6_RBRWP_CLR		0x8000	/* read/write pointer clear */
+/* below are so far hardcoded - should read registers in future */
+#define ICH6_MAX_CORB_ENTRIES	256
+#define ICH6_MAX_RIRB_ENTRIES	256
+
+
+/*
+ * Use CORB/RIRB for communication from/to codecs.
+ * This is the way recommended by Intel (see below).
+ */
+#define USE_CORB_RIRB
+
+/*
+ * Define this if use the position buffer instead of reading SD_LPIB
+ * It's not used as default since SD_LPIB seems to give more accurate position
+ */
+/* #define USE_POSBUF */
+
+/*
+ */
+
+typedef struct snd_azx azx_t;
+typedef struct snd_azx_rb azx_rb_t;
+typedef struct snd_azx_dev azx_dev_t;
+
+struct snd_azx_dev {
+	u32 *bdl;			/* virtual address of the BDL */
+	dma_addr_t bdl_addr;		/* physical address of the BDL */
+	volatile u32 *posbuf;			/* position buffer pointer */
+
+	unsigned int bufsize;		/* size of the play buffer in bytes */
+	unsigned int fragsize;		/* size of each period in bytes */
+	unsigned int frags;		/* number for period in the play buffer */
+	unsigned int fifo_size;		/* FIFO size */
+
+	void __iomem *sd_addr;		/* stream descriptor pointer */
+
+	u32 sd_int_sta_mask;		/* stream int status mask */
+
+	/* pcm support */
+	snd_pcm_substream_t *substream;	/* assigned substream, set in PCM open */
+	unsigned int format_val;	/* format value to be set in the controller and the codec */
+	unsigned char stream_tag;	/* assigned stream */
+	unsigned char index;		/* stream index */
+
+	unsigned int opened: 1;
+	unsigned int running: 1;
+};
+
+/* CORB/RIRB */
+struct snd_azx_rb {
+	u32 *buf;		/* CORB/RIRB buffer
+				 * Each CORB entry is 4byte, RIRB is 8byte
+				 */
+	dma_addr_t addr;	/* physical address of CORB/RIRB buffer */
+	/* for RIRB */
+	unsigned short rp, wp;	/* read/write pointers */
+	int cmds;		/* number of pending requests */
+	u32 res;		/* last read value */
+};
+
+struct snd_azx {
+	snd_card_t *card;
+	struct pci_dev *pci;
+
+	/* pci resources */
+	unsigned long addr;
+	void __iomem *remap_addr;
+	int irq;
+
+	/* locks */
+	spinlock_t reg_lock;
+	struct semaphore open_mutex;
+
+	/* streams */
+	azx_dev_t azx_dev[MAX_ICH6_DEV];
+
+	/* PCM */
+	unsigned int pcm_devs;
+	snd_pcm_t *pcm[AZX_MAX_PCMS];
+
+	/* HD codec */
+	unsigned short codec_mask;
+	struct hda_bus *bus;
+
+	/* CORB/RIRB */
+	azx_rb_t corb;
+	azx_rb_t rirb;
+
+	/* BDL, CORB/RIRB and position buffers */
+	struct snd_dma_buffer bdl;
+	struct snd_dma_buffer rb;
+	struct snd_dma_buffer posbuf;
+};
+
+/*
+ * macros for easy use
+ */
+#define azx_writel(chip,reg,value) \
+	writel(value, (chip)->remap_addr + ICH6_REG_##reg)
+#define azx_readl(chip,reg) \
+	readl((chip)->remap_addr + ICH6_REG_##reg)
+#define azx_writew(chip,reg,value) \
+	writew(value, (chip)->remap_addr + ICH6_REG_##reg)
+#define azx_readw(chip,reg) \
+	readw((chip)->remap_addr + ICH6_REG_##reg)
+#define azx_writeb(chip,reg,value) \
+	writeb(value, (chip)->remap_addr + ICH6_REG_##reg)
+#define azx_readb(chip,reg) \
+	readb((chip)->remap_addr + ICH6_REG_##reg)
+
+#define azx_sd_writel(dev,reg,value) \
+	writel(value, (dev)->sd_addr + ICH6_REG_##reg)
+#define azx_sd_readl(dev,reg) \
+	readl((dev)->sd_addr + ICH6_REG_##reg)
+#define azx_sd_writew(dev,reg,value) \
+	writew(value, (dev)->sd_addr + ICH6_REG_##reg)
+#define azx_sd_readw(dev,reg) \
+	readw((dev)->sd_addr + ICH6_REG_##reg)
+#define azx_sd_writeb(dev,reg,value) \
+	writeb(value, (dev)->sd_addr + ICH6_REG_##reg)
+#define azx_sd_readb(dev,reg) \
+	readb((dev)->sd_addr + ICH6_REG_##reg)
+
+/* for pcm support */
+#define get_azx_dev(substream) (azx_dev_t*)(substream->runtime->private_data)
+
+/* Get the upper 32bit of the given dma_addr_t
+ * Compiler should optimize and eliminate the code if dma_addr_t is 32bit
+ */
+#define upper_32bit(addr) (sizeof(addr) > 4 ? (u32)((addr) >> 32) : (u32)0)
+
+
+/*
+ * Interface for HD codec
+ */
+
+#ifdef USE_CORB_RIRB
+/*
+ * CORB / RIRB interface
+ */
+static int azx_alloc_cmd_io(azx_t *chip)
+{
+	int err;
+
+	/* single page (at least 4096 bytes) must suffice for both ringbuffes */
+	err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(chip->pci),
+				  PAGE_SIZE, &chip->rb);
+	if (err < 0) {
+		snd_printk(KERN_ERR SFX "cannot allocate CORB/RIRB\n");
+		return err;
+	}
+	return 0;
+}
+
+static void azx_init_cmd_io(azx_t *chip)
+{
+	/* CORB set up */
+	chip->corb.addr = chip->rb.addr;
+	chip->corb.buf = (u32 *)chip->rb.area;
+	azx_writel(chip, CORBLBASE, (u32)chip->corb.addr);
+	azx_writel(chip, CORBUBASE, upper_32bit(chip->corb.addr));
+
+	/* set the corb write pointer to 0 */
+	azx_writew(chip, CORBWP, 0);
+	/* reset the corb hw read pointer */
+	azx_writew(chip, CORBRP, ICH6_RBRWP_CLR);
+	/* enable corb dma */
+	azx_writeb(chip, CORBCTL, ICH6_RBCTL_DMA_EN);
+
+	/* RIRB set up */
+	chip->rirb.addr = chip->rb.addr + 2048;
+	chip->rirb.buf = (u32 *)(chip->rb.area + 2048);
+	azx_writel(chip, RIRBLBASE, (u32)chip->rirb.addr);
+	azx_writel(chip, RIRBUBASE, upper_32bit(chip->rirb.addr));
+
+	/* reset the rirb hw write pointer */
+	azx_writew(chip, RIRBWP, ICH6_RBRWP_CLR);
+	/* set N=1, get RIRB response interrupt for new entry */
+	azx_writew(chip, RINTCNT, 1);
+	/* enable rirb dma and response irq */
+#ifdef USE_CORB_RIRB
+	azx_writeb(chip, RIRBCTL, ICH6_RBCTL_DMA_EN | ICH6_RBCTL_IRQ_EN);
+#else
+	azx_writeb(chip, RIRBCTL, ICH6_RBCTL_DMA_EN);
+#endif
+	chip->rirb.rp = chip->rirb.cmds = 0;
+}
+
+static void azx_free_cmd_io(azx_t *chip)
+{
+	/* disable ringbuffer DMAs */
+	azx_writeb(chip, RIRBCTL, 0);
+	azx_writeb(chip, CORBCTL, 0);
+}
+
+/* send a command */
+static int azx_send_cmd(struct hda_codec *codec, hda_nid_t nid, int direct,
+			unsigned int verb, unsigned int para)
+{
+	azx_t *chip = codec->bus->private_data;
+	unsigned int wp;
+	u32 val;
+
+	val = (u32)(codec->addr & 0x0f) << 28;
+	val |= (u32)direct << 27;
+	val |= (u32)nid << 20;
+	val |= verb << 8;
+	val |= para;
+
+	/* add command to corb */
+	wp = azx_readb(chip, CORBWP);
+	wp++;
+	wp %= ICH6_MAX_CORB_ENTRIES;
+
+	spin_lock_irq(&chip->reg_lock);
+	chip->rirb.cmds++;
+	chip->corb.buf[wp] = cpu_to_le32(val);
+	azx_writel(chip, CORBWP, wp);
+	spin_unlock_irq(&chip->reg_lock);
+
+	return 0;
+}
+
+#define ICH6_RIRB_EX_UNSOL_EV	(1<<4)
+
+/* retrieve RIRB entry - called from interrupt handler */
+static void azx_update_rirb(azx_t *chip)
+{
+	unsigned int rp, wp;
+	u32 res, res_ex;
+
+	wp = azx_readb(chip, RIRBWP);
+	if (wp == chip->rirb.wp)
+		return;
+	chip->rirb.wp = wp;
+		
+	while (chip->rirb.rp != wp) {
+		chip->rirb.rp++;
+		chip->rirb.rp %= ICH6_MAX_RIRB_ENTRIES;
+
+		rp = chip->rirb.rp << 1; /* an RIRB entry is 8-bytes */
+		res_ex = le32_to_cpu(chip->rirb.buf[rp + 1]);
+		res = le32_to_cpu(chip->rirb.buf[rp]);
+		if (res_ex & ICH6_RIRB_EX_UNSOL_EV)
+			snd_hda_queue_unsol_event(chip->bus, res, res_ex);
+		else if (chip->rirb.cmds) {
+			chip->rirb.cmds--;
+			chip->rirb.res = res;
+		}
+	}
+}
+
+/* receive a response */
+static unsigned int azx_get_response(struct hda_codec *codec)
+{
+	azx_t *chip = codec->bus->private_data;
+	int timeout = 50;
+
+	while (chip->rirb.cmds) {
+		if (! --timeout) {
+			snd_printk(KERN_ERR "azx_get_response timeout\n");
+			chip->rirb.rp = azx_readb(chip, RIRBWP);
+			chip->rirb.cmds = 0;
+			return -1;
+		}
+		msleep(1);
+	}
+	return chip->rirb.res; /* the last value */
+}
+
+#else
+/*
+ * Use the single immediate command instead of CORB/RIRB for simplicity
+ *
+ * Note: according to Intel, this is not preferred use.  The command was
+ *       intended for the BIOS only, and may get confused with unsolicited
+ *       responses.  So, we shouldn't use it for normal operation from the
+ *       driver.
+ *       I left the codes, however, for debugging/testing purposes.
+ */
+
+#define azx_alloc_cmd_io(chip)	0
+#define azx_init_cmd_io(chip)
+#define azx_free_cmd_io(chip)
+
+/* send a command */
+static int azx_send_cmd(struct hda_codec *codec, hda_nid_t nid, int direct,
+			unsigned int verb, unsigned int para)
+{
+	azx_t *chip = codec->bus->private_data;
+	u32 val;
+	int timeout = 50;
+
+	val = (u32)(codec->addr & 0x0f) << 28;
+	val |= (u32)direct << 27;
+	val |= (u32)nid << 20;
+	val |= verb << 8;
+	val |= para;
+
+	while (timeout--) {
+		/* check ICB busy bit */
+		if (! (azx_readw(chip, IRS) & ICH6_IRS_BUSY)) {
+			/* Clear IRV valid bit */
+			azx_writew(chip, IRS, azx_readw(chip, IRS) | ICH6_IRS_VALID);
+			azx_writel(chip, IC, val);
+			azx_writew(chip, IRS, azx_readw(chip, IRS) | ICH6_IRS_BUSY);
+			return 0;
+		}
+		udelay(1);
+	}
+	snd_printd(SFX "send_cmd timeout: IRS=0x%x, val=0x%x\n", azx_readw(chip, IRS), val);
+	return -EIO;
+}
+
+/* receive a response */
+static unsigned int azx_get_response(struct hda_codec *codec)
+{
+	azx_t *chip = codec->bus->private_data;
+	int timeout = 50;
+
+	while (timeout--) {
+		/* check IRV busy bit */
+		if (azx_readw(chip, IRS) & ICH6_IRS_VALID)
+			return azx_readl(chip, IR);
+		udelay(1);
+	}
+	snd_printd(SFX "get_response timeout: IRS=0x%x\n", azx_readw(chip, IRS));
+	return (unsigned int)-1;
+}
+
+#define azx_update_rirb(chip)
+
+#endif /* USE_CORB_RIRB */
+
+/* reset codec link */
+static int azx_reset(azx_t *chip)
+{
+	int count;
+
+	/* reset controller */
+	azx_writel(chip, GCTL, azx_readl(chip, GCTL) & ~ICH6_GCTL_RESET);
+
+	count = 50;
+	while (azx_readb(chip, GCTL) && --count)
+		msleep(1);
+
+	/* delay for >= 100us for codec PLL to settle per spec
+	 * Rev 0.9 section 5.5.1
+	 */
+	msleep(1);
+
+	/* Bring controller out of reset */
+	azx_writeb(chip, GCTL, azx_readb(chip, GCTL) | ICH6_GCTL_RESET);
+
+	count = 50;
+	while (! azx_readb(chip, GCTL) && --count)
+		msleep(1);
+
+	/* Brent Chartrand said to wait >= 540us for codecs to intialize */
+	msleep(1);
+
+	/* check to see if controller is ready */
+	if (! azx_readb(chip, GCTL)) {
+		snd_printd("azx_reset: controller not ready!\n");
+		return -EBUSY;
+	}
+
+	/* detect codecs */
+	if (! chip->codec_mask) {
+		chip->codec_mask = azx_readw(chip, STATESTS);
+		snd_printdd("codec_mask = 0x%x\n", chip->codec_mask);
+	}
+
+	return 0;
+}
+
+
+/*
+ * Lowlevel interface
+ */  
+
+/* enable interrupts */
+static void azx_int_enable(azx_t *chip)
+{
+	/* enable controller CIE and GIE */
+	azx_writel(chip, INTCTL, azx_readl(chip, INTCTL) |
+		   ICH6_INT_CTRL_EN | ICH6_INT_GLOBAL_EN);
+}
+
+/* disable interrupts */
+static void azx_int_disable(azx_t *chip)
+{
+	int i;
+
+	/* disable interrupts in stream descriptor */
+	for (i = 0; i < MAX_ICH6_DEV; i++) {
+		azx_dev_t *azx_dev = &chip->azx_dev[i];
+		azx_sd_writeb(azx_dev, SD_CTL,
+			      azx_sd_readb(azx_dev, SD_CTL) & ~SD_INT_MASK);
+	}
+
+	/* disable SIE for all streams */
+	azx_writeb(chip, INTCTL, 0);
+
+	/* disable controller CIE and GIE */
+	azx_writel(chip, INTCTL, azx_readl(chip, INTCTL) &
+		   ~(ICH6_INT_CTRL_EN | ICH6_INT_GLOBAL_EN));
+}
+
+/* clear interrupts */
+static void azx_int_clear(azx_t *chip)
+{
+	int i;
+
+	/* clear stream status */
+	for (i = 0; i < MAX_ICH6_DEV; i++) {
+		azx_dev_t *azx_dev = &chip->azx_dev[i];
+		azx_sd_writeb(azx_dev, SD_STS, SD_INT_MASK);
+	}
+
+	/* clear STATESTS */
+	azx_writeb(chip, STATESTS, STATESTS_INT_MASK);
+
+	/* clear rirb status */
+	azx_writeb(chip, RIRBSTS, RIRB_INT_MASK);
+
+	/* clear int status */
+	azx_writel(chip, INTSTS, ICH6_INT_CTRL_EN | ICH6_INT_ALL_STREAM);
+}
+
+/* start a stream */
+static void azx_stream_start(azx_t *chip, azx_dev_t *azx_dev)
+{
+	/* enable SIE */
+	azx_writeb(chip, INTCTL,
+		   azx_readb(chip, INTCTL) | (1 << azx_dev->index));
+	/* set DMA start and interrupt mask */
+	azx_sd_writeb(azx_dev, SD_CTL, azx_sd_readb(azx_dev, SD_CTL) |
+		      SD_CTL_DMA_START | SD_INT_MASK);
+}
+
+/* stop a stream */
+static void azx_stream_stop(azx_t *chip, azx_dev_t *azx_dev)
+{
+	/* stop DMA */
+	azx_sd_writeb(azx_dev, SD_CTL, azx_sd_readb(azx_dev, SD_CTL) &
+		      ~(SD_CTL_DMA_START | SD_INT_MASK));
+	azx_sd_writeb(azx_dev, SD_STS, SD_INT_MASK); /* to be sure */
+	/* disable SIE */
+	azx_writeb(chip, INTCTL,
+		   azx_readb(chip, INTCTL) & ~(1 << azx_dev->index));
+}
+
+
+/*
+ * initialize the chip
+ */
+static void azx_init_chip(azx_t *chip)
+{
+	unsigned char tcsel_reg;
+
+	/* Clear bits 0-2 of PCI register TCSEL (at offset 0x44)
+	 * TCSEL == Traffic Class Select Register, which sets PCI express QOS
+	 * Ensuring these bits are 0 clears playback static on some HD Audio codecs
+	 */
+	pci_read_config_byte (chip->pci, ICH6_PCIREG_TCSEL, &tcsel_reg);
+	pci_write_config_byte(chip->pci, ICH6_PCIREG_TCSEL, tcsel_reg & 0xf8);
+
+	/* reset controller */
+	azx_reset(chip);
+
+	/* initialize interrupts */
+	azx_int_clear(chip);
+	azx_int_enable(chip);
+
+	/* initialize the codec command I/O */
+	azx_init_cmd_io(chip);
+
+#ifdef USE_POSBUF
+	/* program the position buffer */
+	azx_writel(chip, DPLBASE, (u32)chip->posbuf.addr);
+	azx_writel(chip, DPUBASE, upper_32bit(chip->posbuf.addr));
+#endif
+}
+
+
+/*
+ * interrupt handler
+ */
+static irqreturn_t azx_interrupt(int irq, void* dev_id, struct pt_regs *regs)
+{
+	azx_t *chip = dev_id;
+	azx_dev_t *azx_dev;
+	u32 status;
+	int i;
+
+	spin_lock(&chip->reg_lock);
+
+	status = azx_readl(chip, INTSTS);
+	if (status == 0) {
+		spin_unlock(&chip->reg_lock);
+		return IRQ_NONE;
+	}
+	
+	for (i = 0; i < MAX_ICH6_DEV; i++) {
+		azx_dev = &chip->azx_dev[i];
+		if (status & azx_dev->sd_int_sta_mask) {
+			azx_sd_writeb(azx_dev, SD_STS, SD_INT_MASK);
+			if (azx_dev->substream && azx_dev->running) {
+				spin_unlock(&chip->reg_lock);
+				snd_pcm_period_elapsed(azx_dev->substream);
+				spin_lock(&chip->reg_lock);
+			}
+		}
+	}
+
+	/* clear rirb int */
+	status = azx_readb(chip, RIRBSTS);
+	if (status & RIRB_INT_MASK) {
+		if (status & RIRB_INT_RESPONSE)
+			azx_update_rirb(chip);
+		azx_writeb(chip, RIRBSTS, RIRB_INT_MASK);
+	}
+
+#if 0
+	/* clear state status int */
+	if (azx_readb(chip, STATESTS) & 0x04)
+		azx_writeb(chip, STATESTS, 0x04);
+#endif
+	spin_unlock(&chip->reg_lock);
+	
+	return IRQ_HANDLED;
+}
+
+
+/*
+ * set up BDL entries
+ */
+static void azx_setup_periods(azx_dev_t *azx_dev)
+{
+	u32 *bdl = azx_dev->bdl;
+	dma_addr_t dma_addr = azx_dev->substream->runtime->dma_addr;
+	int idx;
+
+	/* reset BDL address */
+	azx_sd_writel(azx_dev, SD_BDLPL, 0);
+	azx_sd_writel(azx_dev, SD_BDLPU, 0);
+
+	/* program the initial BDL entries */
+	for (idx = 0; idx < azx_dev->frags; idx++) {
+		unsigned int off = idx << 2; /* 4 dword step */
+		dma_addr_t addr = dma_addr + idx * azx_dev->fragsize;
+		/* program the address field of the BDL entry */
+		bdl[off] = cpu_to_le32((u32)addr);
+		bdl[off+1] = cpu_to_le32(upper_32bit(addr));
+
+		/* program the size field of the BDL entry */
+		bdl[off+2] = cpu_to_le32(azx_dev->fragsize);
+
+		/* program the IOC to enable interrupt when buffer completes */
+		bdl[off+3] = cpu_to_le32(0x01);
+	}
+}
+
+/*
+ * set up the SD for streaming
+ */
+static int azx_setup_controller(azx_t *chip, azx_dev_t *azx_dev)
+{
+	unsigned char val;
+	int timeout;
+
+	/* make sure the run bit is zero for SD */
+	azx_sd_writeb(azx_dev, SD_CTL, azx_sd_readb(azx_dev, SD_CTL) & ~SD_CTL_DMA_START);
+	/* reset stream */
+	azx_sd_writeb(azx_dev, SD_CTL, azx_sd_readb(azx_dev, SD_CTL) | SD_CTL_STREAM_RESET);
+	udelay(3);
+	timeout = 300;
+	while (!((val = azx_sd_readb(azx_dev, SD_CTL)) & SD_CTL_STREAM_RESET) &&
+	       --timeout)
+		;
+	val &= ~SD_CTL_STREAM_RESET;
+	azx_sd_writeb(azx_dev, SD_CTL, val);
+	udelay(3);
+
+	timeout = 300;
+	/* waiting for hardware to report that the stream is out of reset */
+	while (((val = azx_sd_readb(azx_dev, SD_CTL)) & SD_CTL_STREAM_RESET) &&
+	       --timeout)
+		;
+
+	/* program the stream_tag */
+	azx_sd_writel(azx_dev, SD_CTL,
+		      (azx_sd_readl(azx_dev, SD_CTL) & ~SD_CTL_STREAM_TAG_MASK) |
+		      (azx_dev->stream_tag << SD_CTL_STREAM_TAG_SHIFT));
+
+	/* program the length of samples in cyclic buffer */
+	azx_sd_writel(azx_dev, SD_CBL, azx_dev->bufsize);
+
+	/* program the stream format */
+	/* this value needs to be the same as the one programmed */
+	azx_sd_writew(azx_dev, SD_FORMAT, azx_dev->format_val);
+
+	/* program the stream LVI (last valid index) of the BDL */
+	azx_sd_writew(azx_dev, SD_LVI, azx_dev->frags - 1);
+
+	/* program the BDL address */
+	/* lower BDL address */
+	azx_sd_writel(azx_dev, SD_BDLPL, (u32)azx_dev->bdl_addr);
+	/* upper BDL address */
+	azx_sd_writel(azx_dev, SD_BDLPU, upper_32bit(azx_dev->bdl_addr));
+
+#ifdef USE_POSBUF
+	/* enable the position buffer */
+	if (! (azx_readl(chip, DPLBASE) & ICH6_DPLBASE_ENABLE))
+		azx_writel(chip, DPLBASE, (u32)chip->posbuf.addr | ICH6_DPLBASE_ENABLE);
+#endif
+	/* set the interrupt enable bits in the descriptor control register */
+	azx_sd_writel(azx_dev, SD_CTL, azx_sd_readl(azx_dev, SD_CTL) | SD_INT_MASK);
+
+	return 0;
+}
+
+
+/*
+ * Codec initialization
+ */
+
+static int __devinit azx_codec_create(azx_t *chip, const char *model)
+{
+	struct hda_bus_template bus_temp;
+	int c, codecs, err;
+
+	memset(&bus_temp, 0, sizeof(bus_temp));
+	bus_temp.private_data = chip;
+	bus_temp.modelname = model;
+	bus_temp.pci = chip->pci;
+	bus_temp.ops.command = azx_send_cmd;
+	bus_temp.ops.get_response = azx_get_response;
+
+	if ((err = snd_hda_bus_new(chip->card, &bus_temp, &chip->bus)) < 0)
+		return err;
+
+	codecs = 0;
+	for (c = 0; c < AZX_MAX_CODECS; c++) {
+		if (chip->codec_mask & (1 << c)) {
+			err = snd_hda_codec_new(chip->bus, c, NULL);
+			if (err < 0)
+				continue;
+			codecs++;
+		}
+	}
+	if (! codecs) {
+		snd_printk(KERN_ERR SFX "no codecs initialized\n");
+		return -ENXIO;
+	}
+
+	return 0;
+}
+
+
+/*
+ * PCM support
+ */
+
+/* assign a stream for the PCM */
+static inline azx_dev_t *azx_assign_device(azx_t *chip, int stream)
+{
+	int dev, i;
+	dev = stream == SNDRV_PCM_STREAM_PLAYBACK ? 4 : 0;
+	for (i = 0; i < 4; i++, dev++)
+		if (! chip->azx_dev[dev].opened) {
+			chip->azx_dev[dev].opened = 1;
+			return &chip->azx_dev[dev];
+		}
+	return NULL;
+}
+
+/* release the assigned stream */
+static inline void azx_release_device(azx_dev_t *azx_dev)
+{
+	azx_dev->opened = 0;
+}
+
+static snd_pcm_hardware_t azx_pcm_hw = {
+	.info =			(SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
+				 SNDRV_PCM_INFO_BLOCK_TRANSFER |
+				 SNDRV_PCM_INFO_MMAP_VALID |
+				 SNDRV_PCM_INFO_PAUSE |
+				 SNDRV_PCM_INFO_RESUME),
+	.formats =		SNDRV_PCM_FMTBIT_S16_LE,
+	.rates =		SNDRV_PCM_RATE_48000,
+	.rate_min =		48000,
+	.rate_max =		48000,
+	.channels_min =		2,
+	.channels_max =		2,
+	.buffer_bytes_max =	AZX_MAX_BUF_SIZE,
+	.period_bytes_min =	128,
+	.period_bytes_max =	AZX_MAX_BUF_SIZE / 2,
+	.periods_min =		2,
+	.periods_max =		AZX_MAX_FRAG,
+	.fifo_size =		0,
+};
+
+struct azx_pcm {
+	azx_t *chip;
+	struct hda_codec *codec;
+	struct hda_pcm_stream *hinfo[2];
+};
+
+static int azx_pcm_open(snd_pcm_substream_t *substream)
+{
+	struct azx_pcm *apcm = snd_pcm_substream_chip(substream);
+	struct hda_pcm_stream *hinfo = apcm->hinfo[substream->stream];
+	azx_t *chip = apcm->chip;
+	azx_dev_t *azx_dev;
+	snd_pcm_runtime_t *runtime = substream->runtime;
+	unsigned long flags;
+	int err;
+
+	down(&chip->open_mutex);
+	azx_dev = azx_assign_device(chip, substream->stream);
+	if (azx_dev == NULL) {
+		up(&chip->open_mutex);
+		return -EBUSY;
+	}
+	runtime->hw = azx_pcm_hw;
+	runtime->hw.channels_min = hinfo->channels_min;
+	runtime->hw.channels_max = hinfo->channels_max;
+	runtime->hw.formats = hinfo->formats;
+	runtime->hw.rates = hinfo->rates;
+	snd_pcm_limit_hw_rates(runtime);
+	snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
+	if ((err = hinfo->ops.open(hinfo, apcm->codec, substream)) < 0) {
+		azx_release_device(azx_dev);
+		up(&chip->open_mutex);
+		return err;
+	}
+	spin_lock_irqsave(&chip->reg_lock, flags);
+	azx_dev->substream = substream;
+	azx_dev->running = 0;
+	spin_unlock_irqrestore(&chip->reg_lock, flags);
+
+	runtime->private_data = azx_dev;
+	up(&chip->open_mutex);
+	return 0;
+}
+
+static int azx_pcm_close(snd_pcm_substream_t *substream)
+{
+	struct azx_pcm *apcm = snd_pcm_substream_chip(substream);
+	struct hda_pcm_stream *hinfo = apcm->hinfo[substream->stream];
+	azx_t *chip = apcm->chip;
+	azx_dev_t *azx_dev = get_azx_dev(substream);
+	unsigned long flags;
+
+	down(&chip->open_mutex);
+	spin_lock_irqsave(&chip->reg_lock, flags);
+	azx_dev->substream = NULL;
+	azx_dev->running = 0;
+	spin_unlock_irqrestore(&chip->reg_lock, flags);
+	azx_release_device(azx_dev);
+	hinfo->ops.close(hinfo, apcm->codec, substream);
+	up(&chip->open_mutex);
+	return 0;
+}
+
+static int azx_pcm_hw_params(snd_pcm_substream_t *substream, snd_pcm_hw_params_t *hw_params)
+{
+	return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
+}
+
+static int azx_pcm_hw_free(snd_pcm_substream_t *substream)
+{
+	struct azx_pcm *apcm = snd_pcm_substream_chip(substream);
+	azx_dev_t *azx_dev = get_azx_dev(substream);
+	struct hda_pcm_stream *hinfo = apcm->hinfo[substream->stream];
+
+	/* reset BDL address */
+	azx_sd_writel(azx_dev, SD_BDLPL, 0);
+	azx_sd_writel(azx_dev, SD_BDLPU, 0);
+	azx_sd_writel(azx_dev, SD_CTL, 0);
+
+	hinfo->ops.cleanup(hinfo, apcm->codec, substream);
+
+	return snd_pcm_lib_free_pages(substream);
+}
+
+static int azx_pcm_prepare(snd_pcm_substream_t *substream)
+{
+	struct azx_pcm *apcm = snd_pcm_substream_chip(substream);
+	azx_t *chip = apcm->chip;
+	azx_dev_t *azx_dev = get_azx_dev(substream);
+	struct hda_pcm_stream *hinfo = apcm->hinfo[substream->stream];
+	snd_pcm_runtime_t *runtime = substream->runtime;
+
+	azx_dev->bufsize = snd_pcm_lib_buffer_bytes(substream);
+	azx_dev->fragsize = snd_pcm_lib_period_bytes(substream);
+	azx_dev->frags = azx_dev->bufsize / azx_dev->fragsize;
+	azx_dev->format_val = snd_hda_calc_stream_format(runtime->rate,
+							 runtime->channels,
+							 runtime->format,
+							 hinfo->maxbps);
+	if (! azx_dev->format_val) {
+		snd_printk(KERN_ERR SFX "invalid format_val, rate=%d, ch=%d, format=%d\n",
+			   runtime->rate, runtime->channels, runtime->format);
+		return -EINVAL;
+	}
+
+	snd_printdd("azx_pcm_prepare: bufsize=0x%x, fragsize=0x%x, format=0x%x\n",
+		    azx_dev->bufsize, azx_dev->fragsize, azx_dev->format_val);
+	azx_setup_periods(azx_dev);
+	azx_setup_controller(chip, azx_dev);
+	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+		azx_dev->fifo_size = azx_sd_readw(azx_dev, SD_FIFOSIZE) + 1;
+	else
+		azx_dev->fifo_size = 0;
+
+	return hinfo->ops.prepare(hinfo, apcm->codec, azx_dev->stream_tag,
+				  azx_dev->format_val, substream);
+}
+
+static int azx_pcm_trigger(snd_pcm_substream_t *substream, int cmd)
+{
+	struct azx_pcm *apcm = snd_pcm_substream_chip(substream);
+	azx_dev_t *azx_dev = get_azx_dev(substream);
+	azx_t *chip = apcm->chip;
+	int err = 0;
+
+	spin_lock(&chip->reg_lock);
+	switch (cmd) {
+	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+	case SNDRV_PCM_TRIGGER_RESUME:
+	case SNDRV_PCM_TRIGGER_START:
+		azx_stream_start(chip, azx_dev);
+		azx_dev->running = 1;
+		break;
+	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+	case SNDRV_PCM_TRIGGER_STOP:
+		azx_stream_stop(chip, azx_dev);
+		azx_dev->running = 0;
+		break;
+	default:
+		err = -EINVAL;
+	}
+	spin_unlock(&chip->reg_lock);
+	if (cmd == SNDRV_PCM_TRIGGER_PAUSE_PUSH ||
+	    cmd == SNDRV_PCM_TRIGGER_STOP) {
+		int timeout = 5000;
+		while (azx_sd_readb(azx_dev, SD_CTL) & SD_CTL_DMA_START && --timeout)
+			;
+	}
+	return err;
+}
+
+static snd_pcm_uframes_t azx_pcm_pointer(snd_pcm_substream_t *substream)
+{
+	azx_dev_t *azx_dev = get_azx_dev(substream);
+	unsigned int pos;
+
+#ifdef USE_POSBUF
+	/* use the position buffer */
+	pos = *azx_dev->posbuf;
+#else
+	/* read LPIB */
+	pos = azx_sd_readl(azx_dev, SD_LPIB) + azx_dev->fifo_size;
+#endif
+	if (pos >= azx_dev->bufsize)
+		pos = 0;
+	return bytes_to_frames(substream->runtime, pos);
+}
+
+static snd_pcm_ops_t azx_pcm_ops = {
+	.open = azx_pcm_open,
+	.close = azx_pcm_close,
+	.ioctl = snd_pcm_lib_ioctl,
+	.hw_params = azx_pcm_hw_params,
+	.hw_free = azx_pcm_hw_free,
+	.prepare = azx_pcm_prepare,
+	.trigger = azx_pcm_trigger,
+	.pointer = azx_pcm_pointer,
+};
+
+static void azx_pcm_free(snd_pcm_t *pcm)
+{
+	kfree(pcm->private_data);
+}
+
+static int __devinit create_codec_pcm(azx_t *chip, struct hda_codec *codec,
+				      struct hda_pcm *cpcm, int pcm_dev)
+{
+	int err;
+	snd_pcm_t *pcm;
+	struct azx_pcm *apcm;
+
+	snd_assert(cpcm->stream[0].substreams || cpcm->stream[1].substreams, return -EINVAL);
+	snd_assert(cpcm->name, return -EINVAL);
+
+	err = snd_pcm_new(chip->card, cpcm->name, pcm_dev,
+			  cpcm->stream[0].substreams, cpcm->stream[1].substreams,
+			  &pcm);
+	if (err < 0)
+		return err;
+	strcpy(pcm->name, cpcm->name);
+	apcm = kmalloc(sizeof(*apcm), GFP_KERNEL);
+	if (apcm == NULL)
+		return -ENOMEM;
+	apcm->chip = chip;
+	apcm->codec = codec;
+	apcm->hinfo[0] = &cpcm->stream[0];
+	apcm->hinfo[1] = &cpcm->stream[1];
+	pcm->private_data = apcm;
+	pcm->private_free = azx_pcm_free;
+	if (cpcm->stream[0].substreams)
+		snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &azx_pcm_ops);
+	if (cpcm->stream[1].substreams)
+		snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &azx_pcm_ops);
+	snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
+					      snd_dma_pci_data(chip->pci),
+					      1024 * 64, 1024 * 128);
+	chip->pcm[pcm_dev] = pcm;
+
+	return 0;
+}
+
+static int __devinit azx_pcm_create(azx_t *chip)
+{
+	struct list_head *p;
+	struct hda_codec *codec;
+	int c, err;
+	int pcm_dev;
+
+	if ((err = snd_hda_build_pcms(chip->bus)) < 0)
+		return err;
+
+	pcm_dev = 0;
+	list_for_each(p, &chip->bus->codec_list) {
+		codec = list_entry(p, struct hda_codec, list);
+		for (c = 0; c < codec->num_pcms; c++) {
+			if (pcm_dev >= AZX_MAX_PCMS) {
+				snd_printk(KERN_ERR SFX "Too many PCMs\n");
+				return -EINVAL;
+			}
+			err = create_codec_pcm(chip, codec, &codec->pcm_info[c], pcm_dev);
+			if (err < 0)
+				return err;
+			pcm_dev++;
+		}
+	}
+	return 0;
+}
+
+/*
+ * mixer creation - all stuff is implemented in hda module
+ */
+static int __devinit azx_mixer_create(azx_t *chip)
+{
+	return snd_hda_build_controls(chip->bus);
+}
+
+
+/*
+ * initialize SD streams
+ */
+static int __devinit azx_init_stream(azx_t *chip)
+{
+	int i;
+
+	/* initialize each stream (aka device)
+	 * assign the starting bdl address to each stream (device) and initialize
+	 */
+	for (i = 0; i < MAX_ICH6_DEV; i++) {
+		unsigned int off = sizeof(u32) * (i * AZX_MAX_FRAG * 4);
+		azx_dev_t *azx_dev = &chip->azx_dev[i];
+		azx_dev->bdl = (u32 *)(chip->bdl.area + off);
+		azx_dev->bdl_addr = chip->bdl.addr + off;
+#ifdef USE_POSBUF
+		azx_dev->posbuf = (volatile u32 *)(chip->posbuf.area + i * 8);
+#endif
+		/* offset: SDI0=0x80, SDI1=0xa0, ... SDO3=0x160 */
+		azx_dev->sd_addr = chip->remap_addr + (0x20 * i + 0x80);
+		/* int mask: SDI0=0x01, SDI1=0x02, ... SDO3=0x80 */
+		azx_dev->sd_int_sta_mask = 1 << i;
+		/* stream tag: must be non-zero and unique */
+		azx_dev->index = i;
+		azx_dev->stream_tag = i + 1;
+	}
+
+	return 0;
+}
+
+
+#ifdef CONFIG_PM
+/*
+ * power management
+ */
+static int azx_suspend(snd_card_t *card, pm_message_t state)
+{
+	azx_t *chip = card->pm_private_data;
+	int i;
+
+	for (i = 0; i < chip->pcm_devs; i++)
+		if (chip->pcm[i])
+			snd_pcm_suspend_all(chip->pcm[i]);
+	snd_hda_suspend(chip->bus, state);
+	azx_free_cmd_io(chip);
+	pci_disable_device(chip->pci);
+	return 0;
+}
+
+static int azx_resume(snd_card_t *card)
+{
+	azx_t *chip = card->pm_private_data;
+
+	pci_enable_device(chip->pci);
+	pci_set_master(chip->pci);
+	azx_init_chip(chip);
+	snd_hda_resume(chip->bus);
+	return 0;
+}
+#endif /* CONFIG_PM */
+
+
+/*
+ * destructor
+ */
+static int azx_free(azx_t *chip)
+{
+	if (chip->remap_addr) {
+		int i;
+
+		for (i = 0; i < MAX_ICH6_DEV; i++)
+			azx_stream_stop(chip, &chip->azx_dev[i]);
+
+		/* disable interrupts */
+		azx_int_disable(chip);
+		azx_int_clear(chip);
+
+		/* disable CORB/RIRB */
+		azx_free_cmd_io(chip);
+
+		/* disable position buffer */
+		azx_writel(chip, DPLBASE, 0);
+		azx_writel(chip, DPUBASE, 0);
+
+		/* wait a little for interrupts to finish */
+		msleep(1);
+
+		iounmap(chip->remap_addr);
+	}
+
+	if (chip->irq >= 0)
+		free_irq(chip->irq, (void*)chip);
+
+	if (chip->bdl.area)
+		snd_dma_free_pages(&chip->bdl);
+	if (chip->rb.area)
+		snd_dma_free_pages(&chip->rb);
+#ifdef USE_POSBUF
+	if (chip->posbuf.area)
+		snd_dma_free_pages(&chip->posbuf);
+#endif
+	pci_release_regions(chip->pci);
+	pci_disable_device(chip->pci);
+	kfree(chip);
+
+	return 0;
+}
+
+static int azx_dev_free(snd_device_t *device)
+{
+	return azx_free(device->device_data);
+}
+
+/*
+ * constructor
+ */
+static int __devinit azx_create(snd_card_t *card, struct pci_dev *pci, azx_t **rchip)
+{
+	azx_t *chip;
+	int err = 0;
+	static snd_device_ops_t ops = {
+		.dev_free = azx_dev_free,
+	};
+
+	*rchip = NULL;
+	
+	if ((err = pci_enable_device(pci)) < 0)
+		return err;
+
+	chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
+	
+	if (NULL == chip) {
+		snd_printk(KERN_ERR SFX "cannot allocate chip\n");
+		pci_disable_device(pci);
+		return -ENOMEM;
+	}
+
+	spin_lock_init(&chip->reg_lock);
+	init_MUTEX(&chip->open_mutex);
+	chip->card = card;
+	chip->pci = pci;
+	chip->irq = -1;
+
+	if ((err = pci_request_regions(pci, "ICH HD audio")) < 0) {
+		kfree(chip);
+		pci_disable_device(pci);
+		return err;
+	}
+
+	chip->addr = pci_resource_start(pci,0);
+	chip->remap_addr = ioremap_nocache(chip->addr, pci_resource_len(pci,0));
+	if (chip->remap_addr == NULL) {
+		snd_printk(KERN_ERR SFX "ioremap error\n");
+		err = -ENXIO;
+		goto errout;
+	}
+
+	if (request_irq(pci->irq, azx_interrupt, SA_INTERRUPT|SA_SHIRQ,
+			"HDA Intel", (void*)chip)) {
+		snd_printk(KERN_ERR SFX "unable to grab IRQ %d\n", pci->irq);
+		err = -EBUSY;
+		goto errout;
+	}
+	chip->irq = pci->irq;
+
+	pci_set_master(pci);
+	synchronize_irq(chip->irq);
+
+	/* allocate memory for the BDL for each stream */
+	if ((err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(chip->pci),
+				       PAGE_SIZE, &chip->bdl)) < 0) {
+		snd_printk(KERN_ERR SFX "cannot allocate BDL\n");
+		goto errout;
+	}
+#ifdef USE_POSBUF
+	/* allocate memory for the position buffer */
+	if ((err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(chip->pci),
+				       MAX_ICH6_DEV * 8, &chip->posbuf)) < 0) {
+		snd_printk(KERN_ERR SFX "cannot allocate posbuf\n");
+		goto errout;
+	}
+#endif
+	/* allocate CORB/RIRB */
+	if ((err = azx_alloc_cmd_io(chip)) < 0)
+		goto errout;
+
+	/* initialize streams */
+	azx_init_stream(chip);
+
+	/* initialize chip */
+	azx_init_chip(chip);
+
+	/* codec detection */
+	if (! chip->codec_mask) {
+		snd_printk(KERN_ERR SFX "no codecs found!\n");
+		err = -ENODEV;
+		goto errout;
+	}
+
+	if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) <0) {
+		snd_printk(KERN_ERR SFX "Error creating device [card]!\n");
+		goto errout;
+	}
+
+	*rchip = chip;
+	return 0;
+
+ errout:
+	azx_free(chip);
+	return err;
+}
+
+static int __devinit azx_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
+{
+	static int dev;
+	snd_card_t *card;
+	azx_t *chip;
+	int err = 0;
+
+	if (dev >= SNDRV_CARDS)
+		return -ENODEV;
+	if (! enable[dev]) {
+		dev++;
+		return -ENOENT;
+	}
+
+	card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
+	if (NULL == card) {
+		snd_printk(KERN_ERR SFX "Error creating card!\n");
+		return -ENOMEM;
+	}
+
+	if ((err = azx_create(card, pci, &chip)) < 0) {
+		snd_card_free(card);
+		return err;
+	}
+
+	strcpy(card->driver, "HDA-Intel");
+	strcpy(card->shortname, "HDA Intel");
+	sprintf(card->longname, "%s at 0x%lx irq %i", card->shortname, chip->addr, chip->irq);
+
+	/* create codec instances */
+	if ((err = azx_codec_create(chip, model[dev])) < 0) {
+		snd_card_free(card);
+		return err;
+	}
+
+	/* create PCM streams */
+	if ((err = azx_pcm_create(chip)) < 0) {
+		snd_card_free(card);
+		return err;
+	}
+
+	/* create mixer controls */
+	if ((err = azx_mixer_create(chip)) < 0) {
+		snd_card_free(card);
+		return err;
+	}
+
+	snd_card_set_pm_callback(card, azx_suspend, azx_resume, chip);
+	snd_card_set_dev(card, &pci->dev);
+
+	if ((err = snd_card_register(card)) < 0) {
+		snd_card_free(card);
+		return err;
+	}
+
+	pci_set_drvdata(pci, card);
+	dev++;
+
+	return err;
+}
+
+static void __devexit azx_remove(struct pci_dev *pci)
+{
+	snd_card_free(pci_get_drvdata(pci));
+	pci_set_drvdata(pci, NULL);
+}
+
+/* PCI IDs */
+static struct pci_device_id azx_ids[] = {
+	{ 0x8086, 0x2668, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* ICH6 */
+	{ 0x8086, 0x27d8, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* ICH7 */
+	{ 0, }
+};
+MODULE_DEVICE_TABLE(pci, azx_ids);
+
+/* pci_driver definition */
+static struct pci_driver driver = {
+	.name = "HDA Intel",
+	.id_table = azx_ids,
+	.probe = azx_probe,
+	.remove = __devexit_p(azx_remove),
+	SND_PCI_PM_CALLBACKS
+};
+
+static int __init alsa_card_azx_init(void)
+{
+	return pci_module_init(&driver);
+}
+
+static void __exit alsa_card_azx_exit(void)
+{
+	pci_unregister_driver(&driver);
+}
+
+module_init(alsa_card_azx_init)
+module_exit(alsa_card_azx_exit)
diff -Nru a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/sound/pci/hda/hda_local.h	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,161 @@
+/*
+ * Universal Interface for Intel High Definition Audio Codec
+ *
+ * Local helper functions
+ *
+ * Copyright (c) 2004 Takashi Iwai <tiwai@suse.de>
+ *
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under the terms of the GNU General Public License as published by the Free
+ *  Software Foundation; either version 2 of the License, or (at your option)
+ *  any later version.
+ *
+ *  This program is distributed in the hope that it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ *  more details.
+ *
+ *  You should have received a copy of the GNU General Public License along with
+ *  this program; if not, write to the Free Software Foundation, Inc., 59
+ *  Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#ifndef __SOUND_HDA_LOCAL_H
+#define __SOUND_HDA_LOCAL_H
+
+/*
+ * for mixer controls
+ */
+#define HDA_COMPOSE_AMP_VAL(nid,chs,idx,dir) ((nid) | ((chs)<<16) | ((dir)<<18) | ((idx)<<19))
+#define HDA_CODEC_VOLUME_MONO_IDX(xname, xcidx, nid, channel, xindex, direction) \
+	{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xcidx,  \
+	  .info = snd_hda_mixer_amp_volume_info, \
+	  .get = snd_hda_mixer_amp_volume_get, \
+	  .put = snd_hda_mixer_amp_volume_put, \
+	  .private_value = HDA_COMPOSE_AMP_VAL(nid, channel, xindex, direction) }
+#define HDA_CODEC_VOLUME_IDX(xname, xcidx, nid, xindex, direction) \
+	HDA_CODEC_VOLUME_MONO_IDX(xname, xcidx, nid, 3, xindex, direction)
+#define HDA_CODEC_VOLUME_MONO(xname, nid, channel, xindex, direction) \
+	HDA_CODEC_VOLUME_MONO_IDX(xname, 0, nid, channel, xindex, direction)
+#define HDA_CODEC_VOLUME(xname, nid, xindex, direction) \
+	HDA_CODEC_VOLUME_MONO(xname, nid, 3, xindex, direction)
+#define HDA_CODEC_MUTE_MONO_IDX(xname, xcidx, nid, channel, xindex, direction) \
+	{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xcidx, \
+	  .info = snd_hda_mixer_amp_switch_info, \
+	  .get = snd_hda_mixer_amp_switch_get, \
+	  .put = snd_hda_mixer_amp_switch_put, \
+	  .private_value = HDA_COMPOSE_AMP_VAL(nid, channel, xindex, direction) }
+#define HDA_CODEC_MUTE_IDX(xname, xcidx, nid, xindex, direction) \
+	HDA_CODEC_MUTE_MONO_IDX(xname, xcidx, nid, 3, xindex, direction)
+#define HDA_CODEC_MUTE_MONO(xname, nid, channel, xindex, direction) \
+	HDA_CODEC_MUTE_MONO_IDX(xname, 0, nid, channel, xindex, direction)
+#define HDA_CODEC_MUTE(xname, nid, xindex, direction) \
+	HDA_CODEC_MUTE_MONO(xname, nid, 3, xindex, direction)
+
+int snd_hda_mixer_amp_volume_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo);
+int snd_hda_mixer_amp_volume_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol);
+int snd_hda_mixer_amp_volume_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol);
+int snd_hda_mixer_amp_switch_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo);
+int snd_hda_mixer_amp_switch_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol);
+int snd_hda_mixer_amp_switch_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol);
+
+int snd_hda_create_spdif_out_ctls(struct hda_codec *codec, hda_nid_t nid);
+int snd_hda_create_spdif_in_ctls(struct hda_codec *codec, hda_nid_t nid);
+
+/*
+ * input MUX helper
+ */
+#define HDA_MAX_NUM_INPUTS	8
+struct hda_input_mux_item {
+	const char *label;
+	unsigned int index;
+};
+struct hda_input_mux {
+	unsigned int num_items;
+	struct hda_input_mux_item items[HDA_MAX_NUM_INPUTS];
+};
+
+int snd_hda_input_mux_info(const struct hda_input_mux *imux, snd_ctl_elem_info_t *uinfo);
+int snd_hda_input_mux_put(struct hda_codec *codec, const struct hda_input_mux *imux,
+			  snd_ctl_elem_value_t *ucontrol, hda_nid_t nid,
+			  unsigned int *cur_val);
+
+/*
+ * Multi-channel / digital-out PCM helper
+ */
+
+enum { HDA_FRONT, HDA_REAR, HDA_CLFE, HDA_SIDE }; /* index for dac_nidx */
+enum { HDA_DIG_NONE, HDA_DIG_EXCLUSIVE, HDA_DIG_ANALOG_DUP }; /* dig_out_used */
+
+struct hda_multi_out {
+	int num_dacs;		/* # of DACs, must be more than 1 */
+	hda_nid_t *dac_nids;	/* DAC list */
+	hda_nid_t hp_nid;	/* optional DAC for HP, 0 when not exists */
+	hda_nid_t dig_out_nid;	/* digital out audio widget */
+	int max_channels;	/* currently supported analog channels */
+	int dig_out_used;	/* current usage of digital out (HDA_DIG_XXX) */
+};
+
+int snd_hda_multi_out_dig_open(struct hda_codec *codec, struct hda_multi_out *mout);
+int snd_hda_multi_out_dig_close(struct hda_codec *codec, struct hda_multi_out *mout);
+int snd_hda_multi_out_analog_open(struct hda_codec *codec, struct hda_multi_out *mout,
+				  snd_pcm_substream_t *substream);
+int snd_hda_multi_out_analog_prepare(struct hda_codec *codec, struct hda_multi_out *mout,
+				     unsigned int stream_tag,
+				     unsigned int format,
+				     snd_pcm_substream_t *substream);
+int snd_hda_multi_out_analog_cleanup(struct hda_codec *codec, struct hda_multi_out *mout);
+
+/*
+ * generic codec parser
+ */
+int snd_hda_parse_generic_codec(struct hda_codec *codec);
+
+/*
+ * generic proc interface
+ */
+#ifdef CONFIG_PROC_FS
+int snd_hda_codec_proc_new(struct hda_codec *codec);
+#else
+static inline int snd_hda_codec_proc_new(struct hda_codec *codec) { return 0; }
+#endif
+
+/*
+ * Misc
+ */
+struct hda_board_config {
+	const char *modelname;
+	int config;
+	unsigned short pci_vendor;
+	unsigned short pci_device;
+};
+
+int snd_hda_check_board_config(struct hda_codec *codec, struct hda_board_config *tbl);
+int snd_hda_add_new_ctls(struct hda_codec *codec, snd_kcontrol_new_t *knew);
+
+/*
+ * power management
+ */
+#ifdef CONFIG_PM
+int snd_hda_resume_ctls(struct hda_codec *codec, snd_kcontrol_new_t *knew);
+int snd_hda_resume_spdif_out(struct hda_codec *codec);
+int snd_hda_resume_spdif_in(struct hda_codec *codec);
+#endif
+
+/*
+ * unsolicited event handler
+ */
+
+#define HDA_UNSOL_QUEUE_SIZE	64
+
+struct hda_bus_unsolicited {
+	/* ring buffer */
+	u32 queue[HDA_UNSOL_QUEUE_SIZE * 2];
+	unsigned int rp, wp;
+
+	/* workqueue */
+	struct workqueue_struct *workq;
+	struct work_struct work;
+};
+
+#endif /* __SOUND_HDA_LOCAL_H */
diff -Nru a/sound/pci/hda/hda_patch.h b/sound/pci/hda/hda_patch.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/sound/pci/hda/hda_patch.h	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,14 @@
+/*
+ * HDA Patches - included by hda_codec.c
+ */
+
+/* Realtek codecs */
+extern struct hda_codec_preset snd_hda_preset_realtek[];
+/* C-Media codecs */
+extern struct hda_codec_preset snd_hda_preset_cmedia[];
+
+static const struct hda_codec_preset *hda_preset_tables[] = {
+	snd_hda_preset_realtek,
+	snd_hda_preset_cmedia,
+	NULL
+};
diff -Nru a/sound/pci/hda/hda_proc.c b/sound/pci/hda/hda_proc.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/sound/pci/hda/hda_proc.c	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,298 @@
+/*
+ * Universal Interface for Intel High Definition Audio Codec
+ * 
+ * Generic proc interface
+ *
+ * Copyright (c) 2004 Takashi Iwai <tiwai@suse.de>
+ *
+ *
+ *  This driver 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 driver is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ */
+
+#include <sound/driver.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <sound/core.h>
+#include "hda_codec.h"
+
+static const char *get_wid_type_name(unsigned int wid_value)
+{
+	static char *names[16] = {
+		[AC_WID_AUD_OUT] = "Audio Output",
+		[AC_WID_AUD_IN] = "Audio Input",
+		[AC_WID_AUD_MIX] = "Audio Mixer",
+		[AC_WID_AUD_SEL] = "Audio Selector",
+		[AC_WID_PIN] = "Pin Complex",
+		[AC_WID_POWER] = "Power Widget",
+		[AC_WID_VOL_KNB] = "Volume Knob Widget",
+		[AC_WID_BEEP] = "Beep Generator Widget",
+		[AC_WID_VENDOR] = "Vendor Defined Widget",
+	};
+	wid_value &= 0xf;
+	if (names[wid_value])
+		return names[wid_value];
+	else
+		return "UNKOWN Widget";
+}
+
+static void print_amp_caps(snd_info_buffer_t *buffer,
+			   struct hda_codec *codec, hda_nid_t nid, int dir)
+{
+	unsigned int caps;
+	if (dir == HDA_OUTPUT)
+		caps = snd_hda_param_read(codec, nid, AC_PAR_AMP_OUT_CAP);
+	else
+		caps = snd_hda_param_read(codec, nid, AC_PAR_AMP_IN_CAP);
+	if (caps == -1 || caps == 0) {
+		snd_iprintf(buffer, "N/A\n");
+		return;
+	}
+	snd_iprintf(buffer, "ofs=0x%02x, nsteps=0x%02x, stepsize=0x%02x, mute=%x\n",
+		    caps & AC_AMPCAP_OFFSET,
+		    (caps & AC_AMPCAP_NUM_STEPS) >> AC_AMPCAP_NUM_STEPS_SHIFT,
+		    (caps & AC_AMPCAP_STEP_SIZE) >> AC_AMPCAP_STEP_SIZE_SHIFT,
+		    (caps & AC_AMPCAP_MUTE) >> AC_AMPCAP_MUTE_SHIFT);
+}
+
+static void print_amp_vals(snd_info_buffer_t *buffer,
+			   struct hda_codec *codec, hda_nid_t nid,
+			   int dir, int stereo)
+{
+	unsigned int val;
+	if (stereo) {
+		val = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_AMP_GAIN_MUTE,
+					  AC_AMP_GET_LEFT |
+					 (dir == HDA_OUTPUT ? AC_AMP_GET_OUTPUT :
+					  AC_AMP_GET_INPUT));
+		snd_iprintf(buffer, "0x%02x ", val);
+	}
+	val = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_AMP_GAIN_MUTE,
+				 AC_AMP_GET_RIGHT |
+				 (dir == HDA_OUTPUT ? AC_AMP_GET_OUTPUT :
+				  AC_AMP_GET_INPUT));
+	snd_iprintf(buffer, "0x%02x\n", val);
+}
+
+static void print_pcm_caps(snd_info_buffer_t *buffer,
+			   struct hda_codec *codec, hda_nid_t nid)
+{
+	unsigned int pcm = snd_hda_param_read(codec, nid, AC_PAR_PCM);
+	unsigned int stream = snd_hda_param_read(codec, nid, AC_PAR_STREAM);
+	if (pcm == -1 || stream == -1) {
+		snd_iprintf(buffer, "N/A\n");
+		return;
+	}
+	snd_iprintf(buffer, "rates 0x%03x, bits 0x%02x, types 0x%x\n",
+		    pcm & AC_SUPPCM_RATES, (pcm >> 16) & 0xff, stream & 0xf);
+}
+
+static const char *get_jack_location(u32 cfg)
+{
+	static char *bases[7] = {
+		"N/A", "Rear", "Front", "Left", "Right", "Top", "Bottom",
+	};
+	static unsigned char specials_idx[] = {
+		0x07, 0x08,
+		0x17, 0x18, 0x19,
+		0x37, 0x38
+	};
+	static char *specials[] = {
+		"Rear Panel", "Drive Bar",
+		"Riser", "HDMI", "ATAPI",
+		"Mobile-In", "Mobile-Out"
+	};
+	int i;
+	cfg = (cfg & AC_DEFCFG_LOCATION) >> AC_DEFCFG_LOCATION_SHIFT;
+	if ((cfg & 0x0f) < 7)
+		return bases[cfg & 0x0f];
+	for (i = 0; i < ARRAY_SIZE(specials_idx); i++) {
+		if (cfg == specials_idx[i])
+			return specials[i];
+	}
+	return "UNKNOWN";
+}
+
+static const char *get_jack_connection(u32 cfg)
+{
+	static char *names[16] = {
+		"Unknown", "1/8", "1/4", "ATAPI",
+		"RCA", "Optical","Digital", "Analog",
+		"DIN", "XLR", "RJ11", "Comb",
+		NULL, NULL, NULL, "Other"
+	};
+	cfg = (cfg & AC_DEFCFG_CONN_TYPE) >> AC_DEFCFG_CONN_TYPE_SHIFT;
+	if (names[cfg])
+		return names[cfg];
+	else
+		return "UNKNOWN";
+}
+
+static const char *get_jack_color(u32 cfg)
+{
+	static char *names[16] = {
+		"Unknown", "Black", "Grey", "Blue",
+		"Green", "Red", "Orange", "Yellow",
+		"Purple", "Pink", NULL, NULL,
+		NULL, NULL, "White", "Other",
+	};
+	cfg = (cfg & AC_DEFCFG_COLOR) >> AC_DEFCFG_COLOR_SHIFT;
+	if (names[cfg])
+		return names[cfg];
+	else
+		return "UNKNOWN";
+}
+
+static void print_pin_caps(snd_info_buffer_t *buffer,
+			   struct hda_codec *codec, hda_nid_t nid)
+{
+	static char *jack_types[16] = {
+		"Line Out", "Speaker", "HP Out", "CD",
+		"SPDIF Out", "Digital Out", "Modem Line", "Modem Hand",
+		"Line In", "Aux", "Mic", "Telephony",
+		"SPDIF In", "Digitial In", "Reserved", "Other"
+	};
+	static char *jack_locations[4] = { "Ext", "Int", "Sep", "Oth" };
+	unsigned int caps;
+
+	caps = snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP);
+	snd_iprintf(buffer, "  Pincap 0x08%x:", caps);
+	if (caps & AC_PINCAP_IN)
+		snd_iprintf(buffer, " IN");
+	if (caps & AC_PINCAP_OUT)
+		snd_iprintf(buffer, " OUT");
+	if (caps & AC_PINCAP_HP_DRV)
+		snd_iprintf(buffer, " HP");
+	snd_iprintf(buffer, "\n");
+	caps = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONFIG_DEFAULT, 0);
+	snd_iprintf(buffer, "  Pin Default 0x%08x: %s at %s %s\n", caps,
+		    jack_types[(caps & AC_DEFCFG_DEVICE) >> AC_DEFCFG_DEVICE_SHIFT],
+		    jack_locations[(caps >> (AC_DEFCFG_LOCATION_SHIFT + 4)) & 3],
+		    get_jack_location(caps));
+	snd_iprintf(buffer, "    Conn = %s, Color = %s\n",
+		    get_jack_connection(caps),
+		    get_jack_color(caps));
+}
+
+
+static void print_codec_info(snd_info_entry_t *entry, snd_info_buffer_t *buffer)
+{
+	struct hda_codec *codec = entry->private_data;
+	char buf[32];
+	hda_nid_t nid;
+	int i, nodes;
+
+	snd_hda_get_codec_name(codec, buf, sizeof(buf));
+	snd_iprintf(buffer, "Codec: %s\n", buf);
+	snd_iprintf(buffer, "Address: %d\n", codec->addr);
+	snd_iprintf(buffer, "Vendor Id: 0x%x\n", codec->vendor_id);
+	snd_iprintf(buffer, "Subsystem Id: 0x%x\n", codec->subsystem_id);
+	snd_iprintf(buffer, "Revision Id: 0x%x\n", codec->revision_id);
+	snd_iprintf(buffer, "Default PCM: ");
+	print_pcm_caps(buffer, codec, codec->afg);
+	snd_iprintf(buffer, "Default Amp-In caps: ");
+	print_amp_caps(buffer, codec, codec->afg, HDA_INPUT);
+	snd_iprintf(buffer, "Default Amp-Out caps: ");
+	print_amp_caps(buffer, codec, codec->afg, HDA_OUTPUT);
+
+	nodes = snd_hda_get_sub_nodes(codec, codec->afg, &nid);
+	if (! nid || nodes < 0) {
+		snd_iprintf(buffer, "Invalid AFG subtree\n");
+		return;
+	}
+	for (i = 0; i < nodes; i++, nid++) {
+		unsigned int wid_caps = snd_hda_param_read(codec, nid,
+							   AC_PAR_AUDIO_WIDGET_CAP);
+		unsigned int wid_type = (wid_caps & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT;
+		snd_iprintf(buffer, "Node 0x%02x [%s] wcaps 0x%x:", nid,
+			    get_wid_type_name(wid_type), wid_caps);
+		if (wid_caps & AC_WCAP_STEREO)
+			snd_iprintf(buffer, " Stereo");
+		else
+			snd_iprintf(buffer, " Mono");
+		if (wid_caps & AC_WCAP_DIGITAL)
+			snd_iprintf(buffer, " Digital");
+		if (wid_caps & AC_WCAP_IN_AMP)
+			snd_iprintf(buffer, " Amp-In");
+		if (wid_caps & AC_WCAP_OUT_AMP)
+			snd_iprintf(buffer, " Amp-Out");
+		snd_iprintf(buffer, "\n");
+
+		if (wid_caps & AC_WCAP_IN_AMP) {
+			snd_iprintf(buffer, "  Amp-In caps: ");
+			print_amp_caps(buffer, codec, nid, HDA_INPUT);
+			snd_iprintf(buffer, "  Amp-In vals: ");
+			print_amp_vals(buffer, codec, nid, HDA_INPUT,
+				       wid_caps & AC_WCAP_STEREO);
+		}
+		if (wid_caps & AC_WCAP_OUT_AMP) {
+			snd_iprintf(buffer, "  Amp-Out caps: ");
+			print_amp_caps(buffer, codec, nid, HDA_OUTPUT);
+			snd_iprintf(buffer, "  Amp-Out vals: ");
+			print_amp_vals(buffer, codec, nid, HDA_OUTPUT,
+				       wid_caps & AC_WCAP_STEREO);
+		}
+
+		if (wid_type == AC_WID_PIN) {
+			unsigned int pinctls;
+			print_pin_caps(buffer, codec, nid);
+			pinctls = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
+			snd_iprintf(buffer, "  Pin-ctls: 0x%02x:", pinctls);
+			if (pinctls & AC_PINCTL_IN_EN)
+				snd_iprintf(buffer, " IN");
+			if (pinctls & AC_PINCTL_OUT_EN)
+				snd_iprintf(buffer, " OUT");
+			if (pinctls & AC_PINCTL_HP_EN)
+				snd_iprintf(buffer, " HP");
+			snd_iprintf(buffer, "\n");
+		}
+
+		if ((wid_type == AC_WID_AUD_OUT || wid_type == AC_WID_AUD_IN) &&
+		    (wid_caps & AC_WCAP_FORMAT_OVRD)) {
+			snd_iprintf(buffer, "  PCM: ");
+			print_pcm_caps(buffer, codec, nid);
+		}
+
+		if (wid_caps & AC_WCAP_CONN_LIST) {
+			hda_nid_t conn[HDA_MAX_CONNECTIONS];
+			int c, conn_len;
+			conn_len = snd_hda_get_connections(codec, nid, conn,
+							   HDA_MAX_CONNECTIONS);
+			snd_iprintf(buffer, "  Connection: %d\n", conn_len);
+			snd_iprintf(buffer, "    ");
+			for (c = 0; c < conn_len; c++)
+				snd_iprintf(buffer, " 0x%02x", conn[c]);
+			snd_iprintf(buffer, "\n");
+		}
+	}
+}
+
+/*
+ * create a proc read
+ */
+int snd_hda_codec_proc_new(struct hda_codec *codec)
+{
+	char name[32];
+	snd_info_entry_t *entry;
+	int err;
+
+	snprintf(name, sizeof(name), "codec#%d", codec->addr);
+	err = snd_card_proc_new(codec->bus->card, name, &entry);
+	if (err < 0)
+		return err;
+
+	snd_info_set_text_ops(entry, codec, 32 * 1024, print_codec_info);
+	return 0;
+}
+
diff -Nru a/sound/pci/hda/patch_cmedia.c b/sound/pci/hda/patch_cmedia.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/sound/pci/hda/patch_cmedia.c	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,620 @@
+/*
+ * Universal Interface for Intel High Definition Audio Codec
+ *
+ * HD audio interface patch for C-Media CMI9880
+ *
+ * Copyright (c) 2004 Takashi Iwai <tiwai@suse.de>
+ *
+ *
+ *  This driver 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 driver is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ */
+
+#include <sound/driver.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/pci.h>
+#include <sound/core.h>
+#include "hda_codec.h"
+#include "hda_local.h"
+
+
+/* board config type */
+enum {
+	CMI_MINIMAL,	/* back 3-jack */
+	CMI_MIN_FP,	/* back 3-jack + front-panel 2-jack */
+	CMI_FULL,	/* back 6-jack + front-panel 2-jack */
+	CMI_FULL_DIG,	/* back 6-jack + front-panel 2-jack + digital I/O */
+	CMI_ALLOUT,	/* back 5-jack + front-panel 2-jack + digital out */
+};
+
+struct cmi_spec {
+	int board_config;
+	unsigned int surr_switch: 1;	/* switchable line,mic */
+	unsigned int no_line_in: 1;	/* no line-in (5-jack) */
+	unsigned int front_panel: 1;	/* has front-panel 2-jack */
+
+	/* playback */
+	struct hda_multi_out multiout;
+
+	/* capture */
+	hda_nid_t *adc_nids;
+	hda_nid_t dig_in_nid;
+
+	/* capture source */
+	const struct hda_input_mux *input_mux;
+	unsigned int cur_mux[2];
+
+	/* channel mode */
+	unsigned int num_ch_modes;
+	unsigned int cur_ch_mode;
+	const struct cmi_channel_mode *channel_modes;
+
+	struct hda_pcm pcm_rec[2];	/* PCM information */
+};
+
+/*
+ * input MUX
+ */
+static int cmi_mux_enum_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+{
+	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct cmi_spec *spec = codec->spec;
+	return snd_hda_input_mux_info(spec->input_mux, uinfo);
+}
+
+static int cmi_mux_enum_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct cmi_spec *spec = codec->spec;
+	unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
+
+	ucontrol->value.enumerated.item[0] = spec->cur_mux[adc_idx];
+	return 0;
+}
+
+static int cmi_mux_enum_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct cmi_spec *spec = codec->spec;
+	unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
+
+	return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol,
+				     spec->adc_nids[adc_idx], &spec->cur_mux[adc_idx]);
+}
+
+/*
+ * shared line-in, mic for surrounds
+ */
+
+/* 3-stack / 2 channel */
+static struct hda_verb cmi9880_ch2_init[] = {
+	/* set line-in PIN for input */
+	{ 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
+	/* set mic PIN for input, also enable vref */
+	{ 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
+	/* route front PCM (DAC1) to HP */
+	{ 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 },
+	{}
+};
+
+/* 3-stack / 6 channel */
+static struct hda_verb cmi9880_ch6_init[] = {
+	/* set line-in PIN for input */
+	{ 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
+	/* set mic PIN for input, also enable vref */
+	{ 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
+	/* route front PCM (DAC1) to HP */
+	{ 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 },
+	{}
+};
+
+/* 3-stack+front / 8 channel */
+static struct hda_verb cmi9880_ch8_init[] = {
+	/* set line-in PIN for input */
+	{ 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
+	/* set mic PIN for input, also enable vref */
+	{ 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
+	/* route rear-surround PCM (DAC4) to HP */
+	{ 0x0f, AC_VERB_SET_CONNECT_SEL, 0x03 },
+	{}
+};
+
+struct cmi_channel_mode {
+	unsigned int channels;
+	const struct hda_verb *sequence;
+};
+
+static struct cmi_channel_mode cmi9880_channel_modes[3] = {
+	{ 2, cmi9880_ch2_init },
+	{ 6, cmi9880_ch6_init },
+	{ 8, cmi9880_ch8_init },
+};
+
+static int cmi_ch_mode_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+{
+	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct cmi_spec *spec = codec->spec;
+
+	snd_assert(spec->channel_modes, return -EINVAL);
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+	uinfo->count = 1;
+	uinfo->value.enumerated.items = spec->num_ch_modes;
+	if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
+		uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
+	sprintf(uinfo->value.enumerated.name, "%dch",
+		spec->channel_modes[uinfo->value.enumerated.item].channels);
+	return 0;
+}
+
+static int cmi_ch_mode_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct cmi_spec *spec = codec->spec;
+
+	ucontrol->value.enumerated.item[0] = spec->cur_ch_mode;
+	return 0;
+}
+
+static int cmi_ch_mode_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct cmi_spec *spec = codec->spec;
+
+	snd_assert(spec->channel_modes, return -EINVAL);
+	if (ucontrol->value.enumerated.item[0] >= spec->num_ch_modes)
+		ucontrol->value.enumerated.item[0] = spec->num_ch_modes;
+	if (ucontrol->value.enumerated.item[0] == spec->cur_ch_mode &&
+	    ! codec->in_resume)
+		return 0;
+
+	spec->cur_ch_mode = ucontrol->value.enumerated.item[0];
+	snd_hda_sequence_write(codec, spec->channel_modes[spec->cur_ch_mode].sequence);
+	spec->multiout.max_channels = spec->channel_modes[spec->cur_ch_mode].channels;
+	return 1;
+}
+
+/*
+ */
+static snd_kcontrol_new_t cmi9880_basic_mixer[] = {
+	/* CMI9880 has no playback volumes! */
+	HDA_CODEC_MUTE("PCM Playback Switch", 0x03, 0x0, HDA_OUTPUT), /* front */
+	HDA_CODEC_MUTE("Surround Playback Switch", 0x04, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x05, 1, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x05, 2, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Side Playback Switch", 0x06, 0x0, HDA_OUTPUT),
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		/* The multiple "Capture Source" controls confuse alsamixer
+		 * So call somewhat different..
+		 * FIXME: the controls appear in the "playback" view!
+		 */
+		/* .name = "Capture Source", */
+		.name = "Input Source",
+		.count = 2,
+		.info = cmi_mux_enum_info,
+		.get = cmi_mux_enum_get,
+		.put = cmi_mux_enum_put,
+	},
+	HDA_CODEC_VOLUME("Capture Volume", 0x08, 0, HDA_INPUT),
+	HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0, HDA_INPUT),
+	HDA_CODEC_MUTE("Capture Switch", 0x08, 0, HDA_INPUT),
+	HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0, HDA_INPUT),
+	HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x23, 0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x23, 0, HDA_OUTPUT),
+	{ } /* end */
+};
+
+/*
+ * shared I/O pins
+ */
+static snd_kcontrol_new_t cmi9880_ch_mode_mixer[] = {
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Channel Mode",
+		.info = cmi_ch_mode_info,
+		.get = cmi_ch_mode_get,
+		.put = cmi_ch_mode_put,
+	},
+	{ } /* end */
+};
+
+/* AUD-in selections:
+ * 0x0b 0x0c 0x0d 0x0e 0x0f 0x10 0x11 0x1f 0x20
+ */
+static struct hda_input_mux cmi9880_basic_mux = {
+	.num_items = 4,
+	.items = {
+		{ "Front Mic", 0x5 },
+		{ "Rear Mic", 0x2 },
+		{ "Line", 0x1 },
+		{ "CD", 0x7 },
+	}
+};
+
+static struct hda_input_mux cmi9880_no_line_mux = {
+	.num_items = 3,
+	.items = {
+		{ "Front Mic", 0x5 },
+		{ "Rear Mic", 0x2 },
+		{ "CD", 0x7 },
+	}
+};
+
+/* front, rear, clfe, rear_surr */
+static hda_nid_t cmi9880_dac_nids[4] = {
+	0x03, 0x04, 0x05, 0x06
+};
+/* ADC0, ADC1 */
+static hda_nid_t cmi9880_adc_nids[2] = {
+	0x08, 0x09
+};
+
+#define CMI_DIG_OUT_NID	0x07
+#define CMI_DIG_IN_NID	0x0a
+
+/*
+ */
+static struct hda_verb cmi9880_basic_init[] = {
+	/* port-D for line out (rear panel) */
+	{ 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
+	/* port-E for HP out (front panel) */
+	{ 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
+	/* route front PCM to HP */
+	{ 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 },
+	/* port-A for surround (rear panel) */
+	{ 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
+	/* port-G for CLFE (rear panel) */
+	{ 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
+	/* port-H for side (rear panel) */
+	{ 0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
+	/* port-C for line-in (rear panel) */
+	{ 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
+	/* port-B for mic-in (rear panel) with vref */
+	{ 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
+	/* port-F for mic-in (front panel) with vref */
+	{ 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
+	/* CD-in */
+	{ 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
+	/* route front mic to ADC1/2 */
+	{ 0x08, AC_VERB_SET_CONNECT_SEL, 0x05 },
+	{ 0x09, AC_VERB_SET_CONNECT_SEL, 0x05 },
+	{} /* terminator */
+};
+
+static struct hda_verb cmi9880_allout_init[] = {
+	/* port-D for line out (rear panel) */
+	{ 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
+	/* port-E for HP out (front panel) */
+	{ 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
+	/* route front PCM to HP */
+	{ 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 },
+	/* port-A for side (rear panel) */
+	{ 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
+	/* port-G for CLFE (rear panel) */
+	{ 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
+	/* port-C for surround (rear panel) */
+	{ 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
+	/* port-B for mic-in (rear panel) with vref */
+	{ 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
+	/* port-F for mic-in (front panel) with vref */
+	{ 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
+	/* CD-in */
+	{ 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
+	/* route front mic to ADC1/2 */
+	{ 0x08, AC_VERB_SET_CONNECT_SEL, 0x05 },
+	{ 0x09, AC_VERB_SET_CONNECT_SEL, 0x05 },
+	{} /* terminator */
+};
+
+/*
+ */
+static int cmi9880_build_controls(struct hda_codec *codec)
+{
+	struct cmi_spec *spec = codec->spec;
+	int err;
+
+	err = snd_hda_add_new_ctls(codec, cmi9880_basic_mixer);
+	if (err < 0)
+		return err;
+	if (spec->surr_switch) {
+		err = snd_hda_add_new_ctls(codec, cmi9880_ch_mode_mixer);
+		if (err < 0)
+			return err;
+	}
+	if (spec->multiout.dig_out_nid) {
+		err = snd_hda_create_spdif_out_ctls(codec, spec->multiout.dig_out_nid);
+		if (err < 0)
+			return err;
+	}
+	if (spec->dig_in_nid) {
+		err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid);
+		if (err < 0)
+			return err;
+	}
+	return 0;
+}
+
+static int cmi9880_init(struct hda_codec *codec)
+{
+	struct cmi_spec *spec = codec->spec;
+	if (spec->board_config == CMI_ALLOUT)
+		snd_hda_sequence_write(codec, cmi9880_allout_init);
+	else
+		snd_hda_sequence_write(codec, cmi9880_basic_init);
+	return 0;
+}
+
+#ifdef CONFIG_PM
+/*
+ * resume
+ */
+static int cmi9880_resume(struct hda_codec *codec)
+{
+	struct cmi_spec *spec = codec->spec;
+
+	cmi9880_init(codec);
+	snd_hda_resume_ctls(codec, cmi9880_basic_mixer);
+	if (spec->surr_switch)
+		snd_hda_resume_ctls(codec, cmi9880_ch_mode_mixer);
+	if (spec->multiout.dig_out_nid)
+		snd_hda_resume_spdif_out(codec);
+	if (spec->dig_in_nid)
+		snd_hda_resume_spdif_in(codec);
+
+	return 0;
+}
+#endif
+
+/*
+ * Analog playback callbacks
+ */
+static int cmi9880_playback_pcm_open(struct hda_pcm_stream *hinfo,
+				     struct hda_codec *codec,
+				     snd_pcm_substream_t *substream)
+{
+	struct cmi_spec *spec = codec->spec;
+	return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream);
+}
+
+static int cmi9880_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
+					struct hda_codec *codec,
+					unsigned int stream_tag,
+					unsigned int format,
+					snd_pcm_substream_t *substream)
+{
+	struct cmi_spec *spec = codec->spec;
+	return snd_hda_multi_out_analog_prepare(codec, &spec->multiout, stream_tag,
+						format, substream);
+}
+
+static int cmi9880_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
+				       struct hda_codec *codec,
+				       snd_pcm_substream_t *substream)
+{
+	struct cmi_spec *spec = codec->spec;
+	return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
+}
+
+/*
+ * Digital out
+ */
+static int cmi9880_dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
+					 struct hda_codec *codec,
+					 snd_pcm_substream_t *substream)
+{
+	struct cmi_spec *spec = codec->spec;
+	return snd_hda_multi_out_dig_open(codec, &spec->multiout);
+}
+
+static int cmi9880_dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
+					  struct hda_codec *codec,
+					  snd_pcm_substream_t *substream)
+{
+	struct cmi_spec *spec = codec->spec;
+	return snd_hda_multi_out_dig_close(codec, &spec->multiout);
+}
+
+/*
+ * Analog capture
+ */
+static int cmi9880_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
+				      struct hda_codec *codec,
+				      unsigned int stream_tag,
+				      unsigned int format,
+				      snd_pcm_substream_t *substream)
+{
+	struct cmi_spec *spec = codec->spec;
+
+	snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number],
+				   stream_tag, 0, format);
+	return 0;
+}
+
+static int cmi9880_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
+				      struct hda_codec *codec,
+				      snd_pcm_substream_t *substream)
+{
+	struct cmi_spec *spec = codec->spec;
+
+	snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number], 0, 0, 0);
+	return 0;
+}
+
+
+/*
+ */
+static struct hda_pcm_stream cmi9880_pcm_analog_playback = {
+	.substreams = 1,
+	.channels_min = 2,
+	.channels_max = 8,
+	.nid = 0x03, /* NID to query formats and rates */
+	.ops = {
+		.open = cmi9880_playback_pcm_open,
+		.prepare = cmi9880_playback_pcm_prepare,
+		.cleanup = cmi9880_playback_pcm_cleanup
+	},
+};
+
+static struct hda_pcm_stream cmi9880_pcm_analog_capture = {
+	.substreams = 2,
+	.channels_min = 2,
+	.channels_max = 2,
+	.nid = 0x08, /* NID to query formats and rates */
+	.ops = {
+		.prepare = cmi9880_capture_pcm_prepare,
+		.cleanup = cmi9880_capture_pcm_cleanup
+	},
+};
+
+static struct hda_pcm_stream cmi9880_pcm_digital_playback = {
+	.substreams = 1,
+	.channels_min = 2,
+	.channels_max = 2,
+	/* NID is set in cmi9880_build_pcms */
+	.ops = {
+		.open = cmi9880_dig_playback_pcm_open,
+		.close = cmi9880_dig_playback_pcm_close
+	},
+};
+
+static struct hda_pcm_stream cmi9880_pcm_digital_capture = {
+	.substreams = 1,
+	.channels_min = 2,
+	.channels_max = 2,
+	/* NID is set in cmi9880_build_pcms */
+};
+
+static int cmi9880_build_pcms(struct hda_codec *codec)
+{
+	struct cmi_spec *spec = codec->spec;
+	struct hda_pcm *info = spec->pcm_rec;
+
+	codec->num_pcms = 1;
+	codec->pcm_info = info;
+
+	info->name = "CMI9880";
+	info->stream[SNDRV_PCM_STREAM_PLAYBACK] = cmi9880_pcm_analog_playback;
+	info->stream[SNDRV_PCM_STREAM_CAPTURE] = cmi9880_pcm_analog_capture;
+
+	if (spec->multiout.dig_out_nid || spec->dig_in_nid) {
+		codec->num_pcms++;
+		info++;
+		info->name = "CMI9880 Digital";
+		if (spec->multiout.dig_out_nid) {
+			info->stream[SNDRV_PCM_STREAM_PLAYBACK] = cmi9880_pcm_digital_playback;
+			info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid;
+		}
+		if (spec->dig_in_nid) {
+			info->stream[SNDRV_PCM_STREAM_CAPTURE] = cmi9880_pcm_digital_capture;
+			info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->dig_in_nid;
+		}
+	}
+
+	return 0;
+}
+
+static void cmi9880_free(struct hda_codec *codec)
+{
+	kfree(codec->spec);
+}
+
+/*
+ */
+
+static struct hda_board_config cmi9880_cfg_tbl[] = {
+	{ .modelname = "minimal", .config = CMI_MINIMAL },
+	{ .modelname = "min_fp", .config = CMI_MIN_FP },
+	{ .modelname = "full", .config = CMI_FULL },
+	{ .modelname = "full_dig", .config = CMI_FULL_DIG },
+	{ .modelname = "allout", .config = CMI_ALLOUT },
+	{} /* terminator */
+};
+
+static struct hda_codec_ops cmi9880_patch_ops = {
+	.build_controls = cmi9880_build_controls,
+	.build_pcms = cmi9880_build_pcms,
+	.init = cmi9880_init,
+	.free = cmi9880_free,
+#ifdef CONFIG_PM
+	.resume = cmi9880_resume,
+#endif
+};
+
+static int patch_cmi9880(struct hda_codec *codec)
+{
+	struct cmi_spec *spec;
+
+	spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
+	if (spec == NULL)
+		return -ENOMEM;
+
+	codec->spec = spec;
+	spec->board_config = snd_hda_check_board_config(codec, cmi9880_cfg_tbl);
+	if (spec->board_config < 0) {
+		snd_printd(KERN_INFO "hda_codec: Unknown model for CMI9880\n");
+		spec->board_config = CMI_MINIMAL;
+	}
+
+	switch (spec->board_config) {
+	case CMI_MINIMAL:
+	case CMI_MIN_FP:
+		spec->surr_switch = 1;
+		if (spec->board_config == CMI_MINIMAL)
+			spec->num_ch_modes = 2;
+		else {
+			spec->front_panel = 1;
+			spec->num_ch_modes = 3;
+		}
+		spec->channel_modes = cmi9880_channel_modes;
+		spec->multiout.max_channels = cmi9880_channel_modes[0].channels;
+		spec->input_mux = &cmi9880_basic_mux;
+		break;
+	case CMI_FULL:
+	case CMI_FULL_DIG:
+		spec->front_panel = 1;
+		spec->multiout.max_channels = 8;
+		spec->input_mux = &cmi9880_basic_mux;
+		if (spec->board_config == CMI_FULL_DIG) {
+			spec->multiout.dig_out_nid = CMI_DIG_OUT_NID;
+			spec->dig_in_nid = CMI_DIG_IN_NID;
+		}
+		break;
+	case CMI_ALLOUT:
+		spec->front_panel = 1;
+		spec->multiout.max_channels = 8;
+		spec->no_line_in = 1;
+		spec->input_mux = &cmi9880_no_line_mux;
+		spec->multiout.dig_out_nid = CMI_DIG_OUT_NID;
+		break;
+	}
+
+	spec->multiout.num_dacs = 4;
+	spec->multiout.dac_nids = cmi9880_dac_nids;
+
+	spec->adc_nids = cmi9880_adc_nids;
+
+	codec->patch_ops = cmi9880_patch_ops;
+
+	return 0;
+}
+
+/*
+ * patch entries
+ */
+struct hda_codec_preset snd_hda_preset_cmedia[] = {
+ 	{ .id = 0x434d4980, .name = "CMI9880", .patch = patch_cmi9880 },
+	{} /* terminator */
+};
diff -Nru a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/sound/pci/hda/patch_realtek.c	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,1492 @@
+/*
+ * Universal Interface for Intel High Definition Audio Codec
+ *
+ * HD audio interface patch for ALC 260/880/882 codecs
+ *
+ * Copyright (c) 2004 PeiSen Hou <pshou@realtek.com.tw>
+ *                    Takashi Iwai <tiwai@suse.de>
+ *
+ *  This driver 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 driver is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ */
+
+#include <sound/driver.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/pci.h>
+#include <sound/core.h>
+#include "hda_codec.h"
+#include "hda_local.h"
+
+
+/* ALC880 board config type */
+enum {
+	ALC880_MINIMAL,
+	ALC880_3ST,
+	ALC880_3ST_DIG,
+	ALC880_5ST,
+	ALC880_5ST_DIG,
+	ALC880_W810,
+};
+
+struct alc_spec {
+	/* codec parameterization */
+	unsigned int front_panel: 1;
+
+	snd_kcontrol_new_t* mixers[2];
+	unsigned int num_mixers;
+
+	struct hda_verb *init_verbs;
+
+	char* stream_name_analog;
+	struct hda_pcm_stream *stream_analog_playback;
+	struct hda_pcm_stream *stream_analog_capture;
+
+	char* stream_name_digital;
+	struct hda_pcm_stream *stream_digital_playback;
+	struct hda_pcm_stream *stream_digital_capture;
+
+	/* playback */
+	struct hda_multi_out multiout;
+
+	/* capture */
+	unsigned int num_adc_nids;
+	hda_nid_t *adc_nids;
+	hda_nid_t dig_in_nid;
+
+	/* capture source */
+	const struct hda_input_mux *input_mux;
+	unsigned int cur_mux[3];
+
+	/* channel model */
+	const struct alc_channel_mode *channel_mode;
+	int num_channel_mode;
+
+	/* PCM information */
+	struct hda_pcm pcm_rec[2];
+};
+
+/* DAC/ADC assignment */
+
+static hda_nid_t alc880_dac_nids[4] = {
+	/* front, rear, clfe, rear_surr */
+	0x02, 0x05, 0x04, 0x03
+};
+
+static hda_nid_t alc880_w810_dac_nids[3] = {
+	/* front, rear/surround, clfe */
+	0x02, 0x03, 0x04
+};
+
+static hda_nid_t alc880_adc_nids[3] = {
+	/* ADC0-2 */
+	0x07, 0x08, 0x09,
+};
+
+#define ALC880_DIGOUT_NID	0x06
+#define ALC880_DIGIN_NID	0x0a
+
+static hda_nid_t alc260_dac_nids[1] = {
+	/* front */
+	0x02,
+};
+
+static hda_nid_t alc260_adc_nids[2] = {
+	/* ADC0-1 */
+	0x04, 0x05,
+};
+
+#define ALC260_DIGOUT_NID	0x03
+#define ALC260_DIGIN_NID	0x06
+
+static struct hda_input_mux alc880_capture_source = {
+	.num_items = 4,
+	.items = {
+		{ "Mic", 0x0 },
+		{ "Front Mic", 0x3 },
+		{ "Line", 0x2 },
+		{ "CD", 0x4 },
+	},
+};
+
+static struct hda_input_mux alc260_capture_source = {
+	.num_items = 4,
+	.items = {
+		{ "Mic", 0x0 },
+		{ "Front Mic", 0x1 },
+		{ "Line", 0x2 },
+		{ "CD", 0x4 },
+	},
+};
+
+/*
+ * input MUX handling
+ */
+static int alc_mux_enum_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+{
+	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct alc_spec *spec = codec->spec;
+	return snd_hda_input_mux_info(spec->input_mux, uinfo);
+}
+
+static int alc_mux_enum_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct alc_spec *spec = codec->spec;
+	unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
+
+	ucontrol->value.enumerated.item[0] = spec->cur_mux[adc_idx];
+	return 0;
+}
+
+static int alc_mux_enum_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct alc_spec *spec = codec->spec;
+	unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
+	return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol,
+				     spec->adc_nids[adc_idx], &spec->cur_mux[adc_idx]);
+}
+
+/*
+ * channel mode setting
+ */
+struct alc_channel_mode {
+	int channels;
+	const struct hda_verb *sequence;
+};
+
+
+/*
+ * channel source setting (2/6 channel selection for 3-stack)
+ */
+
+/*
+ * set the path ways for 2 channel output
+ * need to set the codec line out and mic 1 pin widgets to inputs
+ */
+static struct hda_verb alc880_threestack_ch2_init[] = {
+	/* set pin widget 1Ah (line in) for input */
+	{ 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
+	/* set pin widget 18h (mic1) for input, for mic also enable the vref */
+	{ 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
+	/* mute the output for Line In PW */
+	{ 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080 },
+	/* mute for Mic1 PW */
+	{ 0x18, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080 },
+	{ } /* end */
+};
+
+/*
+ * 6ch mode
+ * need to set the codec line out and mic 1 pin widgets to outputs
+ */
+static struct hda_verb alc880_threestack_ch6_init[] = {
+	/* set pin widget 1Ah (line in) for output */
+	{ 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
+	/* set pin widget 18h (mic1) for output */
+	{ 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
+	/* unmute the output for Line In PW */
+	{ 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000 },
+	/* unmute for Mic1 PW */
+	{ 0x18, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000 },
+	/* for rear channel output using Line In 1
+	 * set select widget connection (nid = 0x12) - to summer node
+	 * for rear NID = 0x0f...offset 3 in connection list
+	 */
+	{ 0x12, AC_VERB_SET_CONNECT_SEL, 0x3 },
+	/* for Mic1 - retask for center/lfe */
+	/* set select widget connection (nid = 0x10) - to summer node for
+	 * front CLFE NID = 0x0e...offset 2 in connection list
+	 */
+	{ 0x10, AC_VERB_SET_CONNECT_SEL, 0x2 },
+	{ } /* end */
+};
+
+static struct alc_channel_mode alc880_threestack_modes[2] = {
+	{ 2, alc880_threestack_ch2_init },
+	{ 6, alc880_threestack_ch6_init },
+};
+
+
+/*
+ * channel source setting (6/8 channel selection for 5-stack)
+ */
+
+/* set the path ways for 6 channel output
+ * need to set the codec line out and mic 1 pin widgets to inputs
+ */
+static struct hda_verb alc880_fivestack_ch6_init[] = {
+	/* set pin widget 1Ah (line in) for input */
+	{ 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
+	/* mute the output for Line In PW */
+	{ 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080 },
+	{ } /* end */
+};
+
+/* need to set the codec line out and mic 1 pin widgets to outputs */
+static struct hda_verb alc880_fivestack_ch8_init[] = {
+	/* set pin widget 1Ah (line in) for output */
+	{ 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
+	/* unmute the output for Line In PW */
+	{ 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000 },
+	/* output for surround channel output using Line In 1 */
+	/* set select widget connection (nid = 0x12) - to summer node
+	 * for surr_rear NID = 0x0d...offset 1 in connection list
+	 */
+	{ 0x12, AC_VERB_SET_CONNECT_SEL, 0x1 },
+	{ } /* end */
+};
+
+static struct alc_channel_mode alc880_fivestack_modes[2] = {
+	{ 6, alc880_fivestack_ch6_init },
+	{ 8, alc880_fivestack_ch8_init },
+};
+
+/*
+ * channel source setting for W810 system
+ *
+ * W810 has rear IO for:
+ * Front (DAC 02)
+ * Surround (DAC 03)
+ * Center/LFE (DAC 04)
+ * Digital out (06)
+ *
+ * The system also has a pair of internal speakers, and a headphone jack.
+ * These are both connected to Line2 on the codec, hence to DAC 02.
+ * 
+ * There is a variable resistor to control the speaker or headphone
+ * volume. This is a hardware-only device without a software API.
+ *
+ * Plugging headphones in will disable the internal speakers. This is
+ * implemented in hardware, not via the driver using jack sense. In
+ * a similar fashion, plugging into the rear socket marked "front" will
+ * disable both the speakers and headphones.
+ *
+ * For input, there's a microphone jack, and an "audio in" jack.
+ * These may not do anything useful with this driver yet, because I
+ * haven't setup any initialization verbs for these yet...
+ */
+
+static struct alc_channel_mode alc880_w810_modes[1] = {
+	{ 6, NULL }
+};
+
+/*
+ */
+static int alc880_ch_mode_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
+{
+	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct alc_spec *spec = codec->spec;
+
+	snd_assert(spec->channel_mode, return -ENXIO);
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+	uinfo->count = 1;
+	uinfo->value.enumerated.items = 2;
+	if (uinfo->value.enumerated.item >= 2)
+		uinfo->value.enumerated.item = 1;
+	sprintf(uinfo->value.enumerated.name, "%dch",
+		spec->channel_mode[uinfo->value.enumerated.item].channels);
+	return 0;
+}
+
+static int alc880_ch_mode_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct alc_spec *spec = codec->spec;
+
+	snd_assert(spec->channel_mode, return -ENXIO);
+	ucontrol->value.enumerated.item[0] =
+		(spec->multiout.max_channels == spec->channel_mode[0].channels) ? 0 : 1;
+	return 0;
+}
+
+static int alc880_ch_mode_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct alc_spec *spec = codec->spec;
+	int mode;
+
+	snd_assert(spec->channel_mode, return -ENXIO);
+	mode = ucontrol->value.enumerated.item[0] ? 1 : 0;
+	if (spec->multiout.max_channels == spec->channel_mode[mode].channels &&
+	    ! codec->in_resume)
+		return 0;
+
+	/* change the current channel setting */
+	spec->multiout.max_channels = spec->channel_mode[mode].channels;
+	if (spec->channel_mode[mode].sequence)
+		snd_hda_sequence_write(codec, spec->channel_mode[mode].sequence);
+
+	return 1;
+}
+
+
+/*
+ */
+
+/* 3-stack mode
+ * Pin assignment: Front=0x14, Line-In/Rear=0x1a, Mic/CLFE=0x18, F-Mic=0x1b
+ *                 HP=0x19
+ */
+static snd_kcontrol_new_t alc880_base_mixer[] = {
+	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("Surround Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Surround Playback Switch", 0x1a, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x18, 1, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x18, 2, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
+	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
+	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
+	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x3, HDA_INPUT),
+	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x3, HDA_INPUT),
+	HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
+	HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
+	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Headphone Playback Switch", 0x19, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("Capture Volume", 0x07, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("Capture Switch", 0x07, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x08, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x08, 0x0, HDA_INPUT),
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		/* The multiple "Capture Source" controls confuse alsamixer
+		 * So call somewhat different..
+		 * FIXME: the controls appear in the "playback" view!
+		 */
+		/* .name = "Capture Source", */
+		.name = "Input Source",
+		.count = 2,
+		.info = alc_mux_enum_info,
+		.get = alc_mux_enum_get,
+		.put = alc_mux_enum_put,
+	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Channel Mode",
+		.info = alc880_ch_mode_info,
+		.get = alc880_ch_mode_get,
+		.put = alc880_ch_mode_put,
+	},
+	{ } /* end */
+};
+
+/* 5-stack mode
+ * Pin assignment: Front=0x14, Rear=0x17, CLFE=0x16
+ *                 Line-In/Side=0x1a, Mic=0x18, F-Mic=0x1b, HP=0x19
+ */
+static snd_kcontrol_new_t alc880_five_stack_mixer[] = {
+	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("Surround Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Surround Playback Switch", 0x17, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x16, 1, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x16, 2, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("Side Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Side Playback Switch", 0x1a, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
+	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
+	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
+	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x3, HDA_INPUT),
+	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x3, HDA_INPUT),
+	HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
+	HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
+	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Headphone Playback Switch", 0x19, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("Capture Volume", 0x07, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("Capture Switch", 0x07, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x08, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x08, 0x0, HDA_INPUT),
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		/* The multiple "Capture Source" controls confuse alsamixer
+		 * So call somewhat different..
+		 * FIXME: the controls appear in the "playback" view!
+		 */
+		/* .name = "Capture Source", */
+		.name = "Input Source",
+		.count = 2,
+		.info = alc_mux_enum_info,
+		.get = alc_mux_enum_get,
+		.put = alc_mux_enum_put,
+	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Channel Mode",
+		.info = alc880_ch_mode_info,
+		.get = alc880_ch_mode_get,
+		.put = alc880_ch_mode_put,
+	},
+	{ } /* end */
+};
+
+static snd_kcontrol_new_t alc880_w810_base_mixer[] = {
+	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Surround Playback Switch", 0x15, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x16, 1, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x16, 2, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("Capture Volume", 0x07, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("Capture Switch", 0x07, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x08, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x08, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x09, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x09, 0x0, HDA_INPUT),
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		/* The multiple "Capture Source" controls confuse alsamixer
+		 * So call somewhat different..
+		 * FIXME: the controls appear in the "playback" view!
+		 */
+		/* .name = "Capture Source", */
+		.name = "Input Source",
+		.count = 3,
+		.info = alc_mux_enum_info,
+		.get = alc_mux_enum_get,
+		.put = alc_mux_enum_put,
+	},
+	{ } /* end */
+};
+
+/*
+ */
+static int alc_build_controls(struct hda_codec *codec)
+{
+	struct alc_spec *spec = codec->spec;
+	int err;
+	int i;
+
+	for (i = 0; i < spec->num_mixers; i++) {
+		err = snd_hda_add_new_ctls(codec, spec->mixers[i]);
+		if (err < 0)
+			return err;
+	}
+
+	if (spec->multiout.dig_out_nid) {
+		err = snd_hda_create_spdif_out_ctls(codec, spec->multiout.dig_out_nid);
+		if (err < 0)
+			return err;
+	}
+	if (spec->dig_in_nid) {
+		err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid);
+		if (err < 0)
+			return err;
+	}
+	return 0;
+}
+
+/*
+ * initialize the codec volumes, etc
+ */
+
+static struct hda_verb alc880_init_verbs_three_stack[] = {
+	/* Line In pin widget for input */
+	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
+	/* CD pin widget for input */
+	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
+	/* Mic1 (rear panel) pin widget for input and vref at 80% */
+	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
+	/* Mic2 (front panel) pin widget for input and vref at 80% */
+	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
+	/* unmute amp left and right */
+	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000},
+	/* set connection select to line in (default select for this ADC) */
+	{0x07, AC_VERB_SET_CONNECT_SEL, 0x02},
+	/* unmute front mixer amp left (volume = 0) */
+	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
+	/* mute pin widget amp left and right (no gain on this amp) */
+	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
+	/* unmute rear mixer amp left and right (volume = 0) */
+	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
+	/* mute pin widget amp left and right (no gain on this amp) */
+	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
+	/* unmute rear mixer amp left and right (volume = 0) */
+	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
+	/* mute pin widget amp left and right (no gain on this amp) */
+	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
+
+	/* using rear surround as the path for headphone output */
+	/* unmute rear surround mixer amp left and right (volume = 0) */
+	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
+	/* PASD 3 stack boards use the Mic 2 as the headphone output */
+	/* need to program the selector associated with the Mic 2 pin widget to
+	 * surround path (index 0x01) for headphone output */
+	{0x11, AC_VERB_SET_CONNECT_SEL, 0x01},
+	/* mute pin widget amp left and right (no gain on this amp) */
+	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
+	/* need to retask the Mic 2 pin widget to output */
+	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
+
+	/* Unmute input amps (CD, Line In, Mic 1 & Mic 2) for mixer widget(nid=0x0B)
+	 * to support the input path of analog loopback
+	 * Note: PASD motherboards uses the Line In 2 as the input for front panel
+	 * mic (mic 2)
+	 */
+	/* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 & Line In 2 = 0x03 */
+	/* unmute CD */
+	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))},
+	/* unmute Line In */
+	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))},
+	/* unmute Mic 1 */
+	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
+	/* unmute Line In 2 (for PASD boards Mic 2) */
+	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x03 << 8))},
+
+	/* Unmute input amps for the line out paths to support the output path of
+	 * analog loopback
+	 * the mixers on the output path has 2 inputs, one from the DAC and one
+	 * from the mixer
+	 */
+	/* Amp Indexes: DAC = 0x01 & mixer = 0x00 */
+	/* Unmute Front out path */
+	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
+	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
+	/* Unmute Surround (used as HP) out path */
+	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
+	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
+	/* Unmute C/LFE out path */
+	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
+	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x01 << 8))}, /* mute */
+	/* Unmute rear Surround out path */
+	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
+	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
+
+	{ }
+};
+
+static struct hda_verb alc880_init_verbs_five_stack[] = {
+	/* Line In pin widget for input */
+	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
+	/* CD pin widget for input */
+	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
+	/* Mic1 (rear panel) pin widget for input and vref at 80% */
+	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
+	/* Mic2 (front panel) pin widget for input and vref at 80% */
+	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
+	/* unmute amp left and right */
+	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000},
+	/* set connection select to line in (default select for this ADC) */
+	{0x07, AC_VERB_SET_CONNECT_SEL, 0x02},
+	/* unmute front mixer amp left and right (volume = 0) */
+	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
+	/* mute pin widget amp left and right (no gain on this amp) */
+	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
+	/* five rear and clfe */
+	/* unmute rear mixer amp left and right (volume = 0)  */
+	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
+	/* mute pin widget amp left and right (no gain on this amp) */
+	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
+	/* unmute clfe mixer amp left and right (volume = 0) */
+	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
+	/* mute pin widget amp left and right (no gain on this amp) */
+	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
+
+	/* using rear surround as the path for headphone output */
+	/* unmute rear surround mixer amp left and right (volume = 0) */
+	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
+	/* PASD 3 stack boards use the Mic 2 as the headphone output */
+	/* need to program the selector associated with the Mic 2 pin widget to
+	 * surround path (index 0x01) for headphone output
+	 */
+	{0x11, AC_VERB_SET_CONNECT_SEL, 0x01},
+	/* mute pin widget amp left and right (no gain on this amp) */
+	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
+	/* need to retask the Mic 2 pin widget to output */
+	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
+
+	/* Unmute input amps (CD, Line In, Mic 1 & Mic 2) for mixer
+	 * widget(nid=0x0B) to support the input path of analog loopback
+	 */
+	/* Note: PASD motherboards uses the Line In 2 as the input for front panel mic (mic 2) */
+	/* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 & Line In 2 = 0x03*/
+	/* unmute CD */
+	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))},
+	/* unmute Line In */
+	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))},
+	/* unmute Mic 1 */
+	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
+	/* unmute Line In 2 (for PASD boards Mic 2) */
+	{0x0b, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x03 << 8))},
+
+	/* Unmute input amps for the line out paths to support the output path of
+	 * analog loopback
+	 * the mixers on the output path has 2 inputs, one from the DAC and
+	 * one from the mixer
+	 */
+	/* Amp Indexes: DAC = 0x01 & mixer = 0x00 */
+	/* Unmute Front out path */
+	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
+	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
+	/* Unmute Surround (used as HP) out path */
+	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
+	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
+	/* Unmute C/LFE out path */
+	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
+	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x01 << 8))}, /* mute */
+	/* Unmute rear Surround out path */
+	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
+	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
+
+	{ }
+};
+
+static struct hda_verb alc880_w810_init_verbs[] = {
+	/* front channel selector/amp: input 0: DAC: unmuted, (no volume selection) */
+	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000},
+
+	/* front channel selector/amp: input 1: capture mix: muted, (no volume selection) */
+	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, 0x7180},
+
+	/* front channel selector/amp: output 0: unmuted, max volume */
+	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
+
+	/* front out pin: muted, (no volume selection)  */
+	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
+
+	/* front out pin: NOT headphone enable, out enable, vref disabled */
+	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
+
+
+	/* surround channel selector/amp: input 0: DAC: unmuted, (no volume selection) */
+	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000},
+
+	/* surround channel selector/amp: input 1: capture mix: muted, (no volume selection) */
+	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, 0x7180},
+
+	/* surround channel selector/amp: output 0: unmuted, max volume */
+	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
+
+	/* surround out pin: muted, (no volume selection)  */
+	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
+
+	/* surround out pin: NOT headphone enable, out enable, vref disabled */
+	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
+
+
+	/* c/lfe channel selector/amp: input 0: DAC: unmuted, (no volume selection) */
+	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000},
+
+	/* c/lfe channel selector/amp: input 1: capture mix: muted, (no volume selection) */
+	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, 0x7180},
+
+	/* c/lfe channel selector/amp: output 0: unmuted, max volume */
+	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
+
+	/* c/lfe out pin: muted, (no volume selection)  */
+	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
+
+	/* c/lfe out pin: NOT headphone enable, out enable, vref disabled */
+	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
+
+
+	/* hphone/speaker input selector: front DAC */
+	{0x13, AC_VERB_SET_CONNECT_SEL, 0x0},
+
+	/* hphone/speaker out pin: muted, (no volume selection)  */
+	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
+
+	/* hphone/speaker out pin: NOT headphone enable, out enable, vref disabled */
+	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
+
+
+	{ }
+};
+
+static int alc_init(struct hda_codec *codec)
+{
+	struct alc_spec *spec = codec->spec;
+	snd_hda_sequence_write(codec, spec->init_verbs);
+	return 0;
+}
+
+#ifdef CONFIG_PM
+/*
+ * resume
+ */
+static int alc_resume(struct hda_codec *codec)
+{
+	struct alc_spec *spec = codec->spec;
+	int i;
+
+	alc_init(codec);
+	for (i = 0; i < spec->num_mixers; i++) {
+		snd_hda_resume_ctls(codec, spec->mixers[i]);
+	}
+	if (spec->multiout.dig_out_nid)
+		snd_hda_resume_spdif_out(codec);
+	if (spec->dig_in_nid)
+		snd_hda_resume_spdif_in(codec);
+
+	return 0;
+}
+#endif
+
+/*
+ * Analog playback callbacks
+ */
+static int alc880_playback_pcm_open(struct hda_pcm_stream *hinfo,
+				    struct hda_codec *codec,
+				    snd_pcm_substream_t *substream)
+{
+	struct alc_spec *spec = codec->spec;
+	return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream);
+}
+
+static int alc880_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
+				       struct hda_codec *codec,
+				       unsigned int stream_tag,
+				       unsigned int format,
+				       snd_pcm_substream_t *substream)
+{
+	struct alc_spec *spec = codec->spec;
+	return snd_hda_multi_out_analog_prepare(codec, &spec->multiout, stream_tag,
+						format, substream);
+}
+
+static int alc880_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
+				       struct hda_codec *codec,
+				       snd_pcm_substream_t *substream)
+{
+	struct alc_spec *spec = codec->spec;
+	return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
+}
+
+/*
+ * Digital out
+ */
+static int alc880_dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
+					struct hda_codec *codec,
+					snd_pcm_substream_t *substream)
+{
+	struct alc_spec *spec = codec->spec;
+	return snd_hda_multi_out_dig_open(codec, &spec->multiout);
+}
+
+static int alc880_dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
+					 struct hda_codec *codec,
+					 snd_pcm_substream_t *substream)
+{
+	struct alc_spec *spec = codec->spec;
+	return snd_hda_multi_out_dig_close(codec, &spec->multiout);
+}
+
+/*
+ * Analog capture
+ */
+static int alc880_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
+				      struct hda_codec *codec,
+				      unsigned int stream_tag,
+				      unsigned int format,
+				      snd_pcm_substream_t *substream)
+{
+	struct alc_spec *spec = codec->spec;
+
+	snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number],
+				   stream_tag, 0, format);
+	return 0;
+}
+
+static int alc880_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
+				      struct hda_codec *codec,
+				      snd_pcm_substream_t *substream)
+{
+	struct alc_spec *spec = codec->spec;
+
+	snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number], 0, 0, 0);
+	return 0;
+}
+
+
+/*
+ */
+static struct hda_pcm_stream alc880_pcm_analog_playback = {
+	.substreams = 1,
+	.channels_min = 2,
+	.channels_max = 8,
+	.nid = 0x02, /* NID to query formats and rates */
+	.ops = {
+		.open = alc880_playback_pcm_open,
+		.prepare = alc880_playback_pcm_prepare,
+		.cleanup = alc880_playback_pcm_cleanup
+	},
+};
+
+static struct hda_pcm_stream alc880_pcm_analog_capture = {
+	.substreams = 2,
+	.channels_min = 2,
+	.channels_max = 2,
+	.nid = 0x07, /* NID to query formats and rates */
+	.ops = {
+		.prepare = alc880_capture_pcm_prepare,
+		.cleanup = alc880_capture_pcm_cleanup
+	},
+};
+
+static struct hda_pcm_stream alc880_pcm_digital_playback = {
+	.substreams = 1,
+	.channels_min = 2,
+	.channels_max = 2,
+	/* NID is set in alc_build_pcms */
+	.ops = {
+		.open = alc880_dig_playback_pcm_open,
+		.close = alc880_dig_playback_pcm_close
+	},
+};
+
+static struct hda_pcm_stream alc880_pcm_digital_capture = {
+	.substreams = 1,
+	.channels_min = 2,
+	.channels_max = 2,
+	/* NID is set in alc_build_pcms */
+};
+
+static int alc_build_pcms(struct hda_codec *codec)
+{
+	struct alc_spec *spec = codec->spec;
+	struct hda_pcm *info = spec->pcm_rec;
+	int i;
+
+	codec->num_pcms = 1;
+	codec->pcm_info = info;
+
+	info->name = spec->stream_name_analog;
+	info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *(spec->stream_analog_playback);
+	info->stream[SNDRV_PCM_STREAM_CAPTURE] = *(spec->stream_analog_capture);
+
+	info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = 0;
+	for (i = 0; i < spec->num_channel_mode; i++) {
+		if (spec->channel_mode[i].channels > info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max) {
+		    info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = spec->channel_mode[i].channels;
+		}
+	}
+
+	if (spec->multiout.dig_out_nid || spec->dig_in_nid) {
+		codec->num_pcms++;
+		info++;
+		info->name = spec->stream_name_digital;
+		if (spec->multiout.dig_out_nid) {
+			info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *(spec->stream_digital_playback);
+			info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid;
+		}
+		if (spec->dig_in_nid) {
+			info->stream[SNDRV_PCM_STREAM_CAPTURE] = *(spec->stream_digital_capture);
+			info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->dig_in_nid;
+		}
+	}
+
+	return 0;
+}
+
+static void alc_free(struct hda_codec *codec)
+{
+	kfree(codec->spec);
+}
+
+/*
+ */
+static struct hda_codec_ops alc_patch_ops = {
+	.build_controls = alc_build_controls,
+	.build_pcms = alc_build_pcms,
+	.init = alc_init,
+	.free = alc_free,
+#ifdef CONFIG_PM
+	.resume = alc_resume,
+#endif
+};
+
+/*
+ */
+
+static struct hda_board_config alc880_cfg_tbl[] = {
+	/* Back 3 jack, front 2 jack */
+	{ .modelname = "3stack", .config = ALC880_3ST },
+	{ .pci_vendor = 0x8086, .pci_device = 0xe200, .config = ALC880_3ST },
+	{ .pci_vendor = 0x8086, .pci_device = 0xe201, .config = ALC880_3ST },
+	{ .pci_vendor = 0x8086, .pci_device = 0xe202, .config = ALC880_3ST },
+	{ .pci_vendor = 0x8086, .pci_device = 0xe203, .config = ALC880_3ST },
+	{ .pci_vendor = 0x8086, .pci_device = 0xe204, .config = ALC880_3ST },
+	{ .pci_vendor = 0x8086, .pci_device = 0xe205, .config = ALC880_3ST },
+	{ .pci_vendor = 0x8086, .pci_device = 0xe206, .config = ALC880_3ST },
+	{ .pci_vendor = 0x8086, .pci_device = 0xe207, .config = ALC880_3ST },
+	{ .pci_vendor = 0x8086, .pci_device = 0xe208, .config = ALC880_3ST },
+	{ .pci_vendor = 0x8086, .pci_device = 0xe209, .config = ALC880_3ST },
+	{ .pci_vendor = 0x8086, .pci_device = 0xe20a, .config = ALC880_3ST },
+	{ .pci_vendor = 0x8086, .pci_device = 0xe20b, .config = ALC880_3ST },
+	{ .pci_vendor = 0x8086, .pci_device = 0xe20c, .config = ALC880_3ST },
+	{ .pci_vendor = 0x8086, .pci_device = 0xe20d, .config = ALC880_3ST },
+	{ .pci_vendor = 0x8086, .pci_device = 0xe20e, .config = ALC880_3ST },
+	{ .pci_vendor = 0x8086, .pci_device = 0xe20f, .config = ALC880_3ST },
+	{ .pci_vendor = 0x8086, .pci_device = 0xe210, .config = ALC880_3ST },
+	{ .pci_vendor = 0x8086, .pci_device = 0xe211, .config = ALC880_3ST },
+	{ .pci_vendor = 0x8086, .pci_device = 0xe214, .config = ALC880_3ST },
+	{ .pci_vendor = 0x8086, .pci_device = 0xe302, .config = ALC880_3ST },
+	{ .pci_vendor = 0x8086, .pci_device = 0xe303, .config = ALC880_3ST },
+	{ .pci_vendor = 0x8086, .pci_device = 0xe304, .config = ALC880_3ST },
+	{ .pci_vendor = 0x8086, .pci_device = 0xe306, .config = ALC880_3ST },
+	{ .pci_vendor = 0x8086, .pci_device = 0xe307, .config = ALC880_3ST },
+	{ .pci_vendor = 0x8086, .pci_device = 0xe404, .config = ALC880_3ST },
+	{ .pci_vendor = 0x8086, .pci_device = 0xa101, .config = ALC880_3ST },
+	{ .pci_vendor = 0x107b, .pci_device = 0x3031, .config = ALC880_3ST },
+	{ .pci_vendor = 0x107b, .pci_device = 0x4036, .config = ALC880_3ST },
+	{ .pci_vendor = 0x107b, .pci_device = 0x4037, .config = ALC880_3ST },
+	{ .pci_vendor = 0x107b, .pci_device = 0x4038, .config = ALC880_3ST },
+	{ .pci_vendor = 0x107b, .pci_device = 0x4040, .config = ALC880_3ST },
+	{ .pci_vendor = 0x107b, .pci_device = 0x4041, .config = ALC880_3ST },
+
+	/* Back 3 jack, front 2 jack (Internal add Aux-In) */
+	{ .pci_vendor = 0x1025, .pci_device = 0xe310, .config = ALC880_3ST },
+
+	/* Back 3 jack plus 1 SPDIF out jack, front 2 jack */
+	{ .modelname = "3stack-digout", .config = ALC880_3ST_DIG },
+	{ .pci_vendor = 0x8086, .pci_device = 0xe308, .config = ALC880_3ST_DIG },
+
+	/* Back 3 jack plus 1 SPDIF out jack, front 2 jack (Internal add Aux-In)*/
+	{ .pci_vendor = 0x8086, .pci_device = 0xe305, .config = ALC880_3ST_DIG },
+	{ .pci_vendor = 0x8086, .pci_device = 0xd402, .config = ALC880_3ST_DIG },
+	{ .pci_vendor = 0x1025, .pci_device = 0xe309, .config = ALC880_3ST_DIG },
+
+	/* Back 5 jack, front 2 jack */
+	{ .modelname = "5stack", .config = ALC880_5ST },
+	{ .pci_vendor = 0x107b, .pci_device = 0x3033, .config = ALC880_5ST },
+	{ .pci_vendor = 0x107b, .pci_device = 0x4039, .config = ALC880_5ST },
+	{ .pci_vendor = 0x107b, .pci_device = 0x3032, .config = ALC880_5ST },
+	{ .pci_vendor = 0x103c, .pci_device = 0x2a09, .config = ALC880_5ST },
+
+	/* Back 5 jack plus 1 SPDIF out jack, front 2 jack */
+	{ .modelname = "5stack-digout", .config = ALC880_5ST_DIG },
+	{ .pci_vendor = 0x8086, .pci_device = 0xe224, .config = ALC880_5ST_DIG },
+	{ .pci_vendor = 0x8086, .pci_device = 0xe400, .config = ALC880_5ST_DIG },
+	{ .pci_vendor = 0x8086, .pci_device = 0xe401, .config = ALC880_5ST_DIG },
+	{ .pci_vendor = 0x8086, .pci_device = 0xe402, .config = ALC880_5ST_DIG },
+	{ .pci_vendor = 0x8086, .pci_device = 0xd400, .config = ALC880_5ST_DIG },
+	{ .pci_vendor = 0x8086, .pci_device = 0xd401, .config = ALC880_5ST_DIG },
+	{ .pci_vendor = 0x8086, .pci_device = 0xa100, .config = ALC880_5ST_DIG },
+	{ .pci_vendor = 0x1565, .pci_device = 0x8202, .config = ALC880_5ST_DIG },
+
+	{ .modelname = "w810", .config = ALC880_W810 },
+	{ .pci_vendor = 0x161f, .pci_device = 0x203d, .config = ALC880_W810 },
+
+	{}
+};
+
+static int patch_alc880(struct hda_codec *codec)
+{
+	struct alc_spec *spec;
+	int board_config;
+
+	spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
+	if (spec == NULL)
+		return -ENOMEM;
+
+	codec->spec = spec;
+
+	board_config = snd_hda_check_board_config(codec, alc880_cfg_tbl);
+	if (board_config < 0) {
+		snd_printd(KERN_INFO "hda_codec: Unknown model for ALC880\n");
+		board_config = ALC880_MINIMAL;
+	}
+
+	switch (board_config) {
+	case ALC880_W810:
+		spec->mixers[spec->num_mixers] = alc880_w810_base_mixer;
+		spec->num_mixers++;
+		break;
+	case ALC880_5ST:
+	case ALC880_5ST_DIG:
+		spec->mixers[spec->num_mixers] = alc880_five_stack_mixer;
+		spec->num_mixers++;
+		break;
+	default:
+		spec->mixers[spec->num_mixers] = alc880_base_mixer;
+		spec->num_mixers++;
+		break;
+	}
+
+	switch (board_config) {
+	case ALC880_3ST_DIG:
+	case ALC880_5ST_DIG:
+	case ALC880_W810:
+		spec->multiout.dig_out_nid = ALC880_DIGOUT_NID;
+		break;
+	default:
+		break;
+	}
+
+	switch (board_config) {
+	case ALC880_3ST:
+	case ALC880_3ST_DIG:
+	case ALC880_5ST:
+	case ALC880_5ST_DIG:
+	case ALC880_W810:
+		spec->front_panel = 1;
+		break;
+	default:
+		break;
+	}
+
+	switch (board_config) {
+	case ALC880_5ST:
+	case ALC880_5ST_DIG:
+		spec->init_verbs = alc880_init_verbs_five_stack;
+		spec->channel_mode = alc880_fivestack_modes;
+		spec->num_channel_mode = ARRAY_SIZE(alc880_fivestack_modes);
+		break;
+	case ALC880_W810:
+		spec->init_verbs = alc880_w810_init_verbs;
+		spec->channel_mode = alc880_w810_modes;
+		spec->num_channel_mode = ARRAY_SIZE(alc880_w810_modes);
+		break;
+	default:
+		spec->init_verbs = alc880_init_verbs_three_stack;
+		spec->channel_mode = alc880_threestack_modes;
+		spec->num_channel_mode = ARRAY_SIZE(alc880_threestack_modes);
+		break;
+	}
+
+	spec->stream_name_analog = "ALC880 Analog";
+	spec->stream_analog_playback = &alc880_pcm_analog_playback;
+	spec->stream_analog_capture = &alc880_pcm_analog_capture;
+
+	spec->stream_name_digital = "ALC880 Digital";
+	spec->stream_digital_playback = &alc880_pcm_digital_playback;
+	spec->stream_digital_capture = &alc880_pcm_digital_capture;
+
+	spec->multiout.max_channels = spec->channel_mode[0].channels;
+
+	switch (board_config) {
+	case ALC880_W810:
+		spec->multiout.num_dacs = ARRAY_SIZE(alc880_w810_dac_nids);
+		spec->multiout.dac_nids = alc880_w810_dac_nids;
+		// No dedicated headphone socket - it's shared with built-in speakers.
+		break;
+	default:
+		spec->multiout.num_dacs = ARRAY_SIZE(alc880_dac_nids);
+		spec->multiout.dac_nids = alc880_dac_nids;
+		spec->multiout.hp_nid = 0x03; /* rear-surround NID */
+		break;
+	}
+
+	spec->input_mux = &alc880_capture_source;
+	spec->num_adc_nids = ARRAY_SIZE(alc880_adc_nids);
+	spec->adc_nids = alc880_adc_nids;
+
+	codec->patch_ops = alc_patch_ops;
+
+	return 0;
+}
+
+/*
+ * ALC260 support
+ */
+
+/*
+ * This is just place-holder, so there's something for alc_build_pcms to look
+ * at when it calculates the maximum number of channels. ALC260 has no mixer
+ * element which allows changing the channel mode, so the verb list is
+ * never used.
+ */
+static struct alc_channel_mode alc260_modes[1] = {
+	{ 2, NULL },
+};
+
+snd_kcontrol_new_t alc260_base_mixer[] = {
+	HDA_CODEC_VOLUME("Front Playback Volume", 0x08, 0x0, HDA_OUTPUT),
+	/* use LINE2 for the output */
+	/* HDA_CODEC_MUTE("Front Playback Switch", 0x0f, 0x0, HDA_OUTPUT), */
+	HDA_CODEC_MUTE("Front Playback Switch", 0x15, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT),
+	HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT),
+	HDA_CODEC_VOLUME("Line Playback Volume", 0x07, 0x02, HDA_INPUT),
+	HDA_CODEC_MUTE("Line Playback Switch", 0x07, 0x02, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Playback Volume", 0x07, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("Mic Playback Switch", 0x07, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x07, 0x01, HDA_INPUT),
+	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x07, 0x01, HDA_INPUT),
+	HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x07, 0x05, HDA_INPUT),
+	HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x07, 0x05, HDA_INPUT),
+	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x09, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Headphone Playback Switch", 0x10, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("Capture Volume", 0x04, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("Capture Switch", 0x04, 0x0, HDA_INPUT),
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Capture Source",
+		.info = alc_mux_enum_info,
+		.get = alc_mux_enum_get,
+		.put = alc_mux_enum_put,
+	},
+	{ } /* end */
+};
+
+static struct hda_verb alc260_init_verbs[] = {
+	/* Line In pin widget for input */
+	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
+	/* CD pin widget for input */
+	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
+	/* Mic1 (rear panel) pin widget for input and vref at 80% */
+	{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
+	/* Mic2 (front panel) pin widget for input and vref at 80% */
+	{0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
+	/* LINE-2 is used for line-out in rear */
+	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
+	/* select line-out */
+	{0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
+	/* LINE-OUT pin */
+	{0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
+	/* enable HP */
+	{0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
+	/* unmute amp left and right */
+	{0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000},
+	/* set connection select to line in (default select for this ADC) */
+	{0x04, AC_VERB_SET_CONNECT_SEL, 0x02},
+	/* unmute Line-Out mixer amp left and right (volume = 0) */
+	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
+	/* mute pin widget amp left and right (no gain on this amp) */
+	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
+	/* unmute HP mixer amp left and right (volume = 0) */
+	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
+	/* mute pin widget amp left and right (no gain on this amp) */
+	{0x10, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
+	/* mute LINE-2 out */
+	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
+	/* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 & Line In 2 = 0x03 */
+	/* unmute CD */
+	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))},
+	/* unmute Line In */
+	{0x07,  AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))},
+	/* unmute Mic */
+	{0x07,  AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
+	/* Amp Indexes: DAC = 0x01 & mixer = 0x00 */
+	/* Unmute Front out path */
+	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
+	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
+	/* Unmute Headphone out path */
+	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
+	{0x09, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
+	{ }
+};
+
+static struct hda_pcm_stream alc260_pcm_analog_playback = {
+	.substreams = 1,
+	.channels_min = 2,
+	.channels_max = 2,
+	.nid = 0x2,
+};
+
+static struct hda_pcm_stream alc260_pcm_analog_capture = {
+	.substreams = 1,
+	.channels_min = 2,
+	.channels_max = 2,
+	.nid = 0x4,
+};
+
+static int patch_alc260(struct hda_codec *codec)
+{
+	struct alc_spec *spec;
+
+	spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
+	if (spec == NULL)
+		return -ENOMEM;
+
+	codec->spec = spec;
+
+	spec->mixers[spec->num_mixers] = alc260_base_mixer;
+	spec->num_mixers++;
+
+	spec->init_verbs = alc260_init_verbs;
+	spec->channel_mode = alc260_modes;
+	spec->num_channel_mode = ARRAY_SIZE(alc260_modes);
+
+	spec->stream_name_analog = "ALC260 Analog";
+	spec->stream_analog_playback = &alc260_pcm_analog_playback;
+	spec->stream_analog_capture = &alc260_pcm_analog_capture;
+
+	spec->multiout.max_channels = spec->channel_mode[0].channels;
+	spec->multiout.num_dacs = ARRAY_SIZE(alc260_dac_nids);
+	spec->multiout.dac_nids = alc260_dac_nids;
+
+	spec->input_mux = &alc260_capture_source;
+	spec->num_adc_nids = ARRAY_SIZE(alc260_adc_nids);
+	spec->adc_nids = alc260_adc_nids;
+
+	codec->patch_ops = alc_patch_ops;
+
+	return 0;
+}
+
+/*
+ * ALC882 support
+ *
+ * ALC882 is almost identical with ALC880 but has cleaner and more flexible
+ * configuration.  Each pin widget can choose any input DACs and a mixer.
+ * Each ADC is connected from a mixer of all inputs.  This makes possible
+ * 6-channel independent captures.
+ *
+ * In addition, an independent DAC for the multi-playback (not used in this
+ * driver yet).
+ */
+
+static struct alc_channel_mode alc882_ch_modes[1] = {
+	{ 8, NULL }
+};
+
+static hda_nid_t alc882_dac_nids[4] = {
+	/* front, rear, clfe, rear_surr */
+	0x02, 0x03, 0x04, 0x05
+};
+
+static hda_nid_t alc882_adc_nids[3] = {
+	/* ADC0-2 */
+	0x07, 0x08, 0x09,
+};
+
+/* input MUX */
+/* FIXME: should be a matrix-type input source selection */
+
+static struct hda_input_mux alc882_capture_source = {
+	.num_items = 4,
+	.items = {
+		{ "Mic", 0x0 },
+		{ "Front Mic", 0x1 },
+		{ "Line", 0x2 },
+		{ "CD", 0x4 },
+	},
+};
+
+#define alc882_mux_enum_info alc_mux_enum_info
+#define alc882_mux_enum_get alc_mux_enum_get
+
+static int alc882_mux_enum_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
+{
+	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+	struct alc_spec *spec = codec->spec;
+	const struct hda_input_mux *imux = spec->input_mux;
+	unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
+	static hda_nid_t capture_mixers[3] = { 0x24, 0x23, 0x22 };
+	hda_nid_t nid = capture_mixers[adc_idx];
+	unsigned int *cur_val = &spec->cur_mux[adc_idx];
+	unsigned int i, idx;
+
+	idx = ucontrol->value.enumerated.item[0];
+	if (idx >= imux->num_items)
+		idx = imux->num_items - 1;
+	if (*cur_val == idx && ! codec->in_resume)
+		return 0;
+	for (i = 0; i < imux->num_items; i++) {
+		unsigned int v = (i == idx) ? 0x7000 : 0x7080;
+		snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
+				    v | (imux->items[i].index << 8));
+	}
+	*cur_val = idx;
+	return 1;
+}
+
+/* Pin assignment: Front=0x14, Rear=0x15, CLFE=0x16, Side=0x17
+ *                 Mic=0x18, Front Mic=0x19, Line-In=0x1a, HP=0x1b
+ */
+static snd_kcontrol_new_t alc882_base_mixer[] = {
+	HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Surround Playback Switch", 0x15, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x16, 1, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x16, 2, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Side Playback Switch", 0x17, 0x0, HDA_OUTPUT),
+	HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
+	HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
+	HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
+	HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
+	HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
+	HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
+	HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
+	HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
+	HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
+	HDA_CODEC_VOLUME("Capture Volume", 0x07, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE("Capture Switch", 0x07, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x08, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x08, 0x0, HDA_INPUT),
+	HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x09, 0x0, HDA_INPUT),
+	HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x09, 0x0, HDA_INPUT),
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		/* .name = "Capture Source", */
+		.name = "Input Source",
+		.count = 3,
+		.info = alc882_mux_enum_info,
+		.get = alc882_mux_enum_get,
+		.put = alc882_mux_enum_put,
+	},
+	{ } /* end */
+};
+
+static struct hda_verb alc882_init_verbs[] = {
+	/* Front mixer: unmute input/output amp left and right (volume = 0) */
+	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
+	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
+	/* Rear mixer */
+	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
+	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
+	/* CLFE mixer */
+	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
+	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
+	/* Side mixer */
+	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
+	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
+
+	/* Front Pin: to output mode */
+	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
+	/* Front Pin: mute amp left and right (no volume) */
+	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
+	/* select Front mixer (0x0c, index 0) */
+	{0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
+	/* Rear Pin */
+	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
+	/* Rear Pin: mute amp left and right (no volume) */
+	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
+	/* select Rear mixer (0x0d, index 1) */
+	{0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
+	/* CLFE Pin */
+	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
+	/* CLFE Pin: mute amp left and right (no volume) */
+	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
+	/* select CLFE mixer (0x0e, index 2) */
+	{0x16, AC_VERB_SET_CONNECT_SEL, 0x02},
+	/* Side Pin */
+	{0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
+	/* Side Pin: mute amp left and right (no volume) */
+	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
+	/* select Side mixer (0x0f, index 3) */
+	{0x17, AC_VERB_SET_CONNECT_SEL, 0x03},
+	/* Headphone Pin */
+	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
+	/* Headphone Pin: mute amp left and right (no volume) */
+	{0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
+	/* select Front mixer (0x0c, index 0) */
+	{0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
+	/* Mic (rear) pin widget for input and vref at 80% */
+	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
+	/* Front Mic pin widget for input and vref at 80% */
+	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
+	/* Line In pin widget for input */
+	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
+	/* CD pin widget for input */
+	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
+
+	/* FIXME: use matrix-type input source selection */
+	/* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
+	/* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
+	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
+	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
+	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
+	{0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
+	/* Input mixer2 */
+	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
+	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
+	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
+	{0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
+	/* Input mixer3 */
+	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
+	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
+	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
+	{0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
+	/* ADC1: unmute amp left and right */
+	{0x07, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000},
+	/* ADC2: unmute amp left and right */
+	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000},
+	/* ADC3: unmute amp left and right */
+	{0x08, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000},
+
+	/* Unmute front loopback */
+	{0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
+	/* Unmute rear loopback */
+	{0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
+	/* Mute CLFE loopback */
+	{0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x01 << 8))},
+	/* Unmute side loopback */
+	{0x0f, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
+
+	{ }
+};
+
+static int patch_alc882(struct hda_codec *codec)
+{
+	struct alc_spec *spec;
+
+	spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
+	if (spec == NULL)
+		return -ENOMEM;
+
+	codec->spec = spec;
+
+	spec->mixers[spec->num_mixers] = alc882_base_mixer;
+	spec->num_mixers++;
+
+	spec->multiout.dig_out_nid = ALC880_DIGOUT_NID;
+	spec->dig_in_nid = ALC880_DIGIN_NID;
+	spec->front_panel = 1;
+	spec->init_verbs = alc882_init_verbs;
+	spec->channel_mode = alc882_ch_modes;
+	spec->num_channel_mode = ARRAY_SIZE(alc882_ch_modes);
+
+	spec->stream_name_analog = "ALC882 Analog";
+	spec->stream_analog_playback = &alc880_pcm_analog_playback;
+	spec->stream_analog_capture = &alc880_pcm_analog_capture;
+
+	spec->stream_name_digital = "ALC882 Digital";
+	spec->stream_digital_playback = &alc880_pcm_digital_playback;
+	spec->stream_digital_capture = &alc880_pcm_digital_capture;
+
+	spec->multiout.max_channels = spec->channel_mode[0].channels;
+	spec->multiout.num_dacs = ARRAY_SIZE(alc882_dac_nids);
+	spec->multiout.dac_nids = alc882_dac_nids;
+
+	spec->input_mux = &alc882_capture_source;
+	spec->num_adc_nids = ARRAY_SIZE(alc882_adc_nids);
+	spec->adc_nids = alc882_adc_nids;
+
+	codec->patch_ops = alc_patch_ops;
+
+	return 0;
+}
+
+/*
+ * patch entries
+ */
+struct hda_codec_preset snd_hda_preset_realtek[] = {
+	{ .id = 0x10ec0260, .name = "ALC260", .patch = patch_alc260 },
+ 	{ .id = 0x10ec0880, .name = "ALC880", .patch = patch_alc880 },
+	{ .id = 0x10ec0882, .name = "ALC882", .patch = patch_alc882 },
+	{} /* terminator */
+};
diff -Nru a/sound/pci/ice1712/Makefile b/sound/pci/ice1712/Makefile
--- a/sound/pci/ice1712/Makefile	2005-03-11 12:51:42 -08:00
+++ b/sound/pci/ice1712/Makefile	2005-03-11 12:51:42 -08:00
@@ -5,7 +5,7 @@
 
 snd-ice17xx-ak4xxx-objs := ak4xxx.o
 snd-ice1712-objs := ice1712.o delta.o hoontech.o ews.o
-snd-ice1724-objs := ice1724.o amp.o revo.o aureon.o vt1720_mobo.o pontis.o prodigy192.o
+snd-ice1724-objs := ice1724.o amp.o revo.o aureon.o vt1720_mobo.o pontis.o prodigy192.o juli.o phase.o
 
 # Toplevel Module Dependency
 obj-$(CONFIG_SND_ICE1712) += snd-ice1712.o snd-ice17xx-ak4xxx.o
diff -Nru a/sound/pci/ice1712/ak4xxx.c b/sound/pci/ice1712/ak4xxx.c
--- a/sound/pci/ice1712/ak4xxx.c	2005-03-11 12:51:40 -08:00
+++ b/sound/pci/ice1712/ak4xxx.c	2005-03-11 12:51:40 -08:00
@@ -126,12 +126,16 @@
 {
 	struct snd_ak4xxx_private *priv;
 
-	priv = kmalloc(sizeof(*priv), GFP_KERNEL);
-	if (priv == NULL)
-		return -ENOMEM;
+	if (_priv != NULL) {
+		priv = kmalloc(sizeof(*priv), GFP_KERNEL);
+		if (priv == NULL)
+			return -ENOMEM;
+		*priv = *_priv;
+	} else {
+		priv = NULL;
+	}
 	*ak = *temp;
 	ak->card = ice->card;
-	*priv = *_priv;
         ak->private_value[0] = (unsigned long)priv;
 	ak->private_data[0] = ice;
 	if (ak->ops.lock == NULL)
diff -Nru a/sound/pci/ice1712/envy24ht.h b/sound/pci/ice1712/envy24ht.h
--- a/sound/pci/ice1712/envy24ht.h	2005-03-11 12:51:52 -08:00
+++ b/sound/pci/ice1712/envy24ht.h	2005-03-11 12:51:52 -08:00
@@ -106,7 +106,7 @@
 #define VT1724_REG_I2C_BYTE_ADDR	0x11	/* byte */
 #define VT1724_REG_I2C_DATA		0x12	/* byte */
 #define VT1724_REG_I2C_CTRL		0x13	/* byte */
-#define   VT1724_I2C_EEPROM		0x80	/* EEPROM exists */
+#define   VT1724_I2C_EEPROM		0x80	/* 1 = EEPROM exists */
 #define   VT1724_I2C_BUSY		0x01	/* busy bit */
 
 #define VT1724_REG_GPIO_DATA	0x14	/* word */
diff -Nru a/sound/pci/ice1712/ice1712.c b/sound/pci/ice1712/ice1712.c
--- a/sound/pci/ice1712/ice1712.c	2005-03-11 12:51:42 -08:00
+++ b/sound/pci/ice1712/ice1712.c	2005-03-11 12:51:42 -08:00
@@ -1014,21 +1014,9 @@
 static void snd_ice1712_set_pro_rate(ice1712_t *ice, unsigned int rate, int force)
 {
 	unsigned long flags;
-	unsigned char val;
+	unsigned char val, old;
 	unsigned int i;
 
-	spin_lock_irqsave(&ice->reg_lock, flags);
-	if (inb(ICEMT(ice, PLAYBACK_CONTROL)) & (ICE1712_CAPTURE_START_SHADOW|
-						 ICE1712_PLAYBACK_PAUSE|
-						 ICE1712_PLAYBACK_START)) {
-		spin_unlock_irqrestore(&ice->reg_lock, flags);
-		return;
-	}
-	if (!force && is_pro_rate_locked(ice)) {
-		spin_unlock_irqrestore(&ice->reg_lock, flags);
-		return;
-	}
-
 	switch (rate) {
 	case 8000: val = 6; break;
 	case 9600: val = 3; break;
@@ -1049,8 +1037,22 @@
 		rate = 48000;
 		break;
 	}
-	outb(val, ICEMT(ice, RATE));
 
+	spin_lock_irqsave(&ice->reg_lock, flags);
+	if (inb(ICEMT(ice, PLAYBACK_CONTROL)) & (ICE1712_CAPTURE_START_SHADOW|
+						 ICE1712_PLAYBACK_PAUSE|
+						 ICE1712_PLAYBACK_START)) {
+	      __out:
+		spin_unlock_irqrestore(&ice->reg_lock, flags);
+		return;
+	}
+	if (!force && is_pro_rate_locked(ice))
+		goto __out;
+
+        old = inb(ICEMT(ice, RATE));
+	if (!force && old == val)
+		goto __out;
+	outb(val, ICEMT(ice, RATE));
 	spin_unlock_irqrestore(&ice->reg_lock, flags);
 
 	if (ice->gpio.set_pro_rate)
@@ -2405,6 +2407,7 @@
 		udelay(200);
 		snd_ice1712_write(ice, ICE1712_IREG_CONSUMER_POWERDOWN, 0);
 	}
+	snd_ice1712_set_pro_rate(ice, 48000, 1);
 
 	return 0;
 }
@@ -2545,6 +2548,7 @@
 	ice->cs8427_timeout = cs8427_timeout;
 	spin_lock_init(&ice->reg_lock);
 	init_MUTEX(&ice->gpio_mutex);
+	init_MUTEX(&ice->i2c_mutex);
 	init_MUTEX(&ice->open_mutex);
 	ice->gpio.set_mask = snd_ice1712_set_gpio_mask;
 	ice->gpio.set_dir = snd_ice1712_set_gpio_dir;
diff -Nru a/sound/pci/ice1712/ice1712.h b/sound/pci/ice1712/ice1712.h
--- a/sound/pci/ice1712/ice1712.h	2005-03-11 12:51:41 -08:00
+++ b/sound/pci/ice1712/ice1712.h	2005-03-11 12:51:41 -08:00
@@ -27,6 +27,7 @@
 #include <sound/rawmidi.h>
 #include <sound/i2c.h>
 #include <sound/ak4xxx-adda.h>
+#include <sound/ak4114.h>
 #include <sound/pcm.h>
 
 
@@ -335,11 +336,13 @@
 
 	struct semaphore open_mutex;
 	snd_pcm_substream_t *pcm_reserved[4];
+	snd_pcm_hw_constraint_list_t *hw_rates; /* card-specific rate constraints */
 
 	unsigned int akm_codecs;
 	akm4xxx_t *akm;
 	struct snd_ice1712_spdif spdif;
 
+	struct semaphore i2c_mutex;	/* I2C mutex for ICE1724 registers */
 	snd_i2c_bus_t *i2c;		/* I2C bus */
 	snd_i2c_device_t *cs8427;	/* CS8427 I2C device */
 	unsigned int cs8427_timeout;	/* CS8427 reset timeout in HZ/100 */
@@ -355,12 +358,13 @@
 		unsigned int (*get_data)(ice1712_t *ice);
 		/* misc operators - move to another place? */
 		void (*set_pro_rate)(ice1712_t *ice, unsigned int rate);
+		void (*i2s_mclk_changed)(ice1712_t *ice);
 	} gpio;
 	struct semaphore gpio_mutex;
 
 	/* other board-specific data */
 	union {
-		/* additional i2c devices for EWS boards*/
+		/* additional i2c devices for EWS boards */
 		snd_i2c_device_t *i2cdevs[3];
 		/* AC97 register cache for Aureon */
 		struct aureon_spec {
@@ -375,6 +379,10 @@
 			unsigned int config;
 			unsigned short boxconfig[4];
 		} hoontech;
+		struct {
+			ak4114_t *ak4114;
+			unsigned int analog: 1;
+		} juli;
 	} spec;
 
 };
@@ -477,7 +485,7 @@
 	char *driver;
 	int (*chip_init)(ice1712_t *);
 	int (*build_controls)(ice1712_t *);
-	int no_mpu401: 1;
+	unsigned int no_mpu401: 1;
 	unsigned int eeprom_size;
 	unsigned char *eeprom_data;
 };
diff -Nru a/sound/pci/ice1712/ice1724.c b/sound/pci/ice1712/ice1724.c
--- a/sound/pci/ice1712/ice1724.c	2005-03-11 12:51:43 -08:00
+++ b/sound/pci/ice1712/ice1724.c	2005-03-11 12:51:43 -08:00
@@ -47,6 +47,8 @@
 #include "vt1720_mobo.h"
 #include "pontis.h"
 #include "prodigy192.h"
+#include "juli.h"
+#include "phase.h"
 
 
 MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
@@ -59,6 +61,8 @@
 	       VT1720_MOBO_DEVICE_DESC
 	       PONTIS_DEVICE_DESC
 	       PRODIGY192_DEVICE_DESC
+	       JULI_DEVICE_DESC
+	       PHASE_DEVICE_DESC
 		"{VIA,VT1720},"
 		"{VIA,VT1724},"
 		"{ICEnsemble,Generic ICE1724},"
@@ -401,23 +405,11 @@
 {
 	unsigned long flags;
 	unsigned char val, old;
-	unsigned int i;
+	unsigned int i, mclk_change;
 
 	if (rate > get_max_rate(ice))
 		return;
 
-	spin_lock_irqsave(&ice->reg_lock, flags);
-	if ((inb(ICEMT1724(ice, DMA_CONTROL)) & DMA_STARTS) || 
-	    (inb(ICEMT1724(ice, DMA_PAUSE)) & DMA_PAUSES)) {
-		/* running? we cannot change the rate now... */
-		spin_unlock_irqrestore(&ice->reg_lock, flags);
-		return;
-	}
-	if (!force && is_pro_rate_locked(ice)) {
-		spin_unlock_irqrestore(&ice->reg_lock, flags);
-		return;
-	}
-
 	switch (rate) {
 	case 8000: val = 6; break;
 	case 9600: val = 3; break;
@@ -439,8 +431,21 @@
 		val = 0;
 		break;
 	}
+
+	spin_lock_irqsave(&ice->reg_lock, flags);
+	if ((inb(ICEMT1724(ice, DMA_CONTROL)) & DMA_STARTS) || 
+	    (inb(ICEMT1724(ice, DMA_PAUSE)) & DMA_PAUSES)) {
+		/* running? we cannot change the rate now... */
+		spin_unlock_irqrestore(&ice->reg_lock, flags);
+		return;
+	}
+	if (!force && is_pro_rate_locked(ice)) {
+		spin_unlock_irqrestore(&ice->reg_lock, flags);
+		return;
+	}
+
 	old = inb(ICEMT1724(ice, RATE));
-	if (old != val)
+	if (force || old != val)
 		outb(val, ICEMT1724(ice, RATE));
 	else if (rate == ice->cur_rate) {
 		spin_unlock_irqrestore(&ice->reg_lock, flags);
@@ -450,6 +455,7 @@
 	ice->cur_rate = rate;
 
 	/* check MT02 */
+	mclk_change = 0;
 	if (ice->eeprom.data[ICE_EEP2_ACLINK] & VT1724_CFG_PRO_I2S) {
 		val = old = inb(ICEMT1724(ice, I2S_FORMAT));
 		if (rate > 96000)
@@ -458,25 +464,23 @@
 			val &= ~VT1724_MT_I2S_MCLK_128X; /* 256x MCLK */
 		if (val != old) {
 			outb(val, ICEMT1724(ice, I2S_FORMAT));
-			if (ice->eeprom.subvendor == VT1724_SUBDEVICE_REVOLUTION71) {
-				/* FIXME: is this revo only? */
-				/* assert PRST# to converters; MT05 bit 7 */
-				outb(inb(ICEMT1724(ice, AC97_CMD)) | 0x80, ICEMT1724(ice, AC97_CMD));
-				spin_unlock_irqrestore(&ice->reg_lock, flags);
-				mdelay(5);
-				spin_lock_irqsave(&ice->reg_lock, flags);
-				/* deassert PRST# */
-				outb(inb(ICEMT1724(ice, AC97_CMD)) & ~0x80, ICEMT1724(ice, AC97_CMD));
-			}
+			mclk_change = 1;
 		}
 	}
 	spin_unlock_irqrestore(&ice->reg_lock, flags);
 
+	if (mclk_change && ice->gpio.i2s_mclk_changed)
+		ice->gpio.i2s_mclk_changed(ice);
+	if (ice->gpio.set_pro_rate)
+		ice->gpio.set_pro_rate(ice, rate);
+
 	/* set up codecs */
 	for (i = 0; i < ice->akm_codecs; i++) {
 		if (ice->akm[i].ops.set_rate_val)
 			ice->akm[i].ops.set_rate_val(&ice->akm[i], rate);
 	}
+	if (ice->spdif.ops.setup_rate)
+		ice->spdif.ops.setup_rate(ice, rate);
 }
 
 static int snd_vt1724_pcm_hw_params(snd_pcm_substream_t * substream,
@@ -714,6 +718,13 @@
 static int set_rate_constraints(ice1712_t *ice, snd_pcm_substream_t *substream)
 {
 	snd_pcm_runtime_t *runtime = substream->runtime;
+	if (ice->hw_rates) {
+		/* hardware specific */
+		runtime->hw.rate_min = ice->hw_rates->list[0];
+		runtime->hw.rate_max = ice->hw_rates->list[ice->hw_rates->count - 1];
+		runtime->hw.rates = SNDRV_PCM_RATE_KNOT;
+		return snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, ice->hw_rates);
+	}
 	if (ice->eeprom.data[ICE_EEP2_ACLINK] & VT1724_CFG_PRO_I2S) {
 		/* I2S */
 		/* VT1720 doesn't support more than 96kHz */
@@ -1866,6 +1877,8 @@
 	snd_vt1720_mobo_cards,
 	snd_vt1720_pontis_cards,
 	snd_vt1724_prodigy192_cards,
+	snd_vt1724_juli_cards,
+	snd_vt1724_phase_cards,
 	NULL,
 };
 
@@ -1878,23 +1891,34 @@
 	int t = 0x10000;
 	while ((inb(ICEREG1724(ice, I2C_CTRL)) & VT1724_I2C_BUSY) && t--)
 		;
+	if (t == -1)
+		printk(KERN_ERR "ice1724: i2c busy timeout\n");
 }
 
 unsigned char snd_vt1724_read_i2c(ice1712_t *ice, unsigned char dev, unsigned char addr)
 {
+	unsigned char val;
+
+	down(&ice->i2c_mutex);
 	outb(addr, ICEREG1724(ice, I2C_BYTE_ADDR));
 	outb(dev & ~VT1724_I2C_WRITE, ICEREG1724(ice, I2C_DEV_ADDR));
 	wait_i2c_busy(ice);
-	return inb(ICEREG1724(ice, I2C_DATA));
+	val = inb(ICEREG1724(ice, I2C_DATA));
+	up(&ice->i2c_mutex);
+	//printk("i2c_read: [0x%x,0x%x] = 0x%x\n", dev, addr, val);
+	return val;
 }
 
 void snd_vt1724_write_i2c(ice1712_t *ice, unsigned char dev, unsigned char addr, unsigned char data)
 {
+	down(&ice->i2c_mutex);
 	wait_i2c_busy(ice);
+	//printk("i2c_write: [0x%x,0x%x] = 0x%x\n", dev, addr, data);
 	outb(addr, ICEREG1724(ice, I2C_BYTE_ADDR));
 	outb(data, ICEREG1724(ice, I2C_DATA));
 	outb(dev | VT1724_I2C_WRITE, ICEREG1724(ice, I2C_DEV_ADDR));
 	wait_i2c_busy(ice);
+	up(&ice->i2c_mutex);
 }
 
 static int __devinit snd_vt1724_read_eeprom(ice1712_t *ice, const char *modelname)
@@ -1906,7 +1930,8 @@
 	if (! modelname || ! *modelname) {
 		ice->eeprom.subvendor = 0;
 		if ((inb(ICEREG1724(ice, I2C_CTRL)) & VT1724_I2C_EEPROM) != 0)
-			ice->eeprom.subvendor = (snd_vt1724_read_i2c(ice, dev, 0x00) << 0) |
+			ice->eeprom.subvendor =
+				(snd_vt1724_read_i2c(ice, dev, 0x00) << 0) |
 				(snd_vt1724_read_i2c(ice, dev, 0x01) << 8) | 
 				(snd_vt1724_read_i2c(ice, dev, 0x02) << 16) | 
 				(snd_vt1724_read_i2c(ice, dev, 0x03) << 24);
@@ -2114,6 +2139,7 @@
 	spin_lock_init(&ice->reg_lock);
 	init_MUTEX(&ice->gpio_mutex);
 	init_MUTEX(&ice->open_mutex);
+	init_MUTEX(&ice->i2c_mutex);
 	ice->gpio.set_mask = snd_vt1724_set_gpio_mask;
 	ice->gpio.set_dir = snd_vt1724_set_gpio_dir;
 	ice->gpio.set_data = snd_vt1724_set_gpio_data;
diff -Nru a/sound/pci/ice1712/juli.c b/sound/pci/ice1712/juli.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/sound/pci/ice1712/juli.c	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,230 @@
+/*
+ *   ALSA driver for ICEnsemble VT1724 (Envy24HT)
+ *
+ *   Lowlevel functions for ESI Juli@ cards
+ *
+ *	Copyright (c) 2004 Jaroslav Kysela <perex@suse.cz>
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */      
+
+#include <sound/driver.h>
+#include <asm/io.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <sound/core.h>
+
+#include "ice1712.h"
+#include "envy24ht.h"
+#include "juli.h"
+
+/*
+ * chip addresses on I2C bus
+ */
+#define AK4114_ADDR		0x20		/* S/PDIF receiver */
+#define AK4358_ADDR		0x22		/* DAC */
+
+/*
+ * GPIO pins
+ */
+#define GPIO_FREQ_MASK		(3<<0)
+#define GPIO_FREQ_32KHZ		(0<<0)
+#define GPIO_FREQ_44KHZ		(1<<0)
+#define GPIO_FREQ_48KHZ		(2<<0)
+#define GPIO_MULTI_MASK		(3<<2)
+#define GPIO_MULTI_4X		(0<<2)
+#define GPIO_MULTI_2X		(1<<2)
+#define GPIO_MULTI_1X		(2<<2)		/* also external */
+#define GPIO_MULTI_HALF		(3<<2)
+#define GPIO_INTERNAL_CLOCK	(1<<4)
+#define GPIO_ANALOG_PRESENT	(1<<5)		/* RO only: 0 = present */
+#define GPIO_RXMCLK_SEL		(1<<7)		/* must be 0 */
+#define GPIO_AK5385A_CKS0	(1<<8)
+#define GPIO_AK5385A_DFS0	(1<<9)		/* swapped with DFS1 according doc? */
+#define GPIO_AK5385A_DFS1	(1<<10)
+#define GPIO_DIGOUT_MONITOR	(1<<11)		/* 1 = active */
+#define GPIO_DIGIN_MONITOR	(1<<12)		/* 1 = active */
+#define GPIO_ANAIN_MONITOR	(1<<13)		/* 1 = active */
+#define GPIO_AK5385A_MCLK	(1<<14)		/* must be 0 */
+#define GPIO_MUTE_CONTROL	(1<<15)		/* 0 = off, 1 = on */
+
+static void juli_ak4114_write(void *private_data, unsigned char reg, unsigned char val)
+{
+	snd_vt1724_write_i2c((ice1712_t *)private_data, AK4114_ADDR, reg, val);
+}
+        
+static unsigned char juli_ak4114_read(void *private_data, unsigned char reg)
+{
+	return snd_vt1724_read_i2c((ice1712_t *)private_data, AK4114_ADDR, reg);
+}
+
+/*
+ * AK4358 section
+ */
+
+static void juli_akm_lock(akm4xxx_t *ak, int chip)
+{
+}
+
+static void juli_akm_unlock(akm4xxx_t *ak, int chip)
+{
+}
+
+static void juli_akm_write(akm4xxx_t *ak, int chip,
+			   unsigned char addr, unsigned char data)
+{
+	ice1712_t *ice = ak->private_data[0];
+	 
+	snd_assert(chip == 0, return);
+	snd_vt1724_write_i2c(ice, AK4358_ADDR, addr, data);
+}
+
+/*
+ * change the rate of envy24HT, AK4358
+ */
+static void juli_akm_set_rate_val(akm4xxx_t *ak, unsigned int rate)
+{
+	unsigned char old, tmp, dfs;
+
+	if (rate == 0)  /* no hint - S/PDIF input is master, simply return */
+		return;
+	
+	/* adjust DFS on codecs */
+	if (rate > 96000) 
+		dfs = 2;
+	else if (rate > 48000)
+		dfs = 1;
+	else
+		dfs = 0;
+	
+	tmp = snd_akm4xxx_get(ak, 0, 2);
+	old = (tmp >> 4) & 0x03;
+	if (old == dfs)
+		return;
+	/* reset DFS */
+	snd_akm4xxx_reset(ak, 1);
+	tmp = snd_akm4xxx_get(ak, 0, 2);
+	tmp &= ~(0x03 << 4);
+	tmp |= dfs << 4;
+	snd_akm4xxx_set(ak, 0, 2, tmp);
+	snd_akm4xxx_reset(ak, 0);
+}
+
+static akm4xxx_t akm_juli_dac __devinitdata = {
+	.type = SND_AK4358,
+	.num_dacs = 2,
+	.ops = {
+		.lock = juli_akm_lock,
+		.unlock = juli_akm_unlock,
+		.write = juli_akm_write,
+		.set_rate_val = juli_akm_set_rate_val
+	}
+};
+
+static int __devinit juli_add_controls(ice1712_t *ice)
+{
+	return snd_ice1712_akm4xxx_build_controls(ice);
+}
+
+/*
+ * initialize the chip
+ */
+static int __devinit juli_init(ice1712_t *ice)
+{
+	static unsigned char ak4114_init_vals[] = {
+		/* AK4117_REG_PWRDN */	AK4114_RST | AK4114_PWN | AK4114_OCKS0 | AK4114_OCKS1,
+		/* AK4114_REQ_FORMAT */	AK4114_DIF_I24I2S,
+		/* AK4114_REG_IO0 */	AK4114_TX1E,
+		/* AK4114_REG_IO1 */	AK4114_EFH_1024 | AK4114_DIT | AK4114_IPS(1),
+		/* AK4114_REG_INT0_MASK */ 0,
+		/* AK4114_REG_INT1_MASK */ 0
+	};
+	static unsigned char ak4114_init_txcsb[] = {
+		0x41, 0x02, 0x2c, 0x00, 0x00
+	};
+	int err;
+	akm4xxx_t *ak;
+
+#if 0
+	for (err = 0; err < 0x20; err++)
+		juli_ak4114_read(ice, err);
+	juli_ak4114_write(ice, 0, 0x0f);
+	juli_ak4114_read(ice, 0);
+	juli_ak4114_read(ice, 1);
+#endif
+	err = snd_ak4114_create(ice->card,
+				juli_ak4114_read,
+				juli_ak4114_write,
+				ak4114_init_vals, ak4114_init_txcsb,
+				ice, &ice->spec.juli.ak4114);
+	if (err < 0)
+		return err;
+
+	ice->spec.juli.analog = ice->gpio.get_data(ice) & GPIO_ANALOG_PRESENT;
+
+	if (ice->spec.juli.analog) {
+		printk(KERN_INFO "juli@: analog I/O detected\n");
+		ice->num_total_dacs = 2;
+		ice->num_total_adcs = 2;
+
+		ak = ice->akm = kcalloc(1, sizeof(akm4xxx_t), GFP_KERNEL);
+		if (! ak)
+			return -ENOMEM;
+		ice->akm_codecs = 1;
+		if ((err = snd_ice1712_akm4xxx_init(ak, &akm_juli_dac, NULL, ice)) < 0)
+			return err;
+	}
+	
+	return 0;
+}
+
+
+/*
+ * Juli@ boards don't provide the EEPROM data except for the vendor IDs.
+ * hence the driver needs to sets up it properly.
+ */
+
+static unsigned char juli_eeprom[] __devinitdata = {
+	0x20,	/* SYSCONF: clock 512, mpu401, 1xADC, 1xDACs */
+	0x80,	/* ACLINK: I2S */
+	0xf8,	/* I2S: vol, 96k, 24bit, 192k */
+	0xc3,	/* SPDIF: out-en, out-int, spdif-in */
+	0x9f,	/* GPIO_DIR */
+	0xff,	/* GPIO_DIR1 */
+	0x7f,	/* GPIO_DIR2 */
+	0x9f,	/* GPIO_MASK */
+	0xff,	/* GPIO_MASK1 */
+	0x7f,	/* GPIO_MASK2 */
+	0x16,	/* GPIO_STATE: internal clock, multiple 1x, 48kHz */
+	0x80,	/* GPIO_STATE1: mute */
+	0x00,	/* GPIO_STATE2 */
+};
+
+/* entry point */
+struct snd_ice1712_card_info snd_vt1724_juli_cards[] __devinitdata = {
+	{
+		.subvendor = VT1724_SUBDEVICE_JULI,
+		.name = "ESI Juli@",
+		.model = "juli",
+		.chip_init = juli_init,
+		.build_controls = juli_add_controls,
+		.eeprom_size = sizeof(juli_eeprom),
+		.eeprom_data = juli_eeprom,
+	},
+	{ } /* terminator */
+};
diff -Nru a/sound/pci/ice1712/juli.h b/sound/pci/ice1712/juli.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/sound/pci/ice1712/juli.h	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,10 @@
+#ifndef __SOUND_JULI_H
+#define __SOUND_JULI_H
+
+#define JULI_DEVICE_DESC		"{ESI,Juli@},"
+
+#define VT1724_SUBDEVICE_JULI		0x31305345	/* Juli@ */
+
+extern struct snd_ice1712_card_info  snd_vt1724_juli_cards[];
+
+#endif	/* __SOUND_JULI_H */
diff -Nru a/sound/pci/ice1712/phase.c b/sound/pci/ice1712/phase.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/sound/pci/ice1712/phase.c	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,138 @@
+/*
+ *   ALSA driver for ICEnsemble ICE1724 (Envy24)
+ *
+ *   Lowlevel functions for Terratec PHASE 22
+ *
+ *	Copyright (c) 2005 Misha Zhilin <misha@epiphan.com>
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+/* PHASE 22 overview:
+ *   Audio controller: VIA Envy24HT-S (slightly trimmed down version of Envy24HT)
+ *   Analog chip: AK4524 (partially via Philip's 74HCT125)
+ *   Digital receiver: CS8414-CS (not supported in this release)
+ *
+ *   Envy connects to AK4524
+ *	- CS directly from GPIO 10
+ *	- CCLK via 74HCT125's gate #4 from GPIO 4
+ *	- CDTI via 74HCT125's gate #2 from GPIO 5
+ *		CDTI may be completely blocked by 74HCT125's gate #1 controlled by GPIO 3
+ */
+
+#include <sound/driver.h>
+#include <asm/io.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <sound/core.h>
+
+#include "ice1712.h"
+#include "envy24ht.h"
+#include "phase.h"
+
+static akm4xxx_t akm_phase22 __devinitdata = {
+	.type = SND_AK4524,
+	.num_dacs = 2,
+	.num_adcs = 2,
+};
+
+static struct snd_ak4xxx_private akm_phase22_priv __devinitdata = {
+	.caddr =	2,
+	.cif =		1,
+	.data_mask =	1 << 4,
+	.clk_mask =	1 << 5,
+	.cs_mask =	1 << 10,
+	.cs_addr =	1 << 10,
+	.cs_none =	0,
+	.add_flags = 	1 << 3,
+	.mask_flags =	0,
+};
+
+static int __devinit phase22_init(ice1712_t *ice)
+{
+	akm4xxx_t *ak;
+	int err;
+
+	// Configure DAC/ADC description for generic part of ice1724
+	switch (ice->eeprom.subvendor) {
+	case VT1724_SUBDEVICE_PHASE22:
+		ice->num_total_dacs = 2;
+		ice->num_total_adcs = 2;
+		ice->vt1720 = 1; // Envy24HT-S have 16 bit wide GPIO
+		break;
+	default:
+		snd_BUG();
+		return -EINVAL;
+	}
+
+	// Initialize analog chips
+	ak = ice->akm = kcalloc(1, sizeof(akm4xxx_t), GFP_KERNEL);
+	if (! ak)
+		return -ENOMEM;
+	ice->akm_codecs = 1;
+	switch (ice->eeprom.subvendor) {
+	case VT1724_SUBDEVICE_PHASE22:
+		if ((err = snd_ice1712_akm4xxx_init(ak, &akm_phase22, &akm_phase22_priv, ice)) < 0)
+			return err;
+		break;
+	}
+
+	return 0;
+}
+
+static int __devinit phase22_add_controls(ice1712_t *ice)
+{
+	int err = 0;
+
+	switch (ice->eeprom.subvendor) {
+	case VT1724_SUBDEVICE_PHASE22:
+		err = snd_ice1712_akm4xxx_build_controls(ice);
+		if (err < 0)
+			return err;
+	}
+	return 0;
+}
+
+static unsigned char phase22_eeprom[] __devinitdata = {
+	0x00,	/* SYSCONF: 1xADC, 1xDACs */
+	0x80,	/* ACLINK: I2S */
+	0xf8,	/* I2S: vol, 96k, 24bit*/
+	0xc3,	/* SPDIF: out-en, out-int, spdif-in */
+	0xFF,	/* GPIO_DIR */
+	0xFF,	/* GPIO_DIR1 */
+	0xFF,	/* GPIO_DIR2 */
+	0x00,	/* GPIO_MASK */
+	0x00,	/* GPIO_MASK1 */
+	0x00,	/* GPIO_MASK2 */
+	0x00,	/* GPIO_STATE: */
+	0x00,	/* GPIO_STATE1: */
+	0x00,	/* GPIO_STATE2 */
+};
+
+struct snd_ice1712_card_info snd_vt1724_phase_cards[] __devinitdata = {
+	{
+		.subvendor = VT1724_SUBDEVICE_PHASE22,
+		.name = "Terratec PHASE 22",
+		.model = "phase22",
+		.chip_init = phase22_init,
+		.build_controls = phase22_add_controls,
+		.eeprom_size = sizeof(phase22_eeprom),
+		.eeprom_data = phase22_eeprom,
+	},
+	{ } /* terminator */
+};
diff -Nru a/sound/pci/ice1712/phase.h b/sound/pci/ice1712/phase.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/sound/pci/ice1712/phase.h	2005-03-11 12:51:52 -08:00
@@ -0,0 +1,34 @@
+#ifndef __SOUND_PHASE_H
+#define __SOUND_PHASE_H
+
+/*
+ *   ALSA driver for ICEnsemble ICE1712 (Envy24)
+ *
+ *   Lowlevel functions for Terratec PHASE 22
+ *
+ *	Copyright (c) 2005 Misha Zhilin <misha@epiphan.com>
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation; either version 2 of the License, or
+ *   (at your option) any later version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */      
+
+#define PHASE_DEVICE_DESC "{Terratec,Phase 22},"
+
+#define VT1724_SUBDEVICE_PHASE22	0x3b155011
+
+/* entry point */
+extern struct snd_ice1712_card_info snd_vt1724_phase_cards[];
+
+#endif /* __SOUND_PHASE */
diff -Nru a/sound/pci/ice1712/prodigy192.c b/sound/pci/ice1712/prodigy192.c
--- a/sound/pci/ice1712/prodigy192.c	2005-03-11 12:51:42 -08:00
+++ b/sound/pci/ice1712/prodigy192.c	2005-03-11 12:51:42 -08:00
@@ -36,12 +36,12 @@
 #include "prodigy192.h"
 #include "stac946x.h"
 
-static void stac9460_put(ice1712_t *ice, int reg, unsigned char val)
+static inline void stac9460_put(ice1712_t *ice, int reg, unsigned char val)
 {
 	snd_vt1724_write_i2c(ice, PRODIGY192_STAC9460_ADDR, reg, val);
 }
 
-static unsigned char stac9460_get(ice1712_t *ice, int reg)
+static inline unsigned char stac9460_get(ice1712_t *ice, int reg)
 {
 	return snd_vt1724_read_i2c(ice, PRODIGY192_STAC9460_ADDR, reg);
 }
diff -Nru a/sound/pci/ice1712/revo.c b/sound/pci/ice1712/revo.c
--- a/sound/pci/ice1712/revo.c	2005-03-11 12:51:47 -08:00
+++ b/sound/pci/ice1712/revo.c	2005-03-11 12:51:47 -08:00
@@ -33,6 +33,15 @@
 #include "envy24ht.h"
 #include "revo.h"
 
+static void revo_i2s_mclk_changed(ice1712_t *ice)
+{
+	/* assert PRST# to converters; MT05 bit 7 */
+	outb(inb(ICEMT1724(ice, AC97_CMD)) | 0x80, ICEMT1724(ice, AC97_CMD));
+	mdelay(5);
+	/* deassert PRST# */
+	outb(inb(ICEMT1724(ice, AC97_CMD)) & ~0x80, ICEMT1724(ice, AC97_CMD));
+}
+
 /*
  * change the rate of envy24HT, AK4355 and AK4381
  */
@@ -119,6 +128,17 @@
 	.mask_flags = 0,
 };
 
+static unsigned int rates[] = {
+	32000, 44100, 48000, 64000, 88200, 96000,
+	176400, 192000,
+};
+
+static snd_pcm_hw_constraint_list_t revo_rates = {
+	.count = ARRAY_SIZE(rates),
+	.list = rates,
+	.mask = 0,
+};
+
 static int __devinit revo_init(ice1712_t *ice)
 {
 	akm4xxx_t *ak;
@@ -135,6 +155,8 @@
 		return -EINVAL;
 	}
 
+	ice->gpio.i2s_mclk_changed = revo_i2s_mclk_changed;
+
 	/* second stage of initialization, analog parts and others */
 	ak = ice->akm = kcalloc(2, sizeof(akm4xxx_t), GFP_KERNEL);
 	if (! ak)
@@ -150,6 +172,8 @@
 		snd_ice1712_gpio_write_bits(ice, VT1724_REVO_MUTE, VT1724_REVO_MUTE);
 		break;
 	}
+
+	ice->hw_rates = &revo_rates; /* AK codecs don't support lower than 32k */
 
 	return 0;
 }
diff -Nru a/sound/pci/ice1712/vt1720_mobo.c b/sound/pci/ice1712/vt1720_mobo.c
--- a/sound/pci/ice1712/vt1720_mobo.c	2005-03-11 12:51:41 -08:00
+++ b/sound/pci/ice1712/vt1720_mobo.c	2005-03-11 12:51:41 -08:00
@@ -101,6 +101,15 @@
 		.eeprom_size = sizeof(k8x800_eeprom),
 		.eeprom_data = k8x800_eeprom,
 	},
+	{
+		.subvendor = VT1720_SUBDEVICE_9CJS,
+		.name = "Chaintech 9CJS",
+		/* identical with k8x800 */
+		.chip_init = k8x800_init,
+		.build_controls = k8x800_add_controls,
+		.eeprom_size = sizeof(k8x800_eeprom),
+		.eeprom_data = k8x800_eeprom,
+	},
 	{ } /* terminator */
 };
 
diff -Nru a/sound/pci/ice1712/vt1720_mobo.h b/sound/pci/ice1712/vt1720_mobo.h
--- a/sound/pci/ice1712/vt1720_mobo.h	2005-03-11 12:51:42 -08:00
+++ b/sound/pci/ice1712/vt1720_mobo.h	2005-03-11 12:51:42 -08:00
@@ -26,11 +26,13 @@
 
 #define VT1720_MOBO_DEVICE_DESC        "{Albatron,K8X800 Pro II},"\
 				       "{Chaintech,ZNF3-150},"\
-				       "{Chaintech,ZNF3-250},"
+				       "{Chaintech,ZNF3-250},"\
+				       "{Chaintech,9CJS},"
 
 #define VT1720_SUBDEVICE_K8X800		0xf217052c
 #define VT1720_SUBDEVICE_ZNF3_150	0x0f2741f6
 #define VT1720_SUBDEVICE_ZNF3_250	0x0f2745f6
+#define VT1720_SUBDEVICE_9CJS		0x0f272327
 
 extern struct snd_ice1712_card_info  snd_vt1720_mobo_cards[];
 
diff -Nru a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c
--- a/sound/pci/intel8x0.c	2005-03-11 12:51:47 -08:00
+++ b/sound/pci/intel8x0.c	2005-03-11 12:51:47 -08:00
@@ -118,8 +118,8 @@
 #ifndef PCI_DEVICE_ID_INTEL_ESB_5
 #define PCI_DEVICE_ID_INTEL_ESB_5	0x25a6
 #endif
-#ifndef PCI_DEVICE_ID_INTEL_ICH6_3
-#define PCI_DEVICE_ID_INTEL_ICH6_3	0x266e
+#ifndef PCI_DEVICE_ID_INTEL_ICH6_18
+#define PCI_DEVICE_ID_INTEL_ICH6_18	0x266e
 #endif
 #ifndef PCI_DEVICE_ID_INTEL_ICH7_20
 #define PCI_DEVICE_ID_INTEL_ICH7_20	0x27de
@@ -1059,7 +1059,7 @@
 	intel8x0_t *chip = snd_pcm_substream_chip(substream);
 	ichdev_t *ichdev = get_ichdev(substream);
 	size_t ptr1, ptr;
-	int civ, timeout = 10;
+	int civ, timeout = 100;
 	unsigned int position;
 
 	spin_lock(&chip->reg_lock);
@@ -1067,8 +1067,10 @@
 		civ = igetbyte(chip, ichdev->reg_offset + ICH_REG_OFF_CIV);
 		ptr1 = igetword(chip, ichdev->reg_offset + ichdev->roff_picb);
 		position = ichdev->position;
-		if (ptr1 == 0)
-			udelay(1);
+		if (ptr1 == 0) {
+			udelay(10);
+			continue;
+		}
 		if (civ == igetbyte(chip, ichdev->reg_offset + ICH_REG_OFF_CIV) &&
 		    ptr1 == igetword(chip, ichdev->reg_offset + ichdev->roff_picb))
 			break;
@@ -1761,6 +1763,12 @@
 	},
 	{
 		.vendor = 0x1028,
+		.device = 0x012c,
+		.name = "Dell Precision 650",	/* AD1981A */
+		.type = AC97_TUNE_HP_ONLY
+	},
+	{
+		.vendor = 0x1028,
 		.device = 0x012d,
 		.name = "Dell Precision 450",	/* AD1981B*/
 		.type = AC97_TUNE_HP_ONLY
@@ -1772,6 +1780,12 @@
 		.type = AC97_TUNE_HP_ONLY
 	},
 	{
+		.vendor = 0x1028,
+		.device = 0x0163,
+		.name = "Dell Unknown",	/* STAC9750/51 */
+		.type = AC97_TUNE_HP_ONLY
+	},
+	{
 		.vendor = 0x103c,
 		.device = 0x006d,
 		.name = "HP zv5000",
@@ -1838,6 +1852,12 @@
 		.type = AC97_TUNE_HP_ONLY
 	},
 	{
+		.vendor = 0x10cf,
+		.device = 0x1253,
+		.name = "Fujitsu S6210",	/* STAC9750/51 */
+		.type = AC97_TUNE_HP_ONLY
+	},
+	{
 		.vendor = 0x10f1,
 		.device = 0x2665,
 		.name = "Fujitsu-Siemens Celsius",	/* AD1981? */
@@ -2012,7 +2032,8 @@
 	/* FIXME: my test board doesn't work well with VRA... */
 	if (chip->device_type == DEVICE_ALI)
 		pbus->no_vra = 1;
-	pbus->dra = 1;
+	else
+		pbus->dra = 1;
 	chip->ac97_bus = pbus;
 
 	ac97.pci = chip->pci;
@@ -2320,7 +2341,7 @@
 /*
  * power management
  */
-static int intel8x0_suspend(snd_card_t *card, unsigned int state)
+static int intel8x0_suspend(snd_card_t *card, pm_message_t state)
 {
 	intel8x0_t *chip = card->pm_private_data;
 	int i;
@@ -2345,7 +2366,7 @@
 	return 0;
 }
 
-static int intel8x0_resume(snd_card_t *card, unsigned int state)
+static int intel8x0_resume(snd_card_t *card)
 {
 	intel8x0_t *chip = card->pm_private_data;
 	int i;
@@ -2713,7 +2734,7 @@
 	{ PCI_DEVICE_ID_INTEL_ICH4, "Intel 82801DB-ICH4" },
 	{ PCI_DEVICE_ID_INTEL_ICH5, "Intel ICH5" },
 	{ PCI_DEVICE_ID_INTEL_ESB_5, "Intel 6300ESB" },
-	{ PCI_DEVICE_ID_INTEL_ICH6_3, "Intel ICH6" },
+	{ PCI_DEVICE_ID_INTEL_ICH6_18, "Intel ICH6" },
 	{ PCI_DEVICE_ID_INTEL_ICH7_20, "Intel ICH7" },
 	{ PCI_DEVICE_ID_SI_7012, "SiS SI7012" },
 	{ PCI_DEVICE_ID_NVIDIA_MCP_AUDIO, "NVidia nForce" },
diff -Nru a/sound/pci/intel8x0m.c b/sound/pci/intel8x0m.c
--- a/sound/pci/intel8x0m.c	2005-03-11 12:51:46 -08:00
+++ b/sound/pci/intel8x0m.c	2005-03-11 12:51:46 -08:00
@@ -35,6 +35,7 @@
 #include <sound/pcm.h>
 #include <sound/ac97_codec.h>
 #include <sound/info.h>
+#include <sound/control.h>
 #include <sound/initval.h>
 
 MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
@@ -46,6 +47,8 @@
 		"{Intel,82801CA-ICH3},"
 		"{Intel,82801DB-ICH4},"
 		"{Intel,ICH5},"
+		"{Intel,ICH6},"
+		"{Intel,ICH7},"
 	        "{Intel,MX440},"
 		"{SiS,7013},"
 		"{NVidia,NForce Modem},"
@@ -54,7 +57,7 @@
 		"{NVidia,NForce3 Modem},"
 		"{AMD,AMD768}}");
 
-static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;	/* Index 0-MAX */
+static int index[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = -2}; /* Exclude the first card */
 static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;	/* ID for this card */
 static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;	/* Enable this card */
 static int ac97_clock[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 0};
@@ -93,6 +96,12 @@
 #ifndef PCI_DEVICE_ID_INTEL_ICH5_6
 #define PCI_DEVICE_ID_INTEL_ICH5_6	0x24d6
 #endif
+#ifndef PCI_DEVICE_ID_INTEL_ICH6_6
+#define PCI_DEVICE_ID_INTEL_ICH6_6	0x266d
+#endif
+#ifndef PCI_DEVICE_ID_INTEL_ICH7_6
+#define PCI_DEVICE_ID_INTEL_ICH7_6	0x27dd
+#endif
 #ifndef PCI_DEVICE_ID_SI_7013
 #define PCI_DEVICE_ID_SI_7013		0x7013
 #endif
@@ -247,7 +256,7 @@
 	snd_pcm_t *pcm[2];
 	ichdev_t ichd[2];
 
-	int in_ac97_init: 1;
+	unsigned int in_ac97_init: 1;
 
 	ac97_bus_t *ac97_bus;
 	ac97_t *ac97;
@@ -268,6 +277,8 @@
 	{ 0x8086, 0x2486, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL },	/* ICH3 */
 	{ 0x8086, 0x24c6, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL }, /* ICH4 */
 	{ 0x8086, 0x24d6, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL }, /* ICH5 */
+	{ 0x8086, 0x266d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL },	/* ICH6 */
+	{ 0x8086, 0x27dd, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL },	/* ICH7 */
 	{ 0x8086, 0x7196, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL },	/* 440MX */
 	{ 0x1022, 0x7446, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL },	/* AMD768 */
 	{ 0x1039, 0x7013, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_SIS },	/* SI7013 */
@@ -281,9 +292,60 @@
 #endif
 	{ 0, }
 };
+static int snd_intel8x0m_switch_default_get(snd_kcontrol_t *kcontrol,
+					    snd_ctl_elem_value_t *ucontrol);
+static int snd_intel8x0m_switch_default_put(snd_kcontrol_t *kcontrol,
+					    snd_ctl_elem_value_t *ucontrol);
+static int snd_intel8x0m_switch_default_info(snd_kcontrol_t *kcontrol,
+					     snd_ctl_elem_info_t *uinfo);
+
+#define PRIVATE_VALUE_INITIALIZER(r,m) (((r) & 0xffff) << 16 | ((m) & 0xffff))
+#define PRIVATE_VALUE_MASK(control) ((control)->private_value & 0xffff)
+#define PRIVATE_VALUE_REG(control) (((control)->private_value >> 16) & 0xffff)
+
+static snd_kcontrol_new_t snd_intel8x0m_mixer_switches[] __devinitdata = {
+  { .name  = "Off-hook Switch",
+    .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+    .info  = snd_intel8x0m_switch_default_info,
+    .get   = snd_intel8x0m_switch_default_get,
+    .put   = snd_intel8x0m_switch_default_put,
+    .private_value = PRIVATE_VALUE_INITIALIZER(AC97_GPIO_STATUS,AC97_GPIO_LINE1_OH)
+  }
+};
 
 MODULE_DEVICE_TABLE(pci, snd_intel8x0m_ids);
 
+static int snd_intel8x0m_switch_default_info(snd_kcontrol_t *kcontrol,
+					     snd_ctl_elem_info_t *uinfo)
+{
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
+	uinfo->count = 1;
+	uinfo->value.integer.min = 0;
+	uinfo->value.integer.max = 1;
+	return 0;
+}
+
+static int snd_intel8x0m_switch_default_get(snd_kcontrol_t *kcontrol,
+					    snd_ctl_elem_value_t *ucontrol)
+{
+	unsigned short mask = PRIVATE_VALUE_MASK(kcontrol);
+	unsigned short reg = PRIVATE_VALUE_REG(kcontrol);
+	intel8x0_t *chip = snd_kcontrol_chip(kcontrol);
+	unsigned int status;
+	status = snd_ac97_read(chip->ac97, reg) & mask ? 1 : 0;
+	ucontrol->value.integer.value[0] = status;
+	return 0;
+}
+static int snd_intel8x0m_switch_default_put(snd_kcontrol_t *kcontrol,
+					    snd_ctl_elem_value_t *ucontrol)
+{
+	unsigned short mask = PRIVATE_VALUE_MASK(kcontrol);
+	unsigned short reg = PRIVATE_VALUE_REG(kcontrol);
+	intel8x0_t *chip = snd_kcontrol_chip(kcontrol);
+	unsigned short new_status = ucontrol->value.integer.value[0] ? mask : ~mask;
+	return snd_ac97_update_bits(chip->ac97, reg,
+				    mask, new_status);
+}
 /*
  *  Lowlevel I/O - busmaster
  */
@@ -638,17 +700,12 @@
 
 static int snd_intel8x0m_pcm_trigger(snd_pcm_substream_t *substream, int cmd)
 {
-	ichdev_t *ichdev = get_ichdev(substream);
 	/* hook off/on on start/stop */
-	/* TODO: move it to ac97 controls */
+	/* Moved this to mixer control */
 	switch (cmd) {
 	case SNDRV_PCM_TRIGGER_START:
-		snd_ac97_update_bits(ichdev->ac97, AC97_GPIO_STATUS,
-				     AC97_GPIO_LINE1_OH, AC97_GPIO_LINE1_OH);
 		break;
 	case SNDRV_PCM_TRIGGER_STOP:
-		snd_ac97_update_bits(ichdev->ac97, AC97_GPIO_STATUS,
-				     AC97_GPIO_LINE1_OH, ~AC97_GPIO_LINE1_OH);
 		break;
 	default:
 		return -EINVAL;
@@ -890,6 +947,7 @@
 	ac97_t *x97;
 	int err;
 	unsigned int glob_sta = 0;
+	unsigned int idx;
 	static ac97_bus_ops_t ops = {
 		.write = snd_intel8x0_codec_write,
 		.read = snd_intel8x0_codec_read,
@@ -921,10 +979,14 @@
 		return err;
 	}
 	chip->ac97 = x97;
-	if(ac97_is_modem(x97) && !chip->ichd[ICHD_MDMIN].ac97 ) {
+	if(ac97_is_modem(x97) && !chip->ichd[ICHD_MDMIN].ac97) {
 		chip->ichd[ICHD_MDMIN].ac97 = x97;
 		chip->ichd[ICHD_MDMOUT].ac97 = x97;
 	}
+	for (idx = 0; idx < ARRAY_SIZE(snd_intel8x0m_mixer_switches); idx++) {
+		if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_intel8x0m_mixer_switches[idx], chip))) < 0)
+			goto __err;
+	}
 
 	chip->in_ac97_init = 0;
 	return 0;
@@ -1078,7 +1140,7 @@
 /*
  * power management
  */
-static int intel8x0m_suspend(snd_card_t *card, unsigned int state)
+static int intel8x0m_suspend(snd_card_t *card, pm_message_t state)
 {
 	intel8x0_t *chip = card->pm_private_data;
 	int i;
@@ -1091,7 +1153,7 @@
 	return 0;
 }
 
-static int intel8x0m_resume(snd_card_t *card, unsigned int state)
+static int intel8x0m_resume(snd_card_t *card)
 {
 	intel8x0_t *chip = card->pm_private_data;
 	pci_enable_device(chip->pci);
@@ -1298,6 +1360,8 @@
 	{ PCI_DEVICE_ID_INTEL_ICH3_6, "Intel 82801CA-ICH3" },
 	{ PCI_DEVICE_ID_INTEL_ICH4_6, "Intel 82801DB-ICH4" },
 	{ PCI_DEVICE_ID_INTEL_ICH5_6, "Intel ICH5" },
+	{ PCI_DEVICE_ID_INTEL_ICH6_6, "Intel ICH6" },
+	{ PCI_DEVICE_ID_INTEL_ICH7_6, "Intel ICH7" },
 	{ 0x7446, "AMD AMD768" },
 	{ PCI_DEVICE_ID_SI_7013, "SiS SI7013" },
 	{ PCI_DEVICE_ID_NVIDIA_MCP_MODEM, "NVidia nForce" },
diff -Nru a/sound/pci/korg1212/korg1212.c b/sound/pci/korg1212/korg1212.c
--- a/sound/pci/korg1212/korg1212.c	2005-03-11 12:51:41 -08:00
+++ b/sound/pci/korg1212/korg1212.c	2005-03-11 12:51:41 -08:00
@@ -51,7 +51,7 @@
 //#define K1212_LARGEALLOC		1
 
 // ----------------------------------------------------------------------------
-// the following enum defines the valid states of the Korg 1212 I/O card.
+// Valid states of the Korg 1212 I/O card.
 // ----------------------------------------------------------------------------
 typedef enum {
    K1212_STATE_NONEXISTENT,		// there is no card here
@@ -85,6 +85,8 @@
    K1212_DB_ConfigureMiscMemory   = 6,    // tells card where other buffers are.
    K1212_DB_TriggerFromAdat       = 7,    // tells card to trigger from Adat at a specific
                                           //    timecode value.
+   K1212_DB_DMAERROR              = 0x80, // DMA Error - the PCI bus is congestioned.
+   K1212_DB_CARDSTOPPED           = 0x81, // Card has stopped by user request.
    K1212_DB_RebootCard            = 0xA0, // instructs the card to reboot.
    K1212_DB_BootFromDSPPage4      = 0xA4, // instructs the card to boot from the DSP microcode
                                           //    on page 4 (local page to card).
@@ -93,11 +95,9 @@
    K1212_DB_StartDSPDownload      = 0xAF  // tells the card to download its DSP firmware.
 } korg1212_dbcnst_t;
 
-#define K1212_ISRCODE_DMAERROR      0x80
-#define K1212_ISRCODE_CARDSTOPPED   0x81
 
 // ----------------------------------------------------------------------------
-// The following enumeration defines return codes for DeviceIoControl() calls
+// The following enumeration defines return codes 
 // to the Korg 1212 I/O driver.
 // ----------------------------------------------------------------------------
 typedef enum {
@@ -116,11 +116,6 @@
    K1212_CMDRET_NoAckFromCard,         // the card never acknowledged a command
    K1212_CMDRET_BadParams,             // bad parameters were provided by the caller
 
-   // --------------------------------------------------------------
-   // the following return errors are specific to the wave device
-   // driver interface.  These will not be encountered by users of
-   // the 32 bit DIOC interface (a.k.a. custom or native API).
-   // --------------------------------------------------------------
    K1212_CMDRET_BadDevice,             // the specified wave device was out of range
    K1212_CMDRET_BadFormat              // the specified wave format is unsupported
 } snd_korg1212rc;
@@ -400,9 +395,14 @@
         u16 leftADCInSens;           // ADC left channel input sensitivity
         u16 rightADCInSens;          // ADC right channel input sensitivity
 
-	int opencnt;			// Open/Close count
-	int setcnt;			// SetupForPlay count
-	int playcnt;			// TriggerPlay count
+	int opencnt;		     // Open/Close count
+	int setcnt;		     // SetupForPlay count
+	int playcnt;		     // TriggerPlay count
+	int errorcnt;		     // Error Count
+	unsigned long totalerrorcnt; // Total Error Count
+
+	int dsp_is_loaded;
+	int dsp_stop_is_processed;
 
 };
 
@@ -610,7 +610,7 @@
 static void snd_korg1212_SendStop(korg1212_t *korg1212)
 {
 	if (! korg1212->stop_pending_cnt) {
-		writel(0xffffffff, &korg1212->sharedBufferPtr->cardCommand);
+		korg1212->sharedBufferPtr->cardCommand = 0xffffffff;
 		/* program the timer */
 		korg1212->stop_pending_cnt = HZ;
 		korg1212->timer.expires = jiffies + 1;
@@ -622,9 +622,10 @@
 {
 	unsigned long flags;
 	spin_lock_irqsave(&korg1212->lock, flags);
+	korg1212->dsp_stop_is_processed = 0;
 	snd_korg1212_SendStop(korg1212);
 	spin_unlock_irqrestore(&korg1212->lock, flags);
-	sleep_on_timeout(&korg1212->wait, (HZ * 3) / 2);
+	wait_event_timeout(korg1212->wait, korg1212->dsp_stop_is_processed, (HZ * 3) / 2);
 }
 
 /* timer callback for checking the ack of stop request */
@@ -633,9 +634,10 @@
         korg1212_t *korg1212 = (korg1212_t *) data;
 	
 	spin_lock(&korg1212->lock);
-	if (readl(&korg1212->sharedBufferPtr->cardCommand) == 0) {
+	if (korg1212->sharedBufferPtr->cardCommand == 0) {
 		/* ack'ed */
 		korg1212->stop_pending_cnt = 0;
+		korg1212->dsp_stop_is_processed = 1;
 		wake_up(&korg1212->wait);
 #if K1212_DEBUG_LEVEL > 1
 		K1212_DEBUG_PRINTK("K1212_DEBUG: Stop ack'ed [%s]\n", stateName[korg1212->cardState]);
@@ -647,7 +649,8 @@
 			add_timer(&korg1212->timer);
 		} else {
 			snd_printd("korg1212_timer_func timeout\n");
-			writel(0, &korg1212->sharedBufferPtr->cardCommand);
+			korg1212->sharedBufferPtr->cardCommand = 0;
+			korg1212->dsp_stop_is_processed = 1;
 			wake_up(&korg1212->wait);
 #if K1212_DEBUG_LEVEL > 0
 			K1212_DEBUG_PRINTK("K1212_DEBUG: Stop timeout [%s]\n", stateName[korg1212->cardState]);
@@ -850,15 +853,12 @@
 
 static inline int snd_korg1212_use_is_exclusive(korg1212_t *korg1212)
 {
-	unsigned long flags;
 	int ret = 1;
 
-	spin_lock_irqsave(&korg1212->lock, flags);
 	if ((korg1212->playback_pid != korg1212->capture_pid) &&
 	    (korg1212->playback_pid >= 0) && (korg1212->capture_pid >= 0)) {
 		ret = 0;
 	}
-	spin_unlock_irqrestore(&korg1212->lock, flags);
 	return ret;
 }
 
@@ -1179,18 +1179,23 @@
 #if K1212_DEBUG_LEVEL > 0
                         K1212_DEBUG_PRINTK("K1212_DEBUG: IRQ DNLD count - %ld, %x, [%s].\n", korg1212->irqcount, doorbellValue, stateName[korg1212->cardState]);
 #endif
-                        if (korg1212->cardState == K1212_STATE_DSP_IN_PROCESS)
+                        if (korg1212->cardState == K1212_STATE_DSP_IN_PROCESS) {
+				korg1212->dsp_is_loaded = 1;
 				wake_up(&korg1212->wait);
+			}
                         break;
 
                 // ------------------------------------------------------------------------
                 // an error occurred - stop the card
                 // ------------------------------------------------------------------------
-                case K1212_ISRCODE_DMAERROR:
+                case K1212_DB_DMAERROR:
 #if K1212_DEBUG_LEVEL > 1
                         K1212_DEBUG_PRINTK("K1212_DEBUG: IRQ DMAE count - %ld, %x, [%s].\n", korg1212->irqcount, doorbellValue, stateName[korg1212->cardState]);
 #endif
-                        writel(0, &korg1212->sharedBufferPtr->cardCommand);
+			snd_printk(KERN_ERR "korg1212: DMA Error\n");	
+			korg1212->errorcnt++;
+			korg1212->totalerrorcnt++;
+			korg1212->sharedBufferPtr->cardCommand = 0;
 			snd_korg1212_setCardState(korg1212, K1212_STATE_ERRORSTOP);
                         break;
 
@@ -1198,11 +1203,11 @@
                 // the card has stopped by our request.  Clear the command word and signal
                 // the semaphore in case someone is waiting for this.
                 // ------------------------------------------------------------------------
-                case K1212_ISRCODE_CARDSTOPPED:
+                case K1212_DB_CARDSTOPPED:
 #if K1212_DEBUG_LEVEL > 1
                         K1212_DEBUG_PRINTK("K1212_DEBUG: IRQ CSTP count - %ld, %x, [%s].\n", korg1212->irqcount, doorbellValue, stateName[korg1212->cardState]);
 #endif
-                        writel(0, &korg1212->sharedBufferPtr->cardCommand);
+			korg1212->sharedBufferPtr->cardCommand = 0;
                         break;
 
                 default:
@@ -1267,7 +1272,9 @@
 	if (rc) K1212_DEBUG_PRINTK("K1212_DEBUG: Start DSP Download RC = %d [%s]\n", rc, stateName[korg1212->cardState]);
 #endif
 
-	if (! sleep_on_timeout(&korg1212->wait, HZ * CARD_BOOT_TIMEOUT))
+	korg1212->dsp_is_loaded = 0;
+	wait_event_timeout(korg1212->wait, korg1212->dsp_is_loaded, HZ * CARD_BOOT_TIMEOUT);
+	if (! korg1212->dsp_is_loaded )
 		return -EBUSY; /* timeout */
 
 	snd_korg1212_OnDSPDownloadComplete(korg1212);
@@ -1439,6 +1446,7 @@
 	korg1212->playback_pid = current->pid;
         korg1212->periodsize = K1212_PERIODS;
 	korg1212->channels = K1212_CHANNELS;
+	korg1212->errorcnt = 0;
 
         spin_unlock_irqrestore(&korg1212->lock, flags);
 
@@ -1457,7 +1465,7 @@
 		K1212_DEBUG_PRINTK("K1212_DEBUG: snd_korg1212_capture_open [%s]\n", stateName[korg1212->cardState]);
 #endif
 
-        snd_pcm_set_sync(substream);    // ???
+        snd_pcm_set_sync(substream);
 
 	snd_korg1212_OpenCard(korg1212);
 
@@ -1614,7 +1622,7 @@
         	spin_unlock_irq(&korg1212->lock);
 		return -EAGAIN;
 		/*
-		writel(0, &korg1212->sharedBufferPtr->cardCommand);
+		korg1212->sharedBufferPtr->cardCommand = 0;
 		del_timer(&korg1212->timer);
 		korg1212->stop_pending_cnt = 0;
 		*/
@@ -2118,6 +2126,7 @@
         snd_iprintf(buffer, "Idle mon. State: %d\n", korg1212->idleMonitorOn);
         snd_iprintf(buffer, "Cmd retry count: %d\n", korg1212->cmdRetryCount);
         snd_iprintf(buffer, "      Irq count: %ld\n", korg1212->irqcount);
+        snd_iprintf(buffer, "    Error count: %ld\n", korg1212->totalerrorcnt);
 }
 
 static void __devinit snd_korg1212_proc_init(korg1212_t *korg1212)
@@ -2235,6 +2244,7 @@
 	korg1212->opencnt = 0;
 	korg1212->playcnt = 0;
 	korg1212->setcnt = 0;
+	korg1212->totalerrorcnt = 0;
 	korg1212->playback_pid = -1;
 	korg1212->capture_pid = -1;
         snd_korg1212_setCardState(korg1212, K1212_STATE_UNINITIALIZED);
@@ -2273,7 +2283,7 @@
 #endif
 
         if ((korg1212->iobase = ioremap(korg1212->iomem, iomem_size)) == NULL) {
-		snd_printk(KERN_ERR "unable to remap memory region 0x%lx-0x%lx\n", korg1212->iomem,
+		snd_printk(KERN_ERR "korg1212: unable to remap memory region 0x%lx-0x%lx\n", korg1212->iomem,
                            korg1212->iomem + iomem_size - 1);
                 snd_korg1212_free(korg1212);
                 return -EBUSY;
@@ -2284,7 +2294,7 @@
                           "korg1212", (void *) korg1212);
 
         if (err) {
-		snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq);
+		snd_printk(KERN_ERR "korg1212: unable to grab IRQ %d\n", pci->irq);
                 snd_korg1212_free(korg1212);
                 return -EBUSY;
         }
@@ -2332,7 +2342,7 @@
 
 	if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci),
 				sizeof(KorgSharedBuffer), &korg1212->dma_shared) < 0) {
-		snd_printk(KERN_ERR "can not allocate shared buffer memory (%Zd bytes)\n", sizeof(KorgSharedBuffer));
+		snd_printk(KERN_ERR "korg1212: can not allocate shared buffer memory (%Zd bytes)\n", sizeof(KorgSharedBuffer));
                 snd_korg1212_free(korg1212);
                 return -ENOMEM;
         }
@@ -2349,7 +2359,7 @@
 
 	if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci),
 				korg1212->DataBufsSize, &korg1212->dma_play) < 0) {
-		snd_printk(KERN_ERR "can not allocate play data buffer memory (%d bytes)\n", korg1212->DataBufsSize);
+		snd_printk(KERN_ERR "korg1212: can not allocate play data buffer memory (%d bytes)\n", korg1212->DataBufsSize);
                 snd_korg1212_free(korg1212);
                 return -ENOMEM;
         }
@@ -2363,7 +2373,7 @@
 
 	if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci),
 				korg1212->DataBufsSize, &korg1212->dma_rec) < 0) {
-		snd_printk(KERN_ERR "can not allocate record data buffer memory (%d bytes)\n", korg1212->DataBufsSize);
+		snd_printk(KERN_ERR "korg1212: can not allocate record data buffer memory (%d bytes)\n", korg1212->DataBufsSize);
                 snd_korg1212_free(korg1212);
                 return -ENOMEM;
         }
@@ -2395,7 +2405,7 @@
 
 	if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci),
 				korg1212->dspCodeSize, &korg1212->dma_dsp) < 0) {
-		snd_printk(KERN_ERR "can not allocate dsp code memory (%d bytes)\n", korg1212->dspCodeSize);
+		snd_printk(KERN_ERR "korg1212: can not allocate dsp code memory (%d bytes)\n", korg1212->dspCodeSize);
                 snd_korg1212_free(korg1212);
                 return -ENOMEM;
         }
@@ -2424,11 +2434,12 @@
         if (snd_korg1212_downloadDSPCode(korg1212))
         	return -EBUSY;
 
-	printk(KERN_INFO "dspMemPhy       = %08x U[%08x]\n"
-               "PlayDataPhy     = %08x L[%08x]\n"
-               "RecDataPhy      = %08x L[%08x]\n"
-               "VolumeTablePhy  = %08x L[%08x]\n"
-               "RoutingTablePhy = %08x L[%08x]\n"
+	snd_printk(KERN_ERR 
+	       "korg1212: dspMemPhy = %08x U[%08x], "
+               "PlayDataPhy = %08x L[%08x]\n"
+	       "korg1212: RecDataPhy = %08x L[%08x], "
+               "VolumeTablePhy = %08x L[%08x]\n"
+               "korg1212: RoutingTablePhy = %08x L[%08x], "
                "AdatTimeCodePhy = %08x L[%08x]\n",
 	       (int)korg1212->dma_dsp.addr,    UpperWordSwap(korg1212->dma_dsp.addr),
                korg1212->PlayDataPhy,     LowerWordSwap(korg1212->PlayDataPhy),
diff -Nru a/sound/pci/maestro3.c b/sound/pci/maestro3.c
--- a/sound/pci/maestro3.c	2005-03-11 12:51:47 -08:00
+++ b/sound/pci/maestro3.c	2005-03-11 12:51:47 -08:00
@@ -820,7 +820,7 @@
 	unsigned long iobase;
 
 	int irq;
-	int allegro_flag : 1;
+	unsigned int allegro_flag : 1;
 
 	ac97_t *ac97;
 
@@ -957,6 +957,13 @@
 		.device = 0x80f1,
 		.amp_gpio = 0x03,
 	},
+	/* LEGEND ZhaoYang 3100CF */
+	{
+		.name = "LEGEND ZhaoYang 3100CF",
+		.vendor = 0x1509,
+		.device = 0x1740,
+		.amp_gpio = 0x03,
+	},
 	/* END */
 	{ NULL }
 };
@@ -2385,7 +2392,7 @@
  * APM support
  */
 #ifdef CONFIG_PM
-static int m3_suspend(snd_card_t *card, unsigned int state)
+static int m3_suspend(snd_card_t *card, pm_message_t state)
 {
 	m3_t *chip = card->pm_private_data;
 	int i, index;
@@ -2417,7 +2424,7 @@
 	return 0;
 }
 
-static int m3_resume(snd_card_t *card, unsigned int state)
+static int m3_resume(snd_card_t *card)
 {
 	m3_t *chip = card->pm_private_data;
 	int i, index;
diff -Nru a/sound/pci/nm256/nm256.c b/sound/pci/nm256/nm256.c
--- a/sound/pci/nm256/nm256.c	2005-03-11 12:51:51 -08:00
+++ b/sound/pci/nm256/nm256.c	2005-03-11 12:51:51 -08:00
@@ -1267,7 +1267,7 @@
  * APM event handler, so the card is properly reinitialized after a power
  * event.
  */
-static int nm256_suspend(snd_card_t *card, unsigned int state)
+static int nm256_suspend(snd_card_t *card, pm_message_t state)
 {
 	nm256_t *chip = card->pm_private_data;
 
@@ -1278,7 +1278,7 @@
 	return 0;
 }
 
-static int nm256_resume(snd_card_t *card, unsigned int state)
+static int nm256_resume(snd_card_t *card)
 {
 	nm256_t *chip = card->pm_private_data;
 
diff -Nru a/sound/pci/rme9652/hdsp.c b/sound/pci/rme9652/hdsp.c
--- a/sound/pci/rme9652/hdsp.c	2005-03-11 12:51:42 -08:00
+++ b/sound/pci/rme9652/hdsp.c	2005-03-11 12:51:42 -08:00
@@ -47,8 +47,6 @@
 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;	/* Index 0-MAX */
 static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;	/* ID for this card */
 static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;	/* Enable this card */
-static int precise_ptr[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS-1)] = 0 }; /* Enable precise pointer */
-static int line_outs_monitor[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS-1)] = 0}; /* Send all inputs/playback to line outs */
 
 module_param_array(index, int, NULL, 0444);
 MODULE_PARM_DESC(index, "Index value for RME Hammerfall DSP interface.");
@@ -56,10 +54,6 @@
 MODULE_PARM_DESC(id, "ID string for RME Hammerfall DSP interface.");
 module_param_array(enable, bool, NULL, 0444);
 MODULE_PARM_DESC(enable, "Enable/disable specific Hammerfall DSP soundcards.");
-module_param_array(precise_ptr, bool, NULL, 0444);
-MODULE_PARM_DESC(precise_ptr, "Enable precise pointer (doesn't work reliably).");
-module_param_array(line_outs_monitor, bool, NULL, 0444);
-MODULE_PARM_DESC(line_outs_monitor, "Send all input and playback streams to line outs by default.");
 MODULE_AUTHOR("Paul Davis <paul@linuxaudiosystems.com>, Marcus Andersson, Thomas Charbonnel <thomas@undata.org>");
 MODULE_DESCRIPTION("RME Hammerfall DSP");
 MODULE_LICENSE("GPL");
@@ -445,6 +439,7 @@
 	snd_pcm_substream_t  *playback_substream;
         hdsp_midi_t           midi[2];
 	struct tasklet_struct midi_tasklet;
+	int		      use_midi_tasklet;
 	int                   precise_ptr;
 	u32                   control_register;	     /* cached value */
 	u32                   control2_register;     /* cached value */
@@ -472,7 +467,6 @@
 	pid_t                 capture_pid;
 	pid_t                 playback_pid;
 	int                   running;
-        int                   passthru;              /* non-zero if doing pass-thru */
 	int                   system_sample_rate;
 	char                 *channel_map;
 	int                   dev;
@@ -659,13 +653,13 @@
 
 	if ((hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DllError) != 0) {
 		
-		snd_printk ("loading firmware\n");
+		snd_printk ("Hammerfall-DSP: loading firmware\n");
 
 		hdsp_write (hdsp, HDSP_control2Reg, HDSP_S_PROGRAM);
 		hdsp_write (hdsp, HDSP_fifoData, 0);
 		
 		if (hdsp_fifo_wait (hdsp, 0, HDSP_LONG_WAIT)) {
-			snd_printk ("timeout waiting for download preparation\n");
+			snd_printk ("Hammerfall-DSP: timeout waiting for download preparation\n");
 			return -EIO;
 		}
 		
@@ -674,7 +668,7 @@
 		for (i = 0; i < 24413; ++i) {
 			hdsp_write(hdsp, HDSP_fifoData, hdsp->firmware_cache[i]);
 			if (hdsp_fifo_wait (hdsp, 127, HDSP_LONG_WAIT)) {
-				snd_printk ("timeout during firmware loading\n");
+				snd_printk ("Hammerfall-DSP: timeout during firmware loading\n");
 				return -EIO;
 			}
 		}
@@ -687,7 +681,7 @@
 		}
 		
 		if (hdsp_fifo_wait (hdsp, 0, HDSP_LONG_WAIT)) {
-			snd_printk ("timeout at end of firmware loading\n");
+			snd_printk ("Hammerfall-DSP: timeout at end of firmware loading\n");
 		    	return -EIO;
 		}
 
@@ -697,11 +691,11 @@
 		hdsp->control2_register = 0;
 #endif
 		hdsp_write (hdsp, HDSP_control2Reg, hdsp->control2_register);
-		snd_printk ("finished firmware loading\n");
+		snd_printk ("Hammerfall-DSP: finished firmware loading\n");
 		
 	}
 	if (hdsp->state & HDSP_InitializationComplete) {
-		snd_printk("firmware loaded from cache, restoring defaults\n");
+		snd_printk("Hammerfall-DSP: firmware loaded from cache, restoring defaults\n");
 		spin_lock_irqsave(&hdsp->lock, flags);
 		snd_hdsp_set_defaults(hdsp);
 		spin_unlock_irqrestore(&hdsp->lock, flags); 
@@ -714,16 +708,6 @@
 
 static int hdsp_get_iobox_version (hdsp_t *hdsp)
 {
-	int err;
-	
-	if (hdsp_check_for_iobox (hdsp)) {
-		return -EIO;
-	}
-
-	if ((err = snd_hdsp_enable_io(hdsp)) < 0) {
-		return err;
-	}
-		
 	if ((hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DllError) != 0) {
 	
 		hdsp_write (hdsp, HDSP_control2Reg, HDSP_PROGRAM);
@@ -759,7 +743,7 @@
 {
 	if (hdsp->io_type == H9652 || hdsp->io_type == H9632) return 0;
 	if ((hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DllError) != 0) {
-		snd_printk("firmware not present.\n");
+		snd_printk("Hammerfall-DSP: firmware not present.\n");
 		hdsp->state &= ~HDSP_FirmwareLoaded;
 		return -EIO;
 	}
@@ -787,7 +771,7 @@
 		udelay (100);
 	}
 
-	snd_printk ("wait for FIFO status <= %d failed after %d iterations\n",
+	snd_printk ("Hammerfall-DSP: wait for FIFO status <= %d failed after %d iterations\n",
 		    count, timeout);
 	return -1;
 }
@@ -809,7 +793,7 @@
 	
 	if (hdsp->io_type == H9652 || hdsp->io_type == H9632) {
 
-		/* from martin bjÃ¶rnsen:
+		/* from martin bjornsen:
 		   
 		   "You can only write dwords to the
 		   mixer memory which contain two
@@ -922,7 +906,7 @@
 	default:
 		break;
 	}
-	snd_printk ("unknown spdif frequency status; bits = 0x%x, status = 0x%x\n", rate_bits, status);
+	snd_printk ("Hammerfall-DSP: unknown spdif frequency status; bits = 0x%x, status = 0x%x\n", rate_bits, status);
 	return 0;
 }
 
@@ -1008,7 +992,7 @@
 	if (!(hdsp->control_register & HDSP_ClockModeMaster)) {	
 		if (called_internally) {
 			/* request from ctl or card initialization */
-			snd_printk("device is not running as a clock master: cannot set sample rate.\n");
+			snd_printk("Hammerfall-DSP: device is not running as a clock master: cannot set sample rate.\n");
 			return -1;
 		} else {		
 			/* hw_param request while in AutoSync mode */
@@ -1016,11 +1000,11 @@
 			int spdif_freq = hdsp_spdif_sample_rate(hdsp);
 		
 			if ((spdif_freq == external_freq*2) && (hdsp_autosync_ref(hdsp) >= HDSP_AUTOSYNC_FROM_ADAT1)) {
-				snd_printk("Detected ADAT in double speed mode\n");
+				snd_printk("Hammerfall-DSP: Detected ADAT in double speed mode\n");
 			} else if (hdsp->io_type == H9632 && (spdif_freq == external_freq*4) && (hdsp_autosync_ref(hdsp) >= HDSP_AUTOSYNC_FROM_ADAT1)) {
-				snd_printk("Detected ADAT in quad speed mode\n");			
+				snd_printk("Hammerfall-DSP: Detected ADAT in quad speed mode\n");			
 			} else if (rate != external_freq) {
-				snd_printk("No AutoSync source for requested rate\n");
+				snd_printk("Hammerfall-DSP: No AutoSync source for requested rate\n");
 				return -1;
 			}		
 		}	
@@ -1102,7 +1086,7 @@
 	}
 
 	if (reject_if_open && (hdsp->capture_pid >= 0 || hdsp->playback_pid >= 0)) {
-		snd_printk ("cannot change speed mode (capture PID = %d, playback PID = %d)\n",
+		snd_printk ("Hammerfall-DSP: cannot change speed mode (capture PID = %d, playback PID = %d)\n",
 			    hdsp->capture_pid,
 			    hdsp->playback_pid);
 		return -EBUSY;
@@ -1143,68 +1127,6 @@
 	return 0;
 }
 
-static void hdsp_set_thru(hdsp_t *hdsp, int channel, int enable)
-{
-
-	hdsp->passthru = 0;
-
-	if (channel < 0) {
-
-		int i;
-
-		/* set thru for all channels */
-
-		if (enable) {
-			for (i = 0; i < hdsp->max_channels; i++) {
-				hdsp_write_gain (hdsp, hdsp_input_to_output_key(hdsp,i,i), UNITY_GAIN);
-			}
-		} else {
-			for (i = 0; i < hdsp->max_channels; i++) {
-				hdsp_write_gain (hdsp, hdsp_input_to_output_key(hdsp,i,i), MINUS_INFINITY_GAIN);
-			}
-		}
-
-	} else {
-		int mapped_channel;
-
-		snd_assert(channel < hdsp->max_channels, return);
-
-		mapped_channel = hdsp->channel_map[channel];
-
-		snd_assert(mapped_channel > -1, return);
-
-		if (enable) {
-			hdsp_write_gain (hdsp, hdsp_input_to_output_key(hdsp,mapped_channel,mapped_channel), UNITY_GAIN);
-		} else {
-			hdsp_write_gain (hdsp, hdsp_input_to_output_key(hdsp,mapped_channel,mapped_channel), MINUS_INFINITY_GAIN);
-		}
-	}
-}
-
-static int hdsp_set_passthru(hdsp_t *hdsp, int onoff)
-{
-	if (onoff) {
-		hdsp_set_thru(hdsp, -1, 1);
-		hdsp_reset_hw_pointer(hdsp);
-		hdsp_silence_playback(hdsp);
-
-		/* we don't want interrupts, so do a
-		   custom version of hdsp_start_audio().
-		*/
-
-		hdsp->control_register |= (HDSP_Start|HDSP_AudioInterruptEnable|hdsp_encode_latency(7));
-
-		hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
-		hdsp->passthru = 1;
-	} else {
-		hdsp_set_thru(hdsp, -1, 0);
-		hdsp_stop_audio(hdsp);		
-		hdsp->passthru = 0;
-	}
-
-	return 0;
-}
-
 /*----------------------------------------------------------------------------
    MIDI
   ----------------------------------------------------------------------------*/
@@ -1345,6 +1267,7 @@
 		}
 	} else {
 		hdsp->control_register &= ~ie;
+		tasklet_kill(&hdsp->midi_tasklet);
 	}
 
 	hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
@@ -2741,16 +2664,32 @@
 	return 0;
 }
 
-#define HDSP_PASSTHRU(xname, xindex) \
+#define HDSP_LINE_OUT(xname, xindex) \
 { .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \
   .name = xname, \
   .index = xindex, \
-  .info = snd_hdsp_info_passthru, \
-  .put = snd_hdsp_put_passthru, \
-  .get = snd_hdsp_get_passthru \
+  .info = snd_hdsp_info_line_out, \
+  .get = snd_hdsp_get_line_out, \
+  .put = snd_hdsp_put_line_out \
+}
+
+static int hdsp_line_out(hdsp_t *hdsp)
+{
+	return (hdsp->control_register & HDSP_LineOut) ? 1 : 0;
+}
+
+static int hdsp_set_line_output(hdsp_t *hdsp, int out)
+{
+	if (out) {
+		hdsp->control_register |= HDSP_LineOut;
+	} else {
+		hdsp->control_register &= ~HDSP_LineOut;
+	}
+	hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
+	return 0;
 }
 
-static int snd_hdsp_info_passthru(snd_kcontrol_t * kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_hdsp_info_line_out(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
 {
 	uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
 	uinfo->count = 1;
@@ -2759,61 +2698,106 @@
 	return 0;
 }
 
-static int snd_hdsp_get_passthru(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_hdsp_get_line_out(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
 	hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
-
+	
 	spin_lock_irq(&hdsp->lock);
-	ucontrol->value.integer.value[0] = hdsp->passthru;
+	ucontrol->value.integer.value[0] = hdsp_line_out(hdsp);
 	spin_unlock_irq(&hdsp->lock);
 	return 0;
 }
 
-static int snd_hdsp_put_passthru(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_hdsp_put_line_out(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
 	hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
 	int change;
 	unsigned int val;
-	int err = 0;
-
+	
 	if (!snd_hdsp_use_is_exclusive(hdsp))
 		return -EBUSY;
-
 	val = ucontrol->value.integer.value[0] & 1;
 	spin_lock_irq(&hdsp->lock);
-	change = (ucontrol->value.integer.value[0] != hdsp->passthru);
-	if (change)
-		err = hdsp_set_passthru(hdsp, val);
+	change = (int)val != hdsp_line_out(hdsp);
+	hdsp_set_line_output(hdsp, val);
 	spin_unlock_irq(&hdsp->lock);
-	return err ? err : change;
+	return change;
 }
 
-#define HDSP_LINE_OUT(xname, xindex) \
+#define HDSP_PRECISE_POINTER(xname, xindex) \
 { .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \
   .name = xname, \
   .index = xindex, \
-  .info = snd_hdsp_info_line_out, \
-  .get = snd_hdsp_get_line_out, \
-  .put = snd_hdsp_put_line_out \
+  .info = snd_hdsp_info_precise_pointer, \
+  .get = snd_hdsp_get_precise_pointer, \
+  .put = snd_hdsp_put_precise_pointer \
 }
 
-static int hdsp_line_out(hdsp_t *hdsp)
+static int hdsp_set_precise_pointer(hdsp_t *hdsp, int precise)
 {
-	return (hdsp->control_register & HDSP_LineOut) ? 1 : 0;
+	if (precise) {
+		hdsp->precise_ptr = 1;
+	} else {
+		hdsp->precise_ptr = 0;
+	}
+	return 0;
 }
 
-static int hdsp_set_line_output(hdsp_t *hdsp, int out)
+static int snd_hdsp_info_precise_pointer(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
 {
-	if (out) {
-		hdsp->control_register |= HDSP_LineOut;
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
+	uinfo->count = 1;
+	uinfo->value.integer.min = 0;
+	uinfo->value.integer.max = 1;
+	return 0;
+}
+
+static int snd_hdsp_get_precise_pointer(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+{
+	hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
+	
+	spin_lock_irq(&hdsp->lock);
+	ucontrol->value.integer.value[0] = hdsp->precise_ptr;
+	spin_unlock_irq(&hdsp->lock);
+	return 0;
+}
+
+static int snd_hdsp_put_precise_pointer(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+{
+	hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
+	int change;
+	unsigned int val;
+	
+	if (!snd_hdsp_use_is_exclusive(hdsp))
+		return -EBUSY;
+	val = ucontrol->value.integer.value[0] & 1;
+	spin_lock_irq(&hdsp->lock);
+	change = (int)val != hdsp->precise_ptr;
+	hdsp_set_precise_pointer(hdsp, val);
+	spin_unlock_irq(&hdsp->lock);
+	return change;
+}
+
+#define HDSP_USE_MIDI_TASKLET(xname, xindex) \
+{ .iface = SNDRV_CTL_ELEM_IFACE_HWDEP, \
+  .name = xname, \
+  .index = xindex, \
+  .info = snd_hdsp_info_use_midi_tasklet, \
+  .get = snd_hdsp_get_use_midi_tasklet, \
+  .put = snd_hdsp_put_use_midi_tasklet \
+}
+
+static int hdsp_set_use_midi_tasklet(hdsp_t *hdsp, int use_tasklet)
+{
+	if (use_tasklet) {
+		hdsp->use_midi_tasklet = 1;
 	} else {
-		hdsp->control_register &= ~HDSP_LineOut;
+		hdsp->use_midi_tasklet = 0;
 	}
-	hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
 	return 0;
 }
 
-static int snd_hdsp_info_line_out(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
+static int snd_hdsp_info_use_midi_tasklet(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
 {
 	uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
 	uinfo->count = 1;
@@ -2822,17 +2806,17 @@
 	return 0;
 }
 
-static int snd_hdsp_get_line_out(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_hdsp_get_use_midi_tasklet(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
 	hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
 	
 	spin_lock_irq(&hdsp->lock);
-	ucontrol->value.integer.value[0] = hdsp_line_out(hdsp);
+	ucontrol->value.integer.value[0] = hdsp->use_midi_tasklet;
 	spin_unlock_irq(&hdsp->lock);
 	return 0;
 }
 
-static int snd_hdsp_put_line_out(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
+static int snd_hdsp_put_use_midi_tasklet(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
 {
 	hdsp_t *hdsp = snd_kcontrol_chip(kcontrol);
 	int change;
@@ -2842,8 +2826,8 @@
 		return -EBUSY;
 	val = ucontrol->value.integer.value[0] & 1;
 	spin_lock_irq(&hdsp->lock);
-	change = (int)val != hdsp_line_out(hdsp);
-	hdsp_set_line_output(hdsp, val);
+	change = (int)val != hdsp->use_midi_tasklet;
+	hdsp_set_use_midi_tasklet(hdsp, val);
 	spin_unlock_irq(&hdsp->lock);
 	return change;
 }
@@ -3139,8 +3123,9 @@
 HDSP_WC_SYNC_CHECK("Word Clock Lock Status", 0),
 HDSP_SPDIF_SYNC_CHECK("SPDIF Lock Status", 0),
 HDSP_ADATSYNC_SYNC_CHECK("ADAT Sync Lock Status", 0),
-HDSP_PASSTHRU("Passthru", 0),
 HDSP_LINE_OUT("Line Out", 0),
+HDSP_PRECISE_POINTER("Precise Pointer", 0),
+HDSP_USE_MIDI_TASKLET("Use Midi Tasklet", 0),
 };
 
 static snd_kcontrol_new_t snd_hdsp_96xx_aeb = HDSP_AEB("Analog Extension Board", 0);
@@ -3240,11 +3225,11 @@
 	snd_iprintf(buffer, "Status register: 0x%x\n", status);
 	snd_iprintf(buffer, "Status2 register: 0x%x\n", status2);
 	snd_iprintf(buffer, "FIFO status: %d\n", hdsp_read(hdsp, HDSP_fifoStatus) & 0xff);
-
 	snd_iprintf(buffer, "MIDI1 Output status: 0x%x\n", hdsp_read(hdsp, HDSP_midiStatusOut0));
 	snd_iprintf(buffer, "MIDI1 Input status: 0x%x\n", hdsp_read(hdsp, HDSP_midiStatusIn0));
 	snd_iprintf(buffer, "MIDI2 Output status: 0x%x\n", hdsp_read(hdsp, HDSP_midiStatusOut1));
 	snd_iprintf(buffer, "MIDI2 Input status: 0x%x\n", hdsp_read(hdsp, HDSP_midiStatusIn1));
+	snd_iprintf(buffer, "Use Midi Tasklet: %s\n", hdsp->use_midi_tasklet ? "on" : "off");
 
 	snd_iprintf(buffer, "\n");
 
@@ -3252,7 +3237,7 @@
 
 	snd_iprintf(buffer, "Buffer Size (Latency): %d samples (2 periods of %lu bytes)\n", x, (unsigned long) hdsp->period_bytes);
 	snd_iprintf(buffer, "Hardware pointer (frames): %ld\n", hdsp_hw_pointer(hdsp));
-	snd_iprintf(buffer, "Passthru: %s\n", hdsp->passthru ? "yes" : "no");
+	snd_iprintf(buffer, "Precise pointer: %s\n", hdsp->precise_ptr ? "on" : "off");
 	snd_iprintf(buffer, "Line out: %s\n", (hdsp->control_register & HDSP_LineOut) ? "on" : "off");
 
 	snd_iprintf(buffer, "Firmware version: %d\n", (status2&HDSP_version0)|(status2&HDSP_version1)<<1|(status2&HDSP_version2)<<2);
@@ -3612,40 +3597,6 @@
 		}
 	}
 	
-	if ((hdsp->io_type != H9652) && line_outs_monitor[hdsp->dev]) {
-		
-		int lineouts_base;
-		
-		snd_printk ("sending all inputs and playback streams to line outs.\n");
-
-		/* route all inputs to the line outs for easy monitoring. send
-		   odd numbered channels to right, even to left.
-		*/
-		if (hdsp->io_type == H9632) {
-			/* this is the phones/analog output */
-			lineouts_base = 10;
-		} else {
-			lineouts_base = 26;
-		}
-		
-		for (i = 0; i < hdsp->max_channels; i++) {
-			if (i & 1) { 
-				if (hdsp_write_gain (hdsp, hdsp_input_to_output_key (hdsp, i, lineouts_base), UNITY_GAIN) ||
-				    hdsp_write_gain (hdsp, hdsp_playback_to_output_key (hdsp, i, lineouts_base), UNITY_GAIN)) {
-				    return -EIO;
-				}    
-			} else {
-				if (hdsp_write_gain (hdsp, hdsp_input_to_output_key (hdsp, i, lineouts_base+1), UNITY_GAIN) ||
-				    hdsp_write_gain (hdsp, hdsp_playback_to_output_key (hdsp, i, lineouts_base+1), UNITY_GAIN)) {
-				    
-				    return -EIO;
-				}
-			}
-		}
-	}
-
-	hdsp->passthru = 0;
-
 	/* H9632 specific defaults */
 	if (hdsp->io_type == H9632) {
 		hdsp->control_register |= (HDSP_DAGainPlus4dBu | HDSP_ADGainPlus4dBu | HDSP_PhoneGain0dB);
@@ -3709,21 +3660,29 @@
 	}
 	
 	if (midi0 && midi0status) {
-		/* we disable interrupts for this input until processing is done */
-		hdsp->control_register &= ~HDSP_Midi0InterruptEnable;
-		hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
-		hdsp->midi[0].pending = 1;
-		schedule = 1;
+		if (hdsp->use_midi_tasklet) {
+			/* we disable interrupts for this input until processing is done */
+			hdsp->control_register &= ~HDSP_Midi0InterruptEnable;
+			hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
+			hdsp->midi[0].pending = 1;
+			schedule = 1;
+		} else {
+			snd_hdsp_midi_input_read (&hdsp->midi[0]);
+		}
 	}
-	if (midi1 && midi1status) {
-		/* we disable interrupts for this input until processing is done */
-		hdsp->control_register &= ~HDSP_Midi1InterruptEnable;
-		hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
-		hdsp->midi[1].pending = 1;
-		schedule = 1;
+	if (hdsp->io_type != Multiface && hdsp->io_type != H9632 && midi1 && midi1status) {
+		if (hdsp->use_midi_tasklet) {
+			/* we disable interrupts for this input until processing is done */
+			hdsp->control_register &= ~HDSP_Midi1InterruptEnable;
+			hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
+			hdsp->midi[1].pending = 1;
+			schedule = 1;
+		} else {
+			snd_hdsp_midi_input_read (&hdsp->midi[1]);
+		}
 	}
-	if (schedule)
-	    tasklet_hi_schedule(&hdsp->midi_tasklet);
+	if (hdsp->use_midi_tasklet && schedule)
+		tasklet_hi_schedule(&hdsp->midi_tasklet);
 	return IRQ_HANDLED;
 }
 
@@ -3838,10 +3797,10 @@
 	if (hdsp_check_for_firmware(hdsp)) {
 		if (hdsp->state & HDSP_FirmwareCached) {
 			if (snd_hdsp_load_firmware_from_cache(hdsp) != 0) {
-				snd_printk("Firmware loading from cache failed, please upload manually.\n");
+				snd_printk("Hammerfall-DSP: Firmware loading from cache failed, please upload manually.\n");
 			}
 		} else {
-			snd_printk("No firmware loaded nor cached, please upload firmware.\n");
+			snd_printk("Hammerfall-DSP: No firmware loaded nor cached, please upload firmware.\n");
 		}
 		return -EIO;
 	}
@@ -3946,6 +3905,7 @@
 
 static int snd_hdsp_trigger(snd_pcm_substream_t *substream, int cmd)
 {
+	unsigned long flags;
 	hdsp_t *hdsp = snd_pcm_substream_chip(substream);
 	snd_pcm_substream_t *other;
 	int running;
@@ -3957,15 +3917,15 @@
 	if (hdsp_check_for_firmware(hdsp)) {
 		if (hdsp->state & HDSP_FirmwareCached) {
 			if (snd_hdsp_load_firmware_from_cache(hdsp) != 0) {
-				snd_printk("Firmware loading from cache failed, please upload manually.\n");
+				snd_printk("Hammerfall-DSP: Firmware loading from cache failed, please upload manually.\n");
 			}
 		} else {
-			snd_printk("No firmware loaded nor cached, please upload firmware.\n");
+			snd_printk("Hammerfall-DSP: No firmware loaded nor cached, please upload firmware.\n");
 		}
 		return -EIO;
 	}
 
-	spin_lock(&hdsp->lock);
+	spin_lock_irqsave(&hdsp->lock, flags);
 	running = hdsp->running;
 	switch (cmd) {
 	case SNDRV_PCM_TRIGGER_START:
@@ -3976,7 +3936,7 @@
 		break;
 	default:
 		snd_BUG();
-		spin_unlock(&hdsp->lock);
+		spin_unlock_irqrestore(&hdsp->lock, flags);
 		return -EINVAL;
 	}
 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
@@ -4018,7 +3978,7 @@
 	else if (hdsp->running && !running)
 		hdsp_stop_audio(hdsp);
 	hdsp->running = running;
-	spin_unlock(&hdsp->lock);
+	spin_unlock_irqrestore(&hdsp->lock, flags);
 
 	return 0;
 }
@@ -4035,10 +3995,10 @@
 	if (hdsp_check_for_firmware(hdsp)) {
 		if (hdsp->state & HDSP_FirmwareCached) {
 			if (snd_hdsp_load_firmware_from_cache(hdsp) != 0) {
-				snd_printk("Firmware loading from cache failed, please upload manually.\n");
+				snd_printk("Hammerfall-DSP: Firmware loading from cache failed, please upload manually.\n");
 			}
 		} else {
-			snd_printk("No firmware loaded nor cached, please upload firmware.\n");
+			snd_printk("Hammerfall-DSP: No firmware loaded nor cached, please upload firmware.\n");
 		}
 		return -EIO;
 	}
@@ -4057,7 +4017,11 @@
 				 SNDRV_PCM_INFO_NONINTERLEAVED |
 				 SNDRV_PCM_INFO_SYNC_START |
 				 SNDRV_PCM_INFO_DOUBLE),
+#ifdef SNDRV_BIG_ENDIAN
+	.formats =		SNDRV_PCM_FMTBIT_S32_BE,
+#else
 	.formats =		SNDRV_PCM_FMTBIT_S32_LE,
+#endif
 	.rates =		(SNDRV_PCM_RATE_32000 |
 				 SNDRV_PCM_RATE_44100 | 
 				 SNDRV_PCM_RATE_48000 | 
@@ -4082,7 +4046,11 @@
 				 SNDRV_PCM_INFO_MMAP_VALID |
 				 SNDRV_PCM_INFO_NONINTERLEAVED |
 				 SNDRV_PCM_INFO_SYNC_START),
+#ifdef SNDRV_BIG_ENDIAN
+	.formats =		SNDRV_PCM_FMTBIT_S32_BE,
+#else
 	.formats =		SNDRV_PCM_FMTBIT_S32_LE,
+#endif
 	.rates =		(SNDRV_PCM_RATE_32000 |
 				 SNDRV_PCM_RATE_44100 | 
 				 SNDRV_PCM_RATE_48000 | 
@@ -4290,10 +4258,10 @@
 	if (hdsp_check_for_firmware(hdsp)) {
 		if (hdsp->state & HDSP_FirmwareCached) {
 			if (snd_hdsp_load_firmware_from_cache(hdsp) != 0) {
-				snd_printk("Firmware loading from cache failed, please upload manually.\n");
+				snd_printk("Hammerfall-DSP: Firmware loading from cache failed, please upload manually.\n");
 			}
 		} else {
-			snd_printk("No firmware loaded nor cached, please upload firmware.\n");
+			snd_printk("Hammerfall-DSP: No firmware loaded nor cached, please upload firmware.\n");
 		}
 		return -EIO;
 	}
@@ -4306,11 +4274,6 @@
 	runtime->dma_area = hdsp->playback_buffer;
 	runtime->dma_bytes = HDSP_DMA_AREA_BYTES;
 
-	if (hdsp->capture_substream == NULL) {
-		hdsp_stop_audio(hdsp);
-		hdsp_set_thru(hdsp, -1, 0);
-	}
-
 	hdsp->playback_pid = current->pid;
 	hdsp->playback_substream = substream;
 
@@ -4373,10 +4336,10 @@
 	if (hdsp_check_for_firmware(hdsp)) {
 		if (hdsp->state & HDSP_FirmwareCached) {
 			if (snd_hdsp_load_firmware_from_cache(hdsp) != 0) {
-				snd_printk("Firmware loading from cache failed, please upload manually.\n");
+				snd_printk("Hammerfall-DSP: Firmware loading from cache failed, please upload manually.\n");
 			}
 		} else {
-			snd_printk("No firmware loaded nor cached, please upload firmware.\n");
+			snd_printk("Hammerfall-DSP: No firmware loaded nor cached, please upload firmware.\n");
 		}
 		return -EIO;
 	}
@@ -4389,11 +4352,6 @@
 	runtime->dma_area = hdsp->capture_buffer;
 	runtime->dma_bytes = HDSP_DMA_AREA_BYTES;
 
-	if (hdsp->playback_substream == NULL) {
-		hdsp_stop_audio(hdsp);
-		hdsp_set_thru(hdsp, -1, 0);
-	}
-
 	hdsp->capture_pid = current->pid;
 	hdsp->capture_substream = substream;
 
@@ -4553,12 +4511,12 @@
 	}
 	for (i = 0; i < 26; ++i) {
 		if (copy_u64_le(&peak_rms->playback_rms[i],
-				hdsp->iobase + HDSP_playbackRmsLevel + i * 8,
-				hdsp->iobase + HDSP_playbackRmsLevel + i * 8 + 4))
+				hdsp->iobase + HDSP_playbackRmsLevel + i * 8 + 4,
+				hdsp->iobase + HDSP_playbackRmsLevel + i * 8))
 			return -EFAULT;
 		if (copy_u64_le(&peak_rms->input_rms[i], 
-				hdsp->iobase + HDSP_inputRmsLevel + i * 8,
-				hdsp->iobase + HDSP_inputRmsLevel + i * 8 + 4))
+				hdsp->iobase + HDSP_inputRmsLevel + i * 8 + 4,
+				hdsp->iobase + HDSP_inputRmsLevel + i * 8))
 			return -EFAULT;
 	}
 	return 0;
@@ -4574,7 +4532,7 @@
 		hdsp_peak_rms_t __user *peak_rms = (hdsp_peak_rms_t __user *)arg;
 
 		if (!(hdsp->state & HDSP_FirmwareLoaded)) {
-			snd_printk(KERN_ERR "firmware needs to be uploaded to the card.\n");
+			snd_printk(KERN_ERR "Hammerfall-DSP: firmware needs to be uploaded to the card.\n");
 			return -EINVAL;
 		}
 
@@ -4593,7 +4551,7 @@
 		int i;
 		
 		if (!(hdsp->state & HDSP_FirmwareLoaded)) {
-			snd_printk("Firmware needs to be uploaded to the card.\n");	
+			snd_printk("Hammerfall-DSP: Firmware needs to be uploaded to the card.\n");	
 			return -EINVAL;
 		}
 		spin_lock_irqsave(&hdsp->lock, flags);
@@ -4618,7 +4576,6 @@
 		info.clock_source = (unsigned char)hdsp_clock_source(hdsp);
 		info.autosync_ref = (unsigned char)hdsp_autosync_ref(hdsp);
 		info.line_out = (unsigned char)hdsp_line_out(hdsp);
-		info.passthru = (unsigned char)hdsp->passthru;
 		if (hdsp->io_type == H9632) {
 			info.da_gain = (unsigned char)hdsp_da_gain(hdsp);
 			info.ad_gain = (unsigned char)hdsp_ad_gain(hdsp);
@@ -4661,7 +4618,6 @@
 		}
 		break;
 	}
-#ifndef HDSP_FW_LOADER
 	case SNDRV_HDSP_IOCTL_UPLOAD_FIRMWARE: {
 		hdsp_firmware_t __user *firmware;
 		u32 __user *firmware_data;
@@ -4674,7 +4630,7 @@
 		if (hdsp->state & (HDSP_FirmwareCached | HDSP_FirmwareLoaded))
 			return -EBUSY;
 
-		snd_printk("initializing firmware upload\n");
+		snd_printk("Hammerfall-DSP: initializing firmware upload\n");
 		firmware = (hdsp_firmware_t __user *)argp;
 
 		if (get_user(firmware_data, &firmware->firmware_data)) {
@@ -4696,18 +4652,20 @@
 		}
 		
 		if (!(hdsp->state & HDSP_InitializationComplete)) {
-			snd_hdsp_initialize_channels(hdsp);
-		
+			if ((err = snd_hdsp_enable_io(hdsp)) < 0) {
+				return err;
+			}
+			
+			snd_hdsp_initialize_channels(hdsp);		
 			snd_hdsp_initialize_midi_flush(hdsp);
 	    
 			if ((err = snd_hdsp_create_alsa_devices(hdsp->card, hdsp)) < 0) {
-				snd_printk("error creating alsa devices\n");
+				snd_printk("Hammerfall-DSP: error creating alsa devices\n");
 			    return err;
 			}
 		}
 		break;
 	}
-#endif
 	case SNDRV_HDSP_IOCTL_GET_MIXER: {
 		hdsp_mixer_t __user *mixer = (hdsp_mixer_t __user *)argp;
 		if (copy_to_user(mixer->matrix, hdsp->mixer_matrix, sizeof(unsigned short)*HDSP_MATRIX_MIXER_SIZE))
@@ -4794,6 +4752,7 @@
 	int i;
 	
 	if (hdsp_fifo_wait (hdsp, 0, 100)) {
+		snd_printk("Hammerfall-DSP: enable_io fifo_wait failed\n");
 		return -EIO;
 	}
 	
@@ -4859,24 +4818,25 @@
 	int err;
 	
 	if ((err = snd_hdsp_create_pcm(card, hdsp)) < 0) {
-		snd_printk("Error creating pcm interface\n");
+		snd_printk("Hammerfall-DSP: Error creating pcm interface\n");
 		return err;
 	}
 	
 
 	if ((err = snd_hdsp_create_midi(card, hdsp, 0)) < 0) {
-		snd_printk("Error creating first midi interface\n");
+		snd_printk("Hammerfall-DSP: Error creating first midi interface\n");
 		return err;
 	}
 
-
-	if ((err = snd_hdsp_create_midi(card, hdsp, 1)) < 0) {
-		snd_printk("Error creating second midi interface\n");
-		return err;
+	if (hdsp->io_type == Digiface || hdsp->io_type == H9652) {
+		if ((err = snd_hdsp_create_midi(card, hdsp, 1)) < 0) {
+			snd_printk("Hammerfall-DSP: Error creating second midi interface\n");
+			return err;
+		}
 	}
 
 	if ((err = snd_hdsp_create_controls(card, hdsp)) < 0) {
-		snd_printk("Error creating ctl interface\n");
+		snd_printk("Hammerfall-DSP: Error creating ctl interface\n");
 		return err;
 	}
 
@@ -4889,7 +4849,7 @@
 	hdsp->playback_substream = NULL;
 
 	if ((err = snd_hdsp_set_defaults(hdsp)) < 0) {
-		snd_printk("Error setting default values\n");
+		snd_printk("Hammerfall-DSP: Error setting default values\n");
 		return err;
 	}
 	
@@ -4898,7 +4858,7 @@
 			hdsp->port, hdsp->irq);
 	    
 		if ((err = snd_card_register(card)) < 0) {
-			snd_printk("error registering card\n");
+			snd_printk("Hammerfall-DSP: error registering card\n");
 			return err;
 		}
 		hdsp->state |= HDSP_InitializationComplete;
@@ -4923,9 +4883,7 @@
 		if (hdsp->io_type == H9652 || hdsp->io_type == H9632)
 			return 0;
 	}
-	if (hdsp_check_for_iobox (hdsp))
-		return -EIO;
-
+	
 	/* caution: max length of firmware filename is 30! */
 	switch (hdsp->io_type) {
 	case Multiface:
@@ -4941,16 +4899,16 @@
 			fwfile = "digiface_firmware_rev11.bin";
 		break;
 	default:
-		snd_printk(KERN_ERR "hdsp: invalid io_type %d\n", hdsp->io_type);
+		snd_printk(KERN_ERR "Hammerfall-DSP: invalid io_type %d\n", hdsp->io_type);
 		return -EINVAL;
 	}
 
 	if (request_firmware(&fw, fwfile, &hdsp->pci->dev)) {
-		snd_printk(KERN_ERR "hdsp: cannot load firmware %s\n", fwfile);
+		snd_printk(KERN_ERR "Hammerfall-DSP: cannot load firmware %s\n", fwfile);
 		return -ENOENT;
 	}
 	if (fw->size < sizeof(hdsp->firmware_cache)) {
-		snd_printk(KERN_ERR "hdsp: too short firmware size %d (expected %d)\n",
+		snd_printk(KERN_ERR "Hammerfall-DSP: too short firmware size %d (expected %d)\n",
 			   (int)fw->size, (int)sizeof(hdsp->firmware_cache));
 		release_firmware(fw);
 		return -EINVAL;
@@ -4958,7 +4916,7 @@
 #ifdef SNDRV_BIG_ENDIAN
 	{
 		int i;
-		u32 *src = (void *)fw->data;
+		u32 *src = (u32*)fw->data;
 		for (i = 0; i < ARRAY_SIZE(hdsp->firmware_cache); i++, src++)
 			hdsp->firmware_cache[i] = ((*src & 0x000000ff) << 16) |
 				((*src & 0x0000ff00) << 8)  |
@@ -4969,17 +4927,25 @@
 	memcpy(hdsp->firmware_cache, fw->data, sizeof(hdsp->firmware_cache));
 #endif
 	release_firmware(fw);
-	
+		
 	hdsp->state |= HDSP_FirmwareCached;
 
 	if ((err = snd_hdsp_load_firmware_from_cache(hdsp)) < 0)
 		return err;
 		
 	if (!(hdsp->state & HDSP_InitializationComplete)) {
+		if ((err = snd_hdsp_enable_io(hdsp)) < 0) {
+			return err;
+		}
+
+		if ((err = snd_hdsp_create_hwdep(hdsp->card, hdsp)) < 0) {
+			snd_printk("Hammerfall-DSP: error creating hwdep device\n");
+			return err;
+		}
 		snd_hdsp_initialize_channels(hdsp);
 		snd_hdsp_initialize_midi_flush(hdsp);
 		if ((err = snd_hdsp_create_alsa_devices(hdsp->card, hdsp)) < 0) {
-			snd_printk("error creating alsa devices\n");
+			snd_printk("Hammerfall-DSP: error creating alsa devices\n");
 			return err;
 		}
 	}
@@ -4988,8 +4954,7 @@
 #endif
 
 static int __devinit snd_hdsp_create(snd_card_t *card,
-				     hdsp_t *hdsp,
-				     int precise_ptr)
+				     hdsp_t *hdsp)
 {
 	struct pci_dev *pci = hdsp->pci;
 	int err;
@@ -5004,6 +4969,8 @@
 	hdsp->midi[1].input = NULL;
 	hdsp->midi[0].output = NULL;
 	hdsp->midi[1].output = NULL;
+	hdsp->midi[0].pending = 0;
+	hdsp->midi[1].pending = 0;
 	spin_lock_init(&hdsp->midi[0].lock);
 	spin_lock_init(&hdsp->midi[1].lock);
 	hdsp->iobase = NULL;
@@ -5019,6 +4986,7 @@
 	tasklet_init(&hdsp->midi_tasklet, hdsp_midi_tasklet, (unsigned long)hdsp);
 	
 	pci_read_config_word(hdsp->pci, PCI_CLASS_REVISION, &hdsp->firmware_rev);
+	hdsp->firmware_rev &= 0xff;
 	
 	/* From Martin Bjoernsen :
 	    "It is important that the card's latency timer register in
@@ -5032,27 +5000,17 @@
 	strcpy(card->driver, "H-DSP");
 	strcpy(card->mixername, "Xilinx FPGA");
 
-	switch (hdsp->firmware_rev & 0xff) {
-	case 0xa:
-	case 0xb:
-	case 0x32:
+	if (hdsp->firmware_rev < 0xa) {
+		return -ENODEV;
+	} else if (hdsp->firmware_rev < 0x64) {
 		hdsp->card_name = "RME Hammerfall DSP";
-		break;
-
-	case 0x64:
-	case 0x65:
-	case 0x68:
+	} else if (hdsp->firmware_rev < 0x96) {
 		hdsp->card_name = "RME HDSP 9652";
 		is_9652 = 1;
-		break;
-	case 0x96:
-	case 0x97:
+	} else {
 		hdsp->card_name = "RME HDSP 9632";
 		hdsp->max_channels = 16;
-		is_9632 = 1;
-		break;
-	default:
-		return -ENODEV;
+		is_9632 = 1;	
 	}
 
 	if ((err = pci_enable_device(pci)) < 0) {
@@ -5065,56 +5023,65 @@
 		return err;
 	hdsp->port = pci_resource_start(pci, 0);
 	if ((hdsp->iobase = ioremap_nocache(hdsp->port, HDSP_IO_EXTENT)) == NULL) {
-		snd_printk("unable to remap region 0x%lx-0x%lx\n", hdsp->port, hdsp->port + HDSP_IO_EXTENT - 1);
+		snd_printk("Hammerfall-DSP: unable to remap region 0x%lx-0x%lx\n", hdsp->port, hdsp->port + HDSP_IO_EXTENT - 1);
 		return -EBUSY;
 	}
 
 	if (request_irq(pci->irq, snd_hdsp_interrupt, SA_INTERRUPT|SA_SHIRQ, "hdsp", (void *)hdsp)) {
-		snd_printk("unable to use IRQ %d\n", pci->irq);
+		snd_printk("Hammerfall-DSP: unable to use IRQ %d\n", pci->irq);
 		return -EBUSY;
 	}
 
 	hdsp->irq = pci->irq;
-	hdsp->precise_ptr = precise_ptr;
+	hdsp->precise_ptr = 1;
+	hdsp->use_midi_tasklet = 1;
 
 	if ((err = snd_hdsp_initialize_memory(hdsp)) < 0) {
 		return err;
 	}
 	
-	if (!is_9652 && !is_9632 && hdsp_check_for_iobox (hdsp)) {
-		/* no iobox connected, we defer initialization */
-		snd_printk("card initialization pending : waiting for firmware\n");
-		if ((err = snd_hdsp_create_hwdep(card, hdsp)) < 0) {
-			return err;
+	if (!is_9652 && !is_9632) {
+		/* we wait 2 seconds to let freshly inserted cardbus cards do their hardware init */
+ 		if ((1000 / HZ) < 2000) {
+			set_current_state(TASK_UNINTERRUPTIBLE);
+			schedule_timeout((2000 * HZ + 999) / 1000);
+		} else {
+			mdelay(2000);
+		}
+
+		if ((hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DllError) != 0) {
+#ifdef HDSP_FW_LOADER
+			if ((err = hdsp_request_fw_loader(hdsp)) < 0) {
+				/* we don't fail as this can happen
+				   if userspace is not ready for
+				   firmware upload
+				*/
+				snd_printk("Hammerfall-DSP: couldn't get firmware from userspace. try using hdsploader\n");
+			} else {
+				/* init is complete, we return */
+				return 0;
+			}
+#endif
+			/* no iobox connected, we defer initialization */
+			snd_printk("Hammerfall-DSP: card initialization pending : waiting for firmware\n");
+			if ((err = snd_hdsp_create_hwdep(card, hdsp)) < 0) {
+				return err;
+			}
+			return 0;
+		} else {
+			snd_printk("Hammerfall-DSP: Firmware already present, initializing card.\n");	    
+			if (hdsp_read(hdsp, HDSP_status2Register) & HDSP_version1) {
+				hdsp->io_type = Multiface;
+			} else {
+				hdsp->io_type = Digiface;
+			}
 		}
-		return 0;
 	}
 	
 	if ((err = snd_hdsp_enable_io(hdsp)) != 0) {
 		return err;
 	}
 	
-	if ((hdsp_read (hdsp, HDSP_statusRegister) & HDSP_DllError) != 0) {
-#ifdef HDSP_FW_LOADER
-		if ((err = hdsp_request_fw_loader(hdsp)) < 0)
-			return err;
-#else
-		snd_printk("card initialization pending : waiting for firmware\n");
-		if ((err = snd_hdsp_create_hwdep(card, hdsp)) < 0) {
-			return err;
-		}
-		return 0;
-#endif
-	} 
-	
-	snd_printk("Firmware already loaded, initializing card.\n");
-	
-	if (hdsp_read(hdsp, HDSP_status2Register) & HDSP_version1) {
-		hdsp->io_type = Multiface;
-	} else {
-		hdsp->io_type = Digiface;
-	}
-
 	if (is_9652) {
 	        hdsp->io_type = H9652;
 	}
@@ -5143,6 +5110,7 @@
 {
 	if (hdsp->port) {
 		/* stop the audio, and cancel all interrupts */
+		tasklet_kill(&hdsp->midi_tasklet);
 		hdsp->control_register &= ~(HDSP_Start|HDSP_AudioInterruptEnable|HDSP_Midi0InterruptEnable|HDSP_Midi1InterruptEnable);
 		hdsp_write (hdsp, HDSP_controlRegister, hdsp->control_register);
 	}
@@ -5194,7 +5162,7 @@
 	hdsp->pci = pci;
 	snd_card_set_dev(card, &pci->dev);
 
-	if ((err = snd_hdsp_create(card, hdsp, precise_ptr[dev])) < 0) {
+	if ((err = snd_hdsp_create(card, hdsp)) < 0) {
 		snd_card_free(card);
 		return err;
 	}
diff -Nru a/sound/pci/sonicvibes.c b/sound/pci/sonicvibes.c
--- a/sound/pci/sonicvibes.c	2005-03-11 12:51:47 -08:00
+++ b/sound/pci/sonicvibes.c	2005-03-11 12:51:47 -08:00
@@ -46,6 +46,10 @@
 MODULE_LICENSE("GPL");
 MODULE_SUPPORTED_DEVICE("{{S3,SonicVibes PCI}}");
 
+#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))
+#define SUPPORT_JOYSTICK 1
+#endif
+
 #ifndef PCI_VENDOR_ID_S3
 #define PCI_VENDOR_ID_S3             0x5333
 #endif
@@ -242,8 +246,8 @@
 	snd_kcontrol_t *master_mute;
 	snd_kcontrol_t *master_volume;
 
-#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))
-	struct gameport gameport;
+#ifdef SUPPORT_JOYSTICK
+	struct gameport *gameport;
 #endif
 };
 
@@ -1163,15 +1167,47 @@
 
  */
 
+#ifdef SUPPORT_JOYSTICK
 static snd_kcontrol_new_t snd_sonicvibes_game_control __devinitdata =
 SONICVIBES_SINGLE("Joystick Speed", 0, SV_IREG_GAME_PORT, 1, 15, 0);
 
-static int snd_sonicvibes_free(sonicvibes_t *sonic)
+static int __devinit snd_sonicvibes_create_gameport(sonicvibes_t *sonic)
 {
-#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))
-	if (sonic->gameport.io)
-		gameport_unregister_port(&sonic->gameport);
+	struct gameport *gp;
+
+	sonic->gameport = gp = gameport_allocate_port();
+	if (!gp) {
+		printk(KERN_ERR "sonicvibes: cannot allocate memory for gameport\n");
+		return -ENOMEM;
+	}
+
+	gameport_set_name(gp, "SonicVibes Gameport");
+	gameport_set_phys(gp, "pci%s/gameport0", pci_name(sonic->pci));
+	gp->dev.parent = &sonic->pci->dev;
+	gp->io = sonic->game_port;
+
+	gameport_register_port(gp);
+
+	snd_ctl_add(sonic->card, snd_ctl_new1(&snd_sonicvibes_game_control, sonic));
+
+	return 0;
+}
+
+static void snd_sonicvibes_free_gameport(sonicvibes_t *sonic)
+{
+	if (sonic->gameport) {
+		gameport_unregister_port(sonic->gameport);
+		sonic->gameport = NULL;
+	}
+}
+#else
+static inline int snd_sonicvibes_create_gameport(sonicvibes_t *sonic) { return -ENOSYS; }
+static inline void snd_sonicvibes_free_gameport(sonicvibes_t *sonic) { }
 #endif
+
+static int snd_sonicvibes_free(sonicvibes_t *sonic)
+{
+	snd_sonicvibes_free_gameport(sonic);
 	pci_write_config_dword(sonic->pci, 0x40, sonic->dmaa_port);
 	pci_write_config_dword(sonic->pci, 0x48, sonic->dmac_port);
 	if (sonic->irq >= 0)
@@ -1332,7 +1368,6 @@
 	snd_sonicvibes_debug(sonic);
 #endif
 	sonic->revision = snd_sonicvibes_in(sonic, SV_IREG_REVISION);
-	snd_ctl_add(card, snd_ctl_new1(&snd_sonicvibes_game_control, sonic));
 
 	if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, sonic, &ops)) < 0) {
 		snd_sonicvibes_free(sonic);
@@ -1459,10 +1494,8 @@
 		snd_card_free(card);
 		return err;
 	}
-#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))
-	sonic->gameport.io = sonic->game_port;
-	gameport_register_port(&sonic->gameport);
-#endif
+
+	snd_sonicvibes_create_gameport(sonic);
 
 	if ((err = snd_card_register(card)) < 0) {
 		snd_card_free(card);
diff -Nru a/sound/pci/trident/trident.c b/sound/pci/trident/trident.c
--- a/sound/pci/trident/trident.c	2005-03-11 12:51:40 -08:00
+++ b/sound/pci/trident/trident.c	2005-03-11 12:51:40 -08:00
@@ -157,7 +157,7 @@
 	}
 #endif
 
-	snd_trident_gameport(trident);
+	snd_trident_create_gameport(trident);
 
 	if ((err = snd_card_register(card)) < 0) {
 		snd_card_free(card);
diff -Nru a/sound/pci/trident/trident_main.c b/sound/pci/trident/trident_main.c
--- a/sound/pci/trident/trident_main.c	2005-03-11 12:51:47 -08:00
+++ b/sound/pci/trident/trident_main.c	2005-03-11 12:51:47 -08:00
@@ -48,8 +48,8 @@
 static int snd_trident_pcm_mixer_free(trident_t *trident, snd_trident_voice_t * voice, snd_pcm_substream_t *substream);
 static irqreturn_t snd_trident_interrupt(int irq, void *dev_id, struct pt_regs *regs);
 #ifdef CONFIG_PM
-static int snd_trident_suspend(snd_card_t *card, unsigned int state);
-static int snd_trident_resume(snd_card_t *card, unsigned int state);
+static int snd_trident_suspend(snd_card_t *card, pm_message_t state);
+static int snd_trident_resume(snd_card_t *card);
 #endif
 static int snd_trident_sis_reset(trident_t *trident);
 
@@ -3110,37 +3110,28 @@
 
 #if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))
 
-typedef struct snd_trident_gameport {
-	struct gameport info;
-	trident_t *chip;
-} trident_gameport_t;
-
 static unsigned char snd_trident_gameport_read(struct gameport *gameport)
 {
-	trident_gameport_t *gp = (trident_gameport_t *)gameport;
-	trident_t *chip;
-	snd_assert(gp, return 0);
-	chip = gp->chip;
+	trident_t *chip = gameport->port_data;
+
+	snd_assert(chip, return 0);
 	return inb(TRID_REG(chip, GAMEPORT_LEGACY));
 }
 
 static void snd_trident_gameport_trigger(struct gameport *gameport)
 {
-	trident_gameport_t *gp = (trident_gameport_t *)gameport;
-	trident_t *chip;
-	snd_assert(gp, return);
-	chip = gp->chip;
+	trident_t *chip = gameport->port_data;
+
+	snd_assert(chip, return);
 	outb(0xff, TRID_REG(chip, GAMEPORT_LEGACY));
 }
 
 static int snd_trident_gameport_cooked_read(struct gameport *gameport, int *axes, int *buttons)
 {
-	trident_gameport_t *gp = (trident_gameport_t *)gameport;
-	trident_t *chip;
+	trident_t *chip = gameport->port_data;
 	int i;
 
-	snd_assert(gp, return 0);
-	chip = gp->chip;
+	snd_assert(chip, return 0);
 
 	*buttons = (~inb(TRID_REG(chip, GAMEPORT_LEGACY)) >> 4) & 0xf;
 
@@ -3154,10 +3145,9 @@
 
 static int snd_trident_gameport_open(struct gameport *gameport, int mode)
 {
-	trident_gameport_t *gp = (trident_gameport_t *)gameport;
-	trident_t *chip;
-	snd_assert(gp, return -1);
-	chip = gp->chip;
+	trident_t *chip = gameport->port_data;
+
+	snd_assert(chip, return 0);
 
 	switch (mode) {
 		case GAMEPORT_MODE_COOKED:
@@ -3173,30 +3163,42 @@
 	}
 }
 
-void __devinit snd_trident_gameport(trident_t *chip)
+int __devinit snd_trident_create_gameport(trident_t *chip)
 {
-	trident_gameport_t *gp;
-	gp = kmalloc(sizeof(*gp), GFP_KERNEL);
-	if (! gp) {
-		snd_printk("cannot allocate gameport area\n");
-		return;
+	struct gameport *gp;
+
+	chip->gameport = gp = gameport_allocate_port();
+	if (!gp) {
+		printk(KERN_ERR "trident: cannot allocate memory for gameport\n");
+		return -ENOMEM;
 	}
-	memset(gp, 0, sizeof(*gp));
-	gp->chip = chip;
-	gp->info.fuzz = 64;
-	gp->info.read = snd_trident_gameport_read;
-	gp->info.trigger = snd_trident_gameport_trigger;
-	gp->info.cooked_read = snd_trident_gameport_cooked_read;
-	gp->info.open = snd_trident_gameport_open;
-	chip->gameport = gp;
 
-	gameport_register_port(&gp->info);
+	gameport_set_name(gp, "Trident 4DWave");
+	gameport_set_phys(gp, "pci%s/gameport0", pci_name(chip->pci));
+	gp->dev.parent = &chip->pci->dev;
+
+	gp->port_data = chip;
+	gp->fuzz = 64;
+	gp->read = snd_trident_gameport_read;
+	gp->trigger = snd_trident_gameport_trigger;
+	gp->cooked_read = snd_trident_gameport_cooked_read;
+	gp->open = snd_trident_gameport_open;
+
+	gameport_register_port(gp);
+
+	return 0;
 }
 
-#else
-void __devinit snd_trident_gameport(trident_t *chip)
+static inline void snd_trident_free_gameport(trident_t *chip)
 {
+	if (chip->gameport) {
+		gameport_unregister_port(chip->gameport);
+		chip->gameport = NULL;
+	}
 }
+#else
+int __devinit snd_trident_create_gameport(trident_t *chip) { return -ENOSYS; }
+static inline void snd_trident_free_gameport(trident_t *chip) { }
 #endif /* CONFIG_GAMEPORT */
 
 /*
@@ -3661,12 +3663,7 @@
 
 static int snd_trident_free(trident_t *trident)
 {
-#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))
-	if (trident->gameport) {
-		gameport_unregister_port(&trident->gameport->info);
-		kfree(trident->gameport);
-	}
-#endif
+	snd_trident_free_gameport(trident);
 	snd_trident_disable_eso(trident);
 	// Disable S/PDIF out
 	if (trident->device == TRIDENT_DEVICE_ID_NX)
@@ -3921,7 +3918,7 @@
 }
 
 #ifdef CONFIG_PM
-static int snd_trident_suspend(snd_card_t *card, unsigned int state)
+static int snd_trident_suspend(snd_card_t *card, pm_message_t state)
 {
 	trident_t *trident = card->pm_private_data;
 
@@ -3947,7 +3944,7 @@
 	return 0;
 }
 
-static int snd_trident_resume(snd_card_t *card, unsigned int state)
+static int snd_trident_resume(snd_card_t *card)
 {
 	trident_t *trident = card->pm_private_data;
 
diff -Nru a/sound/pci/via82xx.c b/sound/pci/via82xx.c
--- a/sound/pci/via82xx.c	2005-03-11 12:51:51 -08:00
+++ b/sound/pci/via82xx.c	2005-03-11 12:51:51 -08:00
@@ -367,7 +367,7 @@
 	unsigned int mpu_port_saved;
 #endif
 
-	unsigned char playback_volume[4][2]; /* for VIA8233/C/8235; default = 0 */
+	unsigned char playback_volume[2]; /* for VIA8233/C/8235; default = 0 */
 
 	unsigned int intr_mask; /* SGD_SHADOW mask to check interrupts */
 
@@ -394,8 +394,7 @@
 	snd_info_entry_t *proc_entry;
 
 #ifdef SUPPORT_JOYSTICK
-	struct gameport gameport;
-	struct resource *res_joystick;
+	struct gameport *gameport;
 #endif
 };
 
@@ -942,8 +941,8 @@
 	snd_assert((rbits & ~0xfffff) == 0, return -EINVAL);
 	snd_via82xx_channel_reset(chip, viadev);
 	snd_via82xx_set_table_ptr(chip, viadev);
-	outb(chip->playback_volume[viadev->reg_offset / 0x10][0], VIADEV_REG(viadev, OFS_PLAYBACK_VOLUME_L));
-	outb(chip->playback_volume[viadev->reg_offset / 0x10][1], VIADEV_REG(viadev, OFS_PLAYBACK_VOLUME_R));
+	outb(chip->playback_volume[0], VIADEV_REG(viadev, OFS_PLAYBACK_VOLUME_L));
+	outb(chip->playback_volume[1], VIADEV_REG(viadev, OFS_PLAYBACK_VOLUME_R));
 	outl((runtime->format == SNDRV_PCM_FORMAT_S16_LE ? VIA8233_REG_TYPE_16BIT : 0) | /* format */
 	     (runtime->channels > 1 ? VIA8233_REG_TYPE_STEREO : 0) | /* stereo */
 	     rbits | /* rate */
@@ -1497,17 +1496,15 @@
 static int snd_via8233_dxs_volume_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
 {
 	via82xx_t *chip = snd_kcontrol_chip(kcontrol);
-	unsigned int idx = snd_ctl_get_ioff(kcontrol, &ucontrol->id);
-	ucontrol->value.integer.value[0] = VIA_DXS_MAX_VOLUME - chip->playback_volume[idx][0];
-	ucontrol->value.integer.value[1] = VIA_DXS_MAX_VOLUME - chip->playback_volume[idx][1];
+	ucontrol->value.integer.value[0] = VIA_DXS_MAX_VOLUME - chip->playback_volume[0];
+	ucontrol->value.integer.value[1] = VIA_DXS_MAX_VOLUME - chip->playback_volume[1];
 	return 0;
 }
 
 static int snd_via8233_dxs_volume_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
 {
 	via82xx_t *chip = snd_kcontrol_chip(kcontrol);
-	unsigned int idx = snd_ctl_get_ioff(kcontrol, &ucontrol->id);
-	unsigned long port = chip->port + 0x10 * idx;
+	unsigned int idx;
 	unsigned char val;
 	int i, change = 0;
 
@@ -1516,19 +1513,21 @@
 		if (val > VIA_DXS_MAX_VOLUME)
 			val = VIA_DXS_MAX_VOLUME;
 		val = VIA_DXS_MAX_VOLUME - val;
-		change |= val != chip->playback_volume[idx][i];
-		if (change) {
-			chip->playback_volume[idx][i] = val;
-			outb(val, port + VIA_REG_OFS_PLAYBACK_VOLUME_L + i);
+		if (val != chip->playback_volume[i]) {
+			change = 1;
+			chip->playback_volume[i] = val;
+			for (idx = 0; idx < 4; idx++) {
+				unsigned long port = chip->port + 0x10 * idx;
+				outb(val, port + VIA_REG_OFS_PLAYBACK_VOLUME_L + i);
+			}
 		}
 	}
 	return change;
 }
 
 static snd_kcontrol_new_t snd_via8233_dxs_volume_control __devinitdata = {
-	.name = "VIA DXS Playback Volume",
+	.name = "PCM Playback Volume",
 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-	.count = 4,
 	.info = snd_via8233_dxs_volume_info,
 	.get = snd_via8233_dxs_volume_get,
 	.put = snd_via8233_dxs_volume_put,
@@ -1635,11 +1634,70 @@
 	return 0;
 }
 
+#ifdef SUPPORT_JOYSTICK
+#define JOYSTICK_ADDR	0x200
+static int __devinit snd_via686_create_gameport(via82xx_t *chip, int dev, unsigned char *legacy)
+{
+	struct gameport *gp;
+	struct resource *r;
+
+	if (!joystick[dev])
+		return -ENODEV;
+
+	r = request_region(JOYSTICK_ADDR, 8, "VIA686 gameport");
+	if (!r) {
+		printk(KERN_WARNING "via82xx: cannot reserve joystick port 0x%#x\n", JOYSTICK_ADDR);
+		return -EBUSY;
+	}
+
+	chip->gameport = gp = gameport_allocate_port();
+	if (!gp) {
+		printk(KERN_ERR "via82xx: cannot allocate memory for gameport\n");
+		release_resource(r);
+		kfree_nocheck(r);
+		return -ENOMEM;
+	}
+
+	gameport_set_name(gp, "VIA686 Gameport");
+	gameport_set_phys(gp, "pci%s/gameport0", pci_name(chip->pci));
+	gp->dev.parent = &chip->pci->dev;
+	gp->io = JOYSTICK_ADDR;
+	gp->port_data = r;
+
+	/* Enable legacy joystick port */
+	*legacy |= VIA_FUNC_ENABLE_GAME;
+	pci_write_config_byte(chip->pci, VIA_FUNC_ENABLE, *legacy);
+
+	gameport_register_port(chip->gameport);
+
+	return 0;
+}
+
+static void snd_via686_free_gameport(via82xx_t *chip)
+{
+	if (chip->gameport) {
+		struct resource *r = chip->gameport->port_data;
+
+		gameport_unregister_port(chip->gameport);
+		chip->gameport = NULL;
+		release_resource(r);
+		kfree_nocheck(r);
+	}
+}
+#else
+static inline int snd_via686_create_gameport(via82xx_t *chip, int dev, unsigned char *legacy)
+{
+	return -ENOSYS;
+}
+static inline void snd_via686_free_gameport(via82xx_t *chip) { }
+#endif
+
+
 /*
  *
  */
 
-static int snd_via8233_init_misc(via82xx_t *chip, int dev)
+static int __devinit snd_via8233_init_misc(via82xx_t *chip, int dev)
 {
 	int i, err, caps;
 	unsigned char val;
@@ -1657,9 +1715,18 @@
 			return err;
 	}
 	if (chip->chip_type != TYPE_VIA8233A) {
-		err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_via8233_dxs_volume_control, chip));
-		if (err < 0)
-			return err;
+		/* when no h/w PCM volume control is found, use DXS volume control
+		 * as the PCM vol control
+		 */
+		snd_ctl_elem_id_t sid;
+		memset(&sid, 0, sizeof(sid));
+		strcpy(sid.name, "PCM Playback Volume");
+		sid.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
+		if (! snd_ctl_find_id(chip->card, &sid)) {
+			err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_via8233_dxs_volume_control, chip));
+			if (err < 0)
+				return err;
+		}
 	}
 
 	/* select spdif data slot 10/11 */
@@ -1671,7 +1738,7 @@
 	return 0;
 }
 
-static int snd_via686_init_misc(via82xx_t *chip, int dev)
+static int __devinit snd_via686_init_misc(via82xx_t *chip, int dev)
 {
 	unsigned char legacy, legacy_cfg;
 	int rev_h = 0;
@@ -1718,15 +1785,6 @@
 		mpu_port[dev] = 0;
 	}
 
-#ifdef SUPPORT_JOYSTICK
-#define JOYSTICK_ADDR	0x200
-	if (joystick[dev] &&
-	    (chip->res_joystick = request_region(JOYSTICK_ADDR, 8, "VIA686 gameport")) != NULL) {
-		legacy |= VIA_FUNC_ENABLE_GAME;
-		chip->gameport.io = JOYSTICK_ADDR;
-	}
-#endif
-
 	pci_write_config_byte(chip->pci, VIA_FUNC_ENABLE, legacy);
 	pci_write_config_byte(chip->pci, VIA_PNP_CONTROL, legacy_cfg);
 	if (chip->mpu_res) {
@@ -1741,10 +1799,7 @@
 		pci_write_config_byte(chip->pci, VIA_FUNC_ENABLE, legacy);
 	}
 
-#ifdef SUPPORT_JOYSTICK
-	if (chip->res_joystick)
-		gameport_register_port(&chip->gameport);
-#endif
+	snd_via686_create_gameport(chip, dev, &legacy);
 
 #ifdef CONFIG_PM
 	chip->legacy_saved = legacy;
@@ -1888,6 +1943,15 @@
 		}
 	}
 
+	if (chip->chip_type != TYPE_VIA8233A) {
+		int i, idx;
+		for (idx = 0; idx < 4; idx++) {
+			unsigned long port = chip->port + 0x10 * idx;
+			for (i = 0; i < 2; i++)
+				outb(chip->playback_volume[i], port + VIA_REG_OFS_PLAYBACK_VOLUME_L + i);
+		}
+	}
+
 	return 0;
 }
 
@@ -1895,7 +1959,7 @@
 /*
  * power management
  */
-static int snd_via82xx_suspend(snd_card_t *card, unsigned int state)
+static int snd_via82xx_suspend(snd_card_t *card, pm_message_t state)
 {
 	via82xx_t *chip = card->pm_private_data;
 	int i;
@@ -1920,10 +1984,10 @@
 	return 0;
 }
 
-static int snd_via82xx_resume(snd_card_t *card, unsigned int state)
+static int snd_via82xx_resume(snd_card_t *card)
 {
 	via82xx_t *chip = card->pm_private_data;
-	int idx, i;
+	int i;
 
 	pci_enable_device(chip->pci);
 	pci_set_power_state(chip->pci, 0);
@@ -1939,11 +2003,6 @@
 		pci_write_config_byte(chip->pci, VIA8233_SPDIF_CTRL, chip->spdif_ctrl_saved);
 		outb(chip->capture_src_saved[0], chip->port + VIA_REG_CAPTURE_CHANNEL);
 		outb(chip->capture_src_saved[1], chip->port + VIA_REG_CAPTURE_CHANNEL + 0x10);
-		for (idx = 0; idx < 4; idx++) {
-			unsigned long port = chip->port + 0x10 * idx;
-			for (i = 0; i < 2; i++)
-				outb(chip->playback_volume[idx][i], port + VIA_REG_OFS_PLAYBACK_VOLUME_L + i);
-		}
 	}
 
 	snd_ac97_resume(chip->ac97);
@@ -1973,14 +2032,9 @@
 		kfree_nocheck(chip->mpu_res);
 	}
 	pci_release_regions(chip->pci);
+
 	if (chip->chip_type == TYPE_VIA686) {
-#ifdef SUPPORT_JOYSTICK
-		if (chip->res_joystick) {
-			gameport_unregister_port(&chip->gameport);
-			release_resource(chip->res_joystick);
-			kfree_nocheck(chip->res_joystick);
-		}
-#endif
+		snd_via686_free_gameport(chip);
 		pci_write_config_byte(chip->pci, VIA_FUNC_ENABLE, chip->old_legacy);
 		pci_write_config_byte(chip->pci, VIA_PNP_CONTROL, chip->old_legacy_cfg);
 	}
diff -Nru a/sound/pci/via82xx_modem.c b/sound/pci/via82xx_modem.c
--- a/sound/pci/via82xx_modem.c	2005-03-11 12:51:51 -08:00
+++ b/sound/pci/via82xx_modem.c	2005-03-11 12:51:51 -08:00
@@ -55,7 +55,7 @@
 MODULE_LICENSE("GPL");
 MODULE_SUPPORTED_DEVICE("{{VIA,VT82C686A/B/C modem,pci}}");
 
-static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;	/* Index 0-MAX */
+static int index[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = -2}; /* Exclude the first card */
 static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;	/* ID for this card */
 static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;	/* Enable this card */
 static int ac97_clock[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 48000};
@@ -1034,7 +1034,7 @@
 /*
  * power management
  */
-static int snd_via82xx_suspend(snd_card_t *card, unsigned int state)
+static int snd_via82xx_suspend(snd_card_t *card, pm_message_t state)
 {
 	via82xx_t *chip = card->pm_private_data;
 	int i;
@@ -1051,7 +1051,7 @@
 	return 0;
 }
 
-static int snd_via82xx_resume(snd_card_t *card, unsigned int state)
+static int snd_via82xx_resume(snd_card_t *card)
 {
 	via82xx_t *chip = card->pm_private_data;
 	int i;
diff -Nru a/sound/pci/vx222/vx222_ops.c b/sound/pci/vx222/vx222_ops.c
--- a/sound/pci/vx222/vx222_ops.c	2005-03-11 12:51:40 -08:00
+++ b/sound/pci/vx222/vx222_ops.c	2005-03-11 12:51:40 -08:00
@@ -22,6 +22,7 @@
 
 #include <sound/driver.h>
 #include <linux/delay.h>
+#include <linux/device.h>
 #include <linux/firmware.h>
 #include <sound/core.h>
 #include <sound/control.h>
diff -Nru a/sound/pci/ymfpci/ymfpci.c b/sound/pci/ymfpci/ymfpci.c
--- a/sound/pci/ymfpci/ymfpci.c	2005-03-11 12:51:42 -08:00
+++ b/sound/pci/ymfpci/ymfpci.c	2005-03-11 12:51:42 -08:00
@@ -79,6 +79,96 @@
 
 MODULE_DEVICE_TABLE(pci, snd_ymfpci_ids);
 
+#ifdef SUPPORT_JOYSTICK
+static int __devinit snd_ymfpci_create_gameport(ymfpci_t *chip, int dev,
+						int legacy_ctrl, int legacy_ctrl2)
+{
+	struct gameport *gp;
+	struct resource *r = NULL;
+	int io_port = joystick_port[dev];
+
+	if (!io_port)
+		return -ENODEV;
+
+	if (chip->pci->device >= 0x0010) { /* YMF 744/754 */
+
+		if (io_port == 1) {
+			/* auto-detect */
+			if (!(io_port = pci_resource_start(chip->pci, 2)))
+				return -ENODEV;
+		}
+	} else {
+		if (io_port == 1) {
+			/* auto-detect */
+			for (io_port = 0x201; io_port <= 0x205; io_port++) {
+				if (io_port == 0x203)
+					continue;
+				if ((r = request_region(io_port, 1, "YMFPCI gameport")) != NULL)
+					break;
+			}
+			if (!r) {
+				printk(KERN_ERR "ymfpci: no gameport ports available\n");
+				return -EBUSY;
+			}
+		}
+		switch (io_port) {
+		case 0x201: legacy_ctrl2 |= 0 << 6; break;
+		case 0x202: legacy_ctrl2 |= 1 << 6; break;
+		case 0x204: legacy_ctrl2 |= 2 << 6; break;
+		case 0x205: legacy_ctrl2 |= 3 << 6; break;
+		default:
+			printk(KERN_ERR "ymfpci: invalid joystick port %#x", io_port);
+			return -EINVAL;
+		}
+	}
+
+	if (!r && !(r = request_region(io_port, 1, "YMFPCI gameport"))) {
+		printk(KERN_ERR "ymfpci: joystick port %#x is in use.\n", io_port);
+		return -EBUSY;
+	}
+
+	chip->gameport = gp = gameport_allocate_port();
+	if (!gp) {
+		printk(KERN_ERR "ymfpci: cannot allocate memory for gameport\n");
+		release_resource(r);
+		kfree_nocheck(r);
+		return -ENOMEM;
+	}
+
+
+	gameport_set_name(gp, "Yamaha YMF Gameport");
+	gameport_set_phys(gp, "pci%s/gameport0", pci_name(chip->pci));
+	gp->dev.parent = &chip->pci->dev;
+	gp->io = io_port;
+
+	if (chip->pci->device >= 0x0010) /* YMF 744/754 */
+		pci_write_config_word(chip->pci, PCIR_DSXG_JOYBASE, io_port);
+
+	pci_write_config_word(chip->pci, PCIR_DSXG_LEGACY, legacy_ctrl | YMFPCI_LEGACY_JPEN);
+	pci_write_config_word(chip->pci, PCIR_DSXG_ELEGACY, legacy_ctrl2);
+
+	gameport_register_port(chip->gameport);
+
+	return 0;
+}
+
+void snd_ymfpci_free_gameport(ymfpci_t *chip)
+{
+	if (chip->gameport) {
+		struct resource *r = chip->gameport->port_data;
+
+		gameport_unregister_port(chip->gameport);
+		chip->gameport = NULL;
+
+		release_resource(r);
+		kfree_nocheck(r);
+	}
+}
+#else
+static inline int snd_ymfpci_create_gameport(ymfpci_t *chip, int dev, int l, int l2) { return -ENOSYS; }
+void snd_ymfpci_free_gameport(ymfpci_t *chip) { }
+#endif /* SUPPORT_JOYSTICK */
+
 static int __devinit snd_card_ymfpci_probe(struct pci_dev *pci,
 					   const struct pci_device_id *pci_id)
 {
@@ -86,9 +176,6 @@
 	snd_card_t *card;
 	struct resource *fm_res = NULL;
 	struct resource *mpu_res = NULL;
-#ifdef SUPPORT_JOYSTICK
-	struct resource *joystick_res = NULL;
-#endif
 	ymfpci_t *chip;
 	opl3_t *opl3;
 	char *str;
@@ -138,17 +225,6 @@
 			legacy_ctrl |= YMFPCI_LEGACY_MEN;
 			pci_write_config_word(pci, PCIR_DSXG_MPU401BASE, mpu_port[dev]);
 		}
-#ifdef SUPPORT_JOYSTICK
-		if (joystick_port[dev] == 1) {
-			/* auto-detect */
-			joystick_port[dev] = pci_resource_start(pci, 2);
-		}
-		if (joystick_port[dev] > 0 &&
-		    (joystick_res = request_region(joystick_port[dev], 1, "YMFPCI gameport")) != NULL) {
-			legacy_ctrl |= YMFPCI_LEGACY_JPEN;
-			pci_write_config_word(pci, PCIR_DSXG_JOYBASE, joystick_port[dev]);
-		}
-#endif
 	} else {
 		switch (fm_port[dev]) {
 		case 0x388: legacy_ctrl2 |= 0; break;
@@ -178,34 +254,6 @@
 			legacy_ctrl2 &= ~YMFPCI_LEGACY2_MPUIO;
 			mpu_port[dev] = 0;
 		}
-#ifdef SUPPORT_JOYSTICK
-		if (joystick_port[dev] == 1) {
-			/* auto-detect */
-			long p;
-			for (p = 0x201; p <= 0x205; p++) {
-				if (p == 0x203) continue;
-				if ((joystick_res = request_region(p, 1, "YMFPCI gameport")) != NULL)
-					break;
-			}
-			if (joystick_res)
-				joystick_port[dev] = p;
-		}
-		switch (joystick_port[dev]) {
-		case 0x201: legacy_ctrl2 |= 0 << 6; break;
-		case 0x202: legacy_ctrl2 |= 1 << 6; break;
-		case 0x204: legacy_ctrl2 |= 2 << 6; break;
-		case 0x205: legacy_ctrl2 |= 3 << 6; break;
-		default: joystick_port[dev] = 0; break;
-		}
-		if (! joystick_res && joystick_port[dev] > 0)
-			joystick_res = request_region(joystick_port[dev], 1, "YMFPCI gameport");
-		if (joystick_res) {
-			legacy_ctrl |= YMFPCI_LEGACY_JPEN;
-		} else {
-			legacy_ctrl2 &= ~YMFPCI_LEGACY2_JSIO;
-			joystick_port[dev] = 0;
-		}
-#endif
 	}
 	if (mpu_res) {
 		legacy_ctrl |= YMFPCI_LEGACY_MIEN;
@@ -226,19 +274,10 @@
 			release_resource(fm_res);
 			kfree_nocheck(fm_res);
 		}
-#ifdef SUPPORT_JOYSTICK
-		if (joystick_res) {
-			release_resource(joystick_res);
-			kfree_nocheck(joystick_res);
-		}
-#endif
 		return err;
 	}
 	chip->fm_res = fm_res;
 	chip->mpu_res = mpu_res;
-#ifdef SUPPORT_JOYSTICK
-	chip->joystick_res = joystick_res;
-#endif
 	strcpy(card->driver, str);
 	sprintf(card->shortname, "Yamaha DS-XG (%s)", str);
 	sprintf(card->longname, "%s at 0x%lx, irq %i",
@@ -292,12 +331,8 @@
 			return err;
 		}
 	}
-#ifdef SUPPORT_JOYSTICK
-	if (chip->joystick_res) {
-		chip->gameport.io = joystick_port[dev];
-		gameport_register_port(&chip->gameport);
-	}
-#endif
+
+	snd_ymfpci_create_gameport(chip, dev, legacy_ctrl, legacy_ctrl2);
 
 	if ((err = snd_card_register(card)) < 0) {
 		snd_card_free(card);
diff -Nru a/sound/pci/ymfpci/ymfpci_main.c b/sound/pci/ymfpci/ymfpci_main.c
--- a/sound/pci/ymfpci/ymfpci_main.c	2005-03-11 12:51:51 -08:00
+++ b/sound/pci/ymfpci/ymfpci_main.c	2005-03-11 12:51:51 -08:00
@@ -2079,14 +2079,7 @@
 		release_resource(chip->fm_res);
 		kfree_nocheck(chip->fm_res);
 	}
-#ifdef SUPPORT_JOYSTICK
-	if (chip->joystick_res) {
-		if (chip->gameport.io)
-			gameport_unregister_port(&chip->gameport);
-		release_resource(chip->joystick_res);
-		kfree_nocheck(chip->joystick_res);
-	}
-#endif
+	snd_ymfpci_free_gameport(chip);
 	if (chip->reg_area_virt)
 		iounmap(chip->reg_area_virt);
 	if (chip->work_ptr.area)
@@ -2142,7 +2135,7 @@
 };
 #define YDSXGR_NUM_SAVED_REGS	ARRAY_SIZE(saved_regs_index)
 
-static int snd_ymfpci_suspend(snd_card_t *card, unsigned int state)
+static int snd_ymfpci_suspend(snd_card_t *card, pm_message_t state)
 {
 	ymfpci_t *chip = card->pm_private_data;
 	unsigned int i;
@@ -2161,7 +2154,7 @@
 	return 0;
 }
 
-static int snd_ymfpci_resume(snd_card_t *card, unsigned int state)
+static int snd_ymfpci_resume(snd_card_t *card)
 {
 	ymfpci_t *chip = card->pm_private_data;
 	unsigned int i;
diff -Nru a/sound/pcmcia/pdaudiocf/pdaudiocf.c b/sound/pcmcia/pdaudiocf/pdaudiocf.c
--- a/sound/pcmcia/pdaudiocf/pdaudiocf.c	2005-03-11 12:51:42 -08:00
+++ b/sound/pcmcia/pdaudiocf/pdaudiocf.c	2005-03-11 12:51:42 -08:00
@@ -342,7 +342,7 @@
 		link->state |= DEV_SUSPEND;
 		if (chip) {
 			snd_printdd(KERN_DEBUG "snd_pdacf_suspend calling\n");
-			snd_pdacf_suspend(chip->card, 0);
+			snd_pdacf_suspend(chip->card, PMSG_SUSPEND);
 		}
 		/* Fall through... */
 	case CS_EVENT_RESET_PHYSICAL:
@@ -361,7 +361,7 @@
 			pcmcia_request_configuration(link->handle, &link->conf);
 			if (chip) {
 				snd_printdd(KERN_DEBUG "calling snd_pdacf_resume\n");
-				snd_pdacf_resume(chip->card, 0);
+				snd_pdacf_resume(chip->card);
 			}
 		}
 		snd_printdd(KERN_DEBUG "resume done!\n");
diff -Nru a/sound/pcmcia/pdaudiocf/pdaudiocf.h b/sound/pcmcia/pdaudiocf/pdaudiocf.h
--- a/sound/pcmcia/pdaudiocf/pdaudiocf.h	2005-03-11 12:51:40 -08:00
+++ b/sound/pcmcia/pdaudiocf/pdaudiocf.h	2005-03-11 12:51:40 -08:00
@@ -134,8 +134,8 @@
 int snd_pdacf_ak4117_create(pdacf_t *pdacf);
 void snd_pdacf_powerdown(pdacf_t *chip);
 #ifdef CONFIG_PM
-int snd_pdacf_suspend(snd_card_t *card, unsigned int state);
-int snd_pdacf_resume(snd_card_t *card, unsigned int state);
+int snd_pdacf_suspend(snd_card_t *card, pm_message_t state);
+int snd_pdacf_resume(snd_card_t *card);
 #endif
 int snd_pdacf_pcm_new(pdacf_t *chip);
 irqreturn_t pdacf_interrupt(int irq, void *dev, struct pt_regs *regs);
diff -Nru a/sound/pcmcia/pdaudiocf/pdaudiocf_core.c b/sound/pcmcia/pdaudiocf/pdaudiocf_core.c
--- a/sound/pcmcia/pdaudiocf/pdaudiocf_core.c	2005-03-11 12:51:42 -08:00
+++ b/sound/pcmcia/pdaudiocf/pdaudiocf_core.c	2005-03-11 12:51:42 -08:00
@@ -255,7 +255,7 @@
 
 #ifdef CONFIG_PM
 
-int snd_pdacf_suspend(snd_card_t *card, unsigned int state)
+int snd_pdacf_suspend(snd_card_t *card, pm_message_t state)
 {
 	pdacf_t *chip = card->pm_private_data;
 	u16 val;
@@ -275,7 +275,7 @@
 	return (chip->ak4117->rcs0 & AK4117_UNLCK) == 0;
 }
 
-int snd_pdacf_resume(snd_card_t *card, unsigned int state)
+int snd_pdacf_resume(snd_card_t *card)
 {
 	pdacf_t *chip = card->pm_private_data;
 	int timeout = 40;
diff -Nru a/sound/pcmcia/vx/vx_entry.c b/sound/pcmcia/vx/vx_entry.c
--- a/sound/pcmcia/vx/vx_entry.c	2005-03-11 12:51:41 -08:00
+++ b/sound/pcmcia/vx/vx_entry.c	2005-03-11 12:51:41 -08:00
@@ -346,7 +346,7 @@
 		link->state |= DEV_SUSPEND;
 		if (chip && chip->card->pm_suspend) {
 			snd_printdd(KERN_DEBUG "snd_vx_suspend calling\n");
-			chip->card->pm_suspend(chip->card, 0);
+			chip->card->pm_suspend(chip->card, PMSG_SUSPEND);
 		}
 		/* Fall through... */
 	case CS_EVENT_RESET_PHYSICAL:
@@ -366,7 +366,7 @@
 			pcmcia_request_configuration(link->handle, &link->conf);
 			if (chip && chip->card->pm_resume) {
 				snd_printdd(KERN_DEBUG "calling snd_vx_resume\n");
-				chip->card->pm_resume(chip->card, 0);
+				chip->card->pm_resume(chip->card);
 			}
 		}
 		snd_printdd(KERN_DEBUG "resume done!\n");
diff -Nru a/sound/pcmcia/vx/vxp_ops.c b/sound/pcmcia/vx/vxp_ops.c
--- a/sound/pcmcia/vx/vxp_ops.c	2005-03-11 12:51:42 -08:00
+++ b/sound/pcmcia/vx/vxp_ops.c	2005-03-11 12:51:42 -08:00
@@ -22,6 +22,7 @@
 
 #include <sound/driver.h>
 #include <linux/delay.h>
+#include <linux/device.h>
 #include <linux/firmware.h>
 #include <sound/core.h>
 #include <asm/io.h>
diff -Nru a/sound/ppc/keywest.c b/sound/ppc/keywest.c
--- a/sound/ppc/keywest.c	2005-03-11 12:51:51 -08:00
+++ b/sound/ppc/keywest.c	2005-03-11 12:51:51 -08:00
@@ -76,8 +76,6 @@
 	new_client->flags = 0;
 
 	strcpy(i2c_device_name(new_client), keywest_ctx->name);
-
-	new_client->id = keywest_ctx->id++; /* Automatically unique */
 	keywest_ctx->client = new_client;
 	
 	/* Tell the i2c layer a new client has arrived */
diff -Nru a/sound/ppc/pmac.c b/sound/ppc/pmac.c
--- a/sound/ppc/pmac.c	2005-03-11 12:51:52 -08:00
+++ b/sound/ppc/pmac.c	2005-03-11 12:51:52 -08:00
@@ -40,8 +40,8 @@
 #if defined(CONFIG_PM) && defined(CONFIG_PMAC_PBOOK)
 static int snd_pmac_register_sleep_notifier(pmac_t *chip);
 static int snd_pmac_unregister_sleep_notifier(pmac_t *chip);
-static int snd_pmac_suspend(snd_card_t *card, unsigned int state);
-static int snd_pmac_resume(snd_card_t *card, unsigned int state);
+static int snd_pmac_suspend(snd_card_t *card, pm_message_t state);
+static int snd_pmac_resume(snd_card_t *card);
 #endif
 
 
@@ -1233,7 +1233,7 @@
  * Save state when going to sleep, restore it afterwards.
  */
 
-static int snd_pmac_suspend(snd_card_t *card, unsigned int state)
+static int snd_pmac_suspend(snd_card_t *card, pm_message_t state)
 {
 	pmac_t *chip = card->pm_private_data;
 	unsigned long flags;
@@ -1254,7 +1254,7 @@
 	return 0;
 }
 
-static int snd_pmac_resume(snd_card_t *card, unsigned int state)
+static int snd_pmac_resume(snd_card_t *card)
 {
 	pmac_t *chip = card->pm_private_data;
 
@@ -1294,10 +1294,10 @@
 
 	switch (when) {
 	case PBOOK_SLEEP_NOW:
-		snd_pmac_suspend(chip->card, 0);
+		snd_pmac_suspend(chip->card, PMSG_SUSPEND);
 		break;
 	case PBOOK_WAKE:
-		snd_pmac_resume(chip->card, 0);
+		snd_pmac_resume(chip->card);
 		break;
 	}
 	return PBOOK_SLEEP_OK;
diff -Nru a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c
--- a/sound/usb/usbaudio.c	2005-03-11 12:51:47 -08:00
+++ b/sound/usb/usbaudio.c	2005-03-11 12:51:47 -08:00
@@ -2968,6 +2968,9 @@
 	case QUIRK_MIDI_FIXED_ENDPOINT:
 	case QUIRK_MIDI_YAMAHA:
 	case QUIRK_MIDI_MIDIMAN:
+	case QUIRK_MIDI_NOVATION:
+	case QUIRK_MIDI_MOTU:
+	case QUIRK_MIDI_EMAGIC:
 		return snd_usb_create_midi_interface(chip, iface, quirk);
 	case QUIRK_COMPOSITE:
 		return create_composite_quirk(chip, iface, quirk);
@@ -2980,6 +2983,8 @@
 		return create_ua700_ua25_quirk(chip, iface);
 	case QUIRK_AUDIO_EDIROL_UA1000:
 		return create_ua1000_quirk(chip, iface);
+	case QUIRK_IGNORE_INTERFACE:
+		return 0;
 	default:
 		snd_printd(KERN_ERR "invalid quirk type %d\n", quirk->type);
 		return -ENXIO;
diff -Nru a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h
--- a/sound/usb/usbaudio.h	2005-03-11 12:51:47 -08:00
+++ b/sound/usb/usbaudio.h	2005-03-11 12:51:47 -08:00
@@ -157,6 +157,10 @@
 #define QUIRK_MIDI_STANDARD_INTERFACE	6
 #define QUIRK_AUDIO_EDIROL_UA700_UA25	7
 #define QUIRK_AUDIO_EDIROL_UA1000	8
+#define QUIRK_IGNORE_INTERFACE		9
+#define QUIRK_MIDI_NOVATION		10
+#define QUIRK_MIDI_MOTU			11
+#define QUIRK_MIDI_EMAGIC		12
 
 typedef struct snd_usb_audio_quirk snd_usb_audio_quirk_t;
 typedef struct snd_usb_midi_endpoint_info snd_usb_midi_endpoint_info_t;
@@ -171,7 +175,10 @@
 
 /* data for QUIRK_MIDI_FIXED_ENDPOINT */
 struct snd_usb_midi_endpoint_info {
-	int8_t out_ep, in_ep;	/* ep number, 0 autodetect */
+	int8_t   out_ep;	/* ep number, 0 autodetect */
+	uint8_t  out_interval;	/* interval for interrupt endpoints */
+	int8_t   in_ep;	
+	uint8_t  in_interval;
 	uint16_t out_cables;	/* bitmask */
 	uint16_t in_cables;	/* bitmask */
 };
@@ -189,6 +196,13 @@
 /* for QUIRK_AUDIO/MIDI_STANDARD_INTERFACE, data is NULL */
 
 /* for QUIRK_AUDIO_EDIROL_UA700_UA25/UA1000, data is NULL */
+
+/* for QUIRK_IGNORE_INTERFACE, data is NULL */
+
+/* for QUIRK_MIDI_NOVATION and _MOTU, data is NULL */
+
+/* for QUIRK_MIDI_EMAGIC, data points to a snd_usb_midi_endpoint_info
+ * structure (out_cables and in_cables only) */
 
 /*
  */
diff -Nru a/sound/usb/usbmidi.c b/sound/usb/usbmidi.c
--- a/sound/usb/usbmidi.c	2005-03-11 12:51:51 -08:00
+++ b/sound/usb/usbmidi.c	2005-03-11 12:51:51 -08:00
@@ -1,7 +1,7 @@
 /*
  * usbmidi.c - ALSA USB MIDI driver
  *
- * Copyright (c) 2002-2004 Clemens Ladisch
+ * Copyright (c) 2002-2005 Clemens Ladisch
  * All rights reserved.
  *
  * Based on the OSS usb-midi driver by NAGANO Daisuke,
@@ -38,6 +38,7 @@
 #include <sound/driver.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
+#include <linux/bitops.h>
 #include <linux/interrupt.h>
 #include <linux/spinlock.h>
 #include <linux/string.h>
@@ -49,6 +50,13 @@
 #include <sound/rawmidi.h>
 #include "usbaudio.h"
 
+
+/*
+ * define this to log all USB packets
+ */
+/* #define DUMP_PACKETS */
+
+
 MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>");
 MODULE_DESCRIPTION("USB Audio/MIDI helper module");
 MODULE_LICENSE("Dual BSD/GPL");
@@ -77,22 +85,33 @@
 typedef struct usbmidi_out_port usbmidi_out_port_t;
 typedef struct usbmidi_in_port usbmidi_in_port_t;
 
+struct usb_protocol_ops {
+	void (*input)(snd_usb_midi_in_endpoint_t*, uint8_t*, int);
+	void (*output)(snd_usb_midi_out_endpoint_t*);
+	void (*output_packet)(struct urb*, uint8_t, uint8_t, uint8_t, uint8_t);
+	void (*init_out_endpoint)(snd_usb_midi_out_endpoint_t*);
+	void (*finish_out_endpoint)(snd_usb_midi_out_endpoint_t*);
+};
+
 struct snd_usb_midi {
 	snd_usb_audio_t *chip;
 	struct usb_interface *iface;
 	const snd_usb_audio_quirk_t *quirk;
 	snd_rawmidi_t* rmidi;
+	struct usb_protocol_ops* usb_protocol_ops;
 	struct list_head list;
 
 	struct snd_usb_midi_endpoint {
 		snd_usb_midi_out_endpoint_t *out;
 		snd_usb_midi_in_endpoint_t *in;
 	} endpoints[MIDI_MAX_ENDPOINTS];
+	unsigned long input_triggered;
 };
 
 struct snd_usb_midi_out_endpoint {
 	snd_usb_midi_t* umidi;
 	struct urb* urb;
+	int urb_active;
 	int max_transfer;		/* size of urb buffer */
 	struct tasklet_struct tasklet;
 
@@ -113,6 +132,7 @@
 #define STATE_SYSEX_2	6
 		uint8_t data[2];
 	} ports[0x10];
+	int current_port;
 };
 
 struct snd_usb_midi_in_endpoint {
@@ -121,6 +141,8 @@
 	struct usbmidi_in_port {
 		snd_rawmidi_substream_t* substream;
 	} ports[0x10];
+	int seen_f5;
+	int current_port;
 };
 
 static void snd_usbmidi_do_output(snd_usb_midi_out_endpoint_t* ep);
@@ -156,25 +178,34 @@
 }
 
 /*
- * Receives a USB MIDI packet.
+ * Receives a chunk of MIDI data.
  */
-static void snd_usbmidi_input_packet(snd_usb_midi_in_endpoint_t* ep,
-				     uint8_t packet[4])
+static void snd_usbmidi_input_data(snd_usb_midi_in_endpoint_t* ep, int portidx,
+				   uint8_t* data, int length)
 {
-	int cable = packet[0] >> 4;
-	usbmidi_in_port_t* port = &ep->ports[cable];
+	usbmidi_in_port_t* port = &ep->ports[portidx];
 
 	if (!port->substream) {
-		snd_printd("unexpected port %d!\n", cable);
+		snd_printd("unexpected port %d!\n", portidx);
 		return;
 	}
-	if (!port->substream->runtime ||
-	    !port->substream->runtime->trigger)
+	if (!test_bit(port->substream->number, &ep->umidi->input_triggered))
 		return;
-	snd_rawmidi_receive(port->substream, &packet[1],
-			    snd_usbmidi_cin_length[packet[0] & 0x0f]);
+	snd_rawmidi_receive(port->substream, data, length);
 }
 
+#ifdef DUMP_PACKETS
+static void dump_urb(const char *type, const u8 *data, int length)
+{
+	snd_printk(KERN_DEBUG "%s packet: [", type);
+	for (; length > 0; ++data, --length)
+		printk(" %02x", *data);
+	printk(" ]\n");
+}
+#else
+#define dump_urb(type, data, length) /* nothing */
+#endif
+
 /*
  * Processes the data read from the device.
  */
@@ -183,12 +214,9 @@
 	snd_usb_midi_in_endpoint_t* ep = urb->context;
 
 	if (urb->status == 0) {
-		uint8_t* buffer = (uint8_t*)ep->urb->transfer_buffer;
-		int i;
-
-		for (i = 0; i + 4 <= urb->actual_length; i += 4)
-			if (buffer[i] != 0)
-				snd_usbmidi_input_packet(ep, &buffer[i]);
+		dump_urb("received", urb->transfer_buffer, urb->actual_length);
+		ep->umidi->usb_protocol_ops->input(ep, urb->transfer_buffer,
+						   urb->actual_length);
 	} else {
 		if (snd_usbmidi_urb_error(urb->status) < 0)
 			return;
@@ -200,71 +228,107 @@
 	}
 }
 
+static void snd_usbmidi_out_urb_complete(struct urb* urb, struct pt_regs *regs)
+{
+	snd_usb_midi_out_endpoint_t* ep = urb->context;
+
+	spin_lock(&ep->buffer_lock);
+	ep->urb_active = 0;
+	spin_unlock(&ep->buffer_lock);
+	if (urb->status < 0) {
+		if (snd_usbmidi_urb_error(urb->status) < 0)
+			return;
+	}
+	snd_usbmidi_do_output(ep);
+}
+
 /*
- * Converts the data read from a Midiman device to standard USB MIDI packets.
+ * This is called when some data should be transferred to the device
+ * (from one or more substreams).
  */
-static void snd_usbmidi_in_midiman_complete(struct urb* urb, struct pt_regs *regs)
+static void snd_usbmidi_do_output(snd_usb_midi_out_endpoint_t* ep)
 {
-	if (urb->status == 0) {
-		uint8_t* buffer = (uint8_t*)urb->transfer_buffer;
-		int i;
+	struct urb* urb = ep->urb;
+	unsigned long flags;
 
-		for (i = 0; i + 4 <= urb->actual_length; i += 4) {
-			if (buffer[i + 3] != 0) {
-				/*
-				 * snd_usbmidi_input_packet() doesn't check the
-				 * contents of the message, so we simply use
-				 * some random CIN with the desired length.
-				 */
-				static const uint8_t cin[4] = {
-					0x0, 0xf, 0x2, 0x3
-				};
-				uint8_t ctl = buffer[i + 3];
-				buffer[i + 3] = buffer[i + 2];
-				buffer[i + 2] = buffer[i + 1];
-				buffer[i + 1] = buffer[i + 0];
-				buffer[i + 0] = (ctl & 0xf0) | cin[ctl & 3];
-			} else {
-				buffer[i + 0] = 0;
-			}
-		}
+	spin_lock_irqsave(&ep->buffer_lock, flags);
+	if (ep->urb_active || ep->umidi->chip->shutdown) {
+		spin_unlock_irqrestore(&ep->buffer_lock, flags);
+		return;
 	}
-	snd_usbmidi_in_urb_complete(urb, regs);
+
+	urb->transfer_buffer_length = 0;
+	ep->umidi->usb_protocol_ops->output(ep);
+
+	if (urb->transfer_buffer_length > 0) {
+		dump_urb("sending", urb->transfer_buffer,
+			 urb->transfer_buffer_length);
+		urb->dev = ep->umidi->chip->dev;
+		ep->urb_active = snd_usbmidi_submit_urb(urb, GFP_ATOMIC) >= 0;
+	}
+	spin_unlock_irqrestore(&ep->buffer_lock, flags);
 }
 
-static void snd_usbmidi_out_urb_complete(struct urb* urb, struct pt_regs *regs)
+static void snd_usbmidi_out_tasklet(unsigned long data)
 {
-	snd_usb_midi_out_endpoint_t* ep = urb->context;
+	snd_usb_midi_out_endpoint_t* ep = (snd_usb_midi_out_endpoint_t *) data;
 
-	if (urb->status < 0) {
-		if (snd_usbmidi_urb_error(urb->status) < 0)
-			return;
-	}
 	snd_usbmidi_do_output(ep);
 }
 
+/* helper function to send static data that may not DMA-able */
+static int send_bulk_static_data(snd_usb_midi_out_endpoint_t* ep,
+				 const void *data, int len)
+{
+	int err;
+	void *buf = kmalloc(len, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+	memcpy(buf, data, len);
+	dump_urb("sending", buf, len);
+	err = usb_bulk_msg(ep->umidi->chip->dev, ep->urb->pipe, buf, len,
+			   NULL, HZ / 4);
+	kfree(buf);
+	return err;
+}
+
 /*
- * Converts standard USB MIDI packets to what Midman devices expect.
+ * Standard USB MIDI protocol: see the spec.
+ * Midiman protocol: like the standard protocol, but the control byte is the
+ * fourth byte in each packet, and uses length instead of CIN.
  */
-static void snd_usbmidi_convert_to_midiman(struct urb* urb)
+
+static void snd_usbmidi_standard_input(snd_usb_midi_in_endpoint_t* ep,
+				       uint8_t* buffer, int buffer_length)
 {
-	uint8_t* buffer = (uint8_t*)urb->transfer_buffer;
 	int i;
 
-	for (i = 0; i + 4 <= urb->transfer_buffer_length; i += 4) {
-		uint8_t cin = buffer[i];
-		buffer[i + 0] = buffer[i + 1];
-		buffer[i + 1] = buffer[i + 2];
-		buffer[i + 2] = buffer[i + 3];
-		buffer[i + 3] = (cin & 0xf0) | snd_usbmidi_cin_length[cin & 0x0f];
-	}
+	for (i = 0; i + 3 < buffer_length; i += 4)
+		if (buffer[i] != 0) {
+			int cable = buffer[i] >> 4;
+			int length = snd_usbmidi_cin_length[buffer[i] & 0x0f];
+			snd_usbmidi_input_data(ep, cable, &buffer[i + 1], length);
+		}
+}
+
+static void snd_usbmidi_midiman_input(snd_usb_midi_in_endpoint_t* ep,
+				      uint8_t* buffer, int buffer_length)
+{
+	int i;
+
+	for (i = 0; i + 3 < buffer_length; i += 4)
+		if (buffer[i + 3] != 0) {
+			int port = buffer[i + 3] >> 4;
+			int length = buffer[i + 3] & 3;
+			snd_usbmidi_input_data(ep, port, &buffer[i], length);
+		}
 }
 
 /*
  * Adds one USB MIDI packet to the output buffer.
  */
-static inline void output_packet(struct urb* urb,
-	       			 uint8_t p0, uint8_t p1, uint8_t p2, uint8_t p3)
+static void snd_usbmidi_output_standard_packet(struct urb* urb, uint8_t p0,
+					       uint8_t p1, uint8_t p2, uint8_t p3)
 {
 
 	uint8_t* buf = (uint8_t*)urb->transfer_buffer + urb->transfer_buffer_length;
@@ -276,12 +340,29 @@
 }
 
 /*
+ * Adds one Midiman packet to the output buffer.
+ */
+static void snd_usbmidi_output_midiman_packet(struct urb* urb, uint8_t p0,
+					      uint8_t p1, uint8_t p2, uint8_t p3)
+{
+
+	uint8_t* buf = (uint8_t*)urb->transfer_buffer + urb->transfer_buffer_length;
+	buf[0] = p1;
+	buf[1] = p2;
+	buf[2] = p3;
+	buf[3] = (p0 & 0xf0) | snd_usbmidi_cin_length[p0 & 0x0f];
+	urb->transfer_buffer_length += 4;
+}
+
+/*
  * Converts MIDI commands to USB MIDI packets.
  */
 static void snd_usbmidi_transmit_byte(usbmidi_out_port_t* port,
 				      uint8_t b, struct urb* urb)
 {
 	uint8_t p0 = port->cable;
+	void (*output_packet)(struct urb*, uint8_t, uint8_t, uint8_t, uint8_t) =
+		port->ep->umidi->usb_protocol_ops->output_packet;
 
 	if (b >= 0xf8) {
 		output_packet(urb, p0 | 0x0f, b, 0, 0);
@@ -370,63 +451,237 @@
 	}
 }
 
-/*
- * Moves data from one substream buffer to the URB transfer buffer.
- */
-static void snd_usbmidi_transmit(snd_usb_midi_out_endpoint_t* ep, int port_idx)
+static void snd_usbmidi_standard_output(snd_usb_midi_out_endpoint_t* ep)
 {
 	struct urb* urb = ep->urb;
-	usbmidi_out_port_t* port = &ep->ports[port_idx];
+	int p;
 
-	while (urb->transfer_buffer_length < ep->max_transfer) {
-		uint8_t b;
-		if (snd_rawmidi_transmit_peek(port->substream, &b, 1) != 1) {
-			port->active = 0;
-			break;
+	/* FIXME: lower-numbered ports can starve higher-numbered ports */
+	for (p = 0; p < 0x10; ++p) {
+		usbmidi_out_port_t* port = &ep->ports[p];
+		if (!port->active)
+			continue;
+		while (urb->transfer_buffer_length + 3 < ep->max_transfer) {
+			uint8_t b;
+			if (snd_rawmidi_transmit(port->substream, &b, 1) != 1) {
+				port->active = 0;
+				break;
+			}
+			snd_usbmidi_transmit_byte(port, b, urb);
 		}
-		snd_usbmidi_transmit_byte(port, b, urb);
-		snd_rawmidi_transmit_ack(port->substream, 1);
 	}
 }
 
+static struct usb_protocol_ops snd_usbmidi_standard_ops = {
+	.input = snd_usbmidi_standard_input,
+	.output = snd_usbmidi_standard_output,
+	.output_packet = snd_usbmidi_output_standard_packet,
+};
+
+static struct usb_protocol_ops snd_usbmidi_midiman_ops = {
+	.input = snd_usbmidi_midiman_input,
+	.output = snd_usbmidi_standard_output, 
+	.output_packet = snd_usbmidi_output_midiman_packet,
+};
+
 /*
- * This is called when some data should be transferred to the device
- * (from one or more substreams).
+ * Novation USB MIDI protocol: number of data bytes is in the first byte
+ * (when receiving) (+1!) or in the second byte (when sending); data begins
+ * at the third byte.
  */
-static void snd_usbmidi_do_output(snd_usb_midi_out_endpoint_t* ep)
+
+static void snd_usbmidi_novation_input(snd_usb_midi_in_endpoint_t* ep,
+				       uint8_t* buffer, int buffer_length)
 {
-	int p;
-	struct urb* urb = ep->urb;
-	unsigned long flags;
+	if (buffer_length < 2 || !buffer[0] || buffer_length < buffer[0] + 1)
+		return;
+	snd_usbmidi_input_data(ep, 0, &buffer[2], buffer[0] - 1);
+}
 
-	spin_lock_irqsave(&ep->buffer_lock, flags);
-	if (urb->status == -EINPROGRESS || ep->umidi->chip->shutdown) {
-		spin_unlock_irqrestore(&ep->buffer_lock, flags);
+static void snd_usbmidi_novation_output(snd_usb_midi_out_endpoint_t* ep)
+{
+	uint8_t* transfer_buffer;
+	int count;
+
+	if (!ep->ports[0].active)
+		return;
+	transfer_buffer = ep->urb->transfer_buffer;
+	count = snd_rawmidi_transmit(ep->ports[0].substream,
+				     &transfer_buffer[2],
+				     ep->max_transfer - 2);
+	if (count < 1) {
+		ep->ports[0].active = 0;
 		return;
 	}
+	transfer_buffer[0] = 0;
+	transfer_buffer[1] = count;
+	ep->urb->transfer_buffer_length = 2 + count;
+}
 
-	urb->transfer_buffer_length = 0;
-	for (p= 0; p < 0x10; ++p)
-		if (ep->ports[p].active)
-			snd_usbmidi_transmit(ep, p);
+static struct usb_protocol_ops snd_usbmidi_novation_ops = {
+	.input = snd_usbmidi_novation_input,
+	.output = snd_usbmidi_novation_output,
+};
 
-	if (urb->transfer_buffer_length > 0) {
-		if (ep->umidi->quirk && ep->umidi->quirk->type == QUIRK_MIDI_MIDIMAN)
-			snd_usbmidi_convert_to_midiman(urb);
+/*
+ * Mark of the Unicorn USB MIDI protocol: raw MIDI.
+ */
 
-		urb->dev = ep->umidi->chip->dev;
-		snd_usbmidi_submit_urb(urb, GFP_ATOMIC);
+static void snd_usbmidi_motu_input(snd_usb_midi_in_endpoint_t* ep,
+				   uint8_t* buffer, int buffer_length)
+{
+	snd_usbmidi_input_data(ep, 0, buffer, buffer_length);
+}
+
+static void snd_usbmidi_motu_output(snd_usb_midi_out_endpoint_t* ep)
+{
+	int count;
+
+	if (!ep->ports[0].active)
+		return;
+	count = snd_rawmidi_transmit(ep->ports[0].substream,
+				     ep->urb->transfer_buffer,
+				     ep->max_transfer);
+	if (count < 1) {
+		ep->ports[0].active = 0;
+		return;
 	}
-	spin_unlock_irqrestore(&ep->buffer_lock, flags);
+	ep->urb->transfer_buffer_length = count;
 }
 
-static void snd_usbmidi_out_tasklet(unsigned long data)
+static struct usb_protocol_ops snd_usbmidi_motu_ops = {
+	.input = snd_usbmidi_motu_input,
+	.output = snd_usbmidi_motu_output,
+};
+
+/*
+ * Emagic USB MIDI protocol: raw MIDI with "F5 xx" port switching.
+ */
+
+static void snd_usbmidi_emagic_init_out(snd_usb_midi_out_endpoint_t* ep)
 {
-	snd_usb_midi_out_endpoint_t* ep = (snd_usb_midi_out_endpoint_t *) data;
+	static const u8 init_data[] = {
+		/* initialization magic: "get version" */
+		0xf0,
+		0x00, 0x20, 0x31,	/* Emagic */
+		0x64,			/* Unitor8 */
+		0x0b,			/* version number request */
+		0x00,			/* command version */
+		0x00,			/* EEPROM, box 0 */
+		0xf7
+	};
+	send_bulk_static_data(ep, init_data, sizeof(init_data));
+	/* while we're at it, pour on more magic */
+	send_bulk_static_data(ep, init_data, sizeof(init_data));
+}
+
+static void snd_usbmidi_emagic_finish_out(snd_usb_midi_out_endpoint_t* ep)
+{
+	static const u8 finish_data[] = {
+		/* switch to patch mode with last preset */
+		0xf0,
+		0x00, 0x20, 0x31,	/* Emagic */
+		0x64,			/* Unitor8 */
+		0x10,			/* patch switch command */
+		0x00,			/* command version */
+		0x7f,			/* to all boxes */
+		0x40,			/* last preset in EEPROM */
+		0xf7
+	};
+	send_bulk_static_data(ep, finish_data, sizeof(finish_data));
+}
+
+static void snd_usbmidi_emagic_input(snd_usb_midi_in_endpoint_t* ep,
+				     uint8_t* buffer, int buffer_length)
+{
+	/* ignore padding bytes at end of buffer */
+	while (buffer_length > 0 && buffer[buffer_length - 1] == 0xff)
+		--buffer_length;
+
+	/* handle F5 at end of last buffer */
+	if (ep->seen_f5)
+		goto switch_port;
 
-	snd_usbmidi_do_output(ep);
+	while (buffer_length > 0) {
+		int i;
+
+		/* determine size of data until next F5 */
+		for (i = 0; i < buffer_length; ++i)
+			if (buffer[i] == 0xf5)
+				break;
+		snd_usbmidi_input_data(ep, ep->current_port, buffer, i);
+		buffer += i;
+		buffer_length -= i;
+
+		if (buffer_length <= 0)
+			break;
+		/* assert(buffer[0] == 0xf5); */
+		ep->seen_f5 = 1;
+		++buffer;
+		--buffer_length;
+
+	switch_port:
+		if (buffer_length <= 0)
+			break;
+		if (buffer[0] < 0x80) {
+			ep->current_port = (buffer[0] - 1) & 15;
+			++buffer;
+			--buffer_length;
+		}
+		ep->seen_f5 = 0;
+	}
+}
+
+static void snd_usbmidi_emagic_output(snd_usb_midi_out_endpoint_t* ep)
+{
+	int port0 = ep->current_port;
+	uint8_t* buf = ep->urb->transfer_buffer;
+	int buf_free = ep->max_transfer;
+	int length, i;
+
+	for (i = 0; i < 0x10; ++i) {
+		/* round-robin, starting at the last current port */
+		int portnum = (port0 + i) & 15;
+		usbmidi_out_port_t* port = &ep->ports[portnum];
+
+		if (!port->active)
+			continue;
+		if (snd_rawmidi_transmit_peek(port->substream, buf, 1) != 1) {
+			port->active = 0;
+			continue;
+		}
+
+		if (portnum != ep->current_port) {
+			if (buf_free < 2)
+				break;
+			ep->current_port = portnum;
+			buf[0] = 0xf5;
+			buf[1] = (portnum + 1) & 15;
+			buf += 2;
+			buf_free -= 2;
+		}
+
+		if (buf_free < 1)
+			break;
+		length = snd_rawmidi_transmit(port->substream, buf, buf_free);
+		if (length > 0) {
+			buf += length;
+			buf_free -= length;
+			if (buf_free < 1)
+				break;
+		}
+	}
+	ep->urb->transfer_buffer_length = ep->max_transfer - buf_free;
 }
 
+static struct usb_protocol_ops snd_usbmidi_emagic_ops = {
+	.input = snd_usbmidi_emagic_input,
+	.output = snd_usbmidi_emagic_output,
+	.init_out_endpoint = snd_usbmidi_emagic_init_out,
+	.finish_out_endpoint = snd_usbmidi_emagic_finish_out,
+};
+
+
 static int snd_usbmidi_output_open(snd_rawmidi_substream_t* substream)
 {
 	snd_usb_midi_t* umidi = substream->rmidi->private_data;
@@ -483,6 +738,12 @@
 
 static void snd_usbmidi_input_trigger(snd_rawmidi_substream_t* substream, int up)
 {
+	snd_usb_midi_t* umidi = substream->rmidi->private_data;
+
+	if (up)
+		set_bit(substream->number, &umidi->input_triggered);
+	else
+		clear_bit(substream->number, &umidi->input_triggered);
 }
 
 static snd_rawmidi_ops_t snd_usbmidi_output_ops = {
@@ -511,57 +772,6 @@
 }
 
 /*
- * For Roland devices, use the alternate setting which uses interrupt
- * transfers for input.
- */
-static struct usb_endpoint_descriptor* snd_usbmidi_get_int_epd(snd_usb_midi_t* umidi)
-{
-	struct usb_interface* intf;
-	struct usb_host_interface *hostif;
-	struct usb_interface_descriptor* intfd;
-
-	if (le16_to_cpu(umidi->chip->dev->descriptor.idVendor) != 0x0582)
-		return NULL;
-	intf = umidi->iface;
-	if (!intf || intf->num_altsetting != 2)
-		return NULL;
-
-	hostif = &intf->altsetting[0];
-	intfd = get_iface_desc(hostif);
-	if (intfd->bNumEndpoints != 2 ||
-	    (get_endpoint(hostif, 0)->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_BULK ||
-	    (get_endpoint(hostif, 1)->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_BULK)
-		return NULL;
-
-	hostif = &intf->altsetting[1];
-	intfd = get_iface_desc(hostif);
-	if (intfd->bNumEndpoints != 2 ||
-	    (get_endpoint(hostif, 0)->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_BULK ||
-	    (get_endpoint(hostif, 1)->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_INT)
-		return NULL;
-
-	snd_printdd(KERN_INFO "switching to altsetting %d with int ep\n",
-		    intfd->bAlternateSetting);
-	usb_set_interface(umidi->chip->dev, intfd->bInterfaceNumber,
-			  intfd->bAlternateSetting);
-	return get_endpoint(hostif, 1);
-}
-
-static struct usb_endpoint_descriptor* snd_usbmidi_get_midiman_int_epd(snd_usb_midi_t* umidi)
-{
-	struct usb_interface* intf = umidi->iface;
-	struct usb_host_interface *hostif;
-	struct usb_interface_descriptor *intfd;
-	if (!intf)
-		return NULL;
-	hostif = &intf->altsetting[0];
-	intfd = get_iface_desc(hostif);
-	if (intfd->bNumEndpoints < 1)
-		return NULL;
-	return get_endpoint(hostif, 0);
-}
-
-/*
  * Creates an input endpoint.
  */
 static int snd_usbmidi_in_endpoint_create(snd_usb_midi_t* umidi,
@@ -569,7 +779,6 @@
 					  snd_usb_midi_endpoint_t* rep)
 {
 	snd_usb_midi_in_endpoint_t* ep;
-	struct usb_endpoint_descriptor* int_epd;
 	void* buffer;
 	unsigned int pipe;
 	int length;
@@ -580,17 +789,12 @@
 		return -ENOMEM;
 	ep->umidi = umidi;
 
-	if (umidi->quirk && umidi->quirk->type == QUIRK_MIDI_MIDIMAN)
-		int_epd = snd_usbmidi_get_midiman_int_epd(umidi);
-	else
-		int_epd = snd_usbmidi_get_int_epd(umidi);
-
 	ep->urb = usb_alloc_urb(0, GFP_KERNEL);
 	if (!ep->urb) {
 		snd_usbmidi_in_endpoint_delete(ep);
 		return -ENOMEM;
 	}
-	if (int_epd)
+	if (ep_info->in_interval)
 		pipe = usb_rcvintpipe(umidi->chip->dev, ep_info->in_ep);
 	else
 		pipe = usb_rcvbulkpipe(umidi->chip->dev, ep_info->in_ep);
@@ -600,10 +804,10 @@
 		snd_usbmidi_in_endpoint_delete(ep);
 		return -ENOMEM;
 	}
-	if (int_epd)
+	if (ep_info->in_interval)
 		usb_fill_int_urb(ep->urb, umidi->chip->dev, pipe, buffer, length,
 				 snd_usb_complete_callback(snd_usbmidi_in_urb_complete),
-				 ep, int_epd->bInterval);
+				 ep, ep_info->in_interval);
 	else
 		usb_fill_bulk_urb(ep->urb, umidi->chip->dev, pipe, buffer, length,
 				  snd_usb_complete_callback(snd_usbmidi_in_urb_complete),
@@ -613,12 +817,12 @@
 	return 0;
 }
 
-static int snd_usbmidi_count_bits(uint16_t x)
+static unsigned int snd_usbmidi_count_bits(unsigned int x)
 {
-	int i, bits = 0;
+	unsigned int bits = 0;
 
-	for (i = 0; i < 16; ++i)
-		bits += (x & (1 << i)) != 0;
+	for (; x; x >>= 1)
+		bits += x & 1;
 	return bits;
 }
 
@@ -660,8 +864,9 @@
 		snd_usbmidi_out_endpoint_delete(ep);
 		return -ENOMEM;
 	}
+	/* we never use interrupt output pipes */
 	pipe = usb_sndbulkpipe(umidi->chip->dev, ep_info->out_ep);
-	ep->max_transfer = usb_maxpacket(umidi->chip->dev, pipe, 1) & ~3;
+	ep->max_transfer = usb_maxpacket(umidi->chip->dev, pipe, 1);
 	buffer = kmalloc(ep->max_transfer, GFP_KERNEL);
 	if (!buffer) {
 		snd_usbmidi_out_endpoint_delete(ep);
@@ -680,6 +885,9 @@
 			ep->ports[i].cable = i << 4;
 		}
 
+	if (umidi->usb_protocol_ops->init_out_endpoint)
+		umidi->usb_protocol_ops->init_out_endpoint(ep);
+
 	rep->out = ep;
 	return 0;
 }
@@ -712,8 +920,11 @@
 	umidi = list_entry(p, snd_usb_midi_t, list);
 	for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i) {
 		snd_usb_midi_endpoint_t* ep = &umidi->endpoints[i];
-		if (ep->out && ep->out->urb)
+		if (ep->out && ep->out->urb) {
 			usb_kill_urb(ep->out->urb);
+			if (umidi->usb_protocol_ops->finish_out_endpoint)
+				umidi->usb_protocol_ops->finish_out_endpoint(ep->out);
+		}
 		if (ep->in && ep->in->urb)
 			usb_kill_urb(ep->in->urb);
 	}
@@ -819,6 +1030,13 @@
 	/* M-Audio MidiSport 8x8 */
 	{0x0763, 0x1031, 8, "%s Control"},
 	{0x0763, 0x1033, 8, "%s Control"},
+	/* MOTU Fastlane */
+	{0x07fd, 0x0001, 0, "%s MIDI A"},
+	{0x07fd, 0x0001, 1, "%s MIDI B"},
+	/* Emagic Unitor8/AMT8/MT4 */
+	{0x086a, 0x0001, 8, "%s Broadcast"},
+	{0x086a, 0x0002, 8, "%s Broadcast"},
+	{0x086a, 0x0003, 4, "%s Broadcast"},
 };
 
 static void snd_usbmidi_init_substream(snd_usb_midi_t* umidi,
@@ -928,7 +1146,8 @@
 	for (i = 0; i < intfd->bNumEndpoints; ++i) {
 		hostep = &hostif->endpoint[i];
 		ep = get_ep_desc(hostep);
-		if ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_BULK)
+		if ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_BULK &&
+		    (ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_INT)
 			continue;
 		ms_ep = (struct usb_ms_endpoint_descriptor*)hostep->extra;
 		if (hostep->extralen < 4 ||
@@ -944,6 +1163,8 @@
 				}
 			}
 			endpoints[epidx].out_ep = ep->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
+			if ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT)
+				endpoints[epidx].out_interval = ep->bInterval;
 			endpoints[epidx].out_cables = (1 << ms_ep->bNumEmbMIDIJack) - 1;
 			snd_printdd(KERN_INFO "EP %02X: %d jack(s)\n",
 				    ep->bEndpointAddress, ms_ep->bNumEmbMIDIJack);
@@ -955,6 +1176,8 @@
 				}
 			}
 			endpoints[epidx].in_ep = ep->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
+			if ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT)
+				endpoints[epidx].in_interval = ep->bInterval;
 			endpoints[epidx].in_cables = (1 << ms_ep->bNumEmbMIDIJack) - 1;
 			snd_printdd(KERN_INFO "EP %02X: %d jack(s)\n",
 				    ep->bEndpointAddress, ms_ep->bNumEmbMIDIJack);
@@ -964,38 +1187,93 @@
 }
 
 /*
- * If the endpoints aren't specified, use the first bulk endpoints in the
- * first alternate setting of the interface.
+ * On Roland devices, use the second alternate setting to be able to use
+ * the interrupt input endpoint.
+ */
+static void snd_usbmidi_switch_roland_altsetting(snd_usb_midi_t* umidi)
+{
+	struct usb_interface* intf;
+	struct usb_host_interface *hostif;
+	struct usb_interface_descriptor* intfd;
+
+	intf = umidi->iface;
+	if (!intf || intf->num_altsetting != 2)
+		return;
+
+	hostif = &intf->altsetting[1];
+	intfd = get_iface_desc(hostif);
+	if (intfd->bNumEndpoints != 2 ||
+	    (get_endpoint(hostif, 0)->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_BULK ||
+	    (get_endpoint(hostif, 1)->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_INT)
+		return;
+
+	snd_printdd(KERN_INFO "switching to altsetting %d with int ep\n",
+		    intfd->bAlternateSetting);
+	usb_set_interface(umidi->chip->dev, intfd->bInterfaceNumber,
+			  intfd->bAlternateSetting);
+}
+
+/*
+ * Try to find any usable endpoints in the interface.
  */
-static int snd_usbmidi_detect_endpoint(snd_usb_midi_t* umidi,
-				       snd_usb_midi_endpoint_info_t* endpoint)
+static int snd_usbmidi_detect_endpoints(snd_usb_midi_t* umidi,
+					snd_usb_midi_endpoint_info_t* endpoint,
+					int max_endpoints)
 {
 	struct usb_interface* intf;
 	struct usb_host_interface *hostif;
 	struct usb_interface_descriptor* intfd;
 	struct usb_endpoint_descriptor* epd;
-	int i;
+	int i, out_eps = 0, in_eps = 0;
+
+	if (le16_to_cpu(umidi->chip->dev->descriptor.idVendor) == 0x0582)
+		snd_usbmidi_switch_roland_altsetting(umidi);
 
 	intf = umidi->iface;
 	if (!intf || intf->num_altsetting < 1)
 		return -ENOENT;
-	hostif = intf->altsetting;
+	hostif = intf->cur_altsetting;
 	intfd = get_iface_desc(hostif);
-	if (intfd->bNumEndpoints < 1)
-		return -ENOENT;
 
 	for (i = 0; i < intfd->bNumEndpoints; ++i) {
 		epd = get_endpoint(hostif, i);
-		if ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_BULK)
+		if ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_BULK &&
+		    (epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_INT)
 			continue;
-		if (!endpoint->out_ep && endpoint->out_cables &&
-		    (epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT)
-			endpoint->out_ep = epd->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
-		if (!endpoint->in_ep && endpoint->in_cables &&
-		    (epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN)
-			endpoint->in_ep = epd->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
+		if (out_eps < max_endpoints &&
+		    (epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT) {
+			endpoint[out_eps].out_ep = epd->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
+			if ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT)
+				endpoint[out_eps].out_interval = epd->bInterval;
+			++out_eps;
+		}
+		if (in_eps < max_endpoints &&
+		    (epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN) {
+			endpoint[in_eps].in_ep = epd->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
+			if ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT)
+				endpoint[in_eps].in_interval = epd->bInterval;
+			++in_eps;
+		}
 	}
-	return 0;
+	return (out_eps || in_eps) ? 0 : -ENOENT;
+}
+
+/*
+ * Detects the endpoints for one-port-per-endpoint protocols.
+ */
+static int snd_usbmidi_detect_per_port_endpoints(snd_usb_midi_t* umidi,
+						 snd_usb_midi_endpoint_info_t* endpoints)
+{
+	int err, i;
+	
+	err = snd_usbmidi_detect_endpoints(umidi, endpoints, MIDI_MAX_ENDPOINTS);
+	for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i) {
+		if (endpoints[i].out_ep)
+			endpoints[i].out_cables = 0x0001;
+		if (endpoints[i].in_ep)
+			endpoints[i].in_cables = 0x0001;
+	}
+	return err;
 }
 
 /*
@@ -1034,7 +1312,7 @@
 	if (!endpoint->in_cables && !endpoint->out_cables)
 		return -ENOENT;
 
-	return snd_usbmidi_detect_endpoint(umidi, endpoint);
+	return snd_usbmidi_detect_endpoints(umidi, endpoint, 1);
 }
 
 /*
@@ -1098,11 +1376,11 @@
 		return err;
 
 	ep_info.in_ep = get_endpoint(hostif, 0)->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
+	ep_info.in_interval = get_endpoint(hostif, 0)->bInterval;
 	ep_info.in_cables = endpoint->in_cables;
 	err = snd_usbmidi_in_endpoint_create(umidi, &ep_info, &umidi->endpoints[0]);
 	if (err < 0)
 		return err;
-	umidi->endpoints[0].in->urb->complete = snd_usb_complete_callback(snd_usbmidi_in_midiman_complete);
 
 	if (endpoint->out_cables > 0x0001) {
 		ep_info.out_ep = get_endpoint(hostif, 4)->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
@@ -1203,6 +1481,7 @@
 	umidi->chip = chip;
 	umidi->iface = iface;
 	umidi->quirk = quirk;
+	umidi->usb_protocol_ops = &snd_usbmidi_standard_ops;
 
 	/* detect the endpoint(s) to use */
 	memset(endpoints, 0, sizeof(endpoints));
@@ -1213,15 +1492,30 @@
 		case QUIRK_MIDI_FIXED_ENDPOINT:
 			memcpy(&endpoints[0], quirk->data,
 			       sizeof(snd_usb_midi_endpoint_info_t));
-			err = snd_usbmidi_detect_endpoint(umidi, &endpoints[0]);
+			err = snd_usbmidi_detect_endpoints(umidi, &endpoints[0], 1);
 			break;
 		case QUIRK_MIDI_YAMAHA:
 			err = snd_usbmidi_detect_yamaha(umidi, &endpoints[0]);
 			break;
 		case QUIRK_MIDI_MIDIMAN:
+			umidi->usb_protocol_ops = &snd_usbmidi_midiman_ops;
 			memcpy(&endpoints[0], quirk->data,
 			       sizeof(snd_usb_midi_endpoint_info_t));
 			err = 0;
+			break;
+		case QUIRK_MIDI_NOVATION:
+			umidi->usb_protocol_ops = &snd_usbmidi_novation_ops;
+			err = snd_usbmidi_detect_per_port_endpoints(umidi, endpoints);
+			break;
+		case QUIRK_MIDI_MOTU:
+			umidi->usb_protocol_ops = &snd_usbmidi_motu_ops;
+			err = snd_usbmidi_detect_per_port_endpoints(umidi, endpoints);
+			break;
+		case QUIRK_MIDI_EMAGIC:
+			umidi->usb_protocol_ops = &snd_usbmidi_emagic_ops;
+			memcpy(&endpoints[0], quirk->data,
+			       sizeof(snd_usb_midi_endpoint_info_t));
+			err = snd_usbmidi_detect_endpoints(umidi, &endpoints[0], 1);
 			break;
 		default:
 			snd_printd(KERN_ERR "invalid quirk type %d\n", quirk->type);
diff -Nru a/sound/usb/usbmixer.c b/sound/usb/usbmixer.c
--- a/sound/usb/usbmixer.c	2005-03-11 12:51:42 -08:00
+++ b/sound/usb/usbmixer.c	2005-03-11 12:51:42 -08:00
@@ -305,7 +305,7 @@
 				    request,
 				    USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
 				    validx, cval->ctrlif | (cval->id << 8),
-				    buf, val_len, HZ / 10) >= 0) {
+				    buf, val_len, 100) >= 0) {
 			*value_ret = convert_signed_value(cval, snd_usb_combine_bytes(buf, val_len));
 			return 0;
 		}
@@ -343,7 +343,7 @@
 				    request,
 				    USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT,
 				    validx, cval->ctrlif | (cval->id << 8),
-				    buf, val_len, HZ / 10) >= 0)
+				    buf, val_len, 100) >= 0)
 			return 0;
 	snd_printdd(KERN_ERR "cannot set ctl value: req = 0x%x, wValue = 0x%x, wIndex = 0x%x, type = %d, data = 0x%x/0x%x\n", request, validx, cval->ctrlif | (cval->id << 8), cval->val_type, buf[0], buf[1]);
 	return -EINVAL;
@@ -1519,7 +1519,7 @@
 
 	/* check the mapping table */
 	for (map = usbmix_ctl_maps; map->vendor; map++) {
-		if (map->vendor == le16_to_cpu(dev->idVendor) && map->product == le16_to_cpu(dev->idProduct)) {
+		if (map->vendor == state.vendor && map->product == state.product) {
 			state.map = map->map;
 			chip->ignore_ctl_error = map->ignore_ctl_error;
 			break;
diff -Nru a/sound/usb/usbquirks.h b/sound/usb/usbquirks.h
--- a/sound/usb/usbquirks.h	2005-03-11 12:51:42 -08:00
+++ b/sound/usb/usbquirks.h	2005-03-11 12:51:42 -08:00
@@ -72,6 +72,8 @@
 YAMAHA_DEVICE(0x1008, "UX96"),
 YAMAHA_DEVICE(0x1009, "UX16"),
 YAMAHA_INTERFACE(0x100a, 3, "EOS BX"),
+YAMAHA_DEVICE(0x100c, "UC-MX"),
+YAMAHA_DEVICE(0x100d, "UC-KX"),
 YAMAHA_DEVICE(0x100e, "S08"),
 YAMAHA_DEVICE(0x100f, "CLP-150"),
 YAMAHA_DEVICE(0x1010, "CLP-170"),
@@ -86,6 +88,7 @@
 YAMAHA_DEVICE(0x101a, "CVP-210"),
 YAMAHA_DEVICE(0x101b, "PSR-1100"),
 YAMAHA_DEVICE(0x101c, "PSR-2100"),
+YAMAHA_DEVICE(0x101d, "CLP-175"),
 YAMAHA_DEVICE(0x101e, "PSR-K1"),
 YAMAHA_DEVICE(0x1020, "EZ-250i"),
 YAMAHA_DEVICE(0x1021, "MOTIF ES 6"),
@@ -125,9 +128,12 @@
 YAMAHA_DEVICE(0x5006, "NHB32-C"),
 YAMAHA_DEVICE(0x5007, "DM1000"),
 YAMAHA_DEVICE(0x5008, "01V96"),
+YAMAHA_DEVICE(0x5009, "SPX2000"),
 YAMAHA_DEVICE(0x500a, "PM5D"),
 YAMAHA_DEVICE(0x500b, "DME64N"),
 YAMAHA_DEVICE(0x500c, "DME24N"),
+YAMAHA_DEVICE(0x500d, NULL),
+YAMAHA_DEVICE(0x500e, NULL),
 YAMAHA_DEVICE(0x7000, "DTX"),
 YAMAHA_DEVICE(0x7010, "UB99"),
 #undef YAMAHA_DEVICE
@@ -629,6 +635,19 @@
 	}
 },
 {
+	USB_DEVICE(0x0582, 0x0042),
+	.driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
+		.vendor_name = "Roland",
+		.product_name = "RS-70",
+		.ifnum = 0,
+		.type = QUIRK_MIDI_FIXED_ENDPOINT,
+		.data = & (const snd_usb_midi_endpoint_info_t) {
+			.out_cables = 0x0001,
+			.in_cables  = 0x0001
+		}
+	}
+},
+{
 	USB_DEVICE(0x0582, 0x0044),
 	.driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
 		.vendor_name = "Roland",
@@ -685,19 +704,6 @@
 	}
 },
 {
-	USB_DEVICE(0x0582, 0x0065),
-	.driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
-		.vendor_name = "EDIROL",
-		.product_name = "PCR-1",
-		.ifnum = 0,
-		.type = QUIRK_MIDI_FIXED_ENDPOINT,
-		.data = & (const snd_usb_midi_endpoint_info_t) {
-			.out_cables = 0x0001,
-			.in_cables  = 0x0003
-		}
-	}
-},
-{
 	/*
 	 * This quirk is for the "Advanced Driver" mode. If off, the UA-3FX
 	 * is standard compliant, but has only 16-bit PCM.
@@ -732,6 +738,45 @@
 		.type = QUIRK_MIDI_STANDARD_INTERFACE
 	}
 },
+{
+	USB_DEVICE(0x0582, 0x0065),
+	.driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
+		.vendor_name = "EDIROL",
+		.product_name = "PCR-1",
+		.ifnum = 0,
+		.type = QUIRK_MIDI_FIXED_ENDPOINT,
+		.data = & (const snd_usb_midi_endpoint_info_t) {
+			.out_cables = 0x0001,
+			.in_cables  = 0x0003
+		}
+	}
+},
+{
+	USB_DEVICE_VENDOR_SPEC(0x0582, 0x006a),
+	.driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
+		.vendor_name = "Roland",
+		.product_name = "SP-606",
+		.ifnum = 3,
+		.type = QUIRK_MIDI_FIXED_ENDPOINT,
+		.data = & (const snd_usb_midi_endpoint_info_t) {
+			.out_cables = 0x0001,
+			.in_cables  = 0x0001
+		}
+	}
+},
+{
+	USB_DEVICE(0x0582, 0x006d),
+	.driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
+		.vendor_name = "Roland",
+		.product_name = "FANTOM-X",
+		.ifnum = 0,
+		.type = QUIRK_MIDI_FIXED_ENDPOINT,
+		.data = & (const snd_usb_midi_endpoint_info_t) {
+			.out_cables = 0x0001,
+			.in_cables  = 0x0001
+		}
+	}
+},
 {	/*
 	 * This quirk is for the "Advanced" modes of the Edirol UA-25.
 	 * If the switch is not in an advanced setting, the UA-25 has
@@ -763,6 +808,19 @@
 		}
 	}
 },
+{
+	USB_DEVICE(0x0582, 0x0075),
+	.driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
+		.vendor_name = "BOSS",
+		.product_name = "DR-880",
+		.ifnum = 0,
+		.type = QUIRK_MIDI_FIXED_ENDPOINT,
+		.data = & (const snd_usb_midi_endpoint_info_t) {
+			.out_cables = 0x0001,
+			.in_cables  = 0x0001
+		}
+	}
+},
 
 /* Midiman/M-Audio devices */
 {
@@ -876,6 +934,22 @@
 			 * but captured samples are big-endian (see usbaudio.c).
 			 */
 			{
+				.ifnum = 0,
+				.type = QUIRK_IGNORE_INTERFACE
+			},
+			{
+				.ifnum = 1,
+				.type = QUIRK_IGNORE_INTERFACE
+			},
+			{
+				.ifnum = 2,
+				.type = QUIRK_IGNORE_INTERFACE
+			},
+			{
+				.ifnum = 3,
+				.type = QUIRK_IGNORE_INTERFACE
+			},
+			{
 				.ifnum = 4,
 				.type = QUIRK_AUDIO_STANDARD_INTERFACE
 			},
@@ -884,6 +958,10 @@
 				.type = QUIRK_AUDIO_STANDARD_INTERFACE
 			},
 			{
+				.ifnum = 6,
+				.type = QUIRK_IGNORE_INTERFACE
+			},
+			{
 				.ifnum = 7,
 				.type = QUIRK_AUDIO_STANDARD_INTERFACE
 			},
@@ -936,27 +1014,81 @@
 	.driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
 		.vendor_name = "M-Audio",
 		.product_name = "OmniStudio",
-		.ifnum = 9,
-		.type = QUIRK_MIDI_MIDIMAN,
-		.data = & (const snd_usb_midi_endpoint_info_t) {
-			.out_cables = 0x0001,
-			.in_cables  = 0x0001
+		.ifnum = QUIRK_ANY_INTERFACE,
+		.type = QUIRK_COMPOSITE,
+		.data = & (const snd_usb_audio_quirk_t[]) {
+			{
+				.ifnum = 0,
+				.type = QUIRK_IGNORE_INTERFACE
+			},
+			{
+				.ifnum = 1,
+				.type = QUIRK_IGNORE_INTERFACE
+			},
+			{
+				.ifnum = 2,
+				.type = QUIRK_IGNORE_INTERFACE
+			},
+			{
+				.ifnum = 3,
+				.type = QUIRK_IGNORE_INTERFACE
+			},
+			{
+				.ifnum = 4,
+				.type = QUIRK_AUDIO_STANDARD_INTERFACE
+			},
+			{
+				.ifnum = 5,
+				.type = QUIRK_AUDIO_STANDARD_INTERFACE
+			},
+			{
+				.ifnum = 6,
+				.type = QUIRK_IGNORE_INTERFACE
+			},
+			{
+				.ifnum = 7,
+				.type = QUIRK_AUDIO_STANDARD_INTERFACE
+			},
+			{
+				.ifnum = 8,
+				.type = QUIRK_AUDIO_STANDARD_INTERFACE
+			},
+			{
+				.ifnum = 9,
+				.type = QUIRK_MIDI_MIDIMAN,
+				.data = & (const snd_usb_midi_endpoint_info_t) {
+					.out_cables = 0x0001,
+					.in_cables  = 0x0001
+				}
+			},
+			{
+				.ifnum = -1
+			}
 		}
 	}
 },
 
 /* Mark of the Unicorn devices */
 {
-	/* thanks to Woodley Packard <sweaglesw@thibs.menloschool.org> */
+	/* thanks to Robert A. Lerche <ral 'at' msbit.com> */
 	USB_DEVICE(0x07fd, 0x0001),
 	.driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
 		.vendor_name = "MOTU",
 		.product_name = "Fastlane",
-		.ifnum = 1,
-		.type = QUIRK_MIDI_FIXED_ENDPOINT,
-		.data = & (const snd_usb_midi_endpoint_info_t) {
-			.out_cables = 0x0003,
-			.in_cables  = 0x0003
+		.ifnum = QUIRK_ANY_INTERFACE,
+		.type = QUIRK_COMPOSITE,
+		.data = & (const snd_usb_audio_quirk_t[]) {
+			{
+				.ifnum = 0,
+				.type = QUIRK_MIDI_MOTU
+			},
+			{
+				.ifnum = 1,
+				.type = QUIRK_IGNORE_INTERFACE
+			},
+			{
+				.ifnum = -1
+			}
 		}
 	}
 },
@@ -972,6 +1104,47 @@
 	
 },
 
+/* Emagic devices */
+{
+	USB_DEVICE(0x086a, 0x0001),
+	.driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
+		.vendor_name = "Emagic",
+		/* .product_name = "Unitor8", */
+		.ifnum = 2,
+		.type = QUIRK_MIDI_EMAGIC,
+		.data = & (const snd_usb_midi_endpoint_info_t) {
+			.out_cables = 0x80ff,
+			.in_cables  = 0x80ff
+		}
+	}
+},
+{
+	USB_DEVICE(0x086a, 0x0002),
+	.driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
+		.vendor_name = "Emagic",
+		/* .product_name = "AMT8", */
+		.ifnum = 2,
+		.type = QUIRK_MIDI_EMAGIC,
+		.data = & (const snd_usb_midi_endpoint_info_t) {
+			.out_cables = 0x80ff,
+			.in_cables  = 0x80ff
+		}
+	}
+},
+{
+	USB_DEVICE(0x086a, 0x0003),
+	.driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
+		.vendor_name = "Emagic",
+		/* .product_name = "MT4", */
+		.ifnum = 2,
+		.type = QUIRK_MIDI_EMAGIC,
+		.data = & (const snd_usb_midi_endpoint_info_t) {
+			.out_cables = 0x800f,
+			.in_cables  = 0x8003
+		}
+	}
+},
+
 {
 	USB_DEVICE_VENDOR_SPEC(0x0ccd, 0x0013),
 	.driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
@@ -979,6 +1152,35 @@
 		.product_name = "PHASE 26",
 		.ifnum = 3,
 		.type = QUIRK_MIDI_STANDARD_INTERFACE
+	}
+},
+
+/* Novation EMS devices */
+{
+	USB_DEVICE_VENDOR_SPEC(0x1235, 0x0001),
+	.driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
+		.vendor_name = "Novation",
+		.product_name = "ReMOTE Audio/XStation",
+		.ifnum = 4,
+		.type = QUIRK_MIDI_NOVATION
+	}
+},
+{
+	USB_DEVICE_VENDOR_SPEC(0x1235, 0x0002),
+	.driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
+		.vendor_name = "Novation",
+		.product_name = "Speedio",
+		.ifnum = 3,
+		.type = QUIRK_MIDI_NOVATION
+	}
+},
+{
+	USB_DEVICE_VENDOR_SPEC(0x1235, 0x4661),
+	.driver_info = (unsigned long) & (const snd_usb_audio_quirk_t) {
+		.vendor_name = "Novation",
+		.product_name = "ReMOTE25",
+		.ifnum = 0,
+		.type = QUIRK_MIDI_NOVATION
 	}
 },
 
diff -Nru a/sound/usb/usx2y/usX2Yhwdep.c b/sound/usb/usx2y/usX2Yhwdep.c
--- a/sound/usb/usx2y/usX2Yhwdep.c	2005-03-11 12:51:41 -08:00
+++ b/sound/usb/usx2y/usX2Yhwdep.c	2005-03-11 12:51:41 -08:00
@@ -226,7 +226,7 @@
 		if (err)
 			snd_printk("usb_set_interface error \n");
 		else
-			err = usb_bulk_msg(dev, usb_sndbulkpipe(dev, 2), buf, dsp->length, &lret, 6*HZ);
+			err = usb_bulk_msg(dev, usb_sndbulkpipe(dev, 2), buf, dsp->length, &lret, 6000);
 		kfree(buf);
 	}
 	if (err)
diff -Nru a/sound/usb/usx2y/usbusx2yaudio.c b/sound/usb/usx2y/usbusx2yaudio.c
--- a/sound/usb/usx2y/usbusx2yaudio.c	2005-03-11 12:51:46 -08:00
+++ b/sound/usb/usx2y/usbusx2yaudio.c	2005-03-11 12:51:46 -08:00
@@ -415,7 +415,6 @@
 	unsigned int pipe;
 	int is_playback = subs == subs->usX2Y->subs[SNDRV_PCM_STREAM_PLAYBACK];
 	struct usb_device *dev = subs->usX2Y->chip.dev;
-	struct usb_host_endpoint *ep;
 
 	pipe = is_playback ? usb_sndisocpipe(dev, subs->endpoint) :
 			usb_rcvisocpipe(dev, subs->endpoint);
